diff --git a/SigMaker/SigMaker.vcxproj b/SigMaker/SigMaker.vcxproj index 25cabfb..87c71cd 100644 --- a/SigMaker/SigMaker.vcxproj +++ b/SigMaker/SigMaker.vcxproj @@ -29,27 +29,27 @@ DynamicLibrary true Unicode - v142 + v143 DynamicLibrary true Unicode - v142 + v143 DynamicLibrary false true Unicode - v142 + v143 DynamicLibrary false true Unicode - v142 + v143 @@ -179,7 +179,8 @@ MultiThreadedDLL false false - $(SolutionDir)idasdk75\include\;%(AdditionalIncludeDirectories) + $(SolutionDir)idasdk76\include\;%(AdditionalIncludeDirectories) + stdcpp14 false @@ -191,7 +192,7 @@ /EXPORT:PLUGIN %(AdditionalOptions) false false - $(SolutionDir)idasdk75\lib\x64_win_vc_64;%(AdditionalLibraryDirectories) + $(SolutionDir)idasdk76\lib\x64_win_vc_64;%(AdditionalLibraryDirectories) false diff --git a/builds/Release64/SigMaker64.dll b/builds/Release64/SigMaker64.dll new file mode 100644 index 0000000..76943b4 Binary files /dev/null and b/builds/Release64/SigMaker64.dll differ diff --git a/idasdk75/allmake.mak b/idasdk75/allmake.mak deleted file mode 100644 index 74174cc..0000000 --- a/idasdk75/allmake.mak +++ /dev/null @@ -1,823 +0,0 @@ -# -# Common part of make files for IDA. -# - -# find directory of allmake.mak: -IDA:=$(dir $(lastword $(MAKEFILE_LIST))) - -# define the version number we are building -IDAVER_MAJOR:=7 -IDAVER_MINOR:=5 -# 750 -IDAVERDECIMAL:=$(IDAVER_MAJOR)$(IDAVER_MINOR)0 -# 7.5 -IDAVERDOTTED:=$(IDAVER_MAJOR).$(IDAVER_MINOR) - -# only 32-bit cygwin make is support on Windows -ifeq ($(OS),Windows_NT) - ifneq ($(MAKE_HOST),i686-pc-cygwin) - $(error Only 32-bit cygwin make is supported on Windows. Make sure you are not using 64-bit cygwin, msys, msys2, or any other version of win32 make) - endif -endif - -# if no targets are defined, default to host OS -ifeq ($(or $(__ANDROID__),$(__ANDROID_X86__),$(__ARMLINUX__),$(__LINUX__),$(__MAC__),$(__NT__)),) - ifeq ($(OS),Windows_NT) - __NT__=1 - else - UNAME_S := $(shell uname -s) - ifeq ($(UNAME_S),Linux) - __LINUX__=1 - endif - ifeq ($(UNAME_S),Darwin) - __MAC__=1 - endif - endif -endif - -# only one build target may be defined -ifneq ($(__ANDROID__)$(__ANDROID_X86__)$(__ARMLINUX__)$(__LINUX__)$(__MAC__)$(__NT__),1) - $(error Only one build target may be defined (__ANDROID__, __ANDROID_X86__, __ARMLINUX__, __LINUX__, __MAC__, or __NT__)) -endif - -# detect build configuration -# Note: will set one of M, MM, MMH, M32, MO, MMO, MMHO, MO32, MSO, MMSO, or MSO32 -BUILD_CONFIG-1 := M -BUILD_CONFIG-$(__EA64__) += M -BUILD_CONFIG-$(USE_STATIC_RUNTIME) += S -BUILD_CONFIG-$(IDAHOME) += H -BUILD_CONFIG-$(NDEBUG) += O -BUILD_CONFIG-$(__X86__) += 32 -empty := -space := $(empty) $(empty) -comma := , -BUILD_CONFIG := $(subst $(space),,$(BUILD_CONFIG-1)) -$(BUILD_CONFIG) := 1 - -# definition of a single \n character (empty lines are important!) -define newline - - -endef - -# disable x86 ida64 builds -ifeq ($(or $(MM32),$(MMO32),$(MMSO32)),1) - $(error x86 ida64 builds have been disabled) -endif - -ifdef __ARM__ - PROCDEF = __ARM__ - TARGET_PROCESSOR_NAME=arm -else ifndef __X86__ - ARCH_FLAGS = -m64 - TARGET_PROCESSOR_NAME=x64 -else - ARCH_FLAGS = -m32 - TARGET_PROCESSOR_NAME=x86 -endif - -# define some variables to simplify build system -ifndef __X86__ - __X64__ = 1 - ifndef __EA64__ - __X32__ = 1 - endif -endif -ifndef __NT__ - __UNIX__ = 1 -endif - -ifndef IDAHOME - IDAADV = 1 -endif - -# define SYSNAME -SYSNAME-$(__LINUX__) = linux -SYSNAME-$(__MAC__) = mac -SYSNAME-$(__NT__) = win -SYSNAME = $(SYSNAME-1) - -# path functions (depending on host OS) -ifeq ($(OS),Windows_NT) - # define: convert unix path to dos path by replacing slashes by backslashes - dospath=$(subst /,\\,$(1)) -else - # define: dospath does not do anything in unix - dospath=$(1) -endif -# define: return 1 if path exists, 0 otherwise -ls=$(if $(wildcard $(1)),1,0) - -# define: logical negation -not = $(if $(1),,1) - -# define: greater or equal -gte = $(if $(filter-out $(1),$(word 2,$(sort $(1) $(2)))),,1) - -include $(IDA)defaults.mk - -############################################################################# -ifdef __NT__ - COMPILER_NAME=vc - - # Visual C++ Toolchain and Windows SDK paths - # Note: see comments in defaults.mk for more information about these - # variables. - - # This function searches for a specified path, converts it to a 8.3 - # path with forward slashes as separator, and exports it as an - # environment variable. This way, subcalls to make do not need to - # call $(shell) again. - define require_path - $$(if $(strip $$($(1))),,$$(eval $(1):=$$(subst \,/,$$(shell cygpath -d $(2) 2>/dev/null)))) - $$(if $(strip $$($(1))),,$$(error Could not find $(3) in $(2)$$(newline)*** See defaults.mk and "Visual C++ Toolchain and Windows SDK paths" in allmake.mak)) - $$(eval export $(1)) - endef - - # This function fixes variables imported from defaults.mk/vcvars.bat - # by ensuring that they are surrounded by quotes and by removing the - # trailing backslash. - fix_var=$(1):='$$(patsubst %\,%,$$(patsubst '%,%,$$(patsubst %',%,$$(patsubst "%,%,$$(patsubst %",%,$$($(1)))))))' - - # Note: these cfg files are created in makeenv_vc.mak - ifdef __XPCOMPAT__ - -include $(IDA)vs17paths_xp.cfg - else - -include $(IDA)vs17paths.cfg - endif - - # Visual C++ 2017 Install Directory - ifndef MSVC_ROOT - ifneq (,$(findstring Microsoft$(space)Visual$(space)Studio$(space),$(VCINSTALLDIR))) - ifeq (,$(findstring 2017,$(VCINSTALLDIR))) - $(error Please check your system environment variable VCInstallDir [$(VCINSTALLDIR)].$(newline)It seems to be pointing to an old version of Visual Studio (and not version 2017).$(newline)You may override it in defaults.mk.) - endif - endif - $(eval $(call fix_var,VCINSTALLDIR)) - $(eval $(call require_path,MSVC_ROOT,$(VCINSTALLDIR),Visual C++ 2017 Install Directory)) - export MSVC_ROOT - endif - - # Visual C++ 2017 Tools Version - ifndef MSVC_TOOLSVER - ifndef VCToolsVersion - # Try to obtain version from Microsoft.VCToolsVersion.default.txt - MSVC_TOOLSVER_PATH = $(MSVC_ROOT)/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt - VCToolsVersion := $(shell cat $(MSVC_TOOLSVER_PATH) 2> /dev/null) - ifeq (,$(VCToolsVersion)) - # If that failed, try to detect latest version from the directory names - VCToolsVersion := $(notdir $(lastword $(sort $(wildcard $(MSVC_ROOT)/Tools/MSVC/14.*)))) - endif - ifeq (,$(VCToolsVersion)) - $(error Could not find Visual C++ 2017 Tools Version in $(MSVC_TOOLSVER_PATH)) - endif - endif - $(eval $(call fix_var,VCToolsVersion)) - MSVC_TOOLSVER := $(VCToolsVersion) - export MSVC_TOOLSVER - endif - - # Final Visual C++ 2017 Tools path - $(eval $(call require_path,MSVC_PATH,$(MSVC_ROOT)/Tools/MSVC/$(MSVC_TOOLSVER),Visual C++ 2017 Tools)) - - MSVC_BIN-X86 ?= $(MSVC_PATH)/bin/HostX86/x86 - MSVC_BIN-X64 ?= $(MSVC_PATH)/bin/HostX64/x64 - ifdef __X86__ - MSVC_BIN ?= $(MSVC_BIN-X86) - else - MSVC_BIN ?= $(MSVC_BIN-X64) - endif - MSVC_INCLUDE ?= $(MSVC_PATH)/Include - - # Windows SDK Install Directory - ifndef WSDK_PATH - $(eval $(call fix_var,WindowsSdkDir)) - $(eval $(call require_path,WSDK_PATH,$(WindowsSdkDir),Windows SDK Install Directory)) - export WSDK_PATH - endif - - # Windows SDK Version - ifndef WSDK_VER - ifndef WindowsSDKVersion - # Detect the latest version of the Windows SDK - WSDK_VER_PATH = $(WSDK_PATH)/Include/10.* - WindowsSDKVersion := $(notdir $(lastword $(sort $(wildcard $(WSDK_VER_PATH))))) - ifeq (,$(WindowsSDKVersion)) - $(error Could not find Windows SDK Version in $(WSDK_VER_PATH)) - endif - endif - $(eval $(call fix_var,WindowsSDKVersion)) - WSDK_VER := $(WindowsSDKVersion) - export WSDK_VER - endif - - # Windows SDK Include/Lib paths - INCLUDE_UCRT_PATH ?= $(WSDK_PATH)/Include/$(WSDK_VER)/ucrt - LIB_UCRT_PATH ?= $(WSDK_PATH)/Lib/$(WSDK_VER)/ucrt - $(eval $(call require_path,INCLUDE_UCRT,$(INCLUDE_UCRT_PATH),Windows SDK Include/ucrt)) - $(eval $(call require_path,LIB_UCRT,$(LIB_UCRT_PATH),Windows SDK Lib/ucrt)) - - ifdef __XPCOMPAT__ - $(eval $(call require_path,INCLUDE_MSSDK71,$(MSSDK71_PATH)/Include,Microsoft SDK Include)) - $(eval $(call require_path,LIB_MSSDK71,$(MSSDK71_PATH)/Lib,Microsoft SDK Lib)) - $(eval $(call require_path,SDK_BIN,$(MSSDK71_PATH)/Bin,Microsoft SDK Bin)) - else - INCLUDE_SHARED_PATH ?= $(WSDK_PATH)/Include/$(WSDK_VER)/shared - INCLUDE_UM_PATH ?= $(WSDK_PATH)/Include/$(WSDK_VER)/um - LIB_UM_PATH ?= $(WSDK_PATH)/Lib/$(WSDK_VER)/um - SDK_BIN_PATH ?= $(WSDK_PATH)/Bin/$(WSDK_VER)/ - - $(eval $(call require_path,INCLUDE_SHARED,$(INCLUDE_SHARED_PATH),Windows SDK Include/shared)) - $(eval $(call require_path,INCLUDE_UM,$(INCLUDE_UM_PATH),Windows SDK Include/um)) - $(eval $(call require_path,LIB_UM,$(LIB_UM_PATH),Windows SDK Lib/um)) - $(eval $(call require_path,SDK_BIN,$(SDK_BIN_PATH),Windows SDK Bin)) - endif - - # Export INCLUDE as an environment variable so it may be used by cl. - ifndef INCLUDE - ifdef __XPCOMPAT__ - INCLUDE = $(MSVC_INCLUDE);$(INCLUDE_UCRT);$(INCLUDE_MSSDK71) - else - INCLUDE = $(MSVC_INCLUDE);$(INCLUDE_UCRT);$(INCLUDE_UM);$(INCLUDE_SHARED) - endif - export INCLUDE - endif - - # Export LIB as an environment variable so it may be used by cl/link. - ifndef LIB - ifdef __XPCOMPAT__ - ifdef __X86__ - LIB = $(MSVC_PATH)/lib/x86;$(LIB_UCRT)/x86;$(LIB_MSSDK71) - else - LIB = $(MSVC_PATH)/lib/x64;$(LIB_UCRT)/x64;$(LIB_MSSDK71)/x64 - endif - else - ifdef __X86__ - LIB = $(MSVC_PATH)/lib/x86;$(LIB_UCRT)/x86;$(LIB_UM)/x86 - else - LIB = $(MSVC_PATH)/lib/x64;$(LIB_UCRT)/x64;$(LIB_UM)/x64 - endif - endif - export LIB - endif - - # If a Visual Studio Command Prompt is used, make sure the target - # architecture is correct. - ifdef VSCMD_ARG_TGT_ARCH - ifneq ($(VSCMD_ARG_TGT_ARCH),$(TARGET_PROCESSOR_NAME)) - ifdef __X86__ - EXPECTED_ARCH = x86 - else - EXPECTED_ARCH = x64 - endif - LOWERCASE_BUILD_CONFIG := $(subst M,m,$(subst S,s,$(subst O,o,$(BUILD_CONFIG)))) - $(error Please use the correct Visual Studio Command Prompt for the target architecture$(newline)*** The target architecture for '$(LOWERCASE_BUILD_CONFIG)' is $(EXPECTED_ARCH), and the architecture for the current Visual Studio Command Prompt is $(VSCMD_ARG_TGT_ARCH))) - endif - endif -############################################################################# -else ifdef __LINUX__ - COMPILER_NAME=gcc - PTHR_SWITCH=-pthread - STDLIBS += -lrt -lpthread -lc -############################################################################# -else ifdef __MAC__ - COMPILER_NAME=clang - STDLIBS += -lpthread -liconv - ARCH_FLAGS-$(__X64__) = -arch x86_64 - ARCH_FLAGS-$(__X86__) = -arch i386 - ARCH_FLAGS += $(ARCH_FLAGS-1) - # The following value is defined in defaults.mk. - ARCH_FLAGS += -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) - ifndef MACSDK - MACSDK := $(shell /usr/bin/xcrun --sdk macosx --show-sdk-path) - ifeq ($(MACSDK),) - $(error Could not find MacOSX SDK) - endif - export MACSDK - endif - ARCH_FLAGS += -isysroot $(MACSDK) -endif - -############################################################################# -# toolchain-specific variables - -ifneq (,$(filter $(COMPILER_NAME),gcc clang)) - # file extensions - A = .a - B = $(SUFF64) - O = .o - II = .i - # toolchain output switches - OBJSW = -o # with space - OUTAR = - OUTII = -o # with space - OUTSW = -o # with space - ifdef __MAC__ - OUTMAP = -Wl,-map, - else - OUTMAP = -Wl,-Map, - endif - # misc switches - AROPT = rc - CPPONLY = -E - FORCEC = -xc - NORTTI = -fno-rtti - ifdef __MAC__ - OUTDLL = -dynamiclib - else - OUTDLL = --shared - endif - # utilities - CCACHE-$(USE_CCACHE) = ccache - ifeq ($(COMPILER_NAME),clang) - _CC = clang - _CXX = clang++ - else - _CC = gcc - _CXX = g++ - ifdef USE_GOLD - GOLD = -fuse-ld=gold - endif - endif - AR = $(CROSS_PREFIX)ar$(HOST_EXE) $(AROPT) - CC = $(CCACHE-1) $(CROSS_PREFIX)$(_CC)$(HOST_EXE) $(ARCH_FLAGS) - CCL = $(CROSS_PREFIX)$(_CXX)$(HOST_EXE) $(ARCH_FLAGS) $(GOLD) - CXX = $(CCACHE-1) $(CROSS_PREFIX)$(_CXX)$(HOST_EXE) $(ARCH_FLAGS) -else ifeq ($(COMPILER_NAME),vc) - # file extensions - A = .lib - B = $(SUFF64).exe - O = .obj - II = .i - # toolchain output switches - OBJSW = /Fo - OUTAR = /OUT: - OUTII = /Fi - OUTSW = /OUT: - OUTMAP = /map: - # misc switches - CPPONLY = /P - FORCEC = /TC - NOLOGO = /nologo - NORTTI = /GR- - OUTDLL = /DLL - # utilities - AR = $(MSVC_BIN)/lib.exe $(NOLOGO) - CC = $(MSVC_BIN)/cl.exe $(NOLOGO) - CCL = $(MSVC_BIN)/link.exe $(NOLOGO) - CXX = $(CC) -endif - -############################################################################## -# target-specific cflags/ldflags -ifneq (,$(filter $(COMPILER_NAME),gcc clang)) - - # system cflags - CC_DEFS += $(PROCDEF) - ifdef __MAC__ - CC_DEFS += __MAC__ - else - CC_DEFS += __LINUX__ - endif - - # pic-related flags - # Note: this variable may be overridden in other parts of the build - PIC = -fPIC - - ifdef __MAC__ - LDPIE = $(PIC) -Wl,-pie - else - LDPIE = $(PIC) -pie - endif - - # common cflags - CC_DEFS += $(DEF64) - CC_DEFS += $(DEFX86) - - CC_F += $(PIC) - CC_F += -fdiagnostics-show-option - CC_F += -fno-strict-aliasing - CC_F += -fvisibility=hidden - CC_F += -fwrapv - - CC_INCP += $(I) - - CC_W += -Wall - CC_W += -Wextra - CC_W += -Wformat=2 - CC_W += -Werror=format-security - CC_W += -Werror=format-nonliteral - CC_W += -Wshadow - CC_W += -Wunused - - CC_WNO += -Wno-format-y2k - CC_WNO += -Wno-missing-field-initializers - CC_WNO += -Wno-sign-compare - - CC_X += -g - CC_X += -pipe - - # enable c++11 - CXXSTD = -std=c++11 - - CXX_F += -fvisibility-inlines-hidden - CXX_WNO += -Wno-invalid-offsetof - - # system-specific cflags - ifeq ($(COMPILER_NAME),clang) # mac/android - # 'cc -dumpversion' always reports 4.2.1 for clang - # https://stackoverflow.com/questions/12893731/why-does-clang-dumpversion-report-4-2-1 - - # clang is extra picky - need to add some warning supressions - # must eventually get rid of most of these - CC_WNO += -Wno-char-subscripts - CC_WNO += -Wno-dynamic-class-memaccess - CC_WNO += -Wno-int-to-pointer-cast - CC_WNO += -Wno-invalid-source-encoding - CC_WNO += -Wno-logical-not-parentheses - CC_WNO += -Wno-logical-op-parentheses - CC_WNO += -Wno-null-conversion - CC_WNO += -Wno-nullability-completeness - CC_WNO += -Wno-parentheses-equality - CC_WNO += -Wno-self-assign - CC_WNO += -Wno-unused-const-variable - CC_WNO += -Wno-unused-function - CC_WNO += -Wno-unused-private-field - CC_WNO += -Wno-unused-variable - CC_WNO += -Wno-varargs - - CC_F += -fno-caret-diagnostics - else # (arm)linux - - # get gcc version - ifndef _GCC_VERSION - _GCC_VERSION:=$(wordlist 1,2,$(subst ., ,$(shell $(CC) -dumpversion))) - export _GCC_VERSION - endif - GCC_VERSION=$(firstword $(_GCC_VERSION)).$(lastword $(_GCC_VERSION)) - - CC_WNO += -Wno-unused-local-typedefs - CC_F += -fno-diagnostics-show-caret - - CC_DEFS-$(call gte,$(GCC_VERSION),5.0) += _GLIBCXX_USE_CXX11_ABI=0 - CC_W-$(call gte,$(GCC_VERSION),7.0) += -Wimplicit-fallthrough=0 - CXX_WNO-$(call gte,$(GCC_VERSION),8.0) += -Wno-class-memaccess - - # suppress warning about ABI change in GCC 4.4 - CC_WNO-$(__ARMLINUX__) += -Wno-psabi - endif - - # optimization cflags - ifdef NDEBUG - CC_F += -fdata-sections - CC_F += -ffunction-sections - ifndef __ASAN__ - CC_F += -fomit-frame-pointer - endif - # stack protector - ifdef __TARGET_MAC_HOST_LINUX__ - # disable stack protector for our osxcross toolchain (we check - # against __TARGET_MAC_HOST_LINUX__ since it is hard to check - # for version number in clang). - else ifeq ($(call gte,$(GCC_VERSION),4.9),1) - CC_F += -fstack-protector-strong - else - CC_F += -fstack-protector - endif - CC_DEFS += NDEBUG - CC_DEFS += _FORTIFY_SOURCE=2 - else - CC_DEFS += _DEBUG - endif - - # system-specific ldflags - ifdef __LINUX__ - LDFLAGS += -Wl,--build-id - LDFLAGS += -Wl,--gc-sections - LDFLAGS += -Wl,--warn-shared-textrel - - NO_UNDEFS = -Wl,--no-undefined - DLL_W += $(NO_UNDEFS) - else ifdef __MAC__ - LDFLAGS += -Wl,-dead_strip - - ifndef __TARGET_MAC_HOST_LINUX__ - DLL_X += -compatibility_version 1.0 - DLL_X += -current_version 1.0 - DLL_X += -single_module - endif - endif - - # common linker/compiler flags - ifdef NDEBUG - CCOPT += -O2 - ifdef __LINUX__ - LDOPT += -Wl,-O1 - endif - endif - - # AddressSanitizer flags - ifdef __ASAN__ - CC_DEFS += __ASAN__ - CC_F += -fno-omit-frame-pointer - CC_F += -fsanitize=address - LDFLAGS += -fsanitize=address - export LSAN_OPTIONS=suppressions=$(IDA)etc/bin/known_leaks.txt:detect_leaks=0 - endif - - # final compiler flags - CC_F += $(CC_F-1) - CC_W += $(CC_W-1) - CC_WNO += $(CC_WNO-1) - CXX_WNO += $(CXX_WNO-1) - CC_DEFS += $(CC_DEFS-1) - CC_INCP += $(CC_INCP-1) - CC_D += $(addprefix -D,$(CC_DEFS)) - CC_I += $(addprefix -I,$(CC_INCP)) - - # the -Wno-* flags must come after the -W enabling flags - WARNS = $(sort $(CC_W)) $(sort $(CC_WNO)) - - CFLAGS += $(sort $(CC_X)) - CFLAGS += $(CCOPT) - CFLAGS += $(sort $(CC_I)) - CFLAGS += $(sort $(CC_D)) - CFLAGS += $(sort $(CC_F)) - CFLAGS += $(WARNS) - CFLAGS += $(PTHR_SWITCH) - - # for warning suppression, override the WARNS variable with NOWARNS: - # $(TARGET): WARNS = $(NOWARNS) - NOWARNS = -w - - # dll linker flags - DLLFLAGS += $(DLL_W) $(DLL_X) - -else ifeq ($(COMPILER_NAME),vc) - # for warning suppression, override the WARNS variable with NOWARNS: - # $(TARGET): WARNS = $(NOWARNS) - NOWARNS = -w -wd4702 -wd4738 - - # optimization ldflags - LDOPT += /DEBUG - ifdef NDEBUG - LDOPT += /INCREMENTAL:NO /OPT:ICF /OPT:REF - endif - - # set c runtime to use - ifdef NDEBUG - ifdef USE_STATIC_RUNTIME - RUNTIME_LIBSW = /MT - else - RUNTIME_LIBSW = /MD - endif - else - ifdef USE_STATIC_RUNTIME - RUNTIME_LIBSW = /MTd - else - RUNTIME_LIBSW = /MDd - endif - endif - - # PDB options - PDBFLAGS = /PDB:$(PDBDIR)/ - ifdef NDEBUG - PDBFLAGS += /PDBALTPATH:%_PDB% - endif - # Generate debug info (old style) - PDBFORMAT = /Z7 - - # final compiler flags - CC_DEFS += $(DEF64) - CC_DEFS += $(DEFX86) - CC_DEFS += $(CC_DEFS-1) - CC_INCP += $(CC_INCP-1) - CC_D += $(addprefix -D,$(CC_DEFS)) - CC_I += $(addprefix -I,$(CC_INCP)) - - CFGFILE = @$(IDA)$(SYSDIR).cfg - CFLAGS += $(CFGFILE) - CFLAGS += $(RUNTIME_LIBSW) - CFLAGS += $(PDBFORMAT) - CFLAGS += /Brepro - CFLAGS += $(sort $(CC_I)) - CFLAGS += $(sort $(CC_D)) - CFLAGS += $(sort $(CC_F)) - CFLAGS += $(WARNS) - - # final linker flags - LDFLAGS += /Brepro - LDFLAGS += $(PDBFLAGS) - LDFLAGS += /ERRORREPORT:QUEUE - ifdef __X86__ - LDFLAGS += /LARGEADDRESSAWARE - endif - - ifdef __XPCOMPAT__ - XPSUBSYS-$(__X64__) = /SUBSYSTEM:CONSOLE,5.02 - XPSUBSYS-$(__X86__) = /SUBSYSTEM:CONSOLE,5.01 - LDFLAGS += $(XPSUBSYS-1) - endif - -endif - -# to enable obsolete functions, disable the NO_OBSOLETE_FUNCS variable: -# $(TARGET): NO_OBSOLETE_FUNCS = -NO_OBSOLETE_FUNCS = NO_OBSOLETE_FUNCS -CC_DEFS += $(NO_OBSOLETE_FUNCS) - -CXXFLAGS += $(CXXSTD) -CXXFLAGS += $(CFLAGS) -CXXFLAGS += $(sort $(CXX_F)) -CXXFLAGS += $(sort $(CXX_WNO)) - -LDFLAGS += $(LDOPT) - -############################################################################# -ifdef __X86__ - DEFX86 = __X86__ -endif - -ifdef __EA64__ - SUFF64=64 - ADRSIZE=64 - DEF64 = __EA64__ -else - ADRSIZE=32 -endif - -ifdef NDEBUG - OPTSUF=_opt -endif - -ifdef IDAHOME - EXTRASUF=_home - IDAHOME_PROCESSORS=pc arm ppc mips mc68k -else - ifdef USE_STATIC_RUNTIME - EXTRASUF=_s - endif -endif - -############################################################################# -SYSDIR=$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(OPTSUF)$(EXTRASUF) -# libraries directory -LIBDIR=$(IDA)lib/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(EXTRASUF) -# object files directory (using ?= to allow overriding) -OBJDIR?=obj/$(SYSDIR) -# PDB files directory -PDBDIR=$(IDA)pdb/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(EXTRASUF) -# output directory for target platform -R=$(IDA)bin/ -# input directory with existing build utilities -RS=$(IDA)bin/ -# _ida.hlp placed in main tool directory -HI=$(RS) -# help source -HS=.hls -# help headers -HH=.hhp -# include,help and other directories are common for all platforms and compilers: -I =$(IDA)include/ -C =$(R)cfg/ -RI=$(R)idc/ -F=$(OBJDIR)/ -L=$(LIBDIR)/ - -DUMB=$(L)dumb$(O) -HELP=$(L)help$(O) -HLIB=$(HI)_ida.hlp - -# to be used like this: -# $(L)va$(A): $(call lib, $(VA_OBJS)) -lib=$(1); $(strip $(QARf)$(AR) $(OUTAR)$$@ $$^) - -# to be used like this: $(call _link_exe, target, objs, libs) -_link_exe=$(strip $(QCCL)$(CCL) $(OUTSW)$(1) $(2) $(3) $(LDFLAGS) $(STDLIBS)) - -# to be used like this: $(call link_exe, objs, libs) -link_exe=$(call _link_exe,$@,$(1),$(2)) - -# to be used like this: $(call _link_dll, target, objs, libs) -_link_dll=$(strip $(QCCL)$(CCL) $(OUTDLL) $(DLLFLAGS) $(OUTSW)$(1) $(2) $(3) $(LDFLAGS) $(STDLIBS)) - -# to be used like this: $(call link_dll, objs, libs) -link_dll=$(call _link_dll,$@,$(1),$(2)) - -# to be used like this: $(call link_dumb, target, libs, objs) -link_dumb=$(3) $(patsubst %,$(L)%$(A),$(2)); $(strip $(QCCLf)$(CCL) $(OUTSW)$(1) $(LDFLAGS) $(3) $(patsubst %,$(L)%$(A),$(2)) $(STDLIBS)) - -# to be used like this: -# target: $(call dumb_target, libs, objs) extra_ldflags -dumb_target=$(call link_dumb,$$@,$(1),$(2) $(DUMB)) - -# to be used like this: -# $(R)%$(B): $(F)%$(O) $(call dumb_pattern, libs, objs) extra_ldflags -dumb_pattern=$(call link_dumb,$$@ $$<,$(1),$(2) $(DUMB)) - -# to be used like this: -# OBJS += $(call objs,obj1 obj2 obj3 ...) -objs=$(addprefix $(F),$(addsuffix $(O),$(1))) - -# output name for module dll -module_dll=$(BIN_PATH)$(1)$(SUFF64)$(DLLEXT) - -# output name for server executable -server_exe=$(R)dbgsrv/$(1) - -ifeq ($(or $(M),$(MM),$(MMH),$(MO),$(MMO),$(MMHO)),1) - BUILD_IDA = 1 -endif -ifeq ($(or $(M32),$(MM),$(MO32),$(MMO)),1) - BUILD_DBGSRV = 1 -endif - -# target-os specific variables -ifdef __NT__ - DLLEXT=.dll -else ifdef __MAC__ - DLLEXT=.dylib -else - DLLEXT=.so -endif - -# build system commands -ifeq ($(OS),Windows_NT) - CP=cp -f --preserve=all - MKDIR=-@mkdir - AWK=gawk -else - CP=cp -f - MKDIR=-@mkdir 2>/dev/null - AWK=awk -endif -RM=rm -f -MV=mv - -# used to silence some makefile commands -# run 'make Q=' to prevent commands from being silenced -Q?=@ - -# some makefiles rebuild targets when the makefile itself changes. -# this makes debugging makefiles a pain. -# run 'make MAKEFILE_DEP=' to disable this behaviour. -MAKEFILE_DEP?=makefile - -# libida-related -# Note: $(IDALIB) should be used in the dependency list -# $(LINKIDA) should be used in the link command -ifdef __NT__ - # Note: on Windows, ida.lib does not have a "64" suffix for ea64 - IDALIB = $(L)ida$(A) - LINKIDA = $(IDALIB) -else - IDALIB = $(L)libida$(SUFF64)$(DLLEXT) - LINKIDA = -L$(L) -lida$(SUFF64) -endif - -# simplify command echo -ifdef IDAMAKE_SIMPLIFY - ifeq ($(Q),@) - DO_IDAMAKE_SIMPLIFY=1 - endif -endif - -ifdef DO_IDAMAKE_SIMPLIFY - ifdef IDAMAKE_SIMPLIFY_NO_COLOR - qcolor=$(1) - else - ifeq ($(OS),Windows_NT) - qcolor=-e # - endif - qcolor+="\033[1;34m$(1)\033[0m" - endif - QCXX = @echo $(call qcolor,compile) $< && # - QCC = @echo $(call qcolor,compile) $< && # - QASM = @echo $(call qcolor,asm) $< && # - QARf = @echo $(call qcolor,lib) $$@ && # - QCCL = @echo $(call qcolor,link) $@ && # - QCCLf = @echo $(call qcolor,link) $$@ && # -endif - -# simple build rules -CONLY?=-c - -$(F)%$(O): %.cpp - $(strip $(QCXX)$(CXX) $(CXXFLAGS) $(NORTTI) $(CONLY) $(OBJSW)$@ $<) - -$(F)%$(O): %.c - $(strip $(QCC)$(CC) $(CFLAGS) $(CONLY) $(OBJSW)$@ $(FORCEC) $<) - -$(C)%.cfg: %.cfg - $(CP) $? $@ - -# http://www.cmcrossroads.com/article/printing-value-makefile-variable -print-%: - @echo $* = "$($*)" - @echo $*\'s origin is $(origin $*) - -############################################################################# -.PHONY: all test cfg includes - -# Force make to delete the target if the rule to build it fails -.DELETE_ON_ERROR: diff --git a/idasdk75/dbg/arm_debmod.cpp b/idasdk75/dbg/arm_debmod.cpp deleted file mode 100644 index 0f43a53..0000000 --- a/idasdk75/dbg/arm_debmod.cpp +++ /dev/null @@ -1,294 +0,0 @@ -#include -#include -#include "arm_debmod.h" - -#ifdef ENABLE_LOWCNDS -inline bool has_armv5(void) { return true; } -static arm_debmod_t *ssmod; // pointer to the current debugger module -#endif - - -#include "arm_regs.hpp" -#include "deb_arm.hpp" - -//-------------------------------------------------------------------------- -arm_debmod_t::arm_debmod_t() -{ - static const uchar bpt[] = ARM_BPT_CODE; - bpt_code.append(bpt, sizeof(bpt)); - sp_idx = R_SP; - pc_idx = R_PC; - lr_idx = R_LR; - sr_idx = R_PSR; - nregs = qnumber(arm_registers); - - is_xscale = false; - for ( size_t i = 0; i < 2; i++ ) - { - databpts[i] = BADADDR; - codebpts[i] = BADADDR; - dbptypes[i] = -1; - cbptypes[i] = -1; - } - dbcon = 0; - set_platform("linux"); -} - -//-------------------------------------------------------------------------- -int idaapi arm_debmod_t::dbg_is_ok_bpt(bpttype_t type, ea_t /*ea*/, int len) -{ - if ( type == BPT_SOFT ) - return BPT_OK; - - if ( !is_xscale ) - return BPT_BAD_TYPE; // hardware bpts are supported only for xScale - - // For some reason hardware instruction breakpoints do not work - if ( type == BPT_EXEC ) - return BPT_BAD_TYPE; - - if ( len > 4 ) - return BPT_BAD_LEN; - - bool ok = databpts[0] == BADADDR || databpts[1] == BADADDR; - - return ok ? BPT_OK : BPT_TOO_MANY; -} - -//-------------------------------------------------------------------------- -bool arm_debmod_t::add_hwbpt(bpttype_t type, ea_t ea, int len) -{ - // msg("add_hwbpt %d %a %d\n", type, ea, len); - if ( !is_xscale || len > 4 ) - return false; - - if ( !init_hwbpt_support() ) - return false; - - if ( type == BPT_EXEC ) - { - if ( codebpts[0] != BADADDR && codebpts[1] != BADADDR ) - return false; - - int slot = codebpts[0] != BADADDR; - codebpts[slot] = ea; - cbptypes[slot] = type; - } - else - { - if ( databpts[0] != BADADDR && databpts[1] != BADADDR ) - return false; - - int slot = databpts[0] != BADADDR; - int bits; - switch ( type ) - { - case BPT_WRITE: - bits = 1; // store only - break; - case BPT_RDWR: - bits = 2; // load/store - break; - // BPT_READ: // load only - // bits = 3; - // break; - default: - return false; - } - databpts[slot] = ea; - dbptypes[slot] = type; - dbcon |= bits << (slot*2); - } - return enable_hwbpts(); -} - -//-------------------------------------------------------------------------- -bool arm_debmod_t::del_hwbpt(ea_t ea, bpttype_t type) -{ - // msg("del_hwbpt %a\n", ea); - if ( databpts[0] == ea && dbptypes[0] == type ) - { - databpts[0] = BADADDR; - dbcon &= ~3; - } - else if ( databpts[1] == ea && dbptypes[1] == type ) - { - databpts[1] = BADADDR; - dbcon &= ~(3<<2); - } - else if ( codebpts[0] == ea && cbptypes[0] == type ) - { - codebpts[0] = BADADDR; - } - else if ( codebpts[1] == ea && cbptypes[1] == type ) - { - codebpts[1] = BADADDR; - } - else - { - return false; - } - return enable_hwbpts(); -} - -//-------------------------------------------------------------------------- -void arm_debmod_t::cleanup_hwbpts() -{ - databpts[0] = BADADDR; - databpts[1] = BADADDR; - codebpts[0] = BADADDR; - codebpts[1] = BADADDR; - dbcon = 0; - // disable all bpts - if ( is_xscale ) - disable_hwbpts(); -} - -//-------------------------------------------------------------------------- -int arm_debmod_t::finalize_appcall_stack( - call_context_t &ctx, - regval_map_t ®s, - bytevec_t &/*stk*/) -{ - regs[lr_idx].ival = ctx.ctrl_ea; - // return addrsize as the adjustment factor to add to sp - // we do not need the return address, that's why we ignore the first 4 - // bytes of the prepared stack image - return debapp_attrs.addrsize; -} - -//-------------------------------------------------------------------------- -int arm_debmod_t::get_regidx(const char *regname, int *clsmask) -{ - return arm_get_regidx(clsmask, regname); -} - -#ifdef ENABLE_LOWCNDS -//-------------------------------------------------------------------------- -static const regval_t &idaapi arm_getreg(const char *name, const regval_t *regvals) -{ - int idx = ssmod->get_regidx(name, NULL); - QASSERT(30182, idx >= 0 && idx < ssmod->nregs); - return regvals[idx]; -} - -//-------------------------------------------------------------------------- -static uint32 idaapi arm_get_long(ea_t ea) -{ - uint32 v = -1; - ssmod->dbg_read_memory(ea, &v, sizeof(v), NULL); - return v; -} - -//-------------------------------------------------------------------------- -static uint16 idaapi arm_get_word(ea_t ea) -{ - uint16 v = -1; - ssmod->dbg_read_memory(ea, &v, sizeof(v), NULL); - return v; -} - -//-------------------------------------------------------------------------- -static uint8 idaapi arm_get_byte(ea_t ea) -{ - uint8 v = -1; - ssmod->dbg_read_memory(ea, &v, sizeof(v), NULL); - return v; -} - -//---------------------------------------------------------------------- -// stripped down version of get_dtype_size() -static size_t idaapi arm_get_dtype_size(op_dtype_t dtype) -{ - switch ( dtype ) - { - case dt_byte: return 1; // 8 bit - case dt_word: - case dt_half: return 2; // 16 bit - case dt_dword: - case dt_float: return 4; // 4 byte - case dt_qword: - case dt_double: return 8; // 8 byte - default: return 0; - } -} - -//-------------------------------------------------------------------------- -// since arm does not have a single step facility, we have to emulate it -// with a temporary breakpoint. -drc_t arm_debmod_t::dbg_perform_single_step(debug_event_t *dev, const insn_t &insn) -{ - // read register values - regvals_t values; - values.resize(nregs); - drc_t drc = dbg_read_registers(dev->tid, ARM_RC_GENERAL, values.begin(), NULL); - if ( drc <= DRC_NONE ) - return drc; - - static const opinfo_helpers_t oh = - { - arm_getreg, - arm_get_byte, - arm_get_word, - arm_get_long, - arm_get_dtype_size, - NULL, // has_insn_cf_chg not needed - }; - - // calculate the address of the next executed instruction - lock_begin(); - ssmod = this; - ea_t next = calc_next_exec_insn(insn, values.begin(), oh, false); // TODO pass is_mprofile parameter - ssmod = NULL; - lock_end(); - - // BADADDR means that the execution flow is linear - if ( next == BADADDR ) - { - next = insn.ea + insn.size; - if ( (values[sr_idx].ival & BIT5) != 0 ) // thumb? - next |= 1; - } - - // safety check: self jumping instruction cannot be single stepped - if ( (next & ~1) == insn.ea ) - return DRC_FAILED; - - // add a breakpoint there - update_bpt_info_t ubi; - ubi.ea = next; - ubi.type = BPT_SOFT; - ubi.code = 0; - int nbpts; - drc = dbg_update_bpts(&nbpts, &ubi, 1, 0, NULL); - if ( drc != DRC_OK || nbpts == 0 ) - return drc != DRC_OK ? drc : DRC_FAILED; - - drc = resume_app_and_get_event(dev); - - // clean up: delete the temporary breakpoint - ubi.ea &= ~1; // del_bpt requires an even address - drc_t drc2 = dbg_update_bpts(&nbpts, &ubi, 0, 1, NULL); - if ( drc2 != DRC_OK || nbpts == 0 ) - { - msg("%a: failed to remove single step bpt?!\n", ubi.ea); - drc = drc2 != DRC_OK ? drc2 : DRC_FAILED; - } - // the caller expects to see STEP after us: - if ( drc == DRC_OK ) - dev->set_eid(STEP); - return drc; -} - -#endif // ENABLE_LOWCNDS - -//-------------------------------------------------------------------------- -void arm_debmod_t::adjust_swbpt(ea_t *p_ea, int *p_len) -{ - ea_t &ea = *p_ea; - if ( (ea & 1) != 0 ) // T bit is set, use a thumb breakpoint - { - ea--; - *p_len = 2; - } -} diff --git a/idasdk75/dbg/arm_debmod.h b/idasdk75/dbg/arm_debmod.h deleted file mode 100644 index f003afa..0000000 --- a/idasdk75/dbg/arm_debmod.h +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef __ARM_DEBMOD__ -#define __ARM_DEBMOD__ - -#include "deb_arm.hpp" -#include "debmod.h" - -//-------------------------------------------------------------------------- -class arm_debmod_t : public debmod_t -{ - typedef debmod_t inherited; -protected: - bool is_xscale; - ea_t databpts[2]; - ea_t codebpts[2]; - bpttype_t dbptypes[2]; - bpttype_t cbptypes[2]; - int dbcon; - - int lr_idx; - int sr_idx; - -public: - arm_debmod_t(); - void cleanup_hwbpts(); - - bool del_hwbpt(ea_t ea, bpttype_t type); - bool add_hwbpt(bpttype_t type, ea_t ea, int len); - ea_t is_hwbpt_triggered(thid_t id, bool is_stepping); - - inline bool active_databpts(void) - { - return databpts[0] != BADADDR || databpts[1] != BADADDR; - } - - inline bool active_codebpts(void) - { - return codebpts[0] != BADADDR || codebpts[1] != BADADDR; - } - - inline bool active_hwbpts(void) - { - return active_databpts() || active_codebpts(); - } - - // overridden base class functions - virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) override; - virtual int finalize_appcall_stack(call_context_t &ctx, regval_map_t ®s, bytevec_t &stk) override; - - // new virtial functions - virtual bool init_hwbpt_support() newapi { return true; } - virtual bool disable_hwbpts() newapi { return false; } - virtual bool enable_hwbpts() newapi { return false; } - virtual bool refresh_hwbpts() newapi { return false; } - - virtual int get_regidx(const char *regname, int *clsmask) override; - virtual void adjust_swbpt(ea_t *p_ea, int *p_len) override; - -protected: -#ifdef ENABLE_LOWCNDS - virtual drc_t dbg_perform_single_step(debug_event_t *dev, const insn_t &insn) override; -#endif -}; - -bool is_32bit_thumb_insn(uint16 code); - -#endif diff --git a/idasdk75/dbg/arm_local_impl.cpp b/idasdk75/dbg/arm_local_impl.cpp deleted file mode 100644 index 742784a..0000000 --- a/idasdk75/dbg/arm_local_impl.cpp +++ /dev/null @@ -1,107 +0,0 @@ -#include - -#include -#include -#include -#include -#include - -#include "deb_arm.hpp" - -#include "arm_regs.cpp" - -//-------------------------------------------------------------------------- -int is_arm_valid_bpt(bpttype_t type, ea_t ea, int len) -{ - if ( type == BPT_SOFT ) - { - if ( (ea & 1) != 0 ) - return BPT_BAD_ADDR; - } - else - { - if ( type != BPT_RDWR // type is good? - && type != BPT_WRITE - && type != BPT_EXEC ) - { - return BPT_BAD_TYPE; - } - - if ( (ea & (len-1)) != 0 ) // alignment is good? - return BPT_BAD_ALIGN; - - if ( len != 1 ) - { - warning("AUTOHIDE REGISTRY\n" - "xScale supports only 1 byte length hardware breakpoints"); - return BPT_BAD_LEN; - } - } - return BPT_OK; -} - -//-------------------------------------------------------------------------- -// if bit0 is set, ensure that thumb mode -// if bit0 is clear, ensure that arm mode -static void handle_arm_thumb_modes(ea_t ea) -{ - bool should_be_thumb = (ea & 1) != 0; - bool is_thumb = processor_t::get_code16_mode(ea); - if ( should_be_thumb != is_thumb ) - processor_t::set_code16_mode(ea, should_be_thumb); -} - -//-------------------------------------------------------------------------- -static easet_t pending_addresses; - -static ssize_t idaapi dbg_callback(void *, int code, va_list) -{ - // we apply thumb/arm switches when the process is suspended. - // it is quite late (normally we should do it as soon as the corresponding - // segment is created) but i did not manage to make it work. - // in the segm_added event the addresses are not enabled yet, - // so switching modes fails. - if ( code == dbg_suspend_process && !pending_addresses.empty() ) - { - for ( easet_t::iterator p=pending_addresses.begin(); - p != pending_addresses.end(); - ++p ) - { - handle_arm_thumb_modes(*p); - } - pending_addresses.clear(); - } - return 0; -} - -//-------------------------------------------------------------------------- -// For ARM processors the low bit means 1-thumb, 0-arm mode. -// The following function goes over the address list and sets the mode -// in IDA database according to bit0. It also resets bit0 for all addresses. -void set_arm_thumb_modes(ea_t *addrs, int qty) -{ - for ( int i=0; i < qty; i++ ) - { - ea_t ea = addrs[i]; - segment_t *s = getseg(ea); - if ( s == NULL ) - pending_addresses.insert(ea); - else - handle_arm_thumb_modes(ea); - - addrs[i] = ea & ~1; - } -} - -//-------------------------------------------------------------------------- -void processor_specific_init(void) -{ - hook_to_notification_point(HT_DBG, dbg_callback); -} - -//-------------------------------------------------------------------------- -void processor_specific_term(void) -{ - unhook_from_notification_point(HT_DBG, dbg_callback); - pending_addresses.clear(); -} diff --git a/idasdk75/dbg/arm_regs.cpp b/idasdk75/dbg/arm_regs.cpp deleted file mode 100644 index 0399eb9..0000000 --- a/idasdk75/dbg/arm_regs.cpp +++ /dev/null @@ -1,213 +0,0 @@ - -#include "arm_regs.hpp" - -//------------------------------------------------------------------------- -// NOTE: keep in sync with register_class_arm_t -const char *arm_register_classes[] = -{ - "General registers", - "VFP registers", - NULL -}; - -#ifndef __EA64__ -//------------------------------------------------------------------------- -static const char *const psr[] = -{ - "MODE", // 0 - "MODE", // 1 - "MODE", // 2 - "MODE", // 3 - "MODE", // 4 - "T", // 5 - "F", // 6 - "I", // 7 - "A", // 8 - "E", // 9 - "IT", // 10 - "IT", // 11 - "IT", // 12 - "IT", // 13 - "IT", // 14 - "IT", // 15 - "GE", // 16 - "GE", // 17 - "GE", // 18 - "GE", // 19 - NULL, // 20 - NULL, // 21 - NULL, // 22 - NULL, // 23 - "J", // 24 - "IT2", // 25 additional bits of IT - "IT2", // 26 additional bits of IT - "Q", // 27 - "V", // 28 - "C", // 29 - "Z", // 30 - "N", // 31 -}; - -//------------------------------------------------------------------------- -static const char *const vfp_format[] = -{ - "VFP_1_double", -}; -#else -//------------------------------------------------------------------------- -static const char *const psr[] = -{ - "M", // 0 AArch32 mode that an exception was taken from - "M", // 1 - "M", // 2 - "M", // 3 - "M", // 4 Execution state that the exception was taken from - "T", // 5 T32 Instruction set state bit - "F", // 6 FIQ mask bit - "I", // 7 IRQ mask bit - "A", // 8 Asynchronous data abort mask bit - "E", // 9 Endianness Execution State bit - "IT", // 10 If-Then - "IT", // 11 - "IT", // 12 - "IT", // 13 - "IT", // 14 - "IT", // 15 - "GE", // 16 Greater than or Equal flags - "GE", // 17 - "GE", // 18 - "GE", // 19 - "IL", // 20 Illegal Execution State bit - NULL, // 21 - NULL, // 22 - NULL, // 23 - NULL, // 24 - "IT2", // 25 If-Then - "IT2", // 26 - "Q", // 27 Cumulative saturation bit - "V", // 28 oVerflow condition flag - "C", // 29 Carry condition flag - "Z", // 30 Zero condition flag - "N", // 31 Negative condition flag -}; -#endif - -//------------------------------------------------------------------------- -// NOTE: keep in sync with register_arm_t -register_info_t arm_registers[] = -{ -#ifndef __EA64__ - // General registers - { "R0", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R1", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R2", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R3", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R4", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R5", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R6", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R7", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R8", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R9", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R10", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R11", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "R12", REGISTER_ADDRESS|REGISTER_FP, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "SP", REGISTER_ADDRESS|REGISTER_SP, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "LR", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "PC", REGISTER_ADDRESS|REGISTER_IP, ARM_RC_GENERAL, dt_dword, NULL, 0 }, - { "PSR", 0, ARM_RC_GENERAL, dt_dword, psr, 0xF800007F }, - // VFP registers - { "D0", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D1", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D2", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D3", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D4", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D5", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D6", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D7", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D8", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D9", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D10", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D11", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D12", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D13", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D14", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D15", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D16", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D17", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D18", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D19", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D20", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D21", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D22", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D23", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D24", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D25", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D26", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D27", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D28", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D29", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D30", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "D31", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, - { "FPSCR", 0, ARM_RC_VFP, dt_dword, NULL, 0 }, -#else - // General registers - { "X0", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X1", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X2", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X3", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X4", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X5", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X6", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X7", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X8", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X9", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X10", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X11", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X12", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X13", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X14", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X15", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X16", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X17", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X18", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X19", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X20", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X21", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X22", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X23", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X24", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X25", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X26", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X27", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X28", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X29", REGISTER_ADDRESS|REGISTER_FP, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "X30", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "SP", REGISTER_ADDRESS|REGISTER_SP, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "PC", REGISTER_ADDRESS|REGISTER_IP, ARM_RC_GENERAL, dt_qword, NULL, 0 }, - { "PSR", 0, ARM_RC_GENERAL, dt_dword, psr, 0xF8000000 }, -#endif -}; -CASSERT(qnumber(arm_registers) == ARM_NREGS); - -//------------------------------------------------------------------------- -int arm_get_regidx(int *clsmask, const char *regname) -{ - for ( size_t i = 0; i < qnumber(arm_registers); i++ ) - { - if ( strieq(regname, arm_registers[i].name) ) - { - if ( clsmask != NULL ) - *clsmask = arm_registers[i].register_class; - return i; - } - } - return -1; -} - -//------------------------------------------------------------------------- -int arm_get_regclass(int idx) -{ - if ( idx >= 0 && idx < qnumber(arm_registers) ) - return arm_registers[idx].register_class; - return 0; -} diff --git a/idasdk75/dbg/arm_regs.hpp b/idasdk75/dbg/arm_regs.hpp deleted file mode 100644 index ec39797..0000000 --- a/idasdk75/dbg/arm_regs.hpp +++ /dev/null @@ -1,136 +0,0 @@ - -#pragma once - -#include -#include - -//------------------------------------------------------------------------- -#if defined(__LINUX__) && defined(__ARM__) && !defined(__EA64__) -# define __HAVE_ARM_VFP__ -#endif - -//------------------------------------------------------------------------- -// NOTE: keep in sync with arm_register_classes -enum register_class_arm_t -{ - ARM_RC_GENERAL = 0x01, // General registers - ARM_RC_VFP = 0x02, // VFP registers - ARM_RC_ALL = ARM_RC_GENERAL -#ifdef __HAVE_ARM_VFP__ - | ARM_RC_VFP -#endif -}; - -//------------------------------------------------------------------------- -// NOTE: keep in sync with arm_registers -enum register_arm_t -{ -#ifndef __EA64__ - // General registers - R_R0, - R_R1, - R_R2, - R_R3, - R_R4, - R_R5, - R_R6, - R_R7, - R_R8, - R_R9, - R_R10, - R_R11, - R_R12, - R_SP, - R_LR, - R_PC, - R_PSR, - // VFP registers - R_D0, - R_D1, - R_D2, - R_D3, - R_D4, - R_D5, - R_D6, - R_D7, - R_D8, - R_D9, - R_D10, - R_D11, - R_D12, - R_D13, - R_D14, - R_D15, - R_D16, - R_D17, - R_D18, - R_D19, - R_D20, - R_D21, - R_D22, - R_D23, - R_D24, - R_D25, - R_D26, - R_D27, - R_D28, - R_D29, - R_D30, - R_D31, - R_FPSCR, -#else - // General registers - R_R0, - R_R1, - R_R2, - R_R3, - R_R4, - R_R5, - R_R6, - R_R7, - R_R8, - R_R9, - R_R10, - R_R11, - R_R12, - R_R13, - R_R14, - R_R15, - R_R16, - R_R17, - R_R18, - R_R19, - R_R20, - R_R21, - R_R22, - R_R23, - R_R24, - R_R25, - R_R26, - R_R27, - R_R28, - R_R29, - R_LR, - R_SP, - R_PC, - R_PSR, -#endif -}; - -// Number of registers in arm and aarch64 -#define ARM64_NREGS 34 -#define ARM32_NREGS 50 - -#ifdef __EA64__ - #define ARM_NREGS ARM64_NREGS -#else - #define ARM_NREGS ARM32_NREGS -#endif - -//------------------------------------------------------------------------- -extern const char *arm_register_classes[]; -extern register_info_t arm_registers[ARM_NREGS]; - -//------------------------------------------------------------------------- -int arm_get_regidx(int *clsmask, const char *regname); -int arm_get_regclass(int idx); diff --git a/idasdk75/dbg/bin_search.cpp b/idasdk75/dbg/bin_search.cpp deleted file mode 100644 index 00a67ec..0000000 --- a/idasdk75/dbg/bin_search.cpp +++ /dev/null @@ -1,906 +0,0 @@ -#include -#include "debmod.h" - -//#define TEST -#ifdef TEST -static uchar memory[256]; -static const int PAGESZ = 4; -static ssize_t read_page(ea_t ea, void *buf, size_t size, qstring *) -{ - QASSERT(1517, (size % PAGESZ) == 0); - if ( ea >= sizeof(memory) ) - return -1; - memcpy(buf, &memory[ea], size); - return size; -} -#else -static const int PAGESZ = 4096; -#define read_page(ea, buf, size, errbuf) mod->dbg_read_memory(ea, buf, size, errbuf) -#endif -static const int PAGE_HB = 1000; // page heartbeat counter -static const int TIME_HB = (RECV_TIMEOUT_PERIOD/1000) / 2; - // time period between heartbeats - -//-------------------------------------------------------------------------- -// memrchr is unavailable under Windows and MAC -#if defined(_WIN32) || defined(__MAC__) -// fixme: we need more optimized version -static void *local_memrchr(const void *s, int c, size_t n) -{ - const unsigned char *start = (const unsigned char *)s; - const unsigned char *end = start + n - 1; - while ( end >= start ) - { - if ( *end == c ) - return (void *)end; - end--; - } - return NULL; -} -#else -#define local_memrchr memrchr -#endif - -//-------------------------------------------------------------------------- -class matcher_t -{ -protected: - struct partmatch_t - { - ea_t match_ea; // starting address of the match - size_t ptn_idx; // index of the pattern - size_t ptn_off; // offset inside the pattern - }; - typedef qlist partmatches_t; - - // constructor arguments - ea_t *found_ea; - debmod_t *mod; - const compiled_binpat_vec_t &ptns; - int srch_flags; - qstring *errbuf; //lint !e958 - - uchar page[PAGESZ]; - ea_t page_ea; - partmatches_t pmatches; - ea_t failed_ea; - - // cache - intvec_t simple_ptns; // indexes of patterns w/o a mask and the search is case sensitive - intvec_t complex_ptns; // other patterns - - // heartbeat - uint32 last_hb; // time in secs of the last heartbeat - - matcher_t( - ea_t *_found_ea, - debmod_t *_mod, - const compiled_binpat_vec_t &_ptns, - int _srch_flags, - qstring *_errbuf) - : found_ea(_found_ea), - mod(_mod), - ptns(_ptns), - srch_flags(_srch_flags), - errbuf(_errbuf), - page_ea(BADADDR), - failed_ea(BADADDR) - { - for ( int i=0; i < ptns.size(); ++i ) - { - const compiled_binpat_t &ptn = ptns[i]; - if ( ptn.bytes.empty() ) - continue; - if ( sense_case() && ptn.all_bytes_defined() ) //TODO: && !inf_is_wide_high_byte_first() - for servers - simple_ptns.push_back(i); - else - complex_ptns.push_back(i); - } - memset(page, 0, sizeof(page)); - last_hb = get_secs(qtime64()); - } - - bool sense_case(void) const { return (srch_flags & BIN_SEARCH_CASE) != 0; } - bool check_break(void) const { return (srch_flags & BIN_SEARCH_NOBREAK) == 0; } - - bool test_cancelled(void) const - { - struct ida_local tester_t : public exec_request_t - { - virtual ~tester_t() {} - virtual int idaapi execute(void) - { - return user_cancelled(); - } - }; - tester_t tester; - return execute_sync(tester, MFF_FAST); - } - - void send_heartbeat(size_t *page_counter) - { - *page_counter += 1; - if ( *page_counter >= PAGE_HB ) - { - *page_counter = 0; - uint32 now = get_secs(qtime64()); - if ( now - last_hb >= TIME_HB ) - { - mod->dmsg(""); // heartbeat - last_hb = now; - } - } - } - -public: - DECLARE_VIRTUAL_DTOR(matcher_t) - { - found_ea = NULL; - mod = NULL; - errbuf = NULL; - } - - virtual drc_t walk_memory_ranges(const ea_t srch_start_ea, const ea_t srch_end_ea) = 0; - - drc_t search_memory_range(ea_t range_start_ea, ea_t range_end_ea) - { - if ( range_is_unreadable(range_start_ea) ) - { - #ifndef TEST - mod->debdeb("dbg_bin_search memory range %a..%a is unreadable, skip it\n", range_start_ea, range_end_ea); - #endif - return DRC_FAILED; - } - - return find(range_start_ea, range_end_ea); - } - - virtual drc_t find(ea_t start_ea, ea_t end_ea) = 0; - - bool match_pattern( - const uchar *page_ptr, - const compiled_binpat_t &ptn, - size_t ptn_off, - size_t nbytes) const - { - const uchar *image = ptn.bytes.begin() + ptn_off; - const uchar *mask = ptn.all_bytes_defined() ? NULL : ptn.mask.begin() + ptn_off; - for ( int i=0; i < nbytes; ++i, ++page_ptr, ++image ) - { - uchar c = *page_ptr; - if ( mask != NULL ) - { - if ( mask == SKIP_FF_MASK ) - { - if ( *image == 0xFF ) - continue; - } - else - { - if ( mask[i] == 0 ) - continue; - } - } - uchar c2 = *image; - if ( sense_case() ? (c != c2) : (qtoupper(c) != qtoupper(c2)) ) - return false; - } - return true; - } - - ea_t get_failed_address(void) const { return failed_ea; } - -private: - bool range_is_unreadable(ea_t range_start_ea) - { - uchar dummy; - return mod->dbg_read_memory(range_start_ea, &dummy, sizeof(dummy), NULL) != sizeof(dummy); - } -}; - -typedef janitor_t matcher_janitor_t; -template <> inline matcher_janitor_t::~janitor_t() -{ - delete resource; - resource = NULL; -} - -//-------------------------------------------------------------------------- -class forward_matcher_t : public matcher_t -{ - size_t last_off; - -public: - forward_matcher_t( - ea_t *_found_ea, - debmod_t *_mod, - const compiled_binpat_vec_t &_ptns, - int _srch_flags, - qstring *_errbuf) - : matcher_t(_found_ea, _mod, _ptns, _srch_flags, _errbuf), - last_off(PAGESZ) - {} - - //-------------------------------------------------------------------------- - virtual drc_t walk_memory_ranges(const ea_t srch_start_ea, const ea_t srch_end_ea) override - { - meminfo_vec_t::const_iterator p=mod->old_ranges.begin(); - ea_t range_start_ea = BADADDR; - for ( ; p < mod->old_ranges.end(); ++p ) - { - if ( p->contains(srch_start_ea) ) - { - range_start_ea = srch_start_ea; - break; - } - if ( p->start_ea > srch_start_ea ) - break; - } - if ( range_start_ea == BADADDR ) - { - if ( p == mod->old_ranges.end() || p->start_ea >= srch_end_ea ) - return DRC_FAILED; // not found - range_start_ea = p->start_ea; - } - ea_t range_end_ea = srch_end_ea < p->end_ea ? srch_end_ea : p->end_ea; - drc_t drc = search_memory_range(range_start_ea, range_end_ea); - if ( drc != DRC_FAILED ) // not found - return drc; - - for ( ++p; p < mod->old_ranges.end() && srch_end_ea >= p->end_ea; ++p ) - { - range_start_ea = p->start_ea; - range_end_ea = srch_end_ea < p->end_ea ? srch_end_ea : p->end_ea; - drc = search_memory_range(range_start_ea, range_end_ea); - if ( drc != DRC_FAILED ) // not found - return drc; - } - - return DRC_FAILED; // not found - } - - //-------------------------------------------------------------------------- - // find patterns in [start_ea, end_ea) - virtual drc_t find(ea_t start_ea, ea_t end_ea) override - { - page_ea = align_down(start_ea, PAGESZ); - ea_t page_off = start_ea - page_ea; - size_t page_counter = 0; - while ( page_ea < end_ea ) - { - if ( check_break() && test_cancelled() ) - return DRC_ERROR; - if ( read_page(page_ea, page, sizeof(page), errbuf) != sizeof(page) ) - { - failed_ea = page_ea; - return DRC_ERROR; - } - last_off = end_ea - page_ea; - if ( last_off > PAGESZ ) - last_off = PAGESZ; - // handle partial matches first - for ( partmatches_t::iterator p=pmatches.begin(); p != pmatches.end(); ) - { - switch ( finalize_partial_match(*p) ) - { - case DRC_OK: // found a match - return DRC_OK; - default: - case DRC_FAILED: // definitely failed - p = pmatches.erase(p); - break; - case DRC_NONE: // need to continue matching - ++p; - break; - } - } - // try to find new matches - if ( match_simple_patterns(page_off) ) - return DRC_OK; - if ( !complex_ptns.empty() ) - { - while ( page_off < last_off ) - { - if ( match_at(page_off) ) - return DRC_OK; - page_off++; - } - } - page_ea += PAGESZ; // advance to the next page - page_off = 0; - send_heartbeat(&page_counter); - } - return DRC_FAILED; - } - -private: - //-------------------------------------------------------------------------- - // try to match complex patterns at PAGE_OFF - // too long patterns that do not fit the page will be matched partially - // if the partial match is ok, we will remember them - bool match_at(ea_t page_off) - { - const uchar *page_ptr = page + page_off; - size_t rest = last_off - page_off; - for ( intvec_t::const_iterator p=complex_ptns.begin(); - p != complex_ptns.end(); - ++p ) - { - const int &i = *p; - const compiled_binpat_t &ptn = ptns[i]; - size_t vecsize = ptn.bytes.size(); - size_t nbytes = qmin(rest, vecsize); - if ( !match_pattern(page_ptr, ptn, 0, nbytes) ) - continue; - if ( vecsize <= rest ) - { - *found_ea = page_ea + page_off; - return true; // fits the page, a simple comparison is enough - } - // remember partial match - partmatch_t pm; - pm.match_ea = page_ea + page_off; - pm.ptn_idx = i; - pm.ptn_off = nbytes; - pmatches.push_back(pm); - } - return false; - } - - //-------------------------------------------------------------------------- - // try to match simple patterns inside the page - // the partial match is processed as described above - bool match_simple_patterns(ea_t page_off) - { - for ( intvec_t::const_iterator p=simple_ptns.begin(); - p != simple_ptns.end(); - ++p ) - { - const int &i = *p; - const uchar *page_ptr = page + page_off; - size_t rest = last_off - page_off; - const bytevec_t &ptn_bytes = ptns[i].bytes; - size_t ptn_sz = ptn_bytes.size(); - uchar ptn_ch = ptn_bytes[0]; - - const uchar *pold = page_ptr; - while ( rest > 0 ) - { - const uchar *pnew = (uchar *)memchr(pold, ptn_ch, rest); - if ( pnew == NULL ) - break; - rest -= (pnew - pold); - size_t nbytes = qmin(rest, ptn_sz); - if ( memcmp(pnew, ptn_bytes.begin(), nbytes) == 0 ) - { - ea_t matched_ea = page_ea + (pnew - page); - if ( ptn_sz <= rest ) - { - *found_ea = matched_ea; - return true; - } - // remember partial match - partmatch_t pm; - pm.match_ea = matched_ea; - pm.ptn_idx = i; - pm.ptn_off = nbytes; - pmatches.push_back(pm); - } - pold = pnew + 1; - rest -= 1; - } - } - return false; - } - - //-------------------------------------------------------------------------- - // try to finalize a partial match by matching the next part of the - // long pattern against the start of the PAGE. patterns that are still - // too long for matching may produce new partial matches. - drc_t finalize_partial_match(partmatch_t &pm) - { - const compiled_binpat_t &ptn = ptns[pm.ptn_idx]; - size_t vecsize = ptn.bytes.size(); - size_t ptn_rest = vecsize - pm.ptn_off; - size_t nbytes = qmin(ptn_rest, last_off); - if ( !match_pattern(page, ptn, pm.ptn_off, nbytes) ) - return DRC_FAILED; - if ( ptn_rest <= last_off ) - { - *found_ea = pm.match_ea; - return DRC_OK; // finalized the match - } - if ( last_off != PAGESZ ) - return DRC_FAILED; - // remember a new partial match - pm.ptn_off += PAGESZ; - return DRC_NONE; - } -}; - -//-------------------------------------------------------------------------- -class backward_matcher_t : public matcher_t -{ - ea_t page_off; - -public: - backward_matcher_t( - ea_t *_found_ea, - debmod_t *_mod, - const compiled_binpat_vec_t &_ptns, - int _srch_flags, - qstring *_errbuf) - : matcher_t(_found_ea, _mod, _ptns, _srch_flags, _errbuf), - page_off(0) - {} - - //-------------------------------------------------------------------------- - virtual drc_t walk_memory_ranges(const ea_t srch_start_ea, const ea_t srch_end_ea) override - { - meminfo_vec_t::const_iterator p=mod->old_ranges.end() - 1; - ea_t range_end_ea = BADADDR; - for ( ; p >= mod->old_ranges.begin(); --p ) - { - if ( p->start_ea < srch_end_ea ) - { - range_end_ea = srch_end_ea < p->end_ea ? srch_end_ea : p->end_ea; - break; - } - } - if ( range_end_ea == BADADDR ) - return DRC_FAILED; // not found - ea_t range_start_ea = p->contains(srch_start_ea) ? srch_start_ea : p->start_ea; - drc_t drc = search_memory_range(range_start_ea, range_end_ea); - if ( drc != DRC_FAILED ) // not found - return drc; - - for ( --p; p >= mod->old_ranges.begin() && srch_start_ea < p->end_ea; --p ) - { - range_end_ea = p->end_ea; - range_start_ea = p->contains(srch_start_ea) ? srch_start_ea : p->start_ea; - drc = search_memory_range(range_start_ea, range_end_ea); - if ( drc != DRC_FAILED ) // not found - return drc; - } - - return DRC_FAILED; // not found - } - - //-------------------------------------------------------------------------- - // find patterns in [start_ea, end_ea) - virtual drc_t find(ea_t start_ea, ea_t end_ea) override - { - page_ea = align_down(end_ea - 1, PAGESZ); - ea_t last_off = end_ea - page_ea; - size_t page_counter = 0; - while ( start_ea < page_ea + PAGESZ ) - { - if ( check_break() && test_cancelled() ) - return DRC_ERROR; - if ( read_page(page_ea, page, sizeof(page), errbuf) != sizeof(page) ) - { - failed_ea = page_ea; - return DRC_ERROR; - } - page_off = page_ea < start_ea ? start_ea - page_ea : 0; - // handle partial matches first - for ( partmatches_t::iterator p=pmatches.begin(); p != pmatches.end(); ) - { - switch ( finalize_partial_match(*p) ) - { - case DRC_OK: // found a match - return DRC_OK; - default: - case DRC_FAILED: // definitely failed - p = pmatches.erase(p); - break; - case DRC_NONE: // need to continue matching - ++p; - break; - } - } - // try to find new matches - if ( match_simple_patterns(last_off) ) - return DRC_OK; - if ( !complex_ptns.empty() ) - { - while ( page_off < last_off ) - { - if ( match_before(last_off) ) - return DRC_OK; - last_off--; - } - } - page_ea -= PAGESZ; // advance to the next page - last_off = PAGESZ; - send_heartbeat(&page_counter); - } - return DRC_FAILED; - } - -private: - //-------------------------------------------------------------------------- - // try to match all patterns before LAST_OFF - // too long patterns that do not fit the page will be matched partially - // if the partial match is ok, we will remember them - bool match_before(ea_t last_off) - { - size_t rest = last_off - page_off; - for ( intvec_t::const_iterator p=complex_ptns.begin(); - p != complex_ptns.end(); - ++p ) - { - const int &i = *p; - const compiled_binpat_t &ptn = ptns[i]; - size_t vecsize = ptn.bytes.size(); - size_t nbytes = qmin(rest, vecsize); - if ( !match_pattern(page+last_off-nbytes, ptn, vecsize-nbytes, nbytes) ) - continue; - if ( vecsize <= rest ) - { - *found_ea = page_ea + last_off - nbytes; - return true; // fits the page, a simple comparison is enough - } - // remember partial match - partmatch_t pm; - pm.match_ea = page_ea + last_off - vecsize; - pm.ptn_idx = i; - pm.ptn_off = nbytes; - pmatches.push_back(pm); - } - return false; - } - - //-------------------------------------------------------------------------- - // try to match simple patterns inside the page - // the partial match is processed as described above - bool match_simple_patterns(ea_t last_off) - { - const uchar *page_ptr = page + page_off; - - for ( intvec_t::const_iterator q=simple_ptns.begin(); - q != simple_ptns.end(); - ++q ) - { - const int &i = *q; - size_t rest = last_off - page_off; - const bytevec_t &ptn_bytes = ptns[i].bytes; - size_t ptn_sz = ptn_bytes.size(); - uchar ptn_ch = ptn_bytes[ptn_sz-1]; - - while ( rest > 0 ) - { - const uchar *p = (uchar *)local_memrchr(page_ptr, ptn_ch, rest); - if ( p == NULL ) - break; - rest = p + 1 - page_ptr; - size_t nbytes = qmin(rest, ptn_sz); - if ( memcmp(p + 1 - nbytes, &ptn_bytes[ptn_sz - nbytes], nbytes) == 0 ) - { - ea_t matched_ea = page_ea + (p + 1 - page) - ptn_sz; - if ( ptn_sz <= rest ) - { - *found_ea = matched_ea; - return true; - } - // remember partial match - partmatch_t pm; - pm.match_ea = matched_ea; - pm.ptn_idx = i; - pm.ptn_off = nbytes; - pmatches.push_back(pm); - } - rest -= 1; - } - } - return false; - } - - //-------------------------------------------------------------------------- - // try to finalize a partial match by matching the previous part of the - // long pattern against the end of the PAGE. patterns that are still - // too long for matching may produce new partial matches. - drc_t finalize_partial_match(partmatch_t &pm) - { - const compiled_binpat_t &ptn = ptns[pm.ptn_idx]; - size_t vecsize = ptn.bytes.size(); - size_t ptn_rest = vecsize - pm.ptn_off; - size_t nbytes = qmin(ptn_rest, PAGESZ - page_off); - if ( !match_pattern(page + PAGESZ - nbytes, ptn, ptn_rest - nbytes, nbytes) ) - return DRC_FAILED; - if ( ptn_rest <= PAGESZ - page_off ) - { - *found_ea = pm.match_ea; - return DRC_OK; // finalized the match - } - if ( page_off != 0 ) - return DRC_FAILED; - // remember a new partial match - pm.ptn_off += PAGESZ; - return DRC_NONE; - } - -}; - -#ifndef TEST -//-------------------------------------------------------------------------- -// Note: -// The input search range can include the unreadable memory regions. -// For example, "[vvar]" on Linux. -// read_memory() returns 0 when trying to read from such region. -// These regions must be skipped. -drc_t idaapi debmod_t::dbg_bin_search( - ea_t *found_ea, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &ptns, - int srch_flags, - qstring *errbuf) -{ - static int forbidden = -1; - if ( forbidden == -1 ) - forbidden = qgetenv("IDA_IDB_BIN_SEARCH", NULL); - if ( forbidden ) - return DRC_NONE; - - debdeb("dbg_bin_search %a..%a\n", start_ea, end_ea); - - if ( start_ea >= end_ea || ptns.empty() || old_ranges.empty() ) - return DRC_NONE; - - //lint -esym(429,matcher) has not been freed - matcher_t *matcher = NULL; - matcher_janitor_t matcher_janitor(matcher); - - bool search_backward = (srch_flags & BIN_SEARCH_BACKWARD) != 0; - if ( search_backward ) - matcher = new backward_matcher_t(found_ea, this, ptns, srch_flags, errbuf); - else - matcher = new forward_matcher_t(found_ea, this, ptns, srch_flags, errbuf); - - drc_t drc = matcher->walk_memory_ranges(start_ea, end_ea); - if ( drc != DRC_ERROR ) - return drc; //-V773 without releasing the 'matcher' pointer - - ea_t failed_ea = matcher->get_failed_address(); - if ( failed_ea != BADADDR ) - { - debdeb("dbg_bin_search failed to read memory at %a\n", failed_ea); - if ( errbuf != NULL && errbuf->empty() ) - errbuf->sprnt("Failed to read memory at %a\n", failed_ea); - } - - return DRC_ERROR; -} - -#else // TEST -//-------------------------------------------------------------------------- -drc_t binary_search( - ea_t *found_ea, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &ptns, - int srch_flags, - qstring *errbuf) -{ - matcher_t *matcher; - if ( (srch_flags & BIN_SEARCH_BACKWARD) != 0 ) - matcher = new backward_matcher_t(found_ea, NULL, ptns, srch_flags, errbuf); - else - matcher = new forward_matcher_t(found_ea, NULL, ptns, srch_flags, errbuf); - drc_t drc = matcher->find(start_ea, end_ea); - delete matcher; - return drc; -} - -//--------------------------------------------------------------------------- -inline bool cmpbytes( - const uchar *ptr, - uchar b, - const uchar *pptr, - size_t ptnsize, - bool sense_case) -{ - if ( sense_case ) - return *ptr == b && memcmp(ptr+1, pptr, ptnsize) == 0; //lint !e670 - if ( qtoupper(b) != qtoupper(*ptr) ) - return false; - ++ptr; - for ( int i=0; i < ptnsize; ++i, ++ptr, ++pptr ) - { - if ( qtoupper(*ptr) != qtoupper(*pptr) ) - return false; - } - return true; -} - -//--------------------------------------------------------------------------- -void *memmem( - const void *buf, - size_t bufsize, - const void *ptn, - size_t ptnsize, - bool sense_case) -{ - if ( int(ptnsize) <= 0 || int(bufsize) < 0 || ptnsize > bufsize ) - return NULL; - const uchar *ptr = (const uchar *)buf; - const uchar *const end = ptr + bufsize - ptnsize + 1; - const uchar *pptr = (const uchar *)ptn; - uchar b = *pptr++; - ptnsize--; - while ( ptr < end ) - { - if ( cmpbytes(ptr, b, pptr, ptnsize, sense_case) ) - return (void *)ptr; - ++ptr; - } - return NULL; -} - -//--------------------------------------------------------------------------- -void *memmemr( - const void *buf, - size_t bufsize, - const void *ptn, - size_t ptnsize, - bool sense_case) -{ - if ( int(ptnsize) <= 0 || int(bufsize) < 0 || ptnsize > bufsize ) - return NULL; - const uchar *ptr = (const uchar *)buf + bufsize - ptnsize; - const uchar *const start = (const uchar *)buf; - const uchar *pptr = (const uchar *)ptn; - uchar b = *pptr++; - ptnsize--; - while ( start <= ptr ) - { - if ( cmpbytes(ptr, b, pptr, ptnsize, sense_case) ) - return (void *)ptr; - --ptr; - } - return NULL; -} - -//-------------------------------------------------------------------------- -drc_t simple_binary_search( - eavec_t *found_eas, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &ptns, - int srch_flags, - qstring * /*errbuf*/) -{ - if ( start_ea >= end_ea || start_ea > sizeof(memory) ) - return DRC_FAILED; - bool sense_case = (srch_flags & BIN_SEARCH_CASE) != 0; - found_eas->clear(); - bool backward = (srch_flags & BIN_SEARCH_BACKWARD) != 0; - for ( compiled_binpat_vec_t::const_iterator p=ptns.begin(); - p != ptns.end(); - ++p ) - { - const bytevec_t &vec = p->bytes; - uchar *start = memory + start_ea; - asize_t nbytes = qmin(sizeof(memory)-start_ea, end_ea-start_ea); - uchar *f = (uchar *)(backward - ? memmemr(start, nbytes, vec.begin(), vec.size(), sense_case) - : memmem(start, nbytes, vec.begin(), vec.size(), sense_case)); - if ( f == NULL ) - continue; - ea_t idx = f - memory; - if ( idx >= end_ea ) - continue; - found_eas->push_back(idx); - } - return found_eas->empty() ? DRC_FAILED : DRC_OK; -} - -//-------------------------------------------------------------------------- -static bool check(qstring *found1_s, const eavec_t &found1, ea_t found2) -{ - bool ok = found1.empty() && found2 == BADADDR; - for ( int k=0; k < found1.size(); ++k ) - { - if ( found1[k] == found2 ) - ok = true; - if ( k > 0 ) - found1_s->append(','); - found1_s->cat_sprnt("%a", found1[k]); - } - if ( found1_s->empty() ) - found1_s->sprnt("%a", BADADDR); - return ok; -} - -//-------------------------------------------------------------------------- -int main(int argc, char *argv[]) -{ - bool sense_case = false; - int max_ptns = 3; - for ( int i=1; i < argc; ++i ) - { - char argch = argv[i][0]; - if ( argch == 'C' ) - { - sense_case = true; - } - else if ( '0' < argch && argch <= '9' ) - { - max_ptns = argch - '0'; - } - } - msg("Test bin_search with %d pattern[s] and %s\n", - max_ptns, - sense_case ? "case sensitive" : "case ignored"); - - for ( int i=0; i < sizeof(memory); i++ ) - memory[i] = i;//rand(); - - for ( int i=0; i < 1000000; i++ ) - { - // prepare a pattern for searching - compiled_binpat_vec_t ptns; - int ptns_cnt = max_ptns == 1 ? 1 : (rand() % max_ptns) + 1; - ptns.resize(ptns_cnt); - qstring out; - for ( int c=0; c < ptns.size(); c++ ) - { - size_t off = rand() % sizeof(memory); - size_t len = (rand() % sizeof(memory)/20) + 1; - if ( (rand() % 50) == 0 ) - len += 8; - compiled_binpat_t &pat = ptns[c]; - pat.bytes.resize(len, 0xFF); - size_t copyable = qmin(sizeof(memory)-off, len); - memcpy(pat.bytes.begin(), &memory[off], copyable); - if ( c > 0 ) - out.append(","); - out.cat_sprnt("%X:%X", int(off), int(len)); - // if some rare cases make the pattern possibly insearchable - if ( (rand() % 50) == 0 ) - { - pat.bytes[0] = 0xAA; - out.append("-"); - } - } - ea_t start_ea = rand() % sizeof(memory); - ea_t end_ea = start_ea + (rand() % sizeof(memory)); - if ( end_ea > sizeof(memory) ) - end_ea = sizeof(memory); // no need to test out of memory - int flags = sense_case ? BIN_SEARCH_CASE : BIN_SEARCH_NOCASE; - - eavec_t found1; - simple_binary_search(&found1, start_ea, end_ea, ptns, flags|BIN_SEARCH_FORWARD, NULL); - - ea_t found2 = BADADDR; - binary_search(&found2, start_ea, end_ea, ptns, flags|BIN_SEARCH_FORWARD, NULL); - - qstring found1_s; - bool ok = check(&found1_s, found1, found2); - msg("%3d find (%s) in (%a..%a) => %s %a\n", i, out.c_str(), start_ea, end_ea, found1_s.c_str(), found2); - if ( !ok ) - { - msg("FAILED!\n"); - return 1; - } - - found1.clear(); - simple_binary_search(&found1, start_ea, end_ea, ptns, flags|BIN_SEARCH_BACKWARD, NULL); - - found2 = BADADDR; - binary_search(&found2, start_ea, end_ea, ptns, flags|BIN_SEARCH_BACKWARD, NULL); - - found1_s.qclear(); - ok = check(&found1_s, found1, found2); - msg("%3d findr(%s) in (%a..%a) => %s %a\n", i, out.c_str(), start_ea, end_ea, found1_s.c_str(), found2); - if ( !ok ) - { - msg("FAILED!\n"); - return 1; - } - } - msg("OK\n"); - return 0; -} -#endif // TEST diff --git a/idasdk75/dbg/bochs/bochsext.h b/idasdk75/dbg/bochs/bochsext.h deleted file mode 100644 index c0dee72..0000000 --- a/idasdk75/dbg/bochs/bochsext.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Interactive disassembler (IDA). - * ALL RIGHTS RESERVED. - * Copyright (c) 1990-2020 Hex-Rays - * - * - * This file defines the Bochs Debugger module extension functions. - * Use debugger_t->get_debmod_extensions() to retrieve this structure. - * - */ - -#ifndef __BOCHSEXT__ -#define __BOCHSEXT__ - -#pragma pack(push, 1) - -#define BOCHSEXT_VER 1 - -struct bochsext_t -{ - // the structure version - uint32 version; - - // Sends an arbitrary command to Bochs internal debugger - // cmd - command to send - // out - pointer to qstring that will hold the output of the command - // Returns: true if ok; false if failed to send command to bochs or receive - // a reply - bool (idaapi *send_command)(const char *cmd, qstring *out); -}; - -#pragma pack(pop) - -#endif diff --git a/idasdk75/dbg/bochs/ctrl/bochsys.h b/idasdk75/dbg/bochs/ctrl/bochsys.h deleted file mode 100644 index 96c0188..0000000 --- a/idasdk75/dbg/bochs/ctrl/bochsys.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Interactive disassembler (IDA). - * ALL RIGHTS RESERVED. - * Copyright (c) 1990-2020 Hex-Rays - * - * - * This file defines the functions prototypes that are exported by bochsys.dll - * - * - */ - -#ifndef __BOCHSYS_DLL__ -#define __BOCHSYS_DLL__ - -#define WIN32_LEAN_AND_MEAN -#include - -#define BX_CALLCONV WINAPI - -typedef wchar_t wchar16_t; -//CASSERT(sizeof(wchar16_t) == 2); - -//-------------------------------------------------------------------------- -// These functions are similar to MS Windows functions. Please refer -// to the SDK documentation for more information on how to use them. -extern FARPROC WINAPI BxGetProcAddress(HMODULE hMod, LPCSTR ProcName); -extern HMODULE WINAPI BxGetModuleHandleA(LPCSTR ModuleFileName); -extern DWORD WINAPI BxGetModuleFileNameA(HINSTANCE hModule, LPCSTR lpFilename, DWORD nSize); -extern DWORD WINAPI BxGetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize); -extern HMODULE WINAPI BxLoadLibraryA(LPCTSTR lpFileName); -extern LPVOID WINAPI BxVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); -extern BOOL WINAPI BxVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); -extern DWORD WINAPI BxExitProcess(DWORD); -extern DWORD WINAPI BxGetTickCount(VOID); -extern BOOL WINAPI BxVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); -extern DWORD WINAPI BxWin32SetLastError(DWORD ErrorCode); -extern DWORD WINAPI BxWin32GetLastError(VOID); -extern LPCSTR WINAPI BxWin32GetCommandLineA(VOID); -extern LPWSTR WINAPI BxWin32GetCommandLineW(VOID); -extern LPCSTR WINAPI BxWin32GetEnvironmentStringsA(VOID); -extern LPWSTR WINAPI BxWin32GetEnvironmentStringsW(VOID); -extern LPVOID WINAPI BxWin32TlsGetValue(DWORD dwTlsIndex); -extern BOOL WINAPI BxWin32TlsSetValue(DWORD dwTlsIndex,LPVOID lpTlsValue); -extern BOOL WINAPI BxWin32TlsFree(DWORD dwTlsIndex); -extern DWORD WINAPI BxWin32TlsAlloc(VOID); -extern DWORD WINAPI BxWin32FlsAlloc(VOID); -extern char * WINAPI BxStrCpyA(char *Dst, char *Src); -extern wchar16_t * WINAPI BxStrCpyW(wchar16_t *Dst, wchar16_t *Src); -extern char * WINAPI BxStrCatA(char *Dst, char *Src); -extern wchar16_t * WINAPI BxStrCatW(wchar16_t *Dst, wchar16_t *Src); - -//-------------------------------------------------------------------------- -// Installs an exception handler. Only one exception handler -// can be installed at one time. You need to uninstall one -// before reinstalling another. -// These two functions will return non-zero on success. -typedef DWORD (*PEXCEPTION_HANDLER)(PEXCEPTION_RECORD, struct _EXCEPTION_REGISTRATION_RECORD *, PCONTEXT,struct _EXCEPTION_REGISTRATION_RECORD **); - -extern DWORD WINAPI BxInstallSEH(PEXCEPTION_HANDLER Handler); -extern DWORD WINAPI BxUninstallSEH(); - -#endif diff --git a/idasdk75/dbg/common_local_impl.cpp b/idasdk75/dbg/common_local_impl.cpp deleted file mode 100644 index 7e60060..0000000 --- a/idasdk75/dbg/common_local_impl.cpp +++ /dev/null @@ -1,857 +0,0 @@ -// -// This file is included from other files, do not directly compile it. -// It contains the debugger_t structure definition and a few other helper functions -// - -#include -#include -#include - -bool plugin_inited; -bool debugger_inited; - -#define IS_GDB_DEBUGGER (DEBUGGER_ID == DEBUGGER_ID_GDB_USER || DEBUGGER_ID == DEBUGGER_ID_ARM_IPHONE_USER || DEBUGGER_ID == DEBUGGER_ID_XNU_USER) - -#if TARGET_PROCESSOR == PLFM_386 - #define REGISTERS x86_registers - #define REGISTERS_SIZE qnumber(x86_registers) - #define REGISTER_CLASSES x86_register_classes - #define REGISTER_CLASSES_DEFAULT X86_RC_GENERAL - #define READ_REGISTERS x86_read_registers - #define WRITE_REGISTER x86_write_register - #if !IS_GDB_DEBUGGER - #define is_valid_bpt is_x86_valid_bpt - #endif - #define BPT_CODE X86_BPT_CODE - #define BPT_CODE_SIZE X86_BPT_SIZE -#elif TARGET_PROCESSOR == PLFM_ARM - #define REGISTERS arm_registers - #define REGISTERS_SIZE qnumber(arm_registers) - #define REGISTER_CLASSES arm_register_classes - #define REGISTER_CLASSES_DEFAULT ARM_RC_GENERAL - #define READ_REGISTERS s_read_registers - #define WRITE_REGISTER s_write_register - #if !IS_GDB_DEBUGGER - #define is_valid_bpt is_arm_valid_bpt - #else - #define is_valid_bpt gdb_valid_bpt - #endif - #define BPT_CODE ARM_BPT_CODE - #define BPT_CODE_SIZE ARM_BPT_SIZE -#elif TARGET_PROCESSOR == PLFM_DALVIK - #define BPT_CODE { 0 } - #define BPT_CODE_SIZE 0 - #define READ_REGISTERS s_read_registers - #define WRITE_REGISTER s_write_register - #define is_valid_bpt is_dalvik_valid_bpt -#elif IS_GDB_DEBUGGER - #define REGISTERS NULL - #define REGISTERS_SIZE 0 - #define REGISTER_CLASSES NULL - #define REGISTER_CLASSES_DEFAULT 0 - #define READ_REGISTERS simple_read_registers - #define WRITE_REGISTER simple_write_register - #define is_valid_bpt gdb_valid_bpt - #define BPT_CODE { 0 } - #define BPT_CODE_SIZE 0 -#else - #error This processor is not supported yet -#endif - -static const uchar bpt_code[] = BPT_CODE; - -//-------------------------------------------------------------------------- -int idaapi is_ok_bpt(bpttype_t type, ea_t ea, int len) -{ - int ret = is_valid_bpt(type, ea, len); - if ( ret != BPT_OK ) - return ret; - else - return g_dbgmod.dbg_is_ok_bpt(type, ea, len); -} - -//-------------------------------------------------------------------------- -// For ARM, we have to set the low bit of the address to 1 for thumb mode -#if DEBUGGER_ID == DEBUGGER_ID_ARM_LINUX_USER -static drc_t idaapi arm_update_bpts( - int *nbpts, - update_bpt_info_t *bpts, - int nadd, - int ndel, - qstring *errbuf) -{ - // This function is called from debthread, but to use get_sreg() we must - // switch to the mainthread - struct ida_local arm_bptea_fixer_t : public exec_request_t - { - update_bpt_info_t *bpts; - update_bpt_info_t *e; - qvector thumb_mode; - virtual int idaapi execute(void) override - { - for ( update_bpt_info_t *b=bpts; b != e; b++ ) - { - if ( b->type == BPT_SOFT && get_sreg(b->ea, ARM_T) == 1 ) - { - b->ea++; // odd address means that thumb bpt must be set - thumb_mode.push_back(&b->ea); - } - } - return 0; - } - arm_bptea_fixer_t(update_bpt_info_t *p1, update_bpt_info_t *p2) - : bpts(p1), e(p2) {} - }; - arm_bptea_fixer_t abf(bpts, bpts+nadd); - execute_sync(abf, MFF_READ); - - drc_t drc = s_update_bpts(nbpts, bpts, nadd, ndel, errbuf); - - // reset the odd bit because the addresses are required by the caller - for ( int i=0; i < abf.thumb_mode.size(); i++ ) - (*abf.thumb_mode[i])--; - - return drc; -} -#define s_update_bpts arm_update_bpts -#endif - -//-------------------------------------------------------------------------- -static drc_t idaapi update_bpts( - int *nbpts, - update_bpt_info_t *bpts, - int nadd, - int ndel, - qstring *errbuf) -{ - bool valid_bpt_exists = false; - update_bpt_info_t *e = bpts + nadd; - for ( update_bpt_info_t *b=bpts; b != e; b++ ) - { - if ( b->code == BPT_SKIP ) - continue; - - b->code = is_valid_bpt(b->type, b->ea, b->size); - if ( b->code == BPT_OK ) - valid_bpt_exists = true; - } - - if ( !valid_bpt_exists && ndel == 0 ) - { - if ( nbpts != NULL ) - *nbpts = 0; - return DRC_OK; // none of bpts is writable - } - - drc_t drc = s_update_bpts(nbpts, bpts, nadd, ndel, errbuf); - return drc; -} - -//-------------------------------------------------------------------------- -#ifndef REMOTE_DEBUGGER -// another copy of this function (for remote debugging) is defined in dbg_rpc_handler.cpp -int send_ioctl( - void *, - int fn, - const void *buf, - size_t size, - void **poutbuf, - ssize_t *poutsize) -{ - return g_dbgmod.handle_ioctl(fn, buf, size, poutbuf, poutsize); -} -#endif - -//-------------------------------------------------------------------------- -THREAD_SAFE int debmod_t::send_debug_names_to_ida( - ea_t *addrs, - const char *const *names, - int qty) -{ - return ::send_debug_names_to_ida(addrs, names, qty); -} - -//--------------------------------------------------------------------------- -THREAD_SAFE int send_debug_names_to_ida( - ea_t *addrs, - const char *const *names, - int qty) -{ - struct debug_name_handler_t : public exec_request_t - { - ea_t *addrs; - const char *const *names; - int qty; - debug_name_handler_t(ea_t *_addrs, const char *const *_names, int _qty) - : addrs(_addrs), names(_names), qty(_qty) {} - int idaapi execute(void) override - { - set_arm_thumb_modes(addrs, qty); - return set_debug_names(addrs, names, qty); - } - }; - debug_name_handler_t dnh(addrs, names, qty); - return execute_sync(dnh, MFF_WRITE); -} - -//-------------------------------------------------------------------------- -THREAD_SAFE int debmod_t::send_debug_event_to_ida( - const debug_event_t *ev, - int rqflags) -{ - return ::send_debug_event_to_ida(ev, rqflags); -} - -//--------------------------------------------------------------------------- -THREAD_SAFE int send_debug_event_to_ida( - const debug_event_t *ev, - int rqflags) -{ - return handle_debug_event(ev, rqflags); -} - -//-------------------------------------------------------------------------- -THREAD_SAFE int import_dll(const import_request_t &req) -{ - struct dll_importer_t : public exec_request_t - { - const import_request_t &req; - dll_importer_t(const import_request_t &_req) : req(_req) {} - int idaapi execute(void) override - { - return g_dbgmod.import_dll(req) ? 0 : 1; - } - }; - dll_importer_t di(req); - return execute_sync(di, MFF_WRITE); -} - -//-------------------------------------------------------------------------- -#if TARGET_PROCESSOR != PLFM_ARM -void set_arm_thumb_modes(ea_t * /*addrs*/, int /*qty*/) -{ -} -#endif - -//-------------------------------------------------------------------------- -// installs or uninstalls debugger specific idc functions -bool add_idc_funcs(const ext_idcfunc_t efuncs[], size_t nfuncs, bool reg) -{ - if ( reg ) - { - for ( int i=0; i < nfuncs; i++ ) - if ( !add_idc_func(efuncs[i]) ) - return false; - } - else - { - for ( int i=0; i < nfuncs; i++ ) - if ( !del_idc_func(efuncs[i].name) ) - return false; - } - return true; -} - -//-------------------------------------------------------------------------- -static drc_t init_debugger( - const char *hostname, - int port_num, - const char *password, - qstring *errbuf) -{ - g_dbgmod.dbg_set_debugging((debug & IDA_DEBUG_DEBUGGER) != 0); - - if ( !s_open_remote(hostname, port_num, password, errbuf) ) - return DRC_FAILED; - - uint32_t flags2 = 0; - drc_t drc = s_init(&flags2, errbuf); - if ( drc != DRC_OK ) - { - s_close_remote(); - return drc; - } - - debugger.flags2 |= flags2; -#if defined(REMOTE_DEBUGGER) && !defined(NO_OPEN_FILE) - setflag(debugger.flags2, DBG_HAS_OPEN_FILE, true); -#endif -#ifdef HAVE_UPDATE_CALL_STACK - setflag(debugger.flags2, DBG_HAS_UPDATE_CALL_STACK, true); -#endif -#ifdef HAVE_APPCALL - setflag(debugger.flags2, DBG_HAS_APPCALL, true); -#endif -#ifdef HAVE_MAP_ADDRESS - setflag(debugger.flags2, DBG_HAS_MAP_ADDRESS, true); -#endif - debugger_inited = true; - processor_specific_init(); - register_idc_funcs(true); - init_dbg_idcfuncs(true); -#if DEBUGGER_ID == DEBUGGER_ID_X86_IA32_WIN32_USER || DEBUGGER_ID == DEBUGGER_ID_X86_IA32_BOCHS - install_x86seh_menu(); -#endif - return DRC_OK; -} - -//-------------------------------------------------------------------------- -static drc_t term_debugger(void) -{ - if ( debugger_inited ) - { - debugger_inited = false; -#if DEBUGGER_ID == DEBUGGER_ID_X86_IA32_WIN32_USER || DEBUGGER_ID == DEBUGGER_ID_X86_IA32_BOCHS - remove_x86seh_menu(); -#endif - init_dbg_idcfuncs(false); - register_idc_funcs(false); - processor_specific_term(); - g_dbgmod.dbg_term(); - return s_close_remote(); - } - return DRC_FAILED; -} - -//-------------------------------------------------------------------------- -static ssize_t idaapi idd_notify(void *, int msgid, va_list va) -{ - int retcode = DRC_NONE; - qstring *errbuf; - - switch ( msgid ) - { - case debugger_t::ev_init_debugger: - { - const char *hostname = va_arg(va, const char *); - int portnum = va_arg(va, int); - const char *password = va_arg(va, const char *); - errbuf = va_arg(va, qstring *); - QASSERT(1522, errbuf != NULL); - retcode = init_debugger(hostname, portnum, password, errbuf); - } - break; - - case debugger_t::ev_term_debugger: - retcode = term_debugger(); - break; - - case debugger_t::ev_get_processes: - { - procinfo_vec_t *procs = va_arg(va, procinfo_vec_t *); - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_get_processes(procs, errbuf); - } - break; - - case debugger_t::ev_start_process: - { - const char *path = va_arg(va, const char *); - const char *args = va_arg(va, const char *); - const char *startdir = va_arg(va, const char *); - uint32 dbg_proc_flags = va_arg(va, uint32); - const char *input_path = va_arg(va, const char *); - uint32 input_file_crc32 = va_arg(va, uint32); - errbuf = va_arg(va, qstring *); - retcode = s_start_process(path, - args, - startdir, - dbg_proc_flags, - input_path, - input_file_crc32, - errbuf); - } - break; - - case debugger_t::ev_attach_process: - { - pid_t pid = va_argi(va, pid_t); - int event_id = va_arg(va, int); - uint32 dbg_proc_flags = va_arg(va, uint32); - errbuf = va_arg(va, qstring *); - retcode = s_attach_process(pid, event_id, dbg_proc_flags, errbuf); - } - break; - - case debugger_t::ev_detach_process: - retcode = g_dbgmod.dbg_detach_process(); - break; - - case debugger_t::ev_get_debapp_attrs: - { - debapp_attrs_t *out_pattrs = va_arg(va, debapp_attrs_t *); - g_dbgmod.dbg_get_debapp_attrs(out_pattrs); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_rebase_if_required_to: - { - ea_t new_base = va_arg(va, ea_t); - rebase_if_required_to(new_base); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_request_pause: - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_prepare_to_pause_process(errbuf); - break; - - case debugger_t::ev_exit_process: - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_exit_process(errbuf); - break; - - case debugger_t::ev_get_debug_event: - { - gdecode_t *code = va_arg(va, gdecode_t *); - debug_event_t *event = va_arg(va, debug_event_t *); - int timeout_ms = va_arg(va, int); - *code = g_dbgmod.dbg_get_debug_event(event, timeout_ms); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_resume: - { - debug_event_t *event = va_arg(va, debug_event_t *); - retcode = g_dbgmod.dbg_continue_after_event(event); - } - break; - - case debugger_t::ev_set_exception_info: - { - exception_info_t *info = va_arg(va, exception_info_t *); - int qty = va_arg(va, int); - g_dbgmod.dbg_set_exception_info(info, qty); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_suspended: - { - bool dlls_added = va_argi(va, bool); - thread_name_vec_t *thr_names = va_arg(va, thread_name_vec_t *); - s_stopped_at_debug_event(thr_names, dlls_added); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_thread_suspend: - { - thid_t tid = va_argi(va, thid_t); - retcode = g_dbgmod.dbg_thread_suspend(tid); - } - break; - - case debugger_t::ev_thread_continue: - { - thid_t tid = va_argi(va, thid_t); - retcode = g_dbgmod.dbg_thread_continue(tid); - } - break; - - case debugger_t::ev_set_resume_mode: - { - thid_t tid = va_argi(va, thid_t); - resume_mode_t resmod = va_argi(va, resume_mode_t); - retcode = g_dbgmod.dbg_set_resume_mode(tid, resmod); - } - break; - - case debugger_t::ev_read_registers: - { - thid_t tid = va_argi(va, thid_t); - int clsmask = va_arg(va, int); - regval_t *values = va_arg(va, regval_t *); - errbuf = va_arg(va, qstring *); - retcode = READ_REGISTERS(tid, clsmask, values, errbuf); - } - break; - - case debugger_t::ev_write_register: - { - thid_t tid = va_argi(va, thid_t); - int regidx = va_arg(va, int); - const regval_t *value = va_arg(va, const regval_t *); - errbuf = va_arg(va, qstring *); - retcode = WRITE_REGISTER(tid, regidx, value, errbuf); - } - break; - - case debugger_t::ev_thread_get_sreg_base: - { - ea_t *answer = va_arg(va, ea_t *); - thid_t tid = va_argi(va, thid_t); - int sreg_value = va_arg(va, int); - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_thread_get_sreg_base(answer, tid, sreg_value, errbuf); - } - break; - - case debugger_t::ev_get_memory_info: - { - meminfo_vec_t *ranges = va_arg(va, meminfo_vec_t *); - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_get_memory_info(*ranges, errbuf); - } - break; - - case debugger_t::ev_read_memory: - { - size_t *nbytes = va_arg(va, size_t *); - ea_t ea = va_arg(va, ea_t); - void *buffer = va_arg(va, void *); - size_t size = va_arg(va, size_t); - errbuf = va_arg(va, qstring *); - ssize_t code = g_dbgmod.dbg_read_memory(ea, buffer, size, errbuf); - *nbytes = code >= 0 ? code : 0; - retcode = code >= 0 ? DRC_OK : DRC_NOPROC; - } - break; - - case debugger_t::ev_write_memory: - { - size_t *nbytes = va_arg(va, size_t *); - ea_t ea = va_arg(va, ea_t); - const void *buffer = va_arg(va, void *); - size_t size = va_arg(va, size_t); - errbuf = va_arg(va, qstring *); - ssize_t code = g_dbgmod.dbg_write_memory(ea, buffer, size, errbuf); - *nbytes = code >= 0 ? code : 0; - retcode = code >= 0 ? DRC_OK : DRC_NOPROC; - } - break; - - case debugger_t::ev_check_bpt: - { - int *bptvc = va_arg(va, int *); - bpttype_t type = va_argi(va, bpttype_t); - ea_t ea = va_arg(va, ea_t); - int len = va_arg(va, int); - *bptvc = is_ok_bpt(type, ea, len); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_update_bpts: - { - int *nbpts = va_arg(va, int *); - update_bpt_info_t *bpts = va_arg(va, update_bpt_info_t *); - int nadd = va_arg(va, int); - int ndel = va_arg(va, int); - errbuf = va_arg(va, qstring *); - retcode = update_bpts(nbpts, bpts, nadd, ndel, errbuf); - } - break; - - case debugger_t::ev_update_lowcnds: - { - int *nupdated = va_arg(va, int *); - const lowcnd_t *lowcnds = va_arg(va, const lowcnd_t *); - int nlowcnds = va_arg(va, int); - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_update_lowcnds(nupdated, lowcnds, nlowcnds, errbuf); - } - break; - - case debugger_t::ev_open_file: - { - const char *file = va_arg(va, const char *); - uint64 *fsize = va_arg(va, uint64 *); - bool readonly = va_argi(va, bool); - retcode = g_dbgmod.dbg_open_file(file, fsize, readonly); - } - break; - - case debugger_t::ev_close_file: - { - int fn = va_arg(va, int); - g_dbgmod.dbg_close_file(fn); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_read_file: - { - int fn = va_arg(va, int); - qoff64_t off = va_arg(va, qoff64_t); - void *buf = va_arg(va, void *); - size_t size = va_arg(va, size_t); - retcode = g_dbgmod.dbg_read_file(fn, off, buf, size); - } - break; - - case debugger_t::ev_write_file: - { - int fn = va_arg(va, int); - qoff64_t off = va_arg(va, qoff64_t); - const void *buf = va_arg(va, const void *); - size_t size = va_arg(va, size_t); - retcode = g_dbgmod.dbg_write_file(fn, off, buf, size); - } - break; - - case debugger_t::ev_map_address: - { - ea_t *mapped = va_arg(va, ea_t *); - ea_t ea = va_arg(va, ea_t); - const regval_t *regs = va_arg(va, const regval_t *); - int regnum = va_arg(va, int); - *mapped = g_dbgmod.map_address(ea, regs, regnum); - return DRC_OK; - } - break; - - #ifdef GET_DEBMOD_EXTS - case debugger_t::ev_get_debmod_extensions: - { - const void **ext = va_arg(va, const void **); - *ext = GET_DEBMOD_EXTS(); - retcode = DRC_OK; - } - break; - #endif - - #ifdef HAVE_UPDATE_CALL_STACK - case debugger_t::ev_update_call_stack: - { - thid_t tid = va_argi(va, thid_t); - call_stack_t *trace = va_arg(va, call_stack_t *); - retcode = g_dbgmod.dbg_update_call_stack(tid, trace); - } - break; - #endif - - #ifdef HAVE_APPCALL - case debugger_t::ev_appcall: - { - ea_t *blob_ea = va_arg(va, ea_t *); - ea_t func_ea = va_arg(va, ea_t); - thid_t tid = va_arg(va, thid_t); - const func_type_data_t *fti = va_arg(va, const func_type_data_t *); - int nargs = va_arg(va, int); - const regobjs_t *regargs = va_arg(va, const regobjs_t *); - relobj_t *stkargs = va_arg(va, relobj_t *); - regobjs_t *retregs = va_arg(va, regobjs_t *); - errbuf = va_arg(va, qstring *); - debug_event_t *event = va_arg(va, debug_event_t *); - int opts = va_arg(va, int); - qnotused(nargs); - *blob_ea = g_dbgmod.dbg_appcall(func_ea, tid, fti->stkargs, regargs, stkargs, retregs, errbuf, event, opts); - retcode = DRC_OK; - } - break; - - case debugger_t::ev_cleanup_appcall: - { - thid_t tid = va_argi(va, thid_t); - retcode = g_dbgmod.dbg_cleanup_appcall(tid); - } - break; - #endif - - case debugger_t::ev_eval_lowcnd: - { - thid_t tid = va_argi(va, thid_t); - ea_t ea = va_arg(va, ea_t); - errbuf = va_arg(va, qstring *); - retcode = g_dbgmod.dbg_eval_lowcnd(tid, ea, errbuf); - } - break; - - case debugger_t::ev_send_ioctl: - { - int fn = va_arg(va, int); - const void *buf = va_arg(va, const void *); - size_t size = va_arg(va, size_t); - void **poutbuf = va_arg(va, void **); - ssize_t *poutsize = va_arg(va, ssize_t *); - retcode = g_dbgmod.handle_ioctl(fn, buf, size, poutbuf, poutsize); - } - break; - - case debugger_t::ev_dbg_enable_trace: - { - thid_t tid = va_arg(va, thid_t); - bool enable = va_argi(va, bool); - int trace_flags = va_arg(va, int); - retcode = g_dbgmod.dbg_enable_trace(tid, enable, trace_flags) ? DRC_OK : DRC_NONE; - } - break; - - case debugger_t::ev_is_tracing_enabled: - { - thid_t tid = va_arg(va, thid_t); - int tracebit = va_arg(va, int); - retcode = g_dbgmod.dbg_is_tracing_enabled(tid, tracebit) ? DRC_OK : DRC_NONE; - } - break; - - case debugger_t::ev_rexec: - { - const char *cmdline = va_arg(va, const char *); - retcode = g_dbgmod.dbg_rexec(cmdline); - } - break; - - #ifdef HAVE_GET_SRCINFO_PATH - case debugger_t::ev_get_srcinfo_path: - { - qstring *path = va_arg(va, qstring *); - ea_t base = va_arg(va, ea_t); - bool ok = g_dbgmod.dbg_get_srcinfo_path(path, base); - retcode = ok ? DRC_OK : DRC_NONE; - } - break; - #endif - - case debugger_t::ev_bin_search: - { - ea_t *ea = va_arg(va, ea_t *); - ea_t start_ea = va_arg(va, ea_t); - ea_t end_ea = va_arg(va, ea_t); - const compiled_binpat_vec_t *ptns = va_arg(va, const compiled_binpat_vec_t *); - int srch_flags = va_arg(va, int); - errbuf = va_arg(va, qstring *); - if ( ptns != NULL ) - retcode = g_dbgmod.dbg_bin_search(ea, start_ea, end_ea, *ptns, srch_flags, errbuf); - } - break; - } - - return retcode; -} - -//-------------------------------------------------------------------------- -// Initialize debugger plugin -static plugmod_t *idaapi init(void) -{ - // copy of the definitions from loader.hpp - // we will delete them after improving the debuggers to use PLUGIN_MULTI. -#define PLUGIN_SKIP nullptr -#define PLUGIN_KEEP ((plugmod_t *)2) - - if ( init_plugin() ) - { - update_idd_registers(); - dbg = &debugger; - plugin_inited = true; - return PLUGIN_KEEP; - } - return PLUGIN_SKIP; -} - -//-------------------------------------------------------------------------- -// Terminate debugger plugin -static void idaapi term(void) -{ - if ( plugin_inited ) - { - term_plugin(); - plugin_inited = false; - } - // we're being unloaded, clear the 'dbg' pointer if it's ours - if ( dbg == &debugger ) - dbg = NULL; -} - -//-------------------------------------------------------------------------- -// The plugin method - usually is not used for debugger plugins -static bool idaapi run(size_t arg) -{ -#ifdef HAVE_PLUGIN_RUN - plugin_run(int(arg)); -#else - qnotused(arg); -#endif - return true; -} - -//-------------------------------------------------------------------------- -// -// DEBUGGER DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- - -#ifdef SET_DBG_OPTIONS -# define S_SET_DBG_OPTIONS s_set_dbg_options -#else -# define S_SET_DBG_OPTIONS NULL -# define SET_DBG_OPTIONS NULL -#endif - -#ifndef S_FILETYPE -# define S_FILETYPE 0 -#endif - -// arm has no single step mechanism -// DBG_HAS_SET_RESUME_MODE must be set before init_debugger -#if TARGET_PROCESSOR == PLFM_ARM -# define S_DBG_HAS_SET_RESUME_MODE 0 -#else -# define S_DBG_HAS_SET_RESUME_MODE DBG_HAS_SET_RESUME_MODE -#endif - -#ifndef DEBUGGER_RESMOD -# define DEBUGGER_RESMOD 0 -#endif - -debugger_t debugger = -{ - IDD_INTERFACE_VERSION, - DEBUGGER_NAME, - DEBUGGER_ID, - PROCESSOR_NAME, - DEBUGGER_FLAGS, // flags - DBG_HAS_ATTACH_PROCESS -| DBG_HAS_REQUEST_PAUSE -| DBG_HAS_SET_EXCEPTION_INFO -| DBG_HAS_THREAD_SUSPEND -| DBG_HAS_THREAD_CONTINUE -| S_DBG_HAS_SET_RESUME_MODE -| DBG_HAS_THREAD_GET_SREG_BASE -| DBG_HAS_CHECK_BPT -| DBG_HAS_REXEC, // flags2 - - REGISTER_CLASSES, - REGISTER_CLASSES_DEFAULT, - REGISTERS, - REGISTERS_SIZE, - - MEMORY_PAGE_SIZE, - - bpt_code, - sizeof(bpt_code), - S_FILETYPE, - DEBUGGER_RESMOD, - - S_SET_DBG_OPTIONS, - idd_notify, -}; - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_HIDE|PLUGIN_DBG, // plugin flags - init, // initialize - - term, // terminate. this pointer may be NULL. - - run, // invoke plugin - - comment, // long comment about the plugin - // it could appear in the status line - // or as a hint - - comment, // multiline help about the plugin - - wanted_name, // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/dbg/dbg_rpc_client.cpp b/idasdk75/dbg/dbg_rpc_client.cpp deleted file mode 100644 index 456de35..0000000 --- a/idasdk75/dbg/dbg_rpc_client.cpp +++ /dev/null @@ -1,246 +0,0 @@ - -// This file is included in the debugger stub that runs on the computer with IDA - -#include -#include -#include - -#include "dbg_rpc_client.h" -#include "dbg_rpc_hlp.h" -#include "debmod.h" - -//-------------------------------------------------------------------------- -// check and send to the remote server the specified stub -// do it only if its crc does not match the specified crc -// this function runs on the local machine with ida interface -static uchar *sync_stub(const char *fname, uint32 crc, size_t *psize) -{ - bool complain = true; - uchar *retval = NULL; - char path[QMAXPATH]; - if ( getsysfile(path, sizeof(path), fname, NULL) != NULL ) - { - linput_t *li = open_linput(path, false); - if ( li != NULL ) - { - int64 size = qlsize(li); - if ( size > 0 ) - { - bytevec_t buf; - buf.resize(size); - if ( qlread(li, buf.begin(), size) == size ) - { - complain = false; - if ( calc_crc32(0, buf.begin(), size) != crc ) - { - *psize = size; - retval = buf.extract(); - } - else - { - msg("Kernel debugger stub is up to date...\n"); - *psize = 1; // signal ok - } - } - } - close_linput(li); - } - } - if ( complain ) - warning("AUTOHIDE NONE\nCould not find/read debugger stub %s", fname); - return retval; -} - -//-------------------------------------------------------------------------- -dbg_rpc_client_t::dbg_rpc_client_t(idarpc_stream_t *_irs) - : dbg_rpc_engine_t(/*is_client=*/ true), - client_irs(_irs) -{ - pending_event.clear_all(); - verbose = false; - recv_timeout = RECV_TIMEOUT_PERIOD; -} - -//------------------------------------------------------------------------- -void dbg_rpc_client_t::my_update_wait_dialog( - const char *message, - const rpc_packet_t *rp) -{ - if ( send_request_data.wait_dialog_displayed ) - { - if ( rp->code != send_request_data.code ) - replace_wait_box("%s", message); - } - else - { - show_wait_box("%s", message); - send_request_data.wait_dialog_displayed = true; - } - send_request_data.code = rp->code; -} - -//-------------------------------------------------------------------------- -// requests received from the server. -// here the client handles certain server -> client requests -bytevec_t dbg_rpc_client_t::on_send_request_interrupt(const rpc_packet_t *rp) -{ - memory_deserializer_t mmdsr(rp+1, rp->length); - bytevec_t req = prepare_rpc_packet(RPC_OK); - - switch ( rp->code ) - { - // send_debug_names_to_ida() is thread safe - case RPC_SET_DEBUG_NAMES: - { - my_update_wait_dialog("Downloading Symbols", rp); - int qty = mmdsr.unpack_dd(); - ea_t *addrs = OPERATOR_NEW(ea_t, qty); - char **names = OPERATOR_NEW(char *, qty); - qstring name; - ea_t old = 0; - for ( int i=0; i < qty; i++ ) - { - adiff_t o2 = mmdsr.unpack_ea64(); - if ( mmdsr.unpack_dd() ) - o2 = -o2; - old += o2; - addrs[i] = old; - int oldlen = mmdsr.unpack_dd(); - QASSERT(1203, oldlen >= 0 && oldlen <= name.length()); - //keep the prefix - name.resize(oldlen); - if ( !mmdsr.unpack_str(&name) ) - INTERR(1294); - names[i] = qstrdup(name.c_str()); - } - int result = send_debug_names_to_ida(addrs, names, qty); - verb(("set_debug_name(qty=%d) => %d\n", qty, result)); - req.pack_dd(result); - for ( int i=0; i < qty; i++ ) - qfree(names[i]); - delete [] addrs; - delete [] names; - } - break; - - // import_dll() is thread safe - case RPC_IMPORT_DLL: - { - my_update_wait_dialog("Importing DLLs", rp); - ea_t base = mmdsr.unpack_ea64(); - const char *path = mmdsr.unpack_str(); - int n = mmdsr.unpack_dd(); - const void *bytes = mmdsr.unpack_obj_inplace(n); - bytevec_t uuid(bytes, n); - int result = import_dll(import_request_t(base, path, uuid)); - verb(("import_dll(base=%a, path=%s) => %d\n", base, path, result)); - req.pack_dd(result); - } - break; - - // send_debug_event_to_ida() is thread safe - case RPC_HANDLE_DEBUG_EVENT: - { - debug_event_t ev; - extract_debug_event(&ev, mmdsr); - int rqflags = mmdsr.unpack_dd(); - int code = send_debug_event_to_ida(&ev, rqflags); - req.pack_dd(code); - } - break; - - // sync_stub() is thread safe - case RPC_SYNC_STUB: - { - const char *fname = mmdsr.unpack_str(); - uint32 crc = mmdsr.unpack_dd(); - - // security problem: the debugger server should not be able to - // read an arbitrary file on the local computer. therefore we completely - // ignore the file name and use a hardcoded name. - qnotused(fname); - fname = "ida_kdstub.dll"; - - size_t size = 0; - uchar *contents = sync_stub(fname, crc, &size); - req.pack_dd((uint32)size); - if ( contents != NULL ) - { - req.append(contents, size); - qfree(contents); - } - } - break; - - // msg/error/warning are thread safe - case RPC_ERROR: - case RPC_MSG: - case RPC_WARNING: - { - const char *str = mmdsr.unpack_str(); - if ( *str != '\0' ) - { - if ( rp->code == RPC_MSG ) - msg("%s", str); - else if ( rp->code == RPC_ERROR ) - error("%s", str); - else - warning("%s", str); - } - } - break; - - // no external functions are called - case RPC_EVENT: - { - extract_debug_event(&pending_event, mmdsr); - has_pending_event = true; - req = prepare_rpc_packet(RPC_EVOK); - verbev(("got event, storing it and sending RPC_EVOK\n")); - } - break; - - // i doubt that this code is used on the client side - // ioctl_handler is NULL - case RPC_IOCTL: - { - int code = handle_ioctl_packet(req, mmdsr.ptr, mmdsr.end); - if ( code != RPC_OK ) - return prepare_rpc_packet((uchar)code); - } - break; - - // report_idc_error() is thread safe - case RPC_REPORT_IDC_ERROR: - { - ea_t ea = mmdsr.unpack_ea64(); - error_t code = mmdsr.unpack_dd(); - const char *errprm; - ssize_t errval; - if ( mmdsr.unpack_db() ) - { - errprm = mmdsr.unpack_str(); - errval = (ssize_t)errprm; - } - else - { - errprm = NULL; - errval = mmdsr.unpack_ea64(); - } - report_idc_error(NULL, ea, code, errval, errprm); - } - break; - - default: - return prepare_rpc_packet(RPC_UNK); - } - return req; -} - -//------------------------------------------------------------------------- -void dbg_rpc_client_t::on_send_request_end(const rpc_packet_t *) -{ - if ( send_request_data.wait_dialog_displayed ) - hide_wait_box(); - send_request_data.reset(); -} diff --git a/idasdk75/dbg/dbg_rpc_engine.cpp b/idasdk75/dbg/dbg_rpc_engine.cpp deleted file mode 100644 index 81d9daa..0000000 --- a/idasdk75/dbg/dbg_rpc_engine.cpp +++ /dev/null @@ -1,97 +0,0 @@ - -#include - -#include "dbg_rpc_engine.h" - -//------------------------------------------------------------------------- -dbg_rpc_engine_t::dbg_rpc_engine_t(bool _is_client) - : rpc_engine_t(_is_client), - has_pending_event(false), - poll_debug_events(false) -{ -} - -//-------------------------------------------------------------------------- -// sends a request and waits for a reply -// may occasionally send another request based on the reply -rpc_packet_t *dbg_rpc_engine_t::send_request_and_receive_reply(bytevec_t &req, int flags) -{ - bool displayed = false; - rpc_packet_t *result = NULL; - - while ( true ) - { - if ( displayed && user_cancelled() ) - req = prepare_rpc_packet(RPC_CANCELLED); - - if ( !req.empty() ) - { - int code = send_data(req); - if ( code != 0 || (flags & PREQ_GET_EVENT) != 0 ) - break; - - rpc_packet_t *reqp = (rpc_packet_t *)req.begin(); - if ( reqp->code == RPC_ERROR ) - qexit(1); // sent error packet, may die now - } - - rpc_packet_t *rp = recv_packet(); - if ( rp == NULL ) - break; - - switch ( rp->code ) - { - case RPC_UNK: - dwarning("rpc: remote did not understand our request"); - goto FAILURE; - case RPC_MEM: - dwarning("rpc: no remote memory"); - goto FAILURE; - case RPC_CANCELLED: - msg("rpc: user cancelled the operation\n"); - goto FAILURE; - case RPC_OK: - result = rp; - goto END; - default: - // other replies are passed to the handler - break; - } - - if ( !logged_in ) - { - lprintf("Exploit packet has been detected and ignored\n"); -FAILURE: - qfree(rp); - break; - } - //handle actual command in the request - //FIXME: use a better function name - req = on_send_request_interrupt(rp); - qfree(rp); - } - -END: - on_send_request_end(result); - - return result; -} - -//------------------------------------------------------------------------- -int dbg_rpc_engine_t::_send_request_get_int_result( - bytevec_t &req, - int failure_code, - qstring *errbuf) -{ - rpc_packet_t *rp = send_request_and_receive_reply(req); - if ( rp == NULL ) - return failure_code; - - memory_deserializer_t mmdsr(rp+1, rp->length); - int rc = mmdsr.unpack_dd(); - if ( rc < 0 && errbuf != NULL ) - *errbuf = mmdsr.unpack_str(); - - qfree(rp); - return rc; -} diff --git a/idasdk75/dbg/dbg_rpc_handler.cpp b/idasdk75/dbg/dbg_rpc_handler.cpp deleted file mode 100644 index 52a4cc5..0000000 --- a/idasdk75/dbg/dbg_rpc_handler.cpp +++ /dev/null @@ -1,1418 +0,0 @@ -#include - -#include -#include -#include -#include // otherwise cannot compile win32_remote.bpr -#include - -#include "server.h" - -//-------------------------------------------------------------------------- -// another copy of this function (for local debugging) is defined in common_local_impl.cpp -int send_ioctl( - rpc_engine_t *srv, - int fn, - const void *buf, - size_t size, - void **poutbuf, - ssize_t *poutsize) -{ - return srv->send_ioctl(fn, buf, size, poutbuf, poutsize); -} - -//-------------------------------------------------------------------------- -AS_PRINTF(3, 0) ssize_t dvmsg(int code, rpc_engine_t *rpc, const char *format, va_list va) -{ - if ( code == 0 ) - code = RPC_MSG; - else if ( code > 0 ) - code = RPC_WARNING; - else - code = RPC_ERROR; - - bytevec_t req = prepare_rpc_packet((uchar)code); - - char buf[MAXSTR]; - qvsnprintf(buf, sizeof(buf), format, va); - req.pack_str(buf); - - qfree(rpc->send_request_and_receive_reply(req)); - if ( code == RPC_ERROR ) - exit(1); - return strlen(buf); -} - -//-------------------------------------------------------------------------- -void report_idc_error(rpc_engine_t *rpc, ea_t ea, error_t code, ssize_t errval, const char *errprm) -{ - if ( code == eOS ) - { - dbg_rpc_handler_t *h = (dbg_rpc_handler_t *)rpc; - errval = h->get_debugger_instance()->get_system_specific_errno(); - } - - bytevec_t req = prepare_rpc_packet(RPC_REPORT_IDC_ERROR); - req.pack_ea64(ea); - req.pack_dd(code); - if ( (const char *)errval == errprm ) - { - req.pack_db(1); - req.pack_str(errprm); - } - else - { - req.pack_db(0); - req.pack_ea64(errval); - } - qfree(rpc->send_request_and_receive_reply(req)); -} - -//-------------------------------------------------------------------------- -debmod_t *dbg_rpc_handler_t::get_debugger_instance() -{ - return dbg_mod; //lint !e1535 !e1536 exposes lower access member -} - -//-------------------------------------------------------------------------- -void dbg_rpc_handler_t::prepare_broken_connection(void) -{ - if ( debmod_t::reuse_broken_connections ) - { - if ( !dbg_mod->dbg_prepare_broken_connection() ) - dmsg("Error preparing debugger server to handle a broken connection\n"); - } -} - -//-------------------------------------------------------------------------- -// dbg_rpc_handler_t -//-------------------------------------------------------------------------- -dbg_rpc_handler_t::dbg_rpc_handler_t( - idarpc_stream_t *_irs, - dbgsrv_dispatcher_t *_dispatcher) - : client_handler_t(_irs, /*_verbose=*/ false), - dbg_rpc_engine_t(/*is_client=*/ false), - dbg_mod(NULL), - dispatcher(_dispatcher) -{ - clear_channels(); //lint -esym(1566,dbg_rpc_handler_t::channels) not inited - struct ida_local lambda_t - { - static int ioctl(rpc_engine_t *rpc, int fn, const void *buf, size_t size, void **out, ssize_t *outsz) - { - dbg_rpc_handler_t *serv = (dbg_rpc_handler_t *) rpc; - memory_deserializer_t mmdsr(buf, size); - if ( fn >= MIN_SERVER_IOCTL ) - return serv->handle_server_ioctl(fn, out, outsz, mmdsr); - else - return serv->get_debugger_instance()->handle_ioctl(fn, buf, size, out, outsz); - } - - static progress_loop_ctrl_t recv_data_iter(bool, size_t, size_t, void *ud) - { - dbg_rpc_handler_t *eng = (dbg_rpc_handler_t *) ud; - bool performed = false; - int code = eng->on_recv_packet_progress(&performed); - if ( performed ) - return code == 0 ? plc_skip_iter : plc_cancel; - else - return plc_proceed; - } - }; - - set_ioctl_handler(lambda_t::ioctl); - irs_set_progress_cb(irs, 100, lambda_t::recv_data_iter, this); -} - -//-------------------------------------------------------------------------- -dbg_rpc_handler_t::~dbg_rpc_handler_t() -{ - //lint -e(1506) Call to virtual function 'dbg_rpc_handler_t::get_broken_connection(void)' within a constructor or destructor - if ( !get_broken_connection() ) - delete dbg_mod; // the connection is not broken, delete the debugger instance - - //lint -esym(1579,dbg_rpc_handler_t::dbg_mod) pointer member might have been freed by a separate function - clear_channels(); - - dispatcher = NULL; -} - -//------------------------------------------------------------------------ -// Function safe against time slicing attack, comparing time depends only on str length -static bool password_matches(const char *str, const char *pass) -{ - if ( str == NULL ) - return false; - int str_length = strlen(str); - int pass_length = strlen(pass); - int res = str_length ^ pass_length; - if ( pass_length != 0 ) - { - for ( int i = 0; i < str_length; i++ ) - res |= (pass[i % pass_length] ^ str[i]); - } - return res == 0; -} - -//------------------------------------------------------------------------- -bool dbg_rpc_handler_t::handle() -{ - bytevec_t req = prepare_rpc_packet(RPC_OPEN); - req.pack_dd(IDD_INTERFACE_VERSION); - req.pack_dd(DEBUGGER_ID); - req.pack_dd(sizeof(ea_t)); - - bool send_response = false; - rpc_packet_t *rp = send_request_and_receive_reply(req, PREQ_MUST_LOGIN); - bool ok = rp != NULL; - if ( ok ) - { - send_response = true; - - // Answer is after rpc_packet_t - memory_deserializer_t mmdsr(rp+1, rp->length); - ok = mmdsr.unpack_dd() != 0; - if ( !ok ) - { - lprintf("[%d] Incompatible IDA version\n", session_id); - send_response = false; - } - else if ( !dispatcher->server_password.empty() ) - { - const char *pass = mmdsr.unpack_str(); - if ( !password_matches(pass, dispatcher->server_password.c_str()) ) - { - lprintf("[%d] Bad password\n", session_id); - ok = false; - } - } - logged_in = ok; - - qfree(rp); - } - else - { - lprintf("[%d] Could not establish the connection\n", session_id); - } - - if ( send_response ) - { - req = prepare_rpc_packet(RPC_OK); - req.pack_dd(ok); - send_data(req); - - // remove reception timeout on the server side - recv_timeout = -1; - logged_in = true; - - if ( ok ) - { - // the main loop: handle client requests until it drops the connection - // or sends us RPC_OK (see rpc_debmod_t::close_remote) - bytevec_t empty; - rpc_packet_t *packet = send_request_and_receive_reply(empty); - if ( packet != NULL ) - qfree(packet); - } - } - network_error = false; - - bool preserve_server = false; - if ( get_broken_connection() ) - { - if ( dispatcher->on_broken_conn == BCH_KEEP_DEBMOD ) - { - term_irs(); - lprintf("[%d] Debugged session entered into sleeping mode\n", session_id); - prepare_broken_connection(); - preserve_server = true; - } - else - { - if ( dispatcher->on_broken_conn == BCH_KILL_PROCESS ) - { - int pid = get_debugger_instance()->pid; - if ( pid > 0 ) - { - lprintf("[%d] Killing debugged process %d\n", - session_id, get_debugger_instance()->pid); - int code = kill_process(); - if ( code != 0 ) - lprintf("[%d] Failed to kill process after %d seconds. Giving up\n", - session_id, code); - } - } - goto TERM_DEBMOD; - } - } - else - { -TERM_DEBMOD: - get_debugger_instance()->dbg_term(); - term_irs(); - } - - return !preserve_server; -} - -//-------------------------------------------------------------------------- -void dbg_rpc_handler_t::set_debugger_instance(debmod_t *instance) -{ - dbg_mod = instance; - dbg_mod->rpc = this; -} - -//-------------------------------------------------------------------------- -#ifdef VERBOSE_ENABLED -static const char *bptcode2str(uint code) -{ - static const char *const strs[] = - { - "BPT_OK", - "BPT_INTERNAL_ERR", - "BPT_BAD_TYPE", - "BPT_BAD_ALIGN", - "BPT_BAD_ADDR", - "BPT_BAD_LEN", - "BPT_TOO_MANY", - "BPT_READ_ERROR", - "BPT_WRITE_ERROR", - "BPT_SKIP", - "BPT_PAGE_OK", - }; - if ( code >= qnumber(strs) ) - return "?"; - return strs[code]; -} -#endif - -//-------------------------------------------------------------------------- -int dbg_rpc_handler_t::rpc_update_bpts(bytevec_t &req, memory_deserializer_t &mmdsr) -{ - update_bpt_vec_t bpts; - int nadd = mmdsr.unpack_dd(); - int ndel = mmdsr.unpack_dd(); - - if ( nadd < 0 || ndel < 0 || INT_MAX - ndel < nadd ) - { - req.pack_dd(0); - verb(("update_bpts(nadd=%d, ndel=%d) => 0 (incorrect values)\n", nadd, ndel)); - return 0; - } - - bpts.resize(nadd+ndel); - ea_t ea = 0; - update_bpt_vec_t::iterator b; - update_bpt_vec_t::iterator bend = bpts.begin() + nadd; - for ( b=bpts.begin(); b != bend; ++b ) - { - b->code = BPT_OK; - b->ea = ea + mmdsr.unpack_ea64(); ea = b->ea; - b->size = mmdsr.unpack_dd(); - b->type = mmdsr.unpack_dd(); - b->pid = mmdsr.unpack_dd(); - b->tid = mmdsr.unpack_dd(); - } - - ea = 0; - bend += ndel; - for ( ; b != bend; ++b ) - { - b->ea = ea + mmdsr.unpack_ea64(); ea = b->ea; - uchar len = mmdsr.unpack_db(); - if ( len > 0 ) - { - b->orgbytes.resize(len); - mmdsr.unpack_obj(b->orgbytes.begin(), len); - } - b->type = mmdsr.unpack_dd(); - b->pid = mmdsr.unpack_dd(); - b->tid = mmdsr.unpack_dd(); - } - -#ifdef VERBOSE_ENABLED - for ( b=bpts.begin()+nadd; b != bend; ++b ) - verb(("del_bpt(ea=%a, type=%d orgbytes.size=%" FMT_Z " size=%d)\n", - b->ea, b->type, b->orgbytes.size(), b->type != BPT_SOFT ? b->size : 0)); -#endif - - int nbpts; - qstring errbuf; - drc_t drc = dbg_mod->dbg_update_bpts(&nbpts, bpts.begin(), nadd, ndel, &errbuf); - - bend = bpts.begin() + nadd; -#ifdef VERBOSE_ENABLED - for ( b=bpts.begin(); b != bend; ++b ) - verb(("add_bpt(ea=%a type=%d len=%d) => %s\n", b->ea, b->type, b->size, bptcode2str(b->code))); -#endif - - req.pack_dd(drc); - req.pack_dd(nbpts); - for ( b=bpts.begin(); b != bend; ++b ) - { - req.pack_db(b->code); - if ( b->code == BPT_OK && b->type == BPT_SOFT ) - { - req.pack_db(b->orgbytes.size()); - req.append(b->orgbytes.begin(), b->orgbytes.size()); - } - } - - bend += ndel; - for ( ; b != bend; ++b ) - { - req.pack_db(b->code); - verb(("del_bpt(ea=%a) => %s\n", b->ea, bptcode2str(b->code))); - } - - if ( drc != DRC_OK ) - req.pack_str(errbuf); - return drc; -} - -//-------------------------------------------------------------------------- -void dbg_rpc_handler_t::rpc_update_lowcnds( - bytevec_t &req, - memory_deserializer_t &mmdsr) -{ - ea_t ea = 0; - lowcnd_vec_t lowcnds; - int nlowcnds = mmdsr.unpack_dd(); - lowcnds.resize(nlowcnds); - lowcnd_t *lc = lowcnds.begin(); - for ( int i=0; i < nlowcnds; i++, lc++ ) - { - lc->compiled = false; - lc->ea = ea + mmdsr.unpack_ea64(); ea = lc->ea; - lc->cndbody = mmdsr.unpack_str(); - if ( !lc->cndbody.empty() ) - { - lc->size = 0; - lc->type = mmdsr.unpack_dd(); - if ( lc->type != BPT_SOFT ) - lc->size = mmdsr.unpack_dd(); - int norg = mmdsr.unpack_db(); - if ( norg > 0 ) - { - lc->orgbytes.resize(norg); - mmdsr.unpack_obj(lc->orgbytes.begin(), norg); - } - lc->cmd.ea = mmdsr.unpack_ea64(); - if ( lc->cmd.ea != BADADDR ) - mmdsr.unpack_obj(&lc->cmd, sizeof(lc->cmd)); - } - verb(("update_lowcnd(ea=%a cnd=%s)\n", ea, lc->cndbody.c_str())); - } - int nupdated; - qstring errbuf; - drc_t drc = dbg_mod->dbg_update_lowcnds(&nupdated, lowcnds.begin(), nlowcnds, &errbuf); - verb((" update_lowcnds => %d\n", drc)); - - req.pack_dd(drc); - req.pack_dd(nupdated); - if ( drc != DRC_OK ) - req.pack_str(errbuf); -} - -//-------------------------------------------------------------------------- -bool dbg_rpc_handler_t::check_broken_connection(pid_t pid) -{ - bool result = false; - dispatcher->clients_list->lock(); - client_handlers_list_t::storage_t::iterator p; - for ( p = dispatcher->clients_list->storage.begin(); - p != dispatcher->clients_list->storage.end(); - ++p ) - { - dbg_rpc_handler_t *h = (dbg_rpc_handler_t *) p->first; - if ( h == this ) - continue; - - debmod_t *d = h->get_debugger_instance(); - if ( d->broken_connection && d->pid == pid && d->dbg_continue_broken_connection(pid) ) - { - dbg_mod->dbg_term(); - delete dbg_mod; - dbg_mod = d; - result = true; - verb(("reusing previously broken debugging session\n")); - -#ifndef __SINGLE_THREADED_SERVER__ - qthread_t thr = p->second; - - // free thread - if ( thr != NULL ) - qthread_free(thr); -#endif - - h->term_irs(); - dispatcher->clients_list->storage.erase(p); - delete h; - - d->broken_connection = false; - break; - } - } - dispatcher->clients_list->unlock(); - return result; -} - -//------------------------------------------------------------------------- -int dbg_rpc_handler_t::handle_server_ioctl( - int fn, - void **out, - ssize_t *outsz, - memory_deserializer_t &mmdsr) -{ - int code = -1; - verb(("handle_server_ioctl(fn=%d, bufsize=%" FMT_Z ").\n", fn, mmdsr.size())); - return code; -} - -//------------------------------------------------------------------------- -int dbg_rpc_handler_t::on_recv_packet_progress(bool *performed) -{ - *performed = poll_debug_events; - return poll_debug_events ? poll_events(TIMEOUT) : 0; -} - -//-------------------------------------------------------------------------- -drc_t dbg_rpc_handler_t::rpc_attach_process( - qstring *errbuf, - memory_deserializer_t &mmdsr) -{ - pid_t pid = mmdsr.unpack_dd(); - int event_id = mmdsr.unpack_dd(); - int flags = mmdsr.unpack_dd(); - drc_t drc = check_broken_connection(pid) - ? DRC_OK - : dbg_mod->dbg_attach_process(pid, event_id, flags, errbuf); - verb(("attach_process(pid=%d, evid=%d) => %d\n", pid, event_id, drc)); - return drc; -} - -//------------------------------------------------------------------------- -void dbg_rpc_handler_t::append_start_or_attach(bytevec_t &req, drc_t drc, const qstring &errbuf) const -{ - req.pack_dd(drc); - if ( drc > DRC_NONE ) - { - debapp_attrs_t attrs; - dbg_mod->dbg_get_debapp_attrs(&attrs); - append_debapp_attrs(req, attrs); - append_dynamic_register_set(req, dbg_mod->idaregs); - } - else - { - req.pack_str(errbuf); - } -} - -//------------------------------------------------------------------------- -void dbg_rpc_handler_t::shutdown_gracefully(int /*signum*/) -{ - debmod_t *d = get_debugger_instance(); - if ( d != NULL ) - d->dbg_exit_process(NULL); // kill the process instead of letting it run in wild -} - -//-------------------------------------------------------------------------- -// performs requests on behalf of a remote client -// client -> server -#ifdef __UNIX__ -# define PERM_0755 (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) -# define IS_SUBPATH strneq -#else -# define PERM_0755 0755 -# define IS_SUBPATH strnieq -#endif -bytevec_t dbg_rpc_handler_t::on_send_request_interrupt(const rpc_packet_t *rp) -{ - // While the server is performing a request, it should not poll - // for debugger events - bool saved_poll_mode = poll_debug_events; - poll_debug_events = false; - - memory_deserializer_t mmdsr(rp+1, rp->length); - bytevec_t req = prepare_rpc_packet(RPC_OK); -#if defined(__EXCEPTIONS) || defined(__NT__) - try -#endif - { - switch ( rp->code ) - { - case RPC_INIT: - { - dbg_mod->debugger_flags = mmdsr.unpack_dd(); - bool debug_debugger = mmdsr.unpack_dd() != 0; - if ( debug_debugger ) - verbose = true; - - dbg_mod->dbg_set_debugging(debug_debugger); - qstring errbuf; - uint32_t flags2 = 0; - drc_t drc = dbg_mod->dbg_init(&flags2, &errbuf); - verb(("init(debug_debugger=%d) => %d (flags2=%d)\n", debug_debugger, drc, flags2)); - req.pack_dd(drc); - req.pack_dd(flags2); - if ( drc != DRC_OK ) - req.pack_str(errbuf); - } - break; - - case RPC_TERM: - // Do not dbg_term() here, as it will be called - // at the end of server.cpp's handle_single_session(), - // right after this. - // dbg_mod->dbg_term(); - // verb(("term()\n")); - break; - - case RPC_GET_PROCESSES: - { - procinfo_vec_t procs; - qstring errbuf; - drc_t drc = dbg_mod->dbg_get_processes(&procs, &errbuf); - req.pack_dd(drc); - if ( drc == DRC_OK ) - append_process_info_vec(req, &procs); - else - req.pack_str(errbuf); - verb(("get_processes() => %d\n", drc)); - } - break; - - case RPC_DETACH_PROCESS: - { - drc_t drc = dbg_mod->dbg_detach_process(); - req.pack_dd(drc); - verb(("detach_process() => %d\n", drc)); - } - break; - - case RPC_START_PROCESS: - { - const char *path = mmdsr.unpack_str(); - const char *args = mmdsr.unpack_str(); - const char *sdir = mmdsr.unpack_str(); - int flags = mmdsr.unpack_dd(); - const char *input = mmdsr.unpack_str(); - uint32 crc32 = mmdsr.unpack_dd(); - qstring errbuf; - drc_t drc = DRC_NOFILE; - if ( path != NULL && sdir != NULL && input != NULL ) // protect against malicious ida - { - drc = dbg_mod->dbg_start_process(path, args, sdir, flags, input, crc32, &errbuf); - verb(("start_process(path=%s args=%s flags=%s%s%s\n" - " sdir=%s\n" - " input=%s crc32=%x) => %d\n", - path, args, - flags & DBG_PROC_IS_DLL ? " is_dll" : "", - flags & DBG_PROC_IS_GUI ? " under_gui" : "", - flags & DBG_HIDE_WINDOW ? " hide_window" : "", - sdir, - input, crc32, - drc)); - } - append_start_or_attach(req, drc, errbuf); - } - break; - - case RPC_GET_DEBUG_EVENT: - { - int timeout_ms = mmdsr.unpack_dd(); - gdecode_t result = GDE_NO_EVENT; - if ( !has_pending_event ) - result = dbg_mod->dbg_get_debug_event(&ev, timeout_ms); - req.pack_dd(result); - if ( result >= GDE_ONE_EVENT ) - { - append_debug_event(req, &ev); - verb(("got event: %s\n", debug_event_str(&ev))); - } - else if ( !has_pending_event ) - { - saved_poll_mode = true; - } - verbev(("get_debug_event(timeout=%d) => %d (has_pending=%d, willpoll=%d)\n", timeout_ms, result, has_pending_event, saved_poll_mode)); - } - break; - - case RPC_ATTACH_PROCESS: - { - qstring errbuf; - append_start_or_attach(req, rpc_attach_process(&errbuf, mmdsr), errbuf); - } - break; - - case RPC_PREPARE_TO_PAUSE_PROCESS: - { - qstring errbuf; - drc_t drc = dbg_mod->dbg_prepare_to_pause_process(&errbuf); - verb(("prepare_to_pause_process() => %d\n", drc)); - req.pack_dd(drc); - if ( drc < DRC_NONE ) - req.pack_str(errbuf); - } - break; - - case RPC_EXIT_PROCESS: - { - qstring errbuf; - drc_t drc = dbg_mod->dbg_exit_process(&errbuf); - verb(("exit_process() => %d\n", drc)); - req.pack_dd(drc); - if ( drc < DRC_NONE ) - req.pack_str(errbuf); - } - break; - - case RPC_CONTINUE_AFTER_EVENT: - { - extract_debug_event(&ev, mmdsr); - drc_t drc = dbg_mod->dbg_continue_after_event(&ev); - verb(("continue_after_event(...) => %d\n", drc)); - req.pack_dd(drc); - } - break; - - case RPC_STOPPED_AT_DEBUG_EVENT: - { - bool dlls_added = mmdsr.unpack_db() != 0; - bool ask_thr_names = mmdsr.unpack_db() != 0; - import_infos_t infos; - thread_name_vec_t thr_names; - dbg_mod->dbg_stopped_at_debug_event(&infos, dlls_added, ask_thr_names ? &thr_names : NULL); - process_import_requests(infos); - name_info_t *ni = dbg_mod->get_debug_names(); - int err = RPC_OK; - if ( ni != NULL ) - { - err = send_debug_names_to_ida(ni->addrs.begin(), ni->names.begin(), (int)ni->addrs.size()); - dbg_mod->clear_debug_names(); - } - if ( ask_thr_names ) - { - uint32 n = thr_names.size(); - req.pack_dd(n); - for ( int i=0; i < n; ++i ) - { - thread_name_t &tn = thr_names[i]; - req.pack_dd(tn.tid); - req.pack_str(tn.name); - } - } - } - break; - - case RPC_TH_SUSPEND: - { - thid_t tid = mmdsr.unpack_dd(); - drc_t drc = dbg_mod->dbg_thread_suspend(tid); - verb(("thread_suspend(tid=%d) => %d\n", tid, drc)); - req.pack_dd(drc); - } - break; - - case RPC_TH_CONTINUE: - { - thid_t tid = mmdsr.unpack_dd(); - drc_t drc = dbg_mod->dbg_thread_continue(tid); - verb(("thread_continue(tid=%d) => %d\n", tid, drc)); - req.pack_dd(drc); - } - break; - - case RPC_SET_RESUME_MODE: - { - thid_t tid = mmdsr.unpack_dd(); - resume_mode_t resmod = resume_mode_t(mmdsr.unpack_dd()); - drc_t drc = dbg_mod->dbg_set_resume_mode(tid, resmod); - verb(("set_resume_mode(tid=%d, resmod=%d) => %d\n", tid, resmod, drc)); - req.pack_dd(drc); - } - break; - - case RPC_READ_REGS: - { - drc_t drc = DRC_NONE; - qstring errbuf; - bytevec_t regmap; - regvals_t values; - thid_t tid = mmdsr.unpack_dd(); - int clsmask = mmdsr.unpack_dd(); - int nregs = mmdsr.unpack_dd(); - if ( nregs <= 0 || nregs > dbg_mod->nregs ) - { - errbuf.sprnt("read_regs(tid=%d, mask=%x, nregs=%d) => 0 " - "(incorrect nregs, should be in range 0..%d)\n", - tid, clsmask, nregs, dbg_mod->nregs); - } - else - { - regmap.resize((nregs+7)/8); - mmdsr.unpack_obj(regmap.begin(), regmap.size()); - values.resize(dbg_mod->nregs); - drc = dbg_mod->dbg_read_registers(tid, clsmask, values.begin(), &errbuf); - verb(("read_regs(tid=%d, mask=%x) => %d\n", tid, clsmask, drc)); - } - req.pack_dd(drc); - if ( drc == DRC_OK ) - append_regvals(req, values.begin(), nregs, regmap.begin()); - else - req.pack_str(errbuf); - } - break; - - case RPC_WRITE_REG: - { - thid_t tid = mmdsr.unpack_dd(); - int reg_idx = mmdsr.unpack_dd(); - regval_t value; - unpack_regvals(&value, 1, NULL, mmdsr); - qstring errbuf; - drc_t drc = dbg_mod->dbg_write_register(tid, reg_idx, &value, &errbuf); - verb(("write_reg(tid=%d) => %d\n", tid, drc)); - req.pack_dd(drc); - if ( drc < DRC_NONE ) - req.pack_str(errbuf); - } - break; - - case RPC_GET_SREG_BASE: - { - thid_t tid = mmdsr.unpack_dd(); - int sreg_value = mmdsr.unpack_dd(); - ea_t ea; - qstring errbuf; - drc_t drc = dbg_mod->dbg_thread_get_sreg_base(&ea, tid, sreg_value, &errbuf); - verb(("get_thread_sreg_base(tid=%d, %d) => %a\n", tid, sreg_value, drc == DRC_OK ? ea : BADADDR)); - req.pack_dd(drc); - if ( drc == DRC_OK ) - req.pack_ea64(ea); - else - req.pack_str(errbuf); - } - break; - - case RPC_SET_EXCEPTION_INFO: - { - int qty = mmdsr.unpack_dd(); - exception_info_t *extable = extract_exception_info(qty, mmdsr); - dbg_mod->dbg_set_exception_info(extable, qty); - delete [] extable; - verb(("set_exception_info(qty=%d)\n", qty)); - } - break; - - case RPC_GET_MEMORY_INFO: - { - meminfo_vec_t areas; - qstring errbuf; - drc_t drc = dbg_mod->dbg_get_memory_info(areas, &errbuf); - int qty = areas.size(); - verb(("get_memory_info() => %d (qty=%d)\n", drc, qty)); - req.pack_dd(drc + (-DRC_IDBSEG)); - if ( drc == DRC_OK ) - { - req.pack_dd(qty); - for ( int i=0; i < qty; i++ ) - append_memory_info(req, &areas[i]); - } - else - { - req.pack_str(errbuf); - } - } - break; - - case RPC_GET_SCATTERED_IMAGE: - { - ea_t base = mmdsr.unpack_ea64(); - scattered_image_t si; - int result = dbg_mod->dbg_get_scattered_image(si, base); - int qty = si.size(); - verb(("get_scattered_image(base=%a) => %d (qty=%d)\n", base, result, qty)); - req.pack_dd(result+2); - if ( result > 0 ) - { - req.pack_dd(qty); - for ( int i=0; i < qty; i++ ) - append_scattered_segm(req, &si[i]); - } - } - break; - - case RPC_GET_IMAGE_UUID: - { - ea_t base = mmdsr.unpack_ea64(); - bytevec_t uuid; - bool result = dbg_mod->dbg_get_image_uuid(&uuid, base); - int size = uuid.size(); - verb(("get_image_uuid(base=%a) => %d (size=%d)\n", base, result, size)); - req.pack_dd(result); - if ( result ) - req.pack_buf(uuid.begin(), size); - } - break; - - case RPC_GET_SEGM_START: - { - ea_t base = mmdsr.unpack_ea64(); - const char *segname = mmdsr.unpack_str(); - ea_t result = dbg_mod->dbg_get_segm_start(base, segname); - verb(("get_segm_start(base=%a, segname=%s) => %a\n", base, segname, result)); - req.pack_ea64(result); - } - break; - - case RPC_READ_MEMORY: - { - ea_t ea = mmdsr.unpack_ea64(); - size_t size = mmdsr.unpack_dd(); - uchar *buf = new uchar[size]; - qstring errbuf; - ssize_t result = dbg_mod->dbg_read_memory(ea, buf, size, &errbuf); - verb(("read_memory(ea=%a size=%" FMT_Z ") => %" FMT_ZS, ea, size, result)); - if ( result > 0 && size == 1 ) - verb((" (0x%02X)\n", *buf)); - else - verb(("\n")); - req.pack_dd(uint32(result)); - if ( result > 0 ) - req.append(buf, result); - else - req.pack_str(errbuf); - delete[] buf; - } - break; - - case RPC_WRITE_MEMORY: - { - ea_t ea = mmdsr.unpack_ea64(); - size_t size = mmdsr.unpack_dd(); - uchar *buf = new uchar[size]; - mmdsr.unpack_obj(buf, size); - qstring errbuf; - ssize_t result = dbg_mod->dbg_write_memory(ea, buf, size, &errbuf); - verb(("write_memory(ea=%a size=%" FMT_Z ") => %" FMT_ZS, ea, size, result)); - if ( result && size == 1 ) - verb((" (0x%02X)\n", *buf)); - else - verb(("\n")); - req.pack_dd(uint32(result)); - if ( result <= 0 ) - req.pack_str(errbuf); - delete[] buf; - } - break; - - case RPC_ISOK_BPT: - { - bpttype_t type = mmdsr.unpack_dd(); - ea_t ea = mmdsr.unpack_ea64(); - int len = mmdsr.unpack_dd() - 1; - int result = dbg_mod->dbg_is_ok_bpt(type, ea, len); - verb(("isok_bpt(type=%d ea=%a len=%d) => %d\n", type, ea, len, result)); - req.pack_dd(result); - } - break; - - case RPC_UPDATE_BPTS: - { - int ret = rpc_update_bpts(req, mmdsr); - if ( ret == 0 ) - verb(("rpc_update_bpts failed!\n")); - } - break; - - case RPC_UPDATE_LOWCNDS: - rpc_update_lowcnds(req, mmdsr); - break; - - case RPC_EVAL_LOWCND: - { - thid_t tid = mmdsr.unpack_dd(); - ea_t ea = mmdsr.unpack_ea64(); - qstring errbuf; - drc_t drc = dbg_mod->dbg_eval_lowcnd(tid, ea, &errbuf); - req.pack_dd(drc); - if ( drc != DRC_OK ) - req.pack_str(errbuf); - verb(("eval_lowcnd(tid=%d, ea=%a) => %d\n", tid, ea, drc)); - } - break; - - case RPC_OPEN_FILE: - { - const char *path = mmdsr.unpack_str(); - bool readonly = mmdsr.unpack_dd() != 0; - int64 fsize = 0; - int fn = find_free_channel(); - if ( fn != -1 ) - { - if ( readonly ) - { - channels[fn] = fopenRB(path); - } - else - { - char dir[QMAXPATH]; - if ( qdirname(dir, sizeof(dir), path) && !qisdir(dir) ) - { - char absdir[QMAXPATH]; - qmake_full_path(absdir, sizeof(absdir), dir); - char cwd[QMAXPATH]; - qgetcwd(cwd, sizeof(cwd)); - if ( IS_SUBPATH(absdir, cwd, qstrlen(cwd)) ) - { - qstrvec_t subpaths; - while ( !qisdir(absdir) ) - { - subpaths.insert(subpaths.begin(), absdir); - if ( !qdirname(absdir, sizeof(absdir), absdir) ) - break; - } - for ( size_t i = 0, n = subpaths.size(); i < n; ++i ) - { - const char *subdir = subpaths[i].c_str(); - verb(("open_file() creating directory %s\n", subdir)); - if ( qmkdir(subdir, PERM_0755) != 0 ) - break; - } - } - } - channels[fn] = fopenWB(path); - } - if ( channels[fn] == NULL ) - fn = -1; - else if ( readonly ) - fsize = qfsize(channels[fn]); - } - verb(("open_file('%s', %d) => %d %" FMT_64 "d\n", path, readonly, fn, fsize)); - req.pack_dd(fn); - if ( fn != -1 ) - req.pack_dq(fsize); - else - req.pack_dd(qerrcode()); - } - break; - - case RPC_CLOSE_FILE: - { - int fn = mmdsr.unpack_dd(); - if ( fn >= 0 && fn < qnumber(channels) ) - { - FILE *fp = channels[fn]; - if ( fp != NULL ) - { -#ifdef __UNIX__ - fchmod(fileno(fp), PERM_0755); // set mode 0755 for unix applications -#endif - qfclose(fp); - channels[fn] = NULL; - } - } - verb(("close_file(%d)\n", fn)); - } - break; - - case RPC_READ_FILE: - { - char *buf = NULL; - int fn = mmdsr.unpack_dd(); - int64 off = mmdsr.unpack_dq(); - int32 size = mmdsr.unpack_dd(); - int32 s2 = 0; - if ( size > 0 ) - { - buf = new char[size]; - qfseek(channels[fn], off, SEEK_SET); - s2 = qfread(channels[fn], buf, size); - } - req.pack_dd(s2); - if ( size != s2 ) - req.pack_dd(qerrcode()); - else - req.append(buf, s2); - delete[] buf; - verb(("read_file(%d, 0x%" FMT_64 "X, %d) => %d\n", fn, off, size, s2)); - } - break; - - case RPC_WRITE_FILE: - { - char *buf = NULL; - int fn = mmdsr.unpack_dd(); - uint64 off = mmdsr.unpack_dq(); - uint32 size = mmdsr.unpack_dd(); - if ( size > 0 ) - { - buf = new char[size]; - mmdsr.unpack_obj(buf, size); - } - qfseek(channels[fn], off, SEEK_SET); - uint32 s2 = buf == NULL ? 0 : qfwrite(channels[fn], buf, size); - req.pack_dd(size); - if ( size != s2 ) - req.pack_dd(qerrcode()); - delete [] buf; - verb(("write_file(%d, 0x%" FMT_64 "X, %u) => %u\n", fn, off, size, s2)); - } - break; - - case RPC_EVOK: - req.clear(); - verbev(("got evok!\n")); - break; - - case RPC_IOCTL: - { - int code = handle_ioctl_packet(req, mmdsr.ptr, mmdsr.end); - if ( code != RPC_OK ) - req = prepare_rpc_packet((uchar)code); - } - break; - - case RPC_UPDATE_CALL_STACK: - { - call_stack_t trace; - thid_t tid = mmdsr.unpack_dd(); - drc_t drc = dbg_mod->dbg_update_call_stack(tid, &trace); - req.pack_dd(drc); - if ( drc == DRC_OK ) - append_call_stack(req, trace); - } - break; - - case RPC_APPCALL: - { - ea_t func_ea = mmdsr.unpack_ea64(); - thid_t tid = mmdsr.unpack_dd(); - int stkarg_nbytes = mmdsr.unpack_dd(); - int flags = mmdsr.unpack_dd(); - - regobjs_t regargs, retregs; - relobj_t stkargs; - regobjs_t *rr = (flags & APPCALL_MANUAL) == 0 ? &retregs : NULL; - extract_appcall(®args, &stkargs, rr, mmdsr); - - qstring errbuf; - debug_event_t event; - ea_t sp = dbg_mod->dbg_appcall(func_ea, tid, stkarg_nbytes, ®args, &stkargs, - &retregs, &errbuf, &event, flags); - req.pack_ea64(sp); - if ( sp == BADADDR ) - { - if ( (flags & APPCALL_DEBEV) != 0 ) - append_debug_event(req, &event); - req.pack_str(errbuf); - } - else if ( (flags & APPCALL_MANUAL) == 0 ) - { - append_regobjs(req, retregs, true); - } - } - break; - - case RPC_CLEANUP_APPCALL: - { - thid_t tid = mmdsr.unpack_dd(); - drc_t drc = dbg_mod->dbg_cleanup_appcall(tid); - req.pack_dd(drc); - } - break; - - case RPC_REXEC: - { - const char *cmdline = mmdsr.unpack_str(); - int code = dbg_mod->dbg_rexec(cmdline); - req.pack_dd(code); - } - break; - - case RPC_BIN_SEARCH: - { - ea_t start_ea = mmdsr.unpack_ea64(); - ea_t end_ea = mmdsr.unpack_ea64(); - int cnt = mmdsr.unpack_dd(); - compiled_binpat_vec_t ptns; - ptns.resize(cnt); - for ( int i=0; i < cnt; ++i ) - { - compiled_binpat_t &p = ptns[i]; - // bytes - int sz = mmdsr.unpack_dd(); - if ( sz != 0 ) - { - p.bytes.resize(sz); - mmdsr.unpack_obj(p.bytes.begin(), sz); - } - // mask - sz = mmdsr.unpack_dd(); - if ( sz != 0 ) - { - p.mask.resize(sz); - mmdsr.unpack_obj(p.mask.begin(), sz); - } - // strlits - sz = mmdsr.unpack_dd(); - p.strlits.resize(sz); - for ( int j=0; j < sz; ++j ) - { - p.strlits[j].start_ea = mmdsr.unpack_ea64(); - p.strlits[j].end_ea = mmdsr.unpack_ea64(); - } - // encidx - p.encidx = mmdsr.unpack_dd(); - } - int srch_flags = mmdsr.unpack_dd(); - ea_t srch_ea; - qstring errbuf; - drc_t drc = dbg_mod->dbg_bin_search(&srch_ea, start_ea, end_ea, ptns, srch_flags, &errbuf); - req.pack_dd(drc); - if ( drc == DRC_OK ) - req.pack_ea64(srch_ea); - else if ( drc != DRC_FAILED ) // DRC_FAILED means not found - req.pack_str(errbuf); - } - break; - - default: - req = prepare_rpc_packet(RPC_UNK); - break; - } - } -#if defined(__EXCEPTIONS) || defined(__NT__) - catch ( const std::bad_alloc & ) - { - req = prepare_rpc_packet(RPC_MEM); - } -#endif - - if ( saved_poll_mode ) - poll_debug_events = true; - return req; -} - -//-------------------------------------------------------------------------- -// poll for events from the debugger module -int dbg_rpc_handler_t::poll_events(int timeout_ms) -{ - int code = 0; - if ( !has_pending_event ) - { - // immediately set poll_debug_events to false to avoid recursive calls. - poll_debug_events = false; - has_pending_event = dbg_mod->dbg_get_debug_event(&pending_event, timeout_ms) >= GDE_ONE_EVENT; - if ( has_pending_event ) - { - verbev(("got event, sending it, poll will be 0 now\n")); - bytevec_t req = prepare_rpc_packet(RPC_EVENT); - append_debug_event(req, &pending_event); - code = send_data(req); - has_pending_event = false; - } - else - { // no event, continue to poll - poll_debug_events = true; - } - } - return code; -} - -//-------------------------------------------------------------------------- -// this function runs on the server side -// a dbg_rpc_client sends an RPC_SYNC request and the server must give the stub to the client -bool dbg_rpc_handler_t::rpc_sync_stub(const char *server_stub_name, const char *ida_stub_name) -{ - bool ok = false; - int32 crc32 = -1; - linput_t *li = open_linput(server_stub_name, false); - if ( li != NULL ) - { - crc32 = calc_file_crc32(li); - close_linput(li); - } - - bytevec_t stub = prepare_rpc_packet(RPC_SYNC_STUB); - stub.pack_str(ida_stub_name); - stub.pack_dd(crc32); - rpc_packet_t *rp = send_request_and_receive_reply(stub); - - if ( rp == NULL ) - return ok; - - const uchar *answer = (uchar *)(rp+1); - const uchar *end = answer + rp->length; - size_t size = unpack_dd(&answer, end); - if ( size == 1 ) - { - ok = true; - } - else if ( size != 0 ) - { - FILE *fp = fopenWB(server_stub_name); - if ( fp != NULL ) - { - ok = qfwrite(fp, answer, size) == size; - dmsg("Updated kernel debugger stub: %s\n", ok ? "success" : "failed"); - qfclose(fp); - } - else - { - dwarning("Could not update the kernel debugger stub.\n%s", qerrstr()); - } - } - qfree(rp); - - return ok; -} - -//-------------------------------------------------------------------------- -//lint -e{818} 'addrs' could be declared as pointing to const -int dbg_rpc_handler_t::send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty) -{ - if ( qty == 0 ) - return RPC_OK; - - bytevec_t buf; - - const size_t SZPACKET = 1300; // try not to go over the usual network MSS - // (this number is slightly less that 1460 because - // we stop the loop going over this number) - while ( qty > 0 ) - { - buf.qclear(); - - ea_t old = 0; - const char *optr = ""; - - // Start appending names and EAs - int i = 0; - while ( i < qty ) - { - adiff_t diff = *addrs - old; - bool neg = diff < 0; - if ( neg ) - diff = -diff; - - buf.pack_ea64(diff); // send address deltas - buf.pack_dd(neg); - - old = *addrs; - const char *nptr = *names; - int len = 0; - - // do not send repeating prefixes of names - while ( nptr[len] != '\0' && nptr[len] == optr[len] ) //lint !e690 wrong access - len++; - - buf.pack_dd(len); - buf.pack_str(nptr+len); - optr = nptr; - addrs++; - names++; - i++; - - if ( buf.size() > SZPACKET ) - break; - } - qty -= i; - - bytevec_t req = prepare_rpc_packet(RPC_SET_DEBUG_NAMES); - req.pack_dd(i); - req.append(buf.begin(), buf.size()); - - // should return a qty as much as sent...if not probably network error! - if ( i != send_request_get_long_result(req) ) - return RPC_UNK; - } - - return RPC_OK; -} - -//-------------------------------------------------------------------------- -int dbg_rpc_handler_t::send_debug_event_to_ida(const debug_event_t *debev, int rqflags) -{ - bytevec_t req = prepare_rpc_packet(RPC_HANDLE_DEBUG_EVENT); - append_debug_event(req, debev); - req.pack_dd(rqflags); - return send_request_get_long_result(req); -} - -//-------------------------------------------------------------------------- -void dbg_rpc_handler_t::process_import_requests(const import_infos_t &infos) -{ - // in an effort to avoid sending large amounts of symbol data over the network, - // we attempt to import symbols for each dll on the client side. - // if the client does not support such behavior, then we simply parse the symbols - // on the server side and append to the list of debug names to send to IDA, as normal. - for ( import_infos_t::const_iterator i = infos.begin(); i != infos.end(); ++i ) - { - ea_t base = i->base; - const char *path = i->path.c_str(); - const bytevec_t &uuid = i->uuid; - - bytevec_t req = prepare_rpc_packet(RPC_IMPORT_DLL); - req.pack_ea64(base); - req.pack_str(path); - req.pack_buf(uuid.begin(), uuid.size()); - - int code = send_request_get_long_result(req); - if ( code < 0 ) // cancelled or network error - return; - if ( code != 0 ) // request failed, fall back to parsing symbols server-side - dbg_mod->import_dll(*i); - } -} - -//-------------------------------------------------------------------------- -bool dbg_rpc_handler_t::get_broken_connection(void) -{ - return get_debugger_instance()->broken_connection; -} - -//-------------------------------------------------------------------------- -void dbg_rpc_handler_t::set_broken_connection(void) -{ - get_debugger_instance()->broken_connection = true; -} - -//------------------------------------------------------------------------- -int dbg_rpc_handler_t::kill_process(void) -{ - const int NSEC = 5; - dbg_mod->dbg_exit_process(NULL); - - // now, wait up to NSEC seconds until the process is gone - qtime64_t wait_start = qtime64(); - qtime64_t wait_threshold = make_qtime64( - get_secs(wait_start) + NSEC, - get_usecs(wait_start)); - while ( qtime64() < wait_threshold ) - { - gdecode_t result = dbg_mod->dbg_get_debug_event(&ev, 100); - if ( result >= GDE_ONE_EVENT ) - { - dbg_mod->dbg_continue_after_event(&ev); - if ( ev.eid() == PROCESS_EXITED ) - return 0; - } - } - return NSEC; -} - -//-------------------------------------------------------------------------- -int debmod_t::send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty) -{ - dbg_rpc_handler_t *s = (dbg_rpc_handler_t *)rpc; - return s->send_debug_names_to_ida(addrs, names, qty); -} - -//-------------------------------------------------------------------------- -int debmod_t::send_debug_event_to_ida(const debug_event_t *ev, int rqflags) -{ - dbg_rpc_handler_t *s = (dbg_rpc_handler_t *)rpc; - return s->send_debug_event_to_ida(ev, rqflags); -} diff --git a/idasdk75/dbg/deb_arm.hpp b/idasdk75/dbg/deb_arm.hpp deleted file mode 100644 index 44f8643..0000000 --- a/idasdk75/dbg/deb_arm.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef __DEB_ARM__ -#define __DEB_ARM__ - -#include -#include - -#define MEMORY_PAGE_SIZE 0x1000 -#define ARM_BPT_CODE { 0xF0, 0x01, 0xF0, 0xE7 } // und #10 -#define AARCH64_BPT_CODE { 0x00, 0x00, 0x20, 0xD4 } // brk #0 - -#define ARM_BPT_SIZE 4 // size of BPT instruction - -#define ARM_T 20 // number of virtual T segment register in IDA - // it controls thumb/arm mode. - -int is_arm_valid_bpt(bpttype_t type, ea_t ea, int len); - -#endif - diff --git a/idasdk75/dbg/debmod.cpp b/idasdk75/dbg/debmod.cpp deleted file mode 100644 index 37f5f48..0000000 --- a/idasdk75/dbg/debmod.cpp +++ /dev/null @@ -1,1329 +0,0 @@ -/* - Base debmod class. -*/ - -#ifdef __NT__ -# include -#else -# include -#endif - -#include "debmod.h" -#include -#include -#include -#include -#include -#include -#include - -//-------------------------------------------------------------------------- -// Variables to be used by built-in IDC functions -debmod_t *idc_debmod; -thid_t idc_thread; - -//-------------------------------------------------------------------------- -// Initialize static members -bool debmod_t::reuse_broken_connections = false; - -//-------------------------------------------------------------------------- -static const char *get_event_name(event_id_t id) -{ - switch ( id ) - { - case NO_EVENT: return "NO_EVENT"; - case THREAD_STARTED: return "THREAD_STARTED"; - case STEP: return "STEP"; - case PROCESS_DETACHED: return "PROCESS_DETACHED"; - case PROCESS_STARTED: return "PROCESS_STARTED"; - case PROCESS_ATTACHED: return "PROCESS_ATTACHED"; - case PROCESS_SUSPENDED: return "PROCESS_SUSPENDED"; - case LIB_LOADED: return "LIB_LOADED"; - case PROCESS_EXITED: return "PROCESS_EXITED"; - case THREAD_EXITED: return "THREAD_EXITED"; - case BREAKPOINT: return "BREAKPOINT"; - case EXCEPTION: return "EXCEPTION"; - case LIB_UNLOADED: return "LIB_UNLOADED"; - case INFORMATION: return "INFORMATION"; - case TRACE_FULL: return "TRACE_FULL"; - default: return "???"; - } -} - -#if defined(__MAC__) || defined(__LINUX__) || defined(__ANDROID__) -//--------------------------------------------------------------------------- -inline bool is_esxi() -{ -#ifdef __LINUX__ - static int ok = -1; - if ( ok == -1 ) - { - utsname utsinfo; - ok = uname(&utsinfo) == 0 && strieq(utsinfo.sysname, "VMkernel"); - } - return ok > 0; -#else - return false; -#endif -} - -//--------------------------------------------------------------------------- -drc_t idaapi maclnx_launch_process( - debmod_t *debmod, - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - void **child_pid, - qstring * /*errbuf*/) -{ - // prepare full path if the input_path is relative - char full_input[QMAXPATH]; - if ( startdir[0] != '\0' && !qisabspath(input_path) ) - { - qmake_full_path(full_input, sizeof(full_input), input_path); - input_path = full_input; - } - - // input file specified in the database does not exist - if ( input_path[0] != '\0' && !qfileexist(input_path) ) - { - debmod->dwarning("AUTOHIDE NONE\nInput file is missing: %s", input_path); - return DRC_NOFILE; - } - - // temporary thing, later we will retrieve the real file name - // based on the process id - debmod->input_file_path = input_path; - debmod->is_dll = (flags & DBG_PROC_IS_DLL) != 0; - - if ( !qfileexist(path) ) - { - debmod->dmsg("%s: %s\n", path, winerr(errno)); - return DRC_NETERR; - } - - drc_t mismatch = DRC_OK; - if ( !debmod->check_input_file_crc32(input_file_crc32) ) - mismatch = DRC_CRC; - - //-V:dbg_srv_64:547 is always true -#ifdef __EA64__ - bool dbg_srv_64 = true; -#else - bool dbg_srv_64 = false; - if ( (flags & DBG_PROC_64BIT) != 0 ) - { - debmod->dwarning("Cannot debug a 64bit process with the 32bit debugger server, sorry\n"); - return DRC_NETERR; - } -#endif - - launch_process_params_t lpi; - lpi.path = path; - lpi.args = args; - lpi.startdir = startdir[0] != '\0' ? startdir : NULL; - lpi.flags = LP_NO_ASLR | LP_DETACH_TTY; - - // Vmware ESXi sends SIGHUP when we try to detact. It could be because of a - // racing condition in but I do not have ESXi handy to check. - if ( is_esxi() ) - lpi.flags &= ~LP_DETACH_TTY; - if ( (flags & DBG_NO_TRACE) == 0 ) - lpi.flags |= LP_TRACE; - if ( (flags & DBG_HIDE_WINDOW) != 0 ) - lpi.flags |= LP_HIDE_WINDOW; - - if ( (flags & DBG_PROC_64BIT) != 0 ) - { - lpi.flags |= LP_LAUNCH_64_BIT; - } - else if ( (flags & DBG_PROC_32BIT) != 0 ) - { - lpi.flags |= LP_LAUNCH_32_BIT; - } - else - { - lpi.flags |= dbg_srv_64 ? LP_LAUNCH_64_BIT : LP_LAUNCH_32_BIT; - debmod->dmsg("Launching as %sbit process\n", dbg_srv_64 ? "64" : "32"); - } - - qstring errbuf; - *child_pid = launch_process(lpi, &errbuf); - - if ( *child_pid == NULL ) - { - debmod->dmsg("launch_process: %s", errbuf.c_str()); - return DRC_NETERR; - } - return mismatch; -} -#endif - -//-------------------------------------------------------------------------- -debmod_t::debmod_t(void): -// ph(PH), - debugger_flags(0), - rpc(NULL), - debug_debugger(false), - is_dll(false), - sp_idx(-1), - pc_idx(-1), - fp_idx(-1), - nregs(0), - broken_connection(false), - pid(-1) -{ - debapp_attrs.platform = "UNDEFINED"; - proclist.clear(); -} - -//-------------------------------------------------------------------------- -bool debmod_t::same_as_oldmemcfg(const meminfo_vec_t &ranges) const -{ - return old_ranges == ranges; -} - -//-------------------------------------------------------------------------- -void debmod_t::save_oldmemcfg(const meminfo_vec_t &ranges) -{ - old_ranges = ranges; -} - -//-------------------------------------------------------------------------- -bool debmod_t::check_input_file_crc32(uint32 orig_crc) -{ - // take this opportunity to check that the derived class initialized - // register related fields correctly - QASSERT(30016, sp_idx != -1 && pc_idx != -1 && nregs > 0); - - if ( orig_crc == 0 ) - return true; // the database has no crc - - linput_t *li = open_linput(input_file_path.c_str(), false); - if ( li == NULL ) - return false; - - uint32 crc = calc_file_crc32(li); - close_linput(li); - return crc == orig_crc; -} - -//-------------------------------------------------------------------------- -const exception_info_t *debmod_t::find_exception(int code) -{ - for ( const exception_info_t *ei = exceptions.begin(); - ei != exceptions.end(); - ++ei ) - { - if ( ei->code == (uint)code ) - return ei; - } - return NULL; -} - -//-------------------------------------------------------------------------- -bool debmod_t::get_exception_name(int code, char *buf, size_t bufsize) -{ - const exception_info_t *ei = find_exception(code); - if ( ei != NULL ) - { - qstrncpy(buf, ei->name.c_str(), bufsize); - return true; - } - qsnprintf(buf, bufsize, "%08X", code); - return false; -} - -//---------------------------------------------------------------------- -int idaapi debmod_t::get_system_specific_errno(void) const -{ - // this code must be acceptable by winerr() -#ifdef __NT__ - return GetLastError(); -#else - return errno; -#endif -} - -//------------------------------------------------------------------------- -ssize_t debmod_t::dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va) -{ - if ( rpc == NULL || rpc->is_client ) - return dvnotif_client(code, format, va); - else - return dvnotif_rpc(code, rpc, format, va); -} - -//---------------------------------------------------------------------- -// Display a system error message. This function always returns false -bool debmod_t::deberr(const char *format, ...) -{ - if ( !debug_debugger ) - return false; - - int code = get_system_specific_errno(); - va_list va; - va_start(va, format); - dvnotif(0, rpc, format, va); - va_end(va); - dmsg(": %s\n", winerr(code)); - return false; -} - -//-------------------------------------------------------------------------- -// used to debug the debugger -void debmod_t::debdeb(const char *format, ...) -{ - if ( !debug_debugger ) - return; - - va_list va; - va_start(va, format); - dvnotif(0, rpc, format, va); - va_end(va); -} - -//-------------------------------------------------------------------------- -void debmod_t::cleanup(void) -{ - input_file_path.qclear(); - old_ranges.qclear(); - exceptions.qclear(); - clear_debug_names(); - handling_lowcnds.clear(); -#ifdef ENABLE_LOWCNDS - cndmap.clear(); -#endif - page_bpts.clear(); - pid = 0; - is_dll = false; -} - -//-------------------------------------------------------------------------- -void idaapi debmod_t::dbg_set_exception_info(const exception_info_t *table, int qty) -{ - exceptions.qclear(); - exceptions.reserve(qty); - for ( int i=0; i < qty; i++ ) - exceptions.push_back(*table++); -} - -//-------------------------------------------------------------------------- -char *debug_event_str(const debug_event_t *ev) -{ - static char buf[MAXSTR]; - return debug_event_str(ev, buf, sizeof(buf)); -} - -//-------------------------------------------------------------------------- -char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize) -{ - char *ptr = buf; - char *end = buf + bufsize; - ptr += qsnprintf(ptr, end-ptr, "%s ea=%a", - get_event_name(ev->eid()), - ev->ea); - switch ( ev->eid() ) - { - case PROCESS_STARTED: // New process started - case PROCESS_ATTACHED: // Attached to running process - case LIB_LOADED: // New library loaded - ptr += qsnprintf(ptr, end-ptr, " base=%a size=%a rebase=%a name=%s", - ev->modinfo().base, - ev->modinfo().size, - ev->modinfo().rebase_to, - ev->modinfo().name.c_str()); - break; - case PROCESS_EXITED: // Process stopped - case THREAD_EXITED: // Thread stopped - ptr += qsnprintf(ptr, end-ptr, " exit_code=%d", ev->exit_code()); - break; - case BREAKPOINT: // Breakpoint reached - ptr += qsnprintf(ptr, end-ptr, " hea=%a kea=%a", ev->bpt().hea, ev->bpt().kea); - break; - case EXCEPTION: // Exception - ptr += qsnprintf(ptr, end-ptr, " code=%x can_cont=%d ea=%a info=%s", - ev->exc().code, - ev->exc().can_cont, - ev->exc().ea, - ev->exc().info.c_str()); - break; - case THREAD_STARTED: // thread name - case LIB_UNLOADED: // Library unloaded - case INFORMATION: // User-defined information - APPCHAR(ptr, end, ' '); - APPEND(ptr, end, ev->info().c_str()); - break; - default: - break; - } - qsnprintf(ptr, end-ptr, " pid=%d tid=%d handled=%d", - ev->pid, - ev->tid, - ev->handled); - return buf; -} - -//-------------------------------------------------------------------------- -//lint -e{1536} Exposing low access member 'debmod_t::dn_names' -name_info_t *debmod_t::get_debug_names() -{ - return &dn_names; -} - -//-------------------------------------------------------------------------- -int debmod_t::set_debug_names() -{ - name_info_t *ni = get_debug_names(); - if ( ni->addrs.empty() ) - return 1; - int code = send_debug_names_to_ida( - ni->addrs.begin(), - ni->names.begin(), - (int)ni->addrs.size()); - clear_debug_names(); - return code; -} - -//-------------------------------------------------------------------------- -void debmod_t::clear_debug_names() -{ - if ( dn_names.addrs.empty() ) - return; - - typedef qvector charptr_vec_t; - charptr_vec_t::iterator it_end = dn_names.names.end(); - for ( charptr_vec_t::iterator it=dn_names.names.begin(); it != it_end; ++it ) - qfree(*it); - - dn_names.names.clear(); - dn_names.addrs.clear(); -} - -//-------------------------------------------------------------------------- -void debmod_t::save_debug_name(ea_t ea, const char *name) -{ - dn_names.addrs.push_back(ea); - dn_names.names.push_back(qstrdup(name)); -} - -//-------------------------------------------------------------------------- -ea_t debmod_t::find_debug_name(const char *name) const -{ - for ( size_t i = 0, size = dn_names.names.size(); i < size; i++ ) - { - if ( streq(name, dn_names.names[i]) ) - return dn_names.addrs[i]; - } - return BADADDR; -} - -//-------------------------------------------------------------------------- -bool debmod_t::continue_after_last_event(bool handled) -{ - last_event.handled = handled; - return dbg_continue_after_event(&last_event) == DRC_OK; -} - -//-------------------------------------------------------------------------- -// if there is an active control bpt at the exception address, -// unconditionally suspend the execution at it. continuing won't do any good -// even if the user told us to continue after all exceptions. -bool debmod_t::should_suspend_at_exception( - const debug_event_t *event, - const exception_info_t *ei) -{ - if ( ei == NULL || ei->break_on() ) - return true; - appcalls_t::const_iterator p = appcalls.find(event->tid); - if ( p == appcalls.end() ) - return false; - const call_contexts_t &ctxvec = p->second; - return !ctxvec.empty() && ctxvec.back().ctrl_ea == event->ea; -} - -//-------------------------------------------------------------------------- -bool debmod_t::should_stop_appcall(thid_t, const debug_event_t *event, ea_t ea) -{ - switch ( event->eid() ) - { - case EXCEPTION: - // exception on the stack (non-executable stack?) - if ( event->exc().ea == ea ) - return true; - // no break - case BREAKPOINT: - // reached the control breakpoint? - if ( event->ea == ea ) - return true; - default: - break; - } - return false; -} - -//-------------------------------------------------------------------------- -// return top of the stack range usable by appcall. usually it is equal to the -// current esp, unless the range below the stack pointer is not usable -// (for example, AMD64 ABI required the "red zone" not to be modified) -ea_t debmod_t::calc_appcall_stack(const regvals_t ®vals) -{ - return ea_t(regvals[sp_idx].ival); -} - -//-------------------------------------------------------------------------- -ea_t idaapi debmod_t::dbg_appcall( - ea_t func_ea, - thid_t tid, - int stkarg_nbytes, - const struct regobjs_t *regargs, - struct relobj_t *stkbytes, - struct regobjs_t *retregs, - qstring *errbuf, - debug_event_t *_event, - int options) -{ - enum - { - E_OK, // Success - E_READREGS, // Failed to read registers - E_NOSTACK, // Failed to allocate stack frame - E_REG_USED, // The calling convention refers to reserved registers - E_ARG_ALLOC, // Failed to allocate memory for stack arguments - E_WRITE_ARGS, // Failed to setup stack arguments - E_WRITE_REGS, // Failed to setup register arguments - E_HANDLE_EVENT,// Failed to handle debug event - E_DEBUG_EVENT, // Could not get debug events - E_RESUME, // Failed to resume the application - E_EXCEPTION, // An exception has occurred - E_APPCALL_FROM_EXC, // Cannot issue an AppCall if last event was an exception - E_TIMEOUT, // Timeout - }; - - static const char *const errstrs[] = - { - "success", - "failed to read registers", - "failed to allocate stack frame", - "the calling convention refers to reserved registers", - "failed to allocate memory for stack arguments", - "failed to setup stack arguments", - "failed to setup register arguments", - "failed to handle debug event", - "could not get debug events", - "failed to resume the application", - "an exception has occurred", - "last event was an exception, cannot perform an appcall", - "timeout", - }; - - // Save registers - regval_t rv; - - bool brk = false; - int err = E_OK; - - call_context_t &ctx = appcalls[tid].push_back(); - - regval_map_t call_regs; - ea_t args_sp = BADADDR; - do - { - // In Win32, when WaitForDebugEvent() returns an exception - // it seems that the OS remembers the exception context so that - // the next call to ContinueDebugEvent() will work with the last exception context. - // Now if we carry an AppCall when an exception was just reported: - // - Appcall will change context - // - Appcall's control bpt will generate an exception thus overriding the last exception context saved by the OS - // - After Appcall, IDA kernel cannot really continue from the first exception because it was overwritten - // Currently we will disallow Appcalls if last event is an exception - if ( last_event.eid() == EXCEPTION ) - { - err = E_APPCALL_FROM_EXC; - break; - } - // Save registers - ctx.saved_regs.resize(nregs); - if ( dbg_read_registers(tid, -1, ctx.saved_regs.begin(), NULL) != DRC_OK ) - { - err = E_READREGS; - break; - } - - // Get SP value - ea_t org_sp = calc_appcall_stack(ctx.saved_regs); - if ( org_sp == BADADDR ) - { - err = E_NOSTACK; - break; - } - - // Stack contents - bytevec_t stk; - - // Prepare control address - // We will generate a BP code ptrsz aligned and push unto the stack - // as the first argument. This is where we will set the control bpt. - // Since the bpt is on the stack, two possible scenarios: - // - BPT exception - // - Access violation: trying to execute from NX page - // In both cases we will catch an exception and learn what address was - // involved. - - // - Save the ctrl address - ea_t ctrl_ea = org_sp - debapp_attrs.addrsize; - - // - Compute the pointer where arguments will be allocated on the stack - size_t stkbytes_size = align_up(stkbytes->size(), debapp_attrs.addrsize); - args_sp = ctrl_ea - stkbytes_size; - - // align the stack pointer to 16 byte boundary (gcc compiled programs require it) - args_sp &= ~15; - ctx.ctrl_ea = args_sp + stkbytes_size; - - // Relocate the stack arguments - if ( !stkbytes->relocate(args_sp, false) ) - { - err = E_ARG_ALLOC; - break; - } - - // Prepare the stack. - // The memory layout @SP before transfering to the function: - // R = ret addr - // A = args - - // - Append the return address (its value is the value of the ctrl code address) - stk.append(&ctx.ctrl_ea, debapp_attrs.addrsize); - - // - Append the stack args - stk.append(stkbytes->begin(), stkbytes->size()); - stk.resize(debapp_attrs.addrsize+stkbytes_size); // align up - ctx.sp = args_sp - debapp_attrs.addrsize; - if ( ctx.sp >= org_sp ) - { // underflow? - err = E_NOSTACK; - break; - } - - int delta = finalize_appcall_stack(ctx, call_regs, stk); - ctx.sp += delta; // nbytes inserted at the beginning of stk - - // Write the stack - int nwrite = stk.size() - delta; - if ( nwrite > 0 ) - { - if ( dbg_write_memory(ctx.sp, stk.begin()+delta, nwrite, NULL) != nwrite ) - { - err = E_WRITE_ARGS; - break; - } - //show_hex(stk.begin()+delta, nwrite, "Written stack bytes to %a:\n", ctx.sp); - } - - // ask the debugger to set a breakpoint - dbg_add_bpt(NULL, BPT_SOFT, ctx.ctrl_ea, -1); - - // Copy arg registers to call_regs - for ( size_t i=0; i < regargs->size(); i++ ) - { - const regobj_t &ri = regargs->at(i); - int reg_idx = ri.regidx; - if ( reg_idx == sp_idx || reg_idx == pc_idx ) - { - brk = true; - err = E_REG_USED; - break; - } - - // Copy the register value - if ( ri.size() <= sizeof(rv.fval) ) - { - rv.clear(); - memcpy(rv.fval, ri.value.begin(), ri.size()); - if ( ri.relocate ) - rv.ival += args_sp; - } - else - { - bytevec_t &b = rv.set_bytes(); - b.resize(ri.size()); - memcpy(b.begin(), ri.value.begin(), ri.size()); - rv.rvtype = 0; // custom data format - } - call_regs[reg_idx] = rv; - } - if ( brk ) - break; - - // Set the stack pointer - rv.clear(); - rv.ival = ctx.sp; - call_regs[sp_idx] = rv; - - // Set the instruction pointer - rv.ival = func_ea; - call_regs[pc_idx] = rv; - - // Change all the registers in question - for ( regval_map_t::iterator it = call_regs.begin(); - it != call_regs.end(); - ++it ) - { - if ( dbg_write_register(tid, it->first, &it->second, NULL) != DRC_OK ) - { - err = E_WRITE_REGS; - brk = true; - break; - } - // Mark that we changed the regs already - ctx.regs_spoiled = true; - } - if ( brk ) - break; - - // For manual appcall, we have done everything, just return now - if ( (options & APPCALL_MANUAL) != 0 ) - break; - - // Resume the application - // Since no* exception last occurred**, we can safely say that the - // debugger actually handled the exception. - // * : We disallow appcalls if an exception last occurred - // **: Actually if an AppCall was issued then last event is an exception - // but we will mask it by calling continue_after_event(handled_by_debugger = true) - if ( !continue_after_last_event(true) ) - { - err = E_RESUME; - break; - } - - // We use this list to accumulate the events - // We will give back the events at the end of the loop - debug_event_t tmp; - debug_event_t *event = _event != NULL ? _event : &tmp; - - // Determine timeout for get_debug_event() - uint64 endtime = 0; - int recalc_timeout = 0; // never recalc timeout - int timeout_ms = TIMEOUT; - if ( (options & APPCALL_TIMEOUT) != 0 ) - { - timeout_ms = GET_APPCALL_TIMEOUT(options); - if ( timeout_ms > 0 ) - { - endtime = get_nsec_stamp(); - endtime += timeout_ms * uint64(1000 * 1000); - } - recalc_timeout = 1; // recalc timeout after the first pass - } - - while ( true ) - { - if ( recalc_timeout ) - { - if ( recalc_timeout != 2 ) - { // we will recalc timeout at the next iteration - recalc_timeout = 2; - } - else - { - if ( timeout_ms > 0 ) - { - // calculate the remaining timeout - uint64 now = get_nsec_stamp(); - timeout_ms = int64(endtime - now) / int64(1000 * 1000); - } - if ( timeout_ms <= 0 ) - { // timeout out waiting for the appcall to finish - err = E_TIMEOUT; - if ( dbg_prepare_to_pause_process(NULL) <= DRC_NONE ) - break; // could not even prepare to pause, nothing we can do :( - } - } - } - // Wait for debug events - gdecode_t r = dbg_get_debug_event(event, timeout_ms); - if ( r == GDE_NO_EVENT ) - continue; - if ( r == GDE_ERROR ) - { // error getting debug event (network error, etc) - err = E_DEBUG_EVENT; - break; - } - - // We may get three possible events related to our control breakpoint: - // - Access violation type: because we try to execute non-executable code - // - Or a BPT exception if the stack page happens to be executable - // - Process exit - if ( event->eid() == PROCESS_EXITED // process is gone - || event->eid() == THREAD_EXITED && event->tid == tid ) // our thread is gone - { - send_debug_event_to_ida(event, RQ_SILENT); - args_sp = BADADDR; - brk = true; - break; - } - if ( err == E_TIMEOUT ) - { - send_debug_event_to_ida(event, RQ_SILENT|RQ_SUSPEND); - event->set_eid(NO_EVENT); - last_event.set_eid(NO_EVENT); - break; - } - if ( should_stop_appcall(tid, event, ctx.ctrl_ea) ) - { - last_event.set_eid(NO_EVENT); - break; - } - // Any other exception? - if ( event->eid() == EXCEPTION ) - { - if ( (options & APPCALL_DEBEV) == 0 ) - *errbuf = event->exc().info; // Copy exception text to the user - err = E_EXCEPTION; - // When an exception happens during the appcall, we want to mask - // the exception, because: - // 1. we reset the EIP to its original location - // 2. there is no exception handler for the appcall so we cannot really pass as unhandled - // FIXME - last_event.set_eid(NO_EVENT); - last_event.handled = true; - brk = true; - break; - } - - if ( send_debug_event_to_ida(event, RQ_SILENT|RQ_SUSPEND) != 0 ) - { - err = E_HANDLE_EVENT; - break; - } - dbg_continue_after_event(event); - event->set_eid(NO_EVENT); - } - - if ( brk || err != E_OK ) - break; - - // write the argument vector back because it could be spoiled by the application - if ( stkarg_nbytes > 0 ) - { - int nbytes = stkarg_nbytes; - if ( nbytes > stkbytes->size() // wrong parameters - || dbg_write_memory(args_sp, stkbytes->begin(), nbytes, NULL) != ssize_t(nbytes) ) - { - err = E_WRITE_ARGS; - break; - } - } - - // Retrieve the return value - if ( retregs != NULL && !retregs->empty() ) - { - regvals_t retr; - retr.resize(nregs); - if ( dbg_read_registers(tid, -1, retr.begin(), NULL) <= DRC_NONE ) - { - err = E_READREGS; - break; - } - for ( size_t i=0; i < retregs->size(); i++ ) - { - regobj_t &r = retregs->at(i); - regval_t &v = retr[r.regidx]; - memcpy(r.value.begin(), v.get_data(), r.value.size()); - r.relocate = false; - } - } - } while ( false ); - - if ( err != E_OK ) - { - if ( err != E_EXCEPTION ) - *errbuf = errstrs[err]; - dbg_cleanup_appcall(tid); - args_sp = BADADDR; - } - - return args_sp; -} - -//-------------------------------------------------------------------------- -// Cleanup after appcall() -// The debugger module must keep the stack blob in the memory until this function -// is called. It will be called by the kernel for each successful call_app_func() -drc_t idaapi debmod_t::dbg_cleanup_appcall(thid_t tid) -{ - appcalls_t::iterator p = appcalls.find(tid); - if ( p == appcalls.end() ) - return DRC_FAILED; - call_contexts_t &calls = p->second; - if ( calls.empty() ) - return DRC_FAILED; - - // remove the return breakpoint - call_context_t &ctx = calls.back(); - if ( !preprocess_appcall_cleanup(tid, ctx) ) - return DRC_FAILED; - - dbg_del_bpt(BPT_SOFT, ctx.ctrl_ea, bpt_code.begin(), bpt_code.size()); - if ( ctx.regs_spoiled ) - { - if ( !write_registers(tid, 0, ctx.saved_regs.size(), ctx.saved_regs.begin()) ) - { - dmsg("Failed to restore %" FMT_Z " registers!\n", ctx.saved_regs.size()); - return DRC_FAILED; - } - } - - calls.pop(); - if ( calls.empty() ) - appcalls.erase(p); - return events.empty() ? DRC_OK : DRC_EVENTS; -} - -//-------------------------------------------------------------------------- -drc_t debmod_t::resume_app_and_get_event(debug_event_t *dev) -{ - thid_t tid = dev->tid; - drc_t drc = dbg_continue_after_event(dev); - if ( drc > DRC_NONE ) - { - while ( true ) - { - gdecode_t gc = dbg_get_debug_event(dev, TIMEOUT_INFINITY); - if ( gc != GDE_NO_EVENT ) - break; - } - // is it in our thread? - if ( tid != dev->tid ) - { // very odd! an event from another thread arrived - if ( dev->eid() != THREAD_STARTED ) - dmsg("unexpected event from thread %d arrived (expected thread %d)\n", dev->tid, tid); - drc = DRC_FAILED; // indicate failure - } - } - return drc; -} - -//-------------------------------------------------------------------------- -drc_t debmod_t::dbg_perform_single_step(debug_event_t *dev, const insn_t &) -{ - // all other threads must be frozen at this moment - drc_t drc = dbg_set_resume_mode(dev->tid, RESMOD_INTO); - if ( drc > DRC_NONE ) - drc = resume_app_and_get_event(dev); - return drc; -} - -//-------------------------------------------------------------------------- -// returns true-lowcnd was false, resumed the application -// nb: recursive calls to this function are not handled in any special way! -bool debmod_t::handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags) -{ - if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 - || lc->type != BPT_SOFT && find_page_bpt(lc->ea, lc->size) != page_bpts.end() ) - { - // difficult case: we have to reset pc, remove the bpt, single step, and resume the app - QASSERT(616, !handling_lowcnds.has(lc->ea)); - handling_lowcnds.push_back(lc->ea); - - if ( (elc_flags & ELC_KEEP_EIP) == 0 ) - { - regval_t rv; - rv._set_int(lc->ea); - drc_t drc = dbg_write_register(event->tid, pc_idx, &rv, NULL); - if ( drc <= DRC_NONE ) - { - handling_lowcnds.del(lc->ea); - return false; - } - } - - int code = dbg_freeze_threads_except(event->tid); - if ( code > 0 ) - { - int bptlen = lc->type == BPT_SOFT ? lc->orgbytes.size() : lc->size; - code = dbg_del_bpt(lc->type, lc->ea, lc->orgbytes.begin(), bptlen); - if ( code > 0 ) - { - drc_t drc = dbg_perform_single_step(event, lc->cmd); - if ( drc <= DRC_NONE ) - { - code = 0; - dmsg("%a: failed to single step\n", event->ea); // may happen - } - - if ( dbg_add_bpt(NULL, lc->type, lc->ea, bptlen) <= 0 ) - { - // if this fails, it may be because the breakpoint is invalid - // at this time so we should notify IDA it isn't available - // any more - code = 0; - dwarning("%a: could not restore deleted bpt\n", lc->ea); // odd - } - } - if ( dbg_thaw_threads_except(event->tid) <= 0 ) - { - dwarning("%d: could not resume suspended threads\n", event->tid); // odd - code = 0; - } - } - handling_lowcnds.del(lc->ea); - if ( code <= 0 || event->eid() != STEP ) - return false; // did not resume - } - if ( (elc_flags & ELC_KEEP_SUSP) != 0 ) - return true; - return dbg_continue_after_event(event) > DRC_NONE; -} - -//-------------------------------------------------------------------------- -// return lowcnd_t if its condition is not satisfied -lowcnd_t *debmod_t::get_failed_lowcnd(thid_t tid, ea_t ea) -{ -#ifndef ENABLE_LOWCNDS - //lint -esym(1762, debmod_t::get_failed_lowcnd) could be made const - qnotused(tid); - qnotused(ea); -#else - lowcnds_t::iterator p = cndmap.find(ea); - if ( p != cndmap.end() ) - { - bool ok = true; - idc_value_t rv; - char name[32]; - ::qsnprintf(name, sizeof(name), "__lc%a", ea); - lowcnd_t &lc = p->second; - lock_begin(); - { - idc_debmod = this; // is required by compiler/interpreter - idc_thread = tid; // is required by interpreter - if ( !lc.compiled ) - { - ok = compile_idc_snippet(name, lc.cndbody.begin(), NULL, NULL, true); - if ( ok ) - lc.compiled = true; - } - if ( ok ) - ok = call_idc_func(&rv, name, NULL, 0); - } - lock_end(); - if ( !ok ) - { - report_idc_error(ea, get_qerrno(), get_error_data(0), get_error_string(0)); - return NULL; - } - - idcv_int64(&rv); - if ( rv.i64 == 0 ) - return &lc; // condition is not satisfied, resume - } -#endif - return NULL; -} - -//-------------------------------------------------------------------------- -bool debmod_t::evaluate_and_handle_lowcnd(debug_event_t *event, int elc_flags) -{ - bool resume = false; - if ( event->eid() == BREAKPOINT ) - { - ea_t ea = event->bpt().kea != BADADDR ? event->bpt().kea - : event->bpt().hea != BADADDR ? event->bpt().hea - : event->ea; - lowcnd_t *lc = get_failed_lowcnd(event->tid, ea); - if ( lc != NULL ) - { // condition is not satisfied, just make a single step and resume - debdeb("%a: bptcnd yielded false\n", ea); - event->handled = true; - QASSERT(617, !handling_lowcnds.has(ea)); - resume = handle_lowcnd(lc, event, elc_flags); - } - } - return resume; -} - -//-------------------------------------------------------------------------- -drc_t idaapi debmod_t::dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring * /*errbuf*/) -{ - return get_failed_lowcnd(tid, ea) == NULL ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -drc_t idaapi debmod_t::dbg_update_lowcnds( - int *nupdated, - const lowcnd_t *lowcnds, - int nlowcnds, - qstring * /*errbuf*/) -{ -#ifndef ENABLE_LOWCNDS - qnotused(lowcnds); - qnotused(nlowcnds); - if ( nupdated != NULL ) - *nupdated = 0; - return DRC_OK; -#else - for ( int i=0; i < nlowcnds; i++, lowcnds++ ) - { - ea_t ea = lowcnds->ea; - if ( lowcnds->cndbody.empty() ) - cndmap.erase(ea); - else - cndmap[ea] = *lowcnds; - } - if ( nupdated != NULL ) - *nupdated = nlowcnds; - return DRC_OK; -#endif -} - -//-------------------------------------------------------------------------- -// determine the future bpt size and read the original instruction from memory. -// if necessary, the bpt address may be adjusted. -// return the number of read bytes. -// this function is overloaded in arm debugger subclasses. -int debmod_t::read_bpt_orgbytes(bytevec_t *buf, ea_t ea, int len) -{ - buf->qclear(); - if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 ) - { // we must save the original bytes before adding the bpt - buf->resize(len); - if ( dbg_read_memory(ea, buf->begin(), len, NULL) <= 0 ) - return -1; - } - else - { // if the debuger can itself continue from bpts, - // orgbytes will not be used by the kernel. however - // we must return something because non-empty orgbytes mean - // that a soft bpt is active. we return zeroes in b->orgbytes. - buf->resize(len, 0); - } - return len; -} - -//-------------------------------------------------------------------------- -drc_t idaapi debmod_t::dbg_update_bpts( - int *nbpts, - update_bpt_info_t *ubpts, - int nadd, - int ndel, - qstring * /*errbuf*/) -{ - if ( events.empty() ) - deleted_bpts.clear(); - - // Write breakpoints to the process - int cnt = 0; - update_bpt_info_t *b; - update_bpt_info_t *end = ubpts + nadd; - for ( b=ubpts; b != end; b++ ) - { - int code = b->code; - if ( code != BPT_OK ) - continue; // should be BPT_SKIP - - int len = b->type == BPT_SOFT ? bpt_code.size() : b->size; - ea_t ea = b->ea; - if ( b->type == BPT_SOFT ) - adjust_swbpt(&ea, &len); - - update_bpt_vec_t::iterator d = deleted_bpts.find(*b); - if ( d != deleted_bpts.end() && d->tid == b->tid ) - deleted_bpts.erase(d); - - code = dbg_add_bpt(&b->orgbytes, b->type, ea, len); - debdeb("dbg_add_bpt(type=%d, ea=%a, len=%d) => %d\n", b->type, ea, len, code); - switch ( code ) - { - case 2: - code = BPT_PAGE_OK; - break; - case 1: - code = BPT_OK; - break; - default: - code = BPT_WRITE_ERROR; - break; - case -2: - code = BPT_READ_ERROR; - break; - } - - b->code = code; - if ( code == BPT_OK || code == BPT_PAGE_OK ) - cnt++; - } - - // Delete breakpoints from the process. - end += ndel; - for ( ; b != end; b++ ) - { - b->code = BPT_OK; - int len = b->type == BPT_SOFT ? b->orgbytes.size() : b->size; - int code = dbg_del_bpt(b->type, b->ea, b->orgbytes.begin(), len); - debdeb("dbg_del_bpt(type=%d, ea=%a) => %d\n", b->type, b->ea, code); - if ( code > 0 ) - { - cnt++; - if ( b->type == BPT_SOFT || b->type == BPT_EXEC ) - deleted_bpts.push_back(*b); - } - else - { - b->code = BPT_WRITE_ERROR; - } - } - - if ( nbpts != NULL ) - *nbpts = cnt; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -// Find a page breakpoint that would cause an exception on the given range -// NB: we do not check the user-specified range but the real page range! -page_bpts_t::iterator debmod_t::find_page_bpt( - ea_t ea, - int size) -{ - page_bpts_t::iterator p = page_bpts.lower_bound(calc_page_base(ea)); - if ( p == page_bpts.end() || p->first >= ea+size ) - { - if ( p == page_bpts.begin() ) - return page_bpts.end(); // not found - --p; - } - ea_t page_ea = p->first; - int page_len = p->second.aligned_len; - if ( !interval::overlap(ea, size, page_ea, page_len) ) - p = page_bpts.end(); - return p; -} - -//-------------------------------------------------------------------------- -bool debmod_t::del_page_bpt(ea_t ea, bpttype_t type) -{ - page_bpts_t::iterator p = find_page_bpt(ea); - if ( p == page_bpts.end() ) - return false; // could not find - if ( p->second.ea != ea || p->second.type != type ) - return false; // not exact match - - dbg_enable_page_bpt(p, false); - page_bpts.erase(p); - return true; -} - -//-------------------------------------------------------------------------- -void debmod_t::enable_page_bpts(bool enable) -{ - for ( page_bpts_t::iterator p = page_bpts.begin(); p != page_bpts.end(); ++p ) - dbg_enable_page_bpt(p, enable); -} - -//-------------------------------------------------------------------------- -void debmod_t::set_platform(const char *platform_name) -{ - debapp_attrs.platform = platform_name; -} - -//-------------------------------------------------------------------------- -void debmod_t::dbg_get_debapp_attrs(debapp_attrs_t *out_pattrs) const -{ - *out_pattrs = debapp_attrs; -} - -//-------------------------------------------------------------------------- -bool debmod_t::restore_broken_breakpoints(void) -{ - debmodbpt_map_t::const_iterator p; - for ( p = bpts.begin(); p != bpts.end(); ++p ) - { - const debmod_bpt_t &bpt = p->second; - if ( !dbg_write_memory(bpt.ea, bpt.saved, bpt.nsaved, NULL) ) - msg("Failed to restore broken breakpoint at 0x%a\n", bpt.ea); - } - bpts.clear(); - return true; -} - - -//-------------------------------------------------------------------------- -void debmod_t::log_exception( - const debug_event_t *ev, - const exception_info_t *ei) -{ - if ( ei == NULL || (ei->flags & EXC_SILENT) == 0 ) - { - if ( ev->exc().ea != BADADDR ) - { - dmsg("%a: %s -> %a (exc.code %x, tid %d)\n", - ev->ea, ev->exc().info.c_str(), ev->exc().ea, ev->exc().code, ev->tid); - } - else - { - dmsg("%a: %s (exc.code %x, tid %d)\n", - ev->ea, ev->exc().info.c_str(), ev->exc().code, ev->tid); - } - } -} - -//-------------------------------------------------------------------------- -int idaapi debmod_t::dbg_rexec(const char *cmdline) -{ - msg("REXEC: %s\n", cmdline); - return call_system(cmdline); -} - -//-------------------------------------------------------------------------- -drc_t idaapi debmod_t::dbg_get_processes(procinfo_vec_t *procs, qstring *errbuf) -{ - proclist.qclear(); - get_process_list(&proclist, errbuf); - - size_t size = proclist.size(); - procs->qclear(); - procs->reserve(size); - for ( size_t i = 0; i < size; i++ ) - { - process_info_t &procinf = procs->push_back(); - proclist[i].copy_to(&procinf); - } - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -int idaapi debmod_t::get_process_list(procvec_t *list, qstring *) -{ - list->clear(); - return -1; -} - -//-------------------------------------------------------------------------- -uint64 debmod_t::probe_file_size(int fn, uint64 step) -{ - uint64 low = 0; - uint64 high = step; - char dummy; - while ( dbg_read_file(fn, high-1, &dummy, 1) == 1 ) - { - low = high; - high += step; - if ( step < 0x7FFFFFFFFFFFFFFFULL ) - step *= 2; - } - while ( low+1 < high ) - { - int middle = (high+low)/2; - if ( dbg_read_file(fn, middle-1, &dummy, 1) == 1 ) - low = middle; - else - high = middle; - } - return low; -} diff --git a/idasdk75/dbg/debmod.h b/idasdk75/dbg/debmod.h deleted file mode 100644 index 62957e6..0000000 --- a/idasdk75/dbg/debmod.h +++ /dev/null @@ -1,741 +0,0 @@ -#ifndef __DEBUGGER_MODULE__ -#define __DEBUGGER_MODULE__ - -// -// -// This is the base debmod_t class definition -// From this class all debugger code must inherite and specialize -// -// Some OS specific functions must be implemented: -// bool init_subsystem(); -// bool term_subsystem(); -// debmod_t *create_debug_session(void *); -// int create_thread(thread_cb_t thread_cb, void *context); -// - -#include -#include -#include -#include -#include -#include -#include - -//-------------------------------------------------------------------------- -extern debugger_t debugger; - -//-------------------------------------------------------------------------- -struct name_info_t -{ - eavec_t addrs; - qvector names; - void clear(void) - { - addrs.clear(); - names.clear(); - } -}; - -//-------------------------------------------------------------------------- -// Extended process info -struct ext_process_info_t : public process_info_t -{ - int addrsize; // process bitness 32bit - 4, 64bit - 8, 0 - unknown - qstring ext_name; // human-readable name (e.g. with command line agrs) - void copy_to(process_info_t *dst) - { - dst->pid = pid; - dst->name = ext_name.empty() ? name : ext_name; - } -}; -typedef qvector procvec_t; - -//-------------------------------------------------------------------------- -// Very simple class to store pending events -enum queue_pos_t -{ - IN_FRONT, - IN_BACK -}; - -//-------------------------------------------------------------------------- -struct pagebpt_data_t -{ - ea_t ea; // address of the bpt as specified by the user - ea_t page_ea; // real address of the bpt as written to the process - int user_len; // breakpoint length as specified by the user - int aligned_len; // breakpoint length aligned to the page size - int real_len; // real length of the breakpoint as written to the process - uint32 old_prot; // old page protections (before writing the bpt to the process) - // if 0, the bpt has not been written to the process yet. - uint32 new_prot; // new page protections (when the bpt is active) - bpttype_t type; // breakpoint type -}; - -// Information about page breakpoints is stored in this data structure. -// The map is indexed by the page start address (not the address specified -// by the user!) -typedef std::map page_bpts_t; // page_ea -> bpt info -typedef qvector pbpt_iterators_t; // list of iterators into page_bpts_t - -//-------------------------------------------------------------------------- -// set of addresses -typedef std::set easet_t; - -//------------------------------------------------------------------------- -class idc_value_t; -class rpc_engine_t; -error_t idaapi idc_get_reg_value(idc_value_t *argv, idc_value_t *r); -error_t idaapi idc_set_reg_value(idc_value_t *argv, idc_value_t *r); -void report_idc_error(rpc_engine_t *rpc, ea_t ea, error_t code, ssize_t errval, const char *errprm); - -// IDC function name that is exported by a debugger module -// to allow scripts to send debugger commands -#define IDC_SENDDBG_CMD "send_dbg_command" -#define IDC_READ_MSR "read_msr" -#define IDC_WRITE_MSR "write_msr" -#define IDC_STEP_BACK "step_back" -#define IDC_SET_TEV "set_current_tev" -#define IDC_GET_TEV "get_current_tev" - -// A macro to convert a pointer to ea_t without sign extension. -#define EA_T(ptr) (ea_t)(size_t)(ptr) - -//-------------------------------------------------------------------------- -//-V:debmod_bpt_t:730 not all members of a class are initialized inside the constructor: saved -struct debmod_bpt_t -{ - ea_t ea; - uchar saved[8]; // size of the biggest supported bpt size (PPC64) - uchar nsaved; - int bid; // (epoc) breakpoint id (from TRK) - debmod_bpt_t() : ea(BADADDR), nsaved(0), bid(0) {} - debmod_bpt_t(ea_t _ea, uchar _nsaved) : ea(_ea), nsaved(_nsaved), bid(0) { QASSERT(1796, nsaved < sizeof(saved)); } -}; -typedef std::map debmodbpt_map_t; - -//-------------------------------------------------------------------------- -struct eventlist_t : public std::deque -{ -public: - // save a pending event - void enqueue(const debug_event_t &ev, queue_pos_t pos) - { - if ( pos != IN_BACK ) - push_front(ev); - else - push_back(ev); - } - - // retrieve a pending event - bool retrieve(debug_event_t *event) - { - if ( empty() ) - return false; - // get the first event and return it - *event = front(); - pop_front(); - return true; - } -}; - -//-------------------------------------------------------------------------- -int send_ioctl(rpc_engine_t *rpc, int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize); -int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty); -int send_debug_event_to_ida(const debug_event_t *ev, int rqflags); -void set_arm_thumb_modes(ea_t *addrs, int qty); -char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize); -char *debug_event_str(const debug_event_t *ev); // returns static buf - -//-------------------------------------------------------------------------- -// describes a dll to be imported -struct import_request_t -{ - ea_t base; - qstring path; - bytevec_t uuid; - import_request_t(ea_t _base, const qstring &_path, const bytevec_t &_uuid) - : base(_base), path(_path), uuid(_uuid) {} -}; -DECLARE_TYPE_AS_MOVABLE(import_request_t); -typedef qvector import_infos_t; -int import_dll(const import_request_t &req); - -//-------------------------------------------------------------------------- -struct regctx_t; - -//-------------------------------------------------------------------------- -struct regctx_entry_t -{ - enum type_t - { - IVAL = 0, - FVAL = 1, - DATA = 2, - FUNC = 3, - } type; - int reg_class; - int reg_idx; - union - { - struct - { - size_t offset_in_ctx; - size_t size_in_ctx; - size_t reg_size; - }; - struct - { - void (*read_func)(const regctx_t *, regval_t *, void *); - void (*write_func)(regctx_t *, const regval_t *, void *); - void *user_data; - }; - }; - - uint64_t truncate_ival(uint64_t ival) const - { - switch ( reg_size ) - { - case 1: ival = uint8_t(ival); break; - case 2: ival = uint16_t(ival); break; - case 4: ival = uint32_t(ival); break; - } - return ival; - } - - void read(regval_t *value, const uint8_t *ptr) const - { - if ( type == regctx_entry_t::FUNC ) - { - read_func((regctx_t *) ptr, value, user_data); - } - else - { - const uint8_t *p = ptr + offset_in_ctx; - switch ( type ) - { - case regctx_entry_t::IVAL: - { - uint64_t ival = 0; - switch ( size_in_ctx ) - { - case 1: ival = *(uint8_t *)p; break; - case 2: ival = *(uint16_t *)p; break; - case 4: ival = *(uint32_t *)p; break; - case 8: ival = *(uint64_t *)p; break; - } - ival = truncate_ival(ival); - value->ival = ival; - } - break; - case regctx_entry_t::FVAL: - // TODO: for x86, the value is converted to IEEE format in - // x86_read_registers(). clean this up somehow. - memcpy(value->fval, p, size_in_ctx); - value->rvtype = RVT_FLOAT; - break; - case regctx_entry_t::DATA: - value->set_bytes(p, size_in_ctx); - break; - case regctx_entry_t::FUNC: - // never happens; makes compiler happy. - break; - } - } - } - - bool patch(uint8_t *ptr, const regval_t *value) const - { - if ( type == regctx_entry_t::FUNC ) - { - write_func((regctx_t *) ptr, value, user_data); - } - else - { - uint8_t *p = ptr + offset_in_ctx; - switch ( type ) - { - case regctx_entry_t::IVAL: - { - uint64_t ival = value->ival; - ival = truncate_ival(ival); - switch ( size_in_ctx ) - { - case 1: *(uint8_t *)p = ival; break; - case 2: *(uint16_t *)p = ival; break; - case 4: *(uint32_t *)p = ival; break; - case 8: *(uint64_t *)p = ival; break; - } - } - break; - case regctx_entry_t::FVAL: - // TODO: for x86, the value is converted from IEEE format in - // x86_write_register(). clean this up somehow. - memcpy(p, value->fval, size_in_ctx); - break; - case regctx_entry_t::DATA: - if ( value->get_data_size() != size_in_ctx ) - return false; - memcpy(p, value->get_data(), value->get_data_size()); - break; - case regctx_entry_t::FUNC: - // never happens; makes compiler happy. - break; - } - } - return true; - } -}; -DECLARE_TYPE_AS_MOVABLE(regctx_entry_t); -typedef qvector reg_ctx_entries_t; - -//-------------------------------------------------------------------------- -struct regctx_base_t -{ - dynamic_register_set_t &idaregs; // linked to debmod_t's variable of the same name - thid_t tid; - int clsmask; - - reg_ctx_entries_t entries; - - void setup(thid_t _tid, int _clsmask=0) - { - tid = _tid; - clsmask = _clsmask; - } - - void setup_reg(int dyn_reg_idx) - { - clsmask |= entries[dyn_reg_idx].reg_class; - } - - regctx_base_t(dynamic_register_set_t &_idaregs) - : idaregs(_idaregs) - { - setup(0, 0); - } - - void add_idareg(register_info_t &ri) - { - idaregs.add_register(ri.name, - ri.flags, - ri.dtype, - ri.register_class, - ri.bit_strings, - ri.default_bit_strings_mask); - } - - size_t add_entry( - regctx_entry_t::type_t type, - register_info_t &ri, - size_t offset_in_ctx, - size_t size_in_ctx, - size_t reg_size) - { - size_t dyn_reg_idx = entries.size(); - regctx_entry_t &entry = entries.push_back(); - entry.type = type; - entry.reg_class = ri.register_class; - entry.reg_idx = dyn_reg_idx; - entry.offset_in_ctx = offset_in_ctx; - entry.size_in_ctx = size_in_ctx; - entry.reg_size = reg_size; - add_idareg(ri); - return dyn_reg_idx; - } - - size_t add_ival(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx) - { - QASSERT(1797, size_in_ctx <= sizeof(regval_t::ival)); - size_t reg_size = ri.dtype == dt_word ? 2 - : ri.dtype == dt_dword ? 4 - : ri.dtype == dt_qword ? 8 - : 0; - QASSERT(1798, reg_size != 0); - return add_entry(regctx_entry_t::IVAL, ri, offset_in_ctx, size_in_ctx, reg_size); - } - - size_t add_fval(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx) - { - QASSERT(1799, size_in_ctx <= sizeof(regval_t::fval)); - return add_entry(regctx_entry_t::FVAL, ri, offset_in_ctx, size_in_ctx, size_in_ctx); - } - - size_t add_data(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx) - { - return add_entry(regctx_entry_t::DATA, ri, offset_in_ctx, size_in_ctx, size_in_ctx); - } - - size_t add_func( - register_info_t &ri, - void (*read_func)(const regctx_t *, regval_t *, void *), - void (*write_func)(regctx_t *, const regval_t *, void *), - void *user_data=nullptr) - { - size_t dyn_reg_idx = entries.size(); - regctx_entry_t &entry = entries.push_back(); - entry.type = regctx_entry_t::FUNC; - entry.reg_class = ri.register_class; - entry.reg_idx = dyn_reg_idx; - entry.read_func = read_func; - entry.write_func = write_func; - entry.user_data = user_data; - add_idareg(ri); - return dyn_reg_idx; - } - - void read_all(regval_t *values) - { - for ( const regctx_entry_t &entry: entries ) - if ( (clsmask & entry.reg_class) != 0 ) - entry.read(&values[entry.reg_idx], (const uint8_t *) this); - } - - bool patch(int dyn_reg_idx, const regval_t *value) - { - return entries[dyn_reg_idx].patch((uint8_t *) this, value); - } -}; - -//-------------------------------------------------------------------------- -// Main class to represent a debugger module -class debmod_t -{ -protected: -// processor_t &ph; - typedef std::map regval_map_t; - qvector exceptions; - name_info_t dn_names; - // Pending events. currently used only to store - // exceptions that happen while attaching - eventlist_t events; - // The last event received via a successful get_debug_event() - debug_event_t last_event; - - // debugged process attributes (may be changed after process start/attach) - debapp_attrs_t debapp_attrs; - - procvec_t proclist; - - // appcall contexts - struct call_context_t - { - regvals_t saved_regs; - ea_t sp; - ea_t ctrl_ea; - bool regs_spoiled; - call_context_t() : sp(BADADDR), ctrl_ea(BADADDR), regs_spoiled(false) {} - }; - typedef qstack call_contexts_t; - typedef std::map appcalls_t; - appcalls_t appcalls; - - int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) - { - return ::send_ioctl(rpc, fn, buf, size, poutbuf, poutsize); - } - // If an IDC error occurs: we cannot prepare an error message on the server - // side because we do not have access to error strings (they are in ida.hlp). - // We pass the error code to IDA (with eventual arguments) so it can prepare - // a nice error message for the user - void report_idc_error(ea_t ea, error_t code, ssize_t errval, const char *errprm) - { - return ::report_idc_error(rpc, ea, code, errval, errprm); - } - - typedef std::map lowcnds_t; - lowcnds_t cndmap; - eavec_t handling_lowcnds; - bool evaluate_and_handle_lowcnd(debug_event_t *event, int elc_flags=0); - bool handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags); -#define ELC_KEEP_EIP 0x0001 // do not reset eip before stepping -#define ELC_KEEP_SUSP 0x0002 // keep suspended state, do not resume after stepping - - // helper functions for programmatical single stepping - virtual drc_t dbg_perform_single_step(debug_event_t *event, const insn_t &ins); - virtual int dbg_freeze_threads_except(thid_t) { return 0; } - virtual int dbg_thaw_threads_except(thid_t) { return 0; } - drc_t resume_app_and_get_event(debug_event_t *dev); - void set_platform(const char *platform_name); - - // return number of processes, -1 - not implemented - virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf); - -public: - // initialized by dbg_init() - int debugger_flags; - meminfo_vec_t old_ranges; - rpc_engine_t *rpc; - bool debug_debugger; - // Is dynamic library? - bool is_dll; - - // indexes of sp and program counter registers. - // Must be initialized by derived classes. - int sp_idx; - int pc_idx; - - // index of frame pointer register - int fp_idx; - - // Total number of registers. - // Must be initialized by derived classes. - int nregs; - - // Breakpoint code. - // Must be initialized by derived classes. - bytevec_t bpt_code; - - qstring input_file_path; - - page_bpts_t page_bpts; - - // will either send as msg/warning/error through callui, - // or through 'rpc' if it is present. - DEFINE_ALL_NOTIFICATION_FUNCTIONS(rpc); - AS_PRINTF(3,0) static ssize_t dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va); - - bool broken_connection; - pid_t pid; - - debmodbpt_map_t bpts; - update_bpt_vec_t deleted_bpts; // deleted bpts in the last update_bpts() call - // if bpt EA was deleted then bpt raised in the same place for the - // same thread does not belong to IDA - bool is_ida_bpt(ea_t ea, thid_t tid) - { - if ( bpts.find(ea) != bpts.end() ) - return true; - update_bpt_info_t b; - b.ea = ea; - return deleted_bpts.find(b) != deleted_bpts.end() - && (last_event.eid() != BREAKPOINT - || last_event.ea != ea - || last_event.tid != tid); - } - - static bool reuse_broken_connections; - - //------------------------------------ - // Dynamic register set for debugger_t - //------------------------------------ - dynamic_register_set_t idaregs; - - //------------------------------------ - // Constructors and destructors - //------------------------------------ - debmod_t(); - virtual ~debmod_t() { cleanup(); } - - //------------------------------------ - // Debug names methods - //------------------------------------ - void clear_debug_names(); - name_info_t *get_debug_names(); - void save_debug_name(ea_t ea, const char *name); - int set_debug_names(); - int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty); - int send_debug_event_to_ida(const debug_event_t *ev, int rqflags); - ea_t find_debug_name(const char *name) const; - //------------------------------------ - // Utility methods - //------------------------------------ - void cleanup(void); - AS_PRINTF(2, 3) void debdeb(const char *format, ...); - AS_PRINTF(2, 3) bool deberr(const char *format, ...); - bool same_as_oldmemcfg(const meminfo_vec_t &ranges) const; - void save_oldmemcfg(const meminfo_vec_t &ranges); - bool continue_after_last_event(bool handled = true); - lowcnd_t *get_failed_lowcnd(thid_t tid, ea_t ea); - page_bpts_t::iterator find_page_bpt(ea_t ea, int size=1); - bool del_page_bpt(ea_t ea, bpttype_t type); - void enable_page_bpts(bool enable); - ea_t calc_page_base(ea_t ea) { return align_down(ea, dbg_memory_page_size()); } - void log_exception(const debug_event_t *ev, const exception_info_t *ei); - uint64 probe_file_size(int fn, uint64 step); - void set_input_path(const char *input_path); - int read_bpt_orgbytes(bytevec_t *buf, ea_t ea, int len); - - //------------------------------------ - // Shared methods - //------------------------------------ - virtual bool check_input_file_crc32(uint32 orig_crc); - virtual const exception_info_t *find_exception(int code); - virtual bool get_exception_name(int code, char *buf, size_t bufsize); - virtual drc_t idaapi dbg_get_processes(procinfo_vec_t *info, qstring *errbuf); - - //------------------------------------ - // Methods to be implemented - //------------------------------------ - virtual void idaapi dbg_set_debugging(bool _debug_debugger) = 0; - virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) = 0; - virtual void idaapi dbg_term(void) = 0; - virtual drc_t idaapi dbg_detach_process(void) = 0; - virtual drc_t idaapi dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) = 0; - virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_msecs) = 0; - virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) = 0; - virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) = 0; - virtual drc_t idaapi dbg_exit_process(qstring *errbuf) = 0; - virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) = 0; - virtual void idaapi dbg_set_exception_info(const exception_info_t *info, int qty); - virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) = 0; - virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) = 0; - virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) = 0; - virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) = 0; - virtual drc_t idaapi dbg_read_registers( - thid_t thread_id, - int clsmask, - regval_t *values, - qstring *errbuf) = 0; - virtual drc_t idaapi dbg_write_register( - thid_t thread_id, - int reg_idx, - const regval_t *value, - qstring *errbuf) = 0; - virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) = 0; - virtual ea_t idaapi map_address(ea_t ea, const regval_t *, int /* regnum */) { return ea; } - virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) = 0; - virtual int idaapi dbg_get_scattered_image(scattered_image_t & /*si*/, ea_t /*base*/) { return -1; } - virtual bool idaapi dbg_get_image_uuid(bytevec_t * /*uuid*/, ea_t /*base*/) { return false; } - virtual ea_t idaapi dbg_get_segm_start(ea_t /*base*/, const qstring & /*segname*/) { return BADADDR; } - virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) = 0; - virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) = 0; - virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) = 0; - // for swbpts, len may be -1 (unknown size, for example arm/thumb mode) or bpt opcode length - // dbg_add_bpt returns 2 if it adds a page bpt - virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) = 0; - virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) = 0; - virtual drc_t idaapi dbg_update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf); - virtual int idaapi dbg_add_page_bpt(bpttype_t /*type*/, ea_t /*ea*/, int /*size*/) { return 0; } - virtual bool idaapi dbg_enable_page_bpt(page_bpts_t::iterator /*p*/, bool /*enable*/) { return false; } - virtual drc_t idaapi dbg_update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf); - virtual drc_t idaapi dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf); - virtual int idaapi dbg_open_file(const char * /*file*/, uint64 * /*fsize*/, bool /*readonly*/) { return -1; } - virtual void idaapi dbg_close_file(int /*fn*/) {} - virtual ssize_t idaapi dbg_read_file(int /*fn*/, qoff64_t /*off*/, void * /*buf*/, size_t /*size*/) { return 0; } - virtual ssize_t idaapi dbg_write_file(int /*fn*/, qoff64_t /*off*/, const void * /*buf*/, size_t /*size*/) { return 0; } - virtual int idaapi handle_ioctl( - int /*fn*/, - const void * /*buf*/, - size_t /*size*/, - void ** /*outbuf*/, - ssize_t * /*outsize*/) - { - return 0; - } - virtual int idaapi get_system_specific_errno(void) const; // this code must be acceptable by winerr() - virtual drc_t idaapi dbg_update_call_stack(thid_t, call_stack_t *) { return DRC_NONE; } - virtual ea_t idaapi dbg_appcall( - ea_t /*func_ea*/, - thid_t /*tid*/, - int /*stkarg_nbytes*/, - const struct regobjs_t * /*regargs*/, - struct relobj_t * /*stkargs*/, - struct regobjs_t * /*retregs*/, - qstring *errbuf, - debug_event_t * /*event*/, - int /*flags*/); - virtual drc_t idaapi dbg_cleanup_appcall(thid_t /*tid*/); - virtual bool idaapi write_registers( - thid_t /*tid*/, - int /*start*/, - int /*count*/, - const regval_t * /*values*/) - { - return false; - } - // finalize appcall stack image - // input: stack image contains the return address at the beginning - virtual int finalize_appcall_stack(call_context_t &, regval_map_t &, bytevec_t &) { return 0; } - virtual ea_t calc_appcall_stack(const regvals_t ®vals); - virtual bool should_stop_appcall(thid_t tid, const debug_event_t *event, ea_t ea); - virtual bool should_suspend_at_exception(const debug_event_t *event, const exception_info_t *ei); - virtual bool preprocess_appcall_cleanup(thid_t, call_context_t &) { return true; } - virtual int get_regidx(const char *regname, int *clsmask) = 0; - virtual uint32 dbg_memory_page_size(void) { return 0x1000; } - virtual bool idaapi dbg_prepare_broken_connection(void) { return false; } - virtual bool idaapi dbg_continue_broken_connection(pid_t) { old_ranges.clear(); return true; } - virtual bool idaapi dbg_enable_trace(thid_t, bool, int) { return false; } - virtual bool idaapi dbg_is_tracing_enabled(thid_t, int) { return false; } - virtual int idaapi dbg_rexec(const char *cmdline); - virtual void adjust_swbpt(ea_t *, int *) {}; - virtual void dbg_get_debapp_attrs(debapp_attrs_t *out_pattrs) const; - virtual bool idaapi dbg_get_srcinfo_path(qstring * /*path*/, ea_t /*base*/) const { return false; } - virtual bool import_dll(const import_request_t & /*req*/) { return false; } - virtual drc_t idaapi dbg_bin_search( - ea_t *ea, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &ptns, - int srch_flags, - qstring *errbuf); - - bool restore_broken_breakpoints(void); - void set_addr_size(int size) { debapp_attrs.addrsize = size; } - void set_endianness(bool is_be) { debapp_attrs.is_be = is_be; } -}; - -//--------------------------------------------------------------------------- - -// -// Some functions, per OS implemented -// -bool init_subsystem(); -bool term_subsystem(); -debmod_t *create_debug_session(void *params); - -// -// Processor specific init/term -// -void processor_specific_init(void); -void processor_specific_term(void); - -// Perform an action on all existing debugger modules -struct debmod_visitor_t -{ - virtual int visit(debmod_t *debmod) = 0; -}; -int for_all_debuggers(debmod_visitor_t &v); - - -// -// Utility functions -// - -// Common method between MacOS and Linux to launch a process -drc_t idaapi maclnx_launch_process( - debmod_t *debmod, - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - void **child_pid, - qstring *errbuf); - -bool add_idc_funcs(const struct ext_idcfunc_t funcs[], size_t nfuncs, bool reg); - -// -// Externs -// -extern debmod_t *idc_debmod; -extern thid_t idc_thread; -extern bool ignore_sigint; - -//--------------------------------------------------------------------------- -// server.cpp -bool lock_begin(); -bool lock_end(); - -// bool srv_lock_begin(void); -// bool srv_lock_end(void); - -#endif diff --git a/idasdk75/dbg/linux/linux_debmod.cpp b/idasdk75/dbg/linux/linux_debmod.cpp deleted file mode 100644 index b9e2ac3..0000000 --- a/idasdk75/dbg/linux/linux_debmod.cpp +++ /dev/null @@ -1,3690 +0,0 @@ -/* -* This is a userland linux debugger module -* -* Functions unique for Linux -* -* It can be compiled by gcc -* -*/ - -//#define LDEB // enable debug print in this module - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "symelf.hpp" -#include "linux_debmod.h" - -#ifdef __ANDROID__ -# include -# include "android.hpp" -# include "android.cpp" -#else -# include -#endif - -//-------------------------------------------------------------------------- -// Load IDA register sets. -#ifdef __ARM__ -# include "arm_regs.hpp" -# define arch_registers arm_registers -#else -# include "pc_regs.hpp" -# define arch_registers x86_registers -#endif - -//-------------------------------------------------------------------------- -// Define some ptrace() requests if they're not available. -#ifndef PTRACE_GETREGSET -# define PTRACE_GETREGSET __ptrace_request(0x4204) -# define PTRACE_SETREGSET __ptrace_request(0x4205) -#endif - -#ifdef __HAVE_ARM_VFP__ -# ifndef PTRACE_GETVFPREGS -# define PTRACE_GETVFPREGS __ptrace_request(27) -# define PTRACE_SETVFPREGS __ptrace_request(28) -# endif -#endif - -#if !defined(__ARM__) && !defined(__X86__) && !defined(PTRACE_ARCH_PRCTL) -# define PTRACE_ARCH_PRCTL __ptrace_request(30) -#endif - -//-------------------------------------------------------------------------- -// ARM breakpoint codes. -#ifdef __ARM__ -static const uchar thumb16_bpt[] = { 0x10, 0xDE }; // UND #10 -// we must use 32-bit breakpoints for 32bit instructions inside IT blocks (thumb mode) -// if we use a 16-bit breakpoint and the processor decides to skip it -// because the condition codes are not satisfied, we will end up skipping -// only half of the original 32-bit instruction -static const uchar thumb32_bpt[] = { 0xF0, 0xF7, 0x00, 0xA0 }; -// This bit is combined with the software bpt size to indicate -// that 32bit bpt code should be used. -#define USE_THUMB32_BPT 0x80 -static const uchar aarch64_bpt[] = AARCH64_BPT_CODE; -#endif - -//-------------------------------------------------------------------------- -#if defined(__HAVE_ARM_VFP__) && !defined(__ANDROID__) -struct user_vfp -{ - int64 fpregs[32]; - int32 fpscr; -}; -#endif - -//-------------------------------------------------------------------------- -#ifdef __ARM__ -# if defined(__X86__) -# define user_regs_struct user_regs -# define PCREG uregs[15] -# else // arm64 -# define user_regs_struct user_pt_regs -# define LRREG_IDX 30 -# endif -#else // __ARM__ -# if defined(__X86__) -# define SPREG esp -# define PCREG eip -# define XMM_STRUCT x387 -# define TAGS_REG twd -# define INTEL_REG(reg) e##reg -# define INTEL_SREG(reg) x##reg -# else // x64 -# define SPREG rsp -# define PCREG rip -# define XMM_STRUCT i387 -# define TAGS_REG ftw -# define INTEL_REG(reg) r##reg -# define INTEL_SREG(reg) reg -# endif -#endif - -//-------------------------------------------------------------------------- -#ifdef TESTABLE_BUILD -typedef const char *per_pid_elf_dbgdir_resolver_t(int pid); -static per_pid_elf_dbgdir_resolver_t *per_pid_elf_dbgdir_resolver = nullptr; -#endif - -//-------------------------------------------------------------------------- -// ptrace() uses long as part of its API and we want to use that, so we -// tell lint to ignore it. -//lint -esym(970,long) use of modifier or type 'long' outside of a typedef - -//-------------------------------------------------------------------------- -linux_debmod_t::linux_debmod_t(void) : - ta(nullptr), - complained_shlib_bpt(false), - process_handle(INVALID_HANDLE_VALUE), - thread_handle(INVALID_HANDLE_VALUE), - exited(false), - mapfp(nullptr), - npending_signals(0), - may_run(false), - requested_to_suspend(false), - in_event(false), - nptl_base(BADADDR), - reg_ctx(nullptr) -{ - prochandle.pid = NO_PROCESS; - set_platform("linux"); -} - -#pragma GCC diagnostic ignored "-Wswitch" // case values do not belong to... - -#ifdef LDEB -//-------------------------------------------------------------------------- -const char *get_ptrace_name(__ptrace_request request) -{ - switch ( request ) - { - case PTRACE_TRACEME: return "PTRACE_TRACEME"; /* Indicate that the process making this request should be traced. - All signals received by this process can be intercepted by its - parent, and its parent can use the other `ptrace' requests. */ - case PTRACE_PEEKTEXT: return "PTRACE_PEEKTEXT"; /* Return the word in the process's text space at address ADDR. */ - case PTRACE_PEEKDATA: return "PTRACE_PEEKDATA"; /* Return the word in the process's data space at address ADDR. */ - case PTRACE_PEEKUSER: return "PTRACE_PEEKUSER"; /* Return the word in the process's user area at offset ADDR. */ - case PTRACE_POKETEXT: return "PTRACE_POKETEXT"; /* Write the word DATA into the process's text space at address ADDR. */ - case PTRACE_POKEDATA: return "PTRACE_POKEDATA"; /* Write the word DATA into the process's data space at address ADDR. */ - case PTRACE_POKEUSER: return "PTRACE_POKEUSER"; /* Write the word DATA into the process's user area at offset ADDR. */ - case PTRACE_CONT: return "PTRACE_CONT"; /* Continue the process. */ - case PTRACE_KILL: return "PTRACE_KILL"; /* Kill the process. */ - case PTRACE_SINGLESTEP: return "PTRACE_SINGLESTEP"; /* Single step the process. This is not supported on all machines. */ -#if !defined(__ARM__) || defined(__X86__) - case PTRACE_GETREGS: return "PTRACE_GETREGS"; /* Get all general purpose registers used by a processes. This is not supported on all machines. */ - case PTRACE_SETREGS: return "PTRACE_SETREGS"; /* Set all general purpose registers used by a processes. This is not supported on all machines. */ - case PTRACE_GETFPREGS: return "PTRACE_GETFPREGS"; /* Get all floating point registers used by a processes. This is not supported on all machines. */ - case PTRACE_SETFPREGS: return "PTRACE_SETFPREGS"; /* Set all floating point registers used by a processes. This is not supported on all machines. */ -#endif - case PTRACE_ATTACH: return "PTRACE_ATTACH"; /* Attach to a process that is already running. */ - case PTRACE_DETACH: return "PTRACE_DETACH"; /* Detach from a process attached to with PTRACE_ATTACH. */ -#if !defined(__ARM__) - case PTRACE_GETFPXREGS: return "PTRACE_GETFPXREGS"; /* Get all extended floating point registers used by a processes. This is not supported on all machines. */ - case PTRACE_SETFPXREGS: return "PTRACE_SETFPXREGS"; /* Set all extended floating point registers used by a processes. This is not supported on all machines. */ -#endif - case PTRACE_SYSCALL: return "PTRACE_SYSCALL"; /* Continue and stop at the next (return from) syscall. */ -#if defined(__ARM__) && defined(__X86__) - case PTRACE_GETVFPREGS: return "PTRACE_GETVFPREGS"; /* Get all vfp registers used by a processes. This is not supported on all machines. */ - case PTRACE_SETVFPREGS: return "PTRACE_SETVFPREGS"; /* Set all vfp registers used by a processes. This is not supported on all machines. */ -#endif - case PTRACE_SETOPTIONS: return "PTRACE_SETOPTIONS"; /* Set ptrace filter options. */ - case PTRACE_GETEVENTMSG: return "PTRACE_GETEVENTMSG"; /* Get last ptrace message. */ - case PTRACE_GETSIGINFO: return "PTRACE_GETSIGINFO"; /* Get siginfo for process. */ - case PTRACE_SETSIGINFO: return "PTRACE_SETSIGINFO"; /* Set new siginfo for process. */ - case PTRACE_GETREGSET: return "PTRACE_GETREGSET"; /* Get register content. */ - case PTRACE_SETREGSET: return "PTRACE_SETREGSET"; /* Set register content. */ -#ifdef PTRACE_SEIZE - case PTRACE_SEIZE: return "PTRACE_SEIZE"; /* Like PTRACE_ATTACH, but do not force tracee to trap and do not affect signal or group stop state. */ - case PTRACE_INTERRUPT: return "PTRACE_INTERRUPT"; /* Trap seized tracee. */ - case PTRACE_LISTEN: return "PTRACE_LISTEN"; /* Wait for next group event. */ - case PTRACE_PEEKSIGINFO: return "PTRACE_PEEKSIGINFO"; /* Wait for next group event. */ - case PTRACE_GETSIGMASK: return "PTRACE_GETSIGMASK"; /* Wait for next group event. */ - case PTRACE_SETSIGMASK: return "PTRACE_SETSIGMASK"; /* Wait for next group event. */ -#endif -#if !defined(__ARM__) && !defined(__X86__) - case PTRACE_ARCH_PRCTL: return "PTRACE_ARCH_PRCTL"; //lint !e2444 case value is not in enumeration -#endif - default: - static char buf[MAXSTR]; - qsnprintf(buf, sizeof(buf), "%d", request); - return buf; - } -} -#endif - -//-------------------------------------------------------------------------- -// fixme: can we use peeksize_t instead? -static long qptrace(__ptrace_request request, pid_t pid, void *addr, void *data) -{ - long code = ptrace(request, pid, addr, data); -#ifdef LDEB - if ( request != PTRACE_PEEKTEXT - && request != PTRACE_PEEKUSER - && (request != PTRACE_POKETEXT - && request != PTRACE_POKEDATA -#if !defined(__ARM__) || defined(__X86__) - && request != PTRACE_GETREGS - && request != PTRACE_SETREGS - && request != PTRACE_GETFPREGS - && request != PTRACE_SETFPREGS -#endif -#if defined(__ARM__) && defined(__X86__) - && request != PTRACE_GETVFPREGS - && request != PTRACE_SETVFPREGS -#endif -#if !defined(__ARM__) - && request != PTRACE_SETFPXREGS - && request != PTRACE_GETFPXREGS -#endif - || code != 0) ) - { -// int saved_errno = errno; -// msg("%s(%u, 0x%X, 0x%X) => 0x%X\n", get_ptrace_name(request), pid, addr, data, code); -// errno = saved_errno; - } -#endif - return code; -} - -//-------------------------------------------------------------------------- -#ifdef LDEB -GCC_DIAG_OFF(format-nonliteral); -void linux_debmod_t::log(thid_t tid, const char *format, ...) -{ - if ( tid != -1 ) - { - thread_info_t *thif = get_thread(tid); - if ( thif == NULL ) - { - msg(" %d: ** missing **\n", tid); - } - else - { - const char *name = "?"; - switch ( thif->state ) - { - case RUNNING: name = "RUN "; break; - case STOPPED: name = "STOP"; break; - case DYING: name = "DYIN"; break; - case DEAD: name = "DEAD"; break; - } - msg(" %d: %s %c%c S=%d U=%d ", - thif->tid, - name, - thif->waiting_sigstop ? 'W' : ' ', - thif->got_pending_status ? 'P' : ' ', - thif->suspend_count, - thif->user_suspend); - } - } - va_list va; - va_start(va, format); - vmsg(format, va); - va_end(va); -} - -static const char *strevent(int status) -{ - int event = status >> 16; - if ( WIFSTOPPED(status) - && WSTOPSIG(status) == SIGTRAP - && event != 0 ) - { - switch ( event ) - { - case PTRACE_EVENT_FORK: - return " event=PTRACE_EVENT_FORK"; - case PTRACE_EVENT_VFORK: - return " event=PTRACE_EVENT_VFORK"; - case PTRACE_EVENT_CLONE: - return " event=PTRACE_EVENT_CLONE"; - case PTRACE_EVENT_EXEC: - return " event=PTRACE_EVENT_EXEC"; - case PTRACE_EVENT_VFORK_DONE: - return " event=PTRACE_EVENT_VFORK_DONE"; - case PTRACE_EVENT_EXIT: - return " event=PTRACE_EVENT_EXIT"; - default: - return " UNKNOWN event"; - } - } - return ""; -} - -static char *status_dstr(int status) -{ - static char buf[80]; - if ( WIFSTOPPED(status) ) - { - int sig = WSTOPSIG(status); - ::qsnprintf(buf, sizeof(buf), "stopped(%s)%s", strsignal(sig), strevent(status)); - } - else if ( WIFSIGNALED(status) ) - { - int sig = WTERMSIG(status); - ::qsnprintf(buf, sizeof(buf), "terminated(%s)", strsignal(sig)); - } - else if ( WIFEXITED(status) ) - { - int code = WEXITSTATUS(status); - ::qsnprintf(buf, sizeof(buf), "exited(%d)", code); - } - else - { - ::qsnprintf(buf, sizeof(buf), "status=%x\n", status); - } - return buf; -} - -static void ldeb(const char *format, ...) -{ - va_list va; - va_start(va, format); - vmsg(format, va); - va_end(va); -} -GCC_DIAG_OFF(format-nonliteral); - -#else -//lint -estring(750,status_dstr, strevent) not referenced -#define log(tid, format, args...) -#define ldeb(format, args...) do {} while ( 0 ) -#define status_dstr(status) "?" -#define strevent(status) "" -#endif - -//-------------------------------------------------------------------------- -static int qkill(int pid, int signo) -{ - ldeb("%d: sending signal %s\n", pid, signo == SIGSTOP ? "SIGSTOP" - : signo == SIGKILL ? "SIGKILL" : ""); - int ret; - errno = 0; - static bool tkill_failed = false; - if ( !tkill_failed ) - { - ret = syscall(__NR_tkill, pid, signo); - if ( ret != 0 && errno == ENOSYS ) - { - errno = 0; - tkill_failed = true; - } - } - if ( tkill_failed ) - ret = kill(pid, signo); - if ( ret != 0 ) - ldeb(" %s\n", strerror(errno)); - return ret; -} - -//-------------------------------------------------------------------------- -inline thread_info_t *linux_debmod_t::get_thread(thid_t tid) -{ - threads_t::iterator p = threads.find(tid); - if ( p == threads.end() ) - return NULL; - return &p->second; -} - -#define X86_XSTATE_SSE_SIZE 576 -// #define X86_XSTATE_AVX_SIZE 832 -// #define X86_XSTATE_BNDREGS_SIZE 1024 -// #define X86_XSTATE_BNDCFG_SIZE 1088 -// #define X86_XSTATE_AVX512_SIZE 2688 -// #define X86_XSTATE_PKRU_SIZE 2696 -#define X86_XSTATE_MAX_SIZE 2696 - -//------------------------------------------------------------------------- -static int _has_ptrace_getregset = -1; -static bool has_ptrace_getregset(thid_t tid) -{ - if ( _has_ptrace_getregset < 0 ) - { -#if defined(__ARM__) - uint8_t xstateregs[sizeof(struct user_regs_struct)]; -# define _TEST_PTRACE_OP NT_PRSTATUS -#else - uint8_t xstateregs[X86_XSTATE_SSE_SIZE]; -# define _TEST_PTRACE_OP NT_X86_XSTATE -#endif - struct iovec iov; - iov.iov_base = xstateregs; - iov.iov_len = sizeof(xstateregs); - _has_ptrace_getregset = qptrace(PTRACE_GETREGSET, tid, (void *) _TEST_PTRACE_OP, &iov) == 0; -#undef _TEST_PTRACE_OP - } - return _has_ptrace_getregset > 0; -} - -//------------------------------------------------------------------------- -inline bool qptrace_get_regset(struct iovec *out, size_t what, thid_t tid) -{ - if ( !has_ptrace_getregset(tid) ) - return false; - return qptrace(PTRACE_GETREGSET, tid, (void *) what, out) == 0; -} - -//------------------------------------------------------------------------- -inline bool qptrace_get_regset(void *out, size_t outsz, size_t what, thid_t tid) -{ - struct iovec iov = { out, outsz }; - return qptrace_get_regset(&iov, what, tid); -} - -//------------------------------------------------------------------------- -inline bool qptrace_set_regset(size_t what, thid_t tid, struct iovec &iov) -{ - // we'll assume that if a platform exposes 'PTRACE_GETREGSET' - // it also exposes 'PTRACE_SETREGSET'. - if ( !has_ptrace_getregset(tid) ) - return false; - return qptrace(PTRACE_SETREGSET, tid, (void *) what, &iov) == 0; -} - -//------------------------------------------------------------------------- -inline bool qptrace_set_regset(size_t what, thid_t tid, void *in, size_t insz) -{ - struct iovec iov = { in, insz }; - return qptrace_set_regset(what, tid, iov); -} - -//-------------------------------------------------------------------------- -#if defined(__ARM__) && !defined(__X86__) -inline bool qptrace_get_prstatus(struct user_regs_struct *regset, thid_t tid) -{ - return qptrace_get_regset(regset, sizeof(struct user_regs_struct), NT_PRSTATUS, tid); -} -#endif - -//-------------------------------------------------------------------------- -static ea_t get_ip(thid_t tid) -{ - ea_t ea; -#if defined(__ARM__) && !defined(__X86__) - struct user_regs_struct regset; - ea = qptrace_get_prstatus(®set, tid) ? regset.pc : BADADDR; -#else - const size_t pcreg_off = qoffsetof(user, regs) + qoffsetof(user_regs_struct, PCREG); - // In case 64bit IDA (__EA64__=1) is debugging a 32bit process: - // - size of ea_t is 64 bit - // - qptrace() returns a 32bit long value - // Here we cast the return value to unsigned long to prevent - // extending of the sign bit when convert 32bit long value to 64bit ea_t - ea = (unsigned long)qptrace(PTRACE_PEEKUSER, tid, (void *)pcreg_off, 0); -#endif - return ea; -} - -#include "linux_threads.cpp" - -//-------------------------------------------------------------------------- -#ifndef __ARM__ -static unsigned long get_dr(thid_t tid, int idx) -{ - uchar *offset = (uchar *)qoffsetof(user, u_debugreg) + idx*sizeof(unsigned long int); - unsigned long value = qptrace(PTRACE_PEEKUSER, tid, (void *)offset, 0); - // msg("dr%d => %a\n", idx, value); - return value; -} - -//-------------------------------------------------------------------------- -static bool set_dr(thid_t tid, int idx, ea_t ea) -{ - uchar *offset = (uchar *)qoffsetof(user, u_debugreg) + idx*sizeof(unsigned long int); - - if ( ea == BADADDR ) - ea = 0; // linux does not accept too high values - unsigned long value = ea; - // msg("dr%d <= %a\n", idx, value); - return qptrace(PTRACE_POKEUSER, tid, offset, (void *)value) == 0; -} -#endif - -//-------------------------------------------------------------------------- -bool linux_debmod_t::del_pending_event(event_id_t id, const char *module_name) -{ - for ( eventlist_t::iterator p=events.begin(); p != events.end(); ++p ) - { - if ( p->eid() == id && p->modinfo().name == module_name ) - { - events.erase(p); - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::enqueue_event(const debug_event_t &ev, queue_pos_t pos) -{ - if ( ev.eid() != NO_EVENT ) - { - events.enqueue(ev, pos); - may_run = false; - ldeb("enqueued event, may not run!\n"); - } -} - -//-------------------------------------------------------------------------- -static inline void resume_dying_thread(int tid, int) -{ - qptrace(PTRACE_CONT, tid, 0, (void *)0); -} - -//-------------------------------------------------------------------------- -// we got a signal that does not belong to our thread. find the target thread -// and store the signal there -void linux_debmod_t::store_pending_signal(int _pid, int status) -{ - struct ida_local linux_signal_storer_t : public debmod_visitor_t - { - int pid; - int status; - linux_signal_storer_t(int p, int s) : pid(p), status(s) {} - virtual int visit(debmod_t *debmod) override - { - linux_debmod_t *ld = (linux_debmod_t *)debmod; - threads_t::iterator p = ld->threads.find(pid); - if ( p != ld->threads.end() ) - { - thread_info_t &ti = p->second; - // normally we should not receive a new signal unless the process or the thread - // exited. the exit signals may occur even if there is a pending signal. - QASSERT(30185, !ti.got_pending_status || ld->exited || WIFEXITED(status)); - if ( ti.waiting_sigstop && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP ) - { - ti.waiting_sigstop = false; - ld->set_thread_state(ti, STOPPED); - } - else - { - ti.got_pending_status = true; - ti.pending_status = status; - ld->npending_signals++; - } - return 1; // stop - } - else - { - // we are handling an event from a thread we recently removed, ignore this - if ( ld->deleted_threads.has(pid) ) - { - // do not store the signal but resume the thread and let it finish - resume_dying_thread(pid, status); - return 1; - } - } - - return 0; // continue - } - }; - linux_signal_storer_t lss(_pid, status); - if ( !for_all_debuggers(lss) ) // uses lock_begin(), lock_end() to protect common data - { - if ( WIFSTOPPED(status) ) - { - // we can get SIGSTOP for the new-born lwp before the parent get it - // store pid to mark that we should not wait for SIGSTOP anymore - seen_threads.push_back(_pid); - } - else if ( !WIFSIGNALED(status) ) - { - // maybe it comes from a zombie? - // if we terminate the process, there might be some zombie threads remaining(?) - msg(" %d: failed to store pending status %x, killing unknown thread\n", _pid, status); - qptrace(PTRACE_KILL, _pid, 0, 0); - } - } -} - -//-------------------------------------------------------------------------- -inline bool is_bpt_status(int status) -{ - if ( !WIFSTOPPED(status) ) - return false; - int sig = WSTOPSIG(status); -#ifdef __ARM__ - return sig == SIGTRAP || sig == SIGILL; -#else - return sig == SIGTRAP; -#endif -} - -//-------------------------------------------------------------------------- -// check if there are any pending signals for our process -bool linux_debmod_t::retrieve_pending_signal(pid_t *p_pid, int *status) -{ - if ( npending_signals == 0 ) - return false; - - lock_begin(); - - // try to stick to the same thread as before - threads_t::iterator p = threads.find(last_event.tid); - if ( p != threads.end() ) - { - thread_info_t &ti = p->second; - if ( !ti.got_pending_status || ti.user_suspend > 0 || ti.suspend_count > 0 ) - p = threads.end(); - } - - // find a thread with a signal. - if ( p == threads.end() ) - { - for ( int i=0; i < 3; i++ ) - { - for ( p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - if ( ti.user_suspend > 0 || ti.suspend_count > 0 ) - continue; - if ( ti.got_pending_status ) - { - // signal priorities: STEP, SIGTRAP, others - if ( i == 0 ) - { - if ( !ti.single_step ) - continue; - } - else if ( i == 1 ) - { - if ( !is_bpt_status(ti.pending_status) ) - continue; - } - break; - } - } - } - } - - bool got_pending_signal = false; - if ( p != threads.end() ) - { - *p_pid = p->first; - *status = p->second.pending_status; - p->second.got_pending_status = false; - got_pending_signal = true; - npending_signals--; - QASSERT(30186, npending_signals >= 0); - ldeb("-------------------------------\n"); - log(p->first, "qwait (pending signal): %s (may_run=%d)\n", status_dstr(*status), may_run); - } - lock_end(); - return got_pending_signal; -} - -//-------------------------------------------------------------------------- -// read a zero terminated string. try to avoid reading unreadable memory -bool linux_debmod_t::read_asciiz(tid_t tid, ea_t ea, char *buf, size_t bufsize, bool suspend) -{ - while ( bufsize > 0 ) - { - int pagerest = 4096 - (ea % 4096); // number of bytes remaining on the page - int nread = qmin(pagerest, bufsize); - if ( !suspend && nread > 128 ) - nread = 128; // most paths are short, try to read only 128 bytes - nread = _read_memory(tid, ea, buf, nread, suspend); - if ( nread < 0 ) - return false; // failed - - // did we read a zero byte? - for ( int i=0; i < nread; i++ ) - if ( buf[i] == '\0' ) - return true; - - ea += nread; - buf += nread; - bufsize -= nread; - } - return true; // odd, we did not find any zero byte. should we report success? -} - -//-------------------------------------------------------------------------- -// may add/del threads! -bool linux_debmod_t::gen_library_events(int /*tid*/) -{ - int s = events.size(); - meminfo_vec_t miv; - if ( get_memory_info(miv, false) == 1 ) - handle_dll_movements(miv); - return events.size() != s; -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::handle_hwbpt(debug_event_t *event) -{ -#ifdef __ARM__ - qnotused(event); -#else - - uint32 dr6_value = get_dr(event->tid, 6); - for ( int i=0; i < MAX_BPT; i++ ) - { - if ( dr6_value & (1<tid, i) ) - { - bptaddr_t &addr = event->set_bpt(); - addr.hea = hwbpt_ea[i]; - addr.kea = BADADDR; - set_dr(event->tid, 6, 0); // Clear the status bits - return true; - } - } - } -#endif - return false; -} - -//-------------------------------------------------------------------------- -inline ea_t calc_bpt_event_ea(const debug_event_t *event) -{ -#ifdef __ARM__ - if ( event->exc().code == SIGTRAP || event->exc().code == SIGILL ) - return event->ea; -#else - if ( event->exc().code == SIGTRAP ) -// || event->exc().code == SIGSEGV ) // NB: there was a bug in linux 2.6.10 when int3 was reported as SIGSEGV instead of SIGTRAP - { - return event->ea - 1; // x86 reports the address after the bpt - } -#endif - return BADADDR; -} - -//-------------------------------------------------------------------------- -inline void linux_debmod_t::set_thread_state(thread_info_t &ti, thstate_t state) const -{ - ti.state = state; -} - -//-------------------------------------------------------------------------- -static __inline void clear_tbit(thid_t tid) -{ -#ifdef __ARM__ - qnotused(tid); - return; -#else - - struct user_regs_struct regs; - if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) - { - msg("clear_tbit: error reading registers for thread %d\n", tid); - return; - } - - if ( (regs.eflags & 0x100) != 0 ) - { - regs.eflags &= ~0x100; - if ( qptrace(PTRACE_SETREGS, tid, 0, ®s) != 0 ) - msg("clear_tbit: error writting registers for thread %d\n", tid); - } - -#endif -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::check_for_new_events(chk_signal_info_t *csi, bool *event_prepared) -{ - if ( event_prepared != NULL ) - *event_prepared = false; - - while ( true ) - { - // even if we have pending events, check for new events first. - // this improves multithreaded debugging experience because - // we stick to the same thread (hopefully a new event arrives fast enough - // if we are single stepping). if we first check pending events, - // the user will be constantly switched from one thread to another. - csi->pid = check_for_signal(&csi->status, -1, 0); - if ( csi->pid <= 0 ) - { // no new events, do we have any pending events? - if ( retrieve_pending_signal(&csi->pid, &csi->status) ) - { - // check for extended event, - // if any the debugger event can be prepared - handle_extended_wait(event_prepared, *csi); - break; - } - // if the timeout was zero, nothing else to do - if ( csi->timeout_ms == 0 ) - return false; - // ok, we will wait for new events for a while - csi->pid = check_for_signal(&csi->status, -1, csi->timeout_ms); - if ( csi->pid <= 0 ) - return false; - } - ldeb("-------------------------------\n"); - log(csi->pid, " => qwait: %s\n", status_dstr(csi->status)); - - // check for extended event, - // if any the debugger event can be prepared - handle_extended_wait(event_prepared, *csi); - - if ( threads.find(csi->pid) != threads.end() ) - break; - - // when an application creates many short living threads we may receive events - // from a thread we already removed so, do not store this pending signal, just - // ignore it - if ( !deleted_threads.has(csi->pid) ) - { - // we are not interested in this pid - log(csi->pid, "storing status %d\n", csi->status); - store_pending_signal(csi->pid, csi->status); - } - else - { - // do not store the signal but resume the thread and let it finish - resume_dying_thread(csi->pid, csi->status); - } - csi->timeout_ms = 0; - } - return true; -} - -//-------------------------------------------------------------------------- -// timeout in microseconds -// 0 - no timeout, return immediately -// -1 - wait forever -// returns: 1-ok, 0-failed -int linux_debmod_t::get_debug_event(debug_event_t *event, int timeout_ms) -{ - chk_signal_info_t csi(timeout_ms); - - // even if we have pending events, check for new events first. - bool event_ready = false; - if ( !check_for_new_events(&csi, &event_ready) ) - return false; - - pid_t tid = csi.pid; - int status = csi.status; - - thread_info_t *thif = get_thread(tid); - if ( thif == NULL ) - { - // not our thread?! - debdeb("EVENT FOR UNKNOWN THREAD %d, IGNORED...\n", tid); - size_t sig = WIFSTOPPED(status) ? WSTOPSIG(status) : 0; - qptrace(PTRACE_CONT, tid, 0, (void*)(sig)); - return false; - } - QASSERT(30057, thif->state != STOPPED || exited || WIFEXITED(status) || WIFSIGNALED(status)); - - event->tid = NO_EVENT; // start with empty event - - // if there was a pending event, it means that previously we did not resume - // any threads, all of them are suspended - set_thread_state(*thif, STOPPED); - - dbg_freeze_threads(NO_THREAD); - may_run = false; - - // debugger event could be prepared during the check_for_new_events - if ( event_ready ) - goto EVENT_READY; // report empty event to get called back immediately - - // dbg_freeze_threads may delete some threads and render our 'thif' pointer invalid - thif = get_thread(tid); - if ( thif == NULL ) - { - debdeb("thread %d disappeared after freezing?!...\n", tid); - goto EVENT_READY; // report empty event to get called back immediately - } - - event->pid = process_handle; - event->tid = tid; - if ( exited ) - { - event->ea = BADADDR; - } - else if ( WIFSIGNALED(status) ) - { - siginfo_t info; - qptrace(PTRACE_GETSIGINFO, tid, NULL, &info); - event->ea = (ea_t)(size_t)info.si_addr; - } - else - { - event->ea = get_ip(event->tid); - } - event->handled = false; - if ( WIFSTOPPED(status) ) - { - ea_t proc_ip; - bool suspend; - const exception_info_t *ei; - int code = WSTOPSIG(status); - excinfo_t &exc = event->set_exception(); - exc.code = code; - exc.can_cont = true; - exc.ea = BADADDR; - if ( code == SIGSTOP ) - { - if ( thif->waiting_sigstop ) - { - log(tid, "got pending SIGSTOP!\n"); - thif->waiting_sigstop = false; - goto RESUME; // silently resume the application - } - // convert SIGSTOP into simple PROCESS_SUSPENDED, this will avoid - // a dialog box about the signal. I'm not sure that this is a good thing - // (probably better to report exceptions in the output windows rather than - // in dialog boxes), so I'll comment it out for the moment. - //event->eid = PROCESS_SUSPENDED; - } - - ei = find_exception(code); - if ( ei != NULL ) - { - exc.info.sprnt("got %s signal (%s)", ei->name.c_str(), ei->desc.c_str()); - suspend = should_suspend_at_exception(event, ei); - if ( !suspend && ei->handle() ) - code = 0; // mask the signal - } - else - { - exc.info.sprnt("got unknown signal #%d", code); - suspend = true; - } - proc_ip = calc_bpt_event_ea(event); // if bpt, calc its address from event->ea - if ( proc_ip != BADADDR ) - { // this looks like a bpt-related exception. it occurred either because - // of our bpt either it was generated by the app. - // by default, reset the code so we don't send any SIGTRAP signal to the debugged - // process *except* in the case where the program generated the signal by - // itself - code = 0; - if ( proc_ip == shlib_bpt.bpt_addr && shlib_bpt.bpt_addr != 0 ) - { - log(tid, "got shlib bpt %a\n", proc_ip); - // emulate return from function - if ( !emulate_retn(tid) ) - { - msg("%a: could not return from the shlib breakpoint!\n", proc_ip); - return true; - } - if ( !gen_library_events(tid) ) // something has changed in shared libraries? - { // no, nothing has changed - log(tid, "nothing has changed in dlls\n"); -RESUME: - if ( !requested_to_suspend && !in_event ) - { - ldeb("autoresuming\n"); -// QASSERT(30177, thif->state == STOPPED); - resume_app(NO_THREAD); - return false; - } - log(tid, "app may not run, keeping it suspended (%s)\n", - requested_to_suspend ? "requested_to_suspend" : - in_event ? "in_event" : "has_pending_events"); - event->set_eid(PROCESS_SUSPENDED); - return true; - } - log(tid, "gen_library_events ok\n"); - event->set_eid(NO_EVENT); - } - else if ( (proc_ip == birth_bpt.bpt_addr && birth_bpt.bpt_addr != 0) - || (proc_ip == death_bpt.bpt_addr && death_bpt.bpt_addr != 0) ) - { - log(tid, "got thread bpt %a (%s)\n", proc_ip, proc_ip == birth_bpt.bpt_addr ? "birth" : "death"); - size_t s = events.size(); - thread_handle = tid; // for ps_pdread - // NB! if we don't do this, some running threads can interfere with thread_db - tdb_handle_messages(tid); - // emulate return from function - if ( !emulate_retn(tid) ) - { - msg("%a: could not return from the thread breakpoint!\n", proc_ip); - return true; - } - if ( s == events.size() ) - { - log(tid, "resuming after thread_bpt\n"); - goto RESUME; - } - event->set_eid(NO_EVENT); - } - else - { - // according to the requirement of commdbg a LIB_LOADED event - // should not be reported with the same thread/IP immediately after - // a BPT-related event (see idd.hpp) - // Here we put to the queue all already loaded (but not reported) - // libraries to be sent _before_ BPT (do it only if ELF interpreter - // is not yet loaded, otherwise LIB_LOADED events will be generated - // by shlib_bpt and thus they cannot conflict with regular BPTs - if ( interp.empty() ) - { - gen_library_events(tid); - thif = get_thread(tid); - } - if ( !handle_hwbpt(event) ) - { - if ( bpts.find(proc_ip) != bpts.end() - && !handling_lowcnds.has(proc_ip) ) - { - bptaddr_t &bpta = event->set_bpt(); - bpta.hea = BADADDR; - bpta.kea = BADADDR; - event->ea = proc_ip; - } - else if ( thif != NULL && thif->single_step ) - { - event->set_eid(STEP); - } - else - { - // in case of unknown breakpoints (icebp, int3, etc...) we must remember the signal - // unless it should be masked - if ( ei == NULL || !ei->handle() ) - code = event->exc().code; - } - } - } - } - thif = get_thread(tid); - if ( thif == NULL ) - goto EVENT_READY; // report empty event to get called back immediately - thif->child_signum = code; - if ( !requested_to_suspend && evaluate_and_handle_lowcnd(event) ) - return false; - if ( !suspend && event->eid() == EXCEPTION ) - { - log_exception(event, ei); - log(tid, "resuming after exception %d\n", code); - goto RESUME; - } - } - else - { - int exit_code; - if ( WIFSIGNALED(status) ) - { - int sig = WTERMSIG(status); - debdeb("SIGNALED pid=%d tid=%d signal='%s'(%d) pc=%a\n", event->pid, event->tid, strsignal(sig), sig, event->ea); - exit_code = sig; - } - else - { - exit_code = WEXITSTATUS(status); - } - if ( threads.size() <= 1 || thif->tid == process_handle ) - { - event->set_exit_code(PROCESS_EXITED, exit_code); - exited = true; - } - else - { - log(tid, "got a thread exit\n"); - event->clear(); - dead_thread(event->tid, DEAD); - } - } -EVENT_READY: - log(tid, "low got event: %s, signum=%d\n", debug_event_str(event), thif->child_signum); - thif = get_thread(event->tid); - if ( thif != NULL ) - thif->single_step = false; - last_event = *event; - return true; -} - -//-------------------------------------------------------------------------- -gdecode_t idaapi linux_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) -{ - QASSERT(30059, !in_event || exited); - while ( true ) - { - // are there any pending events? - if ( !events.empty() ) - { - // get the first event and return it - *event = events.front(); - events.pop_front(); - if ( event->eid() == NO_EVENT ) - continue; - log(-1, "GDE1(handling_lowcnds.size()=%" FMT_Z "): %s\n", handling_lowcnds.size(), debug_event_str(event)); - in_event = true; - if ( handling_lowcnds.empty() ) - { - ldeb("requested_to_suspend := 0\n"); - requested_to_suspend = false; - } - return events.empty() ? GDE_ONE_EVENT : GDE_MANY_EVENTS; - } - - debug_event_t ev; - if ( !get_debug_event(&ev, timeout_ms) ) - break; - enqueue_event(ev, IN_BACK); - } - return GDE_NO_EVENT; -} - -//-------------------------------------------------------------------------- -// R is running -// S is sleeping in an interruptible wait -// D is waiting in uninterruptible disk sleep -// Z is zombie -// T is traced or stopped (on a signal) -// W is paging -static char getstate(int tid) -{ - char buf[QMAXPATH]; - qsnprintf(buf, sizeof(buf), "/proc/%u/status", tid); - FILE *fp = fopenRT(buf); - qstring line; - if ( fp == NULL //-V501 identical sub-expressions - || qgetline(&line, fp) < 0 - || qgetline(&line, fp) < 0 ) - { - // no file or file read error (e.g. was deleted after successful fopenRT()) - return ' '; - } - char st; - if ( qsscanf(line.c_str(), "State: %c", &st) != 1 ) - INTERR(30060); - qfclose(fp); - return st; -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::has_pending_events(void) -{ - if ( !events.empty() ) - return true; - - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - if ( ti.got_pending_status && ti.user_suspend == 0 && ti.suspend_count == 0 ) - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -int linux_debmod_t::dbg_freeze_threads(thid_t tid, bool exclude) -{ - ldeb(" freeze_threads(%s %d) handling_lowcnds.size()=%" FMT_Z "\n", exclude ? "exclude" : "only", tid, handling_lowcnds.size()); - // first send all threads the SIGSTOP signal, as fast as possible - typedef qvector queue_t; - queue_t queue; - qvector deadtids; - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - if ( (p->first == tid) == exclude ) - continue; - thread_info_t &ti = p->second; - if ( ti.is_running() ) - { - if ( qkill(ti.tid, SIGSTOP) != 0 ) - { - // In some cases the thread may already be dead but we are not aware - // of it (for example, if many threads died at once, the events - // will be queued and not processed yet. - if ( errno == ESRCH ) - deadtids.push_back(ti.tid); - else - dmsg("failed to send SIGSTOP to thread %d: %s\n", ti.tid, strerror(errno)); - continue; - } - queue.push_back(&ti); - ti.waiting_sigstop = true; - } - ti.suspend_count++; - } - // then wait for the SIGSTOP signals to arrive - while ( !queue.empty() ) - { - int status = 0; - int stid = check_for_signal(&status, -1, exited ? -1 : 0); - if ( stid > 0 ) - { - // if more signals are to arrive, enable the waiter - for ( queue_t::iterator p=queue.begin(); p != queue.end(); ++p ) - { - thread_info_t &ti = **p; - if ( ti.tid == stid ) - { - if ( WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP ) - { - // suspended successfully - ti.waiting_sigstop = false; - set_thread_state(ti, STOPPED); - } - else - { // got another signal, SIGSTOP will arrive later - store_pending_signal(stid, status); - } - stid = -1; - queue.erase(p); - break; - } - } - } - if ( stid > 0 ) // got a signal for some other thread - store_pending_signal(stid, status); - } - - // clean up dead threads - for ( int i=0; i < deadtids.size(); i++ ) - dead_thread(deadtids[i], DEAD); - -#ifdef LDEB - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - if ( (p->first == tid) != exclude ) - { - thid_t tid2 = p->first; - log(tid2, "suspendd (ip=%08a)\n", get_ip(tid2)); - } - } -#endif - return 1; -} - -//-------------------------------------------------------------------------- -int linux_debmod_t::dbg_thaw_threads(thid_t tid, bool exclude) -{ - int ok = 1; - ldeb(" thaw_threads(%s %d), may_run=%d handlng_lowcnd.size()=%" FMT_Z " npending_signals=%d\n", exclude ? "exclude" : "only", tid, may_run, handling_lowcnds.size(), npending_signals); - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - if ( (p->first == tid) == exclude ) - continue; - - thread_info_t &ti = p->second; - log(ti.tid, "(ip=%08a) ", get_ip(ti.tid)); - - if ( ti.is_running() ) - { - QASSERT(30188, ti.suspend_count == 0); - ldeb("already running\n"); - continue; - } - - if ( ti.suspend_count > 0 && --ti.suspend_count > 0 ) - { - ldeb("suspended\n"); - continue; - } - if ( ti.user_suspend > 0 ) - { - ldeb("user suspended\n"); - continue; - } - - if ( ti.got_pending_status ) - { - ldeb("have pending signal\n"); - continue; - } - - if ( (!may_run && ti.state != DYING) || exited ) - { - ldeb("!may_run\n"); - continue; - } - - if ( ti.state == STOPPED || ti.state == DYING ) - { - __ptrace_request request = ti.single_step ? PTRACE_SINGLESTEP : PTRACE_CONT; -#ifdef LDEB - char ostate = getstate(ti.tid); -#endif - ldeb("really resuming\n"); - if ( qptrace(request, ti.tid, 0, (void *)(size_t)(ti.child_signum)) != 0 && ti.state != DYING ) //lint !e571 cast results in sign extension - { - ldeb(" !! failed to resume thread (error %d)\n", errno); - if ( getstate(ti.tid) != 'Z' ) - { - ok = 0; - continue; - } - // we have a zombie thread - // report its death - dead_thread(ti.tid, DYING); - } - if ( ti.state == DYING ) - { - set_thread_state(ti, DEAD); - } - else - { - QASSERT(30178, ti.state == STOPPED); //-V547 is always true - set_thread_state(ti, RUNNING); - } - ldeb("PTRACE_%s, signum=%d, old_state: '%c', new_state: '%c'\n", request == PTRACE_SINGLESTEP ? "SINGLESTEP" : "CONT", ti.child_signum, ostate, getstate(ti.tid)); - } - else - { - ldeb("ti.state is not stopped or dying\n"); - } - } - return ok; -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::suspend_all_threads(void) -{ - return dbg_freeze_threads(NO_THREAD); -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::resume_all_threads(void) -{ - return dbg_thaw_threads(NO_THREAD); -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_continue_after_event(const debug_event_t *event) -{ - if ( event == NULL ) - return DRC_FAILED; - - int tid = event->tid; - thread_info_t *t = get_thread(tid); - if ( t == NULL && event->eid() != THREAD_EXITED && !exited ) - { - dwarning("could not find thread %d!\n", tid); - return DRC_FAILED; - } - - ldeb("continue after event %s%s\n", debug_event_str(event), has_pending_events() ? " (there are pending events)" : ""); - - if ( t != NULL ) - { - if ( event->eid() != THREAD_STARTED - && event->eid() != THREAD_EXITED - && event->eid() != LIB_LOADED - && event->eid() != LIB_UNLOADED - && (event->eid() != EXCEPTION || event->handled) ) - { - t->child_signum = 0; - } - - if ( t->state == DYING ) - { - // this thread is about to exit; resume it so it can do so - t->suspend_count = 0; - t->user_suspend = 0; - dbg_thaw_threads(t->tid, false); - } - else if ( t->state == DEAD ) - { - // remove from internal list - del_thread(event->tid); - } - - // ensure TF bit is not set (if we aren't single stepping) after a SIGTRAP - // because TF bit may still be set - if ( event->eid() == EXCEPTION && !t->single_step - && event->exc().code == SIGTRAP && event->handled ) - clear_tbit(event->tid); - } - - in_event = false; - return resume_app(NO_THREAD) ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -// if tid is specified, resume only it. -bool linux_debmod_t::resume_app(thid_t tid) -{ - may_run = !handling_lowcnds.empty() || !has_pending_events(); - if ( may_run && handling_lowcnds.empty() ) - { - if ( !removed_bpts.empty() ) - { - for ( easet_t::iterator p=removed_bpts.begin(); p != removed_bpts.end(); ++p ) - bpts.erase(*p); - removed_bpts.clear(); - } - } - - return tid == NO_THREAD - ? resume_all_threads() - : dbg_thaw_threads(tid, false); -} - -//-------------------------------------------------------------------------- -// PTRACE_PEEKTEXT / PTRACE_POKETEXT operate on unsigned long values! (i.e. 4 bytes on x86 and 8 bytes on x64) -typedef unsigned long peeksize_t; -#define PEEKSIZE sizeof(peeksize_t) - -//-------------------------------------------------------------------------- -int linux_debmod_t::_read_memory(int tid, ea_t ea, void *buffer, int size, bool suspend) -{ - if ( exited || process_handle == INVALID_HANDLE_VALUE ) - return 0; - - // stop all threads before accessing the process memory - if ( suspend ) - suspend_all_threads(); - - if ( tid == -1 ) - tid = process_handle; - - int read_size = 0; - bool tried_mem = false; - bool tried_peek = false; - // don't use memory for short reads - if ( size > 3 * PEEKSIZE ) - { -TRY_MEMFILE: -#ifndef __ANDROID__ - char filename[64]; - qsnprintf (filename, sizeof(filename), "/proc/%d/mem", tid); - int fd = open(filename, O_RDONLY | O_LARGEFILE); - if ( fd != -1 ) - { - read_size = pread64(fd, buffer, size, ea); - close(fd); - } - // msg("%d: pread64 %d:%a:%d => %d\n", tid, fd, ea, size, read_size); - -#ifdef LDEB - if ( read_size < size ) - perror("read_memory: pread64 failed"); -#endif -#endif - tried_mem = true; - } - - if ( read_size != size && !tried_peek ) - { - uchar *ptr = (uchar *)buffer; - read_size = 0; - tried_peek = true; - while ( read_size < size ) - { - const int shift = ea & (PEEKSIZE-1); - int nbytes = shift == 0 ? PEEKSIZE : PEEKSIZE - shift; - if ( nbytes > (size - read_size) ) - nbytes = size - read_size; - errno = 0; - unsigned long v = qptrace(PTRACE_PEEKTEXT, tid, (void *)(size_t)(ea-shift), 0); - if ( errno != 0 ) - { - ldeb("PEEKTEXT %d:%a => %s\n", tid, ea-shift, strerror(errno)); - break; - } - else - { - //msg("PEEKTEXT %d:%a => OK\n", tid, ea-shift); - } - if ( nbytes == PEEKSIZE ) - { - *(unsigned long*)ptr = v; //lint !e433 !e415 allocated area not large enough for pointer - } - else - { - v >>= (shift*8); - for ( int i=0; i < nbytes; i++ ) - { - ptr[i] = uchar(v); - v >>= 8; - } - } - ptr += nbytes; - ea += nbytes; - read_size += nbytes; - } - } - - // sometimes PEEKTEXT fails but memfile succeeds... so try both - if ( read_size < size && !tried_mem ) - goto TRY_MEMFILE; - - if ( suspend ) - resume_all_threads(); - // msg("READ MEMORY (%d): %d\n", tid, read_size); - return read_size > 0 ? read_size : 0; -} - -//-------------------------------------------------------------------------- -int linux_debmod_t::_write_memory(int tid, ea_t ea, const void *buffer, int size, bool suspend) -{ - if ( exited || process_handle == INVALID_HANDLE_VALUE ) - return 0; - -#ifndef LDEB - if ( debug_debugger ) -#endif - { - show_hex(buffer, size, "WRITE MEMORY %a %d bytes:\n", ea, size); - } - - // stop all threads before accessing the process memory - if ( suspend ) - suspend_all_threads(); - - - if ( tid == -1 ) - tid = process_handle; - - int ok = size; - const uchar *ptr = (const uchar *)buffer; - errno = 0; - - while ( size > 0 ) - { - const int shift = ea & (PEEKSIZE-1); - int nbytes = shift == 0 ? PEEKSIZE : PEEKSIZE - shift; - if ( nbytes > size ) - nbytes = size; - unsigned long word; - memcpy(&word, ptr, qmin(sizeof(word), nbytes)); // use memcpy() to read unaligned bytes - if ( nbytes != PEEKSIZE ) - { - unsigned long old = qptrace(PTRACE_PEEKTEXT, tid, (void *)(size_t)(ea-shift), 0); - if ( errno != 0 ) - { - ok = 0; - break; - } - unsigned long mask = ~0; - mask >>= ((PEEKSIZE - nbytes)*8); - mask <<= (shift*8); - word <<= (shift*8); - word &= mask; - word |= old & ~mask; - } - errno = 0; - qptrace(PTRACE_POKETEXT, process_handle, (void *)(size_t)(ea-shift), (void *)word); - if ( errno ) - { - errno = 0; - qptrace(PTRACE_POKEDATA, process_handle, (void *)(size_t)(ea-shift), (void *)word); - } - if ( errno ) - { - ok = 0; - break; - } - ptr += nbytes; - ea += nbytes; - size -= nbytes; - } - - if ( suspend ) - resume_all_threads(); - - return ok; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi linux_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring * /*errbuf*/) -{ - return _write_memory(-1, ea, buffer, size, true); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi linux_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring * /*errbuf*/) -{ - return _read_memory(-1, ea, buffer, size, true); -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::add_dll(ea_t base, asize_t size, const char *modname, const char *soname) -{ - debdeb("%a: new dll %s (soname=%s)\n", base, modname, soname); - debug_event_t ev; - modinfo_t &mi_ll = ev.set_modinfo(LIB_LOADED); - ev.pid = process_handle; - ev.tid = process_handle; - ev.ea = base; - ev.handled = true; - mi_ll.name = modname; - mi_ll.base = base; - mi_ll.size = size; - mi_ll.rebase_to = BADADDR; - if ( is_dll && input_file_path == modname ) - mi_ll.rebase_to = base; - enqueue_event(ev, IN_FRONT); - - image_info_t ii(base, ev.modinfo().size, modname, soname); - dlls.insert(make_pair(ii.base, ii)); - dlls_to_import.insert(ii.base); -} - -#define LOOK_FOR_DEBUG_FILE_DEBUG_FLAG IDA_DEBUG_DEBUGGER -#include "../../plugins/dwarf/look_for_debug_file.cpp" - -//-------------------------------------------------------------------------- -void linux_debmod_t::_import_symbols_from_file(name_info_t *out, image_info_t &ii) -{ - struct dll_symbol_importer_t : public symbol_visitor_t - { - linux_debmod_t *ld; - image_info_t ⅈ - name_info_t *out; - dll_symbol_importer_t(linux_debmod_t *_ld, name_info_t *_out, image_info_t &_ii) - : symbol_visitor_t(VISIT_SYMBOLS|VISIT_BUILDID|VISIT_DBGLINK), - ld(_ld), - ii(_ii), - out(_out) - {} - virtual int visit_symbol(ea_t ea, const char *name) override - { - ea += ii.base; - out->addrs.push_back(ea); - out->names.push_back(qstrdup(name)); - ii.names[ea] = name; - // every 10000th name send a message to ida - we are alive! - if ( (out->addrs.size() % 10000) == 0 ) - ld->dmsg(""); - return 0; - } - virtual int visit_buildid(const char *buildid) override - { - ii.buildid = buildid; - ld->debdeb("Build ID '%s' of '%s'\n", buildid, ii.fname.c_str()); - return 0; - } - virtual int visit_debuglink(const char *debuglink, uint32 crc) override - { - ii.debuglink = debuglink; - ii.dl_crc = crc; - ld->debdeb("debuglink '%s' of '%s'\n", debuglink, ii.fname.c_str()); - return 0; - } - }; - if ( ii.base == BADADDR ) - { - debdeb("Can't import symbols from %s: no imagebase\n", ii.fname.c_str()); - return; - } - dll_symbol_importer_t dsi(this, out, ii); - load_elf_symbols(ii.fname.c_str(), dsi); -} - -//------------------------------------------------------------------------- -void linux_debmod_t::_import_dll(image_info_t &ii) -{ - bool is_libpthread = stristr(ii.soname.c_str(), "libpthread") != NULL; - // keep nptl names in a separate list to be able to resolve them any time - name_info_t *storage = is_libpthread ? &nptl_names : &pending_names; - if ( is_libpthread ) - nptl_base = ii.base; - - _import_symbols_from_file(storage, ii); - // Try to locate file with the separate debug info. - // FIXME: should we check that libpthread lacks symbols for libthread_db? - // Library.so usually contains debuglink which points to itself, - // so we need to avoid to load library.so another time. - const char *elf_dbgdir = get_elf_debug_file_directory(); -#ifdef TESTABLE_BUILD - if ( per_pid_elf_dbgdir_resolver != NULL ) - { - const char *supp = per_pid_elf_dbgdir_resolver(pid); - if ( supp != NULL ) - elf_dbgdir = supp; - } -#endif - debug_info_file_visitor_t dif( - elf_dbgdir, - /*from envvar=*/ true, - ii.fname.c_str(), - ii.debuglink.c_str(), - ii.dl_crc, - ii.buildid.c_str()); - if ( dif.accept() != 0 && ii.fname != dif.fullpath ) - { - debdeb("load separate debug info '%s'\n", dif.fullpath); - image_info_t ii_deb(ii.base, 0, dif.fullpath, ""); - _import_symbols_from_file(storage, ii_deb); - } - - if ( is_libpthread ) - { - pending_names.addrs.insert(pending_names.addrs.end(), nptl_names.addrs.begin(), nptl_names.addrs.end()); - pending_names.names.insert(pending_names.names.end(), nptl_names.names.begin(), nptl_names.names.end()); - for ( int i=0; i < nptl_names.names.size(); i++ ) - nptl_names.names[i] = qstrdup(nptl_names.names[i]); - } -} - -//-------------------------------------------------------------------------- -// enumerate names from the specified shared object and save the results -// we'll need to send it to IDA later -// if libname == NULL, enum all modules -void linux_debmod_t::enum_names(const char *libname) -{ - if ( dlls_to_import.empty() ) - return; - - for ( easet_t::iterator p=dlls_to_import.begin(); p != dlls_to_import.end(); ) - { - images_t::iterator q = dlls.find(*p); - if ( q != dlls.end() ) - { - image_info_t &ii = q->second; - if ( libname != NULL && ii.soname != libname ) - { - ++p; - continue; - } - _import_dll(ii); - } - p = dlls_to_import.erase(p); - } -} - -//-------------------------------------------------------------------------- -ea_t linux_debmod_t::find_pending_name(const char *name) -{ - if ( name == NULL ) - return BADADDR; - // enumerate pending names in reverse order. we need this to find the latest - // resolved address for a name (on android, pthread_..() functions exist twice) - for ( int i=pending_names.addrs.size()-1; i >= 0; --i ) - if ( streq(pending_names.names[i], name) ) - return pending_names.addrs[i]; - for ( int i=0; i < nptl_names.addrs.size(); ++i ) - if ( streq(nptl_names.names[i], name) ) - return nptl_names.addrs[i]; - return BADADDR; -} - -//-------------------------------------------------------------------------- -void idaapi linux_debmod_t::dbg_stopped_at_debug_event(import_infos_t *, bool dlls_added, thread_name_vec_t *thr_names) -{ - if ( dlls_added ) - { - // we will take advantage of this event to import information - // about the exported functions from the loaded dlls - enum_names(); - - name_info_t &ni = *get_debug_names(); - ni = pending_names; // NB: ownership of name pointers is transferred - pending_names.clear(); - } - if ( thr_names != NULL ) - update_thread_names(thr_names); -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::cleanup(void) -{ - // if the process is still running, kill it, otherwise it runs uncontrolled - // normally the process is dead at this time but may survive if we arrive - // here after an interr. - if ( process_handle != INVALID_HANDLE_VALUE ) - dbg_exit_process(NULL); - process_handle = INVALID_HANDLE_VALUE; - thread_handle = INVALID_HANDLE_VALUE; - is_dll = false; - requested_to_suspend = false; - in_event = false; - - threads.clear(); - dlls.clear(); - dlls_to_import.clear(); - events.clear(); - if ( mapfp != NULL ) - { - qfclose(mapfp); - mapfp = NULL; - } - - complained_shlib_bpt = false; - bpts.clear(); - - tdb_delete(); - erase_internal_bp(birth_bpt); - erase_internal_bp(death_bpt); - erase_internal_bp(shlib_bpt); - npending_signals = 0; - interp.clear(); - exe_path.qclear(); - exited = false; - - for ( int i=0; i < nptl_names.names.size(); i++ ) - qfree(nptl_names.names[i]); - nptl_names.clear(); - - inherited::cleanup(); -} - -//-------------------------------------------------------------------------- -// -// DEBUGGER INTERFACE FUNCTIONS -// -//-------------------------------------------------------------------------- -inline const char *skipword(const char *ptr) -{ - while ( !qisspace(*ptr) && *ptr != '\0' ) - ptr++; - return ptr; -} - -//-------------------------------------------------------------------------- -// find a dll in the memory information array -static const memory_info_t *find_dll(const meminfo_vec_t &miv, const char *name) -{ - for ( int i=0; i < miv.size(); i++ ) - if ( miv[i].name == name ) - return &miv[i]; - return NULL; -} - -//-------------------------------------------------------------------------- -static memory_info_t *find_dll(meminfo_vec_t &miv, const char *name) //lint !e1764 could be reference to const -{ - return CONST_CAST(memory_info_t *)(find_dll(CONST_CAST(const meminfo_vec_t &)(miv), name)); -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::add_shlib_bpt(const meminfo_vec_t &miv, bool attaching) -{ - if ( shlib_bpt.bpt_addr != 0 ) - return true; - - qstring interp_soname; - if ( interp.empty() ) - { - // find out the loader name - struct interp_finder_t : public symbol_visitor_t - { - qstring interp; - interp_finder_t(void) : symbol_visitor_t(VISIT_INTERP) {} - virtual int visit_symbol(ea_t, const char *) override { return 0; } // unused - virtual int visit_interp(const char *name) override - { - interp = name; - return 2; - } - }; - interp_finder_t itf; - const char *exename = exe_path.c_str(); - int code = load_elf_symbols(exename, itf); - if ( code == 0 ) - { // no interpreter - if ( !complained_shlib_bpt ) - { - complained_shlib_bpt = true; - dwarning("AUTOHIDE DATABASE\n%s:\n" - "Could not find the elf interpreter name,\n" - "shared object events will not be reported", exename); - } - return false; - } - if ( code != 2 ) - { - dwarning("%s: could not read symbols on remote computer", exename); - return false; - } - char path[QMAXPATH]; - qmake_full_path(path, sizeof(path), itf.interp.c_str()); - interp_soname.swap(itf.interp); - interp = path; - } - else - { - interp_soname = qbasename(interp.c_str()); - } - - // check if it is present in the memory map (normally it is) - debdeb("INTERP: %s, SONAME: %s\n", interp.c_str(), interp_soname.c_str()); - const memory_info_t *mi = find_dll(miv, interp.c_str()); - if ( mi == NULL ) - { - dwarning("%s: could not find in process memory", interp.c_str()); - return false; - } - - asize_t size = calc_module_size(miv, mi); - add_dll(mi->start_ea, size, interp.c_str(), interp_soname.c_str()); - - // set bpt at r_brk - enum_names(interp_soname.c_str()); // update the name list - const char *bpt_name = "_r_debug"; - ea_t ea = find_pending_name(bpt_name); - if ( ea != BADADDR ) - { - struct r_debug rd; - if ( _read_memory(-1, ea, &rd, sizeof(rd), false) == sizeof(rd) ) - { - if ( rd.r_brk != 0 ) - { - if ( !add_internal_bp(shlib_bpt, rd.r_brk) ) - { - ea_t ea1 = rd.r_brk; - debdeb("%a: could not set shlib bpt\n", ea1); - } - } - } - } - if ( shlib_bpt.bpt_addr == 0 ) - { - static const char *const shlib_bpt_names[] = - { - "r_debug_state", - "_r_debug_state", - "_dl_debug_state", - "rtld_db_dlactivity", - "_rtld_debug_state", - NULL - }; - - for ( int i=0; i < qnumber(shlib_bpt_names); i++ ) - { - bpt_name = shlib_bpt_names[i]; - ea = find_pending_name(bpt_name); - if ( ea != BADADDR && ea != 0 ) - { - if ( add_internal_bp(shlib_bpt, ea) ) - break; - debdeb("%a: could not set shlib bpt (name=%s)\n", ea, bpt_name); - } - } - if ( shlib_bpt.bpt_addr == 0 ) - { -#if defined(__ANDROID__) && defined(__X86__) - // Last attempt for old Android, - // the modern Android doesn't need the special handling - return add_android_shlib_bpt(miv, attaching); -#else - qnotused(attaching); - return false; -#endif - } - } - debdeb("%a: added shlib bpt (%s)\n", shlib_bpt.bpt_addr, bpt_name); - return true; -} - -//-------------------------------------------------------------------------- -thread_info_t &linux_debmod_t::add_thread(int tid) -{ - std::pair ret = - threads.insert(std::make_pair(tid, thread_info_t(tid))); - thread_info_t &ti = ret.first->second; - get_thread_name(&ti.name, tid); - return ti; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::del_thread(int tid) -{ - threads_t::iterator p = threads.find(tid); - QASSERT(30064, p != threads.end()); - if ( p->second.got_pending_status ) - npending_signals--; - threads.erase(p); - - if ( deleted_threads.size() >= 10 ) - deleted_threads.erase(deleted_threads.begin()); - - deleted_threads.push_back(tid); -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::handle_process_start(pid_t _pid, attach_mode_t attaching) -{ - pid = _pid; - deleted_threads.clear(); - process_handle = pid; - add_thread(pid); - int status; - int options = 0; - if ( attaching == AMT_ATTACH_BROKEN ) - options = WNOHANG; - qwait(&status, pid, options); // (should succeed) consume SIGSTOP - debdeb("process pid/tid: %d\n", pid); - may_run = false; - - char fname[QMAXPATH]; - debug_event_t ev; - modinfo_t &mi_ps = ev.set_modinfo(PROCESS_STARTED); - ev.pid = pid; - ev.tid = pid; - ev.ea = get_ip(pid); - ev.handled = true; - get_exec_fname(pid, fname, sizeof(fname)); - mi_ps.name = fname; - mi_ps.base = BADADDR; - mi_ps.size = 0; - mi_ps.rebase_to = BADADDR; - - qsnprintf(fname, sizeof(fname), "/proc/%u/maps", pid); - mapfp = fopenRT(fname); - if ( mapfp == NULL ) - { - dmsg("%s: %s\n", fname, winerr(errno)); - return false; // if fails, the process did not start - } - - exe_path = mi_ps.name.c_str(); - if ( !is_dll ) - input_file_path = exe_path; - - // find the executable base - meminfo_vec_t miv; - // init debapp_attrs.addrsize: 32bit application by default - // get_memory_info() may correct it if meets a 64-bit address - debapp_attrs.addrsize = 4; - if ( get_memory_info(miv, false) <= 0 ) - INTERR(30065); - - term_reg_ctx(); - init_reg_ctx(); - - const memory_info_t *mi = find_dll(miv, mi_ps.name.c_str()); - if ( mi != NULL ) - { - mi_ps.base = mi->start_ea; - mi_ps.size = mi->end_ea - mi->start_ea; - if ( !is_dll ) // exe files: rebase idb to the loaded address - mi_ps.rebase_to = mi->start_ea; - } - else - { - if ( !is_dll ) - dmsg("%s: nowhere in the process memory?!\n", mi_ps.name.c_str()); - } - - if ( !add_shlib_bpt(miv, attaching) ) - dmsg("Could not set the shlib bpt, shared object events will not be handled\n"); - - enqueue_event(ev, IN_BACK); - if ( attaching != AMT_NO_ATTACH ) - { - modinfo_t &mi_pa = ev.set_modinfo(PROCESS_ATTACHED); - enqueue_event(ev, IN_BACK); - if ( !qgetenv("IDA_SKIP_SYMS", NULL) ) - { - // collect exported names from the main module - qstring soname; - get_soname(mi_pa.name.c_str(), &soname); - image_info_t ii(mi_pa.base, mi_pa.size, mi_pa.name.c_str(), soname); - _import_dll(ii); - } - } - - return true; -} - -//-------------------------------------------------------------------------- -static void idaapi kill_all_processes(void) -{ - struct ida_local process_killer_t : public debmod_visitor_t - { - virtual int visit(debmod_t *debmod) override - { - linux_debmod_t *ld = (linux_debmod_t *)debmod; - if ( ld->process_handle != INVALID_HANDLE_VALUE ) - qkill(ld->process_handle, SIGKILL); - return 0; - } - }; - process_killer_t pk; - for_all_debuggers(pk); -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) -{ - void *child_pid; - drc_t drc = maclnx_launch_process(this, path, args, startdir, flags, - input_path, input_file_crc32, &child_pid, - errbuf); - - if ( drc > 0 - && child_pid != NULL - && !handle_process_start(size_t(child_pid), AMT_NO_ATTACH) ) - { - dbg_exit_process(NULL); - drc = DRC_NETERR; - } - - return drc; -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -drc_t idaapi linux_debmod_t::dbg_attach_process(pid_t _pid, int /*event_id*/, int flags, qstring * /*errbuf*/) -{ - is_dll = (flags & DBG_PROC_IS_DLL) != 0; - if ( qptrace(PTRACE_ATTACH, _pid, NULL, NULL) == 0 - && handle_process_start(_pid, AMT_ATTACH_NORMAL) ) - { - gen_library_events(_pid); // detect all loaded libraries - return DRC_OK; - } - qptrace(PTRACE_DETACH, _pid, NULL, NULL); - return DRC_FAILED; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::cleanup_signals(void) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - // cannot leave pending sigstop, try to recieve and handle it - if ( p->second.waiting_sigstop ) - { - thread_info_t &ti = p->second; - ldeb("cleanup_signals:\n"); - log(ti.tid, "must be STOPPED\n"); - QASSERT(30181, ti.state == STOPPED); - qptrace(PTRACE_CONT, ti.tid, 0, 0); - int status; - int tid = check_for_signal(&status, ti.tid, -1); - if ( tid != ti.tid ) - msg("%d: failed to clean up pending SIGSTOP\n", tid); - } - } -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::cleanup_breakpoints(void) -{ - erase_internal_bp(birth_bpt); - erase_internal_bp(death_bpt); - erase_internal_bp(shlib_bpt); -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_detach_process(void) -{ - // restore only internal breakpoints and signals - cleanup_breakpoints(); - cleanup_signals(); - - bool had_pid = false; - bool ok = true; - log(-1, "detach all threads.\n"); - for ( threads_t::iterator p=threads.begin(); ok && p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - if ( ti.tid == process_handle ) - had_pid = true; - - ok = qptrace(PTRACE_DETACH, ti.tid, NULL, NULL) == 0; - log(-1, "detach tid %d: ok=%d\n", ti.tid, ok); - } - - if ( ok && !had_pid ) - { - // if pid was not in the thread list, detach it separately - ok = qptrace(PTRACE_DETACH, process_handle, NULL, NULL) == 0; - log(-1, "detach pid %d: ok=%d\n", process_handle, ok); - } - if ( ok ) - { - debug_event_t ev; - ev.set_eid(PROCESS_DETACHED); - ev.pid = process_handle; - ev.tid = process_handle; - ev.ea = BADADDR; - ev.handled = true; - enqueue_event(ev, IN_BACK); - in_event = false; - exited = true; - threads.clear(); - process_handle = INVALID_HANDLE_VALUE; - return DRC_OK; - } - return DRC_FAILED; -} - -//-------------------------------------------------------------------------- -// if we have to do something as soon as we noticed the connection -// broke, this is the correct place -bool idaapi linux_debmod_t::dbg_prepare_broken_connection(void) -{ - broken_connection = true; - return true; -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -drc_t idaapi linux_debmod_t::dbg_prepare_to_pause_process(qstring * /*errbuf*/) -{ - if ( events.empty() ) - { - qkill(process_handle, SIGSTOP); - thread_info_t &ti = threads.begin()->second; - ti.waiting_sigstop = true; - } - may_run = false; - requested_to_suspend = true; - ldeb("requested_to_suspend := 1\n"); - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_exit_process(qstring * /*errbuf*/) -{ - ldeb("------- exit process\n"); - bool ok = true; - // suspend all threads to avoid problems (for example, killing a - // thread may resume another thread and it can throw an exception because - // of that) - suspend_all_threads(); - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - if ( ti.state == STOPPED ) - { - if ( qptrace(PTRACE_KILL, ti.tid, 0, (void*)SIGKILL) != 0 && errno != ESRCH ) - { - dmsg("PTRACE_KILL %d: %s\n", ti.tid, strerror(errno)); - ok = false; - } - } - else - { - if ( ti.tid != INVALID_HANDLE_VALUE && qkill(ti.tid, SIGKILL) != 0 && errno != ESRCH ) - { - dmsg("SIGKILL %d: %s\n", ti.tid, strerror(errno)); - ok = false; - } - } - if ( ok ) - { - set_thread_state(ti, RUNNING); - ti.suspend_count = 0; - } - } - if ( ok ) - process_handle = INVALID_HANDLE_VALUE; - may_run = true; - exited = true; - return ok ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -// Set hardware breakpoints for one thread -bool linux_debmod_t::set_hwbpts(HANDLE hThread) const -{ -#ifdef __ARM__ - qnotused(hThread); - return false; -#else - bool ok = set_dr(hThread, 0, hwbpt_ea[0]) - && set_dr(hThread, 1, hwbpt_ea[1]) - && set_dr(hThread, 2, hwbpt_ea[2]) - && set_dr(hThread, 3, hwbpt_ea[3]) - && set_dr(hThread, 6, 0) - && set_dr(hThread, 7, dr7); - // msg("set_hwbpts: DR0=%a DR1=%a DR2=%a DR3=%a DR7=%a => %d\n", - // hwbpt_ea[0], - // hwbpt_ea[1], - // hwbpt_ea[2], - // hwbpt_ea[3], - // dr7, - // ok); - return ok; -#endif -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::refresh_hwbpts(void) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - if ( !set_hwbpts(p->second.tid) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::erase_internal_bp(internal_bpt &bp) -{ - bool ok = bp.bpt_addr == 0 || dbg_del_bpt(BPT_SOFT, bp.bpt_addr, bp.saved, bp.nsaved); - bp.bpt_addr = 0; - bp.nsaved = 0; - return ok; -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::add_internal_bp(internal_bpt &bp, ea_t addr) -{ - int len = -1; - int nread = sizeof(bp.saved); -#ifdef __ARM__ - if ( (addr & 1) != 0 ) - { - len = 2; - addr--; - } - else - { - len = 4; - } - CASSERT(sizeof(bp.saved) >= 4); - nread = len; -#endif - if ( _read_memory(-1, addr, bp.saved, nread) == nread ) - { - if ( dbg_add_bpt(NULL, BPT_SOFT, addr, len) ) - { - bp.bpt_addr = addr; - bp.nsaved = nread; - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed, -2-read failed -int idaapi linux_debmod_t::dbg_add_bpt( - bytevec_t *orig_bytes, - bpttype_t type, - ea_t ea, - int len) -{ -#if defined(__ARM__) && defined(__X86__) - bool is_thumb32_bpt = false; - if ( len == (2 | USE_THUMB32_BPT) ) - { - is_thumb32_bpt = true; - len = 4; - } -#endif - ldeb("%a: add bpt (size=%d)\n", ea, len); - if ( type == BPT_SOFT ) - { - if ( orig_bytes != NULL && read_bpt_orgbytes(orig_bytes, ea, len) < 0 ) - return -2; - const uchar *bptcode = bpt_code.begin(); -#ifdef __ARM__ -# ifndef __X86__ - if ( len < 0 ) - len = bpt_code.size(); - bptcode = aarch64_bpt; -# else - if ( len < 0 ) - { // unknown mode. we have to decide between thumb and arm bpts - // ideally we would decode the instruction and try to determine its mode - // unfortunately we do not have instruction decoder in arm server. - // besides, it cannot really help. - // just check for some known opcodes. this is bad but i do not know - // how to do better. - - len = 4; // default to arm mode - uchar opcodes[2]; - if ( dbg_read_memory(ea, opcodes, sizeof(opcodes), NULL) == sizeof(opcodes) ) - { - static const uchar ins1[] = { 0x70, 0x47 }; // BX LR - static const uchar ins3[] = { 0x00, 0xB5 }; // PUSH {LR} - static const uchar ins2[] = { 0x00, 0xBD }; // POP {PC} - static const uchar *const ins[] = { ins1, ins2, ins3 }; - for ( int i=0; i < qnumber(ins); i++ ) - { - const uchar *p = ins[i]; - if ( opcodes[0] == p[0] && opcodes[1] == p[1] ) - { - len = 2; - break; - } - } - } - } - if ( len == 2 ) - bptcode = thumb16_bpt; - else if ( len == 4 && is_thumb32_bpt ) - bptcode = thumb32_bpt; -# endif -#else - if ( len < 0 ) - len = bpt_code.size(); -#endif - QASSERT(30066, len > 0 && len <= bpt_code.size()); - debmod_bpt_t dbpt(ea, len); - if ( dbg_read_memory(ea, dbpt.saved, len, NULL) - && dbg_write_memory(ea, bptcode, len, NULL) == len ) - { - bpts[ea] = dbpt; - removed_bpts.erase(ea); - return 1; - } - } - -#ifndef __ARM__ - if ( add_hwbpt(type, ea, len) ) - return 1; -#endif - - return 0; -} - -//-------------------------------------------------------------------------- -#ifdef __ARM__ -void linux_debmod_t::adjust_swbpt(ea_t *p_ea, int *p_len) -{ - inherited::adjust_swbpt(p_ea, p_len); - // for thumb mode we have to decide between 16-bit and 32-bit bpt - if ( *p_len == 2 ) - { - uint16 opcode; - if ( dbg_read_memory(*p_ea, &opcode, sizeof(opcode), NULL) <= 0 ) - return; - if ( is_32bit_thumb_insn(opcode) ) - *p_len |= USE_THUMB32_BPT; // ask for thumb32 bpt - } -} -#endif - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -int idaapi linux_debmod_t::dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) -{ -#if defined(__ARM__) && defined(__X86__) - if ( len == (2 | USE_THUMB32_BPT) ) - len = 4; -#endif - ldeb("%a: del bpt (size=%d) exited=%d\n", ea, len, exited); - if ( orig_bytes != NULL ) - { - if ( dbg_write_memory(ea, orig_bytes, len, NULL) == len ) - { - removed_bpts.insert(ea); - return true; - } - } - -#ifdef __ARM__ - qnotused(type); - return false; -#else - return del_hwbpt(ea, type); -#endif -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_thread_get_sreg_base(ea_t *pea, thid_t tid, int sreg_value, qstring * /*errbuf*/) -{ -#ifdef __ARM__ - qnotused(tid); - qnotused(sreg_value); - qnotused(pea); - return DRC_FAILED; -#else - *pea = 0; // all other selectors (cs, ds) usually have base of 0... - // since we do not receive the segment register id we need to retrieve, we - // rely on the register value, which is not great. for example, - // on x64 fs==gs==0, and when IDA passes sreg_value==0, we return the - // base of fs. - if ( sreg_value != 0 ) - { - // find out which selector we're asked to retrieve - struct user_regs_struct regs; - memset(®s, -1, sizeof(regs)); - if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) - return DRC_FAILED; - if ( sreg_value == regs.INTEL_SREG(fs) ) - return thread_get_fs_base(tid, fs_idx, pea) ? DRC_OK : DRC_FAILED; - else if ( sreg_value == regs.INTEL_SREG(gs) ) - return thread_get_fs_base(tid, gs_idx, pea) ? DRC_OK : DRC_FAILED; - } - return DRC_OK; -#endif -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_thread_suspend(thid_t tid) -{ - thread_info_t *ti = get_thread(tid); - if ( ti == NULL ) - return DRC_FAILED; - if ( !dbg_freeze_threads(tid, false) ) - return DRC_FAILED; - ti->user_suspend++; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_thread_continue(thid_t tid) -{ - thread_info_t *ti = get_thread(tid); - if ( ti == NULL ) - return DRC_FAILED; - if ( ti->user_suspend > 0 ) - { - if ( --ti->user_suspend > 0 ) - return DRC_OK; - } - return dbg_thaw_threads(tid, false) ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_set_resume_mode(thid_t tid, resume_mode_t resmod) -{ - if ( resmod != RESMOD_INTO ) - return DRC_FAILED; // not supported - - thread_info_t *t = get_thread(tid); - if ( t == NULL ) - return DRC_FAILED; - t->single_step = true; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::emulate_retn(int tid) -{ -#ifdef __ARM__ -# ifndef __X86__ - struct user_regs_struct regs; - if ( !qptrace_get_prstatus(®s, tid) ) - return false; - - // emulate BX LR - regs.pc = regs.regs[LRREG_IDX]; // PC <- LR - - return qptrace_set_regset(NT_PRSTATUS, tid, ®s, sizeof(regs)); -# else - struct user_regs_struct regs; - qptrace(PTRACE_GETREGS, tid, 0, ®s); - // emulate BX LR - int tbit = regs.uregs[14] & 1; - regs.PCREG = regs.uregs[14] & ~1; // PC <- LR - setflag(regs.uregs[16], 1<<5, tbit); // Set/clear T bit in PSR - return qptrace(PTRACE_SETREGS, tid, 0, ®s) == 0; -# endif -#else - struct user_regs_struct regs; - qptrace(PTRACE_GETREGS, tid, 0, ®s); - size_t sizeof_pcreg = debapp_attrs.addrsize; - if ( _read_memory(tid, regs.SPREG, ®s.PCREG, sizeof_pcreg, false) != sizeof_pcreg ) - { - log(-1, "%d: reading return address from %a failed\n", tid, ea_t(regs.SPREG)); - if ( tid == process_handle ) - return false; - if ( _read_memory(process_handle, regs.SPREG, ®s.PCREG, sizeof_pcreg, false) != sizeof_pcreg ) - { - log(-1, "%d: reading return address from %a failed (2)\n", process_handle, ea_t(regs.SPREG)); - return false; - } - } - regs.SPREG += sizeof_pcreg; - log(-1, "%d: retn to %a\n", tid, ea_t(regs.PCREG)); - return qptrace(PTRACE_SETREGS, tid, 0, ®s) == 0; -#endif -} - -//-------------------------------------------------------------------------- -#define qoffsetof2(s, f) (qoffsetof(regctx_t, s) + qoffsetof(decltype(regctx_t::s), f)) -#define offset_size(s, f) qoffsetof2(s, f), sizeof(decltype(regctx_t::s)::f) - -#ifdef __ARM__ -# ifndef __X86__ -//-------------------------------------------------------------------------- -// AArch64 -//-------------------------------------------------------------------------- -struct regctx_t : public regctx_base_t -{ - struct user_regs_struct regs; - - // clsmask helpers - bool clsmask_regs; - - regctx_t(dynamic_register_set_t &_idaregs); - bool init(void); - bool load(void); - bool store(void); -}; - -//-------------------------------------------------------------------------- -regctx_t::regctx_t(dynamic_register_set_t &_idaregs) - : regctx_base_t(_idaregs) -{ - memset(®s, 0, sizeof(regs)); - - clsmask_regs = 0; - - idaregs.set_regclasses(arm_register_classes); -} - -//-------------------------------------------------------------------------- -bool regctx_t::init(void) -{ - if ( (clsmask & ARM_RC_ALL) == 0 ) - return false; - // setup clsmask helpers - clsmask_regs = (clsmask & ARM_RC_GENERAL) != 0; - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::load(void) -{ - if ( !init() ) - return false; - if ( clsmask_regs ) - if ( !qptrace_get_prstatus(®s, tid) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::store(void) -{ - if ( clsmask_regs ) - if ( !qptrace_set_regset(NT_PRSTATUS, tid, ®s, sizeof(regs)) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::init_reg_ctx(void) -{ - reg_ctx = new regctx_t(idaregs); - - // Populate register context - reg_ctx->add_ival(arch_registers[R_R0], offset_size(regs, regs[0])); - reg_ctx->add_ival(arch_registers[R_R1], offset_size(regs, regs[1])); - reg_ctx->add_ival(arch_registers[R_R2], offset_size(regs, regs[2])); - reg_ctx->add_ival(arch_registers[R_R3], offset_size(regs, regs[3])); - reg_ctx->add_ival(arch_registers[R_R4], offset_size(regs, regs[4])); - reg_ctx->add_ival(arch_registers[R_R5], offset_size(regs, regs[5])); - reg_ctx->add_ival(arch_registers[R_R6], offset_size(regs, regs[6])); - reg_ctx->add_ival(arch_registers[R_R7], offset_size(regs, regs[7])); - reg_ctx->add_ival(arch_registers[R_R8], offset_size(regs, regs[8])); - reg_ctx->add_ival(arch_registers[R_R9], offset_size(regs, regs[9])); - reg_ctx->add_ival(arch_registers[R_R10], offset_size(regs, regs[10])); - reg_ctx->add_ival(arch_registers[R_R11], offset_size(regs, regs[11])); - reg_ctx->add_ival(arch_registers[R_R12], offset_size(regs, regs[12])); - reg_ctx->add_ival(arch_registers[R_R13], offset_size(regs, regs[13])); - reg_ctx->add_ival(arch_registers[R_R14], offset_size(regs, regs[14])); - reg_ctx->add_ival(arch_registers[R_R15], offset_size(regs, regs[15])); - reg_ctx->add_ival(arch_registers[R_R16], offset_size(regs, regs[16])); - reg_ctx->add_ival(arch_registers[R_R17], offset_size(regs, regs[17])); - reg_ctx->add_ival(arch_registers[R_R18], offset_size(regs, regs[18])); - reg_ctx->add_ival(arch_registers[R_R19], offset_size(regs, regs[19])); - reg_ctx->add_ival(arch_registers[R_R20], offset_size(regs, regs[20])); - reg_ctx->add_ival(arch_registers[R_R21], offset_size(regs, regs[21])); - reg_ctx->add_ival(arch_registers[R_R22], offset_size(regs, regs[22])); - reg_ctx->add_ival(arch_registers[R_R23], offset_size(regs, regs[23])); - reg_ctx->add_ival(arch_registers[R_R24], offset_size(regs, regs[24])); - reg_ctx->add_ival(arch_registers[R_R25], offset_size(regs, regs[25])); - reg_ctx->add_ival(arch_registers[R_R26], offset_size(regs, regs[26])); - reg_ctx->add_ival(arch_registers[R_R27], offset_size(regs, regs[27])); - reg_ctx->add_ival(arch_registers[R_R28], offset_size(regs, regs[28])); - reg_ctx->add_ival(arch_registers[R_R29], offset_size(regs, regs[29])); - lr_idx = reg_ctx->add_ival(arch_registers[R_LR], offset_size(regs, regs[30])); - sp_idx = reg_ctx->add_ival(arch_registers[R_SP], offset_size(regs, sp)); - pc_idx = reg_ctx->add_ival(arch_registers[R_PC], offset_size(regs, pc)); - sr_idx = reg_ctx->add_ival(arch_registers[R_PSR], offset_size(regs, pstate)); // 32-bit -} - -# else // __ARM__ && __X86__ - -//-------------------------------------------------------------------------- -// ARM (32-bit) -//-------------------------------------------------------------------------- -struct regctx_t : public regctx_base_t -{ - struct user_regs_struct regs; -#ifdef __HAVE_ARM_VFP__ - struct user_vfp vfp_regs; -#endif - - // clsmask helpers - bool clsmask_regs; -#ifdef __HAVE_ARM_VFP__ - bool clsmask_vfp; -#endif - - regctx_t(dynamic_register_set_t &_idaregs); - bool init(void); - bool load(void); - bool store(void); -}; - -//-------------------------------------------------------------------------- -regctx_t::regctx_t(dynamic_register_set_t &_idaregs) - : regctx_base_t(_idaregs) -{ - memset(®s, 0, sizeof(regs)); -#ifdef __HAVE_ARM_VFP__ - memset(&vfp_regs, 0, sizeof(vfp_regs)); -#endif - - clsmask_regs = 0; -#ifdef __HAVE_ARM_VFP__ - clsmask_vfp = 0; -#endif - - idaregs.set_regclasses(arm_register_classes); -} - -//-------------------------------------------------------------------------- -bool regctx_t::init(void) -{ - if ( (clsmask & ARM_RC_ALL) == 0 ) - return false; - // setup clsmask helpers - clsmask_regs = (clsmask & ARM_RC_GENERAL) != 0; -#ifdef __HAVE_ARM_VFP__ - clsmask_vfp = (clsmask & ARM_RC_VFP) != 0; -#endif - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::load(void) -{ - if ( !init() ) - return false; - if ( clsmask_regs ) - if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) - return false; -#ifdef __HAVE_ARM_VFP__ - if ( clsmask_vfp ) - if ( qptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs) != 0 ) - return false; -#endif - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::store(void) -{ - if ( clsmask_regs ) - if ( qptrace(PTRACE_SETREGS, tid, 0, ®s) != 0 ) - return false; -#ifdef __HAVE_ARM_VFP__ - if ( clsmask_vfp ) - if ( qptrace(PTRACE_SETVFPREGS, tid, 0, &vfp_regs) != 0 ) - return false; -#endif - return true; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::init_reg_ctx(void) -{ - reg_ctx = new regctx_t(idaregs); - - // Populate register context - reg_ctx->add_ival(arch_registers[R_R0], offset_size(regs, uregs[0])); - reg_ctx->add_ival(arch_registers[R_R1], offset_size(regs, uregs[1])); - reg_ctx->add_ival(arch_registers[R_R2], offset_size(regs, uregs[2])); - reg_ctx->add_ival(arch_registers[R_R3], offset_size(regs, uregs[3])); - reg_ctx->add_ival(arch_registers[R_R4], offset_size(regs, uregs[4])); - reg_ctx->add_ival(arch_registers[R_R5], offset_size(regs, uregs[5])); - reg_ctx->add_ival(arch_registers[R_R6], offset_size(regs, uregs[6])); - reg_ctx->add_ival(arch_registers[R_R7], offset_size(regs, uregs[7])); - reg_ctx->add_ival(arch_registers[R_R8], offset_size(regs, uregs[8])); - reg_ctx->add_ival(arch_registers[R_R9], offset_size(regs, uregs[9])); - reg_ctx->add_ival(arch_registers[R_R10], offset_size(regs, uregs[10])); - reg_ctx->add_ival(arch_registers[R_R11], offset_size(regs, uregs[11])); - reg_ctx->add_ival(arch_registers[R_R12], offset_size(regs, uregs[12])); - sp_idx = reg_ctx->add_ival(arch_registers[R_SP], offset_size(regs, uregs[13])); - lr_idx = reg_ctx->add_ival(arch_registers[R_LR], offset_size(regs, uregs[14])); - pc_idx = reg_ctx->add_ival(arch_registers[R_PC], offset_size(regs, uregs[15])); - sr_idx = reg_ctx->add_ival(arch_registers[R_PSR], offset_size(regs, uregs[16])); - -#ifdef __HAVE_ARM_VFP__ - size_t offset = qoffsetof2(vfp_regs, fpregs); - for ( size_t i = R_D0; i <= R_D31; i++, offset += sizeof(int64) ) - reg_ctx->add_data(arch_registers[i], offset, sizeof(int64)); - reg_ctx->add_ival(arch_registers[R_FPSCR], offset_size(vfp_regs, fpscr)); -#endif -} - -# endif -#else // !__ARM__ - -//-------------------------------------------------------------------------- -// X86/X64 -//------------------------------------------------------------------------- - -//-------------------------------------------------------------------------- -//lint -esym(749,TAG_*) local enumeration constant '' not referenced -enum -{ - TAG_VALID = 0, - TAG_ZERO = 1, - TAG_SPECIAL = 2, - TAG_EMPTY = 3, -}; - -//------------------------------------------------------------------------- -// Intel® 64 and IA-32 Architectures Software Developer's Manual -// Volume 1: Basic Architecture -// 253665-070US May 2019 - -// 13.1 XSAVE-SUPPORTED FEATURES AND STATE-COMPONENT BITMAPS -// Bit 1 corresponds to the state component used for registers used by the -// streaming SIMD extensions (SSE state). -#define X86_XSTATE_SSE (1ULL << 1) -// Bit 2 corresponds to the state component used for the additional register -// state used by the Intel® Advanced Vector Extensions (AVX state). -#define X86_XSTATE_AVX (1ULL << 2) - -// 13.4 XSAVE AREA -// The legacy region of an XSAVE area comprises the 512 bytes starting at the -// area's base address. [...] The XSAVE feature set uses the legacy area for -// x87 state (state component 0) and SSE state (state component 1). -#define XSAVE_LEGACY_REGION_OFFSET 0 -// The XSAVE header of an XSAVE area comprises the 64 bytes starting at -// offset 512 from the area’s base address: -#define XSAVE_HEADER_OFFSET 512 -// The extended region of an XSAVE area starts at an offset of 576 bytes from -// the area's base address. -#define XSAVE_EXTENDED_REGION_OFFSET 576 - -// 13.4.2 XSAVE Header -// Bytes 7:0 of the XSAVE header is a state-component bitmap (see Section -// 13.1) called XSTATE_BV. -#define XSAVE_XSTATE_BV XSAVE_HEADER_OFFSET - -// 13.5.2 SSE State -// Bytes 287:160 are used for the registers XMM0–XMM7. -// Bytes 415:288 are used for the registers XMM8–XMM15. -#define XSAVE_XMM_OFFSET_BASE (XSAVE_LEGACY_REGION_OFFSET + 160) - -// 13.5.3 AVX State -// Bytes 127:0 of the AVX-state section are used for YMM0_H–YMM7_H. -// Bytes 255:128 are used for YMM8_H–YMM15_H. -#define XSAVE_YMMH_OFFSET_BASE XSAVE_EXTENDED_REGION_OFFSET - -//-------------------------------------------------------------------------- -struct regctx_t : public regctx_base_t -{ - struct user_regs_struct regs; - struct user_fpregs_struct i387; -#ifdef __X86__ - struct user_fpxregs_struct x387; -#endif - uint8_t xstate[X86_XSTATE_MAX_SIZE]; - struct iovec ymm_iov; - - // clsmask helpers - bool clsmask_regs; - bool clsmask_fpregs; -#ifdef __X86__ - bool clsmask_fpxregs; -#endif - bool clsmask_ymm; - - regctx_t(dynamic_register_set_t &_idaregs); - bool init(void); - bool load(void); - bool store(void); -}; - -//-------------------------------------------------------------------------- -regctx_t::regctx_t(dynamic_register_set_t &_idaregs) - : regctx_base_t(_idaregs) -{ - memset(®s, 0, sizeof(regs)); - memset(&i387, 0, sizeof(i387)); -#ifdef __X86__ - memset(&x387, 0, sizeof(x387)); -#endif - memset(xstate, 0, sizeof(xstate)); - - clsmask_regs = 0; - clsmask_fpregs = 0; -#ifdef __X86__ - clsmask_fpxregs = 0; -#endif - clsmask_ymm = 0; - - ymm_iov.iov_base = xstate; - ymm_iov.iov_len = sizeof(xstate); - - idaregs.set_regclasses(x86_register_classes); -} - -//-------------------------------------------------------------------------- -bool regctx_t::init(void) -{ - if ( (clsmask & X86_RC_ALL) == 0 ) - return false; - // setup clsmask helpers - clsmask_regs = (clsmask & (X86_RC_GENERAL|X86_RC_SEGMENTS)) != 0; -#ifdef __X86__ - // 32-bit version uses two different structures to return xmm & fpu - clsmask_fpregs = (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0; - clsmask_fpxregs = (clsmask & X86_RC_XMM) != 0; -#else - // 64-bit version uses one struct to return xmm & fpu - clsmask_fpregs = (clsmask & (X86_RC_FPU|X86_RC_MMX|X86_RC_XMM)) != 0; -#endif - clsmask_ymm = (clsmask & X86_RC_YMM) != 0; - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::load(void) -{ - if ( !init() ) - return false; - if ( clsmask_regs ) - if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) - return false; - // Note: On linux kernels older than 4.8, the ptrace call to fetch - // registers from xstate did not sanitize the state before - // copying data to user-space. If only the YMM register class - // was requested (and not fp or fpx), this could lead to IDA - // having stale data on the lower half of the YMM registers. - // The ptrace calls to fetch fp or fpx registers do sanitize - // the state. This is the only reason we may also get the fp - // registers when the YMM register class is requested, but - // the fp and fpx registers were not requested. The order is - // important in this case (first fp or fpx, then xstate). -#ifdef __X86__ - bool xstate_sanitized = clsmask_fpregs || clsmask_fpxregs; -#else - bool xstate_sanitized = clsmask_fpregs; -#endif - if ( clsmask_fpregs || (clsmask_ymm && !xstate_sanitized) ) - if ( qptrace(PTRACE_GETFPREGS, tid, 0, &i387) != 0 ) - return false; -#ifdef __X86__ - if ( clsmask_fpxregs ) - if ( qptrace(PTRACE_GETFPXREGS, tid, 0, &x387) != 0 ) - return false; -#endif - if ( clsmask_ymm ) - if ( !qptrace_get_regset(&ymm_iov, NT_X86_XSTATE, tid) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::store(void) -{ - if ( clsmask_regs ) - if ( qptrace(PTRACE_SETREGS, tid, 0, ®s) != 0 ) - return false; - // The order of the following calls is VERY IMPORTANT so as - // PTRACE_SETFPXREGS can spoil FPU registers. - // The subsequent call to PTRACE_SETFPREGS will correct them. - // Could it be better to get rid of PTRACE_SETFPREGS and use - // PTRACE_SETFPXREGS for both FPU and XMM registers instead? - if ( clsmask_ymm ) - if ( !qptrace_set_regset(NT_X86_XSTATE, tid, ymm_iov) ) - return false; -#ifdef __X86__ - if ( clsmask_fpxregs ) - if ( qptrace(PTRACE_SETFPXREGS, tid, 0, &x387) != 0 ) - return false; -#endif - if ( clsmask_fpregs ) - if ( qptrace(PTRACE_SETFPREGS, tid, 0, &i387) != 0 ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -static void ftag_read(const regctx_t *ctx, regval_t *value, void * /*user_data*/) -{ - uint32_t ival = ctx->i387.TAGS_REG; -#ifndef __X86__ - // fix 'ftag': - // --- - // Byte 4 is used for an abridged version of the x87 FPU Tag - // Word (FTW). The following items describe its usage: - // — For each j, 0 <= j <= 7, FXSAVE saves a 0 into bit j of - // byte 4 if x87 FPU data register STj has a empty tag; - // otherwise, FXSAVE saves a 1 into bit j of byte 4. - // (...) - // --- - // See also the opposite conversion when writing registers - // (look for 'abridged'.) - uint8_t abridged = ival; - int top = (ctx->i387.swd >> 11) & 0x7; - uint16_t ftag = 0; - for ( int st_idx = 7; st_idx >= 0; --st_idx ) - { - uint16_t tag = TAG_EMPTY; - if ( (abridged & (1 << st_idx)) != 0 ) - { - int actual_st = (st_idx + 8 - top) % 8; - const uint8_t *p = ((const uint8_t *) ctx->i387.st_space) + actual_st * (sizeof(ctx->i387.st_space)/8); //-V706 Suspicious division - bool integer = (p[7] & 0x80) != 0; - uint32 exp = ((p[9] & 0x7f) << 8) | p[8]; //-V557 Array overrun is possible - uint32 frac0 = ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); - uint32 frac1 = (((p[7] & 0x7f) << 24) | (p[6] << 16) | (p[5] << 8) | p[4]); - if ( exp == 0x7fff ) - tag = TAG_SPECIAL; - else if ( exp == 0 ) - tag = (frac0 == 0 && frac1 == 0 && !integer) ? TAG_ZERO : TAG_SPECIAL; - else - tag = integer ? TAG_VALID : TAG_SPECIAL; - } - ftag |= tag << (2 * st_idx); - } - ival = ftag; -#endif - value->ival = ival; -} - -//-------------------------------------------------------------------------- -static void ftag_write(regctx_t *ctx, const regval_t *value, void * /*user_data*/) -{ -#ifndef __X86__ - // => abridged - // See also the opposite conversion when reading registers - // (look for 'abridged'.) - // - // NOTE: This assumes that i387.swd _IS UP-TO-DATE_. - // If it has to be overwritten later in the same batch of - // updates, its new value won't be used here. - uint16_t expanded = value->ival; - uint8_t tags = 0; - int top = (ctx->i387.swd >> 11) & 0x7; - for ( int st_idx = 7; st_idx >= 0; --st_idx ) - if ( ((expanded >> (2 * st_idx)) & 3) != TAG_EMPTY ) - tags |= uint8_t(1 << ((st_idx + 8 - top) % 8)); - ctx->i387.TAGS_REG = tags; -#else - ctx->i387.TAGS_REG = value->ival; -#endif -} - -//-------------------------------------------------------------------------- -static void ymm_read(const regctx_t *ctx, regval_t *value, void *user_data) -{ - size_t ymm_reg_idx = size_t(user_data); - const uint128 *ptrl = (uint128 *) &ctx->xstate[XSAVE_XMM_OFFSET_BASE]; - const uint128 *ptrh = (uint128 *) &ctx->xstate[XSAVE_YMMH_OFFSET_BASE]; - uint8_t ymm[32]; - *(uint128 *) &ymm[ 0] = ptrl[ymm_reg_idx]; - *(uint128 *) &ymm[16] = ptrh[ymm_reg_idx]; - value->set_bytes(ymm, sizeof(ymm)); -} - -//-------------------------------------------------------------------------- -static void ymm_write(regctx_t *ctx, const regval_t *value, void *user_data) -{ - size_t ymm_reg_idx = size_t(user_data); - const uint8_t *ymm = (const uint8_t *) value->get_data(); - uint128 *ptrl = (uint128 *) &ctx->xstate[XSAVE_XMM_OFFSET_BASE]; - uint128 *ptrh = (uint128 *) &ctx->xstate[XSAVE_YMMH_OFFSET_BASE]; - ptrl[ymm_reg_idx] = *(uint128 *) &ymm[ 0]; - ptrh[ymm_reg_idx] = *(uint128 *) &ymm[16]; - ctx->xstate[XSAVE_XSTATE_BV] |= X86_XSTATE_SSE | X86_XSTATE_AVX; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::init_reg_ctx(void) -{ - reg_ctx = new regctx_t(idaregs); - - // Populate register context - size_t offset = 0; - -#ifdef __EA64__ - bool is_64 = debapp_attrs.addrsize > 4; - if ( is_64 ) - { - reg_ctx->add_ival(r_rax, offset_size(regs, INTEL_REG(ax))); - reg_ctx->add_ival(r_rbx, offset_size(regs, INTEL_REG(bx))); - reg_ctx->add_ival(r_rcx, offset_size(regs, INTEL_REG(cx))); - reg_ctx->add_ival(r_rdx, offset_size(regs, INTEL_REG(dx))); - reg_ctx->add_ival(r_rsi, offset_size(regs, INTEL_REG(si))); - reg_ctx->add_ival(r_rdi, offset_size(regs, INTEL_REG(di))); - reg_ctx->add_ival(r_rbp, offset_size(regs, INTEL_REG(bp))); - sp_idx = reg_ctx->add_ival(r_rsp, offset_size(regs, INTEL_REG(sp))); - pc_idx = reg_ctx->add_ival(r_rip, offset_size(regs, INTEL_REG(ip))); - reg_ctx->add_ival(r_r8, offset_size(regs, r8)); - reg_ctx->add_ival(r_r9, offset_size(regs, r9)); - reg_ctx->add_ival(r_r10, offset_size(regs, r10)); - reg_ctx->add_ival(r_r11, offset_size(regs, r11)); - reg_ctx->add_ival(r_r12, offset_size(regs, r12)); - reg_ctx->add_ival(r_r13, offset_size(regs, r13)); - reg_ctx->add_ival(r_r14, offset_size(regs, r14)); - reg_ctx->add_ival(r_r15, offset_size(regs, r15)); - } - else -#endif - { - reg_ctx->add_ival(r_eax, offset_size(regs, INTEL_REG(ax))); - reg_ctx->add_ival(r_ebx, offset_size(regs, INTEL_REG(bx))); - reg_ctx->add_ival(r_ecx, offset_size(regs, INTEL_REG(cx))); - reg_ctx->add_ival(r_edx, offset_size(regs, INTEL_REG(dx))); - reg_ctx->add_ival(r_esi, offset_size(regs, INTEL_REG(si))); - reg_ctx->add_ival(r_edi, offset_size(regs, INTEL_REG(di))); - reg_ctx->add_ival(r_ebp, offset_size(regs, INTEL_REG(bp))); - sp_idx = reg_ctx->add_ival(r_esp, offset_size(regs, INTEL_REG(sp))); - pc_idx = reg_ctx->add_ival(r_eip, offset_size(regs, INTEL_REG(ip))); - } - sr_idx = reg_ctx->add_ival(arch_registers[R_EFLAGS], offset_size(regs, eflags)); - - cs_idx = reg_ctx->add_ival(arch_registers[R_CS], offset_size(regs, INTEL_SREG(cs))); - ds_idx = reg_ctx->add_ival(arch_registers[R_DS], offset_size(regs, INTEL_SREG(ds))); - es_idx = reg_ctx->add_ival(arch_registers[R_ES], offset_size(regs, INTEL_SREG(es))); - fs_idx = reg_ctx->add_ival(arch_registers[R_FS], offset_size(regs, INTEL_SREG(fs))); - gs_idx = reg_ctx->add_ival(arch_registers[R_GS], offset_size(regs, INTEL_SREG(gs))); - ss_idx = reg_ctx->add_ival(arch_registers[R_SS], offset_size(regs, INTEL_SREG(ss))); - - offset = qoffsetof2(i387, st_space); - for ( size_t i = R_ST0; i <= R_ST7; i++, offset += sizeof(regctx_t::i387.st_space)/8 ) //-V706 Suspicious division - reg_ctx->add_fval(arch_registers[i], offset, 10); - reg_ctx->add_ival(arch_registers[R_CTRL], offset_size(i387, cwd)); - reg_ctx->add_ival(arch_registers[R_STAT], offset_size(i387, swd)); - reg_ctx->add_func(arch_registers[R_TAGS], ftag_read, ftag_write); - - offset = qoffsetof2(i387, st_space); - for ( size_t i = R_MMX0; i <= R_MMX7; i++, offset += sizeof(regctx_t::i387.st_space)/8 ) //-V706 Suspicious division - reg_ctx->add_data(arch_registers[i], offset, 8); - - offset = qoffsetof2(XMM_STRUCT, xmm_space); - for ( size_t i = R_XMM0; i <= R_LAST_XMM; i++, offset += 16 ) - { -#ifdef __EA64__ - if ( !is_64 && i >= R_XMM8 ) - break; -#endif - reg_ctx->add_data(arch_registers[i], offset, 16); - } - reg_ctx->add_ival(arch_registers[R_MXCSR], offset_size(XMM_STRUCT, mxcsr)); - - for ( size_t i = R_YMM0; i <= R_LAST_YMM; i++ ) - { -#ifdef __EA64__ - if ( !is_64 && i >= R_YMM8 ) - break; -#endif - reg_ctx->add_func(arch_registers[i], ymm_read, ymm_write, (void *) (i - R_YMM0)); - } -} -#endif // !__ARM__ - -//-------------------------------------------------------------------------- -void linux_debmod_t::term_reg_ctx(void) -{ - if ( reg_ctx != nullptr ) - { - delete reg_ctx; - idaregs.clear(); - } - reg_ctx = nullptr; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_read_registers( - thid_t tid, - int clsmask, - regval_t *values, - qstring * /*errbuf*/) -{ - if ( values == nullptr ) - return DRC_FAILED; - - reg_ctx->setup(tid, clsmask); - if ( !reg_ctx->load() ) - return DRC_FAILED; - - reg_ctx->read_all(values); - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_write_register( - thid_t tid, - int reg_idx, - const regval_t *value, - qstring * /*errbuf*/) -{ - if ( value == nullptr ) - return DRC_FAILED; - - reg_ctx->setup(tid); - reg_ctx->setup_reg(reg_idx); - if ( !reg_ctx->load() ) - return DRC_FAILED; - - if ( reg_idx == pc_idx ) - ldeb("NEW EIP: %08" FMT_64 "X\n", value->ival); - - if ( !reg_ctx->patch(reg_idx, value) ) - return DRC_FAILED; - - if ( !reg_ctx->store() ) - return DRC_FAILED; - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -bool idaapi linux_debmod_t::write_registers( - thid_t tid, - int start, - int count, - const regval_t *values) -{ - if ( values == nullptr ) - return false; - - reg_ctx->setup(tid); - for ( size_t i = 0; i < count; i++ ) - reg_ctx->setup_reg(start + i); - if ( !reg_ctx->load() ) - return false; - - for ( size_t i = 0; i < count; i++, values++ ) - if ( !reg_ctx->patch(start + i, values) ) - return false; - - if ( !reg_ctx->store() ) - return false; - - return true; -} - -//-------------------------------------------------------------------------- -// find DT_SONAME of a elf image directly from the memory -bool linux_debmod_t::get_soname(const char *fname, qstring *soname) const -{ - struct dll_soname_finder_t : public symbol_visitor_t - { - qstring *soname; - dll_soname_finder_t(qstring *res) : symbol_visitor_t(VISIT_DYNINFO), soname(res) {} - virtual int visit_dyninfo(uint64 tag, const char *name, uint64 /*value*/) override - { - if ( tag == DT_SONAME ) - { - *soname = name; - return 1; - } - return 0; - } - }; - - dll_soname_finder_t dsf(soname); - return load_elf_symbols(fname, dsf) == 1; -} - -//-------------------------------------------------------------------------- -asize_t linux_debmod_t::calc_module_size(const meminfo_vec_t &miv, const memory_info_t *mi) const -{ - QASSERT(30067, miv.begin() <= mi && mi < miv.end()); - ea_t start = mi->start_ea; - ea_t end = mi->end_ea; - if ( end == 0 ) - return 0; // unknown size - const qstring &name = mi->name; - while ( ++mi != miv.end() ) - { - if ( name != mi->name ) - break; - end = mi->end_ea; - } - QASSERT(30068, end > start); - return end - start; -} - -//-------------------------------------------------------------------------- -// may add/del threads! -void linux_debmod_t::handle_dll_movements(const meminfo_vec_t &_miv) -{ - ldeb("handle_dll_movements\n"); - - // first, merge memory ranges by module - meminfo_vec_t miv; - for ( size_t i = 0, n = _miv.size(); i < n; ++i ) - { - const memory_info_t &src = _miv[i]; - - // See if we already registered a module with that name. - memory_info_t *target = find_dll(miv, src.name.c_str()); - if ( target != NULL ) - { - // Found one. Let's make sure it contains our addresses. - target->extend(src.start_ea); - target->extend(src.end_ea); - } - else - { - miv.push_back(src); - } - } - - // unload missing dlls - images_t::iterator p; - for ( p=dlls.begin(); p != dlls.end(); ) - { - image_info_t &ii = p->second; - const char *fname = ii.fname.c_str(); - if ( find_dll(miv, fname) == NULL ) - { - if ( !del_pending_event(LIB_LOADED, fname) ) - { - debug_event_t ev; - ev.set_info(LIB_UNLOADED) = fname; - ev.pid = process_handle; - ev.tid = process_handle; - ev.ea = BADADDR; - ev.handled = true; - enqueue_event(ev, IN_FRONT); - } - p = dlls.erase(p); - } - else - { - ++p; - } - } - - // load new dlls - int n = miv.size(); - for ( int i=0; i < n; i++ ) - { - // ignore unnamed dlls - if ( miv[i].name.empty() ) - continue; - - // ignore the input file - if ( !is_dll && miv[i].name == input_file_path ) - continue; - - // ignore if dll already exists - ea_t base = miv[i].start_ea; - p = dlls.find(base); - if ( p != dlls.end() ) - continue; - - // ignore memory chunks which do not correspond to an ELF header - char magic[4]; - if ( _read_memory(-1, base, magic, 4, false) != 4 ) - continue; - - if ( memcmp(magic, "\x7F\x45\x4C\x46", 4) != 0 ) - continue; - - qstring soname; - const char *modname = miv[i].name.c_str(); - get_soname(modname, &soname); - asize_t size = calc_module_size(miv, &miv[i]); - add_dll(base, size, modname, soname.c_str()); - } - if ( !dlls_to_import.empty() ) - tdb_new(); -} - -//-------------------------------------------------------------------------- -// this function has a side effect: it sets debapp_attrs.addrsize to 8 -// if founds a 64-bit address in the mapfile -bool linux_debmod_t::read_mapping(mapfp_entry_t *me) -{ - qstring line; - if ( qgetline(&line, mapfp) <= 0 ) - return false; - - me->ea1 = BADADDR; - me->bitness = 0; - int len = 0; - me->perm[7] = '\0'; - me->device[7] = '\0'; - CASSERT(sizeof(me->perm) == 8); - CASSERT(sizeof(me->device) == 8); - int code = qsscanf(line.begin(), "%a-%a %7s %a %7s %" FMT_64 "x%n", - &me->ea1, &me->ea2, me->perm, - &me->offset, me->device, &me->inode, &len); - if ( code == 6 ) - { - me->bitness = 1; - size_t pos = line.find('-'); - if ( pos != qstring::npos && pos > 8 ) - { - me->bitness = 2; - debapp_attrs.addrsize = 8; - } - char *ptr = line.begin() + len; - ptr = skip_spaces(ptr); - // remove trailing spaces and eventual (deleted) suffix - static const char delsuff[] = " (deleted)"; - const int suflen = sizeof(delsuff) - 1; - char *end = tail(ptr); - while ( end > ptr && qisspace(end[-1]) ) - *--end = '\0'; - if ( end-ptr > suflen && strncmp(end-suflen, delsuff, suflen) == 0 ) - end[-suflen] = '\0'; - me->fname = ptr; - } - return me->ea1 != BADADDR; -} - -//-------------------------------------------------------------------------- -drc_t linux_debmod_t::get_memory_info(meminfo_vec_t &miv, bool suspend) -{ - ldeb("get_memory_info(suspend=%d)\n", suspend); - if ( exited || mapfp == NULL ) - return DRC_NOPROC; - if ( suspend ) - suspend_all_threads(); - - rewind(mapfp); - mapfp_entry_t me; - qstrvec_t possible_interp; - int bitness = 1; - while ( read_mapping(&me) ) - { - // skip empty ranges - if ( me.empty() ) - continue; - - if ( interp.empty() && !me.fname.empty() && !possible_interp.has(me.fname) ) - { - //check for [.../]ld-XXX.so" - size_t pos = me.fname.find("ld-"); - if ( pos != qstring::npos && (pos == 0 || me.fname[pos-1] == '/') ) - possible_interp.push_back(me.fname); - } - - // for some reason linux lists some ranges twice - // ignore them - int i; - for ( i=0; i < miv.size(); i++ ) - if ( miv[i].start_ea == me.ea1 ) - break; - if ( i != miv.size() ) - continue; - - memory_info_t &mi = miv.push_back(); - mi.start_ea = me.ea1; - mi.end_ea = me.ea2; - mi.name.swap(me.fname); -#ifdef __ANDROID__ - // android reports simple library names without path. try to find it. - make_android_abspath(&mi.name); -#endif - mi.bitness = me.bitness; - //msg("%s: %a..%a. Bitness: %d\n", mi.name.c_str(), mi.start_ea, mi.end_ea, mi.bitness); - - if ( bitness < mi.bitness ) - bitness = mi.bitness; - - if ( strchr(me.perm, 'r') != NULL ) - mi.perm |= SEGPERM_READ; - if ( strchr(me.perm, 'w') != NULL ) - mi.perm |= SEGPERM_WRITE; - if ( strchr(me.perm, 'x') != NULL ) - mi.perm |= SEGPERM_EXEC; - } - - if ( !possible_interp.empty() ) - { - bool ok = false; - - for ( size_t i = 0; i < possible_interp.size(); ++i ) - { - interp = possible_interp[i]; - debdeb("trying potential interpreter %s\n", interp.c_str()); - if ( add_shlib_bpt(miv, true) ) - { - ok = true; - dmsg("Found a valid interpeter in %s, will report shared library events!\n", interp.c_str()); - handle_dll_movements(miv); - } - } - - if ( !ok ) - interp.qclear(); - } - - // During the parsing of each memory segment we had just guessed the bitness. - // So fix now bitness of all memory segments - for ( int i = 0; i < miv.size(); i++ ) - miv[i].bitness = bitness; - - if ( suspend ) - resume_all_threads(); - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_get_memory_info(meminfo_vec_t &ranges, qstring * /*errbuf*/) -{ - drc_t drc = get_memory_info(ranges, false); - if ( drc == DRC_OK ) - { - if ( same_as_oldmemcfg(ranges) ) - drc = DRC_NOCHG; - else - save_oldmemcfg(ranges); - } - return drc; -} - -//-------------------------------------------------------------------------- -linux_debmod_t::~linux_debmod_t() -{ - term_reg_ctx(); - mapfp = NULL; - ta = NULL; -} - -//-------------------------------------------------------------------------- -void idaapi linux_debmod_t::dbg_set_debugging(bool _debug_debugger) -{ - debug_debugger = _debug_debugger; -} - -//-------------------------------------------------------------------------- -drc_t idaapi linux_debmod_t::dbg_init(uint32_t *flags2, qstring * /*errbuf*/) -{ - dbg_term(); // initialize various variables - if ( flags2 != nullptr ) - *flags2 = DBG_HAS_GET_PROCESSES | DBG_HAS_DETACH_PROCESS; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -void idaapi linux_debmod_t::dbg_term(void) -{ - cleanup(); - cleanup_hwbpts(); -} - -//-------------------------------------------------------------------------- -//lint -save -esym(818,pea) could be pointer to const -bool idaapi linux_debmod_t::thread_get_fs_base(thid_t tid, int reg_idx, ea_t *pea) const -{ -#if !defined(__ARM__) && !defined(__X86__) - - /* The following definitions come from prctl.h, but may be absent - for certain configurations. */ - #ifndef ARCH_GET_FS - #define ARCH_SET_GS 0x1001 - #define ARCH_SET_FS 0x1002 - #define ARCH_GET_FS 0x1003 - #define ARCH_GET_GS 0x1004 - #endif - - if ( reg_idx == fs_idx ) - { - if ( qptrace(PTRACE_ARCH_PRCTL, tid, pea, (void *) ARCH_GET_FS) == 0 ) - return true; - } - else if ( reg_idx == gs_idx ) - { - if ( qptrace(PTRACE_ARCH_PRCTL, tid, pea, (void *) ARCH_GET_GS) == 0 ) - return true; - } - else if ( reg_idx == cs_idx - || reg_idx == ds_idx - || reg_idx == es_idx - || reg_idx == ss_idx ) - { - *pea = 0; - return true; - } - return false; -#else - qnotused(tid); - qnotused(reg_idx); - qnotused(pea); - return false; -#endif -} //lint -restore - -//-------------------------------------------------------------------------- -int idaapi linux_debmod_t::handle_ioctl(int fn, const void *in, size_t, void **, ssize_t *) -{ - if ( fn == 0 ) // chmod +x - { - // this call is not used anymore - char *fname = (char *)in; - qstatbuf st; - qstat(fname, &st); - int mode = st.qst_mode | S_IXUSR|S_IXGRP|S_IXOTH; - chmod(fname, mode); - } - return 0; -} - -//-------------------------------------------------------------------------- -// recovering from a broken session consists in the following steps: -// -// 1 - Cleanup dlls previously recorded. -// 2 - Do like if we were attaching (calling handle_process_start(attaching=>AMT_ATTACH_BROKEN)) -// 3 - Generate library events. -// 4 - Restore RIP/EIP if we stopped in a breakpoint. -// -bool idaapi linux_debmod_t::dbg_continue_broken_connection(pid_t _pid) -{ - debmod_t::dbg_continue_broken_connection(_pid); - bool ret = in_event = false; - - // cleanup previously recorded information - dlls.clear(); - - // restore broken breakpoints and continue like a normal attach - if ( restore_broken_breakpoints() && handle_process_start(_pid, AMT_ATTACH_BROKEN) ) - { - // generate all library events - gen_library_events(_pid); - - // fix instruction pointer in case we're at a breakpoint - if ( !fix_instruction_pointer() ) - dmsg("Debugger failed to correctly restore the instruction pointer after recovering from a broken connection.\n"); - - // and finally pause the process - ret = true; - } - return ret; -} - -//-------------------------------------------------------------------------- -// if the process was stopped at a breakpoint and then the connections goes -// down, when re-attaching the process we may be at EIP+1 (Intel procs) so -// we need to change EIP to EIP-1 -bool linux_debmod_t::fix_instruction_pointer(void) const -{ - bool ret = true; -#if !defined(__ARM__) - if ( last_event.eid() == BREAKPOINT ) - { - ret = false; - struct user_regs_struct regs; - if ( qptrace(PTRACE_GETREGS, last_event.tid, 0, ®s) == 0 ) - { - if ( last_event.ea == regs.PCREG-1 ) - regs.PCREG--; - - ret = qptrace(PTRACE_SETREGS, last_event.tid, 0, ®s) == 0; - } - } -#endif - return ret; -} - -//-------------------------------------------------------------------------- -bool init_subsystem() -{ - tdb_init(); - qatexit(kill_all_processes); - linux_debmod_t::reuse_broken_connections = true; - return true; -} - -//-------------------------------------------------------------------------- -bool term_subsystem() -{ - del_qatexit(kill_all_processes); - tdb_term(); - return true; -} - -//-------------------------------------------------------------------------- -debmod_t *create_debug_session(void *params) -{ -#ifdef TESTABLE_BUILD - // new_client_handler(), and thus create_debug_session() is called from - // the main thread, so we don't risk a race for setting up the resolver. - if ( per_pid_elf_dbgdir_resolver == NULL ) - per_pid_elf_dbgdir_resolver = (per_pid_elf_dbgdir_resolver_t *) params; //lint !e611 cast between pointer to function type '' and pointer to object type 'void *' -#else - qnotused(params); -#endif - return new linux_debmod_t(); -} diff --git a/idasdk75/dbg/linux/linux_debmod.h b/idasdk75/dbg/linux/linux_debmod.h deleted file mode 100644 index ef89abf..0000000 --- a/idasdk75/dbg/linux/linux_debmod.h +++ /dev/null @@ -1,349 +0,0 @@ -#ifndef __LINUX_DEBUGGER_MODULE__ -#define __LINUX_DEBUGGER_MODULE__ - -#include -#include -#include -#include - -#include "linuxbase_debmod.h" - -extern "C" -{ -#include -} - -#include -#include - -typedef int HANDLE; -typedef uint32 DWORD; -#define INVALID_HANDLE_VALUE (-1) - -using std::pair; -using std::make_pair; - -//-------------------------------------------------------------------------- -typedef std::map ea2name_t; -typedef std::map name2ea_t; - -#ifndef WCONTINUED -#define WCONTINUED 8 -#endif - -#ifndef __WALL -#define __WALL 0x40000000 -#endif - -//-------------------------------------------------------------------------- -// image information -struct image_info_t -{ - image_info_t() : base(BADADDR), size(0), dl_crc(0) {} - image_info_t( - ea_t _base, - asize_t _size, - const qstring &_fname, - const qstring &_soname) - : base(_base), size(_size), fname(_fname), soname(_soname), dl_crc(0) {} - ea_t base; - asize_t size; // image size, currently 0 - qstring fname; - qstring soname; - ea2name_t names; - qstring buildid; - qstring debuglink; - uint32 dl_crc; -}; -typedef std::map images_t; // key: image base address - -//-------------------------------------------------------------------------- -enum thstate_t -{ - RUNNING, // running - STOPPED, // waiting to be resumed after qwait - DYING, // we got a notification that the thread is about to die - DEAD, // dead thread; ignore any signals from it -}; - -//-------------------------------------------------------------------------- -// thread information -struct thread_info_t -{ - thread_info_t(int t) - : tid(t), suspend_count(0), user_suspend(0), child_signum(0), single_step(false), - state(STOPPED), waiting_sigstop(false), got_pending_status(false), pending_status(0) {} - int tid; - int suspend_count; - int user_suspend; - int child_signum; - bool single_step; - thstate_t state; - bool waiting_sigstop; - bool got_pending_status; - int pending_status; - qstring name; // thread name - bool is_running(void) const - { - return state == RUNNING && !waiting_sigstop && !got_pending_status; - } -}; - -//-------------------------------------------------------------------------- -typedef std::map threads_t; // (tid -> info) - -//-------------------------------------------------------------------------- -enum ps_err_e -{ - PS_OK, /* Success. */ - PS_ERR, /* Generic error. */ - PS_BADPID, /* Bad process handle. */ - PS_BADLID, /* Bad LWP id. */ - PS_BADADDR, /* Bad address. */ - PS_NOSYM, /* Symbol not found. */ - PS_NOFREGS /* FPU register set not available. */ -}; -struct ps_prochandle -{ - pid_t pid; -}; - -#ifndef UINT32_C -# define UINT32_C uint32 -#endif - -//-------------------------------------------------------------------------- -struct internal_bpt -{ - ea_t bpt_addr; - uchar saved[BPT_CODE_SIZE]; - uchar nsaved; - internal_bpt(): bpt_addr(0), nsaved(0) {} //-V730 Not all members of a class are initialized -}; - -//-------------------------------------------------------------------------- -struct mapfp_entry_t -{ - ea_t ea1; - ea_t ea2; - ea_t offset; - uint64 inode; - char perm[8]; - char device[8]; - uint8 bitness; // Number of bits in segment addresses (0-16bit, 1-32bit, 2-64bit) - qstring fname; - bool empty(void) const { return ea1 >= ea2; } -}; - -//-------------------------------------------------------------------------- -struct chk_signal_info_t -{ - pid_t pid; - int status; - int timeout_ms; - - chk_signal_info_t(int _timeout_ms) - { - timeout_ms = _timeout_ms; - pid = 0; - status = 0; - } -}; - -//-------------------------------------------------------------------------- -enum attach_mode_t -{ - AMT_NO_ATTACH, - AMT_ATTACH_NORMAL, - AMT_ATTACH_BROKEN -}; - -//-------------------------------------------------------------------------- -class linux_debmod_t: public linuxbase_debmod_t -{ - typedef linuxbase_debmod_t inherited; - - // thread_db related data and functions: - struct ps_prochandle prochandle; - td_thragent_t *ta; - - internal_bpt birth_bpt; //thread created - internal_bpt death_bpt; //thread exited - internal_bpt shlib_bpt; //shared lib list changed - bool complained_shlib_bpt; - - void make_android_abspath(qstring *in_out_path); - bool add_android_shlib_bpt(const meminfo_vec_t &miv, bool attaching); - - bool add_internal_bp(internal_bpt &bp, ea_t addr); - bool erase_internal_bp(internal_bpt &bp); - - bool tdb_enable_event(td_event_e event, internal_bpt *bp); - void tdb_update_threads(void); - bool tdb_new(void); - void tdb_delete(void); - void tdb_handle_messages(int pid); - void dead_thread(int tid, thstate_t state); - void store_pending_signal(int pid, int status); - - // procfs - void procfs_collect_threads(void); - bool attach_collected_thread(unsigned long lwp); - bool get_thread_name(qstring *thr_name, thid_t tid); - void update_thread_names(thread_name_vec_t *thr_names); - - // list of debug names not yet sent to IDA - name_info_t pending_names; - name_info_t nptl_names; - - pid_t check_for_signal(int *status, int pid, int timeout_ms) const; - - int find_largest_addrsize(const meminfo_vec_t &miv); - void _import_dll(image_info_t &ii); - void _import_symbols_from_file(name_info_t *out, image_info_t &ii); - -public: - easet_t dlls_to_import; // list of dlls to import information from - images_t dlls; // list of loaded DLLs - threads_t threads; - qvector deleted_threads; - qvector seen_threads; // thread was born and appeared too early - - // debugged process information - HANDLE process_handle; - HANDLE thread_handle; - - bool exited; // Did the process exit? - - easet_t removed_bpts; // removed breakpoints - - FILE *mapfp; // map file handle - - int npending_signals; // number of pending signals - bool may_run; - bool requested_to_suspend; - bool in_event; // IDA kernel is handling a debugger event - - qstring interp; - - qstring exe_path; // name of the executable file - - ea_t nptl_base; // base of 'libpthread.so' - - regctx_t *reg_ctx; - - linux_debmod_t(); - ~linux_debmod_t(); - - void init_reg_ctx(void); - void term_reg_ctx(void); - - thread_info_t &add_thread(int tid); - void del_thread(int tid); - thread_info_t *get_thread(thid_t tid); - bool retrieve_pending_signal(pid_t *pid, int *status); - int get_debug_event(debug_event_t *event, int timeout_ms); - bool del_pending_event(event_id_t id, const char *module_name); - void enqueue_event(const debug_event_t &ev, queue_pos_t pos); - bool suspend_all_threads(void); - bool resume_all_threads(void); - int dbg_freeze_threads(thid_t tid, bool exclude=true); - int dbg_thaw_threads(thid_t tid, bool exclude=true); - void set_thread_state(thread_info_t &ti, thstate_t state) const; - bool resume_app(thid_t tid); - bool has_pending_events(void); - bool read_asciiz(tid_t tid, ea_t ea, char *buf, size_t bufsize, bool suspend=false); - int _read_memory(int tid, ea_t ea, void *buffer, int size, bool suspend=false); - int _write_memory(int tid, ea_t ea, const void *buffer, int size, bool suspend=false); - void add_dll(ea_t base, asize_t size, const char *modname, const char *soname); - asize_t calc_module_size(const meminfo_vec_t &miv, const memory_info_t *mi) const; - void enum_names(const char *libpath=NULL); - bool add_shlib_bpt(const meminfo_vec_t &miv, bool attaching); - bool gen_library_events(int tid); - bool emulate_retn(int tid); - void cleanup(void); - bool handle_process_start(pid_t pid, attach_mode_t attaching); - drc_t get_memory_info(meminfo_vec_t &areas, bool suspend); - bool set_hwbpts(HANDLE hThread) const; - virtual bool refresh_hwbpts() override; - void handle_dll_movements(const meminfo_vec_t &miv); - bool idaapi thread_get_fs_base(thid_t tid, int reg_idx, ea_t *pea) const; - bool read_mapping(mapfp_entry_t *me); - bool get_soname(const char *fname, qstring *soname) const; - ea_t find_pending_name(const char *name); - bool handle_hwbpt(debug_event_t *event); - bool thread_is_known(const td_thrinfo_t &info) const; - bool listen_thread_events(const td_thrinfo_t &info, const td_thrhandle_t *th_p); - void attach_to_thread(const td_thrinfo_t &info); - void attach_to_thread(int tid, ea_t ea); - bool check_for_new_events(chk_signal_info_t *csi, bool *event_prepared); - void handle_extended_wait(bool *handled, const chk_signal_info_t &csi); - - // - virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; - virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; - virtual void idaapi dbg_term(void) override; - virtual drc_t idaapi dbg_detach_process(void) override; - virtual drc_t idaapi dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) override; - virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; - virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) override; - virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; - virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) override; - virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; - virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; - virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; - virtual drc_t idaapi dbg_read_registers( - thid_t thread_id, - int clsmask, - regval_t *values, - qstring *errbuf) override; - virtual drc_t idaapi dbg_write_register( - thid_t thread_id, - int reg_idx, - const regval_t *value, - qstring *errbuf) override; - virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) override; - virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &areas, qstring *errbuf) override; - virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; - virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; - virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; - virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; - virtual int idaapi handle_ioctl(int fn, const void *buf, size_t size, void **outbuf, ssize_t *outsize) override; - virtual bool idaapi write_registers( - thid_t tid, - int start, - int count, - const regval_t *values) override; - virtual int dbg_freeze_threads_except(thid_t tid) override { return dbg_freeze_threads(tid); } - virtual int dbg_thaw_threads_except(thid_t tid) override { return dbg_thaw_threads(tid); } - - virtual bool idaapi dbg_continue_broken_connection(pid_t pid) override; - virtual bool idaapi dbg_prepare_broken_connection(void) override; - - // thread_db - void display_thrinfo(thid_t tid); - void display_all_threads(); - - void cleanup_breakpoints(void); - void cleanup_signals(void); - - bool fix_instruction_pointer(void) const; -#ifdef __ARM__ - virtual void adjust_swbpt(ea_t *p_ea, int *p_len) override; -#endif - -#ifdef LDEB - void log(thid_t tid, const char *format, ...); -#endif -}; - -#endif diff --git a/idasdk75/dbg/linux/linux_threads.cpp b/idasdk75/dbg/linux/linux_threads.cpp deleted file mode 100644 index 2f033eb..0000000 --- a/idasdk75/dbg/linux/linux_threads.cpp +++ /dev/null @@ -1,1275 +0,0 @@ -/* - Thread support for IDA debugger under Linux. -*/ - -//#define TDEB // debug threads - -//------------------------------------------------------------------- -#ifdef TDEB -#define ddeb(x) _ddeb x -AS_PRINTF(1, 2) inline void _ddeb(const char *format, ...) -{ - va_list va; - va_start(va, format); - vmsg(format, va); - va_end(va); -} -#else -#define ddeb(x) (void)0 -#endif - -//------------------------------------------------------------------- -//#define MANUALLY_LOAD_THREAD_DB -#ifdef MANUALLY_LOAD_THREAD_DB -// On some systems libthread_db cannot be linked statically because only .so files exists. -// Also, linking it statically is probably a bad idea because it is closely -// tied to the thread implementation. -// Therefore we manually load libthread_db.so. - -// Prototypes of functions we use from libthread_db.so: -typedef td_err_e td_init_t(void); -typedef td_err_e td_ta_delete_t(td_thragent_t *__ta); -typedef td_err_e td_ta_event_addr_t(const td_thragent_t *__ta, td_event_e __event, td_notify_t *__ptr); -typedef td_err_e td_ta_event_getmsg_t(const td_thragent_t *__ta, td_event_msg_t *__msg); -typedef td_err_e td_ta_map_lwp2thr_t(const td_thragent_t *__ta, lwpid_t __lwpid, td_thrhandle_t *__th); -typedef td_err_e td_ta_new_t(struct ps_prochandle *__ps, td_thragent_t **__ta); -typedef td_err_e td_ta_set_event_t(const td_thragent_t *__ta, td_thr_events_t *__event); -typedef td_err_e td_ta_thr_iter_t(const td_thragent_t *__ta, td_thr_iter_f *__callback, void *__cbdata_p, td_thr_state_e __state, int __ti_pri, sigset_t *__ti_sigmask_p, unsigned int __ti_user_flags); -typedef td_err_e td_thr_event_enable_t(const td_thrhandle_t *__th, int __event); -typedef td_err_e td_thr_get_info_t(const td_thrhandle_t *__th, td_thrinfo_t *__infop); -typedef td_err_e td_thr_setsigpending_t(const td_thrhandle_t *__th, unsigned char __n, const sigset_t *__ss); -typedef td_err_e td_thr_set_event_t(const td_thrhandle_t *__th, td_thr_events_t *__event); - -// Pointers to imported functions: -static td_init_t *p_td_init = NULL; -static td_ta_delete_t *p_td_ta_delete = NULL; -static td_ta_event_addr_t *p_td_ta_event_addr = NULL; -static td_ta_event_getmsg_t *p_td_ta_event_getmsg = NULL; -static td_ta_map_lwp2thr_t *p_td_ta_map_lwp2thr = NULL; -static td_ta_new_t *p_td_ta_new = NULL; -static td_ta_set_event_t *p_td_ta_set_event = NULL; -static td_ta_thr_iter_t *p_td_ta_thr_iter = NULL; -static td_thr_event_enable_t *p_td_thr_event_enable = NULL; -static td_thr_get_info_t *p_td_thr_get_info = NULL; -static td_thr_setsigpending_t *p_td_thr_setsigpending = NULL; -static td_thr_set_event_t *p_td_thr_set_event = NULL; - -struct symbol_resolve_info_t -{ - const char *name; - void **ptr; -}; -static symbol_resolve_info_t tdsyms[] = -{ - { "td_init", (void**)&p_td_init }, - { "td_ta_delete", (void**)&p_td_ta_delete }, - { "td_ta_event_addr", (void**)&p_td_ta_event_addr }, - { "td_ta_event_getmsg", (void**)&p_td_ta_event_getmsg }, - { "td_ta_map_lwp2thr", (void**)&p_td_ta_map_lwp2thr }, - { "td_ta_new", (void**)&p_td_ta_new }, - { "td_ta_set_event", (void**)&p_td_ta_set_event }, - { "td_ta_thr_iter", (void**)&p_td_ta_thr_iter }, - { "td_thr_event_enable", (void**)&p_td_thr_event_enable }, - { "td_thr_get_info", (void**)&p_td_thr_get_info }, - { "td_thr_setsigpending", (void**)&p_td_thr_setsigpending }, - { "td_thr_set_event", (void**)&p_td_thr_set_event }, -}; - -// These definitions make our source code the same: -#define td_init p_td_init -#define td_ta_delete p_td_ta_delete -#define td_ta_event_addr p_td_ta_event_addr -#define td_ta_event_getmsg p_td_ta_event_getmsg -#define td_ta_map_lwp2thr p_td_ta_map_lwp2thr -#define td_ta_new p_td_ta_new -#define td_ta_set_event p_td_ta_set_event -#define td_ta_thr_iter p_td_ta_thr_iter -#define td_thr_event_enable p_td_thr_event_enable -#define td_thr_get_info p_td_thr_get_info -#define td_thr_setsigpending p_td_thr_setsigpending -#define td_thr_set_event p_td_thr_set_event - -//-------------------------------------------------------------------------- -static bool load_libthread_db_so(void) -{ - if ( p_td_init == NULL ) - { - const char *file = "libthread_db.so"; - void *lib = dlopen(file, RTLD_NOW); - if ( lib == NULL ) - { - msg("dlopen(%s): %s\n", file, dlerror()); - return false; - } - for ( int i=0; i < qnumber(tdsyms); i++ ) - { - *tdsyms[i].ptr = dlsym(lib, tdsyms[i].name); - const char *err = dlerror(); - if ( err != NULL ) - { - msg("dlsym(%s.%s): %s\n", file, tdsyms[i].name, err); - dlclose(lib); - return false; - } - } - } - return true; -} -#else // Automatic loading of libthread_db.so -inline bool load_libthread_db_so(void) { return true; } -#endif - -typedef std::map psnames_t; -static psnames_t psname_cache; - -static bool tdb_inited = false; - -// Return non-zero iff we have tracefork functionality available. -// This function also sets linux_supports_tracefork_flag. -static int linux_supports_tracefork(void); -static void linux_enable_event_reporting(int pid); - -//-------------------------------------------------------------------------- -#define COMPLAIN_IF_FAILED(func, err) \ - do \ - { \ - if ( err != TD_OK ) \ - msg("%s: %s\n", func, tdb_strerr(err)); \ - } \ - while ( 0 ) - -#define DIE_IF_FAILED(func, err) \ - do \ - { \ - if ( err != TD_OK ) \ - error("%s: %s\n", func, tdb_strerr(err));\ - } \ - while ( 0 ) - -static const char *tdb_strerr(td_err_e err) -{ - static char buf[64]; - switch ( err ) - { - case TD_OK: return "ok"; - case TD_ERR: return "generic error"; - case TD_NOTHR: return "no thread to satisfy query"; - case TD_NOSV: return "no sync handle to satisfy query"; - case TD_NOLWP: return "no LWP to satisfy query"; - case TD_BADPH: return "invalid process handle"; - case TD_BADTH: return "invalid thread handle"; - case TD_BADSH: return "invalid synchronization handle"; - case TD_BADTA: return "invalid thread agent"; - case TD_BADKEY: return "invalid key"; - case TD_NOMSG: return "no event message for getmsg"; - case TD_NOFPREGS: return "FPU register set not available"; - case TD_NOLIBTHREAD: return "application not linked with libpthread"; - case TD_NOEVENT: return "requested event is not supported"; - case TD_NOCAPAB: return "capability not available"; - case TD_DBERR: return "debugger service failed"; - case TD_NOAPLIC: return "operation not applicable to"; - case TD_NOTSD: return "no thread-specific data for this thread"; - case TD_MALLOC: return "malloc failed"; - case TD_PARTIALREG: return "only part of register set was written/read"; - case TD_NOXREGS: return "X register set not available for this thread"; -#ifdef TD_TLSDEFER - case TD_TLSDEFER: return "thread has not yet allocated TLS for given module"; -#endif -#ifdef TD_VERSION - case TD_VERSION: return "versions of libpthread and libthread_db do not match"; -#endif -#ifdef TD_NOTLS - case TD_NOTLS: return "there is no TLS segment in the given module"; -#endif - default: - qsnprintf(buf, sizeof(buf), "tdb error %d", err); - return buf; - } -} - -//-------------------------------------------------------------------------- -// Debug print functions -#ifdef TDEB -static const char *tdb_event_name(int ev) -{ - static const char *const names[] = - { - "READY", // 1 - "SLEEP", // 2 - "SWITCHTO", // 3 - "SWITCHFROM", // 4 - "LOCK_TRY", // 5 - "CATCHSIG", // 6 - "IDLE", // 7 - "CREATE", // 8 - "DEATH", // 9 - "PREEMPT", // 10 - "PRI_INHERIT", // 11 - "REAP", // 12 - "CONCURRENCY", // 13 - "TIMEOUT", // 14 - }; - if ( ev > 0 && ev <= qnumber(names) ) - return names[ev-1]; - - static char buf[16]; - qsnprintf(buf, sizeof(buf), "%u", ev); - return buf; -} - -//-------------------------------------------------------------------------- -static char *get_thr_events_str(const td_thr_events_t &set) -{ - static char buf[MAXSTR]; - char *ptr = buf; - char *end = buf + sizeof(buf); - for ( int i=TD_MIN_EVENT_NUM; i <= TD_MAX_EVENT_NUM; i++ ) - { - if ( td_eventismember(&set, i) ) - { - if ( ptr != buf ) - APPCHAR(ptr, end, ' '); - APPEND(ptr, end, tdb_event_name(i)); - } - } - return buf; -} - -//-------------------------------------------------------------------------- -static const char *get_sigset_str(const sigset_t &set) -{ - static char buf[MAXSTR]; - char *ptr = buf; - char *end = buf + sizeof(buf); - for ( int i=0; i <= 32; i++ ) - { - if ( sigismember(CONST_CAST(sigset_t*)(&set), i) ) - { - if ( ptr != buf ) - APPCHAR(ptr, end, ' '); - ptr += qsnprintf(ptr, end-ptr, "%d", i); - } - } - return buf; -} - -//-------------------------------------------------------------------------- -static const char *get_thread_state_name(td_thr_state_e state) -{ - static const char *const names[] = - { - "ANY_STATE", // 0 - "UNKNOWN", // 1 - "STOPPED", // 2 - "RUN", // 3 - "ACTIVE", // 4 - "ZOMBIE", // 5 - "SLEEP", // 6 - "STOPPED_ASLEEP" // 7 - }; - if ( state >= 0 && state < qnumber(names) ) - return names[state]; - - static char buf[16]; - qsnprintf(buf, sizeof(buf), "%u", state); - return buf; -} - -//-------------------------------------------------------------------------- -static const char *get_thread_type_name(td_thr_type_e type) -{ - static const char *const names[] = - { - "ANY_STATE", // 0 - "USER", // 1 - "SYSTEM", // 2 - }; - if ( type >= 0 && type < qnumber(names) ) - return names[type]; - - static char buf[16]; - qsnprintf(buf, sizeof(buf), "%u", type); - return buf; -} - -//-------------------------------------------------------------------------- -static void display_thrinfo(const td_thrinfo_t &thi) -{ -#ifdef __ANDROID__ - msg(" tid : %lx\n", thi.ti_tid); - msg(" kernel pid : %d\n", thi.ti_lid); // lwpid_t - msg(" state : %s\n", get_thread_state_name(thi.ti_state)); -#else - size_t sigmask = *(size_t*)&thi.ti_sigmask; - msg(" tid : %lx\n", thi.ti_tid); - msg(" tls : %lx\n", (size_t)thi.ti_tls); - msg(" entry : %lx\n", (size_t)thi.ti_startfunc); - msg(" stackbase : %lx\n", (size_t)thi.ti_stkbase); - msg(" stacksize : %lx\n", thi.ti_stksize); - msg(" state : %s\n", get_thread_state_name(thi.ti_state)); - msg(" suspended : %d\n", thi.ti_db_suspended); - msg(" type : %s\n", get_thread_type_name(thi.ti_type)); - msg(" priority : %d\n", thi.ti_pri); - msg(" kernel pid : %d\n", thi.ti_lid); // lwpid_t - msg(" signal mask : %lx\n", sigmask); - msg(" traceme : %d\n", thi.ti_traceme); - msg(" pending sg : %s\n", get_sigset_str(thi.ti_pending)); - msg(" enabled ev : %s\n", get_thr_events_str(thi.ti_events)); -#endif -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::display_thrinfo(thid_t tid) -{ - msg("tid=%d\n", tid); - td_thrhandle_t th; - td_err_e err = td_ta_map_lwp2thr(ta, tid, &th); - COMPLAIN_IF_FAILED("td_ta_map_lwp2thr2", err); - - if ( err == 0 ) - { - td_thrinfo_t thi; - memset(&thi, 0, sizeof(thi)); - err = td_thr_get_info(&th, &thi); - COMPLAIN_IF_FAILED("td_thr_get_info2", err); - - if ( err == 0 ) - ::display_thrinfo(thi); - } -} - -//-------------------------------------------------------------------------- -static int display_thread_cb(const td_thrhandle_t *th_p, void * /*data*/) -{ - td_thrinfo_t ti; - td_err_e err = td_thr_get_info(th_p, &ti); - DIE_IF_FAILED("td_thr_get_info", err); - - if ( ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE ) - return 0; - - display_thrinfo(ti); - return 0; -} - -void linux_debmod_t::display_all_threads() -{ - if ( ta != NULL ) - { - td_err_e err = td_ta_thr_iter(ta, display_thread_cb, NULL, - TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, - TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); - COMPLAIN_IF_FAILED("td_ta_thr_iter", err); - } -} - -#endif // end of debug print functions - - -//-------------------------------------------------------------------------- -// Helper functions for thread_db -// (it requires ps_... functions to be defined in the debugger) -//-------------------------------------------------------------------------- -static linux_debmod_t *find_debugger(ps_prochandle *hproc) -{ -#ifdef __ANDROID__ // android passes NULL as hproc, do not use it - qnotused(hproc); - linux_debmod_t *d = (linux_debmod_t *)g_global_server->get_debugger_instance(); - return d; -#else - struct ida_local find_debugger_t : public debmod_visitor_t - { - int pid; - linux_debmod_t *found; - find_debugger_t(int p) : pid(p), found(NULL) {} - virtual int visit(debmod_t *debmod) override - { - linux_debmod_t *ld = (linux_debmod_t *)debmod; - if ( ld->process_handle == pid ) - { - found = ld; - return 1; // stop - } - return 0; // continue - } - }; - find_debugger_t fd(hproc->pid); - for_all_debuggers(fd); -// msg("prochandle: %x, looking for the debugger, found: %x\n", hproc, fd.found); - return fd.found; -#endif -} - -//-------------------------------------------------------------------------- -inline ea_t get_symbol_as_envvar(const char *name) -{ - qstring buf; - return qgetenv(name, &buf) ? strtoull(buf.begin(), NULL, 16) : BADADDR; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_pglobal_lookup( - ps_prochandle *hproc, - const char *obj, - const char *name, - psaddr_t *sym_addr) -{ - ea_t ea; - // cache names for repeated requests. android, for example, requests the - // same name again and again. without the cache, the name would be gone - // from the pending name list and become unresolvable. - psnames_t::iterator p = psname_cache.find(name); - if ( p != psname_cache.end() ) - { - ea = p->second; - } - else - { - linux_debmod_t *ld = find_debugger(hproc); - if ( ld == NULL ) - return PS_BADPID; - - ld->enum_names(obj); // update the name list - - ea = ld->find_pending_name(name); - if ( ea == BADADDR ) - { - if ( ld->nptl_base != BADADDR ) - ea = get_symbol_as_envvar(name); - if ( ea == BADADDR ) - { - if ( ld->nptl_base != BADADDR ) - msg("*WARNING* Failed to resolve name '%s' in libpthread shared object.\n" - " Support for multithread applications will be turned off.\n" - " We recommend you to analyze libpthread and provide the\n" - " missing symbol info as an environment variable:\n" - "\n" - " export %s=####\n" - "\n" - " where #### is the hexadecimal address of the symbol.\n" - " The full list of symbols is in syms_as_envvars.py\n", - name, name); - return PS_NOSYM; - } - ea += ld->nptl_base; - } -#ifdef TDEB - if ( streq(name, "nptl_version") ) - { - char buf[8 + 1]; - buf[0] = '\0'; - ld->_read_memory(-1, ea, buf, 8, false); - buf[8] = '\0'; - msg("nptl_version='%s'\n", buf); - } -#endif - psname_cache[name] = ea; - } - *sym_addr = psaddr_t(size_t(ea)); - ddeb(("ps_pglobal_lookup('%s') => %a\n", name, ea)); - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman pid_t ps_getpid(ps_prochandle *hproc) -{ - return hproc->pid; -} - -#ifdef __ANDROID__ -# ifndef __X86__ -//-------------------------------------------------------------------------- -idaman ps_err_e ps_get_thread_area(const struct ps_prochandle *, lwpid_t lwpid, int idx, void **base) -{ - struct iovec iovec; - uint64_t reg; - - iovec.iov_base = ® - iovec.iov_len = sizeof (reg); - - if ( ptrace(PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0 ) - return PS_ERR; - - /* IDX is the bias from the thread pointer to the beginning of the - thread descriptor. It has to be subtracted due to implementation - quirks in libthread_db. */ - *base = (void *) (reg - idx); - - return PS_OK; -} -# endif - -#else // !__ANDROID__ -//-------------------------------------------------------------------------- -idaman ps_err_e ps_pdread( - ps_prochandle *hproc, - psaddr_t addr, - void *buf, - size_t size) -{ - ddeb(("ps_pdread(%" FMT_Z ", %ld)\n", size_t(addr), size)); - linux_debmod_t *ld = find_debugger(hproc); - if ( ld == NULL ) - { - ddeb(("\t=> bad pid\n")); - return PS_BADPID; - } - if ( ld->thread_handle == INVALID_HANDLE_VALUE - || ld->_read_memory(ld->thread_handle, size_t(addr), buf, size, false) <= 0 ) - { - ddeb(("\t=> read error (1)\n")); - if ( ld->_read_memory(hproc->pid, size_t(addr), buf, size, false) <= 0 ) - { - ddeb(("\t=> read error (2)\n")); - return PS_ERR; - } - } - ddeb(("\t=> read OK\n")); - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_pdwrite( - ps_prochandle *hproc, - psaddr_t addr, - void *buf, - size_t size) -{ - linux_debmod_t *ld = find_debugger(hproc); - if ( ld == NULL ) - return PS_BADPID; - if ( ld->_write_memory(hproc->pid, size_t(addr), buf, size, false) <= 0 ) - return PS_ERR; - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_lgetregs(ps_prochandle *, lwpid_t lwpid, prgregset_t gregset) -{ - if ( qptrace(PTRACE_GETREGS, lwpid, 0, gregset) != 0 ) - return PS_ERR; - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_lsetregs(ps_prochandle *, lwpid_t lwpid, const prgregset_t gregset) -{ - if ( qptrace(PTRACE_SETREGS, lwpid, 0, (void*)gregset) != 0 ) - return PS_ERR; - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_lgetfpregs(ps_prochandle *, lwpid_t lwpid, prfpregset_t *fpregset) -{ - if ( qptrace(PTRACE_GETFPREGS, lwpid, 0, fpregset) != 0 ) - return PS_ERR; - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_lsetfpregs(ps_prochandle *, lwpid_t lwpid, const prfpregset_t *fpregset) -{ - if ( qptrace(PTRACE_SETFPREGS, lwpid, 0, (void*)fpregset) != 0 ) - return PS_ERR; - return PS_OK; -} - -//-------------------------------------------------------------------------- -idaman ps_err_e ps_get_thread_area(const struct ps_prochandle *, lwpid_t lwpid, int idx, void **base) -{ - #ifndef PTRACE_GET_THREAD_AREA - #ifdef __ARM__ - #define PTRACE_GET_THREAD_AREA __ptrace_request(22) - #else - #define PTRACE_GET_THREAD_AREA __ptrace_request(25) - #endif - #endif - unsigned int desc[4]; - if ( qptrace(PTRACE_GET_THREAD_AREA, lwpid, (void *)size_t(idx), &desc) < 0 ) - { -#ifndef __X86__ - // from - #define LINUX_FS 25 - #define LINUX_GS 26 - - /* The following definitions come from prctl.h, but may be absent - for certain configurations. */ - #ifndef ARCH_GET_FS - #define ARCH_SET_GS 0x1001 - #define ARCH_SET_FS 0x1002 - #define ARCH_GET_FS 0x1003 - #define ARCH_GET_GS 0x1004 - #endif - - switch ( idx ) - { - case LINUX_FS: - if ( ptrace(PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) != 0 ) - return PS_ERR; - break; - case LINUX_GS: - if ( ptrace(PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) != 0 ) - return PS_ERR; - break; - default: - return PS_BADADDR; - } -#endif - return PS_ERR; - } - - *(int *)base = desc[1]; - - return PS_OK; -} -#endif - -//-------------------------------------------------------------------------- -// High level interface for the rest of the debugger module -//-------------------------------------------------------------------------- -void tdb_init(void) -{ - if ( !tdb_inited ) - { - if ( !load_libthread_db_so() ) - { - msg("DBG: thread support is not available\n"); - } - else - { - td_err_e code = td_init(); - if ( code == TD_OK ) - tdb_inited = true; - else - msg("DBG: td_init error code %d\n", code); - } - } -} - -//-------------------------------------------------------------------------- -void tdb_term(void) -{ - // no way to uninitialize thread_db -} - -//-------------------------------------------------------------------------- -typedef qvector td_thrinfovec_t; - -//-------------------------------------------------------------------------- -// check if there are pending messages from thread DB -void linux_debmod_t::tdb_handle_messages(int /*tid*/) -{ - if ( ta == NULL ) - return; - - td_event_msg_t tmsg; - td_thrinfo_t ti; - td_err_e err; -#ifndef __ANDROID__ - while ( true ) -#endif - { - err = td_ta_event_getmsg(ta, &tmsg); - if ( err != TD_OK ) - { - if ( err == TD_NOMSG ) - return; - msg("Cannot get thread event message: %s\n", tdb_strerr(err)); - return; - } - - err = td_thr_get_info(tmsg.th_p, &ti); - COMPLAIN_IF_FAILED("td_thr_get_info", err); - switch ( tmsg.event ) - { - case TD_CREATE: - if ( !thread_is_known(ti) ) - { - if ( listen_thread_events(ti, tmsg.th_p) ) - attach_to_thread(ti); - } - break; - - case TD_DEATH: - dead_thread(ti.ti_lid, DYING); - break; - - default: - msg("Spurious thread event %d.", tmsg.event); - } - } -} - -//---------------------------------------------------------------------------- -struct cbdata_t -{ - linux_debmod_t *debmod; - td_thrinfovec_t *threads_list; -}; - -//---------------------------------------------------------------------------- -static int update_threads_cb(const td_thrhandle_t *th_p, void *data) -{ - cbdata_t *cbdata = (cbdata_t *) data; - - td_thrinfo_t ti; - td_err_e err = td_thr_get_info(th_p, &ti); - DIE_IF_FAILED("td_thr_get_info", err); - - if ( ti.ti_state != TD_THR_UNKNOWN && ti.ti_state != TD_THR_ZOMBIE ) - { - if ( !cbdata->debmod->thread_is_known(ti) ) - { - cbdata->debmod->listen_thread_events(ti, th_p); - cbdata->threads_list->push_back(ti); - } - } - return 0; -} - -//---------------------------------------------------------------------------- -bool linux_debmod_t::thread_is_known(const td_thrinfo_t &info) const -{ - return threads.find(info.ti_lid) != threads.end(); -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::listen_thread_events(const td_thrinfo_t &info, const td_thrhandle_t *th_p) -{ -#ifdef TDEB - msg("thread %d is new\n", info.ti_lid); - ::display_thrinfo(info); -#else - qnotused(info); -#endif - td_err_e err; - td_thr_events_t thr_events; - td_event_emptyset(&thr_events); - td_event_addset(&thr_events, TD_CREATE); - td_event_addset(&thr_events, TD_DEATH); -#ifndef __ANDROID__ - td_event_addset(&thr_events, TD_CATCHSIG); -#endif - err = td_thr_set_event(th_p, &thr_events); - DIE_IF_FAILED("td_thr_set_event", err); - - err = td_thr_event_enable(th_p, 1); - COMPLAIN_IF_FAILED("td_thr_event_enable", err); - if ( err != TD_OK ) - { - ddeb(("%d: thread dead already? not adding to list.\n", info.ti_lid)); - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::attach_to_thread(const td_thrinfo_t &info) -{ -#ifndef __ANDROID__ - ea_t ea = (ea_t) (size_t) info.ti_startfunc; -#else - ea_t ea = BADADDR; -#endif - - attach_to_thread(info.ti_lid, ea); -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::attach_to_thread(int tid, ea_t ea) -{ - thread_info_t &ti = add_thread(tid); - debug_event_t ev; - ev.set_info(THREAD_STARTED) = ti.name; - ev.pid = process_handle; - ev.tid = tid; - ev.ea = ea; // TODO: move event below and ev.ea = get_ip() - ev.handled = true; - enqueue_event(ev, IN_FRONT); - // attach to the thread and make it ready for debugging - if ( qptrace(PTRACE_ATTACH, tid, 0, 0) != 0 ) - INTERR(30197); - int status; - int tid2 = check_for_signal(&status, tid, -1); // consume SIGSTOP - if ( tid2 != tid || !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP ) - { - get_thread(tid)->waiting_sigstop = true; - if ( tid2 > 0 ) - store_pending_signal(tid2, status); - } -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::dead_thread(int tid, thstate_t state) -{ - threads_t::iterator p = threads.find(tid); - if ( p != threads.end() ) - { - ddeb(("thread %d died\n", tid)); - set_thread_state(p->second, state); - debug_event_t ev; - ev.set_exit_code(THREAD_EXITED, 0); // ??? - ev.pid = process_handle; - ev.tid = tid; - ev.ea = BADADDR; - ev.handled = true; - enqueue_event(ev, IN_BACK); - if ( state == DEAD ) - del_thread(tid); - } - else - { - msg("unknown thread %d died\n", tid); - } -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::tdb_update_threads(void) -{ - if ( ta != NULL ) - { - td_thrinfovec_t newlist; - cbdata_t cb_payload = { this, &newlist }; - - td_err_e err = td_ta_thr_iter(ta, update_threads_cb, &cb_payload, - TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, - TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); - COMPLAIN_IF_FAILED("td_ta_thr_iter", err); - if ( err != TD_OK ) - return; - - // generate THREAD_STARTED events - for ( int i=0; i < newlist.size(); i++ ) - { - const td_thrinfo_t &info = newlist[i]; - // Main thread is already suspended; others not. - if ( i != 0 ) - dbg_freeze_threads(info.ti_lid, false); - attach_to_thread(newlist[i]); - } - } -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::tdb_enable_event(td_event_e event, internal_bpt *bp) -{ - td_notify_t notify; - td_err_e err = td_ta_event_addr(ta, event, ¬ify); - COMPLAIN_IF_FAILED("td_ta_event_addr", err); - if ( err != TD_OK ) - return false; - bool ok = add_internal_bp(*bp, size_t(notify.u.bptaddr)); - if ( !ok ) - { - // Having the following cast inline in the 'dmsg' call causes - // the __X86__=1 build on linux to report: - // linux_threads.cpp:851:86: warning: format '%a' expects argument of - // type 'double', but argument 3 has type 'size_t {aka unsigned int}' - // ...which AFAICT is a bug in gcc. - // Putting it on a separate line works fine, though. - ea_t bptaddr = ea_t(size_t(notify.u.bptaddr)); - dmsg("%a: failed to add thread_db breakpoint\n", bptaddr); - return false; - } - debdeb("%a: added BP for thread event %s\n", bp->bpt_addr, event == TD_CREATE ? "TD_CREATE" : "TD_DEATH"); - return true; -} - -//-------------------------------------------------------------------------- -// returns true: multithreaded application has been detected -bool linux_debmod_t::tdb_new(void) -{ - if ( ta == NULL ) - { - if ( !tdb_inited ) - return false; // no libthread_db -#ifdef __ANDROID__ - // wait until libc gets loaded. on android v4.2.2 there are 2 sets of pthread_...() - // functions: in /system/bin/linker and in /system/lib/libc.so. The ones - // from /system/bin/linker get resolved first but we have to use the ones - // from /system/lib/libc.so - bool libc_loaded = false; - qstring custom_libc_path; - qgetenv("IDA_LIBC_PATH", &custom_libc_path); - for ( images_t::const_iterator p=dlls.begin(); p != dlls.end(); ++p ) - { - const qstring &path = p->second.fname; - if ( path == "/system/lib/libc.so" - || path == "/system/lib64/libc.so" - || !custom_libc_path.empty() && path == custom_libc_path ) - { - libc_loaded = true; - break; - } - } - if ( !libc_loaded ) - { - debdeb("DBG: /system/lib/libc.so is not loaded yet, use IDA_LIBC_PATH if necessary\n"); - return false; - } -#endif - - if ( linux_supports_tracefork() ) - { - debdeb("DBG: use PTRACE_O_TRACEFORK to follow the fork events\n"); - linux_enable_event_reporting(process_handle); - birth_bpt.bpt_addr = 0; - death_bpt.bpt_addr = 0; - - procfs_collect_threads(); - } - else - { - debdeb("DBG: checking pid %d with thread_db\n", process_handle); - prochandle.pid = process_handle; - td_err_e err = td_ta_new(&prochandle, &ta); - // the call might fail the first time if libc is not loaded yet - // so don't show misleading message to the user - #ifdef TDEB - COMPLAIN_IF_FAILED("td_ta_new", err); - #endif - if ( err != TD_OK ) - { - debdeb("DBG: td_ta_new: %s\n", tdb_strerr(err)); - ta = NULL; - return false; - } - - td_thrhandle_t th; - err = td_ta_map_lwp2thr(ta, process_handle, &th); - COMPLAIN_IF_FAILED("td_ta_map_lwp2thr", err); - if ( err != TD_OK ) - return false; - - err = td_thr_event_enable(&th, TD_CREATE); - DIE_IF_FAILED("td_thr_event_enable(TD_CREATE)", err); -#ifndef __ANDROID__ - err = td_thr_event_enable(&th, TD_DEATH); - DIE_IF_FAILED("td_thr_event_enable(TD_DEATH)", err); -#endif - - // set breakpoints for thread birth/death - td_thr_events_t thr_events; - td_event_emptyset(&thr_events); - td_event_addset(&thr_events, TD_CREATE); - td_event_addset(&thr_events, TD_DEATH); - err = td_ta_set_event(ta, &thr_events); - DIE_IF_FAILED("td_ta_set_event", err); - - tdb_enable_event(TD_CREATE, &birth_bpt); -#ifndef __ANDROID__ - tdb_enable_event(TD_DEATH, &death_bpt); -#endif - debdeb("DBG: thread support has been enabled, birth_bpt=%a death_bpt=%a\n", birth_bpt.bpt_addr, death_bpt.bpt_addr); - - tdb_update_threads(); - } - } - return true; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::tdb_delete(void) -{ - if ( ta != NULL ) - { - td_ta_delete(ta); - ta = NULL; - psname_cache.clear(); - } -} - -//-------------------------------------------------------------------------- -// This variable is a tri-state flag: -// -1 for unknown, -// 0 if PTRACE_O_TRACEFORK cannot be used, -// 1 if it can. -static int linux_supports_tracefork_flag = -1; - -//-------------------------------------------------------------------------- -static int linux_tracefork_grandchild(void *) -{ - _exit(0); -} - -static int linux_tracefork_child(void) -{ - errno = 0; - if ( qptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0 ) - { - msg("PTRACE_O_TRACEFORK test: Cannot trace created process: %s\n", winerr(errno)); - _exit(127); - } - kill(getpid(), SIGSTOP); - - if ( fork() == 0 ) - linux_tracefork_grandchild(NULL); - - _exit(0); -} - -// Determine if PTRACE_O_TRACEFORK can be used to follow fork events. Make -// sure that we can enable the option, and that it had the desired effect. -static void linux_test_for_tracefork(void) -{ - linux_supports_tracefork_flag = 0; - - int child_pid = fork(); - if ( child_pid == 0 ) - linux_tracefork_child(); - - if ( child_pid == -1 ) - { - msg("clone: %s\n", winerr(errno)); - return; - } - - int status; - int ret = qwait(&status, child_pid, 0); - if ( ret == -1 ) - { - msg("waitpid: %s\n", winerr(errno)); - return; - } - else if ( ret != child_pid ) - { - msg("linux_test_for_tracefork: waitpid: unexpected result %d\n", ret); - return; - } - if ( !WIFSTOPPED(status) ) - { - msg("linux_test_for_tracefork: waitpid: unexpected status %d\b", status); - return; - } - - ret = qptrace(PTRACE_SETOPTIONS, child_pid, NULL, (void *)PTRACE_O_TRACEFORK); - if ( ret != 0 ) - { - ret = qptrace(PTRACE_KILL, child_pid, NULL, NULL); - if ( ret != 0 ) - { - msg("linux_test_for_tracefork: failed to kill child"); - return; - } - - ret = qwait(&status, child_pid, 0); - if ( ret != child_pid ) - msg("linux_test_for_tracefork: failed to wait for killed child"); - else if ( !WIFSIGNALED(status) ) - msg("linux_test_for_tracefork: unexpected wait status 0x%x from " - "killed child", status); - return; - } - - ret = qptrace(PTRACE_CONT, child_pid, NULL, NULL); - if ( ret != 0 ) - msg("linux_test_for_tracefork: failed to resume child"); - - ret = qwait(&status, child_pid, 0); - if ( ret == child_pid - && WIFSTOPPED(status) - && status >> 16 == PTRACE_EVENT_FORK ) - { - long second_pid = 0; - ret = qptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &second_pid); - if ( ret == 0 && second_pid != 0 ) - { - int second_status; - - linux_supports_tracefork_flag = 1; - qwait(&second_status, second_pid, 0); - ret = qptrace(PTRACE_KILL, second_pid, NULL, NULL); - if ( ret != 0 ) - msg("linux_test_for_tracefork: failed to kill second child"); - qwait(&status, second_pid, 0); - } - } - else - { - msg("linux_test_for_tracefork: unexpected result from waitpid " - "(%d, status 0x%x)", ret, status); - } - - do - { - ret = qptrace(PTRACE_KILL, child_pid, NULL, NULL); - if ( ret != 0 ) - msg("linux_test_for_tracefork: failed to kill child"); - qwait(&status, child_pid, 0); - } - while ( WIFSTOPPED(status) ); -} - -//-------------------------------------------------------------------------- -static int linux_supports_tracefork(void) -{ - if ( linux_supports_tracefork_flag == -1 ) - linux_test_for_tracefork(); - return linux_supports_tracefork_flag; -} - -//-------------------------------------------------------------------------- -static void linux_enable_event_reporting(int pid) -{ - if ( !linux_supports_tracefork() ) - return; - - qptrace(PTRACE_SETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACECLONE); -} - -//-------------------------------------------------------------------------- -// ported from GDB sources: linux_proc_attach_tgid_threads() -void linux_debmod_t::procfs_collect_threads(void) -{ - // TODO: if (linux_proc_get_tgid (pid) != pid) return; - - qstring pathname; - pathname.sprnt("/proc/%d/task", process_handle); - DIR *dir = opendir(pathname.c_str()); - if ( dir == NULL ) - { - msg("Could not open /proc/%d/task", process_handle); - return; - } - - /* Scan the task list for existing threads. While we go through the - threads, new threads may be spawned. Cycle through the list of - threads until we have done two iterations without finding new - threads. */ - for ( int iterations=0; iterations < 2; ++iterations ) - { - bool new_threads_found = false; - - struct dirent *dp; - while ( (dp = readdir(dir)) != NULL ) - { - /* Fetch one lwp. */ - unsigned long lwp = strtoul(dp->d_name, NULL, 10); - if ( lwp != 0 ) - { - debdeb("DBG: %d found %s thread\n", iterations, dp->d_name); - if ( attach_collected_thread(lwp) ) - { - new_threads_found = true; - debdeb("DBG: %d collected %s thread\n", iterations, dp->d_name); - } - } - } - - if ( new_threads_found ) - { /* Start over. */ - iterations = -1; - } - rewinddir(dir); - } - - closedir(dir); -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::get_thread_name(qstring *thr_name, thid_t tid) -{ - qstring comm_file; - comm_file.sprnt("/proc/%d/task/%d/comm", process_handle, tid); - FILE *fp = fopenRT(comm_file.c_str()); - if ( fp == NULL ) - { - dmsg("%s: %s\n", comm_file.c_str(), winerr(errno)); - return false; - } - qgetline(thr_name, fp); // return code is ignored, assumed empty thread name - qfclose(fp); - return true; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::update_thread_names(thread_name_vec_t *thr_names) -{ - // assert: thr_names != NULL - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - qstring new_thr_name; - if ( get_thread_name(&new_thr_name, ti.tid) - && new_thr_name != ti.name ) - { - ddeb(("Thread %d renamed from '%s' to '%s'\n", ti.tid, ti.name.c_str(), new_thr_name.c_str())); - ti.name.swap(new_thr_name); - thread_name_t &tn = thr_names->push_back(); - tn.tid = ti.tid; - tn.name = ti.name; - } - } -} - -//-------------------------------------------------------------------------- -bool linux_debmod_t::attach_collected_thread(unsigned long lwp) -{ - thread_info_t *thif = get_thread(lwp); - if ( thif != NULL ) - return false; - - // Main thread is already suspended; others not. - if ( lwp != process_handle ) - dbg_freeze_threads(lwp, false); - // generate THREAD_STARTED event - attach_to_thread(lwp, BADADDR); - - return true; -} - -//-------------------------------------------------------------------------- -void linux_debmod_t::handle_extended_wait(bool *handled, const chk_signal_info_t &csi) -{ - if ( handled != NULL ) - *handled = false; - - // extended event guard - int event = csi.status >> 16; - if ( !WIFSTOPPED(csi.status) - || WSTOPSIG(csi.status) != SIGTRAP - || event == 0 ) - { - return; - } - - if ( event == PTRACE_EVENT_CLONE ) - { - unsigned long new_pid; - qptrace(PTRACE_GETEVENTMSG, csi.pid, NULL, &new_pid); - ddeb(("handle_extended_wait: PTRACE_EVENT_CLONE(signal_pid=%d, new_pid=%ld)\n", csi.pid, new_pid)); - thread_info_t &ti = add_thread(new_pid); - - // If we haven't already seen the new PID stop, wait for it now - if ( !seen_threads.del(new_pid) ) - { - // The new child has a pending SIGSTOP. We can't affect it until it - // hits the SIGSTOP, but we're already attached - int status; - int tid2 = check_for_signal(&status, new_pid, -1); - ddeb(("handle_extended_wait: tid2=%d status=%s\n", tid2, status_dstr(status))); - if ( tid2 == -1 ) - INTERR(1200); // waiting for new child - if ( tid2 != new_pid || !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP ) - { - get_thread(new_pid)->waiting_sigstop = true; - if ( tid2 > 0 ) - store_pending_signal(tid2, status); - } - } - linux_enable_event_reporting(new_pid); - - debug_event_t ev; - ev.set_info(THREAD_STARTED) = ti.name; - ev.pid = process_handle; - ev.tid = new_pid; - ev.ea = get_ip(ev.tid); - ev.handled = true; - enqueue_event(ev, IN_FRONT); - - if ( handled != NULL ) - *handled = true; - } -} diff --git a/idasdk75/dbg/linux/linuxbase_debmod.cpp b/idasdk75/dbg/linux/linuxbase_debmod.cpp deleted file mode 100644 index 96ba63f..0000000 --- a/idasdk75/dbg/linux/linuxbase_debmod.cpp +++ /dev/null @@ -1,138 +0,0 @@ -#include -#include -#include -#include "linuxbase_debmod.h" - -//-------------------------------------------------------------------------- -static inline const char *str_bitness(int bitness) -{ - switch ( bitness ) - { - case 8: - return "[64]"; - case 4: - return "[32]"; - default: - return "[x]"; - } -} - -//-------------------------------------------------------------------------- -static void build_process_ext_name(ext_process_info_t *pinfo) -{ - pinfo->ext_name = str_bitness(pinfo->addrsize); - - char buf[QMAXPATH]; - qsnprintf(buf, sizeof(buf), "/proc/%u/cmdline", pinfo->pid); - - FILE *cmdfp = qfopen(buf, "r"); - if ( cmdfp == nullptr ) - return; - - int size = qfread(cmdfp, buf, sizeof(buf)); - qfclose(cmdfp); - - for ( int i=0; i < size; ) - { - const char *in = &buf[i]; - qstring arg = in; - quote_cmdline_arg(&arg); - pinfo->ext_name.append(" "); - pinfo->ext_name.append(arg); - - i += strlen(in) + 1; - } -} - -//-------------------------------------------------------------------------- -// Returns the file name assciated with pid -bool idaapi linuxbase_debmod_t::get_exec_fname( - int _pid, - char *buf, - size_t bufsize) -{ - char path[QMAXPATH]; - qsnprintf(path, sizeof(path), "/proc/%u/exe", _pid); - int len = readlink(path, buf, bufsize-1); - if ( len > 0 ) - { - buf[len] = '\0'; - return true; - } - else - { - // ESXi keeps the real file name inside /proc/PID/exe (which is not a link) - FILE *fp = qfopen(path, "r"); - if ( fp != NULL ) - { - len = qfread(fp, buf, bufsize); - qfclose(fp); - if ( len > 1 && len < bufsize && buf[0] == '/' ) // sanity check - { - buf[len] = '\0'; - return true; - } - } - buf[0] = '\0'; - return false; - } -} - -//-------------------------------------------------------------------------- -// Get process bitness: 32bit - 4, 64bit - 8, 0 - unknown -int idaapi linuxbase_debmod_t::get_process_bitness(int _pid) -{ - char fname[QMAXPATH]; - qsnprintf(fname, sizeof(fname), "/proc/%u/maps", _pid); - FILE *mapfp = fopenRT(fname); - if ( mapfp == NULL ) - return 0; - - int bitness = 4; - qstring line; - while ( qgetline(&line, mapfp) >= 0 ) - { - if ( line.empty() ) - continue; - ea_t ea1; - ea_t ea2; - if ( qsscanf(line.begin(), "%a-%a ", &ea1, &ea2) == 2 ) - { - size_t pos = line.find('-'); - if ( pos != qstring::npos && pos > 8 ) - { - bitness = 8; - break; - } - } - } - qfclose(mapfp); - return bitness; -} - -//-------------------------------------------------------------------------- -int idaapi linuxbase_debmod_t::get_process_list(procvec_t *list, qstring *) -{ - int mypid = getpid(); - list->clear(); - qffblk64_t fb; - for ( int code = qfindfirst("/proc/*", &fb, FA_DIREC); - code == 0; - code = qfindnext(&fb) ) - { - if ( !qisdigit(fb.ff_name[0]) ) - continue; - ext_process_info_t pinfo; - pinfo.pid = atoi(fb.ff_name); - if ( pinfo.pid == mypid ) - continue; - char buf[MAXSTR]; - if ( !get_exec_fname(pinfo.pid, buf, sizeof(buf)) ) - continue; // we skip the process because we cannot debug it anyway - pinfo.name = buf; - pinfo.addrsize = get_process_bitness(pinfo.pid); - build_process_ext_name(&pinfo); - list->push_back(pinfo); - } - return list->size(); -} diff --git a/idasdk75/dbg/linux/makefile b/idasdk75/dbg/linux/makefile deleted file mode 100644 index f64f1ed..0000000 --- a/idasdk75/dbg/linux/makefile +++ /dev/null @@ -1,149 +0,0 @@ -include ../../allmake.mak - -GOALS-$(BUILD_IDA) += modules # target in $(IDA)module.mak -GOALS-$(BUILD_DBGSRV) += server # target in $(IDA)dbg/server.mak -.PHONY: $(GOALS-1) -all: $(GOALS-1) - -#---------------------------------------------------------------------- -ifdef __LINUX__ - SERVER = linux_server$(SUFF64) -endif -ifdef SERVER - SERVERS += $(call server_exe,$(SERVER)) -endif - -#---------------------------------------------------------------------- -USER = $(call module_dll,linux_user) -ifeq ($(and $(BUILD_IDA),$(__LINUX__)),1) - MODULES += $(USER) -endif - -#---------------------------------------------------------------------- -# we explicitly added our module targets -NO_DEFAULT_TARGETS = 1 - -# NOTE: all MODULES must be defined before including plugin.mak. -include ../plugin.mak -# NOTE: target-specific rules and dependencies that use variable -# expansion to name the target (such as "$(MODULE): [...]") must -# come after including plugin.mak - -#---------------------------------------------------------------------- -# select OBJS common to user plugin and debugger server -ifeq ($(or $(__LINUX__),$(__ANDROID__),$(__ANDROID_X86__),$(__ARMLINUX__)),1) - BUILD_LINUX:=1 -endif - -BASE_OBJS-$(BUILD_LINUX) += $(F)linuxbase_debmod$(O) -BASE_OBJS-$(BUILD_LINUX) += $(F)linux_debmod$(O) -BASE_OBJS-$(BUILD_LINUX) += $(F)linux_wait$(O) - -BASE_OBJS += $(BASE_OBJS-1) $(F)symelf$(O) - -#---------------------------------------------------------------------- -ifdef __LINUX__ - SERVER_LDFLAGS += -Wl,--version-script=linux_debmod.script - SERVER_LDFLAGS += $(OUTMAP)$(F)$(@F).map - SERVER_STDLIBS += -lthread_db -lrt -lc -lpthread -ldl -endif -SERVER_OBJS += $(BASE_OBJS) - -# suppress warnings for libthread_db.c -$(F)libthread_db$(O): WARNS = $(NOWARNS) - -include ../server.mak - -#---------------------------------------------------------------------- -STUB_OBJS += $(F)linux_stub$(O) -$(STUB): MODULE_OBJS += $(STUB_OBJS) -$(STUB): $(STUB_OBJS) - -#---------------------------------------------------------------------- -USER_OBJS += $(F)linux_user$(O) -USER_OBJS += $(BASE_OBJS) -$(USER): MODULE_OBJS += $(USER_OBJS) -$(USER): $(USER_OBJS) -$(USER): DEFFILE = linux_debmod.script -$(USER): STDLIBS += -ldl -$(USER): STDLIBS += -lthread_db - -ifeq ($(COMPILER_NAME),gcc) - $(USER): LDFLAGS += -Wl,--export-dynamic -endif - -#---------------------------------------------------------------------- -include $(IDA)objdir.mak - -# MAKEDEP dependency list ------------------ -$(F)armlinux_stub$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../arm_local_impl.cpp ../arm_regs.cpp ../arm_regs.hpp \ - ../common_local_impl.cpp ../common_stub_impl.cpp \ - ../dbg_rpc_client.h ../dbg_rpc_engine.h ../deb_arm.hpp \ - ../debmod.h ../rpc_debmod.h armlinux_stub.cpp \ - linux_local_impl.cpp -$(F)libthread_db$(O): libthread_db.c -$(F)linux_debmod$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)diskio.hpp $(I)err.h $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)network.hpp $(I)pro.h \ - $(I)prodir.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ../../plugins/dwarf/look_for_debug_file.cpp \ - ../arm_debmod.h ../arm_regs.hpp ../dbg_rpc_engine.h \ - ../dbg_rpc_handler.h ../dbg_rpc_handler_ioctls.h \ - ../deb_arm.hpp ../deb_pc.hpp ../debmod.h ../pc_debmod.h \ - ../pc_regs.hpp android.cpp android.hpp linux_debmod.cpp \ - linux_debmod.h linux_threads.cpp linuxbase_debmod.h \ - symelf.hpp -$(F)linux_stub$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../common_local_impl.cpp ../common_stub_impl.cpp \ - ../dbg_rpc_client.h ../dbg_rpc_engine.h ../deb_pc.hpp \ - ../debmod.h ../pc_local_impl.cpp ../pc_regs.hpp \ - ../rpc_debmod.h linux_local_impl.cpp linux_stub.cpp -$(F)linux_user$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../arm_debmod.h ../common_local_impl.cpp \ - ../common_stub_impl.cpp ../deb_arm.hpp ../deb_pc.hpp \ - ../debmod.h ../pc_debmod.h ../pc_local_impl.cpp \ - ../pc_regs.hpp linux_debmod.h linux_local_impl.cpp \ - linux_user.cpp linuxbase_debmod.h -$(F)linux_wait$(O): $(I)bytes.hpp $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)ua.hpp \ - $(I)xref.hpp ../arm_debmod.h ../deb_arm.hpp \ - ../deb_pc.hpp ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ - linux_debmod.h linux_wait.cpp linuxbase_debmod.h -$(F)linuxbase_debmod$(O): $(I)bytes.hpp $(I)diskio.hpp $(I)fpro.h \ - $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)prodir.h $(I)range.hpp \ - $(I)ua.hpp $(I)xref.hpp ../arm_debmod.h ../deb_arm.hpp \ - ../deb_pc.hpp ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ - linuxbase_debmod.cpp linuxbase_debmod.h -$(F)symelf$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)network.hpp \ - $(I)offset.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - symelf.hpp diff --git a/idasdk75/dbg/mac/dbg_macosx.cfg b/idasdk75/dbg/mac/dbg_macosx.cfg deleted file mode 100644 index be6726c..0000000 --- a/idasdk75/dbg/mac/dbg_macosx.cfg +++ /dev/null @@ -1,23 +0,0 @@ - -// This option is ideal when working with the Remote Mac OSX Debugger. -// It allows IDA to parse symbol data for dyld_shared_cache libs locally, rather than -// transferring symbol names over the wire, which can save a significant amount of time. -// -// Here's an example of how to use it: -// -// First download the ios_deploy utility at: https://www.hex-rays.com/products/ida/support/ida/ios_deploy.zip. -// Then run the following commands on the remote OSX machine: -// -// $ mkdir ~/Symbols -// $ ios_deploy symbols -c /var/db/dyld/dyld_shared_cache_x86_64h -d ~/Symbols -// $ ios_deploy symbols -c /var/db/dyld/dyld_shared_cache_i386 -d ~/Symbols -// -// Then, on the client machine running IDA: -// -// $ scp -r user@mac:Symbols ~/ -// set SYMBOL_PATH = "~/Symbols" in dbg_macosx.cfg -// start IDA and run the debugger, symbol loading should now be much faster -// -// Any errors will be printed to the console. - -SYMBOL_PATH = ""; diff --git a/idasdk75/dbg/mac/mac_debmod.cpp b/idasdk75/dbg/mac/mac_debmod.cpp deleted file mode 100644 index b8bf527..0000000 --- a/idasdk75/dbg/mac/mac_debmod.cpp +++ /dev/null @@ -1,3139 +0,0 @@ -#include "mac_debmod.h" -#include - -#include -#include -#include -#include "../../ldr/mach-o/common.h" - -#if defined (__i386__) || defined(__x86_64__) -#define THREAD_STATE_NONE 13 -#else -#error unknown platform -#endif - -#ifdef __EA64__ -#define DEB_SEGM_BITNESS 2 -#define VM_USRSTACK VM_USRSTACK64 -#define COMMPAGE_START 0x7FFFFFE00000ull -#else -#define DEB_SEGM_BITNESS 1 -#define VM_USRSTACK VM_USRSTACK32 -#define COMMPAGE_START 0xFFFF0000ul -#endif - -//#define DEBUG_MAC_DEBUGGER - -#define BPT_CODE_SIZE X86_BPT_SIZE -static const uchar dyld_opcode[BPT_CODE_SIZE] = { 0x55 }; - -mac_debmod_t::stored_signals_t mac_debmod_t::pending_signals; - -mac_debmod_t::mac_debmod_t() : dyld(this, PLFM_386) //-V730 Not all members of a class are initialized inside the constructor -{ - exc_port = MACH_PORT_NULL; - set_platform("macosx"); - is64 = false; - reg_ctx = nullptr; -} - -mac_debmod_t::~mac_debmod_t() -{ - term_reg_ctx(); -} - -extern "C" -{ -extern boolean_t exc_server( - mach_msg_header_t *InHeadP, - mach_msg_header_t *OutHeadP); - -kern_return_t catch_exception_raise_state( - mach_port_t /*exception_port*/, - exception_type_t /*exception*/, - const exception_data_t /*code*/, - mach_msg_type_number_t /*codeCnt*/, - int * /*flavor*/, - const thread_state_t /*old_state*/, - mach_msg_type_number_t /*old_stateCnt*/, - thread_state_t /*new_state*/, - mach_msg_type_number_t * /*new_stateCnt*/); - -kern_return_t catch_exception_raise_state_identity( - mach_port_t /*exception_port*/, - mach_port_t /*thread*/, - mach_port_t /*task*/, - exception_type_t /*exception*/, - exception_data_t /*code*/, - mach_msg_type_number_t /*codeCnt*/, - int * /*flavor*/, - thread_state_t /*old_state*/, - mach_msg_type_number_t /*old_stateCnt*/, - thread_state_t /*new_state*/, - mach_msg_type_number_t * /*new_stateCnt*/); - -kern_return_t catch_exception_raise( - mach_port_t /*exception_port*/, - mach_port_t thread, - mach_port_t task, - exception_type_t exception, - exception_data_t code_vector, - mach_msg_type_number_t code_count); -} - -#define COMPLAIN_IF_FAILED(name) \ - if ( err != KERN_SUCCESS ) \ - msg(name ": %s\n", mach_error_string(err)) - -//-------------------------------------------------------------------------- -bool mac_debmod_t::get_thread_state(thid_t tid, machine_thread_state_t *state) -{ - if ( is64 ) - { - x86_thread_state64_t _state; - if ( get_thread_state64(tid, &_state) ) - { - state->__eax = _state.__rax; - state->__ebx = _state.__rbx; - state->__ecx = _state.__rcx; - state->__edx = _state.__rdx; - state->__edi = _state.__rdi; - state->__esi = _state.__rsi; - state->__ebp = _state.__rbp; - state->__esp = _state.__rsp; - state->__eip = _state.__rip; - state->__r8 = _state.__r8; - state->__r9 = _state.__r9; - state->__r10 = _state.__r10; - state->__r11 = _state.__r11; - state->__r12 = _state.__r12; - state->__r13 = _state.__r13; - state->__r14 = _state.__r14; - state->__r15 = _state.__r15; - state->__eflags = _state.__rflags; - state->__cs = _state.__cs; - state->__fs = _state.__fs; - state->__gs = _state.__gs; - return true; - } - } - else - { - x86_thread_state32_t _state; - if ( get_thread_state32(tid, &_state) ) - { - state->__eax = _state.__eax; - state->__ebx = _state.__ebx; - state->__ecx = _state.__ecx; - state->__edx = _state.__edx; - state->__edi = _state.__edi; - state->__esi = _state.__esi; - state->__ebp = _state.__ebp; - state->__esp = _state.__esp; - state->__eip = _state.__eip; - state->__eflags = _state.__eflags; - state->__ss = _state.__ss; - state->__cs = _state.__cs; - state->__ds = _state.__ds; - state->__es = _state.__es; - state->__fs = _state.__fs; - state->__gs = _state.__gs; - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::set_thread_state(thid_t tid, const machine_thread_state_t *state) -{ - bool ok = false; - if ( is64 ) - { - x86_thread_state64_t _state; - _state.__rax = state->__eax; - _state.__rbx = state->__ebx; - _state.__rcx = state->__ecx; - _state.__rdx = state->__edx; - _state.__rdi = state->__edi; - _state.__rsi = state->__esi; - _state.__rbp = state->__ebp; - _state.__rsp = state->__esp; - _state.__rip = state->__eip; - _state.__r8 = state->__r8; - _state.__r9 = state->__r9; - _state.__r10 = state->__r10; - _state.__r11 = state->__r11; - _state.__r12 = state->__r12; - _state.__r13 = state->__r13; - _state.__r14 = state->__r14; - _state.__r15 = state->__r15; - _state.__rflags = state->__eflags; - _state.__cs = state->__cs; - _state.__fs = state->__fs; - _state.__gs = state->__gs; - ok = set_thread_state64(tid, &_state); - } - else - { - x86_thread_state32_t _state; - _state.__eax = state->__eax; - _state.__ebx = state->__ebx; - _state.__ecx = state->__ecx; - _state.__edx = state->__edx; - _state.__edi = state->__edi; - _state.__esi = state->__esi; - _state.__ebp = state->__ebp; - _state.__esp = state->__esp; - _state.__eip = state->__eip; - _state.__eflags = state->__eflags; - _state.__ss = state->__ss; - _state.__cs = state->__cs; - _state.__ds = state->__ds; - _state.__es = state->__es; - _state.__fs = state->__fs; - _state.__gs = state->__gs; - ok = set_thread_state32(tid, &_state); - } - return ok; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::get_float_state(thid_t tid, machine_float_state_t *state) -{ - //-V:GET_FLOAT_STATE_COMMON:512 'memcpy' function will lead to overflow of the buffer -#define GET_FLOAT_STATE_COMMON(s1, s2) \ - do \ - { \ - s1->__fpu_fcw = *(uint16*)&s2.__fpu_fcw; \ - s1->__fpu_fsw = *(uint16*)&s2.__fpu_fsw; \ - s1->__fpu_ftw = s2.__fpu_ftw; \ - s1->__fpu_fop = s2.__fpu_fop; \ - s1->__fpu_ip = s2.__fpu_ip; \ - s1->__fpu_cs = s2.__fpu_cs; \ - s1->__fpu_dp = s2.__fpu_dp; \ - s1->__fpu_ds = s2.__fpu_ds; \ - s1->__fpu_mxcsr = s2.__fpu_mxcsr; \ - s1->__fpu_mxcsrmask = s2.__fpu_mxcsrmask; \ - /* __fpu_stmm0 thru __fpu_stmm7 */ \ - memcpy(&s1->__fpu_stmm0, &s2.__fpu_stmm0, sizeof(_STRUCT_MMST_REG)*8); \ - /* __fpu_xmm0 thru __fpu_xmm7 */ \ - memcpy(&s1->__fpu_xmm0, &s2.__fpu_xmm0, sizeof(_STRUCT_XMM_REG)*8); \ - /* __fpu_ymmh0 thru __fpu_ymmh7 */ \ - memcpy(&s1->__fpu_ymmh0, &s2.__fpu_ymmh0, sizeof(_STRUCT_XMM_REG)*8); \ - } \ - while ( false ) - - if ( is64 ) - { - x86_avx_state64_t _state; - if ( get_float_state64(tid, &_state) ) - { - GET_FLOAT_STATE_COMMON(state, _state); - /* __fpu_xmm8 thru __fpu_xmm15 */ - memcpy(&state->__fpu_xmm8, &_state.__fpu_xmm8, sizeof(_STRUCT_XMM_REG)*8); //-V512 - /* __fpu_ymmh8 thru __fpu_ymmh15 */ - memcpy(&state->__fpu_ymmh8, &_state.__fpu_ymmh8, sizeof(_STRUCT_XMM_REG)*8); //-V512 - return true; - } - } - else - { - x86_avx_state32_t _state; - if ( get_float_state32(tid, &_state) ) - { - GET_FLOAT_STATE_COMMON(state, _state); - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::set_float_state(thid_t tid, const machine_float_state_t *state) -{ - //-V:SET_FLOAT_STATE_COMMON:512 'memcpy' function will lead to overflow of the buffer -#define SET_FLOAT_STATE_COMMON(s1, s2) \ - do \ - { \ - *(uint16*)&s1.__fpu_fcw = s2->__fpu_fcw; \ - *(uint16*)&s1.__fpu_fsw = s2->__fpu_fsw; \ - s1.__fpu_ftw = s2->__fpu_ftw; \ - s1.__fpu_fop = s2->__fpu_fop; \ - s1.__fpu_ip = s2->__fpu_ip; \ - s1.__fpu_cs = s2->__fpu_cs; \ - s1.__fpu_dp = s2->__fpu_dp; \ - s1.__fpu_ds = s2->__fpu_ds; \ - s1.__fpu_mxcsr = s2->__fpu_mxcsr; \ - s1.__fpu_mxcsrmask = s2->__fpu_mxcsrmask; \ - /* __fpu_stmm0 thru __fpu_stmm7 */ \ - memcpy(&s1.__fpu_stmm0, &s2->__fpu_stmm0, sizeof(_STRUCT_MMST_REG)*8); \ - /* __fpu_xmm0 thru __fpu_xmm7 */ \ - memcpy(&s1.__fpu_xmm0, &s2->__fpu_xmm0, sizeof(_STRUCT_XMM_REG)*8); \ - /* __fpu_ymmh0 thru __fpu_ymmh7 */ \ - memcpy(&s1.__fpu_ymmh0, &s2->__fpu_ymmh0, sizeof(_STRUCT_XMM_REG)*8); \ - } \ - while ( false ) - - bool ok = false; - if ( is64 ) - { - x86_avx_state64_t _state; - SET_FLOAT_STATE_COMMON(_state, state); - /* __fpu_xmm8 thru __fpu_xmm15 */ - memcpy(&_state.__fpu_xmm8, &state->__fpu_xmm8, sizeof(_STRUCT_XMM_REG)*8); //-V512 - /* __fpu_ymmh8 thru __fpu_ymmh15 */ - memcpy(&_state.__fpu_ymmh8, &state->__fpu_ymmh8, sizeof(_STRUCT_XMM_REG)*8); //-V512 - ok = set_float_state64(tid, &_state); - } - else - { - x86_avx_state32_t _state; - SET_FLOAT_STATE_COMMON(_state, state); - ok = set_float_state32(tid, &_state); - } - return ok; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::get_debug_state(thid_t tid, machine_debug_state_t *state) -{ -#if __DARWIN_UNIX03 -#define DRNAME(name) __##name -#else -#define DRNAME(name) name -#endif - -#define GETDRS(s1, s2) \ - do \ - { \ - s1->__dr0 = s2.DRNAME(dr0); \ - s1->__dr1 = s2.DRNAME(dr1); \ - s1->__dr2 = s2.DRNAME(dr2); \ - s1->__dr3 = s2.DRNAME(dr3); \ - s1->__dr4 = s2.DRNAME(dr4); \ - s1->__dr5 = s2.DRNAME(dr5); \ - s1->__dr6 = s2.DRNAME(dr6); \ - s1->__dr7 = s2.DRNAME(dr7); \ - } \ - while ( false ) - - if ( is64 ) - { - x86_debug_state64_t _state; - if ( get_debug_state64(tid, &_state) ) - { - GETDRS(state, _state); - return true; - } - } - else - { - x86_debug_state32_t _state; - if ( get_debug_state32(tid, &_state) ) - { - GETDRS(state, _state); - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::set_debug_state(thid_t tid, const machine_debug_state_t *state) -{ -#define SETDRS(s1, s2) \ - do \ - { \ - s1.DRNAME(dr0) = s2->__dr0; \ - s1.DRNAME(dr1) = s2->__dr1; \ - s1.DRNAME(dr2) = s2->__dr2; \ - s1.DRNAME(dr3) = s2->__dr3; \ - s1.DRNAME(dr4) = s2->__dr4; \ - s1.DRNAME(dr5) = s2->__dr5; \ - s1.DRNAME(dr6) = s2->__dr6; \ - s1.DRNAME(dr7) = s2->__dr7; \ - } \ - while ( false ) - - bool ok = false; - if ( is64 ) - { - x86_debug_state64_t _state; - SETDRS(_state, state); - ok = set_debug_state64(tid, &_state); - } - else - { - x86_debug_state32_t _state; - SETDRS(_state, state); - ok = set_debug_state32(tid, &_state); - } - return ok; -} - -//-------------------------------------------------------------------------- -static const char *get_ptrace_name(int request) -{ - switch ( request ) - { - case PT_TRACE_ME: return "PT_TRACE_ME"; /* child declares it's being traced */ - case PT_READ_I: return "PT_READ_I"; /* read word in child's I space */ - case PT_READ_D: return "PT_READ_D"; /* read word in child's D space */ - case PT_READ_U: return "PT_READ_U"; /* read word in child's user structure */ - case PT_WRITE_I: return "PT_WRITE_I"; /* write word in child's I space */ - case PT_WRITE_D: return "PT_WRITE_D"; /* write word in child's D space */ - case PT_WRITE_U: return "PT_WRITE_U"; /* write word in child's user structure */ - case PT_CONTINUE: return "PT_CONTINUE"; /* continue the child */ - case PT_KILL: return "PT_KILL"; /* kill the child process */ - case PT_STEP: return "PT_STEP"; /* single step the child */ - case PT_ATTACH: return "PT_ATTACH"; /* trace some running process */ - case PT_DETACH: return "PT_DETACH"; /* stop tracing a process */ - case PT_SIGEXC: return "PT_SIGEXC"; /* signals as exceptions for current_proc */ - case PT_THUPDATE: return "PT_THUPDATE"; /* signal for thread# */ - case PT_ATTACHEXC: return "PT_ATTACHEXC"; /* attach to running process with signal exception */ - case PT_FORCEQUOTA: return "PT_FORCEQUOTA"; /* Enforce quota for root */ - case PT_DENY_ATTACH: return "PT_DENY_ATTACH"; - } - return "?"; -} - -//-------------------------------------------------------------------------- -int32 mac_debmod_t::qptrace(int request, pid_t _pid, caddr_t addr, int data) -{ - int32 code = ptrace(request, _pid, addr, data); - int saved_errno = errno; -// if ( (request == PT_CONTINUE || request == PT_STEP) && int(addr) == 1 ) -// addr = (caddr_t)get_ip(_pid); - debdeb("%s(%u, 0x%p, 0x%X) => 0x%X", get_ptrace_name(request), _pid, addr, data, code); - if ( code == -1 ) - deberr(""); - else - debdeb("\n"); - errno = saved_errno; - return code; -} - -//-------------------------------------------------------------------------- -ida_thread_info_t *mac_debmod_t::get_thread(thid_t tid) -{ - threads_t::iterator p = threads.find(tid); - if ( p == threads.end() ) - return NULL; - return &p->second; -} - -//-------------------------------------------------------------------------- -uval_t mac_debmod_t::get_dr(thid_t tid, int idx) -{ - machine_debug_state_t dr_regs; - if ( !get_debug_state(tid, &dr_regs) ) - return 0; - - switch ( idx ) - { - case 0: - return dr_regs.__dr0; - case 1: - return dr_regs.__dr1; - case 2: - return dr_regs.__dr2; - case 3: - return dr_regs.__dr3; - case 4: - return dr_regs.__dr4; - case 5: - return dr_regs.__dr5; - case 6: - return dr_regs.__dr6; - case 7: - return dr_regs.__dr7; - } - - return 0; -} - -//-------------------------------------------------------------------------- -static void set_dr(machine_debug_state_t &dr_regs, int idx, uval_t value) -{ - switch ( idx ) - { - case 0: - dr_regs.__dr0 = value; - break; - case 1: - dr_regs.__dr1 = value; - break; - case 2: - dr_regs.__dr2 = value; - break; - case 3: - dr_regs.__dr3 = value; - break; - case 4: - dr_regs.__dr4 = value; - break; - case 5: - dr_regs.__dr5 = value; - break; - case 6: - dr_regs.__dr6 = value; - break; - case 7: - dr_regs.__dr7 = value; - break; - } -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::set_dr(thid_t tid, int idx, uval_t value) -{ - machine_debug_state_t dr_regs; - - if ( !get_debug_state(tid, &dr_regs) ) - return false; - - ::set_dr(dr_regs, idx, value); - - return set_debug_state(tid, &dr_regs); -} - -//-------------------------------------------------------------------------- -ea_t mac_debmod_t::get_ip(thid_t tid) -{ - machine_thread_state_t state; - if ( !get_thread_state(tid, &state) ) - return BADADDR; - return state.__eip; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::qthread_setsinglestep(ida_thread_info_t &ti) -{ - machine_thread_state_t cpu; - if ( !get_thread_state(ti.tid, &cpu) ) - return false; - - ti.asked_step = ti.single_step; - int bit = ti.single_step ? EFLAGS_TRAP_FLAG : 0; - if ( ((cpu.__eflags ^ bit) & EFLAGS_TRAP_FLAG) == 0 ) - return KERN_SUCCESS; - - if ( ti.single_step ) - cpu.__eflags |= EFLAGS_TRAP_FLAG; - else - cpu.__eflags &= ~EFLAGS_TRAP_FLAG; - - return set_thread_state(ti.tid, &cpu); -} - -//-------------------------------------------------------------------------- -void my_mach_msg_t::display(const char *header) -{ -#ifdef DEBUG_MAC_DEBUGGER - msg("%s\n", header); - msg(" msgh_bits : 0x%x\n", hdr.msgh_bits); - msg(" msgh_size : 0x%x\n", hdr.msgh_size); - msg(" msgh_remote_port: %d\n", hdr.msgh_remote_port); - msg(" msgh_local_port : %d\n", hdr.msgh_local_port); - msg(" msgh_reserved : %d\n", hdr.msgh_reserved); - msg(" msgh_id : 0x%x\n", hdr.msgh_id); - if ( hdr.msgh_size > 24 ) - { - const uint32 *buf = ((uint32 *) this) + 6; - msg(" data :"); - int cnt = hdr.msgh_size / 4 - 6; - for ( int i=0; i < cnt; i++ ) - msg(" %08x", buf[i]); - msg("\n"); - } -#else - qnotused(header); -#endif -} - -// this function won't be called but is declared to avoid linker complaints -kern_return_t catch_exception_raise_state( - mach_port_t /*exception_port*/, - exception_type_t /*exception*/, - const exception_data_t /*code*/, - mach_msg_type_number_t /*codeCnt*/, - int * /*flavor*/, - const thread_state_t /*old_state*/, - mach_msg_type_number_t /*old_stateCnt*/, - thread_state_t /*new_state*/, - mach_msg_type_number_t * /*new_stateCnt*/) -{ - return KERN_FAILURE; -} - -// this function won't be called but is declared to avoid linker complaints -kern_return_t catch_exception_raise_state_identity( - mach_port_t /*exception_port*/, - mach_port_t /*thread*/, - mach_port_t /*task*/, - exception_type_t /*exception*/, - exception_data_t /*code*/, - mach_msg_type_number_t /*codeCnt*/, - int * /*flavor*/, - thread_state_t /*old_state*/, - mach_msg_type_number_t /*old_stateCnt*/, - thread_state_t /*new_state*/, - mach_msg_type_number_t * /*new_stateCnt*/) -{ - return KERN_FAILURE; -} - -// this function will be called by exc_server() -// we use exc_server() for 2 things: -// - to decode mach message and extract exception information -// - to actually handle the exception when we resume execution - -static bool parse_mach_message; -static bool mask_exception; -static mach_exception_info_t local_exinf; - -kern_return_t catch_exception_raise( - mach_port_t /*exception_port*/, - mach_port_t thread, - mach_port_t task, - exception_type_t exception, - exception_data_t code_vector, - mach_msg_type_number_t code_count) -{ - if ( parse_mach_message ) - { - local_exinf.task_port = task; - local_exinf.thread_port = thread; - local_exinf.exception_type = exception; - local_exinf.exception_data = code_vector; - local_exinf.data_count = code_count; - return KERN_SUCCESS; - } - - // handle the exception for real - if ( mask_exception ) - return KERN_SUCCESS; - - return KERN_FAILURE; -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::handle_bpts(debug_event_t *event, bool asked_step) -{ - int code = SIGTRAP; - - // Check for hardware breakpoints first. - // If we do not handle a hwbpt immediately, dr6 stays set and - // we discover it later, after resuming. This breaks everything. - ea_t bpt_ea = event->ea; - uval_t dr6val = get_dr(event->tid, 6); - for ( int i=0; i < MAX_BPT; i++ ) - { - if ( (dr6val & (1<tid, i) ) - { - bptaddr_t &bpta = event->set_bpt(); - bpta.hea = hwbpt_ea[i]; - bpta.kea = BADADDR; - set_dr(event->tid, 6, 0); // Clear the status bits - code = 0; - break; - } - } - } - // x86 returns EIP pointing to the next byte after CC. Take it into account: - bpt_ea--; - if ( code != 0 ) - { - if ( asked_step ) - { - event->set_eid(STEP); - code = 0; - } - else if ( bpts.find(bpt_ea) != bpts.end() ) - { - bptaddr_t &bpta = event->set_bpt(); - bpta.hea = BADADDR; - bpta.kea = BADADDR; - event->ea = bpt_ea; - code = 0; - } - } - return code; -} - -//-------------------------------------------------------------------------- -// event->tid is filled upon entry -// returns true: created a new event in 'event' -bool mac_debmod_t::handle_signal( - int code, - debug_event_t *event, - block_type_t block, - const my_mach_msg_t *excmsg) -{ - ida_thread_info_t *ti = get_thread(event->tid); - if ( ti == NULL ) - { // there is a rare race condition when a thread gets created just after - // last call to update_threads(). check it once more - update_threads(); - ti = get_thread(event->tid); - } - QASSERT(30075, ti != NULL); - - ti->child_signum = 0; - ti->block = block; - if ( block == bl_exception ) - ti->excmsg = *excmsg; - - event->pid = pid; - event->handled = false; - event->ea = get_ip(event->tid); - excinfo_t &exc = event->set_exception(); - exc.code = code; - exc.can_cont = true; - exc.ea = BADADDR; - - if ( code == SIGSTOP ) - { - if ( ti->pending_sigstop ) - { - debdeb("got pending SIGSTOP, good!\n"); - ti->pending_sigstop = false; - if ( ti->asked_step ) - { // not to lose an asked single step, do it again - ti->single_step = true; - qthread_setsinglestep(*ti); - } - my_resume_thread(*ti); - return false; - } - if ( run_state == rs_pausing ) - { - debdeb("successfully paused the process, good!\n"); - run_state = rs_running; - event->set_eid(NO_EVENT); - } - } - if ( event->eid() == EXCEPTION ) - { - bool suspend; - const exception_info_t *ei = find_exception(code); - if ( ei != NULL ) - { - exc.info.sprnt("got %s signal (%s)", ei->name.c_str(), ei->desc.c_str()); - suspend = should_suspend_at_exception(event, ei); - event->handled = ei->handle(); - if ( code == SIGKILL && run_state >= rs_exiting ) - { - event->handled = false; - suspend = false; - } - } - else - { - exc.info.sprnt("got unknown signal #%d", code); - suspend = true; - } - - if ( code == SIGTRAP ) - code = handle_bpts(event, ti->asked_step); - - ti->run_handled = event->handled; - ti->child_signum = code; - if ( run_state != rs_pausing && evaluate_and_handle_lowcnd(event) ) - return false; - if ( !suspend && event->eid() == EXCEPTION ) - { - log_exception(event, ei); - my_resume_thread(*ti); - return false; - } - } - return true; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::check_for_exception( - int timeout, - mach_exception_info_t *exinf, - my_mach_msg_t *excmsg) -{ - if ( exited() ) - return false; - - int flags = MACH_RCV_MSG; - if ( timeout != -1 ) - flags |= MACH_RCV_TIMEOUT; - else - timeout = MACH_MSG_TIMEOUT_NONE; - -// msg("check for exception, timeout %d, runstate=%d\n", timeout, run_state); - - kern_return_t err = mach_msg(&excmsg->hdr, - flags, - 0, // send size - sizeof(my_mach_msg_t), - exc_port, - timeout, // timeout - MACH_PORT_NULL); // notify port - if ( err != MACH_MSG_SUCCESS ) - return false; - if ( excmsg->hdr.msgh_remote_port == -1 ) // remote task alive? - return false; - task_suspend(task); - excmsg->display("received an exception, details:"); - - lock_begin(); - { - my_mach_msg_t reply_msg; - parse_mach_message = true; - memset(&local_exinf, 0, sizeof(local_exinf)); - bool ok = exc_server(&excmsg->hdr, &reply_msg.hdr); - QASSERT(30076, ok); - *exinf = local_exinf; - } - lock_end(); - return true; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::my_resume_thread(ida_thread_info_t &ti) -{ - bool ok = true; - - // setsinglestep may fail after kill(), ignore the return code - qthread_setsinglestep(ti); - - if ( ti.run_handled ) - ti.child_signum = 0; - - switch ( ti.block ) - { - case bl_signal: - if ( in_ptrace ) - { - // we detach from the process and will handle the rest - // using mach api - int pt = ti.single_step ? PT_STEP : PT_CONTINUE; - ok = qptrace(pt, pid, caddr_t(1), ti.child_signum) == 0; - } - else - { - kern_return_t err = thread_resume(ti.tid); - COMPLAIN_IF_FAILED("thread_resume"); - } - break; - - case bl_exception: - // handle the exception with exc_server - my_mach_msg_t reply_msg; - lock_begin(); - { - parse_mach_message = false; - mask_exception = ti.child_signum == 0; - ok = exc_server(&ti.excmsg.hdr, &reply_msg.hdr); - } - lock_end(); - - if ( ok ) - { - kern_return_t err; - err = mach_msg(&reply_msg.hdr, - MACH_SEND_MSG, - reply_msg.hdr.msgh_size, // send size - 0, - reply_msg.hdr.msgh_remote_port, - 0, // timeout - MACH_PORT_NULL); // notify port - COMPLAIN_IF_FAILED("mach_msg"); - ok = (err == KERN_SUCCESS); - } - task_resume(task); - break; - - default: // nothing to do, the process is already running - break; - } - // syscalls may fail after SIGKILL, do not check the error code - //QASSERT(30077, ok); - ti.block = bl_none; - ti.single_step = false; - return true; -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::exception_to_signal(const mach_exception_info_t *exinf) -{ - int code = exinf->exception_data[0]; - int sig = 0; - switch ( exinf->exception_type ) - { - case EXC_BAD_ACCESS: - if ( code == KERN_INVALID_ADDRESS ) - sig = SIGSEGV; - else - sig = SIGBUS; - break; - - case EXC_BAD_INSTRUCTION: - sig = SIGILL; - break; - - case EXC_ARITHMETIC: - sig = SIGFPE; - break; - - case EXC_EMULATION: - sig = SIGEMT; - break; - - case EXC_SOFTWARE: - switch ( code ) - { -// case EXC_UNIX_BAD_SYSCALL: -// sig = SIGSYS; -// break; -// case EXC_UNIX_BAD_PIPE: -// sig = SIGPIPE; -// break; -// case EXC_UNIX_ABORT: -// sig = SIGABRT; -// break; - case EXC_SOFT_SIGNAL: - sig = SIGKILL; - break; - } - break; - - case EXC_BREAKPOINT: - sig = SIGTRAP; - break; - case EXC_CRASH: - sig = SIGABRT; - break; - } - return sig; -} - -//-------------------------------------------------------------------------- -// check if there are any pending signals -bool mac_debmod_t::retrieve_pending_signal(int *status) -{ - bool has_pending_signal = false; - if ( !pending_signals.empty() ) - { - lock_begin(); - for ( stored_signals_t::iterator p=pending_signals.begin(); - p != pending_signals.end(); - ++p ) - { - if ( p->pid == pid ) - { - *status = p->status; - pending_signals.erase(p); - has_pending_signal = true; - break; - } - } - lock_end(); - } - - return has_pending_signal; -} - -//-------------------------------------------------------------------------- -pid_t mac_debmod_t::qwait(int *status, bool hang) -{ - pid_t ret; - lock_begin(); - if ( retrieve_pending_signal(status) ) - { - ret = pid; - } - else - { - int flags = hang ? 0 : WNOHANG; - ret = ::qwait(status, pid, flags); - if ( ret != pid && ret != 0 && ret != -1 ) - { - stored_signal_t &ss = pending_signals.push_back(); - ss.pid = pid; - ss.status = *status; - } - } - lock_end(); - return ret; -} - -//-------------------------------------------------------------------------- -// timeout in milliseconds -// 0 - no timeout, return immediately -// -1 - wait forever -void mac_debmod_t::get_debug_events(int timeout_ms) -{ -// msg("waiting, numpend=%lu timeout=%d...\n", events.size(), timeout_ms); -// for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) -// if ( p->second.blocked() ) -// msg("%d: blocked\n", p->first); - - int status; - debug_event_t event; - if ( !retrieve_pending_signal(&status) ) - { - update_threads(); - - // receive info about any exceptions in the program - // an arbitrary limit of 32 loop iterations is needed if low level breakpoints - // or automatically handled exceptions occur too often. - my_mach_msg_t excmsg; - mach_exception_info_t exinf; - for ( int i=0; - i < 32 && check_for_exception(timeout_ms, &exinf, &excmsg); - i++ ) - { - event.tid = exinf.thread_port; - int sig = exception_to_signal(&exinf); - debdeb("got exception for tid=%d sig=%d %s\n", event.tid, sig, strsignal(sig)); - if ( handle_signal(sig, &event, bl_exception, &excmsg) ) - { - events.enqueue(event, IN_BACK); - // do not break! - // collect all exceptions and convert them to debug_event_t - // if there was a breakpoint hit, convert it to debug_event_t as soon as - // possible. if we pass control to the ida kernel, it may remove the - // breakpoint and we won't recognize our breakpoint in the exception. - // break; - } - timeout_ms = 0; - } - if ( !events.empty() ) - return; - - // check the signals - pid_t wpid = qwait(&status, false); - if ( wpid == -1 || wpid == 0 ) - return; - } - - event.tid = maintid(); - if ( WIFSTOPPED(status) ) - { - int code = WSTOPSIG(status); - debdeb("SIGNAL %d: %s (stopped)\n", code, strsignal(code)); - if ( !handle_signal(code, &event, bl_signal, NULL) ) - return; - } - else - { - int exit_code; - if ( WIFSIGNALED(status) ) - { -// msg("SIGNAL: %s (terminated)\n", strsignal(WSTOPSIG(status))); - exit_code = WSTOPSIG(status); - } - else - { -// msg("SIGNAL: %d (exited)\n", WEXITSTATUS(status)); - exit_code = WEXITSTATUS(status); - } - event.pid = pid; - event.ea = BADADDR; - event.handled = true; - event.set_exit_code(PROCESS_EXITED, exit_code); - run_state = rs_exited; - } -// msg("low got event: %s\n", debug_event_str(&event)); - events.enqueue(event, IN_BACK); -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::handle_dyld_bpt(const debug_event_t *event) -{ - dmsg("handle dyld bpt, ea=%a\n", event->ea); - update_dyld(); - - machine_thread_state_t state; - bool ok = get_thread_state(event->tid, &state); - QASSERT(30078, ok); - - // emulate push ebp - state.__esp -= debapp_attrs.addrsize; - kern_return_t err = write_mem(state.__esp, &state.__ebp, debapp_attrs.addrsize); - QASSERT(30080, err == KERN_SUCCESS); - - ok = set_thread_state(event->tid, &state); - QASSERT(30081, ok); - - dbg_continue_after_event(event); -} - -//-------------------------------------------------------------------------- -gdecode_t idaapi mac_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) -{ - while ( true ) - { - // are there any pending events? - if ( events.retrieve(event) ) - { - switch ( event->eid() ) - { - case BREAKPOINT: - { - // if this is dyld bpt, do not return it to ida - if ( event->ea == dyld.infos.dyld_notify ) - { - handle_dyld_bpt(event); - continue; - } - - update_bpt_info_t b; - b.ea = event->ea; - b.type = event->bpt().hea == event->ea ? BPT_EXEC : BPT_SOFT; - - // it is possible that two threads triggered the same breakpoint, - // in which case we must ignore the redundant breakpoint event. - update_bpt_vec_t::const_iterator d = deleted_bpts.find(b); - if ( d != deleted_bpts.end() ) - { - if ( d->type == BPT_SOFT ) - { - // for software breakpoints, we must rewind ip back 1 - regval_t rval; - rval.set_int(get_ip(event->tid)-1); - drc_t drc = dbg_write_register(event->tid, pc_idx, &rval, NULL); - QASSERT(1536, drc != DRC_FAILED); - } - - // don't return the breakpoint event to ida: just continue - dbg_continue_after_event(event); - continue; - } - - } - break; - - case PROCESS_ATTACHED: - attaching = false; // finally attached to it - break; - - default: - break; - } - - last_event = *event; - - if ( debug_debugger ) - debdeb("GDE1: %s\n", debug_event_str(event)); - - return events.empty() ? GDE_ONE_EVENT : GDE_MANY_EVENTS; - } - - if ( exited() ) - break; - - get_debug_events(timeout_ms); - if ( events.empty() ) - break; - } - - return GDE_NO_EVENT; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::suspend_all_threads(void) -{ - /* Suspend the target process */ - kern_return_t err = task_suspend(task); - return err == KERN_SUCCESS; -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::resume_all_threads() -{ - kern_return_t err = task_resume(task); - QASSERT(30082, err == KERN_SUCCESS); -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::unblock_all_threads(void) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - my_resume_thread(p->second); -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::dbg_freeze_threads_except(thid_t tid) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - if ( p->first != tid ) - { - kern_return_t err = thread_suspend(p->first); - if ( err != KERN_SUCCESS ) - return 0; - } - } - return 1; -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::dbg_thaw_threads_except(thid_t tid) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - if ( p->first != tid ) - { - kern_return_t err = thread_resume(p->first); - if ( err != KERN_SUCCESS ) - { - if ( err == KERN_FAILURE ) - debdeb("Thread %d has suspend count of 0!\n", p->first); - else if ( err == KERN_INVALID_ARGUMENT ) - debdeb("Invalid thread id %d passed\n", p->first); - return 0; - } - } - } - return 1; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_continue_after_event(const debug_event_t *event) -{ - if ( exited() ) - { // reap the last child status - if ( pid != -1 ) - { - debdeb("%d: reaping the child status\n", pid); - int status; - qwait(&status, true); - pid = -1; - } - return DRC_OK; - } - - if ( event == NULL ) - return DRC_FAILED; - - ida_thread_info_t *ti = get_thread(event->tid); - if ( ti != NULL ) - ti->run_handled = event->eid() != EXCEPTION || event->handled; - - if ( debug_debugger ) - { - debdeb("continue after event %s (%d pending, block type %d, sig#=%d,%shandled)\n", - debug_event_str(event), - int(events.size()), - ti == NULL ? 0 : ti->block, - ti == NULL ? 0 : ti->child_signum, - ti != NULL && !ti->run_handled ? "un" : ""); - } - - if ( events.empty() && !attaching ) - { - // if the event queue is empty, we can resume all blocked threads - // here we resume only the threads blocked because of exceptions or signals - // if the debugger kernel has suspended a thread for another reason, it - // will stay suspended. - if ( run_state == rs_pausing ) - { // no need to stop anymore, plan to ignore the sigstop - ti->pending_sigstop = true; - run_state = rs_running; - } - unblock_all_threads(); - } - return DRC_OK; -} - -//-------------------------------------------------------------------------- -kern_return_t mac_debmod_t::read_mem(ea_t ea, void *buffer, int size, int *read_size) -{ - mach_vm_size_t data_count = 0; - kern_return_t err = mach_vm_read_overwrite(task, ea, size, (vm_address_t)buffer, &data_count); - if ( err != KERN_SUCCESS ) - debdeb("vm_read %d: ea=%a size=%d => (%s)\n", task, ea, size, mach_error_string(err)); -// show_hex(buffer, size, "data:\n"); - if ( read_size != NULL ) - *read_size = data_count; - return err; -} - -//-------------------------------------------------------------------------- -kern_return_t mac_debmod_t::write_mem(ea_t ea, void *buffer, int size) -{ - kern_return_t err; -/* vm_machine_attribute_val_t flush = MATTR_VAL_CACHE_FLUSH; -printf("buffer=%x size=%x\n", buffer, size); - err = vm_machine_attribute (mach_task_self(), (vm_offset_t)buffer, size, MATTR_CACHE, &flush); - QASSERT(30084, err == KERN_SUCCESS); // must succeed since it is our memory -*/ - err = mach_vm_write(task, ea, (vm_offset_t)buffer, size); - if ( err != KERN_SUCCESS && err != KERN_PROTECTION_FAILURE ) - debdeb("vm_write %d: ea=%a, size=%d => %s\n", task, ea, size, mach_error_string(err)); - return err; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::xfer_page(ea_t ea, void *buffer, int size, bool write) -{ - mach_vm_address_t b_start = ea; - mach_vm_size_t b_size; - mach_port_t b_object_name; - vm_region_basic_info_data_64_t b_data; - mach_msg_type_number_t b_info_size = VM_REGION_BASIC_INFO_COUNT_64; - - // get basic info for the vm region. - // note that this info is not sufficient for managing memory protections, - // because the region could be made up of sub-regions that contain various different protections - // (this tends to happend with the shared cache). - // we must recurse into the sub-regions to get more specific info. - kern_return_t err = mach_vm_region( - task, - &b_start, - &b_size, - VM_REGION_BASIC_INFO_64, - (vm_region_info_t)&b_data, - &b_info_size, - &b_object_name); - - if ( err != KERN_SUCCESS ) - { - // this call fails for the commpage segment - debdeb("%" FMT_64 "x: vm_region: %s\n", b_start, mach_error_string(err)); - return false; - } - - if ( b_start > ea ) - { - dmsg("%a: region start is higher %" FMT_64 "x\n", ea, b_start); - return false; - } - - int bit = write ? VM_PROT_WRITE : VM_PROT_READ; - - // max permissions do not allow it? fail - // strangely enough the kernel allows us to set any protection, - // including protections bigger than max_protection. but after that it crashes - // we have to verify it ourselves here. - // - // UPDATE: it seems on OSX 10.15, all code regions have max protection r-x, - // but the OS still allows us to explicity set the writable flag with impunity. - // This check is over a decade old and it's likely not relevant anymore, - // so I'm commenting it out to allow software breakpoints to work normally on OSX 10.15. - // - // Moreover, lldb doesn't care about max_protection either - so as long as we're - // doing the same thing as lldb we should be ok. For reference, see the following - // functions in the lldb source: - // - // MachVMMemory::Write - // MachVMRegion::SetProtections - // - //if ( (b_data.max_protection & bit) == 0 ) - //return false; - - mach_vm_address_t b_end = b_start + b_size; - mach_vm_address_t r_start = b_start; - mach_vm_size_t r_size = 0; - - // recurse into the sub-regions of the top-level vm region, - // and find the one that contains the desired ea. - for ( ; r_start < b_end; r_start += r_size ) - { - natural_t depth = 1; - vm_region_submap_info_data_64_t r_data; - mach_msg_type_number_t r_info_size = VM_REGION_SUBMAP_INFO_COUNT_64; - err = mach_vm_region_recurse( - task, - &r_start, - &r_size, - &depth, - (vm_region_info_t)&r_data, - &r_info_size); - - if ( err != KERN_SUCCESS ) - break; - if ( r_start >= b_end ) - break; - - // check if this sub-region contains the desired ea - if ( ea < r_start || ea >= r_start + r_size ) - continue; - - if ( (r_data.protection & bit) == 0 ) - { - // set the desired bit - vm_prot_t new_prot = r_data.protection | bit; - err = KERN_FAILURE; - if ( write ) - { - err = mach_vm_protect(task, r_start, r_size, 0, new_prot); - if ( err != KERN_SUCCESS && (new_prot & VM_PROT_COPY) == 0 ) - { - new_prot |= VM_PROT_COPY; // if failed, make a copy of the page - goto LASTPROT; - } - } - else - { - LASTPROT: - err = mach_vm_protect(task, r_start, r_size, 0, new_prot); - } - if ( err != KERN_SUCCESS ) - { - debdeb("%d: could not set %s permission at %" FMT_64 "x\n", - task, write ? "write" : "read", r_start); - return false; - } - } - - // attempt to xfer - if ( write ) - err = write_mem(ea, buffer, size); - else - err = read_mem(ea, buffer, size, NULL); - - bool ok = (err == KERN_SUCCESS); - if ( ok && write ) - { - vm_machine_attribute_val_t flush = MATTR_VAL_OFF; - err = mach_vm_machine_attribute(task, r_start, r_size, MATTR_CACHE, &flush); - if ( err != KERN_SUCCESS ) - { - static bool complained = false; - if ( !complained ) - { - complained = true; - dmsg("Unable to flush data/instruction cache ea=0x%" FMT_64 "x size=%ld: %s\n", - r_start, long(r_size), mach_error_string(err)); - } - } - } - - // restore old memory protection - if ( (r_data.protection & bit) == 0 ) - { - err = mach_vm_protect(task, r_start, r_size, 0, r_data.protection); - QASSERT(30085, err == KERN_SUCCESS); - } - - return ok; - } - - dmsg("%a: no vm region found\n", ea); - return false; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::xfer_memory(ea_t ea, void *buffer, int size, bool write) -{ - return xfer_page(ea, buffer, size, write); -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::_read_memory(ea_t ea, void *buffer, int size, bool suspend) -{ - if ( exited() || pid <= 0 || size <= 0 ) - return -1; - -// debdeb("READ MEMORY %a:%d: START\n", ea, size); - // stop all threads before accessing the process memory - if ( suspend && !suspend_all_threads() ) - return -1; - if ( exited() ) - return -1; - -// bool ok = xfer_memory(ea, buffer, size, false); - int read_size; - kern_return_t err = read_mem(ea, buffer, size, &read_size); - bool ok = err == KERN_SUCCESS; - - if ( suspend ) - resume_all_threads(); -// debdeb("READ MEMORY %a:%d: END\n", ea, size); - return ok ? read_size : 0; -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::_write_memory(ea_t ea, const void *buffer, int size, bool suspend) -{ - if ( exited() || pid <= 0 || size <= 0 ) - return -1; - - // stop all threads before accessing the process memory - if ( suspend && !suspend_all_threads() ) - return -1; - if ( exited() ) - return -1; - - bool ok = xfer_memory(ea, (void*)buffer, size, true); - - if ( suspend ) - resume_all_threads(); - - return ok ? size : 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi mac_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring * /*errbuf*/) -{ - return _write_memory(ea, buffer, size, true); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi mac_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring * /*errbuf*/) -{ - return _read_memory(ea, buffer, size, true); -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::add_dll(const image_info_t &ii) -{ - debug_event_t ev; - modinfo_t &mi_ll = ev.set_modinfo(LIB_LOADED); - ev.pid = pid; - ev.tid = maintid(); - ev.ea = ii.base; - ev.handled = true; - mi_ll.name = ii.name; - mi_ll.base = ii.base; - mi_ll.size = ii.size; - mi_ll.rebase_to = BADADDR; - if ( is_dll && stricmp(ii.name.c_str(), input_file_path.c_str()) == 0 ) - mi_ll.rebase_to = ii.base; - events.enqueue(ev, IN_FRONT); - - dlls.insert(std::make_pair(ii.base, ii)); - dlls_to_import.insert(ii.base); -} - -//-------------------------------------------------------------------------- -inline bool is_zeropage(const segment_command &sg) -{ - return sg.vmaddr == 0 && sg.fileoff == 0 && sg.initprot == 0; -} - -//-------------------------------------------------------------------------- -inline bool is_text_segment(const segment_command &sg) -{ - if ( is_zeropage(sg) ) - return false; - const char *name = sg.segname; - for ( int i=0; i < sizeof(sg.segname); i++, name++ ) - if ( *name != '_' ) - break; - return strnicmp(name, "TEXT", 4) == 0; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::import_symbols(const image_info_t &ii) -{ - struct ida_local macho_importer_t : public macho_visitor_t - { - mac_debmod_t *md; - macho_importer_t(mac_debmod_t *_md) : macho_visitor_t(MV_SYMBOLS), md(_md) {} - void visit_symbol(ea_t ea, const char *name) - { - md->save_debug_name(ea, name); - } - }; - macho_importer_t mi(this); - return parse_macho_image(mi, ii); -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::import_dll(const import_request_t &req) -{ - images_t::const_iterator p = dlls.find(req.base); - if ( p == dlls.end() ) - return false; - return import_symbols(p->second); -} - -//-------------------------------------------------------------------------- -void idaapi mac_debmod_t::dbg_stopped_at_debug_event( - import_infos_t *infos, - bool dlls_added, - thread_name_vec_t *) -{ - if ( !dlls_added ) - return; - - // we will take advantage of this event to import information - // about the exported functions from the loaded dlls - for ( easet_t::const_iterator p = dlls_to_import.begin(); p != dlls_to_import.end(); ++p ) - { - images_t::const_iterator q = dlls.find(*p); - if ( q == dlls.end() ) - continue; - - const image_info_t &ii = q->second; - - // for the mac_server, try to import shared cache libs on the client side - // since symbol files might be available. - if ( infos != NULL && dyld.is_shared_cache_lib(ii.base) ) - infos->push_back(import_request_t(ii.base, ii.name, ii.uuid)); - else - import_symbols(ii); - } - - dlls_to_import.clear(); -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::cleanup(void) -{ - pid = 0; - is_dll = false; - run_state = rs_exited; - dyld.clear(); - term_exception_ports(); - - threads.clear(); - dlls.clear(); - dlls_to_import.clear(); - events.clear(); - attaching = false; - is64 = false; - exeimg.clear(); - - bpts.clear(); - - inherited::cleanup(); -} - -//-------------------------------------------------------------------------- -// -// DEBUGGER INTERFACE FUNCTIONS -// -//-------------------------------------------------------------------------- -bool mac_debmod_t::thread_exit_event_planned(thid_t tid) -{ - for ( eventlist_t::iterator p=events.begin(); p != events.end(); ++p ) - { - if ( p->eid() == THREAD_EXITED && p->tid == tid ) - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::update_threads(void) -{ - bool generated_events = false; - thread_act_port_array_t threadList; - mach_msg_type_number_t threadCount; - kern_return_t err = task_threads(task, &threadList, &threadCount); - std::set live_tids; - if ( err == KERN_SUCCESS ) - { - QASSERT(30089, threadCount > 0); - for ( int i=0; i < threadCount; i++ ) - { - mach_port_t port = threadList[i]; - int tid = port; - threads_t::iterator p = threads.find(tid); - if ( p == threads.end() ) - { - debug_event_t ev; - ev.set_info(THREAD_STARTED); - ev.pid = pid; - ev.tid = tid; - ev.ea = BADADDR; - ev.handled = true; - events.enqueue(ev, IN_FRONT); - threads.insert(std::make_pair(tid, ida_thread_info_t(tid, port))); - generated_events = true; - set_hwbpts(tid); // set hardware breakpoints if any - } - live_tids.insert(tid); - } - err = mach_vm_deallocate (mach_task_self(), (vm_address_t)threadList, threadCount * sizeof (thread_t)); - QASSERT(30090, err == KERN_SUCCESS); - // remove dead threads - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ) - { - thid_t tid = p->first; - if ( live_tids.find(tid) == live_tids.end() && !thread_exit_event_planned(tid) ) - { - debug_event_t ev; - ev.set_exit_code(THREAD_EXITED, 0); - ev.pid = pid; - ev.tid = tid; - ev.ea = BADADDR; - ev.handled = true; - events.enqueue(ev, IN_BACK); - generated_events = true; - p = threads.erase(p); - continue; - } - ++p; - } - } - return generated_events; -} - -//-------------------------------------------------------------------------- -thid_t mac_debmod_t::init_main_thread(bool reattaching) -{ - thread_act_port_array_t threadList; - mach_msg_type_number_t threadCount; - kern_return_t err = task_threads(task, &threadList, &threadCount); - QASSERT(30091, err == KERN_SUCCESS); - QASSERT(30092, threadCount > 0); - mach_port_t port = threadList[0]; // the first thread is the main thread - thid_t tid = port; - if ( !reattaching ) - { - threads.insert(std::make_pair(tid, ida_thread_info_t(tid, port))); - threads.begin()->second.block = bl_signal; - } - err = mach_vm_deallocate(mach_task_self(), (vm_address_t)threadList, threadCount * sizeof(thread_t)); - QASSERT(30093, err == KERN_SUCCESS); - return tid; -} - -//-------------------------------------------------------------------------- -static kern_return_t save_exception_ports(task_t task, mach_exception_port_info_t *info) -{ - info->count = (sizeof (info->ports) / sizeof (info->ports[0])); - return task_get_exception_ports(task, - EXC_MASK_ALL, - info->masks, - &info->count, - info->ports, - info->behaviors, - info->flavors); -} - -//------------------------------------------------------------------------- -static kern_return_t restore_exception_ports(task_t task, const mach_exception_port_info_t *info) -{ - kern_return_t err = KERN_SUCCESS; - for ( int i = 0; i < info->count; i++ ) - { - err = task_set_exception_ports(task, - info->masks[i], - info->ports[i], - info->behaviors[i], - info->flavors[i]); - if ( err != KERN_SUCCESS ) - break; - } - return err; -} - -//------------------------------------------------------------------------- -void mac_debmod_t::init_exception_ports(void) -{ - kern_return_t err; - - // allocate a new port to receive exceptions - err = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &exc_port); - QASSERT(30094, err == KERN_SUCCESS); - - // add the 'send' right to send replies to threads - err = mach_port_insert_right(mach_task_self(), exc_port, exc_port, MACH_MSG_TYPE_MAKE_SEND); - QASSERT(30095, err == KERN_SUCCESS); - - // save old exception ports - err = save_exception_ports(task, &saved_exceptions); - QASSERT(30096, err == KERN_SUCCESS); - - // set new port for all exceptions - err = task_set_exception_ports(task, EXC_MASK_SOFTWARE | EXC_MASK_BREAKPOINT, exc_port, EXCEPTION_DEFAULT, THREAD_STATE_NONE); - QASSERT(30097, err == KERN_SUCCESS); - -} - -//------------------------------------------------------------------------- -void mac_debmod_t::term_exception_ports(void) -{ - if ( exc_port != MACH_PORT_NULL ) - { - kern_return_t err = restore_exception_ports(mach_task_self(), &saved_exceptions); - QASSERT(30098, err == KERN_SUCCESS); - err = mach_port_deallocate(mach_task_self(), exc_port); - QASSERT(30099, err == KERN_SUCCESS); - exc_port = MACH_PORT_NULL; - } -} - -//----------------------------------------------------------------------------- -bool mac_debmod_t::verify_user_privilege() -{ - struct group *dev_group = getgrnam("_developer"); - if ( dev_group == NULL ) - return false; - - gid_t grouplist[NGROUPS_MAX]; - int ngroups = getgroups(NGROUPS_MAX, grouplist); - for ( int i = 0; i < ngroups; i++ ) - if ( grouplist[i] == dev_group->gr_gid ) - return true; - - return false; -} - -//----------------------------------------------------------------------------- -bool mac_debmod_t::verify_code_signature() -{ - SecCodeRef code = NULL; - sec_code_janitor_t code_janitor(code); - - OSStatus status = SecCodeCopySelf(0, &code); - if ( status != errSecSuccess ) - return false; - - status = SecCodeCheckValidity(code, kSecCSDefaultFlags, NULL); - return status == errSecSuccess; -} - -//----------------------------------------------------------------------------- -bool mac_debmod_t::acquire_taskport_right() -{ - OSStatus status; - AuthorizationRef auth_ref = NULL; - auth_ref_janitor_t ref_janitor(auth_ref); - AuthorizationFlags auth_flags = kAuthorizationFlagExtendRights - | kAuthorizationFlagPreAuthorize - | (1 << 5) /* kAuthorizationFlagLeastPrivileged */; - - // create an authorization context - status = AuthorizationCreate( - NULL, - kAuthorizationEmptyEnvironment, - auth_flags, - &auth_ref); - - if ( status != errAuthorizationSuccess ) - return false; - - AuthorizationItem taskport_items[] = { { "system.privilege.taskport" } }; - AuthorizationRights auth_rights = { 1, taskport_items }; - AuthorizationRights *out_rights = NULL; - auth_rights_janitor_t rights_janitor(out_rights); - - // first try to authorize without credentials - status = AuthorizationCopyRights( - auth_ref, - &auth_rights, - kAuthorizationEmptyEnvironment, - auth_flags, - &out_rights); - - if ( status != errAuthorizationSuccess ) - { - qstring user; - qstring pass; - - if ( !qgetenv("MAC_DEBMOD_USER", &user) - || !qgetenv("MAC_DEBMOD_PASS", &pass) ) - { - return false; - } - - AuthorizationItem credentials[] = - { - { kAuthorizationEnvironmentUsername }, - { kAuthorizationEnvironmentPassword }, - { kAuthorizationEnvironmentShared } - }; - - credentials[0].valueLength = user.length(); - credentials[0].value = user.begin(); - credentials[1].valueLength = pass.length(); - credentials[1].value = pass.begin(); - - AuthorizationEnvironment env = { 3, credentials }; - - // if we received rights in the previous call to AuthorizationCopyRights, - // free it before we re-use the pointer - rights_janitor.~janitor_t(); //-V749 Destructor of the 'rights_janitor' object will be invoked a second time after leaving the object's scope - - status = AuthorizationCopyRights( - auth_ref, - &auth_rights, - &env, - auth_flags, - &out_rights); - - bzero(user.begin(), user.length()); - bzero(pass.begin(), pass.length()); - - return status == errAuthorizationSuccess; - } - - return true; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::handle_process_start(pid_t _pid) -{ - debdeb("handle process start %d\n", _pid); - pid = _pid; - - int status; - int k = qwait(&status, true); - debdeb("qwait on %d: %x (ret=%d)\n", pid, status, k); - QASSERT(30190, k == pid); - - cputype = get_process_cpu(pid); - debapp_attrs.addrsize = get_cpu_bitness(cputype); - is64 = debapp_attrs.addrsize == 8; -#ifdef __X86__ - if ( is64 ) - { - dwarning("Process with pid %d is an x86_64 process. Please use mac_serverx64 to debug it.", pid); - return false; - } -#endif - - term_reg_ctx(); - init_reg_ctx(); - - if ( !WIFSTOPPED(status) ) - { - if ( WIFEXITED(status) ) - { - int exitval = WEXITSTATUS(status); - int err = int8(exitval); - msg("process %d exited unexpectedly with code %d\n", _pid, exitval); - if ( err < 0 ) - msg("possible cause: %s (%d)\n", strerror(-err), -err); - warning("Process exited before debugging start."); - return false; - } - else if ( WIFSIGNALED(status) ) - { - msg("process %d stopped unexpectedly because of signal %d\n", _pid, WTERMSIG(status)); - warning("Process stopped before debugging start."); - return false; - } - debdeb("not stopped?\n"); - return false; - } - if ( WSTOPSIG(status) != SIGTRAP && WSTOPSIG(status) != SIGSTOP ) - { - warning("Got unexpected signal at debugging start."); - msg("got signal %d? (expected SIGTRAP or SIGSTOP)\n", WSTOPSIG(status)); - return false; - } - - /* Get the mach task for the target process */ - kern_return_t err = task_for_pid(mach_task_self(), pid, &task); - if ( err == KERN_FAILURE ) // no access? - { -#define OSX_DEBUGGER_HINT "For more info, please see the 'Mac OS X debugger' help entry (shortcut F1)." - char **argv = *_NSGetArgv(); - const char *program = qbasename(argv[0]); - if ( strstr(program, "server") == NULL ) - program = NULL; // runing local mac debugger module - if ( program != NULL ) - { - dwarning("Permission denied. Please ensure that '%s' is either codesigned or running as root.\n\n" - OSX_DEBUGGER_HINT, - program); - } - else - { - dwarning("Please run IDA with elevated permissons for local debugging.\n" - "Another solution is to run mac_server and use localhost as\n" - "the remote computer name.\n\n" - OSX_DEBUGGER_HINT); - } - return false; - } - QASSERT(30100, err == KERN_SUCCESS); - - in_ptrace = true; - thid_t tid = init_main_thread(false); - debdeb("initially stopped at %a pid=%d tid=%d task=%d\n", get_ip(tid), pid, tid, task); - run_state = rs_running; - - init_dyld(); - init_exeimg(pid, tid); - update_dyld(); - - init_exception_ports(); - return true; -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::create_process_start_event(pid_t _pid, thid_t tid) -{ - debug_event_t ev; - modinfo_t &mi_ps = ev.set_modinfo(PROCESS_STARTED); - ev.pid = _pid; - ev.tid = tid; - ev.ea = BADADDR; - ev.handled = true; - - mi_ps.base = exeimg.base; - mi_ps.name = exeimg.name; - mi_ps.size = exeimg.size; - - events.enqueue(ev, IN_BACK); -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) -{ - void *child_pid; - drc_t drc = maclnx_launch_process(this, path, args, startdir, flags, - input_path, input_file_crc32, &child_pid, - errbuf); - - if ( drc > 0 - && child_pid != NULL - && !handle_process_start((ssize_t)child_pid) ) - { - drc = DRC_NETERR; - } - return drc; -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::create_process_attach_event(pid_t _pid) -{ - // generate the attach event - debug_event_t ev; - modinfo_t &mi_pa = ev.set_modinfo(PROCESS_ATTACHED); - ev.pid = _pid; - ev.tid = maintid(); - ev.ea = get_ip(ev.tid); - ev.handled = true; - mi_pa.name = exeimg.name; - mi_pa.base = exeimg.base; - mi_pa.size = exeimg.size; - mi_pa.rebase_to = BADADDR; - events.enqueue(ev, IN_BACK); - - // generate THREAD_STARTED events - update_threads(); - - // block the process until all generated events are processed - attaching = true; -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -drc_t idaapi mac_debmod_t::dbg_attach_process(pid_t _pid, int /*event_id*/, int /*flags*/, qstring * /*errbuf*/) -{ - if ( qptrace(PT_ATTACH, _pid, NULL, NULL) == 0 - && handle_process_start(_pid) ) - { - create_process_attach_event(_pid); - return DRC_OK; - } - return DRC_FAILED; -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -drc_t idaapi mac_debmod_t::dbg_detach_process(void) -{ - if ( dyld.infos.dyld_notify != 0 ) - { - // remove the dyld breakpoint - int size = dbg_write_memory(dyld.infos.dyld_notify, dyld_opcode, BPT_CODE_SIZE, NULL); - QASSERT(30101, size == BPT_CODE_SIZE); - dyld.infos.dyld_notify = 0; - } - // cleanup exception ports - term_exception_ports(); - if ( in_ptrace ) - { - qptrace(PT_DETACH, pid, 0, 0); - in_ptrace = false; - } - else - { - // let the process run - unblock_all_threads(); - } - debug_event_t ev; - ev.set_eid(PROCESS_DETACHED); - ev.pid = pid; - ev.tid = maintid(); - ev.ea = BADADDR; - ev.handled = true; - events.enqueue(ev, IN_BACK); - return DRC_OK; -} - -//-------------------------------------------------------------------------- -// if we have to do something as soon as we noticed the connection -// broke, this is the correct place -bool idaapi mac_debmod_t::dbg_prepare_broken_connection(void) -{ - broken_connection = true; - return true; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_prepare_to_pause_process(qstring * /*errbuf*/) -{ - debdeb("remote_prepare_to_pause_process\n"); - if ( run_state >= rs_exiting ) - return DRC_FAILED; - run_state = rs_pausing; - kill(pid, SIGSTOP); - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_exit_process(qstring * /*errbuf*/) -{ - // since debhtread is retrieving events in advance, we possibly - // already received the PROCESS_EXITED event. Check for it - if ( exited() ) - { - debdeb("%d: already exited\n", pid); - return DRC_OK; - } - - run_state = rs_exiting; - bool ok = false; - debdeb("%d: sending SIGKILL\n", pid); - if ( kill(pid, SIGKILL) == 0 ) - { - ok = true; - unblock_all_threads(); - } - else - { - debdeb("SIGKILL %d failed: %s\n", pid, strerror(errno)); - } - return ok ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -// Set hardware breakpoints for one thread -bool mac_debmod_t::set_hwbpts(int hThread) -{ - machine_debug_state_t dr_regs; - - if ( !get_debug_state(hThread, &dr_regs) ) - return false; - - ::set_dr(dr_regs, 0, hwbpt_ea[0]); - ::set_dr(dr_regs, 1, hwbpt_ea[1]); - ::set_dr(dr_regs, 2, hwbpt_ea[2]); - ::set_dr(dr_regs, 3, hwbpt_ea[3]); - ::set_dr(dr_regs, 6, 0); - ::set_dr(dr_regs, 7, dr7); - - bool ok = set_debug_state(hThread, &dr_regs); - //dmsg("set_hwbpts: tid=%d DR0=%a DR1=%a DR2=%a DR3=%a DR7=%08X => %d\n", - //hThread, - //hwbpt_ea[0], - //hwbpt_ea[1], - //hwbpt_ea[2], - //hwbpt_ea[3], - //dr7, - //ok); - - return ok; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::refresh_hwbpts(void) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - if ( !set_hwbpts(p->second.tid) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -// 2-ok(pagebpt), 1-ok, 0-failed, -2-read failed -int idaapi mac_debmod_t::dbg_add_bpt( - bytevec_t *orig_bytes, - bpttype_t type, - ea_t ea, - int len) -{ - update_threads(); - - if ( type == BPT_SOFT ) - { - if ( len <= 0 ) - len = bpt_code.size(); - if ( orig_bytes != NULL && read_bpt_orgbytes(orig_bytes, ea, len) < 0 ) - return -2; - debmod_bpt_t dbpt(ea, len); - if ( !dbg_read_memory(ea, dbpt.saved, len, NULL) ) - return -2; - int size = bpt_code.size(); - if ( dbg_write_memory(ea, bpt_code.begin(), size, NULL) != size ) - return 0; - bpts[ea] = dbpt; - return 1; - } - - return add_hwbpt(type, ea, len); -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -int idaapi mac_debmod_t::dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) -{ - // we update threads when we delete a breakpoint because it gives - // better results: new threads are immediately added to the list of - // known threads and properly suspended before "single step" - update_threads(); - - if ( orig_bytes != NULL ) - { - if ( dbg_write_memory(ea, orig_bytes, len, NULL) == len ) - { - bpts.erase(ea); - return true; - } - } - - return del_hwbpt(ea, type); -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_thread_get_sreg_base(ea_t *pea, thid_t /*tid*/, int /*sreg_value*/, qstring * /*errbuf*/) -{ - // assume all segments are based on zero - *pea = 0; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_thread_suspend(thid_t tid) -{ - debdeb("remote_thread_suspend %d\n", tid); - kern_return_t err = thread_suspend(tid); - return err == KERN_SUCCESS ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_thread_continue(thid_t tid) -{ - debdeb("remote_thread_continue %d\n", tid); - kern_return_t err = thread_resume(tid); - return err == KERN_SUCCESS ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_set_resume_mode(thid_t tid, resume_mode_t resmod) -{ - if ( resmod != RESMOD_INTO ) - return DRC_FAILED; // not supported - - ida_thread_info_t *t = get_thread(tid); - if ( t == NULL ) - return DRC_FAILED; - t->single_step = true; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -#define qoffsetof2(s, f) (qoffsetof(regctx_t, s) + qoffsetof(decltype(regctx_t::s), f)) -#define offset_size(s, f) qoffsetof2(s, f), sizeof(decltype(regctx_t::s)::f) - -//-------------------------------------------------------------------------- -struct regctx_t : public regctx_base_t -{ - mac_debmod_t &debmod; - - machine_thread_state_t cpu; - machine_float_state_t fpu; - - // clsmask helpers - bool clsmask_regs; - bool clsmask_fpregs; - - regctx_t(dynamic_register_set_t &_idaregs, mac_debmod_t &_debmod); - bool init(void); - bool load(void); - bool store(void); -}; - -//-------------------------------------------------------------------------- -regctx_t::regctx_t(dynamic_register_set_t &_idaregs, mac_debmod_t &_debmod) - : regctx_base_t(_idaregs), - debmod(_debmod) -{ - memset(&cpu, 0, sizeof(cpu)); - memset(&fpu, 0, sizeof(fpu)); - - clsmask_regs = 0; - clsmask_fpregs = 0; - - idaregs.set_regclasses(x86_register_classes); -} - -//-------------------------------------------------------------------------- -bool regctx_t::init(void) -{ - if ( (clsmask & X86_RC_ALL) == 0 ) - return false; - // setup clsmask helpers - clsmask_regs = (clsmask & (X86_RC_GENERAL|X86_RC_SEGMENTS)) != 0; - clsmask_fpregs = (clsmask & (X86_RC_FPU|X86_RC_MMX|X86_RC_XMM|X86_RC_YMM)) != 0; - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::load(void) -{ - if ( !init() ) - return false; - if ( clsmask_regs ) - if ( !debmod.get_thread_state(tid, &cpu) ) - return false; - if ( clsmask_fpregs ) - if ( !debmod.get_float_state(tid, &fpu) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -bool regctx_t::store(void) -{ - if ( clsmask_regs ) - if ( !debmod.set_thread_state(tid, &cpu) ) - return false; - if ( clsmask_fpregs ) - if ( !debmod.set_float_state(tid, &fpu) ) - return false; - return true; -} - -//-------------------------------------------------------------------------- -static void clear_ival(const regctx_t */*ctx*/, regval_t *value, void */*user_data*/) -{ - value->ival = 0; -} - -//-------------------------------------------------------------------------- -static void nop_write(regctx_t */*ctx*/, const regval_t */*value*/, void */*user_data*/) -{ -} - -//-------------------------------------------------------------------------- -static void ymm_read(const regctx_t *ctx, regval_t *value, void *user_data) -{ - size_t ymm_reg_idx = size_t(user_data); - const uint128 *ptrl = (uint128 *) &ctx->fpu.__fpu_xmm0; - const uint128 *ptrh = (uint128 *) &ctx->fpu.__fpu_ymmh0; - uint8_t ymm[32]; - *(uint128 *) &ymm[ 0] = ptrl[ymm_reg_idx]; - *(uint128 *) &ymm[16] = ptrh[ymm_reg_idx]; - value->set_bytes(ymm, sizeof(ymm)); -} - -//-------------------------------------------------------------------------- -static void ymm_write(regctx_t *ctx, const regval_t *value, void *user_data) -{ - size_t ymm_reg_idx = size_t(user_data); - const uint8_t *ymm = (const uint8_t *) value->get_data(); - uint128 *ptrl = (uint128 *) &ctx->fpu.__fpu_xmm0; - uint128 *ptrh = (uint128 *) &ctx->fpu.__fpu_ymmh0; - ptrl[ymm_reg_idx] = *(uint128 *) &ymm[ 0]; - ptrh[ymm_reg_idx] = *(uint128 *) &ymm[16]; -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::init_reg_ctx(void) -{ - reg_ctx = new regctx_t(idaregs, *this); - - // Populate register context - size_t offset = 0; - -#ifdef __EA64__ - if ( is64 ) - { - reg_ctx->add_ival(r_rax, offset_size(cpu, __eax)); - reg_ctx->add_ival(r_rbx, offset_size(cpu, __ebx)); - reg_ctx->add_ival(r_rcx, offset_size(cpu, __ecx)); - reg_ctx->add_ival(r_rdx, offset_size(cpu, __edx)); - reg_ctx->add_ival(r_rsi, offset_size(cpu, __esi)); - reg_ctx->add_ival(r_rdi, offset_size(cpu, __edi)); - reg_ctx->add_ival(r_rbp, offset_size(cpu, __ebp)); - sp_idx = reg_ctx->add_ival(r_rsp, offset_size(cpu, __esp)); - pc_idx = reg_ctx->add_ival(r_rip, offset_size(cpu, __eip)); - reg_ctx->add_ival(r_r8, offset_size(cpu, __r8)); - reg_ctx->add_ival(r_r9, offset_size(cpu, __r9)); - reg_ctx->add_ival(r_r10, offset_size(cpu, __r10)); - reg_ctx->add_ival(r_r11, offset_size(cpu, __r11)); - reg_ctx->add_ival(r_r12, offset_size(cpu, __r12)); - reg_ctx->add_ival(r_r13, offset_size(cpu, __r13)); - reg_ctx->add_ival(r_r14, offset_size(cpu, __r14)); - reg_ctx->add_ival(r_r15, offset_size(cpu, __r15)); - } - else -#endif - { - reg_ctx->add_ival(r_eax, offset_size(cpu, __eax)); - reg_ctx->add_ival(r_ebx, offset_size(cpu, __ebx)); - reg_ctx->add_ival(r_ecx, offset_size(cpu, __ecx)); - reg_ctx->add_ival(r_edx, offset_size(cpu, __edx)); - reg_ctx->add_ival(r_esi, offset_size(cpu, __esi)); - reg_ctx->add_ival(r_edi, offset_size(cpu, __edi)); - reg_ctx->add_ival(r_ebp, offset_size(cpu, __ebp)); - sp_idx = reg_ctx->add_ival(r_esp, offset_size(cpu, __esp)); - pc_idx = reg_ctx->add_ival(r_eip, offset_size(cpu, __eip)); - } - sr_idx = reg_ctx->add_ival(x86_registers[R_EFLAGS], offset_size(cpu, __eflags)); - - cs_idx = reg_ctx->add_ival(x86_registers[R_CS], offset_size(cpu, __cs)); - fs_idx = reg_ctx->add_ival(x86_registers[R_FS], offset_size(cpu, __fs)); - gs_idx = reg_ctx->add_ival(x86_registers[R_GS], offset_size(cpu, __gs)); - if ( is64 ) - { - ds_idx = reg_ctx->add_func(x86_registers[R_DS], clear_ival, nop_write); - es_idx = reg_ctx->add_func(x86_registers[R_ES], clear_ival, nop_write); - ss_idx = reg_ctx->add_func(x86_registers[R_SS], clear_ival, nop_write); - } - else - { - ds_idx = reg_ctx->add_ival(x86_registers[R_DS], offset_size(cpu, __ds)); - es_idx = reg_ctx->add_ival(x86_registers[R_ES], offset_size(cpu, __es)); - ss_idx = reg_ctx->add_ival(x86_registers[R_SS], offset_size(cpu, __ss)); - } - - offset = qoffsetof2(fpu, __fpu_stmm0); - for ( size_t i = R_ST0; i <= R_ST7; i++, offset += 16 ) - reg_ctx->add_fval(x86_registers[i], offset, 10); - reg_ctx->add_ival(x86_registers[R_CTRL], offset_size(fpu, __fpu_fcw)); - reg_ctx->add_ival(x86_registers[R_STAT], offset_size(fpu, __fpu_fsw)); - reg_ctx->add_ival(x86_registers[R_TAGS], offset_size(fpu, __fpu_ftw)); - - offset = qoffsetof2(fpu, __fpu_stmm0); - for ( size_t i = R_MMX0; i <= R_MMX7; i++, offset += 16 ) - reg_ctx->add_data(x86_registers[i], offset, 8); - - offset = qoffsetof2(fpu, __fpu_xmm0); - for ( size_t i = R_XMM0; i <= R_LAST_XMM; i++, offset += 16 ) - { -#ifdef __EA64__ - if ( !is64 && i >= R_XMM8 ) - break; -#endif - reg_ctx->add_data(x86_registers[i], offset, 16); - } - reg_ctx->add_ival(x86_registers[R_MXCSR], offset_size(fpu, __fpu_mxcsr)); - - for ( size_t i = R_YMM0; i <= R_LAST_YMM; i++ ) - { -#ifdef __EA64__ - if ( !is64 && i >= R_YMM8 ) - break; -#endif - reg_ctx->add_func(x86_registers[i], ymm_read, ymm_write, (void *) (i - R_YMM0)); - } -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::term_reg_ctx(void) -{ - if ( reg_ctx != nullptr ) - { - delete reg_ctx; - idaregs.clear(); - } - reg_ctx = nullptr; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_read_registers( - thid_t tid, - int clsmask, - regval_t *values, - qstring * /*errbuf*/) -{ - if ( values == nullptr ) - return DRC_FAILED; - - reg_ctx->setup(tid, clsmask); - if ( !reg_ctx->load() ) - return DRC_FAILED; - - reg_ctx->read_all(values); - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_write_register( - thid_t tid, - int reg_idx, - const regval_t *value, - qstring * /*errbuf*/) -{ - if ( value == nullptr ) - return DRC_FAILED; - - reg_ctx->setup(tid); - reg_ctx->setup_reg(reg_idx); - if ( !reg_ctx->load() ) - return DRC_FAILED; - - if ( !reg_ctx->patch(reg_idx, value) ) - return DRC_FAILED; - - if ( !reg_ctx->store() ) - return DRC_FAILED; - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -bool idaapi mac_debmod_t::write_registers( - thid_t tid, - int start, - int count, - const regval_t *values) -{ - if ( values == nullptr ) - return false; - - reg_ctx->setup(tid); - for ( size_t i = 0; i < count; i++ ) - reg_ctx->setup_reg(start + i); - if ( !reg_ctx->load() ) - return false; - - for ( size_t i = 0; i < count; i++, values++ ) - if ( !reg_ctx->patch(start + i, values) ) - return false; - - if ( !reg_ctx->store() ) - return false; - - return true; -} - -//-------------------------------------------------------------------------- -// find a dll in the memory information array -bool mac_debmod_t::exist_dll(const images_t &images, ea_t base) -{ - // dyld is never unloaded - if ( base == dyld.base_ea ) - return true; - return images.find(base) != images.end(); -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::update_dyld(void) -{ - if ( dyld.base_ea == BADADDR || dyld.infos_ea == BADADDR ) - return; // dyld not there (static program?) - - if ( dyld.update_infos() ) - { - dyld.update_ranges(); - - QASSERT(30104, dyld.infos.version >= 1); - - // collect info for all dlls in the info_array - struct ida_local image_collector_t : public dll_visitor_t - { - images_t *newimgs; - const mac_debmod_t *dm; - image_collector_t(images_t *_newimgs, const mac_debmod_t *_dm) - : newimgs(_newimgs), dm(_dm) {} - virtual void visit_dll( - ea_t base, - asize_t size, - const char *name, - const bytevec_t &uuid) override - { - if ( base != dm->exeimg.base ) - { - image_info_t ii(base, size, name, uuid); - newimgs->insert(std::make_pair(base, ii)); - } - } - }; - - images_t newimgs; - image_collector_t ic(&newimgs, this); - if ( !dyld.parse_info_array(dyld.infos.num_info, dyld.infos.info_array, ic) ) - return; - - // remove unexisting dlls - for ( images_t::iterator p = dlls.begin(); p != dlls.end(); ) - { - if ( !exist_dll(newimgs, p->first) ) - { - debug_event_t ev; - ev.set_info(LIB_UNLOADED); - ev.pid = pid; - ev.tid = maintid(); - ev.ea = BADADDR; - ev.handled = true; - ev.info() = p->second.name; - events.enqueue(ev, IN_FRONT); - p = dlls.erase(p); - } - else - { - ++p; - } - } - - // add new dlls - for ( images_t::const_iterator p = newimgs.begin(); p != newimgs.end(); ++p ) - { - ea_t base = p->second.base; - // address zero is ignored - if ( base != 0 && dlls.find(base) == dlls.end() ) - add_dll(p->second); - } - } -} - -//-------------------------------------------------------------------------- -int mac_debmod_t::visit_vm_regions(vm_region_visitor_t &rv) -{ - mach_vm_size_t size = 0; - for ( mach_vm_address_t addr = 0; ; addr += size ) - { - mach_port_t object_name; // unused - vm_region_top_info_data_t info; - mach_msg_type_number_t count = VM_REGION_TOP_INFO_COUNT; - kern_return_t kr = mach_vm_region(task, &addr, &size, VM_REGION_TOP_INFO, - (vm_region_info_t)&info, &count, &object_name); - - //debdeb("task=%d addr=%" FMT_64 "x size=%" FMT_64 "x err=%x\n", task, addr, size, kr); - if ( kr != KERN_SUCCESS ) - break; - - mach_vm_address_t subaddr; - mach_vm_size_t subsize = 0; - mach_vm_address_t end = addr + size; - for ( subaddr=addr; subaddr < end; subaddr += subsize ) - { - natural_t depth = 1; - vm_region_submap_info_data_64_t sinfo; - count = VM_REGION_SUBMAP_INFO_COUNT_64; - kr = mach_vm_region_recurse(task, &subaddr, &subsize, &depth, - (vm_region_info_t)&sinfo, &count); - if ( kr != KERN_SUCCESS ) - break; - if ( subaddr >= end ) - break; - - memory_info_t mi; - mi.start_ea = subaddr; - mi.end_ea = subaddr + subsize; - mi.bitness = DEB_SEGM_BITNESS; - - if ( sinfo.protection & 1 ) mi.perm |= SEGPERM_READ; - if ( sinfo.protection & 2 ) mi.perm |= SEGPERM_WRITE; - if ( sinfo.protection & 4 ) mi.perm |= SEGPERM_EXEC; - - int code = rv.visit_region(mi); - if ( code != 0 ) - return code; - } - } - - return 0; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::parse_macho_image(macho_visitor_t &mv, const image_info_t &ii) -{ - bool ok = false; - // we must avoid parsing dyld_shared_cache libs on disk, since the libraries - // on the system are altered before they are inserted into the shared cache - - // thus they will not match their corresponding image in memory. - // we must either have extracted symbol files from the cache or simply parse - // the image in memory directly. - if ( dyld.is_shared_cache_lib(ii.base) ) - ok = dyld.parse_local_symbol_file(ii.base, ii.name.c_str(), ii.uuid, mv); - else - ok = dyld.parse_macho_file(ii.name.c_str(), ii.base, mv, ii.uuid); - - // if parsing failed on disk, fall back to parsing the image in memory - if ( !ok ) - ok = dyld.parse_macho_mem(ii.base, mv); - - return ok; -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::init_dyld(void) -{ - dyld.update_bitness(); - - // find the memory region that corresponds to dyld - debdeb("searching process memory for dyld...\n"); - struct ida_local dyld_finder_t : public vm_region_visitor_t - { - mac_debmod_t *dm; - char fname[QMAXPATH]; - - dyld_finder_t(mac_debmod_t *_dm) : dm(_dm) { memset(fname, 0, sizeof(fname)); } - - virtual int visit_region(memory_info_t &mi) override - { - if ( dm->dyld.is_dyld_header(mi.start_ea, fname, sizeof(fname)) ) - { - dm->dmsg("%a: located dyld header and file '%s'\n", mi.start_ea, fname); - dm->dyld.base_ea = mi.start_ea; - return 1; - } - return 0; - } - }; - - dyld_finder_t df(this); - if ( visit_vm_regions(df) != 1 || dyld.base_ea == BADADDR ) - { - dwarning("failed to find dyld in the target process"); - return; - } - - // add the dyld module - image_info_t ii; - ii.base = dyld.base_ea; - ii.name = df.fname; - - dyld.calc_image_info(NULL, &ii.size, &ii.uuid, ii.name.c_str()); - - add_dll(ii); - - // immediately import it - dbg_stopped_at_debug_event(NULL, true, NULL); - - dyld.infos_ea = find_debug_name("_dyld_all_image_infos"); - dyld.ranges_ea = find_debug_name("_dyld_shared_cache_ranges"); - - if ( dyld.infos_ea == BADADDR || !dyld.update_infos() ) - { - dwarning("failed to read _dyld_all_image_infos in the target process"); - return; - } - - ea_t notify_ea = dyld.infos.dyld_notify; - dmsg("%a: setting bpt for library notifications\n", notify_ea); - - uchar opcode[BPT_CODE_SIZE]; - read_mem(notify_ea, opcode, sizeof(opcode), NULL); - if ( memcmp(opcode, dyld_opcode, BPT_CODE_SIZE) != 0 ) - dwarning("Unexpected dyld_opcode in the debugger server (init_dyld): %x", *(uint32*)opcode); - - // set a breakpoint for library loads/unloads - dbg_add_bpt(NULL, BPT_SOFT, notify_ea, -1); -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::init_exeimg(pid_t _pid, thid_t tid) -{ - // get the executable module name - char buf[MAXSTR]; - get_exec_fname(_pid, buf, sizeof(buf)); - exeimg.name = buf; - - // identify the exe image in memory - struct ida_local exe_finder_t : public vm_region_visitor_t - { - mac_debmod_t *dm; - exe_finder_t(mac_debmod_t *_dm) : dm(_dm) {} - virtual int visit_region(memory_info_t &mi) override - { - if ( dm->dyld.is_exe_header(mi.start_ea) ) - { - dm->dmsg("%a: located exe header\n", mi.start_ea); - image_info_t &ii = dm->exeimg; - ii.base = mi.start_ea; - dm->dyld.calc_image_info(NULL, &ii.size, &ii.uuid, mi.start_ea); - return 1; - } - return 0; - } - }; - - exe_finder_t ef(this); - if ( visit_vm_regions(ef) != 1 ) - dwarning("failed to find executable %s in the target process", buf); - - // add the exe module with the correct base address - create_process_start_event(_pid, tid); - import_symbols(exeimg); -} - -//-------------------------------------------------------------------------- -/*static const char *get_share_mode_name(unsigned char sm, char *buf, size_t bufsize) -{ - switch ( sm ) - { - case SM_COW: return "COW"; - case SM_PRIVATE: return "PRIVATE"; - case SM_EMPTY: return "EMPTY"; - case SM_SHARED: return "SHARED"; - case SM_TRUESHARED: return "TRUESHARED"; - case SM_PRIVATE_ALIASED: return "PRIV_ALIAS"; - case SM_SHARED_ALIASED: return "SHRD_ALIAS"; - } // 1234567890 - qsnprintf(buf, bufsize, "%x", sm); - return buf; -}*/ - -//-------------------------------------------------------------------------- -void mac_debmod_t::clean_stack_regions(meminfo_vec_t &miv) const -{ - // It seems on some versions of OSX, mach_vm_region() can report a region - // of size PAGE_SIZE that lies at the bottom of the user stack. I'm not sure if this - // is a bug in the OS, some undocumented range internal to OSX, or maybe even a deliberate attempt - // to confuse debuggers/hacking tools. Either way, IDA must ignore this region because if - // it doesn't, the stack will be split across two segments which can break stack unwinding. - for ( meminfo_vec_t::iterator p = miv.begin(); p != miv.end(); ++p ) - { - // the erroneous region has size PAGE_SIZE - if ( p->size() != PAGE_SIZE ) - continue; - - // check if this region is located somewhere near the default stack base. - // from vm_param.h: ASLR can slide the stack down by up to 1 MB. - range_t stack_range(VM_USRSTACK-0x100000, VM_USRSTACK); - if ( !stack_range.contains(*p) ) - continue; - - // check if next region is beyond the default stack base. - // (i.e. 'p' represents the bottom of the stack). - meminfo_vec_t::const_iterator next = p; - if ( ++next == miv.end() || next->start_ea < VM_USRSTACK ) - continue; - - // check if previous region is aligned with the erroneous region - meminfo_vec_t::iterator prev = p; - if ( prev == miv.begin() || (--prev)->end_ea != p->start_ea ) - continue; - - // we have found a bogus region at the bottom of the stack. - // extend the previous region and remove this erroneous one. - prev->end_ea = p->end_ea; - miv.erase(p); - break; - } -} - -//-------------------------------------------------------------------------- -void mac_debmod_t::get_image_meminfo(meminfo_vec_t &out, const image_info_t &ii) -{ - struct ida_local sect_finder_t : public macho_visitor_t - { - meminfo_vec_t &out; - const char *dllname; - - sect_finder_t(meminfo_vec_t &_out, const char *path) - : macho_visitor_t(MV_SECTIONS), out(_out), dllname(qbasename(path)) {} - - virtual void visit_section( - ea_t start, - ea_t end, - const qstring &name, - const qstring &, - bool is_code) override - { - if ( start != end ) - { - memory_info_t &s = out.push_back(); - s.name.sprnt("%s:%s", dllname, name.c_str()); - s.start_ea = start; - s.end_ea = end; - s.sclass = is_code ? "CODE" : "DATA"; - s.perm = SEGPERM_READ | (is_code ? SEGPERM_EXEC : 0); - s.bitness = DEB_SEGM_BITNESS; - } - } - }; - - sect_finder_t sf(out, ii.name.c_str()); - parse_macho_image(sf, ii); -} - -//-------------------------------------------------------------------------- -drc_t mac_debmod_t::get_memory_info(meminfo_vec_t &out, bool suspend) -{ - if ( suspend && !suspend_all_threads() ) - return DRC_NOPROC; - if ( exited() ) - return DRC_NOPROC; - - meminfo_vec_t sects; - - // parse section info for the exe - get_image_meminfo(sects, exeimg); - - // parse section info for each loaded dll - for ( images_t::const_iterator i = dlls.begin(); i != dlls.end(); ++i ) - get_image_meminfo(sects, i->second); - - std::sort(sects.begin(), sects.end()); - - meminfo_vec_t regions; - // collect other known vm regions (stack, heap, etc.) - struct ida_local vm_region_collector_t : public vm_region_visitor_t - { - meminfo_vec_t ®ions; - vm_region_collector_t(meminfo_vec_t &_regions) : regions(_regions) {} - virtual int visit_region(memory_info_t &r) override - { - if ( r.start_ea == COMMPAGE_START ) - r.name = "COMMPAGE"; - regions.push_back(r); - return 0; - } - }; - - vm_region_collector_t rc(regions); - visit_vm_regions(rc); - std::sort(regions.begin(), regions.end()); - - macho_utils_t::merge(out, regions, sects); - // FIXME: eventually this should be removed and replaced with a general solution that - // coagulates all user stack vm regions into one. However this would require us to identify exactly - // which memory regions represent the user stack - a task that the OS purposefully makes difficult. - // I'm not sure how we can do it without guessing. Also see issue IDA-1813. - clean_stack_regions(out); - - if ( suspend ) - resume_all_threads(); - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_get_memory_info(meminfo_vec_t &ranges, qstring * /*errbuf*/) -{ - drc_t drc = get_memory_info(ranges, true); - if ( drc == DRC_OK ) - { - if ( same_as_oldmemcfg(ranges) ) - drc = DRC_NOCHG; - else - save_oldmemcfg(ranges); - } - return drc; -} - -//-------------------------------------------------------------------------- -int idaapi mac_debmod_t::dbg_get_scattered_image(scattered_image_t &si, ea_t base) -{ - if ( !dyld.is_shared_cache_lib(base) ) - return -1; - - struct ida_local segm_visitor_t : public macho_visitor_t - { - scattered_image_t &si; - - segm_visitor_t(scattered_image_t &_si) - : macho_visitor_t(MV_SECTIONS), si(_si) {} - - virtual void visit_section( - ea_t start, - ea_t end, - const qstring &name, - const qstring &, - bool) override - { - scattered_segm_t &ss = si.push_back(); - ss.start_ea = start; - ss.end_ea = end; - ss.name = name; - } - }; - - segm_visitor_t sv(si); - return dyld.parse_macho_mem(base, sv) ? 1 : -1; -} - -//-------------------------------------------------------------------------- -bool mac_debmod_t::get_image_info(image_info_t *ii, ea_t base) const -{ - if ( base == exeimg.base ) - { - *ii = exeimg; - return true; - } - - images_t::const_iterator p = dlls.find(base); - if ( p == dlls.end() ) - return false; - - *ii = p->second; - return true; -} - -//-------------------------------------------------------------------------- -bool idaapi mac_debmod_t::dbg_get_image_uuid(bytevec_t *uuid, ea_t base) -{ - image_info_t ii; - if ( !get_image_info(&ii, base) ) - return false; - *uuid = ii.uuid; - return true; -} - -//-------------------------------------------------------------------------- -ea_t idaapi mac_debmod_t::dbg_get_segm_start(ea_t base, const qstring &segname) -{ - image_info_t ii; - if ( !get_image_info(&ii, base) ) - return BADADDR; - - struct ida_local segm_finder_t : public macho_visitor_t - { - ea_t *result; - const qstring &segname; - - segm_finder_t(ea_t *_result, const qstring &_segname) - : macho_visitor_t(MV_SEGMENTS), result(_result), segname(_segname) {} - - virtual void visit_segment(ea_t start, ea_t, const qstring &name, bool) override - { - if ( segname == name ) - *result = start; - } - }; - - ea_t result = BADADDR; - segm_finder_t finder(&result, segname); - parse_macho_image(finder, ii); - - return result; -} - -//-------------------------------------------------------------------------- -void idaapi mac_debmod_t::dbg_set_debugging(bool _debug_debugger) -{ - debug_debugger = _debug_debugger; -} - -//-------------------------------------------------------------------------- -drc_t idaapi mac_debmod_t::dbg_init(uint32_t *flags2, qstring * /*errbuf*/) -{ - // remember if the input is a dll - cleanup(); - cleanup_hwbpts(); - - if ( flags2 != nullptr ) - *flags2 = DBG_HAS_GET_PROCESSES | DBG_HAS_DETACH_PROCESS; - - // here we ensure that IDA can in fact debug other applications. - // if not, we warn the user. - if ( getuid() == 0 ) - return DRC_OK; - - if ( !verify_code_signature() ) - { - msg("WARNING: This program must either be codesigned or run as root to debug mac applications.\n"); - } - else if ( !verify_user_privilege() ) - { - msg("WARNING: This program must be launched by a user in the _developer group in order to debug mac applications\n"); - } - else if ( !acquire_taskport_right() ) - { - msg("WARNING: The debugger could not acquire the necessary permissions from the OS to debug mac applications.\n" - "You will likely have to specify the proper credentials at process start. To avoid this, you can set\n" - "the MAC_DEBMOD_USER and MAC_DEBMOD_PASS environment variables.\n"); - } - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -void idaapi mac_debmod_t::dbg_term(void) -{ - cleanup(); - cleanup_hwbpts(); -} - -//-------------------------------------------------------------------------- -bool idaapi mac_debmod_t::thread_get_fs_base( - thid_t /*tid*/, - int /*reg_idx*/, - ea_t * /*pea*/) -{ - return false; -} - -//-------------------------------------------------------------------------- -int idaapi mac_debmod_t::get_task_suspend_count(void) -{ - task_basic_info info; - mach_msg_type_number_t task_info_count; - kern_return_t err = task_info(task, TASK_BASIC_INFO, (task_info_t)&info, &task_info_count); - debdeb("task_info(TASK_BASIC_INFO) returned %d\n", err); - if ( err != KERN_FAILURE ) - { - return info.suspend_count; - } - else - { - perror("get_task_suspend_count:task_info"); - return -1; - } -} - -//-------------------------------------------------------------------------- -// recovering from a broken session consists in the following steps: -// -// 1 - Cleanup dlls previously recorded. -// 2 - Restore broken breakpoints. -// 3 - Generate PROCESS_STARTED and PROCESS_ATTACHED event. -// -bool idaapi mac_debmod_t::dbg_continue_broken_connection(pid_t _pid) -{ - debmod_t::dbg_continue_broken_connection(pid); - bool ret = false; - - // cleanup previously recorded information - dlls.clear(); - exeimg.clear(); - - // restore broken breakpoints and continue like a normal attach - if ( restore_broken_breakpoints() ) - { - thid_t tid = init_main_thread(true); - - init_dyld(); - init_exeimg(_pid, tid); - update_dyld(); - create_process_attach_event(_pid); - - ret = true; - } - return ret; -} - -//-------------------------------------------------------------------------- -bool init_subsystem() -{ - mac_debmod_t::reuse_broken_connections = true; - - return true; -} - -//-------------------------------------------------------------------------- -bool term_subsystem() -{ - return true; -} - -//-------------------------------------------------------------------------- -debmod_t *create_debug_session(void *) -{ - return new mac_debmod_t(); -} diff --git a/idasdk75/dbg/mac/mac_debmod.h b/idasdk75/dbg/mac/mac_debmod.h deleted file mode 100644 index 13d5679..0000000 --- a/idasdk75/dbg/mac/mac_debmod.h +++ /dev/null @@ -1,546 +0,0 @@ -#ifndef __MAC_DEBUGGER_MODULE__ -#define __MAC_DEBUGGER_MODULE__ - -/* -* This is the mach (MAC OS X) debugger module -* -* Functions unique for Mach (MAC OS X) -* -*/ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MD msg("at line %d\n", __LINE__); - -#define processor_t mach_processor_t - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // needed for SDK versions <= 10.7 -#undef processor_t - -#include "macbase_debmod.h" - -typedef int HANDLE; -class mac_debmod_t; - -#define INVALID_HANDLE_VALUE (-1) - -//-------------------------------------------------------------------------- -// -// DEBUGGER INTERNAL DATA -// -//-------------------------------------------------------------------------- -enum run_state_t -{ - rs_running, - rs_pausing, - rs_suspended, // used by iphone - rs_exiting, - rs_exited -}; - -// image information -struct image_info_t -{ - ea_t base; - asize_t size; - qstring name; - bytevec_t uuid; - - image_info_t() { clear(); } - image_info_t(ea_t _base, uint32 _size, const qstring &_name, const bytevec_t &_uuid) - : base(_base), size(_size), name(_name), uuid(_uuid) {} - - void clear() - { - base = BADADDR; - size = 0; - name.clear(); - uuid.clear(); - } -}; - -typedef std::map images_t; // key: image base address - -union my_mach_msg_t -{ - mach_msg_header_t hdr; - char data[1024]; - void display(const char *header); -}; - -//-------------------------------------------------------------------------- -enum block_type_t -{ - bl_none, // process is running - bl_signal, // blocked due to a signal (must say PTRACE_CONT) - bl_exception, // blocked due to an exception (must say task_resume()) -}; - -//-------------------------------------------------------------------------- -// thread information -//-V:ida_thread_info_t:730 Not all members of a class are initialized inside the constructor. Consider inspecting: excmsg. -struct ida_thread_info_t -{ - ida_thread_info_t(thid_t t, mach_port_t p) - : tid(t), port(p), child_signum(0), asked_step(false), single_step(false), - pending_sigstop(false), block(bl_none), run_handled(false) {} - int tid; - mach_port_t port; - int child_signum; - bool asked_step; - bool single_step; - bool pending_sigstop; - block_type_t block; - my_mach_msg_t excmsg; - bool run_handled; - bool blocked(void) const { return block != bl_none; } -}; - -typedef std::map threads_t; // (tid -> info) - -//-------------------------------------------------------------------------- -struct mach_exception_port_info_t -{ - exception_mask_t masks[EXC_TYPES_COUNT]; - mach_port_t ports[EXC_TYPES_COUNT]; - exception_behavior_t behaviors[EXC_TYPES_COUNT]; - thread_state_flavor_t flavors[EXC_TYPES_COUNT]; - mach_msg_type_number_t count; -}; - -typedef qvector nlists_t; - -//-------------------------------------------------------------------------- -struct mach_exception_info_t -{ - task_t task_port; - thread_t thread_port; - exception_type_t exception_type; - exception_data_t exception_data; - mach_msg_type_number_t data_count; -}; - -//-------------------------------------------------------------------------- -typedef janitor_t auth_ref_janitor_t; -template <> inline auth_ref_janitor_t::~janitor_t() -{ - if ( resource != NULL ) - AuthorizationFree(resource, kAuthorizationFlagDefaults); -} - -//-------------------------------------------------------------------------- -typedef janitor_t auth_rights_janitor_t; -template <> inline auth_rights_janitor_t::~janitor_t() -{ - if ( resource != NULL ) - AuthorizationFreeItemSet(resource); -} - -//-------------------------------------------------------------------------- -typedef janitor_t sec_code_janitor_t; -template <> inline sec_code_janitor_t::~janitor_t() -{ - if ( resource != NULL ) - CFRelease(resource); -} - -struct vm_region_visitor_t -{ - virtual int visit_region(memory_info_t &mi) = 0; -}; - -//-------------------------------------------------------------------------- -struct machine_thread_state_t -{ - ea_t __eax; - ea_t __ebx; - ea_t __ecx; - ea_t __edx; - ea_t __edi; - ea_t __esi; - ea_t __ebp; - ea_t __esp; - ea_t __eip; - ea_t __r8; - ea_t __r9; - ea_t __r10; - ea_t __r11; - ea_t __r12; - ea_t __r13; - ea_t __r14; - ea_t __r15; - ea_t __eflags; - ea_t __ss; - ea_t __cs; - ea_t __ds; - ea_t __es; - ea_t __fs; - ea_t __gs; -}; - -//-------------------------------------------------------------------------- -struct machine_float_state_t -{ - uint16 __fpu_fcw; - uint16 __fpu_fsw; - uint8 __fpu_ftw; - uint16 __fpu_fop; - uint32 __fpu_ip; - uint16 __fpu_cs; - uint32 __fpu_dp; - uint16 __fpu_ds; - uint32 __fpu_mxcsr; - uint32 __fpu_mxcsrmask; - - _STRUCT_MMST_REG __fpu_stmm0; - _STRUCT_MMST_REG __fpu_stmm1; - _STRUCT_MMST_REG __fpu_stmm2; - _STRUCT_MMST_REG __fpu_stmm3; - _STRUCT_MMST_REG __fpu_stmm4; - _STRUCT_MMST_REG __fpu_stmm5; - _STRUCT_MMST_REG __fpu_stmm6; - _STRUCT_MMST_REG __fpu_stmm7; - - _STRUCT_XMM_REG __fpu_xmm0; - _STRUCT_XMM_REG __fpu_xmm1; - _STRUCT_XMM_REG __fpu_xmm2; - _STRUCT_XMM_REG __fpu_xmm3; - _STRUCT_XMM_REG __fpu_xmm4; - _STRUCT_XMM_REG __fpu_xmm5; - _STRUCT_XMM_REG __fpu_xmm6; - _STRUCT_XMM_REG __fpu_xmm7; - _STRUCT_XMM_REG __fpu_xmm8; - _STRUCT_XMM_REG __fpu_xmm9; - _STRUCT_XMM_REG __fpu_xmm10; - _STRUCT_XMM_REG __fpu_xmm11; - _STRUCT_XMM_REG __fpu_xmm12; - _STRUCT_XMM_REG __fpu_xmm13; - _STRUCT_XMM_REG __fpu_xmm14; - _STRUCT_XMM_REG __fpu_xmm15; - - _STRUCT_XMM_REG __fpu_ymmh0; - _STRUCT_XMM_REG __fpu_ymmh1; - _STRUCT_XMM_REG __fpu_ymmh2; - _STRUCT_XMM_REG __fpu_ymmh3; - _STRUCT_XMM_REG __fpu_ymmh4; - _STRUCT_XMM_REG __fpu_ymmh5; - _STRUCT_XMM_REG __fpu_ymmh6; - _STRUCT_XMM_REG __fpu_ymmh7; - _STRUCT_XMM_REG __fpu_ymmh8; - _STRUCT_XMM_REG __fpu_ymmh9; - _STRUCT_XMM_REG __fpu_ymmh10; - _STRUCT_XMM_REG __fpu_ymmh11; - _STRUCT_XMM_REG __fpu_ymmh12; - _STRUCT_XMM_REG __fpu_ymmh13; - _STRUCT_XMM_REG __fpu_ymmh14; - _STRUCT_XMM_REG __fpu_ymmh15; -}; - -//-------------------------------------------------------------------------- -struct machine_debug_state_t -{ - ea_t __dr0; - ea_t __dr1; - ea_t __dr2; - ea_t __dr3; - ea_t __dr4; - ea_t __dr5; - ea_t __dr6; - ea_t __dr7; -}; - -//-------------------------------------------------------------------------- -class mac_debmod_t: public macbase_debmod_t -{ - typedef macbase_debmod_t inherited; -public: - procinfo_vec_t processes; - - // debugged process information - mach_port_t task; // debugged application's task port - - cpu_type_t cputype; // process' CPU type (e.g. CPU_TYPE_I386 or CPU_TYPE_X86_64) - - bool in_ptrace; // We use ptrace to start the debugging session - // but since it is badly broken, we detach and - // revert to low-level mach api immediately after that - - run_state_t run_state; - - dyld_utils_t dyld; - - image_info_t exeimg; // image info for the exe module - - images_t dlls; // list of loaded dynamic libraries - - easet_t dlls_to_import; // list of dlls to import information from - - inline bool exited(void) - { - return run_state == rs_exited; - } - - threads_t threads; - - struct stored_signal_t - { - pid_t pid; - int status; - }; - typedef qvector stored_signals_t; - static stored_signals_t pending_signals; // signals retrieved by other threads - - bool attaching; // Handling events linked to PTRACE_ATTACH, don't run the program yet - bool is64; // is target 64-bit? - - mach_port_t exc_port; - mach_exception_port_info_t saved_exceptions; - - regctx_t *reg_ctx; - - mac_debmod_t(); - ~mac_debmod_t(); - - void init_reg_ctx(void); - void term_reg_ctx(void); - - void handle_dyld_bpt(const debug_event_t *event); - bool retrieve_pending_signal(int *status); - kern_return_t read_mem(ea_t ea, void *buffer, int size, int *read_size); - void unblock_all_threads(); - void resume_all_threads(); - bool suspend_all_threads(); - bool my_resume_thread(ida_thread_info_t &ti); - pid_t qwait(int *status, bool hang); - void get_debug_events(int timeout_ms); - kern_return_t - catch_exception_raise(mach_port_t exception_port, - mach_port_t thread, - mach_port_t task, - exception_type_t exception, - exception_data_t code_vector, - mach_msg_type_number_t code_count); - ea_t get_ip(thid_t tid); - uval_t get_dr(thid_t tid, int idx); - bool set_dr(thid_t tid, int idx, uval_t value); - bool idaapi thread_get_fs_base(thid_t tid, int reg_idx, ea_t *pea); - bool parse_macho_image(macho_visitor_t &mv, const image_info_t &ii); - void clean_stack_regions(meminfo_vec_t &miv) const; - drc_t get_memory_info(meminfo_vec_t &miv, bool suspend); - void init_dyld(void); - void init_exeimg(pid_t _pid, thid_t tid); - void update_dyld(void); - bool exist_dll(const images_t &images, ea_t base); - virtual bool refresh_hwbpts() override; - virtual bool set_hwbpts(int hThread) newapi; - bool handle_process_start(pid_t _pid); - void term_exception_ports(void); - void init_exception_ports(void); - thid_t init_main_thread(bool reattaching); - bool update_threads(void); - bool thread_exit_event_planned(thid_t tid); - void cleanup(void); - bool xfer_memory(ea_t ea, void *buffer, int size, bool write); - void add_dll(const image_info_t &ii); - int _write_memory(ea_t ea, const void *buffer, int size, bool suspend=false); - int _read_memory(ea_t ea, void *buffer, int size, bool suspend=false); - bool xfer_page(ea_t ea, void *buffer, int size, bool write); - kern_return_t write_mem(ea_t ea, void *buffer, int size); - int exception_to_signal(const mach_exception_info_t *exinf); - bool check_for_exception(int timeout, mach_exception_info_t *exinf); - bool handle_signal( - int code, - debug_event_t *event, - block_type_t block, - const my_mach_msg_t *excmsg); - bool check_for_exception( - int timeout, - mach_exception_info_t *exinf, - my_mach_msg_t *excmsg); - bool is_task_valid(task_t task); - int32 qptrace(int request, pid_t pid, caddr_t addr, int data); - ida_thread_info_t *get_thread(thid_t tid); - int handle_bpts(debug_event_t *event, bool asked_step); - - //-------------------------------------------------------------------------- - #define DEFINE_GET_STATE_FUNC(name, type, flavor, flavor_count) \ - bool name(thid_t tid, type *state) \ - { \ - ida_thread_info_t *ti = get_thread(tid); \ - if ( ti == NULL ) \ - return false; \ - mach_port_t port = ti->port; \ - mach_msg_type_number_t stateCount = flavor_count; \ - kern_return_t err; \ - err = thread_get_state(port, \ - flavor, \ - (thread_state_t)state, \ - &stateCount); \ - QASSERT(30105, stateCount == flavor_count); \ - if ( err != KERN_SUCCESS ) \ - { \ - debdeb("tid=%d port=%d: " #name ": %s\n", tid, port, mach_error_string(err)); \ - return false; \ - } \ - return true; \ - } - - #define DEFINE_SET_STATE_FUNC(name, type, flavor, flavor_count) \ - bool name(thid_t tid, const type *state) \ - { \ - ida_thread_info_t *ti = get_thread(tid); \ - if ( ti == NULL ) \ - return false; \ - mach_port_t port = ti->port; \ - mach_msg_type_number_t stateCount = flavor_count; \ - kern_return_t err; \ - err = thread_set_state(port, \ - flavor, \ - (thread_state_t)state, \ - stateCount); \ - QASSERT(30106, stateCount == flavor_count); \ - return err == KERN_SUCCESS; \ - } - - DEFINE_GET_STATE_FUNC(get_thread_state64, x86_thread_state64_t, x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT) - DEFINE_SET_STATE_FUNC(set_thread_state64, x86_thread_state64_t, x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT) - DEFINE_GET_STATE_FUNC(get_thread_state32, x86_thread_state32_t, x86_THREAD_STATE32, x86_THREAD_STATE32_COUNT) - DEFINE_SET_STATE_FUNC(set_thread_state32, x86_thread_state32_t, x86_THREAD_STATE32, x86_THREAD_STATE32_COUNT) - DEFINE_GET_STATE_FUNC(get_float_state64, x86_avx_state64_t, x86_AVX_STATE64, x86_AVX_STATE64_COUNT) - DEFINE_SET_STATE_FUNC(set_float_state64, x86_avx_state64_t, x86_AVX_STATE64, x86_AVX_STATE64_COUNT) - DEFINE_GET_STATE_FUNC(get_float_state32, x86_avx_state32_t, x86_AVX_STATE32, x86_AVX_STATE32_COUNT) - DEFINE_SET_STATE_FUNC(set_float_state32, x86_avx_state32_t, x86_AVX_STATE32, x86_AVX_STATE32_COUNT) - DEFINE_GET_STATE_FUNC(get_debug_state64, x86_debug_state64_t, x86_DEBUG_STATE64, x86_DEBUG_STATE64_COUNT) - DEFINE_SET_STATE_FUNC(set_debug_state64, x86_debug_state64_t, x86_DEBUG_STATE64, x86_DEBUG_STATE64_COUNT) - DEFINE_GET_STATE_FUNC(get_debug_state32, x86_debug_state32_t, x86_DEBUG_STATE32, x86_DEBUG_STATE32_COUNT) - DEFINE_SET_STATE_FUNC(set_debug_state32, x86_debug_state32_t, x86_DEBUG_STATE32, x86_DEBUG_STATE32_COUNT) - - bool get_thread_state(thid_t tid, machine_thread_state_t *state); - bool set_thread_state(thid_t tid, const machine_thread_state_t *state); - bool get_float_state(thid_t tid, machine_float_state_t *state); - bool set_float_state(thid_t tid, const machine_float_state_t *state); - bool get_debug_state(thid_t tid, machine_debug_state_t *state); - bool set_debug_state(thid_t tid, const machine_debug_state_t *state); - - bool qthread_setsinglestep(ida_thread_info_t &ti); - - bool patch_reg_context( - machine_thread_state_t *cpu, - machine_float_state_t *fpu, - int reg_idx, - const regval_t *value) const; - - //-------------------------------------------------------------------------- - inline thid_t maintid(void) - { - return threads.begin()->first; - } - - void create_process_start_event(pid_t pid, thid_t tid); - void create_process_attach_event(pid_t pid); - - // - virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; - virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; - virtual void idaapi dbg_term(void) override; - virtual drc_t idaapi dbg_detach_process(void) override; - virtual drc_t idaapi dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) override; - virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; - virtual drc_t idaapi dbg_attach_process( - pid_t process_id, - int event_id, - int flags, - qstring *errbuf) override; - virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; - virtual void idaapi dbg_stopped_at_debug_event( - import_infos_t *infos, - bool dlls_added, - thread_name_vec_t *thr_names) override; - virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; - virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; - virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; - virtual drc_t idaapi dbg_read_registers( - thid_t thread_id, - int clsmask, - regval_t *values, - qstring *errbuf) override; - virtual drc_t idaapi dbg_write_register( - thid_t thread_id, - int reg_idx, - const regval_t *value, - qstring *errbuf) override; - virtual drc_t idaapi dbg_thread_get_sreg_base( - ea_t *ea, - thid_t thread_id, - int sreg_value, - qstring *errbuf) override; - virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &miv, qstring *errbuf) override; - virtual int idaapi dbg_get_scattered_image(scattered_image_t &sci, ea_t base) override; - virtual bool idaapi dbg_get_image_uuid(bytevec_t *uuid, ea_t base) override; - virtual ea_t idaapi dbg_get_segm_start(ea_t base, const qstring &segname) override; - virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; - virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; - virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; - virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; - virtual bool idaapi write_registers( - thid_t tid, - int start, - int count, - const regval_t *values) override; - - virtual int dbg_freeze_threads_except(thid_t tid) override; - virtual int dbg_thaw_threads_except(thid_t tid) override; - - virtual bool idaapi dbg_continue_broken_connection(pid_t pid) override; - virtual bool idaapi dbg_prepare_broken_connection(void) override; - - void get_image_meminfo(meminfo_vec_t &out, const image_info_t &ii); - - int get_task_suspend_count(void); - - int visit_vm_regions(vm_region_visitor_t &rv); - - static bool acquire_taskport_right(); - static bool verify_code_signature(); - static bool verify_user_privilege(); - - bool import_symbols(const image_info_t &ii); - - virtual bool import_dll(const import_request_t &req) override; - - bool get_image_info(image_info_t *ii, ea_t base) const; -}; - -#endif diff --git a/idasdk75/dbg/mac/mac_debug.plist b/idasdk75/dbg/mac/mac_debug.plist deleted file mode 100644 index 068eef7..0000000 --- a/idasdk75/dbg/mac/mac_debug.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleGetInfoString - OS X Remote Debug Server (32-bit) for IDA, Copyright (c) 2015 Hex-Rays SA - CFBundleExecutable - mac_server - CFBundleIdentifier - com.hexrays.mac_server - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - mac_server - CFBundleVersion - 1.0 - SecTaskAccess - - allowed - debug - safe - - - diff --git a/idasdk75/dbg/mac/mac_debug64.plist b/idasdk75/dbg/mac/mac_debug64.plist deleted file mode 100644 index e22974f..0000000 --- a/idasdk75/dbg/mac/mac_debug64.plist +++ /dev/null @@ -1,25 +0,0 @@ - - - - - CFBundleDevelopmentRegion - English - CFBundleGetInfoString - OS X Remote Debug Server (64-bit) for IDA, Copyright (c) 2015 Hex-Rays SA - CFBundleExecutable - mac_server64 - CFBundleIdentifier - com.hexrays.mac_serverx64 - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - mac_serverx64 - CFBundleVersion - 1.0 - SecTaskAccess - - allowed - debug - - - diff --git a/idasdk75/dbg/mac/mac_local_impl.cpp b/idasdk75/dbg/mac/mac_local_impl.cpp deleted file mode 100644 index 87e3af8..0000000 --- a/idasdk75/dbg/mac/mac_local_impl.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#include - -#include "macho_rebase.cpp" - -//-------------------------------------------------------------------------- -// installs or uninstalls debugger specific idc functions -inline bool register_idc_funcs(bool) -{ - return true; -} - -//-------------------------------------------------------------------------- -void idaapi rebase_if_required_to(ea_t new_base) -{ - // not a shared cache lib: it's safe to just use the imagebase - ea_t base = get_imagebase(); - if ( base == 0 ) - { - // old databases don't have it set; use info from netnode - netnode n(MACHO_NODE); - if ( exist(n) ) - base = n.altval(MACHO_ALT_IMAGEBASE); - } - - if ( base != BADADDR - && new_base != BADADDR - && base != new_base - && !rebase_scattered_segments(new_base) ) - { - rebase_or_warn(base, new_base); - } -} - -//-------------------------------------------------------------------------- -enum macopt_idx_t -{ - MAC_OPT_SYMBOL_PATH // path to symbols extracted from dyld shared cache -}; - -//-------------------------------------------------------------------------- -struct mac_cfgopt_t -{ - const char *name; - char type; - char index; - void *var; - size_t size; -}; - -//lint -esym(843, g_must_save_cfg) could be declared as const -static bool g_must_save_cfg = false; - -//-------------------------------------------------------------------------- -static const mac_cfgopt_t g_cfgopts[] = -{ - { "SYMBOL_PATH", IDPOPT_STR, MAC_OPT_SYMBOL_PATH, &g_dbgmod.dyld.symbol_path, 0 }, -}; -CASSERT(IS_QSTRING(g_dbgmod.dyld.symbol_path)); - -//-------------------------------------------------------------------------- -static const mac_cfgopt_t *find_option(const char *name) -{ - for ( int i=0; i < qnumber(g_cfgopts); i++ ) - if ( strcmp(g_cfgopts[i].name, name) == 0 ) - return &g_cfgopts[i]; - return NULL; -} - -//-------------------------------------------------------------------------- -static void load_mac_options() -{ - if ( !netnode::inited() ) - return; - - netnode node(MAC_NODE); - if ( !exist(node) ) - return; - - for ( int i = 0; i < qnumber(g_cfgopts); i++ ) - { - const mac_cfgopt_t &opt = g_cfgopts[i]; - if ( opt.type == IDPOPT_STR ) - node.supstr((qstring *)opt.var, opt.index); - else - node.supval(opt.index, opt.var, opt.size); - } -} - -//-------------------------------------------------------------------------- -static void save_mac_options() -{ - if ( !g_must_save_cfg || !netnode::inited() ) - return; - - netnode node; - node.create(MAC_NODE); - if ( node != BADNODE ) - { - for ( int i = 0; i < qnumber(g_cfgopts); i++ ) - { - const mac_cfgopt_t &opt = g_cfgopts[i]; - if ( opt.type == IDPOPT_STR ) - node.supset(opt.index, ((qstring *)opt.var)->c_str(), 0); - else - node.supset(opt.index, opt.var, opt.size); - } - } - - g_must_save_cfg = false; -} - -//-------------------------------------------------------------------------- -const char *idaapi set_mac_options(const char *keyword, int pri, int value_type, const void *value) -{ - if ( keyword == NULL ) - { - static const char form[] = - "Mac OSX Debugger Options\n%/" - "<#Path to symbol files extracted from dyld_shared_cache#~S~ymbol path:q:1023:60::>\n"; - - qstring path = g_dbgmod.dyld.symbol_path; - if ( !ask_form(form, NULL, &path) ) - return IDPOPT_OK; - - g_dbgmod.dyld.symbol_path = path; - g_must_save_cfg = true; - } - else - { - if ( *keyword == '\0' ) - { - load_mac_options(); - return IDPOPT_OK; - } - - const mac_cfgopt_t *opt = find_option(keyword); - if ( opt == NULL ) - return IDPOPT_BADKEY; - if ( opt->type != value_type ) - return IDPOPT_BADTYPE; - - if ( opt->type == IDPOPT_STR ) - { - qstring *pvar = (qstring *)opt->var; - *pvar = (char *)value; - } - - if ( pri == IDPOPT_PRI_HIGH ) - g_must_save_cfg = true; - } - - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -static ssize_t idaapi ui_callback(void *, int notification_code, va_list) -{ - if ( notification_code == ui_saving ) - save_mac_options(); - return 0; -} - -//-------------------------------------------------------------------------- -static bool init_plugin(void) -{ -#ifndef RPC_CLIENT - if ( !init_subsystem() ) - return false; -#endif - - if ( !netnode::inited() || is_miniidb() || inf_is_snapshot() ) - { -#ifdef __MAC__ - // local debugger is available if we are running under MAC OS X - return true; -#else - // for other systems only the remote debugger is available - return debugger.is_remote(); -#endif - } - - if ( inf_get_filetype() != S_FILETYPE ) // only Mach-O files - return false; - processor_t &ph = PH; - if ( ph.id != TARGET_PROCESSOR && ph.id != -1 ) - return false; - - hook_to_notification_point(HT_UI, ui_callback); - return true; -} - -//-------------------------------------------------------------------------- -inline void term_plugin(void) -{ -#ifndef RPC_CLIENT - term_subsystem(); -#endif - unhook_from_notification_point(HT_UI, ui_callback); - save_mac_options(); -} - -//-------------------------------------------------------------------------- -static const char comment[] = "Userland Mac OS X debugger plugin."; diff --git a/idasdk75/dbg/mac/mac_stub.cpp b/idasdk75/dbg/mac/mac_stub.cpp deleted file mode 100644 index 97bb1af..0000000 --- a/idasdk75/dbg/mac/mac_stub.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/* - This is the MAC OS X x86 user land debugger entry point file -*/ -#ifndef __GNUC__ -//lint -esym(750, __LITTLE_ENDIAN__) not referenced -#define __LITTLE_ENDIAN__ -#endif -//#define __inline__ inline -#define REMOTE_DEBUGGER -#define RPC_CLIENT - -static const char wanted_name[] = "Remote Mac OS X debugger"; -#define DEBUGGER_NAME "macosx" -#define PROCESSOR_NAME "metapc" -#define DEFAULT_PLATFORM_NAME "macosx" -#define TARGET_PROCESSOR PLFM_386 -#define DEBUGGER_ID DEBUGGER_ID_X86_IA32_MACOSX_USER -#define DEBUGGER_FLAGS (DBG_FLAG_REMOTE \ - | DBG_FLAG_LOWCNDS \ - | DBG_FLAG_DEBTHREAD) -#define DEBUGGER_RESMOD (DBG_RESMOD_STEP_INTO) -#define HAVE_APPCALL -#define S_FILETYPE f_MACHO -#define SET_DBG_OPTIONS set_mac_options -#define MAC_NODE "$ remote mac options" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dbg_rpc_client.h" -#include "rpc_debmod.h" -#include "symmacho.hpp" - -class rstub_debmod_t : public rpc_debmod_t -{ - typedef rpc_debmod_t inherited; - -public: - dyld_utils_t dyld; - - rstub_debmod_t() : inherited(DEFAULT_PLATFORM_NAME), dyld(this, TARGET_PROCESSOR) {} - - // handle an RPC_IMPORT_DLL request from the server. see SYMBOL_PATH in dbg_macosx.cfg. - virtual bool import_dll(const import_request_t &req) override - { - dyld.update_bitness(); - struct ida_local dll_importer_t : public macho_visitor_t - { - dll_importer_t() : macho_visitor_t(MV_SYMBOLS) {} - void visit_symbol(ea_t ea, const char *name) override - { - set_debug_name(ea, name); - } - }; - dll_importer_t di; - return dyld.parse_local_symbol_file(req.base, req.path.c_str(), req.uuid, di); - } -}; - -rstub_debmod_t g_dbgmod; -#include "common_stub_impl.cpp" - -#include "pc_local_impl.cpp" -#include "mac_local_impl.cpp" -#include "common_local_impl.cpp" diff --git a/idasdk75/dbg/mac/mac_user.cpp b/idasdk75/dbg/mac/mac_user.cpp deleted file mode 100644 index 8073ceb..0000000 --- a/idasdk75/dbg/mac/mac_user.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -This is the MAC user land local debugger entry point file -It declares a MAC debugger module and uses the common plugin functions to build the debugger -*/ - -static const char wanted_name[] = "Local Mac OS X debugger"; -#define DEBUGGER_NAME "macosx" -#define PROCESSOR_NAME "metapc" -#define TARGET_PROCESSOR PLFM_386 -#define DEBUGGER_ID DEBUGGER_ID_X86_IA32_MACOSX_USER -#define DEBUGGER_FLAGS (DBG_FLAG_LOWCNDS \ - | DBG_FLAG_DEBTHREAD) -#define DEBUGGER_RESMOD (DBG_RESMOD_STEP_INTO) -#define HAVE_APPCALL -#define S_FILETYPE f_MACHO -#define SET_DBG_OPTIONS set_mac_options -#define MAC_NODE "$ local mac options" - -#include -#include -#include -#include -#include -#include "mac_debmod.h" - -mac_debmod_t g_dbgmod; -#include "common_stub_impl.cpp" - -#include "pc_local_impl.cpp" -#include "mac_local_impl.cpp" -#include "common_local_impl.cpp" diff --git a/idasdk75/dbg/mac/macbase_debmod.cpp b/idasdk75/dbg/mac/macbase_debmod.cpp deleted file mode 100644 index 5294805..0000000 --- a/idasdk75/dbg/mac/macbase_debmod.cpp +++ /dev/null @@ -1,164 +0,0 @@ -#undef processor_t -#define processor_t mach_processor_t -#include -#include -#undef processor_t - -#include -#include -#include -#include "macbase_debmod.h" - -//-------------------------------------------------------------------------- -inline const char *str_bitness(int bitness) -{ - switch ( bitness ) - { - case 8: - return "[64]"; - case 4: - return "[32]"; - default: - return "[?]"; - } -} - -//-------------------------------------------------------------------------- -cpu_type_t macbase_debmod_t::get_process_cpu(pid_t _pid) const -{ - int mib[CTL_MAXNAME]; - size_t mibLen = CTL_MAXNAME; - int err = sysctlnametomib("sysctl.proc_cputype", mib, &mibLen); - if ( err == 0 ) - { - QASSERT(895, mibLen < CTL_MAXNAME); - mib[mibLen] = _pid; - mibLen += 1; - cpu_type_t cpu_type; - size_t cpuTypeSize = sizeof(cpu_type); - err = sysctl(mib, mibLen, &cpu_type, &cpuTypeSize, 0, 0); - if ( err == 0 ) - return cpu_type; - } - msg("error from sysctl: %s\n", strerror(errno)); - return 0; -} - -//-------------------------------------------------------------------------- -static void build_process_ext_name(ext_process_info_t *pinfo) -{ - pinfo->ext_name = str_bitness(pinfo->addrsize); - pinfo->ext_name.append(' '); - pinfo->ext_name.append(pinfo->name); -} - -//-------------------------------------------------------------------------- -// Returns the file name assciated with pid -bool idaapi macbase_debmod_t::get_exec_fname( - int _pid, - char *buf, - size_t bufsize) -{ - int mib[3]; - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - int argmax = 0; - size_t size = sizeof(argmax); - - sysctl(mib, 2, &argmax, &size, NULL, 0); - if ( argmax <= 0 ) - argmax = QMAXPATH; - - char *args = (char *)qalloc(argmax); - if ( args == NULL ) - nomem("get_exec_fname"); - - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = _pid; - - // obtain the arguments for the target process. this will - // only work for processes that belong to the current uid, - // so if you want it to work universally, you need to run - // as root. - size = argmax; - buf[0] = '\0'; - if ( sysctl(mib, 3, args, &size, NULL, 0) != -1 ) - { - char *ptr = args + sizeof(int); -// show_hex(ptr, size, "procargs2\n"); - - qstrncpy(buf, ptr, bufsize); - } - qfree(args); - return true; -} - -//-------------------------------------------------------------------------- -// Get process bitness: 32bit - 4, 64bit - 8, 0 - unknown -int idaapi macbase_debmod_t::get_process_bitness(int _pid) -{ - return get_cpu_bitness(get_process_cpu(_pid)); -} - -//-------------------------------------------------------------------------- -int idaapi macbase_debmod_t::get_process_list(procvec_t *list, qstring *) -{ - list->clear(); - int mypid = getpid(); - int sysControl[4]; - sysControl[0] = CTL_KERN; - sysControl[1] = KERN_PROC; - sysControl[2] = KERN_PROC_ALL; - - qvector info; - size_t length; - int count = 0; - int rc = -1; - for ( int tries=0; rc != 0 && tries < 5; ++tries ) - { - // the first call of sysctl() is used to determine the size of the buffer - // will be passed to the second call - length = 0; - sysctl(sysControl, 3, NULL, &length, NULL, 0); - - // If the number of processes is greater than the size of the buffer - // sysctl() supplies as much data as fits in the buffer and returns ENOMEM. - // We reserve 100 extra elements for processes started after 1st sysctl - // In case even this number is not sufficient we turn to the next attempt - count = (length / sizeof (info[0])) + 100; - if ( count <= 0 ) //-V547 is always false. - return 0; - if ( info.size() < count ) - info.resize(count); - length = sizeof(info[0]) * info.size(); - rc = sysctl(sysControl, 3, info.begin(), &length, NULL, 0); - if ( rc != 0 && errno != ENOMEM ) - return 0; - } - - count = (length / sizeof (info[0])); // exact number of processes - for ( int i=0; i < count; i++ ) - { - extern_proc &ep = info[i].kp_proc; - pid_t _pid = ep.p_pid; - if ( _pid == mypid ) - continue; - mach_port_t port; - kern_return_t result = task_for_pid(mach_task_self(), _pid, &port); - if ( result == KERN_SUCCESS ) - { - ext_process_info_t &pi = list->push_back(); - pi.name = ep.p_comm; - pi.pid = _pid; - pi.addrsize = get_process_bitness(_pid); - build_process_ext_name(&pi); - } - else - { - debdeb("%d: %s is unavailable for debugging\n", _pid, info[i].kp_proc.p_comm); - } - } - return list->size(); -} diff --git a/idasdk75/dbg/mac/macbase_debmod.h b/idasdk75/dbg/mac/macbase_debmod.h deleted file mode 100644 index ce1ed5a..0000000 --- a/idasdk75/dbg/mac/macbase_debmod.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef __MACBASE_HPP__ -#define __MACBASE_HPP__ - -#include "debmod.h" - -#include "pc_debmod.h" -#define BASE_DEBUGGER_MODULE pc_debmod_t - -#ifndef __LINUX__ // linux gcc cannot compile macho-o headers -#include "symmacho.hpp" -#endif - -// avoid conflicts with audit.h: -#define token_t __mac_token_t -#include -#include -#undef token_t - -class macbase_debmod_t: public BASE_DEBUGGER_MODULE -{ - typedef BASE_DEBUGGER_MODULE inherited; - -protected: - // return number of processes, -1 - not implemented - virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf) override; - // return the file name assciated with pid - virtual bool idaapi get_exec_fname(int pid, char *buf, size_t bufsize) newapi; - // get process bitness: 32bit - 4, 64bit - 8, 0 - unknown - virtual int idaapi get_process_bitness(int pid) newapi; - - cpu_type_t get_process_cpu(pid_t pid) const; - inline int idaapi get_cpu_bitness(cpu_type_t cpu); -}; - -//-------------------------------------------------------------------------- -inline int idaapi macbase_debmod_t::get_cpu_bitness(cpu_type_t cpu) -{ - return (cpu & CPU_ARCH_ABI64) != 0 ? 8 : 4; -} - -#endif diff --git a/idasdk75/dbg/mac/makefile b/idasdk75/dbg/mac/makefile deleted file mode 100644 index fab1b5b..0000000 --- a/idasdk75/dbg/mac/makefile +++ /dev/null @@ -1,350 +0,0 @@ -include ../../allmake.mak - -GOALS-$(BUILD_IDA) += configs # target in $(IDA)module.mak -GOALS-$(BUILD_IDA) += modules # target in $(IDA)module.mak -GOALS-$(BUILD_DBGSRV) += server # target in $(IDA)dbg/server.mak -.PHONY: $(GOALS-1) -all: $(GOALS-1) - -#---------------------------------------------------------------------- -ifdef __MAC__ - SERVER = mac_server$(B) -endif -ifdef SERVER - SERVERS += $(call server_exe,$(SERVER)) -endif - -#---------------------------------------------------------------------- -STUB = $(call module_dll,mac_stub) -ifdef BUILD_IDA - MODULES += $(STUB) -endif - -#---------------------------------------------------------------------- -USER = $(call module_dll,mac_user) -ifeq ($(and $(BUILD_IDA),$(__MAC__)),1) - MODULES += $(USER) - CONFIGS += dbg_macosx.cfg -endif - -#---------------------------------------------------------------------- -# we explicitly added our module targets -NO_DEFAULT_TARGETS = 1 - -# NOTE: all MODULES must be defined before including plugin.mak. -include ../plugin.mak -# NOTE: target-specific rules and dependencies that use variable -# expansion to name the target (such as "$(MODULE): [...]") must -# come after including plugin.mak - -#---------------------------------------------------------------------- -# select OBJS common to user plugin and debugger server -BASE_OBJS-$(__MAC__) += $(F)macbase_debmod$(O) -BASE_OBJS-$(__MAC__) += $(F)mac_debmod$(O) -BASE_OBJS-$(__MAC__) += $(F)excServer$(O) - -BASE_OBJS += $(BASE_OBJS-1) $(F)symmacho$(O) - -$(F)symmacho$(O): CC_INCP += ../../ldr/mach-o/h $(IRRXML) -$(F)mac_debmod$(O): CC_INCP += ../../ldr/mach-o/h - -excServer.c: - mig $(MACSDK)/usr/include/mach/exc.defs -ifdef __LINT__ -$(F)excServer$(O): - touch $@ -endif - -#---------------------------------------------------------------------- -SERVER_LDFLAGS += $(OUTMAP)$(F)$(@F).map -SERVER_LDFLAGS += -Wl,-sectcreate,__TEXT,__info_plist,mac_debug$(B).plist - -SERVER_STDLIBS += -framework CoreFoundation -SERVER_STDLIBS += -framework Security - -# NOTE: perform the steps in mac_server_certificate.txt before using CODESIGN_MAC_SERVER! -ifdef CODESIGN_MAC_SERVER - CODESIGN_IDENTITY ?= mac_server - ifdef MAC_KEYCHAIN - CODESIGN_OPTS = --keychain $(MAC_KEYCHAIN).keychain - endif - ifdef MAC_TIMESTAMP - CODESIGN_OPTS += --timestamp=$(MAC_TIMESTAMP) - endif - ifndef __CODE_CHECKER__ - SERVER_POSTACTION = $(strip codesign $(CODESIGN_OPTS) -s "$(CODESIGN_IDENTITY)" $@) - endif -endif -SERVER_OBJS += $(BASE_OBJS) - -include ../server.mak - -#---------------------------------------------------------------------- -STUB_OBJS += $(F)mac_stub$(O) -STUB_OBJS += $(F)symmacho$(O) -$(STUB): MODULE_OBJS += $(STUB_OBJS) -$(STUB): $(STUB_OBJS) - -#---------------------------------------------------------------------- -USER_OBJS += $(F)mac_user$(O) -USER_OBJS += $(BASE_OBJS) -$(USER): MODULE_OBJS += $(USER_OBJS) -$(USER): $(USER_OBJS) -$(USER): STDLIBS += -framework Security -$(USER): STDLIBS += -framework CoreFoundation - -#---------------------------------------------------------------------- -include $(IDA)objdir.mak - -# MAKEDEP dependency list ------------------ -$(F)excServer$(O): ../../ldr/mach-o/h/arm/_types.h \ - ../../ldr/mach-o/h/i386/_types.h \ - ../../ldr/mach-o/h/mach/arm/boolean.h \ - ../../ldr/mach-o/h/mach/arm/vm_types.h \ - ../../ldr/mach-o/h/mach/boolean.h \ - ../../ldr/mach-o/h/mach/i386/boolean.h \ - ../../ldr/mach-o/h/mach/i386/kern_return.h \ - ../../ldr/mach-o/h/mach/i386/vm_param.h \ - ../../ldr/mach-o/h/mach/i386/vm_types.h \ - ../../ldr/mach-o/h/mach/kern_return.h \ - ../../ldr/mach-o/h/mach/machine/boolean.h \ - ../../ldr/mach-o/h/mach/machine/kern_return.h \ - ../../ldr/mach-o/h/mach/machine/vm_types.h \ - ../../ldr/mach-o/h/mach/message.h \ - ../../ldr/mach-o/h/mach/port.h \ - ../../ldr/mach-o/h/mach/ppc/boolean.h \ - ../../ldr/mach-o/h/mach/ppc/kern_return.h \ - ../../ldr/mach-o/h/mach/ppc/vm_param.h \ - ../../ldr/mach-o/h/mach/ppc/vm_types.h \ - ../../ldr/mach-o/h/ppc/_types.h \ - ../../ldr/mach-o/h/sys/_posix_availability.h \ - ../../ldr/mach-o/h/sys/_symbol_aliasing.h \ - ../../ldr/mach-o/h/sys/cdefs.h excServer.c -$(F)mac_debmod$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)diskio.hpp $(I)err.h $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)network.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/mach-o/common.h \ - ../../ldr/mach-o/h/architecture/byte_order.h \ - ../../ldr/mach-o/h/arm/_types.h \ - ../../ldr/mach-o/h/i386/_types.h \ - ../../ldr/mach-o/h/i386/eflags.h \ - ../../ldr/mach-o/h/libkern/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/_OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/machine/OSByteOrder.h \ - ../../ldr/mach-o/h/mach-o/arm/reloc.h \ - ../../ldr/mach-o/h/mach-o/arm64/reloc.h \ - ../../ldr/mach-o/h/mach-o/fat.h \ - ../../ldr/mach-o/h/mach-o/hppa/reloc.h \ - ../../ldr/mach-o/h/mach-o/i860/reloc.h \ - ../../ldr/mach-o/h/mach-o/loader.h \ - ../../ldr/mach-o/h/mach-o/m88k/reloc.h \ - ../../ldr/mach-o/h/mach-o/nlist.h \ - ../../ldr/mach-o/h/mach-o/ppc/reloc.h \ - ../../ldr/mach-o/h/mach-o/reloc.h \ - ../../ldr/mach-o/h/mach-o/sparc/reloc.h \ - ../../ldr/mach-o/h/mach-o/stab.h \ - ../../ldr/mach-o/h/mach-o/x86_64/reloc.h \ - ../../ldr/mach-o/h/mach/arm/_structs.h \ - ../../ldr/mach-o/h/mach/arm/boolean.h \ - ../../ldr/mach-o/h/mach/arm/thread_state.h \ - ../../ldr/mach-o/h/mach/arm/thread_status.h \ - ../../ldr/mach-o/h/mach/arm/vm_types.h \ - ../../ldr/mach-o/h/mach/boolean.h \ - ../../ldr/mach-o/h/mach/i386/_structs.h \ - ../../ldr/mach-o/h/mach/i386/boolean.h \ - ../../ldr/mach-o/h/mach/i386/fp_reg.h \ - ../../ldr/mach-o/h/mach/i386/kern_return.h \ - ../../ldr/mach-o/h/mach/i386/thread_state.h \ - ../../ldr/mach-o/h/mach/i386/thread_status.h \ - ../../ldr/mach-o/h/mach/i386/vm_param.h \ - ../../ldr/mach-o/h/mach/i386/vm_types.h \ - ../../ldr/mach-o/h/mach/kern_return.h \ - ../../ldr/mach-o/h/mach/machine.h \ - ../../ldr/mach-o/h/mach/machine/boolean.h \ - ../../ldr/mach-o/h/mach/machine/kern_return.h \ - ../../ldr/mach-o/h/mach/machine/thread_status.h \ - ../../ldr/mach-o/h/mach/machine/vm_types.h \ - ../../ldr/mach-o/h/mach/message.h \ - ../../ldr/mach-o/h/mach/port.h \ - ../../ldr/mach-o/h/mach/ppc/_structs.h \ - ../../ldr/mach-o/h/mach/ppc/boolean.h \ - ../../ldr/mach-o/h/mach/ppc/kern_return.h \ - ../../ldr/mach-o/h/mach/ppc/thread_status.h \ - ../../ldr/mach-o/h/mach/ppc/vm_param.h \ - ../../ldr/mach-o/h/mach/ppc/vm_types.h \ - ../../ldr/mach-o/h/mach/shared_region.h \ - ../../ldr/mach-o/h/mach/vm_prot.h \ - ../../ldr/mach-o/h/mach/vm_types.h \ - ../../ldr/mach-o/h/ppc/_types.h \ - ../../ldr/mach-o/h/sys/_posix_availability.h \ - ../../ldr/mach-o/h/sys/_symbol_aliasing.h \ - ../../ldr/mach-o/h/sys/appleapiopts.h \ - ../../ldr/mach-o/h/sys/cdefs.h \ - ../../ldr/mach-o/h/sys/ptrace.h \ - ../../ldr/mach-o/macho_node.h ../deb_pc.hpp ../debmod.h \ - ../pc_debmod.h ../pc_regs.hpp mac_debmod.cpp \ - mac_debmod.h macbase_debmod.h symmacho.hpp -$(F)mac_stub$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/mach-o/macho_node.h ../common_local_impl.cpp \ - ../common_stub_impl.cpp ../dbg_rpc_client.h \ - ../dbg_rpc_engine.h ../deb_pc.hpp ../debmod.h \ - ../macho_rebase.cpp ../pc_local_impl.cpp ../pc_regs.hpp \ - ../rpc_debmod.h mac_local_impl.cpp mac_stub.cpp \ - symmacho.hpp -$(F)mac_user$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)diskio.hpp $(I)err.h $(I)expr.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/mach-o/h/architecture/byte_order.h \ - ../../ldr/mach-o/h/arm/_types.h \ - ../../ldr/mach-o/h/i386/_types.h \ - ../../ldr/mach-o/h/libkern/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/_OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/machine/OSByteOrder.h \ - ../../ldr/mach-o/h/mach-o/fat.h \ - ../../ldr/mach-o/h/mach-o/nlist.h \ - ../../ldr/mach-o/h/mach-o/reloc.h \ - ../../ldr/mach-o/h/mach/arm/boolean.h \ - ../../ldr/mach-o/h/mach/arm/vm_types.h \ - ../../ldr/mach-o/h/mach/boolean.h \ - ../../ldr/mach-o/h/mach/i386/boolean.h \ - ../../ldr/mach-o/h/mach/i386/vm_param.h \ - ../../ldr/mach-o/h/mach/i386/vm_types.h \ - ../../ldr/mach-o/h/mach/machine.h \ - ../../ldr/mach-o/h/mach/machine/boolean.h \ - ../../ldr/mach-o/h/mach/machine/vm_types.h \ - ../../ldr/mach-o/h/mach/port.h \ - ../../ldr/mach-o/h/mach/ppc/boolean.h \ - ../../ldr/mach-o/h/mach/ppc/vm_param.h \ - ../../ldr/mach-o/h/mach/ppc/vm_types.h \ - ../../ldr/mach-o/h/mach/shared_region.h \ - ../../ldr/mach-o/h/mach/vm_prot.h \ - ../../ldr/mach-o/h/mach/vm_types.h \ - ../../ldr/mach-o/h/ppc/_types.h \ - ../../ldr/mach-o/h/sys/_posix_availability.h \ - ../../ldr/mach-o/h/sys/_symbol_aliasing.h \ - ../../ldr/mach-o/h/sys/appleapiopts.h \ - ../../ldr/mach-o/h/sys/cdefs.h \ - ../../ldr/mach-o/h/sys/ptrace.h \ - ../../ldr/mach-o/macho_node.h ../common_local_impl.cpp \ - ../common_stub_impl.cpp ../deb_pc.hpp ../debmod.h \ - ../macho_rebase.cpp ../pc_debmod.h ../pc_local_impl.cpp \ - ../pc_regs.hpp mac_debmod.h mac_local_impl.cpp \ - mac_user.cpp macbase_debmod.h symmacho.hpp -$(F)macbase_debmod$(O): $(I)bytes.hpp $(I)diskio.hpp $(I)fpro.h \ - $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)prodir.h $(I)range.hpp \ - $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/mach-o/h/architecture/byte_order.h \ - ../../ldr/mach-o/h/arm/_types.h \ - ../../ldr/mach-o/h/i386/_types.h \ - ../../ldr/mach-o/h/libkern/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/_OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/machine/OSByteOrder.h \ - ../../ldr/mach-o/h/mach-o/fat.h \ - ../../ldr/mach-o/h/mach/arm/boolean.h \ - ../../ldr/mach-o/h/mach/arm/vm_types.h \ - ../../ldr/mach-o/h/mach/boolean.h \ - ../../ldr/mach-o/h/mach/i386/boolean.h \ - ../../ldr/mach-o/h/mach/i386/vm_param.h \ - ../../ldr/mach-o/h/mach/i386/vm_types.h \ - ../../ldr/mach-o/h/mach/machine.h \ - ../../ldr/mach-o/h/mach/machine/boolean.h \ - ../../ldr/mach-o/h/mach/machine/vm_types.h \ - ../../ldr/mach-o/h/mach/ppc/boolean.h \ - ../../ldr/mach-o/h/mach/ppc/vm_param.h \ - ../../ldr/mach-o/h/mach/ppc/vm_types.h \ - ../../ldr/mach-o/h/ppc/_types.h ../deb_pc.hpp \ - ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ - macbase_debmod.cpp macbase_debmod.h symmacho.hpp -$(F)symmacho$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)err.h \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)network.hpp \ - $(I)offset.hpp $(I)pro.h $(I)prodir.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - $(IRRXML)CXMLReaderImpl.h $(IRRXML)fast_atof.h \ - $(IRRXML)heapsort.h $(IRRXML)irrArray.h \ - $(IRRXML)irrString.h $(IRRXML)irrTypes.h \ - $(IRRXML)irrXML.h ../../ldr/ar/aixar.hpp \ - ../../ldr/ar/ar.hpp ../../ldr/ar/arcmn.cpp \ - ../../ldr/mach-o/../ar/ar.hpp \ - ../../ldr/mach-o/../idaldr.h ../../ldr/mach-o/base.cpp \ - ../../ldr/mach-o/common.cpp ../../ldr/mach-o/common.h \ - ../../ldr/mach-o/dsym.cpp ../../ldr/mach-o/dsym.h \ - ../../ldr/mach-o/h/architecture/byte_order.h \ - ../../ldr/mach-o/h/arm/_types.h \ - ../../ldr/mach-o/h/i386/_types.h \ - ../../ldr/mach-o/h/i386/eflags.h \ - ../../ldr/mach-o/h/libkern/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/i386/_OSByteOrder.h \ - ../../ldr/mach-o/h/libkern/machine/OSByteOrder.h \ - ../../ldr/mach-o/h/mach-o/arm/reloc.h \ - ../../ldr/mach-o/h/mach-o/arm64/reloc.h \ - ../../ldr/mach-o/h/mach-o/fat.h \ - ../../ldr/mach-o/h/mach-o/hppa/reloc.h \ - ../../ldr/mach-o/h/mach-o/i860/reloc.h \ - ../../ldr/mach-o/h/mach-o/loader.h \ - ../../ldr/mach-o/h/mach-o/m88k/reloc.h \ - ../../ldr/mach-o/h/mach-o/nlist.h \ - ../../ldr/mach-o/h/mach-o/ppc/reloc.h \ - ../../ldr/mach-o/h/mach-o/reloc.h \ - ../../ldr/mach-o/h/mach-o/sparc/reloc.h \ - ../../ldr/mach-o/h/mach-o/stab.h \ - ../../ldr/mach-o/h/mach-o/x86_64/reloc.h \ - ../../ldr/mach-o/h/mach/arm/_structs.h \ - ../../ldr/mach-o/h/mach/arm/boolean.h \ - ../../ldr/mach-o/h/mach/arm/thread_state.h \ - ../../ldr/mach-o/h/mach/arm/thread_status.h \ - ../../ldr/mach-o/h/mach/arm/vm_types.h \ - ../../ldr/mach-o/h/mach/boolean.h \ - ../../ldr/mach-o/h/mach/i386/_structs.h \ - ../../ldr/mach-o/h/mach/i386/boolean.h \ - ../../ldr/mach-o/h/mach/i386/fp_reg.h \ - ../../ldr/mach-o/h/mach/i386/kern_return.h \ - ../../ldr/mach-o/h/mach/i386/thread_state.h \ - ../../ldr/mach-o/h/mach/i386/thread_status.h \ - ../../ldr/mach-o/h/mach/i386/vm_param.h \ - ../../ldr/mach-o/h/mach/i386/vm_types.h \ - ../../ldr/mach-o/h/mach/kern_return.h \ - ../../ldr/mach-o/h/mach/kmod.h \ - ../../ldr/mach-o/h/mach/machine.h \ - ../../ldr/mach-o/h/mach/machine/boolean.h \ - ../../ldr/mach-o/h/mach/machine/kern_return.h \ - ../../ldr/mach-o/h/mach/machine/thread_status.h \ - ../../ldr/mach-o/h/mach/machine/vm_types.h \ - ../../ldr/mach-o/h/mach/message.h \ - ../../ldr/mach-o/h/mach/port.h \ - ../../ldr/mach-o/h/mach/ppc/_structs.h \ - ../../ldr/mach-o/h/mach/ppc/boolean.h \ - ../../ldr/mach-o/h/mach/ppc/kern_return.h \ - ../../ldr/mach-o/h/mach/ppc/thread_status.h \ - ../../ldr/mach-o/h/mach/ppc/vm_param.h \ - ../../ldr/mach-o/h/mach/ppc/vm_types.h \ - ../../ldr/mach-o/h/mach/vm_prot.h \ - ../../ldr/mach-o/h/mach/vm_types.h \ - ../../ldr/mach-o/h/ppc/_types.h \ - ../../ldr/mach-o/h/sys/_posix_availability.h \ - ../../ldr/mach-o/h/sys/_symbol_aliasing.h \ - ../../ldr/mach-o/h/sys/cdefs.h \ - ../../ldr/mach-o/macho_node.h ../debmod.h symmacho.cpp \ - symmacho.hpp diff --git a/idasdk75/dbg/mac/symmacho.cpp b/idasdk75/dbg/mac/symmacho.cpp deleted file mode 100644 index a36c0c4..0000000 --- a/idasdk75/dbg/mac/symmacho.cpp +++ /dev/null @@ -1,1142 +0,0 @@ -// read Mach-O symbols - -#include -#include -#include "debmod.h" -#include "../../ldr/ar/ar.hpp" -#include "../../ldr/ar/aixar.hpp" -#include "../../ldr/ar/arcmn.cpp" // for is_ar_file -#define BUILD_DEBUGGER -#include "../../ldr/mach-o/common.cpp" -#include "../../ldr/mach-o/dsym.cpp" -#include "symmacho.hpp" - -//-------------------------------------------------------------------------- -macho_utils_t::macho_utils_t(debmod_t *_dbgmod, int _arch) - : dbgmod(_dbgmod), - arch(_arch), - addrsize(DEF_ADDRSIZE), - is64(false), - warned(false) -{ -} - -//-------------------------------------------------------------------------- -void macho_utils_t::clear(void) -{ - addrsize = DEF_ADDRSIZE; - is64 = false; - warned = false; - strcache.clear(); -} - -//-------------------------------------------------------------------------- -int macho_utils_t::get_cputype(void) const -{ - switch ( arch ) - { - case PLFM_386: - return is64 ? CPU_TYPE_X86_64 : CPU_TYPE_I386; - case PLFM_ARM: - return is64 ? CPU_TYPE_ARM64 : CPU_TYPE_ARM; - default: - break; - } - return CPU_TYPE_ANY; -} - -//-------------------------------------------------------------------------- -size_t macho_utils_t::read_mem(ea_t ea, void *buf, size_t bufsize) -{ - return dbgmod->dbg_read_memory(ea, buf, bufsize, NULL); -} - -//-------------------------------------------------------------------------- -void macho_utils_t::update_bitness() -{ - debapp_attrs_t attrs; - dbgmod->dbg_get_debapp_attrs(&attrs); - addrsize = attrs.addrsize; - is64 = addrsize > 4; -} - -//-------------------------------------------------------------------------- -linput_t *macho_utils_t::create_mem_input(ea_t base) -{ - struct ida_local meminput_t : public generic_linput_t - { - ea_t base; - macho_utils_t *mu; - meminput_t(ea_t _base, macho_utils_t *_mu) : base(_base), mu(_mu) - { - // macho images in memory have indeterminate size. - // set it to the max possible size to keep anybody from complaining. - filesize = INT_MAX; - blocksize = 0; - } - virtual ssize_t idaapi read(qoff64_t off, void *buffer, size_t nbytes) override - { - return mu->read_mem(base+off, buffer, nbytes); - } - }; - meminput_t *pmi = new meminput_t(base, this); - return create_generic_linput(pmi); -} - -//-------------------------------------------------------------------------- -void macho_utils_t::get_ptr_value(ea_t *val, const uchar *buf) const -{ - if ( addrsize == 8 ) - *val = *(const uint64 *)buf; - else - *val = *(const uint32 *)buf; -} - -//-------------------------------------------------------------------------- -static void visit_macho_segments(macho_file_t &mfile, macho_visitor_t &mv) -{ - const segcmdvec_t &segcmds = mfile.get_segcmds(); - const secvec_t §ions = mfile.get_sections(); - - for ( size_t i = 0, size = segcmds.size(); i < size; i++ ) - { - const segment_command_64 &sg = segcmds[i]; - if ( sg.vmsize == 0 ) - continue; - - qstring segname(sg.segname, sizeof(sg.segname)); - if ( (mv.flags & MV_SEGMENTS) != 0 ) - { - mv.visit_segment( - sg.vmaddr + mv.slide, - sg.vmaddr + sg.vmsize + mv.slide, - segname, - (sg.flags & VM_PROT_EXECUTE) != 0 || segname == SEG_TEXT); - } - - if ( (mv.flags & MV_SECTIONS) != 0 ) - { - // special check for the header - if ( sections.size() > 0 - && strneq(segcmds[i].segname, "__TEXT", 6) - && segcmds[i].vmaddr < sections[0].addr ) - { - mv.visit_section( - segcmds[i].vmaddr + mv.slide, - sections[0].addr + mv.slide, - "HEADER", - segname, - false); - } - - // visit all sections in the segment - for ( size_t j = 0; j < sg.nsects; j++ ) - { - const section_64 § = sections[mfile.get_seg2section(i) + j]; - qstring sectname(sect.sectname, sizeof(sect.sectname)); - mv.visit_section( - sect.addr + mv.slide, - sect.addr + sect.size + mv.slide, - sectname, - segname, - (sect.flags & (S_ATTR_PURE_INSTRUCTIONS|S_ATTR_SOME_INSTRUCTIONS)) != 0); - } - } - } -} - -//-------------------------------------------------------------------------- -static void visit_macho_symbols( - const nlistvec_t &symbols, - const qstring &strings, - macho_visitor_t &mv, - int cputype) -{ - for ( size_t i=0; i < symbols.size(); i++ ) - { - const struct nlist_64 &nl = symbols[i]; - if ( nl.n_un.n_strx > strings.size() ) - continue; - - const char *name = &strings[nl.n_un.n_strx]; - if ( qstrlen(name) == 0 ) - continue; - - ea_t ea = nl.n_value + mv.slide; - - int type = nl.n_type & N_TYPE; - switch ( type ) - { - case N_UNDF: - case N_PBUD: - case N_ABS: - case N_INDR: - break; - case N_SECT: - // process exported and private symbols - if ( ((nl.n_type & (N_EXT|N_PEXT)) == N_EXT) || nl.n_sect != NO_SECT ) - { - // only set thumb-ness for arm32 symbols in the __text section (n_sect=1) - if ( cputype == CPU_TYPE_ARM && nl.n_sect == 1 ) - mv.handle_thumb(ea, name, (nl.n_desc & 0xF) == N_ARM_THUMB_DEF); - - mv.visit_symbol(ea, name); - } - break; - default: - break; - } - } -} - -//-------------------------------------------------------------------------- -static void visit_macho_function_starts( - macho_file_t &mfile, - macho_visitor_t &mv, - int cputype) -{ - struct ida_local symmacho_fsv_t : public function_starts_visitor_t - { - macho_visitor_t &mv; - int cputype; - - symmacho_fsv_t(macho_visitor_t &_mv, int _cputype) - : mv(_mv), cputype(_cputype) {} - - virtual int visit_start(uint64_t address) override - { - // create a debugger-friendly address - if ( cputype == CPU_TYPE_ARM && (address & 1) != 0 ) - address ^= 1; - mv.visit_function_start(address + mv.slide); - return 0; - } - virtual void handle_error() override - { - mv.handle_function_start_error(); - } - }; - - symmacho_fsv_t fsv(mv, cputype); - mfile.visit_function_starts(fsv); -} - -//-------------------------------------------------------------------------- -static void visit_macho_uuid(macho_file_t &mfile, macho_visitor_t &mv) -{ - uint8 uuid[16]; - if ( mfile.get_uuid(uuid) ) - mv.uuid = bytevec_t(uuid, sizeof(uuid)); -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::parse_macho_file( - const char *path, - ea_t base, - macho_visitor_t &mv, - const bytevec_t &uuid) const -{ - linput_t *li = open_linput(path, false); - if ( li == NULL ) - return false; - linput_janitor_t janitor(li); - if ( !match_macho_uuid(li, uuid) ) - return false; - return parse_macho_input(li, base, mv); -} - -//-------------------------------------------------------------------------- -static bool get_platform_version( - macho_visitor_t &mv, - const macho_platform_version_t &mpv) -{ - if ( mpv.plfm != 0 && mpv.major != 0 ) - { - if ( mpv.plfm == PLATFORM_MACOS ) - mv.version = mpv.minor; // major is always 10 for OSX, which is assumed - else - mv.version = mpv.major; - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -static bool visit_macho_platform_info(macho_file_t &mfile, macho_visitor_t &mv) -{ - macho_platform_version_info_t mpvi; - if ( !mfile.get_platform_version_info(&mpvi) ) - return false; - - // platform version could be encoded in multiple different load commands. - // the sdk versions usually provide the most accurate info. - return get_platform_version(mv, mpvi.build_sdk) - || get_platform_version(mv, mpvi.min_sdk) - || get_platform_version(mv, mpvi.build_minos) - || get_platform_version(mv, mpvi.min_version); -} - -//-------------------------------------------------------------------------- -static bool parse_macho_common( - macho_file_t &mfile, - macho_visitor_t &mv, - ea_t base, - int cputype) -{ - if ( !mfile.parse_header() || !mfile.select_subfile(cputype) ) - return false; - - mv.subtype = mfile.get_mach_header().filetype; - - ea_t maxea = 0; - ea_t imagebase = BADADDR; - const segcmdvec_t &segcmds = mfile.get_segcmds(); - - // since mac os x can scatter application segments over the memory - // we calculate only the text segment size - for ( size_t i = 0; i < segcmds.size(); i++ ) - { - const segment_command_64 &sg = segcmds[i]; - if ( is_text_segment(sg) ) - { - if ( imagebase == BADADDR ) - imagebase = sg.vmaddr; - ea_t end = sg.vmaddr + sg.vmsize; - if ( maxea < end ) - maxea = end; - } - } - - if ( imagebase == BADADDR ) - return false; - - mv.size = maxea - imagebase; - if ( base != BADADDR ) - mv.slide = base - imagebase; - - if ( (mv.flags & MV_UUID) != 0 ) - visit_macho_uuid(mfile, mv); - - if ( (mv.flags & MV_FUNCTION_STARTS) != 0 ) - visit_macho_function_starts(mfile, mv, cputype); - - if ( (mv.flags & (MV_SEGMENTS|MV_SECTIONS)) != 0 ) - visit_macho_segments(mfile, mv); - - if ( (mv.flags & MV_PLATFORM_INFO) != 0 ) - visit_macho_platform_info(mfile, mv); - - return true; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::parse_macho_input( - linput_t *li, - ea_t base, - macho_visitor_t &mv) const -{ - macho_file_t mfile(li); - int cputype = get_cputype(); - - if ( !parse_macho_common(mfile, mv, base, cputype) ) - return false; - - if ( (mv.flags & MV_SYMBOLS) != 0 ) - { - qstring strings; - nlistvec_t symbols; - mfile.get_symbol_table_info(&symbols, &strings); - visit_macho_symbols(symbols, strings, mv, cputype); - } - - return true; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::parse_macho_mem(ea_t base, macho_visitor_t &mv, uint32 hints) -{ - linput_t *li = create_mem_input(base); - if ( li == NULL ) - return false; - - linput_janitor_t janitor(li); - - macho_file_t mfile(li, 0, MACHO_HINT_MEM_IMAGE | hints); - int cputype = get_cputype(); - - if ( !parse_macho_common(mfile, mv, base, cputype) ) - return false; - - if ( (mv.flags & MV_SYMBOLS) != 0 ) - { - struct symtab_command st = { 0 }; - if ( !mfile.get_symtab_command(&st) ) - return false; - - nlistvec_t symbols; - mfile.get_symbol_table(st, &symbols); - - // check if this is a new string table - strings_cache_t::const_iterator i = strcache.find(st.stroff); - if ( i == strcache.end() ) - { - qstring buf; - mfile.get_string_table(st, &buf); - const qstring &strings = strcache.insert(std::make_pair(st.stroff, buf)).first->second; - visit_macho_symbols(symbols, strings, mv, cputype); - } - else - { - // if not, use the existing one - visit_macho_symbols(symbols, i->second, mv, cputype); - } - } - - return true; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::calc_macho_uuid(bytevec_t *out, linput_t *li) const -{ - uint8 uuid[16]; - macho_file_t mfile(li); - - if ( mfile.parse_header() - && mfile.select_subfile(get_cputype()) - && mfile.get_uuid(uuid) ) - { - *out = bytevec_t(uuid, sizeof(uuid)); - return true; - } - - return false; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::match_macho_uuid(linput_t *li, const bytevec_t &uuid) const -{ - macho_file_t mfile(li); - - return mfile.parse_header() - && mfile.select_subfile(get_cputype()) - && mfile.match_uuid(uuid); -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::is_exe_header(ea_t base) -{ - macho_visitor_t v; - parse_macho_mem(base, v); - return v.subtype == MH_EXECUTE; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::calc_image_info( - uint32 *subtype, - asize_t *size, - bytevec_t *uuid, - linput_t *li, - ea_t base) const -{ - macho_visitor_t v(MV_UUID); - if ( !parse_macho_input(li, base, v) ) - return false; - - if ( subtype != NULL ) - *subtype = v.subtype; - if ( size != NULL ) - *size = v.size; - if ( uuid != NULL ) - *uuid = v.uuid; - - return true; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::calc_image_info( - uint32 *subtype, - asize_t *size, - bytevec_t *uuid, - const char *path) const -{ - linput_t *li = open_linput(path, false); - if ( li == NULL ) - return false; - bool ok = calc_image_info(subtype, size, uuid, li, BADADDR); - close_linput(li); - return ok; -} - -//-------------------------------------------------------------------------- -bool macho_utils_t::calc_image_info( - uint32 *subtype, - asize_t *size, - bytevec_t *uuid, - ea_t base) -{ - linput_t *li = create_mem_input(base); - if ( li == NULL ) - return false; - bool ok = calc_image_info(subtype, size, uuid, li, base); - close_linput(li); - return ok; -} - -//-------------------------------------------------------------------------- -qstring macho_utils_t::expand_home_dir(const char *path) -{ - qstring home; - qstring tmp(path); - - char buf[QMAXPATH]; - if ( tmp.length() > 0 && tmp[0] == '~' && qgetenv("HOME", &home) ) - return qmakepath(buf, sizeof(buf), home.c_str(), tmp.substr(1).c_str(), NULL); - - return path; -} - -//-------------------------------------------------------------------------- -// merge 2 range sets -// high priority overrides what is defined in low priority -// FIXME: this function was stolen from ui/memregs.cpp. Since memregs.cpp is -// part of the ui, we can't use it when building the mac_server, and I don't -// think this code is worth moving into dumb.a. -void macho_utils_t::merge( - meminfo_vec_t &res, - const meminfo_vec_t &low, - const meminfo_vec_t &high) -{ - if ( low.empty() ) - { - res = high; - return; - } - - if ( high.empty() ) - { - res = low; - return; - } - - int l = 0; - meminfo_vec_t tmp; - ea_t end = 0; - ea_t lea = low[0].start_ea; - for ( int h=0; ; h++ ) - { - ea_t hea = h < high.size() ? high[h].start_ea : BADADDR; - if ( hea != end ) - { - while ( l < low.size() && lea < hea ) - { // add ranges before the high priority range - if ( low[l].end_ea > end ) - { - tmp.push_back(low[l]); - if ( end >= lea ) - tmp.back().start_ea = end; - end = low[l].end_ea; - if ( end > hea ) - { - end = lea = hea; - tmp.back().end_ea = end; - break; - } - } - l++; - if ( l < low.size() ) - lea = low[l].start_ea; - } - } - if ( h == high.size() ) - break; - tmp.push_back(high[h]); - end = high[h].end_ea; - } - tmp.swap(res); -} - -//-------------------------------------------------------------------------- -dyld_utils_t::dyld_utils_t(debmod_t *_dbgmod, int _arch) - : inherited(_dbgmod, _arch) -{ - base_ea = BADADDR; - entry_ea = BADADDR; - infos_ea = BADADDR; - ranges_ea = BADADDR; -} - -//-------------------------------------------------------------------------- -void dyld_utils_t::clear(void) -{ - inherited::clear(); - infos.clear(); - shared_cache_ranges.clear(); - base_ea = BADADDR; - entry_ea = BADADDR; - infos_ea = BADADDR; - ranges_ea = BADADDR; -} - -//-------------------------------------------------------------------------- -void dyld_all_image_infos_t::clear() -{ - version = 0; - num_info = 0; - info_array = 0; - dyld_notify = 0; - dyld_image_load_address = 0; - dyld_image_infos_address = 0; - shared_cache_slide = 0; - shared_cache_base_address = 0; -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::untag(ea_t *ea) const -{ - if ( !is64 ) - return false; - - uint64 mask = 0; - switch ( arch ) - { - case PLFM_ARM: - // MACH_VM_MAX_ADDRESS = 0x0000000FC0000000, tag stored in bits 36-63 - mask = uint64(0xFFFFFFF) << 36; - break; - case PLFM_386: - // MACH_VM_MAX_ADDRESS = 0x00007FFFFFE00000, tag stored in bits 48-63 - mask = uint64(0xFFFF) << 48; - break; - } - - ea_t orig = *ea; - ea_t addr = uint64(orig) & ~mask; - if ( addr != orig ) - { - *ea = addr; - return true; - } - - return false; -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::update_infos() -{ - // read the important fields from _dyld_all_image_infos in a version-independent - // and bitness-independent manner. - infos.clear(); - if ( infos_ea == BADADDR ) - return false; - ea_t off = infos_ea; - if ( !read(off, &infos.version, sizeof(infos.version)) || infos.version < 1 ) - return false; - off += sizeof(infos.version); - if ( !read(off, &infos.num_info, sizeof(infos.num_info)) ) - return false; - off += sizeof(infos.num_info); - if ( !read(off, &infos.info_array, addrsize) ) - return false; - off += addrsize; - if ( !read(off, &infos.dyld_notify, addrsize) || infos.version < 2 ) - return false; - off += addrsize // dyld_notify - + sizeof(uint8) // processDetachedFromSharedRegion - + sizeof(uint8) // libSystemInitialized - + addrsize - 2; // padding - if ( !read(off, &infos.dyld_image_load_address, addrsize) || infos.version < 9 ) - return false; - off += addrsize // dyldImageLoadAddress - + addrsize // jitInfo - + addrsize // dyldVersion - + addrsize // errorMessage - + addrsize // terminationFlags - + addrsize // coreSymbolicationShmPage - + addrsize // systemOrderFlag - + addrsize // uuidArrayCount - + addrsize; // uuidArray - if ( !read(off, &infos.dyld_image_infos_address, addrsize) ) - return false; - // we will need to know the base address of the shared cache for OSX 10.13/iOS 11 and later - if ( infos.version >= 15 ) - { - off += addrsize // dyldAllImageInfosAddress - + addrsize // initialImageCount - + addrsize // errorKind - + addrsize // errorClientOfDylibPath - + addrsize // errorTargetDylibPath - + addrsize; // errorSymbol - if ( !read(off, &infos.shared_cache_slide, addrsize) ) - return false; - off += addrsize // sharedCacheSlide - + 16; // sharedCacheUUID - if ( !read(off, &infos.shared_cache_base_address, addrsize) ) - return false; - } - // remove any tags from the pointer values - untag(&infos.info_array); - untag(&infos.dyld_notify); - untag(&infos.dyld_image_load_address); - untag(&infos.dyld_image_infos_address); - untag(&infos.shared_cache_base_address); - // it's possible that dyld has been relocated but the fields in dyld_all_image_infos - // haven't been updated yet - do it now. - if ( infos_ea != infos.dyld_image_infos_address ) - { - adiff_t slide = infos_ea - infos.dyld_image_infos_address; - infos.dyld_image_load_address += slide; - infos.dyld_image_infos_address += slide; - infos.dyld_notify += slide; - infos.info_array += slide; - } - // gdb_image_notifier could be a thumb function - clear the thumb bit if needed - if ( arch == PLFM_ARM && !is64 && (infos.dyld_notify & 1) != 0 ) - infos.dyld_notify ^= 1; - return true; -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::update_ranges() -{ - if ( !shared_cache_ranges.empty() ) - return true; - - if ( ranges_ea != BADADDR ) - { - // parse the _dyld_shared_cache_ranges symbol in memory - ea_t count = 0; - if ( !read(ranges_ea, &count, addrsize) ) - return false; - - for ( ea_t i = 0, ptr = ranges_ea + addrsize; i < count; i++, ptr += 2 * addrsize ) - { - ea_t start = 0; - if ( !read(ptr, &start, addrsize) ) - return false; - - ea_t size = 0; - if ( !read(ptr+addrsize, &size, addrsize) ) - return false; - - range_t r(start, start+size); - dbgmod->dmsg("shared cache range: %a..%a\n", r.start_ea, r.end_ea); - shared_cache_ranges.add(r); - } - } - else - { - // _dyld_shared_cache_ranges is no longer present in dyld for OSX 10.13/iOS 11. - // fall back to parsing the mappings in the dyld cache header. - dbgmod->debdeb("parsing cache header: version=%d, shared_cache_base_address=%a, shared_cache_slide=%a\n", - infos.version, - infos.shared_cache_base_address, - infos.shared_cache_slide); - - struct ida_local mapping_visitor_t : public dyld_cache_visitor_t - { - debmod_t *dm; - rangeset_t *ranges; - - mapping_visitor_t(debmod_t *_dm, rangeset_t *_ranges) - : dyld_cache_visitor_t(DCV_MAPPINGS), dm(_dm), ranges(_ranges) {} - - virtual void visit_mapping(ea_t start_ea, ea_t end_ea) override - { - dm->dmsg("shared cache mapping: %a..%a\n", start_ea, end_ea); - ranges->add(range_t(start_ea, end_ea)); - } - }; - - mapping_visitor_t mapv(dbgmod, &shared_cache_ranges); - parse_dyld_cache_header(mapv); - } - - return !shared_cache_ranges.empty(); -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::parse_info_array(uint32 count, ea_t info_array, dll_visitor_t &dv) -{ - size_t bufsize = count * addrsize * 3; // 3 pointers per dyld_image_info element - - bytevec_t buf; - buf.resize(bufsize); - - if ( !read(info_array, buf.begin(), bufsize) ) - return false; - - const uchar *ptr = buf.begin(); - const uchar *end = buf.begin() + bufsize; - - for ( ; ptr < end; ptr += addrsize * 3 ) - { - // dyld_image_info::addr - ea_t base = 0; - get_ptr_value(&base, ptr); - - // dyld_image_info::name - ea_t name_ptr = 0; - get_ptr_value(&name_ptr, ptr+addrsize); - - char name[1024] = { 0 }; - read(name_ptr, name, sizeof(name)); // may fail because we don't know exact size - name[sizeof(name)-1] = '\0'; - - asize_t size = 0; - bytevec_t uuid; - calc_image_info(NULL, &size, &uuid, base); - - dv.visit_dll(base, size, name, uuid); - } - - return true; -} - -//-------------------------------------------------------------------------- -template bool dyld_utils_t::is_dyld_header( - ea_t base, - char *filename, - size_t namesize, - uint32 magic) -{ - H mh; - if ( !read(base, &mh, sizeof(mh)) ) - return false; - - if ( mh.magic != magic || mh.filetype != MH_DYLINKER ) - return false; - - // seems to be dylib - // find its file name - filename[0] = '\0'; - ea_t ea = base + sizeof(mh); - for ( int i=0; i < mh.ncmds; i++ ) - { - struct load_command lc; - lc.cmd = 0; - read(ea, &lc, sizeof(lc)); - if ( lc.cmd == LC_ID_DYLIB ) - { - struct dylib_command dcmd; - read(ea, &dcmd, sizeof(dcmd)); - read(ea+dcmd.dylib.name.offset, filename, namesize); - break; - } - else if ( lc.cmd == LC_ID_DYLINKER ) - { - struct dylinker_command dcmd; - read(ea, &dcmd, sizeof(dcmd)); - read(ea+dcmd.name.offset, filename, namesize); - break; - } - ea += lc.cmdsize; - } - - return true; -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::is_dyld_header_64(ea_t base, char *filename, size_t namesize) -{ - return is_dyld_header(base, filename, namesize, MH_MAGIC_64); -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::is_dyld_header_32(ea_t base, char *filename, size_t namesize) -{ - return is_dyld_header(base, filename, namesize, MH_MAGIC); -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::is_dyld_header(ea_t base, char *filename, size_t namesize) -{ - return is64 - ? is_dyld_header_64(base, filename, namesize) - : is_dyld_header_32(base, filename, namesize); -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::parse_dyld_cache_header(dyld_cache_visitor_t &dcv) -{ - ea_t base = infos.shared_cache_base_address; - if ( base == 0 ) - return false; - - linput_t *li = create_mem_input(base); - if ( li == NULL ) - return false; - - dyld_cache_t dyldcache(li); - linput_janitor_t janitor(li); - - uint32 hflags = (dcv.flags & DCV_MAPPINGS) != 0 ? PHF_MAPPINGS : 0; - - if ( !dyldcache.parse_header(hflags) ) - return false; - - ea_t slide = infos.shared_cache_slide; - - if ( (dcv.flags & DCV_MAPPINGS) != 0 ) - { - for ( int i = 0, nmaps = dyldcache.get_nummappings(); i < nmaps; i++ ) - { - const dyld_cache_mapping_info &mi = dyldcache.get_mapping_info(i); - ea_t start_ea = mi.address + slide; - ea_t end_ea = mi.address + slide + mi.size; - dcv.visit_mapping(start_ea, end_ea); - } - } - - return true; -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::parse_macho_mem(ea_t base, macho_visitor_t &mv, uint32 hints) -{ - if ( is_shared_cache_lib(base) ) - hints |= MACHO_HINT_SHARED_CACHE_LIB; - - return inherited::parse_macho_mem(base, mv, hints); -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::get_symbol_file_path(qstring *path, const char *module) const -{ - if ( symbol_path.empty() ) - return false; - - char buf[QMAXPATH]; - qmakepath(buf, sizeof(buf), symbol_path.c_str(), module, NULL); - *path = inherited::expand_home_dir(buf); - - return true; -} - -//-------------------------------------------------------------------------- -bool dyld_utils_t::parse_local_symbol_file( - ea_t base, - const char *module, - const bytevec_t &uuid, - macho_visitor_t &mv) -{ - qstring path; - if ( !get_symbol_file_path(&path, module) ) - { - // we only show a warning for the iOS debugger, since it's a more serious issue. - // symbol loading is almost unusably slow when the local symbol cache is not present, - // so we make sure the user has a hint of what's wrong. - if ( arch == PLFM_ARM && !warned ) - { - msg("WARNING: No path to local symbol cache specified. Symbol loading might be very slow. " - "You can set SYMBOL_PATH in the debugger's cfg file for faster and more detailed debugging.\n"); - warned = true; - } - return false; - } - - linput_t *li = open_linput(path.c_str(), false); - linput_janitor_t lij(li); - - if ( li == NULL ) - { - // It is normal that a library on the remote machine does not have a corresponding local symbol file. - // Still, we print a message in case the user is looking for symbols in this missing module, - // or if they have accidentally set SYMBOL_PATH in the cfg to a bogus directory - in which case - // a ton of these messages will be printed and it should be pretty obvious what is wrong. - msg("WARNING: symbol file not found %s.\n", path.c_str()); - return false; - } - - if ( !match_macho_uuid(li, uuid) ) - { - // This is a pretty serious issue and we should print a warning message for the user. - // Symbol files extracted from different iOS/OSX machines may not be compatible, even if - // they have the exact same iOS version. This stumped me for a little while - // and it would have been nice if I had this message. - msg("WARNING: UUID mismatch for symbol file %s. " - "Please make sure SYMBOL_PATH in the debugger's cfg file points to symbols that are compatible with the remote machine.\n", - path.c_str()); - return false; - } - - return parse_macho_input(li, base, mv); -} - -//-------------------------------------------------------------------------- -void kernel_utils_t::clear(void) -{ - inherited::clear(); - - kdk_path.clear(); - prelinked_kexts.clear(); - prelink_data_off = 0; - - if ( kcache_li != NULL ) - close_linput(kcache_li); - - kcache_li = NULL; -} - -//-------------------------------------------------------------------------- -void kernel_utils_t::set_kdk_path(const qstring &path) -{ - kdk_path = macho_utils_t::expand_home_dir(path.c_str()); -} - -//-------------------------------------------------------------------------- -struct callback_info_t -{ - qstring path; - uint32 flags; - callback_info_t(uint32 _flags) : flags(_flags) {} -}; - -//-------------------------------------------------------------------------- -static int kdk_callback( - macho_file_t &, - void *ud, - const char *path, - const macho_ident_t &ident) -{ - callback_info_t *info = (callback_info_t *)ud; - - if ( (info->flags & KDK_SEARCH_KCACHE) != 0 && (ident.flags & AUF_IS_KCACHE) == 0 ) - return -1; // not a kernelcache - - if ( (info->flags & KDK_SEARCH_DSYM) != 0 ) - { - struct ida_local lambda_t - { - static int accept(macho_file_t &, void *, const char *, const macho_ident_t &) - { - return 0; // accept file - } - }; - if ( find_dsym_macho(path, ident, lambda_t::accept, NULL) != 0 ) - return -1; // no companion dsym - } - - info->path = path; - return 0; -} - -//-------------------------------------------------------------------------- -bool kernel_utils_t::find_kdk_file( - qstring *path, - int cpu_subtype, - const bytevec_t &uuid, - const char *name, - uint32 flags) const -{ - if ( kdk_path.empty() ) - return false; - - if ( uuid.size() != sizeof(macho_ident_t::uuid) ) - return false; - - macho_ident_t ident; - ident.cpu_type = get_cputype(); - ident.cpu_subtype = cpu_subtype; - - memcpy(ident.uuid, uuid.begin(), sizeof(ident.uuid)); - - int code = -1; - callback_info_t info(flags); - const char *dir = kdk_path.c_str(); - - switch ( cpu_subtype ) - { - case MH_EXECUTE: - code = find_dsym_kernel(dir, ident, kdk_callback, &info); - break; - case MH_KEXT_BUNDLE: - code = find_dsym_kext(dir, ident, name, kdk_callback, &info); - break; - } - - if ( code != 0 ) - return false; - - if ( path != NULL ) - *path = info.path; - - return true; -} - -//-------------------------------------------------------------------------- -uint64 kernel_utils_t::find_kext_offset(const bytevec_t &uuid) const -{ - for ( size_t i = 0, size = prelinked_kexts.size(); i < size; i++ ) - { - if ( prelinked_kexts[i].uuid == uuid ) - return prelinked_kexts[i].off; - } - return BADADDR64; -} - -//-------------------------------------------------------------------------- -bool kernel_utils_t::parse_prelinked_kext( - macho_visitor_t &mv, - ea_t base, - const bytevec_t &uuid) -{ - if ( kcache_li == NULL ) - return false; - - uint64 start_off = find_kext_offset(uuid); - if ( start_off == BADADDR64 ) - return false; - - kcache_single_kmod_input_t *kli = new kcache_single_kmod_input_t( - kcache_li, - start_off, - prelink_data_off); - - linput_t *li = create_generic_linput(kli); - QASSERT(1750, li != NULL); - linput_janitor_t lij(li); - - return parse_macho_input(li, base, mv); -} - -//-------------------------------------------------------------------------- -bool kernel_utils_t::parse_kcache(const bytevec_t &kernel_uuid) -{ - // look for a matching kernelcache in the KDK - qstring path; - if ( !find_kdk_file(&path, MH_EXECUTE, kernel_uuid, NULL, KDK_SEARCH_KCACHE) ) - return false; - - kcache_li = open_linput(path.c_str(), false); - if ( kcache_li == NULL ) - return false; - - macho_file_t kcache(kcache_li); - if ( !kcache.parse_header() || !kcache.select_subfile(get_cputype()) ) - return false; - - dbgmod->dmsg("found kernelcache: %s\n", path.c_str()); - - // extract info about the prelinked kexts. we will use it later. - const kmod_params_vec_t &kpv = kcache.get_kmod_info(); - - for ( size_t i = 0, size = kpv.size(); i < size; i++ ) - { - kext_info_t &info = prelinked_kexts.push_back(); - info.uuid = bytevec_t(kpv[i].uuid, sizeof(kpv[i].uuid)); - info.off = kpv[i].off; - } - - section_64 s; - if ( kcache.get_prelink_data(&s) ) - prelink_data_off = s.offset; - - return true; -} - -//-------------------------------------------------------------------------- -bool kernel_utils_t::find_kext(const bytevec_t &uuid, const char *kext_name) const -{ - return find_kext_offset(uuid) != BADADDR64 - || find_kdk_file(NULL, MH_KEXT_BUNDLE, uuid, kext_name); -} diff --git a/idasdk75/dbg/mac/symmacho.hpp b/idasdk75/dbg/mac/symmacho.hpp deleted file mode 100644 index 88fdfc0..0000000 --- a/idasdk75/dbg/mac/symmacho.hpp +++ /dev/null @@ -1,249 +0,0 @@ -#ifndef SYMMACHO_H -#define SYMMACHO_H - -// manage the mach-o images in a darwin process - -#include -#include -#include - -class debmod_t; -class linput_t; - -typedef std::map strings_cache_t; - -//-------------------------------------------------------------------------- -struct macho_visitor_t -{ - int flags; -#define MV_UUID 0x0001 // visit uuid -#define MV_FUNCTION_STARTS 0x0002 // visit function start eas -#define MV_SYMBOLS 0x0004 // visit symbols -#define MV_SEGMENTS 0x0008 // visit segments -#define MV_SECTIONS 0x0010 // visit sections -#define MV_PLATFORM_INFO 0x0020 // visit build version info - - uint32 subtype; // mh.filetype - asize_t size; // image size - sval_t slide; // ASLR slide - bytevec_t uuid; // filled if MV_UUID is set - uint32 version; // platform version - - macho_visitor_t(int _flags = 0) - : flags(_flags), subtype(0), size(0), slide(0), version(0) {} - - virtual void visit_function_start(ea_t /*ea*/) {} - virtual void visit_symbol(ea_t /*ea*/, const char * /*name*/) {} - virtual void visit_segment(ea_t /*start*/, ea_t /*end*/, const qstring & /*name*/, bool /*is_code*/) {} - virtual void visit_section(ea_t /*start*/, ea_t /*end*/, const qstring & /*sect*/, const qstring & /*seg*/, bool /*is_code*/) {} - - // called when function start info could not be found/loaded - virtual void handle_function_start_error() {} - // called just before a symbol is visited when cpu is CPU_TYPE_ARM - virtual void handle_thumb(ea_t /*ea*/, const char * /*name*/, bool /*is_thumb*/) {} - - DEFINE_VIRTUAL_DTOR(macho_visitor_t) -}; - -//-------------------------------------------------------------------------- -class macho_utils_t -{ -public: - debmod_t *dbgmod; - - int arch; // PLFM_386 or PLFM_ARM - int addrsize; // size of an address in the target process - bool is64; // is target process 64-bit? - bool warned; // warned the user about using SYMBOL_PATH when remote debugging - - // sometimes macho images might share a common string table. ensure the same string table isn't loaded twice. - strings_cache_t strcache; - - macho_utils_t(debmod_t *_dbgmod, int _arch); - DEFINE_VIRTUAL_DTOR(macho_utils_t) - - virtual void clear(void); - - int get_cputype(void) const; - void update_bitness(void); - - size_t read_mem(ea_t ea, void *buf, size_t size); - bool read(ea_t ea, void *buf, size_t size) { return read_mem(ea, buf, size) == size; } - void get_ptr_value(ea_t *val, const uchar *buf) const; - - bool is_exe_header(ea_t base); - - virtual bool parse_macho_file(const char *path, ea_t base, macho_visitor_t &mv, const bytevec_t &uuid) const; - virtual bool parse_macho_input(linput_t *li, ea_t base, macho_visitor_t &mv) const; - virtual bool parse_macho_mem(ea_t base, macho_visitor_t &mv, uint32 hints = 0); - - linput_t *create_mem_input(ea_t base); - - bool calc_macho_uuid(bytevec_t *uuid, linput_t *li) const; - bool match_macho_uuid(linput_t *li, const bytevec_t &uuid) const; - - bool calc_image_info(uint32 *subtype, asize_t *size, bytevec_t *uuid, ea_t base); - bool calc_image_info(uint32 *subtype, asize_t *size, bytevec_t *uuid, const char *path) const; - bool calc_image_info(uint32 *subtype, asize_t *size, bytevec_t *uuid, linput_t *li, ea_t base) const; - - static qstring expand_home_dir(const char *path); - - static void merge( - meminfo_vec_t &res, - const meminfo_vec_t &low, - const meminfo_vec_t &high); -}; - -//-------------------------------------------------------------------------- -struct dyld_all_image_infos_t -{ - uint32 version; - uint32 num_info; - ea_t info_array; - ea_t dyld_notify; - ea_t dyld_image_load_address; - ea_t dyld_image_infos_address; - ea_t shared_cache_slide; - ea_t shared_cache_base_address; - - dyld_all_image_infos_t() { clear(); } - - void clear(); -}; - -//-------------------------------------------------------------------------- -enum dyld_image_mode_t -{ - DYLD_IMAGE_ERROR = -1, - DYLD_IMAGE_ADDING = 0, - DYLD_IMAGE_REMOVING = 1, - DYLD_IMAGE_INFO_CHANGE = 2, -}; - -//-------------------------------------------------------------------------- -struct dll_visitor_t -{ - virtual void visit_dll( - ea_t base, - asize_t size, - const char *name, - const bytevec_t &uuid) = 0; - - DEFINE_VIRTUAL_DTOR(dll_visitor_t) -}; - -//-------------------------------------------------------------------------- -struct dyld_cache_visitor_t -{ - int flags; -#define DCV_MAPPINGS 0x1 // visit shared region mappings - - dyld_cache_visitor_t(int _flags) : flags(_flags) {} - - virtual void visit_mapping(ea_t /*start_ea*/, ea_t /*end_ea*/) {} -}; - -//-------------------------------------------------------------------------- -class dyld_utils_t : public macho_utils_t -{ - typedef macho_utils_t inherited; - - template bool is_dyld_header(ea_t base, char *filename, size_t namesize, uint32 magic); - - bool is_dyld_header_64(ea_t base, char *filename, size_t namesize); - bool is_dyld_header_32(ea_t base, char *filename, size_t namesize); - -public: - ea_t base_ea; // base address of dyld ifself - ea_t entry_ea; // dyld's entry point - ea_t infos_ea; // address of _dyld_all_image_infos - ea_t ranges_ea; // address of _dyld_shared_cache_ranges - - dyld_all_image_infos_t infos; - - rangeset_t shared_cache_ranges; - - qstring symbol_path; - - dyld_utils_t(debmod_t *_dbgmod, int _arch); - DEFINE_VIRTUAL_DTOR(dyld_utils_t) - - virtual void clear(void) override; - - bool is_shared_cache_lib(ea_t base) const { return shared_cache_ranges.contains(base); } - bool is_system_lib(ea_t base) const { return base == base_ea || is_shared_cache_lib(base); } - - bool is_dyld_header(ea_t base, char *filename, size_t namesize); - - bool update_infos(void); - bool update_ranges(void); - - virtual bool parse_macho_mem(ea_t base, macho_visitor_t &mv, uint32 hints = 0) override; - - bool parse_info_array(uint32 count, ea_t info_array, dll_visitor_t &dv); - bool parse_dyld_cache_header(dyld_cache_visitor_t &dcv); - - bool untag(ea_t *ea) const; - - bool get_symbol_file_path(qstring *path, const char *module) const; - bool parse_local_symbol_file( - ea_t base, - const char *module, - const bytevec_t &uuid, - macho_visitor_t &mv); -}; - -struct kext_info_t -{ - uint64 off; - bytevec_t uuid; -}; -DECLARE_TYPE_AS_MOVABLE(kext_info_t); -typedef qvector kext_info_vec_t; - -//-------------------------------------------------------------------------- -class kernel_utils_t : public macho_utils_t -{ - typedef macho_utils_t inherited; - - qstring kdk_path; // path to a Kernel Development Kit - linput_t *kcache_li; // if a kernelcache is present in the KDK, we can use it to parse kexts - uint64 prelink_data_off; // offset of __PRELINK_DATA, required for parsing prelinked kexts - kext_info_vec_t prelinked_kexts; // associate each kext's UUID with its offset in the kernelcache - - uint64 find_kext_offset(const bytevec_t &uuid) const; - -public: - kernel_utils_t(debmod_t *_dbgmod, int _arch) - : inherited(_dbgmod, _arch), kcache_li(NULL), prelink_data_off(0) {} - - virtual ~kernel_utils_t(void) { kernel_utils_t::clear(); } - - virtual void clear(void) override; - - void set_kdk_path(const qstring &path); - - // detect if a kernelcache is present and collect the prelinked kext info - bool parse_kcache(const bytevec_t &kernel_uuid); - - // apply the given visitor to a matching kext in the kernelcache - bool parse_prelinked_kext(macho_visitor_t &mv, ea_t base, const bytevec_t &uuid); - -#define KDK_SEARCH_DEFAULT 0x0 // look for any matching binary -#define KDK_SEARCH_DSYM 0x1 // look for a binary with a companion dSYM -#define KDK_SEARCH_KCACHE 0x2 // look for a kernelcache - - // get the path to a matching binary in the KDK - bool find_kdk_file( - qstring *path, - int cpu_subtype, - const bytevec_t &uuid, - const char *name, - uint32 flags = KDK_SEARCH_DEFAULT) const; - - // check if the given kext appears in the KDK, either as a standalone binary - // or as a prelinked kext in a kernelcache - bool find_kext(const bytevec_t &uuid, const char *kext_name) const; -}; - -#endif // SYMMACHO_H diff --git a/idasdk75/dbg/macho_rebase.cpp b/idasdk75/dbg/macho_rebase.cpp deleted file mode 100644 index 7a13bc4..0000000 --- a/idasdk75/dbg/macho_rebase.cpp +++ /dev/null @@ -1,197 +0,0 @@ - -#include "../ldr/mach-o/macho_node.h" - -//-------------------------------------------------------------------------- -static bool rebase_scattered_segments(ea_t base) -{ - netnode node; - node.create(MACHO_NODE); - - // detect if the code and data segments have moved relative to each other. - // if so, we cannot simply apply a uniform delta to the entire database. - // we must rebase one segment at a time. - ea_t ldr_data = 0; - ea_t ldr_text = 0; - - if ( node.hashval("__DATA", &ldr_data, sizeof(ldr_data), SEGM_TAG) == -1 - || node.hashval("__TEXT", &ldr_text, sizeof(ldr_text), SEGM_TAG) == -1 ) - { - return false; - } - - ea_t dbg_data = g_dbgmod.dbg_get_segm_start(base, "__DATA"); - ea_t dbg_text = g_dbgmod.dbg_get_segm_start(base, "__TEXT"); - - if ( dbg_data == BADADDR || dbg_text == BADADDR ) - return false; - - adiff_t slide = (dbg_data - dbg_text) - (ldr_data - ldr_text); - - if ( slide == 0 ) - return false; - - scattered_image_t si; - // we have detected segment scattering. - // ensure that we can collect the vmaddr for each loader segment in IDA. - if ( g_dbgmod.dbg_get_scattered_image(si, base) <= 0 ) - return false; - - uint8 ubuf[16]; - bytevec_t uuid; - // it is quite possible that the input file does not match the image in the cache. - // if there is a mismatch we warn the user. - if ( !g_dbgmod.dbg_get_image_uuid(&uuid, base) - || uuid.size() != sizeof(ubuf) - || node.supval(MACHO_ALT_UUID, ubuf, sizeof(ubuf)) <= 0 - || memcmp(uuid.begin(), ubuf, sizeof(ubuf)) != 0 ) - { - warning("AUTOHIDE DATABASE\n" - "UUID mismatch between the input file and the image in memory.\n" - "\n" - "This could mean your dyld_shared_cache is out of sync with the library on disk,\n" - "and the database will likely not be rebased properly.\n" - "\n" - "To ensure proper rebasing, please confirm that the input file was included\n" - "the last time update_dyld_shared_cache was run.\n"); - } - - // adjust any pointers between the code and data segments - show_wait_box("Rebasing CODE -> DATA pointers"); - // we want to patch pointers in the database without writing to debugger memory - lock_dbgmem_config(); - - for ( nodeidx_t nidx = node.charfirst(CODE_TAG); - nidx != BADNODE && !user_cancelled(); - nidx = node.charnext(nidx, CODE_TAG) ) - { - ea_t ea = node2ea(nidx); - uchar kind = node.charval_ea(ea, CODE_TAG); - switch ( kind ) - { - case 1: // 32-bit pointer - add_dword(ea, slide); - break; - case 2: // 64-bit pointer - add_qword(ea, slide); - break; - default: // TODO: there are many more. we will deal with them later - break; - } - } - - replace_wait_box("Rebasing DATA -> CODE pointers"); - - for ( nodeidx_t nidx = node.charfirst(DATA_TAG); - nidx != BADNODE && !user_cancelled(); - nidx = node.charnext(nidx, DATA_TAG) ) - { - ea_t ea = node2ea(nidx); - uchar kind = node.charval_ea(ea, DATA_TAG); - switch ( kind ) - { - case 1: // pointer - if ( inf_is_64bit() ) - add_qword(ea, -slide); - else - add_dword(ea, -slide); - break; - default: // TODO: there a few more. we will deal with them later - break; - } - } - - hide_wait_box(); - unlock_dbgmem_config(); - - qvector ldrsegs; - // we must collect all the loader segments before we start calling move_segm(). - // this is to avoid altering the areacb_t as we're iterating over it. - for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) - { - if ( s->is_loader_segm() ) - ldrsegs.push_back(s); - } - - show_wait_box("Rebasing scattered segments"); - - bool ok = true; - size_t ls_count = ldrsegs.size(); - size_t ss_count = si.size(); - - // rebase each loader segment according to its matching segment in the scattered image. - // currently we require the list of scattered segments and the list of loader segments - // to have the exact same ordering. this is because we have no way to uniquely match a - // loader segment and a scattered segment without some context. the segment's name, start_ea, - // type, and selector are all not sufficient in this situation. - for ( size_t i = 0; i < ls_count && !user_cancelled(); i++ ) - { - segment_t *s = ldrsegs[i]; - - qstring name; - get_segm_name(&name, s); - ea_t rebase_to = 0; - - if ( i < ss_count && name == si[i].name ) - { - // found the loader segment in memory. rebase it to this address. - rebase_to = si[i].start_ea; - } - else if ( name == "UNDEF" ) - { - // UNDEF segment is not actually in memory. just rebase it along with the other data segments. - rebase_to = s->start_ea + (dbg_data - ldr_data); - } - else - { - msg("%a: Failed to find segment %s in process memory!\n", s->start_ea, name.c_str()); - ok = false; - break; - } - - if ( s->start_ea != rebase_to ) - { - replace_wait_box("Moving segment %s to %#a", name.c_str(), rebase_to); - int code = move_segm(s, rebase_to, MSF_PRIORITY|MSF_SILENT); - if ( code != MOVE_SEGM_OK ) - { - msg("%a: Failed to rebase segment %s to %a, code=%d\n", s->start_ea, name.c_str(), rebase_to, code); - ok = false; - } - } - } - - hide_wait_box(); - set_imagebase(base); - node.altset(MACHO_ALT_IMAGEBASE, base); - - // update segm eas in the database - qstring idx; - for ( ssize_t s = node.hashfirst(&idx, SEGM_TAG); - s >= 0; - s = node.hashnext(&idx, idx.c_str(), SEGM_TAG) ) - { - ea_t start = g_dbgmod.dbg_get_segm_start(base, idx.c_str()); - if ( start != BADADDR ) - node.hashset(idx.c_str(), &start, sizeof(start), SEGM_TAG); - } - - if ( !ok ) - { - char buf[QMAXPATH]; - dbg_get_input_path(buf, sizeof(buf)); - warning("AUTOHIDE DATABASE\n" - "Some loader segments were not rebased properly.\n" - "\n" - "This error might occur if you are debugging a dylib from /System/Library or /usr/lib,\n" - "since these files have different segment info when they are loaded from dyld_shared_cache.\n" - "\n" - "To ensure more accurate segment info when debugging, you can:\n" - "\n" - " 1. open the dyld_shared_cache in IDA (usually found in /var/db/dyld/)\n" - " 2. select the 'Apple DYLD cache (single module)' option\n" - " 3. select %s from the list of modules\n" - " 4. use %s as the input file path in the Process Options dialog\n", qbasename(buf), buf); - } - - return true; -} diff --git a/idasdk75/dbg/pc_debmod.cpp b/idasdk75/dbg/pc_debmod.cpp deleted file mode 100644 index 2fb612c..0000000 --- a/idasdk75/dbg/pc_debmod.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#ifdef __NT__ -#include -#endif -#include -#include -#include "pc_debmod.h" - -//-------------------------------------------------------------------------- -//lint -esym(1566,pc_debmod_t::hwbpt_ea,pc_debmod_t::hwbpt_type) -//lint -esym(1566,pc_debmod_t::dr6,pc_debmod_t::dr7) -pc_debmod_t::pc_debmod_t() -{ - static const uchar bpt[] = X86_BPT_CODE; - bpt_code.append(bpt, sizeof(bpt)); - sp_idx = R_ESP; - pc_idx = R_EIP; - sr_idx = R_EFLAGS; - fs_idx = R_FS; - gs_idx = R_GS; - cs_idx = R_CS; - ds_idx = R_DS; - es_idx = R_ES; - ss_idx = R_SS; - nregs = X86_NREGS; - - cleanup_hwbpts(); - set_platform(get_local_platform()); -} - -//-------------------------------------------------------------------------- -int pc_debmod_t::get_regidx(const char *regname, int *clsmask) -{ - return x86_get_regidx(clsmask, regname); -} - -//-------------------------------------------------------------------------- -int idaapi pc_debmod_t::dbg_is_ok_bpt(bpttype_t type, ea_t ea, int /* len */) -{ - if ( type == BPT_SOFT ) - return BPT_OK; - - return find_hwbpt_slot(ea, type) == -1 ? BPT_TOO_MANY : BPT_OK; -} - -//-------------------------------------------------------------------------- -// returns -1 if something is wrong -int pc_debmod_t::find_hwbpt_slot(ea_t ea, bpttype_t type) const -{ - for ( int i=0; i < MAX_BPT; i++ ) - { - if ( hwbpt_ea[i] == ea && hwbpt_type[i] == type ) // another breakpoint is here - return -1; - if ( hwbpt_ea[i] == BADADDR ) // empty slot found - return i; - } - return -1; -} - -//-------------------------------------------------------------------------- -bool pc_debmod_t::add_hwbpt(bpttype_t type, ea_t ea, int len) -{ - int i = find_hwbpt_slot(ea, type); // get slot number - if ( i != -1 ) - { - hwbpt_ea[i] = ea; - hwbpt_type[i] = type; - if ( type == BPT_EXEC ) - type = 0; // exec bpts are encoded with 0 on x86 - - // length code used by the processor - int lenc = (len == 2) ? 1 - : (len == 4) ? 3 - : (len == 8) ? 2 - : 0; - - dr7 |= (1 << (i*2)); // enable local breakpoint - dr7 |= (type << (16+(i*4))); // set breakpoint type - dr7 |= (lenc << (18+(i*4))); // set breakpoint length - - return refresh_hwbpts(); - } - return false; -} - -//-------------------------------------------------------------------------- -bool pc_debmod_t::del_hwbpt(ea_t ea, bpttype_t type) -{ - for ( int i=0; i < MAX_BPT; i++ ) - { - if ( hwbpt_ea[i] == ea && hwbpt_type[i] == type ) - { - hwbpt_ea[i] = BADADDR; // clean the address - dr7 &= ~(3 << (i*2)); // clean the enable bits - dr7 &= ~(0xF << (i*4+16)); // clean the length and type - return refresh_hwbpts(); - } - } - return false; -} - - -#ifdef __NT__ -//-------------------------------------------------------------------------- -// Set hardware breakpoint for one thread -bool pc_debmod_t::set_hwbpts(HANDLE hThread) -{ - // sure_suspend_thread(ti); - CONTEXT Context; - Context.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; - - BOOL ok = GetThreadContext(hThread, &Context); - if ( !ok ) - { - deberr("GetThreadContext"); - return false; - } - Context.Dr0 = hwbpt_ea[0]; - Context.Dr1 = hwbpt_ea[1]; - Context.Dr2 = hwbpt_ea[2]; - Context.Dr3 = hwbpt_ea[3]; - Context.Dr6 = 0; - Context.Dr7 = dr7; - - ok = SetThreadContext(hThread, &Context); - if ( !ok ) - { - deberr("SetThreadContext"); - } - // sure_resume_thread(ti); - return ok != FALSE; -} - -//-------------------------------------------------------------------------- -ea_t pc_debmod_t::is_hwbpt_triggered(thid_t id, bool is_stepping) -{ - CONTEXT Context; - Context.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; - HANDLE h = get_thread_handle(id); - if ( GetThreadContext(h, &Context) ) - { - for ( int i=0; i < MAX_BPT; i++ ) - { - if ( (Context.Dr7 & uint32(1 << (i*2))) - && (Context.Dr6 & uint32(1 << i)) ) // Local hardware breakpoint 'i' - { - ULONG_PTR *dr = NULL; - switch ( i ) - { - case 0: dr = &Context.Dr0; break; - case 1: dr = &Context.Dr1; break; - case 2: dr = &Context.Dr2; break; - case 3: dr = &Context.Dr3; break; - } - if ( dr == NULL ) - break; - if ( hwbpt_ea[i] == *dr ) - { - set_hwbpts(h); // Clear the status bits - // do not report exec breakpoint if it occurs while we are stepping - if ( is_stepping && hwbpt_type[i] == BPT_EXEC ) - break; - return hwbpt_ea[i]; - } - //? TRACING else - // debdeb("System hardware breakpoint at %08X ???\n", *dr); //? - // what to do ?: - // reset it, and continue as if no event were received ? - // send it to IDA, and let the user setup a "stop on non-debugger hardware breakpoint" option ? - } - } - } - return BADADDR; -} -#endif // ifdef __NT__ - -//-------------------------------------------------------------------------- -void pc_debmod_t::cleanup_hwbpts() -{ - for ( int i=0; i < MAX_BPT; i++ ) - { - hwbpt_ea[i] = BADADDR; - hwbpt_type[i] = bpttype_t(0); - } - dr6 = 0; - dr7 = 0x100; // exact local breakpoints -} - -//-------------------------------------------------------------------------- -ea_t pc_debmod_t::calc_appcall_stack(const regvals_t ®vals) -{ - ea_t ea = inherited::calc_appcall_stack(regvals); -#ifndef __X86__ - // do not touch the red zone (used by gcc) - ea = ea > 128 ? ea - 128 : BADADDR; -#endif - return ea; -} - -//-------------------------------------------------------------------------- -int pc_debmod_t::finalize_appcall_stack( - call_context_t &, - regval_map_t &, - bytevec_t &stk) -{ - // pc-specific: add endless loop, so user does not execute unwanted code - // after manual appcall. we do not really need to write bpt, - // but it is easy to include it here than skip it. - // previously we reserved 'addrsize' bytes on the stack for this purpose, - // and we use 3 of them. - static const uchar bpt_and_loop[] = { 0xCC, 0xEB, 0xFE }; - stk.append(bpt_and_loop, sizeof(bpt_and_loop)); - return 0; -} - -//-------------------------------------------------------------------------- -bool pc_debmod_t::should_stop_appcall( - thid_t tid, - const debug_event_t *event, - ea_t ea) -{ - if ( inherited::should_stop_appcall(tid, event, ea) ) - return true; - - // Check if the current instruction is a "RET" and then dereferences - // the contents of SP to find the return address. IF it matches, it is - // time to stop - regvals_t regs; - regs.resize(X86_NREGS); - do - { - // Start by reading registers - if ( dbg_read_registers(tid, X86_RC_GENERAL, regs.begin(), NULL) != DRC_OK ) - break; - - // Get the opcodes - uchar opcode; - if ( dbg_read_memory((ea_t)regs[pc_idx].ival, &opcode, 1, NULL) != 1 ) - break; - // Check for "RET" and "RET n" - if ( opcode != 0xC3 && opcode != 0xC2 ) - break; - - // Dereference value at ESP - ea_t at_sp = BADADDR; - if ( dbg_read_memory((ea_t)regs[sp_idx].ival, &at_sp, sizeof(at_sp), NULL) != sizeof(at_sp) ) - break; - return ea == at_sp; // time to stop! - } while ( false ); - return false; -} - -//-------------------------------------------------------------------------- -bool pc_debmod_t::preprocess_appcall_cleanup(thid_t, call_context_t &ctx) -{ - // Linux 2.6.24-19 has a bug(?): - // it doesn't clear trace flag after single-stepping - // so if we single-step and then make an appcall, we would restore eflags with TF set - // but next time we resume the program, kernel thinks that TF was set by the user - // and doesn't clear it, and so our appcall stops immediately - // to prevent that, we'll always clear trace flag before restoring eflags - if ( ctx.saved_regs.size() > sr_idx ) - ctx.saved_regs[sr_idx].ival &= ~0x100; - return true; // success -} - -//-------------------------------------------------------------------------- -void pc_debmod_t::read_fpu_registers( - regval_t *values, - int clsmask, - const void *fptr, - size_t step) -{ - const uchar *vptr = (const uchar *)fptr; - for ( int i=0; i < 8; i++,vptr+=step ) - { - if ( (clsmask & X86_RC_FPU) != 0 ) - { - regval_t *v = &values[R_ST0+i]; - memcpy(v->fval, vptr, 10); //-V512 v->fval underflow - v->rvtype = RVT_FLOAT; - } - if ( (clsmask & X86_RC_MMX) != 0 ) - values[R_MMX0+i].set_bytes(vptr, 8); - } -} - -//-------------------------------------------------------------------------- -const char *pc_debmod_t::get_local_platform() -{ -#ifdef __NT__ -# define LOCAL_PLATFORM "win32" -#else -# ifdef __MAC__ -# define LOCAL_PLATFORM "macosx" -# else -# ifdef __LINUX__ -# define LOCAL_PLATFORM "linux" -# else -# define LOCAL_PLATFORM "PC_UNDEFINED" -# endif -# endif -#endif - return LOCAL_PLATFORM; -} diff --git a/idasdk75/dbg/pc_local_impl.cpp b/idasdk75/dbg/pc_local_impl.cpp deleted file mode 100644 index 0f5cff3..0000000 --- a/idasdk75/dbg/pc_local_impl.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// x86-specific code (compiled only on IDA side, never on the server side) - -#include -#include "pc_regs.hpp" -#include "deb_pc.hpp" - -//-------------------------------------------------------------------------- -// -// DEBUGGER REGISTER AND INSTRUCTION INFORMATIONS -// -//-------------------------------------------------------------------------- - -//-------------------------------------------------------------------------- -#if 0 -static void DEBUG_REGVALS(regval_t *values) -{ - for ( int i = 0; i < qnumber(registers); i++ ) - { - msg("%s = ", registers[i].name); - switch ( registers[i].dtyp ) - { - case dt_qword: msg("%016LX\n", values[i].ival); break; - case dt_dword: msg("%08X\n", values[i].ival); break; - case dt_word: msg("%04X\n", values[i].ival); break; - case dt_tbyte: - for ( int j = 0; j < sizeof(regval_t); j++ ) - { - if ( j == 10 ) - msg(" - "); // higher bytes are not used by x86 floats - msg("%02X ", ((unsigned char*)&values[i])[j]); - } - // msg("%02X ", (unsigned short)values[i].fval[j]); - msg("\n"); - break; - } - } - msg("\n"); -} -#endif - -//-------------------------------------------------------------------------- -drc_t idaapi x86_read_registers( - thid_t thread_id, - int clsmask, - regval_t *values, - qstring *errbuf) -{ - drc_t drc = s_read_registers(thread_id, clsmask, values, errbuf); - if ( drc == DRC_OK ) - { - // FPU related registers - if ( (clsmask & X86_RC_FPU) != 0 ) - { - for ( size_t i = 0; i < debugger.nregs; i++ ) - { - const register_info_t &ri = debugger.regs(i); - if ( ri.register_class == X86_RC_FPU && ri.dtype == dt_tbyte ) - { - int rc = processor_t::realcvt(values[i].fval, values[i].fval, 004); // // load long double - if ( rc == 0 ) - break; // realcvt not implemented - else if ( rc < 0 ) // error - memset(values[i].fval, 0, sizeof(values[i].fval)); - } - } - } - } - return drc; -} - -//-------------------------------------------------------------------------- -drc_t idaapi x86_write_register( - thid_t thread_id, - int reg_idx, - const regval_t *value, - qstring *errbuf) -{ - regval_t rv = *value; - // FPU related registers - const register_info_t &ri = debugger.regs(reg_idx); - if ( ri.register_class == X86_RC_FPU && ri.dtype == dt_tbyte ) - { - uchar fn[10]; - int code = processor_t::realcvt(fn, rv.fval, 014); // store long double //-V536 octal - if ( code == 1 ) - memcpy(rv.fval, fn, 10); //-V512 rv.fval underflow - } - return s_write_register(thread_id, reg_idx, &rv, errbuf); -} - -//-------------------------------------------------------------------------- -int is_x86_valid_bpt(bpttype_t type, ea_t ea, int len) -{ - if ( type != BPT_SOFT ) - { - if ( (debugger.flags & DBG_FLAG_ANYSIZE_HWBPT) == 0 ) - return check_x86_hwbpt(type, ea, len); - - if ( type == 0 ) - return BPT_BAD_TYPE; - } - return BPT_OK; -} - -//-------------------------------------------------------------------------- -void processor_specific_init(void) -{ -} - -//-------------------------------------------------------------------------- -void processor_specific_term(void) -{ -} diff --git a/idasdk75/dbg/rpc_debmod.h b/idasdk75/dbg/rpc_debmod.h deleted file mode 100644 index 04f7144..0000000 --- a/idasdk75/dbg/rpc_debmod.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef __RPC_DEBUGGER_MODULE__ -#define __RPC_DEBUGGER_MODULE__ - -#include "debmod.h" -#include "dbg_rpc_client.h" - -//--------------------------------------------------------------------------- -class rpc_debmod_t - : public debmod_t, - public dbg_rpc_client_t -{ - drc_t process_start_or_attach(bytevec_t &req, qstring *errbuf); - -public: - rpc_debmod_t(const char *default_platform = NULL); - virtual bool idaapi open_remote(const char *hostname, int port_number, const char *password, qstring *errbuf) newapi; - drc_t close_remote(); - - int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) - { - return rpc_engine_t::send_ioctl(fn, buf, size, poutbuf, poutsize); - } - - //-------------------------------------------------------------------------- - inline int getint(ushort code) - { - bytevec_t req = prepare_rpc_packet((uchar)code); - return send_request_get_long_result(req); - } - drc_t get_drc_int(uchar code, int x) - { - bytevec_t req = prepare_rpc_packet(code); - req.pack_dd(x); - return send_request_get_drc_result(req, NULL); - } - inline drc_t get_drc(ushort code, qstring *errbuf=NULL) - { - bytevec_t req = prepare_rpc_packet((uchar)code); - return send_request_get_drc_result(req, errbuf); - } - - // - virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; - virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; - virtual void idaapi dbg_term(void) override; - virtual drc_t idaapi dbg_get_processes(procinfo_vec_t *procs, qstring *errbuf) override; - virtual drc_t idaapi dbg_detach_process(void) override; - virtual drc_t idaapi dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) override; - virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; - virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) override; - virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; - virtual void idaapi dbg_set_exception_info(const exception_info_t *info, int qty) override; - virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) override; - virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; - virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; - virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; - virtual drc_t idaapi dbg_read_registers( - thid_t thread_id, - int clsmask, - regval_t *values, - qstring *errbuf) override; - virtual drc_t idaapi dbg_write_register( - thid_t thread_id, - int reg_idx, - const regval_t *value, - qstring *errbuf) override; - virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) override; - virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &areas, qstring *errbuf) override; - virtual int idaapi dbg_get_scattered_image(scattered_image_t &si, ea_t base) override; - virtual bool idaapi dbg_get_image_uuid(bytevec_t *uuid, ea_t base) override; - virtual ea_t idaapi dbg_get_segm_start(ea_t base, const qstring &segname) override; - virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; - virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; - virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) override; - virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; - virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; - virtual drc_t idaapi dbg_update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf) override; - virtual drc_t idaapi dbg_update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf) override; - virtual drc_t idaapi dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf) override; - virtual int idaapi dbg_open_file(const char *file, uint64 *fsize, bool readonly) override; - virtual void idaapi dbg_close_file(int fn) override; - virtual ssize_t idaapi dbg_read_file(int fn, qoff64_t off, void *buf, size_t size) override; - virtual ssize_t idaapi dbg_write_file(int fn, qoff64_t off, const void *buf, size_t size) override; - virtual int idaapi handle_ioctl(int fn, const void *buf, size_t size, void **outbuf, ssize_t *outsize) override; - virtual int idaapi get_system_specific_errno(void) const override; - virtual drc_t idaapi dbg_update_call_stack(thid_t, call_stack_t *) override; - virtual ea_t idaapi dbg_appcall( - ea_t func_ea, - thid_t tid, - int stkarg_nbytes, - const struct regobjs_t *regargs, - struct relobj_t *stkargs, - struct regobjs_t *retregs, - qstring *errbuf, - debug_event_t *event, - int flags) override; - virtual drc_t idaapi dbg_cleanup_appcall(thid_t tid) override; - virtual int get_regidx(const char *, int *) override { INTERR(30116); } - virtual int idaapi dbg_rexec(const char *cmdline) override; - virtual drc_t idaapi dbg_bin_search( - ea_t *ea, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &ptns, - int srch_flags, - qstring *errbuf) override; -}; - -#endif diff --git a/idasdk75/dbg/server.cpp b/idasdk75/dbg/server.cpp deleted file mode 100644 index 055adcc..0000000 --- a/idasdk75/dbg/server.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - IDA remote debugger server -*/ - -#ifdef _WIN32 -// We use the deprecated inet_ntoa() function for Windows XP compatibility. -//lint -e750 local macro '' not referenced -#define _WINSOCK_DEPRECATED_NO_WARNINGS -#endif - -#include - -#include "server.h" - -// Provide dummy versions for tinfo copy/clear. Debugger servers do not use them -#if !defined(__NT__) -void ida_export copy_tinfo_t(tinfo_t *, const tinfo_t &) {} -void ida_export clear_tinfo_t(tinfo_t *) {} -#endif - -// We don't have a kernel. Provide envvar-based debug file directory retrieval. -#if defined(__LINUX__) -static bool _elf_debug_file_directory_resolved = false; -static qstring _elf_debug_file_directory; -idaman const char *ida_export get_elf_debug_file_directory() -{ - if ( !_elf_debug_file_directory_resolved ) - { - if ( !qgetenv("DEBUG_FILE_DIRECTORY", &_elf_debug_file_directory) ) - qgetenv("ELF_DEBUG_FILE_DIRECTORY", &_elf_debug_file_directory); - if ( _elf_debug_file_directory.empty() ) - _elf_debug_file_directory = "/usr/lib/debug"; - _elf_debug_file_directory_resolved = true; - } - return _elf_debug_file_directory.c_str(); -} - -//------------------------------------------------------------------------- -#ifdef TESTABLE_BUILD -static std::map _pid_elf_debug_file_directories; -void set_elf_debug_file_directory_for_pid(int pid, const char *path) -{ - _pid_elf_debug_file_directories[pid] = path; -} - -//------------------------------------------------------------------------- -const char *get_elf_debug_file_directory_for_pid(int pid) -{ - const char *found = NULL; - std::map::const_iterator it = _pid_elf_debug_file_directories.find(pid); - if ( it != _pid_elf_debug_file_directories.end() ) - found = it->second.begin(); - else - found = get_elf_debug_file_directory(); - return found; -} -#endif -#endif - -//lint -esym(714, dump_udt) not referenced -void dump_udt(const char *, const struct udt_type_data_t &) {} - - -//-------------------------------------------------------------------------- -// SERVER GLOBAL VARIABLES -#ifdef __SINGLE_THREADED_SERVER__ -dbgsrv_dispatcher_t dispatcher(false); - -static bool init_lock(void) { return true; } -bool lock_begin(void) { return true; } -bool lock_end(void) { return true; } -#else -dbgsrv_dispatcher_t dispatcher(true); - -static qmutex_t g_mutex = NULL; -static bool init_lock(void) { g_mutex = qmutex_create(); return g_mutex != NULL; } -bool lock_begin(void) { return qmutex_lock(g_mutex); } -bool lock_end(void) { return qmutex_unlock(g_mutex); } -#endif - -//-------------------------------------------------------------------------- -dbg_rpc_handler_t *g_global_server = NULL; - -//-------------------------------------------------------------------------- -// perform an action (func) on all debuggers -int for_all_debuggers(debmod_visitor_t &v) -{ - int code = 0; - dispatcher.clients_list->lock(); - { - client_handlers_list_t::storage_t::iterator it; - for ( it = dispatcher.clients_list->storage.begin(); - it != dispatcher.clients_list->storage.end(); - ++it ) - { - dbg_rpc_handler_t *h = (dbg_rpc_handler_t *) it->first; - code = v.visit(h->get_debugger_instance()); - if ( code != 0 ) - break; - } - } - dispatcher.clients_list->unlock(); - return code; -} - -//------------------------------------------------------------------------- -dbgsrv_dispatcher_t::dbgsrv_dispatcher_t(bool multi_threaded) - : base_dispatcher_t(multi_threaded), - broken_conns_supported(false), - on_broken_conn(BCH_DEFAULT) -{ - port_number = DEBUGGER_PORT_NUMBER; -} - -//------------------------------------------------------------------------- -void dbgsrv_dispatcher_t::collect_cliopts(cliopts_t *out) -{ - struct ida_local ns_t - { - static void _set_dpassword(const char *value, void *ud) - { - ((dbgsrv_dispatcher_t *) ud)->server_password = value; - } - static void _set_broken_connections_keep_debmod(const char *, void *ud) - { - ((dbgsrv_dispatcher_t *) ud)->on_broken_conn = BCH_KEEP_DEBMOD; - } - static void _set_closing_session_kill_debuggee(const char *, void *ud) - { - ((dbgsrv_dispatcher_t *) ud)->on_broken_conn = BCH_KILL_PROCESS; - } - }; - - static const cliopt_t cliopts[] = - { - { 'P', "password", "Password", ns_t::_set_dpassword, 1 }, - }; - // the following options are valid only if broken connections are supported - static const cliopt_t bc_cliopts[] = - { - { - 'k', - "on-broken-connection-keep-session", - "Keep debugger session alive when connection breaks", - ns_t::_set_broken_connections_keep_debmod, - 0, - }, - { - 'K', - "on-stop-kill-process", - "Kill debuggee when closing session", - ns_t::_set_closing_session_kill_debuggee, - 0, - }, - }; - - base_dispatcher_t::collect_cliopts(out); - for ( size_t i = 0; i < qnumber(cliopts); ++i ) - out->push_back(cliopts[i]); - - if ( broken_conns_supported ) - for ( size_t i = 0; i < qnumber(bc_cliopts); ++i ) - out->push_back(bc_cliopts[i]); -} - -//------------------------------------------------------------------------- -client_handler_t *dbgsrv_dispatcher_t::new_client_handler(idarpc_stream_t *_irs) -{ - dbg_rpc_handler_t *h = new dbg_rpc_handler_t(_irs, this); - h->verbose = verbose; - void *params = NULL; -#if defined(__LINUX__) && defined(TESTABLE_BUILD) - params = (void *) get_elf_debug_file_directory_for_pid; //lint !e611 cast between pointer to function type '' and pointer to object type 'void *' -#endif - h->set_debugger_instance(create_debug_session(params)); - g_global_server = h; - return h; -} - -//------------------------------------------------------------------------- -void dbgsrv_dispatcher_t::shutdown_gracefully(int signum) -{ - base_dispatcher_t::shutdown_gracefully(signum); - term_subsystem(); -} - - -//-------------------------------------------------------------------------- -// debugger remote server - TCP/IP mode -int NT_CDECL main(int argc, const char *argv[]) -{ -#ifdef ENABLE_LOWCNDS - init_idc(); -#endif - - // call the debugger module to initialize its subsystem once - if ( !init_lock() || !init_subsystem() ) - { - lprintf("Could not initialize subsystem!"); - return -1; - } - - qstring password; - if ( qgetenv("IDA_DBGSRV_PASSWD", &password) ) - dispatcher.server_password = password; - - int ida_major = IDA_SDK_VERSION / 100; -#if (IDA_SDK_VERSION % 10) == 0 - int ida_minor = (IDA_SDK_VERSION % 100)/10; //740 -> 4 -#else - int ida_minor = IDA_SDK_VERSION % 100; //741 -> 41 -#endif - - lprintf("IDA " SYSTEM SYSBITS " remote debug server(" __SERVER_TYPE__ ") " - "v%d.%d.%d. Hex-Rays (c) 2004-2020\n", - ida_major, ida_minor, IDD_INTERFACE_VERSION); - - dispatcher.broken_conns_supported = debmod_t::reuse_broken_connections; - cliopts_t cliopts(lprintf); - dispatcher.collect_cliopts(&cliopts); - cliopts.apply(argc, argv, &dispatcher); - dispatcher.install_signal_handlers(); - dispatcher.dispatch(); -} diff --git a/idasdk75/dbg/server.h b/idasdk75/dbg/server.h deleted file mode 100644 index 6855243..0000000 --- a/idasdk75/dbg/server.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SERVER_H -#define SERVER_H - -#include - -#ifdef __NT__ -//# ifndef SIGHUP -//# define SIGHUP 1 -//# endif -# define DEBUGGER_ID DEBUGGER_ID_X86_IA32_WIN32_USER -#else // not NT, i.e. UNIX -# if defined(__LINUX__) -# if defined(__ARM__) -# define DEBUGGER_ID DEBUGGER_ID_ARM_LINUX_USER -# else -# define DEBUGGER_ID DEBUGGER_ID_X86_IA32_LINUX_USER -# endif -# elif defined(__MAC__) -# define DEBUGGER_ID DEBUGGER_ID_X86_IA32_MACOSX_USER -# endif -# include -# include -#endif // !__NT__ - -enum broken_conn_hndl_t -{ - BCH_DEFAULT, - BCH_KEEP_DEBMOD, - BCH_KILL_PROCESS, -}; - -struct dbgsrv_dispatcher_t : public base_dispatcher_t -{ - qstring server_password; - bool broken_conns_supported; - broken_conn_hndl_t on_broken_conn; - - dbgsrv_dispatcher_t(bool multi_threaded); - - virtual void collect_cliopts(cliopts_t *out) override; - virtual client_handler_t *new_client_handler(idarpc_stream_t *irs) override; - - virtual void shutdown_gracefully(int signum) override; -}; - -#include "debmod.h" -#include "dbg_rpc_hlp.h" -#include "dbg_rpc_handler.h" - -// // sizeof(ea_t)==8 and sizeof(size_t)==4 servers cannot be used to debug 64-bit -// // applications. but to debug 32-bit applications, simple 32-bit servers -// // are enough and can work with both 32-bit and 64-bit versions of ida. -// // so, there is no need to build sizeof(ea_t)==8 and sizeof(size_t)==4 servers -// #if defined(__EA64__) == defined(__X86__) -// #error "Mixed mode servers do not make sense, they should not be compiled" -// #endif - -#endif diff --git a/idasdk75/dbg/win32/makefile b/idasdk75/dbg/win32/makefile deleted file mode 100644 index bf8d2eb..0000000 --- a/idasdk75/dbg/win32/makefile +++ /dev/null @@ -1,174 +0,0 @@ -include ../../allmake.mak - -GOALS-$(BUILD_IDA) += modules # target in $(IDA)module.mak -GOALS-$(BUILD_DBGSRV) += server # target in $(IDA)dbg/server.mak -.PHONY: $(GOALS-1) -all: $(GOALS-1) - -#---------------------------------------------------------------------- -ifdef __NT__ - ifndef __X86__ - SERVER = win64_remote$(B) - else - SERVER = win32_remote$(B) - endif -endif -ifdef SERVER - SERVERS += $(call server_exe,$(SERVER)) -endif - -#---------------------------------------------------------------------- -STUB = $(call module_dll,win32_stub) -ifdef BUILD_IDA - MODULES += $(STUB) -endif - -#---------------------------------------------------------------------- -USER = $(call module_dll,win32_user) -ifeq ($(and $(BUILD_IDA),$(__NT__)),1) - MODULES += $(USER) -endif - -#---------------------------------------------------------------------- -# we explicitly added our module targets -NO_DEFAULT_TARGETS = 1 - -# NOTE: all MODULES must be defined before including plugin.mak. -include ../plugin.mak -# NOTE: target-specific rules and dependencies that use variable -# expansion to name the target (such as "$(MODULE): [...]") must -# come after including plugin.mak - -#---------------------------------------------------------------------- -# select OBJS common to user plugin and debugger server -BASE_OBJS-$(__NT__) += $(F)win32_debmod$(O) -BASE_OBJS-$(__NT__) += $(F)win32_util$(O) -BASE_OBJS-$(__NT__) += $(F)winbase_debmod$(O) -BASE_OBJS += $(BASE_OBJS-1) - -#---------------------------------------------------------------------- -SERVER_OBJS += $(F)win32_server$(O) -SERVER_OBJS += $(F)tilfuncs$(O) -SERVER_OBJS += $(BASE_OBJS) - -SERVER_STDLIBS += ole32.lib -SERVER_STDLIBS += oleaut32.lib - -include ../server.mak - -#---------------------------------------------------------------------- -STUB_OBJS += $(F)win32_stub$(O) -STUB_OBJS += $(F)w32sehch$(O) -$(STUB): MODULE_OBJS += $(STUB_OBJS) -$(STUB): $(STUB_OBJS) - -#---------------------------------------------------------------------- -USER_OBJS += $(F)win32_user$(O) -USER_OBJS += $(F)w32sehch$(O) -USER_OBJS += $(BASE_OBJS) -$(USER): MODULE_OBJS += $(USER_OBJS) -$(USER): $(USER_OBJS) -$(USER): STDLIBS += user32.lib - -#---------------------------------------------------------------------- -include $(IDA)objdir.mak - -# MAKEDEP dependency list ------------------ -$(F)tilfuncs$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)diskio.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)ins/pc.hpp $(I)intel.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)network.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/pe/cor.h ../../ldr/pe/corerror.h \ - ../../ldr/pe/corhdr.h ../../ldr/pe/mycor.h \ - ../../ldr/pe/pe.h ../../plugins/pdb/common.cpp \ - ../../plugins/pdb/cvconst.h ../../plugins/pdb/dbghelp.h \ - ../../plugins/pdb/dia2.h ../../plugins/pdb/idaaccess.hpp \ - ../../plugins/pdb/msdia.cpp ../../plugins/pdb/msdia.hpp \ - ../../plugins/pdb/pdb.hpp \ - ../../plugins/pdb/pdbaccess.hpp \ - ../../plugins/pdb/pdbida.hpp \ - ../../plugins/pdb/pdblocal.cpp \ - ../../plugins/pdb/pdblocal.hpp \ - ../../plugins/pdb/varser.hpp ../debmod.h tilfuncs.cpp \ - tilfuncs.hpp -$(F)w32sehch$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp w32sehch.cpp w32sehch.h -$(F)win32_debmod$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)dbg.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)err.h $(I)exehdr.h $(I)fixup.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)offset.hpp $(I)pro.h $(I)prodir.h \ - $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ - $(I)xref.hpp ../../ldr/pe/../idaldr.h \ - ../../ldr/pe/common.cpp ../../ldr/pe/common.h \ - ../../ldr/pe/pe.h ../dbg_pe_hlp.cpp ../deb_pc.hpp \ - ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ - win32_debmod.cpp win32_debmod.h win32_debmod_impl.cpp \ - win32_rpc.h win32_undoc.h win32_util.hpp \ - winbase_debmod.h -$(F)win32_server$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/pe/cor.h ../../ldr/pe/corerror.h \ - ../../ldr/pe/corhdr.h ../../ldr/pe/mycor.h \ - ../../ldr/pe/pe.h ../../plugins/pdb/cvconst.h \ - ../../plugins/pdb/dia2.h ../../plugins/pdb/idaaccess.hpp \ - ../../plugins/pdb/msdia.hpp ../../plugins/pdb/pdb.hpp \ - ../../plugins/pdb/pdbaccess.hpp \ - ../../plugins/pdb/pdbida.hpp \ - ../../plugins/pdb/pdblocal.hpp ../dbg_rpc_hlp.h \ - ../deb_pc.hpp ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ - tilfuncs.hpp win32_debmod.h win32_rpc.h win32_server.cpp \ - win32_util.hpp winbase_debmod.h -$(F)win32_stub$(O): $(I)../ldr/pe/pe.h $(I)../plugins/pdb/pdb.hpp \ - $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/pe/pe.h ../common_local_impl.cpp \ - ../common_stub_impl.cpp ../dbg_rpc_client.h \ - ../dbg_rpc_engine.h ../dbg_rpc_hlp.h ../deb_pc.hpp \ - ../debmod.h ../pc_local_impl.cpp ../pc_regs.hpp \ - ../rpc_debmod.h w32sehch.h win32_local_impl.cpp \ - win32_rpc.h win32_stub.cpp -$(F)win32_user$(O): $(I)../ldr/pe/pe.h $(I)../plugins/pdb/pdb.hpp \ - $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/pe/pe.h ../common_local_impl.cpp \ - ../common_stub_impl.cpp ../dbg_rpc_hlp.h ../deb_pc.hpp \ - ../debmod.h ../pc_debmod.h ../pc_local_impl.cpp \ - ../pc_regs.hpp w32sehch.h win32_debmod.h \ - win32_local_impl.cpp win32_rpc.h win32_server_stub.cpp \ - win32_user.cpp win32_util.hpp winbase_debmod.h -$(F)win32_util$(O): $(I)bytes.hpp $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../deb_pc.hpp ../debmod.h \ - ../pc_debmod.h ../pc_regs.hpp win32_util.cpp \ - win32_util.hpp winbase_debmod.h -$(F)winbase_debmod$(O): $(I)bytes.hpp $(I)ida.hpp $(I)idd.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)network.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../deb_pc.hpp \ - ../debmod.h ../pc_debmod.h ../pc_regs.hpp win32_util.hpp \ - winbase_debmod.cpp winbase_debmod.h diff --git a/idasdk75/dbg/win32/w32sehch.cpp b/idasdk75/dbg/win32/w32sehch.cpp deleted file mode 100644 index 1346456..0000000 --- a/idasdk75/dbg/win32/w32sehch.cpp +++ /dev/null @@ -1,256 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include "w32sehch.h" - -static int req_id = -1; - -//------------------------------------------------------------------------- -// non-modal exception handler chooser -struct x86seh_chooser_t : public chooser_t -{ -protected: - thid_t tid; - qvector list; //lint !e958 padding is required to align members - qstring title_; - - static const int widths_[]; - static const char *const header_[]; - enum { ICON = 144 }; - -public: - // this object must be allocated using `new` - x86seh_chooser_t(thid_t tid); - virtual ~x86seh_chooser_t() - { - unhook_from_notification_point( - HT_DBG, - dbg_handler, const_cast(title)); - } - ssize_t choose(uint32 addr = uint32(-1)) //lint !e1511 member hides non-virtual member - { - return ::choose(this, &addr); - } - - virtual const void *get_obj_id(size_t *len) const override - { - *len = sizeof(tid); - return &tid; - } - - virtual size_t idaapi get_count() const override { return list.size(); } - virtual void idaapi get_row( - qstrvec_t *cols, - int *icon_, - chooser_item_attrs_t *attrs, - size_t n) const override; - virtual cbret_t idaapi enter(size_t n) override; - - // calculate the location of the item, - // `item_data` is a pointer to a 32-bit address - virtual ssize_t idaapi get_item_index(const void *item_data) const override; - virtual bool idaapi init() override; - virtual cbret_t idaapi refresh(ssize_t n) override; - -protected: - static ssize_t idaapi dbg_handler(void *ud, int notif_code, va_list va); -}; - -//------------------------------------------------------------------------- -const int x86seh_chooser_t::widths_[] = -{ - CHCOL_HEX | 10, // Address - 30, // Name -}; -const char *const x86seh_chooser_t::header_[] = -{ - "Address", // 0 - "Name", // 1 -}; - -//------------------------------------------------------------------------- -inline x86seh_chooser_t::x86seh_chooser_t(thid_t tid_) - : chooser_t(CH_NOBTNS | CH_FORCE_DEFAULT | CH_CAN_REFRESH, - qnumber(widths_), widths_, header_), - tid(tid_), - list() -{ - title_.sprnt("[%04X] - Structured exception handlers list", tid); - title = title_.c_str(); - CASSERT(qnumber(widths_) == qnumber(header_)); - icon = ICON; - - hook_to_notification_point( - HT_DBG, - dbg_handler, const_cast(title)); -} - -//------------------------------------------------------------------------- -void idaapi x86seh_chooser_t::get_row( - qstrvec_t *cols_, - int *, - chooser_item_attrs_t *, - size_t n) const -{ - // assert: n < list.size() - uint32 addr = list[n]; - - qstrvec_t &cols = *cols_; - cols[0].sprnt("%08X", addr); - get_nice_colored_name(&cols[1], addr, GNCN_NOCOLOR | GNCN_NOLABEL); - CASSERT(qnumber(header_) == 2); -} - -//------------------------------------------------------------------------- -chooser_t::cbret_t idaapi x86seh_chooser_t::enter(size_t n) -{ - // assert: n < list.size() - ea_t ea = ea_t(list[n]); - if ( !is_code(get_flags(ea)) ) - create_insn(ea); - jumpto(ea); - return cbret_t(); // nothing changed -} - -//------------------------------------------------------------------------ -ssize_t idaapi x86seh_chooser_t::get_item_index(const void *item_data) const -{ - if ( list.empty() ) - return NO_SELECTION; - - // `item_data` is a pointer to a 32-bit address - uint32 item_addr = *(const uint32 *)item_data; - if ( item_addr == uint32(-1) ) - return 0; // first item by default - - // find `item_script` in the list - const uint32 *p = list.find(item_addr); - if ( p != list.end() ) - return p - list.begin(); - return 0; // first item by default -} - -//-------------------------------------------------------------------------- -bool idaapi x86seh_chooser_t::init() -{ - // rebuild the handlers list - uint64 fs_sel; - ea_t fs_base; - uint32 excr_ea; - list.clear(); - if ( !get_reg_val("fs", &fs_sel) - || internal_get_sreg_base(&fs_base, tid, int(fs_sel)) <= DRC_NONE - || read_dbg_memory(fs_base, &excr_ea, sizeof(excr_ea)) != sizeof(excr_ea) ) - { - warning("Failed to build the SEH list for thread %08X", tid); - return false; // do not show the empty chooser - } - - struct EXC_REG_RECORD - { - uint32 p_prev; - uint32 p_handler; - }; - EXC_REG_RECORD rec; - std::set seen; - while ( excr_ea != 0xffffffff ) - { - if ( read_dbg_memory(excr_ea, &rec, sizeof(rec)) != sizeof(rec) ) - break; - - if ( !seen.insert(excr_ea).second ) - { - msg("Circular SEH record has been detected\n"); - break; - } - - list.push_back(rec.p_handler); - excr_ea = rec.p_prev; - } - return true; -} - -//------------------------------------------------------------------------ -chooser_t::cbret_t idaapi x86seh_chooser_t::refresh(ssize_t n) -{ - uint32 item_addr = uint32(-1); - if ( n >= 0 && n < list.size() ) - item_addr = list[n]; // remember the currently selected handler - - init(); - - if ( n < 0 ) - return NO_SELECTION; - ssize_t idx = get_item_index(&item_addr); - // no need to adjust `idx` as get_item_index() returns first item by - // default - return idx; -} - -//------------------------------------------------------------------------- -ssize_t idaapi x86seh_chooser_t::dbg_handler(void *ud, int code, va_list) -{ - if ( code == dbg_suspend_process ) - { - const char *ttl = static_cast(ud); - refresh_chooser(ttl); - } - return 0; -} - - -//------------------------------------------------------------------------- -struct show_window_ah_t : public action_handler_t -{ - virtual int idaapi activate(action_activation_ctx_t *) override - { - thid_t tid = get_current_thread(); - x86seh_chooser_t *ch = new x86seh_chooser_t(tid); - return ch->choose() == 0; - } //lint !e429 Custodial pointer 'ch' has not been freed or returned - - virtual action_state_t idaapi update(action_update_ctx_t *) override - { - return AST_ENABLE; - } -}; -static show_window_ah_t show_window_ah; - - -//--------------------------------------------------------------------------- -void remove_x86seh_menu() -{ - if ( req_id != -1 ) - { - cancel_exec_request(req_id); - req_id = -1; - } -} - -//--------------------------------------------------------------------------- -void install_x86seh_menu() -{ - // HACK: We queue this request because commdbg apparently enables the debug menus - // just after calling init_debugger(). - struct uireq_install_menu_t: public ui_request_t - { - virtual bool idaapi run() override - { - if ( !inf_is_64bit() ) - { - register_and_attach_to_menu( - "Debugger/Debugger windows/Stack trace", - "dbg:sehList", "SEH list", NULL, SETMENU_APP, - &show_window_ah, - &PLUGIN, - ADF_OT_PLUGIN); - } - req_id = -1; - return false; - } - }; - req_id = execute_ui_requests(new uireq_install_menu_t, NULL); -} diff --git a/idasdk75/dbg/win32/win32_debmod.cpp b/idasdk75/dbg/win32/win32_debmod.cpp deleted file mode 100644 index d4c557e..0000000 --- a/idasdk75/dbg/win32/win32_debmod.cpp +++ /dev/null @@ -1,3330 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "win32_debmod.h" - -//-------------------------------------------------------------------------- - -#ifndef TH32CS_SNAPNOHEAPS - #define TH32CS_SNAPNOHEAPS 0x0 -#endif -#include "win32_debmod_impl.cpp" -#define get_reg_class(reg_idx) x86_get_regclass(reg_idx) - -typedef HANDLE WINAPI OpenThread_t(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId); -static OpenThread_t *_OpenThread = NULL; -typedef HRESULT WINAPI GetThreadDescription_t(HANDLE hThread, PWSTR *threadDescription); -static GetThreadDescription_t *_GetThreadDescription = NULL; - -#ifndef __X86__ -typedef BOOL WINAPI Wow64GetThreadContext_t(HANDLE hThread, PWOW64_CONTEXT lpContext); -typedef BOOL WINAPI Wow64SetThreadContext_t(HANDLE hThread, const WOW64_CONTEXT *lpContext); -typedef BOOL WINAPI Wow64GetThreadSelectorEntry_t(HANDLE hThread, DWORD dwSelector, PWOW64_LDT_ENTRY lpSelectorEntry); -static Wow64GetThreadContext_t *_Wow64GetThreadContext = NULL; -static Wow64SetThreadContext_t *_Wow64SetThreadContext = NULL; -static Wow64GetThreadSelectorEntry_t *_Wow64GetThreadSelectorEntry = NULL; -#endif - -// Older SDKs (such as the one used for the ..._opt_s debug servers) -// requires these defines -#ifndef XSTATE_MASK_AVX -# define XSTATE_MASK_AVX (XSTATE_MASK_GSSE) -#endif // XSTATE_MASK_AVX -#ifndef XSTATE_AVX -# define XSTATE_AVX (XSTATE_GSSE) -#endif // XSTATE_AVX - -#define I386_AVX_NREGS 8 -#define CONTEXT_XSTATE_BIT 0x40 - -// https://docs.microsoft.com/en-us/windows/desktop/debug/working-with-xstate-context -// The definition of CONTEXT_XSTATE changed across SDKs. On older SDKs, where it would -// have another value, it wasn't usable anyway, so it's safe to undefine & re-define it. -#ifdef CONTEXT_XSTATE -# if ((CONTEXT_XSTATE & CONTEXT_XSTATE_BIT) == 0) -# undef CONTEXT_XSTATE -# if defined(_M_X64) -# define CONTEXT_XSTATE (0x00100040) -# else -# define CONTEXT_XSTATE (0x00010040) -# endif -# endif -#endif - -//------------------------------------------------------------------------- -// https://docs.microsoft.com/en-us/windows/desktop/debug/working-with-xstate-context -bool context_helper_t::create_context(context_holder_t *out, int *_ctxflags) -{ - out->buffer.qclear(); - out->buffer.clear(); - int ctxsz = sizeof(CONTEXT); -#define CONTEXT_REQUIRES_XSTATE() ((*_ctxflags & CONTEXT_XSTATE_BIT) == CONTEXT_XSTATE_BIT) - if ( CONTEXT_REQUIRES_XSTATE() && !get_xstate_context_size(&ctxsz) ) - *_ctxflags &= ~CONTEXT_XSTATE_BIT; - out->buffer.resize(ctxsz); - if ( CONTEXT_REQUIRES_XSTATE() ) - { - if ( pfnInitializeContext( - out->buffer.begin(), - *_ctxflags, - &out->ptr, - (DWORD *) &ctxsz) == FALSE ) - { - return false; - } - - if ( pfnSetXStateFeaturesMask(out->ptr, XSTATE_MASK_AVX) == FALSE ) - return false; - } - else - { - out->ptr = (PCONTEXT) out->buffer.begin(); - out->ptr->ContextFlags = *_ctxflags; - } - return true; -} - -//------------------------------------------------------------------------- -bool context_helper_t::get_xstate_context_size(int *out_ctxsz) -{ - if ( xstate_context_size < 0 ) - { - xstate_context_size = 0; - const char *error = NULL; - - HINSTANCE h = GetModuleHandle(kernel32_dll); - *(FARPROC*) &pfnGetEnabledXStateFeatures = GetProcAddress(h, "GetEnabledXStateFeatures"); - *(FARPROC*) &pfnInitializeContext = GetProcAddress(h, "InitializeContext"); - *(FARPROC*) &pfnGetXStateFeaturesMask = GetProcAddress(h, "GetXStateFeaturesMask"); - *(FARPROC*) &pfnLocateXStateFeature = GetProcAddress(h, "LocateXStateFeature"); - *(FARPROC*) &pfnSetXStateFeaturesMask = GetProcAddress(h, "SetXStateFeaturesMask"); - *(FARPROC*) &pfnCopyContext = GetProcAddress(h, "CopyContext"); - - if ( pfnGetEnabledXStateFeatures != NULL - && pfnInitializeContext != NULL - && pfnGetXStateFeaturesMask != NULL - && pfnLocateXStateFeature != NULL - && pfnSetXStateFeaturesMask != NULL - && pfnCopyContext != NULL ) - { - DWORD64 feature_mask; - feature_mask = pfnGetEnabledXStateFeatures(); - if ( (feature_mask & XSTATE_MASK_AVX) != 0 ) - { - DWORD context_size = 0; - BOOL success = pfnInitializeContext( - NULL, - CONTEXT_ALL | CONTEXT_XSTATE, - NULL, - &context_size); - - if ( (success != FALSE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER) ) - error = "InitializeContext failed"; - else - xstate_context_size = context_size; - } - else - { - error = "AVX feature not enabled"; - } - } - else - { - error = "Couldn't retrieve AVX functions"; - } - - if ( error != NULL ) - msg("%s\n", error); - } - int ctxsz = xstate_context_size; - bool ok = ctxsz > 0; - if ( ok ) - *out_ctxsz = ctxsz; - return ok; -} - -//------------------------------------------------------------------------- -void context_helper_t::clear() -{ - memset(this, 0, sizeof(*this)); - xstate_context_size = -1; -} - -//-------------------------------------------------------------------------- -// Macro to test the DBG_FLAG_DONT_DISTURB flag -#if 0 -#define NODISTURB_ASSERT(x) QASSERT(x) -#else -#define NODISTURB_ASSERT(x) -#endif - -static int g_code = 0; - -//-------------------------------------------------------------------------- -void win32_debmod_t::check_thread(bool must_be_main_thread) const -{ - // remote debugger uses only one thread - if ( rpc != NULL ) - return; - - // someone turned off debthread? - if ( (debugger_flags & DBG_FLAG_DEBTHREAD) == 0 ) - return; - - // local debugger uses 2 threads and we must be in the correct one - QASSERT(30191, is_main_thread() == must_be_main_thread); -} - -//-------------------------------------------------------------------------- -static int utf16_to_utf8(char *buf, size_t bufsize, LPCWSTR unicode) -{ - qstring res; - utf16_utf8(&res, unicode); - qstrncpy(buf, res.c_str(), bufsize); - size_t n = res.length(); - if ( n > bufsize ) - n = bufsize; - return (int)n; -} - -//-------------------------------------------------------------------------- -// try to locate full path of a dll name without full path -// for example, toolhelp.dll -> c:\windows\toolhelp.dll -static bool find_full_path(char *fname, size_t fnamesize, const char *process_path) -{ - if ( fname[0] != '\0' && !qisabspath(fname) ) - { - char path[QMAXPATH]; - char dir[QMAXPATH]; - // check system directory - GetSystemDirectory(dir, sizeof(dir)); - qmakepath(path, sizeof(path), dir, fname, NULL); - if ( qfileexist(path) ) - { -FOUND: - qstrncpy(fname, path, fnamesize); - return true; - } - // check current process directory - if ( process_path[0] != '\0' && !qisabspath(process_path) ) - { - qdirname(dir, sizeof(dir), process_path); - qmakepath(path, sizeof(path), dir, fname, NULL); - if ( qfileexist(path) ) - goto FOUND; - } - // check current directory - if ( GetCurrentDirectory(sizeof(dir), dir) != 0 ) - { - qmakepath(path, sizeof(path), dir, fname, NULL); - if ( qfileexist(path) ) - goto FOUND; - } - return false; - } - return true; -} - -//-------------------------------------------------------------------------- -ssize_t win32_debmod_t::access_memory(eanat_t ea, void *buffer, ssize_t size, bool do_write, bool suspend) -{ - if ( process_handle == INVALID_HANDLE_VALUE ) - return -1; - - NODISTURB_ASSERT(in_event != NULL || exiting); - - // stop all threads before accessing its memory - if ( suspend ) - suspend_all_threads(); - - ea = s0tops(ea); - void *addr = (void *)ea; - - DWORD_PTR size_access = 0; - const DWORD BADPROT = DWORD(-1); - DWORD oldprotect = BADPROT; - bool ok; - - while ( true ) - { - // try to access the memory - - ok = do_write - ? WriteProcessMemory( - process_handle, // handle of the process whose memory is accessed - addr, // address to start access - buffer, // address of buffer - (DWORD)size, // number of bytes to access - (PDWORD_PTR)&size_access) != 0// address of number of bytes accessed - : ReadProcessMemory( - process_handle, // handle of the process whose memory is accessed - addr, // address to start access - buffer, // address of buffer - (DWORD)size, // number of bytes to access - (PDWORD_PTR)&size_access) != 0;// address of number of bytes accessed - - // if we have changed the page protection, revert it - if ( oldprotect != BADPROT ) - { - if ( !VirtualProtectEx( - process_handle, // handle of the process whose memory is accessed - addr, // address to start access - (DWORD)size, // number of bytes to access - oldprotect, - &oldprotect) ) - { - deberr("VirtualProtectEx2(%p)", addr); - } - break; // do not attempt more than once - } - - // bail out after a successful read/write - if ( ok ) - break; - - // bail out if it is not about "not enough access rights" - // *or* ERROR_PARTIAL_COPY as, sometimes we may read/write - // *only* parts of memory because of page breakpoints - int code = GetLastError(); - if ( code != ERROR_NOACCESS && code != ERROR_PARTIAL_COPY ) - { - deberr("%sProcessMemory(%p)", do_write ? "Write" : "Read", ea); - break; - } - - if ( code != ERROR_PARTIAL_COPY ) - size_access = 0; // size_access may be spoiled after failed ReadProcessMemory - - // check if the address is valid - MEMORY_BASIC_INFORMATION meminfo; - if ( !VirtualQueryEx(process_handle, // handle of process - addr, // address of region - &meminfo, // address of information buffer - sizeof(meminfo)) ) // size of buffer - { - size_access = 0; - break; - } - - // allow the desired access on the page - if ( !VirtualProtectEx( - process_handle, // handle of the process whose memory is accessed - addr, // address to start access - (DWORD)size, // number of bytes to access - do_write ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ, - &oldprotect) ) - { - deberr("VirtualProtectEx1(%08p, size=%d for %s)", ea, int(size), do_write ? "write" : "read"); - break; - } - } - - if ( do_write && ok ) - FlushInstructionCache( - process_handle, // handle to process with cache to flush - addr, // pointer to region to flush - (DWORD)size); // length of region to flush - - if ( suspend ) - resume_all_threads(); - return size_access; -} - -//-------------------------------------------------------------------------- -ssize_t win32_debmod_t::_read_memory(eanat_t ea, void *buffer, size_t size, bool suspend) -{ - return access_memory(ea, buffer, size, false, suspend); -} - -ssize_t idaapi win32_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring * /*errbuf*/) -{ - check_thread(false); - return _read_memory(ea, buffer, size, true); -} - -//-------------------------------------------------------------------------- -// Make sure that the thread is suspended -// by calling SuspendThread twice -// If raw=true then SuspendThread() API will be called and we return directly -// without doing any further logic -static void _sure_suspend_thread(thread_info_t &ti, bool raw = false) -{ - HANDLE h = ti.hThread; - - int count = SuspendThread(h); - if ( raw ) - return; - - if ( count != -1 ) - ti.suspend_count++; - - count = SuspendThread(h); - if ( count != -1 ) - ti.suspend_count++; -} - -//-------------------------------------------------------------------------- -// Resume thread by calling ResumeThread as many times as required -// Note: this function just reverts the actions of sure_suspend_thread -// If the thread was already suspended before calling sure_suspend_thread -// then it will stay in the suspended state -// If raw=true then ResumeThread() will be called and we return directly -// without doing any further logic -static void _sure_resume_thread(thread_info_t &ti, bool raw = false) -{ - HANDLE h = ti.hThread; - if ( raw ) - { - ResumeThread(h); - return; - } - - while ( ti.suspend_count > 0 ) - { - ResumeThread(h); - ti.suspend_count--; - } -} - -//-------------------------------------------------------------------------- -inline void win32_debmod_t::suspend_all_threads(bool raw) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - _sure_suspend_thread(p->second, raw); -} - -//-------------------------------------------------------------------------- -inline void win32_debmod_t::resume_all_threads(bool raw) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - _sure_resume_thread(p->second, raw); -} - -//-------------------------------------------------------------------------- -static int get_thread_suspend_count(HANDLE hThread) -{ - DWORD dwSuspendCount = SuspendThread(hThread); - ResumeThread(hThread); - return dwSuspendCount; -} - -//-------------------------------------------------------------------------- -inline void win32_debmod_t::suspend_running_threads(threadvec_t &suspended) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t t = p->second; - t.suspend_count = get_thread_suspend_count(t.hThread); - if ( t.suspend_count == 0 ) - { - _sure_suspend_thread(t); - suspended.push_back(t); - } - } -} - -//-------------------------------------------------------------------------- -inline void win32_debmod_t::resume_suspended_threads(threadvec_t suspended) const -{ - threadvec_t::iterator p; - for ( p = suspended.begin(); p != suspended.end(); ++p ) - _sure_resume_thread(*p); -} - -//-------------------------------------------------------------------------- -size_t win32_debmod_t::add_dll(image_info_t &ii) -{ - dlls.insert(std::make_pair(ii.base, ii)); - dlls_to_import.insert(ii.base); - return (size_t)ii.imagesize; -} - -//-------------------------------------------------------------------------- -// is modname already present in the loaded module list? -bool win32_debmod_t::module_present(const char *modname) -{ - // host process is not added to dlls, so check it first - if ( process_path == modname ) - return true; - - // check DLLs which we already know about - for ( const auto &p : dlls ) - { - const image_info_t &ii = p.second; - if ( ii.name == modname ) - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -// iterate all modules of the specified process -// until the callback returns != 0 -int win32_debmod_t::for_each_module(DWORD _pid, module_cb_t module_cb, void *ud) -{ - int code = 0; - - module_snapshot_t msnap(get_tool_help()); - MODULEENTRY32 me; - for ( bool ok = msnap.first(TH32CS_SNAPNOHEAPS, _pid, &me); ok; ok = msnap.next(&me) ) - { - code = module_cb(this, &me, ud); - if ( code != 0 ) - break; - } - return code; -} - -//-------------------------------------------------------------------------- -// callback: get info about the main module of the debugger process -//lint -e{818} -int win32_debmod_t::get_dmi_cb(debmod_t *sess, MODULEENTRY32 *me32, void *ud) -{ - win32_debmod_t *_this = (win32_debmod_t *)sess; - // if the module name doesn't correspond to the process name, - // we continue to iterate - char buf[QMAXPATH]; - tchar_utf8(buf, me32->szModule, sizeof(buf)); - if ( !_this->process_path.empty() && stricmp(buf, qbasename(_this->process_path.c_str())) != 0 ) - return 0; - - // ok, this module corresponds to our debugged process - modinfo_t &dmi = *(modinfo_t *)ud; - dmi.name = _this->process_path; - dmi.base = EA_T(me32->modBaseAddr); - dmi.size = (asize_t)me32->modBaseSize; - return 1; // we stop to iterate -} - -//-------------------------------------------------------------------------- -// Return module information on the currently debugged process -void win32_debmod_t::get_debugged_module_info(modinfo_t *dmi) -{ - dmi->name[0] = '\0'; - dmi->base = BADADDR; - dmi->size = 0; - dmi->rebase_to = BADADDR; - for_each_module(pid, get_dmi_cb, dmi); -} - -//-------------------------------------------------------------------------- -void idaapi win32_debmod_t::dbg_stopped_at_debug_event( - import_infos_t *, - bool dlls_added, - thread_name_vec_t *thr_names) -{ - if ( dlls_added ) - { - check_thread(true); - // we will take advantage of this event to import information - // about the exported functions from the loaded dlls and the - // binary itself - name_info_t &ni = *get_debug_names(); - if ( !binary_to_import.name.empty() ) - { - const char *bin_path = binary_to_import.name.c_str(); - linput_t *li = open_linput(bin_path, false); - if ( li != NULL ) - { - get_pe_exports_from_path(bin_path, li, binary_to_import.base, ni); - close_linput(li); - } - binary_to_import.name.clear(); - } - - for ( easet_t::iterator p = dlls_to_import.begin(); p != dlls_to_import.end(); ) - { - get_dll_exports(dlls, *p, ni); - p = dlls_to_import.erase(p); - } - } - - if ( thr_names != NULL ) - update_thread_names(thr_names); -} - -//-------------------------------------------------------------------------- -static void update_thread_description(thread_info_t &ti) -{ - if ( _GetThreadDescription == NULL ) - return; - - PWSTR data; - HRESULT hr = _GetThreadDescription(ti.hThread, &data); - if ( SUCCEEDED(hr) ) - { - int data_sz = wcslen(data) * 2; // size in bytes - qstring newname; - if ( convert_encoding( - (bytevec_t*)&newname, - ENC_UTF16LE, ENC_UTF8, - (const uchar *)data, - data_sz) > 0 ) - { - if ( newname != ti.name ) - { - ti.name = newname.c_str(); // newname over allocated - ti.set_new_name(); - } - } - LocalFree(data); - } -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::update_thread_names(thread_name_vec_t *thr_names) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - update_thread_description(ti); - if ( ti.is_new_name() ) - { - thread_name_t &tn = thr_names->push_back(); - tn.tid = ti.tid; - tn.name = ti.name; - ti.clr_new_name(); - } - } -} - -//-------------------------------------------------------------------------- -// return the address of an exported name -ea_t win32_debmod_t::get_dll_export( - const images_t &_dlls, - ea_t imagebase, - const char *exported_name) -{ - ea_t ret = BADADDR; - - name_info_t ni; - if ( get_dll_exports(_dlls, imagebase, ni, exported_name) && !ni.addrs.empty() ) - ret = ni.addrs[0]; - return ret; -} - -//-------------------------------------------------------------------------- -win32_debmod_t::win32_debmod_t() - : expecting_debug_break(0), stop_at_ntdll_bpts(false) -{ - fake_suspend_event = false; - - pid = -1; - - // Reset handles - process_handle = INVALID_HANDLE_VALUE; - thread_handle = INVALID_HANDLE_VALUE; - redirin_handle = INVALID_HANDLE_VALUE; - redirout_handle = INVALID_HANDLE_VALUE; - - attach_evid = INVALID_HANDLE_VALUE; - attach_status = as_none; - - memset(&cpdi, 0, sizeof(cpdi)); - cpdi.hFile = INVALID_HANDLE_VALUE; // hFile - cpdi.hProcess = INVALID_HANDLE_VALUE; // hProcess - cpdi.hThread = INVALID_HANDLE_VALUE; // hThread - - winxp_step_thread = 0; - memset(&in_event, 0, sizeof(in_event)); - exiting = false; - pause_requested = false; - - broken_event_handle = NULL; - // we don't set platform name here because it will be inherited - // from winbase_debmod_t - - binary_to_import.base = BADADDR; - binary_to_import.size = 0; - binary_to_import.rebase_to = BADADDR; -} - -//---------------------------------------------------------------------- -// return the handle associated with a thread id from the threads list -HANDLE win32_debmod_t::get_thread_handle(thid_t tid) -{ - thread_info_t *tinfo = threads.get(tid); - return tinfo == NULL ? INVALID_HANDLE_VALUE : tinfo->hThread; -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::refresh_hwbpts(void) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - set_hwbpts(p->second.hThread); - return true; -} - -//-------------------------------------------------------------------------- -// 1-ok, 0-failed -int idaapi win32_debmod_t::dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) -{ - check_thread(false); - if ( orig_bytes != NULL ) - { - bool ok = false; - bpts.erase(ea); - suspend_all_threads(); - // write the old value only if our bpt is still present - if ( !has_bpt_at(ea) ) - { - if ( !exiting ) - dmsg("%a: breakpoint vanished from memory\n", ea); - ok = true; - } - else - { - ok = _write_memory(ea, orig_bytes, len) == len; - } - resume_all_threads(); - return ok; - } - - // try to delete a page bpt first - if ( del_page_bpt(ea, type) ) - return true; - return del_hwbpt(ea, type); -} - -//-------------------------------------------------------------------------- -ssize_t win32_debmod_t::_write_memory(eanat_t ea, const void *buffer, size_t size, bool suspend) -{ - if ( !may_write(ea) ) - return -1; - return access_memory(ea, (void *)buffer, size, true, suspend); -} - -//-------------------------------------------------------------------------- -void idaapi win32_debmod_t::dbg_term(void) -{ - check_thread(true); - cleanup_hwbpts(); - cleanup(); - for ( size_t i = 0; i < pdb_remote_sessions.size(); ++i ) - close_pdb_remote_session(pdb_remote_sessions[i]); - inherited::dbg_term(); -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::has_bpt_at(ea_t ea) -{ - uchar bytes[8]; - int size = bpt_code.size(); - return _read_memory(ea, bytes, size) == size - && memcmp(bytes, bpt_code.begin(), size) == 0; -} - -//-------------------------------------------------------------------------- -// 2-ok(pagebpt), 1-ok, 0-failed, -2-read failed -int idaapi win32_debmod_t::dbg_add_bpt( - bytevec_t *orig_bytes, - bpttype_t type, - ea_t ea, - int len) -{ - check_thread(false); - if ( type == BPT_SOFT ) - { - if ( len <= 0 ) - len = bpt_code.size(); - if ( orig_bytes != NULL && read_bpt_orgbytes(orig_bytes, ea, len) < 0 ) - return -2; - debmod_bpt_t dbpt(ea, len); - if ( !dbg_read_memory(ea, dbpt.saved, len, NULL) ) - return -2; - int size = bpt_code.size(); - if ( dbg_write_memory(ea, bpt_code.begin(), size, NULL) != size ) - return 0; - bpts[ea] = dbpt; - return 1; - } - - // try, first, to add a real hw breakpoint - // if it fails, add a memory range type bpt - // reason: the user may try to insert a 5th - // correct hw bpt, however, it isn't possible - // so, instead, we add a page breakpoint - int ret = 0; - if ( check_x86_hwbpt(type, ea, len) == BPT_OK ) - ret = add_hwbpt(type, ea, len); - - if ( !ret ) - ret = dbg_add_page_bpt(type, ea, len); - return ret; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_get_memory_info(meminfo_vec_t &ranges, qstring * /*errbuf*/) -{ - check_thread(false); - NODISTURB_ASSERT(in_event != NULL); - - images.clear(); - thread_ranges.clear(); - class_ranges.clear(); - for ( threads_t::iterator t=threads.begin(); t != threads.end(); ++t ) - add_thread_ranges(t->first, thread_ranges, class_ranges); - - if ( process_handle != INVALID_HANDLE_VALUE ) - { - for ( ea_t ea=0; ea != BADADDR; ) - { - memory_info_t meminf; - ea = get_region_info(ea, &meminf); - if ( ea != BADADDR && meminf.start_ea != BADADDR ) - ranges.push_back(meminf); - } - enable_page_bpts(true); - } - - if ( same_as_oldmemcfg(ranges) ) - return DRC_NOCHG; - - save_oldmemcfg(ranges); - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_thread_suspend(thid_t tid) -{ - check_thread(false); - NODISTURB_ASSERT(in_event != NULL); - int count = SuspendThread(get_thread_handle(tid)); - if ( count == -1 ) - deberr("SuspendThread(%08X)", tid); - - if ( debug_debugger ) - debdeb("SuspendThread(%08X) -> %d\n", tid, count); - - return count != -1 ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_thread_continue(thid_t tid) -{ - check_thread(false); - NODISTURB_ASSERT(in_event != NULL); - int count = ResumeThread(get_thread_handle(tid)); - if ( count == -1 ) - deberr("ResumeThread(%08X)", tid); - - if ( debug_debugger ) - debdeb("ResumeThread(%08X) -> %d\n", tid, count); - - return count != -1 ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -static int calc_ctxflags(int clsmask) -{ - int ctxflags = CONTEXT_CONTROL|CONTEXT_INTEGER; - if ( (clsmask & X86_RC_SEGMENTS) != 0 ) - ctxflags |= CONTEXT_SEGMENTS; - if ( (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0 ) - ctxflags |= CONTEXT_FLOATING_POINT; - if ( (clsmask & X86_RC_XMM) != 0 ) -#ifndef __X86__ - ctxflags |= CONTEXT_FLOATING_POINT; -#else - ctxflags |= CONTEXT_EXTENDED_REGISTERS; -#endif - if ( (clsmask & X86_RC_YMM) != 0 ) -#ifndef __X86__ - ctxflags |= CONTEXT_XSTATE|CONTEXT_FLOATING_POINT; -#else - ctxflags |= CONTEXT_XSTATE|CONTEXT_EXTENDED_REGISTERS; -#endif - return ctxflags; -} - -//-------------------------------------------------------------------------- -// assertions that ensure that the conversion between CONTEXT and WOW64_CONTEXT -// is correct -#ifdef __X86__ -CASSERT(sizeof(FLOATING_SAVE_AREA) == 112); -CASSERT(CONTEXT_CONTROL == 0x10001); -CASSERT(CONTEXT_INTEGER == 0x10002); -CASSERT(CONTEXT_SEGMENTS == 0x10004); -CASSERT(CONTEXT_FLOATING_POINT == 0x10008); -CASSERT(CONTEXT_DEBUG_REGISTERS == 0x10010); -CASSERT(CONTEXT_EXTENDED_REGISTERS == 0x10020); -#else -CASSERT(sizeof(WOW64_FLOATING_SAVE_AREA) == 112); -CASSERT(sizeof(XSAVE_FORMAT) == WOW64_MAXIMUM_SUPPORTED_EXTENSION); -CASSERT(WOW64_CONTEXT_CONTROL == 0x10001); -CASSERT(WOW64_CONTEXT_INTEGER == 0x10002); -CASSERT(WOW64_CONTEXT_SEGMENTS == 0x10004); -CASSERT(WOW64_CONTEXT_FLOATING_POINT == 0x10008); -CASSERT(WOW64_CONTEXT_DEBUG_REGISTERS == 0x10010); -CASSERT(WOW64_CONTEXT_EXTENDED_REGISTERS == 0x10020); -#endif - -#ifndef __X86__ -//-------------------------------------------------------------------------- -inline int ctxflags_to_wow64(int ctxflags) -{ - if ( (ctxflags & CONTEXT_FLOATING_POINT) != 0 ) - ctxflags |= WOW64_CONTEXT_EXTENDED_REGISTERS; - // XSTATE in WOW64 is handled in a separate context - bool requires_xstate = (ctxflags & CONTEXT_XSTATE) == CONTEXT_XSTATE; - if ( requires_xstate ) - ctxflags |= WOW64_CONTEXT_FLOATING_POINT; - ctxflags &= ~CONTEXT_XSTATE_BIT; - ctxflags &= ~CONTEXT_AMD64; - ctxflags |= WOW64_CONTEXT_i386; - return ctxflags; // see CASSERTs anout CONTEXT_... bits above -} - -//-------------------------------------------------------------------------- -void thread_info_t::cvt_from_wow64( - const WOW64_CONTEXT &wow64ctx, - int clsmask, - PCONTEXT xstate_ctx) const -{ - CONTEXT &ctx = get_ctx(); - - ctx.ContextFlags = calc_ctxflags(clsmask); - - if ( xstate_ctx != NULL && debmod->context_helper.xstate_helpers_loaded() ) - debmod->context_helper.pfnCopyContext(&ctx, CONTEXT_XSTATE, xstate_ctx); - - ctx.Dr0 = wow64ctx.Dr0; - ctx.Dr1 = wow64ctx.Dr1; - ctx.Dr2 = wow64ctx.Dr2; - ctx.Dr3 = wow64ctx.Dr3; - ctx.Dr6 = wow64ctx.Dr6; - ctx.Dr7 = wow64ctx.Dr7; - - ctx.SegGs = wow64ctx.SegGs; - ctx.SegFs = wow64ctx.SegFs; - ctx.SegEs = wow64ctx.SegEs; - ctx.SegDs = wow64ctx.SegDs; - - ctx.Rdi = wow64ctx.Edi; - ctx.Rsi = wow64ctx.Esi; - ctx.Rbx = wow64ctx.Ebx; - ctx.Rdx = wow64ctx.Edx; - ctx.Rcx = wow64ctx.Ecx; - ctx.Rax = wow64ctx.Eax; - - ctx.Rbp = wow64ctx.Ebp; - ctx.SegCs = wow64ctx.SegCs; - ctx.EFlags = wow64ctx.EFlags; - ctx.SegSs = wow64ctx.SegSs; - ctx.Rip = wow64ctx.Eip; - ctx.Rsp = wow64ctx.Esp; - - if ( (wow64ctx.ContextFlags & WOW64_CONTEXT_EXTENDED_REGISTERS) != 0 ) - { - memcpy(&ctx.FltSave, wow64ctx.ExtendedRegisters, sizeof(ctx.FltSave)); - } - else if ( (wow64ctx.ContextFlags & WOW64_CONTEXT_FLOATING_POINT) != 0 ) - { - ctx.FltSave.ControlWord = wow64ctx.FloatSave.ControlWord; - ctx.FltSave.StatusWord = wow64ctx.FloatSave.StatusWord; - ctx.FltSave.TagWord = wow64ctx.FloatSave.TagWord; - ctx.FltSave.ErrorOffset = wow64ctx.FloatSave.ErrorOffset; - ctx.FltSave.ErrorSelector = wow64ctx.FloatSave.ErrorSelector; - ctx.FltSave.DataOffset = wow64ctx.FloatSave.DataOffset; - ctx.FltSave.DataSelector = wow64ctx.FloatSave.DataSelector; - memset(ctx.FltSave.FloatRegisters, 0, sizeof(ctx.FltSave.FloatRegisters)); - for ( int i=0; i < 8; i++ ) - memcpy(&ctx.FltSave.FloatRegisters[i], &wow64ctx.FloatSave.RegisterArea[i*10], 10); - } -} - -//-------------------------------------------------------------------------- -void thread_info_t::cvt_to_wow64( - WOW64_CONTEXT *wow64ctx, - PCONTEXT xstate_ctx, - int clsmask) const -{ - int cflags = calc_ctxflags(clsmask); - int wflags = ctxflags_to_wow64(cflags); - wow64ctx->ContextFlags = wflags; - - CONTEXT &ctx = get_ctx(); - - if ( xstate_ctx != NULL && debmod->context_helper.xstate_helpers_loaded() ) - debmod->context_helper.pfnCopyContext(xstate_ctx, CONTEXT_XSTATE, &ctx); - - wow64ctx->Dr0 = ctx.Dr0; - wow64ctx->Dr1 = ctx.Dr1; - wow64ctx->Dr2 = ctx.Dr2; - wow64ctx->Dr3 = ctx.Dr3; - wow64ctx->Dr6 = ctx.Dr6; - wow64ctx->Dr7 = ctx.Dr7; - - wow64ctx->SegGs = ctx.SegGs; - wow64ctx->SegFs = ctx.SegFs; - wow64ctx->SegEs = ctx.SegEs; - wow64ctx->SegDs = ctx.SegDs; - - wow64ctx->Edi = ctx.Rdi; - wow64ctx->Esi = ctx.Rsi; - wow64ctx->Ebx = ctx.Rbx; - wow64ctx->Edx = ctx.Rdx; - wow64ctx->Ecx = ctx.Rcx; - wow64ctx->Eax = ctx.Rax; - - wow64ctx->Ebp = ctx.Rbp; - wow64ctx->SegCs = ctx.SegCs; - wow64ctx->EFlags = ctx.EFlags; - wow64ctx->SegSs = ctx.SegSs; - wow64ctx->Eip = ctx.Rip; - wow64ctx->Esp = ctx.Rsp; - - if ( (wflags & WOW64_CONTEXT_FLOATING_POINT) != 0 ) - { - wow64ctx->FloatSave.ControlWord = ctx.FltSave.ControlWord; - wow64ctx->FloatSave.StatusWord = ctx.FltSave.StatusWord; - wow64ctx->FloatSave.TagWord = ctx.FltSave.TagWord; - wow64ctx->FloatSave.ErrorOffset = ctx.FltSave.ErrorOffset; - wow64ctx->FloatSave.ErrorSelector = ctx.FltSave.ErrorSelector; - wow64ctx->FloatSave.DataOffset = ctx.FltSave.DataOffset; - wow64ctx->FloatSave.DataSelector = ctx.FltSave.DataSelector; - for ( int i=0; i < 8; i++ ) - memcpy(&wow64ctx->FloatSave.RegisterArea[i*10], &ctx.FltSave.FloatRegisters[i], 10); - } - if ( (wflags & WOW64_CONTEXT_EXTENDED_REGISTERS) != 0 ) - memcpy(wow64ctx->ExtendedRegisters, &ctx.FltSave, sizeof(ctx.FltSave)); -} - -#define Eip Rip -#endif - -//-------------------------------------------------------------------------- -bool thread_info_t::read_context(int clsmask) -{ - if ( (flags & clsmask) == clsmask ) - return true; - - int ctxflags = calc_ctxflags(clsmask); - if ( !debmod->context_helper.create_context(&ctx_holder, &ctxflags) ) - return false; - -#ifndef __X86__ - if ( (flags & THR_WOW64) != 0 && _Wow64GetThreadContext != NULL ) - { - WOW64_CONTEXT wow64ctx; - wow64ctx.ContextFlags = ctxflags_to_wow64(ctxflags); - if ( !_Wow64GetThreadContext(hThread, &wow64ctx) ) - return false; - context_holder_t xstate_ctx; - if ( (clsmask & X86_RC_YMM) != 0 ) - { - int xstate_ctxflags = CONTEXT_XSTATE; - if ( !debmod->context_helper.create_context(&xstate_ctx, &xstate_ctxflags) ) - return false; - if ( !GetThreadContext(hThread, xstate_ctx.ptr) ) - return false; - } - invalidate_context(); - cvt_from_wow64(wow64ctx, clsmask, xstate_ctx.ptr); - } - else -#endif - { - CONTEXT &ctx = get_ctx(); - ctx.ContextFlags = ctxflags; - if ( !GetThreadContext(hThread, &ctx) ) - return false; - invalidate_context(); - ctx.ContextFlags = ctxflags; // invalidate_context() zeroed it - } - flags |= (clsmask | X86_RC_GENERAL) & THR_CLSMASK; - return true; -} - -//-------------------------------------------------------------------------- -bool thread_info_t::write_context(int clsmask) -{ -#ifndef __X86__ - if ( (flags & THR_WOW64) != 0 && _Wow64SetThreadContext != NULL ) - { - context_holder_t xstate_ctx; - if ( (clsmask & X86_RC_YMM) != 0 ) - { - int xstate_ctxflags = CONTEXT_XSTATE; - if ( !debmod->context_helper.create_context(&xstate_ctx, &xstate_ctxflags) ) - return false; - } - WOW64_CONTEXT wow64ctx; - cvt_to_wow64(&wow64ctx, xstate_ctx.ptr, clsmask); - if ( xstate_ctx.ptr != NULL ) - { - if ( SetThreadContext(hThread, xstate_ctx.ptr) == 0 ) - return false; - } - if ( _Wow64SetThreadContext(hThread, &wow64ctx) == 0 ) - return false; - return true; - } -#else - qnotused(clsmask); -#endif - return SetThreadContext(hThread, &get_ctx()) != 0; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_prepare_to_pause_process(qstring * /*errbuf*/) -{ - check_thread(false); - bool ok = true; - win_tool_help_t *wth = get_tool_help(); - if ( wth->use_debug_break_process() ) // only possible on XP/2K3 or higher - { - ok = wth->debug_break_process(process_handle); - if ( !stop_at_ntdll_bpts ) - expecting_debug_break = ok; - } - else if ( threads.empty() ) - { - ok = false; - } - else - { - suspend_all_threads(); - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - thread_info_t &ti = p->second; - if ( !ti.read_context(X86_RC_GENERAL) ) - { - ok = false; - continue; - } - // we have a problem: it is possible that eip points past a temporary breakpoint - // that will be removed and replaced by the original instruction opcode. - // if we set a new breakpoint now, it will be at the second byte of the - // instruction and will lead to a crash. - eanat_t ip = ti.get_ctx().Eip; - if ( bpts.find(ip-bpt_code.size()) != bpts.end() ) - continue; // yes, there is a breakpoint just before us. it was just hit - // but hopefully not processed yet - if ( !set_thread_bpt(ti, ip) ) - ok = false; - } - // send WM_NULL to the main thread, hopefully it will wake up the application - thread_info_t &ti = threads.begin()->second; - PostThreadMessageA(ti.tid, WM_NULL, 0, 0); - resume_all_threads(); - } - pause_requested = true; - return ok ? DRC_OK : DRC_FAILED; -} - -//---------------------------------------------------------------------- -// return the name associated with an existing image in 'images' list -// containing a particular range -static const char *get_range_name(const images_t &images, const range_t *range) -{ - for ( images_t::const_iterator p=images.begin(); p != images.end(); ++p ) - { - const image_info_t &img = p->second; - ea_t ea1 = (ea_t)img.base; - ea_t ea2 = ea1 + img.imagesize; - range_t b = range_t(ea1, ea2); - b.intersect(*range); - if ( !b.empty() ) - return img.name.c_str(); - } - return NULL; -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::restore_original_bytes(ea_t ea, bool really_restore) -{ - bpt_info_t::iterator p = thread_bpts.find(ea); - QASSERT(1488, p != thread_bpts.end()); - if ( --p->second.count == 0 ) - { - uchar *obytes = p->second.orig_bytes; - if ( really_restore ) - { - int size = bpt_code.size(); - if ( _write_memory(ea, obytes, size) != size ) - INTERR(1489); - } - thread_bpts.erase(p); - } -} - -//-------------------------------------------------------------------------- -// returns: 0-error,1-ok,2-already had bpt, just increased the counter -int win32_debmod_t::save_original_bytes(ea_t ea) -{ - bpt_info_t::iterator p = thread_bpts.find(ea); - if ( p == thread_bpts.end() ) - { - internal_bpt_info_t ibi; - ibi.count = 1; - int size = bpt_code.size(); - if ( _read_memory(ea, ibi.orig_bytes, size) != size ) - return 0; - thread_bpts.insert(std::make_pair(ea, ibi)); - return 1; - } - else - { - p->second.count++; - return 2; - } -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::del_thread_bpt(thread_info_t &ti, ea_t ea) -{ - if ( ti.bpt_ea == BADADDR ) - return false; - - if ( ti.bpt_ea == ea ) - { - if ( !ti.read_context(X86_RC_GENERAL) ) - return false; - CONTEXT &ctx = ti.get_ctx(); - ctx.Eip = ti.bpt_ea; // reset EIP - DWORD saved = ctx.ContextFlags; - ctx.ContextFlags = CONTEXT_CONTROL; - if ( !ti.write_context(X86_RC_GENERAL) ) - deberr("del_thread_bpt: SetThreadContext"); - ctx.ContextFlags = saved; - } - - // restore old insn if necessary - restore_original_bytes(ti.bpt_ea); - ti.bpt_ea = BADADDR; - return true; -} - -//-------------------------------------------------------------------------- -// delete all thread breakpoints -// returns true if a breakpoint at which we stopped was removed -bool win32_debmod_t::del_thread_bpts(ea_t ea) -{ - bool found = false; - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - found |= del_thread_bpt(p->second, ea); - return found; -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::set_thread_bpt(thread_info_t &ti, ea_t ea) -{ - // delete old thread bpt if any existed before - del_thread_bpt(ti, BADADDR); - - ti.bpt_ea = ea; - int code = save_original_bytes(ti.bpt_ea); - if ( code ) - { - if ( code == 2 ) // already have a bpt? - return true; // yes, then everything ok - int size = bpt_code.size(); - code = _write_memory(ti.bpt_ea, bpt_code.begin(), size); - if ( code > 0 ) - { - if ( code == size ) - return true; - // failed to write, forget the original byte - restore_original_bytes(ti.bpt_ea, false); - } - } - debdeb("%a: set_thread_bpt() failed to pause thread %d\n", ti.bpt_ea, ti.tid); - ti.bpt_ea = BADADDR; - return false; -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::add_thread(const CREATE_THREAD_DEBUG_INFO &thr_info, thid_t tid) -{ - wow64_state_t w = check_wow64_process(); - thread_info_t ti(this, thr_info, tid, w); - threads.insert(std::make_pair(tid, ti)); -} - -//-------------------------------------------------------------------------- -gdecode_t win32_debmod_t::get_debug_event(debug_event_t *event, int timeout_ms) -{ - check_thread(false); - if ( events.retrieve(event) ) - return events.empty() ? GDE_ONE_EVENT : GDE_MANY_EVENTS; - - DEBUG_EVENT DebugEvent; - // we have to wait infinitely if we just try to attach to a running process - if ( attach_status == as_attaching ) - timeout_ms = INFINITE; - if ( !WaitForDebugEvent(&DebugEvent, timeout_ms) ) - { - // no event occurred - if ( attach_status == as_detaching ) // if we were requested to detach, - { // we generate a fake detach event - event->set_eid(PROCESS_DETACHED); - return GDE_ONE_EVENT; - } - // else, we don't return an event - return GDE_NO_EVENT; - } - - if ( attach_status == as_attaching ) - { - if ( DebugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT ) - return GDE_ERROR; - // fill in starting information for the just attached process (we couldn't do it from CreateProcess() return values !) - process_path = ""; - pid = DebugEvent.dwProcessId; - attach_status = as_breakpoint; - } - - if ( debug_debugger ) - show_debug_event(DebugEvent); - - // ignore events coming from other child processes - if ( DebugEvent.dwProcessId != pid ) - { - debdeb("ignore: pid %x != %x\n", DebugEvent.dwProcessId, pid); - bool handled = DebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT - && (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT - || DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT); - - if ( !ContinueDebugEvent(DebugEvent.dwProcessId, - DebugEvent.dwThreadId, - handled ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED) ) - { - deberr("ContinueDebugEvent"); - } - invalidate_all_contexts(); - return GDE_NO_EVENT; - } - - event->pid = DebugEvent.dwProcessId; - event->tid = DebugEvent.dwThreadId; - event->handled = true; - - gdecode_t gdecode = GDE_ONE_EVENT; - switch ( DebugEvent.dwDebugEventCode ) - { - case EXCEPTION_DEBUG_EVENT: - { - EXCEPTION_RECORD &er = DebugEvent.u.Exception.ExceptionRecord; - // remove temporary breakpoints if any - bool was_thread_bpt = del_thread_bpts(EA_T(er.ExceptionAddress)); - bool firsttime = DebugEvent.u.Exception.dwFirstChance != 0; - gdecode = handle_exception(event, er, was_thread_bpt, firsttime); - } - break; - - case CREATE_THREAD_DEBUG_EVENT: - { - // add this thread to our list - add_thread(DebugEvent.u.CreateThread, event->tid); - event->set_info(THREAD_STARTED); - event->ea = EA_T(DebugEvent.u.CreateThread.lpStartAddress); - // set hardware breakpoints if any - set_hwbpts(DebugEvent.u.CreateThread.hThread); - } - break; - - case CREATE_PROCESS_DEBUG_EVENT: - { - // save information for later - cpdi = DebugEvent.u.CreateProcessInfo; - cpdi.lpBaseOfImage = correct_exe_image_base(cpdi.lpBaseOfImage); - if ( process_handle != INVALID_HANDLE_VALUE && process_handle != cpdi.hProcess ) - myCloseHandle(process_handle); // already have an open handle - process_handle = cpdi.hProcess; - - create_start_event(event); - curproc.insert(std::make_pair(event->modinfo().base, image_info_t(this, event->modinfo()))); - - // add record about the main thread into the list - CREATE_THREAD_DEBUG_INFO ctdi; - ctdi.hThread = cpdi.hThread; - ctdi.lpThreadLocalBase = cpdi.lpThreadLocalBase; - ctdi.lpStartAddress = cpdi.lpStartAddress; - add_thread(ctdi, DebugEvent.dwThreadId); - - // set hardware breakpoints if any - set_hwbpts(cpdi.hThread); - - // test hardware breakpoints: - // add_hwbpt(HWBPT_WRITE, 0x0012FF68, 4); - if ( highdlls.empty() && winver.is_DW32() ) // dw32 specific - { - HINSTANCE h = GetModuleHandle(kernel32_dll); - eanat_t addr = eanat_t(h); - uint32 size = calc_imagesize(addr); - highdlls.add(addr, size); - } - break; - } - - case EXIT_THREAD_DEBUG_EVENT: - { - threads.erase(event->tid); - event->set_exit_code(THREAD_EXITED, DebugEvent.u.ExitThread.dwExitCode); - // invalidate corresponding handles - HANDLE h = get_thread_handle(event->tid); - if ( h == thread_handle ) - thread_handle = INVALID_HANDLE_VALUE; - if ( h == cpdi.hThread ) - cpdi.hThread = INVALID_HANDLE_VALUE; - break; - } - - case EXIT_PROCESS_DEBUG_EVENT: - event->set_exit_code(PROCESS_EXITED, DebugEvent.u.ExitProcess.dwExitCode); - exiting = true; - break; - - case LOAD_DLL_DEBUG_EVENT: - { - const LOAD_DLL_DEBUG_INFO &dil = DebugEvent.u.LoadDll; - eanat_t addr = eanat_t(dil.lpBaseOfDll); - modinfo_t &mi_ll = event->set_modinfo(LIB_LOADED); - event->ea = addr; - mi_ll.base = event->ea; - mi_ll.rebase_to = BADADDR; // this must be determined locally - see common_local.cpp - - char full_name[MAXSTR]; - full_name[0] = '\0'; - bool ok = get_filename_for(full_name, - sizeof(full_name), - eanat_t(dil.lpImageName), - dil.fUnicode != 0, - addr); - // Win 7 may send a bogus DLL load event for the main module - // ignore event if this module has already been mapped - if ( !ok || module_present(full_name) ) - { - debdeb("%p: bogus DLL load event, skippping\n", addr); - goto SILENTLY_RESUME; - } - mi_ll.name = full_name; - uint32 size = calc_imagesize(addr); - mi_ll.size = size; - - // does the address fit into ea_t? - HANDLE ntdll_handle = dil.hFile; - if ( highdlls.add_high_module(addr, size, ntdll_handle) ) - { - debdeb("%p: 64bit DLL loaded into high addresses has been detected\n", - addr); - goto SILENTLY_RESUME; - } - - // we defer the import of the dll until the moment when ida stops - // at a debug event. we do so to avoid unnecessary imports because - // the dll might get unloaded before ida stops. - image_info_t di(this, DebugEvent.u.LoadDll, size, full_name); - add_dll(di); - // determine the attach breakpoint if needed - size_t max_ntdlls = check_wow64_process() == WOW64_YES ? 2 : 1; - if ( highdlls.count_ntdlls() < max_ntdlls ) - { - if ( is_ntdll_name(full_name) ) - highdlls.add_ntdll(addr, size); - if ( attach_status == as_none && !stop_at_ntdll_bpts ) - expecting_debug_break = highdlls.count_ntdlls(); - } - break; - } - -SILENTLY_RESUME: - // do not report this event to ida - event->handled = true; - dbg_continue_after_event(event); - return GDE_NO_EVENT; - - case UNLOAD_DLL_DEBUG_EVENT: - event->set_info(LIB_UNLOADED); - { - eanat_t addr = eanat_t(DebugEvent.u.UnloadDll.lpBaseOfDll); - range_t range(addr, addr+MEMORY_PAGE_SIZE); // we assume DLL image is at least a PAGE size - const char *name = get_range_name(dlls, &range); - if ( name != NULL ) - event->info() = name; - else - event->info().clear(); - - // remove ntdll from the list - HANDLE ntdll_handle; - if ( highdlls.del_high_module(&ntdll_handle, addr) ) - { - myCloseHandle(ntdll_handle); - goto SILENTLY_RESUME; - } - - // close the associated DLL handle - images_t::iterator p = dlls.find(addr); - if ( p != dlls.end() ) - { - myCloseHandle(p->second.dll_info.hFile); - // Remove it from the list of dlls to import - // (in the case it was never imported) - dlls_to_import.erase(p->first); - dlls.erase(p); - } - else - { - debdeb("Could not find dll to unload (base=%a)\n", EA_T(DebugEvent.u.UnloadDll.lpBaseOfDll)); - } - } - break; - - case OUTPUT_DEBUG_STRING_EVENT: - { - char buf[MAXSTR]; - get_debug_string(DebugEvent, buf, sizeof(buf)); - event->set_info(INFORMATION) = buf; - } - break; - - case RIP_EVENT: - debdeb("RIP_EVENT (system debugging error)"); - break; - - default: - debdeb("UNKNOWN_EVENT %d", DebugEvent.dwDebugEventCode); - event->handled = false; // don't handle it - break; - } - - if ( gdecode > GDE_NO_EVENT && attach_status == as_breakpoint && event->eid() == EXCEPTION ) - { // exception while attaching. apparently things went wrong - // pretend that we attached successfully - events.enqueue(*event, IN_BACK); - create_attach_event(event, true); - attach_status = as_none; - } - return gdecode; -} - -//-------------------------------------------------------------------------- -gdecode_t idaapi win32_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) -{ - check_thread(false); - gdecode_t gdecode = get_debug_event(event, timeout_ms); - if ( gdecode >= GDE_ONE_EVENT ) - { - last_event = *event; - in_event = &last_event; - pause_requested = false; - } - return gdecode; -} - - -//-------------------------------------------------------------------------- -bool win32_debmod_t::get_debug_string(const DEBUG_EVENT &ev, char *buf, size_t bufsize) -{ - buf[0] = '\0'; - size_t nullsize = ev.u.DebugString.fUnicode ? sizeof(wchar_t) : 1; - size_t msize = qmin(ev.u.DebugString.nDebugStringLength, bufsize-nullsize); - ea_t ea = EA_T(ev.u.DebugString.lpDebugStringData); - ssize_t rsize = _read_memory(ea, buf, msize); - if ( rsize == msize ) - { - buf[rsize] = '\0'; - if ( ev.u.DebugString.fUnicode ) - { - *(wchar_t*)(buf + rsize) = 0; - utf16_to_utf8(buf, bufsize, (LPCWSTR)buf); - } - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::cleanup() -{ - myCloseHandle(redirin_handle); - myCloseHandle(redirout_handle); - myCloseHandle(thread_handle); - myCloseHandle(process_handle); - myCloseHandle(cpdi.hFile); - - // Close handles of remaining DLLs - for ( images_t::iterator p=dlls.begin(); p != dlls.end(); ++p ) - myCloseHandle(p->second.dll_info.hFile); - - pid = -1; - highdlls.clear(); - stop_at_ntdll_bpts = qgetenv("IDA_SYSTEMBREAKPOINT"); - expecting_debug_break = 0; - in_event = NULL; - memset(&cpdi, 0, sizeof(cpdi)); - cpdi.hFile = INVALID_HANDLE_VALUE; - cpdi.hProcess = INVALID_HANDLE_VALUE; - cpdi.hThread = INVALID_HANDLE_VALUE; - attach_status = as_none; - attach_evid = INVALID_HANDLE_VALUE; - - old_ranges.clear(); - threads.clear(); - thread_bpts.clear(); - bpts.clear(); - curproc.clear(); - dlls.clear(); - dlls_to_import.clear(); - images.clear(); - thread_ranges.clear(); - class_ranges.clear(); - context_helper.clear(); - inherited::cleanup(); -} - -#define DRVBUFSIZE 512 - -//-------------------------------------------------------------------------- -// Translate path with device name to drive letters. -// e.g. \Device\HarddiskVolume4\Windows\System32\ntdll.dll -> C:\Windows\System32\ntdll.dll -static void translate_nt_path(qstring *out, LPCWSTR pszFilename) -{ - WCHAR szTemp[DRVBUFSIZE]; - - // get a list of all drive letters - if ( GetLogicalDriveStringsW(qnumber(szTemp) - 1, szTemp) ) - { - WCHAR szName[MAX_PATH]; - WCHAR szDrive[3] = L" :"; - BOOL bFound = FALSE; - WCHAR *p = szTemp; - - do - { - // Copy the drive letter to the template string - *szDrive = *p; - - // Look up device name for this drive - DWORD uNameLen = QueryDosDeviceW(szDrive, szName, qnumber(szName) - 1); - if ( uNameLen != 0 ) - { - //for some reason return value is 2 chars longer, so get the actual length - uNameLen = wcslen(szName); - // do we have a match at the start of filename? - bFound = _wcsnicmp(pszFilename, szName, uNameLen) == 0 - && pszFilename[uNameLen] == L'\\'; - - if ( bFound ) - { - // Reconstruct filename - // by replacing device path with DOS path (drive) - qstring path; - utf16_utf8(out, szDrive); - utf16_utf8(&path, pszFilename + uNameLen); - out->append(path); - return; - } - } - - // Go to the next NULL character. - while ( *p++ ) - ; - } - while ( !bFound && *p ); // end of string - } -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::get_filename_for( - char *buf, - size_t bufsize, - eanat_t image_name_ea, - bool use_unicode, - eanat_t image_base) -{ - buf[0] = '\0'; - // if we have address of file name in the process image from the debug API, try to use it - // remark: depending on the OS, NTDLL.DLL can return an empty string or only the DLL name! - if ( image_name_ea != 0 ) - { - if ( get_filename_from_process(image_name_ea, use_unicode, buf, bufsize) ) - return true; - } - - // various fallbacks - // first try GetMappedFileName - if ( _GetMappedFileName != NULL ) - { - wchar16_t tbuf[MAXSTR]; - HMODULE hmod = (HMODULE)(size_t)image_base; - if ( _GetMappedFileName(process_handle, hmod, tbuf, qnumber(tbuf)) ) - { - qstring tmp; - translate_nt_path(&tmp, tbuf); - qstrncpy(buf, tmp.c_str(), bufsize); - return true; - } - } - - // then try GetModuleFileNameEx - if ( _GetModuleFileNameEx != NULL ) - { - wchar16_t tbuf[MAXSTR]; - HMODULE hmod = (HMODULE)(size_t)image_base; - if ( _GetModuleFileNameEx(process_handle, hmod, tbuf, qnumber(tbuf)) ) - { - qstring tmp; - utf16_utf8(&tmp, tbuf); - qstrncpy(buf, tmp.c_str(), bufsize); - return true; - } - } - - // last: we try to get DLL name by looking at the export name from - // the export directory in PE image in debugged process. - // this is the least reliable way since this string may not match the actual dll filename - get_pe_export_name_from_process(image_base, buf, bufsize); - - // for dlls without path, try to find it - find_full_path(buf, bufsize, process_path.c_str()); - - // convert possible short path to long path - qffblk64_t fb; - if ( qfindfirst(buf, &fb, 0) == 0 ) - { - char *fptr = qbasename(buf); - qstrncpy(fptr, fb.ff_name, bufsize-(fptr-buf)); - } - return buf[0] != '\0'; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_detach_process() -{ - check_thread(false); - if ( in_event != NULL ) - dbg_continue_after_event(in_event); - BOOL ret = get_tool_help()->debug_detach_process(pid); - if ( ret ) - { - attach_status = as_detaching; - exiting = true; - } - return ret ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -void idaapi win32_debmod_t::dbg_set_debugging(bool _debug_debugger) -{ - debug_debugger = _debug_debugger; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_init(uint32_t *flags2, qstring * /*errbuf*/) -{ - check_thread(true); - - cleanup(); - cleanup_hwbpts(); - - if ( flags2 != nullptr ) - *flags2 = g_code; - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -image_info_t::image_info_t(win32_debmod_t *ses) - : sess(ses), base(BADADDR), imagesize(0) -{ - memset(&dll_info, 0, sizeof(dll_info)); -} - -image_info_t::image_info_t( - win32_debmod_t *ses, - ea_t _base, - uint32 _imagesize, - const qstring &_name) - : sess(ses), base(_base), imagesize(_imagesize), name(_name) -{ - memset(&dll_info, 0, sizeof(dll_info)); -} - -image_info_t::image_info_t( - win32_debmod_t *ses, - const LOAD_DLL_DEBUG_INFO &i, - uint32 _imagesize, - const char *_name) - : sess(ses), name(_name), dll_info(i) -{ - base = EA_T(i.lpBaseOfDll); - imagesize = _imagesize; -} - -image_info_t::image_info_t(win32_debmod_t *ses, const modinfo_t &m) - : sess(ses), base(m.base), imagesize(m.size), name(m.name) -{ - memset(&dll_info, 0, sizeof(dll_info)); -} - -//-------------------------------------------------------------------------- -// get (path+)name from debugged process -// lpFileName - pointer to pointer to the file name -// use_unicode - true if the filename is in unicode -bool win32_debmod_t::get_filename_from_process( - eanat_t name_ea, - bool use_unicode, - char *buf, - size_t bufsize) -{ - buf[0] = '\0'; - if ( name_ea == 0 ) - return false; - eanat_t dll_addr; - if ( _read_memory(name_ea, &dll_addr, sizeof(dll_addr)) != sizeof(dll_addr) ) - return false; - if ( dll_addr == NULL ) - return false; - name_ea = dll_addr; - if ( _read_memory(name_ea, buf, bufsize) != bufsize ) - return false; - if ( use_unicode ) - utf16_to_utf8(buf, bufsize, (LPCWSTR)buf); - return true; -} - -//-------------------------------------------------------------------------- -ea_t win32_debmod_t::get_region_info(ea_t ea, memory_info_t *mi) -{ - // okay to keep static, they won't change between clients - static DWORD_PTR totalVirtual = 0; - static DWORD granularity = 0; - - if ( totalVirtual == 0 ) - { - SYSTEM_INFO si; - GetSystemInfo(&si); - granularity = si.dwAllocationGranularity; - totalVirtual = (DWORD_PTR)si.lpMaximumApplicationAddress; - } - - void *addr = (void *)(size_t)ea; - MEMORY_BASIC_INFORMATION meminfo; - while ( !VirtualQueryEx(process_handle, // handle of process - addr, // address of region - &meminfo, // address of information buffer - sizeof(meminfo)) ) // size of buffer - { - // On Windows CE VirtualQueryEx can fail when called with addr == 0, - // so try to call it again with the next page (and end loop after 2d - // iteration to prevent scanning of huge number of pages) - // It's possible VirtualQueryEx fails on Windows CE not only for zero - // address: perhaps we shouldn't limit the number of iterations and return - // to using of a separate variable 'first' (as in win32_debmod.cpp#34) - if ( ea != 0 || ea >= totalVirtual ) - return BADADDR; - // try to find next valid page - ea += granularity; - addr = (void *)(size_t)ea; - } - - eanat_t startea = (eanat_t)meminfo.BaseAddress; - eanat_t endea = startea + meminfo.RegionSize; - if ( endea <= startea //overflow/empty? -#if !defined(__X86__) && !defined(__EA64__) - || endea >= BADADDR//crossed 4GB boundary -#endif - ) - { - if ( endea == startea ) - { - // ignore empty sections ... - mi->start_ea = BADADDR; - mi->end_ea = BADADDR; - return endea + 1; - } - // signal end of enumeration - endea = BADADDR; - } - -// debdeb("VirtualQueryEx(%a): base = %a, end = %a, protect=0x%x, allocprotect=0x%x, state=0x%x\n", ea, startea, endea, meminfo.Protect, meminfo.AllocationProtect, meminfo.State); - - // hide the page bpts in this memory region from ida - uint32 prot = meminfo.Protect; - if ( mask_page_bpts(startea, endea, &prot) ) - { - debdeb(" masked protect=0x%x\n", prot); - meminfo.Protect = prot; - } - - if ( (meminfo.State & (MEM_FREE|MEM_RESERVE)) == MEM_FREE // if the range isn't interesting for/accessible by IDA - || (meminfo.Protect & PAGE_NOACCESS) != 0 ) - { // we simply return an invalid range, and a pointer to the next (eventual) range - mi->start_ea = BADADDR; - mi->end_ea = BADADDR; - return endea; - } - - mi->start_ea = startea; - mi->end_ea = endea; -#ifdef __EA64__ - // we may be running a 32bit process in wow64 with ida64 - mi->bitness = check_wow64_process() > 0 ? 1 : 2; -#else - mi->bitness = 1; // 32bit -#endif - - // convert Windows protection modes to IDA protection modes - mi->perm = win_prot_to_ida_perm(meminfo.Protect); - - // try to associate a segment name to the memory range - const char *ptr; - if ( (ptr=get_range_name(curproc, mi)) != NULL // first try with the current process - || (ptr=get_range_name(dlls, mi)) != NULL // then try in DLLs - || (ptr=get_range_name(images, mi)) != NULL // then try in previous images ranges - || (ptr=get_range_name(thread_ranges, mi)) != NULL ) // and finally in thread ranges - { - // return the filename without the file path - mi->name = qbasename(ptr); - } - else - { - char buf[MAXSTR]; - buf[0] = '\0'; - //check for a mapped filename - get_filename_for(buf, sizeof(buf), 0, false, mi->start_ea); - if ( buf[0] != '\0' ) - { - mi->name = qbasename(buf); - } - // if we found nothing, check if the segment is a PE file header, and we try to locate a name in it - else if ( get_pe_export_name_from_process(mi->start_ea, buf, sizeof(buf)) ) - { // we insert it in the image ranges list - uint32 size = calc_imagesize(mi->start_ea); - image_info_t ii(this, mi->start_ea, size, buf); - images.insert(std::make_pair(ii.base, ii)); - mi->name = buf; - } - } - - // try to associate a segment class name to the memory range - mi->sclass = get_range_name(class_ranges, mi); - return endea; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_attach_process(pid_t _pid, int event_id, int /*flags*/, qstring * /*errbuf*/) -{ - check_thread(false); - int addrsize = get_process_addrsize(_pid); -#ifndef __EA64__ - if ( addrsize > 4 ) - { - dwarning("AUTOHIDE NONE\nPlease use ida64 to debug 64-bit applications"); - SetLastError(ERROR_NOT_SUPPORTED); - return DRC_FAILED; - } -#endif - if ( !DebugActiveProcess(_pid) ) - { - deberr("DebugActiveProcess %08lX", _pid); - return DRC_FAILED; - } - debapp_attrs.addrsize = addrsize; - attach_status = as_attaching; - attach_evid = (HANDLE)(INT_PTR)(event_id); - exiting = false; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring * /*errbuf*/) -{ - check_thread(false); - // input file specified in the database does not exist - if ( input_path[0] != '\0' && !qfileexist(input_path) ) - { - dwarning("AUTOHIDE NONE\nInput file is missing: %s", input_path); - return DRC_NOFILE; - } - - input_file_path = input_path; - is_dll = (flags & DBG_PROC_IS_DLL) != 0; - - char fullpath[QMAXPATH]; - if ( !qfileexist(path) ) - { - if ( qisabspath(path) || !search_path(fullpath, sizeof(fullpath), path, false) ) - { - dwarning("AUTOHIDE NONE\nCannot find application file '%s'", path); - return DRC_NETERR; - } - path = fullpath; - } - - drc_t mismatch = DRC_OK; - if ( !check_input_file_crc32(input_file_crc32) ) - mismatch = DRC_CRC; - - exiting = false; - - // Build a full command line - qstring args_buffer; // this vector must survive until create_process() - if ( args != NULL && args[0] != '\0' ) - { - args_buffer += '"'; - args_buffer += path; - args_buffer += '"'; - args_buffer += ' '; - args_buffer += args; - args = args_buffer.c_str(); - } - - PROCESS_INFORMATION ProcessInformation; - bool is_gui = (flags & DBG_PROC_IS_GUI) != 0; - bool hide_window = (flags & DBG_HIDE_WINDOW) != 0; - if ( !create_process(path, args, startdir, is_gui, hide_window, &ProcessInformation) ) - return DRC_FAILED; - - pid = ProcessInformation.dwProcessId; - process_handle = ProcessInformation.hProcess; - thread_handle = ProcessInformation.hThread; - process_path = path; - - debapp_attrs.addrsize = get_process_addrsize(pid); - - return mismatch; -} - -//-------------------------------------------------------------------------- -//lint -esym(1762,win32_debmod_t::myCloseHandle) could be made const -bool win32_debmod_t::myCloseHandle(HANDLE &h) -{ - bool ok = true; - if ( h != INVALID_HANDLE_VALUE && h != NULL ) - { - DWORD code; - __try - { - ok = CloseHandle(h) != 0; - if ( !ok ) - deberr("CloseHandle(%08X)", h); - } - __except ( code=GetExceptionCode() ) - { - debdeb("CloseHandle(%08X) exception code %08X\n", h, code); - ok = false; - } - h = INVALID_HANDLE_VALUE; - } - return ok; -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::install_callgate_workaround(thread_info_t *ti, const debug_event_t *event) -{ - // add a breakpoint after the call statement - ea_t bpt = event->ea + 7; - ti->callgate_ea = bpt; - if ( !set_thread_bpt(*ti, bpt) ) - INTERR(637); // how can it be? -} - -//-------------------------------------------------------------------------- -// we do not use 'firsttime' argument anymore. we could use it to distinguish -// the first chance and the second chance but it is more logical to -// behave consistently. -gdecode_t win32_debmod_t::handle_exception( - debug_event_t *event, - const EXCEPTION_RECORD &er, - bool was_thread_bpt, - bool /*firsttime*/) -{ - int code = er.ExceptionCode; - const exception_info_t *ei = find_exception(code); - - eanat_t addr = eanat_t(er.ExceptionAddress); - excinfo_t &exc = event->set_exception(); - event->ea = addr; - exc.code = code; - exc.can_cont = (er.ExceptionFlags == 0); - exc.ea = BADADDR; - event->handled = false; - - if ( exiting && ei == NULL ) - { - event->set_exit_code(PROCESS_EXITED, -1); - return GDE_ONE_EVENT; - } - - bool suspend = true; - - // we don't expect callgate breakpoints anymore - ea_t was_callgate_ea = BADADDR; - thread_info_t *ti = threads.get(event->tid); - if ( ti != NULL ) - { - was_callgate_ea = ti->callgate_ea; - ti->callgate_ea = BADADDR; - } - - if ( ei != NULL ) - { - event->handled = ei->handle(); - // if the user asked to suspend the process, do not resume - if ( !was_thread_bpt ) - suspend = ei->break_on() || pause_requested; - } - if ( !suspend ) - suspend = should_suspend_at_exception(event, ei); - exc.info.qclear(); - int elc_flags = 0; - switch ( uint32(code) ) - { - case EXCEPTION_BREAKPOINT: - case STATUS_WX86_BREAKPOINT: - if ( was_thread_bpt ) - { - QASSERT(638, ti != NULL); - - // is installed the workaround for the 'freely running after syscall' problem? - if ( was_callgate_ea == event->ea ) - event->set_eid(STEP); - else - event->set_eid(PROCESS_SUSPENDED); - break; - } - if ( attach_status == as_breakpoint ) // the process was successfully suspended after an attachement - { - create_attach_event(event, true); - break; - } - if ( expecting_debug_break > 0 - && highdlls.has(addr) - && get_kernel_bpt_ea(event->ea, event->tid) == BADADDR ) // not user-defined bpt - { - --expecting_debug_break; - debdeb("%a: resuming after DbgBreakPoint(), expecting bpts: %d\n", event->ea, expecting_debug_break); - event->handled = true; - dbg_continue_after_event(event); - return GDE_NO_EVENT; - } - // is this a breakpoint set by ida? - { - ea_t kea = get_kernel_bpt_ea(event->ea, event->tid); - if ( kea != BADADDR ) - { - bptaddr_t &bpta = event->set_bpt(); - bpta.hea = BADADDR; // no referenced address (only for hardware breakpoint) - bpta.kea = kea == event->ea ? BADADDR : kea; - event->handled = true; - } - } - break; - case EXCEPTION_SINGLE_STEP: - case STATUS_WX86_SINGLE_STEP: - { - bool is_stepping = ti != NULL && ti->is_tracing(); - // if this happened because of a hardware breakpoint - // find out which one caused it - if ( !check_for_hwbpt(event, is_stepping) ) - { - // if we have not asked for single step, do not convert it to STEP - if ( is_stepping ) - { - event->set_eid(STEP); // Single-step breakpoint - event->handled = true; - ti->clr_tracing(); - break; - } - } - } - break; - case EXCEPTION_ACCESS_VIOLATION: - { - ea_t exc_ea = EA_T(er.ExceptionInformation[1]); // virtual address of the inaccessible data. - exc.ea = exc_ea; - // is this a page bpt? - page_bpts_t::iterator p = find_page_bpt(exc_ea); - if ( p == page_bpts.end() ) - { - exc_ea = event->ea; - p = find_page_bpt(exc_ea); - } - if ( p != page_bpts.end() ) - { - // since on access violation the system does not update anything - // there is no need to reset eip when handling lowcnd below. - elc_flags |= ELC_KEEP_EIP; - ea_t exc_eip = EA_T(er.ExceptionAddress); - if ( !should_fire_page_bpt(p, exc_ea, er.ExceptionInformation[0], - exc_eip, dep_policy) ) - { // Silently step over the page breakpoint - if ( ti != NULL && ti->is_tracing() ) - elc_flags |= ELC_KEEP_SUSP; - lowcnd_t lc; - const pagebpt_data_t &bpt = p->second; - lc.ea = bpt.ea; - lc.type = bpt.type; - lc.size = bpt.user_len; - if ( !handling_lowcnds.has(bpt.ea) - && handle_lowcnd(&lc, event, elc_flags) ) - { - if ( (elc_flags & ELC_KEEP_SUSP) != 0 ) - { // if we were tracing, report a STEP event - event->set_eid(STEP); - event->handled = true; - ti->clr_tracing(); - return GDE_ONE_EVENT; - } - return GDE_NO_EVENT; - } - // failed to step over, return the exception - } - else - { - bptaddr_t &bpta = event->set_bpt(); - bpta.hea = p->second.ea; - bpta.kea = BADADDR; - event->handled = true; - break; - } - } - if ( ei != NULL && event->eid() == EXCEPTION ) - { - int einfo = er.ExceptionInformation[0]; - const char *verb = einfo == EXCEPTION_EXECUTE_FAULT ? "executed" - : einfo == EXCEPTION_WRITE_FAULT ? "written" - : "read"; - exc.info.sprnt(ei->desc.c_str(), event->ea, exc.ea, verb); - } - } - break; -#define EXCEPTION_BCC_FATAL 0xEEFFACE -#define EXCEPTION_BCC_NORMAL 0xEEDFAE6 - case EXCEPTION_BCC_FATAL: - case EXCEPTION_BCC_NORMAL: - if ( er.NumberParameters == 5 - && er.ExceptionInformation[0] == 2 // these numbers are highly hypothetic - && er.ExceptionInformation[1] == 3 ) - { - EXCEPTION_RECORD r2; - if ( dbg_read_memory(er.ExceptionInformation[3], &r2, sizeof(r2), NULL) == sizeof(r2) ) - return handle_exception(event, r2, false, false); - } - break; -#define MS_VC_EXCEPTION 0x406D1388L - case MS_VC_EXCEPTION: - // SetThreadName - // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx - if ( er.ExceptionInformation[0] == 0x1000 - && er.ExceptionInformation[3] == 0x00 ) - { - qstring name; - name.resize(MAXSTR); - ea_t nameaddr = er.ExceptionInformation[1]; - if ( dbg_read_memory(nameaddr, name.begin(), name.length(), NULL) > 0 ) - { - thid_t tid = er.ExceptionInformation[2]; - msg("Thread %d is named '%s'\n", tid, name.c_str()); - thread_info_t *tin = threads.get(tid); - if ( tin != NULL ) - { - tin->name = name.c_str(); - tin->set_new_name(); - } - event->handled = true; - } - } - break; - } - if ( !pause_requested && evaluate_and_handle_lowcnd(event, elc_flags) ) - return GDE_NO_EVENT; - - if ( event->eid() == EXCEPTION ) - { - if ( ei == NULL ) - { - exc.info.sprnt("unknown exception code %X", code); - } - else if ( exc.info.empty() ) - { - exc.info.sprnt(ei->desc.c_str(), event->ea, - ea_t(er.ExceptionInformation[0]), - ea_t(er.ExceptionInformation[1])); - } - if ( !suspend ) - { - log_exception(event, ei); - // if a single step was scheduled by the user - if ( ti != NULL && ti->is_tracing() ) - { - clear_tbit(*ti); - if ( event->handled ) - { - // since we mask the exception, we generate a STEP event - event->set_eid(STEP); - return GDE_ONE_EVENT; // got an event - } - } - dbg_continue_after_event(event); - return GDE_NO_EVENT; - } - } - return GDE_ONE_EVENT; -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::check_for_hwbpt(debug_event_t *event, bool is_stepping) -{ - ea_t ea = is_hwbpt_triggered(event->tid, is_stepping); - if ( ea != BADADDR ) - { - bptaddr_t &addr = event->set_bpt(); - addr.hea = ea; - addr.kea = BADADDR; - event->handled = true; - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::create_attach_event(debug_event_t *event, bool attached) -{ - event->set_modinfo(PROCESS_ATTACHED); - event->handled = true; - if ( attached ) - attach_status = as_attached; - else - attach_status = as_attaching; - if ( attach_evid != INVALID_HANDLE_VALUE ) - { - SetEvent(attach_evid); - attach_evid = INVALID_HANDLE_VALUE; - } - modinfo_t &mi_ps = event->modinfo(); - get_debugged_module_info(&mi_ps); - - binary_to_import = mi_ps; -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::create_start_event(debug_event_t *event) -{ - modinfo_t &mi_ps = event->set_modinfo(PROCESS_STARTED); - ea_t base = EA_T(cpdi.lpBaseOfImage); - - process_snapshot_t psnap(get_tool_help()); - PROCESSENTRY32 pe32; - for ( bool ok = psnap.first(TH32CS_SNAPNOHEAPS, &pe32); ok; ok = psnap.next(&pe32) ) - { - if ( pe32.th32ProcessID == event->pid ) - { - char exefile[QMAXPATH]; - tchar_utf8(exefile, pe32.szExeFile, sizeof(exefile)); - if ( !qisabspath(exefile) ) - { - char abspath[QMAXPATH]; - get_filename_for(abspath, - sizeof(abspath), - /*image_name_ea=*/ 0, - /*use_unicode=*/ false, // irrelevant - base); - if ( abspath[0] != '\0' ) - qstrncpy(exefile, abspath, sizeof(exefile)); - } - if ( process_path.empty() || qisabspath(exefile) ) - process_path = exefile; - break; - } - } - mi_ps.name = process_path; - mi_ps.base = base; - mi_ps.size = calc_imagesize(base); - mi_ps.rebase_to = BADADDR; // this must be determined locally - see common_local.cpp - - binary_to_import = mi_ps; -} - -//-------------------------------------------------------------------------- -ea_t win32_debmod_t::get_kernel_bpt_ea(ea_t ea, thid_t tid) -{ - if ( is_ida_bpt(ea, tid) ) - return ea; - return BADADDR; -} - - -ssize_t idaapi win32_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring * /*errbuf*/) -{ - check_thread(false); - return _write_memory(ea, buffer, size, true); -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_thread_get_sreg_base( - ea_t *pea, - thid_t tid, - int sreg_value, - qstring * /*errbuf*/) -{ - check_thread(false); - NODISTURB_ASSERT(in_event != NULL); - HANDLE h = get_thread_handle(tid); - if ( h == INVALID_HANDLE_VALUE ) - return DRC_FAILED; - -#ifndef __X86__ - - thread_info_t *ti = threads.get(tid); - if ( ti != NULL && ti->read_context(X86_RC_SEGMENTS) ) - { - // is this a TLS base register? (FS for wow64 and GS for x64) - CONTEXT &ctx = ti->get_ctx(); - if ( sreg_value == ctx.SegGs && (ti->flags & THR_WOW64) == 0 - || sreg_value == ctx.SegFs && (ti->flags & THR_WOW64) != 0 ) - { - // lpThreadLocalBase is the native (X64) TEB, or GS base - if ( sreg_value == ctx.SegGs ) - *pea = EA_T(ti->lpThreadLocalBase); - else - { - // fs base is the WoW64 TEB - // pointer to it is the first field in the native TEB - LPVOID tib32; - if ( _read_memory(EA_T(ti->lpThreadLocalBase), &tib32, sizeof(tib32)) != sizeof(tib32) ) - return DRC_FAILED; - *pea = EA_T(tib32); - } - return DRC_OK; - } - else if ( (ti->flags & THR_WOW64) != 0 ) - { - WOW64_LDT_ENTRY se; - if ( !_Wow64GetThreadSelectorEntry(h, sreg_value, &se) ) - { - if ( GetLastError() == ERROR_NOT_SUPPORTED ) - { - // in x64 all selectors except fs/gs are 0-based - *pea = 0; - return DRC_OK; - } - deberr("GetThreadSelectorEntry"); - return DRC_FAILED; - } - *pea = (se.HighWord.Bytes.BaseHi << 24) - | (se.HighWord.Bytes.BaseMid << 16) - | se.BaseLow; - return DRC_OK; - } - } -#endif // __X64__ - //below code works for non-x64 - LDT_ENTRY se; - if ( !GetThreadSelectorEntry(h, sreg_value, &se) ) - { - if ( GetLastError() == ERROR_NOT_SUPPORTED ) - { - *pea = 0; - return DRC_OK; - } - deberr("GetThreadSelectorEntry"); - return DRC_FAILED; - } - - *pea = (se.HighWord.Bytes.BaseHi << 24) - | (se.HighWord.Bytes.BaseMid << 16) - | se.BaseLow; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -#ifndef __X86__ -#define FloatSave FltSave // FIXME: use XMM save area! -#define RegisterArea FloatRegisters -#define FPUREG_ENTRY_SIZE 16 -#define XMMREG_PTR ((uchar *)&ctx.Xmm0) -#define XMMREG_MXCSR (ctx.FltSave.MxCsr) -#else -#define XMMREG_PTR ((uchar *)&ctx.ExtendedRegisters[0xA0]) -#define XMMREG_MXCSR (*(uint32 *)&ctx.ExtendedRegisters[0x18]) -#define FPUREG_ENTRY_SIZE 10 -#endif - -#define FPUREG_PTR ((uchar *)ctx.FloatSave.RegisterArea) - -//------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_write_register( - thid_t tid, - int reg_idx, - const regval_t *value, - qstring * /*errbuf*/) -{ - check_thread(false); - if ( value == NULL ) - return DRC_FAILED; - - NODISTURB_ASSERT(in_event != NULL); - - int regclass = get_reg_class(reg_idx); - if ( regclass == 0 ) - return DRC_FAILED; - - thread_info_t *ti = threads.get(tid); - if ( ti == NULL || !ti->read_context(regclass) ) - return DRC_FAILED; - CONTEXT &ctx = ti->get_ctx(); - - // Patch one field - patch_context_struct(ctx, reg_idx, ti, value); - - bool ok = ti->write_context(regclass); - if ( !ok ) - deberr("SetThreadContext"); - debdeb("write_register: %d\n", ok); - return ok ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -bool idaapi win32_debmod_t::write_registers( - thid_t tid, - int start, - int count, - const regval_t *values) -{ - thread_info_t *ti = threads.get(tid); - if ( ti == NULL ) - return false; - if ( !ti->read_context(X86_RC_ALL) ) - return false; - - CONTEXT &ctx = ti->get_ctx(); - for ( int i=0; i < count; i++, values++ ) - patch_context_struct(ctx, start + i, ti, values); - - bool ok = ti->write_context(X86_RC_ALL); - if ( !ok ) - deberr("SetThreadContext"); - debdeb("write_registers: %d\n", ok); - return ok; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_read_registers( - thid_t tid, - int clsmask, - regval_t *values, - qstring * /*errbuf*/) -{ - check_thread(false); - if ( values == NULL ) - return DRC_FAILED; - - NODISTURB_ASSERT(in_event != NULL); - - thread_info_t *ti = threads.get(tid); - if ( ti == NULL || !ti->read_context(clsmask) ) - return DRC_FAILED; - - CONTEXT &ctx = ti->get_ctx(); - if ( (clsmask & X86_RC_SEGMENTS) != 0 ) - { - values[R_CS].ival = ctx.SegCs; - values[R_DS].ival = ctx.SegDs; - values[R_ES].ival = ctx.SegEs; - values[R_FS].ival = ctx.SegFs; - values[R_GS].ival = ctx.SegGs; - values[R_SS].ival = ctx.SegSs; - } - if ( (clsmask & X86_RC_GENERAL) != 0 ) - { -#ifndef __X86__ - values[R_EAX].ival = ctx.Rax; - values[R_EBX].ival = ctx.Rbx; - values[R_ECX].ival = ctx.Rcx; - values[R_EDX].ival = ctx.Rdx; - values[R_ESI].ival = ctx.Rsi; - values[R_EDI].ival = ctx.Rdi; - values[R_EBP].ival = ctx.Rbp; - values[R_ESP].ival = ctx.Rsp; - values[R_EIP].ival = ctx.Rip; -# ifdef __EA64__ - values[R_R8 ].ival = ctx.R8; - values[R_R9 ].ival = ctx.R9; - values[R_R10].ival = ctx.R10; - values[R_R11].ival = ctx.R11; - values[R_R12].ival = ctx.R12; - values[R_R13].ival = ctx.R13; - values[R_R14].ival = ctx.R14; - values[R_R15].ival = ctx.R15; -# endif -#else - values[R_EAX].ival = ctx.Eax; - values[R_EBX].ival = ctx.Ebx; - values[R_ECX].ival = ctx.Ecx; - values[R_EDX].ival = ctx.Edx; - values[R_ESI].ival = ctx.Esi; - values[R_EDI].ival = ctx.Edi; - values[R_EBP].ival = ctx.Ebp; - values[R_ESP].ival = ctx.Esp; - values[R_EIP].ival = ctx.Eip; -#endif - values[R_EFLAGS].ival = ctx.EFlags; - } - if ( (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0 ) - { - if ( (clsmask & X86_RC_FPU) != 0 ) - { - values[R_CTRL].ival = ctx.FloatSave.ControlWord; - values[R_STAT].ival = ctx.FloatSave.StatusWord; - values[R_TAGS].ival = ctx.FloatSave.TagWord; - } - read_fpu_registers(values, clsmask, FPUREG_PTR, FPUREG_ENTRY_SIZE); - } - if ( (clsmask & X86_RC_XMM) != 0 ) - { - const uchar *xptr = XMMREG_PTR; - for ( int i=R_XMM0; i < R_MXCSR; i++,xptr+=16 ) - values[i].set_bytes(xptr, 16); - values[R_MXCSR].ival = XMMREG_MXCSR; - } - if ( (clsmask & X86_RC_YMM) != 0 ) - { - int idx = 0; - DWORD64 feature_mask = 0; - if ( context_helper.xstate_helpers_loaded() - && context_helper.pfnGetXStateFeaturesMask(&ctx, &feature_mask) != FALSE ) - { - DWORD xmm_blob_length = 0; - PM128A Xmm = (PM128A) context_helper.pfnLocateXStateFeature(&ctx, XSTATE_LEGACY_SSE, &xmm_blob_length); - PM128A Ymm = (PM128A) context_helper.pfnLocateXStateFeature(&ctx, XSTATE_AVX, NULL); - const int nxmm_regs = xmm_blob_length / sizeof(Xmm[0]); - const int nymm_regs = qmin(nxmm_regs, 16); - for ( ; idx < nymm_regs; idx++ ) - { -#ifdef __X86__ - if ( idx < I386_AVX_NREGS ) -#else - if ( idx < I386_AVX_NREGS || (ti->flags & THR_WOW64) == 0 ) -#endif - { - bytevec_t &storage = values[R_YMM0+idx].set_bytes(); - storage.resize(32, 0); - if ( Xmm != NULL ) - { - CASSERT(sizeof(Xmm[0].Low) == 8); - memcpy((void *) &storage[0], (void *) &Xmm[idx].Low, 8); - memcpy((void *) &storage[8], (void *) &Xmm[idx].High, 8); - } - if ( Ymm != NULL && (feature_mask & XSTATE_MASK_AVX) != 0 ) - { - CASSERT(sizeof(Ymm[0].Low) == 8); - memcpy((void *) &storage[16], (void *) &Ymm[idx].Low, 8); - memcpy((void *) &storage[24], (void *) &Ymm[idx].High, 8); - } - } - } - } - // All registers that were not set, will be marked as unavailable - for ( ; idx < R_LAST_YMM - R_YMM0 + 1; ++idx ) - values[R_YMM0+idx].set_unavailable(); - } - //? others registers - - return DRC_OK; -} - -//-------------------------------------------------------------------------- -bool thread_info_t::toggle_tbit(bool set_tbit) -{ - if ( !read_context(X86_RC_GENERAL) ) - return false; - - bool ok = true; - CASSERT(EFLAGS_TRAP_FLAG == 0x100); // so we can shift set_tbit << 8 - CONTEXT &ctx = get_ctx(); - if ( (ctx.EFlags & EFLAGS_TRAP_FLAG) != (set_tbit << 8) ) //lint !e647 possible truncation before conversion from 'int' to 'unsigned long' - { - QASSERT(30117, (ctx.ContextFlags & CONTEXT_CONTROL) != 0); - ctx.EFlags |= EFLAGS_TRAP_FLAG; - int saved = ctx.ContextFlags; - ctx.ContextFlags = CONTEXT_CONTROL; - ok = write_context(X86_RC_GENERAL); - ctx.ContextFlags = saved; - if ( ok ) - setflag(flags, THR_TRACING, set_tbit); - else - debmod->deberr("%d: SetThreadContext failed", tid); - } - return ok; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_set_resume_mode(thid_t tid, resume_mode_t resmod) -{ - if ( resmod != RESMOD_INTO ) - return DRC_FAILED; // not supported - - check_thread(false); - NODISTURB_ASSERT(in_event != NULL); - thread_info_t *ti = threads.get(tid); - if ( ti == NULL ) - return DRC_FAILED; - - bool ok = ti->toggle_tbit(true); - if ( !ok ) - deberr("%d: (set_step) SetThreadContext failed", tid); - return ok ? DRC_OK : DRC_FAILED; -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::clear_tbit(thread_info_t &ti) -{ - NODISTURB_ASSERT(in_event != NULL); - bool ok = ti.toggle_tbit(false); - if ( !ok ) - deberr("%d: (clr_step) SetThreadContext failed", ti.tid); - return ok; -} - -//-------------------------------------------------------------------------- -// invalidate registers of all threads -void win32_debmod_t::invalidate_all_contexts(void) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - p->second.invalidate_context(); -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_continue_after_event(const debug_event_t *event) -{ - check_thread(false); - NODISTURB_ASSERT(in_event != NULL || exiting); - - if ( event == NULL ) - return DRC_FAILED; - - if ( events.empty() ) - { - bool done = false; - if ( !done ) //-V547 '!done' is always true - { - // check if we need to install the workaround for single stepping over callgates - thread_info_t *ti = threads.get(event->tid); - if ( ti != NULL && ti->is_tracing() ) - { - if ( check_for_call_large(event, process_handle) ) - install_callgate_workaround(ti, event); - } - - int flag = event->handled ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED; - if ( !ContinueDebugEvent(event->pid, event->tid, flag) ) - { - deberr("ContinueDebugEvent"); - return DRC_FAILED; - } - debdeb("ContinueDebugEvent: handled=%s\n", event->handled ? "yes" : "no"); - if ( event->eid() == PROCESS_EXITED ) - { - // from WaitForDebugEvent help page: - // If the system previously reported an EXIT_PROCESS_DEBUG_EVENT debugging event, - // the system closes the handles to the process and thread when the debugger calls the ContinueDebugEvent function. - // => we don't close these handles to avoid error messages - cpdi.hProcess = INVALID_HANDLE_VALUE; - cpdi.hThread = INVALID_HANDLE_VALUE; - process_handle= INVALID_HANDLE_VALUE; - thread_handle = INVALID_HANDLE_VALUE; - cleanup(); - } - } - invalidate_all_contexts(); - } - in_event = NULL; - return DRC_OK; -} - -//-------------------------------------------------------------------------- -drc_t idaapi win32_debmod_t::dbg_exit_process(qstring * /*errbuf*/) -{ - check_thread(false); - // WindowsCE sometimes reports failure but terminates the application. - // We ignore the return value. - bool check_termination_code = prepare_to_stop_process(in_event, threads); - bool terminated = TerminateProcess(process_handle, -1) != 0; - if ( !terminated && check_termination_code ) - { - deberr("TerminateProcess"); - return DRC_FAILED; - } - exiting = true; - - if ( in_event != NULL && dbg_continue_after_event(in_event) != DRC_OK ) - { - deberr("continue_after_event"); - return DRC_FAILED; - } - return DRC_OK; -} - - -//-------------------------------------------------------------------------- -void win32_debmod_t::show_exception_record(const EXCEPTION_RECORD &er, int level) -{ - char name[MAXSTR]; - get_exception_name(er.ExceptionCode, name, sizeof(name)); - if ( level > 0 ) - dmsg("%*c", level, ' '); - dmsg("%s: fl=%X adr=%a #prm=%d\n", - name, - er.ExceptionFlags, - EA_T(er.ExceptionAddress), - er.NumberParameters); - if ( er.NumberParameters > 0 ) - { - dmsg("%*c", level+2, ' '); - int n = qmin(er.NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS); - for ( int i=0; i < n; i++ ) - dmsg("%s0x%a", i == 0 ? "" : " ", ea_t(er.ExceptionInformation[i])); - dmsg("\n"); - } - if ( er.ExceptionRecord != NULL ) - show_exception_record(*er.ExceptionRecord, level+2); -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::show_debug_event(const DEBUG_EVENT &ev) -{ - if ( !debug_debugger ) - return; - dmsg("[%u %d] ", ev.dwProcessId, ev.dwThreadId); - switch ( ev.dwDebugEventCode ) - { - case EXCEPTION_DEBUG_EVENT: - { - const EXCEPTION_RECORD &er = ev.u.Exception.ExceptionRecord; - dmsg("EXCEPTION: ea=%p first: %d", // no \n intentionally - er.ExceptionAddress, ev.u.Exception.dwFirstChance); - show_exception_record(er); - } - break; - - case CREATE_THREAD_DEBUG_EVENT: - dmsg("CREATE_THREAD: hThread=%X LocalBase=%p Entry=%p\n", - ev.u.CreateThread.hThread, - ev.u.CreateThread.lpThreadLocalBase, - ev.u.CreateThread.lpStartAddress); - break; - - case CREATE_PROCESS_DEBUG_EVENT: - { - const CREATE_PROCESS_DEBUG_INFO &cpinf = ev.u.CreateProcessInfo; - char path[QMAXPATH]; - if ( process_handle == INVALID_HANDLE_VALUE ) - process_handle = cpinf.hProcess; - get_filename_for( - path, - sizeof(path), - eanat_t(cpinf.lpImageName), - cpinf.fUnicode != 0, - eanat_t(cpinf.lpBaseOfImage)); - dmsg("CREATE_PROCESS: hFile=%X hProcess=%X hThread=%X " - "base=%p\n dbgoff=%X dbgsiz=%X tlbase=%p start=%p name=%p '%s' \n", - cpinf.hFile, cpinf.hProcess, cpinf.hThread, cpinf.lpBaseOfImage, - cpinf.dwDebugInfoFileOffset, cpinf.nDebugInfoSize, cpinf.lpThreadLocalBase, - cpinf.lpStartAddress, cpinf.lpImageName, path); - } - break; - - case EXIT_THREAD_DEBUG_EVENT: - dmsg("EXIT_THREAD: code=%d\n", ev.u.ExitThread.dwExitCode); - break; - - case EXIT_PROCESS_DEBUG_EVENT: - dmsg("EXIT_PROCESS: code=%d\n", ev.u.ExitProcess.dwExitCode); - break; - - case LOAD_DLL_DEBUG_EVENT: - { - char path[QMAXPATH]; - const LOAD_DLL_DEBUG_INFO &di = ev.u.LoadDll; - get_filename_for( - path, - sizeof(path), - eanat_t(di.lpImageName), - di.fUnicode != 0, - eanat_t(di.lpBaseOfDll)); - dmsg("LOAD_DLL: h=%X base=%p dbgoff=%X dbgsiz=%X name=%X '%s'\n", - di.hFile, di.lpBaseOfDll, di.dwDebugInfoFileOffset, di.nDebugInfoSize, - di.lpImageName, path); - } - break; - - case UNLOAD_DLL_DEBUG_EVENT: - dmsg("UNLOAD_DLL: base=%p\n", ev.u.UnloadDll.lpBaseOfDll); - break; - - case OUTPUT_DEBUG_STRING_EVENT: - { - char buf[MAXSTR]; - get_debug_string(ev, buf, sizeof(buf)); - dmsg("OUTPUT_DEBUG_STRING: str=\"%s\"\n", buf); - } - break; - - case RIP_EVENT: - dmsg("RIP_EVENT (system debugging error)\n"); - break; - - default: - dmsg("UNKNOWN_DEBUG_EVENT %d\n", ev.dwDebugEventCode); - break; - } -} - -//-------------------------------------------------------------------------- -void win32_debmod_t::patch_context_struct( - CONTEXT &ctx, - int reg_idx, - const thread_info_t *ti, - const regval_t *value) const -{ - switch ( reg_idx ) - { - case R_CS: ctx.SegCs = WORD(value->ival); break; - case R_DS: ctx.SegDs = WORD(value->ival); break; - case R_ES: ctx.SegEs = WORD(value->ival); break; - case R_FS: ctx.SegFs = WORD(value->ival); break; - case R_GS: ctx.SegGs = WORD(value->ival); break; - case R_SS: ctx.SegSs = WORD(value->ival); break; -#ifndef __X86__ - case R_EAX: ctx.Rax = value->ival; break; - case R_EBX: ctx.Rbx = value->ival; break; - case R_ECX: ctx.Rcx = value->ival; break; - case R_EDX: ctx.Rdx = value->ival; break; - case R_ESI: ctx.Rsi = value->ival; break; - case R_EDI: ctx.Rdi = value->ival; break; - case R_EBP: ctx.Rbp = value->ival; break; - case R_ESP: ctx.Rsp = value->ival; break; - case R_EIP: ctx.Rip = value->ival; break; -# ifdef __EA64__ - case R_R8: ctx.R8 = value->ival; break; - case R_R9 : ctx.R9 = value->ival; break; - case R_R10: ctx.R10 = value->ival; break; - case R_R11: ctx.R11 = value->ival; break; - case R_R12: ctx.R12 = value->ival; break; - case R_R13: ctx.R13 = value->ival; break; - case R_R14: ctx.R14 = value->ival; break; - case R_R15: ctx.R15 = value->ival; break; -# endif -#else - case R_EAX: ctx.Eax = (size_t)value->ival; break; - case R_EBX: ctx.Ebx = (size_t)value->ival; break; - case R_ECX: ctx.Ecx = (size_t)value->ival; break; - case R_EDX: ctx.Edx = (size_t)value->ival; break; - case R_ESI: ctx.Esi = (size_t)value->ival; break; - case R_EDI: ctx.Edi = (size_t)value->ival; break; - case R_EBP: ctx.Ebp = (size_t)value->ival; break; - case R_ESP: ctx.Esp = (size_t)value->ival; break; - case R_EIP: ctx.Eip = (size_t)value->ival; break; -#ifdef __EA64__ - case R_R8: break; - case R_R9 : break; - case R_R10: break; - case R_R11: break; - case R_R12: break; - case R_R13: break; - case R_R14: break; - case R_R15: break; -#endif -#endif - case R_TAGS: ctx.FloatSave.TagWord = WORD(value->ival); break; - case R_EFLAGS: ctx.EFlags = DWORD(value->ival); break; - case R_CTRL: ctx.FloatSave.ControlWord = WORD(value->ival); break; - case R_STAT: ctx.FloatSave.StatusWord = WORD(value->ival); break; - case R_MXCSR: XMMREG_MXCSR = value->ival; break; - default: - { - void *xptr = NULL; - // uint8 ymm_storage[32]; - int nbytes = 0; - int regclass = get_reg_class(reg_idx); - if ( (regclass & X86_RC_XMM) != 0 ) - { // XMM registers - xptr = XMMREG_PTR + (reg_idx - R_XMM0) * 16; - nbytes = 16; - } - else if ( (regclass & X86_RC_YMM) != 0 ) - { // YMM registers - if ( context_helper.xstate_helpers_loaded() ) - { - if ( context_helper.pfnSetXStateFeaturesMask(&ctx, XSTATE_MASK_AVX) != FALSE ) - { - DWORD xmm_blob_length = 0; - PM128A Xmm = (PM128A) context_helper.pfnLocateXStateFeature(&ctx, XSTATE_LEGACY_SSE, &xmm_blob_length); - PM128A Ymm = (PM128A) context_helper.pfnLocateXStateFeature(&ctx, XSTATE_AVX, NULL); - const int nxmm_regs = xmm_blob_length / sizeof(Xmm[0]); - const int nymm_regs = qmin(nxmm_regs, 16); - const int ymm_idx = reg_idx - R_YMM0; -#ifdef __X86__ - if ( ymm_idx < nymm_regs && ymm_idx < I386_AVX_NREGS ) -#else - if ( ymm_idx < nymm_regs && (ymm_idx < I386_AVX_NREGS || (ti->flags & THR_WOW64) == 0 ) ) -#endif - { - struct ida_local writer_t - { - const uint8 *data; - size_t bytes_left; - - writer_t(const regval_t *_value) - { - data = (const uint8 *) _value->get_data(); - bytes_left = _value->get_data_size(); - } - - void put8(uint64 *storage) - { - if ( storage != NULL ) - { - const size_t to_write = qmin(8, bytes_left); - if ( to_write > 0 ) - { - memcpy((void *) storage, (void *) &data[0], to_write); - bytes_left -= to_write; - data += to_write; - } - } - else - { - const size_t to_write = qmin(8, bytes_left); - bytes_left -= to_write; - data += to_write; - } - } - - void put16(PM128A storage) - { - if ( storage != NULL ) - { - put8((uint64 *) &storage->Low); - put8((uint64 *) &storage->High); - } - else - { - const size_t to_write = qmin(16, bytes_left); - bytes_left -= to_write; - data += to_write; - } - } - }; - writer_t writer(value); - writer.put16(&Xmm[ymm_idx]); - writer.put16(&Ymm[ymm_idx]); - } - else - { - Xmm[ymm_idx].Low = 0; - Xmm[ymm_idx].High = 0; - Ymm[ymm_idx].Low = 0; - Ymm[ymm_idx].High = 0; - } - } - } - break; // don't do the xptr copying thing - } - else if ( (regclass & X86_RC_FPU) != 0 ) - { - xptr = FPUREG_PTR + (reg_idx-R_ST0) * FPUREG_ENTRY_SIZE; - nbytes = 10; - } - else if ( (regclass & X86_RC_MMX) != 0 ) - { - xptr = FPUREG_PTR + (reg_idx-R_MMX0) * FPUREG_ENTRY_SIZE; - nbytes = 8; - } - else - { - INTERR(30118); - } - const void *vptr = value->get_data(); - size_t size = value->get_data_size(); - memcpy(xptr, vptr, qmin(size, nbytes)); //-V575 null pointer 'xptr' - } - break; - } - qnotused(ti); -} - -//-------------------------------------------------------------------------- -int win32_debmod_t::dbg_freeze_threads_except(thid_t tid) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - if ( p->first != tid ) - _sure_suspend_thread(p->second, true); - return 1; -} - -//-------------------------------------------------------------------------- -int win32_debmod_t::dbg_thaw_threads_except(thid_t tid) -{ - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - if ( p->first != tid ) - _sure_resume_thread(p->second, true); - return 1; -} - -//-------------------------------------------------------------------------- -// if we have to do something as soon as we noticed the connection -// broke, this is the correct place -bool idaapi win32_debmod_t::dbg_prepare_broken_connection(void) -{ - broken_connection = true; - bool ret = false; - if ( restore_broken_breakpoints() ) - { - // create the required event for synchronization; we use it - // to notify when the process was successfully detached - broken_event_handle = CreateEvent(NULL, false, false, NULL); - - if ( broken_event_handle != NULL ) - { - int code = WAIT_TIMEOUT; - while ( code == WAIT_TIMEOUT ) - code = WaitForSingleObject(broken_event_handle, 100); - - if ( code == WAIT_OBJECT_0 ) - { - suspend_running_threads(_suspended_threads); - if ( dbg_detach_process() == DRC_OK ) - SetEvent(broken_event_handle); - } - } - } - - return ret; -} - -//-------------------------------------------------------------------------- -// Continuing from a broken connection in win32 debugger consist in the -// following step (if we're talking about a single threaded server): -// -// 1 - Notify the other thread that we want to reuse that connection -// 2 - Wait for the previous thread to notify that finished his work -// 3 - Reattach to the process and reopen thread's handles as, for a -// reason, the handles we have are invalid (why?). -// 4 - Resume the threads we suspended before. -// -bool idaapi win32_debmod_t::dbg_continue_broken_connection(pid_t _pid) -{ - debmod_t::dbg_continue_broken_connection(_pid); - - QASSERT(676, broken_event_handle != NULL); - - // notify the broken thread we want to reuse the connection - SetEvent(broken_event_handle); - - // and wait for the notification for a maximum of 15 seconds - // as we don't want to wait forever (INFINITE) because the - // other thread may fail - int code = WaitForSingleObject(broken_event_handle, 15000); - if ( code != WAIT_OBJECT_0 ) - { - msg("Error restoring broken connection"); - return false; - } - - if ( dbg_attach_process(_pid, -1, 0, NULL) == DRC_OK && reopen_threads() ) - { - resume_suspended_threads(_suspended_threads); - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -bool win32_debmod_t::reopen_threads(void) -{ - if ( _OpenThread == NULL ) - return false; - - for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) - { - HANDLE hThread; - hThread = _OpenThread(THREAD_ALL_ACCESS, true, p->second.tid); - if ( hThread != NULL ) - p->second.hThread = hThread; - else - deberr("OpenThread"); - p->second.suspend_count = get_thread_suspend_count(hThread); - } - return true; -} - -//-------------------------------------------------------------------------- -static bool enable_privilege(LPCTSTR privilege, bool enable); -static bool g_subsys_inited = false; -static bool g_got_debpriv = false; - -bool init_subsystem() -{ - if ( g_subsys_inited ) - return true; - - if ( !win32_debmod_t::winver.ok() ) - return false; - - win_tool_help_t *wth = win32_debmod_t::get_tool_help(); - if ( wth->ok() ) - g_code |= DBG_HAS_GET_PROCESSES; - - // DebugActiveProcessStop() is only available on XP/2K3 - if ( wth->use_debug_detach_process() ) - g_code |= DBG_HAS_DETACH_PROCESS; - - g_got_debpriv = enable_privilege(SE_DEBUG_NAME, true); - if ( !g_got_debpriv ) - msg("Cannot set debug privilege: %s.\n" - "Debugging of processes owned by another account won't be possible.\n", - winerr(GetLastError())); - - win32_debmod_t::reuse_broken_connections = true; - init_win32_subsystem(); - - HINSTANCE h = GetModuleHandle(kernel32_dll); - *(FARPROC*)&_OpenThread = GetProcAddress(h, TEXT("OpenThread")); - *(FARPROC*)&_GetThreadDescription = GetProcAddress(h, TEXT("GetThreadDescription")); - -#ifndef __X86__ - *(FARPROC*)&_Wow64GetThreadContext = GetProcAddress(h, TEXT("Wow64GetThreadContext")); - *(FARPROC*)&_Wow64SetThreadContext = GetProcAddress(h, TEXT("Wow64SetThreadContext")); - *(FARPROC*)&_Wow64GetThreadSelectorEntry = GetProcAddress(h, TEXT("Wow64GetThreadSelectorEntry")); -#endif - - g_subsys_inited = g_code != 0; - return g_subsys_inited; -} - -//-------------------------------------------------------------------------- -bool term_subsystem() -{ - if ( !g_subsys_inited ) - return true; - - g_subsys_inited = false; - - if ( g_got_debpriv ) - { - enable_privilege(SE_DEBUG_NAME, false); - g_got_debpriv = false; - } - - term_win32_subsystem(); - return true; -} - -//-------------------------------------------------------------------------- -debmod_t *create_debug_session(void *) -{ - return new win32_debmod_t(); -} - -//-------------------------------------------------------------------------- -// -// DEBUG PRIVILEGE -// -//-------------------------------------------------------------------------- -// dynamic linking information for Advapi functions -static HMODULE hAdvapi32 = NULL; -// function prototypes -typedef BOOL (WINAPI *OpenProcessToken_t)( - HANDLE ProcessHandle, - DWORD DesiredAccess, - PHANDLE TokenHandle); -typedef BOOL (WINAPI *LookupPrivilegeValue_t)( - LPCTSTR lpSystemName, - LPCTSTR lpName, - PLUID lpLuid); -typedef BOOL (WINAPI *AdjustTokenPrivileges_t)( - HANDLE TokenHandle, - BOOL DisableAllPrivileges, - PTOKEN_PRIVILEGES NewState, - DWORD BufferLength, - PTOKEN_PRIVILEGES PreviousState, - PDWORD ReturnLength); - -// Function pointers -static OpenProcessToken_t _OpenProcessToken = NULL; -static LookupPrivilegeValue_t _LookupPrivilegeValue = NULL; -static AdjustTokenPrivileges_t _AdjustTokenPrivileges = NULL; - -//-------------------------------------------------------------------------- -static void term_advapi32(void) -{ - if ( hAdvapi32 != NULL ) - { - DWORD code = GetLastError(); - FreeLibrary(hAdvapi32); - SetLastError(code); - hAdvapi32 = NULL; - } -} - -//-------------------------------------------------------------------------- -static bool init_advapi32(void) -{ - // load the library - hAdvapi32 = LoadLibrary(TEXT("advapi32.dll")); - if ( hAdvapi32 == NULL ) - return false; - - // find the needed functions - *(FARPROC*)&_OpenProcessToken = GetProcAddress(hAdvapi32, TEXT("OpenProcessToken")); - *(FARPROC*)&_LookupPrivilegeValue = GetProcAddress(hAdvapi32, TEXT(LookupPrivilegeValue_Name)); - *(FARPROC*)&_AdjustTokenPrivileges = GetProcAddress(hAdvapi32, TEXT("AdjustTokenPrivileges")); - - bool ok = _OpenProcessToken != NULL - && _LookupPrivilegeValue != NULL - && _AdjustTokenPrivileges != NULL; - if ( !ok ) - term_advapi32(); - return ok; -} - - -//-------------------------------------------------------------------------- -// based on code from: -// http://support.microsoft.com/support/kb/articles/Q131/0/65.asp -static bool enable_privilege(LPCTSTR privilege, bool enable) -{ - if ( !win32_debmod_t::winver.is_NT() ) // no privileges on 9X/ME - return true; - - bool ok = false; - if ( init_advapi32() ) - { - HANDLE hToken; - DWORD tokens = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY; - if ( _OpenProcessToken(GetCurrentProcess(), tokens, &hToken) ) - { - LUID luid; - if ( _LookupPrivilegeValue(NULL, privilege, &luid) ) - { - TOKEN_PRIVILEGES tp; - memset(&tp, 0, sizeof(tp)); - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; - ok = _AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL) != FALSE; - } - CloseHandle(hToken); - } - term_advapi32(); - } - return ok; -} diff --git a/idasdk75/dbg/win32/win32_debmod.h b/idasdk75/dbg/win32/win32_debmod.h deleted file mode 100644 index eca8568..0000000 --- a/idasdk75/dbg/win32/win32_debmod.h +++ /dev/null @@ -1,428 +0,0 @@ -#ifndef __WIN32_DEBUGGER_MODULE__ -#define __WIN32_DEBUGGER_MODULE__ - -#include -#include -#include "../../ldr/pe/pe.h" -#include "winbase_debmod.h" - -//-V::720 It is advised to utilize the 'SuspendThread' function only when developing a debugger - -// Type definitions - -class win32_debmod_t; - -//-------------------------------------------------------------------------- -// image information -struct image_info_t -{ - image_info_t() { memset(this, 0, sizeof(*this)); } - image_info_t(win32_debmod_t *); - image_info_t(win32_debmod_t *, ea_t _base, uint32 _imagesize, const qstring &_name); - image_info_t(win32_debmod_t *, const LOAD_DLL_DEBUG_INFO &i, uint32 _imagesize, const char *_name); - image_info_t(win32_debmod_t *, const modinfo_t &m); - - win32_debmod_t *sess; - ea_t base; - uval_t imagesize; - qstring name; - LOAD_DLL_DEBUG_INFO dll_info; -}; - -// key: image base address -typedef std::map images_t; - -//------------------------------------------------------------------------- -struct context_holder_t -{ - bytevec_t buffer; - PCONTEXT ptr; - - context_holder_t() : ptr(NULL) {} -}; - -//------------------------------------------------------------------------- -struct context_helper_t -{ - typedef DWORD64 (WINAPI *PGETENABLEDXSTATEFEATURES)(); - PGETENABLEDXSTATEFEATURES pfnGetEnabledXStateFeatures; - - typedef BOOL (WINAPI *PINITIALIZECONTEXT)(PVOID Buffer, DWORD ContextFlags, PCONTEXT *Context, PDWORD ContextLength); - PINITIALIZECONTEXT pfnInitializeContext; - - typedef BOOL (WINAPI *PGETXSTATEFEATURESMASK)(PCONTEXT Context, PDWORD64 FeatureMask); - PGETXSTATEFEATURESMASK pfnGetXStateFeaturesMask; - - typedef PVOID (WINAPI *LOCATEXSTATEFEATURE)(PCONTEXT Context, DWORD FeatureId, PDWORD Length); - LOCATEXSTATEFEATURE pfnLocateXStateFeature; - - typedef BOOL (WINAPI *SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask); - SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask; - - typedef BOOL (WINAPI *COPYCONTEXT)(PCONTEXT Destination, DWORD ContextFlags, PCONTEXT Source); - COPYCONTEXT pfnCopyContext; - - int xstate_context_size; - bool get_xstate_context_size(int *out_ctxsz); - context_helper_t() { clear(); } - bool create_context(context_holder_t *out, int *ctxflags); - bool xstate_helpers_loaded() const { return xstate_context_size > 0; } - void clear(); -}; - -//-------------------------------------------------------------------------- -// thread information -struct thread_info_t : public CREATE_THREAD_DEBUG_INFO -{ - thread_info_t( - win32_debmod_t *dm, - const CREATE_THREAD_DEBUG_INFO &i, - thid_t t, - wow64_state_t wow64_state); - win32_debmod_t *debmod; - thid_t tid; // thread id - int suspend_count; - ea_t bpt_ea; - int flags; -#define THR_CLSMASK 0x0007 // valid register classes in CONTEXT structure - // we use X86_RC.. constants here -#define THR_TRACING 0x0100 // expecting a STEP event -#define THR_FSSAVED 0x0200 // remembered FS value -#define THR_WOW64 0x0400 // is wow64 process? -#define THR_NEWNAME 0x0800 // thread was renamed - context_holder_t ctx_holder; - ea_t callgate_ea; - qstring name; - - void invalidate_context(void) { flags &= ~THR_CLSMASK; if ( ctx_holder.ptr != NULL ) get_ctx().ContextFlags = 0; } - bool read_context(int clsmask); - bool write_context(int clsmask); - void cvt_from_wow64( - const WOW64_CONTEXT &wow64ctx, - int clsmask, - PCONTEXT xstate_ctx) const; - void cvt_to_wow64( - WOW64_CONTEXT *wow64ctx, - PCONTEXT xstate_ctx, - int clsmask) const; - bool toggle_tbit(bool set_tbit); - bool is_tracing(void) const { return (flags & THR_TRACING) != 0; } - void set_tracing(void) { flags |= THR_TRACING; } - void clr_tracing(void) { flags &= ~THR_TRACING; } -#ifdef __X86__ - ea_t get_ip(void) { return read_context(X86_RC_GENERAL) ? get_ctx().Eip : BADADDR; } -#else - ea_t get_ip(void) { return read_context(X86_RC_GENERAL) ? get_ctx().Rip : BADADDR; } -#endif - bool is_new_name(void) const { return (flags & THR_NEWNAME) != 0; } - void clr_new_name(void) { flags &= ~THR_NEWNAME; } - void set_new_name(void) { flags |= THR_NEWNAME; } - CONTEXT &get_ctx() const { QASSERT(1669, ctx_holder.ptr != NULL); return *ctx_holder.ptr; } -}; - -//-------------------------------------------------------------------------- -inline thread_info_t::thread_info_t( - win32_debmod_t *dm, - const CREATE_THREAD_DEBUG_INFO &i, - thid_t t, - wow64_state_t wow64_state) - : CREATE_THREAD_DEBUG_INFO(i), tid(t), suspend_count(0), bpt_ea(BADADDR), - debmod(dm), - flags(wow64_state > 0 ? THR_WOW64 : 0), - callgate_ea(0) -{ -} - -//-------------------------------------------------------------------------- -// Check if the context structure has valid values at the specified portion -// portion is a conbination of CONTEXT_... bitmasks -inline bool has_portion(const CONTEXT &ctx, int portion) -{ - return (ctx.ContextFlags & portion & 0xFFFF) != 0; -} - -//-------------------------------------------------------------------------- -// (tid -> info) -struct threads_t: public std::map -{ - thread_info_t *get(DWORD tid) - { - const iterator it = find(tid); - if ( it == end() ) - return NULL; - return &it->second; - } -}; - -//-------------------------------------------------------------------------- -typedef qvector threadvec_t; - -//-------------------------------------------------------------------------- -// structure for the internal breakpoint information for threads -struct internal_bpt_info_t -{ - int count; // number of times this breakpoint is 'set' - uchar orig_bytes[BPT_CODE_SIZE]; // original byte values -}; -typedef std::map bpt_info_t; - -//-------------------------------------------------------------------------- -typedef int (*process_cb_t)(debmod_t *, PROCESSENTRY32 *pe32, void *ud); -typedef int (*module_cb_t)(debmod_t *, MODULEENTRY32 *me32, void *ud); - -//---------------------------------------------------------------------------- -// A live PDB session, that will be used remotely (typically by non-windows machines). -struct pdb_remote_session_t; -void close_pdb_remote_session(pdb_remote_session_t *); - -//Wow64-specific events -#ifndef STATUS_WX86_BREAKPOINT -# define STATUS_WX86_BREAKPOINT 0x4000001f -#endif -#ifndef STATUS_WX86_SINGLE_STEP -# define STATUS_WX86_SINGLE_STEP 0x4000001e -#endif - -//-------------------------------------------------------------------------- -class win32_debmod_t : public winbase_debmod_t -{ - typedef winbase_debmod_t inherited; - - gdecode_t get_debug_event(debug_event_t *event, int timeout_ms); - void check_thread(bool must_be_main_thread) const; - void add_thread(const CREATE_THREAD_DEBUG_INFO &thr_info, thid_t tid); - void install_callgate_workaround(thread_info_t *ti, const debug_event_t *event); - int describe_stack_segment( - thid_t tid, - images_t &thr_ranges, - images_t &cls_ranges, - const _NT_TIB &tib, - const char *pref); - void update_thread_names(thread_name_vec_t *thr_names); - - bool get_pe_exports_from_path( - const char *path, - linput_t *li, - ea_t imagebase, - name_info_t &ni, - const char *exported_name=NULL) const; - void patch_context_struct( - CONTEXT &ctx, - int reg_idx, - const thread_info_t *ti, - const regval_t *value) const; - -public: - // debugged process information - qstring process_path; - HANDLE thread_handle; - HANDLE redirin_handle; - HANDLE redirout_handle; - attach_status_t attach_status; - HANDLE attach_evid; - int8 expecting_debug_break; - bool stop_at_ntdll_bpts; - - images_t curproc; // image of the running process - images_t dlls; // list of loaded DLLs - images_t images; // list of detected PE images - images_t thread_ranges; // list of ranges related to threads - images_t class_ranges; // list of ranges related to class names - - easet_t dlls_to_import; // list of dlls to import information from - modinfo_t binary_to_import; // executable to import information from - - bpt_info_t thread_bpts; - - threads_t threads; - - // ID of a thread for which we must emulate a STEP event on XP (using a breakpoint) - thid_t winxp_step_thread; - - CREATE_PROCESS_DEBUG_INFO cpdi; - - debug_event_t *in_event; // current debug event - bool fake_suspend_event; - bool exiting; - bool pause_requested; - procinfo_vec_t processes; - - // threads suspended by the fiber created for restoring broken connections - threadvec_t _suspended_threads; - // event to wait until the broken connection is completely restored - HANDLE broken_event_handle; - context_helper_t context_helper; - - // Module specific methods, to be implemented - virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; - virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; - virtual void idaapi dbg_term(void) override; - virtual drc_t idaapi dbg_detach_process(void) override; - virtual drc_t idaapi dbg_start_process( - const char *path, - const char *args, - const char *startdir, - int flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) override; - virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; - virtual drc_t idaapi dbg_attach_process( - pid_t process_id, - int event_id, - int flags, - qstring *errbuf) override; - virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; - virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; - virtual void idaapi dbg_stopped_at_debug_event( - import_infos_t *infos, - bool dlls_added, - thread_name_vec_t *thr_names) override; - virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; - virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; - virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; - virtual drc_t idaapi dbg_read_registers( - thid_t thread_id, - int clsmask, - regval_t *values, - qstring *errbuf) override; - virtual drc_t idaapi dbg_write_register( - thid_t thread_id, - int reg_idx, - const regval_t *value, - qstring *errbuf) override; - - virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) override; - virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) override; - virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; - virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; - virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; - virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; - virtual int idaapi handle_ioctl(int fn, const void *buf, size_t size, void **outbuf, ssize_t *outsize) override; - // - win32_debmod_t(); - ~win32_debmod_t() { cleanup(); } - - void handle_pdb_thread_request(void *data); - uint32 calc_imagesize(eanat_t base); - bool get_filename_for( - char *buf, - size_t bufsize, - eanat_t image_name_ea, - bool use_unicode, - eanat_t image_base); - ea_t get_dll_export( - const images_t &dlls, - ea_t imagebase, - const char *exported_name); - - bool create_process( - const char *path, - const char *args, - const char *startdir, - bool is_gui, - bool hide_window, - PROCESS_INFORMATION *ProcessInformation); - - void show_debug_event(const DEBUG_EVENT &ev); - - ssize_t _read_memory(eanat_t ea, void *buffer, size_t size, bool suspend = false); - ssize_t _write_memory(eanat_t ea, const void *buffer, size_t size, bool suspend = false); - - int rdmsr(int reg, uint64 *value); - int wrmsr(int reg, uint64 value); - int kldbgdrv_access_msr(struct SYSDBG_MSR *msr, bool write); - - // !! OVERWRITTEN METHODS !! - bool refresh_hwbpts(); - - // Utility methods - gdecode_t handle_exception(debug_event_t *event, - const EXCEPTION_RECORD &er, - bool was_thread_bpt, - bool firsttime); - ssize_t access_memory(eanat_t ea, void *buffer, ssize_t size, bool write, bool suspend); - inline void resume_all_threads(bool raw = false); - inline void suspend_all_threads(bool raw = false); - size_t add_dll(image_info_t &ii); - bool module_present(const char *modname); - HANDLE get_thread_handle(thid_t tid); - static int get_dmi_cb(debmod_t *sess, MODULEENTRY32 *me32, void *ud); - void get_debugged_module_info(modinfo_t *dmi); - int for_each_module(DWORD pid, module_cb_t module_cb, void *ud); - bool myCloseHandle(HANDLE &h); - void cleanup(void); - void restore_original_bytes(ea_t ea, bool really_restore = true); - int save_original_bytes(ea_t ea); - bool set_thread_bpt(thread_info_t &ti, ea_t ea); - bool del_thread_bpt(thread_info_t &ti, ea_t ea); - bool del_thread_bpts(ea_t ea); - bool has_bpt_at(ea_t ea); - bool can_access(ea_t addr); - ea_t get_kernel_bpt_ea(ea_t ea, thid_t tid); - void create_attach_event(debug_event_t *event, bool attached); - void create_start_event(debug_event_t *event); - bool check_for_hwbpt(debug_event_t *event, bool is_stepping=false); - ea_t get_region_info(ea_t ea, memory_info_t *info); - bool get_dll_exports( - const images_t &dlls, - ea_t imagebase, - name_info_t &ni, - const char *exported_name = NULL); - bool get_filename_from_process( - eanat_t name_ea, - bool is_unicode, - char *buf, - size_t bufsize); - bool get_debug_string(const DEBUG_EVENT &ev, char *buf, size_t bufsize); - int add_thread_ranges( - thid_t tid, - images_t &thread_ranges, - images_t &class_ranges); - ea_t get_pe_header(eanat_t imagebase, peheader_t *nh); - bool get_pe_export_name_from_process( - eanat_t imagebase, - char *name, - size_t namesize); - - void show_exception_record(const EXCEPTION_RECORD &er, int level=0); - - eanat_t pstos0(eanat_t ea); - eanat_t s0tops(eanat_t ea); - - bool prepare_to_stop_process(debug_event_t *, const threads_t &); - bool disable_hwbpts(); - bool enable_hwbpts(); - bool may_write(ea_t ea); - LPVOID correct_exe_image_base(LPVOID base); - bool clear_tbit(thread_info_t &th); - void invalidate_all_contexts(void); - void enqueue_event(const debug_event_t &ev, queue_pos_t pos); - - void suspend_running_threads(threadvec_t &suspended); - void resume_suspended_threads(threadvec_t suspended) const; - bool reopen_threads(void); - - virtual bool idaapi write_registers( - thid_t thread_id, - int start, - int count, - const regval_t *values) override; - - virtual bool idaapi dbg_prepare_broken_connection(void) override; - virtual bool idaapi dbg_continue_broken_connection(pid_t pid) override; - - qvector pdb_remote_sessions; - pdb_remote_session_t *get_pdb_session(int id); - void delete_pdb_session(int id); - -protected: - virtual int dbg_freeze_threads_except(thid_t tid) override; - virtual int dbg_thaw_threads_except(thid_t tid) override; -}; - -ea_t s0tops(ea_t ea); - -#endif - diff --git a/idasdk75/dbg/win32/winbase_debmod.cpp b/idasdk75/dbg/win32/winbase_debmod.cpp deleted file mode 100644 index 78b34b8..0000000 --- a/idasdk75/dbg/win32/winbase_debmod.cpp +++ /dev/null @@ -1,619 +0,0 @@ -#include -#include -#include "winbase_debmod.h" - -#ifndef __X86__ -#define IDA_ADDRESS_SIZE 8 -#else -#define IDA_ADDRESS_SIZE 4 -#endif - -const TCHAR kernel32_dll[] = TEXT("kernel32.dll"); - -typedef BOOL WINAPI GetProcessDEPPolicy_t(HANDLE hProcess, LPDWORD lpFlags, PBOOL lpPermanent); -static GetProcessDEPPolicy_t *_GetProcessDEPPolicy = NULL; - -typedef dep_policy_t WINAPI GetSystemDEPPolicy_t(void); -static GetSystemDEPPolicy_t *_GetSystemDEPPolicy = NULL; - -//-------------------------------------------------------------------------- -winbase_debmod_t::winbase_debmod_t(void) - : is_wow64(WOW64_NONE), - process_handle(INVALID_HANDLE_VALUE), - dep_policy(dp_always_off), - highdlls() -{ - HMODULE k32 = GetModuleHandle(kernel32_dll); - - if ( _GetProcessDEPPolicy == NULL ) - *(FARPROC*)&_GetProcessDEPPolicy = GetProcAddress(k32, TEXT("GetProcessDEPPolicy")); - - if ( _GetSystemDEPPolicy == NULL ) - *(FARPROC*)&_GetSystemDEPPolicy = GetProcAddress(k32, TEXT("GetSystemDEPPolicy")); - - if ( _GetSystemDEPPolicy != NULL ) - dep_policy = _GetSystemDEPPolicy(); - - win_tool_help = NULL; - set_platform("win32"); -} - -//-------------------------------------------------------------------------- -// Prepare new page protections for a breakpoint of BPTTYPE. -// Use INPUT as starting page protections. -// Return false in the case of failure. -bool winbase_debmod_t::remove_page_protections( - DWORD *p_input, - bpttype_t bpttype, - dep_policy_t dpolicy, - HANDLE proc_handle) -{ - // If PAGE_GUARD is already set, do not change anything, it is already ok - DWORD input = *p_input; - if ( (input & PAGE_GUARD) != 0 ) - return false; - - // Convert between Unix permissions and Win32 page protections using this array: - static const uchar win32_page_protections[] = - { - PAGE_NOACCESS, // 000 - PAGE_READONLY, // 001 - 0xFF, // 010 WRITE_ONLY does not exist on win32 - PAGE_READWRITE, // 011 - PAGE_EXECUTE, // 100 - PAGE_EXECUTE_READ, // 101 - 0xFF, // 110 EXECUTE_WRITE does not exist on win32 - PAGE_EXECUTE_READWRITE, // 111 - }; - uchar unix; - // convert ..COPY page protections into their non-copy counterparts - // this is the best thing we can do with them because they are automatically - // converted by the system upon a write access - if ( (input & PAGE_WRITECOPY) != 0 ) - { - unix = 3; // rw - } - else if ( (input & PAGE_EXECUTE_WRITECOPY) != 0 ) - { - unix = 7; // rwx - } - else - { - for ( unix=0; unix < 8; unix++ ) - { - uchar p = win32_page_protections[unix]; - if ( p != 0xFF && (input & p) != 0 ) - break; - } - } - QASSERT(622, unix < 8); - - // convert bpttype into unix permissions - int del = 0; - if ( (bpttype & BPT_READ) != 0 ) - del |= 1; - if ( (bpttype & BPT_WRITE) != 0 ) - del |= 2; - if ( (bpttype & BPT_EXEC) != 0 ) - { - del |= 4; - // if DEP is disabled for this process then a program can - // happily execute code in a read only area so we need to - // remove *all* privileges, unfortunately - if ( dpolicy != dp_always_on ) - { - // on XP, GetProcessDEPPolicy returns DEP policy for current process (i.e. the debugger) - // so we can't use it - // assume that DEP is disabled by default - DWORD flags = 0; - BOOL permanent = 0; - if ( _GetProcessDEPPolicy == NULL - || winver.is_strictly_xp() - || winver.is_GetProcessDEPPolicy_broken() - || _GetProcessDEPPolicy(proc_handle, &flags, &permanent) ) - { - // flags == 0: DEP is disabled for the specified process. - // - // Remarks: if permanent == 0 and global DEP policy is OptIn - // flags may be equal to 1 *but* having DEP disabled because, - // in case the process called SetProcessDEPPolicy the - // permanent argument would be 1, it seems to be a bug in the - // documentation - if ( (dpolicy == dp_opt_in && permanent == 0) || flags == 0 ) - del |= 1; - } - } - } - - // Remove the access types to trigger on - unix &= ~del; - - // Handle WRITE_ONLY and EXECUTE_WRITE cases because win32 does not have them. - // We use stricter page permissions for them. This means that there will - // be more useless exceptions but we cannot do much about it. - if ( unix == 2 || unix == 6 ) - unix = 0; // use PAGE_NOACCESS instead of WRITE_ONLY or EXECUTE_WRITE - - uchar perm = win32_page_protections[unix]; - *p_input = (input & ~0xFF) | perm; - return true; -} - -//-------------------------------------------------------------------------- -bool idaapi winbase_debmod_t::dbg_enable_page_bpt( - page_bpts_t::iterator p, - bool enable) -{ - pagebpt_data_t &bpt = p->second; - if ( (bpt.old_prot != 0) == enable ) - return false; // already the desired state - - debdeb("dbg_enable_page_bpt(%s): page_ea=%a, old_prot=0x%x, new_prot=0x%x\n", enable ? "true" : "false", bpt.page_ea, bpt.old_prot, bpt.new_prot); - - DWORD old; - DWORD prot = enable ? bpt.new_prot : bpt.old_prot; - if ( !VirtualProtectEx(process_handle, (void*)(size_t)bpt.page_ea, - bpt.real_len, prot, &old) ) - { - deberr("VirtualProtectEx"); - // if the page disappeared while disabling a bpt, do not complain, - // silently return success - if ( enable ) - return false; - old = 0; - } - - debdeb(" success! old=0x%x\n", old); - - bpt.old_prot = enable ? old : 0; - return true; -} - -//-------------------------------------------------------------------------- -// Should we generate a BREAKPOINT event because of page bpt? -//lint -e{1746} could be made const reference -bool should_fire_page_bpt( - page_bpts_t::iterator p, - ea_t ea, - DWORD failed_access_type, - ea_t pc, - dep_policy_t dep_policy) -{ - const pagebpt_data_t &bpt = p->second; - if ( !interval::contains(bpt.ea, bpt.user_len, ea) ) - return false; // not in the user-defined interval - - int bit; - switch ( failed_access_type ) - { - default: - INTERR(623); //-V796 no break - case EXCEPTION_READ_FAULT: // failed READ access - // depending on the DEP policy we mark this access also - // to be triggered in case of EXEC breakpoints - bit = BPT_READ; - if ( dep_policy != dp_always_on && bpt.type == BPT_EXEC && pc == ea ) - bit |= BPT_EXEC; - break; - case EXCEPTION_WRITE_FAULT: // failed WRITE access - bit = BPT_WRITE; - break; - case EXCEPTION_EXECUTE_FAULT: // failed EXECUTE access - bit = BPT_EXEC; - break; - } - return (bpt.type & bit) != 0; -} - -//-------------------------------------------------------------------------- -// returns 0-failure, 2-success -int idaapi winbase_debmod_t::dbg_add_page_bpt( - bpttype_t type, - ea_t ea, - int size) -{ - // only one page breakpoint per page is permitted - page_bpts_t::iterator p = find_page_bpt(ea, size); - if ( p != page_bpts.end() ) - return 0; // another page bpt exists - - // Find out the current page protections - MEMORY_BASIC_INFORMATION meminfo; - ea_t page_ea = calc_page_base(ea); - if ( !VirtualQueryEx(process_handle, (void *)(size_t)page_ea, - &meminfo, sizeof(meminfo)) ) - { - deberr("VirtualQueryEx"); - return 0; - } - - // Make sure the page is loaded - if ( (meminfo.State & MEM_FREE) != 0 ) - { - deberr("%a: the page has not been allocated", page_ea); - return 0; - } - - // According to MSDN documentation for VirtualQueryEx - // (...) - // AllocationProtect - // The memory protection option when the region was initially allocated. This member can be - // one of the memory protection constants or 0 if the caller does not have access. - // - // Unfortunately, there is no more information about why it my happen so, for now, I'm just - // returning an error. - if ( meminfo.Protect == 0 ) - { - deberr("%a: the page cannot be accessed", page_ea); - return 0; - } - - // Calculate new page protections - int aligned_len = align_up((ea-page_ea)+size, MEMORY_PAGE_SIZE); - int real_len = 0; - DWORD prot = meminfo.Protect; - if ( remove_page_protections(&prot, type, dep_policy, process_handle) ) - { // We have to set new protections - real_len = aligned_len; - } - - // Remember the new breakpoint - p = page_bpts.insert(std::make_pair(page_ea, pagebpt_data_t())).first; - pagebpt_data_t &bpt = p->second; - bpt.ea = ea; - bpt.user_len = size; - bpt.page_ea = page_ea; - bpt.aligned_len = aligned_len; - bpt.real_len = real_len; - bpt.old_prot = 0; - bpt.new_prot = prot; - bpt.type = type; - - // for PAGE_GUARD pages, no need to change the permissions, everything is fine already - if ( real_len == 0 ) - { - bpt.old_prot = meminfo.Protect; - return 2; - } - - return dbg_enable_page_bpt(p, true) ? 2 : 0; -} - -//-------------------------------------------------------------------------- -// returns true if changed *protect (in other words, if we have to mask -// the real page protections and return the original one) -bool winbase_debmod_t::mask_page_bpts( - ea_t startea, - ea_t endea, - uint32 *protect) -{ - // if we have page breakpoints, what we return must be changed to show the - // real segment privileges, instead of the new ones we applied for the bpt - int newprot = 0; - page_bpts_t::iterator p = page_bpts.begin(); - while ( p != page_bpts.end() ) - { - pagebpt_data_t &pbd = p->second; - if ( pbd.page_ea + pbd.real_len > startea ) - { - if ( pbd.page_ea >= endea ) - break; - if ( pbd.old_prot != 0 ) - { // bpt has been written to the process memory - if ( *protect == pbd.new_prot ) - { // return the old protection, before setting the page bpt - newprot = pbd.old_prot; - } - else - { - debdeb("mask_page_bpts: app changed our page protection for %a (expected: 0x%x, actual: 0x%x)\n", pbd.page_ea, pbd.new_prot, *protect); - // page protection has been changed by the application - DWORD prot = *protect; - if ( prot == PAGE_WRITECOPY && pbd.new_prot == PAGE_READWRITE - || prot == PAGE_EXECUTE_WRITECOPY && pbd.new_prot == PAGE_EXECUTE_READWRITE ) - { - // in some cases OS may restore WRITECOPY protection; do nothing in such cases since it works the same way for breakpoint purposes - debdeb(" ignoring changes to WRITECOPY protection\n"); - } - else if ( remove_page_protections(&prot, pbd.type, dep_policy, process_handle) ) - { - pbd.new_prot = prot; - pbd.old_prot = 0; // mark our bpt as non-written - debdeb(" will re-set protection to 0x%x\n", pbd.new_prot); - } - } - } - } - ++p; - } - if ( newprot != 0 ) - { - *protect = newprot; - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -// Page breakpoints modify the page protections to induce access violations. -// We must hide the modified page protections from IDA and report the original -// page protections. -// Second, the application may render a page bpt inactive by changing its page protections. -// In this case we must report to IDA the new page protections and also reactivate -// the page breakpoint. -void winbase_debmod_t::verify_page_protections( - meminfo_vec_t *areas, - const win32_prots_t &prots) -{ - QASSERT(624, areas->size() == prots.size()); - if ( page_bpts.empty() ) - return; - - for ( int i = 0; i < areas->size(); i++ ) - { - uint32 prot = prots[i]; - memory_info_t &a = areas->at(i); - if ( mask_page_bpts(a.start_ea, a.end_ea, &prot) ) - a.perm = win_prot_to_ida_perm(prot); - } - - // reactivate all disabled page bpts, if any - enable_page_bpts(true); -} - -//-------------------------------------------------------------------------- -#ifndef __X86__ -wow64_state_t winbase_debmod_t::check_wow64_process() -{ - if ( is_wow64 == WOW64_NONE ) - { - is_wow64 = check_wow64_handle(process_handle); - if ( is_wow64 > 0 ) - dmsg("WOW64 process has been detected (pid=%d)\n", pid); - } - return is_wow64; -} -#endif - -//-------------------------------------------------------------------------- -bool highdll_vec_t::has(eanat_t addr) const -{ - for ( int i = 0; i < size(); ++i ) - if ( (*this)[i].has(addr) ) - return true; - return false; -} - -//-------------------------------------------------------------------------- -bool highdll_vec_t::add(eanat_t addr, size_t sz, HANDLE h) -{ - if ( has(addr) ) - return false; - - // check removed: on new win10 we can have above 4GB: - // ntdll.dll, wow64.dll, wow64win.dll - // QASSERT(1491, size() < 2); - highdll_range_t &r = push_back(); - r.start = addr; - r.end = addr + sz; - r.handle = h; - return true; -} - -//-------------------------------------------------------------------------- -bool highdll_vec_t::add_high_module( - eanat_t addr, - size_t sz, - HANDLE h) -{ - if ( ea_t(addr) == addr ) - return false; - add(addr, sz, h); //-V779 unreachable code - return true; -} - -//-------------------------------------------------------------------------- -bool highdll_vec_t::del_high_module(HANDLE *h, eanat_t addr) -{ - for ( int i = 0; i < size(); ++i ) - { - const highdll_range_t &r = (*this)[i]; - if ( r.start == addr ) - { - if ( h != NULL ) - *h = r.handle; - erase(begin() + i); - return ea_t(addr) != addr; - } - } - return false; -} - -//-------------------------------------------------------------------------- -void idaapi winbase_debmod_t::dbg_term(void) -{ - is_wow64 = WOW64_NONE; - delete win_tool_help; - win_tool_help = NULL; -} - -//-------------------------------------------------------------------------- -// Check if we need to install a temporary breakpoint to workaround the -// 'freely running after syscall' problem. Exactly, the problem is the -// following: after single stepping over a "jmp far ptr" instruction in -// wow64cpu.dll for a 32bits process under a 64bits OS (Win7), the trap flag -// is lost. Probably, it's a bug in wow64cpu!CpuReturnFromSimulatedCode. -// -// So, if we find an instruction like "call large dword fs:XX" we add a -// temporary breakpoint at the next instruction and re-enable tracing -// when the breakpoint is reached. -bool winbase_debmod_t::check_for_call_large( - const debug_event_t *event, - HANDLE handle) -{ - if ( check_wow64_handle(handle) <= 0 ) - return false; - uchar buf[3]; - if ( dbg_read_memory(event->ea, buf, 3, NULL) == 3 ) - { - // is it the call large instruction? - if ( memcmp(buf, "\x64\xFF\x15", 3) == 0 ) - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -// Get process bitness: 32bit - 4, 64bit - 8, 0 - unknown -int idaapi winbase_debmod_t::get_process_bitness(int _pid) -{ - if ( _pid != -1 && _pid != GetCurrentProcessId() ) - { - if ( !winver.is_64bitOS() ) - return 4; - switch ( check_wow64_pid(_pid) ) - { - case WOW64_BAD: return 0; // bad process id - case WOW64_YES: return 4; // wow64 process, 32bit - case WOW64_NO: return 8; // regular 64bit process - default: break; - } - } - return IDA_ADDRESS_SIZE; -} - -//-------------------------------------------------------------------------- -static const char *str_bitness(int addrsize) -{ - switch ( addrsize ) - { - case 8: - return "[64]"; - case 4: - return "[32]"; - default: - return "[x]"; - } -} - -//-------------------------------------------------------------------------- -// this function may correct pinfo->addrsize -bool winbase_debmod_t::get_process_path( - ext_process_info_t *pinfo, - char *buf, - size_t bufsize) -{ - module_snapshot_t msnap(get_tool_help()); - MODULEENTRY32 me; - if ( !msnap.first(TH32CS_SNAPMODULE, pinfo->pid, &me) ) - { - if ( msnap.last_err() == ERROR_PARTIAL_COPY && pinfo->addrsize == 0 ) - { - // MSDN: If the specified process is a 64-bit process and the caller is a - // 32-bit process, error code is ERROR_PARTIAL_COPY - pinfo->addrsize = 8; - } - qstrncpy(buf, pinfo->name.c_str(), bufsize); - return false; - } - else - { - tchar_utf8(buf, me.szExePath, bufsize); - return true; - } -} - -//-------------------------------------------------------------------------- -win_tool_help_t *winbase_debmod_t::get_tool_help() -{ - if ( win_tool_help == NULL ) - win_tool_help = new win_tool_help_t; - return win_tool_help; -} - -//------------------------------------------------------------------------- -int winbase_debmod_t::get_process_addrsize(pid_t _pid) -{ - int addrsize = get_process_bitness(_pid); - return addrsize != 0 ? addrsize : IDA_ADDRESS_SIZE; -} - -//-------------------------------------------------------------------------- -//lint -e{1762} could be made const [in fact it cannot be made const in x64 mode] -bool winbase_debmod_t::is_ntdll_name(const char *path) -{ - const char *base_name = qbasename(path); - const char *ntdll_name = winver.is_NT() - ? "ntdll.dll" // NT - : "kernel32.dll"; // 9X/Me and KERNEL32.DLL - if ( strieq(base_name, ntdll_name) ) - return true; -#ifndef __X86__ - if ( winver.is_NT() - && check_wow64_process() == WOW64_YES - && strieq(base_name, "ntdll32.dll") ) - { - return true; - } -#endif - return false; -} - -//-------------------------------------------------------------------------- -//lint -esym(1762,winbase_debmod_t::build_process_ext_name) could be made const -void winbase_debmod_t::build_process_ext_name(ext_process_info_t *pinfo) -{ - char fullname[MAXSTR]; - if ( get_process_path(pinfo, fullname, sizeof(fullname)) - && pinfo->addrsize == 0 ) - { - // the WOW64 is optional on R2 x64 server - pinfo->addrsize = IDA_ADDRESS_SIZE; - } - pinfo->ext_name = str_bitness(pinfo->addrsize); - if ( !pinfo->ext_name.empty() ) - pinfo->ext_name += ' '; - pinfo->ext_name += fullname; -} - -//-------------------------------------------------------------------------- -int idaapi winbase_debmod_t::get_process_list(procvec_t *list, qstring *) -{ - int mypid = GetCurrentProcessId(); - list->clear(); - - process_snapshot_t psnap(get_tool_help()); - PROCESSENTRY32 pe32; - for ( bool ok = psnap.first(TH32CS_SNAPNOHEAPS, &pe32); ok; ok = psnap.next(&pe32) ) - { - if ( pe32.th32ProcessID != mypid ) - { - int addrsize = get_process_bitness(pe32.th32ProcessID); -#ifndef __EA64__ - if ( addrsize > 4 ) - continue; // skip 64bit processes, we cannot debug them because ea_t is 32bit -#endif - ext_process_info_t pinfo; - pinfo.pid = pe32.th32ProcessID; - pinfo.addrsize = addrsize; - tchar_utf8(&pinfo.name, pe32.szExeFile); - build_process_ext_name(&pinfo); - list->push_back(pinfo); - } - } - return list->size(); -} - -//-------------------------------------------------------------------------- -// Returns the file name assciated with pid -bool idaapi winbase_debmod_t::get_exec_fname(int _pid, char *buf, size_t bufsize) -{ - ext_process_info_t pinfo; - pinfo.pid = _pid; - pinfo.name.qclear(); - return get_process_path(&pinfo, buf, bufsize); -} - -//-------------------------------------------------------------------------- -win_tool_help_t *winbase_debmod_t::win_tool_help = NULL; -win_version_t winbase_debmod_t::winver; diff --git a/idasdk75/dbg/win32/winbase_debmod.h b/idasdk75/dbg/win32/winbase_debmod.h deleted file mode 100644 index ce2216b..0000000 --- a/idasdk75/dbg/win32/winbase_debmod.h +++ /dev/null @@ -1,179 +0,0 @@ -#ifndef __WINBASE_HPP__ -#define __WINBASE_HPP__ - -// Base class for win32 and windbg modules - -#include -#include - -using std::for_each; -using std::pair; -using std::make_pair; - -//-------------------------------------------------------------------------- -#define BASE_DEBUGGER_MODULE pc_debmod_t -#include "deb_pc.hpp" -#include "pc_debmod.h" -#define BPT_CODE_SIZE X86_BPT_SIZE -#include "win32_util.hpp" - -extern const TCHAR kernel32_dll[]; - -//-------------------------------------------------------------------------- -// DEP policies -enum dep_policy_t -{ - dp_always_off, - dp_always_on, - dp_opt_in, - dp_opt_out -}; - -//-------------------------------------------------------------------------- -enum attach_status_t -{ - as_none, // no attach to process requested - as_attaching, // waiting for CREATE_PROCESS_DEBUG_EVENT, indicating the process is attached - as_breakpoint, // waiting for first breakpoint, indicating the process was properly initialized and suspended - as_attached, // process was successfully attached - as_detaching, // waiting for next get_debug_event() request, to return the process as detached - as_attach_kernel, // attaching to kernel -}; - -// vector of win32 page protections -// we need this type because meminfo_t does not contain the original win32 protections -// but we need them to verify page bpts -typedef qvector win32_prots_t; - -//-------------------------------------------------------------------------- -// When debugging WOW64 processes with ida32 we have to take into account -// ntdll.dll (and wow64*.dll), which are x64 files -// that can be loaded into high addresses (above 4GB) -// Since ea_t cannot represent such addresses, -// we use our own type to remember the DLL boundaries - -typedef size_t eanat_t; - -struct highdll_range_t -{ - eanat_t start; - eanat_t end; - HANDLE handle; - highdll_range_t() : start(0), end(0), handle(INVALID_HANDLE_VALUE) {} - bool has(eanat_t addr) const { return addr >= start && addr < end; } -}; -DECLARE_TYPE_AS_MOVABLE(highdll_range_t); - -struct highdll_vec_t : protected qvector -{ -private: - size_t num_ntdlls; // count of actual ntdll*.dll modules in the list -public: - typedef qvector inherited; - highdll_vec_t() : num_ntdlls(0) {} - void clear() { inherited::clear(); num_ntdlls = 0; } - size_t size() const { return inherited::size(); } - size_t count_ntdlls() const { return num_ntdlls; } - bool empty() const { return inherited::empty(); } - // return false if there is already a dll with such an address - bool add(eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE); - bool add_ntdll(eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE) - { - bool ok = add(addr, size, h); - if ( ok ) - num_ntdlls++; - return ok; - }; - // it returns true if the dll address doesn't fit in `ea_t` - bool add_high_module( - eanat_t addr, - size_t size, - HANDLE h = INVALID_HANDLE_VALUE); - // it returns true if the dll address doesn't fit to `ea_t` - bool del_high_module(HANDLE *h, eanat_t addr); - bool has(eanat_t addr) const; -}; - -//-------------------------------------------------------------------------- -class winbase_debmod_t: public BASE_DEBUGGER_MODULE -{ - typedef BASE_DEBUGGER_MODULE inherited; - wow64_state_t is_wow64; // use check_wow64_process() - -protected: - HANDLE process_handle; - dep_policy_t dep_policy; - highdll_vec_t highdlls; - // local functions - bool mask_page_bpts(ea_t startea, ea_t endea, uint32 *protect); - void verify_page_protections(meminfo_vec_t *areas, const win32_prots_t &prots); - - winbase_debmod_t(void); - - // overridden virtual functions - bool idaapi dbg_enable_page_bpt(page_bpts_t::iterator p, bool enable); - int idaapi dbg_add_page_bpt(bpttype_t type, ea_t ea, int size); - bool check_for_call_large(const debug_event_t *event, HANDLE process_handle); -#ifndef __X86__ - wow64_state_t check_wow64_process(); -#else - wow64_state_t check_wow64_process() { return WOW64_NO; } -#endif - - int get_process_addrsize(pid_t pid); - - bool is_ntdll_name(const char *path); - - // return number of processes, -1 - not implemented - virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf) override; - // return the file name assciated with pid - virtual bool idaapi get_exec_fname(int pid, char *buf, size_t bufsize) newapi; - // get process bitness: 32bit - 4, 64bit - 8, 0 - unknown - virtual int idaapi get_process_bitness(int pid) newapi; - -public: - virtual void idaapi dbg_term(void) override; - - static win_tool_help_t *get_tool_help(); - static win_version_t winver; - -private: - void build_process_ext_name(ext_process_info_t *pinfo); - static bool get_process_path( - ext_process_info_t *pinfo, - char *buf, - size_t bufsize); - static bool remove_page_protections( - DWORD *p_input, - bpttype_t bpttype, - dep_policy_t dpolicy, - HANDLE proc_handle); - - static win_tool_help_t *win_tool_help; -}; - -bool should_fire_page_bpt(page_bpts_t::iterator p, ea_t ea, DWORD failed_access_type, ea_t pc, dep_policy_t dep_policy); - -#ifdef _PE_H_ -bool read_pe_header(peheader_t *pe); -#endif - -//------------------------------------------------------------------------- -inline void tchar_utf8(qstring *buf, TCHAR *tchar) -{ -#ifdef UNICODE - utf16_utf8(buf, tchar); -#else - acp_utf8(buf, tchar); -#endif -} - -//------------------------------------------------------------------------- -inline void tchar_utf8(char *buf, TCHAR *tchar, size_t bufsize) -{ - qstring utf8; - tchar_utf8(&utf8, tchar); - qstrncpy(buf, utf8.c_str(), bufsize); -} - -#endif diff --git a/idasdk75/defaults.mk b/idasdk75/defaults.mk deleted file mode 100644 index ea299c2..0000000 --- a/idasdk75/defaults.mk +++ /dev/null @@ -1,125 +0,0 @@ -############################################################################# -# versions and paths for various external libraries and utils - -ifdef __NT__ - # The following variables may have been set by vcvars.bat. You may - # also set them manually. The default installation directories are - # defined below in case these variables are not set. - # Note: the following paths use backslashes (and may also contain a - # trailing backslash) in order to conform to the variables - # exported by vcvars.bat. - - # Visual C++ 2017 Install Directory - VCINSTALLDIR ?= '$(PROGRAMFILES)\Microsoft Visual Studio\2017\Professional\VC\' - - # Visual C++ 2017 Tools Version - # Note: if this variable is not set, the default version is obtained - # in allmake.mak under "Visual C++ 2017 Tools Version". - # VCToolsVersion ?= '14.11.25503' - - # Windows SDK Install Directory - WindowsSdkDir ?= '$(PROGRAMFILES)\Windows Kits\10\' - - # Windows SDK version - # Note: if this variable is not set, the latest version is detected - # in allmake.mak under "Windows SDK Version". - # WindowsSDKVersion ?= '10.0.17134.0\' - - # Microsoft SDK v7.1A is only used for the win32 debugger server for - # Windows XP compatibility. - MSSDK71_PATH = '$(PROGRAMFILES)/Microsoft SDKs/Windows/v7.1A' -else ifdef __MAC__ - # oldest supported version of MacOSX - MACOSX_DEPLOYMENT_TARGET = 10.9 -endif - -# Python -PYTHON_VERSION_MAJOR?=3 -PYTHON_VERSION_MINOR?=4 -PYTHON_VERNAME=python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) - -# TODO clean this up -ifdef __NT__ - ifneq (,$(wildcard /cygdrive/c/Program\ Files/Python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)/python.exe)) - PYTHON_ROOT ?= C:/Program Files/Python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR) - else - ifeq ($(PYTHON_VERSION_MAJOR),2) - PYTHON_VERSUF=-x64 - endif - PYTHON_ROOT ?= $(SYSTEMDRIVE)/Python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)$(PYTHON_VERSUF) - endif - PYTHON ?= "$(PYTHON_ROOT)/python.exe" -else - PYTHON ?= $(PYTHON_VERNAME) -endif - -# Qt -QTVER?=5.6.3-x64 - -QTDIR-$(__LINUX__) = /usr/local/Qt/$(QTVER)/ -QTDIR-$(__MAC__) = /Users/Shared/Qt/$(QTVER)/ -QTDIR-$(__NT__) = $(SYSTEMDRIVE)/Qt/$(QTVER)/ -QTDIR ?= $(QTDIR-1) - -ifdef __NT__ - ifdef NDEBUG - QTSUFF=.dll - else - QTSUFF=d.dll - endif - QTLIBDIR=bin -else ifdef __LINUX__ - QTPREF=lib - QTSUFF=.so.5 - QTLIBDIR=lib -endif - -# SWiG -ifeq ($(PYTHON_VERSION_MAJOR),3) - SWIG_VERSION?=4.0.1 - ifdef __NT__ - SWIG_DIR_SUFFIX?=-py3-stable-abi-cygwin - else - SWIG_DIR_SUFFIX?=-py3-stable-abi - endif -else - SWIG_VERSION?=4.0.0 -endif -ifdef __NT__ - ifeq ($(PYTHON_VERSION_MAJOR),3) - SWIG_DISTRIBUTION_HAS_UNIX_LAYOUT:=1 - endif -else - SWIG_DISTRIBUTION_HAS_UNIX_LAYOUT:=1 -endif - -ifeq ($(SWIG_DISTRIBUTION_HAS_UNIX_LAYOUT),1) - ifdef USE_CCACHE - # we set CCACHE_DIR so as to not interfere with the system's ccache - # and we set CCACHE_CPP2 to prevent SWiG from printing a bunch of - # warnings due to re-using of the preprocessed source. - SWIG?=CCACHE_DIR='$${HOME}/.ccache-swig' CCACHE_CPP2=1 $(SWIG_HOME)/bin/ccache-swig $(SWIG_HOME)/bin/swig - else - SWIG?=$(SWIG_HOME)/bin/swig - endif - SWIG_INCLUDES?=-I$(SWIG_HOME)/share/swig/$(SWIG_VERSION)/python -I$(SWIG_HOME)/share/swig/$(SWIG_VERSION) -else - SWIG?=$(SWIG_HOME)/swig.exe - SWIG_INCLUDES?=-I$(SWIG_HOME)/Lib/python -I$(SWIG_HOME)/Lib -endif - -############################################################################# -# keep all paths in unix format, with forward slashes -ifeq ($(OS),Windows_NT) - # define: convert dos path to unix path by replacing backslashes by slashes - unixpath=$(subst \,/,$(1)) - - PYTHON_ROOT :=$(call unixpath,$(PYTHON_ROOT)) - PYTHON :=$(call unixpath,$(PYTHON)) - SWIG :=$(call unixpath,$(SWIG)) - QTDIR :=$(call unixpath,$(QTDIR)) -endif - -############################################################################# -# http://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile -.print-% : ; @echo $($*) diff --git a/idasdk75/include/allins.hpp b/idasdk75/include/allins.hpp deleted file mode 100644 index d0cd5f9..0000000 --- a/idasdk75/include/allins.hpp +++ /dev/null @@ -1,21042 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -NN_null = 0, // Unknown Operation -NN_aaa, // ASCII Adjust after Addition -NN_aad, // ASCII Adjust AX before Division -NN_aam, // ASCII Adjust AX after Multiply -NN_aas, // ASCII Adjust AL after Subtraction -NN_adc, // Add with Carry -NN_add, // Add -NN_and, // Logical AND -NN_arpl, // Adjust RPL Field of Selector -NN_bound, // Check Array Index Against Bounds -NN_bsf, // Bit Scan Forward -NN_bsr, // Bit Scan Reverse -NN_bt, // Bit Test -NN_btc, // Bit Test and Complement -NN_btr, // Bit Test and Reset -NN_bts, // Bit Test and Set -NN_call, // Call Procedure -NN_callfi, // Indirect Call Far Procedure -NN_callni, // Indirect Call Near Procedure -NN_cbw, // AL -> AX (with sign) -NN_cwde, // AX -> EAX (with sign) -NN_cdqe, // EAX -> RAX (with sign) -NN_clc, // Clear Carry Flag -NN_cld, // Clear Direction Flag -NN_cli, // Clear Interrupt Flag -NN_clts, // Clear Task-Switched Flag in CR0 -NN_cmc, // Complement Carry Flag -NN_cmp, // Compare Two Operands -NN_cmps, // Compare Strings -NN_cwd, // AX -> DX:AX (with sign) -NN_cdq, // EAX -> EDX:EAX (with sign) -NN_cqo, // RAX -> RDX:RAX (with sign) -NN_daa, // Decimal Adjust AL after Addition -NN_das, // Decimal Adjust AL after Subtraction -NN_dec, // Decrement by 1 -NN_div, // Unsigned Divide -NN_enterw, // Make Stack Frame for Procedure Parameters -NN_enter, // Make Stack Frame for Procedure Parameters -NN_enterd, // Make Stack Frame for Procedure Parameters -NN_enterq, // Make Stack Frame for Procedure Parameters -NN_hlt, // Halt -NN_idiv, // Signed Divide -NN_imul, // Signed Multiply -NN_in, // Input from Port -NN_inc, // Increment by 1 -NN_ins, // Input Byte(s) from Port to String -NN_int, // Call to Interrupt Procedure -NN_into, // Call to Interrupt Procedure if Overflow Flag = 1 -NN_int3, // Trap to Debugger -NN_iretw, // Interrupt Return -NN_iret, // Interrupt Return -NN_iretd, // Interrupt Return (use32) -NN_iretq, // Interrupt Return (use64) -NN_ja, // Jump if Above (CF=0 & ZF=0) -NN_jae, // Jump if Above or Equal (CF=0) -NN_jb, // Jump if Below (CF=1) -NN_jbe, // Jump if Below or Equal (CF=1 | ZF=1) -NN_jc, // Jump if Carry (CF=1) -NN_jcxz, // Jump if CX is 0 -NN_jecxz, // Jump if ECX is 0 -NN_jrcxz, // Jump if RCX is 0 -NN_je, // Jump if Equal (ZF=1) -NN_jg, // Jump if Greater (ZF=0 & SF=OF) -NN_jge, // Jump if Greater or Equal (SF=OF) -NN_jl, // Jump if Less (SF!=OF) -NN_jle, // Jump if Less or Equal (ZF=1 | SF!=OF) -NN_jna, // Jump if Not Above (CF=1 | ZF=1) -NN_jnae, // Jump if Not Above or Equal (CF=1) -NN_jnb, // Jump if Not Below (CF=0) -NN_jnbe, // Jump if Not Below or Equal (CF=0 & ZF=0) -NN_jnc, // Jump if Not Carry (CF=0) -NN_jne, // Jump if Not Equal (ZF=0) -NN_jng, // Jump if Not Greater (ZF=1 | SF!=OF) -NN_jnge, // Jump if Not Greater or Equal (ZF=1) -NN_jnl, // Jump if Not Less (SF=OF) -NN_jnle, // Jump if Not Less or Equal (ZF=0 & SF=OF) -NN_jno, // Jump if Not Overflow (OF=0) -NN_jnp, // Jump if Not Parity (PF=0) -NN_jns, // Jump if Not Sign (SF=0) -NN_jnz, // Jump if Not Zero (ZF=0) -NN_jo, // Jump if Overflow (OF=1) -NN_jp, // Jump if Parity (PF=1) -NN_jpe, // Jump if Parity Even (PF=1) -NN_jpo, // Jump if Parity Odd (PF=0) -NN_js, // Jump if Sign (SF=1) -NN_jz, // Jump if Zero (ZF=1) -NN_jmp, // Jump -NN_jmpfi, // Indirect Far Jump -NN_jmpni, // Indirect Near Jump -NN_jmpshort, // Jump Short (not used) -NN_lahf, // Load Flags into AH Register -NN_lar, // Load Access Right Byte -NN_lea, // Load Effective Address -NN_leavew, // High Level Procedure Exit -NN_leave, // High Level Procedure Exit -NN_leaved, // High Level Procedure Exit -NN_leaveq, // High Level Procedure Exit -NN_lgdt, // Load Global Descriptor Table Register -NN_lidt, // Load Interrupt Descriptor Table Register -NN_lgs, // Load Full Pointer to GS:xx -NN_lss, // Load Full Pointer to SS:xx -NN_lds, // Load Full Pointer to DS:xx -NN_les, // Load Full Pointer to ES:xx -NN_lfs, // Load Full Pointer to FS:xx -NN_lldt, // Load Local Descriptor Table Register -NN_lmsw, // Load Machine Status Word -NN_lock, // Assert LOCK# Signal Prefix -NN_lods, // Load String -NN_loopw, // Loop while ECX != 0 -NN_loop, // Loop while CX != 0 -NN_loopd, // Loop while ECX != 0 -NN_loopq, // Loop while RCX != 0 -NN_loopwe, // Loop while CX != 0 and ZF=1 -NN_loope, // Loop while rCX != 0 and ZF=1 -NN_loopde, // Loop while ECX != 0 and ZF=1 -NN_loopqe, // Loop while RCX != 0 and ZF=1 -NN_loopwne, // Loop while CX != 0 and ZF=0 -NN_loopne, // Loop while rCX != 0 and ZF=0 -NN_loopdne, // Loop while ECX != 0 and ZF=0 -NN_loopqne, // Loop while RCX != 0 and ZF=0 -NN_lsl, // Load Segment Limit -NN_ltr, // Load Task Register -NN_mov, // Move Data -NN_movsp, // Move to/from Special Registers -NN_movs, // Move Byte(s) from String to String -NN_movsx, // Move with Sign-Extend -NN_movzx, // Move with Zero-Extend -NN_mul, // Unsigned Multiplication of AL or AX -NN_neg, // Two's Complement Negation -NN_nop, // No Operation -NN_not, // One's Complement Negation -NN_or, // Logical Inclusive OR -NN_out, // Output to Port -NN_outs, // Output Byte(s) to Port -NN_pop, // Pop a word from the Stack -NN_popaw, // Pop all General Registers -NN_popa, // Pop all General Registers -NN_popad, // Pop all General Registers (use32) -NN_popaq, // Pop all General Registers (use64) -NN_popfw, // Pop Stack into Flags Register -NN_popf, // Pop Stack into Flags Register -NN_popfd, // Pop Stack into Eflags Register -NN_popfq, // Pop Stack into Rflags Register -NN_push, // Push Operand onto the Stack -NN_pushaw, // Push all General Registers -NN_pusha, // Push all General Registers -NN_pushad, // Push all General Registers (use32) -NN_pushaq, // Push all General Registers (use64) -NN_pushfw, // Push Flags Register onto the Stack -NN_pushf, // Push Flags Register onto the Stack -NN_pushfd, // Push Flags Register onto the Stack (use32) -NN_pushfq, // Push Flags Register onto the Stack (use64) -NN_rcl, // Rotate Through Carry Left -NN_rcr, // Rotate Through Carry Right -NN_rol, // Rotate Left -NN_ror, // Rotate Right -NN_rep, // Repeat String Operation -NN_repe, // Repeat String Operation while ZF=1 -NN_repne, // Repeat String Operation while ZF=0 -NN_retn, // Return Near from Procedure -NN_retf, // Return Far from Procedure -NN_sahf, // Store AH into Flags Register -NN_sal, // Shift Arithmetic Left -NN_sar, // Shift Arithmetic Right -NN_shl, // Shift Logical Left -NN_shr, // Shift Logical Right -NN_sbb, // Integer Subtraction with Borrow -NN_scas, // Compare String -NN_seta, // Set Byte if Above (CF=0 & ZF=0) -NN_setae, // Set Byte if Above or Equal (CF=0) -NN_setb, // Set Byte if Below (CF=1) -NN_setbe, // Set Byte if Below or Equal (CF=1 | ZF=1) -NN_setc, // Set Byte if Carry (CF=1) -NN_sete, // Set Byte if Equal (ZF=1) -NN_setg, // Set Byte if Greater (ZF=0 & SF=OF) -NN_setge, // Set Byte if Greater or Equal (SF=OF) -NN_setl, // Set Byte if Less (SF!=OF) -NN_setle, // Set Byte if Less or Equal (ZF=1 | SF!=OF) -NN_setna, // Set Byte if Not Above (CF=1 | ZF=1) -NN_setnae, // Set Byte if Not Above or Equal (CF=1) -NN_setnb, // Set Byte if Not Below (CF=0) -NN_setnbe, // Set Byte if Not Below or Equal (CF=0 & ZF=0) -NN_setnc, // Set Byte if Not Carry (CF=0) -NN_setne, // Set Byte if Not Equal (ZF=0) -NN_setng, // Set Byte if Not Greater (ZF=1 | SF!=OF) -NN_setnge, // Set Byte if Not Greater or Equal (ZF=1) -NN_setnl, // Set Byte if Not Less (SF=OF) -NN_setnle, // Set Byte if Not Less or Equal (ZF=0 & SF=OF) -NN_setno, // Set Byte if Not Overflow (OF=0) -NN_setnp, // Set Byte if Not Parity (PF=0) -NN_setns, // Set Byte if Not Sign (SF=0) -NN_setnz, // Set Byte if Not Zero (ZF=0) -NN_seto, // Set Byte if Overflow (OF=1) -NN_setp, // Set Byte if Parity (PF=1) -NN_setpe, // Set Byte if Parity Even (PF=1) -NN_setpo, // Set Byte if Parity Odd (PF=0) -NN_sets, // Set Byte if Sign (SF=1) -NN_setz, // Set Byte if Zero (ZF=1) -NN_sgdt, // Store Global Descriptor Table Register -NN_sidt, // Store Interrupt Descriptor Table Register -NN_shld, // Double Precision Shift Left -NN_shrd, // Double Precision Shift Right -NN_sldt, // Store Local Descriptor Table Register -NN_smsw, // Store Machine Status Word -NN_stc, // Set Carry Flag -NN_std, // Set Direction Flag -NN_sti, // Set Interrupt Flag -NN_stos, // Store String -NN_str, // Store Task Register -NN_sub, // Integer Subtraction -NN_test, // Logical Compare -NN_verr, // Verify a Segment for Reading -NN_verw, // Verify a Segment for Writing -NN_wait, // Wait until BUSY# Pin is Inactive (HIGH) -NN_xchg, // Exchange Register/Memory with Register -NN_xlat, // Table Lookup Translation -NN_xor, // Logical Exclusive OR - -// -// 486 instructions -// - -NN_cmpxchg, // Compare and Exchange -NN_bswap, // Swap bits in EAX -NN_xadd, // t<-dest; dest<-src+dest; src<-t -NN_invd, // Invalidate Data Cache -NN_wbinvd, // Invalidate Data Cache (write changes) -NN_invlpg, // Invalidate TLB entry - -// -// Pentium instructions -// - -NN_rdmsr, // Read Machine Status Register -NN_wrmsr, // Write Machine Status Register -NN_cpuid, // Get CPU ID -NN_cmpxchg8b, // Compare and Exchange Eight Bytes -NN_rdtsc, // Read Time Stamp Counter -NN_rsm, // Resume from System Management Mode - -// -// Pentium Pro instructions -// - -NN_cmova, // Move if Above (CF=0 & ZF=0) -NN_cmovb, // Move if Below (CF=1) -NN_cmovbe, // Move if Below or Equal (CF=1 | ZF=1) -NN_cmovg, // Move if Greater (ZF=0 & SF=OF) -NN_cmovge, // Move if Greater or Equal (SF=OF) -NN_cmovl, // Move if Less (SF!=OF) -NN_cmovle, // Move if Less or Equal (ZF=1 | SF!=OF) -NN_cmovnb, // Move if Not Below (CF=0) -NN_cmovno, // Move if Not Overflow (OF=0) -NN_cmovnp, // Move if Not Parity (PF=0) -NN_cmovns, // Move if Not Sign (SF=0) -NN_cmovnz, // Move if Not Zero (ZF=0) -NN_cmovo, // Move if Overflow (OF=1) -NN_cmovp, // Move if Parity (PF=1) -NN_cmovs, // Move if Sign (SF=1) -NN_cmovz, // Move if Zero (ZF=1) -NN_fcmovb, // Floating Move if Below -NN_fcmove, // Floating Move if Equal -NN_fcmovbe, // Floating Move if Below or Equal -NN_fcmovu, // Floating Move if Unordered -NN_fcmovnb, // Floating Move if Not Below -NN_fcmovne, // Floating Move if Not Equal -NN_fcmovnbe, // Floating Move if Not Below or Equal -NN_fcmovnu, // Floating Move if Not Unordered -NN_fcomi, // FP Compare, result in EFLAGS -NN_fucomi, // FP Unordered Compare, result in EFLAGS -NN_fcomip, // FP Compare, result in EFLAGS, pop stack -NN_fucomip, // FP Unordered Compare, result in EFLAGS, pop stack -NN_rdpmc, // Read Performance Monitor Counter - -// -// FPP instructuions -// - -NN_fld, // Load Real -NN_fst, // Store Real -NN_fstp, // Store Real and Pop -NN_fxch, // Exchange Registers -NN_fild, // Load Integer -NN_fist, // Store Integer -NN_fistp, // Store Integer and Pop -NN_fbld, // Load BCD -NN_fbstp, // Store BCD and Pop -NN_fadd, // Add Real -NN_faddp, // Add Real and Pop -NN_fiadd, // Add Integer -NN_fsub, // Subtract Real -NN_fsubp, // Subtract Real and Pop -NN_fisub, // Subtract Integer -NN_fsubr, // Subtract Real Reversed -NN_fsubrp, // Subtract Real Reversed and Pop -NN_fisubr, // Subtract Integer Reversed -NN_fmul, // Multiply Real -NN_fmulp, // Multiply Real and Pop -NN_fimul, // Multiply Integer -NN_fdiv, // Divide Real -NN_fdivp, // Divide Real and Pop -NN_fidiv, // Divide Integer -NN_fdivr, // Divide Real Reversed -NN_fdivrp, // Divide Real Reversed and Pop -NN_fidivr, // Divide Integer Reversed -NN_fsqrt, // Square Root -NN_fscale, // Scale: st(0) <- st(0) * 2^st(1) -NN_fprem, // Partial Remainder -NN_frndint, // Round to Integer -NN_fxtract, // Extract exponent and significand -NN_fabs, // Absolute value -NN_fchs, // Change Sign -NN_fcom, // Compare Real -NN_fcomp, // Compare Real and Pop -NN_fcompp, // Compare Real and Pop Twice -NN_ficom, // Compare Integer -NN_ficomp, // Compare Integer and Pop -NN_ftst, // Test -NN_fxam, // Examine -NN_fptan, // Partial tangent -NN_fpatan, // Partial arctangent -NN_f2xm1, // 2^x - 1 -NN_fyl2x, // Y * lg2(X) -NN_fyl2xp1, // Y * lg2(X+1) -NN_fldz, // Load +0.0 -NN_fld1, // Load +1.0 -NN_fldpi, // Load PI=3.14... -NN_fldl2t, // Load lg2(10) -NN_fldl2e, // Load lg2(e) -NN_fldlg2, // Load lg10(2) -NN_fldln2, // Load ln(2) -NN_finit, // Initialize Processor -NN_fninit, // Initialize Processor (no wait) -NN_fsetpm, // Set Protected Mode -NN_fldcw, // Load Control Word -NN_fstcw, // Store Control Word -NN_fnstcw, // Store Control Word (no wait) -NN_fstsw, // Store Status Word -NN_fnstsw, // Store Status Word (no wait) -NN_fclex, // Clear Exceptions -NN_fnclex, // Clear Exceptions (no wait) -NN_fstenv, // Store Environment -NN_fnstenv, // Store Environment (no wait) -NN_fldenv, // Load Environment -NN_fsave, // Save State -NN_fnsave, // Save State (no wait) -NN_frstor, // Restore State -NN_fincstp, // Increment Stack Pointer -NN_fdecstp, // Decrement Stack Pointer -NN_ffree, // Free Register -NN_fnop, // No Operation -NN_feni, // (8087 only) -NN_fneni, // (no wait) (8087 only) -NN_fdisi, // (8087 only) -NN_fndisi, // (no wait) (8087 only) - -// -// 80387 instructions -// - -NN_fprem1, // Partial Remainder ( < half ) -NN_fsincos, // t<-cos(st); st<-sin(st); push t -NN_fsin, // Sine -NN_fcos, // Cosine -NN_fucom, // Compare Unordered Real -NN_fucomp, // Compare Unordered Real and Pop -NN_fucompp, // Compare Unordered Real and Pop Twice - -// -// Instructions added 28.02.96 -// - -NN_setalc, // Set AL to Carry Flag -NN_svdc, // Save Register and Descriptor -NN_rsdc, // Restore Register and Descriptor -NN_svldt, // Save LDTR and Descriptor -NN_rsldt, // Restore LDTR and Descriptor -NN_svts, // Save TR and Descriptor -NN_rsts, // Restore TR and Descriptor -NN_icebp, // ICE Break Point -NN_loadall, // Load the entire CPU state from ES:EDI - -// -// MMX instructions -// - -NN_emms, // Empty MMX state -NN_movd, // Move 32 bits -NN_movq, // Move 64 bits -NN_packsswb, // Pack with Signed Saturation (Word->Byte) -NN_packssdw, // Pack with Signed Saturation (Dword->Word) -NN_packuswb, // Pack with Unsigned Saturation (Word->Byte) -NN_paddb, // Packed Add Byte -NN_paddw, // Packed Add Word -NN_paddd, // Packed Add Dword -NN_paddsb, // Packed Add with Saturation (Byte) -NN_paddsw, // Packed Add with Saturation (Word) -NN_paddusb, // Packed Add Unsigned with Saturation (Byte) -NN_paddusw, // Packed Add Unsigned with Saturation (Word) -NN_pand, // Bitwise Logical And -NN_pandn, // Bitwise Logical And Not -NN_pcmpeqb, // Packed Compare for Equal (Byte) -NN_pcmpeqw, // Packed Compare for Equal (Word) -NN_pcmpeqd, // Packed Compare for Equal (Dword) -NN_pcmpgtb, // Packed Compare for Greater Than (Byte) -NN_pcmpgtw, // Packed Compare for Greater Than (Word) -NN_pcmpgtd, // Packed Compare for Greater Than (Dword) -NN_pmaddwd, // Packed Multiply and Add -NN_pmulhw, // Packed Multiply High -NN_pmullw, // Packed Multiply Low -NN_por, // Bitwise Logical Or -NN_psllw, // Packed Shift Left Logical (Word) -NN_pslld, // Packed Shift Left Logical (Dword) -NN_psllq, // Packed Shift Left Logical (Qword) -NN_psraw, // Packed Shift Right Arithmetic (Word) -NN_psrad, // Packed Shift Right Arithmetic (Dword) -NN_psrlw, // Packed Shift Right Logical (Word) -NN_psrld, // Packed Shift Right Logical (Dword) -NN_psrlq, // Packed Shift Right Logical (Qword) -NN_psubb, // Packed Subtract Byte -NN_psubw, // Packed Subtract Word -NN_psubd, // Packed Subtract Dword -NN_psubsb, // Packed Subtract with Saturation (Byte) -NN_psubsw, // Packed Subtract with Saturation (Word) -NN_psubusb, // Packed Subtract Unsigned with Saturation (Byte) -NN_psubusw, // Packed Subtract Unsigned with Saturation (Word) -NN_punpckhbw, // Unpack High Packed Data (Byte->Word) -NN_punpckhwd, // Unpack High Packed Data (Word->Dword) -NN_punpckhdq, // Unpack High Packed Data (Dword->Qword) -NN_punpcklbw, // Unpack Low Packed Data (Byte->Word) -NN_punpcklwd, // Unpack Low Packed Data (Word->Dword) -NN_punpckldq, // Unpack Low Packed Data (Dword->Qword) -NN_pxor, // Bitwise Logical Exclusive Or - -// -// Undocumented Deschutes processor instructions -// - -NN_fxsave, // Fast save FP context -NN_fxrstor, // Fast restore FP context - -// Pentium II instructions - -NN_sysenter, // Fast Transition to System Call Entry Point -NN_sysexit, // Fast Transition from System Call Entry Point - -// 3DNow! instructions - -NN_pavgusb, // Packed 8-bit Unsigned Integer Averaging -NN_pfadd, // Packed Floating-Point Addition -NN_pfsub, // Packed Floating-Point Subtraction -NN_pfsubr, // Packed Floating-Point Reverse Subtraction -NN_pfacc, // Packed Floating-Point Accumulate -NN_pfcmpge, // Packed Floating-Point Comparison, Greater or Equal -NN_pfcmpgt, // Packed Floating-Point Comparison, Greater -NN_pfcmpeq, // Packed Floating-Point Comparison, Equal -NN_pfmin, // Packed Floating-Point Minimum -NN_pfmax, // Packed Floating-Point Maximum -NN_pi2fd, // Packed 32-bit Integer to Floating-Point -NN_pf2id, // Packed Floating-Point to 32-bit Integer -NN_pfrcp, // Packed Floating-Point Reciprocal Approximation -NN_pfrsqrt, // Packed Floating-Point Reciprocal Square Root Approximation -NN_pfmul, // Packed Floating-Point Multiplication -NN_pfrcpit1, // Packed Floating-Point Reciprocal First Iteration Step -NN_pfrsqit1, // Packed Floating-Point Reciprocal Square Root First Iteration Step -NN_pfrcpit2, // Packed Floating-Point Reciprocal Second Iteration Step -NN_pmulhrw, // Packed Floating-Point 16-bit Integer Multiply with rounding -NN_femms, // Faster entry/exit of the MMX or floating-point state -NN_prefetch, // Prefetch at least a 32-byte line into L1 data cache -NN_prefetchw, // Prefetch processor cache line into L1 data cache (mark as modified) - - -// Pentium III instructions - -NN_addps, // Packed Single-FP Add -NN_addss, // Scalar Single-FP Add -NN_andnps, // Bitwise Logical And Not for Single-FP -NN_andps, // Bitwise Logical And for Single-FP -NN_cmpps, // Packed Single-FP Compare -NN_cmpss, // Scalar Single-FP Compare -NN_comiss, // Scalar Ordered Single-FP Compare and Set EFLAGS -NN_cvtpi2ps, // Packed signed INT32 to Packed Single-FP conversion -NN_cvtps2pi, // Packed Single-FP to Packed INT32 conversion -NN_cvtsi2ss, // Scalar signed INT32 to Single-FP conversion -NN_cvtss2si, // Scalar Single-FP to signed INT32 conversion -NN_cvttps2pi, // Packed Single-FP to Packed INT32 conversion (truncate) -NN_cvttss2si, // Scalar Single-FP to signed INT32 conversion (truncate) -NN_divps, // Packed Single-FP Divide -NN_divss, // Scalar Single-FP Divide -NN_ldmxcsr, // Load Streaming SIMD Extensions Technology Control/Status Register -NN_maxps, // Packed Single-FP Maximum -NN_maxss, // Scalar Single-FP Maximum -NN_minps, // Packed Single-FP Minimum -NN_minss, // Scalar Single-FP Minimum -NN_movaps, // Move Aligned Four Packed Single-FP -NN_movhlps, // Move High to Low Packed Single-FP -NN_movhps, // Move High Packed Single-FP -NN_movlhps, // Move Low to High Packed Single-FP -NN_movlps, // Move Low Packed Single-FP -NN_movmskps, // Move Mask to Register -NN_movss, // Move Scalar Single-FP -NN_movups, // Move Unaligned Four Packed Single-FP -NN_mulps, // Packed Single-FP Multiply -NN_mulss, // Scalar Single-FP Multiply -NN_orps, // Bitwise Logical OR for Single-FP Data -NN_rcpps, // Packed Single-FP Reciprocal -NN_rcpss, // Scalar Single-FP Reciprocal -NN_rsqrtps, // Packed Single-FP Square Root Reciprocal -NN_rsqrtss, // Scalar Single-FP Square Root Reciprocal -NN_shufps, // Shuffle Single-FP -NN_sqrtps, // Packed Single-FP Square Root -NN_sqrtss, // Scalar Single-FP Square Root -NN_stmxcsr, // Store Streaming SIMD Extensions Technology Control/Status Register -NN_subps, // Packed Single-FP Subtract -NN_subss, // Scalar Single-FP Subtract -NN_ucomiss, // Scalar Unordered Single-FP Compare and Set EFLAGS -NN_unpckhps, // Unpack High Packed Single-FP Data -NN_unpcklps, // Unpack Low Packed Single-FP Data -NN_xorps, // Bitwise Logical XOR for Single-FP Data -NN_pavgb, // Packed Average (Byte) -NN_pavgw, // Packed Average (Word) -NN_pextrw, // Extract Word -NN_pinsrw, // Insert Word -NN_pmaxsw, // Packed Signed Integer Word Maximum -NN_pmaxub, // Packed Unsigned Integer Byte Maximum -NN_pminsw, // Packed Signed Integer Word Minimum -NN_pminub, // Packed Unsigned Integer Byte Minimum -NN_pmovmskb, // Move Byte Mask to Integer -NN_pmulhuw, // Packed Multiply High Unsigned -NN_psadbw, // Packed Sum of Absolute Differences -NN_pshufw, // Packed Shuffle Word -NN_maskmovq, // Byte Mask write -NN_movntps, // Move Aligned Four Packed Single-FP Non Temporal -NN_movntq, // Move 64 Bits Non Temporal -NN_prefetcht0, // Prefetch to all cache levels -NN_prefetcht1, // Prefetch to all cache levels -NN_prefetcht2, // Prefetch to L2 cache -NN_prefetchnta, // Prefetch to L1 cache -NN_sfence, // Store Fence - -// Pentium III Pseudo instructions - -NN_cmpeqps, // Packed Single-FP Compare EQ -NN_cmpltps, // Packed Single-FP Compare LT -NN_cmpleps, // Packed Single-FP Compare LE -NN_cmpunordps, // Packed Single-FP Compare UNORD -NN_cmpneqps, // Packed Single-FP Compare NOT EQ -NN_cmpnltps, // Packed Single-FP Compare NOT LT -NN_cmpnleps, // Packed Single-FP Compare NOT LE -NN_cmpordps, // Packed Single-FP Compare ORDERED -NN_cmpeqss, // Scalar Single-FP Compare EQ -NN_cmpltss, // Scalar Single-FP Compare LT -NN_cmpless, // Scalar Single-FP Compare LE -NN_cmpunordss, // Scalar Single-FP Compare UNORD -NN_cmpneqss, // Scalar Single-FP Compare NOT EQ -NN_cmpnltss, // Scalar Single-FP Compare NOT LT -NN_cmpnless, // Scalar Single-FP Compare NOT LE -NN_cmpordss, // Scalar Single-FP Compare ORDERED - -// AMD K7 instructions - -NN_pf2iw, // Packed Floating-Point to Integer with Sign Extend -NN_pfnacc, // Packed Floating-Point Negative Accumulate -NN_pfpnacc, // Packed Floating-Point Mixed Positive-Negative Accumulate -NN_pi2fw, // Packed 16-bit Integer to Floating-Point -NN_pswapd, // Packed Swap Double Word - -// Undocumented FP instructions (thanks to norbert.juffa@amd.com) - -NN_fstp1, // Alias of Store Real and Pop -NN_fcom2, // Alias of Compare Real -NN_fcomp3, // Alias of Compare Real and Pop -NN_fxch4, // Alias of Exchange Registers -NN_fcomp5, // Alias of Compare Real and Pop -NN_ffreep, // Free Register and Pop -NN_fxch7, // Alias of Exchange Registers -NN_fstp8, // Alias of Store Real and Pop -NN_fstp9, // Alias of Store Real and Pop - -// Pentium 4 instructions - -NN_addpd, // Add Packed Double-Precision Floating-Point Values -NN_addsd, // Add Scalar Double-Precision Floating-Point Values -NN_andnpd, // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values -NN_andpd, // Bitwise Logical AND of Packed Double-Precision Floating-Point Values -NN_clflush, // Flush Cache Line -NN_cmppd, // Compare Packed Double-Precision Floating-Point Values -NN_cmpsd, // Compare Scalar Double-Precision Floating-Point Values -NN_comisd, // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS -NN_cvtdq2pd, // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values -NN_cvtdq2ps, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values -NN_cvtpd2dq, // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers -NN_cvtpd2pi, // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers -NN_cvtpd2ps, // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values -NN_cvtpi2pd, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values -NN_cvtps2dq, // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers -NN_cvtps2pd, // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values -NN_cvtsd2si, // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer -NN_cvtsd2ss, // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value -NN_cvtsi2sd, // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value -NN_cvtss2sd, // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value -NN_cvttpd2dq, // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers -NN_cvttpd2pi, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers -NN_cvttps2dq, // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers -NN_cvttsd2si, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer -NN_divpd, // Divide Packed Double-Precision Floating-Point Values -NN_divsd, // Divide Scalar Double-Precision Floating-Point Values -NN_lfence, // Load Fence -NN_maskmovdqu, // Store Selected Bytes of Double Quadword -NN_maxpd, // Return Maximum Packed Double-Precision Floating-Point Values -NN_maxsd, // Return Maximum Scalar Double-Precision Floating-Point Value -NN_mfence, // Memory Fence -NN_minpd, // Return Minimum Packed Double-Precision Floating-Point Values -NN_minsd, // Return Minimum Scalar Double-Precision Floating-Point Value -NN_movapd, // Move Aligned Packed Double-Precision Floating-Point Values -NN_movdq2q, // Move Quadword from XMM to MMX Register -NN_movdqa, // Move Aligned Double Quadword -NN_movdqu, // Move Unaligned Double Quadword -NN_movhpd, // Move High Packed Double-Precision Floating-Point Values -NN_movlpd, // Move Low Packed Double-Precision Floating-Point Values -NN_movmskpd, // Extract Packed Double-Precision Floating-Point Sign Mask -NN_movntdq, // Store Double Quadword Using Non-Temporal Hint -NN_movnti, // Store Doubleword Using Non-Temporal Hint -NN_movntpd, // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint -NN_movq2dq, // Move Quadword from MMX to XMM Register -NN_movsd, // Move Scalar Double-Precision Floating-Point Values -NN_movupd, // Move Unaligned Packed Double-Precision Floating-Point Values -NN_mulpd, // Multiply Packed Double-Precision Floating-Point Values -NN_mulsd, // Multiply Scalar Double-Precision Floating-Point Values -NN_orpd, // Bitwise Logical OR of Double-Precision Floating-Point Values -NN_paddq, // Add Packed Quadword Integers -NN_pause, // Spin Loop Hint -NN_pmuludq, // Multiply Packed Unsigned Doubleword Integers -NN_pshufd, // Shuffle Packed Doublewords -NN_pshufhw, // Shuffle Packed High Words -NN_pshuflw, // Shuffle Packed Low Words -NN_pslldq, // Shift Double Quadword Left Logical -NN_psrldq, // Shift Double Quadword Right Logical -NN_psubq, // Subtract Packed Quadword Integers -NN_punpckhqdq, // Unpack High Data -NN_punpcklqdq, // Unpack Low Data -NN_shufpd, // Shuffle Packed Double-Precision Floating-Point Values -NN_sqrtpd, // Compute Square Roots of Packed Double-Precision Floating-Point Values -NN_sqrtsd, // Compute Square Rootof Scalar Double-Precision Floating-Point Value -NN_subpd, // Subtract Packed Double-Precision Floating-Point Values -NN_subsd, // Subtract Scalar Double-Precision Floating-Point Values -NN_ucomisd, // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS -NN_unpckhpd, // Unpack and Interleave High Packed Double-Precision Floating-Point Values -NN_unpcklpd, // Unpack and Interleave Low Packed Double-Precision Floating-Point Values -NN_xorpd, // Bitwise Logical OR of Double-Precision Floating-Point Values - -// AMD syscall/sysret instructions - -NN_syscall, // Low latency system call -NN_sysret, // Return from system call - -// AMD64 instructions - -NN_swapgs, // Exchange GS base with KernelGSBase MSR - -// New Pentium instructions (SSE3) - -NN_movddup, // Move One Double-FP and Duplicate -NN_movshdup, // Move Packed Single-FP High and Duplicate -NN_movsldup, // Move Packed Single-FP Low and Duplicate - -// Missing AMD64 instructions - -NN_movsxd, // Move with Sign-Extend Doubleword -NN_cmpxchg16b, // Compare and Exchange 16 Bytes - -// SSE3 instructions - -NN_addsubpd, // Add /Sub packed DP FP numbers -NN_addsubps, // Add /Sub packed SP FP numbers -NN_haddpd, // Add horizontally packed DP FP numbers -NN_haddps, // Add horizontally packed SP FP numbers -NN_hsubpd, // Sub horizontally packed DP FP numbers -NN_hsubps, // Sub horizontally packed SP FP numbers -NN_monitor, // Set up a linear address range to be monitored by hardware -NN_mwait, // Wait until write-back store performed within the range specified by the MONITOR instruction -NN_fisttp, // Store ST in intXX (chop) and pop -NN_lddqu, // Load unaligned integer 128-bit - -// SSSE3 instructions - -NN_psignb, // Packed SIGN Byte -NN_psignw, // Packed SIGN Word -NN_psignd, // Packed SIGN Doubleword -NN_pshufb, // Packed Shuffle Bytes -NN_pmulhrsw, // Packed Multiply High with Round and Scale -NN_pmaddubsw, // Multiply and Add Packed Signed and Unsigned Bytes -NN_phsubsw, // Packed Horizontal Subtract and Saturate -NN_phaddsw, // Packed Horizontal Add and Saturate -NN_phaddw, // Packed Horizontal Add Word -NN_phaddd, // Packed Horizontal Add Doubleword -NN_phsubw, // Packed Horizontal Subtract Word -NN_phsubd, // Packed Horizontal Subtract Doubleword -NN_palignr, // Packed Align Right -NN_pabsb, // Packed Absolute Value Byte -NN_pabsw, // Packed Absolute Value Word -NN_pabsd, // Packed Absolute Value Doubleword - -// VMX instructions - -NN_vmcall, // Call to VM Monitor -NN_vmclear, // Clear Virtual Machine Control Structure -NN_vmlaunch, // Launch Virtual Machine -NN_vmresume, // Resume Virtual Machine -NN_vmptrld, // Load Pointer to Virtual Machine Control Structure -NN_vmptrst, // Store Pointer to Virtual Machine Control Structure -NN_vmread, // Read Field from Virtual Machine Control Structure -NN_vmwrite, // Write Field from Virtual Machine Control Structure -NN_vmxoff, // Leave VMX Operation -NN_vmxon, // Enter VMX Operation - -// Undefined Instruction - -NN_ud2, // Undefined Instruction - -// Added with x86-64 - -NN_rdtscp, // Read Time-Stamp Counter and Processor ID - -// Geode LX 3DNow! extensions - -NN_pfrcpv, // Reciprocal Approximation for a Pair of 32-bit Floats -NN_pfrsqrtv, // Reciprocal Square Root Approximation for a Pair of 32-bit Floats - -// SSE2 pseudoinstructions - -NN_cmpeqpd, // Packed Double-FP Compare EQ -NN_cmpltpd, // Packed Double-FP Compare LT -NN_cmplepd, // Packed Double-FP Compare LE -NN_cmpunordpd, // Packed Double-FP Compare UNORD -NN_cmpneqpd, // Packed Double-FP Compare NOT EQ -NN_cmpnltpd, // Packed Double-FP Compare NOT LT -NN_cmpnlepd, // Packed Double-FP Compare NOT LE -NN_cmpordpd, // Packed Double-FP Compare ORDERED -NN_cmpeqsd, // Scalar Double-FP Compare EQ -NN_cmpltsd, // Scalar Double-FP Compare LT -NN_cmplesd, // Scalar Double-FP Compare LE -NN_cmpunordsd, // Scalar Double-FP Compare UNORD -NN_cmpneqsd, // Scalar Double-FP Compare NOT EQ -NN_cmpnltsd, // Scalar Double-FP Compare NOT LT -NN_cmpnlesd, // Scalar Double-FP Compare NOT LE -NN_cmpordsd, // Scalar Double-FP Compare ORDERED - -// SSSE4.1 instructions - -NN_blendpd, // Blend Packed Double Precision Floating-Point Values -NN_blendps, // Blend Packed Single Precision Floating-Point Values -NN_blendvpd, // Variable Blend Packed Double Precision Floating-Point Values -NN_blendvps, // Variable Blend Packed Single Precision Floating-Point Values -NN_dppd, // Dot Product of Packed Double Precision Floating-Point Values -NN_dpps, // Dot Product of Packed Single Precision Floating-Point Values -NN_extractps, // Extract Packed Single Precision Floating-Point Value -NN_insertps, // Insert Packed Single Precision Floating-Point Value -NN_movntdqa, // Load Double Quadword Non-Temporal Aligned Hint -NN_mpsadbw, // Compute Multiple Packed Sums of Absolute Difference -NN_packusdw, // Pack with Unsigned Saturation -NN_pblendvb, // Variable Blend Packed Bytes -NN_pblendw, // Blend Packed Words -NN_pcmpeqq, // Compare Packed Qword Data for Equal -NN_pextrb, // Extract Byte -NN_pextrd, // Extract Dword -NN_pextrq, // Extract Qword -NN_phminposuw, // Packed Horizontal Word Minimum -NN_pinsrb, // Insert Byte -NN_pinsrd, // Insert Dword -NN_pinsrq, // Insert Qword -NN_pmaxsb, // Maximum of Packed Signed Byte Integers -NN_pmaxsd, // Maximum of Packed Signed Dword Integers -NN_pmaxud, // Maximum of Packed Unsigned Dword Integers -NN_pmaxuw, // Maximum of Packed Word Integers -NN_pminsb, // Minimum of Packed Signed Byte Integers -NN_pminsd, // Minimum of Packed Signed Dword Integers -NN_pminud, // Minimum of Packed Unsigned Dword Integers -NN_pminuw, // Minimum of Packed Word Integers -NN_pmovsxbw, // Packed Move with Sign Extend -NN_pmovsxbd, // Packed Move with Sign Extend -NN_pmovsxbq, // Packed Move with Sign Extend -NN_pmovsxwd, // Packed Move with Sign Extend -NN_pmovsxwq, // Packed Move with Sign Extend -NN_pmovsxdq, // Packed Move with Sign Extend -NN_pmovzxbw, // Packed Move with Zero Extend -NN_pmovzxbd, // Packed Move with Zero Extend -NN_pmovzxbq, // Packed Move with Zero Extend -NN_pmovzxwd, // Packed Move with Zero Extend -NN_pmovzxwq, // Packed Move with Zero Extend -NN_pmovzxdq, // Packed Move with Zero Extend -NN_pmuldq, // Multiply Packed Signed Dword Integers -NN_pmulld, // Multiply Packed Signed Dword Integers and Store Low Result -NN_ptest, // Logical Compare -NN_roundpd, // Round Packed Double Precision Floating-Point Values -NN_roundps, // Round Packed Single Precision Floating-Point Values -NN_roundsd, // Round Scalar Double Precision Floating-Point Values -NN_roundss, // Round Scalar Single Precision Floating-Point Values - -// SSSE4.2 instructions - -NN_crc32, // Accumulate CRC32 Value -NN_pcmpestri, // Packed Compare Explicit Length Strings, Return Index -NN_pcmpestrm, // Packed Compare Explicit Length Strings, Return Mask -NN_pcmpistri, // Packed Compare Implicit Length Strings, Return Index -NN_pcmpistrm, // Packed Compare Implicit Length Strings, Return Mask -NN_pcmpgtq, // Compare Packed Data for Greater Than -NN_popcnt, // Return the Count of Number of Bits Set to 1 - -// AMD SSE4a instructions - -NN_extrq, // Extract Field From Register -NN_insertq, // Insert Field -NN_movntsd, // Move Non-Temporal Scalar Double-Precision Floating-Point -NN_movntss, // Move Non-Temporal Scalar Single-Precision Floating-Point -NN_lzcnt, // Leading Zero Count - -// xsave/xrstor instructions - -NN_xgetbv, // Get Value of Extended Control Register -NN_xrstor, // Restore Processor Extended States -NN_xsave, // Save Processor Extended States -NN_xsetbv, // Set Value of Extended Control Register - -// Intel Safer Mode Extensions (SMX) - -NN_getsec, // Safer Mode Extensions (SMX) Instruction - -// AMD-V Virtualization ISA Extension - -NN_clgi, // Clear Global Interrupt Flag -NN_invlpga, // Invalidate TLB Entry in a Specified ASID -NN_skinit, // Secure Init and Jump with Attestation -NN_stgi, // Set Global Interrupt Flag -NN_vmexit, // Stop Executing Guest, Begin Executing Host -NN_vmload, // Load State from VMCB -NN_vmmcall, // Call VMM -NN_vmrun, // Run Virtual Machine -NN_vmsave, // Save State to VMCB - -// VMX+ instructions - -NN_invept, // Invalidate Translations Derived from EPT -NN_invvpid, // Invalidate Translations Based on VPID - -// Intel Atom instructions - -NN_movbe, // Move Data After Swapping Bytes - -// Intel AES instructions - -NN_aesenc, // Perform One Round of an AES Encryption Flow -NN_aesenclast, // Perform the Last Round of an AES Encryption Flow -NN_aesdec, // Perform One Round of an AES Decryption Flow -NN_aesdeclast, // Perform the Last Round of an AES Decryption Flow -NN_aesimc, // Perform the AES InvMixColumn Transformation -NN_aeskeygenassist, // AES Round Key Generation Assist - -// Carryless multiplication - -NN_pclmulqdq, // Carry-Less Multiplication Quadword - -// Returns modifies by operand size prefixes - -NN_retnw, // Return Near from Procedure (use16) -NN_retnd, // Return Near from Procedure (use32) -NN_retnq, // Return Near from Procedure (use64) -NN_retfw, // Return Far from Procedure (use16) -NN_retfd, // Return Far from Procedure (use32) -NN_retfq, // Return Far from Procedure (use64) - -// RDRAND support - -NN_rdrand, // Read Random Number - -// new GPR instructions - -NN_adcx, // Unsigned Integer Addition of Two Operands with Carry Flag -NN_adox, // Unsigned Integer Addition of Two Operands with Overflow Flag -NN_andn, // Logical AND NOT -NN_bextr, // Bit Field Extract -NN_blsi, // Extract Lowest Set Isolated Bit -NN_blsmsk, // Get Mask Up to Lowest Set Bit -NN_blsr, // Reset Lowest Set Bit -NN_bzhi, // Zero High Bits Starting with Specified Bit Position -NN_clac, // Clear AC Flag in EFLAGS Register -NN_mulx, // Unsigned Multiply Without Affecting Flags -NN_pdep, // Parallel Bits Deposit -NN_pext, // Parallel Bits Extract -NN_rorx, // Rotate Right Logical Without Affecting Flags -NN_sarx, // Shift Arithmetically Right Without Affecting Flags -NN_shlx, // Shift Logically Left Without Affecting Flags -NN_shrx, // Shift Logically Right Without Affecting Flags -NN_stac, // Set AC Flag in EFLAGS Register -NN_tzcnt, // Count the Number of Trailing Zero Bits -NN_xsaveopt, // Save Processor Extended States Optimized -NN_invpcid, // Invalidate Processor Context ID -NN_rdseed, // Read Random Seed -NN_rdfsbase, // Read FS Segment Base -NN_rdgsbase, // Read GS Segment Base -NN_wrfsbase, // Write FS Segment Base -NN_wrgsbase, // Write GS Segment Base - -// new AVX instructions - -NN_vaddpd, // Add Packed Double-Precision Floating-Point Values -NN_vaddps, // Packed Single-FP Add -NN_vaddsd, // Add Scalar Double-Precision Floating-Point Values -NN_vaddss, // Scalar Single-FP Add -NN_vaddsubpd, // Add /Sub packed DP FP numbers -NN_vaddsubps, // Add /Sub packed SP FP numbers -NN_vaesdec, // Perform One Round of an AES Decryption Flow -NN_vaesdeclast, // Perform the Last Round of an AES Decryption Flow -NN_vaesenc, // Perform One Round of an AES Encryption Flow -NN_vaesenclast, // Perform the Last Round of an AES Encryption Flow -NN_vaesimc, // Perform the AES InvMixColumn Transformation -NN_vaeskeygenassist, // AES Round Key Generation Assist -NN_vandnpd, // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values -NN_vandnps, // Bitwise Logical And Not for Single-FP -NN_vandpd, // Bitwise Logical AND of Packed Double-Precision Floating-Point Values -NN_vandps, // Bitwise Logical And for Single-FP -NN_vblendpd, // Blend Packed Double Precision Floating-Point Values -NN_vblendps, // Blend Packed Single Precision Floating-Point Values -NN_vblendvpd, // Variable Blend Packed Double Precision Floating-Point Values -NN_vblendvps, // Variable Blend Packed Single Precision Floating-Point Values -NN_vbroadcastf128, // Broadcast 128 Bits of Floating-Point Data -NN_vbroadcasti128, // Broadcast 128 Bits of Integer Data -NN_vbroadcastsd, // Broadcast Double-Precision Floating-Point Element -NN_vbroadcastss, // Broadcast Single-Precision Floating-Point Element -NN_vcmppd, // Compare Packed Double-Precision Floating-Point Values -NN_vcmpps, // Packed Single-FP Compare -NN_vcmpsd, // Compare Scalar Double-Precision Floating-Point Values -NN_vcmpss, // Scalar Single-FP Compare -NN_vcomisd, // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS -NN_vcomiss, // Scalar Ordered Single-FP Compare and Set EFLAGS -NN_vcvtdq2pd, // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values -NN_vcvtdq2ps, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values -NN_vcvtpd2dq, // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers -NN_vcvtpd2ps, // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values -NN_vcvtph2ps, // Convert 16-bit FP Values to Single-Precision FP Values -NN_vcvtps2dq, // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers -NN_vcvtps2pd, // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values -NN_vcvtps2ph, // Convert Single-Precision FP value to 16-bit FP value -NN_vcvtsd2si, // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer -NN_vcvtsd2ss, // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value -NN_vcvtsi2sd, // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value -NN_vcvtsi2ss, // Scalar signed INT32 to Single-FP conversion -NN_vcvtss2sd, // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value -NN_vcvtss2si, // Scalar Single-FP to signed INT32 conversion -NN_vcvttpd2dq, // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers -NN_vcvttps2dq, // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers -NN_vcvttsd2si, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer -NN_vcvttss2si, // Scalar Single-FP to signed INT32 conversion (truncate) -NN_vdivpd, // Divide Packed Double-Precision Floating-Point Values -NN_vdivps, // Packed Single-FP Divide -NN_vdivsd, // Divide Scalar Double-Precision Floating-Point Values -NN_vdivss, // Scalar Single-FP Divide -NN_vdppd, // Dot Product of Packed Double Precision Floating-Point Values -NN_vdpps, // Dot Product of Packed Single Precision Floating-Point Values -NN_vextractf128, // Extract Packed Floating-Point Values -NN_vextracti128, // Extract Packed Integer Values -NN_vextractps, // Extract Packed Floating-Point Values -NN_vfmadd132pd, // Fused Multiply-Add of Packed Double-Precision Floating-Point Values -NN_vfmadd132ps, // Fused Multiply-Add of Packed Single-Precision Floating-Point Values -NN_vfmadd132sd, // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values -NN_vfmadd132ss, // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values -NN_vfmadd213pd, // Fused Multiply-Add of Packed Double-Precision Floating-Point Values -NN_vfmadd213ps, // Fused Multiply-Add of Packed Single-Precision Floating-Point Values -NN_vfmadd213sd, // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values -NN_vfmadd213ss, // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values -NN_vfmadd231pd, // Fused Multiply-Add of Packed Double-Precision Floating-Point Values -NN_vfmadd231ps, // Fused Multiply-Add of Packed Single-Precision Floating-Point Values -NN_vfmadd231sd, // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values -NN_vfmadd231ss, // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values -NN_vfmaddsub132pd, // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values -NN_vfmaddsub132ps, // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values -NN_vfmaddsub213pd, // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values -NN_vfmaddsub213ps, // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values -NN_vfmaddsub231pd, // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values -NN_vfmaddsub231ps, // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values -NN_vfmsub132pd, // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values -NN_vfmsub132ps, // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values -NN_vfmsub132sd, // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values -NN_vfmsub132ss, // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values -NN_vfmsub213pd, // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values -NN_vfmsub213ps, // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values -NN_vfmsub213sd, // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values -NN_vfmsub213ss, // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values -NN_vfmsub231pd, // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values -NN_vfmsub231ps, // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values -NN_vfmsub231sd, // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values -NN_vfmsub231ss, // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values -NN_vfmsubadd132pd, // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values -NN_vfmsubadd132ps, // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values -NN_vfmsubadd213pd, // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values -NN_vfmsubadd213ps, // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values -NN_vfmsubadd231pd, // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values -NN_vfmsubadd231ps, // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values -NN_vfnmadd132pd, // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values -NN_vfnmadd132ps, // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values -NN_vfnmadd132sd, // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values -NN_vfnmadd132ss, // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values -NN_vfnmadd213pd, // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values -NN_vfnmadd213ps, // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values -NN_vfnmadd213sd, // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values -NN_vfnmadd213ss, // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values -NN_vfnmadd231pd, // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values -NN_vfnmadd231ps, // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values -NN_vfnmadd231sd, // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values -NN_vfnmadd231ss, // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values -NN_vfnmsub132pd, // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values -NN_vfnmsub132ps, // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values -NN_vfnmsub132sd, // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values -NN_vfnmsub132ss, // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values -NN_vfnmsub213pd, // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values -NN_vfnmsub213ps, // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values -NN_vfnmsub213sd, // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values -NN_vfnmsub213ss, // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values -NN_vfnmsub231pd, // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values -NN_vfnmsub231ps, // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values -NN_vfnmsub231sd, // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values -NN_vfnmsub231ss, // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values -NN_vgatherdps, // Gather Packed SP FP Values Using Signed Dword Indices -NN_vgatherdpd, // Gather Packed DP FP Values Using Signed Dword Indices -NN_vgatherqps, // Gather Packed SP FP Values Using Signed Qword Indices -NN_vgatherqpd, // Gather Packed DP FP Values Using Signed Qword Indices -NN_vhaddpd, // Add horizontally packed DP FP numbers -NN_vhaddps, // Add horizontally packed SP FP numbers -NN_vhsubpd, // Sub horizontally packed DP FP numbers -NN_vhsubps, // Sub horizontally packed SP FP numbers -NN_vinsertf128, // Insert Packed Floating-Point Values -NN_vinserti128, // Insert Packed Integer Values -NN_vinsertps, // Insert Packed Single Precision Floating-Point Value -NN_vlddqu, // Load Unaligned Packed Integer Values -NN_vldmxcsr, // Load Streaming SIMD Extensions Technology Control/Status Register -NN_vmaskmovdqu, // Store Selected Bytes of Double Quadword with NT Hint -NN_vmaskmovpd, // Conditionally Load Packed Double-Precision Floating-Point Values -NN_vmaskmovps, // Conditionally Load Packed Single-Precision Floating-Point Values -NN_vmaxpd, // Return Maximum Packed Double-Precision Floating-Point Values -NN_vmaxps, // Packed Single-FP Maximum -NN_vmaxsd, // Return Maximum Scalar Double-Precision Floating-Point Value -NN_vmaxss, // Scalar Single-FP Maximum -NN_vminpd, // Return Minimum Packed Double-Precision Floating-Point Values -NN_vminps, // Packed Single-FP Minimum -NN_vminsd, // Return Minimum Scalar Double-Precision Floating-Point Value -NN_vminss, // Scalar Single-FP Minimum -NN_vmovapd, // Move Aligned Packed Double-Precision Floating-Point Values -NN_vmovaps, // Move Aligned Four Packed Single-FP -NN_vmovd, // Move 32 bits -NN_vmovddup, // Move One Double-FP and Duplicate -NN_vmovdqa, // Move Aligned Double Quadword -NN_vmovdqu, // Move Unaligned Double Quadword -NN_vmovhlps, // Move High to Low Packed Single-FP -NN_vmovhpd, // Move High Packed Double-Precision Floating-Point Values -NN_vmovhps, // Move High Packed Single-FP -NN_vmovlhps, // Move Low to High Packed Single-FP -NN_vmovlpd, // Move Low Packed Double-Precision Floating-Point Values -NN_vmovlps, // Move Low Packed Single-FP -NN_vmovmskpd, // Extract Packed Double-Precision Floating-Point Sign Mask -NN_vmovmskps, // Move Mask to Register -NN_vmovntdq, // Store Double Quadword Using Non-Temporal Hint -NN_vmovntdqa, // Load Double Quadword Non-Temporal Aligned Hint -NN_vmovntpd, // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint -NN_vmovntps, // Move Aligned Four Packed Single-FP Non Temporal -NN_vmovq, // Move 64 bits -NN_vmovsd, // Move Scalar Double-Precision Floating-Point Values -NN_vmovshdup, // Move Packed Single-FP High and Duplicate -NN_vmovsldup, // Move Packed Single-FP Low and Duplicate -NN_vmovss, // Move Scalar Single-FP -NN_vmovupd, // Move Unaligned Packed Double-Precision Floating-Point Values -NN_vmovups, // Move Unaligned Four Packed Single-FP -NN_vmpsadbw, // Compute Multiple Packed Sums of Absolute Difference -NN_vmulpd, // Multiply Packed Double-Precision Floating-Point Values -NN_vmulps, // Packed Single-FP Multiply -NN_vmulsd, // Multiply Scalar Double-Precision Floating-Point Values -NN_vmulss, // Scalar Single-FP Multiply -NN_vorpd, // Bitwise Logical OR of Double-Precision Floating-Point Values -NN_vorps, // Bitwise Logical OR for Single-FP Data -NN_vpabsb, // Packed Absolute Value Byte -NN_vpabsd, // Packed Absolute Value Doubleword -NN_vpabsw, // Packed Absolute Value Word -NN_vpackssdw, // Pack with Signed Saturation (Dword->Word) -NN_vpacksswb, // Pack with Signed Saturation (Word->Byte) -NN_vpackusdw, // Pack with Unsigned Saturation -NN_vpackuswb, // Pack with Unsigned Saturation (Word->Byte) -NN_vpaddb, // Packed Add Byte -NN_vpaddd, // Packed Add Dword -NN_vpaddq, // Add Packed Quadword Integers -NN_vpaddsb, // Packed Add with Saturation (Byte) -NN_vpaddsw, // Packed Add with Saturation (Word) -NN_vpaddusb, // Packed Add Unsigned with Saturation (Byte) -NN_vpaddusw, // Packed Add Unsigned with Saturation (Word) -NN_vpaddw, // Packed Add Word -NN_vpalignr, // Packed Align Right -NN_vpand, // Bitwise Logical And -NN_vpandn, // Bitwise Logical And Not -NN_vpavgb, // Packed Average (Byte) -NN_vpavgw, // Packed Average (Word) -NN_vpblendd, // Blend Packed Dwords -NN_vpblendvb, // Variable Blend Packed Bytes -NN_vpblendw, // Blend Packed Words -NN_vpbroadcastb, // Broadcast a Byte Integer -NN_vpbroadcastd, // Broadcast a Dword Integer -NN_vpbroadcastq, // Broadcast a Qword Integer -NN_vpbroadcastw, // Broadcast a Word Integer -NN_vpclmulqdq, // Carry-Less Multiplication Quadword -NN_vpcmpeqb, // Packed Compare for Equal (Byte) -NN_vpcmpeqd, // Packed Compare for Equal (Dword) -NN_vpcmpeqq, // Compare Packed Qword Data for Equal -NN_vpcmpeqw, // Packed Compare for Equal (Word) -NN_vpcmpestri, // Packed Compare Explicit Length Strings, Return Index -NN_vpcmpestrm, // Packed Compare Explicit Length Strings, Return Mask -NN_vpcmpgtb, // Packed Compare for Greater Than (Byte) -NN_vpcmpgtd, // Packed Compare for Greater Than (Dword) -NN_vpcmpgtq, // Compare Packed Data for Greater Than -NN_vpcmpgtw, // Packed Compare for Greater Than (Word) -NN_vpcmpistri, // Packed Compare Implicit Length Strings, Return Index -NN_vpcmpistrm, // Packed Compare Implicit Length Strings, Return Mask -NN_vperm2f128, // Permute Floating-Point Values -NN_vperm2i128, // Permute Integer Values -NN_vpermd, // Full Doublewords Element Permutation -NN_vpermilpd, // Permute Double-Precision Floating-Point Values -NN_vpermilps, // Permute Single-Precision Floating-Point Values -NN_vpermpd, // Permute Double-Precision Floating-Point Elements -NN_vpermps, // Permute Single-Precision Floating-Point Elements -NN_vpermq, // Qwords Element Permutation -NN_vpextrb, // Extract Byte -NN_vpextrd, // Extract Dword -NN_vpextrq, // Extract Qword -NN_vpextrw, // Extract Word -NN_vpgatherdd, // Gather Packed Dword Values Using Signed Dword Indices -NN_vpgatherdq, // Gather Packed Qword Values Using Signed Dword Indices -NN_vpgatherqd, // Gather Packed Dword Values Using Signed Qword Indices -NN_vpgatherqq, // Gather Packed Qword Values Using Signed Qword Indices -NN_vphaddd, // Packed Horizontal Add Doubleword -NN_vphaddsw, // Packed Horizontal Add and Saturate -NN_vphaddw, // Packed Horizontal Add Word -NN_vphminposuw, // Packed Horizontal Word Minimum -NN_vphsubd, // Packed Horizontal Subtract Doubleword -NN_vphsubsw, // Packed Horizontal Subtract and Saturate -NN_vphsubw, // Packed Horizontal Subtract Word -NN_vpinsrb, // Insert Byte -NN_vpinsrd, // Insert Dword -NN_vpinsrq, // Insert Qword -NN_vpinsrw, // Insert Word -NN_vpmaddubsw, // Multiply and Add Packed Signed and Unsigned Bytes -NN_vpmaddwd, // Packed Multiply and Add -NN_vpmaskmovd, // Conditionally Store Dword Values Using Mask -NN_vpmaskmovq, // Conditionally Store Qword Values Using Mask -NN_vpmaxsb, // Maximum of Packed Signed Byte Integers -NN_vpmaxsd, // Maximum of Packed Signed Dword Integers -NN_vpmaxsw, // Packed Signed Integer Word Maximum -NN_vpmaxub, // Packed Unsigned Integer Byte Maximum -NN_vpmaxud, // Maximum of Packed Unsigned Dword Integers -NN_vpmaxuw, // Maximum of Packed Word Integers -NN_vpminsb, // Minimum of Packed Signed Byte Integers -NN_vpminsd, // Minimum of Packed Signed Dword Integers -NN_vpminsw, // Packed Signed Integer Word Minimum -NN_vpminub, // Packed Unsigned Integer Byte Minimum -NN_vpminud, // Minimum of Packed Unsigned Dword Integers -NN_vpminuw, // Minimum of Packed Word Integers -NN_vpmovmskb, // Move Byte Mask to Integer -NN_vpmovsxbd, // Packed Move with Sign Extend -NN_vpmovsxbq, // Packed Move with Sign Extend -NN_vpmovsxbw, // Packed Move with Sign Extend -NN_vpmovsxdq, // Packed Move with Sign Extend -NN_vpmovsxwd, // Packed Move with Sign Extend -NN_vpmovsxwq, // Packed Move with Sign Extend -NN_vpmovzxbd, // Packed Move with Zero Extend -NN_vpmovzxbq, // Packed Move with Zero Extend -NN_vpmovzxbw, // Packed Move with Zero Extend -NN_vpmovzxdq, // Packed Move with Zero Extend -NN_vpmovzxwd, // Packed Move with Zero Extend -NN_vpmovzxwq, // Packed Move with Zero Extend -NN_vpmuldq, // Multiply Packed Signed Dword Integers -NN_vpmulhrsw, // Packed Multiply High with Round and Scale -NN_vpmulhuw, // Packed Multiply High Unsigned -NN_vpmulhw, // Packed Multiply High -NN_vpmulld, // Multiply Packed Signed Dword Integers and Store Low Result -NN_vpmullw, // Packed Multiply Low -NN_vpmuludq, // Multiply Packed Unsigned Doubleword Integers -NN_vpor, // Bitwise Logical Or -NN_vpsadbw, // Packed Sum of Absolute Differences -NN_vpshufb, // Packed Shuffle Bytes -NN_vpshufd, // Shuffle Packed Doublewords -NN_vpshufhw, // Shuffle Packed High Words -NN_vpshuflw, // Shuffle Packed Low Words -NN_vpsignb, // Packed SIGN Byte -NN_vpsignd, // Packed SIGN Doubleword -NN_vpsignw, // Packed SIGN Word -NN_vpslld, // Packed Shift Left Logical (Dword) -NN_vpslldq, // Shift Double Quadword Left Logical -NN_vpsllq, // Packed Shift Left Logical (Qword) -NN_vpsllvd, // Variable Bit Shift Left Logical (Dword) -NN_vpsllvq, // Variable Bit Shift Left Logical (Qword) -NN_vpsllw, // Packed Shift Left Logical (Word) -NN_vpsrad, // Packed Shift Right Arithmetic (Dword) -NN_vpsravd, // Variable Bit Shift Right Arithmetic -NN_vpsraw, // Packed Shift Right Arithmetic (Word) -NN_vpsrld, // Packed Shift Right Logical (Dword) -NN_vpsrldq, // Shift Double Quadword Right Logical (Qword) -NN_vpsrlq, // Packed Shift Right Logical (Qword) -NN_vpsrlvd, // Variable Bit Shift Right Logical (Dword) -NN_vpsrlvq, // Variable Bit Shift Right Logical (Qword) -NN_vpsrlw, // Packed Shift Right Logical (Word) -NN_vpsubb, // Packed Subtract Byte -NN_vpsubd, // Packed Subtract Dword -NN_vpsubq, // Subtract Packed Quadword Integers -NN_vpsubsb, // Packed Subtract with Saturation (Byte) -NN_vpsubsw, // Packed Subtract with Saturation (Word) -NN_vpsubusb, // Packed Subtract Unsigned with Saturation (Byte) -NN_vpsubusw, // Packed Subtract Unsigned with Saturation (Word) -NN_vpsubw, // Packed Subtract Word -NN_vptest, // Logical Compare -NN_vpunpckhbw, // Unpack High Packed Data (Byte->Word) -NN_vpunpckhdq, // Unpack High Packed Data (Dword->Qword) -NN_vpunpckhqdq, // Unpack High Packed Data (Qword->Xmmword) -NN_vpunpckhwd, // Unpack High Packed Data (Word->Dword) -NN_vpunpcklbw, // Unpack Low Packed Data (Byte->Word) -NN_vpunpckldq, // Unpack Low Packed Data (Dword->Qword) -NN_vpunpcklqdq, // Unpack Low Packed Data (Qword->Xmmword) -NN_vpunpcklwd, // Unpack Low Packed Data (Word->Dword) -NN_vpxor, // Bitwise Logical Exclusive Or -NN_vrcpps, // Packed Single-FP Reciprocal -NN_vrcpss, // Scalar Single-FP Reciprocal -NN_vroundpd, // Round Packed Double Precision Floating-Point Values -NN_vroundps, // Round Packed Single Precision Floating-Point Values -NN_vroundsd, // Round Scalar Double Precision Floating-Point Values -NN_vroundss, // Round Scalar Single Precision Floating-Point Values -NN_vrsqrtps, // Packed Single-FP Square Root Reciprocal -NN_vrsqrtss, // Scalar Single-FP Square Root Reciprocal -NN_vshufpd, // Shuffle Packed Double-Precision Floating-Point Values -NN_vshufps, // Shuffle Single-FP -NN_vsqrtpd, // Compute Square Roots of Packed Double-Precision Floating-Point Values -NN_vsqrtps, // Packed Single-FP Square Root -NN_vsqrtsd, // Compute Square Rootof Scalar Double-Precision Floating-Point Value -NN_vsqrtss, // Scalar Single-FP Square Root -NN_vstmxcsr, // Store Streaming SIMD Extensions Technology Control/Status Register -NN_vsubpd, // Subtract Packed Double-Precision Floating-Point Values -NN_vsubps, // Packed Single-FP Subtract -NN_vsubsd, // Subtract Scalar Double-Precision Floating-Point Values -NN_vsubss, // Scalar Single-FP Subtract -NN_vtestpd, // Packed Double-Precision Floating-Point Bit Test -NN_vtestps, // Packed Single-Precision Floating-Point Bit Test -NN_vucomisd, // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS -NN_vucomiss, // Scalar Unordered Single-FP Compare and Set EFLAGS -NN_vunpckhpd, // Unpack and Interleave High Packed Double-Precision Floating-Point Values -NN_vunpckhps, // Unpack High Packed Single-FP Data -NN_vunpcklpd, // Unpack and Interleave Low Packed Double-Precision Floating-Point Values -NN_vunpcklps, // Unpack Low Packed Single-FP Data -NN_vxorpd, // Bitwise Logical OR of Double-Precision Floating-Point Values -NN_vxorps, // Bitwise Logical XOR for Single-FP Data -NN_vzeroall, // Zero All YMM Registers -NN_vzeroupper, // Zero Upper Bits of YMM Registers - -// Transactional Synchronization Extensions - -NN_xabort, // Transaction Abort -NN_xbegin, // Transaction Begin -NN_xend, // Transaction End -NN_xtest, // Test If In Transactional Execution - -// Virtual PC synthetic instructions - -NN_vmgetinfo, // Virtual PC - Get VM Information -NN_vmsetinfo, // Virtual PC - Set VM Information -NN_vmdxdsbl, // Virtual PC - Disable Direct Execution -NN_vmdxenbl, // Virtual PC - Enable Direct Execution -NN_vmcpuid, // Virtual PC - Virtualized CPU Information -NN_vmhlt, // Virtual PC - Halt -NN_vmsplaf, // Virtual PC - Spin Lock Acquisition Failed -NN_vmpushfd, // Virtual PC - Push virtualized flags register -NN_vmpopfd, // Virtual PC - Pop virtualized flags register -NN_vmcli, // Virtual PC - Clear Interrupt Flag -NN_vmsti, // Virtual PC - Set Interrupt Flag -NN_vmiretd, // Virtual PC - Return From Interrupt -NN_vmsgdt, // Virtual PC - Store Global Descriptor Table -NN_vmsidt, // Virtual PC - Store Interrupt Descriptor Table -NN_vmsldt, // Virtual PC - Store Local Descriptor Table -NN_vmstr, // Virtual PC - Store Task Register -NN_vmsdte, // Virtual PC - Store to Descriptor Table Entry -NN_vpcext, // Virtual PC - ISA extension - -// AMD FMA4 - -NN_vfmaddsubps, // Multiply with Alternating Add/Subtract of Packed Single-Precision Floating-Point -NN_vfmaddsubpd, // Multiply with Alternating Add/Subtract of Packed Double-Precision Floating-Point -NN_vfmsubaddps, // Multiply with Alternating Subtract/Add of Packed Single-Precision Floating-Point -NN_vfmsubaddpd, // Multiply with Alternating Subtract/Add of Packed Double-Precision Floating-Point -NN_vfmaddps, // Multiply and Add Packed Single-Precision Floating-Point -NN_vfmaddpd, // Multiply and Add Packed Double-Precision Floating-Point -NN_vfmaddss, // Multiply and Add Scalar Single-Precision Floating-Point -NN_vfmaddsd, // Multiply and Add Scalar Double-Precision Floating-Point -NN_vfmsubps, // Multiply and Subtract Packed Single-Precision Floating-Point -NN_vfmsubpd, // Multiply and Subtract Packed Double-Precision Floating-Point -NN_vfmsubss, // Multiply and Subtract Scalar Single-Precision Floating-Point -NN_vfmsubsd, // Multiply and Subtract Scalar Double-Precision Floating-Point -NN_vfnmaddps, // Negative Multiply and Add Packed Single-Precision Floating-Point -NN_vfnmaddpd, // Negative Multiply and Add Packed Double-Precision Floating-Point -NN_vfnmaddss, // Negative Multiply and Add Scalar Single-Precision Floating-Point -NN_vfnmaddsd, // Negative Multiply and Add Double Single-Precision Floating-Point -NN_vfnmsubps, // Negative Multiply and Subtract Packed Single-Precision Floating-Point -NN_vfnmsubpd, // Negative Multiply and Subtract Packed Double-Precision Floating-Point -NN_vfnmsubss, // Negative Multiply and Subtract Scalar Single-Precision Floating-Point -NN_vfnmsubsd, // Negative Multiply and Subtract Double Single-Precision Floating-Point - -// Intel Memory Protection Extensions (MPX) - -NN_bndmk, // Make Bounds -NN_bndcl, // Check Lower Bound -NN_bndcu, // Check Upper Bound -NN_bndcn, // Check Upper Bound -NN_bndmov, // Move Bounds -NN_bndldx, // Load Extended Bounds Using Address Translation -NN_bndstx, // Store Extended Bounds Using Address Translation - -// New xstate instructions - -NN_xrstors, // Restore Processor Extended States Supervisor -NN_xsavec, // Save Processor Extended States with Compaction -NN_xsaves, // Save Processor Extended States Supervisor - -// PREFETCHWT1 support - -NN_prefetchwt1, // Prefetch Vector Data Into Caches with Intent to Write and T1 Hint - -// Memory instructions - -NN_clflushopt, // Flush a Cache Line Optimized -NN_clwb, // Cache Line Write Back -NN_pcommit, // Persistent Commit (deprecated by Intel) - -// Protection Key Rights for User Pages - -NN_rdpkru, // Read Protection Key Rights for User Pages -NN_wrpkru, // Write Data to User Page Key Register - -// AVX comparison pseudo-ops - -NN_vcmpeqpd, // Compare Packed Double-Precision Floating-Point Values - Equal (ordered, non-signaling) -NN_vcmpltpd, // Compare Packed Double-Precision Floating-Point Values - Less-than (ordered, signaling) -NN_vcmplepd, // Compare Packed Double-Precision Floating-Point Values - Less-than-or-equal (ordered, signaling) -NN_vcmpunordpd, // Compare Packed Double-Precision Floating-Point Values - Unordered (non-signaling) -NN_vcmpneqpd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (unordered, non-signaling) -NN_vcmpnltpd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than (unordered, signaling) -NN_vcmpnlepd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, signaling) -NN_vcmpordpd, // Compare Packed Double-Precision Floating-Point Values - Ordered (non-signaling) -NN_vcmpeq_uqpd, // Compare Packed Double-Precision Floating-Point Values - Equal (unordered, non-signaling) -NN_vcmpngepd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, signaling) -NN_vcmpngtpd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than (unordered, signaling) -NN_vcmpfalsepd, // Compare Packed Double-Precision Floating-Point Values - False (ordered, non-signaling) -NN_vcmpneq_oqpd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (ordered, non-signaling) -NN_vcmpgepd, // Compare Packed Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, signaling) -NN_vcmpgtpd, // Compare Packed Double-Precision Floating-Point Values - Greater-than (ordered, signaling) -NN_vcmptruepd, // Compare Packed Double-Precision Floating-Point Values - True (unordered, non-signaling) -NN_vcmpeq_ospd, // Compare Packed Double-Precision Floating-Point Values - Equal (ordered, signaling) -NN_vcmplt_oqpd, // Compare Packed Double-Precision Floating-Point Values - Less-than (ordered, non-signaling) -NN_vcmple_oqpd, // Compare Packed Double-Precision Floating-Point Values - Less-than-or-equal (ordered, non-signaling) -NN_vcmpunord_spd, // Compare Packed Double-Precision Floating-Point Values - Unordered (signaling) -NN_vcmpneq_uspd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (unordered, signaling) -NN_vcmpnlt_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than (unordered, non-signaling) -NN_vcmpnle_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, non-signaling) -NN_vcmpord_spd, // Compare Packed Double-Precision Floating-Point Values - Ordered (signaling) -NN_vcmpeq_uspd, // Compare Packed Double-Precision Floating-Point Values - Equal (unordered, signaling) -NN_vcmpnge_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, non-signaling) -NN_vcmpngt_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than (unordered, non-signaling) -NN_vcmpfalse_ospd, // Compare Packed Double-Precision Floating-Point Values - False (ordered, signaling) -NN_vcmpneq_ospd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (ordered, signaling) -NN_vcmpge_oqpd, // Compare Packed Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, non-signaling) -NN_vcmpgt_oqpd, // Compare Packed Double-Precision Floating-Point Values - Greater-than (ordered, non-signaling) -NN_vcmptrue_uspd, // Compare Packed Double-Precision Floating-Point Values - True (unordered, signaling) - -NN_vcmpeqps, // Packed Single-FP Compare - Equal (ordered, non-signaling) -NN_vcmpltps, // Packed Single-FP Compare - Less-than (ordered, signaling) -NN_vcmpleps, // Packed Single-FP Compare - Less-than-or-equal (ordered, signaling) -NN_vcmpunordps, // Packed Single-FP Compare - Unordered (non-signaling) -NN_vcmpneqps, // Packed Single-FP Compare - Not-equal (unordered, non-signaling) -NN_vcmpnltps, // Packed Single-FP Compare - Not-less-than (unordered, signaling) -NN_vcmpnleps, // Packed Single-FP Compare - Not-less-than-or-equal (unordered, signaling) -NN_vcmpordps, // Packed Single-FP Compare - Ordered (non-signaling) -NN_vcmpeq_uqps, // Packed Single-FP Compare - Equal (unordered, non-signaling) -NN_vcmpngeps, // Packed Single-FP Compare - Not-greater-than-or-equal (unordered, signaling) -NN_vcmpngtps, // Packed Single-FP Compare - Not-greater-than (unordered, signaling) -NN_vcmpfalseps, // Packed Single-FP Compare - False (ordered, non-signaling) -NN_vcmpneq_oqps, // Packed Single-FP Compare - Not-equal (ordered, non-signaling) -NN_vcmpgeps, // Packed Single-FP Compare - Greater-than-or-equal (ordered, signaling) -NN_vcmpgtps, // Packed Single-FP Compare - Greater-than (ordered, signaling) -NN_vcmptrueps, // Packed Single-FP Compare - True (unordered, non-signaling) -NN_vcmpeq_osps, // Packed Single-FP Compare - Equal (ordered, signaling) -NN_vcmplt_oqps, // Packed Single-FP Compare - Less-than (ordered, non-signaling) -NN_vcmple_oqps, // Packed Single-FP Compare - Less-than-or-equal (ordered, non-signaling) -NN_vcmpunord_sps, // Packed Single-FP Compare - Unordered (signaling) -NN_vcmpneq_usps, // Packed Single-FP Compare - Not-equal (unordered, signaling) -NN_vcmpnlt_uqps, // Packed Single-FP Compare - Not-less-than (unordered, non-signaling) -NN_vcmpnle_uqps, // Packed Single-FP Compare - Not-less-than-or-equal (unordered, non-signaling) -NN_vcmpord_sps, // Packed Single-FP Compare - Ordered (signaling) -NN_vcmpeq_usps, // Packed Single-FP Compare - Equal (unordered, signaling) -NN_vcmpnge_uqps, // Packed Single-FP Compare - Not-greater-than-or-equal (unordered, non-signaling) -NN_vcmpngt_uqps, // Packed Single-FP Compare - Not-greater-than (unordered, non-signaling) -NN_vcmpfalse_osps, // Packed Single-FP Compare - False (ordered, signaling) -NN_vcmpneq_osps, // Packed Single-FP Compare - Not-equal (ordered, signaling) -NN_vcmpge_oqps, // Packed Single-FP Compare - Greater-than-or-equal (ordered, non-signaling) -NN_vcmpgt_oqps, // Packed Single-FP Compare - Greater-than (ordered, non-signaling) -NN_vcmptrue_usps, // Packed Single-FP Compare - True (unordered, signaling) - -NN_vcmpeqsd, // Compare Scalar Double-Precision Floating-Point Values - Equal (ordered, non-signaling) -NN_vcmpltsd, // Compare Scalar Double-Precision Floating-Point Values - Less-than (ordered, signaling) -NN_vcmplesd, // Compare Scalar Double-Precision Floating-Point Values - Less-than-or-equal (ordered, signaling) -NN_vcmpunordsd, // Compare Scalar Double-Precision Floating-Point Values - Unordered (non-signaling) -NN_vcmpneqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (unordered, non-signaling) -NN_vcmpnltsd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than (unordered, signaling) -NN_vcmpnlesd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, signaling) -NN_vcmpordsd, // Compare Scalar Double-Precision Floating-Point Values - Ordered (non-signaling) -NN_vcmpeq_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Equal (unordered, non-signaling) -NN_vcmpngesd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, signaling) -NN_vcmpngtsd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than (unordered, signaling) -NN_vcmpfalsesd, // Compare Scalar Double-Precision Floating-Point Values - False (ordered, non-signaling) -NN_vcmpneq_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (ordered, non-signaling) -NN_vcmpgesd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, signaling) -NN_vcmpgtsd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than (ordered, signaling) -NN_vcmptruesd, // Compare Scalar Double-Precision Floating-Point Values - True (unordered, non-signaling) -NN_vcmpeq_ossd, // Compare Scalar Double-Precision Floating-Point Values - Equal (ordered, signaling) -NN_vcmplt_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Less-than (ordered, non-signaling) -NN_vcmple_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Less-than-or-equal (ordered, non-signaling) -NN_vcmpunord_ssd, // Compare Scalar Double-Precision Floating-Point Values - Unordered (signaling) -NN_vcmpneq_ussd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (unordered, signaling) -NN_vcmpnlt_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than (unordered, non-signaling) -NN_vcmpnle_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, non-signaling) -NN_vcmpord_ssd, // Compare Scalar Double-Precision Floating-Point Values - Ordered (signaling) -NN_vcmpeq_ussd, // Compare Scalar Double-Precision Floating-Point Values - Equal (unordered, signaling) -NN_vcmpnge_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, non-signaling) -NN_vcmpngt_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than (unordered, non-signaling) -NN_vcmpfalse_ossd, // Compare Scalar Double-Precision Floating-Point Values - False (ordered, signaling) -NN_vcmpneq_ossd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (ordered, signaling) -NN_vcmpge_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, non-signaling) -NN_vcmpgt_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than (ordered, non-signaling) -NN_vcmptrue_ussd, // Compare Scalar Double-Precision Floating-Point Values - True (unordered, signaling) - -NN_vcmpeqss, // Scalar Single-FP Compare - Equal (ordered, non-signaling) -NN_vcmpltss, // Scalar Single-FP Compare - Less-than (ordered, signaling) -NN_vcmpless, // Scalar Single-FP Compare - Less-than-or-equal (ordered, signaling) -NN_vcmpunordss, // Scalar Single-FP Compare - Unordered (non-signaling) -NN_vcmpneqss, // Scalar Single-FP Compare - Not-equal (unordered, non-signaling) -NN_vcmpnltss, // Scalar Single-FP Compare - Not-less-than (unordered, signaling) -NN_vcmpnless, // Scalar Single-FP Compare - Not-less-than-or-equal (unordered, signaling) -NN_vcmpordss, // Scalar Single-FP Compare - Ordered (non-signaling) -NN_vcmpeq_uqss, // Scalar Single-FP Compare - Equal (unordered, non-signaling) -NN_vcmpngess, // Scalar Single-FP Compare - Not-greater-than-or-equal (unordered, signaling) -NN_vcmpngtss, // Scalar Single-FP Compare - Not-greater-than (unordered, signaling) -NN_vcmpfalsess, // Scalar Single-FP Compare - False (ordered, non-signaling) -NN_vcmpneq_oqss, // Scalar Single-FP Compare - Not-equal (ordered, non-signaling) -NN_vcmpgess, // Scalar Single-FP Compare - Greater-than-or-equal (ordered, signaling) -NN_vcmpgtss, // Scalar Single-FP Compare - Greater-than (ordered, signaling) -NN_vcmptruess, // Scalar Single-FP Compare - True (unordered, non-signaling) -NN_vcmpeq_osss, // Scalar Single-FP Compare - Equal (ordered, signaling) -NN_vcmplt_oqss, // Scalar Single-FP Compare - Less-than (ordered, non-signaling) -NN_vcmple_oqss, // Scalar Single-FP Compare - Less-than-or-equal (ordered, non-signaling) -NN_vcmpunord_sss, // Scalar Single-FP Compare - Unordered (signaling) -NN_vcmpneq_usss, // Scalar Single-FP Compare - Not-equal (unordered, signaling) -NN_vcmpnlt_uqss, // Scalar Single-FP Compare - Not-less-than (unordered, non-signaling) -NN_vcmpnle_uqss, // Scalar Single-FP Compare - Not-less-than-or-equal (unordered, non-signaling) -NN_vcmpord_sss, // Scalar Single-FP Compare - Ordered (signaling) -NN_vcmpeq_usss, // Scalar Single-FP Compare - Equal (unordered, signaling) -NN_vcmpnge_uqss, // Scalar Single-FP Compare - Not-greater-than-or-equal (unordered, non-signaling) -NN_vcmpngt_uqss, // Scalar Single-FP Compare - Not-greater-than (unordered, non-signaling) -NN_vcmpfalse_osss, // Scalar Single-FP Compare - False (ordered, signaling) -NN_vcmpneq_osss, // Scalar Single-FP Compare - Not-equal (ordered, signaling) -NN_vcmpge_oqss, // Scalar Single-FP Compare - Greater-than-or-equal (ordered, non-signaling) -NN_vcmpgt_oqss, // Scalar Single-FP Compare - Greater-than (ordered, non-signaling) -NN_vcmptrue_usss, // Scalar Single-FP Compare - True (unordered, signaling) - -// AVX-512 instructions - -NN_valignd, // Align Doubleword Vectors -NN_valignq, // Align Quadword Vectors -NN_vblendmpd, // Blend Float64 Vectors Using an OpMask Control -NN_vblendmps, // Blend Float32 Vectors Using an OpMask Control -NN_vpblendmb, // Blend Byte Vectors Using an Opmask Control -NN_vpblendmw, // Blend Word Vectors Using an Opmask Control -NN_vpblendmd, // Blend Int32 Vectors Using an OpMask Control -NN_vpblendmq, // Blend Int64 Vectors Using an OpMask Control -NN_vbroadcastf32x2, // Load with Broadcast Floating-Point Data -NN_vbroadcastf32x4, // Load with Broadcast Floating-Point Data -NN_vbroadcastf64x2, // Load with Broadcast Floating-Point Data -NN_vbroadcastf32x8, // Load with Broadcast Floating-Point Data -NN_vbroadcastf64x4, // Load with Broadcast Floating-Point Data -NN_vbroadcasti32x2, // Load Integer and Broadcast -NN_vbroadcasti32x4, // Load Integer and Broadcast -NN_vbroadcasti64x2, // Load Integer and Broadcast -NN_vbroadcasti32x8, // Load Integer and Broadcast -NN_vbroadcasti64x4, // Load Integer and Broadcast -NN_vcompresspd, // Store Sparse Packed Double-Precision Floating-Point Values into Dense Memory -NN_vcompressps, // Store Sparse Packed Single-Precision Floating-Point Values into Dense Memory -NN_vcvtpd2qq, // Convert Packed Double-Precision Floating-Point Values to Packed Quadword Integers -NN_vcvtpd2udq, // Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers -NN_vcvtpd2uqq, // Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers -NN_vcvtps2udq, // Convert Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values -NN_vcvtps2qq, // Convert Packed Single Precision Floating-Point Values to Packed Singed Quadword Integer Values -NN_vcvtps2uqq, // Convert Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values -NN_vcvtqq2pd, // Convert Packed Quadword Integers to Packed Double-Precision Floating-Point Values -NN_vcvtqq2ps, // Convert Packed Quadword Integers to Packed Single-Precision Floating-Point Values -NN_vcvtsd2usi, // Convert Scalar Double-Precision Floating-Point Value to Unsigned Doubleword Integer -NN_vcvtss2usi, // Convert Scalar Single-Precision Floating-Point Value to Unsigned Doubleword Integer -NN_vcvttpd2qq, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Quadword Integers -NN_vcvttpd2udq, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers -NN_vcvttpd2uqq, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers -NN_vcvttps2udq, // Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values -NN_vcvttps2qq, // Convert with Truncation Packed Single Precision Floating-Point Values to Packed Singed Quadword Integer Values -NN_vcvttps2uqq, // Convert with Truncation Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values -NN_vcvttsd2usi, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Unsigned Integer -NN_vcvttss2usi, // Convert with Truncation Scalar Single-Precision Floating-Point Value to Unsigned Integer -NN_vcvtudq2pd, // Convert Packed Unsigned Doubleword Integers to Packed Double-Precision Floating-Point Values -NN_vcvtudq2ps, // Convert Packed Unsigned Doubleword Integers to Packed Single-Precision Floating-Point Values -NN_vcvtuqq2pd, // Convert Packed Unsigned Quadword Integers to Packed Double-Precision Floating-Point Values -NN_vcvtuqq2ps, // Convert Packed Unsigned Quadword Integers to Packed Single-Precision Floating-Point Values -NN_vcvtusi2sd, // Convert Unsigned Integer to Scalar Double-Precision Floating-Point Value -NN_vcvtusi2ss, // Convert Unsigned Integer to Scalar Single-Precision Floating-Point Value -NN_vdbpsadbw, // Double Block Packed Sum-Absolute-Differences (SAD) on Unsigned Bytes -NN_vexpandpd, // Load Sparse Packed Double-Precision Floating-Point Values from Dense Memory -NN_vexpandps, // Load Sparse Packed Single-Precision Floating-Point Values from Dense Memory -NN_vextractf32x4, // Extract Packed Floating-Point Values -NN_vextractf64x2, // Extract Packed Floating-Point Values -NN_vextractf32x8, // Extract Packed Floating-Point Values -NN_vextractf64x4, // Extract Packed Floating-Point Values -NN_vextracti32x4, // Extract packed Integer Values -NN_vextracti64x2, // Extract packed Integer Values -NN_vextracti32x8, // Extract packed Integer Values -NN_vextracti64x4, // Extract packed Integer Values -NN_vfixupimmpd, // Fix Up Special Packed Float64 Values -NN_vfixupimmps, // Fix Up Special Packed Float32 Values -NN_vfixupimmsd, // Fix Up Special Scalar Float64 Value -NN_vfixupimmss, // Fix Up Special Scalar Float32 Value -NN_vfpclasspd, // Tests Types Of a Packed Float64 Values -NN_vfpclassps, // Tests Types Of a Packed Float32 Values -NN_vfpclasssd, // Tests Types Of a Scalar Float64 Values -NN_vfpclassss, // Tests Types Of a Scalar Float32 Values -NN_vgetexppd, // Convert Exponents of Packed DP FP Values to DP FP Values -NN_vgetexpps, // Convert Exponents of Packed SP FP Values to SP FP Values -NN_vgetexpsd, // Convert Exponents of Scalar DP FP Values to DP FP Value -NN_vgetexpss, // Convert Exponents of Scalar SP FP Values to SP FP Value -NN_vgetmantpd, // Extract Float64 Vector of Normalized Mantissas from Float64 Vector -NN_vgetmantps, // Extract Float32 Vector of Normalized Mantissas from Float32 Vector -NN_vgetmantsd, // Extract Float64 of Normalized Mantissas from Float64 Scalar -NN_vgetmantss, // Extract Float32 Vector of Normalized Mantissa from Float32 Vector -NN_vinsertf32x4, // Insert Packed Floating-Point Values -NN_vinsertf64x2, // Insert Packed Floating-Point Values -NN_vinsertf32x8, // Insert Packed Floating-Point Values -NN_vinsertf64x4, // Insert Packed Floating-Point Values -NN_vinserti32x4, // Insert Packed Integer Values -NN_vinserti64x2, // Insert Packed Integer Values -NN_vinserti32x8, // Insert Packed Integer Values -NN_vinserti64x4, // Insert Packed Integer Values -NN_vmovdqa32, // Move Aligned Packed Integer Values -NN_vmovdqa64, // Move Aligned Packed Integer Values -NN_vmovdqu8, // Move Unaligned Packed Integer Values -NN_vmovdqu16, // Move Unaligned Packed Integer Values -NN_vmovdqu32, // Move Unaligned Packed Integer Values -NN_vmovdqu64, // Move Unaligned Packed Integer Values -NN_vpabsq, // Packed Absolute Value -NN_vpandd, // Logical AND -NN_vpandq, // Logical AND -NN_vpandnd, // Logical AND NOT -NN_vpandnq, // Logical AND NOT -NN_vpbroadcastmb2q, // Broadcast Mask to Vector Register -NN_vpbroadcastmw2d, // Broadcast Mask to Vector Register -NN_vpcmpb, // Compare Packed Byte Values Into Mask -NN_vpcmpub, // Compare Packed Byte Values Into Mask -NN_vpcmpd, // Compare Packed Integer Values into Mask -NN_vpcmpud, // Compare Packed Integer Values into Mask -NN_vpcmpq, // Compare Packed Integer Values into Mask -NN_vpcmpuq, // Compare Packed Integer Values into Mask -NN_vpcmpw, // Compare Packed Word Values Into Mask -NN_vpcmpuw, // Compare Packed Word Values Into Mask -NN_vpcompressd, // Store Sparse Packed Doubleword Integer Values into Dense Memory/Register -NN_vpcompressq, // Store Sparse Packed Quadword Integer Values into Dense Memory/Register -NN_vpconflictd, // Detect Conflicts Within a Vector of Packed Dword Values into Dense Memory/Register -NN_vpconflictq, // Detect Conflicts Within a Vector of Packed Qword Values into Dense Memory/Register -NN_vpermb, // Permute Packed Bytes Elements -NN_vpermw, // Permute Packed Words Elements -NN_vpermi2b, // Full Permute of Bytes From Two Tables Overwriting the Index -NN_vpermi2w, // Full Permute From Two Tables Overwriting the Index -NN_vpermi2d, // Full Permute From Two Tables Overwriting the Index -NN_vpermi2q, // Full Permute From Two Tables Overwriting the Index -NN_vpermi2ps, // Full Permute From Two Tables Overwriting the Index -NN_vpermi2pd, // Full Permute From Two Tables Overwriting the Index -NN_vpermt2b, // Full Permute of Bytes From Two Tables Overwriting a Table -NN_vpermt2w, // Full Permute from Two Tables Overwriting one Table -NN_vpermt2d, // Full Permute from Two Tables Overwriting one Table -NN_vpermt2q, // Full Permute from Two Tables Overwriting one Table -NN_vpermt2ps, // Full Permute from Two Tables Overwriting one Table -NN_vpermt2pd, // Full Permute from Two Tables Overwriting one Table -NN_vpexpandd, // Load Sparse Packed Doubleword Integer Values from Dense Memory/Register -NN_vpexpandq, // Load Sparse Packed Quadword Integer Values from Dense Memory/Register -NN_vplzcntd, // Count the Number of Leading Zero Bits for Packed Dword Values -NN_vplzcntq, // Count the Number of Leading Zero Bits for Packed Qword Values -NN_vpmadd52luq, // Packed Multiply of Unsigned 52-bit Integers and Add the Low 52-bit Products to Qword Accumulators -NN_vpmadd52huq, // Packed Multiply of Unsigned 52-bit Unsigned Integers and Add High 52-bit Products to 64-bit Accumulators -NN_vpmaxsq, // Maximum of Packed Signed Integers -NN_vpmaxuq, // Maximum of Packed Unsigned Integers -NN_vpminsq, // Minimum of Packed Signed Integers -NN_vpminuq, // Minimum of Packed Unsigned Integers -NN_vpmovm2b, // Convert a Mask Register to a Vector Register -NN_vpmovm2w, // Convert a Mask Register to a Vector Register -NN_vpmovm2d, // Convert a Mask Register to a Vector Register -NN_vpmovm2q, // Convert a Mask Register to a Vector Register -NN_vpmovb2m, // Convert a Vector Register to a Mask -NN_vpmovw2m, // Convert a Vector Register to a Mask -NN_vpmovd2m, // Convert a Vector Register to a Mask -NN_vpmovq2m, // Convert a Vector Register to a Mask -NN_vpmovqb, // Down Convert QWord to Byte -NN_vpmovsqb, // Down Convert QWord to Byte -NN_vpmovusqb, // Down Convert QWord to Byte -NN_vpmovqw, // Down Convert QWord to Word -NN_vpmovsqw, // Down Convert QWord to Word -NN_vpmovusqw, // Down Convert QWord to Word -NN_vpmovqd, // Down Convert QWord to DWord -NN_vpmovsqd, // Down Convert QWord to DWord -NN_vpmovusqd, // Down Convert QWord to DWord -NN_vpmovdb, // Down Convert DWord to Byte -NN_vpmovsdb, // Down Convert DWord to Byte -NN_vpmovusdb, // Down Convert DWord to Byte -NN_vpmovdw, // Down Convert DWord to Word -NN_vpmovsdw, // Down Convert DWord to Word -NN_vpmovusdw, // Down Convert DWord to Word -NN_vpmovwb, // Down Convert Word to Byte -NN_vpmovswb, // Down Convert Word to Byte -NN_vpmovuswb, // Down Convert Word to Byte -NN_vpmullq, // Multiply Packed Integers and Store Low Result -NN_vpmultishiftqb, // Select Packed Unaligned Bytes from Quadword Sources -NN_vpord, // Bitwise Logical Or -NN_vporq, // Bitwise Logical Or -NN_vprold, // Bit Rotate Left -NN_vprolvd, // Bit Rotate Left -NN_vprolq, // Bit Rotate Left -NN_vprolvq, // Bit Rotate Left -NN_vprord, // Bit Rotate Right -NN_vprorvd, // Bit Rotate Right -NN_vprorq, // Bit Rotate Right -NN_vprorvq, // Bit Rotate Right -NN_vpscatterdd, // Scatter Packed Dword with Signed Dword -NN_vpscatterdq, // Scatter Packed Qword with Signed Qword Indices -NN_vpscatterqd, // Scatter Packed Dword with Signed Dword -NN_vpscatterqq, // Scatter Packed Qword with Signed Qword Indices -NN_vpsraq, // Bit Shift Arithmetic Right -NN_vpsllvw, // Variable Bit Shift Left Logical -NN_vpsrlvw, // Variable Bit Shift Right Logical -NN_vptestnmb, // Logical NAND and Set -NN_vptestnmw, // Logical NAND and Set -NN_vptestnmd, // Logical NAND and Set -NN_vptestnmq, // Logical NAND and Set -NN_vshuff32x4, // Shuffle Packed Values at 128-bit Granularity -NN_vshuff64x2, // Shuffle Packed Values at 128-bit Granularity -NN_vshufi32x4, // Shuffle Packed Values at 128-bit Granularity -NN_vshufi64x2, // Shuffle Packed Values at 128-bit Granularity -NN_vpternlogd, // Bitwise Ternary Logic -NN_vpternlogq, // Bitwise Ternary Logic -NN_vptestmb, // Logical AND and Set Mask -NN_vptestmw, // Logical AND and Set Mask -NN_vptestmd, // Logical AND and Set Mask -NN_vptestmq, // Logical AND and Set Mask -NN_vpsravw, // Variable Bit Shift Right Arithmetic -NN_vpsravq, // Variable Bit Shift Right Arithmetic -NN_vpxord, // Exclusive Or -NN_vpxorq, // Exclusive Or -NN_vrangepd, // Range Restriction Calculation For Packed Pairs of Float64 Values -NN_vrangeps, // Range Restriction Calculation For Packed Pairs of Float32 Values -NN_vrangesd, // Range Restriction Calculation From a pair of Scalar Float64 Values -NN_vrangess, // Range Restriction Calculation From a Pair of Scalar Float32 Values -NN_vrcp14pd, // Compute Approximate Reciprocals of Packed Float64 Values -NN_vrcp14sd, // Compute Approximate Reciprocal of Scalar Float64 Value -NN_vrcp14ps, // Compute Approximate Reciprocals of Packed Float32 Values -NN_vrcp14ss, // Compute Approximate Reciprocal of Scalar Float32 Value -NN_vreducepd, // Perform Reduction Transformation on Packed Float64 Values -NN_vreducesd, // Perform a Reduction Transformation on a Scalar Float64 Value -NN_vreduceps, // Perform Reduction Transformation on Packed Float32 Values -NN_vreducess, // Perform a Reduction Transformation on a Scalar Float32 Value -NN_vrndscalepd, // Round Packed Float64 Values To Include A Given Number Of Fraction Bits -NN_vrndscalesd, // Round Scalar Float64 Value To Include A Given Number Of Fraction Bits -NN_vrndscaleps, // Round Packed Float32 Values To Include A Given Number Of Fraction Bits -NN_vrndscaless, // Round Scalar Float32 Value To Include A Given Number Of Fraction Bits -NN_vrsqrt14pd, // Compute Approximate Reciprocals of Square Roots of Packed Float64 Values -NN_vrsqrt14sd, // Compute Approximate Reciprocal of Square Root of Scalar Float64 Value -NN_vrsqrt14ps, // Compute Approximate Reciprocals of Square Roots of Packed Float32 Values -NN_vrsqrt14ss, // Compute Approximate Reciprocal of Square Root of Scalar Float32 Value -NN_vscalefpd, // Scale Packed Float64 Values With Float64 Values -NN_vscalefsd, // Scale Scalar Float64 Values With Float64 Values -NN_vscalefps, // Scale Packed Float32 Values With Float32 Values -NN_vscalefss, // Scale Scalar Float32 Value With Float32 Value -NN_vscatterdps, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices -NN_vscatterdpd, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices -NN_vscatterqps, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices -NN_vscatterqpd, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices - -NN_vexp2pd, // Approximation to the Exponential 2^x of Packed Double-Precision Floating-Point Values with Less Than 2^-23 Relative Error -NN_vexp2ps, // Approximation to the Exponential 2^x of Packed Single-Precision Floating-Point Values with Less Than 2^-23 Relative Error -NN_vrcp28pd, // Approximation to the Reciprocal of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error -NN_vrcp28sd, // Approximation to the Reciprocal of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error -NN_vrcp28ps, // Approximation to the Reciprocal of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error -NN_vrcp28ss, // Approximation to the Reciprocal of Scalar Single-Precision Floating-Point Value with Less Than 2^-28 Relative Error -NN_vrsqrt28pd, // Approximation to the Reciprocal Square Root of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error -NN_vrsqrt28sd, // Approximation to the Reciprocal Square Root of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error -NN_vrsqrt28ps, // Approximation to the Reciprocal Square Root of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error -NN_vrsqrt28ss, // Approximation to the Reciprocal Square Root of Scalar Single-Precision Floating-Point Value with Less Than 2^-28 Relative Error - -NN_vgatherpf0dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint -NN_vgatherpf0qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint -NN_vgatherpf0dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint -NN_vgatherpf0qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint -NN_vgatherpf1dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint -NN_vgatherpf1qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint -NN_vgatherpf1dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint -NN_vgatherpf1qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint -NN_vscatterpf0dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write -NN_vscatterpf0qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write -NN_vscatterpf0dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write -NN_vscatterpf0qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write -NN_vscatterpf1dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write -NN_vscatterpf1qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write -NN_vscatterpf1dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write -NN_vscatterpf1qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write - -// AVX-512 comparison pseudo-ops - -NN_vpcmpltd, // Compare Packed Integer Values into Mask -NN_vpcmpled, // Compare Packed Integer Values into Mask -NN_vpcmpneqd, // Compare Packed Integer Values into Mask -NN_vpcmpnltd, // Compare Packed Integer Values into Mask -NN_vpcmpnled, // Compare Packed Integer Values into Mask - -NN_vpcmpequd, // Compare Packed Integer Values into Mask -NN_vpcmpltud, // Compare Packed Integer Values into Mask -NN_vpcmpleud, // Compare Packed Integer Values into Mask -NN_vpcmpnequd, // Compare Packed Integer Values into Mask -NN_vpcmpnltud, // Compare Packed Integer Values into Mask -NN_vpcmpnleud, // Compare Packed Integer Values into Mask - -NN_vpcmpltq, // Compare Packed Integer Values into Mask -NN_vpcmpleq, // Compare Packed Integer Values into Mask -NN_vpcmpneqq, // Compare Packed Integer Values into Mask -NN_vpcmpnltq, // Compare Packed Integer Values into Mask -NN_vpcmpnleq, // Compare Packed Integer Values into Mask - -NN_vpcmpequq, // Compare Packed Integer Values into Mask -NN_vpcmpltuq, // Compare Packed Integer Values into Mask -NN_vpcmpleuq, // Compare Packed Integer Values into Mask -NN_vpcmpnequq, // Compare Packed Integer Values into Mask -NN_vpcmpnltuq, // Compare Packed Integer Values into Mask -NN_vpcmpnleuq, // Compare Packed Integer Values into Mask - -// Opmask instructions - -NN_kaddw, // ADD Two Masks -NN_kaddb, // ADD Two Masks -NN_kaddq, // ADD Two Masks -NN_kaddd, // ADD Two Masks -NN_kandw, // Bitwise Logical AND Masks -NN_kandb, // Bitwise Logical AND Masks -NN_kandq, // Bitwise Logical AND Masks -NN_kandd, // Bitwise Logical AND Masks -NN_kandnw, // Bitwise Logical AND NOT Masks -NN_kandnb, // Bitwise Logical AND NOT Masks -NN_kandnq, // Bitwise Logical AND NOT Masks -NN_kandnd, // Bitwise Logical AND NOT Masks -NN_kmovw, // Move from and to Mask Registers -NN_kmovb, // Move from and to Mask Registers -NN_kmovq, // Move from and to Mask Registers -NN_kmovd, // Move from and to Mask Registers -NN_kunpckbw, // Unpack for Mask Registers -NN_kunpckwd, // Unpack for Mask Registers -NN_kunpckdq, // Unpack for Mask Registers -NN_knotw, // NOT Mask Register -NN_knotb, // NOT Mask Register -NN_knotq, // NOT Mask Register -NN_knotd, // NOT Mask Register -NN_korw, // Bitwise Logical OR Masks -NN_korb, // Bitwise Logical OR Masks -NN_korq, // Bitwise Logical OR Masks -NN_kord, // Bitwise Logical OR Masks -NN_kortestw, // OR Masks And Set Flags -NN_kortestb, // OR Masks And Set Flags -NN_kortestq, // OR Masks And Set Flags -NN_kortestd, // OR Masks And Set Flags -NN_kshiftlw, // Shift Left Mask Registers -NN_kshiftlb, // Shift Left Mask Registers -NN_kshiftlq, // Shift Left Mask Registers -NN_kshiftld, // Shift Left Mask Registers -NN_kshiftrw, // Shift Right Mask Registers -NN_kshiftrb, // Shift Right Mask Registers -NN_kshiftrq, // Shift Right Mask Registers -NN_kshiftrd, // Shift Right Mask Registers -NN_kxnorw, // Bitwise Logical XNOR Masks -NN_kxnorb, // Bitwise Logical XNOR Masks -NN_kxnorq, // Bitwise Logical XNOR Masks -NN_kxnord, // Bitwise Logical XNOR Masks -NN_ktestw, // Packed Bit Test Masks and Set Flags -NN_ktestb, // Packed Bit Test Masks and Set Flags -NN_ktestq, // Packed Bit Test Masks and Set Flags -NN_ktestd, // Packed Bit Test Masks and Set Flags -NN_kxorw, // Bitwise Logical XOR Masks -NN_kxorb, // Bitwise Logical XOR Masks -NN_kxorq, // Bitwise Logical XOR Masks -NN_kxord, // Bitwise Logical XOR Masks - -// SHA Extensions - -NN_sha1rnds4, // Perform Four Rounds of SHA1 Operation -NN_sha1nexte, // Calculate SHA1 State Variable E after Four Rounds -NN_sha1msg1, // Perform an Intermediate Calculation for the Next Four SHA1 Message Dwords -NN_sha1msg2, // Perform a Final Calculation for the Next Four SHA1 Message Dwords -NN_sha256rnds2, // Perform Two Rounds of SHA256 Operation -NN_sha256msg1, // Perform an Intermediate Calculation for the Next Four SHA256 Message Dwords -NN_sha256msg2, // Perform a Final Calculation for the Next Four SHA256 Message Dwords - -// Intel Software Guard Extensions - -NN_encls, // Execute an Enclave System Function of Specified Leaf Number -NN_enclu, // Execute an Enclave User Function of Specified Leaf Number - -// AMD XOP - -NN_vfrczpd, // Extract Fraction Packed Double-Precision Floating-Point -NN_vfrczps, // Extract Fraction Packed Single-Precision Floating-Point -NN_vfrczsd, // Extract Fraction Scalar Double-Precision Floating-Point -NN_vfrczss, // Extract Fraction Scalar Single-Precision Floating Point -NN_vpcmov, // Vector Conditional Moves -NN_vpcomb, // Compare Vector Signed Bytes -NN_vpcomd, // Compare Vector Signed Doublewords -NN_vpcomq, // Compare Vector Signed Quadwords -NN_vpcomub, // Compare Vector Unsigned Bytes -NN_vpcomud, // Compare Vector Unsigned Doublewords -NN_vpcomuq, // Compare Vector Unsigned Quadwords -NN_vpcomuw, // Compare Vector Unsigned Words -NN_vpcomw, // Compare Vector Signed Words -NN_vpermil2pd, // Permute Two-Source Double-Precision Floating-Point Values -NN_vpermil2ps, // Permute Two-Source Single-Precision Floating-Point Values -NN_vphaddbd, // Packed Horizontal Add Signed Byte to Signed Doubleword -NN_vphaddbq, // Packed Horizontal Add Signed Byte to Signed Quadword -NN_vphaddbw, // Packed Horizontal Add Signed Byte to Signed Word -NN_vphadddq, // Packed Horizontal Add Signed Doubleword to Signed Quadword -NN_vphaddubd, // Packed Horizontal Add Unsigned Byte to Doubleword -NN_vphaddubq, // Packed Horizontal Add Unsigned Byte to Quadword -NN_vphaddubw, // Packed Horizontal Add Unsigned Byte to Word -NN_vphaddudq, // Packed Horizontal Add Unsigned Doubleword to Quadword -NN_vphadduwd, // Packed Horizontal Add Unsigned Word to Doubleword -NN_vphadduwq, // Packed Horizontal Add Unsigned Word to Quadword -NN_vphaddwd, // Packed Horizontal Add Signed Word to Signed Doubleword -NN_vphaddwq, // Packed Horizontal Add Signed Word to Signed Quadword -NN_vphsubbw, // Packed Horizontal Subtract Signed Byte to Signed Word -NN_vphsubdq, // Packed Horizontal Subtract Signed Doubleword to Signed Quadword -NN_vphsubwd, // Packed Horizontal Subtract Signed Word to Signed Doubleword -NN_vpmacsdd, // Packed Multiply Accumulate Signed Doubleword to Signed Doubleword -NN_vpmacsdqh, // Packed Multiply Accumulate Signed High Doubleword to Signed Quadword -NN_vpmacsdql, // Packed Multiply Accumulate Signed Low Doubleword to Signed Quadword -NN_vpmacssdd, // Packed Multiply Accumulate Signed Doubleword to Signed Doubleword with Saturation -NN_vpmacssdqh, // Packed Multiply Accumulate Signed High Doubleword to Signed Quadword with Saturation -NN_vpmacssdql, // Packed Multiply Accumulate Signed Low Doubleword to Signed Quadword with Saturation -NN_vpmacsswd, // Packed Multiply Accumulate Signed Word to Signed Doubleword with Saturation -NN_vpmacssww, // Packed Multiply Accumulate Signed Word to Signed Word with Saturation -NN_vpmacswd, // Packed Multiply Accumulate Signed Word to Signed Doubleword -NN_vpmacsww, // Packed Multiply Accumulate Signed Word to Signed Word -NN_vpmadcsswd, // Packed Multiply, Add and Accumulate Signed Word to Signed Doubleword with Saturation -NN_vpmadcswd, // Packed Multiply Add and Accumulate Signed Word to Signed Doubleword -NN_vpperm, // Packed Permute Bytes -NN_vprotb, // Packed Rotate Bytes -NN_vprotd, // Packed Rotate Doublewords -NN_vprotq, // Packed Rotate Quadwords -NN_vprotw, // Packed Rotate Words -NN_vpshab, // Packed Shift Arithmetic Bytes -NN_vpshad, // Packed Shift Arithmetic Doublewords -NN_vpshaq, // Packed Shift Arithmetic Quadwords -NN_vpshaw, // Packed Shift Arithmetic Words -NN_vpshlb, // Packed Shift Logical Bytes -NN_vpshld, // Packed Shift Logical Doublewords -NN_vpshlq, // Packed Shift Logical Quadwords -NN_vpshlw, // Packed Shift Logical Words - -// AMD XOP comparison pseudo-ops - -NN_vpcomltb, // Compare Vector Signed Bytes -NN_vpcomleb, // Compare Vector Signed Bytes -NN_vpcomgtb, // Compare Vector Signed Bytes -NN_vpcomgeb, // Compare Vector Signed Bytes -NN_vpcomeqb, // Compare Vector Signed Bytes -NN_vpcomneqb, // Compare Vector Signed Bytes -NN_vpcomfalseb, // Compare Vector Signed Bytes -NN_vpcomtrueb, // Compare Vector Signed Bytes - -NN_vpcomltw, // Compare Vector Signed Words -NN_vpcomlew, // Compare Vector Signed Words -NN_vpcomgtw, // Compare Vector Signed Words -NN_vpcomgew, // Compare Vector Signed Words -NN_vpcomeqw, // Compare Vector Signed Words -NN_vpcomneqw, // Compare Vector Signed Words -NN_vpcomfalsew, // Compare Vector Signed Words -NN_vpcomtruew, // Compare Vector Signed Words - -NN_vpcomltd, // Compare Vector Signed Doublewords -NN_vpcomled, // Compare Vector Signed Doublewords -NN_vpcomgtd, // Compare Vector Signed Doublewords -NN_vpcomged, // Compare Vector Signed Doublewords -NN_vpcomeqd, // Compare Vector Signed Doublewords -NN_vpcomneqd, // Compare Vector Signed Doublewords -NN_vpcomfalsed, // Compare Vector Signed Doublewords -NN_vpcomtrued, // Compare Vector Signed Doublewords - -NN_vpcomltq, // Compare Vector Signed Quadwords -NN_vpcomleq, // Compare Vector Signed Quadwords -NN_vpcomgtq, // Compare Vector Signed Quadwords -NN_vpcomgeq, // Compare Vector Signed Quadwords -NN_vpcomeqq, // Compare Vector Signed Quadwords -NN_vpcomneqq, // Compare Vector Signed Quadwords -NN_vpcomfalseq, // Compare Vector Signed Quadwords -NN_vpcomtrueq, // Compare Vector Signed Quadwords - -NN_vpcomltub, // Compare Vector Unsigned Bytes -NN_vpcomleub, // Compare Vector Unsigned Bytes -NN_vpcomgtub, // Compare Vector Unsigned Bytes -NN_vpcomgeub, // Compare Vector Unsigned Bytes -NN_vpcomequb, // Compare Vector Unsigned Bytes -NN_vpcomnequb, // Compare Vector Unsigned Bytes -NN_vpcomfalseub, // Compare Vector Unsigned Bytes -NN_vpcomtrueub, // Compare Vector Unsigned Bytes - -NN_vpcomltuw, // Compare Vector Unsigned Words -NN_vpcomleuw, // Compare Vector Unsigned Words -NN_vpcomgtuw, // Compare Vector Unsigned Words -NN_vpcomgeuw, // Compare Vector Unsigned Words -NN_vpcomequw, // Compare Vector Unsigned Words -NN_vpcomnequw, // Compare Vector Unsigned Words -NN_vpcomfalseuw, // Compare Vector Unsigned Words -NN_vpcomtrueuw, // Compare Vector Unsigned Words - -NN_vpcomltud, // Compare Vector Unsigned Doublewords -NN_vpcomleud, // Compare Vector Unsigned Doublewords -NN_vpcomgtud, // Compare Vector Unsigned Doublewords -NN_vpcomgeud, // Compare Vector Unsigned Doublewords -NN_vpcomequd, // Compare Vector Unsigned Doublewords -NN_vpcomnequd, // Compare Vector Unsigned Doublewords -NN_vpcomfalseud, // Compare Vector Unsigned Doublewords -NN_vpcomtrueud, // Compare Vector Unsigned Doublewords - -NN_vpcomltuq, // Compare Vector Unsigned Quadwords -NN_vpcomleuq, // Compare Vector Unsigned Quadwords -NN_vpcomgtuq, // Compare Vector Unsigned Quadwords -NN_vpcomgeuq, // Compare Vector Unsigned Quadwords -NN_vpcomequq, // Compare Vector Unsigned Quadwords -NN_vpcomnequq, // Compare Vector Unsigned Quadwords -NN_vpcomfalseuq, // Compare Vector Unsigned Quadwords -NN_vpcomtrueuq, // Compare Vector Unsigned Quadwords - -// AMD Excavator - -NN_monitorx, // Setup Monitor Address -NN_mwaitx, // Monitor Wait with Timeout - -// AMD Zen - -NN_clzero, // Zero out 64 byte cache - -// Intel Processor Trace - -NN_ptwrite, // Write Data to a Processor Trace Packet - -// new Intel AVX-512 instructions (December 2016) - -NN_v4fmaddps, // Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations) -NN_v4fnmaddps, // Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations) -NN_v4fmaddss, // Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations) -NN_v4fnmaddss, // Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations) -NN_vp4dpwssd, // Dot Product of Signed Words with Dword Accumulation (4-iterations) -NN_vp4dpwssds, // Dot Product of Signed Words with Dword Accumulation and Saturation (4-iterations) -NN_vpopcntd, // Return the Count of Number of Bits Set to 1 in DWORD -NN_vpopcntq, // Return the Count of Number of Bits Set to 1 in QWORD - -// Read Processor ID - -NN_rdpid, // Read Processor ID - -// Invoke VM function - -NN_vmfunc, // Invoke VM function - -// Control-flow Enforcement - -NN_incsspd, // Increment Shadow Stack Pointer (by 4) -NN_incsspq, // Increment Shadow Stack Pointer (by 8) -NN_rdsspd, // Read (low 32 bits of) Shadow Stack Pointer -NN_rdsspq, // Read Shadow Stack Pointer -NN_saveprevssp, // Save Previous Shadow Stack Pointer -NN_rstorssp, // Restore saved Shadow Stack Pointer -NN_wrssd, // Write (4 bytes) to shadow stack -NN_wrssq, // Write (8 bytes) to shadow stack -NN_wrussd, // Write (4 bytes) to User Shadow Stack -NN_wrussq, // Write (8 bytes) to User Shadow Stack -NN_setssbsy, // Mark Shadow Stack Busy -NN_clrssbsy, // Clear Shadow Stack Busy Flag -NN_endbr64, // Terminate an Indirect Branch in 64-bit Mode -NN_endbr32, // Terminate an Indirect Branch in 32-bit and Compatibility Mode - -// Undefined Instruction - -NN_ud0, // Undefined Instruction -NN_ud1, // Undefined Instruction - -// Enqueue Stores - -NN_enqcmd, // Enqueue Command -NN_enqcmds, // Enqueue Command Supervisor - -// AMD Zen2 - -NN_mcommit, // Commit Stores to Memory -NN_rdpru, // Read Processor Register - -// Intel Tremont instructions - -NN_cldemote, // Cache Line Demote -NN_enclv, // Execute an Enclave VMM Function of Specified Leaf Number - -// Direct Stores - -NN_movdiri, // Move Doubleword as Direct Store -NN_movdir64b, // Move 64 Bytes as Direct Store - -// Intel WAITPKG instructions - -NN_tpause, // Timed PAUSE -NN_umonitor, // User Level Set Up Monitor Address -NN_umwait, // User Level Monitor Wait - -// Intel Sapphire Rapids instructions - -NN_serialize, // Serialize Instruction Execution - -// Intel TSX - -NN_xresldtrk, // Resume Tracking Load Addresses -NN_xsusldtrk, // Suspend Tracking Load Addresses - -NN_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -I5_null = 0, // Unknown Operation - -// -// Intel 8080-8085 instructions -// - -I5_aci, -I5_adc, Z80_adc = I5_adc, -I5_add, Z80_add = I5_add, -I5_adi, -I5_ana, -I5_ani, -I5_call, -I5_cnz, -I5_cz, -I5_cnc, -I5_cc, -I5_cpo, -I5_cpe, -I5_cp, -I5_cm, -I5_cmc, -I5_cmp, -I5_cpi, -I5_cma, -I5_daa, -I5_dad, -I5_dcr, -I5_dcx, -I5_di, Z80_di = I5_di, -I5_ei, Z80_ei = I5_ei, -I5_halt, -I5_in, Z80_in = I5_in, -I5_inr, -I5_inx, -I5_jmp, -I5_jnz, -I5_jz, -I5_jnc, -I5_jc, -I5_jpo, -I5_jpe, -I5_jp, -I5_jm, -I5_lda, -I5_ldax, -I5_lhld, -I5_lxi, -I5_mov, -I5_mvi, -I5_nop, -I5_ora, -I5_ori, -I5_out, Z80_out = I5_out, -I5_pchl, -I5_pop, Z80_pop = I5_pop, -I5_push, Z80_push = I5_push, -I5_ret, -I5_rnz, -I5_rz, -I5_rnc, -I5_rc, -I5_rpo, -I5_rpe, -I5_rp, -I5_rm, -I5_ral, -I5_rlc, -I5_rar, -I5_rrc, -I5_rst, -I5_sbb, -I5_sbi, -I5_stc, -I5_sphl, -I5_sta, -I5_stax, -I5_shld, -I5_sui, -I5_sub, Z80_sub = I5_sub, -I5_xra, -I5_xri, -I5_xchg, -I5_xthl, - -I5_rim, -I5_sim, - -// -// Z80 extensions -// - -Z80_and, -Z80_bit, -Z80_call, -Z80_ccf, -Z80_cp, -Z80_cpd, -Z80_cpdr, -Z80_cpi, -Z80_cpir, -Z80_cpl, -Z80_dec, -Z80_djnz, -Z80_ex, -Z80_exx, -Z80_halt, -Z80_im, -Z80_inc, -Z80_ind, -Z80_indr, -Z80_ini, -Z80_inir, -Z80_jp, -Z80_jr, -Z80_ld, -Z80_ldd, -Z80_lddr, -Z80_ldi, -Z80_ldir, -Z80_neg, -Z80_or, -Z80_otdr, -Z80_otir, -Z80_outd, -Z80_outi, -Z80_res, -Z80_ret, -Z80_reti, -Z80_retn, -Z80_rl, -Z80_rla, -Z80_rlc, -Z80_rlca, -Z80_rld, -Z80_rr, -Z80_rra, -Z80_rrc, -Z80_rrca, -Z80_rrd, -Z80_scf, -Z80_sbc, -Z80_set, -Z80_sla, -Z80_sra, -Z80_srl, -Z80_xor, -Z80_inp, // undocumented -Z80_outp, // undocumented -Z80_srr, // undocumented - -// -// HD64180 extensions -// - -HD_in0, Z80_in0 = HD_in0, -HD_mlt, Z80_mlt = HD_mlt, -HD_otim, Z80_otim = HD_otim, -HD_otimr, Z80_otimr = HD_otimr, -HD_otdm, Z80_otdm = HD_otdm, -HD_otdmr, Z80_otdmr = HD_otdmr, -HD_out0, Z80_out0 = HD_out0, -HD_slp, Z80_slp = HD_slp, -HD_tst, Z80_tst = HD_tst, -HD_tstio, Z80_tstio = HD_tstio, - -// -// A80 special instructions -// - -A80_lbcd, -A80_lded, -A80_lspd, -A80_lixd, -A80_liyd, -A80_sbcd, -A80_sded, -A80_sspd, -A80_sixd, -A80_siyd, -A80_xtix, -A80_xtiy, -A80_spix, -A80_spiy, -A80_pcix, -A80_pciy, -A80_mvra, -A80_mvia, -A80_mvar, -A80_mvai, -A80_addix, -A80_addiy, -A80_addc, -A80_addcix, -A80_addciy, -A80_subc, -A80_subcix, -A80_subciy, -A80_jrc, -A80_jrnc, -A80_jrz, -A80_jrnz, -A80_cmpi, -A80_cmpd, -A80_im0, -A80_im1, -A80_im2, -A80_otd, -A80_oti, - -// Intel 8085 undocumented instructions -// (info from http://oak.oakland.edu/pub/cpm/maclib/i8085.lib) - -I5_dsub, // (HL) <- (HL)-(BC), affects all flags -I5_arhl, // SHIFT HL RIGHT ONE BIT, (H7 IS DUPLICATED, L0 IS SHIFTED INTO CY) -I5_rdel, // ROTATE DE LEFT ONE BIT THRU CY, (E0 RECEIVES CY, CY RECEIVES D7) -I5_ldhi, // (DE) <- (HL)+arg -I5_ldsi, // (DE) <- (SP)+arg -I5_shlx, // ((DE)) <- (HL) -I5_lhlx, // (HL) <- ((DE)) -I5_rstv, // RESTART 40H ON V (OVERFLOW) -I5_jx5, // JUMP IF X5 SET -I5_jnx5, // JUMP IF NOT X5 SET - -// Z380 instructions - -Z80_cplw, // Complement HL register -Z80_swap, // Swap upper register word with lower register word -Z80_inw, // Input word -Z80_outw, // Output word -Z80_ldw, // Load word -Z80_addw, // Add word -Z80_subw, // Subtract word -Z80_adcw, // Add with carry word -Z80_sbcw, // Subtract with borrow word -Z80_andw, // AND logical word -Z80_xorw, // XOR logical word -Z80_orw, // OR logical word -Z80_cpw, // Compare word -Z80_ddir, // Decoder directive -Z80_calr, // Call relative -Z80_ldctl, // Load control register -Z80_mtest, // Mode test -Z80_exxx, // Exchange Index Register with Alternate Bank -Z80_exxy, // Exchange Index Register with Alternate Bank -Z80_exall, // Exchange all registers with Alternate Bank -Z80_setc, // Set control bit -Z80_resc, // Reset control bit -Z80_rlcw, // Rotate Left Circular Word -Z80_rrcw, // Rotate Right Circular Word -Z80_rlw, // Rotate Left Word -Z80_rrw, // Rotate Right Word -Z80_slaw, // Shift Left Arithmetic Word -Z80_sraw, // Shift Right Arithmetic Word -Z80_srlw, // Shift Right Logical Word -Z80_multw, // Multiply Word -Z80_multuw, // Multiply Word Unsigned -Z80_divuw, // Divide unsigned -Z80_outaw, // Output word direct to port address -Z80_inaw, // Input word direct from port address -Z80_outa, // Output byte direct to port address -Z80_ina, // Input byte direct from port address -Z80_negw, // Negate word -Z80_exts, // Extend byte sign -Z80_extsw, // Extend word sign -Z80_btest, // Bank test -Z80_ldiw, // Load and increment (word) -Z80_ldirw, // Load and increment, repeat (word) -Z80_lddw, // Load and decrement (word) -Z80_lddrw, // Load and decrement, repeat (word) -Z80_iniw, // Input and increment (word) -Z80_inirw, // Input and increment, repeat (word) -Z80_indw, // Input and decrement (word) -Z80_indrw, // Input and decrement, repeat (word) -Z80_outiw, // Output and increment (word) -Z80_otirw, // Output and increment, repeat (word) -Z80_outdw, // Output and decrement (word) -Z80_otdrw, // Output and decrement, repeat (word) - -// Gameboy instructions - -GB_ldh, -GB_stop, - -I5_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -I860_null = 0, // Unknown Operation - -// -// Intel 860 XP instructions -// - -I860_adds, -I860_addu, -I860_and, -I860_andh, -I860_andnot, -I860_andnoth, -I860_bc, -I860_bc_t, -I860_bla, -I860_bnc, -I860_bnc_t, -I860_br, -I860_bri, -I860_bte, -I860_btne, -I860_call, -I860_calli, -I860_fadd, -I860_faddp, -I860_faddz, -I860_famov, -I860_fiadd, -I860_fisub, -I860_fix, -I860_fld, -I860_flush, -I860_fmlow_dd, -I860_fmul, -I860_form, -I860_frcp, -I860_frsqr, -I860_fst, -I860_fsub, -I860_ftrunc, -I860_fxfr, -I860_fzchkl, -I860_fzchks, -I860_introvr, -I860_ixfr, -I860_ld_c, -I860_ld, -I860_ldint, -I860_ldio, -I860_lock, -I860_or, -I860_orh, -I860_pfadd, -I860_pfaddp, -I860_pfaddz, -I860_pfamov, -I860_pfeq, -I860_pfgt, -I860_pfiadd, -I860_pfisub, -I860_pfix, -I860_pfld, -I860_pfle, -I860_pfmul, -I860_pfmul3_dd, -I860_pform, -I860_pfsub, -I860_pftrunc, -I860_pfzchkl, -I860_pfzchks, -I860_pst_d, -I860_scyc, -I860_shl, -I860_shr, -I860_shra, -I860_shrd, -I860_st_c, -I860_st, -I860_stio, -I860_subs, -I860_subu, -I860_trap, -I860_unlock, -I860_xor, -I860_xorh, -// -// iNTEL 860 XP Pipelined F-P instructions -// -I860_r2p1, -I860_r2pt, -I860_r2ap1, -I860_r2apt, -I860_i2p1, -I860_i2pt, -I860_i2ap1, -I860_i2apt, -I860_rat1p2, -I860_m12apm, -I860_ra1p2, -I860_m12ttpa, -I860_iat1p2, -I860_m12tpm, -I860_ia1p2, -I860_m12tpa, -I860_r2s1, -I860_r2st, -I860_r2as1, -I860_r2ast, -I860_i2s1, -I860_i2st, -I860_i2as1, -I860_i2ast, -I860_rat1s2, -I860_m12asm, -I860_ra1s2, -I860_m12ttsa, -I860_iat1s2, -I860_m12tsm, -I860_ia1s2, -I860_m12tsa, -I860_mr2p1, -I860_mr2pt, -I860_mr2mp1, -I860_mr2mpt, -I860_mi2p1, -I860_mi2pt, -I860_mi2mp1, -I860_mi2mpt, -I860_mrmt1p2, -I860_mm12mpm, -I860_mrm1p2, -I860_mm12ttpm, -I860_mimt1p2, -I860_mm12tpm, -I860_mim1p2, -I860_mr2s1, -I860_mr2st, -I860_mr2ms1, -I860_mr2mst, -I860_mi2s1, -I860_mi2st, -I860_mi2ms1, -I860_mi2mst, -I860_mrmt1s2, -I860_mm12msm, -I860_mrm1s2, -I860_mm12ttsm, -I860_mimt1s2, -I860_mm12tsm, -I860_mim1s2, - -I860_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -I51_null = 0, // Unknown Operation - -I51_acall, // Absolute Call -I51_add, // Add Second Operand to Acc -I51_addc, // Add Second Operand to Acc with carry -I51_ajmp, // Absolute Jump -I51_anl, // Logical AND (op1 &= op2) -I51_cjne, // Compare Operands and JNE -I51_clr, // Clear Operand (0) -I51_cpl, // Complement Operand -I51_da, // Decimal Adjust Accumulator -I51_dec, // Decrement Operand -I51_div, // Divide Acc by B -I51_djnz, // Decrement Operand and JNZ -I51_inc, // Increment Operand -I51_jb, // Jump if Bit is set -I51_jbc, // Jump if Bit is set & clear Bit -I51_jc, // Jump if Carry is set -I51_jmp, // Jump indirect relative to Data Pointer -I51_jnb, // Jump if Bit is clear -I51_jnc, // Jump if Carry is clear -I51_jnz, // Jump if Acc is not zero -I51_jz, // Jump if Acc is zero -I51_lcall, // Long Subroutine Call -I51_ljmp, // Long Jump -I51_mov, // Move (Op1 <- Op2) -I51_movc, // Move code byte relative to second op to Acc -I51_movx, // Move from/to external RAM -I51_mul, // Multiply Acc by B -I51_nop, // No operation -I51_orl, // Logical OR (op1 |= op2) -I51_pop, // Pop from Stack and put in Direct RAM -I51_push, // Push from Direct RAM to Stack -I51_ret, // Return from subroutine -I51_reti, // Return from Interrupt -I51_rl, // Rotate Acc left -I51_rlc, // Rotate Acc left through Carry -I51_rr, // Rotate Acc right -I51_rrc, // Rotate Acc right through Carry -I51_setb, // Set Direct Bit -I51_sjmp, // Short jump -I51_subb, // Subtract Second Operand from Acc with Borrow -I51_swap, // Swap nibbles of Acc -I51_xch, // Exchange Operands -I51_xchd, // Exchange Digit in Acc with Indirect RAM -I51_xrl, // Exclusive OR (op1 ^= op2) - -// 80251 instructions - -I51_jsle, // Jump if less than or equal (signed) -I51_jsg, // Jump if greater than (signed) -I51_jle, // Jump if less than or equal -I51_jg, // Jump if greater than -I51_jsl, // Jump if less than (signed) -I51_jsge, // Jump if greater than or equal (signed) -I51_je, // Jump if equal -I51_jne, // Jump if not equal -I51_trap, // Trap -I51_ejmp, // Extended jump -I51_ecall, // Extended call -I51_eret, // Extended return -I51_movh, // Move immediate 16-bit data to the high word of a dword (double-word) register -I51_movz, // Move 8-bit register to 16-bit register with zero extension -I51_movs, // Move 8-bit register to 16-bit register with sign extension -I51_srl, // Shift logical right by 1 bit -I51_sra, // Shift arithmetic right by 1 bit -I51_sll, // Shift logical left by 1 bit -I51_sub, // Subtract -I51_cmp, // Compare - -// 51mx instructions -I51_emov, // Move (A <- @PRi+disp) or (@PRi+disp <- A) - -I51_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -TMS_null = 0, // Unknown Operation -TMS_abs, // Absolute value of Acc -TMS_adcb, // Add ACCB to Acc With Carry -TMS_add, // Add to Acc -TMS_addb, // Add ACCB to Acc -TMS_addc, // Add to Acc With Carry -TMS_adds, // Add to Acc With Sign-Extension Suppressed -TMS_addt, // Add to Acc With Shift Specified by TREG1 -TMS_adrk, // Add to Aux Register With Short Immediate -TMS_and, // AND With Acc -TMS_andb, // AND ACCD With Acc -TMS_apac, // Add P Register to Acc -TMS_apl, // AND Data Memory Value With DBMR -TMS_apl2, // AND Data Memory Value With Long Constant -TMS_b, // Branch Unconditionally -TMS_bacc, // Branch to Location (Acc) -TMS_baccd, // Branch to Location (Acc) Delayed -TMS_banz, // Branch on Aux Register Not Zero -TMS_banzd, // Branch on Aux Register Not Zero Delayed -TMS_bcnd, // Branch Conditionally -TMS_bcndd, // Branch Conditionally Delayed -TMS_bd, // Branch Unconditionally Delayed -TMS_bit, // Test Bit -TMS_bitt, // Test Bit Specified by TREG2 -TMS_bldd, // Block Move From Data Memory to Data Memory -TMS_bldp, // Block Move From Data Memory to Program Memory -TMS_blpd, // Block Move From Program Memory to Data Memory -TMS_bsar, // Barrel Shift -TMS_cala, // Call Subroutine at (Acc) -TMS_calad, // Call Subroutine at (Acc) Delayed -TMS_call, // Call Unconditionally -TMS_calld, // Call Unconditionally Delayed -TMS_cc, // Call Conditionally -TMS_ccd, // Call Conditionally Delayed -TMS_clrc, // Clear Control Bit -TMS_cmpl, // Complement Acc -TMS_cmpr, // Compare Aux Register With ARCR -TMS_cpl, // Compare DBMR With Data Value -TMS_cpl2, // Compare Long Immediate With Data Value -TMS_crgt, // Test for Acc Greater Than ACCB -TMS_crlt, // Test for Acc Smaller Than ACCB -TMS_dmov, // Data Move in Data Memory -TMS_estop, // Emulator Stop -TMS_exar, // Exchange ACCB With Acc -TMS_idle, // Idle Until Interrupt -TMS_idle2, // Idle Until Interrupt - Low Power Mode -TMS_in, // Input Data From Port -TMS_intr, // Soft Interrupt -TMS_lacb, // Load Acc With ACCB -TMS_lacc, // Load Acc With Shift -TMS_lacl, // Load Low Acc and Clear High Acc -TMS_lact, // Load Acc With Shift Specified by TREG1 -TMS_lamm, // Load Acc With Memory-Mapped Register -TMS_lar, // Load Aux Register -TMS_ldp, // Load Data Memory Pointer -TMS_lmmr, // Load Memory-Mapped Register -TMS_lph, // Load Product High Register -TMS_lst, // Load Status Register -TMS_lt, // Load TREG0 -TMS_lta, // Load TREG0 and Accumulate Previous Product -TMS_ltd, // Load TREG0,Accumulate Previous Product and Move Data -TMS_ltp, // Load TREG0 and Store P -> Acc -TMS_lts, // Load TREG0 and Subtract Previous Product -TMS_mac, // Multiply and Accumulate -TMS_macd, // Multiply and Accumulate With Data Move -TMS_madd, // Multiply and Accumulate With Data Move and Dynamic Addressing -TMS_mads, // Multiply and Accumulate With Dynamic Addressing -TMS_mar, // Modify Aux Register -TMS_mpy, // Multiply -TMS_mpya, // Multiply and Accumulate Previous Product -TMS_mpys, // Multiply and Subtract Previous Product -TMS_mpyu, // Multiply Unsigned -TMS_neg, // Negate Acc -TMS_nmi, // Nonmaskable Interrupt -TMS_nop, // No Operation -TMS_norm, // Normalize Contents of Acc -TMS_opl, // OR With DBMS -TMS_opl2, // OR With Long Immediate -TMS_or, // OR With Acc -TMS_orb, // OR ACCB With Accumulator -TMS_out, // Out Data to Port -TMS_pac, // Load Acc <- P -TMS_pop, // Pop Top of Stack to Low Acc -TMS_popd, // Pop Top of Stack to Data Memory -TMS_pshd, // Push Data Memory Value Onto Stack -TMS_push, // Push Low Acc Onto Stack -TMS_ret, // Return From Subroutine -TMS_retc, // Return Conditionally -TMS_retcd, // Return Conditionally Delayed -TMS_retd, // Return From Subroutine Delayed -TMS_rete, // Enable Interrupts and Return From Interrupt -TMS_reti, // Return From Interrupt -TMS_rol, // Rotate Acc Left -TMS_rolb, // Rotate ACCB and Acc Left -TMS_ror, // Rotate Acc Right -TMS_rorb, // Rotate ACCB and Acc Right -TMS_rpt, // Repeat Next Instruction -TMS_rptb, // Repeat Block -TMS_rptz, // Repeat Preceded by Clearing Acc and P -TMS_sacb, // Store Acc in ACCB -TMS_sach, // Store High Acc With Shift -TMS_sacl, // Store Low Acc With Shift -TMS_samm, // Store Acc in Memory-Mapped Register -TMS_sar, // Store Aux Register -TMS_sath, // Barrel Shift Acc as Specified by TREG1(4) -TMS_satl, // Barrel Shift Acc as Specified by TREG1(3-0) -TMS_sbb, // Subtract ACCB From Acc -TMS_sbbb, // Subtract ACCB From Acc With Borrow -TMS_sbrk, // Subtract From Aux Register Short Immediate -TMS_setc, // Set Control Bit -TMS_sfl, // Shift Acc Left -TMS_sflb, // Shift ACCB and Acc Left -TMS_sfr, // Shift Acc Right -TMS_sfrb, // Shift ACCB and Acc Right -TMS_smmr, // Store Memory-Mapped Register -TMS_spac, // Subtract P From Acc -TMS_sph, // Store High P Register -TMS_spl, // Store Low P Register -TMS_splk, // Store Parallel Long Immediate -TMS_spm, // Store ACCB and Acc Right -TMS_sqra, // Square and Accumulate Previous Product -TMS_sqrs, // Square and Subtract Previous Product -TMS_sst, // Store Status Register -TMS_sub, // Subtract From Acc -TMS_subb, // Subtract From Acc With Borrow -TMS_subc, // Conditional Subtract -TMS_subs, // Subtract From Acc With Sign-Extension Suppressed -TMS_subt, // Subtract From Acc With Shift Specified by TREG1 -TMS_tblr, // Table Read -TMS_tblw, // Table Write -TMS_trap, // Software Interrupt -TMS_xc, // Execute Conditionally -TMS_xor, // Exclusive-OR With Acc -TMS_xorb, // Exclusive-OR of ACCB With Acc -TMS_xpl, // Exclusive-OR Data Memory Value -TMS_xpl2, // Exclusive-OR Data Memory Value -TMS_zalr, // Zero Low Acc Load High Acc With Rounding -TMS_zap, // Zero Acc and P -TMS_zpr, // Zero P Register - -// -// TMS320C2x instructions -// - -TMS2_abs, // Absolute value of accumulator -TMS2_add, // Add to accumulator with shift -TMS2_addc, // Add to accumulator with carry -TMS2_addh, // Add to high accumulator -TMS2_addk, // Add to accumulator short immediate -TMS2_adds, // Add to low accumulator with sign extension suppressed -TMS2_addt, // Add to accumulator with shift specified by T register -TMS2_adlk, // Add to accumulator long immediate with shift -TMS2_adrk, // Add to auxiliary register short immediate -TMS2_and, // And with accumulator -TMS2_andk, // And immediate with accumulator with shift -TMS2_apac, // App P register to accumulator -TMS2_b, // Branch unconditionally -TMS2_bacc, // Branch to address specified by accumulator -TMS2_banz, // Bnrach on auxiliary register not zero -TMS2_bbnz, // Branch if tc bit != 0 -TMS2_bbz, // Branch if tc bit = 0 -TMS2_bc, // Branch on carry -TMS2_bgez, // Branch if accumulator >= 0 -TMS2_bgz, // Branch if accumulator > 0 -TMS2_bioz, // Branch on i/o status = 0 -TMS2_bit, // Test bit -TMS2_bitt, // Test bit specifed by T register -TMS2_blez, // Branch if accumulator <= 0 -TMS2_blkd, // Block move from data memory to data memory -TMS2_blkp, // Block move from program memory to data memory -TMS2_blz, // Branch if accumulator < 0 -TMS2_bnc, // Branch on no carry -TMS2_bnv, // Branch if no overflow -TMS2_bnz, // Branch if accumulator != 0 -TMS2_bv, // Branch on overflow -TMS2_bz, // Branch if accumulator = 0 -TMS2_cala, // Call subroutine indirect -TMS2_call, // Call subroutine -TMS2_cmpl, // Complement accumulator -TMS2_cmpr, // Compare auxiliary register with auxiliary register ar0 -TMS2_cnfd, // Configure block as data memory -TMS2_cnfp, // Configure block as program memory -TMS2_conf, // Configure block as data/program memory -TMS2_dint, // Disable interrupt -TMS2_dmov, // Data move in data memory -TMS2_eint, // Enable interrupt -TMS2_fort, // Format serial port registers -TMS2_idle, // Idle until interrupt -TMS2_in, // Input data from port -TMS2_lac, // Load accumulator with shift -TMS2_lack, // Load accumulator short immediate -TMS2_lact, // Load accumulator with shift specified by T register -TMS2_lalk, // Load accumulator long immediate with shift -TMS2_lar, // Load auxiliary register -TMS2_lark, // Load auxiliary register short immediate -TMS2_larp, // Load auxiliary register pointer -TMS2_ldp, // Load data memory page pointer -TMS2_ldpk, // Load data memory page pointer immediate -TMS2_lph, // Load high P register -TMS2_lrlk, // Load auxiliary register long immediate -TMS2_lst, // Load status register ST0 -TMS2_lst1, // Load status register ST1 -TMS2_lt, // Load T register -TMS2_lta, // Load T register and accumulate previous product -TMS2_ltd, // Load T register, accumulate previous product and move data -TMS2_ltp, // Load T register and store P register in accumulator -TMS2_lts, // Load T register and subtract previous product -TMS2_mac, // Multiply and accumulate -TMS2_macd, // Multiply and accumulate with data move -TMS2_mar, // Modify auxiliary register -TMS2_mpy, // Multiply (with T register, store product in P register) -TMS2_mpya, // Multiply and accumulate previous product -TMS2_mpyk, // Multiply immediate -TMS2_mpys, // Multiply and subtract previous product -TMS2_mpyu, // Multiply unsigned -TMS2_neg, // Negate accumulator -TMS2_nop, // No operation -TMS2_norm, // Normalize contents of accumulator -TMS2_or, // Or with accumulator -TMS2_ork, // Or immediate with accumulator with shift -TMS2_out, // Output data to port -TMS2_pac, // Load accumulator with P register -TMS2_pop, // Pop top of stack to low accumulator -TMS2_popd, // Pop top of stack to data memory -TMS2_pshd, // Push data memory value onto stack -TMS2_push, // Push low accumulator onto stack -TMS2_rc, // Reset carry bit -TMS2_ret, // Return from subroutine -TMS2_rfsm, // Reset serial port frame synchronization mode -TMS2_rhm, // Reset hold mode -TMS2_rol, // Rotate accumulator left -TMS2_ror, // Rotate acuumulator right -TMS2_rovm, // Reset overflow mode -TMS2_rpt, // Repeat instruction as specified by data memory value -TMS2_rptk, // Repeat instruction as specified by immediate value -TMS2_rsxm, // Reset sign extension mode -TMS2_rtc, // Reset test/control flag -TMS2_rtxm, // Reset serial port transmit mode -TMS2_rxf, // Reset external flag -TMS2_sach, // Store high accumulator with shift -TMS2_sacl, // Store low accumulator with shift -TMS2_sar, // Store auxiliary register -TMS2_sblk, // Subtract from accumulator long immediate with shift -TMS2_sbrk, // Subtract from auxiliary register short immediate -TMS2_sc, // Set carry bit -TMS2_sfl, // Shift accumulator left -TMS2_sfr, // Shift accumulator right -TMS2_sfsm, // Set serial port frame synchronization mode -TMS2_shm, // Set hold mode -TMS2_sovm, // Set overflow mode -TMS2_spac, // Subtract P register from accumulator -TMS2_sph, // Store high P register -TMS2_spl, // Store low P register -TMS2_spm, // Set P register output shift mode -TMS2_sqra, // Square and accumulate -TMS2_sqrs, // Square and subtract previous product -TMS2_sst, // Store status register ST0 -TMS2_sst1, // Store status register ST1 -TMS2_ssxm, // Set sign extension mode -TMS2_stc, // Set test/control flag -TMS2_stxm, // Set serial port transmit mode -TMS2_sub, // Subtract from accumulator with shift -TMS2_subb, // Subtract from accumulator with borrow -TMS2_subc, // Conditional subtract -TMS2_subh, // Subtract from high accumulator -TMS2_subk, // Subtract from accumulator shoft immediate -TMS2_subs, // Subtract from low accumulator with sign extension suppressed -TMS2_subt, // Subtract from accumulator with shift specified by T register -TMS2_sxf, // Set external flag -TMS2_tblr, // Table read -TMS2_tblw, // Table write -TMS2_trap, // Software interrupt -TMS2_xor, // Exclusive or with accumulator -TMS2_xork, // Exclusive or immediate with accumulator with shift -TMS2_zac, // Zero accumulator -TMS2_zalh, // Zero low accumulator and load high accumulator -TMS2_zalr, // Zero low accumulator and load high accumulator with rounding -TMS2_zals, // Zero low accumulator and load high accumulator with sign extension suppressed - -TMS_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - M65_null = 0, // Unknown Operation - - // NMOS instructions - - M65_adc, // A <- (A) + M + C - M65_anc, // A <- A /\ M, C <- ~A7 - M65_and, // A <- (A) /\ M - M65_ane, // M <-[(A)\/$EE] /\ (X)/\(M) - M65_arr, // A <- [(A /\ M) >> 1] - M65_asl, // C <- A7, A <- (A) << 1 - M65_asr, // A <- [(A /\ M) >> 1] - M65_bcc, // if C=0, PC = PC + offset - M65_bcs, // if C=1, PC = PC + offset - M65_beq, // if Z=1, PC = PC + offset - M65_bit, // Z <- ~(A /\ M) N<-M7 V<-M6 - M65_bmi, // if N=1, PC = PC + offset - M65_bne, // if Z=0, PC = PC + offset - M65_bpl, // if N=0, PC = PC + offset - M65_brk, // Stack <- PC, PC <- ($fffe) - M65_bvc, // if V=0, PC = PC + offset - M65_bvs, // if V=1, PC = PC + offset - M65_clc, // C <- 0 - M65_cld, // D <- 0 - M65_cli, // I <- 0 - M65_clv, // V <- 0 - M65_cmp, // (A - M) -> NZC - M65_cpx, // (X - M) -> NZC - M65_cpy, // (Y - M) -> NZC - M65_dcp, // M <- (M)-1, (A-M) -> NZC - M65_dec, // M <- (M) - 1 - M65_dex, // X <- (X) - 1 - M65_dey, // Y <- (Y) - 1 - M65_eor, // A <- (A) \-/ M - M65_inc, // M <- (M) + 1 - M65_inx, // X <- (X) +1 - M65_iny, // Y <- (Y) + 1 - M65_isb, // M <- (M) - 1,A <- (A)-M-~C - M65_jmp, // PC <- Address - M65_jmpi, // (PC <- Address) - M65_jsr, // Stack <- PC, PC <- Address - M65_lae, // X,S,A <- (S /\ M) - M65_lax, // A <- M, X <- M - M65_lda, // A <- M - M65_ldx, // X <- M - M65_ldy, // Y <- M - M65_lsr, // C <- A0, A <- (A) >> 1 - M65_lxa, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04 - M65_nop, // [no operation] - M65_ora, // A <- (A) V M - M65_pha, // Stack <- (A) - M65_php, // Stack <- (P) - M65_pla, // A <- (Stack) - M65_plp, // A <- (Stack) - M65_rla, // M <- (M << 1) /\ (A) - M65_rol, // C <- A7 & A <- A << 1 + C - M65_ror, // C<-A0 & A<- (A7=C + A>>1) - M65_rra, // M <- (M >> 1) + (A) + C - M65_rti, // P <- (Stack), PC <-(Stack) - M65_rts, // PC <- (Stack) - M65_sax, // M <- (A) /\ (X) - M65_sbc, // A <- (A) - M - ~C - M65_sbx, // X <- (X)/\(A) - M - M65_sec, // C <- 1 - M65_sed, // D <- 1 - M65_sei, // I <- 1 - M65_sha, // M <- (A) /\ (X) /\ (PCH+1) - M65_shs, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1) - M65_shx, // M <- (X) /\ (PCH+1) - M65_shy, // M <- (Y) /\ (PCH+1) - M65_slo, // M <- (M >> 1) + A + C - M65_sre, // M <- (M >> 1) \-/ A - M65_sta, // M <- (A) - M65_stx, // M <- (X) - M65_sty, // M <- (Y) - M65_tax, // X <- (A) - M65_tay, // Y <- (A) - M65_tsx, // X <- (S) - M65_txa, // A <- (X) - M65_txs, // S <- (X) - M65_tya, // A <- (Y) - - // CMOS instructions - - M65_bbr0, // Branch if bit 0 reset - M65_bbr1, // Branch if bit 1 reset - M65_bbr2, // Branch if bit 2 reset - M65_bbr3, // Branch if bit 3 reset - M65_bbr4, // Branch if bit 4 reset - M65_bbr5, // Branch if bit 5 reset - M65_bbr6, // Branch if bit 6 reset - M65_bbr7, // Branch if bit 7 reset - M65_bbs0, // Branch if bit 0 set - M65_bbs1, // Branch if bit 1 set - M65_bbs2, // Branch if bit 2 set - M65_bbs3, // Branch if bit 3 set - M65_bbs4, // Branch if bit 4 set - M65_bbs5, // Branch if bit 5 set - M65_bbs6, // Branch if bit 6 set - M65_bbs7, // Branch if bit 7 set - M65_rmb0, // Reset memory bit 0 - M65_rmb1, // Reset memory bit 1 - M65_rmb2, // Reset memory bit 2 - M65_rmb3, // Reset memory bit 3 - M65_rmb4, // Reset memory bit 4 - M65_rmb5, // Reset memory bit 5 - M65_rmb6, // Reset memory bit 6 - M65_rmb7, // Reset memory bit 7 - M65_smb0, // Set memory bit 0 - M65_smb1, // Set memory bit 1 - M65_smb2, // Set memory bit 2 - M65_smb3, // Set memory bit 3 - M65_smb4, // Set memory bit 4 - M65_smb5, // Set memory bit 5 - M65_smb6, // Set memory bit 6 - M65_smb7, // Set memory bit 7 - M65_stz, // Store zero - M65_tsb, // Test and set bits - M65_trb, // Test and reset bits - M65_phy, // Push Y register - M65_ply, // Pull Y register - M65_phx, // Push X register - M65_plx, // Pull X register - M65_bra, // Branch always - - M65_last, -}; - - - - -// The instruction types (``itype''s) -// m65* CPUs implements. - -enum m65_itype_t -{ - // http://www.westerndesigncenter.com/wdc/datasheets/Programmanual.pdf - M65816_null=0, // Unknown Operation - M65816_adc, // Add with carry - M65816_and, // AND A with memory - M65816_asl, // Shift memory or A left - M65816_bcc, // Branch if carry clear - M65816_bcs, // Branch if carry set - M65816_beq, // Branch if equal - M65816_bit, // Test memory bits against A - M65816_bmi, // Branch if minus - M65816_bne, // Branch if not equal - M65816_bpl, // Branch if plus - M65816_bra, // Branch always - M65816_brk, // Software break - M65816_brl, // Branch always long - M65816_bvc, // Branch if overflow clear - M65816_bvs, // Branch if overflow set - M65816_clc, // Clear carry flag - M65816_cld, // Clear decimal mode flag - M65816_cli, // Clear interrupt disable flag - M65816_clv, // Clear overflow flag - M65816_cmp, // Compare A with memory - M65816_cop, // Co-processor enable - M65816_cpx, // Compare X with memory - M65816_cpy, // Compare Y with memory - M65816_dec, // Decrement - M65816_dex, // Decrement X - M65816_dey, // Decrement Y - M65816_eor, // XOR A with M - M65816_inc, // Increment - M65816_inx, // Increment X - M65816_iny, // Increment Y - M65816_jml, // Jump long (inter-bank) - M65816_jmp, // Jump - M65816_jsl, // Jump to subroutine long (inter-bank) - M65816_jsr, // Jump to subroutine - M65816_lda, // Load A from memory - M65816_ldx, // Load X from memory - M65816_ldy, // Load Y from memory - M65816_lsr, // Logical shift memory or A right - M65816_mvn, // Block move next - M65816_mvp, // Block move prev - M65816_nop, // Nop - M65816_ora, // Or A with memory - M65816_pea, // Push effective absolute address - M65816_pei, // Push effective indirect address - M65816_per, // Push effective PC-relative indirect address - M65816_pha, // Push A - M65816_phb, // Push B (data bank register) - M65816_phd, // Push D (direct page register) - M65816_phk, // Push K (program bank register) - M65816_php, // Push processor status - M65816_phx, // Push X - M65816_phy, // Push Y - M65816_pla, // Pull A - M65816_plb, // Pull B - M65816_pld, // Pull D - M65816_plp, // Pull processor status - M65816_plx, // Pull X - M65816_ply, // Pull Y - M65816_rep, // Reset status bits - M65816_rol, // Rotate memory or A left - M65816_ror, // Rotate memory or A right - M65816_rti, // Return from interrupt - M65816_rtl, // Return from subroutine long - M65816_rts, // Return from subroutine - M65816_sbc, // Subtract with borrow from A - M65816_sec, // Set carry flag - M65816_sed, // Set decimal mode flag - M65816_sei, // Set interrupt disable flag - M65816_sep, // Set status bits - M65816_sta, // Store A to memory - M65816_stp, // Stop processor - M65816_stx, // Store X to memory - M65816_sty, // Store Y to memory - M65816_stz, // Store zero to memory - M65816_tax, // Transfer A to X - M65816_tay, // Transfer A to Y - M65816_tcd, // Transfer 16-bit A to D (direct page register) - M65816_tcs, // Transfer A to S - M65816_tdc, // Transfer 16-bit D to A - M65816_trb, // Test and reset memory bits against A - M65816_tsb, // Test and set memory bits against A - M65816_tsc, // Transfer S to A - M65816_tsx, // Transfer S to X - M65816_txa, // Transfer X to A - M65816_txs, // Transfer X to S - M65816_txy, // Transfer X to Y - M65816_tya, // Transfer Y to A - M65816_tyx, // Transfer Y to X - M65816_wai, // Wait for interrupt - M65816_wdm, // Reserved - M65816_xba, // Exchange bytes in A - M65816_xce, // Exchange carry and emulation bits - M65816_last -}; - -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-2020 Hex-Rays - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -pdp_null = 0, // Unknown Operation - -pdp_halt, // Stop CPU -pdp_wait, // Wait interrupt -pdp_rti, // Interrupt return -pdp_bpt, // Trap to Debbuger -pdp_iot, // Trap to 20 (i/o) -pdp_reset, // Reset CPU and device -pdp_rtt, // Interrupt return and ignore dbg-flag -pdp_mfpt, // Load Processor Type (* hi model) -pdp_jmp, // Absolute jmp -pdp_rts, // Return into subroutine -pdp_spl, // Set Prior. -pdp_nop, // Not operation -pdp_clc, // Clear C bit in PSW -pdp_clv, // Clear V bit in PSW -pdp_clz, // Clear Z bit in PSW -pdp_cln, // Clear N bit in PSW -pdp_ccc, // Clear All Condition bits in PSW -pdp_sec, // Set C bit in PSW -pdp_sev, // Set V bit in PSW -pdp_sez, // Set Z bit in PSW -pdp_sen, // Set N bit in PSW -pdp_scc, // Set All Condition bits bit in PSW -pdp_swab, // Exchange byte in word -pdp_br, // Relative jmp -pdp_bne, // Jump if Z=0 -pdp_beq, // Jump if Z=1 -pdp_bge, // Jump if N^V=0 -pdp_blt, // Jump if N^V=1 -pdp_bgt, // Jump if Z|(N^V)=0 -pdp_ble, // Jump if Z|(N^V)=1 -pdp_jsr, // Call procedure -pdp_clr, // Clear operand -pdp_com, // Inverse operand -pdp_inc, // Increment operand -pdp_dec, // Decrement operand -pdp_neg, // op = -op -pdp_adc, // Add with Carry -pdp_sbc, // Substract with Carry -pdp_tst, // Test operand -pdp_ror, // Cyclic shift rignt -pdp_rol, // Cyclic shift left -pdp_asr, // Arifmetic shift rignt -pdp_asl, // Arifmetic shift left -pdp_mark, // Return and empty stack -pdp_mfpi, // Load from previous instruction space (*hi model) -pdp_mtpi, // Store to previous instruction space (*hi model) -pdp_sxt, // N=>op -pdp_mov, // Move operand -pdp_cmp, // Compare operands -pdp_bit, // Check Bit's -pdp_bic, // Clear Bit's -pdp_bis, // Set Bit's -pdp_add, // Add operands -pdp_sub, // Substract operands -pdp_mul, // Multiple Reg (*eis) -pdp_div, // Divide Reg (*eis) -pdp_ash, // Multistep shift (*eis) -pdp_ashc, // Multistep shift 2 reg (*eis) -pdp_xor, // Exclusive or (*eis) -pdp_fadd, // Floating Add (*fis) -pdp_fsub, // Floating Subtract (*fis) -pdp_fmul, // Floating Multiple (*fis) -pdp_fdiv, // Floating Divide (*fis) -pdp_sob, // -pdp_bpl, // Jump if N=0 -pdp_bmi, // Jump if N=1 -pdp_bhi, // Jump if (!C)&(!Z)=0 -pdp_blos, // Jump if C|Z=1 -pdp_bvc, // Jump if V=0 -pdp_bvs, // Jump if V=1 -pdp_bcc, // Jump if C=0 -pdp_bcs, // Jump if C=1 -pdp_emt, // Trap to System -pdp_trap, // Trap to user/compiler -pdp_mtps, // Store PSW (*lsi11 only) -pdp_mfpd, // Load from previous data space (*hi model) -pdp_mtpd, // Store to previous data space (*hi model) -pdp_mfps, // Load PSW (*lsi11 only) - // FPU instruction -pdp_cfcc, // Copy cond.codes into FPS to PSW -pdp_setf, // Set Float -pdp_seti, // Set Integer -pdp_setd, // Set Double -pdp_setl, // Set Long Integer -pdp_ldfps, // Load FPS -pdp_stfps, // Store FPS -pdp_stst, // Load interrupt status -pdp_clrd, // Clear -pdp_tstd, // Test -pdp_absd, // op = mod(op) -pdp_negd, // op = -op -pdp_muld, // Multiple -pdp_modd, // Get int. part -pdp_addd, // Add -pdp_ldd, // Load in Acc -pdp_subd, // Substract -pdp_cmpd, // Compare -pdp_std, // Store into Acc -pdp_divd, // Divide -pdp_stexp, // Store exponent -pdp_stcdi, // Store and convert double/float to integer/long -pdp_stcdf, // Store and convert double/float to float/double -pdp_ldexp, // Load exponent -pdp_ldcif, // Load and convert integer/long to double/float -pdp_ldcfd, // Load and convert float/double to double/float -pdp_call, // Jsr PC, -pdp_return, // RTS PC -pdp_compcc, // Complex Condition Codes - -pdp_last - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - mc_null = 0, // Unknown Operation - - mc_abcd, // summa with BCD correction - mc_add, // summa with Dn - mc_adda, // summa with An - mc_addi, // summa with immediate - mc_addq, // -"- - mc_addx, // summa 2 reg and const - mc_and, // logical and - mc_andi, // logical and with immediate - mc_asl, // shift by count - mc_asr, // -"- - mc_b, // branch if cond code - mc_bchg, // bit chang - mc_bclr, // bit clear - mc_bftst, // bit field test - mc_bfchg, // bit field change - mc_bfclr, // bit field set in 0 - mc_bfset, // bit field set in 1 - mc_bfextu, // bit field extract (unsigned) - mc_bfexts, // bit field extract (signed) - mc_bfffo, // bit field offset - mc_bfins, // bit field include - mc_bgnd, // CPU32- enter backgound mode - mc_bkpt, // disable TRAP at any cycles - mc_bra, // branch - mc_bset, // bit set - mc_bsr, // relative call - mc_btst, // bit test - mc_callm, // call module [descrtiptor] (020) - mc_cas, // compare and swap - mc_cas2, // -"- - mc_chk, // compare and trap - mc_chk2, // -"- - mc_cinv, // invalidate cache - mc_clr, // clear data - mc_cmp, // compare data - mc_cmp2, // -"- - mc_cmpa, // compare address - mc_cmpi, // compare immediate - mc_cmpm, // compare memory - mc_cpush, // invalidate cache - mc_db, // (djnz) if cond code - mc_divs, // sign divide - mc_divsl, // -"- - mc_divu, // unsign didide - mc_divul, // -"- - mc_eor, // logical xor - mc_eori, // logical xor with immediate - mc_exg, // exchange registers - mc_ext, // analog cwd - mc_extb, // analog cwq - mc_fabs, // FP abs - mc_facos, // FP acos - mc_fadd, // FP add - mc_fasin, // FP asin - mc_fatan, // FP atan - mc_fatanh, // FP atanh - mc_fb, // fBcc - mc_fcmp, // FP cmp - mc_fcos, // FP cos - mc_fcosh, // FP cosh - mc_fdabs, // FP abs double rounded - mc_fdadd, // FP add - mc_fdb, // fDBcc - mc_fddiv, // FP div double rounded - mc_fdiv, // FP div - mc_fdmove, // FP mov double rounded - mc_fdmul, // FP mul double rounded - mc_fdneg, // FP neg double rounded - mc_fdsqrt, // FP sqrt double rounded - mc_fdsub, // FP sub double rounded - mc_fetox, // FP e**x - mc_fetoxm1, // FP e**x-1 - mc_fgetexp, // FP extract exponent - mc_fgetman, // FP extract mantissa - mc_fint, // FP get integer part - mc_fintrz, // FP get integer part by round - mc_flog2, // FP log[2] - mc_flog10, // FP log[10] - mc_flogn, // FP log[e] - mc_flognp1, // FP log[e] x+1 - mc_fmod, // FP mod - mc_fmove, // move float - mc_fmovecr, // move floating const - mc_fmovem, // move float register list - mc_fmul, // FM mul - mc_fneg, // FP neg - mc_fnop, // float nop - mc_frem, // FP rem - mc_frestore, // restore status - mc_fs, // fScc - mc_fsabs, // FP abs single rounded - mc_fsadd, // FP add single rounded - mc_fsave, // Fsave status - mc_fscale, // FP *2**x - mc_fsdiv, // FP div single rounded - mc_fsgldiv, // FP single div - mc_fsglmul, // FP single mul - mc_fsin, // FP sin - mc_fsincos, // FP sin & cos - mc_fsinh, // FP sinh - mc_fsmove, // FP mov single rounded - mc_fsmul, // FP mul single rounded - mc_fsneg, // FP neg single rounded - mc_fsqrt, // FP sqrt - mc_fssqrt, // FP sqrt single rounded - mc_fssub, // FP sub single rounded - mc_fsub, // FP sub - mc_ftan, // FP tan - mc_ftanh, // FP tanh - mc_ftentox, // FP 10**x - mc_ftrap, // fTRAPcc - mc_ftst, // FP tst - mc_ftwotox, // FP 2**x - mc_halt, // (coldfire) Halt the processor - mc_illegal, // trap to vector - mc_jmp, // absolute Jmp - mc_jsr, // absolute jsr - mc_lea, // load effective address - mc_link, // change sp context - mc_lpstop, // cpu32 - stop - mc_lsl, // logical shift - mc_lsr, // -"- - mc_mac, // multiple and accumulate - mc_macl, // multiple and accumulate with register load - mc_move, // move memory - mc_move16, // move 16 byte - mc_movea, // move move with address reg - mc_movec, // move from/to control register - mc_movem, // move register list - mc_movep, // move with data register - mc_moveq, // move with immediate - mc_moves, // mtpd/mfpd - mc_msac, // multiple and subtract - mc_msacl, // multiple and subtract with register load - mc_muls, // sign multiplication - mc_mulu, // unsign multiplication - mc_nbcd, // negative with BCD correct - mc_neg, // negative - mc_negx, // negative with immediate - mc_nop, // null operation - mc_not, // logical not - mc_or, // logical or - mc_ori, // logical or with immediate - mc_pack, // UNP(bcd)+adj -> PACK(bcd) - mc_pea, // lea into stack - mc_pb, // 68851 pbcc - mc_pdb, // 68851 pdbcc - mc_pflush, // invalidate cache - mc_pflushr, // 68851 load root entry - mc_ploadr, // 68851 - mc_ploadw, // 68851 - mc_pmove, // move MMU register - mc_prestore, // 68851 - mc_psave, // 68851 - mc_ps, // 68851 pscc - mc_ptestr, // test a logical address - mc_ptestw, // -"- - mc_ptrap, // 68851 ptrapcc - mc_pulse, // (coldfire) generate unique PST value - mc_pvalid, // 68851 move AL bit - mc_rol, // cycl. shift - mc_ror, // -"- - mc_roxl, // two op cycl shift - mc_roxr, // -"- - mc_reset, // reset - mc_rtd, // mark - mc_rte, // return with SR - mc_rtm, // reload save module state - mc_rtr, // return with CCR - mc_rts, // return - mc_sbcd, // substract with BCD correction - mc_s, // 1 if cond code else 0 - mc_stop, // halt - mc_sub, // substract - mc_suba, // substract address - mc_subi, // substract immediate - mc_subq, // -"- - mc_subx, // substract memory - mc_swap, // hi and low word in register - mc_tas, // test byte sign - mc_tbl, // CPU32-tblu/tblun/tbls/tblsn - mc_trap, // analog int(86) (or trap if cond code) - mc_trapv, // if V then trap - mc_tst, // test destination - mc_unlk, // destroy address ? - mc_unpk, // PACK(bcd)+adj -> UNPACK(bcd) - mc_wddata, // (coldfire) load WDDATA port (pins) - mc_wdebug, // (coldfire) load debug register - mc_atrap, // MacOS atrap - - // new ColdFire instructions - mc_bitrev, // bit reverse - mc_byterev, // byte reverse - mc_ff1, // find first one - mc_intouch, // instruction fetch touch - mc_mov3q, // move 3-bit data quick - mc_mvs, // move with sign extend - mc_mvz, // move with zero-fill - mc_sats, // signed saturate - mc_movclr, // move from accumulator and clear - mc_maaac, // Multiply and Add to 1st Accumulator, Add to 2nd Accumulator - mc_masac, // Multiply and Add to 1st Accumulator, Subtract from 2nd Accumulator - mc_msaac, // Multiply and Subtract to 1st Accumulator, Add to 2nd Accumulator - mc_mssac, // Multiply and Subtract to 1st Accumulator, Subtract to 2nd Accumulator - - mc_remsl, // Signed Divide Remainder - mc_remul, // Unsigned Divide Remainder - - mc_last -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -mc8_null = 0, // Unknown Operation - -mc8_aba, // Add b to a (11) -mc8_ab, // Add b to index register -mc8_adc, // Add with carry -mc8_add, // Add without carry -mc8_addd, // Add 16-bit to D (11) -mc8_ais, // Add immediate value to stack pointer (8) -mc8_aix, // Add immediate value to index register (H:X) (8) -mc8_and, // Logical AND -mc8_andcc, // Logical AND immdiate with CCR (9) -mc8_asr, // Ariphmetic shift right -mc8_bcc, // Branch if carry bit clear -mc8_bclr, // Clear bit in memory -mc8_bcs, // Branch if carry bit set -mc8_beq, // Branch if equal -mc8_bge, // Branch if >= (signed) -mc8_bgt, // Branch if > (signed) -mc8_bhcc, // Branch if half carry bit clear (8) -mc8_bhcs, // Branch if half carry bit set (8) -mc8_bhi, // Branch if > (unsigned) -mc8_bhs, // Branch if >= (unsigned) (11) -mc8_bih, // Branch if IRQ pin high (8) -mc8_bil, // Branch if IRQ pin low (8) -mc8_bit, // Bit test (8) -mc8_ble, // Branch if <= (signed) (8) -mc8_blo, // Branch if < (unsigned) (11) -mc8_bls, // Branch if <= (unsigned) (8) -mc8_blt, // Branch if < (signed) (8) -mc8_bmc, // Branch if interrupt mask clear (8) -mc8_bmi, // Branch if minus -mc8_bms, // Branch if interrupt mask set (8) -mc8_bne, // Branch if not equal -mc8_bpl, // Branch if not plus -mc8_bra, // Branch always -mc8_brclr, // Branch if bit (n) in memory clear -mc8_brn, // Branch never -mc8_brset, // Branch if bit (n) in memory set -mc8_bset, // Set bit in memory -mc8_bsr, // Branch to subroutine -mc8_bvc, // Branch if overflow cleared (11) -mc8_bvs, // Branch if overflow set (11) -mc8_cba, // Compare A to B (11) -mc8_cbeq, // Compare and branch if equal (8) -mc8_clc, // Clear carry bit -mc8_cli, // Clear interrupt mask -mc8_clr, // Clear -mc8_clv, // Clear overflow flag (11) -mc8_cmp, // Compare accumulator with memory -mc8_com, // Complement -mc8_cp, // Compare index register 16 bit (11) -mc8_cpd, // Compare D 16 bit (11) -mc8_cphx, // Compare index register with memory (8) -mc8_cpx, // Compare X (index register low) with memory (8) -mc8_cwai, // Clear CC bits & wait for interrupt (9) -mc8_daa, // Decimal adjust accumulator -mc8_dbnz, // Decrement and branch if not equal (8) -mc8_de, // Decrement index register (11) -mc8_dec, // Decrement -mc8_des, // Decrement stack pointer (11) -mc8_div, // Divide (8) -mc8_eor, // Excusive OR memory with accumulator -mc8_exg, // Exchange register (9) -mc8_fdiv, // Fractional divide 16 by 16 (11) -mc8_idiv, // Integer divide 16 by 16 (11) -mc8_in, // Increment index register (11) -mc8_inc, // Increment -mc8_ins, // Increment stack pointer (11) -mc8_jmp, // Jump -mc8_jsr, // Jump to subroutine -mc8_ld, // Load index register (11) -mc8_lda, // Load accumulator from memory -mc8_ldd, // Load double accumulator (11) -mc8_ldhx, // Load index register from memory (8) -mc8_lds, // Load stack pointer (11) -mc8_ldx, // Load X (index register low) from memory (8) -mc8_lea, // Load register from memory (9) -mc8_lsl, // Logical (or Ariphmetic) shift left -mc8_lsld, // Logical (or Ariphmetic) shift left double (11) -mc8_lsr, // Logical shift right -mc8_lsrd, // Logical shift right double (11) -mc8_mov, // Move (8) -mc8_mul, // Unsigned multiply -mc8_neg, // Negate -mc8_nop, // No Operation -mc8_nsa, // Nibble swap accumulator (8) -mc8_ora, // Inclusive OR memory with accumulator -mc8_orcc, // Inclusive OR immediate with CCR (9) -mc8_psh, // Push index register into stack (low first) (11) -mc8_psha, // Push accumulator A into stack -mc8_pshb, // Push accumulator B into stack (11) -mc8_pshh, // Push H (index register high) into stack (8) -mc8_pshx, // Push X (index register low) into stack (8) -mc8_pul, // Pull index register from stack (hi first) (11) -mc8_pula, // Pull accumulator A from stack -mc8_pulb, // Pull accumulator B from stack (11) -mc8_pulh, // Pull H (index register high) from stack (8) -mc8_pulx, // Pull X (index register low) from stack (8) -mc8_rol, // Rotate left trough carry -mc8_ror, // Rotate right trough carry -mc8_rsp, // Reset stack pointer (8) -mc8_rti, // Reset from interrupt -mc8_rts, // Reset from subroutine -mc8_sba, // Subtract B from A (11) -mc8_sbc, // Subtract with carry -mc8_sec, // Set carry bit -mc8_sei, // Set interrupt mask bit -mc8_sev, // Set Overflow Flag (11) -mc8_sex, // Sign extended (9) -mc8_slp, // Sleep (HD63701 extention) (11) -mc8_st, // Store index register in memory (11) -mc8_sta, // Store accumulator in memory -mc8_std, // Store accumulators in memory (11) -mc8_sthx, // Store H:X (index reg) (8) -mc8_stop, // Enable IRQ pin. Stop oscillator -mc8_sts, // Store stack pointer (11) -mc8_stx, // Store X (index register low) in memory (8) -mc8_sub, // Subtract -mc8_subd, // Subtract 16-bit (11) -mc8_swi, // Software interrupt -mc8_sync, // Syncronisation with interrupt (9) -mc8_tab, // Transfer A to B (11) -mc8_tap, // Transfer A to CCR -mc8_tax, // Transfer accumulator to X (index register low) (8) -mc8_tba, // Transfer B to A (11) -mc8_test, // Address Bus Counts (in test mode) (11) -mc8_tfr, // Transfer register to register (9) -mc8_tpa, // Transfer CCR to A -mc8_ts, // Transfer SP to index reg (11) -mc8_tst, // Test for negative or zero -mc8_tsx, // Transfer SP to index reg (8) -mc8_txa, // Transfer X (index reg low) to accumulator (8) -mc8_txs, // Transfer index reg X to SP -mc8_tys, // Transfer index reg Y to SP (11) -mc8_wai, // Wait for interrupt (11) -mc8_wait, // Enable interrupt. Stop processor (8) -mc8_xgd, // Exchange D with index register (11) -mc8_1, // Special testing command (11) -mc8_2, // Special testing command (11) -mc8_os9, // OS9 system call (9) -// these instructions must be continuous (HD63701 extention) -mc8_aim, -mc8_oim, -mc8_eim, -mc8_tim, - -// new S08 instructions -mc8_bgnd, // Background (8) -mc8_call, // Call Subroutine (8) -mc8_rtc, // Return fom Call (8) - -// Pseudoinstructions -mc8_skip1, // Skip one byte -mc8_skip2, // Skip two bytes - -mc8_last - - }; - -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-2020 Hex-Rays - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - //j_null = 0, // Unknown Operation - j_nop = 0, // 0 //Do nothing - j_aconst_null, // 1 //Push null object reference - j_iconst_m1, // 2 //Push integer constant -1 - j_iconst_0, // 3 //Push the integer 0 - j_iconst_1, // 4 //Push the integer 1 - j_iconst_2, // 5 //Push the integer 2 - j_iconst_3, // 6 //Push the integer 3 - j_iconst_4, // 7 //Push the integer 4 - j_iconst_5, // 8 //Push the integer 5 - j_lconst_0, // 9 //Push the long integer 0 - j_lconst_1, // 10 //Push the long integer 1 - j_fconst_0, // 11 //Push the single-precision foating point 0.0 - j_fconst_1, // 12 //Push the single-precision foating point 1.0 - j_fconst_2, // 13 //Push the single-precision foating point 2.0 - j_dconst_0, // 14 //Push the double-precision foating point 2.0 - j_dconst_1, // 15 //Push the double-precision foating point 2.0 - j_bipush, // 16 //Push one byte signed integer - j_sipush, // 17 //Push two-byte signed integer - j_ldc, // 18 //Push item from constant pool (i1) - j_ldcw, // 19 //Push item from constant pool (i2) - j_ldc2w, // 20 //Push long or double from constant pool - j_iload, // 21 //Push integer value of the local variable - j_lload, // 22 //Push long value of the local variable - j_fload, // 23 //Push single float value of the local variable - j_dload, // 24 //Push double float value of the local variable - j_aload, // 25 //Push object reference from the local variable - j_iload_0, // 26 //Push integer value of the local variable #0 - j_iload_1, // 27 //Push integer value of the local variable #1 - j_iload_2, // 28 //Push integer value of the local variable #2 - j_iload_3, // 29 //Push integer value of the local variable #3 - j_lload_0, // 30 //Push long value of the local variable #0 - j_lload_1, // 31 //Push long value of the local variable #1 - j_lload_2, // 32 //Push long value of the local variable #2 - j_lload_3, // 33 //Push long value of the local variable #3 - j_fload_0, // 34 //Push single float value of the local variable #0 - j_fload_1, // 35 //Push single float value of the local variable #1 - j_fload_2, // 36 //Push single float value of the local variable #2 - j_fload_3, // 37 //Push single float value of the local variable #3 - j_dload_0, // 38 //Push double float value of the local variable #0 - j_dload_1, // 39 //Push double float value of the local variable #1 - j_dload_2, // 40 //Push double float value of the local variable #2 - j_dload_3, // 41 //Push double float value of the local variable #3 - j_aload_0, // 42 //Push object reference from the local variable #0 - j_aload_1, // 43 //Push object reference from the local variable #1 - j_aload_2, // 44 //Push object reference from the local variable #2 - j_aload_3, // 45 //Push object reference from the local variable #3 - j_iaload, // 46 //Push integer from array - j_laload, // 47 //Push long from array - j_faload, // 48 //Push single float from array - j_daload, // 49 //Push double float from array - j_aaload, // 50 //Push object refernce from array - j_baload, // 51 //Push signed byte from array - j_caload, // 52 //Push character from array - j_saload, // 53 //Push short from array - j_istore, // 54 //Pop integer value into local variable - j_lstore, // 55 //Pop long value into local variable - j_fstore, // 56 //Pop single float value into local variable - j_dstore, // 57 //Pop double float value into local variable - j_astore, // 58 //Pop object refernce into local variable - j_istore_0, // 59 //Pop integer value into local variable #0 - j_istore_1, // 60 //Pop integer value into local variable #1 - j_istore_2, // 61 //Pop integer value into local variable #2 - j_istore_3, // 62 //Pop integer value into local variable #3 - j_lstore_0, // 63 //Pop long value into local variable #0 - j_lstore_1, // 64 //Pop long value into local variable #1 - j_lstore_2, // 65 //Pop long value into local variable #2 - j_lstore_3, // 66 //Pop long value into local variable #3 - j_fstore_0, // 67 //Pop single float value into local variable #0 - j_fstore_1, // 68 //Pop single float value into local variable #1 - j_fstore_2, // 69 //Pop single float value into local variable #2 - j_fstore_3, // 70 //Pop single float value into local variable #3 - j_dstore_0, // 71 //Pop double float value into local variable - j_dstore_1, // 72 //Pop double float value into local variable #0 - j_dstore_2, // 73 //Pop double float value into local variable #1 - j_dstore_3, // 74 //Pop double float value into local variable #2 - j_astore_0, // 75 //Pop object refernce into local variable #0 - j_astore_1, // 76 //Pop object refernce into local variable #1 - j_astore_2, // 77 //Pop object refernce into local variable #2 - j_astore_3, // 78 //Pop object refernce into local variable #3 - j_iastore, // 79 //Pop integer from array - j_lastore, // 80 //Pop long from array - j_fastore, // 81 //Pop single float from array - j_dastore, // 82 //Pop double float from array - j_aastore, // 83 //Pop object refernce from array - j_bastore, // 84 //Pop signed byte from array - j_castore, // 85 //Pop character from array - j_sastore, // 86 //Pop short from array - j_pop, // 87 //Pop top stack word - j_pop2, // 88 //Pop top two stack word - j_dup, // 89 //Duplicate top stack word - j_dup_x1, // 90 //Duplicate top stack word and put two down - j_dup_x2, // 91 //Duplicate top stack word and put three down - j_dup2, // 92 //Duplicate top two stack word - j_dup2_x1, // 93 //Duplicate top two stack words and put two down - j_dup2_x2, // 94 //Duplicate top two stack words and put three down - j_swap, // 95 //Swap two top stack words - j_iadd, // 96 //Integer add - j_ladd, // 97 //Long add - j_fadd, // 98 //Single float add - j_dadd, // 99 //Double float add - j_isub, //100 //Integer subtract - j_lsub, //101 //Long subtract - j_fsub, //102 //Single float subtract - j_dsub, //103 //Double Float subtract - j_imul, //104 //Integer multiply - j_lmul, //105 //Long multiply - j_fmul, //106 //Single float multiply - j_dmul, //107 //Double Float multiply - j_idiv, //108 //Integer divide - j_ldiv, //109 //Long divide - j_fdiv, //110 //Single float divide - j_ddiv, //111 //Double Float divide - j_irem, //112 //Integer reminder - j_lrem, //113 //Long reminder - j_frem, //114 //Single float reminder - j_drem, //115 //Double Float reminder - j_ineg, //116 //Integer negate - j_lneg, //117 //Long negate - j_fneg, //118 //Single float negate - j_dneg, //119 //Double Float negate - j_ishl, //120 //Integer shift left - j_lshl, //121 //Long shift left - j_ishr, //122 //Integer logical shift right - j_lshr, //123 //Long logical shift right - j_iushr, //124 //Integer arithmetic shift right - j_lushr, //125 //Long arithmeticshift right - j_iand, //126 //Integer boolean AND - j_land, //127 //Long boolean AND - j_ior, //128 //Integer boolean OR - j_lor, //129 //Long boolean OR - j_ixor, //130 //Integer boolean XOR - j_lxor, //131 //Long boolean XOR - j_iinc, //132 //Add 8-bit signed const to local variable - j_i2l, //133 //Integer to Long conversion - j_i2f, //134 //Integer to single float conversion - j_i2d, //135 //Integer to double float conversion - j_l2i, //136 //Long to Integer conversion - j_l2f, //137 //Long to single float conversion - j_l2d, //138 //Long to double float conversion - j_f2i, //139 //Single float to Integer conversion - j_f2l, //140 //Single float to Long conversion - j_f2d, //141 //Single float to double float conversion - j_d2i, //142 //Double float to Integer conversion - j_d2l, //143 //Double float to Long conversion - j_d2f, //144 //Double float to double float conversion - j_i2b, //145 //Integer to signed byte conversion - j_i2c, //146 //Integer to unsigned short conversion - j_i2s, //147 //Integer to signed short conversion - j_lcmp, //148 //Long compare - j_fcmpl, //149 //Single float compare (-1 on NaN) - j_fcmpg, //150 //Single float compare (1 on NaN) - j_dcmpl, //151 //Double float compare (-1 on NaN) - j_dcmpg, //152 //Double float compare (1 on NaN) - j_ifeq, //153 //Branch if equal to 0 - j_ifne, //154 //Branch if not equal to 0 - j_iflt, //155 //Branch if less then 0 - j_ifge, //156 //Branch if greater than or equal to 0 - j_ifgt, //157 //Branch if greater than 0 - j_ifle, //158 //Branch if less than or equal to 0 - j_if_icmpeq, //159 //Branch if integers equal - j_if_icmpne, //160 //Branch if integers not equal - j_if_icmplt, //161 //Branch if integers less than - j_if_icmpge, //162 //Branch if integers grater than or equal to - j_if_icmpgt, //163 //Branch if integers grater than - j_if_icmple, //164 //Branch if integers less than or equal to - j_if_acmpeq, //165 //Branch if object references are equal - j_if_acmpne, //166 //Branch if object references not equal - j_goto, //167 //Branch always - j_jsr, //168 //Jump subroutine - j_ret, //169 //Return from subroutine - j_tableswitch, //170 //Access jump table by index and jump - j_lookupswitch, //171 //Access jump table by key match and jump - j_ireturn, //172 //Return integer from function - j_lreturn, //173 //Return long from function - j_freturn, //174 //Return single floatr from function - j_dreturn, //175 //Return double float from function - j_areturn, //176 //Return object reference from function - j_return, //177 //Return (void) from procedure - j_getstatic, //178 //Set static field from class - j_putstatic, //179 //Set static field in class - j_getfield, //180 //Fetch field from object - j_putfield, //181 //Set field in object - j_invokevirtual, //182 //invoke instance method - j_invokespecial, //183 //invoke instance method (superclass/init/...) - j_invokestatic, //184 //invoke a class (static) method - j_invokeinterface, //185 //invoke interface method - j_invokedynamic, //186 // invoke instance method (select by paraneter) - j_new, //187 //Create new object - j_newarray, //188 //Allocate new array - j_anewarray, //189 //Allocate new array of refernces to object - j_arraylength, //190 //Get length of array - j_athrow, //191 //Throw exception or error - j_checkcast, //192 //Make sure object is of given type - j_instanceof, //193 //Determine if an object is of given type - j_monitorenter, //194 //Enter monitored region of code - j_monitorexit, //195 //Exit monitored region of code - j_wide, //196 //wide (prefix of command) - j_multianewarray, //197 //Allocate new multi-dimensional array - j_ifnull, //198 //Branch if NULL-ptr - j_ifnonnull, //199 //Branch if not NULL-ptr - j_goto_w, //200 //Branch always (wide index) - j_jsr_w, //201 //Jump subroutine (wide index) - j_breakpoint, //202 //Stop and pass control to breakpoint handler - // - j_lastnorm, - j_a_invokesuper = j_lastnorm, - j_a_invokevirtualobject, - j_a_invokeignored, - //bottom of table ! (emu) - j_a_software, - j_a_hardware, - // - j_last -}; - -enum name_quick -{ - j_ldc_quick = j_lastnorm, //203 (18) - j_ldcw_quick, //204 (19) - j_ldc2w_quick, //205 (20) - j_getfield_quick, //206 (180) - j_putfield_quick, //207 (181) - j_getfield2_quick, //208 - j_putfield2_quick, //209 - j_getstatic_quick, //210 (178) - j_putstatic_quick, //211 (179) - j_getstatic2_quick, //212 - j_putstatic2_quick, //213 - j_invokevirtual_quick, //214 (182) - j_invokenonvirtual_quick, //215 (183) - j_invokesuper_quick, //216 - j_invokestatic_quick, //217 (184) - j_invokeinterface_quick, //218 (185) - j_invokevirtualobject_quick, //219 - j_invokeignored_quick, //220 - j_new_quick, //221 (187) - j_anewarray_quick, //222 (189) - j_multianewarray_quick, //223 (197) - j_checkcast_quick, //224 (192) - j_instanceof_quick, //225 (193) - j_invokevirtual_quick_w, //226 - j_getfield_quick_w, //227 - j_putfield_quick_w, //228 - j_quick_last -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -ARM_null = 0, // Unknown Operation -ARM_ret, // Return from Subroutine -ARM_nop, // No Operation -ARM_b, // Branch -ARM_bl, // Branch with Link -ARM_asr, // Arithmetic Shift Right -ARM_lsl, // Logical Shift Left -ARM_lsr, // Logical Shift Right -ARM_ror, // Rotate Right -ARM_neg, // Negate -ARM_and, // 0 Rd = Op1 & Op2 -ARM_eor, // 1 Rd = Op1 ^ Op2 -ARM_sub, // 2 Rd = Op1 - Op2 -ARM_rsb, // 3 Rd = Op2 - Op1 -ARM_add, // 4 Rd = Op1 + Op2 -ARM_adc, // 5 Rd = Op1 + Op2 + C -ARM_sbc, // 6 Rd = Op1 - Op2 + C - 1 -ARM_rsc, // 7 Rd = Op2 - Op1 + C - 1 -ARM_tst, // 8 Set cond. codes on Op1 & Op2 -ARM_teq, // 9 Set cond. codes on Op1 ^ Op2 -ARM_cmp, // A Set cond. codes on Op1 - Op2 -ARM_cmn, // B Set cond. codes on Op1 + Op2 -ARM_orr, // C Rd = Op1 | Op2 -ARM_mov, // D Rd = Op2 -ARM_bic, // E Rd = Op1 & ~Op2 -ARM_mvn, // F Rd = ~Op2 -ARM_mrs, // Transfer PSR to Register -ARM_msr, // Transfer Register to PSR -ARM_mul, // Multiply -ARM_mla, // Multiply-Accumulate -ARM_ldr, // Load from Memory -ARM_ldrpc, // Indirect Jump -ARM_str, // Store to Memory -ARM_ldm, // Load Block from Memory -ARM_stm, // Store Block to Memory -ARM_swp, // Single Data Swap -ARM_svc, // Supervisor call - -// Version 4 - -ARM_smull, // Signed Multiply long -ARM_smlal, // Signed Multiply-Accumulate long -ARM_umull, // Unsigned Multiply long -ARM_umlal, // Unsigned Multiply-Accumulate long -ARM_bx, // Branch to/from Thumb mode -ARM_pop, // Pop registers -ARM_push, // Push registers -ARM_adr, // Load address - -// Version 5 - -ARM_bkpt, // Breakpoint -ARM_blx1, // Branch with Link and Exchange (immediate address) -ARM_blx2, // Branch with Link and Exchange (register indirect) -ARM_clz, // Count Leading Zeros - -// Version 5E - -ARM_ldrd, // Load pair of registers -ARM_pld, // Prepare to load data -ARM_qadd, // Saturated addition -ARM_qdadd, // Saturated addition with doubling -ARM_qdsub, // Saturated subtraction with doubling -ARM_qsub, // Saturated subtraction -ARM_smlabb, // Signed multiply-accumulate (bottom*bottom) -ARM_smlatb, // Signed multiply-accumulate (top*bottom) -ARM_smlabt, // Signed multiply-accumulate (bottom*top) -ARM_smlatt, // Signed multiply-accumulate (top*top) -ARM_smlalbb, // Long signed multiply-accumulate (bottom*bottom) -ARM_smlaltb, // Long signed multiply-accumulate (top*bottom) -ARM_smlalbt, // Long signed multiply-accumulate (bottom*top) -ARM_smlaltt, // Long signed multiply-accumulate (top*top) -ARM_smlawb, // Wide signed multiply-accumulate (bottom) -ARM_smulwb, // Wide signed multiply (bottom) -ARM_smlawt, // Wide signed multiply-accumulate (top) -ARM_smulwt, // Wide signed multiply (top) -ARM_smulbb, // Signed multiply (bottom*bottom) -ARM_smultb, // Signed multiply (top*bottom) -ARM_smulbt, // Signed multiply (bottom*top) -ARM_smultt, // Signed multiply (top*top) -ARM_strd, // Store pair of registers - -// Intel xScale coprocessor instructions - -xScale_mia, // Multiply-Internal Accumulate -xScale_miaph, // Multiply-Internal Accumulate Packed HalfWords -xScale_miabb, // Multiply-Internal Accumulate Bottom-Bottom Halves -xScale_miabt, // Multiply-Internal Accumulate Bottom-Top Halves -xScale_miatb, // Multiply-Internal Accumulate Top-Bottom Halves -xScale_miatt, // Multiply-Internal Accumulate Top-Top Halves -xScale_mar, // Move To Internal Accumulator -xScale_mra, // Move From Internal Accumulator - -// Macro instructions - -ARM_movl, // Move immediate to register -ARM_adrl, // Load address -ARM_swbkpt, // WinCE Debugger break - -// Coprocessor instructions - -ARM_cdp, // Coprocessor Data Processing -ARM_cdp2, // Coprocessor Data Processing -ARM_ldc, // Load Coprocessor Register -ARM_ldc2, // Load Coprocessor Register -ARM_stc, // Store Coprocessor Register -ARM_stc2, // Store Coprocessor Register -ARM_mrc, // Move from Coprocessor to ARM Register -ARM_mrc2, // Move from Coprocessor to ARM Register -ARM_mcr, // Move from ARM to Coprocessor Register -ARM_mcr2, // Move from ARM to Coprocessor Register -ARM_mcrr, // Copy pair of registers to coprocessor (5E) -ARM_mrrc, // Copy pair of registers from coprocessor (5E) - -// VFP instructions - -ARM_fabsd, // Floating point Absolute Value, Double precision -ARM_fabss, // Floating point Absolute Value, Single precision -ARM_faddd, // Floating point Addition, Double precision -ARM_fadds, // Floating point Addition, Single precision -ARM_fcmpd, // Floating point Compare, Double precision -ARM_fcmps, // Floating point Compare, Single precision -ARM_fcmped, // Floating point Compare (NaN Exceptions), Double precision -ARM_fcmpes, // Floating point Compare (NaN Exceptions), Single precision -ARM_fcmpezd, // Floating point Compare (NaN Exceptions) with Zero, Double precision -ARM_fcmpezs, // Floating point Compare (NaN Exceptions) with Zero, Single precision -ARM_fcmpzd, // Floating point Compare with Zero, Double precision -ARM_fcmpzs, // Floating point Compare with Zero, Single precision -ARM_fcpyd, // Floating point Copy, Double precision -ARM_fcpys, // Floating point Copy, Single precision -ARM_fcvtsd, // Floating point Convert to Single precision from Double precision -ARM_fcvtds, // Floating point Convert to Double precision from Single precision -ARM_fdivd, // Floating point Divide, Double precision -ARM_fdivs, // Floating point Divide, Single precision -ARM_fldd, // Floating point Load, Double precision -ARM_flds, // Floating point Load, Single precision -ARM_fldmd, // Floating point Load Multiple, Double precision -ARM_fldms, // Floating point Load Multiple, Single precision -ARM_fldmx, // Floating point Load Multiple, Unknown precision -ARM_fmacd, // Floating point Multiply and Accumulate, Double precision -ARM_fmacs, // Floating point Multiply and Accumulate, Single precision -ARM_fmscd, // Floating point Multiply and Subtract, Double precision -ARM_fmscs, // Floating point Multiply and Subtract, Single precision -ARM_fmstat, // Floating point Move Status -ARM_fmuld, // Floating point Multiply, Double precision -ARM_fmuls, // Floating point Multiply, Single precision -ARM_fnegd, // Floating point Negate, Double precision -ARM_fnegs, // Floating point Negate, Single precision -ARM_fnmacd, // Floating point Negated Multiply and Accumulate, Double precision -ARM_fnmacs, // Floating point Negated Multiply and Accumulate, Single precision -ARM_fnmscd, // Floating point Negated Multiply and Subtract, Double precision -ARM_fnmscs, // Floating point Negated Multiply and Subtract, Single precision -ARM_fnmuld, // Floating point Negated Multiply, Double precision -ARM_fnmuls, // Floating point Negated Multiply, Single precision -ARM_fsitod, // Floating point Convert Signed Integer to Double precision -ARM_fsitos, // Floating point Convert Signed Integer to Single precision -ARM_fsqrtd, // Floating point Square Root, Double precision -ARM_fsqrts, // Floating point Square Root, Single precision -ARM_fstd, // Floating point Store, Double precision -ARM_fsts, // Floating point Store, Single precision -ARM_fstmd, // Floating point Store Multiple, Double precision -ARM_fstms, // Floating point Store Multiple, Single precision -ARM_fstmx, // Floating point Store Multiple, Unknown precision -ARM_fsubd, // Floating point Subtract, Double precision -ARM_fsubs, // Floating point Subtract, Single precision -ARM_ftosid, // Floating point Convert to Signed Integer from Double precision -ARM_ftosis, // Floating point Convert to Signed Integer from Single precision -ARM_ftosizd, // Floating point Convert to Signed Integer from Double precision, RZ mode -ARM_ftosizs, // Floating point Convert to Signed Integer from Single precision, RZ mode -ARM_ftouid, // Floating point Convert to Unsigned Integer from Double precision -ARM_ftouis, // Floating point Convert to Unsigned Integer from Single precision -ARM_ftouizd, // Floating point Convert to Unsigned Integer from Double precision, RZ mode -ARM_ftouizs, // Floating point Convert to Unsigned Integer from Single precision, RZ mode -ARM_fuitod, // Floating point Convert Unsigned Integer to Double precision -ARM_fuitos, // Floating point Convert Unsigned Integer to Single precision -ARM_fmdhr, // Floating point Move to Double precision High from Register -ARM_fmrdh, // Floating point Move to Register from Double precision High -ARM_fmdlr, // Floating point Move to Double precision Low from Register -ARM_fmrdl, // Floating point Move to Register from Double precision Low -ARM_fmxr, // Floating point Move to System Register from Register -ARM_fmrx, // Floating point Move to Register from System Register -ARM_fmsr, // Floating point Move to Single precision from Register -ARM_fmrs, // Floating point Move to Register from Single precision - -// VFP ARMv5TE extensions - -ARM_fmdrr, // Floating point Move to Double precision from two Registers -ARM_fmrrd, // Floating point Move to two Registers from Double precision -ARM_fmsrr, // Floating point Move to two Single precision from two Registers -ARM_fmrrs, // Floating point Move to two Registers from two Single precision - -// ARM v5J instructions - -ARM_bxj, // Branch to Jazelle - -// ARM v6 instructions - -ARM_mcrr2, // Move to Coprocessor from two ARM Registers -ARM_mrrc2, // Move to two ARM Registers from Coprocessor -ARM_cps, // Change Processor State -ARM_cpsid, // Disable Interrupts -ARM_cpsie, // Enable Interrupts -ARM_ldrex, // Load Register Exclusive -ARM_pkhbt, // Pack halfword bottom + top -ARM_pkhtb, // Pack halfword top + bottom -ARM_qadd16, // Signed saturating arithmetic hafword-wise addition -ARM_qadd8, // Signed saturating arithmetic byte-wise addition -ARM_qaddsubx, // Signed saturating arithmetic exchange, add, substract -ARM_qsub16, // Signed saturating arithmetic hafword-wise substraction -ARM_qsub8, // Signed saturating arithmetic byte-wise substraction -ARM_qsubaddx, // Signed saturating arithmetic exchange, substract, add -ARM_rev, // Byte Reverse Word -ARM_rev16, // Byte Reverse Packed Halfword -ARM_revsh, // Byte Reverse Signed Halfword -ARM_rfe, // Return from exception -ARM_sadd16, // Signed arithmetic modulo hafword-wise addition -ARM_sadd8, // Signed arithmetic modulo byte-wise addition -ARM_saddsubx, // Signed arithmetic modulo exchange, add, substract -ARM_sel, // Select bytes -ARM_setend, // Set Byte Endianness -ARM_shadd16, // Signed arithmetic hafword-wise addition, halving results -ARM_shadd8, // Signed arithmetic byte-wise addition, halving results -ARM_shaddsubx, // Signed arithmetic exchange, add, substract, halving results -ARM_shsub16, // Signed arithmetic hafword-wise substraction, halving results -ARM_shsub8, // Signed arithmetic byte-wise substraction, halving results -ARM_shsubaddx, // Signed arithmetic exchange, substract, add, halving results -ARM_smlad, // Dual signed multiply, add and accumulate -ARM_smladx, // Dual signed multiply, add and accumulate crossed -ARM_smuad, // Dual signed multiply and add -ARM_smuadx, // Dual signed multiply and add crossed -ARM_smlald, // Dual signed multiply, add and accumulate long -ARM_smlaldx, // Dual signed multiply, add and accumulate long crossed -ARM_smlsd, // Dual signed multiply, substract and accumulate -ARM_smlsdx, // Dual signed multiply, substract and accumulate crossed -ARM_smusd, // Dual signed multiply and substract -ARM_smusdx, // Dual signed multiply and substract crossed -ARM_smlsld, // Dual signed multiply, substract and accumulate long -ARM_smlsldx, // Dual signed multiply, substract and accumulate long crossed -ARM_smmla, // Signed most significant word multiply and accumulate truncated -ARM_smmlar, // Signed most significant word multiply and accumulate rounded -ARM_smmul, // Signed most significant word multiply truncated -ARM_smmulr, // Signed most significant word multiply rounded -ARM_smmls, // Signed most significant word multiply and substract truncated -ARM_smmlsr, // Signed most significant word multiply and substract rounded -ARM_srs, // Store Return State -ARM_ssat, // Signed Saturate -ARM_ssat16, // Signed saturate two halfwords -ARM_ssub16, // Signed arithmetic hafword-wise substraction -ARM_ssub8, // Signed arithmetic byte-wise substraction -ARM_ssubaddx, // Signed arithmetic exchange, substract, add -ARM_strex, // Store Register Exclusive -ARM_sxtab, // Signed extend byte to word, add -ARM_sxtb, // Signed extend byte to word -ARM_sxtab16, // Signed extend two bytes to halfwords, add -ARM_sxtb16, // Signed extend two bytes to halfwords -ARM_sxtah, // Signed extend halfword to word, add -ARM_sxth, // Signed extend halfword to word -ARM_uadd16, // Unsigned arithmetic modulo hafword-wise addition -ARM_uadd8, // Unsigned arithmetic modulo byte-wise addition -ARM_uaddsubx, // Unsigned arithmetic modulo exchange, add, substract -ARM_uhadd16, // Unsigned arithmetic hafword-wise addition, halving results -ARM_uhadd8, // Unsigned arithmetic byte-wise addition, halving results -ARM_uhaddsubx, // Unsigned arithmetic exchange, add, substract, halving results -ARM_uhsub16, // Unsigned arithmetic hafword-wise substraction, halving results -ARM_uhsub8, // Unsigned arithmetic byte-wise substraction, halving results -ARM_uhsubaddx, // Unsigned arithmetic exchange, substract, add, halving results -ARM_umaal, // Multiply unsigned double accumulate long -ARM_uqadd16, // Unsigned saturating arithmetic hafword-wise addition -ARM_uqadd8, // Unsigned saturating arithmetic byte-wise addition -ARM_uqaddsubx, // Unsigned saturating arithmetic exchange, add, substract -ARM_uqsub16, // Unsigned saturating arithmetic hafword-wise substraction -ARM_uqsub8, // Unsigned saturating arithmetic byte-wise substraction -ARM_uqsubaddx, // Unsigned saturating arithmetic exchange, substract, add -ARM_usada8, // Unsigned sum of absolute differences and accumulate -ARM_usad8, // Unsigned sum of absolute differences -ARM_usat, // Unsigned saturate word -ARM_usat16, // Unsigned saturate two halfwords -ARM_usub16, // Unsigned arithmetic hafword-wise substraction -ARM_usub8, // Unsigned arithmetic byte-wise substraction -ARM_usubaddx, // Unsigned arithmetic exchange, substract, add -ARM_uxtab, // Unsigned extend byte to word, add -ARM_uxtb, // Unsigned extend byte to word -ARM_uxtab16, // Unsigned extend two bytes to halfwords, add -ARM_uxtb16, // Unsigned extend two bytes to halfwords -ARM_uxtah, // Unsigned extend halfword to word, add -ARM_uxth, // Unsigned extend halfword to word - -// ARM v6zk instructions - -ARM_clrex, // Clear Exclusive -ARM_ldrexb, // Load Byte Exclusive -ARM_ldrexd, // Load DoubleWord Exclusive -ARM_ldrexh, // Load Halfword Exclusive -ARM_strexb, // Store Byte Exclusive -ARM_strexd, // Store DoubleWord Exclusive -ARM_strexh, // Store Halfword Exclusive -ARM_yield, // Yield (hint) -ARM_sev, // Send Event (hint) -ARM_wfe, // Wait For Event (hint) -ARM_wfi, // Wait For Interrupt (hint) -ARM_smc, // Secure Monitor Call - -// ARM Thumb32 instructions - -ARM_orn, // Rd = Op1 | ~Op2 -ARM_movt, // Move Top -ARM_sbfx, // Signed Bit Field Extract -ARM_ubfx, // Unsigned Bit Field Extract -ARM_bfi, // Bit Field Insert -ARM_bfc, // Bit Field Clear -ARM_tbb, // Table Branch Byte -ARM_tbh, // Table Branch Halfword -ARM_pli, // Prepare to load code -ARM_rbit, // Reverse Bits -ARM_it, // If Then -ARM_mls, // Multiply and Subtract -ARM_sdiv, // Signed Divide -ARM_udiv, // Unsigned Divide -ARM_cbz, // Compare and Branch on Zero -ARM_cbnz, // Compare and Branch on Non-Zero -ARM_dsb, // Data Synchronization Barrier -ARM_dmb, // Data Memory Barrier -ARM_isb, // Instruction Synchronization Barrier -ARM_dbg, // Debug Hint - -ARM_und, // Architecturally undefined instruction - -// missing instructions (not yet decoded) - -ARM_rrx, // Rotate Right with Extend -ARM_enterx, // Enter ThumbEE state -ARM_leavex, // Leave ThumbEE state -ARM_chka, // Check Array -ARM_hb, // Handler Branch -ARM_hbl, // Handler Branch with Link -ARM_hblp, // Handler Branch with Link and Parameter -ARM_hbp, // Handler Branch with Parameter - -// NEON (Advanced SIMD) and extra VFP instructions - -ARM_vaba, // Vector Absolute Difference and Accumulate -ARM_vabal, // Vector Absolute Difference and Accumulate Long -ARM_vabd, // Vector Absolute Difference -ARM_vabdl, // Vector Absolute Difference Long -ARM_vabs, // Vector Absolute -ARM_vacge, // Vector Absolute Compare Greater Than or Equal -ARM_vacgt, // Vector Absolute Compare Greater Than -ARM_vacle, // Vector Absolute Compare Less Than or Equal -ARM_vaclt, // Vector Absolute Compare Less Than -ARM_vadd, // Vector Add -ARM_vaddhn, // Vector Add and Narrow, returning High Half -ARM_vaddl, // Vector Add Long -ARM_vaddw, // Vector Add Wide -ARM_vand, // Vector Bitwise AND -ARM_vbic, // Vector Bitwise Bit Clear -ARM_vbif, // Vector Bitwise Insert if False -ARM_vbit, // Vector Bitwise Insert if True -ARM_vbsl, // Vector Bitwise Select -ARM_vceq, // Vector Compare Equal -ARM_vcge, // Vector Compare Greater Than or Equal -ARM_vcgt, // Vector Compare Greater Than -ARM_vcle, // Vector Compare Less Than or Equal -ARM_vcls, // Vector Count Leading Sign Bits -ARM_vclt, // Vector Compare Less Than -ARM_vclz, // Vector Count Leading Zeros -ARM_vcmp, // Vector Compare -ARM_vcmpe, // Vector Compare (Quiet NaNs trigger Exception) -ARM_vcnt, // Vector Count Number of Bits -ARM_vcvt, // Vector Convert -ARM_vcvtr, // Vector Convert Rounding -ARM_vcvtb, // Vector Convert Half-Precision Bottom -ARM_vcvtt, // Vector Convert Half-Precision Top -ARM_vdiv, // Vector Divide -ARM_vdup, // Vector Duplicate -ARM_veor, // Vector Bitwise Exclusive OR -ARM_vext, // Vector Extract -ARM_vfma, // Vector Fused Multiply Accumulate -ARM_vfms, // Vector Fused Multiply Substract -ARM_vfnma, // Vector Fused Negated Multiply Accumulate -ARM_vfnms, // Vector Fused Negated Multiply Substract -ARM_vhadd, // Vector Halving Add -ARM_vhsub, // Vector Halving Sub -ARM_vld1, // Vector Load Single Element -ARM_vld2, // Vector Load Two-Element Structures -ARM_vld3, // Vector Load Three-Element Structures -ARM_vld4, // Vector Load Four-Element Structures -ARM_vldm, // Vector Load Multiple -ARM_vldr, // Vector Load Register -ARM_vmax, // Vector Maximum -ARM_vmin, // Vector Minimum -ARM_vmla, // Vector Multiply Accumulate -ARM_vmlal, // Vector Multiply Accumulate Long -ARM_vmls, // Vector Multiply Subtract -ARM_vmlsl, // Vector Multiply Subtract Long -ARM_vmov, // Vector Move -ARM_vmovl, // Vector Move Long -ARM_vmovn, // Vector Move and Narrow -ARM_vmrs, // Move FPSCR to ARM Register -ARM_vmsr, // Move to FPSCR from ARM Register -ARM_vmul, // Vector Multiply -ARM_vmull, // Vector Multiply Long -ARM_vmvn, // Vector Bitwise NOT -ARM_vneg, // Vector Negate -ARM_vnmla, // Vector Multiply Add Negated -ARM_vnmls, // Vector Multiply Substract Negated -ARM_vnmul, // Vector Multiply Negated -ARM_vorn, // Vector Bitwise OR NOT -ARM_vorr, // Vector Bitwise OR -ARM_vpadal, // Vector Pairwise Add and Accumulate Long -ARM_vpadd, // Vector Pairwise Add -ARM_vpaddl, // Vector Pairwise Add Long -ARM_vpmax, // Vector Pairwise Maximum -ARM_vpmin, // Vector Pairwise Minimum -ARM_vpop, // Vector Pop -ARM_vpush, // Vector Push -ARM_vqabs, // Vector Saturating Absolute -ARM_vqadd, // Vector Saturating Add -ARM_vqdmlal, // Vector Saturating Doubling Multiply Accumulate Long -ARM_vqdmlsl, // Vector Saturating Doubling Multiply Subtract Long -ARM_vqdmulh, // Vector Saturating Doubling Multiply Returning High Half -ARM_vqdmull, // Vector Saturating Doubling Multiply Long -ARM_vqmovn, // Vector Saturating Move and Narrow -ARM_vqmovun, // Vector Saturating Move and Narrow, Unsigned result -ARM_vqneg, // Vector Saturating Negate -ARM_vqrdmulh, // Vector Saturating Rounding Doubling Multiply Returning High Half -ARM_vqrshl, // Vector Saturating Rounding Shift Left -ARM_vqrshrn, // Vector Saturating Rounding Shift Right, Narrow -ARM_vqrshrun, // Vector Saturating Rounding Shift Right, Narrow, Unsigned result -ARM_vqshl, // Vector Saturating Shift Left -ARM_vqshlu, // Vector Saturating Shift Left, Unsigned result -ARM_vqshrn, // Vector Saturating Shift Right, Narrow -ARM_vqshrun, // Vector Saturating Shift Right, Narrow, Unsigned result -ARM_vqsub, // Vector Saturating Subtract -ARM_vraddhn, // Vector Rounding Add and Narrow, returning High Half -ARM_vrecpe, // Vector Reciprocal Estimate -ARM_vrecps, // Vector Reciprocal Step -ARM_vrev16, // Vector Reverse in halfwords -ARM_vrev32, // Vector Reverse in words -ARM_vrev64, // Vector Reverse in doublewords -ARM_vrhadd, // Vector Rounding Halving Add -ARM_vrshl, // Vector Rounding Shift Left -ARM_vrshr, // Vector Rounding Shift Right -ARM_vrshrn, // Vector Rounding Shift Right and Narrow -ARM_vrsqrte, // Vector Reciprocal Square Root Estimate -ARM_vrsqrts, // Vector Reciprocal Square Root Step -ARM_vrsra, // Vector Rounding Shift Right and Accumulate -ARM_vrsubhn, // Vector Rounding Subtract and Narrow, returning High Half -ARM_vshl, // Vector Shift Left -ARM_vshll, // Vector Shift Left Long -ARM_vshr, // Vector Shift Right -ARM_vshrn, // Vector Shift Right Narrow -ARM_vsli, // Vector Shift Left and Insert -ARM_vsqrt, // Vector Square Root -ARM_vsra, // Vector Shift Right and Accumulate -ARM_vsri, // Vector Shift Right and Insert -ARM_vst1, // Vector Store Single Element -ARM_vst2, // Vector Store Two-Element Structures -ARM_vst3, // Vector Store Three-Element Structures -ARM_vst4, // Vector Store Four-Element Structures -ARM_vstm, // Vector Store Multiple -ARM_vstr, // Vector Store Register -ARM_vsub, // Vector Subtract -ARM_vsubhn, // Vector Subtract and Narrow, returning High Half -ARM_vsubl, // Vector Subtract Long -ARM_vsubw, // Vector Subtract Wide -ARM_vswp, // Vector Swap -ARM_vtbl, // Vector Table Lookup -ARM_vtbx, // Vector Table Extension -ARM_vtrn, // Vector Transpose -ARM_vtst, // Vector Test Bits -ARM_vuzp, // Vector Unzip -ARM_vzip, // Vector Zip - -// ARMv7 Hypervisor extensions - -ARM_eret, // Exception Return -ARM_hvc, // Hypervisor Call - -// new ARMv8 instructions for A32 and T32 mode - -ARM_lda, // Load-Acquire Word/Byte/Halfword -ARM_stl, // Store-Release Word/Byte/Halfword -ARM_ldaex, // Load-Acquire Exclusive Word/Byte/Halfword -ARM_stlex, // Store-Release Exclusive Word/Byte/Halfword -ARM_vsel, // Floating-point Conditional Select - -ARM_vmaxnm, // Vector Maximum Numeric -ARM_vminnm, // Vector Minimum Numeric -ARM_vcvta, // Vector Convert Round to Nearest with Ties to Away -ARM_vcvtn, // Vector Convert Round to Nearest with Ties to Even -ARM_vcvtp, // Vector Convert Round towards +Infinity -ARM_vcvtm, // Vector Convert Round towards -Infinity -ARM_vrintx, // Vector Round to Integral, FPSCR rounding mode and signaling inexactness -ARM_vrintr, // Vector Round to Integral, FPSCR rounding mode -ARM_vrintz, // Vector Round to Integral, Round toward Zero -ARM_vrinta, // Vector Round to Integral, Round to Nearest with Ties to Away -ARM_vrintn, // Vector Round to Integral, Round to Nearest with Ties to Even -ARM_vrintp, // Vector Round to Integral, Round towards +Infinity -ARM_vrintm, // Vector Round to Integral, Round towards -Infinity - -ARM_aesd, // AES single round decryption -ARM_aese, // AES single round encryption -ARM_aesimc, // AES inverse mix columns -ARM_aesmc, // AES mix columns -ARM_sha1c, // SHA1 hash update accelerator, choose -ARM_sha1m, // SHA1 hash update accelerator, majority -ARM_sha1p, // SHA1 hash update accelerator, parity -ARM_sha1h, // SHA1 hash update accelerator, rotate left by 30 -ARM_sha1su0, // SHA1 schedule update accelerator, first part -ARM_sha1su1, // SHA1 schedule update accelerator, second part -ARM_sha256h, // SHA256 hash update accelerator -ARM_sha256h2, // SHA256 hash update accelerator upper part -ARM_sha256su0, // SHA256 schedule update accelerator, first part -ARM_sha256su1, // SHA256 schedule update accelerator, second part - -ARM_dcps1, // Debug Change Processor State to EL1 -ARM_dcps2, // Debug Change Processor State to EL2 -ARM_dcps3, // Debug Change Processor State to EL3 -ARM_hlt, // Halting mode software breakpoint -ARM_sevl, // Send Event Locally - -// ARMv8 AArch64 new instructions - -ARM_tbz, // Test and Branch Zero -ARM_tbnz, // Test and Branch Non-Zero -ARM_br, // Branch To Register -ARM_blr, // Branch and Link Register -ARM_ldur, // Load Single Register (unscaled offset) -ARM_stur, // Store Single Register (unscaled offset) -ARM_ldp, // Load Pair -ARM_stp, // Store Pair -ARM_ldnp, // Load Non-temporal Pair -ARM_stnp, // Store Non-temporal Pair -ARM_ldtr, // Load Unprivileged Register -ARM_sttr, // Store Unprivileged Register -ARM_ldxr, // Load Exclusive Register -ARM_stxr, // Store Exclusive Register -ARM_ldxp, // Load Exclusive Pair -ARM_stxp, // Store Exclusive Pair -ARM_ldar, // Load-Acquire Register -ARM_stlr, // Store-Release Register -ARM_ldaxr, // Load-Acquire Exclusive Register -ARM_stlxr, // Store-Release Exclusive Register -ARM_ldaxp, // Load-Acquire Exclusive Pair -ARM_stlxp, // Store Exclusive Pair -ARM_prfm, // Prefetch Memory -ARM_prfum, // Prefetch Memory (unscaled offset) -ARM_movi, // Move Immediate -ARM_mvni, // Move Inverted Immediate -ARM_movz, // Move with Zero -ARM_movn, // Move with Not -ARM_movk, // Move with Keep -ARM_adrp, // Address of Page -ARM_bfm, // Bitfield Move -ARM_sbfm, // Signed Bitfield Move -ARM_ubfm, // Unsigned Bitfield Move -//ARM_bfi, // Bitfield Insert -ARM_bfxil, // Bitfield Extract and Insert Low -ARM_sbfiz, // Signed Bitfield Insert in Zero -//ARM_sbfx, // Signed Bitfield Extract -ARM_ubfiz, // Signed Bitfield Insert in Zero -//ARM_ubfx, // Unsigned Bitfield Extract -ARM_extr, // Extract -ARM_sxtw, // Signed Extend Word -ARM_uxtw, // Unsigned Extend Word (non-existing insn) -ARM_eon, // Bitwise exclusive OR NOT -ARM_not, // Bitwise NOT -ARM_cls, // Count Leading Sign Bits -ARM_rev32, // Reverse Bytes in Words -ARM_csel, // Conditional Select -ARM_csinc, // Conditional Select Increment -ARM_csinv, // Conditional Select Invert -ARM_csneg, // Conditional Select Negate -ARM_cset, // Conditional Set -ARM_csetm, // Conditional Set Mask -ARM_cinc, // Conditional Increment -ARM_cinv, // Conditional Invert -ARM_cneg, // Conditional Negate -ARM_ngc, // Negate with Carry -ARM_ccmn, // Conditional Compare Negative -ARM_ccmp, // Conditional Compare -ARM_madd, // Multiply-Add -ARM_msub, // Multiply-Subtract -ARM_mneg, // Multiply-Negate -ARM_smaddl, // Signed Multiply-Add Long -ARM_smsubl, // Signed Multiply-Subtract Long -ARM_smnegl, // Signed Multiply-Negate Long -ARM_smulh, // Signed Multiply High -ARM_umaddl, // Unsigned Multiply-Add Long -ARM_umsubl, // Unsigned Multiply-Subtract Long -ARM_umnegl, // Unsigned Multiply-Negate Long -ARM_umulh, // Unsigned Multiply High - -ARM_drps, // Debug Restore Processor State -ARM_sys, // System Maintenance Operation -ARM_sysl, // System Maintenance Operation With Result -ARM_ic, // Instruction Cache Maintenance -ARM_dc, // Data Cache Maintenance -ARM_at, // Address Translation -ARM_tlbi, // TLB Invalidation -ARM_hint, // Hint instruction -ARM_brk, // Monitor debug-mode breakpoint - -// AArch64 Advanced SIMD -ARM_uaba, // Unsigned Integer Absolute Difference and Accumulate -ARM_saba, // Signed Integer Absolute Difference and Accumulate -ARM_uabal, // Unsigned Integer Absolute Difference and Accumulate Long -ARM_uabal2, // Unsigned Integer Absolute Difference and Accumulate Long (Second Part) -ARM_sabal, // Signed Integer Absolute Difference and Accumulate Long -ARM_sabal2, // Signed Integer Absolute Difference and Accumulate Long (Second Part) -ARM_uabd, // Unsigned Integer Absolute Difference -ARM_sabd, // Signed Integer Absolute Difference -ARM_fabd, // Floating-point Absolute Difference -ARM_uabdl, // Unsigned Integer Absolute Difference Long -ARM_uabdl2, // Unsigned Integer Absolute Difference Long (Second Part) -ARM_sabdl, // Signed Integer Absolute Difference Long -ARM_sabdl2, // Signed Integer Absolute Difference Long (Second Part) -ARM_abs, // Integer Absolute Value -ARM_fabs, // Floating-point Absolute Value -ARM_facge, // Floating-point Absolute Compare Greater Than or Equal -ARM_facgt, // Floating-point Absolute Compare Greater Than -ARM_facle, // Floating-point Absolute Compare Less Than or Equal -ARM_faclt, // Floating-point Absolute Compare Less Than -ARM_fadd, // Floating-point Add -ARM_addhn, // Integer Vector Add and Narrow High Half -ARM_addhn2, // Integer Vector Add and Narrow High Half (second part) -ARM_uaddl, // Unsigned Integer Add Long -ARM_uaddl2, // Unsigned Integer Add Long (second part) -ARM_saddl, // Signed Integer Add Long -ARM_saddl2, // Signed Integer Add Long (second part) -ARM_uaddw, // Unsigned Integer Add Wide -ARM_uaddw2, // Unsigned Integer Add Wide (second part) -ARM_saddw, // Signed Integer Add Wide -ARM_saddw2, // Signed Integer Add Wide (second part) -ARM_bif, // Bitwise Vector Insert if False -ARM_bit, // Bitwise Vector Insert if True -ARM_bsl, // Bitwise Vector Select -ARM_cmeq, // Ingeger Vector Compare Equal -ARM_fcmeq, // Floating-point Vector Compare Equal -ARM_cmhs, // Unsigned Compare Greater Than or Equal -ARM_cmge, // Signed Compare Greater Than or Equal -ARM_fcmge, // Floating-point Compare Greater Than or Equal -ARM_cmhi, // Unsigned Compare Greater Than -ARM_cmgt, // Signed Compare Greater Than -ARM_fcmgt, // Floating-point Compare Greater Than -ARM_cmls, // Unsigned Compare Less Than or Equal -ARM_cmle, // Signed Compare Less Than or Equal -ARM_fcmle, // Floating-point Compare Less Than or Equal -ARM_cmlo, // Unsigned Compare Less Than -ARM_cmlt, // Signed Compare Less Than -ARM_fcmlt, // Floating-point Compare Less Than -ARM_fcmp, // Floating-point Compare -ARM_fcmpe, // Floating-point Signaling Compare -ARM_fccmp, // Floating-point Conditional Quiet Compare -ARM_fccmpe, // Floating-point Conditional Signaling Compare -ARM_fcsel, // Floating-point Conditional Select -ARM_cnt, // Vector Count Non-zero Bits -ARM_fcvt, // Floating-point convert precision (scalar) -ARM_fcvtzs, // Convert Floating-point to Signed Integer (Round to Zero) -ARM_fcvtas, // Convert Floating-point to Signed Integer (Round to Nearest, Ties to Away) -ARM_fcvtns, // Convert Floating-point to Signed Integer (Round to Nearest, Ties to Even) -ARM_fcvtps, // Convert Floating-point to Signed Integer (Round towards +Infinity) -ARM_fcvtms, // Convert Floating-point to Signed Integer (Round towards -Infinity) -ARM_fcvtzu, // Convert Floating-point to Unsigned Integer (Round to Zero) -ARM_fcvtau, // Convert Floating-point to Unsigned Integer (Round to Nearest, Ties to Away) -ARM_fcvtnu, // Convert Floating-point to Unsigned Integer (Round to Nearest, Ties to Even) -ARM_fcvtpu, // Convert Floating-point to Unsigned Integer (Round towards +Infinity) -ARM_fcvtmu, // Convert Floating-point to Unsigned Integer (Round towards -Infinity) -ARM_ucvtf, // Convert Unsigned Integer to Floating-point -ARM_scvtf, // Convert Signed Integer to Floating-point -ARM_fcvtn, // Floating-point Convert Precision, Narrow -ARM_fcvtn2, // Floating-point Convert Precision, Narrow (second part) -ARM_fcvtl, // Floating-point Convert Precision, Long -ARM_fcvtl2, // Floating-point Convert Precision, Long (second part) -ARM_fcvtxn, // Floating-point Convert Precision, Narrow (Round to Odd) -ARM_fcvtxn2, // Floating-point Convert Precision, Narrow (Round to Odd) (second part) -ARM_frinta, // Floating-point Round to Integral (Round to Nearest, Ties to Away) -ARM_frinti, // Floating-point Round to Integral (using FPCR rounding mode) -ARM_frintm, // Floating-point Round to Integral (Round towards -Infinity) -ARM_frintn, // Floating-point Round to Integral (Round to Nearest, Ties to Even) -ARM_frintp, // Floating-point Round to Integral (Round towards +Infinity) -ARM_frintx, // Floating-point Round to Integral (using FPCR rounding mode, with exactness test) -ARM_frintz, // Floating-point Round to Integral (Round towards Zero) -ARM_fmadd, // Floating-point scalar fused multiply-add -ARM_fmsub, // Floating-point scalar fused multiply-subtract -ARM_fnmadd, // Floating-point scalar negated fused multiply-add -ARM_fnmsub, // Floating-point scalar negated fused multiply-subtract -ARM_fdiv, // Floating-point Divide -ARM_dup, // Duplicate Single Element to All Elements -ARM_ins, // Insert Single Element in Another Element -ARM_ext, // Bitwise Extract -ARM_uhadd, // Unsigned Integer Halving Add -ARM_shadd, // Signed Integer Halving Add -ARM_uhsub, // Unsigned Integer Halving Subtract -ARM_shsub, // Signed Integer Halving Subtract -ARM_ld1, // Vector Load Single Element -ARM_ld2, // Vector Load Two-Element Structures -ARM_ld3, // Vector Load Three-Element Structures -ARM_ld4, // Vector Load Four-Element Structures -ARM_ld1r, // Vector Load Single Element and Replicate -ARM_ld2r, // Vector Load Two-Element Structures and Replicate -ARM_ld3r, // Vector Load Three-Element Structures and Replicate -ARM_ld4r, // Vector Load Four-Element Structures and Replicate -ARM_umax, // Unsigned Integer Maximum -ARM_smax, // Signed Integer Maximum -ARM_fmax, // Floating-point Maximum -ARM_fmaxnm, // Floating-point maxNum() -ARM_umin, // Unsigned Integer Minimum -ARM_smin, // Signed Integer Minimum -ARM_fmin, // Floating-point Minimum -ARM_fminnm, // Floating-point minNum() -ARM_fmla, // Fused Multiply-Add -ARM_umlal2, // Unsigned Integer Multiply-Add Long (second part) -ARM_smlal2, // Signed Integer Multiply-Add Long (second part) -ARM_fmls, // Fused Multiply-Subtract -ARM_umlsl, // Unsigned Integer Multiply-Subtract Long -ARM_umlsl2, // Unsigned Integer Multiply-Subtract Long (second part) -ARM_smlsl, // Signed Integer Multiply-Subtract Long -ARM_smlsl2, // Signed Integer Multiply-Subtract Long (second part) -ARM_umov, // Unsigned Integer Move -ARM_smov, // Signed Integer Move -ARM_fmov, // Floating-point Move -ARM_uxtl, // Unsigned Integer Vector Lengthen -ARM_uxtl2, // Unsigned Integer Vector Lengthen (second part) -ARM_sxtl, // Signed Integer Vector Lengthen -ARM_sxtl2, // Signed Integer Vector Lengthen (second part) -ARM_xtn, // Integer Vector Narrow -ARM_xtn2, // Integer Vector Narrow (second part) -ARM_fmul, // Floating-point Vector Multiply -ARM_pmul, // Polynomial Vector Multiply -ARM_fmulx, // Floating-point Multiply Extended -ARM_fnmul, // Floating-point Multiply-Negate -ARM_umull2, // Unsigned Integer Vector Multiply Long (second part) -ARM_smull2, // Signed Integer Vector Multiply Long (second part) -ARM_pmull, // Polynomial Vector Multiply Long -ARM_pmull2, // Polynomial Vector Multiply Long (second part) -ARM_fneg, // Floating-point Negate -ARM_uadalp, // Unsigned Integer Vector Add and Accumulate Long Pair -ARM_sadalp, // Signed Integer Vector Add and Accumulate Long Pair -ARM_addp, // Integer Vector Add Pair -ARM_faddp, // Floating-point Vector Add Pair -ARM_uaddlp, // Unsigned Integer Vector Add Long Pair -ARM_saddlp, // Signed Integer Vector Add Long Pair -ARM_umaxp, // Unsigned Integer Maximum Pair -ARM_smaxp, // Signed Integer Maximum Pair -ARM_fmaxp, // Floating-point Maximum Pair -ARM_fmaxnmp, // Floating-point maxNum Pair -ARM_uminp, // Unsigned Integer Minimum Pair -ARM_sminp, // Signed Integer Minimum Pair -ARM_fminp, // Floating-point Minimum Pair -ARM_fminnmp, // Floating-point minNum Pair -ARM_sqabs, // Signed Integer Saturating Absolute -ARM_uqadd, // Unsigned Integer Saturating Add -ARM_sqadd, // Signed Integer Saturating Add -ARM_suqadd, // Signed Integer Saturating Accumulate of Unsigned Values -ARM_usqadd, // Unsigned Integer Saturating Accumulate of Signed Values -ARM_sqdmlal, // Signed Integer Saturating Doubling Multiply Add Long -ARM_sqdmlal2, // Signed Integer Saturating Doubling Multiply Add Long (second part) -ARM_sqdmlsl, // Signed Integer Saturating Doubling Multiply Subtract Long -ARM_sqdmlsl2, // Signed Integer Saturating Doubling Multiply Subtract Long (second part) -ARM_sqdmulh, // Signed Integer Saturating Doubling Multiply Returning High Half -ARM_sqdmull, // Signed Integer Saturating Doubling Multiply Long -ARM_sqdmull2, // Signed Integer Saturating Doubling Multiply Long (second part) -ARM_uqxtn, // Unsigned Integer Saturating Vector Narrow -ARM_uqxtn2, // Unsigned Integer Saturating Vector Narrow (second part) -ARM_sqxtn, // Signed Integer Saturating Vector Narrow -ARM_sqxtn2, // Signed Integer Saturating Vector Narrow (second part) -ARM_sqxtun, // Signed Integer Saturating Vector and Unsigned Narrow -ARM_sqxtun2, // Signed Integer Saturating Vector and Unsigned Narrow (second part) -ARM_sqneg, // Signed Integer Saturating Negate -ARM_sqrdmulh, // Signed Integer Saturating Rounding Doubling Multiply Returning High Half -ARM_uqrshl, // Unsigned Integer Saturating Rounding Shift Left -ARM_sqrshl, // Signed Integer Saturating Rounding Shift Left -ARM_uqrshrn, // Unsigned Integer Saturating Rounding Shift Right, Narrow -ARM_uqrshrn2, // Unsigned Integer Saturating Rounding Shift Right, Narrow (second part) -ARM_sqrshrn, // Signed Integer Saturating Rounding Shift Right, Narrow -ARM_sqrshrn2, // Signed Integer Saturating Rounding Shift Right, Narrow (second part) -ARM_sqrshrun, // Signed Integer Saturating Rounding Shift Right, Narrow, Unsigned result -ARM_sqrshrun2, // Signed Integer Saturating Rounding Shift Right, Narrow, Unsigned result (second part) -ARM_uqshl, // Unsigned Integer Saturating Shift Left -ARM_sqshl, // Signed Integer Saturating Shift Left -ARM_sqshlu, // Signed Integer Saturating Shift Left, Unsigned result -ARM_uqshrn, // Unsigned Integer Saturating Shift Right, Narrow -ARM_uqshrn2, // Unsigned Integer Saturating Shift Right, Narrow (second part) -ARM_sqshrn, // Signed Integer Saturating Shift Right, Narrow -ARM_sqshrn2, // Signed Integer Saturating Shift Right, Narrow (second part) -ARM_sqshrun, // Signed Integer Saturating Shift Right, Narrow, Unsigned result -ARM_sqshrun2, // Signed Integer Saturating Shift Right, Narrow, Unsigned result (second part) -ARM_uqsub, // Unsigned Integer Saturating Subtract -ARM_sqsub, // Signed Integer Saturating Subtract -ARM_raddhn, // Integer Rounding Add and Narrow, returning High Half -ARM_raddhn2, // Integer Rounding Add and Narrow, returning High Half (second part) -ARM_urecpe, // Unsigned Integer Reciprocal Estimate -ARM_frecpe, // Floating-point Reciprocal Estimate -ARM_frecps, // Floating-point Reciprocal Step -ARM_frecpx, // Floating-point Reciprocal Exponent -ARM_rev64, // Reverse doublewords -ARM_urhadd, // Unsigned Integer Rounding Halving Add -ARM_srhadd, // Signed Integer Rounding Halving Add -ARM_urshl, // Unsigned Integer Rounding Shift Left -ARM_srshl, // Signed Integer Rounding Shift Left -ARM_urshr, // Unsigned Integer Rounding Shift Right -ARM_srshr, // Signed Integer Rounding Shift Right -ARM_rshrn, // Integer Rounding Shift Right and Narrow -ARM_rshrn2, // Integer Rounding Shift Right and Narrow (second part) -ARM_ursqrte, // Unsigned Integer Reciprocal Square Root Estimate -ARM_frsqrte, // Floating-point Reciprocal Square Root Estimate -ARM_frsqrts, // Floating-point Reciprocal Square Root Step -ARM_ursra, // Unsigned Integer Rounding Shift Right and Accumulate -ARM_srsra, // Signed Integer Rounding Shift Right and Accumulate -ARM_rsubhn, // Integer Subtract and Narrow, returning High Half -ARM_rsubhn2, // Integer Subtract and Narrow, returning High Half (second part) -ARM_ushl, // Unsigned Integer Shift Left -ARM_sshl, // Signed Integer Shift Left -ARM_ushll, // Unsigned Integer Shift Left Long -ARM_ushll2, // Unsigned Integer Shift Left Long (second part) -ARM_sshll, // Signed Integer Shift Left Long -ARM_sshll2, // Signed Integer Shift Left Long (second part) -ARM_ushr, // Unsigned Integer Shift Right -ARM_sshr, // Signed Integer Shift Right -ARM_shrn, // Integer Shift Right Narrow -ARM_shrn2, // Integer Shift Right Narrow (second part) -ARM_shl, // Shift Left -ARM_shll, // Shift Left Long -ARM_shll2, // Shift Left Long (second part) -ARM_sli, // Integer Vector Shift Left and Insert -ARM_fsqrt, // Floating-point Square Root -ARM_usra, // Unsigned Integer Shift Right and Accumulate -ARM_ssra, // Signed Integer Shift Right and Accumulate -ARM_sri, // Integer Shift Right and Insert -ARM_st1, // Vector Store Single Element -ARM_st2, // Vector Store Two-Element Structures -ARM_st3, // Vector Store Three-Element Structures -ARM_st4, // Vector Store Four-Element Structures -ARM_fsub, // Floating-point Subtract -ARM_subhn, // Integer Subtract and Narrow, returning High Half -ARM_subhn2, // Integer Subtract and Narrow, returning High Half (second part) -ARM_usubl, // Unsigned Integer Subtract Long -ARM_usubl2, // Unsigned Integer Subtract Long (second part) -ARM_ssubl, // Signed Integer Subtract Long -ARM_ssubl2, // Signed Integer Subtract Long (second part) -ARM_usubw, // Unsigned Integer Subtract Wide -ARM_usubw2, // Unsigned Integer Subtract Wide (second part) -ARM_ssubw, // Signed Integer Subtract Wide -ARM_ssubw2, // Signed Integer Subtract Wide (second part) -ARM_tbl, // Vector Table Lookup -ARM_tbx, // Vector Table Extension -ARM_trn1, // Vector Element Transpose (primary) -ARM_trn2, // Vector Element Transpose (secondary) -ARM_cmtst, // Integer Compare Mask Bitwise Test -ARM_uzp1, // Vector Element Unzip (primary) -ARM_uzp2, // Vector Element Unzip (secondary) -ARM_zip1, // Vector Element Zip (primary) -ARM_zip2, // Vector Element Zip (secondary) -ARM_addv, // Integer Sum Elements in Vector -ARM_uaddlv, // Unsigned Integer Sum Elements in Vector Long -ARM_saddlv, // Signed Integer Sum Elements in Vector Long -ARM_umaxv, // Unsigned Integer Max Element in Vector -ARM_smaxv, // Signed Integer Max Element in Vector -ARM_fmaxv, // Floating-point Max Element in Vector -ARM_fmaxnmv, // Floating-point maxNum Element in Vector -ARM_uminv, // Unsigned Integer Min Element in Vector -ARM_sminv, // Signed Integer Min Element in Vector -ARM_fminv, // Floating-point Min Element in Vector -ARM_fminnmv, // Floating-point minNum Element in Vector - -// atomic operations (ARMv8.1/ARMv8.3) -//ARM_swp, // Swap value with memory, No memory ordering -ARM_swpl, // Swap value with memory, Release -ARM_swpa, // Swap value with memory, Acquire -ARM_swpal, // Swap value with memory, Acquire and release - -ARM_ldapr, // Load-Acquire RCpc Register - -ARM_ldadd, // Atomic add on value in memory (return initial value), No memory ordering -ARM_ldaddl, // Atomic add on value in memory (return initial value), Release -ARM_ldadda, // Atomic add on value in memory (return initial value), Acquire -ARM_ldaddal, // Atomic add on value in memory (return initial value), Acquire and release -ARM_stadd, // Atomic add on value in memory (no return), No memory ordering -ARM_staddl, // Atomic add on value in memory (no return), Release - -ARM_ldclr, // Atomic bit clear on value in memory (return initial value), No memory ordering -ARM_ldclrl, // Atomic bit clear on value in memory (return initial value), Release -ARM_ldclra, // Atomic bit clear on value in memory (return initial value), Acquire -ARM_ldclral, // Atomic bit clear on value in memory (return initial value), Acquire and release -ARM_stclr, // Atomic bit clear on value in memory (no return), No memory ordering -ARM_stclrl, // Atomic bit clear on value in memory (no return), Release - -ARM_ldeor, // Atomic exclusive OR on value in memory (return initial value), No memory ordering -ARM_ldeorl, // Atomic exclusive OR on value in memory (return initial value), Release -ARM_ldeora, // Atomic exclusive OR on value in memory (return initial value), Acquire -ARM_ldeoral, // Atomic exclusive OR on value in memory (return initial value), Acquire and release -ARM_steor, // Atomic exclusive OR on value in memory (no return), No memory ordering -ARM_steorl, // Atomic exclusive OR on value in memory (no return), Release - -ARM_ldset, // Atomic bit set on value in memory (return initial value), No memory ordering -ARM_ldsetl, // Atomic bit set on value in memory (return initial value), Release -ARM_ldseta, // Atomic bit set on value in memory (return initial value), Acquire -ARM_ldsetal, // Atomic bit set on value in memory (return initial value), Acquire and release -ARM_stset, // Atomic bit set on value in memory (no return), No memory ordering -ARM_stsetl, // Atomic bit set on value in memory (no return), Release - -ARM_ldsmax, // Atomic signed maximum on value in memory (return initial value), No memory ordering -ARM_ldsmaxl, // Atomic signed maximum on value in memory (return initial value), Release -ARM_ldsmaxa, // Atomic signed maximum on value in memory (return initial value), Acquire -ARM_ldsmaxal, // Atomic signed maximum on value in memory (return initial value), Acquire and release -ARM_stsmax, // Atomic signed maximum on value in memory (no return), No memory ordering -ARM_stsmaxl, // Atomic signed maximum on value in memory (no return), Release - - -ARM_ldsmin, // Atomic signed minimum on value in memory (return initial value), No memory ordering -ARM_ldsminl, // Atomic signed minimum on value in memory (return initial value), Release -ARM_ldsmina, // Atomic signed minimum on value in memory (return initial value), Acquire -ARM_ldsminal, // Atomic signed minimum on value in memory (return initial value), Acquire and release -ARM_stsmin, // Atomic signed minimum on value in memory (no return), No memory ordering -ARM_stsminl, // Atomic signed minimum on value in memory (no return), Release - -ARM_ldumax, // Atomic unsigned maximum on value in memory (return initial value), No memory ordering -ARM_ldumaxl, // Atomic unsigned maximum on value in memory (return initial value), Release -ARM_ldumaxa, // Atomic unsigned maximum on value in memory (return initial value), Acquire -ARM_ldumaxal, // Atomic unsigned maximum on value in memory (return initial value), Acquire and release -ARM_stumax, // Atomic unsigned maximum on value in memory (no return), No memory ordering -ARM_stumaxl, // Atomic unsigned maximum on value in memory (no return), Release - - -ARM_ldumin, // Atomic unsigned minimum on value in memory (return initial value), No memory ordering -ARM_lduminl, // Atomic unsigned minimum on value in memory (return initial value), Release -ARM_ldumina, // Atomic unsigned minimum on value in memory (return initial value), Acquire -ARM_lduminal, // Atomic unsigned minimum on value in memory (return initial value), Acquire and release -ARM_stumin, // Atomic unsigned minimum on value in memory (no return), No memory ordering -ARM_stuminl, // Atomic unsigned minimum on value in memory (no return), Release - -//Compare and Swap (ARMv8.1) - -ARM_cas, // Compare and Swap , No memory ordering -ARM_casl, // Compare and Swap, Release -ARM_casa, // Compare and Swap, Acquire -ARM_casal, // Compare and Swap, Acquire and release - -ARM_casp, // Compare and Swap Pair, No memory ordering -ARM_caspl, // Compare and Swap Pair, Release -ARM_caspa, // Compare and Swap Pair, Acquire -ARM_caspal, // Compare and Swap Pair, Acquire and release - -ARM_ldlar, // Load LOAcquire Register -ARM_stllr, // Store LORelease Register - -ARM_sqrdmlah, // Signed Saturating Rounding Doubling Multiply Accumulate -ARM_sqrdmlsh, // Signed Saturating Rounding Doubling Multiply Subtract - -// Pointer authentication (ARMv8.3) -// only completely new instructions are included; -// authenticated variations of old ones are represented by instruction flags (see arm.hpp) - -ARM_pac, // Pointer Authentication Code for Data/Instruction address/generic -ARM_aut, // Authenticate Data/Instruction address -ARM_xpac, // Strip Pointer Authentication Code - -// ARM insns for the legacy assembler (2 operands) -ARM_ldrd2, // Load pair of registers -ARM_strd2, // Store pair of registers - -// CRC32 (optional in 8.0, mandatory since 8.1) -ARM_crc32, // CRC32 using polynomial 0x04C11DB7 -ARM_crc32c, // CRC32 using polynomial 0x1EDC6F41 - -// Armv8-M Security Extension (TrustZone for Armv8-M) -ARM_tt, // Test Target (query the Security state and access permissions of a memory location) -ARM_tta, // Test Target Alternate Domain (query the Security state and access permissions of a memory location for a Non-secure access) -ARM_sg, // Secure Gateway -ARM_vlldm, // Floating-point Lazy Load Multiple -ARM_vlstm, // Floating-point Lazy Store Multiple - -//MP Extension instructions -ARM_pldw, // Preload Data for write - -// ARMv8.1-RDMA (AArh32) -ARM_vqrdmlah, // Vector Saturating Rounding Doubling Multiply Accumulate Returning High Half. -ARM_vqrdmlsh, // Vector Saturating Rounding Doubling Multiply Subtract Returning High Half - -// ARMv8.2-FP16 (AArch32) - -ARM_vmovx, // Vector Move extraction -ARM_vins, // Vector move Insertion. - -// ARMv8.3-JSConv (AArch32) -ARM_vjcvt, // Javascript Convert to signed fixed-point, rounding toward Zero - -// ARMv8.3-JSConv (A64) -ARM_fjcvtzs, // Javascript Convert to signed fixed-point, rounding toward Zero - - -/* -// ARMv8.3-CompNum, SIMD complex number support -ARM_fcadd, // Floating-point complex add -ARM_fcmla, // Floating-point complex multiply accumulate -*/ - - -ARM_last - - }; - - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * TMS320C6xx - VLIW (very long instruction word) architecture - * - */ - - - -enum -{ -// Original TMS320C62x instructions - -TMS6_null = 0, // Unknown Operation -TMS6_abs, // Absolute value -TMS6_add, // Integer addition without saturation (signed) -TMS6_addu, // Integer addition without saturation (unsigned) -TMS6_addab, // Integer addition using addressing mode (byte) -TMS6_addah, // Integer addition using addressing mode (halfword) -TMS6_addaw, // Integer addition using addressing mode (word) -TMS6_addk, // Integer addition 16bit signed constant -TMS6_add2, // Two 16bit Integer adds on register halves -TMS6_and, // Logical AND -TMS6_b, // Branch -TMS6_clr, // Clear a bit field -TMS6_cmpeq, // Compare for equality -TMS6_cmpgt, // Compare for greater than (signed) -TMS6_cmpgtu, // Compare for greater than (unsigned) -TMS6_cmplt, // Compare for less than (signed) -TMS6_cmpltu, // Compare for less than (unsigned) -TMS6_ext, // Extract and sign-extend a bit filed -TMS6_extu, // Extract an unsigned bit field -TMS6_idle, // Multicycle NOP with no termination until interrupt -TMS6_ldb, // Load from memory (signed 8bit) -TMS6_ldbu, // Load from memory (unsigned 8bit) -TMS6_ldh, // Load from memory (signed 16bit) -TMS6_ldhu, // Load from memory (unsigned 16bit) -TMS6_ldw, // Load from memory (32bit) -TMS6_lmbd, // Leftmost bit detection -TMS6_mpy, // Signed Integer Multiply (LSB16 x LSB16) -TMS6_mpyu, // Unsigned Integer Multiply (LSB16 x LSB16) -TMS6_mpyus, // Integer Multiply Signed*Unsigned (LSB16 x LSB16) -TMS6_mpysu, // Integer Multiply Unsigned*Signed (LSB16 x LSB16) -TMS6_mpyh, // Signed Integer Multiply (MSB16 x MSB16) -TMS6_mpyhu, // Unsigned Integer Multiply (MSB16 x MSB16) -TMS6_mpyhus, // Integer Multiply Unsigned*Signed (MSB16 x MSB16) -TMS6_mpyhsu, // Integer Multiply Signed*Unsigned (MSB16 x MSB16) -TMS6_mpyhl, // Signed Integer Multiply (MSB16 x LSB16) -TMS6_mpyhlu, // Unsigned Integer Multiply (MSB16 x LSB16) -TMS6_mpyhuls, // Integer Multiply Signed*Unsigned (MSB16 x LSB16) -TMS6_mpyhslu, // Integer Multiply Unsigned*Signed (MSB16 x LSB16) -TMS6_mpylh, // Signed Integer Multiply (LSB16 x MB16) -TMS6_mpylhu, // Unsigned Integer Multiply (LSB16 x MSB16) -TMS6_mpyluhs, // Integer Multiply Signed*Unsigned (LSB16 x MSB16) -TMS6_mpylshu, // Integer Multiply Unsigned*Signed (LSB16 x MSB16) -TMS6_mv, // Move from register to register -TMS6_mvc, // Move between the control file & register file -TMS6_mvk, // Move a 16bit signed constant into register -TMS6_mvkh, // Move a 16bit constant into the upper bits of a register -TMS6_mvklh, // Move a 16bit constant into the upper bits of a register -TMS6_neg, // Negate -TMS6_nop, // No operation -TMS6_norm, // Normalize -TMS6_not, // Bitwise NOT -TMS6_or, // Logical or -TMS6_sadd, // Integer addition with saturation -TMS6_sat, // Saturate 40bit value to 32bits -TMS6_set, // Set a bit field -TMS6_shl, // Arithmetic shift left -TMS6_shr, // Arithmetic shift right -TMS6_shru, // Logical shift left -TMS6_smpy, // Integer multiply with left shift & saturation (LSB16*LSB16) -TMS6_smpyhl, // Integer multiply with left shift & saturation (MSB16*LSB16) -TMS6_smpylh, // Integer multiply with left shift & saturation (LSB16*MSB16) -TMS6_smpyh, // Integer multiply with left shift & saturation (MSB16*MSB16) -TMS6_sshl, // Shift left with saturation -TMS6_ssub, // Integer substraction with saturation -TMS6_stb, // Store to memory (signed 8bit) -TMS6_stbu, // Store to memory (unsigned 8bit) -TMS6_sth, // Store to memory (signed 16bit) -TMS6_sthu, // Store to memory (unsigned 16bit) -TMS6_stw, // Store to memory (32bit) -TMS6_sub, // Integer substaraction without saturation (signed) -TMS6_subu, // Integer substaraction without saturation (unsigned) -TMS6_subab, // Integer subtraction using addressing mode (byte) -TMS6_subah, // Integer subtraction using addressing mode (halfword) -TMS6_subaw, // Integer subtraction using addressing mode (word) -TMS6_subc, // Conditional subtract & shift (for division) -TMS6_sub2, // Two 16bit integer subtractions on register halves -TMS6_xor, // Exclusive OR -TMS6_zero, // Zero a register - -// New TMS320C674x instructions - -TMS6_abs2, // Absolute Value With Saturation, Signed, Packed 16-bit -TMS6_absdp, // Absolute Value, Double-Precision Floating-Point -TMS6_abssp, // Absolute Value, Single-Precision Floating-Point -TMS6_add4, // Add Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_addad, // Add Using Doubleword Addressing Mode -TMS6_adddp, // Add Two Double-Precision Floating-Point Values -TMS6_addkpc, // Add Signed 7-bit Constant to Program Counter -TMS6_addsp, // Add Two Single-Precision Floating-Point Values -TMS6_addsub, // Parallel ADD and SUB Operations On Common Inputs -TMS6_addsub2, // Parallel ADD2 and SUB2 Operations On Common Inputs -TMS6_andn, // Bitwise AND Invert -TMS6_avg2, // Average, Signed, Packed 16-bit -TMS6_avgu4, // Average, Unsigned, Packed 16-bit -TMS6_bdec, // Branch and Decrement -TMS6_bitc4, // Bit Count, Packed 8-bit -TMS6_bitr, // Bit Reverse -TMS6_bnop, // Branch With NOP -TMS6_bpos, // Branch Positive -TMS6_callp, // Call Using a Displacement -TMS6_cmpeq2, // Compare for Equality, Packed 16-bit -TMS6_cmpeq4, // Compare for Equality, Packed 8-bit -TMS6_cmpeqdp, // Compare for Equality, Double-Precision Floating-Point Values -TMS6_cmpeqsp, // Compare for Equality, Single-Precision Floating-Point Values -TMS6_cmpgt2, // Compare for Greater Than, Packed 16-bit -TMS6_cmpgtdp, // Compare for Greater Than, Double-Precision Floating-Point Values -TMS6_cmpgtsp, // Compare for Greater Than, Single-Precision Floating-Point Values -TMS6_cmpgtu4, // Compare for Greater Than, Unsigned, Packed 8-bit -TMS6_cmplt2, // Compare for Less Than, Packed 16-bit -TMS6_cmpltdp, // Compare for Less Than, Double-Precision Floating-Point Values -TMS6_cmpltsp, // Compare for Less Than, Single-Precision Floating-Point Values -TMS6_cmpltu4, // Compare for Less Than, Unsigned, Packed 8-bit -TMS6_cmpy, // Complex Multiply Two Pairs, Signed, Packed 16-bit -TMS6_cmpyr, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding -TMS6_cmpyr1, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding -TMS6_ddotp4, // Double Dot Product, Signed, Packed 16-Bit and Signed, Packed 8-Bit -TMS6_ddotph2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit -TMS6_ddotph2r, // Double Dot Product With Rounding, Two Pairs, Signed, Packed 16-Bit -TMS6_ddotpl2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit -TMS6_ddotpl2r, // Double Dot Product With Rounding, Two Pairs, Signed Packed 16-Bit -TMS6_deal, // Deinterleave and Pack -TMS6_dint, // Disable Interrupts and Save Previous Enable State -TMS6_dmv, // Move Two Independent Registers to Register Pair -TMS6_dotp2, // Dot Product, Signed, Packed 16-Bit -TMS6_dotpn2, // Dot Product With Negate, Signed, Packed 16-Bit -TMS6_dotpnrsu2, // Dot Product With Negate, Shift and Round, Signed by Unsigned, Packed 16-Bit -TMS6_dotpnrus2, // Dot Product With Negate, Shift and Round, Unsigned by Signed, Packed 16-Bit -TMS6_dotprsu2, // Dot Product With Shift and Round, Signed by Unsigned, Packed 16-Bit -TMS6_dotprus2, // Dot Product With Shift and Round, Unsigned by Signed, Packed 16-Bit -TMS6_dotpsu4, // Dot Product, Signed by Unsigned, Packed 8-Bit -TMS6_dotpu4, // Dot Product, Unsigned, Packed 8-Bit -TMS6_dotpus4, // Dot Product, Unsigned by Signed, Packed 8-Bit -TMS6_dpack2, // Parallel PACK2 and PACKH2 Operations -TMS6_dpackx2, // Parallel PACKLH2 Operations -TMS6_dpint, // Convert Double-Precision Floating-Point Value to Integer -TMS6_dpsp, // Convert Double-Precision Floating-Point Value to Single-Precision Floating-Point Value -TMS6_dptrunc, // Convert Double-Precision Floating-Point Value to Integer With Truncation -TMS6_gmpy, // Galois Field Multiply -TMS6_gmpy4, // Galois Field Multiply, Packed 8-Bit -TMS6_intdp, // Convert Signed Integer to Double-Precision Floating-Point Value -TMS6_intdpu, // Convert Unsigned Integer to Double-Precision Floating-Point Value -TMS6_intsp, // Convert Signed Integer to Single-Precision Floating-Point Value -TMS6_intspu, // Convert Unsigned Integer to Single-Precision Floating-Point Value -TMS6_lddw, // Load Doubleword From Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_ldndw, // Load Nonaligned Doubleword From Memory With Constant or Register Offset -TMS6_ldnw, // Load Nonaligned Word From Memory With Constant or Register Offset -TMS6_max2, // Maximum, Signed, Packed 16-Bit -TMS6_maxu4, // Maximum, Unsigned, Packed 8-Bit -TMS6_min2, // Minimum, Signed, Packed 16-Bit -TMS6_minu4, // Minimum, Unsigned, Packed 8-Bit -TMS6_mpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB -TMS6_mpy2ir, // Multiply Two 16-Bit x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 32-Bit Result -TMS6_mpy32su, // Multiply Signed 32-Bit x Unsigned 32-Bit Into Signed 64-Bit Result -TMS6_mpy32u, // Multiply Unsigned 32-Bit x Unsigned 32-Bit Into Unsigned 64-Bit Result -TMS6_mpy32us, // Multiply Unsigned 32-Bit x Signed 32-Bit Into Signed 64-Bit Result -TMS6_mpydp, // Multiply Two Double-Precision Floating-Point Values -TMS6_mpyhi, // Multiply 16 MSB x 32-Bit Into 64-Bit Result -TMS6_mpyhir, // Multiply 16 MSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpyi, // Multiply 32-Bit x 32-Bit Into 32-Bit Result -TMS6_mpyid, // Multiply 32-Bit x 32-Bit Into 64-Bit Result -TMS6_mpyih, // Multiply 32-Bit x 16-MSB Into 64-Bit Result -TMS6_mpyihr, // Multiply 32-Bit x 16 MSB, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpyil, // Multiply 32-Bit x 16 LSB Into 64-Bit Result -TMS6_mpyilr, // Multiply 32-Bit x 16 LSB, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpyli, // Multiply 16 LSB x 32-Bit Into 64-Bit Result -TMS6_mpylir, // Multiply 16 LSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpysp, // Multiply Two Single-Precision Floating-Point Values -TMS6_mpysp2dp, // Multiply Two Single-Precision Floating-Point Values for Double-Precision Result -TMS6_mpyspdp, // Multiply Single-Precision Floating-Point Value x Double-Precision Floating-Point Value -TMS6_mpysu4, // Multiply Signed x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_mpyu4, // Multiply Unsigned x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_mpyus4, // Multiply Unsigned x Signed, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_mvd, // Move From Register to Register, Delayed -TMS6_mvkl, // Move Signed Constant Into Register and Sign Extend -TMS6_pack2, // Pack Two 16 LSBs Into Upper and Lower Register Halves -TMS6_packh2, // Pack Two 16 MSBs Into Upper and Lower Register Halves -TMS6_packh4, // Pack Four High Bytes Into Four 8-Bit Halfwords -TMS6_packhl2, // Pack 16 MSB Into Upper and 16 LSB Into Lower Register Halves -TMS6_packl4, // Pack Four Low Bytes Into Four 8-Bit Halfwords -TMS6_packlh2, // Pack 16 LSB Into Upper and 16 MSB Into Lower Register Halves -TMS6_rcpdp, // Double-Precision Floating-Point Reciprocal Approximation -TMS6_rcpsp, // Single-Precision Floating-Point Reciprocal Approximation -TMS6_rint, // Restore Previous Enable State -TMS6_rotl, // Rotate Left -TMS6_rpack2, // Shift With Saturation and Pack Two 16 MSBs Into Upper and Lower Register Halves -TMS6_rsqrdp, // Double-Precision Floating-Point Square-Root Reciprocal Approximation -TMS6_rsqrsp, // Single-Precision Floating-Point Square-Root Reciprocal Approximation -TMS6_sadd2, // Add Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation -TMS6_saddsu2, // Add Two Signed and Unsigned 16-Bit Integers on Register Halves With Saturation -TMS6_saddsub, // Parallel SADD and SSUB Operations On Common Inputs -TMS6_saddsub2, // Parallel SADD2 and SSUB2 Operations On Common Inputs -TMS6_saddu4, // Add With Saturation, Four Unsigned 8-Bit Pairs for Four 8-Bit Results -TMS6_saddus2, // Add Two Unsigned and Signed 16-Bit Integers on Register Halves With Saturation -TMS6_shfl, // Shuffle -TMS6_shfl3, // 3-Way Bit Interleave On Three 16-Bit Values Into a 48-Bit Result -TMS6_shlmb, // Shift Left and Merge Byte -TMS6_shr2, // Arithmetic Shift Right, Signed, Packed 16-Bit -TMS6_shrmb, // Shift Right and Merge Byte -TMS6_shru2, // Arithmetic Shift Right, Unsigned, Packed 16-Bit -TMS6_smpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB With Left Shift and Saturation -TMS6_smpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 64-Bit Result With Left Shift and Saturation -TMS6_spack2, // Saturate and Pack Two 16 LSBs Into Upper and Lower Register Halves -TMS6_spacku4, // Saturate and Pack Four Signed 16-Bit Integers Into Four Unsigned 8-Bit Halfwords -TMS6_spdp, // Convert Single-Precision Floating-Point Value to Double-Precision Floating-Point Value -TMS6_spint, // Convert Single-Precision Floating-Point Value to Integer -TMS6_spkernel, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary -TMS6_spkernelr, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary -TMS6_sploop, // Software Pipelined Loop (SPLOOP) Buffer Operation -TMS6_sploopd, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing -TMS6_sploopw, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing and No Epilog -TMS6_spmask, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control -TMS6_spmaskr, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control -TMS6_sptrunc, // Convert Single-Precision Floating-Point Value to Integer With Truncation -TMS6_sshvl, // Variable Shift Left -TMS6_sshvr, // Variable Shift Right -TMS6_ssub2, // Subtract Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation -TMS6_stdw, // Store Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_stndw, // Store Nonaligned Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_stnw, // Store Nonaligned Word to Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_sub4, // Subtract Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_subabs4, // Subtract With Absolute Value, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_subdp, // Subtract Two Double-Precision Floating-Point Values -TMS6_subsp, // Subtract Two Single-Precision Floating-Point Values -TMS6_swap2, // Swap Bytes in Upper and Lower Register Halves -TMS6_swap4, // Swap Byte Pairs in Upper and Lower Register Halves -TMS6_swe, // Software Exception -TMS6_swenr, // Software Exception, no Return -TMS6_unpkhu4, // Unpack 16 MSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves -TMS6_unpklu4, // Unpack 16 LSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves -TMS6_xormpy, // Galois Field Multiply With Zero Polynomial -TMS6_xpnd2, // Expand Bits to Packed 16-Bit Masks -TMS6_xpnd4, // Expand Bits to Packed 8-Bit Masks - -TMS6_last, - - }; - -/* - * Interactive disassembler (IDA). - * Intel 80196 module - * - */ - - - -enum -{ - I196_null = 0, // Unknown Operation - - I196_add2, // Add words (2 operands) - I196_add3, // Add words (3 operands) - I196_addb2, // Add bytes (2 operands) - I196_addb3, // Add bytes (3 operands) - - I196_addc, // Add words with carry - I196_addcb, // Add bytes with carry - - I196_and2, // Logical AND words (2 operands) - I196_and3, // Logical AND words (3 operands) - I196_andb2, // Logical AND bytes (2 operands) - I196_andb3, // Logical AND bytes (3 operands) - - I196_bmov, // Block move - I196_bmovi, // Interruptable block move - - I196_br, // Branch indirect - - I196_clr, // Clear word - I196_clrb, // Clear byte - I196_clrc, // Clear carry flag - I196_clrvt, // Clear overflow-trap flag - - I196_cmp, // Compare words - I196_cmpb, // Compare bytes - I196_cmpl, // Compare long - - I196_dec, // Decrement word - I196_decb, // Decrement byte - - I196_di, // Disable interrupts - - I196_div, // Divide integers - I196_divb, // Divide short-integers - I196_divu, // Divide words, unsigned - I196_divub, // Divide bytes, unsigned - - I196_djnz, // Decrement and jump if not zero - I196_djnzw, // Decrement and jump if not zero word - - I196_dpts, // Disable peripheral transaction server - - I196_ei, // Enable interrupts - - I196_epts, // Enable peripheral transaction server - - I196_ext, // Sign-extend integer into long-integer - I196_extb, // Sign-extend short-integer into integer - - I196_idlpd, // Idle/powerdown - - I196_inc, // Increment word - I196_incb, // Increment byte - - I196_jbc, // Jump if bit is clear - I196_jbs, // Jump if bit is set - I196_jc, // Jump if carry flag is set - I196_je, // Jump if equal - I196_jge, // Jump if signed greater than or equal - I196_jgt, // Jump if signed greater than - I196_jh, // Jump if higher (unsigned) - I196_jle, // Jump if signed less than or equal - I196_jlt, // Jump if signed less than - I196_jnc, // Jump if carry flag is clear - I196_jne, // Jump if not equal - I196_jnh, // Jump if not higher (unsigned) - I196_jnst, // Jump if sticky bit flag is clear - I196_jnv, // Jump if overflow flag is clear - I196_jnvt, // Jump if overflow-trap flag is clear - I196_jst, // Jump if sticky bit flag is set - I196_jv, // Jump if overflow flag is set - I196_jvt, // Jump if overflow-trap flag is set - - I196_lcall, // Long call - - I196_ld, // Load word - I196_ldb, // Load byte - I196_ldbse, // Load byte sign-extended - I196_ldbze, // Load byte zero-extended - - I196_ljmp, // Long jump - - I196_mul2, // Multiply integers (2 operands) - I196_mul3, // Multiply integers (3 operands) - I196_mulb2, // Multiply short-integers (2 operands) - I196_mulb3, // Multiply short-integers (3 operands) - I196_mulu2, // Multiply words, unsigned (2 operands) - I196_mulu3, // Multiply words, unsigned (3 operands) - I196_mulub2, // Multiply bytes, unsigned (2 operands) - I196_mulub3, // Multiply bytes, unsigned (3 operands) - - I196_neg, // Negate integer - I196_negb, // Negate short-integer - - I196_nop, // No operation - - I196_norml, // Normalize long-integer - - I196_not, // Complement word - I196_notb, // Complement byte - - I196_or, // Logical OR words - I196_orb, // Logical OR bytes - - I196_pop, // Pop word - I196_popa, // Pop all - I196_popf, // Pop flags - I196_push, // Push word - I196_pusha, // Push all - I196_pushf, // Push flags - - I196_ret, // Return from subroutine - - I196_rst, // Reset system - - I196_scall, // Short call - - I196_setc, // Set carry flag - - I196_shl, // Shift word left - I196_shlb, // Shift byte left - I196_shll, // Shift double-word left - I196_shr, // Logical right shift word - I196_shra, // Arithmetic right shift word - I196_shrab, // Arithmetic right shift byte - I196_shral, // Arithmetic right shift double-word - I196_shrb, // Logical right shift byte - I196_shrl, // Logical right shift double-word - - I196_sjmp, // Short jump - - I196_skip, // Two byte no-operation - - I196_st, // Store word - I196_stb, // Store byte - - I196_sub2, // Subtract words (2 operands) - I196_sub3, // Subtract words (3 operands) - I196_subb2, // Subtract bytes (2 operands) - I196_subb3, // subtract bytes (3 operands) - - I196_subc, // Subtract words with borrow - I196_subcb, // Subtract bytes with borrow - - I196_tijmp, // Table indirect jump - - I196_trap, // Software trap - - I196_xch, // Exchange word - I196_xchb, // Exchange byte - - I196_xor, // Logical exclusive-or words - I196_xorb, // Logical exclusive-or bytes - -// 8x196NU, NP instructions - - I196_ebmovi, // Extended interruptable block move - I196_ebr, // Extended branch indirect - I196_ecall, // Extended call - I196_ejmp, // Extended jump - I196_eld, // Extended load word - I196_eldb, // Extended load byte - I196_est, // Extended store word - I196_estb, // Extended store byte - - I196_last -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * Renesas SuperH - RISC with 16bit instructions - * - */ - - - - -enum -{ -SH3_null = 0, // Unknown Operation - -SH3_add, // Add binary -SH3_addc, // Add with Carry -SH3_addv, // Add with V Flag Overflow Check -SH3_and, // AND Logical -SH3_and_b, // AND Byte Logical -SH3_bf, // Branch if False -SH3_bf_s, // Branch of False with Delay Slot -SH3_bra, // Branch -SH3_braf, // Branch Far -SH3_bsr, // Branch to Subroutine -SH3_bsrf, // Branch to Subroutine Far -SH3_bt, // Branch if True -SH3_bt_s, // Branch if True with Delay Slot -SH3_clrmac, // Clear MAC register -SH3_clrs, // Clear S Bit -SH3_clrt, // Clear T Bit -SH3_cmp_eq, // Compare: Equal -SH3_cmp_ge, // Compare: Signed Greater or Equal -SH3_cmp_gt, // Compare: Signed Greater -SH3_cmp_hi, // Compare: Unsigned Greater -SH3_cmp_hs, // Compare: Unsigned Greater or Equal -SH3_cmp_pl, // Compare: Positive -SH3_cmp_pz, // Compare: Positive or Zero -SH3_cmp_str, // Compare: Equal Bytes -SH3_div0s, // Divide Step 0 as Signed -SH3_div0u, // Divide Step 0 as Unsigned -SH3_div1, // Divide Step 1 -SH3_dmuls_l, // Double-Length Multiply as Signed -SH3_dmulu_l, // Double-Length Multiply as Unsigned -SH3_dt, // Decrement and Test -SH3_exts_b, // Extend as Signed (Byte) -SH3_exts_w, // Extend as Signed (Word) -SH3_extu_b, // Extend as Unsigned (Byte) -SH3_extu_w, // Extend as Unsigned (Word) -SH3_jmp, // Jump -SH3_jsr, // Jump to Subroutine -SH3_ldc, // Load to Control Register -SH3_ldc_l, // Load to Control Register Long -SH3_lds, // Load to System Register -SH3_lds_l, // Load to System Register Long -SH3_ldtlb, // Load PTEH/PTEL/PTEA to TLB -SH3_mac_w, // Multiply and Accumulate Word -SH3_mac_l, // Multiply and Accumulate Long -SH3_mov, // Move Data -SH3_mov_b, // Move Byte Data -SH3_mov_w, // Move Word Data -SH3_mov_l, // Move Long Data -SH3_movi, // Move Immediate Byte Data -SH3_movi_w, // Move Immediate Word Data -SH3_movi_l, // Move Immediate Long Data -SH3_movp_b, // Move Peripherial Byte Data -SH3_movp_w, // Move Peripherial Word Data -SH3_movp_l, // Move Peripherial Long Data -SH3_movs_b, // Move Structure Byte Data -SH3_movs_w, // Move Structure Word Data -SH3_movs_l, // Move Structure Long Data -SH3_mova, // Move Effective Address -SH3_movt, // Move T Bit -SH3_mul, // Multiply Long -SH3_muls, // Multiply as Signed Word -SH3_mulu, // Multiply as Unsigned Word -SH3_neg, // Negate -SH3_negc, // Negate with Carry -SH3_nop, // No Operation -SH3_not, // NOT - Logical Complement -SH3_or, // OR Logical -SH3_or_b, // OR Byte Logical -SH3_pref, // Prefetch Data to the Cache -SH3_rotcl, // Rotate with Carry Left -SH3_rotcr, // Rotate with Carry Right -SH3_rotl, // Rotate Left -SH3_rotr, // Rotate Right -SH3_rte, // Return from Exception -SH3_rts, // Return from Subroutine -SH3_sets, // Set S Bit -SH3_sett, // Set T Bit -SH3_shad, // Shift Arithmetic Dynamically -SH3_shal, // Shift Arithmetic Left -SH3_shar, // Shift Arithmetic Right -SH3_shld, // Shift Logical Dynamically -SH3_shll, // Shift Logical Left -SH3_shll2, // Shift Logical Left 2 -SH3_shll8, // Shift Logical Left 8 -SH3_shll16, // Shift Logical Left 16 -SH3_shlr, // Shift Logical Right -SH3_shlr2, // Shift Logical Right 2 -SH3_shlr8, // Shift Logical Right 8 -SH3_shlr16, // Shift Logical Right 16 -SH3_sleep, // Sleep -SH3_stc, // Store Control Register -SH3_stc_l, // Store Control Register Long -SH3_sts, // Store System Register -SH3_sts_l, // Store System Register Long -SH3_sub, // Subtract Binary -SH3_subc, // Subtract with Carry -SH3_subv, // Subtract with V Flag Underflow Check -SH3_swap_b, // Swap Register Halves (Byte) -SH3_swap_w, // Swap Register Halves (Word) -SH3_tas_b, // Test and Set -SH3_trapa, // Trap Always -SH3_tst, // Test Logical -SH3_tst_b, // Test Byte Logical -SH3_xor, // Exclusive OR Logical -SH3_xor_b, // Exclusive OR Byte Logical -SH3_xtrct, // Extract - -SH4_fabs, // Floating-point absolute value -SH4_fadd, // Floating-point add -SH4_fcmp_eq, // Floating-point compare eqaul -SH4_fcmp_gt, // Floating-point compare greater than -SH4_fcnvds, // Floating-point convert double to single precision -SH4_fcnvsd, // Floating-point convert single to double precision -SH4_fdiv, // Floating-point divide -SH4_fipr, // Floating-point inner product -SH4_fldi0, // Floating-point Load Immediate 0.0 -SH4_fldi1, // Floating-point Load Immediate 1.0 -SH4_flds, // Floating-point Load to system register -SH4_float, // Floating-point convert from integer -SH4_fmac, // Floating-point multiply and accumulate -SH4_fmov, // Floating-point move -SH4_fmov_s, // Floating-point move single precision -SH4_fmovex, // Floating-point move extension -SH4_fmul, // Floating-point multiply -SH4_fneg, // Floating-Point sign inversion -SH4_frchg, // FR-bit change -SH4_fschg, // SZ-bit change -SH4_fsqrt, // Floating-point square root -SH4_fsts, // Floating-point store system register -SH4_fsub, // Floating-point subtract -SH4_ftrc, // Floating-point truncate and convert to integer -SH4_ftrv, // Floating-point transform vector -SH4_ftstn, // Floating point square root reciprocal approximate -SH4_movca_l, // Move with cache block allocation -SH4_ocbi, // Operand Cache Block Invalidate -SH4_ocbp, // Operand Cache Block Purge -SH4_ocbwb, // Operand Cache Block Write Back -SH4_fsca, // Floating point sine and cosine approximate - -// SH-2a new instructions - -SH2a_band_b, // Bit And Byte Data -SH2a_bandnot_b, // Bit And Not Byte Data -SH2a_bclr, // Bit Clear -SH2a_bclr_b, // Bit Clear Byte Data -SH2a_bld, // Bit Load -SH2a_bld_b, // Bit Load Byte Data -SH2a_bldnot_b, // Bit Load Not Byte Data -SH2a_bor_b, // Bit Or Byte Data -SH2a_bornot_b, // Bit Or Not Byte Data -SH2a_bset, // Bit Set -SH2a_bset_b, // Bit Set Byte Data -SH2a_bst, // Bit Store -SH2a_bst_b, // Bit Store Byte Data -SH2a_bxor_b, // Bit Exclusive Or Byte Data -SH2a_clips_b, // Clip as Signed Byte -SH2a_clips_w, // Clip as Signed Word -SH2a_clipu_b, // Clip as Unsigned Byte -SH2a_clipu_w, // Clip as Unsigned Word -SH2a_divs, // Divide as Signed -SH2a_divu, // Divide as Unsigned -SH2a_jsr_n, // Jump to Subroutine with No delay slot -SH2a_ldbank, // Load Register Bank -SH2a_movi20, // 20-bit immediate data transfer -SH2a_movi20s, // 20-bit immediate data transfer, 8-bit left-shift -SH2a_movml_l, // Move Multi-register Lower part -SH2a_movmu_l, // Move Multi-register Upper part -SH2a_movrt, // Move Reverse T bit -SH2a_movu_b, // Move Structure Byte Data as Unsigned -SH2a_movu_w, // Move Structure Word Data as Unsigned -SH2a_mulr, // Multiply to Register -SH2a_nott, // Not T bit -SH2a_resbank, // Restore From Register Bank -SH2a_rts_n, // Return from Subroutine with No delay slot -SH2a_rtv_n, // Return to Value and from Subroutine with No delay slot -SH2a_stbank, // Store Register Bank - -// SH-4a new instructions - -SH4a_movco_l, // Move Conditional -SH4a_movli_l, // Move Linked -SH4a_movua_l, // Move Unaligned -SH4a_icbi, // Instruction Cache Block Invalidate -SH4a_prefi, // Prefetch Instruction Cache Block -SH4a_synco, // Synchronize Data Operation -SH4a_fsrra, // Floating Point Square Reciprocal Approximate -SH4a_fpchg, // PR-bit Change - -SH4_last, - - }; - -/* - * Interactive disassembler (IDA). - * Zilog Z8 module - * - */ - - - -enum -{ - Z8_null = 0, // Unknown Operation - - Z8_adc, // Add with carry - Z8_add, // Add - Z8_and, // Logical AND - Z8_call, // Call procedure - Z8_ccf, // Complement carry flag - Z8_clr, // Clear - Z8_com, // Complement - Z8_cp, // Compare - Z8_da, // Decimal adjust - Z8_dec, // Decrement - Z8_decw, // Decrement word - Z8_di, // Disable interrupts - Z8_djnz, // Decrement and jump if non-zero - Z8_ei, // Enable interrupts - Z8_halt, // Enter HALT mode - Z8_inc, // Increment - Z8_incw, // Increment word - Z8_iret, // Return from interrupt - Z8_jp, // Unconditional jump - Z8_jpcond, // Conditional jump - Z8_jr, // Relative jump - Z8_jrcond, // Conditional relative jump - Z8_ld, // Load data - Z8_ldc, // Load constant - Z8_ldci, // Load constant with auto-increment - Z8_lde, // Load external data - Z8_ldei, // Load external data with auto-increment - Z8_nop, // NOP - Z8_or, // Logical OR - Z8_pop, // Pop - Z8_push, // Push - Z8_rcf, // Reset carry flag - Z8_ret, // Return - Z8_rl, // Rotate left - Z8_rlc, // Rotate left through carry - Z8_rr, // Rotate right - Z8_rrc, // Rotate right through carry - Z8_sbc, // Subtract with carry - Z8_scf, // Set carry flag - Z8_sra, // Shift right arithmetic - Z8_srp, // Set register pointer - Z8_stop, // Enter STOP mode - Z8_sub, // Subtract - Z8_swap, // Swap nibbles - Z8_tm, // Test under mask - Z8_tcm, // Test complement under mask - Z8_xor, // Logical EXCLUSIVE OR - Z8_wdh, // Enable WATCH-DOG in HALT mode - Z8_wdt, // Clear WATCH-DOG timer - - Z8_last -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * Atmel AVR - 8-bit RISC processor - * - */ - - - -enum -{ - -AVR_null = 0, // Unknown Operation - -// ARITHMETIC AND LOGIC INSTRUCTIONS -AVR_add, // Add without Carry -AVR_adc, // Add with Carry -AVR_adiw, // Add Immediate to Word -AVR_sub, // Subtract without Carry -AVR_subi, // Subtract Immediate -AVR_sbc, // Subtract with Carry -AVR_sbci, // Subtract Immediate with Carry -AVR_sbiw, // Subtract Immediate from Word -AVR_and, // Logical AND -AVR_andi, // Logical AND with Immediate -AVR_or, // Logical OR -AVR_ori, // Logical OR with Immediate -AVR_eor, // Exclusive OR -AVR_com, // One's Complement -AVR_neg, // Two's Complement -AVR_sbr, // Set Bit(s) in Register -AVR_cbr, // Clear Bit(s) in Register -AVR_inc, // Increment -AVR_dec, // Decrement -AVR_tst, // Test for Zero or Minus -AVR_clr, // Clear Register -AVR_ser, // Set Register -AVR_cp, // Compare -AVR_cpc, // Compare with Carry -AVR_cpi, // Compare with Immediate -AVR_mul, // Multiply - -// BRANCH INSTRUCTIONS -AVR_rjmp, // Relative Jump -AVR_ijmp, // Indirect Jump to (Z) -AVR_jmp, // Jump -AVR_rcall, // Relative Call Subroutine -AVR_icall, // Indirect Call to (Z) -AVR_call, // Call Subroutine -AVR_ret, // Subroutine Return -AVR_reti, // Interrupt Return -AVR_cpse, // Compare, Skip if Equal -AVR_sbrc, // Skip if Bit in Register Cleared -AVR_sbrs, // Skip if Bit in Register Set -AVR_sbic, // Skip if Bit in I/O Register Cleared -AVR_sbis, // Skip if Bit in I/O Register Set -AVR_brbs, // Branch if Status Flag Set -AVR_brbc, // Branch if Status Flag Cleared -AVR_breq, // Branch if Equal -AVR_brne, // Branch if Not Equal -AVR_brcs, // Branch if Carry Set -AVR_brcc, // Branch if Carry Cleared -AVR_brsh, // Branch if Same or Higher -AVR_brlo, // Branch if Lower -AVR_brmi, // Branch if Minus -AVR_brpl, // Branch if Plus -AVR_brge, // Branch if Greater or Equal -AVR_brlt, // Branch if Less Than -AVR_brhs, // Branch if Half Carry Flag Set -AVR_brhc, // Branch if Half Carry Flag Cleared -AVR_brts, // Branch if T Flag Set -AVR_brtc, // Branch if T Flag Cleared -AVR_brvs, // Branch if Overflow Flag is Set -AVR_brvc, // Branch if Overflow Flag is Cleared -AVR_brie, // Branch if Interrupt Enabled -AVR_brid, // Branch if Interrupt Disabled - -// DATA TRANSFER INSTRUCTIONS -AVR_mov, // Copy Register -AVR_ldi, // Load Immediate -AVR_lds, // Load Direct -AVR_ld, // Load Indirect -AVR_ldd, // Load Indirect with Displacement -AVR_sts, // Store Direct to SRAM -AVR_st, // Store Indirect -AVR_std, // Store Indirect with Displacement -AVR_lpm, // Load Program Memory -AVR_in, // In Port -AVR_out, // Out Port -AVR_push, // Push Register on Stack -AVR_pop, // Pop Register from Stack - -// BIT AND BIT-TEST INSTRUCTIONS -AVR_lsl, // Logical Shift Left -AVR_lsr, // Logical Shift Right -AVR_rol, // Rotate Left Through Carry -AVR_ror, // Rotate Right Through Carry -AVR_asr, // Arithmetic Shift Right -AVR_swap, // Swap Nibbles -AVR_bset, // Flag Set -AVR_bclr, // Flag Clear -AVR_sbi, // Set Bit in I/O Register -AVR_cbi, // Clear Bit in I/O Register -AVR_bst, // Bit Store from Register to T -AVR_bld, // Bit load from T to Register -AVR_sec, // Set Carry -AVR_clc, // Clear Carry -AVR_sen, // Set Negative Flag -AVR_cln, // Clear Negative Flag -AVR_sez, // Set Zero Flag -AVR_clz, // Clear Zero Flag -AVR_sei, // Global Interrupt Enable -AVR_cli, // Global Interrupt Disable -AVR_ses, // Set Signed Test Flag -AVR_cls, // Clear Signed Test Flag -AVR_sev, // Set Two's Complement Overflow -AVR_clv, // Clear Two's Complement Overflow -AVR_set, // Set T in SREG -AVR_clt, // Clear T in SREG -AVR_seh, // Set Half Carry Flag in SREG -AVR_clh, // Clear Half Carry Flag in SREG -AVR_nop, // No Operation -AVR_sleep, // Sleep -AVR_wdr, // Watchdog Reset - -// New MegaAVR instructions - -AVR_elpm, // Extended Load Program Memory -AVR_espm, // Extended Store Program Memory -AVR_fmul, // Fractional Multiply Unsigned -AVR_fmuls, // Fractional Multiply Signed -AVR_fmulsu, // Fractional Multiply Signed with Unsigned -AVR_movw, // Copy Register Word -AVR_muls, // Multiply Signed -AVR_mulsu, // Multiply Signed with Unsigned -AVR_spm, // Store Program Memory -AVR_eicall, // Extended Indirect Call to Subroutine -AVR_eijmp, // Extended Indirect Jump - -// New XMega instructions - -AVR_des, // Data Encryption Standard -AVR_lac, // Load And Clear -AVR_las, // Load And Set -AVR_lat, // Load And Toggle -AVR_xch, // Exchange - -AVR_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -MIPS_null = 0, // Unknown Operation - -// The core processor instructions - -MIPS_add, // Add -MIPS_addu, // Add Unsigned -MIPS_and, // AND -MIPS_dadd, // Doubleword Add -MIPS_daddu, // Doubleword Add Unsigned -MIPS_dsub, // Doubleword Subtract -MIPS_dsubu, // Doubleword Subtract Unsigned -MIPS_nor, // NOR -MIPS_or, // OR -MIPS_slt, // Set on Less Than -MIPS_sltu, // Set on Less Than Unsigned -MIPS_sub, // Subtract -MIPS_subu, // Subtract Unsigned -MIPS_xor, // Exclusive OR -MIPS_dsll, // Doubleword Shift Left Logical -MIPS_dsll32, // Doubleword Shift Left Logical + 32 -MIPS_dsra, // Doubleword Shift Right Arithmetic -MIPS_dsra32, // Doubleword Shift Right Arithmetic + 32 -MIPS_dsrl, // Doubleword Shift Right Logical -MIPS_dsrl32, // Doubleword Shift Right Logical + 32 -MIPS_sll, // Shift Left Logical -MIPS_sra, // Shift Right Arithmetic -MIPS_srl, // Shift Right Logical -MIPS_dsllv, // Doubleword Shift Left Logical Variable -MIPS_dsrav, // Doubleword Shift Right Arithmetic Variable -MIPS_dsrlv, // Doubleword Shift Right Logical Variable -MIPS_sllv, // Shift Left Logical Variable -MIPS_srav, // Shift Right Arithmetic Variable -MIPS_srlv, // Shift Right Logical Variable -MIPS_addi, // Add Immediate -MIPS_addiu, // Add Immediate Unsigned -MIPS_daddi, // Doubleword Add Immediate -MIPS_daddiu, // Doubleword Add Immediate Unsigned -MIPS_slti, // Set on Less Than Immediate -MIPS_sltiu, // Set on Less Than Immediate Unsigned -MIPS_andi, // AND Immediate -MIPS_ori, // OR Immediate -MIPS_xori, // Exclusive OR Immediate -MIPS_teq, // Trap if Equal -MIPS_tge, // Trap if Greater Than or Equal -MIPS_tgeu, // Trap if Greater Than or Equal Unsigned -MIPS_tlt, // Trap if Less Than -MIPS_tltu, // Trap if Less Than Unsigned -MIPS_tne, // Trap if Not Equal -MIPS_cfc1, // Move Control From FPU -MIPS_cfc2, // Move Control From Coprocessor 2 -MIPS_ctc1, // Move Control to FPU -MIPS_ctc2, // Move Control to Coprocessor 2 -MIPS_dmfc0, // Doubleword Move From CP0 -MIPS_qmfc2, // Quadword Move From CP2 -MIPS_dmtc0, // Doubleword Move To CP0 -MIPS_qmtc2, // Quadword Move To CP2 -MIPS_mfc0, // Move from CP0 -MIPS_mfc1, // Move from FPU -MIPS_mfc2, // Move from CP2 -MIPS_mtc0, // Move to CP0 -MIPS_mtc1, // Move to FPU -MIPS_mtc2, // Move to CP2 -MIPS_teqi, // Trap if Equal Immediate -MIPS_tgei, // Trap if Greater Than or Equal Immediate -MIPS_tgeiu, // Trap if Greater Than or Equal Immediate Unsigned -MIPS_tlti, // Trap if Less Than Immediate -MIPS_tltiu, // Trap if Less Than Immediate Unsigned -MIPS_tnei, // Trap if Not Equal Immediate -MIPS_ddiv, // Doubleword Divide -MIPS_ddivu, // Doubleword Divide Unsigned -MIPS_div, // Divide -MIPS_divu, // Divide Unsigned -MIPS_dmult, // Doubleword Multiply -MIPS_dmultu, // Doubleword Multiply Unsigned -MIPS_mult, // Multiply -MIPS_multu, // Multiply Unsigned -MIPS_mthi, // Move To HI -MIPS_mtlo, // Move To LO -MIPS_mfhi, // Move From HI -MIPS_mflo, // Move From LO -MIPS_cop0, // Coprocessor 0 Operation -MIPS_cop1, // FPU Operation -MIPS_cop2, // Coprocessor 2 Operation -MIPS_break, // Break -MIPS_syscall, // System Call -MIPS_bc0f, // Branch on Coprocessor 0 False -MIPS_bc1f, // Branch on FPU False -MIPS_bc2f, // Branch on Coprocessor 2 False -MIPS_bc3f, // Branch on Coprocessor 3 False -MIPS_bc0fl, // Branch on Coprocessor 0 False Likely -MIPS_bc1fl, // Branch on FPU False Likely -MIPS_bc2fl, // Branch on Coprocessor 2 False Likely -MIPS_bc3fl, // Branch on Coprocessor 3 False Likely -MIPS_bc0t, // Branch on Coprocessor 0 True -MIPS_bc1t, // Branch on FPU True -MIPS_bc2t, // Branch on Coprocessor 2 True -MIPS_bc3t, // Branch on Coprocessor 3 True -MIPS_bc0tl, // Branch on Coprocessor 0 True Likely -MIPS_bc1tl, // Branch on FPU True Likely -MIPS_bc2tl, // Branch on Coprocessor 2 True Likely -MIPS_bc3tl, // Branch on Coprocessor 3 True Likely -MIPS_bgez, // Branch on Greater Than or Equal to Zero -MIPS_bgezal, // Branch on Greater Than or Equal to Zero And Link -MIPS_bgezall, // Branch on Greater Than or Equal to Zero And Link Likely -MIPS_bgezl, // Branch on Greater Than or Equal to Zero Likely -MIPS_bgtz, // Branch on Greater Than Zero -MIPS_bgtzl, // Branch on Greater Than Zero Likely -MIPS_blez, // Branch on Less Than or Equal to Zero -MIPS_blezl, // Branch on Less Than or Equal to Zero Likely -MIPS_bltz, // Branch on Less Than Zero -MIPS_bltzal, // Branch on Less Than Zero And Link -MIPS_bltzall, // Branch on Less Than Zero And Link Likely -MIPS_bltzl, // Branch on Less Than Zero Likely -MIPS_beq, // Branch on Equal -MIPS_beql, // Branch on Equal Likely -MIPS_bne, // Branch on Not Equal -MIPS_bnel, // Branch on Not Equal Likely -MIPS_jalr, // Jump And Link Register -MIPS_j, // Jump -MIPS_jr, // Jump Register -MIPS_jal, // Jump And Link -MIPS_jalx, // Jump And Link And Exchange -MIPS_cache, // Cache Operation -MIPS_lb, // Load Byte -MIPS_lbu, // Load Byte Unsigned -MIPS_ldl, // Load Doubleword Left -MIPS_ldr, // Load Doubleword Right -MIPS_lwl, // Load Word Left -MIPS_lwr, // Load Word Right -MIPS_ld, // Load Doubleword -MIPS_lld, // Load Linked Doubleword -MIPS_ldc1, // Load Double FPU -MIPS_ldc2, // Load Double Coprocessor 2 -MIPS_ll, // Load Linked -MIPS_lw, // Load Word -MIPS_lwu, // Load Word Unsigned -MIPS_lh, // Load Halfword -MIPS_lhu, // Load Halfword Unsigned -MIPS_lui, // Load Upper Immediate -MIPS_lwc1, // Load Word to FPU -MIPS_lwc2, // Load Word to Coprocessor 2 -MIPS_sb, // Store Byte -MIPS_sdl, // Store Doubleword Left -MIPS_sdr, // Store Doubleword Right -MIPS_swl, // Store Word Left -MIPS_swr, // Store Word Right -MIPS_scd, // Store Conditional Doubleword -MIPS_sd, // Store Doubleword -MIPS_sdc1, // Store Double FPU -MIPS_sdc2, // Store Double Coprocessor 2 -MIPS_sc, // Store Conditional -MIPS_sw, // Store Word -MIPS_sh, // Store Halfword -MIPS_swc1, // Store Word from FPU -MIPS_swc2, // Store Word from Coprocessor 2 -MIPS_sync, // Sync - -// Coprocessor 0 instructions - -MIPS_eret, // Exception Return -MIPS_tlbp, // Probe TLB for Matching Entry -MIPS_tlbr, // Read Indexed TLB Entry -MIPS_tlbwi, // Write Indexed TLB Entry -MIPS_tlbwr, // Write Random TLB Entry - - -// Coprocessor 1 (FPU) instructions - -MIPS_fadd, // Floating-point Add -MIPS_fsub, // Floating-point Subtract -MIPS_fmul, // Floating-point Multiply -MIPS_fdiv, // Floating-point Divide -MIPS_fabs, // Floating-point Absolute Value -MIPS_fcvt_s, // Floating-point Convert to Single Fixed-Point Format -MIPS_fcvt_d, // Floating-point Convert to Double Floating-Point Format -MIPS_fcvt_w, // Floating-point Convert to Fixed-Point Format -MIPS_fcvt_l, // Floating-point Convert to Long Fixed-Point Format -MIPS_fround_l, // Floating-point Round to Long Fixed-Point Format -MIPS_ftrunc_l, // Floating-point Truncate to Long Fixed-Point Format -MIPS_fceil_l, // Floating-point Ceiling to Long Fixed-Point Format -MIPS_ffloor_l, // Floating-point Floor to Long Fixed-Point Format -MIPS_fround_w, // Floating-point Round to Single Fixed-Point Format -MIPS_ftrunc_w, // Floating-point Truncate to Single Fixed-Point Format -MIPS_fceil_w, // Floating-point Ceiling to Single Fixed-Point Format -MIPS_ffloor_w, // Floating-point Floor to Single Fixed-Point Format -MIPS_fmov, // Floating-point Move -MIPS_fneg, // Floating-point Negate -MIPS_fsqrt, // Floating-point Square Root -MIPS_fc_f, // Floating-point Compare -MIPS_fc_un, // Floating-point Compare -MIPS_fc_eq, // Floating-point Compare -MIPS_fc_ueq, // Floating-point Compare -MIPS_fc_olt, // Floating-point Compare -MIPS_fc_ult, // Floating-point Compare -MIPS_fc_ole, // Floating-point Compare -MIPS_fc_ule, // Floating-point Compare -MIPS_fc_sf, // Floating-point Compare -MIPS_fc_ngle, // Floating-point Compare -MIPS_fc_seq, // Floating-point Compare -MIPS_fc_ngl, // Floating-point Compare -MIPS_fc_lt, // Floating-point Compare -MIPS_fc_nge, // Floating-point Compare -MIPS_fc_le, // Floating-point Compare -MIPS_fc_ngt, // Floating-point Compare - -// Pseudo instructions - -MIPS_nop, // No operation -MIPS_mov, // Move register -MIPS_neg, // Negate -MIPS_negu, // Negate Unsigned -MIPS_bnez, // Branch on Not Zero -MIPS_bnezl, // Branch on Not Zero Likely -MIPS_beqz, // Branch on Zero -MIPS_beqzl, // Branch on Zero Likely -MIPS_b, // Branch Always -MIPS_bal, // Branch Always and Link -MIPS_li, // Load Immediate -MIPS_la, // Load Address - -// MIPS IV instructions - -MIPS_pref, // Prefetch -MIPS_ldxc1, // Load Doubleword Indexed to Floating Point -MIPS_lwxc1, // Load Word Indexed to Floating Point -MIPS_sdxc1, // Store Doubleword Indexed from Floating Point -MIPS_swxc1, // Store Word Indexed from Floating Point -MIPS_madd_s, // Floating-Point Multiply Add -MIPS_madd_d, // Floating-Point Multiply Add -MIPS_msub_s, // Floating-Point Multiply Subtract -MIPS_msub_d, // Floating-Point Multiply Subtract -MIPS_movf, // Move Conditional on FP False -MIPS_movt, // Move Conditional on FP True -MIPS_movn, // Move Conditional on Not Zero -MIPS_movz, // Move Conditional on Zero -MIPS_fmovf, // Floating-Point Move Conditional on FP False -MIPS_fmovt, // Floating-Point Move Conditional on FP True -MIPS_fmovn, // Floating-Point Move Conditional on Not Zero -MIPS_fmovz, // Floating-Point Move Conditional on Zero -MIPS_nmadd_s, // Floating-Pont Negative Multiply Add -MIPS_nmadd_d, // Floating-Pont Negative Multiply Add -MIPS_nmsub_s, // Floating-Pont Negative Multiply Subtract -MIPS_nmsub_d, // Floating-Pont Negative Multiply Subtract -MIPS_prefx, // Prefetch Indexed -MIPS_frecip, // Reciprocal Approximation -MIPS_frsqrt, // Reciprocal Suare Root Approximation - -// RSP instructions - -MIPS_lbv, // Load Byte into Vector -MIPS_lsv, // Load Short into Vector -MIPS_llv, // Load Word into Vector -MIPS_ldv, // Load Doubleword into Vector -MIPS_lqv, // Load Quadword into Vector -MIPS_lrv, // Load Rest Vector -MIPS_lpv, // Load Packed Vector -MIPS_luv, // Load Unpack Vector -MIPS_lhv, // Load Half Vector -MIPS_lfv, // Load Fourth Vector -MIPS_lwv, // Load Wrap Vector -MIPS_ltv, // Load Transpose Vector -MIPS_sbv, // Store Byte from Vector -MIPS_ssv, // Store Short from Vector -MIPS_slv, // Store Word from Vector -MIPS_sdv, // Store Doubleword from Vector -MIPS_sqv, // Store Quadword from Vector -MIPS_srv, // Store Rest Vector -MIPS_spv, // Store Packed Vector -MIPS_suv, // Store Unpack Vector -MIPS_shv, // Store Half Vector -MIPS_sfv, // Store Fourth Vector -MIPS_swv, // Store Wrap Vector -MIPS_stv, // Store Transpose Vector -MIPS_vmulf, // Vector (Frac) Multiply -MIPS_vmacf, // Vector (Frac) Multiply Accumulate -MIPS_vmulu, // Vector (Unsigned Frac) Multiply -MIPS_vmacu, // Vector (Unsigned Frac) Multiply Accumulate -MIPS_vrndp, // Vector DCT Round (+) -MIPS_vrndn, // Vector DCT Round (-) -MIPS_vmulq, // Vector (Integer) Multiply -MIPS_vmacq, // Vector (Integer) Multiply Accumulate -MIPS_vmudh, // Vector (High) Multiply -MIPS_vmadh, // Vector (High) Multiply Accumulate -MIPS_vmudm, // Vector (Mid-M) Multiply -MIPS_vmadm, // Vector (Mid-M) Multiply Accumulate -MIPS_vmudn, // Vector (Mid-N) Multiply -MIPS_vmadn, // Vector (Mid-N) Multiply Accumulate -MIPS_vmudl, // Vector (Low) Multiply -MIPS_vmadl, // Vector (Low) Multiply Accumulate -MIPS_vadd, // Vector Add -MIPS_vsub, // Vector Subtract -MIPS_vsut, // Vector SUT (vt - vs) -MIPS_vabs, // Vector Absolute Value -MIPS_vaddc, // Vector ADDC -MIPS_vsubc, // Vector SUBC -MIPS_vaddb, // Vector Add Byte -MIPS_vsubb, // Vector Subtract Byte -MIPS_vaccb, // Vector Add Byte/Add Accumulator -MIPS_vsucb, // Vector Subtract Byte/Add Accumulator -MIPS_vsad, // Vector SAD -MIPS_vsac, // Vector SAC -MIPS_vsum, // Vector SUM -MIPS_vsaw, // Vector SAW -MIPS_vlt, // Vector Less Than -MIPS_veq, // Vector Equal To -MIPS_vne, // Vector Not Equal To -MIPS_vge, // Vector Greater Than or Equal To -MIPS_vcl, // Vector Clip Low -MIPS_vch, // Vector Clip High -MIPS_vcr, // Vector 1's Complement Clip -MIPS_vmrg, // Vector Merge -MIPS_vand, // Vector Logical AND -MIPS_vnand, // Vector Logical NAND -MIPS_vor, // Vector Logical OR -MIPS_vnor, // Vector Logical NOR -MIPS_vxor, // Vector Logical Exclusive OR -MIPS_vnxor, // Vector Logical NOT Exclusive OR -MIPS_vnoop, // Vector No-Operation -MIPS_vmov, // Vector Scalar-Element Move -MIPS_vrcp, // Single Precision, Lookup Source, Write Result -MIPS_vrsq, // Single Precision, Lookup Source, Write Result -MIPS_vrcph, // Set Source, Write Previous Result -MIPS_vrsqh, // Set Source, Write Previous Result -MIPS_vrcpl, // Lookup Source and Previous, Write Result -MIPS_vrsql, // Lookup Source and Previous, Write Result -MIPS_vinst, // Vector Insert Triple (5/5/5/1) -MIPS_vextt, // Vector Extract Triple (5/5/5/1) -MIPS_vinsq, // Vector Insert Quad (4/4/4/4) -MIPS_vextq, // Vector Extract Quad (4/4/4/4) -MIPS_vinsn, // Vector Insert Nibble (4/4/4/4) Sign-Extended -MIPS_vextn, // Vector Insert Nibble (4/4/4/4) Sign-Extended -MIPS_cfc0, // Move Control From Coprocessor 0 -MIPS_ctc0, // Move Control to Coprocessor 0 - -// R5900 (PSX2 or PlayStation2) processor additional commands - -MIPS_mtsa, // Move To Shift Amount Register -MIPS_R5900_first = MIPS_mtsa, -MIPS_mfsa, // Move From Shift Amount Register -MIPS_mtsab, // Move Byte Count To Shift Amount Register -MIPS_mtsah, // Move Halfword Count To Shift Amount Register -MIPS_fadda, // Floating-point add to accumulator -MIPS_fsuba, // Floating-point subtract to accumulator -MIPS_fmula, // Floating-point multiply to accumulator -MIPS_fmadda, // Floating-point multiply and add to accumulator -MIPS_fmsuba, // Floating-point multiply and subtract from accumulator -MIPS_fmadd, // Floating-point multiply and add -MIPS_fmsub, // Floating-point multiply and subtract -MIPS_fmax, // Floating-point maximum -MIPS_fmin, // Floating-point minimum -MIPS_plzcw, // Parallel Leading Zero or One Count Word -MIPS_mthi1, // Move To HI1 Register -MIPS_mtlo1, // Move To LO1 Register -MIPS_pmthl_lw, // Parallel Move From HI/LO Register -MIPS_pmthi, // Parallel Move To HI Register -MIPS_pmtlo, // Parallel Move To LO Register -MIPS_div1, // Divide Pipeline 1 -MIPS_divu1, // Divide Unsigned Pipeline 1 -MIPS_pdivw, // Parallel Divide Word -MIPS_pdivuw, // Parallel Divide Unsigned Word -MIPS_pdivbw, // Parallel Divide Broadcast Word -MIPS_paddw, // Parallel Add Word -MIPS_pmaddw, // Parallel Multiply-Add Word -MIPS_mult1, // Multiply Pipeline 1 -MIPS_multu1, // Multiply Unsigned Pipeline 1 -MIPS_madd1, // Multiply-Add Pipeline 1 -MIPS_maddu1, // Multiply-Add Unsigned Pipeline 1 -MIPS_pmadduw, // Parallel Multiply-Add Unsigned Word -MIPS_psubw, // Parallel Subtract HalfWord -MIPS_pcgtw, // Parallel Compare for Greater Than Word -MIPS_psllvw, // Parallel Shift Left Logical Variable Word -MIPS_pceqw, // Parallel Compare for Equal Word -MIPS_pmaxw, // Parallel Maximize Word -MIPS_psrlvw, // Parallel Shift Right Logical Variable Word -MIPS_pminw, // Parallel Minimize Word -MIPS_psravw, // Parallel Shift Right Arithmetic Variable Word -MIPS_paddh, // Parallel Add Halfword -MIPS_pmsubw, // Parallel Multiply-Subtract Word -MIPS_padsbh, // Parallel Add/Subtract Halfword -MIPS_psubh, // Parallel Subtract Halfword -MIPS_pcgth, // Parallel Compare for Greater Than Halfword -MIPS_pceqh, // Parallel Compare for Equal Halfword -MIPS_pmaxh, // Parallel Maximize Halfword -MIPS_pminh, // Parallel Minimize Halfword -MIPS_paddb, // Parallel Add Byte -MIPS_psubb, // Parallel Subtract Byte -MIPS_pcgtb, // Parallel Compare for Greater Than Byte -MIPS_pinth, // Parallel Interleave Halfword -MIPS_pceqb, // Parallel Compare for Equal Byte -MIPS_pintoh, // Parallel Interleave Odd Halfword -MIPS_pmultw, // Parallel Multiply Word -MIPS_pmultuw, // Parallel Multiply Unsigned Word -MIPS_pcpyld, // Parallel Copy Lower Doubleword -MIPS_pcpyud, // Parallel Copy Upper Doubleword -MIPS_paddsw, // Parallel Add with Signed Saturation Word -MIPS_pmaddh, // Parallel Multiply-Add Halfword -MIPS_padduw, // Parallel Add with Unsigned Saturation Word -MIPS_psubsw, // Parallel Subtract with Signed Saturation Word -MIPS_phmadh, // Parallel Horizontal Multiply-Add Halfword -MIPS_psubuw, // Parallel Subtract with Unsigned Saturation Word -MIPS_pextlw, // Parallel Extend Lower from Word -MIPS_pand, // Parallel AND -MIPS_pextuw, // Parallel Extend Upper from Word -MIPS_por, // Parallel OR -MIPS_ppacw, // Paralle Pack to Word -MIPS_pxor, // Parallel XOR -MIPS_pnor, // Parallel NOR -MIPS_paddsh, // Parallel Add with Signed Saturation Halfword -MIPS_pmsubh, // Parallel Multiply-Subtract Halfword -MIPS_padduh, // Parallel Add with Unsigned Saturation Halfword -MIPS_psubsh, // Parallel Subtract with Signed Saturation Halfword -MIPS_phmsbh, // Parallel Horizontal Multiply-Subtract Halfword -MIPS_psubuh, // Parallel Subtract with Unsigned Saturation Halfword -MIPS_pextlh, // Parallel Extend Lower from Halfword -MIPS_pextuh, // Parallel Extend Upper from Halfword -MIPS_ppach, // Paralle Pack to Halfword -MIPS_paddsb, // Parallel Add with Signed Saturation Byte -MIPS_paddub, // Parallel Add with Unsigned Saturation Byte -MIPS_psubsb, // Parallel Subtract with Signed Saturation Byte -MIPS_psubub, // Parallel Subtract with Unsigned Saturation Byte -MIPS_pextlb, // Parallel Extend Lower from Byte -MIPS_pextub, // Parallel Extend Upper from Byte -MIPS_ppacb, // Paralle Pack to Byte -MIPS_qfsrv, // Quadword Funnel Shift Right Variable -MIPS_pmulth, // Parallel Multiply Halfword -MIPS_pabsw, // Parallel Absolute Word -MIPS_pabsh, // Parallel Absolute Halfword -MIPS_pexoh, // Parallel Exchange Odd Halfword -MIPS_pexch, // Parallel Exchange Center Halfword -MIPS_prevh, // Parallel Reverse Halfword -MIPS_pcpyh, // Parallel Copy Halfword -MIPS_pext5, // Parallel Extend Upper from 5 bits -MIPS_pexow, // Parallel Exchange Odd Word -MIPS_pexcw, // Parallel Exchange Center Word -MIPS_ppac5, // Parallel Pack to 5 bits -MIPS_prot3w, // Parallel Rotate 3 Words -MIPS_psllh, // Parallel Shift Left Logical Halfword -MIPS_psrlh, // Parallel Shift Right Logical Halfword -MIPS_psrah, // Parallel Shift Right Arithmetic Halfword -MIPS_psllw, // Parallel Shift Left Logical Word -MIPS_psrlw, // Parallel Shift Right Logical Word -MIPS_psraw, // Parallel Shift Right Arithmetic Word -MIPS_mfhi1, // Move From HI1 Register -MIPS_mflo1, // Move From LO1 Register -MIPS_pmfhi, // Parallel Move From HI Register -MIPS_pmflo, // Parallel Move From LO Register -MIPS_pmfhl, // Parallel Move From HI/LO Register -MIPS_lq, // Load Quadword -MIPS_sq, // Store Quadword -MIPS_lqc2, // Load Quadword Coprocessor 2 -MIPS_sqc2, // Store Quadword Coprocessor 2 -MIPS_madd_r5900, // Multiply/Add -MIPS_maddu_r5900, // Multiply/Add Unsigned -MIPS_R5900_last = MIPS_maddu_r5900, -MIPS_mult3, // Multiply (3-operand) -MIPS_multu3, // Multiply Unsigned (3-operand) - -// 16-bit instructions -// NOTE: in previous version of IDA, all mips16 instructions -// had separate numbers, even for the instructions with the -// same mnemonics. Now same mnemonics have the same numbers, -// regardless of the encoding. - -MIPS_bteqz=439, // Branch on T Equal to Zero -MIPS_btnez, // Branch on T Not Equal to Zero -MIPS_cmp, // Compare -MIPS_cmpi, // Compare Immediate -MIPS_extend=458, // Extend -MIPS_move=473, // Move -MIPS_not=477, // Not -MIPS_dla=495, // Load 64-bit address - -// Instructions which belong to MIPS32 but which were not decoded by IDA - -MIPS_clo=498, // Count Leading Ones in Word -MIPS_clz, // Count Leading Zeros in Word -MIPS_madd, // Multiply/Add -MIPS_maddu, // Multiply/Add Unsigned -MIPS_msub, // Multiply and Subtract Word to Hi,Lo -MIPS_msubu, // Multiply and Subtract Word to Hi,Lo -MIPS_mul, // Multiply Word to GPR -MIPS_sdbbp, // Software Debug Breakpoint -MIPS_wait, // Enter Standby Mode - -// New instructions for MIPS32 Release 2.0 - -MIPS_alnv_ps, // Floating Point Align Variable -MIPS_deret, // Debug Exception Return -MIPS_di, // Disable interrupts -MIPS_ehb, // Execution Hazard Barrier -MIPS_ei, // Enable interrupts -MIPS_ext, // Extract Bit Field -MIPS_fcvt_ps, // Floating Point Convert Pair to Paired Single -MIPS_fcvt_s_pl, // Floating Point Convert Pair Lower to Single Floating Point -MIPS_fcvt_s_pu, // Floating Point Convert Pair Upper to Single Floating Point -MIPS_ins, // Insert Bit Field -MIPS_jalr_hb, // Jump and Link Register with Hazard Barrier -MIPS_jr_hb, // Jump Register with Hazard Barrier -MIPS_luxc1, // Load Doubleword Indexed Unaligned to Floating Point -MIPS_madd_ps, // Floating Point Multiply Add -MIPS_mfhc1, // Move Word from High Half of Floating Point Register -MIPS_mfhc2, // Move Word from High Half of Coprocessor 2 Register -MIPS_msub_ps, // Floating Point Multiply Subtract -MIPS_mthc1, // Move Word to High Half of Floating Point Register -MIPS_mthc2, // Move Word to High Half of Coprocessor 2 Register -MIPS_nmadd_ps, // Floating Point Negative Multiply Add -MIPS_nmsub_ps, // Floating Point Negative Multiply Subtract -MIPS_pll, // Pair Lower Lower -MIPS_plu, // Pair Lower Upper -MIPS_pul, // Pair Upper Lower -MIPS_puu, // Pair Upper Upper -MIPS_rdhwr, // Read Hardware Register -MIPS_rdpgpr, // Read GPR from Previous Shadow Set -MIPS_rotr, // Rotate Word Right -MIPS_rotrv, // Rotate Word Right Variable -MIPS_seb, // Sign-Extend Byte -MIPS_seh, // Sign-Extend Halfword -MIPS_suxc1, // Store Doubleword Indexed Unaligned from Floating Point -MIPS_synci, // Synchronize Caches to Make Instruction Writes Effective -MIPS_wrpgpr, // Write GPR to Previous Shadow Set -MIPS_wsbh, // Word Swap Bytes Within Halfwords - -// Missing instructions - for some reason they were not supported before - -MIPS_dmfc1, // Doubleword Move From CP1 -MIPS_dmtc1, // Doubleword Move To CP1 - -// additional MIPS16e instructions - -MIPS_save, // Save Registers and Set Up Stack Frame -MIPS_restore, // Restore Registers and Deallocate Stack Frame -MIPS_jalrc, // Jump and Link Register, Compact -MIPS_jrc, // Jump Register, Compact -MIPS_sew, // Sign-Extend Word -MIPS_zeb, // Zero-Extend Byte -MIPS_zeh, // Zero-Extend Halfword -MIPS_zew, // Zero-Extend Word - -// extra pseudoinstructions -MIPS_ssnop, // Superscalar No operation -MIPS_li_s, // Load floating-point immediate -MIPS_li_d, // Load floating-point immediate -MIPS_dneg, // Negate -MIPS_dnegu, // Negate Unsigned -MIPS_pause, // Wait for the LLBit to clear - -// Missing instructions from MIPS64 Release 2 - -MIPS_dclo, // Count Leading Ones in Doubleword -MIPS_dclz, // Count Leading Zeros in Doubleword -MIPS_dext, // Doubleword Extract Bit Field -MIPS_dextm, // Doubleword Extract Bit Field Middle -MIPS_dextu, // Doubleword Extract Bit Field Upper -MIPS_dins, // Doubleword Insert Bit Field -MIPS_dinsm, // Doubleword Insert Bit Field Middle -MIPS_dinsu, // Doubleword Insert Bit Field Upper -MIPS_dmfc2, // Doubleword Move From CP2 -MIPS_dmtc2, // Doubleword Move To CP2 -MIPS_drotr, // Doubleword Rotate Right -MIPS_drotr32, // Doubleword Rotate Right Plus 32 -MIPS_drotrv, // Doubleword Rotate Right Variable -MIPS_dsbh, // Doubleword Swap Bytes Within Halfwords -MIPS_dshd, // Doubleword Swap Halfwords Within Doublewords - -// cnMIPS (Cavium Networks Octeon) instructions - -MIPS_baddu, // Unsigned Byte Add -MIPS_bbit0, // Branch on Bit Clear -MIPS_bbit032, // Branch on Bit Clear Plus 32 -MIPS_bbit1, // Branch on Bit Set -MIPS_bbit132, // Branch on Bit Set Plus 32 -MIPS_cins, // Clear and Insert a Bit Field -MIPS_cins32, // Clear and Insert a Bit Field Plus 32 -MIPS_dmul, // Multiply Doubleword to GPR -MIPS_dpop, // Count Ones in a Doubleword -MIPS_exts, // Extract a Signed Bit Field -MIPS_exts32, // Extract a Signed Bit Field Plus 32 -MIPS_mtm0, // Load Multiplier Register MPL0 -MIPS_mtm1, // Load Multiplier Register MPL1 -MIPS_mtm2, // Load Multiplier Register MPL2 -MIPS_mtp0, // Load Multiplier Register P0 -MIPS_mtp1, // Load Multiplier Register P1 -MIPS_mtp2, // Load Multiplier Register P2 -MIPS_pop, // Count Ones in a Word -MIPS_saa, // Store Atomic Add Word -MIPS_saad, // Store Atomic Add Double Word -MIPS_seq, // Set on Equal -MIPS_seqi, // Set on Equal Immediate -MIPS_sne, // Set on Not Equal -MIPS_snei, // Set on Not Equal Immediate -MIPS_synciobdma, // Synchronize IOBDMAs -MIPS_syncs, // Synchronize Special -MIPS_syncw, // Synchronize Stores -MIPS_syncws, // Synchronize Stores Special -MIPS_uld, // Unaligned Load Doubleword -MIPS_ulw, // Unaligned Load Word -MIPS_usd, // Unaligned Store Doubleword -MIPS_usw, // Unaligned Store Word -MIPS_v3mulu, // 192-bit x 64-bit Unsigned Multiply and Add -MIPS_vmm0, // 64-bit Unsigned Multiply and Add Move -MIPS_vmulu_cn, // 64-bit Unsigned Multiply and Add - -// NEC VR5432 and PSP instructions - -MIPS_dbreak, // Debug Break -MIPS_dret, // Debug Return -MIPS_mfdr, // Move from Debug Register -MIPS_mtdr, // Move to Debug Register - -// Allegrex (Sony PSP) instructions - -PSP_bitrev, // Bit reverse -PSP_max, // Maximum -PSP_min, // Minimum -PSP_mfic, // Move from interrupt controller -PSP_mtic, // Move to interrupt controller -PSP_wsbw, // Word Swap Bytes Within Word -PSP_sleep, // Sleep - -// Allegrex VFPU instructions - -PSP_lv, // Load Vector -PSP_lvl, // Load Vector Left -PSP_lvr, // Load Vector Right -PSP_sv, // Store Vector -PSP_svl, // Store Vector Left -PSP_svr, // Store Vector Right -PSP_mfv, // Move from VFPU -PSP_mtv, // Move to VFPU -PSP_mfvc, // Move Control from VFPU -PSP_mtvc, // Move Control to VFPU -PSP_bvf, // Branch on VFPU False -PSP_bvt, // Branch on VFPU True -PSP_bvfl, // Branch on VFPU False Likely -PSP_bvtl, // Branch on VFPU True Likely -PSP_vnop, // VFPU no-op -PSP_vflush, // VFPU flush -PSP_vsync, // VFPU sync -PSP_vabs, // Vector absolute value -PSP_vadd, // Vector add -PSP_vasin, // Vector arcsine -PSP_vavg, // Vector average -PSP_vbfy1, // IDCT butterfly 1 -PSP_vbfy2, // IDCT butterfly 2 -PSP_vc2i, // Vector convert signed char to integer -PSP_vcmovf, // Vector move if condition field is true -PSP_vcmovt, // Vector move if condition field is false -PSP_vcmp, // Vector compare and set condition fields -PSP_vcos, // Vector cosine -PSP_vcrs, // Vector cross multiplication: vd = [y1*z2, z1*x2, x1*y2] -PSP_vcrsp, // Vector cross product -PSP_vcst, // Set constant -PSP_vdet, // Determinant -PSP_vdiv, // Vector divide -PSP_vdot, // Vector dot product -PSP_vexp2, // Vector exponent of 2 (2^x) -PSP_vf2h, // Vector convert float single to half precision -PSP_vf2id, // Vector convert float to integer, round down -PSP_vf2in, // Vector convert float to integer, round to nearest -PSP_vf2iu, // Vector convert float to integer, round up -PSP_vf2iz, // Vector convert float to integer, round toward zero -PSP_vfad, // Vector funnel add (sum components) -PSP_vfim, // Set floating-point immediate -PSP_vh2f, // Vector convert float half to single precision -PSP_vhdp, // Vector homogenous dot product -PSP_vhtfm2, // Homogenous transform vector by matrix -PSP_vhtfm3, // Homogenous transform vector by matrix -PSP_vhtfm4, // Homogenous transform vector by matrix -PSP_vi2c, // Vector convert integer to signed char -PSP_vi2f, // Vector convert integer to float -PSP_vi2s, // Vector convert integer to signed short -PSP_vi2uc, // Vector convert integer to unsigned char -PSP_vi2us, // Vector convert integer to unsigned short -PSP_vidt, // Set vector to identity -PSP_viim, // Set integer immediate -PSP_vlgb, // -PSP_vlog2, // Vector logarithm base 2 -PSP_vmax, // Vector maximum values -PSP_vmfvc, // Vector move from control register -PSP_vmidt, // Set matrix to identity -PSP_vmin, // Vector minimum values -PSP_vmmov, // Move matrix -PSP_vmmul, // Matrix multiply -PSP_vmone, // Set matrix to ones -PSP_vmov, // Move vector -PSP_vmscl, // Scale matrix by -PSP_vmtvc, // Vector move to control register -PSP_vmul, // Vector multiply -PSP_vmzero, // Set matrix to zeroes -PSP_vneg, // Vector negate -PSP_vnrcp, // Vector negative reciprocal (-1/x) -PSP_vnsin, // Vector negative sine -PSP_vocp, // Vector one complement (1-x) -PSP_vone, // Set vector to ones -PSP_vpfxd, // Set prefix operation for vd -PSP_vpfxs, // Set prefix operation for vs -PSP_vpfxt, // Set prefix operation for vt -PSP_vqmul, // Quaternion multiply -PSP_vrcp, // Vector reciprocal (1/x) -PSP_vrexp2, // Vector reciprocal exponent of 2 (1/(2^x)) -PSP_vrndf1, // Vector generate pseudorandom float (1.0 ~ 2.0) -PSP_vrndf2, // Vector generate pseudorandom float (2.0 ~ 4.0) -PSP_vrndi, // Vector generate pseudorandom integer -PSP_vrnds, // Vector set pseudorandom seed -PSP_vrot, // Rotate vector -PSP_vrsq, // Vector reciprocal square root (1/sqrt(x)) -PSP_vs2i, // Vector convert signed short to integer -PSP_vsat0, // Vector saturate to range 0..1 -PSP_vsat1, // Vector saturate to range -1..1 -PSP_vsbn, // Vector scale by 2^x, round to nearest -PSP_vsbz, // Vector scale by 2^x, round towards zero -PSP_vscl, // Vector scale by -PSP_vscmp, // Vector set signed compare -PSP_vsge, // Vector set results for greater than or equal -PSP_vsgn, // Vector get sign -PSP_vsin, // Vector sine -PSP_vslt, // Vector set results for less -PSP_vsocp, // Vector split and one complement -PSP_vsqrt, // Vector square root -PSP_vsrt1, // Vector sort 1: vd = min(x,y), max(x,y), min(z,w), max(z,w) -PSP_vsrt2, // Vector sort 2: vd = min(x,w), max(y,z), min(y,z), max(x,w) -PSP_vsrt3, // Vector sort 3: vd = max(x,y), min(x,y), max(z,w), min(z,w) -PSP_vsrt4, // Vector sort 4: vd = max(x,w), max(y,z), min(y,z), max(x,w) -PSP_vsub, // Vector subtract -PSP_vt4444, // Transform color RGBA8888 to RGBA4444 -PSP_vt5551, // Transform color RGBA8888 to RGBA5551 -PSP_vt5650, // Transform color RGB888 to RGB565 -PSP_vtfm2, // Transform vector by matrix -PSP_vtfm3, // Transform vector by matrix -PSP_vtfm4, // Transform vector by matrix -PSP_vuc2i, // Vector convert unsigned char to integer -PSP_vus2i, // Vector convert unsigned short to integer -PSP_vwbn, // -PSP_vzero, // VFPU set vector to zeroes - -// PSP Media Engine instructions -PSP_mfvme, // move from VME -PSP_mtvme, // move to VME - -// Toshiba TX19a instructions -MIPS_ac0iu, // Add Coprocessor 0 Immediate Unsigned -MIPS_bs1f, // Bit Search One Forward -MIPS_bfins, // Bit field insert -MIPS_addmiu, // Add Immediate to Memory Word -MIPS_sadd, // Saturated Add -MIPS_ssub, // Saturated Subtract -MIPS_btst, // Bit Test -MIPS_bclr, // Bit Clear -MIPS_bset, // Bit Set -MIPS_bins, // Bit Insert -MIPS_bext, // Bit Extract -MIPS_dive, // Divide, with Overflow Exception -MIPS_diveu, // Divide unsigned, with Overflow Exception -MIPS_min, // Minimum signed -MIPS_max, // Maximum signed - -MIPS_madd3, // Multiply/Add (3-operand) -MIPS_maddu3, // Multiply/Add Unsigned (3-operand) -MIPS_msub3, // Multiply and Subtract Word to Hi,Lo (3-operand) -MIPS_msubu3, // Multiply and Subtract Word to Hi,Lo (3-operand) - -// MIPS-MT -MIPS_dvpe, // Disable Virtual Processor Execution -MIPS_evpe, // Enable Virtual Processor Execution -MIPS_dmt, // Disable Multi-Threaded Execution -MIPS_emt, // Enable Multi-Threaded Execution -MIPS_fork, // Allocate and Schedule a New Thread -MIPS_yield, // Conditionally Deschedule or Deallocate the Current Thread -MIPS_mftr, // Move From Thread Context -MIPS_mftc0, -MIPS_mftlo, -MIPS_mfthi, -MIPS_mftacx, -MIPS_mftdsp, -MIPS_mfthc1, -MIPS_mftc1, -MIPS_cftc1, -MIPS_mfthc2, -MIPS_mftc2, -MIPS_cftc2, -MIPS_mftgpr, -MIPS_mttr, // Move To Thread Context -MIPS_mttc0, -MIPS_mttlo, -MIPS_mtthi, -MIPS_mttacx, -MIPS_mttdsp, -MIPS_mtthc1, -MIPS_mttc1, -MIPS_cttc1, -MIPS_mtthc2, -MIPS_mttc2, -MIPS_cttc2, -MIPS_mttgpr, - -// MIPS-3D -MIPS_faddr, // Floating-point Reduction Addition -MIPS_bc1any2f, // Branch on Any of Two Floating Point Condition Codes False -MIPS_bc1any2t, // Branch on Any of Two Floating Point Condition Codes True -MIPS_bc1any4f, // Branch on Any of Four Floating Point Condition Codes False -MIPS_bc1any4t, // Branch on Any of Four Floating Point Condition Codes True -MIPS_fcabs_f, // Floating-point Absolute Compare -MIPS_fcabs_un, // Floating-point Absolute Compare -MIPS_fcabs_eq, // Floating-point Absolute Compare -MIPS_fcabs_ueq, // Floating-point Absolute Compare -MIPS_fcabs_olt, // Floating-point Absolute Compare -MIPS_fcabs_ult, // Floating-point Absolute Compare -MIPS_fcabs_ole, // Floating-point Absolute Compare -MIPS_fcabs_ule, // Floating-point Absolute Compare -MIPS_fcabs_sf, // Floating-point Absolute Compare -MIPS_fcabs_ngle, // Floating-point Absolute Compare -MIPS_fcabs_seq, // Floating-point Absolute Compare -MIPS_fcabs_ngl, // Floating-point Absolute Compare -MIPS_fcabs_lt, // Floating-point Absolute Compare -MIPS_fcabs_nge, // Floating-point Absolute Compare -MIPS_fcabs_le, // Floating-point Absolute Compare -MIPS_fcabs_ngt, // Floating-point Absolute Compare -MIPS_fcvt_pw_ps, // Floating-point Convert Paired Single to Paired Word -MIPS_fcvt_ps_pw, // Floating-point Convert Paired Word to Paired Single -MIPS_fmulr, // Floating-point Reduction Multiply -MIPS_frecip1, // Floating-point Reduced Precision Reciprocal (Step 1) -MIPS_frecip2, // Floating-point Reduced Precision Reciprocal (Step 2) -MIPS_frsqrt1, // Floating-point Reduced Precision Reciprocal Square Root (Step 1) -MIPS_frsqrt2, // Floating-point Reduced Precision Reciprocal Square Root (Step 2) - -// smartMIPS -MIPS_lwxs, -MIPS_maddp, -MIPS_mflhxu, -MIPS_mtlhx, -MIPS_multp, -MIPS_pperm, - -// microMIPS -MIPS_jals, // Jump and Link, Short Delay Slot -MIPS_lwp, // Load Word Pair -MIPS_ldp, // Load Doubleword Pair -MIPS_lwm, // Load Word Multiple -MIPS_ldm, // Load Doubleword Multiple -MIPS_swp, // Store Word Pair -MIPS_sdp, // Store Doubleword Pair -MIPS_swm, // Store Word Multiple -MIPS_sdm, // Store Doubleword Multiple -MIPS_bnezc, // Branch on Not Equal to Zero, Compact -MIPS_bltzals, // Branch on Less Than Zero and Link, Short Delay-Slot -MIPS_beqzc, // Branch on Equal to Zero, Compact -MIPS_bgezals, // Branch on Greater Than or Equal to Zero and Link, Short Delay-Slot -MIPS_jraddiusp, // Jump Register, Adjust Stack Pointer -MIPS_jalrs, // Jump and Link Register, Short Delay Slot -MIPS_jalrs_hb, // Jump and Link Register with Hazard Barrier, Short Delay-Slot -MIPS_movep, // Move a Pair of Registers - -// had been missed; 64-bit MIPS pseudoinstruction -MIPS_dli, // Doubleword Load Immediate - -// DSP ASE instructions -MIPS_insv, // Insert Bit Field Variable -MIPS_dinsv, // Doubleword Insert Variable Bit Field -MIPS_bposge32, // Branch on Greater Than or Equal To Value 32 in DSPControl Pos Field -MIPS_bposge64, // Branch on Greater Than or Equal To Value 64 in DSPControl Pos Field -MIPS_addu_qb, // Unsigned Add Quad Byte Vectors -MIPS_addu_ph, // Unsigned Add Integer Halfwords -MIPS_addsc, // Add Signed Word and Set Carry Bit -MIPS_subu_qb, // Subtract Unsigned Quad Byte Vector -MIPS_subu_ph, // Subtract Unsigned Integer Halfwords -MIPS_addwc, // Add Word with Carry Bit -MIPS_addq_ph, // Add Fractional Halfword Vectors -MIPS_modsub, // Modular Subtraction on an Index Value -MIPS_subq_ph, // Subtract Fractional Halfword Vector -MIPS_addu_s_qb, // Unsigned Add Quad Byte Vectors -MIPS_addu_s_ph, // Unsigned Add Integer Halfwords -MIPS_raddu_w_qb, // Unsigned Reduction Add Vector Quad Bytes -MIPS_muleq_s_w_phl, // Multiply Vector Fractional Left Halfwords to Expanded Width Products -MIPS_subu_s_qb, // Subtract Unsigned Quad Byte Vector -MIPS_subu_s_ph, // Subtract Unsigned Integer Halfwords -MIPS_muleq_s_w_phr, // Multiply Vector Fractional Right Halfwords to Expanded Width Products -MIPS_muleu_s_ph_qbl, // Multiply Unsigned Vector Left Bytes by Halfwords to Halfword Products -MIPS_addq_s_ph, // Add Fractional Halfword Vectors -MIPS_addq_s_w, // Add Fractional Words -MIPS_mulq_s_ph, // Multiply Vector Fractional Half-Words to Same Size Products -MIPS_muleu_s_ph_qbr, // Multiply Unsigned Vector Right Bytes with halfwords to Half Word Products -MIPS_subq_s_ph, // Subtract Fractional Halfword Vector -MIPS_subq_s_w, // Subtract Fractional Word -MIPS_mulq_rs_ph, // Multiply Vector Fractional Halfwords to Fractional Halfword Products -MIPS_addu_ob, // Unsigned Add Octal Byte Vectors -MIPS_subu_ob, // Subtract Unsigned Octal Byte Vector -MIPS_addq_qh, // Add Fractional Halfword Vectors -MIPS_addq_pw, // Add Fractional Word Vectors -MIPS_subq_qh, // Subtract Fractional Halfword Vector -MIPS_subq_pw, // Subtract Fractional Word Vector -MIPS_addu_s_ob, // Unsigned Add Octal Byte Vectors -MIPS_raddu_l_ob, // Unsigned Reduction Add Vector Octal Bytes -MIPS_muleq_s_pw_qhl, // Multiply Vector Fractional Left Halfwords to Expanded Width Products -MIPS_subu_s_ob, // Subtract Unsigned Octal Byte Vector -MIPS_muleq_s_pw_qhr, // Multiply Vector Fractional Right Halfwords to Expanded Width Products -MIPS_muleu_s_qh_obl, // Multiply Unsigned Vector Left Bytes by Halfwords to Halfword Products -MIPS_addq_s_qh, // Add Fractional Halfword Vectors -MIPS_addq_s_pw, // Add Fractional Word Vectors -MIPS_muleu_s_qh_obr, // Multiply Unsigned Vector Right Bytes by Halfwords to Halfword Products -MIPS_subq_s_qh, // Subtract Fractional Halfword Vector -MIPS_subq_s_pw, // Subtract Fractional Word Vector -MIPS_mulq_rs_qh, // Multiply Vector Fractional Halfwords to Fractional Halfword Products -MIPS_cmpu_eq_qb, // Compare Vectors of Unsigned Byte Values -MIPS_cmp_eq_ph, // Compare Vectors of Signed Integer Halfword Values -MIPS_cmpgdu_eq_qb, // Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl -MIPS_cmpu_lt_qb, // Compare Vectors of Unsigned Byte Values -MIPS_cmp_lt_ph, // Compare Vectors of Signed Integer Halfword Values -MIPS_cmpgdu_lt_qb, // Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl -MIPS_cmpu_le_qb, // Compare Vectors of Unsigned Byte Values -MIPS_cmp_le_ph, // Compare Vectors of Signed Integer Halfword Values -MIPS_cmpgdu_le_qb, // Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl -MIPS_pick_qb, // Pick a Vector of Byte Values Based on Condition Code Bits -MIPS_pick_ph, // Pick a Vector of Halfword Values Based on Condition Code Bits -MIPS_cmpgu_eq_qb, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR -MIPS_precrq_qb_ph, // Precision Reduce Four Fractional Halfwords to Four Bytes -MIPS_precrq_ph_w, // Precision Reduce Fractional Words to Fractional Halfwords -MIPS_cmpgu_lt_qb, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR -MIPS_precr_qb_ph, // Precision Reduce Four Integer Halfwords to Four Bytes -MIPS_precrq_rs_ph_w, // Precision Reduce Fractional Words to Halfwords With Rounding and Saturation -MIPS_cmpgu_le_qb, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR -MIPS_packrl_ph, // Pack a Vector of Halfwords from Vector Halfword Sources -MIPS_precr_sra_ph_w, // Precision Reduce Two Integer Words to Halfwords after a Right Shift -MIPS_precrqu_s_qb_ph, // Precision Reduce Fractional Halfwords to Unsigned Bytes With Saturation -MIPS_precr_sra_r_ph_w, // Precision Reduce Two Integer Words to Halfwords after a Right Shift -MIPS_cmpu_eq_ob, // Compare Vectors of Unsigned Byte Values -MIPS_cmp_eq_qh, // Compare Vectors of Signed Integer Halfword Values -MIPS_cmp_eq_pw, // Compare Vectors of Signed Integer Word Values -MIPS_cmpu_lt_ob, // Compare Vectors of Unsigned Byte Values -MIPS_cmp_lt_qh, // Compare Vectors of Signed Integer Halfword Values -MIPS_cmp_lt_pw, // Compare Vectors of Signed Integer Word Values -MIPS_cmpu_le_ob, // Compare Vectors of Unsigned Byte Values -MIPS_cmp_le_qh, // Compare Vectors of Signed Integer Halfword Values -MIPS_cmp_le_pw, // Compare Vectors of Signed Integer Word Values -MIPS_pick_ob, // Pick a Vector of Byte Values Based on Condition Code Bits -MIPS_pick_qh, // Pick a Vector of Halfword Values Based on Condition Code Bits -MIPS_pick_pw, // Pick a Vector of Word Values Based on Condition Code Bits -MIPS_cmpgu_eq_ob, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR -MIPS_precrq_ob_qh, // Precision Reduce Fractional Halfwords to Fractional Bytes -MIPS_precrq_qh_pw, // Precision Reduce Fractional Words to Fractional Halfwords -MIPS_precrq_pw_l, // Precision Reduce Fractional Doublewords to Fractional Words -MIPS_cmpgu_lt_ob, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR -MIPS_precrq_rs_qh_pw, // Precision Reduce Fractional Words to Halfwords With Rounding and Saturation -MIPS_cmpgu_le_ob, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR -MIPS_packrl_pw, // Pack a Vector of Words from Vector Word Sources -MIPS_precrqu_s_ob_qh, // Precision Reduce Fractional Halfwords to Unsigned Bytes With Saturation -MIPS_absq_s_qb, // Find Absolute Value of Four Fractional Byte Values -MIPS_absq_s_ph, // Find Absolute Value of Two Fractional Halfwords -MIPS_absq_s_w, // Find Absolute Value of Fractional Word -MIPS_repl_qb, // Replicate Immediate Integer into all Vector Element Positions -MIPS_repl_ph, // Replicate Immediate Integer into all Vector Element Positions -MIPS_replv_qb, // Replicate Byte into all Vector Element Positions -MIPS_replv_ph, // Replicate a Halfword into all Vector Element Positions -MIPS_bitrev, // Bit-Reverse Halfword -MIPS_precequ_ph_qbl, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceq_w_phl, // Precision Expand Fractional Halfword to Fractional Word Value -MIPS_preceu_ph_qbl, // Precision Expand Two Unsigned Bytes to Unsigned Halfword Values -MIPS_precequ_ph_qbr, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceq_w_phr, // Precision Expand Fractional Halfword to Fractional Word Value -MIPS_preceu_ph_qbr, // Precision Expand two Unsigned Bytes to Unsigned Halfword Values -MIPS_precequ_ph_qbla, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceu_ph_qbla, // Precision Expand Two Unsigned Bytes to Unsigned Halfword Values -MIPS_precequ_ph_qbra, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceu_ph_qbra, // Precision Expand Two Unsigned Bytes to Unsigned Halfword Values -MIPS_absq_s_qh, // Find Absolute Value of Four Fractional Halfwords -MIPS_absq_s_pw, // Find Absolute Value of Two Fractional Words -MIPS_repl_ob, // Replicate Immediate Integer into all Vector Element Positions -MIPS_repl_qh, // Replicate Immediate Integer into all Vector Element Positions -MIPS_repl_pw, // Replicate Immediate Integer into all Vector Element Positions -MIPS_replv_ob, // Replicate Byte into all Vector Element Positions -MIPS_replv_qh, // Replicate a Halfword into all Vector Element Positions -MIPS_replv_pw, // Replicate Word into all Vector Element Positions -MIPS_precequ_pw_qhl, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceq_pw_qhl, // Precision Expand Two Fractional Halfwords to Fractional Word Values -MIPS_preceq_s_l_pwl, // Precision Expand Fractional Word to Fractional Doubleword Value -MIPS_preceu_qh_obl, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values -MIPS_precequ_pw_qhr, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceq_pw_qhr, // Precision Expand Two Fractional Halfwords to Fractional Word Values -MIPS_preceq_s_l_pwr, // Precision Expand Fractional Word to Fractional Doubleword Value -MIPS_preceu_qh_obr, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values -MIPS_precequ_pw_qhla, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceq_pw_qhla, // Precision Expand Two Fractional Halfwords to Fractional Word Values -MIPS_preceu_qh_obla, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values -MIPS_precequ_pw_qhra, // Precision Expand two Unsigned Bytes to Fractional Halfword Values -MIPS_preceq_pw_qhra, // Precision Expand Two Fractional Halfwords to Fractional Word Values -MIPS_preceu_qh_obra, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values -MIPS_shll_qb, // Shift Left Logical Vector Quad Bytes -MIPS_shll_ph, // Shift Left Logical Vector Pair Halfwords -MIPS_shrl_qb, // Shift Right Logical Vector Quad Bytes -MIPS_shra_ph, // Shift Right Arithmetic Vector Pair Halfwords -MIPS_shrl_ph, // Shift Right Logical Two Halfwords -MIPS_shllv_qb, // Shift Left Logical Variable Vector Quad Bytes -MIPS_shllv_ph, // Shift Left Logical Variable Vector Pair Halfwords -MIPS_shrlv_qb, // Shift Right Logical Variable Vector Quad Bytes -MIPS_shrav_ph, // Shift Right Arithmetic Variable Vector Pair Halfwords -MIPS_shrlv_ph, // Shift Variable Right Logical Pair of Halfwords -MIPS_shra_qb, // Shift Right Arithmetic Vector of Four Bytes -MIPS_shll_s_ph, // Shift Left Logical Vector Pair Halfwords -MIPS_shll_s_w, // Shift Left Logical Word with Saturation -MIPS_shra_r_qb, // Shift Right Arithmetic Vector of Four Bytes -MIPS_shra_r_ph, // Shift Right Arithmetic Vector Pair Halfwords -MIPS_shra_r_w, // Shift Right Arithmetic Word with Rounding -MIPS_shrav_qb, // Shift Right Arithmetic Variable Vector of Four Bytes -MIPS_shllv_s_ph, // Shift Left Logical Variable Vector Pair Halfwords -MIPS_shllv_s_w, // Shift Left Logical Variable Vector Word -MIPS_shrav_r_qb, // Shift Right Arithmetic Variable Vector of Four Bytes -MIPS_shrav_r_ph, // Shift Right Arithmetic Variable Vector Pair Halfwords -MIPS_shrav_r_w, // Shift Right Arithmetic Variable Word with Rounding -MIPS_shll_ob, // Shift Left Logical Vector Octal Bytes -MIPS_shll_qh, // Shift Left Logical Vector Quad Halfwords -MIPS_shll_pw, // Shift Left Logical Vector Pair Words -MIPS_shrl_ob, // Shift Right Logical Vector Octal Bytes -MIPS_shra_qh, // Shift Right Arithmetic Vector Quad Halfwords -MIPS_shra_pw, // Shift Right Arithmetic Vector Pair Words -MIPS_shllv_ob, // Shift Left Logical Variable Vector Octal Bytes -MIPS_shllv_qh, // Shift Left Logical Variable Vector Quad Halfwords -MIPS_shllv_pw, // Shift Left Logical Variable Vector Pair Words -MIPS_shrlv_ob, // Shift Right Logical Variable Vector Octal Bytes -MIPS_shrav_qh, // Shift Right Arithmetic Variable Vector Quad Halfwords -MIPS_shrav_pw, // Shift Right Arithmetic Variable Vector Pair Words -MIPS_shll_s_qh, // Shift Left Logical Vector Quad Halfwords -MIPS_shll_s_pw, // Shift Left Logical Vector Pair Words -MIPS_shra_r_qh, // Shift Right Arithmetic Vector Quad Halfwords -MIPS_shra_r_pw, // Shift Right Arithmetic Vector Pair Words -MIPS_shllv_s_qh, // Shift Left Logical Variable Vector Quad Halfwords -MIPS_shllv_s_pw, // Shift Left Logical Variable Vector Pair Words -MIPS_shrav_r_qh, // Shift Right Arithmetic Variable Vector Quad Halfwords -MIPS_shrav_r_pw, // Shift Right Arithmetic Variable Vector Pair Words -MIPS_lwx, // Load Word Indexed -MIPS_ldx, // Load Doubleword Indexed -MIPS_lhx, // Load Halfword Indexed -MIPS_lbux, // Load Unsigned Byte Indexed -MIPS_dpa_w_ph, // Dot Product with Accumulate on Vector Integer Halfword Elements -MIPS_dpax_w_ph, // Cross Dot Product with Accumulate on Vector Integer Halfword Elements -MIPS_maq_sa_w_phl, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dpaqx_s_w_ph, // Cross Dot Product with Accumulation on Fractional Halfword Elements -MIPS_dps_w_ph, // Dot Product with Subtract on Vector Integer Half-Word Elements -MIPS_dpsx_w_ph, // Cross Dot Product with Subtract on Vector Integer Halfword Elements -MIPS_dpsqx_s_w_ph, // Cross Dot Product with Subtraction on Fractional Halfword Elements -MIPS_mulsa_w_ph, // Multiply and Subtract Vector Integer Halfword Elements and Accumulate -MIPS_maq_sa_w_phr, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dpaqx_sa_w_ph, // Cross Dot Product with Accumulation on Fractional Halfword Elements -MIPS_dpau_h_qbl, // Dot Product with Accumulate on Vector Unsigned Byte Elements -MIPS_dpsu_h_qbl, // Dot Product with Subtraction on Vector Unsigned Byte Elements -MIPS_dpsqx_sa_w_ph, // Cross Dot Product with Subtraction on Fractional Halfword Elements -MIPS_dpaq_s_w_ph, // Dot Product with Accumulation on Fractional Halfword Elements -MIPS_dpaq_sa_l_w, // Dot Product with Accumulate on Fractional Word Element -MIPS_maq_s_w_phl, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dpsq_s_w_ph, // Dot Product with Subtraction on Fractional Halfword Elements -MIPS_dpsq_sa_l_w, // Dot Product with Subtraction on Fractional Word Element -MIPS_mulsaq_s_w_ph, // Multiply And Subtract Vector Fractional Halfwords And Accumulate -MIPS_maq_s_w_phr, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dpau_h_qbr, // Dot Product with Accumulate on Vector Unsigned Byte Elements -MIPS_dpsu_h_qbr, // Dot Product with Subtraction on Vector Unsigned Byte Elements -MIPS_maq_sa_w_qhll, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_maq_sa_w_qhlr, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dmadd, // Multiply Vector Words And Accumulate -MIPS_dmsub, // Multiply Vector Words And Subtract From Accumulator -MIPS_maq_sa_w_qhrl, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dpau_h_obl, // Dot Product with Accumulate on Vector Unsigned Byte Elements -MIPS_dpsu_h_obl, // Dot Product with Subtract on Vector Unsigned Byte Elements -MIPS_maq_sa_w_qhrr, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dpaq_s_w_qh, // Dot Product with Accumulation on Fractional Halfword Elements -MIPS_dpaq_sa_l_pw, // Dot Product with Accumulate on Fractional Word Elements -MIPS_maq_s_w_qhll, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_maq_s_l_pwl, // Multiply with Accumulate Single Vector Fractional Word Element -MIPS_dpsq_s_w_qh, // Dot Product with Subtraction on Fractional Halfword Elements -MIPS_dpsq_sa_l_pw, // Dot Product with Subtraction on Fractional Word Elements -MIPS_maq_s_w_qhlr, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dmaddu, // Multiply Vector Unsigned Words And Accumulate -MIPS_mulsaq_s_w_qh, // Multiply And Subtract Vector Fractional Halfwords And Accumulate -MIPS_mulsaq_s_l_pw, // Multiply And Subtract Vector Fractional Words And Accumulate -MIPS_maq_s_w_qhrl, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_maq_s_l_pwr, // Multiply with Accumulate Single Vector Fractional Word Element -MIPS_dpau_h_obr, // Dot Product with Accumulate on Vector Unsigned Byte Elements -MIPS_dpsu_h_obr, // Dot Product with Subtract on Vector Unsigned Byte Elements -MIPS_maq_s_w_qhrr, // Multiply with Accumulate Single Vector Fractional Halfword Element -MIPS_dmsubu, // Multiply Vector Unsigned Words And Subtract From Accumulator -MIPS_extr_w, // Extract Word Value With Right Shift From Accumulator to GPR -MIPS_extrv_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR -MIPS_extp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR -MIPS_extpdp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos -MIPS_rddsp, // Read DSPControl Register Fields to a GPR -MIPS_shilo, // Shift an Accumulator Value Leaving the Result in the Same Accumulator -MIPS_extpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR -MIPS_extpdpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos -MIPS_wrdsp, // Write Fields to DSPControl Register from a GPR -MIPS_shilov, // Variable Shift of Accumulator Value Leaving the Result in the Same Accumulator -MIPS_extr_r_w, // Extract Word Value With Right Shift And Rounding From Accumulator to GPR -MIPS_extrv_r_w, // Extract Word Value With Variable Right Shift And Rounding From Accumulator to GPR -MIPS_extr_rs_w, // Extract Word Value With Right Shift From Accumulator to GPR -MIPS_extr_s_h, // Extract Halfword Value From Accumulator to GPR With Right Shift and Saturate -MIPS_extrv_rs_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR -MIPS_extrv_s_h, // Extract Halfword Value Variable From Accumulator to GPR With Right Shift and Saturate -MIPS_mthlip, // Copy LO to HI and a GPR to LO and Increment Pos by 32 -MIPS_dextr_w, // Extract Word Value With Right Shift From Accumulator to GPR -MIPS_dextr_l, // Extract Doubleword Value With Right Shift From Accumulator to GPR -MIPS_dextrv_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR -MIPS_dextrv_l, // Extract Doubleword Value With Variable Right Shift From Accumulator to GPR -MIPS_dextp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR -MIPS_dextpdp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos -MIPS_dshilo, // Shift an Accumulator Value Leaving the Result in the Same Accumulator -MIPS_dextpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR -MIPS_dextpdpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos -MIPS_dshilov, // Variable Shift of Accumulator Value Leaving the Result in the Same Accumulator -MIPS_dextr_r_w, // Extract Word Value With Right Shift And Rounding From Accumulator to GPR -MIPS_dextr_r_l, // Extract Doubleword Value With Right Shift And Rounding From Accumulator to GPR -MIPS_dextrv_r_w, // Extract Word Value With Variable Right Shift And Rounding From Accumulator to GPR -MIPS_dextrv_r_l, // Extract Doubleword Value With Variable Right Shift And Rounding From Accumulator to GPR -MIPS_dextr_rs_w, // Extract Word Value With Right Shift From Accumulator to GPR -MIPS_dextr_s_h, // Extract Halfword Value From Accumulator to GPR With Right Shift and Saturate -MIPS_dextr_rs_l, // Extract Doubleword Value With Right Shift From Accumulator to GPR -MIPS_dextrv_rs_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR -MIPS_dextrv_s_h, // Extract Halfword Value Variable From Accumulator to GPR With Right Shift and Saturate -MIPS_dextrv_rs_l, // Extract Doubleword Value With Variable Right Shift From Accumulator to GPR -MIPS_dmthlip, // Copy LO to HI and a GPR to LO and Increment Pos by 64 -MIPS_adduh_qb, // Unsigned Add Vector Quad-Bytes And Right Shift to Halve Results -MIPS_addqh_ph, // Add Fractional Halfword Vectors And Shift Right to Halve Results -MIPS_addqh_w, // Add Fractional Words And Shift Right to Halve Results -MIPS_subuh_qb, // Subtract Unsigned Bytes And Right Shift to Halve Results -MIPS_subqh_ph, // Subtract Fractional Halfword Vectors And Shift Right to Halve Results -MIPS_subqh_w, // Subtract Fractional Words And Shift Right to Halve Results -MIPS_adduh_r_qb, // Unsigned Add Vector Quad-Bytes And Right Shift to Halve Results -MIPS_addqh_r_ph, // Add Fractional Halfword Vectors And Shift Right to Halve Results -MIPS_addqh_r_w, // Add Fractional Words And Shift Right to Halve Results -MIPS_subuh_r_qb, // Subtract Unsigned Bytes And Right Shift to Halve Results -MIPS_subqh_r_ph, // Subtract Fractional Halfword Vectors And Shift Right to Halve Results -MIPS_subqh_r_w, // Subtract Fractional Words And Shift Right to Halve Results -MIPS_mul_ph, // Multiply Vector Integer HalfWords to Same Size Products -MIPS_mul_s_ph, // Multiply Vector Integer HalfWords to Same Size Products -MIPS_mulq_s_w, // Multiply Fractional Words to Same Size Product with Saturation -MIPS_mulq_rs_w, // Multiply Fractional Words to Same Size Product with Saturation and Rounding -MIPS_append, // Left Shift and Append Bits to the LSB -MIPS_balign, // Byte Align Contents from Two Registers -MIPS_prepend, // Right Shift and Prepend Bits to the MSB - -// Cavium Octeon II instructions -MIPS_laa, // Load Atomic Add Word -MIPS_laad, // Load Atomic Add Doubleword -MIPS_lac, // Load Atomic Clear Word -MIPS_lacd, // Load Atomic Clear Doubleword -MIPS_lad, // Load Atomic Decrement Word -MIPS_ladd, // Load Atomic Decrement Doubleword -MIPS_lai, // Load Atomic Increment Word -MIPS_laid, // Load Atomic Increment Doubleword -MIPS_las, // Load Atomic Set Word -MIPS_lasd, // Load Atomic Set Doubleword -MIPS_law, // Load Atomic Swap Word -MIPS_lawd, // Load Atomic Swap Doubleword -// we don't know the following mnemonics for sure -MIPS_lbx, // Load Byte Indexed -MIPS_lhux, // Load Halfword Unsigned Indexed -MIPS_lwux, // Load Word Unsigned Indexed -MIPS_qmac_00, // Q15 Multiply Accumulate -MIPS_qmac_01, // Q15 Multiply Accumulate -MIPS_qmac_02, // Q15 Multiply Accumulate -MIPS_qmac_03, // Q15 Multiply Accumulate -MIPS_qmacs_00, // Q15 Multiply Accumulate -MIPS_qmacs_01, // Q15 Multiply Accumulate -MIPS_qmacs_02, // Q15 Multiply Accumulate -MIPS_qmacs_03, // Q15 Multiply Accumulate -MIPS_zcb, // Zero Cache Block -MIPS_zcbt, // Zero Cache Block - -// MSA ASE -// some of these have the same name as existing mnemonics; to avoid ambiguity -// we use an msa_ prefix on all of them -MIPS_msa_sll_b, // Vector Shift Left -MIPS_msa_sll_h, // Vector Shift Left -MIPS_msa_sll_w, // Vector Shift Left -MIPS_msa_sll_d, // Vector Shift Left -MIPS_msa_slli_b, // Immediate Shift Left -MIPS_msa_slli_h, // Immediate Shift Left -MIPS_msa_slli_w, // Immediate Shift Left -MIPS_msa_slli_d, // Immediate Shift Left -MIPS_msa_sra_b, // Vector Shift Right Arithmetic -MIPS_msa_sra_h, // Vector Shift Right Arithmetic -MIPS_msa_sra_w, // Vector Shift Right Arithmetic -MIPS_msa_sra_d, // Vector Shift Right Arithmetic -MIPS_msa_srai_b, // Immediate Shift Right Arithmetic -MIPS_msa_srai_h, // Immediate Shift Right Arithmetic -MIPS_msa_srai_w, // Immediate Shift Right Arithmetic -MIPS_msa_srai_d, // Immediate Shift Right Arithmetic -MIPS_msa_srl_b, // Vector Shift Right Logical -MIPS_msa_srl_h, // Vector Shift Right Logical -MIPS_msa_srl_w, // Vector Shift Right Logical -MIPS_msa_srl_d, // Vector Shift Right Logical -MIPS_msa_srli_b, // Immediate Shift Right Logical -MIPS_msa_srli_h, // Immediate Shift Right Logical -MIPS_msa_srli_w, // Immediate Shift Right Logical -MIPS_msa_srli_d, // Immediate Shift Right Logical -MIPS_msa_bclr_b, // Vector Bit Clear -MIPS_msa_bclr_h, // Vector Bit Clear -MIPS_msa_bclr_w, // Vector Bit Clear -MIPS_msa_bclr_d, // Vector Bit Clear -MIPS_msa_bclri_b, // Immediate Bit Clear -MIPS_msa_bclri_h, // Immediate Bit Clear -MIPS_msa_bclri_w, // Immediate Bit Clear -MIPS_msa_bclri_d, // Immediate Bit Clear -MIPS_msa_bset_b, // Vector Bit Set -MIPS_msa_bset_h, // Vector Bit Set -MIPS_msa_bset_w, // Vector Bit Set -MIPS_msa_bset_d, // Vector Bit Set -MIPS_msa_bseti_b, // Immediate Bit Set -MIPS_msa_bseti_h, // Immediate Bit Set -MIPS_msa_bseti_w, // Immediate Bit Set -MIPS_msa_bseti_d, // Immediate Bit Set -MIPS_msa_bneg_b, // Vector Bit Negate -MIPS_msa_bneg_h, // Vector Bit Negate -MIPS_msa_bneg_w, // Vector Bit Negate -MIPS_msa_bneg_d, // Vector Bit Negate -MIPS_msa_bnegi_b, // Immediate Bit Negate -MIPS_msa_bnegi_h, // Immediate Bit Negate -MIPS_msa_bnegi_w, // Immediate Bit Negate -MIPS_msa_bnegi_d, // Immediate Bit Negate -MIPS_msa_binsl_b, // Vector Bit Insert Left -MIPS_msa_binsl_h, // Vector Bit Insert Left -MIPS_msa_binsl_w, // Vector Bit Insert Left -MIPS_msa_binsl_d, // Vector Bit Insert Left -MIPS_msa_binsli_b, // Immediate Bit Insert Left -MIPS_msa_binsli_h, // Immediate Bit Insert Left -MIPS_msa_binsli_w, // Immediate Bit Insert Left -MIPS_msa_binsli_d, // Immediate Bit Insert Left -MIPS_msa_binsr_b, // Vector Bit Insert Right -MIPS_msa_binsr_h, // Vector Bit Insert Right -MIPS_msa_binsr_w, // Vector Bit Insert Right -MIPS_msa_binsr_d, // Vector Bit Insert Right -MIPS_msa_binsri_b, // Immediate Bit Insert Right -MIPS_msa_binsri_h, // Immediate Bit Insert Right -MIPS_msa_binsri_w, // Immediate Bit Insert Right -MIPS_msa_binsri_d, // Immediate Bit Insert Right -MIPS_msa_addv_b, // Vector Add -MIPS_msa_addv_h, // Vector Add -MIPS_msa_addv_w, // Vector Add -MIPS_msa_addv_d, // Vector Add -MIPS_msa_addvi_b, // Immediate Add -MIPS_msa_addvi_h, // Immediate Add -MIPS_msa_addvi_w, // Immediate Add -MIPS_msa_addvi_d, // Immediate Add -MIPS_msa_subv_b, // Vector Subtract -MIPS_msa_subv_h, // Vector Subtract -MIPS_msa_subv_w, // Vector Subtract -MIPS_msa_subv_d, // Vector Subtract -MIPS_msa_subvi_b, // Immediate Subtract -MIPS_msa_subvi_h, // Immediate Subtract -MIPS_msa_subvi_w, // Immediate Subtract -MIPS_msa_subvi_d, // Immediate Subtract -MIPS_msa_max_s_b, // Vector Signed Maximum -MIPS_msa_max_s_h, // Vector Signed Maximum -MIPS_msa_max_s_w, // Vector Signed Maximum -MIPS_msa_max_s_d, // Vector Signed Maximum -MIPS_msa_maxi_s_b, // Immediate Signed Maximum -MIPS_msa_maxi_s_h, // Immediate Signed Maximum -MIPS_msa_maxi_s_w, // Immediate Signed Maximum -MIPS_msa_maxi_s_d, // Immediate Signed Maximum -MIPS_msa_max_u_b, // Vector Unsigned Maximum -MIPS_msa_max_u_h, // Vector Unsigned Maximum -MIPS_msa_max_u_w, // Vector Unsigned Maximum -MIPS_msa_max_u_d, // Vector Unsigned Maximum -MIPS_msa_maxi_u_b, // Immediate Unsigned Maximum -MIPS_msa_maxi_u_h, // Immediate Unsigned Maximum -MIPS_msa_maxi_u_w, // Immediate Unsigned Maximum -MIPS_msa_maxi_u_d, // Immediate Unsigned Maximum -MIPS_msa_min_s_b, // Vector Signed Minimum -MIPS_msa_min_s_h, // Vector Signed Minimum -MIPS_msa_min_s_w, // Vector Signed Minimum -MIPS_msa_min_s_d, // Vector Signed Minimum -MIPS_msa_mini_s_b, // Immediate Signed Minimum -MIPS_msa_mini_s_h, // Immediate Signed Minimum -MIPS_msa_mini_s_w, // Immediate Signed Minimum -MIPS_msa_mini_s_d, // Immediate Signed Minimum -MIPS_msa_min_u_b, // Vector Unsigned Minimum -MIPS_msa_min_u_h, // Vector Unsigned Minimum -MIPS_msa_min_u_w, // Vector Unsigned Minimum -MIPS_msa_min_u_d, // Vector Unsigned Minimum -MIPS_msa_mini_u_b, // Immediate Unsigned Minimum -MIPS_msa_mini_u_h, // Immediate Unsigned Minimum -MIPS_msa_mini_u_w, // Immediate Unsigned Minimum -MIPS_msa_mini_u_d, // Immediate Unsigned Minimum -MIPS_msa_max_a_b, // Vector Maximum Based on Absolute Values -MIPS_msa_max_a_h, // Vector Maximum Based on Absolute Values -MIPS_msa_max_a_w, // Vector Maximum Based on Absolute Values -MIPS_msa_max_a_d, // Vector Maximum Based on Absolute Values -MIPS_msa_min_a_b, // Vector Minimum Based on Absolute Value -MIPS_msa_min_a_h, // Vector Minimum Based on Absolute Value -MIPS_msa_min_a_w, // Vector Minimum Based on Absolute Value -MIPS_msa_min_a_d, // Vector Minimum Based on Absolute Value -MIPS_msa_ceq_b, // Vector Compare Equal -MIPS_msa_ceq_h, // Vector Compare Equal -MIPS_msa_ceq_w, // Vector Compare Equal -MIPS_msa_ceq_d, // Vector Compare Equal -MIPS_msa_ceqi_b, // Immediate Compare Equal -MIPS_msa_ceqi_h, // Immediate Compare Equal -MIPS_msa_ceqi_w, // Immediate Compare Equal -MIPS_msa_ceqi_d, // Immediate Compare Equal -MIPS_msa_clt_s_b, // Vector Compare Signed Less Than -MIPS_msa_clt_s_h, // Vector Compare Signed Less Than -MIPS_msa_clt_s_w, // Vector Compare Signed Less Than -MIPS_msa_clt_s_d, // Vector Compare Signed Less Than -MIPS_msa_clti_s_b, // Immediate Compare Signed Less Than -MIPS_msa_clti_s_h, // Immediate Compare Signed Less Than -MIPS_msa_clti_s_w, // Immediate Compare Signed Less Than -MIPS_msa_clti_s_d, // Immediate Compare Signed Less Than -MIPS_msa_clt_u_b, // Vector Compare Unsigned Less Than -MIPS_msa_clt_u_h, // Vector Compare Unsigned Less Than -MIPS_msa_clt_u_w, // Vector Compare Unsigned Less Than -MIPS_msa_clt_u_d, // Vector Compare Unsigned Less Than -MIPS_msa_clti_u_b, // Immediate Compare Unsigned Less Than -MIPS_msa_clti_u_h, // Immediate Compare Unsigned Less Than -MIPS_msa_clti_u_w, // Immediate Compare Unsigned Less Than -MIPS_msa_clti_u_d, // Immediate Compare Unsigned Less Than -MIPS_msa_cle_s_b, // Vector Compare Signed Less Than or Equal -MIPS_msa_cle_s_h, // Vector Compare Signed Less Than or Equal -MIPS_msa_cle_s_w, // Vector Compare Signed Less Than or Equal -MIPS_msa_cle_s_d, // Vector Compare Signed Less Than or Equal -MIPS_msa_clei_s_b, // Immediate Compare Signed Less Than or Equal -MIPS_msa_clei_s_h, // Immediate Compare Signed Less Than or Equal -MIPS_msa_clei_s_w, // Immediate Compare Signed Less Than or Equal -MIPS_msa_clei_s_d, // Immediate Compare Signed Less Than or Equal -MIPS_msa_cle_u_b, // Vector Compare Unsigned Less Than or Equal -MIPS_msa_cle_u_h, // Vector Compare Unsigned Less Than or Equal -MIPS_msa_cle_u_w, // Vector Compare Unsigned Less Than or Equal -MIPS_msa_cle_u_d, // Vector Compare Unsigned Less Than or Equal -MIPS_msa_clei_u_b, // Immediate Compare Unsigned Less Than or Equal -MIPS_msa_clei_u_h, // Immediate Compare Unsigned Less Than or Equal -MIPS_msa_clei_u_w, // Immediate Compare Unsigned Less Than or Equal -MIPS_msa_clei_u_d, // Immediate Compare Unsigned Less Than or Equal -MIPS_msa_ld_b, // Vector Load -MIPS_msa_ld_h, // Vector Load -MIPS_msa_ld_w, // Vector Load -MIPS_msa_ld_d, // Vector Load -MIPS_msa_st_b, // Vector Store -MIPS_msa_st_h, // Vector Store -MIPS_msa_st_w, // Vector Store -MIPS_msa_st_d, // Vector Store -MIPS_msa_sat_s_b, // Immediate Signed Saturate -MIPS_msa_sat_s_h, // Immediate Signed Saturate -MIPS_msa_sat_s_w, // Immediate Signed Saturate -MIPS_msa_sat_s_d, // Immediate Signed Saturate -MIPS_msa_sat_u_b, // Immediate Unsigned Saturate -MIPS_msa_sat_u_h, // Immediate Unsigned Saturate -MIPS_msa_sat_u_w, // Immediate Unsigned Saturate -MIPS_msa_sat_u_d, // Immediate Unsigned Saturate -MIPS_msa_add_a_b, // Vector Add Absolute Values -MIPS_msa_add_a_h, // Vector Add Absolute Values -MIPS_msa_add_a_w, // Vector Add Absolute Values -MIPS_msa_add_a_d, // Vector Add Absolute Values -MIPS_msa_adds_a_b, // Vector Saturated Add of Absolute Values -MIPS_msa_adds_a_h, // Vector Saturated Add of Absolute Values -MIPS_msa_adds_a_w, // Vector Saturated Add of Absolute Values -MIPS_msa_adds_a_d, // Vector Saturated Add of Absolute Values -MIPS_msa_adds_s_b, // Vector Signed Saturated Add of Signed Values -MIPS_msa_adds_s_h, // Vector Signed Saturated Add of Signed Values -MIPS_msa_adds_s_w, // Vector Signed Saturated Add of Signed Values -MIPS_msa_adds_s_d, // Vector Signed Saturated Add of Signed Values -MIPS_msa_adds_u_b, // Vector Unsigned Saturated Add of Unsigned Values -MIPS_msa_adds_u_h, // Vector Unsigned Saturated Add of Unsigned Values -MIPS_msa_adds_u_w, // Vector Unsigned Saturated Add of Unsigned Values -MIPS_msa_adds_u_d, // Vector Unsigned Saturated Add of Unsigned Values -MIPS_msa_ave_s_b, // Vector Signed Average -MIPS_msa_ave_s_h, // Vector Signed Average -MIPS_msa_ave_s_w, // Vector Signed Average -MIPS_msa_ave_s_d, // Vector Signed Average -MIPS_msa_ave_u_b, // Vector Unsigned Average -MIPS_msa_ave_u_h, // Vector Unsigned Average -MIPS_msa_ave_u_w, // Vector Unsigned Average -MIPS_msa_ave_u_d, // Vector Unsigned Average -MIPS_msa_aver_s_b, // Vector Signed Average Rounded -MIPS_msa_aver_s_h, // Vector Signed Average Rounded -MIPS_msa_aver_s_w, // Vector Signed Average Rounded -MIPS_msa_aver_s_d, // Vector Signed Average Rounded -MIPS_msa_aver_u_b, // Vector Unsigned Average Rounded -MIPS_msa_aver_u_h, // Vector Unsigned Average Rounded -MIPS_msa_aver_u_w, // Vector Unsigned Average Rounded -MIPS_msa_aver_u_d, // Vector Unsigned Average Rounded -MIPS_msa_subs_s_b, // Vector Signed Saturated Subtract of Signed Values -MIPS_msa_subs_s_h, // Vector Signed Saturated Subtract of Signed Values -MIPS_msa_subs_s_w, // Vector Signed Saturated Subtract of Signed Values -MIPS_msa_subs_s_d, // Vector Signed Saturated Subtract of Signed Values -MIPS_msa_subs_u_b, // Vector Unsigned Saturated Subtract of Unsigned Values -MIPS_msa_subs_u_h, // Vector Unsigned Saturated Subtract of Unsigned Values -MIPS_msa_subs_u_w, // Vector Unsigned Saturated Subtract of Unsigned Values -MIPS_msa_subs_u_d, // Vector Unsigned Saturated Subtract of Unsigned Values -MIPS_msa_subsus_u_b, // Vector Unsigned Saturated Subtract of Signed from Unsigned -MIPS_msa_subsus_u_h, // Vector Unsigned Saturated Subtract of Signed from Unsigned -MIPS_msa_subsus_u_w, // Vector Unsigned Saturated Subtract of Signed from Unsigned -MIPS_msa_subsus_u_d, // Vector Unsigned Saturated Subtract of Signed from Unsigned -MIPS_msa_subsuu_s_b, // Vector Signed Saturated Subtract of Unsigned Values -MIPS_msa_subsuu_s_h, // Vector Signed Saturated Subtract of Unsigned Values -MIPS_msa_subsuu_s_w, // Vector Signed Saturated Subtract of Unsigned Values -MIPS_msa_subsuu_s_d, // Vector Signed Saturated Subtract of Unsigned Values -MIPS_msa_asub_s_b, // Vector Absolute Values of Signed Subtract -MIPS_msa_asub_s_h, // Vector Absolute Values of Signed Subtract -MIPS_msa_asub_s_w, // Vector Absolute Values of Signed Subtract -MIPS_msa_asub_s_d, // Vector Absolute Values of Signed Subtract -MIPS_msa_asub_u_b, // Vector Absolute Values of Unsigned Subtract -MIPS_msa_asub_u_h, // Vector Absolute Values of Unsigned Subtract -MIPS_msa_asub_u_w, // Vector Absolute Values of Unsigned Subtract -MIPS_msa_asub_u_d, // Vector Absolute Values of Unsigned Subtract -MIPS_msa_mulv_b, // Vector Multiply -MIPS_msa_mulv_h, // Vector Multiply -MIPS_msa_mulv_w, // Vector Multiply -MIPS_msa_mulv_d, // Vector Multiply -MIPS_msa_maddv_b, // Vector Multiply and Add -MIPS_msa_maddv_h, // Vector Multiply and Add -MIPS_msa_maddv_w, // Vector Multiply and Add -MIPS_msa_maddv_d, // Vector Multiply and Add -MIPS_msa_msubv_b, // Vector Multiply and Subtract -MIPS_msa_msubv_h, // Vector Multiply and Subtract -MIPS_msa_msubv_w, // Vector Multiply and Subtract -MIPS_msa_msubv_d, // Vector Multiply and Subtract -MIPS_msa_div_s_b, // Vector Signed Divide -MIPS_msa_div_s_h, // Vector Signed Divide -MIPS_msa_div_s_w, // Vector Signed Divide -MIPS_msa_div_s_d, // Vector Signed Divide -MIPS_msa_div_u_b, // Vector Unsigned Divide -MIPS_msa_div_u_h, // Vector Unsigned Divide -MIPS_msa_div_u_w, // Vector Unsigned Divide -MIPS_msa_div_u_d, // Vector Unsigned Divide -MIPS_msa_mod_s_b, // Vector Signed Modulo -MIPS_msa_mod_s_h, // Vector Signed Modulo -MIPS_msa_mod_s_w, // Vector Signed Modulo -MIPS_msa_mod_s_d, // Vector Signed Modulo -MIPS_msa_mod_u_b, // Vector Unsigned Modulo -MIPS_msa_mod_u_h, // Vector Unsigned Modulo -MIPS_msa_mod_u_w, // Vector Unsigned Modulo -MIPS_msa_mod_u_d, // Vector Unsigned Modulo -MIPS_msa_dotp_s_h, // Vector Signed Dot Product -MIPS_msa_dotp_s_w, // Vector Signed Dot Product -MIPS_msa_dotp_s_d, // Vector Signed Dot Product -MIPS_msa_dotp_u_h, // Vector Unsigned Dot Product -MIPS_msa_dotp_u_w, // Vector Unsigned Dot Product -MIPS_msa_dotp_u_d, // Vector Unsigned Dot Product -MIPS_msa_dpadd_s_h, // Vector Signed Dot Product and Add -MIPS_msa_dpadd_s_w, // Vector Signed Dot Product and Add -MIPS_msa_dpadd_s_d, // Vector Signed Dot Product and Add -MIPS_msa_dpadd_u_h, // Vector Unsigned Dot Product and Add -MIPS_msa_dpadd_u_w, // Vector Unsigned Dot Product and Add -MIPS_msa_dpadd_u_d, // Vector Unsigned Dot Product and Add -MIPS_msa_dpsub_s_h, // Vector Signed Dot Product and Subtract -MIPS_msa_dpsub_s_w, // Vector Signed Dot Product and Subtract -MIPS_msa_dpsub_s_d, // Vector Signed Dot Product and Subtract -MIPS_msa_dpsub_u_h, // Vector Unsigned Dot Product and Subtract -MIPS_msa_dpsub_u_w, // Vector Unsigned Dot Product and Subtract -MIPS_msa_dpsub_u_d, // Vector Unsigned Dot Product and Subtract -MIPS_msa_sld_b, // GPR Columns Slide -MIPS_msa_sld_h, // GPR Columns Slide -MIPS_msa_sld_w, // GPR Columns Slide -MIPS_msa_sld_d, // GPR Columns Slide -MIPS_msa_sldi_b, // Immediate Columns Slide -MIPS_msa_sldi_h, // Immediate Columns Slide -MIPS_msa_sldi_w, // Immediate Columns Slide -MIPS_msa_sldi_d, // Immediate Columns Slide -MIPS_msa_splat_b, // GPR Element Splat -MIPS_msa_splat_h, // GPR Element Splat -MIPS_msa_splat_w, // GPR Element Splat -MIPS_msa_splat_d, // GPR Element Splat -MIPS_msa_splati_b, // Immediate Element Splat -MIPS_msa_splati_h, // Immediate Element Splat -MIPS_msa_splati_w, // Immediate Element Splat -MIPS_msa_splati_d, // Immediate Element Splat -MIPS_msa_pckev_b, // Vector Pack Even -MIPS_msa_pckev_h, // Vector Pack Even -MIPS_msa_pckev_w, // Vector Pack Even -MIPS_msa_pckev_d, // Vector Pack Even -MIPS_msa_pckod_b, // Vector Pack Odd -MIPS_msa_pckod_h, // Vector Pack Odd -MIPS_msa_pckod_w, // Vector Pack Odd -MIPS_msa_pckod_d, // Vector Pack Odd -MIPS_msa_ilvl_b, // Vector Interleave Left -MIPS_msa_ilvl_h, // Vector Interleave Left -MIPS_msa_ilvl_w, // Vector Interleave Left -MIPS_msa_ilvl_d, // Vector Interleave Left -MIPS_msa_ilvr_b, // Vector Interleave Right -MIPS_msa_ilvr_h, // Vector Interleave Right -MIPS_msa_ilvr_w, // Vector Interleave Right -MIPS_msa_ilvr_d, // Vector Interleave Right -MIPS_msa_ilvev_b, // Vector Interleave Even -MIPS_msa_ilvev_h, // Vector Interleave Even -MIPS_msa_ilvev_w, // Vector Interleave Even -MIPS_msa_ilvev_d, // Vector Interleave Even -MIPS_msa_ilvod_b, // Vector Interleave Odd -MIPS_msa_ilvod_h, // Vector Interleave Odd -MIPS_msa_ilvod_w, // Vector Interleave Odd -MIPS_msa_ilvod_d, // Vector Interleave Odd -MIPS_msa_vshf_b, // Vector Data Preserving Shuffle -MIPS_msa_vshf_h, // Vector Data Preserving Shuffle -MIPS_msa_vshf_w, // Vector Data Preserving Shuffle -MIPS_msa_vshf_d, // Vector Data Preserving Shuffle -MIPS_msa_srar_b, // Vector Shift Right Arithmetic Rounded -MIPS_msa_srar_h, // Vector Shift Right Arithmetic Rounded -MIPS_msa_srar_w, // Vector Shift Right Arithmetic Rounded -MIPS_msa_srar_d, // Vector Shift Right Arithmetic Rounded -MIPS_msa_srari_b, // Immediate Shift Right Arithmetic Rounded -MIPS_msa_srari_h, // Immediate Shift Right Arithmetic Rounded -MIPS_msa_srari_w, // Immediate Shift Right Arithmetic Rounded -MIPS_msa_srari_d, // Immediate Shift Right Arithmetic Rounded -MIPS_msa_srlr_b, // Vector Shift Right Logical Rounded -MIPS_msa_srlr_h, // Vector Shift Right Logical Rounded -MIPS_msa_srlr_w, // Vector Shift Right Logical Rounded -MIPS_msa_srlr_d, // Vector Shift Right Logical Rounded -MIPS_msa_srlri_b, // Immediate Shift Right Logical Rounded -MIPS_msa_srlri_h, // Immediate Shift Right Logical Rounded -MIPS_msa_srlri_w, // Immediate Shift Right Logical Rounded -MIPS_msa_srlri_d, // Immediate Shift Right Logical Rounded -MIPS_msa_hadd_s_h, // Vector Signed Horizontal Add -MIPS_msa_hadd_s_w, // Vector Signed Horizontal Add -MIPS_msa_hadd_s_d, // Vector Signed Horizontal Add -MIPS_msa_hadd_u_h, // Vector Unsigned Horizontal Add -MIPS_msa_hadd_u_w, // Vector Unsigned Horizontal Add -MIPS_msa_hadd_u_d, // Vector Unsigned Horizontal Add -MIPS_msa_hsub_s_h, // Vector Signed Horizontal Subtract -MIPS_msa_hsub_s_w, // Vector Signed Horizontal Subtract -MIPS_msa_hsub_s_d, // Vector Signed Horizontal Subtract -MIPS_msa_hsub_u_h, // Vector Unsigned Horizontal Subtract -MIPS_msa_hsub_u_w, // Vector Unsigned Horizontal Subtract -MIPS_msa_hsub_u_d, // Vector Unsigned Horizontal Subtract -MIPS_msa_and_v, // Vector Logical And -MIPS_msa_andi_b, // Immediate Logical And -MIPS_msa_or_v, // Vector Logical Or -MIPS_msa_ori_b, // Immediate Logical Or -MIPS_msa_nor_v, // Vector Logical Negated Or -MIPS_msa_nori_b, // Immediate Logical Negated Or -MIPS_msa_xor_v, // Vector Logical Exclusive Or -MIPS_msa_xori_b, // Immediate Logical Exclusive Or -MIPS_msa_bmnz_v, // Vector Bit Move If Not Zero -MIPS_msa_bmnzi_b, // Immediate Bit Move If Not Zero -MIPS_msa_bmz_v, // Vector Bit Move If Zero -MIPS_msa_bmzi_b, // Immediate Bit Move If Zero -MIPS_msa_bsel_v, // Vector Bit Select -MIPS_msa_bseli_b, // Immediate Bit Select -MIPS_msa_shf_b, // Immediate Set Shuffle Elements -MIPS_msa_shf_h, // Immediate Set Shuffle Elements -MIPS_msa_shf_w, // Immediate Set Shuffle Elements -MIPS_msa_bnz_v, // Immediate Branch If Not Zero (At Least One Element of Any Format Is Not Zero) -MIPS_msa_bz_v, // Immediate Branch If Zero (All Elements of Any Format Are Zero) -MIPS_msa_fill_b, // Vector Fill from GPR -MIPS_msa_fill_h, // Vector Fill from GPR -MIPS_msa_fill_w, // Vector Fill from GPR -MIPS_msa_fill_d, // Vector Fill from GPR -MIPS_msa_pcnt_b, // Vector Population Count -MIPS_msa_pcnt_h, // Vector Population Count -MIPS_msa_pcnt_w, // Vector Population Count -MIPS_msa_pcnt_d, // Vector Population Count -MIPS_msa_nloc_b, // Vector Leading Ones Count -MIPS_msa_nloc_h, // Vector Leading Ones Count -MIPS_msa_nloc_w, // Vector Leading Ones Count -MIPS_msa_nloc_d, // Vector Leading Ones Count -MIPS_msa_nlzc_b, // Vector Leading Zeros Count -MIPS_msa_nlzc_h, // Vector Leading Zeros Count -MIPS_msa_nlzc_w, // Vector Leading Zeros Count -MIPS_msa_nlzc_d, // Vector Leading Zeros Count -MIPS_msa_copy_s_b, // Element Copy to GPR Signed -MIPS_msa_copy_s_h, // Element Copy to GPR Signed -MIPS_msa_copy_s_w, // Element Copy to GPR Signed -MIPS_msa_copy_s_d, // Element Copy to GPR Signed -MIPS_msa_copy_u_b, // Element Copy to GPR Unsigned -MIPS_msa_copy_u_h, // Element Copy to GPR Unsigned -MIPS_msa_copy_u_w, // Element Copy to GPR Unsigned -MIPS_msa_copy_u_d, // Element Copy to GPR Unsigned -MIPS_msa_insert_b, // GPR Insert Element -MIPS_msa_insert_h, // GPR Insert Element -MIPS_msa_insert_w, // GPR Insert Element -MIPS_msa_insert_d, // GPR Insert Element -MIPS_msa_insve_b, // Element Insert Element -MIPS_msa_insve_h, // Element Insert Element -MIPS_msa_insve_w, // Element Insert Element -MIPS_msa_insve_d, // Element Insert Element -MIPS_msa_bnz_b, // Immediate Branch If All Elements Are Not Zero -MIPS_msa_bnz_h, // Immediate Branch If All Elements Are Not Zero -MIPS_msa_bnz_w, // Immediate Branch If All Elements Are Not Zero -MIPS_msa_bnz_d, // Immediate Branch If All Elements Are Not Zero -MIPS_msa_bz_b, // Immediate Branch If At Least One Element Is Zero -MIPS_msa_bz_h, // Immediate Branch If At Least One Element Is Zero -MIPS_msa_bz_w, // Immediate Branch If At Least One Element Is Zero -MIPS_msa_bz_d, // Immediate Branch If At Least One Element Is Zero -MIPS_msa_ldi_b, // Immediate Load -MIPS_msa_ldi_h, // Immediate Load -MIPS_msa_ldi_w, // Immediate Load -MIPS_msa_ldi_d, // Immediate Load -MIPS_msa_fcaf_w, // Vector Floating-Point Quiet Compare Always False -MIPS_msa_fcaf_d, // Vector Floating-Point Quiet Compare Always False -MIPS_msa_fcun_w, // Vector Floating-Point Quiet Compare Unordered -MIPS_msa_fcun_d, // Vector Floating-Point Quiet Compare Unordered -MIPS_msa_fceq_w, // Vector Floating-Point Quiet Compare Equal -MIPS_msa_fceq_d, // Vector Floating-Point Quiet Compare Equal -MIPS_msa_fcueq_w, // Vector Floating-Point Quiet Compare Unordered or Equal -MIPS_msa_fcueq_d, // Vector Floating-Point Quiet Compare Unordered or Equal -MIPS_msa_fclt_w, // Vector Floating-Point Quiet Compare Less Than -MIPS_msa_fclt_d, // Vector Floating-Point Quiet Compare Less Than -MIPS_msa_fcult_w, // Vector Floating-Point Quiet Compare Unordered or Less Than -MIPS_msa_fcult_d, // Vector Floating-Point Quiet Compare Unordered or Less Than -MIPS_msa_fcle_w, // Vector Floating-Point Quiet Compare Less or Equal -MIPS_msa_fcle_d, // Vector Floating-Point Quiet Compare Less or Equal -MIPS_msa_fcule_w, // Vector Floating-Point Quiet Compare Unordered or Less or Equal -MIPS_msa_fcule_d, // Vector Floating-Point Quiet Compare Unordered or Less or Equal -MIPS_msa_fsaf_w, // Vector Floating-Point Signaling Compare Always False -MIPS_msa_fsaf_d, // Vector Floating-Point Signaling Compare Always False -MIPS_msa_fsun_w, // Vector Floating-Point Signaling Compare Unordered -MIPS_msa_fsun_d, // Vector Floating-Point Signaling Compare Unordered -MIPS_msa_fseq_w, // Vector Floating-Point Signaling Compare Equal -MIPS_msa_fseq_d, // Vector Floating-Point Signaling Compare Equal -MIPS_msa_fsueq_w, // Vector Floating-Point Signaling Compare Unordered or Equal -MIPS_msa_fsueq_d, // Vector Floating-Point Signaling Compare Unordered or Equal -MIPS_msa_fslt_w, // Vector Floating-Point Signaling Compare Less Than -MIPS_msa_fslt_d, // Vector Floating-Point Signaling Compare Less Than -MIPS_msa_fsult_w, // Vector Floating-Point Signaling Compare Unordered or Less Than -MIPS_msa_fsult_d, // Vector Floating-Point Signaling Compare Unordered or Less Than -MIPS_msa_fsle_w, // Vector Floating-Point Signaling Compare Less or Equal -MIPS_msa_fsle_d, // Vector Floating-Point Signaling Compare Less or Equal -MIPS_msa_fsule_w, // Vector Floating-Point Signaling Compare Unordered or Less or Equal -MIPS_msa_fsule_d, // Vector Floating-Point Signaling Compare Unordered or Less or Equal -MIPS_msa_fadd_w, // Vector Floating-Point Addition -MIPS_msa_fadd_d, // Vector Floating-Point Addition -MIPS_msa_fsub_w, // Vector Floating-Point Subtraction -MIPS_msa_fsub_d, // Vector Floating-Point Subtraction -MIPS_msa_fmul_w, // Vector Floating-Point Multiplication -MIPS_msa_fmul_d, // Vector Floating-Point Multiplication -MIPS_msa_fdiv_w, // Vector Floating-Point Division -MIPS_msa_fdiv_d, // Vector Floating-Point Division -MIPS_msa_fmadd_w, // Vector Floating-Point Multiply-Add -MIPS_msa_fmadd_d, // Vector Floating-Point Multiply-Add -MIPS_msa_fmsub_w, // Vector Floating-Point Multiply-Sub -MIPS_msa_fmsub_d, // Vector Floating-Point Multiply-Sub -MIPS_msa_fexp2_w, // Vector Floating-Point Base 2 Exponentiation -MIPS_msa_fexp2_d, // Vector Floating-Point Base 2 Exponentiation -MIPS_msa_fexdo_h, // Vector Floating-Point Down-Convert Interchange Format -MIPS_msa_fexdo_w, // Vector Floating-Point Down-Convert Interchange Format -MIPS_msa_ftq_h, // Vector Floating-Point Convert to Fixed-Point -MIPS_msa_ftq_w, // Vector Floating-Point Convert to Fixed-Point -MIPS_msa_fmin_w, // Vector Floating-Point Minimum -MIPS_msa_fmin_d, // Vector Floating-Point Minimum -MIPS_msa_fmin_a_w, // Vector Floating-Point Minimum Based on Absolute Values -MIPS_msa_fmin_a_d, // Vector Floating-Point Minimum Based on Absolute Values -MIPS_msa_fmax_w, // Vector Floating-Point Maximum -MIPS_msa_fmax_d, // Vector Floating-Point Maximum -MIPS_msa_fmax_a_w, // Vector Floating-Point Maximum Based on Absolute Values -MIPS_msa_fmax_a_d, // Vector Floating-Point Maximum Based on Absolute Values -MIPS_msa_fcor_w, // Vector Floating-Point Quiet Compare Ordered -MIPS_msa_fcor_d, // Vector Floating-Point Quiet Compare Ordered -MIPS_msa_fcune_w, // Vector Floating-Point Quiet Compare Unordered or Not Equal -MIPS_msa_fcune_d, // Vector Floating-Point Quiet Compare Unordered or Not Equal -MIPS_msa_fcne_w, // Vector Floating-Point Quiet Compare Not Equal -MIPS_msa_fcne_d, // Vector Floating-Point Quiet Compare Not Equal -MIPS_msa_mul_q_h, // Vector Fixed-Point Multiply -MIPS_msa_mul_q_w, // Vector Fixed-Point Multiply -MIPS_msa_madd_q_h, // Vector Fixed-Point Multiply and Add -MIPS_msa_madd_q_w, // Vector Fixed-Point Multiply and Add -MIPS_msa_msub_q_h, // Vector Fixed-Point Multiply and Subtract -MIPS_msa_msub_q_w, // Vector Fixed-Point Multiply and Subtract -MIPS_msa_fsor_w, // Vector Floating-Point Signaling Compare Ordered -MIPS_msa_fsor_d, // Vector Floating-Point Signaling Compare Ordered -MIPS_msa_fsune_w, // Vector Floating-Point Signaling Compare Unordered or Not Equal -MIPS_msa_fsune_d, // Vector Floating-Point Signaling Compare Unordered or Not Equal -MIPS_msa_fsne_w, // Vector Floating-Point Signaling Compare Not Equal -MIPS_msa_fsne_d, // Vector Floating-Point Signaling Compare Not Equal -MIPS_msa_mulr_q_h, // Vector Fixed-Point Multiply Rounded -MIPS_msa_mulr_q_w, // Vector Fixed-Point Multiply Rounded -MIPS_msa_maddr_q_h, // Vector Fixed-Point Multiply and Add Rounded -MIPS_msa_maddr_q_w, // Vector Fixed-Point Multiply and Add Rounded -MIPS_msa_msubr_q_h, // Vector Fixed-Point Multiply and Subtract Rounded -MIPS_msa_msubr_q_w, // Vector Fixed-Point Multiply and Subtract Rounded -MIPS_msa_fclass_w, // Vector Floating-Point Class Mask -MIPS_msa_fclass_d, // Vector Floating-Point Class Mask -MIPS_msa_ftrunc_s_w, // Vector Floating-Point Truncate and Convert to Signed Integer -MIPS_msa_ftrunc_s_d, // Vector Floating-Point Truncate and Convert to Signed Integer -MIPS_msa_ftrunc_u_w, // Vector Floating-Point Truncate and Convert to Unsigned Integer -MIPS_msa_ftrunc_u_d, // Vector Floating-Point Truncate and Convert to Unsigned Integer -MIPS_msa_fsqrt_w, // Vector Floating-Point Square Root -MIPS_msa_fsqrt_d, // Vector Floating-Point Square Root -MIPS_msa_frsqrt_w, // Vector Approximate Floating-Point Reciprocal of Square Root -MIPS_msa_frsqrt_d, // Vector Approximate Floating-Point Reciprocal of Square Root -MIPS_msa_frcp_w, // Vector Approximate Floating-Point Reciprocal -MIPS_msa_frcp_d, // Vector Approximate Floating-Point Reciprocal -MIPS_msa_frint_w, // Vector Floating-Point Round to Integer -MIPS_msa_frint_d, // Vector Floating-Point Round to Integer -MIPS_msa_flog2_w, // Vector Floating-Point Base 2 Logarithm -MIPS_msa_flog2_d, // Vector Floating-Point Base 2 Logarithm -MIPS_msa_fexupl_w, // Vector Floating-Point Up-Convert Interchange Format Left -MIPS_msa_fexupl_d, // Vector Floating-Point Up-Convert Interchange Format Left -MIPS_msa_fexupr_w, // Vector Floating-Point Up-Convert Interchange Format Right -MIPS_msa_fexupr_d, // Vector Floating-Point Up-Convert Interchange Format Right -MIPS_msa_ffql_w, // Vector Floating-Point Convert from Fixed-Point Left -MIPS_msa_ffql_d, // Vector Floating-Point Convert from Fixed-Point Left -MIPS_msa_ffqr_w, // Vector Floating-Point Convert from Fixed-Point Right -MIPS_msa_ffqr_d, // Vector Floating-Point Convert from Fixed-Point Right -MIPS_msa_ftint_s_w, // Vector Floating-Point Convert to Signed Integer -MIPS_msa_ftint_s_d, // Vector Floating-Point Convert to Signed Integer -MIPS_msa_ftint_u_w, // Vector Floating-Point Round and Convert to Unsigned Integer -MIPS_msa_ftint_u_d, // Vector Floating-Point Round and Convert to Unsigned Integer -MIPS_msa_ffint_s_w, // Vector Floating-Point Round and Convert from Signed Integer -MIPS_msa_ffint_s_d, // Vector Floating-Point Round and Convert from Signed Integer -MIPS_msa_ffint_u_w, // Vector Floating-Point Convert from Unsigned Integer -MIPS_msa_ffint_u_d, // Vector Floating-Point Convert from Unsigned Integer -MIPS_msa_ctcmsa, // GPR Copy to MSA Control Register -MIPS_msa_cfcmsa, // GPR Copy from MSA Control Register -MIPS_msa_move_v, // Vector Move - -// MIPS R6 (LSA is also part of MSA) -MIPS_lsa, // Left Shift Add -MIPS_dlsa, // Doubleword Left Shift Add - -MIPS_last, - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -H8_null = 0, // Unknown Operation - -H8_add, // Add binary -H8_adds, // Add with sign extension -H8_addx, // Add with extend carry -H8_and, // Logical AND -H8_andc, // Logical AND with control register -H8_band, // Bit AND -H8_bra, // Branch always -H8_brn, // Branch never -H8_bhi, // Branch if higher -H8_bls, // Branch if lower or same -H8_bcc, // Branch if carry clear (higher or same) -H8_bcs, // Branch if carry set (lower) -H8_bne, // Branch if not equal -H8_beq, // Branch if equal -H8_bvc, // Branch if overflow clear -H8_bvs, // Branch if overflow set -H8_bpl, // Branch if plus -H8_bmi, // Branch if minus -H8_bge, // Branch if greates or equal -H8_blt, // Branch if less -H8_bgt, // Branch if greater -H8_ble, // Branch if less or equal -H8_bclr, // Bit clear -H8_biand, // Bit invert AND -H8_bild, // Bit invert load -H8_bior, // Bit invert OR -H8_bist, // Bit invert store -H8_bixor, // Bit invert XOR -H8_bld, // Bit load -H8_bnot, // Bit NOT -H8_bor, // Bit OR -H8_bset, // Bit set -H8_bsr, // Branch to subroutine -H8_bst, // Bit store -H8_btst, // Bit test -H8_bxor, // Bit XOR -H8_clrmac, // Clear MAC register -H8_cmp, // Compare -H8_daa, // Decimal adjust add -H8_das, // Decimal adjust subtract -H8_dec, // Decrement -H8_divxs, // Divide extended as signed -H8_divxu, // Divide extended as unsigned -H8_eepmov, // Move data to EEPROM -H8_exts, // Extend as signed -H8_extu, // Extend as unsigned -H8_inc, // Increment -H8_jmp, // Jump -H8_jsr, // Jump to subroutine -H8_ldc, // Load to control register -H8_ldm, // Load to multiple registers -H8_ldmac, // Load to MAC register -H8_mac, // Multiply and accumulate -H8_mov, // Move data -H8_movfpe, // Move from peripheral with E clock -H8_movtpe, // Move to peripheral with E clock -H8_mulxs, // Multiply extend as signed -H8_mulxu, // Multiply extend as unsigned -H8_neg, // Negate -H8_nop, // No operation -H8_not, // Logical complement -H8_or, // Logical OR -H8_orc, // Logical OR with control register -H8_pop, // Pop data from stack -H8_push, // Push data on stack -H8_rotl, // Rotate left -H8_rotr, // Rotate right -H8_rotxl, // Rotate with extend carry left -H8_rotxr, // Rotate with extend carry right -H8_rte, // Return from exception -H8_rts, // Return from subroutine -H8_shal, // Shift arithmetic left -H8_shar, // Shift arithmetic right -H8_shll, // Shift logical left -H8_shlr, // Shift logical right -H8_sleep, // Power down mode -H8_stc, // Store from control register -H8_stm, // Store from multiple registers -H8_stmac, // Store from MAC register -H8_sub, // Subtract binary -H8_subs, // Subtract with sign extension -H8_subx, // Subtract with extend carry -H8_tas, // Test and set -H8_trapa, // Trap always -H8_xor, // Logical XOR -H8_xorc, // Logical XOR with control register - -// H8SX -H8_rtel, // Returns from an exception, restoring data to multiple general registers -H8_rtsl, // Returns from a subroutine, restoring data to multiple general registers -H8_movmd, // Transfers a data block -H8_movsd, // Transfers a data block with zero detection -H8_bras, // Branch always after the next instruction (delay slot) -H8_movab, // MOVe effective Address/B -H8_movaw, // MOVe effective Address/W -H8_moval, // MOVe effective Address/L -H8_bsetne, // Bit SET if Not Equal -H8_bseteq, // Bit SET if EQual -H8_bclrne, // Bit CLeaR if Not Equal -H8_bclreq, // Bit CLeaR if Equal -H8_bstz, // Bit STore Zero flag -H8_bistz, // Bit Invert STore Zero flag -H8_bfld, // Bit Field LoaD -H8_bfst, // Bit Field STore -H8_muls, // MULtiply as Signed -H8_divs, // DIVide as Signed -H8_mulu, // MULtiply as Unsigned -H8_divu, // DIVide as Unsigned -H8_mulsu, // MULtiply as Signed -H8_muluu, // MULtiply as Unsigned -H8_brabc, // BRAnch if Bit Cleared -H8_brabs, // BRAnch if Bit Set -H8_bsrbc, // Branch to SubRoutine if Bit Cleared -H8_bsrbs, // Branch to SubRoutine if Bit Set - -H8_last, - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -PIC_null = 0, // Unknown Operation - -// BYTE-ORIENTED FILE REGISTER OPERATIONS - -PIC_addwf, // Add W and f -PIC_andwf, // AND W with f -PIC_clrf, // Clear f -PIC_clrw, // Clear W -PIC_comf, // Complement f -PIC_decf, // Decrement f -PIC_decfsz, // Decrement f, Skip if 0 -PIC_incf, // Increment f -PIC_incfsz, // Increment f, Skip if 0 -PIC_iorwf, // Inclusive OR W with f -PIC_movf, // Move f -PIC_movwf, // Move W to f -PIC_nop, // No Operation -PIC_rlf, // Rotate Left f through Carry -PIC_rrf, // Rotate Right f through Carry -PIC_subwf, // Subtract W from f -PIC_swapf, // Swap nibbles in f -PIC_xorwf, // Exclusive OR W with f - -// BIT-ORIENTED FILE REGISTER OPERATIONS - -PIC_bcf, // Bit Clear f -PIC_bsf, // Bit Set f -PIC_btfsc, // Bit Test f, Skip if Clear -PIC_btfss, // Bit Test f, Skip if Set - - -// LITERAL AND CONTROL OPERATIONS - -PIC_addlw, // Add literal and W -PIC_andlw, // AND literal with W -PIC_call, // Call subroutine -PIC_clrwdt, // Clear Watchdog Timer -PIC_goto, // Go to address -PIC_iorlw, // Inclusive OR literal with W -PIC_movlw, // Move literal to W -PIC_retfie, // Return from interrupt -PIC_retlw, // Return with literal in W -PIC_return, // Return from Subroutine -PIC_sleep, // Go into standby mode -PIC_sublw, // Subtract W from literal -PIC_xorlw, // Exclusive OR literal with W - -// ADDITIONAL INSTRUCTIONS TO MAINTAIN COMPITIBILITY WITH 12C5xx,16C5x - -PIC_option, // Load OPTION register -PIC_tris, // Load TRIS Register - -// MACROS - -PIC_movfw, // Move Contents of File Reg to W -PIC_tstf, // Test Contents of File Register -PIC_negf, // Negate File Register Contents -PIC_b, // Branch to Address -PIC_clrc, // Clear Carry -PIC_clrdc, // Clear Digit Carry -PIC_clrz, // Clear Zero -PIC_setc, // Set Carry -PIC_setdc, // Set Digit Carry -PIC_setz, // Set Zero -PIC_skpc, // Skip on Carry -PIC_skpdc, // Skip on Digit Carry -PIC_skpnc, // Skip on No Carry -PIC_skpndc, // Skip on No Digit Carry -PIC_skpnz, // Skip on No Zero -PIC_skpz, // Skip on Zero -PIC_bc, // Branch on Carry to Address k -PIC_bdc, // Branch on Digit Carry to k -PIC_bnc, // Branch on No Carry to k -PIC_bndc, // Branch on No Digit Carry to k -PIC_bnz, // Branch on No Zero to Address -PIC_bz, // Branch on Zero to Address k -PIC_addcf, // Add Carry to File Register -PIC_adddcf, // Add Digit to File Register -PIC_subcf, // Subtract Carry from File Reg - -// ADDITIONAL INSTRUCTIONS FOR 18Cxx - -// BYTE-ORIENTED FILE REGISTER OPERATIONS - -PIC_addwf3, // Add W and f -PIC_addwfc3, // Add W and Carry to f -PIC_andwf3, // AND W with f -PIC_clrf2, // Clear f -PIC_comf3, // Complement f -PIC_cpfseq2, // Compare f with W, Skip if == -PIC_cpfsgt2, // Compare f with W, Skip if > -PIC_cpfslt2, // Compare f with W, Skip if < -PIC_decf3, // Decrement f -PIC_decfsz3, // Decrement f, Skip if 0 -PIC_dcfsnz3, // Decrement f, Skip if not 0 -PIC_incf3, // Increment f -PIC_incfsz3, // Increment f, Skip if 0 -PIC_infsnz3, // Increment f, Skip if not 0 -PIC_iorwf3, // Inclusive OR W with f -PIC_movf3, // Move f -PIC_movff2, // Move fs to fd -PIC_movwf2, // Move W to f -PIC_mulwf2, // Multiply W with f -PIC_negf2, // Negate f -PIC_rlcf3, // Rotate Left f through Carry -PIC_rlncf3, // Rotate Left f -PIC_rrcf3, // Rotate Right f through Carry -PIC_rrncf3, // Rotate Right f -PIC_setf2, // Set f -PIC_subfwb3, // Substract f from W with borrow -PIC_subwf3, // Substract W from f -PIC_subwfb3, // Substract W from f with borrow -PIC_swapf3, // Swap nibbles in f -PIC_tstfsz2, // Test f, Skip if 0 -PIC_xorwf3, // Exclusive OR W with f - -// BIT-ORIENTED FILE REGISTER OPERATIONS - -PIC_bcf3, // Bit Clear f -PIC_bsf3, // Bit Set f -PIC_btfsc3, // Bit Test f, Skip if Clear -PIC_btfss3, // Bit Test f, Skip if Set -PIC_btg3, // Bit Toggle f - -// CONTROL OPERATIONS - -PIC_bc1, // Branch if Carry -PIC_bn1, // Branch if Negative -PIC_bnc1, // Branch if not Carry -PIC_bnn1, // Branch if not Negative -PIC_bnov1, // Branch if not Overflow -PIC_bnz1, // Branch if not Zero -PIC_bov1, // Branch if Overflow -PIC_bra1, // Branch unconditionally -PIC_bz1, // Branch if Zero -PIC_call2, // Call subroutine -// PIC_clrwdt -PIC_daw0, // Decimal Adjust W -// PIC_goto -// PIC_nop -// PIC_nop -PIC_pop0, // Pop top of return stack -PIC_push0, // Push top of return stack -PIC_rcall1, // Relative Call subroutine -PIC_reset0, // Software device Reset -PIC_retfie1, // Return from interrupt enable -// PIC_retlw -PIC_return1, // Return from Subroutine -// PIC_sleep - -// LITERAL OPERATIONS - -// PIC_addlw -// PIC_andlw -// PIC_iorlw -PIC_lfsr2, // Move literal to FSR -PIC_movlb1, // Move literal to BSR -// PIC_movlw -PIC_mullw1, // Multiply literal with W -// PIC_retlw -// PIC_sublw -// PIC_xorlw - -// DATA MEMORY <-> PROGRAM MEMORY OPERATIONS - -PIC_tblrd0, // Table Read -PIC_tblrd0p, // Table Read with post-increment -PIC_tblrd0m, // Table Read with post-decrement -PIC_tblrdp0, // Table Read with pre-increment -PIC_tblwt0, // Table Write -PIC_tblwt0p, // Table Write with post-increment -PIC_tblwt0m, // Table Write with post-decrement -PIC_tblwtp0, // Table Write with pre-increment - -// ADDITIONAL INSTRUCTIONS FOR 16F1x and 12F1x - -PIC_addwfc, // Add W and Carry to f -PIC_movlp, // Move literal to PCLATH -PIC_movlb, // Move literal to BSR -PIC_addfsr, // Add Literal to FSRn -PIC_asrf, // Arithmetic Right Shift -PIC_lslf, // Logical Left Shift -PIC_lsrf, // Logical Right Shift -PIC_subwfb, // Subtract with Borrow W from f -PIC_bra, // Relative Branch -PIC_brw, // Relative Branch with W -PIC_callw, // Call Subroutine with W -PIC_reset, // Software device Reset -PIC_moviw, // Move INDFn to W -PIC_movwi, // Move W to INDFn - -PIC_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -PIC16_null = 0, // Unknown Operation - -// Move Instructions -PIC16_EXCH, // Exchange Wns and Wnd -PIC16_MOV, // Move -PIC16_SWAP, // Byte or Nibble Swap Wn -PIC16_TBLRDH, // Table Read High -PIC16_TBLRDL, // Table Read Low -PIC16_TBLWTH, // Table Write High -PIC16_TBLWTL, // Table Write Low -// Only for PIC24E and dsPIC33E -PIC16_MOVPAG, // Move to Page Register - -// Math Instructions -PIC16_ADD, // Add -PIC16_ADDC, // Add with carry -PIC16_DAWB, // Decimal Adjust Wn -PIC16_DEC, // Decrement -PIC16_DEC2, // Decrement by 2 -PIC16_DIV, // Signed/Unsigned Integer Divide -PIC16_INC, // Increment -PIC16_INC2, // Increment by 2 -PIC16_MUL, // Integer Multiply -PIC16_SE, // Sign-Extend Ws -PIC16_SUB, // Subtract -PIC16_SUBB, // Subtract with Borrow -PIC16_SUBBR, // Subtract with Borrow -PIC16_SUBR, // Subtract -PIC16_ZE, // Zero - Extend Ws -// Only for PIC24E and dsPIC33E -PIC16_MULW, // Integer Multiply with 16-bit Result -// Only for dsPIC -PIC16_DIVF, // Fractional Divide - -// Logic Instructions -PIC16_AND, // AND -PIC16_CLR, // Clear f or WREG | Clear Wd -PIC16_COM, // Complement f | Complement Ws -PIC16_IOR, // Inclusive OR -PIC16_NEG, // Negate f | Negate Ws -PIC16_SETM, // Set f or WREG | Set Ws -PIC16_XOR, // Exclusive OR - -// Rotate/Shift Instructions -PIC16_ASR, // Arithmetic Shift Right -PIC16_LSR, // Logical Shift Right -PIC16_RLC, // Rotate Left through Carry -PIC16_RLNC, // Rotate Left without Carry -PIC16_RRC, // Rotate Right through Carry -PIC16_RRNC, // Rotate Right without Carry -PIC16_SL, // Shift Left - -// Bit Instructions -PIC16_BCLR, // Bit Clear f | Bit Clear in Ws -PIC16_BSET, // Bit Set f | Bit Set in Ws -PIC16_BSW, // Bit Write in Ws -PIC16_BTG, // Bit Toggle f | Bit Toggle in Ws -PIC16_BTST, // Bit Test f | Bit Test in Ws -PIC16_BTSTS, // Bit Test/Set f | Bit Test/Set in Ws -PIC16_FBCL, // Find First Bit Change from Left -PIC16_FF1L, // Find First One from Left -PIC16_FF1R, // Find First One from Right - - -// Compare/Skip and Compare/Branch Instructions -PIC16_BTSC, // Bit Test, Skip if Clear -PIC16_BTSS, // Bit Test, Skip if Set -PIC16_CP, // Compare, Set Status Flags -PIC16_CP0, // Compare, Set Status Flags -PIC16_CPB, // Compare using Borrow, set Status Flags -PIC16_CPSEQ, // Compare Wb with Wn, Skip if Equal (Wb = Wn) -PIC16_CPSGT, // Signed Compare Wb with Wn, Skip if Greater Than (Wb > Wn) -PIC16_CPSLT, // Signed Compare Wb with Wn, Skip if Less Than (Wb < Wn) -PIC16_CPSNE, // Signed Compare Wb with Wn, Skip if Not Equal (Wb != Wn) -// Only for PIC24E and dsPIC33E -PIC16_CPBEQ, // Compare Wb with Wn, branch if = -PIC16_CPBNE, // Compare Wb with Wn, Branch if Not Equal (Wb != Wn) -PIC16_CPBGT, // Signed Compare Wb with Wn, Branch if Greater Than (Wb > Wn) -PIC16_CPBLT, // Signed Compare Wb with Wn, Branch if Less Than (Wb < Wn) - -// Program Flow Instructions -PIC16_BRA, // Branch unconditionally/conditionally -PIC16_CALL, // Call Subroutine | Call Indirect Subroutine -PIC16_GOTO, // Unconditional Jump -PIC16_RCALL, // Relative Call | Relative Call -PIC16_REPEAT, // Repeat next instruction -PIC16_RETFIE, // Return from Interrupt -PIC16_RETLW, // Return with Literal in Wn -PIC16_RETURN, // Return -// Only for dsPIC -PIC16_DO, // Initialize Hardware Loop - -// Shadow/Stack Instructions -PIC16_LNK, // Allocate Stack Frame -PIC16_POP, // Pop TOS | Pop Shadow Registers -PIC16_PUSH, // Push to TOS | Push Shadow Registers -PIC16_ULNK, // De-allocate Stack Frame - -// Control Instructions -PIC16_CLRWDT, // Clear Watchdog Timer -PIC16_DISI, // Disable Interrupts Temporarily -PIC16_NOP, // No operation -PIC16_NOPR, // No operation -PIC16_PWRSAV, // Enter Power Saving Mode -PIC16_RESET, // Reset - -// DSP Instructions [Only for dsPIC30F, dsPIC33F and dsPIC33E] -PIC16_LAC, // Load Accumulator -PIC16_SAC, // Store Accumulator -PIC16_SFTAC, // Arithmetic Shift Accumulator -PIC16_CLR1, // Clear Accumulator, Prefetch Operands -PIC16_ED, // Euclidean Distance (No Accumulate) -PIC16_EDAC, // Euclidean Distance -PIC16_MAC, // Multiply and Accumulate -PIC16_MOVSAC, // Prefetch Operands and Store Accumulator -PIC16_MPY, // Multiply to Accumulator -PIC16_MSC, // Multiply and Subtract from Accumulator - -//ICD instructions -PIC16_BREAK, // ICD Break -PIC16_URUN, // ICD Run -PIC16_SSTEP, // ICD Single Step -PIC16_FEX, // ICD Execute - -PIC16_last, - - }; -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -SPARC_null = 0, // Unknown Operation - -// SPARC V9 instructions - -SPARC_add, // Add -SPARC_addcc, // Add and modify condition codes -SPARC_addc, // Add with carry -SPARC_addccc, // Add with carry and modify condition codes -SPARC_and, // And -SPARC_andcc, // And and modify condition codes -SPARC_andn, // And not -SPARC_andncc, // And not (and modify condition codes) -SPARC_b, // Branch on integer condition codes -SPARC_bp, // Branch on integer condition codes with prediction -SPARC_bpr, // Branch on contents of integer register with prediction -SPARC_call, // Call and link -SPARC_casa, // Compare and swap word in alternate space -SPARC_casxa, // Compare and swap doubleword in alternate space -SPARC_done, // Return from trap -SPARC_fabs, // Floating-point absolute value -SPARC_fadd, // Floating-point add -SPARC_fbp, // Branch on floating-point condition codes with prediction -SPARC_fb, // Branch on floating-point condition codes -SPARC_fcmp, // Floating-point compare -SPARC_fcmpe, // Floating-point compare (exception if unordered) -SPARC_fdiv, // Floating-point divide -SPARC_fdmulq, // Floating-point multiply double to quad -SPARC_flush, // Flush instruction memory -SPARC_flushw, // Flush register windows -SPARC_fmov, // Floating-point move -SPARC_fmovcc, // Conditional floating-point move -SPARC_fmovr, // Move floating-point register if integer register contents satisfy condition -SPARC_fmul, // Floating-point multiply -SPARC_fneg, // Floating-point negate -SPARC_fsmuld, // Floating-point multiply single to double -SPARC_fsqrt, // Floating-point square root -SPARC_fsub, // Floating-point subtract -SPARC_fstox, // Convert single floating point to 64-bit integer -SPARC_fdtox, // Convert doublee floating point to 64-bit integer -SPARC_fqtox, // Convert quad floating point to 64-bit integer -SPARC_fxtos, // Convert 64-bit integer to single floating point -SPARC_fxtod, // Convert 64-bit integer to double floating point -SPARC_fxtoq, // Convert 64-bit integer to quad floating point -SPARC_fitos, // Convert 32-bit integer to single floating point -SPARC_fdtos, // Convert single floating point to single floating point -SPARC_fqtos, // Convert quade floating point to single floating point -SPARC_fitod, // Convert 32-bit integer to double floating point -SPARC_fstod, // Convert single floating point to double floating point -SPARC_fqtod, // Convert quade floating point to double floating point -SPARC_fitoq, // Convert 32-bit integer to quad floating point -SPARC_fstoq, // Convert single floating point to quad floating point -SPARC_fdtoq, // Convert quade floating point to quad floating point -SPARC_fstoi, // Convert single floating point to 32-bit integer -SPARC_fdtoi, // Convert doublee floating point to 32-bit integer -SPARC_fqtoi, // Convert quad floating point to 32-bit integer -SPARC_illtrap, // Illegal instruction -SPARC_impdep1, // Implementation-dependent instruction -SPARC_impdep2, // Implementation-dependent instruction -SPARC_jmpl, // Jump and link -SPARC_ldd, // Load doubleword -SPARC_ldda, // Load doubleword from alternate space -SPARC_lddf, // Load double floating-point -SPARC_lddfa, // Load double floating-point from alternate space -SPARC_ldf, // Load floating-point -SPARC_ldfa, // Load floating-point from alternate space -SPARC_ldfsr, // Load floating-point state register lower -SPARC_ldqf, // Load quad floating-point -SPARC_ldqfa, // Load quad floating-point from alternate space -SPARC_ldsb, // Load signed byte -SPARC_ldsba, // Load signed byte from alternate space -SPARC_ldsh, // Load signed halfword -SPARC_ldsha, // Load signed halfword from alternate space -SPARC_ldstub, // Load-store unsigned byte -SPARC_ldstuba, // Load-store unsigned byte in alternate space -SPARC_ldsw, // Load signed word -SPARC_ldswa, // Load signed word from alternate space -SPARC_ldub, // Load unsigned byte -SPARC_lduba, // Load unsigned byte from alternate space -SPARC_lduh, // Load unsigned halfword -SPARC_lduha, // Load unsigned halfword from alternate space -SPARC_lduw, // Load unsigned word -SPARC_lduwa, // Load unsigned word from alternate space -SPARC_ldx, // Load extended -SPARC_ldxa, // Load extended from alternate space -SPARC_ldxfsr, // Load extended floating-point state register -SPARC_membar, // Memory barrier -SPARC_mov, // Move integer register if condition is satisfied -SPARC_movr, // Move integer register on contents of integer register -SPARC_mulscc, // Multiply step and modify condition codes -SPARC_mulx, // Multiply 64-bit integers -SPARC_nop, // No operation -SPARC_or, // Inclusive-or -SPARC_orcc, // Inclusive-or (and modify condition codes) -SPARC_orn, // Inclusive-or not -SPARC_orncc, // Inclusive-or not (and modify condition codes) -SPARC_popc, // Population count -SPARC_prefetch, // Prefetch data -SPARC_prefetcha, // Prefetch data from alternate space -SPARC_rd, // Read state register -SPARC_rdpr, // Read privileged register -SPARC_restore, // Restore caller's window -SPARC_restored, // Window has been restored -SPARC_retry, // Return from trap and retry -SPARC_return, // Return -SPARC_save, // Save caller's window -SPARC_saved, // Window has been saved -SPARC_sdiv, // 32-bit signed integer divide -SPARC_sdivcc, // 32-bit signed integer divide and modify condition codes -SPARC_sdivx, // 64-bit signed integer divide -SPARC_sethi, // Set high 22 bits of low word of integer register -SPARC_sir, // Software-initiated reset -SPARC_sll, // Shift left logical -SPARC_sllx, // Shift left logical, extended -SPARC_smul, // Signed integer multiply -SPARC_smulcc, // Signed integer multiply (and modify condition codes) -SPARC_sra, // Shift right arithmetic -SPARC_srax, // Shift right arithmetic, extended -SPARC_srl, // Shift right logical -SPARC_srlx, // Shift right logical, extended -SPARC_stb, // Store byte -SPARC_stba, // Store byte into alternate space -SPARC_stbar, // Store barrier -SPARC_std, // Store doubleword -SPARC_stda, // Store doubleword into alternate space -SPARC_stdf, // Store double floating-point -SPARC_stdfa, // Store double floating-point into alternate space -SPARC_stf, // Store floating-point -SPARC_stfa, // Store floating-point into alternate space -SPARC_stfsr, // Store floating-point state register -SPARC_sth, // Store halfword -SPARC_stha, // Store halfword into alternate space -SPARC_stqf, // Store quad floating-point -SPARC_stqfa, // Store quad floating-point into alternate space -SPARC_stw, // Store word -SPARC_stwa, // Store word into alternate space -SPARC_stx, // Store extended -SPARC_stxa, // Store extended into alternate space -SPARC_stxfsr, // Store extended floating-point state register -SPARC_sub, // Subtract -SPARC_subcc, // Subtract and modify condition codes -SPARC_subc, // Subtract with carry -SPARC_subccc, // Subtract with carry and modify condition codes -SPARC_swap, // Swap integer register with memory -SPARC_swapa, // Swap integer register with memory in alternate space -SPARC_taddcc, // Tagged add and modify condition codes -SPARC_taddcctv, // Tagged add and modify condition codes (trap on overflow) -SPARC_tsubcc, // Tagged subtract and modify condition codes -SPARC_tsubcctv, // Tagged subtract and modify condition codes (trap on overflow) -SPARC_t, // Trap on integer condition codes -SPARC_udiv, // Unsigned integer divide -SPARC_udivcc, // Unsigned integer divide and modify condition codes -SPARC_udivx, // 64-bit unsigned integer divide -SPARC_umul, // Unsigned integer multiply -SPARC_umulcc, // Unsigned integer multiply and modify condition codes -SPARC_wr, // Write Y register -SPARC_wrpr, // Write privileged register -SPARC_xnor, // Exclusive-nor -SPARC_xnorcc, // Exclusive-nor (and modify condition codes) -SPARC_xor, // Exclusive-or -SPARC_xorcc, // Exclusive-or (and modify condition codes) - -// Synthetic instructions - -SPARC_cmp, // Compare -SPARC_jmp, // Jump -SPARC_iprefetch, // Instruction prefetch -SPARC_tst, // Test -SPARC_ret, // Return from subroutine -SPARC_retl, // Return from leaf subroutine -SPARC_setuw, // Load unsigned constant -SPARC_setsw, // Load signed constant -SPARC_setx, // Load 64-bit constant -SPARC_signx, // Sign-extend 32-bit value to 64 bits -SPARC_not, // One's complement -SPARC_neg, // Two's complement -SPARC_cas, // Compare and swap -SPARC_casl, // Compare and swap, little endian -SPARC_casx, // Compare and swap extended -SPARC_casxl, // Compare and swap extended, little endian -SPARC_inc, // Increment -SPARC_inccc, // Increment and modify condition codes -SPARC_dec, // Deccrement -SPARC_deccc, // Decrement and modify condition codes -SPARC_btst, // Bit test -SPARC_bset, // Bit set -SPARC_bclr, // Bit clear -SPARC_btog, // Bit toggle -SPARC_clr, // Clear -SPARC_clrb, // Clear byte -SPARC_clrh, // Clear halfword -SPARC_clrx, // Clear extended word -SPARC_clruw, // Clear upper word -SPARC_pseudo_mov, // Move register - -// UtlraSPARC II extensions - -SPARC_alignaddress, // Calculate address for misaligned data access -SPARC_array, // 3-D address to blocked byte address conversion -SPARC_edge, // Edge boundary processing {little-endian} -SPARC_faligndata, // Perform data alignment for misaligned data -SPARC_fandnot1, // Negated src1 AND src2 (single precision) -SPARC_fandnot2, // src1 AND negated src2 (single precision) -SPARC_fand, // Logical AND (single precision) -SPARC_fcmpeq, // Four 16-bit/two 32-bit compare; set integer dest if src1 = src2 -SPARC_fcmpgt, // Four 16-bit/two 32-bit compare; set integer dest if src1 > src2 -SPARC_fcmple, // Four 16-bit/two 32-bit compare; set integer dest if src1 <= src2 -SPARC_fcmpne, // Four 16-bit/two 32-bit compare; set integer dest if src1 != src2 -SPARC_fexpand, // Four 8-bit to 16-bit expands -SPARC_fmul8sux16, // Signed upper 8/16-bit partitioned product of corresponding components -SPARC_fmul8ulx16, // Unsigned lower 8/16-bit partitioned product of corresponding components -SPARC_fmul8x16, // 8/16-bit partitioned product of corresponding components -SPARC_fmul8x16al, // 8/16-bit lower a partitioned product of 4 components -SPARC_fmul8x16au, // 8/16-bit upper a partitioned product of 4 components -SPARC_fmuld8sux16, // Signed upper 8/16-bit multiply 32-bit partitioned product of components -SPARC_fmuld8ulx16, // Unsigned lower 8/16-bit multiply 32-bit partitioned product of components -SPARC_fnand, // Logical NAND (single precision) -SPARC_fnor, // Logical NOR (single precision) -SPARC_fnot1, // Negate (1's complement) src1 (single precision) -SPARC_fnot2, // Negate (1's complement) src2 (single precision) -SPARC_fone, // One fill (single precision) -SPARC_fornot1, // Negated src1 OR src2 (single precision) -SPARC_fornot2, // src1 OR negated src2 (single precision) -SPARC_for, // Logical OR (single precision) -SPARC_fpackfix, // Two 32-bit to 16-bit fixed pack -SPARC_fpack, // Four 16-bit/two 32-bit pixel pack -SPARC_fpadd, // Four 16-bit/two 32-bit partitioned add (single precision) -SPARC_fpmerge, // Two 32-bit pixel to 64-bit pixel merge -SPARC_fpsub, // Four 16-bit/two 32-bit partitioned subtract (single precision) -SPARC_fsrc1, // Copy src1 (single precision) -SPARC_fsrc2, // Copy src2 (single precision) -SPARC_fxnor, // Logical XNOR (single precision) -SPARC_fxor, // Logical XOR (single precision) -SPARC_fzero, // Zero fill (single precision) -SPARC_pdist, // Distance between 8 8-bit components -SPARC_shutdown, // Power-down support -//SPARC_stdfa, // 8/16-bit store from a double precision FP register - -// V8 only instructions -SPARC_rett, // Return from trap - -// UA 2005 instructions -SPARC_bmask, // Byte Mask -SPARC_bshuffle, // Byte Shuffle -SPARC_edgen, // Edge boundary processing (no CC) {little-endian} -SPARC_rdhpr, // Read Hyperprivileged Register -SPARC_wrhpr, // Write Hyperprivileged Register -SPARC_siam, // Set Interval Arithmetic Mode - -SPARC_last, - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -HPPA_null = 0, // Unknown Operation - -HPPA_add, // Add -HPPA_addb, // Add and Branch -HPPA_addi, // Add to Immediate -HPPA_addib, // Add Immediate and Branch -HPPA_addil, // Add to Immediate Left -HPPA_and, // AND -HPPA_andcm, // AND complement -HPPA_b, // Branch -HPPA_bb, // Branch on Bit -HPPA_be, // Branch External -HPPA_blr, // Branch and Link Register -HPPA_break, // Break -HPPA_bv, // Branch Vectored -HPPA_bve, // Branch Vectored External -HPPA_cldd, // Coprocessor Load Doubleword -HPPA_cldw, // Coprocessor Load Word -HPPA_clrbts, // Clear Branch Target Stack -HPPA_cmpb, // Compare and Branch -HPPA_cmpclr, // Compare and Clear -HPPA_cmpib, // Compare Immediate and Branch -HPPA_cmpiclr, // Compare Immediate and Clear -HPPA_copr, // Coprocessor Operation -HPPA_cstd, // Coprocessor Store Doubleword -HPPA_cstw, // Coprocessor Store Word -HPPA_dcor, // Decimal Correct -HPPA_depd, // Deposit Doubleword -HPPA_depdi, // Deposit Doubleword Immediate -HPPA_depw, // Deposit Word -HPPA_depwi, // Deposit Word Immediate -HPPA_diag, // Diagnose -HPPA_ds, // Divide Step -HPPA_extrd, // Extract Doubleword -HPPA_extrw, // Extract Word -HPPA_fdc, // Flush Data Cache -HPPA_fdce, // Flush Data Cache Entry -HPPA_fic, // Flush Instruction Cache -HPPA_fice, // Flush Instruction Cache Entry -HPPA_hadd, // Halfword Parallel Add -HPPA_havg, // Halfword Parallel Average -HPPA_hshl, // Halfword Parallel Shift Left -HPPA_hshladd, // Halfword Parallel Shift Left and Add -HPPA_hshr, // Halfword Parallel Shift Right -HPPA_hshradd, // Halfword Parallel Shift Right and Add -HPPA_hsub, // Halfword Parallel Subtract -HPPA_idtlbt, // Insert Data TLB Translation -HPPA_iitlbt, // Insert Instruction TLB Translation -HPPA_lci, // Load Coherence Index -HPPA_ldb, // Load Byte -HPPA_ldcd, // Load and Clear Doubleword -HPPA_ldcw, // Load and Clear Word -HPPA_ldd, // Load Doubleword -HPPA_ldda, // Load Doubleword Absolute -HPPA_ldh, // Load Halfword -HPPA_ldil, // Load Immediate Left -HPPA_ldo, // Load Offset -HPPA_ldsid, // Load Space Identifier -HPPA_ldw, // Load Word -HPPA_ldwa, // Load Word Absolute -HPPA_lpa, // Load Physical Address -HPPA_mfctl, // Move From Control Register -HPPA_mfia, // Move From Instruction Address -HPPA_mfsp, // Move From Space Register -HPPA_mixh, // Mix Halfwords -HPPA_mixw, // Mix Words -HPPA_movb, // Move and Branch -HPPA_movib, // Move Immediate and Branch -HPPA_mtctl, // Move To Control Register -HPPA_mtsarcm, // Move To Shift Amount Register Complement -HPPA_mtsm, // Move To System Mask -HPPA_mtsp, // Move To Space Register -HPPA_or, // Inclusive OR -HPPA_pdc, // Purge Data Cache -HPPA_pdtlb, // Purge Data TLB -HPPA_pdtlbe, // Purge Data TLB Entry -HPPA_permh, // Permute Halfwords -HPPA_pitlb, // Purge Instruction TLB -HPPA_pitlbe, // Purge Instruction TLB Entry -HPPA_popbts, // Pop Branch Target Stack -HPPA_probe, // Probe Access -HPPA_probei, // Probe Access Immediate -HPPA_pushbts, // Push Branch Target Stack -HPPA_pushnom, // Push Nominated -HPPA_rfi, // Return From Interruption -HPPA_rsm, // Reset System Mask -HPPA_shladd, // Shift Left and Add -HPPA_shrpd, // Sihft Right Pair Doubleword -HPPA_shrpw, // Sihft Right Pair Word -HPPA_spop0, // Special Operation Zero -HPPA_spop1, // Special Operation One -HPPA_spop2, // Special Operation Two -HPPA_spop3, // Special Operation Three -HPPA_ssm, // Set System Mask -HPPA_stb, // Store Byte -HPPA_stby, // Store Bytes -HPPA_std, // Store Doubleword -HPPA_stda, // Store Doubleword Absolute -HPPA_stdby, // Store Doubleword Bytes -HPPA_sth, // Store Halfword -HPPA_stw, // Store Word -HPPA_stwa, // Store Word Absolute -HPPA_sub, // Subtract -HPPA_subi, // Subtract from Immediate -HPPA_sync, // Synchronize Caches -HPPA_syncdma, // Synchronize DMA -HPPA_uaddcm, // Unit Add Complement -HPPA_uxor, // Unit XOR -HPPA_xor, // Exclusive OR - -// Floating point instructions - -HPPA_fabs, // Floating-Point Absolute Value -HPPA_fadd, // Floating-Point Add -HPPA_fcmp, // Floating-Point Compare -HPPA_fcnv, // Floating-Point Convert -HPPA_fcpy, // Floating-Point Copy -HPPA_fdiv, // Floating-Point Divide -HPPA_fid, // Floating-Point Identity -HPPA_fldd, // Floating-Point Load Doubleword -HPPA_fldw, // Floating-Point Load Word -HPPA_fmpy, // Floating-Point Multiply -HPPA_fmpyadd, // Floating-Point Multiply/Add -HPPA_fmpyfadd, // Floating-Point Multiply Fused Add -HPPA_fmpynfadd, // Floating-Point Multiply Negate Fused Add -HPPA_fmpysub, // Floating-Point Multiply/Subtract -HPPA_fneg, // Floating-Point Negate -HPPA_fnegabs, // Floating-Point Negate Absolute Value -HPPA_frem, // Floating-Point Remainder -HPPA_frnd, // Floating-Point Round to Integer -HPPA_fsqrt, // Floating-Point Square Root -HPPA_fstd, // Floating-Point Store Doubleword -HPPA_fstw, // Floating-Point Store Word -HPPA_fsub, // Floating-Point Subtract -HPPA_ftest, // Floating-Point Test -HPPA_xmpyu, // Fixed-Point Multiply Unsigned - -// Performance Monitor Coprocessor - -HPPA_pmdis, // Performance Monitor Disable -HPPA_pmenb, // Performance Monitor Enable - -// Macros - -HPPA_call, // Call Subroutine -HPPA_ret, // Return From Subroutine -HPPA_shld, // Shift Left Doubleword -HPPA_shlw, // Shift Left Word -HPPA_shrd, // Shift Right Doubleword -HPPA_shrw, // Shift Right Word -HPPA_ldi, // Load Immediate -HPPA_copy, // Copy Register -HPPA_mtsar, // Move To %SAR -HPPA_nop, // No Operation - -HPPA_last, - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -H8500_null = 0, // Unknown Operation - -// Data transfer - -H8500_mov_g, // B/W Move data -H8500_mov_e, // B Move data -H8500_mov_i, // W Move data -H8500_mov_f, // B/W Move data -H8500_mov_l, // B/W Move data -H8500_mov_s, // B/W Move data -H8500_ldm, // W Pop data from the stack to one or more registers -H8500_stm, // W Push data from one or more registers onto the stack -H8500_xch, // W Exchange data between two general registers -H8500_swap, // B Exchange the upper and lower bytes in a general register -H8500_movtpe, // B Transfer data from a general register to memory -H8500_movfpe, // B Transfer data from memory to a general register - -// Arithmetic operations - -H8500_add_g, // B/W Addition -H8500_add_q, // B/W Addition -H8500_sub, // B/W Subtraction -H8500_adds, // B/W Addition -H8500_subs, // B/W Subtraction -H8500_addx, // B/W Addition with carry -H8500_subx, // B/W Subtraction with borrow -H8500_dadd, // B Decimal addition -H8500_dsub, // B Decimal subtraction -H8500_mulxu, // B/W Unsigned multiplication -H8500_divxu, // B/W Unsigned division -H8500_cmp_g, // B/W Compare data -H8500_cmp_e, // B Compare data -H8500_cmp_i, // W Compare data -H8500_exts, // B Convert byte to word by extending the sign bit -H8500_extu, // B Convert byte to word data by padding with zero bits -H8500_tst, // B/W Compare with 0 -H8500_neg, // B/W Negate -H8500_clr, // B/W Make zero -H8500_tas, // B Test and set - -// Logic Operations - -H8500_and, // B/W Logical AND -H8500_or, // B/W Logical OR -H8500_xor, // B/W Exclusive OR -H8500_not, // B/W Bitwise NOT - -// Shift Operations - -H8500_shal, // B/W Arithmetic shift left -H8500_shar, // B/W Arithmetic shift right -H8500_shll, // B/W Logical shift left -H8500_shlr, // B/W Logical shift right -H8500_rotl, // B/W Rotate left -H8500_rotr, // B/W Rotate right -H8500_rotxl, // B/W Rotate through carry left -H8500_rotxr, // B/W Rotate through carry right - -// Bit Manipulations - -H8500_bset, // B/W Test bit and set -H8500_bclr, // B/W Test bit and clear -H8500_bnot, // B/W Test bit and invert -H8500_btst, // B/W Test bit - -// Branching Instructions - -H8500_bra, // Branch Always -H8500_brn, // Branch Never -H8500_bhi, // Branch if High (C|Z = 0) -H8500_bls, // Branch if Low or Same (C|Z = 1) -H8500_bcc, // Branch if Carry Clear (C = 0) -H8500_bcs, // Branch if Carry Set (C = 1) -H8500_bne, // Branch if Not Equal (Z = 0) -H8500_beq, // Branch if Equal (Z = 1) -H8500_bvc, // Branch if Overflow Clear (V = 0) -H8500_bvs, // Branch if Overflow Set (V = 1) -H8500_bpl, // Branch if Plus (N = 0) -H8500_bmi, // Branch if Minus (N = 1) -H8500_bge, // Branch if Greater or Equal (N^V = 0) -H8500_blt, // Branch if Less Than (N^V = 1) -H8500_bgt, // Branch if Greater Than (Z|(N^V) = 0) -H8500_ble, // Branch if Less or Equal (Z|(N^V) = 1) -H8500_jmp, // Branch unconditionally (same page) -H8500_pjmp, // Branch unconditionally (specified page) -H8500_bsr, // Branch to subroutine (same page) -H8500_jsr, // Branch to subroutine (same page) -H8500_pjsr, // Branch to subroutine (specified page) -H8500_rts, // Return from subroutine (same page) -H8500_prts, // Return from subroutine (different page) -H8500_rtd, // Return from subroutine (same page) and adjust SP -H8500_prtd, // Return from subroutine (different page) and adjust SP -H8500_scb, // Control loop - -// System Control Instructions - -H8500_trapa, // Generate trap exception -H8500_trap_vs, // Generate trap exception if the V bit is set -H8500_rte, // Return from exception-handling routine -H8500_link, // Create stack frame -H8500_unlk, // Deallocate stack frame -H8500_sleep, // Go to power-down state -H8500_ldc, // B/W Move to control register -H8500_stc, // B/W Move from control register -H8500_andc, // B/W Logically AND control register -H8500_orc, // B/W Logically OR control register -H8500_xorc, // B/W Logically exclusive-OR control register -H8500_nop, // No operation -H8500_bpt, // - -H8500_last, - - }; - - - - -enum -{ -DSP56_null = 0, // Unknown Operation - -DSP56_abs, // Absolute Value -DSP56_adc, // Add Long with Carry -DSP56_add, // Addition -DSP56_addl, // Shift Left and Add -DSP56_addr, // Shift Right and Add -DSP56_and, // Logical AND -DSP56_andi, // AND Immediate to Control Register -DSP56_asl, // Arithmetic Shift Left -DSP56_asl4, // Arithmetic Shift Left 4 -DSP56_asr, // Arithmetic Shift Right -DSP56_asr4, // Arithmetic Shift Right 4 -DSP56_asr16, // Arithmetic Shift Right 16 -DSP56_bfchg, // Test Bit Field and Change -DSP56_bfclr, // Clear Bit Field -DSP56_bfset, // Set Bit Field -DSP56_bftsth, // Test Bit Field High -DSP56_bftstl, // Test Bit Field Low -DSP56_bcc, // Branch Conditionaly -DSP56_bchg, // Bit Test and Change -DSP56_bclr, // Bit Test and Clear -DSP56_bra, // Branch Always -DSP56_brclr, // Branch if Bit Clear -DSP56_brkcc, // Exit Current DO Loop Conditionally -DSP56_brset, // Branch if Bit Set -DSP56_bscc, // Branch to Subroutine Conditionaly -DSP56_bsclr, // Branch to Subroutine if Bit Clear -DSP56_bset, // Bit Test and Set -DSP56_bsr, // Branch to Subroutine -DSP56_bsset, // Branch to Subroutine if Bit Set -DSP56_btst, // Bit Test on Memory and Registers -DSP56_chkaau, // Check address ALU result -DSP56_clb, // Count Leading Bits -DSP56_clr, // Clear an Operand -DSP56_clr24, // Clear 24 MS-bits of Accumulator -DSP56_cmp, // Compare -DSP56_cmpm, // Compare Magnitude -DSP56_cmpu, // Compare Unsigned -DSP56_debug, // Enter Debug Mode -DSP56_debugcc, // Enter Debug Mode Conditionally -DSP56_dec, // Decrement by One -DSP56_dec24, // Decrement 24 MS-bit of Accumulator -DSP56_div, // Divide Iteration -DSP56_dmac, // Double-Precision Multiply-Accumulate With Right Shift -DSP56_do, // Start Hardware Loop -DSP56_do_f, // Start Infinite Loop -DSP56_dor, // Start PC-Relative Hardware Loop -DSP56_dor_f, // Start PC-Relative Infinite Loop -DSP56_enddo, // Exit from Hardware Loop -DSP56_eor, // Logical Exclusive OR -DSP56_extract, // Extract Bit Field -DSP56_extractu, // Extract Unsigned Bit Field -DSP56_ext, // Sign Extend Accumulator -DSP56_ill, // Illegal Instruction -DSP56_imac, // Integer Multiply-Accumulate -DSP56_impy, // Integer Multiply -DSP56_inc, // Increment by One -DSP56_inc24, // Increment 24 MS-bit of Accumulator -DSP56_insert, // Insert Bit Field -DSP56_jcc, // Jump Conditionally -DSP56_jclr, // Jump if Bit Clear -DSP56_jmp, // Jump -DSP56_jscc, // Jump to Subroutine Conditionally -DSP56_jsclr, // Jump to Subroutine if Bit Clear -DSP56_jset, // Jump if Bit Set -DSP56_jsr, // Jump to Subroutine -DSP56_jsset, // Jump to Subroutine if Bit Set -DSP56_lra, // Load PC-Reliative Address -DSP56_lsl, // Logical Shift Left -DSP56_lsr, // Logical Shift Right -DSP56_lua, // Load Updated Address -DSP56_lea, // Load Updated Address -DSP56_mac, // Signed Multiply-Accumulate -DSP56_maci, // Signed Multiply-Accumulate With Immediate Operand -DSP56_mac_s_u, // Mixed Multiply-Accumulate -DSP56_macr, // Signed Multiply-Accumulate and Round -DSP56_macri, // Signed Multiply-Accumulate and Round With Immediate Operand -DSP56_max, // Transfer by Signed Value -DSP56_maxm, // Transfer by Magnitude -DSP56_merge, // Merge Two Half Words -DSP56_move, // Move Data -DSP56_movec, // Move Control Register -DSP56_movei, // Move Immediate Short -DSP56_movem, // Move Program Memory -DSP56_movep, // Move Peripheral Data -DSP56_moves, // Move Absolute Short -DSP56_mpy, // Signed Multiply -DSP56_mpyi, // Signed Multiply With Immediate Operand -DSP56_mpy_s_u, // Mixed Multiply -DSP56_mpyr, // Signed Multiply and Round -DSP56_mpyri, // Signed Multiply and Round With Immediate Operand -DSP56_neg, // Negate Accumulator -DSP56_negc, // Negate Accumulator -DSP56_nop, // No Operation -DSP56_norm, // Norm Accumulator Iteration -DSP56_normf, // Fast Accumulator Normalization -DSP56_not, // Logical Complement -DSP56_or, // Logical Inclusive OR -DSP56_ori, // OR Immediate to Control Register -DSP56_pflush, // Program Cache Flush -DSP56_pflushun, // Program Cache Flush Unlocked Sectors -DSP56_pfree, // Program Cache Global Unlock -DSP56_plock, // Lock Instruction Cache Sector -DSP56_plockr, // Lock Instruction Cache Relative Sector -DSP56_punlock, // Unlock Instruction Cache Sector -DSP56_punlockr, // Unlock Instruction Cache Relative Sector -DSP56_rep, // Repeat Next Instruction -DSP56_repcc, // Repeat Next Instruction -DSP56_reset, // Reset On-Chip Peripheral Devices -DSP56_rnd, // Round Accumulator -DSP56_rol, // Rotate Left -DSP56_ror, // Rotate Right -DSP56_rti, // Return from Interrupt -DSP56_rts, // Return from Subroutine -DSP56_sbc, // Subtract Long with Carry -DSP56_stop, // Stop Processing (Low-Power Standby) -DSP56_sub, // Subtract -DSP56_subl, // Shift Left and Subtract -DSP56_subr, // Shift Right and Subtract -DSP56_swap, // Swap Accumulator Words -DSP56_tcc, // Transfer Conditionally -DSP56_tfr, // Transfer Data ALU Register -DSP56_tfr2, // Transfer Data ALU Register -DSP56_tfr3, // Transfer Data ALU Register -DSP56_trap, // Software Interrupt -DSP56_trapcc, // Software Interrupt Conditionally -DSP56_tst, // Test an Operand -DSP56_tst2, // Test an Operand -DSP56_vsl, // Viterbi Shift Left -DSP56_wait, // Wait for Interrupt or DMA Request (Low-Power Standby) -DSP56_zero, // Zero Extend Accumulator -DSP56_swi, // Software Interrupt (only for 56000) -DSP56_pmov, // Pseudo insn -DSP56_last, - -}; - - - - -enum -{ -DSP96_null = 0, // Unknown Operation - -DSP96_abs, // Absolute Value -DSP96_add, // Addition -DSP96_addc, // Add with Carry -DSP96_and, // Logical AND -DSP96_andc, // AND Immediate with Complement -DSP96_andi, // AND Immediate to Control Register -DSP96_asl, // Arithmetic Shift Left -DSP96_asr, // Arithmetic Shift Right -DSP96_bcc, // Branch Conditionally (indirect) -DSP96_bccd, // Branch Conditionally (direct) -DSP96_bchg, // Bit Test and Change -DSP96_bclr, // Bit Test and Clear -DSP96_bfind, // Find Leading One -DSP96_bra, // Branch Always -DSP96_brclr, // Branch if Bit Clear -DSP96_brset, // Branch if Bit Set -DSP96_bscc, // Branch to Subroutine Conditionally (indirect) -DSP96_bsccd, // Branch to Subroutine Conditionally (direct) -DSP96_bsclr, // Branch to Subroutine if Bit Clear -DSP96_bset, // Bit Test and Set -DSP96_bsr, // Branch to Subroutine (indirect) -DSP96_bsrd, // Branch to Subroutine (direct) -DSP96_bsset, // Branch to Subroutine if Bit Set -DSP96_btst, // Bit Test on Memory and Registers -DSP96_clr, // Clear an Operand -DSP96_cmp, // Compare -DSP96_cmpg, // Graphics Compare with Trivial Accept.Reject Flags -DSP96_debugcc, // Enter Debug Mode Conditionally -DSP96_dec, // Decrement by One -DSP96_do, // Start Hardware Loop -DSP96_dor, // Start PC-Relative Hardware Loop -DSP96_enddo, // Exit from Hardware Loop -DSP96_eor, // Logical Exclusive OR -DSP96_ext, // Sign Extend 16-Bit To 32-Bit -DSP96_extb, // Sign Extend 8-Bit to 32-Bit -DSP96_fabs, // Absolute Value -DSP96_fadd, // Add -DSP96_faddsub, // Add and Subtract -DSP96_fbcc, // Branch Conditionally (Floating-Point Condition) (indirect) -DSP96_fbccd, // Branch Conditionally (Floating-Point Condition) (direct) -DSP96_fbscc, // Branch to Subroutine Conditionally (Floating-Point Condition) (indirect) -DSP96_fbsccd, // Branch to Subroutine Conditionally (Floating-Point Condition) (direct) -DSP96_fclr, // Clear a Floating-Point Operand -DSP96_fcmp, // Compare -DSP96_fcmpg, // Graphics Compare with Trivial Accept.Reject Flags -DSP96_fcmpm, // Compare Magnitude -DSP96_fcopys, // Copy Sign -DSP96_fdebugcc, // Enter Debug Mode Conditionally -DSP96_fgetman, // Get Mantissa -DSP96_fint, // Convert to Floating-Point Integer -DSP96_fjcc, // Jump Conditionally (indirect) -DSP96_fjccd, // Jump Conditionally (direct) -DSP96_fjscc, // Jump to Subroutine Conditionally (indirect) -DSP96_fjsccd, // Jump to Subroutine Conditionally (direct) -DSP96_float, // Integer to Floating-Point Conversion -DSP96_floatu, // Unsigned Integer to SP Floating-Point Conversion -DSP96_floor, // Convert to Floating-Point Integer round to -Infinity -DSP96_fmove, // Move FP Data Register(s) -DSP96_fmpyfadd, // Multiply and Add -//DSP96_fmpyfaddx, // Multiply and Add (Single Extended Precision) (Handled with DSP96_fmpyfadd) -DSP96_fmpyfaddsub, // Multiply, Add and Subtract -//DSP96_fmpyfaddsubx, // Multiply, Add and Subtract (Single Extended Precision) (Handled with DSP96_fmpyfaddsub) -DSP96_fmpyfsub, // Multiply and Subtract -//DSP96_fmpyfsubx, // Multiply and Subtract (Single Extended Precision) (Handled with DSP96_fmpyfsub) -DSP96_fmpy, // Multiply -DSP96_fneg, // Change sign -DSP96_fscale, // Scale a Floating-Point Operand -DSP96_fseedd, // Reciprocal Approximation -DSP96_fseedr, // Square-Root Reciprocal Approximation -DSP96_fsub, // Subtract -DSP96_ftfr, // Transfer Floating-Point Register -DSP96_ftrapcc, // Conditional Software Interrupt -DSP96_ftst, // Test a floating-Point Operand -DSP96_getexp, // Get Exponent -DSP96_illegal, // Illegal Instruction -DSP96_inc, // Increment by One -DSP96_int, // Floating-Point to Integer Conversion -DSP96_intrz, // Floating-Point to Integer Conversion Round to Zero -DSP96_intu, // Floating-Point to Unsigned Integer Conversion -DSP96_inturz, // Floating-Point to Unsigned Integer Conversion Round to Zero -DSP96_jcc, // Jump Conditionally (indirect) -DSP96_jccd, // Jump Conditionally (direct) -DSP96_jclr, // Jump if Bit Clear -// DSP96_jmp, // Jump (The same as jcc with condition code = 11111) -DSP96_join, // Join two 16-Bit Integers -DSP96_joinb, // Join two 8-Bit Integers -DSP96_jscc, // Jump to Subroutine Conditionally -DSP96_jsccd, // Jump to Subroutine Conditionally -DSP96_jsclr, // Jump to Subroutine if Bit Clear -DSP96_jset, // Jump if Bit Set -// DSP96_jsr, // Jump to Subroutine ( The same as jscc with condition code = 11111) -DSP96_jsset, // Jump to Subroutine if Bit Set -DSP96_lea, // Load Effective Address -DSP96_lra, // Load PC Relative Address -DSP96_lsl, // Logical Shift Left -DSP96_lsr, // Logical Shift Right -DSP96_move, // Move Data Register(s) -DSP96_movec, // Move Control Register -DSP96_movei, // Move Immediate -DSP96_movem, // Move Program Memory -DSP96_movep, // Move Peripheral Data -DSP96_moves, // Move Absolute Short -DSP96_moveta, // Move Data Register(s) and Test Address -DSP96_mpys, // Signed Multiply -DSP96_mpyu, // Unsigned Multiply -DSP96_neg, // Negate Accumulator -DSP96_negc, // Negate with Carry -DSP96_nop, // No Operation -DSP96_not, // Logical Complement -DSP96_or, // Logical Inclusive OR -DSP96_orc, // OR With Compliment -DSP96_ori, // OR Immediate to Control Register -DSP96_rep, // Repeat Next Instruction -DSP96_reset, // Reset On-Chip Peripheral Devices -DSP96_rol, // Rotate Left -DSP96_ror, // Rotate Right -DSP96_rti, // Return from Interrupt -DSP96_rtr, // Return from Subroutine and Restore Status Register -DSP96_rts, // Return from Subroutine -DSP96_setw, // Set an Operand -DSP96_split, // Extract 16-Bit Integer -DSP96_splitb, // Extract 8-Bit Integer -DSP96_stop, // Stop Processing (Low Power Stand-by) -DSP96_sub, // Subtract -DSP96_subc, // Subtract with Carry -DSP96_tfr, // Transfer Data ALU Register -DSP96_trapcc, // Software Interrupt Conditionally -DSP96_tst, // Test an Operand -DSP96_wait, // Wait for Interrupt or DMA Request (Low Power Stand-by) -DSP96_last, - -}; - -enum PMNum // Parallel Move enumeration -{ - PM96_NoMove, - PM96_R2R, // Register to register parallel move - PM96_Update, // Move update - PM96_XYMem, // X or Y memory move - PM96_XYmemR, // X or Y memory and Registry move - PM96_Long, // Long Memory move - PM96_XY, // XY Memory move - - PM96_IFcc, // Integer if conditional Instruction without CCR update - // All the following moves are handled by IFcc - // PM96_FFcc, // Floating-Point if conditional Instruction without CCR, ER, IER update - // PM96_FFccU, // Floating-Point if conditional Instruction with CCR, ER, IER update - // PM96_IFccU, // Integer if conditional Instruction with CCR update -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -C166_null = 0, // Unknown Operation - -C166_add, // Integer Addition -C166_addb, // Integer Addition Byte -C166_addc, // Integer Addition with Carry -C166_addcb, // Integer Addition with Carry Byte -C166_and, // Logical AND -C166_andb, // Logical AND Byte -C166_ashr, // Arithmetic Shift Right -C166_atomic, // Begin ATOMIC Sequence -C166_band, // Bit Logical AND -C166_bclr, // Bit Clear -C166_bcmp, // Bit to Bit Compare -C166_bfldh, // Bit Field High Byte -C166_bfldl, // Bit Field Low Byte -C166_bmov, // Bit to Bit Move -C166_bmovn, // Bit to Bit Move and Negate -C166_bor, // Bit Logical OR -C166_bset, // Bit Set -C166_bxor, // Bit Logical XOR -C166_calla, // Call Subroutine Absolute -C166_calli, // Call Subroutine Indirect -C166_callr, // Call Subroutine Relative -C166_calls, // Call Inter-Segment Subroutine -C166_cmp, // Integer Compare -C166_cmpb, // Integer Compare Byte -C166_cmpd1, // Integer Compare and Decrement by 1 -C166_cmpd2, // Integer Compare and Decrement by 2 -C166_cmpi1, // Integer Compare and Increment by 1 -C166_cmpi2, // Integer Compare and Increment by 2 -C166_cpl, // Integer One's Complement -C166_cplb, // Integer One's Complement Byte -C166_diswdt, // Disable Watchdog Timer -C166_div, // 16-by-16 Signed Division -C166_divl, // 32-by-16 Signed Division -C166_divlu, // 32-by-16 Unsigned Division -C166_divu, // 16-by-16 Unsigned Division -C166_einit, // End of Intialization -C166_extr, // Begin Extended Register Sequence -C166_extp, // Begin Extended Page Sequence -C166_extpr, // Begin Extended Page and Register Sequence -C166_exts, // Begin Extended Segment Sequence -C166_extsr, // Begin Extended Segment and Register Sequence -C166_idle, // Enter Idle Mode -C166_jb, // Relative Jump if Bit Set -C166_jbc, // Relative Jump if Bit Set and Clear Bit -C166_jmpa, // Absolute Conditional Jump -C166_jmpi, // Indirect Conditional Jump -C166_jmpr, // Relative Conditional Jump -C166_jmps, // Absolute Inter-Segment Jump -C166_jnb, // Relative Jump if Bit Clear -C166_jnbs, // Relative Jump if Bit Clear and Set Bit -C166_mov, // Move Word -C166_movb, // Move Byte -C166_movbs, // Move Byte Sign Extend -C166_movbz, // Move Byte Zero Extend -C166_mul, // Signed Multiplication -C166_mulu, // Unsigned Multiplication -C166_neg, // Integer Two's Complement -C166_negb, // Integer Two's Complement Byte -C166_nop, // No Operation -C166_or, // Logical OR -C166_orb, // Logical OR Byte -C166_pcall, // Push Word and Call Subroutine Absolute -C166_pop, // Pop Word from System Stack -C166_prior, // Prioritize Register -C166_push, // Push Word on System Stack -C166_pwrdn, // Enter Power Down Mode -C166_ret, // Return from Subroutine -C166_reti, // Return from Interrupt Routine -C166_retp, // Return from Subroutine and Pop Word -C166_rets, // Return from Inter-Segment Subroutine -C166_rol, // Rotate Left -C166_ror, // Rotate Right -C166_scxt, // Switch Context -C166_shl, // Shift Left -C166_shr, // Shift Rightt -C166_srst, // Software Reset -C166_srvwdt, // Service Watchdog Timer -C166_sub, // Integer Subtraction -C166_subb, // Integer Subtraction Byte -C166_subc, // Integer Subtraction with Carry -C166_subcb, // Integer Subtraction with Carry Byte -C166_trap, // Software Trap -C166_xor, // Logical Exclusive OR -C166_xorb, // Logical Exclusive OR Byte - -// ST10 MAC instructions - -ST10_CoABS, // Absolute Value -ST10_CoADD, // Add -ST10_CoASHR, // Accumulator Arithmetic Shift Right with Optional Round -ST10_CoCMP, // Compare -ST10_CoLOAD, // Load Accumulator -ST10_CoMAC, // Multiply-Accumulate & Optional Round -ST10_CoMACM, // Multiply-Accumulate Parallel Data Move & Optional Round -ST10_CoMAX, // Maximum -ST10_CoMIN, // Minimum -ST10_CoMOV, // Memory to Memory Move -ST10_CoMUL, // Multiply & Optional Round -ST10_CoNEG, // Negate Accumulator with Optional Rounding -ST10_CoNOP, // No-Operation -ST10_CoRND, // Round Accumulator -ST10_CoSHL, // Accumulator Logical Shift Left -ST10_CoSHR, // Accumulator Logical Shift Right -ST10_CoSTORE, // Store a MAC-Unit Register -ST10_CoSUB, // Subtract - -// missing C166v2/ST10 instructions - -C166_enwdt, // Enable Watchdog Timer -C166_sbrk, // Software Break - -C166_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -ST20_null = 0, // Unknown Operation - -// C1 instructions - -ST20_adc, // add constant -ST20_add, // add -ST20_addc, // add with carry -ST20_ajw, // adjust work space -ST20_and, // and -ST20_arot, // anti-rotate stack -ST20_ashr, // arithmetic shift right -ST20_biquad, // biquad IIR filter step -ST20_bitld, // load bit -ST20_bitmask, // create bit mask -ST20_bitst, // store bit -ST20_breakpoint, // breakpoint -ST20_cj, // conditional jump -ST20_dequeue, // dequeue a process -ST20_divstep, // divide step -ST20_dup, // duplicate -ST20_ecall, // exception call -ST20_enqueue, // enqueue a process -ST20_eqc, // equals constant -ST20_eret, // exception return -ST20_fcall, // function call -ST20_gajw, // general adjust workspace -ST20_gt, // greater than -ST20_gtu, // greater than unsigned -ST20_io, // input/output -ST20_j, // jump -ST20_jab, // jump absolute -ST20_lbinc, // load byte and increment -ST20_ldc, // load constant -ST20_ldl, // load local -ST20_ldlp, // load local pointer -ST20_ldnl, // load non-local -ST20_ldnlp, // load non-local pointer -ST20_ldpi, // load pointer to instruction -ST20_ldprodid, // load product identity -ST20_ldtdesc, // load task descriptor -ST20_lsinc, // load sixteen and increment -ST20_lsxinc, // load sixteen sign extended and increment -ST20_lwinc, // load word and increment -ST20_mac, // multiply accumulate -ST20_mul, // multiply -ST20_nfix, // negative prefix -ST20_nop, // no operation -ST20_not, // bitwise not -ST20_opr, // operate -ST20_or, // or -ST20_order, // order -ST20_orderu, // unsigned order -ST20_pfix, // prefix -ST20_rev, // reverse -ST20_rmw, // read modify write -ST20_rot, // rotate stack -ST20_run, // run process -ST20_saturate, // saturate -ST20_sbinc, // store byte and increment -ST20_shl, // shift left -ST20_shr, // shift right -ST20_signal, // signal -ST20_smacinit, // initialize short multiply accumulate loop -ST20_smacloop, // short multiply accumulate loop -ST20_smul, // short multiply -ST20_ssinc, // store sixteen and increment -ST20_statusclr, // clear bits in status register -ST20_statusset, // set bits in status register -ST20_statustst, // test status register -ST20_stl, // store local -ST20_stnl, // store non-local -ST20_stop, // stop process -ST20_sub, // subtract -ST20_subc, // subtract with carry -ST20_swap32, // byte swap 32 -ST20_swinc, // store word and increment -ST20_timeslice, // timeslice -ST20_umac, // unsigned multiply accumulate -ST20_unsign, // unsign argument -ST20_wait, // wait -ST20_wsub, // word subscript -ST20_xbword, // sign extend byte to word -ST20_xor, // exclusive or -ST20_xsword, // sign extend sixteen to word - -// C2-C4 instructions - -ST20_alt, // alt start -ST20_altend, // alt end -ST20_altwt, // alt wait -ST20_bcnt, // byte count -ST20_bitcnt, // count bits set in word -ST20_bitrevnbits, // reverse bottom n bits in word -ST20_bitrevword, // reverse bits in word -ST20_bsub, // byte subscript -ST20_call, // call -ST20_causeerror, // cause error -ST20_cb, // check byte -ST20_cbu, // check byte unsigned -ST20_ccnt1, // check count from 1 -ST20_cflerr, // check floating point error -ST20_cir, // check in range -ST20_ciru, // check in range unsigned -ST20_clockdis, // clock disable -ST20_clockenb, // clock enable -ST20_clrhalterr, // clear halt-on error flag -ST20_crcbyte, // calculate CRC on byte -ST20_crcword, // calculate CRC on word -ST20_cs, // check sixteen -ST20_csngl, // check single -ST20_csu, // check sixteen unsigned -ST20_csub0, // check subscript from 0 -ST20_cword, // check word -ST20_devlb, // device load byte -ST20_devls, // device load sixteen -ST20_devlw, // device load word -ST20_devmove, // device move -ST20_devsb, // device store byte -ST20_devss, // device store sixteen -ST20_devsw, // device store word -ST20_diff, // difference -ST20_disc, // disable channel -ST20_diss, // disable skip -ST20_dist, // disable timer -ST20_div, // divide -ST20_enbc, // enable channel -ST20_enbs, // enable skip -ST20_enbt, // enable timer -ST20_endp, // end process -ST20_fmul, // fractional multiply -ST20_fptesterr, // test for FPU error -ST20_gcall, // general call -ST20_gintdis, // general interrupt disable -ST20_gintenb, // general interrupt enable -ST20_in, // input message -ST20_insertqueue, // insert at front of scheduler queue -ST20_intdis, // (localised) interrupt disable -ST20_intenb, // (localised) interrupt enable -ST20_iret, // interrupt return -ST20_ladd, // long add -ST20_lb, // load byte -ST20_lbx, // load byte and sign extend -ST20_ldclock, // load clock -ST20_lddevid, // load device identity -ST20_ldiff, // long diff -ST20_ldinf, // load infinity -ST20_ldiv, // long divide -ST20_ldmemstartval, // load value of MemStart address -ST20_ldpri, // load current priority -ST20_ldshadow, // load shadow registers -ST20_ldtimer, // load timer -ST20_ldtraph, // load trap handler -ST20_ldtrapped, // load trapped process status -ST20_lend, // loop end -ST20_lmul, // long multiply -ST20_ls, // load sixteen -ST20_lshl, // long shift left -ST20_lshr, // long shift right -ST20_lsub, // long subtract -ST20_lsum, // long sum -ST20_lsx, // load sixteen and sign extend -ST20_mint, // minimum integer -ST20_move, // move message -ST20_move2dall, // 2D block copy -ST20_move2dinit, // initialize data for 2D block move -ST20_move2dnonzero, // 2D block copy non-zero bytes -ST20_move2dzero, // 2D block copy zero bytes -ST20_norm, // normalize -ST20_out, // output message -ST20_outbyte, // output byte -ST20_outword, // output word -ST20_pop, // pop processor stack -ST20_postnormsn, // post-normalize correction of single length fp number -ST20_prod, // product -ST20_reboot, // reboot -ST20_rem, // remainder -ST20_resetch, // reset channel -ST20_restart, // restart -ST20_ret, // return -ST20_roundsn, // round single length floating point number -ST20_runp, // run process -ST20_satadd, // saturating add -ST20_satmul, // saturating multiply -ST20_satsub, // saturating subtract -ST20_saveh, // save high priority queue registers -ST20_savel, // save low priority queue registers -ST20_sb, // store byte -ST20_seterr, // set error flags -ST20_sethalterr, // set halt-on error flag -ST20_settimeslice, // set timeslicing status -ST20_slmul, // signed long multiply -ST20_ss, // store sixteen -ST20_ssub, // sixteen subscript -ST20_startp, // start process -ST20_stclock, // store clock register -ST20_sthb, // store high priority back pointer -ST20_sthf, // store high priority front pointer -ST20_stlb, // store low priority back pointer -ST20_stlf, // store low priority front pointer -ST20_stoperr, // stop on error -ST20_stopp, // stop process -ST20_stshadow, // store shadow registers -ST20_sttimer, // store timer -ST20_sttraph, // store trap handler -ST20_sttrapped, // store trapped process -ST20_sulmul, // signed timer unsigned long multiply -ST20_sum, // sum -ST20_swapqueue, // swap scheduler queue -ST20_swaptimer, // swap timer queue -ST20_talt, // timer alt start -ST20_taltwt, // timer alt wait -ST20_testerr, // test error flag -ST20_testhalterr, // test halt-on error flag -ST20_testpranal, // test processor analysing -ST20_tin, // timer input -ST20_trapdis, // trap disable -ST20_trapenb, // trap enable -ST20_tret, // trap return -ST20_unpacksn, // unpack single length fp number -ST20_wcnt, // word count -ST20_wsubdb, // form double word subscript -ST20_xdble, // extend to double -ST20_xword, // extend word - -ST20_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -ST7_null = 0, // Unknown Operation - -ST7_adc, // Add with Carry -ST7_add, // Addition -ST7_and, // Logical And -ST7_bcp, // Bit compare -ST7_bres, // Bit Reset -ST7_bset, // Bit Set -ST7_btjf, // Jump if bit is false -ST7_btjt, // Jump if bit is true -ST7_call, // Call subroutine -ST7_callr, // Call subroutine relative -ST7_clr, // Clear -ST7_cp, // Arithmetic Compare -ST7_cpl, // One Complement -ST7_dec, // Decrement -ST7_halt, // Halt -ST7_iret, // Interrupt routine return -ST7_inc, // Increment -ST7_jp, // Absolute Jump -ST7_jra, // Jump relative always -ST7_jrt, // Jump relative -ST7_jrf, // Never jump -ST7_jrih, // Jump if Port INT pin = 1 -ST7_jril, // Jump if Port INT pin = 0 -ST7_jrh, // Jump if H = 1 -ST7_jrnh, // Jump if H = 0 -ST7_jrm, // Jump if I = 1 -ST7_jrnm, // Jump if I = 0 -ST7_jrmi, // Jump if N = 1 (minus) -ST7_jrpl, // Jump if N = 0 (plus) -ST7_jreq, // Jump if Z = 1 (equal) -ST7_jrne, // Jump if Z = 0 (not equal) -ST7_jrc, // Jump if C = 1 -ST7_jrnc, // Jump if C = 0 -ST7_jrult, // Jump if C = 1 -ST7_jruge, // Jump if C = 0 -ST7_jrugt, // Jump if (C + Z = 0) -ST7_jrule, // Jump if (C + Z = 1) -ST7_ld, // Load -ST7_mul, // Multiply -ST7_neg, // Negate -ST7_nop, // No Operation -ST7_or, // OR Operation -ST7_pop, // Pop from the Stack -ST7_push, // Push onto the Stack -ST7_rcf, // Reset carry flag -ST7_ret, // Subroutine Return -ST7_rim, // Enable Interrupts -ST7_rlc, // Rotate left true -ST7_rrc, // Rotate right true -ST7_rsp, // Reset Stack Pointer -ST7_sbc, // Subtract with Carry -ST7_scf, // Set carry flag -ST7_sim, // Disable Interrupts -ST7_sla, // Shift left Arithmetic -ST7_sll, // Shift left Logic -ST7_srl, // Shift right Logic -ST7_sra, // Shift right Arithmetic -ST7_sub, // Substraction -ST7_swap, // SWAP nibbles -ST7_tnz, // Test for Neg & Zero -ST7_trap, // S/W trap -ST7_wfi, // Wait for Interrupt -ST7_xor, // Exclusive OR - -ST7_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -IA64_null, // 0 -IA64_0, // 1 -IA64_1, // 2 -IA64_a, // 3 -IA64_acq, // 4 -IA64_add, // 5 Add -IA64_addl, // 6 -IA64_addp4, // 7 Add pointer -IA64_adds, // 8 -IA64_alloc, // 9 Allocate stack frame -IA64_and, // 10 Logical AND -IA64_andcm, // 11 And complement -IA64_b, // 12 -IA64_bias, // 13 -IA64_br, // 14 Branch -IA64_break, // 15 Break -IA64_brl, // 16 Branch long -IA64_brp, // 17 Branch predict -IA64_bsw, // 18 Bank switch -IA64_c, // 19 -IA64_call, // 20 -IA64_cexit, // 21 -IA64_chk, // 22 Speculation check -IA64_cloop, // 23 -IA64_clr, // 24 -IA64_clrrrb, // 25 Clear RRB -IA64_cmp, // 26 Compare -IA64_cmp4, // 27 Compare word -IA64_cmpxchg1, // 28 Compare and exchange byte -IA64_cmpxchg2, // 29 Compare and exchange halfword -IA64_cmpxchg4, // 30 Compare and exchange word -IA64_cmpxchg8, // 31 Compare and exchange double word -IA64_cond, // 32 -IA64_cover, // 33 Cover stack frame -IA64_ctop, // 34 -IA64_czx1, // 35 Compute zero index -IA64_czx2, // 36 Compute zero index -IA64_d, // 37 -IA64_dep, // 38 Deposit -IA64_dpnt, // 39 -IA64_dptk, // 40 -IA64_e, // 41 -IA64_epc, // 42 Enter privileged code -IA64_eq, // 43 -IA64_excl, // 44 -IA64_exit, // 45 -IA64_exp, // 46 -IA64_extr, // 47 Extract -IA64_f, // 48 -IA64_fabs, // 49 Floating point absolute value -IA64_fadd, // 50 Floating point add -IA64_famax, // 51 Floating point absolute maximum -IA64_famin, // 52 Floating point absolute minimum -IA64_fand, // 53 Floating point logical and -IA64_fandcm, // 54 Floating point and complement -IA64_fault, // 55 -IA64_fc, // 56 Flush cache -IA64_fchkf, // 57 Floating point check flags -IA64_fclass, // 58 Floating point class -IA64_fclrf, // 59 Floating point clear flags -IA64_fcmp, // 60 Floating point compare -IA64_fcvt, // 61 Convert floating point to/from integer -IA64_fetchadd4, // 62 Fetch word and add immediate -IA64_fetchadd8, // 63 Fetch double word and add immediate -IA64_few, // 64 -IA64_fill, // 65 -IA64_flushrs, // 66 Flush register stack -IA64_fma, // 67 Floating point multiply add -IA64_fmax, // 68 Floating point maximum -IA64_fmerge, // 69 Floating point merge -IA64_fmin, // 70 Floating point minimum -IA64_fmix, // 71 Floating point mix -IA64_fmpy, // 72 Floating point multiply -IA64_fms, // 73 Floating point multiply subtract -IA64_fneg, // 74 Floating point negate -IA64_fnegabs, // 75 Floating point negate absolute value -IA64_fnma, // 76 Floating point negative multiply add -IA64_fnmpy, // 77 Floating point negative multiply -IA64_fnorm, // 78 Floating point normalize -IA64_for, // 79 Floating point logical or -IA64_fpabs, // 80 Floating point parallel absolute value -IA64_fpack, // 81 Floating point pack -IA64_fpamax, // 82 Floating point parallel absolute maximum -IA64_fpamin, // 83 Floating point parallel absolute minimum -IA64_fpcmp, // 84 Floating point parallel compare -IA64_fpcvt, // 85 Floating point parallel conversion -IA64_fpma, // 86 Floating point parallel multiply add -IA64_fpmax, // 87 Floating point parallel maximum -IA64_fpmerge, // 88 Floating point parallel merge -IA64_fpmin, // 89 Floating point parallel minimum -IA64_fpmpy, // 90 Floating point parallel multiply -IA64_fpms, // 91 Floating point parallel multiply subtract -IA64_fpneg, // 92 Floating point parallel negate -IA64_fpnegabs, // 93 Floating point parallel negate absolute value -IA64_fpnma, // 94 Floating point parallel negative multiply add -IA64_fpnmpy, // 95 Floating point parallel negative multiply -IA64_fprcpa, // 96 Floating point parallel reciprocal approximation -IA64_fprsqrta, // 97 Floating point parallel reciprocal square root approximation -IA64_frcpa, // 98 Floating point reciprocal approximation -IA64_frsqrta, // 99 Floating point reciprocal square root approximation -IA64_fselect, // 100 Floating point select -IA64_fsetc, // 101 Floating point set controls -IA64_fsub, // 102 Floating point subtract -IA64_fswap, // 103 Floating point swap -IA64_fsxt, // 104 Floating point sign extend -IA64_fwb, // 105 Flush write buffers -IA64_fx, // 106 -IA64_fxor, // 107 Floating point exclusive or -IA64_fxu, // 108 -IA64_g, // 109 -IA64_ga, // 110 -IA64_ge, // 111 -IA64_getf, // 112 Get floating point value or exponent or significand -IA64_geu, // 113 -IA64_gt, // 114 -IA64_gtu, // 115 -IA64_h, // 116 -IA64_hu, // 117 -IA64_i, // 118 -IA64_ia, // 119 -IA64_imp, // 120 -IA64_invala, // 121 Invalidate ALAT -IA64_itc, // 122 Insert translation cache -IA64_itr, // 123 Insert translation register -IA64_l, // 124 -IA64_ld1, // 125 Load byte -IA64_ld2, // 126 Load halfword -IA64_ld4, // 127 Load word -IA64_ld8, // 128 Load double word -IA64_ldf, // 129 Floating point load -IA64_ldf8, // 130 Floating point load -IA64_ldfd, // 131 Floating point load -IA64_ldfe, // 132 Floating point load -IA64_ldfp8, // 133 Floating point load pair -IA64_ldfpd, // 134 Floating point load pair -IA64_ldfps, // 135 Floating point load pair -IA64_ldfs, // 136 Floating point load -IA64_le, // 137 -IA64_leu, // 138 -IA64_lfetch, // 139 Line prefetch -IA64_loadrs, // 140 Load register stack -IA64_loop, // 141 -IA64_lr, // 142 -IA64_lt, // 143 -IA64_ltu, // 144 -IA64_lu, // 145 -IA64_m, // 146 -IA64_many, // 147 -IA64_mf, // 148 Memory fence -IA64_mix1, // 149 Mix bytes -IA64_mix2, // 150 Mix halfwords -IA64_mix4, // 151 Mix words -IA64_mov, // 152 Move register -IA64_movl, // 153 Move long immediate -IA64_mux1, // 154 Mux byte -IA64_mux2, // 155 Mux halfword -IA64_nc, // 156 -IA64_ne, // 157 -IA64_neq, // 158 -IA64_nge, // 159 -IA64_ngt, // 160 -IA64_nl, // 161 -IA64_nle, // 162 -IA64_nlt, // 163 -IA64_nm, // 164 -IA64_nop, // 165 No operation -IA64_nr, // 166 -IA64_ns, // 167 -IA64_nt1, // 168 -IA64_nt2, // 169 -IA64_nta, // 170 -IA64_nz, // 171 -IA64_or, // 172 Logical or -IA64_orcm, // 173 -IA64_ord, // 174 -IA64_pack2, // 175 Pack -IA64_pack4, // 176 Pack -IA64_padd1, // 177 Parallel add bytes -IA64_padd2, // 178 Parallel add halfwords -IA64_padd4, // 179 Parallel add words -IA64_pavg1, // 180 Parallel average bytes -IA64_pavg2, // 181 Parallel average halfwords -IA64_pavgsub1, // 182 Parallel average subtract bytes -IA64_pavgsub2, // 183 Parallel average subtract halfwords -IA64_pcmp1, // 184 Parallel compare bytes -IA64_pcmp2, // 185 Parallel compare halfwords -IA64_pcmp4, // 186 Parallel compare words -IA64_pmax1, // 187 Parallel maxmimum bytes -IA64_pmax2, // 188 Parallel maxmimum halfwords -IA64_pmin1, // 189 Parallel minimum bytes -IA64_pmin2, // 190 Parallel minimum halfwords -IA64_pmpy2, // 191 Parallel multiply -IA64_pmpyshr2, // 192 Parallel multiply and shift right -IA64_popcnt, // 193 Population count -IA64_pr, // 194 -IA64_probe, // 195 Probe address -IA64_psad1, // 196 Parallel sum of absolute difference -IA64_pshl2, // 197 Parallel shift left halfwords -IA64_pshl4, // 198 Parallel shift left words -IA64_pshladd2, // 199 Parallel shift left and Add -IA64_pshr2, // 200 Parallel shift right halfwords -IA64_pshr4, // 201 Parallel shift right words -IA64_pshradd2, // 202 Parallel shift right and Add -IA64_psub1, // 203 Parallel subtract bytes -IA64_psub2, // 204 Parallel subtract halfwords -IA64_psub4, // 205 Parallel subtract words -IA64_ptc, // 206 Purge translation cache -IA64_ptr, // 207 Purge translation register -IA64_r, // 208 -IA64_raz, // 209 -IA64_rel, // 210 -IA64_ret, // 211 -IA64_rfi, // 212 Return from interruption -IA64_rsm, // 213 Reset system mask -IA64_rum, // 214 Reset user mask -IA64_rw, // 215 -IA64_s, // 216 -IA64_s0, // 217 -IA64_s1, // 218 -IA64_s2, // 219 -IA64_s3, // 220 -IA64_sa, // 221 -IA64_se, // 222 -IA64_setf, // 223 Set floating point value, exponent, or significand -IA64_shl, // 224 Shift left -IA64_shladd, // 225 Shift left and Add -IA64_shladdp4, // 226 Shift left and Add pointer -IA64_shr, // 227 Shift right -IA64_shrp, // 228 Shift right pair -IA64_sig, // 229 -IA64_spill, // 230 -IA64_spnt, // 231 -IA64_sptk, // 232 -IA64_srlz, // 233 Serialize -IA64_ssm, // 234 Set system mask -IA64_sss, // 235 -IA64_st1, // 236 Store byte -IA64_st2, // 237 Store halfword -IA64_st4, // 238 Store word -IA64_st8, // 239 Store double word -IA64_stf, // 240 Store floating point -IA64_stf8, // 241 Store floating point -IA64_stfd, // 242 Store floating point -IA64_stfe, // 243 Store floating point -IA64_stfs, // 244 Store floating point -IA64_sub, // 245 Subtract -IA64_sum, // 246 Set user mask -IA64_sxt1, // 247 Sign extend byte -IA64_sxt2, // 248 Sign extend halfword -IA64_sxt4, // 249 Sign extend word -IA64_sync, // 250 Memory synchronization -IA64_tak, // 251 Translation access key -IA64_tbit, // 252 Test bit -IA64_thash, // 253 Translation hashed entry address -IA64_tnat, // 254 Test NaT -IA64_tpa, // 255 Translate to physical address -IA64_trunc, // 256 -IA64_ttag, // 257 Translation hashed entry tag -IA64_u, // 258 -IA64_unc, // 259 -IA64_unord, // 260 -IA64_unpack1, // 261 Unpack byte -IA64_unpack2, // 262 Unpack halfword -IA64_unpack4, // 263 Unpack word -IA64_uss, // 264 -IA64_uus, // 265 -IA64_uuu, // 266 -IA64_w, // 267 -IA64_wexit, // 268 -IA64_wtop, // 269 -IA64_x, // 270 -IA64_xchg1, // 271 Exchange bytes -IA64_xchg2, // 272 Exchange halfwords -IA64_xchg4, // 273 Exchange words -IA64_xchg8, // 274 Exchange double words -IA64_xf, // 275 -IA64_xma, // 276 Fixed point multiply add -IA64_xmpy, // 277 Fixed point multiply -IA64_xor, // 278 Exclusive or -IA64_xuf, // 279 -IA64_z, // 280 -IA64_zxt1, // 281 Zero extend byte -IA64_zxt2, // 282 Zero extend halfword -IA64_zxt4, // 283 Zero extend word -IA64_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -NET_null = 0, // Unknown Operation - -NET_add, // Add two values, returning a new value -NET_add_ovf, // Add signed integer values with overflow check -NET_add_ovf_un, // Add unsigned integer values with overflow check -NET_and, // Bitwise AND of two integral values, returns an integral value -NET_ann_arg, // -NET_ann_call, // Start of simple calling sequence -NET_ann_catch, // Start an exception filter or handler -NET_ann_data, // Multi-byte no operation -NET_ann_data_s, // Multi-byte no operation, short form -NET_ann_dead, // Stack location is no longer live -NET_ann_def, // SSA definition node -NET_ann_hoisted, // Start of the simple portion of a hoisted calling sequence -NET_ann_hoisted_call, // Start of complex argument evaluation -NET_ann_lab, // -NET_ann_live, // Mark a stack location as live -NET_ann_phi, // SSA definition node -NET_ann_ref, // SSA reference node -NET_ann_ref_s, // SSA reference node, short form -NET_arglist, // Return argument list handle for the current method -NET_beq, // Branch to target if equal -NET_beq_s, // Branch to target if equal, short form -NET_bge, // Branch to target if greater than or equal to -NET_bge_s, // Branch to target if greater than or equal to, short form -NET_bge_un, // Branch to target if greater than or equal to (unsigned or unordered) -NET_bge_un_s, // Branch to target if greater than or equal to (unsigned or unordered), short form -NET_bgt, // Branch to target if greater than -NET_bgt_s, // Branch to target if greater than, short form -NET_bgt_un, // Branch to target if greater than (unsigned or unordered) -NET_bgt_un_s, // Branch to target if greater than (unsigned or unordered), short form -NET_ble, // Branch to target if less than or equal to -NET_ble_s, // Branch to target if less than or equal to, short form -NET_ble_un, // Branch to target if less than or equal to (unsigned or unordered) -NET_ble_un_s, // Branch to target if less than or equal to (unsigned or unordered), short form -NET_blt, // Branch to target if less than -NET_blt_s, // Branch to target if less than, short form -NET_blt_un, // Branch to target if less than (unsigned or unordered) -NET_blt_un_s, // Branch to target if less than (unsigned or unordered), short form -NET_bne_un, // Branch to target if unequal or unordered -NET_bne_un_s, // Branch to target if unequal or unordered, short form -NET_box, // Convert value type to object reference -NET_br, // Branch to target -NET_br_s, // Branch to target, short form -NET_break, // Inform a debugger that a breakpoint has been reached -NET_brfalse, // Branch to target if value is zero (false) -NET_brfalse_s, // Branch to target if value is zero (false), short form -NET_brtrue, // Branch to target if value is non-zero (true) -NET_brtrue_s, // Branch to target if value is non-zero (true), short form -NET_call, // Call a method -NET_calli, // Call an indirect method -NET_callvirt, // Call a method associated with obj -NET_castclass, // Cast object to class -NET_ceq, // Push 1 (of type I4) if value1 equals value2, else 0 -NET_cgt, // Push 1 (of type I4) if value1 > value2, else 0 -NET_cgt_un, // Push 1 (of type I4) if value1 > value2, unsigned or unordered, else 0 -NET_ckfinite, // Throw ArithmeticException if value is not a finite number -NET_clt, // Push 1 (of type I4) if value1 < value2, else 0 -NET_clt_un, // Push 1 (of type I4) if value1 < value2, unsigned or unordered, else 0 -NET_conv_i, // Convert to I, pushing I on stack -NET_conv_i1, // Convert to I1, pushing I4 on stack -NET_conv_i2, // Convert to I2, pushing I4 on stack -NET_conv_i4, // Convert to I4, pushing I4 on stack -NET_conv_i8, // Convert to I8, pushing I8 on stack -NET_conv_ovf_i, // Convert to an I (on the stack as I) and throw an exception on overflow -NET_conv_ovf_i1, // Convert to an I1 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_i1_un, // Convert unsigned to an I1 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_i2, // Convert to an I2 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_i2_un, // Convert unsigned to an I2 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_i4, // Convert to an I4 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_i4_un, // Convert unsigned to an I4 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_i8, // Convert to an I8 (on the stack as I8) and throw an exception on overflow -NET_conv_ovf_i8_un, // Convert unsigned to an I8 (on the stack as I8) and throw an exception on overflow -NET_conv_ovf_i_un, // Convert to unsigned an I (on the stack as I) and throw an exception on overflow -NET_conv_ovf_u, // Convert to a U (on the stack as I) and throw an exception on overflow -NET_conv_ovf_u1, // Convert to a U1 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_u1_un, // Convert to unsigned a U1 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_u2, // Convert to a U2 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_u2_un, // Convert to unsigned a U2 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_u4, // Convert to a U4 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_u4_un, // Convert to unsigned a U3 (on the stack as I4) and throw an exception on overflow -NET_conv_ovf_u8, // Convert to a U8 (on the stack as I8) and throw an exception on overflow -NET_conv_ovf_u8_un, // Convert to unsigned a U8 (on the stack as I8) and throw an exception on overflow -NET_conv_ovf_u_un, // Convert to unsigned a U (on the stack as I) and throw an exception on overflow -NET_conv_r4, // Convert to R4, pushing F on stack -NET_conv_r8, // Convert to R8, pushing F on stack -NET_conv_r_un, // Convert unsigned integer to floating point, pushing F on stack -NET_conv_u, // Convert to U, pushing I on stack -NET_conv_u1, // Convert to U1, pushing I4 on stack -NET_conv_u2, // Convert to U2, pushing I4 on stack -NET_conv_u4, // Convert to U4, pushing I4 on stack -NET_conv_u8, // Convert to U8, pushing I8 on stack -NET_cpblk, // Copy data from memory to memory -NET_cpobj, // Copy a value type -NET_div, // Divide two values to return a quotient or floating point result -NET_div_un, // Divide two values, unsigned, returning a quotient -NET_dup, // Duplicate value on the top of the stack -NET_endfilter, // End filter clause of SEH exception handling -NET_endfinally, // End fault clause of an exception block -NET_initblk, // Set a block of memory to a given byte -NET_initobj, // Initialize a value type -NET_isinst, // Test if an object is an instance of a class or interface, returning NULL or an instance of that class or interface -NET_jmp, // Exit current method and jump to specified method -NET_ldarg, // Load argument numbered num onto stack -NET_ldarg_0, // Load argument 0 onto stack -NET_ldarg_1, // Load argument 1 onto stack -NET_ldarg_2, // Load argument 2 onto stack -NET_ldarg_3, // Load argument 3 onto stack -NET_ldarg_s, // Load argument numbered num onto stack, short form -NET_ldarga, // Fetch the address of argument -NET_ldarga_s, // Fetch the address of argument, short form -NET_ldc_i4, // Push num of type I4 onto the stack as I4 -NET_ldc_i4_0, // Push 0 onto the stack as I4 -NET_ldc_i4_1, // Push 1 onto the stack as I4 -NET_ldc_i4_2, // Push 2 onto the stack as I4 -NET_ldc_i4_3, // Push 3 onto the stack as I4 -NET_ldc_i4_4, // Push 4 onto the stack as I4 -NET_ldc_i4_5, // Push 5 onto the stack as I4 -NET_ldc_i4_6, // Push 6 onto the stack as I4 -NET_ldc_i4_7, // Push 7 onto the stack as I4 -NET_ldc_i4_8, // Push 8 onto the stack as I4 -NET_ldc_i4_m1, // Push -1 onto the stack as I4 -NET_ldc_i4_s, // Push num onto the stack as I4, short form -NET_ldc_i8, // Push num of type I8 onto the stack as I8 -NET_ldc_r4, // Push num of type R4 onto the stack as F -NET_ldc_r8, // Push num of type R8 onto the stack as F -NET_ldelem_i, // Load the element at index with type I onto the top of the stack as an I -NET_ldelem_i1, // Load the element at index with type I1 onto the top of the stack as an I4 -NET_ldelem_i2, // Load the element at index with type I2 onto the top of the stack as an I4 -NET_ldelem_i4, // Load the element at index with type I4 onto the top of the stack as an I4 -NET_ldelem_i8, // Load the element at index with type I8 onto the top of the stack as an I8 -NET_ldelem_r4, // Load the element at index with type R4 onto the top of the stack as an F -NET_ldelem_r8, // Load the element at index with type R8 onto the top of the stack as an F -NET_ldelem_ref, // Load the element at index, an object, onto the top of the stack as an O -NET_ldelem_u1, // Load the element at index with type U1 onto the top of the stack as an I4 -NET_ldelem_u2, // Load the element at index with type U2 onto the top of the stack as an I4 -NET_ldelem_u4, // Load the element at index with type U4 onto the top of the stack as an I4 -NET_ldelema, // Load the address of element at index onto the top of the stack -NET_ldfld, // Push the value of field of object on the stack -NET_ldflda, // Push the address of field of object on the stack -NET_ldftn, // Push a pointer to a method referenced by method on the stack -NET_ldind_i, // Indirect load value of type I as I stack -NET_ldind_i1, // Indirect load value of type I1 as I4 on stack -NET_ldind_i2, // Indirect load value of type I2 as I4 on stack -NET_ldind_i4, // Indirect load value of type I4 as I4 on stack -NET_ldind_i8, // Indirect load value of type I8 as I8 on stack -NET_ldind_r4, // Indirect load value of type R4 as F stack -NET_ldind_r8, // Indirect load value of type R8 as F stack -NET_ldind_ref, // Indirect load value of type object ref as O on stack -NET_ldind_u1, // Indirect load value of type U1 as I4 stack -NET_ldind_u2, // Indirect load value of type U2 as I4 stack -NET_ldind_u4, // Indirect load value of type U4 as I4 stack -NET_ldlen, // Push the length (of type U) of array on the stack -NET_ldloc, // Load local variable of index indx onto stack -NET_ldloc_0, // Load local variable 0 onto stack -NET_ldloc_1, // Load local variable 1 onto stack -NET_ldloc_2, // Load local variable 2 onto stack -NET_ldloc_3, // Load local variable 3 onto stack -NET_ldloc_s, // Load local variable of index indx onto stack, short form -NET_ldloca, // Load address of local variable -NET_ldloca_s, // Load address of local variable, short form -NET_ldnull, // Push null GC reference on the stack -NET_ldobj, // Copy instance of value type to the stack. -NET_ldsfld, // Push the value of field on the stack -NET_ldsflda, // Push the address of the static field on the stack -NET_ldstr, // Push a string object for the literal string -NET_ldtoken, // Convert metadata token to its runtime representation -NET_ldvirtftn, // Push address of virtual method on the stack -NET_leave, // Exit a protected region of code -NET_leave_s, // Exit a protected region of code, short form -NET_localloc, // Allocate space from the local memory pool -NET_mkrefany, // Push a typed reference to pointer of type class onto the stack -NET_mul, // Multiply values -NET_mul_ovf, // Multiply signed integer values. Signed result must fit in same size -NET_mul_ovf_un, // Multiply unsigned integer values. Unsigned result must fit in same size -NET_neg, // Negate value -NET_newarr, // Create a zero-based, one-dimensional array -NET_newobj, // Create a new object -NET_nop, // Do nothing -NET_not, // Bitwise complement -NET_or, // Bitwise OR of two integer values, returns an integer -NET_pop, // Pop a value from the stack -NET_refanytype, // Push the type token stored in a typed reference -NET_refanyval, // Push the address stored in a typed reference -NET_rem, // Remainder of dividing value1 by value2 -NET_rem_un, // Remainder of unsigned dividing value1 by value2 -NET_ret, // Return from method, possibly returning a value -NET_rethrow, // Rethrow the current exception -NET_shl, // Shift an integer to the left (shifting in zeros) -NET_shr, // Shift an integer right, (shift in sign), return an integer -NET_shr_un, // Shift an integer right, (shift in zero), return an integer -NET_sizeof, // Push the size, in bytes, of a value type as a U4 -NET_starg, // Store a value to argument -NET_starg_s, // Store a value to argument, short form -NET_stelem_i, // Replace array element at index with the I value on the stack -NET_stelem_i1, // Replace array element at index with the I1 value on the stack -NET_stelem_i2, // Replace array element at index with the I2 value on the stack -NET_stelem_i4, // Replace array element at index with the I4 value on the stack -NET_stelem_i8, // Replace array element at index with the I8 value on the stack -NET_stelem_r4, // Replace array element at index with the R4 value on the stack -NET_stelem_r8, // Replace array element at index with the R8 value on the stack -NET_stelem_ref, // Replace array element at index with the ref value on the stack -NET_stfld, // Store into a field of an object -NET_stind_i, // Store value of type I into memory at address -NET_stind_i1, // Store value of type I1 into memory at address -NET_stind_i2, // Store value of type I2 into memory at address -NET_stind_i4, // Store value of type I4 into memory at address -NET_stind_i8, // Store value of type I8 into memory at address -NET_stind_r4, // Store value of type R4 into memory at address -NET_stind_r8, // Store value of type R8 into memory at address -NET_stind_ref, // Store value of type object ref (type O) into memory at address -NET_stloc, // Pop value from stack into local variable -NET_stloc_0, // Pop value from stack into local variable 0 -NET_stloc_1, // Pop value from stack into local variable 1 -NET_stloc_2, // Pop value from stack into local variable 2 -NET_stloc_3, // Pop value from stack into local variable 3 -NET_stloc_s, // Pop value from stack into local variable, short form -NET_stobj, // Store a value type from the stack into memory -NET_stsfld, // Store a static field of a class -NET_sub, // Subtract value2 from value1, returning a new value -NET_sub_ovf, // Subtract I from an I. Signed result must fit in same size -NET_sub_ovf_un, // Subtract U from a U. Unsigned result must fit in same size -NET_switch, // Jump to one of N values -NET_tail_, // (prefix) subsequent call terminates current method -NET_throw, // Throw an exception -NET_unaligned_, // (prefix) subsequent pointer instruction may be unaligned -NET_unbox, // Convert boxed value type to its raw form -NET_volatile_, // (prefix) subsequent pointer reference is volatile -NET_xor, // Bitwise XOR of integer values, returns an integer -NET_ldelem, // Load the element at index onto the top of the stack -NET_stelem, // Replace array element at index with the ref value on the stack - -// 2.0 instructions -NET_unbox_any, // Extract a value-type from obj, its boxed representation -NET_constrained_, // (prefix) invoke a member on a value of a variable type -NET_no_, // (prefix) possibly skip a fault check -NET_readonly_, // (prefix) following instruction returns a controlled-mutability managed pointer - -NET_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * HCS12X opcodes added by alexbratovic@bratspeed.com 12/12/2007 - * XGATE opcodes added by alexbratovic@bratspeed.com 12/09/2009 - */ - - - - -enum -{ -MC12_null = 0, // Unknown Operation - -MC12_aba, // Add B to A -MC12_abx, // Add B to X -MC12_aby, // Add B to Y -MC12_adca, // Add with carry to A -MC12_adcb, // Add with carry to B -MC12_adda, // Add memory to A -MC12_addb, // Add memory to B -MC12_addd, // Add to D -MC12_anda, // AND A with memory -MC12_andb, // AND B with memory -MC12_andcc, // Logical AND CCR with memory -MC12_asl, // Arithmetic shift left memory -MC12_asla, // Arithmetic shift left A -MC12_aslb, // Arithmetic shift left B -MC12_asld, // Arithmetic shift left D -MC12_asr, // Arithmetic shift right memory -MC12_asra, // Arithmetic shift right A -MC12_asrb, // Arithmetic shift right B -MC12_bcc, // Branch if carry clear -MC12_bclr, // Clear bits in memory -MC12_bcs, // Branch if carry set -MC12_beq, // Branch if equal -MC12_bge, // Branch if greater than or equal -MC12_bgnd, // Enter background debug mode -MC12_bgt, // Branch if greater than -MC12_bhi, // Branch if higher -MC12_bhs, // Branch if higher or same -MC12_bita, // Bit test A -MC12_bitb, // Bit test B -MC12_ble, // Branch if less than or equal -MC12_blo, // Branch if lower -MC12_bls, // Branch if lower or same -MC12_blt, // Branch if less than -MC12_bmi, // Branch if minus -MC12_bne, // Branch if not equal -MC12_bpl, // Branch if plus -MC12_bra, // Branch always -MC12_brclr, // Branch if selected bits clear -MC12_brn, // Branch never -MC12_brset, // Branch if selected bits set -MC12_bset, // Set bits in memory -MC12_bsr, // Branch to subroutine -MC12_bvc, // Branch if overflow clear -MC12_bvs, // Branch if overflow set -MC12_call, // Call subroutine in expanded memory -MC12_cba, // Compare A to B -MC12_clc, // Clear C bit -MC12_cli, // Clear I bit -MC12_clr, // Clear memory -MC12_clra, // Clear A -MC12_clrb, // Clear B -MC12_clv, // Clear V bit -MC12_cmpa, // Compare A to memory -MC12_cmpb, // Compare B to memory -MC12_com, // One's complement memory -MC12_coma, // One's complement A -MC12_comb, // One's complement B -MC12_cpd, // Compare D to memory (16-bit) -MC12_cps, // Compare SP to memory (16-bit) -MC12_cpx, // Compare X to memory (16-bit) -MC12_cpy, // Compare Y to memory (16-bit) -MC12_daa, // Decimal adjust A -MC12_dbeq, // Decrement counter and branch if = 0 -MC12_dbne, // Decrement counter and branch if != 0 -MC12_dec, // Decrement memory -MC12_deca, // Decrement A -MC12_decb, // Decrement B -MC12_des, // Decrement SP -MC12_dex, // Decrement X -MC12_dey, // Decrement Y -MC12_ediv, // 32 by 16 divide (unsigned) Quotient->Y Remainder->D -MC12_edivs, // 32 by 16 divide (signed) Quotient->Y Remainder->D -MC12_emacs, // Multiply and accumulate (signed) -MC12_emaxd, // MAX of two unsigned 16-bit values result to accumulator -MC12_emaxm, // MAX of two unsigned 16-bit values result to memory -MC12_emind, // MIN of two unsigned 16-bit values result to accumulator -MC12_eminm, // MIN of two unsigned 16-bit values result to memory -MC12_emul, // 16 by 16 multiply (unsigned) -MC12_emuls, // 16 by 16 multiply (signed) -MC12_eora, // Exclusive OR A with memory -MC12_eorb, // Exclusive OR B with memory -MC12_etbl, // 16-bit table lookup and interpolate -MC12_exg, // Exchange register to register -MC12_fdiv, // 16 by 16 fractional divide Remainder->D -MC12_ibeq, // Increment counter and branch if = 0 -MC12_ibne, // Increment counter and branch if != 0 -MC12_idiv, // 16 by 16 integer divide (unsigned) Remainder->D -MC12_idivs, // 16 by 16 integer divide (signed) Remainder->D -MC12_inc, // Increment memory -MC12_inca, // Increment A -MC12_incb, // Increment B -MC12_ins, // Increment SP -MC12_inx, // Increment X -MC12_iny, // Increment Y -MC12_jmp, // Jump Address -MC12_jsr, // Jump to subroutine -MC12_lbcc, // Long branch if carry clear -MC12_lbcs, // Long branch if carry set -MC12_lbeq, // Long branch if equal -MC12_lbge, // Long branch if greater than or equal -MC12_lbgt, // Long branch if greater than -MC12_lbhi, // Long branch if higher -MC12_lbhs, // Long branch if higher or same -MC12_lble, // Long branch if less than or equal -MC12_lblo, // Long branch if lower -MC12_lbls, // Long branch if lower or same -MC12_lblt, // Long branch if less than -MC12_lbmi, // Long branch if minus -MC12_lbne, // Long branch if not equal -MC12_lbpl, // Long branch if plus -MC12_lbra, // Long branch always -MC12_lbrn, // Long branch never -MC12_lbvc, // Long branch if overflow clear -MC12_lbvs, // Long branch if overflow set -MC12_ldaa, // Load A -MC12_ldab, // Load B -MC12_ldd, // Load D -MC12_lds, // Load SP -MC12_ldx, // Load X -MC12_ldy, // Load Y -MC12_leas, // Load effective address into SP -MC12_leax, // Load effective address into X -MC12_leay, // Load effective address into Y -MC12_lsl, // Logic shift left memory -MC12_lsla, // Logic shift left A -MC12_lslb, // Logic shift left B -MC12_lsld, // Logic shift left D -MC12_lsr, // Logic shift right memory -MC12_lsra, // Logic shift right A -MC12_lsrb, // Logic shift right B -MC12_lsrd, // Logic shift right D -MC12_maxa, // MAX of two unsigned 8-bit values result to accumulator -MC12_maxm, // MAX of two unsigned 8-bit values result to memory -MC12_mem, // Membership function -MC12_mina, // MIN of two unsigned 8-bit values result to accumulator -MC12_minm, // MIN of two unsigned 8-bit values result to memory -MC12_movb, // Move byte (8-bit) -MC12_movw, // Move word (16-bit) -MC12_mul, // 8 by 8 multiply (unsigned) -MC12_neg, // Two's complement memory -MC12_nega, // Two's complement A -MC12_negb, // Two's complement B -MC12_nop, // Null operation -MC12_oraa, // OR A with memory -MC12_orab, // OR B with memory -MC12_orcc, // Logical OR CCR with memory -MC12_psha, // Push A -MC12_pshb, // Push B -MC12_pshc, // Push CCR -MC12_pshd, // Push D -MC12_pshx, // Push X -MC12_pshy, // Push Y -MC12_pula, // Pull A -MC12_pulb, // Pull B -MC12_pulc, // Pull CCR -MC12_puld, // Pull D -MC12_pulx, // Pull X -MC12_puly, // Pull Y -MC12_rev, // MIN-MAX rule evaluation -MC12_revw, // MIN-MAX rule evaluation -MC12_rol, // Rotate left memory through carry -MC12_rola, // Rotate left A through carry -MC12_rolb, // Rotate left B through carry -MC12_ror, // Rotate right memory through carry -MC12_rora, // Rotate right A through carry -MC12_rorb, // Rotate right B through carry -MC12_rtc, // Return from call -MC12_rti, // Return from interrupt -MC12_rts, // Return from subroutine -MC12_sba, // Subtract B from A -MC12_sbca, // Subtract with borrow from A -MC12_sbcb, // Subtract with borrow from B -MC12_sec, // Set C bit -MC12_sei, // Set I bit -MC12_sev, // Set V bit -MC12_sex, // Sign extend 8-Bit operand -MC12_staa, // Store A -MC12_stab, // Store B -MC12_std, // Store D -MC12_stop, // Stop -MC12_sts, // Store SP -MC12_stx, // Store X -MC12_sty, // Store Y -MC12_suba, // Subtract memory from A -MC12_subb, // Subtract memory from B -MC12_subd, // Subtract memory from D -MC12_swi, // Software interrupt -MC12_tab, // Transfer A to B -MC12_tap, // Transfer A to CCR -MC12_tba, // Transfer B to A -MC12_tbeq, // Test counter and branch if = 0 -MC12_tbl, // 8-bit table lookup and interpolate -MC12_tbne, // Test counter and branch if != 0 -MC12_tfr, // Transfer register to register -MC12_tpa, // Transfer CCR to A -MC12_trap, // Unimplemented opcode interrupt -MC12_tst, // Test memory for zero or minus -MC12_tsta, // Test A for zero or minus -MC12_tstb, // Test B for zero or minus -MC12_tsx, // Transfer SP to X -MC12_tsy, // Transfer SP to Y -MC12_txs, // Transfer X to SP -MC12_tys, // Transfer Y to SP -MC12_wai, // Wait for interrupt -MC12_wav, // Calculates numerator and denominator for weighted average calculation -MC12_wavr, // Resumes execution of interrupted WAV instruction -MC12_xgdx, // Exchange D with X -MC12_xgdy, // Exchange D with Y - -// Pseudoinstructions -MC12_skip1, // Skip one byte -MC12_skip2, // Skip two bytes - -//hcs12x only instructions, 16-bit unless indicated -MC12X_addx, // Add without Carry to X -MC12X_addy, // Add without Carry to Y -MC12X_aded, // Add with Carry to D(A:B) -MC12X_adex, // Add with Carry to X -MC12X_adey, // Add with Carry to Y -MC12X_andx, // Logical AND X with Memory -MC12X_andy, // Logical AND Y with Memory -MC12X_aslw, // Arithmetic Shift Left -MC12X_aslx, // Arithmetic Shift Left X -MC12X_asly, // Arithmetic Shift Left Y -MC12X_asrw, // Arithmetic Shift Right -MC12X_asrx, // Arithmetic Shift Right X -MC12X_asry, // Arithmetic Shift Right Y -MC12X_bitx, // Logical AND X with Memory, does not change X or Memory -MC12X_bity, // Logical AND Y with Memory, does not change Y or Memory -MC12X_btas, // Bit(s) test and Set in Memory, Set CCR flags -MC12X_clrw, // Clear Memory Location -MC12X_clrx, // Clear X -MC12X_clry, // Clear Y -MC12X_comw, // One's Complement Memory -MC12X_comx, // One's Complement X -MC12X_comy, // One's Complement Y -MC12X_cped, // Compare D to Memory with Borrow -MC12X_cpes, // Compare SP to Memory with Borrow -MC12X_cpex, // Compare X to Memory with Borrow -MC12X_cpey, // Compare Y to Memory with Borrow -MC12X_decw, // Decrement Memory -MC12X_decx, // Decrement X -MC12X_decy, // Decrement Y -MC12X_eorx, // Exclusive OR X with Memory -MC12X_eory, // Exclusive OR Y with Memory -MC12X_gldaa, // Load A from Global Memory (8-bit) -MC12X_gldab, // Load B from Global Memory (8-bit) -MC12X_gldd, // Load D(A:B) from Global Memory -MC12X_glds, // Load SP from Global Memory -MC12X_gldx, // Load X from Global Memory -MC12X_gldy, // Load Y from Global Memory -MC12X_gstaa, // Store A to Global Memory (8-bit) -MC12X_gstab, // Store B to Global Memory (8-bit) -MC12X_gstd, // Store D(A:B) to Global Memory -MC12X_gsts, // Store SP to Global Memory -MC12X_gstx, // Store X to Global Memory -MC12X_gsty, // Store Y to Global Memory -MC12X_incw, // Increment Memory -MC12X_incx, // Increment X -MC12X_incy, // Increment Y -MC12X_lsrw, // Logical Shift Memory to Right -MC12X_lsrx, // Logical Shift X to Right -MC12X_lsry, // Logical Shift Y to Right -MC12X_negw, // Two's Complement Memory -MC12X_negx, // Two's Complement X -MC12X_negy, // Two's Complement Y -MC12X_orx, // Logical OR X with memory -MC12X_ory, // Logical OR Y with memory -MC12X_pshcw, // Push CCR onto Stack (16-bit) -MC12X_pulcw, // Pull CCR from Stack (16-bit) -MC12X_rolw, // Rotate Memory Left through Carry -MC12X_rolx, // Rotate X Left through Carry -MC12X_roly, // Rotate Y Left through Carry -MC12X_rorw, // Rotate Memory Right through Carry -MC12X_rorx, // Rotate X Right through Carry -MC12X_rory, // Rotate Y Right through Carry -MC12X_sbed, // Subtract with Borrow from D -MC12X_sbex, // Subtract with Borrow from X -MC12X_sbey, // Subtract with Borrow from Y -MC12X_subx, // Subtract Memory from X -MC12X_suby, // Subtract Memory from Y -MC12X_tstw, // Test Memory for Zero or Minus -MC12X_tstx, // Test X for Zero or Minus -MC12X_tsty, // Test Y for Zero or Minus - -//hcs12x V2 cpu only instructions -MC12X_sys, // System call interrupt - -//hcs12x XGATE co-processor instructions -MC12XGATE_adc, // Add with Carry -MC12XGATE_add, // Add without Carry -MC12XGATE_addh, // Add Immediate 8 bit Constant (High Byte) -MC12XGATE_addl, // Add Immediate 8 bit Constant (Low Byte) -MC12XGATE_and, // Logical AND -MC12XGATE_andh, // Logical AND Immediate 8 bit Constant (High Byte) -MC12XGATE_andl, // Logical AND Immediate 8 bit Constant (Low Byte) -MC12XGATE_asr, // Arithmetic Shift Right -MC12XGATE_bcc, // Branch if Carry Cleared (Same as BHS) -MC12XGATE_bcs, // Branch if Carry Set (Same as BLO) -MC12XGATE_beq, // Branch if Equal -MC12XGATE_bfext, // Bit Field Extract -MC12XGATE_bffo, // Bit Field Find First One -MC12XGATE_bfins, // Bit Field Insert -MC12XGATE_bfinsi, // Bit Field Insert and Invert -MC12XGATE_bfinsx, // Bit Field Insert and XNOR -MC12XGATE_bge, // Branch if Greater than or Equal to Zero -MC12XGATE_bgt, // Branch if Greater than Zero -MC12XGATE_bhi, // Branch if Higher -MC12XGATE_bhs, // Branch if Higher or Same (Same as BCC) -MC12XGATE_bith, // Bit Test Immediate 8 bit Constant (High Byte) -MC12XGATE_bitl, // Bit Test Immediate 8 bit Constant (Low Byte) -MC12XGATE_ble, // Branch if Less or Equal to Zero -MC12XGATE_blo, // Branch if Carry Set (Same as BCS) -MC12XGATE_bls, // Branch if Lower or Same -MC12XGATE_blt, // Branch if Lower than Zero -MC12XGATE_bmi, // Branch if Minus -MC12XGATE_bne, // Branch if Not Equal -MC12XGATE_bpl, // Branch if Plus -MC12XGATE_bra, // Branch Always -MC12XGATE_brk, // Break -MC12XGATE_bvc, // Branch if Overflow Cleared -MC12XGATE_bvs, // Branch if Overflow Set -MC12XGATE_cmp, // Compare -MC12XGATE_cmpl, // Compare Immediate 8 bit Constant (Low Byte) -MC12XGATE_com, // One's Complement -MC12XGATE_cpc, // Compare with Carry -MC12XGATE_cpch, // Compare Immediate 8 bit Constant with Carry(High Byte) -MC12XGATE_csem, // Clear Semaphore -MC12XGATE_csl, // Logical Shift Left with Carry -MC12XGATE_csr, // Logical Shift Right with Carry -MC12XGATE_jal, // Jump and Link -MC12XGATE_ldb, // Load Byte from Memory (Low Byte) -MC12XGATE_ldh, // Load Immediate 8 bit Constant (High Byte) -MC12XGATE_ldl, // Load Immediate 8 bit Constant (Low Byte) -MC12XGATE_ldw, // Load Word from Memory -MC12XGATE_lsl, // Logical Shift Left -MC12XGATE_lsr, // Logical Shift Right -MC12XGATE_mov, // Move Register Content -MC12XGATE_neg, // Two's Complement -MC12XGATE_nop, // No Operation -MC12XGATE_or, // Logical OR -MC12XGATE_orh, // Logical OR Immediate 8 bit Constant (High Byte) -MC12XGATE_orl, // Logical OR Immediate 8 bit Constant (Low Byte) -MC12XGATE_par, // Calculate Parity -MC12XGATE_rol, // Rotate Left -MC12XGATE_ror, // Rotate Right -MC12XGATE_rts, // Return to Scheduler -MC12XGATE_sbc, // Subtract with Carry -MC12XGATE_sex, // Sign Extend Byte to Word -MC12XGATE_sif, // Set Interrupt Flag -MC12XGATE_ssem, // Set Semaphore -MC12XGATE_stb, // Store Byte to Memory (Low Byte) -MC12XGATE_stw, // Store Word to Memory -MC12XGATE_sub, // Subtract without Carry -MC12XGATE_subh, // Subtract Immediate 8 bit Constant (High Byte) -MC12XGATE_subl, // Subtract Immediate 8 bit Constant (Low Byte) -MC12XGATE_tfr, // Transfer from and to Special Registers -MC12XGATE_tst, // Test Register -MC12XGATE_xnor, // Logical Exclusive NOR -MC12XGATE_xnorh, // Logical Exclusive NOR Immediate 8 bit Constant (High Byte) -MC12XGATE_xnorl, // Logical Exclusive NOR Immediate 8 bit Constant (Low Byte) - -//Pseudo instructions that combine two IMM8 into IMM16 -MC12XGATE_add16, // Add Immediate 16 bit Constant -MC12XGATE_and16, // Logical AND Immediate 16 bit Constant -MC12XGATE_cmp16, // Compare Immediate 16 bit Constant -MC12XGATE_ldw16, // Load Immediate 16 bit Constant -MC12XGATE_or16, // Logical OR Immediate 16 bit Constant -MC12XGATE_sub16, // Subtract Immediate 16 bit Constant -MC12XGATE_xnor16, // Logical Exclusive NOR Immediate 16 bit Constant - -MC12_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - - MC6816_null = 0, // Unknown Operation - - // DATA MOVEMENT INSTRUCTIONS - // -------------------------- - - // LOAD INSTRUCTIONS - MC6816_ldaa, // Load A - MC6816_ldab, // Load B - MC6816_ldd, // Load D - MC6816_lde, // Load E - MC6816_lded, // Load Concatenated D and E - - // MOVE INSTRUCTIONS - MC6816_movb, // Move Byte - MC6816_movw, // Move Word - - // STORE INSTRUCTIONS - MC6816_staa, // Store A - MC6816_stab, // Store B - MC6816_std, // Store D - MC6816_ste, // Store E - MC6816_sted, // Store Concatenated D and E - - // TRANSFER INSTRUCTIONS - MC6816_tab, // Transfer A to B - MC6816_tba, // Transfer B to A - MC6816_tde, // Transfer D to E - MC6816_ted, // Transfer E to D - - // EXCHANGE INSTRUCTIONS - MC6816_xgab, // Exchange A with B - MC6816_xgde, // Exchange D with E - - // MATHEMATIC INSTRUCTIONS - // ----------------------- - - // ADDITION AND SUBSTRACTION INSTRUCTIONS - MC6816_aba, // Add B to A - MC6816_adca, // Add with Carry to A - MC6816_adcb, // Add with Carry to B - MC6816_adcd, // Add with Carry to D - MC6816_adce, // Add with Carry to E - MC6816_adda, // Add to A - MC6816_addb, // Add to B - MC6816_addd, // Add to D - MC6816_adde, // Add to E - MC6816_ade, // Add D to E - MC6816_sba, // Subtract B from A - MC6816_sbca, // Subtract with Carry from A - MC6816_sbcb, // Subtract with Carry from B - MC6816_sbcd, // Subtract with Carry from D - MC6816_sbce, // Subtract with Carry from E - MC6816_sde, // Subtract D from E - MC6816_suba, // Subtract from A - MC6816_subb, // Subtract from B - MC6816_subd, // Subtract from D - MC6816_sube, // Subtract from E - - // BINARY CODED DECIMAL INSTRUCTIONS - MC6816_daa, // Decimal Adjust A - MC6816_sxt, // Sign Extend B into A - - // COMPARE AND TEST INSTRUCTIONS - MC6816_cba, // Compare A to B - MC6816_cmpa, // Compare A to Memory - MC6816_cmpb, // Compare B to Memory - MC6816_cpd, // Compare D to Memory - MC6816_cpe, // Compare E to Memory - MC6816_tst, // Test for Zero or Minus - MC6816_tsta, // Test A for Zero or Minus - MC6816_tstb, // Test B for Zero or Minus - MC6816_tstd, // Test D for Zero or Minus - MC6816_tste, // Test E for Zero or Minus - MC6816_tstw, // Test for Zero or Minus Word - - // MULTIPLICATION AND DIVISION INSTRUCTIONS - MC6816_ediv, // Extended Unsigned Divide - MC6816_edivs, // Extended Signed Divide - MC6816_emul, // Extended Unsigned Multiply - MC6816_emuls, // Extended Signed Multiply - MC6816_fdiv, // Unsigned Fractional Divide - MC6816_fmuls, // Signed Fractional Multiply - MC6816_idiv, // Integer Divide - MC6816_mul, // Multiply - - // DECREMENT AND INCREMENT INSTRUCTIONS - MC6816_dec, // Decrement Memory - MC6816_deca, // Decrement A - MC6816_decb, // Decrement B - MC6816_decw, // Decrement Memory Word - MC6816_inc, // Increment Memory - MC6816_inca, // Increment A - MC6816_incb, // Increment B - MC6816_incw, // Increment Memory Word - - // CLEAR, COMPLEMENT, AND NEGATE INSTRUCTIONS - MC6816_clr, // Clear Memory - MC6816_clra, // Clear A - MC6816_clrb, // Clear B - MC6816_clrd, // Clear D - MC6816_clre, // Clear E - MC6816_clrw, // Clear Memory Word - MC6816_com, // One's Complement Byte - MC6816_coma, // One's Complement A - MC6816_comb, // One's Complement B - MC6816_comd, // One's Complement D - MC6816_come, // One's Complement E - MC6816_comw, // One's Complement Word - MC6816_neg, // Two's Complement Byte - MC6816_nega, // Two's Complement A - MC6816_negb, // Two's Complement B - MC6816_negd, // Two's Complement D - MC6816_nege, // Two's Complement E - MC6816_negw, // Two's Complement Word - - // BOOLEAN LOGIC INSTRUCTIONS - MC6816_anda, // AND A - MC6816_andb, // AND B - MC6816_andd, // AND D - MC6816_ande, // AND E - MC6816_eora, // Exclusive OR A - MC6816_eorb, // Exclusive OR B - MC6816_eord, // Exclusive OR D - MC6816_eore, // Exclusive OR E - MC6816_oraa, // OR A - MC6816_orab, // OR B - MC6816_ord, // OR D - MC6816_ore, // OR E - - // BIT TEST AND MANIPULATION INSTRUCTIONS - // -------------------------------------- - MC6816_bita, // Bit Test A - MC6816_bitb, // Bit Test B - MC6816_bclr, // Clear Bit(s) - MC6816_bclrw, // Clear Bit(s) Word - MC6816_bset, // Set Bit(s) - MC6816_bsetw, // Set Bit(s) Word - - // SHIFT AND ROTATE INSTRUCTIONS - // ----------------------------- - MC6816_lsr, // Logic Shift Right - MC6816_lsra, // Logic Shift Right A - MC6816_lsrb, // Logic Shift Right B - MC6816_lsrd, // Logic Shift Right D - MC6816_lsre, // Logic Shift Right E - MC6816_lsrw, // Logic Shift Right Word - MC6816_asl, // Arithmetic Shift Left - MC6816_asla, // Arithmetic Shift Left A - MC6816_aslb, // Arithmetic Shift Left B - MC6816_asld, // Arithmetic Shift Left D - MC6816_asle, // Arithmetic Shift Left E - MC6816_aslw, // Arithmetic Shift Left Word - MC6816_asr, // Arithmetic Shift Right - MC6816_asra, // Arithmetic Shift Right A - MC6816_asrb, // Arithmetic Shift Right B - MC6816_asrd, // Arithmetic Shift Right D - MC6816_asre, // Arithmetic Shift Right E - MC6816_asrw, // Arithmetic Shift Right Word - MC6816_rol, // Rotate Left - MC6816_rola, // Rotate Left A - MC6816_rolb, // Rotate Left B - MC6816_rold, // Rotate Left D - MC6816_role, // Rotate Left E - MC6816_rolw, // Rotate Left Word - MC6816_ror, // Rotate Right - MC6816_rora, // Rotate Right A - MC6816_rorb, // Rotate Right B - MC6816_rord, // Rotate Right D - MC6816_rore, // Rotate Right E - MC6816_rorw, // Rotate Right Word - - // PROGRAM CONTROL INSTRUCTIONS - // ---------------------------- - - // SHORT BRANCH INSTRUCTIONS - MC6816_bra, // Branch Always - MC6816_brn, // Branch Never - MC6816_bcc, // Branch If Carry Clear - MC6816_bcs, // Branch If Carry Set - MC6816_beq, // Branch If Equal to Zero - MC6816_bmi, // Branch If Minus - MC6816_bne, // Branch If Not Equal to Zero - MC6816_bpl, // Branch If Plus - MC6816_bvc, // Branch If Overflow Clear - MC6816_bvs, // Branch If Overflow Set - MC6816_bhi, // Branch If Higher - MC6816_bls, // Branch If Lower or Same - MC6816_bge, // Branch If Greater than or Equal to Zero - MC6816_bgt, // Branch If Greater than Zero - MC6816_ble, // Branch If Less than or Equal to Zero - MC6816_blt, // Branch If Less than Zero - - // LONG BRANCH INSTRUCTIONS - MC6816_lbra, // Long Branch Always - MC6816_lbrn, // Long Branch Never - MC6816_lbcc, // Long Branch If Carry Clear - MC6816_lbcs, // Long Branch If Carry Set - MC6816_lbeq, // Long Branch If Equal to Zero - MC6816_lbev, // Long Branch If EV Set - MC6816_lbmi, // Long Branch If Minus - MC6816_lbmv, // Long Branch If MV Set - MC6816_lbne, // Long Branch If Not Equal to Zero - MC6816_lbpl, // Long Branch If Plus - MC6816_lbvc, // Long Branch If Overflow Clear - MC6816_lbvs, // Long Branch If Overflow Set - MC6816_lbhi, // Long Branch If Higher - MC6816_lbls, // Long Branch If Lower or Same - MC6816_lbge, // Long Branch If Greater than or Equal to Zero - MC6816_lbgt, // Long Branch If Greater than Zero - MC6816_lble, // Long Branch If Less than or Equal to Zero - MC6816_lblt, // Long Branch If Less than Zero - - // BIT CONDITION BRANCH INSTRUCTIONS - MC6816_brclr, // Branch if Bits Clear - MC6816_brset, // Branch if Bits Set - - // JUMP INSTRUCTION - MC6816_jmp, // Jump - - // SUBROUTINE INSTRUCTIONS - MC6816_bsr, // Branch to Subroutine - MC6816_jsr, // Jump to Subroutine - MC6816_lbsr, // Long Branch to Subroutine - MC6816_rts, // Return From Subroutine - - // INTERRUPT INSTRUCTIONS - MC6816_rti, // Return from Interrupt - MC6816_swi, // Software Interrupt - - // INDEXING AND ADDRESS EXTENSION INSTRUCTIONS - // ------------------------------------------- - - // INDEXING INSTRUCTIONS - MC6816_abx, // Add B to IX - MC6816_aby, // Add B to IY - MC6816_abz, // Add B to IZ - MC6816_adx, // Add D to IX - MC6816_ady, // Add D to IY - MC6816_adz, // Add D to IZ - MC6816_aex, // Add E to IX - MC6816_aey, // Add E to IY - MC6816_aez, // Add E to IZ - MC6816_aix, // Add Immediate Value to IX - MC6816_aiy, // Add Immediate Value to IY - MC6816_aiz, // Add Immediate Value to IZ - MC6816_cpx, // Compare IX to Memory - MC6816_cpy, // Compare IY to Memory - MC6816_cpz, // Compare IZ to Memory - MC6816_ldx, // Load IX - MC6816_ldy, // Load IY - MC6816_ldz, // Load IZ - MC6816_stx, // Store IX - MC6816_sty, // Store IY - MC6816_stz, // Store IZ - MC6816_tsx, // Transfer SP to IX - MC6816_tsy, // Transfer SP to IY - MC6816_tsz, // Transfer SP to IZ - MC6816_txs, // Transfer IX to SP - MC6816_txy, // Transfer IX to IY - MC6816_txz, // Transfer IX to IZ - MC6816_tys, // Transfer IY to SP - MC6816_tyx, // Transfer IY to IX - MC6816_tyz, // Transfer IY to IZ - MC6816_tzs, // Transfer IZ to SP - MC6816_tzx, // Transfer IZ to IX - MC6816_tzy, // Transfer IZ to IY - MC6816_xgdx, // Exchange D with IX - MC6816_xgdy, // Exchange D with IY - MC6816_xgdz, // Exchange D with IZ - MC6816_xgex, // Exchange E with IX - MC6816_xgey, // Exchange E with IY - MC6816_xgez, // Exchange E with IZ - - // ADDRESS EXTENSION INSTRUCTIONS - MC6816_tbek, // Transfer B to EK - MC6816_tbsk, // Transfer B to SK - MC6816_tbxk, // Transfer B to XK - MC6816_tbyk, // Transfer B to YK - MC6816_tbzk, // Transfer B to ZK - MC6816_tekb, // Transfer EK to B - MC6816_tskb, // Transfer SK to B - MC6816_txkb, // Transfer XK to B - MC6816_tykb, // Transfer YK to B - MC6816_tzkb, // Transfer ZK to B - - // STACKING INSTRUCTIONS - // --------------------- - MC6816_ais, // Add Immediate Data to SP - MC6816_cps, // Compare SP to Memory - MC6816_lds, // Load SP - MC6816_sts, // Store SP - MC6816_psha, // Push A - MC6816_pshb, // Push B - MC6816_pshm, // Push Multiple Registers - MC6816_pula, // Pull A - MC6816_pulb, // Pull B - MC6816_pulm, // Pull Multiple Registers - - // CONDITION CODE INSTRUCTIONS - // --------------------------- - MC6816_andp, // AND CCR - MC6816_orp, // OR CCR - MC6816_tap, // Transfer A to CCR - MC6816_tdp, // Transfer D to CCR - MC6816_tpa, // Transfer CCR MSB to A - MC6816_tpd, // Transfer CCR to D - - // DIGITAL SIGNAL PROCESSING INSTRUCTIONS - // -------------------------------------- - MC6816_ace, // Add E to AM[31:15] - MC6816_aced, // Add concatenated E and D to AM - MC6816_aslm, // Arithmetic Shift Left AM - MC6816_asrm, // Arithmetic Shift Right AM - MC6816_clrm, // Clear AM - MC6816_ldhi, // Initialize HR and IR - MC6816_mac, // Multiply and Accumulate - MC6816_pshmac, // Push MAC State - MC6816_pulmac, // Pull MAC State - MC6816_rmac, // Repeating Multiply and Accumulate - MC6816_tdmsk, // Transfer D to XMSK:YMSK - MC6816_tedm, // Transfer E and T to AM[31:0] - MC6816_tem, // Transfer E to AM[31:16] - MC6816_tmer, // Transfer AM to E Rounded - MC6816_tmet, // Transfer AM to E Truncated - MC6816_tmxed, // Transfer AM t IX:E:D - - // STOP AND WAIT INSTRUCTIONS - // -------------------------- - MC6816_lpstop, // Low Power Stop - MC6816_wai, // Wait for Interrupt - - // BACKGROUND MODE AND NULL OPERATIONS - // ----------------------------------- - MC6816_bgnd, // Enter Background Debugging Mode - MC6816_nop, // Null operation - - MC6816_last -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -I960_null = 0, // Unknown Operation - -I960_addc, // Add ordinal with carry -I960_addi, // Add integer -I960_addo, // Add ordinal -I960_alterbit, // Alter bit -I960_and, // Src2 AND src1 -I960_andnot, // Src2 AND (NOT src1) -I960_atadd, // Atomic add -I960_atmod, // Atomic modify -I960_b, // Branch -I960_bal, // Branch and Link -I960_balx, // Branch and Link Extended -I960_bbc, // Check bit and branch if clear -I960_bbs, // Check bit and branch if set -I960_bno, // Branch if unordered/false -I960_bg, // Branch if greater -I960_be, // Branch if equal/true -I960_bge, // Branch if greater or equal -I960_bl, // Branch if less -I960_bne, // Branch if not equal -I960_ble, // Branch if less or equal -I960_bo, // Branch if ordered -I960_bx, // Branch Extended -I960_call, // Call -I960_calls, // Call system -I960_callx, // Call extended -I960_chkbit, // Check bit -I960_clrbit, // Clear bit -I960_cmpdeci, // Compare and decrement integer -I960_cmpdeco, // Compare and decrement ordinal -I960_cmpi, // Compare integer -I960_cmpibno, // Compare integer and branch if unordered -I960_cmpibg, // Compare integer and branch if greater -I960_cmpibe, // Compare integer and branch if equal -I960_cmpibge, // Compare integer and branch if greater or equal -I960_cmpibl, // Compare integer and branch if less -I960_cmpibne, // Compare integer and branch if not equal -I960_cmpible, // Compare integer and branch if less or equal -I960_cmpibo, // Compare integer and branch if ordered -I960_cmpinci, // Compare and increment integer -I960_cmpinco, // Compare and increment ordinal -I960_cmpo, // Compare ordinal -I960_cmpobg, // Compare ordinal and branch if greater -I960_cmpobe, // Compare ordinal and branch if equal -I960_cmpobge, // Compare ordinal and branch if greater or equal -I960_cmpobl, // Compare ordinal and branch if less -I960_cmpobne, // Compare ordinal and branch if not equal -I960_cmpoble, // Compare ordinal and branch if less or equal -I960_concmpi, // Conditional compare integer -I960_concmpo, // Conditional compare ordinal -I960_divi, // Divide integer -I960_divo, // Divide ordinal -I960_ediv, // Extended divide -I960_emul, // Extended multiply -I960_eshro, // Extended shift right ordinal -I960_extract, // Extract -I960_faultno, // Fault if unordered -I960_faultg, // Fault if greater -I960_faulte, // Fault if equal -I960_faultge, // Fault if greater or equal -I960_faultl, // Fault if less -I960_faultne, // Fault if not equal -I960_faultle, // Fault if less or equal -I960_faulto, // Fault if ordered -I960_flushreg, // Flush cached local register sets to memory -I960_fmark, // Force mark -I960_ld, // Load word -I960_lda, // Load address -I960_ldib, // Load integer byte -I960_ldis, // Load integer short -I960_ldl, // Load long -I960_ldob, // Load ordinal byte -I960_ldos, // Load ordinal short -I960_ldq, // Load quad -I960_ldt, // Load triple -I960_mark, // Mark -I960_modac, // Modify the AC register -I960_modi, // Modulo integer -I960_modify, // Modify -I960_modpc, // Modify the process controls register -I960_modtc, // Modify trace controls -I960_mov, // Move word -I960_movl, // Move long word -I960_movq, // Move quad word -I960_movt, // Move triple word -I960_muli, // Multiply integer -I960_mulo, // Multiply ordinal -I960_nand, // NOT (src2 AND src1) -I960_nor, // NOT (src2 OR src1) -I960_not, // NOT src1 -I960_notand, // (NOT src2) AND src1 -I960_notbit, // Not bit -I960_notor, // (NOT src2) or src1 -I960_or, // Src2 OR src1 -I960_ornot, // Src2 or (NOT src1) -I960_remi, // Remainder integer -I960_remo, // Remainder ordinal -I960_ret, // Return -I960_rotate, // Rotate left -I960_scanbit, // Scan for bit -I960_scanbyte, // Scan byte equal -I960_setbit, // Set bit -I960_shli, // Shift left integer -I960_shlo, // Shift left ordinal -I960_shrdi, // Shift right dividing integer -I960_shri, // Shift right integer -I960_shro, // Shift right ordinal -I960_spanbit, // Span over bit -I960_st, // Store word -I960_stib, // Store integer byte -I960_stis, // Store integer short -I960_stl, // Store long -I960_stob, // Store ordinal byte -I960_stos, // Store ordinal short -I960_stq, // Store quad -I960_stt, // Store triple -I960_subc, // Subtract ordinal with carry -I960_subi, // Subtract integer -I960_subo, // Subtract ordinal -I960_syncf, // Synchronize faults -I960_testno, // Test for unordered -I960_testg, // Test for greater -I960_teste, // Test for equal -I960_testge, // Test for greater or equal -I960_testl, // Test for less -I960_testne, // Test for not equal -I960_testle, // Test for less or equal -I960_testo, // Test for ordered -I960_xnor, // Src2 XNOR src1 -I960_xor, // Src2 XOR src1 - -// Cx instructions - -I960_sdma, // Set up a DMA controller channel -I960_sysctl, // Perform system control function -I960_udma, // Copy current DMA pointers to internal data RAM - -// Unknown instructions - -I960_dcinva, -I960_cmpob, -I960_cmpib, -I960_cmpos, -I960_cmpis, -I960_bswap, -I960_intdis, -I960_inten, -I960_synmov, -I960_synmovl, -I960_synmovq, -I960_cmpstr, -I960_movqstr, -I960_movstr, -I960_inspacc, -I960_ldphy, -I960_synld, -I960_fill, -I960_daddc, -I960_dsubc, -I960_dmovt, -I960_condrec, -I960_receive, -I960_intctl, -I960_icctl, -I960_dcctl, -I960_halt, -I960_send, -I960_sendserv, -I960_resumprcs, -I960_schedprcs, -I960_saveprcs, -I960_condwait, -I960_wait, -I960_signal, -I960_ldtime, -I960_addono, -I960_addino, -I960_subono, -I960_subino, -I960_selno, -I960_addog, -I960_addig, -I960_subog, -I960_subig, -I960_selg, -I960_addoe, -I960_addie, -I960_suboe, -I960_subie, -I960_sele, -I960_addoge, -I960_addige, -I960_suboge, -I960_subige, -I960_selge, -I960_addol, -I960_addil, -I960_subol, -I960_subil, -I960_sell, -I960_addone, -I960_addine, -I960_subone, -I960_subine, -I960_selne, -I960_addole, -I960_addile, -I960_subole, -I960_subile, -I960_selle, -I960_addoo, -I960_addio, -I960_suboo, -I960_subio, -I960_selo, - -// Floating point instructions - -I960_faddr, I960_fp_first = I960_faddr, -I960_faddrl, -I960_fatanr, -I960_fatanrl, -I960_fclassr, -I960_fclassrl, -I960_fcmpor, -I960_fcmporl, -I960_fcmpr, -I960_fcmprl, -I960_fcosr, -I960_fcosrl, -I960_fcpyrsre, -I960_fcpysre, -I960_fcvtilr, -I960_fcvtir, -I960_fcvtri, -I960_fcvtril, -I960_fcvtzri, -I960_fcvtzril, -I960_fdivr, -I960_fdivrl, -I960_fexpr, -I960_fexprl, -I960_flogbnr, -I960_flogbnrl, -I960_flogepr, -I960_flogeprl, -I960_flogr, -I960_flogrl, -I960_fmovr, -I960_fmovre, -I960_fmovrl, -I960_fmulr, -I960_fmulrl, -I960_fremr, -I960_fremrl, -I960_froundr, -I960_froundrl, -I960_fscaler, -I960_fscalerl, -I960_fsinr, -I960_fsinrl, -I960_fsqrtr, -I960_fsqrtrl, -I960_fsubr, -I960_fsubrl, -I960_ftanr, -I960_ftanrl, I960_fp_last = I960_ftanrl, - -I960_last, - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -F2MC_null = 0, // Unknown Operation - -// TRANSFER INSTRUCTIONS - -F2MC_mov, // Move byte data from source to destination -F2MC_movn, // Move immediate nibble data to A -F2MC_movx, // Move byte data with sign extension from source to A -F2MC_xch, // Exchange byte data of source to destination -F2MC_movw, // Move word data from source to destination -F2MC_xchw, // Exchange word data of source to destination -F2MC_movl, // Move long word data from source to destination - -// NUMERIC DATA OPERATIONS INSTRUCTIONS - -F2MC_add, // Add byte data of destination and source to destination -F2MC_addc1, // Add byte data of AL and AH with Carry to AL -F2MC_addc2, // Add byte data of A and effective address with Carry to A -F2MC_adddc, // Add decimal data of AL and AH with Carry to AL -F2MC_sub, // Subtract byte data of source from festination to destination -F2MC_subc1, // Subtract byte data of AL from AH with Carry to AL -F2MC_subc2, // Subtract byte data of effective address from A with Carry to A -F2MC_subdc, // Subtract decimal data of AL from AH with Carry to AL -F2MC_addw1, // Add word data of AH and AL to AL -F2MC_addw2, // Add word data of destination and source to destination -F2MC_addcw, // Add word data of A and effective address from A with Carry to A -F2MC_subw1, // Subtract word data of AL from AH to AL -F2MC_subw2, // Subtract word data of source from festination to destination -F2MC_subcw, // Subtract word data of A and effective address from A with carry to A -F2MC_addl, // Add long word data of destination and source to destination -F2MC_subl, // Subtract long word data of source from festination to destination -F2MC_inc, // Increment byte data -F2MC_dec, // Decrement byte data -F2MC_incw, // Increment word data -F2MC_decw, // Decrement word data -F2MC_incl, // Increment long word data -F2MC_decl, // Decrement long word data -F2MC_cmp1, // Compare byte data of AH and AL -F2MC_cmp2, // Compare byte data of destination and source -F2MC_cmpw1, // Compare word data of AH and AL -F2MC_cmpw2, // Compare word data of destination and source -F2MC_cmpl, // Compare long word data of destination and source -F2MC_divu1, // Divide unsigned AH by AL -F2MC_divu2, // Divide unsigned word data by unsigned byte data -F2MC_divuw, // Divide unsigned long word data by unsigned word data -F2MC_mulu1, // Multiply unsigned byte AH by AL -F2MC_mulu2, // Multiply unsigned byte data -F2MC_muluw1, // Multiply unsigned word AH by AL -F2MC_muluw2, // Multiply unsigned word data -F2MC_div1, // Divide AH by AL -F2MC_div2, // Divide word data by byte data -F2MC_divw, // Divide long word data by word data -F2MC_mul1, // Multiply byte AH by AL -F2MC_mul2, // Multiply byte data -F2MC_mulw1, // Multiply word AH by AL -F2MC_mulw2, // Multiply word data - -// LOGICAL DATA OPERATION INSTRUCTIONS - -F2MC_and, // And byte data of destination and source to destination -F2MC_or, // Or byte data of destination and source to destination -F2MC_xor, // Exclusive or byte data of destination and source to destination -F2MC_not, // Not byte data of destination -F2MC_andw1, // And word data of AH and AL to AL -F2MC_andw2, // And word data of destination and source to destination -F2MC_orw1, // Or word data of AH and AL to AL -F2MC_orw2, // Or word data of destination and source to destination -F2MC_xorw1, // Exclusive or word data of AH and AL to AL -F2MC_xorw2, // Exclusive or word data of destination and source to destination -F2MC_notw, // Not word data of destination -F2MC_andl, // And long word data of destination and source to destination -F2MC_orl, // Or long word data of destination and source to destination -F2MC_xorl, // Exclusive or long word data of destination and source to destination -F2MC_neg, // Negate byte data of destination -F2MC_negw, // Negate word data of destination -F2MC_nrml, // Normalize long word - -// SHIFT INSTRUCTIONS - -F2MC_rorc, // Rotate byte data of A with Carry to right -F2MC_rolc, // Rotate byte data of A with Carry to left -F2MC_asr, // Arithmetic shift byte data of A to right -F2MC_lsr, // Logical shift byte data of A to right -F2MC_lsl, // Logical shift byte data of A to left -F2MC_asrw1, // Arithmetic shift word data of A to right -F2MC_asrw2, // Arithmetic shift word data of A to right -F2MC_lsrw1, // Logical shift word data of A to right -F2MC_lsrw2, // Logical shift word data of A to right -F2MC_lslw1, // Logical shift word data of A to left -F2MC_lslw2, // Logical shift word data of A to left -F2MC_asrl, // Arithmetic shift long word data of A to right -F2MC_lsrl, // Logical shift long word data of A to right -F2MC_lsll, // Logical shift long word data of A to left - -// BRANCH INSTRUCTIONS - -F2MC_bz, // Branch if Zero -F2MC_bnz, // Branch if Not Zero -F2MC_bc, // Branch if Carry -F2MC_bnc, // Branch if Not Carry -F2MC_bn, // Branch if Negative -F2MC_bp, // Branch if Not Negative -F2MC_bv, // Branch if Overflow -F2MC_bnv, // Branch if Not Overflow -F2MC_bt, // Branch if Sticky -F2MC_bnt, // Branch if Not Sticky -F2MC_blt, // Branch if Overflow or Negative -F2MC_bge, // Branch if Not (Overflow or Negative) -F2MC_ble, // Branch if (Overflow xor Negative) or Zero -F2MC_bgt, // Branch if Not ((Overflow xor Negative) or Zero) -F2MC_bls, // Branch if Carry or Zero -F2MC_bhi, // Branch if Not (Carry or Zero) -F2MC_bra, // Branch unconditionally -F2MC_jmp, // Jump destination address -F2MC_jmpp, // Jump destination physical address -F2MC_call, // Call subroutine -F2MC_callv, // Call vectored subroutine -F2MC_callp, // Call physical address -F2MC_cbne, // Compare byte data and branch if not Equal -F2MC_cwbne, // Compare word data and branch if not Equal -F2MC_dbnz, // Decrement byte data and branch if not Zero -F2MC_dwbnz, // Decrement word data and branch if not Zero -F2MC_int, // Software interrupt -F2MC_intp, // Software interrupt -F2MC_int9, // Software interrupt -F2MC_reti, // Return from interrupt -F2MC_link, // Link and create new stack frame -F2MC_unlink, // Unlink and create new stack frame -F2MC_ret, // Return from subroutine -F2MC_retp, // Return from physical address - -// OTHER INSTRUCTIONS - -F2MC_pushw, // Push to stack memory -F2MC_popw, // Pop from stack memory -F2MC_jctx, // Jump context -// F2MC_and, -// F2MC_or, -// F2MC_mov, -F2MC_movea, // Move effective address to destination -F2MC_addsp, // Add word data of SP and immediate data to SP -// F2MC_mov, -F2MC_nop, // No operation -F2MC_adb, // ADB register -F2MC_dtb, // DTB register -F2MC_pcb, // PCB register -F2MC_spb, // SPB register -F2MC_ncc, // Flag change inhibit -F2MC_cmr, // Common register bank -F2MC_movb, // Move bit data -F2MC_setb, // Set bit -F2MC_clrb, // Clear bit -F2MC_bbc, // Branch if bit condition satisfied -F2MC_bbs, // Branch if bit condition satisfied -F2MC_sbbs, // Set bit and branch if bit set -F2MC_wbts, // Wait until bit condition satisfied -F2MC_wbtc, // Wait until bit condition satisfied -F2MC_swap, // Swap byte data of A -F2MC_swapw, // Swap word data of A -F2MC_ext, // Sign extend from byte data to word data -F2MC_extw, // Sign extend from word data to long word data -F2MC_zext, // Zero extendfrom byte data to word data -F2MC_zextw, // Zero extendfrom word data to long word data -F2MC_movsi, // Move string byte with addresses incremented -F2MC_movsd, // Move string byte with addresses decremented -F2MC_sceqi, // Scan string byte until Equal with address incremented -F2MC_sceqd, // Scan string byte until Equal with address decremented -F2MC_filsi, // Fill string byte -F2MC_movswi, // Move string word with address incremented -F2MC_movswd, // Move string word with address decremented -F2MC_scweqi, // Scan string word until Equal with address incremented -F2MC_scweqd, // Scan string word until Equal with address decremented -F2MC_filswi, // Fill string word - -// MACROS - -F2MC_bz16, // Branch if Zero -F2MC_bnz16, // Branch if Not Zero -F2MC_bc16, // Branch if Carry -F2MC_bnc16, // Branch if Not Carry -F2MC_bn16, // Branch if Negative -F2MC_bp16, // Branch if Not Negative -F2MC_bv16, // Branch if Overflow -F2MC_bnv16, // Branch if Not Overflow -F2MC_bt16, // Branch if Sticky -F2MC_bnt16, // Branch if Not Sticky -F2MC_blt16, // Branch if Overflow or Negative -F2MC_bge16, // Branch if Not (Overflow or Negative) -F2MC_ble16, // Branch if (Overflow xor Negative) or Zero -F2MC_bgt16, // Branch if Not ((Overflow xor Negative) or Zero) -F2MC_bls16, // Branch if Carry or Zero -F2MC_bhi16, // Branch if Not (Carry or Zero) - -F2MC_cbne16, // Compare byte data and branch if not Equal -F2MC_cwbne16, // Compare word data and branch if not Equal - -F2MC_dbnz16, // Decrement byte data and branch if not Zero -F2MC_dwbnz16, // Decrement word data and branch if not Zero - -F2MC_bbc16, // Branch if bit condition satisfied -F2MC_bbs16, // Branch if bit condition satisfied -F2MC_sbbs16, // Set bit and branch if bit set - -F2MC_last, - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -TMS320C3X_null = 0, // Unknown Operation - -TMS320C3X_ABSF, // Absolute value of a floating-point number -TMS320C3X_ABSI, // Absolute value of an integer -TMS320C3X_ADDC, // Add integers with carry -TMS320C3X_ADDF, // Add Floating-Point Values -TMS320C3X_ADDI, // Add Integer -TMS320C3X_AND, // Bitwise-Logical AND -TMS320C3X_ANDN, // Bitwise-Logical AND With Complement -TMS320C3X_ASH, // Arithmetic Shift -TMS320C3X_CMPF, // Compare Floating-Point Value -TMS320C3X_CMPI, // Compare Integer -TMS320C3X_FIX, // Floating-Point-to-Integer Conversion -TMS320C3X_FLOAT, // Integer-to-Floating-Point Conversion -TMS320C3X_IDLE, // Idle Until Interrupt -TMS320C3X_IDLE2, // Low-Power Idle -TMS320C3X_LDE, // Load Floating-Point Exponent -TMS320C3X_LDF, // Load Floating-Point Value -TMS320C3X_LDFI, // Load Floating-Point Value, Interlocked -TMS320C3X_LDI, // Load Integer -TMS320C3X_LDII, // Load Integer, Interlocked -TMS320C3X_LDM, // Load Floating-Point Mantissa -TMS320C3X_LSH, // Logical Shift -TMS320C3X_MPYF, // Multiply Floating-Point Value -TMS320C3X_MPYI, // Multiply Integer -TMS320C3X_NEGB, // Negative Integer With Borrow -TMS320C3X_NEGF, // Negate Floating-Point Value -TMS320C3X_NEGI, // Negate Integer -TMS320C3X_NOP, // No Operation -TMS320C3X_NORM, // Normalize -TMS320C3X_NOT, // Bitwise-Logical Complement -TMS320C3X_POP, // Pop Integer -TMS320C3X_POPF, // Pop Floating-Point Value -TMS320C3X_PUSH, // PUSH Integer -TMS320C3X_PUSHF, // PUSH Floating-Point Value -TMS320C3X_OR, // Bitwise-Logical OR -TMS320C3X_LOPOWER, // Divide Clock by 16 -TMS320C3X_MAXSPEED, // Restore Clock to Regular Speed -TMS320C3X_RND, // Round Floating-Point Value -TMS320C3X_ROL, // Rotate Left -TMS320C3X_ROLC, // Rotate Left Through Carry -TMS320C3X_ROR, // Rotate Right -TMS320C3X_RORC, // Rotate Right Through Carry -TMS320C3X_RPTS, // Repeat Single Instruction -TMS320C3X_STF, // Store Floating-Point Value -TMS320C3X_STFI, // Store Floating-Point Value, Interlocked -TMS320C3X_STI, // Store Integer -TMS320C3X_STII, // Store Integer, Interlocked -TMS320C3X_SIGI, // Signal, Interlocked -TMS320C3X_SUBB, // Subtract Integer With Borrow -TMS320C3X_SUBC, // Subtract Integer Conditionally -TMS320C3X_SUBF, // Subtract Floating-Point Value -TMS320C3X_SUBI, // Subtract Integer -TMS320C3X_SUBRB, // Subtract Reverse Integer With Borrow -TMS320C3X_SUBRF, // Subtract Reverse Floating-Point Value -TMS320C3X_SUBRI, // Subtract Reverse Integer -TMS320C3X_TSTB, // Test Bit Fields -TMS320C3X_XOR, // Bitwise-Exclusive OR -TMS320C3X_IACK, // Interrupt acknowledge - -TMS320C3X_ADDC3, // Add integers with carry (3-operand) -TMS320C3X_ADDF3, // Add floating-point values (3-operand) -TMS320C3X_ADDI3, // Add integers (3 operand) -TMS320C3X_AND3, // Bitwise-logical AND (3-operand) -TMS320C3X_ANDN3, // Bitwise-logical ANDN (3-operand) -TMS320C3X_ASH3, // Arithmetic shift (3-operand) -TMS320C3X_CMPF3, // Compare floating-point values (3-operand) -TMS320C3X_CMPI3, // Compare integers (3-operand) -TMS320C3X_LSH3, // Logical shift (3-operand) -TMS320C3X_MPYF3, // Multiply floating-point value (3-operand) -TMS320C3X_MPYI3, // Multiply integers (3-operand) -TMS320C3X_OR3, // Bitwise-logical OR (3-operand) -TMS320C3X_SUBB3, // Subtract integers with borrow (3-operand) -TMS320C3X_SUBF3, // Subtract floating-point values (3-operand) -TMS320C3X_SUBI3, // Subtract integers (3-operand) -TMS320C3X_TSTB3, // Test Bit Fields, 3-Operand -TMS320C3X_XOR3, // Bitwise-Exclusive OR, 3-Operand - -TMS320C3X_LDFcond, // Load floating-point value conditionally -TMS320C3X_LDIcond, // Load integer conditionally -TMS320C3X_BR, // Branch unconditionally (standard) -TMS320C3X_BRD, // Branch unconditionally (delayed) -TMS320C3X_CALL, // Call subroutine -TMS320C3X_RPTB, // Repeat block of instructions -TMS320C3X_SWI, // Software Interrupt -TMS320C3X_Bcond, // Branch conditionally -TMS320C3X_DBcond, // Decrement and branch conditionally -TMS320C3X_CALLcond, // Call subroutine conditionally -TMS320C3X_TRAPcond, // Trap Conditionally -TMS320C3X_RETIcond, // Return from interrupt conditionally -TMS320C3X_RETScond, // Return from subroutine conditionally -TMS320C3X_RETIU, // Return from interrupt unconditionally -TMS320C3X_RETSU, // Return from subroutine unconditionally - -TMS320C3X_NONE, // Pseudo insn (more accurate definition need) -TMS320C3X_MV_IDX, // Pseudo insn (move to next index need) -TMS320C3X_last, // last ID - -}; - - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -TMS320C54_null = 0, // Unknown Operation - -// ARITHMETIC OPERATIONS - -// ADD INSTRUCTIONS - -TMS320C54_add1, // Add to Accumulator -TMS320C54_add2, // Add to Accumulator -TMS320C54_add3, // Add to Accumulator -TMS320C54_addc, // Add to Accumulator With Carry -TMS320C54_addm, // Add Long-Immediate Value to Memory -TMS320C54_adds, // Add to Accumulator With Sign-Extension Suppressed - -// SUBTRACT INSTRUCTIONS - -TMS320C54_sub1, // Sub From Accumulator -TMS320C54_sub2, // Sub From Accumulator -TMS320C54_sub3, // Sub From Accumulator -TMS320C54_subb, // Sub From Accumulator With Borrow -TMS320C54_subc, // Subtract Conditionally -TMS320C54_subs, // Subtract From Accumulator With Sign Extension Suppressed - -// MULTIPLY INSTRUCTIONS - -TMS320C54_mpy2, // Multiply Without Rounding -TMS320C54_mpy3, // Multiply Without Rounding -TMS320C54_mpyr2, // Multiply With Rounding -TMS320C54_mpya, // Multiply by Accumulator A -TMS320C54_mpyu, // Multiply Unsigned -TMS320C54_squr, // Square - -// MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS - -TMS320C54_mac2, // Multiply Accumulate Without Rounding -TMS320C54_mac3, // Multiply Accumulate Without Rounding -TMS320C54_macr2, // Multiply Accumulate With Rounding -TMS320C54_macr3, // Multiply Accumulate With Rounding -TMS320C54_maca1, // Multiply by Accumulator A and Accumulate Without Rounding -TMS320C54_maca2, // Multiply by Accumulator A and Accumulate Without Rounding -TMS320C54_maca3, // Multiply by Accumulator A and Accumulate Without Rounding -TMS320C54_macar1, // Multiply by Accumulator A and Accumulate With Rounding -TMS320C54_macar2, // Multiply by Accumulator A and Accumulate With Rounding -TMS320C54_macar3, // Multiply by Accumulator A and Accumulate With Rounding -TMS320C54_macd, // Multiply by Program Memory and Accumulate With Delay -TMS320C54_macp, // Multiply by Program Memory and Accumulate -TMS320C54_macsu, // Multiply Signed by Unsigned and Accumulate -TMS320C54_mas2, // Multiply and Subtract Without Rounding -TMS320C54_mas3, // Multiply and Subtract Without Rounding -TMS320C54_masr2, // Multiply and Subtract With Rounding -TMS320C54_masr3, // Multiply and Subtract With Rounding -//TMS320C54_mas, -TMS320C54_masa1, // Multiply by Accumulator A and Subtract Without Rounding -TMS320C54_masa2, // Multiply by Accumulator A and Subtract Without Rounding -TMS320C54_masa3, // Multiply by Accumulator A and Subtract Without Rounding -TMS320C54_masar1, // Multiply by Accumulator A and Subtract With Rounding -TMS320C54_masar2, // Multiply by Accumulator A and Subtract With Rounding -TMS320C54_masar3, // Multiply by Accumulator A and Subtract With Rounding -TMS320C54_squra, // Square and Accumulate -TMS320C54_squrs, // Square and Subtract - -// DOUBLE INSTRUCTIONS - -TMS320C54_dadd2, // Double-Precision/Dual 16-Bit Add to Accumulator -TMS320C54_dadd3, // Double-Precision/Dual 16-Bit Add to Accumulator -TMS320C54_dadst, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract -TMS320C54_drsub, // Double-Precision/Dual 16-Bit Subtract From Long Word -TMS320C54_dsadt, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add -TMS320C54_dsub, // Double-Precision/Dual 16-Bit Subtract From Accumulator -TMS320C54_dsubt, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract - -// APPLICATION-SPECIFIC INSTRUCTIONS - -TMS320C54_abdst, // Absolute distance -TMS320C54_abs1, // Absolute Value of Accumulator -TMS320C54_abs2, // Absolute Value of Accumulator -TMS320C54_cmpl1, // Complement Accumulator -TMS320C54_cmpl2, // Complement Accumulator -TMS320C54_delay, // Memory Delay -TMS320C54_exp, // Accumulator Exponent -TMS320C54_firs, // Symmetrical Finite Impulse Response Filter -TMS320C54_lms, // Least Mean Square -TMS320C54_max, // Accumulator Maximum -TMS320C54_min, // Accumulator Minimum -TMS320C54_neg1, // Negate Accumulator -TMS320C54_neg2, // Negate Accumulator -TMS320C54_norm1, // Normalization -TMS320C54_norm2, // Normalization -TMS320C54_poly, // Polynominal Evaluation -TMS320C54_rnd1, // Round Accumulator -TMS320C54_rnd2, // Round Accumulator -TMS320C54_sat, // Saturate Accumulator -TMS320C54_sqdst, // Square Distance - -// LOGICAL OPERATIONS - -// AND INSTRUCTIONS - -TMS320C54_and1, // AND With Accumulator -TMS320C54_and2, // AND With Accumulator -TMS320C54_and3, // AND With Accumulator -TMS320C54_andm, // AND Memory With Long Immediate - -// OR INSTRUCTIONS - -TMS320C54_or1, // OR With Accumulator -TMS320C54_or2, // OR With Accumulator -TMS320C54_or3, // OR With Accumulator -TMS320C54_orm, // OR Memory With Constant - -// XOR INSTRUCTIONS - -TMS320C54_xor1, // Exclusive OR With Accumulator -TMS320C54_xor2, // Exclusive OR With Accumulator -TMS320C54_xor3, // Exclusive OR With Accumulator -TMS320C54_xorm, // Exclusive OR Memory With Constant - -// SHIFT INSTRUCTIONS - -TMS320C54_rol, // Rotate Accumulator -TMS320C54_roltc, // Rotate Accumulator Left Using TC -TMS320C54_ror, // Rotate Accumulator Right -TMS320C54_sfta2, // Shift Accumulator Arithmetically -TMS320C54_sfta3, // Shift Accumulator Arithmetically -TMS320C54_sftc, // Shift Accumulator Conditionally -TMS320C54_sftl2, // Shift Accumulator Logically -TMS320C54_sftl3, // Shift Accumulator Logically - -// TEST INSTRUCTIONS - -TMS320C54_bit, // Test Bit -TMS320C54_bitf, // Test Bit Field Specified by Immediate Value -TMS320C54_bitt, // Test Bit Specified by T -TMS320C54_cmpm, // Compare Memory With Long Immediate -TMS320C54_cmpr, // Compare Auxiliary Register with AR0 - -// PROGRAM CONTROL OPERATIONS - -// BRANCH INSTRUCTIONS - -TMS320C54_b, // Branch Unconditionally -TMS320C54_bd, // Branch Unconditionally -TMS320C54_bacc, // Branch to Location Specified by Accumulator -TMS320C54_baccd, // Branch to Location Specified by Accumulator -TMS320C54_banz, // Branch on Auxiliary Register Not Zero -TMS320C54_banzd, // Branch on Auxiliary Register Not Zero -TMS320C54_bc2, // Branch Conditionally -TMS320C54_bc3, // Branch Conditionally -TMS320C54_bcd2, // Branch Conditionally -TMS320C54_bcd3, // Branch Conditionally -TMS320C54_fb, // Far Branch Unconditionally -TMS320C54_fbd, // Far Branch Unconditionally -TMS320C54_fbacc, // Far Branch to Location Specified by Accumulator -TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator - -// CALL INSTRUCTIONS - -TMS320C54_cala, // Call Subroutine at Location Specified by Accumulator -TMS320C54_calad, // Call Subroutine at Location Specified by Accumulator -TMS320C54_call, // Call Unconditionally -TMS320C54_calld, // Call Unconditionally -TMS320C54_cc2, // Call Conditionally -TMS320C54_cc3, // Call Conditionally -TMS320C54_ccd2, // Call Conditionally -TMS320C54_ccd3, // Call Conditionally -TMS320C54_fcala, // Far Call Subroutine at Location Specified by Accumulator -TMS320C54_fcalad, // Far Call Subroutine at Location Specified by Accumulator -TMS320C54_fcall, // Far Call Unconditionally -TMS320C54_fcalld, // Far Call Unconditionally - -// INTERRUPT INSTRUCTIONS - -TMS320C54_intr, // Software Interrupt -TMS320C54_trap, // Software Interrupt - -// RETURN INSTRUCTIONS - -TMS320C54_fret, // Far Return -TMS320C54_fretd, // Far Return -TMS320C54_frete, // Enable Interrupts and Far Return From Interrupt -TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt -TMS320C54_rc1, // Return Conditionally -TMS320C54_rc2, // Return Conditionally -TMS320C54_rc3, // Return Conditionally -TMS320C54_rcd1, // Return Conditionally -TMS320C54_rcd2, // Return Conditionally -TMS320C54_rcd3, // Return Conditionally -TMS320C54_ret, // Return -TMS320C54_retd, // Return -TMS320C54_rete, // Enable Interrupts and Return From Interrupt -TMS320C54_reted, // Enable Interrupts and Return From Interrupt -TMS320C54_retf, // Enable Interrupts and Fast Return From Interrupt -TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt - -// REPEAT INSTRUCTIONS - -TMS320C54_rpt, // Repeat Next Instruction -TMS320C54_rptb, // Block Repeat -TMS320C54_rptbd, // Block Repeat -TMS320C54_rptz, // Repeat Next Instruction And Clear Accumulator - -// STACK MANIPULATING INSTRUCTIONS - -TMS320C54_frame, // Stack Pointer Immediate Offset -TMS320C54_popd, // Pop Top of Stack to Data Memory -TMS320C54_popm, // Pop Top of Stack to Memory-Mapped Register -TMS320C54_pshd, // Push Data-Memory Value Onto Stack -TMS320C54_pshm, // Push Memory-Mapped Register Onto Stack - -// MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS - -TMS320C54_idle, // Idle Until Interrupt -TMS320C54_mar, // Modify Auxiliary Register -TMS320C54_nop, // No Operation -TMS320C54_reset, // Software Reset -TMS320C54_rsbx1, // Reset Status Register Bit -TMS320C54_rsbx2, // Reset Status Register Bit -TMS320C54_ssbx1, // Set Status Register Bit -TMS320C54_ssbx2, // Set Status Register Bit -TMS320C54_xc2, // Execute Conditionally -TMS320C54_xc3, // Execute Conditionally - -// LOAD AND STORE OPERATIONS - -// LOAD INSTRUCTIONS - -TMS320C54_dld, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator -TMS320C54_ld1, // Load Accumulator With Shift -TMS320C54_ld2, // Load Accumulator With Shift -TMS320C54_ld3, // Load Accumulator With Shift -TMS320C54_ldm, // Load Memory-Mapped Register -TMS320C54_ldr, // Load Memory Value in Accumulator High With Rounding -TMS320C54_ldu, // Load Unsigned Memory Value -TMS320C54_ltd, // Load T and insert Delay - -// STORE INSTRUCTIONS - -TMS320C54_dst, // Store Accumulator in Long Word -TMS320C54_st, // Store T, TRN, or Immediate Value into Memory -TMS320C54_sth2, // Store Accumulator High Into Memory -TMS320C54_sth3, // Store Accumulator High Into Memory -TMS320C54_stl2, // Store Accumulator Low Into Memory -TMS320C54_stl3, // Store Accumulator Low Into Memory -TMS320C54_stlm, // Store Accumulator Low Into Memory-Mapped Register -TMS320C54_stm, // Store Immediate Value Into Memory-Mapped Register - -// CONDITIONAL STORE INSTRUCTIONS - -TMS320C54_cmps, // Compare, Select and Store Maximum -TMS320C54_saccd, // Store Accumulator Conditionally -TMS320C54_srccd, // Store Block Repeat Counter Conditionally -TMS320C54_strcd, // Store T Conditionally - -// PARALLEL LOAD AND STORE INSTRUCTIONS - -TMS320C54_st_ld, // Store Accumulator With Parallel Load - -// PARALLEL LOAD AND MULTIPLY INSTRUCTIONS - -TMS320C54_ld_mac, // Load Accumulator With Parallel Multiply Accumulate Without Rounding -TMS320C54_ld_macr, // Load Accumulator With Parallel Multiply Accumulate With Rounding -TMS320C54_ld_mas, // Load Accumulator With Parallel Multiply Subtract Without Rounding -TMS320C54_ld_masr, // Load Accumulator With Parallel Multiply Subtract With Rounding - -// PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS - -TMS320C54_st_add, // Store Accumulator With Parallel Add -TMS320C54_st_sub, // Store Accumulator With Parallel Subtract - -// PARALLEL STORE AND MULTIPLY INSTRUCTIONS - -TMS320C54_st_mac, // Store Accumulator With Parallel Multiply Accumulate Without Rounding -TMS320C54_st_macr, // Store Accumulator With Parallel Multiply Accumulate With Rounding -TMS320C54_st_mas, // Store Accumulator With Parallel Multiply Subtract Without Rounding -TMS320C54_st_masr, // Store Accumulator With Parallel Multiply Subtract With Rounding -TMS320C54_st_mpy, // Store Accumulator With Parallel Multiply - -// MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS - -TMS320C54_mvdd, // Move Data From Data Memory to Data Memory With X,Y Addressing -TMS320C54_mvdk, // Move Data From Data Memory to Data Memory With Destination Addressing -TMS320C54_mvdm, // Move Data From Data Memory to Memory-Mapped Register -TMS320C54_mvdp, // Move Data From Data Memory to Program Memory -TMS320C54_mvkd, // Move Data From Data Memory to Data Memory With Source Addressing -TMS320C54_mvmd, // Move Data From Memory-Mapped Register to Data Memory -TMS320C54_mvmm, // Move Data From Memory-Mapped Register to Memory-Mapped Register -TMS320C54_mvpd, // Move Data From Program Memory to Data Memory -TMS320C54_portr, // Read Data From Port -TMS320C54_portw, // Write Data to Port -TMS320C54_reada, // Read Program Memory Addressed by Accumulator A and Store in Data Memory -TMS320C54_writa, // Write Data to Program Memory Addressed by Accumulator A - -TMS320C54_last - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -TMS320C55_null = 0, // Unknown Operation - -// ARITHMETICAL OPERATIONS - -TMS320C55_abdst, // Absolute Distance -TMS320C55_abs1, // Absolute Value -TMS320C55_abs2, // Absolute Value - -TMS320C55_add1, // Addition -TMS320C55_add2, // Addition -TMS320C55_add3, // Addition -TMS320C55_add4, // Addition -TMS320C55_addv1, // Addition -TMS320C55_addv2, // Addition -TMS320C55_addrv1, // Addition and Round -TMS320C55_addrv2, // Addition and Round - -TMS320C55_maxdiff, // Compare and Select Maximum -TMS320C55_dmaxdiff, // Compare and Select 40-bit Maximum -TMS320C55_mindiff, // Compare and Select Minimum -TMS320C55_dmindiff, // Compare and Select 40-bit Minimum - -TMS320C55_addsubcc4, // Conditional Add or Subtract -TMS320C55_addsubcc5, // Conditional Add or Subtract -TMS320C55_addsub2cc, // Conditional Add or Subtract - -TMS320C55_sftcc, // Conditional Shift - -TMS320C55_subc2, // Conditional Subtract -TMS320C55_subc3, // Conditional Subtract - -TMS320C55_addsub, // Paralleled Add - Subtract -TMS320C55_subadd, // Parallel Subtract - Add - -TMS320C55_mpy_mpy, // Two Parallel Multiply -TMS320C55_mpy_mpyr, // Two Parallel Multiply, and Round -TMS320C55_mpy_mpy40, // Two Parallel Multiply, on 40 bits -TMS320C55_mpy_mpyr40, // Two Parallel Multiply, and Round on 40 bits -TMS320C55_mac_mpy, // Parallel Multiply - Accumulate -TMS320C55_macr_mpyr, // Parallel Multiply - Accumulate, and Round -TMS320C55_mac40_mpy40, // Parallel Multiply - Accumulate, on 40 bits -TMS320C55_macr40_mpyr40, // Parallel Multiply - Accumulate, and Round on 40 bits -TMS320C55_mas_mpy, // Parallel Multiply - Subtract -TMS320C55_masr_mpyr, // Parallel Multiply - Subtract, and Round -TMS320C55_mas40_mpy40, // Parallel Multiply - Subtract, on 40 bits -TMS320C55_masr40_mpyr40, // Parallel Multiply - Subtract, and Round on 40 bits -TMS320C55_amar_mpy, // Parallel Modify Auxiliary Register - Multiply -TMS320C55_amar_mpyr, // Parallel Modify Auxiliary Register - Multiply, and Round -TMS320C55_amar_mpy40, // Parallel Modify Auxiliary Register - Multiply, on 40 bits -TMS320C55_amar_mpyr40, // Parallel Modify Auxiliary Register - Multiply, and Round on 40 bits -TMS320C55_mac_mac, // Two Parallel Multiply and Accumulate -TMS320C55_macr_macr, // Two Parallel Multiply and Accumulate, and Round -TMS320C55_mac40_mac40, // Two Parallel Multiply and Accumulate, on 40 bits -TMS320C55_macr40_macr40, // Two Parallel Multiply and Accumulate, and Round on 40 bits -TMS320C55_mas_mac, // Parallel Multiply and Subtract - Multiply and Accumulate -TMS320C55_masr_macr, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round -TMS320C55_mas40_mac40, // Parallel Multiply and Subtract - Multiply and Accumulate, on 40 bits -TMS320C55_masr40_macr40, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round on 40 bits -TMS320C55_amar_mac, // Parallel Modify Auxiliary Register - Multiply and Accumulate -TMS320C55_amar_macr, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round -TMS320C55_amar_mac40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, on 40 bits -TMS320C55_amar_macr40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round on 40 bits -TMS320C55_mas_mas, // Two Parallel Multiply and Subtract -TMS320C55_masr_masr, // Two Parallel Multiply and Subtract, and Round -TMS320C55_mas40_mas40, // Two Parallel Multiply and Subtract, on 40 bits -TMS320C55_masr40_masr40, // Two Parallel Multiply and Subtract, and Round on 40 bits -TMS320C55_amar_mas, // Parallel Modify Auxiliary Register - Multiply and Subtract -TMS320C55_amar_masr, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round -TMS320C55_amar_mas40, // Parallel Modify Auxiliary Register - Multiply and Subtract, on 40 bits -TMS320C55_amar_masr40, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round on 40 bits -TMS320C55_mpy_mac, // Parallel Multiply - Multiply and Accumulate -TMS320C55_mpyr_macr, // Parallel Multiply - Multiply and Accumulate, and Round -TMS320C55_mpy40_mac40, // Parallel Multiply - Multiply and Accumulate, on 40 bits -TMS320C55_mpyr40_macr40, // Parallel Multiply - Multiply and Accumulate, and Round on 40 bits -TMS320C55_amar3, // Three Parallel Modify Auxiliary Registers - -TMS320C55_firsadd, // Parallel Multiply and Accumulate - Add -TMS320C55_firssub, // Parallel Multiply and Accumulate - Subtract - -TMS320C55_mpym_mov, // Parallel Multiply - Store -TMS320C55_mpymr_mov, // Parallel Multiply - Store, and Round -TMS320C55_macm_mov, // Parallel Multiply and Accumulate - Store -TMS320C55_macmr_mov, // Parallel Multiply and Accumulate - Store, and Round -TMS320C55_masm_mov, // Parallel Multiply and Subtract - Store -TMS320C55_masmr_mov, // Parallel Multiply and Subtract - Store, and Round -TMS320C55_add_mov, // Parallel Add - Store -TMS320C55_sub_mov, // Parallel Subtract - Store -TMS320C55_mov_mov, // Parallel Load - Store -TMS320C55_mov_aadd, // Parallel Store - aadd -TMS320C55_mov_add, // Parallel Store - Add -TMS320C55_amar_amar, // Parallel Modify Auxiliary Register - Modify Auxiliary Register -TMS320C55_add_asub, // Parallel Add - asub -TMS320C55_btst_mov, // Parallel Bit Test - Store -TMS320C55_mov_asub, // Parallel Store - asub - -TMS320C55_lms, // Least Mean Square - -TMS320C55_max1, // Maximum Comparison -TMS320C55_max2, // Maximum Comparison -TMS320C55_min1, // Minimum Comparison -TMS320C55_min2, // Minimum Comparison - -TMS320C55_cmp, // Memory Comparison -TMS320C55_cmpu, // Unsigned memory Comparison - -TMS320C55_aadd, // Add Two Registers -TMS320C55_asub, // Subtract Two Registers -TMS320C55_amov, // Move From Register to Register -TMS320C55_amar1, // Auxiliary Register Modification - -TMS320C55_sqr1, // Square -TMS320C55_sqr2, // Square -TMS320C55_sqrr1, // Square and Round -TMS320C55_sqrr2, // Square and Round -TMS320C55_mpy1, // Multiply -TMS320C55_mpy2, // Multiply -TMS320C55_mpy3, // Multiply -TMS320C55_mpyr1, // Multiply and Round -TMS320C55_mpyr2, // Multiply and Round -TMS320C55_mpyr3, // Multiply and Round -TMS320C55_mpyk2, // Multiply by Constant -TMS320C55_mpyk3, // Multiply by Constant -TMS320C55_mpykr2, // Multiply by Constant and Round -TMS320C55_mpykr3, // Multiply by Constant and Round -TMS320C55_mpym2, // Multiply Memory Value -TMS320C55_mpym3, // Multiply Memory Values -TMS320C55_mpymr2, // Multiply Memory Value and Round -TMS320C55_mpymr3, // Multiply Memory Values and Round -TMS320C55_mpym403, // Multiply Memory Values on 40 bits -TMS320C55_mpymr403, // Multiply Memory Values and Round on 40 bits -TMS320C55_mpymu3, // Unsigned multiply Memory Values -TMS320C55_mpymru3, // Unsigned multiply Memory Values and Round -TMS320C55_sqrm, // Square Memory Value -TMS320C55_sqrmr, // Square Memory Value, and Round -TMS320C55_mpymk, // Multiply Memory Value by Constant -TMS320C55_mpymkr, // Multiply Memory Value by Constant and Round - -TMS320C55_sqa1, // Square and Accumulate -TMS320C55_sqa2, // Square and Accumulate -TMS320C55_sqar1, // Square, Accumulate and Round -TMS320C55_sqar2, // Square, Accumulate and Round -TMS320C55_mac3, // Multiply and Accumulate -TMS320C55_mac4, // Multiply and Accumulate -TMS320C55_macr3, // Multiply, Accumulate and Round -TMS320C55_macr4, // Multiply, Accumulate and Round -TMS320C55_mack3, // Multiply by Constant and Accumulate -TMS320C55_mack4, // Multiply by Constant and Accumulate -TMS320C55_mackr3, // Multiply by Constant, Round and Accumulate -TMS320C55_mackr4, // Multiply by Constant, Round and Accumulate -TMS320C55_macm2, // Multiply and Accumulate Memory Values -TMS320C55_macm3, // Multiply and Accumulate Memory Values -TMS320C55_macm4, // Multiply and Accumulate Memory Values -TMS320C55_macmr2, // Multiply and Accumulate Memory Values, and Round -TMS320C55_macmr3, // Multiply and Accumulate Memory Values, and Round -TMS320C55_macmr4, // Multiply and Accumulate Memory Values, and Round -TMS320C55_macm403, // Multiply and Accumulate Memory Values, on 40 bits -TMS320C55_macm404, // Multiply and Accumulate Memory Values, on 40 bits -TMS320C55_macmr403, // Multiply and Accumulate Memory Values, and Round on 40 bits -TMS320C55_macmr404, // Multiply and Accumulate Memory Values, and Round on 40 bits -TMS320C55_macmz, // Multiply and Accumulate Memory Values -TMS320C55_macmrz, // Multiply and Accumulate Memory Values, and Round -TMS320C55_sqam2, // Square and Accumulate Memory Value -TMS320C55_sqam3, // Square and Accumulate Memory Values -TMS320C55_sqamr2, // Square and Accumulate Memory Value, and Round -TMS320C55_sqamr3, // Square and Accumulate Memory Values, and Round -TMS320C55_macmk3, // Multiply Memory Value by Constant and Accumulate -TMS320C55_macmk4, // Multiply Memory Value by Constant and Accumulate -TMS320C55_macmkr3, // Multiply Memory Value by Constant - Accumulate, and Round -TMS320C55_macmkr4, // Multiply Memory Value by Constant - Accumulate, and Round - -TMS320C55_sqs1, // Square and Subtract -TMS320C55_sqs2, // Square and Subtract -TMS320C55_sqsr1, // Square, Subtract and Round -TMS320C55_sqsr2, // Square, Subtract and Round - -TMS320C55_mas2, // Multiply and Subtract -TMS320C55_mas3, // Multiply and Subtract -TMS320C55_masr2, // Multiply, Subtract and Round -TMS320C55_masr3, // Multiply, Subtract and Round -TMS320C55_masm2, // Multiply and Subtract Memory Value -TMS320C55_masm3, // Multiply and Subtract Memory Values -TMS320C55_masm4, // Multiply and Subtract Memory Values -TMS320C55_masmr2, // Multiply and Subtract Memory Values, and Round -TMS320C55_masmr3, // Multiply and Subtract Memory Values, and Round -TMS320C55_masmr4, // Multiply and Subtract Memory Values, and Round -TMS320C55_masm403, // Multiply and Subtract Memory Values, on 40 bits -TMS320C55_masm404, // Multiply and Subtract Memory Values, on 40 bits -TMS320C55_masmr403, // Multiply and Subtract Memory Values, and Round on 40 bits -TMS320C55_masmr404, // Multiply and Subtract Memory Values, and Round on 40 bits -TMS320C55_sqsm2, // Square and Subtract Memory Values -TMS320C55_sqsm3, // Square and Subtract Memory Values -TMS320C55_sqsmr2, // Square and Subtract Memory Values, and Round -TMS320C55_sqsmr3, // Square and Subtract Memory Values, and Round - -TMS320C55_neg1, // Negation -TMS320C55_neg2, // Negation - -TMS320C55_mant_nexp, // Exponent and Mantissa -TMS320C55_exp, // Exponent - -TMS320C55_cmpand, // Compare and AND -TMS320C55_cmpandu, // Unsigned compare and AND -TMS320C55_cmpor, // Compare and OR -TMS320C55_cmporu, // Unsigned compare and OR - -TMS320C55_round1, // Round -TMS320C55_round2, // Round - -TMS320C55_sat1, // Saturate -TMS320C55_sat2, // Saturate -TMS320C55_satr1, // Saturate and Round -TMS320C55_satr2, // Saturate and Round - -TMS320C55_sfts2, // Signed Shift -TMS320C55_sfts3, // Signed Shift -TMS320C55_sftsc2, // Signed Shift with Carry -TMS320C55_sftsc3, // Signed Shift with Carry - -TMS320C55_sqdst, // Square distance - -TMS320C55_sub1, // Subtract -TMS320C55_sub2, // Subtract -TMS320C55_sub3, // Subtract -TMS320C55_sub4, // Subtract - -TMS320C55_band, // Bit Field Comparison - -TMS320C55_bfxpa, // Bit Field Expand - -TMS320C55_bfxtr, // Bit Field Extract - -TMS320C55_btst, // Bit Test -TMS320C55_bnot, // Bit NOT -TMS320C55_bclr2, // Bit Clear -TMS320C55_bset2, // Bit Set -TMS320C55_btstset, // Bit Test and Set -TMS320C55_btstclr, // Bit Test and Clear -TMS320C55_btstnot, // Bit Test and NOT -TMS320C55_btstp, // Bit Pair Test -TMS320C55_bclr1, // Bit Clear -TMS320C55_bset1, // Bit Set - -TMS320C55_amar2, // Load Effective Address to Extended Auxiliary Register -TMS320C55_popboth, // Pop Extended Auxiliary Register from Stack Pointers -TMS320C55_pshboth, // Push Extended Auxiliary Register to Stack Pointers - -// LOGICAL OPERATIONS - -TMS320C55_bcnt, // Count Bit Field - -TMS320C55_not1, // NOT -TMS320C55_not2, // NOT - -TMS320C55_and1, // AND -TMS320C55_and2, // AND -TMS320C55_and3, // AND - -TMS320C55_or1, // OR -TMS320C55_or2, // OR -TMS320C55_or3, // OR - -TMS320C55_xor1, // XOR -TMS320C55_xor2, // XOR -TMS320C55_xor3, // XOR - -TMS320C55_sftl2, // Logical Shift -TMS320C55_sftl3, // Logical Shift - -TMS320C55_rol, // Rotate Left - -TMS320C55_ror, // Rotate Right - -// MISCELLANEOUS OPERATIONS - -// MOVE OPERATIONS - -TMS320C55_swap, // Swap Registers -TMS320C55_swapp, // Swap Pair Registers -TMS320C55_swap4, // Swap 4 Registers - -TMS320C55_mov2, // Move Data -TMS320C55_mov3, // Move 2 Data -TMS320C55_mov402, // Move Data on 40 bits - -TMS320C55_delay, // Memory Delay - -TMS320C55_pop1, // Pop Top of Stack1 -TMS320C55_pop2, // Pop Top of Stack2 - -TMS320C55_psh1, // Pop Top of Stack3 -TMS320C55_psh2, // Pop Top of Stack4 - -// PROGRAM CONTROL OPERATIONS - -TMS320C55_bcc, // Branch Conditionally -TMS320C55_bccu, // Branch Conditionally - -TMS320C55_b, // Branch Unconditionally - -TMS320C55_callcc, // Call Conditionally - -TMS320C55_call, // Call Unconditionally - -TMS320C55_xcc, // Execute Conditionally -TMS320C55_xccpart, // Execute Conditionally - -TMS320C55_idle, // Idle - -TMS320C55_nop, // No Operation -TMS320C55_nop_16, // No Operation - -TMS320C55_rptblocal, // Repeat Block of Instructions Unconditionally -TMS320C55_rptb, // Repeat Block of Instructions Unconditionally - -TMS320C55_rptcc, // Repeat Single Instruction Conditionally - -TMS320C55_rpt, // Repeat Single Instruction Unconditionally -TMS320C55_rptadd, // Repeat Single Instruction Unconditionally and Add to Register -TMS320C55_rptsub, // Repeat Single Instruction Unconditionally and Subtract to Register - -TMS320C55_retcc, // Return Conditionally -TMS320C55_ret, // Return Unconditionally -TMS320C55_reti, // Return from Interrupt - -TMS320C55_intr, // Software Interrupt - -TMS320C55_reset, // Software Reset - -TMS320C55_trap, // Software Trap - -TMS320C55_last - -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -TRIMEDIA_null, - -TRIMEDIA_igtri, // signed compare greater with immediate -TRIMEDIA_igeqi, // signed compare greater or equal with immediate -TRIMEDIA_ilesi, // signed compare less with immediate -TRIMEDIA_ineqi, // signed compare not equal with immediate -TRIMEDIA_ieqli, // signed compare equal with immediate -TRIMEDIA_iaddi, // add with immediate -TRIMEDIA_ild16d, // signed 16-bit load with displacement -TRIMEDIA_ld32d, // 32-bit load with displacement -TRIMEDIA_uld8d, // unsigned 8-bit load with displacement -TRIMEDIA_lsri, // logical shift right immediate -TRIMEDIA_asri, // arithmetic shift right immediate -TRIMEDIA_asli, // arithmetic shift left immediate -TRIMEDIA_iadd, // signed add -TRIMEDIA_isub, // signed subtract -TRIMEDIA_igeq, // signed compare greater or equal -TRIMEDIA_igtr, // signed compare greater -TRIMEDIA_bitand, // bitwise logical AND -TRIMEDIA_bitor, // bitwise logical OR -TRIMEDIA_asr, // arithmetic shift right -TRIMEDIA_asl, // arithmetic shift left -TRIMEDIA_ifloat, // convert signed integer to floating-point -TRIMEDIA_ifixrz, // convert floating-point to integer with round toward zero -TRIMEDIA_fadd, // floating-point add -TRIMEDIA_imin, // signed minimum -TRIMEDIA_imax, // signed maximum -TRIMEDIA_iavgonep, // signed average -TRIMEDIA_ume8uu, // sum of absolute values of unsigned 8-bit differences -TRIMEDIA_imul, // signed multiply -TRIMEDIA_fmul, // floating-point multiply -TRIMEDIA_h_st8d, // hardware 8-bit store with displacement -TRIMEDIA_h_st16d, // hardware 16-bit store with displacement -TRIMEDIA_h_st32d, // hardware 32-bit store with displacement -TRIMEDIA_isubi, // subtract with immediate -TRIMEDIA_ugtr, // unsigned compare greater -TRIMEDIA_ugtri, // unsigned compare greater with immediate -TRIMEDIA_ugeq, // unsigned compare greater or equal -TRIMEDIA_ugeqi, // unsigned compare greater or equal with immediate -TRIMEDIA_ieql, // signed compare equal -TRIMEDIA_ueqli, // unsigned compare equal with immediate -TRIMEDIA_ineq, // signed compare not equal -TRIMEDIA_uneqi, // unsigned compare not equal -TRIMEDIA_ulesi, // unsigned compare less with immediate -TRIMEDIA_ileqi, // signed compare less or equal with immediate -TRIMEDIA_uleqi, // unsigned compare less or equal with immediate -TRIMEDIA_h_iabs, // hardware absolute value -TRIMEDIA_carry, // compute carry bit from unsigned add -TRIMEDIA_izero, // if zero select zero -TRIMEDIA_inonzero, // if nonzero select zero -TRIMEDIA_bitxor, // bitwise logical exclusive OR -TRIMEDIA_bitandinv, // bitwise logical AND NOT -TRIMEDIA_bitinv, // bitwise logical NOT -TRIMEDIA_sex16, // sign extend 16 bits -TRIMEDIA_packbytes, // pack least-significant bytes -TRIMEDIA_pack16lsb, // pack least-significant 16-bit halfwords -TRIMEDIA_pack16msb, // pack most-significant 16-bit halfwords -TRIMEDIA_ubytesel, // select unsigned byte -TRIMEDIA_ibytesel, // signed select byte -TRIMEDIA_mergelsb, // merge least-significant byte -TRIMEDIA_mergemsb, // merge most-significant byte -TRIMEDIA_ume8ii, // unsigned sum of absolute values of signed 8-bit differences -TRIMEDIA_h_dspiabs, // clipped signed absolute value -TRIMEDIA_dspiadd, // clipped signed add -TRIMEDIA_dspuadd, // clipped unsigned add -TRIMEDIA_dspisub, // clipped signed subtract -TRIMEDIA_dspusub, // clipped unsigned subtract -TRIMEDIA_dspidualadd, // dual clipped add of signed 16-bit halfwords -TRIMEDIA_dspidualsub, // dual clipped subtract of signed 16-bit halfwords -TRIMEDIA_h_dspidualabs, // dual clipped absolute value of signed 16-bit halfwords -TRIMEDIA_quadavg, // unsigned byte-wise quad average -TRIMEDIA_iclipi, // clip signed to signed -TRIMEDIA_uclipi, // clip signed to unsigned -TRIMEDIA_uclipu, // clip unsigned to unsigned -TRIMEDIA_iflip, // if non-zero negate -TRIMEDIA_dspuquadaddui, // quad clipped add of unsigned/signed bytes -TRIMEDIA_quadumin, // unsigned byte-wise quad minimum -TRIMEDIA_quadumax, // unsigned byte-wise quad maximum -TRIMEDIA_dualiclipi, // dual-16 clip signed to signed -TRIMEDIA_dualuclipi, // dual-16 clip signed to unsigned -TRIMEDIA_quadumulmsb, // unsigned quad 8-bit multiply most significant -TRIMEDIA_ufir8uu, // unsigned sum of products of unsigned bytes -TRIMEDIA_ifir8ui, // signed sum of products of unsigned/signed bytes -TRIMEDIA_ifir8ii, // signed sum of products of signed bytes -TRIMEDIA_ifir16, // sum of products of signed 16-bit halfwords -TRIMEDIA_ufir16, // sum of products of unsigned 16-bit halfwords -TRIMEDIA_dspidualmul, // dual clipped multiply of signed 16-bit halfwords -TRIMEDIA_lsr, // logical shift right -TRIMEDIA_rol, // rotate left -TRIMEDIA_roli, // rotate left by immediate -TRIMEDIA_funshift1, // funnel-shift 1 byte -TRIMEDIA_funshift2, // funnel-shift 2 bytes -TRIMEDIA_funshift3, // funnel-shift 3 bytes -TRIMEDIA_dualasr, // dual-16 arithmetic shift right -TRIMEDIA_mergedual16lsb,// merge dual 16-bit lsb bytes -TRIMEDIA_fdiv, // floating-point divide -TRIMEDIA_fdivflags, // IEEE status flags from floating-point divide -TRIMEDIA_fsqrt, // floating-point square root -TRIMEDIA_fsqrtflags, // IEEE status flags from floating-point square root -TRIMEDIA_faddflags, // IEEE status flags from floating-point add -TRIMEDIA_fsub, // floating-point subtract -TRIMEDIA_fsubflags, // IEEE status flags from floating-point subtract -TRIMEDIA_fabsval, // floating-point absolute value -TRIMEDIA_fabsvalflags, // IEEE status flags from floating-point absolute value -TRIMEDIA_ifloatrz, // convert signed integer to floating-point with rounding toward zero -TRIMEDIA_ifloatrzflags, // IEEE status flags from convert signed integer to floating-point with rounding toward zero -TRIMEDIA_ufloatrz, // convert unsigned integer to floating-point with round toward zero -TRIMEDIA_ufloatrzflags, // IEEE status flags from convert unsigned integer to floating-point with round toward zero -TRIMEDIA_ifixieee, // convert floating-point to integer using PCSW rounding mode -TRIMEDIA_ifixieeeflags, // IEEE status flags from convert floating-point to integer using PCSW rounding mode -TRIMEDIA_ufixieee, // convert floating-point to unsigned integer using PCSW rounding mode -TRIMEDIA_ufixieeeflags, // IEEE status flags from convert floating-point to unsigned integer using PCSW rounding mode -TRIMEDIA_ufixrz, // convert floating-point to unsigned integer with round toward zero -TRIMEDIA_ufixrzflags, // IEEE status flags from convert floating-point to unsigned integer with round toward zero -TRIMEDIA_ufloat, // convert unsigned integer to floating-point -TRIMEDIA_ufloatflags, // IEEE status flags from convert unsigned integer to floating-point -TRIMEDIA_ifixrzflags, // IEEE status flags from convert floating-point to integer with round toward zero -TRIMEDIA_ifloatflags, // IEEE status flags from convert signed integer to floating-point -TRIMEDIA_umul, // unsigned multiply -TRIMEDIA_imulm, // signed multiply, return most-significant 32 bits -TRIMEDIA_umulm, // unsigned multiply, return most-significant 32 bits -TRIMEDIA_dspimul, // clipped signed multiply -TRIMEDIA_dspumul, // clipped unsigned multiply -TRIMEDIA_fmulflags, // IEEE status flags from floating-point multiply -TRIMEDIA_fgtr, // floating-point compare greater -TRIMEDIA_fgtrflags, // IEEE status flags from floating-point compare greater -TRIMEDIA_fgeq, // floating-point compare greater or equal -TRIMEDIA_fgeqflags, // IEEE status flags from floating-point compare greater or equal -TRIMEDIA_feql, // floating-point compare equal -TRIMEDIA_feqlflags, // IEEE status flags from floating-point compare equal -TRIMEDIA_fneq, // floating-point compare not equal -TRIMEDIA_fneqflags, // IEEE status flags from floating-point compare not equal -TRIMEDIA_fsign, // sign of floating-point value -TRIMEDIA_fsignflags, // IEEE status flags from floating-point sign -TRIMEDIA_cycles, // read clock cycle counter, least-significant word -TRIMEDIA_hicycles, // read clock cycle counter, most-significant word -TRIMEDIA_readdpc, // read destination program counter -TRIMEDIA_readspc, // read source program counter -TRIMEDIA_readpcsw, // read program control and status word -TRIMEDIA_writespc, // write source program counter -TRIMEDIA_writedpc, // write destination program counter -TRIMEDIA_writepcsw, // write program control and status word -TRIMEDIA_curcycles, // read current clock cycle, least-significant word -TRIMEDIA_jmpt, // indirect jump on true -TRIMEDIA_ijmpt, // interruptible indirect jump on true -TRIMEDIA_jmpi, // jump immediate -TRIMEDIA_ijmpi, // interruptible jump immediate -TRIMEDIA_jmpf, // indirect jump on false -TRIMEDIA_ijmpf, // interruptible indirect jump on false -TRIMEDIA_iclr, // invalidate all instruction cache blocks -TRIMEDIA_uimm, // unsigned immediate -TRIMEDIA_ild8d, // signed 8-bit load with displacement -TRIMEDIA_ild8r, // signed 8-bit load with index -TRIMEDIA_uld8r, // unsigned 8-bit load with index -TRIMEDIA_ild16r, // signed 16-bit load with index -TRIMEDIA_ild16x, // signed 16-bit load with scaled index -TRIMEDIA_uld16d, // unsigned 16-bit load with displacement -TRIMEDIA_uld16r, // unsigned 16-bit load with index -TRIMEDIA_uld16x, // unsigned 16-bit load with scaled index -TRIMEDIA_ld32r, // 32-bit load with index -TRIMEDIA_ld32x, // 32-bit load with scaled index -TRIMEDIA_rdtag, // read data cache address tag -TRIMEDIA_rdstatus, // read data cache status bits -TRIMEDIA_dcb, // data cache copy back -TRIMEDIA_dinvalid, // invalidate data cache block -TRIMEDIA_prefd, // prefetch with displacement -TRIMEDIA_prefr, // prefetch with index -TRIMEDIA_pref16x, // prefetch with 16-bit scaled index -TRIMEDIA_pref32x, // prefetch with 32-bit scaled index -TRIMEDIA_allocd, // allocate a cache block with displacement -TRIMEDIA_allocr, // allocate a cache block with index -TRIMEDIA_allocx, // allocate a cache block with scaled index -TRIMEDIA_nop, - -// Pseudo-operations - -TRIMEDIA_alloc, // allocate a cache block -TRIMEDIA_dspiabs, // clipped signed absolute value -TRIMEDIA_dspidualabs, // dual clipped absolute value of signed 16-bit halfwords -TRIMEDIA_iabs, // absolute value -TRIMEDIA_ild16, // signed 16-bit load -TRIMEDIA_ild8, // signed 8-bit load -TRIMEDIA_ineg, // signed negate -TRIMEDIA_ld32, // 32-bit load -TRIMEDIA_pref, // prefetch -TRIMEDIA_sex8, // sign extend 8 bits -TRIMEDIA_st16, // 16-bit store -TRIMEDIA_st16d, // 16-bit store with displacement -TRIMEDIA_st32, // 32-bit store -TRIMEDIA_st32d, // 32-bit store with displacement -TRIMEDIA_st8, // 8-bit store -TRIMEDIA_st8d, // 8-bit store with displacement -TRIMEDIA_uld16, // unsigned 16-bit load -TRIMEDIA_uld8, // unsigned 8-bit load -TRIMEDIA_zex16, // zero extend 16 bits -TRIMEDIA_zex8, // zero extend 8 bits -TRIMEDIA_ident, // identity - -// Unused pseudo-operations: - -TRIMEDIA_iles, -TRIMEDIA_ileq, -TRIMEDIA_ules, -TRIMEDIA_uleq, -TRIMEDIA_fles, -TRIMEDIA_fleq, -TRIMEDIA_ueql, -TRIMEDIA_uneq, -TRIMEDIA_flesflags, -TRIMEDIA_fleqflags, -TRIMEDIA_borrow, -TRIMEDIA_umin, -TRIMEDIA_lsl, -TRIMEDIA_lsli, - -TRIMEDIA_last, - - }; - -/* - * NEC 78K0 processor module for IDA. - * Copyright (c) 2006 Konstantin Norvatoff, - * Freeware. - */ - - - -enum -{ -NEC_78K_0_null = 0, // Unknown Operation - -NEC_78K_0_mov, // Move Byte Data Transfer -NEC_78K_0_xch, // Exchange Byte Data -NEC_78K_0_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer -NEC_78K_0_xchw, // Exchange Word Data - -NEC_78K_0_add, // Add Byte Data Addition -NEC_78K_0_addc, // Add with Carry Addition of Byte Data with Carry -NEC_78K_0_sub, // Subtract Byte Data Subtraction -NEC_78K_0_subc, // Subtract with Carry Subtraction of Byte Data with Carry -NEC_78K_0_and, // And Logical Product of Byte Data -NEC_78K_0_or, // Or Logical Sum of Byte Data -NEC_78K_0_xor, // Exclusive Or Exclusive Logical Sum of Byte Data -NEC_78K_0_cmp, // Compare Byte Data Comparison - -NEC_78K_0_addw, // Add Word Data Addition -NEC_78K_0_subw, // Subtract Word Data Subtraction -NEC_78K_0_cmpw, // Compare Word Data Comparison - -NEC_78K_0_mulu, // Multiply Unsigned Multiplication of Data -NEC_78K_0_divuw, // Divide Unsigned Word Unsigned Division of Word Data - -NEC_78K_0_inc, // Increment Byte Data Increment -NEC_78K_0_dec, // Decrement Byte Data Decrement -NEC_78K_0_incw, // Increment Word Data Increment -NEC_78K_0_decw, // Decrement Word Data Decrement - -NEC_78K_0_ror, // Rotate Right Byte Data Rotation to the Right -NEC_78K_0_rol, // Rotate Left Byte Data Rotation to the Left -NEC_78K_0_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry -NEC_78K_0_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry -NEC_78K_0_ror4, // Rotate Right Digit Digit Rotation to the Right -NEC_78K_0_rol4, // Rotate Left Digit Digit Rotation to the Left - -NEC_78K_0_adjba, // Decimal Adjust Register for Addition Decimal Adjustment of Addition Result -NEC_78K_0_adjbs, // Decimal Adjust Register for Subtraction Decimal Adjustment of Subtraction Result - -NEC_78K_0_mov1, // Move Single Bit 1 Bit Data Transfer -NEC_78K_0_and1, // And Single Bit 1 Bit Data Logical Product -NEC_78K_0_or1, // Or Single Bit 1 Bit Data Logical Sum -NEC_78K_0_xor1, // Exclusive Or Single Bit 1 Bit Data Exclusive Logical Sum -NEC_78K_0_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set -NEC_78K_0_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear -NEC_78K_0_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation - -NEC_78K_0_call, // Call Subroutine Call (16 Bit Direct) -NEC_78K_0_callf, // Call Flag Subroutine Call (11 Bit Direct Specification) -NEC_78K_0_callt, // Call Table Subroutine Call (Refer to the Call Table) -NEC_78K_0_brk, // Break Software Vectored Interrupt -NEC_78K_0_ret, // Return Return from Subroutine -NEC_78K_0_retb, // Return from Interrupt Return from Hardware Vectored Interrupt -NEC_78K_0_reti, // Return from Break Return from Software Vectored Interrupt - -NEC_78K_0_push, // Push -NEC_78K_0_pop, // Pop - -NEC_78K_0_br, // Branch Unconditional Branch -NEC_78K_0_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1) -NEC_78K_0_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0) -NEC_78K_0_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1) -NEC_78K_0_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0) -NEC_78K_0_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1) -NEC_78K_0_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0) -NEC_78K_0_btclr, // Branch if True and Clear Conditional Branch and Clear by Bit Test (Byte Data Bit = 1) -NEC_78K_0_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1!= 0) - -NEC_78K_0_sel, // Select Register Bank Register Bank Selection - - -NEC_78K_0_nop, // No Operation -NEC_78K_0_EI, // Enable Interrupt -NEC_78K_0_DI, // Disable Interrupt -NEC_78K_0_HALT, // HALT Mode Set -NEC_78K_0_STOP, // Stop Mode Set - - -NEC_78K_0_last - - }; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - NEC_78K_0S_null = 0, // Unknown Operation - NEC_78K_0S_cmp, // Compare Byte Data Comparison - NEC_78K_0S_xor, // Exclusive Or Exclusive Logical Sum of Byte Data - NEC_78K_0S_and, // AND Logical Product of Byte Data - NEC_78K_0S_or, // OR Logical Sum of Byte Data - NEC_78K_0S_add, // ADD Byte Data Addition - NEC_78K_0S_sub, // Subtract Byte Data Subtraction - NEC_78K_0S_addc, // Add with Carry Addition of Byte Data with Carry - NEC_78K_0S_subc, // Subtract with Carry Subtraction of Byte Data with Carry - NEC_78K_0S_subw, // Subtract Word Data Subtraction - NEC_78K_0S_addw, // Add Word Data Addition - NEC_78K_0S_cmpw, // Compare Word Data Comparison - NEC_78K_0S_inc, // Increment Byte Data Increment - NEC_78K_0S_dec, // Decrement Byte Data Decrement - NEC_78K_0S_incw, // Increment Word Data Increment - NEC_78K_0S_decw, // Decrement Word Data Decrement - NEC_78K_0S_ror, // Rotate Right Byte Data Rotation to the Right - NEC_78K_0S_rol, // Rotate Left Byte Data Rotation to the Left - NEC_78K_0S_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry - NEC_78K_0S_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry - NEC_78K_0S_call, // CALL Subroutine Call (16 Bit Direct) - NEC_78K_0S_callt, // Call Table Subroutine Call (Call Table Reference) - NEC_78K_0S_ret, // Return from Subroutine - NEC_78K_0S_reti, // Return from Interrupt / Return from Hardware Vectored Interrupt - NEC_78K_0S_mov, // Move Byte Data Transfer - NEC_78K_0S_xch, // Exchange Byte Data Exchange - NEC_78K_0S_xchw, // Exchange Word Data Exchange - NEC_78K_0S_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set - NEC_78K_0S_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear - NEC_78K_0S_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation - NEC_78K_0S_push, // Push - NEC_78K_0S_pop, // Pop - NEC_78K_0S_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer - NEC_78K_0S_br, // Unconditional Branch - NEC_78K_0S_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1) - NEC_78K_0S_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0) - NEC_78K_0S_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1) - NEC_78K_0S_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0) - NEC_78K_0S_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1) - NEC_78K_0S_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0) - NEC_78K_0S_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1 != 0) - NEC_78K_0S_nop, // No Operation - NEC_78K_0S_EI, // Enable Interrupt - NEC_78K_0S_DI, // Disable Interrupt - NEC_78K_0S_HALT, // HALT Mode Set - NEC_78K_0S_STOP, // Stop Mode Set - NEC_78K_0S_last -}; - - - - -// The instruction types (``itype''s) -// M16C/60, M16C/20, M16C/Tiny and M16C/80 CPUs implements. - -enum m16c_itype_t -{ - M16C_null=0, // Unknown Operation - M16C_abs, // Absolute value - M16C_adc, // Add with carry - M16C_adcf, // Add carry flag - M16C_add, // Add without carry - M16C_adjnz, // Add & conditional jump - M16C_and, // Logically AND - M16C_band, // Logically AND bits - M16C_bclr, // Clear bit - M16C_bmcnd, // Conditional bit transfer - // conds (order is important; don't shuffle) (same order as the enum am_cnd8_t in m16c.hpp) - M16C_bmgeu, // Conditional bit transfer: Equal to or greater than; C == 1 - M16C_bmgtu, // Conditional bit transfer: Greater than - M16C_bmeq, // Conditional bit transfer: Equal to; Z == 1 - M16C_bmn, // Conditional bit transfer: Negative - M16C_bmle, // Conditional bit transfer: Equal to or smaller than (signed) - M16C_bmo, // Conditional bit transfer: Overflow; O == 1 - M16C_bmge, // Conditional bit transfer: Equal to or greater than (signed) - M16C_bmltu, // Conditional bit transfer: Smaller than; C == 0 - M16C_bmleu, // Conditional bit transfer: Equal to or smaller than - M16C_bmne, // Conditional bit transfer: Not equal; Z == 0 - M16C_bmpz, // Conditional bit transfer: Positive or zero - M16C_bmgt, // Conditional bit transfer: Greater than (signed) - M16C_bmno, // Conditional bit transfer: No overflow; O == 0 - M16C_bmlt, // Conditional bit transfer: Smaller than (signed) - // --- - M16C_bnand, // Logically AND inverted bits - M16C_bnor, // Logically OR inverted bits - M16C_bnot, // Invert bit - M16C_bntst, // Test inverted bit - M16C_bnxor, // Exclusive OR inverted bits - M16C_bor, // Logically OR bits - M16C_brk, // Debug interrupt - M16C_bset, // Set bit - M16C_btst, // Test bit - M16C_btstc, // Test bit & clear - M16C_btsts, // Test bit & set - M16C_bxor, // Exclusive OR bits - M16C_cmp, // Compare - M16C_dadc, // Decimal add with carry - M16C_dadd, // Decimal add without carry - M16C_dec, // Decrement - M16C_div, // Signed divide - M16C_divu, // Unsigned divide - M16C_divx, // Signed divide (extension) - M16C_dsbb, // Decimal subtract with borrow - M16C_dsub, // Decimal subtract without borrow - M16C_enter, // Build stack frame - M16C_exitd, // Deallocate stack frame - M16C_exts, // Extend sign - M16C_fclr, // Clear flag register bit - M16C_fset, // Set flag register bit - M16C_inc, // Increment - M16C_int, // Interrupt by INT instruction - M16C_into, // Interrupt on overflow - M16C_jcnd, // Jump on condition - // conds (order is important; don't shuffle) (same order as the enum am_cnd8_t in m16c.hpp) - M16C_jgeu, // Conditional jump: Equal to or greater than; C == 1 - M16C_jgtu, // Conditional jump: Greater than - M16C_jeq, // Conditional jump: Equal to; Z == 1 - M16C_jn, // Conditional jump: Negative - M16C_jle, // Conditional jump: Equal to or smaller than (signed) - M16C_jo, // Conditional jump: Overflow; O == 1 - M16C_jge, // Conditional jump: Equal to or greater than (signed) - M16C_jltu, // Conditional jump: Smaller than; C == 0 - M16C_jleu, // Conditional jump: Equal to or smaller than - M16C_jne, // Conditional jump: Not equal; Z == 0 - M16C_jpz, // Conditional jump: Positive or zero - M16C_jgt, // Conditional jump: Greater than (signed) - M16C_jno, // Conditional jump: No overflow; O == 0 - M16C_jlt, // Conditional jump: Smaller than (signed) - // --- - M16C_jmp, // Unconditional jump - M16C_jmpi, // Jump indirect - M16C_jmps, // Jump to special page - M16C_jsr, // Subroutine call - M16C_jsri, // Indirect subroutine call - M16C_jsrs, // Special page subroutine call - M16C_ldc, // Transfer to control register - M16C_ldctx, // Restore context - M16C_lde, // Transfer from extended data area - M16C_ldintb, // Load to INTB register - M16C_ldipl, // Set interrupt enable level - M16C_mov, // Transfer - M16C_mova, // Transfer effective address - M16C_movhh, // Xfer 4-bit data: src(8-bits)'s 4 hi bits -> dest(8-bits)'s 4 hi bits. - M16C_movhl, // Xfer 4-bit data: src(8-bits)'s 4 hi bits -> dest(8-bits)'s 4 lo bits. - M16C_movlh, // Xfer 4-bit data: src(8-bits)'s 4 lo bits -> dest(8-bits)'s 4 hi bits. - M16C_movll, // Xfer 4-bit data: src(8-bits)'s 4 lo bits -> dest(8-bits)'s 4 lo bits. - M16C_mul, // Signed multiply - M16C_mulu, // Unsigned multiply - M16C_neg, // Two's complement - M16C_nop, // No operation - M16C_not, // Invert all bits - M16C_or, // Logically OR - M16C_pop, // Restore register/memory - M16C_popc, // Restore control register - M16C_popm, // Restore multiple registers - M16C_push, // Save register/memory/immediate data - M16C_pusha, // Save effective address - M16C_pushc, // Save control register - M16C_pushm, // Save multiple registers - M16C_reit, // Return from interrupt - M16C_rmpa, // Calculate sum-of-products - M16C_rolc, // Rotate left with carry - M16C_rorc, // Rotate right with carry - M16C_rot, // Rotate - M16C_rts, // Return from subroutine - M16C_sbb, // Subtract with borrow - M16C_sbjnz, // Subtract & conditional jump - M16C_sha, // Shift arithmetic - M16C_shl, // Shift logical - M16C_smovb, // Transfer string backward - M16C_smovf, // Transfer string forward - M16C_sstr, // Store string - M16C_stc, // Transfer from control register - M16C_stctx, // Save context - M16C_ste, // Store to extended data area - M16C_stnz, // Conditional transfer: store on not zero - M16C_stz, // Conditional transfer: store on zero - M16C_stzx, // Conditional transfer: store on zero extension - M16C_sub, // Subtract without borrow - M16C_tst, // Test - M16C_und, // Interrupt for undefined instruction - M16C_wait, // Wait - M16C_xchg, // Exchange - M16C_xor, // Exclusive OR - - // M16C/80 specifics - M16C_addx, - M16C_bitindex, - M16C_brk2, // Debugger-only interrupt - M16C_clip, - M16C_cmpx, - M16C_extz, - M16C_freit, // Fast return from interrupt - M16C_indexb, - M16C_indexbd, - M16C_indexbs, - M16C_indexl, - M16C_indexld, - M16C_indexls, - M16C_indexw, - M16C_indexwd, - M16C_indexws, - M16C_max, - M16C_min, - M16C_movx, - M16C_mulex, - M16C_sccnd, - // conds (order is important; don't shuffle) (same order as the enum am_cnd8_t in m16c.hpp) - M16C_scgeu, // Conditional store: Equal to or greater than; C == 1 - M16C_scgtu, // Conditional store: Greater than - M16C_sceq, // Conditional store: Equal to; Z == 1 - M16C_scn, // Conditional store: Negative - M16C_scle, // Conditional store: Equal to or smaller than (signed) - M16C_sco, // Conditional store: Overflow; O == 1 - M16C_scge, // Conditional store: Equal to or greater than (signed) - M16C_scltu, // Conditional store: Smaller than; C == 0 - M16C_scleu, // Conditional store: Equal to or smaller than - M16C_scne, // Conditional store: Not equal; Z == 0 - M16C_scpz, // Conditional store: Positive or zero - M16C_scgt, // Conditional store: Greater than (signed) - M16C_scno, // Conditional store: No overflow; O == 0 - M16C_sclt, // Conditional store: Smaller than (signed) - // --- - M16C_scmpu, - M16C_sin, - M16C_smovu, - M16C_sout, - M16C_subx, - - // M32C specifics - M16C_shanc, // Shift arithmetic no carry - M16C_shlnc, // Shift logical no carry - - // R32C specifics - M16C_addf, - M16C_adsf, - M16C_cmpf, - M16C_cnvif, - M16C_divf, - M16C_ediv, - M16C_edivu, - M16C_edivx, - M16C_emul, - M16C_emulu, - M16C_exiti, - M16C_index1, - M16C_index2, - M16C_mulf, - M16C_mulx, - M16C_round, - M16C_stop, - M16C_subf, - M16C_suntil, - M16C_swhile, - - M16C_last -}; - - - - - - - -// exporting the ins.cpp array - -// m32r instructions declaration -enum -{ - m32r_null = 0, // Null instruction - m32r_add, // Add - m32r_add3, // Add 3-operand - m32r_addi, // Add immediate - m32r_addv, // Add with overflow checking - m32r_addv3, // Add 3-operand with overflow checking - m32r_addx, // Add with carry - m32r_and, // AND - m32r_and3, // AND 3-operand - m32r_bc, // Branch on C-bit - m32r_beq, // Branch on equal - m32r_beqz, // Branch on equal zero - m32r_bgez, // Branch on greater than or equal zero - m32r_bgtz, // Branch on greater than zero - m32r_bl, // Branch and link - m32r_blez, // Branch on less than or equal zero - m32r_bltz, // Branch on less than zero - m32r_bnc, // Branch on not C-bit - m32r_bne, // Branch on not equal - m32r_bnez, // Branch on not equal zero - m32r_bra, // Branch - m32r_cmp, // Compare - m32r_cmpi, // Compare immediate - m32r_cmpu, // Compare unsigned - m32r_cmpui, // Compare unsigned immediate - m32r_div, // Divide - m32r_divu, // Divide unsigned - m32r_jl, // Jump and link - m32r_jmp, // Jump - m32r_ld, // Load - m32r_ld24, // Load 24-bit immediate - m32r_ldb, // Load byte - m32r_ldh, // Load halfword - m32r_ldi, // Load immediate - m32r_ldub, // Load unsigned byte - m32r_lduh, // Load unsigned halfword - m32r_lock, // Load locked - m32r_machi, // Multiply-accumulate high-order halfwords - m32r_maclo, // Multiply-accumulate low-order halfwords - m32r_macwhi, // Multiply-accumulate word and high-order halfword - m32r_macwlo, // Multiply-accumulate word and low-order halfword - m32r_mul, // Multiply - m32r_mulhi, // Multiply high-order halfwords - m32r_mullo, // Multiply low-order halfwords - m32r_mulwhi, // Multiply word high-order halfwords - m32r_mulwlo, // Multiply word low-order halfwords - m32r_mv, // Move register - m32r_mvfachi, // Move from accumulator high-order word - m32r_mvfaclo, // Move from accumulator low-order word - m32r_mvfacmi, // Move from accumulator middle-order word - m32r_mvfc, // Move from control register - m32r_mvtachi, // Move to accumulator high-order word - m32r_mvtaclo, // Move to accumulator low-order word - m32r_mvtc, // Move to control register - m32r_neg, // Negate - m32r_nop, // No operation - m32r_not, // Logical NOT - m32r_or, // OR - m32r_or3, // OR 3-operand - m32r_push, // Push, mnem for st reg, @-sp - m32r_pop, // Pop, mnem for ld reg, @sp+ - m32r_rac, // Round accumulator - m32r_rach, // Round accumulator halfword - m32r_rem, // Remainder - m32r_remu, // Remainder unsigned - m32r_rte, // Return from EIT - m32r_seth, // Set high-order 16-bit - m32r_sll, // Shift left logical - m32r_sll3, // Shift left logical 3-operand - m32r_slli, // Shift left logical immediate - m32r_sra, // Shirt right arithmetic - m32r_sra3, // Shirt right arithmetic 3-operand - m32r_srai, // Shirt right arithmetic immediate - m32r_srl, // Shift right logical - m32r_srl3, // Shift right logical 3-operand - m32r_srli, // Shift right logical immediate - m32r_st, // Store - m32r_stb, // Store byte - m32r_sth, // Store halfword - m32r_sub, // Substract - m32r_subv, // Substract with overflow checking - m32r_subx, // Substract with borrow - m32r_trap, // Trap - m32r_unlock, // Store unlocked - m32r_xor, // Exclusive OR - m32r_xor3, // Exclusive OR 3-operand - - // M32RX : - - m32rx_bcl, - m32rx_bncl, - m32rx_cmpeq, - m32rx_cmpz, - m32rx_divh, - m32rx_jc, - m32rx_jnc, - m32rx_machi, // 'machi' 3-operand - m32rx_maclo, // 'maclo' 3-operand - m32rx_macwhi, // 'macwhi' 3-operand - m32rx_macwlo, // 'macwlo' 3-operand - m32rx_mulhi, // 'mulhi' 3-operand - m32rx_mullo, // 'mullo' 3-operand - m32rx_mulwhi, // 'mulwhi' 3-operand - m32rx_mulwlo, // 'mulwlo' 3-operand - m32rx_mvfachi, // 'mvfachi' 3-operand - m32rx_mvfaclo, // 'mvfaclo' 3-operand - m32rx_mvfacmi, // 'mvfacmi' 3-operand - m32rx_mvtachi, // 'mvtachi' 3-operand - m32rx_mvtaclo, // 'mvtaclo' 3-operand - m32rx_rac, // 'rac' 3 operand - m32rx_rach, // 'rach' 3 operand - m32rx_satb, - m32rx_sath, - m32rx_sat, - m32rx_pcmpbz, - m32rx_sadd, - m32rx_macwu1, - m32rx_msblo, - m32rx_mulwu1, - m32rx_maclh1, - m32rx_sc, - m32rx_snc, - -// Floating point - m32r_fadd, // Floating-point add - m32r_fsub, // Floating-point subtract - m32r_fmul, // Floating-point multiply - m32r_fdiv, // Floating-point divede - m32r_fmadd, // Floating-point multiply and add - m32r_fmsub, // Floating-point multiply and subtract - m32r_itof, // Integer to float - m32r_utof, // Unsigned integer to float - m32r_ftoi, // Float to integer - m32r_ftos, // Float to short - m32r_fcmp, // Floating-point compare - m32r_fcmpe, // Floating-point compare with exeption if unordered -// Bit Operation Instructions - m32r_bset, // Bit set - m32r_bclr, // Bit clear - m32r_btst, // Bit test - m32r_setpsw, // Set PSW - m32r_clrpsw, // Clear PSW - - m32r_last -}; - - - - - -enum -{ - m740_null = 0, // null instruction - m740_adc, // add with carry - m740_and, // logical and - m740_asl, // arithmetic shift left - m740_bbc, // branch on bit clear - m740_bbs, // branch on bit set - m740_bcc, // branch on carry clear - m740_bcs, // branch on carry set - m740_beq, // branch on equal - m740_bit, // test bit in memory with accumulator - m740_bmi, // branch on result minus - m740_bne, // branch on not equal - m740_bpl, // branch on result plus - m740_bra, // branch always - m740_brk, // force break - m740_bvc, // branch on overflow clear - m740_bvs, // branch on overflow set - m740_clb, // clear bit - m740_clc, // clear carry flag - m740_cld, // clear decimal mode - m740_cli, // clear interrupt disable status - m740_clt, // clear transfer flag - m740_clv, // clear overflow flag - m740_cmp, // compare - m740_com, // complement - m740_cpx, // compare memory and index register X - m740_cpy, // compare memory and index register Y - m740_dec, // decrement by one - m740_dex, // decrement index register X by one - m740_dey, // decrement index register Y by one - m740_div, // divide memory by accumulator - m740_eor, // exclusive or memory with accumulator - m740_inc, // increment by one - m740_inx, // increment index register X by one - m740_iny, // increment index register Y by one - m740_jmp, // jump - m740_jsr, // jump to subroutine - m740_lda, // load accumulator with memory - m740_ldm, // load immediate data to memory - m740_ldx, // load index register X from memory - m740_ldy, // load index register Y from memory - m740_lsr, // logical shift right - m740_mul, // multiply accumulator and memory - m740_nop, // no operation - m740_ora, // or memory with accumulator - m740_pha, // push accumulator on stack - m740_php, // push processor status on stack - m740_pla, // pull accumulator from stack - m740_plp, // pull processor status from stack - m740_rol, // rotate one bit left - m740_ror, // rotate one bit right - m740_rrf, // rotate right of four bits - m740_rti, // return from interrupt - m740_rts, // return from subroutine - m740_sbc, // subtract with carry - m740_seb, // set bit - m740_sec, // set carry flag - m740_sed, // set decimal mode - m740_sei, // set interrupt disable flag - m740_set, // set transfert flag - m740_sta, // store accumulator in memory - m740_stp, // stop - m740_stx, // store index register X in memory - m740_sty, // store index register Y in memory - m740_tax, // transfert accumulator to index register X - m740_tay, // transfert accumulator to index register Y - m740_tst, // test for negative or zero - m740_tsx, // transfert stack pointer to index register X - m740_txa, // transfert index register X to accumulator - m740_txs, // transfert index register X to stack pointer - m740_tya, // transfert index register Y to accumulator - m740_wit, // wait - - m740_last -}; - - - - - -enum -{ - // 7700 : - - m7700_null = 0, // null instruction - m7700_adc, // addition with carry - m7700_and, // logical AND - m7700_asl, // arithmetic shift left - m7700_bbc, // branch on bit clear - m7700_bbs, // branch on bit set - m7700_bcc, // branch on carry clear - m7700_bcs, // branch on carry set - m7700_beq, // branch on equal - m7700_bmi, // branch on result minus - m7700_bne, // branch on not equal - m7700_bpl, // branch on result plus - m7700_bra, // branch always - m7700_brk, // force break - m7700_bvc, // branch on overflow clear - m7700_bvs, // branch on overflow set - m7700_clb, // clear bit - m7700_clc, // clear carry flag - m7700_cli, // clear interrupt disable status - m7700_clm, // clear m flag - m7700_clp, // clear processor status - m7700_clv, // clear overflow flag - m7700_cmp, // compare - m7700_cpx, // compare memory and index register X - m7700_cpy, // compare memory and index register Y - m7700_dec, // decrement by one - m7700_dex, // decrement index register X by one - m7700_dey, // decrement index register Y by one - m7700_div, // divide - m7700_eor, // exclusive OR memory with accumulator - m7700_inc, // increment by one - m7700_inx, // increment index register X by one - m7700_iny, // increment index register Y by one - m7700_jmp, // jump - m7700_jsr, // jump to subroutine - m7700_lda, // load accumulator from memory - m7700_ldm, // load immediate to memory - m7700_ldt, // load immediate to data bank register - m7700_ldx, // load index register X from memory - m7700_ldy, // load index register Y from memory - m7700_lsr, // logical shift right - m7700_mpy, // multiply - m7700_mvn, // move negative - m7700_mvp, // move positive - m7700_nop, // no operation - m7700_ora, // OR memory with accumulator - m7700_pea, // push effective address - m7700_pei, // push effective indirect address - m7700_per, // push effective program counter relative address - m7700_pha, // push accumulator A on stack - m7700_phb, // push accumulator B on stack - m7700_phd, // push direct page register on stack - m7700_phg, // push program bank register on stack - m7700_php, // push processor status on stack - m7700_pht, // push data bank register on stack - m7700_phx, // push index register X on stack - m7700_phy, // push index register Y on stack - m7700_pla, // pull accumulator A from stack - m7700_plb, // pull accumulator B from stack - m7700_pld, // pull direct page register from stack - m7700_plp, // pull processor status from stack - m7700_plt, // pull data bank register from stack - m7700_plx, // pull index register X from stack - m7700_ply, // pull index register Y from stack - m7700_psh, // push - m7700_pul, // pull - m7700_rla, // rotate left accumulator A - m7700_rol, // rotate one bit left - m7700_ror, // rotate one bit right - m7700_rti, // return from interrupt - m7700_rtl, // return from subroutine long - m7700_rts, // return from subroutine - m7700_sbc, // subtract with carry - m7700_seb, // set bit - m7700_sec, // set carry flag - m7700_sei, // set interrupt disable status - m7700_sem, // set m flag - m7700_sep, // set processor status - m7700_sta, // store accumulator in memory - m7700_stp, // stop - m7700_stx, // store index register X in memory - m7700_sty, // store index register Y in memory - m7700_tad, // transfer accumulator A to direct page register - m7700_tas, // transfer accumulator A to stack pointer - m7700_tax, // transfer accumulator A to index register X - m7700_tay, // transfer accumulator A to index register Y - m7700_tbd, // transfer accumulator B to direct page register - m7700_tbs, // transfer accumulator B to stack pointer - m7700_tbx, // transfer accumulator B to index register X - m7700_tby, // transfer accumulator B to index register Y - m7700_tda, // transfer direct page register to accumulator A - m7700_tdb, // transfer direct page register to accumulator B - m7700_tsa, // transfer stack pointer to accumulator A - m7700_tsb, // transfer stack pointer to accumulator B - m7700_tsx, // transfer stack pointer to index register X - m7700_txa, // transfer index register X to accumulator A - m7700_txb, // transfer index register X to accumulator B - m7700_txs, // transfer index register X to stack pointer - m7700_txy, // transfer index register X to Y - m7700_tya, // transfer index register Y to accumulator A - m7700_tyb, // transfer index register Y to accumulator B - m7700_tyx, // transfer index register Y to X - m7700_wit, // wait - m7700_xab, // exchange accumulator A and B - - // 7750 : - - m7750_asr, // arithmetic shift right - m7750_divs, // divide with sign - m7750_exts, // extention with sign - m7750_extz, // extention zero - m7750_mpys, // multiply with sign - - m7700_last -}; - - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * MITSUBISHI 7900 Family - */ - - - -enum -{ -m7900_null = 0, // Unknown Operation - - -m7900_abs, // ABSolute -m7900_absd, // ABSolute at Double-word - -m7900_adc, // ADd with Carry -m7900_adcb, // ADd with Carry at Byte -m7900_adcd, // ADd with Carry at Double-word - -m7900_add, // Addition - -m7900_addb, // ADD at Byte -m7900_addd, // ADD at Double-word -m7900_addm, // ADD immediate and Memory -m7900_addmb, // ADD immediate and Memory at Byte -m7900_addmd, // ADD immediate and Memory at Double-word -m7900_adds, // ADD Stack pointer and immediate -m7900_addx, // ADD index register X and immediate -m7900_addy, // ADD index register Y and immediate - -m7900_and, // Logical AND -m7900_andb, // logical AND between immediate (Byte) - -m7900_andm, // logical AND between immediate value and Memory -m7900_andmb, // logical AND between immediate value and Memory (Byte) -m7900_andmd, // logical AND between immediate value and Memory (Double word) - -m7900_asl, // Arithmetic Shift to Left -m7900_asln, // Arithmetic Shift to Left by n bits -m7900_asldn, // Arithmetic Shift to Left by n bits (Double word) - - -m7900_asr, // Arithmeticshift to the right -m7900_asrn, // Arithmetic Shift to Right by n bits -m7900_asrdn, //Arithmetic Shift to Right by n bits (Double word) - -m7900_bbc, // Branch on Bit Clear -m7900_bbcb, // Branch on Bit Clear (Byte) -m7900_bbs, // Branch on Bit Set -m7900_bbsb, // Branch on Bit Set (Byte) - -m7900_bcc, // Branch on Carry Clear -m7900_bcs, // Branch on Carry Set -m7900_beq, // Branch on EQual -m7900_bge, // Branch on Greater or Equal -m7900_bgt, // Branch on Greater Than -m7900_bgtu, // Branch on Greater Than with Unsign -m7900_ble, // Branch on Less or Equal -m7900_bleu, // Branch on Less Equal with Unsign -m7900_blt, // Branch on Less Than -m7900_bmi, // Branch on result MInus -m7900_bne, // Branch on Not Equal -m7900_bpl, // Branch on result PLus -m7900_bra, // BRanch Always -m7900_bral, // BRanch Always - -m7900_brk, // force BReaK - -m7900_bsc, // Branch on Single bit Clear -m7900_bsr, // Branch to SubRoutine -m7900_bss, // Branch on Single bit Set - -m7900_bvc, // Branch on oVerflow Clear -m7900_bvs, // Branch on oVerflow Set - -m7900_cbeq, // Compare immediate and Branch on EQual -m7900_cbeqb, // Compare immediate and Branch on EQual at Byte -m7900_cbne, // Compare immediate and Branch on Not Equal -m7900_cbneb, // Compare immediate and Branch on Not Equal at Byte - -m7900_clc, // CLear Carry flag -m7900_cli, // CLear Interrupt disable status -m7900_clm, // CLear M flag -m7900_clp, // CLear Processor status - -m7900_clr, // CLeaR accumulator -m7900_clrb, // CLeaR accumulator at Byte -m7900_clrm, // CLeaR Memory -m7900_clrmb, // CLeaR Memory at Byte -m7900_clrx, // CLeaR index register X -m7900_clry, // CLeaR index register Y - -m7900_clv, // CLear oVerflow flag - -m7900_cmp, // CoMPare -m7900_cmpb, // CoMPare at Byte -m7900_cmpd, // CoMPare at Double-word -m7900_cmpm, // CoMPare immediate with Memory -m7900_cmpmb, // CoMPare immediate with Memory at Byte -m7900_cmpmd, // CoMPare immediate with Memory at Double-word - -m7900_cpx, // ComPare memory and index register X -m7900_cpy, // ComPare memory and index register Y - -m7900_debne, // DEcrement memory and Branch on Not Equal - -m7900_dec, // DECrement by one -m7900_dex, // DEcrement index register X by one -m7900_dey, // DEcrement index register Y by one - -m7900_div, // DIVide unsigned -m7900_divs, // DIVide with Sign -m7900_dxbne, // Decrement index register X and Branch on Not Equal -m7900_dybne, // Decrement index register Y and Branch on Not Equal - -m7900_eor, // Exclusive OR memory with accumulator -m7900_eorb, // Exclusive OR immediate with accumulator at Byte -m7900_eorm, // Exclusive OR immediate with Memory -m7900_eormb, // Exclusive OR immediate with Memory at Byte -m7900_eormd, // Exclusive OR immediate with Memory at Double-word - -m7900_exts, // EXTension Sign -m7900_extsd, // EXTension Sign at Double-word -m7900_extz, // EXTension Zero -m7900_extzd, // EXTension Zero at Double-word - -m7900_inc, // INCrement by one -m7900_inx, // INcrement index register X by one -m7900_iny, // INcrement index register y by one - -m7900_jmp, // Jump -m7900_jmpl, // Jump - -m7900_jsr, // Jump to SubRoutine -m7900_jsrl, // Jump to SubRoutine - - -m7900_lda, // LoaD Accumulator from memory -m7900_ldab, // LoaD Accumulator from memory at Byte -m7900_ldad, // LoaD Accumulator from memory at Double-word -m7900_lddn, // LoaD immediate to Direct page register n - -m7900_ldt, // LoaD immediate to DaTa bank register -m7900_ldx, // LoaD index register X from memory -m7900_ldxb, // LoaD index register X from memory at Byte -m7900_ldy, // LoaD index register Y from memory -m7900_ldyb, // LoaD index register Y from memory at Byte - -m7900_lsr, // Logical Shift Right -m7900_lsrn, // Logical n bits Shift Right -m7900_lsrdn, // Logical n bits Shift Right at Double-word - -m7900_movm, // MOVe Memory to memory -m7900_movmb, // MOVe Memory to memory at Byte -m7900_movr, // MOVe Repeat memory to memory -m7900_movrb, // MOVe Repeat memory to memory at Byte - -m7900_mpy, // MultiPlY -m7900_mpys, // MultiPlY with Sign - -m7900_mvn, // MoVe Negative -m7900_mvp, // MoVe Positive - -m7900_neg, // NEGative -m7900_negd, // NEGative at Double-word - -m7900_nop, // No OPeration - -m7900_ora, // OR memory with Accumulator -m7900_orab, // OR immediate with Accumulator at Byte -m7900_oram, // OR immediAte with Memory -m7900_oramb, // OR immediAte with Memory at Byte -m7900_oramd, // OR immediAte with Memory at Double-word - -m7900_pea, // Push Effective Address -m7900_pei, // Push Effective Indirect address -m7900_per, // Push Effective program counter Relative address -m7900_pha, // PusH accumulator A on stack -m7900_phb, // PusH accumulator B on stack -m7900_phd, // PusH Direct page register on stack -m7900_phdn, // PusH Direct page register n on stack -m7900_phg, // PusH proGram bank register on stack - -m7900_phldn, // PusH dpr n to stack and Load immediate to Dpr n - -m7900_php, // PusH Processor status on stack -m7900_pht, // PusH daTa bank register on stack -m7900_phx, // PusH index register X on stack -m7900_phy, // PusH index register Y on stack - -m7900_pla, // PuLl accumulator A from stack -m7900_plb, // PuLl accumulator B from stack -m7900_pld, // PuLl Direct page register from stack -m7900_pldn, // PuLl Direct page register n from stack -m7900_plp, // PuLl Processor status from stack -m7900_plt, // PuLl daTa bank register from stack -m7900_plx, // PuLl index register X from stack -m7900_ply, // PuLl index register Y from stack - -m7900_psh, // PuSH -m7900_pul, // PuLl - -m7900_rla, // Rotate Left accumulator A -m7900_rmpa, // Repeat Multiply and Accumulate - -m7900_rol, // ROtate one bit Left -m7900_roln, // n bits ROtate Left - -m7900_roldn, // n bits ROtate Left at Double-word - -m7900_ror, // ROtate one bit Right -m7900_rorn, // n bits ROtate Right -m7900_rordn, // n bits ROtate Right at Double-word - -m7900_rti, // Return from Interrupt -m7900_rtl, // ReTurn from subroutine Long -m7900_rtld, // ReTurn from subroutine Long and pull Direct page register n -m7900_rts, // ReTurn from Subroutine -m7900_rtsdn, // ReTurn from Subroutine and pull Direct page register n - - -m7900_sbc, // SuBtract with Carry -m7900_sbcb, // SuBtract with Carry at Byte -m7900_sbcd, // SuBtract with Carry at Double-word - - -m7900_sec, // SEt Carry flag -m7900_sei, // SEt Interrupt disable status -m7900_sem, // SEt M flag -m7900_sep, // SEt Processor status - - -m7900_sta, // STore Accumulator in memory -m7900_stab, // STore Accumulator in memory at Byte -m7900_stad, // STore Accumulator in memory at Double-word - - -m7900_stp, // SToP -m7900_stx, // STore index register X in memory -m7900_sty, // STore index register Y in memory - -m7900_sub, // SUBtract -m7900_subb, // SUBtract at Byte -m7900_subd, // SUBtract at Double-word -m7900_subm, // SUBtract immediate from Memory -m7900_submb, // SUBtract immediate from Memory at Byte -m7900_submd, // SUBtract immediate from Memory at Double-word -m7900_subs, // SUBtract Stack pointer -m7900_subx, // SUBtract immediate from index register X -m7900_suby, // SUBtract immediate from index register Y - - - -m7900_tadn, // Transfer accumulator A to Direct page register n - - -m7900_tas, // Transfer accumulator A to Stack pointer -m7900_tax, // Transfer accumulator A to index register X -m7900_tay, // Transfer accumulator A to index register Y - -m7900_tbdn, // Transfer accumulator B to Direct page register n - -m7900_tbs, // Transfer accumulator B to Stack pointer -m7900_tbx, // Transfer accumulator B to index register X -m7900_tby, // Transfer accumulator B to index register Y - -m7900_tdan, // Transfer Direct page register n to accumulator A -m7900_tdbn, // Transfer Direct page register n to accumulator B - -m7900_tds, // Transfer Direct page register to Stack pointer - - -m7900_tsa, // Transfer Stack pointer to accumulator A -m7900_tsb, // Transfer Stack pointer to accumulator B -m7900_tsd, // Transfer Stack pointer to Direct page register -m7900_tsx, // Transfer Stack pointer to index register X -m7900_txa, // Transfer index register X to accumulator A -m7900_txb, // Transfer index register X to accumulator B -m7900_txs, // Transfer index register X to Stack pointer -m7900_txy, // Transfer index register X to Y -m7900_tya, // Transfer index register Y to accumulator A -m7900_tyb, // Transfer index register Y to accumulator B -m7900_tyx, // Transfer index register Y to X - -m7900_wit, // WaIT - -m7900_xab, // eXchange accumulator A and B - -m7900_last // - - }; - - - - -enum -{ - st9_null = 0, // Unknown Operation. - st9_ld, // Load. - st9_ldw, // Load word. - st9_ldpp, // Load (using CSR) => (using CSR). - st9_ldpd, // Load (using DPRx) => (using CSR). - st9_lddp, // Load (using CSR) => (using DPRx). - st9_lddd, // Load (using DPRx) => (using DPRx). - st9_add, // Add. - st9_addw, // Add Word. - st9_adc, // Add with Carry. - st9_adcw, // Add Word with Carry. - st9_sub, // Substract. - st9_subw, // Substract Word. - st9_sbc, // Substract with Carry. - st9_sbcw, // Substract Word with Carry. - st9_and, // Logical AND. - st9_andw, // Logical Word AND. - st9_or, // Logical OR. - st9_orw, // Logical Word OR. - st9_xor, // Logical Exclusive OR. - st9_xorw, // Logical Word Exclusive OR. - st9_cp, // Compare. - st9_cpw, // Compare Word. - st9_tm, // Test under Mask. - st9_tmw, // Test Word under Mask. - st9_tcm, // Test Complement under Mask. - st9_tcmw, // Test Word Complement under Mask. - st9_inc, // Increment. - st9_incw, // Increment Word. - st9_dec, // Decrement. - st9_decw, // Decrement Word. - st9_sla, // Shift Left Arithmetic. - st9_slaw, // Shift Word Left Arithmetic. - st9_sra, // Shift Right Arithmetic. - st9_sraw, // Shift Word Right Arithmetic. - st9_rrc, // Rotate Right through Carry. - st9_rrcw, // Rotate Word Right through Carry. - st9_rlc, // Rotate Left through Carry. - st9_rlcw, // Rotate Word Left through Carry. - st9_ror, // Rotate Right. - st9_rol, // Rotate Left. - st9_clr, // Clear Register. - st9_cpl, // Complement Register. - st9_swap, // Swap Nibbles. - st9_da, // Decimal ajust. - st9_push, // Push on System Stack. - st9_pushw, // Push Word on System Stack. - st9_pea, // Push Effective Address on System Stack. - st9_pop, // Pop from System Stack. - st9_popw, // Pop Word from System Stack. - st9_pushu, // Push on User Stack. - st9_pushuw, // Push Word on User Stack. - st9_peau, // Push Effective Address on User Stack. - st9_popu, // Pop from User Stack. - st9_popuw, // Pop Word from User Stack. - st9_link, // Move System Stack Pointer upward; support for high-level language. - st9_unlink, // Move System Stack Pointer backward; support for high-level language. - st9_linku, // Move User Stack Pointer upward; support for high-level language. - st9_unlinku, // Move User Stack Pointer backward; support for high-level language. - st9_mul, // Multiply 8x8. - st9_div, // Divide 8x8. - st9_divws, // Divide Word Stepped 32/16. - st9_bset, // Bit Set. - st9_bres, // Bit Reset . - st9_bcpl, // Bit Complement. - st9_btset, // Bit Test and Set. - st9_bld, // Bit Load. - st9_band, // Bit AND. - st9_bor, // Bit OR. - st9_bxor, // Bit XOR. - st9_ret, // Return from Subroutine. - st9_rets, // Inter-segment Return to Subroutine. - st9_iret, // Return from Interrupt. - st9_jrcc, // Jump Relative if Condition ``cc'' is Met. - st9_jpcc, // Jump if Condition ``cc'' is Met. - st9_jp, // Unconditional Jump. - st9_jps, // Unconditional Inter-segment Jump. - st9_call, // Unconditional Call. - st9_calls, // Inter-segment Call to Subroutine. - st9_btjf, // Bit Test and Jump if False. - st9_btjt, // Bit Test and Jump if True. - st9_djnz, // Decrement a Working Register and Jump if Non Zero. - st9_dwjnz, // Decrement a Register Pair and Jump if Non Zero. - st9_cpjfi, // Compare and Jump on False. Otherwise Post Increment. - st9_cpjti, // Compare and Jump on True. Otherwise Post Increment. - st9_xch, // Exchange Registers. - st9_srp, // Set Register Pointer Long (16 working registers). - st9_srp0, // Set Register Pointer 0 (8 LSB working registers). - st9_srp1, // Set Register Pointer 1 (8 MSB working registers). - st9_spp, // Set Page Pointer. - st9_ext, // Sign Extend. - st9_ei, // Enable Interrupts. - st9_di, // Disable Interrupts. - st9_scf, // Set Carry Flag. - st9_rcf, // Reset Carry Flag. - st9_ccf, // Complement Carry Flag. - st9_spm, // Select Extended Memory addressing scheme through CSR Register. - st9_sdm, // Select Extended Memory addressing scheme through DPR Registers. - st9_nop, // No Operation. - st9_wfi, // Stop Program Execution and Wait for the next Enable Interrupt. - st9_halt, // Stop Program Execution until System Reset. - st9_etrap, // Undocumented instruction. - st9_eret, // Undocumented instruction. - st9_ald, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED. - st9_aldw, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED. - st9_last -}; - - - - - -enum -{ - fr_null = 0, // null instruction - - fr_add, // add word data of source register / 4-bit immediate data to destination register - fr_add2, // add 4-bit immediate data to destination register - fr_addc, // add word data of source register and carry bit to destination register - fr_addn, // add word data of source register / immediate data to destination register - fr_addn2, // add immediate data to destination register - fr_sub, // subtract word data in source register from destination register - fr_subc, // subtract word data in source register and carry bit from destination register - fr_subn, // subtract word data in source register from destination register - fr_cmp, // compare word / immediate data in source register and destination register - fr_cmp2, // compare immediate data and destination register - fr_and, // and word data of source register to destination register / data in memory - fr_andh, // and half-word data of source register to data in memory - fr_andb, // and byte data of source register to data in memory - fr_or, // or word data of source register to destination register / data in memory - fr_orh, // or half-word data of source register to data in memory - fr_orb, // or byte data of source register to data in memory - fr_eor, // exclusive or word data of source register to destination register / data in memory - fr_eorh, // exclusive or half-word data of source register to data in memory - fr_eorb, // exclusive or byte data of source register to data in memory - fr_bandl, // and 4-bit immediate data to lower 4 bits of byte data in memory - fr_bandh, // and 4-bit immediate data to higher 4 bits of byte data in memory - fr_borl, // or 4-bit immediate data to lower 4 bits of byte data in memory - fr_borh, // or 4-bit immediate data to higher 4 bits of byte data in memory - fr_beorl, // eor 4-bit immediate data to lower 4 bits of byte data in memory - fr_beorh, // eor 4-bit immediate data to higher 4 bits of byte data in memory - fr_btstl, // test lower 4 bits of byte data in memory - fr_btsth, // test higher 4 bits of byte data in memory - fr_mul, // multiply word data - fr_mulu, // multiply unsigned word data - fr_mulh, // multiply half-word data - fr_muluh, // multiply unsigned half-word data - fr_div0s, // initial setting up for signed division - fr_div0u, // initial setting up for unsigned division - fr_div1, // main process of division - fr_div2, // correction when remainder is 0 - fr_div3, // correction when remainder is 0 - fr_div4s, // correction answer for signed division - fr_lsl, // logical shift to the left direction - fr_lsl2, // logical shift to the left direction - fr_lsr, // logical shift to the right direction - fr_lsr2, // logical shift to the right direction - fr_asr, // arithmetic shift to the right direction - fr_asr2, // arithmetic shift to the right direction - fr_ldi_32, // load immediate 32-bit data to destination register - fr_ldi_20, // load immediate 20-bit data to destination register - fr_ldi_8, // load immediate 8-bit data to destination register - fr_ld, // load word data in memory to register / program status register - fr_lduh, // load half-word data in memory to register - fr_ldub, // load byte data in memory to register - fr_st, // store word data in register / program status register to memory - fr_sth, // store half-word data in register to memory - fr_stb, // store byte data in register to memory - fr_mov, // move word data in source register / program status register to destination register / program status register - fr_jmp, // jump - fr_call, // call subroutine - fr_ret, // return from subroutine - fr_int, // software interrupt - fr_inte, // software interrupt for emulator - fr_reti, // return from interrupt - fr_bra, // branch relative if condition satisfied - fr_bno, // branch relative if condition satisfied - fr_beq, // branch relative if condition satisfied - fr_bne, // branch relative if condition satisfied - fr_bc, // branch relative if condition satisfied - fr_bnc, // branch relative if condition satisfied - fr_bn, // branch relative if condition satisfied - fr_bp, // branch relative if condition satisfied - fr_bv, // branch relative if condition satisfied - fr_bnv, // branch relative if condition satisfied - fr_blt, // branch relative if condition satisfied - fr_bge, // branch relative if condition satisfied - fr_ble, // branch relative if condition satisfied - fr_bgt, // branch relative if condition satisfied - fr_bls, // branch relative if condition satisfied - fr_bhi, // branch relative if condition satisfied - fr_dmov, // move word data from register / address to register / address - fr_dmovh, // move half-word data from register / address to register / address - fr_dmovb, // move byte data from register / address to register / address - fr_ldres, // load word data in memory to resource - fr_stres, // store word data in resource to memory - fr_copop, // coprocessor operation - fr_copld, // load 32-bit data from register to coprocessor register - fr_copst, // store 32-bit data from coprocessor register to register - fr_copsv, // save 32-bit data from coprocessor register to register - fr_nop, // no operation - fr_andccr, // and condition code register and immediate data - fr_orccr, // or condition code register and immediate data - fr_stilm, // set immediate data to interrupt level mask register - fr_addsp, // add stack pointer and immediate data - fr_extsb, // sign extend from byte data to word data - fr_extub, // unsign extend from byte data to word data - fr_extsh, // sign extend from byte data to word data - fr_extuh, // unsigned extend from byte data to word data - fr_ldm0, // load multiple registers - fr_ldm1, // load multiple registers - fr_stm0, // store multiple registers - fr_stm1, // store multiple registers - fr_enter, // enter function - fr_leave, // leave function - fr_xchb, // exchange byte data - fr_last // last instruction -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ -ALPHA_null = 0, // Unknown Operation - -ALPHA_addf, // Add F_floating -ALPHA_addg, // Add G_floating -ALPHA_addl, // Add longword -ALPHA_addl_v, // Add longword with overflow -ALPHA_addq, // Add quadword -ALPHA_addq_v, // Add quadword with overflow -ALPHA_adds, // Add S_floating -ALPHA_addt, // Add T_floating -ALPHA_amask, // Architecture mask -ALPHA_and, // Logical product -ALPHA_beq, // Branch if = zero -ALPHA_bge, // Branch if >= zero -ALPHA_bgt, // Branch if > zero -ALPHA_bic, // Bit clear -ALPHA_bis, // Logical sum -ALPHA_blbc, // Branch if low bit clear -ALPHA_blbs, // Branch if low bit set -ALPHA_ble, // Branch if <= zero -ALPHA_blt, // Branch if < zero -ALPHA_bne, // Branch if != zero -ALPHA_br, // Unconditional branch -ALPHA_bsr, // Branch to subroutine -ALPHA_call_pal, // Trap to PALcode -ALPHA_cmoveq, // CMOVE if = zero -ALPHA_cmovge, // CMOVE if >= zero -ALPHA_cmovgt, // CMOVE if > zero -ALPHA_cmovlbc, // CMOVE if low bit clear -ALPHA_cmovlbs, // CMOVE if low bit set -ALPHA_cmovle, // CMOVE if <= zero -ALPHA_cmovlt, // CMOVE if < zero -ALPHA_cmovne, // CMOVE if != zero -ALPHA_cmpbge, // Compare byte -ALPHA_cmpeq, // Compare signed quadword equal -ALPHA_cmpgeq, // Compare G_floating equal -ALPHA_cmpgle, // Compare G_floating less than or equal -ALPHA_cmpglt, // Compare G_floating less than -ALPHA_cmple, // Compare signed quadword less than or equal -ALPHA_cmplt, // Compare signed quadword less than -ALPHA_cmpteq, // Compare T_floating equal -ALPHA_cmptle, // Compare T_floating less than or equal -ALPHA_cmptlt, // Compare T_floating less than -ALPHA_cmptun, // Compare T_floating unordered -ALPHA_cmpule, // Compare unsigned quadword less than or equal -ALPHA_cmpult, // Compare unsigned quadword less than -ALPHA_cpys, // Copy sign -ALPHA_cpyse, // Copy sign and exponent -ALPHA_cpysn, // Copy sign negate -ALPHA_ctlz, // Count leading zero -ALPHA_ctpop, // Count population -ALPHA_cttz, // Count trailing zero -ALPHA_cvtdg, // Convert D_floating to G_floating -ALPHA_cvtgd, // Convert G_floating to D_floating -ALPHA_cvtgf, // Convert G_floating to F_floating -ALPHA_cvtgq, // Convert G_floating to quadword -ALPHA_cvtlq, // Convert longword to quadword -ALPHA_cvtqf, // Convert quadword to F_floating -ALPHA_cvtqg, // Convert quadword to G_floating -ALPHA_cvtql, // Convert quadword to longword -ALPHA_cvtqs, // Convert quadword to S_floating -ALPHA_cvtqt, // Convert quadword to T_floating -ALPHA_cvtst, // Convert S_floating to T_floating -ALPHA_cvttq, // Convert T_floating to quadword -ALPHA_cvtts, // Convert T_floating to S_floating -ALPHA_divf, // Divide F_floating -ALPHA_divg, // Divide G_floating -ALPHA_divs, // Divide S_floating -ALPHA_divt, // Divide T_floating -ALPHA_ecb, // Evict cache block -ALPHA_eqv, // Logical equivalence -ALPHA_excb, // Exception barrier -ALPHA_extbl, // Extract byte low -ALPHA_extlh, // Extract longword high -ALPHA_extll, // Extract longword low -ALPHA_extqh, // Extract quadword high -ALPHA_extql, // Extract quadword low -ALPHA_extwh, // Extract word high -ALPHA_extwl, // Extract word low -ALPHA_fbeq, // Floating branch if = zero -ALPHA_fbge, // Floating branch if >= zero -ALPHA_fbgt, // Floating branch if > zero -ALPHA_fble, // Floating branch if <= zero -ALPHA_fblt, // Floating branch if < zero -ALPHA_fbne, // Floating branch if != zero -ALPHA_fcmoveq, // FCMOVE if = zero -ALPHA_fcmovge, // FCMOVE if >= zero -ALPHA_fcmovgt, // FCMOVE if > zero -ALPHA_fcmovle, // FCMOVE if <= zero -ALPHA_fcmovlt, // FCMOVE if < zero -ALPHA_fcmovne, // FCMOVE if != zero -ALPHA_fetch, // Prefetch data -ALPHA_fetch_m, // Prefetch data, modify intent -ALPHA_ftois, // Floating to integer move, S_floating -ALPHA_ftoit, // Floating to integer move, T_floating -ALPHA_implver, // Implementation version -ALPHA_insbl, // Insert byte low -ALPHA_inslh, // Insert longword high -ALPHA_insll, // Insert longword low -ALPHA_insqh, // Insert quadword high -ALPHA_insql, // Insert quadword low -ALPHA_inswh, // Insert word high -ALPHA_inswl, // Insert word low -ALPHA_itoff, // Integer to floating move, F_floating -ALPHA_itofs, // Integer to floating move, S_floating -ALPHA_itoft, // Integer to floating move, T_floating -ALPHA_jmp, // Jump -ALPHA_jsr, // Jump to subroutine -ALPHA_jsr_coroutine,// Jump to subroutine return -ALPHA_lda, // Load address -ALPHA_ldah, // Load address high -ALPHA_ldbu, // Load zero-extended byte -ALPHA_ldwu, // Load zero-extended word -ALPHA_ldf, // Load F_floating -ALPHA_ldg, // Load G_floating -ALPHA_ldl, // Load sign-extended longword -ALPHA_ldl_l, // Load sign-extended longword locked -ALPHA_ldq, // Load quadword -ALPHA_ldq_l, // Load quadword locked -ALPHA_ldq_u, // Load unaligned quadword -ALPHA_lds, // Load S_floating -ALPHA_ldt, // Load T_floating -ALPHA_maxsb8, // Vector signed byte maximum -ALPHA_maxsw4, // Vector signed word maximum -ALPHA_maxub8, // Vector unsigned byte maximum -ALPHA_maxuw4, // Vector unsigned word maximum -ALPHA_mb, // Memory barrier -ALPHA_mf_fpcr, // Move from FPCR -ALPHA_minsb8, // Vector signed byte minimum -ALPHA_minsw4, // Vector signed word minimum -ALPHA_minub8, // Vector unsigned byte minimum -ALPHA_minuw4, // Vector unsigned word minimum -ALPHA_mskbl, // Mask byte low -ALPHA_msklh, // Mask longword high -ALPHA_mskll, // Mask longword low -ALPHA_mskqh, // Mask quadword high -ALPHA_mskql, // Mask quadword low -ALPHA_mskwh, // Mask word high -ALPHA_mskwl, // Mask word low -ALPHA_mt_fpcr, // Move to FPCR -ALPHA_mulf, // Multiply F_floating -ALPHA_mulg, // Multiply G_floating -ALPHA_mull, // Multiply longword -ALPHA_mull_v, // Multiply longword with overflow -ALPHA_mulq, // Multiply quadword -ALPHA_mulq_v, // Multiply quadword with overflow -ALPHA_muls, // Multiply S_floating -ALPHA_mult, // Multiply T_floating -ALPHA_ornot, // Logical sum with complement -ALPHA_perr, // Pixel error -ALPHA_pklb, // Pack longwords to bytes -ALPHA_pkwb, // Pack words to bytes -ALPHA_rc, // Read and clear -ALPHA_ret, // Return from subroutine -ALPHA_rpcc, // Read process cycle counter -ALPHA_rs, // Read and set -ALPHA_s4addl, // Scaled add longword by 4 -ALPHA_s4addq, // Scaled add quadword by 4 -ALPHA_s4subl, // Scaled subtract longword by 4 -ALPHA_s4subq, // Scaled subtract quadword by 4 -ALPHA_s8addl, // Scaled add longword by 8 -ALPHA_s8addq, // Scaled add quadword by 8 -ALPHA_s8subl, // Scaled subtract longword by 8 -ALPHA_s8subq, // Scaled subtract quadword by 8 -ALPHA_sextb, // Sign extend byte -ALPHA_sextw, // Sign extend word -ALPHA_sll, // Shift left logical -ALPHA_sqrtf, // Square root F_floating -ALPHA_sqrtg, // Square root G_floating -ALPHA_sqrts, // Square root S_floating -ALPHA_sqrtt, // Square root T_floating -ALPHA_sra, // Shift right arithmetic -ALPHA_srl, // Shift right logical -ALPHA_stb, // Store byte -ALPHA_stf, // Store F_floating -ALPHA_stg, // Store G_floating -ALPHA_sts, // Store S_floating -ALPHA_stl, // Store longword -ALPHA_stl_c, // Store longword conditional -ALPHA_stq, // Store quadword -ALPHA_stq_c, // Store quadword conditional -ALPHA_stq_u, // Store unaligned quadword -ALPHA_stt, // Store T_floating -ALPHA_stw, // Store word -ALPHA_subf, // Subtract F_floating -ALPHA_subg, // Subtract G_floating -ALPHA_subl, // Subtract longword -ALPHA_subl_v, // Subtract longword with overflow -ALPHA_subq, // Subtract quadword -ALPHA_subq_v, // Subtract quadword with overflow -ALPHA_subs, // Subtract S_floating -ALPHA_subt, // Subtract T_floating -ALPHA_trapb, // Trap barrier -ALPHA_umulh, // Unsigned multiply quadword high -ALPHA_unpkbl, // Unpack bytes to longwords -ALPHA_unpkbw, // Unpack bytes to words -ALPHA_wh64, // Write hint 64 bytes -ALPHA_wmb, // Write memory barrier -ALPHA_xor, // Logical difference -ALPHA_zap, // Zero bytes -ALPHA_zapnot, // Zero bytes not - -// Macros - -ALPHA_unop, // Universal NOP -ALPHA_nop, // Integer NOP -ALPHA_fnop, // Floating point NOP -ALPHA_clr, // Clear -ALPHA_fabs, // Floating point absolute value -ALPHA_fclr, // Floating point clear -ALPHA_fmov, // Floating point register move -ALPHA_fneg, // Floating point negate -ALPHA_mov, // Move to register -ALPHA_negl, // Negate longword -ALPHA_negl_v, // Negate longword with overflow -ALPHA_negq, // Negate quadword -ALPHA_negq_v, // Negate quadword with overflow -ALPHA_negf, // Negate F_floating -ALPHA_negg, // Negate G_floating -ALPHA_negs, // Negate S_floating -ALPHA_negt, // Negate T_floating -ALPHA_not, // Bitwise NOT -ALPHA_sextl, // Move sign extended -ALPHA_or, // Bitwise OR -ALPHA_andnot, // Bit clear -ALPHA_xornot, // Logical equivalence -ALPHA_br0, // Branch - -ALPHA_last, - -}; - - - - -enum -{ -KR1878_null = 0, // Unknown Operation - -KR1878_mov, -KR1878_cmp, // Compare -KR1878_add, // Addition -KR1878_sub, // Subtract -KR1878_and, // Logical AND -KR1878_or, // Logical Inclusive OR -KR1878_xor, // Logical Exclusive OR - -KR1878_movl, -KR1878_cmpl, // Compare -KR1878_addl, // Addition -KR1878_subl, // Subtract -KR1878_bic, -KR1878_bis, -KR1878_btg, -KR1878_btt, - -KR1878_swap, -KR1878_neg, -KR1878_not, -KR1878_shl, // Shift Left -KR1878_shr, // Shift Right -KR1878_shra, // Arithmetic Shift Right -KR1878_rlc, // Rotate Left -KR1878_rrc, // Rotate Right -KR1878_adc, // Add with Carry -KR1878_sbc, // Subtract with Carry - -KR1878_ldr, -KR1878_mtpr, -KR1878_mfpr, -KR1878_push, -KR1878_pop, -KR1878_sst, -KR1878_cst, -KR1878_tof, -KR1878_tdc, - -KR1878_jmp, // Jump -KR1878_jsr, // Jump to Subroutine -KR1878_jnz, // Jump -KR1878_jz, // Jump -KR1878_jns, // Jump -KR1878_js, // Jump -KR1878_jnc, // Jump -KR1878_jc, // Jump -KR1878_ijmp, // Jump -KR1878_ijsr, // Jump to Subroutine -KR1878_rts, // Return from Subroutine -KR1878_rtsc, // Return from Subroutine -KR1878_rti, // Return from Interrupt - -KR1878_nop, // No Operation -KR1878_wait, -KR1878_stop, -KR1878_reset, -KR1878_sksp, - -KR1878_last, - -}; - - - - -enum -{ -AD218X_null = 0, // Unknown Operation -// AMF subcodes -AD218X_amf_01, // op = op * op (rnd) -AD218X_amf_03, // op = mr + op * op (rnd) -AD218X_amf_02, // op = mr - op * op (rnd) -AD218X_amf_04, // op = op * op (ss) -AD218X_amf_05, // op = op * op (su) -AD218X_amf_06, // op = op * op (us) -AD218X_amf_07, // op = op * op (uu) -AD218X_amf_08, // op = mr + op * op -AD218X_amf_09, // op = mr + op * op -AD218X_amf_0a, // op = mr + op * op -AD218X_amf_0b, // op = mr + op * op -AD218X_amf_0c, // op = mr - op * op -AD218X_amf_0d, // op = mr - op * op -AD218X_amf_0e, // op = mr - op * op -AD218X_amf_0f, // op = mr - op * op -AD218X_amf_10, // op = op -AD218X_amf_11, // op = op + 1 -AD218X_amf_12, // op = op + op + C -AD218X_amf_13, // op = op + op -AD218X_amf_14, // op = not op -AD218X_amf_15, // op = - op -AD218X_amf_16, // op = op - op + C - 1 -AD218X_amf_17, // op = op - op -AD218X_amf_18, // op = op - 1 -AD218X_amf_19, // op = op - op -AD218X_amf_1a, // op = op - op + C - 1 -AD218X_amf_1b, // op = not op -AD218X_amf_1c, // op = op and op -AD218X_amf_1d, // op = op or op -AD218X_amf_1e, // op = op xor op -AD218X_amf_1f, // op = abs op -// Shifter subcodes -AD218X_shft_0, // sr = lshift op (hi) -AD218X_shft_1, // sr = sr or lshift op (hi) -AD218X_shft_2, // sr = lshift op (lo) -AD218X_shft_3, // sr = sr or lshift op (lo) -AD218X_shft_4, // sr = ashift op (hi) -AD218X_shft_5, // sr = sr or ashift op (hi) -AD218X_shft_6, // sr = ashift op (lo) -AD218X_shft_7, // sr = sr or ashift op (lo) -AD218X_shft_8, // sr = norm op (hi) -AD218X_shft_9, // sr = sr or norm op (hi) -AD218X_shft_a, // sr = norm op (lo) -AD218X_shft_b, // sr = sr or norm op (lo) -AD218X_shft_c, // sr = exp op (hi) -AD218X_shft_d, // sr = exp op (hix) -AD218X_shft_e, // sr = exp op (lo) -AD218X_shft_f, // sr = expadj op -// ALU/MAC specific options -AD218X_alu_00, // op = op + op + C [IF COND] X + Const -AD218X_alu_01, // op = op + op -AD218X_alu_02, // op = op - op + C - 1 [IF COND] X - Const -AD218X_alu_03, // op = op - op -AD218X_alu_04, // op = op - op + C - 1 [IF COND] Const - X -AD218X_alu_05, // op = op - op -AD218X_alu_06, // op = op and op [IF COND] X and,or,xor Const -AD218X_alu_07, // op = op or op -AD218X_alu_08, // op = op xor op -AD218X_alu_09, // op = op [IF COND] PASS constant; constant <> 0,1, -1 -AD218X_alu_0a, // op = op + 1 -AD218X_alu_0b, // op = op - 1 -AD218X_alu_0c, // divq op ALU Type 23 -AD218X_alu_0d, // divs op, op ALU Type 24 -AD218X_alu_0e, // none = op ALU Type 9, with no result -AD218X_alu_0f, // none = op + 1 -AD218X_alu_10, // none = op + op + C -AD218X_alu_11, // none = op + op -AD218X_alu_12, // none = not op -AD218X_alu_13, // none = - op -AD218X_alu_14, // none = op - op + C - 1 -AD218X_alu_15, // none = op - op -AD218X_alu_16, // none = op - 1 -AD218X_alu_17, // none = op - op + C - 1 -AD218X_alu_18, // none = op - op -AD218X_alu_19, // none = not op -AD218X_alu_1a, // none = op and op -AD218X_alu_1b, // none = op or op -AD218X_alu_1c, // none = op xor op -AD218X_alu_1d, // none = abs op -AD218X_mac_0, // op = 0 [IF COND] MAC CLEAR -AD218X_mac_1, // op = mr (rnd) [IF COND] MAC TRANSFER -AD218X_mac_2, // op = op * op (ss) [IF COND] X * X -AD218X_mac_3, // op = op * op (uu) -AD218X_mac_4, // op = op * op (rnd) -AD218X_mac_5, // op = mr + op * op (ss) [IF COND] MR + X * X -AD218X_mac_6, // op = mr + op * op (uu) -AD218X_mac_7, // op = mr + op * op (rnd) -AD218X_mac_8, // op = mr - op * op (ss) [IF COND] MR - X * X -AD218X_mac_9, // op = mr - op * op (uu) -AD218X_mac_a, // op = mr - op * op (rnd) -AD218X_mac_b, // if mv sat mr ALU/MAC Type 25 -// ALU/MAC Common case -AD218X_amf, // [IF COND] AMF -// Shifter Common case -AD218X_shft, // [IF COND] Shifter -// Shifter specific options. Shifter Type 15, const -AD218X_shifter_0, // sr = ashift op by op (hi) -AD218X_shifter_1, // sr = sr or ashift op by op (hi) -AD218X_shifter_2, // sr = ashift op by op (lo) -AD218X_shifter_3, // sr = sr or ashift op by op (lo) -AD218X_shifter_4, // sr = lshift op by op (hi) -AD218X_shifter_5, // sr = sr or lshift op by op (hi) -AD218X_shifter_6, // sr = lshift op by op (lo) -AD218X_shifter_7, // sr = sr or lshift op by op (lo) -// Data Movement -AD218X_move_0, // op = op Internal Data Move, Instruction Type 17: -AD218X_move_1, // op = op Load Register Immediate, Instruction Type 6: -AD218X_move_2, // op = op Load Non-Data Register Immediate, Instruction Type 7: -AD218X_move_3, // op = dm(op) Data Memory Read (Direct Address), Instruction Type 3: -AD218X_move_4, // op = dm(op, op) Data Memory Read, Instruction Type 4: -AD218X_move_5, // op = pm(op, op) Program Memory Read -AD218X_move_6, // dm(op) = op Data Memory Write (Direct Address) -AD218X_move_7, // dm(op, op) = op Data Memory Write, Instruction Type 4: -AD218X_move_8, // dm(op, op) = op Data Memory Write, Immediate Data, Instruction Type 2: -AD218X_move_9, // pm(op, op) = op Program Memory Write, Instruction Type 5 -AD218X_move_a, // op = io(op) I/O Memory Space Read/Write, Instruction Type 29: -AD218X_move_b, // io(op) = op -// Flow control -AD218X_jump, // Unconditional JUMP Direct, Instruction Type 10: -AD218X_jump_1, // Conditional JUMP Direct, Instruction Type 10: -AD218X_jump_2, // Unconditional JUMP Indirect, Instruction Type 19: -AD218X_jump_3, // Conditional JUMP Indirect, Instruction Type 19: -AD218X_jump_4, // Conditional JUMP on Flag In Direct Instruction Type 27: -AD218X_call, // Conditional CALL Direct, Instruction Type 10: -AD218X_call_1, // Conditional CALL Indirect, Instruction Type 19: -AD218X_call_2, // Conditional CALL on Flag In Direct Instruction Type 27: -AD218X_rts, // Unconditional Return, Instruction Type 20: -AD218X_rts_cond, // Conditional Return, Instruction Type 20: -AD218X_rti, // Unconditional Return, Instruction Type 20: -AD218X_rti_cond, // Conditional Return, Instruction Type 20: -AD218X_nop, // No operation, Instruction Type 30 -AD218X_do, // Do Until, Instruction Type 11: -// Misc -AD218X_idle, // Idle, Instruction Type 31: -AD218X_idle_1, -AD218X_flag_out, // Flag Out Mode Control Instruction Type 28: -AD218X_stack_ctl, // Stack Control, Instruction Type 26: -AD218X_mode_ctl, // Mode Control, Instruction Type 18: -AD218X_tops_w, // toppcstack = op Internal Data Move, Instruction Type 17: -AD218X_tops_r, // op = toppcstack -AD218X_ints_dis, // dis ints -AD218X_ints_ena, // ena ints -AD218X_modify, // modify(op, op) Modify Address Register, Instruction Type 21: -// ALU/MAC operation with Data Memory Read/Write -AD218X_double_move, // op = dm(op, op), op = pm(op, op) Data & Program Memory Read, Instruction Type 1: -AD218X_amf_move_0, // amf_cmd, op = dm(op, op) ALU/MAC operation with Data Memory Read, Instruction Type 4: -AD218X_amf_move_1, // amf_cmd, op = pm(op, op) ALU/MAC operation with Program Memory Read, Instruction Type 5: -AD218X_amf_move_2, // amf_cmd, op = dm(op, op) Shift operation with Data Memory Read, Instruction Type 12: -AD218X_amf_move_3, // amf_cmd, op = pm(op, op) Shift operation with Program Memory Read, Instruction Type 13: -AD218X_amf_move_4, // amf_cmd, op = op ALU/MAC operation with Data Register Move, Instruction Type 8: -AD218X_amf_move_5, // amf_cmd, op = op Shift operation with Data Register Move, Instruction Type 14: -AD218X_amf_move_6, // dm(op, op) = op, amf_cmd ALU/MAC operation with Data Memory Write, Instruction Type 4: -AD218X_amf_move_7, // pm(op, op) = op, amf_cmd ALU/MAC operation with Program Memory Write, Instruction Type 5: -AD218X_amf_move_8, // dm(op, op) = op, amf_cmd Shift operation with Data Memory Write, Instruction Type 12: -AD218X_amf_move_9, // pm(op, op) = op, amf_cmd Shift operation with Program Memory Write, Instruction Type 13: -AD218X_amf_move_a, // amf_cmd, op = dm(op, op), op = pm(op, op) ALU/MAC with Data and Program Memory Read, Instruction Type 1: -AD218X_last, - -}; - - - - -enum -{ -OAK_Dsp_null = 0, // Unknown Operation -OAK_Dsp_proc, // cmd need further process -// ALU-ALM subcodes -OAK_Dsp_or, //000 Logical Or -OAK_Dsp_and, //001 And -OAK_Dsp_xor, //010 Exclusive Or -OAK_Dsp_add, //011 Add -OAK_Dsp_alm_tst0, //100 Test Bit-field for Zeros -OAK_Dsp_alm_tst1, //101 Test Bit-field for Ones -OAK_Dsp_cmp, //110 Compare -OAK_Dsp_sub, //111 Subtract -// ALM subcodes -OAK_Dsp_alm_msu, //1000 Multiply and Subtract Previous Product -OAK_Dsp_addh, //1001 Add to High Accumulator -OAK_Dsp_addl, //1010 Add to Low Accumulator -OAK_Dsp_subh, //1011 Subtract from High Accumulator -OAK_Dsp_subl, //1100 Subtract from Low Accumulator -OAK_Dsp_sqr, //1101 Square -OAK_Dsp_sqra, //1110 Square and Accumulate Previous Product -OAK_Dsp_cmpu, //1111 Compare Unsigned -// MODA-MODB subcodes conditional -OAK_Dsp_shr, //000 Shift Accumulator Right -OAK_Dsp_shr4, //001 Shift Accumulator Right by 4 Bits -OAK_Dsp_shl, //010 Shift Accumulator Left -OAK_Dsp_shl4, //011 Shift Accumulator Left by 4 Bits -OAK_Dsp_ror, //100 Rotate Accumulator Right through Carry -OAK_Dsp_rol, //101 Rotate Accumulator Left through Carry -OAK_Dsp_clr, //110 Clear Accumulator -OAK_Dsp_mod_reserved, //111 Mod Reserved -// MODA subcodes conditional -OAK_Dsp_not, //1000 Logical Not -OAK_Dsp_neg, //1001 2's Complement of aX-accumulator -OAK_Dsp_rnd, //1010 Round Upper 20 Bits of aX-accumulator -OAK_Dsp_pacr, //1011 Product Move and Round to aX-accumulator -OAK_Dsp_clrr, //1100 Clear and Round aX-accumulator -OAK_Dsp_inc, //1101 Increment Accumulator by One -OAK_Dsp_dec, //1110 Decrement aX-accumulator by One -OAK_Dsp_copy, //1111 Copy aX-accumulator -// --- -OAK_Dsp_norm, //Normalize -OAK_Dsp_divs, //Division Step -// ALB subcodes -OAK_Dsp_set, //000 Set Bit-field -OAK_Dsp_rst, //001 Reset Bit-field -OAK_Dsp_chng, //010 Change Bit-field -OAK_Dsp_addv, //011 Add Long Immediate Value or Data Memory Location -OAK_Dsp_alb_tst0, //100 Test Bit-field for Zeros -OAK_Dsp_alb_tst1, //101 Test Bit-field for Ones -OAK_Dsp_cmpv, //110 Compare Long Immediate Value to Register or Data Memory Location -OAK_Dsp_subv, //111 Subtract Long Immediate Value from a Register or a Data Memory Location -// --- -OAK_Dsp_maxd, //Maximum between Data Memory Location and Accumulator -OAK_Dsp_max, //Maximum between Two Accumulators -OAK_Dsp_min, //Minimum between Two Accumulators -OAK_Dsp_lim, //Limit Accumulator (lim aX[, aX]) -// MUL subcodes -OAK_Dsp_mpy, //000 Multiply -OAK_Dsp_mpysu, //001 Multiply Signed by Unsigned -OAK_Dsp_mac, //010 Multiply and Accumulate Previous Product -OAK_Dsp_macus, //011 Multiply Unsigned by Signed and Accumulate Previous Product -OAK_Dsp_maa, //100 Multiply and Accumulate Aligned Previous Product -OAK_Dsp_macuu, //101 Multiply Unsigned by Unsigned and Accumulate Previous Product -OAK_Dsp_macsu, //110 Multiply Signed by Unsigned and Accumulate Previous Product -OAK_Dsp_maasu, //111 Multiply Signed by Unsigned and Accumulate Aligned Previous Product -//--- -OAK_Dsp_mpyi, //Multiply Signed Short Immediate -OAK_Dsp_msu, //Multiply and Subtract Previous Product -OAK_Dsp_tstb, //Test Specific Bit -OAK_Dsp_shfc, //Shift Accumulators according to Shift Value Register -OAK_Dsp_shfi, //Shift Accumulators by an Immediate Shift Value -OAK_Dsp_exp, //Evaluate the Exponent Value -//--- -OAK_Dsp_mov, //Move Data -OAK_Dsp_movp, //Move from Program Memory into Data Memory -OAK_Dsp_movs, //Move and Shift According to Shift Value Register -OAK_Dsp_movsi, //Move and Shift According to an Immediate Shift Value -OAK_Dsp_movr, //Move and Round -OAK_Dsp_movd, //Move from Data Memory into Program Memory -//--- -OAK_Dsp_push, //Push Register or Long Immediate Value onto Stack -OAK_Dsp_pop, //Pop from Stack into Register -//--- -OAK_Dsp_swap, //Swap aX- and bX-accumulators -OAK_Dsp_banke, //Bank Exchange -OAK_Dsp_rep, //Repeat Next Instruction -OAK_Dsp_bkrep, //Block-Repeat -OAK_Dsp_break, //Break from Block-repeat -//--- -OAK_Dsp_br, //Conditional Branch -OAK_Dsp_brr, //Relative Conditional Branch -OAK_Dsp_br_u, //UnConditional Branch -OAK_Dsp_brr_u, //Relative UnConditional Branch -OAK_Dsp_call, //Conditional Call Subroutine -OAK_Dsp_callr, //Relative Conditional Call Subroutine -OAK_Dsp_calla, //Call Subroutine at Location Specified by Accumulator -//--- -OAK_Dsp_ret, //Return Conditionally -OAK_Dsp_ret_u, //Return UnConditionally -OAK_Dsp_retd, //Delayed Return -OAK_Dsp_reti, //Return from Interrupt Conditionally -OAK_Dsp_reti_u, //Return from Interrupt UnConditionally -OAK_Dsp_retid, //Delayed Return from Interrupt -OAK_Dsp_rets, //Return with Short Immediate Parameter -//--- -OAK_Dsp_cntx, //Context Switching Store or Restore -OAK_Dsp_nop, //No operation -OAK_Dsp_modr, //Modify rN -OAK_Dsp_dint, //Disable Interrupt -OAK_Dsp_eint, //Enable Interrupt -//--- -OAK_Dsp_trap, //Software Interrupt -//--- -OAK_Dsp_lpg, //Load the Page Bits -OAK_Dsp_load, //Load Specific Fields into Registers -OAK_Dsp_mov_eu, //Move Data, eu -OAK_Dsp_last, - -}; - -/* - * TLCS900 processor module for IDA. - * Copyright (c) 1998-2006 Konstantin Norvatoff, - * Freeware. - */ - - -// List of instructions - -// -enum -{ -T900_null = 0, // Unknown Operation -T900_ld, -T900_ldw, -T900_push, -T900_pushw, -T900_pop, -T900_popw, -T900_lda, -T900_ldar, -T900_ex, -T900_mirr, -T900_ldi, -T900_ldiw, -T900_ldir, -T900_ldirw, -T900_ldd, -T900_lddw, -T900_lddr, -T900_lddrw, -T900_cpi, -T900_cpir, -T900_cpd, -T900_cpdr, -T900_add, -T900_addw, -T900_adc, -T900_adcw, -T900_sub, -T900_subw, -T900_sbc, -T900_sbcw, -T900_cp, -T900_cpw, -T900_inc, -T900_incw, -T900_dec, -T900_decw, -T900_neg, -T900_extz, -T900_exts, -T900_daa, -T900_paa, -T900_cpl, -T900_mul, -T900_muls, -T900_div, -T900_divs, -T900_mula, -T900_minc1, -T900_minc2, -T900_minc4, -T900_mdec1, -T900_mdec2, -T900_mdec4, -T900_and, -T900_andw, -T900_or, -T900_orw, -T900_xor, -T900_xorw, -T900_ldcf, -T900_stcf, -T900_andcf, -T900_orcf, -T900_xorcf, -T900_rcf, -T900_scf, -T900_ccf, -T900_zcf, -T900_bit, -T900_res, -T900_set, -T900_chg, -T900_tset, -T900_bs1f, -T900_bs1b, -T900_nop, -T900_ei, -T900_di, -T900_swi, -T900_halt, -T900_ldc, -T900_ldx, -T900_link, -T900_unlk, -T900_ldf, -T900_incf, -T900_decf, -T900_scc, -T900_rlc, -T900_rlc_mem, -T900_rlcw_mem, -T900_rrc, -T900_rrc_mem, -T900_rrcw_mem, -T900_rl, -T900_rl_mem, -T900_rlw_mem, -T900_rr, -T900_rr_mem, -T900_rrw_mem, -T900_sla, -T900_sla_mem, -T900_slaw_mem, -T900_sra, -T900_sra_mem, -T900_sraw_mem, -T900_sll, -T900_sll_mem, -T900_sllw_mem, -T900_srl, -T900_srl_mem, -T900_srlw_mem, -T900_rld, -T900_rrd, -T900_jp, -T900_jp_cond, -T900_jr, -T900_jr_cond, -T900_jrl, -T900_jrl_cond, -T900_call, -T900_calr, -T900_djnz, -T900_ret, -T900_ret_cond, -T900_retd, -T900_reti, -T900_max, -T900_normal, -T900_last -}; - -/* - * Rockwell C39 processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, - * Freeware. - */ - - -// List of instructions - -// -enum -{ -C39_null = 0, // Unknown Operation -C39_adc, -C39_add, -C39_anc, -C39_and, -C39_ane, -C39_arr, -C39_asl, -C39_asr, -C39_bar, -C39_bas, -C39_bbr, -C39_bbs, -C39_bcc, -C39_bcs, -C39_beq, -C39_bit, -C39_bmi, -C39_bne, -C39_bpl, -C39_bra, -C39_brk, -C39_bvc, -C39_bvs, -C39_clc, -C39_cld, -C39_cli, -C39_clv, -C39_clw, -C39_cmp, -C39_cpx, -C39_cpy, -C39_dcp, -C39_dec, -C39_dex, -C39_dey, -C39_eor, -C39_exc, -C39_inc, -C39_ini, -C39_inx, -C39_iny, -C39_isb, -C39_jmp, -C39_jpi, -C39_jsb, -C39_jsr, -C39_lab, -C39_lae, -C39_lai, -C39_lan, -C39_lax, -C39_lda, -C39_ldx, -C39_ldy, -C39_lii, -C39_lsr, -C39_lxa, -C39_mpa, -C39_mpy, -C39_neg, -C39_nop, -C39_nxt, -C39_ora, -C39_pha, -C39_phi, -C39_php, -C39_phw, -C39_phx, -C39_phy, -C39_pia, -C39_pla, -C39_pli, -C39_plp, -C39_plw, -C39_plx, -C39_ply, -C39_psh, -C39_pul, -C39_rba, -C39_rla, -C39_rmb, -C39_rnd, -C39_rol, -C39_ror, -C39_rra, -C39_rti, -C39_rts, -C39_sax, -C39_sba, -C39_sbc, -C39_sbx, -C39_sec, -C39_sed, -C39_sei, -C39_sha, -C39_shs, -C39_shx, -C39_shy, -C39_slo, -C39_smb, -C39_sre, -C39_sta, -C39_sti, -C39_stx, -C39_sty, -C39_tax, -C39_tay, -C39_taw, -C39_tip, -C39_tsx, -C39_twa, -C39_txa, -C39_txs, -C39_tya, -C39_last -}; - -/* - * National Semiconductor Corporation CR16 processor module for IDA. - * Copyright (c) 2002-2006 Konstantin Norvatoff, - * Freeware. - */ - - -// list of instructions - -enum -{ -CR16_null = 0, // Unknown Operation -CR16_addb, -CR16_addw, -CR16_addub, -CR16_adduw, -CR16_addcb, -CR16_addcw, -CR16_andb, -CR16_andw, -CR16_ashub, -CR16_ashuw, -// !!! don't change sequence !!! -CR16_beq, -CR16_bne, -CR16_bcs, -CR16_bcc, -CR16_bhi, -CR16_bls, -CR16_bgt, -CR16_ble, -CR16_bfs, -CR16_bfc, -CR16_blo, -CR16_bhs, -CR16_blt, -CR16_bge, -CR16_br, -//---------------------------- -CR16_bal, -CR16_cmpb, -CR16_cmpw, -CR16_beq1b, -CR16_beq1w, -CR16_beq0b, -CR16_beq0w, -CR16_bne1b, -CR16_bne1w, -CR16_bne0b, -CR16_bne0w, -CR16_di, -CR16_ei, -CR16_excp, -// !!! don't change sequence !!! -CR16_jeq, -CR16_jne, -CR16_jcs, -CR16_jcc, -CR16_jhi, -CR16_jls, -CR16_jgt, -CR16_jle, -CR16_jfs, -CR16_jfc, -CR16_jlo, -CR16_jhs, -CR16_jlt, -CR16_jge, -CR16_jump, -//---------------------------- -CR16_jal, -CR16_loadb, -CR16_loadw, -CR16_loadm, -CR16_lpr, -CR16_lshb, -CR16_lshw, -CR16_movb, -CR16_movw, -CR16_movxb, -CR16_movzb, -CR16_movd, -CR16_mulb, -CR16_mulw, -CR16_mulsb, -CR16_mulsw, -CR16_muluw, -CR16_nop, -CR16_orb, -CR16_orw, -CR16_push, -CR16_pop, -CR16_popret, -CR16_retx, -// !!! don't change sequence !!! -CR16_seq, -CR16_sne, -CR16_scs, -CR16_scc, -CR16_shi, -CR16_sls, -CR16_sgt, -CR16_sle, -CR16_sfs, -CR16_sfc, -CR16_slo, -CR16_shs, -CR16_slt, -CR16_sge, -//---------------------------- -CR16_spr, -CR16_storb, -CR16_storw, -CR16_storm, -CR16_subb, -CR16_subw, -CR16_subcb, -CR16_subcw, -CR16_tbit, -CR16_tbitb, -CR16_tbitw, -CR16_sbitb, -CR16_sbitw, -CR16_cbitb, -CR16_cbitw, -CR16_wait, -CR16_eiwait, -CR16_xorb, -CR16_xorw, -CR16_last -}; - -/* - * Panasonic MN102 (PanaXSeries) processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, - * Freeware. - */ - - -// List of instructions - -enum -{ -mn102_null = 0, // Unknown Operation -mn102_add, -mn102_addc, -mn102_addnf, -mn102_and, -mn102_asr, -mn102_bcc, -mn102_bccx, -mn102_bclr, -mn102_bcs, -mn102_bcsx, -mn102_beq, -mn102_beqx, -mn102_bge, -mn102_bgex, -mn102_bgt, -mn102_bgtx, -mn102_bhi, -mn102_bhix, -mn102_ble, -mn102_blex, -mn102_bls, -mn102_blsx, -mn102_blt, -mn102_bltx, -mn102_bnc, -mn102_bncx, -mn102_bne, -mn102_bnex, -mn102_bns, -mn102_bnsx, -mn102_bra, -mn102_bset, -mn102_btst, -mn102_bvc, -mn102_bvcx, -mn102_bvs, -mn102_bvsx, -mn102_cmp, -mn102_divu, -mn102_ext, -mn102_extx, -mn102_extxb, -mn102_extxbu, -mn102_extxu, -mn102_jmp, -mn102_jsr, -mn102_lsr, -mn102_mov, -mn102_movb, -mn102_movbu, -mn102_movx, -mn102_mul, -mn102_mulq, -mn102_mulqh, -mn102_mulql, -mn102_mulu, -mn102_nop, -mn102_not, -mn102_or, -mn102_pxst, -mn102_rol, -mn102_ror, -mn102_rti, -mn102_rts, -mn102_sub, -mn102_subc, -mn102_tbnz, -mn102_tbz, -mn102_xor, -mn102_last -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * PowerPC - RISC with very complex instructions - */ - - - -enum -{ -PPC_null = 0, // Unknown Operation -PPC_add, // Add -PPC_addc, // Add Carrying -PPC_adde, // Add Extended -PPC_addi, // Add Immediate -PPC_addic, // Add Immediate Carrying -PPC_addis, // Add Immediate Shifted -PPC_addme, // Add to Minus One Extended -PPC_addze, // Add to Zero Extended -PPC_and, // AND -PPC_andc, // AND with Complement -PPC_andi, // AND Immediate -PPC_andis, // AND Immediate Shifted -PPC_b, // Branch -PPC_bc, // Branch Conditional -PPC_bcctr, // Branch Conditional to Count Register -PPC_bclr, // Branch Conditional to Link Register -PPC_cmp, // Compare -PPC_cmpi, // Compare Immediate -PPC_cmpl, // Compare Logical -PPC_cmpli, // Compare Logical Immediate -PPC_cntlzd, // Count Leading Zeros Double Word -PPC_cntlzw, // Count Leading Zeros Word -PPC_crand, // Condition Register AND -PPC_crandc, // Condition Register AND with Complement -PPC_creqv, // Condition Register Equivalent -PPC_crnand, // Condition Register NAND -PPC_crnor, // Condition Register NOR -PPC_cror, // Condiiton Register OR -PPC_crorc, // Condition Register OR with Comlement -PPC_crxor, // Condition Register XOR -PPC_dcba, // -PPC_dcbf, // Data Cache Block Flush -PPC_dcbi, // Data Cache Block Invalidate -PPC_dcbst, // Data Cache Block Store -PPC_dcbt, // Data Cache Block Touch -PPC_dcbtst, // Data Cache Block Touch for Store -PPC_dcbz, // Data Cache Block Set to Zero -PPC_divd, // Divide Double Word -PPC_divdu, // Divide Double Word Unsigned -PPC_divw, // Divide Word -PPC_divwu, // Divide Word Unsigned -PPC_eciwx, // External Control In Word Indexed -PPC_ecowx, // External Control Out Word Indexed -PPC_eieio, // Enforce In-Order Execution of I/O -PPC_eqv, // Equivalent -PPC_extsb, // Extend Sign Byte -PPC_extsh, // Extend Sign Half Word -PPC_extsw, // Extend Sign Word -PPC_fabs, // Floating-Point Absolute Value -PPC_fadd, // Floating-Point Add -PPC_fadds, // Floating-Point Add (Single-Precision) -PPC_fcfid, // Floating-Point Convert from Integer Double Word -PPC_fcmpo, // Floating-Point Compare Ordered -PPC_fcmpu, // Floating-Point Compare Unordered -PPC_fctid, // Floating-Point Convert to Integer Double Word -PPC_fctidz, // Floating-Point Convert to Integer Double Word with Round toward Zero -PPC_fctiw, // Floating-Point Convert to Integer Word -PPC_fctiwz, // Floating-Point Convert to Integer Word with Round toward Zero -PPC_fdiv, // Floating-Point Divide -PPC_fdivs, // Floating-Point Divide Single-Precision -PPC_fmadd, // Floating-Point Multiply-Add -PPC_fmadds, // Floating-Point Multiply-Add Single-Precision -PPC_fmr, // Floating-Point Move Register -PPC_fmsub, // Floating-Point Multiply-Subtract -PPC_fmsubs, // Floating-Point Multiply-Subtract (Single-Precision) -PPC_fmul, // Floating-Point Multiply -PPC_fmuls, // Floating-Point Multiply Single-Precision -PPC_fnabs, // Floating-Point Negative Absolute Value -PPC_fneg, // Floating-Point Negate -PPC_fnmadd, // Floating-Point Negative Multiply-Add -PPC_fnmadds, // Floating-Point Negative Multiply-Add Single-Precision -PPC_fnmsub, // Floating-Point Negative Multiply-Subtract -PPC_fnmsubs, // Floating-Point Negative Multiply-Subtract Single-Precision -PPC_fres, // Floating-Point Reciprocal Estimate Single-Precision -PPC_frsp, // Floating-Point Round to Single-Precision -PPC_frsqrte, // Floating-Point Reciprocal Square Root Estimate -PPC_fsel, // Floating-Point Select -PPC_fsqrt, // Floating-Point Square Root -PPC_fsqrts, // Floating-Point Square Root Single-Precision -PPC_fsub, // Floating-Point Subtract -PPC_fsubs, // Floating-Point Subtract Single-Precision -PPC_icbi, // Instruction Cache Block Invalidate -PPC_isync, // Instruction Synchronize -PPC_lbz, // Load Byte and Zero -PPC_lbzu, // Load Byte and Zero with Update -PPC_lbzux, // Load Byte and Zero with Update Indexed -PPC_lbzx, // Load Byte and Zero Indexed -PPC_ld, // Load Double Word -PPC_ldarx, // Load Double Word and Reserve Indexed -PPC_ldu, // Load Double Word with Update -PPC_ldux, // Load Double Word with Update Indexed -PPC_ldx, // Load Double Word Indexed -PPC_lfd, // Load Floating-Point Double-Precision -PPC_lfdu, // Load Floating-Point Double-Precision with Update -PPC_lfdux, // Load Floating-Point Double-Precision with Update Indexed -PPC_lfdx, // Load Floating-Point Double-Precision Indexed -PPC_lfs, // Load Floating-Point Single-Precision -PPC_lfsu, // Load Floating-Point Single-Precision with Update -PPC_lfsux, // Load Floating-Point Single-Precision with Update Indexed -PPC_lfsx, // Load Floating-Point Single-Precision Indexed -PPC_lha, // Load Half Word Algebraic -PPC_lhau, // Load Half Word Algebraic with Update -PPC_lhaux, // Load Half Word Algebraic with Update Indexed -PPC_lhax, // Load Half Word Algebraic Indexed -PPC_lhbrx, // Load Half Word Byte-reverse Indexed -PPC_lhz, // Load Half Word and Zero -PPC_lhzu, // Load Half Word and Zero with Update -PPC_lhzux, // Load Half Word and Zero with Update Indexed -PPC_lhzx, // Load Half Word and Zero Indexed -PPC_lmw, // Load Multiple Word -PPC_lswi, // Load String Word Immediate -PPC_lswx, // Load String Word Indexed -PPC_lwa, // Load Word Algebraic -PPC_lwarx, // Load Word and Reserve Indexed -PPC_lwaux, // Load Word Algebraic with Update Indexed -PPC_lwax, // Load Word Algebraic Indexed -PPC_lwbrx, // Load Word Byte-Reverse Indexed -PPC_lwz, // Load Word and Zero -PPC_lwzu, // Load Word and Zero with Update -PPC_lwzux, // Load Word and Zero with Update Indexed -PPC_lwzx, // Load Word and Zero Indexed -PPC_mcrf, // Move Condition register Field -PPC_mcrfs, // Move to Condition Register from FPSCR -PPC_mcrxr, // Move to Condition Register from XER -PPC_mfcr, // Move from Condition Register -PPC_mffs, // Move from FPSCR -PPC_mfmsr, // Move from Machine State Register -PPC_mfspr, // Move from Special Purpose Register -PPC_mfsr, // Move from Segment Register -PPC_mfsrin, // Move from Segment Register Indexed -PPC_mftb, // Move from Time Base -PPC_mtcrf, // Move to Condition Register Fields -PPC_mtfsb0, // Move to FPSCR Bit 0 -PPC_mtfsb1, // Move to FPSCR Bit 1 -PPC_mtfsf, // Move to FPSCR Fields -PPC_mtfsfi, // Move to FPSCR Field Immediate -PPC_mtmsr, // Move to Machine State Register -PPC_mtmsrd, // Move to Machine State Register Double Word -PPC_mtspr, // Move to Special Purpose Register -PPC_mtsr, // Move to Segment Register -PPC_mtsrd, // Move to Segment Register Double Word -PPC_mtsrdin, // Move to Segment Register Indirect Double -PPC_mtsrin, // Move to Segment Register Indirect -PPC_mulhd, // Multiply High Double Word -PPC_mulhdu, // Multiply High Double Word Unsigned -PPC_mulhw, // Multiply High Word -PPC_mulhwu, // Multiply High Word Unsigned -PPC_mulld, // Multiply Low Double Word -PPC_mulli, // Multiply Low Immediate -PPC_mullw, // Multiply Low -PPC_nand, // NAND (not AND) -PPC_neg, // Negate -PPC_nor, // NOR (not OR) -PPC_or, // OR -PPC_orc, // OR with Complement -PPC_ori, // OR Immediate -PPC_oris, // OR Immediate Shifted -PPC_rfi, // Return from Interrupt -PPC_rfid, // Return from Interrupt Double Word -PPC_rldcl, // Rotate Left Double Word then Clear Left -PPC_rldcr, // Rotate Left Double Word then Clear Right -PPC_rldic, // Rotate Left Double Word Immediate then Clear -PPC_rldicl, // Rotate Left Double Word Immediate then Clear Left -PPC_rldicr, // Rotate Left Double Word Immediate then Clear Right -PPC_rldimi, // Rotate Left Double Word Immediate then Mask Insert -PPC_rlwimi, // Rotate Left Word Immediate then Mask Insert -PPC_rlwinm, // Rotate Left Word Immediate then AND with Mask -PPC_rlwnm, // Rotate Left Word then AND with Mask -PPC_sc, // System Call -PPC_slbia, // SLB Invalidate All, ISA 3.0 format -PPC_slbie, // SLB Invalidate Entry -PPC_sld, // Shift Left Double Word -PPC_slw, // Shift Left Word -PPC_srad, // Shift Right Algebraic Double Word -PPC_sradi, // Shift Right Algebraic Double Word Immediate -PPC_sraw, // Shift Right Algebraic Word -PPC_srawi, // Shift Right Algebraic Word Immediate -PPC_srd, // Shift Right Double Word -PPC_srw, // Shift Right Word -PPC_stb, // Store Byte -PPC_stbu, // Store Byte with Update -PPC_stbux, // Store Byte with Update Indexed -PPC_stbx, // Store Byte Indexed -PPC_std, // Store Double Word -PPC_stdcx, // Store Double Word Conditional Indexed -PPC_stdu, // Store Double Word with Update -PPC_stdux, // Store Double Word with Update Indexed -PPC_stdx, // Store Double Word Indexed -PPC_stfd, // Store Floating-Point Double-Precision -PPC_stfdu, // Store Floating-Point Double-Precision wiht Update -PPC_stfdux, // Store Floating-Point Double-Precision wiht Update Indexed -PPC_stfdx, // Store Floating-Point Double-Precision Indexed -PPC_stfiwx, // Store Floating-Point as Integer Word Indexed -PPC_stfs, // Store Floating-Point Single-Precision -PPC_stfsu, // Store Floating-Point Single-Precision with Update -PPC_stfsux, // Store Floating-Point Single-Precision with Update Indexed -PPC_stfsx, // Store Floating-Point Single-Precision Indexed -PPC_sth, // Store Half Word -PPC_sthbrx, // Store Half Word Byte-Reverse Indexed -PPC_sthu, // Store Half Word with Update -PPC_sthux, // Store Half Word with Update Indexed -PPC_sthx, // Store Half Word Indexed -PPC_stmw, // Store Multiple Word -PPC_stswi, // Store String Word Immediate -PPC_stswx, // Store String Word Indexed -PPC_stw, // Store Word -PPC_stwbrx, // Store Word Byte-Reverse Indexed -PPC_stwcx, // Store Word Conditional Indexed -PPC_stwu, // Store Word with Update -PPC_stwux, // Store Word with Update Indexed -PPC_stwx, // Store Word Indexed -PPC_subf, // Subtract from -PPC_subfc, // Subtract from Carrying -PPC_subfe, // Subtract from Extended -PPC_subfic, // Subtract from Immediate Carrying -PPC_subfme, // Subtract from Minus One Extended -PPC_subfze, // Subtract from Zero Extended -PPC_sync, // Synchronize -PPC_td, // Trap Double Word -PPC_tdi, // Trap Double Word Immediate -PPC_tlbia, // TLB Invalidate All -PPC_tlbie, // TLB Invalidate Entry, ISA 3.0 format -PPC_tlbsync, // TLB Synchronize -PPC_tw, // Trap Word -PPC_twi, // Trap Word Immediate -PPC_xor, // XOR -PPC_xori, // XOR Immediate -PPC_xoris, // XOR Immediate Shifted - -PPC_last_basic = PPC_xoris, - -// -// Simplified mnemonics -// - -PPC_cmpwi, // Compare Word Immediate -PPC_cmpw, // Compare Word -PPC_cmplwi, // Compare Logical Word Immediate -PPC_cmplw, // Compare Logical Word -PPC_cmpdi, // Compare Double Word Immediate -PPC_cmpd, // Compare Double Word -PPC_cmpldi, // Compare Logical Double Word Immediate -PPC_cmpld, // Compare Logical Double Word - -PPC_trap, // Trap Word Unconditionally -// "trapd" seems like a bug; no such mnemonic appears to exist as just plain -// "trap" is used regardless of word/doubleword, but we have to leave it here -// to not mess up existing databases -PPC_trapd, // Trap Double Word Unconditionally -PPC_twlgt, // Trap Word if Logically Greater Than -PPC_twllt, // Trap Word if Logically Less Than -PPC_tweq, // Trap Word if Equal -PPC_twlge, // Trap Word if Logically Greater Than or Equal -PPC_twlle, // Trap Word if Logically Less Than or Equal -PPC_twgt, // Trap Word if Greater Than -PPC_twge, // Trap Word if Greater Than or Equal -PPC_twlt, // Trap Word if Less Than -PPC_twle, // Trap Word if Less Than or Equal -PPC_twne, // Trap Word if Not Equal -PPC_twlgti, // Trap Word Immediate if Logically Greater Than -PPC_twllti, // Trap Word Immediate if Logically Less Than -PPC_tweqi, // Trap Word Immediate if Equal -PPC_twlgei, // Trap Word Immediate if Logically Greater Than or Equal -PPC_twllei, // Trap Word Immediate if Logically Less Than or Equal -PPC_twgti, // Trap Word Immediate if Greater Than -PPC_twgei, // Trap Word Immediate if Greater Than or Equal -PPC_twlti, // Trap Word Immediate if Less Than -PPC_twlei, // Trap Word Immediate if Less Than or Equal -PPC_twnei, // Trap Word Immediate if Not Equal -PPC_tdlgt, // Trap Double Word if Logically Greater Than -PPC_tdllt, // Trap Double Word if Logically Less Than -PPC_tdeq, // Trap Double Word if Equal -PPC_tdlge, // Trap Double Word if Logically Greater Than or Equal -PPC_tdlle, // Trap Double Word if Logically Less Than or Equal -PPC_tdgt, // Trap Double Word if Greater Than -PPC_tdge, // Trap Double Word if Greater Than or Equal -PPC_tdlt, // Trap Double Word if Less Than -PPC_tdle, // Trap Double Word if Less Than or Equal -PPC_tdne, // Trap Double Word if Not Equal -PPC_tdlgti, // Trap Double Word Immediate if Logically Greater Than -PPC_tdllti, // Trap Double Word Immediate if Logically Less Than -PPC_tdeqi, // Trap Double Word Immediate if Equal -PPC_tdlgei, // Trap Double Word Immediate if Logically Greater Than or Equal -PPC_tdllei, // Trap Double Word Immediate if Logically Less Than or Equal -PPC_tdgti, // Trap Double Word Immediate if Greater Than -PPC_tdgei, // Trap Double Word Immediate if Greater Than or Equal -PPC_tdlti, // Trap Double Word Immediate if Less Than -PPC_tdlei, // Trap Double Word Immediate if Less Than or Equal -PPC_tdnei, // Trap Double Word Immediate if Not Equal -// all trap mnemonics are covered as of Power ISA 2.07; t[dw]nl*, t[dw]lnl*, -// and t[dw]lng* are intentionally missing since they are redundant. in other -// words, the assembler supports (e.g.) both "logically less than or equal" -// (tdlei) in addition to "logically not greater than" (tdlngi)--a disassembler -// need not support both - -PPC_nop, // No Operation -PPC_not, // Complement Register -PPC_mr, // Move Register - -PPC_subi, // Subtract Immediate -PPC_subic, // Subtract Immediate Carrying -PPC_subis, // Subtract Immediate Shifted -PPC_li, // Load Immediate -PPC_lis, // Load Immediate Shifted - -PPC_crset, // Condition Register Set -PPC_crnot, // Condition Register NOT -PPC_crmove, // Condition Register Move -PPC_crclr, // Condition Register Clear - -PPC_mtxer, // Move to integer unit exception register -PPC_mtlr, // Move to link register -PPC_mtctr, // Move to count register -PPC_mtdsisr, // Move to DAE/source instruction service register -PPC_mtdar, // Move to data address register -PPC_mtdec, // Move to decrementer register -PPC_mtsrr0, // Move to status save/restore register 0 -PPC_mtsrr1, // Move to status save/restore register 1 -PPC_mtsprg0, // Move to general special purpose register 0 -PPC_mtsprg1, // Move to general special purpose register 1 -PPC_mtsprg2, // Move to general special purpose register 2 -PPC_mtsprg3, // Move to general special purpose register 3 -PPC_mttbl, // Move to time base register (lower) -PPC_mttbu, // Move to time base register (upper) -PPC_mfxer, // Move from integer unit exception register -PPC_mflr, // Move from link register -PPC_mfctr, // Move from count register -PPC_mfdsisr, // Move from DAE/source instruction service register -PPC_mfdar, // Move from data address register -PPC_mfdec, // Move from decrementer register -PPC_mfsrr0, // Move from status save/restore register 0 -PPC_mfsrr1, // Move from status save/restore register 1 -PPC_mfsprg0, // Move from general special purpose register 0 -PPC_mfsprg1, // Move from general special purpose register 1 -PPC_mfsprg2, // Move from general special purpose register 2 -PPC_mfsprg3, // Move from general special purpose register 3 -PPC_mftbl, // Move from time base register (lower) -PPC_mftbu, // Move from time base register (upper) -PPC_mfpvr, // Move from processor version register - -// suffixes: -// lr - goto lr -// ctr - goto ctr -// l - update lr -// a - absolute - -// branch forms not listed here or elsewhere in the file (e.g. bltlr) are -// being handled by emitting extra characters when printing the instructions -// instead of having separate enums - -PPC_balways, // Branch unconditionally -PPC_bt, // Branch if true -PPC_bf, // Branch if false -PPC_bdnz, // CTR--; branch if CTR non-zero -PPC_bdnzt, // CTR--; branch if CTR non-zero and condition is true -PPC_bdnzf, // CTR--; branch if CTR non-zero and condition is false -PPC_bdz, // CTR--; branch if CTR zero -PPC_bdzt, // CTR--; branch if CTR zero and condition is true -PPC_bdzf, // CTR--; branch if CTR zero and condition is false - -PPC_blt, // Branch if less than -PPC_ble, // Branch if less than or equal -PPC_beq, // Branch if equal -PPC_bge, // Branch if greater than or equal -PPC_bgt, // Branch if greater than -PPC_bne, // Branch if not equal -PPC_bso, // Branch if summary overflow -PPC_bns, // Branch if not summary overflow -// bun and bnu are intentionally missing from this list; they are handled by -// bso/bns (this is the result of historical differences between POWER and PPC -// mnemonics) - -PPC_extlwi, // Extract and Left Justify Immediate -PPC_extrwi, // Extract and Right Justify Immediate -PPC_inslwi, // Insert from Left Immediate -PPC_insrwi, // Insert from Right Immediate -PPC_rotlwi, // Rotate Left Immediate -PPC_rotrwi, // Rotate Right Immediate -PPC_rotlw, // Rotate Left -PPC_slwi, // Shift Left Immediate -PPC_srwi, // Shift Right Immediate -PPC_clrlwi, // Clear Left Immediate -PPC_clrrwi, // Clear Right Immediate -PPC_clrlslwi, // Clear Left and Shift Left Immediate - -// -// PowerPC Embedded Controller Instructions -// - -PPC_dccci, // Data cache congruence class invalidate (p.438-439) -PPC_dcread, // Data cache read (p.440-441) -PPC_icbt, // Instruction cache block touch (p.450-451) -PPC_iccci, // Instruction cache congruence class invalidate (p.452-453) -PPC_icread, // Instruction cache read (p.454-455) -PPC_mfdcr, // Move from device control register (p.484-485) -PPC_mtdcr, // Move to device control register (p.491-492) -PPC_rfci, // Return from critical interrupt (p.507) -PPC_tlbre, // TLB read entry (p.548-549) -PPC_tlbsx, // TLB search indexed (p.550) -PPC_tlbwe, // TLB write entry (p.552-553) -PPC_wrtee, // Write external enable (p.560) -PPC_wrteei, // Write external enable immediate (p.561) - -// -// New PowerPC instructions -// - -PPC_abs, // Absolute -PPC_clcs, // Cache Lines Compute Size -PPC_clf, // Cache Line Flush -PPC_cli, // Cache Line Invalidate -PPC_dclst, // Data Cache Line Store -PPC_div, // Divide -PPC_divs, // Divide Short -PPC_doz, // Different Or Zero -PPC_dozi, // Different Or Zero Immediate -PPC_frsqrtes, // Floating Reciprocal Square Root Estimate Single -PPC_hrfid, // Hypervisor Return from Interrupt Doubleword -PPC_lscbx, // Load String And Compare Byte Indexed -PPC_maskg, // Mask Generate -PPC_maskir, // Mask Insert From Register -PPC_mfsri, // Move From Segment Register Indirect -PPC_mul, // Multiply -PPC_nabs, // Negative Absolute -PPC_popcntb, // Population Count Bytes -PPC_rac, // Real Address Compute -PPC_rfsvc, // Return From SVC, obsolete, see ana.cpp -PPC_rlmi, // Rotate Left Then Mask Insert -PPC_rrib, // Rotate Right And Insert Bit -PPC_slbmfee, // SLB Move From Entry ESID -PPC_slbmfev, // SLB Move From Entry VSID -PPC_slbmte, // SLB Move To Entry -PPC_sle, // Shift Left Extended -PPC_sleq, // Shift Left Extended With MQ -PPC_sliq, // Shift Left Immediate With MQ -PPC_slliq, // Shift Left Long Immediate With MQ -PPC_sllq, // Shift Left Long With MQ -PPC_slq, // Shift Left With MQ -PPC_sraiq, // Shift Right Algebraic Immediate With MQ -PPC_sraq, // Shift Right Algebraic With MQ -PPC_sre, // Shift Right Extended -PPC_srea, // Shift Right Extended Algebraic -PPC_sreq, // Shift Right Extended With MQ -PPC_sriq, // Shift Right Immediate With MQ -PPC_srliq, // Shift Right Long Immediate With MQ -PPC_srlq, // Shift Right Long With MQ -PPC_srq, // Shift Right With MQ - -// New instructions - -PPC_mtocrf, // Move To One Condition Register Field -PPC_mfocrf, // Move From One Condition Register Field - -// Freescale e200z6 instructions -PPC_isel, // Integer Select -PPC_isellt, // Integer Select Less Than -PPC_iselgt, // Integer Select Greater Than -PPC_iseleq, // Integer Select Equal -PPC_dcblc, // Data Cache Block Lock Clear -PPC_dcbtls, // Data Cache Block Touch and Lock Set -PPC_dcbtstls, // Data Cache Block Touch for Store and Lock Set -PPC_icblc, // Instruction Cache Block Lock Clear -PPC_icbtls, // Instruction Cache Block Touch and Lock Set -PPC_tlbivax, // TLB Invalidate Virtual Address Indexed -PPC_rfdi, // Return from Debug Interrupt - -// Freescale MPC603e instructions (G2 core) - -PPC_tlbld, // Load Data TLB Entry -PPC_tlbli, // Load Instruction TLB Entry - -// SPE (Signal Processing Engine) instructions - -PPC_brinc, // Bit Reversed Increment -PPC_evabs, // Vector Absolute Value -PPC_evaddiw, // Vector Add Immediate Word -PPC_evaddsmiaaw, // Vector Add Signed, Modulo, Integer to Accumulator Word -PPC_evaddssiaaw, // Vector Add Signed, Saturate, Integer to Accumulator Word -PPC_evaddumiaaw, // Vector Add Unsigned, Modulo, Integer to Accumulator Word -PPC_evaddusiaaw, // Vector Add Unsigned, Saturate, Integer to Accumulator Word -PPC_evaddw, // Vector Add Word -PPC_evand, // Vector AND -PPC_evandc, // Vector AND with Complement -PPC_evcmpeq, // Vector Compare Equal -PPC_evcmpgts, // Vector Compare Greater Than Signed -PPC_evcmpgtu, // Vector Compare Greater Than Unsigned -PPC_evcmplts, // Vector Compare Less Than Signed -PPC_evcmpltu, // Vector Compare Less Than Unsigned -PPC_evcntlsw, // Vector Count Leading Signed Bits Word -PPC_evcntlzw, // Vector Count Leading Zeros Word -PPC_evdivws, // Vector Divide Word Signed -PPC_evdivwu, // Vector Divide Word Unsigned -PPC_eveqv, // Vector Equivalent -PPC_evextsb, // Vector Extend Sign Byte -PPC_evextsh, // Vector Extend Sign Halfword -PPC_evldd, // Vector Load Double Word into Double Word -PPC_evlddx, // Vector Load Double Word into Double Word Indexed -PPC_evldh, // Vector Load Double into Four Halfwords -PPC_evldhx, // Vector Load Double into Four Halfwords Indexed -PPC_evldw, // Vector Load Double into Two Words -PPC_evldwx, // Vector Load Double into Two Words Indexed -PPC_evlhhesplat, // Vector Load Halfword into Halfwords Even and Splat -PPC_evlhhesplatx, // Vector Load Halfword into Halfwords Even and Splat Indexed -PPC_evlhhossplat, // Vector Load Halfword into Halfword Odd Signed and Splat -PPC_evlhhossplatx, // Vector Load Halfword into Halfword Odd Signed and Splat Indexed -PPC_evlhhousplat, // Vector Load Halfword into Halfword Odd Unsigned and Splat -PPC_evlhhousplatx, // Vector Load Halfword into Halfword Odd Unsigned and Splat Indexed -PPC_evlwhe, // Vector Load Word into Two Halfwords Even -PPC_evlwhex, // Vector Load Word into Two Halfwords Even Indexed -PPC_evlwhos, // Vector Load Word into Two Halfwords Odd Signed (with sign extension) -PPC_evlwhosx, // Vector Load Word into Two Halfwords Odd Signed Indexed (with sign extension) -PPC_evlwhou, // Vector Load Word into Two Halfwords Odd Unsigned (zero-extended) -PPC_evlwhoux, // Vector Load Word into Two Halfwords Odd Unsigned Indexed (zero-extended) -PPC_evlwhsplat, // Vector Load Word into Two Halfwords and Splat -PPC_evlwhsplatx, // Vector Load Word into Two Halfwords and Splat Indexed -PPC_evlwwsplat, // Vector Load Word into Word and Splat -PPC_evlwwsplatx, // Vector Load Word into Word and Splat Indexed -PPC_evmergehi, // Vector Merge High -PPC_evmergehilo, // Vector Merge High/Low -PPC_evmergelo, // Vector Merge Low -PPC_evmergelohi, // Vector Merge Low/High -PPC_evmhegsmfaa, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Fractional and Accumulate -PPC_evmhegsmfan, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Fractional and Accumulate Negative -PPC_evmhegsmiaa, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Integer and Accumulate -PPC_evmhegsmian, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Integer and Accumulate Negative -PPC_evmhegumiaa, // Vector Multiply Halfwords, Even, Guarded, Unsigned, Modulo, Integer and Accumulate -PPC_evmhegumian, // Vector Multiply Halfwords, Even, Guarded, Unsigned, Modulo, Integer and Accumulate Negative -PPC_evmhesmf, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional -PPC_evmhesmfa, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional to Accumulator -PPC_evmhesmfaaw, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional and Accumulate into Words -PPC_evmhesmfanw, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional and Accumulate Negative into Words -PPC_evmhesmi, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer -PPC_evmhesmia, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer to Accumulator -PPC_evmhesmiaaw, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer and Accumulate into Words -PPC_evmhesmianw, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer and Accumulate Negative into Words -PPC_evmhessf, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional -PPC_evmhessfa, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional to Accumulator -PPC_evmhessfaaw, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional and Accumulate into Words -PPC_evmhessfanw, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional and Accumulate Negative into Words -PPC_evmhessiaaw, // Vector Multiply Halfwords, Even, Signed, Saturate, Integer and Accumulate into Words -PPC_evmhessianw, // Vector Multiply Halfwords, Even, Signed, Saturate, Integer and Accumulate Negative into Words -PPC_evmheumi, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer -PPC_evmheumia, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer to Accumulator -PPC_evmheumiaaw, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer and Accumulate into Words -PPC_evmheumianw, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer and Accumulate Negative into Words -PPC_evmheusiaaw, // Vector Multiply Halfwords, Even, Unsigned, Saturate, Integer and Accumulate into Words -PPC_evmheusianw, // Vector Multiply Halfwords, Even, Unsigned, Saturate, Integer and Accumulate Negative into Words -PPC_evmhogsmfaa, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Fractional and Accumulate -PPC_evmhogsmfan, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Fractional and Accumulate Negative -PPC_evmhogsmiaa, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Integer and Accumulate -PPC_evmhogsmian, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Integer and Accumulate Negative -PPC_evmhogumiaa, // Vector Multiply Halfwords, Odd, Guarded, Unsigned, Modulo, Integer and Accumulate -PPC_evmhogumian, // Vector Multiply Halfwords, Odd, Guarded, Unsigned, Modulo, Integer and Accumulate Negative -PPC_evmhosmf, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional -PPC_evmhosmfa, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional to Accumulator -PPC_evmhosmfaaw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional and Accumulate into Words -PPC_evmhosmfanw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional and Accumulate Negative into Words -PPC_evmhosmi, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer -PPC_evmhosmia, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer to Accumulator -PPC_evmhosmiaaw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer and Accumulate into Words -PPC_evmhosmianw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer and Accumulate Negative into Words -PPC_evmhossf, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional -PPC_evmhossfa, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional to Accumulator -PPC_evmhossfaaw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional and Accumulate into Words -PPC_evmhossfanw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional and Accumulate Negative into Words -PPC_evmhossiaaw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Integer and Accumulate into Words -PPC_evmhossianw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Integer and Accumulate Negative into Words -PPC_evmhoumi, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer -PPC_evmhoumia, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer to Accumulator -PPC_evmhoumiaaw, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer and Accumulate into Words -PPC_evmhoumianw, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer and Accumulate Negative into Words -PPC_evmhousiaaw, // Vector Multiply Halfwords, Odd, Unsigned, Saturate, Integer and Accumulate into Words -PPC_evmhousianw, // Vector Multiply Halfwords, Odd, Unsigned, Saturate, Integer and Accumulate Negative into Words -PPC_evmra, // Initialize Accumulator -PPC_evmwhsmf, // Vector Multiply Word High Signed, Modulo, Fractional -PPC_evmwhsmfa, // Vector Multiply Word High Signed, Modulo, Fractional to Accumulator -PPC_evmwhsmi, // Vector Multiply Word High Signed, Modulo, Integer -PPC_evmwhsmia, // Vector Multiply Word High Signed, Modulo, Integer to Accumulator -PPC_evmwhssf, // Vector Multiply Word High Signed, Saturate, Fractional -PPC_evmwhssfa, // Vector Multiply Word High Signed, Saturate, Fractional to Accumulator -PPC_evmwhumi, // Vector Multiply Word High Unsigned, Modulo, Integer -PPC_evmwhumia, // Vector Multiply Word High Unsigned, Modulo, Integer to Accumulator -PPC_evmwlsmiaaw, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate into Words -PPC_evmwlsmianw, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate Negative in Words -PPC_evmwlssiaaw, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate into Words -PPC_evmwlssianw, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate Negative in Words -PPC_evmwlumi, // Vector Multiply Word Low Unsigned, Modulo, Integer -PPC_evmwlumia, // Vector Multiply Word Low Unsigned, Modulo, Integer to Accumulator -PPC_evmwlumiaaw, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate into Words -PPC_evmwlumianw, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate Negative in Words -PPC_evmwlusiaaw, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate into Words -PPC_evmwlusianw, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate Negative in Words -PPC_evmwsmf, // Vector Multiply Word Signed, Modulo, Fractional -PPC_evmwsmfa, // Vector Multiply Word Signed, Modulo, Fractional to Accumulator -PPC_evmwsmfaa, // Vector Multiply Word Signed, Modulo, Fractional and Accumulate -PPC_evmwsmfan, // Vector Multiply Word Signed, Modulo, Fractional and Accumulate Negative -PPC_evmwsmi, // Vector Multiply Word Signed, Modulo, Integer -PPC_evmwsmia, // Vector Multiply Word Signed, Modulo, Integer to Accumulator -PPC_evmwsmiaa, // Vector Multiply Word Signed, Modulo, Integer and Accumulate -PPC_evmwsmian, // Vector Multiply Word Signed, Modulo, Integer and Accumulate Negative -PPC_evmwssf, // Vector Multiply Word Signed, Saturate, Fractional -PPC_evmwssfa, // Vector Multiply Word Signed, Saturate, Fractional to Accumulator -PPC_evmwssfaa, // Vector Multiply Word Signed, Saturate, Fractional and Accumulate -PPC_evmwssfan, // Vector Multiply Word Signed, Saturate, Fractional and Accumulate Negative -PPC_evmwumi, // Vector Multiply Word Unsigned, Modulo, Integer -PPC_evmwumia, // Vector Multiply Word Unsigned, Modulo, Integer to Accumulator -PPC_evmwumiaa, // Vector Multiply Word Unsigned, Modulo, Integer and Accumulate -PPC_evmwumian, // Vector Multiply Word Unsigned, Modulo, Integer and Accumulate Negative -PPC_evnand, // Vector NAND -PPC_evneg, // Vector Negate -PPC_evnor, // Vector NOR -PPC_evor, // Vector OR -PPC_evorc, // Vector OR with Complement Form -PPC_evrlw, // Vector Rotate Left Word -PPC_evrlwi, // Vector Rotate Left Word Immediate -PPC_evrndw, // Vector Round Word -PPC_evsel, // Vector Select -PPC_evslw, // Vector Shift Left Word -PPC_evslwi, // Vector Shift Left Word Immediate -PPC_evsplatfi, // Vector Splat Fractional Immediate -PPC_evsplati, // Vector Splat Immediate -PPC_evsrwis, // Vector Shift Right Word Immediate Signed -PPC_evsrwiu, // Vector Shift Right Word Immediate Unsigned -PPC_evsrws, // Vector Shift Right Word Signed -PPC_evsrwu, // Vector Shift Right Word Unsigned -PPC_evstdd, // Vector Store Double of Double -PPC_evstddx, // Vector Store Double of Double Indexed -PPC_evstdh, // Vector Store Double of Four Halfwords -PPC_evstdhx, // Vector Store Double of Four Halfwords Indexed -PPC_evstdw, // Vector Store Double of Two Words -PPC_evstdwx, // Vector Store Double of Two Words Indexed -PPC_evstwhe, // Vector Store Word of Two Halfwords from Even -PPC_evstwhex, // Vector Store Word of Two Halfwords from Even Indexed -PPC_evstwho, // Vector Store Word of Two Halfwords from Odd -PPC_evstwhox, // Vector Store Word of Two Halfwords from Odd Indexed -PPC_evstwwe, // Vector Store Word of Word from Even -PPC_evstwwex, // Vector Store Word of Word from Even Indexed -PPC_evstwwo, // Vector Store Word of Word from Odd -PPC_evstwwox, // Vector Store Word of Word from Odd Indexed -PPC_evsubfsmiaaw, // Vector Subtract Signed, Modulo, Integer to Accumulator Word -PPC_evsubfssiaaw, // Vector Subtract Signed, Saturate, Integer to Accumulator Word -PPC_evsubfumiaaw, // Vector Subtract Unsigned, Modulo, Integer to Accumulator Word -PPC_evsubfusiaaw, // Vector Subtract Unsigned, Saturate, Integer to Accumulator Word -PPC_evsubfw, // Vector Subtract from Word -PPC_evsubifw, // Vector Subtract Immediate from Word -PPC_evxor, // Vector XOR - -// SPE.Embedded Float Scalar Double - -PPC_efdabs, // Floating-Point Double-Precision Absolute Value -PPC_efdadd, // Floating-Point Double-Precision Add -PPC_efdcfs, // Floating-Point Double-Precision Convert from Single-Precision -PPC_efdcfsf, // Convert Floating-Point Double-Precision from Signed Fraction -PPC_efdcfsi, // Convert Floating-Point Double-Precision from Signed Integer -PPC_efdcfsid, // Convert Floating-Point Double-Precision from Signed Integer Doubleword -PPC_efdcfuf, // Convert Floating-Point Double-Precision from Unsigned Fraction -PPC_efdcfui, // Convert Floating-Point Double-Precision from Unsigned Integer -PPC_efdcfuid, // Convert Floating-Point Double-Precision from Unsigned Integer Doubleword -PPC_efdcmpeq, // Floating-Point Double-Precision Compare Equal -PPC_efdcmpgt, // Floating-Point Double-Precision Compare Greater Than -PPC_efdcmplt, // Floating-Point Double-Precision Compare Less Than -PPC_efdctsf, // Convert Floating-Point Double-Precision to Signed Fraction -PPC_efdctsi, // Convert Floating-Point Double-Precision to Signed Integer -PPC_efdctsidz, // Convert Floating-Point Double-Precision to Signed Integer Doubleword with Round toward Zero -PPC_efdctsiz, // Convert Floating-Point Double-Precision to Signed Integer with Round toward Zero -PPC_efdctuf, // Convert Floating-Point Double-Precision to Unsigned Fraction -PPC_efdctui, // Convert Floating-Point Double-Precision to Unsigned Integer -PPC_efdctuidz, // Convert Floating-Point Double-Precision to Unsigned Integer Doubleword with Round toward Zero -PPC_efdctuiz, // Convert Floating-Point Double-Precision to Unsigned Integer with Round toward Zero -PPC_efddiv, // Floating-Point Double-Precision Divide -PPC_efdmul, // Floating-Point Double-Precision Multiply -PPC_efdnabs, // Floating-Point Double-Precision Negative Absolute Value -PPC_efdneg, // Floating-Point Double-Precision Negate -PPC_efdsub, // Floating-Point Double-Precision Subtract -PPC_efdtsteq, // Floating-Point Double-Precision Test Equal -PPC_efdtstgt, // Floating-Point Double-Precision Test Greater Than -PPC_efdtstlt, // Floating-Point Double-Precision Test Less Than -PPC_efscfd, // Floating-Point Single-Precision Convert from Double-Precision - -// SPE.Embedded Float Scalar Single - -PPC_efsabs, // Floating-Point Single-Precision Absolute Value -PPC_efsadd, // Floating-Point Single-Precision Add -PPC_efscfsf, // Convert Floating-Point Single-Precision from Signed Fraction -PPC_efscfsi, // Convert Floating-Point Single-Precision from Signed Integer -PPC_efscfuf, // Convert Floating-Point Single-Precision from Unsigned Fraction -PPC_efscfui, // Convert Floating-Point Single-Precision from Unsigned Integer -PPC_efscmpeq, // Floating-Point Single-Precision Compare Equal -PPC_efscmpgt, // Floating-Point Single-Precision Compare Greater Than -PPC_efscmplt, // Floating-Point Single-Precision Compare Less Than -PPC_efsctsf, // Convert Floating-Point Single-Precision to Signed Fraction -PPC_efsctsi, // Convert Floating-Point Single-Precision to Signed Integer -PPC_efsctsiz, // Convert Floating-Point Single-Precision to Signed Integer with Round toward Zero -PPC_efsctuf, // Convert Floating-Point Single-Precision to Unsigned Fraction -PPC_efsctui, // Convert Floating-Point Single-Precision to Unsigned Integer -PPC_efsctuiz, // Convert Floating-Point Single-Precision to Unsigned Integer with Round toward Zero -PPC_efsdiv, // Floating-Point Single-Precision Divide -PPC_efsmul, // Floating-Point Single-Precision Multiply -PPC_efsnabs, // Floating-Point Single-Precision Negative Absolute Value -PPC_efsneg, // Floating-Point Single-Precision Negate -PPC_efssub, // Floating-Point Single-Precision Subtract -PPC_efststeq, // Floating-Point Single-Precision Test Equal -PPC_efststgt, // Floating-Point Single-Precision Test Greater Than -PPC_efststlt, // Floating-Point Single-Precision Test Less Than - -// SPE.Embedded Float Vector - -PPC_evfsabs, // Vector Floating-Point Single-Precision Absolute Value -PPC_evfsadd, // Vector Floating-Point Single-Precision Add -PPC_evfscfsf, // Vector Convert Floating-Point Single-Precision from Signed Fraction -PPC_evfscfsi, // Vector Convert Floating-Point Single-Precision from Signed Integer -PPC_evfscfuf, // Vector Convert Floating-Point Single-Precision from Unsigned Fraction -PPC_evfscfui, // Vector Convert Floating-Point Single-Precision from Unsigned Integer -PPC_evfscmpeq, // Vector Floating-Point Single-Precision Compare Equal -PPC_evfscmpgt, // Vector Floating-Point Single-Precision Compare Greater Than -PPC_evfscmplt, // Vector Floating-Point Single-Precision Compare Less Than -PPC_evfsctsf, // Vector Convert Floating-Point Single-Precision to Signed Fraction -PPC_evfsctsi, // Vector Convert Floating-Point Single-Precision to Signed Integer -PPC_evfsctsiz, // Vector Convert Floating-Point Single-Precision to Signed Integer with Round toward Zero -PPC_evfsctuf, // Vector Convert Floating-Point Single-Precision to Unsigned Fraction -PPC_evfsctui, // Vector Convert Floating-Point Single-Precision to Unsigned Integer -PPC_evfsctuiz, // Vector Convert Floating-Point Single-Precision to Unsigned Integer with Round toward Zero -PPC_evfsdiv, // Vector Floating-Point Single-Precision Divide -PPC_evfsmul, // Vector Floating-Point Single-Precision Multiply -PPC_evfsnabs, // Vector Floating-Point Single-Precision Negative Absolute Value -PPC_evfsneg, // Vector Floating-Point Single-Precision Negate -PPC_evfssub, // Vector Floating-Point Single-Precision Subtract -PPC_evfststeq, // Vector Floating-Point Single-Precision Test Equal -PPC_evfststgt, // Vector Floating-Point Single-Precision Test Greater Than -PPC_evfststlt, // Vector Floating-Point Single-Precision Test Less Than - -// Missing instructions from Power ISA 2.06 - -// category: 64-bit -PPC_bpermd, // Bit Permute Doubleword -PPC_divde, // Divide Doubleword Extended -PPC_divdeu, // Divide Doubleword Extended Unsigned -PPC_ldbrx, // Load Doubleword Byte-Reverse Indexed -PPC_prtyd, // Parity Doubleword -PPC_stdbrx, // Store Doubleword Byte-Reverse Indexed -// category: Base -PPC_cmpb, // Compare Bytes -PPC_divwe, // Divide Word Extended -PPC_divweu, // Divide Word Extended Unsigned -PPC_lbarx, // Load Byte and Reserve Indexed -PPC_lharx, // Load Halfword and Reserve Indexed -PPC_popcntd, // Population Count Doubleword -PPC_popcntw, // Population Count Word -PPC_prtyw, // Parity Word -PPC_stbcx, // Store Byte Conditional Indexed -PPC_sthcx, // Store Halfword Conditional Indexed -// category: Binary Coded Decimal Assist -PPC_addg6s, // Add and Generate Sixes -PPC_cbcdtd, // Convert Binary Coded Decimal to Declets -PPC_cdtbcd, // Convert Declets To Binary Coded Decimal -// category: Decimal Floating-Point -PPC_dadd, // DFP Add -PPC_daddq, // DFP Add Quad -PPC_dcffix, // DFP Convert From Fixed -PPC_dcffixq, // DFP Convert From Fixed Quad -PPC_dcmpo, // DFP Compare Ordered -PPC_dcmpoq, // DFP Compare Ordered Quad -PPC_dcmpu, // DFP Compare Unordered -PPC_dcmpuq, // DFP Compare Unordered Quad -PPC_dctdp, // DFP Convert To DFP Long -PPC_dctfix, // DFP Convert To Fixed -PPC_dctfixq, // DFP Convert To Fixed Quad -PPC_dctqpq, // DFP Convert To DFP Extended -PPC_ddedpd, // DFP Decode DPD To BCD -PPC_ddedpdq, // DFP Decode DPD To BCD Quad -PPC_ddiv, // DFP Divide -PPC_ddivq, // DFP Divide Quad -PPC_denbcd, // DFP Encode BCD To DPD -PPC_denbcdq, // DFP Encode BCD To DPD Quad -PPC_diex, // DFP Insert Biased Exponent -PPC_diexq, // DFP Insert Biased Exponent Quad -PPC_dmul, // DFP Multiply -PPC_dmulq, // DFP Multiply Quad -PPC_dqua, // DFP Quantize -PPC_dquai, // DFP Quantize Immediate -PPC_dquaiq, // DFP Quantize Immediate Quad -PPC_dquaq, // DFP Quantize Quad -PPC_drdpq, // DFP Round To DFP Long -PPC_drintn, // DFP Round To FP Integer Without Inexact -PPC_drintnq, // DFP Round To FP Integer Without Inexact Quad -PPC_drintx, // DFP Round To FP Integer With Inexact -PPC_drintxq, // DFP Round To FP Integer With Inexact Quad -PPC_drrnd, // DFP Reround -PPC_drrndq, // DFP Reround Quad -PPC_drsp, // DFP Round To DFP Short -PPC_dscli, // DFP Shift Significand Left Immediate -PPC_dscliq, // DFP Shift Significand Left Immediate Quad -PPC_dscri, // DFP Shift Significand Right Immediate -PPC_dscriq, // DFP Shift Significand Right Immediate Quad -PPC_dsub, // DFP Subtract -PPC_dsubq, // DFP Subtract Quad -PPC_dtstdc, // DFP Test Data Class -PPC_dtstdcq, // DFP Test Data Class Quad -PPC_dtstdg, // DFP Test Data Group -PPC_dtstdgq, // DFP Test Data Group Quad -PPC_dtstex, // DFP Test Exponent -PPC_dtstexq, // DFP Test Exponent Quad -PPC_dtstsf, // DFP Test Significance -PPC_dtstsfq, // DFP Test Significance Quad -PPC_dxex, // DFP Extract Biased Exponent -PPC_dxexq, // DFP Extract Biased Exponent Quad -// category: Decorated Storage -PPC_dsn, // Decorated Storage Notify -PPC_lbdx, // Load Byte with Decoration Indexed -PPC_lddx, // Load Doubleword with Decoration Indexed -PPC_lfddx, // Load Floating Doubleword with Decoration Indexed -PPC_lhdx, // Load Halfword with Decoration Indexed -PPC_lwdx, // Load Word with Decoration Indexed -PPC_stbdx, // Store Byte with Decoration Indexed -PPC_stddx, // Store Doubleword with Decoration Indexed -PPC_stfddx, // Store Floating Doubleword with Decoration Indexed -PPC_sthdx, // Store Halfword with Decoration Indexed -PPC_stwdx, // Store Word with Decoration Indexed -// category: Embedded -PPC_mbar, // Memory Barrier -PPC_rfmci, // Return From Machine Check Interrupt -PPC_tlbilx, // TLB Invalidate Local -PPC_dci, // Data Cache Invalidate -PPC_ici, // Instruction Cache Invalidate -PPC_mfdcrux, // Move From Device Control Register User-mode Indexed -PPC_mfdcrx, // Move From Device Control Register Indexed -PPC_mtdcrux, // Move To Device Control Register User-mode Indexed -PPC_mtdcrx, // Move To Device Control Register Indexed -// category: Embedded.Enhanced Debug -PPC_dnh, // Debugger Notify Halt -// category: Embedded.Hypervisor -PPC_ehpriv, // Embedded Hypervisor Privilege -PPC_rfgi, // Return From Guest Interrupt -// category: Embedded.Processor Control -PPC_msgclr, // Message Clear -PPC_msgsnd, // Message Send -// category: Embedded.External PID -PPC_dcbfep, // Data Cache Block Flush by External PID -PPC_dcbstep, // Data Cache Block Store by External PID -PPC_dcbtep, // Data Cache Block Touch by External PID -PPC_dcbtstep, // Data Cache Block Touch for Store by External PID -PPC_dcbzep, // Data Cache Block set to Zero by External PID -PPC_evlddepx, // Vector Load Doubleword into Doubleword by External Process ID Indexed -PPC_evstddepx, // Vector Store Doubleword into Doubleword by External Process ID Indexed -PPC_icbiep, // Instruction Cache Block Invalidate by External PID -PPC_lbepx, // Load Byte by External Process ID Indexed -PPC_lfdepx, // Load Floating-Point Double by External Process ID Indexed -PPC_lhepx, // Load Halfword by External Process ID Indexed -PPC_lvepx, // Load Vector by External Process ID Indexed -PPC_lvepxl, // Load Vector by External Process ID Indexed LRU -PPC_lwepx, // Load Word by External Process ID Indexed -PPC_stbepx, // Store Byte by External Process ID Indexed -PPC_stfdepx, // Store Floating-Point Double by External Process ID Indexed -PPC_sthepx, // Store Halfword by External Process ID Indexed -PPC_stvepx, // Store Vector by External Process ID Indexed -PPC_stvepxl, // Store Vector by External Process ID Indexed LRU -PPC_stwepx, // Store Word by External Process ID Indexed -PPC_ldepx, // Load Doubleword by External Process ID Indexed -PPC_stdepx, // Store Doubleword by External Process ID Indexed -// category: Embedded.Performance Monitor -PPC_mfpmr, // Move From Performance Monitor Register -PPC_mtpmr, // Move To Performance Monitor Register -// category: Embedded.Thread Management -PPC_mftmr, // Move From Thread Management Register -PPC_mttmr, // Move To Thread Management Register -// category: Embedded.TLB Write Conditional -PPC_tlbsrx, // TLB Search and Reserve -// category: Floating-point -PPC_fcfids, // Floating Convert From Integer Doubleword Single -PPC_fcfidu, // Floating Convert From Integer Doubleword Unsigned -PPC_fcfidus, // Floating Convert From Integer Doubleword Unsigned Single -PPC_fctidu, // Floating Convert To Integer Doubleword Unsigned -PPC_fctiduz, // Floating Convert To Integer Doubleword Unsigned with round toward Zero -PPC_fctiwu, // Floating Convert To Integer Word Unsigned -PPC_fctiwuz, // Floating Convert To Integer Word Unsigned with round toward Zero -PPC_ftdiv, // Floating Test for software Divide -PPC_ftsqrt, // Floating Test for software Square Root -PPC_lfiwax, // Load Floating-Point as Integer Word Algebraic Indexed -PPC_lfiwzx, // Load Floating-Point as Integer Word and Zero Indexed -PPC_lfdp, // Load Floating-Point Double Pair -PPC_lfdpx, // Load Floating-Point Double Pair Indexed -PPC_stfdp, // Store Floating-Point Double Pair -PPC_stfdpx, // Store Floating-Point Double Pair Indexed -PPC_fcpsgn, // Floating Copy Sign -PPC_fre, // Floating Reciprocal Estimate -PPC_frim, // Floating Round to Integer Minus -PPC_frin, // Floating Round to Integer Nearest -PPC_frip, // Floating Round to Integer Plus -PPC_friz, // Floating Round to Integer Toward Zero -// category: Legacy Integer Multiply-Accumulate -PPC_macchw, // Multiply Accumulate Cross Halfword to Word Modulo Signed -PPC_macchws, // Multiply Accumulate Cross Halfword to Word Saturate Signed -PPC_macchwsu, // Multiply Accumulate Cross Halfword to Word Saturate Unsigned -PPC_macchwu, // Multiply Accumulate Cross Halfword to Word Modulo Unsigned -PPC_machhw, // Multiply Accumulate High Halfword to Word Modulo Signed -PPC_machhws, // Multiply Accumulate High Halfword to Word Saturate Signed -PPC_machhwsu, // Multiply Accumulate High Halfword to Word Saturate Unsigned -PPC_machhwu, // Multiply Accumulate High Halfword to Word Modulo Unsigned -PPC_maclhw, // Multiply Accumulate Low Halfword to Word Modulo Signed -PPC_maclhws, // Multiply Accumulate Low Halfword to Word Saturate Signed -PPC_maclhwsu, // Multiply Accumulate Low Halfword to Word Saturate Unsigned -PPC_maclhwu, // Multiply Accumulate Low Halfword to Word Modulo Unsigned -PPC_mulchw, // Multiply Cross Halfword to Word Signed -PPC_mulchwu, // Multiply Cross Halfword to Word Unsigned -PPC_mulhhw, // Multiply High Halfword to Word Signed -PPC_mulhhwu, // Multiply High Halfword to Word Unsigned -PPC_mullhw, // Multiply Low Halfword to Word Signed -PPC_mullhwu, // Multiply Low Halfword to Word Unsigned -PPC_nmacchw, // Negative Multiply Accumulate Cross Halfword to Word Modulo Signed -PPC_nmacchws, // Negative Multiply Accumulate Cross Halfword to Word Saturate Signed -PPC_nmachhw, // Negative Multiply Accumulate High Halfword to Word Modulo Signed -PPC_nmachhws, // Negative Multiply Accumulate High Halfword to Word Saturate Signed -PPC_nmaclhw, // Negative Multiply Accumulate Low Halfword to Word Modulo Signed -PPC_nmaclhws, // Negative Multiply Accumulate Low Halfword to Word Saturate Signed -// category: Legacy Move Assist -PPC_dlmzb, // Determine Leftmost Zero Byte -// category: Load/Store Quadword -PPC_lq, // Load Quadword -PPC_stq, // Store Quadword -// category: Server -PPC_doze, // Doze -PPC_lbzcix, // Load Byte and Zero Caching Inhibited Indexed -PPC_ldcix, // Load Doubleword Caching Inhibited Indexed -PPC_lhzcix, // Load Halfword and Zero Caching Inhibited Indexed -PPC_lwzcix, // Load Word and Zero Caching Inhibited Indexed -PPC_nap, // Nap -PPC_rvwinkle, // Rip Van Winkle -PPC_slbfee, // SLB Find Entry ESID -PPC_sleep, // Sleep -PPC_stbcix, // Store Byte Caching Inhibited Indexed -PPC_stdcix, // Store Doubleword Caching Inhibited Indexed -PPC_sthcix, // Store Halfword Caching Inhibited Indexed -PPC_stwcix, // Store Word Caching Inhibited Indexed -PPC_tlbiel, // TLB Invalidate Entry Local, ISA 3.0 format -// category: Vector -PPC_lvebx, // Load Vector Element Byte Indexed -PPC_lvehx, // Load Vector Element Halfword Indexed -PPC_lvewx, // Load Vector Element Word Indexed -PPC_lvsl, // Load Vector for Shift Left Indexed -PPC_lvsr, // Load Vector for Shift Right Indexed -PPC_lvx, // Load Vector Indexed -PPC_lvxl, // Load Vector Indexed LRU -PPC_mfvscr, // Move From Vector Status and Control Register -PPC_mtvscr, // Move To Vector Status and Control Register -PPC_stvebx, // Store Vector Element Byte Indexed -PPC_stvehx, // Store Vector Element Halfword Indexed -PPC_stvewx, // Store Vector Element Word Indexed -PPC_stvx, // Store Vector Indexed -PPC_stvxl, // Store Vector Indexed LRU -PPC_vaddcuw, // Vector Add and Write Carry-Out Unsigned Word -PPC_vaddfp, // Vector Add Single-Precision -PPC_vaddsbs, // Vector Add Signed Byte Saturate -PPC_vaddshs, // Vector Add Signed Halfword Saturate -PPC_vaddsws, // Vector Add Signed Word Saturate -PPC_vaddubm, // Vector Add Unsigned Byte Modulo -PPC_vaddubs, // Vector Add Unsigned Byte Saturate -PPC_vadduhm, // Vector Add Unsigned Halfword Modulo -PPC_vadduhs, // Vector Add Unsigned Halfword Saturate -PPC_vadduwm, // Vector Add Unsigned Word Modulo -PPC_vadduws, // Vector Add Unsigned Word Saturate -PPC_vand, // Vector Logical AND -PPC_vandc, // Vector Logical AND with Complement -PPC_vavgsb, // Vector Average Signed Byte -PPC_vavgsh, // Vector Average Signed Halfword -PPC_vavgsw, // Vector Average Signed Word -PPC_vavgub, // Vector Average Unsigned Byte -PPC_vavguh, // Vector Average Unsigned Halfword -PPC_vavguw, // Vector Average Unsigned Word -PPC_vcfsx, // Vector Convert From Signed Fixed-Point Word -PPC_vcfux, // Vector Convert From Unsigned Fixed-Point Word -PPC_vcmpbfp, // Vector Compare Bounds Single-Precision -PPC_vcmpeqfp, // Vector Compare Equal To Single-Precision -PPC_vcmpequb, // Vector Compare Equal To Unsigned Byte -PPC_vcmpequh, // Vector Compare Equal To Unsigned Halfword -PPC_vcmpequw, // Vector Compare Equal To Unsigned Word -PPC_vcmpgefp, // Vector Compare Greater Than or Equal To Single-Precision -PPC_vcmpgtfp, // Vector Compare Greater Than Single-Precision -PPC_vcmpgtsb, // Vector Compare Greater Than Signed Byte -PPC_vcmpgtsh, // Vector Compare Greater Than Signed Halfword -PPC_vcmpgtsw, // Vector Compare Greater Than Signed Word -PPC_vcmpgtub, // Vector Compare Greater Than Unsigned Byte -PPC_vcmpgtuh, // Vector Compare Greater Than Unsigned Halfword -PPC_vcmpgtuw, // Vector Compare Greater Than Unsigned Word -PPC_vctsxs, // Vector Convert To Signed Fixed-Point Word Saturate -PPC_vctuxs, // Vector Convert To Unsigned Fixed-Point Word Saturate -PPC_vexptefp, // Vector 2 Raised to the Exponent Estimate FloatingPoint -PPC_vlogefp, // Vector Log Base 2 Estimate Floating-Point -PPC_vmaddfp, // Vector Multiply-Add Single-Precision -PPC_vmaxfp, // Vector Maximum Single-Precision -PPC_vmaxsb, // Vector Maximum Signed Byte -PPC_vmaxsh, // Vector Maximum Signed Halfword -PPC_vmaxsw, // Vector Maximum Signed Word -PPC_vmaxub, // Vector Maximum Unsigned Byte -PPC_vmaxuh, // Vector Maximum Unsigned Halfword -PPC_vmaxuw, // Vector Maximum Unsigned Word -PPC_vmhaddshs, // Vector Multiply-High-Add Signed Halfword Saturate -PPC_vmhraddshs, // Vector Multiply-High-Round-Add Signed Halfword Saturate -PPC_vminfp, // Vector Minimum Single-Precision -PPC_vminsb, // Vector Minimum Signed Byte -PPC_vminsh, // Vector Minimum Signed Halfword -PPC_vminsw, // Vector Minimum Signed Word -PPC_vminub, // Vector Minimum Unsigned Byte -PPC_vminuh, // Vector Minimum Unsigned Halfword -PPC_vminuw, // Vector Minimum Unsigned Word -PPC_vmladduhm, // Vector Multiply-Low-Add Unsigned Halfword Modulo -PPC_vmrghb, // Vector Merge High Byte -PPC_vmrghh, // Vector Merge High Halfword -PPC_vmrghw, // Vector Merge High Word -PPC_vmrglb, // Vector Merge Low Byte -PPC_vmrglh, // Vector Merge Low Halfword -PPC_vmrglw, // Vector Merge Low Word -PPC_vmsummbm, // Vector Multiply-Sum Mixed Byte Modulo -PPC_vmsumshm, // Vector Multiply-Sum Signed Halfword Modulo -PPC_vmsumshs, // Vector Multiply-Sum Signed Halfword Saturate -PPC_vmsumubm, // Vector Multiply-Sum Unsigned Byte Modulo -PPC_vmsumuhm, // Vector Multiply-Sum Unsigned Halfword Modulo -PPC_vmsumuhs, // Vector Multiply-Sum Unsigned Halfword Saturate -PPC_vmulesb, // Vector Multiply Even Signed Byte -PPC_vmulesh, // Vector Multiply Even Signed Halfword -PPC_vmuleub, // Vector Multiply Even Unsigned Byte -PPC_vmuleuh, // Vector Multiply Even Unsigned Halfword -PPC_vmulosb, // Vector Multiply Odd Signed Byte -PPC_vmulosh, // Vector Multiply Odd Signed Halfword -PPC_vmuloub, // Vector Multiply Odd Unsigned Byte -PPC_vmulouh, // Vector Multiply Odd Unsigned Halfword -PPC_vnmsubfp, // Vector Negative Multiply-Subtract Single-Precision -PPC_vnor, // Vector Logical NOR -PPC_vor, // Vector Logical OR -PPC_vperm, // Vector Permute -PPC_vpkpx, // Vector Pack Pixel -PPC_vpkshss, // Vector Pack Signed Halfword Signed Saturate -PPC_vpkshus, // Vector Pack Signed Halfword Unsigned Saturate -PPC_vpkswss, // Vector Pack Signed Word Signed Saturate -PPC_vpkswus, // Vector Pack Signed Word Unsigned Saturate -PPC_vpkuhum, // Vector Pack Unsigned Halfword Unsigned Modulo -PPC_vpkuhus, // Vector Pack Unsigned Halfword Unsigned Saturate -PPC_vpkuwum, // Vector Pack Unsigned Word Unsigned Modulo -PPC_vpkuwus, // Vector Pack Unsigned Word Unsigned Saturate -PPC_vrefp, // Vector Reciprocal Estimate Single-Precision -PPC_vrfim, // Vector Round to Single-Precision Integer toward -Infinity -PPC_vrfin, // Vector Round to Single-Precision Integer Nearest -PPC_vrfip, // Vector Round to Single-Precision Integer toward +Infinity -PPC_vrfiz, // Vector Round to Single-Precision Integer toward Zero -PPC_vrlb, // Vector Rotate Left Byte -PPC_vrlh, // Vector Rotate Left Halfword -PPC_vrlw, // Vector Rotate Left Word -PPC_vrsqrtefp, // Vector Reciprocal Square Root Estimate Single-Precision -PPC_vsel, // Vector Select -PPC_vsl, // Vector Shift Left -PPC_vslb, // Vector Shift Left Byte -PPC_vsldoi, // Vector Shift Left Double by Octet Immediate -PPC_vslh, // Vector Shift Left Halfword -PPC_vslo, // Vector Shift Left by Octet -PPC_vslw, // Vector Shift Left Word -PPC_vspltb, // Vector Splat Byte -PPC_vsplth, // Vector Splat Halfword -PPC_vspltisb, // Vector Splat Immediate Signed Byte -PPC_vspltish, // Vector Splat Immediate Signed Halfword -PPC_vspltisw, // Vector Splat Immediate Signed Word -PPC_vspltw, // Vector Splat Word -PPC_vsr, // Vector Shift Right -PPC_vsrab, // Vector Shift Right Algebraic Byte -PPC_vsrah, // Vector Shift Right Algebraic Halfword -PPC_vsraw, // Vector Shift Right Algebraic Word -PPC_vsrb, // Vector Shift Right Byte -PPC_vsrh, // Vector Shift Right Halfword -PPC_vsro, // Vector Shift Right by Octet -PPC_vsrw, // Vector Shift Right Word -PPC_vsubcuw, // Vector Subtract and Write Carry-Out Unsigned Word -PPC_vsubfp, // Vector Subtract Single-Precision -PPC_vsubsbs, // Vector Subtract Signed Byte Saturate -PPC_vsubshs, // Vector Subtract Signed Halfword Saturate -PPC_vsubsws, // Vector Subtract Signed Word Saturate -PPC_vsububm, // Vector Subtract Unsigned Byte Modulo -PPC_vsububs, // Vector Subtract Unsigned Byte Saturate -PPC_vsubuhm, // Vector Subtract Unsigned Halfword Modulo -PPC_vsubuhs, // Vector Subtract Unsigned Halfword Saturate -PPC_vsubuwm, // Vector Subtract Unsigned Word Modulo -PPC_vsubuws, // Vector Subtract Unsigned Word Saturate -PPC_vsum2sws, // Vector Sum across Half Signed Word Saturate -PPC_vsum4sbs, // Vector Sum across Quarter Signed Byte Saturate -PPC_vsum4shs, // Vector Sum across Quarter Signed Halfword Saturate -PPC_vsum4ubs, // Vector Sum across Quarter Unsigned Byte Saturate -PPC_vsumsws, // Vector Sum across Signed Word Saturate -PPC_vupkhpx, // Vector Unpack High Pixel -PPC_vupkhsb, // Vector Unpack High Signed Byte -PPC_vupkhsh, // Vector Unpack High Signed Halfword -PPC_vupklpx, // Vector Unpack Low Pixel -PPC_vupklsb, // Vector Unpack Low Signed Byte -PPC_vupklsh, // Vector Unpack Low Signed Halfword -PPC_vxor, // Vector Logical XOR -// category: Vector-Scalar Floating-Point -PPC_lxsdx, // Load VSR Scalar Doubleword Indexed -PPC_lxvd2x, // Load VSR Vector Doubleword*2 Indexed -PPC_lxvdsx, // Load VSR Vector Doubleword & Splat Indexed -PPC_lxvw4x, // Load VSR Vector Word*4 Indexed -PPC_stxsdx, // Store VSR Scalar Doubleword Indexed -PPC_stxvd2x, // Store VSR Vector Doubleword*2 Indexed -PPC_stxvw4x, // Store VSR Vector Word*4 Indexed -PPC_xsabsdp, // VSX Scalar Absolute Value Double-Precision -PPC_xsadddp, // VSX Scalar Add Double-Precision -PPC_xscmpodp, // VSX Scalar Compare Ordered Double-Precision -PPC_xscmpudp, // VSX Scalar Compare Unordered Double-Precision -PPC_xscpsgndp, // VSX Scalar Copy Sign Double-Precision -PPC_xscvdpsp, // VSX Scalar Convert Double-Precision to SinglePrecision -PPC_xscvdpsxds, // VSX Scalar truncate Double-Precision to integer and Convert to Signed Fixed-Point Doubleword format with Saturate -PPC_xscvdpsxws, // VSX Scalar truncate Double-Precision to integer and Convert to Signed Fixed-Point Word format with Saturate -PPC_xscvdpuxds, // VSX Scalar truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Doubleword format with Saturate -PPC_xscvdpuxws, // VSX Scalar truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Word format with Saturate -PPC_xscvspdp, // VSX Scalar Convert Single-Precision to DoublePrecision format -PPC_xscvsxddp, // VSX Scalar Convert and round Signed Fixed-Point Doubleword to Double-Precision format -PPC_xscvuxddp, // VSX Scalar Convert and round Unsigned Fixed-Point Doubleword to Double-Precision format -PPC_xsdivdp, // VSX Scalar Divide Double-Precision -PPC_xsmaddadp, // VSX Scalar Multiply-Add Type-A Double-Precision -PPC_xsmaddmdp, // VSX Scalar Multiply-Add Type-M Double-Precision -PPC_xsmaxdp, // VSX Scalar Maximum Double-Precision -PPC_xsmindp, // VSX Scalar Minimum Double-Precision -PPC_xsmsubadp, // VSX Scalar Multiply-Subtract Type-A Double-Precision -PPC_xsmsubmdp, // VSX Scalar Multiply-Subtract Type-M Double-Precision -PPC_xsmuldp, // VSX Scalar Multiply Double-Precision -PPC_xsnabsdp, // VSX Scalar Negative Absolute Value Double-Precision -PPC_xsnegdp, // VSX Scalar Negate Double-Precision -PPC_xsnmaddadp, // VSX Scalar Negative Multiply-Add Type-A DoublePrecision -PPC_xsnmaddmdp, // VSX Scalar Negative Multiply-Add Type-M DoublePrecision -PPC_xsnmsubadp, // VSX Scalar Negative Multiply-Subtract Type-A DoublePrecision -PPC_xsnmsubmdp, // VSX Scalar Negative Multiply-Subtract Type-M DoublePrecision -PPC_xsrdpi, // VSX Scalar Round to Double-Precision Integer -PPC_xsrdpic, // VSX Scalar Round to Double-Precision Integer using Current rounding mode -PPC_xsrdpim, // VSX Scalar Round to Double-Precision Integer toward Infinity -PPC_xsrdpip, // VSX Scalar Round to Double-Precision Integer toward + Infinity -PPC_xsrdpiz, // VSX Scalar Round to Double-Precision Integer toward Zero -PPC_xsredp, // VSX Scalar Reciprocal Estimate Double-Precision -PPC_xsrsqrtedp, // VSX Scalar Reciprocal Square Root Estimate DoublePrecision -PPC_xssqrtdp, // VSX Scalar Square Root Double-Precision -PPC_xssubdp, // VSX Scalar Subtract Double-Precision -PPC_xstdivdp, // VSX Scalar Test for software Divide Double-Precision -PPC_xstsqrtdp, // VSX Scalar Test for software Square Root DoublePrecision -PPC_xvabsdp, // VSX Vector Absolute Value Double-Precision -PPC_xvabssp, // VSX Vector Absolute Value Single-Precision -PPC_xvadddp, // VSX Vector Add Double-Precision -PPC_xvaddsp, // VSX Vector Add Single-Precision -PPC_xvcmpeqdp, // VSX Vector Compare Equal To Double-Precision -PPC_xvcmpeqsp, // VSX Vector Compare Equal To Single-Precision -PPC_xvcmpgedp, // VSX Vector Compare Greater Than or Equal To Double-Precision -PPC_xvcmpgesp, // VSX Vector Compare Greater Than or Equal To SinglePrecision -PPC_xvcmpgtdp, // VSX Vector Compare Greater Than Double-Precision -PPC_xvcmpgtsp, // VSX Vector Compare Greater Than Single-Precision -PPC_xvcpsgndp, // VSX Vector Copy Sign Double-Precision -PPC_xvcpsgnsp, // VSX Vector Copy Sign Single-Precision -PPC_xvcvdpsp, // VSX Vector round and Convert Double-Precision to Single-Precision format -PPC_xvcvdpsxds, // VSX Vector truncate Double-Precision to integer and Convert to Signed Fixed-Point Doubleword Saturate -PPC_xvcvdpsxws, // VSX Vector truncate Double-Precision to integer and Convert to Signed Fixed-Point Word Saturate -PPC_xvcvdpuxds, // VSX Vector truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Doubleword format with Saturate -PPC_xvcvdpuxws, // VSX Vector truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Word format with Saturate -PPC_xvcvspdp, // VSX Vector Convert Single-Precision to DoublePrecision -PPC_xvcvspsxds, // VSX Vector truncate Single-Precision to integer and Convert to Signed Fixed-Point Doubleword format with Saturate -PPC_xvcvspsxws, // VSX Vector truncate Single-Precision to integer and Convert to Signed Fixed-Point Word format with Saturate -PPC_xvcvspuxds, // VSX Vector truncate Single-Precision to integer and Convert to Unsigned Fixed-Point Doubleword format with Saturate -PPC_xvcvspuxws, // VSX Vector truncate Single-Precision to integer and Convert to Unsigned Fixed-Point Word Saturate -PPC_xvcvsxddp, // VSX Vector Convert and round Signed Fixed-Point Doubleword to Double-Precision format -PPC_xvcvsxdsp, // VSX Vector Convert and round Signed Fixed-Point Doubleword to Single-Precision format -PPC_xvcvsxwdp, // VSX Vector Convert Signed Fixed-Point Word to Double-Precision format -PPC_xvcvsxwsp, // VSX Vector Convert and round Signed Fixed-Point Word to Single-Precision format -PPC_xvcvuxddp, // VSX Vector Convert and round Unsigned Fixed-Point Doubleword to Double-Precision format -PPC_xvcvuxdsp, // VSX Vector Convert and round Unsigned Fixed-Point Doubleword to Single-Precision format -PPC_xvcvuxwdp, // VSX Vector Convert Unsigned Fixed-Point Word to Double-Precision format -PPC_xvcvuxwsp, // VSX Vector Convert and round Unsigned Fixed-Point Word to Single-Precision format -PPC_xvdivdp, // VSX Vector Divide Double-Precision -PPC_xvdivsp, // VSX Vector Divide Single-Precision -PPC_xvmaddadp, // VSX Vector Multiply-Add Type-A Double-Precision -PPC_xvmaddasp, // VSX Vector Multiply-Add Type-A Single-Precision -PPC_xvmaddmdp, // VSX Vector Multiply-Add Type-M Double-Precision -PPC_xvmaddmsp, // VSX Vector Multiply-Add Type-M Single-Precision -PPC_xvmaxdp, // VSX Vector Maximum Double-Precision -PPC_xvmaxsp, // VSX Vector Maximum Single-Precision -PPC_xvmindp, // VSX Vector Minimum Double-Precision -PPC_xvminsp, // VSX Vector Minimum Single-Precision -PPC_xvmsubadp, // VSX Vector Multiply-Subtract Type-A Double-Precision -PPC_xvmsubasp, // VSX Vector Multiply-Subtract Type-A Single-Precision -PPC_xvmsubmdp, // VSX Vector Multiply-Subtract Type-M Double-Precision -PPC_xvmsubmsp, // VSX Vector Multiply-Subtract Type-M Single-Precision -PPC_xvmuldp, // VSX Vector Multiply Double-Precision -PPC_xvmulsp, // VSX Vector Multiply Single-Precision -PPC_xvnabsdp, // VSX Vector Negative Absolute Value Double-Precision -PPC_xvnabssp, // VSX Vector Negative Absolute Value Single-Precision -PPC_xvnegdp, // VSX Vector Negate Double-Precision -PPC_xvnegsp, // VSX Vector Negate Single-Precision -PPC_xvnmaddadp, // VSX Vector Negative Multiply-Add Type-A DoublePrecision -PPC_xvnmaddasp, // VSX Vector Negative Multiply-Add Type-A SinglePrecision -PPC_xvnmaddmdp, // VSX Vector Negative Multiply-Add Type-M DoublePrecision -PPC_xvnmaddmsp, // VSX Vector Negative Multiply-Add Type-M SinglePrecision -PPC_xvnmsubadp, // VSX Vector Negative Multiply-Subtract Type-A DoublePrecision -PPC_xvnmsubasp, // VSX Vector Negative Multiply-Subtract Type-A SinglePrecision -PPC_xvnmsubmdp, // VSX Vector Negative Multiply-Subtract Type-M DoublePrecision -PPC_xvnmsubmsp, // VSX Vector Negative Multiply-Subtract Type-M SinglePrecision -PPC_xvrdpi, // VSX Vector Round to Double-Precision Integer -PPC_xvrdpic, // VSX Vector Round to Double-Precision Integer using Current rounding mode -PPC_xvrdpim, // VSX Vector Round to Double-Precision Integer toward Infinity -PPC_xvrdpip, // VSX Vector Round to Double-Precision Integer toward + Infinity -PPC_xvrdpiz, // VSX Vector Round to Double-Precision Integer toward Zero -PPC_xvredp, // VSX Vector Reciprocal Estimate Double-Precision -PPC_xvresp, // VSX Vector Reciprocal Estimate Single-Precision -PPC_xvrspi, // VSX Vector Round to Single-Precision Integer -PPC_xvrspic, // VSX Vector Round to Single-Precision Integer using Current rounding mode -PPC_xvrspim, // VSX Vector Round to Single-Precision Integer toward Infinity -PPC_xvrspip, // VSX Vector Round to Single-Precision Integer toward + Infinity -PPC_xvrspiz, // VSX Vector Round to Single-Precision Integer toward Zero -PPC_xvrsqrtedp, // VSX Vector Reciprocal Square Root Estimate DoublePrecision -PPC_xvrsqrtesp, // VSX Vector Reciprocal Square Root Estimate SinglePrecision -PPC_xvsqrtdp, // VSX Vector Square Root Double-Precision -PPC_xvsqrtsp, // VSX Vector Square Root Single-Precision -PPC_xvsubdp, // VSX Vector Subtract Double-Precision -PPC_xvsubsp, // VSX Vector Subtract Single-Precision -PPC_xvtdivdp, // VSX Vector Test for software Divide Double-Precision -PPC_xvtdivsp, // VSX Vector Test for software Divide Single-Precision -PPC_xvtsqrtdp, // VSX Vector Test for software Square Root DoublePrecision -PPC_xvtsqrtsp, // VSX Vector Test for software Square Root SinglePrecision -PPC_xxland, // VSX Logical AND -PPC_xxlandc, // VSX Logical AND with Complement -PPC_xxlnor, // VSX Logical NOR -PPC_xxlor, // VSX Logical OR -PPC_xxlxor, // VSX Logical XOR -PPC_xxmrghw, // VSX Merge High Word -PPC_xxmrglw, // VSX Merge Low Word -PPC_xxpermdi, // VSX Permute Doubleword Immediate -PPC_xxsel, // VSX Select -PPC_xxsldwi, // VSX Shift Left Double by Word Immediate -PPC_xxspltw, // VSX Splat Word -// category: Wait -PPC_wait, // Wait - -// Obsolete AltiVec instructions - -PPC_dss, // Data Stream Stop -PPC_dssall, // Data Stream Stop All -PPC_dst, // Data Stream Touch -PPC_dstt, // Data Stream Touch Transient -PPC_dstst, // Data Stream Touch for Store -PPC_dststt, // Data Stream Touch for Store Transient - -// Cell BE AltiVec extension -PPC_lvlx, // Load Vector Left Indexed -PPC_lvlxl, // Load Vector Left Indexed Last -PPC_lvrx, // Load Vector Right Indexed -PPC_lvrxl, // Load Vector Right Indexed Last -PPC_stvlx, // Store Vector Left Indexed -PPC_stvlxl, // Store Vector Left Indexed Last -PPC_stvrx, // Store Vector Right Indexed -PPC_stvrxl, // Store Vector Right Indexed Last - -// VLE instructions that don't have matching mnemonics -PPC_add16i, // [e_add16i] Add Immediate -PPC_add2i, // [e_add2i] Add (2 operand) Immediate and Record -PPC_add2is, // [e_add2is] Add (2 operand) Immediate Shifted -PPC_and2i, // [e_and2i] AND (two operand) Immediate -PPC_and2is, // [e_and2is] AND (2 operand) Immediate Shifted -PPC_cmp16i, // [e_cmp16i] Compare Immediate Word -PPC_cmph, // [e_cmph] Compare Halfword -PPC_cmph16i, // [e_cmph16i] Compare Halfword Immediate -PPC_cmphl, // [e_cmphl] Compare Halfword Logical -PPC_cmphl16i, // [e_cmphl16i] Compare Halfword Logical Immediate -PPC_cmpl16i, // [e_cmpl16i] Compare Logical Immediate Word -PPC_mull2i, // [e_mull2i] Multiply (2 operand) Low Immediate -PPC_or2i, // [e_or2i] OR (two operand) Immediate -PPC_or2is, // [e_or2is] OR (2 operand) Immediate Shifted -PPC_rlw, // [e_rlw] Rotate Left Word -PPC_rlwi, // [e_rlwi] Rotate Left Word Immediate -PPC_bclri, // [se_bclri] Bit Clear Immediate -//PPC_bctr, // [se_bctr] Branch to Count Register -//PPC_bctrl, // [se_bctrl] Branch to Count Register and Link -PPC_bgeni, // [se_bgeni] Bit Generate Immediate -PPC_bmaski, // [se_bmaski] Bit Mask Generate Immediate -PPC_bseti, // [se_bseti] Bit Set Immediate -PPC_btsti, // [se_btsti] Bit Test Immediate -PPC_extzb, // [se_extzb] Extend Zero Byte -PPC_extzh, // [se_extzh] Extend Zero Halfword -PPC_illegal, // [se_illegal] Illegal -PPC_mfar, // [se_mfar] Move from Alternate Register -PPC_mtar, // [se_mtar] Move To Alternate Register -PPC_sub, // [se_sub] Subtract -// simplified VLE mnemonics -PPC_sub16i, // [e_sub16i] Subtract Immediate -PPC_sub2i, // [e_sub2i] Subtract (2 operand) Immediate -PPC_sub2is, // [e_sub2is] Subtract (2 operand) Immediate Shifted - -// misc extended mnemonics -PPC_extldi, // Extract and Left Justify Immediate -PPC_extrdi, // Extract and Right Justify Immediate -PPC_insrdi, // Insert from Right Immediate -PPC_rotldi, // Rotate Left Immediate -PPC_rotrdi, // Rotate Right Immediate -PPC_rotld, // Rotate Left -PPC_sldi, // Shift Left Immediate -PPC_srdi, // Shift Right Immediate -PPC_clrldi, // Clear Left Immediate -PPC_clrrdi, // Clear Right Immediate -PPC_clrlsldi, // Clear Left and Shift Left Immediate - -PPC_xnop, // Extended No Operation -PPC_hnop, // Reserved no-op hint -PPC_dcbfl, // Data Cache Block Flush Local -PPC_dcbflp, // Data Cache Block Flush Local Primary -PPC_dcbtt, // Data Cache Block Touch -PPC_dcbtstt, // Data Cache Block Touch for Store -PPC_lwsync, // Lightweight Sync -PPC_ptesync, // Page Table Entry Sync -PPC_waitrsv, // Wait For Reservation Loss -PPC_waitimpl, // Wait For Implementation-specific Condition -PPC_evmr, // Vector Move -PPC_evnot, // Vector Not -PPC_mtcr, // Move to Condition Register -PPC_xvmovdp, // VSX Vector Copy Double-Precision -PPC_xvmovsp, // VSX Vector Copy Single-Precision -PPC_xxspltd, // VSX Splat Doubleword -PPC_xxmrghd, // VSX Merge High Doubleword -PPC_xxmrgld, // VSX Merge Low Doubleword -PPC_xxswapd, // VSX Swap Doubleword - -// Xbox 360 specific -PPC_dcbz128, // Data Cache Block Clear to Zero (128 bytes) -PPC_mtmsree, // Move to Machine State Register EE - -// new Xbox 360 instructions (VMX128) -PPC_vcfpsxws, // Vector Convert From Single-Precision to Signed Fixed-point Word Saturate -PPC_vcfpuxws, // Vector Convert From Single-Precision to Unsigned Fixed-point Word Saturate -PPC_vcsxwfp, // Vector Convert from Signed Fixed-point Word to Single-Precision -PPC_vcuxwfp, // Vector Convert from Unsigned Fixed-point Word to Single-Precision -PPC_vmaddcfp, // Vector Convert from Unsigned Fixed-point Word to Single-Precision -PPC_vmsum3fp, // Vector Multiply-Sum 3-way Single-Precision -PPC_vmsum4fp, // Vector Multiply-Sum 4-way Single-Precision -PPC_vmulfp, // Vector Multiply Single-Precision -PPC_vpermwi, // Vector Permute Word Immediate -PPC_vpkd3d, // Vector Pack D3Dtype, Rotate Left Immediate and Mask Insert -PPC_vrlimi, // Vector Rotate Left Immediate and Mask Insert -PPC_vupkd3d, // Vector Unpack D3Dtype - -// Paired Singles (750CL/Gekko/Broadway) -PPC_ps_cmpu0, // Paired Single Compare Unordered High -PPC_psq_lx, // Paired Single Quantized Load Indexed -PPC_psq_stx, // Paired Single Quantized Store Indexed -PPC_ps_sum0, // Paired Single Vector Sum High -PPC_ps_sum1, // Paired Single Vector Sum Low -PPC_ps_muls0, // Paired Single Multiply Scalar High -PPC_ps_muls1, // Paired Single Multiply Scalar Low -PPC_ps_madds0, // Paired Single Multiply-Add Scalar High -PPC_ps_madds1, // Paired Single Multiply-Add Scalar Low -PPC_ps_div, // Paired Single Divide -PPC_ps_sub, // Paired Single Subtract -PPC_ps_add, // Paired Single Add -PPC_ps_sel, // Paired Single Select -PPC_ps_res, // Paired Single Reciprocal Estimate -PPC_ps_mul, // Paired Single Multiply -PPC_ps_rsqrte, // Paired Single Reciprocal Square Root Estimate -PPC_ps_msub, // Paired Single Multiply-Subtract -PPC_ps_madd, // Paired Single Multiply-Add -PPC_ps_nmsub, // Paired Single Negative Multiply-Subtract -PPC_ps_nmadd, // Paired Single Negative Multiply-Add -PPC_ps_cmpo0, // Paired Single Compare Ordered High -PPC_psq_lux, // Paired Single Quantized Load with update Indexed -PPC_psq_stux, // Paired Single Quantized Store with update Indexed -PPC_ps_neg, // Paired Single Negate -PPC_ps_cmpu1, // Paired Single Compare Unordered Low -PPC_ps_mr, // Paired Single Move Register -PPC_ps_cmpo1, // Paired Single Compare Ordered Low -PPC_ps_nabs, // Paired Single Negative Absolute Value -PPC_ps_abs, // Paired Single Absolute Value -PPC_ps_merge00, // Paired Single Merge High -PPC_ps_merge01, // Paired Single Merge Direct -PPC_ps_merge10, // Paired Single Merge Swapped -PPC_ps_merge11, // Paired Single Merge Low -PPC_dcbz_l, // Data Cache Block Set to Zero Locked -PPC_psq_l, // Paired Single Quantized Load -PPC_psq_lu, // Paired Single Quantized Load update -PPC_psq_st, // Paired Single Quantized Store -PPC_psq_stu, // Paired Single Quantized Store update - -// additional SPE/EFPU2 instructions -PPC_evfsmadd, // Vector Floating-Point Single-Precision Multiply-Add -PPC_evfsmsub, // Vector Floating-Point Single-Precision Multiply-Subtract -PPC_evfssqrt, // Vector Floating-Point Single-Precision Square Root -PPC_evfsnmadd, // Vector Floating-Point Single-Precision Negative Multiply-Add -PPC_evfsnmsub, // Vector Floating-Point Single-Precision Negative Multiply-Subtract -PPC_evfsmax, // Vector Floating-Point Single-Precision Maximum -PPC_evfsmin, // Vector Floating-Point Single-Precision Minimum -PPC_evfsaddsub, // Vector Floating-Point Single-Precision Add / Subtract -PPC_evfssubadd, // Vector Floating-Point Single-Precision Subtract / Add -PPC_evfssum, // Vector Floating-Point Single-Precision Sums -PPC_evfsdiff, // Vector Floating-Point Single-Precision Differences -PPC_evfssumdiff,// Vector Floating-Point Single-Precision Sum / Difference -PPC_evfsdiffsum,// Vector Floating-Point Single-Precision Difference / Sum -PPC_evfsaddx, // Vector Floating-Point Single-Precision Add Exchanged -PPC_evfssubx, // Vector Floating-Point Single-Precision Subtract Exchanged -PPC_evfsaddsubx,// Vector Floating-Point Single-Precision Add / Subtract Exchanged -PPC_evfssubaddx,// Vector Floating-Point Single-Precision Subtract / Add Exchanged -PPC_evfsmulx, // Vector Floating-Point Single-Precision Multiply Exchanged -PPC_evfsmule, // Vector Floating-Point Single-Precision Multiply By Even Element -PPC_evfsmulo, // Vector Floating-Point Single-Precision Multiply By Odd Element -PPC_evfscfh, // Vector Convert Floating-Point Single-Precision from Half-Precision -PPC_evfscth, // Vector Convert Floating-Point Single-Precision to Half-Precision -PPC_efsmax, // Floating-Point Single-Precision Maximum -PPC_efsmin, // Floating-Point Single-Precision Minimum -PPC_efsmadd, // Floating-Point Single-Precision Multiply-Add -PPC_efsmsub, // Floating-Point Single-Precision Multiply-Subtract -PPC_efssqrt, // Floating-Point Single-Precision Square Root -PPC_efsnmadd, // Floating-Point Single-Precision Negative Multiply-Add -PPC_efsnmsub, // Floating-Point Single-Precision Negative Multiply-Subtract -PPC_efscfh, // Convert Floating-Point Single-Precision from Half-Precision -PPC_efscth, // Convert Floating-Point Single-Precision to Half-Precision - -// Volatile Context Save/Restore APU -PPC_lmvgprw, // Load Multiple Volatile GPR Word -PPC_stmvgprw, // Store Multiple Volatile GPR Word -PPC_lmvsprw, // Load Multiple Volatile SPR Word -PPC_stmvsprw, // Store Multiple Volatile SPR Word -PPC_lmvsrrw, // Load Multiple Volatile SRR Word -PPC_stmvsrrw, // Store Multiple Volatile SRR Word -PPC_lmvcsrrw, // Load Multiple Volatile CSRR Word -PPC_stmvcsrrw, // Store Multiple Volatile CSRR Word -PPC_lmvdsrrw, // Load Multiple Volatile DSRR Word -PPC_stmvdsrrw, // Store Multiple Volatile DSRR Word -PPC_lmvmcsrrw, // Load Multiple Volatile MCSRR Word -PPC_stmvmcsrrw, // Store Multiple Volatile MCSRR Word - -// SPE2 (Signal Processing Engine 2) instructions -PPC_evdotpwcssi, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer (to Accumulator) -PPC_evdotpwcsmi, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer (to Accumulator) -PPC_evdotpwcssfr, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotpwcssf, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotpwgasmf, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwxgasmf, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwgasmfr, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwxgasmfr, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwgssmf, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwxgssmf, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwgssmfr, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwxgssmfr, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwcssiaaw3, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer and Accumulate into Words 3 operand -PPC_evdotpwcsmiaaw3, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer and Accumulate into Words 3 operand -PPC_evdotpwcssfraaw3, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words 3 operand -PPC_evdotpwcssfaaw3, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional and Accumulate into Words 3 operand -PPC_evdotpwgasmfaa3, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotpwxgasmfaa3, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotpwgasmfraa3, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate 3 operand -PPC_evdotpwxgasmfraa3, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate 3 operand -PPC_evdotpwgssmfaa3, // Vector Multiply Word Complex, Real, Guarded, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotpwxgssmfaa3, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotpwgssmfraa3, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate 3 operand -PPC_evdotpwxgssmfraa3, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate 3 operand -PPC_evdotpwcssia, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer (to Accumulator) -PPC_evdotpwcsmia, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer (to Accumulator) -PPC_evdotpwcssfra, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotpwcssfa, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotpwgasmfa, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwxgasmfa, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwgasmfra, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwxgasmfra, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwgssmfa, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwxgssmfa, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpwgssmfra, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwxgssmfra, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evdotpwcssiaaw, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer and Accumulate into Words -PPC_evdotpwcsmiaaw, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer and Accumulate into Words -PPC_evdotpwcssfraaw, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words -PPC_evdotpwcssfaaw, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional and Accumulate into Words -PPC_evdotpwgasmfaa, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional and Accumulate -PPC_evdotpwxgasmfaa, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate -PPC_evdotpwgasmfraa, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate -PPC_evdotpwxgasmfraa, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate -PPC_evdotpwgssmfaa, // Vector Multiply Word Complex, Real, Guarded, Signed, Modulo, Fractional and Accumulate -PPC_evdotpwxgssmfaa, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate -PPC_evdotpwgssmfraa, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate -PPC_evdotpwxgssmfraa, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate -PPC_evdotphihcssi, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) -PPC_evdotplohcssi, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) -PPC_evdotphihcssf, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotplohcssf, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotphihcsmi, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) -PPC_evdotplohcsmi, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) -PPC_evdotphihcssfr, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotplohcssfr, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotphihcssiaaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words, 3 operand -PPC_evdotplohcssiaaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words, 3 operand -PPC_evdotphihcssfaaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words, 3 operand -PPC_evdotplohcssfaaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words, 3 operand -PPC_evdotphihcsmiaaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotplohcsmiaaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotphihcssfraaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand -PPC_evdotplohcssfraaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand -PPC_evdotphihcssia, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) -PPC_evdotplohcssia, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) -PPC_evdotphihcssfa, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotplohcssfa, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotphihcsmia, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) -PPC_evdotplohcsmia, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) -PPC_evdotphihcssfra, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotplohcssfra, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotphihcssiaaw, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words -PPC_evdotplohcssiaaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words -PPC_evdotphihcssfaaw, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words -PPC_evdotplohcssfaaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words -PPC_evdotphihcsmiaaw, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words -PPC_evdotplohcsmiaaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words -PPC_evdotphihcssfraaw, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words -PPC_evdotplohcssfraaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words -PPC_evdotphausi, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer (to Accumulator) -PPC_evdotphassi, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer (to Accumulator) -PPC_evdotphasusi, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer (to Accumulator) -PPC_evdotphassf, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotphsssf, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotphaumi, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotphasmi, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotphasumi, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotphassfr, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotphssmi, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer (to Accumulator) -PPC_evdotphsssfr, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotphausiaaw3, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer and Accumulate into Words, 3 operand -PPC_evdotphassiaaw3, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer and Accumulate into Words, 3 operand -PPC_evdotphasusiaaw3, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer and Accumulate into Words, 3 operand -PPC_evdotphassfaaw3, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional and Accumulate into Words, 3 operand -PPC_evdotphsssiaaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Integer and Accumulate into Words, 3 operand -PPC_evdotphsssfaaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional and Accumulate into Words, 3 operand -PPC_evdotphaumiaaw3, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotphasmiaaw3, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotphasumiaaw3, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotphassfraaw3, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand -PPC_evdotphssmiaaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotphsssfraaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand -PPC_evdotphausia, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer (to Accumulator) -PPC_evdotphassia, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer (to Accumulator) -PPC_evdotphasusia, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer (to Accumulator) -PPC_evdotphassfa, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotphsssfa, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional (to Accumulator) -PPC_evdotphaumia, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotphasmia, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotphasumia, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotphassfra, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotphssmia, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer (to Accumulator) -PPC_evdotphsssfra, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round (to Accumulator) -PPC_evdotphausiaaw, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer and Accumulate into Words -PPC_evdotphassiaaw, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer and Accumulate into Words -PPC_evdotphasusiaaw, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer and Accumulate into Words -PPC_evdotphassfaaw, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional and Accumulate into Words -PPC_evdotphsssiaaw, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Integer and Accumulate into Words -PPC_evdotphsssfaaw, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional and Accumulate into Words -PPC_evdotphaumiaaw, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer and Accumulate into Words -PPC_evdotphasmiaaw, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer and Accumulate into Words -PPC_evdotphasumiaaw, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words -PPC_evdotphassfraaw, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round and Accumulate into Words -PPC_evdotphssmiaaw, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer and Accumulate into Words -PPC_evdotphsssfraaw, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round and Accumulate into Words -PPC_evdotp4hgaumi, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotp4hgasmi, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hgasumi, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotp4hgasmf, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotp4hgssmi, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hgssmf, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotp4hxgasmi, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hxgasmf, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpbaumi, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotpbasmi, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotpbasumi, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotp4hxgssmi, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hxgssmf, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotp4hgaumiaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer and Accumulate, 3 operand -PPC_evdotp4hgasmiaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer and Accumulate, 3 operand -PPC_evdotp4hgasumiaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer and Accumulate, 3 operand -PPC_evdotp4hgasmfaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional and Accumulate, 3 operand -PPC_evdotp4hgssmiaa3, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer and Accumulate 3 operand -PPC_evdotp4hgssmfaa3, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotp4hxgasmiaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer and Accumulate 3 operand -PPC_evdotp4hxgasmfaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotpbaumiaaw3, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotpbasmiaaw3, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotpbasumiaaw3, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words, 3 operand -PPC_evdotp4hxgssmiaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer and Accumulate 3 operand -PPC_evdotp4hxgssmfaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate 3 operand -PPC_evdotp4hgaumia, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotp4hgasmia, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hgasumia, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotp4hgasmfa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotp4hgssmia, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hgssmfa, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotp4hxgasmia, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hxgasmfa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotpbaumia, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotpbasmia, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer (to Accumulator) -PPC_evdotpbasumia, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evdotp4hxgssmia, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) -PPC_evdotp4hxgssmfa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) -PPC_evdotp4hgaumiaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer and Accumulate -PPC_evdotp4hgasmiaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer and Accumulate -PPC_evdotp4hgasumiaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer and Accumulate -PPC_evdotp4hgasmfaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional and Accumulate -PPC_evdotp4hgssmiaa, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer and Accumulate -PPC_evdotp4hgssmfaa, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate -PPC_evdotp4hxgasmiaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer and Accumulate -PPC_evdotp4hxgasmfaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate -PPC_evdotpbaumiaaw, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer and Accumulate into Words -PPC_evdotpbasmiaaw, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer and Accumulate into Words -PPC_evdotpbasumiaaw, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words -PPC_evdotp4hxgssmiaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer and Accumulate -PPC_evdotp4hxgssmfaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate -PPC_evdotpwausi, // Vector Dot Product of Words, Add, Unsigned, Saturate, integer (to Accumulator) -PPC_evdotpwassi, // Vector Dot Product of Words, Add, Signed, Saturate, integer (to Accumulator) -PPC_evdotpwasusi, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, integer (to Accumulator) -PPC_evdotpwaumi, // Vector Dot Product of Words, Add, Unsigned, Modulo, integer (to Accumulator) -PPC_evdotpwasmi, // Vector Dot Product of Words, Add, Signed, Modulo, integer (to Accumulator) -PPC_evdotpwasumi, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, integer (to Accumulator) -PPC_evdotpwssmi, // Vector Dot Product of Words, Subtract, Signed, Modulo, integer (to Accumulator) -PPC_evdotpwausiaa3, // Vector Dot Product of Words, Add, Unsigned, Saturate, Integer and Accumulate, 3 operand -PPC_evdotpwassiaa3, // Vector Dot Product of Words, Add, Signed, Saturate, Integer and Accumulate, 3 operand -PPC_evdotpwasusiaa3, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, Integer and Accumulate, 3 operand -PPC_evdotpwsssiaa3, // Vector Dot Product of Words, Subtract, Signed, Saturate, Integer and Accumulate, 3 operand -PPC_evdotpwaumiaa3, // Vector Dot Product of Words, Add, Unsigned, Modulo, Integer and Accumulate, 3 operand -PPC_evdotpwasmiaa3, // Vector Dot Product of Words, Add, Signed, Modulo, Integer and Accumulate, 3 operand -PPC_evdotpwasumiaa3, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, Integer and Accumulate, 3 operand -PPC_evdotpwssmiaa3, // Vector Dot Product of Words, Subtract, Signed, Modulo, Integer and Accumulate, 3 operand -PPC_evdotpwausia, // Vector Dot Product of Words, Add, Unsigned, Saturate, integer (to Accumulator) -PPC_evdotpwassia, // Vector Dot Product of Words, Add, Signed, Saturate, integer (to Accumulator) -PPC_evdotpwasusia, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, integer (to Accumulator) -PPC_evdotpwaumia, // Vector Dot Product of Words, Add, Unsigned, Modulo, integer (to Accumulator) -PPC_evdotpwasmia, // Vector Dot Product of Words, Add, Signed, Modulo, integer (to Accumulator) -PPC_evdotpwasumia, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, integer (to Accumulator) -PPC_evdotpwssmia, // Vector Dot Product of Words, Subtract, Signed, Modulo, integer (to Accumulator) -PPC_evdotpwausiaa, // Vector Dot Product of Words, Add, Unsigned, Saturate, Integer and Accumulate -PPC_evdotpwassiaa, // Vector Dot Product of Words, Add, Signed, Saturate, Integer and Accumulate -PPC_evdotpwasusiaa, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, Integer and Accumulate -PPC_evdotpwsssiaa, // Vector Dot Product of Words, Subtract, Signed, Saturate, Integer and Accumulate -PPC_evdotpwaumiaa, // Vector Dot Product of Words, Add, Unsigned, Modulo, Integer and Accumulate -PPC_evdotpwasmiaa, // Vector Dot Product of Words, Add, Signed, Modulo, Integer and Accumulate -PPC_evdotpwasumiaa, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, Integer and Accumulate -PPC_evdotpwssmiaa, // Vector Dot Product of Words, Subtract, Signed, Modulo, Integer and Accumulate -PPC_evaddih, // Vector Add Immediate Halfword -PPC_evaddib, // Vector Add Immediate Byte -PPC_evsubifh, // Vector Subtract Immediate from Halfword -PPC_evsubifb, // Vector Subtract Immediate from Byte -PPC_evabsb, // Vector Absolute Value Byte -PPC_evabsh, // Vector Absolute Value Halfword -PPC_evabsd, // Vector Absolute Value Doubleword -PPC_evabss, // Vector Absolute Value (Word) and Saturate -PPC_evabsbs, // Vector Absolute Value Byte and Saturate -PPC_evabshs, // Vector Absolute Value Halfword and Saturate -PPC_evabsds, // Vector Absolute Value Doubleword and Saturate -PPC_evnegwo, // Vector Negate Word Odd -PPC_evnegb, // Vector Negate Byte -PPC_evnegbo, // Vector Negate Byte Odd -PPC_evnegh, // Vector Negate Halfword -PPC_evnegho, // Vector Negate Halfwords Odd -PPC_evnegd, // Vector Negate Doubleword -PPC_evnegs, // Vector Negate (Word) and Saturate -PPC_evnegwos, // Vector Negate Word Odd and Saturate -PPC_evnegbs, // Vector Negate Byte and Saturate -PPC_evnegbos, // Vector Negate Byte Odd and Saturate -PPC_evneghs, // Vector Negate Halfword and Saturate -PPC_evneghos, // Vector Negate Halfwords Odd and Saturate -PPC_evnegds, // Vector Negate Doubleword and Saturate -PPC_evextzb, // Vector Extend Zero Byte -PPC_evextsbh, // Vector Extend Sign of Bytes (Odd) to Halfwords -PPC_evextsw, // Vector Extend Sign Word -PPC_evrndhb, // Vector Round Halfword to Byte -PPC_evrnddw, // Vector Round Doubleword to Word -PPC_evrndwhus, // Vector Round Word to Halfword Unsigned and Saturate -PPC_evrndwhss, // Vector Round Word to Halfword Signed and Saturate -PPC_evrndhbus, // Vector Round Halfword to Byte Unsigned and Saturate -PPC_evrndhbss, // Vector Round Halfword to Byte Signed and Saturate -PPC_evrnddwus, // Vector Round Doubleword to Word Unsigned and Saturate -PPC_evrnddwss, // Vector Round Doubleword to Word Signed and Saturate -PPC_evrndwnh, // Vector Round Word to Nearest Even Halfword -PPC_evrndhnb, // Vector Round Halfword to Nearest Even Byte -PPC_evrnddnw, // Vector Round Doubleword to Nearest Even Word -PPC_evrndwnhus, // Vector Round Word to Nearest Even Halfword Unsigned and Saturate -PPC_evrndwnhss, // Vector Round Word to Nearest Even Halfword Signed and Saturate -PPC_evrndhnbus, // Vector Round Halfword to Nearest Byte Unsigned and Saturate -PPC_evrndhnbss, // Vector Round Halfword to Nearest Even Byte Signed and Saturate -PPC_evrnddnwus, // Vector Round Doubleword to Nearest Even Word Unsigned and Saturate -PPC_evrnddnwss, // Vector Round Doubleword to Nearest Even Word Signed and Saturate -PPC_evcntlzh, // Vector Count Leading Zeros Halfword -PPC_evcntlsh, // Vector Count Leading Signed Bits Halfword -PPC_evpopcntb, // Vector Population Count Byte -PPC_circinc, // Circular Increment -PPC_evunpkhibui, // Vector Unpack High Bytes as Unsigned Integers -PPC_evunpkhibsi, // Vector Unpack High Bytes as Signed Integers -PPC_evunpkhihui, // Vector Extract High Halfwords as Unsigned Integers -PPC_evunpkhihsi, // Vector Extract High Halfwords as Signed Integers -PPC_evunpklobui, // Vector Unpack Low Bytes Unsigned Integers -PPC_evunpklobsi, // Vector Unpack Low Bytes as Signed Integers -PPC_evunpklohui, // Vector Unpack Low Halfwords as Unsigned Integers -PPC_evunpklohsi, // Vector Unpack Low Halfwords as Signed Integers -PPC_evunpklohf, // Vector Unpack Low Halfwords as Fractional -PPC_evunpkhihf, // Vector Unpack High Halfwords as Fractional -PPC_evunpklowgsf, // Vector Unpack Low Word to Guarded Signed Fraction -PPC_evunpkhiwgsf, // Vector Unpack High Word to Guarded Signed Fraction -PPC_evsatsduw, // Vector Saturate Signed Doubleword to Unsigned Word Range -PPC_evsatsdsw, // Vector Saturate Signed Doubleword to Signed Word Range -PPC_evsatshub, // Vector Saturate Signed Halfwords to Unsigned Byte Range -PPC_evsatshsb, // Vector Saturate Signed Halfwords to Signed Byte Range -PPC_evsatuwuh, // Vector Saturate Unsigned Words to Unsigned Halfword Range -PPC_evsatswsh, // Vector Saturate Signed Words to Signed Halfword Range -PPC_evsatswuh, // Vector Pack Signed Words to Unsigned Halfword Range -PPC_evsatuhub, // Vector Saturate Unsigned Halfwords to Unsigned Byte Range -PPC_evsatuduw, // Vector Saturate Unsigned Doubleword to Unsigned Word Range -PPC_evsatuwsw, // Vector Saturate Unsigned Words to Signed Word Range -PPC_evsatshuh, // Vector Saturate Signed Halfwords to Unsigned Halfword Range -PPC_evsatuhsh, // Vector Saturate Unsigned Halfwords to Signed Halfword Range -PPC_evsatswuw, // Vector Pack Signed Words to Unsigned Word Range -PPC_evsatswgsdf, // Vector Saturate Signed Word Guarded to Signed Doubleword Fractional -PPC_evsatsbub, // Vector Saturate Signed Bytes to Unsigned Byte Range -PPC_evsatubsb, // Vector Saturate Unsigned Bytes to Signed Byte Range -PPC_evmaxhpuw, // Vector Maximum of Halfword Pairs Unsigned to Word -PPC_evmaxhpsw, // Vector Maximum of Halfword Pairs Signed to Word -PPC_evmaxbpuh, // Vector Maximum of Byte Pairs Unsigned to Halfword -PPC_evmaxbpsh, // Vector Maximum of Byte Pairs Signed to Halfword -PPC_evmaxwpud, // Vector Maximum of Word Pair Unsigned to Doubleword -PPC_evmaxwpsd, // Vector Maximum of Word Pair Signed to Doubleword -PPC_evminhpuw, // Vector Minimum of Halfword Pairs Unsigned to Word -PPC_evminhpsw, // Vector Minimum of Halfword Pairs Signed to Word -PPC_evminbpuh, // Vector Minimum of Byte Pairs Unsigned to Halfword -PPC_evminbpsh, // Vector Minimum of Byte Pairs Signed to Halfword -PPC_evminwpud, // Vector Minimum of Word Pair Unsigned to Doubleword -PPC_evminwpsd, // Vector Minimum of Word Pair Signed to Doubleword -PPC_evmaxmagws, // Vector Maximum Magnitude Word Signed -PPC_evsl, // Vector Shift Left -PPC_evsli, // Vector Shift Left Immediate -PPC_evsplatie, // Vector Splat Immediate Even (to Accumulator) -PPC_evsplatib, // Vector Splat Immediate Byte (to Accumulator) -PPC_evsplatibe, // Vector Splat Immediate Byte Even (to Accumulator) -PPC_evsplatih, // Vector Splat Immediate Halfword (to Accumulator) -PPC_evsplatihe, // Vector Splat Immediate Halfword Even (to Accumulator) -PPC_evsplatid, // Vector Splat Immediate Doubleword (to Accumulator) -PPC_evsplatia, // Vector Splat Immediate (to Accumulator) -PPC_evsplatiea, // Vector Splat Immediate Even (to Accumulator) -PPC_evsplatiba, // Vector Splat Immediate Byte (to Accumulator) -PPC_evsplatibea, // Vector Splat Immediate Byte Even (to Accumulator) -PPC_evsplatiha, // Vector Splat Immediate Halfword (to Accumulator) -PPC_evsplatihea, // Vector Splat Immediate Halfword Even (to Accumulator) -PPC_evsplatida, // Vector Splat Immediate Doubleword (to Accumulator) -PPC_evsplatfio, // Vector Splat Fractional Immediate Odd (to Accumulator) -PPC_evsplatfib, // Vector Splat Fractional Immediate Byte (to Accumulator) -PPC_evsplatfibo, // Vector Splat Fractional Immediate Byte Odd (to Accumulator) -PPC_evsplatfih, // Vector Splat Fractional Immediate Halfword (to Accumulator) -PPC_evsplatfiho, // Vector Splat Fractional Immediate Halfword Odd (to Accumulator) -PPC_evsplatfid, // Vector Splat Fractional Immediate Doubleword (to Accumulator) -PPC_evsplatfia, // Vector Splat Fractional Immediate (to Accumulator) -PPC_evsplatfioa, // Vector Splat Fractional Immediate Odd (to Accumulator) -PPC_evsplatfiba, // Vector Splat Fractional Immediate Byte (to Accumulator) -PPC_evsplatfiboa, // Vector Splat Fractional Immediate Byte Odd (to Accumulator) -PPC_evsplatfiha, // Vector Splat Fractional Immediate Halfword (to Accumulator) -PPC_evsplatfihoa, // Vector Splat Fractional Immediate Halfword Odd (to Accumulator) -PPC_evsplatfida, // Vector Splat Fractional Immediate Doubleword (to Accumulator) -PPC_evcmpgtdu, // Vector Compare Greater Than Doubleword Unsigned -PPC_evcmpgtds, // Vector Compare Greater Than Doubleword Signed -PPC_evcmpltdu, // Vector Compare Less Than Doubleword Unsigned -PPC_evcmpltds, // Vector Compare Less Than Doubleword Signed -PPC_evcmpeqd, // Vector Compare Equal Doubleword -PPC_evswapbhilo, // Vector Swap Bytes High/Low -PPC_evswapblohi, // Vector Swap Bytes Low/High -PPC_evswaphhilo, // Vector Swap Halfwords High/Low -PPC_evswaphlohi, // Vector Swap Halfwords Low/High -PPC_evswaphe, // Vector Swap Halfwords Even -PPC_evswaphhi, // Vector Swap Halfwords High -PPC_evswaphlo, // Vector Swap Halfwords Low -PPC_evswapho, // Vector Swap Halfwords Odd -PPC_evinsb, // Vector Insert Byte -PPC_evxtrb, // Vector Extract Byte -PPC_evsplath, // Vector Splat Halfword -PPC_evsplatb, // Vector Splat Byte -PPC_evinsh, // Vector Insert Halfword -PPC_evclrbe, // Vector Clear Bytes Even -PPC_evclrbo, // Vector Clear Bytes Odd -PPC_evxtrh, // Vector Extract Halfword -PPC_evclrh, // Vector Clear Halfwords -PPC_evselbitm0, // Vector Select Bit if Mask is 0 -PPC_evselbitm1, // Vector Select Bit if Mask is 1 -PPC_evselbit, // Vector Select Bit -PPC_evperm, // Vector Permute -PPC_evperm2, // Vector Permute (form 2) -PPC_evperm3, // Vector Permute (form 3) -PPC_evxtrd, // Vector Extract Doubleword -PPC_evsrbu, // Vector Shift Right Byte Unsigned -PPC_evsrbs, // Vector Shift Right Byte Signed -PPC_evsrbiu, // Vector Shift Right Byte Immediate Unsigned -PPC_evsrbis, // Vector Shift Right Byte Immediate Signed -PPC_evslb, // Vector Shift Left Byte -PPC_evrlb, // Vector Rotate Left Byte -PPC_evslbi, // Vector Shift Left Byte Immediate -PPC_evrlbi, // Vector Rotate Left Byte Immediate -PPC_evsrhu, // Vector Shift Right Halfword Unsigned -PPC_evsrhs, // Vector Shift Right Halfword Signed -PPC_evsrhiu, // Vector Shift Right Halfword Immediate Unsigned -PPC_evsrhis, // Vector Shift Right Halfword Immediate Signed -PPC_evslh, // Vector Shift Left Halfword -PPC_evrlh, // Vector Rotate Left Halfword -PPC_evslhi, // Vector Shift Left Halfword Immediate -PPC_evrlhi, // Vector Rotate Left Halfword Immediate -PPC_evsru, // Vector Shift Right Unsigned -PPC_evsrs, // Vector Shift Right Signed -PPC_evsriu, // Vector Shift Right Immediate Unsigned -PPC_evsris, // Vector Shift Right Immediate Signed -PPC_evlvsl, // Load Vector for Shift Left -PPC_evlvsr, // Load Vector for Shift Right -PPC_evsroiu, // Vector Shift Right by Octet Immediate Unsigned -PPC_evsloi, // Vector Shift Left by Octet Immediate -PPC_evsrois, // Vector Shift Right by Octet Immediate Signed -PPC_evldbx, // Vector Load Double into Eight Bytes [with Modify] Indexed -PPC_evldb, // Vector Load Double into Eight Bytes [with Update] -PPC_evlhhsplathx, // Vector Load Halfword into Halfword and Splat Halfwords [with Modify] Indexed -PPC_evlhhsplath, // Vector Load Halfword into Halfword and Splat Halfwords [with Update] -PPC_evlwbsplatwx, // Vector Load Word as Bytes and Splat Words [with Modify] Indexed -PPC_evlwbsplatw, // Vector Load Word as Bytes and Splat Words [with Update] -PPC_evlwhsplatwx, // Vector Load Word as Halfwords and Splat Words [with Modify] Indexed -PPC_evlwhsplatw, // Vector Load Word as Halfwords and Splat Words [with Update] -PPC_evlbbsplatbx, // Vector Load Byte into Byte and Splat Bytes [with Modify] Indexed -PPC_evlbbsplatb, // Vector Load Byte into Byte and Splat Bytes [with Update] -PPC_evstdbx, // Vector Store Double of Eight Bytes [with Modify] Indexed -PPC_evstdb, // Vector Store Double of Eight Bytes [with Update] -PPC_evlwbex, // Vector Load Word into Four Bytes Even [with Modify] Indexed -PPC_evlwbe, // Vector Load Word into Four Bytes Even [with Update] -PPC_evlwboux, // Vector Load Word into Four Bytes Odd Unsigned [with Modify] Indexed -PPC_evlwbou, // Vector Load Word into Four Bytes Odd Unsigned [with Update] -PPC_evlwbosx, // Vector Load Word into Two Halfwords Odd Signed [with Modify] Indexed -PPC_evlwbos, // Vector Load Word into Four Bytes Odd Signed [with Update] -PPC_evstwbex, // Vector Store Word of Four Bytes from Even [with Modify] Indexed -PPC_evstwbe, // Vector Store Word of Four Bytes from Even [with Update] -PPC_evstwbox, // Vector Store Word of Four Bytes from Odd [with Modify] Indexed -PPC_evstwbo, // Vector Store Word of Four Bytes from Odd [with Update] -PPC_evstwbx, // Vector Store Word of Four Bytes [with Modify] Indexed -PPC_evstwb, // Vector Store Word of Four Bytes [with Update] -PPC_evsthbx, // Vector Store Halfword of Two Bytes [with Modify] Indexed -PPC_evsthb, // Vector Store Halfword of Two Bytes [with Update] -PPC_evlddmx, // Vector Load Double Word into Double Word [with Modify] Indexed -PPC_evlddu, // Vector Load Double Word into Double Word [with Update] -PPC_evldwmx, // Vector Load Double into Two Words [with Modify] Indexed -PPC_evldwu, // Vector Load Double into Two Words [with Update] -PPC_evldhmx, // Vector Load Double into Four Halfwords [with Modify] Indexed -PPC_evldhu, // Vector Load Double into Four Halfwords [with Update] -PPC_evldbmx, // Vector Load Double into Eight Bytes [with Modify] Indexed -PPC_evldbu, // Vector Load Double into Eight Bytes [with Update] -PPC_evlhhesplatmx, // Vector Load Halfword into Halfwords Even and Splat [with Modify] Indexed -PPC_evlhhesplatu, // Vector Load Halfword into Halfwords Even and Splat [with Update] -PPC_evlhhsplathmx, // Vector Load Halfword into Halfword and Splat Halfwords [with Modify] Indexed -PPC_evlhhsplathu, // Vector Load Halfword into Halfword and Splat Halfwords [with Update] -PPC_evlhhousplatmx, // Vector Load Halfword into Halfword Odd Unsigned and Splat [with Modify] Indexed -PPC_evlhhousplatu, // Vector Load Halfword into Halfword Odd Unsigned and Splat [with Update] -PPC_evlhhossplatmx, // Vector Load Halfword into Halfword Odd Signed and Splat [with Modify] Indexed -PPC_evlhhossplatu, // Vector Load Halfword into Halfword Odd Signed and Splat [with Update] -PPC_evlwhemx, // Vector Load Word into Two Halfwords Even [with Modify] Indexed -PPC_evlwheu, // Vector Load Word into Two Halfwords Even [with Update] -PPC_evlwbsplatwmx, // Vector Load Word as Bytes and Splat Words [with Modify] Indexed -PPC_evlwbsplatwu, // Vector Load Word as Bytes and Splat Words [with Update] -PPC_evlwhoumx, // Vector Load Word into Two Halfwords Odd Unsigned [with Modify] Indexed (zero-extended) -PPC_evlwhouu, // Vector Load Word into Two Halfwords Odd Unsigned (zero-extended) [with Update] -PPC_evlwhosmx, // Vector Load Word into Two Halfwords Odd Signed [with Modify] Indexed (with sign extension) -PPC_evlwhosu, // Vector Load Word into Two Halfwords Odd Signed (with sign extension) [with Update] -PPC_evlwwsplatmx, // Vector Load Word into Word and Splat [with Modify] Indexed -PPC_evlwwsplatu, // Vector Load Word into Word and Splat [with Update] -PPC_evlwhsplatwmx, // Vector Load Word as Halfwords and Splat Words [with Modify] Indexed -PPC_evlwhsplatwu, // Vector Load Word as Halfwords and Splat Words [with Update] -PPC_evlwhsplatmx, // Vector Load Word into Two Halfwords and Splat [with Modify] Indexed -PPC_evlwhsplatu, // Vector Load Word into Two Halfwords and Splat [with Update] -PPC_evlbbsplatbmx, // Vector Load Byte into Byte and Splat Bytes [with Modify] Indexed -PPC_evlbbsplatbu, // Vector Load Byte into Byte and Splat Bytes [with Update] -PPC_evstddmx, // Vector Store Double of Double [with Modify] Indexed -PPC_evstddu, // Vector Store Double of Double [with Update] -PPC_evstdwmx, // Vector Store Double of Two Words [with Modify] Indexed -PPC_evstdwu, // Vector Store Double of Two Words [with Update] -PPC_evstdhmx, // Vector Store Double of Four Halfwords [with Modify] Indexed -PPC_evstdhu, // Vector Store Double of Four Halfwords [with Update] -PPC_evstdbmx, // Vector Store Double of Eight Bytes [with Modify] Indexed -PPC_evstdbu, // Vector Store Double of Eight Bytes [with Update] -PPC_evlwbemx, // Vector Load Word into Four Bytes Even [with Modify] Indexed -PPC_evlwbeu, // Vector Load Word into Four Bytes Even [with Update] -PPC_evlwboumx, // Vector Load Word into Four Bytes Odd Unsigned [with Modify] Indexed -PPC_evlwbouu, // Vector Load Word into Four Bytes Odd Unsigned [with Update] -PPC_evlwbosmx, // Vector Load Word into Two Halfwords Odd Signed [with Modify] Indexed -PPC_evlwbosu, // Vector Load Word into Four Bytes Odd Signed [with Update] -PPC_evstwhemx, // Vector Store Word of Two Halfwords from Even [with Modify] Indexed -PPC_evstwheu, // Vector Store Word of Two Halfwords from Even [with Update] -PPC_evstwbemx, // Vector Store Word of Four Bytes from Even [with Modify] Indexed -PPC_evstwbeu, // Vector Store Word of Four Bytes from Even [with Update] -PPC_evstwhomx, // Vector Store Word of Two Halfwords from Odd [with Modify] Indexed -PPC_evstwhou, // Vector Store Word of Two Halfwords from Odd [with Update] -PPC_evstwbomx, // Vector Store Word of Four Bytes from Odd [with Modify] Indexed -PPC_evstwbou, // Vector Store Word of Four Bytes from Odd [with Update] -PPC_evstwwemx, // Vector Store Word of Word from Even [with Modify] Indexed -PPC_evstwweu, // Vector Store Word of Word from Even [with Update] -PPC_evstwbmx, // Vector Store Word of Four Bytes [with Modify] Indexed -PPC_evstwbu, // Vector Store Word of Four Bytes [with Update] -PPC_evstwwomx, // Vector Store Word of Word from Odd [with Modify] Indexed -PPC_evstwwou, // Vector Store Word of Word from Odd [with Update] -PPC_evsthbmx, // Vector Store Halfword of Two Bytes [with Modify] Indexed -PPC_evsthbu, // Vector Store Halfword of Two Bytes [with Update] -PPC_evmhusi, // Vector Multiply Halfword Unsigned, Saturate, Integer -PPC_evmhssi, // Vector Multiply Halfword Signed, Saturate, Integer -PPC_evmhsusi, // Vector Multiply Halfword Signed by Unsigned, Saturate, Integer -PPC_evmhssf, // Vector Multiply Halfword Signed, Saturate, Fractional -PPC_evmhumi, // Vector Multiply Halfword Unsigned, Modulo, Integer -PPC_evmhssfr, // Vector Multiply Halfword Signed, Saturate, Fractional and Round -PPC_evmhesumi, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmhosumi, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmbeumi, // Vector Multiply Bytes Even, Unsigned, Modulo, Integer (to Accumulator) -PPC_evmbesmi, // Vector Multiply Bytes Even, Signed, Modulo, Integer (to Accumulator) -PPC_evmbesumi, // Vector Multiply Bytes Even, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmboumi, // Vector Multiply Bytes Odd, Unsigned, Modulo, Integer (to Accumulator) -PPC_evmbosmi, // Vector Multiply Bytes Odd, Signed, Modulo, Integer (to Accumulator) -PPC_evmbosumi, // Vector Multiply Bytes Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmhesumia, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmhosumia, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmbeumia, // Vector Multiply Bytes Even, Unsigned, Modulo, Integer (to Accumulator) -PPC_evmbesmia, // Vector Multiply Bytes Even, Signed, Modulo, Integer (to Accumulator) -PPC_evmbesumia, // Vector Multiply Bytes Even, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmboumia, // Vector Multiply Bytes Odd, Unsigned, Modulo, Integer (to Accumulator) -PPC_evmbosmia, // Vector Multiply Bytes Odd, Signed, Modulo, Integer (to Accumulator) -PPC_evmbosumia, // Vector Multiply Bytes Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) -PPC_evmwusiw, // Vector Multiply Word Unsigned, Saturate, Integer Word -PPC_evmwssiw, // Vector Multiply Word Signed, Saturate, Integer Word -PPC_evmwhssfr, // Vector Multiply Word High Signed, Saturate, Fractional and Round (to Accumulator) -PPC_evmwehgsmfr, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evmwehgsmf, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional (to Accumulator) -PPC_evmwohgsmfr, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evmwohgsmf, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional (to Accumulator) -PPC_evmwhssfra, // Vector Multiply Word High Signed, Saturate, Fractional and Round (to Accumulator) -PPC_evmwehgsmfra, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evmwehgsmfa, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional (to Accumulator) -PPC_evmwohgsmfra, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional, Round (to Accumulator) -PPC_evmwohgsmfa, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional (to Accumulator) -PPC_evaddusiaa, // Vector Add Unsigned, Saturate, Integer to Accumulator -PPC_evaddssiaa, // Vector Add Signed, Saturate, Integer to Accumulator -PPC_evsubfusiaa, // Vector Subtract from (Accumulator) Unsigned, Saturate, Integer to Accumulator -PPC_evsubfssiaa, // Vector Subtract from Signed, Saturate, Integer to Accumulator -PPC_evaddsmiaa, // Vector Add to Accumulator -PPC_evsubfsmiaa, // Vector Subtract from Accumulator to Accumulator -PPC_evaddh, // Vector Add Halfwords -PPC_evaddhss, // Vector Add Halfwords Signed and Saturate -PPC_evsubfh, // Vector Subtract from Halfword -PPC_evsubfhss, // Vector Subtract from Halfwords Signed and Saturate -PPC_evaddhx, // Vector Add Halfwords Exchanged -PPC_evaddhxss, // Vector Add Halfwords Exchanged, Signed and Saturate -PPC_evsubfhx, // Vector Subtract from Halfwords Exchanged -PPC_evsubfhxss, // Vector Subtract from Halfwords Exchanged, Signed and Saturate -PPC_evaddd, // Vector Add Doubleword -PPC_evadddss, // Vector Add Doubleword Signed and Saturate -PPC_evsubfd, // Vector Subtract from Doubleword -PPC_evsubfdss, // Vector Subtract from Doubleword Signed and Saturate -PPC_evaddb, // Vector Add Bytes -PPC_evaddbss, // Vector Add Bytes Signed and Saturate -PPC_evsubfb, // Vector Subtract from Byte -PPC_evsubfbss, // Vector Subtract from Byte Signed and Saturate -PPC_evaddsubfh, // Vector Add / Subtract from Halfword -PPC_evaddsubfhss, // Vector Add / Subtract from Halfword Signed and Saturate -PPC_evsubfaddh, // Vector Subtract from / Add Halfwords -PPC_evsubfaddhss, // Vector Subtract from / Add Halfwords Signed and Saturate -PPC_evaddsubfhx, // Vector Add / Subtract from Halfword Exchanged -PPC_evaddsubfhxss, // Vector Add / Subtract from Halfword Exchanged, Signed and Saturate -PPC_evsubfaddhx, // Vector Subtract from / Add Halfwords Exchanged -PPC_evsubfaddhxss, // Vector Subtract from / Add Halfwords Exchanged, Signed and Saturate -PPC_evadddus, // Vector Add Doubleword Unsigned and Saturate -PPC_evaddbus, // Vector Add Bytes Unsigned and Saturate -PPC_evsubfdus, // Vector Subtract from Doubleword Unsigned and Saturate -PPC_evsubfbus, // Vector Subtract from Byte Unsigned and Saturate -PPC_evaddwus, // Vector Add Word Unsigned and Saturate -PPC_evaddwxus, // Vector Add Word Exchanged Unsigned and Saturate -PPC_evsubfwus, // Vector Subtract from Word Unsigned and Saturate -PPC_evsubfwxus, // Vector Subtract from Word Exchanged Unsigned and Saturate -PPC_evadd2subf2h, // Vector Add Upper 2 and Subtract from Lower 2 Halfwords -PPC_evadd2subf2hss, // Vector Add Upper 2 and Subtract from Lower 2 Halfwords Signed and Saturate -PPC_evsubf2add2h, // Vector Subtract from Upper 2 / Add Lower 2 Halfwords -PPC_evsubf2add2hss, // Vector Subtract from Upper 2 / Add Lower 2 Halfwords Signed and Saturate -PPC_evaddhus, // Vector Add Halfwords Unsigned and Saturate -PPC_evaddhxus, // Vector Add Halfwords Exchanged, Unsigned and Saturate -PPC_evsubfhus, // Vector Subtract from Halfwords Unsigned and Saturate -PPC_evsubfhxus, // Vector Subtract from Halfwords Exchanged, Unsigned and Saturate -PPC_evaddwss, // Vector Add Word Signed and Saturate -PPC_evsubfwss, // Vector Subtract from Word Signed and Saturate -PPC_evaddwx, // Vector Add Word Exchanged -PPC_evaddwxss, // Vector Add Word Exchanged Signed and Saturate -PPC_evsubfwx, // Vector Subtract from Word Exchanged -PPC_evsubfwxss, // Vector Subtract from Word Exchanged Signed and Saturate -PPC_evaddsubfw, // Vector Add / Subtract from Word -PPC_evaddsubfwss, // Vector Add / Subtract from Word Signed and Saturate -PPC_evsubfaddw, // Vector Subtract from / Add Word -PPC_evsubfaddwss, // Vector Subtract from / Add Word Signed and Saturate -PPC_evaddsubfwx, // Vector Add / Subtract from Word Exchanged -PPC_evaddsubfwxss, // Vector Add / Subtract from Word Exchanged Signed and Saturate -PPC_evsubfaddwx, // Vector Subtract from / Add Word Exchanged -PPC_evsubfaddwxss, // Vector Subtract from / Add Word Exchanged Signed and Saturate -PPC_evmar, // Store Accumulator -PPC_evsumwu, // Vector Sum of Words Unsigned (to Accumulator) -PPC_evsumws, // Vector Sum of Words Signed (to Accumulator) -PPC_evsum4bu, // Vector Sum of 4 Bytes UnsIgned (to Accumulator) -PPC_evsum4bs, // Vector Sum of 4 Bytes SIgned (to Accumulator) -PPC_evsum2hu, // Vector Sum of 2 Halfwords Unsigned (to Accumulator) -PPC_evsum2hs, // Vector Sum of 2 Halfwords Signed (to Accumulator) -PPC_evdiff2his, // Vector Difference of 2 Halfwords Interleaved Signed (to Accumulator) -PPC_evsum2his, // Vector Sum of 2 Halfwords Interleaved Signed (to Accumulator) -PPC_evsumwua, // Vector Sum of Words Unsigned (to Accumulator) -PPC_evsumwsa, // Vector Sum of Words Signed (to Accumulator) -PPC_evsum4bua, // Vector Sum of 4 Bytes UnsIgned (to Accumulator) -PPC_evsum4bsa, // Vector Sum of 4 Bytes SIgned (to Accumulator) -PPC_evsum2hua, // Vector Sum of 2 Halfwords Unsigned (to Accumulator) -PPC_evsum2hsa, // Vector Sum of 2 Halfwords Signed (to Accumulator) -PPC_evdiff2hisa, // Vector Difference of 2 Halfwords Interleaved Signed (to Accumulator) -PPC_evsum2hisa, // Vector Sum of 2 Halfwords Interleaved Signed (to Accumulator) -PPC_evsumwuaa, // Vector Sum of Words Unsigned and Accumulate -PPC_evsumwsaa, // Vector Sum of Words Signed and Accumulate -PPC_evsum4buaaw, // Vector Sum of 4 Bytes Unsigned and Accumulate into Words -PPC_evsum4bsaaw, // Vector Sum of 4 Bytes Signed and Accumulate into Words -PPC_evsum2huaaw, // Vector Sum of 2 Halfwords Unsigned and Accumulate into Words -PPC_evsum2hsaaw, // Vector Sum of 2 Halfwords Signed and Accumulate into Words -PPC_evdiff2hisaaw, // Vector Difference of 2 Halfwords Interleaved Signed and Accumulate into Words -PPC_evsum2hisaaw, // Vector Sum of 2 Halfwords Interleaved Signed and Accumulate into Words -PPC_evdivwsf, // Vector Divide Word Signed Fractional -PPC_evdivwuf, // Vector Divide Word Unsigned Fractional -PPC_evdivs, // Vector Divide Signed -PPC_evdivu, // Vector Divide Unsigned -PPC_evaddwegsi, // Vector Add Word Even Guarded Signed Integer -PPC_evaddwegsf, // Vector Add Word Even Guarded Signed Fraction -PPC_evsubfwegsi, // Vector Subtract from Word Even Guarded Signed Integer -PPC_evsubfwegsf, // Vector Subtract from Word Even Guarded Signed Fraction -PPC_evaddwogsi, // Vector Add Word Odd Guarded Signed Integer -PPC_evaddwogsf, // Vector Add Word Odd Guarded Signed Fraction -PPC_evsubfwogsi, // Vector Subtract from Word Odd Guarded Signed Integer -PPC_evsubfwogsf, // Vector Subtract from Word Odd Guarded Signed Fraction -PPC_evaddhhiuw, // Vector Add Halfwords High Unsigned to Words -PPC_evaddhhisw, // Vector Add Halfwords High Signed to Words -PPC_evsubfhhiuw, // Vector Subtract from Halfwords High Unsigned to Words -PPC_evsubfhhisw, // Vector Subtract from Halfwords High Signed to Words -PPC_evaddhlouw, // Vector Add Halfwords Low Unsigned to Words -PPC_evaddhlosw, // Vector Add Halfwords Low Signed to Words -PPC_evsubfhlouw, // Vector Subtract from Halfwords Low Unsigned to Words -PPC_evsubfhlosw, // Vector Subtract from Halfwords Low Signed to Words -PPC_evmhesusiaaw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Saturate, Integer and Accumulate into Words -PPC_evmhosusiaaw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Saturate, Integer and Accumulate into Words -PPC_evmhesumiaaw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer and Accumulate into Words -PPC_evmhosumiaaw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer and Accumulate into Words -PPC_evmbeusiaah, // Vector Multiply Byte Even, Unsigned, Saturate, Integer and Accumulate Halfwords -PPC_evmbessiaah, // Vector Multiply Byte Even, Signed, Saturate, Integer and Accumulate Halfwords -PPC_evmbesusiaah, // Vector Multiply Byte Even, Signed by Unsigned, Saturate, Integer and Accumulate Halfwords -PPC_evmbousiaah, // Vector Multiply Byte Odd, Unsigned, Saturate, Integer and Accumulate Halfwords -PPC_evmbossiaah, // Vector Multiply Byte Odd, Signed, Saturate, Integer and Accumulate Halfwords -PPC_evmbosusiaah, // Vector Multiply Byte Odd, Signed by Unsigned, Saturate, Integer and Accumulate Halfwords -PPC_evmbeumiaah, // Vector Multiply Byte Even, Unsigned, Modulo, Integer and Accumulate Halfwords -PPC_evmbesmiaah, // Vector Multiply Byte Even, Signed, Modulo, Integer and Accumulate Halfwords -PPC_evmbesumiaah, // Vector Multiply Byte Even, Signed by Unsigned, Modulo, Integer and Accumulate Halfwords -PPC_evmboumiaah, // Vector Multiply Byte Odd, Unsigned, Modulo, Integer and Accumulate Halfwords -PPC_evmbosmiaah, // Vector Multiply Byte Odd, Signed, Modulo, Integer and Accumulate Halfwords -PPC_evmbosumiaah, // Vector Multiply Byte Odd, Signed by Unsigned, Modulo, Integer and Accumulate Halfwords -PPC_evmwlusiaaw3, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate in Words 3 operand -PPC_evmwlssiaaw3, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate in Words -PPC_evmwhssfraaw3, // Vector Multiply Word High Signed, Saturate, Fractional, Round and Accumulate into Words 3 operand -PPC_evmwhssfaaw3, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate into Words 3 operand -PPC_evmwhssfraaw, // Vector Multiply Word High Signed, Saturate, Fractional, Round and Accumulate into Words -PPC_evmwhssfaaw, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate into Words -PPC_evmwlumiaaw3, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate in Words 3 operand -PPC_evmwlsmiaaw3, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate in Words 3 operand -PPC_evmwusiaa, // Vector Multiply Word Unsigned, Saturate, Integer and Accumulate -PPC_evmwssiaa, // Vector Multiply Word Signed, Saturate, Integer and Accumulate -PPC_evmwehgsmfraa, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional, Round and Accumulate -PPC_evmwehgsmfaa, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional and Accumulate -PPC_evmwohgsmfraa, // Vector Multiply Word Odd High Guarded Signed, Modulo, Fractional, Round and Accumulate -PPC_evmwohgsmfaa, // Vector Multiply Word Odd High Guarded Signed, Modulo, Fractional and Accumulate -PPC_evmhesusianw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Saturate, Integer and Accumulate Negative into Words -PPC_evmhosusianw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Saturate, Integer and Accumulate Negative into Words -PPC_evmhesumianw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer and Accumulate Negative into Words -PPC_evmhosumianw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer and Accumulate Negative into Words -PPC_evmbeusianh, // Vector Multiply Byte Even, Unsigned, Saturate, Integer and Accumulate Negative Halfwords -PPC_evmbessianh, // Vector Multiply Byte Even, Signed, Saturate, Integer and Accumulate Negative Halfwords -PPC_evmbesusianh, // Vector Multiply Byte Even, Signed by Unsigned, Saturate, Integer and Accumulate Negative Halfwords -PPC_evmbousianh, // Vector Multiply Byte Odd, Unsigned, Saturate, Integer and Accumulate Negative Halfwords -PPC_evmbossianh, // Vector Multiply Byte Odd, Signed, Saturate, Integer and Accumulate Negative Halfwords -PPC_evmbosusianh, // Vector Multiply Byte Odd, Signed by Unsigned, Saturate, Integer and Accumulate Negative Halfwords -PPC_evmbeumianh, // Vector Multiply Byte Even, Unsigned, Modulo, Integer and Accumulate Negative Halfwords -PPC_evmbesmianh, // Vector Multiply Byte Even, Signed, Modulo, Integer and Accumulate Negative Halfwords -PPC_evmbesumianh, // Vector Multiply Byte Even, Signed by Unsigned, Modulo, Integer and Accumulate Negative Halfwords -PPC_evmboumianh, // Vector Multiply Byte Odd, Unsigned, Modulo, Integer and Accumulate Negative Halfwords -PPC_evmbosmianh, // Vector Multiply Byte Odd, Signed, Modulo, Integer and Accumulate Negative Halfwords -PPC_evmbosumianh, // Vector Multiply Byte Odd, Signed by Unsigned, Modulo, Integer and Accumulate Negative Halfwords -PPC_evmwlusianw3, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate Negative in Words 3 operand -PPC_evmwlssianw3, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate Negative in Words 3 operand -PPC_evmwhssfranw3, // Vector Multiply Word High Signed, Saturate, Fractional, Round, and Accumulate Negative into Words 3 operand -PPC_evmwhssfanw3, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate Negative into Words 3 operand -PPC_evmwhssfranw, // Vector Multiply Word High Signed, Saturate, Fractional, Round, and Accumulate Negative into Words -PPC_evmwhssfanw, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate Negative into Words -PPC_evmwlumianw3, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate Negative in Words 3 operand -PPC_evmwlsmianw3, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate Negative in Words 3 operand -PPC_evmwusian, // Vector Multiply Word Unsigned, Saturate, Integer and Accumulate Negative -PPC_evmwssian, // Vector Multiply Word Signed, Saturate, Integer and Accumulate Negative -PPC_evmwehgsmfran, // Vector Multiply Word Even High, Guarded, Signed, Modulo, Fractional, Round and Accumulate Negative -PPC_evmwehgsmfan, // Vector Multiply Word Even High, Guarded, Signed, Modulo, Fractional and Accumulate Negative -PPC_evmwohgsmfran, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional, Round and Accumulate Negative -PPC_evmwohgsmfan, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional and Accumulate Negative -PPC_evseteqb, // Vector Set if Equal Byte [and Record] -PPC_evseteqh, // Vector Set if Equal Halfword [and Record] -PPC_evseteqw, // Vector Set if Equal Word [and Record] -PPC_evsetgthu, // Vector Set if Greater Than Halfword UnsIgned [and Record] -PPC_evsetgths, // Vector Set if Greater Than Halfword SIgned [and Record] -PPC_evsetgtwu, // Vector Set if Greater Than Word Unsigned [and Record] -PPC_evsetgtws, // Vector Set if Greater Than Word Signed [and Record] -PPC_evsetgtbu, // Vector Set if Greater Than Byte Unsigned [and Record] -PPC_evsetgtbs, // Vector Set if Greater Than Byte SIgned [and Record] -PPC_evsetltbu, // Vector Set if Less Than Byte Unsigned [and Record] -PPC_evsetltbs, // Vector Set if Less Than Byte SIgned [and Record] -PPC_evsetlthu, // Vector Set if Less Than Halfword UnsIgned [and Record] -PPC_evsetlths, // Vector Set if Less Than Halfword SIgned [and Record] -PPC_evsetltwu, // Vector Set if Less Than Word Unsigned [and Record] -PPC_evsetltws, // Vector Set if Less Than Word Signed [and Record] -PPC_evsaduw, // Vector Sum of Absolute Differences of Unsigned Words (to Accumulator) -PPC_evsadsw, // Vector Sum of Absolute Differences of Signed Words (to Accumulator) -PPC_evsad4ub, // Vector Sum of Absolute Differences of 4 Unsigned Bytes (to Accumulator) -PPC_evsad4sb, // Vector Sum of Absolute Differences of 4 Signed Bytes (to Accumulator) -PPC_evsad2uh, // Vector Sum of Absolute Differences of 2 Unsigned Halfwords (to Accumulator) -PPC_evsad2sh, // Vector Sum of Absolute Differences of 2 Signed Halfwords (to Accumulator) -PPC_evsaduwa, // Vector Sum of Absolute Differences of Unsigned Words (to Accumulator) -PPC_evsadswa, // Vector Sum of Absolute Differences of Signed Words (to Accumulator) -PPC_evsad4uba, // Vector Sum of Absolute Differences of 4 Unsigned Bytes (to Accumulator) -PPC_evsad4sba, // Vector Sum of Absolute Differences of 4 Signed Bytes (to Accumulator) -PPC_evsad2uha, // Vector Sum of Absolute Differences of 2 Unsigned Halfwords (to Accumulator) -PPC_evsad2sha, // Vector Sum of Absolute Differences of 2 Signed Halfwords (to Accumulator) -PPC_evabsdifuw, // Vector Absolute Difference of Unsigned Words -PPC_evabsdifsw, // Vector Absolute Difference of Signed Words -PPC_evabsdifub, // Vector Absolute Difference of Unsigned Bytes -PPC_evabsdifsb, // Vector Absolute Difference of Signed Bytes -PPC_evabsdifuh, // Vector Absolute Difference of Unsigned Halfwords -PPC_evabsdifsh, // Vector Absolute Difference of Signed Halfwords -PPC_evsaduwaa, // Vector Sum of Absolute Differences of Unsigned Words and Accumulate -PPC_evsadswaa, // Vector Sum of Absolute Differences of Signed Words and Accumulate -PPC_evsad4ubaaw, // Vector Sum of Absolute Differences of 4 Unsigned Bytes and Accumulate into Words -PPC_evsad4sbaaw, // Vector Sum of Absolute Differences of 4 Signed Bytes and Accumulate into Words -PPC_evsad2uhaaw, // Vector Sum of Absolute Differences of 2 Unsigned Halfwords and Accumulate into Words -PPC_evsad2shaaw, // Vector Sum of Absolute Differences of 2 Signed Halfwords and Accumulate into Words -PPC_evpkshubs, // Vector Pack Signed Halfwords to Unsigned Bytes and Saturate -PPC_evpkshsbs, // Vector Pack Signed Halfwords to Signed Bytes and Saturate -PPC_evpkswuhs, // Vector Pack Signed Words to Unsigned Halfwords and Saturate -PPC_evpkswshs, // Vector Pack Signed Words to Signed Halfwords and Saturate -PPC_evpkuhubs, // Vector Pack Unsigned Halfwords to Unsigned Bytes and Saturate -PPC_evpkuwuhs, // Vector Pack Unsigned Words to Unsigned Halfwords and Saturate -PPC_evpkswshilvs, // Vector Pack Signed Words to Signed Halfwords Interleaved and Saturate -PPC_evpkswgshefrs, // Vector Pack Signed Words Guarded to Signed Halfwords Even Fractional Round and Saturate -PPC_evpkswshfrs, // Vector Pack Signed Words to Signed Halfwords Fractional, Round and Saturate -PPC_evpkswshilvfrs, // Vector Pack Signed Words to Signed Halfwords Interleaved, Fractional, Round and Saturate -PPC_evpksdswfrs, // Vector Pack Signed Doublewords to Signed Words Fractional, Round and Saturate -PPC_evpksdshefrs, // Vector Pack Signed Doublewords to Signed Halfwords Even, Fractional, Round, and Saturate -PPC_evpkuduws, // Vector Pack Unsigned Doublewords to Unsigned Words and Saturate -PPC_evpksdsws, // Vector Pack Signed Doublewords to Signed Words and Saturate -PPC_evpkswgswfrs, // Vector Pack Signed Words Guarded to Signed Words Fractional Round and Saturate -PPC_evilveh, // Vector Interleave Even Halfwords -PPC_evilveoh, // Vector Interleave Even/Odd Halfwords -PPC_evilvhih, // Vector Interleave High Halfwords -PPC_evilvhiloh, // Vector Interleave High/Low Halfwords -PPC_evilvloh, // Vector Interleave Low Halfwords -PPC_evilvlohih, // Vector Interleave Low/High Halfwords -PPC_evilvoeh, // Vector Interleave Odd/Even Halfwords -PPC_evilvoh, // Vector Interleave Odd Halfwords -PPC_evdlveb, // Vector De-interleave Even Bytes -PPC_evdlveh, // Vector De-interleave Even Halfwords -PPC_evdlveob, // Vector De-interleave Even/Odd Bytes -PPC_evdlveoh, // Vector De-interleave Even/Odd Halfwords -PPC_evdlvob, // Vector De-interleave Odd Bytes -PPC_evdlvoh, // Vector De-interleave Odd Halfwords -PPC_evdlvoeb, // Vector De-interleave Odd/Even Bytes -PPC_evdlvoeh, // Vector De-interleave Odd/Even Halfwords -PPC_evmaxbu, // Vector Maximum Byte Unsigned -PPC_evmaxbs, // Vector Maximum Byte Signed -PPC_evmaxhu, // Vector Maximum Halfword Unsigned -PPC_evmaxhs, // Vector Maximum Halfword Signed -PPC_evmaxwu, // Vector Maximum Word Unsigned -PPC_evmaxws, // Vector Maximum Word Signed -PPC_evmaxdu, // Vector Maximum Doubleword Unsigned -PPC_evmaxds, // Vector Maximum Doubleword Signed -PPC_evminbu, // Vector Minimum Byte Unsigned -PPC_evminbs, // Vector Minimum Byte Signed -PPC_evminhu, // Vector Minimum Halfword Unsigned -PPC_evminhs, // Vector Minimum Halfword Signed -PPC_evminwu, // Vector Minimum Word Unsigned -PPC_evminws, // Vector Minimum Word Signed -PPC_evmindu, // Vector Minimum Doubleword Unsigned -PPC_evminds, // Vector Minimum Doubleword Signed -PPC_evavgwu, // Vector Average Word Unsigned -PPC_evavgws, // Vector Average Word Signed -PPC_evavgbu, // Vector Average Byte Unsigned -PPC_evavgbs, // Vector Average Byte Signed -PPC_evavghu, // Vector Average Halfword Unsigned -PPC_evavghs, // Vector Average Halfword Signed -PPC_evavgdu, // Vector Average Doubleword Unsigned -PPC_evavgds, // Vector Average Doubleword Signed -PPC_evavgwur, // Vector Average Word Unsigned with Round -PPC_evavgwsr, // Vector Average Word Signed with Round -PPC_evavgbur, // Vector Average Byte Unsigned with Round -PPC_evavgbsr, // Vector Average Byte Signed with Round -PPC_evavghur, // Vector Average Halfword Unsigned with Round -PPC_evavghsr, // Vector Average Halfword Signed with Round -PPC_evavgdur, // Vector Average Doubleword Unsigned with Round -PPC_evavgdsr, // Vector Average Doubleword Signed with Round - -// Some simplifications that were missed previously -PPC_tdui, // Trap Doubleword Unconditionally with Immediate -PPC_tdu, // Trap Doubleword Unconditionally -PPC_twui, // Trap Word Unconditionally with Immediate -PPC_twu, // Trap Word Unconditionally - -// Power ISA 2.07 -PPC_bctar, // Branch Conditional to Branch Target Address Register -PPC_clrbhrb, // Clear BHRB -PPC_mfbhrbe, // Move From Branch History Rolling Buffer -PPC_mtsle, // Move To Split Little Endian -PPC_mfvsrd, // Move From VSR Doubleword -PPC_mfvsrwz, // Move From VSR Word and Zero -PPC_mtvsrd, // Move To VSR Doubleword -PPC_mtvsrwa, // Move To VSR Word Algebraic -PPC_mtvsrwz, // Move To VSR Word and Zero -PPC_fmrgew, // Floating Merge Even Word -PPC_fmrgow, // Floating Merge Odd Word -PPC_vpksdss, // Vector Pack Signed Doubleword Signed Saturate -PPC_vpksdus, // Vector Pack Signed Doubleword Unsigned Saturate -PPC_vpkudus, // Vector Pack Unsigned Doubleword Unsigned Saturate -PPC_vpkudum, // Vector Pack Unsigned Doubleword Unsigned Modulo -PPC_vupkhsw, // Vector Unpack High Signed Word -PPC_vupklsw, // Vector Unpack Low Signed Word -PPC_vmrgew, // Vector Merge Even Word -PPC_vmrgow, // Vector Merge Odd Word -PPC_vaddudm, // Vector Add Unsigned Doubleword Modulo -PPC_vadduqm, // Vector Add Unsigned Quadword Modulo -PPC_vaddeuqm, // Vector Add Extended Unsigned Quadword Modulo -PPC_vaddcuq, // Vector Add & write Carry Unsigned Quadword -PPC_vaddecuq, // Vector Add Extended & write Carry Unsigned Quadword -PPC_vsubudm, // Vector Subtract Unsigned Doubleword Modulo -PPC_vsubuqm, // Vector Subtract Unsigned Quadword Modulo -PPC_vsubeuqm, // Vector Subtract Extended Unsigned Quadword Modulo -PPC_vsubcuq, // Vector Subtract & write Carry Unsigned Quadword -PPC_vsubecuq, // Vector Subtract Extended & write Carry Unsigned Quadword -PPC_vmulesw, // Vector Multiply Even Signed Word -PPC_vmuleuw, // Vector Multiply Even Unsigned Word -PPC_vmulosw, // Vector Multiply Odd Signed Word -PPC_vmulouw, // Vector Multiply Odd Unsigned Word -PPC_vmuluwm, // Vector Multiply Unsigned Word Modulo -PPC_vmaxsd, // Vector Maximum Signed Doubleword -PPC_vmaxud, // Vector Maximum Unsigned Doubleword -PPC_vminsd, // Vector Minimum Signed Doubleword -PPC_vminud, // Vector Minimum Unsigned Doubleword -PPC_vcmpequd, // Vector Compare Equal To Unsigned Doubleword -PPC_vcmpgtsd, // Vector Compare Greater Than Signed Doubleword -PPC_vcmpgtud, // Vector Compare Greater Than Unsigned Doubleword -PPC_veqv, // Vector Equivalence -PPC_vnand, // Vector NAND -PPC_vorc, // Vector OR with Complement -PPC_vrld, // Vector Rotate Left Doubleword -PPC_vsld, // Vector Shift Left Doubleword -PPC_vsrd, // Vector Shift Right Doubleword -PPC_vsrad, // Vector Shift Right Algebraic Doubleword -PPC_vcipher, // Vector AES Cipher -PPC_vcipherlast, // Vector AES Cipher Last -PPC_vncipher, // Vector AES Inverse Cipher -PPC_vncipherlast, // Vector AES Inverse Cipher Last -PPC_vsbox, // Vector AES S-Box -PPC_vshasigmad, // Vector SHA-512 Sigma Doubleword -PPC_vshasigmaw, // Vector SHA-256 Sigma Word -PPC_vpmsumb, // Vector Polynomial Multiply-Sum Byte -PPC_vpmsumd, // Vector Polynomial Multiply-Sum Doubleword -PPC_vpmsumh, // Vector Polynomial Multiply-Sum Halfword -PPC_vpmsumw, // Vector Polynomial Multiply-Sum Word -PPC_vpermxor, // Vector Permute and Exclusive-OR -PPC_vgbbd, // Vector Gather Bits by Byte by Doubleword -PPC_vclzb, // Vector Count Leading Zeros Byte -PPC_vclzh, // Vector Count Leading Zeros Halfword -PPC_vclzw, // Vector Count Leading Zeros Word -PPC_vclzd, // Vector Count Leading Zeros Doubleword -PPC_vpopcntb, // Vector Population Count Byte -PPC_vpopcntd, // Vector Population Count Doubleword -PPC_vpopcnth, // Vector Population Count Halfword -PPC_vpopcntw, // Vector Population Count Word -PPC_vbpermq, // Vector Bit Permute Quadword -PPC_bcdadd, // Decimal Add Modulo -PPC_bcdsub, // Decimal Subtract Modulo -PPC_lxsiwax, // Load VSX Scalar as Integer Word Algebraic Indexed -PPC_lxsspx, // Load VSX Scalar Single-Precision Indexed -PPC_lxsiwzx, // Load VSX Scalar as Integer Word and Zero Indexed -PPC_stxsiwx, // Store VSX Scalar as Integer Word Indexed -PPC_stxsspx, // Store VSR Scalar Word Indexed -PPC_xsaddsp, // VSX Scalar Add Single-Precision -PPC_xscvdpspn, // VSX Scalar Convert Double-Precision to Single-Precision format Non-signalling -PPC_xscvspdpn, // Scalar Convert Single-Precision to Double-Precision format Non-signalling -PPC_xscvsxdsp, // VSX Scalar Convert Signed Fixed-Point Doubleword to Single-Precision -PPC_xscvuxdsp, // VSX Scalar Convert Unsigned Fixed-Point Doubleword to Single-Precision -PPC_xsdivsp, // VSX Scalar Divide Single-Precision -PPC_xsmaddasp, // VSX Scalar Multiply-Add Type-A Single-Precision -PPC_xsmaddmsp, // VSX Scalar Multiply-Add Type-M Single-Precision -PPC_xsmsubasp, // VSX Scalar Multiply-Subtract Type-A Single-Precision -PPC_xsmsubmsp, // VSX Scalar Multiply-Subtract Type-M Single-Precision -PPC_xsmulsp, // VSX Scalar Multiply Single-Precision -PPC_xsnmaddasp, // VSX Scalar Negative Multiply-Add Type-A Single-Precision -PPC_xsnmaddmsp, // VSX Scalar Negative Multiply-Add Type-M Single-Precision -PPC_xsnmsubasp, // VSX Scalar Negative Multiply-Subtract Type-A Single-Precision -PPC_xsnmsubmsp, // VSX Scalar Negative Multiply-Subtract Type-M Single-Precision -PPC_xsresp, // VSX Scalar Reciprocal Estimate Single-Precision -PPC_xsrsp, // VSX Scalar Round to Single-Precision -PPC_xsrsqrtesp, // VSX Scalar Reciprocal Square Root Estimate Single-Precision -PPC_xssqrtsp, // VSX Scalar Square Root Single-Precision -PPC_xssubsp, // VSX Scalar Subtract Single-Precision -PPC_xxleqv, // VSX Logical Equivalence -PPC_xxlnand, // VSX Logical NAND -PPC_xxlorc, // VSX Logical OR with Complement -PPC_lqarx, // Load Quadword And Reserve Indexed -PPC_stqcx, // Store Quadword Conditional Indexed and record CR0 -PPC_tbegin, // Transaction Begin -PPC_tend, // Transaction End -PPC_tabort, // Transaction Abort -PPC_tabortwc, // Transaction Abort Word Conditional -PPC_tabortwci, // Transaction Abort Word Conditional Immediate -PPC_tabortdc, // Transaction Abort Doubleword Conditional -PPC_tabortdci, // Transaction Abort Doubleword Conditional Immediate -PPC_tsr, // Transaction Suspend or Resume -PPC_tcheck, // Transaction Check -PPC_rfebb, // Return from Event Based Branch -PPC_treclaim, // Transaction Reclaim -PPC_trechkpt, // Transaction Recheckpoint -PPC_msgsndp, // Message Send Privileged -PPC_msgclrp, // Message Clear Privileged -PPC_dcblq, // Data Cache Block Lock Query -PPC_icblq, // Instruction Cache Block Lock Query - -// Simplifications for Power ISA 2.07 -PPC_vmr, // Vector Move Register -PPC_vnot, // Vector Complement Register -PPC_tendall, // Transaction End All -PPC_tsuspend, // Transaction Suspend -PPC_tresume, // Transaction Resume -PPC_mtppr, // Move To Program Priority Register -PPC_mfppr, // Move From Program Priority Register -PPC_mtppr32, // Move To Program Priority Register 32-Bit -PPC_mfppr32, // Move From Program Priority Register 32-Bit -PPC_mtic, // Move To IC -PPC_mfic, // Move From IC -PPC_mtvtb, // Move to VTB -PPC_mfvtb, // Move From VTB -PPC_miso, // "or" Cache Control Hint -PPC_mdoio, // "or" Shared Resource Hint -PPC_mdoom, // "or" Shared Resource Hint -PPC_yield, // "or" Shared Resource Hint -// these are mentioned in the Power ISA 2.07 document but not implemented by -// binutils; since they are just simplifications better to ignore them than to -// emit "weird" mnemonics -// PPC_mtuamr, // Move To Authority Mask Register -// PPC_mfuamr, // Move From Authority Mask Register -// PPC_dcbtct, // Data Cache Block Touch -// PPC_dcbtds, // Data Cache Block Touch -// PPC_dcbna, // Data Cache Block Touch -// PPC_dcbtctep, // Data Cache Block Touch by External PID -// PPC_dcbtdsep, // Data Cache Block Touch by External PID -// PPC_dcbflep, // Data Cache Block Flush by External PID -// PPC_dcbflpep, // Data Cache Block Flush by External PID -// PPC_dcbtstctep, // Data Cache Block Touch for Store by External PID -// -// these are only needed by assemblers -// PPC_lxvx, // Load VSX Vector Doubleword*2 Indexed -// PPC_stxvx, // Store VSX Vector Doubleword*2 Indexed -// PPC_mffprd, // Move From FPR Doubleword -// PPC_mfvrd, // Move From VR Doubleword -// PPC_mffprwz, // Move From FPR Word and Zero -// PPC_mfvrwz, // Move From VR Word and Zero -// PPC_mtfprd, // Move To FPR Doubleword -// PPC_mtvrd, // Move To VR Doubleword -// PPC_mtfprwa, // Move To FPR Word Algebraic -// PPC_mtvrwa, // Move To VR Word Algebraic -// PPC_mtfprwz, // Move To FPR Word and Zero -// PPC_mtvrwz, // Move To VR Word and Zero - -// e500 core family, category ISAT, valid for VLE -// EREF_RM Rev. 1 (EIS 2.1) 06/2014 -PPC_addbss, // Add Byte Signed Saturate -PPC_addhss, // Add Halfword Signed Saturate -PPC_addwss, // Add Word Signed Saturate -PPC_addbus, // Add Byte Unsigned Saturate -PPC_addhus, // Add Halfword Unsigned Saturate -PPC_addwus, // Add Word Unsigned Saturate -PPC_mulhss, // Multiply Halfword SIgned Saturate -PPC_mulwss, // Multiply Word SIgned Saturate -PPC_mulhus, // Multiply Halfword Unsigned Saturate -PPC_mulwus, // Multiply Word Unsigned Saturate -PPC_sat, // Saturate -PPC_subfbss, // Subtract From Byte Signed Saturate -PPC_subfhss, // Subtract From Halfword Signed Saturate -PPC_subfwss, // Subtract From Word Signed Saturate -PPC_subfbus, // Subtract From Byte Unsigned Saturate -PPC_subfhus, // Subtract From Halfword Unsigned Saturate -PPC_subfwus, // Subtract From Word Unsigned Saturate -// simplified mnemonics for PPC_sat -PPC_satsbs, // Saturate -PPC_satubs, // Saturate -PPC_satsbu, // Saturate -PPC_satubu, // Saturate -PPC_abssb, // Saturate -PPC_absub, // Saturate -PPC_satshs, // Saturate -PPC_satuhs, // Saturate -PPC_satshu, // Saturate -PPC_satuhu, // Saturate -PPC_abssh, // Saturate -PPC_absuh, // Saturate -PPC_satsws, // Saturate -PPC_satuws, // Saturate -PPC_satswu, // Saturate -PPC_satuwu, // Saturate -PPC_abssw, // Saturate -PPC_absuw, // Saturate - -//e200 Enhanced Debug extension -PPC_dni, // Debugger Notify Interrupt - -// Power ISA Version 3.0 -PPC_slbieg, // SLB Invalidate Entry Global -PPC_slbiag, // SLB Invalidate All Global -PPC_slbsync, // SLB Synchronize - -PPC_addpcis, // Add PC Immediate Shifted -PPC_lnia, // Add PC Immediate Shifted -PPC_subpcis, // Add PC Immediate Shifted -PPC_cmpeqb, // Compare Equal Byte -PPC_cmprb, // Compare Ranged Byte -PPC_cnttzw, // Count Trailing Zeros Word -PPC_cnttzd, // Count Trailing Zeros Dword -PPC_darn, // Deliver A Random Number -PPC_extswsli, // Extend-Sign Word and Shift Left -PPC_maddhd, // Multiply-Add High Doublewor -PPC_maddhdu, // Multiply-Add High Doubleword Unsigned -PPC_maddld, // Multiply-Add Low Doubleword -PPC_mcrxrx, // Move to CR from XER Extended, PPC_mcrxr disappeared -PPC_setb, // Set Boolean -PPC_modsd, // Modulo Signed Dword -PPC_modud, // Modulo Unsigned Dword -PPC_modsw, // Modulo Signed Word -PPC_moduw, // Modulo Unsigned Word -PPC_mfvsrld, // Move From VSR Lower Doubleword -PPC_mtvsrdd, // Move To VSR Double Dword -PPC_mtvsrws, // Move To VSR Word & Splat -PPC_scv, // System Call Vectored -PPC_rfscv, // Return From System Call Vectored -PPC_stop, // Stop - -PPC_copy, // Copy -PPC_paste, // Paste -PPC_ldat, // Load Dword ATomic -PPC_lwat, // Load Word ATomic -PPC_stdat, // Store Dword ATomic -PPC_stwat, // Store Word ATomic -PPC_cpabort, // Copy-Paste Abort -PPC_wait30, // Wait for Interrupt - -PPC_dtstsfi, // DFP Test Significance Immediate -PPC_dtstsfiq, // DFP Test Significance Immediate Quad - -PPC_bcdcfn, // Decimal Convert From National & record -PPC_bcdcfz, // Decimal Convert From Zoned & record -PPC_bcdctn, // Decimal Convert To National & record -PPC_bcdctz, // Decimal Convert To Zoned & record -PPC_bcdctsq, // Decimal Convert To Signed Qword & record -PPC_bcdcfsq, // Decimal Convert From Signed Qword & record -PPC_bcdsetsgn, // Decimal Set Sign & record -PPC_bcdcpsgn, // Decimal CopySign & record -PPC_bcds, // Decimal Shift & record -PPC_bcdus, // Decimal Unsigned Shift & record -PPC_bcdsr, // Decimal Shift & Round & record -PPC_bcdtrunc, // Decimal Truncate & record -PPC_bcdutrunc, // Decimal Unsigned Truncate & record - -PPC_vabsdub, // Vector Absolute Difference Unsigned Byte -PPC_vabsduh, // Vector Absolute Difference Unsigned Hword -PPC_vabsduw, // Vector Absolute Difference Unsigned Word -PPC_vbpermd, // Vector Bit Permute Dword -PPC_vclzlsbb, // Vector Count Leading Zero Least-Significant Bits Byte -PPC_vctzlsbb, // Vector Count Trailing Zero Least-Significant Bits Byte -PPC_vcmpneb, // Vector Compare Not Equal Byte -PPC_vcmpnezb, // Vector Compare Not Equal or Zero Byte -PPC_vcmpneh, // Vector Compare Not Equal Hword -PPC_vcmpnezh, // Vector Compare Not Equal or Zero Hword -PPC_vcmpnew, // Vector Compare Not Equal Word -PPC_vcmpnezw, // Vector Compare Not Equal or Zero Word -PPC_vctzb, // Vector Count Trailing Zeros Byte -PPC_vctzh, // Vector Count Trailing Zeros Hword -PPC_vctzw, // Vector Count Trailing Zeros Word -PPC_vctzd, // Vector Count Trailing Zeros Dword -PPC_vextractub, // Vector Extract Unsigned Byte -PPC_vextractuh, // Vector Extract Unsigned Hword -PPC_vextractuw, // Vector Extract Unsigned Word -PPC_vextractd, // Vector Extract Dword -PPC_vextsb2w, // Vector Extend Sign Byte to Word -PPC_vextsb2d, // Vector Extend Sign Byte to Dword -PPC_vextsh2w, // Vector Extend Sign Hword to Word -PPC_vextsh2d, // Vector Extend Sign Hword to Dword -PPC_vextsw2d, // Vector Extend Sign Word to Dword -PPC_vextublx, // Vector Extract Unsigned Byte Left-Indexed -PPC_vextubrx, // Vector Extract Unsigned Byte Right-Indexed -PPC_vextuhlx, // Vector Extract Unsigned Hword Left-Indexed -PPC_vextuhrx, // Vector Extract Unsigned Hword Right-Indexed -PPC_vextuwlx, // Vector Extract Unsigned Word Left-Indexed -PPC_vextuwrx, // Vector Extract Unsigned Word Right-Indexed -PPC_vinsertb, // Vector Insert Byte -PPC_vinserth, // Vector Insert Hword -PPC_vinsertw, // Vector Insert Word -PPC_vinsertd, // Vector Insert Dword -PPC_vmul10uq, // Vector Multiply-by-10 Unsigned Qword -PPC_vmul10euq, // Vector Multiply-by-10 Extended Unsigned Qword -PPC_vmul10cuq, // Vector Multiply-by-10 & write Carry Unsigned Qword -PPC_vmul10ecuq, // Vector Multiply-by-10 Extended & write Carry Unsigned Qword -PPC_vnegw, // Vector Negate Word -PPC_vnegd, // Vector Negate Dword -PPC_vpermr, // Vector Permute Right-indexed -PPC_vprtybw, // Vector Parity Byte Word -PPC_vprtybd, // Vector Parity Byte Dword -PPC_vprtybq, // Vector Parity Byte Qword -PPC_vrlwnm, // Vector Rotate Left Word then AND with Mask -PPC_vrlwmi, // Vector Rotate Left Word then Mask Insert -PPC_vrldnm, // Vector Rotate Left Dword then AND with Mask -PPC_vrldmi, // Vector Rotate Left Dword then Mask Insert -PPC_vslv, // Vector Shift Left Variable -PPC_vsrv, // Vector Shift Right Variable - -PPC_lxsd, // Load VSX Scalar Dword -PPC_lxssp, // Load VSX Scalar Single -PPC_lxsibzx, // Load VSX Scalar as Integer Byte & Zero Indexed -PPC_lxsihzx, // Load VSX Scalar as Integer Hword & Zero Indexed -PPC_lxv, // Load VSX Vector -PPC_lxvb16x, // Load VSX Vector Byte*16 Indexed -PPC_lxvh8x, // Load VSX Vector Hword*8 Indexed -PPC_lxvl, // Load VSX Vector with Length -PPC_lxvll, // Load VSX Vector Left-justified with Length -PPC_lxvwsx, // Load VSX Vector Word & Splat Indexed -PPC_lxvx, // Load VSX Vector Indexed -PPC_stxsd, // Store VSX Scalar Dword -PPC_stxsibx, // Store VSX Scalar as Integer Byte Indexed -PPC_stxsihx, // Store VSX Scalar as Integer Hword Indexed -PPC_stxssp, // Store VSX Scalar SP -PPC_stxv, // Store VSX Vector -PPC_stxvb16x, // Store VSX Vector Byte*16 Indexed -PPC_stxvh8x, // Store VSX Vector Hword*8 Indexed -PPC_stxvl, // Store VSX Vector with Length -PPC_stxvll, // Store VSX Vector Left-justified with Length -PPC_stxvx, // Store VSX Vector Indexed - -PPC_xsabsqp, // VSX Scalar Absolute QP -PPC_xsaddqp, // VSX Scalar Add QP -PPC_xscmpexpqp, // VSX Scalar Compare Exponents QP -PPC_xscmpoqp, // VSX Scalar Compare Ordered QP -PPC_xscmpuqp, // VSX Scalar Compare Unordered QP -PPC_xscpsgnqp, // VSX Scalar Copy Sign QP -PPC_xscvdpqp, // VSX Scalar Convert DP to QP -PPC_xscvqpdp, // VSX Scalar Convert QP to DP -PPC_xscvqpsdz, // VSX Scalar Convert QP to Signed Dword truncate -PPC_xscvqpswz, // VSX Scalar Convert QP to Signed Word truncate -PPC_xscvqpudz, // VSX Scalar Convert QP to Unsigned Dword truncate -PPC_xscvqpuwz, // VSX Scalar Convert QP to Unsigned Word truncate -PPC_xscvsdqp, // VSX Scalar Convert Signed Dword to QP -PPC_xscvudqp, // VSX Scalar Convert Unsigned Dword to QP -PPC_xsdivqp, // VSX Scalar Divide QP -PPC_xsiexpqp, // VSX Scalar Insert Exponent QP -PPC_xsmaddqp, // VSX Scalar Multiply-Add QP -PPC_xsmsubqp, // VSX Scalar Multiply-Subtract QP -PPC_xsmulqp, // VSX Scalar Multiply QP -PPC_xsnabsqp, // VSX Scalar Negative Absolute QP -PPC_xsnegqp, // VSX Scalar Negate QP -PPC_xsnmaddqp, // VSX Scalar Negative Multiply-Add QP -PPC_xsnmsubqp, // VSX Scalar Negative Multiply-Subtract QP -PPC_xssqrtqp, // VSX Scalar Square Root QP -PPC_xssubqp, // VSX Scalar Subtract QP -PPC_xsxexpqp, // VSX Scalar Extract Exponent QP -PPC_xsxsigqp, // VSX Scalar Extract Significand QP -PPC_xststdcqp, // VSX Scalar Test Data Class QP -PPC_xsrqpxp, // VSX Scalar Round QP to XP -PPC_xsrqpi, // VSX Scalar Round QP to Integral [with Inexact] -PPC_xscmpeqdp, // VSX Scalar Compare Equal Double-Precision -PPC_xscmpexpdp, // VSX Scalar Compare Exponents DP -PPC_xscmpgedp, // VSX Scalar Compare Greater Than or Equal Double-Precision -PPC_xscmpgtdp, // VSX Scalar Compare Greater Than Double-Precision -PPC_xsiexpdp, // VSX Scalar Insert Exponent DP -PPC_xsmaxcdp, // VSX Scalar Maximum Type-C Double-Precision -PPC_xsmaxjdp, // VSX Scalar Maximum Type-J Double-Precision -PPC_xsmincdp, // VSX Scalar Minimum Type-C Double-Precision -PPC_xsminjdp, // VSX Scalar Minimum Type-J Double-Precision -PPC_xviexpdp, // VSX Vector Insert Exponent DP -PPC_xviexpsp, // VSX Vector Insert Exponent SP -PPC_xxextractuw,// VSX Vector Extract Unsigned Word -PPC_xxinsertw, // VSX Vector Insert Word -PPC_xxperm, // VSX Vector Permute -PPC_xxpermr, // VSX Vector Permute Right-indexed -PPC_xxspltib, // VSX Vector Splat Immediate Byte -PPC_xststdcdp, // VSX Scalar Test Data Class DP -PPC_xststdcsp, // VSX Scalar Test Data Class SP -PPC_xvtstdcdp, // VSX Vector Test Data Class DP -PPC_xvtstdcsp, // VSX Vector Test Data Class SP -PPC_xsxexpdp, // VSX Scalar Extract Exponent DP -PPC_xsxsigdp, // VSX Scalar Extract Significand DP -PPC_xscvdphp, // VSX Scalar Convert DP to HP -PPC_xscvhpdp, // VSX Scalar Convert HP to DP -PPC_xvxexpdp, // VSX Vector Extract Exponent DP -PPC_xvxexpsp, // VSX Vector Extract Exponent SP -PPC_xvxsigdp, // VSX Vector Extract Significand DP -PPC_xvxsigsp, // VSX Vector Extract Significand SP -PPC_xxbrd, // VSX Vector Byte-Reverse Dword -PPC_xxbrh, // VSX Vector Byte-Reverse Hword -PPC_xxbrq, // VSX Vector Byte-Reverse Qword -PPC_xxbrw, // VSX Vector Byte-Reverse Word -PPC_xvcvhpsp, // VSX Vector Convert HP to SP -PPC_xvcvsphp, // VSX Vector Convert SP to HP - -PPC_msgsync, // Message Synchronize - -// Instructions introduced in ISA 3.0 and withdrawn in ISA 3.0B : -// ldmx "Load Dword Monitored Indexed" -// xscmpnedp "VSX Scalar Compare Not Equal Double-Precision" -// xvcmpnedp[.] "VSX Vector Compare Not Equal Double-Precision" -// xvcmpnesp[.] "VSX Vector Compare Not Equal Single-Precision" - -// Power ISA Version 3.0 B -PPC_addex, // Add Extended using alternate carry -PPC_vmsumudm, // Vector Multiply-Sum Unsigned Doubleword Modulo -PPC_mffsce, // Move From FPSCR & Clear Enables -PPC_mffscdrn, // Move From FPSCR Control & set DRN -PPC_mffscdrni, // Move From FPSCR Control & set DRN Immediate -PPC_mffscrn, // Move From FPSCR Control & set RN -PPC_mffscrni, // Move From FPSCR Control & set RN Immediate -PPC_mffsl, // Move From FPSCR Lightweight - -// Cache Bypass Storage APU -PPC_lbdcbx, // Load Byte with Decoration Indexed Cache Bypass -PPC_lhdcbx, // Load Halfword with Decoration Indexed Cache Bypass -PPC_lwdcbx, // Load Word with Decoration Indexed Cache Bypass -PPC_stbdcbx, // Store Byte with Decoration Indexed Cache Bypass -PPC_sthdcbx, // Store Halfword with Decoration Indexed Cache Bypass -PPC_stwdcbx, // Store Word with Decoration Indexed Cache Bypass - -PPC_lbcbx, // Load Byte Indexed Cache Bypass -PPC_lhcbx, // Load Halfword Indexed Cache Bypass -PPC_lwcbx, // Load Word Indexed Cache Bypass -PPC_stbwtx, // Store Byte Indexed Cache Bypass -PPC_sthwtx, // Store Halfword Indexed Cache Bypass -PPC_stwwtx, // Store Word Indexed Cache Bypass -PPC_dsncb, // Decorated Storage Notify Cache Bypass - -// AIOP (E200Z490) -PPC_ldw, // Load Doubleword -PPC_stdw, // Store Doubleword -PPC_lqw, // Load Quadword -PPC_stqw, // Store Quadword -PPC_ldwcb, // Load Doubleword Cache Bypassed -PPC_ldbrw, // Load Byte Reversed Doubleword -PPC_ldwbrw, // Load Two Byte Reversed Words -PPC_stdwwt, // Store Doubleword with Write-Through -PPC_stdbrw, // Store Doubleword Bytes Reversed -PPC_stdwbrw, // Store Doubleword Byte Reversed in Word -PPC_lqdbrw, // Load Quadword Byte Reversed -PPC_stqdbrw, // Store Quadword Byte Reversed -PPC_lwbr, // Load Word Byte Reversed -PPC_lhbr, // Load Halfword Byte Reversed -PPC_stwbr, // Store Word Byte Reversed -PPC_sthbr, // Store Halfword Byte Reversed -PPC_ldwar, // Load Doubleword and reserve -PPC_stdwc, // Store Doubleword conditional on reservation -PPC_addb, // Add Two Bytes -PPC_addbu, // Add Two Unsigned Bytes -PPC_addh, // Add Two Halfwords -PPC_addhu, // Add Two Unsigned Halfwords -PPC_subfb, // Signed Byte One's Complement Add -PPC_subfbu, // Unsigned Byte One's Complement Add -PPC_subfh, // Signed Halfword One's Complement Subtract -PPC_subfhu, // Unsigned Halfword One's Complement Subtract -PPC_byterevw, // Reverse bytes in a word -PPC_byterevh, // Reverse bytes in each halfword -PPC_hwaccel, // Hardware Acceleration Request -PPC_hwacceli, // Hardware Acceleration Request -PPC_ordhwaccel, // Ordered Hardware Acceleration Request -PPC_ordhwacceli,// Ordered Hardware Acceleration Request -PPC_osmcmd, // Ordered Scope Management Command Request -PPC_mpure, // MPU Read Entry Instruction -PPC_mpuwe, // MPU Write Entry Instruction -PPC_mpusync, // MPU Synchronize Instruction - - -PPC_last, -}; - -/* -* Interactive disassembler (IDA). -* Copyright (c) 1990-2020 Hex-Rays -* ALL RIGHTS RESERVED. -* -*/ - - - -//---------------------------------------------------------------------- - - -enum NEC850_Instructions -{ - NEC850_NULL = 0, - - NEC850_BREAKPOINT, - NEC850_XORI, - NEC850_XOR, - NEC850_TST1, - NEC850_TST, - NEC850_TRAP, - NEC850_SUBR, - NEC850_SUB, - NEC850_STSR, - NEC850_ST_B, - NEC850_ST_H, - NEC850_ST_W, - NEC850_SST_B, - NEC850_SST_H, - NEC850_SST_W, - NEC850_SLD_B, - NEC850_SLD_H, - NEC850_SLD_W, - NEC850_SHR, - NEC850_SHL, - NEC850_SET1, - NEC850_SETF, - NEC850_SATSUBR, - NEC850_SATSUBI, - NEC850_SATSUB, - NEC850_SATADD, - NEC850_SAR, - NEC850_RETI, - NEC850_ORI, - NEC850_OR, - NEC850_NOT1, - NEC850_NOT, - NEC850_NOP, - NEC850_MULHI, - NEC850_MULH, - NEC850_MOVHI, - NEC850_MOVEA, - NEC850_MOV, - NEC850_LDSR, - NEC850_LD_B, - NEC850_LD_H, - NEC850_LD_W, - NEC850_JR, - NEC850_JMP, - NEC850_JARL, - NEC850_HALT, - NEC850_EI, - NEC850_DIVH, - NEC850_DI, - NEC850_CMP, - NEC850_CLR1, - NEC850_BV, - NEC850_BL, - NEC850_BZ, - NEC850_BNH, - NEC850_BN, - NEC850_BR, - NEC850_BLT, - NEC850_BLE, - NEC850_BNV, - NEC850_BNC, - NEC850_BNZ, - NEC850_BH, - NEC850_BP, - NEC850_BSA, - NEC850_BGE, - NEC850_BGT, - NEC850_ANDI, - NEC850_AND, - NEC850_ADDI, - NEC850_ADD, - - // - // V850E/E1/ES - // - NEC850_SWITCH, - NEC850_ZXB, - NEC850_SXB, - NEC850_ZXH, - NEC850_SXH, - NEC850_DISPOSE_r0, - NEC850_DISPOSE_r, - NEC850_CALLT, - NEC850_DBTRAP, - NEC850_DBRET, - NEC850_CTRET, - - NEC850_SASF, - - NEC850_PREPARE_sp, - NEC850_PREPARE_i, - - NEC850_MUL, - NEC850_MULU, - - NEC850_DIVH_r3, - NEC850_DIVHU, - NEC850_DIV, - NEC850_DIVU, - - NEC850_BSW, - NEC850_BSH, - NEC850_HSW, - - NEC850_CMOV, - - NEC850_SLD_BU, - NEC850_SLD_HU, - NEC850_LD_BU, - NEC850_LD_HU, - - // - // V850E2 - // - NEC850_ADF, // Add on condition flag - - NEC850_HSH, // Halfword swap halfword - NEC850_MAC, // Multiply and add word - NEC850_MACU, // Multiply and add word unsigned - - NEC850_SBF, // Subtract on condition flag - - NEC850_SCH0L, // Search zero from left - NEC850_SCH0R, // Search zero from right - NEC850_SCH1L, // Search one from left - NEC850_SCH1R, // Search one from right - - // - // V850E2M - // - NEC850_CAXI, // Compare and exchange for interlock - NEC850_DIVQ, // Divide word quickly - NEC850_DIVQU, // Divide word unsigned quickly - NEC850_EIRET, // Return from EI level exception - NEC850_FERET, // Return from FE level exception - NEC850_FETRAP, // FE-level Trap - NEC850_RMTRAP, // Runtime monitor trap - NEC850_RIE, // Reserved instruction exception - NEC850_SYNCE, // Synchronize exceptions - NEC850_SYNCM, // Synchronize memory - NEC850_SYNCP, // Synchronize pipeline - NEC850_SYSCALL, // System call - - // floating point (E1F only) - NEC850_CVT_SW, // Real to integer conversion - NEC850_TRNC_SW, // Real to integer conversion - NEC850_CVT_WS, // Integer to real conversion - NEC850_LDFC, // Load to Floating Controls - NEC850_LDFF, // Load to Floating Flags - NEC850_STFC, // Store Floating Controls - NEC850_STFF, // Store Floating Flags - NEC850_TRFF, // Transfer Floating Flags - - // floating point (E2M) - - NEC850_ABSF_D, // Floating-point Absolute Value (Double) - NEC850_ABSF_S, // Floating-point Absolute Value (Single) - NEC850_ADDF_D, // Floating-point Add (Double) - NEC850_ADDF_S, // Floating-point Add (Single) - NEC850_DIVF_D, // Floating-point Divide (Double) - NEC850_DIVF_S, // Floating-point Divide (Single) - NEC850_MAXF_D, // Floating-point Maximum (Double) - NEC850_MAXF_S, // Floating-point Maximum (Single) - NEC850_MINF_D, // Floating-point Minimum (Double) - NEC850_MINF_S, // Floating-point Minimum (Single) - NEC850_MULF_D, // Floating-point Multiply (Double) - NEC850_MULF_S, // Floating-point Multiply (Single) - NEC850_NEGF_D, // Floating-point Negate (Double) - NEC850_NEGF_S, // Floating-point Negate (Single) - NEC850_RECIPF_D, // Reciprocal of a floating-point value (Double) - NEC850_RECIPF_S, // Reciprocal of a floating-point value (Single - - NEC850_RSQRTF_D, // Reciprocal of the square root of a floating-point value (Double) - NEC850_RSQRTF_S, // Reciprocal of the square root of a floating-point value (Single) - NEC850_SQRTF_D, // Floating-point Square Root (Double) - NEC850_SQRTF_S, // Floating-point Square Root (Single) - NEC850_SUBF_D, // Floating-point Subtract (Double) - NEC850_SUBF_S, // Floating-point Subtract (Single) - NEC850_MADDF_S, // Floating-point Multiply-Add (Single) - NEC850_MSUBF_S, // Floating-point Multiply-Subtract (Single) - NEC850_NMADDF_S, // Floating-point Negate Multiply-Add (Single) - NEC850_NMSUBF_S, // Floating-point Negate Multiply-Subtract (Single) - - NEC850_CEILF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double) - NEC850_CEILF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double) - NEC850_CEILF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single) - NEC850_CEILF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single) - NEC850_CEILF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double) - NEC850_CEILF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double) - NEC850_CEILF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single) - NEC850_CEILF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single) - NEC850_CVTF_DL, // Floating-point Convert to Long Fixed-point Format (Double) - NEC850_CVTF_DS, // Floating-point Convert to Single Floating-point Format (Double) - NEC850_CVTF_DUL, // Floating-point Convert Double to Unsigned-Long (Double) - NEC850_CVTF_DUW, // Floating-point Convert Double to Unsigned-Word (Double) - NEC850_CVTF_DW, // Floating-point Convert to Single Fixed-point Format (Double) - NEC850_CVTF_LD, // Floating-point Convert to Single Floating-point Format (Double) - NEC850_CVTF_LS, // Floating-point Convert to Single Floating-point Format (Single) - NEC850_CVTF_SD, // Floating-point Convert to Double Floating-point Format (Double) - NEC850_CVTF_SL, // Floating-point Convert to Long Fixed-point Format (Single) - NEC850_CVTF_SUL, // Floating-point Convert Single to Unsigned-Long (Single) - NEC850_CVTF_SUW, // Floating-point Convert Single to Unsigned-Word (Single) - NEC850_CVTF_SW, // Floating-point Convert to Single Fixed-point Format (Single) - NEC850_CVTF_ULD, // Floating-point Convert Unsigned-Long to Double (Double) - NEC850_CVTF_ULS, // Floating-point Convert Unsigned-Long to Single (Single) - NEC850_CVTF_UWD, // Floating-point Convert Unsigned-Word to Double (Double) - NEC850_CVTF_UWS, // Floating-point Convert Unsigned-Word to Single (Single) - NEC850_CVTF_WD, // Floating-point Convert to Single Floating-point Format (Double) - NEC850_CVTF_WS, // Floating-point Convert to Single Floating-point Format (Single) - NEC850_FLOORF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double) - NEC850_FLOORF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double) - NEC850_FLOORF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single) - NEC850_FLOORF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single) - NEC850_FLOORF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double) - NEC850_FLOORF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double) - NEC850_FLOORF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single) - NEC850_FLOORF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single) - NEC850_TRNCF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double) - NEC850_TRNCF_DUL, // Floating-point Truncate Double to Unsigned-Long (Double) - NEC850_TRNCF_DUW, // Floating-point Truncate Double to Unsigned-Word (Double) - NEC850_TRNCF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double) - NEC850_TRNCF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single) - NEC850_TRNCF_SUL, // Floating-point Truncate Single to Unsigned-Long (Single) - NEC850_TRNCF_SUW, // Floating-point Truncate Single to Unsigned-Word (Single) - NEC850_TRNCF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single) - NEC850_CMPF_S, // Compares floating-point values (Single) - NEC850_CMPF_D, // Compares floating-point values (Double) - NEC850_CMOVF_S, // Floating-point conditional move (Single) - NEC850_CMOVF_D, // Floating-point conditional move (Double) - NEC850_TRFSR, // Transfers specified CC bit to Zero flag in PSW (Single) - - // - // RH850 - // - NEC850_SYNCI, // Synchronize instruction pipeline - NEC850_SNOOZE, // Snooze - NEC850_BINS, // Bitfield Insert - NEC850_ROTL, // Rotate Left - NEC850_LOOP, // Loop - NEC850_LD_DW, // Load Double Word - NEC850_ST_DW, // Store Double Word - NEC850_LDL_W, // Load Linked - NEC850_STC_W, // Store Conditional - NEC850_CLL, // Clear Load Link - NEC850_CACHE, // Cache operation - NEC850_PREF, // Prefetch - NEC850_PUSHSP, // Push registers to Stack - NEC850_POPSP, // Pop registers from Stack - - // new RH850 FP instructions - NEC850_CVTF_HS, // Floating-point Convert Half to Single (Single) - NEC850_CVTF_SH, // Floating-point Convert Single to Half (Single) - NEC850_FMAF_S, // Floating-point Fused-Multiply-add (Single) - NEC850_FMSF_S, // Floating-point Fused-Multiply-subtract (Single) - NEC850_FNMAF_S, // Floating-point Fused-Negate-Multiply-add (Single) - NEC850_FNMSF_S, // Floating-point Fused-Negate-Multiply-subtract (Single) - - // debug instructions - NEC850_DBPUSH, // - NEC850_DBCP, // - NEC850_DBTAG, // - NEC850_DBHVTRAP, // - - // virtualization instructions - NEC850_EST, // - NEC850_DST, // - NEC850_HVTRAP, // - NEC850_HVCALL, // - NEC850_LDVC_SR, // - NEC850_STVC_SR, // - NEC850_LDTC_GR, // - NEC850_STTC_GR, // - NEC850_LDTC_PC, // - NEC850_STTC_PC, // - NEC850_LDTC_SR, // - NEC850_STTC_SR, // - NEC850_LDTC_VR, // - NEC850_STTC_VR, // - - // TLB instructions - NEC850_TLBAI, // - NEC850_TLBR, // - NEC850_TLBS, // - NEC850_TLBVI, // - NEC850_TLBW, // - - NEC850_LAST_INSTRUCTION -}; - -/* - * Tricore Disassembly Module - * Version 1.0 - * Copyright (c) 2000 by Juergen Krumm - * ALL RIGHTS RESERVED - * - * - */ - - - -enum -{ - TRICORE_null = 0, // Unknown Operation - TRICORE_abs, - TRICORE_abs_b, - TRICORE_abs_h, - TRICORE_absdif, - TRICORE_absdif_b, - TRICORE_absdif_h, - TRICORE_absdifs, - TRICORE_absdifs_h, - TRICORE_abss, - TRICORE_abss_h, - TRICORE_add_b, - TRICORE_add_f, - TRICORE_add_h, - TRICORE_add16, - TRICORE_add16_a, - TRICORE_add32, - TRICORE_add32_a, - TRICORE_addc, - TRICORE_addi, - TRICORE_addih, - TRICORE_addih_a, - TRICORE_adds, - TRICORE_adds_h, - TRICORE_adds_hu, - TRICORE_adds_u, - TRICORE_adds16, - TRICORE_addsc_at, - TRICORE_addsc16_a, - TRICORE_addsc32_a, - TRICORE_addx, - TRICORE_and_and_t, - TRICORE_and_andn_t, - TRICORE_and_eq, - TRICORE_and_ge, - TRICORE_and_ge_u, - TRICORE_and_lt, - TRICORE_and_lt_u, - TRICORE_and_ne, - TRICORE_and_nor_t, - TRICORE_and_or_t, - TRICORE_and_t, - TRICORE_and16, - TRICORE_and32, - TRICORE_andn, - TRICORE_andn_t, - TRICORE_bisr16, - TRICORE_bisr32, - TRICORE_bmerge, - TRICORE_bsplit, - TRICORE_cachea_i, - TRICORE_cachea_w, - TRICORE_cachea_wi, - TRICORE_cadd16, - TRICORE_cadd32, - TRICORE_caddn16, - TRICORE_caddn32, - TRICORE_call16, - TRICORE_call32, - TRICORE_calla, - TRICORE_calli, - TRICORE_clo, - TRICORE_clo_h, - TRICORE_cls, - TRICORE_cls_h, - TRICORE_clz, - TRICORE_clz_h, - TRICORE_cmov16, - TRICORE_cmovn16, - TRICORE_cmp_f, - TRICORE_csub, - TRICORE_csubn, - TRICORE_debug16, - TRICORE_debug32, - TRICORE_dextr, - TRICORE_disable, - TRICORE_div_f, - TRICORE_dsync, - TRICORE_dvadj, - TRICORE_dvinit, - TRICORE_dvinit_b, - TRICORE_dvinit_bu, - TRICORE_dvinit_h, - TRICORE_dvinit_hu, - TRICORE_dvinit_u, - TRICORE_dvstep, - TRICORE_dvstep_u, - TRICORE_enable, - TRICORE_eq_a, - TRICORE_eq_b, - TRICORE_eq_h, - TRICORE_eq_w, - TRICORE_eq16, - TRICORE_eq32, - TRICORE_eqany_b, - TRICORE_eqany_h, - TRICORE_eqz_a, - TRICORE_extr, - TRICORE_extr_u, - TRICORE_ftoi, - TRICORE_ftoq31, - TRICORE_ftou, - TRICORE_ge, - TRICORE_ge_a, - TRICORE_ge_u, - TRICORE_imask, - TRICORE_ins_t, - TRICORE_insert, - TRICORE_insn_t, - TRICORE_isync, - TRICORE_itof, - TRICORE_ixmax, - TRICORE_ixmax_u, - TRICORE_ixmin, - TRICORE_ixmin_u, - TRICORE_j16, - TRICORE_j32, - TRICORE_ja, - TRICORE_jeq_a, - TRICORE_jeq16, - TRICORE_jeq32, - TRICORE_jge, - TRICORE_jge_u, - TRICORE_jgez16, - TRICORE_jgtz16, - TRICORE_ji16, - TRICORE_ji32, - TRICORE_jl, - TRICORE_jla, - TRICORE_jlez16, - TRICORE_jli, - TRICORE_jlt, - TRICORE_jlt_u, - TRICORE_jltz16, - TRICORE_jne_a, - TRICORE_jne16, - TRICORE_jne32, - TRICORE_jned, - TRICORE_jnei, - TRICORE_jnz16, - TRICORE_jnz16_a, - TRICORE_jnz16_t, - TRICORE_jnz32_a, - TRICORE_jnz32_t, - TRICORE_jz16, - TRICORE_jz16_a, - TRICORE_jz16_t, - TRICORE_jz32_a, - TRICORE_jz32_t, - TRICORE_ld_b, - TRICORE_ld_d, - TRICORE_ld_da, - TRICORE_ld_hu, - TRICORE_ld_q, - TRICORE_ld16_a, - TRICORE_ld16_bu, - TRICORE_ld16_h, - TRICORE_ld16_w, - TRICORE_ld32_a, - TRICORE_ld32_bu, - TRICORE_ld32_h, - TRICORE_ld32_w, - TRICORE_ldlcx, - TRICORE_ldmst, - TRICORE_lducx, - TRICORE_lea, - TRICORE_loop16, - TRICORE_loop32, - TRICORE_loopu, - TRICORE_lt_a, - TRICORE_lt_b, - TRICORE_lt_bu, - TRICORE_lt_h, - TRICORE_lt_hu, - TRICORE_lt_u, - TRICORE_lt_w, - TRICORE_lt_wu, - TRICORE_lt16, - TRICORE_lt32, - TRICORE_madd, - TRICORE_madd_f, - TRICORE_madd_h, - TRICORE_madd_q, - TRICORE_madd_u, - TRICORE_maddm_h, - TRICORE_maddms_h, - TRICORE_maddr_h, - TRICORE_maddr_q, - TRICORE_maddrs_h, - TRICORE_maddrs_q, - TRICORE_madds, - TRICORE_madds_h, - TRICORE_madds_q, - TRICORE_madds_u, - TRICORE_maddsu_h, - TRICORE_maddsum_h, - TRICORE_maddsums_h, - TRICORE_maddsur_h, - TRICORE_maddsurs_h, - TRICORE_maddsus_h, - TRICORE_max, - TRICORE_max_b, - TRICORE_max_bu, - TRICORE_max_h, - TRICORE_max_hu, - TRICORE_max_u, - TRICORE_mfcr, - TRICORE_min, - TRICORE_min_b, - TRICORE_min_bu, - TRICORE_min_h, - TRICORE_min_hu, - TRICORE_min_u, - TRICORE_mov_u, - TRICORE_mov16, - TRICORE_mov16_a, - TRICORE_mov16_aa, - TRICORE_mov16_d, - TRICORE_mov32, - TRICORE_mov32_a, - TRICORE_mov32_aa, - TRICORE_mov32_d, - TRICORE_movh, - TRICORE_movh_a, - TRICORE_msub, - TRICORE_msub_f, - TRICORE_msub_h, - TRICORE_msub_q, - TRICORE_msub_u, - TRICORE_msubad_h, - TRICORE_msubadm_h, - TRICORE_msubadms_h, - TRICORE_msubadr_h, - TRICORE_msubadrs_h, - TRICORE_msubads_h, - TRICORE_msubm_h, - TRICORE_msubms_h, - TRICORE_msubr_h, - TRICORE_msubr_q, - TRICORE_msubrs_h, - TRICORE_msubrs_q, - TRICORE_msubs, - TRICORE_msubs_h, - TRICORE_msubs_q, - TRICORE_msubs_u, - TRICORE_mtcr, - TRICORE_mul_f, - TRICORE_mul_h, - TRICORE_mul_q, - TRICORE_mul_u, - TRICORE_mul16, - TRICORE_mul32, - TRICORE_mulm_h, - TRICORE_mulms_h, - TRICORE_mulr_h, - TRICORE_mulr_q, - TRICORE_muls, - TRICORE_muls_u, - TRICORE_nand, - TRICORE_nand_t, - TRICORE_ne, - TRICORE_ne_a, - TRICORE_nez_a, - TRICORE_nop16, - TRICORE_nop32, - TRICORE_nor_t, - TRICORE_nor16, - TRICORE_nor32, - TRICORE_or_and_t, - TRICORE_or_andn_t, - TRICORE_or_eq, - TRICORE_or_ge, - TRICORE_or_ge_u, - TRICORE_or_lt, - TRICORE_or_lt_u, - TRICORE_or_ne, - TRICORE_or_nor_t, - TRICORE_or_or_t, - TRICORE_or_t, - TRICORE_or16, - TRICORE_or32, - TRICORE_orn, - TRICORE_orn_t, - TRICORE_pack, - TRICORE_parity, - TRICORE_q31tof, - TRICORE_qseed_f, - TRICORE_ret16, - TRICORE_ret32, - TRICORE_rfe16, - TRICORE_rfe32, - TRICORE_rfm, - TRICORE_rslcx, - TRICORE_rstv, - TRICORE_rsub16, - TRICORE_rsub32, - TRICORE_rsubs, - TRICORE_rsubs_u, - TRICORE_sat16_b, - TRICORE_sat16_bu, - TRICORE_sat16_h, - TRICORE_sat16_hu, - TRICORE_sat32_b, - TRICORE_sat32_bu, - TRICORE_sat32_h, - TRICORE_sat32_hu, - TRICORE_sel, - TRICORE_seln, - TRICORE_sh_and_t, - TRICORE_sh_andn_t, - TRICORE_sh_eq, - TRICORE_sh_ge, - TRICORE_sh_ge_u, - TRICORE_sh_h, - TRICORE_sh_lt, - TRICORE_sh_lt_u, - TRICORE_sh_nand_t, - TRICORE_sh_ne, - TRICORE_sh_nor_t, - TRICORE_sh_or_t, - TRICORE_sh_orn_t, - TRICORE_sh_xnor_t, - TRICORE_sh_xor_t, - TRICORE_sh16, - TRICORE_sh32, - TRICORE_sha_h, - TRICORE_sha16, - TRICORE_sha32, - TRICORE_shas, - TRICORE_st_d, - TRICORE_st_da, - TRICORE_st_q, - TRICORE_st_t, - TRICORE_st16_a, - TRICORE_st16_b, - TRICORE_st16_h, - TRICORE_st16_w, - TRICORE_st32_a, - TRICORE_st32_b, - TRICORE_st32_h, - TRICORE_st32_w, - TRICORE_stlcx, - TRICORE_stucx, - TRICORE_sub_b, - TRICORE_sub_f, - TRICORE_sub_h, - TRICORE_sub16, - TRICORE_sub16_a, - TRICORE_sub32, - TRICORE_sub32_a, - TRICORE_subc, - TRICORE_subs_h, - TRICORE_subs_hu, - TRICORE_subs_u, - TRICORE_subs16, - TRICORE_subs32, - TRICORE_subx, - TRICORE_svlcx, - TRICORE_swap_w, - TRICORE_syscall, - TRICORE_tlbdemap, - TRICORE_tlbflush_a, - TRICORE_tlbflush_b, - TRICORE_tlbmap, - TRICORE_tlbprobe_a, - TRICORE_tlbprobe_i, - TRICORE_trapsv, - TRICORE_trapv, - TRICORE_unpack, - TRICORE_updfl, - TRICORE_utof, - TRICORE_xnor, - TRICORE_xnor_t, - TRICORE_xor_eq, - TRICORE_xor_ge, - TRICORE_xor_ge_u, - TRICORE_xor_lt, - TRICORE_xor_lt_u, - TRICORE_xor_ne, - TRICORE_xor_t, - TRICORE_xor16, - TRICORE_xor32, - - // new v1.6 instructions - TRICORE_cachei_i, - TRICORE_cachei_w, - TRICORE_cachei_wi, - TRICORE_div, - TRICORE_div_u, - TRICORE_fcall, - TRICORE_fcalla, - TRICORE_fcalli, - TRICORE_fret16, - TRICORE_fret32, - TRICORE_ftoiz, - TRICORE_ftoq31z, - TRICORE_ftouz, - TRICORE_restore, - - // new v1.6.1 instructions - TRICORE_crc32, // Calculate CRC32 - TRICORE_wait, // Suspend execution until the next enabled interrupt or asynchronous trap event - TRICORE_cmpswap_w, // Compare and swap - TRICORE_swapmsk_w, // Swap under mask - - // new v1.6.2 instructions - TRICORE_crc32_b, // CRC32 for big endian data - TRICORE_crc32l_w, // CRC32 for little endian data - TRICORE_crcn, // Arbitrary width and polynomial CRC calculation - TRICORE_shuffle, // Reorder bytes within word - TRICORE_popcnt_w, // Count number of bits set in word - TRICORE_lha, // Load high bits of address value - - TRICORE_last -}; - - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - - ARC_null = 0, // Unknown Operation - - ARC_ld, // Load - ARC_lr, // Load from auxiliary register - ARC_st, // Store - ARC_sr, // Store to auxiliary register - ARC_store_instructions = ARC_sr, - ARC_flag, // Set flags - ARC_asr, // Arithmetic shift right - ARC_lsr, // Logical shift right - ARC_sexb, // Sign extend byte - ARC_sexw, // Sign extend word - ARC_sexh = ARC_sexw, - ARC_extb, // Zero extend byte - ARC_extw, // Zero extend word - ARC_exth = ARC_extw, - ARC_ror, // Rotate right - ARC_rrc, // Rotate right through carry - ARC_b, // Branch - ARC_bl, // Branch and link - ARC_lp, // Zero-overhead loop setup - ARC_j, // Jump - ARC_jl, // Jump and link - ARC_add, // Add - ARC_adc, // Add with carry - ARC_sub, // Subtract - ARC_sbc, // Subtract with carry - ARC_and, // Logical bitwise AND - ARC_or, // Logical bitwise OR - ARC_bic, // Logical bitwise AND with invert - ARC_xor, // Logical bitwise exclusive-OR - - // pseudo instructions - ARC_mov, // Move - ARC_nop, // No operation - ARC_lsl, // Logical shift left - ARC_rlc, // Rotate left through carry - - // arc7 - ARC_brk, // Breakpoint - ARC_sleep, // Sleep until interrupt or restart - - // arc8 - ARC_swi, // Software interrupt - - // extra optional instrutions - ARC_asl, // Arithmetic shift left - ARC_mul64, // Signed 32x32 multiply - ARC_mulu64, // Unsigned 32x32 multiply - ARC_max, // Maximum of two signed integers - ARC_min, // Minimum of two signed integers - ARC_swap, // Exchange upper and lower 16 bits - ARC_norm, // Normalize (find-first-bit) - - // ARCompact instructions - ARC_bbit0, // Branch if bit cleared to 0 - ARC_bbit1, // Branch if bit set to 1 - ARC_br, // Branch on compare - ARC_pop, // Restore register value from stack - ARC_push, // Store register value on stack - - ARC_abs, // Absolute value - ARC_add1, // Add with left shift by 1 bit - ARC_add2, // Add with left shift by 2 bits - ARC_add3, // Add with left shift by 3 bits - ARC_bclr, // Clear specified bit (to 0) - ARC_bmsk, // Bit Mask - ARC_bset, // Set specified bit (to 1) - ARC_btst, // Test value of specified bit - ARC_bxor, // Bit XOR - ARC_cmp, // Compare - ARC_ex, // Atomic Exchange - ARC_mpy, // Signed 32x32 multiply (low) - ARC_mpyh, // Signed 32x32 multiply (high) - ARC_mpym = ARC_mpyh, - ARC_mpyhu, // Unsigned 32x32 multiply (high) - ARC_mpyhm = ARC_mpyhu, - ARC_mpyu, // Unsigned 32x32 multiply (low) - ARC_neg, // Negate - ARC_not, // Logical bit inversion - ARC_rcmp, // Reverse Compare - ARC_rsub, // Reverse Subtraction - ARC_rtie, // Return from Interrupt/Exception - ARC_sub1, // Subtract with left shift by 1 bit - ARC_sub2, // Subtract with left shift by 2 bits - ARC_sub3, // Subtract with left shift by 3 bits - ARC_sync, // Synchronize - ARC_trap, // Raise an exception - ARC_tst, // Test - ARC_unimp, // Unimplemented instruction - - ARC_abss, // Absolute and saturate - ARC_abssw, // Absolute and saturate of word - ARC_abssh = ARC_abssw, - ARC_adds, // Add and saturate - ARC_addsdw, // Add and saturate dual word - ARC_asls, // Arithmetic shift left and saturate - ARC_asrs, // Arithmetic shift right and saturate - ARC_divaw, // Division assist - ARC_negs, // Negate and saturate - ARC_negsw, // Negate and saturate of word - ARC_negsh = ARC_negsw, - ARC_normw, // Normalize to 16 bits - ARC_normh = ARC_normw, - ARC_rnd16, // Round to word - ARC_rndh = ARC_rnd16, - ARC_sat16, // Saturate to word - ARC_sath = ARC_sat16, - ARC_subs, // Subtract and saturate - ARC_subsdw, // Subtract and saturate dual word - - // mac d16 - ARC_muldw, - ARC_muludw, - ARC_mulrdw, - ARC_macdw, - ARC_macudw, - ARC_macrdw, - ARC_msubdw, - - // 32x16 MUL/MAC - ARC_mululw, - ARC_mullw, - ARC_mulflw, - ARC_maclw, - ARC_macflw, - ARC_machulw, - ARC_machlw, - ARC_machflw, - ARC_mulhlw, - ARC_mulhflw, - - // Major 6 compact insns - ARC_acm, - ARC_addqbs, - ARC_avgqb, - ARC_clamp, - ARC_daddh11, - ARC_daddh12, - ARC_daddh21, - ARC_daddh22, - ARC_dexcl1, - ARC_dexcl2, - ARC_dmulh11, - ARC_dmulh12, - ARC_dmulh21, - ARC_dmulh22, - ARC_dsubh11, - ARC_dsubh12, - ARC_dsubh21, - ARC_dsubh22, - ARC_drsubh11, - ARC_drsubh12, - ARC_drsubh21, - ARC_drsubh22, - ARC_fadd, - ARC_fsadd = ARC_fadd, - ARC_fmul, - ARC_fsmul = ARC_fmul, - ARC_fsub, - ARC_fssub = ARC_fsub, - ARC_fxtr, - ARC_iaddr, - ARC_mpyqb, - ARC_sfxtr, - ARC_pkqb, - ARC_upkqb, - ARC_xpkqb, - - // ARCv2 only major 4 instructions - ARC_mpyw, // Signed 16x16 multiply - ARC_mpyuw, // Unsigned 16x16 multiply - ARC_bi, // Branch indexed - ARC_bih, // Branch indexed half-word - ARC_ldi, // Load indexed - ARC_aex, // Exchange with auxiliary register - ARC_bmskn, // Bit mask negated - ARC_seteq, // Set if equal - ARC_setne, // Set if not equal - ARC_setlt, // Set if less than - ARC_setge, // Set if greater or equal - ARC_setlo, // Set if lower than - ARC_seths, // Set if higher or same - ARC_setle, // Set if less than or equal - ARC_setgt, // Set if greater than - - ARC_rol, // Rotate left - ARC_llock, // Load locked - ARC_scond, // Store conditional - - ARC_seti, // Set interrupt enable and priority level - ARC_clri, // Cler and get interrupt enable and priority level - - // ARCv2 compact prolog / epilog instructions - ARC_enter, // Function prologue sequence - ARC_leave, // Function epilogue sequence - - // ARCv2 32-bit extension major 5 DOP instructions - ARC_div, // Signed integer divsion - ARC_divu, // Unsigned integer divsion - ARC_rem, // Signed integer remainder - ARC_remu, // Unsigned integer remainder - ARC_asrsr, // Shift right rounding and saturating - ARC_valgn2h, // Two-way 16-bit vector align - ARC_setacc, // Set the accumulator - ARC_mac, // Signed 32x32 multiply accumulate - ARC_macu, // Unsigned 32x32 multiply accumulate - ARC_dmpyh, // Sum of dual signed 16x16 multiplication - ARC_dmpyhu, // Sum of dual unsigned 16x16 multiplication - ARC_dmach, // Dual signed 16x16 multiply accumulate - ARC_dmachu, // Dual unsigned 16x16 multiply accumulate - ARC_vadd2h, // Dual 16-bit addition - ARC_vadds2h, // Dual 16-bit saturating addition - ARC_vsub2h, // Dual 16-bit subtraction - ARC_vsubs2h, // Dual 16-bit saturating subtraction - ARC_vaddsub2h, // Dual 16-bit addition/subtraction - ARC_vaddsubs2h, // Dual 16-bit saturating addition/subtraction - ARC_vsubadd2h, // Dual 16-bit subtraction/addition - ARC_vsubadds2h, // Dual 16-bit saturating subtraction/addition - ARC_mpyd, // Signed 32x32 multiply (wide) - ARC_mpydu, // Unsigned 32x32 multiply (wide) - ARC_macd, // Signed 32x32 multiply accumulate (wide) - ARC_macdu, // Unsigned 32x32 multiply accumulate (wide) - ARC_vmpy2h, // Dual signed 16x16 multiply (wide) - ARC_vmpy2hf, // Dual 16x16 saturating fractional multiply - ARC_vmpy2hu, // Dual unsigned 16x16 multiply (wide) - ARC_vmpy2hfr, // Dual 16x16 saturating rounded fractional multiply - ARC_vmac2h, // Dual signed 16x16 multiply (wide) - ARC_vmac2hf, // Dual 16x16 saturating fractional multiply - ARC_vmac2hu, // Dual unsigned 16x16 multiply (wide) - ARC_vmac2hfr, // Dual 16x16 saturating rounded fractional multiply - ARC_vmpy2hwf, // Dual 16x16 saturating fractional multiply (wide) - ARC_vasl2h, // Dual 16-bit arithmetic shift left - ARC_vasls2h, // Dual 16-bit saturating arithmetic shift left - ARC_vasr2h, // Dual 16-bit arithmetic shift right - ARC_vasrs2h, // Dual 16-bit saturating arithmetic shift right - ARC_vlsr2h, // Dual 16-bit logical shift right - ARC_vasrsr2h, // Dual 16-bit saturating rounded arithmetic shift right - ARC_vadd4b, // Quad 8-bit addition - ARC_vmax2h, // Dual 16-bit maximum - ARC_vsub4b, // Quad 8-bit subtraction - ARC_vmin2h, // Dual 16-bit minimum - ARC_adcs, // Signed saturating addition with carry in - ARC_sbcs, // Signed saturating subtraction with carry in - ARC_dmpyhwf, // Fractional saturating sum of dual 16x16 signed fractional multiply - ARC_vpack2hl, // Compose lower 16-bits - ARC_vpack2hm, // Compose upper 16-bits - ARC_dmpyhf, // Saturating sum of dual 16x16 signed fractional multiply - ARC_dmpyhfr, // Saturating rounded sum of dual 16x16 signed fractional multiply - ARC_dmachf, // Saturating sum of dual 16x16 signed fractional multiply accumulate - ARC_dmachfr, // Saturating rounded sum of dual 16x16 signed fractional multiply accumulate - ARC_vperm, // Byte permutation with zero or sign extension - ARC_bspush, // Bitstream push - - // ARCv2 32-bit extension major 5 SOP instructions - ARC_swape, // Swap byte ordering - ARC_lsl16, // Logical shift left by 16 bits - ARC_lsr16, // Logical shift right by 16 bits - ARC_asr16, // Arithmetic shift right by 16 bits - ARC_asr8, // Arithmetic shift right by 8 bits - ARC_lsr8, // Logical shift right by 8 bits - ARC_lsl8, // Logical shift left by 8 bits - ARC_rol8, // Rotate left by 8 bits - ARC_ror8, // Rotate right by 8 bits - ARC_ffs, // Find first set bit - ARC_fls, // Find last set bit - - ARC_getacc, // Get accumulator - ARC_normacc, // Normalize accumulator - ARC_satf, // Saturate according to flags - ARC_vpack2hbl, // Pack lower bytes into lower 16 bits - ARC_vpack2hbm, // Pack upper bytes into upper 16 bits - ARC_vpack2hblf, // Pack upper bytes into lower 16 bits - ARC_vpack2hbmf, // Pack lower bytes into upper 16 bits - ARC_vext2bhlf, // Pack lower 2 bytes into upper byte of 16 bits each - ARC_vext2bhmf, // Pack upper 2 bytes into upper byte of 16 bits each - ARC_vrep2hl, // Repeat lower 16 bits - ARC_vrep2hm, // Repeat upper 16 bits - ARC_vext2bhl, // Pack lower 2 bytes into zero extended 16 bits - ARC_vext2bhm, // Pack upper 2 bytes into zero extended 16 bits - ARC_vsext2bhl, // Pack lower 2 bytes into sign extended 16 bits - ARC_vsext2bhm, // Pack upper 2 bytes into sign extended 16 bits - ARC_vabs2h, // Dual 16-bit absolute value - ARC_vabss2h, // Dual saturating 16-bit absolute value - ARC_vneg2h, // Dual 16-bit negation - ARC_vnegs2h, // Dual saturating 16-bit negation - ARC_vnorm2h, // Dual 16-bit normalization - ARC_bspeek, // Bitstream peek - ARC_bspop, // Bitstream pop - ARC_sqrt, // Integer square root - ARC_sqrtf, // Fractional square root - - // ARCv2 32-bit extension major 5 ZOP instructions - ARC_aslacc, // Arithmetic shift of accumulator - ARC_aslsacc, // Saturating arithmetic shift of accumulator - ARC_flagacc, // Copy accumulator flags to status32 register - ARC_modif, // Update address pointer - - // ARCv2 32-bit extension major 6 DOP instructions - ARC_cmpyhnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply - ARC_cmpyhfr, // Fractional 16+16 bit complex saturating rounded multiply - ARC_cmpychfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply - ARC_vmsub2hf, // Dual 16x16 saturating fractional multiply subtract - ARC_vmsub2hfr, // Dual 16x16 saturating rounded fractional multiply subtract - ARC_cmpychnfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply - ARC_cmachnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply accumulate - ARC_cmachfr, // Fractional 16+16 bit complex saturating rounded unshifted accumulate - ARC_cmacchnfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply accumulate - ARC_cmacchfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply accumulate - ARC_mpyf, // Signed 32-bit fractional saturating multiply - ARC_mpyfr, // Signed 32-bit fractional saturating rounded multiply - ARC_macf, // Signed 32-bit fractional saturating multiply accumulate - ARC_macfr, // Signed 32-bit fractional saturating rounded multiply accumulate - ARC_msubf, // Signed 32-bit fractional saturating multiply subtract - ARC_msubfr, // Signed 32-bit fractional saturating rounded multiply subtract - ARC_divf, // Signed 32-bit fractional division - ARC_vmac2hnfr, // Dual signed 16-bit fractional saturating rounded multiply accumulate - ARC_vmsub2hnfr, // Dual signed 16-bit fractional saturating rounded multiply subtract - ARC_mpydf, // Signed 32-bit fractional multiply (wide) - ARC_macdf, // Signed 32-bit fractional multiply accumulate (wide) - ARC_msubwhfl, // Signed 32 x 16 (lower) fractional saturating multiply subtract - ARC_msubdf, // Signed 32-bit fractional multiply subtract (wide) - ARC_dmpyhbl, // Dual 16x8 signed multiply with lower two bytes - ARC_dmpyhbm, // Dual 16x8 signed multiply with upper two bytes - ARC_dmachbl, // Dual 16x8 signed multiply accumulate with lower two bytes - ARC_dmachbm, // Dual 16x8 signed multiply accumulate with upper two bytes - ARC_msubwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply subtract - ARC_cmpyhfmr, // Fractional 16+16 bit complex x 16bit real (upper) saturating rounded multiply - ARC_cbflyhf0r, // Fractional 16+16 bit complex FFT butterfly, first half - ARC_mpywhl, // Signed 32 x 16 (lower) multiply - ARC_macwhl, // Signed 32 x 16 (lower) multiply accumulate - ARC_mpywhul, // Unsigned 32 x 16 (lower) multiply - ARC_macwhul, // Unsigned 32 x 16 (lower) multiply accumulate - ARC_mpywhfm, // Signed 32 x 16 (upper) fractional saturating multiply - ARC_mpywhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply - ARC_macwhfm, // Signed 32 x 16 (upper) fractional saturating multiply accumulate - ARC_macwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply accumulate - ARC_mpywhfl, // Signed 32 x 16 (lower) fractional saturating multiply - ARC_mpywhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply - ARC_macwhfl, // Signed 32 x 16 (lower) fractional saturating multiply accumulate - ARC_macwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply accumulate - ARC_macwhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply accumulate - ARC_macwhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply accumulate - ARC_mpywhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply - ARC_mpywhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply - ARC_msubwhfm, // Signed 32 x 16 (upper) fractional saturating multiply subtract - ARC_msubwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply subtract - - // ARCv2 32-bit extension major 6 SOP instructions - ARC_cbflyhf1r, // Fractional 16+16 bit complex FFT butterfly, second half - - // ARCv2 FPU instructions - ARC_fscmp, // Single precision floating point compare - ARC_fscmpf, // Single precision floating point compare (IEEE 754 flag generation) - ARC_fsmadd, // Single precision floating point fused multiply add - ARC_fsmsub, // Single precision floating point fused multiply subtract - ARC_fsdiv, // Single precision floating point division - ARC_fcvt32, // Single precision floating point / integer conversion - ARC_fssqrt, // Single precision floating point square root - - // ARCv2 jump / execute indexed instructions - ARC_jli, // Jump and link indexed - ARC_ei, // Execute indexed - - ARC_kflag, // Set kernel flags - ARC_wevt, // Enter sleep state - - ARC_last, -}; - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - - - -enum -{ - -TMS28_null = 0, // Unknown Operation - -TMS28_aborti, -TMS28_abs, -TMS28_abstc, -TMS28_add, -TMS28_addb, -TMS28_addcl, -TMS28_addcu, -TMS28_addl, -TMS28_addu, -TMS28_addul, -TMS28_adrk, -TMS28_and, -TMS28_andb, -TMS28_asp, -TMS28_asr, -TMS28_asr64, -TMS28_asrl, -TMS28_b, -TMS28_banz, -TMS28_bar, -TMS28_bf, -TMS28_c27map, -TMS28_c27obj, -TMS28_c28addr, -TMS28_c28map, -TMS28_c28obj, -TMS28_clrc, -TMS28_cmp, -TMS28_cmp64, -TMS28_cmpb, -TMS28_cmpl, -TMS28_cmpr, -TMS28_csb, -TMS28_dec, -TMS28_dint, -TMS28_dmac, -TMS28_dmov, -TMS28_eallow, -TMS28_edis, -TMS28_eint, -TMS28_estop0, -TMS28_estop1, -TMS28_ffc, -TMS28_flip, -TMS28_iack, -TMS28_idle, -TMS28_imacl, -TMS28_impyal, -TMS28_impyl, -TMS28_impysl, -TMS28_impyxul, -TMS28_in, -TMS28_inc, -TMS28_intr, -TMS28_iret, -TMS28_lb, -TMS28_lc, -TMS28_lcr, -TMS28_loopnz, -TMS28_loopz, -TMS28_lpaddr, -TMS28_lret, -TMS28_lrete, -TMS28_lretr, -TMS28_lsl, -TMS28_lsl64, -TMS28_lsll, -TMS28_lsr, -TMS28_lsr64, -TMS28_lsrl, -TMS28_mac, -TMS28_max, -TMS28_maxcul, -TMS28_maxl, -TMS28_min, -TMS28_mincul, -TMS28_minl, -TMS28_mov, -TMS28_mova, -TMS28_movad, -TMS28_movb, -TMS28_movdl, -TMS28_movh, -TMS28_movl, -TMS28_movp, -TMS28_movs, -TMS28_movu, -TMS28_movw, -TMS28_movx, -TMS28_movz, -TMS28_mpy, -TMS28_mpya, -TMS28_mpyb, -TMS28_mpys, -TMS28_mpyu, -TMS28_mpyxu, -TMS28_nasp, -TMS28_neg, -TMS28_neg64, -TMS28_negtc, -TMS28_nop, -TMS28_norm, -TMS28_not, -TMS28_or, -TMS28_orb, -TMS28_out, -TMS28_pop, -TMS28_pread, -TMS28_push, -TMS28_pwrite, -TMS28_qmacl, -TMS28_qmpyal, -TMS28_qmpyl, -TMS28_qmpysl, -TMS28_qmpyul, -TMS28_qmpyxul, -TMS28_rol, -TMS28_ror, -TMS28_rpt, -TMS28_sat, -TMS28_sat64, -TMS28_sb, -TMS28_sbbu, -TMS28_sbf, -TMS28_sbrk, -TMS28_setc, -TMS28_sfr, -TMS28_spm, -TMS28_sqra, -TMS28_sqrs, -TMS28_sub, -TMS28_subb, -TMS28_subbl, -TMS28_subcu, -TMS28_subcul, -TMS28_subl, -TMS28_subr, -TMS28_subrl, -TMS28_subu, -TMS28_subul, -TMS28_sxtb, -TMS28_tbit, -TMS28_tclr, -TMS28_test, -TMS28_trap, -TMS28_tset, -TMS28_uout, -TMS28_xb, -TMS28_xbanz, -TMS28_xcall, -TMS28_xmac, -TMS28_xmacd, -TMS28_xor, -TMS28_xorb, -TMS28_xpread, -TMS28_xpwrite, -TMS28_xret, -TMS28_xretc, -TMS28_zalr, -TMS28_zap, -TMS28_zapa, - -TMS28_last, - -}; - - - -enum -{ -UNSP_null = 0, // Unknown Operation - -//ALU -UNSP_add, // Add -UNSP_adc, // Add with Carry -UNSP_sub, // Subtract -UNSP_sbc, // Subtract with Carry -UNSP_cmp, // Compare -UNSP_cmpc, // Compare with Carry? -UNSP_neg, // Negate -UNSP_negc, // Negate with Carry? -UNSP_xor, // Exclusive-OR -UNSP_load, // Load -UNSP_or, // OR -UNSP_and, // AND -UNSP_test, // Test -UNSP_store, // Store - -UNSP_add_s, // Add (Simple) -UNSP_adc_s, // Add with Carry (Simple) -UNSP_sub_s, // Subtract (Simple) -UNSP_sbc_s, // Subtract with Carry (Simple) -UNSP_cmp_s, // Compare (Simple) -UNSP_cmpc_s, // Compare with Carry? (Simple) -UNSP_neg_s, // Negate (Simple) -UNSP_negc_s, // Negate with Carry? (Simple) -UNSP_xor_s, // Exclusive-OR (Simple) -UNSP_load_s, // Load (Simple) -UNSP_or_s, // OR (Simple) -UNSP_and_s, // AND (Simple) -UNSP_test_s, // Test (Simple) -UNSP_store_s, // Store (Simple) - - -//Misc -UNSP_retf, // Return Function -UNSP_reti, // Return Interrupt -UNSP_pop, // Pop from Stack -UNSP_push, // Push to Stack -UNSP_call, // Call -UNSP_goto, // Goto (far jump) -UNSP_nop, // NOP -UNSP_exp, // Effective Exponent - -//Jump -UNSP_jb, // Jump if Below (unsigned) [jcc, jnae] -UNSP_jae, // Jump if Above or Equal (unsigned) [jcs, jnb] -UNSP_jge, // Jump if Greater or Equal (signed) [jsc, jnl] -UNSP_jl, // Jump if Less (signed) [jss, jnge] -UNSP_jne, // Jump if Not Equal [jnz] -UNSP_je, // Jump if Equal [jz] -UNSP_jpl, // Jump if Positive -UNSP_jmi, // Jump if Negative -UNSP_jbe, // Jump if Below or Equal (unsigned) [jna] -UNSP_ja, // Jump if Above (unsigned) [jnbe] -UNSP_jle, // Jump if Less or Equal (signed) [jng] -UNSP_jg, // Jump if Greater (signed) [jnle] -UNSP_jvc, // Jump if Not Overflow -UNSP_jvs, // Jump if Overflow -UNSP_jmp, // Jump - -//Multiplication/Division -UNSP_mulss, // Multiply Signed * Signed -UNSP_mulus, // Multiply Unsigned * Signed -UNSP_muluu, // Multiply Unsigned * Unsigned -UNSP_divs, // Divide (Sign) -UNSP_divq, // Divide (Quotient) - -//Interrupt -UNSP_int1, // Interrupt flags -UNSP_int2, // Interrupt flags -UNSP_fir_mov, // FIR_MOV setting -UNSP_fraction, // FRACTION setting -UNSP_irq, // IRQ setting -UNSP_secbank, // SECBANK setting -UNSP_fiq, // FIQ setting -UNSP_irqnest, // IRQNEST setting -UNSP_break, // BREAK - -//Shift -UNSP_asr, // Arithmetic shift right -UNSP_asror, // Arithmetic shift right OR -UNSP_lsl, // Logical shift left -UNSP_lslor, // Logical shift left OR -UNSP_lsr, // Logical shift right -UNSP_lsror, // Logical shift right OR -UNSP_rol, // Rotate left -UNSP_ror, // Rotate right - -//Bitops -UNSP_tstb, // Test bit -UNSP_setb, // Set bit -UNSP_clrb, // Clear bit -UNSP_invb, // Invert bit - -UNSP_last, - }; - -/* - * Dalvik opcode enumeration. - */ - - -enum -{ - DALVIK_UNUSED = 0, - DALVIK_NOP, - - DALVIK_MOVE, - DALVIK_MOVE_FROM16, - DALVIK_MOVE_16, - DALVIK_MOVE_WIDE, - DALVIK_MOVE_WIDE_FROM16, - DALVIK_MOVE_WIDE_16, - DALVIK_MOVE_OBJECT, - DALVIK_MOVE_OBJECT_FROM16, - DALVIK_MOVE_OBJECT_16, - - DALVIK_MOVE_RESULT, - DALVIK_MOVE_RESULT_WIDE, - DALVIK_MOVE_RESULT_OBJECT, - DALVIK_MOVE_EXCEPTION, - - DALVIK_RETURN_VOID, - DALVIK_RETURN, - DALVIK_RETURN_WIDE, - DALVIK_RETURN_OBJECT, - - DALVIK_CONST_4, - DALVIK_CONST_16, - DALVIK_CONST, - DALVIK_CONST_HIGH16, - DALVIK_CONST_WIDE_16, - DALVIK_CONST_WIDE_32, - DALVIK_CONST_WIDE, - DALVIK_CONST_WIDE_HIGH16, - DALVIK_CONST_STRING, - DALVIK_CONST_STRING_JUMBO, - DALVIK_CONST_CLASS, - - DALVIK_MONITOR_ENTER, - DALVIK_MONITOR_EXIT, - - DALVIK_CHECK_CAST, - DALVIK_INSTANCE_OF, - - DALVIK_ARRAY_LENGTH, - - DALVIK_NEW_INSTANCE, - DALVIK_NEW_ARRAY, - - DALVIK_FILLED_NEW_ARRAY, - DALVIK_FILLED_NEW_ARRAY_RANGE, - DALVIK_FILL_ARRAY_DATA, - - DALVIK_THROW, - DALVIK_GOTO, - DALVIK_GOTO_16, - DALVIK_GOTO_32, - DALVIK_PACKED_SWITCH, - DALVIK_SPARSE_SWITCH, - - DALVIK_CMPL_FLOAT, - DALVIK_CMPG_FLOAT, - DALVIK_CMPL_DOUBLE, - DALVIK_CMPG_DOUBLE, - DALVIK_CMP_LONG, - - DALVIK_IF_EQ, - DALVIK_IF_NE, - DALVIK_IF_LT, - DALVIK_IF_GE, - DALVIK_IF_GT, - DALVIK_IF_LE, - DALVIK_IF_EQZ, - DALVIK_IF_NEZ, - DALVIK_IF_LTZ, - DALVIK_IF_GEZ, - DALVIK_IF_GTZ, - DALVIK_IF_LEZ, - - DALVIK_AGET, - DALVIK_AGET_WIDE, - DALVIK_AGET_OBJECT, - DALVIK_AGET_BOOLEAN, - DALVIK_AGET_BYTE, - DALVIK_AGET_CHAR, - DALVIK_AGET_SHORT, - DALVIK_APUT, - DALVIK_APUT_WIDE, - DALVIK_APUT_OBJECT, - DALVIK_APUT_BOOLEAN, - DALVIK_APUT_BYTE, - DALVIK_APUT_CHAR, - DALVIK_APUT_SHORT, - - DALVIK_IGET, - DALVIK_IGET_WIDE, - DALVIK_IGET_OBJECT, - DALVIK_IGET_BOOLEAN, - DALVIK_IGET_BYTE, - DALVIK_IGET_CHAR, - DALVIK_IGET_SHORT, - DALVIK_IPUT, - DALVIK_IPUT_WIDE, - DALVIK_IPUT_OBJECT, - DALVIK_IPUT_BOOLEAN, - DALVIK_IPUT_BYTE, - DALVIK_IPUT_CHAR, - DALVIK_IPUT_SHORT, - - DALVIK_SGET, - DALVIK_SGET_WIDE, - DALVIK_SGET_OBJECT, - DALVIK_SGET_BOOLEAN, - DALVIK_SGET_BYTE, - DALVIK_SGET_CHAR, - DALVIK_SGET_SHORT, - DALVIK_SPUT, - DALVIK_SPUT_WIDE, - DALVIK_SPUT_OBJECT, - DALVIK_SPUT_BOOLEAN, - DALVIK_SPUT_BYTE, - DALVIK_SPUT_CHAR, - DALVIK_SPUT_SHORT, - - DALVIK_INVOKE_VIRTUAL, - DALVIK_INVOKE_SUPER, - DALVIK_INVOKE_DIRECT, - DALVIK_INVOKE_STATIC, - DALVIK_INVOKE_INTERFACE, - - DALVIK_INVOKE_VIRTUAL_RANGE, - DALVIK_INVOKE_SUPER_RANGE, - DALVIK_INVOKE_DIRECT_RANGE, - DALVIK_INVOKE_STATIC_RANGE, - DALVIK_INVOKE_INTERFACE_RANGE, - - DALVIK_NEG_INT, - DALVIK_NOT_INT, - DALVIK_NEG_LONG, - DALVIK_NOT_LONG, - DALVIK_NEG_FLOAT, - DALVIK_NEG_DOUBLE, - DALVIK_INT_TO_LONG, - DALVIK_INT_TO_FLOAT, - DALVIK_INT_TO_DOUBLE, - DALVIK_LONG_TO_INT, - DALVIK_LONG_TO_FLOAT, - DALVIK_LONG_TO_DOUBLE, - DALVIK_FLOAT_TO_INT, - DALVIK_FLOAT_TO_LONG, - DALVIK_FLOAT_TO_DOUBLE, - DALVIK_DOUBLE_TO_INT, - DALVIK_DOUBLE_TO_LONG, - DALVIK_DOUBLE_TO_FLOAT, - DALVIK_INT_TO_BYTE, - DALVIK_INT_TO_CHAR, - DALVIK_INT_TO_SHORT, - - DALVIK_ADD_INT, - DALVIK_SUB_INT, - DALVIK_MUL_INT, - DALVIK_DIV_INT, - DALVIK_REM_INT, - DALVIK_AND_INT, - DALVIK_OR_INT, - DALVIK_XOR_INT, - DALVIK_SHL_INT, - DALVIK_SHR_INT, - DALVIK_USHR_INT, - - DALVIK_ADD_LONG, - DALVIK_SUB_LONG, - DALVIK_MUL_LONG, - DALVIK_DIV_LONG, - DALVIK_REM_LONG, - DALVIK_AND_LONG, - DALVIK_OR_LONG, - DALVIK_XOR_LONG, - DALVIK_SHL_LONG, - DALVIK_SHR_LONG, - DALVIK_USHR_LONG, - - DALVIK_ADD_FLOAT, - DALVIK_SUB_FLOAT, - DALVIK_MUL_FLOAT, - DALVIK_DIV_FLOAT, - DALVIK_REM_FLOAT, - DALVIK_ADD_DOUBLE, - DALVIK_SUB_DOUBLE, - DALVIK_MUL_DOUBLE, - DALVIK_DIV_DOUBLE, - DALVIK_REM_DOUBLE, - - DALVIK_ADD_INT_2ADDR, - DALVIK_SUB_INT_2ADDR, - DALVIK_MUL_INT_2ADDR, - DALVIK_DIV_INT_2ADDR, - DALVIK_REM_INT_2ADDR, - DALVIK_AND_INT_2ADDR, - DALVIK_OR_INT_2ADDR, - DALVIK_XOR_INT_2ADDR, - DALVIK_SHL_INT_2ADDR, - DALVIK_SHR_INT_2ADDR, - DALVIK_USHR_INT_2ADDR, - - DALVIK_ADD_LONG_2ADDR, - DALVIK_SUB_LONG_2ADDR, - DALVIK_MUL_LONG_2ADDR, - DALVIK_DIV_LONG_2ADDR, - DALVIK_REM_LONG_2ADDR, - DALVIK_AND_LONG_2ADDR, - DALVIK_OR_LONG_2ADDR, - DALVIK_XOR_LONG_2ADDR, - DALVIK_SHL_LONG_2ADDR, - DALVIK_SHR_LONG_2ADDR, - DALVIK_USHR_LONG_2ADDR, - - DALVIK_ADD_FLOAT_2ADDR, - DALVIK_SUB_FLOAT_2ADDR, - DALVIK_MUL_FLOAT_2ADDR, - DALVIK_DIV_FLOAT_2ADDR, - DALVIK_REM_FLOAT_2ADDR, - DALVIK_ADD_DOUBLE_2ADDR, - DALVIK_SUB_DOUBLE_2ADDR, - DALVIK_MUL_DOUBLE_2ADDR, - DALVIK_DIV_DOUBLE_2ADDR, - DALVIK_REM_DOUBLE_2ADDR, - - DALVIK_ADD_INT_LIT16, - DALVIK_RSUB_INT, // no _LIT16 suffix for this - DALVIK_MUL_INT_LIT16, - DALVIK_DIV_INT_LIT16, - DALVIK_REM_INT_LIT16, - DALVIK_AND_INT_LIT16, - DALVIK_OR_INT_LIT16, - DALVIK_XOR_INT_LIT16, - - DALVIK_ADD_INT_LIT8, - DALVIK_RSUB_INT_LIT8, - DALVIK_MUL_INT_LIT8, - DALVIK_DIV_INT_LIT8, - DALVIK_REM_INT_LIT8, - DALVIK_AND_INT_LIT8, - DALVIK_OR_INT_LIT8, - DALVIK_XOR_INT_LIT8, - DALVIK_SHL_INT_LIT8, - DALVIK_SHR_INT_LIT8, - DALVIK_USHR_INT_LIT8, - - DALVIK_IGET_VOLATILE, - DALVIK_IPUT_VOLATILE, - DALVIK_SGET_VOLATILE, - DALVIK_SPUT_VOLATILE, - DALVIK_IGET_OBJECT_VOLATILE, - - DALVIK_IGET_WIDE_VOLATILE, - DALVIK_IPUT_WIDE_VOLATILE, - DALVIK_SGET_WIDE_VOLATILE, - DALVIK_SPUT_WIDE_VOLATILE, - - // The "breakpoint" instruction is special, in that it should never - // be seen by anything but the debug interpreter. During debugging - // it takes the place of an arbitrary opcode, which means operations - // like "tell me the opcode width so I can find the next instruction" - // aren't possible. (This is correctable, but probably not useful.) - DALVIK_BREAKPOINT, - - DALVIK_THROW_VERIFICATION_ERROR, - - DALVIK_EXECUTE_INLINE, - DALVIK_EXECUTE_INLINE_RANGE, - - DALVIK_INVOKE_DIRECT_EMPTY, - DALVIK_RETURN_VOID_BARRIER, - DALVIK_IGET_QUICK, - DALVIK_IGET_WIDE_QUICK, - DALVIK_IGET_OBJECT_QUICK, - DALVIK_IPUT_QUICK, - DALVIK_IPUT_WIDE_QUICK, - DALVIK_IPUT_OBJECT_QUICK, - - DALVIK_INVOKE_VIRTUAL_QUICK, - DALVIK_INVOKE_VIRTUAL_QUICK_RANGE, - DALVIK_INVOKE_SUPER_QUICK, - DALVIK_INVOKE_SUPER_QUICK_RANGE, - DALVIK_IPUT_OBJECT_VOLATILE, - DALVIK_SGET_OBJECT_VOLATILE, - DALVIK_SPUT_OBJECT_VOLATILE, - - // dex-file format 038 - DALVIK_INVOKE_POLYMORPHIC, - DALVIK_INVOKE_POLYMORPHIC_RANGE, - DALVIK_INVOKE_CUSTOM, - DALVIK_INVOKE_CUSTOM_RANGE, - - DALVIK_LAST, -}; - -/* this file was entirely generated by gen_opc.py */ -enum -{ - s39_null = 0, - s39_a,//add (32) - s39_ad,//add normalized (long HFP) - s39_adb,//add (long BFP) - s39_adbr,//add (long BFP) - s39_adr,//add normalized (long HFP) - s39_adtr,//add (long DFP) - s39_adtra,//add (long DFP) - s39_ae,//add normalized (short HFP) - s39_aeb,//add (short BFP) - s39_aebr,//add (short BFP) - s39_aer,//add normalized (short HFP) - s39_afi,//add immediate (32) - s39_ag,//add (64) - s39_agf,//add (64 <- 32) - s39_agfi,//add immediate (64 <- 32) - s39_agfr,//add (64 <- 32) - s39_agh,//add halfword (64 <- 16) - s39_aghi,//add halfword immediate (64 <- 16) - s39_aghik,//add immediate (64 <- 16) - s39_agr,//add (64) - s39_agrk,//add (64) - s39_agsi,//add immediate (64 <- 8) - s39_ah,//add halfword (32 <- 16) - s39_ahhhr,//add high (32) - s39_ahhlr,//add high (32) - s39_ahi,//add halfword immediate (32 <- 16) - s39_ahik,//add immediate (32 <- 16) - s39_ahy,//add halfword (32 <- 16) - s39_aih,//add immediate high (32) - s39_al,//add logical (32) - s39_alc,//add logical with carry (32) - s39_alcg,//add logical with carry (64) - s39_alcgr,//add logical with carry (64) - s39_alcr,//add logical with carry (32) - s39_alfi,//add logical immediate (32) - s39_alg,//add logical (64) - s39_algf,//add logical (64 <- 32) - s39_algfi,//add logical immediate (64 <- 32) - s39_algfr,//add logical (64 <- 32) - s39_alghsik,//add logical with signed immediate (64 <- 16) - s39_algr,//add logical (64) - s39_algrk,//add logical (64) - s39_algsi,//add logical with signed immediate (64 <- 8) - s39_alhhhr,//add logical high (32) - s39_alhhlr,//add logical high (32) - s39_alhsik,//add logical with signed immediate (32 <- 16) - s39_alr,//add logical (32) - s39_alrk,//add logical (32) - s39_alsi,//add logical with signed immediate (32 <- 8) - s39_alsih,//add logical with signed immediate high (32) - s39_alsihn,//add logical with signed immediate high (32) - s39_aly,//add logical (32) - s39_ap,//add decimal - s39_ar,//add (32) - s39_ark,//add (32) - s39_asi,//add immediate (32 <- 8) - s39_au,//add unnormalized (short HFP) - s39_aur,//add unnormalized (short HFP) - s39_aw,//add unnormalized (long HFP) - s39_awr,//add unnormalized (long HFP) - s39_axbr,//add (extended BFP) - s39_axr,//add normalized (extended HFP) - s39_axtr,//add (extended DFP) - s39_axtra,//add (extended DFP) - s39_ay,//add (32) - s39_b,//unconditional branch - s39_bo,//branch on condition, jump on overflow / if ones - s39_bh,//branch on condition, jump on A high - s39_bnle,//branch on condition, jump on not low or equal - s39_bl,//branch on condition, jump on A low - s39_bnhe,//branch on condition, jump on not high or equal - s39_blh,//branch on condition, jump on low or high - s39_bne,//branch on condition, jump on A not equal B - s39_be,//branch on condition, jump on A equal B - s39_bnlh,//branch on condition, jump on not low or high - s39_bhe,//branch on condition, jump on high or equal - s39_bnl,//branch on condition, jump on A not low - s39_ble,//branch on condition, jump on low or equal - s39_bnh,//branch on condition, jump on A not high - s39_bno,//branch on condition, jump on not overflow / if not ones - s39_bor,//branch on condition, jump on overflow / if ones - s39_bhr,//branch on condition, jump on A high - s39_bnler,//branch on condition, jump on not low or equal - s39_blr,//branch on condition, jump on A low - s39_bnher,//branch on condition, jump on not high or equal - s39_blhr,//branch on condition, jump on low or high - s39_bner,//branch on condition, jump on A not equal B - s39_ber,//branch on condition, jump on A equal B - s39_bnlhr,//branch on condition, jump on not low or high - s39_bher,//branch on condition, jump on high or equal - s39_bnlr,//branch on condition, jump on A not low - s39_bler,//branch on condition, jump on low or equal - s39_bnhr,//branch on condition, jump on A not high - s39_bnor,//branch on condition, jump on not overflow / if not ones - s39_bakr,//branch and stack - s39_bal,//branch and link - s39_balr,//branch and link - s39_bas,//branch and save - s39_basr,//branch and save - s39_bassm,//branch and save and set mode - s39_bc,//branch on condition - s39_bcr,//branch on condition - s39_bct,//branch on count (32) - s39_bctg,//branch on count (64) - s39_bctgr,//branch on count (64) - s39_bctr,//branch on count (32) - s39_bi,//unconditional indirect branch - s39_bio,//branch indirect on condition, jump on overflow / if ones - s39_bih,//branch indirect on condition, jump on A high - s39_binle,//branch indirect on condition, jump on not low or equal - s39_bil,//branch indirect on condition, jump on A low - s39_binhe,//branch indirect on condition, jump on not high or equal - s39_bilh,//branch indirect on condition, jump on low or high - s39_bine,//branch indirect on condition, jump on A not equal B - s39_bie,//branch indirect on condition, jump on A equal B - s39_binlh,//branch indirect on condition, jump on not low or high - s39_bihe,//branch indirect on condition, jump on high or equal - s39_binl,//branch indirect on condition, jump on A not low - s39_bile,//branch indirect on condition, jump on low or equal - s39_binh,//branch indirect on condition, jump on A not high - s39_bino,//branch indirect on condition, jump on not overflow / if not ones - s39_bic,//branch indirect on condition - s39_bpp,//branch prediction preload - s39_bprp,//branch prediction relative preload - s39_br,//unconditional branch - s39_bras,//branch relative and save - s39_brasl,//branch relative and save long - s39_brc,//branch relative on condition - s39_brcl,//branch relative on condition long - s39_brct,//branch relative on count (32) - s39_brctg,//branch relative on count (64) - s39_brcth,//branch relative on count high (32) - s39_brxh,//branch relative on index high (32) - s39_brxhg,//branch relative on index high (64) - s39_brxle,//branch relative on index low or equal (32) - s39_brxlg,//branch relative on index low or equal (64) - s39_bsa,//branch and set authority - s39_bsg,//branch in subspace group - s39_bsm,//branch and set mode - s39_bxh,//branch on index high (32) - s39_bxhg,//branch on index high (64) - s39_bxle,//branch on index low or equal (32) - s39_bxleg,//branch on index low or equal (64) - s39_c,//compare (32) - s39_cd,//compare (long HFP) - s39_cdb,//compare (long BFP) - s39_cdbr,//compare (long BFP) - s39_cdfbr,//convert from fixed (32 to long BFP) - s39_cdfbra,//convert from fixed (32 to long BFP) - s39_cdfr,//convert from fixed (32 to long HFP) - s39_cdftr,//convert from fixed (32 to long DFP) - s39_cdgbr,//convert from fixed (64 to long BFP) - s39_cdgbra,//convert from fixed (64 to long BFP) - s39_cdgr,//convert from fixed (64 to long HFP) - s39_cdgtr,//convert from fixed (64 to long DFP) - s39_cdgtra,//convert from fixed (64 to long DFP) - s39_cdlfbr,//convert from logical (32 to long BFP) - s39_cdlftr,//convert from logical (32 to long DFP) - s39_cdlgbr,//convert from logical (64 to long BFP) - s39_cdlgtr,//convert from logical (64 to long DFP) - s39_cdpt,//convert from packed (to long DFP) - s39_cdr,//compare (long HFP) - s39_cds,//compare double and swap (32) - s39_cdsg,//compare double and swap (64) - s39_cdstr,//convert from signed packed (64 to long DFP) - s39_cdsy,//compare double and swap (32) - s39_cdtr,//compare (long DFP) - s39_cdutr,//convert from unsigned packed (64 to long DFP) - s39_cdzt,//convert from zoned (to long DFP) - s39_ce,//compare (short HFP) - s39_ceb,//compare (short BFP) - s39_cebr,//compare (short BFP) - s39_cedtr,//compare biased exponent (long DFP) - s39_cefbr,//convert from fixed (32 to short BFP) - s39_cefbra,//convert from fixed (32 to short BFP) - s39_cefr,//convert from fixed (32 to short HFP) - s39_cegbr,//convert from fixed (64 to short BFP) - s39_cegbra,//convert from fixed (64 to short BFP) - s39_cegr,//convert from fixed (64 to short HFP) - s39_celfbr,//convert from logical (32 to short BFP) - s39_celgbr,//convert from logical (64 to short BFP) - s39_cer,//compare (short HFP) - s39_cextr,//compare biased exponent (extended DFP) - s39_cfc,//compare and form codeword - s39_cfdbr,//convert to fixed (long BFP to 32) - s39_cfdbra,//convert to fixed (long BFP to 32) - s39_cfdr,//convert to fixed (long HFP to 32) - s39_cfdtr,//convert to fixed (long DFP to 32) - s39_cfebr,//convert to fixed (short BFP to 32) - s39_cfebra,//convert to fixed (short BFP to 32) - s39_cfer,//convert to fixed (short HFP to 32) - s39_cfi,//compare immediate (32) - s39_cfxbr,//convert to fixed (extended BFP to 32) - s39_cfxbra,//convert to fixed (extended BFP to 32) - s39_cfxr,//convert to fixed (extended HFP to 32) - s39_cfxtr,//convert to fixed (extended DFP to 32) - s39_cg,//compare (64) - s39_cgdbr,//convert to fixed (long BFP to 64) - s39_cgdbra,//convert to fixed (long BFP to 64) - s39_cgdr,//convert to fixed (long HFP to 64) - s39_cgdtr,//convert to fixed (long DFP to 64) - s39_cgdtra,//convert to fixed (long DFP to 64) - s39_cgebr,//convert to fixed (short BFP to 64) - s39_cgebra,//convert to fixed (short BFP to 64) - s39_cger,//convert to fixed (short HFP to 64) - s39_cgf,//compare (64 <- 32) - s39_cgfi,//compare immediate (64 <- 32) - s39_cgfr,//compare (64 <- 32) - s39_cgfrl,//compare relative long (64 <- 32) - s39_cgh,//compare halfword (64 <- 16) - s39_cghi,//compare halfword immediate (64 <- 16) - s39_cghrl,//compare halfword relative long (64 <- 16) - s39_cghsi,//compare halfword immediate (64 <- 16) - s39_cgib,//compare immediate and branch (64 <- 8) - s39_cgibh,//compare immediate and branch (64 <- 8), jump on A high - s39_cgibnhe,//compare immediate and branch (64 <- 8), jump on not high or equal - s39_cgiblh,//compare immediate and branch (64 <- 8), jump on low or high - s39_cgibnlh,//compare immediate and branch (64 <- 8), jump on not low or high - s39_cgibnl,//compare immediate and branch (64 <- 8), jump on A not low - s39_cgible,//compare immediate and branch (64 <- 8), jump on low or equal - s39_cgij,//compare immediate and branch relative (64 <- 8) - s39_cgijh,//compare immediate and branch relative (64 <- 8), jump on A high - s39_cgijnhe,//compare immediate and branch relative (64 <- 8), jump on not high or equal - s39_cgijlh,//compare immediate and branch relative (64 <- 8), jump on low or high - s39_cgijnlh,//compare immediate and branch relative (64 <- 8), jump on not low or high - s39_cgijnl,//compare immediate and branch relative (64 <- 8), jump on A not low - s39_cgijle,//compare immediate and branch relative (64 <- 8), jump on low or equal - s39_cgit,//compare immediate and trap (64 <- 16) - s39_cgith,//compare immediate and trap (64 <- 16), jump on A high - s39_cgitnhe,//compare immediate and trap (64 <- 16), jump on not high or equal - s39_cgitlh,//compare immediate and trap (64 <- 16), jump on low or high - s39_cgitnlh,//compare immediate and trap (64 <- 16), jump on not low or high - s39_cgitnl,//compare immediate and trap (64 <- 16), jump on A not low - s39_cgitle,//compare immediate and trap (64 <- 16), jump on low or equal - s39_cgr,//compare (64) - s39_cgrb,//compare and branch (64) - s39_cgrbh,//compare and branch (64), jump on A high - s39_cgrbnhe,//compare and branch (64), jump on not high or equal - s39_cgrblh,//compare and branch (64), jump on low or high - s39_cgrbnlh,//compare and branch (64), jump on not low or high - s39_cgrbnl,//compare and branch (64), jump on A not low - s39_cgrble,//compare and branch (64), jump on low or equal - s39_cgrj,//compare and branch relative (64) - s39_cgrjh,//compare and branch relative (64), jump on A high - s39_cgrjnhe,//compare and branch relative (64), jump on not high or equal - s39_cgrjlh,//compare and branch relative (64), jump on low or high - s39_cgrjnlh,//compare and branch relative (64), jump on not low or high - s39_cgrjnl,//compare and branch relative (64), jump on A not low - s39_cgrjle,//compare and branch relative (64), jump on low or equal - s39_cgrl,//compare relative long (64) - s39_cgrt,//compare and trap (64) - s39_cgrth,//compare and trap (64), jump on A high - s39_cgrtnhe,//compare and trap (64), jump on not high or equal - s39_cgrtlh,//compare and trap (64), jump on low or high - s39_cgrtnlh,//compare and trap (64), jump on not low or high - s39_cgrtnl,//compare and trap (64), jump on A not low - s39_cgrtle,//compare and trap (64), jump on low or equal - s39_cgxbr,//convert to fixed (extended BFP to 64) - s39_cgxbra,//convert to fixed (extended BFP to 64) - s39_cgxr,//convert to fixed (extended HFP to 64) - s39_cgxtr,//convert to fixed (extended DFP to 64) - s39_cgxtra,//convert to fixed (extended DFP to 64) - s39_ch,//compare halfword (32 <- 16) - s39_chf,//compare high (32) - s39_chhr,//compare high (32) - s39_chhsi,//compare halfword immediate (16 <- 16) - s39_chi,//compare halfword immediate (32 <- 16) - s39_chlr,//compare high (32) - s39_chrl,//compare halfword relative long (32 <- 16) - s39_chsi,//compare halfword immediate (32 <- 16) - s39_chy,//compare halfword (32 <- 16) - s39_cib,//comapre immediate and branch (32 <- 8) - s39_cibh,//comapre immediate and branch (32 <- 8), jump on A high - s39_cibnhe,//comapre immediate and branch (32 <- 8), jump on not high or equal - s39_ciblh,//comapre immediate and branch (32 <- 8), jump on low or high - s39_cibnlh,//comapre immediate and branch (32 <- 8), jump on not low or high - s39_cibnl,//comapre immediate and branch (32 <- 8), jump on A not low - s39_cible,//comapre immediate and branch (32 <- 8), jump on low or equal - s39_cih,//compare immediate high (32) - s39_cij,//compare immediate and branch relative (32 <- 8) - s39_cijh,//compare immediate and branch relative (32 <- 8), jump on A high - s39_cijnhe,//compare immediate and branch relative (32 <- 8), jump on not high or equal - s39_cijlh,//compare immediate and branch relative (32 <- 8), jump on low or high - s39_cijnlh,//compare immediate and branch relative (32 <- 8), jump on not low or high - s39_cijnl,//compare immediate and branch relative (32 <- 8), jump on A not low - s39_cijle,//compare immediate and branch relative (32 <- 8), jump on low or equal - s39_cit,//compare immediate and trap (32 <- 16) - s39_cith,//compare immediate and trap (32 <- 16), jump on A high - s39_citnhe,//compare immediate and trap (32 <- 16), jump on not high or equal - s39_citlh,//compare immediate and trap (32 <- 16), jump on low or high - s39_citnlh,//compare immediate and trap (32 <- 16), jump on not low or high - s39_citnl,//compare immediate and trap (32 <- 16), jump on A not low - s39_citle,//compare immediate and trap (32 <- 16), jump on low or equal - s39_cksm,//checksum - s39_cl,//compare logical (32) - s39_clc,//compare logical (character) - s39_clcl,//compare logical long - s39_clcle,//compare logical long extended - s39_clclu,//compare logical long unicode - s39_clfdbr,//convert to logical (long BFP to 32) - s39_clfdtr,//convert to logical (long DFP to 32) - s39_clfebr,//convert to logical (short BFP to 32) - s39_clfhsi,//compare logical immediate (32 <- 16) - s39_clfi,//compare logical immediate (32) - s39_clfit,//compare logical immediate and trap (32 <- 16) - s39_clfith,//compare logical immediate and trap (32 <- 16), jump on A high - s39_clfitnhe,//compare logical immediate and trap (32 <- 16), jump on not high or equal - s39_clfitlh,//compare logical immediate and trap (32 <- 16), jump on low or high - s39_clfitnlh,//compare logical immediate and trap (32 <- 16), jump on not low or high - s39_clfitnl,//compare logical immediate and trap (32 <- 16), jump on A not low - s39_clfitle,//compare logical immediate and trap (32 <- 16), jump on low or equal - s39_clfxbr,//convert to logical (extended BFP to 32) - s39_clfxtr,//convert to logical (extended DFP to 32) - s39_clg,//compare logical (64) - s39_clgdbr,//convert to logical (long BFP to 64) - s39_clgdtr,//convert to logical (long DFP to 64) - s39_clgebr,//convert to logical (short BFP to 64) - s39_clgf,//compare logical (64 <- 32) - s39_clgfi,//compare logical immediate (64 <- 32) - s39_clgfr,//compare logical (64 <- 32) - s39_clgfrl,//compare logical relative long (64 <- 32) - s39_clghrl,//compare logical relative long (64 <- 16) - s39_clghsi,//compare logical relative long (64 <- 16) - s39_clgib,//compare logical immediate and branch (64 <- 8) - s39_clgibh,//compare logical immediate and branch (64 <- 8), jump on A high - s39_clgibnhe,//compare logical immediate and branch (64 <- 8), jump on not high or equal - s39_clgiblh,//compare logical immediate and branch (64 <- 8), jump on low or high - s39_clgibnlh,//compare logical immediate and branch (64 <- 8), jump on not low or high - s39_clgibnl,//compare logical immediate and branch (64 <- 8), jump on A not low - s39_clgible,//compare logical immediate and branch (64 <- 8), jump on low or equal - s39_clgij,//compare logical immediate and branch relative (64 <- 8) - s39_clgijh,//compare logical immediate and branch relative (64 <- 8), jump on A high - s39_clgijnhe,//compare logical immediate and branch relative (64 <- 8), jump on not high or equal - s39_clgijlh,//compare logical immediate and branch relative (64 <- 8), jump on low or high - s39_clgijnlh,//compare logical immediate and branch relative (64 <- 8), jump on not low or high - s39_clgijnl,//compare logical immediate and branch relative (64 <- 8), jump on A not low - s39_clgijle,//compare logical immediate and branch relative (64 <- 8), jump on low or equal - s39_clgit,//compare logical immedate and trap (64 <- 16) - s39_clgith,//compare logical immedate and trap (64 <- 16), jump on A high - s39_clgitnhe,//compare logical immedate and trap (64 <- 16), jump on not high or equal - s39_clgitlh,//compare logical immedate and trap (64 <- 16), jump on low or high - s39_clgitnlh,//compare logical immedate and trap (64 <- 16), jump on not low or high - s39_clgitnl,//compare logical immedate and trap (64 <- 16), jump on A not low - s39_clgitle,//compare logical immedate and trap (64 <- 16), jump on low or equal - s39_clgr,//compare logical (64) - s39_clgrb,//compare logical and branch (64) - s39_clgrbh,//compare logical and branch (64), jump on A high - s39_clgrbnhe,//compare logical and branch (64), jump on not high or equal - s39_clgrblh,//compare logical and branch (64), jump on low or high - s39_clgrbnlh,//compare logical and branch (64), jump on not low or high - s39_clgrbnl,//compare logical and branch (64), jump on A not low - s39_clgrble,//compare logical and branch (64), jump on low or equal - s39_clgrj,//compare logical and branch relative (64) - s39_clgrjh,//compare logical and branch relative (64), jump on A high - s39_clgrjnhe,//compare logical and branch relative (64), jump on not high or equal - s39_clgrjlh,//compare logical and branch relative (64), jump on low or high - s39_clgrjnlh,//compare logical and branch relative (64), jump on not low or high - s39_clgrjnl,//compare logical and branch relative (64), jump on A not low - s39_clgrjle,//compare logical and branch relative (64), jump on low or equal - s39_clgrl,//compare logical relative long (64) - s39_clgrt,//compare logical and trap (64) - s39_clgrth,//compare logical and trap (64), jump on A high - s39_clgrtnhe,//compare logical and trap (64), jump on not high or equal - s39_clgrtlh,//compare logical and trap (64), jump on low or high - s39_clgrtnlh,//compare logical and trap (64), jump on not low or high - s39_clgrtnl,//compare logical and trap (64), jump on A not low - s39_clgrtle,//compare logical and trap (64), jump on low or equal - s39_clgt,//compare logical and trap (64) - s39_clgth,//compare logical and trap (64), jump on A high - s39_clgtnhe,//compare logical and trap (64), jump on not high or equal - s39_clgtlh,//compare logical and trap (64), jump on low or high - s39_clgtnlh,//compare logical and trap (64), jump on not low or high - s39_clgtnl,//compare logical and trap (64), jump on A not low - s39_clgtle,//compare logical and trap (64), jump on low or equal - s39_clgxbr,//convert to logical (extended BFP to 64) - s39_clgxtr,//convert to logical (extended DFP to 64) - s39_clhf,//compare logical high (32) - s39_clhhr,//compare logical high (32) - s39_clhhsi,//compare logical immediate (16 <- 16) - s39_clhlr,//compare logical high (32) - s39_clhrl,//compare logical relative long (32 <- 16) - s39_cli,//compare logical (immediate) - s39_clib,//compare logical immediate and branch (32 <- 8) - s39_clibh,//compare logical immediate and branch (32 <- 8), jump on A high - s39_clibnhe,//compare logical immediate and branch (32 <- 8), jump on not high or equal - s39_cliblh,//compare logical immediate and branch (32 <- 8), jump on low or high - s39_clibnlh,//compare logical immediate and branch (32 <- 8), jump on not low or high - s39_clibnl,//compare logical immediate and branch (32 <- 8), jump on A not low - s39_clible,//compare logical immediate and branch (32 <- 8), jump on low or equal - s39_clih,//compare logical immediate high (32) - s39_clij,//compare logical immediate and branch relative (32 <- 8) - s39_clijh,//compare logical immediate and branch relative (32 <- 8), jump on A high - s39_clijnhe,//compare logical immediate and branch relative (32 <- 8), jump on not high or equal - s39_clijlh,//compare logical immediate and branch relative (32 <- 8), jump on low or high - s39_clijnlh,//compare logical immediate and branch relative (32 <- 8), jump on not low or high - s39_clijnl,//compare logical immediate and branch relative (32 <- 8), jump on A not low - s39_clijle,//compare logical immediate and branch relative (32 <- 8), jump on low or equal - s39_cliy,//compare logical (immediate) - s39_clm,//compare logical character under mask (low) - s39_clmh,//compare logical character under mask (high) - s39_clmy,//compare logical (32) - s39_clr,//compare logical (32) - s39_clrb,//compare logical and branch (32) - s39_clrbh,//compare logical and branch (32), jump on A high - s39_clrbnhe,//compare logical and branch (32), jump on not high or equal - s39_clrblh,//compare logical and branch (32), jump on low or high - s39_clrbnlh,//compare logical and branch (32), jump on not low or high - s39_clrbnl,//compare logical and branch (32), jump on A not low - s39_clrble,//compare logical and branch (32), jump on low or equal - s39_clrj,//compare logical and branch relative (32) - s39_clrjh,//compare logical and branch relative (32), jump on A high - s39_clrjnhe,//compare logical and branch relative (32), jump on not high or equal - s39_clrjlh,//compare logical and branch relative (32), jump on low or high - s39_clrjnlh,//compare logical and branch relative (32), jump on not low or high - s39_clrjnl,//compare logical and branch relative (32), jump on A not low - s39_clrjle,//compare logical and branch relative (32), jump on low or equal - s39_clrl,//compare logical relative long (32) - s39_clrt,//compare logical and trap (32) - s39_clrth,//compare logical and trap (32), jump on A high - s39_clrtnhe,//compare logical and trap (32), jump on not high or equal - s39_clrtlh,//compare logical and trap (32), jump on low or high - s39_clrtnlh,//compare logical and trap (32), jump on not low or high - s39_clrtnl,//compare logical and trap (32), jump on A not low - s39_clrtle,//compare logical and trap (32), jump on low or equal - s39_clst,//compare logical string - s39_clt,//compare logical and trap (32) - s39_clth,//compare logical and trap (32), jump on A high - s39_cltnhe,//compare logical and trap (32), jump on not high or equal - s39_cltlh,//compare logical and trap (32), jump on low or high - s39_cltnlh,//compare logical and trap (32), jump on not low or high - s39_cltnl,//compare logical and trap (32), jump on A not low - s39_cltle,//compare logical and trap (32), jump on low or equal - s39_cly,//compare logical (32) - s39_cmpsc,//compression call - s39_cp,//compare decimal - s39_cpdt,//convert to packed (from long DFP) - s39_cpsdr,//copy sign (long) - s39_cpxt,//convert to packed (from extended DFP) - s39_cpya,//copy access - s39_cr,//compare (32) - s39_crb,//compare and branch (32) - s39_crbh,//compare and branch (32), jump on A high - s39_crbnhe,//compare and branch (32), jump on not high or equal - s39_crblh,//compare and branch (32), jump on low or high - s39_crbnlh,//compare and branch (32), jump on not low or high - s39_crbnl,//compare and branch (32), jump on A not low - s39_crble,//compare and branch (32), jump on low or equal - s39_crdte,//compare and replace DAT table entry - s39_crj,//compare and branch relative (32) - s39_crjh,//compare and branch relative (32), jump on A high - s39_crjnhe,//compare and branch relative (32), jump on not high or equal - s39_crjlh,//compare and branch relative (32), jump on low or high - s39_crjnlh,//compare and branch relative (32), jump on not low or high - s39_crjnl,//compare and branch relative (32), jump on A not low - s39_crjle,//compare and branch relative (32), jump on low or equal - s39_crl,//compare relative long (32) - s39_crt,//compare and trap (32) - s39_crth,//compare and trap (32), jump on A high - s39_crtnhe,//compare and trap (32), jump on not high or equal - s39_crtlh,//compare and trap (32), jump on low or high - s39_crtnlh,//compare and trap (32), jump on not low or high - s39_crtnl,//compare and trap (32), jump on A not low - s39_crtle,//compare and trap (32), jump on low or equal - s39_cs,//compare and swap (32) - s39_csch,//clear subchannel - s39_csdtr,//convert to signed packed (long DFP to 64) - s39_csg,//compare and swap (64) - s39_csp,//compare and swap and purge (32) - s39_cspg,//compare and swap and purge (64) - s39_csst,//compare and swap and store - s39_csxtr,//convert to signed packed (extended DFP to 128) - s39_csy,//compare and swap (32) - s39_cu12,//convert utf-8 to utf-16 - s39_cu14,//convert utf-8 to utf-32 - s39_cu21,//convert utf-16 to utf-8 - s39_cu24,//convert utf-16 to utf-32 - s39_cu41,//convert utf-32 to utf-8 - s39_cu42,//convert utf-32 to utf-16 - s39_cudtr,//convert to unsigned packed (long DFP to 64) - s39_cuse,//compare until substring equal - s39_cutfu,//convert utf-8 to unicode - s39_cuutf,//convert unicode to utf-8 - s39_cuxtr,//convert to unsigned packed (extended DFP to 128) - s39_cvb,//convert to binary (32) - s39_cvbg,//convert to binary (64) - s39_cvby,//convert to binary (32) - s39_cvd,//convert to decimal (32) - s39_cvdg,//convert to decimal (64) - s39_cvdy,//convert to decimal (32) - s39_cxbr,//compare (extended BFP) - s39_cxfbr,//convert from fixed (32 to extended BFP) - s39_cxfbra,//convert from fixed (32 to extended BFP) - s39_cxfr,//convert from fixed (32 to extended HFP) - s39_cxftr,//convert from fixed (32 to extended DFP) - s39_cxgbr,//convert from fixed (64 to extended BFP) - s39_cxgbra,//convert from fixed (64 to extended BFP) - s39_cxgr,//convert from fixed (64 to extended HFP) - s39_cxgtr,//convert from fixed (64 to extended DFP) - s39_cxgtra,//convert from fixed (64 to extended DFP) - s39_cxlfbr,//convert from logical (32 to extended BFP) - s39_cxlftr,//convert from logical (32 to extended DFP) - s39_cxlgbr,//convert from logical (64 to extended BFP) - s39_cxlgtr,//convert from logical (64 to extended DFP) - s39_cxpt,//convert from packed (to extended DFP) - s39_cxr,//compare (extended HFP) - s39_cxstr,//convert from singed packed (128 to extended DFP) - s39_cxtr,//compare (extended DFP) - s39_cxutr,//convert from unsigned packed (128 to extended DFP) - s39_cxzt,//convert from zoned (to extended DFP) - s39_cy,//compare (32) - s39_czdt,//convert to zoned (from long DFP) - s39_czxt,//convert to zoned (from extended DFP) - s39_d,//divide (32 <- 64) - s39_dd,//divide (long HFP) - s39_ddb,//divide (long BFP) - s39_ddbr,//divide (long BFP) - s39_ddr,//divide (long HFP) - s39_ddtr,//divide (long DFP) - s39_ddtra,//divide (long DFP) - s39_de,//divide (short HFP) - s39_deb,//divide (short BFP) - s39_debr,//divide (short BFP) - s39_der,//divide (short HFP) - s39_dfltcc,// - s39_diag,//diagnose - s39_didbr,//divide to integer (long BFP) - s39_diebr,//divide to integer (short BFP) - s39_dl,//divide logical (32 <- 64) - s39_dlg,//divide logical (64 <- 128) - s39_dlgr,//divide logical (64 <- 128) - s39_dlr,//divide logical (32 <- 64) - s39_dp,//divide decimal - s39_dr,//divide (32 <- 64) - s39_dsg,//divide single (64) - s39_dsgf,//divide single (64 <- 32) - s39_dsgfr,//divide single (64 <- 32) - s39_dsgr,//divide single (64) - s39_dxbr,//divide (extended BFP) - s39_dxr,//divide (extended HFP) - s39_dxtr,//divide (extended DFP) - s39_dxtra,//divide (extended DFP) - s39_ear,//extract access - s39_ecag,//extract cache attribute - s39_ecctr,//extract cpu counter - s39_ecpga,//extract coprocessor-group address - s39_ectg,//extract cpu time - s39_ed,//edit - s39_edmk,//edit and mark - s39_eedtr,//extract biased exponent (long DFP to 64) - s39_eextr,//extract biased exponent (extended DFP to 64) - s39_efpc,//extract fpc - s39_epair,//extract primary ASN and instance - s39_epar,//extract primary ASN - s39_epctr,//extract peripheral counter - s39_epsw,//extract psw - s39_ereg,//extract stacked registers (32) - s39_eregg,//extract stacked registers (64) - s39_esair,//extract secondary ASN and instance - s39_esar,//extract secondary ASN - s39_esdtr,//extract significance (long DFP to 64) - s39_esea,//extract and set extended authority - s39_esta,//extract stacked state - s39_esxtr,//extract significance (extended DFP to 64) - s39_etnd,//extract transaction nesting depth - s39_ex,//execute - s39_exrl,//execute relative long - s39_fidbr,//load fp integer (long BFP) - s39_fidbra,//load fp integer (long BFP) - s39_fidr,//load fp integer (long HFP) - s39_fidtr,//load fp integer (long DFP) - s39_fiebr,//load fp integer (short BFP) - s39_fiebra,//load fp integer (short BFP) - s39_fier,//load fp integer (short HFP) - s39_fixbr,//load fp integer (extended BFP) - s39_fixbra,//load fp integer (extended BFP) - s39_fixr,//load fp integer (extended HFP) - s39_fixtr,//load fp integer (extended DFP) - s39_flogr,//find leftmost one - s39_hdr,//halve (long HFP) - s39_her,//halve (short HFP) - s39_hsch,//halt subchannel - s39_iac,//insert address space control - s39_ic,//insert character - s39_icm,//insert characters under mask (low) - s39_icmh,//insert characters under mask (high) - s39_icmy,//insert characters under mask (low) - s39_icy,//insert character - s39_idte,//invalidate dat table entry - s39_iedtr,//insert biased exponent (64 to long DFP) - s39_iextr,//insert biased exponent (64 to extended DFP) - s39_iihf,//insert immediate (high) - s39_iihh,//inset immediate (high high) - s39_iihl,//insert immediate (high low) - s39_iilf,//insert immediate (low) - s39_iilh,//insert immediate (low high) - s39_iill,//insert immediate (low low) - s39_ipk,//insert PSW key - s39_ipm,//insert program mask - s39_ipte,//invalidate page table entry - s39_irbm,//insert reference bits multiple - s39_iske,//insert storage key extended - s39_ivsk,//insert virtual storage key - s39_j,//unconditional jump - s39_jo,//conditional jump, jump on overflow / if ones - s39_jh,//conditional jump, jump on A high - s39_jnle,//conditional jump, jump on not low or equal - s39_jl,//conditional jump, jump on A low - s39_jnhe,//conditional jump, jump on not high or equal - s39_jlh,//conditional jump, jump on low or high - s39_jne,//conditional jump, jump on A not equal B - s39_je,//conditional jump, jump on A equal B - s39_jnlh,//conditional jump, jump on not low or high - s39_jhe,//conditional jump, jump on high or equal - s39_jnl,//conditional jump, jump on A not low - s39_jle,//conditional jump, jump on low or equal - s39_jnh,//conditional jump, jump on A not high - s39_jno,//conditional jump, jump on not overflow / if not ones - s39_jg,//unconditional jump long - s39_jgo,//conditional jump long, jump on overflow / if ones - s39_jgh,//conditional jump long, jump on A high - s39_jgnle,//conditional jump long, jump on not low or equal - s39_jgl,//conditional jump long, jump on A low - s39_jgnhe,//conditional jump long, jump on not high or equal - s39_jglh,//conditional jump long, jump on low or high - s39_jgne,//conditional jump long, jump on A not equal B - s39_jge,//conditional jump long, jump on A equal B - s39_jgnlh,//conditional jump long, jump on not low or high - s39_jghe,//conditional jump long, jump on high or equal - s39_jgnl,//conditional jump long, jump on A not low - s39_jgle,//conditional jump long, jump on low or equal - s39_jgnh,//conditional jump long, jump on A not high - s39_jgno,//conditional jump long, jump on not overflow / if not ones - s39_kdb,//compare and signal (long BFP) - s39_kdbr,//compare and signal (long BFP) - s39_kdsa,// - s39_kdtr,//compare and signal (long DFP) - s39_keb,//compare and signal (short BFP) - s39_kebr,//compare and signal (short BFP) - s39_kimd,//compute intermediate message digest - s39_klmd,//compute last message digest - s39_km,//cipher message - s39_kma,//cipher message with authentication - s39_kmac,//compute message with authentication - s39_kmc,//cipher message with chaining - s39_kmctr,//cipher message with counter - s39_kmf,//cipher message with cipher feedback - s39_kmo,//cipher message with output feedback - s39_kxbr,//compare and signal (extended BFP) - s39_kxtr,//compare and signal (extended DFP) - s39_l,//load (32) - s39_la,//load address - s39_laa,//load and add (32) - s39_laag,//load and add (64) - s39_laal,//load and add logical (32) - s39_laalg,//load and add logical (64) - s39_lae,//load address extended - s39_laey,//load address extended - s39_lam,//load access multiple - s39_lamy,//load access multiple - s39_lan,//load and and (32) - s39_lang,//load and and (64) - s39_lao,//load and or (32) - s39_laog,//load and or (64) - s39_larl,//load address relative long - s39_lasp,//load address space parameters - s39_lat,//load and trap (32L <- 32) - s39_lax,//load and exclusive or (32) - s39_laxg,//load and exclusive or (64) - s39_lay,//load address - s39_lb,//load byte (32 <- 8) - s39_lbh,//load byte high (32 <- 8) - s39_lbr,//load byte (32 <- 8) - s39_lcbb,//load count to block boundary - s39_lcctl,//load cpu-counter-set controls - s39_lcdbr,//load complement (long BFP) - s39_lcdfr,//load complement (long) - s39_lcdr,//load complement (long HFP) - s39_lcebr,//load complement (short BFP) - s39_lcer,//load complement (short HFP) - s39_lcgfr,//load complement (64 <- 32) - s39_lcgr,//load complement (64) - s39_lcr,//load complement (32) - s39_lctl,//load control (32) - s39_lctlg,//load control (64) - s39_lcxbr,//load complement (extended BFP) - s39_lcxr,//load complement (extended HFP) - s39_ld,//load (long) - s39_lde,//load lengthened (short to long HFP) - s39_ldeb,//load lengthened (short to long BFP) - s39_ldebr,//load lengthened (short to long BFP) - s39_lder,//load lengthened (short to long HFP) - s39_ldetr,//load lengthened (short to long DFP) - s39_ldgr,//load fpr from gr (64 to long) - s39_ldr,//load (long) - s39_ldrv,// - s39_ldxbr,//load rounded (extended to long BFP) - s39_ldxbra,//load rounded (extended to long BFP) - s39_ldxr,//load rounded (extended to long HFP) - s39_ldxtr,//load rounded (extended to long HFP) - s39_ldy,//load (long) - s39_le,//load (short) - s39_ledbr,//load rounded (long to short BFP) - s39_ledbra,//load rounded (long to short BFP) - s39_ledr,//load rounded (long to short HFP) - s39_ledtr,//load rounded (long to short DFP) - s39_ler,//load short - s39_lerv,// - s39_lexbr,//load rounded (extended to short BFP) - s39_lexbra,//load rounded (extended to short BFP) - s39_lexr,//load rounded (extended to short HFP) - s39_ley,//load (short) - s39_lfas,//load fpc and signal - s39_lfh,//load high (32) - s39_lfhat,//load high and trap (32h <- 32) - s39_lfpc,//load fpc - s39_lg,//load (64) - s39_lgat,//load and trap (64) - s39_lgb,//load byte (64 <- 8) - s39_lgbr,//load byte (64 <- 8) - s39_lgdr,//load gr from fpr (long to 64) - s39_lgf,//load (64 <- 32) - s39_lgfi,//load immediate (64 <- 32) - s39_lgfr,//load (64 <- 32) - s39_lgfrl,//load relative long (64 <- 32) - s39_lgg,//load guarded (64) - s39_lgh,//load halfword (64 <- 16) - s39_lghi,//load halfword immediate (64 <- 16) - s39_lghr,//load halfword (64 <- 16) - s39_lghrl,//load halfword relative long (64 <- 16) - s39_lgr,//load (64) - s39_lgrl,//load relative long (64) - s39_lgsc,//load guarded storage controls - s39_lh,//load halfword (32 <- 16) - s39_lhh,//load halfword high (32 <- 16) - s39_lhi,//load halfword immediate (32) <- 16 - s39_lhr,//load halfword (32 <- 16) - s39_lhrl,//load halfword relative long (32 <- 16) - s39_lhy,//load halfword (32 <- 16) - s39_llc,//load logical character (32 <- 8) - s39_llch,//load logical character high (32 <- 8) - s39_llcr,//load logical character (32 <- 8) - s39_llgc,//load logical character (64 <- 8) - s39_llgcr,//load logical character (64 <- 8) - s39_llgf,//load logical (64 <- 32) - s39_llgfat,//load logical and trap (64 <- 32) - s39_llgfr,//load logical (64 <- 32) - s39_llgfrl,//load logical relative long (64 <- 32) - s39_llgfsg,//load logical and shift guarded (64 <- 32) - s39_llgh,//load logical halfword (64 <- 16) - s39_llghr,//load logical halfword (64 <- 16) - s39_llghrl,//load logical halfword relative long (64 <- 16) - s39_llgt,//load logical thirty one bits (64 <- 31) - s39_llgtat,//load logical thirty one bits and trap (64 <- 31) - s39_llgtr,//load logical thirty one bits (64 <- 31) - s39_llh,//load logical halfword (32 <- 16) - s39_llhh,//load logical halfword high (32 <- 16) - s39_llhr,//load logical halfword (32 <- 16) - s39_llhrl,//load logical halfword relative long (32 <- 16) - s39_llihf,//load logical immediate (high) - s39_llihh,//load logical immediate (high high) - s39_llihl,//load logical immediate (high low) - s39_llilf,//load logical immediate (low) - s39_llilh,//load logical immediate (low high) - s39_llill,//load logical immediate (low low) - s39_llzrgf,//load logical and zero rightmost byte (64 <- 32) - s39_lm,//load multiple (32) - s39_lmd,//load multiple disjoint (64 <- 32& 32) - s39_lmg,//load multiple (64) - s39_lmh,//load multiple high (32) - s39_lmy,//load multiple high (32) - s39_lndbr,//load negative (long BFP) - s39_lndfr,//load negative (long) - s39_lndr,//load negative (long HFP) - s39_lnebr,//load negative (short BFP) - s39_lner,//load negative (short HFP) - s39_lngfr,//load negative (64 <- 32) - s39_lngr,//load negative (64) - s39_lnr,//load negative (32) - s39_lnxbr,//load negative (extended BFP) - s39_lnxr,//load negative (extended HFP) - s39_loc,//load on condition (32) - s39_loco,//load on condition (32), jump on overflow / if ones - s39_loch,//load on condition (32), jump on A high - s39_locnle,//load on condition (32), jump on not low or equal - s39_locl,//load on condition (32), jump on A low - s39_locnhe,//load on condition (32), jump on not high or equal - s39_loclh,//load on condition (32), jump on low or high - s39_locne,//load on condition (32), jump on A not equal B - s39_loce,//load on condition (32), jump on A equal B - s39_locnlh,//load on condition (32), jump on not low or high - s39_loche,//load on condition (32), jump on high or equal - s39_locnl,//load on condition (32), jump on A not low - s39_locle,//load on condition (32), jump on low or equal - s39_locnh,//load on condition (32), jump on A not high - s39_locno,//load on condition (32), jump on not overflow / if not ones - s39_locfh,//load high on condition (32) - s39_locfho,//load high on condition (32), jump on overflow / if ones - s39_locfhh,//load high on condition (32), jump on A high - s39_locfhnle,//load high on condition (32), jump on not low or equal - s39_locfhl,//load high on condition (32), jump on A low - s39_locfhnhe,//load high on condition (32), jump on not high or equal - s39_locfhlh,//load high on condition (32), jump on low or high - s39_locfhne,//load high on condition (32), jump on A not equal B - s39_locfhe,//load high on condition (32), jump on A equal B - s39_locfhnlh,//load high on condition (32), jump on not low or high - s39_locfhhe,//load high on condition (32), jump on high or equal - s39_locfhnl,//load high on condition (32), jump on A not low - s39_locfhle,//load high on condition (32), jump on low or equal - s39_locfhnh,//load high on condition (32), jump on A not high - s39_locfhno,//load high on condition (32), jump on not overflow / if not ones - s39_locfhr,//load high on condition (32) - s39_locfhro,//load high on condition (32), jump on overflow / if ones - s39_locfhrh,//load high on condition (32), jump on A high - s39_locfhrnle,//load high on condition (32), jump on not low or equal - s39_locfhrl,//load high on condition (32), jump on A low - s39_locfhrnhe,//load high on condition (32), jump on not high or equal - s39_locfhrlh,//load high on condition (32), jump on low or high - s39_locfhrne,//load high on condition (32), jump on A not equal B - s39_locfhre,//load high on condition (32), jump on A equal B - s39_locfhrnlh,//load high on condition (32), jump on not low or high - s39_locfhrhe,//load high on condition (32), jump on high or equal - s39_locfhrnl,//load high on condition (32), jump on A not low - s39_locfhrle,//load high on condition (32), jump on low or equal - s39_locfhrnh,//load high on condition (32), jump on A not high - s39_locfhrno,//load high on condition (32), jump on not overflow / if not ones - s39_locg,//load on condition (64) - s39_locgo,//load on condition (64), jump on overflow / if ones - s39_locgh,//load on condition (64), jump on A high - s39_locgnle,//load on condition (64), jump on not low or equal - s39_locgl,//load on condition (64), jump on A low - s39_locgnhe,//load on condition (64), jump on not high or equal - s39_locglh,//load on condition (64), jump on low or high - s39_locgne,//load on condition (64), jump on A not equal B - s39_locge,//load on condition (64), jump on A equal B - s39_locgnlh,//load on condition (64), jump on not low or high - s39_locghe,//load on condition (64), jump on high or equal - s39_locgnl,//load on condition (64), jump on A not low - s39_locgle,//load on condition (64), jump on low or equal - s39_locgnh,//load on condition (64), jump on A not high - s39_locgno,//load on condition (64), jump on not overflow / if not ones - s39_locghi,//load halfword immediate on condition (64 <- 16) - s39_locghio,//load halfword immediate on condition (64 <- 16), jump on overflow / if ones - s39_locghih,//load halfword immediate on condition (64 <- 16), jump on A high - s39_locghinle,//load halfword immediate on condition (64 <- 16), jump on not low or equal - s39_locghil,//load halfword immediate on condition (64 <- 16), jump on A low - s39_locghinhe,//load halfword immediate on condition (64 <- 16), jump on not high or equal - s39_locghilh,//load halfword immediate on condition (64 <- 16), jump on low or high - s39_locghine,//load halfword immediate on condition (64 <- 16), jump on A not equal B - s39_locghie,//load halfword immediate on condition (64 <- 16), jump on A equal B - s39_locghinlh,//load halfword immediate on condition (64 <- 16), jump on not low or high - s39_locghihe,//load halfword immediate on condition (64 <- 16), jump on high or equal - s39_locghinl,//load halfword immediate on condition (64 <- 16), jump on A not low - s39_locghile,//load halfword immediate on condition (64 <- 16), jump on low or equal - s39_locghinh,//load halfword immediate on condition (64 <- 16), jump on A not high - s39_locghino,//load halfword immediate on condition (64 <- 16), jump on not overflow / if not ones - s39_locgr,//load on condition (64) - s39_locgro,//load on condition (64), jump on overflow / if ones - s39_locgrh,//load on condition (64), jump on A high - s39_locgrnle,//load on condition (64), jump on not low or equal - s39_locgrl,//load on condition (64), jump on A low - s39_locgrnhe,//load on condition (64), jump on not high or equal - s39_locgrlh,//load on condition (64), jump on low or high - s39_locgrne,//load on condition (64), jump on A not equal B - s39_locgre,//load on condition (64), jump on A equal B - s39_locgrnlh,//load on condition (64), jump on not low or high - s39_locgrhe,//load on condition (64), jump on high or equal - s39_locgrnl,//load on condition (64), jump on A not low - s39_locgrle,//load on condition (64), jump on low or equal - s39_locgrnh,//load on condition (64), jump on A not high - s39_locgrno,//load on condition (64), jump on not overflow / if not ones - s39_lochhi,//load halfword high immediate on condition (32 <- 16) - s39_lochhio,//load halfword high immediate on condition (32 <- 16), jump on overflow / if ones - s39_lochhih,//load halfword high immediate on condition (32 <- 16), jump on A high - s39_lochhinle,//load halfword high immediate on condition (32 <- 16), jump on not low or equal - s39_lochhil,//load halfword high immediate on condition (32 <- 16), jump on A low - s39_lochhinhe,//load halfword high immediate on condition (32 <- 16), jump on not high or equal - s39_lochhilh,//load halfword high immediate on condition (32 <- 16), jump on low or high - s39_lochhine,//load halfword high immediate on condition (32 <- 16), jump on A not equal B - s39_lochhie,//load halfword high immediate on condition (32 <- 16), jump on A equal B - s39_lochhinlh,//load halfword high immediate on condition (32 <- 16), jump on not low or high - s39_lochhihe,//load halfword high immediate on condition (32 <- 16), jump on high or equal - s39_lochhinl,//load halfword high immediate on condition (32 <- 16), jump on A not low - s39_lochhile,//load halfword high immediate on condition (32 <- 16), jump on low or equal - s39_lochhinh,//load halfword high immediate on condition (32 <- 16), jump on A not high - s39_lochhino,//load halfword high immediate on condition (32 <- 16), jump on not overflow / if not ones - s39_lochi,//load halfword immediate on condition (32 <- 16) - s39_lochio,//load halfword immediate on condition (32 <- 16), jump on overflow / if ones - s39_lochih,//load halfword immediate on condition (32 <- 16), jump on A high - s39_lochinle,//load halfword immediate on condition (32 <- 16), jump on not low or equal - s39_lochil,//load halfword immediate on condition (32 <- 16), jump on A low - s39_lochinhe,//load halfword immediate on condition (32 <- 16), jump on not high or equal - s39_lochilh,//load halfword immediate on condition (32 <- 16), jump on low or high - s39_lochine,//load halfword immediate on condition (32 <- 16), jump on A not equal B - s39_lochie,//load halfword immediate on condition (32 <- 16), jump on A equal B - s39_lochinlh,//load halfword immediate on condition (32 <- 16), jump on not low or high - s39_lochihe,//load halfword immediate on condition (32 <- 16), jump on high or equal - s39_lochinl,//load halfword immediate on condition (32 <- 16), jump on A not low - s39_lochile,//load halfword immediate on condition (32 <- 16), jump on low or equal - s39_lochinh,//load halfword immediate on condition (32 <- 16), jump on A not high - s39_lochino,//load halfword immediate on condition (32 <- 16), jump on not overflow / if not ones - s39_locr,//load on condition (32) - s39_locro,//load on condition (32), jump on overflow / if ones - s39_locrh,//load on condition (32), jump on A high - s39_locrnle,//load on condition (32), jump on not low or equal - s39_locrl,//load on condition (32), jump on A low - s39_locrnhe,//load on condition (32), jump on not high or equal - s39_locrlh,//load on condition (32), jump on low or high - s39_locrne,//load on condition (32), jump on A not equal B - s39_locre,//load on condition (32), jump on A equal B - s39_locrnlh,//load on condition (32), jump on not low or high - s39_locrhe,//load on condition (32), jump on high or equal - s39_locrnl,//load on condition (32), jump on A not low - s39_locrle,//load on condition (32), jump on low or equal - s39_locrnh,//load on condition (32), jump on A not high - s39_locrno,//load on condition (32), jump on not overflow / if not ones - s39_lpctl,//load peripheral-counter-set controls - s39_lpd,//load pair disjoint (32) - s39_lpdbr,//load positive (long BFP) - s39_lpdfr,//load positive (long) - s39_lpdg,//load pair disjoint (64) - s39_lpdr,//load positive (long HFP) - s39_lpebr,//load positive (short BFP) - s39_lper,//load positive (short HFP) - s39_lpgfr,//load positive (64 <- 32) - s39_lpgr,//load positive (64) - s39_lpp,//load program parameter - s39_lpq,//load pair from quadword (64&64 <- 128) - s39_lpr,//load positive (32) - s39_lpsw,//load PSW - s39_lpswe,//load psw extended - s39_lptea,//load page-table-entry address - s39_lpxbr,//load positive (extended BFP) - s39_lpxr,//load positive (extended HFP) - s39_lr,//load (32) - s39_lra,//load real address (32) - s39_lrag,//load real address (64) - s39_lray,//load real address (32) - s39_lrdr,//load rounded (extended to long HFP) - s39_lrer,//load rounded (long to short HFP) - s39_lrl,//load relative long (32) - s39_lrv,//load reversed (32) - s39_lrvg,//load reversed (64) - s39_lrvgr,//load reversed (64) - s39_lrvh,//load reversed (16) - s39_lrvr,//load reversed (32) - s39_lsctl,//load sampling controls - s39_lt,//load and test (32) - s39_ltdbr,//load and test (long BFP) - s39_ltdr,//load and test (long HFP) - s39_ltdtr,//load and test (long DFP) - s39_ltebr,//load and test (short BFP) - s39_lter,//load and test (short HFP) - s39_ltg,//load and test (64) - s39_ltgf,//load and test (64 <- 32) - s39_ltgfr,//load and test (64 <- 32) - s39_ltgr,//load and test (64) - s39_ltr,//load and test (32) - s39_ltxbr,//load and test (extended BFP) - s39_ltxr,//load and test (extended HFP) - s39_ltxtr,//load and test (extended DFP) - s39_lura,//load using real address (32) - s39_lurag,//load using real address (64) - s39_lxd,//load lengthened (long to extended HFP) - s39_lxdb,//load lengthened (long to extended BFP) - s39_lxdbr,//load lengthened (long to extended BFP) - s39_lxdr,//load lengthened (long to extended HFP) - s39_lxdtr,//load lengthened (long to extended DFP) - s39_lxe,//load lengthened (short to extended HFP) - s39_lxeb,//load lengthened (short to extended BFP) - s39_lxebr,//load lengthened (short to extended BFP) - s39_lxer,//load lengthened (short to extended HFP) - s39_lxr,//load (extended) - s39_ly,//load (32) - s39_lzdr,//load zero (long) - s39_lzer,//load zero (short) - s39_lzrf,//load and zero rightmost byte (32) - s39_lzrg,//load and zero rightmost byte (64) - s39_lzxr,//load zero (extended) - s39_m,//multiply (64 <- 32) - s39_mad,//multiply and add (long HFP) - s39_madb,//multiply and add (long BFP) - s39_madbr,//multiply and add (long BFP) - s39_madr,//multiply and add (long HFP) - s39_mae,//multiply and add (short HFP) - s39_maeb,//multiply and add (short BFP) - s39_maebr,//multiply and add (short BFP) - s39_maer,//multiply and add (short HFP) - s39_may,//multiply & add unnormalized (long to extended HFP) - s39_mayh,//multiply & add unnormalized (long to extended high HFP) - s39_mayhr,//multiply & add unnormalized (long to extended high HFP) - s39_mayl,//multiply & add unnormalized (long to extended low HFP) - s39_maylr,//multiply & add unnormalized (long to extended low HFP) - s39_mayr,//multiply & add unnormalized (long to extended HFP) - s39_mc,//monitor call - s39_md,//multiply (long HFP) - s39_mdb,//multiply (long BFP) - s39_mdbr,//multiply (long BFP) - s39_mde,//multiply (short to long HFP) - s39_mdeb,//multiply (short to long BFP) - s39_mdebr,//multiply (short to long BFP) - s39_mder,//multiply (short to long HFP) - s39_mdr,//multiply (long HFP) - s39_mdtr,//multiply (long DFP) - s39_mdtra,//multiply (long DFP) - s39_me,//multiply (short to long HFP) - s39_mee,//multiply (short HFP) - s39_meeb,//multiply (short BFP) - s39_meebr,//multiply (short BFP) - s39_meer,//multiply (short HFP) - s39_mer,//multiply (short to long HFP) - s39_mfy,//multiply (64 <- 32) - s39_mg,//multiply (128 <- 64) - s39_mgh,//multiply halfword (64 <- 16) - s39_mghi,//multiply halfword immediate (64 <- 16) - s39_mgrk,//multiply (128 <- 64) - s39_mh,//multiply halfword (32 <- 16) - s39_mhi,//multiply halfword immediate (32 <- 16) - s39_mhy,//multiply halfword (32 <- 16) - s39_ml,//multiply logical (64 <- 32) - s39_mlg,//multiply logical (128 <- 64) - s39_mlgr,//multiply logical (128 <- 64) - s39_mlr,//multiply logical (64 <- 32) - s39_mp,//multiply decimal - s39_mr,//multiply (64 <- 32) - s39_ms,//multiply single (32) - s39_msc,//multiply single (32) - s39_msch,//modify subchannel - s39_msd,//multiply and subtract (long HFP) - s39_msdb,//multiply and subtract (long BFP) - s39_msdbr,//multiply and subtract (long BFP) - s39_msdr,//multiply and subtract (long HFP) - s39_mse,//multiply and subtract (short HFP) - s39_mseb,//multiply and subtract (short BFP) - s39_msebr,//multiply and subtract (short BFP) - s39_mser,//multiply and subtract (short HFP) - s39_msfi,//multiply single immediate (32) - s39_msg,//multiply single (64) - s39_msgc,//multiply single (64) - s39_msgf,//multiply single (64 <- 32) - s39_msgfi,//multiply single immediate (64 <- 32) - s39_msgfr,//multiply single (64 <- 32) - s39_msgr,//multiply single (64) - s39_msgrkc,//multiply single (64) - s39_msr,//multiply single (32) - s39_msrkc,//multiply single (32) - s39_msta,//modify stacked state - s39_msy,//multiply single (32) - s39_mvc,//move (character) - s39_mvcdk,//move with destination key - s39_mvcin,//move inverse - s39_mvck,//move with key - s39_mvcl,//move long - s39_mvcle,//move long extended - s39_mvclu,//move long unicode - s39_mvcos,//move with optional specifications - s39_mvcp,//move to primary - s39_mvcrl,// - s39_mvcs,//move to secondary - s39_mvcsk,//move with source key - s39_mvghi,//move (64 <- 16) - s39_mvhhi,//move (16 <- 16) - s39_mvhi,//move (32 <- 16) - s39_mvi,//move (immediate) - s39_mviy,//move (immediate) - s39_mvn,//move numerics - s39_mvo,//move with offset - s39_mvpg,//move page - s39_mvst,//move string - s39_mvz,//move zones - s39_mxbr,//multiply (extended BFP) - s39_mxd,//multiply (long to extended HFP) - s39_mxdb,//multiply (long to extended BFP) - s39_mxdbr,//multiply (long to extended BFP) - s39_mxdr,//multiply (long to extended HFP) - s39_mxr,//multiply (extended HFP) - s39_mxtr,//multiply (extended DFP) - s39_mxtra,//multiply (extended DFP) - s39_my,//multiply unnormalized (long to extended HFP) - s39_myh,//multiply unnormalized (long to extended high HFP) - s39_myhr,//multiply unnormalized (long to extended high HFP) - s39_myl,//multiply unnormalized (long to extended low HFP) - s39_mylr,//multiply unnormalized (long to extended low HFP) - s39_myr,//multiply unnormalized (long to extended HFP) - s39_n,//and (32) - s39_nc,//and (character) - s39_ncgrk,// - s39_ncrk,// - s39_ng,//and (64) - s39_ngr,//and (64) - s39_ngrk,//and (64) - s39_ni,//and (immediate) - s39_niai,//next instruction access intent - s39_nihf,//and immediate (high) - s39_nihh,//and immediate (high high) - s39_nihl,//and immediate (high low) - s39_nilf,//and immediate (low) - s39_nilh,//and immediate (low high) - s39_nill,//and immediate (low low) - s39_niy,//and (immediate) - s39_nngrk,// - s39_nnrk,// - s39_nogrk,// - s39_nop,//no operation - s39_nopr,//no operation - s39_nork,// - s39_nr,//and (32) - s39_nrk,//and (32) - s39_ntstg,//nontransactional store (64) - s39_nxgrk,// - s39_nxrk,// - s39_ny,//and (32) - s39_o,//or (32) - s39_oc,//or (character) - s39_ocgrk,// - s39_ocrk,// - s39_og,//or (64) - s39_ogr,//or (64) - s39_ogrk,//or (64) - s39_oi,//or (immediate) - s39_oihf,//or immediate (high) - s39_oihh,//or immediate (high high) - s39_oihl,//or immediate (high low) - s39_oilf,//or immediate (low) - s39_oilh,//or immediate (low high) - s39_oill,//or immediate (low low) - s39_oiy,//or (immediate) - s39_or,//or (32) - s39_ork,//or (32) - s39_oy,//or (32) - s39_pack,//pack - s39_palb,//purge ALB - s39_pc,//program call - s39_pcc,//perform cryptographic computation - s39_pckmo,//perform cryptographic key management operation - s39_pfd,//prefetch data - s39_pfdrl,//prefetch data relative long - s39_pfmf,//perform frame management function - s39_pfpo,//perform floating point operation - s39_pgin,//page in - s39_pgout,//page out - s39_pka,//pack ascii - s39_pku,//pack unicode - s39_plo,//perform locked operation - s39_popcnt,//population count - s39_ppa,//perform processor assist - s39_ppno,//perform pseudorandom number operation - s39_pr,//program return - s39_prno,//perform pseudorandom number operation - s39_pt,//program transfer - s39_ptf,//perform topology function - s39_ptff,//perform timing facility function - s39_pti,//program transfer with instance - s39_ptlb,//purge TLB - s39_qadtr,//quantize (long DFP) - s39_qaxtr,//quantize (extended DFP) - s39_qctri,//query counter information - s39_qsi,//query sampling information - s39_rchp,//reset channel path - s39_risbg,//rotate then insert selected bits (64) - s39_risbgn,//rotate then insert selected bits (64) - s39_risbhg,//rotate then insert selected bits high (64) - s39_risblg,//rotate then insert selected bits low (64) - s39_rll,//rotate left single logical (32) - s39_rllg,//rotate left single logical (64) - s39_rnsbg,//rotate then and selected bits (64) - s39_rosbg,//rotate then or selected bits (64) - s39_rp,//resume program - s39_rrbe,//reset reference bit extended - s39_rrbm,//reset reference bits multiple - s39_rrdtr,//reround (long DFP) - s39_rrxtr,//reround (extended DFP) - s39_rsch,//resume subchannel - s39_rxsbg,//rotate then exclusive or selected bits (64) - s39_s,//subtract (32) - s39_sac,//set address space control - s39_sacf,//set address space control fast - s39_sal,//set address limit - s39_sam24,//set addressing mode 24 - s39_sam31,//set addressing mode 31 - s39_sam64,//set addressing mode 64 - s39_sar,//set access - s39_scctr,//set cpu counter - s39_schm,//set channel monitor - s39_sck,//set clock - s39_sckc,//set clock comparator - s39_sckpf,//set clock programmable field - s39_sd,//subtract normalized (long HFP) - s39_sdb,//subtract (long BFP) - s39_sdbr,//subtract (long BFP) - s39_sdr,//subtract normalized (long HFP) - s39_sdtr,//subtract normalized (long DFP) - s39_sdtra,//subtract normalized (long DFP) - s39_se,//subtract normalized (short HFP) - s39_seb,//subtract (short BFP) - s39_sebr,//subtract (short BFP) - s39_selgr,// - s39_selgro,//, jump on overflow / if ones - s39_selgrh,//, jump on A high - s39_selgrnle,//, jump on not low or equal - s39_selgrl,//, jump on A low - s39_selgrnhe,//, jump on not high or equal - s39_selgrlh,//, jump on low or high - s39_selgrne,//, jump on A not equal B - s39_selgre,//, jump on A equal B - s39_selgrnlh,//, jump on not low or high - s39_selgrhe,//, jump on high or equal - s39_selgrnl,//, jump on A not low - s39_selgrle,//, jump on low or equal - s39_selgrnh,//, jump on A not high - s39_selgrno,//, jump on not overflow / if not ones - s39_selhhhr,// - s39_selhhhro,//, jump on overflow / if ones - s39_selhhhrh,//, jump on A high - s39_selhhhrnle,//, jump on not low or equal - s39_selhhhrl,//, jump on A low - s39_selhhhrnhe,//, jump on not high or equal - s39_selhhhrlh,//, jump on low or high - s39_selhhhrne,//, jump on A not equal B - s39_selhhhre,//, jump on A equal B - s39_selhhhrnlh,//, jump on not low or high - s39_selhhhrhe,//, jump on high or equal - s39_selhhhrnl,//, jump on A not low - s39_selhhhrle,//, jump on low or equal - s39_selhhhrnh,//, jump on A not high - s39_selhhhrno,//, jump on not overflow / if not ones - s39_selr,// - s39_selro,//, jump on overflow / if ones - s39_selrh,//, jump on A high - s39_selrnle,//, jump on not low or equal - s39_selrl,//, jump on A low - s39_selrnhe,//, jump on not high or equal - s39_selrlh,//, jump on low or high - s39_selrne,//, jump on A not equal B - s39_selre,//, jump on A equal B - s39_selrnlh,//, jump on not low or high - s39_selrhe,//, jump on high or equal - s39_selrnl,//, jump on A not low - s39_selrle,//, jump on low or equal - s39_selrnh,//, jump on A not high - s39_selrno,//, jump on not overflow / if not ones - s39_ser,//subtract normalized (short HFP) - s39_sfasr,//set fpc and signal - s39_sfpc,//set fpc - s39_sg,//subtract (64) - s39_sgf,//subtract (64 <- 32) - s39_sgfr,//subtract (64 <- 32) - s39_sgh,//sintract halfword (64 <- 16) - s39_sgr,//subtract (64) - s39_sgrk,//subtract (64) - s39_sh,//subtract halfword (32 <- 16) - s39_shhhr,//subtract high (32) - s39_shhlr,//subtract high (32) - s39_shy,//subtract halfword (32 <- 16) - s39_sie,//start interpretive execution - s39_siga,//signal adapter - s39_sigp,//signal processor - s39_sl,//subtract logical (32) - s39_sla,//shift left single (32) - s39_slag,//shift left single (64) - s39_slak,//shift left single (32) - s39_slb,//subtract logical with borrow (32) - s39_slbg,//subtract logical with borrow (64) - s39_slbgr,//subtract logical with borrow (64) - s39_slbr,//subtract logical with borrow (32) - s39_slda,//shift left double (64) - s39_sldl,//shift left double logical (64) - s39_sldt,//shift significand left (long DFP) - s39_slfi,//subtract logical immediate (32) - s39_slg,//subtract logical (64) - s39_slgf,//subtract logical (64 <- 32) - s39_slgfi,//subtract logical (64 <- 32) - s39_slgfr,//subtract logical (64 <- 32) - s39_slgr,//subtract logical (64) - s39_slgrk,//subtract logical (64) - s39_slhhhr,//subtract logical high (32) - s39_slhhlr,//subtract logical high (32) - s39_sll,//shift left single logical (32) - s39_sllg,//shift left single logical (64) - s39_sllk,//shift left single logical (32) - s39_slr,//subtract logical (32) - s39_slrk,//subtract logical (32) - s39_slxt,//shift significand left (extended DFP) - s39_sly,//subtract logical (32) - s39_sortl,// - s39_sp,//subtract decimal - s39_spctr,//set peripheral counter - s39_spka,//set PSW key from address - s39_spm,//set program mask - s39_spt,//set CPU timer - s39_spx,//set prefix - s39_sqd,//square root (long HFP) - s39_sqdb,//square root (long BFP) - s39_sqdbr,//square root (long BFP) - s39_sqdr,//square root (long HFP) - s39_sqe,//square root (short HFP) - s39_sqeb,//square root (short BFP) - s39_sqebr,//square root (short BFP) - s39_sqer,//square root (short HFP) - s39_sqxbr,//square root (extended BFP) - s39_sqxr,//square root (extended HFP) - s39_sr,//subtract (32) - s39_sra,//shift right single (32) - s39_srag,//shift right single (64) - s39_srak,//shift right single (32) - s39_srda,//shift right double (64) - s39_srdl,//shift right double logical (64) - s39_srdt,//shift significand right (long DFP) - s39_srk,//subtract (32) - s39_srl,//shift right single logical (32) - s39_srlg,//shift right single logical (64) - s39_srlk,//shift right single logical (64) - s39_srnm,//set bfp rounding mode (2bit) - s39_srnmb,//set bfp rounding mode (3bit) - s39_srnmt,//set dfp rounding mode - s39_srp,//shift and round decimal - s39_srst,//search string - s39_srstu,//search string unicode - s39_srxt,//shift significand right (extended DFP) - s39_ssair,//set secondary ASN with instance - s39_ssar,//set secondary ASN - s39_ssch,//start subchannel - s39_sske,//set storage key extended - s39_ssm,//set system mask - s39_st,//store (32) - s39_stam,//store access multiple - s39_stamy,//store access multiple - s39_stap,//store CPU address - s39_stc,//store character - s39_stch,//store character high (8) - s39_stck,//store clock - s39_stckc,//store clock comparator - s39_stcke,//store clock extended - s39_stckf,//store clock fast - s39_stcm,//store characters under mask (low) - s39_stcmh,//store characters under mask (high) - s39_stcmy,//store characters under mask (low) - s39_stcps,//store channel path status - s39_stcrw,//store channel report word - s39_stctg,//store control (64) - s39_stctl,//store control (64) - s39_stcy,//store character - s39_std,//store (long) - s39_stdrv,// - s39_stdy,//store (long) - s39_ste,//store (short) - s39_sterv,// - s39_stey,//store (short) - s39_stfh,//store high (32) - s39_stfl,//store facility list - s39_stfle,//store facility list extended - s39_stfpc,//store fpc - s39_stg,//store (64) - s39_stgrl,//store relative long (64) - s39_stgsc,//store guarded storage controls - s39_sth,//store halfword (16) - s39_sthh,//store halfword high (16) - s39_sthrl,//store halfword relative long (16) - s39_sthy,//store halfword (16) - s39_stidp,//store CPU id - s39_stm,//store multiple (32) - s39_stmg,//store multiple (64) - s39_stmh,//store multiple high (32) - s39_stmy,//store multiple (32) - s39_stnsm,//store then and system mask - s39_stoc,//store on condition (32) - s39_stoco,//store on condition (32), jump on overflow / if ones - s39_stoch,//store on condition (32), jump on A high - s39_stocnle,//store on condition (32), jump on not low or equal - s39_stocl,//store on condition (32), jump on A low - s39_stocnhe,//store on condition (32), jump on not high or equal - s39_stoclh,//store on condition (32), jump on low or high - s39_stocne,//store on condition (32), jump on A not equal B - s39_stoce,//store on condition (32), jump on A equal B - s39_stocnlh,//store on condition (32), jump on not low or high - s39_stoche,//store on condition (32), jump on high or equal - s39_stocnl,//store on condition (32), jump on A not low - s39_stocle,//store on condition (32), jump on low or equal - s39_stocnh,//store on condition (32), jump on A not high - s39_stocno,//store on condition (32), jump on not overflow / if not ones - s39_stocfh,//store high on condition - s39_stocfho,//store high on condition, jump on overflow / if ones - s39_stocfhh,//store high on condition, jump on A high - s39_stocfhnle,//store high on condition, jump on not low or equal - s39_stocfhl,//store high on condition, jump on A low - s39_stocfhnhe,//store high on condition, jump on not high or equal - s39_stocfhlh,//store high on condition, jump on low or high - s39_stocfhne,//store high on condition, jump on A not equal B - s39_stocfhe,//store high on condition, jump on A equal B - s39_stocfhnlh,//store high on condition, jump on not low or high - s39_stocfhhe,//store high on condition, jump on high or equal - s39_stocfhnl,//store high on condition, jump on A not low - s39_stocfhle,//store high on condition, jump on low or equal - s39_stocfhnh,//store high on condition, jump on A not high - s39_stocfhno,//store high on condition, jump on not overflow / if not ones - s39_stocg,//store on condition (64) - s39_stocgo,//store on condition (64), jump on overflow / if ones - s39_stocgh,//store on condition (64), jump on A high - s39_stocgnle,//store on condition (64), jump on not low or equal - s39_stocgl,//store on condition (64), jump on A low - s39_stocgnhe,//store on condition (64), jump on not high or equal - s39_stocglh,//store on condition (64), jump on low or high - s39_stocgne,//store on condition (64), jump on A not equal B - s39_stocge,//store on condition (64), jump on A equal B - s39_stocgnlh,//store on condition (64), jump on not low or high - s39_stocghe,//store on condition (64), jump on high or equal - s39_stocgnl,//store on condition (64), jump on A not low - s39_stocgle,//store on condition (64), jump on low or equal - s39_stocgnh,//store on condition (64), jump on A not high - s39_stocgno,//store on condition (64), jump on not overflow / if not ones - s39_stosm,//store then or system mask - s39_stpq,//store pair to quadword - s39_stpt,//store CPU timer - s39_stpx,//store prefix - s39_strag,//store real address - s39_strl,//store relative long (32) - s39_strv,//store reversed (32) - s39_strvg,//store reversed (64) - s39_strvh,//store reversed (16) - s39_stsch,//store subchannel - s39_stsi,//store system information - s39_stura,//store using real address (32) - s39_sturg,//store using real address (64) - s39_sty,//store (32) - s39_su,//subtract unnormalized (short HFP) - s39_sur,//subtract unnormalized (short HFP) - s39_svc,//supervisor call - s39_sw,//subtract unnormalized (long HFP) - s39_swr,//subtract unnormalized (long HFP) - s39_sxbr,//subtract (extended BFP) - s39_sxr,//subtract normalized (extended HFP) - s39_sxtr,//subtract (extended DFP) - s39_sxtra,//subtract (extended DFP) - s39_sy,//subtract (32) - s39_tabort,//transaction abort - s39_tam,//test addressing mode - s39_tar,//test access - s39_tb,//test block - s39_tbdr,//convert HFP to BFP (long) - s39_tbedr,//convert HFP to BFP (long to short) - s39_tbegin,//transaction begin (nonconstrained) - s39_tbeginc,//transaction begin (constrained) - s39_tcdb,//test data class (long BFP) - s39_tceb,//test data class (short BFP) - s39_tcxb,//test data class (extended BFP) - s39_tdcdt,//test data class (long DFP) - s39_tdcet,//test data class (short DFP) - s39_tdcxt,//test data class (extended DFP) - s39_tdgdt,//test data group (long DFP) - s39_tdget,//test data group (short DFP) - s39_tdgxt,//test data group (extended DFP) - s39_tend,//transaction end - s39_thder,//convert BFP to HFP (short to long) - s39_thdr,//convert BFP to HFP (long) - s39_tm,//test under mask - s39_tmhh,//test under mask (high high) - s39_tmhl,//test under mask (high low) - s39_tmlh,//test under mask (low high) - s39_tmll,//test under mask (low low) - s39_tmy,//test under mask - s39_tp,//test decimal - s39_tpei,//test pending external interruption - s39_tpi,//test pending interruption - s39_tprot,//test protection - s39_tr,//translate - s39_trace,//trace (32) - s39_tracg,//trace (64) - s39_trap2,//trap - s39_trap4,//trap - s39_tre,//translate extended - s39_troo,//translate one to one - s39_trot,//translate one to two - s39_trt,//translate and test - s39_trte,//translate and test extended - s39_trto,//translate two to one - s39_trtr,//translate and test reverse - s39_trtre,//translate and test reverse extended - s39_trtt,//translate two to two - s39_ts,//test and set - s39_tsch,//test subchannel - s39_unpk,//unpack - s39_unpka,//unpack ascii - s39_unpku,//unpack unicode - s39_upt,//update tree - s39_va,//vector add - s39_vab,//vector add byte - s39_vac,//vector add with carry - s39_vacc,//vector add compute carry - s39_vaccb,//vector add compute carry byte - s39_vaccc,//vector add with carry compute carry - s39_vacccq,//vector add with carry compute carry quadword - s39_vaccf,//vector add compute carry word - s39_vaccg,//vector add compute carry doubleword - s39_vacch,//vector add compute carry halfword - s39_vaccq,//vector add compute carry quadword - s39_vacq,//vector add with carry quadword - s39_vaf,//vector add word - s39_vag,//vector add double word - s39_vah,//vector add halfword - s39_vap,//vector add decimal - s39_vaq,//vector add quad word - s39_vavg,//vector average - s39_vavgb,//vector average byte - s39_vavgf,//vector average word - s39_vavgg,//vector average double word - s39_vavgh,//vector average half word - s39_vavgl,//vector average logical - s39_vavglb,//vector average logical byte - s39_vavglf,//vector average logical word - s39_vavglg,//vector average logical double word - s39_vavglh,//vector average logical half word - s39_vbperm,//vector bit permute - s39_vcdg,//vector fp convert from fixed 64 bit - s39_vcdgb,//vector fp convert from fixed 64 bit - s39_vcdlg,//vector fp convert from logical 64 bit - s39_vcdlgb,//vector fp convert from logical 64 bit - s39_vcefb,// - s39_vcelfb,// - s39_vceq,//vector compare equal - s39_vceqb,//vector compare equal byte - s39_vceqbs,//vector compare equal byte - s39_vceqf,//vector compare equal word - s39_vceqfs,//vector compare equal word - s39_vceqg,//vector compare equal double word - s39_vceqgs,//vector compare equal double word - s39_vceqh,//vector compare equal half word - s39_vceqhs,//vector compare equal half word - s39_vcfeb,// - s39_vcfpl,// - s39_vcfps,// - s39_vcgd,//vector fp convert to fixed 64 bit - s39_vcgdb,//vector fp convert to fixed 64 bit - s39_vch,//vector compare high - s39_vchb,//vector compare high byte - s39_vchbs,//vector compare high byte - s39_vchf,//vector compare high word - s39_vchfs,//vector compare high word - s39_vchg,//vector compare high double word - s39_vchgs,//vector compare high double word - s39_vchh,//vector compare high half word - s39_vchhs,//vector compare high half word - s39_vchl,//vector compare high logical - s39_vchlb,//vector compare high logical byte - s39_vchlbs,//vector compare high logical byte - s39_vchlf,//vector compare high logical word - s39_vchlfs,//vector compare high logical word - s39_vchlg,//vector compare high logical double word - s39_vchlgs,//vector compare high logical double word - s39_vchlh,//vector compare high logical half word - s39_vchlhs,//vector compare high logical half word - s39_vcksm,//vector checksum - s39_vclfeb,// - s39_vclfp,// - s39_vclgd,//vector fp convert to logical 64 bit - s39_vclgdb,//vector fp convert to logical 64 bit - s39_vclz,//vector count leading zeros - s39_vclzb,//vector count leading zeros byte - s39_vclzf,//vector count leading zeros word - s39_vclzg,//vector count leading zeros doubleword - s39_vclzh,//vector count leading zeros halfword - s39_vcp,//vector compare decimal - s39_vcsfp,// - s39_vctz,//vector count trailing zeros - s39_vctzb,//vector count trailing zeros byte - s39_vctzf,//vector count trailing zeros word - s39_vctzg,//vector count trailing zeros doubleword - s39_vctzh,//vector count trailing zeros halfword - s39_vcvb,//vector convert to binary - s39_vcvbg,//vector convert to binary - s39_vcvd,//vector convert to decimal - s39_vcvdg,//vector convert to decimal - s39_vdp,//vector divide decimal - s39_vec,//vector element compare - s39_vecb,//vector element compare byte - s39_vecf,//vector element compare word - s39_vecg,//vector element compare double word - s39_vech,//vector element compare half word - s39_vecl,//vector element compare logical - s39_veclb,//vector element compare logical byte - s39_veclf,//vector element compare logical word - s39_veclg,//vector element compare logical double word - s39_veclh,//vector element compare logical half word - s39_verim,//vector element rotate and insert under mask - s39_verimb,//vector element rotate and insert under mask byte - s39_verimf,//vector element rotate and insert under mask word - s39_verimg,//vector element rotate and insert under mask doubleword - s39_verimh,//vector element rotate and insert under mask halfword - s39_verll,//vector element rotate left logical - s39_verllb,//vector element rotate left logical byte - s39_verllf,//vector element rotate left logical word - s39_verllg,//vector element rotate left logical doubleword - s39_verllh,//vector element rotate left logical halfword - s39_verllv,//vector element rotate left logical - s39_verllvb,//vector element rotate left logical byte - s39_verllvf,//vector element rotate left logical word - s39_verllvg,//vector element rotate left logical doubleword - s39_verllvh,//vector element rotate left logical halfword - s39_vesl,//vector element shift left - s39_veslb,//vector element shift left byte - s39_veslf,//vector element shift left word - s39_veslg,//vector element shift left doubleword - s39_veslh,//vector element shift left halfword - s39_veslv,//vector element shift left - s39_veslvb,//vector element shift left byte - s39_veslvf,//vector element shift left word - s39_veslvg,//vector element shift left doubleword - s39_veslvh,//vector element shift left halfword - s39_vesra,//vector element shift right arithmetic - s39_vesrab,//vector element shift right arithmetic byte - s39_vesraf,//vector element shift right arithmetic word - s39_vesrag,//vector element shift right arithmetic doubleword - s39_vesrah,//vector element shift right arithmetic halfword - s39_vesrav,//vector element shift right arithmetic - s39_vesravb,//vector element shift right arithmetic byte - s39_vesravf,//vector element shift right arithmetic word - s39_vesravg,//vector element shift right arithmetic doubleword - s39_vesravh,//vector element shift right arithmetic halfword - s39_vesrl,//vector element shift right logical - s39_vesrlb,//vector element shift right logical byte - s39_vesrlf,//vector element shift right logical word - s39_vesrlg,//vector element shift right logical doubleword - s39_vesrlh,//vector element shift right logical halfword - s39_vesrlv,//vector element shift right logical - s39_vesrlvb,//vector element shift right logical byte - s39_vesrlvf,//vector element shift right logical word - s39_vesrlvg,//vector element shift right logical doubleword - s39_vesrlvh,//vector element shift right logical halfword - s39_vfa,//vector fp add - s39_vfadb,//vector fp add long - s39_vfae,//vector find any element equal - s39_vfaeb,//vector find any element equal byte - s39_vfaebs,//vector find any element equal - s39_vfaef,//vector find any element equal word - s39_vfaefs,//vector find any element equal - s39_vfaeh,//vector find any element equal halfword - s39_vfaehs,//vector find any element equal - s39_vfaezb,//vector find any element equal - s39_vfaezbs,//vector find any element equal - s39_vfaezf,//vector find any element equal - s39_vfaezfs,//vector find any element equal - s39_vfaezh,//vector find any element equal - s39_vfaezhs,//vector find any element equal - s39_vfasb,//vector fp add short - s39_vfce,//vector fp compare equal - s39_vfcedb,//vector fp compare equal long - s39_vfcedbs,//vector fp compare equal long - s39_vfcesb,//vector fp compare equal short - s39_vfcesbs,//vector fp compare equal short - s39_vfch,//vector fp compare high - s39_vfchdb,//vector fp compare high long - s39_vfchdbs,//vector fp compare high long - s39_vfche,//vector fp compare high or equal - s39_vfchedb,//vector fp compare high or equal long - s39_vfchedbs,//vector fp compare high or equal long - s39_vfchesb,//vector fp compare high or equal short - s39_vfchesbs,//vector fp compare high or equal short - s39_vfchsb,//vector fp compare high short - s39_vfchsbs,//vector fp compare high short - s39_vfd,//vector fp divide - s39_vfddb,//vector fp divide long - s39_vfdsb,//vector fp divide short - s39_vfee,//vector find element equal - s39_vfeeb,//vector find element equal byte - s39_vfeebs,//vector find element equal byte - s39_vfeef,//vector find element equal word - s39_vfeefs,//vector find element equal word - s39_vfeeh,//vector find element equal halfword - s39_vfeehs,//vector find element equal halfword - s39_vfeezb,//vector find element equal byte - s39_vfeezbs,//vector find element equal byte - s39_vfeezf,//vector find element equal word - s39_vfeezfs,//vector find element equal word - s39_vfeezh,//vector find element equal halfword - s39_vfeezhs,//vector find element equal halfword - s39_vfene,//vector find element not equal - s39_vfeneb,//vector find element not equal byte - s39_vfenebs,//vector find element not equal byte - s39_vfenef,//vector find element not equal word - s39_vfenefs,//vector find element not equal word - s39_vfeneh,//vector find element not equal halfword - s39_vfenehs,//vector find element not equal halfword - s39_vfenezb,//vector find element not equal byte - s39_vfenezbs,//vector find element not equal byte - s39_vfenezf,//vector find element not equal word - s39_vfenezfs,//vector find element not equal word - s39_vfenezh,//vector find element not equal halfword - s39_vfenezhs,//vector find element not equal halfword - s39_vfi,//vector load fp integer - s39_vfidb,//vector load fp integer long - s39_vfisb,//vector load fp integer short - s39_vfkedb,//vector fp compare and signal equal long - s39_vfkedbs,//vector fp compare and signal equal long - s39_vfkesb,//vector fp compare and signal equal short - s39_vfkesbs,//vector fp compare and signal equal short - s39_vfkhdb,//vector fp compare and signal high long - s39_vfkhdbs,//vector fp compare and signal high long - s39_vfkhedb,//vector fp compare and signal high or equal long - s39_vfkhedbs,//vector fp compare and signal high or equal long - s39_vfkhesb,//vector fp compare and signal high or equal short - s39_vfkhesbs,//vector fp compare and signal high or equal short - s39_vfkhsb,//vector fp compare and signal high short - s39_vfkhsbs,//vector fp compare and signal high short - s39_vflcdb,//vector fp perform sign operation long - s39_vflcsb,//vector fp perform sign operation short - s39_vfll,//vector fp load lengthened - s39_vflls,//vector fp load lengthened - s39_vflndb,//vector fp perform sign operation long - s39_vflnsb,//vector fp perform sign operation short - s39_vflpdb,//vector fp perform sign operation long - s39_vflpsb,//vector fp perform sign operation short - s39_vflr,//vector fp load rounded - s39_vflrd,//vector fp load rounded long - s39_vfm,//vector fp multiply - s39_vfma,//vector fp multiply and add - s39_vfmadb,//vector fp multiply and add long - s39_vfmasb,//vector fp multiply and add short - s39_vfmax,//vector fp maximum - s39_vfmaxdb,//vector fp maximum long - s39_vfmaxsb,//vector fp maximum short - s39_vfmdb,//vector fp multiply long - s39_vfmin,//vector fp minimum - s39_vfmindb,//vector fp minimum long - s39_vfminsb,//vector fp minimum short - s39_vfms,//vector fp multiply and subtract - s39_vfmsb,//vector fp multiply short - s39_vfmsdb,//vector fp multiply and subtract long - s39_vfmssb,//vector fp multiply and subtract short - s39_vfnma,//vector fp negative multiply and add - s39_vfnmadb,//vector fp negative multiply and add long - s39_vfnmasb,//vector fp negative multiply and add short - s39_vfnms,//vector fp negative multiply and subtract - s39_vfnmsdb,//vector fp negative multiply and subtract long - s39_vfnmssb,//vector fp negative multiply and subtract short - s39_vfpso,//vector fp perform sign operation - s39_vfpsodb,//vector fp perform sign operation long - s39_vfpsosb,//vector fp perform sign operation short - s39_vfs,//vector fp subtract - s39_vfsdb,//vector fp subtract long - s39_vfsq,//vector fp square root - s39_vfsqdb,//vector fp square root long - s39_vfsqsb,//vector fp square root short - s39_vfssb,//vector fp subtract short - s39_vftci,//vector fp test data class immediate - s39_vftcidb,//vector fp test data class immediate - s39_vftcisb,//vector fp test data class immediate short - s39_vgbm,//vector generate byte mask - s39_vgef,//vector gather element (32) - s39_vgeg,//vector gather element (64) - s39_vgfm,//vector galois field multiply sum - s39_vgfma,//vector galois field multiply sum and accumulate - s39_vgfmab,//vector galois field multiply sum and accumulate byte - s39_vgfmaf,//vector galois field multiply sum and accumulate word - s39_vgfmag,//vector galois field multiply sum and accumulate doubleword - s39_vgfmah,//vector galois field multiply sum and accumulate halfword - s39_vgfmb,//vector galois field multiply sum byte - s39_vgfmf,//vector galois field multiply sum word - s39_vgfmg,//vector galois field multiply sum doubleword - s39_vgfmh,//vector galois field multiply sum halfword - s39_vgm,//vector generate mask - s39_vgmb,//vector generate mask byte - s39_vgmf,//vector generate mask word - s39_vgmg,//vector generate mask double word - s39_vgmh,//vector generate mask halfword - s39_vistr,//vector isolate string - s39_vistrb,//vector isolate string byte - s39_vistrbs,//vector isolate string byte - s39_vistrf,//vector isolate string word - s39_vistrfs,//vector isolate string word - s39_vistrh,//vector isolate string halfword - s39_vistrhs,//vector isolate string halfword - s39_vl,//vector load - s39_vlbb,//vector load to block boundary - s39_vlbr,// - s39_vlbrf,// - s39_vlbrg,// - s39_vlbrh,// - s39_vlbrq,// - s39_vlbrrep,// - s39_vlbrrepf,// - s39_vlbrrepg,// - s39_vlbrreph,// - s39_vlc,//vector load complement - s39_vlcb,//vector load complement byte - s39_vlcf,//vector load complement word - s39_vlcg,//vector load complement doubleword - s39_vlch,//vector load complement halfword - s39_vlde,//vector fp load lengthened - s39_vldeb,//vector fp load lengthened short to long - s39_vleb,//vector load byte element - s39_vlebrf,// - s39_vlebrg,// - s39_vlebrh,// - s39_vled,//vector fp load rounded - s39_vledb,//vector fp load rounded long to short - s39_vlef,//vector load element (32) - s39_vleg,//vector load element (64) - s39_vleh,//vector load element (16) - s39_vleib,//vector load element immediate (8) - s39_vleif,//vector load element immediate (32) - s39_vleig,//vector load element immediate (64) - s39_vleih,//vector load element immediate (16) - s39_vler,// - s39_vlerf,// - s39_vlerg,// - s39_vlerh,// - s39_vlgv,//vector load gr from vr element - s39_vlgvb,//vector load gr from vr byte element - s39_vlgvf,//vector load gr from vr word element - s39_vlgvg,//vector load gr from vr double word element - s39_vlgvh,//vector load gr from vr halfword element - s39_vlip,//vector load immediate decimal - s39_vll,//vector load with length - s39_vllebrz,// - s39_vllebrze,// - s39_vllebrzf,// - s39_vllebrzg,// - s39_vllebrzh,// - s39_vllez,//vector load logical element and zero - s39_vllezb,//vector load logical byte element and zero - s39_vllezf,//vector load logical word element and zero - s39_vllezg,//vector load logical double word element and zero - s39_vllezh,//vector load logical halfword element and zero - s39_vllezlf,//vector load logical word element and zero - left aligned - s39_vlm,//vector load multiple - s39_vlp,//vector load positive - s39_vlpb,//vector load positive byte - s39_vlpf,//vector load positive word - s39_vlpg,//vector load positive doubleword - s39_vlph,//vector load positive halfword - s39_vlr,//vector load - s39_vlrep,//vector load and replicate - s39_vlrepb,//vector load and replicate byte elements - s39_vlrepf,//vector load and replicate word elements - s39_vlrepg,//vector load and replicate double word elements - s39_vlreph,//vector load and replicate halfword elements - s39_vlrl,//vector load rightmost with immediate length - s39_vlrlr,//vector load rightmost with immediate length - s39_vlvg,//vector load VR element from GR - s39_vlvgb,//vector load VR byte element from GR - s39_vlvgf,//vector load VR word element from GR - s39_vlvgg,//vector load VR double word element from GR - s39_vlvgh,//vector load VR halfword element from GR - s39_vlvgp,//vector load VR from GRs disjoint - s39_vmae,//vector multiply and add even - s39_vmaeb,//vector multiply and add even byte - s39_vmaef,//vector multiply and add even word - s39_vmaeh,//vector multiply and add even halfword - s39_vmah,//vector multiply and add high - s39_vmahb,//vector multiply and add high byte - s39_vmahf,//vector multiply and add high word - s39_vmahh,//vector multiply and add high halfword - s39_vmal,//vector multiply and add low - s39_vmalb,//vector multiply and add low byte - s39_vmale,//vector multiply and add logical even - s39_vmaleb,//vector multiply and add logical even byte - s39_vmalef,//vector multiply and add logical even word - s39_vmaleh,//vector multiply and add logical even halfword - s39_vmalf,//vector multiply and add low word - s39_vmalh,//vector multiply and add logical high - s39_vmalhb,//vector multiply and add logical high byte - s39_vmalhf,//vector multiply and add logical high word - s39_vmalhh,//vector multiply and add logical high halfword - s39_vmalhw,//vector multiply and add low halfword - s39_vmalo,//vector multiply and add logical odd - s39_vmalob,//vector multiply and add logical odd byte - s39_vmalof,//vector multiply and add logical odd word - s39_vmaloh,//vector multiply and add logical odd halfword - s39_vmao,//vector multiply and add odd - s39_vmaob,//vector multiply and add odd byte - s39_vmaof,//vector multiply and add odd word - s39_vmaoh,//vector multiply and add odd halfword - s39_vme,//vector multiply even - s39_vmeb,//vector multiply even byte - s39_vmef,//vector multiply even word - s39_vmeh,//vector multiply even halfword - s39_vmh,//vector multiply high - s39_vmhb,//vector multiply high byte - s39_vmhf,//vector multiply high word - s39_vmhh,//vector multiply high halfword - s39_vml,//vector multiply low - s39_vmlb,//vector multiply low byte - s39_vmle,//vector multiply logical even - s39_vmleb,//vector multiply logical even byte - s39_vmlef,//vector multiply logical even word - s39_vmleh,//vector multiply logical even halfword - s39_vmlf,//vector multiply low word - s39_vmlh,//vector multiply logical high - s39_vmlhb,//vector multiply logical high byte - s39_vmlhf,//vector multiply logical high word - s39_vmlhh,//vector multiply logical high halfword - s39_vmlhw,//vector multiply low halfword - s39_vmlo,//vector multiply logical odd - s39_vmlob,//vector multiply logical odd byte - s39_vmlof,//vector multiply logical odd word - s39_vmloh,//vector multiply logical odd halfword - s39_vmn,//vector minimum - s39_vmnb,//vector minimum byte - s39_vmnf,//vector minimum word - s39_vmng,//vector minimum doubleword - s39_vmnh,//vector minimum halfword - s39_vmnl,//vector minimum logical - s39_vmnlb,//vector minimum logical byte - s39_vmnlf,//vector minimum logical word - s39_vmnlg,//vector minimum logical doubleword - s39_vmnlh,//vector minimum logical halfword - s39_vmo,//vector multiply odd - s39_vmob,//vector multiply odd byte - s39_vmof,//vector multiply odd word - s39_vmoh,//vector multiply odd halfword - s39_vmp,//vector multiply decimal - s39_vmrh,//vector merge high - s39_vmrhb,//vector merge high byte - s39_vmrhf,//vector merge high word - s39_vmrhg,//vector merge high double word - s39_vmrhh,//vector merge high halfword - s39_vmrl,//vector merge low - s39_vmrlb,//vector merge low byte - s39_vmrlf,//vector merge low word - s39_vmrlg,//vector merge low double word - s39_vmrlh,//vector merge low halfword - s39_vmsl,//vector multiply sum logical - s39_vmslg,//vector multiply sum logical double word - s39_vmsp,//vector multiply and shift decimal - s39_vmx,//vector maximum - s39_vmxb,//vector maximum byte - s39_vmxf,//vector maximum word - s39_vmxg,//vector maximum doubleword - s39_vmxh,//vector maximum halfword - s39_vmxl,//vector maximum logical - s39_vmxlb,//vector maximum logical byte - s39_vmxlf,//vector maximum logical word - s39_vmxlg,//vector maximum logical doubleword - s39_vmxlh,//vector maximum logical halfword - s39_vn,//vector and - s39_vnc,//vector and with complement - s39_vnn,//vector nand - s39_vno,//vector nor - s39_vnot,//vector not - s39_vnx,//vector not exclusive or - s39_vo,//vector or - s39_voc,//vector or with complement - s39_vone,//vector set to ones - s39_vpdi,//vector permute double word immediate - s39_vperm,//vector permute - s39_vpk,//vector pack - s39_vpkf,//vector pack word - s39_vpkg,//vector pack double word - s39_vpkh,//vector pack halfword - s39_vpkls,//vector pack logical saturate - s39_vpklsf,//vector pack logical saturate word - s39_vpklsfs,//vector pack logical saturate word - s39_vpklsg,//vector pack logical saturate double word - s39_vpklsgs,//vector pack logical saturate double word - s39_vpklsh,//vector pack logical saturate halfword - s39_vpklshs,//vector pack logical saturate halfword - s39_vpks,//vector pack saturate - s39_vpksf,//vector pack saturate word - s39_vpksfs,//vector pack saturate word - s39_vpksg,//vector pack saturate double word - s39_vpksgs,//vector pack saturate double word - s39_vpksh,//vector pack saturate halfword - s39_vpkshs,//vector pack saturate halfword - s39_vpkz,//vector pack zoned - s39_vpopct,//vector population count - s39_vpopctb,//vector population count byte - s39_vpopctf,//vector population count word - s39_vpopctg,//vector population count double word - s39_vpopcth,//vector population count halfword - s39_vpsop,//vector perform sign operation decimal - s39_vrep,//vector replicate - s39_vrepb,//vector replicate byte - s39_vrepf,//vector replicate word - s39_vrepg,//vector replicate double word - s39_vreph,//vector replicate halfword - s39_vrepi,//vector replicate immediate - s39_vrepib,//vector replicate immediate byte - s39_vrepif,//vector replicate immediate word - s39_vrepig,//vector replicate immediate double word - s39_vrepih,//vector replicate immediate halfword - s39_vrp,//vector remainder decimal - s39_vs,//vector subtract - s39_vsb,//vector subtract byte - s39_vsbcbi,//vector subtract with borrow compute borrow indication - s39_vsbcbiq,//vector subtract with borrow compute borrow indication quadword - s39_vsbi,//vector subtract with borrow indication - s39_vsbiq,//vector subtract with borrow indication quadword - s39_vscbi,//vector subtract compute borrow indication - s39_vscbib,//vector subtract compute borrow indication byte - s39_vscbif,//vector subtract compute borrow indication word - s39_vscbig,//vector subtract compute borrow indication doubleword - s39_vscbih,//vector subtract compute borrow indication halfword - s39_vscbiq,//vector subtract compute borrow indication quadword - s39_vscef,//vector scatter element (32) - s39_vsceg,//vector scatter element (64) - s39_vsdp,//vector shift and divide decimal - s39_vseg,//vector sign extend to double word - s39_vsegb,//vector sign extend byte to double word - s39_vsegf,//vector sign extend word to double word - s39_vsegh,//vector sign extend halfword to double word - s39_vsel,//vector select - s39_vsf,//vector subtract word - s39_vsg,//vector subtract doubleword - s39_vsh,//vector subtract halfword - s39_vsl,//vector shift left - s39_vslb,//vector shift left by byte - s39_vsld,// - s39_vsldb,//vector shift left double by byte - s39_vsp,//vector subtract decimal - s39_vsq,//vector subtract quadword - s39_vsra,//vector shift right arithmetic - s39_vsrab,//vector shift right arithmetic by byte - s39_vsrd,// - s39_vsrl,//vector shift right logical - s39_vsrlb,//vector shift right logical by byte - s39_vsrp,//vector shift and round decimal - s39_vst,//vector store - s39_vstbr,// - s39_vstbrf,// - s39_vstbrg,// - s39_vstbrh,// - s39_vstbrq,// - s39_vsteb,//vector store element (8) - s39_vstebrf,// - s39_vstebrg,// - s39_vstebrh,// - s39_vstef,//vector store element (32) - s39_vsteg,//vector store element (64) - s39_vsteh,//vector store element (16) - s39_vster,// - s39_vsterf,// - s39_vsterg,// - s39_vsterh,// - s39_vstl,//vector store with length - s39_vstm,//vector store multiple - s39_vstrc,//vector string range compare - s39_vstrcb,//vector string range compare byte - s39_vstrcbs,//vector string range compare byte - s39_vstrcf,//vector string range compare word - s39_vstrcfs,//vector string range compare word - s39_vstrch,//vector string range compare halfword - s39_vstrchs,//vector string range compare halfword - s39_vstrczb,//vector string range compare byte - s39_vstrczbs,//vector string range compare byte - s39_vstrczf,//vector string range compare word - s39_vstrczfs,//vector string range compare word - s39_vstrczh,//vector string range compare halfword - s39_vstrczhs,//vector string range compare halfword - s39_vstrl,//vector store rightmost with length - s39_vstrlr,//vector store rightmost with length - s39_vstrs,// - s39_vstrsb,// - s39_vstrsf,// - s39_vstrsh,// - s39_vstrszb,// - s39_vstrszf,// - s39_vstrszh,// - s39_vsum,//vector sum across word - s39_vsumb,//vector sum across word - byte elements - s39_vsumg,//vector sum across doubleword - s39_vsumgf,//vector sum across doubleword - word - s39_vsumgh,//vector sum across doubleword - halfword - s39_vsumh,//vector sum across word - halfword elements - s39_vsumq,//vector sum across quadword - s39_vsumqf,//vector sum across quadword - word elements - s39_vsumqg,//vector sum across quadword - doubleword elements - s39_vtm,//vector test under mask - s39_vtp,//vector test decimal - s39_vuph,//vector unpack high - s39_vuphb,//vector unpack high byte - s39_vuphf,//vector unpack high word - s39_vuphh,//vector unpack high halfword - s39_vupkz,//vector unpack zoned - s39_vupl,//vector unpack low - s39_vuplb,//vector unpack low byte - s39_vuplf,//vector unpack low word - s39_vuplh,//vector unpack logical high - s39_vuplhb,//vector unpack logical high byte - s39_vuplhf,//vector unpack logical high word - s39_vuplhh,//vector unpack logical high halfword - s39_vuplhw,//vector unpack low halfword - s39_vupll,//vector unpack logical low - s39_vupllb,//vector unpack logical low byte - s39_vupllf,//vector unpack logical low word - s39_vupllh,//vector unpack logical low halfword - s39_vzero,//vector set to zero - s39_wcdgb,//vector fp convert from fixed 64 bit - s39_wcdlgb,//vector fp convert from logical 64 bit - s39_wcefb,// - s39_wcelfb,// - s39_wcfeb,// - s39_wcgdb,//vector fp convert to fixed 64 bit - s39_wclfeb,// - s39_wclgdb,//vector fp convert to logical 64 bit - s39_wfadb,//vector fp add long - s39_wfasb,//scalar vector fp add scalar short - s39_wfaxb,//scalar vector fp add scalar extended - s39_wfc,//vector fp compare scalar - s39_wfcdb,//vector fp compare scalar long - s39_wfcedb,//vector fp compare equal long - s39_wfcedbs,//vector fp compare equal long - s39_wfcesb,//scalar vector fp compare equal scalar short - s39_wfcesbs,//scalar fp compare equal scalar short - s39_wfcexb,//scalar vector fp compare equal scalar extended - s39_wfcexbs,//scalar vector fp compare equal scalar extended - s39_wfchdb,//vector fp compare high long - s39_wfchdbs,//vector fp compare high long - s39_wfchedb,//vector fp compare high or equal long - s39_wfchedbs,//vector fp compare high or equal long - s39_wfchesb,//scalar vector fp compare high or equal scalar short - s39_wfchesbs,//scalar vector fp compare high or equal scalar short - s39_wfchexb,//scalar vector fp compare high or equal scalar extended - s39_wfchexbs,//scalar vector fp compare high or equal scalar extended - s39_wfchsb,//scalar vector fp compare high scalar short - s39_wfchsbs,//scalar vector fp compare high scalar short - s39_wfchxb,//scalar vector fp compare high scalar extended - s39_wfchxbs,//scalar vector fp compare high scalar extended - s39_wfcsb,//scalar vector fp compare scalar short - s39_wfcxb,//scalar vector fp compare scalar extended - s39_wfddb,//vector fp divide long - s39_wfdsb,//scalar vector fp divide scalar short - s39_wfdxb,//scalar vector fp divide scalar extended - s39_wfidb,//vector load fp integer long - s39_wfisb,//scalar vector load fp integer scalar short - s39_wfixb,//scalar vector load fp integer scalar extended - s39_wfk,//vector fp compare and signal scalar - s39_wfkdb,//vector fp compare and signal scalar long - s39_wfkedb,//vector fp compare and signal equal long - s39_wfkedbs,//vector fp compare and signal equal long - s39_wfkesb,//scalar vector fp compare and signal equal scalar short - s39_wfkesbs,//scalar fp compare and signal equal scalar short - s39_wfkexb,//scalar vector fp compare and signal equal scalar extended - s39_wfkexbs,//scalar vector fp compare and signal equal scalar extended - s39_wfkhdb,//vector fp compare and signal high long - s39_wfkhdbs,//vector fp compare and signal high long - s39_wfkhedb,//vector fp compare and signal high or equal long - s39_wfkhedbs,//vector fp compare and signal high or equal long - s39_wfkhesb,//scalar vector fp compare and signal high or equal scalar short - s39_wfkhesbs,//scalar vector fp compare and signal high or equal scalar short - s39_wfkhexb,//scalar vector fp compare and signal high or equal scalar extended - s39_wfkhexbs,//scalar vector fp compare and signal high or equal scalar extended - s39_wfkhsb,//scalar vector fp compare and signal high scalar short - s39_wfkhsbs,//scalar vector fp compare and signal high scalar short - s39_wfkhxb,//scalar vector fp compare and signal high scalar extended - s39_wfkhxbs,//scalar vector fp compare and signal high scalar extended - s39_wfksb,//scalar vector fp compare and signal scalar short - s39_wfkxb,//scalar vector fp compare and signal scalar extended - s39_wflcdb,//vector fp perform sign operation long - s39_wflcsb,//scalar vector fp perform sign operation scalar short - s39_wflcxb,//scalar vector fp perform sign operation scalar extended - s39_wflld,//scalar vector fp load lengthened long - s39_wflls,//scalar vector fp load lengthened short - s39_wflndb,//vector fp perform sign operation long - s39_wflnsb,//scalar vector fp perform sign operation scalar short - s39_wflnxb,//scalar vector fp perform sign operation scalar extended - s39_wflpdb,//vector fp perform sign operation long - s39_wflpsb,//scalar vector fp perform sign operation scalar short - s39_wflpxb,//scalar vector fp perform sign operation scalar extended - s39_wflrd,//scalar vector fp load rounded long - s39_wflrx,//scalar vector fp load rounded extended - s39_wfmadb,//vector fp multiply and add long - s39_wfmasb,//scalar vector fp multiply and add scalar short - s39_wfmaxb,//scalar vector fp multiply and add scalar extended - s39_wfmaxdb,//scalar fp maximum scalar long - s39_wfmaxsb,//scalar fp maximum scalar short - s39_wfmaxxb,//scalar fp maximum scalar extended - s39_wfmdb,//vector fp multiply long - s39_wfmindb,//scalar fp minimum scalar long - s39_wfminsb,//scalar fp minimum scalar short - s39_wfminxb,//scalar fp minimum scalar extended - s39_wfmsb,//scalar vector fp multiply scalar short - s39_wfmsdb,//vector fp multiply and subtract long - s39_wfmssb,//scalar vector fp multiply and subtract scalar short - s39_wfmsxb,//scalar vector fp multiply and subtract scalar extended - s39_wfmxb,//scalar vector fp multiply scalar extended - s39_wfnmadb,//scalar vector fp negative multiply and add scalar long - s39_wfnmasb,//scalar vector fp negative multiply and add scalar short - s39_wfnmaxb,//scalar vector fp negative multiply and add scalar extended - s39_wfnmsdb,//scalar vector fp negative multiply and subtract scalar long - s39_wfnmssb,//scalar vector fp negative multiply and subtract scalar short - s39_wfnmsxb,//scalar vector fp negative multiply and subtract scalar extended - s39_wfpsodb,//vector fp perform sign operation long - s39_wfpsosb,//scalar vector fp perform sign operation scalar short - s39_wfpsoxb,//scalar vector fp perform sign operation scalar extended - s39_wfsdb,//vector fp subtract long - s39_wfsqdb,//vector fp square root long - s39_wfsqsb,//scalar vector fp square root scalar short - s39_wfsqxb,//scalar vector fp square root scalar extended - s39_wfssb,//scalar vector fp subtract scalar short - s39_wfsxb,//scalar vector fp subtract scalar extended - s39_wftcidb,//vector fp test data class immediate - s39_wftcisb,//scalar vector fp test data class immediate scalar short - s39_wftcixb,//scalar vector fp test data class immediate scalar extended - s39_wldeb,//vector fp load lengthened short to long - s39_wledb,//vector fp load rounded long to short - s39_x,//exclusive or (32) - s39_xc,//exclusive or (character) - s39_xg,//exclusive or (64) - s39_xgr,//exclusive or (64) - s39_xgrk,//exclusive or (64) - s39_xi,//exclusive or (immediate) - s39_xihf,//exclusive or immediate (high) - s39_xilf,//exclusive or immediate (low) - s39_xiy,//exclusive or immediate (immediate) - s39_xr,//exclusive or (32) - s39_xrk,//exclusive or (32) - s39_xsch,//cancel subchannel - s39_xy,//exclusive or with long offset - s39_zap,//zero and add - s39_vx,//vector exclusive or - s39_last, -}; - diff --git a/idasdk75/include/auto.hpp b/idasdk75/include/auto.hpp deleted file mode 100644 index d15e4de..0000000 --- a/idasdk75/include/auto.hpp +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _AUTO_HPP -#define _AUTO_HPP -#include - -/*! \file auto.hpp - - \brief Functions that work with the autoanalyzer queue. - - The autoanalyzer works when IDA is not busy processing - the user keystrokes. It has several queues, each queue having - its own priority. The analyzer stops when all queues are empty. - - A queue contains addresses or address ranges. - The addresses are kept sorted by their values. - The analyzer will process all addresses from the first queue, then - switch to the second queue and so on. - There are no limitations on the size of the queues. - - This file also contains functions that deal with the IDA status - indicator and the autoanalysis indicator. - You may use these functions to change the indicator value. -*/ - -typedef int atype_t; ///< identifies an autoanalysis queue - see \ref AU_ - -/// \defgroup AU_ Autoanalysis queues -/// Names and priorities of the analyzer queues -//@{ -const atype_t - AU_NONE = 00, ///< placeholder, not used - AU_UNK = 10, ///< 0: convert to unexplored - AU_CODE = 20, ///< 1: convert to instruction - AU_WEAK = 25, ///< 2: convert to instruction (ida decision) - AU_PROC = 30, ///< 3: convert to procedure start - AU_TAIL = 35, ///< 4: add a procedure tail - AU_FCHUNK=38, ///< 5: find func chunks - AU_USED = 40, ///< 6: reanalyze - AU_TYPE = 50, ///< 7: apply type information - AU_LIBF = 60, ///< 8: apply signature to address - AU_LBF2 = 70, ///< 9: the same, second pass - AU_LBF3 = 80, ///< 10: the same, third pass - AU_CHLB = 90, ///< 11: load signature file (file name is kept separately) - AU_FINAL=200; ///< 12: final pass -//@} - - -typedef int idastate_t; ///< IDA status indicator - see \ref st_ - -/// \defgroup st_ Status indicator states -//@{ -const idastate_t - // meaning - st_Ready = 0, ///< READY: IDA is doing nothing - st_Think = 1, ///< THINKING: Autoanalysis on, the user may press keys - st_Waiting = 2, ///< WAITING: Waiting for the user input - st_Work = 3; ///< BUSY: IDA is busy -//@} - - -/// Get current state of autoanalyzer. -/// If auto_state == ::AU_NONE, IDA is currently not running the analysis -/// (it could be temporarily interrupted to perform the user's requests, for example). - -idaman atype_t ida_export get_auto_state(void); - - -/// Set current state of autoanalyzer. -/// \param new_state new state of autoanalyzer -/// \return previous state - -idaman atype_t ida_export set_auto_state(atype_t new_state); - - -/// See ::get_auto_display -struct auto_display_t -{ - atype_t type = AU_NONE; - ea_t ea = BADADDR; - idastate_t state = st_Ready; -}; - -/// Get structure which holds the autoanalysis indicator contents - -idaman bool ida_export get_auto_display(auto_display_t *auto_display); - - -/// Change autoanalysis indicator value. -/// \param ea linear address being analyzed -/// \param type autoanalysis type (see \ref AU_) - -idaman void ida_export show_auto(ea_t ea, atype_t type=AU_NONE); - - -/// Show an address on the autoanalysis indicator. -/// The address is displayed in the form " @:12345678". -/// \param ea - linear address to display - -inline void show_addr(ea_t ea) { show_auto(ea); } - - -/// Change IDA status indicator value -/// \param st - new indicator status -/// \return old indicator status - -idaman idastate_t ida_export set_ida_state(idastate_t st); - - -/// Is it allowed to create stack variables automatically?. -/// This function should be used by IDP modules before creating stack vars. - -inline bool may_create_stkvars(void) -{ - return inf_should_create_stkvars() && get_auto_state() == AU_USED; -} - - -/// Is it allowed to trace stack pointer automatically?. -/// This function should be used by IDP modules before tracing sp. - -inline bool may_trace_sp(void) -{ - if ( inf_should_trace_sp() ) - { - atype_t auto_state = get_auto_state(); - return auto_state == AU_USED; - } - return false; -} - - -/// Put range of addresses into a queue. -/// 'start' may be higher than 'end', the kernel will swap them in this case. -/// 'end' doesn't belong to the range. - -idaman void ida_export auto_mark_range(ea_t start,ea_t end,atype_t type); - - -/// Put single address into a queue. Queues keep addresses sorted. - -inline void auto_mark(ea_t ea, atype_t type) -{ - auto_mark_range(ea, ea+1, type); -} - - -/// Remove range of addresses from a queue. -/// 'start' may be higher than 'end', the kernel will swap them in this case. -/// 'end' doesn't belong to the range. - -idaman void ida_export auto_unmark(ea_t start, ea_t end, atype_t type); - -// Convenience functions - -/// Plan to perform reanalysis -inline void plan_ea(ea_t ea) -{ - auto_mark(ea, AU_USED); -} -/// Plan to perform reanalysis -inline void plan_range(ea_t sEA, ea_t eEA) -{ - auto_mark_range(sEA, eEA, AU_USED); -} -/// Plan to make code -inline void auto_make_code(ea_t ea) -{ - auto_mark(ea, AU_CODE); -} -/// Plan to make code&function -inline void auto_make_proc(ea_t ea) -{ - auto_make_code(ea); - auto_mark(ea, AU_PROC); -} - -/// Plan to reanalyze callers of the specified address. -/// This function will add to ::AU_USED queue all instructions that -/// call (not jump to) the specified address. -/// \param ea linear address of callee -/// \param noret !=0: the callee doesn't return, mark to undefine subsequent -/// instructions in the caller. 0: do nothing. - -idaman void ida_export reanalyze_callers(ea_t ea, bool noret); - - -/// Delete all analysis info that IDA generated for for the given range - -idaman void ida_export revert_ida_decisions(ea_t ea1, ea_t ea2); - - -/// Plan to apply the callee's type to the calling point - -idaman void ida_export auto_apply_type(ea_t caller, ea_t callee); - -/// Plan to apply the tail_ea chunk to the parent -/// \param tail_ea linear address of start of tail -/// \param parent_ea linear address within parent. If BADADDR, automatically -/// try to find parent via xrefs. - -idaman void ida_export auto_apply_tail(ea_t tail_ea, ea_t parent_ea); - -/// Analyze the specified range. -/// Try to create instructions where possible. -/// Make the final pass over the specified range if specified. -/// This function doesn't return until the range is analyzed. -/// \retval 1 ok -/// \retval 0 Ctrl-Break was pressed - -idaman int ida_export plan_and_wait(ea_t ea1, ea_t ea2, bool final_pass=true); - - -/// Process everything in the queues and return true. -/// \return false if the user clicked cancel. -/// (the wait box must be displayed by the caller if desired) - -idaman bool ida_export auto_wait(void); - - -/// Process everything in the specified range and return true. -/// \return number of autoanalysis steps made. -1 if the user clicked cancel. -/// (the wait box must be displayed by the caller if desired) - -idaman ssize_t ida_export auto_wait_range(ea_t ea1, ea_t ea2); - - -/// Analyze one address in the specified range and return true. -/// \return if processed anything. false means that there is nothing to -/// process in the specified range. - -idaman bool ida_export auto_make_step(ea_t ea1, ea_t ea2); - - -/// Remove an address range (ea1..ea2) from queues ::AU_CODE, ::AU_PROC, ::AU_USED. -/// To remove an address range from other queues use auto_unmark() function. -/// 'ea1' may be higher than 'ea2', the kernel will swap them in this case. -/// 'ea2' doesn't belong to the range. - -idaman void ida_export auto_cancel(ea_t ea1, ea_t ea2); - - -/// Are all queues empty? -/// (i.e. has autoanalysis finished?). - -idaman bool ida_export auto_is_ok(void); - - -/// Peek into a queue 'type' for an address not lower than 'low_ea'. -/// Do not remove address from the queue. -/// \return the address or #BADADDR - -idaman ea_t ida_export peek_auto_queue(ea_t low_ea, atype_t type); - - -/// Retrieve an address from queues regarding their priority. -/// Returns #BADADDR if no addresses not lower than 'lowEA' and less than -/// 'highEA' are found in the queues. -/// Otherwise *type will have queue type. - -idaman ea_t ida_export auto_get(atype_t *type, ea_t lowEA, ea_t highEA); - - -/// Try to create instruction -/// \param ea linear address of callee -/// \return the length of the instruction or 0 - -idaman int ida_export auto_recreate_insn(ea_t ea); - - -/// Get autoanalyzer state - -idaman bool ida_export is_auto_enabled(void); - - -/// Temporarily enable/disable autoanalyzer. Not user-facing, but rather because -/// IDA sometimes need to turn AA on/off regardless of inf.s_genflags:INFFL_AUTO -/// \return old state - -idaman bool ida_export enable_auto(bool enable); - - - -#endif // _AUTO_HPP diff --git a/idasdk75/include/bytes.hpp b/idasdk75/include/bytes.hpp deleted file mode 100644 index 05a0f02..0000000 --- a/idasdk75/include/bytes.hpp +++ /dev/null @@ -1,2495 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef BYTES_HPP -#define BYTES_HPP - -#include -#include -#include - -typedef tid_t enum_t; // #include -class insn_t; - -/*! \file bytes.hpp - - \brief Contains functions that deal with individual byte characteristics. - - Each byte of the disassembled program is represented by a 32-bit - value. We will call this value 'flags'. The structure of the flags is - here. - - You are not allowed to inspect individual bits of flags and modify them directly. - Use special functions to inspect and/or modify flags. - - Flags are kept in a virtual array file (*.id1). - Addresses (ea) are all 32-bit (or 64-bit) quantities. -*/ - -//-------------------------------------------------------------------------- -/// Allocate flags for address range. -/// This function does not change the storage type of existing ranges. -/// Exit with an error message if not enough disk space. -/// \param start_ea should be lower than end_ea. -/// \param end_ea does not belong to the range. -/// \param stt ::storage_type_t -/// \return 0 if ok, otherwise an error code - -idaman error_t ida_export enable_flags(ea_t start_ea, ea_t end_ea, storage_type_t stt); - - -/// Deallocate flags for address range. -/// Exit with an error message if not enough disk space (this may occur too). -/// \param start_ea should be lower than end_ea. -/// \param end_ea does not belong to the range. -/// \return 0 if ok, otherwise return error code - -idaman error_t ida_export disable_flags(ea_t start_ea, ea_t end_ea); - - -/// Change flag storage type for address range. -/// \param start_ea should be lower than end_ea. -/// \param end_ea does not belong to the range. -/// \param stt ::storage_type_t -/// \return error code - -idaman error_t ida_export change_storage_type(ea_t start_ea, ea_t end_ea, storage_type_t stt); - - -/// Get next address in the program (i.e. next address which has flags). -/// \return #BADADDR if no such address exist. - -idaman ea_t ida_export next_addr(ea_t ea); - - -/// Get previous address in the program. -/// \return #BADADDR if no such address exist. - -idaman ea_t ida_export prev_addr(ea_t ea); - - -/// Get the first address of next contiguous chunk in the program. -/// \return #BADADDR if next chunk doesn't exist. - -idaman ea_t ida_export next_chunk(ea_t ea); - - -/// Get the last address of previous contiguous chunk in the program. -/// \return #BADADDR if previous chunk doesn't exist. - -idaman ea_t ida_export prev_chunk(ea_t ea); - - -/// Get start of the contiguous address block containing 'ea'. -/// \return #BADADDR if 'ea' doesn't belong to the program. - -idaman ea_t ida_export chunk_start(ea_t ea); - - -/// Get size of the contiguous address block containing 'ea'. -/// \return 0 if 'ea' doesn't belong to the program. - -idaman asize_t ida_export chunk_size(ea_t ea); - - -/// Search for a hole in the addressing space of the program. -/// \param bottom address to start searching -/// \param size size of desired block -/// \param step bit mask for the start of hole (0xF would align hole to a paragraph). -/// if 'step' is negative, the bottom address with be aligned. -/// otherwise the kernel will try to use it as is and align it -/// only when the hole is too small. -/// \return start of the hole or #BADADDR - -idaman ea_t ida_export free_chunk(ea_t bottom, asize_t size, int32 step); - - -/// Flag tester - see next_that(), prev_that() -typedef bool idaapi testf_t(flags_t flags, void *ud); - - -/// Find next address with a flag satisfying the function 'testf'. -/// \note do not pass is_unknown() to this function to find unexplored bytes. -/// It will fail under the debugger. To find unexplored bytes, use next_unknown(). -/// \param ea start searching at this address + 1 -/// \param maxea not included in the search range. -/// \param testf test function to find next address -/// \param ud user data - may point to anything. it will be passed to testf. -/// \return the found address or #BADADDR. - -idaman ea_t ida_export next_that( - ea_t ea, - ea_t maxea, - testf_t *testf, - void *ud=nullptr); - - -/// Similar to next_that(), but will find the next address that is unexplored - -inline ea_t idaapi next_unknown(ea_t ea, ea_t maxea) -{ - return next_that(ea, maxea, nullptr); -} - - -/// Find previous address with a flag satisfying the function 'testf'. -/// \note do not pass is_unknown() to this function to find unexplored bytes -/// It will fail under the debugger. To find unexplored bytes, use prev_unknown(). -/// \param ea start searching from this address - 1. -/// \param minea included in the search range. -/// \param testf test function to find previous address -/// \param ud user data - may point to anything. it will be passed to testf. -/// \return the found address or #BADADDR. - -idaman ea_t ida_export prev_that( - ea_t ea, - ea_t minea, - testf_t *testf, - void *ud=nullptr); - - -/// Similar to prev_that(), but will find the previous address that is unexplored - -inline ea_t idaapi prev_unknown(ea_t ea, ea_t minea) -{ - return prev_that(ea, minea, nullptr); -} - - -/// Get start of previous defined item. -/// \param ea begin search at this address -/// \param minea included in the search range -/// \return #BADADDR if none exists. - -idaman ea_t ida_export prev_head(ea_t ea, ea_t minea); - - -/// Get start of next defined item. -/// \param ea begin search at this address -/// \param maxea not included in the search range -/// \return #BADADDR if none exists. - -idaman ea_t ida_export next_head(ea_t ea, ea_t maxea); - - -/// Get address of previous non-tail byte. -/// \return #BADADDR if none exists. - -idaman ea_t ida_export prev_not_tail(ea_t ea); - - -/// Get address of next non-tail byte. -/// \return #BADADDR if none exists. - -idaman ea_t ida_export next_not_tail(ea_t ea); - - -/// Adjust the address and get the nearest visible address. -/// (i.e. an address which will appear in the disassembly) -/// \return #BADADDR only if no addresses are valid - -ea_t adjust_visea(ea_t ea); - - -/// Get previous visible address. -/// \return #BADADDR if none exists. - -idaman ea_t ida_export prev_visea(ea_t ea); - - -/// Get next visible address. -/// \return #BADADDR if none exists. - -idaman ea_t ida_export next_visea(ea_t ea); - - -/// Is an address the first visible address? - -bool is_first_visea(ea_t ea); - - -/// Is an address the last visible address? - -bool is_last_visea(ea_t ea); - - -/// Is the address visible on the screen (not hidden)? - -bool is_visible_finally(ea_t ea); // do we need to show anything - // at this address? - - - -/// Get the start address of the item at 'ea'. -/// If there is no current item, then 'ea' will be returned -/// (see definition at the end of bytes.hpp source) - -inline ea_t idaapi get_item_head(ea_t ea); - - -/// Get the end address of the item at 'ea'. The returned address -/// doesn't belong to the current item. Unexplored bytes are counted as -/// 1 byte entities. - -idaman ea_t ida_export get_item_end(ea_t ea); - - -/// Calculate maximal reasonable end address of a new item. -/// This function will limit the item with the current segment bounds. -/// \param ea linear address -/// \param how when to stop the search. A combination of \ref ITEM_END_ -/// \return end of new item. If it is not possible to create an item, -/// it will return 'ea'. - -idaman ea_t ida_export calc_max_item_end(ea_t ea, int how=15); -/// \defgroup ITEM_END_ Item end search flags -/// passed as 'how' parameter to calc_max_item_end() -//@{ -#define ITEM_END_FIXUP 0x0001 ///< stop at the first fixup -#define ITEM_END_INITED 0x0002 ///< stop when initialization changes - ///< i.e. - ///< - if is_loaded(ea): stop if uninitialized byte is encountered - ///< - if !is_loaded(ea): stop if initialized byte is encountered -#define ITEM_END_NAME 0x0004 ///< stop at the first named location -#define ITEM_END_XREF 0x0008 ///< stop at the first referenced location -//@} - - -/// Get size of item (instruction/data) in bytes. -/// Unexplored bytes have length of 1 byte. This function never returns 0. - -inline asize_t get_item_size(ea_t ea) { return get_item_end(ea) - ea; } - - - - -/// Is the specified address 'ea' present in the program? - -idaman bool ida_export is_mapped(ea_t ea); - - -/// Get flags for the specified address, extended form - -idaman flags_t ida_export get_flags_ex(ea_t ea, int how); - -#define GFE_VALUE 0x0001 ///< get flags with #FF_IVL & #MS_VAL. - ///< It is much slower under remote debugging - ///< because the kernel needs to read - ///< the process memory. - -/// \copydoc GFE_VALUE -inline flags_t idaapi get_flags(ea_t ea) { return get_flags_ex(ea, 0); } - - -/// Get flags value for address 'ea'. -/// \return 0 if address is not present in the program - -inline flags_t idaapi get_full_flags(ea_t ea) { return get_flags_ex(ea, GFE_VALUE); } - - -/// Get flag of the item at 'ea' even if it is a tail byte of some -/// array or structure. This function is used to get flags of structure members -/// or array elements. -/// \param from linear address of the instruction which refers to 'ea' -/// \param n number of operand which refers to 'ea' -/// \param ea the referenced address -/// \param appzero append a struct field name if the field offset is zero? -/// meaningful only if the name refers to a structure. -/// \return flags or 0 (if failed) - -idaman flags_t ida_export get_item_flag(ea_t from, int n, ea_t ea, bool appzero); - - -//-------------------------------------------------------------------------- -/// \defgroup FF_ Flags structure -/// Here we define the organization of ::flags_t values. -/// Low 8 bits contain value of corresponding byte of the program. -/// The next bit is set if the byte is initialized. -//@{ -#define MS_VAL 0x000000FFLU ///< Mask for byte value -#define FF_IVL 0x00000100LU ///< Byte has value ? -//@} - -/// Do flags contain byte value? - -inline THREAD_SAFE bool idaapi has_value(flags_t F) { return (F & FF_IVL) != 0; } - - -/// Delete byte value from flags. The corresponding byte becomes -/// uninitialized. - -idaman void ida_export del_value(ea_t ea); - - -/// Does the specified address have a byte value (is initialized?) - -idaman bool ida_export is_loaded(ea_t ea); - - -/// Get number of bits in a byte at the given address. -/// \return \ph{dnbits()} if the address doesn't -/// belong to a segment, otherwise the result depends on the -/// segment type - -idaman int ida_export nbits(ea_t ea); - - -/// Get number of bytes required to store a byte at the given address - -inline int bytesize(ea_t ea) - { return (nbits(ea)+7)/8; } - - -/// Get one byte (8-bit) of the program at 'ea'. -/// This function works only for 8bit byte processors. - -idaman uchar ida_export get_byte(ea_t ea); - - -/// Get one byte (8-bit) of the program at 'ea' from the database. -/// Works even if the debugger is active. -/// See also get_dbg_byte() to read the process memory directly. -/// This function works only for 8bit byte processors. - -idaman uchar ida_export get_db_byte(ea_t ea); - - -/// Get one word (16-bit) of the program at 'ea'. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// This function works only for 8bit byte processors. - -idaman ushort ida_export get_word(ea_t ea); - - -/// Get one dword (32-bit) of the program at 'ea'. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// This function works only for 8bit byte processors. - -idaman uint32 ida_export get_dword(ea_t ea); - - -/// Get one qword (64-bit) of the program at 'ea'. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// This function works only for 8bit byte processors. - -idaman uint64 ida_export get_qword(ea_t ea); - - -/// Get one wide byte of the program at 'ea'. -/// Some processors may access more than 8bit quantity at an address. -/// These processors have 32-bit byte organization from the IDA's point of view. - -idaman uint64 ida_export get_wide_byte(ea_t ea); - - -/// Get one wide word (2 'byte') of the program at 'ea'. -/// Some processors may access more than 8bit quantity at an address. -/// These processors have 32-bit byte organization from the IDA's point of view. -/// This function takes into account order of bytes specified in \inf{is_be()} - -idaman uint64 ida_export get_wide_word(ea_t ea); - - -/// Get two wide words (4 'bytes') of the program at 'ea'. -/// Some processors may access more than 8bit quantity at an address. -/// These processors have 32-bit byte organization from the IDA's point of view. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \note this function works incorrectly if \ph{nbits} > 16 - -idaman uint64 ida_export get_wide_dword(ea_t ea); - - -/// Get 8 bits of the program at 'ea'. -/// The main usage of this function is to iterate range of bytes. -/// Here is an example: -/// \code -/// uint64 v; -/// int nbit = 0; -/// for ( ... ) { -/// uchar byte = get_octet(&ea, &v, &nbit); -/// ... -/// } -/// \endcode -/// 'ea' is incremented each time when a new byte is read. -/// In the above example, it will be incremented in the first loop iteration. - -idaman uchar ida_export get_octet(ea_t *ea, uint64 *v, int *nbit); - - - -/// Get 16bits of the program at 'ea'. -/// \return 1 byte (getFullByte()) if the current processor has 16-bit byte, -/// otherwise return get_word() - -idaman uint32 ida_export get_16bit(ea_t ea); - - -/// Get not more than 32bits of the program at 'ea'. -/// \return 32 bit value, depending on \ph{nbits}: -/// - if ( nbits <= 8 ) return get_dword(ea); -/// - if ( nbits <= 16) return get_wide_word(ea); -/// - return get_wide_byte(ea); - -idaman uint32 ida_export get_32bit(ea_t ea); - - -/// Get not more than 64bits of the program at 'ea'. -/// \return 64 bit value, depending on \ph{nbits}: -/// - if ( nbits <= 8 ) return get_qword(ea); -/// - if ( nbits <= 16) return get_wide_dword(ea); -/// - return get_wide_byte(ea); - -idaman uint64 ida_export get_64bit(ea_t ea); - - -/// Get the value at of the item at 'ea'. -/// This function works with entities up to sizeof(ea_t) -/// (bytes, word, etc) -/// \param v pointer to the result. may be nullptr -/// \param ea linear address -/// \param size size of data to read. If 0, then the item -/// type at 'ea' will be used -/// \return success - -idaman bool ida_export get_data_value(uval_t *v, ea_t ea, asize_t size); - - -/// Visit all the patched bytes one byte at a time. -/// \param ea1 start linear address -/// \param ea2 end linear address -/// \param cb callback called for each found byte. -/// if the callback returns non-zero then that value will be -/// returned to the caller and the enumeration will be interrupted. -/// \param ud user data passed to the callback -/// \return the return value returned by the callback (if any) or zero -/// if the enumeration was completed. - -idaman int ida_export visit_patched_bytes( - ea_t ea1, - ea_t ea2, - int (idaapi *cb)(ea_t ea, qoff64_t fpos, uint64 o, uint64 v, void *ud), - void *ud = nullptr); - - -/// Get original byte value (that was before patching). -/// This function works for wide byte processors too. - -idaman uint64 ida_export get_original_byte(ea_t ea); - - -/// Get original word value (that was before patching). -/// This function works for wide byte processors too. -/// This function takes into account order of bytes specified in \inf{is_be()} - -idaman uint64 ida_export get_original_word(ea_t ea); - - -/// Get original dword (that was before patching) -/// This function works for wide byte processors too. -/// This function takes into account order of bytes specified in \inf{is_be()} - -idaman uint64 ida_export get_original_dword(ea_t ea); - - -/// Get original qword value (that was before patching) -/// This function DOESN'T work for wide byte processors too. -/// This function takes into account order of bytes specified in \inf{is_be()} - -idaman uint64 ida_export get_original_qword(ea_t ea); - - -/// Set value of one byte of the program. -/// This function modifies the database. If the debugger is active -/// then the debugged process memory is patched too. -/// \note The original value of the byte is completely lost and can't -/// be recovered by the get_original_byte() function. -/// See also put_dbg_byte() to write to the process memory directly when -/// the debugger is active. -/// This function can handle wide byte processors. -/// \param ea linear address -/// \param x byte value -/// \return true if the database has been modified - -idaman bool ida_export put_byte(ea_t ea, uint64 x); - - -/// Set value of one word of the program. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// This function works for wide byte processors too. -/// \note The original value of the word is completely lost and can't -/// be recovered by the get_original_word() function. -/// ea - linear address -/// x - word value - -idaman void ida_export put_word(ea_t ea, uint64 x); - - -/// Set value of one dword of the program. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// This function works for wide byte processors too. -/// \param ea linear address -/// \param x dword value -/// \note the original value of the dword is completely lost and can't -/// be recovered by the get_original_dword() function. - -idaman void ida_export put_dword(ea_t ea, uint64 x); - - -/// Set value of one qword (8 bytes) of the program. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// This function DOESN'T works for wide byte processors. -/// \param ea linear address -/// \param x qword value - -idaman void ida_export put_qword(ea_t ea, uint64 x); - - -/// Patch a byte of the program. The original value of the byte is saved -/// and can be obtained by get_original_byte(). -/// This function works for wide byte processors too. -/// \retval true the database has been modified, -/// \retval false the debugger is running and the process' memory -/// has value 'x' at address 'ea', or -/// the debugger is not running, and the IDB -/// has value 'x' at address 'ea already. - -idaman bool ida_export patch_byte(ea_t ea, uint64 x); - - -/// Patch a word of the program. The original value of the word is saved -/// and can be obtained by get_original_word(). -/// This function works for wide byte processors too. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \retval true the database has been modified, -/// \retval false the debugger is running and the process' memory -/// has value 'x' at address 'ea', or -/// the debugger is not running, and the IDB -/// has value 'x' at address 'ea already. - -idaman bool ida_export patch_word(ea_t ea, uint64 x); - - -/// Patch a dword of the program. The original value of the dword is saved -/// and can be obtained by get_original_dword(). -/// This function DOESN'T work for wide byte processors. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \retval true the database has been modified, -/// \retval false the debugger is running and the process' memory -/// has value 'x' at address 'ea', or -/// the debugger is not running, and the IDB -/// has value 'x' at address 'ea already. - -idaman bool ida_export patch_dword(ea_t ea, uint64 x); - - -/// Patch a qword of the program. The original value of the qword is saved -/// and can be obtained by get_original_qword(). -/// This function DOESN'T work for wide byte processors. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \retval true the database has been modified, -/// \retval false the debugger is running and the process' memory -/// has value 'x' at address 'ea', or -/// the debugger is not running, and the IDB -/// has value 'x' at address 'ea already. - -idaman bool ida_export patch_qword(ea_t ea, uint64 x); - - -/// Revert patched byte -/// \retval true byte was patched before and reverted now - -idaman bool ida_export revert_byte(ea_t ea); - - -/// Add a value to one byte of the program. -/// This function works for wide byte processors too. -/// \param ea linear address -/// \param value byte value - -idaman void ida_export add_byte(ea_t ea, uint32 value); - - -/// Add a value to one word of the program. -/// This function works for wide byte processors too. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \param ea linear address -/// \param value byte value - -idaman void ida_export add_word(ea_t ea, uint64 value); - - -/// Add a value to one dword of the program. -/// This function works for wide byte processors too. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \note this function works incorrectly if \ph{nbits} > 16 -/// \param ea linear address -/// \param value byte value - -idaman void ida_export add_dword(ea_t ea, uint64 value); - - -/// Add a value to one qword of the program. -/// This function does not work for wide byte processors. -/// This function takes into account order of bytes specified in \inf{is_be()} -/// \param ea linear address -/// \param value byte value - -idaman void ida_export add_qword(ea_t ea, uint64 value); - - -/// Return set of ranges with zero initialized bytes. -/// The returned set includes only big zero initialized ranges (at least >1KB). -/// Some zero initialized byte ranges may be not included. -/// Only zero bytes that use the sparse storage method (STT_MM) are reported. -/// \param zranges pointer to the return value. cannot be nullptr -/// \param range the range of addresses to verify. can be nullptr - means all ranges -/// \return true if the result is a non-empty set - -idaman bool ida_export get_zero_ranges(rangeset_t *zranges, const range_t *range); - - -/// Get the specified number of bytes of the program into the buffer. -/// If mask was specified it will contain a bitmap of initialized / uninitialized -/// database bytes. -/// \param ea linear address -/// \param buf buffer to hold bytes -/// \param size size of buffer in normal 8-bit bytes (sizeof(buf)) -/// \param gmb_flags combination of \ref GMB_ bits -/// \param mask bitmap of initialize/uninitialized bytes -/// (may be nullptr; must be at least (size+7)/8) -/// \return if the user cancelled, return -1; otherwise number of read bytes. - -idaman ssize_t ida_export get_bytes( - void *buf, - ssize_t size, - ea_t ea, - int gmb_flags=0, - void *mask=nullptr); - -/// \defgroup GMB_ flags for get_bytes() -//@{ -#define GMB_READALL 0x01 ///< try to read all bytes - ///< if this bit is not set, fail at first uninited byte -#define GMB_WAITBOX 0x02 ///< show wait box (may return -1 in this case) -///@} - - -/// Modify the specified number of bytes of the program. -/// This function does not save the original values of bytes. -/// See also patch_bytes(). -/// \param ea linear address -/// \param buf buffer with new values of bytes -/// \param size size of buffer in normal 8-bit bytes (sizeof(buf)) - -idaman void ida_export put_bytes(ea_t ea, const void *buf, size_t size); - - -/// Patch the specified number of bytes of the program. -/// Original values of bytes are saved and are available with get_original...() -/// functions. -/// See also put_bytes(). -/// \param ea linear address -/// \param buf buffer with new values of bytes -/// \param size size of buffer in normal 8-bit bytes (sizeof(buf)) - -idaman void ida_export patch_bytes(ea_t ea, const void *buf, size_t size); - -//------------------------------------------------------------------------- -/// \defgroup FF_states States -/// \ingroup FF_ -/// Represent general characteristics of a byte in the program. -/// -/// Each byte of the program may be in one of four states. -/// - unexplored -/// - start of instruction -/// - start of data -/// - second, third (tail) byte of instruction or data. -/// -/// Initially, all bytes of the program are unexplored. -/// IDA modifies flags and doing so converts bytes to instructions -/// and data. -//@{ - -/// \defgroup FF_statebits Bits: byte states -//@{ -#define MS_CLS 0x00000600LU ///< Mask for typing -#define FF_CODE 0x00000600LU ///< Code ? -#define FF_DATA 0x00000400LU ///< Data ? -#define FF_TAIL 0x00000200LU ///< Tail ? -#define FF_UNK 0x00000000LU ///< Unknown ? -//@} - -/// \defgroup FF_statefuncs Functions: examine byte states -//@{ - -/// Does flag denote start of an instruction? - -inline THREAD_SAFE bool idaapi is_code(flags_t F) { return (F & MS_CLS) == FF_CODE; } -inline THREAD_SAFE bool idaapi f_is_code(flags_t F, void *) { return is_code(F); } ///< \copydoc is_code() - - -/// Does flag denote start of data? - -inline THREAD_SAFE bool idaapi is_data(flags_t F) { return (F & MS_CLS) == FF_DATA; } -inline THREAD_SAFE bool idaapi f_is_data(flags_t F, void *) { return is_data(F); } ///< \copydoc is_data() - - -/// Does flag denote tail byte? - -inline THREAD_SAFE bool idaapi is_tail(flags_t F) { return (F & MS_CLS) == FF_TAIL; } -inline THREAD_SAFE bool idaapi f_is_tail(flags_t F, void *) { return is_tail(F); } ///< \copydoc is_tail() -inline THREAD_SAFE bool idaapi is_not_tail(flags_t F) { return !is_tail(F); } ///< \copydoc is_tail() -inline THREAD_SAFE bool idaapi f_is_not_tail(flags_t F, void *) { return is_not_tail(F); } ///< \copydoc is_tail() - - -/// Does flag denote unexplored byte? - -inline THREAD_SAFE bool idaapi is_unknown(flags_t F) { return (F & MS_CLS) == FF_UNK; } - - -/// Does flag denote start of instruction OR data? - -inline THREAD_SAFE bool idaapi is_head(flags_t F) { return (F & FF_DATA) != 0; } -inline THREAD_SAFE bool idaapi f_is_head(flags_t F, void *) { return is_head(F); } ///< \copydoc is_head() - -//@} FF_statefuncs -//@} FF_states - -/// del_items' callback function -typedef bool idaapi may_destroy_cb_t(ea_t); - -/// Convert item (instruction/data) to unexplored bytes. -/// The whole item (including the head and tail bytes) will be destroyed. -/// It is allowed to pass any address in the item to this function -/// \param ea any address within the first item to delete -/// \param flags combination of \ref DELIT_ -/// \param nbytes number of bytes in the range to be undefined -/// \param may_destroy optional routine invoked before deleting a head -/// item. If callback returns false then item has not to -/// be deleted and operation fails -/// \return true on sucessful operation, otherwise false - -idaman bool ida_export del_items( - ea_t ea, - int flags=0, - asize_t nbytes=1, - may_destroy_cb_t *may_destroy=nullptr); - -/// \defgroup DELIT_ Unexplored byte conversion flags -/// passed as 'flags' parameter to del_items() -//@{ -#define DELIT_SIMPLE 0x0000 ///< simply undefine the specified item(s) -#define DELIT_EXPAND 0x0001 ///< propagate undefined items; for example - ///< if removing an instruction removes all - ///< references to the next instruction, then - ///< plan to convert to unexplored the next - ///< instruction too. -#define DELIT_DELNAMES 0x0002 ///< delete any names at the specified - ///< address range (except for the starting - ///< address). this bit is valid if nbytes > 1 -#define DELIT_NOTRUNC 0x0004 ///< don't truncate the current function - ///< even if #AF_TRFUNC is set -#define DELIT_NOUNAME 0x0008 ///< reject to delete if a user name is - ///< in address range (except for the starting - ///< address). this bit is valid if nbytes > 1 -#define DELIT_NOCMT 0x0010 ///< reject to delete if a comment is - ///< in address range (except for the starting - ///< address). this bit is valid if nbytes > 1 -#define DELIT_KEEPFUNC 0x0020 ///< do not undefine the function start. - ///< Just delete xrefs, ops e.t.c. -//@} - - -//------------------------------------------------------------------------- -// Manual instructions (they are used to completely override an automatically -// generated instruction by a user specified string). - -/// Is the instruction overridden? -/// \param ea linear address of the instruction or data item - -idaman bool ida_export is_manual_insn(ea_t ea); // Is the instruction overridden? - - -/// Retrieve the user-specified string for the manual instruction. -/// \param buf output buffer -/// \param ea linear address of the instruction or data item -/// \return size of manual instruction or -1 - -idaman ssize_t ida_export get_manual_insn(qstring *buf, ea_t ea); - - -/// Set manual instruction string. -/// \param ea linear address of the instruction or data item -/// \param manual_insn "" - delete manual string. -/// nullptr - do nothing - -idaman void ida_export set_manual_insn(ea_t ea, const char *manual_insn); // Set user-specified string - - -//------------------------------------------------------------------------- -/*! \defgroup FF_statespecb Bits: specific state information - \ingroup FF_states - Flags keep information common to all four states of bytes. - This information will not be automatically discarded during - transitions between different states. -*/ -//@{ -#define MS_COMM 0x000FF800 ///< Mask of common bits -#define FF_COMM 0x00000800 ///< Has comment ? -#define FF_REF 0x00001000 ///< has references -#define FF_LINE 0x00002000 ///< Has next or prev lines ? -#define FF_NAME 0x00004000 ///< Has name ? -#define FF_LABL 0x00008000 ///< Has dummy name? -#define FF_FLOW 0x00010000 ///< Exec flow from prev instruction -#define FF_SIGN 0x00020000 ///< Inverted sign of operands -#define FF_BNOT 0x00040000 ///< Bitwise negation of operands -#define FF_UNUSED 0x00080000 ///< unused bit (was used for variable bytes) -//@} - -/// \defgroup FF_statespecf Functions: examine specific state information -/// \ingroup FF_states -//@{ - -/// Does the previous instruction exist and pass execution flow to the current byte? - -inline THREAD_SAFE bool idaapi is_flow(flags_t F) { return (F & FF_FLOW) != 0; } - - -/// Does the current byte have additional anterior or posterior lines? - -inline THREAD_SAFE bool idaapi has_extra_cmts(flags_t F) { return (F & FF_LINE) != 0; } -inline THREAD_SAFE bool idaapi f_has_extra_cmts(flags_t f, void *) { return has_extra_cmts(f); } - -/// Does the current byte have an indented comment? - -inline THREAD_SAFE bool idaapi has_cmt(flags_t F) { return (F & FF_COMM) != 0; } -inline THREAD_SAFE bool idaapi f_has_cmt(flags_t f, void *) { return has_cmt(f); } - -/// Does the current byte have cross-references to it? - -inline THREAD_SAFE bool idaapi has_xref(flags_t F) { return (F & FF_REF) != 0; } -inline THREAD_SAFE bool idaapi f_has_xref(flags_t f, void *) { return has_xref(f); } ///< \copydoc has_xref() - - -/// Does the current byte have non-trivial (non-dummy) name? - -inline THREAD_SAFE bool idaapi has_name(flags_t F) { return (F & FF_NAME) != 0; } -inline THREAD_SAFE bool idaapi f_has_name(flags_t f, void *) { return has_name(f); } ///< \copydoc has_name() - - - -#define FF_ANYNAME (FF_LABL|FF_NAME) - -/// Does the current byte have dummy (auto-generated, with special prefix) name? - -inline THREAD_SAFE bool idaapi has_dummy_name(flags_t F) { return (F & FF_ANYNAME) == FF_LABL; } -inline THREAD_SAFE bool idaapi f_has_dummy_name(flags_t f, void *) { return has_dummy_name(f); } ///< \copydoc has_dummy_name() - - -/// Does the current byte have auto-generated (no special prefix) name? - -inline THREAD_SAFE bool idaapi has_auto_name(flags_t F) { return (F & FF_ANYNAME) == FF_ANYNAME; } - - -/// Does the current byte have any name? - -inline THREAD_SAFE bool idaapi has_any_name(flags_t F) { return (F & FF_ANYNAME) != 0; } - - -/// Does the current byte have user-specified name? - -inline THREAD_SAFE bool idaapi has_user_name(flags_t F) { return (F & FF_ANYNAME) == FF_NAME; } -inline THREAD_SAFE bool idaapi f_has_user_name(flags_t F, void *) { return has_user_name(F); } ///< \copydoc has_user_name() - -// signness deals with the form of operands of the current instruction/data. -// inverted sign means the following: -// if the bit is clear |then when the bit is set -// and the output is |the output should be: -// ------------ |---------- -// unsigned |signed -// signed |unsigned -// - -/// Should sign of n-th operand inverted during output?. -/// allowed values of n: 0-first operand, 1-other operands - -idaman bool ida_export is_invsign(ea_t ea, flags_t F, int n); - - -/// Toggle sign of n-th operand. -/// allowed values of n: 0-first operand, 1-other operands - -idaman bool ida_export toggle_sign(ea_t ea, int n); - - -/// Should we negate the operand?. -/// \ash{a_bnot} should be defined in the idp module in order to work -/// with this function - -idaman bool ida_export is_bnot(ea_t ea, flags_t F, int n); -idaman bool ida_export toggle_bnot(ea_t ea, int n); ///< Toggle binary negation of operand. also see is_bnot() - - -/// Display leading zeroes in operands. -/// The global switch for the leading zeroes is in \inf{s_genflags} -/// The leading zeroes doesn't work if the octal numbers start with 0 - -idaman bool ida_export is_lzero(ea_t ea, int n); ///< Display leading zeroes? - ///< (takes into account \inf{s_genflags}) -idaman bool ida_export set_lzero(ea_t ea, int n); ///< Set toggle lzero bit -idaman bool ida_export clr_lzero(ea_t ea, int n); ///< Clear lzero bit -inline bool idaapi toggle_lzero(ea_t ea, int n) ///< Toggle lzero bit -{ - return (is_lzero(ea, n) ? clr_lzero : set_lzero)(ea, n); -} - -//@} FF_statespecf - - -/// Check if leading zeroes are important - -idaman bool ida_export leading_zero_important(ea_t ea, int n); - - -//------------------------------------------------------------------------- -/// \defgroup FF_op Instruction/Data operands -/// \ingroup FF_ -/// Represent instruction/data operands. -/// -/// IDA keeps 2 bitmasks: -/// - representation of the first operand -/// - representation of other operands (we will call this -/// 'representation of second operand' -/// although it is also applied to third, fourth, etc operands too) -/// -/// For data bytes, only the first bitmask is used (i.e. all elements of -/// an array have the same type). -//@{ - -/// \defgroup FF_opbits Bits: instruction operand types -//@{ -#define MS_0TYPE 0x00F00000LU ///< Mask for 1st arg typing -#define FF_0VOID 0x00000000LU ///< Void (unknown)? -#define FF_0NUMH 0x00100000LU ///< Hexadecimal number? -#define FF_0NUMD 0x00200000LU ///< Decimal number? -#define FF_0CHAR 0x00300000LU ///< Char ('x')? -#define FF_0SEG 0x00400000LU ///< Segment? -#define FF_0OFF 0x00500000LU ///< Offset? -#define FF_0NUMB 0x00600000LU ///< Binary number? -#define FF_0NUMO 0x00700000LU ///< Octal number? -#define FF_0ENUM 0x00800000LU ///< Enumeration? -#define FF_0FOP 0x00900000LU ///< Forced operand? -#define FF_0STRO 0x00A00000LU ///< Struct offset? -#define FF_0STK 0x00B00000LU ///< Stack variable? -#define FF_0FLT 0x00C00000LU ///< Floating point number? -#define FF_0CUST 0x00D00000LU ///< Custom representation? - -#define MS_1TYPE 0x0F000000LU ///< Mask for the type of other operands -#define FF_1VOID 0x00000000LU ///< Void (unknown)? -#define FF_1NUMH 0x01000000LU ///< Hexadecimal number? -#define FF_1NUMD 0x02000000LU ///< Decimal number? -#define FF_1CHAR 0x03000000LU ///< Char ('x')? -#define FF_1SEG 0x04000000LU ///< Segment? -#define FF_1OFF 0x05000000LU ///< Offset? -#define FF_1NUMB 0x06000000LU ///< Binary number? -#define FF_1NUMO 0x07000000LU ///< Octal number? -#define FF_1ENUM 0x08000000LU ///< Enumeration? -#define FF_1FOP 0x09000000LU ///< Forced operand? -#define FF_1STRO 0x0A000000LU ///< Struct offset? -#define FF_1STK 0x0B000000LU ///< Stack variable? -#define FF_1FLT 0x0C000000LU ///< Floating point number? -#define FF_1CUST 0x0D000000LU ///< Custom representation? -//@} - -/// \defgroup FF_opfuncs1 Functions: examine operand flags (specific operands) -//@{ - -/// Is the first operand defined? Initially operand has no defined representation - -inline THREAD_SAFE bool idaapi is_defarg0(flags_t F) { return (F & MS_0TYPE) != FF_0VOID; } - - -/// Is the second operand defined? Initially operand has no defined representation - -inline THREAD_SAFE bool idaapi is_defarg1(flags_t F) { return (F & MS_1TYPE) != FF_1VOID; } - - -/// Is the first operand offset? (example: push offset xxx) - -inline THREAD_SAFE bool idaapi is_off0(flags_t F) { return (F & MS_0TYPE) == FF_0OFF; } - - -/// Is the second operand offset? (example: mov ax, offset xxx) - -inline THREAD_SAFE bool idaapi is_off1(flags_t F) { return (F & MS_1TYPE) == FF_1OFF; } - - -/// Is the first operand character constant? (example: push 'a') - -inline THREAD_SAFE bool idaapi is_char0(flags_t F) { return (F & MS_0TYPE) == FF_0CHAR; } - - -/// Is the second operand character constant? (example: mov al, 'a') - -inline THREAD_SAFE bool idaapi is_char1(flags_t F) { return (F & MS_1TYPE) == FF_1CHAR; } - - -/// Is the first operand segment selector? (example: push seg seg001) - -inline THREAD_SAFE bool idaapi is_seg0(flags_t F) { return (F & MS_0TYPE) == FF_0SEG; } - - -/// Is the second operand segment selector? (example: mov dx, seg dseg) - -inline THREAD_SAFE bool idaapi is_seg1(flags_t F) { return (F & MS_1TYPE) == FF_1SEG; } - - -/// Is the first operand a symbolic constant (enum member)? - -inline THREAD_SAFE bool idaapi is_enum0(flags_t F) { return (F & MS_0TYPE) == FF_0ENUM; } - - -/// Is the second operand a symbolic constant (enum member)? - -inline THREAD_SAFE bool idaapi is_enum1(flags_t F) { return (F & MS_1TYPE) == FF_1ENUM; } - - -/// Is the first operand an offset within a struct? - -inline THREAD_SAFE bool idaapi is_stroff0(flags_t F) { return (F & MS_0TYPE) == FF_0STRO; } - - -/// Is the second operand an offset within a struct? - -inline THREAD_SAFE bool idaapi is_stroff1(flags_t F) { return (F & MS_1TYPE) == FF_1STRO; } - - -/// Is the first operand a stack variable? - -inline THREAD_SAFE bool idaapi is_stkvar0(flags_t F) { return (F & MS_0TYPE) == FF_0STK; } - - -/// Is the second operand a stack variable? - -inline THREAD_SAFE bool idaapi is_stkvar1(flags_t F) { return (F & MS_1TYPE) == FF_1STK; } - - -/// Is the first operand a floating point number? - -inline THREAD_SAFE bool idaapi is_float0(flags_t F) { return (F & MS_0TYPE) == FF_0FLT; } - - -/// Is the second operand a floating point number? - -inline THREAD_SAFE bool idaapi is_float1(flags_t F) { return (F & MS_1TYPE) == FF_1FLT; } - - -/// Does the first operand use a custom data representation? - -inline THREAD_SAFE bool idaapi is_custfmt0(flags_t F) { return (F & MS_0TYPE) == FF_0CUST; } - - -/// Does the second operand use a custom data representation? - -inline THREAD_SAFE bool idaapi is_custfmt1(flags_t F) { return (F & MS_1TYPE) == FF_1CUST; } - - -/// Is the first operand a number (i.e. binary, octal, decimal or hex?) - -idaman bool ida_export is_numop0(flags_t F); - - -/// Is the second operand a number (i.e. binary, octal, decimal or hex?) - -idaman bool ida_export is_numop1(flags_t F); - - -/// Get flags for first operand - -inline THREAD_SAFE flags_t get_optype_flags0(flags_t F) { return F & MS_0TYPE; } - - -/// Get flags for second operand - -inline THREAD_SAFE flags_t get_optype_flags1(flags_t F) { return F & MS_1TYPE; } - -//@} FF_opfuncs1 - -//------------------------------------------------------------------------- -// -// The following 2 masks are used with operand numbers -// -#define OPND_OUTER 0x80 ///< outer offset base (combined with operand number). - ///< used only in set, get, del_offset() functions -#define OPND_MASK 0x0F ///< mask for operand number -#define OPND_ALL OPND_MASK ///< all operands - -/*! \defgroup FF_opfuncs2 Functions: examine operand flags (arbitrary operand) - For the following functions, 'n' may be: - - 0 : first operand - - 1 : second operand - - #OPND_ALL : both operands - function returns 1 if the first - OR the second operand satisfies the condition -*/ -//@{ -idaman bool ida_export is_defarg(flags_t F, int n); ///< is defined? -idaman bool ida_export is_off(flags_t F, int n); ///< is offset? -idaman bool ida_export is_char(flags_t F, int n); ///< is character constant? -idaman bool ida_export is_seg(flags_t F, int n); ///< is segment? -idaman bool ida_export is_enum(flags_t F, int n); ///< is enum? -idaman bool ida_export is_manual(flags_t F, int n); ///< is forced operand? (use is_forced_operand()) -idaman bool ida_export is_stroff(flags_t F, int n); ///< is struct offset? -idaman bool ida_export is_stkvar(flags_t F, int n); ///< is stack variable? -idaman bool ida_export is_fltnum(flags_t F, int n); ///< is floating point number? -idaman bool ida_export is_custfmt(flags_t F, int n); ///< is custom data format? -idaman bool ida_export is_numop(flags_t F, int n); ///< is number (bin, oct, dec, hex)? -idaman bool ida_export is_suspop(ea_t ea, flags_t F, int n); ///< is suspicious operand? -//@} - -/// Should processor module create xrefs from the operand?. -/// Currently 'offset' and 'structure offset' operands create xrefs - -idaman bool ida_export op_adds_xrefs(flags_t F, int n); - - -/// (internal function) change representation of operand(s). -/// \param ea linear address -/// \param type new flag value (should be obtained from char_flag(), num_flag() and -/// similar functions) -/// \param n number of operand (0, 1, -1) -/// \retval 1 ok -/// \retval 0 failed (applied to a tail byte) - -idaman bool ida_export set_op_type(ea_t ea, flags_t type, int n); - - -/// Set operand representation to be 'segment'. -/// If applied to unexplored bytes, converts them to 16/32bit word data -/// \param ea linear address -/// \param n number of operand (0, 1, -1) -/// \return success - -idaman bool ida_export op_seg(ea_t ea, int n); - - -/// Set operand representation to be 'enum_t'. -/// If applied to unexplored bytes, converts them to 16/32bit word data -/// \param ea linear address -/// \param n number of operand (0, 1, -1) -/// \param id id of enum -/// \param serial the serial number of the constant in the enumeration, -/// usually 0. the serial numbers are used if the enumeration -/// contains several constants with the same value -/// \return success - -idaman bool ida_export op_enum(ea_t ea, int n, enum_t id, uchar serial); - - -/// Get enum id of 'enum' operand. -/// \param ea linear address -/// \param n number of operand (0, 1, -1) -/// \param serial pointer to variable to hold the serial number of the -/// constant in the enumeration -/// \return id of enum or #BADNODE - -idaman enum_t ida_export get_enum_id(uchar *serial, ea_t ea, int n); - - -/// Set operand representation to be 'struct offset'. -/// If applied to unexplored bytes, converts them to 16/32bit word data -/// \param insn the instruction -/// \param n number of operand (0, 1, -1) -/// \param path structure path (strpath). see nalt.hpp for more info. -/// \param path_len length of the structure path -/// \param delta struct offset delta. usually 0. denotes the difference -/// between the structure base and the pointer into the structure. -/// \return success - -idaman bool ida_export op_stroff( - const insn_t &insn, - int n, - const tid_t *path, - int path_len, - adiff_t delta); - - -/// Get struct path of operand. -/// \param path buffer for structure path (strpath). see nalt.hpp for more info. -/// \param delta struct offset delta -/// \param ea linear address -/// \param n number of operand (0, 1, -1) -/// \return length of strpath - -idaman int ida_export get_stroff_path(tid_t *path, adiff_t *delta, ea_t ea, int n); - -/// Set operand representation to be 'stack variable'. -/// Should be applied to an instruction within a function. -/// Should be applied after creating a stack var using -/// insn_t::create_stkvar(). -/// \param ea linear address -/// \param n number of operand (0, 1, -1) -/// \return success - -idaman bool ida_export op_stkvar(ea_t ea, int n); - - -/// Set forced operand. -/// \param ea linear address -/// \param n number of operand (0, 1, 2) -/// \param op text of operand -/// - nullptr: do nothing (return 0) -/// - "" : delete forced operand -/// \return success - -idaman bool ida_export set_forced_operand(ea_t ea, int n, const char *op); - - -/// Get forced operand. -/// \param buf output buffer, may be nullptr -/// \param ea linear address -/// \param n number of operand (0, 1, 2) -/// \return size of forced operand or -1 - -idaman ssize_t ida_export get_forced_operand(qstring *buf, ea_t ea, int n); - - -/// Is operand manually defined?. -/// \param ea linear address -/// \param n number of operand (0, 1, 2) - -idaman bool ida_export is_forced_operand(ea_t ea, int n); - - -//------------------------------------------------------------------------- -/*! \defgroup FF_opfuncs3 Functions: get type information bits for flags - Values of these functions are used as input to set_op_type() function -*/ -//@{ -inline constexpr flags_t idaapi char_flag(void) { return FF_1CHAR|FF_0CHAR; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi off_flag(void) { return FF_1OFF |FF_0OFF; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi enum_flag(void) { return FF_1ENUM|FF_0ENUM; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi stroff_flag(void) { return FF_1STRO|FF_0STRO; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi stkvar_flag(void) { return FF_1STK |FF_0STK; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi flt_flag(void) { return FF_1FLT |FF_0FLT; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi custfmt_flag(void) { return FF_1CUST|FF_0CUST; } ///< see \ref FF_opbits -inline constexpr flags_t idaapi seg_flag(void) { return FF_1SEG |FF_0SEG; } ///< see \ref FF_opbits - -idaman flags_t ida_export num_flag(void); ///< Get number of default base (bin, oct, dec, hex) -/// Get number flag of the base, regardless of current processor - better to use num_flag() -inline constexpr flags_t idaapi hex_flag(void) { return FF_1NUMH|FF_0NUMH; } -inline constexpr flags_t idaapi dec_flag(void) { return FF_1NUMD|FF_0NUMD; } ///< \copydoc hex_flag() -inline constexpr flags_t idaapi oct_flag(void) { return FF_1NUMO|FF_0NUMO; } ///< \copydoc hex_flag() -inline constexpr flags_t idaapi bin_flag(void) { return FF_1NUMB|FF_0NUMB; } ///< \copydoc hex_flag() -//@} - -/*! \defgroup FF_opfuncs4 Functions: set operand representation - The following functions set operand representation. - If they are applied to unexplored bytes, they convert them. - - no segment : fail - - 16bit segment : to 16bit word data - - 32bit segment : to dword - \param ea linear address - \param n number of operand (0, 1, -1) - \return success -*/ -//@{ -inline bool idaapi op_chr(ea_t ea, int n) { return set_op_type(ea, char_flag(), n); } ///< set op type to char_flag() -inline bool idaapi op_num(ea_t ea, int n) { return set_op_type(ea, num_flag(), n); } ///< set op type to num_flag() -inline bool idaapi op_hex(ea_t ea, int n) { return set_op_type(ea, hex_flag(), n); } ///< set op type to hex_flag() -inline bool idaapi op_dec(ea_t ea, int n) { return set_op_type(ea, dec_flag(), n); } ///< set op type to dec_flag() -inline bool idaapi op_oct(ea_t ea, int n) { return set_op_type(ea, oct_flag(), n); } ///< set op type to oct_flag() -inline bool idaapi op_bin(ea_t ea, int n) { return set_op_type(ea, bin_flag(), n); } ///< set op type to bin_flag() -inline bool idaapi op_flt(ea_t ea, int n) { return set_op_type(ea, flt_flag(), n); } ///< set op type to flt_flag() -//@} - -/// Set custom data format for operand (fid-custom data format id) - -idaman bool ida_export op_custfmt(ea_t ea, int n, int fid); - - -/// Remove operand representation information. -/// (set operand representation to be 'undefined') -/// \param ea linear address -/// \param n number of operand (0, 1, -1) -/// \return success - -idaman bool ida_export clr_op_type(ea_t ea, int n); - - -/// Get default base of number for the current processor. -/// \return 2, 8, 10, 16 - -idaman int ida_export get_default_radix(void); - - -/// Get radix of the operand, in: flags. -/// If the operand is not a number, returns get_default_radix() -/// \param F flags -/// \param n number of operand (0, 1, -1) -/// \return 2, 8, 10, 16 - -idaman int ida_export get_radix(flags_t F, int n); - - -//------------------------------------------------------------------------- -/// \defgroup FF_databits Bits: data bytes -//@{ -#define DT_TYPE 0xF0000000 ///< Mask for DATA typing - -#define FF_BYTE 0x00000000 ///< byte -#define FF_WORD 0x10000000 ///< word -#define FF_DWORD 0x20000000 ///< double word -#define FF_QWORD 0x30000000 ///< quadro word -#define FF_TBYTE 0x40000000 ///< tbyte -#define FF_STRLIT 0x50000000 ///< string literal -#define FF_STRUCT 0x60000000 ///< struct variable -#define FF_OWORD 0x70000000 ///< octaword/xmm word (16 bytes/128 bits) -#define FF_FLOAT 0x80000000 ///< float -#define FF_DOUBLE 0x90000000 ///< double -#define FF_PACKREAL 0xA0000000 ///< packed decimal real -#define FF_ALIGN 0xB0000000 ///< alignment directive -// 0xC0000000 ///< reserved -#define FF_CUSTOM 0xD0000000 ///< custom data type -#define FF_YWORD 0xE0000000 ///< ymm word (32 bytes/256 bits) -#define FF_ZWORD 0xF0000000 ///< zmm word (64 bytes/512 bits) -//@} - -/// \defgroup FF_datafuncs1 Functions: examine data bits -//@{ -inline constexpr flags_t idaapi code_flag(void) { return FF_CODE; } ///< #FF_CODE -inline constexpr flags_t idaapi byte_flag(void) { return FF_DATA|FF_BYTE; } ///< Get a flags_t representing a byte -inline constexpr flags_t idaapi word_flag(void) { return FF_DATA|FF_WORD; } ///< Get a flags_t representing a word -inline constexpr flags_t idaapi dword_flag(void) { return FF_DATA|FF_DWORD; } ///< Get a flags_t representing a double word -inline constexpr flags_t idaapi qword_flag(void) { return FF_DATA|FF_QWORD; } ///< Get a flags_t representing a quad word -inline constexpr flags_t idaapi oword_flag(void) { return FF_DATA|FF_OWORD; } ///< Get a flags_t representing a octaword -inline constexpr flags_t idaapi yword_flag(void) { return FF_DATA|FF_YWORD; } ///< Get a flags_t representing a ymm word -inline constexpr flags_t idaapi zword_flag(void) { return FF_DATA|FF_ZWORD; } ///< Get a flags_t representing a zmm word -inline constexpr flags_t idaapi tbyte_flag(void) { return FF_DATA|FF_TBYTE; } ///< Get a flags_t representing a tbyte -inline constexpr flags_t idaapi strlit_flag(void) { return FF_DATA|FF_STRLIT; } ///< Get a flags_t representing a string literal -inline constexpr flags_t idaapi stru_flag(void) { return FF_DATA|FF_STRUCT; } ///< Get a flags_t representing a struct -inline constexpr flags_t idaapi cust_flag(void) { return FF_DATA|FF_CUSTOM; } ///< Get a flags_t representing custom type data -inline constexpr flags_t idaapi align_flag(void) { return FF_DATA|FF_ALIGN; } ///< Get a flags_t representing an alignment directive -inline constexpr flags_t idaapi float_flag(void) { return FF_DATA|FF_FLOAT; } ///< Get a flags_t representing a float -inline constexpr flags_t idaapi double_flag(void) { return FF_DATA|FF_DOUBLE; } ///< Get a flags_t representing a double -inline constexpr flags_t idaapi packreal_flag(void) { return FF_DATA|FF_PACKREAL; } ///< Get a flags_t representing a packed decimal real - -inline THREAD_SAFE bool idaapi is_byte(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_BYTE; } ///< #FF_BYTE -inline THREAD_SAFE bool idaapi is_word(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_WORD; } ///< #FF_WORD -inline THREAD_SAFE bool idaapi is_dword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_DWORD; } ///< #FF_DWORD -inline THREAD_SAFE bool idaapi is_qword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_QWORD; } ///< #FF_QWORD -inline THREAD_SAFE bool idaapi is_oword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_OWORD; } ///< #FF_OWORD -inline THREAD_SAFE bool idaapi is_yword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_YWORD; } ///< #FF_YWORD -inline THREAD_SAFE bool idaapi is_zword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_ZWORD; } ///< #FF_ZWORD -inline THREAD_SAFE bool idaapi is_tbyte(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_TBYTE; } ///< #FF_TBYTE -inline THREAD_SAFE bool idaapi is_float(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_FLOAT; } ///< #FF_FLOAT -inline THREAD_SAFE bool idaapi is_double(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_DOUBLE; } ///< #FF_DOUBLE -inline THREAD_SAFE bool idaapi is_pack_real(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_PACKREAL; } ///< #FF_PACKREAL -inline THREAD_SAFE bool idaapi is_strlit(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_STRLIT; } ///< #FF_STRLIT -inline THREAD_SAFE bool idaapi is_struct(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_STRUCT; } ///< #FF_STRUCT -inline THREAD_SAFE bool idaapi is_align(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_ALIGN; } ///< #FF_ALIGN -inline THREAD_SAFE bool idaapi is_custom(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_CUSTOM; } ///< #FF_CUSTOM - -inline THREAD_SAFE bool idaapi f_is_byte(flags_t F, void *) { return is_byte(F); } ///< See is_byte() -inline THREAD_SAFE bool idaapi f_is_word(flags_t F, void *) { return is_word(F); } ///< See is_word() -inline THREAD_SAFE bool idaapi f_is_dword(flags_t F, void *) { return is_dword(F); } ///< See is_dword() -inline THREAD_SAFE bool idaapi f_is_qword(flags_t F, void *) { return is_qword(F); } ///< See is_qword() -inline THREAD_SAFE bool idaapi f_is_oword(flags_t F, void *) { return is_oword(F); } ///< See is_oword() -inline THREAD_SAFE bool idaapi f_is_yword(flags_t F, void *) { return is_yword(F); } ///< See is_yword() -inline THREAD_SAFE bool idaapi f_is_tbyte(flags_t F, void *) { return is_tbyte(F); } ///< See is_tbyte() -inline THREAD_SAFE bool idaapi f_is_float(flags_t F, void *) { return is_float(F); } ///< See is_float() -inline THREAD_SAFE bool idaapi f_is_double(flags_t F, void *) { return is_double(F); } ///< See is_double() -inline THREAD_SAFE bool idaapi f_is_pack_real(flags_t F, void *) { return is_pack_real(F); } ///< See is_pack_real() -inline THREAD_SAFE bool idaapi f_is_strlit(flags_t F, void *) { return is_strlit(F); } ///< See is_strlit() -inline THREAD_SAFE bool idaapi f_is_struct(flags_t F, void *) { return is_struct(F); } ///< See is_struct() -inline THREAD_SAFE bool idaapi f_is_align(flags_t F, void *) { return is_align(F); } ///< See is_align() -inline THREAD_SAFE bool idaapi f_is_custom(flags_t F, void *) { return is_custom(F); } ///< See is_custom() - - -/// Do the given flags specify the same data type? - -inline THREAD_SAFE bool idaapi is_same_data_type(flags_t F1, flags_t F2) { return ((F1 ^ F2) & DT_TYPE) == 0; } - - -/// Get flags from size (in bytes). -/// Supported sizes: 1, 2, 4, 8, 16, 32. -/// For other sizes returns 0 - -idaman flags_t ida_export get_flags_by_size(size_t size); -//@} FF_datafuncs1 - - -/// \defgroup FF_datafuncs2 Functions: manipulate data bits -/// \param ea linear address -/// \param length size of array in bytes. should be divisible by the size of -/// one item of the specified type. -/// \return success -//@{ - -/// Convert to data (byte, word, dword, etc). -/// This function may be used to create arrays. -/// \param ea linear address -/// \param dataflag type of data. Value of function byte_flag(), word_flag(), etc. -/// \param size size of array in bytes. should be divisible by the size of -/// one item of the specified type. for variable sized items -/// it can be specified as 0, and the kernel will try to calculate the size. -/// \param tid type id. If the specified type is a structure, -/// then tid is structure id. Otherwise should be #BADNODE. -/// \return success - -idaman bool ida_export create_data( - ea_t ea, - flags_t dataflag, - asize_t size, - tid_t tid); - - -inline THREAD_SAFE flags_t idaapi calc_dflags(flags_t f, bool force) { return f | (force ? FF_COMM : 0); } -/// Convert to byte -inline bool idaapi create_byte(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_BYTE, force), length, BADNODE); -} -/// Convert to word -inline bool idaapi create_word(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_WORD, force), length, BADNODE); -} -/// Convert to dword -inline bool idaapi create_dword(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_DWORD, force), length, BADNODE); -} -/// Convert to quadword -inline bool idaapi create_qword(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_QWORD, force), length, BADNODE); -} -/// Convert to octaword/xmm word -inline bool idaapi create_oword(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_OWORD, force), length, BADNODE); -} -/// Convert to ymm word -inline bool idaapi create_yword(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_YWORD, force), length, BADNODE); -} -/// Convert to zmm word -inline bool idaapi create_zword(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_ZWORD, force), length, BADNODE); -} -/// Convert to tbyte -inline bool idaapi create_tbyte(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_TBYTE, force), length, BADNODE); -} -/// Convert to float -inline bool idaapi create_float(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_FLOAT, force), length, BADNODE); -} -/// Convert to double -inline bool idaapi create_double(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_DOUBLE, force), length, BADNODE); -} -/// Convert to packed decimal real -inline bool idaapi create_packed_real(ea_t ea, asize_t length, bool force=false) -{ - return create_data(ea, calc_dflags(FF_PACKREAL, force), length, BADNODE); -} -/// Convert to struct -inline bool idaapi create_struct(ea_t ea, asize_t length, tid_t tid, bool force=false) -{ - return create_data(ea, calc_dflags(FF_STRUCT, force), length, tid); -} -/// Convert to custom data type -inline bool idaapi create_custdata(ea_t ea, asize_t length, int dtid, int fid, bool force=false) -{ - return create_data(ea, calc_dflags(FF_CUSTOM, force), length, dtid|(fid<<16)); -} - - -/// Alignment: 0 or 2..32. If it is 0, is will be calculated -idaman bool ida_export create_align(ea_t ea, asize_t length, int alignment); -idaman int ida_export calc_min_align(asize_t length); ///< Returns: 1..32 -idaman int ida_export calc_max_align(ea_t endea); ///< Returns: 0..32 -idaman int ida_export calc_def_align(ea_t ea, int mina, int maxa); ///< Calculate default alignment -idaman bool ida_export create_16bit_data(ea_t ea, asize_t length); ///< Convert to 16-bit quantity (take byte size into account) -idaman bool ida_export create_32bit_data(ea_t ea, asize_t length); ///< Convert to 32-bit quantity (take byte size into account) -//@} FF_datafuncs2 - -//@} FF_op - -/// \defgroup ALOPT_ string literal length options -/// passed as 'options' parameter to get_max_strlit_length() -//@{ -#define ALOPT_IGNHEADS 0x01 ///< don't stop if another data item is encountered. - ///< only the byte values will be used to determine - ///< the string length. - ///< if not set, a defined data item or instruction - ///< will truncate the string -#define ALOPT_IGNPRINT 0x02 ///< if set, don't stop at non-printable codepoints, - ///< but only at the terminating character (or not - ///< unicode-mapped character (e.g., 0x8f in CP1252)) -#define ALOPT_IGNCLT 0x04 ///< if set, don't stop at codepoints that are not - ///< part of the current 'culture'; accept all - ///< those that are graphical (this is typically - ///< used used by user-initiated actions creating - ///< string literals.) -#define ALOPT_MAX4K 0x08 ///< if string length is more than 4K, return the - ///< accumulated length - -//@} - -/// Determine maximum length of string literal. -/// -/// If the string literal has a length prefix (e.g., STRTYPE_LEN2 has -/// a two-byte length prefix), the length of that prefix (i.e., 2) -/// will be part of the returned value. -/// -/// \param ea starting address -/// \param strtype string type. one of \ref STRTYPE_ -/// \param options combination of \ref ALOPT_ -/// \return length of the string in octets (octet==8bit) - -idaman size_t ida_export get_max_strlit_length( - ea_t ea, - int32 strtype, - int options = 0); - -/// \defgroup STRCONV_ string conversion flags -/// passed as 'flags' parameter to get_strlit_contents() -//@{ -#define STRCONV_ESCAPE 0x00000001 ///< convert non-printable characters to C escapes (\n, \xNN, \uNNNN) -#define STRCONV_REPLCHAR 0x00000002 ///< convert non-printable characters to the Unicode replacement character (U+FFFD) -#define STRCONV_INCLLEN 0x00000004 ///< for Pascal-style strings, include the prefixing length byte(s) as C-escaped sequence -//@} - -/// Get contents of string literal, as UTF-8-encoded codepoints. -/// This function returns the displayed part of the string -/// It works even if the string has not been created in the database yet. -/// -/// If 'len' is size_t(-1), it will be computed like so: -/// - if a string literal is present at 'ea', get_item_size() * bytesize(ea) will be used -/// - otherwise, get_max_strlit_length(..., ALOPT_IGNHEADS) will be used -/// -/// About 'maxcps': this specifies a limit to the number of codepoints, -/// not bytes in the UTF-8 output buffer. So for example although U+4e12 -/// will use 3 bytes in the output buffer, it still counts as only 1 -/// character -- unless STRCONV_ESCAPE is used. -/// If 'STRCONV_ESCAPE' is used, U+4e12 will be converted to the string -/// "\u4E12", and will use 6 bytes in the output buffer and also count -/// as 6 codepoints. -/// -/// If 'STRCONV_REPLCHAR', any undecodable byte will re represented -/// as U+FFFD, occupy 3 bytes in the output buffer, and count for 1 codepoint. -/// -/// \param[out] utf8 output buffer -/// \param[in] ea linear address of the string -/// \param[in] len length of the string, in octets (octet=8bit) -/// \param[in] type type of the string. one of \ref STRTYPE_ -/// \param[in, out] maxcps maximum length of codepoints, after possible -/// escaping, in output buffer (not counting terminating zero) -/// on exit, will be set to 0 if string got truncated -/// can be nullptr if not needed -/// \param[in] flags combination of \ref STRCONV_ -/// \return length of generated text (in bytes) or -1 - -idaman ssize_t ida_export get_strlit_contents( - qstring *utf8, - ea_t ea, - size_t len, - int32 type, - size_t *maxcps = nullptr, - int flags = 0); - - -/// Convert to string literal and give a meaningful name. -/// 'start' may be higher than 'end', the kernel will swap them in this case -/// \param start starting address -/// \param len length of the string in bytes. -/// if 0, then get_max_strlit_length() will be used -/// to determine the length -/// \param strtype string type. one of \ref STRTYPE_ -/// \return success - -idaman bool ida_export create_strlit(ea_t start, size_t len, int32 strtype); - - - -//------------------------------------------------------------------------- -/// \defgroup PSTF_ flags for use with get_strlit_type_info -//@{ -#define PSTF_TNORM 0 ///< use normal name -#define PSTF_TBRIEF 1 ///< use brief name (e.g., in the 'Strings window') -#define PSTF_TINLIN 2 ///< use 'inline' name (e.g., in the structures comments) -#define PSTF_TMASK 3 ///< type mask -#define PSTF_HOTKEY 0x4 ///< have hotkey markers part of the name -#define PSTF_ENC 0x8 ///< if encoding is specified, append it -//@} - - -/// Get string type information: the string type name (possibly -/// decorated with hotkey markers), and the tooltip. -/// -/// \param out the output buffer -/// \param strtype the string type -/// \param out_tooltip an optional output buffer for the tooltip -/// \param flags or'ed PSTF_* constants -/// \return length of generated text - -idaman bool ida_export print_strlit_type( - qstring *out, - int32 strtype, - qstring *out_tooltip = nullptr, - int flags = 0); - - -/// Get additional information about an operand representation. -/// \param buf buffer to receive the result. may not be nullptr -/// \param ea linear address of item -/// \param n number of operand, 0 or 1 -/// \param flags flags of the item -/// \return nullptr if no additional representation information - -idaman opinfo_t *ida_export get_opinfo( - opinfo_t *buf, - ea_t ea, - int n, - flags_t flags); - - -/// Set additional information about an operand representation. -/// This function is a low level one. Only the kernel should use it. -/// \param ea linear address of the item -/// \param n number of operand, 0 or 1 -/// \param flag flags of the item -/// \param ti additional representation information -/// \param suppress_events do not generate changing_op_type and op_type_changed events -/// \return success - -idaman bool ida_export set_opinfo( - ea_t ea, - int n, - flags_t flag, - const opinfo_t *ti, - bool suppress_events=false); - - -/// Get size of data type specified in flags 'F'. -/// \param ea linear address of the item -/// \param F flags -/// \param ti additional information about the data type. For example, -/// if the current item is a structure instance, -/// then ti->tid is structure id. Otherwise is ignored (may be nullptr). -/// If specified as nullptr, will be automatically retrieved from the database -/// \return -/// - byte : 1 -/// - word : 2 -/// - etc... -/// -/// If flags doesn't specify a data, then return 1 - -idaman asize_t ida_export get_data_elsize(ea_t ea, flags_t F, const opinfo_t *ti=nullptr); - - -/// Get full size of data type specified in flags 'F'. -/// takes into account processors with wide bytes -/// e.g. returns 2 for a byte element with 16-bit bytes -inline asize_t get_full_data_elsize(ea_t ea, flags_t F, const opinfo_t *ti=nullptr) -{ - asize_t nbytes = get_data_elsize(ea, F, ti); - return nbytes * bytesize(ea); -} - - -/// Is the item at 'ea' variable size?. -/// \param ea linear address of the item -/// \param F flags -/// \param ti additional information about the data type. For example, -/// if the current item is a structure instance, -/// then ti->tid is structure id. Otherwise is ignored (may be nullptr). -/// If specified as nullptr, will be automatically retrieved from the database -/// \param itemsize if not nullptr and the item is varsize, itemsize -/// will contain the calculated item size (for struct types, the minimal size is returned) -/// \retval 1 varsize item -/// \retval 0 fixed item -/// \retval -1 error (bad data definition) - -idaman int ida_export is_varsize_item( - ea_t ea, - flags_t F, - const opinfo_t *ti=nullptr, - asize_t *itemsize=nullptr); - - -/// Can define item (instruction/data) of the specified 'length', starting at 'ea'? -/// \note if there is an item starting at 'ea', this function ignores it -/// \note this function converts to unexplored all encountered data items -/// with fixup information. Should be fixed in the future. -/// \param flags if not 0, then the kernel will ignore the data types -/// specified by the flags and destroy them. For example: -///
-///                  1000 dw 5
-///                  1002 db 5 ; undef
-///                  1003 db 5 ; undef
-///                  1004 dw 5
-///                  1006 dd 5
-///                  
-/// can_define_item(1000, 6, 0) - false because of dw at 1004 \n -/// can_define_item(1000, 6, word_flag()) - true, word at 1004 is destroyed -/// \return 1-yes, 0-no -/// -/// This function may return 0 if: -/// - a new item would cross segment boundaries -/// - a new item would overlap with existing items (except items specified by 'flags') - -idaman bool ida_export can_define_item(ea_t ea, asize_t length, flags_t flags); - -/// \defgroup FF_CODE Code bytes -/// \ingroup FF_ -/// Represent characteristics of instructions -//@{ - -//------------------------------------------------------------------------- -/// \defgroup FF_codebits Bits: code bytes -//@{ -#define MS_CODE 0xF0000000LU ///< Mask for code bits -#define FF_FUNC 0x10000000LU ///< function start? -// 0x20000000LU // not used -#define FF_IMMD 0x40000000LU ///< Has Immediate value ? -#define FF_JUMP 0x80000000LU ///< Has jump table or switch_info? -//@} - -/// \defgroup FF_codefuncs Functions: work with code bits -//@{ - -/// Has immediate value? - -inline THREAD_SAFE bool idaapi has_immd(flags_t F) { return is_code(F) && (F & FF_IMMD) != 0; } - - -/// Is function start? - -inline THREAD_SAFE bool idaapi is_func(flags_t F) { return is_code(F) && (F & FF_FUNC) != 0; } - - -/// Set 'has immediate operand' flag. -/// Returns true if the #FF_IMMD bit was not set and now is set - -idaman bool ida_export set_immd(ea_t ea); - - -//@} FF_codefuncs -//@} FF_CODE - -//----------------------------------------------------------------------- -// Custom data type and format definitions -//----------------------------------------------------------------------- - -/// Information about a data type -struct data_type_t -{ - int cbsize; ///< size of this structure - void *ud; ///< user-defined data to be passed to callbacks - int props; ///< properties -#define DTP_NODUP 0x0001 ///< do not use dup construct - const char *name; ///< name of the data type. must be unique - const char *menu_name; ///< Visible data type name to use in menus - ///< if nullptr, no menu item will be created - const char *hotkey; ///< Hotkey for the corresponding menu item - ///< if nullptr, no hotkey will be associated with the menu item - const char *asm_keyword; ///< keyword to use for this type in the assembly - ///< if nullptr, the data type cannot be used in the listing - ///< it can still be used in cpuregs window - asize_t value_size; ///< size of the value in bytes - - /// Should this type be shown in UI menus - /// \return success - bool is_present_in_menus() const { return menu_name != nullptr && asm_keyword != nullptr; } - - /// May create data? nullptr means always may - /// \param ud user-defined data - /// \param ea address of the future item - /// \param nbytes size of the future item - bool (idaapi *may_create_at)( - void *ud, - ea_t ea, - size_t nbytes); - - /// This function is used to determine size of the (possible) item at 'ea'. - /// This callback is required only for varsize datatypes. - /// \param ud user-defined data - /// \param ea address of the item - /// \param maxsize maximal size of the item - /// \return 0 if no such item can be created/displayed - asize_t (idaapi *calc_item_size)( - void *ud, - ea_t ea, - asize_t maxsize); -}; - -/// Information about a data format -struct data_format_t -{ - int32 cbsize; ///< size of this structure - void *ud; ///< user-defined data to be passed to callbacks - int props; ///< properties (currently 0) - const char *name; ///< Format name, must be unique - const char *menu_name; ///< Visible format name to use in menus - ///< if nullptr, no menu item will be created - const char *hotkey; ///< Hotkey for the corresponding menu item - ///< if nullptr, no hotkey will be associated with the menu item - asize_t value_size; ///< size of the value in bytes - ///< 0 means any size is ok - ///< data formats that are registered for standard types (dtid 0) - ///< may be called with any value_size (instruction operands only) - int32 text_width; ///< Usual width of the text representation - ///< This value is used to calculate the width - ///< of the control to display values of this type - - /// Should this format be shown in UI menus - /// \return success - bool is_present_in_menus() const { return menu_name != nullptr; } - - /// Convert to colored string. - /// \param ud user-defined data - /// \param out output buffer. may be nullptr - /// \param value value to print. may not be nullptr - /// \param size size of value in 8-bit bytes - /// \param current_ea current address (BADADDR if unknown) - /// \param operand_num current operand number - /// \param dtid custom data type id (0-standard built-in data type) - /// \return success - bool (idaapi *print)( - void *ud, - qstring *out, - const void *value, - asize_t size, - ea_t current_ea, - int operand_num, - int dtid); - - /// Convert from uncolored string. - /// \param ud user-defined data - /// \param value output buffer. may be nullptr - /// \param input input string. may not be nullptr - /// \param current_ea current address (BADADDR if unknown) - /// \param operand_num current operand number (-1 if unknown) - /// \param errstr buffer for error message - /// \return success - bool (idaapi *scan)( - void *ud, - bytevec_t *value, - const char *input, - ea_t current_ea, - int operand_num, - qstring *errstr); - - /// Analyze custom data format occurrence - /// This callback can be used to create xrefs from the current item. - /// This callback may be missing. - /// \param ud user-defined data - /// \param current_ea current address (BADADDR if unknown) - /// \param operand_num current operand number - void (idaapi *analyze)( - void *ud, - ea_t current_ea, - int operand_num); -}; - - -/// Register a new data type. -/// \param dtinfo description of the new data type -/// \return > 0 : id of the new custom data type, -/// < 0 : error when the custom data type with the same name has -/// already been registered -/// \note dtid 0 is reserved for built-in data types. - -idaman int ida_export register_custom_data_type(const data_type_t *dtinfo); - - -/// Unregister a data type. -/// When the idb is closed, all custom data types are automatically -/// unregistered, but since it happens too late (plugin modules could -/// already be unloaded) one has to unregister custom data types explicitly. -/// The ids of unregistered custom data types remain allocated and when the -/// same name is reused to register a custom data type, it will get assigned -/// the same id. -/// \param dtid data type to unregister -/// \retval true ok -/// \retval false no such dtid - -idaman bool ida_export unregister_custom_data_type(int dtid); - - -/// Register a new data format. -/// \param dtform description of the new data format -/// \return > 0 : id of the new custom data format, -/// < 0 : error when the custom data format with the same name has -/// already been registered to the data type -/// \note dfid 0 is unused. - -idaman int ida_export register_custom_data_format(const data_format_t *dtform); - - -/// Unregister a data format. -/// \sa unregister_custom_data_type() -/// \param dfid data format to unregister -/// \retval true ok -/// \retval false no such dfid - -idaman bool ida_export unregister_custom_data_format(int dfid); - - -/// Get definition of a registered custom data type. -/// \param dtid data type id -/// \return data type definition or nullptr - -idaman const data_type_t *ida_export get_custom_data_type(int dtid); - - -/// Get definition of a registered custom data format. -/// \param dfid data format id -/// \return data format definition or nullptr - -idaman const data_format_t *ida_export get_custom_data_format(int dfid); - - -/// Attach the data format to the data type. -/// \param dtid data type id that can use the data format. -/// 0 means all standard data types. Such data formats can be -/// applied to any data item or instruction operands. For -/// instruction operands, the data_format_t::value_size check -/// is not performed by the kernel. -/// \param dfid data format id -/// \retval true ok -/// \retval false no such `dtid', or no such `dfid', or the data format has -/// already been attached to the data type - -idaman bool ida_export attach_custom_data_format(int dtid, int dfid); - - -/// Detach the data format from the data type. -/// Unregistering a custom data type detaches all attached data formats, -/// no need to detach them explicitly. You still need unregister them. -/// Unregistering a custom data format detaches it from all attached data -/// types. -/// \param dtid data type id to detach data format from -/// \param dfid data format id to detach -/// \retval true ok -/// \retval false no such `dtid', or no such `dfid', or the data format was -/// not attached to the data type - -idaman bool ida_export detach_custom_data_format(int dtid, int dfid); - - -/// - -idaman bool ida_export is_attached_custom_data_format(int dtid, int dfid); - -/// Get list of registered custom data type ids. -/// \param out buffer for the output. may be nullptr -/// \param min_size minimum value size -/// \param max_size maximum value size -/// \return number of custom data types with the specified size limits - -idaman int ida_export get_custom_data_types( - intvec_t *out, - asize_t min_size=0, - asize_t max_size=BADADDR); - - -/// Get list of attached custom data formats for the specified data type. -/// \param out buffer for the output. may be nullptr -/// \param dtid data type id -/// \return number of returned custom data formats. if error, returns -1 - -idaman int ida_export get_custom_data_formats(intvec_t *out, int dtid); - - -/// Get id of a custom data type. -/// \param name name of the custom data type -/// \return id or -1 - -idaman int ida_export find_custom_data_type(const char *name); - - -/// Get id of a custom data format. -/// \param name name of the custom data format -/// \return id or -1 - -idaman int ida_export find_custom_data_format(const char *name); - - -//-------------------------------------------------------------------------- -// I N D E N T E D C O M M E N T S -//-------------------------------------------------------------------------- - -/// Set an indented comment. -/// \param ea linear address -/// \param comm comment string -/// - nullptr: do nothing (return 0) -/// - "" : delete comment -/// \param rptble is repeatable? -/// \return success - -idaman bool ida_export set_cmt(ea_t ea, const char *comm, bool rptble); - - -/// Get an indented comment. -/// \param buf output buffer, may be nullptr -/// \param ea linear address. may point to tail byte, the function -/// will find start of the item -/// \param rptble get repeatable comment? -/// \return size of comment or -1 - -idaman ssize_t ida_export get_cmt(qstring *buf, ea_t ea, bool rptble); - - -/// Append to an indented comment. -/// Creates a new comment if none exists. -/// Appends a newline character and the specified string otherwise. -/// \param ea linear address -/// \param str comment string to append -/// \param rptble append to repeatable comment? -/// \return success - -idaman bool ida_export append_cmt(ea_t ea, const char *str, bool rptble); - - -//-------------------------------------------------------------------- -// P R E D E F I N E D C O M M E N T S -//-------------------------------------------------------------------- - -/// Get predefined comment. -/// \param buf buffer for the comment -/// \param ins current instruction information -/// \return size of comment or -1 - -idaman ssize_t ida_export get_predef_insn_cmt( - qstring *buf, - const insn_t &ins); - - -//-------------------------------------------------------------------------- -// S E A R C H F U N C T I O N S -//-------------------------------------------------------------------------- -/// Find forward a byte with the specified value (only 8-bit value from the database). -/// example: ea=4 size=3 will inspect addresses 4, 5, and 6 -/// \param sEA linear address -/// \param size number of bytes to inspect -/// \param value value to find -/// \param bin_search_flags combination of \ref BIN_SEARCH_ -/// \return address of byte or #BADADDR - -idaman ea_t ida_export find_byte(ea_t sEA, asize_t size, uchar value, int bin_search_flags); - - -/// Find reverse a byte with the specified value (only 8-bit value from the database). -/// example: ea=4 size=3 will inspect addresses 6, 5, and 4 -/// \param sEA the lower address of the search range -/// \param size number of bytes to inspect -/// \param value value to find -/// \param bin_search_flags combination of \ref BIN_SEARCH_ -/// \return address of byte or #BADADDR - -idaman ea_t ida_export find_byter(ea_t sEA, asize_t size, uchar value, int bin_search_flags); - - -//------------------------------------------------------------------------- -struct compiled_binpat_t // compiled binary pattern compiled_binpat_t -{ - bytevec_t bytes; - bytevec_t mask; - rangevec_t strlits; // range of string literals, in _bytes_ ranges (not CPs) - int encidx; - - compiled_binpat_t() : encidx(-1) {} - bool all_bytes_defined() const { return mask.empty(); } - void qclear() { bytes.qclear(); mask.qclear(); strlits.qclear(); encidx = -1; } -}; -DECLARE_TYPE_AS_MOVABLE(compiled_binpat_t); -typedef qvector compiled_binpat_vec_t; - -#define PBSENC_DEF1BPU 0 /// Use the default 1 byte-per-unit IDB encoding -#define PBSENC_ALL -1 /// Use all IDB encodings - -/// Convert user-specified binary string to internal representation. -/// \param [out] out a vector of compiled binary patterns, for use with bin_search2() -/// \param ea linear address to convert for (the conversion depends on the -/// address, because the number of bits in a byte depend on the -/// segment type) -/// \param in input text string. contains space-separated: -/// - numbers (numeric base is determined by 'radix') -/// - if value of number fits a byte, it is considered as a byte -/// - if value of number fits a word, it is considered as 2 bytes -/// - if value of number fits a dword,it is considered as 4 bytes -/// - "..." string constants -/// - 'x' single-character constants -/// - ? variable bytes -/// \note Examples of search strings (assuming base 16): -/// CD 21 - bytes 0xCD, 0x21 -/// 21CD - bytes 0xCD, 0x21 (little endian ) or 0x21, 0xCD (big-endian) -/// "Hello", 0 - the null terminated string "Hello" -/// L"Hello" - 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0 -/// B8 ? ? ? ? 90 - byte 0xB8, 4 bytes with any value, byte 0x90 -/// -/// \param radix numeric base of numbers (8,10,16) -/// \param strlits_encoding the target encoding into which the string -/// literals present in 'in', should be encoded. -/// Can be any from [1, get_encoding_qty()), or -/// the special values PBSENC_* -/// \param errbuf error buffer (can be nullptr) -/// \return false either in case of parsing error, or if at least one -/// requested target encoding couldn't encode the string -/// literals present in "in". -// true otherwise -idaman bool ida_export parse_binpat_str( - compiled_binpat_vec_t *out, - ea_t ea, - const char *in, - int radix, - int strlits_encoding=PBSENC_DEF1BPU, - qstring *errbuf=nullptr); - - -/// Search for a string in the program. -/// \param start_ea linear address, start of range to search -/// \param end_ea linear address, end of range to search (exclusive) -/// \param data the prepared data to search for (see parse_binpat_str()) -/// \param flags combination of \ref BIN_SEARCH_ -/// \return #BADADDR (if pressed Ctrl-Break or not found) or string address. - -idaman ea_t ida_export bin_search2( - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &data, - int flags); - -inline ea_t bin_search2( - ea_t start_ea, - ea_t end_ea, - const uchar *image, - const uchar *mask, - size_t len, - int flags) -{ - compiled_binpat_vec_t bbv; - compiled_binpat_t &bv = bbv.push_back(); - bv.bytes.append(image, len); - if ( mask != nullptr ) - bv.mask.append(mask, len); - return bin_search2(start_ea, end_ea, bbv, flags); -} - -//t -/// \defgroup BIN_SEARCH_ Search flags -/// passed as 'flags' parameter to bin_search() -//@{ -#define BIN_SEARCH_CASE 0x01 ///< case sensitive -#define BIN_SEARCH_NOCASE 0x00 ///< case insensitive -#define BIN_SEARCH_NOBREAK 0x02 ///< don't check for Ctrl-Break -#define BIN_SEARCH_INITED 0x04 ///< find_byte, find_byter: any initilized value -#define BIN_SEARCH_NOSHOW 0x08 ///< don't show search progress or update screen -#define BIN_SEARCH_FORWARD 0x00 ///< search forward for bytes -#define BIN_SEARCH_BACKWARD 0x10 ///< search backward for bytes -//@} - - -/// Find the next initialized address - -inline ea_t idaapi next_inited(ea_t ea, ea_t maxea) -{ - if ( ea >= maxea ) - return BADADDR; - ++ea; - return find_byte(ea, maxea-ea, 0, BIN_SEARCH_INITED); -} - -/// Find the previous initialized address - -inline ea_t idaapi prev_inited(ea_t ea, ea_t minea) -{ - if ( ea <= minea ) - return BADADDR; - --ea; - return find_byter(minea, ea-minea, 0, BIN_SEARCH_INITED); -} - -/// Compare 'len' bytes of the program starting from 'ea' with 'image'. -/// \param ea linear address -/// \param image bytes to compare with -/// \param mask array of 1/0 bytes, it's length is 'len'. 1 means to perform -/// the comparison of the corresponding byte. 0 means not to perform. -/// if mask == nullptr, then all bytes of 'image' will be compared. -/// if mask == #SKIP_FF_MASK then 0xFF bytes will be skipped -/// \param len length of block to compare in bytes. -/// \param sense_case case-sensitive comparison? -/// \retval 1 equal -/// \retval 0 not equal - -idaman bool ida_export equal_bytes( - ea_t ea, - const uchar *image, - const uchar *mask, - size_t len, - bool sense_case); - -/// Used by equal_bytes() to skip 0xFF when searching the program -#define SKIP_FF_MASK ((const uchar *)0xFF) - - - -//------------------------------------------------------------------------ -// H I D D E N A R E A S -//------------------------------------------------------------------------ - -/// Hidden ranges - address ranges which can be replaced by their descriptions. -/// There is also a possibility to hide individual items completely (nalt.hpp, hide_item) -/// \note After modifying any of this struct's fields please call update_hidden_range() - -struct hidden_range_t : public range_t -{ - char *description; ///< description to display if the range is collapsed - char *header; ///< header lines to display if the range is expanded - char *footer; ///< footer lines to display if the range is expanded - bool visible; ///< the range state - bgcolor_t color; ///< range color -}; - -/// Update hidden range information in the database. -/// You cannot use this function to change the range boundaries -/// \param ha range to update -/// \return success - -idaman bool ida_export update_hidden_range(const hidden_range_t *ha); - - -/// Mark a range of addresses as hidden. -/// The range will be created in the invisible state with the default color -/// \param ea1 linear address of start of the address range -/// \param ea2 linear address of end of the address range -/// \param description, header, footer range parameters -/// \return success - -idaman bool ida_export add_hidden_range( - ea_t ea1, - ea_t ea2, - const char *description, - const char *header, - const char *footer, - bgcolor_t color); - - -/// Get pointer to hidden range structure, in: linear address. -/// \param ea any address in the hidden range - -idaman hidden_range_t *ida_export get_hidden_range(ea_t ea); - - -/// Get pointer to hidden range structure, in: number of hidden range. -/// \param n number of hidden range, is in range 0..get_hidden_range_qty()-1 - -idaman hidden_range_t *ida_export getn_hidden_range(int n); - - -/// Get number of hidden ranges - -idaman int ida_export get_hidden_range_qty(void); - - -/// Get number of a hidden range. -/// \param ea any address in the hidden range -/// \return number of hidden range (0..get_hidden_range_qty()-1) - -idaman int ida_export get_hidden_range_num(ea_t ea); - - -/// Get pointer to previous hidden range. -/// \param ea any address in the program -/// \return ptr to hidden range or nullptr if previous hidden range doesn't exist - -idaman hidden_range_t *ida_export get_prev_hidden_range(ea_t ea); - - -/// Get pointer to next hidden range. -/// \param ea any address in the program -/// \return ptr to hidden range or nullptr if next hidden range doesn't exist - -idaman hidden_range_t *ida_export get_next_hidden_range(ea_t ea); - - -/// Get pointer to the first hidden range. -/// \return ptr to hidden range or nullptr - -idaman hidden_range_t *ida_export get_first_hidden_range(void); - - -/// Get pointer to the last hidden range. -/// \return ptr to hidden range or nullptr - -idaman hidden_range_t *ida_export get_last_hidden_range(void); - - -/// Delete hidden range. -/// \param ea any address in the hidden range -/// \return success - -idaman bool ida_export del_hidden_range(ea_t ea); - - -//-------------------------------------------------------------------------- -inline ea_t idaapi get_item_head(ea_t ea) -{ - if ( is_tail(get_flags(ea)) ) - ea = prev_not_tail(ea); - return ea; -} - -//------------------------------------------------------------------------ -// M E M O R Y M A P P I N G -//------------------------------------------------------------------------ - -/// IDA supports memory mapping. References to the addresses from -/// the mapped range use data and meta-data from the mapping range. -/// \note You should set flag PR2_MAPPING in ph.flag2 to use memory mapping - - -/// Add memory mapping range. -/// \param from start of the mapped range (nonexistent address) -/// \param to start of the mapping range (existent address) -/// \param size size of the range -/// \return success - -idaman bool ida_export add_mapping(ea_t from, ea_t to, asize_t size); - - -/// Delete memory mapping range. -/// \param ea any address in the mapped range - -idaman void ida_export del_mapping(ea_t ea); - - -/// Translate address according to current mappings. -/// \param ea address to translate -/// \return translated address - -idaman ea_t ida_export use_mapping(ea_t ea); - -/// Get number of mappings. - -idaman size_t ida_export get_mappings_qty(void); - -/// Get memory mapping range by its number. -/// \param from start of the mapped range -/// \param to start of the mapping range -/// \param size size of the range -/// \param n number of mapping range (0..get_mappings_qty()-1) -/// \return false if the specified range doesn't exist, -/// otherwise returns `from', `to', `size' -idaman bool ida_export get_mapping( - ea_t *from, - ea_t *to, - asize_t *size, - size_t n); - - -#ifndef BYTES_SOURCE // undefined bit masks so no one can use them directly -#undef MS_VAL -#undef FF_IVL -#undef MS_CLS -#undef FF_CODE -#undef FF_DATA -#undef FF_TAIL -#undef FF_UNK -#undef MS_COMM -#undef FF_COMM -#undef FF_REF -#undef FF_LINE -#undef FF_NAME -#undef FF_LABL -#undef FF_ANYNAME -#undef FF_FLOW -#undef FF_SIGN -#undef FF_BNOT -#undef MS_0TYPE -#undef FF_0VOID -#undef FF_0NUMH -#undef FF_0NUMD -#undef FF_0CHAR -#undef FF_0SEG -#undef FF_0OFF -#undef FF_0NUMB -#undef FF_0NUMO -#undef FF_0ENUM -#undef FF_0FOP -#undef FF_0STRO -#undef FF_0STK -#undef FF_0FLT -#undef FF_0CUST -#undef MS_1TYPE -#undef FF_1VOID -#undef FF_1NUMH -#undef FF_1NUMD -#undef FF_1CHAR -#undef FF_1SEG -#undef FF_1OFF -#undef FF_1NUMB -#undef FF_1NUMO -#undef FF_1ENUM -#undef FF_1FOP -#undef FF_1STRO -#undef FF_1STK -#undef FF_1FLT -#undef FF_1CUST -#undef DT_TYPE -#undef FF_BYTE -#undef FF_WORD -#undef FF_DWORD -#undef FF_QWORD -#undef FF_OWORD -#undef FF_YWORD -#undef FF_ZWORD -#undef FF_FLOAT -#undef FF_DOUBLE -#undef FF_TBYTE -#undef FF_PACKREAL -#undef FF_STRLIT -#undef FF_STRUCT -#undef FF_ALIGN -#undef FF_CUSTOM -#undef MS_CODE -#undef FF_FUNC -#undef FF_IMMD -//#undef FF_JUMP -#undef MS_TAIL -#undef TL_TSFT -#undef TL_TOFF -#undef MAX_TOFF -#endif // BYTES_SOURCE - -// byte array to hex string -inline THREAD_SAFE ssize_t get_hex_string(char *buf, size_t bufsize, const uchar *bytes, size_t len) -{ - const char *const start = buf; - const char *const end = buf + bufsize; - for ( size_t i = 0; i < len; i++ ) - buf += ::qsnprintf(buf, end - buf, "%02X", *bytes++); - return buf - start; -} - - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED ea_t ida_export bin_search(ea_t, ea_t, const uchar *, const uchar *, size_t, int, int); // use bin_search2() -idaman DEPRECATED uchar ida_export get_8bit(ea_t *ea, uint32 *v, int *nbit); // use get_octet() -#endif - - -#endif // BYTES_HPP diff --git a/idasdk75/include/compress.hpp b/idasdk75/include/compress.hpp deleted file mode 100644 index 0994653..0000000 --- a/idasdk75/include/compress.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef COMPRESS_HPP -#define COMPRESS_HPP - -#include - -/*! \file compress.hpp - - \brief Data compression functions - -*/ - -/// Compress data. -/// This function depends on the value of legacy_idb, so it is not completely -/// thread safe. However, legacy_idb does not change its value. -/// \return \ref PKZ_ - -idaman THREAD_SAFE int ida_export zip_deflate( - void *ud, - ssize_t (idaapi *file_reader)(void *ud, void *buf, size_t size), - ssize_t (idaapi *file_writer)(void *ud, const void *buf, size_t size)); - - -/// Uncompress data. -/// This function depends on the value of legacy_idb, so it is not completely -/// thread safe. However, legacy_idb does not change its value. -/// \return \ref PKZ_ - -idaman THREAD_SAFE int ida_export zip_inflate( - void *ud, - ssize_t (idaapi *file_reader)(void *ud, void *buf, size_t size), - ssize_t (idaapi *file_writer)(void *ud, const void *buf, size_t size)); - - -/// Process zip file and enumerate all files stored in it -/// \param zipfile name of zip file -/// \param callback callback for each file. params: -/// - ud: user data -/// - offset: offset in the zip file -/// - method: compression method (\ref compression_methods) -/// - csize: compressed size -/// - ucsize: uncompressed size -/// - attributes: file attributes -/// \param ud user data -/// \return \ref PKZ_ - -idaman THREAD_SAFE int ida_export process_zipfile( - const char *zipfile, - int (idaapi *callback)( - void *ud, - qoff64_t offset, - int method, - uint64 csize, - uint64 ucsize, - uint32 attributes, - const char *filename), - void *ud = NULL); - - -/// Process zip file and enumerate all files stored in it -/// \param li input file -/// \param callback callback for each file. params: -/// - ud: user data -/// - offset: offset in the zip file -/// - method: compression method (\ref compression_methods) -/// - csize: compressed size -/// - ucsize: uncompressed size -/// - attributes: file attributes -/// \param ud user data -/// \return \ref PKZ_ - -idaman THREAD_SAFE int ida_export process_zip_linput( - linput_t *li, - int (idaapi *callback)( - void *ud, - qoff64_t offset, - int method, - uint64 csize, - uint64 ucsize, - uint32 attributes, - const char *filename), - void *ud = NULL); - - -/// Search for specified entry in zip file, and calls the -/// callback with it, if found. -/// \param zipfile name of zip file -/// \param entry entry in zip file. E.g., "path/to/entry.dat" -/// \param callback callback for each file. params: -/// - ud: user data -/// - offset: offset in the zip file -/// - method: compression method (\ref compression_methods) -/// - csize: compressed size -/// - ucsize: uncompressed size -/// - attributes: file attributes -/// \param ud user data -/// \param case_sensitive should the search be case sensitive? -/// \return \ref PKZ_ - -idaman THREAD_SAFE int ida_export process_zipfile_entry( - const char *zipfile, - const char *entry, - int (idaapi *callback)( - void *ud, - qoff64_t offset, - int method, - uint64 csize, - uint64 ucsize, - uint32 attributes, - const char *filename), - void *ud = NULL, - bool case_sensitive = true); - - -/// \defgroup PKZ_ Compression error codes -/// Returned by functions in compress.hpp -//@{ -#define PKZ_OK 0 -#define PKZ_ERRNO 1 -#define PKZ_STREAM_ERROR 2 -#define PKZ_DATA_ERROR 3 -#define PKZ_MEM_ERROR 4 -#define PKZ_BUF_ERROR 5 -#define PKZ_VERSION_ERROR 6 -#define PKZ_RERR 777 // read error -#define PKZ_WERR 778 // write error -//@} - -/// \defgroup compression_methods Compression methods -/// passed as 'method' parameter to callback functions in compress.hpp -//@{ -#define STORED 0 -#define SHRUNK 1 -#define REDUCED1 2 -#define REDUCED2 3 -#define REDUCED3 4 -#define REDUCED4 5 -#define IMPLODED 6 -#define TOKENIZED 7 -#define DEFLATED 8 -#define NUM_METHODS 9 /* index of last method + 1 */ -//@} - -extern bool legacy_idb; ///< for old idb files - -/// Upon closing outer linput, perform one of these actions -enum linput_close_code_t -{ - LOC_CLOSE, ///< close the inner linput - LOC_UNMAKE, ///< unmake the inner linput - LOC_KEEP, ///< do nothing -}; - - -/// Create a linput to read a compressed input stream -/// \param in linput with compressed data, seeked to the stream beginning -/// \param insize size of compressed data. -1 - unknown -/// \param loc what to do upon closing the resulting linput -/// \return linput that can be used to read uncompressed data. -/// NULL if any error (no more linput descriptors). - -idaman THREAD_SAFE linput_t *ida_export create_zip_linput( - linput_t *in, - ssize_t insize=-1, - linput_close_code_t loc=LOC_CLOSE); - -#endif diff --git a/idasdk75/include/config.hpp b/idasdk75/include/config.hpp deleted file mode 100644 index c0c054e..0000000 --- a/idasdk75/include/config.hpp +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _CONFIG_HPP -#define _CONFIG_HPP - -//----------------------------------------------------------------------- -/// \defgroup IDPOPT_T Option value types -/// Passed as 'value_type' parameter to ::set_options_t callbacks -//@{ -#define IDPOPT_STR 1 ///< string constant (char *) -#define IDPOPT_NUM 2 ///< number (uval_t *) -#define IDPOPT_BIT 3 ///< bit, yes/no (int *) -#define IDPOPT_I64 5 ///< 64bit number (int64 *) -#define IDPOPT_CST 6 ///< lexer (lexer_t*) - ///< Custom type, starting with a '{' - ///< Values of this type should be handled by - ///< ::set_options_t callbacks. E.g.,: - ///< \code - ///< ERROR_STRINGS = - ///< { - ///< {0, "Unknown error"}, - ///< {1, "Missing filename"}, - ///< {5, "Out-of-memory"} - ///< } - ///< \endcode - ///< For values of this type, the data that will - ///< be passed as the callback's 'value' parameter - ///< is the lexer instance that is being used - ///< to parse the configuration file. - ///< You can use \ref parse_json() (see parsejson.hpp) - ///< to parse JSON-format data - ///< NB: the '{' is already consumed by the parser, - ///< so you need to push it again if it's a part of the JSON object -//@} - -/// \defgroup IDPOPT_RET Option result codes -/// Predefined return values for ::set_options_t callbacks -//@{ -#define IDPOPT_OK NULL ///< ok -#define IDPOPT_BADKEY ((char*)1) ///< illegal keyword -#define IDPOPT_BADTYPE ((char*)2) ///< illegal type of value -#define IDPOPT_BADVALUE ((char*)3) ///< illegal value (bad range, for example) -//@} - - -/// Callback - called when a config directive is processed in IDA. -/// Also see read_config_file() and processor_t::set_idp_options -/// \param keyword keyword encountered in IDA.CFG/user config file. -/// if NULL, then an interactive dialog form should be displayed -/// \param value_type type of value of the keyword - one of \ref IDPOPT_T -/// \param value pointer to value -/// \param idb_loaded true if the ev_oldfile/ev_newfile events have been generated? -/// \return one of \ref IDPOPT_RET, otherwise a pointer to an error message - -typedef const char *(idaapi set_options_t)( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded); - -/// \defgroup IDAOPT_PRIO Option priority -/// Specifies the priority of a configuration option. Since options may -/// be specified in different way, and applied in various orders, we need -/// option priorities. -/// Normally the default priority option does not overwrite the existing value -/// whereas the high priority one does. -/// High priority options may be stored in the database to be available -/// in the next session. -//@{ -#define IDPOPT_PRI_DEFAULT 1 ///< default priority - taken from config file -#define IDPOPT_PRI_HIGH 2 ///< high priority - received from UI or a script function -//@} - - -//------------------------------------------------------------------------- -/// Parse the value type for the value token 'value'. -/// This is mostly used for converting from values that a cfgopt_handler_t -/// receives, into data that callbacks -/// - processor_t::set_idp_options -/// - debugger_t::set_dbg_options -/// expect. -/// -/// Plugins that wish to use options shouldn't rely on this, -/// and use the cfgopt_t utility instead. -/// -/// \param out parsed data -/// \param lx the lexer in use -/// \param value the value token -/// \return true if guessing didn't lead to an error, false otherwise. -/// note that even if 'true' is returned, it doesn't mean the -/// type could be guessed: merely that no syntax error occurred. -class lexer_t; -struct token_t; -idaman bool ida_export parse_config_value( - idc_value_t *out, - lexer_t *lx, - const token_t &value); - -//------------------------------------------------------------------------- -typedef const char *(idaapi cfgopt_handler_t)( - lexer_t *lx, - const token_t &keyword, - const token_t &value); - -//------------------------------------------------------------------------- -typedef const char *(idaapi cfgopt_handler2_t)( - lexer_t *lx, - const token_t &keyword, - const token_t &value, - int64 param1, - int64 param2); - -//------------------------------------------------------------------------- -typedef const char *(idaapi cfgopt_handler3_t)( - lexer_t *lx, - const token_t &keyword, - const token_t &value, - int64 param1, - int64 param2, - void *obj); - -//----------------------------------------------------------------------- -/// used by cfgopt_t. You shouldn't have to deal with those directly. -#define IDPOPT_NUM_INT (0) -#define IDPOPT_NUM_CHAR (1 << 24) -#define IDPOPT_NUM_SHORT (2 << 24) -#define IDPOPT_NUM_RANGE (1 << 26) -#define IDPOPT_NUM_UNS (1 << 27) - -#define IDPOPT_BIT_UINT 0 -#define IDPOPT_BIT_UCHAR (1 << 24) -#define IDPOPT_BIT_USHORT (2 << 24) -#define IDPOPT_BIT_BOOL (3 << 24) - -#define IDPOPT_STR_QSTRING (1 << 24) -#define IDPOPT_STR_LONG (1 << 25) - -#define IDPOPT_I64_RANGES (1 << 24) -#define IDPOPT_I64_UNS (1 << 25) - -#define IDPOPT_CST_PARAMS (1 << 24) - -#define IDPOPT_MBROFF (1 << 18) - -//------------------------------------------------------------------------- -struct cfgopt_t; -idaman const char *ida_export cfgopt_t__apply( - const cfgopt_t *_this, - int vtype, - const void *vdata); -idaman const char *ida_export cfgopt_t__apply2( - const cfgopt_t *_this, - int vtype, - const void *vdata, - void *obj); - -//------------------------------------------------------------------------- -// cfgopt_t objects are suitable for being statically initialized, and -// passed to 'read_config_file'. -// -// E.g., -// --- -// static const cfgopt_t g_opts[] = -// { -// cfgopt_t("AUTO_UNDEFINE", &auto_undefine, -1, 1), -// cfgopt_t("NOVICE", &novice, true), -// cfgopt_t("EDITOR", editor_buf, sizeof(editor_buf)), -// cfgopt_t("SCREEN_PALETTE", set_screen_palette), // specific handler for SCREEN_PALETTE -// }; -// -// ... -// -// read_config_file("myfile", g_opts, qnumber(g_opts), other_handler) -// --- -// -// NOTES: -// * so-called 'long' strings (the default) can span on multiple lines, -// and are terminated by a ';' -struct cfgopt_t -{ - const char *name; - union - { - void *ptr; - size_t mbroff; // offset of a structure member - cfgopt_handler_t *hnd; // to avoid reinterpret_cast and gcc's error: - cfgopt_handler2_t *hnd2; // "a reinterpret_cast is not a constant expression" - cfgopt_handler3_t *hnd3; // - }; - int flags; - struct num_range_t - { - constexpr num_range_t(int64 _min, int64 _max) : minval(_min), maxval(_max) {} - int64 minval; - int64 maxval; - }; - struct params_t - { - constexpr params_t(int64 _p1, int64 _p2) : p1(_p1), p2(_p2) {} - int64 p1; - int64 p2; - }; - union - { - size_t buf_size; - num_range_t num_range; - uint32 bit_flags; - params_t params; - void *mbroff_obj; - }; - - // IDPOPT_STR - constexpr cfgopt_t(const char *_n, char *_p, size_t _sz, bool _long = true) - : name(_n), ptr(_p), flags(IDPOPT_STR | (_long ? IDPOPT_STR_LONG : 0)), buf_size(_sz) - {} - constexpr cfgopt_t(const char *_n, qstring *_p, bool _long = true) - : name(_n), ptr(_p), flags(IDPOPT_STR | IDPOPT_STR_QSTRING | (_long ? IDPOPT_STR_LONG : 0)), buf_size(0) - {} - - // IDPOPT_NUM - constexpr cfgopt_t(const char *_n, int *_p) - : name(_n), ptr(_p), flags(IDPOPT_NUM), buf_size(0) {} - constexpr cfgopt_t(const char *_n, uint *_p) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS), buf_size(0) {} - constexpr cfgopt_t(const char *_n, char *_p) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_CHAR), buf_size(0) {} - constexpr cfgopt_t(const char *_n, uchar *_p) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_CHAR), buf_size(0) {} - constexpr cfgopt_t(const char *_n, short *_p) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_SHORT), buf_size(0) {} - constexpr cfgopt_t(const char *_n, ushort *_p) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_SHORT), buf_size(0) {} - // IDPOPT_NUM + ranges - constexpr cfgopt_t(const char *_n, int *_p, int _min, int _max) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_RANGE), num_range(_min, _max) {} - constexpr cfgopt_t(const char *_n, uint *_p, uint _min, uint _max) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_RANGE), num_range(_min, _max) {} - constexpr cfgopt_t(const char *_n, char *_p, char _min, char _max) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_CHAR | IDPOPT_NUM_RANGE), num_range(_min, _max) {} - constexpr cfgopt_t(const char *_n, uchar *_p, uchar _min, uchar _max) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_CHAR | IDPOPT_NUM_RANGE), num_range(_min, _max) {} - constexpr cfgopt_t(const char *_n, short *_p, short _min, short _max) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_RANGE | IDPOPT_NUM_SHORT), num_range(_min, _max) {} - constexpr cfgopt_t(const char *_n, ushort *_p, ushort _min, ushort _max) - : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_RANGE | IDPOPT_NUM_SHORT), num_range(_min, _max) {} - - // IDPOPT_BIT - constexpr cfgopt_t(const char *_n, bool *_p, bool _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT | IDPOPT_BIT_BOOL), bit_flags(_flags) {} - constexpr cfgopt_t(const char *_n, uchar *_p, uchar _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT | IDPOPT_BIT_UCHAR), bit_flags(_flags) {} - constexpr cfgopt_t(const char *_n, ushort *_p, ushort _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT | IDPOPT_BIT_USHORT), bit_flags(_flags) {} - constexpr cfgopt_t(const char *_n, uint32 *_p, uint32 _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT), bit_flags(_flags) {} - - // IDPOPT_I64 - constexpr cfgopt_t(const char *_n, int64 *_p) : name(_n), ptr(_p), flags(IDPOPT_I64), buf_size(0) {} - constexpr cfgopt_t(const char *_n, uint64 *_p) : name(_n), ptr(_p), flags(IDPOPT_I64 | IDPOPT_NUM_UNS), buf_size(0) {} - // IDPOPT_I64 + ranges - constexpr cfgopt_t(const char *_n, int64 *_p, int64 _min, int64 _max) - : name(_n), ptr(_p), flags(IDPOPT_I64 | IDPOPT_I64_RANGES), num_range(_min, _max) {} - constexpr cfgopt_t(const char *_n, uint64 *_p, uint64 _min, uint64 _max) - : name(_n), ptr(_p), flags(IDPOPT_I64 | IDPOPT_I64_UNS | IDPOPT_I64_RANGES), num_range(int64(_min), int64(_max)) {} - - // IDPOPT_CST - constexpr cfgopt_t(const char *_n, cfgopt_handler_t *_p) - : name(_n), hnd(_p), flags(IDPOPT_CST), buf_size(0) {} - // IDPOPT_CST + params - constexpr cfgopt_t(const char *_n, cfgopt_handler2_t *_p, int64 _p1=0, int64 _p2=0) - : name(_n), hnd2(_p), flags(IDPOPT_CST | IDPOPT_CST_PARAMS), params(_p1, _p2) {} - - // configuration option based on the offset of a structure member - - // IDPOPT_STR - template - constexpr cfgopt_t(const char *_n, qstring T:: *, size_t _mbroff, bool _long = true) - : name(_n), - mbroff(_mbroff), - flags(IDPOPT_MBROFF | IDPOPT_STR | IDPOPT_STR_QSTRING | (_long ? IDPOPT_STR_LONG : 0)), - buf_size(0) - {} -#define CFGOPT_QS(nm, cfgt, cfgm, _long) \ - cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm), _long) - -#define CFGOPT_INNER_QS(nm, cfgt, cfgm, mt, mf, _long) \ - cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf), _long) - - - // IDPOPT_NUM -#define CTR_CFGOPT(ctrtype, ctrflags) \ - template \ - constexpr cfgopt_t(const char *_n, ctrtype T:: *, size_t _mbroff) \ - : name(_n), \ - mbroff(_mbroff), \ - flags(IDPOPT_MBROFF|IDPOPT_NUM|ctrflags), \ - buf_size(0) \ - {} - CTR_CFGOPT(int, 0) - CTR_CFGOPT(uint, IDPOPT_NUM_UNS) - CTR_CFGOPT(char, IDPOPT_NUM_CHAR) - CTR_CFGOPT(uchar, IDPOPT_NUM_UNS|IDPOPT_NUM_CHAR) - CTR_CFGOPT(short, IDPOPT_NUM_SHORT) - CTR_CFGOPT(ushort, IDPOPT_NUM_SHORT|IDPOPT_NUM_UNS) -#undef CTR_CFGOPT - -#define CFGOPT_N(nm, cfgt, cfgm) \ - cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm)) - -#define CFGOPT_INNER_N(nm, cfgt, cfgm, mt, mf) \ - cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf)) - - - // IDPOPT_NUM + ranges -#define CTR_CFGOPT(ctrtype, ctrflags) \ - template \ - constexpr cfgopt_t(const char *_n, ctrtype T:: *, size_t _mbroff, int64 _min, int64 _max) \ - : name(_n), \ - mbroff(_mbroff), \ - flags(IDPOPT_MBROFF|IDPOPT_NUM|IDPOPT_NUM_RANGE|ctrflags), \ - num_range(_min, _max) \ - {} - CTR_CFGOPT(int, 0) - CTR_CFGOPT(uint, IDPOPT_NUM_UNS) - CTR_CFGOPT(char, IDPOPT_NUM_CHAR) - CTR_CFGOPT(uchar, IDPOPT_NUM_UNS|IDPOPT_NUM_CHAR) - CTR_CFGOPT(short, IDPOPT_NUM_SHORT) - CTR_CFGOPT(ushort, IDPOPT_NUM_SHORT|IDPOPT_NUM_UNS) -#undef CTR_CFGOPT - -#define CFGOPT_R(nm, cfgt, cfgm, min, max) \ - cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm), min, max) - -#define CFGOPT_INNER_R(nm, cfgt, cfgm, mt, mf, min, max) \ - cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf), min, max) - - - // IDPOPT_BIT -#define CTR_CFGOPT(ctrtype, ctrflags) \ - template \ - constexpr cfgopt_t(const char *_n, ctrtype T:: *, size_t _mbroff, ctrtype _flags) \ - : name(_n), \ - mbroff(_mbroff), \ - flags(IDPOPT_MBROFF|IDPOPT_BIT|ctrflags), \ - bit_flags(_flags) \ - {} - CTR_CFGOPT(bool, IDPOPT_BIT_BOOL); - CTR_CFGOPT(uchar, IDPOPT_BIT_UCHAR); - CTR_CFGOPT(ushort, IDPOPT_BIT_USHORT); - CTR_CFGOPT(uint32, 0); -#undef CTR_CFGOPT -#define CFGOPT_B(nm, cfgt, cfgm, _flags) \ - cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm), _flags) - -#define CFGOPT_INNER_B(nm, cfgt, cfgm, mt, mf, _flags) \ - cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf), _flags) - - - // IDPOPT_I64 - template - constexpr cfgopt_t(const char *_n, int64 T:: *, size_t _mbroff) - : name(_n), - mbroff(_mbroff), - flags(IDPOPT_MBROFF|IDPOPT_I64), - buf_size(0) - {} - template - constexpr cfgopt_t(const char *_n, uint64 T:: *, size_t _mbroff) - : name(_n), - mbroff(_mbroff), - flags(IDPOPT_MBROFF|IDPOPT_I64|IDPOPT_NUM_UNS), - buf_size(0) - {} - - // IDPOPT_I64 + ranges - template - constexpr cfgopt_t(const char *_n, int64 T:: *, size_t _mbroff, int64 _min, int64 _max) - : name(_n), - mbroff(_mbroff), - flags(IDPOPT_MBROFF|IDPOPT_I64|IDPOPT_I64_RANGES), - num_range(_min, _max) - {} - template - constexpr cfgopt_t(const char *_n, uint64 T:: *, size_t _mbroff, uint64 _min, uint64 _max) - : name(_n), - mbroff(_mbroff), - flags(IDPOPT_MBROFF|IDPOPT_I64|IDPOPT_I64_UNS|IDPOPT_I64_RANGES), - num_range(int64(_min), int64(_max)) - {} - - // IDPOPT_CST + params - constexpr cfgopt_t(const char *_n, cfgopt_handler3_t *_p, int64 _p1=0, int64 _p2=0) - : name(_n), hnd3(_p), flags(IDPOPT_MBROFF|IDPOPT_CST), params(_p1, _p2) {} - - int type() const { return flags & 0xf; } - int qualifier() const { return flags & 0xf000000; } - - const char *apply(int vtype, const void *vdata, void *obj=nullptr) const - { - return cfgopt_t__apply2(this, vtype, vdata, obj); - } -}; - -/// Parse the input, and apply options. -/// -/// \param input input file name, or string -/// \param is_file is input a string, or a file name -/// \param opts options destcriptions -/// \param nopts the number of entries present in the 'opts' array -/// \param defhdlr a handler to be called, if a directive couldn't be found in 'opts' -/// \param defines a list of preprocessor identifiers to define (so it is -/// possible to use #ifdef checks in the file.) -/// NB: the actual identifier defined by the parser will be -/// surrounded with double underscores (e.g., passing 'FOO' -/// will result in '__FOO__' being defined) -/// Additionally, the parser will also define a similar macro -/// with the current processor name (e.g., __ARM__) -/// \param ndefines the number of defines in the list -/// \param obj see cfgopt_t constructor based on the offset of a structure member -/// \return true if parsing finished without errors, false if there was a -/// syntax error, callback returned an error, or no file was found -/// at all. - -idaman bool ida_export read_config( - const char *input, - bool is_file, - const cfgopt_t opts[], - size_t nopts, - cfgopt_handler_t *defhdlr = NULL, - const char *const *defines = NULL, - size_t ndefines = 0); - -idaman bool ida_export read_config2( - const char *input, - bool is_file, - const cfgopt_t opts[], - size_t nopts, - cfgopt_handler_t *defhdlr = nullptr, - const char *const *defines = nullptr, - size_t ndefines = 0, - void *obj = nullptr); - -inline bool read_config_file2( - const char *filename, - const cfgopt_t opts[], - size_t nopts, - cfgopt_handler_t *defhdlr = nullptr, - const char *const *defines = nullptr, - size_t ndefines = 0, - void *obj = nullptr) -{ - return read_config2(filename, true, opts, nopts, defhdlr, defines, ndefines, obj); -} - -/// Search for all IDA system files with the given name. -/// This function will search, in that order, for the following files: -/// -# %IDADIR%/cfg/ -/// -# for each directory 'ONEDIR' in %IDAUSR%: %ONEDIR%/cfg/ -/// -/// For each directive in each of those files, the same processing as -/// that of read_config will be performed. - -inline bool read_config_file( - const char *filename, - const cfgopt_t opts[], - size_t nopts, - cfgopt_handler_t *defhdlr = NULL, - const char *const *defines = NULL, - size_t ndefines = 0) -{ - return read_config(filename, true, opts, nopts, defhdlr, defines, ndefines); -} - - -/// For each directive in 'string', the same processing as that of -/// read_config will be performed. -inline bool read_config_string( - const char *string, - const cfgopt_t opts[], - size_t nopts, - cfgopt_handler_t *defhdlr = NULL, - const char *const *defines = NULL, - size_t ndefines = 0) -{ - return read_config(string, false, opts, nopts, defhdlr, defines, ndefines); -} - - -/// Process one or more config directive(s). -/// \param directive the directives to process -/// \param priority priority \ref IDPOPT_RET -/// In the case of errors this function displays a message and exits. - -idaman void ida_export process_config_directive( - const char *directive, - int priority=IDPOPT_PRI_HIGH); - - -/// Register array of config options. -/// This function can be used by a plugin to register the config options. -/// After registering an option, it becomes usable by the -/// process_config_directive() function. -/// \param opts array of config options -/// \param nopts number of options to install. 0 means uninstall -/// \param cb callback that will be invoked upon changing a config option -/// \param obj see cfgopt_t constructor based on the offset of a structure member -/// \return success - -typedef void idaapi config_changed_cb_t(const cfgopt_t &opt, int vtype, const void *vdata); - -idaman bool ida_export register_cfgopts( - const cfgopt_t opts[], - size_t nopts, - config_changed_cb_t cb=nullptr, - void *obj=nullptr); - - -/// Get one of config parameters defined by CC_PARMS in ida.cfg. -/// All parameters for all compilers are stored in local map during last read -/// of ida.cfg - this function just returns previously stored parameter value for -/// given compiler (NULL if no such parameter) -idaman const char *ida_export cfg_get_cc_parm(comp_t compid, const char *name); - - -/// Get header path config parameter from ida.cfg. -/// Also see cfg_get_cc_parm() - -inline const char *cfg_get_cc_header_path(comp_t compid) -{ - return cfg_get_cc_parm(compid, "HEADER_PATH"); -} - - -/// Get predefined macros config parameter from ida.cfg. -/// Also see cfg_get_cc_parm() - -inline const char *cfg_get_cc_predefined_macros(comp_t compid) -{ - return cfg_get_cc_parm(compid, "PREDEFINED_MACROS"); -} - -#endif // _CONFIG_HPP diff --git a/idasdk75/include/dbg.hpp b/idasdk75/include/dbg.hpp deleted file mode 100644 index b6c450b..0000000 --- a/idasdk75/include/dbg.hpp +++ /dev/null @@ -1,2624 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef DBG_HPP -#define DBG_HPP - -#include -#include -#include // for callui() and ui_notification_t - -/*! \file dbg.hpp - - \brief Contains functions to control the debugging of a process. - - See \ref dbg_funcs for a complete explanation of these functions. - - These functions are inlined for the kernel. - They are not inlined for the user-interfaces. -*/ - -//-------------------------------------------------------------------- -// D E B U G G E R I N F O R M A T I O N -//-------------------------------------------------------------------- - -/// This structure contains information about the current debugger. -/// (NULL if no debugger was loaded) - see idd.hpp for details about this structure. -/// -/// All functions defined in this structure should only be called by the kernel !!! -idaman debugger_t ida_export_data *dbg; - -//-------------------------------------------------------------------- -// D E B U G G E R C A L L B A C K S -//-------------------------------------------------------------------- -/// Debugger notification codes. -/// -/// A plugin can receive notifications of all major events in the -/// debugger, by calling the hook_to_notification_point() function -/// with ::HT_DBG as ::hook_type_t (see loader.hpp for details about -/// installing and removing such callbacks). -/// -/// IDA generates two major different types of debugger notifications: -/// -/// - debugger event notification: -/// this notification monitors usual events occurring during the -/// execution of a process. -/// These event notifications are always generated for any process. -/// Some of these event notifications are interpreted by IDA -/// (high-level events), while others are directly generated by the -/// debugger module (low-level events). -/// Low-level events always return a ::debug_event_t structure as an argument. -/// -/// - debugger asynchronous function result notification: -/// such a notification occurs only when a debugger properly terminated -/// the execution of an asynchronous function (see \ref dbg_funcs) -/// -/// How to control the process execution (after the execution of all notification -/// handlers) from the notification handler: -/// -/// - to force the process to STOP: -/// call suspend_process(). -/// In this case, the current debugger command will be aborted and no new -/// request will be started. -/// -/// - to force the process to CONTINUE: -/// call continue_process(). -/// In this case, no new request will be started. -/// -/// - to start new debugger command(s): -/// call as many request_COMMAND() as needed, then call run_requests(). -/// In this case, the current debugger command (if any) will be aborted. -/// (see \ref dbg_funcs in this file for more details about requests) -/// -/// - else, the process execution will depend on the current debugger options or -/// object settings. Some examples: -/// - a new loaded library will stop the process depending on the associated debugger option. -/// - a breakpoint will stop the process depending on its properties. -/// -/// A plugin must not call asynchronous debugger functions from the notification handler! -/// Use the REQUEST QUEUE mechanism instead (request_...()). -/// -/// If the plugin wants to access the process memory from a notification point, -/// it should call invalidate_dbgmem_config() and/or invalidate_dbgmem_contents() -/// functions. The invalidate_dbgmem_config() is really slow, so do not call it -/// unless the process memory config have changed after the last time the process -/// was suspended. The invalidate_dbgmem_contents() is fast and flushes the -/// memory cache in the ida kernel. Without it, functions like get_byte() would -/// return stale values! -enum dbg_notification_t -{ - dbg_null = 0, - - // debugger low-level event notifications (see IDD.HPP for details). - - dbg_process_start, ///< \param event (const ::debug_event_t *) - ///< \note This event notification is also an asynchronous - ///< function result notification for start_process() ! - - dbg_process_exit, ///< \param event (const ::debug_event_t *) - ///< \note This event notification is also an asynchronous - ///< function result notification for start_process() ! - - dbg_process_attach, ///< \param event (const ::debug_event_t *) - ///< \note This event notification is also an asynchronous - ///< function result notification for start_process() ! - - dbg_process_detach, ///< \param event (const ::debug_event_t *) - ///< \note This event notification is also an asynchronous - ///< function result notification for start_process() ! - - dbg_thread_start, ///< \param event (const ::debug_event_t *) - - dbg_thread_exit, ///< \param event (const ::debug_event_t *) - - dbg_library_load, ///< \param event (const ::debug_event_t *) - - dbg_library_unload, ///< \param event (const ::debug_event_t *) - - dbg_information, ///< \param event (const ::debug_event_t *) - - dbg_exception, ///< \param event (const ::debug_event_t *) - ///< \param[out] warn (int *) filled with: - ///< - -1: display an exception warning dialog - ///< if the process is suspended. - ///< - 0: never display an exception warning dialog. - ///< - 1: always display an exception warning dialog. - - // debugger high-level event notifications - - dbg_suspend_process, ///< The process is now suspended. - ///< \param event (const ::debug_event_t *) - ///< \note This event notification is also an asynchronous - ///< function result notification for suspend_process() ! - - dbg_bpt, ///< A user defined breakpoint was reached. - ///< \param tid (::thid_t) - ///< \param bptea (::ea_t) - ///< \param[out] warn (int *) filled with: - ///< - -1: display an exception warning dialog - ///< if the process is suspended. - ///< - 0: never display an exception warning dialog. - ///< - 1: always display an exception warning dialog. - - dbg_trace, ///< A step occurred (one instruction was executed). This event - ///< notification is only generated if step tracing is enabled. - ///< \param tid (::thid_t) thread ID - ///< \param ip (::ea_t) current instruction pointer. - ///< usually points after the executed instruction - ///< \retval 1 do not log this trace event - ///< \retval 0 log it - - dbg_request_error, ///< An error occurred during the processing of a request. - ///< \param failed_command (::ui_notification_t) - ///< \param failed_dbg_notification (::dbg_notification_t) - - // debugger asynchronous function result notifications - // Please note some low-level event notifications also act as asynchronous - // function result notifications. - - dbg_step_into, ///< \param event (const ::debug_event_t *) - - dbg_step_over, ///< \param event (const ::debug_event_t *) - - dbg_run_to, ///< \param event (const ::debug_event_t *) - - dbg_step_until_ret, ///< \param event (const ::debug_event_t *) - - dbg_bpt_changed, ///< Breakpoint has been changed. - ///< \param bptev_code (int) \ref BPTEV_ - ///< \param bpt (::bpt_t *) - - dbg_started_loading_bpts, ///< Started loading breakpoint info from idb - dbg_finished_loading_bpts, ///< Finished loading breakpoint info from idb - - dbg_last, ///< The last debugger notification code -}; - -/// \defgroup BPTEV_ Breakpoint modification events -/// Passed as 'bptev_code' parameter to ::dbg_bpt_changed callback -//@{ -#define BPTEV_ADDED 0 ///< Breakpoint has been added -#define BPTEV_REMOVED 1 ///< Breakpoint has been removed -#define BPTEV_CHANGED 2 ///< Breakpoint has been modified -//@} - -#ifndef __UI__ - -//-------------------------------------------------------------------- -// D E B U G G E R F U N C T I O N S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs Debugger functions -/// -/// Control the debugging of a process. -/// -/// Debugger functions complete either SYNCHRONOUSLY or ASYNCHRONOUSLY: -/// -/// - SYNCHRONOUS FUNCTIONS execute the entire action before the function returns. -/// -/// - ASYNCHRONOUS FUNCTIONS return before the action has executed in its -/// entirety. They simply start the action, but the result of the action will -/// only be available later. For example, run_to() can execute a lot of -/// instructions before terminating. -/// Such functions provide a notification code to indicate the end of their -/// execution (see the 'Notification' keyword in the function documentation). -/// Install a callback using hook_to_notification_point() to be notified -/// when the action is terminated. -/// -/// DEBUGGER COMMANDS are functions who influence the execution of the debugged -/// process. They are available in 2 forms: -/// -/// - COMMAND(): (e.g. suspend_process()) -/// In this mode, the command will be directly executed. However, it is forbidden -/// to use asynchronous commands in this mode from a debugger notification handler -/// (see ::dbg_notification_t). -/// -/// - request_COMMAND(): (e.g. request_suspend_process()) -/// In this mode, a REQUEST to run the command will be memorized at the end of -/// the REQUEST QUEUE (see below). This is mandatory to use this mode for asynchronous -/// commands from a debugger notification handler (see ::dbg_notification_t). -/// -/// -/// The REQUEST QUEUE contains a list of planned debugger commands. -/// These commands will be started only in the following cases: -/// -/// - the previous command terminated, and no call to suspend_process() -/// or continue_process() occurred in the asynchronous function result -/// notification handler (if any). -/// -/// - run_requests() was called. -/// Please note that when called from a debugger notification handler the -/// queued requests will only be started after the execution of all -/// notification handlers. -/// -/// A request which fails to start (by returning 0) will generate a -/// ::dbg_request_error notification. -//@{ - -/// Execute requests until all requests are processed or an asynchronous -/// function is called. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return false if not all requests could be processed -/// (indicates an asynchronous function was started) -/// \note If called from a notification handler, the execution of requests will -/// be postponed to the end of the execution of all notification handlers. - -inline bool idaapi run_requests(void) { return callui(ui_dbg_run_requests).cnd; } - - -/// Get the current running request. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return ui_null if no running request - -inline ui_notification_t idaapi get_running_request(void) { return (ui_notification_t)callui(ui_dbg_get_running_request).i; } - - -/// Is a request currently running? - -inline bool is_request_running(void) { return get_running_request() != ui_null; } - - -/// Get the notification associated (if any) with the current running request. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return dbg_null if no running request - -inline dbg_notification_t idaapi get_running_notification(void) { return (dbg_notification_t)callui(ui_dbg_get_running_notification).i; } - - -/// Clear the queue of waiting requests. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \note If a request is currently running, this one isn't stopped. - -inline void idaapi clear_requests_queue(void) { callui(ui_dbg_clear_requests_queue); } -//@} dbg_funcs - -//-------------------------------------------------------------------- -// P R O C E S S C O M M A N D S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_cmds Process commands -/// \ingroup dbg_funcs -/// -/// Use these functions to manipulate the debugged process. -//@{ - -/// Return the state of the currently debugged process. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return one of \ref DSTATE_ - -inline int idaapi get_process_state(void) { return callui(ui_dbg_get_process_state).i; } - -#endif // __UI__ - -/// \defgroup DSTATE_ Debugged process states -/// See get_process_state(), set_process_state(), invalidate_dbg_state() -//@{ -#define DSTATE_SUSP -1 ///< process is suspended and will not continue -#define DSTATE_NOTASK 0 ///< no process is currently debugged -#define DSTATE_RUN 1 ///< process is running -//@} - -/// \defgroup DBGINV_ Debugged process invalidation options -/// See set_process_state() and invalidate_dbg_state() -//@{ -#define DBGINV_MEMORY 0x0001 ///< invalidate cached memory contents -#define DBGINV_MEMCFG 0x0002 ///< invalidate cached process segmentation -#define DBGINV_REGS 0x0004 ///< invalidate cached register values -#define DBGINV_ALL 0x7FFF ///< invalidate everything -#define DBGINV_REDRAW 0x8000 ///< refresh the screen -#define DBGINV_NONE 0 ///< invalidate nothing -//@} - -#ifndef __UI__ - -/// Set new state for the debugged process. -/// Notifies the IDA kernel about the change of the debugged process state. -/// For example, a debugger module could call this function when it knows -/// that the process is suspended for a short period of time. -/// Some IDA API calls can be made only when the process is suspended. -/// The process state is usually restored before returning control to the caller. -/// You must know that it is ok to change the process state, doing it at arbitrary -/// moments may crash the application or IDA. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param newstate new process state (one of \ref DSTATE_) -/// if #DSTATE_NOTASK is passed then the state is not changed -/// \param p_thid ptr to new thread id. may be NULL or pointer to #NO_THREAD. -/// the pointed variable will contain the old thread id upon return -/// \param dbginv \ref DBGINV_ -/// \return old debugger state (one of \ref DSTATE_) - -inline int idaapi set_process_state(int newstate, thid_t *p_thid, int dbginv) { return callui(ui_dbg_set_process_state, newstate, p_thid, dbginv).i; } - - -/// Invalidate cached debugger information. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param dbginv \ref DBGINV_ -/// \return current debugger state (one of \ref DSTATE_) - -inline int idaapi invalidate_dbg_state(int dbginv) -{ - return set_process_state(DSTATE_NOTASK, NULL, dbginv); -} - - -/// Start a process in the debugger. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_process_start} -/// \note You can also use the run_to() function to easily start the execution -/// of a process until a given address is reached. -/// \note For all parameters, a NULL value indicates the debugger will take -/// the value from the defined Process Options. -/// \param path path to the executable to start -/// \param args arguments to pass to process -/// \param sdir starting directory for the process -/// \retval -1 impossible to create the process -/// \retval 0 the starting of the process was cancelled by the user -/// \retval 1 the process was properly started - -inline int idaapi start_process( - const char *path = NULL, - const char *args = NULL, - const char *sdir = NULL) -{ - return callui(ui_dbg_start_process, path, args, sdir).i; -} - - -/// Post a start_process() request - -inline int idaapi request_start_process( - const char *path = NULL, - const char *args = NULL, - const char *sdir = NULL) -{ - return callui(ui_dbg_request_start_process, path, args, sdir).i; -} - - -/// Suspend the process in the debugger. -/// \sq{ -/// Type, -/// - Synchronous function (if in a notification handler) -/// - Asynchronous function (everywhere else) -/// - available as Request, -/// Notification, -/// - none (if in a notification handler) -/// - ::dbg_suspend_process (everywhere else) -/// } -/// \note The suspend_process() function can be called from a notification -/// handler to force the stopping of the process. -/// In this case, no notification will be generated. -/// When you suspend a process, the running command is always aborted. - -inline bool idaapi suspend_process(void) { return callui(ui_dbg_suspend_process).cnd; } - -/// Post a suspend_process() request - -inline bool idaapi request_suspend_process(void) { return callui(ui_dbg_request_suspend_process).cnd; } - - -/// Continue the execution of the process in the debugger. -/// \sq{Type, Synchronous function - available as Request, -/// Notification, none (synchronous function)} -/// \note The continue_process() function can be called from a notification -/// handler to force the continuation of the process. In this case -/// the request queue will not be examined, IDA will simply resume -/// execution. Usually it makes sense to call request_continue_process() -/// followed by run_requests(), so that IDA will first start a queued -/// request (if any) and then resume the application. - -inline bool idaapi continue_process(void) { return callui(ui_dbg_continue_process).cnd; } - -/// Post a continue_process() request. -/// \note This requires an explicit call to run_requests() - -inline bool idaapi request_continue_process(void) { return callui(ui_dbg_request_continue_process).cnd; } - - -/// Terminate the debugging of the current process. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_process_exit} - -inline bool idaapi exit_process(void) { return callui(ui_dbg_exit_process).cnd; } - -/// Post an exit_process() request. - -inline bool idaapi request_exit_process(void) { return callui(ui_dbg_request_exit_process).cnd; } - - -/// Take a snapshot of running processes and return their description. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param[out] array with information about each running process -/// \return number of processes or -1 on error - -inline ssize_t idaapi get_processes(procinfo_vec_t *proclist) { return callui(ui_dbg_get_processes, proclist).ssize; } - - -/// Attach the debugger to a running process. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_process_attach} -/// \note This function shouldn't be called as a request if #NO_PROCESS is used. -/// \param pid PID of the process to attach to. If #NO_PROCESS, a dialog box -/// will interactively ask the user for the process to attach to. -/// \retval -4 debugger was not inited -/// \retval -3 the attaching is not supported -/// \retval -2 impossible to find a compatible process -/// \retval -1 impossible to attach to the given process (process died, privilege -/// needed, not supported by the debugger plugin, ...) -/// \retval 0 the user cancelled the attaching to the process -/// \retval 1 the debugger properly attached to the process - -inline int idaapi attach_process(pid_t pid=NO_PROCESS, int event_id=-1) { return callui(ui_dbg_attach_process, pid, event_id).i; } - -/// Post an attach_process() request - -inline int idaapi request_attach_process(pid_t pid, int event_id) { return callui(ui_dbg_request_attach_process, pid, event_id).i; } - - -/// Detach the debugger from the debugged process. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_process_detach} - -inline bool idaapi detach_process(void) { return callui(ui_dbg_detach_process).cnd; } - -/// Post a detach_process() request - -inline bool idaapi request_detach_process(void) { return callui(ui_dbg_request_detach_process).cnd; } - - -/// Is the debugger busy?. -/// Some debuggers do not accept any commands while the debugged application -/// is running. For such a debugger, it is unsafe to do anything with the -/// database (even simple queries like get_byte may lead to undesired consequences). -/// Returns: true if the debugged application is running under such a debugger - -inline bool idaapi is_debugger_busy(void) { return callui(ui_dbg_is_busy).cnd; } - -//@} dbg_funcs_cmds - - -//-------------------------------------------------------------------- -// T H R E A D S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_threads Threads -/// \ingroup dbg_funcs -/// -/// Inspect/Manipulate threads of debugged process. -//@{ - -/// Get number of threads. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline int idaapi get_thread_qty(void) { return callui(ui_dbg_get_thread_qty).i; } - - -/// Get the ID of a thread. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of thread, is in range 0..get_thread_qty()-1 -/// \return #NO_THREAD if the thread doesn't exist. - -inline thid_t idaapi getn_thread(int n) { return (thid_t)callui(ui_dbg_getn_thread, n).i; } - - -/// Get current thread ID. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline thid_t idaapi get_current_thread(void) { return callui(ui_dbg_get_current_thread).i; } - - -/// Get the NAME of a thread -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of thread, is in range 0..get_thread_qty()-1 -/// or -1 for the current thread -/// \return thread name or NULL if the thread doesn't exist. - -inline const char *idaapi getn_thread_name(int n) { return callui(ui_dbg_getn_thread_name, n).cptr; } - - -/// Select the given thread as the current debugged thread. -/// All thread related execution functions will work on this thread. -/// The process must be suspended to select a new thread. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param tid ID of the thread to select -/// \return false if the thread doesn't exist. - -inline bool idaapi select_thread(thid_t tid) { return callui(ui_dbg_select_thread, tid).cnd; } - -/// Post a select_thread() request - -inline bool idaapi request_select_thread(thid_t tid) { return callui(ui_dbg_request_select_thread, tid).cnd; } - - -/// Suspend thread. -/// Suspending a thread may deadlock the whole application if the suspended -/// was owning some synchronization objects. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param tid thread id -/// \retval -1 network error -/// \retval 0 failed -/// \retval 1 ok - -inline int idaapi suspend_thread(thid_t tid) { return callui(ui_dbg_suspend_thread, tid).i; } - -/// Post a suspend_thread() request - -inline int idaapi request_suspend_thread(thid_t tid) { return callui(ui_dbg_request_suspend_thread, tid).i; } - - -/// Resume thread. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param tid thread id -/// \retval -1 network error -/// \retval 0 failed -/// \retval 1 ok - -inline int idaapi resume_thread(thid_t tid) { return callui(ui_dbg_resume_thread, tid).i; } - -/// Post a resume_thread() request - -inline int idaapi request_resume_thread(thid_t tid) { return callui(ui_dbg_request_resume_thread, tid).i; } - -//@} dbg_funcs_threads - - -//-------------------------------------------------------------------- -// M O D U L E S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_modules Modules -/// \ingroup dbg_funcs -/// -/// Functions to enumerate modules loaded into the process. -/// -/// \param modinfo structure to receive the answer -/// \return false if there are no (more) modules -/// -/// Typical loop to enumerate modules would look like: -/// \code -/// modinfo_t minfo; -/// for ( bool ok=get_first_module(&minfo); ok; ok=get_next_module(&minfo) ) -/// ... -/// \endcode -//@{ -inline bool idaapi get_first_module(modinfo_t *modinfo) ///< See \ref dbg_funcs_modules -{ return callui(ui_dbg_get_first_module, modinfo).cnd; } - -inline bool idaapi get_next_module(modinfo_t *modinfo) ///< See \ref dbg_funcs_modules -{ return callui(ui_dbg_get_next_module, modinfo).cnd; } - -//@} - - -//-------------------------------------------------------------------- -// E X E C U T I O N F L O W C O N T R O L C O M M A N D S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_flow Execution flow control -/// \ingroup dbg_funcs -/// -/// Use these functions to run instructions in the debugged process. -//@{ - -/// Execute one instruction in the current thread. -/// Other threads are kept suspended. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_step_into} - -inline bool idaapi step_into(void) { return callui(ui_dbg_step_into).cnd; } - -/// Post a step_into() request - -inline bool idaapi request_step_into(void) { return callui(ui_dbg_request_step_into).cnd; } - - -/// Execute one instruction in the current thread, -/// but without entering into functions. -/// Others threads keep suspended. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_step_over} - -inline bool idaapi step_over(void) { return callui(ui_dbg_step_over).cnd; } - -/// Post a step_over() request - -inline bool idaapi request_step_over(void) { return callui(ui_dbg_request_step_over).cnd; } - - -/// Execute the process until the given address is reached. -/// If no process is active, a new process is started. -/// Technically, the debugger sets up a temporary breakpoint at -/// the given address, and continues (or starts) the execution of -/// the whole process. -/// So, all threads continue their execution! -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_run_to} -/// \param ea target address -/// \param pid not used yet. please do not specify this parameter. -/// \param tid not used yet. please do not specify this parameter. - -inline bool idaapi run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_run_to, ea, pid, tid).cnd; } - -/// Post a run_to() request - -inline bool idaapi request_run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_request_run_to, ea, pid, tid).cnd; } - -/// Execute instructions in the current thread until -/// a function return instruction is executed (aka "step out"). -/// Other threads are kept suspended. -/// \sq{Type, Asynchronous function - available as Request, -/// Notification, ::dbg_step_until_ret} - -inline bool idaapi step_until_ret(void) { return callui(ui_dbg_step_until_ret).cnd; } - -/// Post a step_until_ret() request - -inline bool idaapi request_step_until_ret(void) { return callui(ui_dbg_request_step_until_ret).cnd; } - - -/// How to resume the application. -/// Set resume mode but do not resume process. - -inline bool idaapi set_resume_mode(thid_t tid, resume_mode_t mode) { return callui(ui_dbg_set_resume_mode, tid, mode).cnd; } - -/// Post a set_resume_mode() request - -inline bool idaapi request_set_resume_mode(thid_t tid, resume_mode_t mode) { return callui(ui_dbg_request_set_resume_mode, tid, mode).cnd; } - -//@} dbg_funcs_flow - - -//-------------------------------------------------------------------- -// R E G I S T E R S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_regs Registers -/// \ingroup dbg_funcs -/// -/// Inspect/Manipulate registers for debugged process. -/// The debugger structure defines a set of hardware registers in \dbg{registers} -/// IDA also recognizes register names for each defined bit in bit registers. -/// You can use all these names to set or get a register value. -/// -/// For example, with the x86 Userland Win32 debugger you can use -/// register names like: -/// - "EAX", ... "EBP", "ESP", "EFL": for classical integer registers -/// - "CS", "DS", ... : for segment registers -/// - "ST0", "ST1", ... : for FPU registers -/// - "CF", "PF", "AF", "ZF", ... : for special bit values -//@{ - -/// Get register information -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi get_dbg_reg_info(const char *regname, register_info_t *ri) { return callui(ui_dbg_get_reg_info, regname, ri).cnd; } - -/// Read a register value from the current thread. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi get_reg_val(const char *regname, regval_t *regval) { return callui(ui_dbg_get_reg_val, regname, regval).cnd; } - -/// Get register value as an unsigned 64-bit int - -inline bool idaapi get_reg_val(const char *regname, uint64 *ival) { return callui(ui_dbg_get_reg_val_i, regname, ival).cnd; } - - -/// Get value of the SP register for the current thread. -/// Requires a suspended debugger. -inline bool idaapi get_sp_val(ea_t *out) { return callui(ui_dbg_get_sp_val, out).cnd; } - -/// Get value of the IP (program counter) register for the current thread. -/// Requires a suspended debugger. -inline bool idaapi get_ip_val(ea_t *out) { return callui(ui_dbg_get_ip_val, out).cnd; } - -/// Write a register value to the current thread. -/// \sq{Type, Synchronous function - available as Request, -/// Notification, none (synchronous function)} - -inline bool idaapi set_reg_val(const char *regname, const regval_t *regval) { return callui(ui_dbg_set_reg_val, regname, regval).cnd; } - -/// Write a register value to the current thread - -inline bool idaapi set_reg_val(const char *regname, uint64 ival) { return callui(ui_dbg_set_reg_val_i, regname, ival).cnd; } - -/// Post a set_reg_val() request - -inline bool idaapi request_set_reg_val(const char *regname, const regval_t *regval) { return callui(ui_dbg_request_set_reg_val, regname, regval).cnd; } - - -/// Does a register contain an integer value? -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi is_reg_integer(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i-2 == RVT_INT; } - - -/// Does a register contain a floating point value? -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi is_reg_float(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i-2 == RVT_FLOAT; } - - -/// Does a register contain a value of a custom data type? -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi is_reg_custom(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i >= 2; } - -//@} dbg_funcs_regs - -#endif // __UI__ - -//-------------------------------------------------------------------- -// B R E A K P O I N T S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_bpts Breakpoints -/// \ingroup dbg_funcs -/// -/// Work with debugger breakpoints. -//@{ - - - -/// Helper function for ::bpt_location_t -int idaapi set_bptloc_string(const char *s); -const char *idaapi get_bptloc_string(int i); ///< \copydoc set_bptloc_string() - - -/// Breakpoint location types -enum bpt_loctype_t -{ - BPLT_ABS, ///< absolute address: ea - BPLT_REL, ///< relative address: module_path, offset - BPLT_SYM, ///< symbolic: symbol_name, offset - BPLT_SRC, ///< source level: filename, lineno -}; - -/// Describes a breakpoint location -struct bpt_location_t -{ -//private: - ea_t info; - int index; - bpt_loctype_t loctype; -//public: - bpt_loctype_t type(void) const { return loctype; } ///< Get bpt type - bool is_empty_path(void) const { return index == 0; } ///< No path/filename specified? (::BPLT_REL, ::BPLT_SRC) - const char *path(void) const { return get_bptloc_string(index); } ///< Get path/filename (::BPLT_REL, ::BPLT_SRC) - const char *symbol(void) const { return get_bptloc_string(index); } ///< Get symbol name (::BPLT_SYM) - int lineno(void) const { return int(info); } ///< Get line number (::BPLT_SRC) - uval_t offset(void) const { return (uval_t)info; } ///< Get offset (::BPLT_REL, ::BPLT_SYM) - ea_t ea(void) const { return info; } ///< Get address (::BPLT_ABS) - - bpt_location_t(void) : info(BADADDR), index(0), loctype(BPLT_ABS) {} ///< Constructor (default type is ::BPLT_ABS) - - /// Specify an absolute address location - void set_abs_bpt(ea_t a) - { - info = a; - loctype = BPLT_ABS; - } - - /// Specify a source level location - void set_src_bpt(const char *fn, int _lineno) - { - index = set_bptloc_string(fn); - info = _lineno; - loctype = BPLT_SRC; - } - - /// Specify a symbolic location - void set_sym_bpt(const char *_symbol, uval_t _offset=0) - { - index = set_bptloc_string(_symbol); - info = _offset; - loctype = BPLT_SYM; - } - - /// Specify a relative address location - void set_rel_bpt(const char *mod, uval_t _offset) - { - index = set_bptloc_string(mod); - info = _offset; - loctype = BPLT_REL; - } - - /// Lexically compare two breakpoint locations. - /// Bpt locations are first compared based on type (i.e. ::BPLT_ABS < ::BPLT_REL). - /// ::BPLT_ABS locations are compared based on their ea values. - /// For all other location types, locations are first compared based on their - /// string (path/filename/symbol), then their offset/lineno. - int compare(const bpt_location_t &r) const { return callui(ui_dbg_compare_bpt_locs, this, &r).i; } - bool operator==(const bpt_location_t &r) const { return compare(r) == 0; } - bool operator!=(const bpt_location_t &r) const { return compare(r) != 0; } - bool operator< (const bpt_location_t &r) const { return compare(r) < 0; } - bool operator> (const bpt_location_t &r) const { return compare(r) > 0; } - bool operator<=(const bpt_location_t &r) const { return compare(r) <= 0; } - bool operator>=(const bpt_location_t &r) const { return compare(r) >= 0; } - - /// Internal function - size_t print(qstring *buf) const; -}; - -/// Characteristics of a breakpoint -struct bpt_t -{ - size_t cb; ///< size of this structure - qstring cndbody; ///< Condition as entered by the user - bpt_location_t loc; ///< Location - pid_t pid; ///< breakpoint process id - thid_t tid; ///< breakpoint thread id - ea_t ea; ///< Address, if known. For #BPLT_SRC, index into an internal data struct - bpttype_t type; ///< Breakpoint type - int pass_count; ///< Number of times the breakpoint is hit before stopping - ///< (default is 0: stop always) - uint32 flags; ///< \ref BPT_T -/// \defgroup BPT_T Breakpoint property bits -/// Used by bpt_t::flags -//@{ -#define BPT_BRK 0x001 ///< suspend execution upon hit -#define BPT_TRACE 0x002 ///< add trace information upon hit -#define BPT_UPDMEM 0x004 ///< refresh the memory layout and contents before evaluating bpt condition -#define BPT_ENABLED 0x008 ///< enabled? -#define BPT_LOWCND 0x010 ///< condition is calculated at low level (on the server side) -#define BPT_TRACEON 0x020 ///< enable tracing when the breakpoint is reached -#define BPT_TRACE_INSN 0x040 ///< instruction tracing -#define BPT_TRACE_FUNC 0x080 ///< function tracing -#define BPT_TRACE_BBLK 0x100 ///< basic block tracing -#define BPT_TRACE_TYPES (BPT_TRACE_INSN|BPT_TRACE_FUNC|BPT_TRACE_BBLK) - ///< trace insns, functions, and basic blocks. - ///< if any of #BPT_TRACE_TYPES bits are set but #BPT_TRACEON is clear, - ///< then turn off tracing for the specified trace types -#define BPT_ELANG_MASK 0xF0000000u -#define BPT_ELANG_SHIFT 28 ///< index of the extlang (scripting language) of the condition -//@} - - uint32 props; ///< \ref BKPT_ -/// \defgroup BKPT_ Internal breakpoint properties -/// Used by bpt_t::props -//@{ -#define BKPT_BADBPT 0x01 ///< failed to write the bpt to the process memory (at least one location) -#define BKPT_LISTBPT 0x02 ///< include in bpt list (user-defined bpt) -#define BKPT_TRACE 0x04 ///< trace bpt; should not be deleted when the process gets suspended -#define BKPT_ACTIVE 0x08 ///< active? -#define BKPT_PARTIAL 0x10 ///< partially active? (some locations were not written yet) -#define BKPT_CNDREADY 0x20 ///< condition has been compiled -#define BKPT_FAKEPEND 0x40 ///< fake pending bpt: it is inactive but another - ///< bpt of the same type is active at the same address(es) -#define BKPT_PAGE 0x80 ///< written to the process as a page bpt. is available - ///< only after writing the bpt to the process. -//@} - - int size; ///< Size of the breakpoint (0 for software breakpoints) - int cndidx; ///< Internal number of the condition (<0-none) - - bpt_t(void) : cb(sizeof(*this)), pid(NO_PROCESS), tid(NO_THREAD), ea(BADADDR), - type(BPT_SOFT), pass_count(0), flags(BPT_BRK|BPT_ENABLED), - props(0), size(0), cndidx(-1) {} - - bool is_hwbpt(void) const { return type != BPT_SOFT; } ///< Is hardware breakpoint? - bool enabled(void) const { return (flags & BPT_ENABLED) != 0; } ///< Is breakpoint enabled? - bool is_low_level(void) const { return (flags & BPT_LOWCND) != 0; } ///< Is bpt condition calculated at low level? - bool badbpt(void) const { return (props & BKPT_BADBPT) != 0; } ///< Failed to write bpt to process memory? - bool listbpt(void) const { return (props & BKPT_LISTBPT) != 0; } ///< Include in the bpt list? - bool is_compiled(void) const { return (props & BKPT_CNDREADY) != 0; } ///< Condition has been compiled? - /// Written completely to process? - bool is_active(void) const { return (props & (BKPT_PARTIAL|BKPT_ACTIVE)) == BKPT_ACTIVE; } - /// Written partially to process? - bool is_partially_active(void) const { return (props & BKPT_PARTIAL) != 0; } - /// Not written to process at all? - bool is_inactive(void) const { return (props & (BKPT_PARTIAL|BKPT_ACTIVE)) == 0; } - /// Page breakpoint? - bool is_page_bpt(void) const { return (props & BKPT_PAGE) != 0; } - - /// Get bpt size - int get_size(void) const { return is_hwbpt() ? size : 1; } - /// Set bpt location to an absolute address - void set_abs_bpt(ea_t a) { loc.set_abs_bpt(a); ea = a; } - /// Set bpt location to a source line - void set_src_bpt(const char *fn, int lineno) { loc.set_src_bpt(fn, lineno); ea = BADADDR; } - /// Set bpt location to a symbol - void set_sym_bpt(const char *sym, uval_t o) { loc.set_sym_bpt(sym, o); ea = BADADDR; } - /// Set bpt location to a relative address - void set_rel_bpt(const char *mod, uval_t o) { loc.set_rel_bpt(mod, o); ea = BADADDR; } - - bool is_absbpt(void) const { return loc.type() == BPLT_ABS; } ///< Is absolute address breakpoint? - bool is_relbpt(void) const { return loc.type() == BPLT_REL; } ///< Is relative address breakpoint? - bool is_symbpt(void) const { return loc.type() == BPLT_SYM; } ///< Is symbolic breakpoint? - bool is_srcbpt(void) const { return loc.type() == BPLT_SRC; } ///< Is source level breakpoint? - - /// Does breakpoint trace anything? - bool is_tracemodebpt(void) const { return (flags & BPT_TRACE_TYPES) != 0; } - /// Is this a tracing breakpoint, and is tracing enabled? - bool is_traceonbpt(void) const { return is_tracemodebpt() && (flags & BPT_TRACEON) != 0; } - /// Is this a tracing breakpoint, and is tracing disabled? - bool is_traceoffbpt(void) const { return is_tracemodebpt() && (flags & BPT_TRACEON) == 0; } - /// Configure tracing options - bool set_trace_action(bool enable, int trace_types) - { - trace_types &= BPT_TRACE_TYPES; - if ( trace_types == 0 ) - return false; - flags |= trace_types; - setflag(flags, BPT_TRACEON, enable); - return true; - } - - /// Get the scripting language name for the condition string - const char *get_cnd_elang() const; - - /// Set the scripting language name for the condition string - /// \return false if too many languages were used - bool set_cnd_elang(const char *name); - - size_t get_cnd_elang_idx() const { return flags >> BPT_ELANG_SHIFT; } - - void set_cond(const char *cnd); ///< Internal function - bool eval_cond(ea_t ea, bool *fire, const char *bpt_type); ///< Internal function -}; -typedef qvector bpt_vec_t; ///< vector of breakpoints - - -enum movbpt_code_t -{ - MOVBPT_OK, // moved ok - MOVBPT_NOT_FOUND, // source bpt not found - MOVBPT_DEST_BUSY, // destination location is busy (we already have such a bpt) - MOVBPT_BAD_TYPE, // BPLT_ABS is not supported -}; -typedef qvector movbpt_codes_t; - -struct movbpt_info_t -{ - bpt_location_t from; - bpt_location_t to; -}; -DECLARE_TYPE_AS_MOVABLE(movbpt_info_t); -typedef qvector movbpt_infos_t; - -#ifndef __UI__ - - -/// Get number of breakpoints. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline int idaapi get_bpt_qty(void) { return callui(ui_dbg_get_bpt_qty).i; } - - -/// Get the characteristics of a breakpoint. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of breakpoint, is in range 0..get_bpt_qty()-1 -/// \param[out] bpt filled with the characteristics. -/// \return false if no breakpoint exists - -inline bool idaapi getn_bpt(int n, bpt_t *bpt) { return callui(ui_dbg_getn_bpt, n, bpt).cnd; } - - -/// Get the characteristics of a breakpoint. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param ea any address in the breakpoint range -/// \param[out] bpt if not NULL, is filled with the characteristics. -/// \return false if no breakpoint exists - -inline bool idaapi get_bpt(ea_t ea, bpt_t *bpt) { return callui(ui_dbg_get_bpt, ea, bpt).cnd; } - - -/// Does a breakpoint exist at the given location? - -inline bool exist_bpt(ea_t ea) { return get_bpt(ea, NULL); } - - -/// Add a new breakpoint in the debugged process. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \note Only one breakpoint can exist at a given address. -/// \param ea any address in the process memory space. -/// Depending on the architecture, hardware breakpoints -/// always be setup at random address. For example, on x86, -/// hardware breakpoints should be aligned depending on their size. -/// Moreover, on the x86 architecture, it is impossible to setup -/// more than 4 hardware breakpoints. -/// \param size size of the breakpoint (irrelevant for software breakpoints): -/// As for the address, hardware breakpoints can't always be setup -/// with random size. -/// \param type type of the breakpoint (#BPT_SOFT for software breakpoint) -/// special case #BPT_DEFAULT (#BPT_SOFT|#BPT_EXEC): -/// try to add instruction breakpoint of the appropriate type -/// as follows: software bpt if supported, hwbpt otherwise - -inline bool idaapi add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_DEFAULT) { return callui(ui_dbg_add_oldbpt, ea, size, type).cnd; } - -/// Post an add_bpt(ea_t, asize_t, bpttype_t) request - -inline bool idaapi request_add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_DEFAULT) { return callui(ui_dbg_request_add_oldbpt, ea, size, type).cnd; } - - -/// Add a new breakpoint in the debugged process. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param bpt Breakpoint to add. It describes the break condition, -/// type, flags, location (module relative, source breakpoint -/// or absolute) and other attributes. - -inline bool idaapi add_bpt(const bpt_t &bpt) { return callui(ui_dbg_add_bpt, &bpt).cnd; } - -/// Post an add_bpt(const bpt_t &) request - -inline bool idaapi request_add_bpt(const bpt_t &bpt) { return callui(ui_dbg_request_add_bpt, &bpt).cnd; } - - -/// Delete an existing breakpoint in the debugged process. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param ea any address in the breakpoint range - -inline bool idaapi del_bpt(ea_t ea) { return callui(ui_dbg_del_oldbpt, ea).cnd; } - -/// Post a del_bpt(ea_t) request - -inline bool idaapi request_del_bpt(ea_t ea) { return callui(ui_dbg_request_del_oldbpt, ea).cnd; } - - -/// Delete an existing breakpoint in the debugged process. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param bptloc Breakpoint location - -inline bool idaapi del_bpt(const bpt_location_t &bptloc) { return callui(ui_dbg_del_bpt, &bptloc).cnd; } - -/// Post a del_bpt(const bpt_location_t &) request - -inline bool idaapi request_del_bpt(const bpt_location_t &bptloc) { return callui(ui_dbg_request_del_bpt, &bptloc).cnd; } - - -/// Update modifiable characteristics of an existing breakpoint. -/// To update the breakpoint location, use change_bptlocs() -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \note Only the following fields can be modified: -/// - bpt_t::cndbody -/// - bpt_t::pass_count -/// - bpt_t::flags -/// - bpt_t::size -/// - bpt_t::type -/// \note Changing some properties will require removing and then re-adding -/// the breakpoint to the process memory (or the debugger backend), which -/// can lead to race conditions (i.e., breakpoint(s) can be missed) in -/// case the process is not suspended. -/// Here are a list of scenarios that will require the breakpoint -/// to be removed & then re-added: -/// - bpt_t::size is modified -/// - bpt_t::type is modified -/// - bpt_t::flags's BPT_ENABLED is modified -/// - bpt_t::flags's BPT_LOWCND is changed -/// - bpt_t::flags's BPT_LOWCND remains set, but cndbody changed - -inline bool idaapi update_bpt(const bpt_t *bpt) { return callui(ui_dbg_update_bpt, bpt).cnd; } - - -/// Find a breakpoint by location. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param bptloc Breakpoint location -/// \param bpt bpt is filled if the breakpoint was found - -inline bool idaapi find_bpt(const bpt_location_t &bptloc, bpt_t *bpt) { return callui(ui_dbg_find_bpt, &bptloc, bpt).cnd; } - - -/// Move breakpoint(s) from one location to another -/// \param movinfo what bpts to move and where to -/// \param codes vector of return codes, if detailed error info is required -/// \param del_hindering_bpts should delete hindering breakpoints? -/// \return number of moved bpts - -inline int idaapi change_bptlocs( - const movbpt_infos_t &movinfo, - movbpt_codes_t *codes = NULL, - bool del_hindering_bpts = true) -{ - return callui(ui_dbg_change_bptlocs, &movinfo, codes, del_hindering_bpts).i; -} - - - -/// \name enable/disable breakpoints -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// Enable or disable an existing breakpoint. -/// A disabled breakpoint isn't available anymore in the process. -//@{ -inline bool idaapi enable_bpt(ea_t ea, bool enable = true) { return callui(ui_dbg_enable_oldbpt, ea, enable).cnd; } -inline bool idaapi enable_bpt(const bpt_location_t &bptloc, bool enable = true) { return callui(ui_dbg_enable_bpt, &bptloc, enable).cnd; } -inline bool disable_bpt(ea_t ea) { return enable_bpt(ea, false); } -inline bool disable_bpt(const bpt_location_t &bptloc) { return enable_bpt(bptloc, false); } -inline bool idaapi request_enable_bpt(ea_t ea, bool enable = true) { return callui(ui_dbg_request_enable_oldbpt, ea, enable).cnd; } -inline bool idaapi request_enable_bpt(const bpt_location_t &bptloc, bool enable = true) { return callui(ui_dbg_request_enable_bpt, &bptloc, enable).cnd; } -inline bool request_disable_bpt(ea_t ea) { return request_enable_bpt(ea, false); } -inline bool request_disable_bpt(const bpt_location_t &bptloc) { return request_enable_bpt(bptloc, false); } -//@} - - -/// Check the breakpoint at the specified address. -/// \return one of \ref BPTCK_ - -inline int idaapi check_bpt(ea_t ea) { return callui(ui_dbg_check_bpt, ea).i; } - -#endif // __UI__ - -/// \defgroup BPTCK_ Breakpoint status codes -/// Return values for check_bpt() -//@{ -#define BPTCK_NONE -1 ///< breakpoint does not exist -#define BPTCK_NO 0 ///< breakpoint is disabled -#define BPTCK_YES 1 ///< breakpoint is enabled -#define BPTCK_ACT 2 ///< breakpoint is active (written to the process) -//@} - -#ifndef SWIG -/// Visit all breakpoints. -/// To use this class, derive your own class from it and call for_all_bpts(). -/// It is forbidden to add/del bpts from the visit_bpt() function. -/// If bpts are nevertheless modified, the enumeration should be stopped -struct bpt_visitor_t -{ - int _for_all_bpts(int bvflags); ///< do not use this function. - range_t range; ///< if specified, restricts the address range - const char *name; ///< if specified, restricts bpts to the ones that match the given name - bpt_visitor_t(void) : range(0, BADADDR), name(NULL) {} - /// Defines action taken when breakpoint is visited - virtual int idaapi visit_bpt(const bpt_t *bpt) = 0; - int idaapi for_all_bpts(int bvflags) - { - return callui(ui_dbg_for_all_bpts, this, bvflags).i; - } -}; - -/// \defgroup BVF_ Breakpoint visitor flags -/// Passed as 'bvflags' parameter to bpt_visitor_t::_for_all_bpts() -/// \note it is forbidden to modify bpt states from the bpt_visitor_t::visit_bpt() -/// function if #BVF_STATE is not #BVFS_ANY -//@{ -#define BVF_ABS 0x0001 ///< include absolute bpts -#define BVF_REL 0x0002 ///< include relative bpts -#define BVF_SYM 0x0004 ///< include symbolic bpts -#define BVF_SRC 0x0008 ///< include source bpts -#define BVF_ALL 0x000F ///< include all bpt location types -#define BVF_STATE 0x0030 ///< bpt state mask -#define BVFS_ANY 0x0000 ///< any state -#define BVFS_INPROC 0x0010 ///< written to process memory -#define BVFS_PENDING 0x0020 ///< pending -#define BVFS_DISABLED 0x0030 ///< disabled. -//@} -#endif // SWIG - - -//@} dbg_funcs_bpts - - -#ifndef __UI__ - -/// \defgroup dbg_funcs_tracing Tracing -/// \ingroup dbg_funcs -/// -/// Trace instructions/functions/basic blocks - -//-------------------------------------------------------------------- -// T R A C I N G B U F F E R -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_trcbuf Tracing buffer -/// \ingroup dbg_funcs_tracing -/// -/// Work with debugger trace buffer. -/// IDA memorizes various types of trace events in a circular buffer: -/// instruction tracing, function call and return, breakpoint access ... -//@{ - - -/// Specify the new size of the circular buffer. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param size if 0, buffer isn't circular and events are never removed. -/// If the new size is smaller than the existing number of trace events, -/// a corresponding number of trace events are removed. -/// \note If you specify 0, all available memory can be quickly used !!! - -inline bool idaapi set_trace_size(int size) { return callui(ui_dbg_set_trace_size, size).cnd; } - - -/// Clear all events in the trace buffer. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} - -inline void idaapi clear_trace(void) { callui(ui_dbg_clear_trace); } - -/// Post a clear_trace() request - -inline void idaapi request_clear_trace(void) { callui(ui_dbg_request_clear_trace); } - -//@} dbg_funcs_trcbuf - - -//-------------------------------------------------------------------- -// S T E P T R A C I N G -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_strace Step tracing -/// \ingroup dbg_funcs_tracing -/// -/// Plugins can use these functions to implement a custom tracing engine. -/// When enabled, IDA uses single-stepping feature of the debugger -/// and generates a dbg_trace notification after each step in the current thread. -/// Tracing buffer is not maintained in this mode (you need to use one of the -/// higher level tracing types for it) -//@{ - -/// Get current state of step tracing. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi is_step_trace_enabled(void) { return callui(ui_dbg_is_step_trace_enabled).cnd; } - - -/// \name Enable/Disable step tracing -/// Enable or disable the step tracing -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -/// \param enable -/// - 1 : enable step tracing -/// - 0 : disable step tracing -/// - -1 : temporarily disable step tracing -/// (trace-over breakpoints are conserved: -/// these could re-enable step tracing later) -//@{ - -inline bool idaapi enable_step_trace(int enable = 1) { return callui(ui_dbg_enable_step_trace, enable).cnd; } -inline bool disable_step_trace(void) { return enable_step_trace(0); } -inline bool idaapi request_enable_step_trace(int enable = 1) { return callui(ui_dbg_request_enable_step_trace, enable).cnd; } -inline bool request_disable_step_trace(void) { return request_enable_step_trace(false); } -//@} - -#endif // __UI__ - - -/// \defgroup ST_ Step trace options -/// Flags returned by get_step_trace_options() -//@{ -#define ST_OVER_DEBUG_SEG 0x01 ///< step tracing will be disabled when IP is in a debugger segment -#define ST_OVER_LIB_FUNC 0x02 ///< step tracing will be disabled when IP is in a library function -#define ST_ALREADY_LOGGED 0x04 ///< step tracing will be disabled when IP is already logged -#define ST_SKIP_LOOPS 0x08 ///< step tracing will try to skip loops already recorded -#define ST_DIFFERENTIAL 0x10 ///< tracing: log only new instructions (not previously logged) -/// mask of available options, to ensure compatibility with newer IDA versions -#define ST_OPTIONS_MASK (ST_OVER_DEBUG_SEG|ST_OVER_LIB_FUNC|ST_ALREADY_LOGGED|ST_SKIP_LOOPS|ST_DIFFERENTIAL) -#define ST_OPTIONS_DEFAULT (ST_OVER_DEBUG_SEG|ST_OVER_LIB_FUNC) -//@} - -/// specific options for instruction tracing (see set_insn_trace_options()) -#define IT_LOG_SAME_IP 0x01 ///< instruction tracing will log new instructions even when IP doesn't change -/// specific options for function tracing (see set_func_trace_options()) -#define FT_LOG_RET 0x01 ///< function tracing will log returning instructions -/// specific options for basic block tracing (see set_bblk_trace_options()) -#define BT_LOG_INSTS 0x01 ///< log all instructions in the current basic block - -#ifndef __UI__ - -/// Get current step tracing options. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return \ref ST_ - -inline int idaapi get_step_trace_options(void) { return callui(ui_dbg_get_step_trace_options).i; } - -/// Modify step tracing options. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} - -inline void idaapi set_step_trace_options(int options) { callui(ui_dbg_set_step_trace_options, options); } - -/// Post a set_step_trace_options() request - -inline void idaapi request_set_step_trace_options(int options) { callui(ui_dbg_request_set_step_trace_options, options); } - -//@} dbg_funcs_strace - - -//-------------------------------------------------------------------- -// I N S T R U C T I O N S T R A C I N G -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_trcins Instruction tracing -/// \ingroup dbg_funcs_tracing -/// -/// When instruction tracing is active, each executed instruction is stored -/// in the tracing buffer. -/// Internally, IDA uses step tracing to record register values after the -/// execution of the instruction. -//@{ - -/// Get current state of instruction tracing. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi is_insn_trace_enabled(void) { return callui(ui_dbg_is_insn_trace_enabled).cnd; } - -/// \name Enable/Disable instruction tracing -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -//@{ -inline bool idaapi enable_insn_trace(bool enable = true) { return callui(ui_dbg_enable_insn_trace, enable).cnd; } -inline bool disable_insn_trace(void) { return enable_insn_trace(false); } -inline bool idaapi request_enable_insn_trace(bool enable = true) { return callui(ui_dbg_request_enable_insn_trace, enable).cnd; } -inline bool request_disable_insn_trace(void) { return request_enable_insn_trace(false); } -//@} - - -/// Get current instruction tracing options. -/// Also see #IT_LOG_SAME_IP -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline int idaapi get_insn_trace_options(void) { return callui(ui_dbg_get_insn_trace_options).i; } - - -/// Modify instruction tracing options. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} - -inline void idaapi set_insn_trace_options(int options) { callui(ui_dbg_set_insn_trace_options, options); } - -/// Post a set_insn_trace_options() request - -inline void idaapi request_set_insn_trace_options(int options) { callui(ui_dbg_request_set_insn_trace_options, options); } - -//@} dbg_funcs_trcins - - -//-------------------------------------------------------------------- -// F U N C T I O N S T R A C I N G -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_trcfunc Functions tracing -/// \ingroup dbg_funcs_tracing -/// -/// Each call to a function or return from a function is stored -/// in the tracing buffer. -//@{ - -/// Get current state of functions tracing. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline bool idaapi is_func_trace_enabled(void) { return callui(ui_dbg_is_func_trace_enabled).cnd; } - - -/// \name Enable/Disable functions tracing -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -//@{ -inline bool idaapi enable_func_trace(bool enable = true) { return callui(ui_dbg_enable_func_trace, enable).cnd; } -inline bool disable_func_trace(void) { return enable_func_trace(false); } -inline bool idaapi request_enable_func_trace(bool enable = true) { return callui(ui_dbg_request_enable_func_trace, enable).cnd; } -inline bool request_disable_func_trace(void) { return request_enable_func_trace(false); } -//@} - - -/// Get current function tracing options. -/// Also see #FT_LOG_RET -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline int idaapi get_func_trace_options(void) { return callui(ui_dbg_get_func_trace_options).i; } - - -/// Modify function tracing options. -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} - -inline void idaapi set_func_trace_options(int options) { callui(ui_dbg_set_func_trace_options, options); } - -/// Post a set_func_trace_options() request - -inline void idaapi request_set_func_trace_options(int options) { callui(ui_dbg_request_set_func_trace_options, options); } - -//@} dbg_funcs_trcfunc - - -//-------------------------------------------------------------------- -// B A S I C B L O C K T R A C I N G -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_trcbb Basic block tracing -/// \ingroup dbg_funcs_tracing -//@{ - -// Modify basic block tracing options. -// Type: Synchronous function - available as Request -// Notification: none (synchronous function) - - -/// \name Enable/Disable basic blocks tracing -/// \sq{Type, Synchronous function - available as request, -/// Notification, none (synchronous function)} -//@{ -inline bool idaapi enable_bblk_trace(bool enable = true) { return callui(ui_dbg_enable_bblk_trace, enable).cnd; } -inline bool disable_bblk_trace(void) { return enable_bblk_trace(false); } -inline bool idaapi request_enable_bblk_trace(bool enable = true) { return callui(ui_dbg_request_enable_bblk_trace, enable).cnd; } -inline bool request_disable_bblk_trace(void) { return request_enable_bblk_trace(false); } -inline bool idaapi is_bblk_trace_enabled(void) { return callui(ui_dbg_is_bblk_trace_enabled).cnd; } -//@} - -/// Get current basic block tracing options. -/// Also see #BT_LOG_INSTS -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline int idaapi get_bblk_trace_options(void) { return callui(ui_dbg_get_bblk_trace_options).i; } - - -/// Modify basic block tracing options (see #BT_LOG_INSTS) - -inline void idaapi set_bblk_trace_options(int options) { callui(ui_dbg_set_bblk_trace_options, options); } - -/// Post a set_bblk_trace_options() request - -inline void idaapi request_set_bblk_trace_options(int options) { callui(ui_dbg_request_set_bblk_trace_options, options); } - -//@} dbg_funcs_trcbb - -#endif // __UI__ - -//-------------------------------------------------------------------- -// T R A C I N G E V E N T S -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_trcev Tracing events -/// \ingroup dbg_funcs_tracing -//@{ - -/// Trace event types -enum tev_type_t -{ - tev_none = 0, ///< no event - tev_insn, ///< an instruction trace - tev_call, ///< a function call trace - tev_ret, ///< a function return trace - tev_bpt, ///< write, read/write, execution trace - tev_mem, ///< memory layout changed - tev_event, ///< debug event occurred - tev_max, ///< first unused event type -}; - -typedef qvector dbgevt_vec_t; ///< vector of debug events - -/// Common information for all trace events -struct tev_info_t -{ - tev_type_t type; ///< trace event type - thid_t tid; ///< thread where the event was recorded - ea_t ea; ///< address where the event occurred -}; -typedef qvector tevinfo_vec_t; ///< vector of trace event info objects - - -/// Required typedef for get_insn_tev_reg_mem() -struct memreg_info_t -{ - ea_t ea; - bytevec_t bytes; -}; -DECLARE_TYPE_AS_MOVABLE(memreg_info_t); -typedef qvector memreg_infos_t; - - -#ifndef __UI__ - -/// Get number of trace events available in trace buffer. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline int idaapi get_tev_qty(void) { return callui(ui_dbg_get_tev_qty).i; } - - -/// Get main information about a trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \param[out] tev_info result -/// \return success - -inline bool idaapi get_tev_info(int n, tev_info_t *tev_info) { return callui(ui_dbg_get_tev_info, n, tev_info).cnd; } - - -/// Read a register value from an instruction trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \param regname name of desired register -/// \param[out] regval result -/// \return false if not an instruction event. -/// \note This is the value of the register before the execution of -/// the instruction. - -inline bool idaapi get_insn_tev_reg_val(int n, const char *regname, regval_t *regval) { return callui(ui_dbg_get_insn_tev_reg_val, n, regname, regval).cnd; } - -inline bool idaapi get_insn_tev_reg_val(int n, const char *regname, uint64 *ival) { return callui(ui_dbg_get_insn_tev_reg_val_i, n, regname, ival).cnd; } - - -/// Read the memory pointed by register values from an instruction trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \param[out] memmap result -/// \return false if not an instruction event or no memory is available - -inline bool idaapi get_insn_tev_reg_mem(int n, memreg_infos_t *memmap) { return callui(ui_dbg_get_insn_tev_reg_mem, n, memmap).cnd; } - - -/// Read the resulting register value from an instruction trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \param regname name of desired register -/// \param[out] regval result -/// \return false if not an instruction trace event or register wasn't modified. - -inline bool idaapi get_insn_tev_reg_result(int n, const char *regname, regval_t *regval) { return callui(ui_dbg_get_insn_tev_reg_result, n, regname, regval).cnd; } - -inline bool idaapi get_insn_tev_reg_result(int n, const char *regname, uint64 *ival) { return callui(ui_dbg_get_insn_tev_reg_result_i, n, regname, ival).cnd; } - - -/// Get the called function from a function call trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \return #BADADDR if not a function call event. - -inline ea_t idaapi get_call_tev_callee(int n) { ea_t ea; callui(ui_dbg_get_call_tev_callee, n, &ea); return ea; } - - -/// Get the return address from a function return trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \return #BADADDR if not a function return event. - -inline ea_t idaapi get_ret_tev_return(int n) { ea_t ea; callui(ui_dbg_get_ret_tev_return, n, &ea); return ea; } - - -/// Get the address associated to a read, read/write or execution trace event. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \return #BADADDR if not a read, read/write or execution trace event. -/// \note Usually, a breakpoint is associated with a read, read/write or execution -/// trace event. However, the returned address could be any address in the -/// range of this breakpoint. -/// If the breakpoint was deleted after the trace event, the address no longer -/// corresponds to a valid breakpoint. - -inline ea_t idaapi get_bpt_tev_ea(int n) { ea_t ea; callui(ui_dbg_get_bpt_tev_ea, n, &ea); return ea; } - - -/// Get the memory layout, if any, for the specified tev object. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \param[out] mi result -/// \return false if the tev_t object is not of type ::tev_mem, true otherwise, -/// with the new memory layout in "mi". - -inline bool idaapi get_tev_memory_info(int n, meminfo_vec_t *mi) { return callui(ui_dbg_get_tev_memory_info, n, mi).cnd; } - - -/// Get the corresponding debug event, if any, for the specified tev object. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \param n number of trace event, is in range 0..get_tev_qty()-1. -/// 0 represents the latest added trace event. -/// \param[out] d result -/// \return false if the tev_t object doesn't have any associated debug -/// event, true otherwise, with the debug event in "d". - -inline bool idaapi get_tev_event(int n, debug_event_t *d) { return callui(ui_dbg_get_tev_event, n, d).cnd; } - - -/// Get the base address of the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return the base address of the currently loaded trace - -inline ea_t idaapi get_trace_base_address(void) { ea_t ea; callui(ui_dbg_get_trace_base_address, &ea); return ea; } - - -/// Set the base address of the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi set_trace_base_address(ea_t ea) { callui(ui_dbg_set_trace_base_address, ea); } - - -/// Add a thread to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi dbg_add_thread(thid_t tid) { callui(ui_dbg_add_thread, tid); } - - -/// Delete a thread from the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi dbg_del_thread(thid_t tid) { callui(ui_dbg_del_thread, tid); } - - -/// Add a new trace element to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi dbg_add_tev(tev_type_t type, thid_t tid, ea_t address) { callui(ui_dbg_add_tev, type, tid, address); } - -#endif // __UI__ - -/// Structure used for dbg_add_many_tevs() -struct tev_reg_value_t -{ - regval_t value; - int reg_idx; - - tev_reg_value_t(int _reg_idx = -1, uint64 _value = uint64(-1)) : reg_idx(_reg_idx) - { - value._set_int(_value); - } -}; -DECLARE_TYPE_AS_MOVABLE(tev_reg_value_t); -typedef qvector tev_reg_values_t; ///< vector of trace event reg values - -/// Structure used for dbg_add_many_tevs() -struct tev_info_reg_t -{ - tev_info_t info; - tev_reg_values_t registers; -}; -DECLARE_TYPE_AS_MOVABLE(tev_info_reg_t); -typedef qvector tevinforeg_vec_t; ///< vector of trace elements - - -/// Se dbg_add_insn_tev() -enum save_reg_values_t -{ - SAVE_ALL_VALUES = 0, - SAVE_DIFF, - SAVE_NONE -}; - -#ifndef __UI__ - -/// Add many new trace elements to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return false if the operation failed for any ::tev_info_t object - -inline bool idaapi dbg_add_many_tevs(tevinforeg_vec_t *new_tevs) { return callui(ui_dbg_add_many_tevs, new_tevs).cnd; } - - -/// Add a new instruction trace element to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return false if the operation failed, true otherwise - -inline bool idaapi dbg_add_insn_tev(thid_t tid, ea_t ea, save_reg_values_t save = SAVE_DIFF) { return callui(ui_dbg_add_insn_tev, tid, ea, save).cnd; } - - -/// Add a new breakpoint trace element to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} -/// \return false if the operation failed, true otherwise - -inline bool idaapi dbg_add_bpt_tev(thid_t tid, ea_t ea, ea_t bp) { return callui(ui_dbg_add_bpt_tev, tid, ea, bp).cnd; } - - -/// Add a new call trace element to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi dbg_add_call_tev(thid_t tid, ea_t caller, ea_t callee) { callui(ui_dbg_add_call_tev, tid, caller, callee); } - - -/// Add a new return trace element to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi dbg_add_ret_tev(thid_t tid, ea_t ret_insn, ea_t return_to) { callui(ui_dbg_add_ret_tev, tid, ret_insn, return_to); } - - -/// Add a new debug event to the current trace. -/// \sq{Type, Synchronous function, -/// Notification, none (synchronous function)} - -inline void idaapi dbg_add_debug_event(debug_event_t *event) { callui(ui_dbg_add_debug_event, event); } - -//@} dbg_funcs_trcev - - -//--------------------------------------------------------------------------- -// Trace management functions -//--------------------------------------------------------------------------- -/// \defgroup dbg_funcs_trcm Trace management functions -/// \ingroup dbg_funcs_tracing -//@{ - -/// Load a recorded trace file in the trace window. -/// If the call succeeds and 'buf' is not null, the description of the -/// trace stored in the binary trace file will be returned in 'buf' - -inline bool idaapi load_trace_file(qstring *buf, const char *filename) { return callui(ui_dbg_load_trace_file, buf, filename).cnd; } - - -/// Save the current trace in the specified file - -inline bool idaapi save_trace_file(const char *filename, const char *description) { return callui(ui_dbg_save_trace_file, filename, description).cnd; } - - -/// Is the specified file a valid trace file for the current database? - -inline bool idaapi is_valid_trace_file(const char *filename) { return callui(ui_dbg_is_valid_trace_file, filename).cnd; } - - -/// Change the description of the specified trace file - -inline bool idaapi set_trace_file_desc(const char *filename, const char *description) { return callui(ui_dbg_set_trace_file_desc, filename, description).cnd; } - - -/// Get the file header of the specified trace file - -inline bool idaapi get_trace_file_desc(qstring *buf, const char *filename) { return callui(ui_dbg_get_trace_file_desc, buf, filename).cnd; } - - -/// Show the choose trace dialog - -inline bool idaapi choose_trace_file(qstring *buf) { return callui(ui_dbg_choose_trace_file, buf).cnd; } - - -/// Show difference between the current trace and the one from 'filename' - -inline bool idaapi diff_trace_file(const char *NONNULL filename) { return callui(ui_dbg_diff_trace_file, filename).cnd; } - - -/// Show the trace callgraph - -inline bool idaapi graph_trace(void) { return callui(ui_dbg_graph_trace).cnd; } - - -/// Set highlight trace parameters. - -inline void idaapi set_highlight_trace_options( - bool hilight, - bgcolor_t color, - bgcolor_t diff) -{ - callui(ui_dbg_set_highlight_trace_options, hilight, color, diff); -} - - -/// Set platform name of current trace - -inline void idaapi set_trace_platform(const char *platform) { callui(ui_dbg_set_trace_platform, platform); } - - -/// Get platform name of current trace - -inline const char *idaapi get_trace_platform() { return callui(ui_dbg_get_trace_platform).cptr; } - - -/// Set dynamic register set of current trace - -inline void idaapi set_trace_dynamic_register_set(dynamic_register_set_t &idaregs) { callui(ui_dbg_set_trace_dynamic_register_set, &idaregs); } - - -/// Get dynamic register set of current trace - -inline void idaapi get_trace_dynamic_register_set(dynamic_register_set_t *idaregs) { callui(ui_dbg_get_trace_dynamic_register_set, idaregs); } - -//@} dbg_funcs_trcm - -#endif // __UI__ - -//--------------------------------------------------------------------------- -// High level functions (usable from scripts) -//-------------------------------------------------------------------- -/// \defgroup dbg_funcs_high High level functions -/// \ingroup dbg_funcs -/// -/// These functions can be used from scripts -//@{ - -/// Wait for the next debugger event. -/// See also get_process_state() to get info about the current state -/// of the debugged application - -/// Debugger event codes -enum dbg_event_code_t -{ - DEC_NOTASK = -2, ///< process does not exist - DEC_ERROR = -1, ///< error - DEC_TIMEOUT = 0, ///< timeout -}; - -/// \defgroup WFNE_ Wait for debugger event flags -/// Passed as 'wfne' parameter to wait_for_next_event() -//@{ -#define WFNE_ANY 0x0001 ///< return the first event (even if it doesn't suspend the process) -#define WFNE_SUSP 0x0002 ///< wait until the process gets suspended -#define WFNE_SILENT 0x0004 ///< 1: be slient, 0:display modal boxes if necessary -#define WFNE_CONT 0x0008 ///< continue from the suspended state -#define WFNE_NOWAIT 0x0010 ///< do not wait for any event, immediately return ::DEC_TIMEOUT - ///< (to be used with #WFNE_CONT) -#define WFNE_USEC 0x0020 ///< timeout is specified in microseconds - ///< (minimum non-zero timeout is 40000us) -//@} - -/// \defgroup DOPT_ Debugger options -/// Passed as 'options' parameter to set_debugger_options() -//@{ -#define DOPT_SEGM_MSGS 0x00000001 ///< log debugger segments modifications -#define DOPT_START_BPT 0x00000002 ///< break on process start -#define DOPT_THREAD_MSGS 0x00000004 ///< log thread starts/exits -#define DOPT_THREAD_BPT 0x00000008 ///< break on thread start/exit -#define DOPT_BPT_MSGS 0x00000010 ///< log breakpoints -//#define DOPT_BINS_BPT 0x00000020 // break on breakpoint instruction -#define DOPT_LIB_MSGS 0x00000040 ///< log library loads/unloads -#define DOPT_LIB_BPT 0x00000080 ///< break on library load/unload -#define DOPT_INFO_MSGS 0x00000100 ///< log debugging info events -#define DOPT_INFO_BPT 0x00000200 ///< break on debugging information -#define DOPT_REAL_MEMORY 0x00000400 ///< do not hide breakpoint instructions -#define DOPT_REDO_STACK 0x00000800 ///< reconstruct the stack -#define DOPT_ENTRY_BPT 0x00001000 ///< break on program entry point -#define DOPT_EXCDLG 0x00006000 ///< exception dialogs: -# define EXCDLG_NEVER 0x00000000 ///< never display exception dialogs -# define EXCDLG_UNKNOWN 0x00002000 ///< display for unknown exceptions -# define EXCDLG_ALWAYS 0x00006000 ///< always display -#define DOPT_LOAD_DINFO 0x00008000 ///< automatically load debug files (pdb) -#define DOPT_END_BPT 0x00010000 ///< evaluate event condition on process end -#define DOPT_TEMP_HWBPT 0x00020000 ///< when possible use hardware bpts for temp bpts -//@} - - -#ifndef __UI__ - -/// Wait for the next event. -/// -/// This function (optionally) resumes the process execution, -/// and waits for a debugger event until a possible timeout occurs. -/// -/// \param wfne combination of \ref WFNE_ constants -/// \param timeout number of seconds to wait, -1-infinity -/// \return either an event_id_t (if > 0), or a dbg_event_code_t (if <= 0) - -inline dbg_event_code_t idaapi wait_for_next_event(int wfne, int timeout) { return dbg_event_code_t(callui(ui_dbg_wait_for_next_event, wfne, timeout).i); } - - -/// Get the current debugger event - -inline const debug_event_t *idaapi get_debug_event(void) { return (const debug_event_t *)callui(ui_dbg_get_debug_event).vptr; } - - -/// Set debugger options. -/// Replaces debugger options with the specification combination \ref DOPT_ -/// \return the old debugger options - -inline uint idaapi set_debugger_options(uint options) { return callui(ui_dbg_set_debugger_options, options).i; } - - -/// Set remote debugging options. -/// Should be used before starting the debugger. -/// \param host If empty, IDA will use local debugger. -/// If NULL, the host will not be set. -/// \param pass If NULL, the password will not be set -/// \param port If -1, the default port number will be used - -inline void idaapi set_remote_debugger(const char *host, const char *pass, int port=-1) { callui(ui_dbg_set_remote_debugger, host, pass, port); } - - -/// Get process options. -/// Any of the arguments may be NULL - -inline void idaapi get_process_options( - qstring *path, - qstring *args, - qstring *sdir, - qstring *host, - qstring *pass, - int *port) -{ - callui(ui_dbg_get_process_options, path, args, sdir, host, pass, port); -} - - -/// Set process options. -/// Any of the arguments may be NULL, which means 'do not modify' - -inline void idaapi set_process_options( - const char *path, - const char *args, - const char *sdir, - const char *host, - const char *pass, - int port) -{ - callui(ui_dbg_set_process_options, path, args, sdir, host, pass, port); -} - - -/// Retrieve the exception information. -/// You may freely modify the returned vector and add/edit/delete exceptions -/// You must call store_exceptions() after any modifications -/// Note: exceptions with code zero, multiple exception codes or names are prohibited - -inline excvec_t *idaapi retrieve_exceptions(void) { return (excvec_t *)callui(ui_dbg_retrieve_exceptions).vptr; } - - -/// Update the exception information stored in the debugger module by -/// invoking its dbg->set_exception_info callback - -inline bool idaapi store_exceptions(void) { return callui(ui_dbg_store_exceptions).cnd; } - - -/// Convenience function: define new exception code. -/// \param code exception code (cannot be 0) -/// \param name exception name (cannot be empty or NULL) -/// \param desc exception description (maybe NULL) -/// \param flags combination of \ref EXC_ -/// \return failure message or NULL. -/// You must call store_exceptions() if this function succeeds - -inline const char *idaapi define_exception(uint code, const char *name, const char *desc, int flags) { return callui(ui_dbg_define_exception, code, name, desc, flags).cptr; } - -#endif // __UI__ - - -//-------------------------------------------------------------------- - -/// Is set_dbg_options() present in ::debugger_t? - -inline THREAD_SAFE bool have_set_options(const debugger_t *_dbg) -{ - return _dbg != NULL && _dbg->set_dbg_options != NULL; -} - -//-------------------------------------------------------------------- - -/// Convenience function to set debugger specific options. It checks if the debugger -/// is present and the function is present and calls it. - -inline const char *idaapi set_dbg_options( - debugger_t *_dbg, - const char *keyword, - int pri, - int value_type, - const void *value) -{ - const char *code = IDPOPT_BADKEY; - if ( have_set_options(_dbg) ) - code = _dbg->set_dbg_options(keyword, pri, value_type, value); - return code; -} - - -inline const char *idaapi set_dbg_default_options( - debugger_t *_dbg, - const char *keyword, - int value_type, - const void *value) -{ - return set_dbg_options(_dbg, keyword, IDPOPT_PRI_DEFAULT, value_type, value); -} - -inline const char *idaapi set_int_dbg_options( - debugger_t *_dbg, - const char *keyword, - int32 value) -{ - sval_t sv = value; - return set_dbg_default_options(_dbg, keyword, IDPOPT_NUM, &sv); -} - -#ifndef __KERNEL__ -/// Set options for ::dbg - -inline const char *idaapi set_dbg_options( - const char *keyword, - int pri, - int value_type, - const void *value) -{ - return set_dbg_options(dbg, keyword, pri, value_type, value); -} - -/// Set ::dbg options with #IDPOPT_PRI_DEFAULT - -inline const char *idaapi set_dbg_default_options( - const char *keyword, - int value_type, - const void *value) -{ - return set_dbg_options(keyword, IDPOPT_PRI_DEFAULT, value_type, value); -} - -/// Set an integer value option for ::dbg - -inline const char *idaapi set_int_dbg_options( - const char *keyword, - int32 value) -{ - sval_t sv = value; - return set_dbg_default_options(keyword, IDPOPT_NUM, &sv); -} -#endif // __KERNEL__ - -//@} dbg_funcs_high - -//--------------------------------------------------------------------------- -// S O U R C E I N F O R M A T I O N P R O V I D E R S -//--------------------------------------------------------------------------- -/// \defgroup dbg_funcs_srcinfo Source information providers -/// \ingroup dbg_funcs -/// -/// These providers supply information about the source files and lines -/// to the source level debugger. -/// -/// \note objects that inherit from ::qrefcnt_obj_t must be freed -/// using the release() method. do not use the 'delete' operator! -/// See description for qrefcnt_obj_t::release() -/// -/// Currently this interface is not frozen and may change. -/// We will freeze it once we settle things down. -//@{ - -class srcinfo_provider_t; - -class idc_value_t; -class rangeset_t; -class source_item_t; -class argloc_t; - -/// Maintain a reference count for source items -typedef qrefcnt_t source_item_ptr; -/// Iterator for source items -typedef qiterator _source_item_iterator; -/// Maintain a reference count for source item iterators -typedef qrefcnt_t<_source_item_iterator> source_item_iterator; -/// Vector of source items -typedef qvector source_items_t; - -//-------------------------------------------------------------------------- -/// Execution context. Currently not defined in detail. Will probably -/// hold information about the execution context, like: -/// - thread id -/// - current register values -/// - stack frame address - -class eval_ctx_t -{ - int size_cb; -public: - eval_ctx_t(ea_t _ea) : size_cb(sizeof(*this)), ea(_ea) {} - ea_t ea; -}; - - -#ifndef __UI__ -class TWidget; -#endif - -//-------------------------------------------------------------------------- -/// Describes a source file -class source_file_t : public qrefcnt_obj_t -{ -public: - /// Call this function to free source_file_t - virtual void idaapi release() override = 0; - - /// Get source info provider. - /// There is no need to free or release it after using - virtual srcinfo_provider_t *idaapi get_provider(void) const = 0; - - /// Get path to the source file (or a symbolic name). - /// \param[out] errbuf pointer to buffer for the error message - virtual const char *idaapi get_path(qstring *errbuf) = 0; - - /// Open window with source code (optional function). - /// \param[out] strvec pointer to source text. the text should not be destroyed until the form is closed - /// \param[out] pview pointer to view that displays the source text (subview of TWidget) - /// \param lnnum,colnum cursor coordinates - virtual TWidget *open_srcview(strvec_t **strvec, TWidget **pview, int lnnum, int colnum) = 0; - - /// Read entire file (colored lines). - /// \param[out] buf pointer to output buffer - /// \param[out] errbuf pointer to buffer for the error message - virtual bool idaapi read_file(strvec_t *buf, qstring *errbuf) = 0; -}; - -/// Maintain a reference count for source file objects -typedef qrefcnt_t source_file_ptr; -/// Iterator for source files -typedef qiterator _source_file_iterator; -/// Maintain a reference count for source file iterators -typedef qrefcnt_t<_source_file_iterator> source_file_iterator; - -//-------------------------------------------------------------------------- -/// Kinds of source items. -/// Source items are organized into trees. Each tree starts with a MODULE. -/// Each MODULE consists of FUNC and STTVAR global items. -/// Each FUNC consists of STMTs (statements). -/// Each STMT contains some EXPRs (expressions). -enum src_item_kind_t -{ - SRCIT_NONE, ///< unknown - SRCIT_MODULE, ///< module - SRCIT_FUNC, ///< function - SRCIT_STMT, ///< a statement (if/while/for...) - SRCIT_EXPR, ///< an expression (a+b*c) - SRCIT_STTVAR, ///< static variable/code - SRCIT_LOCVAR ///< a stack, register, or register-relative local variable or parameter -}; - -//-------------------------------------------------------------------------- -/// Describes a subdivision of source information -class source_item_t : public qrefcnt_obj_t -{ -public: - /// Call this function to free source_item_t - virtual void idaapi release() override = 0; - - /// Get source files of the item - virtual source_file_iterator idaapi get_source_files() = 0; - - /// Get name of the item - virtual bool idaapi get_name(qstring *buf) const = 0; - - /// Get line number of the item (1-based) - virtual int idaapi get_lnnum() const = 0; - - /// Get ending line number (1-based.) - /// The returned line number is the next - /// line after the expression - virtual int idaapi get_end_lnnum() const = 0; - - /// Get column number of the item. - /// If unknown, return -1 - virtual int idaapi get_colnum() const = 0; - - /// Get ending column number. - /// The returned column number is the next - /// column after the expression. - /// If unknown, return -1 - virtual int idaapi get_end_colnum() const = 0; - - /// Get starting address of the item - virtual ea_t idaapi get_ea() const = 0; - - /// Get size of the item in bytes. - /// If the item is fragmented, return size - /// of the main fragment. - /// if unknown, return 0. - /// On error, return (asize_t) -1. - virtual asize_t idaapi get_size() const = 0; - - /// Get item boundaries as a set of ranges. - /// This function will be used to determine what breakpoints to set for - /// stepping into/stepping over the item. - virtual bool idaapi get_item_bounds(rangeset_t *set) const = 0; - - /// Get parent of the item. - /// \param max_kind maximal source item kind we are interested in. - /// for example, if max_kinds==#SRCIT_STMT, we are not interested - /// in expressions, only in the enclosing statement or function - virtual source_item_ptr idaapi get_parent(src_item_kind_t max_kind) const = 0; - - /// Create an iterator to enumerate all children of the item - virtual source_item_iterator idaapi create_children_iterator() = 0; - - /// Calculate a string to display as a hint. - /// \param hint output buffer for the hint (may by multiline & with colors) - /// \param ctx execution context. NULL means missing context. - /// \param nlines number of important lines in the hint - virtual bool idaapi get_hint( - qstring *hint, - const eval_ctx_t *ctx, - int *nlines) const = 0; - - /// Evaluate item value (meaningful only for expression items). - /// \param ctx execution context. NULL means missing context. - /// \param res buffer for the result (or exception if evaluation failed) - /// \param errbuf buffer for the error message - virtual bool idaapi evaluate( - const eval_ctx_t *ctx, - idc_value_t *res, - qstring *errbuf) const = 0; - - /// Do these two items have the same source?. - /// \retval false the source of the underlying data - /// differs between the two items. - /// \retval true when either the source of the underlying - /// data is the same for the two items, or - /// when such information is not available. - /// - /// E.g., A DWARF implementation of source_item_t will - /// return true if the two items are backed by DIEs - /// that have the same file offset. - virtual bool idaapi equals(const source_item_t *other) const = 0; - - /// \name Getters (for modification) - /// The following functions can be used to extract the item information - /// in order to modify it. For example, if the user wants to modify a variable - /// we will find what exactly needs to be modified. - //@{ - - /// Get item kind - virtual src_item_kind_t idaapi get_item_kind(const eval_ctx_t * /*ctx*/) const newapi { return SRCIT_NONE; } - /// Does this source item represent a statement? - bool is_stmt(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_STMT; } - /// Does this source item represent a module? - bool is_module(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_MODULE; } - /// Does this source item represent a function? - bool is_func(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_FUNC; } - /// Does this source item represent an expression? - bool is_expr(const eval_ctx_t *ctx) const { return get_item_kind(ctx) >= SRCIT_EXPR; } - /// Does this source item represent a stack, register, or register-relative local variable or parameter? - bool is_locvar(const eval_ctx_t *ctx) const { return get_item_kind(ctx) >= SRCIT_LOCVAR; } - /// Does this source item represent a static variable or code? - bool is_sttvar(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_STTVAR; } - - /// Get source info provider. - /// The instance shouldn't be freed or released after using - virtual srcinfo_provider_t *idaapi get_provider(void) const = 0; - - /// Get the location for this source item - virtual bool idaapi get_location(argloc_t * /*out*/, const eval_ctx_t * /*ctx*/) const newapi { return false; } - - /// Get expression type - virtual bool idaapi get_expr_tinfo(tinfo_t *tif) const = 0; - //@} -}; - -#define SRCDBG_PROV_VERSION 4 - -//-------------------------------------------------------------------------- -/// Describes the mechanism used to retrieve source file information -class srcinfo_provider_t -{ -public: - /// size of this class - size_t cb; - - /// \ref SPF_ - int flags; -/// \defgroup SPF_ Source info provider property bits -/// Used by srcinfo_provider_t::flags -//@{ -#define SPF_DECOMPILER 0x0001 ///< is a decompiler? -#define SPF_ENABLED 0x0002 ///< enabled by the user - ///< (this bit is managed by ida) -#define SPF_ACTIVE 0x0004 ///< is willing to work with the current idb - ///< (this bit is managed by ida) -#define SPF_VERSION_MASK 0xFF000000 ///< Version mask, in the flags. - ///< No other flag should have a bit rank > 23. -//@} - - /// internal (unique) name of srcinfo provider - const char *name; - - /// external (displayable) name of srcinfo provider - const char *display_name; - - srcinfo_provider_t(const char *_name, const char *_display_name, int _flags=0) - : cb(sizeof(*this)), flags(_flags), name(_name), display_name(_display_name) - { - flags |= SRCDBG_PROV_VERSION << 24; - } - - /// Is the source info provider a decompiler? - bool is_decompiler(void) const { return (flags & SPF_DECOMPILER) != 0; } - /// Has the provider been enabled by the user? - bool is_enabled(void) const { return (flags & SPF_ENABLED) != 0; } - /// Is the provider willing to work with the current idb? - bool is_active(void) const { return (flags & SPF_ACTIVE) != 0; } - - /// See #SPF_VERSION_MASK - uint8 get_version() const { return (flags >> 24) & 0xFF; } - - /// Enable or disable the provider. - /// If the provider fails to initialize, it returns false, otherwise true - virtual bool idaapi enable_provider(bool enable) = 0; - - /// Configure srcinfo provider. - /// See the description of ::set_options_t - virtual const char *idaapi set_options( - const char *keyword, - int value_type, - const void *value) = 0; - - /// Inform the provider that a module got loaded. - /// The provider is not required to read the module information immediately; - /// it may postpone it until really required. - virtual void idaapi add_module(const char *path, ea_t base, asize_t size) = 0; - - /// Inform the provider that a module got unloaded. - virtual void idaapi del_module(ea_t base) = 0; - - /// Inform the provider that we will request for information now. - /// This function must be called before calling all functions below. - /// probably it will be called when the process gets suspended. - virtual void idaapi get_ready(void) = 0; - - /// Ask the provider if the source information has changed - /// and the screen should be refreshed. UI will call this function - /// periodically (when idle). if it returns a flag value other than #SPCH_NONE, - /// then the source information must be refreshed. - virtual int idaapi get_change_flags(void) = 0; -/// \defgroup SPCH_ Source info changed flags -/// Returned by srcinfo_provider_t::get_change_flags() -//@{ -#define SPCH_NONE 0x0000 ///< nothing has changed -#define SPCH_FILES 0x0001 ///< source files have changed -#define SPCH_ITEMS 0x0002 ///< source items have changed -#define SPCH_LINES 0x0004 ///< source line numbers have changed -//@} - - /// Locate source item by address. - /// The kernel will inquire all registered providers and use the best reply. - /// \param ea linear address - /// \param size size of the item - /// \param level the desired item level: - /// - ::SRCIT_STMT: a statement - /// - ::SRCIT_EXPR: an expression - /// - ::SRCIT_FUNC: a global code item - /// - SRCIT_xxxVAR: a global data item (the exact type is not checked) - /// \param may_decompile meaningful only for the decompiler. if set to false - /// and the function at 'ea' has not been decompiled yet, fail. - virtual source_item_iterator idaapi find_source_items( - ea_t ea, - asize_t size, - src_item_kind_t level, - bool may_decompile) = 0; - - /// Locate source item by a position in a source file. - /// if colnum == 0, return the statement that starts at the specified line. - /// if lnnum == 0, return information about all lines (colnum is ignored in this case) - virtual source_item_iterator idaapi find_source_items(source_file_t *sf, int lnnum, int colnum=0) = 0; - - /// Create iterators to enumerate files. - /// \param filename name of the source file to enumerate - virtual source_file_iterator idaapi create_file_iterator(const char *filename=NULL) = 0; - - /// Create iterators to enumerate items - virtual source_item_iterator idaapi create_item_iterator(const source_file_t *sf) = 0; - - /// Apply the debug information (types, functions, globals) - /// from the module whose path is 'path', to the IDB - virtual bool idaapi apply_module_info(const char * /*path*/) { return false; } - - /// Locate a global variable by its name. - /// \param name The variable name - /// \param ea The current address - /// \return the source item, or NULL - virtual source_item_ptr idaapi find_static_item(const char *name, ea_t ea) = 0; -}; - - -//-------------------------------------------------------------------------- -/// Register a source information provider. -/// Source information providers will call this function to register themselves -/// with IDA kernel. -/// Returns false: a service provider with this name already exists. - -inline bool idaapi register_srcinfo_provider(srcinfo_provider_t *sp) { return callui(ui_dbg_register_provider, sp).cnd; } - - -/// Unregister a source information provider. -/// Returns false: no such provider. - -inline bool idaapi unregister_srcinfo_provider(srcinfo_provider_t *sp) { return callui(ui_dbg_unregister_provider, sp).cnd; } - - -#ifndef __UI__ -class source_view_t; - -/// Create a source code view - -inline source_view_t *create_source_viewer( - TWidget **out_ccv, - TWidget *parent, - TWidget *custview, - source_file_ptr sf, - strvec_t *lines, - int lnnum, - int colnum, - int flags) -{ - return (source_view_t *) callui( - ui_create_source_viewer, out_ccv, parent, custview, &sf, - lines, lnnum, colnum, flags).vptr; -} - -#endif - -//-------------------------------------------------------------------------- -/// Get one byte of the debugged process memory. -/// \param x pointer to byte value -/// \param ea linear address -/// \return true success -/// \return false address inaccessible or debugger not running - -idaman bool ida_export get_dbg_byte(uint32 *x, ea_t ea); - - -/// Change one byte of the debugged process memory. -/// \param ea linear address -/// \param x byte value -/// \return true if the process memory has been modified - -idaman bool ida_export put_dbg_byte(ea_t ea, uint32 x); - -//@} dbg_funcs_srcinfo - -//-------------------------------------------------------------------------- -// D E B U G G E R M E M O R Y F U N C T I O N S F O R U I -//-------------------------------------------------------------------------- -/// \defgroup dbg_funcs_mem Debugger memory functions for UI -/// \ingroup dbg_funcs -/// -/// Inspect debugged process memory. -//@{ - -/// Set the memory information source for IDA kernel. -/// This function allows the kernel to use information coming from somewhere -/// other than the database (from the debugger, for example) -/// \param dbg_get_memory_config returns current memory configuration -/// in the dynamic memory allocated by qalloc(). -/// The kernel will qfree() it automatically. -/// If this argument is NULL, then the debugged -/// process memory is not used. -/// - n: number of ::range_t elements in the answer -/// \param memory_read read bytes from the debugged process memory -/// \param memory_write write bytes to the debugged process memory -/// (don't forget to call invalidate_dbgmem_contents() from it) - -idaman void ida_export set_dbgmem_source( - range_t *(idaapi*dbg_get_memory_config)(int *n), - int (idaapi*memory_read) (ea_t ea, void *buffer, int size), - int (idaapi*memory_write)(ea_t ea, const void *buffer, int size)); - - -/// Invalidate the debugged process memory configuration. -/// Call this function if the debugged process might have changed its memory -/// layout (allocated more memory, for example) - -idaman void ida_export invalidate_dbgmem_config(void); - - -/// Invalidate the debugged process memory contents. -/// Call this function each time the process has been stopped or the process -/// memory is modified. -/// If ea == #BADADDR, then the whole memory contents will be invalidated - -idaman void ida_export invalidate_dbgmem_contents(ea_t ea, asize_t size); - - -/// Is the debugger currently running? - -idaman bool ida_export is_debugger_on(void); - - -/// Is the address mapped to debugger memory? - -idaman bool ida_export is_debugger_memory(ea_t ea); - -//@} dbg_funcs_mem - -//------------------------------------------------------------------------ -#ifndef __UI__ // Not for the UI - - -/// \defgroup dbg_funcs_conv Misc -/// \ingroup dbg_funcs -/// -/// Convenience functions offered by the user interface -//@{ -inline ea_t idaapi get_tev_ea(int n) { ea_t ea; callui(ui_dbg_get_tev_ea, n, &ea); return ea; } -inline int idaapi get_tev_type(int n) { return callui(ui_dbg_get_tev_type, n).i; } -inline int idaapi get_tev_tid(int n) { return callui(ui_dbg_get_tev_tid, n).i; } -inline bool idaapi get_module_info(ea_t ea, modinfo_t *modinfo) { return callui(ui_dbg_get_module_info, ea, modinfo).cnd; } -inline void idaapi bring_debugger_to_front(void) { callui(ui_dbg_bring_to_front); } -inline bool idaapi collect_stack_trace(thid_t tid, call_stack_t *trace) { return callui(ui_dbg_collect_stack_trace, tid, trace).cnd; } -inline const char *idaapi get_debugger_event_cond(void) { return callui(ui_dbg_get_event_cond).cptr; } -inline void idaapi set_debugger_event_cond(const char *NONNULL evcond) { callui(ui_dbg_set_event_cond, evcond); } -inline bool idaapi load_debugger(const char *dbgname, bool use_remote) { return callui(ui_dbg_load_debugger, dbgname, use_remote).cnd; } -inline void idaapi get_manual_regions(meminfo_vec_t *ranges) { callui(ui_dbg_get_manual_regions, ranges); } -inline void idaapi set_manual_regions(const meminfo_vec_t *ranges) { callui(ui_dbg_set_manual_regions, ranges); } -inline void idaapi edit_manual_regions() { callui(ui_dbg_edit_manual_regions); } -inline void idaapi enable_manual_regions(bool enable) { callui(ui_dbg_enable_manual_regions, enable); } -inline int idaapi hide_all_bpts(void) { return callui(ui_dbg_hide_all_bpts).i; } -inline int idaapi handle_debug_event(const debug_event_t *ev, int rqflags) { return callui(ui_dbg_handle_debug_event, ev, rqflags).i; } -inline bool idaapi add_virt_module(const modinfo_t *mod) { return callui(ui_dbg_add_vmod, mod).cnd; } -inline bool idaapi del_virt_module(const ea_t base) { return callui(ui_dbg_del_vmod, base).cnd; } -inline int idaapi set_bptloc_string(const char *s) { return callui(ui_dbg_set_bptloc_string, s).i; } -inline const char *idaapi get_bptloc_string(int i) { return callui(ui_dbg_get_bptloc_string, i).cptr; } -inline int idaapi internal_cleanup_appcall(thid_t tid) { return callui(ui_dbg_internal_cleanup_appcall, tid).i; } -inline int idaapi internal_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value) { return callui(ui_dbg_internal_get_sreg_base, answer, tid, sreg_value).i; } -inline int idaapi internal_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) { return callui(ui_dbg_internal_ioctl, fn, buf, size, poutbuf, poutsize).i; } -inline ssize_t idaapi read_dbg_memory(ea_t ea, void *buffer, size_t size) { return callui(ui_dbg_read_memory, ea, buffer, size).ssize; } -inline ssize_t idaapi write_dbg_memory(ea_t ea, const void *buffer, size_t size) { return callui(ui_dbg_write_memory, ea, buffer, size).ssize; } -inline int idaapi get_reg_vals(thid_t tid, int clsmask, regval_t *values) { return callui(ui_dbg_read_registers, tid, clsmask, values).i; } -inline int idaapi set_reg_val(thid_t tid, int regidx, const regval_t *value) { return callui(ui_dbg_write_register, tid, regidx, value).i; } -inline int idaapi get_dbg_memory_info(meminfo_vec_t *ranges) { return callui(ui_dbg_get_memory_info, ranges).i; } -inline void idaapi set_bpt_group(bpt_t &bpt, const char *grp_name) { callui(ui_dbg_set_bpt_group, &bpt, grp_name); } -inline bool idaapi set_bptloc_group(const bpt_location_t &bptloc, const char *grp_name) { return callui(ui_dbg_set_bptloc_group, &bptloc, grp_name).cnd; } -inline bool idaapi get_bpt_group(qstring *grp_name, const bpt_location_t &bptloc) { return callui(ui_dbg_get_bpt_group, grp_name, &bptloc).cnd; } -inline size_t idaapi list_bptgrps(qstrvec_t *bptgrps) { return callui(ui_dbg_list_bptgrps, bptgrps).ssize; } -inline bool idaapi rename_bptgrp(const char *old_name, const char *new_name) { return callui(ui_dbg_rename_bptgrp, old_name, new_name).cnd; } -inline bool idaapi del_bptgrp(const char *name) { return callui(ui_dbg_del_bptgrp, name).cnd; } -inline ssize_t idaapi get_grp_bpts(bpt_vec_t *bpts, const char *grp_name) { return callui(ui_dbg_get_grp_bpts, bpts, grp_name).ssize; } -inline const char *bpt_t::get_cnd_elang() const { return (const char *)(callui(ui_dbg_internal_get_elang, this).cptr); } -inline bool bpt_t::set_cnd_elang(const char *name) { return callui(ui_dbg_internal_set_elang, this, name).cnd; } -inline srcinfo_provider_t *idaapi get_srcinfo_provider(const char *name) { return (srcinfo_provider_t *)callui(ui_dbg_get_srcinfo_provider, name).vptr; } -inline bool idaapi get_global_var(srcinfo_provider_t *prov, ea_t ea, const char *name, source_item_ptr *out) { return callui(ui_dbg_get_global_var, prov, ea, name, out).cnd; } -inline bool idaapi get_local_var(srcinfo_provider_t *prov, ea_t ea, const char *name, source_item_ptr *out) { return callui(ui_dbg_get_local_var, prov, ea, name, out).cnd; } -inline bool idaapi get_local_vars(srcinfo_provider_t *prov, ea_t ea, source_items_t *out) { return callui(ui_dbg_get_local_vars, prov, ea, out).cnd; } -inline void idaapi add_path_mapping(const char *src, const char *dst) { callui(ui_dbg_add_path_mapping, src, dst); } -inline bool idaapi get_current_source_file(qstring *out) { return callui(ui_dbg_get_current_source_file, out).cnd; } -inline int idaapi get_current_source_line(void) { return callui(ui_dbg_get_current_source_line).i; } -inline bool idaapi srcdbg_step_into(void) { return callui(ui_dbg_srcdbg_step_into).cnd; } -inline bool idaapi srcdbg_request_step_into(void) { return callui(ui_dbg_srcdbg_request_step_into).cnd; } -inline bool idaapi srcdbg_step_over(void) { return callui(ui_dbg_srcdbg_step_over).cnd; } -inline bool idaapi srcdbg_request_step_over(void) { return callui(ui_dbg_srcdbg_request_step_over).cnd; } -inline bool idaapi srcdbg_step_until_ret(void) { return callui(ui_dbg_srcdbg_step_until_ret).cnd; } -inline bool idaapi srcdbg_request_step_until_ret(void) { return callui(ui_dbg_srcdbg_request_step_until_ret).cnd; } -inline drc_t idaapi dbg_bin_search(ea_t *out, ea_t start_ea, ea_t end_ea, const compiled_binpat_vec_t &data, int srch_flags, qstring *errbuf) - { return drc_t(callui(ui_dbg_bin_search, out, start_ea, end_ea, &data, srch_flags, errbuf).i); } -//@} dbg_funcs_conv - -inline bool idaapi dbg_can_query(debugger_t *_dbg) -{ - // Debugger can be queried IIF it is set and either currently in - // suspended state, or can be queried while not in suspended state - return _dbg != NULL && (_dbg->may_disturb() || get_process_state() < DSTATE_NOTASK); -} -#ifndef __KERNEL__ -inline bool idaapi dbg_can_query(void) -{ - return dbg_can_query(dbg); -} -#endif // __KERNEL__ -#endif // __UI__ - - -// internal kernel functions to lock the debugger memory configuration updates -// Do not use these functions! They will be removed! -idaman void ida_export lock_dbgmem_config(void); -idaman void ida_export unlock_dbgmem_config(void); - - -#endif diff --git a/idasdk75/include/demangle.hpp b/idasdk75/include/demangle.hpp deleted file mode 100644 index 33b1333..0000000 --- a/idasdk75/include/demangle.hpp +++ /dev/null @@ -1,269 +0,0 @@ -/* - * CPP/D/Swift Demangler. - * Copyright (c) 2000-2018 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _DEMANGLE_HPP -#define _DEMANGLE_HPP - -// int32 result code -#define ME_INTERR -1 // Internal error -#define ME_PARAMERR -2 // Input parameters are wrong -#define ME_ILLSTR -3 // Incorrectly mangled name -#define ME_SMALLANS -4 // Output buffer is too small - // This code is possible only with the 'old' calling - // form. With the new calling form the output buffer - // will have '...' as the last characters and the - // result code or'ed with the sign bit -#define ME_FRAME -5 // Partial demanging is possible (the input name has - // unrecognized suffix) -#define ME_NOCOMP -6 // Could not determine the compiler -#define ME_ERRAUTO -7 // Specified compiler is impossible for the input name -#define ME_NOHASHMEM -8 // Out of internal indexes-most likely bad input name -#define ME_NOSTRMEM -9 // Out of internal buffers (can't be!:) - -#define ME_NOERROR_LIMIT -10 // Lowest error number. Lower values - // signal about the truncated output name - // (the output buffer is too small) - -#define M_PRCMSK 0x0000000F // If = 0, then data -#define MT_DEFAULT 0x00000001 // 1 - default (for watcom/gnu only this) -#define MT_CDECL 0x00000002 // 2 - __cdecl -#define MT_PASCAL 0x00000003 // 3 - __pascal -#define MT_STDCALL 0x00000004 // 4 - __stdcall -#define MT_FASTCALL 0x00000005 // 5 - __fastcall -#define MT_THISCALL 0x00000006 // 6 - __thiscall [ms & bc => pragma only] -#define MT_FORTRAN 0x00000007 // 7 - __fortran -#define MT_SYSCALL 0x00000008 // 8 - __syscall [without ms] -#define MT_INTERRUPT 0x00000009 // 9 - __interrupt (only with __cdecl!) -#define MT_MSFASTCALL 0x0000000A // A - __msfastcall (bc) -#define MT_CLRCALL 0x0000000B // B - __clrcall (vc7) -#define MT_DMDCALL 0x0000000C // C - __dcall (dm D language abi) -#define MT_VECTORCALL 0x0000000D // D - __vectorcall (vc13) -#define MT_REGCALL 0x0000000E // E - __regcall (icl, clang) - -// reserved -#define MT_LOCALNAME 0x0000000F // f - might be function or data. Currently - // is used only for bc - as the - // identifier for local pascal labels - -#define M_SAVEREGS 0x00000010 // For functions with "__saveregs" - -#define M_CLASS 0x000000E0 // 0 - no keyword (not a member field) -#define MT_PUBLIC 0x00000020 // 1 - public -#define MT_PRIVATE 0x00000040 // 2 - private -#define MT_PROTECT 0x00000060 // 3 - protected -#define MT_MEMBER 0x00000080 // 4 - undetermined (bc/wat/gcc) -#define MT_VTABLE 0x000000A0 // 5 - vtable (bc/gnu) -#define MT_RTTI 0x000000C0 // 6 - typeinfo table (gcc3), witness table (Swift) -// reserved - -#define M_PARMSK 0x0000FF00 // Parameter number mask (excluding ellipsis) - // 255 - >= 255 -#define MT_PARSHF 8 // shift to PARMSK -#define MT_PARMAX 0xFF // Number limiter - // ATT: when CC is __vectorcall and mode is 'C' - // real argscount is unknown. This number is - // total sizeof of all arguments divided to - // sizeof of defptr -#define M_ELLIPSIS 0x00010000 // The function _certainly_ has '...' -#define MT_VOIDARG 0x0001FF00 // If = 0, the func(void), i.e. no parameters -#define M_STATIC 0x00020000 // static - // gcc3 - static data in a function - // might be encountered in object files and - // (possibly) in binaries with debug info -#define M_VIRTUAL 0x00040000 // virtual - // NOTE: for (D) not virtual -- this (counted!) -#define M_AUTOCRT 0x00080000 // Most likely "autogenerated" function (data) - // NOTE: +M_STATIC => "__linkproc__" (bc) - -#define M_TYPMASK 0x00700000 // Special functions (0-regular function) -#define MT_OPERAT 0x00100000 // 1 - operator -#define MT_CONSTR 0x00200000 // 2 - constructor -#define MT_DESTR 0x00300000 // 3 - destructor -#define MT_CASTING 0x00400000 // 4 - type conversion -#define MT_CLRCDTOR 0x00500000 // 5 - delphi2010 CLR ctor/dtor for packages -// reserved - -#define M_TRUNCATE 0x00800000 // Name was truncated by the compiler (bc/va) -#define M_THUNK 0x01000000 // [thunk]: -#define M_ANONNSP 0x02000000 // ms => Anonymous Namespace for field - // gc3 => Item placed in Anonymous namespace - // wat => anonymous_enum - // bc => + TMPLNAM = PascalTemplate (for DCC) - // If separate - "automatic" except_t - // from CBuilder for "external" variables - // or a template for global object - // constructor/destructor tables (for CBuilder - // as well) -#define M_TMPLNAM 0x04000000 // ms => template name (?) - // wat => - // bc => template name => its description table - // gc3 => any template funciton/data -#define M_DBGNAME 0x08000000 // ms => CV: - // wat => xxxx: (T?xxxx-form) - // bc => old pascal format (capitalized) - // gc3 => unicode symbols or 'vendor-extension' - // qualifiers are present - -#define M_COMPILER 0x70000000 // Compiler mask (0-unknown) -#define MT_MSCOMP 0x10000000 // 1 - microsoft/symantec -#define MT_BORLAN 0x20000000 // 2 - borland -#define MT_WATCOM 0x30000000 // 3 - watcom -#define MT_OTHER 0x40000000 // 4 - digital mars D language (start: _D) - // - apple Swift language (start: [_]_T) -// !!! The following definitions must be last and in this order! -#define MT_GNU 0x50000000 // 5 - GNU - (over VA for autodetection) -#define MT_GCC3 0x60000000 // 6 - gcc-v3 - // In the short form this answer is possible - // for GNU/VA as well, but gcc3 can be - // explicitly requested only with it. - // Autodetection works but not very reliable. -#define MT_VISAGE 0x70000000 // 7 - Visual Age - never autodetected - // In the short form this answer means VA - // or GNU. In the automatic mode GNU will - // be used! -//--------------------------------------------------------------------------- -// Flags to inhibit different parts of the demangled name -#define MNG_PTRMSK 0x7 // Memory model mask -// DO NOT change order in this group (PtrType) -#define MNG_DEFNEAR 0x0 // inhibit near, display everything else -#define MNG_DEFNEARANY 0x1 // inhibit near/__ptr64, display everything else -#define MNG_DEFFAR 0x2 // inhibit far, display everything else -#define MNG_NOPTRTYP16 0x3 // inhibit everything (disables vc7-extensions) -#define MNG_DEFHUGE 0x4 // inhibit huge, display everything else -#define MNG_DEFPTR64 0x5 // inhibit __pt64, display everything else - // ATT: in 64bit must be + MNG_NOTYPE|MNG_NOCALLC -#define MNG_DEFNONE 0x6 // display everything -#define MNG_NOPTRTYP 0x7 // inhibit everything -// -#define MNG_NODEFINIT 0x00000008 // Inhibit everything except the main name - // This flag is not recommended - // for __fastcall/__stdcall GCC3 names - // because there is a high probablity of - // incorrect demangling. Use it only when - // you are sure that the input is a - // cygwin/mingw function name -// -#define MNG_NOUNDERSCORE 0x00000010 // Inhibit underscores in __ccall, __pascal... + -#define MNG_NOTYPE 0x00000020 // Inhibit callc&based -#define MNG_NORETTYPE 0x00000040 // Inhibit return type of functions -#define MNG_NOBASEDT 0x00000080 // Inhibit base types - // NOTE: also inhibits "__linkproc__" - // NOTE: -"- 'implicit self types' (Swift) -#define MNG_NOCALLC 0x00000100 // Inhibit __pascal/__ccall/etc - // NOTE: also inhibits "extern (cc)" (D) -#define MNG_NOPOSTFC 0x00000200 // Inhibit postfix const -#define MNG_NOSCTYP 0x00000400 // Inhibit public/private/protected - // NOTE: also inhibits in/out/lazy for args (D) - // NOTE: -"- dynamic/super/override/... (Swift) -#define MNG_NOTHROW 0x00000800 // Inhibit throw description - // NOTE: also inhibits all funcattr (D) -#define MNG_NOSTVIR 0x00001000 // Inhibit "static" & "virtual" - // NOTE: also inhibits (D) top-level procs (<=) -#define MNG_NOECSU 0x00002000 // Inhibit class/struct/union/enum[/D:typedef] -#define MNG_NOCSVOL 0x00004000 // Inhibit const/volatile/restrict - // NOTE: also inhibits __unaligned (vc) - // NOTE: also inhibits transaction_safe(gcc) - // NOTE: also inhibits shared/immutable (D) - // NOTE: also inhibits prefix/postfix/infix/inout (Swift) -#define MNG_NOCLOSUR 0x00008000 // Inhibit __closure for borland - // 'reabstract thunk' description (Swift) -#define MNG_NOUNALG 0x00010000 // Inhibit __unaligned (see NOCSVOL) - // NOTE: also inhibit transaction_safe (see NOCSVOL) -#define MNG_NOMANAGE 0x00020000 // Inhibit __pin/__box/__gc for ms(.net) - // NOTE: also inhibit archetype/witness (Swift) - // NOTE: also ingibit [abi:xxxx] (gcc3) -#define MNG_NOMODULE 0x00040000 // Inhibit module names (Swift) -// 0x00080000 -//++++++ -#define MNG_SHORT_S 0x00100000 // signed (int) is displayed as s(int) -#define MNG_SHORT_U 0x00200000 // unsigned (int) is displayed as u(int) -#define MNG_ZPT_SPACE 0x00400000 // Display space after comma in the arglist - // NOTE: also spaces in name:type pair (Swift) - // and around Swift return clause -> -#define MNG_DROP_IMP 0x00800000 // Inhibit __declspec(dllimport) -// -// 0x01000000 -#define MNG_IGN_ANYWAY 0x02000000 // Ingore '_nn' at the end of name -#define MNG_IGN_JMP 0x04000000 // Ingore 'j_' at the beginning of name -#define MNG_MOVE_JMP 0x08000000 // Move 'j_' prefix to the demangled name - // If both MNG_IGN_JMP and MNG_MOVE_JMP - // are set then move the prefix only if - // the name was not truncated -// -#define MNG_COMPILER_MSK 0x70000000 // Compiler mask (0-autodetect) - -#define MNG_SHORT_FORM (MNG_NOTYPE|MNG_NORETTYPE|MNG_NOPOSTFC|MNG_NOPTRTYP \ - | MNG_NOSCTYP|MNG_NOTHROW|MNG_NOSTVIR|MNG_NOECSU|MNG_NOCLOSUR \ - | MNG_SHORT_U|MNG_DROP_IMP|MNG_NOUNALG|MNG_NOMANAGE \ - | MNG_IGN_JMP|MNG_MOVE_JMP|MNG_IGN_ANYWAY) -#define MNG_LONG_FORM (MNG_ZPT_SPACE | MNG_IGN_JMP | MNG_IGN_ANYWAY | MNG_NOPTRTYP) - -// The description of the following symbol is in the notes -#define MNG_CALC_VALID (MNG_COMPILER_MSK|MNG_IGN_JMP|MNG_IGN_ANYWAY) - -//--------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -#ifndef H2ASH - -#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_DEMANGLE__) -typedef int32 ida_export demangler_t( - char *answer, - uint answer_length, - const char *str, - uint32 disable_mask); -idaman demangler_t demangle; -#endif - -// If answer_length == 0 then no demangling is performed neither. The function -// will check if demangling is possible and what compiler is used to mangle -// the name. If the name cannot be demangled then the function will return 0. -// NOTE: the answer MT_MSCOMP+1 means __msfastcall -// (or borland class name with "_4" suffix) and the demangling is possible -// either as MS (__fastcall) or as bc (__msfastcall) -// NOTE: the answer MT_GCC3+1 means POSSIBLE mingw/cygwin with -// __stdcall/__fastcall but it might also mean ms-stdcall. -// In essense it means that the demangler cannot determine the compiler -// precisely. -// It also means that the demangling is possible in the gcc3 mode -// ONLY when the compiler is explicitly set to gcc3 and MNG_NODEFINIT -// bit is not set. - -// If answer == NULL then the demangler will return check if the demangling -// is possible and only return the flags. -// In this case answer_length should be enough to hold the demangled name. - -// NOTE: If int32(answer_length) < 0 then the demangler will calcuate the -// the number of purged bytes for the given name. In this case -// disable_mask may contain only bits included in MNG_CALC_VALID, -// and -answer_length must be equal to the register size (e.g. -// sizeof(uint16/uint32/uint64)). The value of the register size -// is used to check the numeric value in the ms stdcall/fastcall -// encoding (it is used in the gcc mode too). -// if return value <= 0 - no purged bytes or valid information. -// If (value & 1) != 0 - ms stdcall (definite npurged is value-1. -// If (value & 1) == 0 - 'encoded' counter (not implemented yet). - -// If answer != NULL (and answer_length != 0) - perform demangling and fill out. -// NOTE: if int32(answer_length) < 0 then the buffer size will be -answer_length -// but 'answer' is interpreted not as a pointer to the output buffer but -// as a pointer to pointer to the output buffer (char**). -// In this case if the function succeeds,a pointer to the answer end -// will be returned in the pointer (like stpcpy). In this form 'answer' -// cannot be NULL and *(char**)answer cannot be NULL. -// answer_length must be greater than 9 for the 'truncated' answer. - -typedef int mangled_name_type_t; -const mangled_name_type_t MANGLED_CODE = 0; -const mangled_name_type_t MANGLED_DATA = 1; -const mangled_name_type_t MANGLED_UNKNOWN = 2; - -idaman mangled_name_type_t ida_export get_mangled_name_type(const char *name); - -#endif // H2ASH -#endif // _DEMANGLE_HPP diff --git a/idasdk75/include/diskio.hpp b/idasdk75/include/diskio.hpp deleted file mode 100644 index 8414168..0000000 --- a/idasdk75/include/diskio.hpp +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _DISKIO_HPP -#define _DISKIO_HPP - -#include - -/*! \file diskio.hpp - - \brief File I/O functions for IDA - - You should not use standard C file I/O functions in modules. - Use functions from this header, pro.h and fpro.h instead. - - This file also declares a call_system() function. -*/ - -//------------------------------------------------------------------------- -// S E A R C H F O R F I L E S -//------------------------------------------------------------------------- - - -/// Get IDA directory (if subdir==NULL) -/// or the specified subdirectory (see \ref SUBDIR) - -idaman THREAD_SAFE const char *ida_export idadir(const char *subdir); - - -/// Search for IDA system file. -/// This function searches for a file in: -/// -# each directory specified by %IDAUSR% -/// -# ida directory [+ subdir] -/// and returns the first match. -/// \param[out] buf buffer for file name -/// \param bufsize size of output buffer -/// \param filename name of file to search -/// \param subdir if specified, the file is looked for in the specified subdirectory -/// of the ida directory first (see \ref SUBDIR) -/// \return NULL if not found, otherwise a pointer to full file name. - -idaman THREAD_SAFE char *ida_export getsysfile( - char *buf, - size_t bufsize, - const char *filename, - const char *subdir); - -/// \defgroup SUBDIR IDA subdirectories -/// Passed as 'subdir' parameter to idadir(), getsysfile(), and others. -//@{ -#define CFG_SUBDIR "cfg" -#define IDC_SUBDIR "idc" -#define IDS_SUBDIR "ids" -#define IDP_SUBDIR "procs" -#define LDR_SUBDIR "loaders" -#define SIG_SUBDIR "sig" -#define TIL_SUBDIR "til" -#define PLG_SUBDIR "plugins" -#define THM_SUBDIR "themes" -//@} - -/// Get user ida related directory. -/// \code -/// - if $IDAUSR is defined: -/// - the first element in $IDAUSR -/// - else -/// - default user directory ($HOME/.idapro or %APPDATA%Hex-Rays/IDA Pro) -/// \endcode - -idaman THREAD_SAFE const char *ida_export get_user_idadir(void); - - -/// Get list of directories in which to find a specific IDA resource -/// (see \ref SUBDIR). The order of the resulting list is as follows: -/// \code -/// - [$IDAUSR/subdir (0..N entries)] -/// - $IDADIR/subdir -/// \endcode -/// \param[out] dirs output vector for directory names -/// \param subdir name of the resource to list -/// \param flags \ref IDA_SUBDIR_ bits -/// \return number of directories appended to 'dirs' - -idaman THREAD_SAFE int ida_export get_ida_subdirs(qstrvec_t *dirs, const char *subdir, int flags=0); - -/// \defgroup IDA_SUBDIR_ Subdirectory modification flags -/// Passed as 'flags' parameter to get_ida_subdirs() -//@{ -#define IDA_SUBDIR_IDP 0x0001 ///< append the processor name as a subdirectory -#define IDA_SUBDIR_IDADIR_FIRST 0x0002 ///< $IDADIR/subdir will be first, not last -#define IDA_SUBDIR_ONLY_EXISTING 0x0004 ///< only existing directories will be present -//@} - - -/// Get a folder location by CSIDL (see \ref CSIDL). -/// Path should be of at least MAX_PATH size - -idaman THREAD_SAFE bool ida_export get_special_folder(char *buf, size_t bufsize, int csidl); - -/// \defgroup CSIDL Common CSIDLs -/// Passed as 'csidl' parameter to get_special_folder() -//@{ -#ifndef CSIDL_APPDATA -#define CSIDL_APPDATA 0x001a -#endif -#ifndef CSIDL_LOCAL_APPDATA -#define CSIDL_LOCAL_APPDATA 0x001c -#endif -#ifndef CSIDL_PROGRAM_FILES -#define CSIDL_PROGRAM_FILES 0x0026 -#endif -#ifndef CSIDL_PROGRAM_FILES_COMMON -#define CSIDL_PROGRAM_FILES_COMMON 0x002b -#endif -#ifndef CSIDL_PROGRAM_FILESX86 -#define CSIDL_PROGRAM_FILESX86 0x002a -#endif -//@} - -/// Enumerate files in the specified directory. -/// \param[out] answer buffer to contain the file name for which -/// file_enumerator_t::visit_file returns non-zero value -/// (may be NULL) -/// \param answer_size size of 'answer' -/// \param path directory to enumerate files in -/// \param fname mask of file names to enumerate -/// \param fv file_enumerator_t::visit_file function called for each file -/// - file: full file name (with path) -/// - if returns non-zero value, the enumeration -/// is stopped and the return code is -/// is returned to the caller. -/// the callback function -/// \return zero or the code returned by 'func' - -struct file_enumerator_t -{ - virtual int visit_file(const char *file) = 0; - DEFINE_VIRTUAL_DTOR(file_enumerator_t) -}; - -idaman THREAD_SAFE int ida_export enumerate_files2( - char *answer, - size_t answer_size, - const char *path, - const char *fname, - file_enumerator_t &fv); - - - -//------------------------------------------------------------------------- -// O P E N / R E A D / W R I T E / C L O S E F I L E S -//------------------------------------------------------------------------- - -/// \name Open/Read/Write/Close Files -/// There are two sets of "open file" functions. -/// The first set tries to open a file and returns success or failure. -/// The second set is "open or die": if the file cannot be opened -/// then the function will display an error message and exit. -//@{ - -/// Open a new file for write in text mode, deny write. -/// If a file exists, it will be removed. -/// \return NULL if failure - -idaman THREAD_SAFE FILE *ida_export fopenWT(const char *file); - - -/// Open a new file for write in binary mode, deny read/write. -/// If a file exists, it will be removed. -/// \return NULL if failure - -idaman THREAD_SAFE FILE *ida_export fopenWB(const char *file); - - -/// Open a file for read in text mode, deny none. -/// \return NULL if failure - -idaman THREAD_SAFE FILE *ida_export fopenRT(const char *file); - - -/// Open a file for read in binary mode, deny none. -/// \return NULL if failure - -idaman THREAD_SAFE FILE *ida_export fopenRB(const char *file); - - -/// Open a file for read/write in binary mode, deny write. -/// \return NULL if failure - -idaman THREAD_SAFE FILE *ida_export fopenM(const char *file); - - -/// Open a file for append in text mode, deny none. -/// \return NULL if failure - -idaman THREAD_SAFE FILE *ida_export fopenA(const char *file); - - -/// Open a file for read in binary mode or die, deny none. -/// If a file cannot be opened, this function displays a message and exits. - -idaman THREAD_SAFE FILE *ida_export openR(const char *file); - - -/// Open a file for read in text mode or die, deny none. -/// If a file cannot be opened, this function displays a message and exits. - -idaman THREAD_SAFE FILE *ida_export openRT(const char *file); - - -/// Open a file for read/write in binary mode or die, deny write. -/// If a file cannot be opened, this function displays a message and exits. - -idaman THREAD_SAFE FILE *ida_export openM(const char *file); - - -//@} - -//------------------------------------------------------------------------- -// F I L E S I Z E / D I S K S P A C E -//------------------------------------------------------------------------- - -/// Get length of file in bytes. -/// \param fp pointer to file - -idaman THREAD_SAFE uint64 ida_export qfsize(FILE *fp); - - -/// Change size of file or die. -/// If an error occurs, this function displays a message and exits. -/// \param fp pointer to file -/// \param size new size of file - -idaman THREAD_SAFE void ida_export echsize(FILE *fp, uint64 size); - - -/// Get free disk space in bytes. -/// \param path name of any directory on the disk to get information about - -idaman THREAD_SAFE uint64 ida_export get_free_disk_space(const char *path); - - -//------------------------------------------------------------------------- -// I / O P O R T D E F I N I T I O N S F I L E -//------------------------------------------------------------------------- -/// Describes an I/O port bit -struct ioport_bit_t -{ - qstring name; ///< name of the bit - qstring cmt; ///< comment -}; -DECLARE_TYPE_AS_MOVABLE(ioport_bit_t); -typedef qvector ioport_bits_t; - -/// Describes an I/O port -struct ioport_t -{ - ea_t address; ///< address of the port - qstring name; ///< name of the port - qstring cmt; ///< comment - ioport_bits_t bits; ///< bit names - void *userdata; ///< arbitrary data. initialized to NULL. - - ioport_t() - : address(0), userdata(NULL) - { - } -}; -DECLARE_TYPE_AS_MOVABLE(ioport_t); -typedef qvector ioports_t; - -/// Read i/o port definitions from a config file. -/// -/// Each device definition in the input file begins with a line like this: -/// -/// \v{.devicename} -/// -/// After it go the port definitions in this format: -/// -/// \v{portname address} -/// -/// The bit definitions (optional) are represented like this: -/// -/// \v{portname.bitname bitnumber} -/// -/// Lines beginning with a space are ignored. -/// comment lines should be started with ';' character. -/// -/// The default device is specified at the start of the file: -/// -/// \v{.default device_name} -/// -/// \note It is permissible to have a symbol mapped to several addresses -/// but all addresses must be unique. -/// \param[out] ports output vector -/// \param device contains device name to load. If default_device[0] == 0 -/// then the default device is determined by .default directive -/// in the config file. -/// \param file config file name -/// \param callback callback to call when the input line can't be parsed normally. -/// - line: input line to parse -/// - returns error message. if NULL, then the line is parsed ok. -/// \return -1 on error or size of vector - -idaman THREAD_SAFE ssize_t ida_export read_ioports( - ioports_t *ports, - qstring *device, - const char *file, - const char *(idaapi *callback)( - const ioports_t &ports, - const char *line)=NULL); - - -struct ioports_fallback_t -{ - // returns success or fills ERRBUF with an error message - virtual bool handle(qstring *errbuf, const ioports_t &ports, const char *line) = 0; -}; - -idaman THREAD_SAFE ssize_t ida_export read_ioports2( - ioports_t *ports, - qstring *device, - const char *file, - ioports_fallback_t *callback=nullptr); - - -/// Allow the user to choose the ioport device. -/// \param[in,out] device in: contains default device name. If default_device[0] == 0 -/// then the default device is determined by .default directive -/// in the config file. -/// out: the selected device name -/// \param file config file name -/// \param parse_params if present (non NULL), then defines a callback which -/// will be called for all lines not starting with a dot (.) -/// This callback may parse these lines are prepare a simple -/// processor parameter string. This string will be displayed -/// along with the device name. -/// If it returns #IOPORT_SKIP_DEVICE, then the current -/// device will not be included in the list. -/// \retval true the user selected a device, its name is in 'device' -/// \retval false the selection was cancelled. if device=="NONE" upon return, -/// then no devices were found in the configuration file - -idaman THREAD_SAFE bool ida_export choose_ioport_device( - qstring *_device, - const char *file, - const char *(idaapi *parse_params)( - qstring *buf, - const char *line)=NULL); - -struct choose_ioport_parser_t -{ - /// \retval true and fill PARAM with a displayed string - /// \retval false and empty PARAM to skip the current device - /// \retval false and fill PARAM with an error message - virtual bool parse(qstring *param, const char *line) = 0; -}; - -idaman THREAD_SAFE bool ida_export choose_ioport_device2( - qstring *_device, - const char *file, - choose_ioport_parser_t *parse_params); - -/// See 'parse_params' parameter to choose_ioport_device() -#define IOPORT_SKIP_DEVICE ((const char *)(-1)) - - -/// Find ioport in the array of ioports - -idaman THREAD_SAFE const ioport_t *ida_export find_ioport(const ioports_t &ports, ea_t address); - - -/// Find ioport bit in the array of ioports - -idaman THREAD_SAFE const ioport_bit_t *ida_export find_ioport_bit(const ioports_t &ports, ea_t address, size_t bit); - - -//------------------------------------------------------------------------- -// S Y S T E M S P E C I F I C C A L L S -//------------------------------------------------------------------------- - -/// Execute a operating system command. -/// This function suspends the interface (Tvision), runs the command -/// and redraws the screen. -/// \param command command to execute. If NULL, an interactive shell is activated -/// \return the error code returned by system() call - -idaman THREAD_SAFE int ida_export call_system(const char *command); - - -//------------------------------------------------------------------------- -// L O A D E R I N P U T S O U R C E F U N C T I O N S -//------------------------------------------------------------------------- - -/// \name Loader Input Source -/// Starting with v4.8 IDA can load and run remote files. -/// In order to do that, we replace the FILE* in the loader modules -/// with an abstract input source (linput_t). The source might be linked to -/// a local or remote file. -//@{ - -class linput_t; ///< loader input source - - -/// linput types -enum linput_type_t -{ - LINPUT_NONE, ///< invalid linput - LINPUT_LOCAL, ///< local file - LINPUT_RFILE, ///< remote file (\dbg{open_file}, \dbg{read_file}) - LINPUT_PROCMEM, ///< debugged process memory (read_dbg_memory()) - LINPUT_GENERIC ///< generic linput -}; - - -/// Read the input source. -/// If failed, inform the user and ask him if he wants to continue. -/// If he does not, this function will not return (loader_failure() will be called). -/// This function may be called only from loaders! - -idaman void ida_export lread(linput_t *li, void *buf, size_t size); - - -/// Read the input source. -/// \return number of read bytes or -1 - -idaman ssize_t ida_export qlread(linput_t *li, void *buf, size_t size); - - -/// Read one line from the input source. -/// \return NULL if failure, otherwise 's' - -idaman char *ida_export qlgets(char *s, size_t len, linput_t *li); - - -/// Read one character from the input source. -/// \return EOF if failure, otherwise the read character - -idaman int ida_export qlgetc(linput_t *li); - - -/// Read multiple bytes and swap if necessary. -/// \param li input file -/// \param buf pointer to output buffer -/// \param size number of bytes to read -/// \param mf big endian? -/// \retval 0 ok -/// \retval -1 failure - -idaman int ida_export lreadbytes(linput_t *li, void *buf, size_t size, bool mf); - -/// Helper to define lread2bytes(), lread4bytes(), etc -#define DEF_LREADBYTES(read, type, size) \ -/*! \brief Read a value from linput - also see lreadbytes() */ \ -inline int idaapi read(linput_t *li, type *res, bool mf) \ - { return lreadbytes(li, res, size, mf); } -DEF_LREADBYTES(lread2bytes, int16, 2) -DEF_LREADBYTES(lread2bytes, uint16, 2) -DEF_LREADBYTES(lread4bytes, int32, 4) -DEF_LREADBYTES(lread4bytes, uint32, 4) -DEF_LREADBYTES(lread8bytes, int64, 8) -DEF_LREADBYTES(lread8bytes, uint64, 8) -#undef DEF_LREADBYTES - - -/// Read a zero-terminated string from the input. -/// If fpos == -1 then no seek will be performed. - -idaman char *ida_export qlgetz( - linput_t *li, - int64 fpos, - char *buf, - size_t bufsize); - - -/// Get the input source size - -idaman int64 ida_export qlsize(linput_t *li); - - -/// Set input source position. -/// \return the new position (not 0 as fseek!) - -idaman qoff64_t ida_export qlseek(linput_t *li, qoff64_t pos, int whence=SEEK_SET); - - -/// Get input source position - -inline qoff64_t idaapi qltell(linput_t *li) { return qlseek(li, 0, SEEK_CUR); } - - -/// Open loader input - -idaman linput_t *ida_export open_linput(const char *file, bool remote); - - -/// Close loader input - -idaman THREAD_SAFE void ida_export close_linput(linput_t *li); - - -/// Get FILE* from the input source. -/// If the input source is linked to a remote file, then return NULL. -/// Otherwise return the underlying FILE* -/// Please do not use this function if possible. - -idaman THREAD_SAFE FILE *ida_export qlfile(linput_t *li); - - -/// Convert FILE * to input source. -/// Used for temporary linput_t objects - call unmake_linput() to free -/// the slot after the use. - -idaman THREAD_SAFE linput_t *ida_export make_linput(FILE *fp); - -/// Free an linput_t object (also see make_linput()) - -idaman THREAD_SAFE void ida_export unmake_linput(linput_t *li); - - -/// Generic linput class - may be used to create a linput_t instance for -/// any data source -struct generic_linput_t -{ - /// \name Warning - /// The following two fields must be filled before calling create_generic_linput() - //@{ - uint64 filesize; ///< input file size - uint32 blocksize; ///< preferred block size to work with - ///< read/write sizes will be in multiples of this number. - ///< for example, 4096 is a nice value - ///< blocksize 0 means that the filesize is unknown. - ///< the internal cache will be disabled in this case. - ///< also, seeks from the file end will fail. - ///< blocksize=-1 means error. - //@} - virtual ssize_t idaapi read(qoff64_t off, void *buffer, size_t nbytes) = 0; - DEFINE_VIRTUAL_DTOR(generic_linput_t) -}; - -/// Create a generic linput -/// \param gl linput description. -/// this object will be destroyed by close_linput() -/// using "delete gl;" - -idaman THREAD_SAFE linput_t *ida_export create_generic_linput(generic_linput_t *gl); - -/// Trivial memory linput - -idaman THREAD_SAFE linput_t *ida_export create_bytearray_linput(const uchar *start, size_t size); - - -/// Create a linput for process memory. -/// This linput will use read_dbg_memory() to read data. -/// \param start starting address of the input -/// \param size size of the memory area to represent as linput -/// if unknown, may be passed as 0 - -idaman linput_t *ida_export create_memory_linput(ea_t start, asize_t size); - -/// Get linput type - -inline THREAD_SAFE linput_type_t idaapi get_linput_type(linput_t *li) -{ - return *(linput_type_t *)li; -} - -/// Object that will free an linput_t at destruction-time -typedef janitor_t linput_janitor_t; -/// Free the linput_t -template <> inline linput_janitor_t::~janitor_t() -{ - close_linput(resource); -} - -//--------------------------------------------------------------------------- -/// Helper class - adapts linput to be used in extract_... functions -/// as a data supplier (see kernwin.hpp) -class linput_buffer_t -{ -public: - linput_buffer_t(linput_t *linput, int64 size=0): li(linput), lsize(size) {} - ssize_t read(void *buf, size_t n) - { - return qlread(li, buf, n); - } - bool eof() - { - if ( lsize == 0 ) - lsize = qlsize(li); - return qltell(li) >= lsize; - } -protected: - linput_t *li; -private: - int64 lsize; -}; - -//@} - -// ------------------------------------------------------------------------- - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED THREAD_SAFE FILE *ida_export ecreate(const char *file); -idaman DEPRECATED THREAD_SAFE void ida_export eclose(FILE *fp); -idaman DEPRECATED THREAD_SAFE void ida_export eread(FILE *fp, void *buf, size_t size); -idaman DEPRECATED THREAD_SAFE void ida_export ewrite(FILE *fp, const void *buf, size_t size); -idaman DEPRECATED THREAD_SAFE void ida_export eseek(FILE *fp, qoff64_t pos); -idaman DEPRECATED THREAD_SAFE int ida_export enumerate_files( - char *answer, - size_t answer_size, - const char *path, - const char *fname, - int (idaapi*func)(const char *file,void *ud), - void *ud=NULL); -#endif -#endif // _DISKIO_HPP diff --git a/idasdk75/include/entry.hpp b/idasdk75/include/entry.hpp deleted file mode 100644 index 1a9fd99..0000000 --- a/idasdk75/include/entry.hpp +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _ENTRY_HPP -#define _ENTRY_HPP - -/*! \file entry.hpp - - \brief Functions that deal with entry points - - Exported functions are considered as entry points as well. - - IDA maintains list of entry points to the program. - Each entry point: - - has an address - - has a name - - may have an ordinal number -*/ - -/// Get number of entry points - -idaman size_t ida_export get_entry_qty(void); - -/// \defgroup AEF_ entry flags -/// Passed as 'flags' parameter to add_entry(ea_t, const char *, int) -//@{ -#define AEF_UTF8 0x0 ///< the name is given in UTF-8 (default) -#define AEF_IDBENC 0x1 ///< the name is given in the IDB encoding; - ///< non-ASCII bytes will be decoded accordingly - ///< Specifying AEF_IDBENC also implies AEF_NODUMMY -#define AEF_NODUMMY 0x2 ///< automatically prepend the name with '_' if - ///< it begins with a dummy suffix. See also AEF_IDBENC -//@} - - -/// Add an entry point to the list of entry points. -/// \param ord ordinal number -/// if ordinal number is equal to 'ea' then ordinal is not used -/// \param ea linear address -/// \param name name of entry point. If the specified location already -/// has a name, the old name will be appended to the regular -/// comment. If name == NULL, then the old name will be retained. -/// \param makecode should the kernel convert bytes at the entry point -/// to instruction(s) -/// \param flags See AEF_* -/// \return success (currently always true) - -idaman bool ida_export add_entry(uval_t ord, ea_t ea, const char *name, bool makecode, int flags=AEF_UTF8); - - -/// Get ordinal number of an entry point. -/// \param idx internal number of entry point. Should be -/// in the range 0..get_entry_qty()-1 -/// \return ordinal number or 0. - -idaman uval_t ida_export get_entry_ordinal(size_t idx); - - -/// Get entry point address by its ordinal -/// \param ord ordinal number of entry point -/// \return address or #BADADDR - -idaman ea_t ida_export get_entry(uval_t ord); - - -/// Get name of the entry point by its ordinal. -/// \param buf output buffer, may be NULL -/// \param ord ordinal number of entry point -/// \return size of entry name or -1 - -idaman ssize_t ida_export get_entry_name(qstring *buf, uval_t ord); - - -/// Rename entry point. -/// \param ord ordinal number of the entry point -/// \param name name of entry point. If the specified location already -/// has a name, the old name will be appended to a repeatable -/// comment. -/// \param flags See AEF_* -/// \return success - -idaman bool ida_export rename_entry(uval_t ord, const char *name, int flags=AEF_UTF8); - - -/// Set forwarder name for ordinal. -/// \param ord ordinal number of the entry point -/// \param name forwarder name for entry point. -/// \param flags See AEF_* -/// \return success - -idaman bool ida_export set_entry_forwarder(uval_t ord, const char *name, int flags=AEF_UTF8); - - -/// Get forwarder name for the entry point by its ordinal. -/// \param buf output buffer, may be NULL -/// \param ord ordinal number of entry point -/// \return size of entry forwarder name or -1 - -idaman ssize_t ida_export get_entry_forwarder(qstring *buf, uval_t ord); - - -#endif // _ENTRY_HPP diff --git a/idasdk75/include/enum.hpp b/idasdk75/include/enum.hpp deleted file mode 100644 index 74d3bff..0000000 --- a/idasdk75/include/enum.hpp +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * Enums and bitfields - * Bitfields will be abbreviated as "bf". - * - */ - -#ifndef _ENUM_HPP -#define _ENUM_HPP - -#include - -/*! \file enum.hpp - - \brief Assembly level enum management - - Enums and bitfields are represented as ::enum_t. -*/ - -typedef tid_t enum_t; ///< Enums and bitfields - -typedef uval_t bmask_t; ///< unsigned value that describes a bitmask - ///< a bit mask is 32/64 bits. - -#define DEFMASK (bmask_t(-1)) ///< default bitmask - -typedef uval_t const_t; ///< members of enums - -/// Max number of identical constants allowed for one enum type -const uchar MAX_ENUM_SERIAL = 255; - - -/// Get number of declared ::enum_t types - -idaman size_t ida_export get_enum_qty(void); - - -/// Get enum by its index in the list of enums (0..get_enum_qty()-1). - -idaman enum_t ida_export getn_enum(size_t idx); - - -/// Get the index in the list of enums - -idaman uval_t ida_export get_enum_idx(enum_t id); - - -/// Get enum by name - -idaman enum_t ida_export get_enum(const char *name); - - -/// Is enum a bitfield? -/// (otherwise - plain enum, no bitmasks except for #DEFMASK are allowed) - -idaman bool ida_export is_bf(enum_t id); - - -/// Is enum collapsed? - -idaman bool ida_export is_enum_hidden(enum_t id); - - -/// Collapse enum - -idaman bool ida_export set_enum_hidden(enum_t id, bool hidden); - - -/// Does enum come from type library? - -idaman bool ida_export is_enum_fromtil(enum_t id); - - -/// Specify that enum comes from a type library - -idaman bool ida_export set_enum_fromtil(enum_t id, bool fromtil); - - -/// Is a ghost copy of a local type? - -idaman bool ida_export is_ghost_enum(enum_t id); - - -/// Specify that enum is a ghost copy of a local type - -idaman bool ida_export set_enum_ghost(enum_t id, bool ghost); - - -/// Get name of enum - -idaman ssize_t ida_export get_enum_name(qstring *out, enum_t id); - -/// Get name of enum -/// \param[out] out buffer to hold the name -/// \param id enum id -/// \param flags \ref ENFL_ - -idaman ssize_t ida_export get_enum_name2(qstring *out, enum_t id, int flags=0); - -/// \defgroup ENFL_ Enum name flags -/// Passed as 'flags' parameter to get_enum_name() -//@{ -#define ENFL_REGEX 0x0001 ///< apply regular expressions to beautify the name -//@} - -inline qstring get_enum_name(tid_t id, int flags=0) -{ - qstring name; - get_enum_name2(&name, id, flags); - return name; -} - - -/// Get the width of a enum element -/// allowed values: 0 (unspecified),1,2,4,8,16,32,64 - -idaman size_t ida_export get_enum_width(enum_t id); - - -/// See comment for get_enum_width() - -idaman bool ida_export set_enum_width(enum_t id, int width); - - -/// Get enum comment - -idaman ssize_t ida_export get_enum_cmt(qstring *buf, enum_t id, bool repeatable); - - -/// Get the number of the members of the enum - -idaman size_t ida_export get_enum_size(enum_t id); - - -/// Get flags determining the representation of the enum. -/// (currently they define the numeric base: octal, decimal, hex, bin) and signness. - -idaman flags_t ida_export get_enum_flag(enum_t id); - - -/// Get a reference to an enum member by its name - -idaman const_t ida_export get_enum_member_by_name(const char *name); - - -/// Get value of an enum member - -idaman uval_t ida_export get_enum_member_value(const_t id); - - -/// Get the parent enum of an enum member - -idaman enum_t ida_export get_enum_member_enum(const_t id); - - -/// Get bitmask of an enum member - -idaman bmask_t ida_export get_enum_member_bmask(const_t id); - - -/// Find an enum member by enum, value and bitmask -/// \note if serial -1, return a member with any serial - -idaman const_t ida_export get_enum_member(enum_t id, uval_t value, int serial, bmask_t mask); - - -/// \name Access to all used bitmasks in an enum -//@{ - -/// Get first bitmask in the enum (bitfield) -/// -/// \param enum_id id of enum (bitfield) -/// \return the smallest bitmask for enum, or DEFMASK -/// -idaman bmask_t ida_export get_first_bmask(enum_t id); - -/// Get last bitmask in the enum (bitfield) -/// -/// \param enum_id id of enum -/// \return the biggest bitmask for enum, or DEFMASK -idaman bmask_t ida_export get_last_bmask(enum_t id); - -/// Get next bitmask in the enum (bitfield) -/// -/// \param enum_id id of enum -/// \param value the current bitmask -/// \return value of a bitmask with value higher than the specified value, or DEFMASK -idaman bmask_t ida_export get_next_bmask(enum_t id, bmask_t bmask); - -/// Get prev bitmask in the enum (bitfield) -/// -/// \param enum_id id of enum -/// \param value the current bitmask -/// \return value of a bitmask with value lower than the specified value, or DEFMASK -idaman bmask_t ida_export get_prev_bmask(enum_t id, bmask_t bmask); -//@} - - -/// \name Access to all enum members with specified bitmask -/// \note these functions return values, not ::const_t! -//@{ -idaman uval_t ida_export get_first_enum_member(enum_t id, bmask_t bmask=DEFMASK); -idaman uval_t ida_export get_last_enum_member(enum_t id, bmask_t bmask=DEFMASK); -idaman uval_t ida_export get_next_enum_member(enum_t id, uval_t value, bmask_t bmask=DEFMASK); -idaman uval_t ida_export get_prev_enum_member(enum_t id, uval_t value, bmask_t bmask=DEFMASK); -//@} - - -/// Get name of an enum member by const_t - -idaman ssize_t ida_export get_enum_member_name(qstring *out, const_t id); - - -/// Get enum member's comment - -idaman ssize_t ida_export get_enum_member_cmt(qstring *buf, const_t id, bool repeatable); - - -/// \name Access to all enum members with specified value and mask -/// A sample loop looks like this: -/// \code -/// const_t main_cid; -/// uchar serial; -/// for ( const_t cid=main_cid=get_first_serial_enum_member(&serial, id, v, mask); -/// cid != BADNODE; -/// cid = get_next_serial_enum_member(&serial, main_cid) ) -/// { -/// ... -/// } -/// \endcode -/// The 'out_serial' argument of get_first_serial_enum_member/get_last_serial_enum_member can be NULL. -/// The 'in_out_serial' is required for the other functions. -//@{ -idaman const_t ida_export get_first_serial_enum_member(uchar *out_serial, enum_t id, uval_t value, bmask_t bmask); -idaman const_t ida_export get_last_serial_enum_member(uchar *out_serial, enum_t id, uval_t value, bmask_t bmask); -idaman const_t ida_export get_next_serial_enum_member(uchar *in_out_serial, const_t first_cid); -idaman const_t ida_export get_prev_serial_enum_member(uchar *in_out_serial, const_t first_cid); -//@} - - -/// Enum member visitor - see for_all_enum_members(). -/// Derive your visitor from this class. -struct enum_member_visitor_t -{ - /// Implements action to take when enum member is visited. - /// \return nonzero to stop the iteration - virtual int idaapi visit_enum_member(const_t cid, uval_t value) = 0; -}; - - -/// Visit all members of a given enum - -idaman int ida_export for_all_enum_members(enum_t id, enum_member_visitor_t &cv); - - -/// Get serial number of an enum member - -idaman uchar ida_export get_enum_member_serial(const_t cid); - - -/// Get corresponding type ordinal number - -idaman int32 ida_export get_enum_type_ordinal(enum_t id); - - -/// Set corresponding type ordinal number - -idaman void ida_export set_enum_type_ordinal(enum_t id, int32 ord); - - -//-------------------------------------------------------------------------- -// MANIPULATION - -/// Add new enum type. -/// - if idx==#BADADDR then add as the last idx -/// - if name==NULL then generate a unique name "enum_%d" - -idaman enum_t ida_export add_enum(size_t idx, const char *name, flags_t flag); - - -/// Delete an enum type - -idaman void ida_export del_enum(enum_t id); - - -/// Set serial number of enum. -/// Also see get_enum_idx(). - -idaman bool ida_export set_enum_idx(enum_t id, size_t idx); - - -/// Set 'bitfield' bit of enum (i.e. convert it to a bitfield) - -idaman bool ida_export set_enum_bf(enum_t id, bool bf); - - -/// Set name of enum type - -idaman bool ida_export set_enum_name(enum_t id,const char *name); - - -/// Set comment for enum type - -idaman bool ida_export set_enum_cmt(enum_t id,const char *cmt,bool repeatable); - - -/// Set data representation flags - -idaman bool ida_export set_enum_flag(enum_t id, flags_t flag); - - -/// Add member to enum type. -/// \return 0 if ok, otherwise one of \ref ENUM_MEMBER_ - -idaman int ida_export add_enum_member( - enum_t id, - const char *name, - uval_t value, - bmask_t bmask=DEFMASK); - - -/// \defgroup ENUM_MEMBER_ Add enum member result codes -/// Return values for add_enum_member() -//@{ -#define ENUM_MEMBER_ERROR_NAME 1 ///< already have member with this name (bad name) -#define ENUM_MEMBER_ERROR_VALUE 2 ///< already have 256 members with this value -#define ENUM_MEMBER_ERROR_ENUM 3 ///< bad enum id -#define ENUM_MEMBER_ERROR_MASK 4 ///< bad bmask -#define ENUM_MEMBER_ERROR_ILLV 5 ///< bad bmask and value combination (~bmask & value != 0) -//@} - - -/// Delete member of enum type - -idaman bool ida_export del_enum_member(enum_t id, uval_t value, uchar serial, bmask_t bmask); - - -/// Set name of enum member - -idaman bool ida_export set_enum_member_name(const_t id, const char *name); - - -/// Set comment for enum member - -inline bool set_enum_member_cmt(const_t id, const char *cmt, bool repeatable) -{ - return set_enum_cmt(id, cmt, repeatable); -} - - -/// Is bitmask one bit? - -inline THREAD_SAFE bool is_one_bit_mask(bmask_t mask) -{ - return (mask & (mask-1)) == 0; -} - - -/// \name Work with the bitmask name & comment -//@{ -idaman bool ida_export set_bmask_name(enum_t id, bmask_t bmask, const char *name); -idaman ssize_t ida_export get_bmask_name(qstring *out, enum_t id, bmask_t bmask); - -idaman bool ida_export set_bmask_cmt(enum_t id, bmask_t bmask, const char *cmt, bool repeatable); -idaman ssize_t ida_export get_bmask_cmt(qstring *buf, enum_t id, bmask_t bmask, bool repeatable); -//@} - -#endif // _ENUM_HPP diff --git a/idasdk75/include/err.h b/idasdk75/include/err.h deleted file mode 100644 index 75c154d..0000000 --- a/idasdk75/include/err.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _ERR_H -#define _ERR_H - -#include - -/*! \file err.h - - \brief Thread safe functions that deal with error codes - -*/ - -/// Print error message to stderr (analog of perror) - -idaman THREAD_SAFE AS_PRINTF(1, 0) void ida_export vqperror(const char *format, va_list va); - - -/// Get error description string. -/// if _qerrno=-1, get_qerrno() will be used - -idaman THREAD_SAFE const char *ida_export qstrerror(error_t _qerrno); - - -/// A convenience function to generate error messages (returns "header: error message") - -idaman THREAD_SAFE char *ida_export get_errdesc(const char *header, error_t _qerrno=-1); - - -/// Get error message for MS Windows error codes - -idaman THREAD_SAFE char *ida_export winerr(int code); - - -/// errno or GetLastError() depending on the system. - -idaman THREAD_SAFE int ida_export qerrcode(int new_code=-1); - - -/// Get error string corresponding to qerrcode(). -/// if code == -1, then qerrcode() will be called. - -idaman const char *ida_export qerrstr(int code=-1); - - -#ifdef __cplusplus - -/// See vqperror() - -THREAD_SAFE AS_PRINTF(1, 2) inline void qperror(const char *format, ...) -{ - va_list va; - va_start(va, format); - vqperror(format, va); - va_end(va); -} - - -/// See set_qerrno() - -THREAD_SAFE inline void set_errno(int code) -{ - errno = code; - set_qerrno(eOS); -} -#endif - -// Internal functions -/// \cond - -// n=0..3 -idaman THREAD_SAFE void ida_export set_error_data(int n, size_t data); -idaman THREAD_SAFE void ida_export set_error_string(int n, const char *str); -idaman THREAD_SAFE size_t ida_export get_error_data(int n); -idaman THREAD_SAFE const char *ida_export get_error_string(int n); - -#define QPRM_TYPE(t,n,x) set_error_data(n-1, t(x)) -#define QPRM_CHAR(n,x) QPRM_TYPE(char,n,x) -#define QPRM_SHORT(n,x) QPRM_TYPE(short,n,x) -#define QPRM_INT(n,x) QPRM_TYPE(int,n,x) -#define QPRM_INT32(n,x) QPRM_TYPE(int32,n,x) -#define QPRM_UCHAR(n,x) QPRM_TYPE(uchar,n,x) -#define QPRM_USHORT(n,x) QPRM_TYPE(ushort,n,x) -#define QPRM_UINT(n,x) QPRM_TYPE(uint,n,x) -#define QPRM_UINT32(n,x) QPRM_TYPE(uint32,n,x) -#define QPRM(n,x) set_error_string(n-1, x) - -/// \endcond - -#endif - diff --git a/idasdk75/include/exehdr.h b/idasdk75/include/exehdr.h deleted file mode 100644 index 835e029..0000000 --- a/idasdk75/include/exehdr.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * EXE-file header layout - * - */ - -#ifndef __EXEHDR_H -#define __EXEHDR_H -#pragma pack(push, 1) - -struct exehdr -{ - uint16 exe_ident; -#define EXE_ID 0x5A4D // 'MZ' -#define EXE_ID2 0x4D5A // 'ZM' (DOS works with this also) - uint16 PartPag; - uint16 PageCnt; - uint16 ReloCnt; - uint16 HdrSize; - uint16 MinMem; - uint16 MaxMem; - uint16 ReloSS; - uint16 ExeSP; - uint16 ChkSum; - uint16 ExeIP; - uint16 ReloCS; - uint16 TablOff; - uint16 Overlay; -/* - uint16 res[4]; // Reserved words - uint16 oemid; // OEM identifier (for e_oeminfo) - uint16 oeminfo; // OEM information; e_oemid specific - uint16 res2[10]; // Reserved words - uint32 lfanew; // File address of new exe header -*/ - int32 CalcEXE_Length(void) - { - int32 len = PageCnt * 512L - HdrSize * 16; - if ( PartPag != 0 ) - len -= 512 - PartPag; - return len; - } - void CalcEXE_Pages(int32 len) - { - PartPag = uint16(len % 512); - PageCnt = uint16(len / 512); - if ( PartPag != 0 ) - PageCnt++; - } -}; - -struct exehdr_full: exehdr -{ - uint16 res[4]; // Reserved words - uint16 oemid; // OEM identifier (for e_oeminfo) - uint16 oeminfo; // OEM information; e_oemid specific - uint16 res2[10]; // Reserved words - uint32 lfanew; // File address of new exe header -}; - -#define PSPsize 0x100 -#define PE_PTROFF 0x3C -#pragma pack(pop) -#endif diff --git a/idasdk75/include/expr.hpp b/idasdk75/include/expr.hpp deleted file mode 100644 index 5d40ac4..0000000 --- a/idasdk75/include/expr.hpp +++ /dev/null @@ -1,1191 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _EXPR_H -#define _EXPR_H - -#include - -/*! \file expr.hpp - - \brief Functions that deal with C-like expressions and built-in IDC language. - - Functions marked #THREAD_SAFE may be called from any thread. - No simultaneous calls should be made for the same variable. - We protect only global structures, individual variables must - be protected manually. -*/ - -//------------------------------------------------------------------------ - -// Forward declarations -class idc_value_t; -class idc_class_t; -class idc_object_t; - -/// IDC script extension -#define IDC_LANG_EXT "idc" - -/// Convert IDC variable to a long (32/64bit) number. -/// \return v = 0 if impossible to convert to long - -idaman THREAD_SAFE error_t ida_export idcv_long(idc_value_t *v); - - -/// Convert IDC variable to a 64bit number. -/// \return v = 0 if impossible to convert to int64 - -idaman THREAD_SAFE error_t ida_export idcv_int64(idc_value_t *v); - - -/// Convert IDC variable to a long number. -/// \return -/// - v = 0 if IDC variable = "false" string -/// - v = 1 if IDC variable = "true" string -/// - v = number if IDC variable is number or string containing a number -/// - eTypeConflict if IDC variable = empty string - -idaman THREAD_SAFE error_t ida_export idcv_num(idc_value_t *v); - - -/// Convert IDC variable to a text string - -idaman THREAD_SAFE error_t ida_export idcv_string(idc_value_t *v); - - -/// Convert IDC variable to a floating point - -idaman THREAD_SAFE error_t ida_export idcv_float(idc_value_t *v); - - -/// Create an IDC object. The original value of 'v' is discarded (freed). -/// \param v variable to hold the object. any previous value will be cleaned -/// \param icls ptr to the desired class. NULL means "object" class -/// this ptr must be returned by add_idc_class() or find_idc_class() -/// \return always eOk - -idaman THREAD_SAFE error_t ida_export idcv_object( - idc_value_t *v, - const idc_class_t *icls=NULL); - - -/// Move 'src' to 'dst'. -/// This function is more effective than copy_idcv since it never copies big -/// amounts of data. - -idaman THREAD_SAFE error_t ida_export move_idcv( - idc_value_t *dst, - idc_value_t *src); - - -/// Copy 'src' to 'dst'. -/// For idc objects only a reference is copied. - -idaman THREAD_SAFE error_t ida_export copy_idcv( - idc_value_t *dst, - const idc_value_t &src); - - -/// Deep copy an IDC object. -/// This function performs deep copy of idc objects. -/// If 'src' is not an object, copy_idcv() will be called - -idaman THREAD_SAFE error_t ida_export deep_copy_idcv( - idc_value_t *dst, - const idc_value_t &src); - - -/// Free storage used by #VT_STR/#VT_OBJ IDC variables. -/// After this call the variable has a numeric value 0 - -idaman THREAD_SAFE void ida_export free_idcv(idc_value_t *v); - - -/// Swap 2 variables - -idaman THREAD_SAFE void ida_export swap_idcvs( - idc_value_t *v1, - idc_value_t *v2); - - -/// Retrieves the IDC object class name. -/// \param out qstring ptr for the class name. Can be NULL. -/// \param obj class instance variable -/// \return error code, eOk on success - -idaman THREAD_SAFE error_t ida_export get_idcv_class_name( - qstring *out, - const idc_value_t *obj); - - -/// Get an object attribute. -/// \param res buffer for the attribute value -/// \param obj variable that holds an object reference. -/// if obj is NULL it searches global variables, then user functions -/// \param attr attribute name -/// \param may_use_getattr may call getattr functions to calculate the attribute if it does not exist -/// \return error code, eOk on success - -idaman THREAD_SAFE error_t ida_export get_idcv_attr( - idc_value_t *res, - const idc_value_t *obj, - const char *attr, - bool may_use_getattr=false); - - -/// Set an object attribute. -/// \param obj variable that holds an object reference. -/// if obj is NULL then it tries to modify a global variable with the attribute name -/// \param attr attribute name -/// \param value new attribute value -/// \param may_use_setattr may call setattr functions for the class -/// \return error code, eOk on success - -idaman THREAD_SAFE error_t ida_export set_idcv_attr( - idc_value_t *obj, - const char *attr, - const idc_value_t &value, - bool may_use_setattr=false); - - -/// Delete an object attribute. -/// \param obj variable that holds an object reference -/// \param attr attribute name -/// \return error code, eOk on success - -idaman THREAD_SAFE error_t ida_export del_idcv_attr( - idc_value_t *obj, - const char *attr); - - -/// \name Enumerate object attributes -//@{ -idaman THREAD_SAFE const char *ida_export first_idcv_attr(const idc_value_t *obj); -idaman THREAD_SAFE const char *ida_export last_idcv_attr(const idc_value_t *obj); -idaman THREAD_SAFE const char *ida_export next_idcv_attr(const idc_value_t *obj, const char *attr); -idaman THREAD_SAFE const char *ida_export prev_idcv_attr(const idc_value_t *obj, const char *attr); -//@} - - -/// Get text representation of idc_value_t - -idaman bool ida_export print_idcv( - qstring *out, - const idc_value_t &v, - const char *name=NULL, - int indent=0); - - -/// Get slice. -/// \param res output variable that will contain the slice -/// \param v input variable (string or object) -/// \param i1 slice start index -/// \param i2 slice end index (excluded) -/// \param flags \ref VARSLICE_ or 0 -/// \returns eOk if success - -idaman THREAD_SAFE error_t ida_export get_idcv_slice( - idc_value_t *res, - const idc_value_t *v, - uval_t i1, - uval_t i2, - int flags=0); - -/// \defgroup VARSLICE_ IDC variable slice flags -/// Passed as 'flags' parameter to get_idcv_slice() and set_idcv_slice() -//@{ -#define VARSLICE_SINGLE 0x0001 ///< return single index (i2 is ignored) -//@} - -/// Set slice. -/// \param v variable to modify (string or object) -/// \param i1 slice start index -/// \param i2 slice end index (excluded) -/// \param in new value for the slice -/// \param flags \ref VARSLICE_ or 0 -/// \return eOk on success - -idaman THREAD_SAFE error_t ida_export set_idcv_slice( - idc_value_t *v, - uval_t i1, - uval_t i2, - const idc_value_t &in, - int flags=0); - - -//------------------------------------------------------------------------- -// IDC class related functions - -/// Create a new IDC class. -/// \param name name of the new class -/// \param super the base class for the new class. if the new class is not based -/// on any other class, pass NULL -/// \return pointer to the created class. If such a class already exists, a pointer -/// to it will be returned. -/// Pointers to other existing classes may be invalidated by this call. - -idaman THREAD_SAFE idc_class_t *ida_export add_idc_class( - const char *name, - const idc_class_t *super=NULL); - - -/// Find an existing IDC class by its name. -/// \param name name of the class -/// \return pointer to the class or NULL. -/// The returned pointer is valid until a new call to add_idc_class() - -idaman THREAD_SAFE idc_class_t *ida_export find_idc_class(const char *name); - - -/// Set an IDC class method. -/// \param icls pointer to the class -/// \param fullfuncname name of the function to call. use full method name: classname.funcname -/// \retval true success -/// \retval false the function could not be found - -idaman THREAD_SAFE bool ida_export set_idc_method(idc_class_t *icls, const char *fullfuncname); - - -/// \name Set user-defined functions to work with object attributes. -/// If the function name is NULL, the definitions are removed. -/// \return name of the old attribute function. NULL means error, "" means no previous attr func -//@{ -idaman THREAD_SAFE const char *ida_export set_idc_getattr(idc_class_t *icls, const char *fullfuncname); -idaman THREAD_SAFE const char *ida_export set_idc_setattr(idc_class_t *icls, const char *fullfuncname); -//@} - -/// Set a destructor for an idc class. -/// The destructor is called before deleting any object of the specified class. -/// Exceptions that escape the destructor are silently ignored, runtime errors too. - -idaman THREAD_SAFE const char *ida_export set_idc_dtor(idc_class_t *icls, const char *fullfuncname); - - -/// Dereference a #VT_REF variable. -/// \param v variable to dereference -/// \param vref_flags \ref VREF_ -/// \return pointer to the dereference result or NULL. -/// If returns NULL, qerrno is set to eExecBadRef "Illegal variable reference" - -idaman THREAD_SAFE idc_value_t *ida_export deref_idcv(idc_value_t *v, int vref_flags); - -/// \defgroup VREF_ Dereference IDC variable flags -/// Passed as 'vref_flags' parameter to deref_idcv() -//@{ -#define VREF_LOOP 0x0000 ///< dereference until we get a non #VT_REF -#define VREF_ONCE 0x0001 ///< dereference only once, do not loop -#define VREF_COPY 0x0002 ///< copy the result to the input var (v) -//@} - - -/// Create a variable reference. -/// Currently only references to global variables can be created. -/// \param ref ptr to the result -/// \param v variable to reference -/// \return success - -idaman THREAD_SAFE bool ida_export create_idcv_ref(idc_value_t *ref, const idc_value_t *v); - - -/// Add global IDC variable. -/// \param name name of the global variable -/// \return pointer to the created variable or existing variable. -/// NB: the returned pointer is valid until a new global var is added. - -idaman THREAD_SAFE idc_value_t *ida_export add_idc_gvar(const char *name); - - -/// Find an existing global IDC variable by its name. -/// \param name name of the global variable -/// \return pointer to the variable or NULL. -/// NB: the returned pointer is valid until a new global var is added. -/// FIXME: it is difficult to use this function in a thread safe manner - -idaman THREAD_SAFE idc_value_t *ida_export find_idc_gvar(const char *name); - - -//------------------------------------------------------------------------- -/// Class to hold idc values -class idc_value_t -{ -public: - char vtype; ///< \ref VT_ -/// \defgroup VT_ IDC value types -/// Used by idc_value_t::vtype -//@{ -#define VT_LONG 2 ///< Integer (see idc_value_t::num) -#define VT_FLOAT 3 ///< Floating point (see idc_value_t::e) -#define VT_WILD 4 ///< Function with arbitrary number of arguments. - ///< The actual number of arguments will be passed in idc_value_t::num. - ///< This value should not be used for ::idc_value_t. -#define VT_OBJ 5 ///< Object (see idc_value_t::obj) -#define VT_FUNC 6 ///< Function (see idc_value_t::funcidx) -#define VT_STR 7 ///< String (see qstr() and similar functions) -#define VT_PVOID 8 ///< void * -#define VT_INT64 9 ///< i64 -#define VT_REF 10 ///< Reference -//@} - -#ifndef SWIG - union - { -#endif //SWIG - sval_t num; ///< #VT_LONG - ushort e[6]; ///< #VT_FLOAT - idc_object_t *obj; - int funcidx; ///< #VT_FUNC - void *pvoid; ///< #VT_PVOID - int64 i64; ///< #VT_INT64 - uchar reserve[sizeof(qstring)]; ///< internal housekeeping: 64-bit qstring is bigger than 12 bytes -#ifndef SWIG - }; -#endif // SWIG - - /// Create a #VT_LONG value - idc_value_t(sval_t n=0) : vtype(VT_LONG), num(n) {} - /// Create a $VT_LONG with an existing idc value - idc_value_t(const idc_value_t &r) : vtype(VT_LONG) { copy_idcv(this, r); } - /// Create a #VT_STR value - idc_value_t(const char *_str) : vtype(VT_STR) { new(&qstr()) qstring(_str); } - /// Create a #VT_STR value - idc_value_t(const qstring &_str) : vtype(VT_STR) { new(&qstr()) qstring(_str); } - /// Destructor - ~idc_value_t(void) { clear(); } - /// See free_idcv() - void clear(void) { free_idcv(this); } // put num 0 - /// Assign this value to an existing value - idc_value_t &operator = (const idc_value_t &r) - { - copy_idcv(this, r); - return *this; - } - qstring &qstr(void) { return *(qstring *)# } ///< #VT_STR - const qstring &qstr(void) const { return *(qstring *)# } ///< #VT_STR - const char *c_str(void) const { return qstr().c_str(); } ///< #VT_STR - const uchar *u_str(void) const { return (const uchar *)c_str(); } ///< #VT_STR - void swap(idc_value_t &v) { swap_idcvs(this, &v); } ///< Set this = r and v = this - bool is_zero(void) const { return vtype == VT_LONG && num == 0; } ///< Does value represent the integer 0? - bool is_integral(void) { return vtype == VT_LONG || vtype == VT_INT64; } ///< Does value represent a whole number? - /// Convertible types are #VT_LONG, #VT_FLOAT, #VT_INT64, and #VT_STR - bool is_convertible(void) const { return (vtype >= 1 && vtype <= VT_FLOAT) || vtype == VT_STR || vtype == VT_INT64; } - - /// \name Warning - /// The following functions do not free the existing data! - /// When the contents are unknown, use the functions without a leading underscore. - //@{ - void _create_empty_string(void) { vtype = VT_STR; new (&qstr()) qstring; } - void _set_string(const qstring &_str) - { - vtype = VT_STR; - new (&qstr()) qstring(_str); - } - void _set_string(const char *_str, size_t len) - { - vtype = VT_STR; - new (&qstr()) qstring(_str, len); - } - void _set_string(const char *_str) - { - size_t len = _str == NULL ? 0 : strlen(_str); - _set_string(_str, len); - } - void _set_long(sval_t v) { vtype = VT_LONG; num = v; } - void _set_pvoid(void *p) { vtype = VT_PVOID; pvoid = p; } - void _set_int64(int64 v) { vtype = VT_INT64; i64 = v; } - void _set_float(const ushort f[6]) { vtype = VT_FLOAT; memcpy(e, f, sizeof(e)); } - //@} - - /// \name Setters - /// These functions ensure the previous value is cleared - //@{ - void create_empty_string(void) { clear(); _create_empty_string(); } - void set_string(const char *_str, size_t len) { clear(); _set_string(_str, len); } - void set_string(const char *_str) { clear(); _set_string(_str); } - void set_string(const qstring &_str) { clear(); _set_string(_str); } - void set_long(sval_t v) { clear(); _set_long(v); } - void set_pvoid(void *p) { clear(); vtype = VT_PVOID; pvoid = p; } - void set_int64(int64 v) { clear(); vtype = VT_INT64; i64 = v; } - void set_float(const ushort f[6]) { clear(); vtype = VT_FLOAT; memcpy(e, f, sizeof(e)); } - //@} -}; - -/// Global idc variable -struct idc_global_t -{ - qstring name; - idc_value_t value; - idc_global_t(void) {} - idc_global_t(const char *n) : name(n) {} -}; -typedef qvector idc_vars_t; ///< vector of global idc variables - -/// Prototype of an external IDC function (implemented in C). -/// \param argv vector of input arguments. IDA will convert all arguments -/// to types specified by ext_idcfunc_t::args, except for #VT_WILD -/// \param r return value of the function or exception -/// \return 0 if ok, all other values indicate error. -/// the error code must be set with set_qerrno(): -/// - #eExecThrow - a new exception has been generated, see 'r' -/// - other values - runtime error has occurred - -typedef error_t idaapi idc_func_t(idc_value_t *argv, idc_value_t *r); - -#define eExecThrow 90 ///< See return value of ::idc_func_t - -/// Element of functions table. See idcfuncs_t::funcs -struct ext_idcfunc_t -{ - const char *name; ///< Name of function - idc_func_t *fptr; ///< Pointer to the Function - const char *args; ///< Type of arguments. Terminated with 0. - ///< #VT_WILD at the end means a variadic function. - ///< Actual number of arguments will be passed - ///< in res->num in this case. - const idc_value_t *defvals; ///< Default argument values. - ///< Only the rightmost arguments may have - ///< default values. - int ndefvals; ///< Number of default values. - int flags; ///< \ref EXTFUN_ -/// \defgroup EXTFUN_ Function description flags -/// Used by ext_idcfunc_t::flags -//@{ -#define EXTFUN_BASE 0x0001 ///< requires open database. -#define EXTFUN_NORET 0x0002 ///< does not return. the interpreter may - ///< clean up its state before calling it. -#define EXTFUN_SAFE 0x0004 ///< thread safe function. may be called - ///< from any thread. -//@} -}; - -/// Describes an array of IDC functions -struct idcfuncs_t -{ - size_t qnty; ///< Number of functions - ext_idcfunc_t *funcs; ///< Function table - - /// \name IDC Engine - /// IDC engine requires the following functions (all of them may be NULL) - //@{ - - /// Start IDC engine. Called before executing any IDC code. - error_t (idaapi *startup)(void); - - /// Stop IDC engine. Called when all IDC engines finish. - /// In other words, nested IDC engines do not call startup/shutdown. - error_t (idaapi *shutdown)(void); - - /// Initialize IDC engine. Called once at the very beginning of work. - /// This callback may create additional IDC classes, methods, etc. - void (idaapi *init_idc)(void); - - /// Terminate IDC engine. Called once at the very end of work. - void (idaapi *term_idc)(void); - - /// Is the database open? (used for #EXTFUN_BASE functions). - /// if this pointer is NULL, #EXTFUN_BASE is not checked. - bool (idaapi *is_database_open)(void); - - /// Convert an address to a string. - /// if this pointer is NULL, '%a' will be used. - size_t (idaapi *ea2str)(char *buf, size_t bufsize, ea_t ea); - - /// Should a variable name be accepted without declaration?. - /// When the parser encounters an unrecognized variable, this callback is called. - /// If it returns false, the parser generates the 'undefined variable' error - /// else the parser generates code to call to a set or get function, - /// depending on the current context. - /// If this pointer is NULL, undeclared variables won't be supported. - /// However, if 'resolver' object is provided to the parser, it will be used - /// to resolve such names to constants at the compilation time. - /// This callback is used by IDA to handle processor register names. - bool (idaapi *undeclared_variable_ok)(const char *name); - - //@} - - /// \name Indexes - /// Indexes into the 'f' array. non-positive values mean that the function does not exist - //@{ - - /// Retrieve value of an undeclared variable. - /// Expected prototype: get(#VT_STR varname) - int get_unkvar; - - /// Store a value to an undeclared variable. - /// Expected prototype: set(#VT_WILD new_value, #VT_STR varname) - int set_unkvar; - - /// Execute resolved function. - /// If 'resolver' was used to resolve an unknown name to a constant in a function - /// call context, such a call will be redirected here. - /// Expected prototype: exec_resolved_func(#VT_LONG func, #VT_WILD typeinfo, ...) - /// This callback is used in IDA for Appcall. - int exec_resolved_func; - - /// Calculate sizeof(type). - /// This function is used by the interpreter to calculate sizeof() expressions. - /// Please note that the 'type' argument is an IDC object of typeinfo class. - /// Expected prototype: calc_sizeof(#VT_OBJ typeinfo) - /// This callback requires support of the type system (available only in IDA kernel) - /// It should not be used by standalone IDC interpreters. - int calc_sizeof; - - /// Get address of the specified field using the type information from the idb. - /// This function is used to resolve expressions like 'mystr.field' where - /// mystr does not represent an IDC object but just a plain number. - /// The number is interpreted as an address in the current idb. - /// This function retrieves type information at this address and tried to find - /// the specified 'field'. It returns the address of the 'field' in the idb. - /// This callback should not be used by standalone IDC interpreters. - int get_field_ea; - - //@} -}; - -// Our idc_value_t and idc_global_t classes are freely movable with memcpy() -DECLARE_TYPE_AS_MOVABLE(idc_value_t); -DECLARE_TYPE_AS_MOVABLE(idc_global_t); - -//------------------------------------------------------------------------ -/// Add an IDC function. -/// This function does not modify the predefined kernel functions. -/// Example: -/// \code -/// static error_t idaapi myfunc5(idc_value_t *argv, idc_value_t *res) -/// { -/// msg("myfunc is called with arg0=%a and arg1=%s\n", argv[0].num, argv[1].str); -/// res->num = 5; // let's return 5 -/// return eOk; -/// } -/// static const char myfunc5_args[] = { VT_LONG, VT_STR, 0 }; -/// static const ext_idcfunc_t myfunc_desc = { "MyFunc5", myfunc5, myfunc5_args, NULL, 0, EXTFUN_BASE }; -/// -/// // after this: -/// add_idc_func(myfunc_desc); -/// -/// // there is a new IDC function which can be called like this: -/// MyFunc5(0x123, "test"); -/// -/// \endcode -/// \param func function description block. -/// \note If the function already exists, it will be replaced by the new function -/// \return success - -idaman THREAD_SAFE bool ida_export add_idc_func(const ext_idcfunc_t &func); - - -/// Delete an IDC function -/// -idaman THREAD_SAFE bool ida_export del_idc_func(const char *name); - - -// Find an idc function that starts with the given prefix. -// \param out buffer for the output name -// \param prefix prefix to search for -// \param n how many matches to skip -// Returns: success -idaman THREAD_SAFE bool ida_export find_idc_func( - qstring *out, - const char *prefix, - int n=0); - - -/// Possible syntax element highlighting style names -enum syntax_highlight_style -{ - HF_DEFAULT = 0, - HF_KEYWORD1 = 1, - HF_KEYWORD2 = 2, - HF_KEYWORD3 = 3, - HF_STRING = 4, - HF_COMMENT = 5, - HF_PREPROC = 6, - HF_NUMBER = 7, - - HF_MAX, -}; -#define HF_FIRST HF_KEYWORD1 - -struct highlighter_cbs_t -{ - virtual ~highlighter_cbs_t() {} - virtual void idaapi set_style(int32 /*start*/, int32 /*len*/, syntax_highlight_style /*style*/) {} - virtual int32 idaapi prev_block_state() { return 0; } - virtual int32 idaapi cur_block_state() { return 0; } - virtual void idaapi set_block_state(int32 /*state*/) {} -}; - -/// Base class for syntax highligters -struct syntax_highlighter_t -{ - /// Function for extlang syntax highlighting - /// \param context implementation specific context. can be NULL - /// \param ighlighter_cbs structure with set of callbacks - /// \param text part of text to colorize - typedef void idaapi block_highlighter_t( - void *context, - highlighter_cbs_t *highlighter_cbs, - const qstring &text); - syntax_highlighter_t(block_highlighter_t *bh=nullptr) : highlight_block(bh) {} - virtual ~syntax_highlighter_t() {} - block_highlighter_t *highlight_block; -}; - - -//------------------------------------------------------------------------ -/// External language (to support third party language interpreters) -struct extlang_t -{ - size_t size; ///< Size of this structure - uint32 flags; ///< Language features -#define EXTLANG_IDC 0x01 -#define EXTLANG_NS_AWARE 0x02 ///< Namespace-aware (see above.) - int32 refcnt; ///< Reference count - const char *name; ///< Language name - const char *fileext; ///< File name extension for the language - syntax_highlighter_t *highlighter; // Language syntax highlighter - - /// Compile an expression. - /// \param name name of the function which will - /// hold the compiled expression - /// \param current_ea current address. if unknown then #BADADDR - /// \param expr expression to compile - /// \param[out] errbuf error message if compilation fails - /// \return success - bool (idaapi *compile_expr)( - const char *name, - ea_t current_ea, - const char *expr, - qstring *errbuf); - - /// Compile (load) a file. - /// - /// If an extlang_t object claims to be namespace-aware, it means its - /// 'compile_file()' will have to create namespaces for _certain_ paths: - /// - plugins, - /// - loaders. - /// - /// For example, if compile_file() receives a hypothetical path: - /// .../loaders/myloader.py, - /// the namespace-aware extlang_t handling 'py' files will have to create - /// a namespace derived from the loader file name (without its extension), - /// i.e., '__loaders__myloader', into which the file will be compiled. - /// - /// Then, call_func() has to be prepared to receive a function name that - /// is namespace-qualified: "__loaders__myloader.accept_file()". - /// - /// compile_file() must handle the following 'special' paths, and create - /// the following namespaces to compile them into: - /// .../loaders/ => '__loaders__' - /// .../plugins/ => '__plugins__' - /// - /// Similarly, a namespace-aware extlang_t's load_procmod() - /// will have to load the processor module in its own namespace: - /// .../procs/ => '__procs__' - /// - /// \param file file name - /// \param[out] errbuf error message if compilation fails - bool (idaapi *compile_file)(const char *file, qstring *errbuf); - - /// Evaluate a previously compiled expression. - /// \param[out] result function result or exception - /// \param name function to call - /// \param nargs number of input arguments - /// \param args input arguments - /// \param[out] errbuf error message if evaluation fails - /// \return success - bool (idaapi *call_func)( - idc_value_t *result, - const char *name, - const idc_value_t args[], - size_t nargs, - qstring *errbuf); - - /// Compile and evaluate an expression. - /// \param[out] rv expression value or exception - /// \param current_ea current address. if unknown then BADADDR - /// \param expr expression to evaluate - /// \param[out] errbuf error message if evaluation fails - /// \return success - bool (idaapi *eval_expr)( - idc_value_t *rv, - ea_t current_ea, - const char *expr, - qstring *errbuf); - - /// Compile and execute a string with statements. - /// (see also: eval_expr() which works with expressions) - /// \param str input string to execute - /// \param[out] errbuf error message - /// \return success - bool (idaapi *eval_snippet)( - const char *str, - qstring *errbuf); - - /// Create an object instance. - /// \param result created object or exception - /// \param name object class name - /// \param args input arguments - /// \param nargs number of input arguments - /// \param errbuf error message if evaluation fails - /// \return success - bool (idaapi *create_object)( - idc_value_t *result, - const char *name, - const idc_value_t args[], - size_t nargs, - qstring *errbuf); - - /// Returns the attribute value of a given object from the global scope. - /// \param[out] result attribute value - /// \param obj object (may be NULL) - /// \param attr attribute name. - /// if NULL or empty string then the object instance name - /// (i.e. class name) should be returned. - /// \return success - bool (idaapi *get_attr)( - idc_value_t *result, - const idc_value_t *obj, - const char *attr); - - /// Sets the attribute value of a given object in the global scope. - /// \param obj object (may be NULL) - /// \param attr attribute name - /// \param value attribute value - /// \return success - bool (idaapi *set_attr)( - idc_value_t *obj, - const char *attr, - const idc_value_t &value); - - /// Calls a member function. - /// \param[out] result function result or exception - /// \param obj object instance - /// \param name method name to call - /// \param args input arguments - /// \param nargs number of input arguments - /// \param[out] errbuf error message if evaluation fails - /// \return success - bool (idaapi *call_method)( - idc_value_t *result, - const idc_value_t *obj, - const char *name, - const idc_value_t args[], - size_t nargs, - qstring *errbuf); - - /// Compile (load) a file with processor module. - /// - /// See the note about namespace-awareness in compile_file() - /// - /// \param[out] procobj created object or exception - /// \param path processor module file name - /// \param[out] errbuf error message if compilation fails - /// \retval true success - /// \retval false if errbuf is empty then file has been - /// loaded (compiled) successfully but - /// it doesn't contain processor module - bool (idaapi *load_procmod)( - idc_value_t *procobj, - const char *path, - qstring *errbuf); - - /// Unload previously loaded processor module. - /// \param path processor module file name - /// \param[out] errbuff error message if compilation fails - /// \return success - bool (idaapi *unload_procmod)( - const char *path, - qstring *errbuf); - - bool is_idc(void) const { return (flags & EXTLANG_IDC) != 0; } - bool is_namespace_aware(void) const { return (flags & EXTLANG_NS_AWARE) != 0; } - void release(void) {} -}; - -typedef qvector extlangs_t; ///< vector of external language descriptions -typedef qrefcnt_t extlang_object_t; - -/// Get current active external language. - -idaman void *ida_export get_current_extlang(void); // do not use - -inline const extlang_object_t get_extlang(void) // use this function -{ - return extlang_object_t((extlang_t *)get_current_extlang()); -} - - -/// Install an external language interpreter. -/// Any previously registered interpreter will be automatically unregistered. -/// The installed extlang can be used in select_extlang(). -/// \param el description of the new language. must point to static storage. -/// \return extlang id; -1 means failure and will happen if the extlang has -/// already been installed - -idaman ssize_t ida_export install_extlang(extlang_t *el); - - -/// Uninstall an external language interpreter. -/// \return success - -idaman bool ida_export remove_extlang(extlang_t *el); - - -/// Selects the external language interpreter. -/// The specified extlang must be registered before selecting it. -/// It will be used to evaluate expressions entered in dialog boxes. -/// It will also replace the eval_expr() and eval_expr_long() functions. -/// \return success - -idaman bool ida_export select_extlang(extlang_t *el); - - -struct extlang_visitor_t -{ - virtual ssize_t idaapi visit_extlang(extlang_t *extlang) = 0; -}; - -/// Process all registered extlangs -// \param ev visitor object -// \param select temporarily select extlang for the duration of the visit -// \return 0 or the first non-zero value returned by visit_extlang() - -idaman ssize_t ida_export for_all_extlangs(extlang_visitor_t &ev, bool select=false); - - -// Helper function to search for extlang -enum find_extlang_kind_t -{ - FIND_EXTLANG_BY_EXT, - FIND_EXTLANG_BY_NAME, - FIND_EXTLANG_BY_IDX, -}; - -// do not use -idaman void *ida_export find_extlang(const void *str, find_extlang_kind_t kind); - - -/// Get the extlang that can handle the given file extension - -inline extlang_object_t find_extlang_by_ext(const char *ext) -{ - return extlang_object_t((extlang_t *)find_extlang(ext, FIND_EXTLANG_BY_EXT)); -} - -/// Find an extlang by name - -inline extlang_object_t find_extlang_by_name(const char *name) -{ - return extlang_object_t((extlang_t *)find_extlang(name, FIND_EXTLANG_BY_NAME)); -} - -/// Find an extlang by index - -inline extlang_object_t find_extlang_by_index(size_t idx) -{ - return extlang_object_t((extlang_t *)find_extlang(&idx, FIND_EXTLANG_BY_IDX)); -} - - - -//------------------------------------------------------------------------ -/// Set or append a header path. -/// IDA looks for the include files in the appended header paths, -/// then in the ida executable directory. -/// \param path list of directories to add (separated by ';') -/// may be NULL, in this case nothing is added -/// \param add true: append. -/// false: remove old paths. -/// \retval true success -/// \retval false no memory - -idaman THREAD_SAFE bool ida_export set_header_path(const char *path, bool add); - - -/// Get full name of IDC file name. -/// Search for file in list of include directories, IDCPATH directory -/// and the current directory. -/// \param buf buffer for the answer -/// \param bufsize size of buffer -/// \param file file name without full path -/// \return NULL is file not found. -/// otherwise returns pointer to buf - -idaman THREAD_SAFE char *ida_export get_idc_filename( - char *buf, - size_t bufsize, - const char *file); - - -/// Compile and execute "main" function from system file. -/// \param file file name with IDC function(s). -/// The file will be searched in the idc subdir of ida -/// \param complain_if_no_file -/// - 1: display warning if the file is not found -/// - 0: don't complain if file doesn't exist -/// \retval 1 ok, file is compiled and executed -/// \retval 0 failure, compilation or execution error, warning is displayed - -idaman THREAD_SAFE bool ida_export exec_system_script( - const char *file, - bool complain_if_no_file=true); - - -/// Compile and calculate an expression. -/// \param res pointer to result. The result will be converted -/// to 32/64bit number. Use eval_expr() if you -/// need the result of another type. -/// \param where the current linear address in the addressing space of the -/// program being disassembled. it will be used to resolve -/// names of local variables, etc. -/// if not applicable, then should be #BADADDR -/// \param line a text line with IDC expression -/// \param[out] errbuf buffer for the error message -/// \retval true ok -/// \retval false error, see errbuf - -idaman bool ida_export eval_expr_long( - sval_t *res, - ea_t where, - const char *line, - qstring *errbuf=NULL); - -/// See eval_expr_long() - -inline bool idaapi eval_expr_long( - uval_t *res, - ea_t where, - const char *line, - qstring *errbuf=NULL) -{ - return eval_expr_long((sval_t *)res, where, line, errbuf); -} - - -/// Compile and calculate an expression. -/// \param rv pointer to the result -/// \param where the current linear address in the addressing space of the -/// program being disassembled. If will be used to resolve -/// names of local variables etc. -/// if not applicable, then should be #BADADDR. -/// \param line the expression to evaluate -/// \param[out] errbuf buffer for the error message -/// \retval true ok -/// \retval false error, see errbuf - -idaman bool ida_export eval_expr( - idc_value_t *rv, - ea_t where, - const char *line, - qstring *errbuf=NULL); - - -/// Same as eval_expr(), but will always use the IDC interpreter regardless of the -/// currently installed extlang. - -idaman bool ida_export eval_idc_expr( - idc_value_t *rv, - ea_t where, - const char *buf, - qstring *errbuf=NULL); - - -/// Compile a text file with IDC function(s). -/// \param file name of file to compile -/// if NULL, then "File not found" is returned. -/// \param[out] errbuf buffer for the error message -/// \param cpl_flags \ref CPL_ or 0 -/// \retval true ok -/// \retval false error, see errbuf - -/// \defgroup CPL_ Flags for compile_idc_file() -//@{ -#define CPL_DEL_MACROS 0x0001 ///< delete macros at the end of compilation -#define CPL_USE_LABELS 0x0002 ///< allow program labels in the script -#define CPL_ONLY_SAFE 0x0004 ///< allow calls of only thread-safe functions -//@} - -idaman THREAD_SAFE bool ida_export compile_idc_file( - const char *file, - qstring *errbuf=NULL, - int cpl_flags = CPL_DEL_MACROS|CPL_USE_LABELS); - - -/// Compile text with IDC function(s). -/// \param line line with IDC function(s) (can't be NULL!) -/// \param[out] errbuf buffer for the error message -/// \param resolver callback object to get values of undefined variables -/// This object will be called if IDC function contains -/// references to undefined variables. May be NULL. -/// \param only_safe_funcs if true, any calls to functions without #EXTFUN_SAFE flag -/// will lead to a compilation error. -/// \retval true ok -/// \retval false error, see errbuf - -struct idc_resolver_t -{ - virtual uval_t idaapi resolve_name(const char *name) = 0; -}; - -idaman THREAD_SAFE bool ida_export compile_idc_text( - const char *line, - qstring *errbuf=NULL, - idc_resolver_t *resolver=NULL, - bool only_safe_funcs=false); - - -/// Compile text with IDC statements. -/// \param func name of the function to create out of the snippet -/// \param text text to compile -/// \param[out] errbuf buffer for the error message -/// \param resolver callback object to get values of undefined variables -/// This object will be called if IDC function contains -/// references to undefined variables. May be NULL. -/// \param only_safe_funcs if true, any calls to functions without #EXTFUN_SAFE flag -/// will lead to a compilation error. -/// \retval true ok -/// \retval false error, see errbuf - -idaman bool ida_export compile_idc_snippet( - const char *func, - const char *text, - qstring *errbuf=NULL, - idc_resolver_t *resolver=NULL, - bool only_safe_funcs=false); - - -// Execution of IDC code can generate exceptions. Exception objects -// will have the following attributes: -// file - the source file name -// line - the line number that was executing when the exception occurred -// func - the function name -// pc - bytecode program counter -// For runtime errors, the following additional attributes exist: -// qerrno - runtime error code -// description - text description of the runtime error - -/// Execute an IDC function. -/// \param[out] result pointer to idc_value_t to hold the return value of the function. -/// If execution fails, this variable will contain -/// the exception information. -/// Can be NULL if return value is not required. -/// \param fname function name. User-defined functions, built-in functions, -/// and plugin-defined functions are accepted. -/// \param args array of parameters -/// \param argsnum number of parameters to pass to 'fname'. -/// This number should be equal to number of parameters -/// the function expects. -/// \param[out] errbuf buffer for the error message -/// \param resolver callback object to get values of undefined variables -/// This object will be called if IDC function contains -/// references to undefined variables. May be NULL. -/// \retval true ok -/// \retval false error, see errbuf - -idaman bool ida_export call_idc_func( - idc_value_t *result, - const char *fname, - const idc_value_t args[], - size_t argsnum, - qstring *errbuf=NULL, - idc_resolver_t *resolver=NULL); - - -/// Compile and execute IDC function(s) from file. -/// \param result ptr to idc_value_t to hold result of the function. -/// If execution fails, this variable will contain -/// the exception information. -/// You may pass NULL if you are not interested in the returned -/// value. -/// \param path text file containing text of IDC functions -/// \param func function name to execute -/// \param args array of parameters -/// \param argsnum number of parameters to pass to 'fname' -/// This number should be equal to number of parameters -/// the function expects. -/// \param[out] errbuf buffer for the error message -/// \retval true ok -/// \retval false error, see errbuf - -THREAD_SAFE inline bool exec_idc_script( - idc_value_t *result, - const char *path, - const char *func, - const idc_value_t args[], - size_t argsnum, - qstring *errbuf=NULL) -{ - if ( !compile_idc_file(path, errbuf) ) - return false; - return call_idc_func(result, func, args, argsnum, errbuf); -} - - -/// Compile and execute IDC statements or expressions. -/// \param result ptr to idc_value_t to hold result of the function. -/// If execution fails, this variable will contain -/// the exception information. -/// You may pass NULL if you are not interested in the returned -/// value. -/// \param line body of IDC the function -/// \param[out] errbuf buffer for the error message -/// \param resolver callback object to get values of undefined variables -/// This object will be called if IDC function contains -/// references to undefined variables. May be NULL. -/// \return success -/// \note see also eval_idc_expr() - - -idaman bool ida_export eval_idc_snippet( - idc_value_t *result, - const char *line, - qstring *errbuf=NULL, - idc_resolver_t *resolver=NULL); - - -//------------------------------------------------------------------------ -/// Setup lowcnd callbacks to read/write registers. -/// These callbacks will be used by the idc engine to read/write registers -/// while calculating low level breakpoint conditions for local debuggers. - -idaman void ida_export setup_lowcnd_regfuncs(idc_func_t *getreg, idc_func_t *setreg); - -//------------------------------------------------------------------------ -/// Extract type & data from the idc_value_t instance that -/// was passed to parse_config_value(). -/// -/// \param vtype pointer to storage that will hold the type (\ref IDPOPT_T) -/// \param vdata pointer to storage that contains the value (see \ref IDPOPT_T -/// for what type of data is pointed to.) -/// \param v the value holder -/// \return true in case of success, false if 'v' is of unexpected type -inline THREAD_SAFE bool get_idptype_and_data(int *vtype, const void **vdata, const idc_value_t &v) -{ - switch ( v.vtype ) - { - case VT_STR: *vtype = IDPOPT_STR, *vdata = v.c_str(); break; - case VT_LONG: *vtype = IDPOPT_NUM; *vdata = &v.num; break; - case VT_WILD: *vtype = IDPOPT_BIT; *vdata = &v.num; break; - case VT_INT64: *vtype = IDPOPT_I64; *vdata = &v.i64; break; - case VT_PVOID: *vtype = IDPOPT_CST; *vdata = v.pvoid; break; - default: return false; - } - return true; -} - -/// Create an idc execution exception object. -/// This helper function can be used to return an exception from C++ code to IDC. -/// In other words this function can be called from idc_func_t() callbacks. -/// Sample usage: if ( !ok ) return throw_idc_exception(r, "detailed error msg"); -/// \param r object to hold the exception object -/// \param desc exception description -/// \return eExecThrow - -idaman error_t ida_export throw_idc_exception(idc_value_t *r, const char *desc); - - -#endif /* _EXPR_H */ diff --git a/idasdk75/include/fixup.hpp b/idasdk75/include/fixup.hpp deleted file mode 100644 index 6519f0a..0000000 --- a/idasdk75/include/fixup.hpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef FIXUP_HPP -#define FIXUP_HPP - -#include -#include - -/*! \file fixup.hpp - - \brief Functions that deal with fixup information - - A loader should setup fixup information using set_fixup(). -*/ - -//-------------------------------------------------------------------------- -/// Fixup information structure - -typedef uint16 fixup_type_t; ///< see \ref fixup_type_t -/// \defgroup fixup_type_t Types of fixups -/// Fixup may be of standard or custom type. Standard types fall into -/// range 1..FIXUP_CUSTOM-1 and custom types fall into range -/// FIXUP_CUSTOM..MAX_UINT16. -/// \note Fixup type 0 is unused. -/// \name Fixup standard types -//@{ -#define FIXUP_OFF8 13 ///< 8-bit offset -#define FIXUP_OFF16 1 ///< 16-bit offset -#define FIXUP_SEG16 2 ///< 16-bit base--logical segment base (selector) -#define FIXUP_PTR16 3 ///< 32-bit long pointer (16-bit base:16-bit - ///< offset) -#define FIXUP_OFF32 4 ///< 32-bit offset -#define FIXUP_PTR32 5 ///< 48-bit pointer (16-bit base:32-bit offset) -#define FIXUP_HI8 6 ///< high 8 bits of 16bit offset -#define FIXUP_HI16 7 ///< high 16 bits of 32bit offset -#define FIXUP_LOW8 8 ///< low 8 bits of 16bit offset -#define FIXUP_LOW16 9 ///< low 16 bits of 32bit offset -#define V695_FIXUP_VHIGH 10 ///< obsolete -#define V695_FIXUP_VLOW 11 ///< obsolete -#define FIXUP_OFF64 12 ///< 64-bit offset -//#define FIXUP_ 0xE -#define FIXUP_CUSTOM 0x8000 ///< start of the custom types range -//@} - -/// Is fixup processed by processor module? -inline THREAD_SAFE bool is_fixup_custom(fixup_type_t type) -{ - return (type & FIXUP_CUSTOM) != 0; -} - -/// \defgroup FIXUPF_ Fixup flags -/// Used by fixup_data_t -//@{ -/// fixup is relative to the linear address `base'. Otherwise fixup is -/// relative to the start of the segment with `sel' selector. -#define FIXUPF_REL 0x0001 -/// target is a location (otherwise - segment). -/// Use this bit if the target is a symbol rather than an offset from the -/// beginning of a segment. -#define FIXUPF_EXTDEF 0x0002 -/// fixup is ignored by IDA -/// - disallows the kernel to convert operands -/// - this fixup is not used during output -#define FIXUPF_UNUSED 0x0004 -/// fixup was not present in the input file -#define FIXUPF_CREATED 0x0008 -/// additional flags. The bits from this mask are not stored in the database -/// and can be used by the loader at its discretion. -#define FIXUPF_LOADER_MASK 0xF0000000 -//@} - -struct fixup_handler_t; -struct fixup_data_t -{ -protected: - fixup_type_t type; // fixup type - uint32 flags; // FIXUPF_... bits - uval_t base; // base for relative fixups - -public: - sel_t sel; ///< selector of the target segment. - ///< BADSEL means an absolute (zero based) target. - ///< \sa FIXUPF_REL - - ea_t off; ///< target offset - ///< \note The target is calculated as - ///< `get_base() + off`. - - adiff_t displacement; ///< displacement (offset from the target) - -public: - fixup_data_t() - : type(0), - flags(0), - base(0), - sel(BADSEL), - off(0), - displacement(0) {} - fixup_data_t(fixup_type_t type_, uint32 flags_ = 0) - : type(type_), - flags(flags_), - base(0), - sel(BADSEL), - off(0), - displacement(0) {} - - /// Fixup type \ref fixup_type_t - fixup_type_t get_type(void) const { return type; } - void set_type(fixup_type_t type_) { type = type_; } - void set_type_and_flags(fixup_type_t type_, uint32 flags_ = 0) - { - type = type_; - flags = flags_; - } - - bool is_custom(void) const; ///< \ref is_fixup_custom() - - /// Fixup flags \ref FIXUPF_ - uint32 get_flags() const { return flags; } - - bool is_extdef(void) const { return (flags & FIXUPF_EXTDEF) != 0; } - void set_extdef(void) { flags |= FIXUPF_EXTDEF; } - void clr_extdef(void) { flags &= ~FIXUPF_EXTDEF; } - - bool is_unused(void) const { return (flags & FIXUPF_UNUSED) != 0; } - void set_unused(void) { flags |= FIXUPF_UNUSED; } - void clr_unused(void) { flags &= ~FIXUPF_UNUSED; } - - /// Is fixup relative? - bool has_base(void) const { return (flags & FIXUPF_REL) != 0; } - - /// Is fixup artificial? - bool was_created(void) const { return (flags & FIXUPF_CREATED) != 0; } - - /// Get base of fixup. - /// \note The target is calculated as `get_base() + off`. - /// \sa FIXUPF_REL - ea_t get_base() const - { - return has_base() ? base : sel != BADSEL ? sel2ea(sel) : 0; - } - - /// Set base of fixup. - /// The target should be set before a call of this function. - void set_base(ea_t new_base) - { - ea_t target = get_base() + off; - flags |= FIXUPF_REL; - base = new_base; - off = target - base; - } - - void set_sel(const segment_t *seg) - { - sel = seg == NULL ? BADSEL : seg->sel; - } - - /// Set selector of fixup to the target. - /// The target should be set before a call of this function. - void set_target_sel() - { - ea_t target = get_base() + off; - set_sel(getseg(target)); - flags &= ~FIXUPF_REL; - base = 0; // just in case - off = target - get_base(); - } - - void set(ea_t source) const; ///< \ref set_fixup() - bool get(ea_t source); ///< \ref get_fixup() - - /// \ref get_fixup_handler() - const fixup_handler_t *get_handler() const; - - /// \ref get_fixup_desc() - const char *get_desc(qstring *buf, ea_t source) const; - - // TODO rewrite to the inline implementation which uses - // fixup_handler_t::size - int calc_size() const; ///< \ref calc_fixup_size() - uval_t get_value(ea_t ea) const; ///< \ref get_fixup_value() - bool patch_value(ea_t ea) const; ///< \ref patch_fixup_value() - -}; - -/// Get fixup information - -idaman bool ida_export get_fixup(fixup_data_t *fd, ea_t source); - - -/// Check that a fixup exists at the given address - -inline bool exists_fixup(ea_t source) -{ - return get_fixup(NULL, source); -} - - -/// Set fixup information. You should fill ::fixup_data_t and call this -/// function and the kernel will remember information in the database. -/// \param source the fixup source address, i.e. the address modified by -/// the fixup -/// \param fd fixup data - -idaman void ida_export set_fixup(ea_t source, const fixup_data_t &fd); - - -/// Delete fixup information - -idaman void ida_export del_fixup(ea_t source); - - -/// \name Enumerate addresses with fixup information: -//@{ -/// Get the first address with fixup information -/// -/// \return the first address with fixup information, or BADADDR -idaman ea_t ida_export get_first_fixup_ea(void); - -/// Find next address with fixup information -/// -/// \param ea current address -/// \return the next address with fixup information, or BADADDR -idaman ea_t ida_export get_next_fixup_ea(ea_t ea); - -/// Find previous address with fixup information -/// -/// \param ea current address -/// \return the previous address with fixup information, or BADADDR -idaman ea_t ida_export get_prev_fixup_ea(ea_t ea); -//@} - - -/// Get handler of standard or custom fixup - -idaman const fixup_handler_t * ida_export get_fixup_handler(fixup_type_t type); - - -/// Use fixup information for an address. -/// This function converts item_ea flags to offsets/segments. -/// For undefined bytes, you may set item_ea == fixup_ea. In this case this -/// function will create an item (byte, word, dword) there. -/// \param item_ea start address of item to modify -/// \param fixup_ea address of fixup record -/// \param n number of operand. may be 0, 1, 2, or OPND_ALL -/// \param is_macro is the instruction at 'item_ea' a macro? -/// if yes, then partial fixups (HIGH, LOW) won't be applied -/// \retval false no fixup at fixup_ea or it has #FIXUPF_UNUSED flag -/// \retval true ok, the fixup information was applied - -idaman bool ida_export apply_fixup(ea_t item_ea, ea_t fixup_ea, int n, bool is_macro); - - -/// Get the operand value. -/// This function get fixup bytes from data or an instruction at `ea' and -/// convert them to the operand value (maybe partially). -/// It is opposite in meaning to the `patch_fixup_value()`. -/// For example, FIXUP_HI8 read a byte at `ea' and shifts it left by 8 bits, -/// or AArch64's custom fixup BRANCH26 get low 26 bits of the insn at `ea' -/// and shifts it left by 2 bits. -/// This function is mainly used to get a relocation addend. -/// \param ea address to get fixup bytes from, the size of the fixup -/// bytes depends on the fixup type. -/// \sa fixup_handler_t::size -/// \param type fixup type -/// \retval operand value - -idaman uval_t ida_export get_fixup_value(ea_t ea, fixup_type_t type); - - -/// Patch the fixup bytes. -/// This function updates data or an instruction at `ea' to the fixup bytes. -/// For example, FIXUP_HI8 updates a byte at `ea' to the high byte of -/// `fd->off', or AArch64's custom fixup BRANCH26 updates low 26 bits of the -/// insn at `ea' to the value of `fd->off' shifted right by 2. -/// \param ea address where data are changed, the size of the changed data -/// depends on the fixup type. -/// \sa fixup_handler_t::size -/// \param fd fixup data -/// \retval false the fixup bytes do not fit (e.g. `fd->off' is greater -/// than 0xFFFFFFC for BRANCH26). The database is changed -/// even in this case. - -idaman bool ida_export patch_fixup_value(ea_t ea, const fixup_data_t &fd); - - -/// Get FIXUP description comment. - -idaman const char *ida_export get_fixup_desc( - qstring *buf, - ea_t source, - const fixup_data_t &fd); - - -/// Calculate size of fixup in bytes (the number of bytes the fixup patches) -/// \retval -1 means error - -idaman int ida_export calc_fixup_size(fixup_type_t type); - - -//-------------------------------------------------------------------------- -// inline implementation -inline bool fixup_data_t::is_custom(void) const -{ - return is_fixup_custom(type); -} -inline void fixup_data_t::set(ea_t source) const -{ - set_fixup(source, *this); -} - -inline bool fixup_data_t::get(ea_t source) -{ - return get_fixup(this, source); -} - -inline const char *fixup_data_t::get_desc(qstring *buf, ea_t source) const -{ - return get_fixup_desc(buf, source, *this); -} - -inline int fixup_data_t::calc_size() const -{ - return calc_fixup_size(type); -} - -inline uval_t fixup_data_t::get_value(ea_t ea) const -{ - return get_fixup_value(ea, type); -} - -inline bool fixup_data_t::patch_value(ea_t ea) const -{ - return patch_fixup_value(ea, *this); -} - -inline const fixup_handler_t *fixup_data_t::get_handler() const -{ - return get_fixup_handler(type); -} - - -/// \name Custom fixups -/// Processor modules and plugins may register custom fixup handlers. File -/// loaders should use find_custom_fixup() function to find the handler -/// created by the processor module. The custom fixup handlers will be -/// unregistered automatically before the database gets closed. -//@{ - -//-------------------------------------------------------------------------- -/// Implements the core behavior of a custom fixup -struct fixup_handler_t -{ - int32 cbsize; ///< size of this structure - const char *name; ///< Format name, must be unique - uint32 props; ///< \ref FHF_ -/// \defgroup FHF_ Fixup handler properties -/// Used by fixup_handler_t::props -//@{ -#define FHF_VERIFY 0x0001 ///< verify that the value fits into WIDTH - ///< bits. If this property is not set we - ///< just truncate the value. -#define FHF_CODE 0x0002 ///< verify that ITEM_EA in std_apply() points - ///< to an instruction. -#define FHF_FORCE_CODE 0x0004 ///< if ITEM_EA in std_apply() points to an - ///< unknown item, then convert it to code. - ///< this property is valid only with FHF_CODE. -#define FHF_ABS_OPVAL 0x0008 ///< create absolute refinfo in std_apply() - ///< because the operand also has the absolute - ///< value (usually for o_near operands) -//@} - -/// \defgroup fh_options Tuning options -//@{ - uint8 size; ///< size in bytes - uint8 width; ///< number of significant bits before shifting - uint8 shift; ///< number of bits to shift right before patching. - ///< The following should be true: - ///< `width - shift <= size * 8' - uint8 rsrv4; // reserved - - uint32 reftype; ///< reference info type and flags, - ///< std_apply() produces an offset of this type -//@} - - /// Apply a fixup: take it into account while analyzing the file. - /// Usually it consists of converting the operand into an offset expression. - /// \sa apply_fixup() - /// If this callback is not specified then std_apply() is used. - bool (idaapi *apply)( - const fixup_handler_t *fh, - ea_t item_ea, - ea_t fixup_ea, - int opnum, - bool is_macro, - const fixup_data_t &fd); - - /// Get the operand value. - /// This callback is called from get_fixup_value(). - /// \sa get_fixup_value() - /// If this callback is not specified then std_get_value() is used. - uval_t (idaapi *get_value)(const fixup_handler_t *fh, ea_t ea); - - /// Patch the fixup bytes. - /// This callback is called from patch_fixup_value() or after changing the - /// fixup (e.g. after it was moved from one location to another). - /// If this callback is not specified then std_patch_value() is used. - /// \sa patch_fixup_value() - /// \retval false the fixup bytes do not fit. The database is changed - /// even in this case. - bool (idaapi *patch_value)( - const fixup_handler_t *fh, - ea_t ea, - const fixup_data_t &fd); - -}; - - -/// \name std_apply() -/// This internal function takes \ref fh_options and \ref FHF_ to convert -/// the fixup to an offset. - -/// \name std_patch_value() -/// This internal function takes \ref fh_options and \ref FHF_ to determine -/// how to patch the bytes. -/// 1) it verifies that the fixup value fits to the fixup_handler_t::width -/// bits if the FHF_VERIFY property is specified, -/// 2) it discards bits that do not fit, -/// 3) it shifts the result right by fixup_handler_t::shift bits, -/// 4) it puts the result to the rightmost bits of fixup_handler_t::size -/// bytes at the given address. -/// For example, FIXUP_HI8 uses size = 1, and width = 16, and shift = 8, and -/// property FHF_VERIFY, or AArch64's custom fixup BRANCH26 uses size = 4, -/// and width = 28, and shift = 2, and property FHF_VERIFY. - -/// \name std_get_value() -/// This internal function takes \ref fh_options to determine how to get the -/// operand value. -/// It is opposite in meaning to the `std_patch_value()`. -/// 1) it gets the fixup_handler_t::size bytes at the given address, -/// 2) it shifts the result left by fixup_handler_t::shift bits, -/// 3) it returns the rightmost fixup_handler_t::width bits as a signed -/// value. - - -/// Register a new custom fixup. -/// This function must be called by a processor module or plugin, but not -/// by a file loader. File loaders should use find_custom_fixup() function -/// to find the handler created by the processor module. -/// \return id of the new custom fixup handler with FIXUP_CUSTOM bit set or -/// 0 (e.g. when the custom fixup handler with the same name was -/// already registered). - -idaman fixup_type_t ida_export register_custom_fixup( - const fixup_handler_t *cfh); - - -/// Unregister a new custom fixup format. Should be called by the processor -/// module before the database gets closed. - -idaman bool ida_export unregister_custom_fixup(fixup_type_t type); - - -/// Get id of a custom fixup handler. -/// \param name name of the custom fixup handler -/// \return id with FIXUP_CUSTOM bit set or 0 - -idaman fixup_type_t ida_export find_custom_fixup(const char *name); - -//@} - - -//-------------------------------------------------------------------------- -/// Collect fixup records for the specified range. -/// Partially overlapping records will be reported too. -/// \return success (false means no fixup info have been found) - -struct fixup_info_t -{ - ea_t ea; - fixup_data_t fd; -}; -DECLARE_TYPE_AS_MOVABLE(fixup_info_t); -typedef qvector fixups_t; - -idaman bool ida_export get_fixups(fixups_t *out, ea_t ea, asize_t size); - - -/// Does the specified address range contain any fixup information? - -inline bool contains_fixups(ea_t ea, asize_t size) -{ - return get_fixups(NULL, ea, size); -} - - -/// Relocate the bytes with fixup information once more (generic function). -/// This function may be called from loader_t::move_segm() if it suits the goal. -/// If loader_t::move_segm is not defined then this function will be called -/// automatically when moving segments or rebasing the entire program. -/// Special parameter values (from = BADADDR, size = 0, to = delta) are used -/// when the function is called from rebase_program(delta). - -idaman void ida_export gen_fix_fixups(ea_t from, ea_t to, asize_t size); - - -#endif // FIXUP_HPP diff --git a/idasdk75/include/fpro.h b/idasdk75/include/fpro.h deleted file mode 100644 index 4edc0a4..0000000 --- a/idasdk75/include/fpro.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __FPRO_H -#define __FPRO_H - -#include -#include - -/*! \file fpro.h - - \brief System independent counterparts of FILE* related functions from Clib - - You should not use C standard I/O functions in your modules. - The reason: Each module compiled with Borland - (and statically linked to Borland's library) will host a copy of - the FILE * information. - - So, if you open a file in the plugin and pass the handle to the - kernel, the kernel will not be able to use it. - - If you really need to use the standard functions, define USE_STANDARD_FILE_FUNCTIONS. - In this case do not mix them with q... functions. -*/ - -#if !defined(USE_STANDARD_FILE_FUNCTIONS) && !defined(__CODE_CHECKER__) -#undef stdin -#undef stdout -#undef stderr -#undef fgetc -#undef fputc -#define stdin dont_use_stdin ///< use gets() -#define stdout dont_use_stdout ///< use qprintf() -#define stderr dont_use_stderr ///< use qeprintf() -#define fopen dont_use_fopen ///< use qfopen() -#define fread dont_use_fread ///< use qfread() -#define fwrite dont_use_fwrite ///< use qfwrite() -#define ftell dont_use_ftell ///< use qftell() -#define fseek dont_use_fseek ///< use qfseek() -#define fclose dont_use_fclose ///< use qfclose() -#define fflush dont_use_fflush ///< use qflush() -#define fputc dont_use_fputc ///< use qfputc() -#define fgetc dont_use_fgetc ///< use qfgetc() -#define fgets dont_use_fgets ///< use qfgets() -#define fputs dont_use_fputs ///< use qfputs() -#define vfprintf dont_use_vfprintf ///< use qvfprintf() -#define vfscanf dont_use_vfscanf ///< use qvfscanf() -#define fprintf dont_use_fprintf ///< use qfprintf() -#define fscanf dont_use_fscanf ///< use qfscanf() -#endif - - -/// \name File I/O -/// The following functions work just like their counterparts from Clib, -/// only they are safer, system independent, and they set qerrno (see get_qerrno()). -//@{ -idaman THREAD_SAFE FILE *ida_export qfopen(const char *file, const char *mode); -idaman THREAD_SAFE ssize_t ida_export qfread(FILE *fp, void *buf, size_t n); -idaman THREAD_SAFE ssize_t ida_export qfwrite(FILE *fp, const void *buf, size_t n); -idaman THREAD_SAFE qoff64_t ida_export qftell(FILE *fp); -idaman THREAD_SAFE int ida_export qfseek(FILE *fp, qoff64_t offset, int whence); -idaman THREAD_SAFE int ida_export qfclose(FILE *fp); -idaman THREAD_SAFE int ida_export qflush(FILE *fp); -idaman THREAD_SAFE int ida_export qfputc(int chr, FILE *fp); -idaman THREAD_SAFE int ida_export qfgetc(FILE *fp); -idaman THREAD_SAFE char *ida_export qfgets(char *s, size_t len, FILE *fp); -idaman THREAD_SAFE int ida_export qfputs(const char *s, FILE *fp); -idaman FILE *ida_export qtmpfile(void); -idaman THREAD_SAFE int ida_export qunlink(const char *fname); -idaman THREAD_SAFE int ida_export qaccess(const char *fname, int mode); -idaman THREAD_SAFE char *ida_export qgets(char *line, size_t linesize); - -idaman THREAD_SAFE AS_PRINTF(2, 0) int ida_export qvfprintf(FILE *fp, const char *format, va_list va); -idaman THREAD_SAFE AS_PRINTF(1, 0) int ida_export qvprintf(const char *format, va_list va); -idaman THREAD_SAFE AS_PRINTF(1, 0) int ida_export qveprintf(const char *format, va_list va); -idaman THREAD_SAFE AS_SCANF(2, 0) int ida_export qvfscanf(FILE *fp, const char *format, va_list va); - -#ifdef __cplusplus -THREAD_SAFE AS_PRINTF(2, 3) inline int qfprintf(FILE *fp, const char *format, ...) -{ - va_list va; - va_start(va, format); - int code = qvfprintf(fp, format, va); - va_end(va); - return code; -} - -THREAD_SAFE AS_PRINTF(1, 2) inline int qprintf(const char *format, ...) -{ - va_list va; - va_start(va, format); - int code = qvprintf(format, va); - va_end(va); - return code; -} - -THREAD_SAFE AS_PRINTF(1, 2) inline int qeprintf(const char *format, ...) -{ - va_list va; - va_start(va, format); - int code = qveprintf(format, va); - va_end(va); - return code; -} - -THREAD_SAFE AS_SCANF(2, 3) inline int qfscanf(FILE *fp, const char *format, ...) -{ - va_list va; - va_start(va, format); - int code = qvfscanf(fp, format, va); - va_end(va); - return code; -} -#endif -//@} - - -/// Read line from file (the newline is removed from the output buffer) -/// \param buf output buffer -/// \param fp pointer to file -/// \return -1 or length of line - -idaman THREAD_SAFE ssize_t ida_export qgetline(qstring *buf, FILE *fp); - -/// Rename a file: 'newname' may exist, and will be deleted - -idaman THREAD_SAFE int ida_export qrename(const char *oldfname, const char *newfname); - -/// Move a file - more powerful version of qrename -/// \retval 0 success -/// \retval -1 system error -/// \retval else a combination of flags to be given for successful move -idaman THREAD_SAFE int ida_export qmove(const char *oldfname, const char *newfname, uint32 flags); -enum -{ - QMOVE_CROSS_FS = 0x01, // UNIX: allow moving between different filesystem - QMOVE_OVERWRITE = 0x02, // Overwrite existing file - QMOVE_OVR_RO = 0x04, // Overwrite file even if it is write-protected -}; - -/// Copy a file. -/// \param from source file name -/// \param to destination file name -/// \param overwrite overwrite output if it exists? -/// \param cb user callback. return false to abort the copy loop -/// \param ud user data passed back to cb -/// \param flags reserved (should be zero) -/// \retval -1 input file not found -/// \retval -2 output file not writable -/// \retval -3 output file already exists while overwrite is false -/// \retval -4 write failure -/// \retval -5 interrupted from the callback - -idaman THREAD_SAFE int ida_export qcopyfile( - const char *from, - const char *to, - bool overwrite = true, - bool (idaapi *cb)(uint64 pos, uint64 total, void *ud)=NULL, - void *ud = NULL, - int flags = 0); - - -/// Get temporary file name. -/// Returns absolute path, includes directory, and uses TEMP/TMP vars. - -idaman char *ida_export qtmpnam(char *buf, size_t bufsize); - - -/// File janitor: will close a file at destruction-time -typedef janitor_t file_janitor_t; -template <> inline file_janitor_t::~janitor_t() -{ - qfclose(resource); -} - -/// \name readbytes/writebytes -/// Add-ins for 2..32 byte read/writes. -/// \param fp pointer to file -/// \param res value read from file -/// \param size size of value in bytes (1..32) -/// \param mostfirst is MSB first? (0/1) -/// \retval 0 All these functions return 0 on success -//@{ -idaman THREAD_SAFE int ida_export freadbytes(FILE *fp,void *res,int size,int mostfirst); -idaman THREAD_SAFE int ida_export fwritebytes(FILE *fp,const void *l,int size,int mostfirst); - -#ifdef __cplusplus -#define DEF_FREADBYTES(read, write, type, size) \ - inline THREAD_SAFE int read(FILE *fp, type *res, bool mostfirst) \ - { return freadbytes(fp, res, size, mostfirst); } \ - inline THREAD_SAFE int write(FILE *fp, const type *res, bool mostfirst) \ - { return fwritebytes(fp, res, size, mostfirst); } -DEF_FREADBYTES(fread2bytes, fwrite2bytes, int16, 2) -DEF_FREADBYTES(fread2bytes, fwrite2bytes, uint16, 2) -DEF_FREADBYTES(fread4bytes, fwrite4bytes, int32, 4) -DEF_FREADBYTES(fread4bytes, fwrite4bytes, uint32, 4) -DEF_FREADBYTES(fread8bytes, fwrite8bytes, longlong, 8) -DEF_FREADBYTES(fread8bytes, fwrite8bytes, ulonglong, 8) -#else -#define fread2bytes(fp,v,mf) freadbytes(fp,v,2,mf) -#define fwrite2bytes(fp,v,mf) fwritebytes(fp,v,2,mf) -#define fread4bytes(fp,v,mf) freadbytes(fp,v,4,mf) -#define fwrite4bytes(fp,v,mf) fwritebytes(fp,v,4,mf) -#define fread8bytes(fp,v,mf) freadbytes(fp,v,8,mf) -#define fwrite8bytes(fp,v,mf) fwritebytes(fp,v,8,mf) -#endif -//@} - -#if !defined(feof) || !defined(ferror) -// If feof() and ferror() are not macros, we cannot use them -// Fortunately, for borland and vc they are macros, so there is no problem -// GCC defines them as functions: I have no idea whether they will work or not -// Anyway we remove the error directive from this file -// so the plugins can be compiled with gcc -//#error feof or ferror are not macros! -#endif - - -#endif diff --git a/idasdk75/include/frame.hpp b/idasdk75/include/frame.hpp deleted file mode 100644 index 559bb75..0000000 --- a/idasdk75/include/frame.hpp +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _FRAME_HPP -#define _FRAME_HPP -#include - -/*! \file frame.hpp - - \brief Routines to manipulate function stack frames, stack - variables, register variables and local labels. - - The frame is represented as a structure: -
-    +------------------------------------------------+
-    | function arguments                             |
-    +------------------------------------------------+
-    | return address (isn't stored in func_t)        |
-    +------------------------------------------------+
-    | saved registers (SI, DI, etc - func_t::frregs) |
-    +------------------------------------------------+ <- typical BP
-    |                                                |  |
-    |                                                |  | func_t::fpd
-    |                                                |  |
-    |                                                | <- real BP
-    | local variables (func_t::frsize)               |
-    |                                                |
-    |                                                |
-    +------------------------------------------------+ <- SP
-  
- - To access the structure of a function frame, use: - - get_struc() (use func_t::frame as structure ID) - - get_frame(const func_t *pfn) - - get_frame(ea_t ea) -*/ - -class struc_t; -class member_t; -class op_t; - -// We need to trace value of SP register. For this we introduce -// an array of SP register change points. - -// SP register change point -// -// NOTE: To manipulate/modify stack points, please use the specialized -// functions provided below in this file (stack pointer change points) - -struct stkpnt_t -{ - ea_t ea; // linear address - sval_t spd; // here we keep a cumulative difference from [BP-frsize] - DECLARE_COMPARISONS(stkpnt_t) - { - if ( ea < r.ea ) - return -1; - if ( ea > r.ea ) - return 1; - return 0; - } -}; -DECLARE_TYPE_AS_MOVABLE(stkpnt_t); -// we declare a struct to be able to forward declare it in other files -struct stkpnts_t : public qvector -{ - DECLARE_COMPARISONS(stkpnts_t) { return compare_containers(*this, r); } -}; - -//-------------------------------------------------------------------------- -// F R A M E M A N I P U L A T I O N -//-------------------------------------------------------------------------- - -/// Add function frame. -/// \param pfn pointer to function structure -/// \param frsize size of function local variables -/// \param frregs size of saved registers -/// \param argsize size of function arguments range which will be purged upon return. -/// this parameter is used for __stdcall and __pascal calling conventions. -/// for other calling conventions please pass 0. -/// \retval 1 ok -/// \retval 0 failed (no function, frame already exists) - -idaman bool ida_export add_frame( - func_t *pfn, - sval_t frsize, - ushort frregs, - asize_t argsize); - - -/// Delete a function frame. -/// \param pfn pointer to function structure -/// \return success - -idaman bool ida_export del_frame(func_t *pfn); - - -/// Set size of function frame. -/// Note: The returned size may not include all stack arguments. It does so -/// only for __stdcall and __fastcall calling conventions. To get the entire -/// frame size for all cases use get_struc_size(get_frame(pfn)). -/// \param pfn pointer to function structure -/// \param frsize size of function local variables -/// \param frregs size of saved registers -/// \param argsize size of function arguments that will be purged -/// from the stack upon return -/// \return success - -idaman bool ida_export set_frame_size( - func_t *pfn, - asize_t frsize, - ushort frregs, - asize_t argsize); - - -/// Get full size of a function frame. -/// This function takes into account size of local variables + size of -/// saved registers + size of return address + number of purged bytes. -/// The purged bytes correspond to the arguments of the functions with -/// __stdcall and __fastcall calling conventions. -/// \param pfn pointer to function structure, may be NULL -/// \return size of frame in bytes or zero - -idaman asize_t ida_export get_frame_size(const func_t *pfn); - - -/// Get size of function return address. -/// \param pfn pointer to function structure, can't be NULL - -idaman int ida_export get_frame_retsize(const func_t *pfn); - -/// Parts of a frame -enum frame_part_t -{ - FPC_ARGS, - FPC_RETADDR, - FPC_SAVREGS, - FPC_LVARS, -}; - -/// Get offsets of the frame part in the frame. -/// \param range pointer to the output buffer with the frame part -/// start/end(exclusive) offsets, can't be NULL -/// \param pfn pointer to function structure, can't be NULL -/// \param part frame part - -idaman void ida_export get_frame_part(range_t *range, const func_t *pfn, frame_part_t part); - -/// Get starting address of arguments section - -inline ea_t frame_off_args(const func_t *pfn) -{ - range_t range; - get_frame_part(&range, pfn, FPC_ARGS); - return range.start_ea; -} - -/// Get starting address of return address section - -inline ea_t frame_off_retaddr(const func_t *pfn) -{ - range_t range; - get_frame_part(&range, pfn, FPC_RETADDR); - return range.start_ea; -} - -/// Get starting address of saved registers section - -inline ea_t frame_off_savregs(const func_t *pfn) -{ - range_t range; - get_frame_part(&range, pfn, FPC_SAVREGS); - return range.start_ea; -} - -/// Get start address of local variables section - -inline ea_t frame_off_lvars(const func_t *pfn) -{ - range_t range; - get_frame_part(&range, pfn, FPC_LVARS); - return range.start_ea; -} - -/// Does the given offset lie within the arguments section? - -inline bool processor_t::is_funcarg_off(const func_t *pfn, uval_t frameoff) const -{ - range_t args; - get_frame_part(&args, pfn, FPC_ARGS); - return stkup() - ? frameoff < args.end_ea - : frameoff >= args.start_ea; -} - -/// Does the given offset lie within the local variables section? - -inline sval_t processor_t::lvar_off(const func_t *pfn, uval_t frameoff) const -{ - range_t lvars; - get_frame_part(&lvars, pfn, FPC_LVARS); - return stkup() - ? frameoff - lvars.start_ea - : lvars.end_ea - frameoff; -} - -/// Get pointer to function frame. -/// \param pfn pointer to function structure - -idaman struc_t *ida_export get_frame(const func_t *pfn); - -/// Get pointer to function frame. -/// \param ea any address in the function - -inline struc_t *get_frame(ea_t ea) { return get_frame(get_func(ea)); } - - -/// Convert struct offsets into fp-relative offsets. -/// This function converts the offsets inside the struc_t object -/// into the frame pointer offsets (for example, EBP-relative). - -inline sval_t soff_to_fpoff(func_t *pfn, uval_t soff) -{ - return soff - pfn->frsize + pfn->fpd; -} - - -/// Update frame pointer delta. -/// \param pfn pointer to function structure -/// \param fpd new fpd value. -/// cannot be bigger than the local variable range size. -/// \return success - -idaman bool ida_export update_fpd(func_t *pfn, asize_t fpd); - - -/// Set the number of purged bytes for a function or data item (funcptr). -/// This function will update the database and plan to reanalyze items -/// referencing the specified address. It works only for processors -/// with #PR_PURGING bit in 16 and 32 bit modes. -/// \param ea address of the function of item -/// \param nbytes number of purged bytes -/// \param override_old_value may overwrite old information about purged bytes -/// \return success - -idaman bool ida_export set_purged(ea_t ea, int nbytes, bool override_old_value); - - -/// Get function by its frame id. -/// \warning this function works only with databases created by IDA > 5.6 -/// \param frame_id id of the function frame -/// \return start address of the function or #BADADDR - -idaman ea_t ida_export get_func_by_frame(tid_t frame_id); - - -//-------------------------------------------------------------------------- -// S T A C K V A R I A B L E S -//-------------------------------------------------------------------------- - -/// Get pointer to stack variable. -/// \param actval actual value used to fetch stack variable -/// this pointer may point to 'v' -/// \param insn the instruction -/// \param x reference to instruction operand -/// \param v immediate value in the operand (usually x.addr) -/// \return NULL or ptr to stack variable - -idaman member_t *ida_export get_stkvar( - sval_t *actval, - const insn_t &insn, - const op_t &x, - sval_t v); - -/// Automatically add stack variable if doesn't exist. -/// Processor modules should use insn_t::create_stkvar(). -/// \param insn the instruction -/// \param x reference to instruction operand -/// \param v immediate value in the operand (usually x.addr) -/// \param flags \ref STKVAR_1 -/// \return success - -idaman bool ida_export add_stkvar(const insn_t &insn, const op_t &x, sval_t v, int flags); - -/// \defgroup STKVAR_1 Add stkvar flags -/// Passed as 'flags' parameter to add_stkvar() -//@{ -#define STKVAR_VALID_SIZE 0x0001 ///< x.dtyp contains correct variable type - ///< (for insns like 'lea' this bit must be off) - ///< in general, dr_O references do not allow - ///< to determine the variable size -//@} - -/// Define/redefine a stack variable. -/// \param pfn pointer to function -/// \param name variable name, NULL means autogenerate a name -/// \param off offset of the stack variable in the frame. -/// negative values denote local variables, positive - function arguments. -/// \param flags variable type flags (byte_flag() for a byte variable, for example) -/// \param ti additional type information (like offsets, structs, etc) -/// \param nbytes number of bytes occupied by the variable -/// \return success - -idaman bool ida_export define_stkvar( - func_t *pfn, - const char *name, - sval_t off, - flags_t flags, - const opinfo_t *ti, - asize_t nbytes); - - -/// Build automatic stack variable name. -/// \param buf pointer to buffer -/// \param pfn pointer to function (can't be NULL!) -/// \param v value of variable offset -/// \return length of stack variable name or -1 - -idaman ssize_t ida_export build_stkvar_name( - qstring *buf, - const func_t *pfn, - sval_t v); - - -/// Calculate offset of stack variable in the frame structure. -/// \param pfn pointer to function (can't be NULL!) -/// \param insn the instruction -/// \param n number of operand: (0..#UA_MAXOP-1) -/// -1 if error, return #BADADDR -/// \return #BADADDR if some error (issue a warning if stack frame is bad) - -idaman ea_t ida_export calc_stkvar_struc_offset( - func_t *pfn, - const insn_t &insn, - int n); - - -/// Find and delete wrong frame info. -/// Namely, we delete: -/// - unreferenced stack variable definitions -/// - references to dead stack variables (i.e. operands displayed in red) -/// these operands will be untyped and most likely displayed in hex. -/// We also plan to reanalyze instruction with the stack frame references -/// \param pfn pointer to the function -/// \param should_reanalyze callback to determine which instructions to reanalyze -/// \return number of deleted definitions - -idaman int ida_export delete_wrong_frame_info( - func_t *pfn, - bool idaapi should_reanalyze(const insn_t &insn)); - - -//-------------------------------------------------------------------------- -// R E G I S T E R V A R I A B L E S -//-------------------------------------------------------------------------- -/// \defgroup regvar Register variables -/// Definition of ::regvar_t and related functions -//@{ - -/// A register variable allows the user to rename a general processor register -/// to a meaningful name. -/// IDA doesn't check whether the target assembler supports the register renaming. -/// All register definitions will appear at the beginning of the function. -struct regvar_t : public range_t -{ - char *canon; ///< canonical register name (case-insensitive) - char *user; ///< user-defined register name - char *cmt; ///< comment to appear near definition -}; -DECLARE_TYPE_AS_MOVABLE(regvar_t); - -/// Define a register variable. -/// \param pfn function in which the definition will be created -/// \param ea1,ea2 range of addresses within the function where the definition -/// will be used -/// \param canon name of a general register -/// \param user user-defined name for the register -/// \param cmt comment for the definition -/// \return \ref REGVAR_ERROR_ - -idaman int ida_export add_regvar( - func_t *pfn, - ea_t ea1, - ea_t ea2, - const char *canon, - const char *user, - const char *cmt); -/// \defgroup REGVAR_ERROR_ Register variable error codes -/// Return values for functions in described in \ref regvar -//@{ -#define REGVAR_ERROR_OK 0 ///< all ok -#define REGVAR_ERROR_ARG (-1) ///< function arguments are bad -#define REGVAR_ERROR_RANGE (-2) ///< the definition range is bad -#define REGVAR_ERROR_NAME (-3) ///< the provided name(s) can't be accepted -//@} - -/// Find a register variable definition (powerful version). -/// One of 'canon' and 'user' should be NULL. -/// If both 'canon' and 'user' are NULL it returns the first regvar -/// definition in the range. -/// \param pfn function in question -/// \param ea1,ea2 range of addresses to search. -/// ea1==BADADDR means the entire function -/// \param canon name of a general register -/// \param user user-defined name for the register -/// \return NULL-not found, otherwise ptr to regvar_t - -idaman regvar_t *ida_export find_regvar(func_t *pfn, ea_t ea1, ea_t ea2, const char *canon, const char *user); - - -/// Find a register variable definition. -/// \param pfn function in question -/// \param ea current address -/// \param canon name of a general register -/// \return NULL-not found, otherwise ptr to regvar_t - -inline regvar_t *find_regvar(func_t *pfn, ea_t ea, const char *canon) -{ - return find_regvar(pfn, ea, ea+1, canon, NULL); -} - - -/// Is there a register variable definition? -/// \param pfn function in question -/// \param ea current address - -inline bool has_regvar(func_t *pfn, ea_t ea) -{ - return find_regvar(pfn, ea, ea+1, NULL, NULL) != NULL; -} - - -/// Rename a register variable. -/// \param pfn function in question -/// \param v variable to rename -/// \param user new user-defined name for the register -/// \return \ref REGVAR_ERROR_ - -idaman int ida_export rename_regvar(func_t *pfn, regvar_t *v, const char *user); - - -/// Set comment for a register variable. -/// \param pfn function in question -/// \param v variable to rename -/// \param cmt new comment -/// \return \ref REGVAR_ERROR_ - -idaman int ida_export set_regvar_cmt(func_t *pfn, regvar_t *v, const char *cmt); - - -/// Delete a register variable definition. -/// \param pfn function in question -/// \param ea1,ea2 range of addresses within the function where the definition holds -/// \param canon name of a general register -/// \return \ref REGVAR_ERROR_ - -idaman int ida_export del_regvar(func_t *pfn, ea_t ea1, ea_t ea2, const char *canon); - -//@} regvar - -//-------------------------------------------------------------------------- -// S P R E G I S T E R C H A N G E P O I N T S -//-------------------------------------------------------------------------- - -/// Add automatic SP register change point. -/// \param pfn pointer to function. may be NULL. -/// \param ea linear address where SP changes. -/// usually this is the end of the instruction which -/// modifies the stack pointer (\cmd{ea}+\cmd{size}) -/// \param delta difference between old and new values of SP -/// \return success - -idaman bool ida_export add_auto_stkpnt(func_t *pfn, ea_t ea, sval_t delta); - - -/// Add user-defined SP register change point. -/// \param ea linear address where SP changes -/// \param delta difference between old and new values of SP -/// \return success - -idaman bool ida_export add_user_stkpnt(ea_t ea, sval_t delta); - - -/// Delete SP register change point. -/// \param pfn pointer to function. may be NULL. -/// \param ea linear address -/// \return success - -idaman bool ida_export del_stkpnt(func_t *pfn, ea_t ea); - - -/// Get difference between the initial and current values of ESP. -/// \param pfn pointer to function. may be NULL. -/// \param ea linear address of an instruction -/// \return 0 or the difference, usually a negative number. -/// returns the sp-diff before executing the instruction. - -idaman sval_t ida_export get_spd(func_t *pfn, ea_t ea); - - -/// Get effective difference between the initial and current values of ESP. -/// This function returns the sp-diff used by the instruction. -/// The difference between get_spd() and get_effective_spd() is present only -/// for instructions like "pop [esp+N]": they modify sp and use the modified value. -/// \param pfn pointer to function. may be NULL. -/// \param ea linear address -/// \return 0 or the difference, usually a negative number - -idaman sval_t ida_export get_effective_spd(func_t *pfn, ea_t ea); - - -/// Get modification of SP made at the specified location -/// \param pfn pointer to function. may be NULL. -/// \param ea linear address -/// \return 0 if the specified location doesn't contain a SP change point. -/// otherwise return delta of SP modification. - -idaman sval_t ida_export get_sp_delta(func_t *pfn, ea_t ea); - - -/// Recalculate SP delta for an instruction that stops execution. -/// The next instruction is not reached from the current instruction. -/// We need to recalculate SP for the next instruction. -/// -/// This function will create a new automatic SP register change -/// point if necessary. It should be called from the emulator (emu.cpp) -/// when auto_state == ::AU_USED if the current instruction doesn't pass -/// the execution flow to the next instruction. -/// \param cur_ea linear address of the current instruction -/// \retval 1 new stkpnt is added -/// \retval 0 nothing is changed - -idaman bool ida_export recalc_spd(ea_t cur_ea); - - -/// An xref to an argument or variable located in a function's stack frame -struct xreflist_entry_t -{ - ea_t ea; ///< Location of the insn referencing the stack frame member - uchar opnum; ///< Number of the operand of that instruction - uchar type; ///< The type of xref (::cref_t & ::dref_t) - - DECLARE_COMPARISONS(xreflist_entry_t) - { - int code = ::compare(ea, r.ea); - if ( code == 0 ) - { - code = ::compare(type, r.type); - if ( code == 0 ) - code = ::compare(opnum, r.opnum); - } - return code; - } -}; -DECLARE_TYPE_AS_MOVABLE(xreflist_entry_t); -typedef qvector xreflist_t; ///< vector of xrefs to variables in a function's stack frame - -/// Fill 'out' with a list of all the xrefs made from function 'pfn', to -/// the argument or variable 'mptr' in 'pfn's stack frame. -/// \param out the list of xrefs to fill. -/// \param pfn the function to scan. -/// \param mptr the argument/variable in pfn's stack frame. - -idaman void ida_export build_stkvar_xrefs(xreflist_t *out, func_t *pfn, const member_t *mptr); - - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED ea_t ida_export get_min_spd_ea(func_t *pfn); -idaman DEPRECATED int ida_export delete_unreferenced_stkvars(func_t *pfn); -idaman DEPRECATED int ida_export delete_wrong_stkvar_ops(func_t *pfn); -#endif - -#endif // _FRAME_HPP diff --git a/idasdk75/include/funcs.hpp b/idasdk75/include/funcs.hpp deleted file mode 100644 index 49add31..0000000 --- a/idasdk75/include/funcs.hpp +++ /dev/null @@ -1,950 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef FUNCS_HPP -#define FUNCS_HPP -#include -#include - -/*! \file funcs.hpp - - \brief Routines for working with functions within the disassembled program. - - This file also contains routines for working with library signatures - (e.g. FLIRT). - - Each function consists of function chunks. At least one function chunk - must be present in the function definition - the function entry chunk. - Other chunks are called function tails. There may be several of them - for a function. - - A function tail is a continuous range of addresses. - It can be used in the definition of one or more functions. - One function using the tail is singled out and called the tail owner. - This function is considered as 'possessing' the tail. - get_func() on a tail address will return the function possessing the tail. - You can enumerate the functions using the tail by using ::func_parent_iterator_t. - - Each function chunk in the disassembly is represented as an "range" (a range - of addresses, see range.hpp for details) with characteristics. - - A function entry must start with an instruction (code) byte. -*/ - -struct stkpnt_t; // #include -struct regvar_t; // #include -struct llabel_t; // #include -class insn_t; // #include - -/// Register argument description. -/// regargs are destroyed when the full function type is determined. -struct regarg_t -{ - int reg; - type_t *type; - char *name; -}; - - -//------------------------------------------------------------------------ -/// A function is a set of continuous ranges of addresses with characteristics -class func_t : public range_t -{ -public: - uint64 flags; ///< \ref FUNC_ -/// \defgroup FUNC_ Function flags -/// Used by func_t::flags -//@{ -#define FUNC_NORET 0x00000001 ///< Function doesn't return -#define FUNC_FAR 0x00000002 ///< Far function -#define FUNC_LIB 0x00000004 ///< Library function - -#define FUNC_STATICDEF 0x00000008 ///< Static function - -#define FUNC_FRAME 0x00000010 ///< Function uses frame pointer (BP) -#define FUNC_USERFAR 0x00000020 ///< User has specified far-ness - ///< of the function -#define FUNC_HIDDEN 0x00000040 ///< A hidden function chunk -#define FUNC_THUNK 0x00000080 ///< Thunk (jump) function -#define FUNC_BOTTOMBP 0x00000100 ///< BP points to the bottom of the stack frame -#define FUNC_NORET_PENDING 0x00200 ///< Function 'non-return' analysis must be performed. - ///< This flag is verified upon func_does_return() -#define FUNC_SP_READY 0x00000400 ///< SP-analysis has been performed. - ///< If this flag is on, the stack - ///< change points should not be not - ///< modified anymore. Currently this - ///< analysis is performed only for PC -#define FUNC_FUZZY_SP 0x00000800 ///< Function changes SP in untraceable way, - ///< for example: and esp, 0FFFFFFF0h -#define FUNC_PROLOG_OK 0x00001000 ///< Prolog analysis has be performed - ///< by last SP-analysis -#define FUNC_PURGED_OK 0x00004000 ///< 'argsize' field has been validated. - ///< If this bit is clear and 'argsize' - ///< is 0, then we do not known the real - ///< number of bytes removed from - ///< the stack. This bit is handled - ///< by the processor module. -#define FUNC_TAIL 0x00008000 ///< This is a function tail. - ///< Other bits must be clear - ///< (except #FUNC_HIDDEN). -#define FUNC_LUMINA 0x00010000 ///< Function info is provided by Lumina. -//@} - - /// Is a far function? - bool is_far(void) const { return (flags & FUNC_FAR) != 0; } - /// Does function return? - bool does_return(void) const { return (flags & FUNC_NORET) == 0; } - /// Has SP-analysis been performed? - bool analyzed_sp(void) const { return (flags & FUNC_SP_READY) != 0; } - /// Needs prolog analysis? - bool need_prolog_analysis(void) const { return (flags & FUNC_PROLOG_OK) == 0; } -#ifndef SWIG - union - { - /// attributes of a function entry chunk - struct - { -#endif // SWIG - // - // Stack frame of the function. It is represented as a structure: - // - // +------------------------------------------------+ - // | function arguments | - // +------------------------------------------------+ - // | return address (isn't stored in func_t) | - // +------------------------------------------------+ - // | saved registers (SI, DI, etc - func_t::frregs) | - // +------------------------------------------------+ <- typical BP - // | | | - // | | | func_t::fpd - // | | | - // | | <- real BP - // | local variables (func_t::frsize) | - // | | - // | | - // +------------------------------------------------+ <- SP - // - uval_t frame; ///< netnode id of frame structure - see frame.hpp - asize_t frsize; ///< size of local variables part of frame in bytes. - ///< If #FUNC_FRAME is set and #fpd==0, the frame pointer - ///< (EBP) is assumed to point to the top of the local - ///< variables range. - ushort frregs; ///< size of saved registers in frame. This range is - ///< immediately above the local variables range. - asize_t argsize; ///< number of bytes purged from the stack - ///< upon returning - asize_t fpd; ///< frame pointer delta. (usually 0, i.e. realBP==typicalBP) - ///< use update_fpd() to modify it. - - bgcolor_t color; ///< user defined function color - - // the following fields should not be accessed directly: - - uint32 pntqty; ///< number of SP change points - stkpnt_t *points; ///< array of SP change points. - ///< use ...stkpnt...() functions to access this array. - - int regvarqty; ///< number of register variables (-1-not read in yet) - ///< use find_regvar() to read register variables - regvar_t *regvars; ///< array of register variables. - ///< this array is sorted by: start_ea. - ///< use ...regvar...() functions to access this array. - - int llabelqty; ///< number of local labels - llabel_t *llabels; ///< local labels. - ///< this array shouldn't be accessed directly; name.hpp - ///< functions should be used instead. - - int regargqty; ///< number of register arguments. - ///< During analysis IDA tries to guess the register - ///< arguments. It stores store the guessing outcome - ///< in this field. As soon as it determines the final - ///< function prototype, regargqty is set to zero. - regarg_t *regargs; ///< unsorted array of register arguments. - ///< use ...regarg...() functions to access this array. - ///< regargs are destroyed when the full function - ///< type is determined. - - int tailqty; ///< number of function tails - range_t *tails; ///< array of tails, sorted by ea. - ///< use func_tail_iterator_t to access function tails. -#ifndef SWIG - }; - /// attributes of a function tail chunk - struct - { -#endif // SWIG - ea_t owner; ///< the address of the main function possessing this tail - int refqty; ///< number of referers - ea_t *referers; ///< array of referers (function start addresses). - ///< use func_parent_iterator_t to access the referers. -#ifndef SWIG - }; - }; -#endif // SWIG - - func_t(ea_t start=0, ea_t end=0, flags_t f=0) - : range_t(start, end), flags(f|FUNC_NORET_PENDING), frame(BADNODE), - frsize(0), frregs(0), argsize(0), fpd(0), color(DEFCOLOR), - pntqty(0), points(nullptr), - regvarqty(0), regvars(nullptr), - llabelqty(0), llabels(nullptr), - regargqty(0), regargs(nullptr), - tailqty(0), tails(nullptr) - { - } -}; -DECLARE_TYPE_AS_MOVABLE(func_t); - -/// Does function describe a function entry chunk? -inline bool is_func_entry(const func_t *pfn) { return pfn != nullptr && (pfn->flags & FUNC_TAIL) == 0; } -/// Does function describe a function tail chunk? -inline bool is_func_tail(const func_t *pfn) { return pfn != nullptr && (pfn->flags & FUNC_TAIL) != 0; } - - -/// Lock function pointer -/// Locked pointers are guaranteed to remain valid until they are unlocked. -/// Ranges with locked pointers cannot be deleted or moved. - -idaman void ida_export lock_func_range(const func_t *pfn, bool lock); - -/// Helper class to lock a function pointer so it stays valid -class lock_func -{ - const func_t *pfn; -public: - lock_func(const func_t *_pfn) : pfn(_pfn) - { - lock_func_range(pfn, true); - } - ~lock_func(void) - { - lock_func_range(pfn, false); - } -}; - -/// Is the function pointer locked? - -idaman bool ida_export is_func_locked(const func_t *pfn); - -//-------------------------------------------------------------------- -// F U N C T I O N S -//-------------------------------------------------------------------- -/// Get pointer to function structure by address. -/// \param ea any address in a function -/// \return ptr to a function or nullptr. -/// This function returns a function entry chunk. - -idaman func_t *ida_export get_func(ea_t ea); - - -/// Get the containing tail chunk of 'ea'. -/// \retval -1 means 'does not contain ea' -/// \retval 0 means the 'pfn' itself contains ea -/// \retval >0 the number of the containing function tail chunk - -idaman int ida_export get_func_chunknum(func_t *pfn, ea_t ea); - -/// Does the given function contain the given address? - -inline bool func_contains(func_t *pfn, ea_t ea) -{ - return get_func_chunknum(pfn, ea) >= 0; -} - -/// Do two addresses belong to the same function? -inline bool is_same_func(ea_t ea1, ea_t ea2) -{ - func_t *pfn = get_func(ea1); - return pfn != nullptr && func_contains(pfn, ea2); -} - -/// Get pointer to function structure by number. -/// \param n number of function, is in range 0..get_func_qty()-1 -/// \return ptr to a function or nullptr. -/// This function returns a function entry chunk. - -idaman func_t *ida_export getn_func(size_t n); - - -/// Get total number of functions in the program - -idaman size_t ida_export get_func_qty(void); - - -/// Get ordinal number of a function. -/// \param ea any address in the function -/// \return number of function (0..get_func_qty()-1). -/// -1 means 'no function at the specified address'. - -idaman int ida_export get_func_num(ea_t ea); - - -/// Get pointer to the previous function. -/// \param ea any address in the program -/// \return ptr to function or nullptr if previous function doesn't exist - -idaman func_t *ida_export get_prev_func(ea_t ea); - - -/// Get pointer to the next function. -/// \param ea any address in the program -/// \return ptr to function or nullptr if next function doesn't exist - -idaman func_t *ida_export get_next_func(ea_t ea); - - -/// Get function ranges. -/// \param ranges buffer to receive the range info -/// \param pfn ptr to function structure -/// \return end address of the last function range (BADADDR-error) - -idaman ea_t ida_export get_func_ranges(rangeset_t *ranges, func_t *pfn); - - -/// Get function comment. -/// \param buf buffer for the comment -/// \param pfn ptr to function structure -/// \param repeatable get repeatable comment? -/// \return size of comment or -1 -/// In fact this function works with function chunks too. - -idaman ssize_t ida_export get_func_cmt(qstring *buf, const func_t *pfn, bool repeatable); - - -/// Set function comment. -/// This function works with function chunks too. -/// \param pfn ptr to function structure -/// \param cmt comment string, may be multiline (with '\n'). -/// Use empty str ("") to delete comment -/// \param repeatable set repeatable comment? - -idaman bool ida_export set_func_cmt(const func_t *pfn, const char *cmt, bool repeatable); - - -/// Update information about a function in the database (::func_t). -/// You must not change the function start and end addresses using this function. -/// Use set_func_start() and set_func_end() for it. -/// \param pfn ptr to function structure -/// \return success - -idaman bool ida_export update_func(func_t *pfn); - - -/// Add a new function. -/// If the fn->end_ea is #BADADDR, then IDA will try to determine the -/// function bounds by calling find_func_bounds(..., #FIND_FUNC_DEFINE). -/// \param pfn ptr to filled function structure -/// \return success - -idaman bool ida_export add_func_ex(func_t *pfn); - - -/// Add a new function. -/// If the function end address is #BADADDR, then IDA will try to determine -/// the function bounds by calling find_func_bounds(..., #FIND_FUNC_DEFINE). -/// \param ea1 start address -/// \param ea2 end address -/// \return success - -inline bool add_func(ea_t ea1, ea_t ea2=BADADDR) -{ - func_t fn(ea1, ea2); - return add_func_ex(&fn); -} - - -/// Delete a function. -/// \param ea any address in the function entry chunk -/// \return success - -idaman bool ida_export del_func(ea_t ea); - - -/// Move function chunk start address. -/// \param ea any address in the function -/// \param newstart new end address of the function -/// \return \ref MOVE_FUNC_ - -idaman int ida_export set_func_start(ea_t ea, ea_t newstart); -/// \defgroup MOVE_FUNC_ Function move result codes -/// Return values for set_func_start() -//@{ -#define MOVE_FUNC_OK 0 ///< ok -#define MOVE_FUNC_NOCODE 1 ///< no instruction at 'newstart' -#define MOVE_FUNC_BADSTART 2 ///< bad new start address -#define MOVE_FUNC_NOFUNC 3 ///< no function at 'ea' -#define MOVE_FUNC_REFUSED 4 ///< a plugin refused the action -//@} - - -/// Move function chunk end address. -/// \param ea any address in the function -/// \param newend new end address of the function -/// \return success - -idaman bool ida_export set_func_end(ea_t ea, ea_t newend); - - -/// Reanalyze a function. -/// This function plans to analyzes all chunks of the given function. -/// Optional parameters (ea1, ea2) may be used to narrow the analyzed range. -/// \param pfn pointer to a function -/// \param ea1 start of the range to analyze -/// \param ea2 end of range to analyze -/// \param analyze_parents meaningful only if pfn points to a function tail. -/// if true, all tail parents will be reanalyzed. -/// if false, only the given tail will be reanalyzed. - -idaman void ida_export reanalyze_function( - func_t *pfn, - ea_t ea1=0, - ea_t ea2=BADADDR, - bool analyze_parents=false); - - -/// Determine the boundaries of a new function. -/// This function tries to find the start and end addresses of a new function. -/// It calls the module with \ph{func_bounds} in order to fine tune -/// the function boundaries. -/// \param nfn structure to fill with information -/// \ nfn->start_ea points to the start address of the new function. -/// \param flags \ref FIND_FUNC_F -/// \return \ref FIND_FUNC_R - -idaman int ida_export find_func_bounds(func_t *nfn, int flags); - -/// \defgroup FIND_FUNC_F Find function bounds flags -/// Passed as 'flags' parameter to find_func_bounds() -//@{ -#define FIND_FUNC_NORMAL 0x0000 ///< stop processing if undefined byte is encountered -#define FIND_FUNC_DEFINE 0x0001 ///< create instruction if undefined byte is encountered -#define FIND_FUNC_IGNOREFN 0x0002 ///< ignore existing function boundaries. - ///< by default the function returns function boundaries - ///< if ea belongs to a function. -#define FIND_FUNC_KEEPBD 0x0004 ///< do not modify incoming function boundaries, - ///< just create instructions inside the boundaries. -//@} - -/// \defgroup FIND_FUNC_R Find function bounds result codes -/// Return values for find_func_bounds() -//@{ -#define FIND_FUNC_UNDEF 0 ///< function has instructions that pass execution flow to unexplored bytes. - ///< nfn->end_ea will have the address of the unexplored byte. -#define FIND_FUNC_OK 1 ///< ok, 'nfn' is ready for add_func() -#define FIND_FUNC_EXIST 2 ///< function exists already. - ///< its bounds are returned in 'nfn'. -//@} - - -/// Get function name. -/// \param out buffer for the answer -/// \param ea any address in the function -/// \return length of the function name - -idaman ssize_t ida_export get_func_name(qstring *out, ea_t ea); - - -/// Calculate function size. -/// This function takes into account all fragments of the function. -/// \param pfn ptr to function structure - -idaman asize_t ida_export calc_func_size(func_t *pfn); - - -/// Get function bitness (which is equal to the function segment bitness). -/// pfn==nullptr => returns 0 -/// \retval 0 16 -/// \retval 1 32 -/// \retval 2 64 - -idaman int ida_export get_func_bitness(const func_t *pfn); - -/// Get number of bits in the function addressing -inline int idaapi get_func_bits(const func_t *pfn) { return 1 << (get_func_bitness(pfn)+4); } - -/// Get number of bytes in the function addressing -inline int idaapi get_func_bytes(const func_t *pfn) { return get_func_bits(pfn)/8; } - - -/// Is the function visible (not hidden)? - -inline bool is_visible_func(func_t *pfn) { return (pfn->flags & FUNC_HIDDEN) == 0; } - -/// Is the function visible (event after considering #SCF_SHHID_FUNC)? -inline bool is_finally_visible_func(func_t *pfn) -{ - return (inf_get_cmtflg() & SCF_SHHID_FUNC) != 0 || is_visible_func(pfn); -} - -/// Set visibility of function - -idaman void ida_export set_visible_func(func_t *pfn, bool visible); - - -/// Give a meaningful name to function if it consists of only 'jump' instruction. -/// \param pfn pointer to function (may be nullptr) -/// \param oldname old name of function. -/// if old name was in "j_..." form, then we may discard it -/// and set a new name. -/// if oldname is not known, you may pass nullptr. -/// \return success - -idaman int ida_export set_func_name_if_jumpfunc(func_t *pfn, const char *oldname); - - -/// Calculate target of a thunk function. -/// \param pfn pointer to function (may not be nullptr) -/// \param fptr out: will hold address of a function pointer (if indirect jump) -/// \return the target function or #BADADDR - -idaman ea_t ida_export calc_thunk_func_target(func_t *pfn, ea_t *fptr); - - -/// Does the function return?. -/// To calculate the answer, #FUNC_NORET flag and is_noret() are consulted -/// The latter is required for imported functions in the .idata section. -/// Since in .idata we have only function pointers but not functions, we have -/// to introduce a special flag for them. - -idaman bool ida_export func_does_return(ea_t callee); - - -/// Plan to reanalyze noret flag. -/// This function does not remove FUNC_NORET if it is already present. -/// It just plans to reanalysis. - -idaman bool ida_export reanalyze_noret_flag(ea_t ea); - - -/// Signal a non-returning instruction. -/// This function can be used by the processor module to tell the kernel -/// about non-returning instructions (like call exit). The kernel will -/// perform the global function analysis and find out if the function -/// returns at all. This analysis will be done at the first call to func_does_return() -/// \return true if the instruction 'noret' flag has been changed - -idaman bool ida_export set_noret_insn(ea_t insn_ea, bool noret); - - -//-------------------------------------------------------------------- -// F U N C T I O N C H U N K S -//-------------------------------------------------------------------- -/// Get pointer to function chunk structure by address. -/// \param ea any address in a function chunk -/// \return ptr to a function chunk or nullptr. -/// This function may return a function entry as well as a function tail. - -idaman func_t *ida_export get_fchunk(ea_t ea); - - -/// Get pointer to function chunk structure by number. -/// \param n number of function chunk, is in range 0..get_fchunk_qty()-1 -/// \return ptr to a function chunk or nullptr. -/// This function may return a function entry as well as a function tail. - -idaman func_t *ida_export getn_fchunk(int n); - - -/// Get total number of function chunks in the program - -idaman size_t ida_export get_fchunk_qty(void); - - -/// Get ordinal number of a function chunk in the global list of function chunks. -/// \param ea any address in the function chunk -/// \return number of function chunk (0..get_fchunk_qty()-1). -/// -1 means 'no function chunk at the specified address'. - -idaman int ida_export get_fchunk_num(ea_t ea); - - -/// Get pointer to the previous function chunk in the global list. -/// \param ea any address in the program -/// \return ptr to function chunk or nullptr if previous function chunk doesn't exist - -idaman func_t *ida_export get_prev_fchunk(ea_t ea); - - -/// Get pointer to the next function chunk in the global list. -/// \param ea any address in the program -/// \return ptr to function chunk or nullptr if next function chunk doesn't exist - -idaman func_t *ida_export get_next_fchunk(ea_t ea); - - -//-------------------------------------------------------------------- -// Functions to manipulate function chunks - -/// Append a new tail chunk to the function definition. -/// If the tail already exists, then it will simply be added to the function tail list -/// Otherwise a new tail will be created and its owner will be set to be our function -/// If a new tail cannot be created, then this function will fail. -/// \param ea1 start of the tail. If a tail already exists at the specified address -/// it must start at 'ea1' -/// \param ea2 end of the tail. If a tail already exists at the specified address -/// it must end at 'ea2'. If specified as BADADDR, IDA will determine -/// the end address itself. - -idaman bool ida_export append_func_tail(func_t *pfn, ea_t ea1, ea_t ea2); - - -/// Remove a function tail. -/// If the tail belongs only to one function, it will be completely removed. -/// Otherwise if the function was the tail owner, the first function using -/// this tail becomes the owner of the tail. - -idaman bool ida_export remove_func_tail(func_t *pfn, ea_t tail_ea); - - -/// Set a function as the possessing function of a function tail. -/// The function should already refer to the tail (after append_func_tail). - -idaman bool ida_export set_tail_owner(func_t *fnt, ea_t func_start); - - -// Auxiliary function(s) to be used in func_..._iterator_t - -class func_parent_iterator_t; -class func_tail_iterator_t; -class func_item_iterator_t; - -/// Declare helper functions for ::func_item_iterator_t -#define DECLARE_FUNC_ITERATORS(prefix) \ -prefix bool ida_export func_tail_iterator_set(func_tail_iterator_t *fti, func_t *pfn, ea_t ea);\ -prefix bool ida_export func_tail_iterator_set_ea(func_tail_iterator_t *fti, ea_t ea);\ -prefix bool ida_export func_parent_iterator_set(func_parent_iterator_t *fpi, func_t *pfn);\ -prefix bool ida_export func_item_iterator_next(func_item_iterator_t *fii, testf_t *testf, void *ud);\ -prefix bool ida_export func_item_iterator_prev(func_item_iterator_t *fii, testf_t *testf, void *ud);\ -prefix bool ida_export func_item_iterator_decode_prev_insn(func_item_iterator_t *fii, insn_t *out); \ -prefix bool ida_export func_item_iterator_decode_preceding_insn(func_item_iterator_t *fii, eavec_t *visited, bool *p_farref, insn_t *out); -DECLARE_FUNC_ITERATORS(idaman) - -/// Helper function to accept any address -inline THREAD_SAFE bool idaapi f_any(flags_t, void *) { return true; } - -/// Class to enumerate all function tails sorted by addresses. -/// Enumeration is started with main(), first(), or last(). -/// If first() is used, the function entry chunk will be excluded from the enumeration. -/// Otherwise it will be included in the enumeration (for main() and last()). -/// The loop may continue until the next() or prev() function returns false. -/// These functions return false when the enumeration is over. -/// The tail chunks are always sorted by their addresses. -/// -/// Sample code: -/// \code -/// func_tail_iterator_t fti(pfn); -/// for ( bool ok=fti.first(); ok; ok=fti.next() ) -/// const range_t &a = fti.chunk(); -/// .... -/// \endcode -/// -/// If the 'ea' parameter is used in the constructor, then the iterator is positioned -/// at the chunk containing the specified 'ea'. Otherwise it is positioned at the -/// function entry chunk. -/// If 'pfn' is specified as nullptr then the set() function will fail, -/// but it is still possible to use the class. In this case the iteration will be -/// limited by the segment boundaries. -/// The function main chunk is locked during the iteration. -/// It is also possible to enumerate one single arbitrary range using set_range() -/// This function is mainly designed to be used from ::func_item_iterator_t. -class func_tail_iterator_t -{ - func_t *pfn; - int idx; - range_t seglim; // valid and used only if pfn == nullptr -public: - func_tail_iterator_t(void) : pfn(nullptr), idx(-1) {} - func_tail_iterator_t(func_t *_pfn, ea_t ea=BADADDR) : pfn(nullptr) { set(_pfn, ea); } - ~func_tail_iterator_t(void) - { - // if was iterating over function chunks, unlock the main chunk - if ( pfn != nullptr ) - lock_func_range(pfn, false); - } - bool set(func_t *_pfn, ea_t ea=BADADDR) { return func_tail_iterator_set(this, _pfn, ea); } - bool set_ea(ea_t ea) { return func_tail_iterator_set_ea(this, ea); } - // set an arbitrary range - bool set_range(ea_t ea1, ea_t ea2) - { - this->~func_tail_iterator_t(); - pfn = nullptr; - idx = -1; - seglim = range_t(ea1, ea2); - return !seglim.empty(); - } - const range_t &chunk(void) const - { - if ( pfn == nullptr ) - return seglim; - return idx >= 0 && idx < pfn->tailqty ? pfn->tails[idx] : *(range_t*)pfn; - } - bool first(void) { if ( pfn != nullptr ) { idx = 0; return pfn->tailqty > 0; } return false; } // get only tail chunks - bool last(void) { if ( pfn != nullptr ) { idx = pfn->tailqty - 1; return true; } return false; } // get all chunks (the entry chunk last) - bool next(void) { if ( pfn != nullptr && idx+1 < pfn->tailqty ) { idx++; return true; } return false; } - bool prev(void) { if ( idx >= 0 ) { idx--; return true; } return false; } - bool main(void) { idx = -1; return pfn != nullptr; } // get all chunks (the entry chunk first) -}; - - -/// Function to iterate function chunks (all of them including the entry chunk) -/// \param pfn pointer to the function -/// \param func function to call for each chunk -/// \param ud user data for 'func' -/// \param include_parents meaningful only if pfn points to a function tail. -/// if true, all tail parents will be iterated. -/// if false, only the given tail will be iterated. - -idaman void ida_export iterate_func_chunks( - func_t *pfn, - void (idaapi *func)(ea_t ea1, ea_t ea2, void *ud), - void *ud=nullptr, - bool include_parents=false); - - -/// Class to enumerate all function instructions and data sorted by addresses. -/// The function entry chunk items are enumerated first regardless of their addresses -/// -/// Sample code: -/// \code -/// func_item_iterator_t fii; -/// for ( bool ok=fii.set(pfn, ea); ok; ok=fii.next_addr() ) -/// ea_t ea = fii.current(); -/// .... -/// \endcode -/// -/// If 'ea' is not specified in the call to set(), then the enumeration starts at -/// the function entry point. -/// If 'pfn' is specified as nullptr then the set() function will fail, -/// but it is still possible to use the class. In this case the iteration will be -/// limited by the segment boundaries. -/// It is also possible to enumerate addresses in an arbitrary range using set_range(). -class func_item_iterator_t -{ - func_tail_iterator_t fti; - ea_t ea; -public: - func_item_iterator_t(void) : ea(BADADDR) {} - func_item_iterator_t(func_t *pfn, ea_t _ea=BADADDR) { set(pfn, _ea); } - /// Set a function range. if pfn == nullptr then a segment range will be set. - bool set(func_t *pfn, ea_t _ea=BADADDR) - { - ea = (_ea != BADADDR || pfn == nullptr) ? _ea : pfn->start_ea; - return fti.set(pfn, _ea); - } - /// Set an arbitrary range - bool set_range(ea_t ea1, ea_t ea2) { ea = ea1; return fti.set_range(ea1, ea2); } - bool first(void) { if ( !fti.main() ) return false; ea=fti.chunk().start_ea; return true; } - bool last(void) { if ( !fti.last() ) return false; ea=fti.chunk().end_ea; return true; } - ea_t current(void) const { return ea; } - const range_t &chunk(void) const { return fti.chunk(); } - bool next(testf_t *func, void *ud) { return func_item_iterator_next(this, func, ud); } - bool prev(testf_t *func, void *ud) { return func_item_iterator_prev(this, func, ud); } - bool next_addr(void) { return next(f_any, nullptr); } - bool next_head(void) { return next(f_is_head, nullptr); } - bool next_code(void) { return next(f_is_code, nullptr); } - bool next_data(void) { return next(f_is_data, nullptr); } - bool next_not_tail(void) { return next(f_is_not_tail, nullptr); } - bool prev_addr(void) { return prev(f_any, nullptr); } - bool prev_head(void) { return prev(f_is_head, nullptr); } - bool prev_code(void) { return prev(f_is_code, nullptr); } - bool prev_data(void) { return prev(f_is_data, nullptr); } - bool prev_not_tail(void) { return prev(f_is_not_tail, nullptr); } - bool decode_prev_insn(insn_t *out) { return func_item_iterator_decode_prev_insn(this, out); } - bool decode_preceding_insn(eavec_t *visited, bool *p_farref, insn_t *out) - { return func_item_iterator_decode_preceding_insn(this, visited, p_farref, out); } -}; - -/// Class to enumerate all function parents sorted by addresses. -/// Enumeration is started with first() or last(). -/// The loop may continue until the next() or prev() function returns false. -/// The parent functions are always sorted by their addresses. -/// The tail chunk is locked during the iteration. -/// -/// Sample code: -/// \code -/// func_parent_iterator_t fpi(fnt); -/// for ( bool ok=fpi.first(); ok; ok=fpi.next() ) -/// ea_t parent = fpi.parent(); -/// .... -/// \endcode -class func_parent_iterator_t -{ - func_t *fnt; - int idx; -public: - func_parent_iterator_t(void) : fnt(nullptr), idx(0) {} - func_parent_iterator_t(func_t *_fnt) : fnt(nullptr) { set(_fnt); } - ~func_parent_iterator_t(void) - { - if ( fnt != nullptr ) - lock_func_range(fnt, false); - } - bool set(func_t *_fnt) { return func_parent_iterator_set(this, _fnt); } - ea_t parent(void) const { return fnt->referers[idx]; } - bool first(void) { idx = 0; return is_func_tail(fnt) && fnt->refqty > 0; } - bool last(void) { idx = fnt->refqty - 1; return idx >= 0; } - bool next(void) { if ( idx+1 < fnt->refqty ) { idx++; return true; } return false; } - bool prev(void) { if ( idx > 0 ) { idx--; return true; } return false; } - void reset_fnt(func_t *_fnt) { fnt = _fnt; } // for internal use only! -}; - - -/// \name Get prev/next address in function -/// Unlike func_item_iterator_t which always enumerates the main function -/// chunk first, these functions respect linear address ordering. -//@{ -idaman ea_t ida_export get_prev_func_addr(func_t *pfn, ea_t ea); -idaman ea_t ida_export get_next_func_addr(func_t *pfn, ea_t ea); -//@} - -//-------------------------------------------------------------------- -/// \name -/// Functions to work with temporary register argument definitions -//@{ -idaman void ida_export read_regargs(func_t *pfn); -idaman void ida_export add_regarg(func_t *pfn, int reg, const tinfo_t &tif, const char *name); -//@} - -//-------------------------------------------------------------------- -// L I B R A R Y M O D U L E S I G N A T U R E S -//-------------------------------------------------------------------- - -/// \defgroup IDASGN_ Error codes for signature functions: -/// See calc_idasgn_state() and del_idasgn() -//@{ -#define IDASGN_OK 0 ///< ok -#define IDASGN_BADARG 1 ///< bad number of signature -#define IDASGN_APPLIED 2 ///< signature is already applied -#define IDASGN_CURRENT 3 ///< signature is currently being applied -#define IDASGN_PLANNED 4 ///< signature is planned to be applied -//@} - -/// Add a signature file to the list of planned signature files. -/// \param fname file name. should not contain directory part. -/// \return 0 if failed, otherwise number of planned (and applied) signatures - -idaman int ida_export plan_to_apply_idasgn(const char *fname); // plan to use library - - -/// Apply a signature file to the specified address. -/// \param signame short name of signature file (the file name without path) -/// \param ea address to apply the signature -/// \param is_startup if set, then the signature is treated as a startup one -/// for startup signature ida doesn't rename the first -/// function of the applied module. -/// \return \ref LIBFUNC_ - -idaman int ida_export apply_idasgn_to(const char *signame, ea_t ea, bool is_startup); - - -/// Get number of signatures in the list of planned and applied signatures. -/// \return 0..n - -idaman int ida_export get_idasgn_qty(void); - - -/// Get number of the the current signature. -/// \return 0..n-1 - -idaman int ida_export get_current_idasgn(void); - - -/// Get state of a signature in the list of planned signatures -/// \param n number of signature in the list (0..get_idasgn_qty()-1) -/// \return state of signature or #IDASGN_BADARG - -idaman int ida_export calc_idasgn_state(int n); - - -/// Remove signature from the list of planned signatures. -/// \param n number of signature in the list (0..get_idasgn_qty()-1) -/// \return #IDASGN_OK, #IDASGN_BADARG, #IDASGN_APPLIED - -idaman int ida_export del_idasgn(int n); - - -/// Get information about a signature in the list. -/// \param signame buffer for the name of the signature. -/// (short form, only base name without the directory part -/// will be stored). -/// if signame == nullptr, then the name won't be returned. -/// \param optlibs buffer for the names of the optional libraries -/// if optlibs == nullptr, then the optional libraries are not returned -/// \param n number of signature in the list (0..get_idasgn_qty()-1) -/// \return number of successfully recognized modules using this signature. -/// -1 means the 'n' is a bad argument, i.e. no signature with this -/// number exists.. - -idaman int32 ida_export get_idasgn_desc( - qstring *signame, - qstring *optlibs, - int n); - - -class idasgn_t; - -/// Get idasgn header by a short signature name. -/// \param name short name of a signature -/// \return nullptr if can't find the signature - -idaman idasgn_t *ida_export get_idasgn_header_by_short_name(const char *name); - - -/// Get full description of the signature by its short name. -/// \param buf the output buffer -/// \param name short name of a signature -/// \return size of signature description or -1 - -idaman ssize_t ida_export get_idasgn_title( - qstring *buf, - const char *name); - -/// Determine compiler/vendor using the startup signatures. -/// If determined, then appropriate signature files are included into -/// the list of planned signature files. - -idaman void ida_export determine_rtl(void); - - -/// Apply a startup signature file to the specified address. -/// \param ea address to apply the signature to; usually \inf{start_ea} -/// \param startup the name of the signature file without path and extension -/// \return true if successfully applied the signature - -idaman bool ida_export apply_startup_sig(ea_t ea, const char *startup); - - -/// Apply the currently loaded signature file to the specified address. -/// If a library function is found, then create a function and name -/// it accordingly. -/// \param ea any address in the program -/// \returns \ref LIBFUNC_ - -idaman int ida_export try_to_add_libfunc(ea_t ea); - - -/// \defgroup LIBFUNC_ Library function codes -/// Return values for try_to_add_libfunc() and apply_idasgn_to() -//@{ -#define LIBFUNC_FOUND 0 ///< ok, library function is found -#define LIBFUNC_NONE 1 ///< no, this is not a library function -#define LIBFUNC_DELAY 2 ///< no decision because of lack of information -//@} - -// KERNEL mode functions - -/// \cond -/// kept in the sdk because inlined -inline void save_signatures(void) {} -bool invalidate_sp_analysis(func_t *pfn); -inline bool invalidate_sp_analysis(ea_t ea) - { return invalidate_sp_analysis(get_func(ea)); } -/// \endcond - - -#endif diff --git a/idasdk75/include/gdl.hpp b/idasdk75/include/gdl.hpp deleted file mode 100644 index a1c4e42..0000000 --- a/idasdk75/include/gdl.hpp +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * - * Graph drawing support - * - */ - -#ifndef __GDLDRAW_HPP -#define __GDLDRAW_HPP - -#include -#include - -#include - -/*! \file gdl.hpp - - \brief Low level graph drawing operations - -*/ - -//------------------------------------------------------------------------- -// forward declarations: -class node_iterator; -class qflow_chart_t; -class gdl_graph_t; - -/// Flow chart block types -enum fc_block_type_t -{ - fcb_normal, ///< normal block - fcb_indjump, ///< block ends with indirect jump - fcb_ret, ///< return block - fcb_cndret, ///< conditional return block - fcb_noret, ///< noreturn block - fcb_enoret, ///< external noreturn block (does not belong to the function) - fcb_extern, ///< external normal block - fcb_error, ///< block passes execution past the function end -}; - -#ifndef SWIG -#define DECLARE_HELPER(decl) \ -decl node_iterator *ida_export node_iterator_goup(node_iterator *); \ -decl void ida_export create_qflow_chart(qflow_chart_t &); \ -decl bool ida_export append_to_flowchart(qflow_chart_t &, ea_t, ea_t); \ -decl fc_block_type_t ida_export fc_calc_block_type(const qflow_chart_t &, size_t); \ -decl bool ida_export create_multirange_qflow_chart(qflow_chart_t &, const rangevec_t &); -#else -#define DECLARE_HELPER(decl) -#endif // SWIG - -DECLARE_HELPER(idaman) - -//------------------------------------------------------------------------- -/// Set of integer constants -class intset_t : public std::set -{ -public: - DEFINE_MEMORY_ALLOCATION_FUNCS() - size_t idaapi print(char *buf, size_t bufsize) const; - const char *idaapi dstr(void) const; - bool has(int value) const - { - const_iterator p = find(value); - const_iterator q = end(); - return p != q; - } -}; - -typedef qvector array_of_intvec_t; - -/// Map of integer constants to integer constants -class intmap_t : public std::map -{ -public: - DEFINE_MEMORY_ALLOCATION_FUNCS() - size_t idaapi print(char *buf, size_t bufsize) const; - const char *idaapi dstr(void) const; -}; - -typedef qvector array_of_intmap_t; - -//------------------------------------------------------------------------- -/// Set of graph nodes -class node_set_t : public intset_t -{ -public: - idaapi node_set_t(void) {} - idaapi node_set_t(int node) { insert(node); } - idaapi node_set_t(const gdl_graph_t *g); - bool idaapi add(int node) { return insert(node).second; } - void idaapi sub(int node) { erase(node); } - void idaapi sub(const node_set_t &r); - void idaapi add(const node_set_t &r); - void idaapi intersect(const node_set_t &r); - void idaapi extract(intvec_t &out) const; - int idaapi first(void) const { return empty() ? -1 : *begin(); } -}; - -typedef qvector array_of_node_set_t; - -//------------------------------------------------------------------------- -/// Node iterator (used to draw graphs) -class node_iterator -{ - DECLARE_HELPER(friend) - friend class gdl_graph_t; - const gdl_graph_t *g; - int i; - node_iterator &_goup(void); - node_iterator &goup(void) { return *node_iterator_goup(this); } -public: - node_iterator(const gdl_graph_t *_g, int n) : g(_g), i(n) {} - node_iterator &operator++(void) { i++; return goup(); } - bool operator==(const node_iterator &n) const { return i == n.i && g == n.g; } - bool operator!=(const node_iterator &n) const { return !(*this == n); } - int operator*(void) const { return i; } -}; - -//------------------------------------------------------------------------- -/// gdl graph interface - includes only functions required to draw it -class gdl_graph_t -{ - // does a path from 'm' to 'n' exist? - bool idaapi path(node_set_t &visited, int m, int n) const; -public: - DEFINE_MEMORY_ALLOCATION_FUNCS() - DEFINE_VIRTUAL_DTOR(gdl_graph_t) - virtual char *idaapi get_node_label(char *buf, int /*bufsize*/, int /*n*/) const { buf[0] = '\0'; return buf; } - virtual void idaapi print_graph_attributes(FILE * /*fp*/) const {} - virtual bool idaapi print_node(FILE * /*fp*/, int /*n*/) const { return false; } - virtual bool idaapi print_edge(FILE * /*fp*/, int /*i*/, int /*j*/) const { return false; } - virtual void idaapi print_node_attributes(FILE * /*fp*/, int /*n*/) const {} - virtual int idaapi size(void) const = 0; // number of the max node number - virtual int idaapi node_qty(void) const { return size(); } // number of alive nodes - virtual bool idaapi exists(int /*node*/) const { return true; } - virtual int idaapi entry(void) const { return 0; } - virtual int idaapi exit(void) const { return size()-1; } - virtual int idaapi nsucc(int node) const = 0; - virtual int idaapi npred(int node) const = 0; - virtual int idaapi succ(int node, int i) const = 0; - virtual int idaapi pred(int node, int i) const = 0; - virtual bool idaapi empty(void) const { return node_qty() == 0; } - virtual bgcolor_t idaapi get_node_color(int /*n*/) const { return DEFCOLOR; } - virtual bgcolor_t idaapi get_edge_color(int /*i*/, int /*j*/) const { return DEFCOLOR; } - void idaapi gen_gdl(FILE *fp) const; - void idaapi gen_gdl(const char *file) const; - size_t idaapi nedge(int node, bool ispred) const { return ispred ? npred(node) : nsucc(node); } - int idaapi edge(int node, int i, bool ispred) const { return ispred ? pred(node, i) : succ(node, i); } - int idaapi front(void) { return *begin(); } - node_iterator idaapi begin(void) const { return node_iterator(this, 0).goup(); } - node_iterator idaapi end(void) const { return node_iterator(this, size()); } - // does a path from 'm' to 'n' exist? - bool idaapi path_exists(int m, int n) const { node_set_t v; return path(v, m, n); } - - void idaapi gen_dot(FILE *fp) const; - void idaapi gen_dot(const char *file) const; -}; - - -/// Create GDL file for graph - -idaman void ida_export gen_gdl(const gdl_graph_t *g, const char *fname); - - -/// Display GDL file by calling wingraph32. -/// The exact name of the grapher is taken from the configuration file -/// and set up by setup_graph_subsystem(). -/// \return error code from os, 0 if ok - -idaman int ida_export display_gdl(const char *fname); - - -//------------------------------------------------------------------------- -// Build and display program graphs - -/// Build and display a flow graph. -/// \param filename output file name. the file extension is not used. maybe NULL. -/// \param title graph title -/// \param pfn function to graph -/// \param ea1, ea2 if pfn == NULL, then the address range -/// \param gflags combination of \ref CHART_1. -/// if none of #CHART_GEN_DOT, #CHART_GEN_GDL, #CHART_WINGRAPH -/// is specified, the function will return false -/// \return success. if fails, a warning message is displayed on the screen - -idaman bool ida_export gen_flow_graph( - const char *filename, - const char *title, - func_t *pfn, - ea_t ea1, - ea_t ea2, - int gflags); - -/// \defgroup CHART_1 Flow graph building flags -/// Passed as flags parameter to: -/// - gen_flow_graph() -/// - gen_simple_call_chart() -/// - gen_complex_call_chart() -//@{ -#define CHART_PRINT_NAMES 0x1000 ///< print labels for each block? -#define CHART_GEN_DOT 0x2000 ///< generate .dot file (file extension is forced to .dot) -#define CHART_GEN_GDL 0x4000 ///< generate .gdl file (file extension is forced to .gdl) -#define CHART_WINGRAPH 0x8000 ///< call grapher to display the graph -//@} - - -/// Build and display a simple function call graph. -/// \param filename output file name. the file extension is not used. maybe NULL. -/// \param wait message to display during graph building -/// \param title graph title -/// \param gflags combination of #CHART_NOLIBFUNCS and \ref CHART_1. -/// if none of #CHART_GEN_DOT, #CHART_GEN_GDL, #CHART_WINGRAPH -/// is specified, the function will return false. -/// \return success. if fails, a warning message is displayed on the screen - -idaman bool ida_export gen_simple_call_chart( - const char *filename, - const char *wait, - const char *title, - int gflags); - - -/// Build and display a complex xref graph. -/// \param filename output file name. the file extension is not used. maybe NULL. -/// \param wait message to display during graph building -/// \param title graph title -/// \param ea1, ea2 address range -/// \param flags combination of \ref CHART_2 and \ref CHART_1. -/// if none of #CHART_GEN_DOT, #CHART_GEN_GDL, #CHART_WINGRAPH -/// is specified, the function will return false. -/// \param recursion_depth optional limit of recursion -/// \return success. if fails, a warning message is displayed on the screen - -idaman bool ida_export gen_complex_call_chart( - const char *filename, - const char *wait, - const char *title, - ea_t ea1, - ea_t ea2, - int flags, - int32 recursion_depth=-1); - -/// \defgroup CHART_2 Call chart building flags -/// Passed as flags parameter to gen_complex_call_chart() -//@{ -#define CHART_NOLIBFUNCS 0x0400 ///< don't include library functions in the graph -#define CHART_REFERENCING 0x0001 ///< references to the addresses in the list -#define CHART_REFERENCED 0x0002 ///< references from the addresses in the list -#define CHART_RECURSIVE 0x0004 ///< analyze added blocks -#define CHART_FOLLOW_DIRECTION 0x0008 ///< analyze references to added blocks only in the direction of the reference who discovered the current block -#define CHART_IGNORE_XTRN 0x0010 -#define CHART_IGNORE_DATA_BSS 0x0020 -#define CHART_IGNORE_LIB_TO 0x0040 ///< ignore references to library functions -#define CHART_IGNORE_LIB_FROM 0x0080 ///< ignore references from library functions -#define CHART_PRINT_COMMENTS 0x0100 -#define CHART_PRINT_DOTS 0x0200 ///< print dots if xrefs exist outside of the range recursion depth -//@} - - -/// Setup the user-defined graph colors and graph viewer program. -/// This function is called by the GUI at the beginning, so no need to call -/// it again. - -idaman void ida_export setup_graph_subsystem(const char *_grapher, bgcolor_t (idaapi *get_graph_color)(int color)); - - -//-V:cancellable_graph_t:730 not all members of a class are initialized inside the constructor -class cancellable_graph_t : public gdl_graph_t -{ -public: - mutable bool cancelled; - char padding[3]; // make the class nicely aligned. otherwise we have problems - // with gcc in qflow_chart_t. - cancellable_graph_t(void) : cancelled(false) {} - DEFINE_VIRTUAL_DTOR(cancellable_graph_t) - bool idaapi check_cancel(void) const; -}; - -//-------------------------------------------------------------------------- -/// Information about a basic block of a \ref qflow_chart_t -struct qbasic_block_t : public range_t -{ - intvec_t succ; ///< list of node successors - intvec_t pred; ///< list of node predecessors -}; - -/// Does this block never return? -inline THREAD_SAFE bool is_noret_block(fc_block_type_t btype) -{ - return btype == fcb_noret || btype == fcb_enoret; -} - -/// Does this block return? -inline THREAD_SAFE bool is_ret_block(fc_block_type_t btype) -{ - return btype == fcb_ret || btype == fcb_cndret; -} - -/// \defgroup FC_ Flow chart flags -/// Passed as 'flags' parameter to qflow_chart_t -//@{ -#define FC_PRINT 0x0001 ///< print names (used only by display_flow_chart()) -#define FC_NOEXT 0x0002 ///< do not compute external blocks. Use this to prevent jumps leaving the - ///< function from appearing in the flow chart. Unless specified, the - ///< targets of those outgoing jumps will be present in the flow - ///< chart under the form of one-instruction blocks -#define FC_RESERVED 0x0004 // former FC_PREDS -#define FC_APPND 0x0008 ///< multirange flowchart (set by append_to_flowchart) -#define FC_CHKBREAK 0x0010 ///< build_qflow_chart() may be aborted by user -#define FC_CALL_ENDS 0x0020 ///< call instructions terminate basic blocks -#define FC_NOPREDS 0x0040 ///< do not compute predecessor lists -//@} - -/// A flow chart for a function, or a set of address ranges -class qflow_chart_t : public cancellable_graph_t -{ -public: - typedef qvector blocks_t; - DECLARE_HELPER(friend) - qstring title; - range_t bounds; ///< overall bounds of the qflow_chart_t instance - func_t *pfn = nullptr; ///< the function this instance was built upon - int flags = 0; ///< flags. See \ref FC_ - blocks_t blocks; ///< basic blocks - int nproper = 0; ///< number of basic blocks belonging to the specified range - - idaapi qflow_chart_t(void) {} - idaapi qflow_chart_t(const char *_title, func_t *_pfn, ea_t _ea1, ea_t _ea2, int _flags) - : title(_title), bounds(_ea1, _ea2), pfn(_pfn), flags(_flags) - { - refresh(); - } - DEFINE_VIRTUAL_DTOR(qflow_chart_t) - void idaapi create(const char *_title, func_t *_pfn, ea_t _ea1, ea_t _ea2, int _flags) - { - title = _title; - pfn = _pfn; - bounds = range_t(_ea1, _ea2); - flags = _flags; - refresh(); - } - void idaapi create(const char *_title, const rangevec_t &ranges, int _flags) - { - title = _title; - flags = _flags; - create_multirange_qflow_chart(*this, ranges); - } - void idaapi append_to_flowchart(ea_t ea1, ea_t ea2) { ::append_to_flowchart(*this, ea1, ea2); } - void idaapi refresh(void) { create_qflow_chart(*this); } - fc_block_type_t calc_block_type(size_t blknum) const - { return fc_calc_block_type(*this, blknum); } - bool is_ret_block(size_t blknum) const { return ::is_ret_block(calc_block_type(blknum)); } - bool is_noret_block(size_t blknum) const { return ::is_noret_block(calc_block_type(blknum)); } - virtual void idaapi print_node_attributes(FILE * /*fp*/, int /*n*/) const override {} - virtual int idaapi nsucc(int node) const override { return int(blocks[node].succ.size()); } - virtual int idaapi npred(int node) const override { return int(blocks[node].pred.size()); } - virtual int idaapi succ(int node, int i) const override { return blocks[node].succ[i]; } - virtual int idaapi pred(int node, int i) const override { return blocks[node].pred[i]; } - virtual char *idaapi get_node_label(char * /*buf*/, int /*bufsize*/, int /*n*/) const override { return NULL; } - virtual int idaapi size(void) const override { return int(blocks.size()); } - bool idaapi print_names(void) const { return (flags & FC_PRINT) != 0; } -}; - -#endif // __GDLDRAW_HPP diff --git a/idasdk75/include/graph.hpp b/idasdk75/include/graph.hpp deleted file mode 100644 index 4c1f6a3..0000000 --- a/idasdk75/include/graph.hpp +++ /dev/null @@ -1,1511 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * Graph type definitions - * - * Due to the use of STL and virtual functions, some parts of this - * interface might be incompatible with compilers other than Visual Studio - * on Windows and gcc on Unix systems - */ - -#ifndef __GRAPH_DEF_HPP -#define __GRAPH_DEF_HPP - -#include -#include -#include -#include -#include - -/*! \file graph.hpp - - \brief Graph view management - -*/ - -class func_t; -class abstract_graph_t; - -//------------------------------------------------------------------------- -/// \defgroup NIF_ Node info flags -/// Passed as 'flags' parameter to set_node_info(). -/// Also see node_info_t::get_flags_for_valid(). -//@{ -#define NIF_BG_COLOR (1 << 0) ///< node_info_t::bg_color -#define NIF_FRAME_COLOR (1 << 1) ///< node_info_t::frame_color -#define NIF_EA (1 << 2) ///< node_info_t::ea -#define NIF_TEXT (1 << 3) ///< node_info_t::text -#define NIF_FLAGS (1 << 4) ///< node_info_t::flags -#define NIF_ALL (NIF_BG_COLOR | NIF_FRAME_COLOR | NIF_EA | NIF_TEXT | NIF_FLAGS) -//@} - -//------------------------------------------------------------------------- -/// \defgroup GLICTL_ graph_location_info_t control flags -/// Passed as 'flags' parameter to viewer_set_gli() and viewer_get_gli(). -//@{ -#define GLICTL_CENTER (1 << 0) ///< the gli should be set/get as center -//@} - -/// Information about a node in a graph -struct node_info_t -{ -private: - size_t cb; ///< size of this structure -public: - node_info_t() - : cb(sizeof(*this)), - bg_color(DEFCOLOR), - frame_color(DEFCOLOR), - flags(0), - ea(BADADDR) {} - bgcolor_t bg_color; ///< background color - bgcolor_t frame_color; ///< color of enclosing frame -#define NIFF_SHOW_CONTENTS (1 << 0) // force show contents of huge node - uint32 flags; ///< flags - ea_t ea; ///< address - qstring text; ///< node contents - - /// Has valid #bg_color? - inline bool valid_bg_color() const { return bg_color != DEFCOLOR; } - /// Has valid #frame_color? - inline bool valid_frame_color() const { return frame_color != DEFCOLOR; } - /// Has valid #ea? - inline bool valid_ea() const { return ea != BADADDR; } - /// Has non-empty #text? - inline bool valid_text() const { return !text.empty(); } - /// Has valid #flags? - inline bool valid_flags() const { return flags != 0; } - - /// Get combination of \ref NIF_ describing which attributes are valid - inline uint32 get_flags_for_valid() const - { - uint32 F = 0; - if ( valid_bg_color() ) - F |= NIF_BG_COLOR; - if ( valid_frame_color() ) - F |= NIF_FRAME_COLOR; - if ( valid_ea() ) - F |= NIF_EA; - if ( valid_text() ) - F |= NIF_TEXT; - if ( valid_flags() ) - F |= NIF_FLAGS; - return F; - } -}; - -/// Graph instances have a unique id (see mutable_graph_t::gid) -typedef ea_t graph_id_t; - - -/// Get node info. -/// \param out result -/// \param gid id of desired graph -/// \param node node number -/// \return success - -idaman bool ida_export get_node_info(node_info_t *out, graph_id_t gid, int node); - - -/// Set node info. -/// \param gid id of desired graph -/// \param node node number -/// \param ni node info to use -/// \param flags combination of \ref NIF_, -/// identifying which fields of 'ni' will be used - -idaman void ida_export set_node_info(graph_id_t gid, int node, const node_info_t &ni, uint32 flags); - - -/// Delete the ::node_info_t for the given node - -idaman void ida_export del_node_info(graph_id_t gid, int node); - - -/// Clear node info for the given node. -/// \param gid id of desired graph -/// \param node node number -/// \param flags combination of \ref NIF_, -/// identifying which fields of ::node_info_t -/// will be cleared - -idaman void ida_export clr_node_info(graph_id_t gid, int node, uint32 flags); - - -//------------------------------------------------------------------------- -/// Node ordering in a graph. -/// Maps a node number to a number describing its -/// order in the graph (and vice versa). -class node_ordering_t -{ - intvec_t node_by_order; ///< ordered sequence of node numbers - intvec_t order_by_node; ///< node number => index in #node_by_order -public: - DEFINE_MEMORY_ALLOCATION_FUNCS() - void idaapi clear(void) - { - node_by_order.clear(); - order_by_node.clear(); - } - void idaapi resize(int n) - { - clear(); - node_by_order.resize(n, -1); - } - size_t idaapi size(void) const { return node_by_order.size(); } - void idaapi set(int _node, int num) - { - node_by_order[num] = _node; - if ( !order_by_node.empty() ) - order_by_node[_node] = num; - } - bool idaapi clr(int _node); - int idaapi node(size_t _order) const { return size() > _order ? node_by_order[_order] : -1; } - int idaapi order(int _node); -}; - -//------------------------------------------------------------------------- -/// Edge connecting two graph nodes -struct edge_t -{ - int src; ///< source node number - int dst; ///< destination node number - idaapi edge_t(void) : src(0), dst(0) {} - idaapi edge_t(int x, int y) : src(x), dst(y) {} - bool idaapi operator < (const edge_t &y) const - { return src < y.src || (src == y.src && dst < y.dst); } - bool idaapi operator == (const edge_t &y) const - { return src == y.src && dst == y.dst; } - bool idaapi operator != (const edge_t &y) const - { return src != y.src || dst != y.dst; } -}; -DECLARE_TYPE_AS_MOVABLE(edge_t); - -typedef qvector edgevec_t; ///< vector of graph edges -struct edgeset_t; -struct edge_segs_vec_t; -struct edge_infos_t; -struct destset_t; - -enum edge_type_t -{ - edge_error = 0, - edge_tree = 1, - edge_forward = 2, - edge_back = 3, - edge_cross = 4, - edge_subgraph = 5 // edge of a subgraph (used in collapse) -}; - -//------------------------------------------------------------------------- -class edge_typer_t; - -//------------------------------------------------------------------------- -/// Node visitor - see abstract_graph_t::visit_nodes() -class graph_node_visitor_t -{ - node_set_t visited; ///< set of previously visited nodes -public: - /// Reset visited nodes - void idaapi reinit(void) { visited.clear(); } - /// Mark node as visited - void idaapi set_visited(int n) { visited.add(n); } - /// Have we already visited the given node? - bool idaapi is_visited(int n) const { return visited.has(n); } - - /// Implements action to take when a node is visited - virtual int idaapi visit_node(int /*node*/) { return 0; } - /// Should the edge between 'n' and 'm' be ignored? - virtual bool idaapi is_forbidden_edge(int /*n*/, int /*m*/) const { return false; } - - DEFINE_VIRTUAL_DTOR(graph_node_visitor_t) -}; - -//------------------------------------------------------------------------- -/// Path visitor - see abstract_graph_t::visit_paths() -struct graph_path_visitor_t -{ - intvec_t path; ///< current path - bool prune; ///< walk_forward(): prune := true - ///< means to stop the current path - - - virtual int idaapi walk_forward(int /*node*/) { return 0; } - virtual int idaapi walk_backward(int /*node*/) { return 0; } - - DEFINE_VIRTUAL_DTOR(graph_path_visitor_t) -}; - -//------------------------------------------------------------------------- -/// Coordinate in a graph view -struct point_t -{ - int x, y; - point_t(void) : x(0), y(0) {} - point_t(int _x, int _y) : x(_x), y(_y) {} - point_t &add(const point_t &r) - { - x += r.x; - y += r.y; - return *this; - } - point_t &sub(const point_t &r) - { - x -= r.x; - y -= r.y; - return *this; - } - template void div(T d) - { - x /= d; - y /= d; - } - void negate(void) - { - x = -x; - y = -y; - } -#ifdef VCL_H - point_t(const TPoint &p) : x(p.x), y(p.y) {} -#endif - bool operator ==(const point_t &r) const { return x == r.x && y == r.y; } - bool operator !=(const point_t &r) const { return !(*this == r); } - const char *idaapi dstr(void) const; - size_t idaapi print(char *buf, size_t bufsize) const; -}; -DECLARE_TYPE_AS_MOVABLE(point_t); -typedef qvector pointvec_t; - -/// Calculate distance between p and q -inline THREAD_SAFE double calc_dist(point_t p, point_t q) -{ - double dx = q.x - p.x; - double dy = q.y - p.y; - return sqrt(dx*dx+dy*dy); -} - -/// Ordered sequence of points -class pointseq_t : public pointvec_t -{ -public: - const char *idaapi dstr(void) const; - size_t idaapi print(char *buf, size_t bufsize) const; -}; - -/// A rectangle in a graph view -struct rect_t -{ - int left; - int top; - int right; - int bottom; - rect_t(void) : left(0), top(0), right(0), bottom(0) {} - rect_t(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} - rect_t(const point_t &p0, const point_t &p1) - : left (qmin(p0.x, p1.x)), - top (qmin(p0.y, p1.y)), - right (qmax(p0.x, p1.x)), - bottom(qmax(p0.y, p1.y)) {} - int width(void) const { return right - left; } - int height(void) const { return bottom - top; } - void move_to(const point_t &p) - { - int dx = p.x - left; - int dy = p.y - top; - move_by(point_t(dx, dy)); - } - void move_by(const point_t &p) - { - left += p.x; - right += p.x; - top += p.y; - bottom += p.y; - } - point_t center(void) const - { - return point_t((left+right)/2, (top+bottom)/2); - } - point_t topleft(void) const - { - return point_t(left, top); - } - point_t bottomright(void) const - { - return point_t(right, bottom); - } - void grow(int delta) - { - left -= delta; - right += delta; - top -= delta; - bottom += delta; - } - void intersect(const rect_t &r) - { - if ( left < r.left ) - left = r.left; - if ( right > r.right ) - right = r.right; - if ( top < r.top ) - top = r.top; - if ( bottom > r.bottom ) - bottom = r.bottom; - } - void make_union(const rect_t &r) - { - if ( left > r.left ) - left = r.left; - if ( right < r.right ) - right = r.right; - if ( top > r.top ) - top = r.top; - if ( bottom < r.bottom ) - bottom = r.bottom; - } - bool empty(void) const - { - return left >= right || top >= bottom; - } - bool is_intersection_empty(const rect_t &r) const - { - return left >= r.right - || right <= r.left - || top >= r.bottom - || bottom <= r.top; - } - bool contains(const point_t &p) const - { - return left <= p.x - && right > p.x - && top <= p.y - && bottom > p.y; - } - int area(void) const { return width()*height(); } - bool idaapi operator == (const rect_t &r) const - { - return left == r.left - && right == r.right - && top == r.top - && bottom == r.bottom; - } - bool idaapi operator != (const rect_t &r) const { return !(*this == r); } - bool idaapi operator < (const rect_t &r) const; -#ifdef VCL_H - const TRect &operator()(void) const { return *(TRect *)this; } - TRect &operator()(void) { return *(TRect *)this; } - rect_t(const TRect &r) : left(r.left), top(r.top), right(r.right), bottom(r.bottom) {} -#endif -}; -DECLARE_TYPE_AS_MOVABLE(rect_t); - -//--------------------------------------------------------------------------- -/// Coordinate in a graph view (double precision) -struct TPointDouble -{ - double x, y; - TPointDouble(void) : x(0.0), y(0.0) {} - TPointDouble(double a, double b) : x(a), y(b) {} - TPointDouble(const point_t &r) : x(r.x), y(r.y) {} - void add(const TPointDouble &r) - { - x += r.x; - y += r.y; - } - void sub(const TPointDouble &r) - { - x -= r.x; - y -= r.y; - } - void negate(void) - { - x = -x; - y = -y; - } - template void div(T d) - { - x /= d; - y /= d; - } - bool operator ==(const TPointDouble &r) const { return x == r.x && y == r.y; } //-V550 An odd precise comparison: x == r.x - bool operator !=(const TPointDouble &r) const { return !(*this == r); } -}; - -//--------------------------------------------------------------------------- -typedef int layout_type_t; ///< see \ref layout_ -/// \defgroup layout_ Proximity view layouts -//@{ -const layout_type_t - layout_none = 0, - layout_digraph = 1, - layout_tree = 2, - layout_circle = 3, - layout_polar_tree = 4, - layout_orthogonal = 5, - layout_radial_tree = 6; -//@} - -/// Attributes of a graph edge -struct edge_info_t -{ - bgcolor_t color; ///< edge color - int width; ///< edge width - int srcoff; ///< source: edge port offset from the left - int dstoff; ///< destination: edge port offset from the left - pointseq_t layout; ///< describes geometry of edge -#if !defined(_MSC_VER) || _MSC_VER >= 1600 - void idaapi reverse_layout(void) { std::reverse(layout.begin(), layout.end()); } -#endif - void idaapi add_layout_point(point_t p); - idaapi edge_info_t(void) : color(DEFCOLOR), width(1), srcoff(-1), dstoff(-1) {} -}; - -/// Edge layout point -//-V:edge_layout_point_t:690 lacks the '=' operator -struct edge_layout_point_t -{ - int pidx; ///< index into edge_info_t::layout - edge_t e; ///< parent edge - idaapi edge_layout_point_t(void) : pidx(-1), e(-1, -1) {} - idaapi edge_layout_point_t(const edge_layout_point_t &r) : pidx(r.pidx), e(r.e) {} - idaapi edge_layout_point_t(const edge_t &_e, int _pidx) : pidx(_pidx), e(_e) {} - int idaapi compare(const edge_layout_point_t &r) const - { - if ( e < r.e ) - return -1; - if ( r.e < e ) - return 1; - return ::compare(pidx, r.pidx); - } - bool idaapi operator == (const edge_layout_point_t &r) const - { - return pidx == r.pidx && e == r.e; - } - bool idaapi operator != (const edge_layout_point_t &r) const - { - return !(*this == r); - } -}; - -/// Element of a graph selection - could be a node or edge layout point. -/// See ::screen_graph_selection_t. -struct selection_item_t -{ - bool is_node; ///< represents a selected node? - int node; ///< node number (is_node = true) - edge_layout_point_t elp; ///< edge layout point (is_node = false) - idaapi selection_item_t(void) : is_node(false), node(-1) {} - idaapi selection_item_t(int n) : is_node(true), node(n) {} - idaapi selection_item_t(edge_layout_point_t &_elp) - : is_node(false), node(-1), elp(_elp) {} - idaapi selection_item_t(edge_t e, int idx) - : is_node(false), node(-1), elp(e, idx) {} - idaapi selection_item_t(class graph_item_t &); - int idaapi compare(const selection_item_t &r) const - { - if ( is_node != r.is_node ) - return is_node - r.is_node; - if ( is_node ) - return ::compare(node, r.node); - return elp.compare(r.elp); - } - bool idaapi operator == (const selection_item_t &r) const - { return compare(r) == 0; } - bool idaapi operator != (const selection_item_t &r) const - { return compare(r) != 0; } - bool idaapi operator < (const selection_item_t &r) const - { return compare(r) < 0; } -}; - - -/// Selection in a graph. -/// (A list of nodes and edge layout points). -/// This selection is used to move a subgraph on the screen. -typedef qvector screen_graph_selection_base_t; - -struct screen_graph_selection_t : public screen_graph_selection_base_t -{ - bool idaapi has(const selection_item_t &item) const - { return (const_iterator)find(item) != end(); } - void idaapi add(const screen_graph_selection_t &s) - { - for ( screen_graph_selection_t::const_iterator p=s.begin(); p != s.end(); ++p ) - add_unique(*p); - } - void idaapi sub(const screen_graph_selection_t &s) - { - for ( screen_graph_selection_t::const_iterator p=s.begin(); p != s.end(); ++p ) - del(*p); - } - void idaapi add_node(int node) { add_unique(selection_item_t(node)); } - void idaapi del_node(int node) { del(selection_item_t(node)); } - void idaapi add_point(edge_t e, int idx) { add_unique(selection_item_t(e, idx)); } - void idaapi del_point(edge_t e, int idx) { del(selection_item_t(e, idx)); } - - size_t idaapi nodes_count() const { return items_count(true); } - size_t idaapi points_count() const { return items_count(false); } - size_t idaapi items_count(bool look_for_nodes) const - { - size_t cnt = 0; - for ( size_t i = 0, sz = size(); i < sz; ++i ) - if ( at(i).is_node == look_for_nodes ) - ++cnt; - return cnt; - } -}; - -/// Sub-segment of a graph edge -struct edge_segment_t -{ - edge_t e; - int nseg; - int x0, x1; - size_t idaapi length(void) const { return abs(x1-x0); } - bool idaapi toright(void) const { return x1 > x0; } // horizontal segment to the right - bool idaapi operator < (const edge_segment_t &r) const - { - return e < r.e; -/* // longest edges first - int ll = x1 - x0; if ( ll < 0 ) ll = -ll; - int rl = r.x1 - r.x0; if ( rl < 0 ) rl = -rl; - if ( rl < ll ) - return true; - if ( rl == ll ) - return e < r.e; - return false;*/ - } -}; - -//--------------------------------------------------------------------------- -/// See ::graph_item_t -enum graph_item_type_t -{ // valid graph_item_t fields: - git_none, ///< nothing - git_edge, ///< edge (graph_item_t::e, graph_item_t::n. n is farthest edge endpoint) - git_node, ///< node title (graph_item_t::n) - git_tool, ///< node title button (graph_item_t::n, graph_item_t::b) - git_text, ///< node text (graph_item_t::n, graph_item_t::p) - git_elp, ///< edge layout point (graph_item_t::elp) -}; - -/// Describes a sub-item of a graph -class graph_item_t -{ -public: - graph_item_type_t type; ///< type - edge_t e; ///< edge source and destination - int n; ///< node number - int b; ///< button number - point_t p; ///< text coordinates in the node - edge_layout_point_t elp; ///< edge layout point - bool operator == (const graph_item_t &r) const; - bool is_node(void) const { return type >= git_node && type <= git_text; } - bool is_edge(void) const { return type == git_edge || type == git_elp; } -}; - -//------------------------------------------------------------------------- -/// One dimensional range -struct interval_t -{ - int x0, x1; // x0 always <= x1, otherwise the interval is empty - bool empty(void) const { return x0 < x1; } - void intersect(const interval_t &r) - { - if ( x0 < r.x0 ) - x0 = r.x0; - if ( x1 > r.x1 ) - x1 = r.x1; - } - void make_union(const interval_t &r) - { - if ( x0 > r.x0 ) - x0 = r.x0; - if ( x1 < r.x1 ) - x1 = r.x1; - } - void move_by(int shift) - { - x0 += shift; - x1 += shift; - } - interval_t(void) : x0(0), x1(0) {} - interval_t(int y0, int y1) - { - x0 = qmin(y0, y1); - x1 = qmax(y0, y1); - } - interval_t(const edge_segment_t &s) - { - x0 = qmin(s.x0, s.x1); - x1 = qmax(s.x0, s.x1); - } - int length(void) const { return x1 - x0; } - bool contains(int x) const { return x0 <= x && x <= x1; } - bool operator ==(const interval_t &r) const { return x0 == r.x0 && x1 == r.x1; } - bool operator !=(const interval_t &r) const { return !(*this == r); } -}; - -//------------------------------------------------------------------------- -/// Organize graph nodes by row -struct row_info_t -{ - intvec_t nodes; ///< list of nodes at the row - int top; ///< top y coord of the row - int bottom; ///< bottom y coord of the row - int height(void) const { return bottom - top; } - row_info_t(void) : top(0), bottom(0) {} -}; -typedef qvector graph_row_info_t; ///< vector of row infos - -static const int ygap = 30; -static const int xgap = 10; -static const int arrow_height = 10; -static const int arrow_width = 8; - -struct graph_location_info_t; -class graph_visitor_t; - -//------------------------------------------------------------------------- -/// Abstract graph interface -class abstract_graph_t : public gdl_graph_t -{ - void idaapi find_entries(node_set_t &entries) const; - void idaapi depth_first(int root, struct depth_first_info_t &di) const; - size_t idaapi remove_reachable(int n, node_set_t *s) const; - int idaapi longest_path(int n, intvec_t &tops, int row_height) const; - size_t idaapi sort_layer_nodes( - const row_info_t &r1, - const intmap_t &lpi1, - row_info_t &r2, - intmap_t &lpi2, - bool ispred) const; - size_t idaapi calc_cross_num( - const intvec_t &r1, - const intvec_t &r2, - const intmap_t &lpi1, - bool ispred) const; - size_t idaapi num_crossings(const graph_row_info_t &gri, const array_of_intmap_t &nodepi) const; - int idaapi calc_x_coord(const row_info_t &ri, int idx, bool ispred, int first_added_node) const; - void idaapi try_move_down(intvec_t &tops, int n, int row_height) const; - -protected: - /// Returns one entry point for each connected component - void idaapi get_connected_components(intvec_t &entries) const; - - /// Find longest paths from the entries. take into account node heights. - /// if row_height > 0, then use it instead of real node heights. - /// return max distance found - int idaapi calc_longest_pathes( - const node_set_t &entries, - intvec_t &tops, - int row_height) const; - - /// Move entry nodes down as much as possible - void idaapi move_nodes_down( - intvec_t &tops, - const node_ordering_t &post, - int first_reverser_node, - int row_height) const; - - /// Create graph row info from 'tops' - void idaapi create_graph_row_info( - const intvec_t &tops, - graph_row_info_t &gri, - int graph_height) const; - - /// Calculate height of each row - void idaapi calc_row_heights(graph_row_info_t &gri) const; - - /// Minimize crossings - void idaapi minimize_crossings(graph_row_info_t &gri) const; - - /// Calculate x coords of all nodes - void idaapi set_x_coords( - const graph_row_info_t &gri, - const node_set_t &selfrefs, - int first_added_node); - - /// Gather information about all edge segments - void idaapi gather_edge_segments( - const graph_row_info_t &gri, - edge_segs_vec_t &ges) const; - - /// Make all edges rectangular - void idaapi make_rect_edges( - graph_row_info_t &gri, - const edge_segs_vec_t &ges, - int first_reverser_node); - - /// Assign ports to edges - void idaapi assign_edge_ports( - const graph_row_info_t &gri, - const node_set_t &selfrefs); - - /// Recalculate width of all edges - void idaapi recalc_edge_widths( - const edgeset_t &back_edges, - const edge_infos_t &self_edges); - - /// Clear layout information in the graph - void idaapi clear_layout_info(void); - - void idaapi depth_first( - node_ordering_t *pre, - node_ordering_t *post, - edge_typer_t *et) const; - - void idaapi create_spanning_tree( - edge_typer_t *et, - node_set_t *entries, - edgeset_t *back_edges, - node_ordering_t *pre, - node_ordering_t *post) const; - - void idaapi tree_layout(edge_typer_t &et, const node_set_t &entries); - - /// Is there a path from M to N which terminates with a back edge to N? - bool idaapi path_back(const array_of_node_set_t &domin, int m, int n) const; - bool idaapi path_back(edge_typer_t &et, int m, int n) const; - - /// Visit nodes starting from 'node', depth first - int idaapi visit_nodes(int node, graph_node_visitor_t &gv) const; - - /// Visit all possible paths starting from 'node'. - /// A path cannot contain the same node twice. - int idaapi visit_paths(int node, graph_path_visitor_t &gv) const; - -public: - qstring title; ///< graph title - bool rect_edges_made; ///< have create rectangular edges? - layout_type_t current_layout; ///< see \ref layout_ - point_t circle_center; ///< for layout_circle - int circle_radius; ///< for layout_circle - hook_cb_t *callback; ///< user-defined callback - void *callback_ud; ///< user data for #callback - - idaapi abstract_graph_t(void) - : rect_edges_made(false), - current_layout(layout_none), - circle_radius(0), - callback(NULL), - callback_ud(NULL) - {} - DEFINE_VIRTUAL_DTOR(abstract_graph_t) - void idaapi clear(void); - void idaapi dump_graph(const char *header) const; - bool idaapi calc_bounds(rect_t *r); - void idaapi calc_fitting_params( - const rect_t &area, - const rect_t &r, - graph_location_info_t *gli, - double max_zoom); - bool idaapi calc_fitting_params( - const rect_t &area, - graph_location_info_t *gli, - double max_zoom); - int idaapi for_all_nodes_edges(graph_visitor_t &nev, bool visit_nodes=true); - // get edge ports - fills s, d arguments and returns edge_info_t - const edge_info_t *idaapi get_edge_ports( - edge_t e, - point_t &s, - point_t &d) const; - // add edges from/to the node - void idaapi add_node_edges(edgevec_t &dlist, int node); - const rect_t &idaapi nrect(int n) const - { return (CONST_CAST(abstract_graph_t *)(this))->nrect(n); } - const edge_info_t *idaapi get_edge(edge_t e) const - { return (CONST_CAST(abstract_graph_t *)(this))->get_edge(e); } - virtual rect_t &idaapi nrect(int n) = 0; - virtual edge_info_t *idaapi get_edge(edge_t e) = 0; - virtual abstract_graph_t *idaapi clone(void) const = 0; - - bool idaapi create_tree_layout(void); - bool idaapi create_circle_layout(point_t p, int radius); - bool idaapi create_polar_tree_layout(point_t p, int radius); - bool idaapi create_radial_tree_layout(point_t p, int radius); - bool idaapi create_orthogonal_layout(void); - - void set_callback(hook_cb_t *_callback, void *_ud) - { - callback = _callback; - callback_ud = _ud; - } - ssize_t vgrcall(int code, va_list va) - { - if ( callback != NULL ) - return callback(callback_ud, code, va); - return 0; - } - ssize_t grcall(int code, ...) - { - va_list va; - va_start(va, code); - ssize_t result = vgrcall(code, va); - va_end(va); - return result; - } -}; - -/// For some reason GCC insists on putting the vtable into object files, -/// even though we only use ::mutable_graph_t by pointer. -/// This looks like a linker bug. We fix it by declaring functions as pure virtual -/// when plugins are compiled. -#if defined(__GNUC__) && (defined(__KERNEL__) || !defined(__UI__)) // compiling a plugin or the kernel with gcc? -#define GCC_PUREVIRT = 0 -#else -#define GCC_PUREVIRT -#endif - -//------------------------------------------------------------------------- -struct edge_infos_wrapper_t -{ - edge_infos_wrapper_t(); - edge_infos_wrapper_t(const edge_infos_wrapper_t &other); - edge_infos_wrapper_t &idaapi operator=(const edge_infos_wrapper_t &other); - ~edge_infos_wrapper_t() { clear(); } - void clear(); - - edge_infos_t *ptr; -}; - -#ifdef _DEBUG -#define CHKNODEIDX(n) QASSERT(1385, int(n) >= 0) -#else -#define CHKNODEIDX(n) -#endif - -//------------------------------------------------------------------------- -/// Base class used by graphs in IDA -class mutable_graph_t : public abstract_graph_t -{ - typedef abstract_graph_t inherited; - friend ssize_t idaapi graph_dispatcher(void *, int code, va_list va); - int idaapi _find_subgraph_node(int group, int n) const; - void idaapi collapse_edges(const intvec_t &nodes, int group); - void idaapi del_node_keep_edges(int n); - void idaapi add_dest(destset_t &ne, edge_t e, int g); - void idaapi reverse_edges( - const edgeset_t &back_edges, - edge_infos_t &self_edges, - node_set_t &entries); - void idaapi layout_self_reference_edges(const edge_infos_t &selfrefs); - void idaapi restore_edges(int first_reserver_node, bool failed); - - void idaapi add_layer_nodes(graph_row_info_t &gri, intvec_t &tops); - void idaapi del_layer_nodes(graph_row_info_t &gri, int first_added_node); - void idaapi fix_collapsed_group_edges(void); - -public: - uval_t gid; ///< graph id - unique for the database - ///< for flowcharts it is equal to the function start_ea - intvec_t belongs; ///< the subgraph the node belongs to - ///< INT_MAX means that the node doesn't exist - ///< sign bit means collapsed node - bytevec_t node_flags; ///< node flags -#define MTG_GROUP_NODE 0x01 ///< is group node? -#define MTG_DOT_NODE 0x02 ///< is dot node? -#define MTG_NON_DISPLAYABLE_NODE 0x08 ///< for disassembly graphs - non-displayable nodes have a visible - ///< area that is too large to generate disassembly lines for without - ///< IDA slowing down significantly (see MAX_VISIBLE_NODE_AREA) - - // groups: original edges without considering any group info - array_of_intvec_t org_succs; - array_of_intvec_t org_preds; - - array_of_intvec_t succs; - array_of_intvec_t preds; - typedef qvector node_layout_t; - node_layout_t nodes; - edge_infos_wrapper_t edges; - - idaapi mutable_graph_t(uval_t id); - idaapi mutable_graph_t(const abstract_graph_t &g, uval_t id); - DEFINE_VIRTUAL_DTOR(mutable_graph_t); - virtual int idaapi size(void) const override { return int(succs.size()); } - virtual int idaapi node_qty(void) const override; - void idaapi clear(void); - virtual bool idaapi empty(void) const override; - virtual bool idaapi exists(int node) const override { return is_visible_node(node); } -#define COLLAPSED_NODE 0x80000000 - int idaapi get_node_representative(int node); - int idaapi get_node_group(int node) const { CHKNODEIDX(node); return (belongs[node] & ~COLLAPSED_NODE); } - void idaapi set_node_group(int node, int group) { CHKNODEIDX(node); belongs[node] = group | (belongs[node] & COLLAPSED_NODE); } - bool idaapi is_deleted_node(int node) const { CHKNODEIDX(node); return belongs[node] == INT_MAX; } - void idaapi set_deleted_node(int node) { CHKNODEIDX(node); belongs[node] = INT_MAX; } - bool idaapi is_subgraph_node(int node) const { return get_node_group(node) != node; } - bool idaapi is_dot_node(int node) const { CHKNODEIDX(node); return (node_flags[node] & MTG_DOT_NODE) != 0; } - bool idaapi is_group_node(int node) const { CHKNODEIDX(node); return (node_flags[node] & MTG_GROUP_NODE) != 0; } - bool idaapi is_displayable_node(int node) const { CHKNODEIDX(node); return (node_flags[node] & MTG_NON_DISPLAYABLE_NODE) == 0; } - bool idaapi is_simple_node(int node) const { return !is_group_node(node); } - bool idaapi is_collapsed_node(int node) const { CHKNODEIDX(node); return (belongs[node] & COLLAPSED_NODE) != 0; } - bool idaapi is_uncollapsed_node(int node) const { return is_group_node(node) && !is_collapsed_node(node); } - bool idaapi is_visible_node(int node) const; - bool idaapi groups_are_present(void) const; - // iterate subgraph nodes, return -1 at the end - int idaapi get_first_subgraph_node(int group) const { return _find_subgraph_node(group, 0); } - int idaapi get_next_subgraph_node(int group, int current) const { return _find_subgraph_node(group, current+1); } - void idaapi insert_visible_nodes(intvec_t &nodes, int group) const; - void idaapi insert_simple_nodes(intvec_t &nodes, int group) const; - bool idaapi check_new_group(const intvec_t &nodes, intvec_t &refined); - int idaapi create_group(const intvec_t &nodes); // -1 - error - bool idaapi delete_group(int group); - bool idaapi change_group_visibility(int group, bool expand); - bool idaapi change_visibility(const intvec_t &nodes, bool expand); - virtual int idaapi nsucc(int b) const override { CHKNODEIDX(b); return (int)succs[b].size(); } - virtual int idaapi npred(int b) const override { CHKNODEIDX(b); return (int)preds[b].size(); } - virtual int idaapi succ(int b, int i) const override { CHKNODEIDX(b); return succs[b][i]; } - virtual int idaapi pred(int b, int i) const override { CHKNODEIDX(b); return preds[b][i]; } - const intvec_t &idaapi succset(int b) const { CHKNODEIDX(b); return succs[b]; } - const intvec_t &idaapi predset(int b) const { CHKNODEIDX(b); return preds[b]; } - - void idaapi reset(void) { resize(0); } - virtual bool idaapi redo_layout(void) GCC_PUREVIRT; - virtual void idaapi resize(int n) GCC_PUREVIRT; - virtual int idaapi add_node(const rect_t *r) GCC_PUREVIRT; - virtual ssize_t idaapi del_node(int n) GCC_PUREVIRT; // returns number of deleted edges - virtual bool idaapi add_edge(int i, int j, const edge_info_t *ei) GCC_PUREVIRT; - virtual bool idaapi del_edge(int i, int j) GCC_PUREVIRT; // true: found and deleted the edge - virtual bool idaapi replace_edge(int i, int j, int x, int y) GCC_PUREVIRT; - virtual bool idaapi refresh(void) GCC_PUREVIRT; - virtual mutable_graph_t *idaapi clone(void) const override GCC_PUREVIRT; - - // get node rectangle - const rect_t &idaapi nrect(int n) const - { return (CONST_CAST(mutable_graph_t *)(this))->nrect(n); } - virtual rect_t &idaapi nrect(int n) override; - virtual edge_info_t *idaapi get_edge(edge_t e) override GCC_PUREVIRT; - - virtual bool idaapi set_nrect(int n, const rect_t &r) GCC_PUREVIRT; - virtual bool idaapi set_edge(edge_t e, const edge_info_t *ei) GCC_PUREVIRT; - - bool idaapi create_digraph_layout(void); - - void idaapi del_custom_layout(void); - bool idaapi get_custom_layout(void); - void idaapi set_custom_layout(void) const; - bool idaapi get_graph_groups(void); - void idaapi set_graph_groups(void) const; - virtual ea_t idaapi calc_group_ea(const intvec_t & /*nodes*/) newapi { return BADADDR; } - - point_t idaapi calc_center_of(const intvec_t &nodes) const; - void idaapi move_to_same_place(const intvec_t &collapsing_nodes, point_t p); - void idaapi move_grouped_nodes(const intvec_t &groups, const mutable_graph_t *ng); - - virtual bool idaapi is_user_graph() newapi { return false; } -}; - -//------------------------------------------------------------------------- -/// Visit all nodes and edges in a graph -class graph_visitor_t -{ -protected: - abstract_graph_t *g; - virtual int idaapi visit_node(int n, rect_t &r) = 0; - virtual int idaapi visit_edge(edge_t e, edge_info_t *ei) = 0; - friend int idaapi abstract_graph_t::for_all_nodes_edges(graph_visitor_t &nev, bool visit_nodes); -}; - -//------------------------------------------------------------------------- -/// Graph notification codes -enum graph_notification_t -{ - // Callbacks called by IDA (plugins can hook to them): - - grcode_calculating_layout, ///< calculating user-defined graph layout. - ///< \param g (::mutable_graph_t *) - ///< \retval 0 not implemented - ///< \retval 1 graph layout calculated by the plugin - - grcode_layout_calculated, ///< graph layout calculated. - ///< \param g (::mutable_graph_t *) - ///< \param layout_succeeded (bool) - ///< \retval 0 must return 0 - - grcode_changed_graph, ///< new graph has been set. - ///< \param g (::mutable_graph_t *) - ///< \retval 0 must return 0 - - grcode_reserved, - - grcode_clicked, ///< graph is being clicked. - ///< this callback allows you to ignore some clicks. - ///< it occurs too early, internal graph variables are not updated yet. - ///< current_item1, current_item2 point to the same thing. - ///< item2 has more information. - ///< see also: ::custom_viewer_click_t - ///< \param gv (::graph_viewer_t *) - ///< \param current_item1 (::selection_item_t *) - ///< \param current_item2 (::graph_item_t *) - ///< \retval 0 ok - ///< \retval 1 ignore click - - grcode_dblclicked, ///< a graph node has been double clicked. - ///< \param gv (::graph_viewer_t *) - ///< \param current_item (::selection_item_t *) - ///< \retval 0 ok - ///< \retval 1 ignore click - - grcode_creating_group, ///< a group is being created. - ///< \param g (::mutable_graph_t *) - ///< \param nodes (::intvec_t *) - ///< \retval 0 ok - ///< \retval 1 forbid group creation - - grcode_deleting_group, ///< a group is being deleted. - ///< \param g (::mutable_graph_t *) - ///< \param old_group (int) - ///< \retval 0 ok - ///< \retval 1 forbid group deletion - - grcode_group_visibility, ///< a group is being collapsed/uncollapsed - ///< \param g (::mutable_graph_t *) - ///< \param group (int) - ///< \param expand (bool) - ///< \retval 0 ok - ///< \retval 1 forbid group modification - - grcode_gotfocus, ///< a graph viewer got focus. - ///< \param gv (::graph_viewer_t *) - ///< \retval 0 must return 0 - - grcode_lostfocus, ///< a graph viewer lost focus. - ///< \param gv (::graph_viewer_t *) - ///< \retval 0 must return 0 - - grcode_user_refresh, ///< refresh user-defined graph node number and edges. - ///< \param g (::mutable_graph_t *) - ///< \return success - - grcode_user_gentext, ///< generate text for user-defined graph nodes. - ///< \param g (::mutable_graph_t *) - ///< \return success - - grcode_user_text, ///< retrieve text for user-defined graph node. - ///< NB: do not use anything calling GDI! - ///< \param g (::mutable_graph_t *) - ///< \param node (int) - ///< \param result (const char **) - ///< \param bg_color (::bgcolor_t *) may be NULL - ///< \return success, result must be filled - - grcode_user_size, ///< calculate node size for user-defined graph. - ///< \param g (::mutable_graph_t *) - ///< \param node (int) - ///< \param cx (int *) - ///< \param cy (int *) - ///< \retval 0 did not calculate. ida will use node text size - ///< \retval 1 calculated. ida will add node title to the size - - grcode_user_title, ///< render node title of a user-defined graph. - ///< \param g (::mutable_graph_t *) - ///< \param node (int) - ///< \param title_rect (::rect_t *) - ///< \param title_bg_color (int) - ///< \param dc (HDC) - ///< \retval 0 did not render, ida will fill it with title_bg_color - ///< \retval 1 rendered node title - - grcode_user_draw, ///< render node of a user-defined graph. - ///< NB: draw only on the specified DC and nowhere else! - ///< \param g (::mutable_graph_t *) - ///< \param node (int) - ///< \param node_rect (::rect_t *) - ///< \param dc (HDC) - ///< \retval 0 not rendered - ///< \retval 1 rendered - - grcode_user_hint, ///< retrieve hint for the user-defined graph. - ///< \param g (::mutable_graph_t *) - ///< \param mousenode (int) - ///< \param mouseedge_src (int) - ///< \param mouseedge_dst (int) - ///< \param hint (char **) must be allocated by qalloc() or qstrdup() - ///< \retval 0 use default hint - ///< \retval 1 use proposed hint - - grcode_destroyed, ///< graph is being destroyed. Note that this doesn't mean - ///< the graph viewer is being destroyed; this only means - ///< that the graph that is being displayed by it is being - ///< destroyed, and that, e.g., any possibly cached data should - ///< be invalidated (this event can happen when, for example, - ///< the user decides to group nodes together: that operation - ///< will effectively create a new graph, that will replace - ///< the old one.) - ///< To be notified when the graph viewer itself is being destroyed, - ///< please see notification 'view_close', in kernwin.hpp - ///< \param g (::mutable_graph_t *) - ///< \retval 0 must return 0 - - //------------------------------------------------------------------------- - // Callbacks callable from plugins (see inline functions below): - //------------------------------------------------------------------------- - - // graph_viewer_t (or IDA View graph) manipulation. - grcode_create_graph_viewer = 256, ///< use create_graph_viewer() - grcode_get_graph_viewer, ///< use get_graph_viewer() - grcode_get_viewer_graph, ///< use get_viewer_graph() - grcode_create_mutable_graph, ///< use create_mutable_graph() - grcode_set_viewer_graph, ///< use set_viewer_graph() - grcode_refresh_viewer, ///< use refresh_viewer() - grcode_fit_window, ///< use viewer_fit_window() - grcode_get_curnode, ///< use viewer_get_curnode() - grcode_center_on, ///< use viewer_center_on() - grcode_get_selection, ///< use viewer_get_selection() - - // mutable_graph_t (and abstract_graph_t) manipulation. - grcode_del_custom_layout, ///< use mutable_graph_t::del_custom_layout() - grcode_set_custom_layout, ///< use mutable_graph_t::set_custom_layout() - grcode_set_graph_groups, ///< use mutable_graph_t::set_graph_groups() - grcode_clear, ///< use mutable_graph_t::clear() - grcode_create_digraph_layout, ///< use mutable_graph_t::create_digraph_layout() - grcode_create_tree_layout, ///< use abstract_graph_t::create_tree_layout() - grcode_create_circle_layout, ///< use abstract_graph_t::create_circle_layout() - grcode_get_node_representative, ///< use mutable_graph_t::get_node_representative() - grcode_find_subgraph_node, ///< use mutable_graph_t::_find_subgraph_node() - grcode_create_group, ///< use mutable_graph_t::create_group() - grcode_get_custom_layout, ///< use mutable_graph_t::get_custom_layout() - grcode_get_graph_groups, ///< use mutable_graph_t::get_graph_groups() - grcode_empty, ///< use mutable_graph_t::empty() - grcode_is_visible_node, ///< use mutable_graph_t::is_visible_node() - grcode_delete_group, ///< use mutable_graph_t::delete_group() - grcode_change_group_visibility, ///< use mutable_graph_t::change_group_visibility() - grcode_set_edge, ///< use mutable_graph_t::set_edge() - grcode_node_qty, ///< use mutable_graph_t::node_qty() - grcode_nrect, ///< use mutable_graph_t::nrect() - - // More graph_viewer_t manipulation. - grcode_set_titlebar_height, ///< use viewer_set_titlebar_height() - grcode_create_user_graph_place, ///< use create_user_graph_place() - grcode_create_disasm_graph1, ///< use create_disasm_graph(ea_t ea) - grcode_create_disasm_graph2, ///< use create_disasm_graph(const rangevec_t &ranges) - grcode_set_node_info, ///< use viewer_set_node_info() - grcode_get_node_info, ///< use viewer_get_node_info() - grcode_del_node_info, ///< use viewer_del_node_info() - - // Deprecated. Those were meant to work with intset_t, that we now got rid of. - grcode_viewer_create_groups, - grcode_viewer_delete_groups, - grcode_viewer_groups_visibility, - - // - grcode_viewer_create_groups_vec, ///< use viewer_create_groups() - grcode_viewer_delete_groups_vec, ///< use viewer_delete_groups() - grcode_viewer_groups_visibility_vec,///< use viewer_set_groups_visibility() - grcode_delete_mutable_graph, ///< use delete_mutable_graph() - grcode_edge_infos_wrapper_copy, ///< use edge_infos_wrapper_t::operator=() - grcode_edge_infos_wrapper_clear, ///< use edge_infos_wrapper_t::clear() - - // - grcode_attach_menu_item, - - // - grcode_set_gli, ///< use viewer_set_gli() - grcode_get_gli, ///< use viewer_get_gli() -}; - - -//------------------------------------------------------------------------- -#ifndef SWIG -/// \name grentry -/// IDA designates a function for handling graph operations (::grentry). -/// This function accepts a notification code (::graph_notification_t), -/// along with a list of relevant arguments, and handles the action appropriately -/// (similar to ::callui in kernwin.hpp). -//@{ - - -inline ssize_t grentry(graph_notification_t event_code, ...) -{ - va_list va; - va_start(va, event_code); - ssize_t code = invoke_callbacks(HT_GRAPH, event_code, va); - va_end(va); - return code; -} -//@} -#endif - - -//------------------------------------------------------------------------- -struct group_crinfo_t -{ - intvec_t nodes; - qstring text; -}; -typedef qvector groups_crinfos_t; - -#ifndef __UI__ - -typedef TWidget graph_viewer_t; ///< graph view opaque structure - - -/// Create a custom graph viewer. -/// \param title the widget title -/// \param id graph id -/// \param callback callback to handle graph notifications -/// (::graph_notification_t) -/// \param ud user data passed to callback -/// \param title_height node title height -/// \return new viewer - -inline graph_viewer_t *idaapi create_graph_viewer( - const char *title, - uval_t id, - hook_cb_t *callback, - void *ud, - int title_height, - TWidget *parent=NULL) -{ - graph_viewer_t *gv = NULL; - grentry(grcode_create_graph_viewer, title, &gv, id, callback, ud, title_height, parent); - return gv; -} - - -/// Get custom graph viewer for given form - -inline graph_viewer_t *idaapi get_graph_viewer(TWidget *parent) { graph_viewer_t *gv = NULL; grentry(grcode_get_graph_viewer, parent, &gv); return gv; } - - -/// Create a new empty graph with given id - -inline mutable_graph_t *idaapi create_mutable_graph(uval_t id) { mutable_graph_t *g = NULL; grentry(grcode_create_mutable_graph, id, &g); return g; } - - -/// Create a graph for the function that contains 'ea' - -inline mutable_graph_t *idaapi create_disasm_graph(ea_t ea) { mutable_graph_t *g = NULL; grentry(grcode_create_disasm_graph1, ea, &g); return g; } - - -/// Create a graph using an arbitrary set of ranges - -inline mutable_graph_t *idaapi create_disasm_graph(const rangevec_t &ranges) { mutable_graph_t *g = NULL; grentry(grcode_create_disasm_graph2, &ranges, &g); return g; } - - -/// Get graph object for given custom graph viewer - -inline mutable_graph_t *idaapi get_viewer_graph(graph_viewer_t *gv) { mutable_graph_t *g = NULL; grentry(grcode_get_viewer_graph, gv, &g); return g; } - - -/// Set the underlying graph object for the given viewer - -inline void idaapi set_viewer_graph(graph_viewer_t *gv, mutable_graph_t *g) { grentry(grcode_set_viewer_graph, gv, g); } - - -/// Redraw the graph in the given view - -inline void idaapi refresh_viewer(graph_viewer_t *gv) { grentry(grcode_refresh_viewer, gv); } - - -/// Fit graph viewer to its parent form - -inline void idaapi viewer_fit_window(graph_viewer_t *gv) { grentry(grcode_fit_window, gv); } - - -/// Get number of currently selected node (-1 if none) - -inline int idaapi viewer_get_curnode(graph_viewer_t *gv) { return grentry(grcode_get_curnode, gv); } - - -/// Center the graph view on the given node - -inline void idaapi viewer_center_on(graph_viewer_t *gv, int node) { grentry(grcode_center_on, gv, node); } - -/// Set location info for given graph view -/// If flags contains GLICTL_CENTER, then the gli will be set to be -/// the center of the view. Otherwise it will be the top-left. - -inline void idaapi viewer_set_gli( - graph_viewer_t *gv, - const graph_location_info_t *gli, - uint32 flags = 0) -{ - grentry(grcode_set_gli, gv, gli, flags); -} - - -/// Get location info for given graph view -/// If flags contains GLICTL_CENTER, then the gli that will be retrieved, will -/// be the one at the center of the view. Otherwise it will be the top-left. - -inline bool idaapi viewer_get_gli( - graph_location_info_t *out, - graph_viewer_t *gv, - uint32 flags = 0) -{ - return grentry(grcode_get_gli, out, gv, flags) == 0; -} - - -/// Set node info for node in given viewer (see set_node_info()) - -inline void idaapi viewer_set_node_info( - graph_viewer_t *gv, - int n, - const node_info_t &ni, - uint32 flags) -{ - grentry(grcode_set_node_info, gv, n, &ni, flags); -} - - -/// Get node info for node in given viewer (see get_node_info()) - -inline bool idaapi viewer_get_node_info( - graph_viewer_t *gv, - node_info_t *out, - int n) -{ - return grentry(grcode_get_node_info, gv, out, n) == 1; -} - - -/// Delete node info for node in given viewer (see del_node_info()) - -inline void idaapi viewer_del_node_info(graph_viewer_t *gv, int n) -{ - grentry(grcode_del_node_info, gv, n); -} - - -/// This will perform an operation similar to what happens when -/// a user manually selects a set of nodes, right-clicks and selects -/// "Create group". This is a wrapper around mutable_graph_t::create_group -/// that will, in essence: -/// - clone the current graph -/// - for each group_crinfo_t, attempt creating group in that new graph -/// - if all were successful, animate to that new graph. -/// \note this accepts parameters that allow creating -/// of multiple groups at once; which means only one graph -/// animation will be triggered. - -inline bool idaapi viewer_create_groups( - graph_viewer_t *gv, - intvec_t *out_group_nodes, - const groups_crinfos_t &gi) -{ - return grentry(grcode_viewer_create_groups_vec, gv, out_group_nodes, &gi) == 1; -} - - -/// Wrapper around mutable_graph_t::delete_group. -/// This function will: -/// - clone the current graph -/// - attempt deleting the groups in that new graph -/// - if successful, animate to that new graph. - -inline bool idaapi viewer_delete_groups( - graph_viewer_t *gv, - const intvec_t &groups, - int new_current = -1) -{ - return grentry(grcode_viewer_delete_groups_vec, gv, &groups, new_current) == 1; -} - - -/// Wrapper around mutable_graph_t::change_visibility. -/// This function will: -/// - clone the current graph -/// - attempt changing visibility of the groups in that new graph -/// - if successful, animate to that new graph. - -inline bool idaapi viewer_set_groups_visibility( - graph_viewer_t *gv, - const intvec_t &groups, - bool expand, - int new_current = -1) -{ - return grentry(grcode_viewer_groups_visibility_vec, gv, &groups, - expand, new_current) == 1; -} - - -/// Attach a previously-registered action to the view's context menu. -/// See kernwin.hpp for how to register actions. -/// \param name action name -/// \return success - -inline bool idaapi viewer_attach_menu_item(graph_viewer_t *g, const char *name) -{ - return grentry(grcode_attach_menu_item, g, name) != 0; -} - - -/// Get currently selected items for graph viewer - -inline bool idaapi viewer_get_selection( - graph_viewer_t *gv, - screen_graph_selection_t *sgs) -{ - return grentry(grcode_get_selection, gv, sgs) != 0; -} - - -/// Set height of node title bars (::grcode_set_titlebar_height) - -inline int idaapi viewer_set_titlebar_height(graph_viewer_t *gv, int height) -{ - return grentry(grcode_set_titlebar_height, gv, height); -} - - -/// Delete graph object. -/// \warning use this only if you are dealing with ::mutable_graph_t instances -/// that have not been used together with a ::graph_viewer_t. -/// If you have called set_viewer_graph() with your graph, the graph's -/// lifecycle will be managed by the viewer, and you shouldn't -/// interfere with it - -inline void idaapi delete_mutable_graph(mutable_graph_t *g) -{ - grentry(grcode_delete_mutable_graph, g); -} - - -inline void idaapi mutable_graph_t::del_custom_layout(void) { grentry(grcode_del_custom_layout, this); } -inline void idaapi mutable_graph_t::set_custom_layout(void) const { grentry(grcode_set_custom_layout, this); } -inline void idaapi mutable_graph_t::set_graph_groups(void) const { grentry(grcode_set_graph_groups, this); } -inline void idaapi mutable_graph_t::clear(void) { grentry(grcode_clear, this); } -inline bool idaapi mutable_graph_t::create_digraph_layout(void) { return grentry(grcode_create_digraph_layout, this) != 0; } -inline bool idaapi abstract_graph_t::create_tree_layout(void) { return grentry(grcode_create_tree_layout, this) != 0; } -inline bool idaapi abstract_graph_t::create_circle_layout(point_t c, int radius) { return grentry(grcode_create_circle_layout, this, c.x, c.y, radius) != 0; } -inline int idaapi mutable_graph_t::get_node_representative(int node) { return grentry(grcode_get_node_representative, this, node); } -inline int idaapi mutable_graph_t::_find_subgraph_node(int gr, int n) const { return grentry(grcode_find_subgraph_node, this, gr, n); } -inline int idaapi mutable_graph_t::create_group(const intvec_t &_nodes) { return grentry(grcode_create_group, this, &_nodes); } -inline bool idaapi mutable_graph_t::get_custom_layout(void) { return grentry(grcode_get_custom_layout, this) != 0; } -inline bool idaapi mutable_graph_t::get_graph_groups(void) { return grentry(grcode_get_graph_groups, this) != 0; } -inline bool idaapi mutable_graph_t::empty(void) const { return grentry(grcode_empty, this) != 0; } -inline bool idaapi mutable_graph_t::is_visible_node(int node) const { return grentry(grcode_is_visible_node, this, node) != 0; } -inline bool idaapi mutable_graph_t::delete_group(int group) { return grentry(grcode_delete_group, this, group) != 0; } -inline bool idaapi mutable_graph_t::change_group_visibility(int gr, bool exp) { return grentry(grcode_change_group_visibility, this, gr, exp) != 0; } -inline bool idaapi mutable_graph_t::set_edge(edge_t e, const edge_info_t *ei) { return grentry(grcode_set_edge, this, e.src, e.dst, ei) != 0; } -inline int idaapi mutable_graph_t::node_qty(void) const { return grentry(grcode_node_qty, this); } -inline rect_t &idaapi mutable_graph_t::nrect(int n) { rect_t *r; grentry(grcode_nrect, this, n, &r); return *r; } - -inline edge_infos_wrapper_t &idaapi edge_infos_wrapper_t::operator=( - const edge_infos_wrapper_t &other) -{ - grentry(grcode_edge_infos_wrapper_copy, this, &other); return *this; -} - -inline void edge_infos_wrapper_t::clear() -{ - grentry(grcode_edge_infos_wrapper_clear, this); -} - - - -/// Structure returned by get_custom_viewer_place() if the first -/// parameter is a graph viewer. -struct user_graph_place_t : public place_t -{ - int node; -}; - - -/// Get a copy of a ::user_graph_place_t (returns a pointer to static storage) - -inline user_graph_place_t *create_user_graph_place(int node, int lnnum) { user_graph_place_t *r; grentry(grcode_create_user_graph_place, node, lnnum, &r); return r; } - -#endif // UI - -#endif // __GRAPH_DEF_HPP diff --git a/idasdk75/include/help.h b/idasdk75/include/help.h deleted file mode 100644 index 8892f76..0000000 --- a/idasdk75/include/help.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _HELP_H -#define _HELP_H - -typedef int help_t; /* Help messages are referred by ints */ - -// Get pointer to message text by its message id -// The message texts are read from ida.hlp at the beginning -// Returns: pointer to message text (NULL is never returned by IDA) - -idaman THREAD_SAFE const char *ida_export itext(help_t msg_id); - -#ifdef __KERNWIN_HPP -GCC_DIAG_OFF(format-nonliteral); -NORETURN inline void Err(help_t format, ...) -{ - va_list va; - va_start(va, format); - verror(itext(format), va); - // NOTREACHED -} - -inline void Warn(help_t format, ...) -{ - va_list va; - va_start(va, format); - vwarning(itext(format), va); - va_end(va); -} - -inline void Info(help_t format, ...) -{ - va_list va; - va_start(va, format); - vinfo(itext(format), va); - va_end(va); -} - -inline int Message(help_t format,...) -{ - va_list va; - va_start(va, format); - int nbytes = vmsg(itext(format), va); - va_end(va); - return nbytes; -} - -inline int vask_yn(int deflt, help_t format, va_list va) -{ - return vask_yn(deflt, itext(format), va); -} - -inline int ask_yn(int deflt, help_t format, ...) -{ - va_list va; - va_start(va, format); - int code = vask_yn(deflt, itext(format), va); - va_end(va); - return code; -} -GCC_DIAG_ON(format-nonliteral); -#endif - -#ifndef NO_OBSOLETE_FUNCS -#endif - -#endif /* _HELP_H */ diff --git a/idasdk75/include/ida.hpp b/idasdk75/include/ida.hpp deleted file mode 100644 index 817dec2..0000000 --- a/idasdk75/include/ida.hpp +++ /dev/null @@ -1,1229 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _IDA_HPP -#define _IDA_HPP - -#include -#include - -class plugin_t; -struct plugmod_t; - -/*! \file ida.hpp - - \brief Contains the ::inf structure definition and some - functions common to the whole IDA project. - - The ::inf structure is saved in the database and contains information - specific to the current program being disassembled. - Initially it is filled with values from ida.cfg. - - Although it is not a good idea to change values in ::inf - structure (because you will overwrite values taken from ida.cfg), - you are allowed to do it if you feel it necessary. - -*/ - -//-------------------------------------------------------------------------- -/// Known input file formats (kept in \inf{filetype}): -enum filetype_t -{ - f_EXE_old, ///< MS DOS EXE File - f_COM_old, ///< MS DOS COM File - f_BIN, ///< Binary File - f_DRV, ///< MS DOS Driver - f_WIN, ///< New Executable (NE) - f_HEX, ///< Intel Hex Object File - f_MEX, ///< MOS Technology Hex Object File - f_LX, ///< Linear Executable (LX) - f_LE, ///< Linear Executable (LE) - f_NLM, ///< Netware Loadable Module (NLM) - f_COFF, ///< Common Object File Format (COFF) - f_PE, ///< Portable Executable (PE) - f_OMF, ///< Object Module Format - f_SREC, ///< R-records - f_ZIP, ///< ZIP file (this file is never loaded to IDA database) - f_OMFLIB, ///< Library of OMF Modules - f_AR, ///< ar library - f_LOADER, ///< file is loaded using LOADER DLL - f_ELF, ///< Executable and Linkable Format (ELF) - f_W32RUN, ///< Watcom DOS32 Extender (W32RUN) - f_AOUT, ///< Linux a.out (AOUT) - f_PRC, ///< PalmPilot program file - f_EXE, ///< MS DOS EXE File - f_COM, ///< MS DOS COM File - f_AIXAR, ///< AIX ar library - f_MACHO, ///< Mac OS X - f_PSXOBJ, ///< Sony Playstation PSX object file -}; - -/// Is unstructured input file? -inline bool is_filetype_like_binary(filetype_t ft) -{ return ft == f_BIN || ft == f_HEX || ft == f_MEX || ft == f_SREC; } - -//-------------------------------------------------------------------------- - -typedef uchar comp_t; ///< target compiler id -typedef uchar cm_t; ///< calling convention and memory model - -/// Information about the target compiler -struct compiler_info_t -{ - comp_t id; ///< compiler id (see \ref COMP_) - cm_t cm; ///< memory model and calling convention (see \ref CM_) - uchar size_i; ///< sizeof(int) - uchar size_b; ///< sizeof(bool) - uchar size_e; ///< sizeof(enum) - uchar defalign; ///< default alignment for structures - uchar size_s; ///< short - uchar size_l; ///< long - uchar size_ll; ///< longlong - uchar size_ldbl; ///< longdouble (if different from \ph{tbyte_size}) -}; - -//-------------------------------------------------------------------------- -/// Storage types for flag bits -enum storage_type_t -{ - STT_CUR = -1, ///< use current storage type (may be used only as a function argument) - STT_VA = 0, ///< regular storage: virtual arrays, an explicit flag for each byte - STT_MM = 1, ///< memory map: sparse storage. useful for huge objects - STT_DBG = 2, ///< memory map: temporary debugger storage. used internally -}; - -/// \def{EA64_ALIGN, Maintain 64-bit alignments in 64-bit mode} -#ifdef __EA64__ -#define EA64_ALIGN(n) uint32 n; -#else -#define EA64_ALIGN(n) -#endif - -//-------------------------------------------------------------------------- -/// The database parameters. -/// This structure is kept in the ida database. -/// It contains the essential parameters for the current program -#define IDAINFO_TAG_SIZE 3 -#define IDAINFO_PROCNAME_SIZE 16 -#define IDAINFO_STRLIT_PREF_SIZE 16 -struct idainfo -{ - char tag[IDAINFO_TAG_SIZE]; ///< 'IDA' - char zero; ///< this field is not present in the database - ushort version; ///< Version of database - char procname[IDAINFO_PROCNAME_SIZE]; ///< Name of the current processor (with \0) - - ushort s_genflags; ///< \ref INFFL_ -/// \defgroup INFFL_ General idainfo flags -/// Used by idainfo::s_genflags -//@{ -#define INFFL_AUTO 0x01 ///< Autoanalysis is enabled? -#define INFFL_ALLASM 0x02 ///< may use constructs not supported by - ///< the target assembler -#define INFFL_LOADIDC 0x04 ///< loading an idc file that contains database info -#define INFFL_NOUSER 0x08 ///< do not store user info in the database -#define INFFL_READONLY 0x10 ///< (internal) temporary interdiction to modify the database -#define INFFL_CHKOPS 0x20 ///< check manual operands? (unused) -#define INFFL_NMOPS 0x40 ///< allow non-matched operands? (unused) -#define INFFL_GRAPH_VIEW 0x80 ///< currently using graph options (\dto{graph}) -//@} - - uint32 lflags; ///< \ref LFLG_ -/// \defgroup LFLG_ Misc. database flags -/// used by idainfo::lflags -//@{ -#define LFLG_PC_FPP 0x00000001 ///< decode floating point processor instructions? -#define LFLG_PC_FLAT 0x00000002 ///< 32-bit program? -#define LFLG_64BIT 0x00000004 ///< 64-bit program? -#define LFLG_IS_DLL 0x00000008 ///< Is dynamic library? -#define LFLG_FLAT_OFF32 0x00000010 ///< treat ::REF_OFF32 as 32-bit offset for 16bit segments (otherwise try SEG16:OFF16) -#define LFLG_MSF 0x00000020 ///< Byte order: is MSB first? -#define LFLG_WIDE_HBF 0x00000040 ///< Bit order of wide bytes: high byte first? - ///< (wide bytes: \ph{dnbits} > 8) -#define LFLG_DBG_NOPATH 0x00000080 ///< do not store input full path in debugger process options -#define LFLG_SNAPSHOT 0x00000100 ///< memory snapshot was taken? -#define LFLG_PACK 0x00000200 ///< pack the database? -#define LFLG_COMPRESS 0x00000400 ///< compress the database? -#define LFLG_KERNMODE 0x00000800 ///< is kernel mode binary? -//@} - -/// \defgroup IDB_ Line prefix options -/// Used by idainfo::get_pack_mode -//@{ -#define IDB_UNPACKED 0 ///< leave database components unpacked -#define IDB_PACKED 1 ///< pack database components into .idb -#define IDB_COMPRESSED 2 ///< compress & pack database components -//@} - - uint32 database_change_count; ///< incremented after each byte and regular - ///< segment modifications - - ushort filetype; ///< The input file type - - ushort ostype; ///< OS type the program is for - ///< bit definitions in libfuncs.hpp - - ushort apptype; ///< Application type - ///< bit definitions in libfuncs.hpp - - uchar asmtype; ///< target assembler number - - uchar specsegs; ///< What format do special segments use? 0-unspecified, 4-entries are 4 bytes, 8- entries are 8 bytes. - - uint32 af; ///< \ref AF_ -/// \defgroup AF_ Analysis flags -/// used by idainfo::af -//@{ -#define AF_CODE 0x00000001 ///< Trace execution flow -#define AF_MARKCODE 0x00000002 ///< Mark typical code sequences as code -#define AF_JUMPTBL 0x00000004 ///< Locate and create jump tables -#define AF_PURDAT 0x00000008 ///< Control flow to data segment is ignored -#define AF_USED 0x00000010 ///< Analyze and create all xrefs -#define AF_UNK 0x00000020 ///< Delete instructions with no xrefs - -#define AF_PROCPTR 0x00000040 ///< Create function if data xref data->code32 exists -#define AF_PROC 0x00000080 ///< Create functions if call is present -#define AF_FTAIL 0x00000100 ///< Create function tails -#define AF_LVAR 0x00000200 ///< Create stack variables -#define AF_STKARG 0x00000400 ///< Propagate stack argument information -#define AF_REGARG 0x00000800 ///< Propagate register argument information -#define AF_TRACE 0x00001000 ///< Trace stack pointer -#define AF_VERSP 0x00002000 ///< Perform full SP-analysis. (\ph{verify_sp}) -#define AF_ANORET 0x00004000 ///< Perform 'no-return' analysis -#define AF_MEMFUNC 0x00008000 ///< Try to guess member function types -#define AF_TRFUNC 0x00010000 ///< Truncate functions upon code deletion - -#define AF_STRLIT 0x00020000 ///< Create string literal if data xref exists -#define AF_CHKUNI 0x00040000 ///< Check for unicode strings -#define AF_FIXUP 0x00080000 ///< Create offsets and segments using fixup info -#define AF_DREFOFF 0x00100000 ///< Create offset if data xref to seg32 exists -#define AF_IMMOFF 0x00200000 ///< Convert 32bit instruction operand to offset -#define AF_DATOFF 0x00400000 ///< Automatically convert data to offsets - -#define AF_FLIRT 0x00800000 ///< Use flirt signatures -#define AF_SIGCMT 0x01000000 ///< Append a signature name comment for recognized anonymous library functions -#define AF_SIGMLT 0x02000000 ///< Allow recognition of several copies of the same function -#define AF_HFLIRT 0x04000000 ///< Automatically hide library functions - -#define AF_JFUNC 0x08000000 ///< Rename jump functions as j_... -#define AF_NULLSUB 0x10000000 ///< Rename empty functions as nullsub_... - -#define AF_DODATA 0x20000000 ///< Coagulate data segs at the final pass -#define AF_DOCODE 0x40000000 ///< Coagulate code segs at the final pass -#define AF_FINAL 0x80000000 ///< Final pass of analysis -//@} - uint32 af2; ///< \ref AF2_ -/// \defgroup AF2_ Analysis flags 2 -/// Used by idainfo::af2 -//@{ -#define AF2_DOEH 0x00000001 ///< Handle EH information -#define AF2_DORTTI 0x00000002 ///< Handle RTTI information -#define AF2_MACRO 0x00000004 ///< Try to combine several instructions - ///< into a macro instruction -/// remaining 29 bits are reserved -//@} - uval_t baseaddr; ///< base address of the program (paragraphs) - sel_t start_ss; ///< selector of the initial stack segment - sel_t start_cs; ///< selector of the segment with the main entry point - ea_t start_ip; ///< IP register value at the start of - ///< program execution - ea_t start_ea; ///< Linear address of program entry point - ea_t start_sp; ///< SP register value at the start of - ///< program execution - ea_t main; ///< address of main() - ea_t min_ea; ///< current limits of program - ea_t max_ea; ///< maxEA is excluded - ea_t omin_ea; ///< original minEA (is set after loading the input file) - ea_t omax_ea; ///< original maxEA (is set after loading the input file) - - ea_t lowoff; ///< Low limit for offsets - ///< (used in calculation of 'void' operands) - ea_t highoff; ///< High limit for offsets - ///< (used in calculation of 'void' operands) - - uval_t maxref; ///< Max tail for references - - range_t privrange; ///< Range of addresses reserved for internal use. - ///< Initially (MAXADDR, MAXADDR+0x800000) - sval_t netdelta; ///< Delta value to be added to all adresses for mapping to netnodes. - ///< Initially 0 - - /// CROSS REFERENCES - uchar xrefnum; ///< Number of references to generate - ///< in the disassembly listing - ///< 0 - xrefs won't be generated at all - uchar type_xrefnum; ///< Number of references to generate - ///< in the struct & enum windows - ///< 0 - xrefs won't be generated at all - uchar refcmtnum; ///< Number of comment lines to - ///< generate for refs to string literals - ///< or demangled names - ///< 0 - such comments won't be - ///< generated at all - uchar s_xrefflag; ///< \ref SW_X -/// \defgroup SW_X Xref options -/// Used by idainfo::s_xrefflag -//@{ -#define SW_SEGXRF 0x01 ///< show segments in xrefs? -#define SW_XRFMRK 0x02 ///< show xref type marks? -#define SW_XRFFNC 0x04 ///< show function offsets? -#define SW_XRFVAL 0x08 ///< show xref values? (otherwise-"...") -//@} - - /// NAMES - ushort max_autoname_len; ///< max autogenerated name length (without zero byte) - char nametype; ///< \ref NM_ -/// \defgroup NM_ Dummy names representation types -/// Used by idainfo::nametype -//@{ -#define NM_REL_OFF 0 -#define NM_PTR_OFF 1 -#define NM_NAM_OFF 2 -#define NM_REL_EA 3 -#define NM_PTR_EA 4 -#define NM_NAM_EA 5 -#define NM_EA 6 -#define NM_EA4 7 -#define NM_EA8 8 -#define NM_SHORT 9 -#define NM_SERIAL 10 -//@} - - uint32 short_demnames; ///< short form of demangled names - uint32 long_demnames; ///< long form of demangled names - ///< see demangle.h for definitions - uchar demnames; ///< \ref DEMNAM_ -/// \defgroup DEMNAM_ Demangled name flags -/// used by idainfo::demnames -//@{ -#define DEMNAM_MASK 3 ///< mask for name form -#define DEMNAM_CMNT 0 ///< display demangled names as comments -#define DEMNAM_NAME 1 ///< display demangled names as regular names -#define DEMNAM_NONE 2 ///< don't display demangled names -#define DEMNAM_GCC3 4 ///< assume gcc3 names (valid for gnu compiler) -#define DEMNAM_FIRST 8 ///< override type info -//@} - - uchar listnames; ///< \ref LN_ -/// \defgroup LN_ Name list options -/// Used by idainfo::listnames -//@{ -#define LN_NORMAL 0x01 ///< include normal names -#define LN_PUBLIC 0x02 ///< include public names -#define LN_AUTO 0x04 ///< include autogenerated names -#define LN_WEAK 0x08 ///< include weak names -//@} - - /// DISASSEMBLY LISTING DETAILS - uchar indent; ///< Indentation for instructions - uchar comment; ///< Indentation for comments - ushort margin; ///< max length of data lines - ushort lenxref; ///< max length of line with xrefs - uint32 outflags; ///< \ref OFLG_ -/// \defgroup OFLG_ output flags -/// used by idainfo::outflags -//@{ -#define OFLG_SHOW_VOID 0x002 ///< Display void marks? -#define OFLG_SHOW_AUTO 0x004 ///< Display autoanalysis indicator? -#define OFLG_GEN_NULL 0x010 ///< Generate empty lines? -#define OFLG_SHOW_PREF 0x020 ///< Show line prefixes? -#define OFLG_PREF_SEG 0x040 ///< line prefixes with segment name? -#define OFLG_LZERO 0x080 ///< generate leading zeroes in numbers -#define OFLG_GEN_ORG 0x100 ///< Generate 'org' directives? -#define OFLG_GEN_ASSUME 0x200 ///< Generate 'assume' directives? -#define OFLG_GEN_TRYBLKS 0x400 ///< Generate try/catch directives? -//@} - - uchar s_cmtflg; ///< \ref SCF_ -/// \defgroup SCF_ Comment options -/// Used by idainfo::s_cmtflg -//@{ -#define SCF_RPTCMT 0x01 ///< show repeatable comments? -#define SCF_ALLCMT 0x02 ///< comment all lines? -#define SCF_NOCMT 0x04 ///< no comments at all -#define SCF_LINNUM 0x08 ///< show source line numbers -#define SCF_TESTMODE 0x10 ///< testida.idc is running -#define SCF_SHHID_ITEM 0x20 ///< show hidden instructions -#define SCF_SHHID_FUNC 0x40 ///< show hidden functions -#define SCF_SHHID_SEGM 0x80 ///< show hidden segments -//@} - - uchar s_limiter; ///< \ref LMT_ -/// \defgroup LMT_ Delimiter options -/// Used by idainfo::s_limiter -//@{ -#define LMT_THIN 0x01 ///< thin borders -#define LMT_THICK 0x02 ///< thick borders -#define LMT_EMPTY 0x04 ///< empty lines at the end of basic blocks -//@} - - short bin_prefix_size; ///< # of instruction bytes (opcodes) to show in line prefix - uchar s_prefflag; ///< \ref PREF_ -/// \defgroup PREF_ Line prefix options -/// Used by idainfo::s_prefflag -//@{ -#define PREF_SEGADR 0x01 ///< show segment addresses? -#define PREF_FNCOFF 0x02 ///< show function offsets? -#define PREF_STACK 0x04 ///< show stack pointer? -#define PREF_PFXTRUNC 0x08 ///< truncate instruction bytes if they would need more than 1 line -//@} - - /// STRING LITERALS - uchar strlit_flags; ///< \ref STRF_ -/// \defgroup STRF_ string literal flags -/// Used by idainfo::strlit_flags -//@{ -#define STRF_GEN 0x01 ///< generate names? -#define STRF_AUTO 0x02 ///< names have 'autogenerated' bit? -#define STRF_SERIAL 0x04 ///< generate serial names? -#define STRF_UNICODE 0x08 ///< unicode strings are present? -#define STRF_COMMENT 0x10 ///< generate auto comment for string references? -#define STRF_SAVECASE 0x20 ///< preserve case of strings for identifiers -//@} - uchar strlit_break; ///< string literal line break symbol - char strlit_zeroes; ///< leading zeroes - int32 strtype; ///< current ascii string type - ///< see nalt.hpp for string types - char strlit_pref[IDAINFO_STRLIT_PREF_SIZE]; ///< prefix for string literal names - uval_t strlit_sernum; ///< serial number - - // DATA ITEMS - uval_t datatypes; ///< data types allowed in data carousel - - /// COMPILER - compiler_info_t cc; ///< Target compiler - uint32 abibits; ///< ABI features. Depends on info returned by get_abi_name() - ///< Processor modules may modify them in set_compiler - -/// \defgroup ABI_ abi options -/// Used by idainfo::abibits -//@{ -#define ABI_8ALIGN4 0x00000001 ///< 4 byte alignment for 8byte scalars (__int64/double) inside structures? -#define ABI_PACK_STKARGS 0x00000002 ///< do not align stack arguments to stack slots -#define ABI_BIGARG_ALIGN 0x00000004 ///< use natural type alignment for argument if the alignment exceeds native word size - ///< (e.g. __int64 argument should be 8byte aligned on some 32bit platforms) -#define ABI_STACK_LDBL 0x00000008 ///< long double arguments are passed on stack -#define ABI_STACK_VARARGS 0x00000010 ///< varargs are always passed on stack (even when there are free registers) -#define ABI_HARD_FLOAT 0x00000020 ///< use the floating-point register set -#define ABI_SET_BY_USER 0x00000040 ///< compiler/abi were set by user flag and require SETCOMP_BY_USER flag to be changed -#define ABI_GCC_LAYOUT 0x00000080 ///< use gcc layout for udts (used for mingw) -#define ABI_MAP_STKARGS 0x00000100 ///< register arguments are mapped to stack area (and consume stack slots) -#define ABI_HUGEARG_ALIGN 0x00000200 ///< use natural type alignment for an argument - ///< even if its alignment exceeds double native word size - ///< (the default is to use double word max). - ///< e.g. if this bit is set, __int128 has 16-byte alignment -//@} - - uint32 appcall_options; ///< appcall options, see idd.hpp - EA64_ALIGN(padding); - ///< total size for 32bit: 216 bytes - ///< for 64bit: 296 bytes - -}; -#ifdef __EA64__ -CASSERT(sizeof(idainfo) == 280); -#else -CASSERT(sizeof(idainfo) == 200); -#endif - -#if !defined(NO_OBSOLETE_FUNCS) -#define SW_RPTCMT SCF_RPTCMT -#define SW_ALLCMT SCF_ALLCMT -#define SW_NOCMT SCF_NOCMT -#define SW_LINNUM SCF_LINNUM -#define SW_TESTMODE SCF_TESTMODE -#define SW_SHHID_ITEM SCF_SHHID_ITEM -#define SW_SHHID_FUNC SCF_SHHID_FUNC -#define SW_SHHID_SEGM SCF_SHHID_SEGM -#endif - -// we have to continue to export INF for old plugins -#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_INF__) -idaman idainfo ida_export_data inf; ///< program specific information -#endif - -enum inftag_t -{ - INF_VERSION = 0, - INF_PROCNAME = 1, - INF_GENFLAGS = 2, - INF_LFLAGS = 3, - INF_DATABASE_CHANGE_COUNT = 4, - INF_FILETYPE = 5, - INF_OSTYPE = 6, - INF_APPTYPE = 7, - INF_ASMTYPE = 8, - INF_SPECSEGS = 9, - INF_AF = 10, - INF_AF2 = 11, - INF_BASEADDR = 12, - INF_START_SS = 13, - INF_START_CS = 14, - INF_START_IP = 15, - INF_START_EA = 16, - INF_START_SP = 17, - INF_MAIN = 18, - INF_MIN_EA = 19, - INF_MAX_EA = 20, - INF_OMIN_EA = 21, - INF_OMAX_EA = 22, - INF_LOWOFF = 23, - INF_HIGHOFF = 24, - INF_MAXREF = 25, - INF_PRIVRANGE = 26, - INF_PRIVRANGE_START_EA = 27, - INF_PRIVRANGE_END_EA = 28, - INF_NETDELTA = 29, - INF_XREFNUM = 30, - INF_TYPE_XREFNUM = 31, - INF_REFCMTNUM = 32, - INF_XREFFLAG = 33, - INF_MAX_AUTONAME_LEN = 34, - INF_NAMETYPE = 35, - INF_SHORT_DEMNAMES = 36, - INF_LONG_DEMNAMES = 37, - INF_DEMNAMES = 38, - INF_LISTNAMES = 39, - INF_INDENT = 40, - INF_COMMENT = 41, - INF_MARGIN = 42, - INF_LENXREF = 43, - INF_OUTFLAGS = 44, - INF_CMTFLG = 45, - INF_LIMITER = 46, - INF_BIN_PREFIX_SIZE = 47, - INF_PREFFLAG = 48, - INF_STRLIT_FLAGS = 49, - INF_STRLIT_BREAK = 50, - INF_STRLIT_ZEROES = 51, - INF_STRTYPE = 52, - INF_STRLIT_PREF = 53, - INF_STRLIT_SERNUM = 54, - INF_DATATYPES = 55, - INF_CC = 56, - INF_CC_ID = 57, - INF_CC_CM = 58, - INF_CC_SIZE_I = 59, - INF_CC_SIZE_B = 60, - INF_CC_SIZE_E = 61, - INF_CC_DEFALIGN = 62, - INF_CC_SIZE_S = 63, - INF_CC_SIZE_L = 64, - INF_CC_SIZE_LL = 65, - INF_CC_SIZE_LDBL = 66, - INF_ABIBITS = 67, - INF_APPCALL_OPTIONS = 68, - INF_LAST -}; - -/// get program specific information (a scalar value) -/// \param tag one of inftag_t constants -/// \return the requested info. if wrong tag is specified, return 0 -idaman size_t ida_export getinf(inftag_t tag); - -/// get program specific information (a non-scalar value) -/// \param tag one of inftag_t constants -/// \param buf output buffer -/// \param bufsize size of the output buffer -/// \return number of bytes stored in the buffer -idaman size_t ida_export getinf_buf(inftag_t tag, void *buf, size_t bufsize); - -/// get a flag value -/// \param tag one of inftag_t constants -/// \param flag a flag in the field -/// \return whether the flag is set -idaman bool ida_export getinf_flag(inftag_t tag, uint32 flag); - -/// set program specific information -/// \param tag one of inftag_t constants -/// \return success -idaman bool ida_export setinf(inftag_t tag, ssize_t value); - -/// set program specific information -/// \param tag one of inftag_t constants -/// \param buf ptr to new value -/// \param bufsize size of the new value -/// \return success -idaman bool ida_export setinf_buf(inftag_t tag, const void *buf, size_t bufsize); - -/// set a flag value -/// \param tag one of inftag_t constants -/// \param flag a flag in the field -/// \param value whether to set, or clear the flag -/// \return the previous value -idaman bool ida_export setinf_flag(inftag_t tag, uint32 flag, bool value=true); - - -// -inline ushort inf_get_version() { return ushort(getinf(INF_VERSION)); } -inline bool inf_set_version(ushort _v) { return setinf(INF_VERSION, ssize_t(_v)); } - -inline ushort inf_get_genflags() { return ushort(getinf(INF_GENFLAGS)); } -inline bool inf_set_genflags(ushort _v) { return setinf(INF_GENFLAGS, ssize_t(_v)); } -inline bool inf_is_auto_enabled(void) { return getinf_flag(INF_GENFLAGS, INFFL_AUTO); } -inline bool inf_set_auto_enabled(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_AUTO, _v); } -inline bool inf_use_allasm(void) { return getinf_flag(INF_GENFLAGS, INFFL_ALLASM); } -inline bool inf_set_use_allasm(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_ALLASM, _v); } -inline bool inf_loading_idc(void) { return getinf_flag(INF_GENFLAGS, INFFL_LOADIDC); } -inline bool inf_set_loading_idc(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_LOADIDC, _v); } -inline bool inf_no_store_user_info(void) { return getinf_flag(INF_GENFLAGS, INFFL_NOUSER); } -inline bool inf_set_no_store_user_info(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_NOUSER, _v); } -inline bool inf_readonly_idb(void) { return getinf_flag(INF_GENFLAGS, INFFL_READONLY); } -inline bool inf_set_readonly_idb(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_READONLY, _v); } -inline bool inf_check_manual_ops(void) { return getinf_flag(INF_GENFLAGS, INFFL_CHKOPS); } -inline bool inf_set_check_manual_ops(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_CHKOPS, _v); } -inline bool inf_allow_non_matched_ops(void) { return getinf_flag(INF_GENFLAGS, INFFL_NMOPS); } -inline bool inf_set_allow_non_matched_ops(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_NMOPS, _v); } -inline bool inf_is_graph_view(void) { return getinf_flag(INF_GENFLAGS, INFFL_GRAPH_VIEW); } -inline bool inf_set_graph_view(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_GRAPH_VIEW, _v); } - -inline uint32 inf_get_lflags() { return uint32(getinf(INF_LFLAGS)); } -inline bool inf_set_lflags(uint32 _v) { return setinf(INF_LFLAGS, ssize_t(_v)); } -inline bool inf_decode_fpp(void) { return getinf_flag(INF_LFLAGS, LFLG_PC_FPP); } -inline bool inf_set_decode_fpp(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_PC_FPP, _v); } -inline bool inf_is_32bit(void) { return getinf_flag(INF_LFLAGS, LFLG_PC_FLAT); } -inline bool inf_set_32bit(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_PC_FLAT, _v); } -inline bool inf_is_64bit(void) { return getinf_flag(INF_LFLAGS, LFLG_64BIT); } -inline bool inf_set_64bit(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_64BIT, _v); } -inline bool inf_is_dll(void) { return getinf_flag(INF_LFLAGS, LFLG_IS_DLL); } -inline bool inf_set_dll(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_IS_DLL, _v); } -inline bool inf_is_flat_off32(void) { return getinf_flag(INF_LFLAGS, LFLG_FLAT_OFF32); } -inline bool inf_set_flat_off32(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_FLAT_OFF32, _v); } -inline bool inf_is_be(void) { return getinf_flag(INF_LFLAGS, LFLG_MSF); } -inline bool inf_set_be(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_MSF, _v); } -inline bool inf_is_wide_high_byte_first(void) { return getinf_flag(INF_LFLAGS, LFLG_WIDE_HBF); } -inline bool inf_set_wide_high_byte_first(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_WIDE_HBF, _v); } -inline bool inf_dbg_no_store_path(void) { return getinf_flag(INF_LFLAGS, LFLG_DBG_NOPATH); } -inline bool inf_set_dbg_no_store_path(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_DBG_NOPATH, _v); } -inline bool inf_is_snapshot(void) { return getinf_flag(INF_LFLAGS, LFLG_SNAPSHOT); } -inline bool inf_set_snapshot(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_SNAPSHOT, _v); } -inline bool inf_pack_idb(void) { return getinf_flag(INF_LFLAGS, LFLG_PACK); } -inline bool inf_set_pack_idb(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_PACK, _v); } -inline bool inf_compress_idb(void) { return getinf_flag(INF_LFLAGS, LFLG_COMPRESS); } -inline bool inf_set_compress_idb(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_COMPRESS, _v); } -inline bool inf_is_kernel_mode(void) { return getinf_flag(INF_LFLAGS, LFLG_KERNMODE); } -inline bool inf_set_kernel_mode(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_KERNMODE, _v); } - -inline uint32 inf_get_database_change_count() { return uint32(getinf(INF_DATABASE_CHANGE_COUNT)); } -inline bool inf_set_database_change_count(uint32 _v) { return setinf(INF_DATABASE_CHANGE_COUNT, ssize_t(_v)); } - -inline filetype_t inf_get_filetype() { return filetype_t(getinf(INF_FILETYPE)); } -inline bool inf_set_filetype(filetype_t _v) { return setinf(INF_FILETYPE, ssize_t(_v)); } - -inline ushort inf_get_ostype() { return ushort(getinf(INF_OSTYPE)); } -inline bool inf_set_ostype(ushort _v) { return setinf(INF_OSTYPE, ssize_t(_v)); } - -inline ushort inf_get_apptype() { return ushort(getinf(INF_APPTYPE)); } -inline bool inf_set_apptype(ushort _v) { return setinf(INF_APPTYPE, ssize_t(_v)); } - -inline uchar inf_get_asmtype() { return uchar(getinf(INF_ASMTYPE)); } -inline bool inf_set_asmtype(uchar _v) { return setinf(INF_ASMTYPE, ssize_t(_v)); } - -inline uchar inf_get_specsegs() { return uchar(getinf(INF_SPECSEGS)); } -inline bool inf_set_specsegs(uchar _v) { return setinf(INF_SPECSEGS, ssize_t(_v)); } - -inline uint32 inf_get_af() { return uint32(getinf(INF_AF)); } -inline bool inf_set_af(uint32 _v) { return setinf(INF_AF, ssize_t(_v)); } -inline bool inf_trace_flow(void) { return getinf_flag(INF_AF, AF_CODE); } -inline bool inf_set_trace_flow(bool _v=true) { return setinf_flag(INF_AF, AF_CODE, _v); } -inline bool inf_mark_code(void) { return getinf_flag(INF_AF, AF_MARKCODE); } -inline bool inf_set_mark_code(bool _v=true) { return setinf_flag(INF_AF, AF_MARKCODE, _v); } -inline bool inf_create_jump_tables(void) { return getinf_flag(INF_AF, AF_JUMPTBL); } -inline bool inf_set_create_jump_tables(bool _v=true) { return setinf_flag(INF_AF, AF_JUMPTBL, _v); } -inline bool inf_noflow_to_data(void) { return getinf_flag(INF_AF, AF_PURDAT); } -inline bool inf_set_noflow_to_data(bool _v=true) { return setinf_flag(INF_AF, AF_PURDAT, _v); } -inline bool inf_create_all_xrefs(void) { return getinf_flag(INF_AF, AF_USED); } -inline bool inf_set_create_all_xrefs(bool _v=true) { return setinf_flag(INF_AF, AF_USED, _v); } -inline bool inf_del_no_xref_insns(void) { return getinf_flag(INF_AF, AF_UNK); } -inline bool inf_set_del_no_xref_insns(bool _v=true) { return setinf_flag(INF_AF, AF_UNK, _v); } -inline bool inf_create_func_from_ptr(void) { return getinf_flag(INF_AF, AF_PROCPTR); } -inline bool inf_set_create_func_from_ptr(bool _v=true) { return setinf_flag(INF_AF, AF_PROCPTR, _v); } -inline bool inf_create_func_from_call(void) { return getinf_flag(INF_AF, AF_PROC); } -inline bool inf_set_create_func_from_call(bool _v=true) { return setinf_flag(INF_AF, AF_PROC, _v); } -inline bool inf_create_func_tails(void) { return getinf_flag(INF_AF, AF_FTAIL); } -inline bool inf_set_create_func_tails(bool _v=true) { return setinf_flag(INF_AF, AF_FTAIL, _v); } -inline bool inf_should_create_stkvars(void) { return getinf_flag(INF_AF, AF_LVAR); } -inline bool inf_set_should_create_stkvars(bool _v=true) { return setinf_flag(INF_AF, AF_LVAR, _v); } -inline bool inf_propagate_stkargs(void) { return getinf_flag(INF_AF, AF_STKARG); } -inline bool inf_set_propagate_stkargs(bool _v=true) { return setinf_flag(INF_AF, AF_STKARG, _v); } -inline bool inf_propagate_regargs(void) { return getinf_flag(INF_AF, AF_REGARG); } -inline bool inf_set_propagate_regargs(bool _v=true) { return setinf_flag(INF_AF, AF_REGARG, _v); } -inline bool inf_should_trace_sp(void) { return getinf_flag(INF_AF, AF_TRACE); } -inline bool inf_set_should_trace_sp(bool _v=true) { return setinf_flag(INF_AF, AF_TRACE, _v); } -inline bool inf_full_sp_ana(void) { return getinf_flag(INF_AF, AF_VERSP); } -inline bool inf_set_full_sp_ana(bool _v=true) { return setinf_flag(INF_AF, AF_VERSP, _v); } -inline bool inf_noret_ana(void) { return getinf_flag(INF_AF, AF_ANORET); } -inline bool inf_set_noret_ana(bool _v=true) { return setinf_flag(INF_AF, AF_ANORET, _v); } -inline bool inf_guess_func_type(void) { return getinf_flag(INF_AF, AF_MEMFUNC); } -inline bool inf_set_guess_func_type(bool _v=true) { return setinf_flag(INF_AF, AF_MEMFUNC, _v); } -inline bool inf_truncate_on_del(void) { return getinf_flag(INF_AF, AF_TRFUNC); } -inline bool inf_set_truncate_on_del(bool _v=true) { return setinf_flag(INF_AF, AF_TRFUNC, _v); } -inline bool inf_create_strlit_on_xref(void) { return getinf_flag(INF_AF, AF_STRLIT); } -inline bool inf_set_create_strlit_on_xref(bool _v=true) { return setinf_flag(INF_AF, AF_STRLIT, _v); } -inline bool inf_check_unicode_strlits(void) { return getinf_flag(INF_AF, AF_CHKUNI); } -inline bool inf_set_check_unicode_strlits(bool _v=true) { return setinf_flag(INF_AF, AF_CHKUNI, _v); } -inline bool inf_create_off_using_fixup(void) { return getinf_flag(INF_AF, AF_FIXUP); } -inline bool inf_set_create_off_using_fixup(bool _v=true) { return setinf_flag(INF_AF, AF_FIXUP, _v); } -inline bool inf_create_off_on_dref(void) { return getinf_flag(INF_AF, AF_DREFOFF); } -inline bool inf_set_create_off_on_dref(bool _v=true) { return setinf_flag(INF_AF, AF_DREFOFF, _v); } -inline bool inf_op_offset(void) { return getinf_flag(INF_AF, AF_IMMOFF); } -inline bool inf_set_op_offset(bool _v=true) { return setinf_flag(INF_AF, AF_IMMOFF, _v); } -inline bool inf_data_offset(void) { return getinf_flag(INF_AF, AF_DATOFF); } -inline bool inf_set_data_offset(bool _v=true) { return setinf_flag(INF_AF, AF_DATOFF, _v); } -inline bool inf_use_flirt(void) { return getinf_flag(INF_AF, AF_FLIRT); } -inline bool inf_set_use_flirt(bool _v=true) { return setinf_flag(INF_AF, AF_FLIRT, _v); } -inline bool inf_append_sigcmt(void) { return getinf_flag(INF_AF, AF_SIGCMT); } -inline bool inf_set_append_sigcmt(bool _v=true) { return setinf_flag(INF_AF, AF_SIGCMT, _v); } -inline bool inf_allow_sigmulti(void) { return getinf_flag(INF_AF, AF_SIGMLT); } -inline bool inf_set_allow_sigmulti(bool _v=true) { return setinf_flag(INF_AF, AF_SIGMLT, _v); } -inline bool inf_hide_libfuncs(void) { return getinf_flag(INF_AF, AF_HFLIRT); } -inline bool inf_set_hide_libfuncs(bool _v=true) { return setinf_flag(INF_AF, AF_HFLIRT, _v); } -inline bool inf_rename_jumpfunc(void) { return getinf_flag(INF_AF, AF_JFUNC); } -inline bool inf_set_rename_jumpfunc(bool _v=true) { return setinf_flag(INF_AF, AF_JFUNC, _v); } -inline bool inf_rename_nullsub(void) { return getinf_flag(INF_AF, AF_NULLSUB); } -inline bool inf_set_rename_nullsub(bool _v=true) { return setinf_flag(INF_AF, AF_NULLSUB, _v); } -inline bool inf_coagulate_data(void) { return getinf_flag(INF_AF, AF_DODATA); } -inline bool inf_set_coagulate_data(bool _v=true) { return setinf_flag(INF_AF, AF_DODATA, _v); } -inline bool inf_coagulate_code(void) { return getinf_flag(INF_AF, AF_DOCODE); } -inline bool inf_set_coagulate_code(bool _v=true) { return setinf_flag(INF_AF, AF_DOCODE, _v); } -inline bool inf_final_pass(void) { return getinf_flag(INF_AF, AF_FINAL); } -inline bool inf_set_final_pass(bool _v=true) { return setinf_flag(INF_AF, AF_FINAL, _v); } - -inline uint32 inf_get_af2() { return uint32(getinf(INF_AF2)); } -inline bool inf_set_af2(uint32 _v) { return setinf(INF_AF2, ssize_t(_v)); } -inline bool inf_handle_eh(void) { return getinf_flag(INF_AF2, AF2_DOEH); } -inline bool inf_set_handle_eh(bool _v=true) { return setinf_flag(INF_AF2, AF2_DOEH, _v); } -inline bool inf_handle_rtti(void) { return getinf_flag(INF_AF2, AF2_DORTTI); } -inline bool inf_set_handle_rtti(bool _v=true) { return setinf_flag(INF_AF2, AF2_DORTTI, _v); } -inline bool inf_macros_enabled(void) { return getinf_flag(INF_AF2, AF2_MACRO); } -inline bool inf_set_macros_enabled(bool _v=true) { return setinf_flag(INF_AF2, AF2_MACRO, _v); } - -inline uval_t inf_get_baseaddr() { return uval_t(getinf(INF_BASEADDR)); } -inline bool inf_set_baseaddr(uval_t _v) { return setinf(INF_BASEADDR, ssize_t(_v)); } - -inline sel_t inf_get_start_ss() { return sel_t(getinf(INF_START_SS)); } -inline bool inf_set_start_ss(sel_t _v) { return setinf(INF_START_SS, ssize_t(_v)); } - -inline sel_t inf_get_start_cs() { return sel_t(getinf(INF_START_CS)); } -inline bool inf_set_start_cs(sel_t _v) { return setinf(INF_START_CS, ssize_t(_v)); } - -inline ea_t inf_get_start_ip() { return ea_t(getinf(INF_START_IP)); } -inline bool inf_set_start_ip(ea_t _v) { return setinf(INF_START_IP, ssize_t(_v)); } - -inline ea_t inf_get_start_ea() { return ea_t(getinf(INF_START_EA)); } -inline bool inf_set_start_ea(ea_t _v) { return setinf(INF_START_EA, ssize_t(_v)); } - -inline ea_t inf_get_start_sp() { return ea_t(getinf(INF_START_SP)); } -inline bool inf_set_start_sp(ea_t _v) { return setinf(INF_START_SP, ssize_t(_v)); } - -inline ea_t inf_get_main() { return ea_t(getinf(INF_MAIN)); } -inline bool inf_set_main(ea_t _v) { return setinf(INF_MAIN, ssize_t(_v)); } - -inline ea_t inf_get_min_ea() { return ea_t(getinf(INF_MIN_EA)); } -inline bool inf_set_min_ea(ea_t _v) { return setinf(INF_MIN_EA, ssize_t(_v)); } - -inline ea_t inf_get_max_ea() { return ea_t(getinf(INF_MAX_EA)); } -inline bool inf_set_max_ea(ea_t _v) { return setinf(INF_MAX_EA, ssize_t(_v)); } - -inline ea_t inf_get_omin_ea() { return ea_t(getinf(INF_OMIN_EA)); } -inline bool inf_set_omin_ea(ea_t _v) { return setinf(INF_OMIN_EA, ssize_t(_v)); } - -inline ea_t inf_get_omax_ea() { return ea_t(getinf(INF_OMAX_EA)); } -inline bool inf_set_omax_ea(ea_t _v) { return setinf(INF_OMAX_EA, ssize_t(_v)); } - -inline ea_t inf_get_lowoff() { return ea_t(getinf(INF_LOWOFF)); } -inline bool inf_set_lowoff(ea_t _v) { return setinf(INF_LOWOFF, ssize_t(_v)); } - -inline ea_t inf_get_highoff() { return ea_t(getinf(INF_HIGHOFF)); } -inline bool inf_set_highoff(ea_t _v) { return setinf(INF_HIGHOFF, ssize_t(_v)); } - -inline uval_t inf_get_maxref() { return uval_t(getinf(INF_MAXREF)); } -inline bool inf_set_maxref(uval_t _v) { return setinf(INF_MAXREF, ssize_t(_v)); } - -inline sval_t inf_get_netdelta() { return sval_t(getinf(INF_NETDELTA)); } -inline bool inf_set_netdelta(sval_t _v) { return setinf(INF_NETDELTA, ssize_t(_v)); } - -inline uchar inf_get_xrefnum() { return uchar(getinf(INF_XREFNUM)); } -inline bool inf_set_xrefnum(uchar _v) { return setinf(INF_XREFNUM, ssize_t(_v)); } - -inline uchar inf_get_type_xrefnum() { return uchar(getinf(INF_TYPE_XREFNUM)); } -inline bool inf_set_type_xrefnum(uchar _v) { return setinf(INF_TYPE_XREFNUM, ssize_t(_v)); } - -inline uchar inf_get_refcmtnum() { return uchar(getinf(INF_REFCMTNUM)); } -inline bool inf_set_refcmtnum(uchar _v) { return setinf(INF_REFCMTNUM, ssize_t(_v)); } - -inline uchar inf_get_xrefflag() { return uchar(getinf(INF_XREFFLAG)); } -inline bool inf_set_xrefflag(uchar _v) { return setinf(INF_XREFFLAG, ssize_t(_v)); } -inline bool inf_show_xref_seg(void) { return getinf_flag(INF_XREFFLAG, SW_SEGXRF); } -inline bool inf_set_show_xref_seg(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_SEGXRF, _v); } -inline bool inf_show_xref_tmarks(void) { return getinf_flag(INF_XREFFLAG, SW_XRFMRK); } -inline bool inf_set_show_xref_tmarks(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_XRFMRK, _v); } -inline bool inf_show_xref_fncoff(void) { return getinf_flag(INF_XREFFLAG, SW_XRFFNC); } -inline bool inf_set_show_xref_fncoff(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_XRFFNC, _v); } -inline bool inf_show_xref_val(void) { return getinf_flag(INF_XREFFLAG, SW_XRFVAL); } -inline bool inf_set_show_xref_val(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_XRFVAL, _v); } - -inline ushort inf_get_max_autoname_len() { return ushort(getinf(INF_MAX_AUTONAME_LEN)); } -inline bool inf_set_max_autoname_len(ushort _v) { return setinf(INF_MAX_AUTONAME_LEN, ssize_t(_v)); } - -inline char inf_get_nametype() { return char(getinf(INF_NAMETYPE)); } -inline bool inf_set_nametype(char _v) { return setinf(INF_NAMETYPE, ssize_t(_v)); } - -inline uint32 inf_get_short_demnames() { return uint32(getinf(INF_SHORT_DEMNAMES)); } -inline bool inf_set_short_demnames(uint32 _v) { return setinf(INF_SHORT_DEMNAMES, ssize_t(_v)); } - -inline uint32 inf_get_long_demnames() { return uint32(getinf(INF_LONG_DEMNAMES)); } -inline bool inf_set_long_demnames(uint32 _v) { return setinf(INF_LONG_DEMNAMES, ssize_t(_v)); } - -inline uchar inf_get_demnames() { return uchar(getinf(INF_DEMNAMES)); } -inline bool inf_set_demnames(uchar _v) { return setinf(INF_DEMNAMES, ssize_t(_v)); } - -inline uchar inf_get_listnames() { return uchar(getinf(INF_LISTNAMES)); } -inline bool inf_set_listnames(uchar _v) { return setinf(INF_LISTNAMES, ssize_t(_v)); } - -inline uchar inf_get_indent() { return uchar(getinf(INF_INDENT)); } -inline bool inf_set_indent(uchar _v) { return setinf(INF_INDENT, ssize_t(_v)); } - -inline uchar inf_get_comment() { return uchar(getinf(INF_COMMENT)); } -inline bool inf_set_comment(uchar _v) { return setinf(INF_COMMENT, ssize_t(_v)); } - -inline ushort inf_get_margin() { return ushort(getinf(INF_MARGIN)); } -inline bool inf_set_margin(ushort _v) { return setinf(INF_MARGIN, ssize_t(_v)); } - -inline ushort inf_get_lenxref() { return ushort(getinf(INF_LENXREF)); } -inline bool inf_set_lenxref(ushort _v) { return setinf(INF_LENXREF, ssize_t(_v)); } - -inline uint32 inf_get_outflags() { return uint32(getinf(INF_OUTFLAGS)); } -inline bool inf_set_outflags(uint32 _v) { return setinf(INF_OUTFLAGS, ssize_t(_v)); } -inline bool inf_show_void(void) { return getinf_flag(INF_OUTFLAGS, OFLG_SHOW_VOID); } -inline bool inf_set_show_void(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_SHOW_VOID, _v); } -inline bool inf_show_auto(void) { return getinf_flag(INF_OUTFLAGS, OFLG_SHOW_AUTO); } -inline bool inf_set_show_auto(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_SHOW_AUTO, _v); } -inline bool inf_gen_null(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_NULL); } -inline bool inf_set_gen_null(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_NULL, _v); } -inline bool inf_show_line_pref(void) { return getinf_flag(INF_OUTFLAGS, OFLG_SHOW_PREF); } -inline bool inf_set_show_line_pref(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_SHOW_PREF, _v); } -inline bool inf_line_pref_with_seg(void) { return getinf_flag(INF_OUTFLAGS, OFLG_PREF_SEG); } -inline bool inf_set_line_pref_with_seg(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_PREF_SEG, _v); } -inline bool inf_gen_lzero(void) { return getinf_flag(INF_OUTFLAGS, OFLG_LZERO); } -inline bool inf_set_gen_lzero(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_LZERO, _v); } -inline bool inf_gen_org(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_ORG); } -inline bool inf_set_gen_org(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_ORG, _v); } -inline bool inf_gen_assume(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_ASSUME); } -inline bool inf_set_gen_assume(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_ASSUME, _v); } -inline bool inf_gen_tryblks(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_TRYBLKS); } -inline bool inf_set_gen_tryblks(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_TRYBLKS, _v); } - -inline uchar inf_get_cmtflg() { return uchar(getinf(INF_CMTFLG)); } -inline bool inf_set_cmtflg(uchar _v) { return setinf(INF_CMTFLG, ssize_t(_v)); } -inline bool inf_show_repeatables(void) { return getinf_flag(INF_CMTFLG, SCF_RPTCMT); } -inline bool inf_set_show_repeatables(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_RPTCMT, _v); } -inline bool inf_show_all_comments(void) { return getinf_flag(INF_CMTFLG, SCF_ALLCMT); } -inline bool inf_set_show_all_comments(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_ALLCMT, _v); } -inline bool inf_hide_comments(void) { return getinf_flag(INF_CMTFLG, SCF_NOCMT); } -inline bool inf_set_hide_comments(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_NOCMT, _v); } -inline bool inf_show_src_linnum(void) { return getinf_flag(INF_CMTFLG, SCF_LINNUM); } -inline bool inf_set_show_src_linnum(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_LINNUM, _v); } -inline bool inf_test_mode(void) { return getinf_flag(INF_CMTFLG, SCF_TESTMODE); } -inline bool inf_show_hidden_insns(void) { return getinf_flag(INF_CMTFLG, SCF_SHHID_ITEM); } -inline bool inf_set_show_hidden_insns(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_SHHID_ITEM, _v); } -inline bool inf_show_hidden_funcs(void) { return getinf_flag(INF_CMTFLG, SCF_SHHID_FUNC); } -inline bool inf_set_show_hidden_funcs(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_SHHID_FUNC, _v); } -inline bool inf_show_hidden_segms(void) { return getinf_flag(INF_CMTFLG, SCF_SHHID_SEGM); } -inline bool inf_set_show_hidden_segms(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_SHHID_SEGM, _v); } - -inline uchar inf_get_limiter() { return uchar(getinf(INF_LIMITER)); } -inline bool inf_set_limiter(uchar _v) { return setinf(INF_LIMITER, ssize_t(_v)); } -inline bool inf_is_limiter_thin(void) { return getinf_flag(INF_LIMITER, LMT_THIN); } -inline bool inf_set_limiter_thin(bool _v=true) { return setinf_flag(INF_LIMITER, LMT_THIN, _v); } -inline bool inf_is_limiter_thick(void) { return getinf_flag(INF_LIMITER, LMT_THICK); } -inline bool inf_set_limiter_thick(bool _v=true) { return setinf_flag(INF_LIMITER, LMT_THICK, _v); } -inline bool inf_is_limiter_empty(void) { return getinf_flag(INF_LIMITER, LMT_EMPTY); } -inline bool inf_set_limiter_empty(bool _v=true) { return setinf_flag(INF_LIMITER, LMT_EMPTY, _v); } - -inline short inf_get_bin_prefix_size() { return short(getinf(INF_BIN_PREFIX_SIZE)); } -inline bool inf_set_bin_prefix_size(short _v) { return setinf(INF_BIN_PREFIX_SIZE, ssize_t(_v)); } - -inline uchar inf_get_prefflag() { return uchar(getinf(INF_PREFFLAG)); } -inline bool inf_set_prefflag(uchar _v) { return setinf(INF_PREFFLAG, ssize_t(_v)); } -inline bool inf_prefix_show_segaddr(void) { return getinf_flag(INF_PREFFLAG, PREF_SEGADR); } -inline bool inf_set_prefix_show_segaddr(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_SEGADR, _v); } -inline bool inf_prefix_show_funcoff(void) { return getinf_flag(INF_PREFFLAG, PREF_FNCOFF); } -inline bool inf_set_prefix_show_funcoff(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_FNCOFF, _v); } -inline bool inf_prefix_show_stack(void) { return getinf_flag(INF_PREFFLAG, PREF_STACK); } -inline bool inf_set_prefix_show_stack(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_STACK, _v); } -inline bool inf_prefix_truncate_opcode_bytes(void) { return getinf_flag(INF_PREFFLAG, PREF_PFXTRUNC); } -inline bool inf_set_prefix_truncate_opcode_bytes(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_PFXTRUNC, _v); } - -inline uchar inf_get_strlit_flags() { return uchar(getinf(INF_STRLIT_FLAGS)); } -inline bool inf_set_strlit_flags(uchar _v) { return setinf(INF_STRLIT_FLAGS, ssize_t(_v)); } -inline bool inf_strlit_names(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_GEN); } -inline bool inf_set_strlit_names(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_GEN, _v); } -inline bool inf_strlit_name_bit(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_AUTO); } -inline bool inf_set_strlit_name_bit(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_AUTO, _v); } -inline bool inf_strlit_serial_names(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_SERIAL); } -inline bool inf_set_strlit_serial_names(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_SERIAL, _v); } -inline bool inf_unicode_strlits(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_UNICODE); } -inline bool inf_set_unicode_strlits(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_UNICODE, _v); } -inline bool inf_strlit_autocmt(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_COMMENT); } -inline bool inf_set_strlit_autocmt(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_COMMENT, _v); } -inline bool inf_strlit_savecase(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_SAVECASE); } -inline bool inf_set_strlit_savecase(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_SAVECASE, _v); } - -inline uchar inf_get_strlit_break() { return uchar(getinf(INF_STRLIT_BREAK)); } -inline bool inf_set_strlit_break(uchar _v) { return setinf(INF_STRLIT_BREAK, ssize_t(_v)); } - -inline char inf_get_strlit_zeroes() { return char(getinf(INF_STRLIT_ZEROES)); } -inline bool inf_set_strlit_zeroes(char _v) { return setinf(INF_STRLIT_ZEROES, ssize_t(_v)); } - -inline int32 inf_get_strtype() { return int32(getinf(INF_STRTYPE)); } -inline bool inf_set_strtype(int32 _v) { return setinf(INF_STRTYPE, ssize_t(_v)); } - -inline uval_t inf_get_strlit_sernum() { return uval_t(getinf(INF_STRLIT_SERNUM)); } -inline bool inf_set_strlit_sernum(uval_t _v) { return setinf(INF_STRLIT_SERNUM, ssize_t(_v)); } - -inline uval_t inf_get_datatypes() { return uval_t(getinf(INF_DATATYPES)); } -inline bool inf_set_datatypes(uval_t _v) { return setinf(INF_DATATYPES, ssize_t(_v)); } - -inline uint32 inf_get_abibits() { return uint32(getinf(INF_ABIBITS)); } -inline bool inf_set_abibits(uint32 _v) { return setinf(INF_ABIBITS, ssize_t(_v)); } -inline bool inf_is_mem_aligned4(void) { return getinf_flag(INF_ABIBITS, ABI_8ALIGN4); } -inline bool inf_set_mem_aligned4(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_8ALIGN4, _v); } -inline bool inf_pack_stkargs(void) { return getinf_flag(INF_ABIBITS, ABI_PACK_STKARGS); } -inline bool inf_set_pack_stkargs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_PACK_STKARGS, _v); } -inline bool inf_big_arg_align(void) { return getinf_flag(INF_ABIBITS, ABI_BIGARG_ALIGN); } -inline bool inf_set_big_arg_align(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_BIGARG_ALIGN, _v); } -inline bool inf_huge_arg_align(void) { return getinf_flag(INF_ABIBITS, ABI_HUGEARG_ALIGN); } -inline bool inf_set_huge_arg_align(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_HUGEARG_ALIGN, _v); } -inline bool inf_stack_ldbl(void) { return getinf_flag(INF_ABIBITS, ABI_STACK_LDBL); } -inline bool inf_set_stack_ldbl(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_STACK_LDBL, _v); } -inline bool inf_stack_varargs(void) { return getinf_flag(INF_ABIBITS, ABI_STACK_VARARGS); } -inline bool inf_set_stack_varargs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_STACK_VARARGS, _v); } -inline bool inf_is_hard_float(void) { return getinf_flag(INF_ABIBITS, ABI_HARD_FLOAT); } -inline bool inf_set_hard_float(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_HARD_FLOAT, _v); } -inline bool inf_abi_set_by_user(void) { return getinf_flag(INF_ABIBITS, ABI_SET_BY_USER); } -inline bool inf_set_abi_set_by_user(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_SET_BY_USER, _v); } -inline bool inf_use_gcc_layout(void) { return getinf_flag(INF_ABIBITS, ABI_GCC_LAYOUT); } -inline bool inf_set_use_gcc_layout(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_GCC_LAYOUT, _v); } -inline bool inf_map_stkargs(void) { return getinf_flag(INF_ABIBITS, ABI_MAP_STKARGS); } -inline bool inf_set_map_stkargs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_MAP_STKARGS, _v); } - -inline uint32 inf_get_appcall_options() { return uint32(getinf(INF_APPCALL_OPTIONS)); } -inline bool inf_set_appcall_options(uint32 _v) { return setinf(INF_APPCALL_OPTIONS, ssize_t(_v)); } - -inline ea_t inf_get_privrange_start_ea() { return ea_t(getinf(INF_PRIVRANGE_START_EA)); } -inline bool inf_set_privrange_start_ea(ea_t _v) { return setinf(INF_PRIVRANGE_START_EA, ssize_t(_v)); } - -inline ea_t inf_get_privrange_end_ea() { return ea_t(getinf(INF_PRIVRANGE_END_EA)); } -inline bool inf_set_privrange_end_ea(ea_t _v) { return setinf(INF_PRIVRANGE_END_EA, ssize_t(_v)); } - -inline comp_t inf_get_cc_id() { return comp_t(getinf(INF_CC_ID)); } -inline bool inf_set_cc_id(comp_t _v) { return setinf(INF_CC_ID, ssize_t(_v)); } - -inline cm_t inf_get_cc_cm() { return cm_t(getinf(INF_CC_CM)); } -inline bool inf_set_cc_cm(cm_t _v) { return setinf(INF_CC_CM, ssize_t(_v)); } - -inline uchar inf_get_cc_size_i() { return uchar(getinf(INF_CC_SIZE_I)); } -inline bool inf_set_cc_size_i(uchar _v) { return setinf(INF_CC_SIZE_I, ssize_t(_v)); } - -inline uchar inf_get_cc_size_b() { return uchar(getinf(INF_CC_SIZE_B)); } -inline bool inf_set_cc_size_b(uchar _v) { return setinf(INF_CC_SIZE_B, ssize_t(_v)); } - -inline uchar inf_get_cc_size_e() { return uchar(getinf(INF_CC_SIZE_E)); } -inline bool inf_set_cc_size_e(uchar _v) { return setinf(INF_CC_SIZE_E, ssize_t(_v)); } - -inline uchar inf_get_cc_defalign() { return uchar(getinf(INF_CC_DEFALIGN)); } -inline bool inf_set_cc_defalign(uchar _v) { return setinf(INF_CC_DEFALIGN, ssize_t(_v)); } - -inline uchar inf_get_cc_size_s() { return uchar(getinf(INF_CC_SIZE_S)); } -inline bool inf_set_cc_size_s(uchar _v) { return setinf(INF_CC_SIZE_S, ssize_t(_v)); } - -inline uchar inf_get_cc_size_l() { return uchar(getinf(INF_CC_SIZE_L)); } -inline bool inf_set_cc_size_l(uchar _v) { return setinf(INF_CC_SIZE_L, ssize_t(_v)); } - -inline uchar inf_get_cc_size_ll() { return uchar(getinf(INF_CC_SIZE_LL)); } -inline bool inf_set_cc_size_ll(uchar _v) { return setinf(INF_CC_SIZE_LL, ssize_t(_v)); } - -inline uchar inf_get_cc_size_ldbl() { return uchar(getinf(INF_CC_SIZE_LDBL)); } -inline bool inf_set_cc_size_ldbl(uchar _v) { return setinf(INF_CC_SIZE_LDBL, ssize_t(_v)); } - -inline bool inf_get_procname(char *buf, size_t bufsize=IDAINFO_PROCNAME_SIZE) -{ - return (bool)getinf_buf(INF_PROCNAME, buf, bufsize); -} -inline qstring inf_get_procname() -{ - char buf[IDAINFO_PROCNAME_SIZE]; - if ( !getinf_buf(INF_PROCNAME, buf, sizeof(buf)) ) - buf[0] = '\0'; - return qstring(buf); -} -inline bool inf_set_procname(const char *_v, size_t len=size_t(-1)) -{ - if ( _v == NULL ) - return false; - if ( len == size_t(-1) ) - len = ::qstrlen(_v); - return setinf_buf(INF_PROCNAME, _v, qmin(len, IDAINFO_PROCNAME_SIZE)); -} - -inline bool inf_get_strlit_pref(char *buf, size_t bufsize=IDAINFO_STRLIT_PREF_SIZE) -{ - return (bool)getinf_buf(INF_STRLIT_PREF, buf, bufsize); -} -inline qstring inf_get_strlit_pref() -{ - char buf[IDAINFO_STRLIT_PREF_SIZE]; - if ( !getinf_buf(INF_STRLIT_PREF, buf, sizeof(buf)) ) - buf[0] = '\0'; - return qstring(buf); -} -inline bool inf_set_strlit_pref(const char *_v, size_t len=size_t(-1)) -{ - if ( _v == NULL ) - return false; - if ( len == size_t(-1) ) - len = ::qstrlen(_v); - return setinf_buf(INF_STRLIT_PREF, _v, qmin(len, IDAINFO_STRLIT_PREF_SIZE)); -} - -inline bool inf_get_cc(compiler_info_t *out) { return (bool)getinf_buf(INF_CC, out, sizeof(*out)); } -inline bool inf_set_cc(const compiler_info_t &_v) { return setinf_buf(INF_CC, &_v, sizeof(_v)); } - -inline bool inf_get_privrange(range_t *out) { return (bool)getinf_buf(INF_PRIVRANGE, out, sizeof(*out)); } -inline bool inf_set_privrange(const range_t &_v) { return setinf_buf(INF_PRIVRANGE, &_v, sizeof(_v)); } - -// - -inline range_t inf_get_privrange() { range_t r; inf_get_privrange(&r); return r; } - -/// Get/set low/high 16bit halves of inf.af -inline ushort inf_get_af_low() { return inf_get_af() & 0xffff; } -inline void inf_set_af_low(ushort saf) { uint32 af = (inf_get_af() & 0xffff0000) | saf; inf_set_af(af); } -inline ushort inf_get_af_high() { return (inf_get_af() >> 16) & 0xffff; } -inline void inf_set_af_high(ushort saf2) { uint32 af = (inf_get_af() & 0xffff) | (saf2 << 16); inf_set_af(af); } -/// Get/set low 16bit half of inf.af2 -inline ushort inf_get_af2_low() { return inf_get_af2() & 0xffff; } -inline void inf_set_af2_low(ushort saf) { uint32 af2 = (inf_get_af2() & 0xffff0000) | saf; inf_set_af2(af2); } - -inline int inf_get_pack_mode() -{ - uint32 lflags = inf_get_lflags(); - return (lflags & LFLG_COMPRESS) != 0 ? IDB_COMPRESSED - : (lflags & LFLG_PACK) != 0 ? IDB_PACKED - : IDB_UNPACKED; -} - -inline int inf_set_pack_mode(int pack_mode) -{ - int old = inf_get_pack_mode(); - uint32 lflags = inf_get_lflags(); - setflag(lflags, LFLG_COMPRESS, pack_mode == IDB_COMPRESSED); - setflag(lflags, LFLG_PACK, pack_mode == IDB_PACKED); - inf_set_lflags(lflags); - return old; -} - -inline void inf_inc_database_change_count(int cnt=1) -{ inf_set_database_change_count(inf_get_database_change_count()+cnt); } - -/// Get #DEMNAM_MASK bits of #demnames -inline uchar inf_get_demname_form(void) { return uchar(inf_get_demnames() & DEMNAM_MASK); } - -inline uval_t inf_postinc_strlit_sernum(uval_t cnt=1) -{ - uval_t was = inf_get_strlit_sernum(); - inf_set_strlit_sernum(was + cnt); - return was; -} - -inline bool inf_like_binary(void) -{ return is_filetype_like_binary(inf_get_filetype()); } - - - -//------------------------------------------------------------------------- -/// max number of operands allowed for an instruction - -#define UA_MAXOP 8 - - -/// Get default disassembly line options - -inline int calc_default_idaplace_flags(void) -{ - return 0; -} - -//------------------------------------------------------------------------- -/// \def{MAXADDR, Start of the private netnode range} -/// In the past this was the maximal address of the disassembly listing. -#ifdef __EA64__ -#ifdef __GNUC__ -#define MAXADDR 0xFF00000000000000ll -#else -#define MAXADDR 0xFF00000000000000ui64 -#endif -#else -#define MAXADDR 0xFF000000L -#endif - - -//------------------------------------------------------------------------- -/// Convert (sel,off) value to a linear address - -inline ea_t idaapi to_ea(sel_t reg_cs, uval_t reg_ip) -{ - return (reg_cs << 4) + reg_ip; -} - -/// \def{IDB_EXT32, Database file extension for 32-bit programs} -/// \def{IDB_EXT64, Database file extension for 64-bit programs} -/// \def{IDB_EXT, Database file extension} -#define IDB_EXT32 "idb" -#define IDB_EXT64 "i64" -#ifdef __EA64__ -#define IDB_EXT IDB_EXT64 -#else -#define IDB_EXT IDB_EXT32 -#endif - -//-------------------------------------------------------------------------- -/// Callback provided to hook_to_notification_point(). -/// A plugin can hook to a notification point and receive notifications -/// of all major events in IDA. The callback function will be called -/// for each event. -/// \param user_data data supplied in call to hook_to_notification_point() -/// \param notification_code processor_t::event_t or ::ui_notification_t or -/// debugger_t::event_t, depending on the hook type -/// \param va additional parameters supplied with the notification. -/// see the event descriptions for information -/// \retval 0 ok, the event should be processed further -/// \retval !=0 the event is blocked and should be discarded. -/// in the case of processor modules, the returned value is used -/// as the return value of processor_t::notify() - -typedef ssize_t idaapi hook_cb_t(void *user_data, int notification_code, va_list va); - -/// Types of events that be hooked to with hook_to_notification_point() -enum hook_type_t -{ - HT_IDP, ///< Hook to the processor module. - ///< The callback will receive all processor_t::event_t events. - HT_UI, ///< Hook to the user interface. - ///< The callback will receive all ::ui_notification_t events. - HT_DBG, ///< Hook to the debugger. - ///< The callback will receive all ::dbg_notification_t events. - HT_IDB, ///< Hook to the database events. - ///< These events are separated from the ::HT_IDP group - ///< to speed things up (there are too many plugins and - ///< modules hooking to the ::HT_IDP). Some essential events - ///< are still generated in th ::HT_IDP group: - ///< make_code, make_data - ///< This list is not exhaustive. - ///< A common trait of all events in this group: the kernel - ///< does not expect any reaction to the event and does not - ///< check the return code. For event names, see ::idb_event. - HT_DEV, ///< Internal debugger events. - ///< Not stable and undocumented for the moment - HT_VIEW, ///< Custom/IDA views notifications. - ///< Refer to ::view_notification_t - ///< for notification codes - HT_OUTPUT, ///< Output window notifications. - ///< Refer to ::msg_notification_t - ///< (::view_notification_t) - HT_GRAPH, ///< Handling graph operations - ///< (::graph_notification_t) - HT_IDD, ///< Hook to the debugger plugin. - ///< The callback will receive all debugger_t::event_t events. - HT_LAST -}; - - -/// Register a callback for a class of events in IDA - -idaman bool ida_export hook_to_notification_point( - hook_type_t hook_type, - hook_cb_t *cb, - void *user_data = NULL); - - -/// Unregister a callback (also see hook_to_notification_point()). -/// A plugin should unhook before being unloaded -/// (preferably in its termination function). -/// If different callbacks have the same callback function pointer -/// and user_data is not NULL, only the callback whose associated -/// user defined data matches will be removed. -/// \return number of unhooked functions. - -idaman int ida_export unhook_from_notification_point( - hook_type_t hook_type, - hook_cb_t *cb, - void *user_data = NULL); - - -/// Generate event notification. -/// \param hook_type hook type -/// \param notification_code event code -/// \param va additional arguments -/// \return !=0: event processed - -idaman ssize_t ida_export invoke_callbacks(hook_type_t hook_type, int notification_code, va_list va); - - -/// Implements action to take when the event was processed by the notification callback -/// (i.e. when the notification callback returns non-zero code). -/// All the registered (\ref register_post_event_visitor()) post-event visitors will be -/// called in turn after the event was processed by one of the notification callbacks. - -struct post_event_visitor_t -{ - /// Action for post-event management. - /// May change the result of the processed event or data carried by the event. - /// \param code the notification callback or other post-event action - /// return code (result of the processed event) - /// \param notification_code event code - /// \param va additional arguments, the same as for processed event - /// \return result of the event processed - - virtual ssize_t idaapi handle_post_event( - ssize_t code, - int notification_code, - va_list va) = 0; - - DEFINE_VIRTUAL_DTOR(post_event_visitor_t) -}; - - -/// Register the post-event visitor. -/// The kernel will not take ownership, nor delete the VISITOR instance. -/// Therefore, it's up to the plugin to handle it. -/// In addition, the post_event_visitor_t will be automatically unregistered -/// when the owner plugin is unloaded from memory. -/// \param hook_type hook type -/// \param visitor post-event visitor -/// \param owner the owner plugin of the post_event_visitor_t type -/// \return success - -idaman bool ida_export register_post_event_visitor( - hook_type_t hook_type, - post_event_visitor_t *visitor, - const plugmod_t *owner); - - -/// Unregister the post-event visitor. -/// \param hook_type hook type -/// \param visitor post-event visitor -/// \return success - -idaman bool ida_export unregister_post_event_visitor( - hook_type_t hook_type, - post_event_visitor_t *visitor); - - - -#endif // _IDA_HPP diff --git a/idasdk75/include/ida_highlighter.hpp b/idasdk75/include/ida_highlighter.hpp deleted file mode 100644 index a38ed82..0000000 --- a/idasdk75/include/ida_highlighter.hpp +++ /dev/null @@ -1,146 +0,0 @@ -#ifndef IDA_HIGHLIGHTER -#define IDA_HIGHLIGHTER - -#include - -idaman void ida_export code_highlight_block(void *context, highlighter_cbs_t *highlighter_cbs, const qstring &text); - -// returns the length of text to colorize -// negative values may have special meaning in the future. -typedef ssize_t idaapi external_colorizer_t(syntax_highlight_style *color, const char *str); -typedef qvector external_colorizers_t; - -// returns true if identifier is colorized -typedef bool idaapi external_ident_colorizer_t(syntax_highlight_style *color, const qstring &ident); -typedef qvector external_ident_colorizers_t; - - -#define MLTCMTMASK 0xF -#define PREPROC_FLAG 0x10 - -// Common implementation of syntax_highlighter_t used in different parts of IDA -//-V:ida_syntax_highlighter_t:730 not all members of a class are initialized inside the constructor -struct ida_syntax_highlighter_t : syntax_highlighter_t -{ -protected: - // keys of keywords_t point to memory from keyword_strings. - // once allocated, this buffer won't be moved in the memory. - qstrvec_t keyword_memory; - // helper class so that keywords_t gets sorted by string contents, not pointer values. - struct plain_char_ptr_t - { - const char *ptr; - plain_char_ptr_t(const char *p = NULL) : ptr(p) {} - bool operator <(const plain_char_ptr_t &r) const - { - return strcmp(ptr, r.ptr) < 0; - } - bool operator ==(const plain_char_ptr_t &r) const - { - return strcmp(ptr, r.ptr) == 0; - } - }; - struct multicmt_t - { - qstring open_multicmt; - qstring close_multicmt; - multicmt_t() {} - multicmt_t(const char *_open_multicmt, const char *_close_multicmt) : - open_multicmt(_open_multicmt), - close_multicmt(_close_multicmt) - {} - }; - - // typedef std::map keywords_t; - struct keywords_style_t - { - qvector keywords; - syntax_highlight_style style; - }; - typedef qvector keywords_t; - //typedef qvector keywords_t; - typedef qvector multicmtvec_t; - keywords_t keywords; - - qstring open_cmt; // string that opens a regular line comment - multicmtvec_t multicmts; - char literal_closer; // either close_strconst or close_chrconst for the current literal - - // color mappings - syntax_highlight_style text_color = HF_DEFAULT; - syntax_highlight_style comment_color = HF_COMMENT; - syntax_highlight_style string_color = HF_STRING; - syntax_highlight_style preprocessor_color = HF_PREPROC; - - external_colorizers_t external_colorizers; - external_ident_colorizers_t external_ident_colorizers; - - // work variables - const char *input; // pointer to the start of the input buffer - const char *pending; // pointer in the input buffer - syntax_highlight_style style = HF_DEFAULT; // current highlighting style - - bool pending_nonspaces_present(const char *end) - { - for ( const char *p = pending; p != end; ++p ) - if ( !qisspace(*p) ) - return true; - return false; - } - - const char *parse_literal_const(highlighter_cbs_t *highlighter_cbs, const char *ptr, char literal_closer); - void flush_output(highlighter_cbs_t *highlighter_cbs, const char *ptr, syntax_highlight_style style); - void handle_cmt(highlighter_cbs_t *highlighter_cbs, int mcmt_idx, const char **ptr); - void handle_preproc(highlighter_cbs_t *highlighter_cbs, const char **ptr); - -public: - // if any of the following features is not needed, just zero them out: - char open_strconst; // character that opens a string constant - char close_strconst; // character that closes a string constant - char open_chrconst; // character that closes a character constant - char close_chrconst; // character that opens a character constant - char escape_char; // backslash - char preprocessor_char; // # - - ida_syntax_highlighter_t() : syntax_highlighter_t(&code_highlight_block) {} - - void highlight_block_ex(highlighter_cbs_t *highlighter_cbs, const qstring &text); - void add_external_colorizer(external_colorizer_t *th) { external_colorizers.push_back(th); } - void add_external_ident_colorizer(external_ident_colorizer_t *th) { external_ident_colorizers.push_back(th); } - void set_open_cmt(const char *begin) { open_cmt = begin; } - void add_multi_line_comment(const char *begin, const char *end) - { - multicmt_t &mcmt = multicmts.push_back(); - mcmt.open_multicmt = begin; - mcmt.close_multicmt = end; - } - - void add_keywords(const char *kwstr, syntax_highlight_style _style) - { - char *ctx; - // in order not to allocate every keyword separately, we allocate the whole - // kwstr string at once and will just store pointers to it in the map. - qstring &mem = keyword_memory.push_back(); - mem = kwstr; - keywords_style_t *pair_p = NULL; - for ( int i = 0; i < keywords.size(); i++ ) - { - if ( keywords[i].style == _style ) - { - pair_p = &keywords[i]; - break; - } - } - if ( pair_p == NULL ) - { - keywords_style_t &pair = keywords.push_back(); - pair_p = &pair; - pair_p->style = _style; - } - for ( char *kw = qstrtok(mem.begin(), "|", &ctx); kw != NULL; kw = qstrtok(NULL, "|", &ctx) ) - pair_p->keywords.push_back(kw); - } -}; - - -#endif //IDA_HIGHLIGHTER diff --git a/idasdk75/include/idd.hpp b/idasdk75/include/idd.hpp deleted file mode 100644 index 82534fc..0000000 --- a/idasdk75/include/idd.hpp +++ /dev/null @@ -1,1956 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _IDD_HPP -#define _IDD_HPP -#include -#include - -/*! \file idd.hpp - - \brief Contains definition of the interface to IDD modules. - - The interface consists of structures describing the target - debugged processor and a debugging API. -*/ - -/// The IDD interface version number -#define IDD_INTERFACE_VERSION 26 - -class idc_value_t; -class tinfo_t; - -//==================================================================== -// -// Process and Threads -// - -typedef int pid_t; ///< process id -typedef int thid_t; ///< thread id - -#define NO_PROCESS pid_t(-1) ///< No process -#define NO_THREAD 0 ///< No thread. - ///< in ::PROCESS_STARTED this value - ///< can be used to specify that - ///< the main thread has not been created. - ///< It will be initialized later - ///< by a ::THREAD_STARTED event. - -/// Process information -struct process_info_t -{ - pid_t pid; ///< process id - qstring name; ///< process name -}; -DECLARE_TYPE_AS_MOVABLE(process_info_t); -typedef qvector procinfo_vec_t; - -//-------------------------------------------------------------------- -/// Runtime attributes of the debugger/process. -/// It is guaranteed that these attributes are really valid after start/attach process -struct debapp_attrs_t -{ - int32 cbsize; ///< control field: size of this structure - - /// address size of the process. - /// Since 64-bit debuggers usually can debug 32-bit applications, we cannot - /// rely on sizeof(ea_t) to detect the current address size. The following - /// variable should be used instead. It is initialized with 8 for 64-bit - /// debuggers but they should adjust it as soon as they learn that a - /// 32-bit application is being debugged. - /// For 32-bit debuggers it is initialized with 4. - int addrsize; - - qstring platform; ///< platform name process is running/debugging under. - ///< (is used as a key value in exceptions.cfg) - -/// \def{DEF_ADDRSIZE, Default address size - see debapp_attrs_t::addrsize} -#ifdef __EA64__ -#define DEF_ADDRSIZE 8 -#else -#define DEF_ADDRSIZE 4 -#endif - - int is_be; - - /// Constructor - initialize with #DEF_ADDRSIZE - debapp_attrs_t() - : cbsize(sizeof(debapp_attrs_t)), - addrsize(DEF_ADDRSIZE), - is_be(-1) - {} -}; - -//==================================================================== -// -// Registers -// - -typedef unsigned char register_class_t; ///< Each register is associated to - ///< a register class. - ///< example: "segment", "mmx", ... - -/// Debuggee register information -struct register_info_t -{ - const char *name; ///< Register name. - uint32 flags; ///< \ref REGISTER_ -/// \defgroup REGISTER_ Register info attribute flags -/// Used by register_info_t::flags -//@{ -#define REGISTER_READONLY 0x0001 ///< the user can't modify the current value of this register -#define REGISTER_IP 0x0002 ///< instruction pointer -#define REGISTER_SP 0x0004 ///< stack pointer -#define REGISTER_FP 0x0008 ///< frame pointer -#define REGISTER_ADDRESS 0x0010 ///< may contain an address -#define REGISTER_CS 0x0020 ///< code segment -#define REGISTER_SS 0x0040 ///< stack segment -#define REGISTER_NOLF 0x0080 ///< displays this register without returning to the next line - ///< allowing the next register to be displayed to its right (on the same line) -#define REGISTER_CUSTFMT 0x0100 ///< register should be displayed using a custom data format. - ///< the format name is in bit_strings[0] - ///< the corresponding ::regval_t will use ::bytevec_t -//@} - register_class_t register_class; ///< segment, mmx, etc. - op_dtype_t dtype; ///< Register size (see \ref dt_) - const char *const *bit_strings; ///< strings corresponding to each bit of the register. - ///< (NULL = no bit, same name = multi-bits mask) - uval_t default_bit_strings_mask; ///< mask of default bits -}; -DECLARE_TYPE_AS_MOVABLE(register_info_t); -typedef qvector register_info_vec_t; - -//-------------------------------------------------------------------------- -struct dynamic_register_set_t -{ - typedef qvector const_char_vec_t; - - register_info_vec_t ri_vec; - qstrvec_t strvec; - const_char_vec_t classname_ptrs; - qvector bit_strings_ptrs_vec; - - void clear(void) - { - ri_vec.clear(); - strvec.clear(); - classname_ptrs.clear(); - bit_strings_ptrs_vec.clear(); - } - - void add_register( - const char *name, - int flags, - op_dtype_t dtype, - register_class_t register_class, - const char *const *bit_strings, - uval_t bits_mask) - { - // Allocate bit_strings. - if ( bit_strings != nullptr ) - { - size_t num_bits = (flags & REGISTER_CUSTFMT) != 0 ? 1 - : dtype == dt_word ? 16 - : dtype == dt_dword ? 32 - : dtype == dt_qword ? 64 - : 0; - QASSERT(1795, num_bits != 0); - const_char_vec_t &ptrvec = bit_strings_ptrs_vec.push_back(); - ptrvec.resize(num_bits, nullptr); - for ( size_t i = 0; i < num_bits; i++ ) - { - if ( bit_strings[i] != nullptr ) - { - qstring &field_name = strvec.push_back(); - field_name = bit_strings[i]; - ptrvec[i] = field_name.c_str(); - } - } - bit_strings = ptrvec.begin(); - } - - // Allocate name. - qstring ®name = strvec.push_back(); - regname = name; - - // Add entry for register. - register_info_t &ri = ri_vec.push_back(); - ri.name = regname.c_str(); - ri.flags = flags; - ri.dtype = dtype; - ri.register_class = register_class; - ri.bit_strings = bit_strings; - ri.default_bit_strings_mask = bits_mask; - } - - void set_regclasses(const char **register_classes) - { - while ( *register_classes != nullptr ) - { - qstring ®ister_class = strvec.push_back(); - register_class = *register_classes++; - classname_ptrs.push_back(register_class.begin()); - } - classname_ptrs.push_back(nullptr); - } - - // Values for debugger_t. - size_t nregs(void) { return ri_vec.size(); } - register_info_t *registers(void) { return ri_vec.begin(); } - const char **regclasses(void) { return classname_ptrs.begin(); } -}; - -// helper functions: -idaman THREAD_SAFE void ida_export serialize_dynamic_register_set( - bytevec_t *buf, - dynamic_register_set_t &idaregs); -idaman THREAD_SAFE void ida_export deserialize_dynamic_register_set( - dynamic_register_set_t *idaregs, - memory_deserializer_t &mmdsr); - -//==================================================================== -// -// Memory -// - -/// Used by debugger modules to report memory are information to IDA kernel. -/// It is ok to return empty fields if information is not available. -struct memory_info_t : public range_t -{ - qstring name; ///< Memory range name - qstring sclass; ///< Memory range class name - ea_t sbase; ///< Segment base (meaningful only for segmented architectures, e.g. 16-bit x86) - ///< The base is specified in paragraphs (i.e. shifted to the right by 4) - uchar bitness; ///< Number of bits in segment addresses (0-16bit, 1-32bit, 2-64bit) - uchar perm; ///< Memory range permissions (0-no information): see segment.hpp - memory_info_t(void) - : sbase(0),bitness(0),perm(0) {} - bool operator ==(const memory_info_t &r) const - { - return start_ea == r.start_ea - && end_ea == r.end_ea - && name == r.name - && sclass == r.sclass - && sbase == r.sbase - && bitness == r.bitness - && perm == r.perm; - } - bool operator !=(const memory_info_t &r) const { return !(*this == r); } -}; -DECLARE_TYPE_AS_MOVABLE(memory_info_t); -typedef qvector meminfo_vec_t; ///< vector of memory info objects - -/// Used by debugger modules to keep track of images that are not mapped uniformly into memory. -struct scattered_segm_t : public range_t -{ - qstring name; ///< name of the segment -}; -DECLARE_TYPE_AS_MOVABLE(scattered_segm_t); -typedef qvector scattered_image_t; ///< vector of scattered segments - -//==================================================================== -// -// Debug events -// - -/// Debug event codes -enum event_id_t -{ - NO_EVENT = 0x00000000, ///< Not an interesting event. This event can be - ///< used if the debugger module needs to return - ///< an event but there are no valid events. - PROCESS_STARTED = 0x00000001, ///< New process has been started. - PROCESS_EXITED = 0x00000002, ///< Process has been stopped. - THREAD_STARTED = 0x00000004, ///< New thread has been started. - THREAD_EXITED = 0x00000008, ///< Thread has been stopped. - BREAKPOINT = 0x00000010, ///< Breakpoint has been reached. IDA will complain - ///< about unknown breakpoints, they should be reported - ///< as exceptions. - STEP = 0x00000020, ///< One instruction has been executed. Spurious - ///< events of this kind are silently ignored by IDA. - EXCEPTION = 0x00000040, ///< Exception. - LIB_LOADED = 0x00000080, ///< New library has been loaded. - LIB_UNLOADED = 0x00000100, ///< Library has been unloaded. - INFORMATION = 0x00000200, ///< User-defined information. - ///< This event can be used to return empty information - ///< This will cause IDA to call get_debug_event() - ///< immediately once more. - PROCESS_ATTACHED = 0x00000400, ///< Successfully attached to running process. - PROCESS_DETACHED = 0x00000800, ///< Successfully detached from process. - PROCESS_SUSPENDED= 0x00001000, ///< Process has been suspended. - ///< This event can be used by the debugger module - ///< to signal if the process spontaneously gets - ///< suspended (not because of an exception, - ///< breakpoint, or single step). IDA will silently - ///< switch to the 'suspended process' mode without - ///< displaying any messages. - TRACE_FULL = 0x00002000, ///< The trace buffer of the tracer module is full - ///< and IDA needs to read it before continuing -}; - -// helper functions: -struct debug_event_t; -idaman THREAD_SAFE void ida_export free_debug_event(debug_event_t *ev); -idaman THREAD_SAFE void ida_export copy_debug_event(debug_event_t *ev, const debug_event_t &r); -idaman THREAD_SAFE void ida_export set_debug_event_code(debug_event_t *ev, event_id_t id); - -/// Describes a module load event. -/// (see ::PROCESS_STARTED, ::PROCESS_ATTACHED, ::LIB_LOADED) -struct modinfo_t -{ - qstring name; ///< full name of the module - ea_t base; ///< module base address. if unknown pass #BADADDR - asize_t size; ///< module size. if unknown pass 0 - ea_t rebase_to; ///< if not #BADADDR, then rebase the program to the specified address -}; -DECLARE_TYPE_AS_MOVABLE(modinfo_t); -typedef qvector modinfovec_t; - -/// Describes a breakpoint event. -/// (see ::BREAKPOINT) -struct bptaddr_t -{ - ea_t hea; ///< Possible address referenced by hardware breakpoints - ea_t kea; ///< Address of the triggered bpt from the kernel's point - ///< of view. (for some systems with special memory mappings, - ///< the triggered ea might be different from event ea). - ///< Use to #BADADDR for flat memory model. - bptaddr_t(): hea(BADADDR), kea(BADADDR) {} -}; - -/// Describes an exception. -/// (see ::EXCEPTION) -struct excinfo_t -{ - uint32 code; ///< Exception code - bool can_cont; ///< Execution of the process can continue after this exception? - ea_t ea; ///< Possible address referenced by the exception - qstring info; ///< Exception message -}; - -/// This structure is used only when detailed information -/// about a debug event is needed. -struct debug_event_t -{ - pid_t pid; ///< Process where the event occurred - thid_t tid; ///< Thread where the event occurred - ea_t ea; ///< Address where the event occurred - bool handled; ///< Is event handled by the debugger?. - ///< (from the system's point of view) - ///< Meaningful for ::EXCEPTION events -private: - event_id_t _eid; -#ifndef SWIG - char bytes[qmax(sizeof(modinfo_t), sizeof(excinfo_t))]; - void check_usage(uint32 req) { QASSERT(1502, (_eid & req) != 0); } -#endif //SWIG - -public: - debug_event_t(void) : - pid(NO_PROCESS), - tid(NO_THREAD), - ea(BADADDR), - handled(false), - _eid(NO_EVENT) - { - memset(bytes, 0, sizeof(bytes)); - } - debug_event_t(const debug_event_t &r) : _eid(NO_EVENT) { copy(r); } - ~debug_event_t(void) { clear(); } - debug_event_t &operator =(const debug_event_t &r) { return copy(r); } - debug_event_t ©(const debug_event_t &r) { copy_debug_event(this, r); return *this; } - - /// clear the dependent information (see below), set event code to NO_EVENT - void clear(void) { free_debug_event(this); } - - void clear_all(void) - { - clear(); - pid = NO_PROCESS; - tid = NO_THREAD; - ea = BADADDR; - handled = false; - } - - /// Event code - event_id_t eid() const { return _eid; } - - /// Set event code. - /// If the new event code is compatible with the old one - /// then the dependent information (see below) will be preserved. - /// Otherwise the event will be cleared and the new event code will be set. - void set_eid(event_id_t id) { set_debug_event_code(this, id); } - - /// Information that depends on the event code: - - ///< ::PROCESS_STARTED, ::PROCESS_ATTACHED, ::LIB_LOADED - modinfo_t &modinfo() - { - check_usage(PROCESS_STARTED | PROCESS_ATTACHED | LIB_LOADED); - return *(modinfo_t *)bytes; - } - ///< ::PROCESS_EXITED, ::THREAD_EXITED - int &exit_code() - { - check_usage(PROCESS_EXITED | THREAD_EXITED); - return *(int *)bytes; - } - ///< ::THREAD_STARTED (thread name) - ///< ::LIB_UNLOADED (unloaded library name) - ///< ::INFORMATION (will be displayed in the output window if not empty) - qstring &info() - { - check_usage(THREAD_STARTED | LIB_UNLOADED | INFORMATION); - return *(qstring *)bytes; - } - ///< ::BREAKPOINT - bptaddr_t &bpt() - { - check_usage(BREAKPOINT); - return *(bptaddr_t *)bytes; - } - ///< ::EXCEPTION - excinfo_t &exc() - { - check_usage(EXCEPTION); - return *(excinfo_t *)bytes; - } - - const modinfo_t &modinfo() const { return CONST_CAST(debug_event_t*)(this)->modinfo(); } - const int &exit_code() const { return CONST_CAST(debug_event_t*)(this)->exit_code(); } - const qstring &info() const { return CONST_CAST(debug_event_t*)(this)->info(); } - const bptaddr_t &bpt() const { return CONST_CAST(debug_event_t*)(this)->bpt(); } - const excinfo_t &exc() const { return CONST_CAST(debug_event_t*)(this)->exc(); } - - modinfo_t &set_modinfo(event_id_t id) - { - set_eid(id); - return modinfo(); - } - - void set_exit_code(event_id_t id, int code) - { - set_eid(id); - exit_code() = code; - } - - qstring &set_info(event_id_t id) - { - set_eid(id); - return info(); - } - - bptaddr_t &set_bpt(void) - { - set_eid(BREAKPOINT); - return bpt(); - } - - excinfo_t &set_exception(void) - { - set_eid(EXCEPTION); - return exc(); - } - - /// On some systems with special memory mappings the triggered ea might be - /// different from the actual ea. Calculate the address to use. - ea_t bpt_ea(void) const - { - return _eid == BREAKPOINT && bpt().kea != BADADDR ? bpt().kea : ea; - } - - friend THREAD_SAFE void ida_export free_debug_event(debug_event_t *ev); - friend THREAD_SAFE void ida_export copy_debug_event(debug_event_t *ev, const debug_event_t &r); - friend THREAD_SAFE void ida_export set_debug_event_code(debug_event_t *ev, event_id_t id); -}; -DECLARE_TYPE_AS_MOVABLE(debug_event_t); - -typedef int bpttype_t; ///< hardware breakpoint type (see \ref BPT_H) - -/// \defgroup BPT_H Hardware breakpoint ids -/// Fire the breakpoint upon one of these events -//@{ -const bpttype_t - BPT_WRITE = 1, ///< Write access - BPT_READ = 2, ///< Read access - BPT_RDWR = 3, ///< Read/write access - BPT_SOFT = 4, ///< Software breakpoint - BPT_EXEC = 8, ///< Execute instruction - BPT_DEFAULT = (BPT_SOFT|BPT_EXEC); ///< Choose bpt type automatically -//@} - -/// Exception information -struct exception_info_t -{ - uint code; ///< exception code - uint32 flags; ///< \ref EXC_ -/// \defgroup EXC_ Exception info flags -/// Used by exception_info_t::flags -//@{ -#define EXC_BREAK 0x0001 ///< break on the exception -#define EXC_HANDLE 0x0002 ///< should be handled by the debugger? -#define EXC_MSG 0x0004 ///< instead of a warning, log the exception to the output window -#define EXC_SILENT 0x0008 ///< do not warn or log to the output window -//@} - - /// Should we break on the exception? - bool break_on(void) const { return (flags & EXC_BREAK) != 0; } - - /// Should we handle the exception? - bool handle(void) const { return (flags & EXC_HANDLE) != 0; } - - qstring name; ///< Exception standard name - qstring desc; ///< Long message used to display info about the exception - - exception_info_t(void) : code(0), flags(0) {} - exception_info_t(uint _code, uint32 _flags, const char *_name, const char *_desc) - : code(_code), flags(_flags), name(_name), desc(_desc) {} -}; -DECLARE_TYPE_AS_MOVABLE(exception_info_t); -typedef qvector excvec_t; ///< vector of exception info objects - -/// Structure to hold a register value. -/// Small values (up to 64-bit integers and floating point values) use -/// #RVT_INT and #RVT_FLOAT types. For bigger values the bytes() vector is used. -struct regval_t -{ - int32 rvtype; ///< one of \ref RVT_ -/// \defgroup RVT_ Register value types -/// Used by regval_t::rvtype -//@{ -#define RVT_INT (-1) ///< integer -#define RVT_FLOAT (-2) ///< floating point -#define RVT_UNAVAILABLE (-3) ///< unavailable - ///< other values mean custom data type -//@} -#ifndef SWIG - union - { -#endif //SWIG - uint64 ival; ///< 8: integer value - uint16 fval[6]; ///< 12: floating point value in the internal representation (see ieee.h) -#ifndef SWIG - uchar reserve[sizeof(bytevec_t)]; ///< bytevec_t: custom data type (use bytes() to access it) - }; -#endif //SWIG - regval_t(void) : rvtype(RVT_INT), ival(~uint64(0)) {} - ~regval_t(void) { clear(); } - regval_t(const regval_t &r) : rvtype(RVT_INT) { *this = r; } - - /// Assign this regval to the given value - regval_t &operator = (const regval_t &r) - { - if ( this == &r ) - return *this; - if ( r.rvtype >= 0 ) - { - if ( rvtype >= 0 ) - bytes() = r.bytes(); - else - new (&bytes()) bytevec_t(r.bytes()); - } - else // r.rvtype < 0 - { - if ( rvtype >= 0 ) - bytes().~bytevec_t(); - memcpy(fval, r.fval, sizeof(fval)); - } - rvtype = r.rvtype; - return *this; - } - - /// Clear register value - void clear(void) - { - if ( rvtype >= 0 ) - { - bytes().~bytevec_t(); - rvtype = RVT_INT; - } - } - - /// Compare two regvals with '==' - bool operator == (const regval_t &r) const - { - if ( rvtype == r.rvtype ) - { - if ( rvtype == RVT_UNAVAILABLE ) - return true; - if ( rvtype == RVT_INT ) - return ival == r.ival; - return memcmp(get_data(), r.get_data(), get_data_size()) == 0; - } - return false; - } - - /// Compare two regvals with '!=' - bool operator != (const regval_t &r) const { return !(*this == r); } - - /// Set this = r and r = this - void swap(regval_t &r) { qswap(*this, r); } - - /// Use set_int() - void _set_int(uint64 x) { ival = x; } - /// Use set_float() - void _set_float(const ushort *x) { memcpy(fval, x, sizeof(fval)); rvtype = RVT_FLOAT; } - /// Use set_bytes(const uchar *, size_t) - void _set_bytes(const uchar *data, size_t size) { new (&bytes()) bytevec_t(data, size); rvtype = 0; } - /// Use set_bytes(const bytevec_t &) - void _set_bytes(const bytevec_t &v) { new (&bytes()) bytevec_t(v); rvtype = 0; } - /// Use set_bytes(void) - bytevec_t &_set_bytes(void) { new (&bytes()) bytevec_t; rvtype = 0; return bytes(); } - /// Use set_unavailable(void) - void _set_unavailable(void) { ival = 0; rvtype = RVT_UNAVAILABLE; } - - /// \name Setters - /// These functions ensure that the previous value is cleared - //@{ - /// Set int value (ival) - void set_int(uint64 x) { clear(); _set_int(x); } - /// Set float value (fval) - void set_float(const ushort *x) { clear(); _set_float(x); } - /// Set custom regval with raw data - void set_bytes(const uchar *data, size_t size) { clear(); _set_bytes(data, size); } - /// Set custom value with existing bytevec - void set_bytes(const bytevec_t &v) { clear(); _set_bytes(v); } - /// Initialize this regval to an empty custom value - bytevec_t &set_bytes(void) { clear(); _set_bytes(); return bytes(); } - /// Mark as unavailable - void set_unavailable(void) { clear(); _set_unavailable(); } - - //@} - - /// \name Getters - //@{ - /// Get custom value - bytevec_t &bytes(void) { return *(bytevec_t *)reserve; } - /// Get const custom value - const bytevec_t &bytes(void) const { return *(bytevec_t *)reserve; } - /// Get pointer to value - void *get_data(void) { return rvtype >= 0 ? (void *)bytes().begin() : (void *)&fval; } - /// Get const pointer to value - const void *get_data(void) const { return rvtype >= 0 ? (void *)bytes().begin() : (void *)&fval; } - /// Get size of value - size_t get_data_size(void) const - { - if ( rvtype >= 0 ) - return bytes().size(); - if ( rvtype == RVT_INT ) - return sizeof(ival); - if ( rvtype == RVT_FLOAT ) - return sizeof(fval); - return 0; - } - //@} -}; -DECLARE_TYPE_AS_MOVABLE(regval_t); -typedef qvector regvals_t; ///< vector register value objects - -/// Instruction operand information -struct idd_opinfo_t -{ - bool modified; ///< the operand is modified (written) by the instruction - ea_t ea; ///< operand address (#BADADDR - no address) - regval_t value; ///< operand value. custom data is represented by 'bytes'. - int debregidx; ///< for custom data: index of the corresponding register in dbg->registers - int value_size; ///< size of the value in bytes - - idd_opinfo_t(void) : modified(false), ea(BADADDR), debregidx(-1), value_size(0) {} -}; - -/// Call stack trace information -struct call_stack_info_t -{ - ea_t callea; ///< the address of the call instruction. - ///< for the 0th frame this is usually just the current value of EIP. - ea_t funcea; ///< the address of the called function - ea_t fp; ///< the value of the frame pointer of the called function - bool funcok; ///< is the function present? - bool operator==(const call_stack_info_t &r) const - { - return callea == r.callea - && funcea == r.funcea - && funcok == r.funcok - && fp == r.fp; - } - bool operator!=(const call_stack_info_t &r) const { return !(*this == r); } -}; -DECLARE_TYPE_AS_MOVABLE(call_stack_info_t); -typedef qvector call_stack_t; - -//------------------------------------------------------------------------- -THREAD_SAFE inline void append_regval(bytevec_t &s, const regval_t &value) -{ - s.pack_dd(value.rvtype+2); - if ( value.rvtype == RVT_INT ) - { - s.pack_dq(value.ival+1); - } - else if ( value.rvtype == RVT_FLOAT ) - { - s.append(value.fval, sizeof(value.fval)); - } - else if ( value.rvtype != RVT_UNAVAILABLE ) - { - const bytevec_t &b = value.bytes(); - s.pack_dd(b.size()); - s.append(b.begin(), b.size()); - } -} - -//------------------------------------------------------------------------- -template -THREAD_SAFE inline void extract_regval(regval_t *out, T &v) -{ - out->clear(); - out->rvtype = extract_dd(v) - 2; - if ( out->rvtype == RVT_INT ) - { - out->ival = extract_dq(v) - 1; - } - else if ( out->rvtype == RVT_FLOAT ) - { - extract_obj(v, out->fval, sizeof(out->fval)); - } - else if ( out->rvtype != RVT_UNAVAILABLE ) - { - bytevec_t &b = out->_set_bytes(); - int size = extract_dd(v); - b.resize(size); - extract_obj(v, b.begin(), size); - } -} - -//------------------------------------------------------------------------- -template -THREAD_SAFE inline void extract_regvals( - regval_t *values, - int n, - T &v, - const uchar *regmap) -{ - for ( int i=0; i < n && !v.eof(); i++ ) - if ( regmap == NULL || test_bit(regmap, i) ) - extract_regval(&values[i], v); -} - -//-------------------------------------------------------------------------- -THREAD_SAFE inline void unpack_regvals( - regval_t *values, - int n, - const uchar *regmap, - memory_deserializer_t &mmdsr) -{ - extract_regvals(values, n, mmdsr, regmap); -} - - -/// Call a function from the debugged application. -/// \param[out] r function return value -/// - for #APPCALL_MANUAL, r will hold the new stack point value -/// - for #APPCALL_DEBEV, r will hold the exception information upon failure -/// and the return code will be eExecThrow -/// \param func_ea address to call -/// \param tid thread to use. #NO_THREAD means to use the current thread -/// \param ptif pointer to type of the function to call -/// \param argv array of arguments -/// \param argnum number of actual arguments -/// \return #eOk if successful, otherwise an error code - -idaman error_t ida_export dbg_appcall( - idc_value_t *retval, - ea_t func_ea, - thid_t tid, - const tinfo_t *ptif, - idc_value_t *argv, - size_t argnum); - - -/// Cleanup after manual appcall. -/// \param tid thread to use. #NO_THREAD means to use the current thread -/// The application state is restored as it was before calling the last appcall(). -/// Nested appcalls are supported. -/// \return #eOk if successful, otherwise an error code - -idaman error_t ida_export cleanup_appcall(thid_t tid); - - -/// Return values for get_debug_event() -enum gdecode_t -{ - GDE_ERROR = -1, ///< error - GDE_NO_EVENT, ///< no debug events are available - GDE_ONE_EVENT, ///< got one event, no more available yet - GDE_MANY_EVENTS, ///< got one event, more events available -}; - -/// Input argument for update_bpts() -struct update_bpt_info_t -{ - ea_t ea; ///< in: bpt address - bytevec_t orgbytes; ///< in(del), out(add): original bytes (only for swbpts) - bpttype_t type; ///< in: bpt type - int size; ///< in: bpt size (only for hwbpts) - uchar code; ///< in: 0. #BPT_SKIP entries must be skipped by the debugger module - ///< out: \ref BPT_ - pid_t pid; ///< in: process id - thid_t tid; ///< in: thread id - - update_bpt_info_t() - : ea(BADADDR), type(BPT_SOFT), size(0), code(0), pid(NO_PROCESS), tid(NO_THREAD) {} - - /// facilitate update_bpt_vec_t::find() - bool operator==(const update_bpt_info_t &b) const - { - return ea == b.ea && type == b.type; - } -}; -DECLARE_TYPE_AS_MOVABLE(update_bpt_info_t); -typedef qvector update_bpt_vec_t; ///< vector of update breakpoint info objects - -/// Input argument for update_lowcnds(). -/// Server-side low-level breakpoint conditions -struct lowcnd_t -{ - ea_t ea; ///< address of the condition - qstring cndbody; ///< new condition. empty means 'remove condition' - ///< the following fields are valid only if condition is not empty: - bpttype_t type; ///< existing breakpoint type - bytevec_t orgbytes; ///< original bytes (if type==#BPT_SOFT) - insn_t cmd; ///< decoded instruction at 'ea' - ///< (used for processors without single step feature, e.g. arm) - bool compiled; ///< has 'cndbody' already been compiled? - int size; ///< breakpoint size (if type!=#BPT_SOFT) -}; -typedef qvector lowcnd_vec_t; ///< vector of low-level breakpoint conditions - -/// Output argument for ev_suspended -/// New thread names -struct thread_name_t -{ - thid_t tid; ///< thread - qstring name; ///< new thread name -}; -typedef qvector thread_name_vec_t; ///< vector of thread names - -//==================================================================== -/// How to resume the application. The corresponding bit for \ref DBG_FLAG_ -/// must be set in order to use a resume mode. -enum resume_mode_t -{ - RESMOD_NONE, ///< no stepping, run freely - RESMOD_INTO, ///< step into call (the most typical single stepping) - RESMOD_OVER, ///< step over call - RESMOD_OUT, ///< step out of the current function (run until return) - RESMOD_SRCINTO, ///< until control reaches a different source line - RESMOD_SRCOVER, ///< next source line in the current stack frame - RESMOD_SRCOUT, ///< next source line in the previous stack frame - RESMOD_USER, ///< step out to the user code - RESMOD_HANDLE, ///< step into the exception handler - RESMOD_MAX, -}; - -//==================================================================== -// Tracing bits -#define STEP_TRACE 0x01 // lowest level trace. trace buffers are not maintained -#define INSN_TRACE 0x02 // instruction tracing -#define FUNC_TRACE 0x04 // function tracing -#define BBLK_TRACE 0x08 // basic block tracing - -//==================================================================== -/// Debugger return codes. -/// Success if positive (> DRC_NONE). -enum drc_t -{ - DRC_EVENTS = 3, ///< success, there are pending events - DRC_CRC = 2, ///< success, but the input file crc does not match - DRC_OK = 1, ///< success - DRC_NONE = 0, ///< reaction to the event not implemented - DRC_FAILED = -1, ///< failed or false - DRC_NETERR = -2, ///< network error - DRC_NOFILE = -3, ///< file not found - DRC_IDBSEG = -4, ///< use idb segmentation - DRC_NOPROC = -5, ///< the process does not exist anymore - DRC_NOCHG = -6, ///< no changes - DRC_ERROR = -7, ///< unclassified error, may be complemented by errbuf -}; - -//==================================================================== -/// This structure describes a debugger API module. -/// (functions needed to debug a process on a specific -/// operating system). -/// -/// The address of this structure must be put into the ::dbg variable by -/// the plugin_t::init() function of the debugger plugin. -struct debugger_t -{ - int version; ///< Expected kernel version, - ///< should be #IDD_INTERFACE_VERSION - const char *name; ///< Short debugger name like win32 or linux - int id; ///< one of \ref DEBUGGER_ID_ - - /// \defgroup DEBUGGER_ID_ Debugger API module id - /// Used by debugger_t::id - //@{ - #define DEBUGGER_ID_X86_IA32_WIN32_USER 0 ///< Userland win32 processes (win32 debugging APIs) - #define DEBUGGER_ID_X86_IA32_LINUX_USER 1 ///< Userland linux processes (ptrace()) - #define DEBUGGER_ID_X86_IA32_MACOSX_USER 3 ///< Userland MAC OS X processes - #define DEBUGGER_ID_ARM_IPHONE_USER 5 ///< iPhone 1.x - #define DEBUGGER_ID_X86_IA32_BOCHS 6 ///< BochsDbg.exe 32 - #define DEBUGGER_ID_6811_EMULATOR 7 ///< MC6812 emulator (beta) - #define DEBUGGER_ID_GDB_USER 8 ///< GDB remote - #define DEBUGGER_ID_WINDBG 9 ///< WinDBG using Microsoft Debug engine - #define DEBUGGER_ID_X86_DOSBOX_EMULATOR 10 ///< Dosbox MS-DOS emulator - #define DEBUGGER_ID_ARM_LINUX_USER 11 ///< Userland arm linux - #define DEBUGGER_ID_TRACE_REPLAYER 12 ///< Fake debugger to replay recorded traces - #define DEBUGGER_ID_X86_PIN_TRACER 14 ///< PIN Tracer module - #define DEBUGGER_ID_DALVIK_USER 15 ///< Dalvik - #define DEBUGGER_ID_XNU_USER 16 ///< XNU Kernel - //@} - - const char *processor; ///< Required processor name. - ///< Used for instant debugging to load the correct - ///< processor module - - uint32 flags; /// \ref DBG_FLAG_ - uint32 flags2; /// \ref DBG_FLAG2_ - /// may be set inside debugger_t::init_debugger() except of the severals - - /// \defgroup DBG_FLAG_ Debugger module features - /// Used by debugger_t::flags - //@{ - #define DBG_FLAG_REMOTE 0x00000001 ///< Remote debugger (requires remote host name unless #DBG_FLAG_NOHOST) - #define DBG_FLAG_NOHOST 0x00000002 ///< Remote debugger with does not require network params (host/port/pass). - ///< (a unique device connected to the machine) - #define DBG_FLAG_FAKE_ATTACH 0x00000004 ///< ::PROCESS_ATTACHED is a fake event - ///< and does not suspend the execution - #define DBG_FLAG_HWDATBPT_ONE 0x00000008 ///< Hardware data breakpoints are - ///< one byte size by default - #define DBG_FLAG_CAN_CONT_BPT 0x00000010 ///< Debugger knows to continue from a bpt. - ///< This flag also means that the debugger module - ///< hides breakpoints from ida upon read_memory - #define DBG_FLAG_NEEDPORT 0x00000020 ///< Remote debugger requires port number (to be used with DBG_FLAG_NOHOST) - #define DBG_FLAG_DONT_DISTURB 0x00000040 ///< Debugger can handle only - ///< get_debug_event(), - ///< request_pause(), - ///< exit_process(). - ///< when the debugged process is running. - ///< The kernel may also call service functions - ///< (file I/O, map_address, etc) - #define DBG_FLAG_SAFE 0x00000080 ///< The debugger is safe (probably because it just emulates the application - ///< without really running it) - #define DBG_FLAG_CLEAN_EXIT 0x00000100 ///< IDA must suspend the application and remove - ///< all breakpoints before terminating the application. - ///< Usually this is not required because the application memory - ///< disappears upon termination. - #define DBG_FLAG_USE_SREGS 0x00000200 ///< Take segment register values into account (non flat memory) - #define DBG_FLAG_NOSTARTDIR 0x00000400 ///< Debugger module doesn't use startup directory - #define DBG_FLAG_NOPARAMETERS 0x00000800 ///< Debugger module doesn't use commandline parameters - #define DBG_FLAG_NOPASSWORD 0x00001000 ///< Remote debugger doesn't use password - #define DBG_FLAG_CONNSTRING 0x00002000 ///< Display "Connection string" instead of "Hostname" and hide the "Port" field - #define DBG_FLAG_SMALLBLKS 0x00004000 ///< If set, IDA uses 256-byte blocks for caching memory contents. - ///< Otherwise, 1024-byte blocks are used - #define DBG_FLAG_MANMEMINFO 0x00008000 ///< If set, manual memory region manipulation commands - ///< will be available. Use this bit for debugger modules - ///< that cannot return memory layout information - #define DBG_FLAG_EXITSHOTOK 0x00010000 ///< IDA may take a memory snapshot at ::PROCESS_EXITED event - #define DBG_FLAG_VIRTHREADS 0x00020000 ///< Thread IDs may be shuffled after each debug event. - ///< (to be used for virtual threads that represent cpus for windbg kmode) - #define DBG_FLAG_LOWCNDS 0x00040000 ///< Low level breakpoint conditions are supported. - #define DBG_FLAG_DEBTHREAD 0x00080000 ///< Supports creation of a separate thread in ida - ///< for the debugger (the debthread). - ///< Most debugger functions will be called from debthread (exceptions are marked below) - ///< The debugger module may directly call only #THREAD_SAFE functions. - ///< To call other functions please use execute_sync(). - ///< The debthread significantly increases debugging - ///< speed, especially if debug events occur frequently (to be tested) - #define DBG_FLAG_DEBUG_DLL 0x00100000 ///< Can debug standalone DLLs. - ///< For example, Bochs debugger can debug any snippet of code - #define DBG_FLAG_FAKE_MEMORY 0x00200000 ///< get_memory_info()/read_memory()/write_memory() work with the idb. - ///< (there is no real process to read from, as for the replayer module) - ///< the kernel will not call these functions if this flag is set. - ///< however, third party plugins may call them, they must be implemented. - #define DBG_FLAG_ANYSIZE_HWBPT 0x00400000 ///< The debugger supports arbitrary size hardware breakpoints. - #define DBG_FLAG_TRACER_MODULE 0x00800000 ///< The module is a tracer, not a full featured debugger module - #define DBG_FLAG_PREFER_SWBPTS 0x01000000 ///< Prefer to use software breakpoints - //@} - - /// \defgroup DBG_FLAG2_ Debugger module features - /// Used by debugger_t::flags2 - //@{ - #define DBG_HAS_GET_PROCESSES 0x00000001 ///< supports ev_get_processes - #define DBG_HAS_ATTACH_PROCESS 0x00000002 ///< supports ev_attach_process - #define DBG_HAS_DETACH_PROCESS 0x00000004 ///< supports ev_detach_process - #define DBG_HAS_REQUEST_PAUSE 0x00000008 ///< supports ev_request_pause - #define DBG_HAS_SET_EXCEPTION_INFO \ - 0x00000010 ///< supports ev_set_exception_info - #define DBG_HAS_THREAD_SUSPEND 0x00000020 ///< supports ev_thread_suspend - #define DBG_HAS_THREAD_CONTINUE 0x00000040 ///< supports ev_thread_continue - #define DBG_HAS_SET_RESUME_MODE 0x00000080 ///< supports ev_set_resume_mode - ///< cannot be set inside the debugger_t::init_debugger() - #define DBG_HAS_THREAD_GET_SREG_BASE \ - 0x00000100 ///< supports ev_thread_get_sreg_base - #define DBG_HAS_CHECK_BPT 0x00000200 ///< supports ev_check_bpt - #define DBG_HAS_OPEN_FILE 0x00000400 ///< supports ev_open_file, ev_close_file, ev_read_file, ev_write_file - #define DBG_HAS_UPDATE_CALL_STACK \ - 0x00000800 ///< supports ev_update_call_stack - #define DBG_HAS_APPCALL 0x00001000 ///< supports ev_appcall, ev_cleanup_appcall - #define DBG_HAS_REXEC 0x00002000 ///< supports ev_rexec - #define DBG_HAS_MAP_ADDRESS 0x00004000 ///< supports ev_map_address, - ///< avoid using this bit, especially together with DBG_FLAG_DEBTHREAD - ///< because it may cause big slow downs - //@} - - bool is_remote(void) const { return (flags & DBG_FLAG_REMOTE) != 0; } - bool must_have_hostname(void) const - { return (flags & (DBG_FLAG_REMOTE|DBG_FLAG_NOHOST)) == DBG_FLAG_REMOTE; } - bool can_continue_from_bpt(void) const - { return (flags & DBG_FLAG_CAN_CONT_BPT) != 0; } - bool may_disturb(void) const - { return (flags & DBG_FLAG_DONT_DISTURB) == 0; } - bool is_safe(void) const - { return (flags & DBG_FLAG_SAFE) != 0; } - bool use_sregs(void) const - { return (flags & DBG_FLAG_USE_SREGS) != 0; } - size_t cache_block_size(void) const - { return (flags & DBG_FLAG_SMALLBLKS) != 0 ? 256 : 1024; } - bool use_memregs(void) const - { return (flags & DBG_FLAG_MANMEMINFO) != 0; } - bool may_take_exit_snapshot(void) const - { return (flags & DBG_FLAG_EXITSHOTOK) != 0; } - bool virtual_threads(void) const - { return (flags & DBG_FLAG_VIRTHREADS) != 0; } - bool supports_lowcnds(void) const - { return (flags & DBG_FLAG_LOWCNDS) != 0; } - bool supports_debthread(void) const - { return (flags & DBG_FLAG_DEBTHREAD) != 0; } - bool can_debug_standalone_dlls(void) const - { return (flags & DBG_FLAG_DEBUG_DLL) != 0; } - bool fake_memory(void) const - { return (flags & DBG_FLAG_FAKE_MEMORY) != 0; } - - bool has_get_processes(void) const - { return (flags2 & DBG_HAS_GET_PROCESSES) != 0; } - bool has_attach_process(void) const - { return (flags2 & DBG_HAS_ATTACH_PROCESS) != 0; } - bool has_detach_process(void) const - { return (flags2 & DBG_HAS_DETACH_PROCESS) != 0; } - bool has_request_pause(void) const - { return (flags2 & DBG_HAS_REQUEST_PAUSE) != 0; } - bool has_set_exception_info(void) const - { return (flags2 & DBG_HAS_SET_EXCEPTION_INFO) != 0; } - bool has_thread_suspend(void) const - { return (flags2 & DBG_HAS_THREAD_SUSPEND) != 0; } - bool has_thread_continue(void) const - { return (flags2 & DBG_HAS_THREAD_CONTINUE) != 0; } - bool has_set_resume_mode(void) const - { return (flags2 & DBG_HAS_SET_RESUME_MODE) != 0; } - bool has_thread_get_sreg_base(void) const - { return (flags2 & DBG_HAS_THREAD_GET_SREG_BASE) != 0; } - bool has_check_bpt(void) const - { return (flags2 & DBG_HAS_CHECK_BPT) != 0; } - bool has_open_file(void) const - { return (flags2 & DBG_HAS_OPEN_FILE) != 0; } - bool has_update_call_stack(void) const - { return (flags2 & DBG_HAS_UPDATE_CALL_STACK) != 0; } - bool has_appcall(void) const - { return (flags2 & DBG_HAS_APPCALL) != 0; } - bool has_rexec(void) const - { return (flags2 & DBG_HAS_REXEC) != 0; } - bool has_map_address(void) const - { return (flags2 & DBG_HAS_MAP_ADDRESS) != 0; } - - const char **regclasses; ///< Array of register class names - int default_regclasses; ///< Mask of default printed register classes - register_info_t *registers; ///< Array of registers. Use regs() to access it - int nregs; ///< Number of registers - - // A function for accessing the 'registers' array - inline register_info_t ®s(int idx) - { - return registers[idx]; - } - - int memory_page_size; ///< Size of a memory page - - const uchar *bpt_bytes; ///< Array of bytes for a breakpoint instruction - uchar bpt_size; ///< Size of this array - uchar filetype; ///< for miniidbs: use this value - ///< for the file type after attaching - ///< to a new process - ushort resume_modes; ///< \ref DBG_RESMOD_ - /// \defgroup DBG_RESMOD_ Resume modes - /// Used by debugger_t::resume_modes - //@{ - #define DBG_RESMOD_STEP_INTO 0x0001 ///< ::RESMOD_INTO is available - #define DBG_RESMOD_STEP_OVER 0x0002 ///< ::RESMOD_OVER is available - #define DBG_RESMOD_STEP_OUT 0x0004 ///< ::RESMOD_OUT is available - #define DBG_RESMOD_STEP_SRCINTO 0x0008 ///< ::RESMOD_SRCINTO is available - #define DBG_RESMOD_STEP_SRCOVER 0x0010 ///< ::RESMOD_SRCOVER is available - #define DBG_RESMOD_STEP_SRCOUT 0x0020 ///< ::RESMOD_SRCOUT is available - #define DBG_RESMOD_STEP_USER 0x0040 ///< ::RESMOD_USER is available - #define DBG_RESMOD_STEP_HANDLE 0x0080 ///< ::RESMOD_HANDLE is available - //@} - bool is_resmod_avail(int resmod) const - { return (resume_modes & (1 << (resmod - 1))) != 0; } - -#if !defined(_MSC_VER) // this compiler complains :( - static const int default_port_number = 23946; -#define DEBUGGER_PORT_NUMBER debugger_t::default_port_number -#else -#define DEBUGGER_PORT_NUMBER 23946 -#endif - - /// Set debugger options (parameters that are specific to the debugger module). - /// See the definition of ::set_options_t for arguments. - /// See the convenience function in dbg.hpp if you need to call it. - /// The kernel will generate this event after reading the debugger specific - /// config file (arguments are: keyword="", type=#IDPOPT_STR, value="") - /// This event is optional. - /// This event is generated in the main thread - const char *(idaapi *set_dbg_options)( - const char *keyword, - int pri, - int value_type, - const void *value); - - /// Callback notification codes. - /// - /// They are passed to notify() when certain events occur in the kernel, - /// allowing the debugger plugin to take appropriate actions. - /// - /// Debugger plugins must implement the desired reaction to these events - /// in the notify() function. - /// - /// The notify() function should not be called directly. See inline functions - /// below. - enum event_t - { - /// Initialize debugger. - /// This event is generated in the main thread. - /// \param hostname (const char *) - /// \param portnum (int) - /// \param password (const char *) - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_FAILED - ev_init_debugger, - - /// Terminate debugger. - /// This event is generated in the main thread. - /// \return ::DRC_OK, ::DRC_FAILED - ev_term_debugger, - - /// Return information about the running processes. - /// This event is generated in the main thread. - /// Available if \ref DBG_HAS_GET_PROCESSES is set - /// \param procs (::procinfo_vec_t *) - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_get_processes, - - /// Start an executable to debug. - /// This event is generated in debthread. - /// Must be implemented. - /// \param path (const char *) path to executable - /// \param args (const char *) arguments to pass to executable - /// \param startdir (const char *) initial working directory of new process - /// \param dbg_proc_flags (uint32) \ref DBG_PROC_ - /// \param input_path (const char *) path to the file that was used to create the idb file - /// It is not always the same as 'path' - e.g. if we are analyzing - /// a dll and want to launch an executable that loads it. - /// \param input_file_crc32 (uint32) CRC value for 'input_path' - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_CRC, ::DRC_FAILED, ::DRC_NETERR, ::DRC_NOFILE - ev_start_process, - - /// Attach to an existing running process. - /// event_id should be equal to -1 if not attaching to a crashed process. - /// This event is generated in debthread. - /// Available if \ref DBG_HAS_ATTACH_PROCESS is set - /// \param pid (::pid_t) process id to attach - /// \param event_id (int) event to trigger upon attaching - /// \param dbg_proc_flags (uint32) \ref DBG_PROC_ - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_attach_process, - - /// Detach from the debugged process. - /// May be generated while the process is running or suspended. - /// Must detach from the process in any case. - /// The kernel will repeatedly call get_debug_event() until ::PROCESS_DETACHED is received. - /// In this mode, all other events will be automatically handled and process will be resumed. - /// This event is generated from debthread. - /// Available if \ref DBG_HAS_DETACH_PROCESS is set - /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_detach_process, - - /// Retrieve process- and debugger-specific runtime attributes. - /// This event is generated in the main thread. - /// \param out_pattrs (::debapp_attrs_t *) - /// \return ::DRC_NONE, ::DRC_OK - ev_get_debapp_attrs, - - /// Rebase database if the debugged program has been rebased by the system. - /// This event is generated in the main thread. - /// \param new_base (::ea_t) - /// \return ::DRC_NONE, ::DRC_OK - ev_rebase_if_required_to, - - /// Prepare to pause the process. - /// Normally the next get_debug_event() will pause the process - /// If the process is sleeping, - /// then the pause will not occur until the process wakes up. - /// If the debugger module does not react to this event, - /// then it will be impossible to pause the program. - /// This event is generated in debthread. - /// Available if \ref DBG_HAS_REQUEST_PAUSE is set - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_request_pause, - - /// Stop the process. - /// May be generated while the process is running or suspended. - /// Must terminate the process in any case. - /// The kernel will repeatedly call get_debug_event() until ::PROCESS_EXITED is received. - /// In this mode, all other events will be automatically handled and process will be resumed. - /// This event is generated in debthread. - /// Must be implemented. - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_exit_process, - - /// Get a pending debug event and suspend the process. - /// This event will be generated regularly by IDA. - /// This event is generated in debthread. - /// IMPORTANT: the BREAKPOINT/EXCEPTION/STEP events must be reported - /// only after reporting other pending events for a thread. - /// Must be implemented. - /// \param code (::gdecode_t *) - /// \param event (::debug_event_t *) - /// \param timeout_ms (int) - /// \retval ignored - ev_get_debug_event, - - /// Continue after handling the event. - /// This event is generated in debthread. - /// Must be implemented. - /// \param event (::debug_event_t *) - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_resume, - - /// Set exception handling. - /// This event is generated in debthread or the main thread. - /// Available if \ref DBG_HAS_SET_EXCEPTION_INFO is set - /// \param info (::exception_info_t *) - /// \param qty (int) - /// \return ::DRC_NONE, ::DRC_OK - ev_set_exception_info, - - /// This event will be generated by the kernel each time - /// it has suspended the debugger process and refreshed the database. - /// The debugger module may add information to the database if it wants. - /// - /// The reason for introducing this event is that when an event line - /// LOAD_DLL happens, the database does not reflect the memory state yet - /// and therefore we can't add information about the dll into the database - /// in the get_debug_event() event. - /// Only when the kernel has adjusted the database we can do it. - /// Example: for imported PE DLLs we will add the exported event - /// names to the database. - /// - /// This event is generated in the main thread. - /// \param dlls_added (bool) - /// \param thr_names (::thread_name_vec_t *) (for the kernel only, must be NULL) - /// \return ::DRC_NONE, ::DRC_OK - ev_suspended, - - /// \name Threads - /// The following events manipulate threads. - /// These events are generated in debthread. - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - //@{ - - /// Suspend a running thread - /// Available if \ref DBG_HAS_THREAD_SUSPEND is set - /// \param tid (::thid_t) - ev_thread_suspend, - - /// Resume a suspended thread - /// Available if \ref DBG_HAS_THREAD_CONTINUE is set - /// \param tid (::thid_t) - ev_thread_continue, - - /// Specify resume action - /// Available if \ref DBG_HAS_SET_RESUME_MODE is set - /// \param tid (::thid_t) - /// \param resmod (::resume_mode_t) - ev_set_resume_mode, - - //@} - - /// Read thread registers. - /// This event is generated in debthread. - /// Must be implemented. - /// \param tid (::thid_t) thread id - /// \param clsmask (int) bitmask of register classes to read - /// \param values (::regval_t *) pointer to vector of regvals for all registers. - /// regval must have debugger_t::nregs elements - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_read_registers, - - /// Write one thread register. - /// This event is generated in debthread. - /// Must be implemented. - /// \param tid (::thid_t) thread id - /// \param regidx (int) register index - /// \param value (const ::regval_t *) new value of the register - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_write_register, - - /// Get information about the base of a segment register. - /// Currently used by the IBM PC module to resolve references like fs:0. - /// This event is generated in debthread. - /// Available if \ref DBG_HAS_THREAD_GET_SREG_BASE is set - /// \param answer (::ea_t *) pointer to the answer. can't be NULL. - /// \param tid (::thid_t) thread id - /// \param sreg_value (int) value of the segment register (returned by get_reg_val()) - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_thread_get_sreg_base, - - /// \name Memory manipulation - /// The following events manipulate bytes in the memory. - //@{ - - /// Get information on the memory ranges. - /// The debugger module fills 'ranges'. The returned vector must be sorted. - /// This event is generated in debthread. - /// Must be implemented. - /// \param ranges (::meminfo_vec_t *) - /// \param errbuf (::qstring *) may be NULL - /// \retval ::DRC_OK new memory layout is returned - /// \retval ::DRC_FAILED, ::DRC_NETERR, ::DRC_NOPROC, ::DRC_NOCHG, ::DRC_IDBSEG - ev_get_memory_info, - - /// Read process memory. - /// This event is generated in debthread. - /// \param nbytes (size_t *) number of read bytes - /// \param ea (::ea_t) - /// \param buffer (void *) - /// \param size (::size_t) - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NOPROC - ev_read_memory, - - /// Write process memory. - /// This event is generated in debthread. - /// \param nbytes (size_t *) number of written bytes - /// \param ea (::ea_t) - /// \param buffer (const void *) - /// \param size (::size_t) - /// \param errbuf (::qstring *) may be NULL - /// \retval ::DRC_OK, ::DRC_FAILED, ::DRC_NOPROC - ev_write_memory, - - //@} - - /// Is it possible to set breakpoint? - /// This event is generated in debthread or in the main thread if debthread - /// is not running yet. - /// It is generated to verify hardware breakpoints. - /// Available if \ref DBG_HAS_CHECK_BPT is set - /// \param bptvc (int *) breakpoint verification codes \ref BPT_ - /// \param type (::bpttype_t) \ref BPT_H - /// \param ea (::ea_t) - /// \param len (int) - /// \return ::DRC_OK, ::DRC_NONE - ev_check_bpt, - - /// Add/del breakpoints. - /// bpts array contains nadd bpts to add, followed by ndel bpts to del. - /// This event is generated in debthread. - /// \param nbpts (int *) number of updated breakpoints - /// \param bpts (::update_bpt_info_t *) - /// \param nadd (int) - /// \param ndel (int) - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR - ev_update_bpts, - - /// Update low-level (server side) breakpoint conditions. - /// This event is generated in debthread. - /// \param nupdated (int *) number of updated conditions - /// \param lowcnds (const ::lowcnd_t *) - /// \param nlowcnds (int) - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK, ::DRC_NETERR - ev_update_lowcnds, - - /// \name Remote file - /// Open/close/read/write a remote file. - /// These events are generated in the main thread - /// Available if \ref DBG_HAS_OPEN_FILE is set - //@{ - - /// \param file (const char *) - /// \param fsize (::uint64 *) - /// \param readonly (bool) - /// \param errbuf (::qstring *) may be NULL - /// \retval (int) handle - /// \retval -1 error - ev_open_file, - - /// \param fn (int) handle - /// \return ignored - ev_close_file, - - /// \param fn (int) handle - /// \param off (::qoff64_t) - /// \param buf (void *) - /// \param size (size_t) - /// \param errbuf (::qstring *) may be NULL - /// \retval number of read bytes - ev_read_file, - - /// \param fn (int) handle - /// \param off (::qoff64_t) - /// \param buf (const void *) - /// \param size (size_t) - /// \param errbuf (::qstring *) may be NULL - /// \retval number of written bytes - ev_write_file, - - //@} - - /// Map process address. - /// The debugger module may ignore this event. - /// This event is generated in debthread. - /// IDA will generate this event only if \ref DBG_HAS_MAP_ADDRESS is set. - /// \param mapped (::ea_t *) mapped address or #BADADDR - /// \param off (::ea_t) offset to map - /// \param regs (const ::regval_t *) current register values. - /// if regs == NULL, then perform global mapping, - /// which is independent on used registers - /// usually such a mapping is a trivial identity mapping - /// \param regnum (int) required mapping. - /// May be specified as a segment register number or a regular - /// register number if the required mapping can be deduced from it. - /// For example, esp implies that ss should be used. - /// \return ::DRC_NONE, ::DRC_OK see MAPPED - ev_map_address, - - /// Get pointer to debugger specific events. - /// This event returns a pointer to a structure that holds pointers to - /// debugger module specific events. For information on the structure - /// layout, please check the corresponding debugger module. Most debugger - /// modules return NULL because they do not have any extensions. Available - /// extensions may be generated from plugins. - /// This event is generated in the main thread. - /// \param ext (void **) - /// \return ::DRC_NONE, ::DRC_OK see EXT - ev_get_debmod_extensions, - - /// Calculate the call stack trace. - /// This event is generated when the process is suspended and should fill - /// the 'trace' object with the information about the current call stack. - /// If this event returns DRC_NONE, IDA will use the standard - /// mechanism (based on the frame pointer chain) to calculate the stack trace - /// This event is generated in the main thread. - /// Available if \ref DBG_HAS_UPDATE_CALL_STACK is set - /// \param tid (::thid_t) - /// \param trace (::call_stack_t *) - /// \retval ::DRC_NONE false or not implemented - /// \return ::DRC_OK success - ev_update_call_stack, - - /// Call application function. - /// This event calls a function from the debugged application. - /// This event is generated in debthread - /// Available if \ref HAS_APPCALL is set - /// \param[out] blob_ea (::ea_t *) ea of stkargs blob, - /// #BADADDR if failed and errbuf is filled - /// \param func_ea (::ea_t) address to call - /// \param tid (::thid_t) thread to use - /// \param fti (const ::func_type_data_t *) type information for the generated event - /// \param nargs (int) number of actual arguments - /// \param regargs (const ::regobjs_t *) information about register arguments - /// \param stkargs (::relobj_t *) memory blob to pass as stack arguments - /// (usually contains pointed data) - /// it must be relocated by the callback but not changed otherwise - /// \param retregs (::regobjs_t *) event return registers. - /// \param[out] errbuf (::qstring *) the error message. if empty on failure, see EVENT. - /// should not be filled if an appcall exception - /// happened but #APPCALL_DEBEV is set - /// \param[out] event (::debug_event_t *) the last debug event that occurred during appcall execution - /// filled only if the appcall execution fails and #APPCALL_DEBEV is set - /// \param options (int) appcall options, usually taken from \inf{appcall_options}. - /// possible values: combination of \ref APPCALL_ or 0 - /// \retval ::DRC_NONE - /// \retval ::DRC_OK, see BLOB_EA - ev_appcall, - - /// Cleanup after appcall(). - /// The debugger module must keep the stack blob in the memory until this event - /// is generated. It will be generated by the kernel for each successful appcall(). - /// There is an exception: if #APPCALL_MANUAL, IDA may not call cleanup_appcall. - /// If the user selects to terminate a manual appcall, then cleanup_appcall will be generated. - /// Otherwise, the debugger module should terminate the appcall when the generated - /// event returns. - /// This event is generated in debthread. - /// Available if \ref HAS_APPCALL is set - /// \param tid (::thid_t) - /// \retval ::DRC_EVENTS success, there are pending events - /// \retval ::DRC_OK success - /// \retval ::DRC_FAILED failed - /// \retval ::DRC_NETERR network error - ev_cleanup_appcall, - - /// Evaluate a low level breakpoint condition at 'ea'. - /// Other evaluation errors are displayed in a dialog box. - /// This call is used by IDA when the process has already been temporarily - /// suspended for some reason and IDA has to decide whether the process - /// should be resumed or definitely suspended because of a breakpoint - /// with a low level condition. - /// This event is generated in debthread. - /// \param tid (::thid_t) - /// \param ea (::ea_t) - /// \param errbuf (::qstring *) may be NULL - /// \retval ::DRC_OK condition is satisfied - /// \retval ::DRC_FAILED not satisfied - /// \retval ::DRC_NETERR network error - ev_eval_lowcnd, - - /// Perform a debugger-specific event. - /// This event is generated in debthread - /// \param fn (int) - /// \param buf (const void *) - /// \param size (size_t) - /// \param poutbuf (void **) - /// \param poutsize (ssize_t *) - /// \param errbuf (::qstring *) may be NULL - /// \retval DRC_... - ev_send_ioctl, - - /// Enable/Disable tracing. - /// The kernel will generated this event if the debugger plugin set DBG_FLAG_TRACER_MODULE. - /// TRACE_FLAGS can be a set of #STEP_TRACE, #INSN_TRACE, #BBLK_TRACE or #FUNC_TRACE. - /// This event is generated in the main thread. - /// \param tid (::thid_t) - /// \param enable (bool) - /// \param trace_flags (int) - /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NONE - ev_dbg_enable_trace, - - /// Is tracing enabled? - /// The kernel will generated this event if the debugger plugin set DBG_FLAG_TRACER_MODULE. - /// TRACE_BIT can be one of the following: #STEP_TRACE, #INSN_TRACE, #BBLK_TRACE or #FUNC_TRACE - /// \param tid (::thid_t) - /// \param tracebit (int) - /// \retval ::DRC_OK bit is set - /// \retval ::DRC_NONE bit is not set or not implemented - ev_is_tracing_enabled, - - /// Execute a command on the remote computer. - /// Available if \ref DBG_HAS_REXEC is set - /// \param cmdline (const char *) - /// \return (int) exit code - ev_rexec, - - /// Get the path to a file containing source debug info for the given module. - /// This allows srcinfo providers to call into the debugger when looking for debug info. - /// It is useful in certain cases like the iOS debugger, which is a remote debugger but - /// the remote debugserver does not provide dwarf info. So, we allow the debugger client - /// to decide where to look for debug info locally. - /// \param path (qstring *) output path (file might not exist) - /// \param base (::ea_t) base address of a module in the target process - /// \return ::DRC_NONE, ::DRC_OK result stored in PATH - ev_get_srcinfo_path, - - /// Search for a binary pattern in the program. - /// \param out (::ea_t *) binary pattern address - /// \param start_ea (::ea_t) linear address, start of range to search - /// \param end_ea (::ea_t) linear address, end of range to search (exclusive) - /// \param data (const ::compiled_binpat_vec_t *) - /// the prepared data to search for (see parse_binpat_str()) - /// \param srch_flags (int) combination of \ref BIN_SEARCH_ - /// \param errbuf (::qstring *) may be NULL - /// \return ::DRC_OK EA contains the binary pattern address - /// \retval ::DRC_FAILED not found - /// \retval ::DRC_NONE not implemented - /// \retval ::DRC_NETERR, ::DRC_ERROR - ev_bin_search, - }; - - /// Event notification callback. - /// It will be hooked to the HT_IDD notification point - /// when the debugger is loaded and unhooked during - /// the debugger unloading. - /// The debugger plugin will be the last one - /// who will receive the notification. - hook_cb_t *callback; - - /// Event notification handler - ssize_t notify(event_t event_code, ...) - { - va_list va; - va_start(va, event_code); - ssize_t code = invoke_callbacks(HT_IDD, event_code, va); - va_end(va); - return code; - } - drc_t notify_drc(event_t event_code, ...) - { - va_list va; - va_start(va, event_code); - drc_t code = drc_t(invoke_callbacks(HT_IDD, event_code, va)); - va_end(va); - return code; - } - - /// \defgroup DBG_PROC_ Debug process flags - /// Passed as 'dbg_proc_flags' parameter to debugger_t::start_process - //@{ - #define DBG_PROC_IS_DLL 0x01 ///< database contains a dll (not exe) - #define DBG_PROC_IS_GUI 0x02 ///< using gui version of ida - #define DBG_PROC_32BIT 0x04 ///< application is 32-bit - #define DBG_PROC_64BIT 0x08 ///< application is 64-bit - #define DBG_NO_TRACE 0x10 ///< do not trace the application (mac/linux) - #define DBG_HIDE_WINDOW 0x20 ///< application should be hidden on startup (windows) - //@} - - /// \defgroup BPT_ Breakpoint verification codes - /// Return values for debugger_t::check_bpt - //@{ - #define BPT_OK 0 ///< breakpoint can be set - #define BPT_INTERNAL_ERR 1 ///< interr occurred when verifying breakpoint - #define BPT_BAD_TYPE 2 ///< bpt type is not supported - #define BPT_BAD_ALIGN 3 ///< alignment is invalid - #define BPT_BAD_ADDR 4 ///< ea is invalid - #define BPT_BAD_LEN 5 ///< bpt len is invalid - #define BPT_TOO_MANY 6 ///< reached max number of supported breakpoints - #define BPT_READ_ERROR 7 ///< failed to read memory at bpt ea - #define BPT_WRITE_ERROR 8 ///< failed to write memory at bpt ea - #define BPT_SKIP 9 ///< update_bpts(): do not process bpt - #define BPT_PAGE_OK 10 ///< update_bpts(): ok, added a page bpt - //@} - - /// \defgroup APPCALL_ Appcall options - /// Passed as 'options' parameter to debugger_t::appcall - //@{ - #define APPCALL_MANUAL 0x0001 ///< Only set up the appcall, do not run. - ///< debugger_t::cleanup_appcall will not be generated by ida! - #define APPCALL_DEBEV 0x0002 ///< Return debug event information - #define APPCALL_TIMEOUT 0x0004 ///< Appcall with timeout. - ///< If timed out, errbuf will contain "timeout". - ///< See #SET_APPCALL_TIMEOUT and #GET_APPCALL_TIMEOUT - /// Set appcall timeout in milliseconds - #define SET_APPCALL_TIMEOUT(msecs) ((uint(msecs) << 16)|APPCALL_TIMEOUT) - /// Timeout value is contained in high 2 bytes of 'options' parameter - #define GET_APPCALL_TIMEOUT(options) (uint(options) >> 16) - //@} - - // Notification helpers, should be used instead of direct dbg->notify(...) calls - inline bool init_debugger(const char *hostname, int portnum, const char *password, qstring *errbuf=NULL); - inline bool term_debugger(void); - inline drc_t get_processes(procinfo_vec_t *procs, qstring *errbuf=NULL); - inline drc_t start_process(const char *path, - const char *args, - const char *startdir, - uint32 dbg_proc_flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf=NULL); - inline drc_t attach_process(pid_t pid, int event_id, uint32 dbg_proc_flags, qstring *errbuf=NULL); - inline drc_t detach_process(qstring *errbuf=NULL); - inline bool get_debapp_attrs(debapp_attrs_t *out_pattrs); - inline void rebase_if_required_to(ea_t new_base); - inline drc_t request_pause(qstring *errbuf=NULL); - inline drc_t exit_process(qstring *errbuf=NULL); - inline gdecode_t get_debug_event(debug_event_t *event, int timeout_ms); - inline drc_t resume(const debug_event_t *event, qstring *errbuf=NULL); - inline void set_exception_info(const exception_info_t *info, int qty); - inline void suspended(bool dlls_added, thread_name_vec_t *thr_names=NULL); - inline drc_t thread_suspend(thid_t tid, qstring *errbuf=NULL); - inline drc_t thread_continue(thid_t tid, qstring *errbuf=NULL); - inline drc_t set_resume_mode(thid_t tid, resume_mode_t resmod, qstring *errbuf=NULL); - inline drc_t read_registers(thid_t tid, int clsmask, regval_t *values, qstring *errbuf=NULL); - inline drc_t write_register(thid_t tid, int regidx, const regval_t *value, qstring *errbuf=NULL); - inline drc_t thread_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value, qstring *errbuf=NULL); - inline drc_t get_memory_info(meminfo_vec_t &ranges, qstring *errbuf=NULL); - inline drc_t read_memory(size_t *nbytes, ea_t ea, void *buffer, size_t size, qstring *errbuf=NULL); - inline drc_t write_memory(size_t *nbytes, ea_t ea, const void *buffer, size_t size, qstring *errbuf=NULL); - inline drc_t check_bpt(int *bptvc, bpttype_t type, ea_t ea, int len); - inline drc_t update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf=NULL); - inline drc_t update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf=NULL); - inline int open_file(const char *file, uint64 *fsize, bool readonly, qstring *errbuf=NULL); - inline void close_file(int fn); - inline ssize_t read_file(int fn, qoff64_t off, void *buf, size_t size, qstring *errbuf=NULL); - inline ssize_t write_file(int fn, qoff64_t off, const void *buf, size_t size, qstring *errbuf=NULL); - inline ea_t map_address(ea_t off, const regval_t *regs, int regnum); - inline const void *get_debmod_extensions(void); - inline bool update_call_stack(thid_t tid, call_stack_t *trace); - inline ea_t appcall( - ea_t func_ea, - thid_t tid, - const struct func_type_data_t *fti, - int nargs, - const struct regobjs_t *regargs, - struct relobj_t *stkargs, - struct regobjs_t *retregs, - qstring *errbuf, - debug_event_t *event, - int options); - inline drc_t cleanup_appcall(thid_t tid); - inline drc_t eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf=NULL); - inline drc_t send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize, qstring *errbuf=NULL); - inline bool dbg_enable_trace(thid_t tid, bool enable, int trace_flags); - inline bool is_tracing_enabled(thid_t tid, int tracebit); - inline int rexec(const char *cmdline); - inline bool get_srcinfo_path(qstring *path, ea_t base); - inline drc_t bin_search( - ea_t *out, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &data, - int srch_flags, - qstring *errbuf=NULL); -}; - -#ifndef __X86__ - CASSERT(sizeof(debugger_t) == 104); -#else - CASSERT(sizeof(debugger_t) == 60); -#endif - - -#define RQ_MASKING 0x0001 // masking step handler: unless errors, tmpbpt handlers won't be generated - // should be used only with request_internal_step() -#define RQ_SUSPEND 0x0002 // suspending step handler: suspends the app - // handle_debug_event: suspends the app -#define RQ_NOSUSP 0x0000 // running step handler: continues the app -#define RQ_IGNWERR 0x0004 // ignore breakpoint write failures -#define RQ_SILENT 0x0008 // all: no dialog boxes -#define RQ_VERBOSE 0x0000 // all: display dialog boxes -#define RQ_SWSCREEN 0x0010 // handle_debug_event: switch screens -#define RQ__NOTHRRF 0x0020 // handle_debug_event: do not refresh threads -#define RQ_PROCEXIT 0x0040 // snapshots: the process is exiting -#define RQ_IDAIDLE 0x0080 // handle_debug_event: ida is idle -#define RQ_SUSPRUN 0x0100 // handle_debug_event: suspend at PROCESS_STARTED -#define RQ_RESUME 0x0200 // handle_debug_event: resume application -#define RQ_RESMOD 0xF000 // resume_mode_t -#define RQ_RESMOD_SHIFT 12 -#define RQ_INTO (RESMOD_INTO << RQ_RESMOD_SHIFT) - -inline bool debugger_t::init_debugger(const char *hostname, int portnum, const char *password, qstring *errbuf) -{ - return notify_drc(ev_init_debugger, hostname, portnum, password, errbuf) == DRC_OK; -} -inline bool debugger_t::term_debugger(void) -{ - return notify_drc(ev_term_debugger) == DRC_OK; -} -inline drc_t debugger_t::get_processes(procinfo_vec_t *procs, qstring *errbuf) -{ - return notify_drc(ev_get_processes, procs, errbuf); -} -inline drc_t debugger_t::start_process( - const char *path, - const char *args, - const char *startdir, - uint32 dbg_proc_flags, - const char *input_path, - uint32 input_file_crc32, - qstring *errbuf) -{ - return notify_drc(ev_start_process, path, args, startdir, dbg_proc_flags, input_path, input_file_crc32, errbuf); -} -inline drc_t debugger_t::attach_process(pid_t pid, int event_id, uint32 dbg_proc_flags, qstring *errbuf) -{ - return notify_drc(ev_attach_process, pid, event_id, dbg_proc_flags, errbuf); -} -inline drc_t debugger_t::detach_process(qstring *errbuf) -{ - return notify_drc(ev_detach_process, errbuf); -} -inline bool debugger_t::get_debapp_attrs(debapp_attrs_t *out_pattrs) -{ - return notify_drc(ev_get_debapp_attrs, out_pattrs) != DRC_NONE; -} -inline void debugger_t::rebase_if_required_to(ea_t new_base) -{ - notify_drc(ev_rebase_if_required_to, new_base); -} -inline drc_t debugger_t::request_pause(qstring *errbuf) -{ - return notify_drc(ev_request_pause, errbuf); -} -inline drc_t debugger_t::exit_process(qstring *errbuf) -{ - return notify_drc(ev_exit_process, errbuf); -} -inline gdecode_t debugger_t::get_debug_event(debug_event_t *event, int timeout_ms) -{ - gdecode_t code = GDE_ERROR; - notify_drc(ev_get_debug_event, &code, event, timeout_ms); - return code; -} -inline drc_t debugger_t::resume(const debug_event_t *event, qstring *errbuf) -{ - return notify_drc(ev_resume, event, errbuf); -} -inline void debugger_t::set_exception_info(const exception_info_t *info, int qty) -{ - notify_drc(ev_set_exception_info, info, qty); -} -inline void debugger_t::suspended(bool dlls_added, thread_name_vec_t *thr_names) -{ - notify_drc(ev_suspended, dlls_added, thr_names); -} -inline drc_t debugger_t::thread_suspend(thid_t tid, qstring *errbuf) -{ - return notify_drc(ev_thread_suspend, tid, errbuf); -} -inline drc_t debugger_t::thread_continue(thid_t tid, qstring *errbuf) -{ - return notify_drc(ev_thread_continue, tid, errbuf); -} -inline drc_t debugger_t::set_resume_mode(thid_t tid, resume_mode_t resmod, qstring *errbuf) -{ - return notify_drc(ev_set_resume_mode, tid, resmod, errbuf); -} -inline drc_t debugger_t::read_registers(thid_t tid, int clsmask, regval_t *values, qstring *errbuf) -{ - return notify_drc(ev_read_registers, tid, clsmask, values, errbuf); -} -inline drc_t debugger_t::write_register(thid_t tid, int regidx, const regval_t *value, qstring *errbuf) -{ - return notify_drc(ev_write_register, tid, regidx, value, errbuf); -} -inline drc_t debugger_t::thread_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value, qstring *errbuf) -{ - return notify_drc(ev_thread_get_sreg_base, answer, tid, sreg_value, errbuf); -} -inline drc_t debugger_t::get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) -{ - return notify_drc(ev_get_memory_info, &ranges, errbuf); -} -inline drc_t debugger_t::read_memory(size_t *nbytes, ea_t ea, void *buffer, size_t size, qstring *errbuf) -{ - return notify_drc(ev_read_memory, nbytes, ea, buffer, size, errbuf); -} -inline drc_t debugger_t::write_memory(size_t *nbytes, ea_t ea, const void *buffer, size_t size, qstring *errbuf) -{ - return notify_drc(ev_write_memory, nbytes, ea, buffer, size, errbuf); -} -inline drc_t debugger_t::check_bpt(int *bptvc, bpttype_t type, ea_t ea, int len) -{ - return notify_drc(ev_check_bpt, bptvc, type, ea, len); -} -inline drc_t debugger_t::update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf) -{ - return notify_drc(ev_update_bpts, nbpts, bpts, nadd, ndel, errbuf); -} -inline drc_t debugger_t::update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf) -{ - return notify_drc(ev_update_lowcnds, nupdated, lowcnds, nlowcnds, errbuf); -} -inline int debugger_t::open_file(const char *file, uint64 *fsize, bool readonly, qstring *errbuf) -{ - return int(notify(ev_open_file, file, fsize, readonly, errbuf)); -} -inline void debugger_t::close_file(int fn) -{ - notify(ev_close_file, fn); -} -inline ssize_t debugger_t::read_file(int fn, qoff64_t off, void *buf, size_t size, qstring *errbuf) -{ - return notify(ev_read_file, fn, off, buf, size, errbuf); -} -inline ssize_t debugger_t::write_file(int fn, qoff64_t off, const void *buf, size_t size, qstring *errbuf) -{ - return notify(ev_write_file, fn, off, buf, size, errbuf); -} -inline ea_t debugger_t::map_address(ea_t off, const regval_t *rvs, int regnum) -{ - ea_t mapped; - return notify_drc(ev_map_address, &mapped, off, rvs, regnum) == DRC_OK - ? mapped - : off; -} -inline const void *debugger_t::get_debmod_extensions(void) -{ - void *ext; - if ( notify_drc(ev_get_debmod_extensions, &ext) != DRC_OK ) - ext = NULL; - return ext; -} -inline bool debugger_t::update_call_stack(thid_t tid, call_stack_t *trace) -{ - return notify_drc(ev_update_call_stack, tid, trace) != DRC_NONE; -} -inline ea_t debugger_t::appcall( - ea_t func_ea, - thid_t tid, - const struct func_type_data_t *fti, - int nargs, - const struct regobjs_t *regargs, - struct relobj_t *stkargs, - struct regobjs_t *retregs, - qstring *errbuf, - debug_event_t *event, - int options) -{ - ea_t blob_ea; - if ( notify_drc(ev_appcall, &blob_ea, func_ea, tid, fti, nargs, regargs, stkargs, retregs, errbuf, event, options) != DRC_OK ) - { - blob_ea = BADADDR; - if ( errbuf != NULL ) - *errbuf = "Debugger plugin does not support an application function call"; - } - return blob_ea; -} -inline drc_t debugger_t::cleanup_appcall(thid_t tid) -{ - return notify_drc(ev_cleanup_appcall, tid); -} -inline drc_t debugger_t::eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf) -{ - return notify_drc(ev_eval_lowcnd, tid, ea, errbuf); -} -inline drc_t debugger_t::send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize, qstring *errbuf) -{ - return notify_drc(ev_send_ioctl, fn, buf, size, poutbuf, poutsize, errbuf); -} -inline bool debugger_t::dbg_enable_trace(thid_t tid, bool enable, int trace_flags) -{ - return notify_drc(ev_dbg_enable_trace, tid, enable, trace_flags) == DRC_OK; -} -inline bool debugger_t::is_tracing_enabled(thid_t tid, int tracebit) -{ - return notify_drc(ev_is_tracing_enabled, tid, tracebit) == DRC_OK; -} -inline int debugger_t::rexec(const char *cmdline) -{ - return int(notify(ev_rexec, cmdline)); -} -inline bool debugger_t::get_srcinfo_path(qstring *path, ea_t base) -{ - return notify_drc(ev_get_srcinfo_path, path, base) == DRC_OK; -} -inline drc_t debugger_t::bin_search( - ea_t *out, - ea_t start_ea, - ea_t end_ea, - const compiled_binpat_vec_t &data, - int srch_flags, - qstring *errbuf) -{ - return notify_drc(ev_bin_search, out, start_ea, end_ea, &data, srch_flags, errbuf); -} -#endif // _IDD_HPP diff --git a/idasdk75/include/idp.hpp b/idasdk75/include/idp.hpp deleted file mode 100644 index eee6ce4..0000000 --- a/idasdk75/include/idp.hpp +++ /dev/null @@ -1,3097 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _IDP_HPP -#define _IDP_HPP - -#include -#include -#include -#include -#include -#include -#include - -/*! \file idp.hpp - - \brief Contains definition of the interface to IDP modules. - - The interface consists of two structures: - - definition of target assembler: ::ash - - definition of current processor: ::ph - - These structures contain information about target processor and assembler features. - - It also defines two groups of kernel events: - - processor_t::event_t processor related events - - idb_event:event_code_t database related events - - The processor related events are used to communicate with the processor module. - The database related events are used to inform any interested parties, like - plugins or processor modules, about the changes in the database. - -*/ - -typedef int help_t; ///< message id from ida.hlp - -struct outctx_t; -struct regval_t; -struct stkpnts_t; -struct simd_info_t; -struct reg_accesses_t; - -/// The interface version number. -/// \note see also #IDA_SDK_VERSION from pro.h - -#define IDP_INTERFACE_VERSION 700 - -//----------------------------------------------------------------------- -/// Structure used to describe byte streams -/// (for "ret" instruction and empirics) -struct bytes_t -{ - uchar len; - const uchar *bytes; -}; - -//----------------------------------------------------------------------- -/// Internal representation of processor instructions. -/// Definition of all internal instructions are kept in special arrays. -/// One of such arrays describes instruction names and features. -struct instruc_t -{ - const char *name; ///< instruction name - uint32 feature; ///< combination of \ref CF_ -/// \defgroup CF_ Instruction feature bits -/// Used by instruc_t::feature -//@{ -#define CF_STOP 0x00001 ///< Instruction doesn't pass execution to the - ///< next instruction -#define CF_CALL 0x00002 ///< CALL instruction (should make a procedure here) -#define CF_CHG1 0x00004 ///< The instruction modifies the first operand -#define CF_CHG2 0x00008 ///< The instruction modifies the second operand -#define CF_CHG3 0x00010 ///< The instruction modifies the third operand -#define CF_CHG4 0x00020 ///< The instruction modifies 4 operand -#define CF_CHG5 0x00040 ///< The instruction modifies 5 operand -#define CF_CHG6 0x00080 ///< The instruction modifies 6 operand -#define CF_USE1 0x00100 ///< The instruction uses value of the first operand -#define CF_USE2 0x00200 ///< The instruction uses value of the second operand -#define CF_USE3 0x00400 ///< The instruction uses value of the third operand -#define CF_USE4 0x00800 ///< The instruction uses value of the 4 operand -#define CF_USE5 0x01000 ///< The instruction uses value of the 5 operand -#define CF_USE6 0x02000 ///< The instruction uses value of the 6 operand -#define CF_JUMP 0x04000 ///< The instruction passes execution using indirect - ///< jump or call (thus needs additional analysis) -#define CF_SHFT 0x08000 ///< Bit-shift instruction (shl,shr...) -#define CF_HLL 0x10000 ///< Instruction may be present in a high level - ///< language function. -#define CF_CHG7 0x020000 ///< The instruction modifies the 7th operand -#define CF_CHG8 0x040000 ///< The instruction modifies the 8th operand -#define CF_USE7 0x080000 ///< The instruction uses value of the 7th operand -#define CF_USE8 0x100000 ///< The instruction uses value of the 8th operand -//@} -}; - - -/// Does an instruction with the specified feature modify the i-th operand? - -inline THREAD_SAFE bool has_cf_chg(uint32 feature, uint opnum) -{ - static const int bits[] = - { - CF_CHG1, CF_CHG2, CF_CHG3, CF_CHG4, - CF_CHG5, CF_CHG6, CF_CHG7, CF_CHG8, - }; - CASSERT(qnumber(bits) == UA_MAXOP); - return opnum < UA_MAXOP && (feature & bits[opnum]) != 0; -} - - -/// Does an instruction with the specified feature use a value of the i-th operand? - -inline THREAD_SAFE bool has_cf_use(uint32 feature, uint opnum) -{ - static const int bits[] = - { - CF_USE1, CF_USE2, CF_USE3, CF_USE4, - CF_USE5, CF_USE6, CF_USE7, CF_USE8, - }; - CASSERT(qnumber(bits) == UA_MAXOP); - return opnum < UA_MAXOP && (feature & bits[opnum]) != 0; -} - - -/// Does the specified instruction have the specified feature? - -idaman bool ida_export has_insn_feature(int icode, uint32 bit); - - - -/// Is the instruction a "call"? - -idaman bool ida_export is_call_insn(const insn_t &insn); - - -/// Is the instruction a "return"? - -idaman bool ida_export is_ret_insn(const insn_t &insn, bool strict=true); - - -/// Is the instruction an indirect jump? - -idaman bool ida_export is_indirect_jump_insn(const insn_t &insn); - - -/// Is the instruction the end of a basic block? - -idaman bool ida_export is_basic_block_end(const insn_t &insn, bool call_insn_stops_block); - - -//===================================================================== -/// Describes the target assembler. -/// An IDP module may have several target assemblers. -/// In this case you should create a structure for each supported -/// assembler. -struct asm_t -{ - uint32 flag; ///< \ref AS_ -/// \defgroup AS_ Assembler feature bits -/// Used by asm_t::flag. -//@{ -#define AS_OFFST 0x00000001L ///< offsets are 'offset xxx' ? -#define AS_COLON 0x00000002L ///< create colons after data names ? -#define AS_UDATA 0x00000004L ///< can use '?' in data directives - -#define AS_2CHRE 0x00000008L ///< double char constants are: "xy -#define AS_NCHRE 0x00000010L ///< char constants are: 'x -#define AS_N2CHR 0x00000020L ///< can't have 2 byte char consts - - // String literals: -#define AS_1TEXT 0x00000040L ///< 1 text per line, no bytes -#define AS_NHIAS 0x00000080L ///< no characters with high bit -#define AS_NCMAS 0x00000100L ///< no commas in ascii directives - -#define AS_HEXFM 0x00000E00L ///< mask - hex number format -#define ASH_HEXF0 0x00000000L ///< 34h -#define ASH_HEXF1 0x00000200L ///< h'34 -#define ASH_HEXF2 0x00000400L ///< 34 -#define ASH_HEXF3 0x00000600L ///< 0x34 -#define ASH_HEXF4 0x00000800L ///< $34 -#define ASH_HEXF5 0x00000A00L ///< <^R > (radix) -#define AS_DECFM 0x00003000L ///< mask - decimal number format -#define ASD_DECF0 0x00000000L ///< 34 -#define ASD_DECF1 0x00001000L ///< #34 -#define ASD_DECF2 0x00002000L ///< 34. -#define ASD_DECF3 0x00003000L ///< .34 -#define AS_OCTFM 0x0001C000L ///< mask - octal number format -#define ASO_OCTF0 0x00000000L ///< 123o -#define ASO_OCTF1 0x00004000L ///< 0123 -#define ASO_OCTF2 0x00008000L ///< 123 -#define ASO_OCTF3 0x0000C000L ///< @123 -#define ASO_OCTF4 0x00010000L ///< o'123 -#define ASO_OCTF5 0x00014000L ///< 123q -#define ASO_OCTF6 0x00018000L ///< ~123 -#define ASO_OCTF7 0x0001C000L ///< q'123 -#define AS_BINFM 0x000E0000L ///< mask - binary number format -#define ASB_BINF0 0x00000000L ///< 010101b -#define ASB_BINF1 0x00020000L ///< ^B010101 -#define ASB_BINF2 0x00040000L ///< %010101 -#define ASB_BINF3 0x00060000L ///< 0b1010101 -#define ASB_BINF4 0x00080000L ///< b'1010101 -#define ASB_BINF5 0x000A0000L ///< b'1010101' - -#define AS_UNEQU 0x00100000L ///< replace undefined data items with EQU (for ANTA's A80) -#define AS_ONEDUP 0x00200000L ///< One array definition per line -#define AS_NOXRF 0x00400000L ///< Disable xrefs during the output file generation -#define AS_XTRNTYPE 0x00800000L ///< Assembler understands type of extern symbols as ":type" suffix -#define AS_RELSUP 0x01000000L ///< Checkarg: 'and','or','xor' operations with addresses are possible -#define AS_LALIGN 0x02000000L ///< Labels at "align" keyword are supported. -#define AS_NOCODECLN 0x04000000L ///< don't create colons after code names -#define AS_NOSPACE 0x10000000L ///< No spaces in expressions -#define AS_ALIGN2 0x20000000L ///< .align directive expects an exponent rather than a power of 2 - ///< (.align 5 means to align at 32byte boundary) -#define AS_ASCIIC 0x40000000L ///< ascii directive accepts C-like escape sequences - ///< (\\n,\\x01 and similar) -#define AS_ASCIIZ 0x80000000L ///< ascii directive inserts implicit zero byte at the end -//@} - uint16 uflag; ///< user defined flags (local only for IDP) - ///< you may define and use your own bits - const char *name; ///< Assembler name (displayed in menus) - help_t help; ///< Help screen number, 0 - no help - const char *const *header; ///< array of automatically generated header lines - ///< they appear at the start of disassembled text - const char *origin; ///< org directive - const char *end; ///< end directive - const char *cmnt; ///< comment string (see also cmnt2) - char ascsep; ///< string literal delimiter - char accsep; ///< char constant delimiter - const char *esccodes; ///< special chars that cannot appear - ///< as is in string and char literals - - // Data representation (db,dw,...): - const char *a_ascii; ///< string literal directive - const char *a_byte; ///< byte directive - const char *a_word; ///< word directive - const char *a_dword; ///< NULL if not allowed - const char *a_qword; ///< NULL if not allowed - const char *a_oword; ///< NULL if not allowed - const char *a_float; ///< float; 4bytes; NULL if not allowed - const char *a_double; ///< double; 8bytes; NULL if not allowed - const char *a_tbyte; ///< long double; NULL if not allowed - const char *a_packreal; ///< packed decimal real NULL if not allowed - const char *a_dups; ///< array keyword. the following - ///< sequences may appear: - ///< - #h header - ///< - #d size - ///< - #v value - ///< - #s(b,w,l,q,f,d,o) size specifiers - ///< for byte,word, - ///< dword,qword, - ///< float,double,oword - const char *a_bss; ///< uninitialized data directive - ///< should include '%s' for the - ///< size of data - const char *a_equ; ///< 'equ' Used if AS_UNEQU is set - const char *a_seg; ///< 'seg ' prefix (example: push seg seg001) - - const char *a_curip; ///< current IP (instruction pointer) symbol in assembler - - /// Generate function header lines. - /// If NULL, then function headers are displayed as normal lines - void (idaapi *out_func_header)(outctx_t &ctx, func_t *); - - /// Generate function footer lines. - /// If NULL, then a comment line is displayed - void (idaapi *out_func_footer)(outctx_t &ctx, func_t *); - - const char *a_public; ///< "public" name keyword. NULL-use default, ""-do not generate - const char *a_weak; ///< "weak" name keyword. NULL-use default, ""-do not generate - const char *a_extrn; ///< "extern" name keyword - const char *a_comdef; ///< "comm" (communal variable) - - /// Get name of type of item at ea or id. - /// (i.e. one of: byte,word,dword,near,far,etc...) - ssize_t (idaapi *get_type_name)( - qstring *buf, - flags_t flag, - ea_t ea_or_id); - - const char *a_align; ///< "align" keyword - - char lbrace; ///< left brace used in complex expressions - char rbrace; ///< right brace used in complex expressions - - const char *a_mod; ///< % mod assembler time operation - const char *a_band; ///< & bit and assembler time operation - const char *a_bor; ///< | bit or assembler time operation - const char *a_xor; ///< ^ bit xor assembler time operation - const char *a_bnot; ///< ~ bit not assembler time operation - const char *a_shl; ///< << shift left assembler time operation - const char *a_shr; ///< >> shift right assembler time operation - const char *a_sizeof_fmt; ///< size of type (format string) - - uint32 flag2; ///< \ref AS2_ -/// \defgroup AS2_ Secondary assembler feature bits -/// Used by asm_t::flag2 -//@{ -#define AS2_BRACE 0x00000001 ///< Use braces for all expressions -#define AS2_STRINV 0x00000002 ///< Invert meaning of \inf{wide_high_byte_first} for text strings - ///< (For processors with bytes bigger than 8 bits) -#define AS2_BYTE1CHAR 0x00000004 ///< One symbol per processor byte - ///< Meaningful only for wide byte processors -#define AS2_IDEALDSCR 0x00000008 ///< Description of struc/union is in - ///< the 'reverse' form (keyword before name) - ///< the same as in borland tasm ideal -#define AS2_TERSESTR 0x00000010 ///< 'terse' structure initialization form - ///< NAME is supported -#define AS2_COLONSUF 0x00000020 ///< addresses may have ":xx" suffix - ///< this suffix must be ignored when extracting - ///< the address under the cursor -#define AS2_YWORD 0x00000040 ///< a_yword field is present and valid -//@} - - const char *cmnt2; ///< comment close string (usually NULL) - ///< this is used to denote a string which - ///< closes comments, for example, if the - ///< comments are represented with (* ... *) - ///< then cmnt = "(*" and cmnt2 = "*)" - const char *low8; ///< low8 operation, should contain %s for the operand - const char *high8; ///< high8 - const char *low16; ///< low16 - const char *high16; ///< high16 - const char *a_include_fmt; ///< the include directive (format string) - const char *a_vstruc_fmt; ///< if a named item is a structure and displayed - ///< in the verbose (multiline) form then display the name - ///< as printf(a_strucname_fmt, typename) - ///< (for asms with type checking, e.g. tasm ideal) - const char *a_rva; ///< 'rva' keyword for image based offsets - ///< (see #REFINFO_RVAOFF) - const char *a_yword; ///< 32-byte (256-bit) data; NULL if not allowed - ///< requires #AS2_YWORD -}; -#ifndef __X86__ -CASSERT(sizeof(asm_t) == 408); -#else -CASSERT(sizeof(asm_t) == 208); -#endif - -// forward declarations for notification helpers -struct proc_def_t; -struct extlang_t; -class qflow_chart_t; -struct libfunc_t; -struct fixup_data_t; -struct idd_opinfo_t; -class argloc_t; -struct func_type_data_t; -struct regobjs_t; -class callregs_t; -struct funcarg_t; - -//-------------------------------------------------------------------------- -struct event_listener_t -{ - size_t listener_flags = 0; // reserved - /// Callback to handle events. The event code depends on the event - /// group where the callback is attached to. - virtual ssize_t idaapi on_event(ssize_t code, va_list va) = 0; - DEFINE_VIRTUAL_DTOR(event_listener_t) -}; - -/// Install an event listener. -/// The installed listener will be called for all kernel events of the specified -/// type (\ref hook_type_t). -/// \param hook_type one of \ref hook_type_t constants -/// \param cb The event listener object -/// \param owner The listener owner. Points to an instance of: plugin_t, -/// processor_t, or loader_t. Can be nullptr, which means -/// undefined owner. The owner is used by the kernel for -/// automatic removal of the event listener when the owner is -/// unloaded from the memory. -/// \param hkcb_flags combination of \ref HKCB_ bits -/// \return success -idaman bool ida_export hook_event_listener( - hook_type_t hook_type, - event_listener_t *cb, - const void *owner, - int hkcb_flags=0); -/// \defgroup HKCB_ Hook installation bits. -//@{ -#define HKCB_GLOBAL 0x0001 ///< is global event listener? if true, the listener - ///< will survive database closing and opening. it - ///< will stay in the memory until explicitly - ///< unhooked. otherwise the kernel will delete it - ///< as soon as the owner is unloaded. - ///< should be used only with PLUGIN_FIX plugins. -#define HKCB_AUTODEL 0x0002 ///< automatically delete event listener object after uninstalling it -//@} - -/// Uninstall an event listener. -/// \param hook_type one of \ref hook_type_t constants -/// \param cb the listener object -/// \return success -/// Uninstalling a listener is necessary only for global listeners and -/// listeners with undefined owner. Other listeners are uninstalled automatically -/// when the owner module is unloaded. The uninstalled listener will be -/// automatically deleted by this call if it was installed with the HKCB_AUTODEL -// flag -idaman bool ida_export unhook_event_listener( - hook_type_t hook_type, - event_listener_t *cb); - -/// Declare listener with a context -#define DECLARE_LISTENER(listener_type, ctx_type, ctx_name) \ - struct listener_type : public event_listener_t \ - { \ - ctx_type &ctx_name; \ - listener_type(ctx_type &_ctx) : ctx_name(_ctx) {} \ - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; \ - } - -//===================================================================== -/// Describes a processor module (IDP). -/// An IDP file may have only one such structure called LPH. -/// The kernel will copy it to ::ph structure and use ::ph. -struct processor_t -{ - int32 version; ///< Expected kernel version, - ///< should be #IDP_INTERFACE_VERSION - int32 id; ///< one of \ref PLFM_ -/// \defgroup PLFM_ Processor IDs -/// Used by processor_t::id. -/// Numbers above 0x8000 are reserved for the third-party modules -//@{ -#define PLFM_386 0 ///< Intel 80x86 -#define PLFM_Z80 1 ///< 8085, Z80 -#define PLFM_I860 2 ///< Intel 860 -#define PLFM_8051 3 ///< 8051 -#define PLFM_TMS 4 ///< Texas Instruments TMS320C5x -#define PLFM_6502 5 ///< 6502 -#define PLFM_PDP 6 ///< PDP11 -#define PLFM_68K 7 ///< Motorola 680x0 -#define PLFM_JAVA 8 ///< Java -#define PLFM_6800 9 ///< Motorola 68xx -#define PLFM_ST7 10 ///< SGS-Thomson ST7 -#define PLFM_MC6812 11 ///< Motorola 68HC12 -#define PLFM_MIPS 12 ///< MIPS -#define PLFM_ARM 13 ///< Advanced RISC Machines -#define PLFM_TMSC6 14 ///< Texas Instruments TMS320C6x -#define PLFM_PPC 15 ///< PowerPC -#define PLFM_80196 16 ///< Intel 80196 -#define PLFM_Z8 17 ///< Z8 -#define PLFM_SH 18 ///< Renesas (formerly Hitachi) SuperH -#define PLFM_NET 19 ///< Microsoft Visual Studio.Net -#define PLFM_AVR 20 ///< Atmel 8-bit RISC processor(s) -#define PLFM_H8 21 ///< Hitachi H8/300, H8/2000 -#define PLFM_PIC 22 ///< Microchip's PIC -#define PLFM_SPARC 23 ///< SPARC -#define PLFM_ALPHA 24 ///< DEC Alpha -#define PLFM_HPPA 25 ///< Hewlett-Packard PA-RISC -#define PLFM_H8500 26 ///< Hitachi H8/500 -#define PLFM_TRICORE 27 ///< Tasking Tricore -#define PLFM_DSP56K 28 ///< Motorola DSP5600x -#define PLFM_C166 29 ///< Siemens C166 family -#define PLFM_ST20 30 ///< SGS-Thomson ST20 -#define PLFM_IA64 31 ///< Intel Itanium IA64 -#define PLFM_I960 32 ///< Intel 960 -#define PLFM_F2MC 33 ///< Fujistu F2MC-16 -#define PLFM_TMS320C54 34 ///< Texas Instruments TMS320C54xx -#define PLFM_TMS320C55 35 ///< Texas Instruments TMS320C55xx -#define PLFM_TRIMEDIA 36 ///< Trimedia -#define PLFM_M32R 37 ///< Mitsubishi 32bit RISC -#define PLFM_NEC_78K0 38 ///< NEC 78K0 -#define PLFM_NEC_78K0S 39 ///< NEC 78K0S -#define PLFM_M740 40 ///< Mitsubishi 8bit -#define PLFM_M7700 41 ///< Mitsubishi 16bit -#define PLFM_ST9 42 ///< ST9+ -#define PLFM_FR 43 ///< Fujitsu FR Family -#define PLFM_MC6816 44 ///< Motorola 68HC16 -#define PLFM_M7900 45 ///< Mitsubishi 7900 -#define PLFM_TMS320C3 46 ///< Texas Instruments TMS320C3 -#define PLFM_KR1878 47 ///< Angstrem KR1878 -#define PLFM_AD218X 48 ///< Analog Devices ADSP 218X -#define PLFM_OAKDSP 49 ///< Atmel OAK DSP -#define PLFM_TLCS900 50 ///< Toshiba TLCS-900 -#define PLFM_C39 51 ///< Rockwell C39 -#define PLFM_CR16 52 ///< NSC CR16 -#define PLFM_MN102L00 53 ///< Panasonic MN10200 -#define PLFM_TMS320C1X 54 ///< Texas Instruments TMS320C1x -#define PLFM_NEC_V850X 55 ///< NEC V850 and V850ES/E1/E2 -#define PLFM_SCR_ADPT 56 ///< Processor module adapter for processor modules written in scripting languages -#define PLFM_EBC 57 ///< EFI Bytecode -#define PLFM_MSP430 58 ///< Texas Instruments MSP430 -#define PLFM_SPU 59 ///< Cell Broadband Engine Synergistic Processor Unit -#define PLFM_DALVIK 60 ///< Android Dalvik Virtual Machine -#define PLFM_65C816 61 ///< 65802/65816 -#define PLFM_M16C 62 ///< Renesas M16C -#define PLFM_ARC 63 ///< Argonaut RISC Core -#define PLFM_UNSP 64 ///< SunPlus unSP -#define PLFM_TMS320C28 65 ///< Texas Instruments TMS320C28x -#define PLFM_DSP96K 66 ///< Motorola DSP96000 -#define PLFM_SPC700 67 ///< Sony SPC700 -#define PLFM_AD2106X 68 ///< Analog Devices ADSP 2106X -#define PLFM_PIC16 69 ///< Microchip's 16-bit PIC -#define PLFM_S390 70 ///< IBM's S390 -//@} - - uint32 flag; ///< \ref PR_ -/// \defgroup PR_ Processor feature bits -/// Used by processor_t::flag -//@{ -#define PR_SEGS 0x000001 ///< has segment registers? -#define PR_USE32 0x000002 ///< supports 32-bit addressing? -#define PR_DEFSEG32 0x000004 ///< segments are 32-bit by default -#define PR_RNAMESOK 0x000008 ///< allow user register names for location names -//#define PR_DB2CSEG 0x0010 // .byte directive in code segments -// // should define even number of bytes -// // (used by AVR processor) -#define PR_ADJSEGS 0x000020 ///< IDA may adjust segments' starting/ending addresses. -#define PR_DEFNUM 0x0000C0 ///< mask - default number representation -#define PRN_HEX 0x000000 ///< hex -#define PRN_OCT 0x000040 ///< octal -#define PRN_DEC 0x000080 ///< decimal -#define PRN_BIN 0x0000C0 ///< binary -#define PR_WORD_INS 0x000100 ///< instruction codes are grouped 2bytes in binary line prefix -#define PR_NOCHANGE 0x000200 ///< The user can't change segments and code/data attributes - ///< (display only) -#define PR_ASSEMBLE 0x000400 ///< Module has a built-in assembler and will react to ev_assemble -#define PR_ALIGN 0x000800 ///< All data items should be aligned properly -#define PR_TYPEINFO 0x001000 ///< the processor module supports type information callbacks - ///< ALL OF THEM SHOULD BE IMPLEMENTED! -#define PR_USE64 0x002000 ///< supports 64-bit addressing? -#define PR_SGROTHER 0x004000 ///< the segment registers don't contain the segment selectors. -#define PR_STACK_UP 0x008000 ///< the stack grows up -#define PR_BINMEM 0x010000 ///< the processor module provides correct segmentation for binary files - ///< (i.e. it creates additional segments) - ///< The kernel will not ask the user to specify the RAM/ROM sizes -#define PR_SEGTRANS 0x020000 ///< the processor module supports the segment translation feature - ///< (meaning it calculates the code - ///< addresses using the map_code_ea() function) -#define PR_CHK_XREF 0x040000 ///< don't allow near xrefs between segments with different bases -#define PR_NO_SEGMOVE 0x080000 ///< the processor module doesn't support move_segm() - ///< (i.e. the user can't move segments) -//#define PR_FULL_HIFXP 0x100000 // ::REF_VHIGH operand value contains full operand -// // (not only the high bits) Meaningful if \ph{high_fixup_bits} -#define PR_USE_ARG_TYPES 0x200000 ///< use \ph{use_arg_types} callback -#define PR_SCALE_STKVARS 0x400000 ///< use \ph{get_stkvar_scale} callback -#define PR_DELAYED 0x800000 ///< has delayed jumps and calls - ///< if this flag is set, \ph{is_basic_block_end}, \ph{has_delay_slot} - ///< should be implemented -#define PR_ALIGN_INSN 0x1000000 ///< allow ida to create alignment instructions arbitrarily. - ///< Since these instructions might lead to other wrong instructions - ///< and spoil the listing, IDA does not create them by default anymore -#define PR_PURGING 0x2000000 ///< there are calling conventions which may purge bytes from the stack -#define PR_CNDINSNS 0x4000000 ///< has conditional instructions -#define PR_USE_TBYTE 0x8000000 ///< ::BTMT_SPECFLT means _TBYTE type -#define PR_DEFSEG64 0x10000000 ///< segments are 64-bit by default -#define PR_OUTER 0x20000000 ///< has outer operands (currently only mc68k) -//@} - - uint32 flag2; ///< \ref PR2_ -/// \defgroup PR2_ Processor additional feature bits -/// Used by processor_t::flag2 -//@{ -#define PR2_MAPPINGS 0x000001 ///< the processor module uses memory mapping -#define PR2_IDP_OPTS 0x000002 ///< the module has processor-specific configuration options -#define PR2_REALCVT 0x000004 ///< the module has a custom 'ev_realcvt' implementation (otherwise IEEE-754 format is assumed) -#define PR2_CODE16_BIT 0x000008 ///< low bit of code addresses has special meaning - ///< e.g. ARM Thumb, MIPS16 -#define PR2_MACRO 0x000010 ///< processor supports macro instructions -#define PR2_USE_CALCREL 0x000020 ///< (Lumina) the module supports calcrel info -#define PR2_REL_BITS 0x000040 ///< (Lumina) calcrel info has bits granularity, not bytes - construction flag only -//@} - - bool has_idp_opts(void) const { return (flag2 & PR2_IDP_OPTS) != 0; } ///< #PR_IDP_OPTS - bool has_realcvt(void) const { return (flag2 & PR2_REALCVT) != 0; } ///< #PR_REALCVT - bool has_segregs(void) const { return (flag & PR_SEGS) != 0; } ///< #PR_SEGS - bool use32(void) const { return (flag & (PR_USE64|PR_USE32)) != 0; } ///< #PR_USE64 or #PR_USE32 - bool use64(void) const { return (flag & PR_USE64) != 0; } ///< #PR_USE64 - bool ti(void) const { return (flag & PR_TYPEINFO) != 0; } ///< #PR_TYPEINFO - bool stkup(void) const { return (flag & PR_STACK_UP) != 0; } ///< #PR_STACK_UP - bool use_tbyte(void) const { return (flag & PR_USE_TBYTE) != 0; } ///< #PR_USE_TBYTE - bool use_mappings(void) const { return (flag2 & PR2_MAPPINGS) != 0; } ///< #PR2_MAPPINGS - bool has_code16_bit(void) const { return (flag2 & PR2_CODE16_BIT) != 0; } ///< #PR2_CODE16_BIT - bool supports_macros(void) const { return (flag2 & PR2_MACRO) != 0; } ///< #PR2_MACRO - bool supports_calcrel(void) const { return (flag2 & PR2_USE_CALCREL) != 0; } ///< #PR2_USE_CALCREL - bool calcrel_in_bits(void) const { return (flag2 & PR2_REL_BITS) != 0; } ///< #PR2_REL_BITS - - - /// Get segment bitness - /// \retval 2 #PR_DEFSEG64 - /// \retval 1 #PR_DEFSEG32 - /// \retval 0 none specified - - int get_segm_bitness(void) const { return (flag & PR_DEFSEG64) != 0 ? 2 : (flag & PR_DEFSEG32) != 0; } - - int32 cnbits; ///< Number of bits in a byte - ///< for code segments (usually 8). - ///< IDA supports values up to supported - ///< address bits size - int32 dnbits; ///< Number of bits in a byte - ///< for non-code segments (usually 8). - ///< IDA supports values up to supported - ///< address bit size - - /// \name Byte size - /// Number of 8bit bytes required to hold one byte of the target processor. - //@{ - int cbsize(void) { return (cnbits+7)/8; } ///< for code segments - int dbsize(void) { return (dnbits+7)/8; } ///< for non-code segments - //@} - - /// \name Names - /// IDP module may support several compatible processors. - /// The following arrays define processor names: - //@{ - const char *const *psnames; ///< short processor names (NULL terminated). - ///< Each name should be shorter than 9 characters - const char *const *plnames; ///< long processor names (NULL terminated). - ///< No restriction on name lengths. - //@} - - inline int get_proc_index(); ///< \retval currently selected processor subtype (index into psnames/plnames) - - const asm_t *const *assemblers; ///< pointer to array of target - ///< assembler definitions. You may - ///< change this array when current - ///< processor is changed. - ///< (NULL terminated) - -/// Custom instruction codes defined by processor extension plugins -/// must be greater than or equal to this -#define CUSTOM_INSN_ITYPE 0x8000 - -/// processor_t::use_regarg_type uses this bit in the return value -/// to indicate that the register value has been spoiled -#define REG_SPOIL 0x80000000L - - typedef const regval_t &(idaapi regval_getter_t)( - const char *name, - const regval_t *regvalues); - - // - - /// Callback notification codes. - /// - /// These are passed to notify() when certain events occur in the kernel, - /// allowing the processor module to take the appropriate action. - /// - /// If you are not developing a processor module, you do not need to - /// use the codes directly many of them already have a corresponding function - /// to use instead (\idpcode{is_call_insn} vs is_call_insn(ea_t), for example). - /// - /// If you are developing a processor module, your notify() function - /// must implement the desired behavior when called with a given code. - /// Not all events need to be handled, some of them are optional. - enum event_t - { - ev_init, ///< The IDP module is just loaded. - ///< \param idp_modname (const char *) processor module name - ///< \retval <0 on failure - - ev_term, ///< The IDP module is being unloaded - - ev_newprc, ///< Before changing processor type. - ///< \param pnum (int) processor number in the array of processor names - ///< \param keep_cfg (bool) true: do not modify kernel configuration - ///< \retval 1 ok - ///< \retval <0 prohibit - - ev_newasm, ///< Before setting a new assembler. - ///< \param asmnum (int) - ///< See also ev_asm_installed - - ev_newfile, ///< A new file has been loaded. - ///< \param fname (char *) input file name - - ev_oldfile, ///< An old file has been loaded. - ///< \param fname (char *) input file name - - ev_newbinary, ///< IDA is about to load a binary file. - ///< \param filename (char *) binary file name - ///< \param fileoff (::qoff64_t) offset in the file - ///< \param basepara (::ea_t) base loading paragraph - ///< \param binoff (::ea_t) loader offset - ///< \param nbytes (::uint64) number of bytes to load - - ev_endbinary, ///< IDA has loaded a binary file. - ///< \param ok (bool) file loaded successfully? - - ev_set_idp_options, ///< Set IDP-specific configuration option - ///< Also see set_options_t in config.hpp - ///< \param keyword (const char *) - ///< \param value_type (int) - ///< \param value (const void *) - ///< \param errbuf (const char **) - a error message will be returned here (can be NULL) - ///< \param idb_loaded (bool) true if the ev_oldfile/ev_newfile events have been generated - ///< \retval 1 ok - ///< \retval 0 not implemented - ///< \retval -1 error (and message in errbuf) - - ev_set_proc_options, ///< Called if the user specified an option string in the command line: - ///< -p:. - ///< Can be used for setting a processor subtype. - ///< Also called if option string is passed to set_processor_type() - ///< and IDC's SetProcessorType(). - ///< \param options (const char *) - ///< \param confidence (int) - ///< 0: loader's suggestion - ///< 1: user's decision - ///< \retval <0 if bad option string - - ev_ana_insn, ///< Analyze one instruction and fill 'out' structure. - ///< This function shouldn't change the database, flags or anything else. - ///< All these actions should be performed only by emu_insn() function. - ///< \insn_t{ea} contains address of instruction to analyze. - ///< \param out (::insn_t *) - ///< \return length of the instruction in bytes, 0 if instruction can't be decoded. - ///< \retval 0 if instruction can't be decoded. - - ev_emu_insn, ///< Emulate instruction, create cross-references, plan to analyze - ///< subsequent instructions, modify flags etc. Upon entrance to this function, - ///< all information about the instruction is in 'insn' structure. - ///< \param insn (const ::insn_t *) - ///< \retval 1 ok - ///< \retval -1 the kernel will delete the instruction - - ev_out_header, ///< Function to produce start of disassembled text - ///< \param outctx (::outctx_t *) - ///< \retval void - - ev_out_footer, ///< Function to produce end of disassembled text - ///< \param outctx (::outctx_t *) - ///< \retval void - - ev_out_segstart, ///< Function to produce start of segment - ///< \param outctx (::outctx_t *) - ///< \param seg (::segment_t *) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_out_segend, ///< Function to produce end of segment - ///< \param outctx (::outctx_t *) - ///< \param seg (::segment_t *) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_out_assumes, ///< Function to produce assume directives - ///< when segment register value changes. - ///< \param outctx (::outctx_t *) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_out_insn, ///< Generate text representation of an instruction in 'ctx.insn' - ///< outctx_t provides functions to output the generated text. - ///< This function shouldn't change the database, flags or anything else. - ///< All these actions should be performed only by emu_insn() function. - ///< \param outctx (::outctx_t *) - ///< \retval void - - ev_out_mnem, ///< Generate instruction mnemonics. - ///< This callback should append the colored mnemonics to ctx.outbuf - ///< Optional notification, if absent, out_mnem will be called. - ///< \param outctx (::outctx_t *) - ///< \retval 1 if appended the mnemonics - ///< \retval 0 not implemented - - ev_out_operand, ///< Generate text representation of an instruction operand - ///< outctx_t provides functions to output the generated text. - ///< All these actions should be performed only by emu_insn() function. - ///< \param outctx (::outctx_t *) - ///< \param op (const ::op_t *) - ///< \retval 1 ok - ///< \retval -1 operand is hidden - - ev_out_data, ///< Generate text representation of data items - ///< This function may change the database and create cross-references - ///< if analyze_only is set - ///< \param outctx (::outctx_t *) - ///< \param analyze_only (bool) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_out_label, ///< The kernel is going to generate an instruction - ///< label line or a function header. - ///< \param outctx (::outctx_t *) - ///< \param colored_name (const char *) - ///< \retval <0 if the kernel should not generate the label - ///< \retval 0 not implemented or continue - - ev_out_special_item, ///< Generate text representation of an item in a special segment - ///< i.e. absolute symbols, externs, communal definitions etc - ///< \param outctx (::outctx_t *) - ///< \param segtype (uchar) - ///< \retval 1 ok - ///< \retval 0 not implemented - ///< \retval -1 overflow - - ev_gen_stkvar_def, ///< Generate stack variable definition line - ///< Default line is - ///< varname = type ptr value, - ///< where 'type' is one of byte,word,dword,qword,tbyte - ///< \param outctx (::outctx_t *) - ///< \param mptr (const ::member_t *) - ///< \param v (sval_t) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_gen_regvar_def, ///< Generate register variable definition line. - ///< \param outctx (::outctx_t *) - ///< \param v (::regvar_t *) - ///< \retval >0 ok, generated the definition text - ///< \retval 0 not implemented - - ev_gen_src_file_lnnum, ///< Callback: generate analog of: - ///< \code - ///< #line "file.c" 123 - ///< \endcode - ///< directive. - ///< \param outctx (::outctx_t *) output context - ///< \param file (const char *) source file (may be NULL) - ///< \param lnnum (size_t) line number - ///< \retval 1 directive has been generated - ///< \retval 0 not implemented - - ev_creating_segm, ///< A new segment is about to be created. - ///< \param seg (::segment_t *) - ///< \retval 1 ok - ///< \retval <0 segment should not be created - - ev_moving_segm, ///< May the kernel move the segment? - ///< \param seg (::segment_t *) segment to move - ///< \param to (::ea_t) new segment start address - ///< \param flags (int) combination of \ref MSF_ - ///< \retval 0 yes - ///< \retval <0 the kernel should stop - - ev_coagulate, ///< Try to define some unexplored bytes. - ///< This notification will be called if the - ///< kernel tried all possibilities and could - ///< not find anything more useful than to - ///< convert to array of bytes. - ///< The module can help the kernel and convert - ///< the bytes into something more useful. - ///< \param start_ea (::ea_t) - ///< \return number of converted bytes - - ev_undefine, ///< An item in the database (insn or data) is being deleted. - ///< \param ea (ea_t) - ///< \retval 1 do not delete srranges at the item end - ///< \retval 0 srranges can be deleted - - ev_treat_hindering_item, ///< An item hinders creation of another item. - ///< \param hindering_item_ea (::ea_t) - ///< \param new_item_flags (::flags_t) (0 for code) - ///< \param new_item_ea (::ea_t) - ///< \param new_item_length (::asize_t) - ///< \retval 0 no reaction - ///< \retval !=0 the kernel may delete the hindering item - - ev_rename, ///< The kernel is going to rename a byte. - ///< \param ea (::ea_t) - ///< \param new_name (const char *) - ///< \param flags (int) \ref SN_ - ///< \retval <0 if the kernel should not rename it. - ///< \retval 2 to inhibit the notification. I.e., - ///< the kernel should not rename, but - ///< 'set_name()' should return 'true'. - ///< also see \idpcode{renamed} - ///< the return value is ignored when kernel is going to delete name - - ev_is_far_jump, ///< is indirect far jump or call instruction? - ///< meaningful only if the processor has 'near' and 'far' reference types - ///< \param icode (int) - ///< \retval 0 not implemented - ///< \retval 1 yes - ///< \retval -1 no - - ev_is_sane_insn, ///< Is the instruction sane for the current file type?. - ///< \param insn (const ::insn_t*) the instruction - ///< \param no_crefs (int) - ///< 1: the instruction has no code refs to it. - ///< ida just tries to convert unexplored bytes - ///< to an instruction (but there is no other - ///< reason to convert them into an instruction) - ///< 0: the instruction is created because - ///< of some coderef, user request or another - ///< weighty reason. - ///< \retval >=0 ok - ///< \retval <0 no, the instruction isn't - ///< likely to appear in the program - - ev_is_cond_insn, ///< Is conditional instruction? - ///< \param insn (const ::insn_t *) instruction address - ///< \retval 1 yes - ///< \retval -1 no - ///< \retval 0 not implemented or not instruction - - ev_is_call_insn, ///< Is the instruction a "call"? - ///< \param insn (const ::insn_t *) instruction - ///< \retval 0 unknown - ///< \retval <0 no - ///< \retval 1 yes - - ev_is_ret_insn, ///< Is the instruction a "return"? - ///< \param insn (const ::insn_t *) instruction - ///< \param strict (bool) - ///< 1: report only ret instructions - ///< 0: include instructions like "leave" - ///< which begins the function epilog - ///< \retval 0 unknown - ///< \retval <0 no - ///< \retval 1 yes - - ev_may_be_func, ///< Can a function start here? - ///< \param insn (const ::insn_t*) the instruction - ///< \param state (int) autoanalysis phase - ///< 0: creating functions - ///< 1: creating chunks - ///< \return probability 1..100 - - ev_is_basic_block_end, ///< Is the current instruction end of a basic block?. - ///< This function should be defined for processors - ///< with delayed jump slots. - ///< \param insn (const ::insn_t*) the instruction - ///< \param call_insn_stops_block (bool) - ///< \retval 0 unknown - ///< \retval <0 no - ///< \retval 1 yes - - ev_is_indirect_jump, ///< Determine if instruction is an indirect jump. - ///< If #CF_JUMP bit cannot describe all jump types - ///< jumps, please define this callback. - ///< \param insn (const ::insn_t*) the instruction - ///< \retval 0 use #CF_JUMP - ///< \retval 1 no - ///< \retval 2 yes - - ev_is_insn_table_jump, ///< Determine if instruction is a table jump or call. - ///< If #CF_JUMP bit cannot describe all kinds of table - ///< jumps, please define this callback. - ///< It will be called for insns with #CF_JUMP bit set. - ///< \param insn (const ::insn_t*) the instruction - ///< \retval 0 yes - ///< \retval <0 no - - ev_is_switch, ///< Find 'switch' idiom. - ///< It will be called for instructions marked with #CF_JUMP. - ///< \param si (switch_info_t *), out - ///< \param insn (const ::insn_t *) instruction possibly belonging to a switch - ///< \retval 1 switch is found, 'si' is filled - ///< \retval 0 no switch found or not implemented - - ev_calc_switch_cases, ///< Calculate case values and targets for a custom jump table. - ///< \param casevec (::casevec_t *) vector of case values (may be NULL) - ///< \param targets (::eavec_t *) corresponding target addresses (my be NULL) - ///< \param insn_ea (::ea_t) address of the 'indirect jump' instruction - ///< \param si (::switch_info_t *) switch information - ///< \retval 1 ok - ///< \retval <=0 failed - - ev_create_switch_xrefs, ///< Create xrefs for a custom jump table. - ///< \param jumpea (::ea_t) address of the jump insn - ///< \param si (const ::switch_info_t *) switch information - ///< \return must return 1 - ///< Must be implemented if module uses custom jump tables, \ref SWI_CUSTOM - - ev_is_align_insn, ///< Is the instruction created only for alignment purposes?. - ///< Do not directly call this function, use ::is_align_insn() - ///< \param ea (ea_t) - instruction address - ///< \retval number of bytes in the instruction - - ev_is_alloca_probe, ///< Does the function at 'ea' behave as __alloca_probe? - ///< \param ea (::ea_t) - ///< \retval 1 yes - ///< \retval 0 no - - ev_delay_slot_insn, ///< Get delay slot instruction - ///< \param ea (::ea_t *) in: instruction address in question, - ///< out: (if the answer is positive) - ///< if the delay slot contains valid insn: - ///< the address of the delay slot insn - ///< else: - ///< BADADDR (invalid insn, e.g. a branch) - ///< \param bexec (bool *) execute slot if jumping, - ///< initially set to 'true' - ///< \param fexec (bool *) execute slot if not jumping, - ///< initally set to 'true' - ///< \retval 1 positive answer - ///< \retval <=0 ordinary insn - ///< \note Input EA may point to the instruction with a delay slot or - ///< to the delay slot instruction itself. - - ev_is_sp_based, ///< Check whether the operand is relative to stack pointer or frame pointer - ///< This event is used to determine how to output a stack variable - ///< If not implemented, then all operands are sp based by default. - ///< Implement this event only if some stack references use frame pointer - ///< instead of stack pointer. - ///< \param mode (int *) out, combination of \ref OP_FP_SP - ///< \param insn (const insn_t *) - ///< \param op (const op_t *) - ///< \retval 0 not implemented - ///< \retval 1 ok - - ev_can_have_type, ///< Can the operand have a type as offset, segment, decimal, etc? - ///< (for example, a register AX can't have a type, meaning that the user can't - ///< change its representation. see bytes.hpp for information about types and flags) - ///< \param op (const ::op_t *) - ///< \retval 0 unknown - ///< \retval <0 no - ///< \retval 1 yes - - ev_cmp_operands, ///< Compare instruction operands - ///< \param op1 (const ::op_t*) - ///< \param op2 (const ::op_t*) - ///< \retval 1 equal - ///< \retval -1 not equal - ///< \retval 0 not implemented - - ev_adjust_refinfo, ///< Called from apply_fixup before converting operand to reference. - ///< Can be used for changing the reference info. - ///< (e.g. the PPC module adds REFINFO_NOBASE for some references) - ///< \param ri (refinfo_t *) - ///< \param ea (::ea_t) instruction address - ///< \param n (int) operand number - ///< \param fd (const fixup_data_t *) - ///< \retval <0 do not create an offset - ///< \retval 0 not implemented or refinfo adjusted - - ev_get_operand_string, ///< Request text string for operand (cli, java, ...). - ///< \param buf (qstring *) - ///< \param insn (const ::insn_t*) the instruction - ///< \param opnum (int) operand number, -1 means any string operand - ///< \retval 0 no string (or empty string) - ///< \retval >0 original string length without terminating zero - - ev_get_reg_name, ///< Generate text representation of a register. - ///< Most processor modules do not need to implement this callback. - ///< It is useful only if \ph{reg_names}[reg] does not provide - ///< the correct register name. - ///< \param buf (qstring *) output buffer - ///< \param reg (int) internal register number as defined in the processor module - ///< \param width (size_t) register width in bytes - ///< \param reghi (int) if not -1 then this function will return the register pair - ///< \retval -1 if error - ///< \retval strlen(buf) if success - - ev_str2reg, ///< Convert a register name to a register number. - ///< The register number is the register index in the \ph{reg_names} array - ///< Most processor modules do not need to implement this callback - ///< It is useful only if \ph{reg_names}[reg] does not provide - ///< the correct register names - ///< \param regname (const char *) - ///< \retval register number + 1 - ///< \retval 0 not implemented or could not be decoded - - ev_get_autocmt, ///< Callback: get dynamic auto comment. - ///< Will be called if the autocomments are enabled - ///< and the comment retrieved from ida.int starts with - ///< '$!'. 'insn' contains valid info. - ///< \param buf (qstring *) output buffer - ///< \param insn (const ::insn_t*) the instruction - ///< \retval 1 new comment has been generated - ///< \retval 0 callback has not been handled. - ///< the buffer must not be changed in this case - - ev_get_bg_color, ///< Get item background color. - ///< Plugins can hook this callback to color disassembly lines dynamically - ///< \param color (::bgcolor_t *), out - ///< \param ea (::ea_t) - ///< \retval 0 not implemented - ///< \retval 1 color set - - ev_is_jump_func, ///< Is the function a trivial "jump" function?. - ///< \param pfn (::func_t *) - ///< \param jump_target (::ea_t *) - ///< \param func_pointer (::ea_t *) - ///< \retval <0 no - ///< \retval 0 don't know - ///< \retval 1 yes, see 'jump_target' and 'func_pointer' - - ev_func_bounds, ///< find_func_bounds() finished its work. - ///< The module may fine tune the function bounds - ///< \param possible_return_code (int *), in/out - ///< \param pfn (::func_t *) - ///< \param max_func_end_ea (::ea_t) (from the kernel's point of view) - ///< \retval void - - ev_verify_sp, ///< All function instructions have been analyzed. - ///< Now the processor module can analyze the stack pointer - ///< for the whole function - ///< \param pfn (::func_t *) - ///< \retval 0 ok - ///< \retval <0 bad stack pointer - - ev_verify_noreturn, ///< The kernel wants to set 'noreturn' flags for a function. - ///< \param pfn (::func_t *) - ///< \retval 0: ok. any other value: do not set 'noreturn' flag - - ev_create_func_frame, ///< Create a function frame for a newly created function - ///< Set up frame size, its attributes etc - ///< \param pfn (::func_t *) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_get_frame_retsize, ///< Get size of function return address in bytes - ///< If this event is not implemented, the kernel will assume - ///< - 8 bytes for 64-bit function - ///< - 4 bytes for 32-bit function - ///< - 2 bytes otherwise - ///< \param frsize (int *) frame size (out) - ///< \param pfn (const ::func_t *), can't be NULL - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_get_stkvar_scale_factor, ///< Should stack variable references be multiplied by - ///< a coefficient before being used in the stack frame?. - ///< Currently used by TMS320C55 because the references into - ///< the stack should be multiplied by 2 - ///< \return scaling factor - ///< \retval 0 not implemented - ///< \note #PR_SCALE_STKVARS should be set to use this callback - - ev_demangle_name, ///< Demangle a C++ (or another language) name into a user-readable string. - ///< This event is called by ::demangle_name() - ///< \param res (int32 *) value to return from ::demangle_name() - ///< \param out (::qstring *) output buffer. may be NULL - ///< \param name (const char *) mangled name - ///< \param disable_mask (uint32) flags to inhibit parts of output or compiler info/other (see MNG_) - ///< \param demreq (demreq_type_t) operation to perform - ///< \retval 1 if success - ///< \retval 0 not implemented - ///< \note if you call ::demangle_name() from the handler, protect against recursion! - - // the following 5 events are very low level - // take care of possible recursion - ev_add_cref, ///< A code reference is being created. - ///< \param from (::ea_t) - ///< \param to (::ea_t) - ///< \param type (::cref_t) - ///< \retval <0 cancel cref creation - ///< \retval 0 not implemented or continue - - ev_add_dref, ///< A data reference is being created. - ///< \param from (::ea_t) - ///< \param to (::ea_t) - ///< \param type (::dref_t) - ///< \retval <0 cancel dref creation - ///< \retval 0 not implemented or continue - - ev_del_cref, ///< A code reference is being deleted. - ///< \param from (::ea_t) - ///< \param to (::ea_t) - ///< \param expand (bool) - ///< \retval <0 cancel cref deletion - ///< \retval 0 not implemented or continue - - ev_del_dref, ///< A data reference is being deleted. - ///< \param from (::ea_t) - ///< \param to (::ea_t) - ///< \retval <0 cancel dref deletion - ///< \retval 0 not implemented or continue - - ev_coagulate_dref, ///< Data reference is being analyzed. - ///< plugin may correct 'code_ea' (e.g. for thumb mode refs, we clear the last bit) - ///< \param from (::ea_t) - ///< \param to (::ea_t) - ///< \param may_define (bool) - ///< \param code_ea (::ea_t *) - ///< \retval <0 cancel dref analysis - ///< \retval 0 not implemented or continue - - ev_may_show_sreg, ///< The kernel wants to display the segment registers - ///< in the messages window. - ///< \param current_ea (::ea_t) - ///< \retval <0 if the kernel should not show the segment registers. - ///< (assuming that the module has done it) - ///< \retval 0 not implemented - - ev_loader_elf_machine, ///< ELF loader machine type checkpoint. - ///< A plugin check of the 'machine_type'. If it is the desired one, - ///< the the plugin fills 'p_procname' with the processor name - ///< (one of the names present in \ph{psnames}). - ///< 'p_pd' is used to handle relocations, otherwise can be left untouched. - ///< This event occurs for each newly loaded ELF file - ///< \param li (linput_t *) - ///< \param machine_type (int) - ///< \param p_procname (const char **) - ///< \param p_pd (proc_def_t **) (see ldr\elf.h) - ///< \retval e_machine value (if it is different from the - ///< original e_machine value, procname and 'p_pd' will be ignored - ///< and the new value will be used) - - ev_auto_queue_empty, ///< One analysis queue is empty. - ///< \param type (::atype_t) - ///< \retval void - ///< see also \ref idb_event::auto_empty_finally - - ev_validate_flirt_func, ///< Flirt has recognized a library function. - ///< This callback can be used by a plugin or proc module - ///< to intercept it and validate such a function. - ///< \param start_ea (::ea_t) - ///< \param funcname (const char *) - ///< \retval -1 do not create a function, - ///< \retval 0 function is validated - - ev_adjust_libfunc_ea, ///< Called when a signature module has been matched against - ///< bytes in the database. This is used to compute the - ///< offset at which a particular module's libfunc should - ///< be applied. - ///< \param sig (const idasgn_t *) - ///< \param libfun (const libfunc_t *) - ///< \param ea (::ea_t *) \note 'ea' initially contains the ea_t of the - ///< start of the pattern match - ///< \retval 1 the ea_t pointed to by the third argument was modified. - ///< \retval <=0 not modified. use default algorithm. - - ev_assemble, ///< Assemble an instruction. - ///< (display a warning if an error is found). - ///< \param bin (::uchar *) pointer to output opcode buffer - ///< \param ea (::ea_t) linear address of instruction - ///< \param cs (::ea_t) cs of instruction - ///< \param ip (::ea_t) ip of instruction - ///< \param use32 (bool) is 32bit segment? - ///< \param line (const char *) line to assemble - ///< \return size of the instruction in bytes - - ev_extract_address, ///< Extract address from a string. - ///< \param out_ea (ea_t *), out - ///< \param screen_ea (ea_t) - ///< \param string (const char *) - ///< \param position (size_t) - ///< \retval 1 ok - ///< \retval 0 kernel should use the standard algorithm - ///< \retval -1 error - - ev_realcvt, ///< Floating point -> IEEE conversion - ///< \param m (void *) pointer to data - ///< \param e (uint16 *) internal IEEE format data - ///< \param swt (uint16) operation (see realcvt() in ieee.h) - ///< \retval 0 not implemented - ///< \retval 1 ok - ///< \retval \ref REAL_ERROR_ on error - - ev_gen_asm_or_lst, ///< Callback: generating asm or lst file. - ///< The kernel calls this callback twice, at the beginning - ///< and at the end of listing generation. The processor - ///< module can intercept this event and adjust its output - ///< \param starting (bool) beginning listing generation - ///< \param fp (FILE *) output file - ///< \param is_asm (bool) true:assembler, false:listing - ///< \param flags (int) flags passed to gen_file() - ///< \param outline (html_line_cb_t **) ptr to ptr to outline callback. - ///< if this callback is defined for this code, it will be - ///< used by the kernel to output the generated lines - ///< \retval void - - ev_gen_map_file, ///< Generate map file. If not implemented - ///< the kernel itself will create the map file. - ///< \param nlines (int *) number of lines in map file (-1 means write error) - ///< \param fp (FILE *) output file - ///< \retval 0 not implemented - ///< \retval 1 ok - ///< \retval -1 write error - - ev_create_flat_group, ///< Create special segment representing the flat group. - ///< \param image_base (::ea_t) - ///< \param bitness (int) - ///< \param dataseg_sel (::sel_t) - ///< return value is ignored - - ev_getreg, ///< IBM PC only internal request, - ///< should never be used for other purpose - ///< Get register value by internal index - ///< \param regval (uval_t *), out - ///< \param regnum (int) - ///< \retval 1 ok - ///< \retval 0 not implemented - ///< \retval -1 failed (undefined value or bad regnum) - - ev_analyze_prolog, ///< Analyzes function prolog, epilog, and updates - ///< purge, and function attributes - ///< \param ea (::ea_t) start of function - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_calc_spdelta, ///< Calculate amount of change to sp for the given insn. - ///< This event is required to decompile code snippets. - ///< \param spdelta (::sval_t *) - ///< \param insn (const ::insn_t *) - ///< \retval 1 ok - ///< \retval 0 not implemented - - ev_calcrel, ///< Reserved - ev_find_reg_value, ///< Find register value via a register tracker. - ///< The returned value in 'out' is valid - ///< before executing the instruction. - ///< \param out (uval_t *) pointer to the found value - ///< \param pinsn (const ::insn_t *) instruction - ///< \param reg (int) register index - ///< \retval 1 if implemented, and value was found - ///< \retval 0 not implemented, -1 decoding failed, or no value found - - ev_find_op_value, ///< Find operand value via a register tracker. - ///< The returned value in 'out' is valid - ///< before executing the instruction. - ///< \param out (uval_t *) pointer to the found value - ///< \param pinsn (const ::insn_t *) instruction - ///< \param opn (int) operand index - ///< \retval 1 if implemented, and value was found - ///< \retval 0 not implemented, -1 decoding failed, or no value found - - ev_replaying_undo, ///< Replaying an undo/redo buffer - ///< \param action_name (const char *) action that we perform undo/redo for. may be NULL for intermediary buffers. - ///< \param vec (const undo_records_t *) - ///< \param is_undo (bool) true if performing undo, false if performing redo - ///< This event may be generated multiple times per undo/redo - ev_ending_undo, ///< Ended undoing/redoing an action - ///< \param action_name (const char *) action that we finished undoing/redoing. is not NULL. - ///< \param is_undo (bool) true if performing undo, false if performing redo - - ev_set_code16_mode, ///< Some processors have ISA 16-bit mode - ///< e.g. ARM Thumb mode, PPC VLE, MIPS16 - ///< Set ISA 16-bit mode - ///< \param ea (ea_t) address to set new ISA mode - ///< \param code16 (bool) true for 16-bit mode, false for 32-bit mode - ev_get_code16_mode, ///< Get ISA 16-bit mode - ///< \param ea (ea_t) address to get the ISA mode - ///< \retval 1 16-bit mode - ///< \retval 0 not implemented or 32-bit mode - - ev_get_procmod, ///< Get pointer to the processor module object. - ///< All processor modules must implement this. - ///< The pointer is returned as size_t. - - ev_asm_installed, ///< After setting a new assembler - ///< \param asmnum (int) - ///< See also ev_newasm - - ev_get_reg_accesses, ///< Get info about the registers that are used/changed by an instruction. - ///< \param accvec (::reg_accesses_t*) out: info about accessed registers - ///< \param insn (const ::insn_t *) instruction in question - ///< \param flags (int) reserved, must be 0 - ///< \retval -1 if accvec is nullptr - ///< \retval 1 found the requested access (and filled accvec) - ///< \retval 0 not implemented - - ev_last_cb_before_debugger, ///< START OF DEBUGGER CALLBACKS - - ev_next_exec_insn = 1000, ///< Get next address to be executed - ///< This function must return the next address to be executed. - ///< If the instruction following the current one is executed, then it must return #BADADDR - ///< Usually the instructions to consider are: jumps, branches, calls, returns. - ///< This function is essential if the 'single step' is not supported in hardware. - ///< \param target (::ea_t *), out: pointer to the answer - ///< \param ea (::ea_t) instruction address - ///< \param tid (int) current therad id - ///< \param getreg (::processor_t::regval_getter_t *) function to get register values - ///< \param regvalues (const ::regval_t *) register values array - ///< \retval 0 unimplemented - ///< \retval 1 implemented - - ev_calc_step_over, ///< Calculate the address of the instruction which will be - ///< executed after "step over". The kernel will put a breakpoint there. - ///< If the step over is equal to step into or we cannot calculate - ///< the address, return #BADADDR. - ///< \param target (::ea_t *) pointer to the answer - ///< \param ip (::ea_t) instruction address - ///< \retval 0 unimplemented - ///< \retval 1 implemented - - ev_calc_next_eas, ///< Calculate list of addresses the instruction in 'insn' - ///< may pass control to. - ///< This callback is required for source level debugging. - ///< \param res (::eavec_t *), out: array for the results. - ///< \param insn (const ::insn_t*) the instruction - ///< \param over (bool) calculate for step over (ignore call targets) - ///< \retval <0 incalculable (indirect jumps, for example) - ///< \retval >=0 number of addresses of called functions in the array. - ///< They must be put at the beginning of the array (0 if over=true) - - ev_get_macro_insn_head, ///< Calculate the start of a macro instruction. - ///< This notification is called if IP points to the middle of an instruction - ///< \param head (::ea_t *), out: answer, #BADADDR means normal instruction - ///< \param ip (::ea_t) instruction address - ///< \retval 0 unimplemented - ///< \retval 1 implemented - - ev_get_dbr_opnum, ///< Get the number of the operand to be displayed in the - ///< debugger reference view (text mode). - ///< \param opnum (int *) operand number (out, -1 means no such operand) - ///< \param insn (const ::insn_t*) the instruction - ///< \retval 0 unimplemented - ///< \retval 1 implemented - - ev_insn_reads_tbit, ///< Check if insn will read the TF bit. - ///< \param insn (const ::insn_t*) the instruction - ///< \param getreg (::processor_t::regval_getter_t *) function to get register values - ///< \param regvalues (const ::regval_t *) register values array - ///< \retval 2 yes, will generate 'step' exception - ///< \retval 1 yes, will store the TF bit in memory - ///< \retval 0 no - - ev_clean_tbit, ///< Clear the TF bit after an insn like pushf stored it in memory. - ///< \param ea (::ea_t) instruction address - ///< \param getreg (::processor_t::regval_getter_t *) function to get register values - ///< \param regvalues (const ::regval_t *) register values array - ///< \retval 1 ok - ///< \retval 0 failed - - ev_get_idd_opinfo, ///< Get operand information. - ///< This callback is used to calculate the operand - ///< value for double clicking on it, hints, etc. - ///< \param opinf (::idd_opinfo_t *) the output buffer - ///< \param ea (::ea_t) instruction address - ///< \param n (int) operand number - ///< \param thread_id (int) current thread id - ///< \param getreg (::processor_t::regval_getter_t *) function to get register values - ///< \param regvalues (const ::regval_t *) register values array - ///< \retval 1 ok - ///< \retval 0 failed - - ev_get_reg_info, ///< Get register information by its name. - ///< example: "ah" returns: - ///< - main_regname="eax" - ///< - bitrange_t = { offset==8, nbits==8 } - ///< - ///< This callback may be unimplemented if the register - ///< names are all present in \ph{reg_names} and they all have - ///< the same size - ///< \param main_regname (const char **), out - ///< \param bitrange (::bitrange_t *), out: position and size of the value within 'main_regname' (empty bitrange == whole register) - ///< \param regname (const char *) - ///< \retval 1 ok - ///< \retval -1 failed (not found) - ///< \retval 0 unimplemented - - // END OF DEBUGGER CALLBACKS - - // START OF TYPEINFO CALLBACKS TODO: get this into doxygen output - // The codes below will be called only if #PR_TYPEINFO is set. - // Please note that some codes are optional but the more codes - // are implemented, the better the analysis. - - ev_last_cb_before_type_callbacks, - - ev_setup_til = 2000, ///< Setup default type libraries. (called after loading - ///< a new file into the database). - ///< The processor module may load tils, setup memory - ///< model and perform other actions required to set up - ///< the type system. - ///< This is an optional callback. - ///< \param none - ///< \retval void - - ev_get_abi_info, ///< Get all possible ABI names and optional extensions for given compiler - ///< abiname/option is a string entirely consisting of letters, digits and underscore - ///< \param abi_names (qstrvec_t *) - all possible ABis each in form abiname-opt1-opt2-... - ///< \param abi_opts (qstrvec_t *) - array of all possible options in form "opt:description" or opt:hint-line#description - ///< \param comp (comp_t) - compiler ID - ///< \retval 0 not implemented - ///< \retval 1 ok - - ev_max_ptr_size, ///< Get maximal size of a pointer in bytes. - ///< \param none - ///< \return max possible size of a pointer - - ev_get_default_enum_size, ///< Get default enum size. Not generated anymore. - ///< inf_get_cc_size_e() is used instead - - ev_get_cc_regs, ///< Get register allocation convention for given calling convention - ///< \param regs (::callregs_t *), out - ///< \param cc (::cm_t) - ///< \retval 1 - ///< \retval 0 not implemented - - ev_get_stkarg_offset, ///< Get offset from SP to the first stack argument. - ///< For example: pc: 0, hppa: -0x34, ppc: 0x38 - ///< \param none - ///< \return the offset (usually 0) - - ev_shadow_args_size, ///< Get size of shadow args in bytes. - ///< \param[out] shadow_args_size (int *) - ///< \param pfn (::func_t *) (may be NULL) - ///< \retval 1 if filled *shadow_args_size - ///< \retval 0 not implemented - - ev_get_simd_types, ///< Get SIMD-related types according to given attributes ant/or argument location - ///< \param out (::simd_info_vec_t *) - ///< \param simd_attrs (const ::simd_info_t *), may be NULL - ///< \param argloc (const ::argloc_t *), may be NULL - ///< \param create_tifs (bool) return valid tinfo_t objects, create if neccessary - ///< \retval number of found types - ///< \retval -1 error - ///< If name==NULL, initialize all SIMD types - - ev_calc_cdecl_purged_bytes, - ///< Calculate number of purged bytes after call. - ///< \param ea (::ea_t) address of the call instruction - ///< \return number of purged bytes (usually add sp, N) - - ev_calc_purged_bytes, ///< Calculate number of purged bytes by the given function type. - ///< \param[out] p_purged_bytes (int *) ptr to output - ///< \param fti (const ::func_type_data_t *) func type details - ///< \retval 1 - ///< \retval 0 not implemented - - ev_calc_retloc, ///< Calculate return value location. - ///< \param[out] retloc (::argloc_t *) - ///< \param rettype (const tinfo_t *) - ///< \param cc (::cm_t) - ///< \retval 0 not implemented - ///< \retval 1 ok, - ///< \retval -1 error - - ev_calc_arglocs, ///< Calculate function argument locations. - ///< This callback should fill retloc, all arglocs, and stkargs. - ///< This callback is never called for ::CM_CC_SPECIAL functions. - ///< \param fti (::func_type_data_t *) points to the func type info - ///< \retval 0 not implemented - ///< \retval 1 ok - ///< \retval -1 error - - ev_calc_varglocs, ///< Calculate locations of the arguments that correspond to '...'. - ///< \param ftd (::func_type_data_t *), inout: info about all arguments (including varargs) - ///< \param[out] aux_regs (::regobjs_t *) buffer for hidden register arguments, may be NULL - ///< \param[out] aux_stkargs (::relobj_t *) buffer for hidden stack arguments, may be NULL - ///< \param nfixed (int) number of fixed arguments - ///< \retval 0 not implemented - ///< \retval 1 ok - ///< \retval -1 error - ///< On some platforms variadic calls require - ///< passing additional information: for example, - ///< number of floating variadic arguments must - ///< be passed in rax on gcc-x64. The locations - ///< and values that constitute this additional - ///< information are returned in the buffers - ///< pointed by aux_regs and aux_stkargs - - ev_adjust_argloc, ///< Adjust argloc according to its type/size - ///< and platform endianess - ///< \param argloc (argloc_t *), inout - ///< \param type (const tinfo_t *), may be NULL - ///< NULL means primitive type of given size - ///< \param size (int) - ///< 'size' makes no sense if type != NULL - ///< (type->get_size() should be used instead) - ///< \retval 0 not implemented - ///< \retval 1 ok - ///< \retval -1 error - - ev_lower_func_type, ///< Get function arguments which should be converted to pointers when lowering function prototype. - ///< The processor module can also modify 'fti' in order to make non-standard conversion - ///< of some arguments. - ///< \param argnums (intvec_t *), out - numbers of arguments to be converted to pointers in acsending order - ///< \param fti (::func_type_data_t *), inout func type details - ///< (special values -1/-2 for return value - position of hidden 'retstr' argument: -1 - at the beginning, -2 - at the end) - ///< \retval 0 not implemented - ///< \retval 1 argnums was filled - ///< \retval 2 argnums was filled and made substantial changes to fti - - ev_equal_reglocs, ///< Are 2 register arglocs the same?. - ///< We need this callback for the pc module. - ///< \param a1 (::argloc_t *) - ///< \param a2 (::argloc_t *) - ///< \retval 1 yes - ///< \retval -1 no - ///< \retval 0 not implemented - - ev_use_stkarg_type, ///< Use information about a stack argument. - ///< \param ea (::ea_t) address of the push instruction which - ///< pushes the function argument into the stack - ///< \param arg (const ::funcarg_t *) argument info - ///< \retval 1 ok - ///< \retval <=0 failed, the kernel will create a comment with the - ///< argument name or type for the instruction - - ev_use_regarg_type, ///< Use information about register argument. - ///< \param[out] idx (int *) pointer to the returned value, may contain: - ///< - idx of the used argument, if the argument is defined - ///< in the current instruction, a comment will be applied by the kernel - ///< - idx | #REG_SPOIL - argument is spoiled by the instruction - ///< - -1 if the instruction doesn't change any registers - ///< - -2 if the instruction spoils all registers - ///< \param ea (::ea_t) address of the instruction - ///< \param rargs (const ::funcargvec_t *) vector of register arguments - ///< (including regs extracted from scattered arguments) - ///< \retval 1 - ///< \retval 0 not implemented - - ev_use_arg_types, ///< Use information about callee arguments. - ///< \param ea (::ea_t) address of the call instruction - ///< \param fti (::func_type_data_t *) info about function type - ///< \param rargs (::funcargvec_t *) array of register arguments - ///< \retval 1 (and removes handled arguments from fti and rargs) - ///< \retval 0 not implemented - - ev_arg_addrs_ready, ///< Argument address info is ready. - ///< \param caller (::ea_t) - ///< \param n (int) number of formal arguments - ///< \param tif (tinfo_t *) call prototype - ///< \param addrs (::ea_t *) argument intilization addresses - ///< \retval <0 do not save into idb; other values mean "ok to save" - - ev_decorate_name, ///< Decorate/undecorate a C symbol name. - ///< \param outbuf (::qstring *) output buffer - ///< \param name (const char *) name of symbol - ///< \param mangle (bool) true-mangle, false-unmangle - ///< \param cc (::cm_t) calling convention - ///< \param type (const ::tinfo_t *) name type (NULL-unknown) - ///< \retval 1 if success - ///< \retval 0 not implemented or failed - - ev_arch_changed, ///< The loader is done parsing arch-related - ///< information, which the processor module - ///< might want to use to finish its - ///< initialization. - ///< \retval 1 if success - ///< \retval 0 not implemented or failed - - ev_last_cb_before_loader, - - // END OF TYPEINFO CALLBACKS - - ev_loader=3000, ///< This code and higher ones are reserved - ///< for the loaders. - ///< The arguments and the return values are - ///< defined by the loaders - }; - - /// Event notification handler - hook_cb_t *_notify; - static ssize_t notify(event_t event_code, ...) - { - va_list va; - va_start(va, event_code); - ssize_t code = invoke_callbacks(HT_IDP, event_code, va); - va_end(va); - return code; - } - - // Notification helpers, should be used instead of direct ph.notify(...) calls - inline static ssize_t init(const char *idp_modname); - inline static ssize_t term(); - inline static ssize_t newprc(int pnum, bool keep_cfg); - inline static ssize_t newasm(int asmnum); - inline static ssize_t asm_installed(int asmnum); - inline static ssize_t newfile(const char *fname); - inline static ssize_t oldfile(const char *fname); - inline static ssize_t newbinary(const char *filename, qoff64_t fileoff, ea_t basepara, ea_t binoff, uint64 nbytes); - inline static ssize_t endbinary(bool ok); - inline static ssize_t creating_segm(segment_t *seg); - inline static ssize_t assemble(uchar *_bin, ea_t ea, ea_t cs, ea_t ip, bool _use32, const char *line); - inline static ssize_t ana_insn(insn_t *out); - inline static ssize_t emu_insn(const insn_t &insn); - inline static ssize_t out_header(outctx_t &ctx); - inline static ssize_t out_footer(outctx_t &ctx); - inline static ssize_t out_segstart(outctx_t &ctx, segment_t *seg); - inline static ssize_t out_segend(outctx_t &ctx, segment_t *seg); - inline static ssize_t out_assumes(outctx_t &ctx); - inline static ssize_t out_insn(outctx_t &ctx); - inline static ssize_t out_mnem(outctx_t &ctx); - inline static ssize_t out_operand(outctx_t &ctx, const op_t &op); - inline static ssize_t out_data(outctx_t &ctx, bool analyze_only); - inline static ssize_t out_label(outctx_t &ctx, const char *colored_name); - inline static ssize_t out_special_item(outctx_t &ctx, uchar segtype); - inline static ssize_t gen_stkvar_def(outctx_t &ctx, const class member_t *mptr, sval_t v); - inline static ssize_t gen_regvar_def(outctx_t &ctx, regvar_t *v); - inline static ssize_t gen_src_file_lnnum(outctx_t &ctx, const char *file, size_t lnnum); - inline static ssize_t rename(ea_t ea, const char *new_name, int flags); - inline static ssize_t may_show_sreg(ea_t current_ea); - inline static ssize_t coagulate(ea_t start_ea); - inline static void auto_queue_empty(/*atype_t*/ int type); - - inline static ssize_t func_bounds(int *possible_return_code, func_t *pfn, ea_t max_func_end_ea); - inline static ssize_t may_be_func(const insn_t &insn, int state); - inline static ssize_t is_sane_insn(const insn_t &insn, int no_crefs); - inline static ssize_t cmp_operands(const op_t &op1, const op_t &op2); - inline static ssize_t is_jump_func(func_t *pfn, ea_t *jump_target, ea_t *func_pointer); - inline static ssize_t is_basic_block_end(const insn_t &insn, bool call_insn_stops_block); - inline static ssize_t getreg(uval_t *rv, int regnum); - inline static ssize_t undefine(ea_t ea); - inline static ssize_t moving_segm(segment_t *seg, ea_t to, int flags); - inline static ssize_t is_sp_based(const insn_t &insn, const op_t &x); - inline static ssize_t is_far_jump(int icode); - inline static ssize_t is_call_insn(const insn_t &insn); - inline static ssize_t is_ret_insn(const insn_t &insn, bool strict); - inline static ssize_t is_align_insn(ea_t ea); - inline static ssize_t can_have_type(const op_t &op); - inline static ssize_t get_stkvar_scale_factor(); - inline static ssize_t demangle_name(int32 *res, qstring *out, const char *name, uint32 disable_mask, /*demreq_type_t*/ int demreq); - inline static ssize_t create_flat_group(ea_t image_base, int bitness, sel_t dataseg_sel); - inline static ssize_t is_alloca_probe(ea_t ea); - inline static ssize_t get_reg_name(qstring *buf, int reg, size_t width, int reghi); - inline static ssize_t gen_asm_or_lst(bool starting, FILE *fp, bool is_asm, int flags, /*html_line_cb_t ** */ void *outline); - inline static ssize_t gen_map_file(int *nlines, FILE *fp); - inline static ssize_t get_autocmt(qstring *buf, const insn_t &insn); - inline static ssize_t is_insn_table_jump(const insn_t &insn); - inline static ssize_t loader_elf_machine(linput_t *li, int machine_type, const char **p_procname, proc_def_t **p_pd); - inline static ssize_t is_indirect_jump(const insn_t &insn); - inline static ssize_t verify_noreturn(func_t *pfn); - inline static ssize_t verify_sp(func_t *pfn); - inline static ssize_t create_func_frame(func_t *pfn); - inline static ssize_t get_frame_retsize(int *retsize, const func_t *pfn); - inline static ssize_t analyze_prolog(ea_t fct_ea); - inline static ssize_t calc_spdelta(sval_t *spdelta, const insn_t &ins); - inline static ssize_t calcrel(bytevec_t *out_relbits, size_t *out_consumed, ea_t ea); - inline static ssize_t get_reg_accesses(reg_accesses_t *accvec, const insn_t &insn, int flags); - inline static ssize_t find_reg_value(uval_t *out, const insn_t &insn, int reg); - inline static ssize_t find_op_value(uval_t *out, const insn_t &insn, int op); - inline static ssize_t treat_hindering_item(ea_t hindering_item_ea, flags_t new_item_flags, ea_t new_item_ea, asize_t new_item_length); - inline static ssize_t extract_address(ea_t *out_ea, ea_t screen_ea, const char *string, size_t x); - inline static ssize_t str2reg(const char *regname); - inline static ssize_t is_switch(switch_info_t *si, const insn_t &insn); - inline static ssize_t create_switch_xrefs(ea_t jumpea, const switch_info_t &si); - inline static ssize_t calc_switch_cases(/*casevec_t * */void *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si); - inline static ssize_t get_bg_color(bgcolor_t *color, ea_t ea); - inline static ssize_t validate_flirt_func(ea_t start_ea, const char *funcname); - inline static ssize_t get_operand_string(qstring *buf, const insn_t &insn, int opnum); - inline static ssize_t add_cref(ea_t from, ea_t to, cref_t type); - inline static ssize_t add_dref(ea_t from, ea_t to, dref_t type); - inline static ssize_t del_cref(ea_t from, ea_t to, bool expand); - inline static ssize_t del_dref(ea_t from, ea_t to); - inline static ssize_t coagulate_dref(ea_t from, ea_t to, bool may_define, ea_t *code_ea); - inline static const char *set_idp_options(const char *keyword, int vtype, const void *value, bool idb_loaded = true); - inline static ssize_t set_proc_options(const char *options, int confidence); - inline static ssize_t adjust_libfunc_ea(const idasgn_t &sig, const libfunc_t &libfun, ea_t *ea); - inline static ssize_t realcvt(void *m, unsigned short *e, unsigned short swt); - inline bool delay_slot_insn(ea_t *ea, bool *bexec, bool *fexec); - inline static ssize_t adjust_refinfo(refinfo_t *ri, ea_t ea, int n, const fixup_data_t &fd); - inline static ssize_t is_cond_insn(const insn_t &insn); - inline static ssize_t set_code16_mode(ea_t ea, bool code16 = true); - inline static bool get_code16_mode(ea_t ea); - inline static ssize_t next_exec_insn(ea_t *target, ea_t ea, int tid, regval_getter_t *_getreg, const regval_t ®values); - inline static ssize_t calc_step_over(ea_t *target, ea_t ip); - inline static ssize_t get_macro_insn_head(ea_t *head, ea_t ip); - inline static ssize_t get_dbr_opnum(int *opnum, const insn_t &insn); - inline static ssize_t insn_reads_tbit(const insn_t &insn, regval_getter_t *_getreg, const regval_t ®values); - inline static ssize_t get_idd_opinfo(idd_opinfo_t *opinf, ea_t ea, int n, int thread_id, regval_getter_t *_getreg, const regval_t ®values); - inline static ssize_t calc_next_eas(eavec_t *res, const insn_t &insn, bool over); - inline static ssize_t clean_tbit(ea_t ea, regval_getter_t *_getreg, const regval_t ®values); - inline static const char *get_reg_info(const char *regname, bitrange_t *bitrange); - inline static ssize_t setup_til(); - inline static ssize_t max_ptr_size(); - inline static ssize_t calc_cdecl_purged_bytes(ea_t ea); - inline static ssize_t equal_reglocs(const argloc_t &a1, const argloc_t &a2); - inline static ssize_t decorate_name(qstring *outbuf, const char *name, bool mangle, cm_t cc, const tinfo_t &type); - inline static ssize_t calc_retloc(argloc_t *retloc, const tinfo_t &rettype, cm_t cc); - inline static ssize_t calc_varglocs(func_type_data_t *ftd, regobjs_t *regs, relobj_t *stkargs, int nfixed); - inline static ssize_t calc_arglocs(func_type_data_t *fti); - inline static ssize_t use_stkarg_type(ea_t ea, const funcarg_t &arg); - inline static ssize_t use_regarg_type(int *idx, ea_t ea, /*const funcargvec_t * */void *rargs); - inline static ssize_t use_arg_types(ea_t ea, func_type_data_t *fti, /*funcargvec_t * */void *rargs); - inline static ssize_t calc_purged_bytes(int *p_purged_bytes, const func_type_data_t &fti); - inline static ssize_t shadow_args_size(int *shadow_size, func_t *pfn); - inline static ssize_t get_cc_regs(callregs_t *regs, cm_t cc); - inline static ssize_t get_simd_types(/*simd_info_vec_t * */void *out, const simd_info_t *simd_attrs, const argloc_t *argloc, bool create_tifs); - inline static ssize_t arg_addrs_ready(ea_t caller, int n, const tinfo_t &tif, ea_t *addrs); - inline static ssize_t adjust_argloc(argloc_t *argloc, const tinfo_t *type, int size); - inline static ssize_t lower_func_type(intvec_t *argnums, func_type_data_t *fti); - inline static ssize_t get_abi_info(qstrvec_t *abi_names, qstrvec_t *abi_opts, comp_t comp); - inline static ssize_t arch_changed(); -/// \defgroup OP_FP_SP SP/FP operand flags -/// Return values for processor_t::is_sp_based() -//@{ -#define OP_FP_BASED 0x00000000 ///< operand is FP based -#define OP_SP_BASED 0x00000001 ///< operand is SP based -#define OP_SP_ADD 0x00000000 ///< operand value is added to the pointer -#define OP_SP_SUB 0x00000002 ///< operand value is subtracted from the pointer -//@} - - /// Get the stack variable scaling factor. - /// Useful for processors who refer to the stack with implicit scaling factor. - /// TMS320C55 for example: SP(#1) really refers to (SP+2) - int get_stkvar_scale(void) - { - if ( (flag & PR_SCALE_STKVARS) == 0 ) - return 1; - int scale = notify(ev_get_stkvar_scale_factor); - if ( scale == 0 ) - error("Request ph.get_stkvar_scale_factor should be implemented"); - else if ( scale <= 0 ) - error("Invalid return code from ph.get_stkvar_scale_factor request"); - return scale; - } - - // Processor register information: - const char *const *reg_names; ///< array of register names - int32 regs_num; ///< number of registers - - /// \name Segment registers - /// Segment register information (use virtual CS and DS registers if your - /// processor doesn't have segment registers): - //@{ - int32 reg_first_sreg; ///< number of first segment register - int32 reg_last_sreg; ///< number of last segment register - int32 segreg_size; ///< size of a segment register in bytes - //@} - - /// \name Virtual segment registers - /// If your processor doesn't have segment registers, - /// you should define 2 virtual segment registers for CS and DS. - /// Let's call them rVcs and rVds. - //@{ - int32 reg_code_sreg; ///< number of CS register - int32 reg_data_sreg; ///< number of DS register - //@} - - - /// \name Empirics - //@{ - const bytes_t *codestart; ///< Array of typical code start sequences. - ///< This array is used when a new file - ///< is loaded to find the beginnings of code - ///< sequences. - ///< This array is terminated with - ///< a zero length item. - const bytes_t *retcodes; ///< Array of 'return' instruction opcodes. - ///< This array is used to determine - ///< form of autogenerated locret_... - ///< labels. - ///< The last item of it should be { 0, NULL } - ///< This array may be NULL - ///< Better way of handling return instructions - ///< is to define the \idpcode{is_ret_insn} callback in - ///< the notify() function - //@} - - /// \name Instruction set - //@{ - int32 instruc_start; ///< icode of the first instruction - int32 instruc_end; ///< icode of the last instruction + 1 - - /// Does the given value specify a valid instruction for this instruction set?. - /// See #instruc_start and #instruc_end - bool is_canon_insn(uint16 itype) const { return itype >= instruc_start && itype < instruc_end; } - - const instruc_t *instruc; ///< Array of instructions - //@} - - /// Size of long double (tbyte) for this processor - /// (meaningful only if \ash{a_tbyte} != NULL) - size_t tbyte_size; - - /// Number of digits in floating numbers after the decimal point. - /// If an element of this array equals 0, then the corresponding - /// floating point data is not used for the processor. - /// This array is used to align numbers in the output. - /// - real_width[0] - number of digits for short floats (only PDP-11 has them) - /// - real_width[1] - number of digits for "float" - /// - real_width[2] - number of digits for "double" - /// - real_width[3] - number of digits for "long double" - /// - /// Example: IBM PC module has { 0,7,15,19 } - char real_width[4]; - - /// Icode of return instruction. It is ok to give any of possible return instructions - int32 icode_return; - - /// Reserved, currently equals to NULL - void *unused_slot; - - inline void ensure_processor(void); - inline size_t sizeof_ldbl() const; - inline ssize_t get_stkarg_offset() const; - inline bool is_funcarg_off(const func_t *pfn, uval_t frameoff) const; - inline sval_t lvar_off(const func_t *pfn, uval_t frameoff) const; - inline bool is_lumina_usable() const; -}; -#ifndef __X86__ -CASSERT(sizeof(processor_t) == 144); -#else -CASSERT(sizeof(processor_t) == 104); -#endif - -// The following two structures contain information about the current -// processor and assembler. - -//-V:ph:688 local variable ph with the same name -#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_PH__) -idaman processor_t ida_export_data ph; ///< current processor -idaman asm_t ida_export_data ash; ///< current assembler -#endif - -idaman processor_t *ida_export get_ph(); -#define PH (*get_ph()) -idaman asm_t *ida_export get_ash(); -#define ASH (*get_ash()) - -#ifndef SWIG -// ignore_micro manager: can be used in modules/plugins as a base class -struct ignore_micro_t -{ - //-------------------------------------------------------------------------- - /// \name Ignore micro - /// netnode to keep information about various kinds of instructions - //@{ - netnode ignore_micro; - -#define IM_NONE 0 // regular instruction -#define IM_PROLOG 1 // prolog instruction -#define IM_EPILOG 2 // epilog instruction -#define IM_SWITCH 3 // switch instruction (the indirect jump should not be marked) - - inline void init_ignore_micro(void) { ignore_micro.create("$ ignore micro"); } - inline void term_ignore_micro(void) { ignore_micro = BADNODE; } - inline char get_ignore_micro(ea_t ea) const { return ignore_micro.charval_ea(ea, 0); } - inline void set_ignore_micro(ea_t ea, uchar im_type) { ignore_micro.charset_ea(ea, im_type, 0); } - inline void clr_ignore_micro(ea_t ea) { ignore_micro.chardel_ea(ea, 0); } - inline ea_t next_marked_insn(ea_t ea) { return node2ea(ignore_micro.charnext(ea2node(ea), 0)); } - inline void mark_prolog_insn(ea_t ea) { set_ignore_micro(ea, IM_PROLOG); } - inline void mark_epilog_insn(ea_t ea) { set_ignore_micro(ea, IM_EPILOG); } - inline void mark_switch_insn(ea_t ea) { set_ignore_micro(ea, IM_SWITCH); } - inline bool is_prolog_insn(ea_t ea) const { return get_ignore_micro(ea) == IM_PROLOG; } - inline bool is_epilog_insn(ea_t ea) const { return get_ignore_micro(ea) == IM_EPILOG; } - inline bool is_switch_insn(ea_t ea) const { return get_ignore_micro(ea) == IM_SWITCH; } - inline bool should_ignore_micro(ea_t ea) const { return get_ignore_micro(ea) != IM_NONE; } - //@} -}; -#endif // SWIG - -// Each processor module subclasses this class and reacts to HT_IDP events -struct procmod_t : public event_listener_t, public ignore_micro_t -{ - processor_t &ph; - asm_t &ash; - size_t procmod_flags = 0; - size_t reserved = 0; // for the future - procmod_t() : ph(PH), ash(ASH) {} -}; - -struct plugmod_t -{ - size_t owner = 0; // internal info used by the kernel - size_t reserved = 0; // for the future - - /// Invoke the plugin. - virtual bool idaapi run(size_t arg) = 0; - - /// Helper function to hook event listeners. - bool hook_event_listener( - hook_type_t hook_type, - event_listener_t *cb, - int hkcb_flags=0) - { - return ::hook_event_listener(hook_type, cb, this, hkcb_flags); - } - - /// Virtual destructor. - virtual ~plugmod_t() {} -}; - -inline ssize_t processor_t::init(const char *idp_modname) -{ - return notify(ev_init, idp_modname); -} -inline ssize_t processor_t::term() -{ - return notify(ev_term); -} -inline ssize_t processor_t::newprc(int pnum, bool keep_cfg) -{ - return notify(ev_newprc, pnum, keep_cfg); -} -inline ssize_t processor_t::newasm(int asmnum) -{ - return notify(ev_newasm, asmnum); -} -inline ssize_t processor_t::asm_installed(int asmnum) -{ - return notify(ev_asm_installed, asmnum); -} -inline ssize_t processor_t::get_reg_accesses(reg_accesses_t *accvec, const insn_t &insn, int flags) -{ - return notify(ev_get_reg_accesses, accvec, &insn, flags); -} -inline ssize_t processor_t::newfile(const char *fname) -{ - return notify(ev_newfile, fname); -} -inline ssize_t processor_t::oldfile(const char *fname) -{ - return notify(ev_oldfile, fname); -} -inline ssize_t processor_t::newbinary(const char *filename, qoff64_t fileoff, ea_t basepara, ea_t binoff, uint64 nbytes) -{ - return notify(ev_newbinary, filename, fileoff, basepara, binoff, nbytes); -} -inline ssize_t processor_t::endbinary(bool ok) -{ - return notify(ev_endbinary, ok); -} -inline ssize_t processor_t::creating_segm(segment_t *seg) -{ - return notify(ev_creating_segm, seg); -} -inline ssize_t processor_t::assemble(uchar *_bin, ea_t ea, ea_t cs, ea_t ip, bool _use32, const char *line) -{ - return notify(ev_assemble, _bin, ea, cs, ip, _use32, line, _bin); -} -inline ssize_t processor_t::ana_insn(insn_t *out) -{ - return notify(ev_ana_insn, out); -} -inline ssize_t processor_t::emu_insn(const insn_t &insn) -{ - return notify(ev_emu_insn, &insn); -} -inline ssize_t processor_t::out_header(outctx_t &ctx) -{ - return notify(ev_out_header, &ctx); -} -inline ssize_t processor_t::out_footer(outctx_t &ctx) -{ - return notify(ev_out_footer, &ctx); -} -inline ssize_t processor_t::out_segstart(outctx_t &ctx, segment_t *seg) -{ - return notify(ev_out_segstart, &ctx, seg); -} -inline ssize_t processor_t::out_segend(outctx_t &ctx, segment_t *seg) -{ - return notify(ev_out_segend, &ctx, seg); -} -inline ssize_t processor_t::out_assumes(outctx_t &ctx) -{ - return notify(ev_out_assumes, &ctx); -} -inline ssize_t processor_t::out_insn(outctx_t &ctx) -{ - return notify(ev_out_insn, &ctx); -} -inline ssize_t processor_t::out_mnem(outctx_t &ctx) -{ - return notify(ev_out_mnem, &ctx); -} -inline ssize_t processor_t::out_operand(outctx_t &ctx, const op_t &op) -{ - return notify(ev_out_operand, &ctx, &op); -} -inline ssize_t processor_t::out_data(outctx_t &ctx, bool analyze_only) -{ - return notify(ev_out_data, &ctx, analyze_only); -} -inline ssize_t processor_t::out_label(outctx_t &ctx, const char *colored_name) -{ - return notify(ev_out_label, &ctx, colored_name); -} -inline ssize_t processor_t::out_special_item(outctx_t &ctx, uchar segtype) -{ - return notify(ev_out_special_item, &ctx, segtype); -} -inline ssize_t processor_t::gen_stkvar_def(outctx_t &ctx, const class member_t *mptr, sval_t v) -{ - return notify(ev_gen_stkvar_def, &ctx, mptr, v); -} -inline ssize_t processor_t::gen_regvar_def(outctx_t &ctx, regvar_t *v) -{ - return notify(ev_gen_regvar_def, &ctx, v); -} -inline ssize_t processor_t::gen_src_file_lnnum(outctx_t &ctx, const char *file, size_t lnnum) -{ - return notify(ev_gen_src_file_lnnum, &ctx, file, lnnum); -} -inline ssize_t processor_t::rename(ea_t ea, const char *new_name, int flags) -{ - return notify(ev_rename, ea, new_name, flags); -} -inline ssize_t processor_t::may_show_sreg(ea_t current_ea) -{ - return notify(ev_may_show_sreg, current_ea); -} -inline ssize_t processor_t::coagulate(ea_t start_ea) -{ - return notify(ev_coagulate, start_ea); -} -inline void processor_t::auto_queue_empty(/*atype_t*/ int type) -{ - notify(ev_auto_queue_empty, type); -} -inline ssize_t processor_t::func_bounds(int *possible_return_code, func_t *pfn, ea_t max_func_end_ea) -{ - return notify(ev_func_bounds, possible_return_code, pfn, max_func_end_ea); -} -inline ssize_t processor_t::may_be_func(const insn_t &insn, int state) -{ - return notify(ev_may_be_func, &insn, state); -} -inline ssize_t processor_t::is_sane_insn(const insn_t &insn, int no_crefs) -{ - return notify(ev_is_sane_insn, &insn, no_crefs); -} -inline ssize_t processor_t::cmp_operands(const op_t &op1, const op_t &op2) -{ - return notify(ev_cmp_operands, &op1, &op2); -} -inline ssize_t processor_t::is_jump_func(func_t *pfn, ea_t *jump_target, ea_t *func_pointer) -{ - return notify(ev_is_jump_func, pfn, jump_target, func_pointer); -} -inline ssize_t processor_t::is_basic_block_end(const insn_t &insn, bool call_insn_stops_block) -{ - return notify(ev_is_basic_block_end, &insn, call_insn_stops_block); -} -inline ssize_t processor_t::getreg(uval_t *rv, int regnum) -{ - return notify(ev_getreg, rv, regnum); -} -inline ssize_t processor_t::undefine(ea_t ea) -{ - return notify(ev_undefine, ea); -} -inline ssize_t processor_t::moving_segm(segment_t *seg, ea_t to, int flags) -{ - return notify(ev_moving_segm, seg, to, flags); -} -inline ssize_t processor_t::is_sp_based(const insn_t &insn, const op_t &x) -{ - int mode; - int code = notify(ev_is_sp_based, &mode, &insn, &x); - return code == 0 ? OP_SP_BASED : mode; -} -inline ssize_t processor_t::is_far_jump(int icode) -{ - return notify(ev_is_far_jump, icode); -} -inline ssize_t processor_t::is_call_insn(const insn_t &insn) -{ - return notify(ev_is_call_insn, &insn); -} -inline ssize_t processor_t::is_ret_insn(const insn_t &insn, bool strict) -{ - return notify(ev_is_ret_insn, &insn, strict); -} -inline ssize_t processor_t::is_align_insn(ea_t ea) -{ - return notify(ev_is_align_insn, ea); -} -inline ssize_t processor_t::can_have_type(const op_t &op) -{ - return notify(ev_can_have_type, &op); -} -inline ssize_t processor_t::get_stkvar_scale_factor() -{ - return notify(ev_get_stkvar_scale_factor); -} -inline ssize_t processor_t::demangle_name(int32 *res, qstring *out, const char *name, uint32 disable_mask, /*demreq_type_t*/ int demreq) -{ - return notify(ev_demangle_name, res, out, name, disable_mask, demreq); -} -inline ssize_t processor_t::create_flat_group(ea_t image_base, int bitness, sel_t dataseg_sel) -{ - return notify(ev_create_flat_group, image_base, bitness, dataseg_sel); -} -inline ssize_t processor_t::is_alloca_probe(ea_t ea) -{ - return notify(ev_is_alloca_probe, ea); -} -inline ssize_t processor_t::get_reg_name(qstring *buf, int reg, size_t width, int reghi) -{ - return notify(ev_get_reg_name, buf, reg, width, reghi); -} -inline ssize_t processor_t::gen_asm_or_lst(bool starting, FILE *fp, bool is_asm, int flags, /*html_line_cb_t ** */ void *outline) -{ - return notify(ev_gen_asm_or_lst, starting, fp, is_asm, flags, outline); -} -inline ssize_t processor_t::gen_map_file(int *nlines, FILE *fp) -{ - return notify(ev_gen_map_file, nlines, fp); -} -inline ssize_t processor_t::get_autocmt(qstring *buf, const insn_t &insn) -{ - return notify(ev_get_autocmt, buf, &insn); -} -inline ssize_t processor_t::is_insn_table_jump(const insn_t &insn) -{ - return notify(ev_is_insn_table_jump, &insn); -} -inline ssize_t processor_t::loader_elf_machine(linput_t *li, int machine_type, const char **p_procname, proc_def_t **p_pd) -{ - return notify(ev_loader_elf_machine, li, machine_type, p_procname, p_pd); -} -inline ssize_t processor_t::is_indirect_jump(const insn_t &insn) -{ - return notify(ev_is_indirect_jump, &insn); -} -inline ssize_t processor_t::verify_noreturn(func_t *pfn) -{ - return notify(ev_verify_noreturn, pfn); -} -inline ssize_t processor_t::verify_sp(func_t *pfn) -{ - return notify(ev_verify_sp, pfn); -} -inline ssize_t processor_t::create_func_frame(func_t *pfn) -{ - return notify(ev_create_func_frame, pfn); -} -inline ssize_t processor_t::get_frame_retsize(int *retsize, const func_t *pfn) -{ - return notify(ev_get_frame_retsize, retsize, pfn); -} -inline ssize_t processor_t::analyze_prolog(ea_t fct_ea) -{ - return notify(ev_analyze_prolog, fct_ea); -} -inline ssize_t processor_t::calc_spdelta(sval_t *spdelta, const insn_t &insn) -{ - return notify(ev_calc_spdelta, spdelta, &insn); -} -inline ssize_t processor_t::calcrel(bytevec_t *out_relbits, size_t *out_consumed, ea_t ea) -{ - return notify(ev_calcrel, out_relbits, out_consumed, ea); -} -inline ssize_t processor_t::find_reg_value(uval_t *out, const insn_t &insn, int reg) -{ - return notify(ev_find_reg_value, out, &insn, reg); -} -inline ssize_t processor_t::find_op_value(uval_t *out, const insn_t &insn, int opn) -{ - return notify(ev_find_op_value, out, &insn, opn); -} -inline ssize_t processor_t::treat_hindering_item(ea_t hindering_item_ea, flags_t new_item_flags, ea_t new_item_ea, asize_t new_item_length) -{ - return notify(ev_treat_hindering_item, hindering_item_ea, new_item_flags, new_item_ea, new_item_length); -} -inline ssize_t processor_t::extract_address(ea_t *out_ea, ea_t screen_ea, const char *string, size_t x) -{ - return notify(ev_extract_address, out_ea, screen_ea, string, x); -} -inline ssize_t processor_t::str2reg(const char *regname) -{ - return notify(ev_str2reg, regname); -} -inline ssize_t processor_t::is_switch(switch_info_t *si, const insn_t &insn) -{ - return notify(ev_is_switch, si, &insn); -} -inline ssize_t processor_t::create_switch_xrefs(ea_t jumpea, const switch_info_t &si) -{ - return notify(ev_create_switch_xrefs, jumpea, &si); -} -inline ssize_t processor_t::calc_switch_cases(/*casevec_t * */void *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si) -{ - return notify(ev_calc_switch_cases, casevec, targets, insn_ea, &si); -} -inline ssize_t processor_t::get_bg_color(bgcolor_t *color, ea_t ea) -{ - return notify(ev_get_bg_color, color, ea); -} -inline ssize_t processor_t::validate_flirt_func(ea_t start_ea, const char *funcname) -{ - return notify(ev_validate_flirt_func, start_ea, funcname); -} -inline ssize_t processor_t::get_operand_string(qstring *buf, const insn_t &insn, int opnum) -{ - return notify(ev_get_operand_string, buf, &insn, opnum); -} -inline ssize_t processor_t::add_cref(ea_t from, ea_t to, cref_t type) -{ - return notify(ev_add_cref, from, to, type); -} -inline ssize_t processor_t::add_dref(ea_t from, ea_t to, dref_t type) -{ - return notify(ev_add_dref, from, to, type); -} -inline ssize_t processor_t::del_cref(ea_t from, ea_t to, bool expand) -{ - return notify(ev_del_cref, from, to, expand); -} -inline ssize_t processor_t::del_dref(ea_t from, ea_t to) -{ - return notify(ev_del_dref, from, to); -} -inline ssize_t processor_t::coagulate_dref(ea_t from, ea_t to, bool may_define, ea_t *code_ea) -{ - return notify(ev_coagulate_dref, from, to, may_define, code_ea); -} -inline const char *processor_t::set_idp_options(const char *keyword, int vtype, const void *value, bool idb_loaded) -{ - const char *errmsg = IDPOPT_BADKEY; - int code = notify(ev_set_idp_options, keyword, vtype, value, &errmsg, idb_loaded); - return code == 1 ? IDPOPT_OK : code == 0 ? IDPOPT_BADKEY : errmsg; -} -inline ssize_t processor_t::set_proc_options(const char *options, int confidence) -{ - return notify(ev_set_proc_options, options, confidence); -} -inline ssize_t processor_t::adjust_libfunc_ea(const idasgn_t &sig, const libfunc_t &libfun, ea_t *ea) -{ - return notify(ev_adjust_libfunc_ea, &sig, &libfun, ea); -} -inline ssize_t processor_t::realcvt(void *m, unsigned short *e, unsigned short swt) -{ - return notify(ev_realcvt, m, e, swt); -} -inline ssize_t processor_t::adjust_refinfo(refinfo_t *ri, ea_t ea, int n, const fixup_data_t &fd) -{ - return notify(ev_adjust_refinfo, ri, ea, n, &fd); -} -inline ssize_t processor_t::is_cond_insn(const insn_t &insn) -{ - return notify(ev_is_cond_insn, &insn); -} -inline ssize_t processor_t::set_code16_mode(ea_t ea, bool code16) -{ - return notify(ev_set_code16_mode, ea, code16); -} -inline bool processor_t::get_code16_mode(ea_t ea) -{ - return notify(ev_get_code16_mode, ea) == 1; -} -inline ssize_t processor_t::next_exec_insn(ea_t *target, ea_t ea, int tid, regval_getter_t *_getreg, const regval_t ®values) -{ - return notify(ev_next_exec_insn, target, ea, tid, _getreg, ®values); -} -inline ssize_t processor_t::calc_step_over(ea_t *target, ea_t ip) -{ - return notify(ev_calc_step_over, target, ip); -} -inline ssize_t processor_t::get_macro_insn_head(ea_t *head, ea_t ip) -{ - return notify(ev_get_macro_insn_head, head, ip); -} -inline ssize_t processor_t::get_dbr_opnum(int *opnum, const insn_t &insn) -{ - return notify(ev_get_dbr_opnum, opnum, &insn); -} -inline ssize_t processor_t::insn_reads_tbit(const insn_t &insn, regval_getter_t *_getreg, const regval_t ®values) -{ - return notify(ev_insn_reads_tbit, &insn, _getreg, ®values); -} -inline ssize_t processor_t::get_idd_opinfo(idd_opinfo_t *opinf, ea_t ea, int n, int thread_id, regval_getter_t *_getreg, const regval_t ®values) -{ - return notify(ev_get_idd_opinfo, opinf, ea, n, thread_id, _getreg, ®values); -} -inline ssize_t processor_t::calc_next_eas(eavec_t *res, const insn_t &insn, bool over) -{ - return notify(ev_calc_next_eas, res, &insn, over); -} -inline ssize_t processor_t::clean_tbit(ea_t ea, regval_getter_t *_getreg, const regval_t ®values) -{ - return notify(ev_clean_tbit, ea, _getreg, ®values); -} -inline ssize_t processor_t::setup_til() -{ - return notify(ev_setup_til); -} -inline ssize_t processor_t::max_ptr_size() -{ - return notify(ev_max_ptr_size); -} -inline ssize_t processor_t::calc_cdecl_purged_bytes(ea_t ea) -{ - return notify(ev_calc_cdecl_purged_bytes, ea); -} -inline ssize_t processor_t::get_stkarg_offset() const -{ - return ti() ? notify(ev_get_stkarg_offset) : 0; -} -inline ssize_t processor_t::equal_reglocs(const argloc_t &a1, const argloc_t &a2) -{ - return notify(ev_equal_reglocs, &a1, &a2); -} -inline ssize_t processor_t::decorate_name(qstring *outbuf, const char *name, bool mangle, cm_t cc, const tinfo_t &type) -{ - return notify(ev_decorate_name, outbuf, name, mangle, cc, &type); -} -inline ssize_t processor_t::calc_retloc(argloc_t *retloc, const tinfo_t &rettype, cm_t cc) -{ - return notify(ev_calc_retloc, retloc, &rettype, cc); -} -inline ssize_t processor_t::calc_varglocs(func_type_data_t *ftd, regobjs_t *regs, relobj_t *stkargs, int nfixed) -{ - return notify(ev_calc_varglocs, ftd, regs, stkargs, nfixed); -} -inline ssize_t processor_t::calc_arglocs(func_type_data_t *fti) -{ - return notify(ev_calc_arglocs, fti); -} -inline ssize_t processor_t::use_stkarg_type(ea_t ea, const funcarg_t &arg) -{ - return notify(ev_use_stkarg_type, ea, &arg); -} -inline ssize_t processor_t::use_regarg_type(int *idx, ea_t ea, /*const funcargvec_t * */void *rargs) -{ - return notify(ev_use_regarg_type, idx, ea, rargs); -} -inline ssize_t processor_t::use_arg_types(ea_t ea, func_type_data_t *fti, /*funcargvec_t * */void *rargs) -{ - return notify(ev_use_arg_types, ea, fti, rargs); -} -inline ssize_t processor_t::calc_purged_bytes(int *p_purged_bytes, const func_type_data_t &fti) -{ - return notify(ev_calc_purged_bytes, p_purged_bytes, &fti); -} -inline ssize_t processor_t::shadow_args_size(int *shadow_size, func_t *pfn) -{ - return notify(ev_shadow_args_size, shadow_size, pfn); -} -inline ssize_t processor_t::get_cc_regs(callregs_t *regs, cm_t cc) -{ - return notify(ev_get_cc_regs, regs, cc); -} -inline ssize_t processor_t::get_simd_types(/*simd_info_vec_t * */void *out, const simd_info_t *simd_attrs, const argloc_t *argloc, bool create_tifs) -{ - return notify(ev_get_simd_types, out, simd_attrs, argloc, create_tifs); -} -inline ssize_t processor_t::arg_addrs_ready(ea_t caller, int n, const tinfo_t &tif, ea_t *addrs) -{ - return notify(ev_arg_addrs_ready, caller, n, &tif, addrs); -} -inline ssize_t processor_t::adjust_argloc(argloc_t *argloc, const tinfo_t *type, int size) -{ - return notify(ev_adjust_argloc, argloc, type, size); -} -inline ssize_t processor_t::lower_func_type(intvec_t *argnums, func_type_data_t *fti) -{ - return notify(ev_lower_func_type, argnums, fti); -} -inline ssize_t processor_t::get_abi_info(qstrvec_t *abi_names, qstrvec_t *abi_opts, comp_t comp) -{ - return notify(ev_get_abi_info, abi_names, abi_opts, comp); -} -inline ssize_t processor_t::arch_changed() -{ - return notify(ev_arch_changed); -} - - -idaman int ida_export str2reg(const char *p); ///< Get any reg number (-1 on error) - - -/// If the instruction at 'ea' looks like an alignment instruction, -/// return its length in bytes. Otherwise return 0. - -idaman int ida_export is_align_insn(ea_t ea); - - -/// Get text representation of a register. -/// For most processors this function will just return \ph{reg_names}[reg]. -/// If the processor module has implemented processor_t::get_reg_name, it will be -/// used instead -/// \param buf output buffer -/// \param reg internal register number as defined in the processor module -/// \param width register width in bytes -/// \param reghi if specified, then this function will return the register pair -/// \return length of register name in bytes or -1 if failure - -idaman ssize_t ida_export get_reg_name(qstring *buf, int reg, size_t width, int reghi = -1); - - -/// Get register information - useful for registers like al, ah, dil, etc. -/// Example: this function for "al" returns "eax" in 32bit mode -/// \return main register name (NULL no such register) - -inline const char *processor_t::get_reg_info(const char *regname, bitrange_t *bitrange) -{ - const char *r2; - int code = notify(ev_get_reg_info, &r2, bitrange, regname); - if ( code == 0 ) // not implemented? - { - if ( ::str2reg(regname) != -1 ) - { - if ( bitrange != NULL ) - bitrange->reset(); - return regname; - } - return NULL; - } - return code == 1 ? r2 : NULL; -} - -/// Get register number and size from register name -struct reg_info_t -{ - int reg; ///< register number - int size; ///< register size - DECLARE_COMPARISONS(reg_info_t) - { - if ( reg != r.reg ) - return reg > r.reg ? 1 : -1; - if ( size != r.size ) - return size > r.size ? 1 : -1; - return 0; - } -}; -DECLARE_TYPE_AS_MOVABLE(reg_info_t); -typedef qvector reginfovec_t; ///< vector of register info objects - - -/// Get register info by name. -/// \param[out] ri result -/// \param regname name of register -/// \return success - -idaman bool ida_export parse_reg_name(reg_info_t *ri, const char *regname); - - -/// Possible memory and register access types. -enum access_type_t ENUM_SIZE(uchar) -{ - NO_ACCESS = 0, - WRITE_ACCESS = 1, - READ_ACCESS = 2, - RW_ACCESS = WRITE_ACCESS | READ_ACCESS, -}; - -/// Information about a register accessed by an instruction. -struct reg_access_t -{ - int regnum = 0; ///< register number (only entire registers) - bitrange_t range; ///< bitrange inside the register - access_type_t access_type = NO_ACCESS; - uchar opnum = 0; ///< operand number - - bool have_common_bits(const reg_access_t &r) const - { - return regnum == r.regnum && range.has_common(r.range); - } - - bool operator==(const reg_access_t &r) const - { - return regnum == r.regnum - && range == r.range - && access_type == r.access_type - && opnum == r.opnum; - } - - bool operator!=(const reg_access_t &r) const - { - return !(*this == r); - } -}; -DECLARE_TYPE_AS_MOVABLE(reg_access_t); -typedef qvector reg_access_vec_t; - -struct reg_accesses_t : public reg_access_vec_t {}; - - -inline bool insn_t::is_canon_insn(const processor_t &_ph) const // see ::insn_t in ua.hpp -{ - return _ph.is_canon_insn(itype); -} - -inline const char *insn_t::get_canon_mnem(const processor_t &_ph) const // see ::insn_t in ua.hpp -{ - return is_canon_insn(_ph) ? _ph.instruc[itype-_ph.instruc_start].name : NULL; -} - -inline uint32 insn_t::get_canon_feature(const processor_t &_ph) const // ::insn_t in ua.hpp -{ - return is_canon_insn(_ph) ? _ph.instruc[itype-_ph.instruc_start].feature : 0; -} - - -/// Get size of long double -inline size_t processor_t::sizeof_ldbl() const -{ - return inf_get_cc_size_ldbl() ? inf_get_cc_size_ldbl() : tbyte_size; -} - -/// Flags passed as 'level' parameter to set_processor_type() -enum setproc_level_t -{ - SETPROC_IDB = 0, ///< set processor type for old idb - SETPROC_LOADER = 1, ///< set processor type for new idb; - ///< if the user has specified a compatible processor, - ///< return success without changing it. - ///< if failure, call loader_failure() - SETPROC_LOADER_NON_FATAL = 2, ///< the same as SETPROC_LOADER but non-fatal failures. - SETPROC_USER = 3, ///< set user-specified processor - ///< used for -p and manual processor change at later time -}; - -/// Set target processor type. -/// Once a processor module is loaded, it cannot be replaced until we close the idb. -/// \param procname name of processor type (one of names present in \ph{psnames}) -/// \param level \ref SETPROC_ -/// \return success - -idaman bool ida_export set_processor_type( - const char *procname, - setproc_level_t level); - - -/// Get name of the current processor module. -/// The name is derived from the file name. -/// For example, for IBM PC the module is named "pc.w32" (windows version), -/// then the module name is "PC" (uppercase). -/// If no processor module is loaded, this function will return NULL -/// \param buf the output buffer, should be at least #QMAXFILE length -/// \param bufsize size of output buffer - -idaman char *ida_export get_idp_name(char *buf, size_t bufsize); - - -/// Set target assembler. -/// \param asmnum number of assembler in the current processor module -/// \return success - -idaman bool ida_export set_target_assembler(int asmnum); - - -/// Helper function to get the delay slot instruction -inline bool processor_t::delay_slot_insn(ea_t *ea, bool *bexec, bool *fexec) -{ - bool ok = (flag & PR_DELAYED) != 0; - if ( ok ) - { - bool be = true; - bool fe = true; - ok = notify(ev_delay_slot_insn, ea, &be, &fe) == 1; - if ( ok ) - { - if ( bexec != NULL ) - *bexec = be; - if ( fexec != NULL ) - *fexec = fe; - } - } - return ok; -} - -/// IDB event group. Some events are still in the processor group, so you will -/// need to hook to both groups. These events do not return anything. -/// -/// The callback function should return 0 but the kernel won't check it. -/// Use the hook_to_notification_point() function to install your callback. -namespace idb_event -{ - // - - /// IDB event codes - enum event_code_t - { - closebase, ///< The database will be closed now - - savebase, ///< The database is being saved - - upgraded, ///< The database has been upgraded - ///< and the receiver can upgrade its info as well - ///< \param from (int) - old IDB version - - auto_empty, ///< Info: all analysis queues are empty. - ///< This callback is called once when the - ///< initial analysis is finished. If the queue is - ///< not empty upon the return from this callback, - ///< it will be called later again. - - auto_empty_finally, ///< Info: all analysis queues are empty definitively. - ///< This callback is called only once. - - determined_main, ///< The main() function has been determined. - ///< \param main (::ea_t) address of the main() function - local_types_changed, ///< Local types have been changed - - extlang_changed, ///< The list of extlangs or the default extlang was changed. - ///< \param kind (int) - ///< 0: extlang installed - ///< 1: extlang removed - ///< 2: default extlang changed - ///< \param el (::extlang_t *) pointer to the extlang affected - ///< \param idx (int) extlang index - - idasgn_loaded, ///< FLIRT signature has been loaded - ///< for normal processing (not for - ///< recognition of startup sequences). - ///< \param short_sig_name (const char *) - - kernel_config_loaded, ///< This event is issued when ida.cfg is parsed. - ///< \param pass_number (int) - - loader_finished, ///< External file loader finished its work. - ///< Use this event to augment the existing loader functionality. - ///< \param li (linput_t *) - ///< \param neflags (::uint16) \ref NEF_ - ///< \param filetypename (const char *) - - flow_chart_created, ///< Gui has retrieved a function flow chart. - ///< Plugins may modify the flow chart in this callback. - ///< \param fc (qflow_chart_t *) - - compiler_changed, ///< The kernel has changed the compiler information. - ///< (\inf{cc} structure; \ref get_abi_name) - - changing_ti, ///< An item typestring (c/c++ prototype) is to be changed. - ///< \param ea (::ea_t) - ///< \param new_type (const ::type_t *) - ///< \param new_fnames (const ::p_list *) - - ti_changed, ///< An item typestring (c/c++ prototype) has been changed. - ///< \param ea (::ea_t) - ///< \param type (const ::type_t *) - ///< \param fnames (const ::p_list *) - - changing_op_ti, ///< An operand typestring (c/c++ prototype) is to be changed. - ///< \param ea (::ea_t) - ///< \param n (int) - ///< \param new_type (const ::type_t *) - ///< \param new_fnames (const ::p_list *) - op_ti_changed, ///< An operand typestring (c/c++ prototype) has been changed. - ///< \param ea (::ea_t) - ///< \param n (int) - ///< \param type (const ::type_t *) - ///< \param fnames (const ::p_list *) - - changing_op_type, ///< An operand type (offset, hex, etc...) is to be changed. - ///< \param ea (::ea_t) - ///< \param n (int) eventually or'ed with OPND_OUTER or OPND_ALL - ///< \param opinfo (const opinfo_t *) additional operand info - op_type_changed, ///< An operand type (offset, hex, etc...) has been set or deleted. - ///< \param ea (::ea_t) - ///< \param n (int) eventually or'ed with OPND_OUTER or OPND_ALL - - enum_created, ///< An enum type has been created. - ///< \param id (::enum_t) - - deleting_enum, ///< An enum type is to be deleted. - ///< \param id (::enum_t) - enum_deleted, ///< An enum type has been deleted. - ///< \param id (::enum_t) - - renaming_enum, ///< An enum or enum member is to be renamed. - ///< \param id (::tid_t) - ///< \param is_enum (bool) - ///< \param newname (const char *) - enum_renamed, ///< An enum or member has been renamed. - ///< \param id (::tid_t) - - changing_enum_bf, ///< An enum type 'bitfield' attribute is to be changed. - ///< \param id (::enum_t) - ///< \param new_bf (bool) - enum_bf_changed, ///< An enum type 'bitfield' attribute has been changed. - ///< \param id (::enum_t) - - changing_enum_cmt, ///< An enum or member type comment is to be changed. - ///< \param id (::tid_t) - ///< \param repeatable (bool) - ///< \param newcmt (const char *) - enum_cmt_changed, ///< An enum or member type comment has been changed. - ///< \param id (::tid_t) - ///< \param repeatable (bool) - - enum_member_created, ///< An enum member has been created. - ///< \param id (::enum_t) - ///< \param cid (::const_t) - - deleting_enum_member, ///< An enum member is to be deleted. - ///< \param id (::enum_t) - ///< \param cid (::const_t) - enum_member_deleted, ///< An enum member has been deleted. - ///< \param id (::enum_t) - ///< \param cid (::const_t) - - struc_created, ///< A new structure type has been created. - ///< \param struc_id (::tid_t) - - deleting_struc, ///< A structure type is to be deleted. - ///< \param sptr (::struc_t *) - struc_deleted, ///< A structure type has been deleted. - ///< \param struc_id (::tid_t) - - changing_struc_align, ///< A structure type is being changed (the struct alignment). - ///< \param sptr (::struc_t *) - struc_align_changed, ///< A structure type has been changed (the struct alignment). - ///< \param sptr (::struc_t *) - - renaming_struc, ///< A structure type is to be renamed. - ///< \param id (::tid_t) - ///< \param oldname (const char *) - ///< \param newname (const char *) - struc_renamed, ///< A structure type has been renamed. - ///< \param sptr (::struc_t *) - - expanding_struc, ///< A structure type is to be expanded/shrunk. - ///< \param sptr (::struc_t *) - ///< \param offset (::ea_t) - ///< \param delta (::adiff_t) - struc_expanded, ///< A structure type has been expanded/shrank. - ///< \param sptr (::struc_t *) - - struc_member_created, ///< A structure member has been created. - ///< \param sptr (::struc_t *) - ///< \param mptr (::member_t *) - - deleting_struc_member, ///< A structure member is to be deleted. - ///< \param sptr (::struc_t *) - ///< \param mptr (::member_t *) - struc_member_deleted, ///< A structure member has been deleted. - ///< \param sptr (::struc_t *) - ///< \param member_id (::tid_t) - ///< \param offset (::ea_t) - - renaming_struc_member, ///< A structure member is to be renamed. - ///< \param sptr (::struc_t *) - ///< \param mptr (::member_t *) - ///< \param newname (const char *) - struc_member_renamed, ///< A structure member has been renamed. - ///< \param sptr (::struc_t *) - ///< \param mptr (::member_t *) - - changing_struc_member, ///< A structure member is to be changed. - ///< \param sptr (::struc_t *) - ///< \param mptr (::member_t *) - ///< \param flag (::flags_t) - ///< \param ti (const ::opinfo_t *) - ///< \param nbytes (::asize_t) - struc_member_changed, ///< A structure member has been changed. - ///< \param sptr (::struc_t *) - ///< \param mptr (::member_t *) - - changing_struc_cmt, ///< A structure type comment is to be changed. - ///< \param struc_id (::tid_t) - ///< \param repeatable (bool) - ///< \param newcmt (const char *) - struc_cmt_changed, ///< A structure type comment has been changed. - ///< \param struc_id (::tid_t) - ///< \param repeatable_cmt (bool) - - segm_added, ///< A new segment has been created. - ///< \param s (::segment_t *) - ///< See also adding_segm - - deleting_segm, ///< A segment is to be deleted. - ///< \param start_ea (::ea_t) - segm_deleted, ///< A segment has been deleted. - ///< \param start_ea (::ea_t) - ///< \param end_ea (::ea_t) - - changing_segm_start, ///< Segment start address is to be changed. - ///< \param s (::segment_t *) - ///< \param new_start (::ea_t) - ///< \param segmod_flags (int) - segm_start_changed, ///< Segment start address has been changed. - ///< \param s (::segment_t *) - ///< \param oldstart (::ea_t) - - changing_segm_end, ///< Segment end address is to be changed. - ///< \param s (::segment_t *) - ///< \param new_end (::ea_t) - ///< \param segmod_flags (int) - segm_end_changed, ///< Segment end address has been changed. - ///< \param s (::segment_t *) - ///< \param oldend (::ea_t) - - changing_segm_name, ///< Segment name is being changed. - ///< \param s (::segment_t *) - ///< \param oldname (const char *) - segm_name_changed, ///< Segment name has been changed. - ///< \param s (::segment_t *) - ///< \param name (const char *) - - changing_segm_class, ///< Segment class is being changed. - ///< \param s (::segment_t *) - segm_class_changed, ///< Segment class has been changed. - ///< \param s (::segment_t *) - ///< \param sclass (const char *) - - segm_attrs_updated, ///< Segment attributes has been changed. - ///< \param s (::segment_t *) - ///< This event is generated for secondary segment - ///< attributes (examples: color, permissions, etc) - - segm_moved, ///< Segment has been moved. - ///< \param from (::ea_t) - ///< \param to (::ea_t) - ///< \param size (::asize_t) - ///< \param changed_netmap (bool) - ///< See also \ref idb_event::allsegs_moved - - allsegs_moved, ///< Program rebasing is complete. - ///< This event is generated after series of - ///< segm_moved events - ///< \param info (::segm_move_infos_t *) - - func_added, ///< The kernel has added a function. - ///< \param pfn (::func_t *) - - func_updated, ///< The kernel has updated a function. - ///< \param pfn (::func_t *) - - set_func_start, ///< Function chunk start address will be changed. - ///< \param pfn (::func_t *) - ///< \param new_start (::ea_t) - - set_func_end, ///< Function chunk end address will be changed. - ///< \param pfn (::func_t *) - ///< \param new_end (::ea_t) - - deleting_func, ///< The kernel is about to delete a function. - ///< \param pfn (::func_t *) - // - frame_deleted, ///< The kernel has deleted a function frame. - ///< \param pfn (::func_t *) - - thunk_func_created, ///< A thunk bit has been set for a function. - ///< \param pfn (::func_t *) - - func_tail_appended, ///< A function tail chunk has been appended. - ///< \param pfn (::func_t *) - ///< \param tail (::func_t *) - - deleting_func_tail, ///< A function tail chunk is to be removed. - ///< \param pfn (::func_t *) - ///< \param tail (const ::range_t *) - - func_tail_deleted, ///< A function tail chunk has been removed. - ///< \param pfn (::func_t *) - ///< \param tail_ea (::ea_t) - - tail_owner_changed, ///< A tail chunk owner has been changed. - ///< \param tail (::func_t *) - ///< \param owner_func (::ea_t) - ///< \param old_owner (::ea_t) - - func_noret_changed, ///< #FUNC_NORET bit has been changed. - ///< \param pfn (::func_t *) - - stkpnts_changed, ///< Stack change points have been modified. - ///< \param pfn (::func_t *) - - updating_tryblks, ///< About to update tryblk information - ///< \param tbv (const ::tryblks_t *) - tryblks_updated, ///< Updated tryblk information - ///< \param tbv (const ::tryblks_t *) - - deleting_tryblks, ///< About to delete tryblk information in given range - ///< \param range (const ::range_t *) - // - sgr_changed, ///< The kernel has changed a segment register value. - ///< \param start_ea (::ea_t) - ///< \param end_ea (::ea_t) - ///< \param regnum (int) - ///< \param value (::sel_t) - ///< \param old_value (::sel_t) - ///< \param tag (::uchar) \ref SR_ - - make_code, ///< An instruction is being created. - ///< \param insn (const ::insn_t*) - - make_data, ///< A data item is being created. - ///< \param ea (::ea_t) - ///< \param flags (::flags_t) - ///< \param tid (::tid_t) - ///< \param len (::asize_t) - - destroyed_items, ///< Instructions/data have been destroyed in [ea1,ea2). - ///< \param ea1 (::ea_t) - ///< \param ea2 (::ea_t) - ///< \param will_disable_range (bool) - - renamed, ///< The kernel has renamed a byte. - ///< See also the \idpcode{rename} event - ///< \param ea (::ea_t) - ///< \param new_name (const char *) - ///< \param local_name (bool) - - byte_patched, ///< A byte has been patched. - ///< \param ea (::ea_t) - ///< \param old_value (::uint32) - - changing_cmt, ///< An item comment is to be changed. - ///< \param ea (::ea_t) - ///< \param repeatable_cmt (bool) - ///< \param newcmt (const char *) - cmt_changed, ///< An item comment has been changed. - ///< \param ea (::ea_t) - ///< \param repeatable_cmt (bool) - - changing_range_cmt, ///< Range comment is to be changed. - ///< \param kind (::range_kind_t) - ///< \param a (const ::range_t *) - ///< \param cmt (const char *) - ///< \param repeatable (bool) - range_cmt_changed, ///< Range comment has been changed. - ///< \param kind (::range_kind_t) - ///< \param a (const ::range_t *) - ///< \param cmt (const char *) - ///< \param repeatable (bool) - - extra_cmt_changed, ///< An extra comment has been changed. - ///< \param ea (::ea_t) - ///< \param line_idx (int) - ///< \param cmt (const char *) - - item_color_changed, ///< An item color has been changed. - ///< \param ea (::ea_t) - ///< \param color (::bgcolor_t) - ///< if color==DEFCOLOR, the the color is deleted. - - callee_addr_changed, ///< Callee address has been updated by the user. - ///< \param ea (::ea_t) - ///< \param callee (::ea_t) - - bookmark_changed, ///< Boomarked position changed. - ///< \param index (::uint32) - ///< \param pos (::const lochist_entry_t *) - ///< \param desc (::const char *) - ///< if desc==NULL, then the bookmark was deleted. - - sgr_deleted, ///< The kernel has deleted a segment register value. - ///< \param start_ea (::ea_t) - ///< \param end_ea (::ea_t) - ///< \param regnum (int) - - adding_segm, ///< A segment is being created. - ///< \param s (::segment_t *) - - func_deleted, ///< A function has been deleted. - ///< \param func_ea (::ea_t) - - dirtree_mkdir, ///< Dirtree: a directory has been created. - ///< \param dt (::dirtree_t *) - ///< \param path (::const char *) - - dirtree_rmdir, ///< Dirtree: a directory has been deleted. - ///< \param dt (::dirtree_t *) - ///< \param path (::const char *) - - dirtree_link, ///< Dirtree: an item has been linked/unlinked. - ///< \param dt (::dirtree_t *) - ///< \param path (::const char *) - ///< \param link (::bool) - - dirtree_move, ///< Dirtree: a directory or item has been moved. - ///< \param dt (::dirtree_t *) - ///< \param from (::const char *) - ///< \param to (::const char *) - - dirtree_rank, ///< Dirtree: a directory or item rank has been changed. - ///< \param dt (::dirtree_t *) - ///< \param path (::const char *) - ///< \param rank (::size_t) - - dirtree_rminode, ///< Dirtree: an inode became unavailable. - ///< \param dt (::dirtree_t *) - ///< \param inode (::inode_t) - }; -} - - -/// the kernel will use this function to generate idb_events - -inline void gen_idb_event(idb_event::event_code_t code, ...) -{ - va_list va; - va_start(va, code); - invoke_callbacks(HT_IDB, code, va); - va_end(va); -} - -inline int processor_t::get_proc_index(void) -{ - qstring curproc = inf_get_procname(); - int i = 0; - while ( psnames[i] != nullptr ) - { - if ( curproc == psnames[i] ) - return i; - i++; - } - // should not reach here - INTERR(10336); -} - -/// Starting from IDA v7.5 all modules should use the following 3 functions -/// to handle idb specific static data because now the kernel supports -/// opening and working with multiple idbs files simultaneously. -/// See the source code of the processor modules in the SDK for the usage examples. - -/// Register pointer to database specific module data. -/// \param data_id initially the pointed-to value must be 0, the kernel will fill -/// it with a unique id. once assigned, the data_id does not change. -/// \param data_ptr pointer to the data to register -/// \return data_ptr. -/// The registered pointer can later be retrieved using get_module_data() - -idaman void *ida_export set_module_data(int *data_id, void *data_ptr); - - -/// Unregister pointer to database specific module data. -/// \param data_id an data_id that was assigned by set_module_data() -/// \return previously registered pointer for the current database. -/// it can be deallocated now. -/// Multiple calls to this function with the same id are forbidden. - -idaman void *ida_export clr_module_data(int data_id); - - - -/// Get pointer to the database specific module data. -/// \param data_id data id that was initialized by set_module_data() -/// \return previously registered pointer for the current database - -idaman void *ida_export get_module_data(int data_id); - -// Convenience macros to handle the module data. -// They assume the existence of a global variable "int data_id" -#define SET_MODULE_DATA(type) (type *)set_module_data(&data_id, new type) -#define GET_MODULE_DATA(type) ((type *)get_module_data(data_id)) - - -#endif // _IDP_HPP diff --git a/idasdk75/include/ieee.h b/idasdk75/include/ieee.h deleted file mode 100644 index 4fcd8d9..0000000 --- a/idasdk75/include/ieee.h +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - - * Floating Point Number Libary. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - */ - -#ifndef _IEEE_H_ -#define _IEEE_H_ - -/*! \file ieee.h - - \brief IEEE floating point functions - -*/ - -//------------------------------------------------------------------- -/// Number of 16 bit words in ::eNE -#define IEEE_NE 6 - -/// Number of 16 bit words in ::eNI -#define IEEE_NI (IEEE_NE+3) - -//========================================================================== -/// Array offset to exponent -#define IEEE_E 1 - -/// Array offset to high guard word -#define IEEE_M 2 - -/// The exponent of 1.0 -#define IEEE_EXONE (0x3fff) - -//=================================================================== -/// External x type format -typedef uint16 eNE[IEEE_NE]; - -/// Internal format: -/// - 0 : sign (0/1) -/// - 1 : exponent (based of #IEEE_EXONE). If exp = 0, value = 0. -/// - 2 : high word of mantissa (always zero after normalize) -typedef uint16 eNI[IEEE_NI]; - -/// Exponent in eNE for NaN and Inf -#define E_SPECIAL_EXP 0x7fff - -/// 0.0 -extern const eNE ieee_ezero; -#define EZERO { 0, 0000000,0000000,0000000,0000000,0000000 } - -/// 1.0 -extern const eNE ieee_eone; -#define EONE { 0, 0000000,0000000,0000000,0100000,0x3fff } - -/// 2.0 -extern const eNE ieee_etwo; - -/// 32.0 -extern const eNE ieee_e32; - -/// 6.93147180559945309417232121458176568075500134360255E-1 -extern const eNE ieee_elog2; - -/// 1.41421356237309504880168872420969807856967187537695E0 -extern const eNE ieee_esqrt2; - -/// 2/sqrt(PI) = 1.12837916709551257389615890312154517168810125865800E0 -extern const eNE ieee_eoneopi; - -/// 3.14159265358979323846264338327950288419716939937511E0 -extern const eNE ieee_epi; - -/// 5.7721566490153286060651209008240243104215933593992E-1 -extern const eNE ieee_eeul; - - -/// Clear (zero-out) the given value - -inline void ecleaz(eNI x) { memset(x, 0, sizeof(eNI)); } - - -/// Move eNI => eNE - -idaman THREAD_SAFE void ida_export emovo(const eNI a, eNE b); - - -/// Move eNE => eNI - -idaman THREAD_SAFE void ida_export emovi(const eNE a, eNI b); - - -/// Shift NI format up (+) or down - -idaman THREAD_SAFE int ida_export eshift(eNI x, int sc); - - -/// Normalize and round off. -/// \param s the internal format number to be rounded -/// \param lost indicates whether or not the number is exact. -/// this is the so-called sticky bit. -/// \param subflg indicates whether the number was obtained -/// by a subtraction operation. In that case if lost is nonzero -/// then the number is slightly smaller than indicated. -/// \param exp the biased exponent, which may be negative. -/// the exponent field of "s" is ignored but is replaced by -/// "exp" as adjusted by normalization and rounding. -/// \param rndbase if 0 => is the rounding control. -/// else is processor defined base (rndprc) -/// \return success - -idaman THREAD_SAFE int ida_export emdnorm(eNI s, int lost, int subflg, int32 exp, int rndbase); - - -/// \defgroup REAL_ERROR_ Floating point/IEEE Conversion codes -/// Return values for and processor_t::realcvt_t request -//@{ -#define REAL_ERROR_FORMAT -1 ///< not supported format for current .idp -#define REAL_ERROR_RANGE -2 ///< number too big (small) for store (mem NOT modified) -#define REAL_ERROR_BADDATA -3 ///< illegal real data for load (IEEE data not filled) -//@} -// -/// \name Prototypes -/// IDP module event prototype -- should be implemented in idp -//@{ - -/// Floating point conversion function: implemented by \ph{realcvt}. -/// \param m pointer to data -/// \param e internal IEEE format data -/// \param swt operation: -/// - 000: load trunc. float (DEC ^F) 2 bytes (m->e) -/// - 001: load float 4 bytes (m->e) -/// - 003: load double 8 bytes (m->e) -/// - 004: load long double 10 bytes (m->e) -/// - 005: load long double 12 bytes (m->e) -/// - 010: store trunc. float (DEC ^F) 2 bytes (e->m) -/// - 011: store float 4 bytes (e->m) -/// - 013: store double 8 bytes (e->m) -/// - 014: store long double 10 bytes (e->m) -/// - 015: store long double 12 bytes (e->m) -/// \retval 0 ok -/// \retval \ref REAL_ERROR_ on error - -int idaapi realcvt(void *m, eNE e, uint16 swt); - - -/// Little endian - -int l_realcvt(void *m, eNE e, uint16 swt); - - -/// Big endian - -int b_realcvt(void *m, eNE e, uint16 swt); - -//@} - - -/// Standard IEEE 754 floating point conversion function. -/// See comment for realcvt(). - -idaman THREAD_SAFE int ida_export ieee_realcvt(void *m, eNE e, uint16 swt); - - -/// \name Misc arithmetic/conversion functions -/// \retval 0 ok -/// \retval 1 overfloat / underfloat -/// \retval 2 illegal data (asctoreal()) -/// \retval 3 divide by 0 (ediv()) -/// \retval 4 too big for integer (eetol()) -//@{ - -/// IEEE to ascii string. -/// \param mode broken down into: -/// - low byte: number of digits after '.' -/// - second byte: FPNUM_LENGTH -/// - third byte: FPNUM_DIGITS - -idaman THREAD_SAFE void ida_export realtoasc(char *buf, size_t bufsize, const eNE x, uint mode); - - -/// ascii string to IEEE - -idaman THREAD_SAFE int ida_export asctoreal(const char **sss, eNE y); - - -/// long to IEEE - -idaman THREAD_SAFE void ida_export eltoe(sval_t l, eNE e); - - -/// int64 to IEEE - -idaman THREAD_SAFE void ida_export eltoe64(int64 l, eNE e); - - -/// uint64 to IEEE - -idaman THREAD_SAFE void ida_export eltoe64u(uint64 l, eNE e); - - -/// IEEE to long (+-0.5 if flg) - -idaman THREAD_SAFE int ida_export eetol(sval_t *l, const eNE a, bool roundflg); - - -/// IEEE to long (+-0.5 if flg) - -idaman THREAD_SAFE int ida_export eetol64(int64 *l, const eNE a, bool roundflg); - - -/// IEEE to ulong (+-0.5 if flg) - -idaman THREAD_SAFE int ida_export eetol64u(uint64 *l, const eNE a, bool roundflg); - - -/// b = a*(2**pwr2) - -idaman THREAD_SAFE int ida_export eldexp(const eNE a, int32 pwr2, eNE b); - - -/// if(!subflg) c = a + b, -/// else c = a - b - -idaman THREAD_SAFE int ida_export eadd(const eNE a, const eNE b, eNE c, int subflg); - - -/// c = a * b - -idaman THREAD_SAFE int ida_export emul(const eNE a, const eNE b, eNE c); - - -/// c = a / b - -idaman THREAD_SAFE int ida_export ediv(const eNE a, const eNE b, eNE c); - - -// predefined functions -/// \cond -void eclear(eNE a); -void emov(eNE a, eNE b); -void eabs(eNE x); -int esign(eNE x); -/// \endcond - -/// x = 0 -#define eclear(a) memset(a, 0, sizeof(eNE)) - -/// b = a -#define emov(a, b) memcpy(b, a, sizeof(eNE)) - -/// x = |x| -#define eabs(x) (x[IEEE_NE-1] &= 0x7fff) - -#ifdef __cplusplus -/// x = -x -inline void eneg(eNE x) -{ - if ( x[IEEE_NE-1] != 0 ) - x[IEEE_NE-1] ^= 0x8000; -} -#endif - -/// x < 0 ? -/// \note non standard answer is returned -#define esign(x) (x[IEEE_NE-1] & 0x8000) - -//@} - - -/// Comparison. -/// \retval 0 if a = b -/// \retval 1 if a > b -/// \retval -1 if a < b - -idaman THREAD_SAFE int ida_export ecmp(const eNE a, const eNE b); - - -/// Check for NaN/Inf -enum fpvalue_kind_t -{ - FPV_BADARG, ///< wrong value of max_exp - FPV_NORM, ///< regular value - FPV_NAN, ///< NaN - FPV_PINF, ///< positive infinity - FPV_NINF, ///< negative infinity -}; - -/// \name max_exp values -/// common values for max_exp (for IEEE floating point values) -//@{ -const uint32 - MAXEXP_FLOAT = 0x80, - MAXEXP_DOUBLE = 0x400, - MAXEXP_LNGDBL = 0x4000; -//@} - - -/// See ::fpvalue_kind_t - -idaman THREAD_SAFE fpvalue_kind_t ida_export get_fpvalue_kind(const eNE a, uint16 reserved = 0); - -#endif diff --git a/idasdk75/include/intel.hpp b/idasdk75/include/intel.hpp deleted file mode 100644 index 91d0c6d..0000000 --- a/idasdk75/include/intel.hpp +++ /dev/null @@ -1,1228 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _INTEL_HPP -#define _INTEL_HPP -#include -#include -#include - -#define PROC_MAXOP 5 // max number of operands -CASSERT(PROC_MAXOP <= UA_MAXOP); - -//--------------------------------- -// Intel 80x86 insn_t.auxpref bits -#define aux_lock 0x00000001 -#define aux_rep 0x00000002 -#define aux_repne 0x00000004 -#define aux_use32 0x00000008 // segment type is 32-bits -#define aux_use64 0x00000010 // segment type is 64-bits -#define aux_large 0x00000020 // offset field is 32-bit (16-bit is not enough) -#define aux_short 0x00000040 // short (byte) displacement used -#define aux_sgpref 0x00000080 // a segment prefix byte is not used -#define aux_oppref 0x00000100 // operand size prefix byte is not used -#define aux_adpref 0x00000200 // address size prefix byte is not used -#define aux_basess 0x00000400 // SS based instruction -#define aux_natop 0x00000800 // operand size is not overridden by prefix -#define aux_natad 0x00001000 // addressing mode is not overridden by prefix -#define aux_fpemu 0x00002000 // FP emulator instruction -#define aux_vexpr 0x00004000 // VEX-encoded instruction -#define aux_bnd 0x00008000 // MPX-encoded instruction -#define aux_evex 0x00010000 // EVEX-encoded instruction -#define aux_xop 0x00020000 // XOP-encoded instruction -#define aux_xacquire 0x00040000 // HLE prefix hints -#define aux_xrelease 0x00080000 // HLE prefix hints - -//--------------------------------- -// operand types and other customization: -#define o_trreg o_idpspec0 // IDP specific type -#define o_dbreg o_idpspec1 // IDP specific type -#define o_crreg o_idpspec2 // IDP specific type -#define o_fpreg o_idpspec3 // IDP specific type -#define o_mmxreg o_idpspec4 // IDP specific type -#define o_xmmreg o_idpspec5 // xmm register -#define o_ymmreg o_idpspec5+1 // ymm register -#define o_zmmreg o_idpspec5+2 // zmm register -#define o_kreg o_idpspec5+3 // opmask register - -// 04.10.97: For o_mem,o_near,o_far we keep segment information as -// segrg - number of segment register to use -// if it is == SEGREG_IMM, then the segment was specified as an immediate -// value, look at segsel. - -#define segrg specval_shorts.high -#define SEGREG_IMM 0xFFFF // this value of segrg means that - // segment selector value is in - // "segsel": -#define segsel specval_shorts.low -#define hasSIB specflag1 -#define sib specflag2 -#define rex insnpref // REX byte for 64-bit mode, or bits from the VEX byte if vexpr() - -// Op6 is used for opmask registers in EVEX. -// specflags from Op6 are used to extend insn_t. -#define evex_flags Op6.specflag2 // bits from the EVEX byte if evexpr() - -#define cr_suff specflag1 // o_crreg: D suffix for cr registers (used for CR8D) - -// bits in insn_t.evex_flags: -const int EVEX_R = 0x01; // High-16 register specifier modifier -const int EVEX_L = 0x02; // Vector length/RC -const int EVEX_z = 0x04; // Zeroing/Merging -const int EVEX_b = 0x08; // Broadcast/RC/SAE Context -const int EVEX_V = 0x10; // High-16 NDS/VIDX register specifier - -// bits in insn_t.rex: -const int REX_W = 8; // 64-bit operand size -const int REX_R = 4; // modrm reg field extension -const int REX_X = 2; // sib index field extension -const int REX_B = 1; // modrm r/m, sib base, or opcode reg fields extension -const int VEX_L = 0x80; // 256-bit operation (YMM register) - -typedef short regnum_t; - -enum RegNo -{ - R_none = -1, - R_ax = 0, - R_cx, // 1 - R_dx, // 2 - R_bx, // 3 - R_sp, // 4 - R_bp, // 5 - R_si, // 6 - R_di, // 7 - R_r8, // 8 - R_r9, // 9 - R_r10, // 10 - R_r11, // 11 - R_r12, // 12 - R_r13, // 13 - R_r14, // 14 - R_r15, // 15 - - R_al, - R_cl, - R_dl, - R_bl, - R_ah, - R_ch, - R_dh, - R_bh, - - R_spl, - R_bpl, - R_sil, - R_dil, - - R_ip, - - R_es, // 0 - R_cs, // 1 - R_ss, // 2 - R_ds, // 3 - R_fs, - R_gs, - - R_cf, // main cc's - R_zf, - R_sf, - R_of, - - R_pf, // additional cc's - R_af, - R_tf, - R_if, - R_df, - - R_efl, // eflags - - // the following registers will be used in the disassembly - // starting from ida v5.7 - - R_st0, // floating point registers (not used in disassembly) - R_st1, - R_st2, - R_st3, - R_st4, - R_st5, - R_st6, - R_st7, - R_fpctrl,// fpu control register - R_fpstat,// fpu status register - R_fptags,// fpu tags register - - R_mm0, // mmx registers - R_mm1, - R_mm2, - R_mm3, - R_mm4, - R_mm5, - R_mm6, - R_mm7, - - R_xmm0, // xmm registers - R_xmm1, - R_xmm2, - R_xmm3, - R_xmm4, - R_xmm5, - R_xmm6, - R_xmm7, - R_xmm8, - R_xmm9, - R_xmm10, - R_xmm11, - R_xmm12, - R_xmm13, - R_xmm14, - R_xmm15, - R_mxcsr, - - R_ymm0, // AVX 256-bit registers - R_ymm1, - R_ymm2, - R_ymm3, - R_ymm4, - R_ymm5, - R_ymm6, - R_ymm7, - R_ymm8, - R_ymm9, - R_ymm10, - R_ymm11, - R_ymm12, - R_ymm13, - R_ymm14, - R_ymm15, - - R_bnd0, // MPX registers - R_bnd1, - R_bnd2, - R_bnd3, - - R_xmm16, // AVX-512 extended XMM registers - R_xmm17, - R_xmm18, - R_xmm19, - R_xmm20, - R_xmm21, - R_xmm22, - R_xmm23, - R_xmm24, - R_xmm25, - R_xmm26, - R_xmm27, - R_xmm28, - R_xmm29, - R_xmm30, - R_xmm31, - - R_ymm16, // AVX-512 extended YMM registers - R_ymm17, - R_ymm18, - R_ymm19, - R_ymm20, - R_ymm21, - R_ymm22, - R_ymm23, - R_ymm24, - R_ymm25, - R_ymm26, - R_ymm27, - R_ymm28, - R_ymm29, - R_ymm30, - R_ymm31, - - R_zmm0, // AVX-512 ZMM registers - R_zmm1, - R_zmm2, - R_zmm3, - R_zmm4, - R_zmm5, - R_zmm6, - R_zmm7, - R_zmm8, - R_zmm9, - R_zmm10, - R_zmm11, - R_zmm12, - R_zmm13, - R_zmm14, - R_zmm15, - R_zmm16, - R_zmm17, - R_zmm18, - R_zmm19, - R_zmm20, - R_zmm21, - R_zmm22, - R_zmm23, - R_zmm24, - R_zmm25, - R_zmm26, - R_zmm27, - R_zmm28, - R_zmm29, - R_zmm30, - R_zmm31, - - R_k0, // AVX-512 opmask registers - R_k1, - R_k2, - R_k3, - R_k4, - R_k5, - R_k6, - R_k7, - - R_last, -}; - -CASSERT(R_last == 173); - -inline bool is_segreg(int r) { return r >= R_es && r <= R_gs; } -inline bool is_fpureg(int r) { return r >= R_st0 && r <= R_st7; } -inline bool is_mmxreg(int r) { return r >= R_mm0 && r <= R_mm7; } -inline bool is_xmmreg(int r) { return r >= R_xmm0 && r <= R_xmm15; } -inline bool is_ymmreg(int r) { return r >= R_ymm0 && r <= R_ymm15; } - -int cvt_to_wholereg(int _reg, bool allow_high_byte_regs); // byte reg -> whole reg -int calc_dbg_reg_index(const char *name); - -//------------------------------------------------------------------------- -// is conditional branch? -inline bool insn_jcc(const insn_t &insn) -{ - switch ( insn.itype ) - { - case NN_ja: - case NN_jae: - case NN_jb: - case NN_jbe: - case NN_jc: - case NN_je: - case NN_jg: - case NN_jge: - case NN_jl: - case NN_jle: - case NN_jna: - case NN_jnae: - case NN_jnb: - case NN_jnbe: - case NN_jnc: - case NN_jne: - case NN_jng: - case NN_jnge: - case NN_jnl: - case NN_jnle: - case NN_jno: - case NN_jnp: - case NN_jns: - case NN_jnz: - case NN_jo: - case NN_jp: - case NN_jpe: - case NN_jpo: - case NN_js: - case NN_jz: - return true; - } - return false; -} - -//------------------------------------------------------------------------- -inline bool insn_default_opsize_64(const insn_t &insn) -{ - if ( insn_jcc(insn) ) - return true; - switch ( insn.itype ) - { - // use ss - case NN_pop: - case NN_popf: - case NN_popfq: - case NN_push: - case NN_pushf: - case NN_pushfq: - case NN_retn: - case NN_retf: - case NN_retnq: - case NN_retfq: - case NN_call: - case NN_callfi: - case NN_callni: - case NN_enter: - case NN_enterq: - case NN_leave: - case NN_leaveq: - - // near branches - case NN_jcxz: - case NN_jecxz: - case NN_jrcxz: - case NN_jmp: - case NN_jmpni: - case NN_jmpshort: - case NN_loop: - case NN_loopq: - case NN_loope: - case NN_loopqe: - case NN_loopne: - case NN_loopqne: - return true; - } - return false; -} - -inline bool mode16(const insn_t &insn) { return (insn.auxpref & (aux_use32|aux_use64)) == 0; } // 16-bit mode? -inline bool mode32(const insn_t &insn) { return (insn.auxpref & aux_use32) != 0; } // 32-bit mode? -inline bool mode64(const insn_t &insn) { return (insn.auxpref & aux_use64) != 0; } // 64-bit mode? -inline bool natad(const insn_t &insn) { return (insn.auxpref & aux_natad) != 0; } // natural address size (no prefixes)? -inline bool natop(const insn_t &insn) { return (insn.auxpref & aux_natop) != 0; } // natural operand size (no prefixes)? -inline bool vexpr(const insn_t &insn) { return (insn.auxpref & aux_vexpr) != 0; } // VEX encoding used -inline bool evexpr(const insn_t &insn) { return (insn.auxpref & aux_evex) != 0; } // EVEX encoding used -inline bool xopexpr(const insn_t &insn) { return (insn.auxpref & aux_xop) != 0; } // XOP encoding used - -inline bool ad16(const insn_t &insn) // is current addressing 16-bit? -{ - int p = insn.auxpref & (aux_use32|aux_use64|aux_natad); - return p == aux_natad || p == aux_use32; -} - -inline bool ad32(const insn_t &insn) // is current addressing 32-bit? -{ - int p = insn.auxpref & (aux_use32|aux_use64|aux_natad); - return p == (aux_natad|aux_use32) - || p == 0 - || p == aux_use64; -} - -inline bool ad64(const insn_t &insn) // is current addressing 64-bit? -{ -#ifdef __EA64__ - int p = insn.auxpref & (aux_use32|aux_use64|aux_natad); - return p == (aux_natad|aux_use64); -#else - qnotused(insn); - return false; -#endif -} - -inline bool op16(const insn_t &insn) // is current operand size 16-bit? -{ - int p = insn.auxpref & (aux_use32|aux_use64|aux_natop); - return p == aux_natop // 16-bit segment, no prefixes - || p == aux_use32 // 32-bit segment, 66h - || p == aux_use64 && (insn.rex & REX_W) == 0; // 64-bit segment, 66h, no rex.w -} - -inline bool op32(const insn_t &insn) // is current operand size 32-bit? -{ - int p = insn.auxpref & (aux_use32|aux_use64|aux_natop); - return p == 0 // 16-bit segment, 66h - || p == (aux_use32|aux_natop) // 32-bit segment, no prefixes - || p == (aux_use64|aux_natop) && (insn.rex & REX_W) == 0; // 64-bit segment, 66h, no rex.w -} - -inline bool op64(const insn_t &insn) // is current operand size 64-bit? -{ -#ifdef __EA64__ - return mode64(insn) - && ((insn.rex & REX_W) != 0 - || natop(insn) && insn_default_opsize_64(insn)); // 64-bit segment, rex.w or insns-64 -#else - qnotused(insn); - return false; -#endif -} - -inline bool op256(const insn_t &insn) // is VEX.L == 1 or EVEX.L'L == 01? -{ - return (insn.rex & VEX_L) != 0 - && (vexpr(insn) - || xopexpr(insn) - || evexpr(insn) && (insn.evex_flags & EVEX_L) == 0); -} - -inline bool op512(const insn_t &insn) // is EVEX.L'L == 10? -{ - return evexpr(insn) && (insn.rex & VEX_L) == 0 && (insn.evex_flags & EVEX_L) != 0; -} - -inline bool is_vsib(const insn_t &insn) // does instruction use VSIB variant of the sib byte? -{ - switch ( insn.itype ) - { - case NN_vgatherdps: - case NN_vgatherdpd: - case NN_vgatherqps: - case NN_vgatherqpd: - case NN_vpgatherdd: - case NN_vpgatherdq: - case NN_vpgatherqd: - case NN_vpgatherqq: - - case NN_vscatterdps: - case NN_vscatterdpd: - case NN_vscatterqps: - case NN_vscatterqpd: - case NN_vpscatterdd: - case NN_vpscatterdq: - case NN_vpscatterqd: - case NN_vpscatterqq: - - case NN_vgatherpf0dps: - case NN_vgatherpf0qps: - case NN_vgatherpf0dpd: - case NN_vgatherpf0qpd: - case NN_vgatherpf1dps: - case NN_vgatherpf1qps: - case NN_vgatherpf1dpd: - case NN_vgatherpf1qpd: - - case NN_vscatterpf0dps: - case NN_vscatterpf0qps: - case NN_vscatterpf0dpd: - case NN_vscatterpf0qpd: - case NN_vscatterpf1dps: - case NN_vscatterpf1qps: - case NN_vscatterpf1dpd: - case NN_vscatterpf1qpd: - return true; - } - return false; -} - -inline regnum_t vsib_index_fixreg(const insn_t &insn, regnum_t index) -{ - switch ( insn.itype ) - { - case NN_vscatterdps: - case NN_vscatterqps: - case NN_vscatterqpd: - case NN_vpscatterdd: - case NN_vpscatterqd: - case NN_vpscatterqq: - - case NN_vpgatherdd: - case NN_vpgatherqd: - case NN_vpgatherqq: - case NN_vgatherdps: - case NN_vgatherqps: - case NN_vgatherqpd: - if ( index > 15 ) - index += op512(insn) ? R_zmm0 : op256(insn) ? (R_ymm16 - 16) : (R_xmm16 - 16); - else - index += op512(insn) ? R_zmm0 : op256(insn) ? R_ymm0 : R_xmm0; - break; - - case NN_vscatterdpd: - case NN_vpscatterdq: - - case NN_vgatherdpd: - case NN_vpgatherdq: - if ( index > 15 ) - index += op512(insn) ? (R_ymm16 - 16) : (R_xmm16 - 16); - else - index += op512(insn) ? R_ymm0 : R_xmm0; - break; - - case NN_vgatherpf0dps: - case NN_vgatherpf0qps: - case NN_vgatherpf0qpd: - case NN_vgatherpf1dps: - case NN_vgatherpf1qps: - case NN_vgatherpf1qpd: - - case NN_vscatterpf0dps: - case NN_vscatterpf0qps: - case NN_vscatterpf0qpd: - case NN_vscatterpf1dps: - case NN_vscatterpf1qps: - case NN_vscatterpf1qpd: - index += R_zmm0; - break; - - case NN_vgatherpf0dpd: - case NN_vgatherpf1dpd: - case NN_vscatterpf0dpd: - case NN_vscatterpf1dpd: - if ( index > 15 ) - index += R_ymm16 - 16; - else - index += R_ymm0; - break; - } - return index; -} - -inline int sib_base(const insn_t &insn, const op_t &x) // get extended sib base -{ - int base = x.sib & 7; -#ifdef __EA64__ - if ( insn.rex & REX_B ) - base |= 8; -#else - qnotused(insn); -#endif - return base; -} - -inline regnum_t sib_index(const insn_t &insn, const op_t &x) // get extended sib index -{ - regnum_t index = regnum_t((x.sib >> 3) & 7); -#ifdef __EA64__ - if ( (insn.rex & REX_X) != 0 ) - index |= 8; -#endif - if ( is_vsib(insn) ) - { - if ( (insn.evex_flags & EVEX_V) != 0 ) - index |= 16; - index = vsib_index_fixreg(insn, index); - } - return index; -} - -inline int sib_scale(const op_t &x) -{ - int scale = (x.sib >> 6) & 3; - return scale; -} - -// get the base register of the operand with a displacement -// NB: for 16-bit code, returns a phrase number -// use x86_base_reg() if you need to handle 16-bit instructions -inline int x86_base(const insn_t &insn, const op_t &x) -{ - return x.hasSIB ? sib_base(insn, x) : x.phrase; -} - -// get the base register of the operand with a displacement -// returns correct register for 16-bit code too -inline int x86_base_reg(const insn_t &insn, const op_t &x) -{ - if ( x.hasSIB ) - { - if ( x.type == o_mem ) - return R_none; - return sib_base(insn, x); // base register is encoded in the SIB - } - else if ( !ad16(insn) ) - { - return x.phrase; // 'phrase' contains the base register number - } - else if ( x.phrase == ushort(R_none) ) - { - return R_sp; - } - switch ( x.phrase ) - { - case 0: // [BX+SI] - case 1: // [BX+DI] - case 7: // [BX] - return R_bx; - case 2: // [BP+SI] - case 3: // [BP+DI] - case 6: // [BP] - return R_bp; - case 4: // [SI] - return R_si; - case 5: // [DI] - return R_di; - default: - INTERR(10259); - } -} - -const int INDEX_NONE = 4; // no index register is present -// get the index register of the operand with a displacement -inline int x86_index(const insn_t &insn, const op_t &x) -{ - return x.hasSIB ? sib_index(insn, x) : INDEX_NONE; -} - -inline int x86_index_reg(const insn_t &insn, const op_t &x) -{ - if ( x.hasSIB ) - { - int idx = sib_index(insn, x); - if ( idx != INDEX_NONE ) - return idx; - return R_none; - } - if ( !ad16(insn) ) - return R_none; - switch ( x.phrase ) - { - case 0: // [BX+SI] - case 2: // [BP+SI] - return R_si; - case 1: // [BX+DI] - case 3: // [BP+DI] - return R_di; - case 4: // [SI] - case 5: // [DI] - case 7: // [BX] - case 6: // [BP] - return R_none; - default: - INTERR(10260); - } -} -// get the scale factor of the operand with a displacement -inline int x86_scale(const op_t &x) -{ - return x.hasSIB ? sib_scale(x) : 0; -} - -// does the operand have a displacement? -inline int has_displ(const op_t &x) -{ - return x.type == o_displ || x.type == o_mem && x.hasSIB; -} - -// does the insn refer to the TLS variable? -inline bool has_tls_segpref(const insn_t &insn) -{ - if ( insn.segpref == 0 ) - return false; - return mode64(insn) && insn.segpref == R_fs - || mode32(insn) && insn.segpref == R_gs; -} - -// should we treat the memory operand as a displacement? -inline bool mem_as_displ(const insn_t &insn, const op_t &x) -{ - // the operand should be an offset and it should be the TLS variable - // or the second operand of "lea" instruction - // .text:08000000 mov eax, gs:(ti1 - static_TP) - // .text:08000E8F lea ecx, (_ZN4dmngL4sessE - _GLOBAL_OFFSET_TABLE_) - return (has_tls_segpref(insn) || insn.itype == NN_lea) - && is_off(get_flags(insn.ea), x.n); -} - -// does the operand refer to stack? (sp or bp based) -bool is_stack_ref(const insn_t &insn, const op_t &x, int breg); - -// return addressing width in form of dt_... constant -inline op_dtype_t address_dtype(const insn_t &insn) -{ - return char(ad64(insn) ? dt_qword : ad32(insn) ? dt_dword : dt_word); -} - -// return operand width in form of dt_... constant -inline op_dtype_t operand_dtype(const insn_t &insn) -{ - return char(op64(insn) ? dt_qword : op32(insn) ? dt_dword : op16(insn) ? dt_word : dt_byte); -} - -inline bool is_io_insn(const insn_t &insn) -{ - return insn.itype == NN_ins - || insn.itype == NN_outs - || insn.itype == NN_out - || insn.itype == NN_in; -} - -//--------------------------------- -const char callee_tag = 'A'; -const char fbase_tag = 'b'; -const char frame_tag = 'f'; -const char purge_tag = 'p'; -const char ret_tag = 'r'; -const char pushinfo_tag = 's'; -const char is_ptr_tag = 'P'; -const char finally_tag = 'F'; -const char handler_tag = 'h'; -const char vxd_tag1 = 'V'; -const char vxd_tag2 = 'W'; - -// fbase reg is a register used to access data for the current function -// it is usually initialized by __i686_get_pc_thunk() function - -struct fbase_reg_t -{ - ea_t value; - ea_t minea; // address where the fbase reg is defined - int16 reg; -}; - -// the second operand of lea instruction should not be treated as memory reference -// unless there is cs: prefix or the user has specified 'offset' flag -// in other cases lea is used for arbirary calculations -inline bool is_arith_lea(const insn_t &insn, const op_t &x) -{ - return insn.itype == NN_lea - && x.segrg != R_cs - && !is_off(get_flags(insn.ea), x.n); -} - -// the following operand types are ignored for imul's third operand -inline bool is_forbidden_imul_flag(const insn_t &insn, const op_t &x, flags_t F) -{ - if ( x.n == 2 && insn.Op2.shown() ) - return is_off1(F) || is_stroff1(F) || is_stkvar1(F); - return false; -} - -inline bool is_push_ecx(uchar b) -{ - return b == 0x51; // push ecx -} - -inline bool is_push_eax(uchar b) -{ - return b == 0x50; // push eax -} - -inline bool is_push_edx(uchar b) -{ - return b == 0x52; // push edx -} - -inline bool is_push_ebx(uchar b) -{ - return b == 0x53; // push ebx -} - -inline bool is_volatile_reg(int r) -{ - return r != R_bx - && r != R_bp - && r != R_si - && r != R_di - && r != R_r12 - && r != R_r13 - && r != R_r14 - && r != R_r15; -} - -//------------------------------------------------------------------ -struct pushreg_t -{ - ea_t ea; // instruction ea - sval_t off; // offset from the frame top (sp delta) - sval_t width; // register width (or number of allocated bytes) - regnum_t reg; // register number (R_none means stack space allocation) - uint16 flags; // additional flags -#define PRF_NONE 0x0000 // Entry describes a push or an allocation -#define PRF_MOVE 0x0001 // Entrz describes a register save by a move instruction -#define PRF_SPILL 0x0002 // Indicates that entry is located before local stack region -#define PRF_MASK (PRF_MOVE | PRF_SPILL) -}; - -struct pushinfo_t -{ - enum { PUSHINFO_VERSION = 4 }; - int flags; -#define PINF_SEHCALL 0x0001 // call to SEH_prolog is present -#define PINF_SEHMAN 0x0002 // Manual SEH setup -#define PINF_COOKIE 0x0004 // Has security cookie -#define PINF_ALIGNED 0x0008 // Lvars are align stred (visual studio) -#define PINF_VARARG 0x0010 // Vararg prolog (currently used for gcc64) -#define PINF_BPOFF 0x0020 // xmm_stkoff/reg_stkoff are from rbp (otherwise from rsp) -#define PINF_HAVE_SSIZE 0x0040 // pushinfo_t structure contains its own size (field 'cb') -#define PINF_PSI_FLAGS 0x0080 // pushreg_t structure contains flags field - qvector psi; // stack allocation instructions - ssize_t bpidx = -1; // index into psi - uint32 spoiled = 0; // bitmask of spoiled registers at the end of prolog - - eavec_t prolog_insns; // additional prolog instruction addresses - // (in addition to instructions from psi) - - typedef qvector pop_info_t; - pop_info_t pops; // pop insns for pushs (indexes shifted by one) - // in other words, this is epilog instructions - // index 0: epilog insns not linked to a push insn - // 1..psi.size(): epilog insns for each push insn - // usually there will be only one pop for each push. - // but there might be several pops for each push. - // (because the function has several returns) - - int eh_type; // function has exception handling - // low 16 bits: type, high 16 bits: version -#define EH_NONE 0 // no EH found -#define EH_VCSEH 1 // SEH (__except_handlerN, __SEH_prologN) -#define EH_VCCPPEH 2 // MSVC C++ EH (_EH_prolog[N]) - int seh_ver() - { - if ( (eh_type & 0xFFFF) == EH_VCSEH ) - return (eh_type >> 16) & 0xFFFF; - return 0; - } - int eh_ver() - { - if ( (eh_type & 0xFFFF) == EH_VCCPPEH ) - return (eh_type >> 16) & 0xFFFF; - return 0; - } - - ea_t eh_info = BADADDR; // for SEH: scopetable address, for C++ EH: __ehhandler address - - // for gcc64 vararg (see PINF_VARARG): - sval_t xmm_stkoff = 0; // offset from ebp to xmm savearea - sval_t reg_stkoff = 0; // offset from ebp to gpreg savearea - // these 2 offsets are either from rsp or rbp - // see PINF_BPOFF for that - int xmm_nsaved = 0; // number of saved xmm regs - int reg_nsaved = 0; // number of saved general purpose regs - - int cb = sizeof(pushinfo_t); // size of this structure - - pushinfo_t(void) : flags(PINF_HAVE_SSIZE|PINF_PSI_FLAGS), eh_type(EH_NONE) {} -}; - -enum spec_func_type_t -{ - SF_NONE, - SF_EH_PROLOG, - SF_SEH_PROLOG, - SF_SEH_EPILOG, - SF_ALLOCA, - SF_CHK, - SF_SYSINIT, - SF_EH_EPILOG, - SF_LSTRCATN, -}; - -inline bool is_mingw_abi(void) -{ - if ( default_compiler() != COMP_MS ) - return false; // "mingw" abi can be defined only for MSVC - qstring abiname; - get_abi_name(&abiname); - return abiname == "mingw"; -} - -inline bool is_msabi(void) -{ - comp_t cc = default_compiler(); - return cc == COMP_MS || cc == COMP_UNK && inf_get_filetype() == f_PE; -} - -inline int pc_shadow_area_size() -{ - return inf_is_64bit() && is_msabi() ? 4 * 8 : 0; -} - -struct regval_t; -typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); - -// Structure where information about a mmx/xmm/ymm type is returned -struct mmtype_t -{ - const char *name; - const type_t *type; - const type_t *fields; - tinfo_t tif; -}; - -//---------------------------------------------------------------------- -// The following events are supported by the PC module in the processor_t::notify() function -namespace pc_module_t -{ - enum event_codes_t - { - ev_set_difbase = processor_t::ev_loader, - // set AFIDP_DIFBASE flag - // in: int onoff - // Returns: nothing - ev_restore_pushinfo,// Restore function prolog info from the database - // in: pushinfo_t *pi - // ea_t func_start - // Returns: 1-ok, otherwise-failed - ev_save_pushinfo, // Save function prolog info to the database - // in: ea_t func_start - // pushinfo_t *pi - // Returns: 1-ok, otherwise-failed - ev_prolog_analyzed, // This event is generated by the PC module - // at the end of prolog analysis. Plugins may - // hook to it and improve the analysis. - // in: ea_t first_past_prolog_insn - // pushinfo_t *pi - // Returns: 1-ok, 2-ok but do not automatically verify epilog - ev_verify_epilog, // Verify function epilog - // in: int *answer - // pushinfo_t *pi - // const insn_t *insn - // 'insn' structure must be filled with the first epilog instruction - // number of verified epilog instructions will be in the 'answer' - // returns: 1-ok, otherwise-failed - obsolete_ev_find_reg_value, // not used anymore, use ev_find_reg_value - ev_dbgtools_path, // Returns the configuration value of the debugging tools path (from IDA.CFG) - // in: char *path - // size_t path_size - // returns: 1-if value is set, 0-if value not set in IDA.CFG - ev_is_get_pc_thunk, // Detect get_pc_thunk calls - // in: RegNo *p_reg, - // ea_t *p_end - // const insn_t *ins - // returns: 1-found, -1-not found, 0-not implemented - - ev_vxd_loaded, // notification: a virtual device driver (Vxd) is loaded - - ev_get_borland_template_node, - // out: netnode *node - // returns: 1-found, -1-not found - ev_clear_borland_template_node, - // returns: nothing - ev_borland_template,// Applies Borland RTTI template for the given address - // in: ea_t ea, - // bool bp_mode if false - bc - // bool recursive - // returns: 1-created, -1-not created - ev_get_segval, // Get segment for the specified instruction operand - // in: ea_t *out, - // const insn_t *insn, - // const op_t *x - // returns: 1-success - ev_get_idpflags, // Get idpflags - // in: uint32 *idpflags - // returns: 1 success, fill IDPFLAGS - ev_get_ret_target, // Some 'ret' insns do not return from the function but are used for short jumps - // (for example: push off; ret). The following functions mark such 'ret' instructions. - // in: ea_t ea - // ea_t *target - // returns: 1 success, fill TARGET - ev_set_ret_target, // in: ea_t ea - // ea_t target - ev_del_ret_target, // in: ea_t ea - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline void set_difbase(int onoff) - { - processor_t::notify(idp_ev(ev_set_difbase), onoff); - } - - inline bool restore_pushinfo(pushinfo_t *pi, ea_t func_start) - { - return processor_t::notify(idp_ev(ev_restore_pushinfo), pi, func_start) == 1; - } - - inline bool save_pushinfo(ea_t func_start, pushinfo_t *pi) - { - return processor_t::notify(idp_ev(ev_restore_pushinfo), func_start, pi) == 1; - } - - inline int prolog_analyzed(ea_t first_past_prolog_insn, pushinfo_t *pi) - { - return processor_t::notify(idp_ev(ev_prolog_analyzed), first_past_prolog_insn, pi); - } - - inline bool verify_epilog(int *answer, pushinfo_t *pi, const insn_t &insn) - { - return processor_t::notify(idp_ev(ev_verify_epilog), answer, pi, &insn) == 1; - } - - inline bool dbgtools_path(char *path, size_t path_size) - { - return processor_t::notify(idp_ev(ev_dbgtools_path), path, path_size) == 1; - } - - inline int is_get_pc_thunk(RegNo *p_reg, ea_t *p_end, const insn_t &insn) - { - return processor_t::notify(idp_ev(ev_is_get_pc_thunk), p_reg, p_end, &insn); - } - - inline int vxd_loaded() - { - return processor_t::notify(idp_ev(ev_vxd_loaded)); - } - - inline bool get_borland_template_node(netnode *node) - { - return processor_t::notify(idp_ev(ev_get_borland_template_node), node) > 0; - } - - inline void clear_borland_template_node(void) - { - processor_t::notify(idp_ev(ev_clear_borland_template_node)); - } - - inline bool borland_template(ea_t ea, bool bp_mode, bool recursive) - { - return processor_t::notify(idp_ev(ev_borland_template), - ea, - bp_mode, - recursive) > 0; - } - - inline ea_t get_segval(const insn_t &insn, const op_t &x) - { - ea_t ea = BADADDR; - processor_t::notify(idp_ev(ev_get_segval), &ea, &insn, &x); - return ea; - } - - inline uint32 get_idpflags() - { - uint32 idpflags; - processor_t::notify(idp_ev(ev_get_idpflags), &idpflags); - return idpflags; - } - - inline bool get_ret_target(ea_t ea, ea_t *target) - { - return processor_t::notify(idp_ev(ev_get_ret_target), ea, target) == 1; - } - - inline void set_ret_target(ea_t ea, ea_t target) - { - processor_t::notify(idp_ev(ev_set_ret_target), ea, target); - } - - inline void del_ret_target(ea_t ea) - { - processor_t::notify(idp_ev(ev_del_ret_target), ea); - } -} - -//------------------------------------------------------------------------- -#define AFIDP_PUSH 0x0001 // push seg; push num; is converted to offset -#define AFIDP_NOP 0x0002 // db 90h after jmp is converted to nop - -#define AFIDP_MOVOFF 0x0004 // mov reg, numoff <- convert to offset - // mov segreg, immseg - -#define AFIDP_MOVOFF2 0x0008 // mov z, numoff <- convert to offset - // mov z, immseg - // where z - o_mem, o_displ -#define AFIDP_ZEROINS 0x0010 // allow zero opcode instructions: - // add [bx+si], al (16bit) - // add [eax], al (32bit) - // add [rax], al (64bit) - -#define AFIDP_BRTTI 0x0020 // Advanced analysis of Borlands RTTI -#define AFIDP_UNKRTTI 0x0040 // -"- with 'unknown_libname' -#define AFIDP_EXPFUNC 0x0080 // for PE? bc(ms?) - expanding - // function (exception subblock) -#define AFIDP_DIFBASE 0x0100 // Allow references with different segment bases -#define AFIDP_NOPREF 0x0200 // Don't display superfluous prefixes -#define AFIDP_NOVXD 0x0400 // Don't interpret int 20 as VxDcall -#define AFIDP_NOFPEMU 0x0800 // Disable FPU emulation instructions -#define AFIDP_SHOWRIP 0x1000 // Explicit RIP-addressing -#define AFIDP_NOSEH 0x2000 // Disable SEH/EH analysis -#define AFIDP_INT3STOP 0x4000 // int 3 may stop code flow - // call - // int 3 <- this is likely a no-return guard -#define AFIDP_NOAGGRJMPS 0x8000 // Don't aggressively convert jumps to thunk functions - // 'NO' is used to simplify upgrading existing idbs - -inline bool should_af_push(void) { return (pc_module_t::get_idpflags() & AFIDP_PUSH) != 0; } -inline bool should_af_nop(void) { return (pc_module_t::get_idpflags() & AFIDP_NOP) != 0; } -inline bool should_af_movoff(void) { return (pc_module_t::get_idpflags() & AFIDP_MOVOFF) != 0; } -inline bool should_af_movoff2(void) { return (pc_module_t::get_idpflags() & AFIDP_MOVOFF2) != 0; } -inline bool should_af_zeroins(void) { return (pc_module_t::get_idpflags() & AFIDP_ZEROINS) != 0; } -inline bool should_af_brtti(void) { return (pc_module_t::get_idpflags() & AFIDP_BRTTI) != 0; } -inline bool should_af_urtti(void) { return (pc_module_t::get_idpflags() & AFIDP_UNKRTTI) != 0; } -inline bool should_af_fexp(void) { return (pc_module_t::get_idpflags() & AFIDP_EXPFUNC) != 0; } -inline bool should_af_difbase(void) { return (pc_module_t::get_idpflags() & AFIDP_DIFBASE) != 0; } -inline bool should_af_nopref(void) { return (pc_module_t::get_idpflags() & AFIDP_NOPREF) != 0; } -inline bool should_af_vxd(void) { return (pc_module_t::get_idpflags() & AFIDP_NOVXD) == 0; } -inline bool should_af_fpemu(void) { return (pc_module_t::get_idpflags() & AFIDP_NOFPEMU) == 0; } -inline bool should_af_showrip(void) { return (pc_module_t::get_idpflags() & AFIDP_SHOWRIP) != 0; } -inline bool should_af_seh(void) { return (pc_module_t::get_idpflags() & AFIDP_NOSEH) == 0; } -inline bool should_af_int3stop(void) { return (pc_module_t::get_idpflags() & AFIDP_INT3STOP) != 0; } -inline bool should_af_aggrjmps(void) { return (pc_module_t::get_idpflags() & AFIDP_NOAGGRJMPS) == 0; } - -//------------------------------------------------------------------------- -inline bool get_ret_target(ea_t ea, ea_t *target) { return pc_module_t::get_ret_target(ea, target); } -inline void set_ret_target(ea_t ea, ea_t target) { return pc_module_t::set_ret_target(ea, target); } -inline void del_ret_target(ea_t ea) { return pc_module_t::del_ret_target(ea); } - -//------------------------------------------------------------------------- -// Don't use the following define's with underscores at the start! -#define _PT_486p 0x00000001 -#define _PT_486r 0x00000002 -#define _PT_386p 0x00000004 -#define _PT_386r 0x00000008 -#define _PT_286p 0x00000010 -#define _PT_286r 0x00000020 -#define _PT_086 0x00000040 -#define _PT_586p 0x00000080 // Pentium real mode -#define _PT_586r 0x00000100 // Pentium protected mode -#define _PT_686r 0x00000200 // Pentium Pro real -#define _PT_686p 0x00000400 // Pentium Pro protected -#define _PT_mmx 0x00000800 // MMX extensions -#define _PT_pii 0x00001000 // Pentium II -#define _PT_3d 0x00002000 // 3DNow! extensions -#define _PT_piii 0x00004000 // Pentium III -#define _PT_k7 0x00008000 // AMD K7 -#define _PT_p4 0x00010000 // Pentium 4 -#define _PT_sse3 0x00020000 // SSE3 + SSSE3 -#define _PT_sse4 0x00040000 // SSE4.1 + SSE4.2 - -// -// The following values mean 'is XXX processor or better?' -// - -#define PT_sse4 _PT_sse4 -#define PT_sse3 (_PT_sse3 | _PT_sse4 ) -#define PT_p4 ( PT_sse3 | _PT_p4 ) -#define PT_k7 ( PT_p4 | _PT_k7 ) -#define PT_piii ( PT_k7 | _PT_piii ) -#define PT_k62 ( PT_piii | _PT_3d ) -#define PT_3d _PT_3d -#define PT_pii ( PT_piii | _PT_pii ) -#define PT_mmx (_PT_mmx | _PT_3d ) -#define PT_686p ( PT_pii | _PT_686p ) -#define PT_686r ( PT_686p | _PT_686r ) -#define PT_586p ( PT_686r | _PT_586p ) -#define PT_586r ( PT_586p | _PT_586r ) -#define PT_486p ( PT_586r | _PT_486p ) -#define PT_486r ( PT_486p | _PT_486r ) -#define PT_386p ( PT_486r | _PT_386p ) -#define PT_386r ( PT_386p | _PT_386r ) -#define PT_286p ( PT_386r | _PT_286p ) -#define PT_286r ( PT_286p | _PT_286r ) -#define PT_086 ( PT_286r | _PT_086 ) - -// -// The following values mean 'is exactly XXX processor?' -// - -#define PT_ismmx (_PT_mmx ) -#define PT_is686 (_PT_686r | _PT_686p) -#define PT_is586 (_PT_586r | _PT_586p) -#define PT_is486 (_PT_486r | _PT_486p) -#define PT_is386 (_PT_386r | _PT_386p) -#define PT_is286 (_PT_286r | _PT_286p) -#define PT_is086 (_PT_086) - -//--------------------------------------------------------------------- -inline bool isProtected(uint32 type) -{ - return (type - & (_PT_286p - | _PT_386p - | _PT_486p - | _PT_586p - | _PT_686p - | _PT_pii)) != 0; -} - -inline bool isAMD(uint32 type) { return (type & PT_k7 ) != 0; } -inline bool isp4(uint32 type) { return (type & PT_p4 ) != 0; } -inline bool isp3(uint32 type) { return (type & PT_piii) != 0; } -inline bool is3dnow(uint32 type) { return (type & PT_3d ) != 0; } -inline bool ismmx(uint32 type) { return (type & PT_mmx ) != 0; } -inline bool isp2(uint32 type) { return (type & PT_pii ) != 0; } -inline bool is686(uint32 type) { return (type & PT_686r) != 0; } -inline bool is586(uint32 type) { return (type & PT_586r) != 0; } -inline bool is486(uint32 type) { return (type & PT_486r) != 0; } -inline bool is386(uint32 type) { return (type & PT_386r) != 0; } // is 386 or better ? -inline bool is286(uint32 type) { return (type & PT_286r) != 0; } // is 286 or better ? - -#endif // _INTEL_HPP diff --git a/idasdk75/include/jumptable.hpp b/idasdk75/include/jumptable.hpp deleted file mode 100644 index c0db20f..0000000 --- a/idasdk75/include/jumptable.hpp +++ /dev/null @@ -1,824 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __JUMPTABLE_HPP -#define __JUMPTABLE_HPP - -#include -#include // op_t -#include // switch_info_t, jumptable_info_t -#include - -// Class to check for a jump table sequence. -// This class should be used in preference to the hard encoding of jump table sequences -// because it allows for: -// - instruction rescheduling -// - intermingling the jump sequence with other instructions -// - sequence variants -// -// For this class: -// all instructions of the sequence are numbered starting from the last instruction. -// The last instruction has the number 0. -// The instruction before the last instruciton has the number 1, etc. -// There is a virtual function jpiN() for each instruction of the sequence -// These functions return true if 'insn' is filled with the required instruction -// -// The comparison is made in the match() function: -// -// ea points to the last instruction of the sequence (instruction #0) -// -// the 'depends' array contains dependencies between the instructions of the sequence. -// For example: -// ARM thumb LDRH switch -// 7 SUB Ra, #minv (optional) -// 6 CMP Ra, #size -// 5 BCS defea -// 4 ADR Rb, jt -// 3 ADD Rb, Rb, Ra -// 2 LDRH Rb, [Rb,Ra] -// 1 LSL Rb, Rb, #1 -// 0 ADD PC, Rb -// In this sequence, instruction #0 depends on the value of Rb which is produced -// by the instruction #1. So, the instruction #0 depends on #1. Therefore, depends[0] -// will contain '1' as its element. -// The instruction #3 depends on 2 registers: Ra and Rb, or in other words, -// it depends on the instructions #4 and #6. Therefore, depends[2] will contain { 4, 6 } -// Maximum 4 dependencies per instruction are allowed. -// -// FIXME -// The 'roots' array contains the first instruction of the dependency chains. -// In our case we can say that there are 2 dependency chains: -// 0 -> 1 -> 2 -> 3 -> 4 -// -> 6 -> 7 -// 5 -> 6 -// Therefore the roots array will consist of {1, 5}. -// 0 denotes the end of the chain and cannot be the root of a dependency chain -// Usually 1 is a root of any jump sequence. -// -// The dependency array allows for checking for optimized sequences of instructions. -// If 2 instructions are not dependent on each other, they may appear in any order. -// (for example, the instruction #4 and the instruction sequence #5-6-7 may appear -// in any order because they do not depend on each other) -// Also any other instructions not modifying the register values may appear between -// the instructions of the sequence (due to the instruction rescheduling performed -// by the compiler). -// -// Provision for optional instructions: -// The presence of an optional instruction in the sequence (like #7) is signalled -// by a negative number of the dependency in the 'depends' array. -// -// Provision for variable instructions: -// In some cases several variants of the same instructions may be supported. -// For example, the instruction #5 might be BCS as well as BGE. It is the job of -// the jpi5() function to check for all variants. -// -// In order to use the 'jump_pattern_t' class you should derive another class from it -// and define the jpiN() virtual functions. -// Then you have to define the 'depends' and 'roots' arrays and call the match() -// function. -// If you processor contains instructions who modify registers in peculiar ways -// you might want to override the check_spoiled() function. - - -//---------------------------------------------------------------------- -// Macro to declare implementation of methods of jump_pattern_t -class jump_pattern_t; -// tracked registers -// We use the 'size' term to denote the number of bits involved in the insn. -// E.g. an operand of type dt_byte has 8-bit size. -// We store the current size (the number of used bits) in the DTYPE field -// of the 'op_t' structure. It may differ from the size of operand in the -// insn. See the comment for set_moved(). -// We extend the 'op_dtype_t' type by some negative constants to denote -// sizes from 2 to 7 bits. -typedef qvector tracked_regs_t; -#define DECLARE_JUMP_PATTERN_HELPERS(decl)\ -decl void ida_export check_spoiled_jpt(const jump_pattern_t *_this, tracked_regs_t *_regs); \ -decl bool ida_export match_jpt(jump_pattern_t *_this);\ -decl bool ida_export same_value_jpt(jump_pattern_t *_this, const op_t &op, int r_i);\ -decl void ida_export combine_regs_jpt(jump_pattern_t *_this, tracked_regs_t *dst, const tracked_regs_t &src, ea_t ea);\ -decl void ida_export mark_switch_insns_jpt(const jump_pattern_t *_this, int last, int);\ -decl bool ida_export set_moved_jpt(const jump_pattern_t *_this, const op_t &dst, const op_t &src, tracked_regs_t &_regs, op_dtype_t real_dst_dtype, op_dtype_t real_src_dtype); - -DECLARE_JUMP_PATTERN_HELPERS(idaman) - -class jump_pattern_t -{ -protected: - // 32-bit operand generates a 32-bit result, zero- or sign-extended to a - // 64-bit result. This flag may be overwritten in processor modules. - // For example: - // ARM: MOV W8, #0x3C will clear the upper 32 bits of X8, - // PC : mov eax, 3Ch will clear the upper 32 bits of rax - bool modifying_r32_spoils_r64; - -public: - typedef bool (jump_pattern_t::*check_insn_t)(void); - inline jump_pattern_t( - switch_info_t *si, // may be NULL - const char (*depends)[4], - int last_reg); - - insn_t insn; // current instruction - switch_info_t *si; // answers will be here - - enum - { - NINS = 16, // the maximum length of the sequence - INS_MASK = 0x0F, - }; - ea_t eas[NINS]; - bool skip[NINS]; // do not check the Nth insn if skip[N] is true - int non_spoiled_reg; // if non_spoiled_reg was spoiled then we stop - // matching - check_insn_t check[NINS]; - // this is the hidden return value of the jpiN() methods. If it is set and - // jpiN() returned 'true' then we stop processing the dependency chain. If - // it is set and jpiN() returned 'false' then we stop checking the insns - // in the current basic block and we are switching to the next one (and we - // fail if there is no such block). - bool stop_matching; - // this flag can be analyzed by jpiN(). It means that the current insn is - // in the linear flow from the previous insn. It is always 'true' if the - // insn has JPT_NEAR flag. - bool in_linear_flow; - // this address can be analyzed by jpiN(). It means the end of the current - // block. It may help if we want to check in-block jumps. - ea_t block_end; - - #define JPT_OPT 0x10 // the dependent insn might be missing - #define JPT_NEAR 0x20 // the dependent insn must be in the linear flow - - const char (*depends)[4]; // instruction, on which we depend, and - // additional JPT_... flags - - // mark swith instructions to be ignored by the decompiler - // do not mark the indirect jmp (eas[0]) as ignored - // it will be used to recognize switch idioms - // unmark NLOWCASE insns after LAST (in the case of SWI_HXNOLOWCASE flag) - void mark_switch_insns(int last = NINS - 1, int nlowcase = 0) const - { - mark_switch_insns_jpt(this, last, nlowcase); - } - - // for fragmented switch idioms, cmp/jbe might be located in a separate - // fragment. we must not mark these instructions as part of the switch - // idiom because doing so would spoil the program logic for the decompiler - // and make the switch operator unreachable. the following vector keeps - // addresses of all instructions which must not be marked. this vector is - // maintained by derived classes. - eavec_t remote_code; - // extra insns used to calculate values (discovered by find_op_value) - eavec_t extra_insn_eas; - // tracked registers - tracked_regs_t regs; - - // handle a possible delay slot situation - // while walking backwards in the execution flow - // if is false and is in a delay - // slot of a branch likely instruction - // then set to the branch instruction - // (=annul the delay slot) - // if is true and the instruction at - // has a delay slot then set to the delay slot - // (=execute the delay slot) - virtual void process_delay_slot(ea_t &/*ea*/, bool /*branch*/) const {} - - // an artificial register to track the address of the conditional jump - // .value - condition - // .addr - address of the conditional jump - // .specval - address of the default case - // the derived class can use .reg to track the condition register - enum - { - o_condjump = 99, - cc_inc_ncases = 0x01, // increment ncases - cc_check_max_ncases = 0x02, // comparison with the maximum value - }; - - // compare supported operands - virtual bool equal_ops(const op_t &x, const op_t &y) const - { - if ( x.type != y.type ) - return false; - switch ( x.type ) - { - case o_void: - // consider spoiled values as not equal - return false; - case o_reg: - // ignore difference in the data size of registers - return x.reg == y.reg; - case o_condjump: - // we do not track the condition flags - return true; - } - return false; - } - - // return true if the instruction `insn' is a move one, - // there is no need check spoiled registers in this case - virtual bool handle_mov(tracked_regs_t & /*_regs*/ ) - { - return false; - } - // does the instruction `insn' spoil `_regs' ? - virtual void check_spoiled(tracked_regs_t *_regs) const - { - check_spoiled_jpt(this, _regs); - } - // some binaries use the following pattern - // xor eax, eax | mov al, cl - // so we can extend dtype of the operand from dt_byte to dt_dword - virtual op_dtype_t extend_dtype(const op_t &op) const - { - return op.dtype; // do not extend - } - - // these methods are not virtual and should be used in processor - // module only - inline void track(int reg, int r_i, op_dtype_t dtype); - inline void trackop(const op_t &op, int r_i); - inline bool is_spoiled(int r_i) { return regs[r_i].type == o_void; } - inline bool is_equal(int reg, int r_i, op_dtype_t dtype); - inline bool is_equal(const op_t &op, int r_i); - inline bool same_value(const op_t &op, int r_i); - - virtual bool jpi0(void) = 0; - virtual bool jpi1(void) { return false; } - virtual bool jpi2(void) { return false; } - virtual bool jpi3(void) { return false; } - virtual bool jpi4(void) { return false; } - virtual bool jpi5(void) { return false; } - virtual bool jpi6(void) { return false; } - virtual bool jpi7(void) { return false; } - virtual bool jpi8(void) { return false; } - virtual bool jpi9(void) { return false; } - virtual bool jpia(void) { return false; } - virtual bool jpib(void) { return false; } - virtual bool jpic(void) { return false; } - virtual bool jpid(void) { return false; } - virtual bool jpie(void) { return false; } - virtual bool jpif(void) { return false; } - // jpi will be called if pre_jpi returns true - virtual bool pre_jpi(int /*n*/) { return true; } - - bool match(const insn_t &_insn) { insn = _insn; return match_jpt(this); } - - // remove compiler warnings -- class with virtual functions MUST have virtual destructor - virtual ~jump_pattern_t() {} - - // helpers for mov instruction tracing (see methods handle_mov(), - // check_spoiled() above) - inline static void set_spoiled(tracked_regs_t *_regs); - inline void set_spoiled(tracked_regs_t *_regs, const op_t &op) const; - // track 'mov' insn: dst <- src - // it returns 'true' if insn changes any of the tracked registers - // REAL_DST_DTYPE is the size that will be changed in the DST operand by - // the insn. It can be greater than the operand size because some insns - // clear the upper bits. For example: - // xor eax, eax | mov ax, cx REAL_DST_DTYPE is 32 - // xor bh, bh | mov bl, cl REAL_DST_DTYPE is 16 - // Extending of the 32-bit register to 64 bits is performed automatically - // based on the modifying_r32_spoils_r64 flag. - // REAL_SRC_DTYPE is the size that will be used in the SRC operand by the - // insn. It can be less than the operand size. For example: - // ARM: AND W8, W8, #0xFF will use 8 bits of X8, - // PC : cwde will use 16 bits of rax. - bool set_moved( - const op_t &dst, - const op_t &src, - tracked_regs_t &_regs, - op_dtype_t real_dst_dtype = dt_void, - op_dtype_t real_src_dtype = dt_void) const - { - return set_moved_jpt(this, dst, src, _regs, real_dst_dtype, real_src_dtype); - } - // calculate state of registers before a conditional jump as the - // combination of states of each branch - void combine_regs( - tracked_regs_t *dst, - const tracked_regs_t &src, - ea_t ea) - { - combine_regs_jpt(this, dst, src, ea); - } - -protected: - bool match_tree(); - bool follow_tree(ea_t ea, int n); - bool same_value_impl(const op_t &op, int r_i); - - inline bool equal_ops_dtype(const op_t &op, const op_t ®) const; - static inline bool is_narrower(op_dtype_t dt1, op_dtype_t dt2); - enum - { - dt_7bit = 255, - dt_6bit = 254, - dt_5bit = 253, - dt_4bit = 252, - dt_3bit = 251, - dt_2bit = 250, - }; - static inline int get_dtype_nbits(op_dtype_t dtype); - - // helper for check_spoiled() - // TODO introduce new virtual methods spoils() and spoils_flags() and - // replace check_spoiled() by non-virtual method - inline void check_spoiled_not_reg( - tracked_regs_t *_regs, - uint maxop = UA_MAXOP) const; - - DECLARE_JUMP_PATTERN_HELPERS(friend) -}; - -//---------------------------------------------------------------------- -// kinds of jump tables -enum { JT_NONE = 0, JT_SWITCH, JT_CALL }; -// It returns a nonzero JT_... kind if it found a jump pattern. This kind is -// passed to the check_table() function. -typedef int is_pattern_t(switch_info_t *si, const insn_t &insn, procmod_t *procmod); -// It returns a refined kind. For example, JT_NONE if the found jump pattern -// is not a switch, or JT_CALL if it is a call of a func from an array -typedef int table_checker_t( - switch_info_t *si, - ea_t jump_ea, - int is_pattern_res, - procmod_t *pm); -// check a flat 32/16/8 bit jump table -- the most common case -idaman int ida_export check_flat_jump_table( - switch_info_t *si, - ea_t jump_ea, - int is_pattern_res = JT_SWITCH); - -// This function finds a switch. It calls functions from the PATTERNS -// array in turn until the first one returns a nonzero value. -// If a suitable pattern is found, it calls check_table() for the final -// check, passing a nonzero result code of the 'is_pattern_t' function. -// If the CHECK_TABLE parameter is NULL then check_flat_jump_table() is -// called. -// NAME is used for a debug output. -// It returns 'false' if INSN is not a switch or it is a call of a func from -// an array. In the latter case it defines this array. -idaman bool ida_export check_for_table_jump( - switch_info_t *si, - const insn_t &insn, - is_pattern_t *const patterns[], - size_t qty, - table_checker_t *check_table = NULL, - const char *name = NULL); - -//---------------------------------------------------------------------- -// sometimes the size of the jump table is misdetected -// check if any of the would-be targets point into the table -// and if so, truncate it -// if 'ignore_refs' is false, also stop at first data reference -idaman void ida_export trim_jtable( - switch_info_t *si, - ea_t jump_ea, - bool ignore_refs = false); - -//---------------------------------------------------------------------- -// this function find the size of the jump table for indirect switches -// (indirect switches have the values table which contains indexes into -// the jump table) -// in: si->ncases has the size of the values table -// out: si->jcases is initialized -idaman bool ida_export find_jtable_size(switch_info_t *si); - -//---------------------------------------------------------------------- -// get default jump address from the jump table. -// This method can be used only for a sparse nonindirect switch with default -// case in the jump table. -idaman ea_t ida_export find_defjump_from_table( - ea_t jump_ea, - const switch_info_t &si); - - -//---------------------------------------------------------------------- -// iterate instructions in the backward execution flow -//lint -esym(1512,backward_flow_iterator_t*) destructor is not virtual -template -// State: default constructor, operator= -// Ctrl: combine_regs(State *, const State& ,ea_t) -// process_delay_slot(ea_t &/*ea*/, bool /*branch*/) -struct backward_flow_iterator_t -{ -public: - ea_t cur_ea; // current address - State ®s; // current state of the tracked registers - Ctrl &ctrl; // to combine state - bool only_near; // should we follow only the linear flow? - uint max_insn_cnt; - -protected: - //lint --e{958} padding is required - func_t *pfn; // to check bounds - const segment_t *seg; - ea_t start_ea; - ea_t cur_end; // end of current basic block - uint insn_cnt; - // visited basic blocks: - // key_type - start of the block, mapped_type - end of the block; - typedef std::map visited_t; - visited_t visited; - // waiting basic blocks: - // key_type - end of the block, mapped_type - state at the end; - struct state_t - { - State regs; - uint insn_cnt; - state_t() : regs(), insn_cnt(UINT_MAX) {} - }; - typedef std::map waiting_t; - waiting_t waiting; - -public: - backward_flow_iterator_t( - ea_t start_ea_, - State &start_regs, - Ctrl &ctrl_, - bool only_near_, - uint max_insn_cnt_ = 0) - : cur_ea(start_ea_), - regs(start_regs), - ctrl(ctrl_), - only_near(only_near_), - max_insn_cnt(max_insn_cnt_), - pfn(NULL), - seg(NULL), - start_ea(start_ea_), - cur_end(BADADDR), - insn_cnt(0), - visited(), - waiting() - { - // to check bounds - pfn = get_func(start_ea); - if ( pfn == NULL ) - { - seg = getseg(start_ea); - QASSERT(10183, seg != NULL); - } - } - - // fl_U : no previous instruction (start of a function or a cycle, - // or non linear flow if ONLY_NEAR is true), - // fl_F : got previous instruction by linear flow, - // fl_JF: got previous instruction by jump; - inline cref_t prev_insn(); - // stop iterating the current basic block, switch to the lowest waiting - // block - inline cref_t skip_block(); - - inline ea_t get_cur_end() const - { - return cur_end == BADADDR ? cur_ea : cur_end; - } - -protected: - // find visited basic block containing the address - // it returns the pointer to the address of the block end or NULL - inline ea_t *find_visited(ea_t ea); - // get the lowest to start_ea waiting block - inline cref_t get_waiting(); - // combine insn counter - count the shortest path - static inline void combine_insn_cnt(uint *dst, uint src) - { - if ( src < *dst ) - *dst = src; - } - - bool check_bounds() const - { - if ( pfn != NULL ) - return func_contains(pfn, cur_ea); - return seg->contains(cur_ea); - } -}; - -//------------------------------------------------------------------------- -// simple backward flow iterator -struct no_regs_t {}; -struct simple_bfi_t - : public backward_flow_iterator_t -{ - typedef backward_flow_iterator_t base_t; - -protected: - no_regs_t regs_; - -public: - simple_bfi_t(ea_t ea) - : base_t(ea, regs_, *this, false) {} - static void combine_regs(no_regs_t *, const no_regs_t &, ea_t) {} - static void process_delay_slot(ea_t &, bool) {} -}; - - -//====================================================================== -// inline implementation -//---------------------------------------------------------------------- -//-V:jump_pattern_t:730 not all members of a class are initialized inside the constructor -inline jump_pattern_t::jump_pattern_t( - switch_info_t *_si, - const char (*_depends)[4], - int last_reg) - : modifying_r32_spoils_r64(true), - si(_si), - non_spoiled_reg(-1), - in_linear_flow(false), - depends(_depends), - regs() -{ - if ( si != NULL ) - si->clear(); - regs.resize(last_reg + 1); -} - -//---------------------------------------------------------------------- -inline bool jump_pattern_t::equal_ops_dtype( - const op_t &op, - const op_t ®) const -{ - if ( !equal_ops(op, reg) ) - return false; - // operand should be wider than a tracked register - // e.g. after 'cmp cl, imm' we cannot use cx - if ( !is_narrower(op.dtype, reg.dtype) ) - return true; - // we believe that dword is widened to qword - if ( modifying_r32_spoils_r64 && op.dtype == dt_dword ) - return true; - // try to extend - if ( !is_narrower(extend_dtype(op), reg.dtype) ) - return true; - return false; -} - -//---------------------------------------------------------------------- -// return true if size1 is narrow than size2 -inline bool jump_pattern_t::is_narrower(op_dtype_t dt1, op_dtype_t dt2) -{ - if ( dt1 < dt_2bit ) - return dt2 < dt_2bit && dt1 < dt2; - else - return dt2 < dt_2bit || dt1 < dt2; -} - -//---------------------------------------------------------------------- -inline int jump_pattern_t::get_dtype_nbits(op_dtype_t dtype) -{ - switch ( dtype ) - { - case dt_byte: return 8; - case dt_word: return 16; - case dt_dword: return 32; - case dt_qword: return 64; - case dt_7bit: return 7; - case dt_6bit: return 6; - case dt_5bit: return 5; - case dt_4bit: return 4; - case dt_3bit: return 3; - case dt_2bit: return 2; - default: return -1; - } -} - -//---------------------------------------------------------------------- -inline void jump_pattern_t::check_spoiled_not_reg( - tracked_regs_t *_regs, - uint maxop) const -{ - uint32 feature = insn.get_canon_feature(PH); - if ( feature == 0 ) - return; - for ( uint i = 0; i < maxop; ++i ) - { - if ( has_cf_chg(feature, i) - && insn.ops[i].type != o_void - && insn.ops[i].type != o_reg ) - { - set_spoiled(_regs, insn.ops[i]); - } - } -} - -//---------------------------------------------------------------------- -inline void jump_pattern_t::track(int reg, int r_i, op_dtype_t dtype) -{ - regs[r_i].type = o_reg; - regs[r_i].reg = reg; - regs[r_i].dtype = dtype; -} -inline void jump_pattern_t::trackop(const op_t &op, int r_i) -{ - regs[r_i] = op; -} - -//---------------------------------------------------------------------- -inline bool jump_pattern_t::is_equal(int reg, int r_i, op_dtype_t dtype) -{ - op_t op; - op.type = o_reg; - op.reg = reg; - op.dtype = dtype; - return is_equal(op, r_i); -} -inline bool jump_pattern_t::is_equal(const op_t &op, int r_i) -{ - if ( regs[r_i].type == o_void ) - { - // there is no reason to continue match - stop_matching = true; - return false; - } - return equal_ops_dtype(op, regs[r_i]); -} - -//---------------------------------------------------------------------- -inline bool jump_pattern_t::same_value(const op_t &op, int r_i) -{ - return same_value_jpt(this, op, r_i); -} - -//---------------------------------------------------------------------- -inline void jump_pattern_t::set_spoiled(tracked_regs_t *__regs) -{ - tracked_regs_t &_regs = *__regs; - // spoil all registers - for ( size_t i = 0; i < _regs.size(); ++i ) - _regs[i].type = o_void; -} -inline void jump_pattern_t::set_spoiled(tracked_regs_t *__regs, const op_t &op) const -{ - tracked_regs_t &_regs = *__regs; - for ( size_t i = 0; i < _regs.size(); ++i ) - if ( equal_ops(_regs[i], op) ) - _regs[i].type = o_void; // spoil register -} - -//---------------------------------------------------------------------- -// find the previous instruction in code flow -// take into account branches and potential delay slots -template -inline cref_t backward_flow_iterator_t::prev_insn() -{ - size_t refcnt = 0; - // check visited basic block - ea_t *visited_end = find_visited(cur_ea); - if ( visited_end == NULL ) - { - // analyze references to the current address - flags_t F = get_flags(cur_ea); - if ( is_flow(F) ) - ++refcnt; - if ( has_xref(F) && !is_func(F) ) // do not count jumps to function - { - xrefblk_t xb; - for ( bool ok = xb.first_to(cur_ea, XREF_FAR); - ok && xb.iscode; - ok = xb.next_to() ) - { - // count only xrefs from jumps - if ( xb.type == fl_JF || xb.type == fl_JN ) - { - if ( only_near ) - { - if ( refcnt > 0 ) - return fl_U; - // do not consider the flow through another switch as linear - if ( (get_flags(xb.from) & FF_JUMP) != 0 ) - return fl_U; - } - ++refcnt; - ea_t ea = xb.from; - ctrl.process_delay_slot(ea, true); - // ignore jumps from already visited blocks - if ( find_visited(ea) != NULL ) - continue; - // add basic block to the waiting set (combine state of the - // tracked registers at the jump source) - state_t &src_state = waiting[ea]; - ctrl.combine_regs(&src_state.regs, regs, ea); - combine_insn_cnt(&src_state.insn_cnt, insn_cnt); - } - } - } - - if ( cur_end == BADADDR ) - cur_end = cur_ea; - - // try ordinary flow - if ( is_flow(F) ) - { - ea_t prev_ea = prev_not_tail(cur_ea); - if ( prev_ea != BADADDR ) - { - cur_ea = prev_ea; - if ( check_bounds() - && (max_insn_cnt == 0 || insn_cnt < max_insn_cnt) ) - { - ++insn_cnt; - // remove reached waiting basic block - typename waiting_t::iterator w = waiting.find(cur_ea); - if ( w != waiting.end() ) - { - ctrl.combine_regs(®s, w->second.regs, cur_ea); - combine_insn_cnt(&insn_cnt, w->second.insn_cnt); - waiting.erase(w); - } - else - { - ctrl.process_delay_slot(cur_ea, false); - } - return fl_F; - } - } - // choose another branch - } - - // save block [cur_ea, cur_end] as visited - visited[cur_ea] = cur_end; - } - else if ( cur_end != BADADDR ) - { - // reach visited basic block => extend it - *visited_end = cur_end; - } - - // get the lowest waiting block - cref_t ret = get_waiting(); - // consider one xref as a linear flow - if ( ret == fl_JF && refcnt == 1 && waiting.empty() ) - ret = fl_F; - return ret; -} - -//---------------------------------------------------------------------- -template -inline cref_t backward_flow_iterator_t::skip_block() -{ - // check visited basic block - ea_t *visited_end = find_visited(cur_ea); - if ( visited_end == NULL ) - { - if ( cur_end == BADADDR ) - cur_end = cur_ea; - // save block [cur_ea, cur_end] as visited - visited[cur_ea] = cur_end; - } - else if ( cur_end != BADADDR ) - { - // reach visited basic block => extend it - *visited_end = cur_end; - } - - // get the lowest waiting block - return get_waiting(); -} - -//---------------------------------------------------------------------- -template -inline cref_t backward_flow_iterator_t::get_waiting() -{ - while ( !waiting.empty() ) - { - typename waiting_t::iterator w = waiting.upper_bound(start_ea); - if ( w != waiting.begin() ) - --w; - cur_ea = w->first; - if ( check_bounds() ) - { - cur_end = BADADDR; - regs = w->second.regs; - insn_cnt = w->second.insn_cnt; - waiting.erase(w); - return fl_JF; - } - waiting.erase(w); - } - return fl_U; -} - -//---------------------------------------------------------------------- -template -inline ea_t *backward_flow_iterator_t::find_visited(ea_t ea) -{ - visited_t::iterator v = visited.upper_bound(ea); - // assert: v == visited.end() || v->first > ea - if ( v == visited.begin() ) - return NULL; - --v; - // assert: v->first <= ea - if ( ea > v->second ) - return NULL; - return &v->second; -} - - -#endif diff --git a/idasdk75/include/kernwin.hpp b/idasdk75/include/kernwin.hpp deleted file mode 100644 index bedfd84..0000000 --- a/idasdk75/include/kernwin.hpp +++ /dev/null @@ -1,7681 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -/*! \file kernwin.hpp - - \brief Defines the interface between the kernel and the UI. - - It contains: - - the UI dispatcher notification codes (::ui_notification_t) - - convenience functions for UI services - - structures which hold information about the - lines (disassembly, structures, enums) generated - by the kernel - - functions to interact with the user (dialog boxes) - - some string and conversion functions. -*/ - -#ifndef __KERNWIN_HPP -#define __KERNWIN_HPP -//-V:DEF_SET_METHOD:524 equivalent function bodies -//-V:DEF_FIELD_METHOD:524 -//-V:place_t:730 not all members of a class are initialized inside the constructor -//-V:structplace_t:730 -//-V:idaplace_t:730 -//-V:enumplace_t:730 - -#ifndef SWIG -typedef uchar color_t; ///< see -typedef uval_t bmask_t; ///< see -typedef tid_t enum_t; ///< see -struct rangevec_t; ///< see -class location_t; ///< see -struct lochist_entry_t; ///< see -struct strwinsetup_t; ///< see -struct renderer_info_t; ///< see -struct segm_move_infos_t; ///< see -struct load_info_t; ///< see -#endif // SWIG - -/// Message box kinds -enum mbox_kind_t -{ - mbox_internal, ///< internal error - mbox_info, - mbox_warning, - mbox_error, - mbox_nomem, - mbox_feedback, - mbox_readerror, - mbox_writeerror, - mbox_filestruct, - mbox_wait, - mbox_hide, - mbox_replace, -}; - - -/// List chooser types -enum choose_type_t -{ - chtype_generic, ///< the generic choose() function - chtype_idasgn, ///< see choose_idasgn() - chtype_entry, ///< see choose_entry() - chtype_name, ///< see choose_name() - chtype_stkvar_xref, ///< see choose_stkvar_xref() - chtype_xref, ///< see choose_xref() - chtype_enum, ///< see choose_enum() - chtype_enum_by_value, ///< Deprecated. See ::chtype_enum_by_value_and_size - chtype_func, ///< see choose_func() - chtype_segm, ///< see choose_segm() - chtype_struc, ///< see choose_struc() - chtype_strpath, ///< see choose_struc_path() - chtype_idatil, ///< see choose_til() - chtype_enum_by_value_and_size, ///< see choose_enum_by_value() - chtype_srcp, ///< see choose_srcp() -}; - - -enum beep_t ///< Beep types -{ - beep_default = 0 -}; - - -// Notify UI about various events. The kernel will call this function -// when something interesting for the UI happens. -// The UI should avoid calling the kernel from this callback. - -class func_t; -class segment_t; -struct sreg_range_t; -class struc_t; -class member_t; -class plugin_t; -struct plugmod_t; -struct procmod_t; -class minsn_t; -class idc_value_t; -class linput_t; -class snapshot_t; - -/// TWidget renderer type -enum tcc_renderer_type_t -{ - TCCRT_INVALID = 0, ///< invalid - TCCRT_FLAT, ///< flat view - TCCRT_GRAPH, ///< graph view - TCCRT_PROXIMITY ///< proximity view -}; - -/// TWidget ::place_t type -enum tcc_place_type_t -{ - TCCPT_INVALID = 0, ///< invalid - TCCPT_PLACE, ///< ::place_t - TCCPT_SIMPLELINE_PLACE, ///< ::simpleline_place_t - TCCPT_IDAPLACE, ///< ::idaplace_t - TCCPT_ENUMPLACE, ///< ::enumplace_t - TCCPT_STRUCTPLACE ///< ::structplace_t -}; - -/// Represents mouse button for view_mouse_event_t objects -enum vme_button_t -{ - VME_UNKNOWN, ///< unknown mouse button - VME_LEFT_BUTTON, ///< left mouse button - VME_RIGHT_BUTTON, ///< right mouse button - VME_MID_BUTTON, ///< middle mouse button -}; - -//------------------------------------------------------------------------- -/// \defgroup SETMENU_ Set menu flags -/// Passed as 'flags' parameter to attach_action_to_menu() -/// In case menupath == NULL new item will be added to the end of menu even when -/// SETMENU_APP is not set. SETMENU_FIRST can be used to change this behaviour -/// Note: The upper 16 bits are reserved for UI internal use. -//@{ -#define SETMENU_POSMASK 0x3 -#define SETMENU_INS 0x0 ///< add menu item before the specified path (default) -#define SETMENU_APP 0x1 ///< add menu item after the specified path -#define SETMENU_FIRST 0x2 ///< add item to the beginning of menu -//@} - -/// \defgroup CREATETB_ create toolbar flags -/// Passed as 'flags' parameter to create_toolbar() -//@{ -#define CREATETB_ADV 0x1 ///< toolbar is for 'advanced mode' only -//@} - -//------------------------------------------------------------------------- -/// \defgroup HIF_ set_highlightr flags -/// Passed as 'flags' parameter to set_highlight() -//@{ -#define HIF_IDENTIFIER 0x1 ///< text is an identifier (i.e., when searching for the current highlight, SEARCH_IDENT will be used) -#define HIF_REGISTER 0x2 ///< text represents a register (aliases/subregisters will be highlit as well) -#define HIF_LOCKED 0x4 ///< locked; clicking/moving the cursor around doesn't change the highlight -#define HIF_NOCASE 0x8 ///< case insensitive -//@} - -#define REG_HINTS_MARKER SCOLOR_ON "\x7F" -#define REG_HINTS_MARKER_LEN 2 -#define SRCDBG_HINTS_MARKER SCOLOR_ON "\x7E" -#define SRCDBG_HINTS_MARKER_LEN 2 - - -#ifndef SWIG -/// Callui return codes. -/// The size of this type should be 4 bytes at most, -/// otherwise different compilers return it differently -union callui_t -{ - bool cnd; - char i8; - int i; - short i16; - int32 i32; - uchar u8; - ushort u16; - uint32 u32; - char *cptr; - void *vptr; - ssize_t ssize; - func_t *fptr; - segment_t *segptr; - struc_t *strptr; - plugin_t *pluginptr; - sreg_range_t *sraptr; -}; - -/// Events marked as 'ui:' should be used as a parameter to callui(). -/// (See convenience functions like get_screen_ea()) -/// Events marked as 'cb:' are designed to be callbacks and should not -/// be used in callui(). The user may hook to ::HT_UI events to catch them - -enum ui_notification_t -{ - ui_null = 0, - - ui_range, ///< cb: The disassembly range has been changed (\inf{min_ea} ... \inf{max_ea}). - ///< UI should redraw the scrollbars. See also: ::ui_lock_range_refresh - ///< \param none - ///< \return void - - ui_refresh_choosers, ///< cb: The list (chooser) window contents have been changed (names, signatures, etc). - ///< UI should redraw them. Please consider request_refresh() instead - ///< \param none - ///< \return void - - ui_idcstart, ///< cb: Start of IDC engine work. - ///< \param none - ///< \return void - - ui_idcstop, ///< cb: Stop of IDC engine work. - ///< \param none - ///< \return void - - ui_suspend, ///< cb: Suspend graphical interface. - ///< Only the text version. - ///< Interface should respond to it. - ///< \param none - ///< \return void - - ui_resume, ///< cb: Resume the suspended graphical interface. - ///< Only the text version. - ///< Interface should respond to it - ///< \param none - ///< \return void - - ui_broadcast, ///< cb: broadcast call - ///< \param magic (::int64) a magic number - ///< \param ... other parameters depend on the given magic - ///< modules may hook to this event and reply to the caller. - ///< for example, the decompiler uses it to communicate - ///< its entry point to other plugins - - ui_read_selection, ///< ui: see read_selection() - - ui_read_range_selection, ///< ui: see read_range_selection() - - ui_unmarksel, ///< ui: see unmark_selection() - - ui_screenea, ///< ui: see get_screen_ea() - - ui_saving, ///< cb: The kernel is flushing its buffers to the disk. - ///< The user interface should save its state. - ///< Parameters: none - ///< Returns: none - - ui_saved, ///< cb: The kernel has saved the database. - ///< This callback just informs the interface. - ///< \param none - ///< \return void - - ui_refreshmarked, ///< ui: see refresh_idaview() - - ui_refresh, ///< ui: see refresh_idaview_anyway() - - ui_choose, ///< ui: Allow the user to choose an object. - ///< Always use the helper inline functions for this code. - ///< See \ref ui_choose_funcs for a list of such functions. - ///< \param type (::choose_type_t) type of chooser to display - ///< \param ... other parameters depend on the given type - ///< \return depends on the given type - - ui_close_chooser, ///< ui: see close_chooser() - - ui_banner, ///< ui: see banner() - - ui_setidle, ///< ui: Set a function to call at idle times. - ///< \param func (int (*)(void)) pointer to function that will be called - ///< \return void - - ui_database_closed, ///< cb: The database has been closed. - ///< See also processor_t::closebase, it occurs earlier. - ///< See also ui_initing_database. - ///< This is not the same as IDA exiting. If you need - ///< to perform cleanup at the exiting time, use qatexit(). - ///< \param none - ///< \return void - - ui_beep, ///< ui: see beep() - - ui_is_msg_inited, ///< ui: see is_msg_inited() - - ui_msg, ///< ui: Show a message in the message window. - ///< \param format (const char *) format of message body - ///< \param va (va_list) format args - ///< \return number of bytes output - - ui_mbox, ///< ui: Show a message box. - ///< \param kind (::mbox_kind_t) - ///< \param format (const char *) format of message body - ///< \param va (va_list]) format args - ///< \return void - - ui_clr_cancelled, ///< ui: see clr_cancelled() - - ui_set_cancelled, ///< ui: see set_cancelled() - - ui_test_cancelled, ///< ui: see user_cancelled() - - ui_ask_buttons, ///< ui: see ask_yn() and ask_buttons() - - ui_ask_file, ///< ui: see ask_file() - - ui_ask_form, ///< ui: see \ref FORM_C - - ui_ask_text, ///< ui: see ask_text() - - ui_ask_str, ///< ui: see ask_str() - - ui_ask_addr, ///< ui: see ask_addr() - - ui_ask_seg, ///< ui: see ask_seg() - - ui_ask_long, ///< ui: see ask_long() - - ui_add_idckey, ///< ui: see add_idc_hotkey() - -/// \defgroup IDCHK_ IDC hotkey error codes -/// return values for add_idc_hotkey() -//@{ -#define IDCHK_OK 0 ///< ok -#define IDCHK_ARG -1 ///< bad argument(s) -#define IDCHK_KEY -2 ///< bad hotkey name -#define IDCHK_MAX -3 ///< too many IDC hotkeys -//@} - - ui_del_idckey, ///< ui: see ui_del_idckey() - - ui_analyzer_options, ///< ui: see analyzer_options() - - ui_load_file, ///< ui: see ui_load_new_file() - - ui_run_dbg, ///< ui: see ui_run_debugger() - - ui_get_cursor, ///< ui: see get_cursor() - - ui_get_curline, ///< ui: see get_curline() - - ui_copywarn, ///< ui: see display_copyright_warning() - - ui_noabort, ///< ui: Disable 'abort' menu item - the database was not compressed. - ///< \param none - ///< \return void - - ui_lock_range_refresh,///< ui: Lock the ui_range refreshes. - ///< The ranges will not be refreshed until the corresponding - ///< ::ui_unlock_range_refresh is issued. - ///< \param none - ///< \return void - - ui_unlock_range_refresh,///< ui: Unlock the ::ui_range refreshes. - ///< If the number of locks is back to zero, then refresh the ranges. - ///< \param none - ///< \return void - - ui_genfile_callback, ///< cb: handle html generation. - ///< \param html_header_cb_t ** - ///< \param html_footer_cb_t ** - ///< \param html_line_cb_t ** - ///< \return void - - ui_open_url, ///< ui: see open_url() - - ui_hexdumpea, ///< ui: Return the current address in a hex view. - ///< \param result (::ea_t *) - ///< \param hexdump_num (int) - ///< \return void - - ui_get_key_code, ///< ui: see get_key_code() - - ui_setup_plugins_menu,///< ui: setup plugins submenu - ///< \param none - ///< \return void - - ui_get_kernel_version,///< ui: see get_kernel_version() - - ui_is_idaq, ///< ui: see is_idaq() - - ui_refresh_navband, ///< ui: see refresh_navband() - - ui_debugger_menu_change, ///< cb: debugger menu modification detected - ///< \param enable (bool) - ///< true: debugger menu has been added, or a different debugger has been selected - ///< false: debugger menu will be removed (user switched to "No debugger") - ///< \return void - - ui_get_curplace, ///< ui: see get_custom_viewer_place(). See also ui_get_custom_viewer_location - - ui_obsolete_display_widget, - ui_close_widget, ///< ui: see close_widget() - -/// \defgroup WIDGET_CLOSE Form close flags -/// passed as options to close_widget() -//@{ -#define WCLS_SAVE 0x1 ///< save state in desktop config -#define WCLS_NO_CONTEXT 0x2 ///< don't change the current context (useful for toolbars) -#define WCLS_DONT_SAVE_SIZE 0x4 ///< don't save size of the window -#define WCLS_DELETE_LATER 0x8 ///< assign the deletion of the widget to the UI loop ///< \return void -#define WCLS_CLOSE_LATER WCLS_DELETE_LATER -//@} - - ui_activate_widget, ///< ui: see activate_widget() - - ui_find_widget, ///< ui: see find_widget() - - ui_get_current_widget, - ///< ui: see get_current_widget() - - ui_widget_visible, ///< TWidget is displayed on the screen. - ///< Use this event to populate the window with controls - ///< \param widget (TWidget *) - ///< \return void - - ui_widget_closing, ///< TWidget is about to close. - ///< This event precedes ui_widget_invisible. Use this - ///< to perform some possible actions relevant to - ///< the lifecycle of this widget - ///< \param widget (TWidget *) - ///< \return void - - ui_widget_invisible, ///< TWidget is being closed. - ///< Use this event to destroy the window controls - ///< \param widget (TWidget *) - ///< \return void - - ui_get_ea_hint, ///< cb: ui wants to display a simple hint for an address. - ///< Use this event to generate a custom hint - ///< See also more generic ::ui_get_item_hint - ///< \param buf (::qstring *) - ///< \param ea (::ea_t) - ///< \return true if generated a hint - - ui_get_item_hint, ///< cb: ui wants to display multiline hint for an item. - ///< See also more generic ::ui_get_custom_viewer_hint - ///< \param[out] hint (::qstring *) the output string - ///< \param ea (ea_t) or item id like a structure or enum member - ///< \param max_lines (int) maximal number of lines - ///< \param[out] important_lines (int *) number of important lines. if zero, output is ignored - ///< \return true if generated a hint - - ui_refresh_custom_viewer, - ///< ui: see refresh_custom_viewer() - - ui_destroy_custom_viewer, - ///< ui: see destroy_custom_viewer() - - ui_jump_in_custom_viewer, - ///< ui: see jumpto() - - ui_get_custom_viewer_curline, - ///< ui: see get_custom_viewer_curline() - - ui_get_current_viewer,///< ui: see get_current_viewer() - - ui_is_idaview, ///< ui: see is_idaview() - - ui_get_custom_viewer_hint, - ///< cb: ui wants to display a hint for a viewer (idaview or custom). - ///< If the REG_HINTS_MARKER sequence is found in the - ///< returned hints string, it will be replaced with the - ///< contents of the "regular" hints. - ///< If the SRCDBG_HINTS_MARKER sequence is found in the - ///< returned hints string, it will be replaced with the - ///< contents of the source-level debugger-generated hints. - ///< The following keywords might appear at the beginning of the - ///< returned hints: - ///< HIGHLIGHT text\n - ///< where text will be highlighted - ///< CAPTION caption\n - ///< caption for the hint widget - ///< \param[out] hint (::qstring *) the output string - ///< \param viewer (TWidget*) viewer - ///< \param place (::place_t *) current position in the viewer - ///< \param[out] important_lines (int *) number of important lines. - ///< if zero, the result is ignored - ///< \return true if generated a hint - - ui_set_custom_viewer_range, - ///< ui: set_custom_viewer_range() - - ui_database_inited, ///< cb: database initialization has completed. - ///< the kernel is about to run idc scripts - ///< \param is_new_database (int) - ///< \param idc_script (const char *) - may be NULL - ///< \return void - ///< See also ui_initing_database. - ///< This event is called for both new and old databases. - - ui_ready_to_run, ///< cb: all UI elements have been initialized. - ///< Automatic plugins may hook to this event to - ///< perform their tasks. - ///< \param none - ///< \return void - - ui_set_custom_viewer_handler, - ///< ui: see set_custom_viewer_handler(). - ///< also see other examples in \ref ui_scvh_funcs - - ui_refresh_chooser, ///< ui: see refresh_chooser() - - ui_open_builtin, ///< ui: open a window of a built-in type. see \ref ui_open_builtin_funcs - - ui_preprocess_action, ///< cb: ida ui is about to handle a user action. - ///< \param name (const char *) ui action name. - ///< these names can be looked up in ida[tg]ui.cfg - ///< \retval 0 ok - ///< \retval nonzero a plugin has handled the command - - ui_postprocess_action,///< cb: an ida ui action has been handled - - ui_set_custom_viewer_mode, - ///< ui: switch between graph/text modes. - ///< \param custom_viewer (TWidget *) - ///< \param graph_view (bool) - ///< \param silent (bool) - ///< \return bool success - - ui_gen_disasm_text, ///< ui: see gen_disasm_text() - - ui_gen_idanode_text, ///< cb: generate disassembly text for a node. - ///< Plugins may intercept this event and provide - ///< custom text for an IDA graph node - ///< They may use gen_disasm_text() for that. - ///< \param text (text_t *) - ///< \param fc (qflow_chart_t *) - ///< \param node (int) - ///< \return bool text_has_been_generated - - ui_install_cli, ///< ui: see: - ///< install_command_interpreter(), - ///< remove_command_interpreter() - - ui_execute_sync, ///< ui: see execute_sync() - - ui_get_chooser_obj, ///< ui: see get_chooser_obj() - - ui_enable_chooser_item_attrs, - ///< ui: see enable_chooser_item_attrs() - - ui_get_chooser_item_attrs, - ///< cb: get item-specific attributes for a chooser. - ///< This callback is generated only after enable_chooser_attrs() - ///< \param chooser (const ::chooser_base_t *) - ///< \param n (::size_t) - ///< \param attrs (::chooser_item_attrs_t *) - ///< \return void - - ui_set_dock_pos, ///< ui: see set_dock_pos() - -/// \defgroup DP_ Docking positions -/// passed as 'orient' parameter to set_dock_pos() -//@{ -#define DP_LEFT 0x0001 ///< Dock src_form to the left of dest_form -#define DP_TOP 0x0002 ///< Dock src_form above dest_form -#define DP_RIGHT 0x0004 ///< Dock src_form to the right of dest_form -#define DP_BOTTOM 0x0008 ///< Dock src_form below dest_form -#define DP_INSIDE 0x0010 ///< Create a new tab bar with both src_form and dest_form -#define DP_TAB 0x0040 ///< Place src_form into a tab next to dest_form, - ///< if dest_form is in a tab bar - ///< (otherwise the same as #DP_INSIDE) -#define DP_BEFORE 0x0020 ///< place src_form before dst_form in the tab bar instead of after - ///< used with #DP_INSIDE. -#define DP_FLOATING 0x0080 ///< Make src_form floating -//@} - - ui_get_opnum, ///< ui: see get_opnum() - - ui_install_custom_datatype_menu, - ///< ui: install/remove custom data type menu item. - ///< \param dtid (int) data type id - ///< \param install (bool) - ///< \return success - - ui_install_custom_optype_menu, - ///< ui: install/remove custom operand type menu item. - ///< \param fid (int) format id - ///< \param install (bool) - ///< \return success - - ui_get_range_marker, ///< ui: Get pointer to function. - ///< see mark_range_for_refresh(ea_t, asize_t). - ///< This function will be called by the kernel when the - ///< database is changed - ///< \param none - ///< \return vptr: (idaapi*marker)(ea_t ea, asize_t) or NULL - - ui_lookup_key_code, ///< ui: see lookup_key_code() - - ui_load_custom_icon_file, - ///< ui: see load_custom_icon(const char *) - - ui_load_custom_icon, ///< ui: see load_custom_icon(const void *, unsigned int, const char *) - - ui_free_custom_icon, ///< ui: see free_custom_icon() - - ui_process_action, ///< ui: see process_ui_action() - - ui_create_code_viewer,///< ui: see create_code_viewer() - -/// \defgroup CDVF_ Code viewer flags -/// passed as 'flags' parameter to create_code_viewer() -//@{ -#define CDVF_NOLINES 0x0001 ///< don't show line numbers -#define CDVF_LINEICONS 0x0002 ///< icons can be drawn over the line control -#define CDVF_STATUSBAR 0x0004 ///< keep the status bar in the custom viewer -//@} - - ui_addons, ///< ui: see \ref ui_addons_funcs - - ui_execute_ui_requests, - ///< ui: see execute_ui_requests(ui_request_t, ...) - - ui_execute_ui_requests_list, - ///< ui: see execute_ui_requests(ui_requests_t) - - ui_register_timer, ///< ui: see register_timer() - - ui_unregister_timer, ///< ui: see unregister_timer() - - ui_take_database_snapshot, - ///< ui: see take_database_snapshot() - - ui_restore_database_snapshot, - ///< ui: see restore_database_snapshot() - - ui_set_code_viewer_line_handlers, - ///< ui: see set_code_viewer_line_handlers() - - ui_refresh_custom_code_viewer, - ///< ui: Refresh custom code viewer. - ///< \param TWidget *code_viewer - ///< \return void - - ui_create_source_viewer, - ///< ui: Create new source viewer. - ///< \param top_tl (TWidget **) toplevel widget of created source viewer (can be NULL) - ///< \param parent (TWidget *) - ///< \param custview (TWidget *) - ///< \param path (const char *) - ///< \param lines (strvec_t *) - ///< \param lnnum (int) - ///< \param colnum (int) - ///< \param flags (int) (\ref SVF_) - ///< \return source_view_t * - -/// \defgroup SVF_ Source viewer creation flags -/// passed as 'flags' parameter to callback for ::ui_create_source_viewer -//@{ -#define SVF_COPY_LINES 0x0000 ///< keep a local copy of '*lines' -#define SVF_LINES_BYPTR 0x0001 ///< remember the 'lines' ptr. do not make a copy of '*lines' -//@} - - ui_get_tab_size, ///< ui: see get_tab_size() - - ui_repaint_qwidget, ///< ui: see repaint_custom_viewer() - - ui_custom_viewer_set_userdata, - ///< ui: Change ::place_t user data for a custom view. - ///< \param custom_viewer (TWidget *) - ///< \param user_data (void *) - ///< \return old user_data - - ui_jumpto, ///< ui: see jumpto(ea_t, int, int) - - ui_cancel_exec_request, - ///< ui: see cancel_exec_request() - - ui_open_form, ///< ui: see vopen_form() - - ui_unrecognized_config_directive, - ///< ui: Possibly handle an extra config directive, - ///< passed through '-d' or '-D'. - ///< \param directive (const char *) The config directive - ///< \return char * - one of \ref IDPOPT_RET - ///< See also register_cfgopts, which is better - - ui_get_output_cursor, ///< ui: see get_output_cursor() - - ui_get_output_curline,///< ui: see get_output_curline() - - ui_get_output_selected_text, - ///< ui: see get_output_selected_text() - - ui_get_renderer_type, ///< ui: see get_view_renderer_type() - - ui_set_renderer_type, ///< ui: see set_view_renderer_type() - - ui_get_viewer_user_data, - ///< ui: see get_viewer_user_data() - - ui_get_viewer_place_type, - ///< ui: see get_viewer_place_type() - - ui_ea_viewer_history_push_and_jump, - ///< ui: see ea_viewer_history_push_and_jump() - - ui_ea_viewer_history_info, - ///< ui: see get_ea_viewer_history_info() - - ui_register_action, - ///< ui: see register_action() - - ui_unregister_action, - ///< ui: see unregister_action() - - ui_attach_action_to_menu, - ///< ui: see attach_action_to_menu() - - ui_detach_action_from_menu, - ///< ui: see detach_action_from_menu() - - ui_attach_action_to_popup, - ///< ui: see attach_action_to_popup() - - ui_detach_action_from_popup, - ///< ui: see detach_action_from_popup() - - ui_attach_dynamic_action_to_popup, - ///< ui: see create attach_dynamic_action_to_popup() - - ui_attach_action_to_toolbar, - ///< ui: see attach_action_to_toolbar() - - ui_detach_action_from_toolbar, - ///< ui: see detach_action_from_toolbar() - - ui_updating_actions, ///< cb: IDA is about to update all actions. If your plugin - ///< needs to perform expensive operations more than once - ///< (e.g., once per action it registers), you should do them - ///< only once, right away. - ///< \param ctx (::action_update_ctx_t *) - ///< \return void - - ui_updated_actions, ///< cb: IDA is done updating actions. - ///< \param none - ///< \return void - - ui_populating_widget_popup, - ///< cb: IDA is populating the context menu for a widget. - ///< This is your chance to attach_action_to_popup(). - ///< - ///< Have a look at ui_finish_populating_widget_popup, - ///< if you want to augment the - ///< context menu with your own actions after the menu - ///< has had a chance to be properly populated by the - ///< owning component or plugin (which typically does it - ///< on ui_populating_widget_popup.) - ///< - ///< \param widget (TWidget *) - ///< \param popup_handle (TPopupMenu *) - ///< \param ctx (const action_activation_ctx_t *) - ///< \return void - ///< - ///< ui: see ui_finish_populating_widget_popup - - ui_finish_populating_widget_popup, - ///< cb: IDA is about to be done populating the - ///< context menu for a widget. - ///< This is your chance to attach_action_to_popup(). - ///< - ///< \param widget (TWidget *) - ///< \param popup_handle (TPopupMenu *) - ///< \param ctx (const action_activation_ctx_t *) - ///< \return void - ///< - ///< ui: see ui_populating_widget_popup - - ui_update_action_attr, - ///< ui: see \ref ui_uaa_funcs - - ui_get_action_attr, ///< ui: see \ref ui_gaa_funcs - - ui_plugin_loaded, ///< cb: The plugin was loaded in memory. - ///< \param plugin_info (const ::plugin_info_t *) - - ui_plugin_unloading, ///< cb: The plugin is about to be unloaded - ///< \param plugin_info (const ::plugin_info_t *) - - ui_get_widget_type, ///< ui: see get_widget_type() - - ui_current_widget_changed, - ///< cb: The currently-active TWidget changed. - ///< \param widget (TWidget *) - ///< \param prev_widget (TWidget *) - ///< \return void - - ui_get_widget_title, ///< ui: see get_widget_title() - - ui_get_user_strlist_options, - ///< ui: see get_user_strlist_options() - - ui_create_custom_viewer, - ///< ui: see create_viewer() - - // custom viewer navigation flags -#define CVNF_LAZY (1 << 0) ///< try and move the cursor to a line displaying the - ///< place_t if possible. This might disregard the Y - ///< position in case of success -#define CVNF_JUMP (1 << 1) ///< push the current position in this viewer's - ///< lochist_t before going to the new location -#define CVNF_ACT (1 << 2) ///< activate (i.e., switch to) the viewer. - ///< Activation is performed before the new - ///< lochist_entry_t instance is actually copied - ///< to the viewer's lochist_t (otherwise, if the - ///< viewer was invisible its on_location_changed() - ///< handler wouldn't be called.) - ui_custom_viewer_jump,///< ui: set the current location, and have the viewer display it - ///< \param v (TWidget *) - ///< \param loc (const lochist_entry_t *) - ///< \param flags (uint32) or'ed combination of CVNF_* values - ///< \return success - - ui_set_custom_viewer_handlers, - ///< ui: see set_custom_viewer_handlers() - - ui_get_registered_actions, - ///< ui: see get_registered_actions() - - ui_create_toolbar, ///< ui: see create_toolbar() - ui_delete_toolbar, ///< ui: see delete_toolbar() - ui_create_menu, ///< ui: see create_menu() - ui_delete_menu, ///< ui: see delete_menu() - ui_obsolete_set_nav_colorizer, - ui_get_chooser_data, ///< ui: see get_chooser_data() - ui_get_highlight, ///< ui: see get_highlight() - ui_set_highlight, ///< ui: see set_highlight() - - ui_set_mappings, ///< ui: Show current memory mappings - ///< and allow the user to change them. - ui_create_empty_widget, - ///< ui: see create_empty_widget() - - ui_msg_clear, ///< ui: see msg_clear() - ui_msg_save, ///< ui: see msg_save() - ui_msg_get_lines, ///< ui: see msg_get_lines() - - ui_chooser_default_enter, - ///< ui: jump to the address returned by get_ea() callback in the - ///< case of the non-modal choosers - ///< \param chooser (const ::chooser_base_t *) - ///< \param n/sel (::size_t *) for chooser_t - ///< (::sizevec_t *) for chooser_multi_t - ///< \return int chooser_t::cbres_t - - ui_screen_ea_changed, - ///< cb: The "current address" changed - ///< \param ea (ea_t) - ///< \param prev_ea (ea_t) - ///< \return void - - ui_get_active_modal_widget, - ///< ui: see get_active_modal_widget() - - ui_navband_pixel, ///< ui: see get_navband_pixel - ui_navband_ea, ///< ui: see get_navband_ea - ui_get_window_id, ///< ui: set get_window_id (GUI only) - - ui_create_desktop_widget, - ///< cb: create a widget, to be placed in the widget tree (at desktop-creation time.) - ///< \param title (const char *) - ///< \param cfg (const jobj_t *) - ///< \return TWidget * the created widget, or null - - ui_strchoose, ///< ui: undocumented - - - ui_set_nav_colorizer, ///< ui: see set_nav_colorizer() - ui_display_widget, ///< ui: see display_widget() - -/// \defgroup WIDGET_OPEN Widget open flags -/// passed as options to open_form() and display_widget() -//@{ -// -#define WOPN_RESTORE 0x00000004u ///< if the widget was the only widget in a floating area the - ///< last time it was closed, it will be restored as - ///< floating, with the same position+size as before -#define WOPN_PERSIST 0x00000040u ///< widget will remain available when starting or stopping debugger sessions -#define WOPN_CLOSED_BY_ESC 0x00000080u ///< override idagui.cfg:CLOSED_BY_ESC: esc will close -#define WOPN_NOT_CLOSED_BY_ESC 0x00000100u ///< override idagui.cfg:CLOSED_BY_ESC: esc will not close -#define WOPN_SZHINT 0x00000200u ///< when floating or in a splitter (i.e., not tabbed), - ///< use the widget's size hint to determine the best - ///< geometry (Qt only) -#define WOPN_DP_MASK 0x0FFF0000u -#define WOPN_DP_SHIFT 16 -#define WOPN_DP_LEFT (DP_LEFT << WOPN_DP_SHIFT) - ///< Dock widget to the left of dest_ctrl -#define WOPN_DP_TOP (DP_TOP << WOPN_DP_SHIFT) - ///< Dock widget above dest_ctrl -#define WOPN_DP_RIGHT (DP_RIGHT << WOPN_DP_SHIFT) - ///< Dock widget to the right of dest_ctrl -#define WOPN_DP_BOTTOM (DP_BOTTOM << WOPN_DP_SHIFT) - ///< Dock widget below dest_ctrl -#define WOPN_DP_INSIDE (DP_INSIDE << WOPN_DP_SHIFT) - ///< Create a new tab bar with both widget and dest_ctrl -#define WOPN_DP_TAB (DP_TAB << WOPN_DP_SHIFT) - ///< Place widget into a tab next to dest_ctrl, - ///< if dest_ctrl is in a tab bar - ///< (otherwise the same as #WOPN_DP_INSIDE) -#define WOPN_DP_BEFORE (DP_BEFORE << WOPN_DP_SHIFT) - ///< place widget before dst_form in the tab bar instead of after - ///< used with #WOPN_DP_INSIDE and #WOPN_DP_TAB -#define WOPN_DP_FLOATING (DP_FLOATING << WOPN_DP_SHIFT) - ///< Make widget floating -#define WOPN_DP_INSIDE_BEFORE (WOPN_DP_INSIDE | WOPN_DP_BEFORE) -#define WOPN_DP_TAB_BEFORE (WOPN_DP_TAB | WOPN_DP_BEFORE) -#define WOPN_GET_DP(v) (((v) & WOPN_DP_MASK) >> WOPN_DP_SHIFT) -//@} - - ui_get_lines_rendering_info, - ///< cb: get lines rendering information - ///< \param out (lines_rendering_output_t *) - ///< \param widget (const TWidget *) - ///< \param info (const lines_rendering_input_t *) - ///< \return void - - ui_sync_sources, - ///< ui: [un]synchronize sources - ///< \param what (const sync_source_t *) - ///< \param with (const sync_source_t *) - ///< \param sync (bool) - ///< \return success - - ui_get_widget_config, ///< cb: retrieve the widget configuration (it will be passed - ///< back at ui_create_desktop_widget-, and ui_set_widget_config-time) - ///< \param widget (const TWidget *) - ///< \param cfg (jobj_t *) - ///< \return void - - ui_set_widget_config, ///< cb: set the widget configuration - ///< \param widget (const TWidget *) - ///< \param cfg (const jobj_t *) - ///< \return void - - ui_get_custom_viewer_location, - ///< ui: see get_custom_viewer_location() - ///< \param out (lochist_entry_t *) - ///< \param custom_viewer (TWidget *) - ///< \param mouse (bool) - - ui_initing_database, ///< cb: database initialization has started. - ///< \return void - ///< See also ui_database_inited. - ///< This event is called for both new and old databases. - - ui_destroying_procmod, ///< cb: The processor module is about to be destroyed - ///< \param procmod (const ::procmod_t *) - - ui_destroying_plugmod, ///< cb: The plugin object is about to be destroyed - ///< \param plugmod (const ::plugmod_t *) - - ui_update_file_history, ///< ui: manipulate the file history - ///< \param add_path (const char *) - ///< \param del_path (const char *) - - ui_cancel_thread_exec_requests, - ///< ui: see cancel_thread_exec_requests() - - ui_get_synced_group, - ///< ui: see get_synced_group() - - ui_show_rename_dialog, ///< ui: undocumented - ///< Rename address dialog -] - ///< \param ea (ea_t) - ///< \param ndialog (int) dialog number \ref RENADDR_DIALOGS - ///< \param[inout] hr_flags (ushort *) additional flags - ///< \return success -/// \defgroup RENADDR_DIALOGS Dialogs for "Rename address" -//@{ -// -#define RENADDR_IDA 0 ///< dialog for "IDA View" -#define RENADDR_HR 1 ///< dialog for "Pseudocode" - ///< additional flags: - ///< 0x01 Library function - ///< 0x02 Mark as decompiled -//@} -// -[ - ui_last, ///< the last notification code - - ui_dbg_begin = 1000, ///< debugger callgates. should not be used directly, see dbg.hpp for details - ui_dbg_run_requests = ui_dbg_begin, - ui_dbg_get_running_request, - ui_dbg_get_running_notification, - ui_dbg_clear_requests_queue, - ui_dbg_get_process_state, - ui_dbg_start_process, - ui_dbg_request_start_process, - ui_dbg_suspend_process, - ui_dbg_request_suspend_process, - ui_dbg_continue_process, - ui_dbg_request_continue_process, - ui_dbg_exit_process, - ui_dbg_request_exit_process, - ui_dbg_get_thread_qty, - ui_dbg_getn_thread, - ui_dbg_select_thread, - ui_dbg_request_select_thread, - ui_dbg_step_into, - ui_dbg_request_step_into, - ui_dbg_step_over, - ui_dbg_request_step_over, - ui_dbg_run_to, - ui_dbg_request_run_to, - ui_dbg_step_until_ret, - ui_dbg_request_step_until_ret, - ui_dbg_get_bpt_qty, - ui_dbg_add_oldbpt, - ui_dbg_request_add_oldbpt, - ui_dbg_del_oldbpt, - ui_dbg_request_del_oldbpt, - ui_dbg_enable_oldbpt, - ui_dbg_request_enable_oldbpt, - ui_dbg_set_trace_size, - ui_dbg_clear_trace, - ui_dbg_request_clear_trace, - ui_dbg_is_step_trace_enabled, - ui_dbg_enable_step_trace, - ui_dbg_request_enable_step_trace, - ui_dbg_get_step_trace_options, - ui_dbg_set_step_trace_options, - ui_dbg_request_set_step_trace_options, - ui_dbg_is_insn_trace_enabled, - ui_dbg_enable_insn_trace, - ui_dbg_request_enable_insn_trace, - ui_dbg_get_insn_trace_options, - ui_dbg_set_insn_trace_options, - ui_dbg_request_set_insn_trace_options, - ui_dbg_is_func_trace_enabled, - ui_dbg_enable_func_trace, - ui_dbg_request_enable_func_trace, - ui_dbg_get_func_trace_options, - ui_dbg_set_func_trace_options, - ui_dbg_request_set_func_trace_options, - ui_dbg_get_tev_qty, - ui_dbg_get_tev_info, - ui_dbg_get_call_tev_callee, - ui_dbg_get_ret_tev_return, - ui_dbg_get_bpt_tev_ea, - ui_dbg_get_reg_value_type, - ui_dbg_get_processes, - ui_dbg_attach_process, - ui_dbg_request_attach_process, - ui_dbg_detach_process, - ui_dbg_request_detach_process, - ui_dbg_get_first_module, - ui_dbg_get_next_module, - ui_dbg_bring_to_front, - ui_dbg_get_current_thread, - ui_dbg_wait_for_next_event, - ui_dbg_get_debug_event, - ui_dbg_set_debugger_options, - ui_dbg_set_remote_debugger, - ui_dbg_load_debugger, - ui_dbg_retrieve_exceptions, - ui_dbg_store_exceptions, - ui_dbg_define_exception, - ui_dbg_suspend_thread, - ui_dbg_request_suspend_thread, - ui_dbg_resume_thread, - ui_dbg_request_resume_thread, - ui_dbg_get_process_options, - ui_dbg_check_bpt, - ui_dbg_set_process_state, - ui_dbg_get_manual_regions, - ui_dbg_set_manual_regions, - ui_dbg_enable_manual_regions, - ui_dbg_set_process_options, - ui_dbg_is_busy, - ui_dbg_hide_all_bpts, - ui_dbg_edit_manual_regions, - ui_dbg_get_sp_val, - ui_dbg_get_ip_val, - ui_dbg_get_reg_val, - ui_dbg_set_reg_val, - ui_dbg_request_set_reg_val, - ui_dbg_get_insn_tev_reg_val, - ui_dbg_get_insn_tev_reg_result, - ui_dbg_register_provider, - ui_dbg_unregister_provider, - ui_dbg_handle_debug_event, - ui_dbg_add_vmod, - ui_dbg_del_vmod, - ui_dbg_compare_bpt_locs, - ui_dbg_save_bpts, - ui_dbg_set_bptloc_string, - ui_dbg_get_bptloc_string, - ui_dbg_internal_appcall, - ui_dbg_internal_cleanup_appcall, - ui_dbg_internal_get_sreg_base, - ui_dbg_internal_ioctl, - ui_dbg_read_memory, - ui_dbg_write_memory, - ui_dbg_read_registers, - ui_dbg_write_register, - ui_dbg_get_memory_info, - ui_dbg_get_event_cond, - ui_dbg_set_event_cond, - ui_dbg_enable_bpt, - ui_dbg_request_enable_bpt, - ui_dbg_del_bpt, - ui_dbg_request_del_bpt, - ui_dbg_map_source_path, - ui_dbg_map_source_file_path, - ui_dbg_modify_source_paths, - ui_dbg_is_bblk_trace_enabled, - ui_dbg_enable_bblk_trace, - ui_dbg_request_enable_bblk_trace, - ui_dbg_get_bblk_trace_options, - ui_dbg_set_bblk_trace_options, - ui_dbg_request_set_bblk_trace_options, - // trace management - ui_dbg_load_trace_file, - ui_dbg_save_trace_file, - ui_dbg_is_valid_trace_file, - ui_dbg_set_trace_file_desc, - ui_dbg_get_trace_file_desc, - ui_dbg_choose_trace_file, - ui_dbg_diff_trace_file, - ui_dbg_graph_trace, - ui_dbg_get_tev_memory_info, - ui_dbg_get_tev_event, - ui_dbg_get_insn_tev_reg_mem, - // breakpoint management (new codes were introduced in v6.3) - ui_dbg_getn_bpt, - ui_dbg_get_bpt, - ui_dbg_find_bpt, - ui_dbg_add_bpt, - ui_dbg_request_add_bpt, - ui_dbg_update_bpt, - ui_dbg_for_all_bpts, - ui_dbg_get_tev_ea, - ui_dbg_get_tev_type, - ui_dbg_get_tev_tid, - ui_dbg_get_trace_base_address, - // calluis for creating traces from scratch (added in 6.4) - ui_dbg_set_trace_base_address, - ui_dbg_add_tev, - ui_dbg_add_insn_tev, - ui_dbg_add_call_tev, - ui_dbg_add_ret_tev, - ui_dbg_add_bpt_tev, - ui_dbg_add_debug_event, - ui_dbg_add_thread, - ui_dbg_del_thread, - ui_dbg_add_many_tevs, - ui_dbg_set_bpt_group, - ui_dbg_set_highlight_trace_options, - ui_dbg_set_trace_platform, - ui_dbg_get_trace_platform, - // added in 6.6 - ui_dbg_internal_get_elang, - ui_dbg_internal_set_elang, - - // added in 6.7 - ui_dbg_load_dbg_dbginfo, - ui_dbg_set_resume_mode, - ui_dbg_request_set_resume_mode, - ui_dbg_set_bptloc_group, - ui_dbg_list_bptgrps, - ui_dbg_rename_bptgrp, - ui_dbg_del_bptgrp, - ui_dbg_get_grp_bpts, - ui_dbg_get_bpt_group, - ui_dbg_change_bptlocs, - - // added in 7.1 - ui_dbg_collect_stack_trace, - ui_dbg_get_module_info, - - // source-level debugging - ui_dbg_get_srcinfo_provider, - ui_dbg_get_global_var, - ui_dbg_get_local_var, - ui_dbg_get_local_vars, - ui_dbg_add_path_mapping, - ui_dbg_get_current_source_file, - ui_dbg_get_current_source_line, - - ui_dbg_srcdbg_step_into, - ui_dbg_srcdbg_request_step_into, - ui_dbg_srcdbg_step_over, - ui_dbg_srcdbg_request_step_over, - ui_dbg_srcdbg_step_until_ret, - ui_dbg_srcdbg_request_step_until_ret, - - ui_dbg_getn_thread_name, - ui_dbg_bin_search, - - ui_dbg_get_insn_tev_reg_val_i, - ui_dbg_get_insn_tev_reg_result_i, - ui_dbg_get_reg_val_i, - ui_dbg_set_reg_val_i, - - ui_dbg_get_reg_info, - - ui_dbg_set_trace_dynamic_register_set, - ui_dbg_get_trace_dynamic_register_set, - - ui_dbg_end, - - // Debugging notifications -#ifdef _DEBUG - debug_obsolete_assert_thread_waitready = ui_dbg_end -#endif -}; - - -//-------------------------------------------------------------------------- - - -/// Pointer to the user-interface dispatcher function. -/// This pointer is in the kernel - -idaman callui_t ida_export_data (idaapi*callui)(ui_notification_t what,...); - - -/// After calling init_kernel() the ui must call this function. -/// It will open the database specified in the command line. -/// If the database did not exist, a new database will be created and -/// the input file will be loaded. -/// \return 0-ok, otherwise an exit code - -idaman int ida_export init_database(int argc, const char *const *argv, int *newfile); - - -/// The database termination function. -/// This function should be called to close the database. - -idaman void ida_export term_database(void); - - -/// See error() - -idaman NORETURN AS_PRINTF(1, 0) void ida_export verror(const char *format, va_list va); - - -/// See show_hex() - -idaman AS_PRINTF(3, 0) void ida_export vshow_hex( - const void *dataptr, - size_t len, - const char *format, - va_list va); - - -/// See show_hex_file() - -idaman AS_PRINTF(4, 0) void ida_export vshow_hex_file( - linput_t *li, - int64 pos, - size_t count, - const char *format, - va_list va); - - -#endif // SWIG - -/// Get IDA kernel version (in a string like "5.1"). - -inline ssize_t get_kernel_version(char *buf, size_t bufsize) -{ - return callui(ui_get_kernel_version, buf, bufsize).ssize; -} - -//-------------------------------------------------------------------------- -// K E R N E L S E R V I C E S F O R U I -//-------------------------------------------------------------------------- -// -// Generating text for the disassembly, enum, and structure windows. - -/*! \brief Denotes a displayed line. - - (location_t would be a better name but it is too late to rename it now) - - An object may be displayed on one or more lines. All lines of an object are - generated at once and kept in a linearray_t class. - - place_t is an abstract class, another class must be derived from it. \n - Currently the following classes are used in IDA: - - idaplace_t - disassembly view \n - enumplace_t - enum view \n - structplace_t - structure view - - Example (idaplace_t): \verbatim - - 004015AC - 004015AC loc_4015AC: ; CODE XREF: sub_4014B8+C5j - 004015AC xor eax, eax \endverbatim - - The first line is denoted by idaplace_t with ea=4015AC, lnnum=0 \n - The second line is denoted by idaplace_t with ea=4015AC, lnnum=1 \n - The third line is denoted by idaplace_t with ea=4015AC, lnnum=2 - - NB: the place_t class may change in the future, do not rely on it -*/ -class place_t -{ -public: - int lnnum; ///< Number of line within the current object - place_t(void) {} ///< Constructor - place_t(int ln) : lnnum(ln) {} ///< Constructor - DEFINE_MEMORY_ALLOCATION_FUNCS() - - /// Generate a short description of the location. - /// This description is used on the status bar. - /// \param out_buf the output buffer - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - virtual void idaapi print(qstring *out_buf, void *ud) const = 0; - - /// Map the location to a number. - /// This mapping is used to draw the vertical scrollbar. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - virtual uval_t idaapi touval(void *ud) const = 0; - - /// Clone the location. - /// \return a pointer to a copy of the current location in dynamic memory - virtual place_t *idaapi clone(void) const = 0; - - /// Copy the specified location object to the current object - virtual void idaapi copyfrom(const place_t *from) = 0; - - /// Map a number to a location. - /// When the user clicks on the scrollbar and drags it, we need to determine - /// the location corresponding to the new scrollbar position. This function - /// is used to determine it. It builds a location object for the specified 'x' - /// and returns a pointer to it. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - /// \param x number to map - /// \param lnnum line number to initialize 'lnnum' - /// \return a freshly allocated object. See also PCF_MAKEPLACE_ALLOCATES - virtual place_t *idaapi makeplace(void *ud, uval_t x, int lnnum) const= 0; - - /// Deprecated. Please consider compare2(const place_t *, void *) instead. - virtual int idaapi compare(const place_t *t2) const = 0; - - /// Adjust the current location to point to a displayable object. - /// This function validates the location and makes sure that it points to - /// an existing object. For example, if the location points to the middle - /// of an instruction, it will be adjusted to point to the beginning of the - /// instruction. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - virtual void idaapi adjust(void *ud) = 0; - - /// Move to the previous displayable location. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - /// \return success - virtual bool idaapi prev(void *ud) = 0; - - /// Move to the next displayable location. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - /// \return success - virtual bool idaapi next(void *ud) = 0; - - /// Are we at the first displayable object?. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - /// \return true if the current location points to the first displayable object - virtual bool idaapi beginning(void *ud) const = 0; - - /// Are we at the last displayable object?. - /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t - /// \return true if the current location points to the last displayable object - virtual bool idaapi ending(void *ud) const = 0; - - /// Generate text lines for the current location. - /// \param out storage for the lines - /// \param out_deflnnum pointer to the cell that will contain the number of - /// the most 'interesting' generated line - /// \param out_pfx_color pointer to the cell that will contain the line prefix color - /// \param out_bgcolor pointer to the cell that will contain the background color - /// \param ud pointer to user-defined context data. Is supplied by linearray_t - /// \param maxsize the maximum number of lines to generate - /// \return number of generated lines - virtual int idaapi generate( - qstrvec_t *out, - int *out_deflnnum, - color_t *out_pfx_color, - bgcolor_t *out_bgcolor, - void *ud, - int maxsize) const = 0; - - /// Serialize this instance. - /// It is fundamental that all instances of a particular subclass - /// of of place_t occupy the same number of bytes when serialized. - /// \param out buffer to serialize into - virtual void idaapi serialize(bytevec_t *out) const = 0; - - /// De-serialize into this instance. - /// 'pptr' should be incremented by as many bytes as - /// de-serialization consumed. - /// \param pptr pointer to a serialized representation of a place_t of this type. - /// \param end pointer to end of buffer. - /// \return whether de-serialization was successful - virtual bool idaapi deserialize(const uchar **pptr, const uchar *end) = 0; - - /// Get the place's ID (i.e., the value returned by register_place_class()) - /// \return the id - virtual int idaapi id() const = 0; - - /// Get this place type name. - /// All instances of a given class must return the same string. - /// \return the place type name. Please try and pick something that is - /// not too generic, as it might clash w/ other plugins. A good - /// practice is to prefix the class name with the name - /// of your plugin. E.g., "myplugin:srcplace_t". - virtual const char *idaapi name() const = 0; - - /// Map the location to an ea_t. - /// \return the corresponding ea_t, or BADADDR; - virtual ea_t idaapi toea() const { return BADADDR; } - - /// Rebase the place instance - /// \param infos the segments that were moved - /// \return true if place was rebased, false otherwise - virtual bool idaapi rebase(const segm_move_infos_t & /*infos*/ ) { return true; } - - /// Visit this place, possibly 'unhiding' a section of text. - /// If entering that place required some expanding, a place_t - /// should be returned that represents that section, plus some - /// flags for later use by 'leave()'. - /// \param out_flags flags to be used together with the place_t that is - /// returned, in order to restore the section to its - /// original state when leave() is called. - /// \return a place_t corresponding to the beginning of the section - /// of text that had to be expanded. That place_t's leave() will - /// be called with the flags contained in 'out_flags' when the user - /// navigates away from it. - virtual place_t *idaapi enter(uint32 * /*out_flags*/) const { return NULL; } - - /// Leave this place, possibly 'hiding' a section of text that was - /// previously expanded (at enter()-time.) - virtual void idaapi leave(uint32 /*flags*/) const {} - - /// Compare two locations except line numbers (lnnum). - /// This function is used to organize loops. - /// For example, if the user has selected an range, its boundaries are remembered - /// as location objects. Any operation within the selection will have the following - /// look: for ( loc=starting_location; loc < ending_location; loc.next() ) - /// In this loop, the comparison function is used. - /// \param t2 the place to compare this one to. - /// \param ud pointer to user-defined context data. - /// \retval -1 if the current location is less than 't2' - /// \retval 0 if the current location is equal to than 't2' - /// \retval 1 if the current location is greater than 't2' - virtual int idaapi compare2(const place_t *t2, void * /*ud*/) const { return compare(t2); } -}; - -#define DEFAULT_PLACE_LNNUM -1 - -#ifndef SWIG -/// compare places and their lnnums -idaman int ida_export l_compare(const place_t *t1, const place_t *t2); -idaman int ida_export l_compare2(const place_t *t1, const place_t *t2, void *ud); - -//-------------------------------------------------------------------------- -/// Helper to define exported functions for ::place_t implementations -#define define_place_exported_functions(classname) \ -class classname; \ -idaman void ida_export classname ## __print(const classname *, qstring *, void*); \ -idaman uval_t ida_export classname ## __touval(const classname *,void*); \ -idaman place_t * ida_export classname ## __clone(const classname *); \ -idaman void ida_export classname ## __copyfrom(classname *,const place_t*); \ -idaman place_t * ida_export classname ## __makeplace(const classname *,void*,uval_t,int); \ -idaman int ida_export classname ## __compare(const classname *,const place_t*); \ -idaman int ida_export classname ## __compare2(const classname *,const place_t*, void*); \ -idaman void ida_export classname ## __adjust(classname *,void*); \ -idaman bool ida_export classname ## __prev(classname *,void*); \ -idaman bool ida_export classname ## __next(classname *,void*); \ -idaman bool ida_export classname ## __beginning(const classname *,void*); \ -idaman bool ida_export classname ## __ending(const classname *,void*); \ -idaman int ida_export classname ## __generate( \ - const classname *, \ - qstrvec_t*, \ - int*, \ - color_t*, \ - bgcolor_t*, \ - void*, \ - int); \ -idaman void ida_export classname ## __serialize(const classname *, bytevec_t *out); \ -idaman bool ida_export classname ## __deserialize(classname *, const uchar **, const uchar *); \ -idaman int ida_export classname ## __id(const classname *); \ -idaman const char *ida_export classname ## __name(const classname *); \ -idaman ea_t ida_export classname ## __toea(const classname *); \ -idaman place_t * ida_export classname ## __enter(const classname *, uint32 *); \ -idaman void ida_export classname ## __leave(const classname *, uint32); \ -idaman bool ida_export classname ## __rebase(classname *, const segm_move_infos_t &); - - -/// Helper to define virtual functions in ::place_t implementations -#define define_place_virtual_functions(class) \ - virtual void idaapi print(qstring *buf, void *ud) const override \ - { class ## __print(this, buf, ud); } \ - virtual uval_t idaapi touval(void *ud) const override \ - { return class ## __touval(this,ud); } \ - virtual place_t *idaapi clone(void) const override \ - { return class ## __clone(this); } \ - virtual void idaapi copyfrom(const place_t *from) override \ - { class ## __copyfrom(this,from); } \ - virtual place_t *idaapi makeplace( \ - void *ud, \ - uval_t x, \ - int _lnnum) const override \ - { return class ## __makeplace(this,ud,x,_lnnum); } \ - virtual int idaapi compare(const place_t *t2) const override \ - { return class ## __compare(this, t2); } \ - virtual void idaapi adjust(void *ud) override \ - { class ## __adjust(this,ud); } \ - virtual bool idaapi prev(void *ud) override \ - { return class ## __prev(this,ud); } \ - virtual bool idaapi next(void *ud) override \ - { return class ## __next(this,ud); } \ - virtual bool idaapi beginning(void *ud) const override \ - { return class ## __beginning(this,ud); } \ - virtual bool idaapi ending(void *ud) const override \ - { return class ## __ending(this,ud); } \ - virtual int idaapi generate( \ - qstrvec_t *_out, \ - int *_out_lnnum, \ - color_t *_out_pfx_color, \ - bgcolor_t *_out_bg_color, \ - void *_ud, \ - int _max) const override \ - { \ - return class ## __generate( \ - this, _out, _out_lnnum, _out_pfx_color, \ - _out_bg_color, _ud, _max); \ - } \ - virtual void idaapi serialize(bytevec_t *out) const override \ - { class ## __serialize(this, out); } \ - virtual bool idaapi deserialize( \ - const uchar **pptr, \ - const uchar *end) override \ - { return class ## __deserialize(this, pptr, end); } \ - virtual int idaapi id() const override \ - { return class ## __id(this); } \ - virtual const char * idaapi name() const override \ - { return class ## __name(this); } \ - virtual ea_t idaapi toea() const override \ - { return class ## __toea(this); } \ - virtual place_t *idaapi enter(uint32 *out_flags) const override \ - { return class ## __enter(this, out_flags); } \ - virtual void idaapi leave(uint32 flags) const override \ - { return class ## __leave(this, flags); } \ - virtual bool idaapi rebase(const segm_move_infos_t &infos) override \ - { return class ## __rebase(this, infos); } \ - virtual int idaapi compare2(const place_t *t2, void *ud) const override \ - { return class ## __compare2(this, t2, ud); } - -define_place_exported_functions(simpleline_place_t) - - -#endif // SWIG - -//-------------------------------------------------------------------------- - -/*! \defgroup simpleline Simpleline interface - - \brief IDA custom viewer sample. - - It is enough to create an object of ::strvec_t class, put all lines - into it and create a custom ida viewer (::ui_create_custom_viewer). - \code - strvec_t sv; - // fill it with lines... - simpleline_place_t s1; - simpleline_place_t s2(sv.size()-1); - cv = (TWidget *)callui(ui_create_custom_viewer, - "My title", - &s1, - &s2, - &s1, - 0, - &sv).vptr; - \endcode - This will produce a nice colored text view. - Also see the SDK's 'custview' and 'hexview' plugins for more complete examples. -*/ -//@{ - -/// Maintain basic information for a line in a custom view -struct simpleline_t -{ - qstring line; ///< line text - color_t color; ///< line prefix color - bgcolor_t bgcolor; ///< line background color - simpleline_t(void) : color(1), bgcolor(DEFCOLOR) {} ///< Constructor (default colors) - simpleline_t(color_t c, const char *str) : line(str), color(c), bgcolor(DEFCOLOR) {} ///< Constructor - simpleline_t(const char *str) : line(str), color(1), bgcolor(DEFCOLOR) {} ///< Constructor - simpleline_t(const qstring &str) : line(str), color(1), bgcolor(DEFCOLOR) {} ///< Constructor - DEFINE_MEMORY_ALLOCATION_FUNCS() -}; - -/// A collection of simple lines to populate a custom view. -/// This is an example of what you would pass as the 'ud' argument to create_custom_viewer() -typedef qvector strvec_t; - -/// A location in a view populated by a ::strvec_t -class simpleline_place_t : public place_t -{ -public: - uint32 n; ///< line number - simpleline_place_t(void) { n = 0; lnnum = 0; } ///< Constructor - simpleline_place_t(int _n) { n = _n; lnnum = 0; } ///< Constructor - define_place_virtual_functions(simpleline_place_t); -}; -//@} - -//-------------------------------------------------------------------------- -// user defined data for linearray_t: use ptr to result of calc_default_idaplace_flags() -#ifndef SWIG -define_place_exported_functions(idaplace_t) -#endif // SWIG -/// A location in a disassembly view -class idaplace_t : public place_t -{ -public: - ea_t ea; ///< address - idaplace_t(void) {} ///< Constructor - idaplace_t(ea_t x, int ln) : place_t(ln), ea(x) {} ///< Constructor - define_place_virtual_functions(idaplace_t); -}; - -//-------------------------------------------------------------------------- -// user defined data for linearray_t: NULL -#ifndef SWIG -define_place_exported_functions(enumplace_t) -#endif // SWIG -/// A location in an enum view -class enumplace_t : public place_t -{ -public: - size_t idx; ///< enum serial number - bmask_t bmask; ///< enum member bitmask - uval_t value; ///< enum member value - uchar serial; ///< enum member serial number - enumplace_t(void) {} ///< Constructor - enumplace_t(size_t i, bmask_t m, uval_t v, uchar s, int ln) ///< Constructor - : place_t(ln), idx(i), bmask(m), value(v), serial(s) {} - define_place_virtual_functions(enumplace_t); -}; - -//-------------------------------------------------------------------------- -// user defined data for linearray_t: ea_t *pea -// if pea != NULL then the function stack frame is displayed, *pea == function start -// else normal structure list is displayed -#ifndef SWIG -define_place_exported_functions(structplace_t) -#endif // SWIG -/// A location in a struct view -class structplace_t : public place_t -{ -public: - uval_t idx; ///< struct serial number - uval_t offset; ///< offset within struct - structplace_t(void) {} ///< Constructor - structplace_t(uval_t i, uval_t o, int ln) : place_t(ln), idx(i), offset(o) {} ///< Constructor - define_place_virtual_functions(structplace_t); -}; - -//------------------------------------------------------------------------- -/// A location in a hex view -#ifndef SWIG -define_place_exported_functions(hexplace_t) -struct outctx_base_t; -struct hexplace_gen_t; -class hexview_t; -idaman void ida_export hexplace_t__out_one_item( - const hexplace_t *_this, - outctx_base_t &ctx, - const hexplace_gen_t *hg, - int itemno, - color_t *color, - color_t patch_or_edit); -idaman size_t ida_export hexplace_t__ea2str( - char *buf, - size_t bufsize, - const hexplace_gen_t *hg, - ea_t ea); -#endif // SWIG - -#define HEXPLACE_COLOR_EDITED COLOR_SYMBOL -#define HEXPLACE_COLOR_PATCHED COLOR_VOIDOP -#define HEXPLACE_COLOR_SHOWSPACES COLOR_RESERVED1 - -// A helper, used as 'userdata' for generating lines in a hexplace_t -// None of the function pointers can be NULL -struct hexplace_gen_t -{ - // data format to display - enum data_kind_t - { - dk_float, - dk_int, - dk_addr_names, - dk_addr_text, - }; - enum int_format_t - { - if_hex, - if_signed, - if_unsigned, - }; - // result of get_byte_value() - enum byte_kind_t - { - BK_VALID, // has a valid value - BK_INVALIDADDR, // address is invalid - BK_NOVALUE, // address is valid but contains no value - }; - - virtual bool is_editing() const = 0; - virtual bool is_editing_text() const = 0; - virtual bool is_curitem_changed() const = 0; - virtual bool is_edited_byte(ea_t ea, uint64 *out_value=NULL) const = 0; - virtual byte_kind_t get_byte_value( - ea_t ea, - uint64 *out_value, - bool *out_edited) const = 0; - virtual void get_encoding(qstring *out) const = 0; - virtual ea_t get_cur_item_ea() const = 0; - virtual void get_cur_item_text(qstring *out) const = 0; - virtual int get_alignment() const = 0; - virtual int get_line_len(ea_t ea) const = 0; - virtual int get_items_per_line() const = 0; - virtual int get_bytes_per_item() const = 0; - virtual int get_item_width(ea_t ea) const = 0; - virtual data_kind_t get_data_kind() const = 0; - virtual int_format_t get_int_format() const = 0; - virtual bool has_central_separator() const = 0; - virtual bool show_text() const = 0; - virtual bool show_segaddr() const = 0; - virtual int get_bitness() const = 0; - - bool is_addr_kind() const - { - data_kind_t k = get_data_kind(); - return k == dk_addr_names || k == dk_addr_text; - } -}; - -//------------------------------------------------------------------------- -// class to represent lines in a hex dump window -// one line consists of hv->grid.items_per_line items -// each item is hv->grid.bytes_per_item bytes for 8-bit bytes or one "wide" byte -class hexplace_t : public idaplace_t -{ -protected: - ea_t sol; // EA at start-of-line -public: - hexplace_t(ea_t _ea, short ln) : idaplace_t(_ea, ln), sol(_ea) {} - define_place_virtual_functions(hexplace_t); - - void out_one_item( - outctx_base_t &ctx, - const hexplace_gen_t *hg, - int itemno, - color_t *color, - color_t patch_or_edit) const - { - hexplace_t__out_one_item(this, ctx, hg, itemno, color, patch_or_edit); - } - - // convert ea to text - // use seg:off if segment base is not zero - // otherwise print just the address - static size_t ea2str(char *buf, size_t bufsize, const hexplace_gen_t *hg, ea_t ea) - { - return hexplace_t__ea2str(buf, bufsize, hg, ea); - } - -}; - -//------------------------------------------------------------------------- -#define PCF_EA_CAPABLE 0x00000001 ///< toea() implementation returns meaningful data -#define PCF_MAKEPLACE_ALLOCATES 0x00000002 ///< makeplace() returns a freshly allocated (i.e., non-static) - ///< instance. All new code should pass that flag to - ///< register_place_class(), and the corresponding - ///< makeplace() class implementation should - ///< return new instances. - -//------------------------------------------------------------------------- -idaman int ida_export internal_register_place_class( - const place_t *tmplate, - int flags, - const plugin_t *owner, - int sdk_version); - - -//------------------------------------------------------------------------- -/// Register information about a place_t class. -/// -/// The kernel will not take ownership, nor delete the 'tmplate' instance. -/// Therefore, it's up to the plugin to handle it (the recommended way -/// of doing it is to pass address of a const static instance.) -/// In addition, the place_t will be automatically unregistered when the owner -/// plugin is unloaded from memory. -/// \param tmplate the place_t template -/// \param flags or'ed combination of PCF_* flags. You should always -/// pass at least PCF_MAKEPLACE_ALLOCATES, and have the -/// place_t::makeplace() implementation create new instances. -/// \param owner the owner plugin of the place_t type. Cannot be NULL. -/// \return the place_t ID, or -1 if an error occurred. -inline int register_place_class( - const place_t *tmplate, - int flags, - const plugin_t *owner) -{ - return internal_register_place_class(tmplate, flags, owner, IDA_SDK_VERSION); -} - -//------------------------------------------------------------------------- -/// Get information about a previously-registered place_t class. -/// See also register_place_class(). -/// \param out_flags output flags (can be NULL) -/// \param out_sdk_version sdk version the place was created with (can be NULL) -/// \param id place class ID -/// \return the place_t template, or NULL if not found -idaman const place_t *ida_export get_place_class( - int *out_flags, - int *out_sdk_version, - int id); - -//------------------------------------------------------------------------- -/// See get_place_class() -inline const place_t *get_place_class_template(int id) -{ - return get_place_class(NULL, NULL, id); -} - -//------------------------------------------------------------------------- -/// See get_place_class() -inline bool is_place_class_ea_capable(int id) -{ - int flags; - if ( get_place_class(&flags, NULL, id) == NULL ) - return false; - return (flags & PCF_EA_CAPABLE) != 0; -} - -//------------------------------------------------------------------------- -/// Get the place class ID for the place that has been registered as 'name'. -/// \param name the class name -/// \return the place class ID, or -1 if not found -idaman int ida_export get_place_class_id(const char *name); - -#ifndef __UI__ - // A TWidget represents any user-facing widget present in IDA. - // E.g., "IDA View-*", "Hex View-*", "Imports", "General registers", ... - class TWidget; -#else - #ifdef __QT__ - namespace QT - { - class QWidget; - }; - typedef QT::QWidget TWidget; - #else - class TView; - typedef TView TWidget; - #endif -#endif - -//------------------------------------------------------------------------- -class sync_source_t -{ - uchar storage[16]; - - const TWidget **get_widget_ptr_storage() const - { - return (const TWidget **) &storage[sizeof(storage) - sizeof(TWidget *)]; - } - -public: - sync_source_t(); // No - sync_source_t(const TWidget *_view) - { - memset(storage, 0, sizeof(storage)); - *get_widget_ptr_storage() = _view; - storage[0] = '\0'; - } - sync_source_t(const char *_regname) - { - QASSERT(1716, _regname[0] != '\0'); - memset(storage, 0, sizeof(storage)); - qstrncpy((char *) storage, _regname, sizeof(storage)); - } - - bool operator==(const sync_source_t &_o) const - { - return memcmp(storage, _o.storage, sizeof(storage)) == 0; - } - bool operator!=(const sync_source_t &_o) const - { - return !((*this) == _o); - } - - bool is_register() const { return storage[0] != '\0'; } - bool is_widget() const { return !is_register(); } - const TWidget *get_widget() const - { - QASSERT(1717, is_widget()); - return *get_widget_ptr_storage(); - } - const char *get_register() const - { - QASSERT(1718, is_register()); - return (const char *) storage; - } -}; -DECLARE_TYPE_AS_MOVABLE(sync_source_t); -CASSERT(sizeof(sync_source_t) == 16); -typedef qvector sync_source_vec_t; - -struct synced_group_t : public sync_source_vec_t -{ - bool has_widget(const TWidget *v) const { return has(sync_source_t((TWidget *) v)); } - bool has_register(const char *r) const { return has(sync_source_t(r)); } - bool has(const sync_source_t &ss) const { return find(ss) != end(); } -}; - -//------------------------------------------------------------------------- -/// Converts from an entry with a given place type, to another entry, -/// with another place type, to be used with the view 'view'. Typically -/// used when views are synchronized. -/// The 'renderer_info_t' part of 'dst' will be pre-filled with -/// the current renderer_info_t of 'view', while the 'place_t' instance -/// will always be NULL. -enum lecvt_code_t -{ - LECVT_CANCELED = -1, - LECVT_ERROR = 0, - LECVT_OK = 1, -}; -typedef lecvt_code_t idaapi lochist_entry_cvt_t( - lochist_entry_t *dst, - const lochist_entry_t &src, - TWidget *view); - -//------------------------------------------------------------------------- -/// Register a converter, that will be used for the following reasons: -/// - determine what view can be synchronized with what other view -/// - when views are synchronized, convert the location from one view, -/// into an appropriate location in the other view -/// - if one of p1 or p2 is "idaplace_t", and the other is PCF_EA_CAPABLE, -/// then the converter will also be called when the user wants to jump to -/// an address (e.g., by pressing "g"). In that case, from's place_t's lnnum -/// will be set to -1 (i.e., can be used to descriminate between proper -/// synchronizations, and jump to's if needed.) -/// -/// Note: the converter can be used to convert in both directions, and can be -/// called with its 'from' being of the class of 'p1', or 'p2'. -/// If you want your converter to work in only one direction (e.g., from -/// 'my_dictionary_place_t' -> 'my_definition_place_t'), you can have it -/// return false when it is called with a lochist_entry_t's whose place is -/// of type 'my_definition_place_t'. -/// -/// Note: Whenever one of the 'p1' or 'p2' places is unregistered, -/// corresponding converters will be automatically unregistered as well. -/// -/// \param p1 the name of the first place_t class this converter can convert from/to -/// \param p2 the name of the second place_t class this converter can convert from/to -/// \param cvt the converter -idaman void ida_export register_loc_converter( - const char *p1, - const char *p2, - lochist_entry_cvt_t *cvt); - -//------------------------------------------------------------------------- -/// Search for a place converter from lochist_entry_t's with places of type -/// 'p1' to lochist_entry_t's with places of type 'p2'. -/// \param p1 the name of the place_t class to convert from -/// \param p2 the name of the place_t class to convert to -/// \return a converter, or NULL if none found -idaman lochist_entry_cvt_t *ida_export lookup_loc_converter( - const char *p1, - const char *p2); - - - -//---------------------------------------------------------------------- -/// A position in a text window -class twinpos_t -{ -public: - place_t *at; ///< location in view - int x; ///< cursor x - twinpos_t(void) { at=NULL; x=0; } ///< Constructor - twinpos_t(place_t *t) { at=t; x=0; } ///< Constructor - twinpos_t(place_t *t,int x0) { at=t; x=x0; } ///< Constructor - DEFINE_MEMORY_ALLOCATION_FUNCS() -}; - -/// A line in a text window -class twinline_t -{ -public: - place_t *at; ///< location in view - qstring line; ///< line contents - color_t prefix_color; ///< line prefix color - bgcolor_t bg_color; ///< line background color - bool is_default; ///< is this the default line of the current location? - twinline_t(void) ///< Constructor - { - at = NULL; - prefix_color = 1; - bg_color = DEFCOLOR; - is_default = false; - } - twinline_t(place_t *t, color_t pc, bgcolor_t bc) ///< Constructor - { - at = t; - prefix_color = pc; - bg_color = bc; - is_default = false; - } - DEFINE_MEMORY_ALLOCATION_FUNCS() -}; -DECLARE_TYPE_AS_MOVABLE(twinline_t); - -/// A group of lines in a text window -typedef qvector text_t; - -#ifndef SWIG - -/// Helper for declaring member functions of the ::linearray_t class -#define DECLARE_LINEARRAY_HELPERS(decl) \ -decl void ida_export linearray_t_ctr(linearray_t *, void *ud); \ -decl void ida_export linearray_t_dtr(linearray_t *); \ -decl int ida_export linearray_t_set_place(linearray_t *, const place_t *new_at); \ -decl bool ida_export linearray_t_beginning(const linearray_t *); \ -decl bool ida_export linearray_t_ending(const linearray_t *); \ -decl const qstring *ida_export linearray_t_down(linearray_t *); \ -decl const qstring *ida_export linearray_t_up(linearray_t *); - -class linearray_t; -DECLARE_LINEARRAY_HELPERS(idaman) - -/// The group of lines corresponding to a single place within a view -class linearray_t -{ - DECLARE_LINEARRAY_HELPERS(friend) - int _set_place(const place_t *new_at); - const qstring *_down (void); - const qstring *_up (void); - - qstrvec_t lines; // lines corresponding to the current place_t - place_t *at; - void *ud; // user defined data (UD) - // its meaning depends on the place_t used - color_t prefix_color; // prefix color - bgcolor_t bg_color; // background color - qstring extra; // the last line of the previous location after moving down - int dlnnum; // default line number (if unknown, -1) - - int getlines(void); - void cleanup(void); - -public: - - linearray_t(void *_ud) { linearray_t_ctr(this, _ud); } ///< Constructor - ~linearray_t(void) { linearray_t_dtr(this); } ///< Constructor - DEFINE_MEMORY_ALLOCATION_FUNCS() - - /// Position the array. - /// This function must be called before calling any other member functions. - /// - /// ::linearray_t doesn't own ::place_t structures. - /// The caller must take care of place_t objects. - /// - /// \param new_at new position of the array - /// \return the delta of lines that the linearray_t had to adjust the place by. \n - /// For example, if the place_t has a lnnum of 5, but it turns out, upon generating lines, \n - /// that the number of lines for that particular place is only 2, then 3 will be returned. - int set_place(const place_t *new_at) { return linearray_t_set_place(this, new_at); } - - /// Get the current place. - /// If called before down(), then returns place of line which will be returned by down(). - /// If called after up(), then returns place if line returned by up(). - place_t *get_place (void) const { return at; } - - /// Get current background color. - /// (the same behavior as with get_place(): good before down() and after up()) - bgcolor_t get_bg_color(void) const { return bg_color; } - - /// Get current prefix color. - /// (the same behavior as with get_place(): good before down() and after up()) - bgcolor_t get_pfx_color(void) const { return prefix_color; } - - /// Get default line number. - /// (the same behavior as with get_place(): good before down() and after up()) - int get_dlnnum(void) const { return dlnnum; } - - /// Get number of lines for the current place. - /// (the same behavior as with get_place(): good before down() and after up()) - int get_linecnt(void) const { return int(lines.size()); } - - /// Get pointer to user data - void *userdata(void) const { return ud; } - - /// Change the user data - void set_userdata(void *userd) { ud = userd; } - - /// Are we at the beginning? - bool beginning(void) const { return linearray_t_beginning(this); } - - // Are we at the end? - bool ending(void) const { return linearray_t_ending(this); } - - /// Get a line from down direction. - /// place is ok BEFORE - const qstring *down(void) - { return linearray_t_down(this); } - - /// Get a line from up direction. - /// place is ok AFTER - const qstring *up(void) - { return linearray_t_up(this); } - -}; -#endif // SWIG - -//------------------------------------------------------------------------- -typedef qvector section_lines_refs_t; -typedef qvector sections_lines_refs_t; - -//------------------------------------------------------------------------- -/// Contains information necessary for plugins to compute extra -/// information needed for rendering. -struct lines_rendering_input_t -{ - int cb; - sections_lines_refs_t sections_lines; ///< references to the lines that are used for rendering - const synced_group_t *sync_group; ///< the 'synced' group 'widget' (see ui_get_lines_rendering_info) belongs to, or NULL - - lines_rendering_input_t() - : cb(sizeof(*this)), - sync_group(NULL) {} -}; - -//------------------------------------------------------------------------- -/// \defgroup CK_ keys -/// passed as 'bg_color' of a line_rendering_output_entry_t, to use -/// a CSS property of the widget ('qproperty-line-bgovl-extra-N') -/// instead of a direct color -//@{ -// -#define CK_TRACE 80 ///< traced address -#define CK_TRACE_OVL 81 ///< overlay trace address -#define CK_EXTRA1 82 ///< extra background overlay #1 -#define CK_EXTRA2 83 ///< extra background overlay #2 -#define CK_EXTRA3 84 ///< extra background overlay #3 -#define CK_EXTRA4 85 ///< extra background overlay #4 -#define CK_EXTRA5 86 ///< extra background overlay #5 -#define CK_EXTRA6 87 ///< extra background overlay #6 -#define CK_EXTRA7 88 ///< extra background overlay #7 -#define CK_EXTRA8 89 ///< extra background overlay #8 -#define CK_EXTRA9 90 ///< extra background overlay #9 -#define CK_EXTRA10 91 ///< extra background overlay #10 -#define CK_EXTRA11 92 ///< extra background overlay #11 -#define CK_EXTRA12 93 ///< extra background overlay #12 -#define CK_EXTRA13 94 ///< extra background overlay #13 -#define CK_EXTRA14 95 ///< extra background overlay #14 -#define CK_EXTRA15 96 ///< extra background overlay #15 -#define CK_EXTRA16 97 ///< extra background overlay #16 - -//@} - -/// \defgroup LROEF_ line_rendering_output_entry_t flags -/// used by 'flags' of a line_rendering_output_entry_t -//@{ -#define LROEF_MASK 0x00FFFFFF -#define LROEF_FULL_LINE 0x00000000 ///< full line background -#define LROEF_CPS_RANGE 0x00000001 ///< background for range of chars -//@} - -struct line_rendering_output_entry_t -{ - const twinline_t *line; - uint32 flags; ///< \ref LROEF_ - - // 0x00000000: nothing - // 0xAABBGGRR: where AA is 0: BBGGRR contains a key (CK_*) to a color property - // 0xAABBGGRR: where AA is !0: 0xAABBGGRR is the background color, with alpha value, to be applied to that line - // - // The 'bg_color' specified here, will be applied on top of the background - // color that was computed for 'line', which itself can be: - // - none (i.e., the default background color), - // - a possible value stored in the IDB (see 'set_item_color()'), - // - a value provided by processor_t::ev_get_bg_color - // The value provided here should typically be partly transparent - // so that it doesn't obstruct the computed background color - // (the best, by far, is to stick to CK_* keys: their corresponding - // colors typically have partial translucency, and each theme can - // customize them.) - bgcolor_t bg_color; - - int cpx; ///< number of char to start from, valid if LROEF_CPS_RANGE - int nchars; ///< chars count, valid if LROEF_CPS_RANGE - - line_rendering_output_entry_t(const twinline_t *_line, uint32 _flags=0, bgcolor_t _bg_color=0) - : line(_line), flags(_flags), bg_color(_bg_color), cpx(-1), nchars(-1) {} - - line_rendering_output_entry_t(const twinline_t *_line, int _cpx, int _nchars, uint32 _flags, bgcolor_t _bg_color) - : line(_line), flags(_flags|LROEF_CPS_RANGE), bg_color(_bg_color), cpx(_cpx), nchars(_nchars) {} - - bool is_bg_color_empty() const { return bg_color == 0; } - bool is_bg_color_key() const { return (bg_color & 0xFF000000) == 0 && !is_bg_color_empty(); } - bool is_bg_color_direct() const { return (bg_color & 0xFF000000) != 0; } - - bool operator==(const line_rendering_output_entry_t &r) const - { - bool ok = (flags & LROEF_MASK) == (r.flags & LROEF_MASK) - && line == r.line - && bg_color == r.bg_color; - if ( ok && (flags & LROEF_CPS_RANGE) != 0 ) - ok = cpx == r.cpx && nchars == r.nchars; - return ok; - } - - bool operator!=(const line_rendering_output_entry_t &r) const - { return !(*this == r); } -}; -DECLARE_TYPE_AS_MOVABLE(line_rendering_output_entry_t); -typedef qvector line_rendering_output_entries_refs_t; - -//------------------------------------------------------------------------- -struct lines_rendering_output_t -{ - line_rendering_output_entries_refs_t entries; - uint32 flags; - - lines_rendering_output_t() : flags(0) {} - ~lines_rendering_output_t() - { - clear(); - } - - void clear() - { - for ( size_t i = 0, n = entries.size(); i < n; ++i ) - delete entries[i]; - } - - bool operator==(const lines_rendering_output_t &r) const - { - if ( flags != r.flags ) - return false; - const size_t n = entries.size(); - if ( n != r.entries.size() ) - return false; - for ( size_t i = 0; i < n; ++i ) - if ( *entries[i] != *r.entries[i] ) - return false; - return true; - } - - bool operator!=(const lines_rendering_output_t &r) const - { return !(*this == r); } - - void swap(lines_rendering_output_t &r) - { - qswap(flags, r.flags); - entries.swap(r.entries); - } -}; - - -#ifndef SWIG -/// Bitmask of builtin window types to be refreshed: -idaman uint64 ida_export get_dirty_infos(void); -#endif // SWIG - - -/// Request a refresh of a builtin window. -/// \param mask \ref IWID_ -/// \param cnd set if true or clear flag otherwise - -idaman void ida_export request_refresh(uint64 mask, bool cnd=true); -inline void clear_refresh_request(uint64 mask) { request_refresh(mask, false); } - - -/// Get a refresh request state -/// \param mask \ref IWID_ -/// \returns the state (set or cleared) - -idaman bool ida_export is_refresh_requested(uint64 mask); - - -//------------------------------------------------------------------------- -typedef int twidget_type_t; ///< \ref BWN_ - -/// \defgroup BWN_ Window types -/// also see \ref ui_open_builtin_funcs -//@{ -#define BWN_UNKNOWN -1 ///< unknown window -#define BWN_EXPORTS 0 ///< exports -#define BWN_IMPORTS 1 ///< imports -#define BWN_NAMES 2 ///< names -#define BWN_FUNCS 3 ///< functions -#define BWN_STRINGS 4 ///< strings -#define BWN_SEGS 5 ///< segments -#define BWN_SEGREGS 6 ///< segment registers -#define BWN_SELS 7 ///< selectors -#define BWN_SIGNS 8 ///< signatures -#define BWN_TILS 9 ///< type libraries -#define BWN_LOCTYPS 10 ///< local types -#define BWN_CALLS 11 ///< function calls -#define BWN_PROBS 12 ///< problems -#define BWN_BPTS 13 ///< breakpoints -#define BWN_THREADS 14 ///< threads -#define BWN_MODULES 15 ///< modules -#define BWN_TRACE 16 ///< trace view -#define BWN_CALL_STACK 17 ///< call stack -#define BWN_XREFS 18 ///< xrefs -#define BWN_SEARCH 19 ///< search results -#define BWN_FRAME 25 ///< function frame -#define BWN_NAVBAND 26 ///< navigation band -#define BWN_ENUMS 27 ///< enumerations -#define BWN_STRUCTS 28 ///< structures -#define BWN_DISASM 29 ///< disassembly views -#define BWN_DUMP 30 ///< hex dumps -#define BWN_NOTEPAD 31 ///< notepad -#define BWN_OUTPUT 32 ///< the text area, in the output window -#define BWN_CLI 33 ///< the command-line, in the output window -#define BWN_WATCH 34 ///< the 'watches' debugger window -#define BWN_LOCALS 35 ///< the 'locals' debugger window -#define BWN_STKVIEW 36 ///< the 'Stack view' debugger window -#define BWN_CHOOSER 37 ///< a non-builtin chooser -#define BWN_SHORTCUTCSR 38 ///< the shortcuts chooser (Qt version only) -#define BWN_SHORTCUTWIN 39 ///< the shortcuts window (Qt version only) -#define BWN_CPUREGS 40 ///< one of the 'General registers', 'FPU register', ... debugger windows -#define BWN_SO_STRUCTS 41 ///< the 'Structure offsets' dialog's 'Structures and Unions' panel -#define BWN_SO_OFFSETS 42 ///< the 'Structure offsets' dialog's offset panel -#define BWN_CMDPALCSR 43 ///< the command palette chooser (Qt version only) -#define BWN_CMDPALWIN 44 ///< the command palette window (Qt version only) -#define BWN_SNIPPETS 45 ///< the 'Execute script' window -#define BWN_CUSTVIEW 46 ///< custom viewers -#define BWN_ADDRWATCH 47 ///< the 'Watch List' window -#define BWN_PSEUDOCODE 48 ///< hexrays decompiler views -#define BWN_CALLS_CALLERS 49 ///< function calls, callers -#define BWN_CALLS_CALLEES 50 ///< function calls, callees -#define BWN_MDVIEWCSR 51 ///< lumina metadata view chooser -#define BWN_DISASM_ARROWS 52 ///< disassembly arrows widget -#define BWN_CV_LINE_INFOS 53 ///< custom viewers' lineinfo widget -#define BWN_SRCPTHMAP_CSR 54 ///< "Source paths..."'s path mappings chooser -#define BWN_SRCPTHUND_CSR 55 ///< "Source paths..."'s undesired paths chooser -#define BWN_UNDOHIST 56 ///< Undo history -#define BWN_SNIPPETS_CSR 57 ///< the list of snippets in the 'Execute script' window -#define BWN_SCRIPTS_CSR 58 ///< the "Recent scripts" chooser - -/// Alias. Some BWN_* were confusing, and thus have been renamed. -/// This is to ensure bw-compat. -#define BWN_STACK BWN_CALL_STACK -#define BWN_DISASMS BWN_DISASM ///< \copydoc BWN_STACK -#define BWN_DUMPS BWN_DUMP ///< \copydoc BWN_STACK -#define BWN_SEARCHS BWN_SEARCH ///< \copydoc BWN_STACK -//@} - -/// \defgroup IWID_ Window refresh flags -/// passed as 'mask' parameter to request_refresh() -//@{ -#define IWID_EXPORTS (1ULL << BWN_EXPORTS ) ///< exports (0) -#define IWID_IMPORTS (1ULL << BWN_IMPORTS ) ///< imports (1) -#define IWID_NAMES (1ULL << BWN_NAMES ) ///< names (2) -#define IWID_FUNCS (1ULL << BWN_FUNCS ) ///< functions (3) -#define IWID_STRINGS (1ULL << BWN_STRINGS ) ///< strings (4) -#define IWID_SEGS (1ULL << BWN_SEGS ) ///< segments (5) -#define IWID_SEGREGS (1ULL << BWN_SEGREGS ) ///< segment registers (6) -#define IWID_SELS (1ULL << BWN_SELS ) ///< selectors (7) -#define IWID_SIGNS (1ULL << BWN_SIGNS ) ///< signatures (8) -#define IWID_TILS (1ULL << BWN_TILS ) ///< type libraries (9) -#define IWID_LOCTYPS (1ULL << BWN_LOCTYPS ) ///< local types (10) -#define IWID_CALLS (1ULL << BWN_CALLS ) ///< function calls (11) -#define IWID_PROBS (1ULL << BWN_PROBS ) ///< problems (12) -#define IWID_BPTS (1ULL << BWN_BPTS ) ///< breakpoints (13) -#define IWID_THREADS (1ULL << BWN_THREADS ) ///< threads (14) -#define IWID_MODULES (1ULL << BWN_MODULES ) ///< modules (15) -#define IWID_TRACE (1ULL << BWN_TRACE ) ///< trace view (16) -#define IWID_CALL_STACK (1ULL << BWN_CALL_STACK ) ///< call stack (17) -#define IWID_XREFS (1ULL << BWN_XREFS ) ///< xrefs (18) -#define IWID_SEARCH (1ULL << BWN_SEARCH ) ///< search results (19) -#define IWID_FRAME (1ULL << BWN_FRAME ) ///< function frame (25) -#define IWID_NAVBAND (1ULL << BWN_NAVBAND ) ///< navigation band (26) -#define IWID_ENUMS (1ULL << BWN_ENUMS ) ///< enumerations (27) -#define IWID_STRUCTS (1ULL << BWN_STRUCTS ) ///< structures (28) -#define IWID_DISASM (1ULL << BWN_DISASM ) ///< disassembly views (29) -#define IWID_DUMP (1ULL << BWN_DUMP ) ///< hex dumps (30) -#define IWID_NOTEPAD (1ULL << BWN_NOTEPAD ) ///< notepad (31) -#define IWID_OUTPUT (1ULL << BWN_OUTPUT ) ///< output (32) -#define IWID_CLI (1ULL << BWN_CLI ) ///< input line (33) -#define IWID_WATCH (1ULL << BWN_WATCH ) ///< watches (34) -#define IWID_LOCALS (1ULL << BWN_LOCALS ) ///< locals (35) -#define IWID_STKVIEW (1ULL << BWN_STKVIEW ) ///< stack view (36) -#define IWID_CHOOSER (1ULL << BWN_CHOOSER ) ///< chooser (37) -#define IWID_SHORTCUTCSR (1ULL << BWN_SHORTCUTCSR ) ///< shortcuts chooser (38) -#define IWID_SHORTCUTWIN (1ULL << BWN_SHORTCUTWIN ) ///< shortcuts window (39) -#define IWID_CPUREGS (1ULL << BWN_CPUREGS ) ///< registers (40) -#define IWID_SO_STRUCTS (1ULL << BWN_SO_STRUCTS ) ///< stroff (41) -#define IWID_SO_OFFSETS (1ULL << BWN_SO_OFFSETS ) ///< stroff (42) -#define IWID_CMDPALCSR (1ULL << BWN_CMDPALCSR ) ///< command palette (43) -#define IWID_CMDPALWIN (1ULL << BWN_CMDPALWIN ) ///< command palette (44) -#define IWID_SNIPPETS (1ULL << BWN_SNIPPETS ) ///< snippets (45) -#define IWID_CUSTVIEW (1ULL << BWN_CUSTVIEW ) ///< custom viewers (46) -#define IWID_ADDRWATCH (1ULL << BWN_ADDRWATCH ) ///< address watches (47) -#define IWID_PSEUDOCODE (1ULL << BWN_PSEUDOCODE ) ///< decompiler (48) -#define IWID_CALLS_CALLERS (1ULL << BWN_CALLS_CALLERS) ///< funcalls, callers (49) -#define IWID_CALLS_CALLEES (1ULL << BWN_CALLS_CALLEES) ///< funcalls, callees (50) -#define IWID_MDVIEWCSR (1ULL << BWN_MDVIEWCSR ) ///< lumina md view (51) -#define IWID_DISASM_ARROWS (1ULL << BWN_DISASM_ARROWS) ///< arrows widget (52) -#define IWID_CV_LINE_INFOS (1ULL << BWN_CV_LINE_INFOS) ///< lineinfo widget (53) -#define IWID_SRCPTHMAP_CSR (1ULL << BWN_SRCPTHMAP_CSR) ///< mappings chooser (54) -#define IWID_SRCPTHUND_CSR (1ULL << BWN_SRCPTHUND_CSR) ///< undesired chooser (55) -#define IWID_UNDOHIST (1ULL << BWN_UNDOHIST ) ///< Undo history (56) -#define IWID_SNIPPETS_CSR (1ULL << BWN_SNIPPETS_CSR ) ///< snippets chooser (57) -#define IWID_SCRIPTS_CSR (1ULL << BWN_SCRIPTS_CSR ) ///< recent scripts (58) - -#define IWID_IDAMEMOS (IWID_DISASMS|IWID_DUMPS ) ///< disassembly + hex dump views -#define IWID_ALL 0xFFFFFFFFFFFFFFFFULL ///< mask - -/// Alias. Some IWID_* were confusing, and thus have been renamed. -/// This is to ensure bw-compat. -#define IWID_STACK IWID_CALL_STACK -#define IWID_DISASMS IWID_DISASM -#define IWID_DUMPS IWID_DUMP -#define IWID_SEARCHS IWID_SEARCH -//@} - -/// Does the given widget type specify a chooser widget? - -inline bool is_chooser_widget(twidget_type_t t) -{ - return t == BWN_CHOOSER - || (t >= BWN_EXPORTS && t <= BWN_SEARCH && t != BWN_CALLS) - || t == BWN_SHORTCUTCSR - || t == BWN_CMDPALCSR - || t == BWN_CALLS_CALLERS - || t == BWN_CALLS_CALLEES - || t == BWN_MDVIEWCSR - || t == BWN_SRCPTHMAP_CSR - || t == BWN_SRCPTHUND_CSR - || t == BWN_UNDOHIST - || t == BWN_SNIPPETS_CSR - || t == BWN_SCRIPTS_CSR; -} - - -#ifndef SWIG -//--------------------------------------------------------------------------- -// D E B U G G I N G F U N C T I O N S -//--------------------------------------------------------------------------- - -/// Controls debug messages - combination of \ref IDA_DEBUG_ -idaman uint32 ida_export_data debug; - -/// \defgroup IDA_DEBUG_ IDA debug bits -/// used by ::debug -//@{ -#define IDA_DEBUG_DREFS 0x00000001 ///< drefs -#define IDA_DEBUG_OFFSET 0x00000002 ///< offsets -#define IDA_DEBUG_FLIRT 0x00000004 ///< flirt -#define IDA_DEBUG_IDP 0x00000008 ///< idp module -#define IDA_DEBUG_LDR 0x00000010 ///< ldr module -#define IDA_DEBUG_PLUGIN 0x00000020 ///< plugin module -#define IDA_DEBUG_IDS 0x00000040 ///< ids files -#define IDA_DEBUG_CONFIG 0x00000080 ///< config file -#define IDA_DEBUG_CHECKMEM 0x00000100 ///< check heap consistency -#define IDA_DEBUG_CHECKARG 0x00000200 ///< checkarg -#define IDA_DEBUG_DEMANGLE 0x00000400 ///< demangler -#define IDA_DEBUG_QUEUE 0x00000800 ///< queue -#define IDA_DEBUG_ROLLBACK 0x00001000 ///< rollback -#define IDA_DEBUG_ALREADY 0x00002000 ///< already data or code -#define IDA_DEBUG_TIL 0x00004000 ///< type system -#define IDA_DEBUG_NOTIFY 0x00008000 ///< show all notifications -#define IDA_DEBUG_DEBUGGER 0x00010000 ///< debugger -#define IDA_DEBUG_APPCALL 0x00020000 ///< appcall -#define IDA_DEBUG_SRCDBG 0x00040000 ///< source debugging -#define IDA_DEBUG_ACCESSIBILITY 0x00080000 ///< accessibility -#define IDA_DEBUG_NETWORK 0x00100000 ///< network -#define IDA_DEBUG_INTERNET IDA_DEBUG_NETWORK ///< internet connection (for API backward compatibility) -#define IDA_DEBUG_SIMPLEX 0x00200000 ///< full stack analysis -#define IDA_DEBUG_DBGINFO 0x00400000 ///< handling of debug info (e.g. pdb, dwarf) -#define IDA_DEBUG_LUMINA 0x00800000 ///< lumina related -#define IDA_DEBUG_THEMES 0x01000000 ///< themes -#define IDA_DEBUG_REGEX 0x02000000 ///< regular expression -#define IDA_DEBUG_ALWAYS 0xFFFFFFFF ///< everything -//@} - - -/// Display debug message. -/// \param ida_debug_bits \ref IDA_DEBUG_, also see ::debug -/// \param format printf()-style format -/// \return number of bytes output -/// Note: use deb() macro - -AS_PRINTF(1, 2) inline int ida_deb(const char *format, ...) -{ - va_list va; - va_start(va, format); - int nbytes = callui(ui_msg, format, va).i; - va_end(va); - return nbytes; -} - -#define deb(ida_debug_bits, ...) \ - do \ - { \ - if ( (debug & (ida_debug_bits)) != 0 ) \ - ida_deb(__VA_ARGS__); \ - } while ( false ) - - -/// Checking heap is not available anymore. -#define checkmem() do {} while (0) // ida_checkmem(__FILE__, __LINE__) -/// \copydoc checkmem() -idaman void ida_export ida_checkmem(const char *file, int line); - - -/// Display hex dump in the messages window - -AS_PRINTF(3, 4) inline void show_hex( - const void *dataptr, - size_t len, - const char *format, - ...) -{ - va_list va; - va_start(va,format); - vshow_hex(dataptr, len, format, va); - va_end(va); -} - - -/// Display hex dump of a file in the messages window - -AS_PRINTF(4, 5) inline void show_hex_file( - linput_t *li, - int64 pos, - size_t count, - const char *format, - ...) -{ - va_list va; - va_start(va,format); - vshow_hex_file(li, pos, count, format, va); - va_end(va); -} -#endif // SWIG - -//------------------------------------------------------------------------- -// U I S E R V I C E F U N C T I O N S -//------------------------------------------------------------------------- - -/// \defgroup CH_ Generic chooser flags -/// used as 'chooser_base_t::flags' -//@{ -/// Modal chooser -#define CH_MODAL 0x00000001 -/// The chooser instance's lifecycle is not tied to the lifecycle of the -/// widget showing its contents. Closing the widget will not destroy the -/// chooser structure. This allows for, e.g., static global chooser instances -/// that don't need to be allocated on the heap. Also stack-allocated chooser -/// instances must set this bit. -#define CH_KEEP 0x00000002 -/// The chooser will allow multi-selection (only for GUI choosers). This bit -/// is set when using the chooser_multi_t structure. -#define CH_MULTI 0x00000004 -///< Obsolete -#define CH_MULTI_EDIT 0x00000008 -/// do not display ok/cancel/help/search buttons. -/// Meaningful only for gui modal windows because non-modal windows do not -/// have any buttons anyway. Text mode does not have them neither. -#define CH_NOBTNS 0x00000010 -/// generate ui_get_chooser_item_attrs (gui only) -#define CH_ATTRS 0x00000020 -/// use the chooser before opening the database -#define CH_NOIDB 0x00000040 -/// if a non-modal chooser was already open, change selection to the default -/// one -#define CH_FORCE_DEFAULT 0x00000080 -/// allow to insert new items -#define CH_CAN_INS 0x00000100 -/// allow to delete existing item(s) -#define CH_CAN_DEL 0x00000200 -/// allow to edit existing item(s) -#define CH_CAN_EDIT 0x00000400 -/// allow to refresh chooser -#define CH_CAN_REFRESH 0x00000800 - -/// open with quick filter enabled and focused -#define CH_QFLT 0x00001000 -#define CH_QFTYP_SHIFT 13 -#define CH_QFTYP_DEFAULT 0 ///< set quick filtering type to the possible existing default for this chooser -#define CH_QFTYP_NORMAL (1 << CH_QFTYP_SHIFT) ///< normal (i.e., lexicographical) quick filter type -#define CH_QFTYP_WHOLE_WORDS (2 << CH_QFTYP_SHIFT) ///< whole words quick filter type -#define CH_QFTYP_REGEX (3 << CH_QFTYP_SHIFT) ///< regex quick filter type -#define CH_QFTYP_FUZZY (4 << CH_QFTYP_SHIFT) ///< fuzzy search quick filter type -#define CH_QFTYP_MASK (0x7 << CH_QFTYP_SHIFT) - -/// don't show a status bar -#define CH_NO_STATUS_BAR 0x00010000 - -/// restore floating position if present (equivalent of WOPN_RESTORE) (GUI version only) -#define CH_RESTORE 0x00020000 - -//#define CH_FREE 0x00040000 - -#define CH_BUILTIN_SHIFT 19 -#define CH_BUILTIN(id) ((id+1) << CH_BUILTIN_SHIFT) -/// Mask for builtin chooser numbers. Plugins should not use them. -#define CH_BUILTIN_MASK (0x3F << CH_BUILTIN_SHIFT) - -/// The chooser can provide a dirtree_t, meaning a tree-like structure -/// can be provided to the user (instead of a flat table) -#define CH_HAS_DIRTREE 0x02000000 - -#define CH_TM_NO_TREE 0x00000000 ///< chooser will show up in no-tree mode -#define CH_TM_FOLDERS_ONLY 0x04000000 ///< chooser will show in folders-only mode -#define CH_TM_FULL_TREE 0x08000000 ///< chooser will show in no-tree mode -#define CH_TM_SHIFT 26 -#define CH_TM_MASK (0x3 << CH_TM_SHIFT) - -//#define CH_FREE 0xF0000000 -//@} - -/// \defgroup CHCOL_ Chooser column flags -/// used by 'widths' parameter for \ref choosers -//@{ -#define CHCOL_PLAIN 0x00000000 ///< plain string -#define CHCOL_PATH 0x00010000 ///< file path -#define CHCOL_HEX 0x00020000 ///< hexadecimal number -#define CHCOL_DEC 0x00030000 ///< decimal number -#define CHCOL_EA 0x00040000 ///< address -#define CHCOL_FNAME 0x00050000 ///< function name -#define CHCOL_FORMAT 0x00070000 ///< column format mask - -#define CHCOL_DEFHIDDEN 0x00100000 ///< column should be hidden by default -#define CHCOL_DRAGHINT 0x00200000 ///< the column number that will be used - ///< to build hints for the dragging undo - ///< label. This should be provided for at - ///< most one column for any given chooser. -#define CHCOL_INODENAME 0x00400000 ///< if CH_HAS_DIRTREE has been specified, - ///< this instructs the chooser that this - ///< column shows the inode name. This - ///< should be provided for at most one - ///< column for any given chooser. -//@} - - -/// \defgroup CHITEM_ Chooser item property bits -/// used by chooser_item_attrs_t::flags -//@{ -#define CHITEM_BOLD 0x0001 ///< display the item in bold -#define CHITEM_ITALIC 0x0002 ///< display the item in italic -#define CHITEM_UNDER 0x0004 ///< underline the item -#define CHITEM_STRIKE 0x0008 ///< strikeout the item -#define CHITEM_GRAY 0x0010 ///< gray out the item -//@} - -/// \name Chooser title -/// prefixes to be used in the chooser title -//@{ -#define CHOOSER_NOMAINMENU "NOMAINMENU\n" ///< do not display main menu -#define CHOOSER_NOSTATUSBAR "NOSTATUSBAR\n" ///< do not display status bar (obsolete. Use CH_NO_STATUS_BAR instead) -//@} - -class dirtree_t; -typedef uval_t inode_t; - -/// Chooser item attributes -struct chooser_item_attrs_t -{ - int cb; ///< size of this structure. - ///< the callback must check this field and fill only - ///< the existing fields. the first 2 fields always exist: - int flags; ///< \ref CHITEM_ - bgcolor_t color; ///< item color - chooser_item_attrs_t() - : cb(sizeof(chooser_item_attrs_t)), - flags(0), - color(DEFCOLOR) {} - void reset(void) ///< restore to defaults - { - cb = sizeof(chooser_item_attrs_t); - flags = 0; - color = DEFCOLOR; - } -}; - -#ifndef SWIG - -/// Chooser object. #chooser -struct chooser_base_t -{ -protected: - uint32 version; ///< version of the class - - uint32 flags; ///< \ref CH_ - -public: - // TODO reduce to 4 values - // embedded chooser: width, height. Other values are ignored. - // qt: y1 == -2 => minimal height (and centered) - // Other values are ignored. - int x0; ///< screen position, \ref choosers - int y0; - int x1; - int y1; - int width; ///< (in chars) - int height; ///< (in chars) - - const char *title; ///< menu title (includes ptr to help). - ///< May have chooser title prefixes (see "Chooser - ///< title" above). - int columns; ///< number of columns - const int *widths; ///< column widths - ///< - low 16 bits of each value hold the column width - ///< - high 16 bits are flags (see \ref CHCOL_) - const char *const *header; - ///< header line; contains the tooltips, and column name - ///< for each of 'columns' columns. - ///< When tooltips need to be provided, the syntax - ///< should be: "#tooltip#column-name". (Otherwise, - ///< the syntax is simply "column-name".) - int icon; ///< default icon - - /// \defgroup chooser_index Special values of the chooser index - /// Used in the following contexts: - /// 1. as the return value of the choose() function - /// 2. as the `idx` field of the return value of the get_item_index(), - /// ins(), del(), edit(), enter(), refresh() callbacks of the - /// `chooser_t` structure and of the callback of type - /// `chooser_cb_t` passed to the add_chooser_command() - /// 3. as the parameter `n` of the chooser_t::refresh() callback and - /// of the callback of type `chooser_cb_t` passed to the - /// add_chooser_command() - /// Usage matrix - // Context | 1 | 2 | 3 - // --------------------------- - // NO_SELECTION | X | X | X - // EMPTY_CHOOSER | X | | - // ALREADY_EXISTS | X | | - //@{ - enum - { - NO_SELECTION = -1, ///< there is no selected item - EMPTY_CHOOSER = -2, ///< the chooser has no data and cannot be - ///< displayed - ALREADY_EXISTS = -3, ///< the non-modal chooser with the same data is - ///< already open - NO_ATTR = -4, ///< reserved for IDAPython - }; - //@} - - enum { POPUP_INS, POPUP_DEL, POPUP_EDIT, POPUP_REFRESH, NSTDPOPUPS }; - /// array of custom popup menu names. - /// Used to replace labels for the standard handlers (Insert, Delete, - /// Edit, Refresh). \n - /// An empty name means that the default name will be used. - /// \note Availability of items in the popup menu is determined by the - /// `CH_CAN_...` flags. - qstring popup_names[NSTDPOPUPS]; - - int deflt_col; ///< Column that will have focus. - - chooser_base_t( - uint32 flags_ = 0, - int columns_ = 0, - const int *widths_ = NULL, - const char *const *header_ = NULL, - const char *title_ = NULL) - : version(1), - flags(flags_), - x0(-1), y0(-1), x1(-1), y1(-1), - width(0), - height(0), - title(title_), - columns(columns_), - widths(widths_), - header(header_), - icon(-1), - deflt_col(0) {} - virtual ~chooser_base_t() {} - DEFINE_MEMORY_ALLOCATION_FUNCS() - - // called when the corresponding widget is destroyed. - // - // In some rare cases where multiple chooser_base_t instance can - // be backed by the same data (\sa get_obj_id), and a second instance - // is created while the first is already displayed (therefore making - // that second instance a duplicate), the second instance will be - // destroyed through this method (and chooser_base_t::ALREADY_EXISTS - // will be returned from choose().) - void call_destructor() - { - if ( (flags & CH_KEEP) == 0 ) - delete this; - } - - /// get pointer to some custom data. - /// \note These data are also called "the underlying object". - /// Now this method is used only in the ActionsInspector class and - /// ida_kernwin.Choose IDAPython's class. - virtual void *get_chooser_obj() { return this; } - - /// get the id of the chooser data. - /// The choosers are the same if they have the same data ids. - /// \param[out] len length of the id. If it is 0 then it is considered - /// that the method returned an unique id. - /// \return address of the id or NULL in the case len == 0 - virtual const void *get_obj_id(size_t *len) const - { - // return the unique id - *len = 0; - return NULL; - } - - /// do the current and the given objects hold the same data? - bool is_same(const chooser_base_t *other) const - { - size_t len1; - const void *id1 = get_obj_id(&len1); - size_t len2; - const void *id2 = other->get_obj_id(&len2); - return len1 == len2 && len1 != 0 && memcmp(id1, id2, len1) == 0; - } - - /// is an operation allowed? - bool can_ins() const { return (flags & CH_CAN_INS ) != 0; } - bool can_del() const { return (flags & CH_CAN_DEL ) != 0; } - bool can_edit() const { return (flags & CH_CAN_EDIT ) != 0; } - bool can_refresh() const { return (flags & CH_CAN_REFRESH) != 0; } - - /// is a popup action allowed? - bool popup_allowed(int i) const - { - switch ( i ) - { - case POPUP_INS: return can_ins(); - case POPUP_DEL: return can_del(); - case POPUP_EDIT: return can_edit(); - case POPUP_REFRESH: return can_refresh(); - default: return false; - } - } - bool is_status_bar_hidden() const { return (flags & CH_NO_STATUS_BAR) != 0; } - bool should_restore_geometry() const { return (flags & CH_RESTORE) != 0; } - /// is choose modal? - bool is_modal() const { return (flags & CH_MODAL) != 0; } - /// is multi-selection allowed? - bool is_multi() const { return (flags & CH_MULTI) != 0; } - /// should chooser generate ui_get_chooser_item_attrs events? - bool ask_item_attrs() const { return (flags & CH_ATTRS) != 0; } - /// can use the chooser before opening the database? - bool is_noidb() const { return (flags & CH_NOIDB) != 0; } - /// should selection of the already opened non-modal chooser be changed? - bool is_force_default() const { return (flags & CH_FORCE_DEFAULT) != 0; } - /// get number of the built-in chooser - uint get_builtin_number() const - { - return ((flags & CH_BUILTIN_MASK) >> CH_BUILTIN_SHIFT) - 1; - } - /// enable or disable generation of ui_get_chooser_item_attrs events - void set_ask_item_attrs(bool enable) - { - if ( enable ) - flags |= CH_ATTRS; - else - flags &= ~CH_ATTRS; - } - // check chooser version - void check_version(uint32 ver) const { QASSERT(40217, version >= ver); } - // should the quick filter be visible at startup? - bool is_quick_filter_visible_initially() const { return (flags & CH_QFLT) != 0; } - // what mode should the quick filter initially be put in? - int get_quick_filter_initial_mode() const { return flags & CH_QFTYP_MASK; } - // does the chooser have the ability to show a tree view? - bool has_dirtree() const { return (flags & CH_HAS_DIRTREE) != 0; } - - /// initialize the chooser and populate it. - /// \retval false the chooser is empty, do not display it - virtual bool idaapi init() { return true; } - - /// get the number of elements in the chooser - virtual size_t idaapi get_count() const = 0; - - /// get a description of an element. - /// \param[out] cols vector of strings. \n - /// will receive the contents of each column - /// \param[out] icon element's icon id, -1 - no icon - /// \param[out] attrs element attributes - /// \param n element number (0..get_count()-1) - virtual void idaapi get_row( - qstrvec_t *cols, - int *icon_, - chooser_item_attrs_t *attrs, - size_t n) const = 0; - - /// get an address of an element. - /// Used to set breakpoint in any chooser which implements this callback. - /// \param n element number (0-based) - /// \return the effective address, BADADDR if the element has no address - virtual ea_t idaapi get_ea(size_t /*n*/) const { return BADADDR; } - - /// return value of ins(), del(), edit(), enter(), refresh() callbacks - /// - /// If the chooser implements get_dirtree(), and has ins() and/or del() - /// capabilities, the meaning of the returned index(es) combined with - /// ALL_CHANGED and SELECTION_CHANGED must be as follows: - /// - for ins(): the index (in case of a chooser_t, or first index - /// in case of a chooser_multi_t), will be the index of the row - /// that was inserted. - /// - for del(): the index (or indexes in case of a chooser_multi_t), - /// will be the index(es) of the row(s) that was(were) deleted. - enum cbres_t - { - NOTHING_CHANGED, - ALL_CHANGED, - SELECTION_CHANGED, - }; - - /// The chooser window is closed. - virtual void idaapi closed() {} - -protected: - // the default names of the standard handlers are different for the qt- - // and txt-versions of the chooser - void init_popup_names(const char *const default_popup_names[NSTDPOPUPS]) - { - for ( int i = 0; i < NSTDPOPUPS; ++i ) - { - if ( popup_names[i].empty() ) - popup_names[i] = default_popup_names[i]; - } - } -}; - -/// The chooser object without multi-selection. -struct chooser_t : public chooser_base_t -{ - /// Return value of ins(), del(), edit(), enter(), refresh() callbacks - struct cbret_t - { - ssize_t idx; - cbres_t changed; - cbret_t() : idx(NO_SELECTION), changed(NOTHING_CHANGED) {} - cbret_t(ssize_t idx_, cbres_t changed_ = ALL_CHANGED) - : idx(idx_), changed(changed_) {} - }; - - chooser_t(uint32 flags_ = 0, - int columns_ = 0, - const int *widths_ = NULL, - const char *const *header_ = NULL, - const char *title_ = NULL) - : chooser_base_t( - (flags_ & ~CH_MULTI), - columns_, widths_, header_, - title_) {} - - /// Display a generic list chooser and allow the user to select an item. - /// May be overridden in derived choosers. - /// \param deflt default selection or NO_SELECTION - /// see the choose() function below - //lint -sem(chooser_t::choose,custodial(t)) - inline ssize_t choose(ssize_t deflt = 0); - - /// Get the position (index) of the item. - /// A simple chooser considers `item_data` as an index. - /// \param item_data pointer to some data that identifies the item - /// \return idx item index, - /// NO_SELECTION - there is no item with such data - virtual ssize_t idaapi get_item_index(const void *item_data) const newapi - { - // no calculation when `item_data` already is an index - return *(const ssize_t *)item_data; - } - - /// Type of ins(), del(), edit(), enter(), refresh() callbacks - typedef cbret_t (idaapi chooser_t::*cb_t)(size_t n); - - /// User asked to insert an element. - virtual cbret_t idaapi ins(ssize_t /*n*/) newapi { return cbret_t(); } - - /// User deleted an element. - /// \param n index of the element to delete - /// \return idx index of the selected item (cursor) - /// changed what is changed - virtual cbret_t idaapi del(size_t /*n*/) newapi { return cbret_t(); } - - /// User asked to edit an element. - /// \param n index of the element to edit - /// \return idx index of the selected item (cursor) - /// changed what is changed - virtual cbret_t idaapi edit(size_t /*n*/) newapi { return cbret_t(); } //-V524 body is equal to del() - - /// User pressed the enter key. - /// \param n index of the element where was pressed - /// \retval false nothing changed - /// \return idx index of the selected item (cursor) - /// changed what is changed - inline virtual cbret_t idaapi enter(size_t n) newapi - { - cbres_t changed = cbres_t(callui(ui_chooser_default_enter, this, &n).i); - return cbret_t(n, changed); - } - - /// The chooser needs to be refreshed. - /// \param n index of the selected (current) item - /// \return idx new index of the current item - /// (as it may change during refresh) - /// changed what is changed - virtual cbret_t idaapi refresh(ssize_t n) newapi - { - return cbret_t(n, ALL_CHANGED); - } - - /// Selection changed (cursor moved). - /// \note This callback is not supported in the txt-version. - /// \param n index of the new selected item - virtual void idaapi select(ssize_t /*n*/) const newapi {} - - /// get the dirtree_t that will be used to present a tree-like - /// structure to the user (see CH_HAS_DIRTREE) - /// \return the dirtree_t, or NULL - virtual dirtree_t *idaapi get_dirtree() newapi { return NULL; } - - /// Map an item index to a dirtree_t inode - /// This is necessary only if CH_HAS_DIRTREE is specified - /// \param n index of the item - /// \return the inode number - virtual inode_t idaapi index_to_inode(size_t /*n*/) const newapi { return inode_t(BADADDR); } - -protected: - ssize_t new_sel_after_del(size_t n) const - { - size_t cnt = get_count(); - // assert: n < cnt - return n + 1 < cnt - ? n + 1 - : n - 1; // the last item deleted => no selection - } - ssize_t adjust_last_item(size_t n) const - { - size_t cnt = get_count(); - if ( cnt == 0 ) - return NO_SELECTION; - // take in account deleting of the last item(s) - return n < cnt ? n : cnt - 1; - } -}; - -/// The chooser object with multi-selection. -struct chooser_multi_t : public chooser_base_t -{ - chooser_multi_t( - uint32 flags_ = 0, - int columns_ = 0, - const int *widths_ = NULL, - const char *const *header_ = NULL, - const char *title_ = NULL) - : chooser_base_t( - flags_ | CH_MULTI, - columns_, widths_, header_, - title_) {} - - /// Display a generic list chooser and allow the user to select an item. - /// May be overridden in derived choosers. - /// \param deflt default selection (may be empty) - /// see the choose() function below - //lint -sem(chooser_multi_t::choose,custodial(t)) - inline ssize_t choose(const sizevec_t &deflt = sizevec_t()); - - /// Get the positions of the items. - /// A simple chooser considers `item_data` as a list of indexes. - /// \param[in,out] sel items indexes - /// \param item_data pointer to some data that identifies the items - virtual void idaapi get_item_index( - sizevec_t *sel, - const void *item_data) const newapi - { - // no calculation when `item_data` already is a vector - *sel = *(const sizevec_t *)item_data; - } - - /// Type of ins(), del(), edit(), enter(), refresh() callbacks - typedef cbres_t (idaapi chooser_multi_t::*cb_t)(sizevec_t *sel); - - /// User asked to insert an element. - virtual cbres_t idaapi ins(sizevec_t * /*sel*/) newapi - { - return NOTHING_CHANGED; - } - - /// User deleted elements. - /// \param[in,out] sel selected items - /// \return what is changed - virtual cbres_t idaapi del(sizevec_t * /*sel*/) newapi - { - return NOTHING_CHANGED; - } - - /// User asked to edit an element. - /// \param[in,out] sel selected items - /// \return what is changed - virtual cbres_t idaapi edit(sizevec_t * /*sel*/) newapi - { - return NOTHING_CHANGED; - } - - /// User pressed the enter key. - /// \param[in,out] sel selected items - /// \return what is changed - virtual cbres_t idaapi enter(sizevec_t *sel) newapi - { - return cbres_t(callui(ui_chooser_default_enter, this, sel).i); - } - - /// The chooser needs to be refreshed. - /// It returns the new positions of the selected items. - /// \param[in,out] sel selected items - /// \return what is changed - virtual cbres_t idaapi refresh(sizevec_t * /*sel*/) newapi - { - return ALL_CHANGED; - } - - /// Selection changed - /// \note This callback is not supported in the txt-version. - /// \param sel new selected items - virtual void idaapi select(const sizevec_t &/*sel*/) const newapi {} - - /// get the dirtree_t that will be used to present a tree-like - /// structure to the user (see CH_HAS_DIRTREE) - /// \return the dirtree_t, or NULL - virtual dirtree_t *idaapi get_dirtree() newapi { return NULL; } - - /// Map an item index to a dirtree_t inode - /// This is necessary only if CH_HAS_DIRTREE is specified - /// \param n index of the item - /// \return the inode number - virtual inode_t idaapi index_to_inode(size_t /*n*/) const newapi - { - return inode_t(BADADDR); - } - -protected: - // used in the del() callback to iterate - static bool next_item_to_del(sizevec_t *sel); - ssize_t new_sel_after_del(const sizevec_t &sel) const; - void adjust_last_item(sizevec_t *sel, size_t n) const; -}; - - -/// Multi line text control, used to embed a text control in a form -struct textctrl_info_t -{ - size_t cb; ///< size of this structure - qstring text; ///< in, out: text control value - uint16 flags; ///< \ref TXTF_ -/// \defgroup TXTF_ Text control property bits -/// used by textctrl_info_t::flags -//@{ -#define TXTF_AUTOINDENT 0x0001 ///< auto-indent on new line -#define TXTF_ACCEPTTABS 0x0002 ///< Tab key inserts 'tabsize' spaces -#define TXTF_READONLY 0x0004 ///< text cannot be edited (but can be selected and copied) -#define TXTF_SELECTED 0x0008 ///< shows the field with its text selected -#define TXTF_MODIFIED 0x0010 ///< gets/sets the modified status -#define TXTF_FIXEDFONT 0x0020 ///< the control uses IDA's fixed font -#define TXTF_LINENUMBERS 0x0040 ///< the text editor widget should display line numbers -//@} - uint16 tabsize; ///< how many spaces a single tab will indent - textctrl_info_t(): cb(sizeof(textctrl_info_t)), flags(0), tabsize(0) {} ///< Constructor -}; - -/// \defgroup choosers Functions: generic list choosers -/// These functions display a window that allows the user to select items -//@{ - - -/// Display a generic list chooser (n-column) and allow the user to select -/// an item. -/// The closed() callback will be called when the window is closed. -/// In addition, after the window is closed, the chooser instance -/// will be delete()d unless CH_KEEP is specified (useful for global, or -/// stack-allocated chooser instances, that must not be deleted.) -/// \param def_item pointer to some data that identifies the default item -/// For modal choosers: -/// \return the index of the selected item (0-based) -/// \retval chooser_base_t::NO_SELECTION the user refused to choose -/// anything (pressed Esc). -/// \retval chooser_base_t::EMPTY_CHOOSER the chooser was not created -/// because the init() callback has returned 'false' -/// For non-modal choosers: -/// \retval 0 the chooser was created successfully -/// \retval chooser_base_t::ALREADY_EXISTS did not open a new chooser -/// because a chooser with the same object is already open. If -/// CH_FORCE_DEFAULT is set, the cursor of the chooser will be -/// positioned to the new item. - -//lint -sem(choose,custodial(1)) -ssize_t choose(chooser_base_t *ch, const void *def_item); - -inline ssize_t chooser_t::choose(ssize_t deflt) -{ - // chooser uses the default implementation of the get_item_index() - // callback - return ::choose(this, &deflt); -} - -inline ssize_t chooser_multi_t::choose(const sizevec_t &deflt) -{ - // chooser uses the default implementation of the get_item_index() - // callback - return ::choose(this, &deflt); -} - -//@} - -#endif // SWIG - -/// \defgroup add_chooser_command Obsolete add_chooser_command() -//@{ -/// single selection chooser callback -typedef chooser_t::cbret_t idaapi chooser_cb_t( - chooser_t *chobj, - ssize_t n); -/// multi selection chooser callback -typedef chooser_base_t::cbres_t idaapi chooser_multi_cb_t( - chooser_multi_t *chobj, - sizevec_t *sel); - -/// Flags -#define CHOOSER_NO_SELECTION 0x01 - ///< enable even if there's no selected item. - ///< `n` will be NO_SELECTION for a callback. -#define CHOOSER_MULTI_SELECTION 0x02 - ///< enable for multiple selections. - ///< A callback of type `chooser_multi_cb_t` will - ///< be called for all selected items. -#define CHOOSER_POPUP_MENU 0x04 - ///< Add command to the popup menu. - -//------------------------------------------------------------------------- -/// Values of the `menu_index` parameter -#define CHOOSER_MENU_EDIT 0 ///< Obsolete. Please don't use -#define CHOOSER_MENU_JUMP 1 ///< Obsolete. Please don't use -#define CHOOSER_MENU_SEARCH 2 ///< Obsolete. Please don't use -//@} - -//------------------------------------------------------------------------- -enum navaddr_type_t -{ - nat_lib = 0, - nat_fun, - nat_cod, - nat_dat, - nat_und, - nat_ext, - nat_err, - nat_gap, - nat_cur, - nat_auto, // auto-analysis cursor color - nat_lum, // related to lumina - nat_last -}; - -/// Navigation band colorizer function. -/// -/// If ea==BADADDR, then 'nbytes' is a navaddr_type_t, and the colorizer -/// is in charge of returning the color associated to that type of address. -/// This is used for maintaining the legend in-sync with the colors used to -/// display the addresses in the navigation bar. -/// -/// \param ea address to calculate the color of, or BADADDR (see above) -/// \param nbytes number of bytes, this can be ignored for quick&dirty approach -/// \param ud user data -/// \return color of the specified address in RGB - -typedef uint32 idaapi nav_colorizer_t(ea_t ea, asize_t nbytes, void *ud); - - -/// Install new navigation band colorizer (::ui_set_nav_colorizer). - -inline void set_nav_colorizer( - nav_colorizer_t **out_was_func, - void **out_was_ud, - nav_colorizer_t *func, - void *ud) -{ - callui(ui_set_nav_colorizer, out_was_func, out_was_ud, func, ud); -} - -/// Custom viewer & code viewer handler types -enum custom_viewer_handler_id_t -{ - CVH_USERDATA, - CVH_KEYDOWN, ///< see ::custom_viewer_keydown_t - CVH_POPUP, ///< see ::custom_viewer_popup_t - CVH_DBLCLICK, ///< see ::custom_viewer_dblclick_t - CVH_CURPOS, ///< see ::custom_viewer_curpos_t - CVH_CLOSE, ///< see ::custom_viewer_close_t - CVH_CLICK, ///< see ::custom_viewer_click_t - CVH_QT_AWARE, ///< see set_custom_viewer_qt_aware() - CVH_HELP, ///< see ::custom_viewer_help_t - CVH_MOUSEMOVE, ///< see ::custom_viewer_mouse_moved_t - - CDVH_USERDATA = 1000, ///< see set_code_viewer_user_data() - CDVH_SRCVIEW, ///< see set_code_viewer_is_source() - CDVH_LINES_CLICK, ///< see ::code_viewer_lines_click_t - CDVH_LINES_DBLCLICK, ///< see ::code_viewer_lines_click_t - CDVH_LINES_POPUP, ///< see ::code_viewer_lines_click_t - CDVH_LINES_DRAWICON, ///< see ::code_viewer_lines_icon_t - CDVH_LINES_LINENUM, ///< see ::code_viewer_lines_linenum_t - CDVH_LINES_ICONMARGIN, ///< see set_code_viewer_lines_icon_margin() - CDVH_LINES_RADIX, ///< see set_code_viewer_lines_radix() - CDVH_LINES_ALIGNMENT ///< see set_code_viewer_lines_alignment() -}; - -//------------------------------------------------------------------------- -/// state & 1 => Shift is pressed \n -/// state & 2 => Alt is pressed \n -/// state & 4 => Ctrl is pressed \n -/// state & 8 => Mouse left button is pressed \n -/// state & 16 => Mouse right button is pressed \n -/// state & 32 => Mouse middle button is pressed \n -/// state & 128 => Meta is pressed (OSX only) -#define VES_SHIFT (1 << 0) -#define VES_ALT (1 << 1) -#define VES_CTRL (1 << 2) -#define VES_MOUSE_LEFT (1 << 3) -#define VES_MOUSE_RIGHT (1 << 4) -#define VES_MOUSE_MIDDLE (1 << 5) -#define VES_META (1 << 7) -typedef int view_event_state_t; - -//------------------------------------------------------------------------- -/// Notification codes for events in the message window -enum msg_notification_t -{ - msg_activated, ///< The message window is activated. - ///< \param none - ///< \return void - - msg_deactivated, ///< The message window is deactivated. - ///< \param none - ///< \return void - - msg_click, ///< Click event. - ///< \param x (int) x-coordinate - ///< \param y (int) y-coordinate - ///< \param state (::view_event_state_t) - ///< \retval 1 handled - ///< \retval 0 not handled (invoke default handler) - - msg_dblclick, ///< Double click event. - ///< \param x (int) x-coordinate - ///< \param y (int) y-coordinate - ///< \param state (::view_event_state_t) - ///< \retval 1 handled - ///< \retval 0 not handled (invoke default handler) - - msg_closed, ///< View closed. - ///< \param none - ///< \return void - - msg_keydown, ///< Key down event. - ///< \param key (int) - ///< \param state (::view_event_state_t) - ///< \retval 1 handled - ///< \retval 0 not handled (invoke default handler) -}; - -//------------------------------------------------------------------------- -/// Information about a position relative to the renderer -struct renderer_pos_info_t -{ - /// Constructor - renderer_pos_info_t() : node(-1), cx(-1), cy(-1), sx(-1) {} - - int node; ///< the node, or -1 if the current renderer - ///< is not a graph renderer. - - short cx; ///< the X coords of the character in the current line. - ///< When in graph mode: X coords of the character in 'node'. \n - ///< When in flat mode: X coords of the character in the line, w/o \n - ///< taking scrolling into consideration. - - short cy; ///< the Y coords of the character. - ///< When in graph mode: Y coords of the character in 'node'. \n - ///< When in flat mode: Line number, starting from the top. - - short sx; ///< the number of chars that are scrolled (flat mode only) - - bool operator == (const renderer_pos_info_t &r) const - { return node == r.node && cx == r.cx && cy == r.cy && sx == r.sx; } - bool operator != (const renderer_pos_info_t &r) const - { return !(*this == r); } -}; - -//------------------------------------------------------------------------- -struct selection_item_t; - -//------------------------------------------------------------------------- -/// Abstraction of location in flat view/graph views -/// (out of 'view_mouse_event_t' to make it easy for SWiG to wrap) -union view_mouse_event_location_t -{ - ea_t ea; ///< flat view (rtype == ::TCCRT_FLAT) - const selection_item_t *item; ///< graph views (rtype != ::TCCRT_FLAT). - ///< NULL if mouse is not currently over an item. -}; - - -/// Information about a mouse action within a view -struct view_mouse_event_t -{ - tcc_renderer_type_t rtype; ///< type of renderer that received the event - - uint32 x; ///< screen x coordinate - uint32 y; ///< screen y coordinate - - typedef view_mouse_event_location_t location_t; - location_t location; ///< location where event was generated - - view_event_state_t state; ///< contains information about what buttons are CURRENTLY pressed - ///< on the keyboard and mouse. view_mouse_event_t instances created - ///< in functions like mouseReleaseEvent() won't contain any information - ///< about the mouse, because it has been released. - - vme_button_t button; ///< represents which mouse button was responsible for generating the event. - ///< This field does not care about the current state of the mouse. - - renderer_pos_info_t renderer_pos; ///< position where event was generated, relative to the renderer -}; - -//------------------------------------------------------------------------- -/// Notification codes sent by the UI for IDAView or custom viewer events. -/// These notification codes should be used together with ::HT_VIEW hook type. -enum view_notification_t -{ - view_activated, ///< A view is activated - ///< \param view (TWidget *) - - view_deactivated, ///< A view is deactivated - ///< \param view (TWidget *) - - view_keydown, ///< Key down event - ///< \param view (TWidget *) - ///< \param key (int) - ///< \param state (::view_event_state_t) - - view_click, ///< Click event - ///< \param view (TWidget *) - ///< \param event (const ::view_mouse_event_t *) - - view_dblclick, ///< Double click event - ///< \param view (TWidget *) - ///< \param event (const ::view_mouse_event_t *) - - view_curpos, ///< Cursor position changed - ///< \param view (TWidget *) - - view_created, ///< A view is being created. - ///< \param view (TWidget *) - - view_close, ///< View closed - ///< \param view (TWidget *) - - view_switched, ///< A view's renderer has changed. - ///< \param view (TWidget *) - ///< \param rt (::tcc_renderer_type_t) - - view_mouse_over, ///< The user moved the mouse over (or out of) a node or an edge. - ///< This is only relevant in a graph view. - ///< \param view (TWidget *) - ///< \param event (const ::view_mouse_event_t *) - - view_loc_changed, ///< The location for the view has changed (can be either - ///< the place_t, the renderer_info_t, or both.) - ///< \param view (TWidget *) - ///< \param now (const lochist_entry_t *) - ///< \param was (const lochist_entry_t *) - - view_mouse_moved, ///< The mouse moved on the view - ///< \param view (TWidget *) - ///< \param event (const ::view_mouse_event_t *) -}; - -#ifndef SWIG - -/// The user has pressed a key - -typedef bool idaapi custom_viewer_keydown_t(TWidget *cv, int vk_key, int shift, void *ud); - - -/// The user right clicked. See ::ui_populating_widget_popup, too. - -typedef void idaapi custom_viewer_popup_t(TWidget *cv, void *ud); - - -/// The user moved the mouse. - -typedef void idaapi custom_viewer_mouse_moved_t(TWidget *cv, int shift, view_mouse_event_t *e, void *ud); - - -/// The user clicked - -typedef bool idaapi custom_viewer_click_t(TWidget *cv, int shift, void *ud); - - -/// The user double clicked - -typedef bool idaapi custom_viewer_dblclick_t(TWidget *cv, int shift, void *ud); - - -/// Deprecated. -/// -/// See custom_viewer_location_changed_t for a more -/// competent, and general solution. - -typedef void idaapi custom_viewer_curpos_t(TWidget *cv, void *ud); - - -/// Custom viewer is being destroyed - -typedef void idaapi custom_viewer_close_t(TWidget *cv, void *ud); - - -/// Custom viewer: the user pressed F1 -/// If the return value != -1, it is treated as a help context to display (from ida.hlp) - -typedef int idaapi custom_viewer_help_t(TWidget *cv, void *ud); - - -/// Fine-tune 'loc->place()' according to the X position (i.e., 'loc->renderer_info().pos.cx') -/// -/// You can consider that the place_t object is a 'row cursor' in the -/// list of lines that fill the screen. But, it is only a 'vertical' -/// cursor: e.g., the simpleline_place_t has the 'n' mumber, which -/// specifies what line the place_t corresponds to, in the backing -/// strvec_t instance. -//// -/// However, some views have a place that can be sensitive to the X -/// coordinates of the view's cursor. Think of the "Hex View-1", or -/// the "Pseudocode-A" views: when moving the cursor on the X axis, -/// the 'row cursor' will not change (since we are moving on the same -/// line), but the corresponding 'ea_t' might. -/// -/// For such tricky situations, we provide the following callback, that -/// will provide the ability to update the 'loc->place()'s internal state -/// according to 'loc->renderer_info().pos.cx' so -/// that it really reflects the current cursor position. -/// Most custom viewers will not need to implement this, but if some data -/// in your place_t instances is dependent upon the X coordinate of the -/// cursor, you'll probably want to. -/// -/// Called whenever the user moves the cursor around (mouse, keyboard) -/// -/// Note: this callback should only ever read 'loc->renderer_info()', -/// not modify it. Doing so will result in undefined behavior. - -typedef void idaapi custom_viewer_adjust_place_t(TWidget *v, lochist_entry_t *loc, void *ud); - - -/// Does the line pointed to by pline include pitem, and if so at what X coordinate? -/// -/// place_t instances can be considered as a 'cursor' in a set of lines (see -/// custom_viewer_adjust_place_t), but they can be 'tuned' to -/// correctly represent the current position (e.g., hexrays decompiler plugins -/// tune its place_t instances so they contain the real, current 'ea_t', that -/// corresponds to the C-like expression that's shown at the X coordinate -/// within that line.) -/// -/// But then, when the viewer has to determine whether a certain twinline_t -/// in fact displays the current place, the sublcass's implementation of -/// place_t::compare() might lead it to think that the current twinline_t's -/// place_t is not correct (e.g., because the 'ea_t' has been fine-tuned -/// according to the caret's X coordinates.) -/// -/// Thus, if your plugin implements custom_viewer_adjust_place_t, -/// you probably want to implement this as well, or refreshes might be -/// unnecessarily frequent, leading to a worse user experience. -/// -/// This is typically called when the user moves the cursor around. -/// return -/// -1 if pitem is not included in pline -/// -2 pitem points to the entire line -/// >= 0 for the X coordinate within the pline, where pitem points - -typedef int idaapi custom_viewer_get_place_xcoord_t(TWidget *v, const place_t *pline, const place_t *pitem, void *ud); - - -enum locchange_reason_t -{ - lcr_unknown, - lcr_goto, - lcr_user_switch, // user pressed - lcr_auto_switch, // automatic switch - lcr_jump, - lcr_navigate, // navigate back & forward - lcr_scroll, // user used scrollbars - lcr_internal, // misc. other reasons -}; - -#define LCMD_SYNC (1 << 0) -class locchange_md_t // location change metadata -{ -protected: - uchar cb; - uchar r; - uchar f; - uchar reserved; - -public: - locchange_md_t(locchange_reason_t _reason, bool _sync) - : cb(sizeof(*this)), r(uchar(_reason)), f(_sync ? LCMD_SYNC : 0), reserved(0) {} - locchange_reason_t reason() const { return locchange_reason_t(r); } - bool is_sync() const { return (f & LCMD_SYNC) != 0; } -}; -CASSERT(sizeof(locchange_md_t) == sizeof(uint32)); -DECLARE_TYPE_AS_MOVABLE(locchange_md_t); - -/// The user asked to navigate to the given location. -/// -/// This gives the view the possibility of declining the move. -/// Reasons for this can be: -/// - the location cannot be displayed, -/// - going there requires a long-running operation, that can be -/// canceled by the user (e.g., in case of the hexrays plugins: -/// during decompilation of the target function.) -/// - ... -/// -/// This is called before the new location is committed to the view's history. -/// -/// return -/// 0 if the move is accepted -/// != 0 otherwise - -typedef int idaapi custom_viewer_can_navigate_t( - TWidget *v, - const lochist_entry_t *now, - const locchange_md_t &md, - void *ud); - - -/// The viewer's location (i.e., place, or cursor) changed. - -typedef void idaapi custom_viewer_location_changed_t( - TWidget *v, - const lochist_entry_t *was, - const lochist_entry_t *now, - const locchange_md_t &md, - void *ud); - - -// Code viewer handlers for the lineinfo widget located to the left of the text. - -/// The user clicked, right clicked or double clicked. -/// pos: the clicked icon number. -1 means the click occurred on space not reserved to icons. - -typedef void idaapi code_viewer_lines_click_t(TWidget *c, const place_t *p, int pos, int shift, void *ud); - - -/// Icon drawing. -/// \param pos the icon number, will be 0,1,2,3... \n -/// can be modified to skip positions and draw at the specified one -/// \return the id of the icon to draw. If bitwise or'ed with 0x80000000, -/// IDA calls this function once more with pos+1 to retrieve one more icon. - -typedef int idaapi code_viewer_lines_icon_t(TWidget *cv, const place_t *p, int *pos, void *ud); - - -/// Calculate the line number. Return false to not print any number. - -typedef bool idaapi code_viewer_lines_linenum_t(TWidget *cv, const place_t *p, uval_t *num, void *ud); - -#endif // SWIG - -//------------------------------------------------------------------------ - -/// Command line interpreter. -/// Provides functionality for the command line (located at the bottom of the main window). -/// Only GUI version of IDA supports CLIs. -struct cli_t -{ - size_t size; ///< size of this structure - int32 flags; ///< \ref CLIF_ -/// \defgroup CLIF_ CLI attributes -/// used by cli_t::flags -//@{ -#define CLIF_QT_AWARE 1 ///< keydown event will use Qt key codes -//@} - const char *sname; ///< short name (displayed on the button) - const char *lname; ///< long name (displayed in the menu) - const char *hint; ///< hint for the input line - - /// Callback: the user pressed Enter. - /// CLI is free to execute the line immediately or ask for more lines. - /// \param line command to execute (utf-8-encoded) - /// \retval true executed line - /// \retval false ask for more lines - bool (idaapi *execute_line)(const char *line); - - void *unused; - - /// Callback: a keyboard key has been pressed. - /// This callback is optional. - /// It is a generic callback and the CLI is free to do whatever it wants. - /// \param line current input line (in/out argument) - /// \param p_x pointer to current x coordinate of the cursor (in/out) - /// \param p_sellen pointer to current selection length (usually 0) - /// \param p_vk_key pointer to virtual key code (in/out). - /// if the key has been handled, it should be reset to 0 by CLI - /// \param shift shift state - /// \retval true modified input line or x coordinate or selection length - /// \retval false otherwise - bool (idaapi *keydown)( - qstring *line, - int *p_x, - int *p_sellen, - int *p_vk_key, - int shift); - - /// Callback: the user pressed Tab/Shift+Tab. - /// This callback is optional. - /// \param[out] out_completions results of completion - /// \param[out] out_match_start the codepoint index in the line, where match starts - /// \param[out] out_match_end the codepoint index in the line, where ends ends - /// \param line command line - /// \param x codepoint index of the cursor in line - /// \retval true got results - /// \retval false otherwise - bool (idaapi *find_completions)( - qstrvec_t *out_completions, - int *out_match_start, - int *out_match_end, - const char *line, - int x); -}; - -//--------------------------------------------------------------------------- -/// \defgroup MFF_ Exec request flags -/// passed as 'reqf' parameter to execute_sync() -//@{ -#define MFF_FAST 0x0000 ///< Execute code as soon as possible. - ///< this mode is ok for calling ui related functions - ///< that do not query the database. - -#define MFF_READ 0x0001 ///< Execute code only when ida is idle and it is safe - ///< to query the database. - ///< this mode is recommended only - ///< for code that does not modify the database. - ///< (nb: ida may be in the middle of executing - ///< another user request, for example it may be waiting - ///< for him to enter values into a modal dialog box) - -#define MFF_WRITE 0x0002 ///< Execute code only when ida is idle and it is safe - ///< to modify the database. in particular, - ///< this flag will suspend execution if there is - ///< a modal dialog box on the screen - ///< this mode can be used to call any ida api function - ///< #MFF_WRITE implies #MFF_READ - -#define MFF_NOWAIT 0x0004 ///< Do not wait for the request to be executed. - ///< the caller should ensure that the request is not - ///< destroyed until the execution completes. - ///< if not, the request will be ignored. - ///< the request must be created using the 'new' operator - ///< to use it with this flag. - ///< it can be used in cancel_exec_request(). - ///< This flag can be used to delay the code execution - ///< until the next UI loop run even from the main thread. -//@} - - -/// Execute code in the main thread - to be used with execute_sync(). -struct exec_request_t -{ - /// Internal magic - enum { MFF_MAGIC = 0x12345678 }; - - /// Can this request be executed? - bool valid(void) const - { - return (code & ~7) == MFF_MAGIC && (sem != NULL || (code & MFF_NOWAIT) != 0); - } - - int code; ///< temporary location, used internally - - qsemaphore_t sem; ///< semaphore to communicate with the main thread. - ///< If NULL, will be initialized by execute_sync(). - - /// Callback to be executed. - /// If this function raises an exception, execute_sync() never returns. - virtual int idaapi execute(void) = 0; - - /// Constructor - exec_request_t(void) : code(0), sem(NULL) {} - - /// Destructor - // FIXME: windows: gcc compiled plugins cannot use exec_request_t because the destructor - // is generated differently! - virtual ~exec_request_t(void) { qsem_free(sem); sem = NULL; code = 0; } -}; - -//--------------------------------------------------------------------------- -/// Base class for defining UI requests. -/// Override the run() method and insert your code. -class ui_request_t -{ -public: - /// Run the UI request - /// \retval false remove the request from the queue - /// \retval true reschedule the request and run it again - virtual bool idaapi run() = 0; - DEFINE_VIRTUAL_DTOR(ui_request_t); -}; - -/// List of UI requests. The ui_request_t is allocated by the caller -/// but its ownership is transferred to the execute_ui_requests(). -/// The ui_request_t instance will be deleted as soon as it is executed and -/// was not rescheduled for another run. -class ui_requests_t : public qlist -{ - DECLARE_UNCOPYABLE(ui_requests_t) -public: - ui_requests_t() {} ///< Constructor - ~ui_requests_t() ///< Destructor - { - for ( iterator p=begin(); p != end(); ++p ) - delete *p; - } -}; - -/// Snapshot restoration completion callback. see restore_database_snapshot() -typedef void idaapi ss_restore_cb_t(const char *errmsg, void *ud); - -/// \defgroup UIJMP_ Jump flags -/// passed as 'uijmp_flags' parameter to jumpto() -//@{ -#define UIJMP_ACTIVATE 0x0001 ///< activate the new window -#define UIJMP_DONTPUSH 0x0002 ///< do not remember the current address - ///< in the navigation history -#define UIJMP_VIEWMASK 0x000C -#define UIJMP_ANYVIEW 0x0000 ///< jump in any ea_t-capable view -#define UIJMP_IDAVIEW 0x0004 ///< jump in idaview -#define UIJMP_IDAVIEW_NEW 0x0008 ///< jump in new idaview -//@} - -struct screen_graph_selection_t; -struct dirtree_selection_t; -typedef uval_t const_t; - -//------------------------------------------------------------------------- -/// Maintain information about the current state of the UI. -/// This allows actions to behave appropriately (see ::action_handler_t) -struct action_ctx_base_t -{ - /// Constructor - action_ctx_base_t() - { - cur_sel.from.at = NULL; - cur_sel.to.at = NULL; - reset(); - } - -/// \defgroup ACF_ Action context property bits -/// used by action_ctx_base_t::cur_flags -//@{ -#define ACF_HAS_SELECTION 1 << 0 ///< there is currently a valid selection -#define ACF_XTRN_EA 1 << 1 ///< cur_ea is in 'externs' segment -#define ACF_HAS_FIELD_DIRTREE_SELECTION 1 << 2 ///< 'cur_enum_member' and 'dirtree_selection' fields are present -//@} - - /// Invalidate all context info - void reset() - { - widget = NULL; - widget_type = BWN_UNKNOWN; - widget_title.clear(); - chooser_selection.clear(); - action = NULL; - - // - cur_flags = ACF_HAS_FIELD_DIRTREE_SELECTION; - cur_ea = BADADDR; - cur_value = BADADDR; - cur_func = cur_fchunk = NULL; - cur_struc = NULL; cur_strmem = NULL; - cur_enum = enum_t(-1); - cur_seg = NULL; - - cur_sel.from.at = NULL; - cur_sel.from.x = -1; - cur_sel.to.at = NULL; - cur_sel.to.x = -1; - - regname = NULL; - focus = NULL; - graph_selection = NULL; - cur_enum_member = const_t(-1); - dirtree_selection = NULL; - } - TWidget *widget; - twidget_type_t widget_type; ///< type of current widget - qstring widget_title; ///< title of current widget - sizevec_t chooser_selection; ///< current chooser selection (0-based) - const char *action; ///< action name - - uint32 cur_flags; ///< Current address information. see \ref ACF_ - - /// Check if the given flag is set - inline bool has_flag(uint32 flag) const { return (cur_flags & flag) == flag; } - - ea_t cur_ea; ///< the current EA of the position in the view - uval_t cur_value; ///< the possible address, or value the cursor is positioned on - - func_t *cur_func; ///< the current function - func_t *cur_fchunk; ///< the current function chunk - - struc_t *cur_struc; ///< the current structure - member_t *cur_strmem; ///< the current structure member - - enum_t cur_enum; ///< the current enum - - segment_t *cur_seg; ///< the current segment - - struct - { - twinpos_t from; ///< start of selection - twinpos_t to; ///< end of selection - } cur_sel; ///< the currently selected range. also see #ACF_HAS_SELECTION - - const char *regname; ///< register name (if widget_type == BWN_CPUREGS and context menu opened on register) - - TWidget *focus; ///< The focused widget in case it is not the 'form' itself (e.g., the 'quick filter' input in choosers.) - - screen_graph_selection_t *graph_selection; ///< the current graph selection (if in a graph view) - const_t cur_enum_member; - - dirtree_selection_t *dirtree_selection; ///< the current dirtree_t selection (if applicable) -}; - -//------------------------------------------------------------------------- -/// Instances of this class will be filled with information that is -/// commonly used by actions when they need to -/// be activated. This is so they don't have to perform (possibly) -/// costly operations more than once. -typedef action_ctx_base_t action_activation_ctx_t; - -//------------------------------------------------------------------------- -/// Instances of this class will be filled with information that is -/// commonly used by actions when they need to -/// update. This is so they don't have to perform (possibly) -/// costly operations more than once. -typedef action_ctx_base_t action_update_ctx_t; - -#define AHF_VERSION 1 ///< action handler version (used by action_handler_t::flags) -#define AHF_VERSION_MASK 0xFF ///< mask for action_handler_t::flags - -//------------------------------------------------------------------------- -/// Action states - returned by action_handler_t::update() -enum action_state_t -{ - AST_ENABLE_ALWAYS, ///< enable action and do not call action_handler_t::update() anymore - - AST_ENABLE_FOR_IDB, ///< enable action for the current idb. - ///< call action_handler_t::update() when a database is opened/closed - - AST_ENABLE_FOR_WIDGET, ///< enable action for the current widget. - ///< call action_handler_t::update() when a widget gets/loses focus - - AST_ENABLE, ///< enable action - call action_handler_t::update() when anything changes - - AST_DISABLE_ALWAYS, ///< disable action and do not call action_handler_t::action() anymore - AST_DISABLE_FOR_IDB, ///< analog of ::AST_ENABLE_FOR_IDB - AST_DISABLE_FOR_WIDGET, ///< analog of ::AST_ENABLE_FOR_WIDGET - AST_DISABLE, ///< analog of ::AST_ENABLE -}; - - -/// Check if the given action state is one of AST_ENABLE* - -inline bool is_action_enabled(action_state_t s) -{ - return s <= AST_ENABLE; -} - -//------------------------------------------------------------------------- -/// Manages the behavior of a registered action -struct action_handler_t -{ - int flags; ///< internal - for version management - - /// Constructor - action_handler_t(int _f = 0) : flags(_f) { flags |= AHF_VERSION; } - - /// Activate an action. - /// This function implements the core behavior of an action. - /// It is called when the action is triggered, from a menu, from - /// a popup menu, from the toolbar, or programmatically. - /// \returns non-zero: all IDA windows will be refreshed - virtual int idaapi activate(action_activation_ctx_t *ctx) = 0; - - /// Update an action. - /// This is called when the context of the UI changed, and we need to let the - /// action update some of its properties if needed (label, icon, ...) - /// - /// In addition, this lets IDA know whether the action is enabled, - /// and when it should be queried for availability again. - /// - /// Note: This callback is not meant to change anything in the - /// application's state, except by calling one (or many) of - /// the "update_action_*()" functions on this very action. - virtual action_state_t idaapi update(action_update_ctx_t *ctx) = 0; - - /// Destructor - virtual ~action_handler_t() {} -}; - -/// Describe an action to be registered (see register_action()) -struct action_desc_t -{ - int cb; ///< size of this structure - const char *name; ///< the internal name of the action; must be unique. - ///< a way to reduce possible conflicts is to prefix it - ///< with some specific prefix. E.g., "myplugin:doSthg". - - const char *label; ///< the label of the action, possibly with an accelerator - ///< key definition (e.g., "~J~ump to operand") - - action_handler_t *handler; ///< the action handler, for activating/updating. - ///< please read the comments at register_action(). - - const void *owner; ///< either the plugin_t, or plugmod_t responsible for - ///< registering the action. Can be NULL - ///< Please see \ref ACTION_DESC_LITERAL_PLUGMOD - - const char *shortcut; ///< an optional shortcut definition. E.g., "Ctrl+Enter" - const char *tooltip; ///< an optional tooltip for the action - int icon; ///< an optional icon ID to use - -/// \defgroup ADF_ Action flags -/// used by register_action(). The upper 16 bits are reserved. -//@{ -#define ADF_OWN_HANDLER 0x01 ///< handler is owned by the action; it'll be - ///< destroyed when the action is unregistered. - ///< You shouldn't have to use this. -#define ADF_NO_UNDO 0x02 ///< the action does not create an undo point. - ///< useful for actions that do not modify the database. -#define ADF_OT_MASK 0x0C ///< Owner type mask -#define ADF_OT_PLUGIN 0x00 ///< Owner is a plugin_t -#define ADF_OT_PLUGMOD 0x04 ///< Owner is a plugmod_t -#define ADF_OT_PROCMOD 0x08 ///< Owner is a procmod_t -#define ADF_GLOBAL 0x10 ///< Register the action globally, so that it's - ///< available even if no IDB is present -#define ADF_NO_HIGHLIGHT 0x20 ///< After activating, do not update the highlight - ///< according to what's under the cursor (listings only.) -//@} - int flags; ///< See \ref ADF_ -}; - -/// Get an ::action_desc_t instance with the provided plugmod_t as the owner -/// This is meant for plugins -#define ACTION_DESC_LITERAL_PLUGMOD(name, label, handler, plgmod, shortcut, tooltip, icon) \ - { sizeof(action_desc_t), name, label, handler, plgmod, shortcut, tooltip, icon, ADF_OT_PLUGMOD } - -/// Get an ::action_desc_t instance with the provided procmod_t as the owner -/// This is meant for processor modules implementing processor_t::ev_get_procmod -#define ACTION_DESC_LITERAL_PROCMOD(name, label, handler, prcmod, shortcut, tooltip, icon) \ - { sizeof(action_desc_t), name, label, handler, prcmod, shortcut, tooltip, icon, ADF_OT_PROCMOD } - -/// Get an ::action_desc_t instance with a given owner and flags -#define ACTION_DESC_LITERAL_OWNER(name, label, handler, owner, shortcut, tooltip, icon, flags) \ - { sizeof(action_desc_t), name, label, handler, owner, shortcut, tooltip, icon, flags } - -/// For attach_dynamic_action_to_popup() only -#define DYNACTION_DESC_LITERAL(label, handler, shortcut, tooltip, icon) \ - { sizeof(action_desc_t), NULL, label, handler, NULL, shortcut, tooltip, icon, ADF_OWN_HANDLER } - -/// Codes for getting/setting action attributes -enum action_attr_t -{ - AA_NONE, ///< no effect - AA_LABEL, ///< see update_action_label() - AA_SHORTCUT, ///< see update_action_shortcut() - AA_TOOLTIP, ///< see update_action_tooltip() - AA_ICON, ///< see update_action_icon() - AA_STATE, ///< see update_action_state() - AA_CHECKABLE, ///< see update_action_checkable() - AA_CHECKED, ///< see update_action_checked() - AA_VISIBILITY, ///< see update_action_visibility() -}; - -#ifndef SWIG -// Handlers to be used with create_custom_viewer() -class custom_viewer_handlers_t -{ - int cb; -public: - custom_viewer_handlers_t( - custom_viewer_keydown_t *_keyboard = NULL, - custom_viewer_popup_t *_popup = NULL, - custom_viewer_mouse_moved_t *_mouse_moved = NULL, - custom_viewer_click_t *_click = NULL, - custom_viewer_dblclick_t *_dblclick = NULL, - custom_viewer_curpos_t *_curpos = NULL, - custom_viewer_close_t *_close = NULL, - custom_viewer_help_t *_help = NULL, - custom_viewer_adjust_place_t *_adjust_place = NULL, - custom_viewer_get_place_xcoord_t *_get_place_xcoord = NULL, - custom_viewer_location_changed_t *_location_changed = NULL, - custom_viewer_can_navigate_t *_can_navigate = NULL) - : cb(sizeof(*this)), - keyboard(_keyboard), - popup(_popup), - mouse_moved(_mouse_moved), - click(_click), - dblclick(_dblclick), - curpos(_curpos), - close(_close), - help(_help), - adjust_place(_adjust_place), - get_place_xcoord(_get_place_xcoord), - location_changed(_location_changed), - can_navigate(_can_navigate) - {} - custom_viewer_keydown_t *keyboard; - custom_viewer_popup_t *popup; - custom_viewer_mouse_moved_t *mouse_moved; - custom_viewer_click_t *click; - custom_viewer_dblclick_t *dblclick; - custom_viewer_curpos_t *curpos; - custom_viewer_close_t *close; - custom_viewer_help_t *help; - custom_viewer_adjust_place_t *adjust_place; - custom_viewer_get_place_xcoord_t *get_place_xcoord; - custom_viewer_location_changed_t *location_changed; - custom_viewer_can_navigate_t *can_navigate; -}; -#endif // SWIG - - -#ifndef __UI__ // Not for the UI - -// Convenience functions offered by the user interface - -/// Execute a list of UI requests (::ui_execute_ui_requests_list). -/// \returns a request id: a unique number that can be used to cancel the request - -THREAD_SAFE inline int execute_ui_requests(ui_requests_t *reqs) -{ - return callui(ui_execute_ui_requests_list, reqs).i; -} - - -/// Execute a variable number of UI requests (::ui_execute_ui_requests). -/// The UI requests will be dispatched in the context of the main thread. -/// \param req pointer to the first request ,use NULL to terminate the var arg request list -/// \return a request id: a unique number that can be used to cancel the request - -THREAD_SAFE inline int execute_ui_requests(ui_request_t *req, ...) -{ - va_list va; - va_start(va, req); - int req_id = callui(ui_execute_ui_requests, req, va).i; - va_end(va); - return req_id; -} - - -/// Try to cancel an asynchronous exec request (::ui_cancel_exec_request). -/// \param req_id request id -/// \retval true successfully canceled -/// \retval false request has already been processed. - -THREAD_SAFE inline bool cancel_exec_request(int req_id) -{ - return callui(ui_cancel_exec_request, req_id).cnd; -} - - -/// Try to cancel asynchronous exec requests created by the specified thread. -/// \param tid thread id -/// \return number of the canceled requests. - -THREAD_SAFE inline int cancel_thread_exec_requests(qthread_t tid) -{ - return callui(ui_cancel_thread_exec_requests, tid).i; -} - -/// Get the group of widgets/registers -/// this view is synchronized with -/// \param w the widget -/// \return the group of widgets/registers, or NULL -inline const synced_group_t *get_synced_group(const TWidget *w) -{ - return (synced_group_t *) callui(ui_get_synced_group, w).vptr; -} - -/// Jump to the specified address (::ui_jumpto). -/// \param ea destination -/// \param opnum -1: don't change x coord -/// \param uijmp_flags \ref UIJMP_ -/// \return success - -inline bool jumpto(ea_t ea, int opnum=-1, int uijmp_flags=UIJMP_ACTIVATE) -{ - return callui(ui_jumpto, ea, opnum, uijmp_flags).cnd; -} - - -/// Show a banner dialog box (::ui_banner). -/// \param wait time to wait before closing -/// \retval 1 ok -/// \retval 0 esc was pressed - -inline bool banner(int wait) { return callui(ui_banner, wait).cnd; } - - -/// Can we use msg() functions? - -THREAD_SAFE inline bool is_msg_inited(void) { return callui(ui_is_msg_inited).cnd; } - - -/// Refresh marked windows (::ui_refreshmarked) - -inline void refresh_idaview(void) { callui(ui_refreshmarked); } - - -/// Refresh all disassembly views (::ui_refresh), forces an immediate refresh. -/// Please consider request_refresh() instead - -inline void refresh_idaview_anyway(void) { callui(ui_refresh); } - - -/// Allow the user to set analyzer options. (show a dialog box) (::ui_analyzer_options) - -inline void analyzer_options(void) { callui(ui_analyzer_options); } - - -/// Get the address at the screen cursor (::ui_screenea) - -inline ea_t get_screen_ea(void) { ea_t ea; callui(ui_screenea, &ea); return ea; } - - -/// Get current operand number, -1 means no operand (::ui_get_opnum) - -inline int get_opnum(void) { return callui(ui_get_opnum).i; } - - -/// Get the cursor position on the screen (::ui_get_cursor). -/// \note coordinates are 0-based -/// \param[out] x x-coordinate -/// \param[out] y y-coordinate -/// \retval true pointers are filled -/// \retval false no disassembly window open - -inline bool get_cursor(int *x, int *y) { return callui(ui_get_cursor, x, y).cnd; } - - -/// Get coordinates of the output window's cursor (::ui_get_output_cursor). -/// \note coordinates are 0-based -/// \note this function will succeed even if the output window is not visible -/// \param[out] x column -/// \param[out] y line number (global, from the start of output) -/// \retval false the output window has been destroyed. -/// \retval true pointers are filled - -inline bool get_output_cursor(int *x, int *y) { return callui(ui_get_output_cursor, x, y).cnd; } - - -/// Get current line from the disassemble window (::ui_get_curline). -/// \return cptr current line with the color codes -/// (use tag_remove() to remove the color codes) - -inline const char *get_curline(void) { return callui(ui_get_curline).cptr; } - - -/// Open the given url (::ui_open_url) - -inline void open_url(const char *url) { callui(ui_open_url, url); } - - -/// Get the current address in a hex view. -/// \param hexdump_num number of hexview window - -inline ea_t get_hexdump_ea(int hexdump_num) { ea_t ea; callui(ui_hexdumpea, &ea, hexdump_num); return ea; } - - -/// Get keyboard key code by its name (::ui_get_key_code) - -inline ushort get_key_code(const char *keyname) { return callui(ui_get_key_code, keyname).i16; } - - -/// Get shortcut code previously created by ::ui_get_key_code. -/// \param key key constant -/// \param shift modifiers -/// \param is_qt are we using gui version? - -inline ushort lookup_key_code(int key, int shift, bool is_qt) { return callui(ui_lookup_key_code, key, shift, is_qt).i16; } - - -/// Refresh navigation band if changed (::ui_refresh_navband). -/// \param force refresh regardless - -inline void refresh_navband(bool force) { callui(ui_refresh_navband, force); } - - -/// Mark a non-modal custom chooser for a refresh (::ui_refresh_chooser). -/// \param title title of chooser -/// \return success - -inline bool refresh_chooser(const char *title) { return callui(ui_refresh_chooser, title).cnd; } - - -/// Close a non-modal chooser (::ui_close_chooser). -/// \param title window title of chooser to close -/// \return success - -inline bool close_chooser(const char *title) { return callui(ui_close_chooser, title).cnd; } - - -/// Install command line interpreter (::ui_install_cli) - -inline void install_command_interpreter(const cli_t *cp) { callui(ui_install_cli, cp, true); } - - -/// Remove command line interpreter (::ui_install_cli) - -inline void remove_command_interpreter(const cli_t *cp) { callui(ui_install_cli, cp, false); } - - -/// Generate disassembly text for a range. -/// \param[out] text result -/// \param ea1 start address -/// \param ea2 end address -/// \param truncate_lines (on idainfo::margin) - -inline void gen_disasm_text(text_t &text, ea_t ea1, ea_t ea2, bool truncate_lines) { callui(ui_gen_disasm_text, &text, ea1, ea2, truncate_lines); } - - -/// Execute code in the main thread. -/// \param req request specifying the code to execute -/// \param reqf \ref MFF_ -/// \return if \ref #MFF_NOWAIT is specified, return the request id. -/// otherwise return the value returned by exec_request_t::execute(). - -THREAD_SAFE inline int execute_sync(exec_request_t &req, int reqf) { return callui(ui_execute_sync, &req, reqf).i; } - - -/// Set the docking position of a widget (::ui_set_dock_pos). -/// \param src_ctrl title of widget to dock -/// \param dest_ctrl where to dock: if NULL or invalid then create -/// a new tab relative to current active tab -/// \param orient \ref DP_ -/// \param left,top,right,bottom dimensions of dock, if not specified or invalid then -/// create the widget in the center of the screen with the -/// default size -/// \return success - -inline bool set_dock_pos(const char *src_ctrl, const char *dest_ctrl, int orient, int left = 0, int top = 0, int right = 0, int bottom = 0) -{ - return callui(ui_set_dock_pos, src_ctrl, dest_ctrl, orient, left, top, right, bottom).cnd; -} - - -/// Load an icon from a file (::ui_load_custom_icon_file). -/// Also see load_custom_icon(const void *, unsigned int, const char *) -/// \param file_name path to file -/// \return icon id - -inline int load_custom_icon(const char *file_name) { return callui(ui_load_custom_icon_file, file_name).i; } - - -/// Load an icon and return its id (::ui_load_custom_icon). -/// \param ptr pointer to raw image data -/// \param len image data length -/// \param format image format -/// \return icon id - -inline int load_custom_icon(const void *ptr, unsigned int len, const char *format) { return callui(ui_load_custom_icon, ptr, len, format).i; } - - -/// Free an icon loaded with load_custom_icon() (::ui_free_custom_icon). - -inline void free_custom_icon(int icon_id) { callui(ui_free_custom_icon, icon_id); } - - -/// Processes a UI action by name. -/// \param name action name -/// \param flags reserved/not used -/// \param param reserved/not used - -inline bool process_ui_action(const char *name, int flags=0, void *param=NULL) -{ - return callui(ui_process_action, name, flags, param).cnd; -} - - -/// Take a database snapshot (::ui_take_database_snapshot). -/// \param ss in/out parameter. -/// - in: description, flags -/// - out: filename, id -/// \param err_msg optional error msg buffer -/// \return success - -inline bool take_database_snapshot( - snapshot_t *ss, - qstring *err_msg) -{ - return callui(ui_take_database_snapshot, ss, err_msg).cnd; -} - - -/// Restore a database snapshot. -/// Note: This call is asynchronous. When it is completed, the callback will be triggered. -/// \param ss snapshot instance (see build_snapshot_tree()) -/// \param cb A callback that will be triggered with a NULL string. -/// on success and an actual error message on failure. -/// \param ud user data passed to be passed to the callback -/// \return false if restoration could not be started (snapshot file was not found). \n -/// If the returned value is True then check if the operation succeeded from the callback. - -inline bool restore_database_snapshot( - const snapshot_t *ss, - ss_restore_cb_t *cb, - void *ud) -{ - return callui(ui_restore_database_snapshot, ss, cb, ud).cnd; -} - -/// Timer opaque handle -typedef struct __qtimer_t {} *qtimer_t; - - -/// Register a timer (::ui_register_timer). -/// Timer functions are thread-safe and the callback is executed -/// in the context of the main thread. -/// \param interval_ms interval in milliseconds -/// \param callback the callback can return -1 to unregister the timer; -/// any other value >= 0 defines the new interval for the timer -/// \param ud callback params -/// \return handle to registered timer (use this handle to unregister it), or NULL - -THREAD_SAFE inline qtimer_t register_timer( - int interval_ms, - int (idaapi *callback)(void *ud), - void *ud) -{ - return (qtimer_t)(callui(ui_register_timer, interval_ms, callback, ud).vptr); -} - - -/// Unregister a timer (::ui_unregister_timer). -/// \param t handle to a registered timer -/// \return success - -THREAD_SAFE inline bool unregister_timer(qtimer_t t) -{ - return callui(ui_unregister_timer, t).cnd; -} - -//------------------------------------------------------------------------- - -/// Create a new action (::ui_register_action). -/// After an action has been created, it is possible to attach it -/// to menu items (attach_action_to_menu()), or to popup menus -/// (attach_action_to_popup()). -/// -/// Because the actions will need to call the handler's activate() and -/// update() methods at any time, you shouldn't build your action handler -/// on the stack. -/// -/// Please see the SDK's "ht_view" plugin for an example how -/// to register actions. -/// \param desc action to register -/// \return success - -inline bool register_action(const action_desc_t &desc) -{ - return callui(ui_register_action, &desc).cnd; -} - - -/// Delete a previously-registered action (::ui_unregister_action). -/// \param name name of action -/// \return success - -inline bool unregister_action(const char *name) -{ - return callui(ui_unregister_action, name).cnd; -} - - -/// Get a list of all currently-registered actions -/// \param out the list of actions to be filled -inline void get_registered_actions(qstrvec_t *out) -{ - callui(ui_get_registered_actions, out); -} - - -/// Create a toolbar with the given name, label and optional position -/// \param name name of toolbar (must be unique) -/// \param label label of toolbar -/// \param before if non-NULL, the toolbar before which the new toolbar will be inserted -/// \param flags a combination of \ref CREATETB_, to determine toolbar position -/// \return success -inline bool create_toolbar( - const char *name, - const char *label, - const char *before = NULL, - int flags = 0) -{ - return callui(ui_create_toolbar, name, label, before, flags).cnd; -} - - -/// Delete an existing toolbar -/// \param name name of toolbar -/// \return success -inline bool delete_toolbar(const char *name) -{ - return callui(ui_delete_toolbar, name).cnd; -} - - -/// Create a menu with the given name, label and optional position, -/// either in the menubar, or as a submenu. -/// If 'menupath' is non-NULL, it provides information about where -/// the menu should be positioned. -/// First, IDA will try and resolve the corresponding menu by its name. -/// If such an existing menu is found and is present in the menubar, -/// then the new menu will be inserted in the menubar before it. -/// Otherwise, IDA will try to resolve 'menupath' as it would for -/// attach_action_to_menu() and, if found, add the new menu like so: -/// \code -/// // The new 'My menu' submenu will appear in the 'Comments' submenu -/// // before the 'Enter comment..." command -/// create_menu("(...)", "My menu", "Edit/Comments/Enter comment..."); -/// \endcode -/// or -/// \code -/// // The new 'My menu' submenu will appear at the end of the -/// // 'Comments' submenu. -/// create_menu("(...)", "My menu", "Edit/Comments/"); -/// \endcode -/// If the above fails, the new menu will be appended to the menubar. -/// \param name name of menu (must be unique) -/// \param label label of menu -/// \param menupath where should the menu be inserted -/// \return success -inline bool create_menu( - const char *name, - const char *label, - const char *menupath=NULL) -{ - return callui(ui_create_menu, name, label, menupath).cnd; -} - - -/// Delete an existing menu -/// \param name name of menu -/// \return success -inline bool delete_menu(const char *name) -{ - return callui(ui_delete_menu, name).cnd; -} - - -/// Attach a previously-registered action to the menu (::ui_attach_action_to_menu). -/// \note You should not change top level menu, or the Edit,Plugins submenus -/// If you want to modify the debugger menu, do it at the ui_debugger_menu_change -/// event (ida might destroy your menu item if you do it elsewhere). -/// \param menupath path to the menu item after or before which the insertion will take place. \n -/// - Example: Debug/StartProcess -/// - Whitespace, punctuation are ignored. -/// - It is allowed to specify only the prefix of the menu item. -/// - Comparison is case insensitive. -/// - menupath may start with the following prefixes: -/// - [S] - modify the main menu of the structure window -/// - [E] - modify the main menu of the enum window -/// \param name the action name -/// \param flags a combination of \ref SETMENU_, to determine menu item position -/// \return success - -inline bool attach_action_to_menu( - const char *menupath, - const char *name, - int flags) -{ - return callui(ui_attach_action_to_menu, menupath, name, flags).cnd; -} - - -/// Detach an action from the menu (::ui_detach_action_from_menu). -/// \param menupath path to the menu item -/// \param name the action name -/// \return success - -inline bool detach_action_from_menu( - const char *menupath, - const char *name) -{ - return callui(ui_detach_action_from_menu, menupath, name).cnd; -} - - -/// Attach an action to an existing toolbar (::ui_attach_action_to_toolbar). -/// \param toolbar_name the name of the toolbar -/// \param name the action name -/// \return success - -inline bool attach_action_to_toolbar( - const char *toolbar_name, - const char *name) -{ - return callui(ui_attach_action_to_toolbar, toolbar_name, name).cnd; -} - - -/// Detach an action from the toolbar (::ui_detach_action_from_toolbar). -/// \param toolbar_name the name of the toolbar -/// \param name the action name -/// \return success - -inline bool detach_action_from_toolbar( - const char *toolbar_name, - const char *name) -{ - return callui(ui_detach_action_from_toolbar, toolbar_name, name).cnd; -} - - -/// Helper. -/// -/// You are not encouraged to use this, as it mixes flags for -/// both register_action(), and attach_action_to_menu(). -/// -/// The only reason for its existence is to make it simpler -/// to port existing plugins to the new actions API. - -inline bool register_and_attach_to_menu( - const char *menupath, - const char *name, - const char *label, - const char *shortcut, - int flags, - action_handler_t *handler, - void *owner, - int action_desc_t_flags) -{ - action_desc_t desc = ACTION_DESC_LITERAL_OWNER(name, label, handler, owner, shortcut, NULL, -1, action_desc_t_flags); - if ( !register_action(desc) ) - return false; - if ( !attach_action_to_menu(menupath, name, (flags & SETMENU_POSMASK)) ) - { - unregister_action(name); - return false; - } - return true; -} - -//------------------------------------------------------------------------ -// Get VCL global variables -class TPopupMenu; - -/// Display a widget, dock it if not done before -/// \param widget widget to display -/// \param options \ref WIDGET_OPEN -/// \param dest_ctrl where to dock: if NULL or invalid then -/// use the active docker if there is not -/// create a new tab relative to current active tab - -inline void display_widget(TWidget *widget, uint32 options, const char *dest_ctrl=NULL) -{ - callui(ui_display_widget, widget, options, dest_ctrl); -} - - -/// Close widget (::ui_close_widget, only gui version). -/// \param widget pointer to the widget to close -/// \param options \ref WIDGET_CLOSE - -inline void close_widget(TWidget *widget, int options) -{ - callui(ui_close_widget, widget, options); -} - - -/// Activate widget (only gui version) (::ui_activate_widget). -/// \param widget existing widget to display -/// \param take_focus give focus to given widget - -inline void activate_widget(TWidget *widget, bool take_focus) -{ - callui(ui_activate_widget, widget, take_focus); -} - - -/// Find widget with the specified caption (only gui version) (::ui_find_widget). -/// NB: this callback works only with the tabbed widgets! -/// \param caption title of tab, or window title if widget is not tabbed -/// \return pointer to the TWidget, NULL if none is found - -inline TWidget *find_widget(const char *caption) -{ - return (TWidget *) callui(ui_find_widget, caption).vptr; -} - - -/// Get a pointer to the current widget (::ui_get_current_widget). - -inline TWidget *get_current_widget(void) -{ - return (TWidget *) callui(ui_get_current_widget).vptr; -} - - -/// Get the type of the TWidget * (::ui_get_widget_type). - -inline twidget_type_t get_widget_type(TWidget *widget) -{ - return twidget_type_t(callui(ui_get_widget_type, widget).i); -} - - -/// Get the TWidget's title (::ui_get_widget_title). - -inline bool get_widget_title(qstring *buf, TWidget *widget) -{ - return callui(ui_get_widget_title, buf, widget).cnd; -} - -/// Create new ida viewer based on ::place_t (::ui_create_custom_viewer). -/// \param title name of viewer -/// \param minplace first location of the viewer -/// \param maxplace last location of the viewer -/// \param curplace set current location -/// \param rinfo renderer information (can be NULL) -/// \param ud contents of viewer -/// \param handlers handlers for the viewer (can be NULL) -/// \param parent widget to hold viewer -/// \return pointer to resulting viewer - -inline TWidget *create_custom_viewer( - const char *title, - const place_t *minplace, - const place_t *maxplace, - const place_t *curplace, - const renderer_info_t *rinfo, - void *ud, - const custom_viewer_handlers_t *cvhandlers, - void *cvhandlers_ud, - TWidget *parent = NULL) -{ - return (TWidget*) callui( - ui_create_custom_viewer, title, minplace, - maxplace, curplace, rinfo, ud, cvhandlers, cvhandlers_ud, parent).vptr; -} - - -/// Append 'loc' to the viewer's history, and cause the viewer -/// to display it. -///< \param v (TWidget *) -///< \param loc (const lochist_entry_t &) -///< \param flags (uint32) or'ed combination of CVNF_* values -///< \return success - -inline bool custom_viewer_jump( - TWidget *v, - const lochist_entry_t &loc, - uint32 flags=0) -{ - return callui(ui_custom_viewer_jump, v, &loc, flags).cnd; -} - - -/// Push current location in the history and jump to the given location (::ui_ea_viewer_history_push_and_jump). -/// This will jump in the given ea viewer and also in other synchronized views. -/// \param v ea viewer -/// \param ea jump destination -/// \param x,y coords on screen -/// \param lnnum desired line number of given address - -inline bool ea_viewer_history_push_and_jump(TWidget *v, ea_t ea, int x, int y, int lnnum) -{ - return callui(ui_ea_viewer_history_push_and_jump, v, ea, x, y, lnnum).cnd; -} - - -/// Get information about what's in the history (::ui_ea_viewer_history_info). -/// \param[out] nback number of available back steps -/// \param[out] nfwd number of available forward steps -/// \param v ea viewer -/// \retval false if the given ea viewer does not exist -/// \retval true otherwise - -inline bool get_ea_viewer_history_info(int *nback, int *nfwd, TWidget *v) -{ - return callui(ui_ea_viewer_history_info, nback, nfwd, v).cnd; -} - - -/// Refresh custom ida viewer (::ui_refresh_custom_viewer) - -inline void refresh_custom_viewer(TWidget *custom_viewer) -{ - callui(ui_refresh_custom_viewer, custom_viewer); -} - - -/// Repaint the given widget immediately (::ui_repaint_qwidget) - -inline void repaint_custom_viewer(TWidget *custom_viewer) -{ - callui(ui_repaint_qwidget, custom_viewer); -} - - -/// Destroy custom ida viewer - -inline void destroy_custom_viewer(TWidget *custom_viewer) -{ - callui(ui_destroy_custom_viewer, custom_viewer); -} - - -/// Set cursor position in custom ida viewer. -/// \param custom_viewer view -/// \param place target position -/// \param x desired cursor position (column) -/// \param y desired cursor position (line) -/// \return success - -inline bool jumpto(TWidget *custom_viewer, place_t *place, int x, int y) -{ - return callui(ui_jump_in_custom_viewer, custom_viewer, place, x, y).cnd; -} - - -/// Get current place in a custom viewer (::ui_get_curplace). -/// -/// See also the more complete get_custom_viewer_location() -/// -/// \param custom_viewer view -/// \param mouse mouse position (otherwise cursor position) -/// \param[out] x x coordinate -/// \param[out] y y coordinate - -inline place_t *get_custom_viewer_place( - TWidget *custom_viewer, - bool mouse, - int *x, - int *y) -{ - return (place_t *)callui(ui_get_curplace, custom_viewer, mouse, x, y).vptr; -} - - -/// Get the current location in a custom viewer (::ui_get_custom_viewer_location). -inline bool get_custom_viewer_location( - lochist_entry_t *out, - TWidget *custom_viewer, - bool mouse=false) -{ - return callui(ui_get_custom_viewer_location, out, custom_viewer, mouse).cnd; -} - -/// Are we running inside IDA Qt? - -inline bool is_idaq() -{ - return callui(ui_is_idaq).cnd; -} - - -/// Insert a previously-registered action into the widget's popup menu (::ui_attach_action_to_popup). -/// This function has two "modes": 'single-shot', and 'permanent'. -/// \param widget target widget -/// \param popup_handle target popup menu -/// - if non-NULL, the action is added to this popup -/// menu invocation (i.e., 'single-shot') -/// - if NULL, the action is added to a list of actions -/// that should always be present in context menus for this widget -/// (i.e., 'permanent'.) -/// \param name action name -/// \param popuppath can be NULL -/// \param flags a combination of SETMENU_ flags (see \ref SETMENU_) -/// \return success - -inline bool attach_action_to_popup( - TWidget *widget, - TPopupMenu *popup_handle, - const char *name, - const char *popuppath = NULL, - int flags = 0) -{ - return callui(ui_attach_action_to_popup, widget, popup_handle, name, popuppath, flags).cnd; -} - - -/// Remove a previously-registered action, from the list of 'permanent' -/// context menu actions for this widget (::ui_detach_action_from_popup). -/// This only makes sense if the action has been added to 'widget's list -/// of permanent popup actions by calling attach_action_to_popup -/// in 'permanent' mode. -/// \param widget target widget -/// \param name action name - -inline bool detach_action_from_popup(TWidget *widget, const char *name) -{ - return callui(ui_detach_action_from_popup, widget, name).cnd; -} - - -/// Create & insert an action into the widget's popup menu (::ui_attach_dynamic_action_to_popup). -/// \note action_desc_t::handler for 'desc' must be instantiated using 'new', as it -/// will be 'delete'd when the action is unregistered. -/// \param widget target widget -/// \param popup_handle target popup -/// \param desc created with #DYNACTION_DESC_LITERAL -/// \param popuppath can be NULL -/// \param flags a combination of SETMENU_ constants (see \ref SETMENU_) -/// \param buf a buffer, to retrieve the generated action name - can be NULL -/// \return success - -inline bool attach_dynamic_action_to_popup( - TWidget *widget, - TPopupMenu *popup_handle, - const action_desc_t &desc, - const char *popuppath = NULL, - int flags = 0, - qstring *buf = NULL) -{ - return callui(ui_attach_dynamic_action_to_popup, widget, - popup_handle, &desc, popuppath, flags, buf).cnd; -} - -/// \defgroup ui_uaa_funcs Functions: update actions -/// Convenience functions for ::ui_update_action_attr -//@{ - -/// Update an action's label (::ui_update_action_attr). -/// \param name action name -/// \param label new label -/// \return success - -inline bool update_action_label(const char *name, const char *label) -{ - return callui(ui_update_action_attr, name, AA_LABEL, label).cnd; -} - - -/// Update an action's shortcut (::ui_update_action_attr). -/// \param name action name -/// \param shortcut new shortcut -/// \return success - -inline bool update_action_shortcut(const char *name, const char *shortcut) -{ - return callui(ui_update_action_attr, name, AA_SHORTCUT, shortcut).cnd; -} - - -/// Update an action's tooltip (::ui_update_action_attr). -/// \param name action name -/// \param tooltip new tooltip -/// \return success - -inline bool update_action_tooltip(const char *name, const char *tooltip) -{ - return callui(ui_update_action_attr, name, AA_TOOLTIP, tooltip).cnd; -} - - -/// Update an action's icon (::ui_update_action_attr). -/// \param name action name -/// \param icon new icon id -/// \return success - -inline bool update_action_icon(const char *name, int icon) -{ - return callui(ui_update_action_attr, name, AA_ICON, &icon).cnd; -} - - -/// Update an action's state (::ui_update_action_attr). -/// \param name action name -/// \param state new state -/// \return success - -inline bool update_action_state(const char *name, action_state_t state) -{ - return callui(ui_update_action_attr, name, AA_STATE, &state).cnd; -} - - -/// Update an action's checkability (::ui_update_action_attr). -/// \param name action name -/// \param checkable new checkability -/// \return success - -inline bool update_action_checkable(const char *name, bool checkable) -{ - return callui(ui_update_action_attr, name, AA_CHECKABLE, &checkable).cnd; -} - - -/// Update an action's checked state (::ui_update_action_attr). -/// \param name action name -/// \param checked new checked state -/// \return success - -inline bool update_action_checked(const char *name, bool checked) -{ - return callui(ui_update_action_attr, name, AA_CHECKED, &checked).cnd; -} - - -/// Update an action's visibility (::ui_update_action_attr). -/// \param name action name -/// \param visible new visibility -/// \return success - -inline bool update_action_visibility(const char *name, bool visible) -{ - return callui(ui_update_action_attr, name, AA_VISIBILITY, &visible).cnd; -} - -//@} - -/// \defgroup ui_gaa_funcs Functions: get action attributes -/// Convenience functions for ::ui_get_action_attr -//{ - -/// Get an action's label (::ui_get_action_attr). -/// \param[out] label the action label -/// \param name the action name -/// \return success - -inline bool get_action_label(qstring *label, const char *name) -{ - return callui(ui_get_action_attr, name, AA_LABEL, label).cnd; -} - - -/// Get an action's shortcut (::ui_get_action_attr). -/// \param[out] shortcut the action shortcut -/// \param name the action name -/// \return success - -inline bool get_action_shortcut(qstring *shortcut, const char *name) -{ - return callui(ui_get_action_attr, name, AA_SHORTCUT, shortcut).cnd; -} - - -/// Get an action's tooltip (::ui_get_action_attr). -/// \param[out] tooltip the action tooltip -/// \param name the action name -/// \return success - -inline bool get_action_tooltip(qstring *tooltip, const char *name) -{ - return callui(ui_get_action_attr, name, AA_TOOLTIP, tooltip).cnd; -} - - -/// Get an action's icon (::ui_get_action_attr). -/// \param name the action name -/// \param[out] icon the icon id -/// \return success - -inline bool get_action_icon(const char *name, int *icon) -{ - return callui(ui_get_action_attr, name, AA_ICON, icon).cnd; -} - - -/// Get an action's state (::ui_get_action_attr). -/// \param name the action name -/// \param[out] state the action's state -/// \return success - -inline bool get_action_state(const char *name, action_state_t *state) -{ - return callui(ui_get_action_attr, name, AA_STATE, state).cnd; -} - - -/// Get an action's checkability (::ui_get_action_attr). -/// \param name the action name -/// \param[out] checkable the action's checkability -/// \return success - -inline bool get_action_checkable(const char *name, bool *checkable) -{ - return callui(ui_get_action_attr, name, AA_CHECKABLE, checkable).cnd; -} - - -/// Get an action's checked state (::ui_get_action_attr). -/// \param name the action name -/// \param[out] checked the action's checked state -/// \return success - -inline bool get_action_checked(const char *name, bool *checked) -{ - return callui(ui_get_action_attr, name, AA_CHECKED, checked).cnd; -} - - -/// Get an action's visibility (::ui_get_action_attr). -/// \param name the action name -/// \param[out] visibility the action's visibility -/// \return success - -inline bool get_action_visibility(const char *name, bool *visibility) -{ - return callui(ui_get_action_attr, name, AA_VISIBILITY, visibility).cnd; -} - -//@} - -/// \defgroup ui_scvh_funcs Functions: custom viewer handlers -/// Convenience functions for ::ui_set_custom_viewer_handler -//@{ - -/// Set handlers for custom viewer events -/// Any of these handlers may be NULL - -inline void set_custom_viewer_handlers( - TWidget *custom_viewer, - const custom_viewer_handlers_t *cvh, - void *cvh_ud) -{ - callui(ui_set_custom_viewer_handlers, custom_viewer, cvh, cvh_ud); -} - - -/// Set a handler for a custom viewer event (::ui_set_custom_viewer_handler). -/// see also ::ui_set_custom_viewer_handlers -/// \param custom_viewer the custom viewer -/// \param handler_id one of CVH_ in ::custom_viewer_handler_id_t -/// \param handler_or_data can be a handler or data. see examples in \ref ui_scvh_funcs -/// \return old value of the handler or data - -inline void *set_custom_viewer_handler( - TWidget *custom_viewer, - custom_viewer_handler_id_t handler_id, - void *handler_or_data) -{ - return callui(ui_set_custom_viewer_handler, custom_viewer, handler_id, - handler_or_data).vptr; -} - - -/// Allow the given viewer to interpret Qt events (::ui_set_custom_viewer_handler) - -inline bool set_custom_viewer_qt_aware(TWidget *custom_viewer) -{ - return callui(ui_set_custom_viewer_handler, custom_viewer, CVH_QT_AWARE).cnd; -} - -//@} - - -/// Get current line of custom viewer (::ui_get_custom_viewer_curline). -/// The returned line contains color codes -/// \param custom_viewer view -/// \param mouse mouse position (otherwise cursor position) -/// \return pointer to contents of current line - -inline const char *get_custom_viewer_curline(TWidget *custom_viewer, bool mouse) -{ - return callui(ui_get_custom_viewer_curline, custom_viewer, mouse).cptr; -} - - -/// Get current line of output window (::ui_get_output_curline). -/// \param buf output buffer -/// \param mouse current for mouse pointer? -/// \return false if output contains no text - -inline bool get_output_curline(qstring *buf, bool mouse) -{ - return callui(ui_get_output_curline, buf, mouse).cnd; -} - - -/// Returns selected text from output window (::ui_get_output_selected_text). -/// \param buf output buffer -/// \return true if there is a selection - -inline bool get_output_selected_text(qstring *buf) -{ - return callui(ui_get_output_selected_text, buf).cnd; -} - - -/// Get current ida viewer (idaview or custom viewer) (::ui_get_current_viewer) - -inline TWidget *get_current_viewer(void) -{ - return (TWidget *)callui(ui_get_current_viewer).vptr; -} - - -/// Get the type of renderer currently in use in the given view (::ui_get_renderer_type) - -inline tcc_renderer_type_t get_view_renderer_type(TWidget *v) -{ - return tcc_renderer_type_t(callui(ui_get_renderer_type, v).i); -} - - -/// Set the type of renderer to use in a view (::ui_set_renderer_type) - -inline void set_view_renderer_type(TWidget *v, tcc_renderer_type_t rt) -{ - callui(ui_set_renderer_type, v, rt); -} - - -/// Set position range for custom viewer (::ui_set_custom_viewer_range) - -inline void set_custom_viewer_range( - TWidget *custom_viewer, - const place_t *minplace, - const place_t *maxplace) -{ - callui(ui_set_custom_viewer_range, custom_viewer, minplace, maxplace); -} - - -/// Create an empty widget, serving as a container for custom -/// user widgets - -inline TWidget *create_empty_widget(const char *title, int icon = -1) -{ - return (TWidget *) callui(ui_create_empty_widget, title, icon).vptr; -} - - -/// Clear the "Output window" - -inline void msg_clear() -{ - callui(ui_msg_clear); -} - - -/// Save the "Output window" contents into a file -/// \param path The path of the file to save the contents into. -/// An empty path means that the user will be prompted for -/// the destination and, if the file already exists, the user -/// will be asked to confirm before overriding its contents. -/// Upon return, 'path' will contain the path that the user -/// chose. -/// \return success - -inline bool msg_save(qstring &path) -{ - return callui(ui_msg_save, &path).cnd; -} - - -/// Retrieve the last 'count' lines from the output window, in reverse -/// order (from most recent, to least recent) -/// \param out Output storage -/// \param count The number of lines to retrieve. -1 means: all - -inline void msg_get_lines(qstrvec_t *out, int count=-1) -{ - callui(ui_msg_get_lines, out, count); -} - - -/// Get the current, active modal TWidget instance. -/// Note that in this context, the "wait dialog" is not considered: -/// this function will return NULL even if it is currently shown. -/// \return TWidget * the active modal widget, or NULL - -inline TWidget *get_active_modal_widget(void) -{ - return (TWidget *) callui(ui_get_active_modal_widget).vptr; -} - - -/// Translate the provided ea_t, into its pixel position (plus pixel ranges) -/// on the navigation band. - -inline int get_navband_pixel(bool *out_is_vertical, ea_t ea) -{ - return callui(ui_navband_pixel, out_is_vertical, ea).i; -} - - -/// Translate the pixel position on the navigation band, into an address - -inline ea_t get_navband_ea(int pixel) -{ - ea_t ea = BADADDR; - callui(ui_navband_ea, &ea, pixel); - return ea; -} - - -/// Get the system-specific window ID (GUI version only) -/// \param the name of the window (NULL means the main IDA window) -/// \return the low-level window ID - -inline void *get_window_id(const char *name=NULL) -{ - return callui(ui_get_window_id, name).vptr; -} - - -/// Is the given custom view an idaview? (::ui_is_idaview) - -inline bool is_idaview(TWidget *v) -{ - return callui(ui_is_idaview, v).cnd; -} - - -/// Get the selected range boundaries (::ui_read_selection). -/// \param v view -/// \param[out] p1 start of selection -/// \param[out] p2 end of selection -/// \retval false no range is selected -/// \retval true ok, start and end are filled - -inline bool read_selection(TWidget *v, twinpos_t *p1, twinpos_t *p2) -{ - return callui(ui_read_selection, v, p1, p2).cnd; -} - - -/// Get the address range for the selected range boundaries, -/// this is the convenient function for read_selection() -/// \param v view, NULL means the last active window -/// containing addresses -/// \param[out] ea1 start ea -/// \param[out] ea2 end ea -/// \retval 0 no range is selected \n -/// \retval 1 ok, start ea and end ea are filled - -inline bool read_range_selection(TWidget *v, ea_t *ea1, ea_t *ea2) -{ - return callui(ui_read_range_selection, v, ea1, ea2).cnd; -} - - -/// Unmark selection (::ui_unmarksel) - -inline void unmark_selection(void) { callui(ui_unmarksel); } - - -/// Create a code viewer (::ui_create_code_viewer). -/// A code viewer contains on the left side a widget representing the -/// line numbers, and on the right side, the child widget passed as -/// parameter. -/// It will inherit its title from the child widget. -/// -/// \param custview the custom view to be added -/// \param flags \ref CDVF_ -/// \param parent widget to contain the new code viewer - -inline TWidget *create_code_viewer( - TWidget *custview, - int flags = 0, - TWidget *parent = NULL) -{ - return (TWidget*)callui(ui_create_code_viewer, custview, flags, parent).vptr; -} - - -/// Set a handler for a code viewer event (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs -/// \param code_viewer the code viewer -/// \param handler_id one of CDVH_ in ::custom_viewer_handler_id_t -/// \param handler_or_data can be a handler or data. see examples in \ref ui_scvh_funcs -/// \return old value of the handler or data - -inline void *set_code_viewer_handler( - TWidget *code_viewer, - custom_viewer_handler_id_t handler_id, - void *handler_or_data) -{ - return callui(ui_set_custom_viewer_handler, code_viewer, handler_id, - handler_or_data).vptr; -} - - -/// Set the user data on a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs - -inline bool set_code_viewer_user_data(TWidget *code_viewer, void *ud) -{ - return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_USERDATA, ud).cnd; -} - - -/// Get the user data from a custom viewer (::ui_get_viewer_user_data) - -inline void *get_viewer_user_data(TWidget *viewer) -{ - return callui(ui_get_viewer_user_data, viewer).vptr; -} - - -/// Get the type of ::place_t instances a viewer uses & creates (::ui_get_viewer_place_type). - -inline tcc_place_type_t get_viewer_place_type(TWidget *viewer) -{ - return tcc_place_type_t(callui(ui_get_viewer_place_type, viewer).i); -} - - -/// Set handlers for code viewer line events. -/// Any of these handlers may be NULL - -inline void set_code_viewer_line_handlers( - TWidget *code_viewer, - code_viewer_lines_click_t *click_handler, - code_viewer_lines_click_t *popup_handler, - code_viewer_lines_click_t *dblclick_handler, - code_viewer_lines_icon_t *drawicon_handler, - code_viewer_lines_linenum_t *linenum_handler) -{ - callui(ui_set_code_viewer_line_handlers, code_viewer, click_handler, - popup_handler, dblclick_handler, drawicon_handler, linenum_handler); -} - - -/// Set space allowed for icons in the margin of a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs - -inline bool set_code_viewer_lines_icon_margin(TWidget *code_viewer, int margin) -{ - return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_LINES_ICONMARGIN, margin).cnd; -} - - -/// Set alignment for lines in a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs - -inline bool set_code_viewer_lines_alignment(TWidget *code_viewer, int align) -{ - return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_LINES_ALIGNMENT, align).cnd; -} - - -/// Set radix for values displayed in a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs - -inline bool set_code_viewer_lines_radix(TWidget *code_viewer, int radix) -{ - return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_LINES_RADIX, radix).cnd; -} - - -/// Specify that the given code viewer is used to display source code (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs - -inline bool set_code_viewer_is_source(TWidget *code_viewer) -{ - return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_SRCVIEW).cnd; -} - - -/// Get the size of a tab in spaces (::ui_get_tab_size). -/// \param path the path of the source view for which the tab size is requested. -/// - if NULL, the default size is returned. - -inline int get_tab_size(const char *path) -{ - return callui(ui_get_tab_size, path).i; -} - - -/// Clear "Cancelled" flag (::ui_clr_cancelled) - -THREAD_SAFE inline void clr_cancelled(void) { callui(ui_clr_cancelled); } - - -/// Set "Cancelled" flag (::ui_set_cancelled) - -THREAD_SAFE inline void set_cancelled(void) { callui(ui_set_cancelled); } - - -/// Test the ctrl-break flag (::ui_test_cancelled). -/// \retval 1 Ctrl-Break is detected, a message is displayed -/// \retval 2 Ctrl-Break is detected again, a message is not displayed -/// \retval 0 Ctrl-Break is not detected - -THREAD_SAFE inline bool user_cancelled(void) { return callui(ui_test_cancelled).cnd; } - - -/// Display a load file dialog and load file (::ui_load_file). -/// \param[out] temp_file name of the file with the extracted archive member. -/// \param[in,out] filename the name of input file as is, -/// library or archive name -/// \param[in,out] pli loader input source, -/// may be changed to point to temp_file -/// \param neflags combination of NEF_... bits (see \ref NEF_) -/// \param[in,out] ploaders list of loaders which accept file, -/// may be changed for loaders of temp_file -/// \retval true file was successfully loaded -/// \retval false otherwise - -inline bool ui_load_new_file( - qstring *temp_file, - qstring *filename, - linput_t **pli, - ushort neflags, - load_info_t **ploaders) -{ - return callui(ui_load_file, temp_file, filename, pli, neflags, ploaders).cnd; -} - - -/// Load a debugger plugin and run the specified program (::ui_run_dbg). -/// \param dbgopts value of the -r command line switch -/// \param exename name of the file to run -/// \param argc number of arguments for the executable -/// \param argv argument vector -/// \return success - -inline bool ui_run_debugger( - const char *dbgopts, - const char *exename, - int argc, - const char *const *argv) -{ - return callui(ui_run_dbg, dbgopts, exename, argc, argv).cnd; -} - - -/// Load debugging information from a file. -/// \param path path to file -/// \param li loader input. if NULL, check DBG_NAME_KEY -/// \param base loading address -/// \param verbose dump status to message window - -inline bool load_dbg_dbginfo( - const char *path, - linput_t *li=NULL, - ea_t base=BADADDR, - bool verbose=false) -{ - return callui(ui_dbg_load_dbg_dbginfo, path, li, base, verbose).cnd; -} - - -/// Add hotkey for IDC function (::ui_add_idckey). -/// \param hotkey hotkey name -/// \param idcfunc IDC function name -/// \return \ref IDCHK_ - -inline int add_idc_hotkey(const char *hotkey, const char *idcfunc) -{ - return callui(ui_add_idckey, hotkey, idcfunc).i; -} - - -/// Delete IDC function hotkey (::ui_del_idckey). -/// \param hotkey hotkey name -/// \retval 1 ok -/// \retval 0 failed - -inline bool del_idc_hotkey(const char *hotkey) -{ - return callui(ui_del_idckey, hotkey).cnd; -} - - -inline void get_user_strlist_options(strwinsetup_t *out) -{ - callui(ui_get_user_strlist_options, out); -} - - -/// Get the highlighted identifier in the viewer (::ui_get_highlight). -/// \param out_str buffer to copy identifier to -/// \param viewer the viewer -/// \param out_flags storage for the flags -/// \return false if no identifier is highlighted - -inline bool get_highlight(qstring *out_str, TWidget *viewer, uint32 *out_flags) -{ - return callui(ui_get_highlight, out_str, viewer, out_flags).cnd; -} - - -/// Set the highlighted identifier in the viewer (::ui_set_highlight). -/// \param viewer the viewer -/// \param str the text to match, or NULL to remove current -/// \param flags combination of HIF_... bits (see \ref HIF_) -/// \return false if an error occurred - -inline bool set_highlight(TWidget *viewer, const char *str, int flags) -{ - return callui(ui_set_highlight, viewer, str, flags).cnd; -} - - -#ifndef SWIG -/// Pointer to range marker function (for idaviews and hexviews) -/// This pointer is initialized by setup_range_marker() - -extern void (idaapi*range_marker)(ea_t ea, asize_t size); - - -/// Initialize pointer to idaview marker - -inline void setup_range_marker(void) -{ - void *ptr = callui(ui_get_range_marker).vptr; - if ( ptr != NULL ) - range_marker = reinterpret_cast(ptr); -} - -/// Inform the UI about any modifications of [ea, ea+size) - -inline void mark_range_for_refresh(ea_t ea, asize_t size) -{ - if ( range_marker != NULL ) - range_marker(ea, size); -} - - -/// Tell UI to refresh all idaviews and hexviews - -inline void mark_all_eaviews_for_refresh(void) -{ - if ( range_marker != NULL ) - range_marker(0, BADADDR); -} - -/// Ignores range_marker during the lifetime of the object. -/// Refreshes all idaviews and hexviews at the end. -struct range_marker_suspender_t -{ - void (idaapi *backup)(ea_t ea, asize_t size); - range_marker_suspender_t(void) - { - backup = range_marker; - range_marker = NULL; - } - ~range_marker_suspender_t(void) - { - range_marker = backup; - mark_all_eaviews_for_refresh(); - } -}; -#endif // SWIG - - -/// \defgroup ui_open_builtin_funcs Functions: open built-in windows -/// Convenience functions for ::ui_open_builtin -//@{ - -/// Open the exports window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_exports_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_EXPORTS, ea).vptr; -} - - -/// Open the exports window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_imports_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_IMPORTS, ea).vptr; -} - - -/// Open the names window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_names_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_NAMES, ea).vptr; -} - - -/// Open the functions window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_funcs_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_FUNCS, ea).vptr; -} - - -/// Open the strings window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \param selstart,selend only display strings that occur within this range -/// \return pointer to resulting window - -inline TWidget *open_strings_window(ea_t ea, ea_t selstart=BADADDR, ea_t selend=BADADDR) -{ - return (TWidget *) callui(ui_open_builtin, BWN_STRINGS, ea, selstart, selend).vptr; -} - - -/// Open the segments window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_segments_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_SEGS, ea).vptr; -} - - -/// Open the segment registers window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_segregs_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_SEGREGS, ea).vptr; -} - - -/// Open the selectors window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_selectors_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_SELS, 0).vptr; -} - - -/// Open the signatures window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_signatures_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_SIGNS, 0).vptr; -} - - -/// Open the type libraries window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_tils_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_TILS, 0).vptr; -} - - -/// Open the local types window (::ui_open_builtin). -/// \param ordinal ordinal of type to select by default -/// \return pointer to resulting window - -inline TWidget *open_loctypes_window(int ordinal) -{ - return (TWidget *) callui(ui_open_builtin, BWN_LOCTYPS, ordinal).vptr; -} - - -/// Open the function calls window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_calls_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_CALLS, ea).vptr; -} - -/// Open the problems window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_problems_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_PROBS, ea).vptr; -} - - -/// Open the breakpoints window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_bpts_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_BPTS, ea).vptr; -} - - -/// Open the threads window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_threads_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_THREADS, 0).vptr; -} - - -/// Open the modules window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_modules_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_MODULES, 0).vptr; -} - - -/// Open the trace window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_trace_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_TRACE, 0).vptr; -} - - -/// Open the call stack window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_stack_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_STACK, 0).vptr; -} - - -/// Open the cross references window (::ui_open_builtin). -/// \param ea index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_xrefs_window(ea_t ea) -{ - return (TWidget *) callui(ui_open_builtin, BWN_XREFS, ea).vptr; -} - - -/// Open the frame window for the given function (::ui_open_builtin). -/// \param pfn function to analyze -/// \param offset offset where the cursor is placed -/// \return pointer to resulting window if 'pfn' is a valid function and the window was displayed, \n -/// NULL otherwise - -inline TWidget *open_frame_window(func_t *pfn, uval_t offset) -{ - return (TWidget *) callui(ui_open_builtin, BWN_FRAME, pfn, offset).vptr; -} - - -/// Open the navigation band window (::ui_open_builtin). -/// \param ea sets the address of the navband arrow -/// \param zoom sets the navband zoom level -/// \return pointer to resulting window - -inline TWidget *open_navband_window(ea_t ea, int zoom) -{ - return (TWidget *) callui(ui_open_builtin, BWN_NAVBAND, ea, zoom).vptr; -} - - -/// Open the enums window (::ui_open_builtin). -/// \param const_id index of entry to select by default -/// \return pointer to resulting window - -inline TWidget *open_enums_window(tid_t const_id=BADADDR) -{ - return (TWidget *) callui(ui_open_builtin, BWN_ENUMS, const_id).vptr; -} - - -/// Open the structs window (::ui_open_builtin). -/// \param id index of entry to select by default -/// \param offset offset where the cursor is placed -/// \return pointer to resulting window - -inline TWidget *open_structs_window(tid_t id=BADADDR, uval_t offset=0) -{ - return (TWidget *) callui(ui_open_builtin, BWN_STRUCTS, id, offset).vptr; -} - - -/// Open a disassembly view (::ui_open_builtin). -/// \param window_title title of view to open -/// \param ranges if != NULL, then display a flow chart with the specified ranges -/// \return pointer to resulting window - -inline TWidget *open_disasm_window(const char *window_title, const rangevec_t *ranges=NULL) -{ - return (TWidget *) callui(ui_open_builtin, BWN_DISASMS, window_title, BADADDR, ranges, 0).vptr; -} - - -/// Open a hexdump view (::ui_open_builtin). -/// \param window_title title of view to open -/// \return pointer to resulting window - -inline TWidget *open_hexdump_window(const char *window_title) -{ - return (TWidget *) callui(ui_open_builtin, BWN_DUMPS, window_title, BADADDR, 0).vptr; -} - - -/// Open the notepad window (::ui_open_builtin). -/// \return pointer to resulting window - -inline TWidget *open_notepad_window(void) -{ - return (TWidget *) callui(ui_open_builtin, BWN_NOTEPAD, 0).vptr; -} - -//@} - -/// [Un]synchronize sources -/// \param what -/// \param with -/// \param sync -/// \return success -inline bool sync_sources( - const sync_source_t &what, - const sync_source_t &with, - bool sync) -{ - return callui(ui_sync_sources, &what, &with, sync).cnd; -} - - -/// \defgroup ui_choose_funcs Functions: built-in choosers -/// Convenience functions for ::ui_choose and ::choose_type_t -//@{ - - -/// Choose a signature (::ui_choose, ::chtype_idasgn). -/// \return name of selected signature, NULL if none selected - -inline char *choose_idasgn(void) -{ - return callui(ui_choose, chtype_idasgn).cptr; -} - - -/// Choose a type library (::ui_choose, ::chtype_idatil). -/// \param buf output buffer to store the library name -/// \retval true 'buf' was filled with the name of the selected til -/// \retval false otherwise - -inline bool choose_til(qstring *buf) -{ - return callui(ui_choose, chtype_idatil, buf).cnd; -} - - -/// Choose an entry point (::ui_choose, ::chtype_entry). -/// \param title chooser title -/// \return ea of selected entry point, #BADADDR if none selected - -inline ea_t choose_entry(const char *title) -{ - ea_t ea; - callui(ui_choose, chtype_entry, &ea, title); - return ea; -} - - -/// Choose a name (::ui_choose, ::chtype_name). -/// \param title chooser title -/// \return ea of selected name, #BADADDR if none selected - -inline ea_t choose_name(const char *title) -{ - ea_t ea; - callui(ui_choose, chtype_name, &ea, title); - return ea; -} - - -/// Choose an xref to a stack variable (::ui_choose, ::chtype_name). -/// \param pfn function -/// \param mptr variable -/// \return ea of the selected xref, BADADDR if none selected - -inline ea_t choose_stkvar_xref(func_t *pfn, member_t *mptr) -{ - ea_t ea; - callui(ui_choose, chtype_stkvar_xref, &ea, pfn, mptr); - return ea; -} - - -/// Choose an xref to an address (::ui_choose, ::chtype_xref). -/// \param to referenced address -/// \return ea of selected xref, BADADDR if none selected - -inline ea_t choose_xref(ea_t to) -{ - ea_t ea; - callui(ui_choose, chtype_xref, &ea, to); - return ea; -} - - -/// Choose an enum (::ui_choose, ::chtype_enum). -/// \param title chooser title -/// \param default_id id of enum to select by default -/// \return enum id of selected enum, #BADNODE if none selected - -inline enum_t choose_enum(const char *title, enum_t default_id) -{ - enum_t enum_id = default_id; - callui(ui_choose, chtype_enum, &enum_id, title); - return enum_id; -} - - -/// Choose an enum, restricted by value & size (::ui_choose, ::chtype_enum_by_value_and_size). -/// If the given value cannot be found initially, this function will -/// ask if the user would like to import a standard enum. -/// \param title chooser title -/// \param default_id id of enum to select by default -/// \param value value to search for -/// \param nbytes size of value -/// \param[out] serial serial number of imported enum member, if one was found -/// \return enum id of selected (or imported) enum, #BADNODE if none was found - -inline enum_t choose_enum_by_value( - const char *title, - enum_t default_id, - uint64 value, - int nbytes, - uchar *serial) -{ - enum_t enum_id = default_id; - callui(ui_choose, chtype_enum_by_value_and_size, &enum_id, title, value, nbytes, serial); - return enum_id; -} - - -/// Choose a function (::ui_choose, ::chtype_func). -/// \param title chooser title -/// \param default_ea ea of function to select by default -/// \return pointer to function that was selected, NULL if none selected - -inline func_t *choose_func(const char *title, ea_t default_ea) -{ - return callui(ui_choose, chtype_func, title, default_ea).fptr; -} - - -/// Choose a segment (::ui_choose, ::chtype_segm). -/// \param title chooser title -/// \param default_ea ea of segment to select by default -/// \return pointer to segment that was selected, NULL if none selected - -inline segment_t *choose_segm(const char *title, ea_t default_ea) -{ - return callui(ui_choose, chtype_segm, title, default_ea).segptr; -} - - -/// Choose a structure (::ui_choose, ::chtype_segm). -/// \param title chooser title; -/// \return pointer to structure that was selected, NULL if none selected - -inline struc_t *choose_struc(const char *title) -{ - return callui(ui_choose, chtype_struc, title).strptr; -} - - -/// Choose a segment register change point (::ui_choose, ::chtype_srcp). -/// \param title chooser title -/// \return pointer to segment register range of selected change point, NULL if none selected - -inline sreg_range_t *choose_srcp(const char *title) -{ - return callui(ui_choose, chtype_srcp, title).sraptr; -} - -//@} - -#ifndef SWIG - -/// Get path to a structure offset (for nested structures/enums) (::ui_choose, ::chtype_strpath). - -inline int choose_struc_path( - const char *title, - tid_t strid, - uval_t offset, - adiff_t delta, - bool appzero, - tid_t *path) -{ - return callui(ui_choose, chtype_strpath, title, strid, - offset, delta, appzero, path).i; -} - - - - -/// Invoke the chooser with a chooser object (::ui_choose, ::chtype_generic). -/// see the choose() function above - -//lint -sem(choose,custodial(1)) -inline ssize_t choose(chooser_base_t *ch, const void *def_item) -{ - return callui(ui_choose, chtype_generic, ch, def_item).ssize; -} - -#endif // SWIG - - -/// Get the underlying object of the specified chooser (::ui_get_chooser_obj). -/// \note This is object is chooser-specific. -/// \return the object that was used to create the chooser - -inline void *get_chooser_obj(const char *chooser_caption) -{ - return callui(ui_get_chooser_obj, chooser_caption).vptr; -} - -/// Get the text corresponding to the index N in the chooser data. -/// Use -1 to get the header. - -inline bool get_chooser_data( - qstrvec_t *out, - const char *chooser_caption, - int n) -{ - return callui(ui_get_chooser_data, out, chooser_caption, n).cnd; -} - - -/// Enable item-specific attributes for chooser items (::ui_enable_chooser_item_attrs). -/// For example: color list items differently depending on a criterium. \n -/// If enabled, the chooser will generate ui_get_chooser_item_attrs \n -/// events that can be intercepted by a plugin to modify the item attributes. \n -/// This event is generated only in the GUI version of IDA. \n -/// Specifying #CH_ATTRS bit at the chooser creation time has the same effect. -/// \return success - -inline bool idaapi enable_chooser_item_attrs(const char *chooser_caption, bool enable) -{ - return callui(ui_enable_chooser_item_attrs, chooser_caption, enable).cnd; -} - - -/// See show_wait_box() - -THREAD_SAFE AS_PRINTF(1, 0) inline void show_wait_box_v(const char *format, va_list va) -{ - callui(ui_mbox, mbox_wait, format, va); -} - - -/// Display a dialog box with "Please wait...". -/// If the text message starts with "HIDECANCEL\n", the cancel button \n -/// won't be displayed in the dialog box and you don't need to check \n -/// for cancellations with user_cancelled(). Plugins must call hide_wait_box() \n -/// to close the dialog box, otherwise the user interface will be disabled. -/// -/// Note that, if the wait dialog is already visible, show_wait_box() will \n -/// 1) push the currently-displayed text on a stack \n -/// 2) display the new text \n -/// Then, when hide_wait_box() is called, if that stack isn't empty its top \n -/// label will be popped and restored in the wait dialog. \n -/// This implies that a plugin should call hide_wait_box() exactly as many \n -/// times as it called show_wait_box(), or the wait dialog might remain \n -/// visible and block the UI. \n -/// Also, in case the plugin knows the wait dialog is currently displayed, \n -/// alternatively it can call replace_wait_box(), to replace the text of the\n -/// dialog without pushing the currently-displayed text on the stack. -THREAD_SAFE AS_PRINTF(1, 2) inline void show_wait_box(const char *format, ...) -{ - va_list va; - va_start(va, format); - show_wait_box_v(format, va); - va_end(va); -} - - -/// Hide the "Please wait dialog box" - -THREAD_SAFE inline void hide_wait_box(void) -{ - // stupid watcom requires va_list should not be NULL - callui(ui_mbox, mbox_hide, NULL, &callui); -} - - -/// Replace the label of "Please wait dialog box" - -THREAD_SAFE AS_PRINTF(1, 2) inline void replace_wait_box(const char *format, ...) -{ - va_list va; - va_start(va, format); - callui(ui_mbox, mbox_replace, format, va); - va_end(va); -} - - -/// Issue a beeping sound (::ui_beep). -/// \param beep_type ::beep_t - -inline void beep(beep_t beep_type=beep_default) -{ - callui(ui_beep, beep_type); -} - - -/// Display copyright warning (::ui_copywarn). -/// \return yes/no - -inline bool display_copyright_warning(void) -{ - return callui(ui_copywarn).cnd; -} - -#endif // __UI__ END OF UI SERVICE FUNCTIONS - - -/// Show a message box asking to send the input file to support@hex-rays.com. -/// \param format the reason why the input file is bad - -THREAD_SAFE AS_PRINTF(1, 2) inline void ask_for_feedback(const char *format, ...) -{ - va_list va; - va_start(va, format); - callui(ui_mbox, mbox_feedback, format, va); - va_end(va); -} - - -/// Display a dialog box and wait for the user to input an address (::ui_ask_addr). -/// \param addr in/out parameter. contains pointer to the address. -/// \param format printf() style format string with the question -/// \retval 0 the user pressed Esc. -/// \retval 1 ok, the user entered an address - -AS_PRINTF(2, 3) inline bool ask_addr(ea_t *addr, const char *format, ...) -{ - va_list va; - va_start(va, format); - bool ok = callui(ui_ask_addr, addr, format, va).cnd; - va_end(va); - return ok; -} - - -/// Display a dialog box and wait for the user to input an segment name (::ui_ask_seg). -/// This function allows to enter segment register names, segment base -/// paragraphs, segment names to denote a segment. -/// \param sel in/out parameter. contains selector of the segment -/// \param format printf() style format string with the question -/// \retval 0 if the user pressed Esc. \n -/// \retval 1 ok, the user entered an segment name - -AS_PRINTF(2, 3) inline bool ask_seg(sel_t *sel, const char *format, ...) -{ - va_list va; - va_start(va, format); - bool ok = callui(ui_ask_seg, sel, format, va).cnd; - va_end(va); - return ok; -} - - -/// Display a dialog box and wait for the user to input an number (::ui_ask_long). -/// The number is represented in C-style. -/// This function allows to enter any IDC expression and -/// properly calculates it. -/// \param value in/out parameter. contains pointer to the number -/// \param format printf() style format string with the question -/// \retval 0 if the user pressed Esc. \n -/// \retval 1 ok, the user entered a valid number. - -AS_PRINTF(2, 3) inline bool ask_long(sval_t *value, const char *format, ...) -{ - va_list va; - va_start(va, format); - bool ok = callui(ui_ask_long, value, format, va).cnd; - va_end(va); - return ok; -} - - -//--------------------------------------------------------------------------- -// E R R O R / W A R N I N G / I N F O D I A L O G B O X E S -//--------------------------------------------------------------------------- - -/// If this variable is set, then dialog boxes will not appear on the screen. -/// Warning/info messages are shown in the messages window. \n -/// The default value of user input dialogs will be returned to the -/// caller immediately. \n -/// This variable is used to enable unattended work of ida. - -idaman bool ida_export_data batch; - - -/// Exiting because of a a fatal error? -/// Is non-zero if we are exiting with from the error() function. - -idaman int ida_export_data errorexit; - - -/// Display error dialog box and exit. -/// If you just want to display an error message and let IDA continue, -/// do NOT use this function! Use warning() or info() instead. -/// \param format printf() style message string. -/// It may have some prefixes, see 'Format of dialog box' for details. - -THREAD_SAFE AS_PRINTF(1, 2) NORETURN inline void error(const char *format,...) -{ - va_list va; - va_start(va, format); - verror(format, va); - // NOTREACHED -} - - -/// Display warning dialog box and wait for the user to press Enter or Esc. -/// This messagebox will by default contain a "Don't display this message again" \n -/// checkbox if the message is repetitively displayed. If checked, the message \n -/// won't be displayed anymore during the current IDA session. \n -/// \param format printf() style format string. -/// It may have some prefixes, see 'Format of dialog box' for details. - -THREAD_SAFE AS_PRINTF(1, 0) inline void vwarning(const char *format, va_list va) -{ - callui(ui_mbox, mbox_warning, format, va); -} - -THREAD_SAFE AS_PRINTF(1, 2) inline void warning(const char *format, ...) -{ - va_list va; - va_start(va, format); - vwarning(format, va); - va_end(va); -} - - -/// Display info dialog box and wait for the user to press Enter or Esc. -/// This messagebox will by default contain a "Don't display this message again" \n -/// checkbox. If checked, the message will never be displayed anymore (state saved \n -/// in the Windows registry or the idareg.cfg file for a non-Windows version). -/// \param format printf() style format string. -/// It may have some prefixes, see 'Format of dialog box' for details. - -THREAD_SAFE AS_PRINTF(1, 0) inline void vinfo(const char *format, va_list va) -{ - callui(ui_mbox, mbox_info, format, va); -} - -THREAD_SAFE AS_PRINTF(1, 2) inline void info(const char *format, ...) -{ - va_list va; - va_start(va, format); - vinfo(format, va); - va_end(va); -} - - -/// Display "no memory for module ..." dialog box and exit. -/// \param format printf() style message string. - -THREAD_SAFE AS_PRINTF(1, 0) NORETURN inline void vnomem(const char *format, va_list va) -{ - callui(ui_mbox, mbox_nomem, format, va); - // NOTREACHED - abort(); // to suppress compiler warning or error -} - -THREAD_SAFE AS_PRINTF(1, 2) NORETURN inline void nomem(const char *format, ...) -{ - va_list va; - va_start(va, format); - vnomem(format, va); - // NOTREACHED -} - - -/// Output a formatted string to the output window [analog of printf()]. -/// Everything appearing on the output window may be written -/// to a text file. For this the user should define the following environment -/// variable: \n -/// set IDALOG=idalog.txt -/// -/// \param format printf() style message string. -/// \return number of bytes output - -THREAD_SAFE AS_PRINTF(1, 0) inline int vmsg(const char *format, va_list va) -{ - return callui(ui_msg, format, va).i; -} - -THREAD_SAFE AS_PRINTF(1, 2) inline int msg(const char *format, ...) -{ - va_list va; - va_start(va, format); - int nbytes = vmsg(format, va); - va_end(va); - return nbytes; -} - - - -#ifndef SWIG - -/*! \defgroup FORM_C ask_form()/open_form() - - \brief This module describes how to generate a custom form. - -
-
-  The following keywords might appear at the beginning of the 'form' argument
-  (case insensitive):
-
-  STARTITEM number
-
-    where number is a number of input field the cursor will stand on.
-    By default the cursor is in the first field of the dialog box.
-    The input fields are numbered from 0 (the first field is field 0).
-
-  BUTTON name caption
-
-    Alternative caption for a button. It may contain the character
-    to highlight in this form:  ~Y~es
-    Valid button names are: YES, NO, CANCEL
-    For example:
-        BUTTON YES Please do
-        BUTTON NO Nope
-        BUTTON CANCEL NONE
-
-    By default the NO button is not displayed. If it is displayed, then
-    the return value of the function will be different!
-    (see the function description)
-
-    Empty text means that there won't be any corresponding button.
-    (you may also use NONE as the caption to hide it)
-
-    A * after the button name means that this button will be the default:
-
-      BUTTON CANCEL* Cancel
-
-  Next, if the dialog box is kept in IDA.HLP, the following may appear:
-  (this defines help context for the whole dialog box)
-
-  @hlpMessageName[]
-
-  If the form is not in IDA.HLP file, then it can have a built-in
-  help message. In this case the help screen should be enclosed in the
-  following keywords:
-
-  HELP
-  ....
-  ....
-  ....
-  ENDHELP
-
-  Each keyword should be on a separate line.
-
-  Next there must be the title line and two empty lines.
-  Most of the text in the dialog box text string is copied to the dialog
-  without modification. There are three special cases:
-
-        - dynamic labels (format parameters)
-        - callback arguments
-        - input fields
-
-  For example, this dialog box:
-
-  ------ format:
-        Sample dialog box
-
-
-        This is sample dialog box for %A
-        using address %$
-
-        <~E~nter value:N::18::>
-
-  ------
-
-  Contains two dynamic labels (text %A and address %$) and one input field
-  (numerical input box with the label "Enter value").
-
-  Parameters for the dynamic labels and input fields are taken from the
-  function's input arguments (va_list). The corresponding argument should
-  contain a pointer (sic, pointer) to the value to be displayed.
-
-  The dialog box above should be called as
-
-                \code
-                char *string = "something";
-                ea_t addr = someaddr;
-                uval_t answer = 0;
-                int ok = ask_form(format, string, &addr, &answer);
-                \endcode
-
-
-  Dynamic labels are used to specify variant parts of the dialog box text.
-  They use the following syntax:
-
-        %nT
-
-  where
-        n  - optional decimal field ID, which may be used in the
-             ::form_actions_t calls to get/set label value at runtime
-        T  - a character specifying type of input field. All input field
-             types (except B and K) are valid format specifiers. See below
-             for the list.
-
-
-  There are two special specifiers for callbacks:
-
-  The combination '%/' corresponds to a callback function that will be
-  called when any of the fields is modified. The callback type is ::formchgcb_t.
-  There can be only one such callback. It corresponds to the first variadic
-  argument regardless of its exact position in the format string.
-
-  The combination '%*' is used to store user data (void *) in the form.
-  This data can be later retrieved from the ::formchgcb_t callback via the
-  form action method get_ud().
-
-  Input fields use the following syntax:
-
-  
-
-  where
-        label - any text string serving as label for the input field
-                the label may contain an accelerator key like this: "~O~pen"
-                (O is the accelerator key; Alt-O will work too)
-        type  - a character specifying type of input field.
-                The form() function will perform initial validation of
-                value specified by the user and convert it appropriately.
-                See table of input field types below. The type can be followed
-                by a decimal number, an input field ID.
-        width - for A, I, T, X: decimal number specifying size of the buffer
-                  passed for text input fields (including terminating 0).
-                  if omitted or <0, assumed to be at least MAXSTR
-
-                for B, k: the code generated when the user presses the button (passed to the button callback)
-                for f (path to file) this attribute specifies the dialog type:
-                  0-'open file' dialog box
-                  1-'save file' dialog box
-                for F (folder) it is ignored (buffer is assumed to be at least QMAXPATH long)
-                for b (dropdown list) this attribute specifies the readonly attribute:
-                  0   - read-only dropdown list
-                  > 0 - editable dropdown list
-                for i, q: decimal number specifying maximum possible number
-                  of characters that can be entered into the input field
-                for the rest of controls: this field is ignored
-        swidth -decimal number specifying width of visible part of input field.
-                this number may be omitted.
-        @hlp[]- help context for the input field. you may replace the
-                help context with '::' (two colons) if you don't want to
-                specify help context. The help context is a number of help
-                page from IDA.HLP file.
-
-
-  Input field types                               va_list parameter
-  -----------------                               -----------------
-
-  q - UTF-8 string                                ::qstring*
-  h - HTML text                                   char * (only for GUI version; only for dynamic labels; no input)
-  S - segment                                     ::sel_t*
-  N - hex number, C notation                      ::uval_t*
-  n - signed hex number, C notation               ::sval_t*
-  L - C notation number                           ::uint64*
-      (prefix 0x - hex, 0 - octal, otherwise decimal)
-  l - same as L but with optional sign            ::int64*
-  M - hex number, no "0x" prefix                  ::uval_t*
-  D - decimal number                              ::sval_t*
-  O - octal number, C notation                    ::sval_t*
-  Y - binary number, "0b" prefix                  ::sval_t*
-  H - char value, C notation                      ::sval_t*
-  $ - address                                     ::ea_t*
-  I - ident                                       char* at least #MAXNAMELEN size (obsolete, will be removed)
-  i - ident                                       ::qstring*
-  B - button                                      ::buttoncb_t*
-  k - txt: button (same as B)/gui: hyperlink      ::buttoncb_t*
-  K - color button                                ::bgcolor_t*
-  F - path to folder                              char* at least #QMAXPATH size
-  f - path to file                                char* at least #QMAXPATH size
-  T - type declaration                            char* at least #MAXSTR size, obsolete, see below
-  y - type declaration                            ::qstring*
-  X - command                                     char* at least #MAXSTR size
-  E - chooser                                     ::chooser_base_t * - embedded chooser
-                                                  ::sizevec_t * - in/out: selected lines (0-based)
-                                                    (NB: this field takes two args)
-  t - multi line text control                     ::textctrl_info_t *
-  b - dropdown list                               ::qstrvec_t * - the list of items
-                                                  int* or ::qstring* - the preselected item
-                                                    (::qstring* when the combo is editable, i.e. width field is >0)
-
-  A - UTF-8 string                                char* at least MAXSTR size, obsolete. Use 'q' instead.
-
-  The M, n, N, D, O, Y, H, $ fields try to parse the input as an IDC expression
-  and convert the result into the required value type
-
-  If the buffer for 'F' field contains filemasks and descriptions like this:
-    *.exe|Executable files,*.dll|Dll files
-  they will be used in the dialog box filter.
-
-  The hint message can be specified before the label enclosed in '#':
-
-  <#hint message#label:...>
-
-  Radiobuttons and checkboxes are represented by:
-
-  
-  >         - end of block
-
-  where valid types are C and R
-  (you may use lowercase 'c' and 'r' if you need to create two radiobutton
-  or checkbox groups on the same lines). The field ID of the whole group
-  can be specified between the brackets: ID>
-
-  field types           va_list parameter
-  -----------           -----------------
-
-  C - checkbox          ushort*                 bit mask of checkboxes
-  R - radiobutton       ushort*                 number of radiobutton
-
-  The box title and hint messages can be specified like this:
-
-  <#item hint#title#box hint#label:type>
-
-  The title and the box hint can be specified only in the first item of the box.
-  If the hint doesn't exist, it should be specified as an empty hint (##title##)
-  The subsequent items can have an item hint only:
-
-  <#item hint#label:type>
-
-  Initial values of input fields are specified in the corresponding
-  input/output parameters (taken from va_list array).
-
-  OK, Cancel and (possibly) Help buttons are displayed at the bottom of
-  the dialog box automatically. Their captions can be changed by the BUTTON
-  keywords described at the beginning of this page.
-
-  Input field definition examples:
-
-   
-   <~A~nalysis enabled:C>
-   <~I~ndicator enabled:C>>
-   
-   <~O~utput file:f:1:64::>
-   <~O~utput directory:F::64::>
-
-  Resizable fields can be separated by splitters (GUI only).
-
-  A vertical splitter is represented by <|>. E.g.,:
-    <~Chooser~:E1:0:40:::><|><~E~ditor:t2:0:40:::>
-  whereas a horizontal splitter is represented by <->. E.g.,:
-    <~Chooser~:E1:0:40:::>
-    <->
-    <~E~ditor:t2:0:40:::>
-
-  
-*/ -//@{ -//---------------------------------------------------------------------- -// F O R M S - C O M P L E X D I A L O G B O X E S -//---------------------------------------------------------------------- - -/// See ask_form() - -inline int vask_form(const char *format, va_list va) -{ - return callui(ui_ask_form, format, va).i; -} - -/// Display a dialog box and wait for the user. -/// If the form contains the "BUTTON NO " keyword, then the return values -/// are the same as in the ask_yn() function (\ref ASKBTN_) -/// \param form dialog box as a string. see \ref FORM_C -/// \retval 0 the user pressed Esc, no memory to display or form syntax error -/// a dialog box (a warning is displayed in this case). -/// all variables retain their original values. -/// \retval 1 ok, all input fields are filled and validated. -/// \retval -1 the form had BUTTON CANCEL and the user cancelled the dialog - -inline int ask_form(const char *form, ...) -{ - va_list va; - va_start(va, form); - int code = vask_form(form, va); - va_end(va); - return code; -} - - -/// Create and/or activate dockable modeless form (::ui_open_form). -/// \param format string -/// \param flags \ref WIDGET_OPEN -/// \param va args -/// \return pointer to resulting TWidget - -inline TWidget *vopen_form(const char *format, uint32 flags, va_list va) -{ - return (TWidget *)callui(ui_open_form, format, flags, va).vptr; -} - - -/// Display a dockable modeless dialog box and return a handle to it. -/// \param form dialog box as a string. see \ref FORM_C -/// \param flags \ref WIDGET_OPEN -/// \return handle to the form or NULL. -/// the handle can be used with TWidget functions: close_widget()/activate_widget()/etc - -inline TWidget *open_form(const char *form, uint32 flags, ...) -{ - va_list va; - va_start(va, flags); - TWidget *widget = vopen_form(form, flags, va); - va_end(va); - return widget; -} - -//@} FORM_C - - -/// Functions available from ::formchgcb_t. -/// For getters/setters for specific field values, see #DEF_SET_METHOD. -struct form_actions_t -{ - /// Get value of an input field. - /// \return false if no such field id or invalid field type (B) - virtual bool idaapi _get_field_value(int field_id, void *buf) = 0; - - /// Set value of an input field. - /// \return false if no such field id or invalid field type (B) - virtual bool idaapi _set_field_value(int field_id, const void *buf) = 0; - - /// Enable or disable an input field. - /// \return false if no such field id - virtual bool idaapi enable_field(int field_id, bool enable) = 0; - - /// Show or hide an input field. - /// \return false if no such field id - virtual bool idaapi show_field(int field_id, bool display) = 0; - - /// Move/Resize an input field. - /// Parameters specified as -1 are not modified. - /// \return false no such field id - virtual bool idaapi move_field(int field_id, int x, int y, int w, int h) = 0; - - /// Get currently focused input field. - /// \return -1 if no such field - virtual int idaapi get_focused_field(void) = 0; - - /// Set currently focused input field. - /// \return false if no such field id - virtual bool idaapi set_focused_field(int field_id) = 0; - - /// Refresh a field - virtual void idaapi refresh_field(int field_id) = 0; - - /// Close the form - virtual void idaapi close(int close_normally) = 0; - - /// Retrieve the user data specified through %* - virtual void *idaapi get_ud() = 0; - - /// Get value of an UTF-8 string input field. - /// \return false if no such field id or invalid field type (B) - virtual bool idaapi _get_str_field_value(int field_id, char *buf, const size_t bufsize) = 0; - -/// Helper to define functions in ::form_actions_t that get/set field values of different types. -/// Please see this file's source code for specific uses. -#define DEF_SET_METHOD(NAME, TYPE) \ - inline bool idaapi set_ ## NAME ## _value(int field_id, const TYPE *val) \ - { \ - return _set_field_value(field_id, val); \ - } -/// \copydoc DEF_SET_METHOD -#define DEF_FIELD_METHOD(NAME, TYPE) \ - inline bool idaapi get_ ## NAME ## _value(int field_id, TYPE *val) \ - { \ - return _get_field_value(field_id, val); \ - } \ - DEF_SET_METHOD(NAME, TYPE) -/// \copydoc DEF_SET_METHOD -#define DEF_STR_FIELD_METHOD(NAME ) \ - inline bool idaapi get_ ## NAME ## _value(int field_id, char *buf, const size_t bufsize) \ - { \ - return _get_str_field_value(field_id, buf, bufsize); \ - } \ - DEF_SET_METHOD(NAME, char) - - // get/set value of radio button (r, R) - DEF_FIELD_METHOD(radiobutton, ushort) - // get/set value of radio button group - DEF_FIELD_METHOD(rbgroup, ushort) - // get/set value of check box (c, C) - DEF_FIELD_METHOD(checkbox, ushort) - // get/set value of check box group - DEF_FIELD_METHOD(cbgroup, ushort) - // get/set value of color control (K) - DEF_FIELD_METHOD(color, bgcolor_t) - // get/set embedded chooser selected items (E) - DEF_FIELD_METHOD(chooser, sizevec_t) - // get/set value of editable combo box (b when field 'width' >0) - DEF_FIELD_METHOD(combobox, qstring) - // get/set selected item of read-only combo box (b when field 'width' ==0) - DEF_FIELD_METHOD(combobox, int) - // get/set value of multiline text input control (t) - DEF_FIELD_METHOD(text, textctrl_info_t) - // get/set text of buttons - DEF_FIELD_METHOD(button, qstring) - // get/set value of dynamic label (%) - DEF_STR_FIELD_METHOD(label) - // get/set string value (A, I, T) - DEF_STR_FIELD_METHOD(string) - // get/set string value (q) - DEF_FIELD_METHOD(string, qstring) - // get/set value of segment (S) - DEF_FIELD_METHOD(segment, sel_t) - // get/set signed value (n,D,O,Y,H) - DEF_FIELD_METHOD(signed, sval_t) - // get/set unsigned value (N, M) - DEF_FIELD_METHOD(unsigned, uval_t) - // get/set value of default base (usually hex) number (l) - DEF_FIELD_METHOD(int64, int64) - // get/set value of default base (usually hex) number (L) - DEF_FIELD_METHOD(uint64, uint64) - // get/set address value ($) - DEF_FIELD_METHOD(ea, ea_t) - // get/set path value (F,f) - DEF_STR_FIELD_METHOD(path) - // get/set identifier value (I) - DEF_FIELD_METHOD(ident, qstring) - -#undef DEF_FIELD_METHOD -#undef DEF_SET_METHOD -#undef DEF_STR_FIELD_METHOD -}; - - -/// Callback. Called when an input field is modified. -/// The callback will be also called before displaying the form and as soon -/// as the user presses OK. -/// \param field_id id of the modified field -/// \retval -1 form is going to be displayed -/// \retval -2 form is going to be closed with OK. -/// \retval >0 form will be closed - -typedef int idaapi formchgcb_t(int field_id, form_actions_t &fa); - - -/// Callback. Called when a button is clicked. -/// \param button_code button code as specified in the form -/// \retval 0 currently ignored - -typedef int idaapi buttoncb_t(int button_code, form_actions_t &fa); - - -#endif // SWIG - -//--------------------------------------------------------------------------- -// Y E S / N O D I A L O G B O X -//--------------------------------------------------------------------------- - -/// \defgroup ASKBTN_ Button IDs -/// used by ask_yn() and ask_buttons() -//@{ -#define ASKBTN_YES 1 ///< Yes button -#define ASKBTN_NO 0 ///< No button -#define ASKBTN_CANCEL -1 ///< Cancel button -#define ASKBTN_BTN1 1 ///< First (Yes) button -#define ASKBTN_BTN2 0 ///< Second (No) button -#define ASKBTN_BTN3 -1 ///< Third (Cancel) button -//@} - - -THREAD_SAFE AS_PRINTF(5, 0) inline int vask_buttons( - const char *Yes, - const char *No, - const char *Cancel, - int deflt, - const char *format, - va_list va) -{ - return callui(ui_ask_buttons, Yes, No, Cancel, deflt, format, va).i; -} - - -AS_PRINTF(2, 0) inline int vask_yn(int deflt, const char *format, va_list va) -{ - return vask_buttons(NULL, NULL, NULL, deflt, format, va); -} - - -/// Display a dialog box and get choice from "Yes", "No", "Cancel". -/// \param deflt default choice: one of \ref ASKBTN_ -/// \param format The question in printf() style format -/// \return the selected button (one of \ref ASKBTN_). Esc key returns #ASKBTN_CANCEL. - -AS_PRINTF(2, 3) inline int ask_yn(int deflt, const char *format, ...) -{ - va_list va; - va_start(va, format); - int code = vask_yn(deflt, format, va); - va_end(va); - return code; -} - - -/// Display a dialog box and get choice from maximum three possibilities (::ui_ask_buttons). -/// \note for all buttons: -/// - use "" or NULL to take the default name for the button. -/// - use 'format' to hide the cancel button -/// \param Yes text for the first button -/// \param No text for the second button -/// \param Cancel text for the third button -/// \param deflt default choice: one of \ref ASKBTN_ -/// \param format printf-style format string for question. It may have some prefixes, see below. -/// \param va parameters for the format string -/// \return one of \ref ASKBTN_ specifying the selected button (Esc key returns Cancel/3rd button value) - -AS_PRINTF(5, 6) inline int ask_buttons( - const char *Yes, - const char *No, - const char *Cancel, - int deflt, - const char *format, - ...) -{ - va_list va; - va_start(va, format); - int code = vask_buttons(Yes, No, Cancel, deflt, format, va); - va_end(va); - return code; -} - -//------------------------------------------------------------------------ -/* Format of dialog box (actually they are mutliline strings - delimited by newline characters) - - The very first line of dialog box can specify a dialog box - title if the following line appears: - - TITLE title string - - - Then, the next line may contain an icon to display - in the GUI version (ignored by the text version): - - ICON NONE (no icon) - INFO (information icon) - QUESTION (question icon) - WARNING (warning icon) - ERROR (error icon) - - - Then, the next line may contain a 'Don't display this message again' - checkbox. If this checkbox is selected and the user didn't select cancel, - the button he selected is saved and automatically returned. - - AUTOHIDE NONE (no checkbox) - DATABASE (return value is saved to database) - REGISTRY (return value is saved to Windows registry or idareg.cfg - if non-Windows version) - SESSION (return value is saved for the current IDA session) - It is possible to append "*" to the AUTOHIDE keywords to have this checkbox - initially checked. For example: "AUTOHIDE REGISTRY*" - - To hide the cancel button the following keyword can be used: - - HIDECANCEL - - To enable rich text (i.e., HTML) in the Qt version of IDA, - the following keyword can be used: - - RICHTEXT - - Please note that the user still can cancel the dialog box by pressing Esc - or clicking on the 'close window' button. - - Finally, if the dialog box is kept in IDA.HLP, the following may appear - to add a Help button (this defines help context for the whole dialog box): - - @hlpMessageName[] - - - Each keyword should be alone on a line. - - Next, a format string must be specified. - To center message lines in the text version, start them with '\3' character - (currently ignored in the GUI version). -*/ - -//--------------------------------------------------------------------------- -// A S K S T R I N G O F T E X T -//--------------------------------------------------------------------------- - -/// Display a dialog box and wait for the user to input a text string (::ui_ask_str). -/// Use this function to ask one-line text. For multiline input, use ask_text(). -/// This function will trim the trailing spaces. -/// \param str qstring to fill. Can contain the default value. Cannot be NULL. -/// \param hist category of history lines. an arbitrary number. \n -/// this number determines lines accessible in the history \n -/// of the user input (when he presses down arrow) \n -/// One of \ref HIST_ should be used here -/// \param format printf() style format string with the question -/// \return false if the user cancelled the dialog, otherwise returns true. - -AS_PRINTF(3, 0) inline bool vask_str( - qstring *str, - int hist, - const char *format, - va_list va) -{ - return callui(ui_ask_str, str, hist, format, va).cnd; -} - -AS_PRINTF(3, 4) inline bool ask_str(qstring *str, int hist, const char *format, ...) -{ - va_list va; - va_start(va, format); - bool result = vask_str(str, hist, format, va); - va_end(va); - return result; -} - -/// \defgroup HIST_ Input line history constants -/// passed as 'hist' parameter to ask_str() -//@{ -#define HIST_SEG 1 ///< segment names -#define HIST_CMT 2 ///< comments -#define HIST_SRCH 3 ///< search substrings -#define HIST_IDENT 4 ///< names -#define HIST_FILE 5 ///< file names -#define HIST_TYPE 6 ///< type declarations -#define HIST_CMD 7 ///< commands -#define HIST_DIR 8 ///< directory names (text version only) -//@} - - -/// Display a dialog box and wait for the user to input an identifier. -/// If the user enters a non-valid identifier, this function displays a warning -/// and allows the user to correct it. -/// \param str qstring to fill. Can contain the default value. Cannot be NULL. -/// \param format printf() style format string with the question -/// \return false if the user cancelled the dialog, otherwise returns true. - -AS_PRINTF(2, 3) inline bool ask_ident(qstring *str, const char *format, ...) -{ - va_list va; - va_start(va, format); - bool result = vask_str(str, HIST_IDENT, format, va); - va_end(va); - return result; -} - - -/// Display a dialog box and wait for the user to input multiline text (::ui_ask_text). -/// \param answer output buffer -/// \param max_size maximum size of text in bytes including terminating zero (0 for unlimited) -/// \param defval default value. will be displayed initially in the input line. -/// may be NULL. -/// \param format printf() style format string with the question. -/// the following options are accepted at its beginning: -/// "ACCEPT TABS\n": accept tabulations in the input -/// "NORMAL FONT\n": use regular font (otherwise the notepad font) -/// \return false-if the user pressed Esc, otherwise returns true. - -AS_PRINTF(4, 0) inline bool vask_text( - qstring *answer, - size_t max_size, - const char *defval, - const char *format, - va_list va) -{ - return callui(ui_ask_text, answer, max_size, defval, format, va).cnd; -} - -AS_PRINTF(4, 5) inline bool ask_text( - qstring *answer, - size_t max_size, - const char *defval, - const char *format, - ...) -{ - va_list va; - va_start(va, format); - bool result = vask_text(answer, max_size, defval, format, va); - va_end(va); - return result; -} - - -//--------------------------------------------------------------------------- -// A S K A D D R E S S E S , N A M E S , N U M B E R S , E T C . -//--------------------------------------------------------------------------- - -/// Display a dialog box and wait for the user to input a file name (::ui_ask_file). -/// This function displays a window with file names present in the directory -/// pointed to by 'defval'. -/// -/// The 'format' parameter can contain a 'FILTER' description, of the -/// form 'description1|{wildcard1}+|...|descriptionN|{wildcardsN}+', -/// where each file type description has a corresponding set of one -/// (or more) ';'-separated mask(s). E.g., -/// \code -/// Text files|*.txt|Executable files|*.exe;*.bin -/// \endcode -/// -/// \param for_saving will the filename be used to save a file? -/// \param defval default value. will be displayed initially in the input line. -/// may be NULL may be or a wildcard file name. -/// \param format printf-style format string with the dialog title, possibly including a filter. -/// \return NULL the user cancelled the dialog. -/// Otherwise the user entered a valid file name. - -AS_PRINTF(3, 0) inline char *vask_file( - bool for_saving, - const char *defval, - const char *format, - va_list va) -{ - return callui(ui_ask_file, for_saving, defval, format, va).cptr; -} - - -AS_PRINTF(3, 4) inline char *ask_file( - bool for_saving, - const char *defval, - const char *format, - ...) -{ - va_list va; - va_start(va, format); - char *answer = vask_file(for_saving, defval, format, va); - va_end(va); - return answer; -} - - -//--------------------------------------------------------------------------- -// A D D - O N S -//--------------------------------------------------------------------------- - -/// Information about an installed add-on (e.g. a plugin) -struct addon_info_t -{ - size_t cb; //< size of this structure - const char *id; //< product code, e.g. "com.hexrays.hexx86w". Must be unique - const char *name; //< descriptive name, e.g. "Hex-Rays x86 Decompiler (Windows)" - const char *producer; //< e.g. "Hex-Rays SA" - const char *version; //< version string, e.g. 1.5.110408 - const char *url; //< URL of the product http://www.hex-rays.com/decompiler.shtml - const char *freeform; //< any string, e.g. "Copyright (c) 2007-2020 Hex-Rays" - const void *custom_data; //< custom data (license ID etc). Can be NULL. Not displayed in UI. - size_t custom_size; - - /// Constructor - addon_info_t() - : cb(sizeof(addon_info_t)), - id(nullptr), - name(nullptr), - producer(nullptr), - version(nullptr), - url(nullptr), - freeform(nullptr), - custom_data(nullptr), - custom_size(0) - {} -}; - -#ifndef __UI__ - -/// \defgroup ui_addons_funcs Functions: add-ons -/// Convenience functions for ::ui_addons -//@{ - -/// Register an add-on. Show its info in the About box. -/// For plugins, should be called from init() function -/// (repeated calls with the same product code overwrite previous entries) -/// returns: index of the add-on in the list, or -1 on error - -inline int register_addon(const addon_info_t *info) -{ - return callui(ui_addons, 0, info).i; -} - - -/// Get number of installed addons - -inline int addon_count() -{ - return callui(ui_addons, 1).i; -} - - -/// Get info about a registered addon with a given product code. -/// info->cb must be valid! -/// NB: all pointers are invalidated by next call to register_addon or get_addon_info -/// \return false if not found - -inline bool get_addon_info(const char *id, addon_info_t *info) -{ - return callui(ui_addons, 2, id, info).cnd; -} - - -/// Get info about a registered addon with specific index. -/// info->cb must be valid! -/// NB: all pointers are invalidated by next call to register_addon or get_addon_info -/// \return false if index is out of range - -inline bool get_addon_info_idx(int index, addon_info_t *info) -{ - return callui(ui_addons, 3, index, info).cnd; -} - -//@} ui_addons_funcs - -#endif - -//--------------------------------------------------------------------------- -// S T R I N G F U N C T I O N S -//--------------------------------------------------------------------------- -/// \defgroup str_funcs Functions: strings -/// functions that manipulate strings -//@{ - -/// Add space characters to the colored string so that its length will be at least -/// 'len' characters. Don't trim the string if it is longer than 'len'. -/// \param str pointer to colored string to modify (may not be NULL) -/// \param bufsize size of the buffer with the string -/// \param len the desired length of the string -/// \return pointer to the end of input string - -idaman THREAD_SAFE char *ida_export add_spaces(char *str, size_t bufsize, ssize_t len); - - -/// Remove trailing space characters from a string. -/// \param str pointer to string to modify (may be NULL) -/// \return pointer to input string - -idaman THREAD_SAFE char *ida_export trim(char *str); - - -/// Skip whitespaces in the string. -/// \return pointer to first non-whitespace char in given string - -idaman THREAD_SAFE const char *ida_export skip_spaces(const char *ptr); -inline char *skip_spaces(char *ptr) ///< \copydoc skip_spaces() - { return CONST_CAST(char*)(skip_spaces((const char *)ptr)); } - -/// Map strings to integer values - see strarray() -struct strarray_t -{ - int code; - const char *text; -}; - - -/// \defgroup CLNL_ line cleanup flags -/// Passed as 'flags' parameter to qcleanline() -//@{ -#define CLNL_RTRIM (1 << 0) ///< Remove trailing space characters. -#define CLNL_LTRIM (1 << 1) ///< Remove leading space characters. -#define CLNL_FINDCMT (1 << 2) ///< Search for the comment symbol everywhere in the line, not only at the beginning - -#define CLNL_TRIM (CLNL_RTRIM|CLNL_LTRIM) -//@} - -/// Performs some cleanup operations to a line. -/// \param buf string to modify -/// \param cmt_char character that denotes the start of a comment: -/// - the entire text is removed if the line begins with -/// this character (ignoring leading spaces) -/// - all text after (and including) this character is removed -/// if flag CLNL_FINDCMT is set -/// \param flags a combination of \ref CLNL_. defaults to CLNL_TRIM -/// \return length of line - -idaman THREAD_SAFE ssize_t ida_export qcleanline( - qstring *buf, - char cmt_char='\0', - uint32 flags=CLNL_TRIM|CLNL_FINDCMT); - - -/// Find a line with the specified code in the ::strarray_t array. -/// If the last element of the array has code==0 then it is considered as the default entry. \n -/// If no default entry exists and the code is not found, strarray() returns "". - -idaman THREAD_SAFE const char *ida_export strarray(const strarray_t *array, size_t array_size, int code); - - -/// Convert linear address to UTF-8 string - -idaman size_t ida_export ea2str(char *buf, size_t bufsize, ea_t ea); - -#ifndef SWIG - -//--------------------------------------------------------------------------- -// C O N V E R S I O N S -//--------------------------------------------------------------------------- -/// \defgroup conv Functions: string conversion -/// functions that convert between string encodings -//@{ - -/// Convert linear address to UTF-8 string -inline bool ea2str(qstring *out, ea_t ea) -{ - char tmp[MAXSTR]; - if ( ea2str(tmp, sizeof(tmp), ea) <= 0 ) - return false; - *out = tmp; - return true; -} - - -/// Convert string to linear address. -/// Tries to interpret the string as: \n -/// 1) "current IP" keyword if supported by assembler (e.g. "$" in x86) \n -/// 2) segment:offset expression, where "segment" may be a name or a fixed segment register (e.g. cs, ds) \n -/// 3) just segment name/register (translated to segment's start address) \n -/// 4) a name in the database (or debug name during debugging) \n -/// 5) +delta or -delta, where numerical 'delta' is added to or subtracted from 'screenEA' \n -/// 6) if all else fails, try to evaluate 'str' as an IDC expression - -idaman bool ida_export str2ea(ea_t *ea_ptr, const char *str, ea_t screen_ea); - - -/// Same as str2ea() but possibly with some steps skipped. -/// \param flags \ref S2EAOPT_ - -idaman bool ida_export str2ea_ex(ea_t *ea_ptr, const char *str, ea_t screen_ea, int flags); - -/// \defgroup S2EAOPT_ String to address conversion flags -/// passed as 'flags' parameter to str2ea_ex() -//@{ -#define S2EAOPT_NOCALC 0x00000001 ///< don't try to interpret string as IDC (or current extlang) expression -//@} - - -/// Convert a number in C notation to an address. -/// decimal: 1234 \n -/// octal: 0123 \n -/// hexadecimal: 0xabcd \n -/// binary: 0b00101010 - -idaman bool ida_export atoea(ea_t *pea, const char *str); - - -/// Convert segment selector to UTF-8 string - -idaman size_t ida_export stoa(qstring *buf, ea_t from, sel_t seg); - - -/// Convert UTF-8 string to segment selector. -/// \retval 0 fail -/// \retval 1 ok (hex) -/// \retval 2 ok (segment name or reg) - -idaman int ida_export atos(sel_t *seg, const char *str); - - -#define MAX_NUMBUF (128+8) ///< 16-byte value in binary base (0b00101010...) - - -/// Get the number of UTF-8 characters required to represent -/// a number with the specified number of bytes and radix. -/// \param nbytes if 0, use default number of bytes, usually 4 or 8 depending on __EA64__ -/// \param radix if 0, use default radix, usually 16 - -idaman size_t ida_export b2a_width(int nbytes, int radix); - - -/// Convert number to UTF-8 string (includes leading zeroes). -/// \param x value to convert -/// \param buf output buffer -/// \param bufsize size of output buffer -/// \param nbytes 1, 2, 3, or 4 -/// \param radix 2, 8, 10, or 16 -/// \return size of resulting string - -idaman size_t ida_export b2a32(char *buf, size_t bufsize, uint32 x, int nbytes, int radix); - - -/// Same as b2a32(), but can handle 'nbytes' = 8 - -idaman size_t ida_export b2a64(char *buf, size_t bufsize, uint64 x, int nbytes, int radix); - - - -/// Get max number of UTF-8 characters required to represent -/// a given type of value, with a given size (without leading zeroes). -/// \param nbytes size of number -/// \param flag should be one of FF_ for #MS_0TYPE -/// \param n if 1, shr 'flag' by 4 - -idaman size_t ida_export btoa_width(int nbytes, flags_t flag, int n); - - -/// Same as b2a32(), but will generate a string without any leading zeroes. -/// Can be used to output some numbers in the instructions. - -idaman size_t ida_export btoa32(char *buf, size_t bufsize, uint32 x, int radix=0); - - -/// 64-bit equivalent of btoa32() - -idaman size_t ida_export btoa64(char *buf, size_t bufsize, uint64 x, int radix=0); - - -/// 128-bit equivalent of btoa32() - -idaman size_t ida_export btoa128(char *buf, size_t bufsize, uint128 x, int radix=0); - -#ifdef __EA64__ -#define b2a b2a64 -#define btoa btoa64 -#define atob atob64 -#else -#define b2a b2a32 ///< shortcut for number->string conversion, see b2a32() -#define btoa btoa32 ///< shortcut for number->string conversion, see btoa32() -#define atob atob32 ///< shortcut for string->number conversion, see atob32() -#endif - - -/// Convert instruction operand immediate number to UTF-8. -/// This is the main function to output numbers in the instruction operands. \n -/// It prints the number with or without the leading zeroes depending on the flags. \n -/// This function is called from out_value(). Please use out_value() if you can. - -idaman size_t ida_export numop2str( - char *buf, - size_t bufsize, - ea_t ea, - int n, - uint64 x, - int nbytes, - int radix=0); - - -/// Convert UTF-8 to a number using the current assembler formats. -/// e.g. for ibmpc, '12o' is octal, '12h' is hex, etc. -/// \return success - -idaman bool ida_export atob32(uint32 *x, const char *str); - - -/// 64-bit equivalent of atob32() - -idaman bool ida_export atob64(uint64 *x, const char *str); // returns 1-ok - - -/// Auxiliary function. -/// Print displacement to a name (+disp or -disp) in the natural radix -/// \param buf output buffer to append to -/// \param disp displacement to output. 0 leads to no modifications -/// \param tag whether to output color tags - -idaman void ida_export append_disp(qstring *buf, adiff_t disp, bool tag=true); - - -/// Convert RADIX50 -> UTF-8. -/// \param p pointer to UTF-8 string -/// \param r pointer to radix50 string -/// \param k number of elements in the input string \n -/// (element of radix50 string is a word) \n -/// (element of UTF-8 string is a character) -/// \return number of elements left unprocessed in the input string, \n -/// because the input string contains unconvertible elements. \n -/// 0-ok, all elements are converted - -idaman THREAD_SAFE int ida_export r50_to_asc(char *p, const ushort *r, int k); - - -/// Convert UTF-8 -> RADIX50 (see r50_to_asc()) - -int THREAD_SAFE asc_to_r50(ushort *r, const char *p, int k); - - -//@} Conversion functions -//@} String functions - -//---------------------------------------------------------------------------- - -/// Calculate CRC32 (polynom 0xEDB88320, zlib compatible). -/// \note in IDA versions before 6.0 a different, incompatible algorithm was used - -idaman THREAD_SAFE uint32 ida_export calc_crc32(uint32 crc, const void *buf, size_t len); - - -/// Calculate an input source CRC32 - -idaman THREAD_SAFE uint32 ida_export calc_file_crc32(linput_t *fp); - - -/// Match a string with a regular expression. -/// \retval 0 no match -/// \retval 1 match -/// \retval -1 error - -idaman int ida_export regex_match(const char *str, const char *pattern, bool sense_case); - - -//---------------------------------------------------------------------------- -/// \cond -#define IS_BUTTONCB_T(v) (std::is_same<decltype(v), buttoncb_t>::value) -#define IS_FORMCHGCB_T(v) (std::is_same<decltype(v), formchgcb_t>::value) -#define IS_TEXTCTRL_INFO_T(v) (std::is_base_of<textctrl_info_t, std::remove_reference<decltype(v)>::type>::value) -#define IS_CHOOSER_BASE_T(v) (std::is_base_of<chooser_base_t, std::remove_reference<decltype(v)>::type>::value) - -/// \endcond - -#endif // SWIG - -//---------------------------------------------------------------------------- -/// \defgroup winkeys Compatibility Windows virtual keys -/// compatibility windows virtual keys to use in plugins which are not Qt aware. (check the #CVH_QT_AWARE flag) -/// these keys are provided for compilation of older plugins that use windows virtual keys on all platforms. -/// those constants are currently passed to cli_t->keydown and customview/CVH_KEYDOWN handlers. -//@{ -#define IK_CANCEL 0x03 -#define IK_BACK 0x08 -#define IK_TAB 0x09 -#define IK_CLEAR 0x0C -#define IK_RETURN 0x0D -#define IK_SHIFT 0x10 -#define IK_CONTROL 0x11 -#define IK_MENU 0x12 -#define IK_PAUSE 0x13 -#define IK_CAPITAL 0x14 -#define IK_KANA 0x15 -#define IK_ESCAPE 0x1B -#define IK_MODECHANGE 0x1F -#define IK_SPACE 0x20 -#define IK_PRIOR 0x21 -#define IK_NEXT 0x22 -#define IK_END 0x23 -#define IK_HOME 0x24 -#define IK_LEFT 0x25 -#define IK_UP 0x26 -#define IK_RIGHT 0x27 -#define IK_DOWN 0x28 -#define IK_SELECT 0x29 -#define IK_PRINT 0x2A -#define IK_EXECUTE 0x2B -#define IK_SNAPSHOT 0x2C -#define IK_INSERT 0x2D -#define IK_DELETE 0x2E -#define IK_HELP 0x2F -#define IK_LWIN 0x5B -#define IK_RWIN 0x5C -#define IK_APPS 0x5D -#define IK_SLEEP 0x5F -#define IK_NUMPAD0 0x60 -#define IK_NUMPAD1 0x61 -#define IK_NUMPAD2 0x62 -#define IK_NUMPAD3 0x63 -#define IK_NUMPAD4 0x64 -#define IK_NUMPAD5 0x65 -#define IK_NUMPAD6 0x66 -#define IK_NUMPAD7 0x67 -#define IK_NUMPAD8 0x68 -#define IK_NUMPAD9 0x69 -#define IK_MULTIPLY 0x6A -#define IK_ADD 0x6B -#define IK_SEPARATOR 0x6C -#define IK_SUBTRACT 0x6D -#define IK_DECIMAL 0x6E -#define IK_DIVIDE 0x6F -#define IK_F1 0x70 -#define IK_F2 0x71 -#define IK_F3 0x72 -#define IK_F4 0x73 -#define IK_F5 0x74 -#define IK_F6 0x75 -#define IK_F7 0x76 -#define IK_F8 0x77 -#define IK_F9 0x78 -#define IK_F10 0x79 -#define IK_F11 0x7A -#define IK_F12 0x7B -#define IK_F13 0x7C -#define IK_F14 0x7D -#define IK_F15 0x7E -#define IK_F16 0x7F -#define IK_F17 0x80 -#define IK_F18 0x81 -#define IK_F19 0x82 -#define IK_F20 0x83 -#define IK_F21 0x84 -#define IK_F22 0x85 -#define IK_F23 0x86 -#define IK_F24 0x87 -#define IK_NUMLOCK 0x90 -#define IK_SCROLL 0x91 -#define IK_OEM_FJ_MASSHOU 0x93 -#define IK_OEM_FJ_TOUROKU 0x94 -#define IK_LSHIFT 0xA0 -#define IK_RSHIFT 0xA1 -#define IK_LCONTROL 0xA2 -#define IK_RCONTROL 0xA3 -#define IK_LMENU 0xA4 -#define IK_RMENU 0xA5 -#define IK_BROWSER_BACK 0xA6 -#define IK_BROWSER_FORWARD 0xA7 -#define IK_BROWSER_REFRESH 0xA8 -#define IK_BROWSER_STOP 0xA9 -#define IK_BROWSER_SEARCH 0xAA -#define IK_BROWSER_FAVORITES 0xAB -#define IK_BROWSER_HOME 0xAC -#define IK_VOLUME_MUTE 0xAD -#define IK_VOLUME_DOWN 0xAE -#define IK_VOLUME_UP 0xAF -#define IK_MEDIA_NEXT_TRACK 0xB0 -#define IK_MEDIA_PREV_TRACK 0xB1 -#define IK_MEDIA_STOP 0xB2 -#define IK_MEDIA_PLAY_PAUSE 0xB3 -#define IK_LAUNCH_MAIL 0xB4 -#define IK_LAUNCH_MEDIA_SELECT 0xB5 -#define IK_LAUNCH_APP1 0xB6 -#define IK_LAUNCH_APP2 0xB7 -#define IK_OEM_1 0xBA -#define IK_OEM_PLUS 0xBB -#define IK_OEM_COMMA 0xBC -#define IK_OEM_MINUS 0xBD -#define IK_OEM_PERIOD 0xBE -#define IK_OEM_2 0xBF -#define IK_OEM_3 0xC0 -#define IK_OEM_4 0xDB -#define IK_OEM_5 0xDC -#define IK_OEM_6 0xDD -#define IK_OEM_7 0xDE -#define IK_OEM_102 0xE2 -#define IK_PLAY 0xFA -#define IK_ZOOM 0xFB -#define IK_OEM_CLEAR 0xFE -//@} - -/// Enumeration of form callback special values -enum cb_id -{ - CB_INIT = -1, - CB_YES = -2, - CB_CLOSE = -3, - CB_INVISIBLE = -4, // corresponds to ui_widget_invisible - CB_DESTROYING = -5, // when the actual widget tree is being destroyed -}; - -#ifndef SWIG -//------------------------------------------------------------------------- -inline void place_t__serialize(const place_t *_this, bytevec_t *out) -{ - out->pack_dd(_this->lnnum); -} - -//------------------------------------------------------------------------- -inline bool place_t__deserialize(place_t *_this, const uchar **pptr, const uchar *end) -{ - if ( *pptr >= end ) - return false; - _this->lnnum = unpack_dd(pptr, end); - return true; -} -#endif - - -#ifndef NO_OBSOLETE_FUNCS -/// Deprecated. Please use ACTION_DESC_LITERAL_* instead. -#define ACTION_DESC_LITERAL(name, label, handler, shortcut, tooltip, icon)\ - { sizeof(action_desc_t), name, label, handler, &PLUGIN, shortcut, tooltip, icon, ADF_OT_PLUGIN } -#endif - -#endif // __KERNWIN_HPP diff --git a/idasdk75/include/lex.hpp b/idasdk75/include/lex.hpp deleted file mode 100644 index a40fd87..0000000 --- a/idasdk75/include/lex.hpp +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef LEX_HPP -#define LEX_HPP - -/*! \file lex.hpp - - \brief Tools for parsing C-like input - - Functions in this file use objects of opaque type lexer_t. - To create a lexer_t instance, use create_lexer(). -*/ - -typedef ushort lxtype; ///< see \ref lx_ - -/// \defgroup lx_ Parser token types -/// See token_t::type -/// \note All separators have their ASCII codes as lxtype -//@{ -const lxtype - lx_end = 1, ///< no more tokens - lx_ident = 2, ///< ident - lx_number = 3, ///< long constant - lx_string = 4, ///< string constant (token_t.chr != 0 => unicode string) - lx_char = 5, ///< char constant - lx_typename = 6, ///< user-defined type - lx_float = 7, ///< IEEE floating point constant - lx_int64 = 8, ///< int64 constant - lx_key = 128; ///< keywords start. All keys are lx_key + keynum. \n - ///< Two-char separators are: (c1 + (c2 << 8)). \n - ///< Three-char separators: - ///< - "<<=" = ('<' + ('<'<<8)) + '=' - ///< - ">>=" = ('>' + ('>'<<8)) + '=' -//@} - - -/// Parser token -struct token_t -{ - qstring str; ///< idents & strings - lxtype type; ///< see \ref lx_ - sval_t num; ///< long & char constants - union - { - bool unicode; ///< (::lx_string: != 0 => unicode string) - bool is_unsigned; ///< (::lx_number, ::lx_int64: != 0 => unsigned value) - }; - union - { - ushort fnum[6]; ///< floating point constant - int64 i64; ///< ::lx_int64 - }; - token_t() : type(0), num(0), unicode(false) - { - // init maximum member of union - memset(&fnum[0], 0x00, sizeof(fnum)); - } -}; -DECLARE_TYPE_AS_MOVABLE(token_t); - -class lexer_t; // lexical analyzer, opaque structure - - -/// Preprocessor callback for unknown tokens. -/// Will be called when preprocessor calculates the value of #if expression. - -typedef error_t lx_resolver_t(lexer_t *lx, void *ud, token_t *curtok, sval_t *res); - -#ifdef _MSC_VER -#pragma warning(push) -// Conversion from 'type1 ' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. -// We want this sign-extension to happen, since it comes mostly from HANDLEs. -// (see https://msdn.microsoft.com/en-us/library/ms235307.aspx ) -#pragma warning(disable:4826) -#endif - -/// Preprocessor cast -struct cast_t -{ - bool is_unsigned; - int size; - - cast_t() - { - reset(); - } - void reset(void) - { - is_unsigned = false; - size = 0; - } -}; - -struct lex_value_t -{ - bool is_unsigned; - union - { - int64 val; - uint64 uval; - }; - - lex_value_t() - { - reset(); - } - void set(const lex_value_t &v) - { - set_val(v.val, v.is_unsigned); - } - void reset(void) - { - set_val(0, true); - } - void set_val(int64 v, bool _is_unsigned) - { - is_unsigned = _is_unsigned; - val = v; - } - - uint64 get_uval(void) const - { - return val; - } - int64 get_val(void) const - { - return val; - } - - bool is_zero(void) const - { - return get_val() == 0; - } - - void perform_cast(const cast_t &cast); - - void unary_minus(const lex_value_t &v); - void unary_plus(const lex_value_t &v); - void unary_not(const lex_value_t &v); - void bitwise_not(const lex_value_t &v); - - void mul(const lex_value_t &v); - void div(const lex_value_t &v); - void mod(const lex_value_t &v); - void add(const lex_value_t &v); - void sub(const lex_value_t &v); - - void shift_right(const lex_value_t &v); - void shift_left(const lex_value_t &v); - void bitwise_and(const lex_value_t &v); - void bitwise_xor(const lex_value_t &v); - void bitwise_or(const lex_value_t &v); - void logical_and(const lex_value_t &v); - void logical_or(const lex_value_t &v); - - void cmpge(const lex_value_t &v); - void cmple(const lex_value_t &v); - void cmplt(const lex_value_t &v); - void cmpgt(const lex_value_t &v); - void cmpeq(const lex_value_t &v); - void cmpneq(const lex_value_t &v); -}; - -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -/// Preprocessor callbacks for casts. -/// Will be called when preprocessor calculates the value of #if expression. - -typedef error_t lx_parse_cast_t(lexer_t *lx, cast_t *cast, token_t *ct); - -/// Preprocessor callback. -/// It will be called for each input line. -/// \return an error code (0-ok) - -typedef int idaapi lx_preprocessor_cb(void *ud, const char *fname, int nl, const char *line); - - -/// Callback for #pragma directives. -/// \return an error code (0-ok) - -typedef int idaapi lx_pragma_cb(void *ud, const char *line); - - -/// Callback for #warning directives. -/// \return an error code (0-ok) - -typedef int idaapi lx_warning_cb(void *ud, const char *line); - - -/// Callback for #define directives -/// \return an error code (0-ok) - -typedef int idaapi lx_macro_cb( - void *ud, - const char *name, - const char *body, - int nargs, - bool isfunc, - bool is_new_macro); - - -/// Callback for #undef directives -/// \return an error code (0-ok) - -typedef int idaapi lx_undef_cb(void *ud, const char *name); - - -/// Create new lexical analyzer and set its keyword table. -/// If keys==NULL, then set the default C keyword table - -idaman lexer_t *ida_export create_lexer( - const char *const *keys, - size_t size, - void *ud=NULL); - - -/// Destroy a lexical analyzer - -idaman void ida_export destroy_lexer(lexer_t *lx); - - -/// Define a macro - -idaman error_t ida_export lex_define_macro( - lexer_t *lx, - const char *macro, - const char *body, - int nargs=0, - bool isfunc=false); - -/// Undefine a macro - -idaman void ida_export lex_undefine_macro( - lexer_t *lx, - const char *macro); - -/// Set lexer options. -/// \param options \ref LXOPT_ -/// \return the old options - -idaman int ida_export lex_set_options(lexer_t *lx, int options); - -/// \defgroup LXOPT_ Lexer options -/// Passed as 'options' parameter to lex_set_options(). -/// By default all options are on. -//@{ -#define LXOPT_PARSE_FLOATS 0x0001 ///< enable floating point constants -#define LXOPT_REQ_SEPARATOR 0x0002 ///< require a separator between a number and an ident or a character/string constant or dot -#define LXOPT_NOCASE_FILES 0x0004 ///< case-insensitive file search -#define LXOPT_C99_CONSTANTS 0x0008 ///< the size and sign of constants depend on the value itself and the 'U', 'L', and 'LL' - ///< modifier suffixes. otherwise the constant is always considered as signed and the size - ///< depends only on the number of bytes in the value -//@} - - -/// Get next token -/// \param p_lnnum line number where the token starts - -idaman error_t ida_export lex_get_token(lexer_t *lx, token_t *t); -idaman error_t ida_export lex_get_token2(lexer_t *lx, token_t *t, int32 *p_lnnum); - - -/// Enumerate all macros. -/// Do so until 'cb' returns non-zero. - -idaman int ida_export lex_enum_macros( - const lexer_t *lx, - int idaapi cb(const char *name, const char *body, int nargs, bool isfunc, void *ud), - void *ud=NULL); - - -/// Debug: get text representation of token - -idaman const char *ida_export lex_print_token(qstring *buf, const token_t *t); - - -//------------------------------------------------------------------------- -/// \name String oriented functions -//@{ - -/// Set the input line and the macro table. -/// if macros==NULL, the macro table will not be changed. - -idaman error_t ida_export lex_init_string( - lexer_t *lx, - const char *line, - void *macros=NULL); -//@} - -//------------------------------------------------------------------------- -/// \name File oriented functions -//@{ - -/// Initialization: file may be NULL. -/// Also see lex_term_file(). - -idaman error_t ida_export lex_init_file(lexer_t *lx, const char *file); - - -/// Error handling. -/// if level > 0, then return information about the enclosing file which -/// included the current one. - -idaman const char *ida_export lex_get_file_line( - lexer_t *lx, - int32 *linenum, - const char **lineptr, - int level=0); - - -/// Termination: also see lex_init_file() - -idaman void ida_export lex_term_file(lexer_t *lx, bool del_macros); -//@} - -//------------------------------------------------------------------------- -/// \name Token stack -//@{ -typedef qstack<token_t> tokenstack_t; ///< see get_token(), unget_token() - - -/// Retrieve token from a stack or lexer. -/// If buf is not empty then get the token on top of the stack. -/// If buf is empty then gen the next token from the lexer. -/// \return success - -inline bool get_token(token_t *t, lexer_t *lx, tokenstack_t &buf) -{ - if ( !buf.empty() ) - *t = buf.pop(); - else if ( lex_get_token(lx, t) != eOk ) - return false; - return true; -} - - -/// Push a token back onto the token stack - -inline void unget_token(const token_t &t, tokenstack_t &buf) -{ - buf.push(t); -} -//@} - - -#endif // LEX_HPP diff --git a/idasdk75/include/lines.hpp b/idasdk75/include/lines.hpp deleted file mode 100644 index 2d02ec5..0000000 --- a/idasdk75/include/lines.hpp +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _LINES_HPP -#define _LINES_HPP - -#include <ida.hpp> - -/*! \file lines.hpp - - \brief High level functions that deal with the generation - of the disassembled text lines. - - This file also contains definitions for the syntax highlighting. - - Finally there are functions that deal with anterior/posterior - user-defined lines. -*/ - -struct range_t; - -//--------------------------------------------------------------------------- -// C O L O R D E F I N I T I O N S -//--------------------------------------------------------------------------- - -/// \defgroup color_def Color definitions -/// -/// Here we describe the structure of embedded escape sequences used to -/// implement syntax highlighting. -/// -/// IDP module should insert appropriate escape characters into the -/// output lines as necessary. This approach allows to create an IDP -/// module without the syntax highlighting too - just don't use -/// escape sequences. -/// -/// A typical color sequence looks like this: -/// -/// #COLOR_ON COLOR_xxx text #COLOR_OFF COLOR_xxx -/// -/// The first 2 items turn color 'xxx' on, then the text follows, -/// and the color is turned off by two last items. -/// -/// For the convenience we've defined a set of macro definitions -/// and functions to deal with colors. -//@{ - -/// \defgroup color_esc Color escape characters -/// Initiate/Terminate a color tag -//@{ -#define COLOR_ON '\1' ///< Escape character (ON). - ///< Followed by a color code (::color_t). -#define COLOR_OFF '\2' ///< Escape character (OFF). - ///< Followed by a color code (::color_t). -#define COLOR_ESC '\3' ///< Escape character (Quote next character). - ///< This is needed to output '\1' and '\2' - ///< characters. -#define COLOR_INV '\4' ///< Escape character (Inverse foreground and background colors). - ///< This escape character has no corresponding #COLOR_OFF. - ///< Its action continues until the next #COLOR_INV or end of line. - -#define SCOLOR_ON "\1" ///< Escape character (ON) -#define SCOLOR_OFF "\2" ///< Escape character (OFF) -#define SCOLOR_ESC "\3" ///< Escape character (Quote next character) -#define SCOLOR_INV "\4" ///< Escape character (Inverse colors) - -/// Is the given char a color escape character? -inline THREAD_SAFE bool requires_color_esc(char c) { return c >= COLOR_ON && c <= COLOR_INV; } -//@} - -typedef uchar color_t; ///< color tag - see \ref COLOR_ -/// \defgroup COLOR_ Color tags -/// Specify a color for a syntax item -//@{ -const color_t - COLOR_DEFAULT = 0x01, ///< Default - COLOR_REGCMT = 0x02, ///< Regular comment - COLOR_RPTCMT = 0x03, ///< Repeatable comment (comment defined somewhere else) - COLOR_AUTOCMT = 0x04, ///< Automatic comment - COLOR_INSN = 0x05, ///< Instruction - COLOR_DATNAME = 0x06, ///< Dummy Data Name - COLOR_DNAME = 0x07, ///< Regular Data Name - COLOR_DEMNAME = 0x08, ///< Demangled Name - COLOR_SYMBOL = 0x09, ///< Punctuation - COLOR_CHAR = 0x0A, ///< Char constant in instruction - COLOR_STRING = 0x0B, ///< String constant in instruction - COLOR_NUMBER = 0x0C, ///< Numeric constant in instruction - COLOR_VOIDOP = 0x0D, ///< Void operand - COLOR_CREF = 0x0E, ///< Code reference - COLOR_DREF = 0x0F, ///< Data reference - COLOR_CREFTAIL = 0x10, ///< Code reference to tail byte - COLOR_DREFTAIL = 0x11, ///< Data reference to tail byte - COLOR_ERROR = 0x12, ///< Error or problem - COLOR_PREFIX = 0x13, ///< Line prefix - COLOR_BINPREF = 0x14, ///< Binary line prefix bytes - COLOR_EXTRA = 0x15, ///< Extra line - COLOR_ALTOP = 0x16, ///< Alternative operand - COLOR_HIDNAME = 0x17, ///< Hidden name - COLOR_LIBNAME = 0x18, ///< Library function name - COLOR_LOCNAME = 0x19, ///< Local variable name - COLOR_CODNAME = 0x1A, ///< Dummy code name - COLOR_ASMDIR = 0x1B, ///< Assembler directive - COLOR_MACRO = 0x1C, ///< Macro - COLOR_DSTR = 0x1D, ///< String constant in data directive - COLOR_DCHAR = 0x1E, ///< Char constant in data directive - COLOR_DNUM = 0x1F, ///< Numeric constant in data directive - COLOR_KEYWORD = 0x20, ///< Keywords - COLOR_REG = 0x21, ///< Register name - COLOR_IMPNAME = 0x22, ///< Imported name - COLOR_SEGNAME = 0x23, ///< Segment name - COLOR_UNKNAME = 0x24, ///< Dummy unknown name - COLOR_CNAME = 0x25, ///< Regular code name - COLOR_UNAME = 0x26, ///< Regular unknown name - COLOR_COLLAPSED= 0x27, ///< Collapsed line - COLOR_FG_MAX = 0x28, ///< Max color number - - // Fictive colors - - COLOR_ADDR = COLOR_FG_MAX, ///< hidden address marks. - ///< the address is represented as 8digit - ///< hex number: 01234567. - ///< it doesn't have #COLOR_OFF pair. - ///< NB: for 64-bit IDA, the address is 16digit. - - COLOR_OPND1 = COLOR_ADDR+1, ///< Instruction operand 1 - COLOR_OPND2 = COLOR_ADDR+2, ///< Instruction operand 2 - COLOR_OPND3 = COLOR_ADDR+3, ///< Instruction operand 3 - COLOR_OPND4 = COLOR_ADDR+4, ///< Instruction operand 4 - COLOR_OPND5 = COLOR_ADDR+5, ///< Instruction operand 5 - COLOR_OPND6 = COLOR_ADDR+6, ///< Instruction operand 6 - COLOR_OPND7 = COLOR_ADDR+7, ///< Instruction operand 7 - COLOR_OPND8 = COLOR_ADDR+8, ///< Instruction operand 8 - - - COLOR_RESERVED1= COLOR_ADDR+11,///< This tag is reserved for internal IDA use - COLOR_LUMINA = COLOR_ADDR+12;///< Lumina-related, only for the navigation band -//@} - -/// Size of a tagged address (see ::COLOR_ADDR) -#define COLOR_ADDR_SIZE (sizeof(ea_t)*2) - -/// \defgroup SCOLOR_ Color string constants -/// These definitions are used with the #COLSTR macro -//@{ -#define SCOLOR_DEFAULT "\x01" ///< Default -#define SCOLOR_REGCMT "\x02" ///< Regular comment -#define SCOLOR_RPTCMT "\x03" ///< Repeatable comment (defined not here) -#define SCOLOR_AUTOCMT "\x04" ///< Automatic comment -#define SCOLOR_INSN "\x05" ///< Instruction -#define SCOLOR_DATNAME "\x06" ///< Dummy Data Name -#define SCOLOR_DNAME "\x07" ///< Regular Data Name -#define SCOLOR_DEMNAME "\x08" ///< Demangled Name -#define SCOLOR_SYMBOL "\x09" ///< Punctuation -#define SCOLOR_CHAR "\x0A" ///< Char constant in instruction -#define SCOLOR_STRING "\x0B" ///< String constant in instruction -#define SCOLOR_NUMBER "\x0C" ///< Numeric constant in instruction -#define SCOLOR_VOIDOP "\x0D" ///< Void operand -#define SCOLOR_CREF "\x0E" ///< Code reference -#define SCOLOR_DREF "\x0F" ///< Data reference -#define SCOLOR_CREFTAIL "\x10" ///< Code reference to tail byte -#define SCOLOR_DREFTAIL "\x11" ///< Data reference to tail byte -#define SCOLOR_ERROR "\x12" ///< Error or problem -#define SCOLOR_PREFIX "\x13" ///< Line prefix -#define SCOLOR_BINPREF "\x14" ///< Binary line prefix bytes -#define SCOLOR_EXTRA "\x15" ///< Extra line -#define SCOLOR_ALTOP "\x16" ///< Alternative operand -#define SCOLOR_HIDNAME "\x17" ///< Hidden name -#define SCOLOR_LIBNAME "\x18" ///< Library function name -#define SCOLOR_LOCNAME "\x19" ///< Local variable name -#define SCOLOR_CODNAME "\x1A" ///< Dummy code name -#define SCOLOR_ASMDIR "\x1B" ///< Assembler directive -#define SCOLOR_MACRO "\x1C" ///< Macro -#define SCOLOR_DSTR "\x1D" ///< String constant in data directive -#define SCOLOR_DCHAR "\x1E" ///< Char constant in data directive -#define SCOLOR_DNUM "\x1F" ///< Numeric constant in data directive -#define SCOLOR_KEYWORD "\x20" ///< Keywords -#define SCOLOR_REG "\x21" ///< Register name -#define SCOLOR_IMPNAME "\x22" ///< Imported name -#define SCOLOR_SEGNAME "\x23" ///< Segment name -#define SCOLOR_UNKNAME "\x24" ///< Dummy unknown name -#define SCOLOR_CNAME "\x25" ///< Regular code name -#define SCOLOR_UNAME "\x26" ///< Regular unknown name -#define SCOLOR_COLLAPSED "\x27" ///< Collapsed line -#define SCOLOR_ADDR "\x28" ///< Hidden address mark -//@} - -//----------------- Line prefix colors -------------------------------------- -/// \defgroup COLOR_PFX Line prefix colors -/// Note: line prefix colors are not used in processor modules -//@{ -#define COLOR_DEFAULT 0x01 ///< Default -#define COLOR_SELECTED 0x02 ///< Selected -#define COLOR_LIBFUNC 0x03 ///< Library function -#define COLOR_REGFUNC 0x04 ///< Regular function -#define COLOR_CODE 0x05 ///< Single instruction -#define COLOR_DATA 0x06 ///< Data bytes -#define COLOR_UNKNOWN 0x07 ///< Unexplored byte -#define COLOR_EXTERN 0x08 ///< External name definition segment -#define COLOR_CURITEM 0x09 ///< Current item -#define COLOR_CURLINE 0x0A ///< Current line -#define COLOR_HIDLINE 0x0B ///< Hidden line -#define COLOR_LUMFUNC 0x0C ///< Lumina function -#define COLOR_BG_MAX 0x0D ///< Max color number - -#define PALETTE_SIZE (COLOR_FG_MAX+COLOR_BG_MAX) -//@} - - -/// This macro is used to build colored string constants (e.g. for format strings) -/// \param str string literal to surround with color tags -/// \param tag one of SCOLOR_xxx constants -#define COLSTR(str,tag) SCOLOR_ON tag str SCOLOR_OFF tag - - -//------------------------------------------------------------------------ - -/// \defgroup color_conv Convenience functions -/// Higher level convenience functions are defined in ua.hpp. -/// Please use the following functions only if functions from ua.hpp -/// are not useful in your case. -//@{ - -/// Insert an address mark into a string. -/// \param buf pointer to the output buffer; the tag will be appended or inserted into it -/// \param ea address to include -/// \param ins if true, the tag will be inserted at the beginning of the buffer - -idaman THREAD_SAFE void ida_export tag_addr(qstring *buf, ea_t ea, bool ins=false); - - -/// Move pointer to a 'line' to 'cnt' positions right. -/// Take into account escape sequences. -/// \param line pointer to string -/// \param cnt number of positions to move right -/// \return moved pointer - -idaman THREAD_SAFE const char *ida_export tag_advance(const char *line, int cnt); - - -/// Move the pointer past all color codes. -/// \param line can't be NULL -/// \return moved pointer, can't be NULL - -idaman THREAD_SAFE const char *ida_export tag_skipcodes(const char *line); - - -/// Skip one color code. -/// This function should be used if you are interested in color codes -/// and want to analyze all of them. -/// Otherwise tag_skipcodes() function is better since it will skip all colors at once. -/// This function will skip the current color code if there is one. -/// If the current symbol is not a color code, it will return the input. -/// \return moved pointer - -idaman THREAD_SAFE const char *ida_export tag_skipcode(const char *line); - - -/// Calculate length of a colored string -/// This function computes the length in unicode codepoints of a line -/// \return the number of codepoints in the line, or -1 on error - -idaman THREAD_SAFE ssize_t ida_export tag_strlen(const char *line); - - -/// Remove color escape sequences from a string. -/// \param buf output buffer with the string, cannot be NULL. -/// \param str input string, cannot be NULL. -/// \param init_level used to verify that COLOR_ON and COLOR_OFF tags are balanced -/// \return length of resulting string, -1 if error - -idaman THREAD_SAFE ssize_t ida_export tag_remove(qstring *buf, const char *str, int init_level=0); - -inline THREAD_SAFE ssize_t idaapi tag_remove(qstring *buf, const qstring &str, int init_level=0) -{ - return tag_remove(buf, str.c_str(), init_level); -} - -inline THREAD_SAFE ssize_t idaapi tag_remove(qstring *buf, int init_level=0) -{ - if ( buf->empty() ) - return 0; - return tag_remove(buf, buf->begin(), init_level); -} - -//@} color_conv - -//@} color_def - - -/// Get prefix color for line at 'ea' -/// \return \ref COLOR_PFX -idaman color_t ida_export calc_prefix_color(ea_t ea); - -/// Get background color for line at 'ea' -/// \return RGB color -idaman bgcolor_t ida_export calc_bg_color(ea_t ea); - - -//------------------------------------------------------------------------ -// S O U R C E F I L E S -//------------------------------------------------------------------------ - -/// \name Source files -/// IDA can keep information about source files used to create the program. -/// Each source file is represented by a range of addresses. -/// A source file may contain several address ranges. -//@{ - -/// Mark a range of address as belonging to a source file. -/// An address range may belong only to one source file. -/// A source file may be represented by several address ranges. -/// \param ea1 linear address of start of the address range -/// \param ea2 linear address of end of the address range (excluded) -/// \param filename name of source file. -/// \return success - -idaman bool ida_export add_sourcefile(ea_t ea1, ea_t ea2, const char *filename); - - -/// Get name of source file occupying the given address. -/// \param ea linear address -/// \param bounds pointer to the output buffer with the address range -/// for the current file. May be NULL. -/// \return NULL if source file information is not found, -/// otherwise returns pointer to file name - -idaman const char *ida_export get_sourcefile(ea_t ea, range_t *bounds=NULL); - - -/// Delete information about the source file. -/// \param ea linear address -/// \return success - -idaman bool ida_export del_sourcefile(ea_t ea); -//@} - -//------------------------------------------------------------------------ -// G E N E R A T I O N O F D I S A S S E M B L E D T E X T -//------------------------------------------------------------------------ - -/// \name Generation of disassembled text -//@{ - -/// User-defined line-prefixes are displayed just after the autogenerated -/// line prefixes in the disassembly listing. -/// There is no need to call this function explicitly. -/// Use the user_defined_prefix_t class. -/// \param prefix_len prefixed length. if 0, then uninstall UDP -/// \param udp object to generate user-defined prefix -/// \param install true:install, false:uninstall -/// \param owner pointer to the plugin_t that owns UDP -/// if non-NULL, then the object will be uninstalled and destroyed -/// when the plugin gets unloaded -idaman bool ida_export install_user_defined_prefix( - size_t prefix_len, - struct user_defined_prefix_t *udp, - const void *owner); - -/// Class to generate user-defined prefixes in the disassembly listing. -struct user_defined_prefix_t -{ - /// Creating a user-defined prefix object installs it. - user_defined_prefix_t(size_t prefix_len, const void *owner) - { - install_user_defined_prefix(prefix_len, this, owner); - } - - /// Destroying a user-defined prefix object uninstalls it. - virtual idaapi ~user_defined_prefix_t() - { - install_user_defined_prefix(0, this, nullptr); - } - - // Get a user-defined prefix. - /// This callback must be overridden by the derived class. - /// \param out the output buffer - /// \param ea the current address - /// \param insn the current instruction. if the current item is not - /// an instruction, then insn.itype is zero. - /// \param indent see explanations for \ref gen_printf() - /// \param line the line to be generated. - /// the line usually contains color tags. - /// this argument can be examined to decide - /// whether to generate the prefix. - virtual void idaapi get_user_defined_prefix( - qstring *vout, - ea_t ea, - const class insn_t &insn, - int lnnum, - int indent, - const char *line) = 0; -}; - -//@} - -//------------------------------------------------------------------------ -// A N T E R I O R / P O S T E R I O R L I N E S -//------------------------------------------------------------------------ - -/// \name Anterior/Posterior lines -//@{ - -/// See higher level functions below - -idaman AS_PRINTF(3, 0) bool ida_export vadd_extra_line( - ea_t ea, - int vel_flags, // see VEL_... - const char *format, - va_list va); - -#define VEL_POST 0x01 // append posterior line -#define VEL_CMT 0x02 // append comment line - - -/// Add anterior/posterior non-comment line(s). -/// \param ea linear address -/// \param isprev do we add anterior lines? (0-no, posterior) -/// \param format printf() style format string. may contain \\n to denote new lines. -/// \return true if success - -AS_PRINTF(3, 4) inline bool add_extra_line(ea_t ea, bool isprev, const char *format, ...) -{ - va_list va; - va_start(va,format); - int vel_flags = (isprev ? 0 : VEL_POST); - bool ok = vadd_extra_line(ea, vel_flags, format, va); - va_end(va); - return ok; -} - - -/// Add anterior/posterior comment line(s). -/// \param ea linear address -/// \param isprev do we add anterior lines? (0-no, posterior) -/// \param format printf() style format string. may contain \\n to denote -/// new lines. The resulting string should not contain comment -/// characters (;), the kernel will add them automatically. -/// \return true if success - -AS_PRINTF(3, 4) inline bool add_extra_cmt(ea_t ea, bool isprev, const char *format, ...) -{ - va_list va; - va_start(va,format); - int vel_flags = (isprev ? 0 : VEL_POST) | VEL_CMT; - bool ok = vadd_extra_line(ea, vel_flags, format, va); - va_end(va); - return ok; -} - - -/// Add anterior comment line(s) at the start of program. -/// \param format printf() style format string. may contain \\n to denote -/// new lines. The resulting string should not contain comment -/// characters (;), the kernel will add them automatically. -/// \return true if success - -AS_PRINTF(1, 2) inline bool add_pgm_cmt(const char *format, ...) -{ - va_list va; - va_start(va,format); - bool ok = vadd_extra_line(inf_get_min_ea(), VEL_CMT, format, va); - va_end(va); - return ok; -} - -//@} - -///---------------------------------------------------------------------\cond -/// The following functions are used in kernel only: - -// Generate disassembly (many lines) and put them into a buffer -// Returns number of generated lines -idaman int ida_export generate_disassembly( - qstrvec_t *out, // buffer to hold generated lines - int *lnnum, // number of "the most interesting" line - ea_t ea, // address to generate disassembly for - int maxsize, // maximum number of lines - bool as_stack); // Display undefined items as 2/4/8 bytes - -// Generate one line of disassembly -// This function discards all "non-interesting" lines -// It is designed to generate one-line descriptions -// of addresses for lists, etc. -idaman bool ida_export generate_disasm_line( - qstring *buf, // output buffer - ea_t ea, // address to generate disassembly for - int flags=0); -#define GENDSM_FORCE_CODE (1 << 0) // generate a disassembly line as if - // there is an instruction at 'ea' -#define GENDSM_MULTI_LINE (1 << 1) // if the instruction consists of several lines, - // produce all of them (useful for parallel instructions) -#define GENDSM_REMOVE_TAGS (1 << 2) // remove tags from output buffer - -/// Get length of the line prefix that was used for the last generated line - -idaman int ida_export get_last_pfxlen(void); - - -// Get pointer to the sequence of characters denoting 'close comment' -// empty string means no comment (the current assembler has no open-comment close-comment pairs) -// This function uses ash.cmnt2 - -idaman const char *ida_export closing_comment(void); - - -// Every anterior/posterior line has its number. -// Anterior lines have numbers from E_PREV -// Posterior lines have numbers from E_NEXT - -const int E_PREV = 1000; -const int E_NEXT = 2000; - -idaman int ida_export get_first_free_extra_cmtidx(ea_t ea, int start); -idaman void ida_export update_extra_cmt(ea_t ea, int what, const char *str); -idaman void ida_export del_extra_cmt(ea_t ea, int what); -idaman ssize_t ida_export get_extra_cmt(qstring *buf, ea_t ea, int what); -idaman void ida_export delete_extra_cmts(ea_t ea, int what); - -idaman ea_t ida_export align_down_to_stack(ea_t newea); -idaman ea_t ida_export align_up_to_stack(ea_t ea1, ea_t ea2=BADADDR); - -// A helper class, to encode from UTF-8, -> into the target encoding. -// This is typically used when generating listings (or any kind of -// output file.) -struct encoder_t -{ - // whether or not a message should be printed, letting the - // user know that some text couldn't be recoded properly - enum notify_recerr_t - { - nr_none, - nr_once, - }; - - virtual ~encoder_t() {} - virtual bool idaapi get_bom(bytevec_t *out) const = 0; - // returns true if conversion was entirely successful, false otherwise. - // codepoints that couldn't be converted, will be output as C - // literal-escaped UTF-8 sequences (e.g., "\xC3\xD9"), and if - // 'nr_once' was passed at creation-time, a one-time notification - // well be output in the messages window. - virtual bool idaapi encode(qstring *s) const = 0; - // encode()s the UTF-8 string composed by format + args, and - // returns true if all the resulting bytes could be written to - // the output file. - AS_PRINTF(3, 4) virtual bool idaapi print(FILE *out, const char *format, ...) const = 0; - // should a file be opened as binary, or should it rather be opened - // in text mode? This will have an importance in how '\n' characters - // are possibly converted into '\x0A\x0D' on windows, which is most - // inappropriate when output'ing e.g., UTF-16, UTF-32.. - virtual bool idaapi requires_binary_mode() const = 0; -}; - -// Create the encoder with the given target encoding. If -1 is passed -// then the effective target encoding will be computed like so: -// if ( encidx < 0 ) -// { -// encidx = get_outfile_encoding_idx(); -// if ( encidx == STRENC_DEFAULT ) -// encidx = get_default_encoding_idx(BPU_1B); -// } -idaman encoder_t *ida_export create_encoding_helper( - int encidx=-1, - encoder_t::notify_recerr_t nr=encoder_t::nr_once); - -/// Callback functions to output lines: -//@{ -typedef int idaapi html_header_cb_t(FILE *fp); -typedef int idaapi html_footer_cb_t(FILE *fp); -typedef int idaapi html_line_cb_t( - FILE *fp, - const qstring &line, - bgcolor_t prefix_color, - bgcolor_t bg_color); -#define gen_outline_t html_line_cb_t -//@} - -///-------------------------------------------------------------------\endcond - - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED void ida_export set_user_defined_prefix( // use install_user_defined_prefix() - size_t width, - void (idaapi *get_user_defined_prefix)( - qstring *buf, - ea_t ea, - int lnnum, - int indent, - const char *line)); -#endif - -#endif diff --git a/idasdk75/include/llong.hpp b/idasdk75/include/llong.hpp deleted file mode 100644 index 4ea3f6d..0000000 --- a/idasdk75/include/llong.hpp +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _LLONG_HPP -#define _LLONG_HPP - -//--------------------------------------------------------------------------- -#if defined(_MSC_VER) - -typedef unsigned __int64 ulonglong; -typedef __int64 longlong; - -#elif defined(__GNUC__) - -typedef unsigned long long ulonglong; -typedef long long longlong; - -#endif - -//--------------------------------------------------------------------------- -#ifdef __cplusplus -inline constexpr longlong make_longlong(uint32 ll,int32 hh) { return ll | (longlong(hh) << 32); } -inline constexpr ulonglong make_ulonglong(uint32 ll,int32 hh) { return ll | (ulonglong(hh) << 32); } -inline uint32 low(const ulonglong &x) { return uint32(x); } -inline uint32 high(const ulonglong &x) { return uint32(x>>32); } -inline uint32 low(const longlong &x) { return uint32(x); } -inline int32 high(const longlong &x) { return uint32(x>>32); } -#else -#define make_longlong(ll,hh) (ll | (longlong(hh) << 32)) -#define make_ulonglong(ll,hh) (ll | (ulonglong(hh) << 32)) -#endif - -idaman THREAD_SAFE longlong ida_export llong_scan( - const char *buf, - int radix, - const char **end); -#ifndef swap64 - idaman THREAD_SAFE ulonglong ida_export swap64(ulonglong); -# ifdef __cplusplus - inline longlong swap64(longlong x) - { - return longlong(swap64(ulonglong(x))); - } -# endif -#endif - -//--------------------------------------------------------------------------- -// 128 BIT NUMBERS -//--------------------------------------------------------------------------- -#ifdef __HAS_INT128__ - -typedef unsigned __int128 uint128; -typedef __int128 int128; - -inline int128 make_int128(ulonglong ll,longlong hh) { return ll | (int128(hh) << 64); } -inline uint128 make_uint128(ulonglong ll,ulonglong hh) { return ll | (uint128(hh) << 64); } -inline ulonglong low(const uint128 &x) { return ulonglong(x); } -inline ulonglong high(const uint128 &x) { return ulonglong(x>>64); } -inline ulonglong low(const int128 &x) { return ulonglong(x); } -inline longlong high(const int128 &x) { return ulonglong(x>>64); } - -#else -#ifdef __cplusplus -//-V:uint128:730 not all members of a class are initialized inside the constructor -class uint128 -{ - ulonglong l; - ulonglong h; - friend class int128; -public: - uint128(void) {} - uint128(uint x) { l = x; h = 0; } - uint128(int x) { l = x; h = (x < 0)? -1 : 0; } - uint128(ulonglong x) { l = x; h = 0; } - uint128(longlong x) { l = x; h = (x < 0) ? -1 : 0; } - uint128(ulonglong ll, ulonglong hh) { l = ll; h = hh; } - friend ulonglong low (const uint128 &x) { return x.l; } - friend ulonglong high(const uint128 &x) { return x.h; } - friend uint128 operator+(const uint128 &x, const uint128 &y); - friend uint128 operator-(const uint128 &x, const uint128 &y); - friend uint128 operator/(const uint128 &x, const uint128 &y); - friend uint128 operator%(const uint128 &x, const uint128 &y); - friend uint128 operator*(const uint128 &x, const uint128 &y); - friend uint128 operator|(const uint128 &x, const uint128 &y); - friend uint128 operator&(const uint128 &x, const uint128 &y); - friend uint128 operator^(const uint128 &x, const uint128 &y); - friend uint128 operator>>(const uint128 &x, int cnt); - friend uint128 operator<<(const uint128 &x, int cnt); - uint128 &operator+=(const uint128 &y); - uint128 &operator-=(const uint128 &y); - uint128 &operator/=(const uint128 &y); - uint128 &operator%=(const uint128 &y); - uint128 &operator*=(const uint128 &y); - uint128 &operator|=(const uint128 &y); - uint128 &operator&=(const uint128 &y); - uint128 &operator^=(const uint128 &y); - uint128 &operator>>=(int cnt); - uint128 &operator<<=(int cnt); - uint128 &operator++(void); - uint128 &operator--(void); - friend uint128 operator+(const uint128 &x) { return x; } - friend uint128 operator-(const uint128 &x); - friend uint128 operator~(const uint128 &x) { return uint128(~x.l,~x.h); } - friend int operator==(const uint128 &x, const uint128 &y) { return x.l == y.l && x.h == y.h; } - friend int operator!=(const uint128 &x, const uint128 &y) { return x.l != y.l || x.h != y.h; } - friend int operator> (const uint128 &x, const uint128 &y) { return x.h > y.h || (x.h == y.h && x.l > y.l); } - friend int operator< (const uint128 &x, const uint128 &y) { return x.h < y.h || (x.h == y.h && x.l < y.l); } - friend int operator>=(const uint128 &x, const uint128 &y) { return x.h > y.h || (x.h == y.h && x.l >= y.l); } - friend int operator<=(const uint128 &x, const uint128 &y) { return x.h < y.h || (x.h == y.h && x.l <= y.l); } -}; - -//-V:int128:730 not all members of a class are initialized inside the constructor -class int128 -{ - ulonglong l; - longlong h; - friend class uint128; -public: - int128(void) {} - int128(uint x) { l = x; h = 0; } - int128(int x) { l = x; h = (x < 0) ? -1 : 0; } - int128(ulonglong x) { l = x; h = 0; } - int128(longlong x) { l = x; h = (x < 0) ? -1 : 0; } - int128(ulonglong ll, ulonglong hh) { l=ll; h=hh; } - int128(const uint128 &x) { l=x.l; h=x.h; } - friend ulonglong low (const int128 &x) { return x.l; } - friend ulonglong high(const int128 &x) { return x.h; } - friend int128 operator+(const int128 &x, const int128 &y); - friend int128 operator-(const int128 &x, const int128 &y); - friend int128 operator/(const int128 &x, const int128 &y); - friend int128 operator%(const int128 &x, const int128 &y); - friend int128 operator*(const int128 &x, const int128 &y); - friend int128 operator|(const int128 &x, const int128 &y); - friend int128 operator&(const int128 &x, const int128 &y); - friend int128 operator^(const int128 &x, const int128 &y); - friend int128 operator>>(const int128 &x, int cnt); - friend int128 operator<<(const int128 &x, int cnt); - int128 &operator+=(const int128 &y); - int128 &operator-=(const int128 &y); - int128 &operator/=(const int128 &y); - int128 &operator%=(const int128 &y); - int128 &operator*=(const int128 &y); - int128 &operator|=(const int128 &y); - int128 &operator&=(const int128 &y); - int128 &operator^=(const int128 &y); - int128 &operator>>=(int cnt); - int128 &operator<<=(int cnt); - int128 &operator++(void); - int128 &operator--(void); - friend int128 operator+(const int128 &x) { return x; } - friend int128 operator-(const int128 &x); - friend int128 operator~(const int128 &x) { return int128(~x.l,~x.h); } - friend int operator==(const int128 &x, const int128 &y) { return x.l == y.l && x.h == y.h; } - friend int operator!=(const int128 &x, const int128 &y) { return x.l != y.l || x.h != y.h; } - friend int operator> (const int128 &x, const int128 &y) { return x.h > y.h || (x.h == y.h && x.l > y.l); } - friend int operator< (const int128 &x, const int128 &y) { return x.h < y.h || (x.h == y.h && x.l < y.l); } - friend int operator>=(const int128 &x, const int128 &y) { return x.h > y.h || (x.h == y.h && x.l >= y.l); } - friend int operator<=(const int128 &x, const int128 &y) { return x.h < y.h || (x.h == y.h && x.l <= y.l); } -}; - -inline int128 make_int128(ulonglong ll, longlong hh) { return int128(ll, hh); } -inline uint128 make_uint128(ulonglong ll, longlong hh) { return uint128(ll, hh); } -idaman THREAD_SAFE void ida_export swap128(uint128 *x); - -//--------------------------------------------------------------------------- -inline uint128 operator+(const uint128 &x, const uint128 &y) -{ - ulonglong h = x.h + y.h; - ulonglong l = x.l + y.l; - if ( l < x.l ) - h = h + 1; - return uint128(l,h); -} - -//--------------------------------------------------------------------------- -inline uint128 operator-(const uint128 &x, const uint128 &y) -{ - ulonglong h = x.h - y.h; - ulonglong l = x.l - y.l; - if ( l > x.l ) - h = h - 1; - return uint128(l,h); -} - -//--------------------------------------------------------------------------- -inline uint128 operator|(const uint128 &x, const uint128 &y) -{ - return uint128(x.l | y.l, x.h | y.h); -} - -//--------------------------------------------------------------------------- -inline uint128 operator&(const uint128 &x, const uint128 &y) -{ - return uint128(x.l & y.l, x.h & y.h); -} - -//--------------------------------------------------------------------------- -inline uint128 operator^(const uint128 &x, const uint128 &y) -{ - return uint128(x.l ^ y.l, x.h ^ y.h); -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator+=(const uint128 &y) -{ - return *this = *this + y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator-=(const uint128 &y) -{ - return *this = *this - y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator|=(const uint128 &y) -{ - return *this = *this | y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator&=(const uint128 &y) -{ - return *this = *this & y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator^=(const uint128 &y) -{ - return *this = *this ^ y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator/=(const uint128 &y) -{ - return *this = *this / y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator%=(const uint128 &y) -{ - return *this = *this % y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator*=(const uint128 &y) -{ - return *this = *this * y; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator<<=(int cnt) -{ - return *this = *this << cnt; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator>>=(int cnt) -{ - return *this = *this >> cnt; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator++(void) -{ - if ( ++l == 0 ) - ++h; - return *this; -} - -//--------------------------------------------------------------------------- -inline uint128 &uint128::operator--(void) -{ - if ( l == 0 ) - --h; - --l; - return *this; -} - -//--------------------------------------------------------------------------- -inline uint128 operator-(const uint128 &x) -{ - return ~x + 1; -} - -#endif // ifdef __cplusplus -#endif // ifdef __HAS_INT128__ - -#endif // define _LLONG_HPP diff --git a/idasdk75/include/loader.hpp b/idasdk75/include/loader.hpp deleted file mode 100644 index 3b974ce..0000000 --- a/idasdk75/include/loader.hpp +++ /dev/null @@ -1,1040 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _LOADER_HPP -#define _LOADER_HPP -#include <ida.hpp> - -/*! \file loader.hpp - - \brief Definitions of IDP, LDR, PLUGIN module interfaces - - This file also contains: - - functions to load files into the database - - functions to generate output files - - high level functions to work with the database (open, save, close) - - The LDR interface consists of one structure: loader_t \n - The IDP interface consists of one structure: processor_t \n - The PLUGIN interface consists of one structure: plugin_t - - Modules can't use standard FILE* functions. - They must use functions from <fpro.h> - - Modules can't use standard memory allocation functions. - They must use functions from <pro.h> - - The exported entry #1 in the module should point to the - the appropriate structure. (loader_t for LDR module, for example) -*/ - -//---------------------------------------------------------------------- -// DEFINITION OF LDR MODULES -//---------------------------------------------------------------------- - -class linput_t; // loader input source. see diskio.hpp for the functions -struct extlang_t; // check expr.hpp -struct plugmod_t; // idp.hpp - -/// Loader description block - must be exported from the loader module -struct loader_t -{ - uint32 version; ///< api version, should be #IDP_INTERFACE_VERSION - uint32 flags; ///< \ref LDRF_ -/// \defgroup LDRF_ Loader flags -/// Used by loader_t::flags -//@{ -#define LDRF_RELOAD 0x0001 ///< loader recognizes #NEF_RELOAD flag -#define LDRF_REQ_PROC 0x0002 ///< Requires a processor to be set. - ///< if this bit is not set, load_file() must - ///< call set_processor_type(..., SETPROC_LOADER) -//@} - - /// Check input file format. - /// This function will be called one or more times depending on the result value. - /// \param[out] fileformat name of file format - /// \param[out] processor desired processor (optional) - /// \param li input file - /// \param filename name of the input file, - /// if it is an archive member name then the actual file doesn't exist - /// \return - /// 1 if file format is recognized, and fills 'fileformatname', otherwise returns 0. - /// This function may return a unique file format number instead of 1. - /// To get this unique number, please contact the author. - /// If the return value is ORed with #ACCEPT_ARCHIVE, then - /// it is an archive loader. Its process_archive() will be called - /// instead of load_file(). - /// If the return value is ORed with #ACCEPT_CONTINUE, then - /// this function will be called another time. - /// If the return value is ORed with #ACCEPT_FIRST, then this format - /// should be placed first in the "load file" dialog box. - /// In the sorting order of file formats the archive formats have priority. - int (idaapi *accept_file)( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *filename); - -/// Specify that a file format is served by archive loader -/// See loader_t::accept_file -#define ACCEPT_ARCHIVE 0x2000 -/// Specify that the function must be called another time -/// See loader_t::accept_file -#define ACCEPT_CONTINUE 0x4000 -/// Specify that a file format should be place first in "load file" dialog box. -/// See loader_t::accept_file -#define ACCEPT_FIRST 0x8000 - - /// Load file into the database. - /// \param li input file - /// \param neflags \ref NEF_ - /// \param fileformatname name of type of the file - /// (it was returned by #accept_file) - /// - /// If this function fails, loader_failure() should be called - void (idaapi *load_file)( - linput_t *li, - ushort neflags, - const char *fileformatname); -/// \defgroup NEF_ Load file flags -/// Passed as 'neflags' parameter to loader_t::load_file -//@{ -#define NEF_SEGS 0x0001 ///< Create segments -#define NEF_RSCS 0x0002 ///< Load resources -#define NEF_NAME 0x0004 ///< Rename entries -#define NEF_MAN 0x0008 ///< Manual load -#define NEF_FILL 0x0010 ///< Fill segment gaps -#define NEF_IMPS 0x0020 ///< Create import segment -#define NEF_FIRST 0x0080 ///< This is the first file loaded - ///< into the database. -#define NEF_CODE 0x0100 ///< for load_binary_file(): - ///< load as a code segment -#define NEF_RELOAD 0x0200 ///< reload the file at the same place: - ///< - don't create segments - ///< - don't create fixup info - ///< - don't import segments - ///< - etc - ///< load only the bytes into the base. - ///< a loader should have #LDRF_RELOAD - ///< bit set -#define NEF_FLAT 0x0400 ///< Autocreate FLAT group (PE) -#define NEF_MINI 0x0800 ///< Create mini database (do not copy - ///< segment bytes from the input file; - ///< use only the file header metadata) -#define NEF_LOPT 0x1000 ///< Display additional loader options dialog -#define NEF_LALL 0x2000 ///< Load all segments without questions -//@} - - /// Create output file from the database. - /// This function may be absent. - /// If fp == NULL, then this function returns: - /// - 0: can't create file of this type - /// - 1: ok, can create file of this type - /// - /// If fp != NULL, then this function should create the output file - int (idaapi *save_file)(FILE *fp, const char *fileformatname); - - /// Take care of a moved segment (fix up relocations, for example). - /// This function may be absent. - /// A special calling method \code move_segm(BADADDR, delta, 0, formatname); \endcode - /// means that the whole program has been moved in the memory (rebased) by delta bytes - /// \param from previous linear address of the segment - /// \param to current linear address of the segment - /// \param size size of the moved segment - /// \param fileformatname the file format - /// \retval 1 ok - /// \retval 0 failure - int (idaapi *move_segm)( - ea_t from, - ea_t to, - asize_t size, - const char *fileformatname); - - /// Display list of archive members and let the user select one. - /// Extract the selected archive member into a temporary file. - /// \param[out] temp_file name of the file with the extracted archive member. - /// \param li input file - /// \param[in,out] module_name in: name of archive - /// out: name of the extracted archive member - /// \param[in,out] neflags \ref NEF_ - /// \param fileformatname name of type of the file - /// (it was returned by #accept_file) - /// \param defmember extract the specified member, - /// for example "subdir/member.exe", - /// may be NULL - /// \param errbuf error message if 0 is returned, - /// may be NULL - /// \return -1-cancelled by the user, 1-ok, 0-error, see errbuf for details - int (idaapi *process_archive)( - qstring *temp_file, - linput_t *li, - qstring *module_name, - ushort *neflags, - const char *fileformatname, - const char *defmember, - qstring *errbuf); -}; - - -/// See loader_failure() - -idaman AS_PRINTF(1, 0) NORETURN void ida_export vloader_failure(const char *format, va_list va); - - -/// Display a message about a loader failure and stop the loading process. -/// The kernel will destroy the database. -/// If format == NULL, no message will be displayed -/// This function does not return (it longjumps)! -/// It may be called only from loader_t::load_file - -AS_PRINTF(1, 2) NORETURN inline void loader_failure(const char *format=NULL, ...) -{ - va_list va; - va_start(va, format); - vloader_failure(format, va); -} - -//------------------------------------------------------------------------- -#if defined(__NT__) -# define DLLEXT "dll" -#elif defined(__LINUX__) -# define DLLEXT "so" -#elif defined(__MAC__) -# define DLLEXT "dylib" -#else -# error Unknown loader ext -#endif - -//---------------------------------------------------------------------- -/// \def{LOADER_DLL, Pattern to find loader files} -#ifdef __EA64__ -# define LOADER_DLL "*64." DLLEXT -#else -# define LOADER_DLL "*." DLLEXT -#endif - -//---------------------------------------------------------------------- -// Functions for the UI to load files -//---------------------------------------------------------------------- -/// List of loaders -struct load_info_t -{ - load_info_t *next; - qstring dllname; - qstring ftypename; - qstring processor; ///< desired processor name - filetype_t ftype; - uint32 loader_flags; ///< copy of loader_t::flags - uint32 lflags; ///< \ref LIF_ - int pri; ///< 2-archldr, 1-place first, 0-normal priority - -/// \defgroup LIF_ loader info flags -/// Used by load_info_t::lflags -//@{ -#define LIF_ARCHLDR 0x0001 ///< archive loader -//@} - - bool is_archldr(void) { return (lflags & LIF_ARCHLDR) != 0; } -}; -DECLARE_TYPE_AS_MOVABLE(load_info_t); - -/// Build list of potential loaders - -idaman load_info_t *ida_export build_loaders_list(linput_t *li, const char *filename); - - -/// Free the list of loaders - -idaman void ida_export free_loaders_list(load_info_t *list); - - -/// Get name of loader from its DLL file -/// (for example, for PE files we will get "PE"). -/// This function modifies the original string and returns a pointer into it. -/// NB: if the file extension is a registered extlang extension (e.g. py or idc) -/// the extension is retained - -idaman char *ida_export get_loader_name_from_dll(char *dllname); - - -/// Get name of loader used to load the input file into the database. -/// If no external loader was used, returns -1. -/// Otherwise copies the loader file name without the extension in the buf -/// and returns its length -/// (for example, for PE files we will get "PE"). -/// For scripted loaders, the file extension is retained. - -idaman ssize_t ida_export get_loader_name(char *buf, size_t bufsize); - - -/// Load a binary file into the database. -/// This function usually is called from ui. -/// \param filename the name of input file as is -/// (if the input file is from library, then -/// this is the name from the library) -/// \param li loader input source -/// \param _neflags \ref NEF_. For the first file, -/// the flag #NEF_FIRST must be set. -/// \param fileoff Offset in the input file -/// \param basepara Load address in paragraphs -/// \param binoff Load offset (load_address=(basepara<<4)+binoff) -/// \param nbytes Number of bytes to load from the file. -/// - 0: up to the end of the file -/// -/// If nbytes is bigger than the number of -/// bytes rest, the kernel will load as much -/// as possible -/// \retval true ok -/// \retval false failed (couldn't open the file) - -idaman bool ida_export load_binary_file( - const char *filename, - linput_t *li, - ushort _neflags, - qoff64_t fileoff, - ea_t basepara, - ea_t binoff, - uint64 nbytes); - - -/// Load a non-binary file into the database. -/// This function usually is called from ui. -/// \param filename the name of input file as is -/// (if the input file is from library, then -/// this is the name from the library) -/// \param li loader input source -/// \param sysdlldir a directory with system dlls. Pass "." if unknown. -/// \param _neflags \ref NEF_. For the first file -/// the flag #NEF_FIRST must be set. -/// \param loader pointer to ::load_info_t structure. -/// If the current IDP module has \ph{loader} != NULL -/// then this argument is ignored. -/// \return success - -idaman bool ida_export load_nonbinary_file( - const char *filename, - linput_t *li, - const char *sysdlldir, - ushort _neflags, - load_info_t *loader); - - -/// Calls loader_t::process_archive() -/// For parameters and return value description -/// look at loader_t::process_archive(). -/// Additional parameter: -/// \param loader pointer to ::load_info_t structure. - -idaman int ida_export process_archive( - qstring *temp_file, - linput_t *li, - qstring *module_name, - ushort *neflags, - const char *defmember, - const load_info_t *loader, - qstring *errbuf=NULL); - -//-------------------------------------------------------------------------- -/// Output file types -enum ofile_type_t -{ - OFILE_MAP = 0, ///< MAP file - OFILE_EXE = 1, ///< Executable file - OFILE_IDC = 2, ///< IDC file - OFILE_LST = 3, ///< Disassembly listing - OFILE_ASM = 4, ///< Assembly - OFILE_DIF = 5, ///< Difference -}; - -//------------------------------------------------------------------ -/// Generate an output file. -/// \param otype type of output file. -/// \param fp the output file handle -/// \param ea1 start address. For some file types this argument is ignored -/// \param ea2 end address. For some file types this argument is ignored -/// as usual in ida, the end address of the range is not included -/// \param flags \ref GENFLG_ -/// -/// For ::OFILE_EXE: -/// \retval 0 can't generate exe file -/// \retval 1 ok -/// -/// For other file types: -/// \return number of the generated lines. -1 if an error occurred - -idaman int ida_export gen_file(ofile_type_t otype, FILE *fp, ea_t ea1, ea_t ea2, int flags); - -/// \defgroup GENFLG_ Generate file flags -/// Passed as 'flags' parameter to gen_file() -//@{ -#define GENFLG_MAPSEG 0x0001 ///< ::OFILE_MAP: generate map of segments -#define GENFLG_MAPNAME 0x0002 ///< ::OFILE_MAP: include dummy names -#define GENFLG_MAPDMNG 0x0004 ///< ::OFILE_MAP: demangle names -#define GENFLG_MAPLOC 0x0008 ///< ::OFILE_MAP: include local names -#define GENFLG_IDCTYPE 0x0008 ///< ::OFILE_IDC: gen only information about types -#define GENFLG_ASMTYPE 0x0010 ///< ::OFILE_ASM,::OFILE_LST: gen information about types too -#define GENFLG_GENHTML 0x0020 ///< ::OFILE_ASM,::OFILE_LST: generate html (::ui_genfile_callback will be used) -#define GENFLG_ASMINC 0x0040 ///< ::OFILE_ASM,::OFILE_LST: gen information only about types -//@} - -//---------------------------------------------------------------------- -// Helper functions for the loaders & ui -//---------------------------------------------------------------------- - -/// Load portion of file into the database. -/// This function will include (ea1..ea2) into the addressing space of the -/// program (make it enabled) -/// \param li pointer of input source -/// \param pos position in the file -/// \param ea1,ea2 range of destination linear addresses -/// \param patchable should the kernel remember correspondence of -/// file offsets to linear addresses. -/// \retval 1 ok -/// \retval 0 read error, a warning is displayed - -idaman int ida_export file2base( - linput_t *li, - qoff64_t pos, - ea_t ea1, - ea_t ea2, - int patchable); - -#define FILEREG_PATCHABLE 1 ///< means that the input file may be - ///< patched (i.e. no compression, - ///< no iterated data, etc) -#define FILEREG_NOTPATCHABLE 0 ///< the data is kept in some encoded - ///< form in the file. - - -/// Load database from the memory. -/// This function works for wide byte processors too. -/// \param memptr pointer to buffer with bytes -/// \param ea1,ea2 range of destination linear addresses -/// \param fpos position in the input file the data is taken from. -/// if == -1, then no file position correspond to the data. -/// \return 1 always - -idaman int ida_export mem2base(const void *memptr, ea_t ea1, ea_t ea2, qoff64_t fpos); - - -/// Unload database to a binary file. -/// This function works for wide byte processors too. -/// \param fp pointer to file -/// \param pos position in the file -/// \param ea1,ea2 range of source linear addresses -/// \return 1-ok(always), write error leads to immediate exit - -idaman int ida_export base2file(FILE *fp, qoff64_t pos, ea_t ea1, ea_t ea2); - - -/// Extract a module for an archive file. -/// Parse an archive file, show the list of modules to the user, allow him to -/// select a module, extract the selected module to a file (if the extract module -/// is an archive, repeat the process). -/// This function can handle ZIP, AR, AIXAR, OMFLIB files. -/// The temporary file will be automatically deleted by IDA at the end. -/// \param[in,out] filename in: input file. -/// out: name of the selected module. -/// \param bufsize size of the buffer with 'filename' -/// \param[out] temp_file_ptr will point to the name of the file that -/// contains the extracted module -/// \param is_remote is the input file remote? -/// \retval true ok -/// \retval false something bad happened (error message has been displayed to the user) - -idaman bool ida_export extract_module_from_archive( - char *filename, - size_t bufsize, - char **temp_file_ptr, - bool is_remote); - - -/// Add long comment at \inf{min_ea}. -/// - Input file: .... -/// - File format: .... -/// -/// This function should be called only from the loader to describe the input file. - -idaman void ida_export create_filename_cmt(void); - - -/// Get the input file type. -/// This function can recognize libraries and zip files. - -idaman filetype_t ida_export get_basic_file_type(linput_t *li); - - -/// Get name of the current file type. -/// The current file type is kept in \inf{filetype}. -/// \param buf buffer for the file type name -/// \param bufsize its size -/// \return size of answer, this function always succeeds - -idaman size_t ida_export get_file_type_name(char *buf, size_t bufsize); - - -//---------------------------------------------------------------------- -// Work with IDS files: read and use information from them -// - -/// See ::importer_t -struct impinfo_t -{ - const char *dllname; - void (idaapi*func)(uval_t num, const char *name, uval_t node); - uval_t node; -}; - - -/// Callback for checking dll module - passed to import_module(). -/// \param li pointer to input file -/// \param ii import info. -/// If the function finds that ii.dllname does not match -/// the module name passed to import_module(), it returns 0. \n -/// Otherwise it calls ii.func for each exported entry. \n -/// If ii.dllname==NULL then ii.func will be called -/// with num==0 and name==dllname. -/// \retval 0 dllname doesn't match, import_module() should continue -/// \retval 1 ok - -typedef int idaapi importer_t(linput_t *li, impinfo_t *ii); - - -/// Find and import a DLL module. -/// This function adds information to the database (renames functions, etc). -/// \param module name of DLL -/// \param windir system directory with dlls -/// \param modnode node with information about imported entries. -/// either altval or supval arrays may be absent. -/// the node should never be deleted. -/// - imports by ordinals: -/// altval(ord) contains linear address -/// - imports by name: -/// supval(ea) contains the imported name -/// \param importer callback function (may be NULL) to check dll module -/// \param ostype type of operating system (subdir name). -/// NULL means the IDS directory itself (not recommended) - -idaman void ida_export import_module( - const char *module, - const char *windir, - uval_t modnode, - importer_t *importer, - const char *ostype); - - -/// Load and apply IDS file. -/// This function loads the specified IDS file and applies it to the database. -/// If the program imports functions from a module with the same name -/// as the name of the ids file being loaded, then only functions from this -/// module will be affected. Otherwise (i.e. when the program does not import -/// a module with this name) any function in the program may be affected. -/// \param fname name of file to apply -/// \retval 1 ok -/// \retval 0 some error (a message is displayed). -/// if the ids file does not exist, no message is displayed - -idaman int ida_export load_ids_module(char *fname); - - -//---------------------------------------------------------------------- -// DEFINITION OF PLUGIN MODULES -//---------------------------------------------------------------------- -/// A plugin is a module in the plugins subdirectory that can perform -/// an action asked by the user. (usually via pressing a hotkey) -class plugin_t -{ -public: - int version; ///< Should be equal to #IDP_INTERFACE_VERSION - int flags; ///< \ref PLUGIN_ -/// \defgroup PLUGIN_ Plugin features -/// Used by plugin_t::flags -//@{ -#define PLUGIN_MOD 0x0001 ///< Plugin changes the database. - ///< IDA won't call the plugin if - ///< the processor module prohibited any changes. -#define PLUGIN_DRAW 0x0002 ///< IDA should redraw everything after calling the plugin. -#define PLUGIN_SEG 0x0004 ///< Plugin may be applied only if the current address belongs to a segment -#define PLUGIN_UNL 0x0008 ///< Unload the plugin immediately after calling 'run'. - ///< This flag may be set anytime. - ///< The kernel checks it after each call to 'run' - ///< The main purpose of this flag is to ease - ///< the debugging of new plugins. -#define PLUGIN_HIDE 0x0010 ///< Plugin should not appear in the Edit, Plugins menu. - ///< This flag is checked at the start. -#define PLUGIN_DBG 0x0020 ///< A debugger plugin. init() should put - ///< the address of ::debugger_t to dbg. -#define PLUGIN_PROC 0x0040 ///< Load plugin when a processor module is loaded. (and keep it - ///< until the processor module is unloaded) -#define PLUGIN_FIX 0x0080 ///< Load plugin when IDA starts and keep it in the memory until IDA stops -#define PLUGIN_MULTI 0x0100 ///< The plugin can work with multiple idbs in parallel. - ///< init() returns a pointer to a plugmod_t object - ///< run/term functions are not used. - ///< Virtual functions of plugmod_t are used instead. -#define PLUGIN_SCRIPTED 0x8000 ///< Scripted plugin. Should not be used by plugins, - ///< the kernel sets it automatically. -//@} - - plugmod_t *(idaapi *init)(void); ///< Initialize plugin - returns a pointer to plugmod_t -#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_PLUGIN_RETURN_CODES__) -/// \defgroup PLUGIN_INIT Plugin initialization codes -/// Return values for plugin_t::init() -/// Deprecated, please update your plugins to use PLUGIN_MULTI. -//@{ -#define PLUGIN_SKIP nullptr ///< Plugin doesn't want to be loaded -#define PLUGIN_OK ((plugmod_t *)1) ///< Plugin agrees to work with the current database. - ///< It will be loaded as soon as the user presses the hotkey -#define PLUGIN_KEEP ((plugmod_t *)2) ///< Plugin agrees to work with the current database and wants to stay in the memory -//@} -#endif - - void (idaapi *term)(void); ///< Terminate plugin. This function will be called - ///< when the plugin is unloaded. May be NULL. - ///< Must be NULL for PLUGIN_MULTI plugins - bool (idaapi *run)(size_t arg); ///< Invoke plugin. - ///< Must be NULL for PLUGIN_MULTI plugins - const char *comment; ///< Long comment about the plugin. - ///< it could appear in the status line - ///< or as a hint - const char *help; ///< Multiline help about the plugin - const char *wanted_name; ///< The preferred short name of the plugin - const char *wanted_hotkey; ///< The preferred hotkey to run the plugin -}; - -#ifndef __X86__ - CASSERT(sizeof(plugin_t) == 64); -#else - CASSERT(sizeof(plugin_t) == 36); -#endif - -#if !defined(__KERNEL__) && !defined(PLUGIN_SUBMODULE) -idaman ida_module_data plugin_t PLUGIN; // (declaration for plugins) -#endif - -/// Get plugin options from the command line. -/// If the user has specified the options in the -Oplugin_name:options -/// format, them this function will return the 'options' part of it -/// The 'plugin' parameter should denote the plugin name -/// Returns NULL if there we no options specified - -idaman const char *ida_export get_plugin_options(const char *plugin); - - -//-------------------------------------------------------------------------- -/// Pattern to find plugin files -#ifdef __EA64__ -# define PLUGIN_DLL "*64." DLLEXT -#else -# define PLUGIN_DLL "*." DLLEXT -#endif - - -// LOW LEVEL DLL LOADING FUNCTIONS -// Only the kernel should use these functions! -/// \cond -#define LNE_MAXSEG 10 // Max number of segments - -#if 0 -extern char dlldata[4096]; // Reserved place for DLL data -#define DLLDATASTART 0xA0 // Absolute offset of dlldata -extern char ldrdata[64]; // Reserved place for LOADER data -#define LDRDATASTART (DLLDATASTART+sizeof(dlldata)) // Absolute offset of ldrdata -#endif - -struct idadll_t -{ - void *dllinfo[LNE_MAXSEG]; - void *entry; // first entry point of DLL - idadll_t(void) { dllinfo[0] = NULL; entry = NULL; } - bool is_loaded(void) const { return dllinfo[0] != NULL; } -}; - -#define MODULE_ENTRY_LOADER "LDSC" -#define MODULE_ENTRY_PLUGIN "PLUGIN" -#define MODULE_ENTRY_IDP "LPH" - -int _load_core_module( - idadll_t *dllmem, - const char *file, - const char *entry); - // dllmem - allocated segments - // dos: segment 1 (data) isn't allocated - // Returns 0 - ok, else: -#define RE_NOFILE 1 /* No such file */ -#define RE_NOTIDP 2 /* Not IDP file */ -#define RE_NOPAGE 3 /* Can't load: bad segments */ -#define RE_NOLINK 4 /* No linkage info */ -#define RE_BADRTP 5 /* Bad relocation type */ -#define RE_BADORD 6 /* Bad imported ordinal */ -#define RE_BADATP 7 /* Bad relocation atype */ -#define RE_BADMAP 8 /* DLLDATA offset is invalid */ - -void load_core_module_or_die( - idadll_t *dllmem, - const char *file, - const char *entry); -idaman bool ida_export load_core_module( - idadll_t *dllmem, - const char *file, - const char *entry); - -idaman void ida_export free_dll(idadll_t *dllmem); -/// \endcond - -/// Processor name -struct idp_name_t -{ - qstring lname; ///< long processor name - qstring sname; ///< short processor name - bool hidden; ///< is hidden - idp_name_t() : hidden(false) {} -}; -DECLARE_TYPE_AS_MOVABLE(idp_name_t); -typedef qvector<idp_name_t> idp_names_t; ///< vector of processor names - -/// Processor module description -struct idp_desc_t -{ - qstring path; ///< module file name - time_t mtime; ///< time of last modification - qstring family; ///< processor's family - idp_names_t names; ///< processor names - bool is_script; ///< the processor module is a script - bool checked; ///< internal, for cache management - idp_desc_t(): mtime(time_t(-1)), is_script(false), checked(false) {} -}; -DECLARE_TYPE_AS_MOVABLE(idp_desc_t); -typedef qvector<idp_desc_t> idp_descs_t; ///< vector of processor module descriptions - - -/// Get IDA processor modules descriptions - -idaman const idp_descs_t *ida_export get_idp_descs(void); - - -//-------------------------------------------------------------------------- -/// \def{IDP_DLL, Pattern to find idp files} -#ifdef __EA64__ -# define IDP_DLL "*64." DLLEXT -#else -# define IDP_DLL "*." DLLEXT -#endif - - -//-------------------------------------------------------------------------- -/// Structure to store Plugin information -struct plugin_info_t -{ - plugin_info_t *next; ///< next plugin information - char *path; ///< full path to the plugin - char *org_name; ///< original short name of the plugin - char *name; ///< short name of the plugin - ///< it will appear in the menu - ushort org_hotkey; ///< original hotkey to run the plugin - ushort hotkey; ///< current hotkey to run the plugin - size_t arg; ///< argument used to call the plugin - plugin_t *entry; ///< pointer to the plugin if it is already loaded - idadll_t dllmem; - int flags; ///< a copy of plugin_t::flags - char *comment; ///< a copy of plugin_t::comment -}; - - -/// Get pointer to the list of plugins. (some plugins might be listed several times -/// in the list - once for each configured argument) - -idaman plugin_info_t *ida_export get_plugins(void); - - -/// Find a user-defined plugin and optionally load it. -/// \param name short plugin name without path and extension, -/// or absolute path to the file name -/// \param load_if_needed if the plugin is not present in the memory, try to load it -/// \return pointer to plugin description block - -idaman plugin_t *ida_export find_plugin(const char *name, bool load_if_needed=false); - -inline plugin_t *load_plugin(const char *name) -{ - return find_plugin(name, true); -} - - -/// Run a loaded plugin with the specified argument. -/// \param ptr pointer to plugin description block -/// \param arg argument to run with - -idaman bool ida_export run_plugin(const plugin_t *ptr, size_t arg); - - -/// Load & run a plugin - -inline bool idaapi load_and_run_plugin(const char *name, size_t arg) -{ - return run_plugin(load_plugin(name), arg); -} - - -/// Run a plugin as configured. -/// \param ptr pointer to plugin information block - -idaman bool ida_export invoke_plugin(plugin_info_t *ptr); - - -/// Information for the user interface about available debuggers -struct dbg_info_t -{ - plugin_info_t *pi; - struct debugger_t *dbg; - dbg_info_t(plugin_info_t *_pi, struct debugger_t *_dbg) : pi(_pi), dbg(_dbg) {} -}; -DECLARE_TYPE_AS_MOVABLE(dbg_info_t); - - -/// Get information about available debuggers - -idaman size_t ida_export get_debugger_plugins(const dbg_info_t **array); - - -/// Initialize plugins with the specified flag - -idaman void ida_export init_plugins(int flag); - - -/// Terminate plugins with the specified flag - -idaman void ida_export term_plugins(int flag); - - -//------------------------------------------------------------------------ - -/// Get offset in the input file which corresponds to the given ea. -/// If the specified ea can't be mapped into the input file offset, -/// return -1. - -idaman qoff64_t ida_export get_fileregion_offset(ea_t ea); - - -/// Get linear address which corresponds to the specified input file offset. -/// If can't be found, return #BADADDR - -idaman ea_t ida_export get_fileregion_ea(qoff64_t offset); - - -//------------------------------------------------------------------------ -/// Generate an exe file (unload the database in binary form). -/// \return fp the output file handle. if fp == NULL then return: -/// - 1: can generate an executable file -/// - 0: can't generate an executable file -/// \retval 1 ok -/// \retval 0 failed - -idaman int ida_export gen_exe_file(FILE *fp); - - -//------------------------------------------------------------------------ -/// Reload the input file. -/// This function reloads the byte values from the input file. -/// It doesn't modify the segmentation, names, comments, etc. -/// \param file name of the input file. if file == NULL then returns: -/// - 1: can reload the input file -/// - 0: can't reload the input file -/// \param is_remote is the file located on a remote computer with -/// the debugger server? -/// \return success - -idaman bool ida_export reload_file(const char *file, bool is_remote); - - -//--------------------------------------------------------------------------- -// S N A P S H O T F U N C T I O N S - -/// Maximum database snapshot description length -#define MAX_DATABASE_DESCRIPTION 128 - -class snapshot_t; -typedef qvector<snapshot_t *> snapshots_t; ///< vector of database snapshots - -/// Snapshot attributes -class snapshot_t -{ -private: - snapshot_t &operator=(const snapshot_t &); - snapshot_t(const snapshot_t &); - - int compare(const snapshot_t &r) const - { - return ::compare(id, r.id); - } - -public: - qtime64_t id; ///< snapshot ID. This value is computed using qgettimeofday() - uint16 flags; ///< \ref SSF_ -/// \defgroup SSF_ Snapshot flags -/// Used by snapshot_t::flags -//@{ -#define SSF_AUTOMATIC 0x0001 ///< automatic snapshot -//@} - char desc[MAX_DATABASE_DESCRIPTION]; ///< snapshot description - char filename[QMAXPATH]; ///< snapshot file name - snapshots_t children; ///< snapshot children - DEFINE_MEMORY_ALLOCATION_FUNCS() - DECLARE_COMPARISON_OPERATORS(snapshot_t) - void clear() - { - for ( snapshots_t::iterator p=children.begin(); - p != children.end(); - ++p ) - { - delete *p; - } - children.clear(); - } - - snapshot_t(): id(0), flags(0) - { - filename[0] = desc[0] = '\0'; - } - - ~snapshot_t() - { - clear(); - } -}; -DECLARE_TYPE_AS_MOVABLE(snapshot_t); - -//------------------------------------------------------------------------ -/// Build the snapshot tree. -/// \param root snapshot root that will contain the snapshot tree elements. -/// \return success - -idaman bool ida_export build_snapshot_tree(snapshot_t *root); - - -//------------------------------------------------------------------------ -/// Update the snapshot attributes. -/// \note only the snapshot description can be updated. -/// \param filename snapshot file name or NULL for the current database -/// \param root snapshot root (returned from build_snapshot_tree()) -/// \param attr snapshot instance containing the updated attributes -/// \param uf \ref SSUF_ -/// \return success -idaman bool ida_export update_snapshot_attributes( - const char *filename, - const snapshot_t *root, - const snapshot_t *attr, - int uf); - -/// \defgroup SSUF_ Snapshot update flags -/// Passed as 'uf' parameter to update_snapshot_attributes() -//@{ -#define SSUF_DESC 0x00000001 ///< Update the description -#define SSUF_PATH 0x00000002 ///< Update the path -#define SSUF_FLAGS 0x00000004 ///< Update the flags -//@} - -//------------------------------------------------------------------------ -/// Visit the snapshot tree. -/// \param root snapshot root to start the enumeration from -/// \param callback callback called for each child. return 0 to continue enumeration -/// and non-zero to abort enumeration -/// \param ud user data. will be passed back to the callback -/// \return true-ok, false-failed - -idaman int ida_export visit_snapshot_tree( - snapshot_t *root, - int (idaapi *callback)(snapshot_t *ss, void *ud), - void *ud=NULL); - - -/// Flush buffers to the disk - -idaman int ida_export flush_buffers(void); - - -/// Is the database considered as trusted? - -idaman bool ida_export is_trusted_idb(void); - -//------------------------------------------------------------------------ -/// Save current database using a new file name. -/// \param outfile output database file name -/// \param flags \ref DBFL_ -/// \param root optional: snapshot tree root. -/// \param attr optional: snapshot attributes -/// \note when both root and attr are not NULL then the snapshot -/// attributes will be updated, otherwise the snapshot attributes -/// will be inherited from the current database. -/// \return success - -idaman bool ida_export save_database( - const char *outfile, - uint32 flags, - const snapshot_t *root = NULL, - const snapshot_t *attr = NULL); - -/// \defgroup DBFL_ Database flags -/// Used to manage saving/closing of a database -//@{ -#define DBFL_KILL 0x01 ///< delete unpacked database -#define DBFL_COMP 0x02 ///< collect garbage -#define DBFL_BAK 0x04 ///< create backup file (if !DBFL_KILL) -#define DBFL_TEMP 0x08 ///< temporary database -//@} - -/// Get the current database flag -/// \param dbfl flag \ref DBFL_ -/// \returns the state of the flag (set or cleared) - -idaman bool ida_export is_database_flag(uint32 dbfl); - -/// Set or clear database flag -/// \param dbfl flag \ref DBFL_ -/// \param cnd set if true or clear flag otherwise - -idaman void ida_export set_database_flag(uint32 dbfl, bool cnd=true); -inline void clr_database_flag(uint32 dbfl) { set_database_flag(dbfl, false); } - -/// Is a temporary database? -inline bool is_temp_database(void) { return is_database_flag(DBFL_TEMP); } - - -//------------------------------------------------------------------------ -/// \defgroup PATH_TYPE_ Types of the file pathes -//@{ -enum path_type_t -{ - PATH_TYPE_CMD, ///< full path to the file specified in the command line - PATH_TYPE_IDB, ///< full path of IDB file - PATH_TYPE_ID0, ///< full path of ID0 file -}; -//@} - -/// Get the file path -/// \param pt file path type \ref PATH_TYPE_ -/// \returns file path, never returns NULL -idaman const char *ida_export get_path(path_type_t pt); - -/// Set the file path -/// \param pt file path type \ref PATH_TYPE_ -/// \param path new file path, -/// use NULL or empty string to clear the file path -idaman void ida_export set_path(path_type_t pt, const char *path); - - -/// Check the file extension -/// \returns true if it is the reserved extension -idaman bool ida_export is_database_ext(const char *ext); - - -/// Get the value of the ELF_DEBUG_FILE_DIRECTORY configuration -/// directive. -idaman const char *ida_export get_elf_debug_file_directory(); - -/// \cond - -#endif diff --git a/idasdk75/include/moves.hpp b/idasdk75/include/moves.hpp deleted file mode 100644 index da61849..0000000 --- a/idasdk75/include/moves.hpp +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __MOVES_HPP -#define __MOVES_HPP - -//------------------------------------------------------------------------- -struct graph_location_info_t -{ - double zoom; // zoom level, 1.0 == 100%, 0 means auto position - double orgx; // graph origin, x coord - double orgy; // graph origin, y coord - graph_location_info_t(void) : zoom(0), orgx(0), orgy(0) {} - bool operator == (const graph_location_info_t &r) const - { return zoom == r.zoom && orgx == r.orgx && orgy == r.orgy; } //-V550 An odd precise comparison: zoom == r.zoom - bool operator != (const graph_location_info_t &r) const - { return !(*this == r); } - void serialize(bytevec_t *out) const; - bool deserialize(memory_deserializer_t &mmdsr); -}; - -//------------------------------------------------------------------------- -inline void graph_location_info_t::serialize(bytevec_t *out) const -{ - CASSERT(sizeof(graph_location_info_t) == 3*8); - out->append(this, sizeof(graph_location_info_t)); -} - -//------------------------------------------------------------------------- -inline bool graph_location_info_t::deserialize(memory_deserializer_t &mmdsr) -{ - return mmdsr.unpack_obj(this, sizeof(graph_location_info_t)) != NULL; -} - -//------------------------------------------------------------------------- -struct segm_move_info_t -{ - segm_move_info_t(ea_t _from = 0, ea_t _to = 0, size_t _sz = 0) - : from(_from), to(_to), size(_sz) {} - ea_t from, to; - size_t size; - - bool operator == (const segm_move_info_t &r) const - { return from == r.from && to == r.to && size == r.size; } - bool operator != (const segm_move_info_t &r) const - { return !(*this == r); } -}; -DECLARE_TYPE_AS_MOVABLE(segm_move_info_t); -typedef qvector<segm_move_info_t> segm_move_info_vec_t; - -struct segm_move_infos_t : public segm_move_info_vec_t -{ - const segm_move_info_t *find(ea_t ea) const - { - for ( size_t i = 0; i < size(); ++i ) - { - const segm_move_info_t &cur = at(i); - if ( ea >= cur.from && ea < cur.from + cur.size ) - return &cur; - } - return NULL; - } -}; - -//------------------------------------------------------------------------- -class place_t; - -//------------------------------------------------------------------------- -struct renderer_info_pos_t // out of renderer_info_t, to enable SWiG parsing -{ - int node; - short cx; - short cy; - - renderer_info_pos_t() : node(-1), cx(-1), cy(-1) {} - bool operator == (const renderer_info_pos_t &r) const - { return node == r.node && cx == r.cx && cy == r.cy; } - bool operator != (const renderer_info_pos_t &r) const - { return !(*this == r); } - void serialize(bytevec_t *out) const; - bool deserialize(memory_deserializer_t &mmdsr); -}; - -//------------------------------------------------------------------------- -inline void renderer_info_pos_t::serialize(bytevec_t *out) const -{ - out->pack_dd(node); - out->pack_dw(cx); - out->pack_dw(cy); -} - -//------------------------------------------------------------------------- -inline bool renderer_info_pos_t::deserialize(memory_deserializer_t &mmdsr) -{ - node = mmdsr.unpack_dd(); - cx = mmdsr.unpack_dw(); - if ( mmdsr.empty() ) - return false; - cy = mmdsr.unpack_dw(); - return true; -} - -//------------------------------------------------------------------------- -struct renderer_info_t -{ - renderer_info_t() { clear(); } - graph_location_info_t gli; - typedef renderer_info_pos_t pos_t; - pos_t pos; - tcc_renderer_type_t rtype; - - bool operator == (const renderer_info_t &r) const - { return rtype == r.rtype && pos == r.pos && gli == r.gli; } - bool operator != (const renderer_info_t &r) const - { return !(*this == r); } - - void clear() - { - gli = {}; - pos = {}; - rtype = TCCRT_INVALID; - } -}; - - -//------------------------------------------------------------------------- -class lochist_t; -struct lochist_entry_t; -struct expanded_area_t; - -#define LSEF_PLACE (1 << 0) -#define LSEF_RINFO (1 << 1) -#define LSEF_PTYPE (1 << 2) -#define LSEF_ALL (LSEF_PLACE|LSEF_RINFO|LSEF_PTYPE) - -#ifndef SWIG -#define DEFINE_LOCHIST_T_HELPERS(decl) \ - decl void ida_export lochist_t_register_live(lochist_t &); \ - decl void ida_export lochist_t_deregister_live(lochist_t &); \ - decl bool ida_export lochist_t_init (lochist_t &, const char *, const place_t &, void *, uint32); \ - decl void ida_export lochist_t_jump (lochist_t &, bool try_to_unhide, const lochist_entry_t &e); \ - decl bool ida_export lochist_t_fwd (lochist_t &, uint32 cnt, bool try_to_unhide); \ - decl bool ida_export lochist_t_back (lochist_t &, uint32 cnt, bool try_to_unhide); \ - decl bool ida_export lochist_t_seek (lochist_t &, uint32 index, bool try_to_unhide, bool apply_cur); \ - decl const lochist_entry_t *ida_export lochist_t_get_current(const lochist_t &); \ - decl uint32 ida_export lochist_t_current_index(const lochist_t &); \ - decl void ida_export lochist_t_set (lochist_t &, uint32, const lochist_entry_t &); \ - decl bool ida_export lochist_t_get (lochist_entry_t *, const lochist_t &, uint32); \ - decl uint32 ida_export lochist_t_size (const lochist_t &);\ - decl void ida_export lochist_t_save (const lochist_t &); \ - decl void ida_export lochist_t_clear (lochist_t &); -#else -#define DEFINE_LOCHIST_T_HELPERS(decl) -#endif // SWIG -DEFINE_LOCHIST_T_HELPERS(idaman) - -#ifndef SWIG -#define DEFINE_LOCHIST_ENTRY_T_HELPERS(decl) \ - decl void ida_export lochist_entry_t_serialize(bytevec_t *, const lochist_entry_t &); \ - decl bool ida_export lochist_entry_t_deserialize(lochist_entry_t *, const uchar **, const uchar *const, const place_t *); -#else -#define DEFINE_LOCHIST_ENTRY_T_HELPERS(decl) -#endif // SWIG -DEFINE_LOCHIST_ENTRY_T_HELPERS(idaman) - -//------------------------------------------------------------------------- -struct lochist_entry_t -{ - renderer_info_t rinfo; - place_t *plce; - - lochist_entry_t() : plce(NULL) {} - lochist_entry_t(const place_t *p, const renderer_info_t &r) - : rinfo(r), plce((place_t *) p) - { - if ( plce != NULL ) - plce = plce->clone(); - } -#ifndef SWIG - lochist_entry_t(const lochist_t &s); -#endif // SWIG - lochist_entry_t(const lochist_entry_t &other) : plce(NULL) { *this = other; } - ~lochist_entry_t() { clear(); } - const renderer_info_t &renderer_info() const { return rinfo; } - const place_t *place() const { return plce; } - - renderer_info_t &renderer_info() { return rinfo; } - place_t *place() { return plce; } - void set_place(const place_t *p) { clear(); plce = p == NULL ? NULL : p->clone(); } - void set_place(const place_t &p) { set_place(&p); } - - bool is_valid() const { return plce != NULL; } - - lochist_entry_t &operator=(const lochist_entry_t &r) - { - clear(); - (*this).rinfo = r.rinfo; - if ( r.plce != NULL ) - plce = r.plce->clone(); - return *this; - } - - void acquire_place(place_t *in_p) - { clear(); plce = in_p; } - - void serialize(bytevec_t *out) const { lochist_entry_t_serialize(out, *this); } - bool deserialize(const uchar **ptr, const uchar *const end, const place_t *tmplate) - { return lochist_entry_t_deserialize(this, ptr, end, tmplate); } - -private: - void clear() - { - if ( plce != NULL ) - qfree(plce); - } - - friend class lochist_t; - DEFINE_LOCHIST_T_HELPERS(friend) - DEFINE_LOCHIST_ENTRY_T_HELPERS(friend) -}; -DECLARE_TYPE_AS_MOVABLE(lochist_entry_t); - -#define UNHID_SEGM 0x0001 // unhid a segment at 'target' -#define UNHID_FUNC 0x0002 // unhid a function at 'target' -#define UNHID_RANGE 0x0004 // unhid an range at 'target' - -#define DEFAULT_CURSOR_Y 0xFFFF -#define DEFAULT_LNNUM -1 -#define CURLOC_LIST "$ curlocs" -#define MAX_MARK_SLOT 1024 // Max number of marked locations - -//------------------------------------------------------------------------- -class lochist_t -{ - void *ud; - - DEFINE_LOCHIST_T_HELPERS(friend) - - lochist_entry_t cur; - netnode node; - -#define LHF_HISTORY_DISABLED (1 << 0) // enable history? - uint32 flags; - -public: - lochist_t() : flags(0) { lochist_t_register_live(*this); } - ~lochist_t() { lochist_t_deregister_live(*this); } - bool is_history_enabled() const { return (flags & LHF_HISTORY_DISABLED) == 0; } - int get_place_id() const - { - const place_t *p = cur.place(); - return p == NULL ? -1 : p->id(); - } - bool init(const char *stream_name, const place_t *_defpos, void *_ud, uint32 _flags) - { return lochist_t_init(*this, stream_name, *_defpos, _ud, _flags); } - - nodeidx_t netcode() const - { return node; } - - void jump(bool try_to_unhide, const lochist_entry_t &e) - { lochist_t_jump(*this, try_to_unhide, e); } - - uint32 current_index() const - { return lochist_t_current_index(*this); } - - bool seek(uint32 index, bool try_to_unhide) - { return lochist_t_seek(*this, index, try_to_unhide, true); } - - bool fwd(uint32 cnt, bool try_to_unhide) - { return lochist_t_fwd(*this, cnt, try_to_unhide); } - - bool back(uint32 cnt, bool try_to_unhide) - { return lochist_t_back(*this, cnt, try_to_unhide); } - - void save() const - { lochist_t_save(*this); } - - void clear() - { lochist_t_clear(*this); } - - const lochist_entry_t &get_current() const - { return *lochist_t_get_current(*this); } - - void set_current(const lochist_entry_t &e) - { return set(current_index(), e); } - - void set(uint32 index, const lochist_entry_t &e) - { lochist_t_set(*this, index, e); } - - bool get(lochist_entry_t *out, uint32 index) const - { return lochist_t_get(out, *this, index); } - - uint32 size(void) const - { return lochist_t_size(*this); } - - const place_t *get_template_place() const - { return cur.place(); } -}; -DECLARE_TYPE_AS_MOVABLE(lochist_t); - -//------------------------------------------------------------------------- -#ifndef SWIG -idaman uint32 ida_export bookmarks_t_mark(const lochist_entry_t &, uint32, const char *, const char *, void *); -idaman bool ida_export bookmarks_t_get(lochist_entry_t *, qstring *, uint32 *, void *); -idaman bool ida_export bookmarks_t_get_desc(qstring *, const lochist_entry_t &, uint32, void *); -idaman uint32 ida_export bookmarks_t_find_index(const lochist_entry_t &, void *); -idaman uint32 ida_export bookmarks_t_size(const lochist_entry_t &, void *); -idaman bool ida_export bookmarks_t_erase(const lochist_entry_t &, uint32, void *); -#endif // SWIG - -//------------------------------------------------------------------------- -class bookmarks_t -{ - bookmarks_t(); // No. - ~bookmarks_t() {} -public: -#define BOOKMARKS_CHOOSE_INDEX (uint32(-1)) -#define BOOKMARKS_BAD_INDEX (uint32(-1)) - - // Mark/unmark position - // index - the marked position number (0..MAX_MARK_SLOT) - // if specified as BOOKMARKS_CHOOSE_INDEX: ask the user to select the mark slot. - // title - if index == BOOKMARKS_CHOOSE_INDEX, then the window caption of - // the dialog which will appear on the screen. title==NULL will - // lead to the default caption: "please select a mark slot" - // desc - description of the marked position. If NULL, IDA will show a - // dialog box asking the user to enter the description. - // returns used marker number (BOOKMARKS_BAD_INDEX - none) - static uint32 mark( - const lochist_entry_t &e, - uint32 index, - const char *title, - const char *desc, - void *ud) - { return bookmarks_t_mark(e, index, title, desc, ud); } - - // 'out_entry' MUST: - // - contain a valid place_t*; data will be deserialized into it - // - have a valid, corresponding tcc_place_type_t - static bool get( - lochist_entry_t *out_entry, - qstring *out_desc, - uint32 *index, // index==BOOKMARKS_CHOOSE_INDEX? let the user choose - void *ud) - { return bookmarks_t_get(out_entry, out_desc, index, ud); } - - static bool get_desc( - qstring *out, - const lochist_entry_t &e, - uint32 index, - void *ud) - { return bookmarks_t_get_desc(out, e, index, ud); } - - static uint32 find_index( - const lochist_entry_t &e, - void *ud) - { return bookmarks_t_find_index(e, ud); } - - static uint32 size( - const lochist_entry_t &e, - void *ud) - { return bookmarks_t_size(e, ud); } - - static bool erase( - const lochist_entry_t &e, - uint32 index, - void *ud) - { return bookmarks_t_erase(e, index, ud); } -}; - -//------------------------------------------------------------------------- -inline lochist_entry_t::lochist_entry_t(const lochist_t &lh) - : plce(NULL) -{ - *this = lh.get_current(); -} - - -#endif // __MOVES_HPP - diff --git a/idasdk75/include/nalt.hpp b/idasdk75/include/nalt.hpp deleted file mode 100644 index 5987eb6..0000000 --- a/idasdk75/include/nalt.hpp +++ /dev/null @@ -1,1576 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef NALT_HPP -#define NALT_HPP - -#include <ida.hpp> -#include <netnode.hpp> - -/*! \file nalt.hpp - - \brief Definitions of various information kept in netnodes - - Each address in the program has a corresponding netnode: netnode(ea). - - If we have no information about an address, the corresponding - netnode is not created. - Otherwise we will create a netnode and save information in it. - All variable length information (names, comments, offset information, etc) - is stored in the netnode. - - Don't forget that some information is already stored in the flags (bytes.hpp) - - \warning - Many of the functions in this file are very low level (they are marked - as low level functions). Use them only if you can't find higher level - function to set/get/del information. - - You can create your own nodes in IDP module and store information - in them. See ::netnode. -*/ - -/// \defgroup NALT_ Structure of altvals array -/// Structure of altvals array of netnode(ea). -/// altvals is a virtual array of 32-bit longs attached to a netnode. -/// the size of this array is unlimited. Unused indexes are not kept in the -/// database. We use only first several indexes to this array. -//@{ -#define NALT_ENUM uval_t(-2) ///< reserved for enums, see enum.hpp -#define NALT_WIDE uval_t(-1) ///< 16-bit byte value -#define NALT_SWITCH 1 ///< switch idiom address (used at jump targets) -//#define NALT_OBASE1 2 // offset base 2 -#define NALT_STRUCT 3 ///< struct id -//#define NALT_SEENF 4 // 'seen' flag (used in structures) -//#define NALT_OOBASE0 5 // outer offset base 1 -//#define NALT_OOBASE1 6 // outer offset base 2 -//#define NALT_XREFPOS 7 // saved xref address in the xrefs window -#define NALT_AFLAGS 8 ///< additional flags for an item -#define NALT_LINNUM 9 ///< source line number -#define NALT_ABSBASE 10 ///< absolute segment location -#define NALT_ENUM0 11 ///< enum id for the first operand -#define NALT_ENUM1 12 ///< enum id for the second operand -//#define NALT_STROFF0 13 // struct offset, struct id for the first operand -//#define NALT_STROFF1 14 // struct offset, struct id for the second operand -#define NALT_PURGE 15 ///< number of bytes purged from the stack when a function is called indirectly -#define NALT_STRTYPE 16 ///< type of string item -#define NALT_ALIGN 17 ///< alignment value if the item is #FF_ALIGN - ///< (should by equal to power of 2) -//#define NALT_HIGH0 18 // linear address of byte referenced by -// // high 16 bits of an offset (FF_0HIGH) -//#define NALT_HIGH1 19 // linear address of byte referenced by -// // high 16 bits of an offset (FF_1HIGH) -#define NALT_COLOR 20 ///< instruction/data background color -//@} - -/// \defgroup NSUP_ Structure of supvals array -/// Structure of supvals array of netnode(ea). -/// Supvals is a virtual array of objects of arbitrary length attached -/// to a netnode (length of one element is limited by #MAXSPECSIZE, though) -/// We use first several indexes to this array: -//@{ -#define NSUP_CMT 0 ///< regular comment -#define NSUP_REPCMT 1 ///< repeatable comment -#define NSUP_FOP1 2 ///< forced operand 1 -#define NSUP_FOP2 3 ///< forced operand 2 -#define NSUP_JINFO 4 ///< jump table info -#define NSUP_ARRAY 5 ///< array parameters -#define NSUP_OMFGRP 6 ///< OMF: group of segments (not used anymore) -#define NSUP_FOP3 7 ///< forced operand 3 -#define NSUP_SWITCH 8 ///< switch information -#define NSUP_REF0 9 ///< complex reference information for operand 1 -#define NSUP_REF1 10 ///< complex reference information for operand 2 -#define NSUP_REF2 11 ///< complex reference information for operand 3 -#define NSUP_OREF0 12 ///< outer complex reference information for operand 1 -#define NSUP_OREF1 13 ///< outer complex reference information for operand 2 -#define NSUP_OREF2 14 ///< outer complex reference information for operand 3 -#define NSUP_STROFF0 15 ///< stroff: struct path for the first operand -#define NSUP_STROFF1 16 ///< stroff: struct path for the second operand -#define NSUP_SEGTRANS 17 ///< segment translations -#define NSUP_FOP4 18 ///< forced operand 4 -#define NSUP_FOP5 19 ///< forced operand 5 -#define NSUP_FOP6 20 ///< forced operand 6 -#define NSUP_REF3 21 ///< complex reference information for operand 4 -#define NSUP_REF4 22 ///< complex reference information for operand 5 -#define NSUP_REF5 23 ///< complex reference information for operand 6 -#define NSUP_OREF3 24 ///< outer complex reference information for operand 4 -#define NSUP_OREF4 25 ///< outer complex reference information for operand 5 -#define NSUP_OREF5 26 ///< outer complex reference information for operand 6 -#define NSUP_XREFPOS 27 ///< saved xref address and type in the xrefs window -#define NSUP_CUSTDT 28 ///< custom data type id -#define NSUP_GROUPS 29 ///< SEG_GRP: pack_dd encoded list of selectors -#define NSUP_ARGEAS 30 ///< instructions that initialize call arguments -#define NSUP_FOP7 31 ///< forced operand 7 -#define NSUP_FOP8 32 ///< forced operand 8 -#define NSUP_REF6 33 ///< complex reference information for operand 7 -#define NSUP_REF7 34 ///< complex reference information for operand 8 -#define NSUP_OREF6 35 ///< outer complex reference information for operand 7 -#define NSUP_OREF7 36 ///< outer complex reference information for operand 8 - -// values E_PREV..E_NEXT+1000 are reserved (1000..2000..3000 decimal) - -/// SP change points blob (see funcs.cpp). -/// values NSUP_POINTS..NSUP_POINTS+0x1000 are reserved -#define NSUP_POINTS 0x1000 - -/// manual instruction. -/// values NSUP_MANUAL..NSUP_MANUAL+0x1000 are reserved -#define NSUP_MANUAL 0x2000 - -/// type information. -/// values NSUP_TYPEINFO..NSUP_TYPEINFO+0x1000 are reserved -#define NSUP_TYPEINFO 0x3000 - -/// register variables. -/// values NSUP_REGVAR..NSUP_REGVAR+0x1000 are reserved -#define NSUP_REGVAR 0x4000 - -/// local labels. -/// values NSUP_LLABEL..NSUP_LLABEL+0x1000 are reserved -#define NSUP_LLABEL 0x5000 - -/// register argument type/name descriptions -/// values NSUP_REGARG..NSUP_REGARG+0x1000 are reserved -#define NSUP_REGARG 0x6000 - -/// function tails or tail referers -/// values NSUP_FTAILS..NSUP_FTAILS+0x1000 are reserved -#define NSUP_FTAILS 0x7000 - -/// graph group information -/// values NSUP_GROUP..NSUP_GROUP+0x1000 are reserved -#define NSUP_GROUP 0x8000 - -/// operand type information. -/// values NSUP_OPTYPES..NSUP_OPTYPES+0x100000 are reserved -#define NSUP_OPTYPES 0x9000 - -/// function metadata before lumina information was applied -/// values NSUP_ORIGFMD..NSUP_ORIGFMD+0x1000 are reserved -#define NSUP_ORIGFMD 0x109000 - -//@} - -/// \defgroup NALT_X Netnode xref tags -/// Tag values to store xrefs (see cref.cpp) -//@{ -#define NALT_CREF_TO 'X' ///< code xref to, idx: target address -#define NALT_CREF_FROM 'x' ///< code xref from, idx: source address -#define NALT_DREF_TO 'D' ///< data xref to, idx: target address -#define NALT_DREF_FROM 'd' ///< data xref from, idx: source address -//@} - -/// \defgroup N_TAG Netnode graph tags -/// Tag values to store graph info -//@{ -#define NSUP_GR_INFO 'g' ///< group node info: color, ea, text -#define NALT_GR_LAYX 'p' ///< group layout ptrs, hash: md5 of 'belongs' -#define NSUP_GR_LAYT 'l' ///< group layouts, idx: layout pointer -//@} - -/// Patch netnode tag -#define PATCH_TAG 'P' - -/// Get netnode for the specified address. - -idaman nodeidx_t ida_export ea2node(ea_t ea); -idaman ea_t ida_export node2ea(nodeidx_t ndx); -inline netnode getnode(ea_t ea) { return netnode(ea2node(ea)); } - -//-------------------------------------------------------------------------- -// C O N V E N I E N C E F U N C T I O N S -//-------------------------------------------------------------------------- - -/// \name Get structure ID -/// Returns the struct id of the struct type at the specified address. -/// Use this function when is_struct()==true -//@{ - -idaman tid_t ida_export get_strid(ea_t ea); - -//@} - -/// \name xrefpos -//@{ -/// Position of cursor in the window with cross-references to the address. -/// Used by the user-interface. -struct xrefpos_t -{ - ea_t ea; - uchar type; // the type of xref (::cref_t & ::dref_t) - xrefpos_t(ea_t ea_ = BADADDR, uchar type_ = 0) : ea(ea_), type(type_) {} - bool is_valid() const { return ea != BADADDR; } -}; - -idaman ssize_t ida_export get_xrefpos(xrefpos_t *out, ea_t ea); -idaman void ida_export set_xrefpos(ea_t ea, const xrefpos_t *in); -inline void idaapi del_xrefpos(ea_t ea) { getnode(ea).supdel(NSUP_XREFPOS); } - -//@} - -/// \defgroup AFL_ Additional flags for the location -/// All 32-bits of the main flags (bytes.hpp) are used up. -/// Additional flags keep more information about addresses. -/// AFLNOTE: DO NOT use these flags directly unless there is absolutely no way. -/// They are too low level and may corrupt the database. -//@{ -#define AFL_LINNUM 0x00000001L ///< has line number info -#define AFL_USERSP 0x00000002L ///< user-defined SP value -#define AFL_PUBNAM 0x00000004L ///< name is public (inter-file linkage) -#define AFL_WEAKNAM 0x00000008L ///< name is weak -#define AFL_HIDDEN 0x00000010L ///< the item is hidden completely -#define AFL_MANUAL 0x00000020L ///< the instruction/data is specified by the user -#define AFL_NOBRD 0x00000040L ///< the code/data border is hidden -#define AFL_ZSTROFF 0x00000080L ///< display struct field name at 0 offset when displaying an offset. - ///< example: - ///< \v{offset somestruct.field_0} - ///< if this flag is clear, then - ///< \v{offset somestruct} -#define AFL_BNOT0 0x00000100L ///< the 1st operand is bitwise negated -#define AFL_BNOT1 0x00000200L ///< the 2nd operand is bitwise negated -#define AFL_LIB 0x00000400L ///< item from the standard library. - ///< low level flag, is used to set - ///< #FUNC_LIB of ::func_t -#define AFL_TI 0x00000800L ///< has typeinfo? (#NSUP_TYPEINFO) -#define AFL_TI0 0x00001000L ///< has typeinfo for operand 0? (#NSUP_OPTYPES) -#define AFL_TI1 0x00002000L ///< has typeinfo for operand 1? (#NSUP_OPTYPES+1) -#define AFL_LNAME 0x00004000L ///< has local name too (#FF_NAME should be set) -#define AFL_TILCMT 0x00008000L ///< has type comment? (such a comment may be changed by IDA) -#define AFL_LZERO0 0x00010000L ///< toggle leading zeroes for the 1st operand -#define AFL_LZERO1 0x00020000L ///< toggle leading zeroes for the 2nd operand -#define AFL_COLORED 0x00040000L ///< has user defined instruction color? -#define AFL_TERSESTR 0x00080000L ///< terse structure variable display? -#define AFL_SIGN0 0x00100000L ///< code: toggle sign of the 1st operand -#define AFL_SIGN1 0x00200000L ///< code: toggle sign of the 2nd operand -#define AFL_NORET 0x00400000L ///< for imported function pointers: doesn't return. - ///< this flag can also be used for any instruction - ///< which halts or finishes the program execution -#define AFL_FIXEDSPD 0x00800000L ///< sp delta value is fixed by analysis. - ///< should not be modified by modules -#define AFL_ALIGNFLOW 0x01000000L ///< the previous insn was created for alignment purposes only -#define AFL_USERTI 0x02000000L ///< the type information is definitive. - ///< (comes from the user or type library) -#define AFL_RETFP 0x04000000L ///< function returns a floating point value -#define AFL_USEMODSP 0x08000000L ///< insn modifes SP and uses the modified value - ///< example: pop [rsp+N] -#define AFL_NOTCODE 0x10000000L ///< autoanalysis should not create code here -#define AFL_NOTPROC 0x20000000L ///< autoanalysis should not create proc here -//@} - -/// \name Work with additional location flags -/// See \ref AFL_ -//@{ -inline void set_aflags0(ea_t ea, uint32 flags) { getnode(ea).altset(NALT_AFLAGS,flags); } -inline uint32 get_aflags0(ea_t ea) { return flags_t(getnode(ea).altval(NALT_AFLAGS)); } -inline void del_aflags0(ea_t ea) { getnode(ea).altdel(NALT_AFLAGS); } -idaman void ida_export set_aflags(ea_t ea, uint32 flags); -idaman void ida_export set_abits(ea_t ea,uint32 bits); -idaman void ida_export clr_abits(ea_t ea,uint32 bits); -idaman uint32 ida_export get_aflags(ea_t ea); -idaman void ida_export del_aflags(ea_t ea); - -inline bool is_hidden_item(ea_t ea) { return (get_aflags(ea) & AFL_HIDDEN) != 0; } -inline void hide_item(ea_t ea) { set_abits(ea, AFL_HIDDEN); } -inline void unhide_item(ea_t ea) { clr_abits(ea, AFL_HIDDEN); } - -inline bool is_hidden_border(ea_t ea) { return (get_aflags(ea) & AFL_NOBRD) != 0; } -inline void hide_border(ea_t ea) { set_abits(ea, AFL_NOBRD); } -inline void unhide_border(ea_t ea) { clr_abits(ea, AFL_NOBRD); } - -inline bool uses_modsp(ea_t ea) { return (get_aflags(ea) & AFL_USEMODSP) != 0; } -inline void set_usemodsp(ea_t ea) { set_abits(ea, AFL_USEMODSP); } -inline void clr_usemodsp(ea_t ea) { clr_abits(ea, AFL_USEMODSP); } - -inline bool is_zstroff(ea_t ea) { return (get_aflags(ea) & AFL_ZSTROFF) != 0; } -inline void set_zstroff(ea_t ea) { set_abits(ea, AFL_ZSTROFF); } -inline void clr_zstroff(ea_t ea) { clr_abits(ea, AFL_ZSTROFF); } - -inline bool is__bnot0(ea_t ea) { return (get_aflags(ea) & AFL_BNOT0) != 0; } -inline void set__bnot0(ea_t ea) { set_abits(ea, AFL_BNOT0); } -inline void clr__bnot0(ea_t ea) { clr_abits(ea, AFL_BNOT0); } - -inline bool is__bnot1(ea_t ea) { return (get_aflags(ea) & AFL_BNOT1) != 0; } -inline void set__bnot1(ea_t ea) { set_abits(ea, AFL_BNOT1); } -inline void clr__bnot1(ea_t ea) { clr_abits(ea, AFL_BNOT1); } - -inline bool is_libitem(ea_t ea) { return (get_aflags(ea) & AFL_LIB) != 0; } -inline void set_libitem(ea_t ea) { set_abits(ea, AFL_LIB); } -inline void clr_libitem(ea_t ea) { clr_abits(ea, AFL_LIB); } - -inline bool has_ti(ea_t ea) { return (get_aflags(ea) & AFL_TI) != 0; } -inline void set_has_ti(ea_t ea) { set_abits(ea, AFL_TI); } -inline void clr_has_ti(ea_t ea) { clr_abits(ea, AFL_TI); } - -inline bool has_ti0(ea_t ea) { return (get_aflags(ea) & AFL_TI0) != 0; } -inline void set_has_ti0(ea_t ea) { set_abits(ea, AFL_TI0); } -inline void clr_has_ti0(ea_t ea) { clr_abits(ea, AFL_TI0); } - -inline bool has_ti1(ea_t ea) { return (get_aflags(ea) & AFL_TI1) != 0; } -inline void set_has_ti1(ea_t ea) { set_abits(ea, AFL_TI1); } -inline void clr_has_ti1(ea_t ea) { clr_abits(ea, AFL_TI1); } - -inline bool has_lname(ea_t ea) { return (get_aflags(ea) & AFL_LNAME) != 0; } -inline void set_has_lname(ea_t ea) { set_abits(ea, AFL_LNAME); } -inline void clr_has_lname(ea_t ea) { clr_abits(ea, AFL_LNAME); } - -inline bool is_tilcmt(ea_t ea) { return (get_aflags(ea) & AFL_TILCMT) != 0; } -inline void set_tilcmt(ea_t ea) { set_abits(ea, AFL_TILCMT); } -inline void clr_tilcmt(ea_t ea) { clr_abits(ea, AFL_TILCMT); } - -inline bool is_usersp(ea_t ea) { return (get_aflags(ea) & AFL_USERSP) != 0; } -inline void set_usersp(ea_t ea) { set_abits(ea, AFL_USERSP); } -inline void clr_usersp(ea_t ea) { clr_abits(ea, AFL_USERSP); } - -inline bool is_lzero0(ea_t ea) { return (get_aflags(ea) & AFL_LZERO0) != 0; } -inline void set_lzero0(ea_t ea) { set_abits(ea, AFL_LZERO0); } -inline void clr_lzero0(ea_t ea) { clr_abits(ea, AFL_LZERO0); } - -inline bool is_lzero1(ea_t ea) { return (get_aflags(ea) & AFL_LZERO1) != 0; } -inline void set_lzero1(ea_t ea) { set_abits(ea, AFL_LZERO1); } -inline void clr_lzero1(ea_t ea) { clr_abits(ea, AFL_LZERO1); } - -inline bool is_colored_item(ea_t ea) { return (get_aflags(ea) & AFL_COLORED) != 0; } -inline void set_colored_item(ea_t ea) { set_abits(ea, AFL_COLORED); } // use set_item_color() -inline void clr_colored_item(ea_t ea) { clr_abits(ea, AFL_COLORED); } // use del_item_color() - -inline bool is_terse_struc(ea_t ea) { return (get_aflags(ea) & AFL_TERSESTR) != 0; } -inline void set_terse_struc(ea_t ea) { set_abits(ea, AFL_TERSESTR); } -inline void clr_terse_struc(ea_t ea) { clr_abits(ea, AFL_TERSESTR); } - -inline bool is__invsign0(ea_t ea) { return (get_aflags(ea) & AFL_SIGN0) != 0; } -inline void set__invsign0(ea_t ea) { set_abits(ea, AFL_SIGN0); } -inline void clr__invsign0(ea_t ea) { clr_abits(ea, AFL_SIGN0); } - -inline bool is__invsign1(ea_t ea) { return (get_aflags(ea) & AFL_SIGN1) != 0; } -inline void set__invsign1(ea_t ea) { set_abits(ea, AFL_SIGN1); } -inline void clr__invsign1(ea_t ea) { clr_abits(ea, AFL_SIGN1); } - -inline bool is_noret(ea_t ea) { return (get_aflags(ea) & AFL_NORET) != 0; } -inline void set_noret(ea_t ea) { set_abits(ea, AFL_NORET); } -inline void clr_noret(ea_t ea) { clr_abits(ea, AFL_NORET); } - -inline bool is_fixed_spd(ea_t ea) { return (get_aflags(ea) & AFL_FIXEDSPD) != 0; } -inline void set_fixed_spd(ea_t ea) { set_abits(ea, AFL_FIXEDSPD); } -inline void clr_fixed_spd(ea_t ea) { clr_abits(ea, AFL_FIXEDSPD); } - -inline bool is_align_flow(ea_t ea) { return (get_aflags(ea) & AFL_ALIGNFLOW) != 0; } -inline void set_align_flow(ea_t ea) { set_abits(ea, AFL_ALIGNFLOW); } -inline void clr_align_flow(ea_t ea) { clr_abits(ea, AFL_ALIGNFLOW); } - -inline bool is_userti(ea_t ea) { return (get_aflags(ea) & AFL_USERTI) != 0; } -inline void set_userti(ea_t ea) { set_abits(ea, AFL_USERTI); } -inline void clr_userti(ea_t ea) { clr_abits(ea, AFL_USERTI); } - -inline bool is_retfp(ea_t ea) { return (get_aflags(ea) & AFL_RETFP) != 0; } -inline void set_retfp(ea_t ea) { set_abits(ea, AFL_RETFP); } -inline void clr_retfp(ea_t ea) { clr_abits(ea, AFL_RETFP); } - -inline bool is_notproc(ea_t ea) { return (get_aflags(ea) & AFL_NOTPROC) != 0; } -inline void set_notproc(ea_t ea) { set_abits(ea, AFL_NOTPROC); } -inline void clr_notproc(ea_t ea) { clr_abits(ea, AFL_NOTPROC); } -//@} - -/// Mark address so that it cannot be converted to instruction -idaman void ida_export set_notcode(ea_t ea); - -/// Clear not-code mark -inline void clr_notcode(ea_t ea) { clr_abits(ea, AFL_NOTCODE); } - -/// Is the address marked as not-code? -inline bool is_notcode(ea_t ea) { return (get_aflags(ea) & AFL_NOTCODE) != 0; } - - -/// Change visibility of item at given ea - -inline void set_visible_item(ea_t ea, bool visible) -{ - if ( visible ) - unhide_item(ea); - else - hide_item(ea); -} - -/// Test visibility of item at given ea - -inline bool is_visible_item(ea_t ea) { return !is_hidden_item(ea); } - - -/// Is instruction visible? - -inline bool is_finally_visible_item(ea_t ea) -{ - return (inf_get_cmtflg() & SCF_SHHID_ITEM) != 0 || is_visible_item(ea); -} - - -/// \name Source line numbers -/// They are sometimes present in object files. -//@{ -idaman void ida_export set_source_linnum(ea_t ea, uval_t lnnum); -idaman uval_t ida_export get_source_linnum(ea_t ea); -idaman void ida_export del_source_linnum(ea_t ea); -//@} - -/// \name Absolute segment base address -/// These functions may be used if necessary (despite of the AFLNOTE above). -//@{ -inline ea_t get_absbase(ea_t ea) -{ - ea_t x; - return getnode(ea).supval(NALT_ABSBASE, &x, sizeof(x), atag) > 0 ? ea_t(x-1) : ea_t(-1); -} -inline void set_absbase(ea_t ea, ea_t x) -{ - x++; - getnode(ea).supset(NALT_ABSBASE, &x, sizeof(x), atag); -} -inline void del_absbase(ea_t ea) { getnode(ea).supdel(NALT_ABSBASE, atag); } -//@} - -/// \name Purged bytes -/// Number of bytes purged from the stack when a function is called indirectly -/// get_ind_purged() may be used if necessary (despite of the AFLNOTE above). -/// Use set_purged() to modify this value (do not use set_ind_purged()) -//@{ -inline ea_t get_ind_purged(ea_t ea) -{ - ea_t x; - return getnode(ea).supval(NALT_PURGE, &x, sizeof(x), atag) > 0 ? ea_t(x-1) : ea_t(-1); -} -inline void set_ind_purged(ea_t ea, ea_t x) -{ - x++; - getnode(ea).supset(NALT_PURGE, &x, sizeof(x), atag); -} -inline void del_ind_purged(ea_t ea) { getnode(ea).supdel(NALT_PURGE, atag); } -//@} - -/// \name Get type of string -/// Use higher level function get_opinfo(). -//@{ -inline uint32 get_str_type(ea_t ea) -{ - uint32 x; - return getnode(ea).supval(NALT_STRTYPE, &x, sizeof(x), atag) > 0 ? uint32(x-1) : uint32(-1); -} -inline void set_str_type(ea_t ea, uint32 x) -{ - x++; - getnode(ea).supset(NALT_STRTYPE, &x, sizeof(x), atag); -} -inline void del_str_type(ea_t ea) { getnode(ea).supdel(NALT_STRTYPE, atag); } -//@} - -// Number of bytes per "units" in a string. E.g., ASCII, Windows-1252, -// UTF-8 all take up one byte per unit, while UTF-16 variations take 2 and -// UTF-32 variations take 4. -// (Note that an "unit" in this context is not necessarily a character, -// since UTF-8-encoded characters can be encoded in up to 4 bytes, -// and UTF-16-encoded characters can be encoded in up to 2 bytes.) -#define STRWIDTH_1B 0 -#define STRWIDTH_2B 1 -#define STRWIDTH_4B 2 -#define STRWIDTH_MASK 0x03 - -// The string layout; how the string is laid out in data. -#define STRLYT_TERMCHR 0 -#define STRLYT_PASCAL1 1 -#define STRLYT_PASCAL2 2 -#define STRLYT_PASCAL4 3 -#define STRLYT_MASK 0xFC -#define STRLYT_SHIFT 2 - - -/// \defgroup STRTYPE_ String type codes -//@{ -///< Character-terminated string. The termination characters are kept in -///< the next bytes of string type. -#define STRTYPE_TERMCHR (STRWIDTH_1B|STRLYT_TERMCHR<<STRLYT_SHIFT) -///< C-style string. -#define STRTYPE_C STRTYPE_TERMCHR -///< Zero-terminated 16bit chars -#define STRTYPE_C_16 (STRWIDTH_2B|STRLYT_TERMCHR<<STRLYT_SHIFT) -///< Zero-terminated 32bit chars -#define STRTYPE_C_32 (STRWIDTH_4B|STRLYT_TERMCHR<<STRLYT_SHIFT) -///< Pascal-style, one-byte length prefix -#define STRTYPE_PASCAL (STRWIDTH_1B|STRLYT_PASCAL1<<STRLYT_SHIFT) -///< Pascal-style, 16bit chars, one-byte length prefix -#define STRTYPE_PASCAL_16 (STRWIDTH_2B|STRLYT_PASCAL1<<STRLYT_SHIFT) -///< Pascal-style, two-byte length prefix -#define STRTYPE_LEN2 (STRWIDTH_1B|STRLYT_PASCAL2<<STRLYT_SHIFT) -///< Pascal-style, 16bit chars, two-byte length prefix -#define STRTYPE_LEN2_16 (STRWIDTH_2B|STRLYT_PASCAL2<<STRLYT_SHIFT) -///< Pascal-style, four-byte length prefix -#define STRTYPE_LEN4 (STRWIDTH_1B|STRLYT_PASCAL4<<STRLYT_SHIFT) -///< Pascal-style, 16bit chars, four-byte length prefix -#define STRTYPE_LEN4_16 (STRWIDTH_2B|STRLYT_PASCAL4<<STRLYT_SHIFT) -//@} - -/// \name Work with string type codes -/// See \ref STRTYPE_ -//@{ -inline THREAD_SAFE uchar idaapi get_str_type_code(int32 strtype) { return uchar(strtype); } -inline THREAD_SAFE char get_str_term1(int32 strtype) { return char(strtype>>8); } -inline THREAD_SAFE char get_str_term2(int32 strtype) { return char(strtype>>16); } - // if the second termination character is - // '\0', then it doesn't exist. -/// Get index of the string encoding for this string -inline THREAD_SAFE uchar idaapi get_str_encoding_idx(int32 strtype) { return uchar(strtype>>24); } - -inline THREAD_SAFE bool is_pascal(int32 strtype) -{ - int lyt = get_str_type_code(strtype) >> STRLYT_SHIFT; - return lyt >= STRLYT_PASCAL1 && lyt <= STRLYT_PASCAL4; -} - -inline THREAD_SAFE size_t get_str_type_prefix_length(int32 strtype) -{ - switch ( get_str_type_code(strtype) ) - { - case STRTYPE_LEN4_16: - case STRTYPE_LEN4: - return 4; - case STRTYPE_LEN2_16: - case STRTYPE_LEN2: - return 2; - case STRTYPE_PASCAL_16: - case STRTYPE_PASCAL: - return 1; - } - return 0; -} -//@} - -#define STRENC_DEFAULT 0x00 ///< use default encoding for this type (see get_default_encoding_idx()) -#define STRENC_NONE 0xFF ///< force no-conversion encoding - -/// \name Alignment value -/// (should be power of 2) -/// These functions may be used if necessary (despite of the AFLNOTE above). -//@{ -inline uint32 get_alignment(ea_t ea) -{ - uint32 x; - return getnode(ea).supval(NALT_ALIGN, &x, sizeof(x), atag) > 0 ? uint32(x-1) : uint32(-1); -} -inline void set_alignment(ea_t ea,uint32 x) -{ - x++; - getnode(ea).supset(NALT_ALIGN, &x, sizeof(x), atag); -} -inline void del_alignment(ea_t ea) { getnode(ea).supdel(NALT_ALIGN, atag); } -//@} - - -/// \name Instruction/Data background color -//@{ -idaman void ida_export set_item_color(ea_t ea, bgcolor_t color); -idaman bgcolor_t ida_export get_item_color(ea_t ea); // returns DEFCOLOR if no color -idaman bool ida_export del_item_color(ea_t ea); -//@} - - -//------------------------------------------------------------------------- -/// \name Array representation -//@{ -/// Describes how to display an array -struct array_parameters_t -{ - int32 flags; -#define AP_ALLOWDUPS 0x00000001L ///< use 'dup' construct -#define AP_SIGNED 0x00000002L ///< treats numbers as signed -#define AP_INDEX 0x00000004L ///< display array element indexes as comments -#define AP_ARRAY 0x00000008L ///< create as array (this flag is not stored in database) -#define AP_IDXBASEMASK 0x000000F0L ///< mask for number base of the indexes -#define AP_IDXDEC 0x00000000L ///< display indexes in decimal -#define AP_IDXHEX 0x00000010L ///< display indexes in hex -#define AP_IDXOCT 0x00000020L ///< display indexes in octal -#define AP_IDXBIN 0x00000030L ///< display indexes in binary - - int32 lineitems; ///< number of items on a line - int32 alignment; ///< -1 - don't align. - ///< 0 - align automatically. - ///< else item width -}; -idaman ssize_t ida_export get_array_parameters(array_parameters_t *out, ea_t ea); -idaman void ida_export set_array_parameters(ea_t ea, const array_parameters_t *in); -inline void idaapi del_array_parameters(ea_t ea) { getnode(ea).supdel(NSUP_ARRAY); } -//@} - -//-------------------------------------------------------------------------- -/// Information about a switch statement -struct switch_info_t -{ - uint32 flags; ///< \ref SWI_ -/// \defgroup SWI_ Switch info flags -/// Used by switch_info_t::flags -//@{ -#define SWI_SPARSE 0x00000001 ///< sparse switch (value table present) - ///< otherwise lowcase present -#define SWI_V32 0x00000002 ///< 32-bit values in table -#define SWI_J32 0x00000004 ///< 32-bit jump offsets -#define SWI_VSPLIT 0x00000008 ///< value table is split (only for 32-bit values) -#define SWI_RESERVED 0x00000010 ///< was: SWI_DEFAULT -#define SWI_DEF_IN_TBL 0x00000020 ///< default case is an entry in the jump table. - ///< This flag is applicable in 2 cases: - ///< 1. The sparse indirect switch (i.e. a switch with a values table) - ///< <jump table size> == <value table size> + 1. - ///< The default case entry is the last one in the table - ///< (or the first one in the case of an inversed jump table). - ///< 2. The switch with insns in the jump table. - ///< The default case entry is before the first entry of the table. - ///< See also the find_defjump_from_table() helper function. -#define SWI_JMP_INV 0x00000040 ///< jumptable is inversed. (last entry is - ///< for first entry in values table) -#define SWI_SHIFT_MASK 0x00000180 ///< use formula (element<<shift) + elbase to find jump targets -#define SWI_ELBASE 0x00000200 ///< elbase is present (otherwise the base of the switch - ///< segment will be used) -#define SWI_JSIZE 0x00000400 ///< jump offset expansion bit -#define SWI_VSIZE 0x00000800 ///< value table element size expansion bit -#define SWI_SEPARATE 0x00001000 ///< create an array of individual elements (otherwise separate items) -#define SWI_SIGNED 0x00002000 ///< jump table entries are signed -#define SWI_CUSTOM 0x00004000 ///< custom jump table. - ///< \ph{create_switch_xrefs} will be called to create code xrefs - ///< for the table. Custom jump table must be created by the - ///< module (see also #SWI_STDTBL) -//#define SWI_EXTENDED 0x00008000 ///< reserved -#define SWI_INDIRECT 0x00010000 ///< value table elements are used as indexes into the jump table - ///< (for sparse switches) -#define SWI_SUBTRACT 0x00020000 ///< table values are subtracted from the elbase instead of being added -#define SWI_HXNOLOWCASE 0x00040000 ///< lowcase value should not be used by the decompiler (internal flag) -#define SWI_STDTBL 0x00080000 ///< custom jump table with standard table formatting. - ///< ATM IDA doesn't use SWI_CUSTOM for switches with standard - ///< table formatting. So this flag can be considered as obsolete. -#define SWI_DEFRET 0x00100000 ///< return in the default case (defjump==BADADDR) -#define SWI_SELFREL 0x00200000 ///< jump address is relative to the element not to ELBASE -#define SWI_JMPINSN 0x00400000 ///< jump table entries are insns. For such entries SHIFT has a - ///< different meaning. It denotes the number of insns in the - ///< entry. For example, 0 - the entry contains the jump to the - ///< case, 1 - the entry contains one insn like a 'mov' and jump - ///< to the end of case, and so on. -#define SWI_VERSION 0x00800000 ///< the structure contains the VERSION member -//@} - - /// See #SWI_SHIFT_MASK. - /// possible answers: 0..3. - int get_shift(void) const { return ((flags & SWI_SHIFT_MASK) >> 7); } - - /// See #SWI_SHIFT_MASK - void set_shift(int shift) - { - flags &= ~SWI_SHIFT_MASK; - flags |= ((shift & 3) << 7); - } - - int get_jtable_element_size(void) const - { // this brain damaged logic is needed for compatibility with old versions - int code = flags & (SWI_J32|SWI_JSIZE); - if ( code == 0 ) - return 2; - if ( code == SWI_J32 ) - return 4; - if ( code == SWI_JSIZE ) - return 1; - return 8; - } - void set_jtable_element_size(int size) - { - flags &= ~SWI_J32|SWI_JSIZE; - switch ( size ) - { - case 4: - flags |= SWI_J32; - break; - case 1: - flags |= SWI_JSIZE; - break; - case 8: - flags |= SWI_J32|SWI_JSIZE; - break; - case 2: - break; - default: - INTERR(1297); - } - } - int get_vtable_element_size(void) const - { - int code = flags & (SWI_V32|SWI_VSIZE); - if ( code == 0 ) - return 2; - if ( code == SWI_V32 ) - return 4; - if ( code == SWI_VSIZE ) - return 1; - return 8; - } - void set_vtable_element_size(int size) - { - flags &= ~SWI_V32|SWI_VSIZE; - switch ( size ) - { - case 4: - flags |= SWI_V32; - break; - case 1: - flags |= SWI_VSIZE; - break; - case 8: - flags |= SWI_V32|SWI_VSIZE; - break; - case 2: - break; - default: - INTERR(1298); - } - } - - bool has_default(void) const { return defjump != BADADDR; } - bool has_elbase(void) const { return (flags & SWI_ELBASE) != 0; } - bool is_sparse(void) const { return (flags & SWI_SPARSE) != 0; } - bool is_custom(void) const { return (flags & SWI_CUSTOM) != 0; } - bool is_indirect(void) const { return (flags & SWI_INDIRECT) != 0; } - bool is_subtract(void) const { return (flags & SWI_SUBTRACT) != 0; } - bool is_nolowcase(void) const { return (flags & SWI_HXNOLOWCASE) != 0; } - bool use_std_table(void) const { return !is_custom() || (flags & SWI_STDTBL) != 0; } - - ushort ncases; ///< number of cases (excluding default) - ea_t jumps; ///< jump table start address - union - { - ea_t values; ///< values table address (if #SWI_SPARSE is set) - uval_t lowcase; ///< the lowest value in cases - }; - ea_t defjump; ///< default jump address (#BADADDR if no default case) - ea_t startea; ///< start of the switch idiom - int jcases; ///< number of entries in the jump table (SWI_INDIRECT) - - sval_t ind_lowcase; - sval_t get_lowcase(void) const { return is_indirect() ? ind_lowcase : lowcase; } - ea_t elbase; ///< element base - - int regnum; ///< the switch expression as a value of the REGNUM register - ///< before the instruction at EXPR_EA. -1 means 'unknown' - op_dtype_t regdtype; ///< size of the switch expression register as dtype - - int get_jtable_size(void) const { return is_indirect() ? jcases : ncases; } - void set_jtable_size(int size) - { - if ( is_indirect() ) - jcases = size; - else - ncases = uint16(size); - } - void set_elbase(ea_t base) - { - elbase = base; - flags |= SWI_ELBASE; - } - - void set_expr(int r, op_dtype_t dt) { regnum = r; regdtype = dt; } - - /// get separate parts of the switch - bool get_jrange_vrange(range_t *jrange = NULL, range_t *vrange = NULL) const - { - if ( !use_std_table() ) - return false; - if ( jrange != NULL ) - { - int n = get_jtable_size(); - if ( (flags & SWI_DEF_IN_TBL) != 0 ) - ++n; - int jsize = get_jtable_element_size(); - *jrange = range_t(jumps, jumps + jsize * n); - } - if ( vrange != NULL && is_sparse() ) - { - int vsize = get_vtable_element_size(); - *vrange = range_t(values, values + vsize * ncases); - } - return true; - } - - uval_t custom; ///< information for custom tables (filled and used by modules) - - enum { SWITCH_INFO_VERSION = 2 }; - int version; - int get_version() const - { - return (flags & SWI_VERSION) == 0 ? 1 : version; - } - - // version 2 - ea_t expr_ea; ///< the address before that the switch expression is in REGNUM. - ///< If BADADDR, then the first insn marked as IM_SWITCH after - ///< STARTEA is used. - eavec_t marks; ///< the insns marked as IM_SWITCH. They used to delete the switch. - - switch_info_t(void) - : flags(SWI_VERSION), - ncases(0), - jumps(BADADDR), - lowcase(0), - defjump(BADADDR), - startea(BADADDR), - jcases(0), - ind_lowcase(0), - elbase(0), - regnum(-1), - regdtype(0), - custom(0), - version(SWITCH_INFO_VERSION), - expr_ea(BADADDR), - marks() {} - void clear(void) { *this = switch_info_t(); } -}; - -/// \name Switch info -/// See ::switch_info_t, xref.hpp for related functions -//@{ -idaman ssize_t ida_export get_switch_info(switch_info_t *out, ea_t ea); -idaman void ida_export set_switch_info(ea_t ea, const switch_info_t &in); -idaman void ida_export del_switch_info(ea_t ea); -//@} - -/// \name Switch parent -/// Address which holds the switch info (::switch_info_t). Used at the jump targets. -//@{ -inline ea_t get_switch_parent(ea_t ea) -{ - ea_t x; - return getnode(ea).supval(NALT_SWITCH, &x, sizeof(x), atag) > 0 ? ea_t(x-1) : ea_t(-1); -} -inline void set_switch_parent(ea_t ea,ea_t x) -{ - x++; - getnode(ea).supset(NALT_SWITCH, &x, sizeof(x), atag); -} -inline void del_switch_parent(ea_t ea) { getnode(ea).supdel(NALT_SWITCH, atag); } -//@} - -/// \name Custom data types -//@{ -/// Information about custom data types -struct custom_data_type_ids_t -{ - int16 dtid; ///< data type id - int16 fids[UA_MAXOP]; ///< data format ids - - void set(tid_t tid) - { - memset(fids, -1, sizeof(fids)); - dtid = ushort(tid); - fids[0] = ushort(tid >> 16); - } -}; -idaman int ida_export get_custom_data_type_ids(custom_data_type_ids_t *cdis, ea_t ea); -idaman void ida_export set_custom_data_type_ids(ea_t ea, const custom_data_type_ids_t *cdis); -inline void idaapi del_custom_data_type_ids(ea_t ea) { getnode(ea).supdel(NSUP_CUSTDT); } -//@} - -typedef uchar reftype_t; ///< see \ref reftype_ -/// \defgroup reftype_ Types of references -/// References are represented in the following form: -/// -/// \v{target + tdelta - base} -/// -/// If the target is not present, then it will be calculated using -/// -/// \v{target = operand_value - tdelta + base} -/// -/// The target must be present for LOW and HIGH reference types -//@{ -const reftype_t - V695_REF_OFF8 = 0, ///< reserved - REF_OFF16 = 1, ///< 16bit full offset - REF_OFF32 = 2, ///< 32bit full offset - REF_LOW8 = 3, ///< low 8bits of 16bit offset - REF_LOW16 = 4, ///< low 16bits of 32bit offset - REF_HIGH8 = 5, ///< high 8bits of 16bit offset - REF_HIGH16 = 6, ///< high 16bits of 32bit offset - V695_REF_VHIGH = 7, ///< obsolete - V695_REF_VLOW = 8, ///< obsolete - REF_OFF64 = 9, ///< 64bit full offset - REF_OFF8 = 10, ///< 8bit full offset - REF_LAST = REF_OFF8; -//@} - -/// Can the target be calculated using operand value? - -inline bool is_reftype_target_optional(reftype_t type); - -/// Get REF_... constant from size -/// Supported sizes: 1,2,4,8,16 -/// For other sizes returns reftype_t(-1) - -idaman reftype_t ida_export get_reftype_by_size(size_t size); - -/// Information about a reference -struct refinfo_t -{ - ea_t target; ///< reference target (#BADADDR-none) - ea_t base; ///< base of reference (may be BADADDR) - adiff_t tdelta; ///< offset from the target - uint32 flags; ///< \ref REFINFO_ -/// \defgroup REFINFO_ Reference info flags -/// Used by refinfo_t::flags -//@{ -#define REFINFO_TYPE 0x000F ///< reference type -#define REFINFO_RVAOFF 0x0010 ///< based reference (rva) - ///< refinfo_t::base will be forced to get_imagebase() - ///< such a reference is displayed with the \ash{a_rva} keyword -#define REFINFO_PASTEND 0x0020 ///< reference past an item - ///< it may point to an nonexistent address - ///< do not destroy alignment dirs -#define REFINFO_CUSTOM 0x0040 ///< a custom reference - ///< the kernel will call \ph{notify}(ph.custom_offset, .... - ///< that can change all arguments used for calculations. - ///< This flag is useful for custom fixups -#define REFINFO_NOBASE 0x0080 ///< don't create the base xref - ///< implies that the base can be any value - ///< nb: base xrefs are created only if the offset base - ///< points to the middle of a segment -#define REFINFO_SUBTRACT 0x0100 ///< the reference value is subtracted from the base value instead of (as usual) being added to it -#define REFINFO_SIGNEDOP 0x0200 ///< the operand value is sign-extended (only supported for REF_OFF8/16/32/64) -//@} - - reftype_t type(void) const - { - return reftype_t(flags & (REFINFO_TYPE | REFINFO_CUSTOM)); - } - - bool is_target_optional() const ///< \ref is_reftype_target_optional() - { - reftype_t rt = flags & (REFINFO_TYPE | REFINFO_CUSTOM); - return is_reftype_target_optional(rt); - } - - bool no_base_xref(void) const { return (flags & REFINFO_NOBASE) != 0; } - bool is_pastend(void) const { return (flags & REFINFO_PASTEND) != 0; } - bool is_rvaoff(void) const { return (flags & REFINFO_RVAOFF) != 0; } - bool is_custom(void) const { return (flags & REFINFO_CUSTOM) != 0; } - bool is_subtract(void) const { return (flags & REFINFO_SUBTRACT) != 0; } - bool is_signed(void) const { return (flags & REFINFO_SIGNEDOP) != 0; } - - // RT can include REFINFO_CUSTOM bit - void set_type(reftype_t rt) - { - flags &= ~(REFINFO_TYPE | REFINFO_CUSTOM); - flags |= rt; - } - - // init the structure with some default values - // reft_and_flags should be REF_xxx optionally ORed with some REFINFO_xxx flags - void init(uint32 reft_and_flags, ea_t _base = 0, ea_t _target = BADADDR, adiff_t _tdelta = 0) - { - flags = reft_and_flags; - base = _base; - target = _target; - tdelta = _tdelta; - } - - // internal use - ea_t _get_target(adiff_t opval) const; - ea_t _get_value(ea_t target) const; - adiff_t _get_opval(adiff_t opval) const; -}; - -/// Manage a custom refinfo type -struct custom_refinfo_handler_t -{ - int32 cbsize; ///< size of this structure - const char *name; ///< Format name, must be unique - const char *desc; ///< Refinfo description to use in Ctrl-R dialog - int props; ///< properties (currently 0) -/// \defgroup RHF_ Refinfo handler properties -/// Used by custom_refinfo_handler_t::props -//@{ -#define RHF_TGTOPT 0x0001 ///< can the target be calculated using - ///< operand value? -//@} - - // this callback prepares the full offset expression in buf and - // returns 1 if it is a simple expression or 2 if it is a complex one. - // Or this callback checks the compliance of opval and fullvalue, - // and possibly updates values of target and fullvalue, - // and prepares the format, - // and returns 3 to continue standard processing with updated values. - // Or this callback just prepares the format and returns 4 to continue. - // It returns 0 in the case of error. - // It is guaranteed that before calling this callback, the - // calc_reference_data() callback is always called. - int (idaapi *gen_expr)( - qstring *buf, - qstring *format, // buffer for the format (if retcode>=3) - ea_t ea, - int opnum, - const refinfo_t &ri, - ea_t from, - adiff_t *opval, // the output value is not used - ea_t *target, // the target prepared by calc_reference_data() - ea_t *fullvalue, - int getn_flags); - - // this callback replaces calc_target. - // It calculates target and base, - // and calculates an internal variable fullvalue, - // and checks the compliance of opval and fullvalue, - // and returns the success flag. - bool (idaapi *calc_reference_data)( - ea_t *target, - ea_t *base, - ea_t from, - const refinfo_t &ri, - adiff_t opval); - - // just custom format - void (idaapi *get_format)(qstring *format); -}; - - -/// Register a new custom refinfo type. - -idaman int ida_export register_custom_refinfo(const custom_refinfo_handler_t *crh); - - -/// Unregister a new custom refinfo type. - -idaman bool ida_export unregister_custom_refinfo(int crid); - - -/// Get id of a custom refinfo type. - -idaman int ida_export find_custom_refinfo(const char *name); - - -/// Get definition of a registered custom refinfo type. - -idaman const custom_refinfo_handler_t *ida_export get_custom_refinfo(int crid); - - -/// Get refinfo handler - -inline const custom_refinfo_handler_t *idaapi get_custom_refinfo_handler( - const refinfo_t &ri) -{ - return ri.is_custom() ? get_custom_refinfo(ri.type()) : NULL; -} - -// inline implementaion -inline bool is_reftype_target_optional(reftype_t type) -{ - if ( (type & REFINFO_CUSTOM) != 0 ) - { - const custom_refinfo_handler_t *cfh = get_custom_refinfo(type); - if ( cfh == NULL ) - return false; - return (cfh->props & RHF_TGTOPT) != 0; - } - switch ( type ) - { - case REF_OFF8: - case REF_OFF16: - case REF_OFF32: - case REF_OFF64: - return true; - } - return false; -} - - -/// Get descriptions of all standard and custom refinfo types. - -struct refinfo_desc_t -{ - uint32 type; ///< Refinfo type, see \ref REFINFO_ - ///< Custom refinfo has REFINFO_CUSTOM bit. - const char *name; ///< Refinfo name - const char *desc; ///< Refinfo description to use in Ctrl-R dialog -}; -DECLARE_TYPE_AS_MOVABLE(refinfo_desc_t); -typedef qvector<refinfo_desc_t> refinfo_desc_vec_t; -idaman void ida_export get_refinfo_descs(refinfo_desc_vec_t *descs); - - -#define MAXSTRUCPATH 32 ///< maximal inclusion depth of unions - -/// Information for structure offsets. -/// ids[0] contains the id of the structure. -/// ids[1..len-1] contain ids of the structure members used in the structure offset -/// expression. -/// len is the length of the path, i.e. the number of elements in 'ids' -struct strpath_t -{ - int len; - tid_t ids[MAXSTRUCPATH]; // for union member ids - adiff_t delta; -}; - -/// See opinfo_t::ec -struct enum_const_t -{ - tid_t tid; - uchar serial; -}; - -/// Additional information about an operand type -union opinfo_t -{ - refinfo_t ri; ///< for offset members - tid_t tid; ///< for struct, etc. members - strpath_t path; ///< for stroff - int32 strtype; ///< for strings (\ref STRTYPE_) - enum_const_t ec; ///< for enums - custom_data_type_ids_t cd; ///< for custom data -}; - -//-V:printop_t:730 Not all members of a class are initialized inside the constructor -struct printop_t -{ - flags_t flags; // new operand representation flags - opinfo_t ti; // new operand type -#define POF_VALID_TI 0x1 // is operand type initialized? -#define POF_VALID_AFLAGS 0x2 // internal - uchar features; // features this instance holds - int suspop; // out: will be set by print_operand() - flags_t aflags; // alternative aflags - - printop_t() : flags(0), features(0), suspop(0), aflags(0) {} //-V730 'ti' is not initialized - bool is_ti_initialized() const { return (features & POF_VALID_TI) == POF_VALID_TI; } - void set_ti_initialized(bool v=true) { setflag(features, POF_VALID_TI, v); } - bool is_aflags_initialized() const { return (features & POF_VALID_AFLAGS) == POF_VALID_AFLAGS; } - void set_aflags_initialized(bool v=true) { setflag(features, POF_VALID_AFLAGS, v); } - - const opinfo_t *get_ti() const { return is_ti_initialized() ? &ti : NULL; } -}; - -/// \name Get/Set refinfo -/// n may be 0, 1, 2, #OPND_MASK. -/// #OPND_OUTER may be used too. -/// Don't use these functions, see get_opinfo(), set_opinfo() -//@{ -idaman bool ida_export set_refinfo_ex(ea_t ea, int n, const refinfo_t *ri); -idaman bool ida_export set_refinfo( - ea_t ea, - int n, - reftype_t type, - ea_t target=BADADDR, - ea_t base=0, - adiff_t tdelta=0); -idaman bool ida_export get_refinfo(refinfo_t *ri, ea_t ea, int n); -idaman bool ida_export del_refinfo(ea_t ea, int n); -//@} - -//-------------------------------------------------------------------------- -/// \name Structure paths -/// Structure paths for unions and structures with unions (strpath) -/// a structure path is an array of id's. -/// the first id is the id of the structure itself. -/// additional id's (if any) specify which member of a union we should select -/// the maximal size of array is #MAXSTRUCPATH. -/// strpaths are used to determine how to display structure offsets. -//@{ -idaman void ida_export write_struc_path(ea_t ea, int idx, const tid_t *path, int plen, adiff_t delta); -idaman int ida_export read_struc_path(tid_t *path, adiff_t *delta, ea_t ea, int idx); // returns plen -//@} - -//@} - - -//-------------------------------------------------------------------------- -// type information (ti) storage -// up to 256 operands are supported for ti. - -typedef uchar type_t; -typedef uchar p_list; -class tinfo_t; - -/// \name Types -/// Work with function/data types -/// These functions may be used if necessary (despite of the AFLNOTE above). -//@{ -idaman bool ida_export get_tinfo(tinfo_t *tif, ea_t ea); -idaman bool ida_export set_tinfo(ea_t ea, const tinfo_t *tif); -inline void idaapi del_tinfo(ea_t ea) { set_tinfo(ea, NULL); } -//@} - -/// \name Operand types -/// These functions may be used if necessary (despite of the AFLNOTE above). -//@{ -idaman bool ida_export get_op_tinfo(tinfo_t *tif, ea_t ea, int n); -idaman bool ida_export set_op_tinfo(ea_t ea, int n, const tinfo_t *tif); -inline void idaapi del_op_tinfo(ea_t ea, int n) { set_op_tinfo(ea, n, NULL); } -//@} - -//------------------------------------------------------------------------// -/// \defgroup RIDX_ Rootnode indexes: -//@{ - -// supvals -#define RIDX_FILE_FORMAT_NAME 1 ///< file format name for loader modules -#define RIDX_SELECTORS 2 ///< 2..63 are for selector_t blob (see init_selectors()) -#define RIDX_GROUPS 64 ///< segment group information (see init_groups()) -#define RIDX_H_PATH 65 ///< C header path -#define RIDX_C_MACROS 66 ///< C predefined macros -#define RIDX_SMALL_IDC_OLD 67 ///< Instant IDC statements (obsolete) -#define RIDX_NOTEPAD 68 ///< notepad blob, occupies 1000 indexes (1MB of text) -#define RIDX_INCLUDE 1100 ///< assembler include file name -#define RIDX_SMALL_IDC 1200 ///< Instant IDC statements, blob -#define RIDX_DUALOP_GRAPH 1300 ///< Graph text representation options -#define RIDX_DUALOP_TEXT 1301 ///< Text text representation options -#define RIDX_MD5 1302 ///< MD5 of the input file -#define RIDX_IDA_VERSION 1303 ///< version of ida which created the database - -#define RIDX_STR_ENCODINGS 1305 ///< a list of encodings for the program strings -#define RIDX_SRCDBG_PATHS 1306 ///< source debug paths, occupies 20 indexes -#define RIDX_SELECTED_EXTLANG 1327 ///< last selected extlang name (from the execute script box) -#define RIDX_DBG_BINPATHS 1328 ///< unused (20 indexes) -#define RIDX_SHA256 1349 ///< SHA256 of the input file -#define RIDX_ABINAME 1350 ///< ABI name (processor specific) -#define RIDX_ARCHIVE_PATH 1351 ///< archive file path -#define RIDX_PROBLEMS 1352 ///< problem lists -#define RIDX_SRCDBG_UNDESIRED 1353 ///< user-closed source files, occupies 20 indexes - -// altvals -#define RIDX_ALT_VERSION uval_t(-1) ///< initial version of database -#define RIDX_ALT_CTIME uval_t(-2) ///< database creation timestamp -#define RIDX_ALT_ELAPSED uval_t(-3) ///< seconds database stayed open -#define RIDX_ALT_NOPENS uval_t(-4) ///< how many times the database is opened -#define RIDX_ALT_CRC32 uval_t(-5) ///< input file crc32 -#define RIDX_ALT_IMAGEBASE uval_t(-6) ///< image base -#define RIDX_ALT_IDSNODE uval_t(-7) ///< ids modnode id (for import_module) -#define RIDX_ALT_FSIZE uval_t(-8) ///< input file size -#define RIDX_ALT_OUTFILEENC uval_t(-9) ///< output file encoding index -//@} - -//--------------------------------------------------------------------------- -/// Get file name only of the input file -idaman ssize_t ida_export get_root_filename(char *buf, size_t bufsize); - -/// Get debugger input file name/path (see #LFLG_DBG_NOPATH) -idaman ssize_t ida_export dbg_get_input_path(char *buf, size_t bufsize); - -// The following functions should eventually be replaced by exported functions -#ifndef __KERNEL__ -/// Get full path of the input file -inline ssize_t idaapi get_input_file_path(char *buf, size_t bufsize) -{ - return root_node.valstr(buf, bufsize); -} - -/// Set full path of the input file -inline void set_root_filename(const char *file) { root_node.set(file); } - -/// Get size of input file in bytes -inline uint32 idaapi retrieve_input_file_size(void) { return uint32(root_node.altval(RIDX_ALT_FSIZE)); } - -/// Get input file crc32 stored in the database. -/// it can be used to check that the input file has not been changed. -inline uint32 idaapi retrieve_input_file_crc32(void) { return uint32(root_node.altval(RIDX_ALT_CRC32)); } - -/// Get input file md5 -inline bool idaapi retrieve_input_file_md5(uchar hash[16]) { return root_node.supval(RIDX_MD5, hash, 16) == 16; } - -/// Get input file sha256 -inline bool idaapi retrieve_input_file_sha256(uchar hash[32]) { return root_node.supval(RIDX_SHA256, hash, 32) == 32; } - -/// Get name of the include file -inline ssize_t idaapi get_asm_inc_file(qstring *buf) { return root_node.supstr(buf, RIDX_INCLUDE); } - -/// Set name of the include file -inline bool idaapi set_asm_inc_file(const char *file) { return root_node.supset(RIDX_INCLUDE, file); } - -/// Get image base address -inline ea_t idaapi get_imagebase(void) { return root_node.altval(RIDX_ALT_IMAGEBASE); } - -/// Set image base address -inline void idaapi set_imagebase(ea_t base) { root_node.altset(RIDX_ALT_IMAGEBASE, base); } - -/// Get ids modnode -inline netnode idaapi get_ids_modnode(void) { return root_node.altval(RIDX_ALT_IDSNODE); } - -/// Set ids modnode -inline void idaapi set_ids_modnode(netnode id) { root_node.altset(RIDX_ALT_IDSNODE, id); } - -/// Get archive file path from which input file was extracted -inline ssize_t idaapi get_archive_path(qstring *buf) { return root_node.supstr(buf, RIDX_ARCHIVE_PATH); } - -/// Set archive file path from which input file was extracted -inline bool idaapi set_archive_path(const char *file) { return root_node.supset(RIDX_ARCHIVE_PATH, file); } -#endif - -//--------------------------------------------------------------------------- -/// \name String encodings -/// Encoding names can be a codepage names (CP1251, windows-1251), -/// charset name (Shift-JIS, UTF-8), or just codepage number (866, 932). -/// user-accessible encodings are counted from 1 -/// (index 0 is reserved) -//@{ - -/// Get total number of encodings (counted from 0) - -idaman int ida_export get_encoding_qty(); - - -/// Get encoding name for specific index (1-based). -/// \return NULL if idx is out of bounds - -idaman const char *ida_export get_encoding_name(int idx); - - -/// Add a new encoding (e.g. "UTF-8"). -/// \return its index (1-based) -/// if it's already in the list, return its index - -idaman int ida_export add_encoding(const char *encoding); - - -/// Delete an encoding (1-based) - -idaman bool ida_export del_encoding(int idx); - - -/// Change name for an encoding (1-based) - -idaman bool ida_export rename_encoding(int idx, const char *encoding); - - -#define BPU_1B 1 -#define BPU_2B 2 -#define BPU_4B 4 - -/// Get the amount of bytes per unit (e.g., 2 for UTF-16, 4 for UTF-32) -/// for the encoding with the given index. -/// -/// \param idx the encoding index -/// \return the number of bytes per units (1/2/4); -1 means error - -idaman int ida_export get_encoding_bpu(int idx); - - -//------------------------------------------------------------------------- -inline int get_strtype_bpu(int32 strtype) -{ - int w = get_str_type_code(strtype) & STRWIDTH_MASK; - return w == STRWIDTH_2B ? BPU_2B : (w == STRWIDTH_4B ? BPU_4B : BPU_1B); -} - -/// Get default encoding index for a specific string type. -/// \param bpu the amount of bytes per unit (e.g., 1 for ASCII, CP1252, UTF-8..., 2 for UTF-16, 4 for UTF-32) -/// 0 means no specific encoding is set - byte values are displayed without conversion. - -idaman int ida_export get_default_encoding_idx(int bpu); - -/// set default encoding for a string type -/// \param bpu the amount of bytes per unit -/// \param idx the encoding index -/// idx can be 0 to disable encoding conversion - -idaman bool ida_export set_default_encoding_idx(int bpu, int idx); - - -/// Get encoding name for this strtype - -inline const char *idaapi encoding_from_strtype(int32 strtype) -{ - uchar enc = get_str_encoding_idx(strtype); - if ( enc == 0 ) - enc = get_default_encoding_idx(get_strtype_bpu(strtype)); - return get_encoding_name(enc); // will return NULL if enc is 0 -} - - -/// Get the index of the encoding used when producing files -/// 0 means no that the IDB's default 1 byte-per-unit encoding is used - -idaman int ida_export get_outfile_encoding_idx(); - - -/// set encoding to be used when producing files -/// \param idx the encoding index -/// idx can be 0 to use the IDB's default 1-byte-per-unit encoding - -idaman bool ida_export set_outfile_encoding_idx(int idx); - - -//@} - -//------------------------------------------------------------------------// -/// \name Functions to work with imports -//@{ - -/// Get number of import modules - -idaman uint ida_export get_import_module_qty(); - - -/// Get import module name. -/// \retval true ok -/// \retval false bad index - -idaman bool ida_export get_import_module_name(qstring *buf, int mod_index); - - -/// Callback for enumerating imports. -/// \param ea import address -/// \param name import name (NULL if imported by ordinal) -/// \param ord import ordinal (0 for imports by name) -/// \param param user parameter passed to enum_import_names() -/// \retval 1 ok -/// \retval 0 stop enumeration - -typedef int idaapi import_enum_cb_t(ea_t ea, const char *name, uval_t ord, void *param); - - -/// Enumerate imports from specific module. -/// \retval 1 finished ok -/// \retval -1 error -/// \retval other callback return value (<=0) - -idaman int ida_export enum_import_names(int mod_index, import_enum_cb_t *callback, void *param=NULL); - - -/// Delete all imported modules information - -idaman void ida_export delete_imports(void); -//@} - - -/// Check consistency of name records, return number of bad ones - -idaman int ida_export validate_idb_names2(bool do_repair); - -#ifndef SWIG - - -//-------------------------------------------------------------------------- -/// \name Ignore micro -/// netnode to keep information about various kinds of instructions -//@{ -extern netnode ignore_micro; - -#define IM_NONE 0 // regular instruction -#define IM_PROLOG 1 // prolog instruction -#define IM_EPILOG 2 // epilog instruction -#define IM_SWITCH 3 // switch instruction (the indirect jump should not be marked) - -inline void init_ignore_micro(void) { ignore_micro.create("$ ignore micro"); } -inline void term_ignore_micro(void) { ignore_micro = BADNODE; } -inline char get_ignore_micro(ea_t ea) { return ignore_micro.charval_ea(ea, 0); } -inline void set_ignore_micro(ea_t ea, uchar im_type) { ignore_micro.charset_ea(ea, im_type, 0); } -inline void clr_ignore_micro(ea_t ea) { ignore_micro.chardel_ea(ea, 0); } -inline ea_t next_marked_insn(ea_t ea) { return node2ea(ignore_micro.charnext(ea2node(ea), 0)); } -inline void mark_prolog_insn(ea_t ea) { set_ignore_micro(ea, IM_PROLOG); } -inline void mark_epilog_insn(ea_t ea) { set_ignore_micro(ea, IM_EPILOG); } -inline void mark_switch_insn(ea_t ea) { set_ignore_micro(ea, IM_SWITCH); } -inline bool is_prolog_insn(ea_t ea) { return get_ignore_micro(ea) == IM_PROLOG; } -inline bool is_epilog_insn(ea_t ea) { return get_ignore_micro(ea) == IM_EPILOG; } -inline bool is_switch_insn(ea_t ea) { return get_ignore_micro(ea) == IM_SWITCH; } -inline bool should_ignore_micro(ea_t ea) { return get_ignore_micro(ea) != IM_NONE; } -//@} -#endif // SWIG - -//-------------------------------------------------------------------------- -// Set address of .got section -inline void set_gotea(ea_t gotea) -{ - netnode n; - n.create("$ got"); - n.altset(0, ea2node(gotea)+1); -} - -//-------------------------------------------------------------------------- -// Get address of .got section -inline ea_t get_gotea(void) -{ - netnode n("$ got"); - return exist(n) ? node2ea(n.altval(0) - 1) : BADADDR; -} - - -#if !defined(NO_OBSOLETE_FUNCS) -idaman DEPRECATED int ida_export validate_idb_names(); // use validate_idb_names2 -#endif - -#ifndef BYTES_SOURCE // undefined bit masks so no one can use them directly -#undef AFL_LINNUM -#undef AFL_USERSP -#undef AFL_PUBNAM -#undef AFL_WEAKNAM -#undef AFL_HIDDEN -#undef AFL_MANUAL -#undef AFL_NOBRD -#undef AFL_ZSTROFF -#undef AFL_BNOT0 -#undef AFL_BNOT1 -#undef AFL_LIB -#undef AFL_TI -#undef AFL_TI0 -#undef AFL_TI1 -#undef AFL_LNAME -#undef AFL_TILCMT -#undef AFL_LZERO0 -#undef AFL_LZERO1 -#undef AFL_COLORED -#undef AFL_TERSESTR -#undef AFL_SIGN0 -#undef AFL_SIGN1 -#undef AFL_NORET -#undef AFL_FIXEDSPD -#undef NALT_ENUM -#undef NALT_WIDE -#undef NALT_SWITCH -//#undef NALT_STRUCT -#undef NALT_XREFPOS -#undef NALT_AFLAGS -#undef NALT_LINNUM -#undef NALT_ABSBASE -//#undef NALT_ENUM0 -//#undef NALT_ENUM1 -#undef NALT_PURGE -#undef NALT_STRTYPE -#undef NALT_ALIGN -#undef NALT_COLOR -#undef NSUP_CMT -#undef NSUP_REPCMT -#undef NSUP_FOP1 -#undef NSUP_FOP2 -#undef NSUP_JINFO -#undef NSUP_ARRAY -#undef NSUP_OMFGRP -#undef NSUP_FOP3 -#undef NSUP_SWITCH -#undef NSUP_REF0 -#undef NSUP_REF1 -#undef NSUP_REF2 -#undef NSUP_OREF0 -#undef NSUP_OREF1 -#undef NSUP_OREF2 -#undef NSUP_STROFF0 -#undef NSUP_STROFF1 -#undef NSUP_SEGTRANS -#undef NSUP_FOP4 -#undef NSUP_FOP5 -#undef NSUP_FOP6 -#undef NSUP_FOP7 -#undef NSUP_FOP8 -#undef NSUP_REF3 -#undef NSUP_REF4 -#undef NSUP_REF5 -#undef NSUP_REF6 -#undef NSUP_REF7 -#undef NSUP_OREF3 -#undef NSUP_OREF4 -#undef NSUP_OREF5 -#undef NSUP_OREF6 -#undef NSUP_OREF7 -#undef NSUP_MANUAL -#undef NSUP_FTAILS -#undef NSUP_GROUP -#endif - -#endif // NALT_HPP diff --git a/idasdk75/include/name.hpp b/idasdk75/include/name.hpp deleted file mode 100644 index 95d5ea6..0000000 --- a/idasdk75/include/name.hpp +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _NAME_HPP -#define _NAME_HPP - -#include <ida.hpp> - -/*! \file name.hpp - - \brief Functions that deal with names. - - A non-tail address of the program may have a name. - Tail addresses (i.e. the addresses in the middle of an instruction or - data item) cannot have names. -*/ - -class func_t; // funcs.hpp -typedef uchar color_t; // lines.hpp - -/// Maximum length of a name in IDA (with the trailing zero) -#define MAXNAMELEN 512 - - -/// Name prefix used by IDA for the imported functions -#define FUNC_IMPORT_PREFIX "__imp_" - - -/// Set or delete name of an item at the specified address. -/// An item can be anything: instruction, function, data byte, word, string, -/// structure, etc... -/// Include name into the list of names. -/// \param ea linear address. -/// do nothing if ea is not valid (return 0). -/// tail bytes can't have names. -/// \param name new name. -/// - NULL: do nothing (return 0). -/// - "" : delete name. -/// - otherwise this is a new name. -/// \param flags \ref SN_. -/// If a bit is not specified, then the corresponding action is not performed -/// and the name will retain the same bits as before calling this function. -/// For new names, default is: non-public, non-weak, non-auto. -/// \retval 1 ok, name is changed -/// \retval 0 failure, a warning is displayed - -idaman bool ida_export set_name(ea_t ea, const char *name, int flags=0); - -/// \defgroup SN_ Set name flags -/// Passed as 'flag' parameter to set_name(ea_t, const char *, int) -//@{ -#define SN_CHECK 0x00 -#define SN_NOCHECK 0x01 ///< Don't fail if the name contains invalid characters. - ///< If this bit is clear, all invalid chars - ///< (those !is_ident_cp()) will be replaced - ///< by SUBSTCHAR - ///< List of valid characters is defined in ida.cfg -#define SN_PUBLIC 0x02 ///< if set, make name public -#define SN_NON_PUBLIC 0x04 ///< if set, make name non-public -#define SN_WEAK 0x08 ///< if set, make name weak -#define SN_NON_WEAK 0x10 ///< if set, make name non-weak -#define SN_AUTO 0x20 ///< if set, make name autogenerated -#define SN_NON_AUTO 0x40 ///< if set, make name non-autogenerated -#define SN_NOLIST 0x80 ///< if set, exclude name from the list. - ///< if not set, then include the name into - ///< the list (however, if other bits are set, - ///< the name might be immediately excluded - ///< from the list). -#define SN_NOWARN 0x100 ///< don't display a warning if failed -#define SN_LOCAL 0x200 ///< create local name. a function should exist. - ///< local names can't be public or weak. - ///< also they are not included into the list of names - ///< they can't have dummy prefixes. -#define SN_IDBENC 0x400 ///< the name is given in the IDB encoding; - ///< non-ASCII bytes will be decoded accordingly. - ///< Specifying SN_IDBENC also implies SN_NODUMMY -#define SN_FORCE 0x800 ///< if the specified name is already present - ///< in the database, try variations with a - ///< numerical suffix like "_123" -#define SN_NODUMMY 0x1000 ///< automatically prepend the name with '_' if it - ///< begins with a dummy suffix such as 'sub_'. - ///< See also SN_IDBENC -#define SN_DELTAIL 0x2000 ///< if name cannot be set because of a tail byte, - ///< delete the hindering item -//@} - -inline bool force_name(ea_t ea, const char *name, int flags=0) -{ - return set_name(ea, name, flags|SN_FORCE|SN_NODUMMY); -} - -/// \name Delete a name of a program item -/// \param ea linear address -/// \retval 1 ok, name is deleted -/// \retval 0 failure, invalid address -//@{ -inline bool del_global_name(ea_t ea) { return set_name(ea,"", SN_NOWARN); } -inline bool del_local_name(ea_t ea) { return set_name(ea,"", SN_LOCAL|SN_NOWARN); } -//@} - -/// Give an autogenerated (dummy) name. -/// Autogenerated names have special prefixes (loc_...). -/// \param from linear address of the operand which references to the address -/// \param ea linear address -/// \retval 1 ok, dummy name is generated or the byte already had a name -/// \retval 0 failure, invalid address or tail byte - -idaman bool ida_export set_dummy_name(ea_t from, ea_t ea); // give dummy name - - -/// \name Set/Clear bit in flags for 'autogenerated but meaningful name' -/// This bit affects value of has_user_name(), has_auto_name() functions. -/// \param ea linear address -/// \retval 1 ok -/// \retval 0 no meaningful name is present at the specified address -//@{ -idaman bool ida_export make_name_auto(ea_t ea); -idaman bool ida_export make_name_user(ea_t ea); -//@} - - -enum ucdr_kind_t -{ - UCDR_STRLIT = 0x01, // string literals - UCDR_NAME = 0x02, // regular (unmangled) names - UCDR_MANGLED = 0x04, // mangled names - UCDR_TYPE = 0x08, // type names -}; - -enum nametype_t -{ - // identifier (e.g., function name) - VNT_IDENT = UCDR_NAME|UCDR_MANGLED, - // type name (can contain '<', '>', ...) - VNT_TYPE = UCDR_TYPE, - // UDT (structure, union, enum) member - VNT_UDTMEM = UCDR_NAME, - // string literal - VNT_STRLIT = UCDR_STRLIT, - VNT_VISIBLE = VNT_UDTMEM,// visible cp (obsolete; will be deleted) -}; - -/// Validate a name. -/// This function replaces all invalid characters in the name with SUBSTCHAR. -/// However, it will return false if name is valid but not allowed to be an -/// identifier (is a register name). -/// -/// \param[in,out] name ptr to name. the name will be modified -/// \param type the type of name we want to validate -/// \param flags see SN_* . Only SN_IDBENC is currently considered -/// -/// \return success - -idaman bool ida_export validate_name( - qstring *name, - nametype_t type, - int flags = 0); - - -/// Is the given codepoint acceptable in the given context? - -idaman bool ida_export is_valid_cp(wchar32_t cp, nametype_t kind, void *data=NULL); - - -/// Mark the given codepoint (or range) as acceptable or unacceptable in the given context -/// If 'endcp' is not BADCP, it is considered to be the end of the range: -/// [cp, endcp), and is not included in the range - -idaman void ida_export set_cp_validity(ucdr_kind_t kind, wchar32_t cp, wchar32_t endcp=BADCP, bool valid=true); - - -/// Is the given codepoint (or range) acceptable in the given context? -/// If 'endcp' is not BADCP, it is considered to be the end of the range: -/// [cp, endcp), and is not included in the range - -idaman bool ida_export get_cp_validity(ucdr_kind_t kind, wchar32_t cp, wchar32_t endcp=BADCP); - - -/// Can a character appear in a name? (present in ::NameChars or ::MangleChars) - -inline bool is_ident_cp(wchar32_t cp) { return is_valid_cp(cp, VNT_IDENT); } - - -/// Can a character appear in a string literal (present in ::StrlitChars) -/// If 'specific_ranges' are specified, those will be used instead of -/// the ones corresponding to the current culture (only if ::StrlitChars -/// is configured to use the current culture) - -inline bool is_strlit_cp(wchar32_t cp, const rangeset_crefvec_t *specific_ranges=NULL) -{ return is_valid_cp(cp, VNT_STRLIT, (void *) specific_ranges); } - - -/// Can a character be displayed in a name? (present in ::NameChars) - -inline bool is_visible_cp(wchar32_t cp) -{ return is_valid_cp(cp, VNT_VISIBLE); } - - -/// Is a valid name? (including ::MangleChars) - -idaman bool ida_export is_ident(const char *name); - - -/// Is valid user-specified name? (valid name & !dummy prefix). -/// \param name name to test. may be NULL. -/// \retval 1 yes -/// \retval 0 no - -idaman bool ida_export is_uname(const char *name); - - -/// Is valid type name? -/// \param name name to test. may be NULL. -/// \retval 1 yes -/// \retval 0 no - -idaman bool ida_export is_valid_typename(const char *name); - - -/// Is dummy name? -/// \param name name to test. may be NULL. -/// \return #BADADDR if not, otherwise the address denoted by the name - -idaman ea_t ida_export dummy_name_ea(const char *name); - - -/// Extract a name or address from the specified string. -/// \param[out] out output buffer for the identifier -/// \param line input string -/// \param x x coordinate of cursor -/// \return -1 if cannot extract. otherwise length of the name - -idaman ssize_t ida_export extract_name(qstring *out, const char *line, int x); - - -/// Remove name from the list of names -/// \param ea address of the name - -idaman void ida_export hide_name(ea_t ea); - - -/// Insert name to the list of names - -idaman void ida_export show_name(ea_t ea); - - -/// Get address of the name. -/// Dummy names (like byte_xxxx where xxxx are hex digits) are parsed by this -/// function to obtain the address. The database is not consulted for them. -/// This function works only with regular names. -/// \param from linear address where the name is used. -/// if not applicable, then should be #BADADDR. -/// \param name any name in the program or NULL -/// \return address of the name or #BADADDR - -idaman ea_t ida_export get_name_ea(ea_t from, const char *name); - - -/// Get address of the name used in the expression for the address -/// \param from address of the operand which references to the address -/// \param to the referenced address -/// \return address of the name used to represent the operand - -idaman ea_t ida_export get_name_base_ea(ea_t from, ea_t to); - - -/// Get value of the name. -/// This function knows about: regular names, enums, special segments, etc. -/// \param[out] value pointer to variable with answer -/// \param from linear address where the name is used -/// if not applicable, then should be BADADDR -/// \param name any name in the program or NULL -/// \return \ref NT_ - -idaman int ida_export get_name_value(uval_t *value, ea_t from, const char *name); - -/// \defgroup NT_ Name value result codes -/// Return values for get_name_value() -//@{ -#define NT_NONE 0 ///< name doesn't exist or has no value -#define NT_BYTE 1 ///< name is byte name (regular name) -#define NT_LOCAL 2 ///< name is local label -#define NT_STKVAR 3 ///< name is stack variable name -#define NT_ENUM 4 ///< name is symbolic constant -#define NT_ABS 5 ///< name is absolute symbol (#SEG_ABSSYM) -#define NT_SEG 6 ///< name is segment or segment register name -#define NT_STROFF 7 ///< name is structure member -#define NT_BMASK 8 ///< name is a bit group mask name -#define NT_REGVAR 9 ///< name is a renamed register (*value is idx into pfn->regvars) -//@} - - -/// Additional information for get_ea_name() function -struct getname_info_t -{ - size_t cb; ///< size of this struct - int32 inhibitor; ///< codes to inhibit parts of demangled name (see \ref MNG_). - ///< Usually this is one of \inf{short_demnames} or \inf{long_demnames}. - int32 demform; ///< demangle only if \inf{demnames} is equal to 'demform'. - int32 demcode; ///< out: return value of demangler - getname_info_t(void) : cb(sizeof(*this)), inhibitor(0), demform(0), demcode(0) {} -}; - - -/// Get name at the specified address. -/// \param[out] out buffer to hold the name -/// \param ea linear address -/// \param gtn_flags how exactly the name should be retrieved. -/// combination of \ref GN_ bits -/// \param gtni additional information for name demangling -/// Please use the convenience functions declared below instead of calling -/// get_ea_name directly. -/// \return success - -idaman ssize_t ida_export get_ea_name( - qstring *out, - ea_t ea, - int gtn_flags=0, - getname_info_t *gtni=NULL); - -/// \defgroup GN_ bits for get_ea_name() function. There is a convenience -/// function calc_gtn_flags() to calculate the GN_LOCAL flag -//@{ -#define GN_VISIBLE 0x0001 ///< replace forbidden characters by SUBSTCHAR -#define GN_COLORED 0x0002 ///< return colored name -#define GN_DEMANGLED 0x0004 ///< return demangled name -#define GN_STRICT 0x0008 ///< fail if cannot demangle -#define GN_SHORT 0x0010 ///< use short form of demangled name -#define GN_LONG 0x0020 ///< use long form of demangled name -#define GN_LOCAL 0x0040 ///< try to get local name first; if failed, get global -#define GN_ISRET 0x0080 ///< for dummy names: use retloc -#define GN_NOT_ISRET 0x0100 ///< for dummy names: do not use retloc -#define GN_NOT_DUMMY 0x0200 ///< do not return a dummy name - -//@} - -// Convenience functions for get_ea_name returning ssize_t - -inline ssize_t get_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, gtn_flags); -} - -inline ssize_t idaapi get_visible_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, GN_VISIBLE|gtn_flags); -} - -inline ssize_t idaapi get_colored_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, GN_VISIBLE|GN_COLORED|gtn_flags); -} - -inline ssize_t idaapi get_short_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, GN_VISIBLE|GN_DEMANGLED|GN_SHORT|gtn_flags); -} - -inline ssize_t idaapi get_long_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, GN_VISIBLE|GN_DEMANGLED|GN_LONG|gtn_flags); -} - -inline ssize_t idaapi get_colored_short_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_SHORT|gtn_flags); -} - -inline ssize_t idaapi get_colored_long_name(qstring *out, ea_t ea, int gtn_flags=0) -{ - return get_ea_name(out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_LONG|gtn_flags); -} - -inline ssize_t idaapi get_demangled_name( - qstring *out, - ea_t ea, - int32 inhibitor, - int demform, - int gtn_flags=0) -{ - getname_info_t gtni; - gtni.inhibitor = inhibitor; - gtni.demform = demform; - gtn_flags |= GN_VISIBLE | GN_DEMANGLED; - return get_ea_name(out, ea, gtn_flags, >ni); -} - -inline ssize_t idaapi get_colored_demangled_name( - qstring *out, - ea_t ea, - int32 inhibitor, - int demform, - int gtn_flags=0) -{ - return get_demangled_name(out, ea, inhibitor, demform, gtn_flags|GN_COLORED); -} - -// Convenience functions for get_ea_name returning qstring - -inline qstring get_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, gtn_flags); - return out; -} - -inline qstring get_visible_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, GN_VISIBLE|gtn_flags); - return out; -} - -inline qstring idaapi get_colored_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, GN_VISIBLE|GN_COLORED|gtn_flags); - return out; -} - -inline qstring idaapi get_short_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, GN_VISIBLE|GN_DEMANGLED|GN_SHORT|gtn_flags); - return out; -} - -inline qstring idaapi get_long_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, GN_VISIBLE|GN_DEMANGLED|GN_LONG|gtn_flags); - return out; -} - -inline qstring idaapi get_colored_short_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_SHORT|gtn_flags); - return out; -} - -inline qstring idaapi get_colored_long_name(ea_t ea, int gtn_flags=0) -{ - qstring out; - get_ea_name(&out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_LONG|gtn_flags); - return out; -} - -inline qstring idaapi get_demangled_name( - ea_t ea, - int32 inhibitor, - int demform, - int gtn_flags=0) -{ - qstring out; - getname_info_t gtni; - gtni.inhibitor = inhibitor; - gtni.demform = demform; - gtn_flags |= GN_VISIBLE | GN_DEMANGLED; - get_ea_name(&out, ea, gtn_flags, >ni); - return out; -} - -inline qstring idaapi get_colored_demangled_name( - ea_t ea, - int32 inhibitor, - int demform, - int gtn_flags=0) -{ - qstring out; - get_demangled_name(&out, ea, inhibitor, demform, gtn_flags|GN_COLORED); - return out; -} - -/// Calculate flags for get_ea_name() function -#ifdef FUNCS_HPP -inline int calc_gtn_flags(ea_t from, ea_t ea) -{ - return func_contains(get_func(from), ea) ? GN_LOCAL : 0; -} -#endif - -/// Get name color. -/// \param from linear address where the name is used. -/// if not applicable, then should be #BADADDR. -/// The kernel returns a local name color if the reference is -/// within a function, i.e. 'from' and 'ea' belong to the same function. -/// \param ea linear address - -idaman color_t ida_export get_name_color(ea_t from, ea_t ea); - - -/// \defgroup GETN_ Name expression flags -/// Passed as 'flags' parameter to get_name_expr() -//@{ -#define GETN_APPZERO 0x0001 ///< meaningful only if the name refers to a structure. - ///< append a struct field name if the field offset is zero? -#define GETN_NOFIXUP 0x0002 ///< ignore the fixup information when producing the name -#define GETN_NODUMMY 0x0004 ///< do not create a new dummy name but pretend it exists -//@} - -/// Convert address to name expression (name with a displacement). -/// This function takes into account fixup information and returns -/// a colored name expression (in the form <name> +/- <offset>). -/// It also knows about structure members and arrays. -/// If the specified address doesn't have a name, a dummy name is generated. -/// \param[out] out output buffer for the name -/// \param from linear address of instruction operand or data referring to -/// the name. This address will be used to get fixup information, -/// so it should point to exact position of the operand in the -/// instruction. -/// \param n number of referencing operand. for data items specify 0 -/// \param ea address to convert to name expression -/// \param off the value of name expression. this parameter is used only to -/// check that the name expression will have the wanted value. -/// 'off' may be equal to BADADDR but this is discouraged -/// because it prohibits checks. -/// \param flags \ref GETN_ -/// \return < 0 if address is not valid, no segment or other failure. -/// otherwise the length of the name expression in characters. - -idaman ssize_t ida_export get_name_expr( - qstring *out, - ea_t from, - int n, - ea_t ea, - uval_t off, - int flags=GETN_APPZERO); - -/// Get a nice colored name at the specified address. -/// Ex: -/// - segment:sub+offset -/// - segment:sub:local_label -/// - segment:label -/// - segment:address -/// - segment:address+offset -/// \param[out] buf buffer to hold the name -/// \param ea linear address -/// \param flags \ref GNCN_ -/// \return the length of the generated name in bytes. - -idaman ssize_t ida_export get_nice_colored_name( - qstring *buf, - ea_t ea, - int flags=0); - -/// \defgroup GNCN_ Nice colored name flags -/// Passed as 'flags' parameter to get_nice_colored_name() -//@{ -#define GNCN_NOSEG 0x0001 ///< ignore the segment prefix when producing the name -#define GNCN_NOCOLOR 0x0002 ///< generate an uncolored name -#define GNCN_NOLABEL 0x0004 ///< don't generate labels -#define GNCN_NOFUNC 0x0008 ///< don't generate funcname+... expressions -#define GNCN_SEG_FUNC 0x0010 ///< generate both segment and function names (default is to omit segment name if a function name is present) -#define GNCN_SEGNUM 0x0020 ///< segment part is displayed as a hex number -#define GNCN_REQFUNC 0x0040 ///< return 0 if the address does not belong to a function -#define GNCN_REQNAME 0x0080 ///< return 0 if the address can only be represented as a hex number -#define GNCN_NODBGNM 0x0100 ///< don't use debug names -#define GNCN_PREFDBG 0x0200 ///< if using debug names, prefer debug names over function names -//@} - - -/// Append names of struct fields to a name if the name is a struct name. -/// \param out pointer to the output buffer -/// \param disp displacement from the name -/// \param n number of operand n which the name appears -/// \param path path in the struct. path is an array of id's. -/// maximal length of array is #MAXSTRUCPATH. -/// the first element of the array is the structure id. -/// consecutive elements are id's of used union members (if any). -/// \param plen size of path array -/// \param flags the input flags. they will be returned if the struct -/// cannot be found. -/// \param delta delta to add to displacement -/// \param appzero should append a struct field name if the displacement is zero? -/// \return flags of the innermost struct member or the input flags - -idaman flags_t ida_export append_struct_fields( - qstring *out, - adiff_t *disp, - int n, - const tid_t *path, - int plen, - flags_t flags, - adiff_t delta, - bool appzero); - - -/// Get offset within a structure if the operand refers to structure. -/// Ex: -/// \v{mov ax, somedata.field5-2 (before it was max ax, 3)} -/// for this instruction, op #1 the function will return -/// - disp: the value of 'field5', i.e. 5 -/// - delta: -2 -/// - path: the existing path if any -/// \param disp pointer to displacement (answer will be here) -/// \param delta pointer to displacement delta (answer will be here) -/// \param path existing strpath (if any) -/// \param ea linear address of instruction/data -/// \param n number of operand -/// \return if success, then length of path + 1. -/// if failed, then 0. - -idaman int ida_export get_struct_operand( - adiff_t *disp, - adiff_t *delta, - tid_t *path, - ea_t ea, - int n); - - -/// \name Work with publicness of a name -//@{ -idaman bool ida_export is_public_name(ea_t ea); -idaman void ida_export make_name_public(ea_t ea); -idaman void ida_export make_name_non_public(ea_t ea); -//@} - - -/// \name Work with weak names. -//@{ -idaman bool ida_export is_weak_name(ea_t ea); -idaman void ida_export make_name_weak(ea_t ea); -idaman void ida_export make_name_non_weak(ea_t ea); -//@} - -/// \name Work with the list of names -//@{ - -/// Get number of names in the list - -idaman size_t ida_export get_nlist_size(void); - -/// Get index of the name in the list -/// \warning returns the closest match. -/// may return idx >= size. - -idaman size_t ida_export get_nlist_idx(ea_t ea); - -/// Is name included into names list? - -idaman bool ida_export is_in_nlist(ea_t ea); - -/// Get address from the list at 'idx' - -idaman ea_t ida_export get_nlist_ea(size_t idx); - -/// Get name using idx - -idaman const char *ida_export get_nlist_name(size_t idx); - -/// Rebuild names list - -idaman void ida_export rebuild_nlist(void); -//@} - -/// Renumber dummy names - -idaman void ida_export reorder_dummy_names(void); - -/// Specify strategy for retrieving debug names -enum debug_name_how_t -{ - DEBNAME_EXACT, ///< find a name at exactly the specified address - DEBNAME_LOWER, ///< find a name with the address >= the specified address - DEBNAME_UPPER, ///< find a name with the address > the specified address - DEBNAME_NICE, ///< find a name with the address <= the specified address -}; - -/// ea, name pair -struct ea_name_t -{ - ea_t ea; - qstring name; - ea_name_t(void) : ea(BADADDR) {} - ea_name_t(ea_t _ea, const qstring &_name) : ea(_ea), name(_name) {} -}; -DECLARE_TYPE_AS_MOVABLE(ea_name_t); -typedef qvector<ea_name_t> ea_name_vec_t; ///< vector of ea,name pairs - -/// \name Debug names -/// Debug names exist during the debugging session. -/// The kernel does not verify them for anything and happily accepts -/// any string as a name. -//@{ -idaman int ida_export set_debug_names(const ea_t *addrs, const char *const *names, int qty); -idaman bool ida_export set_debug_name(ea_t ea, const char *name); -idaman ssize_t ida_export get_debug_name( - qstring *out, - ea_t *ea_ptr, - debug_name_how_t how); -idaman void ida_export del_debug_names(ea_t ea1, ea_t ea2); -idaman ea_t ida_export get_debug_name_ea(const char *name); -idaman void ida_export get_debug_names(ea_name_vec_t *names, ea_t ea1, ea_t ea2); -//@} - - -enum demreq_type_t -{ - DQT_NPURGED_8 = -8, // only calculate number of purged bytes (sizeof(arg)==8) - DQT_NPURGED_4 = -4, // only calculate number of purged bytes (sizeof(arg)==4) - DQT_NPURGED_2 = -2, // only calculate number of purged bytes (sizeof(arg)==2) - DQT_COMPILER = 0, // only detect compiler that generated the name - DQT_NAME_TYPE = 1, // only detect the name type (data/code) - DQT_FULL = 2, // really demangle -}; - -/// Demangle a name. -/// \param out output buffer -/// \param name name to demangle -/// \param disable_mask bits to inhibit parts of demangled name (see \ref MNG_). -/// by the M_COMPILER bits a specific compiler can be -/// selected (see \ref MT_). -/// \return ME_... or MT__ bitmasks from demangle.hpp - -idaman int32 ida_export demangle_name( - qstring *out, - const char *name, - uint32 disable_mask, - demreq_type_t demreq=DQT_FULL); - -/// Demangle a name. -inline qstring idaapi demangle_name( - const char *name, - uint32 disable_mask, - demreq_type_t demreq=DQT_FULL) -{ - qstring out; - demangle_name(&out, name, disable_mask, demreq); - return out; -} - - -inline int32 detect_compiler_using_demangler(const char *name) -{ - return demangle_name(NULL, name, 0, DQT_COMPILER); -} - -/// What name types to ignore -typedef int ignore_name_def_t; -const ignore_name_def_t - ignore_none = 0, - ignore_regvar = 1, - ignore_llabel = 2, - ignore_stkvar = 3, - ignore_glabel = 4; - -/// Is the name defined locally in the specified function? -/// \param pfn pointer to function -/// \param name name to check -/// \param ignore_name_def which names to ignore when checking -/// \param ea1 the starting address of the range inside the function (optional) -/// \param ea2 the ending address of the range inside the function (optional) -/// \return true if the name has been defined -idaman bool ida_export is_name_defined_locally( - func_t *pfn, - const char *name, - ignore_name_def_t ignore_name_def, - ea_t ea1=BADADDR, - ea_t ea2=BADADDR); - -// Clean a name. -// This function removes punctuation marks (underscores and dots) from both -// ends of the name, and other typical prefixes/suffixes. Name is assumed to -// have the following format: [j_][@][.][_*][imp_]name[@digits][_NN] -// \param out output buffer -// \param ea address of the name (used to remove the module name) -// if != BADADDR, the optional prefix (module name) will be -// removed -// \param name name to clean -// \param flags combination of CN_... bits -// \return true if returned a non-empty name -idaman bool ida_export cleanup_name( - qstring *out, - ea_t ea, - const char *name, - uint32 flags=0); - -#define CN_KEEP_TRAILING__DIGITS 0x01 // do not remove "_\d+" at the end of name - - -#endif // _NAME_HPP diff --git a/idasdk75/include/netnode.hpp b/idasdk75/include/netnode.hpp deleted file mode 100644 index 605936b..0000000 --- a/idasdk75/include/netnode.hpp +++ /dev/null @@ -1,1120 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _NETNODE_HPP -#define _NETNODE_HPP - -/*! \file netnode.hpp - - \brief Functions that provide the lowest level public interface to the database. - - (Namely, Btree). To learn more about Balanced Trees: - http://www.bluerwhite.org/btree/ - - We don't use Btree directly. - Instead, we have another layer built on the top of Btree. - Here is a brief explanation of this layer. - - An object called "netnode" is modeled on the top of Btree. - Each netnode has a unique id: a 32-bit value (64-bit for ida64). - Usually there is a trivial mapping of the linear addresses used in - the program to netnodes. If we have additional information about - an address (a comment is attached to it, for example), this - information is stored in the corresponding netnode. - See nalt.hpp to see how the kernel uses netnodes. - Also, some netnodes have no corresponding linear address (however, they still - have an id). They are used to store information not related to a particular - address. - - Each netnode _may_ have the following attributes: - - - a name: an arbitrary non-empty string, up to 255KB-1 bytes - - - a value: arbitrary sized object, max size is MAXSPECSIZE - - - altvals: a sparse array of 32-bit values. - indexes in this array may be 8-bit or 32-bit values - - - supvals: an array of arbitrary sized objects. (size of each - object is limited by MAXSPECSIZE) - indexes in this array may be 8-bit or 32-bit values - - - charvals: a sparse array of 8-bit values. - indexes in this array may be 8-bit or 32-bit values - - - hashvals: a hash (an associative array). - indexes in this array are strings - values are arbitrary sized (max size is MAXSPECSIZE) - - Initially a new netnode contains no information at all so no disk space - is used for it. As you add new information, the netnode grows. - - All arrays that are attached to the netnode behave in the same manner. - Initially: - - all members of altvals/charvals array are zeroes - - all members of supvals/hashvals array are undefined - - If you need to store objects bigger that MAXSPECSIZE, please note that - there are high-level functions to store arbitrary sized objects in supvals. - See setblog/getblob and other blob-related functions. - - You may use netnodes to store additional information about the program. - Limitations on the use of netnodes are the following: - - - use netnodes only if you could not find a kernel service to - store your type of information - - - do not create netnodes with valid identifier names. - Use the "$ " prefix (or any other prefix with characters not allowed - in the identifiers for the names of your netnodes. - Although you will probably not destroy anything by - accident, using already defined names for the names of your - netnodes is still discouraged. - - - you may create as many netnodes as you want (creation of an unnamed - netnode does not increase the size of the database). - however, since each netnode has a number, creating too many netnodes - could lead to the exhaustion of the netnode numbers (the numbering - starts at 0xFF000000) - - - remember that netnodes are automatically saved to the disk - by the kernel. - - Advanced info: - - In fact a netnode may contain up to 256 arrays of arbitrary sized - objects (not only the 4 listed above). Each array has an 8-bit tag. - Usually tags are represented by character constants. For example, altvals - and supvals are simply 2 of 256 arrays, with the tags 'A' and 'S' respectively. - -*/ - -#include <range.hpp> - -//-------------------------------------------------------------------------- -/// Maximum length of a netnode name. WILL BE REMOVED IN THE FUTURE -const int MAXNAMESIZE = 512; - -/// Maximum length of a name. We permit names up to 32KB-1 bytes. -const int MAX_NODENAME_SIZE = 32*1024; - -/// Maximum length of strings or objects stored in a supval array element -const int MAXSPECSIZE = 1024; - -/// \typedef{nodeidx_t, numbers are 64 bit for 64 bit IDA} -#ifdef __EA64__ -typedef uint64 nodeidx_t; -#else -typedef uint32 nodeidx_t; -#endif - -/// A number to represent a bad netnode reference -#define BADNODE nodeidx_t(-1) - -/// \defgroup nn_res Reserved netnode tags -/// Tags internally used in netnodes. You should not use them -/// for your tagged alt/sup/char/hash arrays. -//@{ -const uchar atag = 'A'; ///< Array of altvals -const uchar stag = 'S'; ///< Array of supvals -const uchar htag = 'H'; ///< Array of hashvals -const uchar vtag = 'V'; ///< Value of netnode -const uchar ntag = 'N'; ///< Name of netnode -const uchar ltag = 'L'; ///< Links between netnodes -//@} - -// Internal bit used to request ea2node() mapping of alt and sup indexes -const int NETMAP_IDX = 0x100; -// Internal bit used to request ea2node() mapping of alt values. -// Such values are stored after being incremented by one. -const int NETMAP_VAL = 0x200; -// Internal bit used to make sure a string obtained with getblob() is -// null-terminated. -const int NETMAP_STR = 0x400; -// Internal bit: use 8-bit indexes. -const int NETMAP_X8 = 0x800; -// Internal bit: use 8-bit values. -const int NETMAP_V8 = 0x1000; - -/// visitor to be used by altadjust2 to skip the adjustment of some altvals -struct altadjust_visitor_t -{ - virtual bool should_skip(nodeidx_t ea) = 0; -}; - -/// \name Helper functions -/// They should not be called directly! See ::netnode -//@{ -class netnode; -class linput_t; -idaman bool ida_export netnode_check(netnode *, const char *name, size_t namlen, bool create); -idaman void ida_export netnode_kill(netnode *); -idaman bool ida_export netnode_start(netnode *); -idaman bool ida_export netnode_end(netnode *); -idaman bool ida_export netnode_next(netnode *); -idaman bool ida_export netnode_prev(netnode *); -idaman ssize_t ida_export netnode_get_name(nodeidx_t num, qstring *out); -idaman bool ida_export netnode_rename(nodeidx_t num, const char *newname, size_t namlen); -idaman ssize_t ida_export netnode_valobj(nodeidx_t num, void *buf, size_t bufsize); -idaman ssize_t ida_export netnode_valstr(nodeidx_t num, char *buf, size_t bufsize); -idaman ssize_t ida_export netnode_qvalstr(nodeidx_t num, qstring *buf); -idaman bool ida_export netnode_set(nodeidx_t num, const void *value, size_t length); -idaman bool ida_export netnode_delvalue(nodeidx_t num); -idaman nodeidx_t ida_export netnode_altval(nodeidx_t num, nodeidx_t alt, int tag); -idaman uchar ida_export netnode_charval(nodeidx_t num, nodeidx_t alt, int tag); -idaman nodeidx_t ida_export netnode_altval_idx8(nodeidx_t num, uchar alt, int tag); -idaman uchar ida_export netnode_charval_idx8(nodeidx_t num, uchar alt, int tag); -idaman ssize_t ida_export netnode_supval(nodeidx_t num, nodeidx_t alt, void *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_supstr(nodeidx_t num, nodeidx_t alt, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qsupstr(nodeidx_t num, qstring *buf, nodeidx_t alt, int tag); -idaman bool ida_export netnode_supset(nodeidx_t num, nodeidx_t alt, const void *value, size_t length, int tag); -idaman bool ida_export netnode_supdel(nodeidx_t num, nodeidx_t alt, int tag); -idaman nodeidx_t ida_export netnode_lower_bound(nodeidx_t num, nodeidx_t cur, int tag); -idaman nodeidx_t ida_export netnode_supfirst(nodeidx_t num, int tag); -idaman nodeidx_t ida_export netnode_supnext(nodeidx_t num, nodeidx_t cur, int tag); -idaman nodeidx_t ida_export netnode_suplast(nodeidx_t num, int tag); -idaman nodeidx_t ida_export netnode_supprev(nodeidx_t num, nodeidx_t cur, int tag); -idaman ssize_t ida_export netnode_supval_idx8(nodeidx_t num, uchar alt, void *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_supstr_idx8(nodeidx_t num, uchar alt, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qsupstr_idx8(nodeidx_t num, qstring *buf, uchar alt, int tag); -idaman bool ida_export netnode_supset_idx8(nodeidx_t num, uchar alt, const void *value, size_t length, int tag); -idaman bool ida_export netnode_supdel_idx8(nodeidx_t num, uchar alt, int tag); -idaman nodeidx_t ida_export netnode_lower_bound_idx8(nodeidx_t num, uchar alt, int tag); -idaman nodeidx_t ida_export netnode_supfirst_idx8(nodeidx_t num, int tag); -idaman nodeidx_t ida_export netnode_supnext_idx8(nodeidx_t num, uchar alt, int tag); -idaman nodeidx_t ida_export netnode_suplast_idx8(nodeidx_t num, int tag); -idaman nodeidx_t ida_export netnode_supprev_idx8(nodeidx_t num, uchar alt, int tag); -idaman bool ida_export netnode_supdel_all(nodeidx_t num, int tag); -idaman int ida_export netnode_supdel_range(nodeidx_t num, nodeidx_t idx1, nodeidx_t idx2, int tag); -idaman int ida_export netnode_supdel_range_idx8(nodeidx_t num, nodeidx_t idx1, nodeidx_t idx2, int tag); -idaman ssize_t ida_export netnode_hashval(nodeidx_t num, const char *idx, void *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_hashstr(nodeidx_t num, const char *idx, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qhashstr(nodeidx_t num, qstring *buf, const char *idx, int tag); -idaman nodeidx_t ida_export netnode_hashval_long(nodeidx_t num, const char *idx, int tag); -idaman bool ida_export netnode_hashset(nodeidx_t num, const char *idx, const void *value, size_t length, int tag); -idaman bool ida_export netnode_hashdel(nodeidx_t num, const char *idx, int tag); -idaman ssize_t ida_export netnode_hashfirst(nodeidx_t num, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qhashfirst(nodeidx_t num, qstring *buf, int tag); -idaman ssize_t ida_export netnode_hashnext(nodeidx_t num, const char *idx, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qhashnext(nodeidx_t num, qstring *buf, const char *idx, int tag); -idaman ssize_t ida_export netnode_hashlast(nodeidx_t num, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qhashlast(nodeidx_t num, qstring *buf, int tag); -idaman ssize_t ida_export netnode_hashprev(nodeidx_t num, const char *idx, char *buf, size_t bufsize, int tag); -idaman ssize_t ida_export netnode_qhashprev(nodeidx_t num, qstring *buf, const char *idx, int tag); -idaman size_t ida_export netnode_blobsize(nodeidx_t num, nodeidx_t start, int tag); -idaman void *ida_export netnode_getblob(nodeidx_t num, void *buf, size_t *bufsize, nodeidx_t start, int tag); -idaman ssize_t ida_export netnode_qgetblob(nodeidx_t num, bytevec_t *buf, size_t elsize, nodeidx_t start, int tag); -idaman bool ida_export netnode_setblob(nodeidx_t num, const void *buf, size_t size, nodeidx_t start, int tag); -idaman int ida_export netnode_delblob(nodeidx_t num, nodeidx_t start, int tag); -idaman bool ida_export netnode_inited(void); -idaman bool ida_export netnode_is_available(void); -idaman size_t ida_export netnode_copy(nodeidx_t num, nodeidx_t count, nodeidx_t target, bool move); -idaman size_t ida_export netnode_altshift(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, int tag); -idaman size_t ida_export netnode_charshift(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, int tag); -idaman size_t ida_export netnode_supshift(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, int tag); -idaman void ida_export netnode_altadjust(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, bool (idaapi *should_skip)(nodeidx_t ea)); -idaman void ida_export netnode_altadjust2(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, altadjust_visitor_t &av); -idaman bool ida_export netnode_exist(const netnode &n); -//@} - -//-------------------------------------------------------------------------- -// N E T N O D E -//-------------------------------------------------------------------------- - -/// Definition of the IDA database node. -/// Note that the size of the 'netnode' class is 4 bytes and it can be -/// freely casted to 'uint32' and back. This makes it easy to store -/// information about the program location in the netnodes. -/// Please pass netnodes to functions by value. -class netnode -{ - /// \cond - friend class netlink; - /// \endcond -public: - - //-------------------------------------------------------------------------- - /// \name Constructors, conversions and assignments - //@{ - - /// Constructor to create a netnode to access information about the - /// specified linear address (possibly missing) - netnode(nodeidx_t num=BADNODE) { netnodenumber = num; } - - /// Conversion from netnode to a linear address - operator nodeidx_t() const { return netnodenumber; } - - /// Construct an instance of netnode class to access the specified netnode. - /// \param _name name of netnode - /// \param namlen length of the name. may be omitted, in this - /// case the length will be calculated with strlen() - /// \param do_create true: create the netnode if it doesn't exist yet. - /// false: don't create the netnode, set netnumber to #BADNODE if - /// it doesn't exist - netnode(const char *_name, size_t namlen=0, bool do_create=false) - { - netnode_check(this, _name, namlen, do_create); - } - - //@} - - /// Does the specified netnode exist?. - /// \retval true there is some information attached to the netnode. - /// \retval false unnamed netnode without any information - friend bool exist(const netnode &n) { return netnode_exist(n); } - - //-------------------------------------------------------------------------- - /// \name Create/Delete - /// \note You can check if a netnode already exists with exist() - //@{ - - /// Create a named netnode. - /// \param _name name of netnode to create. - /// names of user-defined netnodes must have the "$ " prefix - /// in order to avoid clashes with program byte names. - /// \param namlen length of the name. if not specified, it will be - /// calculated using strlen() - /// \retval 1 ok, the node is created - /// \retval 0 the node already exists. you may use the netnode class to access it. - bool create(const char *_name, size_t namlen=0) - { - return netnode_check(this, _name, namlen, true); - } - - /// Create unnamed netnode. - /// \retval 1 ok - /// \retval 0 should not happen, indicates internal error - bool create(void) { return create(nullptr); } - - /// Delete a netnode with all information attached to it - void kill(void) { netnode_kill(this); } - - //@} - - //-------------------------------------------------------------------------- - /// \name Netnode names - //@{ - - /// Get the netnode name. - /// \return -1 if netnode is unnamed (buf is untouched in this case), - /// otherwise the name length - ssize_t get_name(qstring *buf) const - { - return netnode_get_name(*this, buf); - } - - /// Rename a netnode. - /// \param newname new name of netnode. nullptr or "" means to delete name. - /// names of user-defined netnodes must have the "$ " prefix - /// in order to avoid clashes with program byte names. - /// \param namlen length of new name. if not specified, it will be - /// calculated using strlen() - /// \retval 1 ok - /// \retval 0 failed, newname is already used - bool rename(const char *newname, size_t namlen=0) - { - return netnode_rename(*this, newname, namlen); - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Value of netnode - //@{ - - /// Get value of netnode. - /// Netnode values are arbitrary sized objects with max size is #MAXSPECSIZE. - /// NB: do not use this function for strings - see valstr(). - /// \return length of value, -1 if no value present - ssize_t valobj(void *buf, size_t bufsize) const - { - return netnode_valobj(*this, buf, bufsize); - } - - /// Get string value of netnode. - /// See explanations for supstr() function about the differences between valobj() - /// and valstr() - /// \return length of value, -1 if no value present - ssize_t valstr(qstring *buf) const - { - return netnode_qvalstr(*this, buf); - } - - /// \sa valstr(qstring *buf) const - ssize_t valstr(char *buf, size_t bufsize) const - { - return netnode_valstr(*this, buf, bufsize); - } - - /// Set value of netnode. - /// \param value pointer to value - /// \param length length of value. if not specified, it will be calculated - /// using strlen() - /// \returns 1 - ok - bool set(const void *value, size_t length=0) - { - return netnode_set(*this, value, length); - } - - /// Delete value of netnode. - /// \retval 1 ok - /// \retval 0 failed, netnode is bad or other error - bool delvalue(void) - { - return netnode_delvalue(*this); - } - - /// Value of netnode as a long number: - bool set_long(nodeidx_t x) { return set(&x, sizeof(x)); } - bool value_exists(void) const { return valobj(nullptr, 0) >= 0; } - nodeidx_t long_value(void) const - { - nodeidx_t v = 0; - if ( valobj(&v, sizeof(v)) > 0 ) - return v; - return BADNODE; - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Arrays of altvals. - /// altvals: a sparse array of 32-bit values. - /// indexes in this array may be 8-bit or 32-bit values - //@{ - - /// Get altval element of the specified array. - /// \param alt index into array of altvals - /// \param tag tag of array. may be omitted - /// \return value of altval element. nonexistent altval members are returned - /// as zeroes - nodeidx_t altval(nodeidx_t alt, uchar tag=atag) const - { - return netnode_altval(*this, alt, tag); - } - nodeidx_t altval_ea(ea_t ea, uchar tag=atag) const - { - return netnode_altval(*this, ea, tag|NETMAP_IDX); - } - - /// Set value of altval array. - /// \param alt index into array of altvals - /// \param value new value of altval element - /// \param tag tag of array - /// \retval 1 ok - /// \retval 0 failed, normally should not occur - bool altset(nodeidx_t alt, nodeidx_t value, uchar tag=atag) - { - return netnode_supset(*this, alt, &value, sizeof(value), tag); - } - bool altset_ea(ea_t ea, nodeidx_t value, uchar tag=atag) - { - return netnode_supset(*this, ea, &value, sizeof(value), tag|NETMAP_IDX); - } - - /// Delete element of altval array. - /// \param alt index into array of altvals - /// \param tag tag of array - /// \retval 1 ok - /// \retval 0 failed, element doesn't exist - bool altdel(nodeidx_t alt, uchar tag=atag) - { - return netnode_supdel(*this, alt, tag); - } - bool altdel_ea(ea_t ea, uchar tag=atag) - { - return netnode_supdel(*this, ea, tag|NETMAP_IDX); - } - - /// Store/retrieve/delete an address value in the netnode that corresponds - /// to an address. - bool easet(ea_t ea, ea_t addr, uchar tag) - { - return netnode_supset(*this, ea, &addr, sizeof(addr), tag|NETMAP_IDX|NETMAP_VAL); - } - ea_t eaget(ea_t ea, uchar tag) const - { - return netnode_altval(*this, ea, tag|NETMAP_IDX|NETMAP_VAL); - } - bool eadel(ea_t ea, uchar tag) - { - return netnode_supdel(*this, ea, tag|NETMAP_IDX); - } - - bool easet_idx(nodeidx_t idx, ea_t addr, uchar tag) - { - return netnode_supset(*this, idx, &addr, sizeof(addr), tag|NETMAP_VAL); - } - ea_t eaget_idx(nodeidx_t idx, uchar tag) - { - return netnode_altval(*this, idx, tag|NETMAP_VAL); - } - - bool easet_idx8(uchar idx, ea_t addr, uchar tag) - { - return netnode_supset_idx8(*this, idx, &addr, sizeof(addr), tag|NETMAP_VAL); - } - ea_t eaget_idx8(uchar idx, uchar tag) const - { - return netnode_altval_idx8(*this, idx, tag|NETMAP_VAL); - } - bool eadel_idx8(uchar idx, uchar tag) - { - return netnode_supdel_idx8(*this, idx, tag); - } - - /// Get first existing element of altval array. - /// \param tag tag of array - /// \return index of first existing element of altval array, - /// #BADNODE if altval array is empty - nodeidx_t altfirst(uchar tag=atag) const - { - return supfirst(tag); - } - - /// Get next existing element of altval array. - /// \param cur current index - /// \param tag tag of array - /// \return index of the next existing element of altval array, - /// #BADNODE if no more altval array elements exist - nodeidx_t altnext(nodeidx_t cur, uchar tag=atag) const - { - return supnext(cur, tag); - } - - /// Get last element of altval array. - /// \param tag tag of array - /// \return index of last existing element of altval array, - /// #BADNODE if altval array is empty - nodeidx_t altlast(uchar tag=atag) const - { - return suplast(tag); - } - - /// Get previous existing element of altval array. - /// \param cur current index - /// \param tag tag of array - /// \return index of the previous existing element of altval array, - /// #BADNODE if no more altval array elements exist - nodeidx_t altprev(nodeidx_t cur, uchar tag=atag) const - { - return supprev(cur, tag); - } - - /// Shift the altval array elements. - /// Moves the array elements at (from..from+size) to (to..to+size) - /// \return number of shifted elements - size_t altshift(nodeidx_t from, nodeidx_t to, nodeidx_t size, uchar tag=atag) - { - return netnode_altshift(*this, from, to, size, tag); - } - - /// Adjust values of altval arrays elements. - /// All altvals in the range from+1..from+size+1 and adjusted to have - /// values in the range to+1..to+size+1. - /// The parameter should_skip() can be used to skip the adjustment of some altvals - void altadjust(nodeidx_t from, nodeidx_t to, nodeidx_t size, bool (idaapi *should_skip)(nodeidx_t ea)=nullptr) - { - netnode_altadjust(*this, from, to, size, should_skip); - } - void altadjust2(nodeidx_t from, nodeidx_t to, nodeidx_t size, altadjust_visitor_t &av) - { - netnode_altadjust2(*this, from, to, size, av); - } - - - //@} - - /// \name Arrays of altvals: 8-bit values - /// The following functions behave in the same manner as the functions - /// described above. The only difference is that the array value is 8-bits. - /// - index: 32 bits - /// - value: 8 bits - //@{ - uchar charval(nodeidx_t alt, uchar tag) const { return netnode_charval(*this, alt, tag); } - bool charset(nodeidx_t alt, uchar val, uchar tag) { return supset(alt, &val, sizeof(val), tag); } - bool chardel(nodeidx_t alt, uchar tag) { return supdel(alt, tag); } - uchar charval_ea(ea_t ea, uchar tag) const { return netnode_charval(*this, ea, tag|NETMAP_IDX); } - bool charset_ea(ea_t ea, uchar val, uchar tag) { return netnode_supset(*this, ea, &val, sizeof(val), tag|NETMAP_IDX); } - bool chardel_ea(ea_t ea, uchar tag) { return netnode_supdel(*this, ea, tag|NETMAP_IDX); } - nodeidx_t charfirst(uchar tag) const { return supfirst(tag); } - nodeidx_t charnext(nodeidx_t cur, uchar tag) const { return supnext(cur, tag); } - nodeidx_t charlast(uchar tag) const { return suplast(tag); } - nodeidx_t charprev(nodeidx_t cur, uchar tag) const { return supprev(cur, tag); } - size_t charshift(nodeidx_t from, nodeidx_t to, nodeidx_t size, uchar tag) - { return netnode_charshift(*this, from, to, size, tag); } - //@} - - /// \name Arrays of altvals: 8-bit indexes - /// Another set of functions to work with altvals. - /// The only difference is that the array index is 8-bits, - /// and therefore the array may contain up to 256 elements only. - /// - index: 8 bits - /// - value: 32 bits - //@{ - nodeidx_t altval_idx8(uchar alt, uchar tag) const { return netnode_altval_idx8(*this, alt, tag); } - bool altset_idx8(uchar alt, nodeidx_t val, uchar tag) { return supset_idx8(alt, &val, sizeof(val), tag); } - bool altdel_idx8(uchar alt, uchar tag) { return supdel_idx8(alt, tag); } - nodeidx_t altfirst_idx8(uchar tag) const { return supfirst_idx8(tag); } - nodeidx_t altnext_idx8(uchar cur, uchar tag) const { return supnext_idx8(cur, tag); } - nodeidx_t altlast_idx8(uchar tag) const { return suplast_idx8(tag); } - nodeidx_t altprev_idx8(uchar cur, uchar tag) const { return supprev_idx8(cur, tag); } - //@} - - /// \name More altvals - /// Another set of functions to work with altvals. - /// - index: 8 bits - /// - value: 8 bits - //@{ - uchar charval_idx8(uchar alt, uchar tag) const { return netnode_charval_idx8(*this, alt, tag); } - bool charset_idx8(uchar alt, uchar val, uchar tag) { return supset_idx8(alt, &val, sizeof(val), tag); } - //-V::524 equivalent functions - bool chardel_idx8(uchar alt, uchar tag) { return supdel_idx8(alt, tag); } - nodeidx_t charfirst_idx8(uchar tag) const { return supfirst_idx8(tag); } - nodeidx_t charnext_idx8(uchar cur, uchar tag) const { return supnext_idx8(cur, tag); } - nodeidx_t charlast_idx8(uchar tag) const { return suplast_idx8(tag); } - nodeidx_t charprev_idx8(uchar cur, uchar tag) const { return supprev_idx8(cur, tag); } - //@} - - /// \name Delete altvals - /// \note To delete range of elements in an altval array, see supdel_range() - //@{ - - /// Delete all elements of altval array. - /// This function may be applied to 32-bit and 8-bit altval arrays. - /// This function deletes the whole altval array. - /// \return success - bool altdel(void) - { - return supdel_all(atag); - } - - /// Delete all elements of the specified altval array. - /// This function may be applied to 32-bit and 8-bit altval arrays. - /// This function deletes the whole altval array. - /// \param tag tag of array - /// \return success - bool altdel_all(uchar tag=atag) - { - return supdel_all(tag); - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Arrays of supvals - /// supvals: an array of arbitrary sized objects. - /// (size of each object is limited by #MAXSPECSIZE). - /// indexes in this array may be 8-bit or 32-bit values. - //@{ - - /// Get value of the specified supval array element. - /// NB: do not use this function to retrieve strings, see supstr()! - /// \param alt index into array of supvals - /// \param buf output buffer, may be nullptr - /// \param bufsize size of output buffer - /// \param tag tag of array. Default: stag - /// \return size of value, -1 if element doesn't exist - ssize_t supval(nodeidx_t alt, void *buf, size_t bufsize, uchar tag=stag) const - { return netnode_supval(*this, alt, buf, bufsize, tag); } - ssize_t supval_ea(ea_t ea, void *buf, size_t bufsize, uchar tag=stag) const - { return netnode_supval(*this, ea, buf, bufsize, tag|NETMAP_IDX); } - - /// Get string value of the specified supval array element. - /// The differences between supval() and supstr() are the following: - /// -# Strings are stored with the terminating zero in the old databases. - /// supval() returns the exact size of the stored object (with - /// the terminating zero) but supstr returns the string length without - /// the terminating zero. supstr() can handle strings stored with or - /// without the terminating zero. - /// -# supstr() makes sure that the string is terminated with 0 even if - /// the string was stored in the database without it or the output - /// buffer is too small to hold the entire string. In the latter case - /// the string will be truncated but still will have the terminating zero. - /// - /// If you do not use the string length returned by supval/supstr() functions - /// and you are sure that the output buffer is big enough to hold the entire - /// string and the string has been stored in the database with the terminating - /// zero, then you can continue to use supval() instead of supstr(). - /// - /// \param buf output buffer, may be nullptr - /// \param alt index into array of supvals - /// \param tag tag of array. Default: stag - /// \return length of the output string, -1 if element doesn't exist - ssize_t supstr(qstring *buf, nodeidx_t alt, uchar tag=stag) const - { return netnode_qsupstr(*this, buf, alt, tag); } - ssize_t supstr_ea(qstring *buf, ea_t ea, uchar tag=stag) const - { return netnode_qsupstr(*this, buf, ea, tag|NETMAP_IDX); } - - /// \sa supstr(qstring *buf, nodeidx_t alt, uchar tag=stag) const - ssize_t supstr(nodeidx_t alt, char *buf, size_t bufsize, uchar tag=stag) const - { return netnode_supstr(*this, alt, buf, bufsize, tag); } - ssize_t supstr_ea(ea_t ea, char *buf, size_t bufsize, uchar tag=stag) const - { return netnode_supstr(*this, ea, buf, bufsize, tag|NETMAP_IDX); } - - /// Set value of supval array element. - /// \param alt index into array of supvals - /// \param value pointer to supval value - /// \param length length of 'value'. If not specified, the length is calculated - /// using strlen()+1. - /// \param tag tag of array - /// \retval 1 ok - /// \retval 0 should not occur - indicates internal error - bool supset(nodeidx_t alt, const void *value, size_t length=0, uchar tag=stag) - { return netnode_supset(*this, alt, value, length, tag); } - bool supset_ea(ea_t ea, const void *value, size_t length=0, uchar tag=stag) - { return netnode_supset(*this, ea, value, length, tag|NETMAP_IDX); } - - /// Delete supval element. - /// \param alt index into array of supvals - /// \param tag tag of array - /// \retval true deleted - /// \retval false element does not exist - bool supdel(nodeidx_t alt, uchar tag=stag) - { return netnode_supdel(*this, alt, tag); } - bool supdel_ea(ea_t ea, uchar tag=stag) - { return netnode_supdel(*this, ea, tag|NETMAP_IDX); } - - /// Get lower bound of existing elements of supval array. - /// \param cur current index - /// \param tag tag of array - /// \return index of first existing element of supval array >= cur - /// #BADNODE if supval array is empty - nodeidx_t lower_bound(nodeidx_t cur, uchar tag=stag) const - { return netnode_lower_bound(*this, cur, tag); } - nodeidx_t lower_bound_ea(ea_t ea, uchar tag=stag) const - { return netnode_lower_bound(*this, ea, tag|NETMAP_IDX); } - - /// Get first existing element of supval array. - /// \param tag tag of array - /// \return index of first existing element of supval array, - /// #BADNODE if supval array is empty - nodeidx_t supfirst(uchar tag=stag) const - { return netnode_supfirst(*this, tag); } - - /// Get next existing element of supval array. - /// \param cur current index - /// \param tag tag of array - /// \return index of the next existing element of supval array, - /// #BADNODE if no more supval array elements exist - nodeidx_t supnext(nodeidx_t cur, uchar tag=stag) const - { return netnode_supnext(*this, cur, tag); } - - /// Get last existing element of supval array. - /// \param tag tag of array - /// \return index of last existing element of supval array, - /// #BADNODE if supval array is empty - nodeidx_t suplast(uchar tag=stag) const - { return netnode_suplast(*this, tag); } - - /// Get previous existing element of supval array. - /// \param cur current index - /// \param tag tag of array - /// \return index of the previous existing element of supval array - /// #BADNODE if no more supval array elements exist - nodeidx_t supprev(nodeidx_t cur, uchar tag=stag) const - { return netnode_supprev(*this, cur, tag); } - - - /// Shift the supval array elements. - /// Moves the array elements at (from..from+size) to (to..to+size) - /// \return number of shifted elements - size_t supshift(nodeidx_t from, nodeidx_t to, nodeidx_t size, uchar tag=stag) - { return netnode_supshift(*this, from, to, size, tag); } - - //@} - - /// \name Arrays of supvals: 8-bit indexes - /// The following functions behave in the same manner as the functions - /// described above. The only difference is that the array index is 8-bits - /// and therefore the array may contains up to 256 elements only. - //@{ - ssize_t supval_idx8(uchar alt, void *buf, size_t bufsize, uchar tag) const { return netnode_supval_idx8(*this, alt, buf, bufsize, tag); } - ssize_t supstr_idx8(uchar alt, char *buf, size_t bufsize, uchar tag) const { return netnode_supstr_idx8(*this, alt, buf, bufsize, tag); } - ssize_t supstr_idx8(qstring *buf, uchar alt, uchar tag) const { return netnode_qsupstr_idx8(*this, buf, alt, tag); } - bool supset_idx8(uchar alt, const void *value, size_t length, uchar tag) { return netnode_supset_idx8(*this, alt, value, length, tag); } - bool supdel_idx8(uchar alt, uchar tag) { return netnode_supdel_idx8(*this, alt, tag); } - nodeidx_t lower_bound_idx8(uchar alt, uchar tag) const { return netnode_lower_bound_idx8(*this, alt, tag); } - nodeidx_t supfirst_idx8(uchar tag) const { return netnode_supfirst_idx8(*this, tag); } - nodeidx_t supnext_idx8(uchar alt, uchar tag) const { return netnode_supnext_idx8(*this, alt, tag); } - nodeidx_t suplast_idx8(uchar tag) const { return netnode_suplast_idx8(*this, tag); } - nodeidx_t supprev_idx8(uchar alt, uchar tag) const { return netnode_supprev_idx8(*this, alt, tag); } - //@} - - /// \name Delete supvals - //@{ - - /// Delete all elements of supval array. - /// This function may be applied to 32-bit and 8-bit supval arrays. - /// This function deletes the whole supval array. - /// \return success - bool supdel(void) - { - return supdel_all(stag); - } - - /// Delete all elements of the specified supval array. - /// This function may be applied to 32-bit and 8-bit supval arrays. - /// This function deletes the whole supval array. - /// \return success - bool supdel_all(uchar tag) - { - return netnode_supdel_all(*this, tag); - } - - /// Delete range of elements in the specified supval array. - /// Elements in range [idx1, idx2) will be deleted. - /// \note This function can also be used to delete a range of altval elements - /// \param idx1 first element to delete - /// \param idx2 last element to delete + 1 - /// \param tag tag of array - /// \return number of deleted elements - int supdel_range(nodeidx_t idx1, nodeidx_t idx2, uchar tag) - { - return netnode_supdel_range(*this, idx1, idx2, tag); - } - /// Same as above, but accepts 8-bit indexes - int supdel_range_idx8(uchar idx1, uchar idx2, uchar tag) - { - return netnode_supdel_range_idx8(*this, idx1, idx2, tag); - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Hashes - /// Associative arrays indexed by strings. - /// hashvals: Indexes in this array are strings. - /// Values are arbitrary sized (max size is #MAXSPECSIZE) - //@{ - - /// Get value of the specified hash element. - /// \param idx index into hash - /// \param buf output buffer, may be nullptr - /// \param bufsize output buffer size - /// \param tag tag of hash. Default: htag - /// \return -1 if element doesn't exist or idx is nullptr. - /// otherwise returns the value size in bytes - ssize_t hashval(const char *idx, void *buf, size_t bufsize, uchar tag=htag) const - { return netnode_hashval(*this, idx, buf, bufsize, tag); } - - /// Similar to supstr(), but accepts a hash index - ssize_t hashstr(qstring *buf, const char *idx, uchar tag=htag) const - { return netnode_qhashstr(*this, buf, idx, tag); } - - /// \sa hashstr(qstring *buf, const char *idx, uchar tag=htag) const - ssize_t hashstr(const char *idx, char *buf, size_t bufsize, uchar tag=htag) const - { return netnode_hashstr(*this, idx, buf, bufsize, tag); } - - /// Get value of the specified hash element. - /// \param idx index into hash - /// \param tag tag of hash. Default: htag - /// \return value of hash element (it should be set using hashset(nodeidx_t)), - /// 0 if the element does not exist - nodeidx_t hashval_long(const char *idx, uchar tag=htag) const - { return netnode_hashval_long(*this, idx, tag); } - - /// Set value of hash element. - /// \param idx index into hash - /// \param value pointer to value - /// \param length length of 'value'. If not specified, the length is calculated - /// using strlen()+1. - /// \param tag tag of hash. Default: htag - /// \retval 1 ok - /// \retval 0 should not occur - indicates internal error - bool hashset(const char *idx, const void *value, size_t length=0, uchar tag=htag) - { return netnode_hashset(*this, idx, value, length, tag); } - - /// Set value of hash element to long value. - /// \param idx index into hash - /// \param value new value of hash element - /// \param tag tag of hash. Default: htag - /// \retval 1 ok - /// \retval 0 should not occur - indicates internal error - bool hashset(const char *idx, nodeidx_t value, uchar tag=htag) - { return hashset(idx, &value, sizeof(value), tag); } - - /// Delete hash element. - /// \param idx index into hash - /// \param tag tag of hash. Default: htag - /// \retval true deleted - /// \retval false element does not exist - bool hashdel(const char *idx, uchar tag=htag) - { return netnode_hashdel(*this, idx, tag); } - - /// Get first existing element of hash. - /// \note elements of hash are kept sorted in lexical order - /// \param buf output buffer, may be nullptr - /// \param tag tag of hash. Default: htag - /// \return size of index of first existing element of hash, - /// -1 if hash is empty - ssize_t hashfirst(qstring *buf, uchar tag=htag) const - { return netnode_qhashfirst(*this, buf, tag); } - - /// \sa hashfirst(qstring *buf, uchar tag=htag) const - ssize_t hashfirst(char *buf, size_t bufsize, uchar tag=htag) const - { return netnode_hashfirst(*this, buf, bufsize, tag); } - - /// Get next existing element of hash. - /// \note elements of hash are kept sorted in lexical order - /// \param buf output buffer, may be nullptr - /// \param idx current index into hash - /// \param tag tag of hash. Default: htag - /// \return size of index of the next existing element of hash, - /// -1 if no more hash elements exist - ssize_t hashnext(qstring *buf, const char *idx, uchar tag=htag) const - { return netnode_qhashnext(*this, buf, idx, tag); } - - /// \sa hashnext(qstring *buf, const char *idx, uchar tag=htag) const - ssize_t hashnext(const char *idx, char *buf, size_t bufsize, uchar tag=htag) const - { return netnode_hashnext(*this, idx, buf, bufsize, tag); } - - /// Get last existing element of hash. - /// \note elements of hash are kept sorted in lexical order - /// \param buf output buffer, may be nullptr - /// \param tag tag of hash. Default: htag - /// \return size of index of last existing element of hash, - /// -1 if hash is empty - ssize_t hashlast(qstring *buf, uchar tag=htag) const - { return netnode_qhashlast(*this, buf, tag); } - - /// \sa hashlast(qstring *buf, uchar tag=htag) const - ssize_t hashlast(char *buf, size_t bufsize, uchar tag=htag) const - { return netnode_hashlast(*this, buf, bufsize, tag); } - - /// Get previous existing element of supval array. - /// \note elements of hash are kept sorted in lexical order - /// \param buf output buffer, may be nullptr - /// \param idx current index into hash - /// \param tag tag of hash. Default: htag - /// \return size of index of the previous existing element of hash, - /// -1 if no more hash elements exist - ssize_t hashprev(qstring *buf, const char *idx, uchar tag=htag) const - { return netnode_qhashprev(*this, buf, idx, tag); } - - /// \sa hashprev(qstring *buf, const char *idx, uchar tag=htag) const - ssize_t hashprev(const char *idx, char *buf, size_t bufsize, uchar tag=htag) const - { return netnode_hashprev(*this, idx, buf, bufsize, tag); } - - /// Delete all elements of hash. - /// This function deletes the whole hash. - /// \param tag tag of hash. Default: htag - /// \return success - bool hashdel_all(uchar tag=htag) - { - return supdel_all(tag); - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Blobs - /// Virtually unlimited size binary objects. - /// Blobs are stored in several supval array elements. - //@{ - - /// Get size of blob. - /// \param _start index of the first supval element used to store blob - /// \param tag tag of supval array - /// \return number of bytes required to store a blob - size_t blobsize(nodeidx_t _start, uchar tag) - { - return netnode_blobsize(*this, _start, tag); - } - size_t blobsize_ea(ea_t ea, uchar tag) - { - return netnode_blobsize(*this, ea, tag|NETMAP_IDX); - } - - /// Get blob from a netnode. - /// \param buf buffer to read into. if nullptr, the buffer will be - /// allocated using qalloc() - /// \param[in, out] bufsize in: size of 'buf' in bytes (if buf == nullptr then meaningless). - /// out: size of the blob if it exists. - /// bufsize may be nullptr - /// \param _start index of the first supval element used to store blob - /// \param tag tag of supval array - /// \return nullptr if blob doesn't exist, - /// otherwise returns pointer to blob - void *getblob( - void *buf, - size_t *bufsize, - nodeidx_t _start, - uchar tag) - { - return netnode_getblob(*this, buf, bufsize, _start, tag); - } - void *getblob_ea( - void *buf, - size_t *bufsize, - ea_t ea, - uchar tag) - { - return netnode_getblob(*this, buf, bufsize, ea, tag|NETMAP_IDX); - } - - /// Get blob from a netnode. - /// \param blob output ::qvector buffer - /// \param _start index of the first supval element used to store blob - /// \param tag tag of supval array - /// \return -1 if blob doesn't exist, size of blob otherwise - template <class T> - ssize_t getblob( - qvector<T> *blob, - nodeidx_t _start, - uchar tag) - { - return netnode_qgetblob(*this, (bytevec_t *)blob, sizeof(T), _start, tag); - } - template <class T> - ssize_t getblob_ea( - qvector<T> *blob, - ea_t ea, - uchar tag) - { - return netnode_qgetblob(*this, (bytevec_t *)blob, sizeof(T), nodeidx_t(ea), tag|NETMAP_IDX); - } - - /// Get blob from a netnode into a qstring* and make sure the string is - /// null-terminated. - /// \param buf output ::qstring buffer - /// \param _start index of the first supval element used to store blob - /// \param tag tag of supval array - /// \return -1 if blob doesn't exist - /// size of string (including terminating null) otherwise - ssize_t getblob( - qstring *buf, - nodeidx_t _start, - uchar tag) - { - return netnode_qgetblob(*this, (bytevec_t *)buf, 1, _start, tag|NETMAP_STR); - } - - /// Store a blob in a netnode. - /// \param buf pointer to blob to save - /// \param size size of blob in bytes - /// \param _start index of the first supval element used to store blob - /// \param tag tag of supval array - /// \return success - bool setblob( - const void *buf, - size_t size, - nodeidx_t _start, - uchar tag) - { - return netnode_setblob(*this, buf, size, _start, tag); - } - bool setblob_ea( - const void *buf, - size_t size, - ea_t ea, - uchar tag) - { - return netnode_setblob(*this, buf, size, ea, tag|NETMAP_IDX); - } - - /// Delete a blob. - /// \param _start index of the first supval element used to store blob - /// \param tag tag of supval array - /// \return number of deleted supvals - int delblob(nodeidx_t _start, uchar tag) - { - return netnode_delblob(*this, _start, tag); - } - int delblob_ea(ea_t ea, uchar tag) - { - return netnode_delblob(*this, ea, tag|NETMAP_IDX); - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Enumerate all netnodes - //@{ - - /// Get first netnode in the graph. - /// Sets netnodenumber to the lowest existing number. - /// \retval true ok - /// \retval false graph is empty - bool start(void) - { - return netnode_start(this); - } - - /// Get last netnode in the graph. - /// Sets netnodenumber to the highest existing number. - /// \retval true ok - /// \retval false graph is empty - bool end(void) - { - return netnode_end(this); - } - - /// Get next netnode in the graph. - /// Sets netnodenumber to the next existing number - /// \retval true ok - /// \retval false no more netnodes - bool next(void) - { - return netnode_next(this); - } - - /// Get prev netnode in the graph. - /// Sets netnodenumber to the previous existing number - /// \retval true ok - /// \retval false no more netnodes - bool prev(void) - { - return netnode_prev(this); - } - - //@} - - //-------------------------------------------------------------------------- - /// \name Move and copy netnodes - /// \param target the target netnode - /// \param count how many netnodes to copy - /// \return number of copied/moved keys, #BADNODE if failure or not enough memory - //@{ - size_t copyto(netnode target, nodeidx_t count=1) { return netnode_copy(netnodenumber, count, target.netnodenumber, false); } - size_t moveto(netnode target, nodeidx_t count=1) { return netnode_copy(netnodenumber, count, target.netnodenumber, true); } - //@} - - //-------------------------------------------------------------------------- - /// \name Netnode comparisons - //@{ - bool operator==(netnode &n) const { return netnodenumber == n.netnodenumber; } - bool operator!=(netnode &n) const { return netnodenumber != n.netnodenumber; } - bool operator==(nodeidx_t x) const { return netnodenumber == x; } - bool operator!=(nodeidx_t x) const { return netnodenumber != x; } - //@} - - - static bool inited(void) { return netnode_inited(); } - static bool is_available(void) { return netnode_is_available(); } - -private: - // The netnode number. - // Usually this is the linear address that the netnode keeps information about. - nodeidx_t netnodenumber; -}; -#ifdef __EA64__ -CASSERT(sizeof(netnode) == 8); -#else -CASSERT(sizeof(netnode) == 4); -#endif - -//----------------------------------------------------------------------- - -/// The root node is used by the kernel, do not use it directly in your modules. -/// Its name: "Root Node" -#if !defined(__KERNEL__) || defined(__DEFINE_ROOT_NODE__) -idaman netnode ida_export_data root_node; -#endif - - -#endif // _NETNODE_HPP diff --git a/idasdk75/include/network.hpp b/idasdk75/include/network.hpp deleted file mode 100644 index dac825c..0000000 --- a/idasdk75/include/network.hpp +++ /dev/null @@ -1,454 +0,0 @@ -#ifndef NETWORK_HPP -#define NETWORK_HPP - -#include <map> - -#include <pro.h> - -#ifdef __NT__ -# if !defined(AF_MAX) -# include <ws2tcpip.h> -# endif -# define SYSTEM "Windows" -# define socklen_t int -# define SHUT_RD SD_RECEIVE -# define SHUT_WR SD_SEND -# define SHUT_RDWR SD_BOTH -#else // not NT, i.e. UNIX -# include <netinet/in.h> -# include <netinet/tcp.h> -# include <arpa/inet.h> -# include <netdb.h> -# define closesocket(s) close(s) -# define SOCKET size_t -# define INVALID_SOCKET size_t(-1) -# define SOCKET_ERROR (-1) -# if defined(__LINUX__) -# if defined(__ARM__) -# if defined(__ANDROID__) -# define SYSTEM "Android" -# else -# define SYSTEM "ARM Linux" -# endif -# else -# if defined(__ANDROID__) -# define SYSTEM "Android x86" -# else -# define SYSTEM "Linux" -# endif -# endif - // linux debugger cannot be multithreaded because it uses thread_db. - // i doubt that this library is meant to be used with multiple - // applications simultaneously. -# define __SINGLE_THREADED_SERVER__ -# elif defined(__MAC__) -# define SYSTEM "Mac OS X" -# else -# error "Unknown platform" -# endif -# include <sys/socket.h> -# include <netinet/in.h> -#endif - -#ifndef __X86__ -# define _SYSBITS " 64-bit" -#else -# define _SYSBITS " 32-bit" -#endif - -#ifdef TESTABLE_BUILD -# ifdef __EA64__ -# define SYSBITS _SYSBITS " (sizeof ea=64)" -# else -# define SYSBITS _SYSBITS " (sizeof ea=32)" -# endif -#else -# define SYSBITS _SYSBITS -#endif - -#ifdef __SINGLE_THREADED_SERVER__ -# define __SERVER_TYPE__ "ST" -#else -# define __SERVER_TYPE__ "MT" -#endif - -#define TIMEOUT (1000/25) // timeout for polling (ms) -#define TIMEOUT_INFINITY -1 -#define RECV_HELLO_TIMEOUT 1000 // timeout for the first packet (ms) -#define RECV_TIMEOUT_PERIOD 10000 // timeout for recv (ms) - -// bidirectional codes (client <-> server) -enum base_packet_id_t -{ - RPC_OK = 0, // response: function call succeeded - RPC_UNK, // response: unknown function code - RPC_MEM, // response: no memory - base_packet_id_last -}; - -#define RPC_OPEN 3 // server->client: i'm ready, the very first packet - -#define RPC_EVENT 4 // server->client: debug event ready, followed by debug_event -#define RPC_EVOK 5 // client->server: event processed (in response to RPC_EVENT) -#define RPC_CANCELLED 6 // client->server: operation was cancelled by the user -// we need EVOK to handle the situation when the debug -// event was detected by the server during polling and -// was sent to the client using RPC_EVENT but client has not received it yet -// and requested GET_DEBUG_EVENT. In this case we should not -// call remote_get_debug_event() but instead force the client -// to use the event sent by RPC_EVENT. -// In other words, if the server has sent RPC_EVENT but has not -// received RPC_EVOK, it should fail all GET_DEBUG_EVENTS. - -// client->server codes -#define RPC_INIT 10 -#define RPC_TERM 11 -#define RPC_GET_PROCESSES 12 -#define RPC_START_PROCESS 13 -#define RPC_EXIT_PROCESS 14 -#define RPC_ATTACH_PROCESS 15 -#define RPC_DETACH_PROCESS 16 -#define RPC_GET_DEBUG_EVENT 17 -#define RPC_PREPARE_TO_PAUSE_PROCESS 18 -#define RPC_STOPPED_AT_DEBUG_EVENT 19 -#define RPC_CONTINUE_AFTER_EVENT 20 -#define RPC_TH_SUSPEND 21 -#define RPC_TH_CONTINUE 22 -#define RPC_SET_RESUME_MODE 23 -#define RPC_GET_MEMORY_INFO 24 -#define RPC_READ_MEMORY 25 -#define RPC_WRITE_MEMORY 26 -#define RPC_UPDATE_BPTS 27 -#define RPC_UPDATE_LOWCNDS 28 -#define RPC_EVAL_LOWCND 29 -#define RPC_ISOK_BPT 30 -#define RPC_READ_REGS 31 -#define RPC_WRITE_REG 32 -#define RPC_GET_SREG_BASE 33 -#define RPC_SET_EXCEPTION_INFO 34 - -#define RPC_OPEN_FILE 35 -#define RPC_CLOSE_FILE 36 -#define RPC_READ_FILE 37 -#define RPC_WRITE_FILE 38 -#define RPC_IOCTL 39 // both client and the server may send this packet -#define RPC_UPDATE_CALL_STACK 40 -#define RPC_APPCALL 41 -#define RPC_CLEANUP_APPCALL 42 -#define RPC_REXEC 43 -#define RPC_GET_SCATTERED_IMAGE 44 -#define RPC_GET_IMAGE_UUID 45 -#define RPC_GET_SEGM_START 46 -#define RPC_BIN_SEARCH 47 - -// server->client codes -#define RPC_SET_DEBUG_NAMES 50 -#define RPC_SYNC_STUB 51 -#define RPC_ERROR 52 -#define RPC_MSG 53 -#define RPC_WARNING 54 -#define RPC_HANDLE_DEBUG_EVENT 55 -#define RPC_REPORT_IDC_ERROR 56 -#define RPC_IMPORT_DLL 57 - -#pragma pack(push, 1) - -struct PACKED rpc_packet_t -{ // fields are always sent in the network order - uint32 length; // length of the packet (do not count length & code) - uchar code; // function code -}; -CASSERT(sizeof(rpc_packet_t) == 5); -#pragma pack(pop) - -enum rpc_notification_type_t -{ - rnt_unknown = 0, - rnt_msg, - rnt_warning, - rnt_error, -}; - -#define DEFINE_ONE_NOTIFICATION_FUNCTION(FuncName, NotifCode, RpcEngineInst) \ - AS_PRINTF(2, 3) void FuncName(const char *format, ...) \ - { \ - va_list va; \ - va_start(va, format); \ - dvnotif(NotifCode, RpcEngineInst, format, va); \ - va_end(va); \ - } - -#define DEFINE_ALL_NOTIFICATION_FUNCTIONS(RpcEngineInst) \ - DEFINE_ONE_NOTIFICATION_FUNCTION(dmsg, 0, RpcEngineInst) \ - DEFINE_ONE_NOTIFICATION_FUNCTION(dwarning, 1, RpcEngineInst) \ - DEFINE_ONE_NOTIFICATION_FUNCTION(derror, -1, RpcEngineInst) - -class rpc_engine_t; - -//------------------------------------------------------------------------- -AS_PRINTF(2, 0) ssize_t dvnotif_client( - int code, - const char *format, - va_list va); - -#ifdef __NT__ -# define IRSERR_TIMEOUT WAIT_TIMEOUT -#else -# define IRSERR_TIMEOUT ETIME -#endif -#define IRSERR_CANCELLED -0xE5CA7E // escape -#define IRSERR_SKIP_ITER -0x5217 // skip recv() in rpc_engine_t's recv_data loop - -//------------------------------------------------------------------------- -// idarpc_stream_t -//------------------------------------------------------------------------- -// the idarpc_stream_t structure is not defined. -// it is used as an opaque type provided by the transport level. -// the transport level defines its own local type for it. -struct idarpc_stream_t; - -idarpc_stream_t *irs_new(bool use_tls=false); -bool irs_init_client(idarpc_stream_t *irs, const char *hostname, int port_number); -bool irs_init_server( - idarpc_stream_t *irs, - const char *hostname, - int port_number, - const char *certchain=nullptr, - const char *privkey=nullptr); -bool irs_accept(idarpc_stream_t *irs, idarpc_stream_t *listener); -bool irs_handshake(idarpc_stream_t *irs, int timeout_ms = -1); -int irs_ready(idarpc_stream_t *irs, int timeout_ms = -1); -ssize_t irs_recv(idarpc_stream_t *irs, void *buf, size_t n); -ssize_t irs_send(idarpc_stream_t *irs, const void *buf, size_t n); -void irs_term(idarpc_stream_t **pirs, int shutdown_flags = -1); -int irs_get_error(idarpc_stream_t *irs); -const char *irs_strerror(idarpc_stream_t *irs); -bool irs_peername(idarpc_stream_t *irs, qstring *out, bool lookupname = true); -bool irs_sockname(idarpc_stream_t *irs, qstring *out, bool lookupname = true); - -enum progress_loop_ctrl_t -{ - plc_proceed, - plc_skip_iter, - plc_cancel, -}; -typedef progress_loop_ctrl_t irs_progress_cb_t(bool receiving, size_t processed, size_t total, void *); -void irs_set_progress_cb(idarpc_stream_t *irs, int ms, irs_progress_cb_t cb, void *ud=NULL); -struct irs_cancellable_op_t -{ - idarpc_stream_t *irs; - irs_cancellable_op_t(idarpc_stream_t *_irs, bool receiving, size_t goal=0); - ~irs_cancellable_op_t(); - void inc_progress(size_t progress); -}; - -//------------------------------------------------------------------------- -typedef qtime64_t utc_timestamp_t; - -//------------------------------------------------------------------------- -// base_dispatcher_t + client_handler_t -//------------------------------------------------------------------------- -struct client_handler_t -{ - FILE *channels[16]; - idarpc_stream_t *irs; - qstring peer_name; - uint32 session_id; - utc_timestamp_t session_start; - bool verbose; - - void close_all_channels(); - void clear_channels(); - int find_free_channel() const; - - client_handler_t(idarpc_stream_t *_irs, bool _verbose); - virtual ~client_handler_t(); - - virtual bool handle() = 0; // true - delete this - virtual void shutdown_gracefully(int signum) = 0; - - //lint -sem(client_handler_t::term_irs,cleanup) - void term_irs(); - - AS_PRINTF(2, 3) int lprintf(const char *format, ...) const; - -private: - DECLARE_UNCOPYABLE(client_handler_t); -}; - -//------------------------------------------------------------------------- -struct client_handlers_list_t -{ - typedef std::map<client_handler_t *, qthread_t> storage_t; - storage_t storage; - - virtual ~client_handlers_list_t() {} - virtual void lock() {} - virtual void unlock() {} - virtual bool is_multi_threaded() const { return false; } -}; - -//------------------------------------------------------------------------- -struct mt_client_handlers_list_t : public client_handlers_list_t -{ - qmutex_t mutex; - - mt_client_handlers_list_t() { mutex = qmutex_create(); QASSERT(1540, mutex != NULL); } - virtual ~mt_client_handlers_list_t() { qmutex_free(mutex); } - virtual void lock() override { qmutex_lock(mutex); } - virtual void unlock() override { qmutex_unlock(mutex); } - virtual bool is_multi_threaded() const override { return true; } -}; - -//------------------------------------------------------------------------- -struct base_dispatcher_t -{ - ushort port_number; - qstring ipv4_address; - qstring certchain; - qstring privkey; - idarpc_stream_t *irs; - client_handlers_list_t *clients_list; - bool use_tls; - bool verbose; - - base_dispatcher_t(bool multi_threaded);// : port_number(-1), irs(NULL), verbose(false) {} - virtual ~base_dispatcher_t(); - void dispatch(); - - virtual void collect_cliopts(cliopts_t *out); - - // - void install_signal_handlers(); - - // - virtual client_handler_t *new_client_handler(idarpc_stream_t *_irs) = 0; - void delete_client_handler(client_handler_t *inst); - - virtual void shutdown_gracefully(int signum); - - -private: - void handle_session(client_handler_t *handler); - void add_to_clients_list(client_handler_t *handler, qthread_t t); - DECLARE_UNCOPYABLE(base_dispatcher_t); -}; - -//------------------------------------------------------------------------- -// packing/unpacking utils -//------------------------------------------------------------------------- -bytevec_t prepare_rpc_packet(uchar code); -void finalize_packet(bytevec_t &pkt); -//const char *get_rpc_name(int code); - -//------------------------------------------------------------------------- -// rpc_engine_t -//------------------------------------------------------------------------- -#define VERBOSE_ENABLED -#ifdef VERBOSE_ENABLED -#define verb(x) do { if ( verbose ) msg x; } while(0) -#define verb_eng(engine, x) do { if ( (engine)->verbose ) msg x; } while(0) -#else -#define verb(x) //msg x -#define verb_eng(engine, x) -#endif -#define verbev(x) //msg x - -//------------------------------------------------------------------------- -struct rpc_packet_data_t -{ - uchar code; - - rpc_packet_data_t(uchar _code) : code(_code) {} - virtual ~rpc_packet_data_t() {} - virtual void serialize(bytevec_t *out, int version) const = 0; - virtual bool deserialize(const uchar **ptr, size_t len, int version) = 0; -}; - -//------------------------------------------------------------------------- -typedef int ioctl_handler_t( - class rpc_engine_t *rpc, - int fn, - const void *buf, - size_t size, - void **poutbuf, - ssize_t *poutsize); - -//------------------------------------------------------------------------- -typedef rpc_packet_data_t *rpc_packet_instantiator_t(const uchar *ptr, size_t len, int version); - -//------------------------------------------------------------------------- -struct rpc_packet_type_desc_t -{ - uchar code; - const char *name; - rpc_packet_instantiator_t *instantiate; -}; -DECLARE_TYPE_AS_MOVABLE(rpc_packet_type_desc_t); -typedef qvector<rpc_packet_type_desc_t> rpc_packet_type_desc_vec_t; - -//--------------------------------------------------------------------------- -class rpc_engine_t -{ -public: - bool network_error; - - // pointer to the ioctl request handler, in case you - // need to handle ioctl requests from the server. - ioctl_handler_t *ioctl_handler; - int recv_timeout; - bool is_client; - bool logged_in; - -protected: - void register_packet_type_descs(const rpc_packet_type_desc_t *ptypes, size_t cnt); - const rpc_packet_type_desc_t *find_packet_type_desc(int code) const; - const rpc_packet_type_desc_t *find_packet_type_desc(const char *name) const; - -public: - rpc_engine_t(bool is_client); - virtual ~rpc_engine_t() {} - - int handle_ioctl_packet(bytevec_t &pkt, const uchar *ptr, const uchar *end); - - // low-level: deal with bytes, and don't handle "conversations". - int send_data(bytevec_t &data); - rpc_packet_t *recv_packet(); - - virtual rpc_packet_t *send_request_and_receive_reply(bytevec_t &pkt) = 0; - - virtual idarpc_stream_t *get_irs() const = 0; - AS_PRINTF(3, 0) virtual ssize_t send_notif(int code, const char *format, va_list va); - - virtual bool get_broken_connection(void) { return false; } - virtual void set_broken_connection(void) {}; - - int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize); - void set_ioctl_handler(ioctl_handler_t *h) { ioctl_handler = h; } - - DEFINE_ALL_NOTIFICATION_FUNCTIONS(this); - -private: - rpc_packet_type_desc_vec_t ptypes; - - int recv_data(void *out, size_t len); - - AS_PRINTF(3,0) static ssize_t dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va); -}; - -//------------------------------------------------------------------------- -AS_PRINTF(3, 0) ssize_t dvnotif_rpc( - int code, - rpc_engine_t *rpc, - const char *format, - va_list va); - -//--------------------------------------------------------------------------- -AS_PRINTF(1, 0) int vlprintf(const char *format, va_list va); -AS_PRINTF(1, 2) int lprintf(const char *format, ...); -void set_lprintf_output(FILE *out); - -//--------------------------------------------------------------------------- -size_t format_timestamp(char *buf, size_t bufsize, qtime64_t ts); - -#endif // NETWORK_HPP diff --git a/idasdk75/include/offset.hpp b/idasdk75/include/offset.hpp deleted file mode 100644 index d76fefe..0000000 --- a/idasdk75/include/offset.hpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _OFFSET_HPP -#define _OFFSET_HPP - -#include <nalt.hpp> -#include <segment.hpp> - -/*! \file offset.hpp - - \brief Functions that deal with offsets. - - "Being an offset" is a characteristic of an operand. - This means that operand or its part represent offset from - some address in the program. This linear address is called - "offset base". Some operands may have 2 offsets simultaneously. - Generally, IDA doesn't handle this except for Motorola outer offsets. - Thus there may be two offset values in an operand: simple offset and - outer offset. - - Outer offsets are handled by specifying special operand number: - it should be ORed with #OPND_OUTER value. - - See bytes.hpp for further explanation of operand numbers. -*/ - - -/// Get default reference type depending on the segment. -/// \return one of ::REF_OFF8,::REF_OFF16,::REF_OFF32 - -idaman reftype_t ida_export get_default_reftype(ea_t ea); - - -/// Convert operand to a reference. -/// To delete an offset, use clr_op_type() function. -/// \param ea linear address. -/// if 'ea' has unexplored bytes, try to convert them to -/// - no segment: fail -/// - 16bit segment: to 16bit word data -/// - 32bit segment: to dword -/// \param n number of operand (may be ORed with #OPND_OUTER) -/// - 0: first -/// - 1: second -/// - 2: third -/// - #OPND_MASK: all operands -/// \param ri reference information -/// \return success - -idaman bool ida_export op_offset_ex(ea_t ea, int n, const refinfo_t *ri); - - -/// See op_offset_ex() - -idaman bool ida_export op_offset( - ea_t ea, - int n, - reftype_t type, - ea_t target=BADADDR, - ea_t base=0, - adiff_t tdelta=0); - - -/// Convert operand to a reference with the default reference type - -inline bool op_plain_offset(ea_t ea, int n, ea_t base) -{ - reftype_t reftype = get_default_reftype(ea); - return op_offset(ea, n, reftype, BADADDR, base) != 0; -} - - -/// Get offset base value -/// \param ea linear address -/// \param n number of operand -/// \return offset base or #BADADDR - -inline ea_t get_offbase(ea_t ea, int n) -{ - refinfo_t ri; - if ( !get_refinfo(&ri, ea, n) ) - return BADADDR; - return ri.base; -} - - -/// Get offset expression (in the form "offset name+displ"). -/// This function uses offset translation function (\ph{translate}) if your IDP -/// module has such a function. Translation function is used to map linear -/// addresses in the program (only for offsets). -/// -/// Example: suppose we have instruction at linear address 0x00011000: -/// \v{mov ax, [bx+7422h]} -/// and at ds:7422h: -/// \v{array dw ...} -/// We want to represent the second operand with an offset expression, so -/// then we call: -/// \v{ -/// get_offset_expresion(0x001100, 1, 0x001102, 0x7422, buf); -/// | | | | | -/// | | | | +output buffer -/// | | | +value of offset expression -/// | | +address offset value in the instruction -/// | +the second operand -/// +address of instruction -/// } -/// and the function will return a colored string: -/// \v{offset array} -/// \param buf output buffer to hold offset expression -/// \param ea start of instruction or data with the offset expression -/// \param n number of operand (may be ORed with #OPND_OUTER) -/// - 0: first operand -/// - 1: second operand -/// \param from linear address of instruction operand or data referring to -/// the name. This address will be used to get fixup information, -/// so it should point to exact position of operand in the -/// instruction. -/// \param offset value of operand or its part. The function will return -/// text representation of this value as offset expression. -/// \param getn_flags combination of: -/// - #GETN_APPZERO: meaningful only if the name refers to -/// a structure. appends the struct field name -/// if the field offset is zero -/// - #GETN_NODUMMY: do not generate dummy names for the expression -/// but pretend they already exist -/// (useful to verify that the offset expression -/// can be represented) -/// \retval 0 can't convert to offset expression -/// \retval 1 ok, a simple offset expression -/// \retval 2 ok, a complex offset expression - - -idaman int ida_export get_offset_expression( - qstring *buf, - ea_t ea, - int n, - ea_t from, - adiff_t offset, - int getn_flags=0); - - -/// See get_offset_expression() - -idaman int ida_export get_offset_expr( - qstring *buf, - ea_t ea, - int n, - const refinfo_t &ri, - ea_t from, - adiff_t offset, - int getn_flags=0); - - -/// Does the specified address contain a valid OFF32 value?. -/// For symbols in special segments the displacement is not taken into account. -/// If yes, then the target address of OFF32 will be returned. -/// If not, then #BADADDR is returned. - -idaman ea_t ida_export can_be_off32(ea_t ea); - - -/// Try to calculate the offset base -/// This function takes into account the fixup information, -/// current ds and cs values. -/// \param ea the referencing instruction/data address -/// \param n operand number -/// - 0: first operand -/// - 1: other operand -/// \return output base address or #BADADDR - -idaman ea_t ida_export calc_offset_base(ea_t ea, int n); - - -/// Try to calculate the offset base. -/// 2 bases are checked: current ds and cs. -/// If fails, return #BADADDR - -idaman ea_t ida_export calc_probable_base_by_value(ea_t ea, uval_t off); - - -/// Calculate the target and base addresses of an offset expression. -/// The calculated target and base addresses are returned in the locations -/// pointed by 'base' and 'target'. In case 'ri.base' is #BADADDR, the -/// function calculates the offset base address from the referencing -/// instruction/data address. -/// The target address is copied from ri.target. If ri.target is #BADADDR -/// then the target is calculated using the base address and 'opval'. -/// This function also checks if 'opval' matches the full value of the -/// reference and takes in account the memory-mapping. -/// \param target output target address -/// \param base output base address -/// \param from the referencing instruction/data address -/// \param ri reference info block from the database -/// \param opval operand value (usually op_t::value or op_t::addr) -/// \return success -idaman bool ida_export calc_reference_data( - ea_t *target, - ea_t *base, - ea_t from, - const refinfo_t &ri, - adiff_t opval); - - -/// Add xrefs for a reference from the given instruction (\insn_t{ea}). -/// This function creates a cross references to the target and the base. -/// insn_t::add_off_drefs() calls this function to create xrefs for -/// 'offset' operand. -/// \param insn the referencing instruction -/// \param from the referencing instruction/data address -/// \param ri reference info block from the database -/// \param opval operand value (usually op_t::value or op_t::addr) -/// \param type type of xref -/// \param opoff offset of the operand from the start of instruction -/// \return the target address of the reference -idaman ea_t ida_export add_refinfo_dref( - const insn_t &insn, - ea_t from, - const refinfo_t &ri, - adiff_t opval, - dref_t type, - int opoff); - - -/// Calculates the target, using the provided refinfo_t - -inline ea_t calc_target(ea_t from, adiff_t opval, const refinfo_t &ri) -{ - ea_t target; - if ( !calc_reference_data(&target, NULL, from, ri, opval) ) - return BADADDR; - return target; -} - -/// Retrieves refinfo_t structure and calculates the target - -inline ea_t calc_target(ea_t from, ea_t ea, int n, adiff_t opval) -{ - refinfo_t ri; - return get_refinfo(&ri, ea, n) ? calc_target(from, opval, ri) : BADADDR; -} - -/// Calculate the value of the reference base. - -inline ea_t calc_basevalue(ea_t target, ea_t base) -{ - return base - get_segm_base(getseg(target)); -} - - -#endif // _OFFSET_HPP diff --git a/idasdk75/include/parsejson.hpp b/idasdk75/include/parsejson.hpp deleted file mode 100644 index 098eb8c..0000000 --- a/idasdk75/include/parsejson.hpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef PARSEJSON_HPP -#define PARSEJSON_HPP - -/*! \file parsejson.hpp - - \brief Tools for parsing JSON-formatted input - - See also lex.hpp/parse.hpp for finer-grained functions & documentation. -*/ -#include <lex.hpp> - -//--------------------------------------------------------------------------- -enum jtype_t -{ - JT_UNKNOWN = 0, - JT_NUM, - JT_STR, - JT_OBJ, - JT_ARR, - JT_BOOL, -}; - -//--------------------------------------------------------------------------- -struct jobj_t; -struct jarr_t; - -#define DECLARE_JVALUE_HELPERS(decl) \ - decl void ida_export jvalue_t_clear(jvalue_t *); \ - decl void ida_export jvalue_t_copy(jvalue_t *, const jvalue_t &); - - -struct jvalue_t; -DECLARE_JVALUE_HELPERS(idaman) - -//------------------------------------------------------------------------- -struct jvalue_t -{ - jvalue_t() : _type(JT_UNKNOWN), _num(0) {} - jvalue_t(const jvalue_t &o) : _type(JT_UNKNOWN) { jvalue_t_copy(this, o); } - ~jvalue_t() { clear(); } - - void clear() { jvalue_t_clear(this); } - - jvalue_t &operator=(const jvalue_t &o) { jvalue_t_copy(this, o); return *this; } - - jtype_t type() const { return _type; } - int64 num() const { QASSERT(1277, _type == JT_NUM); return _num; } - const char *str() const { QASSERT(1278, _type == JT_STR); return _str->c_str(); } - const qstring &qstr() const { QASSERT(1623, _type == JT_STR); return *_str; } - const jobj_t &obj() const { QASSERT(1279, _type == JT_OBJ); return *_obj; } - const jarr_t &arr() const { QASSERT(1280, _type == JT_ARR); return *_arr; } - bool vbool() const { QASSERT(1281, _type == JT_BOOL); return _bool; } - jobj_t &obj() { QASSERT(1282, _type == JT_OBJ); return *_obj; } - jarr_t &arr() { QASSERT(1283, _type == JT_ARR); return *_arr; } - - //lint -sem(jvalue_t::set_str, custodial(1)) function takes ownership of its argument - //lint -sem(jvalue_t::set_obj, custodial(1)) function takes ownership of its argument - //lint -sem(jvalue_t::set_arr, custodial(1)) function takes ownership of its argument - void set_num(int64 i) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_NUM; _num = i; } - void set_str(qstring *s) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_STR; _str = s; } - void set_obj(jobj_t *o) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_OBJ; _obj = o; } - void set_arr(jarr_t *a) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_ARR; _arr = a; } - void set_bool(bool b) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_BOOL; _bool = b; } - - jobj_t *extract_obj() { QASSERT(1624, _type == JT_OBJ); jobj_t *o = _obj; _obj = NULL; _type = JT_UNKNOWN; return o; } - jarr_t *extract_arr() { QASSERT(1625, _type == JT_ARR); jarr_t *a = _arr; _arr = NULL; _type = JT_UNKNOWN; return a; } - -private: - DECLARE_JVALUE_HELPERS(friend) - - jtype_t _type; - - union - { - int64 _num; - qstring *_str; - jobj_t *_obj; - jarr_t *_arr; - bool _bool; - }; -}; -DECLARE_TYPE_AS_MOVABLE(jvalue_t); -typedef qvector<jvalue_t> jvalues_t; - -//--------------------------------------------------------------------------- -struct kvp_t -{ - qstring key; - jvalue_t value; -}; -DECLARE_TYPE_AS_MOVABLE(kvp_t); - -//------------------------------------------------------------------------- -struct jobj_t : public qvector<kvp_t> -{ - bool has_value(const char *k) const { return get_value(k) != NULL; } - jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN) - { - jvalue_t *v = NULL; - for ( size_t i = 0, _n = size(); i < _n; ++i ) - { - if ( at(i).key == k ) - { - if ( t == JT_UNKNOWN || at(i).value.type() == t ) - v = &at(i).value; - break; - } - } - return v; - } - - const jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN) const - { - return ((jobj_t *) this)->get_value(k, t); - } - - const jvalue_t *get_value_or_fail(const char *k, jtype_t t=JT_UNKNOWN) const - { - const jvalue_t *v = get_value(k, t); - QASSERT(1289, v != NULL); - return v; - } - - jvalue_t *get_value_or_new(const char *key) - { - jvalue_t *v = get_value(key); - if ( v == NULL ) - { - kvp_t &kvp = push_back(); - kvp.key = key; - v = &kvp.value; - } - return v; - } - - int64 get_num(const char *k) const { return get_value_or_fail(k)->num(); } - bool get_bool(const char *k) const { return get_value_or_fail(k)->vbool(); } - const char *get_str(const char *k) const { return get_value_or_fail(k)->str(); } - const jobj_t &get_obj(const char *k) const { return get_value_or_fail(k)->obj(); } - const jarr_t &get_arr(const char *k) const { return get_value_or_fail(k)->arr(); } - -#define DEFINE_FLAG_GETTER(Type, JType, GetExpr) \ - bool get(Type *out, const char *k) const \ - { \ - const jvalue_t *v = get_value(k, JType); \ - bool ok = v != NULL; \ - if ( ok ) \ - *out = GetExpr; \ - return ok; \ - } -#define DEFINE_DFLT_GETTER(Type, JType, GetExpr) \ - Type get(const char *k, Type dflt) const \ - { \ - const jvalue_t *v = get_value(k, JType); \ - return v != NULL ? GetExpr : dflt; \ - } -#define DEFINE_SETTER(Type, SetExpr) \ - void put(const char *key, Type value) \ - { \ - jvalue_t *v = get_value_or_new(key); \ - SetExpr; \ - } -#define DEFINE_ACCESSORS(Type, ConstType, JType, GetExpr, SetExpr) \ - DEFINE_FLAG_GETTER(ConstType, JType, GetExpr) \ - DEFINE_DFLT_GETTER(ConstType, JType, GetExpr) \ - DEFINE_SETTER(Type, SetExpr) - - DEFINE_ACCESSORS(int, int, JT_NUM, v->num(), v->set_num(value)); - DEFINE_ACCESSORS(int64, int64, JT_NUM, v->num(), v->set_num(value)); - DEFINE_ACCESSORS(bool, bool, JT_BOOL, v->vbool(), v->set_bool(value)); - DEFINE_ACCESSORS(jarr_t *, const jarr_t *, JT_ARR, &v->arr(), v->set_arr(value)); // setter takes ownership - DEFINE_ACCESSORS(jobj_t *, const jobj_t *, JT_OBJ, &v->obj(), v->set_obj(value)); // setter takes ownership - DEFINE_ACCESSORS(const char *, const char *, JT_STR, v->str(), v->set_str(new qstring(value))); -#undef DEFINE_ACCESSORS -#undef DEFINE_SETTER -#undef DEFINE_DFLT_GETTER -#undef DEFINE_FLAG_GETTER -}; -DECLARE_TYPE_AS_MOVABLE(jobj_t); - -//--------------------------------------------------------------------------- -struct jarr_t -{ - jvalues_t values; - - size_t count_items_with_type(jtype_t t) const - { - size_t cnt = 0; - for ( size_t i = 0, n = values.size(); i < n; ++i ) - if ( values[i].type() == t ) - ++cnt; - return cnt; - } - - bool is_homogeneous(jtype_t t) const - { - return count_items_with_type(t) == values.size(); - } -}; -DECLARE_TYPE_AS_MOVABLE(jarr_t); - -//--------------------------------------------------------------------------- -// Note: If 'ungot_tokens' is not NULL, its contents will be used before fetching tokens from the lexer -idaman THREAD_SAFE error_t ida_export parse_json(jvalue_t *out, lexer_t *lx, tokenstack_t *ungot_tokens = NULL); -idaman THREAD_SAFE error_t ida_export parse_json_string(jvalue_t *out, const char *s); - -//------------------------------------------------------------------------- -#define SJF_PRETTY 0x1 -idaman THREAD_SAFE bool ida_export serialize_json( - qstring *out, - const jvalue_t &v, - uint32 flags=0); - -inline THREAD_SAFE bool serialize_json( - qstring *out, - const jobj_t *o, - uint32 flags=0) -{ - jvalue_t v; - v.set_obj((jobj_t *) o); - bool rc = serialize_json(out, v, flags); - v.extract_obj(); - return rc; -} - -#endif // PARSEJSON_HPP diff --git a/idasdk75/include/pro.h b/idasdk75/include/pro.h deleted file mode 100644 index 05fbf2f..0000000 --- a/idasdk75/include/pro.h +++ /dev/null @@ -1,4664 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _PRO_H -#define _PRO_H - -/*! \file pro.h - - \brief This is the first header included in the IDA project. - - It defines the most common types, functions and data. - Also, it tries to make system dependent definitions. - - The following preprocessor macros are used in the project - (the list may be incomplete) - - Platform must be specified as one of: - - __NT__ - MS Windows (all platforms) \n - __LINUX__ - Linux \n - __MAC__ - MAC OS X - - __EA64__ - 64-bit address size (sizeof(ea_t)==8) \n - - __X86__ - 32-bit debug servers (sizeof(void*)==4) \n - __X64__ - x64 processor (sizeof(void*)==8) default \n - __PPC__ - PowerPC \n - __ARM__ - ARM -*/ - -/// IDA SDK v7.5 -#define IDA_SDK_VERSION 750 - -//--------------------------------------------------------------------------- -#if !defined(__NT__) && !defined(__LINUX__) && !defined(__MAC__) -# if defined(_MSC_VER) -# define __NT__ -# elif defined(__APPLE__) -# define __MAC__ -# elif defined(__linux__) -# define __LINUX__ -# else -# error "Please define one of: __NT__, __LINUX__, __MAC__" -# endif -#endif - -// Linux or Mac imply Unix -#if defined(__LINUX__) || defined(__MAC__) -#define __UNIX__ -#endif - -/// \def{BADMEMSIZE, Invalid memory size} -#ifndef __X86__ -#define BADMEMSIZE 0x7FFFFFFFFFFFFFFFull -#else -#define BADMEMSIZE 0x7FFFFFFFul -#endif - -/// \def{ENUM_SIZE, Specify size of enum values} -#define ENUM_SIZE(t) : t - -#ifndef SWIG -#include <stdlib.h> /* size_t, NULL, memory */ -#include <stdarg.h> -#include <stddef.h> -#include <stdio.h> -#include <assert.h> -#include <limits.h> -#include <ctype.h> -#include <time.h> -#ifdef __cplusplus -#include <new> -#include <string> -#endif -#if defined(__NT__) -# include <malloc.h> -#endif - -/// \def{WIN32_LEAN_AND_MEAN, compile faster} -#if defined(_MSC_VER) -# define WIN32_LEAN_AND_MEAN -# include <string.h> -# include <io.h> -# include <direct.h> -#ifdef __cplusplus -# include <map> -#endif -#else -#ifdef __cplusplus -# include <algorithm> -#endif -# include <wchar.h> -# include <string.h> -# include <unistd.h> -# include <sys/stat.h> -# include <errno.h> -#endif -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> - -#endif // SWIG - -#define STL_SUPPORT_PRESENT - -//--------------------------------------------------------------------------- -/// \def{EXTERNC, specify C linkage} -/// \def{C_INCLUDE, helper for 'extern "C" {}' statements} -/// \def{C_INCLUDE_END, \copydoc C_INCLUDE} -/// \def{INLINE, inline keyword for c++} -#if defined(__cplusplus) || defined(SWIG) -#define EXTERNC extern "C" -#define C_INCLUDE EXTERNC \ - { - -#define C_INCLUDE_END } -#define INLINE inline -#else -#define EXTERNC -#define C_INCLUDE -#define C_INCLUDE_END -#define INLINE __inline -#endif - -//--------------------------------------------------------------------------- -#ifndef MAXSTR -#define MAXSTR 1024 ///< maximum string size -#endif - -#define SMAXSTR QSTRINGIZE(MAXSTR) ///< get #MAXSTR as a string - -/// \def{NT_CDECL, Some NT functions require __cdecl calling convention} -#ifdef __NT__ -#define NT_CDECL __cdecl -#else -#define NT_CDECL -#endif - -/// \def{DEPRECATED, identifies parts of the IDA API that are considered deprecated} -/// \def{NORETURN, function does not return} -/// \def{PACKED, type is packed} -/// \def{AS_PRINTF, function accepts printf-style format and args} -/// \def{AS_SCANF, function accepts scanf-style format and args} -/// \def{WARN_UNUSED_RESULT, warn if a function returns a result that is never used} -#if defined(SWIG) -#define constexpr -#define DEPRECATED -#define NORETURN -#define PACKED -#define AS_STRFTIME(format_idx) -#define AS_PRINTF(format_idx, varg_idx) -#define AS_SCANF(format_idx, varg_idx) -#define WARN_UNUSED_RESULT -#elif defined(__GNUC__) -#define DEPRECATED __attribute__((deprecated)) -#define NORETURN __attribute__((noreturn)) -#define PACKED __attribute__((__packed__)) -#define AS_STRFTIME(format_idx) __attribute__((format(strftime, format_idx, 0))) -#define AS_PRINTF(format_idx, varg_idx) __attribute__((format(printf, format_idx, varg_idx))) -#define AS_SCANF(format_idx, varg_idx) __attribute__((format(scanf, format_idx, varg_idx))) -#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) -#else -#define DEPRECATED __declspec(deprecated) -#define NORETURN __declspec(noreturn) -#define PACKED -#define AS_STRFTIME(format_idx) -#define AS_PRINTF(format_idx, varg_idx) -#define AS_SCANF(format_idx, varg_idx) -#define WARN_UNUSED_RESULT -#endif - -/// \def{GCC_DIAG_OFF, disable a specific GCC warning for the following code} -/// \def{GCC_DIAG_ON, enable or restore a specific GCC warning for the following code} -#if defined(__GNUC__) && !defined(SWIG) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 -#define GCC_DIAG_JOINSTR(x,y) _QSTRINGIZE(x ## y) -# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x) -# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) -# if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__) -# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \ - GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) -# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop) -# else -# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) -# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(warning GCC_DIAG_JOINSTR(-W,x)) -# endif -#else -# define GCC_DIAG_OFF(x) -# define GCC_DIAG_ON(x) -#endif - -// A function attribute to disable ASAN -#if defined(__clang__) || defined (__GNUC__) -# define DISABLE_ASAN __attribute__((no_sanitize_address)) -#else -# define DISABLE_ASAN -#endif - -#if defined(DONT_DEPRECATE) -#undef DEPRECATED -#define DEPRECATED -#endif - -//--------------------------------------------------------------------------- - -#define __MF__ 0 ///< byte sex of our platform (Most significant byte First). - ///< 0: little endian (Intel 80x86). - ///< 1: big endian (PowerPC). - -//--------------------------------------------------------------------------- -/// Macro to avoid of message 'Parameter x is never used' -#define qnotused(x) (void)x - -#ifdef __clang__ -# define NONNULL _Nonnull -#else -# define NONNULL -#endif - -// this macro can be used as a suffix for declarations/definitions instead of qnotused() -#if defined(__clang__) || defined(__GNUC__) -# define QUNUSED __attribute__((unused)) -#else -# define QUNUSED -#endif - -/// \def{va_argi, GNU C complains about some data types in va_arg because they are promoted to int and proposes to replace them by int} -#ifdef __GNUC__ -#define va_argi(va, type) ((type)va_arg(va, int)) -#else -#define va_argi(va, type) va_arg(va, type) -#endif - -//--------------------------------------------------------------------------- -#define CONST_CAST(x) const_cast<x> ///< cast a const to non-const -#define _QSTRINGIZE(x) #x ///< return x as a string. See #SMAXSTR for example -#define QSTRINGIZE(x) _QSTRINGIZE(x) ///< see #_QSTRINGIZE - -//--------------------------------------------------------------------------- - -/// \def{idaapi, specifies __stdcall calling convention} -/// \def{ida_export, functions marked with this keyword are available as part of the IDA SDK} -/// \def{idaman, specifies c linkage} -/// \def{ida_export_data, data items marked with this keyword are available as part of the IDA SDK} -/// \def{ida_module_data, identifies a data item that will be exported} -/// \def{ida_local, identifies a non-public type definition} -#if defined(SWIG) // for SWIG - #define idaapi - #define idaman - #define ida_export - #define ida_export_data - #define ida_module_data - #define __fastcall - #define ida_local -#elif defined(APIDEF) // for API DEF files - #define idaapi - #define idaman - #define ida_export ida_export - #define ida_export_data ida_export_data - #define ida_module_data - #define __fastcall - #define ida_local -#elif defined(__NT__) // MS Windows - #define idaapi __stdcall - #define ida_export idaapi - #ifdef __CODE_CHECKER__ - // tell lint that this function will be exported - #define idaman EXTERNC __declspec(dllexport) - #else - #define idaman EXTERNC - #endif - #if defined(__KERNEL__) // kernel - #define ida_export_data - #define ida_module_data - #else // modules - #define ida_export_data __declspec(dllimport) - #define ida_module_data __declspec(dllexport) - #endif - #define ida_local -#elif defined(__UNIX__) // for unix - #define idaapi - #if defined(__MAC__) - #define idaman EXTERNC __attribute__((visibility("default"))) - #define ida_local __attribute__((visibility("hidden"))) - #else - #if __GNUC__ >= 4 - #define idaman EXTERNC __attribute__ ((visibility("default"))) - #define ida_local __attribute__((visibility("hidden"))) - #else - #define idaman EXTERNC - #define ida_local - #endif - #endif - #define ida_export - #define ida_export_data - #define ida_module_data - #define __fastcall -#endif - -/// Functions callable from any thread are marked with this keyword -#define THREAD_SAFE - -/// This keyword is used to introduce new virtual functions that do not override -/// any existing virtual function -#define newapi - -//--------------------------------------------------------------------------- -#ifndef __cplusplus -typedef int bool; //-V607 Ownerless typedef -#define false 0 -#define true 1 -#endif - -//--------------------------------------------------------------------------- -// Linux C mode compiler already has these types defined -#if !defined(__LINUX__) || defined(__cplusplus) -typedef unsigned char uchar; ///< unsigned 8 bit value -typedef unsigned short ushort; ///< unsigned 16 bit value -typedef unsigned int uint; ///< unsigned 32 bit value -#endif - -typedef char int8; ///< signed 8 bit value -typedef signed char sint8; ///< signed 8 bit value -typedef unsigned char uint8; ///< unsigned 8 bit value -typedef short int16; ///< signed 16 bit value -typedef unsigned short uint16; ///< unsigned 16 bit value -typedef int int32; ///< signed 32 bit value -typedef unsigned int uint32; ///< unsigned 32 bit value - -#include <llong.hpp> - -typedef longlong int64; ///< signed 64 bit value -typedef ulonglong uint64; ///< unsigned 64 bit value - -/// \fn{int64 qatoll(const char *nptr), Convert string to 64 bit integer} -#if defined(__UNIX__) -INLINE int64 qatoll(const char *nptr) { return atoll(nptr); } -#elif defined(_MSC_VER) -INLINE int64 qatoll(const char *nptr) { return _atoi64(nptr); } -#else -INLINE int64 qatoll(const char *nptr) { return atol(nptr); } -#endif - -// VS2010 lacks strtoull -#ifdef _MSC_VER -#define strtoull _strtoui64 -#endif - -/// \typedef{wchar16_t, 2-byte char} -/// \typedef{wchar32_t, 4-byte char} -#if defined(_MSC_VER) -typedef wchar_t wchar16_t; -typedef uint32 wchar32_t; -#elif defined(__GNUC__) -typedef uint16 wchar16_t; -typedef uint32 wchar32_t; -#endif - -/// Signed size_t - used to check for size overflows when the counter becomes -/// negative. Also signed size_t allows us to signal an error condition using -/// a negative value, for example, as a function return value. -#if !defined(_SSIZE_T_DEFINED) && !defined(__ssize_t_defined) && !defined(__GNUC__) -typedef ptrdiff_t ssize_t; -#endif - -/// \def{FMT_64, compiler-specific printf format specifier for 64-bit numbers} -/// \def{FMT_Z, compiler-specific printf format specifier for size_t} -/// \def{FMT_ZS, compiler-specific printf format specifier for ssize_t} -#if defined(__GNUC__) && !defined(__MINGW32__) - #define FMT_64 "ll" - #define FMT_Z "zu" - #define FMT_ZS "zd" -#elif defined(_MSC_VER) && _MSC_VER >= 1900 - #define FMT_64 "I64" - #define FMT_Z "zu" - #define FMT_ZS "td" -#elif defined(_MSC_VER) || defined(__MINGW32__) - #define FMT_64 "I64" - #ifndef __X86__ - #define FMT_Z "I64u" - #define FMT_ZS "I64d" - #else - #define FMT_Z "u" - #define FMT_ZS "d" - #endif -#elif !defined(SWIG) - #error "unknown compiler" -#endif - -/// \typedef{ea_t, effective address} -/// \typedef{sel_t, segment selector} -/// \typedef{asize_t, memory chunk size} -/// \typedef{adiff_t, address difference} -/// \def{SVAL_MIN, minimum value for an object of type int} -/// \def{SVAL_MAX, maximum value for an object of type int} -/// \def{FMT_EA, format specifier for ::ea_t values} -#ifdef __EA64__ - typedef uint64 ea_t; - typedef uint64 sel_t; - typedef uint64 asize_t; - typedef int64 adiff_t; - #define FMT_EA FMT_64 - #ifdef __GNUC__ - #define SVAL_MIN LLONG_MIN - #define SVAL_MAX LLONG_MAX - #else - #define SVAL_MIN _I64_MIN - #define SVAL_MAX _I64_MAX - #endif -#else - typedef uint32 ea_t; - typedef uint32 sel_t; - typedef uint32 asize_t; - typedef int32 adiff_t; - #define SVAL_MIN INT_MIN - #define SVAL_MAX INT_MAX - #define FMT_EA "" -#endif - -typedef asize_t uval_t; ///< unsigned value used by the processor. - ///< - for 32-bit ::ea_t - ::uint32 - ///< - for 64-bit ::ea_t - ::uint64 -typedef adiff_t sval_t; ///< signed value used by the processor. - ///< - for 32-bit ::ea_t - ::int32 - ///< - for 64-bit ::ea_t - ::int64 - -typedef uint64 ea64_t; ///< 64-bit address, regardless of IDA bitness. - ///< we need this type for interoperability with - ///< debug servers, lumina, etc - -/// Error code (errno) -typedef int error_t; - -typedef uint8 op_dtype_t; - - -#ifdef __cplusplus -#define DEFARG(decl, val) decl = val -#else -#define DEFARG(decl, val) decl -#endif - -#ifndef SWIG -#define BADADDR ea_t(-1) ///< this value is used for 'bad address' -#define BADSEL sel_t(-1) ///< 'bad selector' value -#define BADADDR64 ea64_t(-1ULL) - -//------------------------------------------------------------------------- -// Time related functions - -typedef int32 qtime32_t; ///< we use our own time type because time_t - ///< can be 32-bit or 64-bit depending on the compiler -typedef uint64 qtime64_t; ///< 64-bit time value expressed as seconds and - ///< microseconds since the Epoch - -/// Get the 'seconds since the epoch' part of a qtime64_t - -INLINE THREAD_SAFE uint32 get_secs(qtime64_t t) -{ - return (uint32)(t>>32); -} - - -/// Get the microseconds part of a qtime64_t - -INLINE THREAD_SAFE uint32 get_usecs(qtime64_t t) -{ - return (uint32)(t); -} - - -/// Get a ::qtime64_t instance from a seconds value and microseconds value. -/// \param secs seconds -/// \param usecs microseconds - -INLINE THREAD_SAFE qtime64_t make_qtime64(uint32 secs, DEFARG(int32 usecs,0)) -{ - return ((qtime64_t)(secs) << 32) | usecs; -} - - -/// Converts calendar time into a string. -/// Puts 'wrong timestamp\\n' into the buffer if failed -/// \param buf output buffer -/// \param bufsize size of the output buffer -/// \param t calendar time -/// \return success - -idaman THREAD_SAFE bool ida_export qctime(char *buf, size_t bufsize, qtime32_t t); - - -/// Converts calendar time into a string using Coordinated Universal Time (UTC). -/// Function is equivalent to asctime(gmtime(t)). -/// Puts 'wrong timestamp\\n' into the buffer if failed. -/// \param buf output buffer -/// \param bufsize of the output buffer -/// \param t calendar time -/// \return success - -idaman THREAD_SAFE bool ida_export qctime_utc(char *buf, size_t bufsize, qtime32_t t); - - -/// Converts a time value to a tm structure. -/// \param[out] _tm result -/// \param t local time -/// \returns success - -idaman THREAD_SAFE bool ida_export qlocaltime(struct tm *_tm, qtime32_t t); - - -/// Same as qlocaltime(struct tm *, qtime32_t), but accepts a 64-bit time value - -INLINE THREAD_SAFE bool qlocaltime64(struct tm *_tm, qtime64_t t) -{ - return qlocaltime(_tm, get_secs(t)); -} - - -/// Get string representation of a qtime32_t. -/// Copies into 'buf' the content of 'format', expanding its format specifiers into the -/// corresponding values that represent the time described in 't', with a limit of 'bufsize' characters -/// see http://www.cplusplus.com/reference/ctime/strftime/ for more -/// \param buf output buffer -/// \param bufsize of the output buffer -/// \param format format string -/// \param t time value -/// \return length of the resulting string - -idaman AS_STRFTIME(3) THREAD_SAFE size_t ida_export qstrftime( - char *buf, - size_t bufsize, - const char *format, - qtime32_t t); - - -/// Same as qstrftime(), but accepts a 64-bit time value - -idaman AS_STRFTIME(3) THREAD_SAFE size_t ida_export qstrftime64( - char *buf, - size_t bufsize, - const char *format, - qtime64_t t); - - -/// Suspend execution for given number of milliseconds - -idaman THREAD_SAFE void ida_export qsleep(int milliseconds); - - -/// High resolution timer. -/// On Unix systems, returns current time in nanoseconds. -/// On Windows, returns a high resolution counter (QueryPerformanceCounter) -/// \return stamp in nanoseconds - -idaman THREAD_SAFE uint64 ida_export get_nsec_stamp(void); - -/// Get the current time with microsecond resolution (in fact the resolution -/// is worse on windows) - -idaman THREAD_SAFE qtime64_t ida_export qtime64(void); - - -/// Generate a random buffer. -/// \param[out] buffer pointer to result -/// \param bufsz size of buffer -/// \return success - -idaman THREAD_SAFE bool ida_export gen_rand_buf(void *buffer, size_t bufsz); - - -#define qoff64_t int64 ///< file offset - -/// Describes miscellaneous file attributes -struct qstatbuf -{ - uint64 qst_dev; ///< ID of device containing file - uint32 qst_ino; ///< inode number - uint32 qst_mode; ///< protection - uint32 qst_nlink; ///< number of hard links - uint32 qst_uid; ///< user ID of owner - uint32 qst_gid; ///< group ID of owner - uint64 qst_rdev; ///< device ID (if special file) - qoff64_t qst_size; ///< total size, in bytes - int32 qst_blksize; ///< blocksize for file system I/O - int32 qst_blocks; ///< number of 512B blocks allocated - qtime64_t qst_atime; ///< time of last access - qtime64_t qst_mtime; ///< time of last modification - qtime64_t qst_ctime; ///< time of last status change -}; - -// non standard functions are missing: -#ifdef _MSC_VER -#if _MSC_VER <= 1200 -# define for if(0); else for ///< MSVC <= 1200 is not compliant to the ANSI standard -#else -# pragma warning(disable : 4200) ///< zero-sized array in structure (non accept from cmdline) -# if _MSC_VER >= 1921 && _MSC_VER < 1924 // avoid compiler bug: -# pragma function(memmove) // https://developercommunity.visualstudio.com/content/problem/583227/vs-2019-cl-1921277022-memmove-instrinsic-optimizat.html -# endif -#endif -/// \name VS posix names -/// Shut up Visual Studio (VS deprecated posix names but there seems to be no good reason for that) -//@{ -#define chdir _chdir -#define fileno _fileno -#define getcwd _getcwd -#define memicmp _memicmp -# define F_OK 0 -# define W_OK 2 -# define R_OK 4 -//@} -#endif - -/// Is this IDA kernel? If not, we are executing a standalone application -idaman bool ida_export_data is_ida_kernel; - -//--------------------------------------------------------------------------- -/* error codes */ -/*--------------------------------------------------*/ - -#define eOk 0 ///< no error -#define eOS 1 ///< os error, see errno -#define eDiskFull 2 ///< disk full -#define eReadError 3 ///< read error -#define eFileTooLarge 4 ///< file too large - - -/// Set qerrno - -idaman THREAD_SAFE error_t ida_export set_qerrno(error_t code); - - -/// Get qerrno - -idaman THREAD_SAFE error_t ida_export get_qerrno(void); - -//--------------------------------------------------------------------------- -// debugging macros -/// \def{ZZZ, debug print} -/// \def{BPT, trigger a breakpoint from IDA. also see #INTERR} -#define ZZZ msg("%s:%d\n", __FILE__, __LINE__) -#if defined(__GNUC__) -# define BPT __builtin_trap() -#elif defined(_MSC_VER) // Visual C++ -# define BPT __debugbreak() -# ifdef __CODE_CHECKER__ - NORETURN void __debugbreak(void); -# endif -#endif - -/// \def{CASSERT, results in a compile error if the cnd is not true} -#ifdef __CODE_CHECKER__ -#define CASSERT(cnd) extern int pclint_cassert_dummy_var -#else -#define CASSERT(cnd) static_assert((cnd), QSTRINGIZE(cnd)) -#endif - -/// \def{INTERR, Show internal error message and terminate execution abnormally. -/// When IDA is being run under a debugger this will ensure that -/// the debugger will break immediately.} -#ifdef __CODE_CHECKER__ -#define INTERR(code) interr(code) -#else -#define INTERR(code) do { if ( under_debugger ) BPT; interr(code); } while(1) -#endif - -#define QASSERT(code, cond) do if ( !(cond) ) INTERR(code); while (0) ///< run time assertion -#define QBUFCHECK(buf, size, src) ida_fill_buffer(buf, size, src, __FILE__, __LINE__) ///< run time assertion -idaman bool ida_export_data under_debugger; ///< is IDA running under a debugger? - -#define INTERR_EXC_FMT "Internal error %d occurred when running a script. Either\n" \ - " - the script misused the IDA API, or\n" \ - " - there is a logic error in IDA\n" \ - "Please check the script first.\n" \ - "If it appears correct, send a bug report to <support@hex-rays.com>.\n" \ - "In any case we strongly recommend you to restart IDA as soon as possible." - -#ifdef __cplusplus -struct interr_exc_t : public std::exception -{ - int code; - interr_exc_t(int _code) : code(_code) {} -}; -#endif // __cplusplus -idaman THREAD_SAFE NORETURN void ida_export interr(int code); ///< Show internal error message and terminate execution - -// Should an 'interr()' throw an 'interr_exc_t' instance, -// or terminate IDA (the default)? -idaman bool ida_export_data interr_should_throw; - -//--------------------------------------------------------------------------- -idaman THREAD_SAFE void *ida_export qalloc(size_t size); ///< System independent malloc -idaman THREAD_SAFE void *ida_export qrealloc(void *alloc, size_t newsize); ///< System independent realloc -idaman THREAD_SAFE void *ida_export qcalloc(size_t nitems, size_t itemsize); ///< System independent calloc -idaman THREAD_SAFE void ida_export qfree(void *alloc); ///< System independent free -idaman THREAD_SAFE char *ida_export qstrdup(const char *string); ///< System independent strdup -#define qnew(t) ((t*)qalloc(sizeof(t))) ///< create a new object in memory -/// \def{qnewarray, qalloc_array() is safer than qnewarray} -#define qnewarray(t,n) use_qalloc_array - -/// Use this class to avoid integer overflows when allocating arrays -#ifdef __cplusplus -template <class T> -T *qalloc_array(size_t n) -{ - return (T *)qcalloc(n, sizeof(T)); -} - -/// Use this class to avoid integer overflows when allocating arrays -template <class T> -T *qrealloc_array(T *ptr, size_t n) -{ - size_t nbytes = n * sizeof(T); - if ( nbytes < n ) - return NULL; // integer overflow - return (T *)qrealloc(ptr, nbytes); -} - -/// \def{qnumber, determine capacity of an array} -#ifdef __GNUC__ -# define qnumber(arr) ( \ - 0 * sizeof(reinterpret_cast<const ::qnumber_check_type *>(arr)) \ - + 0 * sizeof(::qnumber_check_type::check_type((arr), &(arr))) \ - + sizeof(arr) / sizeof((arr)[0]) ) - struct qnumber_check_type - { - struct is_pointer; - struct is_array {}; - template <typename T> - static is_pointer check_type(const T *, const T *const *); - static is_array check_type(const void *, const void *); - }; -#elif defined(_MSC_VER) && !defined(__CODE_CHECKER__) -# define qnumber(array) _countof(array) -#else // poor man's implementation for other compilers and lint -# define qnumber(array) (sizeof(array)/sizeof(array[0])) -#endif -#endif //__cplusplus - -#define qoffsetof offsetof - -/// \def{set_vva, extracts a va_list passed as a variadic function argument} -/// \def{va_copy, copy a va_list} -#if defined(__GNUC__) && !defined(__X86__) - // gcc64 uses special array-type va_list, so we have to resort to tricks like these - #define set_vva(va2, vp) va_copy(va2, *(va_list*)va_arg(vp, void*)) -#else - #ifndef va_copy - #define va_copy(dst, src) dst = src - #endif - #if defined(__clang__) - #define set_vva(va2, vp) va2 = va_arg(vp, va_list) - #else - #define set_vva(va2, vp) va_copy(va2, va_arg(vp, va_list)) - #endif -#endif - - -/// Reverse memory block. -/// Analog of strrev() function -/// \param buf pointer to buffer to reverse -/// \param size size of buffer -/// \return pointer to buffer - -idaman THREAD_SAFE void *ida_export memrev(void *buf, ssize_t size); - -#if defined(__GNUC__) && !defined(_WIN32) -idaman THREAD_SAFE int ida_export memicmp(const void *x, const void *y, size_t size); -#endif - -//--------------------------------------------------------------------------- -/* strings */ -/// \def{strnicmp, see 'VS posix names'} -/// \def{stricmp, see 'VS posix names'} -#ifdef __GNUC__ -#define strnicmp strncasecmp -#define stricmp strcasecmp -#elif defined(_MSC_VER) -#define strnicmp _strnicmp -#define stricmp _stricmp -#endif - - -/// Replace all occurrences of a character within a string. -/// \param str to modify -/// \param char1 char to be replaced -/// \param char2 replacement char -/// \return pointer to resulting string - -idaman THREAD_SAFE char *ida_export strrpl(char *str, int char1, int char2); - - -/// Get tail of a string -INLINE THREAD_SAFE char *tail(char *str) { return strchr(str, '\0'); } -#ifdef __cplusplus -/// \copydoc tail(char *) -inline THREAD_SAFE const char *tail(const char *str) { return strchr(str, '\0'); } -#endif - - -/// A safer strncpy - makes sure that there is a terminating zero. -/// nb: this function doesn't fill the whole buffer zeroes as strncpy does -/// nb: ssize_t(dstsize) must be > 0 - -idaman THREAD_SAFE char *ida_export qstrncpy(char *dst, const char *src, size_t dstsize); - - -/// A safer stpncpy - returns pointer to the end of the destination -/// nb: ssize_t(dstsize) must be > 0 - -idaman THREAD_SAFE char *ida_export qstpncpy(char *dst, const char *src, size_t dstsize); - - -/// A safer strncat - accepts the size of the 'dst' as 'dstsize' and returns dst -/// nb: ssize_t(dstsize) must be > 0 - -idaman THREAD_SAFE char *ida_export qstrncat(char *dst, const char *src, size_t dstsize); - - -/// Thread-safe version of strtok - -idaman THREAD_SAFE char *ida_export qstrtok(char *s, const char *delim, char **save_ptr); - - -/// Convert the string to lowercase - -idaman THREAD_SAFE char *ida_export qstrlwr(char *str); - - -/// Convert the string to uppercase - -idaman THREAD_SAFE char *ida_export qstrupr(char *str); - - -/// Find one string in another (Case insensitive analog of strstr()). -/// \param s1 string to be searched -/// \param s2 string to search for -/// \return a pointer to the first occurrence of s2 within s1, NULL if none exists - -idaman THREAD_SAFE const char *ida_export stristr(const char *s1, const char *s2); - - -#ifdef __cplusplus -/// Same as stristr(const char *, const char *) but returns a non-const result -inline char *idaapi stristr(char *s1, const char *s2) { return CONST_CAST(char *)(stristr((const char *)s1, s2)); } -#endif - -/// \defgroup ctype Functions to test ASCII char attributes -/// The is...() functions in ctype.h will misbehave with 'char' argument. We introduce more robust functions. -/// These functions only operate on ascii chars and are intended to be locale-independent. -//@{ -INLINE THREAD_SAFE bool ida_local qisascii(char c) { return (c & ~0x7f) == 0; } -INLINE THREAD_SAFE bool ida_local qisspace(char c) { return qisascii(c) && isspace((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qisalpha(char c) { return qisascii(c) && isalpha((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qisalnum(char c) { return qisascii(c) && isalnum((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qispunct(char c) { return qisascii(c) && ispunct((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qislower(char c) { return qisascii(c) && islower((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qisupper(char c) { return qisascii(c) && isupper((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qisprint(char c) { return qisascii(c) && isprint((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qisdigit(char c) { return qisascii(c) && isdigit((uchar)(c)) != 0; } -INLINE THREAD_SAFE bool ida_local qisxdigit(char c) { return qisascii(c) && isxdigit((uchar)(c)) != 0; } -//@} - -/// Get lowercase equivalent of given char -INLINE THREAD_SAFE int ida_local qtolower(char c) { return tolower((uchar)(c)); } -/// Get uppercase equivalent of given char -INLINE THREAD_SAFE int ida_local qtoupper(char c) { return toupper((uchar)(c)); } - -// We forbid using dangerous functions in IDA -#if !defined(USE_DANGEROUS_FUNCTIONS) && !defined(__CODE_CHECKER__) -#undef strcpy -#define strcpy dont_use_strcpy ///< use qstrncpy() -#define stpcpy dont_use_stpcpy ///< use qstpncpy() -#define strncpy dont_use_strncpy ///< use qstrncpy() -#define strcat dont_use_strcat ///< use qstrncat() -#define strncat dont_use_strncat ///< use qstrncat() -#define gets dont_use_gets ///< use qfgets() -#define sprintf dont_use_sprintf ///< use qsnprintf() -#define snprintf dont_use_snprintf ///< use qsnprintf() -#define wsprintfA dont_use_wsprintf ///< use qsnprintf() -#undef strcmpi -#undef strncmpi -#define strcmpi dont_use_strcmpi ///< use stricmp() -#define strncmpi dont_use_strncmpi ///< use strnicmp() -#define getenv dont_use_getenv ///< use qgetenv() -#define setenv dont_use_setenv ///< use qsetenv() -#define putenv dont_use_putenv ///< use qsetenv() -#define strtok dont_use_strrok ///< use qstrtok() -#undef strlwr -#undef strupr -#define strlwr dont_use_strlwr ///< use qstrlwr() -#define strupr dont_use_strupr ///< use qstrupr() -#define waitid dont_use_waitid ///< use qwait() -#define waitpid dont_use_waitpid ///< use qwait() -#define wait dont_use_wait ///< use qwait() -#endif - -//--------------------------------------------------------------------------- -#define streq(s1, s2) (strcmp((s1), (s2)) == 0) ///< convenient check for string equality -#define strieq(s1, s2) (stricmp((s1), (s2)) == 0) ///< see #streq -#define strneq(s1, s2, count) (strncmp((s1), (s2), (count)) == 0) ///< see #streq -#define strnieq(s1, s2, count) (strnicmp((s1), (s2), (count)) == 0) ///< see #streq - -//--------------------------------------------------------------------------- -/// \defgroup qsnprintf qsnprintf/qsscanf -/// safer versions of sprintf/sscanf -/// -/// Our definitions of sprintf-like functions support one additional format specifier -/// -/// "%a" which corresponds to ::ea_t -/// -/// Usual optional fields like the width can be used too: %04a. -/// The width specifier will be doubled for 64-bit version. -/// These function return the number of characters _actually written_ to the output string. -/// excluding the terminating zero. (which is different from the snprintf). -/// They always terminate the output with a zero byte (if n > 0). -//@{ -idaman AS_PRINTF(3, 4) THREAD_SAFE int ida_export qsnprintf(char *buffer, size_t n, const char *format, ...); ///< A safer snprintf -idaman AS_SCANF (2, 3) THREAD_SAFE int ida_export qsscanf(const char *input, const char *format, ...); ///< A safer sscanf -idaman AS_PRINTF(3, 0) THREAD_SAFE int ida_export qvsnprintf(char *buffer, size_t n, const char *format, va_list va); ///< See qsnprintf() -idaman AS_SCANF (2, 0) THREAD_SAFE int ida_export qvsscanf(const char *input, const char *format, va_list va); ///< See qsscanf() -idaman AS_PRINTF(3, 4) THREAD_SAFE int ida_export append_snprintf(char *buf, const char *end, const char *format, ...); ///< Append result of sprintf to 'buf' -//@} - -//--------------------------------------------------------------------------- -/// qsnprintf that does not check its arguments. -/// Normally gcc complains about the non-literal formats. However, sometimes we -/// still need to call qsnprintf with a dynamically built format string. -/// OTOH, there are absolutely no checks of the input arguments, so be careful! -GCC_DIAG_OFF(format-nonliteral); -INLINE int nowarn_qsnprintf(char *buf, size_t size, const char *format, ...) -{ - va_list va; - int code; - va_start(va, format); -#ifdef __cplusplus - code = ::qvsnprintf(buf, size, format, va); -#else - code = qvsnprintf(buf, size, format, va); -#endif - va_end(va); - return code; -} -GCC_DIAG_ON(format-nonliteral); - -//--------------------------------------------------------------------------- -/// \def{QMAXPATH, maximum number of characters in a path specification} -/// \def{QMAXFILE, maximum number of characters in a filename specification} -#if defined(__NT__) -#define QMAXPATH 260 -#define QMAXFILE 260 -#else -#define QMAXPATH PATH_MAX -#define QMAXFILE PATH_MAX -#endif - -idaman THREAD_SAFE char *ida_export vqmakepath(char *buf, size_t bufsize, const char *s1, va_list); ///< See qmakepath() - - -/// Construct a path from a null-terminated sequence of strings. -/// \param buf output buffer. Can be == s1, but must not be NULL -/// \param bufsize size of buffer -/// \return pointer to result - -idaman THREAD_SAFE char *ida_export qmakepath(char *buf, size_t bufsize, const char *s1, ...); - - -/// Get the current working directory. -/// \param buf output buffer -/// \param bufsize size of buffer -/// This function calls error() if any problem occurs. - -idaman void ida_export qgetcwd(char *buf, size_t bufsize); - - -/// Change the current working directory. -/// \param path the new directory -/// The possible return values are the same as those of the POSIX 'chdir' - -idaman int ida_export qchdir(const char *path); - - -/// Get the directory part of the path. -/// path and buf may point to the same buffer -/// \param[out] buf buffer for the directory part. can be NULL. -/// \param[out] bufsize size of this buffer -/// \param path path to split -/// \retval true ok -/// \retval false input buffer did not have the directory part. -/// In this case the buffer is filled with "." - -idaman THREAD_SAFE bool ida_export qdirname(char *buf, size_t bufsize, const char *path); - - -/// Construct filename from base name and extension. -/// \param buf output buffer. Can be == base, but must not be NULL -/// \param bufsize size of buffer -/// \param base base name -/// \param ext extension -/// \return pointer to result - -idaman THREAD_SAFE char *ida_export qmakefile( - char *buf, - size_t bufsize, - const char *base, - const char *ext); - - -/// Split filename into base name and extension. -/// \param file filename, may be changed -/// \param base filled with base part, can be NULL -/// \param ext filled with extension part, can be NULL -/// \return the base part - -idaman THREAD_SAFE char *ida_export qsplitfile(char *file, char **base, char **ext); - - -/// Is the file name absolute (not relative to the current dir?) - -idaman THREAD_SAFE bool ida_export qisabspath(const char *file); - - -/// Get the file name part of the given path. -/// \return NULL if path is NULL - -idaman THREAD_SAFE const char *ida_export qbasename(const char *path); - -#ifdef __cplusplus -/// Same as qbasename(const char *), but accepts and returns non-const char pointers -inline char *qbasename(char *path) { return CONST_CAST(char *)(qbasename((const char *)path)); } -#endif - - -/// Convert relative path to absolute path - -idaman THREAD_SAFE char *ida_export qmake_full_path(char *dst, size_t dstsize, const char *src); - - -/// Search for a file in the PATH environment variable or the current directory. -/// \param buf output buffer to hold the full file path -/// \param bufsize output buffer size -/// \param file the file name to look for. If the file is an absolute path -/// then buf will return the file value. -/// \param search_cwd search the current directory if file was not found in the PATH -/// \return true if the file was found and false otherwise - -idaman THREAD_SAFE bool ida_export search_path( - char *buf, - size_t bufsize, - const char *file, - bool search_cwd); - -/// Delimiter of directory lists -#if defined(__UNIX__) -#define DELIMITER ":" ///< for Unix - ';' for Windows -#else -#define DELIMITER ";" ///< for MS DOS, Windows, other systems - ':' for Unix -#endif - - -/// Set file name extension unconditionally. -/// \param outbuf buffer to hold the answer. may be the same -/// as the file name. -/// \param bufsize output buffer size -/// \param file the file name -/// \param ext new extension (with or without '.') -/// \return pointer to the new file name - -idaman THREAD_SAFE char *ida_export set_file_ext( - char *outbuf, - size_t bufsize, - const char *file, - const char *ext); - - -/// Get pointer to extension of file name. -/// \param file filename -/// \return pointer to the file extension or NULL if extension doesn't exist - -idaman THREAD_SAFE const char *ida_export get_file_ext(const char *file); - -/// Does the given file name have an extension? -#ifdef __cplusplus -inline THREAD_SAFE bool idaapi has_file_ext(const char *file) - { return get_file_ext(file) != NULL; } -#endif - - -/// Set file name extension if none exists. -/// This function appends the extension to a file name. -/// It won't change file name if extension already exists -/// \param buf output buffer -/// \param bufsize size of the output buffer -/// \param file file name -/// \param ext extension (with or without '.') -/// \return pointer to the new file name - -#ifdef __cplusplus -inline THREAD_SAFE char *idaapi make_file_ext( - char *buf, - size_t bufsize, - const char *file, - const char *ext) -{ - if ( has_file_ext(file) ) - return ::qstrncpy(buf, file, bufsize); - else - return set_file_ext(buf, bufsize, file, ext); -} -#endif - - -/// Sanitize the file name. -/// Remove the directory path, and replace wildcards ? * and chars<' ' with _. -/// If the file name is empty, then: -/// - namesize != 0: generate a new temporary name, return true -/// - namesize == 0: return false - -idaman THREAD_SAFE bool ida_export sanitize_file_name(char *name, size_t namesize); - -//--------------------------------------------------------------------------- -/* input/output */ -/*--------------------------------------------------*/ -#if !defined(__NT__) && !defined(_MSC_VER) -#define O_BINARY 0 -#endif - -#ifndef SEEK_SET -# define SEEK_SET 0 ///< beginning of file -# define SEEK_CUR 1 ///< current position of the file * -# define SEEK_END 2 ///< end of file * -#endif - -/*--------------------------------------------------*/ -/* you should use these functions for file i/o */ - - -/// Works the same as it's counterpart from Clib. -/// The only difference is that it sets 'qerrno' variable too - -idaman THREAD_SAFE int ida_export qopen(const char *file, int mode); - - -/// Open file with given sharing_mode (use O_RDONLY, O_WRONLY, O_RDWR flags), sets qerrno - -idaman THREAD_SAFE int ida_export qopen_shared(const char *file, int mode, int share_mode); - - -/// Create new file with O_RDWR, sets qerrno - -idaman THREAD_SAFE int ida_export qcreate(const char *file, int stat); - -idaman THREAD_SAFE int ida_export qread(int h, void *buf, size_t n); ///< \copydoc qopen -idaman THREAD_SAFE int ida_export qwrite(int h, const void *buf, size_t n); ///< \copydoc qopen -idaman THREAD_SAFE qoff64_t ida_export qtell(int h); ///< \copydoc qopen -idaman THREAD_SAFE qoff64_t ida_export qseek(int h, int64 offset, int whence); ///< \copydoc qopen -idaman THREAD_SAFE int ida_export qclose(int h); ///< \copydoc qopen -idaman THREAD_SAFE int ida_export qdup(int h); ///< \copydoc qopen -idaman THREAD_SAFE int ida_export qfsync(int h); ///< \copydoc qopen - - -/// Get the file size. -/// This function may return 0 if the file is not found. - -idaman THREAD_SAFE uint64 ida_export qfilesize(const char *fname); - -/// Get file length in bytes. -/// \param h file descriptor -/// \return file length in bytes, -1 if error - -idaman THREAD_SAFE uint64 ida_export qfilelength(int h); - -/// Change file size. -/// \param h file descriptor -/// \param fsize desired size -/// \retval 0 on success -/// \retval -1 otherwise and qerrno is set - -idaman THREAD_SAFE int ida_export qchsize(int h, uint64 fsize); - -/// Create an empty directory. -/// \param file name (or full path) of directory to be created -/// \param mode permissions (only used on unix systems) -/// \return 0 success -/// \return -1 otherwise and qerrno is set - -idaman THREAD_SAFE int ida_export qmkdir(const char *file, int mode); - -/// Delete a directory. -/// \param file name (or full path) of directory to be removed -/// \return 0 success -/// \return -1 otherwise and qerrno is set - -idaman THREAD_SAFE int ida_export qrmdir(const char *file); - -/// Does the given file exist? - -idaman THREAD_SAFE bool ida_export qfileexist(const char *file); - - -/// Does the given path specify a directory? - -idaman THREAD_SAFE bool ida_export qisdir(const char *file); - -/// Get file status -idaman THREAD_SAFE int ida_export qstat(const char *path, struct qstatbuf *buf); -idaman THREAD_SAFE int ida_export qfstat(int fd, struct qstatbuf *buf); - -//--------------------------------------------------------------------------- -/// Add a function to be called at exit time - -idaman THREAD_SAFE void ida_export qatexit(void (idaapi *func)(void)); - - -/// Remove a previously added exit-time function - -idaman THREAD_SAFE void ida_export del_qatexit(void (idaapi*func)(void)); - -#endif // SWIG - - -/// Call qatexit functions, shut down UI and kernel, and exit. -/// \param code exit code - -idaman THREAD_SAFE NORETURN void ida_export qexit(int code); - -//--------------------------------------------------------------------------- -#define qmin(a,b) ((a) < (b)? (a): (b)) ///< universal min -#define qmax(a,b) ((a) > (b)? (a): (b)) ///< universal max -#ifdef __cplusplus -template <class T> T qabs(T x) { return x < 0 ? -x : x; } -#else -int qabs(int x) { return x < 0 ? -x : x; } -#endif - -//---------------------------------------------------------------------- -/// Test if 'bit' is set in 'bitmap' -INLINE THREAD_SAFE bool idaapi test_bit(const uchar *bitmap, size_t bit) -{ - return (bitmap[bit/8] & (1<<(bit&7))) != 0; -} -/// Set 'bit' in 'bitmap' -INLINE THREAD_SAFE void idaapi set_bit(uchar *bitmap, size_t bit) -{ - uchar *p = bitmap + bit/8; - *p = (uchar)(*p | (1<<(bit&7))); -} -/// Clear 'bit' in 'bitmap' -INLINE THREAD_SAFE void idaapi clear_bit(uchar *bitmap, size_t bit) -{ - uchar *p = bitmap + bit/8; - *p = (uchar)(*p & ~(1<<(bit&7))); -} -/// Set bits between [low, high) in 'bitmap' -INLINE THREAD_SAFE void idaapi set_bits(uchar *bitmap, size_t low, size_t high) -{ - size_t bit; - for ( bit = low; bit < high; ++bit ) - set_bit(bitmap, bit); -} -/// Clear bits between [low, high) in 'bitmap' -INLINE THREAD_SAFE void idaapi clear_bits(uchar *bitmap, size_t low, size_t high) -{ - size_t bit; - for ( bit = low; bit < high; ++bit ) - clear_bit(bitmap, bit); -} -/// Set first 'nbits' of 'bitmap' -INLINE THREAD_SAFE void idaapi set_all_bits(uchar *bitmap, size_t nbits) -{ - memset(bitmap, 0xFF, (nbits+7)/8); - if ( (nbits & 7) != 0 ) - { - uchar *p = bitmap + nbits/8; - *p = (uchar)(*p & ~((1 << (nbits&7))-1)); - } -} -/// Clear first 'nbits' of 'bitmap' -INLINE THREAD_SAFE void idaapi clear_all_bits(uchar *bitmap, size_t nbits) -{ - memset(bitmap, 0, (nbits+7)/8); -} - -/// calculate ceil(log2(d64)) or floor(log2(d64)), -/// it returns 0 if d64 == 0 -idaman int ida_export log2ceil(uint64 d64); -idaman int ida_export log2floor(uint64 d64); - -/// calculate number of set bits (the population count) -idaman int ida_export bitcount(uint64 x); - -/// round up or down to a power of 2 -idaman uint32 ida_export round_up_power2(uint32 x); -idaman uint32 ida_export round_down_power2(uint32 x); - -#ifdef __cplusplus -//---------------------------------------------------------------------- -/// Functions to work with intervals -namespace interval -{ - /// max offset of the interval (assume s != 0) - inline THREAD_SAFE uval_t last(uval_t off, asize_t s) - { - return off + s - 1; - } - /// Do (off1,s1) and (off2,s2) overlap? - inline THREAD_SAFE bool overlap(uval_t off1, asize_t s1, uval_t off2, asize_t s2) - { - return s1 != 0 && s2 != 0 && off2 <= last(off1, s1) && off1 <= last(off2, s2); - } - /// Does (off1,s1) include (off2,s2)? - inline THREAD_SAFE bool includes(uval_t off1, asize_t s1, uval_t off2, asize_t s2) - { - return s1 != 0 && off2 >= off1 && last(off2, s2) <= last(off1, s1); - } - /// Does (off1,s1) contain off? - inline THREAD_SAFE bool contains(uval_t off1, asize_t s1, uval_t off) - { - return s1 != 0 && off >= off1 && off <= last(off1, s1); - } -} -#endif - -//---------------------------------------------------------------------- -#ifdef __cplusplus -/// Shift by the amount exceeding the operand size*8 is undefined by the standard. -/// Indeed, GNUC may decide not to rotate the operand in some cases. -/// We have to check this manually. -template <class T> T left_shift(const T &value, int shift) -{ - return shift >= sizeof(T)*8 ? 0 : (value << shift); -} -/// \copydoc left_shift -template <class T> T right_ushift(const T &value, int shift) -{ - return shift >= sizeof(T)*8 ? 0 : (value >> shift); -} -/// \copydoc left_shift -template <class T> T right_sshift(const T &value, int shift) -{ - return shift >= sizeof(T)*8 ? (value >= 0 ? 0 : -1) : (value >> shift); -} - -/// Rotate left -template<class T> T qrotl(T value, size_t count) -{ - const size_t nbits = sizeof(T) * 8; - count %= nbits; - - T high = value >> (nbits - count); - value <<= count; - value |= high; - return value; -} - -/// Rotate right -template<class T> T qrotr(T value, size_t count) -{ - const size_t nbits = sizeof(T) * 8; - count %= nbits; - - T low = value << (nbits - count); - value >>= count; - value |= low; - return value; -} - -/// Make a mask of 'count' bits -template <class T> T make_mask(int count) -{ - return left_shift<T>(1, count) - 1; -} - -/// Set a 'bit' in 'where' if 'value' if not zero -template<class T, class U> void idaapi setflag(T &where, U bit, bool cnd) -{ - if ( cnd ) - where = T(where | bit); - else - where = T(where & ~T(bit)); -} - -/// Check that unsigned multiplication does not overflow -template<class T> bool is_mul_ok(T count, T elsize) -{ - CASSERT((T)(-1) > 0); // make sure T is unsigned - if ( elsize == 0 || count == 0 ) - return true; - return count <= ((T)(-1)) / elsize; -} - -/// Check that unsigned or unsigned+signed addition does not overflow -template<class U, class T> bool is_add_ok(U x, T y) -{ - CASSERT((U)(-1) > 0); // make sure U is unsigned - return y >= 0 ? y <= ((U)(-1)) - x : -y <= x; -} - -/// \def{OPERATOR_NEW, GCC does not check for an integer overflow in 'operator new[]'. We have to do it -/// ourselves. Please note that 'char' arrays can still be allocated with -/// plain 'operator new'.} -#ifdef __GNUC__ -# define OPERATOR_NEW(type, count) (is_mul_ok(size_t(count), sizeof(type)) \ - ? new type[count] \ - : (type *)qalloc_or_throw(BADMEMSIZE)) -#else -# define OPERATOR_NEW(type, count) new type[count] -#endif - -#endif // __cplusplus - -//------------------------------------------------------------------------- -/// Sign-, or zero-extend the value 'v' to occupy 64 bits. -/// The value 'v' is considered to be of size 'nbytes'. - -idaman uint64 ida_export extend_sign(uint64 v, int nbytes, bool sign_extend); - - -/// We cannot use multi-character constants because they are not portable - use this macro instead -#define MC2(c1, c2) ushort(((c2)<<8)|c1) -#define MC3(c1, c2, c3) uint32(((((c3)<<8)|(c2))<<8)|c1) ///< \copydoc MC2 -#define MC4(c1, c2, c3, c4) uint32(((((((c4)<<8)|(c3))<<8)|(c2))<<8)|c1) ///< \copydoc MC2 - - -//--------------------------------------------------------------------------- -/// Read at most 4 bytes from file. -/// \param h file handle -/// \param res value read from file -/// \param size size of value in bytes (1,2,4) -/// \param mf is MSB first? -/// \return 0 on success, nonzero otherwise - -idaman THREAD_SAFE int ida_export readbytes(int h, uint32 *res, int size, bool mf); - - -/// Write at most 4 bytes to file. -/// \param h file handle -/// \param l value to write -/// \param size size of value in bytes (1,2,4) -/// \param mf is MSB first? -/// \return 0 on success, nonzero otherwise - -idaman THREAD_SAFE int ida_export writebytes(int h, uint32 l, int size, bool mf); - - -/// Read a 2 byte entity from a file. -/// \param h file handle -/// \param res value read from file -/// \param mf is MSB first? -/// \return 0 on success, nonzero otherwise - -idaman THREAD_SAFE int ida_export read2bytes(int h, uint16 *res, bool mf); - -#define read4bytes(h, res, mf) readbytes(h, res, 4, mf) ///< see readbytes() -#define write2bytes(h, l, mf) writebytes(h, l, 2, mf) ///< see writebytes() -#define write4bytes(h, l, mf) writebytes(h, l, 4, mf) ///< see writebytes() - -//--------------------------------------------------------------------------- -/// \fn{uint32 swap32(uint32 x), Switch endianness of given value} -/// \fn{ushort swap16(ushort x), \copydoc swap32} -/// \def{swap32, Switch endianness of given value} -/// \def{swap16, \copydoc swap32} -#ifdef __cplusplus -# ifndef swap32 -inline THREAD_SAFE uint32 swap32(uint32 x) - { return (x>>24) | (x<<24) | ((x>>8) & 0x0000FF00L) | ((x<<8) & 0x00FF0000L); } -# endif -# ifndef swap16 -inline THREAD_SAFE ushort swap16(ushort x) - { return ushort((x<<8) | (x>>8)); } -# endif -#else -# ifndef swap32 -# define swap32(x) uint32((x>>24) | (x<<24) | ((x>>8) & 0x0000FF00L) | ((x<<8) & 0x00FF0000L)) -# endif -# ifndef swap16 -# define swap16(x) ushort((x<<8) | (x>>8)) -# endif -#endif - -/// \def{swapea, Switch endianness of an ::ea_t value} -#ifdef __EA64__ -#define swapea swap64 -#else -#define swapea swap32 -#endif - -/// \def{qhtons, \copydoc swap32} -/// \def{qntohs, \copydoc swap32} -/// \def{qhtonl, \copydoc swap32} -/// \def{qntohl, \copydoc swap32} -#if __MF__ -#define qhtonl(x) (x) -#define qntohl(x) (x) -#define qhtons(x) (x) -#define qntohs(x) (x) -#else -#define qhtons(x) swap16(x) -#define qntohs(x) swap16(x) -#define qhtonl(x) swap32(x) -#define qntohl(x) swap32(x) -#endif - - -/// Swap endianness of a given value in memory. -/// \param dst result of swap -/// \param src value to be swapped -/// \param size size of value: can be 1, 2, 4, 8, or 16. -/// For any other values of size this function does nothing - -idaman THREAD_SAFE void ida_export swap_value(void *dst, const void *src, int size); - - -idaman THREAD_SAFE void ida_export reloc_value(void *value, int size, adiff_t delta, bool mf); - - -/// Rotate left - can be used to rotate a value to the right if the count is negative. -/// \param x value to rotate -/// \param count shift amount -/// \param bits number of bits to rotate (32 will rotate a dword) -/// \param offset number of first bit to rotate. -/// (bits=8 offset=16 will rotate the third byte of the value) -/// \return the rotated value - -idaman THREAD_SAFE uval_t ida_export rotate_left(uval_t x, int count, size_t bits, size_t offset); - - -#ifdef __cplusplus -/// Swap 2 objects of the same type using memory copies -template <class T> inline THREAD_SAFE void qswap(T &a, T &b) -{ - char temp[sizeof(T)]; - memcpy(&temp, &a, sizeof(T)); - memcpy(&a, &b, sizeof(T)); - memcpy(&b, &temp, sizeof(T)); -} - -//--------------------------------------------------------------------------- -#ifndef SWIG -//-V:unpack_db:656 Variables are initialized through the call to the same function -//-V:unpack_dw:656 -//-V:unpack_dd:656 -//-V:unpack_ea:656 -//-V:unpack_ea64:656 -//-V:unpack_str:656 -//-V:unpack_ds:656 - -/// \defgroup pack Pack/Unpack -/// Functions for packing and unpacking values -//{ - -/// Pack a byte into a character string. -/// This function encodes numbers using an encoding similar to UTF. -/// The smaller the number, the better the packing. -/// \param ptr pointer to output buffer -/// \param end pointer to end of output buffer -/// \param x value to pack -/// \return pointer to end of resulting string - -THREAD_SAFE inline uchar *idaapi pack_db(uchar *ptr, uchar *end, uchar x) -{ - if ( ptr < end ) - *ptr++ = x; - return ptr; -} - - -/// Unpack a byte from a character string, pack_db() - -THREAD_SAFE inline uchar idaapi unpack_db(const uchar **pptr, const uchar *end) -{ - const uchar *ptr = *pptr; - uchar x = 0; - if ( ptr < end ) - x = *ptr++; - *pptr = ptr; - return x; -} - -idaman THREAD_SAFE uchar *ida_export pack_dw(uchar *ptr, uchar *end, uint16 x); ///< pack a word, see pack_db() -idaman THREAD_SAFE uchar *ida_export pack_dd(uchar *ptr, uchar *end, uint32 x); ///< pack a double word, see pack_db() -idaman THREAD_SAFE uchar *ida_export pack_dq(uchar *ptr, uchar *end, uint64 x); ///< pack a quadword, see pack_db() -idaman THREAD_SAFE ushort ida_export unpack_dw(const uchar **pptr, const uchar *end); ///< unpack a word, see unpack_db() -idaman THREAD_SAFE uint32 ida_export unpack_dd(const uchar **pptr, const uchar *end); ///< unpack a double word, see unpack_db() -idaman THREAD_SAFE uint64 ida_export unpack_dq(const uchar **pptr, const uchar *end); ///< unpack a quadword, see unpack_db() - -/// Pack an ea value into a character string, see pack_dd()/pack_dq() - -THREAD_SAFE inline uchar *pack_ea(uchar *ptr, uchar *end, ea_t ea) -{ -#ifdef __EA64__ - return pack_dq(ptr, end, ea); -#else - return pack_dd(ptr, end, ea); -#endif -} - -/// Unpack an ea value, see unpack_dd()/unpack_dq() - -THREAD_SAFE inline ea_t unpack_ea(const uchar **ptr, const uchar *end) -{ -#ifdef __EA64__ - return unpack_dq(ptr, end); -#else - return unpack_dd(ptr, end); -#endif -} - -/// Unpack an ea value (always use 64bit, use delta 1) -THREAD_SAFE inline ea64_t unpack_ea64(const uchar **ptr, const uchar *end) -{ - return unpack_dq(ptr, end) - 1; -} - - -/// Unpack an object of a known size. -/// \param destbuf output buffer -/// \param destsize size of output buffer -/// \param pptr pointer to packed object -/// \param end pointer to end of packed object -/// \return pointer to the destination buffer. -/// if any error, returns NULL. - -THREAD_SAFE inline void *idaapi unpack_obj( - void *destbuf, - size_t destsize, - const uchar **pptr, - const uchar *end) -{ - const uchar *src = *pptr; - const uchar *send = src + destsize; - if ( send < src || send > end ) - return NULL; - *pptr = send; - return memcpy(destbuf, src, destsize); -} - - -/// Unpack an object of an unknown size (packed with append_buf()). -/// \param pptr pointer to packed object -/// \param end pointer to end of packed object -/// \return pointer to the destination buffer, which is allocated in the dynamic memory. \n -/// the caller should use qfree() to deallocate it. \n -/// if any error, returns NULL. \n -/// NB: zero size objects will return NULL too. - -THREAD_SAFE inline void *idaapi unpack_buf(const uchar **pptr, const uchar *end) -{ - size_t size = unpack_dd(pptr, end); - if ( size == 0 ) - return NULL; - const uchar *src = *pptr; - const uchar *srcend = src + size; - if ( srcend < src || srcend > end ) - return NULL; - void *dst = qalloc(size); - if ( dst != NULL ) - { - memcpy(dst, src, size); - *pptr = srcend; - } - return dst; -} - - -/// In-place version of unpack_obj(). -/// It does not copy any data. It just returns a pointer to the object in the packed string. -/// If any error, it returns NULL. - -THREAD_SAFE inline const void *idaapi unpack_obj_inplace( - const uchar **pptr, - const uchar *end, - size_t objsize) -{ - const uchar *ret = *pptr; - const uchar *rend = ret + objsize; - if ( rend < ret || rend > end ) - return NULL; - *pptr = rend; - return ret; -} - - -/// In-place version of unpack_buf(). -/// It does not copy any data. It just returns a pointer to the object in the packed string. -/// If any error, it returns NULL. - -THREAD_SAFE inline const void *idaapi unpack_buf_inplace( - const uchar **pptr, - const uchar *end) -{ - size_t objsize = unpack_dd(pptr, end); - return unpack_obj_inplace(pptr, end, objsize); -} - - -/// Pack a string. -/// \param ptr pointer to output buffer -/// \param end pointer to end of output buffer -/// \param x string to pack. If NULL, empty string is packed -/// \param len number of chars to pack. If 0, the length of given string is used -/// \return pointer to end of packed string - -idaman THREAD_SAFE uchar *ida_export pack_ds( - uchar *ptr, - uchar *end, - const char *x, - size_t len=0); - - -/// Unpack a string. -/// \param pptr pointer to packed string -/// \param end pointer to end of packed string -/// \param empty_null if true, then return NULL for empty strings. \n -/// otherwise return an empty string (not NULL). -/// \return pointer to unpacked string. \n -/// this string will be allocated in dynamic memory. \n -/// the caller should use qfree() to deallocate it. - -idaman THREAD_SAFE char *ida_export unpack_ds( - const uchar **pptr, - const uchar *end, - bool empty_null); - -/// Unpack a string. -/// \param dst pointer to buffer string will be copied to -/// \param dstsize buffer size -/// \param pptr pointer to packed string -/// \param end pointer to end of packed string -/// \return success -THREAD_SAFE inline bool unpack_ds_to_buf( - char *dst, - size_t dstsize, - const uchar **pptr, - const uchar *end) -{ - const void *buf = unpack_buf_inplace(pptr, end); - if ( buf == NULL ) - return false; - size_t size = *pptr - (const uchar *)buf; - if ( size >= dstsize ) - size = dstsize - 1; - memcpy(dst, buf, size); - dst[size] = '\0'; - return true; -} - - -/// Unpack an LEB128 encoded (DWARF-3 style) signed/unsigned value. -/// Do not use this function directly - see \ref unp_templates - -idaman THREAD_SAFE bool ida_export unpack_xleb128( - void *res, - int nbits, - bool is_signed, - const uchar **pptr, - const uchar *end); - -/// \defgroup unp_templates Template unpacking -/// Template functions that can unpack values -//@{ - -template <class T> -inline THREAD_SAFE bool unpack_uleb128(T *res, const uchar **pptr, const uchar *end) -{ - CASSERT((T)(-1) > 0); // make sure T is unsigned - return unpack_xleb128(res, sizeof(T)*8, false, pptr, end); -} - -template <class T> -inline THREAD_SAFE bool unpack_sleb128(T *res, const uchar **pptr, const uchar *end) -{ - CASSERT((T)(-1) < 0); // make sure T is signed - return unpack_xleb128(res, sizeof(T)*8, true, pptr, end); -} - -//@} Template unpacking functions - -// packed sizes -/// \cond -static constexpr int ea_packed_size = sizeof(ea_t) + sizeof(ea_t)/4; // 5 or 10 bytes -static constexpr int dq_packed_size = 10; -static constexpr int dd_packed_size = 5; -static constexpr int dw_packed_size = 3; -/// \endcond - -inline THREAD_SAFE int ds_packed_size(const char *s) { return s ? int(strlen(s)+dd_packed_size) : 1; } - -//---------------------------------------------------------------------------- -inline THREAD_SAFE int dw_size(uchar first_byte) -{ - return (first_byte & 0x80) == 0 ? 1 - : (first_byte & 0xC0) == 0xC0 ? 3 - : 2; -} - -//---------------------------------------------------------------------------- -inline THREAD_SAFE int dd_size(uchar first_byte) -{ - return (first_byte & 0x80) == 0x00 ? 1 - : (first_byte & 0xC0) != 0xC0 ? 2 - : (first_byte & 0xE0) == 0xE0 ? 5 - : 4; -} - -//---------------------------------------------------------------------------- -// unpack data from an object which must have the following functions: -// ssize_t read(void *buf, size_t count) -// bool eof() - return true if there is no more data to read -template <class T> -inline THREAD_SAFE uchar extract_db(T &v) -{ - uchar x = 0; - v.read(&x, 1); - return x; -} - -template <class T> -inline THREAD_SAFE void *extract_obj(T &v, void *destbuf, size_t destsize) -{ - if ( destsize == 0 ) - return NULL; - return v.read(destbuf, destsize) == destsize ? destbuf : NULL; -} - -template <class T> -inline THREAD_SAFE uint16 extract_dw(T &v) -{ - uchar packed[dw_packed_size]; - packed[0] = extract_db(v); - int psize = dw_size(packed[0]); - extract_obj(v, &packed[1], psize-1); - const uchar *ptr = packed; - return unpack_dw(&ptr, packed + psize); -} - -template <class T> -inline THREAD_SAFE uint32 extract_dd(T &v) -{ - uchar packed[dd_packed_size]; - packed[0] = extract_db(v); - int psize = dd_size(packed[0]); - extract_obj(v, &packed[1], psize-1); - const uchar *ptr = packed; - return unpack_dd(&ptr, packed + psize); -} - -template <class T> -inline THREAD_SAFE uint64 extract_dq(T &v) -{ - uint32 l = extract_dd(v); - uint32 h = extract_dd(v); - return make_ulonglong(l, h); -} - -template <class T> -inline THREAD_SAFE ea_t extract_ea(T &v) -{ -#ifdef __EA64__ - return extract_dq(v); -#else - return extract_dd(v); -#endif -} - -template <class T> -inline THREAD_SAFE void *extract_buf(T &v, size_t size) -{ - void *buf = qalloc(size); - if ( buf == NULL ) - return NULL; - return extract_obj(v, buf, size); -} - -template <class T> -inline THREAD_SAFE void *extract_array(T &v, size_t *sz, size_t maxsize) -{ - size_t size = extract_dd(v); - if ( size == 0 || size > maxsize ) - return NULL; - *sz = size; - return extract_buf(v, size); -} - -inline const char *unpack_str(const uchar **pptr, const uchar *end) -{ // zero terminated string, return inplace ptr - const uchar *ptr = *pptr; - const uchar *str = ptr; - do - if ( ptr >= end ) - return nullptr; // no terminating zero? - while ( *ptr++ != '\0' ); - *pptr = ptr; - return (char*)str; -} - -//@} Packing functions -#endif // SWIG -#endif // cplusplus - -/// \name Safe buffer append -/// In the following macros, 'buf' must be always less than 'end'. -/// When we run up to the end, we put a 0 there and don't increase buf anymore -//@{ -/// Append a character to the buffer checking the buffer size -#define APPCHAR(buf, end, chr) \ - do \ - { \ - char __chr = (chr); \ - QASSERT(518, (buf) < (end)); \ - *(buf)++ = __chr; \ - if ( (buf) >= (end) ) \ - { \ - (buf) = (end)-1; \ - (buf)[0] = '\0'; \ - } \ - } while (0) - -/// Put a zero byte at buffer. -/// NB: does not increase buf pointer! -#define APPZERO(buf, end) \ - do \ - { \ - QASSERT(519, (buf) < (end)); \ - *(buf) = '\0'; \ - } while (0) - -/// Append a string to the buffer checking the buffer size -#define APPEND(buf, end, name) \ - do \ - { \ - QASSERT(520, (buf) < (end)); \ - const char *__ida_in = (name); \ - while ( true ) \ - { \ - if ( (buf) == (end)-1 ) \ - { \ - (buf)[0] = '\0'; \ - break; \ - } \ - if ( (*(buf) = *__ida_in++) == '\0' ) \ - break; \ - (buf)++; \ - } \ - } while ( 0 ) -//@} - -/// qalloc() 'size' bytes, and throw a "not enough memory" error if failed - -idaman THREAD_SAFE void *ida_export qalloc_or_throw(size_t size); - - -/// qrealloc() 'ptr' by 'size', and throw a "not enough memory" error if failed - -idaman THREAD_SAFE void *ida_export qrealloc_or_throw(void *ptr, size_t size); - - -/// Change capacity of given qvector. -/// \param vec a pointer to a qvector -/// \param old a pointer to the qvector's array -/// \param cnt number of elements to reserve -/// \param elsize size of each element -/// \return a pointer to the newly allocated array - -idaman THREAD_SAFE void *ida_export qvector_reserve(void *vec, void *old, size_t cnt, size_t elsize); - -#if defined(__cplusplus) - /// \def{PLACEMENT_DELETE, bcc complains about placement delete} - /// \def{DEFINE_MEMORY_ALLOCATION_FUNCS, - /// Convenience macro to declare memory allocation functions. - /// It must be used for all classes that can be allocated/freed by the IDA kernel.} - #if defined(SWIG) - #define DEFINE_MEMORY_ALLOCATION_FUNCS() - #else - #define PLACEMENT_DELETE void operator delete(void *, void *) {} - #define DEFINE_MEMORY_ALLOCATION_FUNCS() \ - void *operator new (size_t _s) { return qalloc_or_throw(_s); } \ - void *operator new[](size_t _s) { return qalloc_or_throw(_s); } \ - void *operator new(size_t /*size*/, void *_v) { return _v; } \ - void operator delete (void *_blk) { qfree(_blk); } \ - void operator delete[](void *_blk) { qfree(_blk); } \ - PLACEMENT_DELETE - #endif - -/// Macro to declare standard inline comparison operators -#define DECLARE_COMPARISON_OPERATORS(type) \ - bool operator==(const type &r) const { return compare(r) == 0; } \ - bool operator!=(const type &r) const { return compare(r) != 0; } \ - bool operator< (const type &r) const { return compare(r) < 0; } \ - bool operator> (const type &r) const { return compare(r) > 0; } \ - bool operator<=(const type &r) const { return compare(r) <= 0; } \ - bool operator>=(const type &r) const { return compare(r) >= 0; } - -/// Macro to declare comparisons for our classes. -/// All comparison operators call the compare() function which returns -1/0/1 -#define DECLARE_COMPARISONS(type) \ - DECLARE_COMPARISON_OPERATORS(type) \ - int compare(const type &r) const - -// Internal declarations to detect movable types -/// \cond -// Can we move around objects of type T using simple memcpy/memmove?. -// This class can be specialized for any type T to improve qvector's behavior. -template <class T> struct ida_movable_type -{ - static constexpr bool value = std::is_pod<T>::value; -}; -#define DECLARE_TYPE_AS_MOVABLE(T) template <> struct ida_movable_type<T> { static constexpr bool value = true; } -template <class T> inline constexpr THREAD_SAFE bool may_move_bytes(void) -{ - return ida_movable_type<T>::value; -} -/// \endcond - -//--------------------------------------------------------------------------- -/// Reimplementation of vector class from STL. -/// Only the most essential functions are implemented. \n -/// The vector container accepts objects agnostic to their positions -/// in the memory because it will move them arbitrarily (realloc and memmove). \n -/// The reason why we have it is because it is not compiler dependent -/// (hopefully) and therefore can be used in IDA API. -template <class T> class qvector -{ - T *array; - size_t n, alloc; - friend void *ida_export qvector_reserve(void *vec, void *old, size_t cnt, size_t elsize); - /// Copy contents of given qvector into this one - qvector<T> &assign(const qvector<T> &x) - { - size_t _newsize = x.n; - if ( _newsize > 0 ) - { - array = (T*)qalloc_or_throw(_newsize * sizeof(T)); - alloc = _newsize; - copy_range(x, 0, _newsize); - } - return *this; - } - /// Move data down in memory. - /// \param dst destination ptr - /// \param src source ptr - /// \param cnt number of elements to move - void shift_down(T *dst, T *src, size_t cnt) - { - if ( may_move_bytes<T>() ) - { - memmove(dst, src, cnt*sizeof(T)); - } - else - { - ssize_t s = cnt; - while ( --s >= 0 ) - { - new(dst) T(std::move(*src)); - src->~T(); - ++src; - ++dst; - } - } - } - /// Move data up in memory. - /// \param dst destination ptr - /// \param src source ptr - /// \param cnt number of elements to move - void shift_up(T *dst, T *src, size_t cnt) - { - if ( may_move_bytes<T>() ) - { - memmove(dst, src, cnt*sizeof(T)); - } - else - { - ssize_t s = cnt; - dst += s; - src += s; - while ( --s >= 0 ) - { - --src; - --dst; - new(dst) T(std::move(*src)); - src->~T(); - } - } - } - /// Copies a range of elements from another qvector. - void copy_range(const qvector<T> &x, size_t from, size_t _newsize) - { - if ( std::is_trivially_copyable<T>::value ) - { - memcpy(array + from, x.array + from, (_newsize-from)*sizeof(T)); - } - else - { - for ( size_t i = from; i < _newsize; i++ ) - new(array+i) T(x.array[i]); - } - n = _newsize; - } - /// Resizes to a smaller size, destroying elements if needed. - void resize_less(size_t _newsize) - { - if ( !std::is_trivially_destructible<T>::value ) - { - size_t _size = n; - for ( size_t i = _newsize; i < _size; i++ ) - array[i].~T(); - } - n = _newsize; - } - /// Resizes to a bigger size, and zeroes the new elements (they - /// should be of a std::is_trivially_constructible type). - void resize_more_trivial(size_t _newsize) - { - reserve(_newsize); - memset(array+n, 0, (_newsize-n)*sizeof(T)); - n = _newsize; - } - /// Resizes to a bigger size with a given element. - void resize_more(size_t _newsize, const T &x) - { - reserve(_newsize); - for ( size_t i = n; i < _newsize; i++ ) - new(array+i) T(x); - n = _newsize; - } -public: - typedef T value_type; ///< the type of objects contained in this qvector - /// Constructor - qvector(void) : array(NULL), n(0), alloc(0) {} - /// Constructor - creates a new qvector identical to 'x' - qvector(const qvector<T> &x) : array(NULL), n(0), alloc(0) { assign(x); } - /// Destructor - ~qvector(void) - { - if ( std::is_trivially_destructible<T>::value ) - qfree(array); - else - clear(); - } - DEFINE_MEMORY_ALLOCATION_FUNCS() - /// Append a new element to the end the qvector. - void push_back(const T &x) - { - reserve(n+1); - new (array+n) T(x); - ++n; - } - /// Append a new empty element to the end of the qvector. - /// \return a reference to this new element - T &push_back(void) - { - reserve(n+1); - T *ptr = array + n; - new (ptr) T; - ++n; - return *ptr; - } - /// Remove the last element in the qvector - void pop_back(void) - { - if ( n > 0 ) - array[--n].~T(); - } - size_t size(void) const { return n; } ///< Get the number of elements in the qvector - bool empty(void) const { return n == 0; } ///< Does the qvector have 0 elements? - const T &operator[](size_t _idx) const { return array[_idx]; } ///< Allows use of typical c-style array indexing for qvectors - T &operator[](size_t _idx) { return array[_idx]; } ///< Allows use of typical c-style array indexing for qvectors - const T &at(size_t _idx) const { return array[_idx]; } ///< Get element at index '_idx' - T &at(size_t _idx) { return array[_idx]; } ///< Get element at index '_idx' - const T &front(void) const { return array[0]; } ///< Get the first element in the qvector - T &front(void) { return array[0]; } ///< Get the first element in the qvector - const T &back(void) const { return array[n-1]; } ///< Get the last element in the qvector - T &back(void) { return array[n-1]; } ///< Get the last element in the qvector - /// Destroy all elements but do not free memory - void qclear(void) - { - resize_less(0); - } - /// Destroy all elements and free memory - void clear(void) - { - if ( array != NULL ) - { - qclear(); - qfree(array); - array = NULL; - alloc = 0; - } - } - /// Allow assignment of one qvector to another using '=' - qvector<T> &operator=(const qvector<T> &x) - { - if ( this != &x ) - { - clear(); - assign(x); - } - return *this; - } - /// Resize to the given size. - /// If the given size (_newsize) is less than the current size (n) of the qvector, then the last n - _newsize elements are simply deleted. \n - /// If the given size is greater than the current size, the qvector is grown to _newsize, and the last _newsize - n elements will be filled with copies of 'x'. \n - /// If the given size is equal to the current size, this function does nothing. - void resize(size_t _newsize, const T &x) - { - if ( _newsize < n ) - resize_less(_newsize); - else if ( _newsize > n ) - resize_more(_newsize, x); - } - /// Same as resize(size_t, const T &), but extra space is filled with empty elements - void resize(size_t _newsize) - { - if ( std::is_trivially_constructible<T>::value && _newsize > n ) - resize_more_trivial(_newsize); - else - resize(_newsize, T()); - } -#ifndef SWIG - // Resize the array but do not initialize elements - void resize_noinit(size_t _newsize) - { - CASSERT(std::is_trivially_constructible<T>::value); - CASSERT(std::is_trivially_destructible<T>::value); - reserve(_newsize); - n = _newsize; - } -#endif - /// Add an element to the end of the qvector, which will be a new T() if x is not given - void grow(const T &x=T()) - { - reserve(n+1); - new(array+n) T(x); - ++n; - } - /// Get the number of elements that this qvector can contain - not the same - /// as the number of elements currently in the qvector (size()) - size_t capacity(void) const { return alloc; } - /// Increase the capacity of the qvector. If cnt is not greater than the current capacity - /// this function does nothing. - void reserve(size_t cnt) - { - if ( cnt > alloc ) - { - if ( may_move_bytes<T>() ) - { - array = (T *)qvector_reserve(this, array, cnt, sizeof(T)); - } - else - { - size_t old_alloc = alloc; - T *new_array = (T *)qvector_reserve(this, NULL, cnt, sizeof(T)); - size_t new_alloc = alloc; - alloc = old_alloc; - shift_down(new_array, array, n); - qfree(array); - array = new_array; - alloc = new_alloc; - } - } - } - /// Shrink the capacity down to the current number of elements - void truncate(void) - { - if ( alloc > n ) - { - array = (T*)qrealloc(array, n*sizeof(T)); // should not fail - alloc = n; - } - } - /// Replace all attributes of this qvector with that of 'r', and vice versa. - /// Effectively sets this = r and r = this without copying/allocating any memory. - void swap(qvector<T> &r) - { - T *array2 = array; - size_t n2 = n; - size_t alloc2 = alloc; - - array = r.array; - n = r.n; - alloc = r.alloc; - - r.array = array2; - r.n = n2; - r.alloc = alloc2; - } - /// Empty the qvector and return a pointer to it's contents. - /// The caller must free the result of this function - T *extract(void) - { - truncate(); - alloc = 0; - n = 0; - T *res = array; - array = NULL; - return res; - } - /// Populate the qvector with dynamic memory. - /// The qvector must be empty before calling this method! - void inject(T *s, size_t len) - { - array = s; - alloc = len; - n = len; - } - /// Allow ability to test the equality of two qvectors using '=='. - bool operator == (const qvector<T> &r) const - { - if ( n != r.n ) - return false; - for ( size_t i=0; i < n; i++ ) - if ( array[i] != r[i] ) - return false; - return true; - } - /// Allow ability to test equality of two qvectors using '!=' - bool operator != (const qvector<T> &r) const { return !(*this == r); } - - typedef T *iterator; - typedef const T *const_iterator; - - iterator begin(void) { return array; } ///< Get an iterator that points to the first element in the qvector - iterator end(void) { return array + n; } ///< Get an iterator that points to the end of the qvector (NOT the last element) - const_iterator begin(void) const { return array; } ///< Get a const iterator that points to the first element in the qvector - const_iterator end(void) const { return array + n; } ///< Get a const iterator that points to the end of the qvector (NOT the last element) - /// Insert an element into the qvector at a specified position. - /// \param it an iterator that points to the desired position of the new element - /// \param x the element to insert - /// \return an iterator that points to the newly inserted element - iterator insert(iterator it, const T &x) - { - size_t idx = it - array; - reserve(n+1); - T *p = array + idx; - size_t rest = end() - p; - shift_up(p+1, p, rest); - new(p) T(x); - n++; - return iterator(p); - } - /// Insert a several elements to the qvector at a specified position. - /// \param it position at which new elements will be inserted - /// \param first pointer to first element to be inserted - /// \param last pointer to end of elements to be inserted (the element pointed to by 'last' will not be included) - /// \return an iterator that points to the first newly inserted element. - template <class it2> iterator insert(iterator it, it2 first, it2 last) - { - size_t cnt = last - first; - if ( cnt == 0 ) - return it; - - size_t idx = it - array; - reserve(n+cnt); - T *p = array + idx; - size_t rest = end() - p; - shift_up(p+cnt, p, rest); - while ( first != last ) - { - new(p) T(*first); - ++p; - ++first; - } - n += cnt; - return iterator(array+idx); - } - /// Remove an element from the qvector. - /// \param it pointer to element to be removed - /// \return pointer to the element that took its place - iterator erase(iterator it) - { - it->~T(); - size_t rest = end() - it - 1; - shift_down(it, it+1, rest); - n--; - return it; - } - /// Remove a subset of the qvector. - /// \param first pointer to head of subset to be removed - /// \param last pointer to end of subset to be removed (element pointed to by last will not be removed) - /// \return a pointer to the element that took the place of 'first' - iterator erase(iterator first, iterator last) - { - for ( T *p=first; p != last; ++p ) - p->~T(); - size_t rest = end() - last; - shift_down(first, last, rest); - n -= last - first; - return first; - } - // non-standard extensions: - /// Find an element in the qvector. - /// \param x element to find - /// \return an iterator that points to the first occurrence of 'x' - iterator find(const T &x) - { - iterator p; - const_iterator e; - for ( p=begin(), e=end(); p != e; ++p ) - if ( x == *p ) - break; - return p; - } - /// \copydoc find - const_iterator find(const T &x) const - { - const_iterator p, e; - for ( p=begin(), e=end(); p != e; ++p ) - if ( x == *p ) - break; - return p; - } -#ifndef SWIG - /// Find index of the specified value or return -1 - ssize_t index(const T &x) const - { - for ( const_iterator p=begin(), e=end(); p != e; ++p ) - if ( x == *p ) - return p - begin(); - return -1; - } - /// Add an element to the end of the qvector - void add(const T &x) { push_back(x); } -#endif - /// Does the qvector contain x? - bool has(const T &x) const { return find(x) != end(); } - /// Add an element to the end of the qvector - only if it isn't already present. - /// \param x the element to add - /// \return false if 'x' is already in the qvector, true otherwise - bool add_unique(const T &x) - { - if ( has(x) ) - return false; - push_back(x); - return true; - } - /// Find an element and remove it. - /// \param x the element to remove - /// \return false if 'x' was not found, true otherwise - bool del(const T &x) - { - iterator p = find(x); - if ( p == end() ) - return false; - erase(p); - return true; - } -#ifndef SWIG - const char *dstr(void) const; // debug print -#endif -}; - -typedef qvector<uval_t> uvalvec_t; ///< vector of unsigned values -typedef qvector<sval_t> svalvec_t; ///< vector of signed values -typedef qvector<ea_t> eavec_t; ///< vector of addresses -typedef qvector<int> intvec_t; ///< vector of integers -typedef qvector<bool> boolvec_t; ///< vector of bools -typedef qvector<size_t> sizevec_t; ///< vector of sizes - -/// Reimplementation of stack class from STL. -/// The reason why we have it is because it is not compiler dependent -/// (hopefully) and therefore can be used in IDA API -template<class T> -class qstack : public qvector<T> -{ - typedef qvector<T> inherited; -public: - T pop(void) - { - T v = inherited::back(); - inherited::pop_back(); - return v; - } - const T &top(void) const - { - return inherited::back(); - } - T &top(void) { return CONST_CAST(T&)(CONST_CAST(const qstack<T>*)(this)->top()); } - void push(const T &v) - { - inherited::push_back(v); - } -}; - -/// Standard lexical comparison. -/// \return -1 if a < b, 1 if a > b, and 0 if a == b -template <class T> int lexcompare(const T &a, const T &b) -{ - if ( a < b ) - return -1; - if ( a > b ) - return 1; - return 0; -} - -/// Lexical comparison of two vectors. Also see lexcompare(). -/// \return 0 if the two vectors are identical -/// 1 if 'a' is larger than 'b' -/// -1 if 'a' is smaller than 'b' -/// otherwise return the first nonzero lexical comparison between each element in 'a' and 'b' -template <class T> int lexcompare_vectors(const T &a, const T &b) -{ - if ( a.size() != b.size() ) - return a.size() > b.size() ? 1 : -1; - for ( int i=0; i < a.size(); i++ ) - { - int code = lexcompare(a[i], b[i]); - if ( code != 0 ) - return code; - } - return 0; -} - -/// Smart pointer to objects derived from ::qrefcnt_obj_t -template <class T> -class qrefcnt_t -{ - T *ptr; - void delref(void) - { - if ( ptr != NULL && --ptr->refcnt == 0 ) - ptr->release(); - } -public: - explicit qrefcnt_t(T *p) : ptr(p) {} - qrefcnt_t(const qrefcnt_t &r) : ptr(r.ptr) - { - if ( ptr != NULL ) - ptr->refcnt++; - } - qrefcnt_t &operator=(const qrefcnt_t &r) - { - delref(); - ptr = r.ptr; - if ( ptr != NULL ) - ptr->refcnt++; - return *this; - } - ~qrefcnt_t(void) - { - delref(); - } - void reset(void) - { - delref(); - ptr = NULL; - } - operator T *() const - { - return ptr; - } - T *operator ->() const - { - return ptr; - } - T &operator *() const - { - return *ptr; - } -}; - -/// Base class for reference count objects -class qrefcnt_obj_t -{ -public: - int refcnt; ///< counter - /// Constructor - qrefcnt_obj_t(void) : refcnt(1) {} - /// Call destructor. - /// We use release() instead of operator delete() to maintain binary - /// compatibility with all compilers (vc and gcc use different vtable layouts - /// for operator delete) - virtual void idaapi release(void) = 0; -}; - -/// Interface class for iterator types. -template <class T> -class qiterator : public qrefcnt_obj_t -{ -public: - typedef T value_type; - virtual bool idaapi first(void) = 0; - virtual bool idaapi next(void) = 0; - virtual T idaapi operator *(void) = 0; - virtual T get(void) newapi { return this->operator*(); } -}; - - -/// \name strlen -/// Get the length of the given string -//@{ -inline THREAD_SAFE size_t idaapi qstrlen(const char *s) { return strlen(s); } -inline THREAD_SAFE size_t idaapi qstrlen(const uchar *s) { return strlen((const char *)s); } -idaman THREAD_SAFE size_t ida_export qstrlen(const wchar16_t *s); -//@} - -/// \name strcmp -/// Lexical comparison of strings. -/// \return 0 if two strings are identical -/// > 0 if 's1' is larger than 's2' -/// < 0 if 's2' is larger than 's1' -/// otherwise return first nonzero comparison between chars in 's1' and 's2' -//@{ -inline THREAD_SAFE int idaapi qstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); } -inline THREAD_SAFE int idaapi qstrcmp(const uchar *s1, const uchar *s2) { return strcmp((const char *)s1, (const char *)s2); } -idaman THREAD_SAFE int ida_export qstrcmp(const wchar16_t *s1, const wchar16_t *s2); -//@} - -/// \name strstr -/// Find a string within another string. -/// \return a pointer to the first occurrence of 's2' within 's1', NULL if s2 is not found in s1 -//@{ -inline THREAD_SAFE const char *idaapi qstrstr(const char *s1, const char *s2) { return strstr(s1, s2); } -inline THREAD_SAFE const uchar *idaapi qstrstr(const uchar *s1, const uchar *s2) { return (const uchar *)strstr((const char *)s1, (const char *)s2); } -//@} - -/// \name strchr -/// Find a character within a string. -/// \return a pointer to the first occurrence of 'c' within 's1', NULL if c is not found in s1 -//@{ -inline THREAD_SAFE char *idaapi qstrchr(char *s1, char c) { return strchr(s1, c); } -inline THREAD_SAFE const char *idaapi qstrchr(const char *s1, char c) { return strchr(s1, c); } -inline THREAD_SAFE uchar *idaapi qstrchr(uchar *s1, uchar c) { return (uchar *)strchr((char *)s1, c); } -inline THREAD_SAFE const uchar *idaapi qstrchr(const uchar *s1, uchar c) { return (const uchar *)strchr((const char *)s1, c); } -idaman THREAD_SAFE const wchar16_t *ida_export qstrchr(const wchar16_t *s1, wchar16_t c); -inline THREAD_SAFE wchar16_t *idaapi qstrchr(wchar16_t *s1, wchar16_t c) - { return (wchar16_t *)qstrchr((const wchar16_t *)s1, c); } -//@} - -/// \name qstrrchr -/// Find a last occurrence of a character within a string. -/// \return a pointer to the last occurrence of 'c' within 's1', NULL if c is not found in s1 -//@{ -inline THREAD_SAFE const char *idaapi qstrrchr(const char *s1, char c) { return strrchr(s1, c); } -inline THREAD_SAFE char *idaapi qstrrchr(char *s1, char c) { return strrchr(s1, c); } -inline THREAD_SAFE const uchar *idaapi qstrrchr(const uchar *s1, uchar c) { return (const uchar *)strrchr((const char *)s1, c); } -inline THREAD_SAFE uchar *idaapi qstrrchr(uchar *s1, uchar c) { return (uchar *)strrchr((const char *)s1, c); } -idaman THREAD_SAFE const wchar16_t *ida_export qstrrchr(const wchar16_t *s1, wchar16_t c); -inline THREAD_SAFE wchar16_t *idaapi qstrrchr(wchar16_t *s1, wchar16_t c) - { return (wchar16_t *)qstrrchr((const wchar16_t *)s1, c); } -//@} - - -/// Reimplementation of the string class from STL. -/// Only the most essential functions are implemented. -/// The reason why we have this is because it is not compiler dependent -/// (hopefully) and therefore can be used in IDA API -template<class qchar> -class _qstring //-V:_qstring:690 The class implements the '=' operator, but lacks a copy constructor. It is dangerous to use such a class. -{ - qvector<qchar> body; - void assign(const qchar *ptr, size_t len) - { - body.resize_noinit(len+1); - memmove(body.begin(), ptr, len*sizeof(qchar)); - body[len] = '\0'; - } -public: - /// Constructor - _qstring(void) {} - /// Constructor - creates a new qstring from an existing char * - _qstring(const qchar *ptr) - { - if ( ptr != NULL ) - assign(ptr, ::qstrlen(ptr)); - } - /// Constructor - creates a new qstring using first 'len' chars from 'ptr' - _qstring(const qchar *ptr, size_t len) - { - if ( len > 0 ) - assign(ptr, len); - } - void swap(_qstring<qchar> &r) { body.swap(r.body); } ///< Swap contents of two qstrings. see qvector::swap() - size_t length(void) const { size_t l = body.size(); return l ? l - 1 : 0; } ///< Get number of chars in this qstring (not including terminating zero) - size_t size(void) const { return body.size(); } ///< Get number of chars in this qstring (including terminating zero) - size_t capacity(void) const { return body.capacity(); } ///< Get number of chars this qstring can contain (including terminating zero) - - /// Resize to the given size. - /// The resulting qstring will have length() = s, and size() = s+1 \n - /// if 's' is greater than the current size then the extra space is filled with 'c'. \n - /// if 's' is less than the current size then the trailing chars are removed - void resize(size_t s, qchar c) - { - size_t oldsize = body.size(); - if ( oldsize != 0 && s >= oldsize ) - body[oldsize-1] = c; // erase the terminating zero - body.resize(s+1, c); - body[s] = 0; // ensure the terminating zero - } - /// Similar to resize(size_t, qchar) - but any extra space is filled with zeroes - void resize(size_t s) - { - if ( s == 0 ) - { - body.clear(); - } - else - { - body.resize(s+1); - body[s] = 0; // ensure the terminating zero - } - } - void remove_last(int cnt=1) - { - ssize_t len = body.size() - cnt; - if ( len <= 1 ) - { - body.clear(); - } - else - { - body.resize_noinit(len); - body[len-1] = 0; - } - } - void reserve(size_t cnt) { body.reserve(cnt); } ///< Increase capacity the qstring. see qvector::reserve() - void clear(void) { body.clear(); } ///< Clear qstring and free memory - void qclear(void) { body.qclear(); } ///< Clear qstring but do not free memory yet - bool empty(void) const { return body.size() <= 1; } ///< Does the qstring have 0 non-null elements? - /// Convert the qstring to a char * - const qchar *c_str(void) const - { - static const qchar nullstr[] = { 0 }; - return body.empty() ? nullstr : &body[0]; - } - typedef qchar *iterator; - typedef const qchar *const_iterator; - iterator begin(void) { return body.begin(); } ///< Get a pointer to the beginning of the qstring - const_iterator begin(void) const { return body.begin(); } ///< Get a const pointer to the beginning of the qstring - iterator end(void) { return body.end(); } ///< Get a pointer to the end of the qstring (this is not the terminating zero) - const_iterator end(void) const { return body.end(); } ///< Get a const pointer to the end of the qstring (this is not the terminating zero) - /// Allow assignment of qstrings using '=' - _qstring &operator=(const qchar *str) - { - size_t len = str == NULL ? 0 : ::qstrlen(str); - if ( len > 0 ) - assign(str, len); - else - qclear(); - return *this; - } - _qstring &operator=(const _qstring &qstr) - { - if ( this != &qstr ) - { - size_t len = qstr.length(); - if ( len > 0 ) - assign(qstr.begin(), len); - else - qclear(); - } - return *this; - } - /// Append a char using '+=' - _qstring &operator+=(qchar c) - { - return append(c); - } - /// Append another qstring using '+=' - _qstring &operator+=(const _qstring &r) - { - return append(r); - } - /// Get result of appending two qstrings using '+' - _qstring operator+(const _qstring &r) const - { - _qstring s = *this; - s += r; - return s; - } - DECLARE_COMPARISONS(_qstring) - { - return ::qstrcmp(c_str(), r.c_str()); - } - /// Test equality of a qstring and a const char* using '==' - bool operator==(const qchar *r) const - { - return ::qstrcmp(c_str(), r) == 0; - } - bool operator!=(const qchar *r) const { return !(*this == r); } ///< Test equality of a qstring and a const char* with '!=' - /// Compare two qstrings using '<'. see qstrcmp() - bool operator<(const qchar *r) const - { - return ::qstrcmp(c_str(), r) < 0; - } - /// Retrieve char at index 'idx' using '[]' - const qchar &operator[](size_t idx) const - { - if ( !body.empty() || idx ) - return body[idx]; - static const qchar nullstr[] = { 0 }; - return nullstr[0]; - } - /// Retrieve char at index 'idx' using '[]' - qchar &operator[](size_t idx) - { - if ( !body.empty() || idx ) - return body[idx]; - static qchar nullstr[] = { 0 }; - return nullstr[0]; - } - const qchar &at(size_t idx) const { return body.at(idx); } ///< Retrieve const char at index 'idx' - qchar &at(size_t idx) { return body.at(idx); } ///< Retrieve char at index 'idx' - /// Extract C string from _qstring. Must qfree() it. - qchar *extract(void) { return body.extract(); } - /// Assign this qstring to an existing char *. - /// See qvector::inject(T *, size_t) - void inject(qchar *s, size_t len) - { - body.inject(s, len); - } - /// Same as to inject(qchar *, size_t), with len = strlen(s) - void inject(qchar *s) - { - if ( s != NULL ) - { - size_t len = ::qstrlen(s) + 1; - body.inject(s, len); - } - } - /// Get the last qchar in the string (for concatenation checks) - qchar last(void) const - { - size_t len = length(); - return len == 0 ? '\0' : body[len-1]; - } - /// Find a substring. - /// \param str the substring to look for - /// \param pos starting position - /// \return the position of the beginning of the first occurrence of str, _qstring::npos of none exists - size_t find(const qchar *str, size_t pos=0) const - { - if ( pos <= length() ) - { - const qchar *beg = c_str(); - const qchar *ptr = ::qstrstr(beg+pos, str); - if ( ptr != NULL ) - return ptr - beg; - } - return npos; - } - /// Replace all occurrences of 'what' with 'with'. - /// \return false if 'what' is not found in the qstring, true otherwise - bool replace(const qchar *what, const qchar *with) - { - _qstring result; - size_t len_what = ::qstrlen(what); - const qchar *_start = c_str(); - const qchar *last_pos = _start; - while ( true ) - { - const qchar *pos = ::qstrstr(last_pos, what); - if ( pos == NULL ) - break; - size_t n = pos - last_pos; - if ( n > 0 ) - result.append(last_pos, n); - result.append(with); - last_pos = pos + len_what; - } - // no match at all? - if ( last_pos == _start ) - return false; - // any pending characters? - if ( *last_pos ) - result.append(last_pos); - swap(result); - return true; - } - /// Same as find(const qchar *, size_t), but takes a qstring parameter - size_t find(const _qstring &str, size_t pos=0) const { return find(str.c_str(), pos); } - /// Find a character in the qstring. - /// \param c the character to look for - /// \param pos starting position - /// \return index of first occurrence of 'c' if c is found, _qstring::npos otherwise - size_t find(qchar c, size_t pos=0) const - { - if ( pos <= length() ) - { - const qchar *beg = c_str(); - const qchar *ptr = qstrchr(beg+pos, c); - if ( ptr != NULL ) - return ptr - beg; - } - return npos; - } - /// Search backwards for a character in the qstring. - /// \param c the char to look for - /// \param pos starting position - /// \return index of first occurrence of 'c' if c is found, _qstring::npos otherwise - size_t rfind(qchar c, size_t pos=0) const - { - if ( pos <= length() ) - { - const qchar *beg = c_str(); - const qchar *ptr = qstrrchr(beg+pos, c); - if ( ptr != NULL ) - return ptr - beg; - } - return npos; - } - /// Get a substring. - /// \param pos starting position - /// \param n ending position (non-inclusive) - /// \return the resulting substring - _qstring<qchar> substr(size_t pos=0, size_t n=npos) const - { - size_t endp = qmin(length(), n); - if ( pos >= endp ) - pos = endp; - return _qstring<qchar>(c_str()+pos, endp-pos); - } - /// Remove characters from the qstring. - /// \param idx starting position - /// \param cnt number of characters to remove - _qstring &remove(size_t idx, size_t cnt) - { - size_t len = length(); - if ( idx < len && cnt != 0 ) - { - cnt += idx; - if ( cnt < len ) - { - iterator p1 = body.begin() + cnt; - iterator p2 = body.begin() + idx; - memmove(p2, p1, (len-cnt)*sizeof(qchar)); - idx += len - cnt; - } - body.resize_noinit(idx+1); - body[idx] = '\0'; - } - return *this; - } - /// Insert a character into the qstring. - /// \param idx position of insertion (if idx >= length(), the effect is the same as append) - /// \param c char to insert - _qstring &insert(size_t idx, qchar c) - { - size_t len = length(); - body.resize_noinit(len+2); - body[len+1] = '\0'; - if ( idx < len ) - { - iterator p1 = body.begin() + idx; - memmove(p1+1, p1, (len-idx)*sizeof(qchar)); - len = idx; - } - body[len] = c; - return *this; - } - /// Insert a string into the qstring. - /// \param idx position of insertion (if idx >= length(), the effect is the same as append) - /// \param str the string to insert - /// \param addlen number of chars from 'str' to insert - _qstring &insert(size_t idx, const qchar *str, size_t addlen) - { - size_t len = length(); - body.resize_noinit(len+addlen+1); - body[len+addlen] = '\0'; - if ( idx < len ) - { - iterator p1 = body.begin() + idx; - iterator p2 = p1 + addlen; - memmove(p2, p1, (len-idx)*sizeof(qchar)); - len = idx; - } - memmove(body.begin()+len, str, addlen*sizeof(qchar)); - return *this; - } - /// Same as insert(size_t, const qchar *, size_t), but all chars in str are inserted - _qstring &insert(size_t idx, const qchar *str) - { - if ( str != NULL ) - { - size_t addlen = ::qstrlen(str); - insert(idx, str, addlen); - } - return *this; - } - /// Same as insert(size_t, const qchar *), but takes a qstring parameter - _qstring &insert(size_t idx, const _qstring &qstr) - { - size_t len = length(); - size_t add = qstr.length(); - body.resize_noinit(len+add+1); - body[len+add] = '\0'; - if ( idx < len ) - { - iterator p1 = body.begin() + idx; - iterator p2 = p1 + add; - memmove(p2, p1, (len-idx)*sizeof(qchar)); - len = idx; - } - memcpy(body.begin()+len, qstr.begin(), add*sizeof(qchar)); - return *this; - } - _qstring &insert(qchar c) { return insert(0, c); } ///< Prepend the qstring with 'c' - _qstring &insert(const qchar *str) { return insert(0, str); } ///< Prepend the qstring with 'str' - _qstring &insert(const _qstring &qstr) { return insert(0, qstr); } ///< Prepend the qstring with 'qstr' - /// Append c to the end of the qstring - _qstring &append(qchar c) - { - size_t len = length(); - body.resize_noinit(len+2); - body[len] = c; - body[len+1] = '\0'; - return *this; - } - /// Append a string to the qstring. - /// \param str the string to append - /// \param addlen number of characters from 'str' to append - _qstring &append(const qchar *str, size_t addlen) - { - size_t len = length(); - body.resize_noinit(len+addlen+1); - body[len+addlen] = '\0'; - memmove(body.begin()+len, str, addlen*sizeof(qchar)); - return *this; - } - /// Same as append(const qchar *, size_t), but all chars in 'str' are appended - _qstring &append(const qchar *str) - { - if ( str != NULL ) - { - size_t addlen = ::qstrlen(str); - append(str, addlen); - } - return *this; - } - /// Same as append(const qchar *), but takes a qstring argument - _qstring &append(const _qstring &qstr) - { - size_t add = qstr.length(); - if ( add != 0 ) - { - size_t len = length(); - body.resize_noinit(len+add+1); - body[len+add] = '\0'; - memcpy(body.begin()+len, qstr.begin(), add*sizeof(qchar)); - } - return *this; - } - /// Append result of qvsnprintf() to qstring - AS_PRINTF(2, 0) _qstring &cat_vsprnt(const char *format, va_list va) - { // since gcc64 forbids reuse of va_list, we make a copy for the second call: - va_list copy; - va_copy(copy, va); - size_t add = ::qvsnprintf(NULL, 0, format, va); - if ( add != 0 ) - { - size_t len = length(); - body.resize_noinit(len+add+1); - ::qvsnprintf(body.begin()+len, add+1, format, copy); - } - return *this; - } - /// Replace qstring with the result of qvsnprintf() - AS_PRINTF(2, 0) _qstring &vsprnt(const char *format, va_list va) - { // since gcc64 forbids reuse of va_list, we make a copy for the second call: - va_list copy; - va_copy(copy, va); - body.clear(); - size_t add = ::qvsnprintf(NULL, 0, format, va); - if ( add != 0 ) - { - body.resize_noinit(add+1); - ::qvsnprintf(body.begin(), add+1, format, copy); - } - return *this; - } - /// Append result of qsnprintf() to qstring - AS_PRINTF(2, 3) _qstring &cat_sprnt(const char *format, ...) - { - va_list va; - va_start(va, format); - cat_vsprnt(format, va); - va_end(va); - return *this; - } - /// Replace qstring with the result of qsnprintf() - AS_PRINTF(2, 3) _qstring &sprnt(const char *format, ...) - { - va_list va; - va_start(va, format); - vsprnt(format, va); - va_end(va); - return *this; - } - /// Replace qstring with the result of qsnprintf() - /// \sa inline int nowarn_qsnprintf(char *buf, size_t size, const char *format, ...) - GCC_DIAG_OFF(format-nonliteral); - _qstring &nowarn_sprnt(const char *format, ...) //-V524 body is equal to sprnt - { - va_list va; - va_start(va, format); - vsprnt(format, va); - va_end(va); - return *this; - } - GCC_DIAG_ON(format-nonliteral); - /// Fill qstring with a character. - /// The qstring is resized if necessary until 'len' chars have been filled - /// \param pos starting position - /// \param c the character to fill - /// \param len number of positions to fill with 'c' - _qstring &fill(size_t pos, qchar c, size_t len) - { - size_t endp = pos + len + 1; - if ( body.size() < endp ) - { - body.resize_noinit(endp); - body[endp-1] = '\0'; - } - memset(body.begin()+pos, c, len); - return *this; - } - /// Clear contents of qstring and fill with 'c' - _qstring &fill(qchar c, size_t len) - { - body.qclear(); - if ( len > 0 ) - resize(len, c); - return *this; - } - /// Remove all instances of the specified char from the beginning of the qstring - _qstring <rim(qchar blank = ' ') - { - if ( !empty() ) - { - iterator b = body.begin(); - iterator e = body.end()-1; - while ( b < e && *b == blank ) - b++; - if ( b > body.begin() ) - { - memmove(body.begin(), b, sizeof(qchar)*(e-b+1)); - resize(e-b); - } - } - return *this; - } - /// Remove all instances of the specified char from the end of the qstring - _qstring &rtrim(qchar blank = ' ') - { - if ( !empty() ) - { - iterator b = body.begin(); - iterator e = body.end()-1; - while ( e > b && *(e-1) == blank ) - e--; - resize(e-b); - } - return *this; - } - /// Remove all instances of the specified char from both ends of the qstring - _qstring &trim2(qchar blank = ' ') - { - rtrim(blank); - ltrim(blank); - return *this; - } - /// Invalid position - static constexpr size_t npos = (size_t) -1; -}; -typedef _qstring<char> qstring; ///< regular string -typedef _qstring<uchar> qtype; ///< type string -typedef _qstring<wchar16_t> qwstring; ///< unicode string -typedef qvector<qstring> qstrvec_t; ///< vector of strings -typedef qvector<qwstring> qwstrvec_t; ///< vector of unicode strings - -/// Vector of bytes (use for dynamic memory) -class bytevec_t: public qvector<uchar> -{ -public: - /// Constructor - bytevec_t() {} - /// Constructor - fill bytevec with 'sz' bytes from 'buf' - bytevec_t(const void *buf, size_t sz) { append(buf, sz); } - /// Append bytes to the bytevec - /// \param buf pointer to buffer that will be appended - /// \param sz size of buffer - bytevec_t &append(const void *buf, size_t sz) - { - if ( sz > 0 ) - { - size_t cur_sz = size(); - size_t new_sz = cur_sz + sz; - if ( new_sz < cur_sz ) - new_sz = BADMEMSIZE; // integer overflow, ask too much and it will throw - resize(new_sz); - memcpy(begin() + cur_sz, buf, sz); - } - return *this; - } - /// Pack a byte and append the result to the bytevec - void pack_db(uint8 x) { push_back(x); } - /// Pack a word and append the result to the bytevec - void pack_dw(uint16 x) - { - uchar packed[dw_packed_size]; - size_t len = ::pack_dw(packed, packed+sizeof(packed), x) - packed; - append(packed, len); - } - /// Pack a dword and append the result to the bytevec - void pack_dd(uint32 x) - { - uchar packed[dd_packed_size]; - size_t len = ::pack_dd(packed, packed+sizeof(packed), x) - packed; - append(packed, len); - } - /// Pack a quadword and append the result to the bytevec - void pack_dq(uint64 x) - { - uchar packed[dq_packed_size]; - size_t len = ::pack_dq(packed, packed+sizeof(packed), x) - packed; - append(packed, len); - } - /// Pack an ea value and append the result to the bytevec - void pack_ea(ea_t x) - { - uchar packed[ea_packed_size]; - size_t len = ::pack_ea(packed, packed+sizeof(packed), x) - packed; - append(packed, len); - } - /// Pack an ea value (64bits) and append the result to the bytevec - /// We pass ea_t as a 64-bit quantity (to be able to debug 32-bit programs with ida64) - /// adding 1 to the address ensures that BADADDR is passed correctly. - /// without it, 32-bit server would return 0xffffffff and ida64 would not consider it - /// as a BADADDR. - void pack_ea64(ea64_t ea) - { - return pack_dq(ea+1); - } - /// Pack a string (length+contents) and append the result to the bytevec - void pack_ds(const char *x) - { - size_t len = strlen(x); -#ifndef __X86__ - QASSERT(4, len <= 0xFFFFFFFF); -#endif - pack_dd(len); - append(x, len); - } - /// Pack a string (zero-terminated) and append the result to the bytevec - void pack_str(const char *str) - { - if ( str == NULL ) - str = ""; - size_t len = strlen(str) + 1; - append(str, len); - } - /// Pack a string (zero-terminated) and append the result to the bytevec - void pack_str(const qstring &s) - { - // the opposite operation is 'unpack_str()' which gets the length - // when it encounters a terminating '\0'. Since we don't store the - // string length, we cannot store zeroes that 's' might contain - // and thus we cannot rely on its length(). - pack_str(s.c_str()); - } - /// Pack an object of size 'len' and append the result to the bytevec - void pack_buf(const void *buf, size_t len) - { -#ifndef __X86__ - QASSERT(5, len <= 0xFFFFFFFF); -#endif - pack_dd(len); - append(buf, len); - } - /// Pack an object of size 'len' and append the result to the bytevec - void pack_bytevec(const bytevec_t &b) - { - pack_buf(b.begin(), b.size()); - } - /// Pack an eavec and append the result to the bytevec. - /// Also see unpack_eavec(). - /// \param ea when we pack an eavec, we only store the differences between each - /// value and this parameter. \n - /// This is because groups of ea values will likely be similar, and therefore - /// the differences will usually be small. \n - /// A good example is packing the addresses of a function prologue. \n - /// One can pass the start ea of the function as this parameter, - /// which results in a quick and efficient packing/unpacking. \n - /// (Just be sure to use the func's start ea when unpacking, of course) - /// \param vec eavec to pack - void pack_eavec(ea_t ea, const eavec_t &vec) - { - int nelems = vec.size(); - pack_dw(nelems); // 16bits, fixme! - ea_t old = ea; - for ( int i=0; i < nelems; i++ ) - { - ea_t nea = vec[i]; - pack_ea(nea-old); - old = nea; - } - } - - /// Grow the bytevec and fill with a value - /// \param sz number of bytes to add to bytevec - /// \param filler filler value - bytevec_t &growfill(size_t sz, uchar filler=0) - { - if ( sz > 0 ) - { - size_t cur_sz = size(); - size_t new_sz = cur_sz + sz; - if ( new_sz < cur_sz ) - new_sz = BADMEMSIZE; // integer overflow, ask too much and it will throw - resize(new_sz, filler); - } - return *this; - } - /// See qvector::inject(T *, size_t) - void inject(void *buf, size_t len) - { - qvector<uchar>::inject((uchar *)buf, len); - } - - /// Is the specified bit set in the bytevec? - bool test_bit(size_t bit) const { return ::test_bit(begin(), bit); } - /// Set the specified bit - void set_bit(size_t bit) { ::set_bit(begin(), bit); } - /// Clear the specified bit - void clear_bit(size_t bit) { ::clear_bit(begin(), bit); } - /// See set_all_bits(uchar *, size_t) - void set_all_bits(size_t nbits) { resize((nbits+7)/8); ::set_all_bits(begin(), nbits); } - /// See clear_all_bits(uchar *, size_t) - void clear_all_bits(size_t nbits) { ::clear_all_bits(begin(), nbits); } - /// For each bit that is set in 'b', set the corresponding bit in this bytevec - void set_bits(const bytevec_t &b) - { - size_t nbytes = b.size(); - if ( size() < nbytes ) - resize(nbytes); - for ( size_t i=0; i < nbytes; i++ ) - at(i) |= b[i]; - } - /// Set each bit between [low, high) - void set_bits(size_t low, size_t high) { ::set_bits(begin(), low, high); } - /// For each bit that is set in 'b', the clear the corresponding bit in this bytevec - void clear_bits(const bytevec_t &b) - { - size_t nbytes = qmin(size(), b.size()); - iterator p = begin(); - for ( size_t i=0; i < nbytes; i++, ++p ) - *p = (uchar)(*p & ~b[i]); - } - /// Clear each bit between [low, high) - void clear_bits(size_t low, size_t high) { ::clear_bits(begin(), low, high); } -}; - -/// Relocation information (relocatable objects - see ::relobj_t) -struct reloc_info_t : public bytevec_t -{ -/// \defgroup RELOBJ_ Relocatable object info flags -/// used by relobj_t::ri -//@{ -#define RELOBJ_MASK 0xF ///< the first byte describes the relocation entry types -#define RELSIZE_1 0 ///< 8-bit relocations -#define RELSIZE_2 1 ///< 16-bit relocations -#define RELSIZE_4 2 ///< 32-bit relocations -#define RELSIZE_8 3 ///< 64-bit relocations -#define RELSIZE_CUST 15 ///< custom relocations, should be handled internally -#define RELOBJ_CNT 0x80 ///< counter present (not used yet) -//@} -}; - -idaman THREAD_SAFE bool ida_export relocate_relobj(struct relobj_t *_relobj, ea_t ea, bool mf); - -/// Relocatable object -struct relobj_t : public bytevec_t -{ - ea_t base; ///< current base - reloc_info_t ri; ///< relocation info - - relobj_t(void) : base(0) {} - bool relocate(ea_t ea, bool mf) { return relocate_relobj(this, ea, mf); } ///< mf=1:big endian -}; - -#define QLIST_DEFINED ///< signal that the qlist class has been defined -/// Linked list -/// Note: linked list is not movable! -template <class T> class qlist -{ - struct listnode_t - { - listnode_t *next; - listnode_t *prev; - void fix_links(size_t len) - { - if ( len == 0 ) - { - next = this; - prev = this; - } - else - { - next->prev = this; - prev->next = this; - } - } - }; - - struct datanode_t : public listnode_t - { - T data; - }; - - listnode_t node; - size_t length; - - void init(void) - { - node.next = &node; - node.prev = &node; - length = 0; - } - -public: - typedef T value_type; - class const_iterator; -/// Used for defining the 'iterator' and 'const_iterator' classes for qlist -#define DEFINE_LIST_ITERATOR(iter, constness, cstr) \ - class iter \ - { \ - friend class qlist<T>; \ - constness listnode_t *cur; \ - iter(constness listnode_t *x) : cur(x) {} \ - public: \ - typedef constness T value_type; \ - iter(void) : cur(NULL) {} \ - iter(const iter &x) : cur(x.cur) {} \ - cstr \ - iter &operator=(const iter &x) { cur = x.cur; return *this; } \ - bool operator==(const iter &x) const { return cur == x.cur; } \ - bool operator!=(const iter &x) const { return cur != x.cur; } \ - constness T &operator*(void) const { return ((datanode_t*)cur)->data; } \ - constness T *operator->(void) const { return &(operator*()); } \ - iter &operator++(void) /* prefix ++ */ \ - { \ - cur = cur->next; \ - return *this; \ - } \ - iter operator++(int) /* postfix ++ */ \ - { \ - iter tmp = *this; \ - ++(*this); \ - return tmp; \ - } \ - iter &operator--(void) /* prefix -- */ \ - { \ - cur = cur->prev; \ - return *this; \ - } \ - iter operator--(int) /* postfix -- */ \ - { \ - iter tmp = *this; \ - --(*this); \ - return tmp; \ - } \ - }; - DEFINE_LIST_ITERATOR(iterator,, friend class const_iterator; ) - DEFINE_LIST_ITERATOR(const_iterator, const, const_iterator(const iterator &x) : cur(x.cur) {} ) - -/// Used to define qlist::reverse_iterator and qlist::const_reverse_iterator -#define DEFINE_REVERSE_ITERATOR(riter, iter) \ - class riter \ - { \ - iter p; \ - public: \ - riter(void) {} \ - riter(const iter &x) : p(x) {} \ - typename iter::value_type &operator*(void) const { iter q=p; return *--q; } \ - typename iter::value_type *operator->(void) const { return &(operator*()); } \ - riter &operator++(void) { --p; return *this; } \ - riter operator++(int) { iter q=p; --p; return q; } \ - riter &operator--(void) { ++p; return *this; } \ - riter operator--(int) { iter q=p; ++p; return q; } \ - bool operator==(const riter &x) const { return p == x.p; } \ - bool operator!=(const riter &x) const { return p != x.p; } \ - }; - DEFINE_REVERSE_ITERATOR(reverse_iterator, iterator) - DEFINE_REVERSE_ITERATOR(const_reverse_iterator, const_iterator) -#undef DEFINE_LIST_ITERATOR -#undef DEFINE_REVERSE_ITERATOR - /// Constructor - qlist(void) { init(); } - /// Constructor - creates a qlist identical to 'x' - qlist(const qlist<T> &x) - { - init(); - insert(begin(), x.begin(), x.end()); - } - /// Destructor - ~qlist(void) - { - clear(); - } - DEFINE_MEMORY_ALLOCATION_FUNCS() - - /// Construct a new qlist using '=' - qlist<T> &operator=(const qlist<T> &x) - { - if ( this != &x ) - { - iterator first1 = begin(); - iterator last1 = end(); - const_iterator first2 = x.begin(); - const_iterator last2 = x.end(); - while ( first1 != last1 && first2 != last2 ) - *first1++ = *first2++; - if ( first2 == last2 ) - erase(first1, last1); - else - insert(last1, first2, last2); - } - return *this; - } - /// Set this = x and x = this, without copying any memory - void swap(qlist<T> &x) - { - std::swap(node, x.node); - std::swap(length, x.length); - node.fix_links(length); - x.node.fix_links(x.length); - } - - iterator begin(void) { return node.next; } ///< Get a pointer to the head of the list - iterator end(void) { return &node; } ///< Get a pointer to the end of the list - bool empty(void) const { return length == 0; } ///< Get true if the list has 0 elements - size_t size(void) const { return length; } ///< Get the number of elements in the list - T &front(void) { return *begin(); } ///< Get the first element in the list - T &back(void) { return *(--end()); } ///< Get the last element in the list - - const_iterator begin(void) const { return node.next; } ///< \copydoc begin - const_iterator end(void) const { return &node; } ///< \copydoc end - const T&front(void) const { return *begin(); } ///< \copydoc front - const T&back(void) const { return *(--end()); } ///< \copydoc end - - reverse_iterator rbegin() { return reverse_iterator(end()); } ///< Get a reverse iterator that points to end of list. See DEFINE_REVERSE_ITERATOR - reverse_iterator rend() { return reverse_iterator(begin()); } ///< Get a reverse iterator that points to beginning of list. See DEFINE_REVERSE_ITERATOR - const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } ///< See rbegin() - const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } ///< See rend() - - /// Insert an element into the qlist. - /// \param p the position to insert the element - /// \param x the element to be inserted - /// \return position of newly inserted element - iterator insert(iterator p, const T &x) - { - datanode_t *tmp = (datanode_t*)qalloc_or_throw(sizeof(datanode_t)); - new (&(tmp->data)) T(x); - linkin(p, tmp); - return tmp; - } - /// Insert an empty element into the qlist. - /// \param p position to insert the element - /// \return reference to this new element - iterator insert(iterator p) - { - datanode_t *tmp = (datanode_t*)qalloc_or_throw(sizeof(datanode_t)); - new (&(tmp->data)) T(); - linkin(p, tmp); - return tmp; - } - /// Insert all elements between 'first' and 'last' (non-inclusive) - /// at position pointed to by 'p' - template <class it2> void insert(iterator p, it2 first, it2 last) - { - while ( first != last ) - insert(p, *first++); - } - /// Insert at beginning of list - void push_front(const T &x) { insert(begin(), x); } - /// Insert at end of list - void push_back(const T &x) { insert(end(), x); } - /// Insert empty element at end of list - T &push_back(void) - { - iterator p = insert(end()); - return ((datanode_t *)p.cur)->data; - } - /// Erase element at position pointed to by 'p' - iterator erase(iterator p) - { - listnode_t *q = p.cur->next; - p.cur->prev->next = p.cur->next; - p.cur->next->prev = p.cur->prev; - ((datanode_t*)p.cur)->data.~T(); - qfree(p.cur); - --length; - return q; - } - /// Erase all elements between 'p1' and 'p2' - void erase(iterator p1, iterator p2) - { - while ( p1 != p2 ) - p1 = erase(p1); - } - /// Erase all elements in the qlist - void clear(void) { erase(begin(), end()); } - /// Erase first element of the qlist - void pop_front(void) { erase(begin()); } - /// Erase last element of the qlist - void pop_back(void) { iterator tmp = end(); erase(--tmp); } - /// Compare two qlists with '==' - bool operator==(const qlist<T> &x) const - { - if ( length != x.length ) - return false; - const_iterator q=x.begin(); - for ( const_iterator p=begin(), e=end(); p != e; ++p,++q ) - if ( *p != *q ) - return false; - return true; - } - /// Compare two qlists with != - bool operator!=(const qlist<T> &x) const { return !(*this == x); } -private: - void linkin(iterator p, listnode_t *tmp) - { - tmp->next = p.cur; - tmp->prev = p.cur->prev; - p.cur->prev->next = tmp; - p.cur->prev = tmp; - ++length; - } -}; - -// Our containers do not care about their addresses. They can be moved around with simple memcpy -/// \cond -template <class T> struct ida_movable_type<qvector<T> > { static constexpr bool value = true; }; -template <class T> struct ida_movable_type<_qstring<T> > { static constexpr bool value = true; }; -template <class T> struct ida_movable_type<qlist<T> > { static constexpr bool value = false; }; -template <class T> struct ida_movable_type<qiterator<T> > { static constexpr bool value = true; }; -/// \endcond - -//---------------------------------------------------------------------------- -#ifndef SWIG -/// Unpack a vector of ea values. -/// \param[out] vec resulting vector -/// \param ea base value that was used to pack the eavec (see pack_eavec()) -/// \param ptr pointer to packed eavec -/// \param end pointer to end of packed eavec - -THREAD_SAFE inline void unpack_eavec( - eavec_t *vec, - ea_t ea, - const uchar **ptr, - const uchar *end) -{ - ea_t old = ea; - int n = unpack_dw(ptr, end); - vec->resize(n); - for ( int i=0; i < n; i++ ) - { - old += unpack_ea(ptr, end); - vec->at(i) = old; - } -} - -THREAD_SAFE inline bool unpack_bytevec( - bytevec_t *out, - const uchar **pptr, - const uchar *end) -{ - uint32 nbytes = unpack_dd(pptr, end); - if ( nbytes == 0 ) - return true; - const size_t old_size = out->size(); - out->resize(old_size + nbytes); - return unpack_obj(out->begin() + old_size, nbytes, pptr, end) != NULL; -} - -inline bool unpack_str(qstring *out, const uchar **pptr, const uchar *end) -{ // zero terminated string, append to qstring - const char *str = unpack_str(pptr, end); - if ( str == nullptr ) - return false; - out->append(str, ((char*)*pptr-str) - 1); - return true; -} - -// Convenience struct for unpacking a data stream -THREAD_SAFE struct memory_deserializer_t -{ - const uchar *ptr; - const uchar *end; - - memory_deserializer_t(const qstring &s) : ptr((uchar*)s.begin()), end(ptr+s.size()) {} - memory_deserializer_t(const bytevec_t &b) : ptr(b.begin()), end(b.end()) {} - memory_deserializer_t(const uchar *p, const uchar *e) : ptr(p), end(e) {} - memory_deserializer_t(const void *p, size_t s) : ptr((uchar*)p), end(ptr+s) {} - bool empty() const { return ptr >= end; } - size_t size() const { return end-ptr; } - bool advance(size_t s) { if ( size() < s ) return false; ptr += s; return true; } - uint8 unpack_db() { return ::unpack_db(&ptr, end); } - uint16 unpack_dw() { return ::unpack_dw(&ptr, end); } - uint32 unpack_dd() { return ::unpack_dd(&ptr, end); } - uint64 unpack_dq() { return ::unpack_dq(&ptr, end); } - ea_t unpack_ea() { return ::unpack_ea(&ptr, end); } - ea64_t unpack_ea64() { return ::unpack_ea64(&ptr, end); } - // unpack zero terminated string - const char *unpack_str() { return ::unpack_str(&ptr, end); } - bool unpack_str(qstring *out) { return ::unpack_str(out, &ptr, end); } - // string with length prefix (dd), return string allocated in the heap - char *unpack_ds(bool empty_null=false) - { - return ::unpack_ds(&ptr, end, empty_null); - } - // string with length prefix (dd), return in the specified buffer - bool unpack_ds_to_buf(char *buf, size_t bufsize) - { - return ::unpack_ds_to_buf(buf, bufsize, &ptr, end); - } - const void *unpack_obj_inplace(size_t objsize) - { - return ::unpack_obj_inplace(&ptr, end, objsize); - } - const void *unpack_buf_inplace() - { - return ::unpack_buf_inplace(&ptr, end); - } - const void *unpack_obj(void *obj, size_t objsize) - { - return ::unpack_obj(obj, objsize, &ptr, end); - } - const void *unpack_buf() - { - return ::unpack_buf(&ptr, end); - } - void unpack_eavec(eavec_t *vec, ea_t ea) - { - ::unpack_eavec(vec, ea, &ptr, end); - } - bool unpack_bytevec(bytevec_t *out) - { - return ::unpack_bytevec(out, &ptr, end); - } - #define SCALAR_TYPE(n) class T, typename std::enable_if<std::is_scalar<T>::value && sizeof(T) == n, int>::type = 0 - template <SCALAR_TYPE(1)> void unpack(T *out) { *out = (T)unpack_db(); } - template <SCALAR_TYPE(2)> void unpack(T *out) { *out = unpack_dw(); } - template <SCALAR_TYPE(4)> void unpack(T *out) { *out = unpack_dd(); } - template <SCALAR_TYPE(8)> void unpack(T *out) { *out = unpack_dq(); } - #undef SCALAR_TYPE - void unpack(qstring *out) { *out = unpack_str(); } - template <class T> - void unpack(qvector<T> *out) - { - uint32 cnt = unpack_dd(); - out->qclear(); - out->reserve(cnt); - for ( size_t i = 0; i < cnt; i++ ) - unpack(&out->push_back()); - } - // linput_t like interface - ssize_t read(void *obj, size_t objsize) { return unpack_obj(obj, objsize) ? objsize : -1; } - bool eof() const { return empty(); } -}; -#define DECLARE_MEMORY_DESERIALIZER(name) \ - name(const void *p, size_t s) : memory_deserializer_t(p, s) {} \ - using memory_deserializer_t::unpack; \ - -#endif // SWIG - -//------------------------------------------------------------------------- -/// Resource janitor to facilitate use of the RAII idiom -template <typename T> -struct janitor_t -{ - janitor_t(T &r) : resource(r) {} ///< Constructor - ~janitor_t(); ///< We provide no implementation for this function, you should - ///< provide specialized implementation yourself -protected: - T &resource; -}; - -#ifndef SWIG -//------------------------------------------------------------------------- -/// Template to compare any 2 values of the same type. Returns -1/0/1 -template <typename, typename = void> -struct has_compare_method : std::false_type {}; -// std::void_t is from c++17, so we declare it ourselves -template< class... > using qvoid_t = void; -template <typename T> -struct has_compare_method<T, qvoid_t<decltype(std::declval<T>().compare(std::declval<T>()))>> - : std::true_type {}; -template <class T, typename std::enable_if<has_compare_method<T>::value, int>::type = 0> -int compare(const T &a, const T &b) -{ - return a.compare(b); -} -template <class T, typename std::enable_if<!has_compare_method<T>::value, int>::type = 0> -int compare(const T &a, const T &b) -{ - if ( a < b ) - return -1; - if ( a > b ) - return 1; - return 0; -} - -//------------------------------------------------------------------------- -template <class T> -int compare(const qvector<T> &a, const qvector<T> &b) -{ - return compare_containers(a, b); -} - -//------------------------------------------------------------------------- -template <class T> -int compare(const qlist<T> &a, const qlist<T> &b) -{ - return compare_containers(a, b); -} - -//------------------------------------------------------------------------- -template <class T, class U> -int compare(const std::pair<T, U> &a, const std::pair<T, U> &b) -{ - int code = compare(a.first, b.first); - if ( code != 0 ) - return code; - return compare(a.second, b.second); -} - -//------------------------------------------------------------------------- -/// Template to compare any 2 containers of the same type. Returns -1/0/1 -template <class T> -int compare_containers(const T &l, const T &r) -{ - auto p = std::begin(l); - auto pe = std::end(l); - auto q = std::begin(r); - auto qe = std::end(r); - for ( ; p != pe && q != qe; ++p,++q ) - { - int code = compare(*p, *q); - if ( code != 0 ) - return code; - } - if ( p == pe && q != qe ) - return -1; - if ( p != pe && q == qe ) - return 1; - return 0; -} -#endif - -//------------------------------------------------------------------------- -/// Align element up to nearest boundary -template <class T> T align_up(T val, int elsize) -{ - int mask = elsize - 1; - val += mask; - val &= ~mask; - return val; -} - -//------------------------------------------------------------------------- -/// Align element down to nearest boundary -template <class T> T align_down(T val, int elsize) -{ - int mask = elsize - 1; - val &= ~mask; - return val; -} - -//------------------------------------------------------------------------- -/// \def{DEFINE_VIRTUAL_DTOR, -/// GCC generates multiple destructors and they occupy multiple slots of the -/// virtual function table. Since it makes the vft incompatible with other -/// compilers - we simply never generate virtual destructors for gcc. This is not an -/// ideal solution but it works. -/// We have this problem only under MS Windows. On other platforms everything is -/// compiled with GCC so the vft layout is the same for the kernel and plugins.} -/// \def{DECLARE_VIRTUAL_DTOR, see #DEFINE_VIRTUAL_DTOR} -#if defined(SWIG) - #define DEFINE_VIRTUAL_DTOR(name) - #define DECLARE_VIRTUAL_DTOR(name) -#elif defined(__GNUC__) && defined(__NT__) - #define DEFINE_VIRTUAL_DTOR(name) virtual void idaapi dummy_dtor_for_gcc(void) {} - #define DECLARE_VIRTUAL_DTOR(name) virtual void idaapi dummy_dtor_for_gcc(void) -#else - #define DEFINE_VIRTUAL_DTOR(name) virtual ~name(void) {} - #define DECLARE_VIRTUAL_DTOR(name) virtual ~name(void) -#endif - -/// Declare class as uncopyable. -/// (copy assignment and copy ctr are undefined, so if anyone calls them, -/// there will be a compilation or link error) -#define DECLARE_UNCOPYABLE(T) T &operator=(const T &); T(const T &); - -#ifndef SWIG -//------------------------------------------------------------------------- -// check the variable type -/// \cond -#define IS_QSTRING(v) (std::is_base_of<qstring, std::remove_reference<decltype(v)>::type>::value) -#define IS_SIZEVEC_T(v) (std::is_base_of<sizevec_t, std::remove_reference<decltype(v)>::type>::value) -#define IS_QSTRVEC_T(v) (std::is_base_of<qstrvec_t, std::remove_reference<decltype(v)>::type>::value) - -/// \endcond -#endif - -#endif // __cplusplus - -#ifndef __cplusplus -typedef struct bytevec_tag bytevec_t; -typedef struct qstring_tag qstring; -typedef struct qwstring_tag qwstring; -#endif - -/// Encode base64 - -idaman THREAD_SAFE bool ida_export base64_encode(qstring *output, const void *input, size_t size); - -/// Decode base64 - -idaman THREAD_SAFE bool ida_export base64_decode(bytevec_t *output, const char *input, size_t size); ///< Decode base64 - - -/// Convert tabulations to spaces -/// \param out output buffer to append to -/// \param str input string. cannot be equal to out->c_str() -/// \param tabsize tabulation size -/// \returns true-replaced some tabs - -idaman THREAD_SAFE bool ida_export replace_tabs(qstring *out, const char *str, int tabsize); - - -/// \defgroup c_str_conv Functions: c strings -/// String C-style conversions (convert \\n to a newline and vice versa) -//@{ -idaman THREAD_SAFE char *ida_export str2user(char *dst, const char *src, size_t dstsize); ///< Make a user representation -idaman THREAD_SAFE char *ida_export user2str(char *dst, const char *src, size_t dstsize); ///< Make an internal representation -idaman THREAD_SAFE char ida_export back_char(const char **p); ///< Translate char after '\\' -#ifdef __cplusplus -idaman THREAD_SAFE void ida_export qstr2user(qstring *dst, const char *src, int nsyms=-1);///< see str2user() -inline THREAD_SAFE void qstr2user(qstring *dst, const qstring &src) { qstr2user(dst, src.c_str(), src.length()); } -idaman THREAD_SAFE void ida_export user2qstr(qstring *dst, const qstring &src); ///< see user2str() -#else -idaman THREAD_SAFE void ida_export qstr2user(qstring *dst, const qstring *src); ///< see str2user() -idaman THREAD_SAFE void ida_export user2qstr(qstring *dst, const qstring *src); ///< see user2str() -#endif -//@} - - -/// Does byte sequence consist of valid UTF-8-encoded codepoints? -/// \param in the byte sequence -/// \returns success - -idaman THREAD_SAFE bool ida_export is_valid_utf8(const char *in); - - -#ifdef __cplusplus - -/// UTF-8 -> UTF-16 -/// \param out the output buffer -/// \param in the input UTF-8 byte stream -/// \param nsyms the number of UTF-8-encoded codepoints in the byte stream -/// \returns success -idaman THREAD_SAFE bool ida_export utf8_utf16(qwstring *out, const char *in, int nsyms=-1); - - -/// UTF-16 -> UTF-8 -/// \param out the output buffer -/// \param in the input UTF-16 stream -/// \param nsyms the number of 16-bit items in 'in'. This does not necessarily -/// correspond to the number of codepoints: each surrogate pair -/// will take 2 items. -/// \returns success -idaman THREAD_SAFE bool ida_export utf16_utf8(qstring *out, const wchar16_t *in, int nsyms=-1); - - -inline bool is_lead_surrogate(wchar32_t wch) { return 0xD800 <= wch && wch < 0xDC00; } -inline bool is_tail_surrogate(wchar32_t wch) { return 0xDC00 <= wch && wch <= 0xDFFF; } -inline wchar32_t utf16_surrogates_to_cp(wchar16_t lead_surrogate, wchar16_t tail_surrogate) -{ - return (0x10000 + (wchar32_t(lead_surrogate & 0x3FF) << 10)) | (tail_surrogate & 0x3FF); -} - - -/// \defgroup IDBDEC_ IDB default encoding -> UTF-8 encoding flags -/// used by idb_utf8 -//@{ -#define IDBDEC_ESCAPE 0x00000001 ///< convert non-printable characters to C escapes (\n, \xNN, \uNNNN) -//@} - -/// IDB default C string encoding -> UTF-8 -/// \returns success (i.e., all bytes converted) - -idaman THREAD_SAFE bool ida_export idb_utf8(qstring *out, const char *in, int nsyms=-1, int flags=0); - - -#ifdef __NT__ -// These are typically used in the text UI (TUI), and -// also to convert argv to UTF-8 at startup. -idaman THREAD_SAFE bool ida_export change_codepage( - qstring *out, - const char *in, - int incp, - int outcp); -#ifndef CP_ACP -#define CP_ACP 0 -#endif -#ifndef CP_OEM -#define CP_OEM 1 -#endif -#ifndef CP_UTF8 -#define CP_UTF8 65001 -#endif -INLINE THREAD_SAFE bool acp_utf8(qstring *out, const char *in) -{ - return change_codepage(out, in, CP_ACP, CP_UTF8); -} -#else // !__NT__ -INLINE THREAD_SAFE bool idaapi change_codepage(qstring *, const char *, int, int) { return false; } -#endif // __NT__ - - -//------------------------------------------------------------------------- -// helpers to compose 16/32-bit wchar's from [M]UTF-8-encoded data -inline THREAD_SAFE wchar16_t utf8_wchar16(uchar b0, uchar b1) -{ - return (wchar16_t(b0 & 0x1f) << 6) | (b1 & 0x3f); -} - -//------------------------------------------------------------------------- -inline THREAD_SAFE wchar16_t utf8_wchar16(uchar b0, uchar b1, uchar b2) -{ - return (wchar16_t(b0 & 0x0f) << 12) - | (wchar16_t(b1 & 0x3f) << 6) - | (b2 & 0x3f); -} - -//------------------------------------------------------------------------- -inline THREAD_SAFE wchar32_t utf8_wchar32(uchar b0, uchar b1, uchar b2, uchar b3) -{ - return (wchar32_t(b0 & 0x07) << 18) - | (wchar32_t(b1 & 0x3f) << 12) - | (wchar32_t(b2 & 0x3f) << 6) - | (b3 & 0x3f); -} - -#endif // __cplusplus - - -#define BADCP wchar32_t(-1) - -/// Read one UTF-8 character from string. if error, return BADCP - -idaman THREAD_SAFE wchar32_t ida_export get_utf8_char(const char **pptr); - - -/// Get the UTF-8 character from string, before 'p'. -/// -/// \param out_cp the output codepoint storage. May be NULL. -/// \param p the pointer, pointing in the 'begin' string right after the UTF-8-encoded codepoint we want to retrieve -/// \param begin the beginning of the string -/// \returns success - -idaman THREAD_SAFE bool ida_export prev_utf8_char(wchar32_t *out_cp, const char **p, const char *begin); - - -/// Advance by n codepoints into the UTF-8 buffer. -/// -/// Each bad byte (i.e., can't be decoded as UTF-8) will count as 1 codepoint. -/// In addition, encountering an unexpected end-of-string (i.e., '\0') will -/// cause this function to stop and return a non-zero value. -/// -/// \param putf8 a pointer to the UTF-8 bytes buffer to advance into -/// \param n the number of codepoints to advance into the buffer -/// \returns the number of codepoints that we failed to decode, thus: -/// 0 - success, >0 - a terminating zero was encountered. - -idaman THREAD_SAFE size_t ida_export skip_utf8(const char **putf8, size_t n); - - -/// Encode the codepoint into a UTF-8 byte sequence, and add terminating zero -/// \param out output buffer (must be at least MAX_UTF8_SEQ_LEN bytes wide) -/// \param cp the codepoint to encode -/// \returns how many bytes were put into the output buffer -/// (without the terminating zero), or size_t(-1) on failure - -idaman THREAD_SAFE ssize_t ida_export put_utf8_char(char *out, wchar32_t cp); - - -/// Is the provided codepoint graphical? - -idaman THREAD_SAFE bool ida_export is_cp_graphical(wchar32_t cp); - - -// Get number of codepoints in UTF-8 string. Any 'bad' byte -// (i.e., can't be decoded) counts for 1 codepoint. - -idaman THREAD_SAFE size_t ida_export qustrlen(const char *utf8); - - -/// A safer strncpy - makes sure that there is a terminating zero. -/// nb: this function doesn't truncate the last UTF-8 character. -/// \sa qstrncpy() -/// \retval false if the input buffer was truncated - -idaman THREAD_SAFE bool ida_export qustrncpy(char *dst, const char *utf8, size_t dstsize); - - -// A few Unicode-related helpful defines - -#define CP_BOM 0xFEFF -#define UTF8_BOM "\xEF\xBB\xBF" -#define UTF8_BOM_SZ (sizeof(UTF8_BOM) - 1) - -#define UTF16LE_BOM "\xFF\xFE" -#define UTF16BE_BOM "\xFE\xFF" -#define UTF16_BOM_SZ (sizeof(UTF16LE_BOM) - 1) - -#define UTF32LE_BOM "\xFF\xFE\x00\x00" -#define UTF32BE_BOM "\x00\x00\xFE\xFF" -#define UTF32_BOM_SZ (sizeof(UTF32LE_BOM) - 1) - -#define CP_ELLIPSIS 0x2026 -#define UTF8_ELLIPSIS "\xE2\x80\xA6" -#define UTF8_ELLIPSIS_SZ (sizeof(UTF8_ELLIPSIS) - 1) - -#define CP_REPLCHAR 0xFFFD -#define UTF8_REPLCHAR "\xEF\xBF\xBD" -#define UTF8_REPLCHAR_SZ (sizeof(UTF8_REPLCHAR) - 1) - - -// To cover unicode, 4 bytes is enough. Still, from the UTF-8 spec at -// https://tools.ietf.org/html/rfc3629: -// "Another security issue occurs when encoding to UTF-8: the ISO/IEC -// 10646 description of UTF-8 allows encoding character numbers up to -// U+7FFFFFFF, yielding sequences of up to 6 bytes. There is therefore -// a risk of buffer overflow if the range of character numbers is not -// explicitly limited to U+10FFFF or if buffer sizing doesn't take into -// account the possibility of 5- and 6-byte sequences." -// Furthermore, since buffers holding UTF-8 sequences are usually placed -// onto the stack, it's probably not a bad thing to make them 8-bytes -// aligned -- and keep room for a terminating zero, too. -#define MAX_UTF8_SEQ_LEN (6 + 1 + 1) - - - -/// \defgroup CEF_ Convert encoding flags -/// used by convert_encoding -//@{ -#define CEF_RETERR 0x1 // return -1 if iconv() returns -1 -//@} - -/// Convert data from encoding fromcode into tocode. -/// \param flags see CEF_* -/// \return number of input bytes converted (can be less than actual size if there was an invalid character) -/// -1 if source or target encoding is not supported -/// possible encoding names: windows codepages ("CP1251" etc), charset names ("Shift-JIS"), and many encodings supported by iconv - -idaman ssize_t ida_export convert_encoding( - bytevec_t *out, - const char *fromcode, - const char *tocode, - const uchar *indata, - ssize_t insize, - DEFARG(int flags,0)); - -#ifdef __cplusplus -inline ssize_t convert_encoding( - bytevec_t *out, - const char *fromcode, - const char *tocode, - const bytevec_t *indata, - DEFARG(int flags,0)) -{ - QASSERT(1451, ssize_t(indata->size()) >= 0); - return convert_encoding(out, fromcode, tocode, indata->begin(), indata->size(), flags); -} -#endif - -#define ENC_WIN1252 "windows-1252" -#define ENC_UTF8 "UTF-8" -#define ENC_MUTF8 "MUTF-8" // modified UTF-8, used by Dalvik and Java (https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8) -#define ENC_UTF16 "UTF-16" -#define ENC_UTF16LE "UTF-16LE" -#define ENC_UTF16BE "UTF-16BE" -#define ENC_UTF32 "UTF-32" -#define ENC_UTF32LE "UTF-32LE" -#define ENC_UTF32BE "UTF-32BE" - - - -#ifndef CP_UTF8 -#define CP_UTF8 65001 ///< UTF-8 codepage -#endif - -#ifndef CP_UTF16 -#define CP_UTF16 1200 ///< UTF-16 codepage -#endif - -#ifdef __NT__ -# ifndef INVALID_FILE_ATTRIBUTES -# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) ///< old Visual C++ compilers were not defining this -# endif -# ifndef BELOW_NORMAL_PRIORITY_CLASS -# define BELOW_NORMAL_PRIORITY_CLASS 0x00004000 ///< \copydoc INVALID_FILE_ATTRIBUTES -# endif -#endif - -#define SUBSTCHAR '_' ///< default char, used if a char cannot be represented in a codepage - -typedef uint32 flags_t; ///< 32-bit flags for each address -typedef ea_t tid_t; ///< type id (for enums, structs, etc) - -typedef uint32 bgcolor_t; ///< background color in RGB -#define DEFCOLOR bgcolor_t(-1) ///< default color (used in function, segment definitions) - -//------------------------------------------------------------------------- -// Command line -//------------------------------------------------------------------------- - -#ifdef __cplusplus -/// Tools for command line parsing -struct channel_redir_t -{ - int fd; ///< channel number - qstring file; ///< file name to redirect to/from. - ///< if empty, the channel must be closed. - int flags; ///< \ref IOREDIR_ -/// \defgroup IOREDIR_ i/o redirection flags -/// used by channel_redir_t::flags -//@{ -#define IOREDIR_INPUT 0x01 ///< input redirection -#define IOREDIR_OUTPUT 0x02 ///< output redirection -#define IOREDIR_APPEND 0x04 ///< append, do not overwrite the output file -#define IOREDIR_QUOTED 0x08 ///< the file name was quoted -//@} - bool is_input(void) const { return (flags & IOREDIR_INPUT) != 0; } - bool is_output(void) const { return (flags & IOREDIR_OUTPUT) != 0; } - bool is_append(void) const { return (flags & IOREDIR_APPEND) != 0; } - bool is_quoted(void) const { return (flags & IOREDIR_QUOTED) != 0; } - int start; ///< begin of the redirection string in the command line - int length; ///< length of the redirection string in the command line -}; -typedef qvector<channel_redir_t> channel_redirs_t; ///< vector of channel_redir_t objects -#else -typedef struct channel_redirs_tag channel_redirs_t; -typedef struct qstrvec_tag qstrvec_t; -#endif - -/// Parse a space separated string (escaping with backslash is supported). -/// \param[out] args a string vector to hold the results -/// \param[out] redirs map of channel redirections found in cmdline -/// - if NULL, redirections won't be parsed -/// - if there are syntax errors in redirections, consider them as arguments -/// \param cmdline the string to be parsed -/// \param flags #LP_PATH_WITH_ARGS or 0 -/// \return the number of parsed arguments - -idaman THREAD_SAFE size_t ida_export parse_command_line( - qstrvec_t *args, - channel_redirs_t *redirs, - const char *cmdline, - int flags); - - -/// Copy and expand command line arguments. -/// For '@filename' arguments the file contents are inserted into the resulting argv. -/// Format of the file: one switch per line, ';' for comment lines -/// On windows, argv will also be interpreted as OEM codepage, and -/// will be decoded as such and re-encoded into UTF-8. -/// \param[out] p_argc size of the returned argv array -/// \param argc number of entries in argv array -/// \param argv array of strings -/// \return new argv (terminated by NULL). -/// It must be freed with free_argv() - -char **expand_argv(int *p_argc, int argc, const char *const argv[]); - - -/// Free 'argc' elements of 'argv' - -INLINE void free_argv(int argc, char **argv) -{ - int i; - if ( argv != NULL ) - { - for ( i = 0; i < argc; i++ ) - qfree(argv[i]); - qfree(argv); - } -} - - -/// Quote a command line argument if it contains escape characters. -/// For example, *.c will be converted into "*.c" because * may be inadvertently -/// expanded by the shell -/// \return true: modified 'arg' - -idaman bool ida_export quote_cmdline_arg(qstring *arg); - -//------------------------------------------------------------------------- -// Command-line tools -//------------------------------------------------------------------------- -typedef void cliopt_handler_t(const char *value, void *ud); -typedef void cliopt_poly_handler_t(int argc, const char **argv, void *ud); -struct cliopt_t -{ - char shortname; - const char *longname; - const char *help; - cliopt_handler_t *handler; - int nargs; // number of arguments. Can be 0, 1 or -1. - // If '-1', it means 'poly_handler' will be used -}; -DECLARE_TYPE_AS_MOVABLE(cliopt_t); - -struct cliopts_t; -#ifndef SWIG -# define DEFINE_CLIOPTS_T_HELPERS(decl) \ - decl void ida_export cliopts_t_add(cliopts_t &, const cliopt_t *, size_t); \ - decl void ida_export cliopts_t_apply(cliopts_t &, int, const char *[], void *); \ - decl const cliopt_t *ida_export cliopts_t_find_short(const cliopts_t &, char); \ - decl const cliopt_t *ida_export cliopts_t_find_long(const cliopts_t &, const char *); \ - decl void ida_export cliopts_t_usage(const cliopts_t &, bool); -#else -# define DEFINE_CLIOPTS_T_HELPERS(decl) -#endif // SWIG -DEFINE_CLIOPTS_T_HELPERS(idaman) - -struct cliopts_t : public qvector<cliopt_t> -{ - qstring prog_name; - qstring epilog; - typedef AS_PRINTF(1, 2) int usage_printer_t(const char *format, ...); - usage_printer_t *printer; - - cliopts_t(usage_printer_t *_printer) - : printer(_printer) {} - - void add(const cliopt_t *opts, size_t nopts) { cliopts_t_add(*this, opts, nopts); } - void apply(int argc, const char *argv[], void *ud=nullptr) { cliopts_t_apply(*this, argc, argv, ud); } - const cliopt_t *find_short(char shortname) const { return cliopts_t_find_short(*this, shortname); } - const cliopt_t *find_long(const char *longname) const { return cliopts_t_find_long(*this, longname); } - void usage(bool is_error=true) const { return cliopts_t_usage(*this, is_error); } - -private: - DEFINE_CLIOPTS_T_HELPERS(friend); -}; - -//------------------------------------------------------------------------- -// INSTANT DEBUGGING -//------------------------------------------------------------------------- - -#ifdef __cplusplus -/// Options for instant debugging -struct instant_dbgopts_t -{ - qstring debmod; ///< name of debugger module - qstring env; ///< config variables for debmod. example: DEFAULT_CPU=13;MAXPACKETSIZE=-1 - qstring host; ///< remote hostname (if remote debugging) - qstring pass; ///< password for the remote debugger server - int port = 0; ///< port number for the remote debugger server - int pid = -1; ///< process to attach to (-1: ask the user) - int event_id = -1; ///< event to trigger upon attaching - bool attach = false; ///< should attach to a process? -}; -#else -struct instant_dbgopts_t; -#endif - -/// Parse the -r command line switch (for instant debugging). -/// r_switch points to the value of the -r switch. Example: win32@localhost+ -/// \return true-ok, false-parse error - -idaman bool ida_export parse_dbgopts(struct instant_dbgopts_t *ido, const char *r_switch); - - -//------------------------------------------------------------------------- -// PROCESSES -//------------------------------------------------------------------------- - -/// Information for launching a process with IDA API -/// Note: all string data such as paths (e.g., 'path', 'args' & 'startdir') -/// or 'env' should be UTF-8 encoded. -struct launch_process_params_t -{ - size_t cb; ///< size of this structure - int flags; ///< \ref LP_ -/// \defgroup LP_ Launch process flags -/// used by launch_process_params_t::flags -//@{ -#define LP_NEW_CONSOLE 0x0001 ///< create new console (only ms windows) -#define LP_TRACE 0x0002 ///< debug: unix: ptrace(TRACEME), windows: DEBUG_PROCESS -#define LP_PATH_WITH_ARGS 0x0004 ///< 'args' contains executable path too -#define LP_USE_SHELL 0x0008 ///< use shell to launch the command. - ///< 'path' is ignored in this case. -#define LP_LAUNCH_32_BIT 0x0010 ///< prefer to launch 32-bit part of file (only mac) -#define LP_LAUNCH_64_BIT 0x0020 ///< prefer to launch 64-bit part of file (only mac) - ///< only one of LP_LAUNCH_*_BIT bits can be specified -#define LP_NO_ASLR 0x0040 ///< disable ASLR (only mac) -#define LP_DETACH_TTY 0x0080 ///< detach the current tty (unix) -#define LP_HIDE_WINDOW 0x0100 ///< tries to hide new window on startup (only windows) -//@} - const char *path; ///< file to run - const char *args; ///< command line arguments - ssize_t in_handle; ///< handle for stdin or -1 - ssize_t out_handle; ///< handle for stdout or -1 - ssize_t err_handle; ///< handle for stderr or -1 - char *env; ///< zero separated environment variables that will be appended - ///< to the existing environment block (existing variables will be updated). - ///< each variable has the following form: var=value\0 - ///< must be terminated with two zero bytes! - const char *startdir; ///< current directory for the new process - void *info; ///< os specific info (on windows it points to PROCESS_INFORMATION) - ///< on unix, not used -#ifdef __cplusplus - launch_process_params_t(void) ///< constructor - : cb(sizeof(*this)), flags(0), path(NULL), args(NULL), - in_handle(-1), out_handle(-1), err_handle(-1), - env(NULL), startdir(NULL), info(NULL) {} -#endif -}; - -/// Launch the specified process in parallel. -/// \return handle (unix: child pid), NULL - error - -#ifdef __cplusplus -idaman THREAD_SAFE void *ida_export launch_process( - const launch_process_params_t &lpp, - qstring *errbuf=NULL); -#else -idaman THREAD_SAFE void *ida_export launch_process( - const struct launch_process_params_t *lpp, - qstring *errbuf); -#endif - -/// Forcibly terminate a running process. -/// \returns 0-ok, otherwise an error code that can be passed to winerr() - -idaman THREAD_SAFE int ida_export term_process(void *handle); - - -/// Wait for state changes in a child process (UNIX only). -/// Here: child, status, flags - the same as in system call waitpid() -/// \param timeout_ms timeout in milliseconds - -idaman THREAD_SAFE int ida_export qwait_timed(int *status, int child, int flags, int timeout_ms); - -#if defined(__UNIX__) -# ifdef WCONTINUED -# define QWCONTINUED WCONTINUED -# else -# define QWCONTINUED 8 -# endif -# ifdef WNOHANG -# define QWNOHANG WNOHANG -# else -# define QWNOHANG 1 -# endif -inline THREAD_SAFE int qwait(int *status, int child, int flags) -{ - return qwait_timed(status, child, flags, (flags & QWNOHANG) != 0 ? 0 : -1); -} -#endif - - -/// Check whether process has terminated or not. -/// \param handle process handle to wait for -/// \param[out] exit_code pointer to the buffer for the exit code -/// \param msecs how long to wait. special values: -/// - 0: do not wait -/// - 1 or -1: wait infinitely -/// - other values: timeout in milliseconds -/// \retval 0 process has exited, and the exit code is available. -/// if *exit_code < 0: the process was killed with a signal -*exit_code -/// \retval 1 process has not exited yet -/// \retval -1 error happened, see error code for winerr() in *exit_code - -idaman THREAD_SAFE int ida_export check_process_exit( - void *handle, - int *exit_code, - DEFARG(int msecs,-1)); - -/// Teletype control -enum tty_control_t -{ - TCT_UNKNOWN = 0, - TCT_OWNER, - TCT_NOT_OWNER -}; - - -/// Check if the current process is the owner of the TTY specified -/// by 'fd' (typically an opened descriptor to /dev/tty). - -idaman THREAD_SAFE enum tty_control_t ida_export is_control_tty(int fd); - - -/// If the current terminal is the controlling terminal of the calling -/// process, give up this controlling terminal. -/// \note The current terminal is supposed to be /dev/tty - -idaman THREAD_SAFE void ida_export qdetach_tty(void); - - -/// Make the current terminal the controlling terminal of the calling -/// process. -/// \note The current terminal is supposed to be /dev/tty - -idaman THREAD_SAFE void ida_export qcontrol_tty(void); - -//------------------------------------------------------------------------- -/// THREADS -//------------------------------------------------------------------------- - -/// Thread callback function -typedef int idaapi qthread_cb_t(void *ud); - -/// Thread opaque handle -#ifdef __cplusplus -#define OPAQUE_HANDLE(n) typedef struct __ ## n {} *n -#else -#define OPAQUE_HANDLE(n) typedef struct __ ## n { char __dummy; } *n -#endif -OPAQUE_HANDLE(qthread_t); - - -/// Create a thread and return a thread handle - -idaman THREAD_SAFE qthread_t ida_export qthread_create(qthread_cb_t *thread_cb, void *ud); - - -/// Free a thread resource (does not kill the thread) -/// (calls pthread_detach under unix) - -idaman THREAD_SAFE void ida_export qthread_free(qthread_t q); - - -/// Wait a thread until it terminates - -idaman THREAD_SAFE bool ida_export qthread_join(qthread_t q); - - -/// Forcefully kill a thread (calls pthread_cancel under unix) - -idaman THREAD_SAFE bool ida_export qthread_kill(qthread_t q); - - -/// Get current thread. Must call qthread_free() to free it! - -idaman THREAD_SAFE qthread_t ida_export qthread_self(void); - - -/// Is the current thread the same as 'q'? - -idaman THREAD_SAFE bool ida_export qthread_same(qthread_t q); - - -/// Are two threads equal? - -idaman THREAD_SAFE bool ida_export qthread_equal(qthread_t q1, qthread_t q2); - - -/// Are we running in the main thread? - -idaman THREAD_SAFE bool ida_export is_main_thread(void); - - -/// Thread safe function to work with the environment - -idaman THREAD_SAFE bool ida_export qsetenv(const char *varname, const char *value); -idaman THREAD_SAFE bool ida_export qgetenv(const char *varname, DEFARG(qstring *buf,NULL)); ///< \copydoc qsetenv - - -//------------------------------------------------------------------------- -/// Semaphore. -/// Named semaphores are public, nameless ones are local to the process -//------------------------------------------------------------------------- -OPAQUE_HANDLE(qsemaphore_t); - -idaman THREAD_SAFE qsemaphore_t ida_export qsem_create(const char *name, int init_count); ///< Create a new semaphore -idaman THREAD_SAFE bool ida_export qsem_free(qsemaphore_t sem); ///< Free a semaphore -idaman THREAD_SAFE bool ida_export qsem_post(qsemaphore_t sem); ///< Unlock a semaphore -idaman THREAD_SAFE bool ida_export qsem_wait(qsemaphore_t sem, int timeout_ms); ///< Lock and decrement a semaphore. timeout = -1 means block indefinitely - -//------------------------------------------------------------------------- -/// Mutex -//------------------------------------------------------------------------- -OPAQUE_HANDLE(qmutex_t); -idaman THREAD_SAFE bool ida_export qmutex_free(qmutex_t m); ///< Free a mutex -idaman THREAD_SAFE qmutex_t ida_export qmutex_create(void); ///< Create a new mutex -idaman THREAD_SAFE bool ida_export qmutex_lock(qmutex_t m); ///< Lock a mutex -idaman THREAD_SAFE bool ida_export qmutex_unlock(qmutex_t m); ///< Unlock a mutex - - -#ifdef __cplusplus -/// Mutex locker object. Will lock a given mutex upon creation and unlock it when the object is destroyed -class qmutex_locker_t -{ - qmutex_t lock; -public: - qmutex_locker_t(qmutex_t _lock) : lock(_lock) { qmutex_lock(lock); } - ~qmutex_locker_t(void) { qmutex_unlock(lock); } -}; -#endif - -//------------------------------------------------------------------------- -// PIPES -//------------------------------------------------------------------------- -#ifdef __NT__ -typedef void *qhandle_t; ///< MS Windows HANDLE -const qhandle_t NULL_PIPE_HANDLE = nullptr; -#else -typedef int qhandle_t; ///< file handle in Unix -const qhandle_t NULL_PIPE_HANDLE = 0; -#endif - - -/// Create a pipe. -/// \param[out] handles -/// - handles[0] : read handle -/// - handles[1] : write handle -/// \return error code (0-ok) - -idaman THREAD_SAFE int ida_export qpipe_create(qhandle_t handles[2]); - - -/// Read from a pipe. \return number of read bytes. -1-error - -idaman THREAD_SAFE ssize_t ida_export qpipe_read(qhandle_t handle, void *buf, size_t size); - - -/// Write to a pipe. \return number of written bytes. -1-error - -idaman THREAD_SAFE ssize_t ida_export qpipe_write(qhandle_t handle, const void *buf, size_t size); - - -/// Close a pipe. \return error code (0-ok) - -idaman THREAD_SAFE int ida_export qpipe_close(qhandle_t handle); - - -/// Wait for file/socket/pipe handles. -/// \param[out] idx handle index -/// \param handles handles to wait for -/// \param n number of handles -/// \param write_bitmask bitmask of indexes of handles opened for writing -/// \param timeout_ms timeout value in milliseconds -/// \return error code. on timeout, returns 0 and sets idx to -1 - -idaman THREAD_SAFE int ida_export qwait_for_handles( - int *idx, - const qhandle_t *handles, - int n, - uint32 write_bitmask, - int timeout_ms); - - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED THREAD_SAFE bool ida_export unpack_memory(void *buf, size_t size, const uchar **pptr, const uchar *end); // use unpack_obj -#endif // NO_OBSOLETE_FUNCS - -#endif /* _PRO_H */ diff --git a/idasdk75/include/problems.hpp b/idasdk75/include/problems.hpp deleted file mode 100644 index 2d87181..0000000 --- a/idasdk75/include/problems.hpp +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _PROBLEMS_HPP -#define _PROBLEMS_HPP - -/*! \file problems.hpp - - \brief Functions that deal with the list of problems. - - There are several problem lists. An address may be inserted to any list. - The kernel simply maintains these lists, no additional processing - is done. - - The problem lists are accessible for the user - from the View->Subviews->Problems menu item. - - Addresses in the lists are kept sorted. In general IDA just maintains - these lists without using them during analysis (except PR_ROLLED). - -*/ - -typedef uchar problist_id_t; ///< see \ref PR_ - -/// \defgroup PR_ Problem types -//@{ -const problist_id_t - PR_NOBASE = 1, ///< Can't find offset base - PR_NONAME = 2, ///< Can't find name - PR_NOFOP = 3, ///< Can't find forced op (not used anymore) - PR_NOCMT = 4, ///< Can't find comment (not used anymore) - PR_NOXREFS = 5, ///< Can't find references - PR_JUMP = 6, ///< Jump by table !!!! ignored - PR_DISASM = 7, ///< Can't disasm - PR_HEAD = 8, ///< Already head - PR_ILLADDR = 9, ///< Exec flows beyond limits - PR_MANYLINES = 10, ///< Too many lines - PR_BADSTACK = 11, ///< Failed to trace the value of the stack pointer - PR_ATTN = 12, ///< Attention! Probably erroneous situation. - PR_FINAL = 13, ///< Decision to convert to instruction/data is made by IDA - PR_ROLLED = 14, ///< The decision made by IDA was wrong and rolled back - PR_COLLISION = 15, ///< FLAIR collision: the function with the given name already exists - PR_DECIMP = 16, ///< FLAIR match indecision: the patterns matched, but not the function(s) being referenced - PR_END = 17; ///< Number of problem types -//@} - -/// Get the human-friendly description of the problem, -/// if one was provided to remember_problem. -/// \param buf a buffer to store the message into. -/// \param t problem list type. -/// \param ea linear address. -/// \return the message length or -1 if none - -idaman ssize_t ida_export get_problem_desc(qstring *buf, problist_id_t t, ea_t ea); - - -/// Insert an address to a list of problems. -/// Display a message saying about the problem (except of ::PR_ATTN,::PR_FINAL) -/// ::PR_JUMP is temporarily ignored. -/// \param type problem list type -/// \param ea linear address -/// \param msg a user-friendly message to be displayed instead of -/// the default more generic one associated with -/// the type of problem. Defaults to NULL. - -idaman void ida_export remember_problem(problist_id_t type, ea_t ea, const char *msg = NULL); - - -/// Get an address from the specified problem list. -/// The address is not removed from the list. -/// \param type problem list type -/// \param lowea the returned address will be higher or equal -/// than the specified address -/// \return linear address or #BADADDR - -idaman ea_t ida_export get_problem(problist_id_t type, ea_t lowea); - - -/// Remove an address from a problem list -/// \param type problem list type -/// \param ea linear address -/// \return success - -idaman bool ida_export forget_problem(problist_id_t type, ea_t ea); - - -/// Get problem list description - -idaman const char *ida_export get_problem_name(problist_id_t type, bool longname=true); - - -/// Check if the specified address is present in the problem list - -idaman bool ida_export is_problem_present(problist_id_t t, ea_t ea); - - -inline bool was_ida_decision(ea_t ea) { return is_problem_present(PR_FINAL, ea); } - - -#endif // _PROBLEMS_HPP diff --git a/idasdk75/include/prodir.h b/idasdk75/include/prodir.h deleted file mode 100644 index d442112..0000000 --- a/idasdk75/include/prodir.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _PRODIR_H -#define _PRODIR_H - -//-V:qffblk_t:730 not all members of a class are initialized inside the constructor -//-V:qffblk64_t:730 - - -/*! \file prodir.h - - \brief Unified interface to qfindfirst(),qfindnext(),qfindclose() functions. - - These are low level functions, it is better to use enumerate_files2(). -*/ - -/// \def{DIRCHAR, Path separator} -/// \def{SDIRCHAR, Path separator as a string} -/// \def{DRVCHAR, Windows drive separator} -#ifdef __NT__ -#define __FAT__ -#define SDIRCHAR "\\" -#define DIRCHAR '\\' -#define DRVCHAR ':' -#else -#define SDIRCHAR "/" -#define DIRCHAR '/' -#endif - -/// Extension character is '.' for all systems -#define EXTCHAR '.' - -//---------------------------------------------------------------------------- -/// \struct{qffblk_t, Various file statistics returned by qfind()-like functions} -/// \var{qffblk_t::ff_name, file path} -/// \var{qffblk_t::ff_fsize, file size} -/// \var{qffblk_t::ff_attrib, file attribute} -/// \var{qffblk_t::ff_ftime, file time stamp (ms dos fat format)} -/// \var{qffblk_t::ff_fdate, file date stamp (ms dos fat format)} -/// \def{FA_RDONLY, File cannot be opened for writing} -/// \def{FA_DIREC, Directory} -/// \def{FA_ARCH, File has not been backed up} -/// \def{MAXPATH, Size limit of qffblk_t::ff_name} -#if defined(__UNIX__) - #define MAXPATH QMAXPATH - struct qffblk_t // Unix - { - // user fields: - int ff_attrib; - #define FA_DIREC S_IFDIR - #define FA_ARCH 0 - #define FA_RDONLY 0 - char ff_name[QMAXPATH]; - uint32 ff_fsize; - uint16 ff_fdate; - uint16 ff_ftime; - // private fields: - void *filelist; - int fileidx, fileqty; - char dirpath[QMAXPATH]; - char pattern[QMAXPATH]; - int attr; - qffblk_t(void) : filelist(NULL), fileqty(0) {} - }; -#elif !defined(__X86__) - // Win64 - use Visual Studio's ffblk - #define MAXPATH _MAX_PATH - struct qffblk_t - { - // inlined __finddata64_t from Visual Studio (for compatibility with IDA 7.0 API) - unsigned attrib; - // Time values are stored in UTC format. - __time64_t time_create; // -1 for FAT file systems - __time64_t time_access; // -1 for FAT file systems - __time64_t time_write; - __int64 size; - char name[260]; // NB: file name is assumed to be UTF-8 - intptr_t handle; // handle returned by _wfindfirst64 - int attr; // attr value passed to qfindfirst. only FA_DIREC is checked - #define FA_RDONLY 0x01 - #define FA_DIREC 0x10 - #define FA_ARCH 0x20 - #define ff_name name - #define ff_attrib attrib - #define ff_fsize size - unsigned short ff_ftime; // FAT/DOS format modification time - unsigned short ff_fdate; // FAT/DOS format modification date - qffblk_t(void) : handle(-1) {} - }; - CASSERT(sizeof(qffblk_t) == 0x140); -#else - #define MAXPATH 260 - struct qffblk_t // Win32 - use Borland's ffblk (IDA 6.95 API compatibility) - { - long ff_reserved; - long ff_fsize; - unsigned long ff_attrib; - #define FA_RDONLY 0x01 - #define FA_DIREC 0x10 - #define FA_ARCH 0x20 - unsigned short ff_ftime; - unsigned short ff_fdate; - char ff_name[MAXPATH]; - qffblk_t(void) : ff_reserved(0) {} - }; -#endif - -/// \def{MAXDRIVE, Max drive name size} -/// \def{MAXDIR, Max directory name size} -/// \def{MAXFILE, Max file name size} -/// \def{MAXEXT, Max file extension size} -#if defined(__UNIX__) - #define MAXDRIVE QMAXPATH - #define MAXDIR QMAXPATH - #define MAXFILE QMAXPATH - #define MAXEXT QMAXPATH -#else - #define MAXDRIVE _MAX_DRIVE - #define MAXDIR _MAX_DIR - #define MAXFILE _MAX_FNAME - #define MAXEXT _MAX_EXT -#endif - -/// Find first file that matches the pattern. -/// \param pattern file name pattern, usually with * and ? wildcards -/// \param blk structure that will hold the answer. -/// blk->ff_name will hold the file name, for example. -/// \param attr the desired file types (#FA_DIREC for directories only or 0 for both directories and files) -/// \return 0 if found a file, other values mean error (check qerrno) - -idaman THREAD_SAFE int ida_export qfindfirst( - const char *pattern, - struct qffblk64_t *blk, - int attr); - - -/// Find next file that matches the pattern. -/// \param blk structure that holds the current state. -/// blk->ff_name will hold the next file name upon return. -/// \return 0 if found the next file, other values mean error (check qerrno) - -idaman THREAD_SAFE int ida_export qfindnext(struct qffblk64_t *blk); - -/// Stop the file enumeration and free internal structures. -/// \note usually there is no need to call this function manually, it is called -/// from the ::qffblk64_t destructor. -/// \param blk file enumeration structure - -idaman THREAD_SAFE void ida_export qfindclose(struct qffblk64_t *blk); - - -/// Common structure with 64-bit ff_fsize - see ::qffblk_t. -struct qffblk64_t -{ - int ff_attrib; - char ff_name[QMAXPATH]; - uint64 ff_fsize; - uint16 ff_fdate; - uint16 ff_ftime; - // private field - struct qffblk_t base; - - qffblk64_t(void) {} - ~qffblk64_t(void) { qfindclose(this); } -}; - -#endif // _PRODIR_H diff --git a/idasdk75/include/range.hpp b/idasdk75/include/range.hpp deleted file mode 100644 index 4616aa3..0000000 --- a/idasdk75/include/range.hpp +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _RANGE_HPP -#define _RANGE_HPP - -/*! \file range.hpp - - \brief Contains the definition of ::rangecb_t. - - This is a base class used by many parts of IDA. - It is a collection of address ranges in the program. - It conceptually consists of separate ::range_t instances. - - A range is a non-empty continuous range of addresses (specified by - its start and end addresses, the end address is excluded from the - range) with some characteristics. For example, the ensemble of program - segments is represented by an "rangecb_t" called "segs". - - Ranges are stored in the Btree part of the IDA database. - To learn more about Btrees (Balanced Trees): - http://www.bluerwhite.org/btree/ -*/ - -#ifndef SWIG -struct range_t; -/// Helper function. Should not be called directly! -idaman size_t ida_export range_t_print(const range_t *, char *buf, size_t bufsize); -#endif - -//-------------------------------------------------------------------------- -/// Base class for an range. This class is used as a base class for -/// a class with real information - see segment.hpp for example. -/// The end address points beyond the range. -struct range_t -{ - friend size_t ida_export range_t_print(const range_t *cb, char *buf, size_t bufsize); - ea_t start_ea; ///< start_ea included - ea_t end_ea; ///< end_ea excluded - /// Constructor - range_t(void) : start_ea(0), end_ea(0) {} - /// Constructor - range_t(ea_t ea1, ea_t ea2) : start_ea(ea1), end_ea(ea2) {} - - /// Compare two range_t instances, based on the start_ea - int compare(const range_t &r) const { return start_ea > r.start_ea ? 1 : start_ea < r.start_ea ? -1 : 0; } - - bool operator ==(const range_t &r) const { return compare(r) == 0; } ///< Compare two range_t's with '==' - bool operator !=(const range_t &r) const { return compare(r) != 0; } ///< Compare two range_t's with '!=' - bool operator > (const range_t &r) const { return compare(r) > 0; } ///< Compare two range_t's with '<' - bool operator < (const range_t &r) const { return compare(r) < 0; } ///< Compare two range_t's with '>' - - /// Is 'ea' in the address range? - bool contains(ea_t ea) const { return start_ea <= ea && end_ea > ea; } - - /// Is every ea in 'r' also in this range_t? - bool contains(const range_t &r) const { return r.start_ea >= start_ea && r.end_ea <= end_ea; } - - /// Is there an ea in 'r' that is also in this range_t? - bool overlaps(const range_t &r) const { return r.start_ea < end_ea && start_ea < r.end_ea; } - - /// Set #start_ea, #end_ea to 0 - void clear(void) { start_ea = end_ea = 0; } - - /// Is the size of the range_t <= 0? - bool empty(void) const { return start_ea >= end_ea; } - - /// Get #end_ea - #start_ea - asize_t size(void) const { return end_ea - start_ea; } - - /// Assign the range_t to the intersection between the range_t and 'r' - void intersect(const range_t &r) - { - if ( start_ea < r.start_ea ) - start_ea = r.start_ea; - if ( end_ea > r.end_ea ) - end_ea = r.end_ea; - if ( end_ea < start_ea ) - end_ea = start_ea; - } - - /// Ensure that the range_t includes 'ea' - void extend(ea_t ea) - { - if ( start_ea > ea ) - start_ea = ea; - if ( end_ea < ea ) - end_ea = ea; - } - - /// Print the range_t. - /// \param buf the output buffer - /// \param bufsize the size of the buffer - size_t print(char *buf, size_t bufsize) const { return range_t_print(this, buf, bufsize); } -}; -DECLARE_TYPE_AS_MOVABLE(range_t); -typedef qvector<range_t> rangevec_base_t; -struct rangevec_t : public rangevec_base_t /// Vector of range_t instances -{ -}; - -//-------------------------------------------------------------------------- -// Various kinds of ranges, see -// \ref idb_event::changing_range_cmt -// \ref idb_event::range_cmt_changed -enum range_kind_t -{ - RANGE_KIND_UNKNOWN, - RANGE_KIND_FUNC, ///< \ref func_t - RANGE_KIND_SEGMENT, ///< \ref segment_t - RANGE_KIND_HIDDEN_RANGE, ///< \ref hidden_range_t -}; - -//-------------------------------------------------------------------------- -/// Helper functions. Should not be called directly! -#ifndef SWIG -#define RANGESET_HELPER_DEFINITIONS(decl) \ -decl bool ida_export rangeset_t_add(rangeset_t *, const range_t &range);\ -decl bool ida_export rangeset_t_sub(rangeset_t *, const range_t &range);\ -decl bool ida_export rangeset_t_add2(rangeset_t *, const rangeset_t &aset);\ -decl bool ida_export rangeset_t_sub2(rangeset_t *, const rangeset_t &aset);\ -decl bool ida_export rangeset_t_has_common(const rangeset_t *, const range_t &range, bool strict);\ -decl bool ida_export rangeset_t_has_common2(const rangeset_t *, const rangeset_t &aset);\ -decl bool ida_export rangeset_t_contains(const rangeset_t *, const rangeset_t &aset);\ -decl size_t ida_export rangeset_t_print(const rangeset_t *, char *buf, size_t bufsize);\ -decl bool ida_export rangeset_t_intersect(rangeset_t *, const rangeset_t &aset);\ -decl const range_t *ida_export rangeset_t_find_range(const rangeset_t *, ea_t ea);\ -decl ea_t ida_export rangeset_t_next_addr(const rangeset_t *, ea_t ea);\ -decl ea_t ida_export rangeset_t_prev_addr(const rangeset_t *, ea_t ea);\ -decl ea_t ida_export rangeset_t_next_range(const rangeset_t *, ea_t ea);\ -decl ea_t ida_export rangeset_t_prev_range(const rangeset_t *, ea_t ea);\ -decl rangevec_t::const_iterator ida_export rangeset_t_lower_bound(const rangeset_t *, ea_t ea);\ -decl rangevec_t::const_iterator ida_export rangeset_t_upper_bound(const rangeset_t *, ea_t ea);\ -decl void ida_export rangeset_t_swap(rangeset_t *, rangeset_t &r); -#else -#define RANGESET_HELPER_DEFINITIONS(decl) -#endif // SWIG - -class rangeset_t; - -RANGESET_HELPER_DEFINITIONS(idaman) - -/// An ordered set of non-overlapping address ranges -class rangeset_t -{ - rangevec_t bag; - mutable const range_t *cache; - int undo_code = -1; - - RANGESET_HELPER_DEFINITIONS(friend) - bool verify(void) const; -public: - DEFINE_MEMORY_ALLOCATION_FUNCS() - /// Constructor - rangeset_t(void) : cache(NULL) {} - /// Constructor - Initialize set with 'range' - rangeset_t(const range_t &range): cache(NULL) { if ( !range.empty() ) bag.push_back(range); } - /// Constructor - Initialize set with 'ivs' - rangeset_t(const rangeset_t &ivs) : bag(ivs.bag), cache(NULL) {} - rangeset_t &operator=(const rangeset_t &ivs) { bag = ivs.bag; cache = NULL; return *this; } - /// Set this = 'r' and 'r' = this. See qvector::swap() - void swap(rangeset_t &r) { rangeset_t_swap(this, r); } - - /// Add an address range to the set. - /// If 'range' intersects an existing element e, then e is extended - /// to include 'range', and any superfluous elements (subsets of e) are removed. - /// \param range address range to add. cannot be empty - /// \return false if 'range' was not added (the set was unchanged) - bool add(const range_t &range) { return rangeset_t_add(this, range); } - - /// Create a new range_t from 'start' and 'end' and add it to the set - bool add(ea_t start, ea_t _end) { return add(range_t(start, _end)); } - - /// Add each element of 'aset' to the set. - /// \return false if no elements were added (the set was unchanged) - bool add(const rangeset_t &aset) { return rangeset_t_add2(this, aset); } - - /// Subtract an address range from the set. - /// All subsets of 'range' will be removed, and all elements that intersect - /// 'range' will be truncated/split so they do not include 'range'. - /// \param range address range to subtract. cannot be empty. - /// \return false if 'range' was not subtracted (the set was unchanged) - bool sub(const range_t &range) { return rangeset_t_sub(this, range); } - - /// Subtract an ea (an range of size 1) from the set. See sub(const range_t &) - bool sub(ea_t ea) { return sub(range_t(ea, ea+1)); } - - /// Subtract each range in 'aset' from the set - /// \return false if nothing was subtracted (the set was unchanged) - bool sub(const rangeset_t &aset) { return rangeset_t_sub2(this, aset); } - - /// Is there an ea in 'range' that is also in the rangeset? - bool has_common(const range_t &range) const - { return rangeset_t_has_common(this, range, false); } - - /// Is every ea in 'range' contained in the rangeset? - bool includes(const range_t &range) const - { return rangeset_t_has_common(this, range, true); } - - /// Print each range_t in the rangeset - size_t print(char *buf, size_t bufsize) const - { return rangeset_t_print(this, buf, bufsize); } - - /// Size in bytes - asize_t count(void) const; - - /// Get the range_t at index 'idx' - const range_t &getrange(int idx) const { return bag[idx]; } - - /// Get the last range_t in the set - const range_t &lastrange(void) const { return bag.back(); } - - /// Get the number of range_t elements in the set - size_t nranges(void) const { return bag.size(); } - - /// Does the set have zero elements - bool empty(void) const { return bag.empty(); } - - /// Delete all elements from the set. See qvector::clear() - void clear(void) { bag.clear(); cache = NULL; } - - /// Does any element of 'aset' overlap with an element in this rangeset?. See range_t::overlaps() - bool has_common(const rangeset_t &aset) const - { return rangeset_t_has_common2(this, aset); } - - /// Does an element of the rangeset contain 'ea'? See range_t::contains(ea_t) - bool contains(ea_t ea) const { return !empty() && find_range(ea) != NULL; } - - /// Is every element in 'aset' contained in an element of this rangeset?. See range_t::contains(range_t) - bool contains(const rangeset_t &aset) const - { return rangeset_t_contains(this, aset); } - - /// Set the rangeset to its intersection with 'aset'. - /// \return false if the set was unchanged - bool intersect(const rangeset_t &aset) - { return rangeset_t_intersect(this, aset); } - - /// Is every element in the rangeset contained in an element of 'aset'? - bool is_subset_of(const rangeset_t &aset) const { return aset.contains(*this); } - - /// Do this rangeset and 'aset' have identical elements? - bool is_equal(const rangeset_t &aset) const { return bag == aset.bag; } - - bool operator==(const rangeset_t &aset) const { return is_equal(aset); } ///< Compare two rangesets with '==' - bool operator!=(const rangeset_t &aset) const { return !is_equal(aset); } ///< Compare two rangesets with '!=' - - typedef rangevec_t::iterator iterator; ///< Iterator for rangesets - typedef rangevec_t::const_iterator const_iterator; ///< Const iterator for rangesets - const_iterator begin(void) const { return bag.begin(); } ///< Get an iterator that points to the first element in the set - const_iterator end(void) const { return bag.end(); } ///< Get an iterator that points to the end of the set. (This is NOT the last element) - iterator begin(void) { return bag.begin(); } ///< \copydoc begin - iterator end(void) { return bag.end(); } ///< \copydoc end - - /// Get the first range that contains at least one ea_t value greater than 'ea' - const_iterator lower_bound(ea_t ea) const { return rangeset_t_lower_bound(this, ea); } - - /// Get the first range such that every ea_t value in this range is strictly greater than 'ea' - const_iterator upper_bound(ea_t ea) const { return rangeset_t_upper_bound(this, ea); } - - /// Get the element from the set that contains 'ea'. - /// \return NULL if there is no such element - const range_t *find_range(ea_t ea) const - { return rangeset_t_find_range(this, ea); } - - /// When searching the rangeset, we keep a cached element to help speed up searches. - /// \return a pointer to the cached element - const range_t *cached_range(void) const { return cache; } - - /// Get the smallest ea_t value greater than 'ea' contained in the rangeset - ea_t next_addr(ea_t ea) const { return rangeset_t_next_addr(this, ea); } - - /// Get the largest ea_t value less than 'ea' contained in the rangeset - ea_t prev_addr(ea_t ea) const { return rangeset_t_prev_addr(this, ea); } - - /// Get the smallest ea_t value greater than 'ea' that is not in the same range as 'ea' - ea_t next_range(ea_t ea) const { return rangeset_t_next_range(this, ea); } - - /// Get the largest ea_t value less than 'ea' that is not in the same range as 'ea' - ea_t prev_range(ea_t ea) const { return rangeset_t_prev_range(this, ea); } - - /// Subtract the address range (from, from+size) and add the range (to, to+size) - int move_chunk(ea_t from, ea_t to, asize_t size); - - /// TODO: return code borrowed from va.hpp, same with move_chunk() - int check_move_args(ea_t from, ea_t to, asize_t size); -}; -DECLARE_TYPE_AS_MOVABLE(rangeset_t); -typedef qvector<rangeset_t> array_of_rangesets; ///< Array of rangeset_t objects -typedef qvector<const rangeset_t*> rangeset_crefvec_t; - -#endif // _RANGE_HPP diff --git a/idasdk75/include/regex.h b/idasdk75/include/regex.h deleted file mode 100644 index fb1aaca..0000000 --- a/idasdk75/include/regex.h +++ /dev/null @@ -1,240 +0,0 @@ -/************************************************* -* Perl-Compatible Regular Expressions * -*************************************************/ - -/* PCRE2 is a library of functions to support regular expressions whose syntax -and semantics are as close as possible to those of the Perl 5 language. - - Written by Philip Hazel - Original API code Copyright (c) 1997-2012 University of Cambridge - New API code Copyright (c) 2016 University of Cambridge - ------------------------------------------------------------------------------ -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - - * Neither the name of the University of Cambridge nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------ -*/ - - -#ifndef _REGEX_H_ -#define _REGEX_H_ -#ifdef __cplusplus -#include <map> -#include <kernwin.hpp> -#endif - -#include <pro.h> - -#ifdef __GNUC__ -#undef __P -#endif - -typedef off_t regoff_t; -/* The structure representing a compiled regular expression. */ - -struct regex_t -{ - int re_magic; - size_t re_nsub; /* number of parenthesized subexpressions */ - const char *re_endp; /* end pointer for REG_PEND */ - void *re_g; /* none of your business :-) */ -}; - -/* The structure in which a captured offset is returned. */ - -struct regmatch_t -{ - regoff_t rm_so; /* start of match */ - regoff_t rm_eo; /* end of match */ -}; -#ifndef REG_ICASE -/* Options, mostly defined by POSIX, but with some extras. */ - -#define REG_ICASE 0x0001 /* Maps to PCRE2_CASELESS */ -#define REG_NEWLINE 0x0002 /* Maps to PCRE2_MULTILINE */ -#define REG_NOTBOL 0x0004 /* Maps to PCRE2_NOTBOL */ -#define REG_NOTEOL 0x0008 /* Maps to PCRE2_NOTEOL */ -#define REG_DOTALL 0x0010 /* NOT defined by POSIX; maps to PCRE2_DOTALL */ -#define REG_NOSUB 0x0020 /* Maps to PCRE2_NO_AUTO_CAPTURE */ -#define REG_UTF 0x0040 /* NOT defined by POSIX; maps to PCRE2_UTF */ -#define REG_STARTEND 0x0080 /* BSD feature: pass subject string by so,eo */ -#define REG_NOTEMPTY 0x0100 /* NOT defined by POSIX; maps to PCRE2_NOTEMPTY */ -#define REG_UNGREEDY 0x0200 /* NOT defined by POSIX; maps to PCRE2_UNGREEDY */ -#define REG_UCP 0x0400 /* NOT defined by POSIX; maps to PCRE2_UCP */ - -/* This is not used by PCRE2, but by defining it we make it easier -to slot PCRE2 into existing programs that make POSIX calls. */ - -#define REG_EXTENDED 0 -#define REG_TRACE 0 // unsupported by PCRE2 - -/* Error values. Not all these are relevant or used by the wrapper. */ - - -enum -{ - REG_ASSERT = 1, /* internal error ? */ - REG_BADBR, /* invalid repeat counts in {} */ - REG_BADPAT, /* pattern error */ - REG_BADRPT, /* ? * + invalid */ - REG_EBRACE, /* unbalanced {} */ - REG_EBRACK, /* unbalanced [] */ - REG_ECOLLATE, /* collation error - not relevant */ - REG_ECTYPE, /* bad class */ - REG_EESCAPE, /* bad escape sequence */ - REG_EMPTY, /* empty expression */ - REG_EPAREN, /* unbalanced () */ - REG_ERANGE, /* bad range inside [] */ - REG_ESIZE, /* expression too big */ - REG_ESPACE, /* failed to get memory */ - REG_ESUBREG, /* bad back reference */ - REG_INVARG, /* bad argument */ - REG_NOMATCH /* match failed */ -}; -#endif //REG_ICASE - -/* The functions */ - -// compile the regular expression -idaman THREAD_SAFE int ida_export qregcomp( - struct regex_t *preg, - const char *pattern, - int cflags); - -// mapping from error codes returned by qregcomp() and qregexec() to a string -idaman THREAD_SAFE size_t ida_export qregerror( - int errcode, - const struct regex_t *preg, - char *errbuf, - size_t errbuf_size); - -// match regex against a string -idaman THREAD_SAFE int ida_export qregexec( - const struct regex_t *preg, - const char *str, - size_t nmatch, - struct regmatch_t pmatch[], - int eflags); - -// free any memory allocated by qregcomp -idaman THREAD_SAFE void ida_export qregfree(struct regex_t *preg); - - -#ifdef __cplusplus - -//------------------------------------------------------------------------- -class refcnted_regex_t : public qrefcnt_obj_t -{ - regex_t regex; - - refcnted_regex_t() - { - regex = {}; - } - virtual ~refcnted_regex_t() - { - qregfree(®ex); - } -public: - virtual void idaapi release(void) override - { - delete this; - } - int exec(const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) - { - return qregexec(®ex, string, nmatch, pmatch, eflags); - } - int process_errors(int code, qstring *errmsg) - { - if ( code != 0 && errmsg != NULL ) - { - char errbuf[MAXSTR]; - qregerror(code, ®ex, errbuf, sizeof(errbuf)); - *errmsg = errbuf; - } - return code; - } - static refcnted_regex_t *create(const qstring &text, bool case_insensitive, qstring *errmsg) - { - if ( text.empty() ) - return NULL; - refcnted_regex_t *p = new refcnted_regex_t(); - int rflags = REG_EXTENDED; - if ( case_insensitive ) - rflags |= REG_ICASE; - int code = qregcomp(&p->regex, text.begin(), rflags); - if ( p->process_errors(code, errmsg) != 0 ) - { - // It is unnecessary to qregfree() here: the deletion of 'p' will - // call qregfree (but anyway, even that is unnecessary, because - // if we end up here, it means qregcomp() failed, and when that - // happens, qregcomp() frees the regex itself.) - delete p; - p = NULL; - } - return p; - } - size_t nsub(void) - { - /* number of parenthesized subexpressions */ - return regex.re_nsub; - } - DECLARE_UNCOPYABLE(refcnted_regex_t); -}; -typedef qrefcnt_t<refcnted_regex_t> regex_ptr_t; - -//--------------------------------------------------------------------------- -struct regex_cache_t -{ - regex_ptr_t &find_or_create(const qstring &str) - { - regex_cache_map_t::iterator it = cache.find(str); - if ( it == cache.end() ) - { - qstring errmsg; - regex_ptr_t rx = regex_ptr_t(refcnted_regex_t::create(str, false, &errmsg)); - if ( rx == NULL ) - error("%s", errmsg.c_str()); - it = cache.insert(regex_cache_map_t::value_type(str, rx)).first; - } - return it->second; - } - -private: - typedef std::map<qstring,regex_ptr_t> regex_cache_map_t; - regex_cache_map_t cache; -}; - -#endif //__cplusplus - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED THREAD_SAFE int ida_export regcomp(struct regex_t *preg, const char *pattern, int cflags); -idaman DEPRECATED THREAD_SAFE size_t ida_export regerror(int errcode, const struct regex_t *preg, char *errbuf, size_t errbuf_size); -idaman DEPRECATED THREAD_SAFE int ida_export regexec(const struct regex_t *preg, const char *str, size_t nmatch, struct regmatch_t pmatch[], int eflags); -idaman DEPRECATED THREAD_SAFE void ida_export regfree(struct regex_t *preg); -#endif - -#endif /* !_REGEX_H_ */ diff --git a/idasdk75/include/registry.hpp b/idasdk75/include/registry.hpp deleted file mode 100644 index 751100b..0000000 --- a/idasdk75/include/registry.hpp +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __REGISTRY_HPP -#define __REGISTRY_HPP - -/*! \file registry.hpp - - \brief Registry related functions - - IDA uses the registry to store global configuration options that must - persist after IDA has been closed. - - On Windows, IDA uses the Windows registry directly. On Unix systems, the registry - is stored in a file (typically ~/.idapro/ida.reg). - - The root key for accessing IDA settings in the registry is defined by #ROOT_KEY_NAME. -*/ - -/// Key used to store IDA settings in registry (Windows version). -/// \note this name is automatically prepended to all -/// key names passed to functions in this file. -#define ROOT_KEY_NAME "Software\\Hex-Rays\\IDA" - -/// \cond -// Low level functions. DO NOT USE THEM. See the wrappers below. -// 'mode' is: -// - 0: data is a raw buffer, and its datalen must be able to hold the entire binary contents -// - 1: data is a raw buffer, and its datalen doesn't need to be able to hold the entire binary contents -// - 2: data is a ::bytevec_t*, datalen is ignored. -idaman bool ida_export reg_bin_op( - const char *name, - bool save, - void *data, - size_t datalen, - const char *subkey, - int mode = 0); -idaman bool ida_export reg_str_get(qstring *buf, const char *name, const char *subkey); -idaman void ida_export reg_str_set(const char *name, const char *subkey, const char *buf); -idaman int ida_export reg_int_op( - const char *name, - bool save, - int value, - const char *subkey = NULL); -/// \endcond - -/// Types of values stored in the registry -enum regval_type_t -{ - reg_unknown = 0, ///< unknown - reg_sz = 1, ///< utf8 string - reg_binary = 3, ///< binary data - reg_dword = 4 ///< 32-bit number -}; - - -/// Delete a key from the registry -idaman bool ida_export reg_delete_subkey(const char *name); - -/// Delete a subtree from the registry -idaman bool ida_export reg_delete_tree(const char *name); - -/// Delete a value from the registry. -/// \param name value name -/// \param subkey parent key -/// \return success - -idaman bool ida_export reg_delete(const char *name, const char *subkey = NULL); - - -/// Is there already a key with the given name? - -idaman bool ida_export reg_subkey_exists(const char *name); - - -/// Is there already a value with the given name? -/// \param name value name -/// \param subkey parent key - -idaman bool ida_export reg_exists(const char *name, const char *subkey = NULL); - - -/// Retrieve the child names of the given key. -/// \param out result -/// \param name key name -/// \param subkeys if true, collect subkey names. if false, collect value names. -/// \return false if the given key does not exist - -idaman bool ida_export reg_subkey_children(qstrvec_t *out, const char *name, bool subkeys); - - -/// Get data type of a given value. -/// \param out result -/// \param name value name -/// \param subkey key name -/// \return false if the [key+]value doesn't exist - -idaman bool ida_export reg_data_type(regval_type_t *out, const char *name, const char *subkey = NULL); - - -/// Retrieve all string values associated with the given key. -/// Also see reg_update_strlist(). - -idaman void ida_export reg_read_strlist(qstrvec_t *list, const char *subkey); - - -/// Update list of strings associated with given key. -/// \param subkey key name -/// \param add string to be added to list, can be NULL -/// \param maxrecs limit list to this size -/// \param rem string to be removed from list, can be NULL -/// \param ignorecase ignore case for 'add' and 'rem' - -idaman void ida_export reg_update_strlist( - const char *subkey, - const char *add, - size_t maxrecs, - const char *rem = NULL, - bool ignorecase = false); - - -/// Write binary data to the registry. -/// \param name value name -/// \param data input, must not be NULL -/// \param datalen length of input in bytes -/// \param subkey key name - -inline void reg_write_binary( - const char *name, - const void *data, - size_t datalen, - const char *subkey = NULL) -{ - reg_bin_op(name, true, CONST_CAST(void *)(data), datalen, subkey); -} - - -/// Read binary data from the registry. -/// \param name value name -/// \param[out] data result, must not be NULL -/// \param datalen length of out buffer in bytes -/// \param subkey key name -/// \return false if 'data' is not large enough to hold all data present. -/// in this case 'data' is left untouched. - -inline bool reg_read_binary( - const char *name, - void *data, - size_t datalen, - const char *subkey = NULL) -{ - return reg_bin_op(name, false, data, datalen, subkey); -} - - -/// Read a chunk of binary data from the registry. -/// This function succeeds even in the case of a partial read. -/// \param name value name -/// \param[out] data result, must not be NULL -/// \param datalen length of output buffer in bytes -/// \param subkey key name -/// \return success - -inline bool reg_read_binary_part( - const char *name, - void *data, - size_t datalen, - const char *subkey = NULL) -{ - return reg_bin_op(name, false, data, datalen, subkey, 1); -} - - -/// Read binary data from the registry. -/// \param name value name -/// \param[out] data output buffer, must not be NULL -/// \param subkey key name -/// \return success - -inline bool reg_read_binary( - const char *name, - bytevec_t *data, - const char *subkey = NULL) -{ - return reg_bin_op(name, false, data, 0, subkey, 2); -} - - -/// Write a string to the registry. -/// \param name value name -/// \param utf8 utf8-encoded string -/// \param subkey key name - -inline void reg_write_string( - const char *name, - const char *utf8, - const char *subkey = NULL) -{ - reg_str_set(name, subkey, utf8); -} - - -/// Read a string from the registry. -/// \param[out] utf8 output buffer -/// \param name value name -/// \param subkey key name -/// \return success - -inline bool reg_read_string( - qstring *utf8, - const char *name, - const char *subkey = NULL) -{ - return reg_str_get(utf8, name, subkey); -} - - -/// Read integer value from the registry. -/// \param name value name -/// \param defval default value -/// \param subkey key name -/// \return the value read from the registry, or 'defval' if the read failed - -inline int reg_read_int(const char *name, int defval, const char *subkey = NULL) -{ - return reg_int_op(name, false, defval, subkey); -} - - -/// Write integer value to the registry. -/// \param name value name -/// \param value value to write -/// \param subkey key name - -inline void reg_write_int(const char *name, int value, const char *subkey = NULL) -{ - reg_int_op(name, true, value, subkey); -} - - -/// Read boolean value from the registry. -/// \param name value name -/// \param defval default value -/// \param subkey key name -/// \return boolean read from registry, or 'defval' if the read failed - -inline bool reg_read_bool(const char *name, bool defval, const char *subkey = NULL) -{ - return reg_int_op(name, false, int(defval), subkey) != 0; -} - - -/// Write boolean value to the registry. -/// \param name value name -/// \param value boolean to write (nonzero = true) -/// \param subkey key name - -inline void reg_write_bool(const char *name, int value, const char *subkey = NULL) -{ - reg_int_op(name, true, value != 0, subkey); -} - - -/// Get all subkey names of given key - -inline bool reg_subkey_subkeys(qstrvec_t *out, const char *name) -{ - return reg_subkey_children(out, name, true); -} - - -/// Get all value names under given key - -inline bool reg_subkey_values(qstrvec_t *out, const char *name) -{ - return reg_subkey_children(out, name, false); -} - - -/// Update registry with a file list. -/// Case sensitivity will vary depending on the target OS. -/// \note 'add' and 'rem' must be UTF-8, just like for regular string operations. - -inline void reg_update_filestrlist( - const char *subkey, - const char *add, - size_t maxrecs, - const char *rem = NULL) -{ - reg_update_strlist( - subkey, add, maxrecs, rem, - #ifdef __NT__ // Ignore case in Windows - true - #else - false - #endif - ); -} - -//----------------------------------------------------------------------------- -// INTERNALS - -/// \cond -#define _RVN_(f) regname_ ## f - -#ifndef __DEFINE_REG_NAMES__ -#define REG_VAL_NAME(n,s) \ - extern const char _RVN_(n)[] -#else -#define REG_VAL_NAME(n,s) \ - extern const char _RVN_(n)[]; \ - const char _RVN_(n)[] = s -#endif - -#define REG_BOOL_FUNC(func, valname) \ -REG_VAL_NAME(func, valname); \ -inline void regset_ ## func(bool value) \ - { reg_write_bool(_RVN_(func), value); } \ -inline bool regget_ ## func(bool def) \ - { return reg_read_bool(_RVN_(func), def); } - -#define REG_INT_FUNC(func, valname) \ -REG_VAL_NAME(func,valname); \ -inline void regset_ ## func(int value) \ -{ \ - reg_int_op(_RVN_(func), true, value); \ -} \ -inline int regget_ ## func(int def=0) \ -{ \ - return reg_int_op(_RVN_(func), false, def); \ -} - -idaman void ida_export reg_load(void); -idaman void ida_export reg_flush(void); - -// if using history functions below, you have to define the following two variables -extern const char regkey_history[]; -extern int max_history_files; // max number of files in the file menu - // and in the welcome box -#define MAX_HISTORY_FILES_DEF 10 // default value - -inline void regget_history(qstrvec_t *list) -{ -#ifdef DEMO - qnotused(list); -#else - reg_read_strlist(list, regkey_history); -#endif -} - -inline void reg_update_history(const char *addfile, const char *removefile = NULL) -{ -#ifdef DEMO - qnotused(addfile); - qnotused(removefile); -#else - // On Windows avoid duplicate upper/lower-case entries - // by using reg_update_filestrlist() which takes care of case sensitivity - reg_update_filestrlist(regkey_history, addfile, max_history_files, removefile); -#endif -} - -inline void reg_history_size_truncate(void) -{ -#ifndef DEMO - reg_update_strlist(regkey_history, NULL, max_history_files, NULL); -#endif -} -/// \endcond - -#endif // __REGISTRY_HPP diff --git a/idasdk75/include/search.hpp b/idasdk75/include/search.hpp deleted file mode 100644 index 05f8b92..0000000 --- a/idasdk75/include/search.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Interactive disassembler (IDA). - * ALL RIGHTS RESERVED. - * Copyright (c) 1990-2020 Hex-Rays - * - */ - -#ifndef __SEARCH_HPP -#define __SEARCH_HPP - -/*! \file search.hpp - - \brief Middle-level search functions - - They all are controlled by \ref SEARCH_ -*/ - -/// \defgroup SEARCH_ Search flags -//@{ -#define SEARCH_UP 0x000 ///< search towards lower addresses -#define SEARCH_DOWN 0x001 ///< search towards higher addresses -#define SEARCH_NEXT 0x002 ///< skip the starting address when searching. - ///< this bit is useful only for search(), bin_search2(), find_reg_access(). - ///< find_.. functions skip the starting address automatically. -#define SEARCH_CASE 0x004 ///< case-sensitive search (case-insensitive otherwise) -#define SEARCH_REGEX 0x008 ///< regular expressions in search string (supported only for the text search) -#define SEARCH_NOBRK 0x010 ///< do not test if the user clicked cancel to interrupt the search -#define SEARCH_NOSHOW 0x020 ///< do not display the search progress/refresh screen -#define SEARCH_IDENT 0x080 ///< search for an identifier (text search). - ///< it means that the characters before - ///< and after the match cannot be is_visible_char(). -#define SEARCH_BRK 0x100 ///< return #BADADDR if the search was cancelled. -#define SEARCH_USE 0x200 ///< find_reg_access: search for a use (read access) -#define SEARCH_DEF 0x400 ///< find_reg_access: search for a definition (write access) -//@} - - -/// Is the #SEARCH_DOWN bit set? - -inline THREAD_SAFE bool search_down(int sflag) { return (sflag & SEARCH_DOWN) != 0; } - - -/// \name find_... functions -/// \param ea start ea -/// \param sflag combination of \ref SEARCH_ -/// \param[out] opnum filled with operand number whenever relevant -/// \return first ea at which the search criteria is met -//@{ - - -/// Find next error or problem - -idaman ea_t ida_export find_error(ea_t ea, int sflag, int *opnum=NULL); - - -/// Find next operand without any type info - -idaman ea_t ida_export find_notype(ea_t ea, int sflag, int *opnum=NULL); - - -/// Find next unexplored address - -idaman ea_t ida_export find_unknown(ea_t ea, int sflag); - - -/// Find next ea that is the start of an instruction or data - -idaman ea_t ida_export find_defined(ea_t ea, int sflag); - - -/// Find next suspicious operand - -idaman ea_t ida_export find_suspop(ea_t ea, int sflag, int *opnum=NULL); - - -/// Find next data address - -idaman ea_t ida_export find_data(ea_t ea,int sflag); - - -/// Find next code address - -idaman ea_t ida_export find_code(ea_t ea,int sflag); - - -/// Find next code address that does not belong to a function - -idaman ea_t ida_export find_not_func(ea_t ea,int sflag); - - -/// Find next immediate operand with the given value - -idaman ea_t ida_export find_imm(ea_t ea, int sflag, uval_t search_value, int *opnum=NULL); - - -/// See search() - -idaman ea_t ida_export find_text(ea_t start_ea, int y, int x, const char *ustr, int sflag); - - -/// Find access to a register. -/// \param out pointer to the output buffer. must be non-null. -/// upon success contains info about the found register. -/// upon failed search for a read access out->range contains -/// the info about the non-redefined parts of the register. -/// \param start_ea starting address -/// \param end_ea ending address. BADADDR means that the end limit is missing. -/// otherwise, if the search direction is SEARCH_UP, -/// END_EA must be lower than START_EA. -/// \param regname the register to search for. -/// \param sflag combination of \ref SEARCH_ bits. -/// \note This function does not care about the control flow and -/// probes all instructions in the specified range, starting from START_EA. -/// Only direct references to registers are detected. Function calls and -/// system traps are ignored. -/// \return the found address. BADADDR if not found or error. -idaman ea_t ida_export find_reg_access( - struct reg_access_t *out, - ea_t start_ea, - ea_t end_ea, - const char *regname, - int sflag); - -//@} - -class place_t; - - -/// Search for a text substring (low level function). -/// \param ud line array parameter -/// \param[in,out] start pointer to starting place: -/// - start->ea: starting address -/// - start->lnnum: starting Y coordinate -/// \param end pointer to ending place: -/// - end->ea: ending address -/// - end->lnnum: ending Y coordinate -/// \param[in,out] startx pointer to starting X coordinate -/// \param str substring to search for. -/// \param sflag \ref SEARCH_ -/// \retval 0 substring not found -/// \retval 1 substring found. The matching position is returned in: -/// - start->ea: address -/// - start->lnnum: Y coordinate -/// - *startx: X coordinate -/// \retval 2 search was cancelled by ctrl-break. -/// The farthest searched address is -/// returned in the same manner as in the successful return (1). -/// \retval 3 the input regular expression is bad. -/// The error message was displayed. - -idaman int ida_export search( - void *ud, - place_t *start, - const place_t *end, - int *startx, - const char *str, - int sflag); - - -#if !defined(NO_OBSOLETE_FUNCS) -idaman DEPRECATED int ida_export user2bin(uchar *, uchar *, ea_t, const char *, int, bool); // use parse_binpat_str() -idaman DEPRECATED ea_t ida_export find_binary(ea_t, ea_t, const char *, int, int); // use bin_search2() - -#endif - - -#endif // __SEARCH_HPP diff --git a/idasdk75/include/segment.hpp b/idasdk75/include/segment.hpp deleted file mode 100644 index 4bc8f25..0000000 --- a/idasdk75/include/segment.hpp +++ /dev/null @@ -1,1203 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _SEGMENT_HPP -#define _SEGMENT_HPP - -#include <ida.hpp> -#include <range.hpp> // segments are range of addresses - // with characteristics - -/*! \file segment.hpp - - \brief Functions that deal with program segmentation. - - IDA requires that all program addresses belong to segments - (each address must belong to exactly one segment). - The situation when an address doesn't belong to any segment - is allowed as a temporary situation only when the user changes program - segmentation. Bytes outside a segment can't be converted to - instructions, have names, comments, etc. - Each segment has its start address, ending address and represents - a contiguous range of addresses. There might be unused holes between - segments. - - Each segment has its unique segment selector. This selector is used - to distinguish the segment from other segments. For 16-bit programs - the selector is equal to the segment base paragraph. For 32-bit - programs there is special array to translate the selectors to - the segment base paragraphs. A selector is a 32/64 bit value. - - The segment base paragraph determines the offsets in the segment. - If the start address of the segment == (base << 4) then the first - offset in the segment will be 0. The start address should be - higher or equal to (base << 4). - We will call the offsets in the segment 'virtual addresses'. - So, the virtual address of the first byte of the segment is - - (start address of segment - segment base linear address) - - For IBM PC, the virtual address corresponds to the offset part of the address. - For other processors (Z80, for example), virtual addresses correspond - to Z80 addresses and linear addresses are used only internally. - For MS Windows programs the segment base paragraph is 0 and therefore - the segment virtual addresses are equal to linear addresses. -*/ - -/// \defgroup seg Segments -/// \copybrief segment.hpp - - -/// Maximum number of segment registers is 16 (see segregs.hpp) -#define SREG_NUM 16 - - -//------------------------------------------------------------------------- -// D E F I N I T O N O F S E G M E N T S T R U C T U R E -//------------------------------------------------------------------------- -/// \defgroup seg_t Segment structure -/// Definition of ::segment_t and related functions -/// \ingroup seg -//@{ - -/// Describes a program segment -class segment_t : public range_t -{ -public: -/* 8 */ uval_t name; ///< use get/set_segm_name() functions -/* 12 */ uval_t sclass; ///< use get/set_segm_class() functions -/* 16 */ uval_t orgbase; ///< this field is IDP dependent. - ///< you may keep your information about - ///< the segment here - -/* 20 */ uchar align; ///< \ref sa_ -/// \defgroup sa_ Segment alignment codes -/// \ingroup seg_t -/// Used by segment_t::align -//@{ -#define saAbs 0 ///< Absolute segment. -#define saRelByte 1 ///< Relocatable, byte aligned. -#define saRelWord 2 ///< Relocatable, word (2-byte) aligned. -#define saRelPara 3 ///< Relocatable, paragraph (16-byte) aligned. -#define saRelPage 4 ///< Relocatable, aligned on 256-byte boundary -#define saRelDble 5 ///< Relocatable, aligned on a double word (4-byte) - ///< boundary. -#define saRel4K 6 ///< This value is used by the PharLap OMF for page (4K) - ///< alignment. It is not supported by LINK. -#define saGroup 7 ///< Segment group -#define saRel32Bytes 8 ///< 32 bytes -#define saRel64Bytes 9 ///< 64 bytes -#define saRelQword 10 ///< 8 bytes -#define saRel128Bytes 11 ///< 128 bytes -#define saRel512Bytes 12 ///< 512 bytes -#define saRel1024Bytes 13 ///< 1024 bytes -#define saRel2048Bytes 14 ///< 2048 bytes -#define saRel_MAX_ALIGN_CODE saRel2048Bytes -//@} - -/* 21 */ uchar comb; ///< \ref sc_ -/// \defgroup sc_ Segment combination codes -/// \ingroup seg_t -/// Used by segment_t::comb -//@{ -#define scPriv 0 ///< Private. Do not combine with any other program - ///< segment. -#define scGroup 1 ///< Segment group -#define scPub 2 ///< Public. Combine by appending at an offset that meets - ///< the alignment requirement. -#define scPub2 4 ///< As defined by Microsoft, same as C=2 (public). -#define scStack 5 ///< Stack. Combine as for C=2. This combine type forces - ///< byte alignment. -#define scCommon 6 ///< Common. Combine by overlay using maximum size. -#define scPub3 7 ///< As defined by Microsoft, same as C=2 (public). -#define sc_MAX_COMB_CODE scPub3 -//@} - -/* 22 */ uchar perm; ///< \ref SEGPERM_ (0 means no information) -/// \defgroup SEGPERM_ Segment permissions -/// \ingroup seg_t -/// Used by segment_t::perm -//@{ -#define SEGPERM_EXEC 1 ///< Execute -#define SEGPERM_WRITE 2 ///< Write -#define SEGPERM_READ 4 ///< Read -#define SEGPERM_MAXVAL (SEGPERM_EXEC + SEGPERM_WRITE + SEGPERM_READ) -//@} - -/* 23 */ uchar bitness; ///< Number of bits in the segment addressing - ///< - 0: 16 bits - ///< - 1: 32 bits - ///< - 2: 64 bits -#define SEG_MAX_BITNESS_CODE 2 - - /// Use 32 bit segment addressing? - bool use32(void) const { return bitness >= 1; } - /// Use 64 bit segment addressing? - bool use64(void) const { return bitness == 2; } - /// Get number of address bits - int abits(void) const { return 1<<(bitness+4); } - /// Get number of address bytes - int abytes(void) const { return abits() / 8; } - -/// \defgroup SFL_ Segment flags -/// \ingroup seg_t -/// Used by segment_t::flags - -/* 24 */ ushort flags; ///< \ref SFL_ - -/// IDP dependent field (IBM PC: if set, ORG directive is not commented out) -/// \ingroup SFL_ -#define SFL_COMORG 0x01 - - /// \name Segment flag: ORG directive - /// See #SFL_COMORG - //@{ - bool comorg(void) const { return (flags & SFL_COMORG) != 0; } - void set_comorg(void) { flags |= SFL_COMORG; } - void clr_comorg(void) { flags &= ~SFL_COMORG; } - //@} - -/// Orgbase is present? (IDP dependent field) -/// \ingroup SFL_ -#define SFL_OBOK 0x02 - - /// \name Segment flag: orgbase - /// See #SFL_OBOK - //@{ - bool ob_ok(void) const { return (flags & SFL_OBOK) != 0; } - void set_ob_ok(void) { flags |= SFL_OBOK; } - void clr_ob_ok(void) { flags &= ~SFL_OBOK; } - //@} - -/// Is the segment hidden? -/// \ingroup SFL_ -#define SFL_HIDDEN 0x04 - - /// \name Segment flag: hidden - /// See #SFL_HIDDEN - //@{ - bool is_visible_segm(void) const { return (flags & SFL_HIDDEN) == 0; } - void set_visible_segm(bool visible) { setflag(flags, SFL_HIDDEN, !visible); } - //@} - -/// Is the segment created for the debugger?. -/// Such segments are temporary and do not have permanent flags. -/// \ingroup SFL_ -#define SFL_DEBUG 0x08 - - /// \name Segment flag: debugger segment - /// See #SFL_DEBUG - //@{ - bool is_debugger_segm(void) const { return (flags & SFL_DEBUG) != 0; } - void set_debugger_segm(bool debseg) { setflag(flags, SFL_DEBUG, debseg); } - //@} - -/// Is the segment created by the loader? -/// \ingroup SFL_ -#define SFL_LOADER 0x10 - - /// \name Segment flag: loader segment - /// See #SFL_LOADER - //@{ - bool is_loader_segm(void) const { return (flags & SFL_LOADER) != 0; } - void set_loader_segm(bool ldrseg) { setflag(flags, SFL_LOADER, ldrseg); } - //@} - -/// Hide segment type (do not print it in the listing) -/// \ingroup SFL_ -#define SFL_HIDETYPE 0x20 - - /// \name Segment flag: hide segment type - /// See #SFL_HIDETYPE - //@{ - bool is_hidden_segtype(void) const { return (flags & SFL_HIDETYPE) != 0; } - void set_hidden_segtype(bool hide) { setflag(flags, SFL_HIDETYPE, hide); } - //@} - -/// Header segment (do not create offsets to it in the disassembly) -/// \ingroup SFL_ -#define SFL_HEADER 0x40 - - /// \name Segment flag: header segment - /// See #SFL_HEADER - //@{ - bool is_header_segm(void) const { return (flags & SFL_HEADER) != 0; } - void set_header_segm(bool on) { setflag(flags, SFL_HEADER, on); } - //@} - - /// Ephemeral segments are not analyzed automatically - /// (no flirt, no functions unless required, etc). - /// Most likely these segments will be destroyed at the end of the - /// debugging session unless the user changes their status. - bool is_ephemeral_segm(void) const - { return (flags & (SFL_DEBUG|SFL_LOADER)) == SFL_DEBUG; } - -/* 28 */ sel_t sel; ///< segment selector - should be unique. You can't - ///< change this field after creating the segment. - ///< Exception: 16bit OMF files may have several - ///< segments with the same selector, but this is not - ///< good (no way to denote a segment exactly) - ///< so it should be fixed in the future. - -/* 32 */ sel_t defsr[SREG_NUM];///< default segment register values. - ///< first element of this array keeps information - ///< about value of \ph{reg_first_sreg} - -/* 96 */ uchar type; ///< segment type (see \ref SEG_). - ///< The kernel treats different segment types differently. - ///< Segments marked with '*' contain no instructions - ///< or data and are not declared as 'segments' in - ///< the disassembly. - -/// \defgroup SEG_ Segment types -/// \ingroup seg_t -/// Used by segment_t::type -//@{ -#define SEG_NORM 0 ///< unknown type, no assumptions -#define SEG_XTRN 1 ///< * segment with 'extern' definitions. - ///< no instructions are allowed -#define SEG_CODE 2 ///< code segment -#define SEG_DATA 3 ///< data segment -#define SEG_IMP 4 ///< java: implementation segment -#define SEG_GRP 6 ///< * group of segments -#define SEG_NULL 7 ///< zero-length segment -#define SEG_UNDF 8 ///< undefined segment type (not used) -#define SEG_BSS 9 ///< uninitialized segment -#define SEG_ABSSYM 10 ///< * segment with definitions of absolute symbols -#define SEG_COMM 11 ///< * segment with communal definitions -#define SEG_IMEM 12 ///< internal processor memory & sfr (8051) -#define SEG_MAX_SEGTYPE_CODE SEG_IMEM -//@} - -/* 100 */ bgcolor_t color; ///< the segment color - - /// Update segment information. You must call this function after modification - /// of segment characteristics. Note that not all fields of segment structure - /// may be modified directly, there are special functions to modify some fields. - /// \return success - inline bool update(void); - - /// Constructor - segment_t(void) - : name(0), - sclass(0), - orgbase(0), - align(0), - comb(0), - perm(0), - bitness(0), - flags(0), - sel(0), - type(SEG_NORM), - color(DEFCOLOR) - { - memset(defsr, 0, sizeof(defsr)); - } - -}; // total 104/192 bytes - -#ifdef __EA64__ -CASSERT(sizeof(segment_t) == 192); -#else -CASSERT(sizeof(segment_t) == 104); -#endif - -/// See #SFL_HIDDEN -inline bool is_visible_segm(segment_t *s) { return s->is_visible_segm(); } -/// See #SFL_HIDDEN, #SCF_SHHID_SEGM -inline bool is_finally_visible_segm(segment_t *s) -{ - return (inf_get_cmtflg() & SCF_SHHID_SEGM) != 0 || is_visible_segm(s); -} -/// See #SFL_HIDDEN -idaman void ida_export set_visible_segm(segment_t *s, bool visible); - - -/// Has segment a special type?. -/// (#SEG_XTRN, #SEG_GRP, #SEG_ABSSYM, #SEG_COMM) - -idaman bool ida_export is_spec_segm(uchar seg_type); - - -/// Does the address belong to a segment with a special type?. -/// (#SEG_XTRN, #SEG_GRP, #SEG_ABSSYM, #SEG_COMM) -/// \param ea linear address - -idaman bool ida_export is_spec_ea(ea_t ea); - - -/// Lock segment pointer -/// Locked pointers are guaranteed to remain valid until they are unlocked. -/// Ranges with locked pointers cannot be deleted or moved. - -idaman void ida_export lock_segm(const segment_t *segm, bool lock); - -/// Helper class to lock a segment pointer so it stays valid -class lock_segment -{ - const segment_t *segm; -public: - lock_segment(const segment_t *_segm) : segm(_segm) - { - lock_segm(segm, true); - } - ~lock_segment(void) - { - lock_segm(segm, false); - } -}; - -/// Is a segment pointer locked? -idaman bool ida_export is_segm_locked(const segment_t *segm); - -//@} seg_t - -//------------------------------------------------------------------------- -// S E G M E N T S E L E C T O R S -// -/// \defgroup seg_sel Segment selectors -/// \ingroup seg -/// The kernel maintains a table to translate selector values to -/// segment base paragraphs. A Paragraph is a 16byte quantity. -/// This table and translation is necessary because IBM PC uses -/// 16bit selectors in instructions but segments may reside anywhere -/// in the linear addressing space. For example, if a segment with -/// selector 5 resides at 0x400000, we need to have selector translation -/// 5 -> 0x400000. -/// For 16bit programs the selector translation table is usually empty, -/// selector values are equal to segment base paragraphs. -//@{ -//------------------------------------------------------------------------- - -/// Get description of selector (0..get_selector_qty()-1) - -idaman bool ida_export getn_selector(sel_t *sel, ea_t *base, int n); - - -/// Get number of defined selectors - -idaman size_t ida_export get_selector_qty(void); - - -/// Allocate a selector for a segment if necessary. -/// You must call this function before calling add_segm_ex(). -/// add_segm() calls this function itself, so you don't need to -/// allocate a selector. -/// This function will allocate a selector if 'segbase' requires more than -/// 16 bits and the current processor is IBM PC. -/// Otherwise it will return the segbase value. -/// \param segbase a new segment base paragraph -/// \return the allocated selector number - -idaman sel_t ida_export setup_selector(ea_t segbase); - - -/// Allocate a selector for a segment unconditionally. -/// You must call this function before calling add_segm_ex(). -/// add_segm() calls this function itself, so you don't need to -/// allocate a selector. -/// This function will allocate a new free selector and setup its mapping -/// using find_free_selector() and set_selector() functions. -/// \param segbase a new segment base paragraph -/// \return the allocated selector number - -idaman sel_t ida_export allocate_selector(ea_t segbase); - - -/// Find first unused selector. -/// \return a number >= 1 - -idaman sel_t ida_export find_free_selector(void); - - -/// Set mapping of selector to a paragraph. -/// You should call this function _before_ creating a segment -/// which uses the selector, otherwise the creation of the segment will fail. -/// \param selector number of selector to map -/// - if selector == #BADSEL, then return 0 (fail) -/// - if the selector has had a mapping, old mapping is destroyed -/// - if the selector number is equal to paragraph value, then the mapping is -/// destroyed because we don't need to keep trivial mappings. -/// \param paragraph paragraph to map selector -/// \retval 1 ok -/// \retval 0 failure (bad selector or too many mappings) - -idaman int ida_export set_selector(sel_t selector, ea_t paragraph); - - -/// Delete mapping of a selector. -/// Be wary of deleting selectors that are being used in the program, this -/// can make a mess in the segments. -/// \param selector number of selector to remove from the translation table - -idaman void ida_export del_selector(sel_t selector); - - -/// Get mapping of a selector. -/// \param selector number of selector to translate -/// \return paragraph the specified selector is mapped to. -/// if there is no mapping, returns 'selector'. - -idaman ea_t ida_export sel2para(sel_t selector); - - -/// Get mapping of a selector as a linear address. -/// \param selector number of selector to translate to linear address -/// \return linear address the specified selector is mapped to. -/// if there is no mapping, returns to_ea(selector,0); - -inline ea_t idaapi sel2ea(sel_t selector) -{ - if ( selector == BADSEL ) - return BADADDR; - return to_ea(sel2para(selector), 0); -} - - -/// Find a selector that has mapping to the specified paragraph. -/// \param base paragraph to search in the translation table -/// \return selector value or base - -idaman sel_t ida_export find_selector(ea_t base); - - -/// Enumerate all selectors from the translation table. -/// This function calls 'func' for each selector in the translation table. -/// If 'func' returns non-zero code, enumeration is stopped and this code -/// is returned. -/// \param func callback function -/// - sel: selector number -/// - para: selector mapping -/// \return 0 or code returned by 'func'. - -idaman int ida_export enumerate_selectors(int (idaapi *func)(sel_t sel,ea_t para)); - - -/// Enumerate all segments with the specified selector. -/// This function will call the callback function 'func' for each -/// segment that has the specified selector. Enumeration starts -/// from the last segment and stops at the first segment (reverse order). -/// If the callback function 'func' returns a value != #BADADDR, the -/// enumeration is stopped and this value is returned to the caller. -/// \param selector segments that have this selector are enumerated -/// \param func callback function -/// - s: pointer to segment structure -/// - ud: user data -/// \param ud pointer to user data. this pointer will be passed -/// to the callback function -/// \return #BADADDR or the value returned by the callback function 'func' - -idaman ea_t ida_export enumerate_segments_with_selector( - sel_t selector, - ea_t (idaapi *func)(segment_t *s, void *ud), - void *ud=NULL); - - -/// Get pointer to segment structure. -/// This function finds a segment by its selector. If there are several -/// segments with the same selectors, the last one will be returned. -/// \param selector a segment with the specified selector will be returned -/// \return pointer to segment or NULL - -idaman segment_t *ida_export get_segm_by_sel(sel_t selector); - -//@} seg_sel - -//------------------------------------------------------------------------- -// S E G M E N T M A N I P U L A T I O N F U N C T I O N S -//------------------------------------------------------------------------- -/// \defgroup seg_man Segment manipulation functions -/// Add/Delete/Modify segments -/// \ingroup seg -//@{ - -/// Add a new segment. -/// If a segment already exists at the specified range of addresses, -/// this segment will be truncated. Instructions and data in the old -/// segment will be deleted if the new segment has another addressing -/// mode or another segment base address. -/// \param s pointer to filled segment structure. -/// segment selector should have proper mapping (see set_selector()). -/// - if s.start_ea==#BADADDR then s.start_ea <- get_segm_base(&s) -/// - if s.end_ea==#BADADDR, then a segment up to the next segment -/// will be created (if the next segment doesn't exist, then -/// 1 byte segment will be created). -/// - if the s.end_ea < s.start_ea, then fail. -/// - if s.end_ea is too high and the new segment would overlap -/// the next segment, s.end_ea is adjusted properly. -/// \param name name of new segment. may be NULL. -/// if specified, the segment is immediately renamed -/// \param sclass class of the segment. may be NULL. -/// if specified, the segment class is immediately changed -/// \param flags \ref ADDSEG_ -/// \retval 1 ok -/// \retval 0 failed, a warning message is displayed - -idaman bool ida_export add_segm_ex( - segment_t *NONNULL s, - const char *name, - const char *sclass, - int flags); -/// \defgroup ADDSEG_ Add segment flags -/// Passed as 'flags' parameter to add_segm_ex() -//@{ -#define ADDSEG_NOSREG 0x0001 ///< set all default segment register values to #BADSEL - ///< (undefine all default segment registers) -#define ADDSEG_OR_DIE 0x0002 ///< qexit() if can't add a segment -#define ADDSEG_NOTRUNC 0x0004 ///< don't truncate the new segment at the beginning of the next segment if they overlap. - ///< destroy/truncate old segments instead. -#define ADDSEG_QUIET 0x0008 ///< silent mode, no "Adding segment..." in the messages window -#define ADDSEG_FILLGAP 0x0010 ///< fill gap between new segment and previous one. - ///< i.e. if such a gap exists, and this gap is less - ///< than 64K, then fill the gap by extending the - ///< previous segment and adding .align directive - ///< to it. This way we avoid gaps between segments. - ///< too many gaps lead to a virtual array failure. - ///< it cannot hold more than ~1000 gaps. -#define ADDSEG_SPARSE 0x0020 ///< use sparse storage method for the new segment -#define ADDSEG_NOAA 0x0040 ///< do not mark new segment for auto-analysis -#define ADDSEG_IDBENC 0x0080 ///< 'name' and 'sclass' are given in the IDB encoding; - ///< non-ASCII bytes will be decoded accordingly -//@} - - -/// Add a new segment, second form. -/// Segment alignment is set to #saRelByte. -/// Segment combination is "public" or "stack" (if segment class is "STACK"). -/// Addressing mode of segment is taken as default (16bit or 32bit). -/// Default segment registers are set to #BADSEL. -/// If a segment already exists at the specified range of addresses, -/// this segment will be truncated. Instructions and data in the old -/// segment will be deleted if the new segment has another addressing -/// mode or another segment base address. -/// \param para segment base paragraph. -/// if paragraph can't fit in 16bit, then a new selector is -/// allocated and mapped to the paragraph. -/// \param start start address of the segment. -/// if start==#BADADDR then start <- to_ea(para,0). -/// \param end end address of the segment. end address should be higher than -/// start address. For emulate empty segments, use #SEG_NULL segment -/// type. If the end address is lower than start address, then fail. -/// If end==#BADADDR, then a segment up to the next segment -/// will be created (if the next segment doesn't exist, then -/// 1 byte segment will be created). -/// If 'end' is too high and the new segment would overlap -/// the next segment, 'end' is adjusted properly. -/// \param name name of new segment. may be NULL -/// \param sclass class of the segment. may be NULL. -/// type of the new segment is modified if class is one of -/// predefined names: -/// - "CODE" -> #SEG_CODE -/// - "DATA" -> #SEG_DATA -/// - "CONST" -> #SEG_DATA -/// - "STACK" -> #SEG_BSS -/// - "BSS" -> #SEG_BSS -/// - "XTRN" -> #SEG_XTRN -/// - "COMM" -> #SEG_COMM -/// - "ABS" -> #SEG_ABSSYM -/// \retval 1 ok -/// \retval 0 failed, a warning message is displayed - -idaman bool ida_export add_segm( - ea_t para, - ea_t start, - ea_t end, - const char *name, - const char *sclass, - int flags=0); - - -/// Delete a segment. -/// \param ea any address belonging to the segment -/// \param flags \ref SEGMOD_ -/// \retval 1 ok -/// \retval 0 failed, no segment at 'ea'. - -idaman bool ida_export del_segm(ea_t ea, int flags); - -/// \defgroup SEGMOD_ Segment modification flags -/// Used by functions in \ref seg_man -//@{ -#define SEGMOD_KILL 0x0001 ///< disable addresses if segment gets shrinked or deleted -#define SEGMOD_KEEP 0x0002 ///< keep information (code & data, etc) -#define SEGMOD_SILENT 0x0004 ///< be silent -#define SEGMOD_KEEP0 0x0008 ///< flag for internal use, don't set -#define SEGMOD_KEEPSEL 0x0010 ///< do not try to delete unused selector -#define SEGMOD_NOMOVE 0x0020 ///< don't move info from the start of segment to the new start address - ///< (for set_segm_start()) -#define SEGMOD_SPARSE 0x0040 ///< use sparse storage if extending the segment - ///< (for set_segm_start(), set_segm_end()) -//@} - - -/// Get number of segments - -idaman int ida_export get_segm_qty(void); - - -/// Get pointer to segment by linear address. -/// \param ea linear address belonging to the segment -/// \return NULL or pointer to segment structure - -idaman segment_t *ida_export getseg(ea_t ea); - - -/// Get pointer to segment by its number. -/// \warning Obsoleted because it can slow down the debugger (it has to refresh the whole -/// memory segmentation to calculate the correct answer) -/// \param n segment number in the range (0..get_segm_qty()-1) -/// \returns NULL or pointer to segment structure - -idaman segment_t *ida_export getnseg(int n); - - -/// Get number of segment by address. -/// \param ea linear address belonging to the segment -/// \return -1 if no segment occupies the specified address. -/// otherwise returns number of the specified segment (0..get_segm_qty()-1) -idaman int ida_export get_segm_num(ea_t ea); - - -/// Get pointer to the next segment -idaman segment_t *ida_export get_next_seg(ea_t ea); -/// Get pointer to the previous segment -idaman segment_t *ida_export get_prev_seg(ea_t ea); - -/// Get pointer to the first segment -idaman segment_t *ida_export get_first_seg(void); -/// Get pointer to the last segment -idaman segment_t *ida_export get_last_seg(void); - - -/// Get pointer to segment by its name. -/// If there are several segments with the same name, returns the first of them. -/// \param name segment name. may be NULL. -/// \return NULL or pointer to segment structure - -idaman segment_t *ida_export get_segm_by_name(const char *name); - - -/// Set segment end address. -/// The next segment is shrinked to allow expansion of the specified segment. -/// The kernel might even delete the next segment if necessary. -/// The kernel will ask the user for a permission to destroy instructions -/// or data going out of segment scope if such instructions exist. -/// \param ea any address belonging to the segment -/// \param newend new end address of the segment -/// \param flags \ref SEGMOD_ -/// \retval 1 ok -/// \retval 0 failed, a warning message is displayed - -idaman bool ida_export set_segm_end(ea_t ea, ea_t newend, int flags); - - -/// Set segment start address. -/// The previous segment is trimmed to allow expansion of the specified segment. -/// The kernel might even delete the previous segment if necessary. -/// The kernel will ask the user for a permission to destroy instructions -/// or data going out of segment scope if such instructions exist. -/// \param ea any address belonging to the segment -/// \param newstart new start address of the segment -/// note that segment start address should be higher than -/// segment base linear address. -/// \param flags \ref SEGMOD_ -/// \retval 1 ok -/// \retval 0 failed, a warning message is displayed - -idaman bool ida_export set_segm_start(ea_t ea, ea_t newstart, int flags); - - -/// Move segment start. -/// The main difference between this function and set_segm_start() is -/// that this function may expand the previous segment while set_segm_start() -/// never does it. So, this function allows to change bounds of two segments -/// simultaneously. If the previous segment and the specified segment -/// have the same addressing mode and segment base, then instructions -/// and data are not destroyed - they simply move from one segment -/// to another. Otherwise all instructions/data which migrate -/// from one segment to another are destroyed. -/// \note this function never disables addresses. -/// \param ea any address belonging to the segment -/// \param newstart new start address of the segment -/// note that segment start address should be higher than -/// segment base linear address. -/// \param mode policy for destroying defined items -/// - 0: if it is necessary to destroy defined items, -/// display a dialog box and ask confirmation -/// - 1: if it is necessary to destroy defined items, -/// just destroy them without asking the user -/// - -1: if it is necessary to destroy defined items, -/// don't destroy them (i.e. function will fail) -/// - -2: don't destroy defined items (function will succeed) -/// \retval 1 ok -/// \retval 0 failed, a warning message is displayed - -idaman bool ida_export move_segm_start(ea_t ea, ea_t newstart, int mode); - - -/// Move a segment to a new address. -/// This function moves all information to the new address. -/// It fixes up address sensitive information in the kernel. -/// The total effect is equal to reloading the segment to the target address. -/// For the file format dependent address sensitive information, loader_t::move_segm is called. -/// Also IDB notification event idb_event::segm_moved is called. -/// \param s segment to move -/// \param to new segment start address -/// \param flags \ref MSF_ -/// \return \ref MOVE_SEGM_ - -idaman int ida_export move_segm(segment_t *s, ea_t to, int flags=0); - -/// \defgroup MSF_ Move segment flags -/// Passed as 'flags' parameter to move_segm() and rebase_program() -//@{ -#define MSF_SILENT 0x0001 ///< don't display a "please wait" box on the screen -#define MSF_NOFIX 0x0002 ///< don't call the loader to fix relocations -#define MSF_LDKEEP 0x0004 ///< keep the loader in the memory (optimization) -#define MSF_FIXONCE 0x0008 ///< call loader only once with the special calling method. - ///< valid for rebase_program(). see loader_t::move_segm. -#define MSF_PRIORITY 0x0020 ///< loader segments will overwrite any existing debugger segments when moved. - ///< valid for move_segm() -#define MSF_NETNODES 0x0080 ///< move netnodes instead of changing inf.netdelta (this is slower) - ///< valid for rebase_program() -//@} - -/// \defgroup MOVE_SEGM_ Move segment result codes -/// Return values for move_segm() add rebase_program() -//@{ -#define MOVE_SEGM_OK 0 ///< all ok -#define MOVE_SEGM_PARAM -1 ///< The specified segment does not exist -#define MOVE_SEGM_ROOM -2 ///< Not enough free room at the target address -#define MOVE_SEGM_IDP -3 ///< IDP module forbids moving the segment -#define MOVE_SEGM_CHUNK -4 ///< Too many chunks are defined, can't move -#define MOVE_SEGM_LOADER -5 ///< The segment has been moved but the loader complained -#define MOVE_SEGM_ODD -6 ///< Cannot move segments by an odd number of bytes -#define MOVE_SEGM_ORPHAN -7 ///< Orphan bytes hinder segment movement -#define MOVE_SEGM_DEBUG -8 ///< Debugger segments cannot be moved -//@} - - -/// Rebase the whole program by 'delta' bytes. -/// \param delta number of bytes to move the program -/// \param flags \ref MSF_ -/// it is recommended to use #MSF_FIXONCE so that the loader takes -/// care of global variables it stored in the database -/// \return \ref MOVE_SEGM_ - -idaman int ida_export rebase_program(adiff_t delta, int flags); - - -/// Convert a debugger segment to a regular segment and vice versa. -/// When converting debug->regular, the memory contents will be copied -/// to the database. -/// \param s segment to modify -/// \param is_deb_segm new status of the segment -/// \return \ref CSS_ - -idaman int ida_export change_segment_status(segment_t *s, bool is_deb_segm); - -/// \defgroup CSS_ Change segment status result codes -/// Return values for change_segment_status() -//@{ -#define CSS_OK 0 ///< ok -#define CSS_NODBG -1 ///< debugger is not running -#define CSS_NORANGE -2 ///< could not find corresponding memory range -#define CSS_NOMEM -3 ///< not enough memory (might be because the segment - ///< is too big) -#define CSS_BREAK -4 ///< memory reading process stopped by user -//@} - - -/// Take a memory snapshot of the running process. -/// \param only_loader_segs only is_loader_segm() segments will be affected -/// \return success - -idaman bool ida_export take_memory_snapshot(bool only_loader_segs); - - -/// Is the database a miniidb created by the debugger?. -/// \return true if the database contains no segments -/// or only debugger segments - -idaman bool ida_export is_miniidb(void); - - -/// Internal function - -idaman bool ida_export set_segm_base(segment_t *s, ea_t newbase); - -//@} seg_man - -//------------------------------------------------------------------------- -// S E G M E N T G R O U P S -//------------------------------------------------------------------------- -/// \defgroup seg_grp Segment groups -/// \ingroup seg -//@{ - - -/// Create a new group of segments (used OMF files). -/// \param grp selector of group segment (segment type is #SEG_GRP) -/// You should create an 'empty' (1 byte) group segment -/// It won't contain anything and will be used to -/// redirect references to the group of segments to the -/// common selector. -/// \param sel common selector of all segments belonging to the segment -/// You should create all segments within the group with the -/// same selector value. -/// \return 1 ok -/// \return 0 too many groups (see #MAX_GROUPS) - -idaman int ida_export set_group_selector(sel_t grp, sel_t sel); - -#define MAX_GROUPS 8 ///< max number of segment groups - - -/// Get common selector for a group of segments. -/// \param grpsel selector of group segment -/// \return common selector of the group or 'grpsel' if no such group is found - -idaman sel_t ida_export get_group_selector(sel_t grpsel); - -//@} seg_grp - -//------------------------------------------------------------------------- -// S E G M E N T T R A N S L A T I O N S -/// -/// \defgroup seg_trans Segment translations -/// \ingroup seg -/// -/// Used to represent overlayed memory banks. -/// Segment translations are used to redirect access to overlayed segments -/// so that the correct overlay is accessed. Each segment has its own -/// translation list. For example, suppose we have -/// four segments: -/// <pre> -/// A 1000-2000 -/// B 1000-2000 -/// C 2000-3000 -/// D 2000-3000 -/// </pre> -/// A and B occupy the same virtual addresses. The same with C and D. -/// Segment A works with segment C, segment B works with segment D. -/// -/// So all references from A to 2000-3000 should go to C. For this -/// we add translation C for segment A. The same with B,D: add -/// translation D for segment B. Also, we need to specify the correct -/// segment to be accessed from C, thus we add translation A for segment C. -/// And we add translation B for segment D. -/// -/// After this, all references to virtual addresses 2000-3000 made from A -/// go to segment C (even if segment A would be large and occupy 1000-3000) -/// So, we need the following translations: -/// <pre> -/// A: C -/// B: D -/// C: A -/// D: B -/// </pre> -/// With translations, the segments may reside at any linear addresses, -/// all references will pass through the translation mechanism and go to the -/// correct segment. -/// -/// Segment translation works only for code segments (see map_code_ea()) -//@{ -//------------------------------------------------------------------------- - -/// Add segment translation. -/// \param segstart start address of the segment to add translation to -/// \param mappedseg start address of the overlayed segment -/// \retval 1 ok -/// \retval 0 too many translations or bad segstart - -idaman bool ida_export add_segment_translation(ea_t segstart, ea_t mappedseg); - -#define MAX_SEGM_TRANSLATIONS 64 ///< max number of segment translations - - -/// Set new translation list. -/// \param segstart start address of the segment to add translation to -/// \param transmap vector of segment start addresses for the translation list. -/// If transmap is empty, the translation list is deleted. -/// \retval 1 ok -/// \retval 0 too many translations or bad segstart - -idaman bool ida_export set_segment_translations(ea_t segstart, const eavec_t &transmap); - - -/// Delete the translation list -/// \param segstart start address of the segment to delete translation list - -idaman void ida_export del_segment_translations(ea_t segstart); - - -/// Get segment translation list. -/// \param transmap vector of segment start addresses for the translation list -/// \param segstart start address of the segment to get information about -/// \return -1 if no translation list or bad segstart. -/// otherwise returns size of translation list. - -idaman ssize_t ida_export get_segment_translations(eavec_t *transmap, ea_t segstart); -//@} seg_trans - -//------------------------------------------------------------------------- -// S E G M E N T C O M M E N T S -// -/// \defgroup seg_cmt Segment comments -/// \ingroup seg -/// -/// Segment comments are rarely used yet. -/// The user may define a segment comment by pressing ':' -/// while standing on the segment name at the segment start. -/// -/// The main advantage of segment comments compared to anterior -/// lines (see lines.hpp) is that they are attached to a segment, -/// not to an address and they will move with the start of segment -/// if the segment boundaries change. -/// -/// You may set segment comments in your LDR module to describe -/// characteristics of a segment in comments. -/// -/// Repeatable segment comments are not used at all, because I don't -/// know where they should be repeated. -//@{ -//------------------------------------------------------------------------- - -/// Get segment comment. -/// \param buf buffer for the comment -/// \param s pointer to segment structure -/// \param repeatable 0: get regular comment. -/// 1: get repeatable comment. -/// \return size of comment or -1 - -idaman ssize_t ida_export get_segment_cmt(qstring *buf, const segment_t *s, bool repeatable); - - -/// Set segment comment. -/// \param s pointer to segment structure -/// \param cmt comment string, may be multiline (with '\n'). -/// maximal size is 4096 bytes. -/// Use empty str ("") to delete comment -/// \param repeatable 0: set regular comment. -/// 1: set repeatable comment. -/// - -idaman void ida_export set_segment_cmt(const segment_t *s, const char *cmt, bool repeatable); - - -/// Generate segment footer line as a comment line. -/// This function may be used in IDP modules to generate segment footer -/// if the target assembler doesn't have 'ends' directive. - -idaman void ida_export std_out_segm_footer(struct outctx_t &ctx, segment_t *seg); - -//@} seg_cmt - -//------------------------------------------------------------------------- -// S E G M E N T N A M E S -//------------------------------------------------------------------------- -/// \defgroup seg_name Segment names -/// \ingroup seg -/// Various ways to retrieve the name of a segment -//@{ - -/// Rename segment. -/// The new name is validated (see validate_name). -/// A segment always has a name. If you hadn't specified a name, -/// the kernel will assign it "seg###" name where ### is segment number. -/// \param s pointer to segment (may be NULL) -/// \param name new segment name -/// \param flags ADDSEG_IDBENC or 0 -/// \retval 1 ok, name is good and segment is renamed -/// \retval 0 failure, name is bad or segment is NULL - -idaman int ida_export set_segm_name( - segment_t *s, - const char *name, - int flags=0); - - -/// Get true segment name by pointer to segment. -/// \param buf output buffer. cannot be NULL -/// \param s pointer to segment -/// \param flags 0-return name as is; 1-substitute bad symbols with _ -/// 1 corresponds to GN_VISIBLE -/// \return size of segment name (-1 if s==NULL) - -idaman ssize_t ida_export get_segm_name(qstring *buf, const segment_t *s, int flags=0); - - -/// Get segment name by pointer to segment. -/// \param buf output buffer. cannot be NULL -/// \param s pointer to segment -/// \return size of segment name (-1 if s==NULL) - -inline ssize_t idaapi get_visible_segm_name(qstring *buf, const segment_t *s) -{ - return get_segm_name(buf, s, 1); -} - - -/// Get colored segment name expression in the form (segname + displacement). -/// \param buf output buffer to hold segment expression -/// \param from linear address of instruction operand or data referring to -/// the name. This address will be used to get fixup information, -/// so it should point to exact position of operand in the -/// instruction. -/// \param sel value to convert to segment expression -/// \return size of segment expression or -1 - -ssize_t get_segm_expr(qstring *buf, ea_t from, sel_t sel); - -//@} seg_name - -//------------------------------------------------------------------------- -// S E G M E N T C L A S S E S A N D T Y P E S -//------------------------------------------------------------------------- -/// \defgroup seg_type Segment classes and types -/// \ingroup seg -/// See \ref SEG_ -//@{ - -/// Get segment class. -/// Segment class is arbitrary text (max 8 characters). -/// \param buf output buffer. cannot be NULL. -/// \param s pointer to segment -/// \return size of segment class (-1 if s==NULL or bufsize<=0) - -idaman ssize_t ida_export get_segm_class(qstring *buf, const segment_t *s); - - -/// Set segment class. -/// \param s pointer to segment (may be NULL) -/// \param sclass segment class (may be NULL). -/// If segment type is #SEG_NORM and segment class is one of predefined -/// names, then segment type is changed to: -/// - "CODE" -> #SEG_CODE -/// - "DATA" -> #SEG_DATA -/// - "STACK" -> #SEG_BSS -/// - "BSS" -> #SEG_BSS -/// - if "UNK" then segment type is reset to #SEG_NORM. -/// \retval 1 ok, name is good and segment is renamed -/// \retval 0 failure, name is NULL or bad or segment is NULL - -idaman int ida_export set_segm_class(segment_t *s, const char *sclass, int flags=0); - - -/// Get segment type. -/// \param ea any linear address within the segment -/// \return \ref SEG_, #SEG_UNDF if no segment found at 'ea' - -idaman uchar ida_export segtype(ea_t ea); - -//@} seg_type - -//------------------------------------------------------------------------- -// S E G M E N T A L I G N M E N T A N D C O M B I N A T I O N -//------------------------------------------------------------------------- -/// \defgroup seg_align Segment alignment and combination -/// \ingroup seg -//@{ - -/// Get text representation of segment alignment code. -/// \return text digestable by IBM PC assembler. - -idaman const char *ida_export get_segment_alignment(uchar align); - - -/// Get text representation of segment combination code. -/// \return text digestable by IBM PC assembler. - -idaman const char *ida_export get_segment_combination(uchar comb); - -//@} seg_align - -//------------------------------------------------------------------------- -// S E G M E N T A D D R E S S I N G -//------------------------------------------------------------------------- -/// \defgroup seg_addr Segment addressing -/// \ingroup seg -//@{ - -/// Get segment base paragraph. -/// Segment base paragraph may be converted to segment base linear address -/// using to_ea() function. -/// In fact, to_ea(get_segm_para(s), 0) == get_segm_base(s). -/// \param s pointer to segment -/// \return 0 if s == NULL, -/// the segment base paragraph - -idaman ea_t ida_export get_segm_para(const segment_t *s); - - -/// Get segment base linear address. -/// Segment base linear address is used to calculate virtual addresses. -/// The virtual address of the first byte of the segment will be -/// (start address of segment - segment base linear address) -/// \param s pointer to segment -/// \return 0 if s == NULL, -/// otherwise segment base linear address - -idaman ea_t ida_export get_segm_base(const segment_t *s); - - -/// Change segment addressing mode (16, 32, 64 bits). -/// You must use this function to change segment addressing, never change -/// the 'bitness' field directly. -/// This function will delete all instructions, comments and names in the segment -/// \param s pointer to segment -/// \param bitness new addressing mode of segment -/// - 2: 64bit segment -/// - 1: 32bit segment -/// - 0: 16bit segment -/// \return success - -idaman bool ida_export set_segm_addressing(segment_t *s, size_t bitness); - -//@} seg_addr - -//----------------------------------------------------------------------- - -/// Does the address belong to a debug segment? - -inline bool is_debugger_segm(ea_t ea) -{ - segment_t *s = getseg(ea); - return s != NULL && s->is_debugger_segm(); -} - -/// Does the address belong to an ephemeral segment? - -inline bool is_ephemeral_segm(ea_t ea) -{ - segment_t *s = getseg(ea); - return s != NULL && s->is_ephemeral_segm(); -} - -//------------------------------------------------------------------------- -inline ea_t correct_address(ea_t ea, ea_t from, ea_t to, ea_t size, bool skip_check=false) -{ - if ( skip_check || (ea >= from && ea < from+size) ) - ea += to - from; - return ea; -} - -//------------------------------------------------------------------------- -idaman bool ida_export update_segm(segment_t *s); - -inline bool segment_t::update(void) -{ - return update_segm(this); -} - -/// Truncate and sign extend a delta depending on the segment -idaman adiff_t ida_export segm_adjust_diff(const segment_t *s, adiff_t delta); - -/// Truncate an address depending on the segment -idaman ea_t ida_export segm_adjust_ea(const segment_t *s, ea_t ea); - -#endif // _SEGMENT_HPP diff --git a/idasdk75/include/segregs.hpp b/idasdk75/include/segregs.hpp deleted file mode 100644 index 2714806..0000000 --- a/idasdk75/include/segregs.hpp +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _SRAREA_HPP -#define _SRAREA_HPP - -#include <range.hpp> - -/*! \file segregs.hpp - - \brief Functions that deal with the segment registers. - - If your processor doesn't use segment registers, then these functions - are of no use for you. However, you should define - two virtual segment registers - CS and DS (for code segment and - data segment) and specify their internal numbers in the LPH structure - (processor_t::reg_code_sreg and processor_t::reg_data_sreg). -*/ - -//------------------------------------------------------------------------- -/// The values of the segment registers are kept as address ranges. The segment -/// register does not change its value within one address range. -/// The processor module finds segment register change points and splits -/// ::sreg_range_t ranges so that a new sreg_range_t range is started at -/// each segment register change point. The kernel deletes sreg_range_t -/// if an instruction is converted back to unexplored bytes. -/// -/// So, we have information about a segment register by keeping information -/// about the range of addresses where segment register does not change the value. -/// -/// Note that each segment has information about the default values of -/// the segment registers. This information is used if the value of a segment -/// register could not be determined. -struct sreg_range_t : public range_t -{ - sel_t val; ///< segment register value - uchar tag; ///< \ref SR_ - -/// \defgroup SR_ Segment register range tags -/// Used by sreg_range_t::tag -//@{ -#define SR_inherit 1 ///< the value is inherited from the previous range -#define SR_user 2 ///< the value is specified by the user -#define SR_auto 3 ///< the value is determined by IDA -#define SR_autostart 4 ///< used as #SR_auto for segment starting address -//@} -}; -DECLARE_TYPE_AS_MOVABLE(sreg_range_t); - - -/// Get value of a segment register. -/// This function uses segment register range and default segment register -/// values stored in the segment structure. -/// \param ea linear address in the program -/// \param rg number of the segment register -/// \return value of the segment register, #BADSEL if value is unknown. - -idaman sel_t ida_export get_sreg(ea_t ea, int rg); - - -/// Create a new segment register range. -/// This function is used when the IDP emulator detects that a segment -/// register changes its value. -/// \param ea linear address where the segment register will -/// have a new value. if ea==#BADADDR, nothing to do. -/// \param rg the number of the segment register -/// \param v the new value of the segment register. If the value is -/// unknown, you should specify #BADSEL. -/// \param tag the register info tag. see \ref SR_ -/// \param silent if false, display a warning() in the case of failure -/// \return success - -idaman bool ida_export split_sreg_range( - ea_t ea, - int rg, - sel_t v, - uchar tag, - bool silent=false); - - -/// Set default value of a segment register for a segment. -/// \param sg pointer to segment structure -/// if NULL, then set the register for all segments -/// \param rg number of segment register -/// \param value its default value. this value will be used by get_sreg() -/// if value of the register is unknown at the specified address. -/// \return success - -idaman bool ida_export set_default_sreg_value(segment_t *sg, int rg, sel_t value); - - -/// Set the segment register value at the next instruction. -/// This function is designed to be called from idb_event::sgr_changed handler -/// in order to contain the effect of changing a segment -/// register value only until the next instruction. -/// -/// It is useful, for example, in the ARM module: the modification -/// of the T register does not affect existing instructions later in the code. -/// \param ea1 address to start to search for an instruction -/// \param ea2 the maximal address -/// \param rg the segment register number -/// \param value the segment register value - -idaman void ida_export set_sreg_at_next_code(ea_t ea1, ea_t ea2, int rg, sel_t value); - - -/// Get segment register range by linear address. -/// \param out segment register range -/// \param ea any linear address in the program -/// \param rg the segment register number -/// \return success - -idaman bool ida_export get_sreg_range(sreg_range_t *out, ea_t ea, int rg); - - -/// Get segment register range previous to one with address. -/// \note more efficient then get_sreg_range(reg, ea-1) -/// \param out segment register range -/// \param ea any linear address in the program -/// \param rg the segment register number -/// \return success - -idaman bool ida_export get_prev_sreg_range(sreg_range_t *out, ea_t ea, int rg); - - -/// Set default value of DS register for all segments - -idaman void ida_export set_default_dataseg(sel_t ds_sel); - - -/// Get number of segment register ranges. -/// \param rg the segment register number - -idaman size_t ida_export get_sreg_ranges_qty(int rg); - - -/// Get segment register range by its number. -/// \param out segment register range -/// \param rg the segment register number -/// \param n number of range (0..qty()-1) -/// \return success - -idaman bool ida_export getn_sreg_range(sreg_range_t *out, int rg, int n); - - -/// Get number of segment register range by address. -/// \param ea any address in the range -/// \param rg the segment register number -/// \return -1 if no range occupies the specified address. -/// otherwise returns number of -/// the specified range (0..get_srranges_qty()-1) - -idaman int ida_export get_sreg_range_num(ea_t ea, int rg); - - -/// Delete segment register range started at ea. -/// When a segment register range is deleted, -/// the previous range is extended to cover the empty space. -/// The segment register range at the beginning of a segment cannot be deleted. -/// \param ea start_ea of the deleted range -/// \param rg the segment register number -/// \return success - -idaman bool ida_export del_sreg_range(ea_t ea, int rg); - - -/// Duplicate segment register ranges. -/// \param dst_rg number of destination segment register -/// \param src_rg copy ranges from -/// \param map_selector map selectors to linear addresses using sel2ea() - -idaman void ida_export copy_sreg_ranges(int dst_rg, int src_rg, bool map_selector=false); - - -#endif // _SRAREA_HPP diff --git a/idasdk75/include/strlist.hpp b/idasdk75/include/strlist.hpp deleted file mode 100644 index 22c3e4c..0000000 --- a/idasdk75/include/strlist.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * The Interactive Disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _STRLIST_HPP -#define _STRLIST_HPP - -/*! \file strlist.hpp - - \brief Functions that deal with the string list - - While the kernel keeps the strings list, it does not update it. - The string list is not used by the kernel because - keeping it up-to-date would slow down IDA without any benefit. - - The users of this list should build_strlist() before accessing it. -*/ - -/// Structure to keep string list parameters -struct strwinsetup_t -{ - strwinsetup_t() - : minlen(-1), display_only_existing_strings(0), - only_7bit(1), ignore_heads(0) {} - bytevec_t strtypes; // set of allowed string types - sval_t minlen; - uchar display_only_existing_strings; - uchar only_7bit; - uchar ignore_heads; - - inline bool is_initialized() const { return minlen > -1; } - -}; - -/// Information about one string from the string list -struct string_info_t -{ - ea_t ea; - int length; // in octets - int type; - string_info_t() : ea(BADADDR), length(0), type(0) {} - string_info_t(ea_t _ea) : ea(_ea), length(0), type(0) {} - bool operator<(const string_info_t &r) const { return ea < r.ea; } -}; -DECLARE_TYPE_AS_MOVABLE(string_info_t); - - -/// Get access to the static string list options - -idaman strwinsetup_t *ida_export get_strlist_options(); - - -/// Build the string list. -/// You should initialize options before this call using the -/// restore_config() or setup_strings_window() methods. - -idaman void ida_export build_strlist(); - - -/// Clear the string list. - -idaman void ida_export clear_strlist(); - - -/// Get number of elements in the string list - -idaman size_t ida_export get_strlist_qty(void); - - -/// Get nth element of the string list (n=0..get_strlist_qty()-1) - -idaman bool ida_export get_strlist_item(string_info_t *si, size_t n); - - -#endif // _STRLIST_HPP diff --git a/idasdk75/include/struct.hpp b/idasdk75/include/struct.hpp deleted file mode 100644 index 1beaa14..0000000 --- a/idasdk75/include/struct.hpp +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -/*! \file struct.hpp - - \brief Structure type management (assembly level types) - -*/ - -#ifndef _STRUCT_HPP -#define _STRUCT_HPP -#include <bytes.hpp> - -#define STRUC_SEPARATOR '.' ///< structname.fieldname - -/// Describes a member of an assembly level structure -class member_t -{ -public: - tid_t id; ///< name(), cmt, rptcmt - ea_t soff; ///< start offset (for unions - number of the member 0..n) - ea_t eoff; ///< end offset - flags_t flag; ///< type+representation bits -//private: - uint32 props; ///< \ref MF_ -/// \defgroup MF_ Struct member properties -/// Used by member_t::props -//@{ -#define MF_OK 0x00000001 ///< is the member ok? (always yes) -#define MF_UNIMEM 0x00000002 ///< is a member of a union? -#define MF_HASUNI 0x00000004 ///< has members of type "union"? -#define MF_BYTIL 0x00000008 ///< the member was created due to the type system -#define MF_HASTI 0x00000010 ///< has type information? -#define MF_BASECLASS 0x00000020 ///< a special member representing base class -#define MF_DTOR 0x00000040 ///< a special member representing destructor -#define MF_DUPNAME 0x00000080 ///< duplicate name resolved with _N suffix (N==soff) -//@} - - /// Is a member of a union? - bool unimem(void) const { return (props & MF_UNIMEM) != 0; } - /// Has members of type "union"? - bool has_union(void) const { return (props & MF_HASUNI) != 0; } - /// Was the member created due to the type system? - bool by_til(void) const { return (props & MF_BYTIL) != 0; } - /// Has type information? - bool has_ti(void) const { return (props & MF_HASTI) != 0; } - /// Is a base class member? - bool is_baseclass(void) const { return (props & MF_BASECLASS) != 0; } - /// Duplicate name was resolved during import? - bool is_dupname(void) const { return (props & MF_DUPNAME) != 0; } - /// Is a virtual destructor? - bool is_destructor(void) const { return (props & MF_DTOR) != 0; } - /// Get start offset (for unions - returns 0) - ea_t get_soff(void) const { return unimem() ? 0 : soff; } -}; - -/// Information about a structure type (assembly level) -//-V:struc_t:730 not all members of a class are initialized inside the constructor -class struc_t -{ -protected: - struc_t(void) {} ///< plugins may not create struc_t instances. they should - ///< use add_struc() and get_struc() -public: - tid_t id; ///< struct id - uint32 memqty; ///< number of members - member_t *members; ///< only defined members are stored here. - ///< there may be gaps between members. - ushort age; ///< not used - uint32 props; ///< \ref SF_ -/// \defgroup SF_ Structure properties -/// Used by struc_t::props -//@{ -#define SF_VAR 0x00000001 ///< is variable size structure (varstruct)? - ///< a variable size structure is one with - ///< the zero size last member. - ///< if the last member is a varstruct, then the current - ///< structure is a varstruct too. -#define SF_UNION 0x00000002 ///< is a union? - ///< varunions are prohibited! -#define SF_HASUNI 0x00000004 ///< has members of type "union"? -#define SF_NOLIST 0x00000008 ///< don't include in the chooser list -#define SF_TYPLIB 0x00000010 ///< the structure comes from type library -#define SF_HIDDEN 0x00000020 ///< the structure is collapsed -#define SF_FRAME 0x00000040 ///< the structure is a function frame -#define SF_ALIGN 0x00000F80 ///< alignment (shift amount: 0..31) -#define SF_GHOST 0x00001000 ///< ghost copy of a local type -//@} - - /// Is variable size structure? - bool is_varstr(void) const { return (props & SF_VAR) != 0; } - /// Is a union? - bool is_union(void) const { return (props & SF_UNION) != 0; } - /// Has members of type "union"? - bool has_union(void) const { return (props & SF_HASUNI) != 0; } - /// Is included in chooser list? - /// Use \ref set_struc_listed to change the listed status - bool is_choosable(void) const { return (props & SF_NOLIST) == 0; } - /// Does structure come from a type library? - bool from_til(void) const { return (props & SF_TYPLIB) != 0; } - /// Is the structure collapsed? - /// Use \ref set_struc_hidden to change the hidden status - bool is_hidden(void) const { return (props & SF_HIDDEN) != 0; } - /// Is this structure a function frame? - bool is_frame(void) const { return (props & SF_FRAME) != 0; } - /// See #SF_ALIGN - int get_alignment(void) const { return (props & SF_ALIGN) >> 7; } - /// Is a ghost copy of a local type? - bool is_ghost(void) const { return (props & SF_GHOST) != 0; } - - /// Do not use; use set_struc_align() - void set_alignment(int shift) - { - props &= ~SF_ALIGN; - props |= (shift << 7) & SF_ALIGN; - } - - void set_ghost(bool _is_ghost) { setflag(props, SF_GHOST, _is_ghost); } - - mutable int32 ordinal; ///< corresponding local type ordinal number -}; - -/// \name Internal structures list -/// IDA maintains an internal vector of known structures. -/// Use these functions to work with this vector. -//@{ - -/// Get number of known structures - -idaman size_t ida_export get_struc_qty(void); - - -/// Get index of first structure. -/// \return #BADADDR if no known structures, 0 otherwise - -idaman uval_t ida_export get_first_struc_idx(void); - - -/// Get index of last structure. -/// \return #BADADDR if no known structures, get_struc_qty()-1 otherwise - -idaman uval_t ida_export get_last_struc_idx(void); - - -/// Get previous struct index. -/// \return #BADADDR if resulting index is negative, otherwise idx - 1 - -inline THREAD_SAFE uval_t get_prev_struc_idx(uval_t idx) { return idx == BADNODE ? idx : idx - 1; } - - -/// Get next struct index. -/// \return #BADADDR if resulting index is out of bounds, otherwise idx++ - -idaman uval_t ida_export get_next_struc_idx(uval_t idx); - - -/// Get internal number of the structure - -idaman uval_t ida_export get_struc_idx(tid_t id); - - -/// Get struct id by struct number - -idaman tid_t ida_export get_struc_by_idx(uval_t idx); - - -/// Get pointer to struct type info - -idaman struc_t *ida_export get_struc(tid_t id); - -//@} - - -/// Get struct id by name - -inline tid_t get_struc_id(const char *name) -{ - tid_t id = node2ea(netnode(name)); - return get_struc(id) == NULL ? BADADDR : id; -} - - -/// Get struct name by id -/// \param[out] out buffer to hold the name -/// \param id struct id -/// \param flags \ref STRNFL_ - -idaman ssize_t ida_export get_struc_name(qstring *out, tid_t id, int flags=0); - -/// \defgroup STRNFL_ Struct name flags -/// Passed as 'flags' parameter to get_struc_name() -//@{ -#define STRNFL_REGEX 0x0001 ///< apply regular expressions to beautify the name -//@} - -inline qstring get_struc_name(tid_t id, int flags=0) -{ - qstring name; - get_struc_name(&name, id, flags); - return name; -} - -/// Get struct comment - -inline ssize_t get_struc_cmt(qstring *buf, tid_t id, bool repeatable) { return getnode(id).supstr(buf, repeatable != 0); } - - -/// Get struct size (also see get_struc_size(tid_t)) - -idaman asize_t ida_export get_struc_size(const struc_t *sptr); - -/// Get struct size (also see get_struc_size(const struc_t *)) - -inline asize_t get_struc_size(tid_t id) { return get_struc_size(get_struc(id)); } - - -/// \name Struct offsets -/// \note for unions, soff == number of the current member -//@{ - -/// Get offset of member with largest offset less than 'offset'. -/// \return #BADADDR if no prev offset - -idaman ea_t ida_export get_struc_prev_offset(const struc_t *sptr, ea_t offset); - - -/// Get offset of member with smallest offset larger than 'offset'. -/// \return #BADADDR if no next offset - -idaman ea_t ida_export get_struc_next_offset(const struc_t *sptr, ea_t offset); - - -/// Get offset of last member. -/// \return #BADADDR if memqty == 0 - -idaman ea_t ida_export get_struc_last_offset(const struc_t *sptr); - - -/// Get offset of first member. -/// \return #BADADDR if memqty == 0 - -idaman ea_t ida_export get_struc_first_offset(const struc_t *sptr); - - -/// For unions: returns number of members, for structs: returns size of structure - -inline ea_t get_max_offset(struc_t *sptr) -{ - if ( sptr == NULL ) - return 0; // just to avoid GPF - return sptr->is_union() - ? sptr->memqty - : get_struc_size(sptr); -} - -//@} - -/// Is variable size structure? - -inline bool is_varstr(tid_t id) -{ - struc_t *sptr = get_struc(id); - return sptr != NULL && sptr->is_varstr(); -} - -/// Is a union? - -inline bool is_union(tid_t id) -{ - struc_t *sptr = get_struc(id); - return sptr != NULL && sptr->is_union(); -} - - -/// Get containing structure of member by its full name "struct.field" - -idaman struc_t *ida_export get_member_struc(const char *fullname); - - -/// Get child struct if member is a struct - -idaman struc_t *ida_export get_sptr(const member_t *mptr); - - -/// Get member at given offset - -idaman member_t *ida_export get_member(const struc_t *sptr, asize_t offset); - -/// Get member id at given offset - -inline tid_t get_member_id(const struc_t *sptr, asize_t offset) -{ - member_t *mptr = get_member(sptr, offset); - return mptr != NULL ? mptr->id : BADADDR; -} - - -/// Get a member by its name, like "field44" - -idaman member_t *ida_export get_member_by_name(const struc_t *sptr, const char *membername); - - -/// Get a member by its fully qualified name, "struct.field" - -idaman member_t *ida_export get_member_by_fullname(struc_t **sptr_place, const char *fullname); - - -/// Get a member's fully qualified name, "struct.field" - -inline ssize_t idaapi get_member_fullname(qstring *out, tid_t mid) { return getnode(mid).get_name(out); } - - -/// Get name of structure member - -idaman ssize_t ida_export get_member_name(qstring *out, tid_t mid); - -inline qstring get_member_name(tid_t mid) -{ - qstring name; - get_member_name(&name, mid); - return name; -} - - -/// Get comment of structure member - -inline ssize_t idaapi get_member_cmt(qstring *buf, tid_t mid, bool repeatable) { return getnode(mid).supstr(buf, repeatable != 0); } - - -/// Get size of structure member. -/// May return 0 for the last member of varstruct. -/// For union members, returns member_t::eoff. - -inline asize_t get_member_size(const member_t *NONNULL mptr) { return mptr->unimem() ? mptr->eoff : (mptr->eoff - mptr->soff); } - - -/// Is variable size member? - -idaman bool ida_export is_varmember(const member_t *mptr); - - -/// Get member that is most likely referenced by the specified offset. -/// Useful for offsets > sizeof(struct). - -idaman member_t *ida_export get_best_fit_member(const struc_t *sptr, asize_t offset); - - -/// Get the next member idx, if it does not exist, return -1 - -idaman ssize_t ida_export get_next_member_idx(const struc_t *sptr, asize_t off); - - -/// Get the prev member idx, if it does not exist, return -1 - -idaman ssize_t ida_export get_prev_member_idx(const struc_t *sptr, asize_t off); - -//-------------------------------------------------------------------------- -// manipulation - -/// Create a structure type. -/// if idx==#BADADDR then add as the last idx. -/// if name==NULL then a name will be generated "struct_%d". - -idaman tid_t ida_export add_struc(uval_t idx, const char *name, bool is_union=false); - - -/// Delete a structure type - -idaman bool ida_export del_struc(struc_t *sptr); - - -/// Set internal number of struct. -/// Also see get_struc_idx(), get_struc_by_idx(). - -idaman bool ida_export set_struc_idx(const struc_t *sptr, uval_t idx); - - -/// Set structure alignment (#SF_ALIGN) - -idaman bool ida_export set_struc_align(struc_t *sptr, int shift); - - -/// Set structure name - -idaman bool ida_export set_struc_name(tid_t id, const char *name); - - -/// Set structure comment - -idaman bool ida_export set_struc_cmt(tid_t id, const char *cmt, bool repeatable); - - -/// Return values for add_struc_member() -enum struc_error_t -{ - STRUC_ERROR_MEMBER_OK = 0, ///< success - STRUC_ERROR_MEMBER_NAME = -1, ///< already has member with this name (bad name) - STRUC_ERROR_MEMBER_OFFSET = -2, ///< already has member at this offset - STRUC_ERROR_MEMBER_SIZE = -3, ///< bad number of bytes or bad sizeof(type) - STRUC_ERROR_MEMBER_TINFO = -4, ///< bad typeid parameter - STRUC_ERROR_MEMBER_STRUCT = -5, ///< bad struct id (the 1st argument) - STRUC_ERROR_MEMBER_UNIVAR = -6, ///< unions can't have variable sized members - STRUC_ERROR_MEMBER_VARLAST = -7, ///< variable sized member should be the last member in the structure - STRUC_ERROR_MEMBER_NESTED = -8, ///< recursive structure nesting is forbidden -}; - - -/// Add member to existing structure. -/// \param sptr structure to modify -/// \param fieldname if NULL, then "anonymous_#" name will be generated -/// \param offset #BADADDR means add to the end of structure -/// \param flag type + representation bits -/// \param mt additional info about member type. -/// must be present for -/// structs, offsets, enums, strings, -/// struct offsets. -/// \param nbytes if == 0 then the structure -/// will be a varstruct. -/// in this case the member should be -/// the last member in the structure - -idaman struc_error_t ida_export add_struc_member( - struc_t *sptr, - const char *fieldname, - ea_t offset, - flags_t flag, - const opinfo_t *mt, - asize_t nbytes); - - -/// Delete member at given offset - -idaman bool ida_export del_struc_member(struc_t *sptr, ea_t offset); - - -/// Delete members which occupy range of offsets (off1..off2). -/// \return number of deleted members or -1 on error - -idaman int ida_export del_struc_members(struc_t *sptr, ea_t off1, ea_t off2); - - -/// Set name of member at given offset - -idaman bool ida_export set_member_name(struc_t *sptr, ea_t offset,const char *name); - - -/// Set type of member at given offset (also see add_struc_member()) - -idaman bool ida_export set_member_type(struc_t *sptr, ea_t offset, flags_t flag,const opinfo_t *mt, asize_t nbytes); - - -/// Set member comment - -idaman bool ida_export set_member_cmt(member_t *mptr,const char *cmt, bool repeatable); - - -/// Expand/Shrink structure type - -idaman bool ida_export expand_struc(struc_t *sptr, ea_t offset, adiff_t delta, bool recalc=true); - - -/// Update struct information in the database (internal function) - -idaman void ida_export save_struc(struc_t *sptr, bool may_update_ltypes=true); - - -/// Hide/unhide a struct type -inline void idaapi set_struc_hidden(struc_t *sptr, bool is_hidden) -{ - setflag(sptr->props, SF_HIDDEN, is_hidden); - save_struc(sptr, false); -} - -/// Add/remove a struct type from the struct list -inline void idaapi set_struc_listed(struc_t *sptr, bool is_listed) -{ - setflag(sptr->props, SF_NOLIST, !is_listed); - save_struc(sptr, false); -} - -/// Member type information (return values for set_member_tinfo()) -enum smt_code_t -{ - SMT_BADARG = -6, ///< bad parameters - SMT_NOCOMPAT = -5, ///< the new type is not compatible with the old type - SMT_WORSE = -4, ///< the new type is worse than the old type - SMT_SIZE = -3, ///< the new type is incompatible with the member size - SMT_ARRAY = -2, ///< arrays are forbidden as function arguments - SMT_OVERLAP = -1, ///< member would overlap with members that cannot be deleted - SMT_FAILED = 0, ///< failed to set new member type - SMT_OK = 1, ///< success: changed the member type - SMT_KEEP = 2, ///< no need to change the member type, the old type is better -}; - - -/// Get tinfo for given member - -idaman bool ida_export get_member_tinfo(tinfo_t *tif, const member_t *mptr); - - -/// Delete tinfo for given member - -idaman bool ida_export del_member_tinfo(struc_t *sptr, member_t *mptr); - - -/// Set tinfo for given member. -/// \param sptr containing struct -/// \param mptr target member -/// \param memoff offset within member -/// \param tif type info -/// \param flags \ref SET_MEMTI_ - -idaman smt_code_t ida_export set_member_tinfo( - struc_t *sptr, - member_t *mptr, - uval_t memoff, - const tinfo_t &tif, - int flags); - -/// \defgroup SET_MEMTI_ Set member tinfo flags -/// Passed as 'flags' parameter to set_member_tinfo() -//@{ -#define SET_MEMTI_MAY_DESTROY 0x0001 ///< may destroy other members -#define SET_MEMTI_COMPATIBLE 0x0002 ///< new type must be compatible with the old -#define SET_MEMTI_FUNCARG 0x0004 ///< mptr is function argument (cannot create arrays) -#define SET_MEMTI_BYTIL 0x0008 ///< new type was created by the type subsystem -#define SET_MEMTI_USERTI 0x0010 ///< user-specified type -//@} - - -/// Try to get tinfo for given member - if failed, generate a tinfo using information about the -/// member id from the disassembly - -idaman bool ida_export get_or_guess_member_tinfo(tinfo_t *tif, const member_t *mptr); - - -/// Get operand type info for member - -inline opinfo_t *retrieve_member_info(opinfo_t *buf, const member_t *mptr) -{ - if ( mptr == NULL ) - return NULL; - return get_opinfo(buf, mptr->id, 0, mptr->flag); -} - - -/// Is member name prefixed with "anonymous"? - -inline THREAD_SAFE bool is_anonymous_member_name(const char *name) -{ - return name == NULL - || strncmp(name, "anonymous", 9) == 0; -} - - -/// Is member name an auto-generated name? - -inline THREAD_SAFE bool is_dummy_member_name(const char *name) -{ - return name == NULL - || strncmp(name, "arg_", 4) == 0 - || strncmp(name, "var_", 4) == 0 - || is_anonymous_member_name(name); -} - - -/// Check if the specified member id points to a struct member - -inline member_t *idaapi get_member_by_id( - qstring *out_mname, // note: id 'out_mname' is important for SWiG - tid_t mid, - struc_t **sptr_place) -{ - if ( get_member_fullname(out_mname, mid) > 0 ) - return get_member_by_fullname(sptr_place, out_mname->begin()); - return NULL; -} - - -/// Check if the specified member id points to a struct member. convenience function - -inline member_t *idaapi get_member_by_id(tid_t mid, struc_t **sptr_place=NULL) -{ - qstring buf; - return get_member_by_id(&buf, mid, sptr_place); -} - - -/// Is a member id? - -inline bool is_member_id(tid_t mid) -{ - return get_member_by_id(mid) != NULL; -} - - -/// Is a special member with the name beginning with ' '? - -idaman bool ida_export is_special_member(tid_t id); - - -/// Implements action to take when a field is visited with visit_stroff_fields() -struct ida_local struct_field_visitor_t -{ - virtual int idaapi visit_field(struc_t *sptr, member_t *mptr) = 0; -}; - - -//-------------------------------------------------------------------------- -/// Visit structure fields in a stroff expression or in a reference to a struct data variable. -/// This function can be used to enumerate all components of an expression like 'a.b.c'. -/// \param sfv visitor object -/// \param path struct path (path[0] contains the initial struct id) -/// \param plen len -/// \param[in,out] disp offset into structure -/// \param appzero should visit field at offset zero? - -idaman flags_t ida_export visit_stroff_fields( - struct_field_visitor_t &sfv, - const tid_t *path, - int plen, - adiff_t *disp, - bool appzero); - - -//-------------------------------------------------------------------------- -/// Should display a structure offset expression as the structure size? - -inline bool stroff_as_size(int plen, const struc_t *sptr, asize_t value) -{ - return plen == 1 - && value > 0 - && sptr != NULL - && !sptr->is_varstr() - && value == get_struc_size(sptr); -} - -//------------------------------------------------------------------------- -// F U N C T I O N S F O R T H E K E R N E L -//------------------------------------------------------------------------- - -///-------------------------------------------------------------------\cond -inline void save_structs(void) {} -///----------------------------------------------------------------\endcond - - -#endif // _STRUCT_HPP diff --git a/idasdk75/include/tryblks.hpp b/idasdk75/include/tryblks.hpp deleted file mode 100644 index 1443718..0000000 --- a/idasdk75/include/tryblks.hpp +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 2016-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * Module independent exception description - */ - -#ifndef TRYBLKS_HPP -#define TRYBLKS_HPP - -/*! \file tryblks.hpp - * - * \brief Architecture independent exception handling info. - * - * Try blocks have the following general properties: - * - An try block specifies a possibly fragmented guarded code region. - * - Each try block has always at least one catch/except block description - * - Each catch block contains its boundaries and a filter. - * - Additionally a catch block can hold sp adjustment and the offset to the - * exception object offset (C++). - * - Try blocks can be nested. Nesting is automatically calculated at the retrieval time. - * - There may be (nested) multiple try blocks starting at the same address. - * - * See examples in tests/input/src/eh_tests. - * - */ - -// We use end_ea=BADADDR if the exact boundaries are unknown of any range. - -//---------------------------------------------------------------------------- -// An exception handler clause (the body of __except or catch statement) -struct try_handler_t : public rangevec_t -{ - sval_t disp; // displacement to the stack region of the guarded region. - // if it is valid, it is fpreg relative. - // -1 means unknown. - int fpreg; // frame register number used in handler. -1 means none. - - try_handler_t() : disp(-1), fpreg(-1) {} - void clear(void) - { - rangevec_t::clear(); - disp = -1; - fpreg = -1; - } -}; -DECLARE_TYPE_AS_MOVABLE(try_handler_t); - -//---------------------------------------------------------------------------- -// __except() {} statement -struct seh_t : public try_handler_t -{ - rangevec_t filter; // boundaries of the filter callback. if filter is empty, - ea_t seh_code; // then use seh_code -#define SEH_CONTINUE BADADDR // EXCEPTION_CONTINUE_EXECUTION (-1) -#define SEH_SEARCH ea_t(0) // EXCEPTION_CONTINUE_SEARCH (0) (alias of __finally) -#define SEH_HANDLE ea_t(1) // EXCEPTION_EXECUTE_HANDLER (1) - void clear(void) - { - try_handler_t::clear(); - filter.clear(); - seh_code = SEH_CONTINUE; - } -}; -DECLARE_TYPE_AS_MOVABLE(seh_t); - -//---------------------------------------------------------------------------- -// catch() {} statement -struct catch_t : public try_handler_t -{ - sval_t obj; // fpreg relative displacement to the exception object. -1 if unknown. - sval_t type_id; // the type caught by this catch. -1 means "catch(...)" -#define CATCH_ID_ALL sval_t(-1) // catch(...) -#define CATCH_ID_CLEANUP sval_t(-2) // a cleanup handler invoked if exception occures - - catch_t() : obj(-1), type_id(-1) {} -}; -DECLARE_TYPE_AS_MOVABLE(catch_t); -typedef qvector<catch_t> catchvec_t; - -//---------------------------------------------------------------------------- -class tryblk_t : public rangevec_t // block guarded by try/__try {...} statements -{ -#ifndef SWIG - char reserve[qmax(sizeof(catchvec_t), sizeof(seh_t))]; // seh_t or catchvec_t -#endif - uchar cb; // size of tryblk_t - uchar kind; // one of the following kinds -#define TB_NONE 0 // empty -#define TB_SEH 1 // MS SEH __try/__except/__finally -#define TB_CPP 2 // C++ language try/catch - -public: - uchar level; // nesting level, calculated by get_tryblks() - - // C++ try/catch block (TB_CPP) - catchvec_t &cpp() { return *(( catchvec_t *)reserve); } - const catchvec_t &cpp() const { return *((const catchvec_t *)reserve); } - - // SEH __except/__finally case (TB_SEH) - seh_t &seh() { return *(( seh_t *)reserve); } - const seh_t &seh() const { return *((const seh_t *)reserve); } - - tryblk_t() : rangevec_t(), cb(sizeof(*this)), kind(TB_NONE), level(0) { reserve[0] = '\0'; } - ~tryblk_t() { clear(); } - tryblk_t(const tryblk_t &r) : rangevec_t(), kind(TB_NONE) { *this = r; } - uchar get_kind(void) const { return kind; } - bool empty(void) const { return kind == TB_NONE; } - bool is_seh(void) const { return kind == TB_SEH; } - bool is_cpp(void) const { return kind == TB_CPP; } - - //------------------------------------------------------------------------- - tryblk_t &operator=(const tryblk_t &r) - { - if ( this != &r ) // don't copy yourself - { - if ( kind != TB_NONE ) - clear(); - kind = r.kind; - level = r.level; - rangevec_t::operator=(r); - - if ( kind == TB_SEH ) - new (reserve) seh_t(r.seh()); - else if ( kind == TB_CPP ) - new (reserve) catchvec_t(r.cpp()); - } - return *this; - } - - //------------------------------------------------------------------------- - void clear(void) - { - if ( kind == TB_CPP ) - cpp().~catchvec_t(); - else if ( kind == TB_SEH ) - seh().~seh_t(); - kind = TB_NONE; - } - - //------------------------------------------------------------------------- - seh_t &set_seh(void) - { - if ( kind != TB_SEH ) - { - clear(); - new (reserve) seh_t; - kind = TB_SEH; - } - else - { - seh().clear(); - } - return seh(); - } - - //------------------------------------------------------------------------- - catchvec_t &set_cpp(void) - { - if ( kind != TB_CPP ) - { - clear(); - new (reserve) catchvec_t; - kind = TB_CPP; - } - else - { - cpp().clear(); - } - return cpp(); - } -}; -DECLARE_TYPE_AS_MOVABLE(tryblk_t); -typedef qvector<tryblk_t> tryblks_t; - -///------------------------------------------------------------------------- -/// Retrieve try block information from the specified address range. -/// Try blocks are sorted by starting address and their nest levels calculated. -/// \param tbv output buffer; may be NULL -/// \param range address range to change -/// \return number of found try blocks - -idaman size_t ida_export get_tryblks(tryblks_t *tbv, const range_t &range); - -/// Delete try block information in the specified range. -/// \param range the range to be cleared - -idaman void ida_export del_tryblks(const range_t &range); - - -/// Add one try block information. -/// \param tb try block to add. -/// \return error code; 0 means good - -idaman int ida_export add_tryblk(const tryblk_t &tb); - -/// \defgroup TBERR_ Try block handling error codes -//@{ -#define TBERR_OK 0 ///< ok -#define TBERR_START 1 ///< bad start address -#define TBERR_END 2 ///< bad end address -#define TBERR_ORDER 3 ///< bad address order -#define TBERR_EMPTY 4 ///< empty try block -#define TBERR_KIND 5 ///< illegal try block kind -#define TBERR_NO_CATCHES 6 ///< no catch blocks at all -#define TBERR_INTERSECT 7 ///< range would intersect inner tryblk -//@} - -/// Find the start address of the system eh region including the argument. -/// \param ea search address -/// \return start address of surrounding tryblk, otherwise BADADDR - -idaman ea_t ida_export find_syseh(ea_t ea); - - -#endif // TRYBLKS_HPP diff --git a/idasdk75/include/typeinf.hpp b/idasdk75/include/typeinf.hpp deleted file mode 100644 index 3eb21f0..0000000 --- a/idasdk75/include/typeinf.hpp +++ /dev/null @@ -1,4356 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * Type Information. - * - */ - -#ifndef _TYPEINF_HPP -#define _TYPEINF_HPP -#include <idp.hpp> -#include <name.hpp> - -/*! \file typeinf.hpp - - \brief Describes the type information records in IDA. - - The recommended way of using type info is to use the ::tinfo_t class. - The type information is internally kept as an array of bytes terminated by 0. - - Items in brackets [] are optional and sometimes are omitted. - ::type_t... means a sequence of ::type_t bytes which defines a type. - - \note to work with the types of instructions or data in the database, - use get_tinfo()/set_tinfo() and similar functions. -*/ - -/// byte sequence used to describe a type in IDA (see \ref tf) -typedef uchar type_t; -/// pascal-like string: dt length, characters -typedef uchar p_string; -/// several ::p_string's -typedef uchar p_list; - -struct til_t; // type information library -class lexer_t; // lexical analyzer -class argloc_t; // argument location -class tinfo_t; // type info object - -struct func_type_data_t; - -//------------------------------------------------------------------------ -#define RESERVED_BYTE 0xFF ///< multifunctional purpose -//------------------------------------------------------------------------ -/// \defgroup tf Type flags -/// Here we describe the byte arrays used to describe type information -//@{ - -/// \defgroup tf_mask Masks -//@{ -const type_t TYPE_BASE_MASK = 0x0F; ///< the low 4 bits define the basic type -const type_t TYPE_FLAGS_MASK = 0x30; ///< type flags - they have different - ///< meaning depending on the basic type -const type_t TYPE_MODIF_MASK = 0xC0; ///< modifiers. - ///< - for ::BT_ARRAY see \ref tf_array - ///< - ::BT_VOID can have them ONLY in 'void *' - -const type_t TYPE_FULL_MASK = (TYPE_BASE_MASK | TYPE_FLAGS_MASK); ///< basic type with type flags -//@} - -/*! \defgroup tf_unk Basic type: unknown & void - ::BT_UNK and ::BT_VOID with non-zero type flags can be used in function - (and struct) declarations to describe the function arguments or structure - fields if only their size is known. They may be used in ida to describe - the user input. - - For struct used also as 'single-field-alignment-suffix' - [__declspec(align(x))] with ::TYPE_MODIF_MASK == ::TYPE_FULL_MASK. -*/ -//@{ -const type_t BT_UNK = 0x00; ///< unknown -const type_t BT_VOID = 0x01; ///< void -const type_t BTMT_SIZE0 = 0x00; ///< ::BT_VOID - normal void; ::BT_UNK - don't use -const type_t BTMT_SIZE12 = 0x10; ///< size = 1 byte if ::BT_VOID; 2 if ::BT_UNK -const type_t BTMT_SIZE48 = 0x20; ///< size = 4 bytes if ::BT_VOID; 8 if ::BT_UNK -const type_t BTMT_SIZE128 = 0x30; ///< size = 16 bytes if ::BT_VOID; unknown if ::BT_UNK - ///< (IN struct alignment - see below) -//@} - -/// \defgroup tf_int Basic type: integer -//@{ -const type_t BT_INT8 = 0x02; ///< __int8 -const type_t BT_INT16 = 0x03; ///< __int16 -const type_t BT_INT32 = 0x04; ///< __int32 -const type_t BT_INT64 = 0x05; ///< __int64 -const type_t BT_INT128 = 0x06; ///< __int128 (for alpha & future use) -const type_t BT_INT = 0x07; ///< natural int. (size provided by idp module) -const type_t BTMT_UNKSIGN = 0x00; ///< unknown signedness -const type_t BTMT_SIGNED = 0x10; ///< signed -const type_t BTMT_USIGNED = 0x20; ///< unsigned -const type_t BTMT_UNSIGNED = BTMT_USIGNED; -const type_t BTMT_CHAR = 0x30; ///< specify char or segment register - ///< - ::BT_INT8 - char - ///< - ::BT_INT - segment register - ///< - other BT_INT... - don't use -//@} - -/// \defgroup tf_bool Basic type: bool -//@{ -const type_t BT_BOOL = 0x08; ///< bool -const type_t BTMT_DEFBOOL = 0x00; ///< size is model specific or unknown(?) -const type_t BTMT_BOOL1 = 0x10; ///< size 1byte -const type_t BTMT_BOOL2 = 0x20; ///< size 2bytes - !inf_is_64bit() -const type_t BTMT_BOOL8 = 0x20; ///< size 8bytes - inf_is_64bit() -const type_t BTMT_BOOL4 = 0x30; ///< size 4bytes -//@} - -/// \defgroup tf_float Basic type: float -//@{ -const type_t BT_FLOAT = 0x09; ///< float -const type_t BTMT_FLOAT = 0x00; ///< float (4 bytes) -const type_t BTMT_DOUBLE = 0x10; ///< double (8 bytes) -const type_t BTMT_LNGDBL = 0x20; ///< long double (compiler specific) -const type_t BTMT_SPECFLT = 0x30; ///< float (variable size). - ///< if \ph{use_tbyte()} then use \ph{tbyte_size}, - ///< otherwise 2 bytes -//@} - -/// \defgroup tf_last_basic Basic type: last -//@{ -const type_t _BT_LAST_BASIC = BT_FLOAT; ///< the last basic type, - ///< all basic types may be followed by - ///< [tah-typeattrs] -//@} - -/*! \defgroup tf_ptr Derived type: pointer - Pointers to undeclared yet ::BT_COMPLEX types are prohibited -*/ -//@{ -const type_t BT_PTR = 0x0A; ///< pointer. - ///< has the following format: - ///< [db sizeof(ptr)]; [tah-typeattrs]; type_t... -const type_t BTMT_DEFPTR = 0x00; ///< default for model -const type_t BTMT_NEAR = 0x10; ///< near -const type_t BTMT_FAR = 0x20; ///< far -const type_t BTMT_CLOSURE = 0x30; ///< closure. - ///< - if ptr to ::BT_FUNC - __closure. - ///< in this case next byte MUST be - ///< #RESERVED_BYTE, and after it ::BT_FUNC - ///< - else the next byte contains sizeof(ptr) - ///< allowed values are 1 - \varmem{ph,processor_t,max_ptr_size} - ///< - if value is bigger than \varmem{ph,processor_t,max_ptr_size}, - ///< based_ptr_name_and_size() is called to - ///< find out the typeinfo -//@} - -/*! \defgroup tf_array Derived type: array - For ::BT_ARRAY, the BTMT_... flags must be equivalent to the BTMT_... flags of its elements -*/ -//@{ -const type_t BT_ARRAY = 0x0B; ///< array -const type_t BTMT_NONBASED = 0x10; ///< \code - /// if set - /// array base==0 - /// format: dt num_elem; [tah-typeattrs]; type_t... - /// if num_elem==0 then the array size is unknown - /// else - /// format: da num_elem, base; [tah-typeattrs]; type_t... \endcode - /// used only for serialization -const type_t BTMT_ARRESERV = 0x20; ///< reserved bit -//@} - -/*! \defgroup tf_func Derived type: function - Ellipsis is not taken into account in the number of parameters - The return type cannot be ::BT_ARRAY or ::BT_FUNC. -*/ -//@{ -const type_t BT_FUNC = 0x0C; ///< function. - ///< format: <pre> - /// optional: ::CM_CC_SPOILED | num_of_spoiled_regs - /// if num_of_spoiled_reg == BFA_FUNC_MARKER: - /// ::bfa_byte - /// if (bfa_byte & BFA_FUNC_EXT_FORMAT) != 0 - /// ::fti_bits (only low bits: FTI_SPOILED,...,FTI_VIRTUAL) - /// num_of_spoiled_reg times: spoiled reg info (see extract_spoiledreg) - /// else - /// bfa_byte is function attribute byte (see \ref BFA_...) - /// else: - /// num_of_spoiled_reg times: spoiled reg info (see extract_spoiledreg) - /// ::cm_t ... calling convention and memory model - /// [tah-typeattrs]; - /// ::type_t ... return type; - /// [serialized argloc_t of returned value (if ::CM_CC_SPECIAL{PE} && !return void); - /// if !::CM_CC_VOIDARG: - /// dt N (N=number of parameters) - /// if ( N == 0 ) - /// if ::CM_CC_ELLIPSIS or ::CM_CC_SPECIALE - /// func(...) - /// else - /// parameters are unknown - /// else - /// N records: - /// ::type_t ... (i.e. type of each parameter) - /// [serialized argloc_t (if ::CM_CC_SPECIAL{PE})] (i.e. place of each parameter) - /// [#FAH_BYTE + de( \ref funcarg_t::flags )] </pre> - -const type_t BTMT_DEFCALL = 0x00; ///< call method - default for model or unknown -const type_t BTMT_NEARCALL = 0x10; ///< function returns by retn -const type_t BTMT_FARCALL = 0x20; ///< function returns by retf -const type_t BTMT_INTCALL = 0x30; ///< function returns by iret - ///< in this case cc MUST be 'unknown' -//@} - -/// \defgroup tf_complex Derived type: complex -//@{ -const type_t BT_COMPLEX = 0x0D; ///< struct/union/enum/typedef. - ///< format: <pre> - /// [dt N (N=field count) if !::BTMT_TYPEDEF] - /// if N == 0: - /// p_string name (unnamed types have names "anon_...") - /// [sdacl-typeattrs]; - /// else, for struct & union: - /// if N == 0x7FFE // Support for high (i.e., > 4095) members count - /// N = deserialize_de() - /// ALPOW = N & 0x7 - /// MCNT = N >> 3 - /// if MCNT == 0 - /// empty struct - /// if ALPOW == 0 - /// ALIGN = get_default_align() - /// else - /// ALIGN = (1 << (ALPOW - 1)) - /// [sdacl-typeattrs]; - /// else, for enums: - /// if N == 0x7FFE // Support for high enum entries count. - /// N = deserialize_de() - /// [tah-typeattrs]; </pre> - /// -const type_t BTMT_STRUCT = 0x00; ///< struct: - ///< MCNT records: type_t; [sdacl-typeattrs]; -const type_t BTMT_UNION = 0x10; ///< union: - ///< MCNT records: type_t... -const type_t BTMT_ENUM = 0x20; ///< enum: - ///< next byte bte_t (see below) - ///< N records: de delta(s) - ///< OR - ///< blocks (see below) -const type_t BTMT_TYPEDEF = 0x30; ///< named reference - ///< always p_string name - -const type_t BT_BITFIELD = 0x0E; ///< bitfield (only in struct) - ///< ['bitmasked' enum see below] - ///< next byte is dt - ///< ((size in bits << 1) | (unsigned ? 1 : 0)) -const type_t BTMT_BFLDI8 = 0x00; ///< __int8 -const type_t BTMT_BFLDI16 = 0x10; ///< __int16 -const type_t BTMT_BFLDI32 = 0x20; ///< __int32 -const type_t BTMT_BFLDI64 = 0x30; ///< __int64 -//@} - -const type_t BT_RESERVED = 0x0F; ///< RESERVED - - -//------------------------------------------------------------------------ -/*! \defgroup tf_modifiers Type modifiers - "const volatile" types are forbidden -*/ -//@{ -const type_t BTM_CONST = 0x40; ///< const -const type_t BTM_VOLATILE = 0x80; ///< volatile -//@} - -//------------------------------------------------------------------------ -/// \defgroup tf_enum Special enum definitions -//@{ -typedef uchar bte_t; ///< Enum type flags - -const bte_t BTE_SIZE_MASK = 0x07; ///< storage size. - ///< - if == 0 then inf_get_cc_size_e() - ///< - else 1 << (n -1) = 1,2,4...64 -const bte_t BTE_RESERVED = 0x08; ///< must be 0, in order to distinguish - ///< from a tah-byte -const bte_t BTE_BITFIELD = 0x10; ///< 'subarrays'. In this case ANY record - ///< has the following format: - ///< - 'de' mask (has name) - ///< - 'dt' cnt - ///< - cnt records of 'de' values - ///< (cnt CAN be 0) - ///< \note delta for ALL subsegment is ONE -const bte_t BTE_OUT_MASK = 0x60; ///< output style mask -const bte_t BTE_HEX = 0x00; ///< hex -const bte_t BTE_CHAR = 0x20; ///< char or hex -const bte_t BTE_SDEC = 0x40; ///< signed decimal -const bte_t BTE_UDEC = 0x60; ///< unsigned decimal -const bte_t BTE_ALWAYS = 0x80; ///< this bit MUST be present -//@} - -/// \defgroup tf_conv_segreg Convenience definitions: segment register -//@{ -const type_t BT_SEGREG = (BT_INT | BTMT_CHAR); ///< segment register -//@} - -/// \defgroup tf_conv_unk Convenience definitions: unknown types -//@{ -const type_t BT_UNK_BYTE = (BT_VOID | BTMT_SIZE12); ///< 1 byte -const type_t BT_UNK_WORD = (BT_UNK | BTMT_SIZE12); ///< 2 bytes -const type_t BT_UNK_DWORD = (BT_VOID | BTMT_SIZE48); ///< 4 bytes -const type_t BT_UNK_QWORD = (BT_UNK | BTMT_SIZE48); ///< 8 bytes -const type_t BT_UNK_OWORD = (BT_VOID | BTMT_SIZE128); ///< 16 bytes -const type_t BT_UNKNOWN = (BT_UNK | BTMT_SIZE128); ///< unknown size - for parameters -//@} - -//------------------------------------------------------------------------ -/// \defgroup tf_shortcuts Convenience definitions: shortcuts -//@{ -const type_t BTF_BYTE = BT_UNK_BYTE; ///< byte -const type_t BTF_UNK = BT_UNKNOWN; ///< unknown -const type_t BTF_VOID = BT_VOID | BTMT_SIZE0; ///< void - -const type_t BTF_INT8 = BT_INT8 | BTMT_SIGNED; ///< signed byte -const type_t BTF_CHAR = BT_INT8 | BTMT_CHAR; ///< signed char -const type_t BTF_UCHAR = BT_INT8 | BTMT_USIGNED; ///< unsigned char -const type_t BTF_UINT8 = BT_INT8 | BTMT_USIGNED; ///< unsigned byte - -const type_t BTF_INT16 = BT_INT16 | BTMT_SIGNED; ///< signed short -const type_t BTF_UINT16 = BT_INT16 | BTMT_USIGNED; ///< unsigned short - -const type_t BTF_INT32 = BT_INT32 | BTMT_SIGNED; ///< signed int -const type_t BTF_UINT32 = BT_INT32 | BTMT_USIGNED; ///< unsigned int - -const type_t BTF_INT64 = BT_INT64 | BTMT_SIGNED; ///< signed long -const type_t BTF_UINT64 = BT_INT64 | BTMT_USIGNED; ///< unsigned long - -const type_t BTF_INT128 = BT_INT128 | BTMT_SIGNED; ///< signed 128-bit value -const type_t BTF_UINT128 = BT_INT128 | BTMT_USIGNED; ///< unsigned 128-bit value - -const type_t BTF_INT = BT_INT | BTMT_UNKSIGN; ///< int, unknown signedness -const type_t BTF_UINT = BT_INT | BTMT_USIGNED; ///< unsigned int -const type_t BTF_SINT = BT_INT | BTMT_SIGNED; ///< singed int - -const type_t BTF_BOOL = BT_BOOL; ///< boolean - -const type_t BTF_FLOAT = BT_FLOAT | BTMT_FLOAT; ///< float -const type_t BTF_DOUBLE = BT_FLOAT | BTMT_DOUBLE; ///< double -const type_t BTF_LDOUBLE = BT_FLOAT | BTMT_LNGDBL; ///< long double -const type_t BTF_TBYTE = BT_FLOAT | BTMT_SPECFLT; ///< see ::BTMT_SPECFLT - -const type_t BTF_STRUCT = BT_COMPLEX | BTMT_STRUCT; ///< struct -const type_t BTF_UNION = BT_COMPLEX | BTMT_UNION; ///< union -const type_t BTF_ENUM = BT_COMPLEX | BTMT_ENUM; ///< enum -const type_t BTF_TYPEDEF = BT_COMPLEX | BTMT_TYPEDEF; ///< typedef -//@} - -//@} tf - -//------------------------------------------------------------------------ -// convenience functions: - -inline THREAD_SAFE bool is_type_const(type_t t) { return (t & BTM_CONST) != 0; } ///< See ::BTM_CONST -inline THREAD_SAFE bool is_type_volatile(type_t t) { return (t & BTM_VOLATILE) != 0; } ///< See ::BTM_VOLATILE - -inline THREAD_SAFE type_t get_base_type(type_t t) { return (t & TYPE_BASE_MASK); } ///< Get get basic type bits (::TYPE_BASE_MASK) -inline THREAD_SAFE type_t get_type_flags(type_t t) { return (t & TYPE_FLAGS_MASK); } ///< Get type flags (::TYPE_FLAGS_MASK) -inline THREAD_SAFE type_t get_full_type(type_t t) { return (t & TYPE_FULL_MASK); } ///< Get basic type bits + type flags (::TYPE_FULL_MASK) - -/// Is the type_t the last byte of type declaration? -/// (there are no additional bytes after a basic type, see ::_BT_LAST_BASIC) -inline THREAD_SAFE bool is_typeid_last(type_t t) { return(get_base_type(t) <= _BT_LAST_BASIC); } - -/// Identifies an unknown or void type with a known size (see \ref tf_unk) -inline THREAD_SAFE bool is_type_partial(type_t t) { return(get_base_type(t) <= BT_VOID) && get_type_flags(t) != 0; } - -inline THREAD_SAFE bool is_type_void(type_t t) { return(get_full_type(t) == BTF_VOID); } ///< See ::BTF_VOID -inline THREAD_SAFE bool is_type_unknown(type_t t) { return(get_full_type(t) == BT_UNKNOWN); } ///< See ::BT_UNKNOWN - -inline THREAD_SAFE bool is_type_ptr(type_t t) { return(get_base_type(t) == BT_PTR); } ///< See ::BT_PTR -inline THREAD_SAFE bool is_type_complex(type_t t) { return(get_base_type(t) == BT_COMPLEX); } ///< See ::BT_COMPLEX -inline THREAD_SAFE bool is_type_func(type_t t) { return(get_base_type(t) == BT_FUNC); } ///< See ::BT_FUNC -inline THREAD_SAFE bool is_type_array(type_t t) { return(get_base_type(t) == BT_ARRAY); } ///< See ::BT_ARRAY - -inline THREAD_SAFE bool is_type_typedef(type_t t) { return(get_full_type(t) == BTF_TYPEDEF); } ///< See ::BTF_TYPEDEF -inline THREAD_SAFE bool is_type_sue(type_t t) { return is_type_complex(t) && !is_type_typedef(t); } ///< Is the type a struct/union/enum? -inline THREAD_SAFE bool is_type_struct(type_t t) { return(get_full_type(t) == BTF_STRUCT); } ///< See ::BTF_STRUCT -inline THREAD_SAFE bool is_type_union(type_t t) { return(get_full_type(t) == BTF_UNION); } ///< See ::BTF_UNION -inline THREAD_SAFE bool is_type_struni(type_t t) { return(is_type_struct(t) || is_type_union(t)); } ///< Is the type a struct or union? -inline THREAD_SAFE bool is_type_enum(type_t t) { return(get_full_type(t) == BTF_ENUM); } ///< See ::BTF_ENUM - -inline THREAD_SAFE bool is_type_bitfld(type_t t) { return(get_base_type(t) == BT_BITFIELD); } ///< See ::BT_BITFIELD - - -/// Does the type_t specify one of the basic types in \ref tf_int? -inline THREAD_SAFE bool is_type_int(type_t bt) { bt = get_base_type(bt); return bt >= BT_INT8 && bt <= BT_INT; } - -/// Does the type specify a 128-bit value? (signed or unsigned, see \ref tf_int) -inline THREAD_SAFE bool is_type_int128(type_t t) -{ - return get_full_type(t) == (BT_INT128|BTMT_UNKSIGN) - || get_full_type(t) == (BT_INT128|BTMT_SIGNED); -} - -/// Does the type specify a 64-bit value? (signed or unsigned, see \ref tf_int) -inline THREAD_SAFE bool is_type_int64(type_t t) -{ - return get_full_type(t) == (BT_INT64|BTMT_UNKSIGN) - || get_full_type(t) == (BT_INT64|BTMT_SIGNED); -} - -/// Does the type specify a 32-bit value? (signed or unsigned, see \ref tf_int) -inline THREAD_SAFE bool is_type_int32(type_t t) -{ - return get_full_type(t) == (BT_INT32|BTMT_UNKSIGN) - || get_full_type(t) == (BT_INT32|BTMT_SIGNED); -} - -/// Does the type specify a 16-bit value? (signed or unsigned, see \ref tf_int) -inline THREAD_SAFE bool is_type_int16(type_t t) -{ - return get_full_type(t) == (BT_INT16|BTMT_UNKSIGN) - || get_full_type(t) == (BT_INT16|BTMT_SIGNED); -} - -/// Does the type specify a char value? (signed or unsigned, see \ref tf_int) -inline THREAD_SAFE bool is_type_char(type_t t) // chars are signed by default(?) -{ - return get_full_type(t) == (BT_INT8|BTMT_CHAR) - || get_full_type(t) == (BT_INT8|BTMT_SIGNED); -} - -/// Is the type a pointer, array, or function type? -inline THREAD_SAFE bool is_type_paf(type_t t) -{ - t = get_base_type(t); - return t >= BT_PTR && t <= BT_FUNC; -} - -/// Is the type a pointer or array type? -inline THREAD_SAFE bool is_type_ptr_or_array(type_t t) { t = get_base_type(t); return t == BT_PTR || t == BT_ARRAY; } -/// Is the type a floating point type? -inline THREAD_SAFE bool is_type_floating(type_t t) { return get_base_type(t) == BT_FLOAT; } // any floating type -/// Is the type an integral type (char/short/int/long/bool)? -inline THREAD_SAFE bool is_type_integral(type_t t) { return get_full_type(t) > BT_VOID && get_base_type(t) <= BT_BOOL; } -/// Is the type an extended integral type? (integral or enum) -inline THREAD_SAFE bool is_type_ext_integral(type_t t) { return is_type_integral(t) || is_type_enum(t); } -/// Is the type an arithmetic type? (floating or integral) -inline THREAD_SAFE bool is_type_arithmetic(type_t t) { return get_full_type(t) > BT_VOID && get_base_type(t) <= BT_FLOAT; } -/// Is the type an extended arithmetic type? (arithmetic or enum) -inline THREAD_SAFE bool is_type_ext_arithmetic(type_t t) { return is_type_arithmetic(t) || is_type_enum(t); } - -inline THREAD_SAFE bool is_type_uint(type_t t) { return get_full_type(t) == BTF_UINT; } ///< See ::BTF_UINT -inline THREAD_SAFE bool is_type_uchar(type_t t) { return get_full_type(t) == BTF_UCHAR; } ///< See ::BTF_UCHAR -inline THREAD_SAFE bool is_type_uint16(type_t t) { return get_full_type(t) == BTF_UINT16; } ///< See ::BTF_UINT16 -inline THREAD_SAFE bool is_type_uint32(type_t t) { return get_full_type(t) == BTF_UINT32; } ///< See ::BTF_UINT32 -inline THREAD_SAFE bool is_type_uint64(type_t t) { return get_full_type(t) == BTF_UINT64; } ///< See ::BTF_UINT64 -inline THREAD_SAFE bool is_type_uint128(type_t t) { return get_full_type(t) == BTF_UINT128; } ///< See ::BTF_UINT128 -inline THREAD_SAFE bool is_type_ldouble(type_t t) { return get_full_type(t) == BTF_LDOUBLE; } ///< See ::BTF_LDOUBLE -inline THREAD_SAFE bool is_type_double(type_t t) { return get_full_type(t) == BTF_DOUBLE; } ///< See ::BTF_DOUBLE -inline THREAD_SAFE bool is_type_float(type_t t) { return get_full_type(t) == BTF_FLOAT; } ///< See ::BTF_FLOAT -inline THREAD_SAFE bool is_type_tbyte(type_t t) { return get_full_type(t) == BTF_TBYTE; } ///< See ::BTF_FLOAT -inline THREAD_SAFE bool is_type_bool(type_t t) { return get_base_type(t) == BT_BOOL; } ///< See ::BTF_BOOL - -/*! \defgroup tattr Type attributes - \ingroup tf - The type attributes start with the type attribute header byte (::TAH_BYTE), - followed by attribute bytes -*/ -//@{ -#define TAH_BYTE 0xFE ///< type attribute header byte -#define FAH_BYTE 0xFF ///< function argument attribute header byte - -#define MAX_DECL_ALIGN 0x000F - -/// \defgroup tattr_ext Extended type attributes -//@{ -#define TAH_HASATTRS 0x0010 ///< has extended attributes -//@} - -/// \defgroup tattr_udt Type attributes for udts -//@{ -#define TAUDT_UNALIGNED 0x0040 ///< struct: unaligned struct -#define TAUDT_MSSTRUCT 0x0020 ///< struct: gcc msstruct attribute -#define TAUDT_CPPOBJ 0x0080 ///< struct: a c++ object, not simple pod type -#define TAUDT_VFTABLE 0x0100 ///< struct: is virtual function table -//@} - -/// \defgroup tattr_field Type attributes for udt fields -//@{ -#define TAFLD_BASECLASS 0x0020 ///< field: do not include but inherit from the current field -#define TAFLD_UNALIGNED 0x0040 ///< field: unaligned field -#define TAFLD_VIRTBASE 0x0080 ///< field: virtual base (not supported yet) -#define TAFLD_VFTABLE 0x0100 ///< field: ptr to virtual function table -//@} - -/// \defgroup tattr_ptr Type attributes for pointers -//@{ -#define TAPTR_PTR32 0x0020 ///< ptr: __ptr32 -#define TAPTR_PTR64 0x0040 ///< ptr: __ptr64 -#define TAPTR_RESTRICT 0x0060 ///< ptr: __restrict -#define TAPTR_SHIFTED 0x0080 ///< ptr: __shifted(parent_struct, delta) -//@} - -/// \defgroup tattr_enum Type attributes for enums -//@{ -#define TAENUM_64BIT 0x0020 ///< enum: store 64-bit values -#define TAENUM_UNSIGNED 0x0040 ///< enum: unsigned -#define TAENUM_SIGNED 0x0080 ///< enum: signed -//@} - -#define TAH_ALL 0x01F0 ///< all defined bits - -//@} tattr - - -/// The TAH byte (type attribute header byte) denotes the start of type attributes. -/// (see "tah-typeattrs" in the type bit definitions) - -inline THREAD_SAFE bool is_tah_byte(type_t t) -{ - return t == TAH_BYTE; -} - - -/// Identify an sdacl byte. -/// The first sdacl byte has the following format: 11xx000x. -/// The sdacl bytes are appended to udt fields. They indicate the start of type -/// attributes (as the tah-bytes do). The sdacl bytes are used in the udt -/// headers instead of the tah-byte. This is done for compatibility with old -/// databases, they were already using sdacl bytes in udt headers and as udt -/// field postfixes. -/// (see "sdacl-typeattrs" in the type bit definitions) - -inline THREAD_SAFE bool is_sdacl_byte(type_t t) -{ - return ((t & ~TYPE_FLAGS_MASK) ^ TYPE_MODIF_MASK) <= BT_VOID; -} - -#ifndef SWIG -/// Compare two bytevecs with '<'. -/// v1 is considered less than v2 if either: -/// - v1.size() < v2.size() -/// - there is some i such that v1[i] < v2[i] - -inline THREAD_SAFE bool operator <(const bytevec_t &v1, const bytevec_t &v2) -{ - size_t n = qmin(v1.size(), v2.size()); - for ( size_t i=0; i < n; i++ ) - { - uchar k1 = v1[i]; - uchar k2 = v2[i]; - if ( k1 < k2 ) - return true; - if ( k1 > k2 ) - return false; - } - return v1.size() < v2.size(); -} -#endif - -/// \addtogroup tattr_ext Extended type attributes -//@{ -/// Extended type attributes. -struct type_attr_t -{ - qstring key; ///< one symbol keys are reserved to be used by the kernel - ///< the ones starting with an underscore are reserved too - bytevec_t value; ///< attribute bytes - bool operator < (const type_attr_t &r) const { return key < r.key; } - bool operator >= (const type_attr_t &r) const { return !(*this < r); } -}; -DECLARE_TYPE_AS_MOVABLE(type_attr_t); - -/// this vector must be sorted by keys -typedef qvector<type_attr_t> type_attrs_t; - -typedef int type_sign_t; ///< type signedness -const type_sign_t - no_sign = 0, ///< no sign, or unknown - type_signed = 1, ///< signed type - type_unsigned = 2; ///< unsigned type -//@} - -//--------------------------------------------------------------------------- -idaman bool ida_export append_argloc(qtype *out, const argloc_t &vloc); ///< Serialize argument location -idaman bool ida_export extract_argloc(argloc_t *vloc, const type_t **ptype, bool is_retval); ///< Deserialize argument location - -idaman const type_t *ida_export resolve_typedef(const til_t *til, const type_t *type); - -// low level functions to be used in predicate_t::should_display() -// in other places please use tinfo_t -inline bool is_restype_void(const til_t *til, const type_t *type) -{ - type = resolve_typedef(til, type); - return type != NULL && is_type_void(*type); -} - -inline bool is_restype_enum(const til_t *til, const type_t *type) -{ - type = resolve_typedef(til, type); - return type != NULL && is_type_enum(*type); -} - -inline bool is_restype_struni(const til_t *til, const type_t *type) -{ - type = resolve_typedef(til, type); - return type != NULL && is_type_struni(*type); -} - -inline bool is_restype_struct(const til_t *til, const type_t *type) -{ - type = resolve_typedef(til, type); - return type != NULL && is_type_struct(*type); -} - -// Get a base type for the specified size. -// This function prefers to return integer types -// \param size size in bytes; should be 1,2,4,8,16 or sizeof(floating point) -// \return BT_INT.. or BT_FLOAT... or BT_UNK - -idaman type_t ida_export get_scalar_bt(int size); - - -//------------------------------------------------------------------------ -/// Type Information Library -//------------------------------------------------------------------------ -struct til_t -{ - char *name; ///< short file name (without path and extension) - char *desc; ///< human readable til description - int nbases; ///< number of base tils - struct til_t **base; ///< tils that our til is based on - uint32 flags; ///< \ref TIL_ -/// \defgroup TIL_ Type info library property bits -/// used by til_t::flags -//@{ -#define TIL_ZIP 0x0001 ///< pack buckets using zip -#define TIL_MAC 0x0002 ///< til has macro table -#define TIL_ESI 0x0004 ///< extended sizeof info (short, long, longlong) -#define TIL_UNI 0x0008 ///< universal til for any compiler -#define TIL_ORD 0x0010 ///< type ordinal numbers are present -#define TIL_ALI 0x0020 ///< type aliases are present (this bit is used only on the disk) -#define TIL_MOD 0x0040 ///< til has been modified, should be saved -#define TIL_STM 0x0080 ///< til has extra streams -#define TIL_SLD 0x0100 ///< sizeof(long double) -//@} - /// Has the til been modified? (#TIL_MOD) - inline bool is_dirty(void) const { return (flags & TIL_MOD) != 0; } - /// Mark the til as modified (#TIL_MOD) - inline void set_dirty(void) { flags |= TIL_MOD; } - compiler_info_t cc; ///< information about the target compiler - struct til_bucket_t *syms; ///< symbols - struct til_bucket_t *types; ///< types - struct til_bucket_t *macros; ///< macros - int nrefs; ///< number of references to the til - int nstreams; ///< number of extra streams - struct til_stream_t **streams; ///< symbol stream storage - /// Constructor - til_t(void) - : name(nullptr), - desc(nullptr), - nbases(0), - base(nullptr), - flags(0), - syms(nullptr), - types(nullptr), - macros(nullptr), - nrefs(0), - nstreams(0), - streams(nullptr) - { - cc = {}; - } -}; - - -/// Initialize a til - -idaman til_t *ida_export new_til(const char *name, const char *desc); - - -/// Add multiple base tils. -/// \param[out] errbuf error message -/// \param ti target til -/// \param tildir directory where specified tils can be found. -/// NULL means all default til subdirectories. -/// \param bases comma separated list of til names -/// \param gen_events generate corresponding IDB events -/// \return one of \ref TIL_ADD_ - -idaman int ida_export add_base_tils(qstring *errbuf, til_t *ti, const char *tildir, const char *bases, bool gen_events); - -/// \defgroup TIL_ADD_ Add TIL result codes -/// returned by add_base_tils() -//@{ -#define TIL_ADD_FAILED 0 ///< see errbuf -#define TIL_ADD_OK 1 ///< some tils were added -#define TIL_ADD_ALREADY 2 ///< the base til was already added -//@} - - -/// Load til from a file. -/// Failure to load base tils are reported into 'errbuf'. They do not prevent -/// loading of the main til. -/// \param name filename of the til. If it's an absolute path, tildir is ignored. -/// - NB: the file extension is forced to .til -/// \param[out] errbuf error message -/// \param tildir directory where to load the til from. -/// NULL means default til subdirectories. -/// \return pointer to resulting til, NULL if failed and error message is in errbuf - -idaman til_t *ida_export load_til(const char *name, qstring *errbuf, const char *tildir=NULL); - - -/// Sort til (use after modifying it). -/// \return false if no memory or bad parameter - -idaman bool ida_export sort_til(til_t *ti); - - -/// Collect garbage in til. -/// Must be called before storing the til. -/// \return true if any memory was freed - -idaman bool ida_export compact_til(til_t *ti); - - -/// Store til to a file. -/// If the til contains garbage, it will be collected before storing the til. -/// Your plugin should call compact_til() before calling store_til(). -/// \param ti type library to store -/// \param tildir directory where to store the til. NULL means current directory. -/// \param name filename of the til. If it's an absolute path, tildir is ignored. -/// - NB: the file extension is forced to .til -/// \return success - -idaman bool ida_export store_til(til_t *ti, const char *tildir, const char *name); - - -/// Free memory allocated by til - -idaman void ida_export free_til(til_t *ti); - - -/// Get human-readable til description - -idaman til_t *ida_export load_til_header(const char *tildir, const char *name, qstring *errbuf); - - -//------------------------------------------------------------------------ -/// \defgroup CM_ CM -/// Calling convention & Model -//@{ - -/// \defgroup CM_ptr Default pointer size -//@{ -const cm_t CM_MASK = 0x03; -const cm_t CM_UNKNOWN = 0x00; ///< unknown -const cm_t CM_N8_F16 = 0x01; ///< if sizeof(int)<=2: near 1 byte, far 2 bytes -const cm_t CM_N64 = 0x01; ///< if sizeof(int)>2: near 8 bytes, far 8 bytes -const cm_t CM_N16_F32 = 0x02; ///< near 2 bytes, far 4 bytes -const cm_t CM_N32_F48 = 0x03; ///< near 4 bytes, far 6 bytes -//@} -/// \defgroup CM_M_ Model -//@{ -const cm_t CM_M_MASK = 0x0C; -const cm_t CM_M_NN = 0x00; ///< small: code=near, data=near (or unknown if CM_UNKNOWN) -const cm_t CM_M_FF = 0x04; ///< large: code=far, data=far -const cm_t CM_M_NF = 0x08; ///< compact: code=near, data=far -const cm_t CM_M_FN = 0x0C; ///< medium: code=far, data=near - -/// Does the given model specify far code?. -inline THREAD_SAFE bool is_code_far(cm_t cm) { return((cm & 4) != 0); } -/// Does the given model specify far data?. -inline THREAD_SAFE bool is_data_far(cm_t cm) { return((cm &= CM_M_MASK) && cm != CM_M_FN); } -//@} - -/// \defgroup CM_CC_ Calling convention -//@{ -const cm_t CM_CC_MASK = 0xF0; -const cm_t CM_CC_INVALID = 0x00; ///< this value is invalid -const cm_t CM_CC_UNKNOWN = 0x10; ///< unknown calling convention -const cm_t CM_CC_VOIDARG = 0x20; ///< function without arguments - ///< if has other cc and argnum == 0, - ///< represent as f() - unknown list -const cm_t CM_CC_CDECL = 0x30; ///< stack -const cm_t CM_CC_ELLIPSIS = 0x40; ///< cdecl + ellipsis -const cm_t CM_CC_STDCALL = 0x50; ///< stack, purged -const cm_t CM_CC_PASCAL = 0x60; ///< stack, purged, reverse order of args -const cm_t CM_CC_FASTCALL = 0x70; ///< stack, purged (x86), first args are in regs (compiler-dependent) -const cm_t CM_CC_THISCALL = 0x80; ///< stack, purged (x86), first arg is in reg (compiler-dependent) -const cm_t CM_CC_MANUAL = 0x90; ///< special case for compiler specific (not used) -const cm_t CM_CC_SPOILED = 0xA0; ///< This is NOT a cc! Mark of __spoil record - ///< the low nibble is count and after n {spoilreg_t} - ///< present real cm_t byte. if n == BFA_FUNC_MARKER, - ///< the next byte is the function attribute byte. -const cm_t CM_CC_RESERVE4 = 0xB0; -const cm_t CM_CC_RESERVE3 = 0xC0; -const cm_t CM_CC_SPECIALE = 0xD0; ///< ::CM_CC_SPECIAL with ellipsis -const cm_t CM_CC_SPECIALP = 0xE0; ///< Equal to ::CM_CC_SPECIAL, but with purged stack -const cm_t CM_CC_SPECIAL = 0xF0; ///< usercall: locations of all arguments - ///< and the return value are explicitly specified -//@} CM_CC_ - -//@} CM_ - -/*! \defgroup BFA_ Function attribute byte - \ingroup tf_func - Zero attribute byte is forbidden. -*/ -//@{ -const type_t BFA_NORET = 0x01; ///< __noreturn -const type_t BFA_PURE = 0x02; ///< __pure -const type_t BFA_HIGH = 0x04; ///< high level prototype (with possibly hidden args) -const type_t BFA_STATIC = 0x08; ///< static -const type_t BFA_VIRTUAL= 0x10; ///< virtual - -const cm_t BFA_FUNC_MARKER = 0x0F; ///< This is NOT a cc! (used internally as a marker) -const type_t BFA_FUNC_EXT_FORMAT = 0x80; ///< This is NOT a real attribute (used internally as marker for extended format) -//@} - -#ifndef SWIG -/// Helper to declare common ::argloc_t related functions -#define ARGLOC_HELPER_DEFINITIONS(decl) \ -decl void ida_export copy_argloc(argloc_t *dst, const argloc_t *src); \ -decl void ida_export cleanup_argloc(argloc_t *vloc);\ -decl int ida_export compare_arglocs(const argloc_t &a, const argloc_t &b); -#else -#define ARGLOC_HELPER_DEFINITIONS(decl) -#endif // SWIG -ARGLOC_HELPER_DEFINITIONS(idaman) - -/// \defgroup argloc Argument locations -/// \ingroup CM_ -//@{ - -/// Specifies the location type of a function argument - see \ref ALOC_ -typedef int argloc_type_t; -/// \defgroup ALOC_ Argument location types -//@{ -const argloc_type_t - ALOC_NONE = 0, ///< none - ALOC_STACK = 1, ///< stack offset - ALOC_DIST = 2, ///< distributed (scattered) - ALOC_REG1 = 3, ///< one register (and offset within it) - ALOC_REG2 = 4, ///< register pair - ALOC_RREL = 5, ///< register relative - ALOC_STATIC = 6, ///< global address - ALOC_CUSTOM = 7; ///< custom argloc (7 or higher) -//@} - -/// Register-relative argument location -struct rrel_t -{ - sval_t off; ///< displacement from the address pointed by the register - int reg; ///< register index (into \varmem{ph,processor_t,reg_names}) -}; - -class scattered_aloc_t; - -/// Description of a custom argloc. Custom arglocs can be added by plugins in order -/// to describe the locations unsupported by the ida kernel. -struct custloc_desc_t -{ - size_t cbsize; ///< size of this structure - const char *name; ///< name of the custom argloc type. must be unique - - /// Copy src into empty_dst - void (idaapi *copy)(argloc_t *empty_dst, const argloc_t &src); - - /// Clear contents of loc before it is modified (may be NULL) - void (idaapi *cleanup)(argloc_t *loc); - - /// May be NULL - bool (idaapi *verify)( - const argloc_t &loc, - int size, - const rangeset_t *gaps, - bool part_of_scattered); - - /// Lexical comparison of two arglocs - int (idaapi *compare)(const argloc_t &a, const argloc_t &b); - - /// Get textual description of the location (not the value at the location!) - size_t (idaapi *print)( - char *buf, - size_t bufsize, - const argloc_t &loc, - asize_t size, - int praloc_flags); // PRALOC_... - - /// Dereference the struct/union pointed by 'strloc': take member at offset 'off' - /// (or use the field name), improve member 'tif' if necessary - bool (idaapi *deref_field)( - argloc_t *out, - tinfo_t *tif, - const argloc_t &strloc, - const tinfo_t &struct_tif, - asize_t off, - const qstring &name); - - /// Dereference the array pointed by 'arrloc': take member number 'n' - /// (element size is 'elsize'), improve member 'tif' if necessary - bool (idaapi *deref_array)( - argloc_t *out, - tinfo_t *tif, - const argloc_t &arrloc, - const tinfo_t &array_tif, - asize_t n, - asize_t elsize); - - /// Dereference the pointer at 'loc': retrieve location of the pointed object, - /// improve 'tif' of the pointed object if necessary - bool (idaapi *deref_ptr)( - argloc_t *out, - tinfo_t *tif, - const argloc_t &ptrloc); - - /// Read the pointer at 'loc': retrieve value of a simple object. - /// the object value must fit value_u. - bool (idaapi *read_value)( - value_u *value, - const argloc_t &loc, - int size, - const tinfo_t &tif); - - /// Update value at 'loc'. if idcv is VT_LONG/VT_INT64/VT_FLOAT, the value - /// in native format is copied to 'scalar_value' for your convenience. otherwise - /// please use 'idcv' and not 'scalar_value'. - bool (idaapi *write_value)( - const argloc_t &loc, - const idc_value_t &idcv, - const value_u &scalar_value, - int size, - qstring *errbuf); - - /// Calc max natural string length at 'loc' in the debugged process memory - asize_t (idaapi *calc_string_length)( - const argloc_t &loc, - const tinfo_t &string_tif); - - /// Retrieve string at 'loc' from the debugged process memory, - /// returns quoted string value - bool (idaapi *get_string)( - qstring *out, - tinfo_t *elem_tif, - const argloc_t &loc, - const tinfo_t &string_tif, - size_t len); - - /// Retrieve size of array at 'loc' (number of elements) - asize_t (idaapi *guess_array_size)( - const argloc_t &loc, - const tinfo_t &array_tif); - - /// Retrieve type of the object at 'loc' - bool (idaapi *get_tinfo)( - tinfo_t *out, - const argloc_t &loc); - - /// Calculate the number of children for the given location. - /// (arrays, structs, ptrs may have children and therefore be expanded) - int (idaapi *calc_number_of_children)(const argloc_t &loc, const tinfo_t &tif); - - /// Get string containing a printable representation of the pointer at 'loc'. - /// Returns the number of characters printed. - /// May be NULL. - size_t (idaapi *print_ptr_value)( - char *buf, - size_t bufsize, - bool *is_valid_ptr, - const argloc_t &loc, - const tinfo_t &tif); -}; - - -/// Save a custom argloc -idaman int ida_export install_custom_argloc(const custloc_desc_t *custloc); -/// Delete the custom argloc at the given index -idaman bool ida_export remove_custom_argloc(int idx); -/// Retrieve the custom argloc at the given index -idaman const custloc_desc_t *ida_export retrieve_custom_argloc(int idx); - -/// Describes an argument location. -/// A typical argument is stored in one location, either a register or a stack slot. \n -/// However, some arguments can be stored in multiple locations, for example in a pair \n -/// of registers. In some really complex cases an argument can be located in multiple \n -/// registers and some stack slots. This class can describe all these cases. -class argloc_t // #argloc -{ -public: - typedef size_t biggest_t; - -private: - argloc_type_t type; - union - { - sval_t sval; // ::ALOC_STACK, ::ALOC_STATIC - uint32 reginfo; // ::ALOC_REG1, ::ALOC_REG2 - rrel_t *rrel; // ::ALOC_RREL - scattered_aloc_t *dist; // ::ALOC_DIST - void *custom; // ::ALOC_CUSTOM - biggest_t biggest; // to facilitate manipulation of this union - }; - ARGLOC_HELPER_DEFINITIONS(friend) - -public: - argloc_t(void) : type(ALOC_NONE), biggest(0) {} ///< Constructor - argloc_t(const argloc_t &r) : type(ALOC_NONE) { copy_argloc(this, &r); } ///< Constructor - ~argloc_t(void) { cleanup_argloc(this); } ///< Destructor - argloc_t &operator=(const argloc_t &r) { copy_argloc(this, &r); return *this; } ///< Constructor - DEFINE_MEMORY_ALLOCATION_FUNCS() - - /// Assign this == r and r == this - void swap(argloc_t &r) - { - biggest_t tmp = biggest; biggest = r.biggest; r.biggest = tmp; - argloc_type_t t = type; type = r.type; r.type = t; - } - - const char *dstr(void) const; - - argloc_type_t atype(void) const { return type; } ///< Get type (\ref ALOC_) - bool is_reg1(void) const { return type == ALOC_REG1; } ///< See ::ALOC_REG1 - bool is_reg2(void) const { return type == ALOC_REG2; } ///< See ::ALOC_REG2 - bool is_reg(void) const { return type == ALOC_REG1 || type == ALOC_REG2; } ///< is_reg1() || is_reg2() - bool is_rrel(void) const { return type == ALOC_RREL; } ///< See ::ALOC_RREL - bool is_ea(void) const { return type == ALOC_STATIC; } ///< See ::ALOC_STATIC - bool is_stkoff(void) const { return type == ALOC_STACK; } ///< See ::ALOC_STACK - bool is_scattered(void) const { return type == ALOC_DIST; } ///< See ::ALOC_DIST - inline bool has_reg() const; ///< TRUE if argloc has a register part - inline bool has_stkoff() const; ///< TRUE if argloc has a stack part - inline bool is_mixed_scattered() const; ///< mixed scattered: consists of register and stack parts - bool is_fragmented(void) const { return type == ALOC_DIST || type == ALOC_REG2; } ///< is_scattered() || is_reg2() - bool is_custom(void) const { return type >= ALOC_CUSTOM; } ///< See ::ALOC_CUSTOM - bool is_badloc(void) const { return type == ALOC_NONE; } ///< See ::ALOC_NONE - - /// Get the register info. - /// Use when atype() == ::ALOC_REG1 or ::ALOC_REG2 - int reg1(void) const { return uint16(reginfo); } - - /// Get offset from the beginning of the register in bytes. - /// Use when atype() == ::ALOC_REG1 - int regoff(void) const { return uint16(reginfo >> 16); } - - /// Get info for the second register. - /// Use when atype() == ::ALOC_REG2 - int reg2(void) const { return uint16(reginfo >> 16); } - - /// Get all register info. - /// Use when atype() == ::ALOC_REG1 or ::ALOC_REG2 - uint32 get_reginfo(void) const { return reginfo; } - - /// Get the stack offset. - /// Use if atype() == ::ALOC_STACK - sval_t stkoff(void) const { return sval; } - - /// Get the global address. - /// Use when atype() == ::ALOC_STATIC - ea_t get_ea(void) const { return sval; } - - /// Get scattered argument info. - /// Use when atype() == ::ALOC_DIST - scattered_aloc_t &scattered(void) { return *dist; } - const scattered_aloc_t &scattered(void) const { return *dist; } ///< copydoc scattered() - - /// Get register-relative info. - /// Use when atype() == ::ALOC_RREL - rrel_t &get_rrel(void) { return *rrel; } - const rrel_t &get_rrel(void) const { return *rrel; } ///< copydoc get_rrel() - - /// Get custom argloc info. - /// Use if atype() == ::ALOC_CUSTOM - void *get_custom(void) const { return custom; } - - /// Get largest element in internal union - biggest_t get_biggest(void) const { return biggest; } - - // be careful with these functions, they do not cleanup! - void _set_badloc(void) { type = ALOC_NONE; } ///< Use set_badloc() - void _set_reg1(int reg, int off=0) { type = ALOC_REG1; reginfo = reg | (off << 16); } ///< Use set_reg1() - void _set_reg2(int _reg1, int _reg2) { type = ALOC_REG2; reginfo = _reg1 | (_reg2 << 16); } ///< Use set_reg2() - void _set_stkoff(sval_t off) { type = ALOC_STACK; sval = off; } ///< Use set_stkoff() - void _set_ea(ea_t _ea) { type = ALOC_STATIC; sval = _ea; } ///< Use set_ea - /// Use consume_rrel() - bool _consume_rrel(rrel_t *p) //lint -sem(argloc_t::_consume_rrel, custodial(1)) - { - if ( p == NULL ) - return false; - type = ALOC_RREL; - rrel = p; - return true; - } - /// Use consume_scattered() - bool _consume_scattered(scattered_aloc_t *p) - { - if ( p == NULL ) - return false; - type = ALOC_DIST; - dist = p; - return true; - } - - /// Set custom argument location (careful - this function does not clean up!) - void _set_custom(argloc_type_t ct, void *pdata) { type = ct; custom = pdata; } - - /// Set biggest element in internal union (careful - this function does not clean up!) - void _set_biggest(argloc_type_t ct, biggest_t data) { type = ct; biggest = data; } - - /// Set register location - void set_reg1(int reg, int off=0) { cleanup_argloc(this); _set_reg1(reg, off); } - - /// Set secondary register location - void set_reg2(int _reg1, int _reg2) { cleanup_argloc(this); _set_reg2(_reg1, _reg2); } - - /// Set stack offset location - void set_stkoff(sval_t off) { cleanup_argloc(this); _set_stkoff(off); } - - /// Set static ea location - void set_ea(ea_t _ea) { cleanup_argloc(this); _set_ea(_ea); } - - /// Set register-relative location - can't be NULL - void consume_rrel(rrel_t *p) { cleanup_argloc(this); _consume_rrel(p); } - - /// Set distributed argument location - void consume_scattered(scattered_aloc_t *p) { cleanup_argloc(this); _consume_scattered(p); } - - /// Set to invalid location - void set_badloc(void) { cleanup_argloc(this); } - - /// Calculate offset that can be used to compare 2 similar arglocs - sval_t calc_offset(void) const - { - switch ( type ) - { - default: - case ALOC_NONE: - case ALOC_DIST: - case ALOC_REG2: - return -1; - case ALOC_RREL: - return rrel->off; - case ALOC_STACK: - case ALOC_STATIC: - return sval; - case ALOC_REG1: - return reg1(); - } - } - - /// Move the location to point 'delta' bytes further - bool advance(int delta) - { - switch ( type ) - { - case ALOC_REG1: - _set_reg1(reg1()+delta, regoff()); - break; - case ALOC_STACK: - case ALOC_STATIC: - sval += delta; - break; - case ALOC_RREL: - rrel->off += delta; - break; - default: - return false; - } - return true; - } - - /// Set register offset to justify it to the upper part of _SLOTSIZE - void justify_reg_high(size_t size, size_t _slotsize) - { - if ( is_reg1() ) - _set_reg1(reg1(), size < _slotsize ? _slotsize - size : 0); - } - - /// Set stack offset to right-justify it in _SLOTSIZE - void justify_stkoff_right(size_t size, size_t _slotsize) - { - if ( is_stkoff() ) - { - sval_t off = align_down(stkoff(), _slotsize); - if ( size < _slotsize ) - off += _slotsize - size; - _set_stkoff(off); - } - } - - DECLARE_COMPARISONS(argloc_t) - { - return compare_arglocs(*this, r); - } -}; -DECLARE_TYPE_AS_MOVABLE(argloc_t); -typedef qvector<argloc_t> arglocs_t; ///< vector of argument locations - -/// Subsection of an argument location -struct argpart_t : public argloc_t -{ - ushort off; ///< offset from the beginning of the argument - ushort size; ///< the number of bytes - DEFINE_MEMORY_ALLOCATION_FUNCS() - argpart_t(const argloc_t &a) : argloc_t(a), off(0xFFFF), size(0) {} ///< Constructor - argpart_t(void) : off(0xFFFF), size(0) {} ///< Constructor - argpart_t ©_from(const argloc_t &a) { *(argloc_t*)this = a; return *this; } - - /// Does this argpart have a valid offset? - bool bad_offset(void) const { return off == 0xFFFF; } - - /// Does this argpart have a valid size? - bool bad_size(void) const { return size == 0; } - - /// Compare two argparts, based on their offset - bool operator < (const argpart_t &r) const { return off < r.off; } - - /// Assign this = r and r = this - void swap(argpart_t &r) - { - argloc_t::swap(r); - qswap(off, r.off); - qswap(size, r.size); - } -}; -DECLARE_TYPE_AS_MOVABLE(argpart_t); -typedef qvector<argpart_t> argpartvec_t; - -/// Used to manage arguments that are described by multiple locations (also see ::ALOC_DIST) -class scattered_aloc_t : public argpartvec_t -{ -public: - DEFINE_MEMORY_ALLOCATION_FUNCS() -}; -DECLARE_TYPE_AS_MOVABLE(scattered_aloc_t); - - -/// Verify argloc_t. -/// \param size total size of the variable -/// \param gaps if not NULL, specifies gaps in structure definition. -/// these gaps should not map to any argloc, but everything else must be covered -/// \return 0 if ok, otherwise an interr code. - -idaman int ida_export verify_argloc(const argloc_t &vloc, int size, const rangeset_t *gaps); - - -/// Verify and optimize scattered argloc into simple form. -/// All new arglocs must be processed by this function. -/// \retval true success -/// \retval false the input argloc was illegal - -idaman bool ida_export optimize_argloc(argloc_t *vloc, int size, const rangeset_t *gaps); - - -/// Convert an argloc to human readable form - -idaman size_t ida_export print_argloc( - char *buf, - size_t bufsize, - const argloc_t &vloc, - int size=0, - int vflags=0); -#define PRALOC_VERIFY 0x01 ///< interr if illegal argloc -#define PRALOC_STKOFF 0x02 ///< print stack offsets - - -/// Visit all argument locations. The callback will not receive ::ALOC_DIST/::ALOC_REG2 types, -/// they will be converted into smaller argloc types (::ALOC_REG1 or other) -struct aloc_visitor_t -{ - virtual int idaapi visit_location(argloc_t &v, int off, int size) = 0; - DEFINE_VIRTUAL_DTOR(aloc_visitor_t) -}; - -/// Compress larger argloc types and initiate the aloc visitor -idaman int ida_export for_all_arglocs(aloc_visitor_t &vv, argloc_t &vloc, int size, int off=0); - -/// Same as ::aloc_visitor_t, but may not modify the argloc -struct const_aloc_visitor_t -{ - virtual int idaapi visit_location(const argloc_t &v, int off, int size) = 0; - DEFINE_VIRTUAL_DTOR(const_aloc_visitor_t) -}; - -/// See for_all_arglocs() -inline int idaapi for_all_const_arglocs(const_aloc_visitor_t &vv, const argloc_t &vloc, int size, int off=0) -{ - return for_all_arglocs(*(aloc_visitor_t*)(&vv), - CONST_CAST(argloc_t&)(vloc), - size, - off); -} - -//-------------------------------------------------------------------------- -/// \defgroup C_PC_ Standard C-language models for x86 -/// \ingroup CM_ -//@{ -const cm_t C_PC_TINY = (CM_N16_F32 | CM_M_NN); -const cm_t C_PC_SMALL = (CM_N16_F32 | CM_M_NN); -const cm_t C_PC_COMPACT = (CM_N16_F32 | CM_M_NF); -const cm_t C_PC_MEDIUM = (CM_N16_F32 | CM_M_FN); -const cm_t C_PC_LARGE = (CM_N16_F32 | CM_M_FF); -const cm_t C_PC_HUGE = (CM_N16_F32 | CM_M_FF); -const cm_t C_PC_FLAT = (CM_N32_F48 | CM_M_NN); -//@} - - -/// Get the calling convention - -inline THREAD_SAFE cm_t get_cc(cm_t cm) { return(cm & CM_CC_MASK); } - - -/// Does the calling convention specify argument locations explicitly? - -inline THREAD_SAFE bool is_user_cc(cm_t cm) -{ - cm_t cc = get_cc(cm); - return cc >= CM_CC_SPECIALE; -} - - -/// Does the calling convention use ellipsis? - -inline THREAD_SAFE bool is_vararg_cc(cm_t cm) -{ - cm_t cc = get_cc(cm); - return cc == CM_CC_ELLIPSIS || cc == CM_CC_SPECIALE; -} - - -/// Does the calling convention clean the stack arguments upon return?. -/// \note this function is valid only for x86 code - -inline THREAD_SAFE bool is_purging_cc(cm_t cm) -{ - cm_t cc = get_cc(cm); - return cc == CM_CC_STDCALL || cc == CM_CC_PASCAL || cc == CM_CC_SPECIALP || cc == CM_CC_FASTCALL || cc == CM_CC_THISCALL; -} - -//-------------------------------------------------------------------------- -/// Function argument passing: how GP & FP registers cooperate with each other -enum argreg_policy_t -{ - ARGREGS_POLICY_UNDEFINED, - ARGREGS_GP_ONLY, ///< GP registers used for all arguments - ARGREGS_INDEPENDENT, ///< FP/GP registers used separately (like gcc64) - ARGREGS_BY_SLOTS, ///< fixed FP/GP register per each slot (like vc64) - ARGREGS_FP_CONSUME_GP, ///< FP register also consumes one or more GP regs but not vice versa (aix ppc ABI) - ARGREGS_MIPS_O32, ///< MIPS ABI o32 -}; - -//@} argloc - -class callregs_t; - -/// Register allocation calling convention. -/// (allocation policy, arrays of GP and FP registers) -class callregs_t -{ - bool set_inds(int *p_ind1, int *p_ind2, int ind) const - { - if ( ind == -1 ) - return false; - *p_ind1 = ind; - *p_ind2 = by_slots() ? ind : -1; - return true; - } - - // copy -1-terminated array to a vector - static void set_regarray(intvec_t *regvec, const int *regarray) - { - regvec->clear(); - if ( regarray != NULL ) - while ( *regarray != -1 ) - regvec->push_back(*regarray++); - } - void calc_nregs() - { - nregs = gpregs.size(); - if ( policy == ARGREGS_INDEPENDENT || policy == ARGREGS_FP_CONSUME_GP ) - nregs += int(fpregs.size()); - } - -public: - argreg_policy_t policy; ///< argument policy - int nregs; ///< max number of registers that can be used in a call - intvec_t gpregs; ///< array of gp registers - intvec_t fpregs; ///< array of fp registers - - /// Constructor - callregs_t(): policy(ARGREGS_POLICY_UNDEFINED), nregs(0) {} - - /// Constructor - initialize with the given request (see init_regs()) - callregs_t(cm_t cc): policy(ARGREGS_POLICY_UNDEFINED), nregs(0) - { - init_regs(cc); - } - - /// Init policy & registers for given CC. - void init_regs(cm_t cc) - { - processor_t::get_cc_regs(this, get_cc(cc)); - } - - // policy-specific options - bool by_slots() const { return policy == ARGREGS_BY_SLOTS; } - - /// Init policy & registers (arrays are -1-terminated) - void set(argreg_policy_t _policy, const int *gprs, const int *fprs) - { - policy = _policy; - set_regarray(&gpregs, gprs); - set_regarray(&fpregs, fprs); - calc_nregs(); - } - - /// Set policy and registers to invalid values - void reset() - { - set(ARGREGS_POLICY_UNDEFINED, NULL, NULL); - } - - /// Get max number of registers may be used in a function call. - static int regcount(cm_t cc) - { - callregs_t vr(cc); return vr.nregs; - } - - // return index of register, -1 else - static int findreg(const intvec_t ®s, int r) - { - intvec_t::const_iterator p = regs.find(r); - return p == regs.end() ? -1 : (p-regs.begin()); - } - - /// Get register indexes within GP/FP arrays. - /// (-1 -> is not present in the corresponding array) - bool reginds(int *gp_ind, int *fp_ind, int r) const - { - return findregs(gp_ind, fp_ind, r, gpregs, fpregs); - } - -protected: - /// Search for register r in gprs and fprs. - /// If found, fill gp_ind and fp_ind based on #policy - bool findregs(int *gp_ind, int *fp_ind, int r, const intvec_t &gprs, const intvec_t &fprs) const - { - *gp_ind = *fp_ind = -1; - return set_inds(gp_ind, fp_ind, findreg(gprs, r)) - || set_inds(fp_ind, gp_ind, findreg(fprs, r)); - } -}; - -//-------------------------------------------------------------------------- -/// \defgroup CC -/// Target compiler -//@{ - -/// \defgroup COMP_ Compiler IDs -//@{ -const comp_t COMP_MASK = 0x0F; -const comp_t COMP_UNK = 0x00; ///< Unknown -const comp_t COMP_MS = 0x01; ///< Visual C++ -const comp_t COMP_BC = 0x02; ///< Borland C++ -const comp_t COMP_WATCOM = 0x03; ///< Watcom C++ -//const comp_t COMP_ = 0x04 -//const comp_t COMP_ = 0x05 -const comp_t COMP_GNU = 0x06; ///< GNU C++ -const comp_t COMP_VISAGE = 0x07; ///< Visual Age C++ -const comp_t COMP_BP = 0x08; ///< Delphi -//---- -const comp_t COMP_UNSURE = 0x80; ///< uncertain compiler id -//@} - - -/// \defgroup CC_funcs Functions: work with compiler IDs -//@{ - -/// Get compiler bits - -inline THREAD_SAFE comp_t get_comp(comp_t comp) { return(comp & COMP_MASK); } - - -/// Get full compiler name - -idaman const char *ida_export get_compiler_name(comp_t id); - - -/// Get abbreviated compiler name - -idaman const char *ida_export get_compiler_abbr(comp_t id); - -/// Collection of compiler descriptions -typedef qvector<comp_t> compvec_t; - - -/// Get names of all built-in compilers - -idaman void ida_export get_compilers(compvec_t *ids, qstrvec_t *names, qstrvec_t *abbrs); - - -/// See ::COMP_UNSURE - -inline THREAD_SAFE comp_t is_comp_unsure(comp_t comp) { return (comp & COMP_UNSURE); } - - -/// Get compiler specified by \varmem{inf,idainfo,cc} - -inline comp_t default_compiler(void) { return get_comp(inf_get_cc_id()); } - - -/// Is the target compiler ::COMP_GNU? - -inline bool is_gcc(void) { return default_compiler() == COMP_GNU; } - - -/// Is the target compiler 32 bit gcc? - -inline bool is_gcc32(void) { return is_gcc() && !inf_is_64bit(); } - - -/// Is the target compiler 64 bit gcc? - -inline bool is_gcc64(void) { return is_gcc() && inf_is_64bit(); } - - -/// Should use the struct/union layout as done by gcc? - -inline bool gcc_layout(void) { return is_gcc() || (inf_get_abibits() & ABI_GCC_LAYOUT) != 0; } - - -/// Change current compiler. -/// \param cc compiler to switch to -/// \param flags \ref SETCOMP_ -/// \param abiname ABI name -/// \return success - -idaman bool ida_export set_compiler( - const compiler_info_t &cc, - int flags, - const char *abiname=NULL); - -/// \defgroup SETCOMP_ Set compiler flags -//@{ -#define SETCOMP_OVERRIDE 0x0001 ///< may override old compiler info -#define SETCOMP_ONLY_ID 0x0002 ///< cc has only 'id' field - ///< the rest will be set to defaults - ///< corresponding to the program bitness -#define SETCOMP_ONLY_ABI 0x0004 ///< ignore cc field complete, use only abiname -#define SETCOMP_BY_USER 0x0008 ///< invoked by user, cannot be replaced by module/loader -//@} - - -/// Set the compiler id (see \ref COMP_) - -inline bool idaapi set_compiler_id(comp_t id, const char *abiname=NULL) -{ - compiler_info_t cc; - cc.id = id; - return set_compiler(cc, SETCOMP_ONLY_ID, abiname); -} - -/// Set abi name (see \ref COMP_) - -inline bool idaapi set_abi_name(const char *abiname, bool user_level = false) -{ - compiler_info_t cc; - cc.id = 0; - int flags = SETCOMP_ONLY_ABI | (user_level ? SETCOMP_BY_USER : 0); - return set_compiler(cc, flags, abiname); -} - -/// Get ABI name. -/// \return length of the name (>=0) - -idaman ssize_t ida_export get_abi_name(qstring *out); - - -/// Add/remove/check ABI option -/// General form of full abi name: abiname-opt1-opt2-... or -opt1-opt2-... -/// \param abi_opts - ABI options to add/remove in form opt1-opt2-... -/// \param user_level - initiated by user if TRUE (==SETCOMP_BY_USER) -/// \return success -idaman bool ida_export append_abi_opts(const char *abi_opts, bool user_level = false); -idaman bool ida_export remove_abi_opts(const char *abi_opts, bool user_level = false); - -/// \param compstr - compiler description in form <abbr>:<abiname> -/// \param user_level - initiated by user if TRUE -/// \return success -idaman bool ida_export set_compiler_string(const char *compstr, bool user_level); - -//@} CC_funcs -//@} CC - -//-------------------------------------------------------------------------- -const size_t BADSIZE = size_t(-1); ///< bad type size -#define MAX_FUNC_ARGS 256 ///< max number of function arguments - -//-------------------------------------------------------------------------- -/// abstractness of declaration (see h2ti()) -enum abs_t { abs_unk, abs_no, abs_yes }; -enum sclass_t ///< storage class -{ - sc_unk, ///< unknown - sc_type, ///< typedef - sc_ext, ///< extern - sc_stat, ///< static - sc_reg, ///< register - sc_auto, ///< auto - sc_friend, ///< friend - sc_virt ///< virtual -}; - -/// \defgroup parse_tinfo Type parsing -/// Format/Parse/Print type information -//@{ - -/// \defgroup HTI_ Type formatting flags -//@{ -#define HTI_CPP 0x00000001 ///< C++ mode (not implemented) -#define HTI_INT 0x00000002 ///< debug: print internal representation of types -#define HTI_EXT 0x00000004 ///< debug: print external representation of types -#define HTI_LEX 0x00000008 ///< debug: print tokens -#define HTI_UNP 0x00000010 ///< debug: check the result by unpacking it -#define HTI_TST 0x00000020 ///< test mode: discard the result -#define HTI_FIL 0x00000040 ///< "input" is file name, - ///< otherwise "input" contains a C declaration -#define HTI_MAC 0x00000080 ///< define macros from the base tils -#define HTI_NWR 0x00000100 ///< no warning messages -#define HTI_NER 0x00000200 ///< ignore all errors but display them -#define HTI_DCL 0x00000400 ///< don't complain about redeclarations -#define HTI_NDC 0x00000800 ///< don't decorate names -#define HTI_PAK 0x00007000 ///< explicit structure pack value (#pragma pack) -#define HTI_PAK_SHIFT 12 ///< shift for #HTI_PAK. This field should - ///< be used if you want to remember an explicit - ///< pack value for each structure/union type. - ///< See #HTI_PAK... definitions -#define HTI_PAKDEF 0x00000000 ///< default pack value -#define HTI_PAK1 0x00001000 ///< #pragma pack(1) -#define HTI_PAK2 0x00002000 ///< #pragma pack(2) -#define HTI_PAK4 0x00003000 ///< #pragma pack(4) -#define HTI_PAK8 0x00004000 ///< #pragma pack(8) -#define HTI_PAK16 0x00005000 ///< #pragma pack(16) - -#define HTI_HIGH 0x00008000 ///< assume high level prototypes - ///< (with hidden args, etc) -#define HTI_LOWER 0x00010000 ///< lower the function prototypes -#define HTI_RAWARGS 0x00020000 ///< leave argument names unchanged (do not remove underscores) -//@} - - -/// This callback will be called for each type/variable declaration. -/// \param name var/func/type name -/// \param tif type info -/// \param cmt main comment -/// \param value symbol value -/// \param cb_data data passed to callback -/// \retval T_CBBRKDEF the type declaration won't be saved in the til - -typedef int idaapi h2ti_type_cb( - const char *name, - const tinfo_t &tif, - const char *cmt, - const uint64 *value, - void *cb_data); - - -/// Specify a printing callback when parsing types. -/// See h2ti() and parse_decls(). -typedef AS_PRINTF(1, 2) int printer_t(const char *format, ...); - - -/// Convert declarations to type_t*. -/// This is a low level function - use parse_decls() or parse_decl() -/// \param ti type info library -/// \param lx input lexer. may be NULL. always destroyed by h2ti() -/// \param input file name or C declaration -/// \param flags combination of \ref HTI_ -/// \param type_cb callback - for each type -/// \param var_cb callback - for each var -/// \param print_cb may pass msg() here -/// \param _cb_data data passed to callbacks -/// \param _isabs the expected abstracness of the type declaration(s) -/// \return number of errors (they are displayed using print_cb). zero means ok - -idaman int ida_export h2ti( - til_t *ti, - lexer_t *lx, - const char *input, - int flags=HTI_HIGH, - h2ti_type_cb *type_cb=NULL, - h2ti_type_cb *var_cb=NULL, - printer_t *print_cb=NULL, - void *_cb_data=NULL, - abs_t _isabs=abs_unk); - - -/// Parse ONE declaration. -/// If the input string contains more than one declaration, the first complete -/// type declaration (#PT_TYP) or the last variable declaration (#PT_VAR) will be used. -/// \note name & tif may be empty after the call! -/// \param[out] tif type info -/// \param[out] out declared name -/// \param til type library to use. may be NULL -/// \param decl C declaration to parse -/// \param flags combination of \ref PT_ bits -/// \retval true ok -/// \retval false declaration is bad, the error message is displayed if !PT_SIL - -idaman bool ida_export parse_decl( - tinfo_t *tif, - qstring *out, - til_t *til, - const char *decl, - int flags); - -/// \defgroup PT_ Type parsing flags -//@{ -#define PT_SIL 0x0001 ///< silent, no messages -#define PT_NDC 0x0002 ///< don't decorate names -#define PT_TYP 0x0004 ///< return declared type information -#define PT_VAR 0x0008 ///< return declared object information -#define PT_PACKMASK 0x0070 ///< mask for pack alignment values -#define PT_HIGH 0x0080 ///< assume high level prototypes - ///< (with hidden args, etc) -#define PT_LOWER 0x0100 ///< lower the function prototypes -#define PT_REPLACE 0x0200 ///< replace the old type (used in idc) -#define PT_RAWARGS 0x0400 ///< leave argument names unchanged (do not remove underscores) -//@} - - -/// Convert \ref PT_ to \ref HTI_. -/// Type parsing flags lesser than 0x10 don't have stable meaning and will be ignored -/// (more on these flags can be seen in idc.idc) - -inline THREAD_SAFE int convert_pt_flags_to_hti(int pt_flags) -{ - return ((pt_flags >> 4) & 0x1f) << HTI_PAK_SHIFT; -} - - -/// Parse many declarations and store them in a til. -/// If there are any errors, they will be printed using 'printer'. -/// This function uses default include path and predefined macros from the -/// database settings. It always uses the #HTI_DCL bit. -/// \param til type library to store the result -/// \param input input string or file name (see hti_flags) -/// \param printer function to output error messages (use msg or NULL or your own callback) -/// \param hti_flags combination of \ref HTI_ -/// \return number of errors, 0 means ok. - -idaman int ida_export parse_decls( - til_t *til, - const char *input, - printer_t *printer, - int hti_flags); - - -/// Get type declaration for the specified address. -/// \param out output buffer -/// \param ea address -/// \param prtype_flags combination of \ref PRTYPE_ -/// \return success - -idaman bool ida_export print_type(qstring *out, ea_t ea, int prtype_flags); - - -/// \defgroup PRTYPE_ Type printing flags -//@{ -#define PRTYPE_1LINE 0x0000 ///< print to one line -#define PRTYPE_MULTI 0x0001 ///< print to many lines -#define PRTYPE_TYPE 0x0002 ///< print type declaration (not variable declaration) -#define PRTYPE_PRAGMA 0x0004 ///< print pragmas for alignment -#define PRTYPE_SEMI 0x0008 ///< append ; to the end -#define PRTYPE_CPP 0x0010 ///< use c++ name (only for print_type()) -#define PRTYPE_DEF 0x0020 ///< tinfo_t: print definition, if available -#define PRTYPE_NOARGS 0x0040 ///< tinfo_t: do not print function argument names -#define PRTYPE_NOARRS 0x0080 ///< tinfo_t: print arguments with #FAI_ARRAY as pointers -#define PRTYPE_NORES 0x0100 ///< tinfo_t: never resolve types (meaningful with PRTYPE_DEF) -#define PRTYPE_RESTORE 0x0200 ///< tinfo_t: print restored types for #FAI_ARRAY and #FAI_STRUCT -#define PRTYPE_NOREGEX 0x0400 ///< do not apply regular expressions to beautify name -#define PRTYPE_COLORED 0x0800 ///< add color tag COLOR_SYMBOL for any parentheses, commas and colons -//@} - -//@} parse_tinfo - - -/// \defgroup named_types Named types -/// functions to work with named types -//@{ - - -/// Get named typeinfo. -/// The returned pointers are pointers to static storage. \n -/// They are valid until free_til(), set_named_type(), del_named_type(), \n -/// rename_named_type(), set_numbered_type(), del_numbered_type(), \n -/// and idb structure/enum manipulation (in other words, until ::til_t is changed). -/// \param ti pointer to type information library -/// \param name name of type -/// \param ntf_flags combination of \ref NTF_ -/// \param type ptr to ptr to output buffer for the type info -/// \param fields ptr to ptr to the field/args names. may be NULL -/// \param cmt ptr to ptr to the main comment. may be NULL -/// \param fieldcmts ptr to ptr to the field/args comments. may be NULL -/// \param sclass ptr to storage class -/// \param value ptr to symbol value. for types, ptr to the ordinal number -/// \retval 0 can't find the named type (or name==NULL) -/// \retval 1 ok, the buffers are filled with information (if not NULL) -/// \retval 2 ok, found it in a base til - -idaman int ida_export get_named_type( - const til_t *ti, - const char *name, - int ntf_flags, - const type_t **type=NULL, - const p_list **fields=NULL, - const char **cmt=NULL, - const p_list **fieldcmts=NULL, - sclass_t *sclass=NULL, - uint32 *value=NULL); - -/// \defgroup NTF_ Flags for named types -//@{ -#define NTF_TYPE 0x0001 ///< type name -#define NTF_SYMU 0x0008 ///< symbol, name is unmangled ('func') -#define NTF_SYMM 0x0000 ///< symbol, name is mangled ('_func') - ///< only one of #NTF_TYPE and #NTF_SYMU, #NTF_SYMM can be used -#define NTF_NOBASE 0x0002 ///< don't inspect base tils (for get_named_type) -#define NTF_REPLACE 0x0004 ///< replace original type (for set_named_type) -#define NTF_UMANGLED 0x0008 ///< name is unmangled (don't use this flag) -#define NTF_NOCUR 0x0020 ///< don't inspect current til file (for get_named_type) -#define NTF_64BIT 0x0040 ///< value is 64bit -#define NTF_FIXNAME 0x0080 ///< force-validate the name of the type when setting - ///< (set_named_type, set_numbered_type only) -#define NTF_IDBENC 0x0100 ///< the name is given in the IDB encoding; - ///< non-ASCII bytes will be decoded accordingly - ///< (set_named_type, set_numbered_type only) -#define NTF_CHKSYNC 0x0200 ///< check that synchronization to IDB passed OK - ///< (set_numbered_type, set_named_type) -//@} - - -/// See get_named_type() above. -/// \note If the value in the 'ti' library is 32-bit, it will -/// be sign-extended before being stored in the 'value' pointer. - -inline int idaapi get_named_type64( - const til_t *ti, - const char *name, - int ntf_flags, - const type_t **type=NULL, - const p_list **fields=NULL, - const char **cmt=NULL, - const p_list **fieldcmts=NULL, - sclass_t *sclass=NULL, - uint64 *value=NULL) -{ - return get_named_type(ti, name, ntf_flags | NTF_64BIT, - type, fields, cmt, fieldcmts, sclass, (uint32 *)value); -} - - -/// Error codes for save_tinfo functions: -enum tinfo_code_t -{ - TERR_OK = 0, ///< ok - TERR_SAVE = -1, ///< failed to save - TERR_SERIALIZE = -2, ///< failed to serialize - TERR_WRONGNAME = -3, ///< name is not acceptable - TERR_BADSYNC = -4, ///< failed to synchronize with IDB -}; - - -/// Delete information about a symbol. -/// \param ti type library -/// \param name name of symbol -/// \param ntf_flags combination of \ref NTF_ -/// \return success - -idaman bool ida_export del_named_type(til_t *ti, const char *name, int ntf_flags); - - -/// Enumerate types. -/// Returns mangled names. -/// Never returns anonymous types. To include it, enumerate types by ordinals. - -idaman const char *ida_export first_named_type(const til_t *ti, int ntf_flags); - - -/// \copydoc first_named_type() - -idaman const char *ida_export next_named_type(const til_t *ti, const char *name, int ntf_flags); - - -/// Copy a named type from one til to another. -/// This function will copy the specified type and all dependent types -/// from the source type library to the destination library. -/// \param dsttil Destination til. It must have orginal types enabled -/// \param srctil Source til. -/// \param name name of the type to copy -/// \return ordinal number of the copied type. 0 means error - -idaman uint32 ida_export copy_named_type( - til_t *dsttil, - const til_t *srctil, - const char *name); - - -/// Decorate/undecorate a C symbol name. -/// \param out output buffer -/// \param name name of symbol -/// \param mangle true-mangle, false-unmangle -/// \param cc calling convention -/// \param type name type (NULL-unknown) -/// \return success - -idaman bool ida_export decorate_name( - qstring *out, - const char *name, - bool mangle, - cm_t cc=CM_CC_UNKNOWN, - const tinfo_t *type = NULL); - - -/// Generic function for decorate_name() (may be used in IDP modules) - -idaman bool ida_export gen_decorate_name( - qstring *out, - const char *name, - bool mangle, - cm_t cc, - const tinfo_t *type); - - -/// Get C or C++ form of the name. -/// \param out output buffer -/// \param name original (mangled or decorated) name -/// \param type name type if known, otherwise NULL -/// \param ccn_flags one of \ref CCN_ - -idaman ssize_t ida_export calc_c_cpp_name( - qstring *out, - const char *name, - const tinfo_t *type, - int ccn_flags); -/// \defgroup CCN_ C/C++ naming flags -//@{ -#define CCN_C 0x00 // prepare C name -#define CCN_CPP 0x01 // prepare C++ name -//@} - -//@} named_types - -//-------------------------------------------------------------------------- -/// \defgroup numbered_types Numbered types -/// Functions to work with numbered (ordinal) types. -/// Numbered types may be named or anonymous. -/// They are referenced by their ordinal number. Access to them is faster because -/// there is no need to resolve their names. Also, they can stay anonymous -/// and be aliased. They can be used only in the local type library -/// created by IDA (in idati). -//@{ - -/// Enable the use of numbered types in til. -/// Currently it is impossible to disable numbered types once they are enabled - -idaman bool ida_export enable_numbered_types(til_t *ti, bool enable); - - -/// Retrieve a type by its ordinal number - -idaman bool ida_export get_numbered_type( - const til_t *ti, - uint32 ordinal, - const type_t **type=NULL, - const p_list **fields=NULL, - const char **cmt=NULL, - const p_list **fieldcmts=NULL, - sclass_t *sclass=NULL); - - -/// Allocate a range of ordinal numbers for new types. -/// \param ti type library -/// \param qty number of ordinals to allocate -/// \return the first ordinal. 0 means failure. - -idaman uint32 ida_export alloc_type_ordinals(til_t *ti, int qty); - - -/// \call2{alloc_type_ordinals,ti,1} - -inline uint32 alloc_type_ordinal(til_t *ti) { return alloc_type_ordinals(ti, 1); } - - -/// Get number of allocated ordinals. -/// \return uint32(-1) if failed - -idaman uint32 ida_export get_ordinal_qty(const til_t *ti); - - -/// Store a type in the til. -/// 'name' may be NULL for anonymous types. -/// The specified ordinal must be free (no other type is using it). -/// For ntf_flags, only #NTF_REPLACE is consulted. - -idaman tinfo_code_t ida_export set_numbered_type( - til_t *ti, - uint32 ordinal, - int ntf_flags, - const char *name, - const type_t *type, - const p_list *fields=NULL, - const char *cmt=NULL, - const p_list *fldcmts=NULL, - const sclass_t *sclass=NULL); - - -/// Delete a numbered type - -idaman bool ida_export del_numbered_type(til_t *ti, uint32 ordinal); - - -/// Create a type alias. -/// Redirects all references to source type to the destination type. -/// This is equivalent to instantaneous replacement all reference to srctype by dsttype. - -idaman bool ida_export set_type_alias(til_t *ti, uint32 src_ordinal, uint32 dst_ordinal); - - -/// Find the final alias destination. -/// If the ordinal has not been aliased, return the specified ordinal itself -/// If failed, returns 0. - -idaman uint32 ida_export get_alias_target(const til_t *ti, uint32 ordinal); - - -/// Get type ordinal by its name - -inline int32 get_type_ordinal(const til_t *ti, const char *name) -{ - uint32 ordinal = 0; - get_named_type(ti, name, NTF_TYPE|NTF_NOBASE, NULL, NULL, NULL, NULL, NULL, &ordinal); - return ordinal; -} - -/// Get type name (if exists) by its ordinal. -/// If the type is anonymous, returns "". If failed, returns NULL - -idaman const char *ida_export get_numbered_type_name(const til_t *ti, uint32 ordinal); - - -/// Create anonymous name for numbered type. This name can be used -/// to reference a numbered type by its ordinal -/// Ordinal names have the following format: '#' + set_de(ord) -/// Returns: -1 if error, otherwise the name length - -idaman ssize_t ida_export create_numbered_type_name(qstring *buf, int32 ord); - - -/// Check if the name is an ordinal name. -/// Ordinal names have the following format: '#' + set_de(ord) - -idaman bool ida_export is_ordinal_name(const char *name, uint32 *ord=NULL); - - -/// Get ordinal number of an idb type (struct/enum). -/// The 'type' parameter is used only to determine the kind of the type (struct or enum) -/// Use this function to find out the correspondence between idb types and til types - -idaman int ida_export get_ordinal_from_idb_type(const char *name, const type_t *type); - - -/// Is the specified idb type automatically synchronized? - -inline bool idaapi is_autosync(const char *name, const type_t *type) -{ - return get_ordinal_from_idb_type(name, type) != -1; -} -inline bool idaapi is_autosync(const char *name, const tinfo_t &tif); ///< copydoc is_autosync(const char*, const type_t *) - - -/// Generate a name like $hex_numbers based on the field types and names - -idaman void ida_export build_anon_type_name( - qstring *buf, - const type_t *type, - const p_list *fields); - - -const uint32 BADORD = uint32(-1); ///< invalid type ordinal - - -/// Compact numbered types to get rid of empty slots. -/// \param ti type library to compact -/// \param min_ord minimal ordinal number to start to compact. lower -/// ordinals are not modified -/// \param p_ordmap the resulting mapping -/// (for example, the new ordinal of min_ord will be in ordmap[0]) -/// \param flags reserved -/// \return number of freed type slots - -idaman int ida_export compact_numbered_types( - til_t *ti, - uint32 min_ord=0, - intvec_t *p_ordmap=NULL, - int flags=0); - -//@} numbered_types - -//-------------------------------------------------------------------------- -// ALIGNMENT - -/// Get default alignment for structure fields. -/// \return one of 1,2,4,8,... - -inline size_t get_default_align(void) { return inf_get_cc_defalign(); } - - -/// Get alignment delta for the a structure field. -/// \param cur_tot_size the structure size calculated so far -/// \param elem_size size of the current field. -/// the whole structure should be calculated -/// \param algn the structure alignment (0,1,2,4,8...) - -inline THREAD_SAFE void align_size(size_t &cur_tot_size, size_t elem_size, size_t algn) -{ - size_t al = elem_size; - if ( algn != 0 && algn < al ) - al = algn; - cur_tot_size = align_up(cur_tot_size, al); -} - -/// Dereference a pointer. -/// \param[out] ptr_ea in/out parameter -/// - in: address of the pointer -/// - out: the pointed address -/// \param tif type of the pointer -/// \param[out] closure_obj closure object (not used yet) -/// \return success - -idaman bool ida_export deref_ptr( - ea_t *ptr_ea, - const tinfo_t &tif, - ea_t *closure_obj=NULL); - - -/// Remove pointer of a type. -/// (i.e. convert "char *" into "char"). -/// Optionally remove the "lp" (or similar) prefix of the input name. -/// If the input type is not a pointer, then fail. - -idaman bool ida_export remove_tinfo_pointer(tinfo_t *tif, const char **pname, const til_t *til=NULL); - -/// Copy a named type from til to idb. -/// \param til type library -/// \param idx the position of the new type in the list of types (structures or enums). -/// -1 means at the end of the list -/// \param name the type name -/// \param flags combination of \ref IMPTYPE_ -/// \return #BADNODE on error - -idaman tid_t ida_export import_type(const til_t *til, int idx, const char *name, int flags=0); - -/// \defgroup IMPTYPE_ Import type flags -/// passed as 'flags' parameter to import_type() -//@{ -#define IMPTYPE_VERBOSE 0x0001 ///< more verbose output (dialog boxes may appear) -#define IMPTYPE_OVERRIDE 0x0002 ///< override existing type -#define IMPTYPE_LOCAL 0x0004 ///< the type is local, the struct/enum won't be marked as til type. - ///< there is no need to specify this bit if til==idati, - ///< the kernel will set it automatically -//@} - -/// Load a til file. -/// \param name til name -/// \param flags combination of \ref ADDTIL_F -/// \return one of \ref ADDTIL_R - -idaman int ida_export add_til(const char *name, int flags); - -/// \defgroup ADDTIL_F Load TIL flags -/// passed as 'flags' parameter to add_til() -//@{ -#define ADDTIL_DEFAULT 0x0000 ///< default behavior -#define ADDTIL_INCOMP 0x0001 ///< load incompatible tils -#define ADDTIL_SILENT 0x0002 ///< do not ask any questions -//@} - -/// \defgroup ADDTIL_R Load TIL result codes -/// return values for add_til() -//@{ -#define ADDTIL_FAILED 0 ///< something bad, the warning is displayed -#define ADDTIL_OK 1 ///< ok, til is loaded -#define ADDTIL_COMP 2 ///< ok, but til is not compatible with the current compiler -#define ADDTIL_ABORTED 3 ///< til was not loaded (incompatible til rejected by user) -//@} - - -/// Unload a til file - -idaman bool ida_export del_til(const char *name); - - -/// Apply the specified named type to the address. -/// \param ea linear address -/// \param name the type name, e.g. "FILE" -/// \return success - -idaman bool ida_export apply_named_type(ea_t ea, const char *name); - - -/// Apply the specified type to the specified address. -/// This function sets the type and tries to convert the item at the specified -/// address to conform the type. -/// \param ea linear address -/// \param tif type string in internal format -/// \param flags combination of \ref TINFO_ -/// \returns success - -idaman bool ida_export apply_tinfo( - ea_t ea, - const tinfo_t &tif, - uint32 flags); - -/// \defgroup TINFO_ Apply tinfo flags -/// passed as 'flags' parameter to apply_tinfo() -//@{ -#define TINFO_GUESSED 0x0000 ///< this is a guessed type -#define TINFO_DEFINITE 0x0001 ///< this is a definite type -#define TINFO_DELAYFUNC 0x0002 ///< if type is a function and no function exists at ea, - ///< schedule its creation and argument renaming to auto-analysis - ///< otherwise try to create it immediately -#define TINFO_STRICT 0x0004 ///< never convert given type to another one before applying -//@} - - -/// Apply the specified type to the address. -/// This function parses the declaration and calls apply_tinfo() -/// \param til type library -/// \param ea linear address -/// \param decl type declaration in C form -/// \param flags flags to pass to apply_tinfo (#TINFO_DEFINITE is always passed) -/// \return success - -idaman bool ida_export apply_cdecl(til_t *til, ea_t ea, const char *decl, int flags=0); - - -/// Apply the type of the called function to the calling instruction. -/// This function will append parameter comments and rename the local -/// variables of the calling function. It also stores information about -/// the instructions that initialize call arguments in the database. -/// Use get_arg_addrs() to retrieve it if necessary. Alternatively it is -/// possible to hook to processor_t::arg_addrs_ready event. -/// \param caller linear address of the calling instruction. -/// must belong to a function. -/// \param tif type info -/// \return success - -idaman bool ida_export apply_callee_tinfo(ea_t caller, const tinfo_t &tif); - - -/// Retrieve argument initialization addresses. -/// This function retrieves information about argument addresses. -/// This information is stored in the database by apply_callee_tinfo(). -/// \param out linear addresses of the instructions that load call arguments -/// \param caller address of the call instruction -/// \return success - -idaman bool ida_export get_arg_addrs(eavec_t *out, ea_t caller); - - -/// Apply the specified type and name to the address. -/// This function checks if the address already has a type. If the old type \n -/// does not exist or the new type is 'better' than the old type, then the \n -/// new type will be applied. A type is considered better if it has more \n -/// information (e.g. ::BTMT_STRUCT is better than ::BT_INT). \n -/// The same logic is with the name: if the address already have a meaningful \n -/// name, it will be preserved. Only if the old name does not exist or it \n -/// is a dummy name like byte_123, it will be replaced by the new name. -/// \param dea linear address -/// \param tif type string in the internal format -/// \param name new name for the address -/// \return success - -idaman bool ida_export apply_once_tinfo_and_name( - ea_t dea, - const tinfo_t &tif, - const char *name); - - -// To retrieve the type information attach to an address, use get_tinfo() function -// (see nalt.hpp) - - -/// Generate a type information about the id from the disassembly. -/// id can be a structure/union/enum id or an address. -/// \return one of \ref GUESS_ - -idaman int ida_export guess_tinfo(tinfo_t *tif, tid_t id); - -/// \defgroup GUESS_ Guess tinfo codes -/// return values for guess_tinfo() -//@{ -#define GUESS_FUNC_FAILED 0 ///< couldn't guess the function type -#define GUESS_FUNC_TRIVIAL 1 ///< the function type doesn't have interesting info -#define GUESS_FUNC_OK 2 ///< ok, some non-trivial information is gathered -//@} - - -// The following functions should eventually be replaced by exported functions -#ifndef __KERNEL__ -/// Set include directory path the target compiler -inline void set_c_header_path(const char *incdir) { root_node.supset(RIDX_H_PATH, incdir); } - -/// Get the include directory path of the target compiler -inline ssize_t get_c_header_path(qstring *buf) { return root_node.supstr(buf, RIDX_H_PATH); } - -/// Set predefined macros for the target compiler -inline void set_c_macros(const char *macros) { root_node.supset(RIDX_C_MACROS, macros); } - -/// Get predefined macros for the target compiler -inline ssize_t get_c_macros(qstring *buf) { return root_node.supstr(buf, RIDX_C_MACROS); } -#endif - -//------------------------------------------------------------------------ -// HIGH LEVEL FUNCTIONS TO SUPPORT TILS IN THE IDA KERNEL - -/// Pointer to the local type library - this til is private for each IDB file -/// Function that accepts til_t* uses local type library instead of NULL. - -idaman const til_t *ida_export get_idati(void); - - -/// Extract information from a tinfo_t. -/// \param[out] psize size of tif -/// \param[out] pflags description of type using flags_t -/// \param[out] mt info for non-scalar types -/// \param tif the type to inspect -/// \param[out] alsize alignment - -idaman bool ida_export get_idainfo_by_type( - size_t *out_size, - flags_t *out_flags, - opinfo_t *out_mt, - const tinfo_t &tif, - size_t *out_alsize=NULL); - -//------------------------------------------------------------------------ -// Type information object: tinfo_t - -struct ptr_type_data_t; -struct udt_type_data_t; -struct enum_type_data_t; -struct array_type_data_t; -struct typedef_type_data_t; -struct bitfield_type_data_t; - -/// IDs for common types -enum stock_type_id_t -{ - STI_PCHAR, ///< char * - STI_PUCHAR, ///< uint8 * - STI_PCCHAR, ///< const char * - STI_PCUCHAR, ///< const uint8 * - STI_PBYTE, ///< _BYTE * - STI_PINT, ///< int * - STI_PUINT, ///< unsigned int * - STI_PVOID, ///< void * - STI_PPVOID, ///< void ** - STI_PCVOID, ///< const void * - STI_ACHAR, ///< char[] - STI_AUCHAR, ///< uint8[] - STI_ACCHAR, ///< const char[] - STI_ACUCHAR, ///< const uint8[] - STI_FPURGING, ///< void __userpurge(int) - STI_FDELOP, ///< void __cdecl(void *) - STI_MSGSEND, ///< void *(void *, const char *, ...) - STI_AEABI_LCMP, ///< int __fastcall(int64 x, int64 y) - STI_AEABI_ULCMP, ///< int __fastcall(uint64 x, uint64 y) - STI_DONT_USE, ///< unused stock type id; should not be used - STI_SIZE_T, ///< size_t - STI_SSIZE_T, ///< ssize_t - STI_AEABI_MEMCPY, ///< void __fastcall(void *, const void *, size_t) - STI_AEABI_MEMSET, ///< void __fastcall(void *, size_t, int) - STI_AEABI_MEMCLR, ///< void __fastcall(void *, size_t) - STI_RTC_CHECK_2, ///< int16 __fastcall(int16 x) - STI_RTC_CHECK_4, ///< int32 __fastcall(int32 x) - STI_RTC_CHECK_8, ///< int64 __fastcall(int64 x) - STI_LAST -}; - -/// Constants to be used with get_udt_details() -enum gtd_udt_t -{ - GTD_CALC_LAYOUT = 0, ///< calculate udt layout - GTD_NO_LAYOUT = BTM_VOLATILE, ///< don't calculate udt layout - ///< please note that udt layout may have been - ///< calculated earlier - GTD_DEL_BITFLDS = BTM_CONST, ///< delete udt bitfields -}; - -/// Constants to be used with get_func_details() -enum gtd_func_t -{ - GTD_CALC_ARGLOCS = 0, ///< calculate func arg locations - GTD_NO_ARGLOCS = BTM_VOLATILE, ///< don't calculate func arg locations - ///< please note that the locations may have been - ///< calculated earlier -}; - -/// Constants to be used with get_size() -enum gts_code_t -{ - GTS_NESTED = 0x01, ///< nested type (embedded into a udt) - GTS_BASECLASS = 0x02, ///< is baseclass of a udt -}; - -/// \defgroup SUDT_ UDT serialization flags -/// passed as 'sudt_flags' parameter of helpers declared in #DECLARE_TINFO_HELPERS -//@{ -#define SUDT_SORT 0x0001 ///< fields are not sorted by offset, sort them first -#define SUDT_ALIGN 0x0002 ///< recalculate field alignments, struct packing, etc - ///< to match the offsets and size info -#define SUDT_GAPS 0x0004 ///< allow to fill gaps with additional members (_BYTE[]) -#define SUDT_UNEX 0x0008 ///< references to nonexistent member types are acceptable - ///< in this case it is better to set the corresponding - ///< udt_member_t::fda field to the type alignment. if this - ///< field is not set, ida will try to guess the alignment. -#define SUDT_FAST 0x0010 ///< serialize without verifying offsets and alignments - -#define SUDT_CONST 0x0040 ///< only for serialize_udt: make type const -#define SUDT_VOLATILE 0x0080 ///< only for serialize_udt: make type volatile - -#define SUDT_TRUNC 0x0100 ///< serialize: truncate useless strings from fields, fldcmts -//@} - -/// Macro to declare common tinfo_t related functions -#define DECLARE_TINFO_HELPERS(decl)\ -decl void ida_export copy_tinfo_t(tinfo_t *_this, const tinfo_t &r); \ -decl void ida_export clear_tinfo_t(tinfo_t *_this);\ -decl bool ida_export create_tinfo(tinfo_t *_this, type_t bt, type_t bt2, void *ptr);\ -decl int ida_export verify_tinfo(uint32 typid);\ -decl bool ida_export get_tinfo_details(uint32 typid, type_t bt2, void *buf);\ -decl size_t ida_export get_tinfo_size(uint32 *p_effalign, uint32 typid, int gts_code);\ -decl size_t ida_export get_tinfo_pdata(void *outptr, uint32 typid, int what);\ -decl size_t ida_export get_tinfo_property(uint32 typid, int gta_prop);\ -decl size_t ida_export set_tinfo_property(tinfo_t *tif, int sta_prop, size_t x);\ -decl bool ida_export serialize_tinfo(qtype *type, qtype *fields, qtype *fldcmts, const tinfo_t *tif, int sudt_flags);\ -decl bool ida_export deserialize_tinfo(tinfo_t *tif, const til_t *til, const type_t **ptype, const p_list **pfields, const p_list **pfldcmts);\ -decl int ida_export find_tinfo_udt_member(struct udt_member_t *udm, uint32 typid, int strmem_flags);\ -decl bool ida_export print_tinfo(qstring *result, const char *prefix, int indent, int cmtindent, int flags, const tinfo_t *tif, const char *name, const char *cmt);\ -decl const char *ida_export dstr_tinfo(const tinfo_t *tif);\ -decl int ida_export visit_subtypes(struct tinfo_visitor_t *visitor, struct type_mods_t *out, const tinfo_t &tif, const char *name, const char *cmt);\ -decl bool ida_export compare_tinfo(uint32 t1, uint32 t2, int tcflags);\ -decl int ida_export lexcompare_tinfo(uint32 t1, uint32 t2, int);\ -decl bool ida_export get_stock_tinfo(tinfo_t *tif, stock_type_id_t id);\ -decl uint64 ida_export read_tinfo_bitfield_value(uint32 typid, uint64 v, int bitoff);\ -decl uint64 ida_export write_tinfo_bitfield_value(uint32 typid, uint64 dst, uint64 v, int bitoff);\ -decl bool ida_export get_tinfo_attr(uint32 typid, const qstring &key, bytevec_t *bv, bool all_attrs);\ -decl bool ida_export set_tinfo_attr(tinfo_t *tif, const type_attr_t &ta, bool may_overwrite);\ -decl bool ida_export del_tinfo_attr(tinfo_t *tif, const qstring &key, bool make_copy);\ -decl bool ida_export get_tinfo_attrs(uint32 typid, type_attrs_t *tav, bool include_ref_attrs);\ -decl bool ida_export set_tinfo_attrs(tinfo_t *tif, type_attrs_t *ta);\ -decl uint32 ida_export score_tinfo(const tinfo_t *tif);\ -decl tinfo_code_t ida_export save_tinfo(tinfo_t *tif, til_t *til, size_t ord, const char *name, int ntf_flags);\ -decl bool ida_export append_tinfo_covered(rangeset_t *out, uint32 typid, uint64 offset);\ -decl bool ida_export calc_tinfo_gaps(rangeset_t *out, uint32 typid);\ -decl bool ida_export name_requires_qualifier(qstring *out, uint32 typid, const char *name, uint64 offset);\ - -DECLARE_TINFO_HELPERS(idaman) - -/*! \defgroup tf_nontrivial Nontrivial types - \ingroup tf - bits 0..5: base type \n - bits 6..7: const & volatile bits \n - bit 8: 'is_typeref' bit \n - bits 9..31: type detail idx -*/ -//@{ -const int FIRST_NONTRIVIAL_TYPID = 0x100; ///< Denotes the first bit describing a nontrivial type -const int TYPID_ISREF = 0x100; ///< Identifies that a type that is a typeref -const int TYPID_SHIFT = 9; ///< First type detail bit -//@} - -//-V:create_array:678 An object is used as an argument to its own method. -//-V:create_ptr:678 -/// Primary mechanism for managing type information -class tinfo_t // #tinfo_t #tif -{ - uint32 typid; /// byte sequence describing the type - bool create_type(type_t decl_type, type_t bt2, void *details) - { - return create_tinfo(this, decl_type, bt2, details); - } - /// Get the type details. - /// The information is copied to the user-supplied buffer. - /// Also check out convenience functions below (get_ptr_details, etc), they work faster because - /// they do not copy the entire type info but only the desired part of it. - bool get_type_details(type_t bt2, void *buf) const { return get_tinfo_details(typid, bt2, buf); } - void copy(const tinfo_t &r) { copy_tinfo_t(this, r); } - DECLARE_TINFO_HELPERS(friend) - friend struct type_detail_t; - friend tinfo_t remove_pointer(const tinfo_t &tif); - /// Various type properties (properties are a 32-bit scalar values) - enum gta_prop_t - { - GTA_DECLALIGN, ///< declared alignment - GTA_RESOLVE, ///< real type (fully resolve eventual type references) - GTA_REALTYPE, ///< real type (do not fully resolve type refs) - GTA_TYPE_SIGN, ///< get type sign - GTA_FROM_SUBTIL, ///< is from a subtil (not from main til) - GTA_IS_FORWARD, ///< is forward declaration? - GTA_IS_FUNCPTR, ///< is a pointer to a function? - GTA_ORDINAL, ///< get initial type ordinal - GTA_FINAL_ORDINAL, ///< get final (resolved) type ordinal - GTA_PTR_OBJ, ///< ptr: pointed type - GTA_SAFE_PTR_OBJ, ///< ptr: pointed type or type itself - GTA_ARRAY_ELEM, ///< array: array element - GTA_ARRAY_NELEMS, ///< array: number of elements - GTA_PTRARR_SUBTIF, ///< ptr&array: pointed object or array element (nb: deletes current tif) - GTA_PTRARR_SIZE, ///< ptr&array: get size of subtype - GTA_UNPADDED_SIZE, ///< udt: sizeof baseclass when embedded into a derived class - GTA_UDT_NMEMBERS, ///< udt: get number of udt members - GTA_IS_SMALL_UDT, ///< udt: is small udt (can be passed in regs) - GTA_ONEMEM_TYPE, ///< udt&array: object consisting of one member: type of the member - GTA_ENUM_BASE_TYPE, ///< enum: get enum base type - GTA_FUNC_CC, ///< func: calling convention - GTA_PURGED_BYTES, ///< func: number of purged bytes - GTA_IS_HIGH_TYPE, ///< func: is high type - GTA_FUNC_NARGS, ///< func: number of arguments - GTA_FUNC_RET, ///< func: get function return type - GTA_FUNC_ARG, ///< func: get type of function arg - GTA_LAST_FUNC_ARG = GTA_FUNC_ARG + 255, - GTA_IS_SSE_TYPE, ///< is a SSE vector type? - GTA_IS_ANON_UDT, ///< is anonymous struct/union? - GTA_IS_VFTABLE, ///< is vftable? - GTA_HAS_VFTABLE, ///< has vftable? - GTA_IS_SHIFTED_PTR, ///< is a shifted pointer? - GTA_IS_VARSTRUCT, ///< is a variable-size structure? - }; - enum sta_prop_t ///< set type property - { - STA_DECLALIGN, ///< set declared alignment - STA_TYPE_SIGN, ///< set type sign - STA_UDT_ALIGN, ///< calculate udt field alignments - }; - enum gta_pdata_t ///< get info returned by pointer - { - GTP_NAME, ///< get referenced name - GTP_NEXT_NAME, ///< get immediately next referenced name - GTP_FINAL_NAME, ///< get final referenced name - GTP_TIL, ///< get type library - }; - -public: - /// Constructor - tinfo_t(): typid(BT_UNK) {} - /// Constructor - can only be used to initialize simple types! - explicit tinfo_t(type_t decl_type) : typid(decl_type) {} - /// Constructor - tinfo_t(const tinfo_t &r) : typid(0) { copy(r); } - /// Copy contents of given tinfo into this one - tinfo_t &operator=(const tinfo_t &r) { copy(r); return *this; } - /// Destructor - ~tinfo_t(void) { clear(); } - /// Clear contents of this tinfo, and remove from the type system - void clear(void) { clear_tinfo_t(this); } - /// Assign this = r and r = this - void swap(tinfo_t &r) { uint32 tmp = typid; typid = r.typid; r.typid = tmp; } - DEFINE_MEMORY_ALLOCATION_FUNCS() - - /// Create a tinfo_t object for an existing named type. - /// \param til type library to use - /// \param name name of the type to link to - /// \param decl_type if the reference was explicitly specified with the type tag \n - /// (::BTF_STRUCT/::BTF_UNION/::BTF_ENUM) you may specify it. \n - /// the kernel will accept only the specified tag after resolving \n - /// the type. If the resolved type does not correspond to the \n - /// explicitly specified tag, the type will be considered as undefined \n - /// \param resolve true: immediately resolve the type and return success code. - /// false: return true but do not immediately resolve the type - /// \param try_ordinal true: try to replace name reference by an ordinal reference - inline bool get_named_type( - const til_t *til, - const char *name, - type_t decl_type=BTF_TYPEDEF, - bool resolve=true, - bool try_ordinal=true); - - /// Create a tinfo_t object for an existing ordinal type. - /// \param til type library to use - /// \param ordinal number of the type to link to - /// \param decl_type if the reference was explicitly specified with the type tag - /// (BTF_STRUCT/BTF_UNION/BTF_ENUM) you may specify it. - /// the kernel will accept only the specified tag after resolving - /// the type. If the resolved type does not correspond to the - /// explicitly specified tag, the type will be considered as undefined - /// \param resolve true: immediately resolve the type and return success code - /// false: return true but do not immediately resolve the type - inline bool get_numbered_type( - const til_t *til, - uint32 ordinal, - type_t decl_type=BTF_TYPEDEF, - bool resolve=true); - - /// Serialize tinfo_t object into a type string. - bool serialize( - qtype *type, - qtype *fields=NULL, - qtype *fldcmts=NULL, - int sudt_flags=SUDT_FAST|SUDT_TRUNC) const - { - return serialize_tinfo(type, fields, fldcmts, this, sudt_flags); - } - - /// Deserialize a type string into a tinfo_t object - bool deserialize( - const til_t *til, - const type_t **ptype, - const p_list **pfields=NULL, - const p_list **pfldcmts=NULL) - { - return deserialize_tinfo(this, til, ptype, pfields, pfldcmts); - } - /// \copydoc deserialize() - bool deserialize( - const til_t *til, - const qtype *ptype, - const qtype *pfields=NULL, - const qtype *pfldcmts=NULL) - { - const type_t *tp = ptype->begin(); - const p_list *fp = pfields == NULL ? NULL : pfields->begin(); - const p_list *cp = pfldcmts == NULL ? NULL : pfldcmts->begin(); - return deserialize(til, &tp, fp == NULL ? NULL : &fp, cp == NULL ? NULL : &cp); - } - - /// Is the type object correct?. - /// It is possible to create incorrect types. For example, we can define a - /// function that returns a enum and then delete the enum type. - /// If this function returns false, the type should not be used in - /// disassembly. Please note that this function does not verify all - /// involved types: for example, pointers to undefined types are permitted. - bool is_correct(void) const { return verify_tinfo(typid) == 0; } - - /// Get the resolved base type. - /// Deserialization options: - /// - if full=true, the referenced type will be deserialized fully, - /// this may not always be desirable (slows down things) - /// - if full=false, we just return the base type, the referenced type will be - /// resolved again later if necessary - /// (this may lead to multiple resolvings of the same type) - /// imho full=false is a better approach because it does not perform - /// unnecessary actions just in case. however, in some cases the caller knows - /// that it is very likely that full type info will be required. in those cases - /// full=true makes sense - type_t get_realtype(bool full=false) const { return (type_t)get_tinfo_property(typid, full ? GTA_RESOLVE : GTA_REALTYPE); } - - /// Get declared type (without resolving type references; they are returned as is). - /// Obviously this is a very fast function and should be used instead of get_realtype() - /// if possible. - THREAD_SAFE type_t get_decltype(void) const { return type_t(typid); } - - /// Was tinfo_t initialized with some type info or not? - THREAD_SAFE bool empty(void) const { return get_decltype() == BT_UNK; } - - /// Is the type really present? (not a reference to a missing type, for example) - bool present(void) const { return get_realtype() != BT_UNK; } - - /// Get the type size in bytes. - /// \param p_effalign buffer for the alignment value - /// \param gts_code combination of GTS_... constants - /// \return ::BADSIZE in case of problems - size_t get_size(uint32 *p_effalign=NULL, int gts_code=0) const { return get_tinfo_size(p_effalign, typid, gts_code); } - - /// Get the type size in bytes without the final padding, in bytes. - /// For some UDTs get_unpadded_size() != get_size() - size_t get_unpadded_size(void) const { return get_tinfo_property(typid, GTA_UNPADDED_SIZE); } - - /// Get type sign - type_sign_t get_sign(void) const { return get_tinfo_property(typid, GTA_TYPE_SIGN); } - - /// Is this a signed type? - bool is_signed(void) const { return get_sign() == type_signed; } - - /// Is this an unsigned type? - bool is_unsigned(void) const { return get_sign() == type_unsigned; } - - /// Get declared alignment of the type - uchar get_declalign(void) const { return uchar(get_tinfo_property(typid, GTA_DECLALIGN)); } - - /// Set declared alignment of the type - bool set_declalign(uchar declalign) { return set_tinfo_property(this, STA_DECLALIGN, declalign) != 0; } - - /// Is this type a type reference?. - /// Type references cannot be modified. Once created, they do not change. - /// Because of this, the set_... functions applied to typerefs create - /// a new type id. Other types are modified directly. - THREAD_SAFE bool is_typeref(void) const { return (typid & TYPID_ISREF) != 0; } - - /// Does this type refer to a nontrivial type? - THREAD_SAFE bool has_details(void) const { return typid >= FIRST_NONTRIVIAL_TYPID; } - - /// Does a type refer to a name?. - /// If yes, fill the provided buffer with the type name and return true. - /// Names are returned for numbered types too: either a user-defined nice name - /// or, if a user-provided name does not exist, an ordinal name - /// (like #xx, see create_numbered_type_name()). - bool get_type_name(qstring *out) const { return is_typeref() && get_tinfo_pdata(out, typid, GTP_NAME); } - - /// Use in the case of typedef chain (TYPE1 -> TYPE2 -> TYPE3...TYPEn). - /// \return the name of the last type in the chain (TYPEn). - /// if there is no chain, returns TYPE1 - bool get_final_type_name(qstring *out) const { return is_typeref() && get_tinfo_pdata(out, typid, GTP_FINAL_NAME); } - - /// Use In the case of typedef chain (TYPE1 -> TYPE2 -> TYPE3...TYPEn). - /// \return the name of the next type in the chain (TYPE2). - /// if there is no chain, returns failure - bool get_next_type_name(qstring *out) const { return is_typeref() && get_tinfo_pdata(out, typid, GTP_NEXT_NAME); } - - /// Get type ordinal (only if the type was created as a numbered type, 0 if none) - uint32 get_ordinal(void) const { return get_tinfo_property(typid, GTA_ORDINAL); } - - /// Get final type ordinal (0 is none) - uint32 get_final_ordinal(void) const { return get_tinfo_property(typid, GTA_FINAL_ORDINAL); } - - /// Get the type library for tinfo_t - const til_t *get_til(void) const { const til_t *til; get_tinfo_pdata(&til, typid, GTP_TIL); return til; } - - /// Was the named type found in some base type library (not the top level type library)?. - /// If yes, it usually means that the type comes from some loaded type library, - /// not the local type library for the database - bool is_from_subtil(void) const { return is_typeref() && get_tinfo_property(typid, GTA_FROM_SUBTIL); } - - /// Is this a forward declaration?. - /// Forward declarations are placeholders: the type definition does not exist - bool is_forward_decl(void) const { return get_tinfo_property(typid, GTA_IS_FORWARD) != 0; } - - THREAD_SAFE bool is_decl_const(void) const { return is_type_const(get_decltype()); } ///< \isdecl{is_type_const} - THREAD_SAFE bool is_decl_volatile(void) const { return is_type_volatile(get_decltype()); } ///< \isdecl{is_type_volatile} - THREAD_SAFE bool is_decl_void(void) const { return is_type_void(get_decltype()); } ///< \isdecl{is_type_void} - THREAD_SAFE bool is_decl_partial(void) const { return is_type_partial(get_decltype()); } ///< \isdecl{is_type_partial} - THREAD_SAFE bool is_decl_unknown(void) const { return is_type_unknown(get_decltype()); } ///< \isdecl{is_type_unknown} - THREAD_SAFE bool is_decl_last(void) const { return is_typeid_last(get_decltype()); } ///< \isdecl{is_typeid_last} - THREAD_SAFE bool is_decl_ptr(void) const { return is_type_ptr(get_decltype()); } ///< \isdecl{is_type_ptr} - THREAD_SAFE bool is_decl_array(void) const { return is_type_array(get_decltype()); } ///< \isdecl{is_type_array} - THREAD_SAFE bool is_decl_func(void) const { return is_type_func(get_decltype()); } ///< \isdecl{is_type_func} - THREAD_SAFE bool is_decl_complex(void) const { return is_type_complex(get_decltype()); } ///< \isdecl{is_type_complex} - THREAD_SAFE bool is_decl_typedef(void) const { return is_type_typedef(get_decltype()); } ///< \isdecl{is_type_typedef} - THREAD_SAFE bool is_decl_sue(void) const { return is_type_sue(get_decltype()); } ///< \isdecl{is_type_sue} - THREAD_SAFE bool is_decl_struct(void) const { return is_type_struct(get_decltype()); } ///< \isdecl{is_type_struct} - THREAD_SAFE bool is_decl_union(void) const { return is_type_union(get_decltype()); } ///< \isdecl{is_type_union} - THREAD_SAFE bool is_decl_udt(void) const { return is_type_struni(get_decltype()); } ///< \isdecl{is_type_struni} - THREAD_SAFE bool is_decl_enum(void) const { return is_type_enum(get_decltype()); } ///< \isdecl{is_type_enum} - THREAD_SAFE bool is_decl_bitfield(void) const { return is_type_bitfld(get_decltype()); } ///< \isdecl{is_type_bitfld} - THREAD_SAFE bool is_decl_int128(void) const { return is_type_int128(get_decltype()); } ///< \isdecl{is_type_int128} - THREAD_SAFE bool is_decl_int64(void) const { return is_type_int64(get_decltype()); } ///< \isdecl{is_type_int64} - THREAD_SAFE bool is_decl_int32(void) const { return is_type_int32(get_decltype()); } ///< \isdecl{is_type_int32} - THREAD_SAFE bool is_decl_int16(void) const { return is_type_int16(get_decltype()); } ///< \isdecl{is_type_int16} - THREAD_SAFE bool is_decl_int(void) const { return is_type_int(get_decltype()); } ///< \isdecl{is_type_int} - THREAD_SAFE bool is_decl_char(void) const { return is_type_char(get_decltype()); } ///< \isdecl{is_type_char} - THREAD_SAFE bool is_decl_uint(void) const { return is_type_uint(get_decltype()); } ///< \isdecl{is_type_uint} - THREAD_SAFE bool is_decl_uchar(void) const { return is_type_uchar(get_decltype()); } ///< \isdecl{is_type_uchar} - THREAD_SAFE bool is_decl_uint16(void) const { return is_type_uint16(get_decltype()); } ///< \isdecl{is_type_uint16} - THREAD_SAFE bool is_decl_uint32(void) const { return is_type_uint32(get_decltype()); } ///< \isdecl{is_type_uint32} - THREAD_SAFE bool is_decl_uint64(void) const { return is_type_uint64(get_decltype()); } ///< \isdecl{is_type_uint64} - THREAD_SAFE bool is_decl_uint128(void) const { return is_type_uint128(get_decltype()); } ///< \isdecl{is_type_uint128} - THREAD_SAFE bool is_decl_ldouble(void) const { return is_type_ldouble(get_decltype()); } ///< \isdecl{is_type_ldouble} - THREAD_SAFE bool is_decl_double(void) const { return is_type_double(get_decltype()); } ///< \isdecl{is_type_double} - THREAD_SAFE bool is_decl_float(void) const { return is_type_float(get_decltype()); } ///< \isdecl{is_type_float} - THREAD_SAFE bool is_decl_tbyte(void) const { return is_type_tbyte(get_decltype()); } ///< \isdecl{is_type_tbyte} - THREAD_SAFE bool is_decl_floating(void) const { return is_type_floating(get_decltype()); } ///< \isdecl{is_type_floating} - THREAD_SAFE bool is_decl_bool(void) const { return is_type_bool(get_decltype()); } ///< \isdecl{is_type_bool} - THREAD_SAFE bool is_decl_paf(void) const { return is_type_paf(get_decltype()); } ///< \isdecl{is_type_paf} - THREAD_SAFE bool is_well_defined(void) const { return !empty() && !is_decl_partial(); } ///< !(empty()) && !(is_decl_partial()) - - // Probe the resolved type for various attributes: - bool is_const(void) const { return is_type_const(get_realtype()); } ///< \isreal{is_type_const} - bool is_volatile(void) const { return is_type_volatile(get_realtype()); } ///< \isreal{is_type_volatile} - bool is_void(void) const { return is_type_void(get_realtype()); } ///< \isreal{is_type_void} - bool is_partial(void) const { return is_type_partial(get_realtype()); } ///< \isreal{is_type_partial} - bool is_unknown(void) const { return is_type_unknown(get_realtype()); } ///< \isreal{is_type_unknown} - bool is_ptr(void) const { return is_type_ptr(get_realtype()); } ///< \isreal{is_type_ptr} - bool is_array(void) const { return is_type_array(get_realtype()); } ///< \isreal{is_type_array} - bool is_func(void) const { return is_type_func(get_realtype()); } ///< \isreal{is_type_func} - bool is_complex(void) const { return is_type_complex(get_realtype()); } ///< \isreal{is_type_complex} - bool is_struct(void) const { return is_type_struct(get_realtype()); } ///< \isreal{is_type_struct} - bool is_union(void) const { return is_type_union(get_realtype()); } ///< \isreal{is_type_union} - bool is_udt(void) const { return is_type_struni(get_realtype()); } ///< \isreal{is_type_struni} - bool is_enum(void) const { return is_type_enum(get_realtype()); } ///< \isreal{is_type_enum} - bool is_sue(void) const { return is_type_sue(get_realtype()); } ///< \isreal{is_type_sue} - bool is_bitfield(void) const { return is_type_bitfld(get_realtype()); } ///< \isreal{is_type_bitfld} - bool is_int128(void) const { return is_type_int128(get_realtype()); } ///< \isreal{is_type_int128} - bool is_int64(void) const { return is_type_int64(get_realtype()); } ///< \isreal{is_type_int64} - bool is_int32(void) const { return is_type_int32(get_realtype()); } ///< \isreal{is_type_int32} - bool is_int16(void) const { return is_type_int16(get_realtype()); } ///< \isreal{is_type_int16} - bool is_int(void) const { return is_type_int(get_realtype()); } ///< \isreal{is_type_int} - bool is_char(void) const { return is_type_char(get_realtype()); } ///< \isreal{is_type_char} - bool is_uint(void) const { return is_type_uint(get_realtype()); } ///< \isreal{is_type_uint} - bool is_uchar(void) const { return is_type_uchar(get_realtype()); } ///< \isreal{is_type_uchar} - bool is_uint16(void) const { return is_type_uint16(get_realtype()); } ///< \isreal{is_type_uint16} - bool is_uint32(void) const { return is_type_uint32(get_realtype()); } ///< \isreal{is_type_uint32} - bool is_uint64(void) const { return is_type_uint64(get_realtype()); } ///< \isreal{is_type_uint64} - bool is_uint128(void) const { return is_type_uint128(get_realtype()); } ///< \isreal{is_type_uint128} - bool is_ldouble(void) const { return is_type_ldouble(get_realtype()); } ///< \isreal{is_type_ldouble} - bool is_double(void) const { return is_type_double(get_realtype()); } ///< \isreal{is_type_double} - bool is_float(void) const { return is_type_float(get_realtype()); } ///< \isreal{is_type_float} - bool is_tbyte(void) const { return is_type_tbyte(get_realtype()); } ///< \isreal{is_type_tbyte} - bool is_bool(void) const { return is_type_bool(get_realtype()); } ///< \isreal{is_type_bool} - bool is_paf(void) const { return is_type_paf(get_realtype()); } ///< \isreal{is_type_paf} - bool is_ptr_or_array(void) const { return is_type_ptr_or_array(get_realtype()); } ///< \isreal{is_type_ptr_or_array} - bool is_integral(void) const { return is_type_integral(get_realtype()); } ///< \isreal{is_type_integral} - bool is_ext_integral(void) const { return is_type_ext_integral(get_realtype()); } ///< \isreal{is_type_ext_integral} - bool is_floating(void) const { return is_type_floating(get_realtype()); } ///< \isreal{is_type_floating} - bool is_arithmetic(void) const { return is_type_arithmetic(get_realtype()); } ///< \isreal{is_type_arithmetic} - bool is_ext_arithmetic(void) const { return is_type_ext_arithmetic(get_realtype()); } ///< \isreal{is_type_ext_arithmetic} - /// Does the type represent a single number? - bool is_scalar(void) const { type_t bt = get_realtype(); return get_base_type(bt) <= BT_PTR || is_type_enum(bt); } - - /// Get the pointer info. - bool get_ptr_details(ptr_type_data_t *pi) const - { - return get_type_details(BT_PTR|BTM_VOLATILE, pi); - } - - /// Get the array specific info - bool get_array_details(array_type_data_t *ai) const - { - return get_type_details(BT_ARRAY, ai); - } - - /// Get the enum specific info - bool get_enum_details(enum_type_data_t *ei) const - { - return get_type_details(BTF_ENUM, ei); - } - - /// Get the bitfield specific info - bool get_bitfield_details(bitfield_type_data_t *bi) const - { - return get_type_details(BT_BITFIELD, bi); - } - - /// Get the udt specific info - bool get_udt_details(udt_type_data_t *udt, gtd_udt_t gtd=GTD_CALC_LAYOUT) const - { - return get_type_details(BTF_STRUCT|gtd, udt); - } - - /// Get only the function specific info for this tinfo_t - bool get_func_details(func_type_data_t *fi, gtd_func_t gtd=GTD_CALC_ARGLOCS) const - { - return get_type_details(BT_FUNC|gtd, fi); - } - - /// Is this pointer to a function? - bool is_funcptr(void) const { return get_tinfo_property(typid, GTA_IS_FUNCPTR) != 0; } - - /// Is a shifted pointer? - bool is_shifted_ptr(void) const { return get_tinfo_property(typid, GTA_IS_SHIFTED_PTR) != 0; } - - /// Is a variable-size structure? - bool is_varstruct(void) const { return get_tinfo_property(typid, GTA_IS_VARSTRUCT) != 0; } - - /// ::BT_PTR & ::BT_ARRAY: get size of pointed object or array element. On error returns -1 - int get_ptrarr_objsize(void) const { return get_tinfo_property(typid, GTA_PTRARR_SIZE); } - - /// ::BT_PTR & ::BT_ARRAY: get the pointed object or array element. - /// If the current type is not a pointer or array, return empty type info. - tinfo_t get_ptrarr_object(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_PTRARR_SUBTIF); return r; } - - /// ::BT_PTR: get type of pointed object. - /// If the current type is not a pointer, return empty type info. - /// See also get_ptrarr_object() and remove_pointer() - tinfo_t get_pointed_object(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_PTR_OBJ); return r; } - - /// Is "void *"?. This function does not check the pointer attributes and type modifiers - bool is_pvoid(void) const { return get_pointed_object().is_void(); } - - /// ::BT_ARRAY: get type of array element. See also get_ptrarr_object() - tinfo_t get_array_element(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_ARRAY_ELEM); return r; } - - /// ::BT_ARRAY: get number of elements (-1 means error) - int get_array_nelems(void) const { return get_tinfo_property(typid, GTA_ARRAY_NELEMS); } - - /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Get type of n-th arg (-1 means return type, see get_rettype()) - tinfo_t get_nth_arg(int n) const - { - tinfo_t r; - if ( n >= -1 && n < MAX_FUNC_ARGS ) - r.typid = get_tinfo_property(typid, GTA_FUNC_ARG+n); - return r; - } - - /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Get the function's return type - tinfo_t get_rettype(void) const { return get_nth_arg(-1); } - - /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Calculate number of arguments (-1 - error) - int get_nargs(void) const { return get_tinfo_property(typid, GTA_FUNC_NARGS); } - - /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Get calling convention - cm_t get_cc(void) const { return (cm_t)get_tinfo_property(typid, GTA_FUNC_CC); } - bool is_user_cc(void) const { return ::is_user_cc(get_cc()); } ///< \tinfocc{is_user_cc} - bool is_vararg_cc(void) const { return ::is_vararg_cc(get_cc()); } ///< \tinfocc{is_vararg_cc} - bool is_purging_cc(void) const { return ::is_purging_cc(get_cc()); } ///< \tinfocc{is_purging_cc} - - /// ::BT_FUNC: Calculate number of purged bytes - int calc_purged_bytes(void) const { return get_tinfo_property(typid, GTA_PURGED_BYTES); } - - /// ::BT_FUNC: Is high level type? - bool is_high_func(void) const { return get_tinfo_property(typid, GTA_IS_HIGH_TYPE) != 0; } - - /// ::BTF_STRUCT,::BTF_UNION: Find a udt member. - /// - at the specified offset (#STRMEM_OFFSET) - /// - with the specified index (#STRMEM_INDEX) - /// - with the specified type (#STRMEM_TYPE) - /// - with the specified name (#STRMEM_NAME) - /// \return the index of the found member or -1 - int find_udt_member(struct udt_member_t *udm, int strmem_flags) const { return find_tinfo_udt_member(udm, typid, strmem_flags); } -/// \defgroup STRMEM_ Find UDT member flags -/// used by 'strmem_flags' parameter to find_udt_member() -//@{ -#define STRMEM_MASK 0x0007 -#define STRMEM_OFFSET 0x0000 ///< get member by offset - ///< - in: udm->offset - is a member offset in bits -#define STRMEM_INDEX 0x0001 ///< get member by number - ///< - in: udm->offset - is a member number -#define STRMEM_AUTO 0x0002 ///< get member by offset if struct, or get member by index if union - ///< - nb: union: index is stored in the udm->offset field! - ///< - nb: struct: offset is in bytes (not in bits)! -#define STRMEM_NAME 0x0003 ///< get member by name - ///< - in: udm->name - the desired member name. -#define STRMEM_TYPE 0x0004 ///< get member by type. - ///< - in: udm->type - the desired member type. - ///< member types are compared with tinfo_t::equals_to() -#define STRMEM_SIZE 0x0005 ///< get member by size. - ///< - in: udm->size - the desired member size. -#define STRMEM_MINS 0x0006 ///< get smallest member by size. -#define STRMEM_MAXS 0x0007 ///< get biggest member by size. -#define STRMEM_VFTABLE 0x10000000 - ///< can be combined with #STRMEM_OFFSET, #STRMEM_AUTO - ///< get vftable instead of the base class -#define STRMEM_SKIP_EMPTY 0x20000000 - ///< can be combined with #STRMEM_OFFSET, #STRMEM_AUTO - ///< skip empty members (i.e. having zero size) - ///< only last empty member can be returned -#define STRMEM_CASTABLE_TO 0x40000000 - ///< can be combined with #STRMEM_TYPE: - ///< member type must be castable to the specified type -#define STRMEM_ANON 0x80000000 - ///< can be combined with #STRMEM_NAME: - ///< look inside anonymous members too. -//@} - - /// Get number of udt members. -1-error - int get_udt_nmembers(void) const { return get_tinfo_property(typid, GTA_UDT_NMEMBERS); } - - /// Is an empty struct/union? (has no fields) - bool is_empty_udt(void) const { return get_udt_nmembers() == 0; } - - /// Is a small udt? (can fit a register or a pair of registers) - bool is_small_udt(void) const { return get_tinfo_property(typid, GTA_IS_SMALL_UDT) != 0; } - - /// Requires full qualifier? (name is not unique) - /// \param out qualifier. may be NULL - /// \param name field name - /// \param off field offset in bits - /// \return if the name is not unique, returns true - bool requires_qualifier(qstring *out, const char *name, uint64 offset) const { return name_requires_qualifier(out, typid, name, offset); } - - /// Calculate set of covered bytes for the type - /// \param out pointer to the output buffer. covered bytes will be appended to it. - bool append_covered(rangeset_t *out, uint64 offset=0) const { return append_tinfo_covered(out, typid, offset); } - - /// Calculate set of padding bytes for the type - /// \param out pointer to the output buffer; old buffer contents will be lost. - bool calc_gaps(rangeset_t *out) const { return calc_tinfo_gaps(out, typid); } - - /// Floating value or an object consisting of one floating member entirely - bool is_one_fpval(void) const { return get_onemember_type().is_floating(); } - - /// Is a SSE vector type? - bool is_sse_type(void) const { return get_tinfo_property(typid, GTA_IS_SSE_TYPE) != 0; } - - /// Is an anonymous struct/union? - /// We assume that types with names are anonymous if the name starts with $ - bool is_anonymous_udt(void) const { return get_tinfo_property(typid, GTA_IS_ANON_UDT) != 0; } - - /// Is a vftable type? - bool is_vftable(void) const { return get_tinfo_property(typid, GTA_IS_VFTABLE) != 0; } - - /// Has a vftable? - bool has_vftable(void) const { return get_tinfo_property(typid, GTA_HAS_VFTABLE) != 0; } - - /// Get enum base type (convert enum to integer type) - /// Returns ::BT_UNK if failed to convert - type_t get_enum_base_type(void) const { return (type_t)get_tinfo_property(typid, GTA_ENUM_BASE_TYPE); } - - /// For objects consisting of one member entirely: return type of the member - tinfo_t get_onemember_type(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_ONEMEM_TYPE); return r; } - - /// Calculate the type score (the higher - the nicer is the type) - uint32 calc_score(void) const { return score_tinfo(this); } - - /// Get a C-like string representation of the type. - /// \param out output string - /// \param name name of type - /// \param prtype_flags \ref PRTYPE_ - /// \param indent structure level indent - /// \param cmtindent comment indent - /// \param prefix string prepended to each line - /// \param cmt comment text - /// \return success - bool print( - qstring *out, - const char *name=NULL, - int prtype_flags=PRTYPE_1LINE, - int indent=0, - int cmtindent=0, - const char *prefix=NULL, - const char *cmt=NULL) const - { - return print_tinfo(out, prefix, indent, cmtindent, prtype_flags, this, name, cmt); - } - - /// Function to facilitate debugging - const char *dstr(void) const { return dstr_tinfo(this); } - - /// Get type attributes (all_attrs: include attributes of referenced types, if any) - bool get_attrs(type_attrs_t *tav, bool all_attrs=false) const { return get_tinfo_attrs(typid, tav, all_attrs); } - - /// Get a type attribute - bool get_attr(const qstring &key, bytevec_t *bv, bool all_attrs=true) const { return get_tinfo_attr(typid, key, bv, all_attrs); } - - /// Set type attributes. If necessary, a new typid will be created. - /// this function modifies tav! (returns old attributes, if any) - /// \return false: bad attributes - bool set_attrs(type_attrs_t *tav) { return set_tinfo_attrs(this, tav); } - - /// Set a type attribute. If necessary, a new typid will be created. - bool set_attr(const type_attr_t &ta, bool may_overwrite=true) { return set_tinfo_attr(this, ta, may_overwrite); } - - /// Del all type attributes. typerefs cannot be modified by this function. - void del_attrs(void) { set_tinfo_attrs(this, NULL); } - - /// Del a type attribute. typerefs cannot be modified by this function. - bool del_attr(const qstring &key, bool make_copy=true) { return del_tinfo_attr(this, key, make_copy); } - - bool create_simple_type(type_t decl_type) { return create_type(decl_type, BT_INT, NULL); } - bool create_ptr(const ptr_type_data_t &p, type_t decl_type=BT_PTR) { return create_type(decl_type, BT_PTR|BTM_VOLATILE, (void*)&p); } - bool create_array(const array_type_data_t &p, type_t decl_type=BT_ARRAY) { return create_type(decl_type, BT_ARRAY, (void*)&p); } - bool create_bitfield(const bitfield_type_data_t &p, type_t decl_type=BT_BITFIELD) { return create_type(decl_type, BT_BITFIELD, (void*)&p); } - bool create_typedef(const typedef_type_data_t &p, type_t decl_type=BTF_TYPEDEF, bool try_ordinal=true) - { - type_t bt2 = try_ordinal ? BTF_TYPEDEF : BTF_TYPEDEF|BTM_VOLATILE; - return create_type(decl_type, bt2, (void *)&p); - } - - /// \name Convenience functions - //@{ - inline bool create_ptr(const tinfo_t &tif, uchar bps=0, type_t decl_type=BT_PTR); - inline bool create_array(const tinfo_t &tif, uint32 nelems=0, uint32 base=0, type_t decl_type=BT_ARRAY); - inline void create_typedef(const til_t *til, const char *name, type_t decl_type=BTF_TYPEDEF, bool try_ordinal=true) { get_named_type(til, name, decl_type, false, try_ordinal); } - inline void create_typedef(const til_t *til, uint ord, type_t decl_type=BTF_TYPEDEF) { get_numbered_type(til, ord, decl_type, false); } - inline bool create_bitfield(uchar nbytes, uchar width, bool is_unsigned=false, type_t decl_type=BT_BITFIELD); - //@} - - /// \name Warning - /// These functions consume 'p' (make it empty) - //@{ - bool create_udt(udt_type_data_t &p, type_t decl_type) { return create_type(decl_type, BTF_STRUCT, &p); } - bool create_enum(enum_type_data_t &p, type_t decl_type=BTF_ENUM) { return create_type(decl_type, BTF_ENUM, &p); } - bool create_func(func_type_data_t &p, type_t decl_type=BT_FUNC) { return create_type(decl_type, BT_FUNC, &p); } - //@} - - /// \name Store type - /// Store the type info in the type library as a named or numbered type. - /// The tinfo_t object will be replaced by a reference to the created type. - /// Allowed bits for ntf_flags: #NTF_NOBASE, #NTF_REPLACE - //@{ - tinfo_code_t set_named_type(til_t *til, const char *name, int ntf_flags=0) { return save_tinfo(this, til, 0, name, ntf_flags|NTF_TYPE); } - tinfo_code_t set_symbol_type(til_t *til, const char *name, int ntf_flags=0) { return save_tinfo(this, til, 0, name, ntf_flags); } // NTF_SYMM and NTF_SYMU are permitted - tinfo_code_t set_numbered_type(til_t *til, uint32 ord, int ntf_flags=0, const char *name=NULL) { return save_tinfo(this, til, ord, name, ntf_flags); } - //@} - - /// Create a forward declaration. - /// decl_type: ::BTF_STRUCT, ::BTF_UNION, or ::BTF_ENUM - tinfo_code_t create_forward_decl(til_t *til, type_t decl_type, const char *name, int ntf_flags=0) - { - create_typedef(til, "", decl_type, false); - return set_named_type(til, name, ntf_flags); - } - - /// Get stock type information. - /// This function can be used to get tinfo_t for some common types. - /// The same tinfo_t will be returned for the same id, thus saving memory - /// and increasing the speed - /// Please note that retrieving the STI_SIZE_T or STI_SSIZE_T stock type, - /// will also have the side-effect of adding that type to the 'idati' TIL, - /// under the well-known name 'size_t' or 'ssize_t' (respectively). - static tinfo_t get_stock(stock_type_id_t id) { tinfo_t t; get_stock_tinfo(&t, id); return t; } - - /// Convert an array into a pointer. - /// type[] => type * - inline bool convert_array_to_ptr(void); - - /// Replace the current type with the ptr obj or array element. - /// This function performs one of the following conversions: - /// - type[] => type - /// - type* => type - /// If the conversion is performed successfully, return true - inline bool remove_ptr_or_array(void) - { - tinfo_t tif = get_ptrarr_object(); - if ( tif.empty() ) - return false; - swap(tif); - return true; - } - - /// Change the type sign. Works only for the types that may have sign - bool change_sign(type_sign_t sign) { return set_tinfo_property(this, STA_TYPE_SIGN, sign) != 0; } - - /// Calculate the udt alignments using the field offsets/sizes and the total udt size - /// This function does not work on typerefs - bool calc_udt_aligns(int sudt_flags=SUDT_GAPS) - { return set_tinfo_property(this, STA_UDT_ALIGN, sudt_flags) != 0; } - - /// \name Bitfields - /// Helper functions to store/extract bitfield values - //@{ - uint64 read_bitfield_value(uint64 v, int bitoff) const { return read_tinfo_bitfield_value(typid, v, bitoff); } - uint64 write_bitfield_value(uint64 dst, uint64 v, int bitoff) const { return write_tinfo_bitfield_value(typid, dst, v, bitoff); } - //@} - - /// \name Modifiers - /// Work with type modifiers: const and volatile - //@{ - type_t get_modifiers(void) const { return typid & TYPE_MODIF_MASK; } - void set_modifiers(type_t mod) { if ( !empty() ) typid = (typid & ~TYPE_MODIF_MASK) | (mod & TYPE_MODIF_MASK); } - void set_const(void) { if ( !empty() ) typid |= BTM_CONST; } - void set_volatile(void) { if ( !empty() ) typid |= BTM_VOLATILE; } - void clr_const(void) { typid &= ~BTM_CONST; } - void clr_volatile(void) { typid &= ~BTM_VOLATILE; } - void clr_const_volatile(void) { typid &= ~TYPE_MODIF_MASK; } - //@} - - DECLARE_COMPARISONS(tinfo_t) - { // simple comparison: good enough to organize std::map, etc - // for this function "unsigned char" and "uchar" are different - // for deeper comparison see compare_with() - return lexcompare_tinfo(typid, r.typid, 0); - } -/// \defgroup TCMP_ tinfo_t comparison flags -/// passed as 'tcflags' parameter to tinfo_t::compare_with() -//@{ -#define TCMP_EQUAL 0x0000 ///< are types equal? -#define TCMP_IGNMODS 0x0001 ///< ignore const/volatile modifiers -#define TCMP_AUTOCAST 0x0002 ///< can t1 be cast into t2 automatically? -#define TCMP_MANCAST 0x0004 ///< can t1 be cast into t2 manually? -#define TCMP_CALL 0x0008 ///< can t1 be called with t2 type? -#define TCMP_DELPTR 0x0010 ///< remove pointer from types before comparing -#define TCMP_DECL 0x0020 ///< compare declarations without resolving them -#define TCMP_ANYBASE 0x0040 ///< accept any base class when casting -#define TCMP_SKIPTHIS 0x0080 ///< skip the first function argument in comparison -//@} - /// Compare two types, based on given flags (see \ref TCMP_) - bool compare_with(const tinfo_t &r, int tcflags=0) const { return compare_tinfo(typid, r.typid, tcflags); } - bool equals_to(const tinfo_t &r) const { return compare_with(r, 0); } - bool is_castable_to(const tinfo_t &target) const { return compare_with(target, TCMP_AUTOCAST); } - bool is_manually_castable_to(const tinfo_t &target) const { return compare_with(target, TCMP_MANCAST); } -}; -DECLARE_TYPE_AS_MOVABLE(tinfo_t); -typedef qvector<tinfo_t> tinfovec_t; ///< vector of tinfo objects - -//------------------------------------------------------------------------ -/// SIMD type info -struct simd_info_t -{ - const char *name; ///< name of SIMD type (NULL-undefined) - tinfo_t tif; ///< SIMD type (empty-undefined) - uint16 size; ///< SIMD type size in bytes (0-undefined) - type_t memtype; ///< member type - ///< BTF_INT8/16/32/64/128, BTF_UINT8/16/32/64/128 - ///< BTF_INT - integrals of any size/sign - ///< BTF_FLOAT, BTF_DOUBLE - ///< BTF_TBYTE - floatings of any size - ///< BTF_UNION - union of integral and floating types - ///< BTF_UNK - undefined - - simd_info_t(const char *nm = NULL, uint16 sz = 0, type_t memt = BTF_UNK) - : name(nm), size(sz), memtype(memt) {} - - bool match_pattern(const simd_info_t *pattern) - { - if ( pattern == NULL ) - return true; - if ( pattern->size != 0 && pattern->size != size - || pattern->name != NULL && !streq(pattern->name, name) - || !pattern->tif.empty() && !pattern->tif.compare_with(tif) ) - { - return false; - } - if ( pattern->memtype == BTF_UNK || pattern->memtype == memtype ) - return true; - return pattern->memtype == BTF_TBYTE && is_type_float(memtype) - || pattern->memtype == BTF_INT && is_type_int(memtype); - } -}; -DECLARE_TYPE_AS_MOVABLE(simd_info_t); -typedef qvector<simd_info_t> simd_info_vec_t; - -//------------------------------------------------------------------------ -/// Use func_type_data_t::guess_cc() -idaman cm_t ida_export guess_func_cc( - const func_type_data_t &fti, - int npurged, - int cc_flags); -/// Use func_type_data_t::dump() -idaman bool ida_export dump_func_type_data( - qstring *out, - const func_type_data_t &fti, - int praloc_bits); - -//------------------------------------------------------------------------ -/// Pointer type information (see tinfo_t::get_ptr_details()) -struct ptr_type_data_t // #ptr -{ - tinfo_t obj_type; ///< pointed object type - tinfo_t closure; ///< cannot have both closure and based_ptr_size - uchar based_ptr_size; - uchar taptr_bits; ///< TAH bits - tinfo_t parent; ///< Parent struct - int32 delta; ///< Offset from the beginning of the parent struct - ptr_type_data_t( - tinfo_t c=tinfo_t(), - uchar bps=0, - tinfo_t p=tinfo_t(), - int32 d=0) - : closure(c), based_ptr_size(bps), taptr_bits(0), parent(p), delta(d) {} - DEFINE_MEMORY_ALLOCATION_FUNCS() - void swap(ptr_type_data_t &r) { qswap(*this, r); } ///< Set this = r and r = this - bool operator == (const ptr_type_data_t &r) const - { - return obj_type == r.obj_type - && closure == r.closure - && based_ptr_size == r.based_ptr_size; - } - bool operator != (const ptr_type_data_t &r) const { return !(*this == r); } - bool is_code_ptr(void) const { return obj_type.is_func(); } ///< Are we pointing to code? - bool is_shifted() const { return delta != 0; } -}; -DECLARE_TYPE_AS_MOVABLE(ptr_type_data_t); - -//------------------------------------------------------------------------ -/// Array type information (see tinfo_t::get_array_details()) -struct array_type_data_t // #array -{ - tinfo_t elem_type; ///< element type - uint32 base; ///< array base - uint32 nelems; ///< number of elements - array_type_data_t(size_t b=0, size_t n=0) : base(b), nelems(n) {} ///< Constructor - DEFINE_MEMORY_ALLOCATION_FUNCS() - void swap(array_type_data_t &r) { qswap(*this, r); } ///< set this = r and r = this -}; -DECLARE_TYPE_AS_MOVABLE(array_type_data_t); - -//------------------------------------------------------------------------- -/// Information about a single function argument -struct funcarg_t -{ - argloc_t argloc; ///< argument location - qstring name; ///< argument name (may be empty) - qstring cmt; ///< argument comment (may be empty) - tinfo_t type; ///< argument type - uint32 flags; ///< \ref FAI_ -/// \defgroup FAI_ Function argument property bits -/// used by funcarg_t::flags -//@{ -#define FAI_HIDDEN 0x0001 ///< hidden argument -#define FAI_RETPTR 0x0002 ///< pointer to return value. implies hidden -#define FAI_STRUCT 0x0004 ///< was initially a structure -#define FAI_ARRAY 0x0008 ///< was initially an array - ///< see "__org_typedef" or "__org_arrdim" type attributes - ///< to determine the original type -#define TA_ORG_TYPEDEF "__org_typedef" ///< the original typedef name (simple string) -#define TA_ORG_ARRDIM "__org_arrdim" ///< the original array dimension (pack_dd) -#define TA_FORMAT "format" ///< info about the 'format' argument - ///< 3 times pack_dd: - ///< \ref format_functype_t, - ///< argument number of 'format', - ///< argument number of '...' -//@} - funcarg_t(void) : flags(0) {} ///< Constructor - bool operator == (const funcarg_t &r) const - { - return argloc == r.argloc - && name == r.name -// && cmt == r.cmt - && type == r.type; - } - bool operator != (const funcarg_t &r) const { return !(*this == r); } -}; -DECLARE_TYPE_AS_MOVABLE(funcarg_t); -typedef qvector<funcarg_t> funcargvec_t; ///< vector of function argument objects - -/// Function type information (see tinfo_t::get_func_details()) -struct func_type_data_t : public funcargvec_t // #func -{ - int flags; ///< \ref FTI_ -/// \defgroup FTI_ Function type data property bits -/// used by func_type_data_t::flags -//@{ -#define FTI_SPOILED 0x0001 ///< information about spoiled registers is present -#define FTI_NORET 0x0002 ///< noreturn -#define FTI_PURE 0x0004 ///< __pure -#define FTI_HIGH 0x0008 ///< high level prototype (with possibly hidden args) -#define FTI_STATIC 0x0010 ///< static -#define FTI_VIRTUAL 0x0020 ///< virtual -#define FTI_CALLTYPE 0x00C0 ///< mask for FTI_*CALL -#define FTI_DEFCALL 0x0000 ///< default call -#define FTI_NEARCALL 0x0040 ///< near call -#define FTI_FARCALL 0x0080 ///< far call -#define FTI_INTCALL 0x00C0 ///< interrupt call -#define FTI_ARGLOCS 0x0100 ///< info about argument locations has been calculated - ///< (stkargs and retloc too) -#define FTI_ALL 0x01FF ///< all defined bits -//@} - tinfo_t rettype; ///< return type - argloc_t retloc; ///< return location - uval_t stkargs; ///< size of stack arguments (not used in build_func_type) - reginfovec_t spoiled; ///< spoiled register information. - ///< if spoiled register info is present, it overrides - ///< the standard spoil info (eax, edx, ecx for x86) - cm_t cc; ///< calling convention - func_type_data_t(): flags(0), stkargs(0), cc(0) {} - void swap(func_type_data_t &r) { qswap(*this, r); } - bool is_high(void) const { return (flags & FTI_HIGH) != 0; } - bool is_noret(void) const { return (flags & FTI_NORET) != 0; } - bool is_pure(void) const { return (flags & FTI_PURE) != 0; } - int get_call_method(void) const { return flags & FTI_CALLTYPE; } - cm_t get_cc(void) const - { - cm_t ret = ::get_cc(cc); - // if the calling convention is not specified, use the default one - if ( ret <= CM_CC_UNKNOWN ) - ret = ::get_cc(inf_get_cc_cm()); - return ret; - } - bool is_vararg_cc() const { return ::is_vararg_cc(cc); } - /// Guess function calling convention - /// use the following info: argument locations and 'stkargs' - cm_t guess_cc(int purged, int cc_flags) const - { - return guess_func_cc(*this, purged, cc_flags); - } -#define CC_CDECL_OK 0x01 ///< can use __cdecl calling convention? -#define CC_ALLOW_ARGPERM 0x02 ///< disregard argument order? -#define CC_ALLOW_REGHOLES 0x04 ///< allow holes in register argument list? -#define CC_HAS_ELLIPSIS 0x08 ///< function has a variable list of arguments? - /// Dump information that is not always visible in the function prototype. - /// (argument locations, return location, total stkarg size) - bool dump(qstring *out, int praloc_bits=PRALOC_STKOFF) const - { - return dump_func_type_data(out, *this, praloc_bits); - } -}; - -/// Function index for the 'format' attribute. -enum format_functype_t -{ - FMTFUNC_PRINTF, - FMTFUNC_SCANF, - FMTFUNC_STRFTIME, - FMTFUNC_STRFMON, -}; - -//------------------------------------------------------------------------- -/// Describes an enum value -struct enum_member_t -{ - qstring name; - qstring cmt; - uint64 value; - DEFINE_MEMORY_ALLOCATION_FUNCS() - bool operator == (const enum_member_t &r) const - { - return name == r.name -// && cmt == r.cmt - && value == r.value; - } - bool operator != (const enum_member_t &r) const { return !(*this == r); } - void swap(enum_member_t &r) { qswap(*this, r); } -}; -DECLARE_TYPE_AS_MOVABLE(enum_member_t); -typedef qvector<enum_member_t> enum_member_vec_t; ///< vector of enum values - -/// Enum type information (see tinfo_t::get_enum_details()) -struct enum_type_data_t : public enum_member_vec_t // #enum -{ - intvec_t group_sizes; ///< if present, specifies bitfield group sizes - ///< each group starts with a mask member - uint32 taenum_bits; ///< \ref tattr_enum - bte_t bte; ///< enum member sizes (shift amount) and style - enum_type_data_t(bte_t _bte=BTE_ALWAYS|BTE_HEX) : taenum_bits(0), bte(_bte) {} - DEFINE_MEMORY_ALLOCATION_FUNCS() - - bool is_64bit(void) const { return (taenum_bits & TAENUM_64BIT) != 0; } - bool is_hex(void) const { return (bte & BTE_OUT_MASK) == BTE_HEX; } - bool is_char(void) const { return (bte & BTE_OUT_MASK) == BTE_CHAR; } - bool is_sdec(void) const { return (bte & BTE_OUT_MASK) == BTE_SDEC; } - bool is_udec(void) const { return (bte & BTE_OUT_MASK) == BTE_UDEC; } - int calc_nbytes(void) const - { - int emsize = bte & BTE_SIZE_MASK; - return emsize != 0 ? 1 << (emsize-1) : inf_get_cc_size_e(); - } - uint64 calc_mask(void) const { return make_mask<uint64>(calc_nbytes()*8); } - void swap(enum_type_data_t &r) { qswap(*this, r); } ///< swap two instances -}; -DECLARE_TYPE_AS_MOVABLE(enum_type_data_t); - -//------------------------------------------------------------------------- -/// Type information for typedefs -struct typedef_type_data_t // #typedef -{ - const til_t *til; ///< type library to use when resolving - union - { - const char *name; ///< is_ordref=false: target type name. we do not own this pointer! - uint32 ordinal; ///< is_ordref=true: type ordinal number - }; - bool is_ordref; ///< is reference by ordinal? - bool resolve; ///< should resolve immediately? - typedef_type_data_t(const til_t *_til, const char *_name, bool _resolve=false) - : name(_name), is_ordref(false), resolve(_resolve) { til = _til == NULL ? get_idati() : _til; } - typedef_type_data_t(const til_t *_til, uint32 ord, bool _resolve=false) - : ordinal(ord), is_ordref(true), resolve(_resolve) { til = _til == NULL ? get_idati() : _til; } - DEFINE_MEMORY_ALLOCATION_FUNCS() - void swap(typedef_type_data_t &r) { qswap(*this, r); } -}; -DECLARE_TYPE_AS_MOVABLE(typedef_type_data_t); - -//------------------------------------------------------------------------- -/// An object to represent struct or union members -struct udt_member_t // #udm -{ - uint64 offset; ///< member offset in bits - uint64 size; ///< size in bits - qstring name; ///< member name - qstring cmt; ///< member comment - tinfo_t type; ///< member type - int effalign; ///< effective field alignment (in bytes) - uint32 tafld_bits; ///< TAH bits - uchar fda; ///< field alignment (shift amount) - udt_member_t(void) - : offset(0), size(0), effalign(0), tafld_bits(0), fda(0) - { - } - bool is_bitfield(void) const { return type.is_decl_bitfield(); } - bool is_zero_bitfield(void) const { return size == 0 && is_bitfield(); } - bool is_unaligned(void) const { return (tafld_bits & TAFLD_UNALIGNED) != 0; } - bool is_baseclass(void) const { return (tafld_bits & TAFLD_BASECLASS) != 0; } - bool is_virtbase(void) const { return (tafld_bits & TAFLD_VIRTBASE) != 0; } - bool is_vftable(void) const { return (tafld_bits & TAFLD_VFTABLE) != 0; } - void set_unaligned(void) { tafld_bits |= TAFLD_UNALIGNED; } - void set_baseclass(void) { tafld_bits |= TAFLD_BASECLASS; } - void set_virtbase(void) { tafld_bits |= TAFLD_VIRTBASE; } - void set_vftable(void) { tafld_bits |= TAFLD_VFTABLE; } - void clr_unaligned(void) { tafld_bits &= ~TAFLD_UNALIGNED; } - void clr_baseclass(void) { tafld_bits &= ~TAFLD_BASECLASS; } - void clr_virtbase(void) { tafld_bits &= ~TAFLD_VIRTBASE; } - void clr_vftable(void) { tafld_bits &= ~TAFLD_VFTABLE; } - uint64 begin(void) const { return offset; } - uint64 end(void) const { return offset + size; } - bool operator < (const udt_member_t &r) const - { - return offset < r.offset; - } - bool operator == (const udt_member_t &r) const - { - return offset == r.offset - && size == r.size - && name == r.name -// && cmt == r.cmt - && type == r.type - && fda == r.fda - && tafld_bits == r.tafld_bits - && effalign == r.effalign; - } - bool operator != (const udt_member_t &r) const { return !(*this == r); } - DEFINE_MEMORY_ALLOCATION_FUNCS() - void swap(udt_member_t &r) { qswap(*this, r); } - // the user cannot enter anonymous fields in ida (they can come only from tils), - // so we use the following trick: if the field type starts with $ and the name - // with __, then we consider the field as anonymous - bool is_anonymous_udm() const - { - return name[0] == '_' && name[1] == '_' && type.is_anonymous_udt(); - } -}; -DECLARE_TYPE_AS_MOVABLE(udt_member_t); -typedef qvector<udt_member_t> udtmembervec_t; ///< vector of udt member objects - - -/// An object to represent struct or union types (see tinfo_t::get_udt_details()) -struct udt_type_data_t : public udtmembervec_t // #udt -{ - size_t total_size; ///< total structure size in bytes - size_t unpadded_size; ///< unpadded structure size in bytes - uint32 effalign; ///< effective structure alignment (in bytes) - uint32 taudt_bits; ///< TA... and TAUDT... bits - uchar sda; ///< declared structure alignment (shift amount+1). 0 - unspecified - uchar pack; ///< #pragma pack() alignment (shift amount) - bool is_union; ///< is union or struct? - - udt_type_data_t(void) - : total_size(0), unpadded_size(0), effalign(0), - taudt_bits(0), sda(0), pack(0), - is_union(false) - { - } - void swap(udt_type_data_t &r) { qswap(*this, r); } - DEFINE_MEMORY_ALLOCATION_FUNCS() - bool is_unaligned(void) const { return (taudt_bits & TAUDT_UNALIGNED) != 0; } - bool is_msstruct(void) const { return (taudt_bits & TAUDT_MSSTRUCT) != 0; } - bool is_cppobj(void) const { return (taudt_bits & TAUDT_CPPOBJ) != 0; } - bool is_vftable(void) const { return (taudt_bits & TAUDT_VFTABLE) != 0; } - - bool is_last_baseclass(size_t idx) // we assume idx is valid - { - return at(idx).is_baseclass() - && (idx+1 == size() || !at(idx+1).is_baseclass()); - } -}; -DECLARE_TYPE_AS_MOVABLE(udt_type_data_t); - -// The type name of a virtual function table (__vftable) of a class is -// constructed by appending the following suffix to the class name. -// In the case of multiple inheritance we append the vft offset -// to the class name (with format %04X) -// Example: CLS_0024_vtbl is used for the vft located at the offset 0x24 of CLS - -#define VTBL_SUFFIX "_vtbl" - -// The member name of a virtual function table -// Complex cases are not handled yet. - -#define VTBL_MEMNAME "__vftable" - -//------------------------------------------------------------------------- -/// Bitfield type information (see tinfo_t::get_bitfield_details()) -struct bitfield_type_data_t // #bitfield -{ - uchar nbytes; ///< enclosing type size (1,2,4,8 bytes) - uchar width; ///< number of bits - bool is_unsigned; ///< is bitfield unsigned? - bitfield_type_data_t(uchar _nbytes=0, uchar _width=0, bool _is_unsigned=false) - : nbytes(_nbytes), width(_width), is_unsigned(_is_unsigned) - { - } - bool serialize(qtype *type, type_t mods) const; - DECLARE_COMPARISONS(bitfield_type_data_t) - { - if ( nbytes != r.nbytes ) - return nbytes > r.nbytes ? 1 : -1; - if ( width != r.width ) - return width > r.width ? 1 : -1; - if ( is_unsigned ) - { - if ( !r.is_unsigned ) - return 1; - } - else - { - if ( r.is_unsigned ) - return -1; - } - return 0; - } - void swap(bitfield_type_data_t &r) { qswap(*this, r); } -}; -DECLARE_TYPE_AS_MOVABLE(bitfield_type_data_t); - -//-------------------------------------------------------------------------- -// This tag can be used at the beginning of -// udt_member_t::cmt -// funcarg_t::cmt -// enum_member_t::cmt -// to specify the line number where it is defined. -// Example: "\x05123." means the line number 123 -#define TPOS_LNNUM "\x05" - -//------------------------------------------------------------------------- -// return argument alignment (which depends on ABI and natural type alignment) -inline int get_arg_align(int type_align, int slotsize) -{ - if ( type_align > slotsize*2 && !inf_huge_arg_align() ) - type_align = slotsize*2; - return type_align < slotsize - ? inf_pack_stkargs() ? type_align : slotsize - : inf_big_arg_align() ? type_align : slotsize; -} - -inline int get_arg_align(const tinfo_t &tif, int slotsize) -{ - uint32 align = 0; - tif.get_size(&align); - return get_arg_align(align, slotsize); -} - -inline sval_t align_stkarg_up(sval_t spoff, int type_align, int slotsize) -{ - uint32 align = get_arg_align(type_align, slotsize); - return align_up(spoff, align); -} - -inline sval_t align_stkarg_up(sval_t spoff, const tinfo_t &tif, int slotsize) -{ - uint32 align = get_arg_align(tif, slotsize); - return align_up(spoff, align); -} - -inline bool argloc_t::has_reg() const -{ - if ( !is_scattered() ) - return is_reg(); - for ( const auto &part : scattered() ) - if ( part.is_reg() ) - return true; - return false; -}; - -inline bool argloc_t::has_stkoff() const -{ - if ( !is_scattered() ) - return is_stkoff(); - for ( const auto &part : scattered() ) - if ( part.is_stkoff() ) - return true; - return false; -}; - -inline bool argloc_t::is_mixed_scattered() const -{ - if ( !is_scattered() ) - return false; - bool reg_found = false; - bool stkoff_found = false; - for ( const auto &part : scattered() ) - { - if ( part.is_reg() ) - reg_found = true; - if ( part.is_stkoff() ) - stkoff_found = true; - } - return reg_found && stkoff_found; -}; - -inline bool tinfo_t::get_named_type( - const til_t *til, - const char *name, - type_t decl_type, - bool resolve, - bool try_ordinal) -{ - typedef_type_data_t tp(til, name, resolve); - return create_typedef(tp, decl_type, try_ordinal); -} - -inline bool tinfo_t::get_numbered_type( - const til_t *til, - uint32 ordinal, - type_t decl_type, - bool resolve) -{ - typedef_type_data_t tp(til, ordinal, resolve); - return create_typedef(tp, decl_type, false); -} - -inline bool tinfo_t::create_ptr( - const tinfo_t &tif, - uchar bps, - type_t decl_type) -{ - ptr_type_data_t pi(tinfo_t(), bps); - pi.obj_type = tif; - return create_ptr(pi, decl_type); -} - -inline bool tinfo_t::create_array( - const tinfo_t &tif, - uint32 nelems, - uint32 base, - type_t decl_type) -{ - array_type_data_t ai(base, nelems); - ai.elem_type = tif; - return create_array(ai, decl_type); -} - -inline bool tinfo_t::create_bitfield( - uchar nbytes, - uchar width, - bool _is_unsigned, - type_t decl_type) -{ - bitfield_type_data_t bi(nbytes, width, _is_unsigned); - return create_bitfield(bi, decl_type); -} - -inline bool tinfo_t::convert_array_to_ptr(void) -{ - bool ok = false; - array_type_data_t ai; - if ( get_array_details(&ai) ) - { - ptr_type_data_t pi; - pi.obj_type.swap(ai.elem_type); - create_ptr(pi); - ok = true; - } - return ok; -} - -/// ::BT_PTR: If the current type is a pointer, return the pointed object. -/// If the current type is not a pointer, return the current type. -/// See also get_ptrarr_object() and get_pointed_object() -inline tinfo_t remove_pointer(const tinfo_t &tif) -{ - tinfo_t r; - r.typid = get_tinfo_property(tif.typid, tinfo_t::GTA_SAFE_PTR_OBJ); - return r; -} - -/// Information about how to modify the current type, used by ::tinfo_visitor_t. -struct type_mods_t -{ - tinfo_t type; ///< current type - qstring name; ///< current type name - qstring cmt; ///< comment for current type - int flags; ///< \ref TVIS_ -/// \defgroup TVIS_ Type modification bits -/// used by type_mods_t::flags -//@{ -#define TVIS_TYPE 0x0001 ///< new type info is present -#define TVIS_NAME 0x0002 ///< new name is present -#define TVIS_CMT 0x0004 ///< new comment is present -//@} - type_mods_t(void) : flags(0) {} - void clear(void) { flags = 0; } - - /// The visit_type() function may optionally save the modified type info. - /// Use the following functions for that. The new name and comment will be applied - /// only if the current tinfo element has storage for them. - void set_new_type(const tinfo_t &t) { type = t; flags |= TVIS_TYPE; } - void set_new_name(const qstring &n) { name = n; flags |= TVIS_NAME; } - void set_new_cmt(const qstring &c) { cmt = c; flags |= TVIS_CMT; } - - bool has_type(void) const { return (flags & TVIS_TYPE) != 0; } - bool has_name(void) const { return (flags & TVIS_NAME) != 0; } - bool has_cmt(void) const { return (flags & TVIS_CMT) != 0; } - bool has_info(void) const { return flags != 0; } -}; - -/// Visit all subtypes of a type. Derive your visitor from this class and use apply_to() -struct tinfo_visitor_t -{ - int state; ///< \ref TVST_ -/// \defgroup TVST_ tinfo visitor states -/// used by tinfo_visitor_t::state -//@{ -#define TVST_PRUNE 0x01 ///< don't visit children of current type -#define TVST_DEF 0x02 ///< visit type definition (meaningful for typerefs) -#define TVST_LEVEL 0x04 // has level member (internal use) -//@} - int level; // recursion level (internal use) - tinfo_visitor_t(int s=0) : state(s|TVST_LEVEL), level(0) {} - - DEFINE_VIRTUAL_DTOR(tinfo_visitor_t) - - /// Visit a subtype. - /// this function must be implemented in the derived class. - /// it may optionally fill out with the new type info. this can be used to - /// modify types (in this case the 'out' argument of apply_to() may not be NULL) - /// return 0 to continue the traversal. - /// return !=0 to stop the traversal. - virtual int idaapi visit_type( - type_mods_t *out, - const tinfo_t &tif, - const char *name, - const char *cmt) = 0; - - /// To refuse to visit children of the current type, use this: - void prune_now(void) { state |= TVST_PRUNE; } - - /// Call this function to initiate the traversal - int apply_to(const tinfo_t &tif, type_mods_t *out=NULL, const char *name=NULL, const char *cmt=NULL) - { - return visit_subtypes(this, out, tif, name, cmt); - } -}; - - -//------------------------------------------------------------------------ -// Definitions for packing/unpacking idc objects - -/// Object that represents a register -struct regobj_t -{ - int regidx; ///< index into dbg->registers - int relocate; ///< 0-plain num, 1-must relocate - bytevec_t value; - size_t size(void) const { return value.size(); } -}; -DECLARE_TYPE_AS_MOVABLE(regobj_t); -typedef qvector<regobj_t> regobjvec_t; - -struct regobjs_t : public regobjvec_t {}; /// Collection of register objects - - -/// Read a typed idc object from the database - -idaman error_t ida_export unpack_idcobj_from_idb( - idc_value_t *obj, - const tinfo_t &tif, - ea_t ea, - const bytevec_t *off0, // if !NULL: bytevec that represents object at 'ea' - int pio_flags=0); -#define PIO_NOATTR_FAIL 0x0004 ///< missing attributes are not ok -#define PIO_IGNORE_PTRS 0x0008 ///< do not follow pointers - - -/// Read a typed idc object from the byte vector - -idaman error_t ida_export unpack_idcobj_from_bv( - idc_value_t *obj, - const tinfo_t &tif, - const bytevec_t &bytes, - int pio_flags=0); - - -/// Write a typed idc object to the database - -idaman error_t ida_export pack_idcobj_to_idb( - const idc_value_t *obj, - const tinfo_t &tif, - ea_t ea, - int pio_flags=0); - - -/// Write a typed idc object to the byte vector. -/// Byte vector may be non-empty, this function will append data to it - -idaman error_t ida_export pack_idcobj_to_bv( - const idc_value_t *obj, - const tinfo_t &tif, - relobj_t *bytes, - void *objoff, // NULL - append object to 'bytes' - // if not NULL: - // in: int32*: offset in 'bytes' for the object - // -1 means 'do not store the object itself in bytes - // store only pointed objects' - // out: data for object (if *(int32*)objoff == -1) - int pio_flags=0); - - -/// Helper function for the processor modules. -/// to be called from \ph{use_stkarg_type} - -idaman bool ida_export apply_tinfo_to_stkarg( - const insn_t &insn, - const op_t &x, - uval_t v, - const tinfo_t &tif, - const char *name); - -//------------------------------------------------------------------------ -// Helper struct for the processor modules: process call arguments -struct argtinfo_helper_t -{ - size_t reserved = 0; - - virtual ~argtinfo_helper_t() {} - - /// Set the operand type as specified - virtual bool idaapi set_op_tinfo( - const insn_t &insn, - const op_t &x, - const tinfo_t &tif, - const char *name) = 0; - - /// Is the current insn a stkarg load?. - /// if yes: - /// - src: index of the source operand in \insn_t{ops} - /// - dst: index of the destination operand in \insn_t{ops} - /// \insn_t{ops}[dst].addr is expected to have the stack offset - virtual bool idaapi is_stkarg_load(const insn_t &insn, int *src, int *dst) = 0; - - /// The call instruction with a delay slot?. - virtual bool idaapi has_delay_slot(ea_t /*caller*/) { return false; } - - /// This function is to be called by the processor module in response - /// to ev_use_arg_types. - inline void use_arg_tinfos(ea_t caller, func_type_data_t *fti, funcargvec_t *rargs); -}; - -/// Do not call this function directly, use argtinfo_helper_t -idaman void ida_export gen_use_arg_tinfos2( - struct argtinfo_helper_t *_this, - ea_t caller, - func_type_data_t *fti, - funcargvec_t *rargs); - -inline void argtinfo_helper_t::use_arg_tinfos( - ea_t caller, - func_type_data_t *fti, - funcargvec_t *rargs) -{ - gen_use_arg_tinfos2(this, caller, fti, rargs); -} - -//------------------------------------------------------------------------- - -/// Looks for a hole at the beginning of the stack arguments. Will make use -/// of the IDB's func_t function at that place (if present) to help determine -/// the presence of such a hole. - -idaman bool ida_export func_has_stkframe_hole(ea_t ea, const func_type_data_t &fti); - -//------------------------------------------------------------------------- -/// Interface class - see ::ida_lowertype_helper_t -class lowertype_helper_t -{ -public: - virtual bool idaapi func_has_stkframe_hole( - const tinfo_t &candidate, - const func_type_data_t &candidate_data) = 0; - - virtual int idaapi get_func_purged_bytes( - const tinfo_t &candidate, - const func_type_data_t &candidate_data) = 0; -}; - -//------------------------------------------------------------------------- -/// An implementation of ::lowertype_helper_t that has access to the -/// IDB, and thus can help spot holes in the stack arguments. -class ida_lowertype_helper_t : public lowertype_helper_t -{ - const tinfo_t &tif; - ea_t ea; - int purged_bytes; - -public: - ida_lowertype_helper_t(const tinfo_t &_tif, ea_t _ea, int _pb) - : tif(_tif), ea(_ea), purged_bytes(_pb) {} - - virtual bool idaapi func_has_stkframe_hole( - const tinfo_t &candidate, - const func_type_data_t &candidate_data) override - { - return candidate == tif - ? ::func_has_stkframe_hole(ea, candidate_data) - : false; - } - - virtual int idaapi get_func_purged_bytes( - const tinfo_t &candidate, - const func_type_data_t &) override - { - return candidate == tif - ? purged_bytes - : -1; - } -}; - -//------------------------------------------------------------------------- -/// Lower type. -/// Inspect the type and lower all function subtypes using lower_func_type(). \n -/// We call the prototypes usually encountered in source files "high level" \n -/// They may have implicit arguments, array arguments, big structure retvals, etc \n -/// We introduce explicit arguments (i.e. 'this' pointer) and call the result \n -/// "low level prototype". See #FTI_HIGH. -/// -/// In order to improve heuristics for recognition of big structure retvals, \n -/// it is recommended to pass a helper that will be used to make decisions. \n -/// That helper will be used only for lowering 'tif', and not for the children \n -/// types walked through by recursion. -/// \retval 1 removed #FTI_HIGH, -/// \retval 2 made substantial changes -/// \retval -1 failure - -idaman int ida_export lower_type( - til_t *til, - tinfo_t *tif, - const char *name=NULL, - lowertype_helper_t *_helper=NULL); - - -/// Replace references to ordinal types by name references. -/// This function 'unties' the type from the current local type library -/// and makes it easier to export it. -/// \param til type library to use. may be NULL. -/// \param tif type to modify (in/out) -/// \retval number of replaced subtypes, -1 on failure - -idaman int ida_export replace_ordinal_typerefs(til_t *til, tinfo_t *tif); - - -/// See begin_type_updating() -enum update_type_t -{ - UTP_ENUM, - UTP_STRUCT, -}; - -/// Mark the beginning of a large update operation on the types. -/// Can be used with add_enum_member(), add_struc_member, etc... -/// Also see end_type_updating() - -idaman void ida_export begin_type_updating(update_type_t utp); - - -/// Mark the end of a large update operation on the types (see begin_type_updating()) - -idaman void ida_export end_type_updating(update_type_t utp); - -//-------------------------------------------------------------------------- -/// See format_cdata() -struct format_data_info_t -{ - int ptvf; /// \ref PTV_ -/// \defgroup PTV_ C data formatting properties -/// used by format_data_info_t::ptvf -//@{ -#define PTV_DEREF 0x0001 ///< take value to print from the debugged process. - ///< #VT_LONG: the address is specified by idc_value_t::num - ///< #VT_PVOID: argloc_t is pointed by idc_value_t::pvoid -#define PTV_QUEST 0x0002 ///< print '?' for uninited data -#define PTV_EMPTY 0x0004 ///< return empty string for uninited data - ///< should not specify PTV_QUEST and PTV_EMPTY together -#define PTV_CSTR 0x0008 ///< print constant strings inline -#define PTV_EXPAND 0x0010 ///< print only top level on separate lines - ///< max_length applies to separate lines - ///< margin is ignored -#define PTV_LZHEX 0x0020 ///< print hex numbers with leading zeroes -#define PTV_STPFLT 0x0040 ///< fail on bad floating point numbers - ///< (if not set, just print ?flt for them) -#define PTV_SPACE 0x0080 ///< add spaces after commas and around braces -#define PTV_DEBUG 0x0100 ///< format output for debugger -#define PTV_NOPTR 0x0200 ///< prevent pointer values from appearing in the output -#define PTV_NTOP 0x40000000 ///< internal flag, do not use -#define PTV_KEEP 0x80000000 ///< internal flag, do not use -//@} - int radix; ///< number representation (8,10,16) - int max_length; ///< max length of the formatted text (0 means no limit) - ///< should be used to format huge arrays for the screen, - ///< we cannot display the whole array anyway - ///< if this limit is hit, the function returns false - ///< and qerrno is set to eMaxLengthExceeded - int arrbase; ///< for arrays: the first element of array to print - int arrnelems; ///< for arrays: number of elements to print - int margin; ///< length of one line (0 means to print everything on one line) - ///< if an item cannot be printed in a shorter way, - ///< some output lines can be considerably longer - ///< 1 means each item on its own line - int indent; ///< how many spaces to use to indent nested structures/arrays - - format_data_info_t(void) - : ptvf(PTV_EMPTY|PTV_CSTR|PTV_SPACE), radix(10), max_length(0), - arrbase(0), arrnelems(0), - margin(80), indent(2) {} -}; - -/// Additional information about the output lines -struct valinfo_t -{ - argloc_t loc; - qstring label; - tinfo_t type; - valinfo_t(argloc_t l=argloc_t(), const char *name=NULL, const tinfo_t &tif=tinfo_t()) - : loc(l), label(name), type(tif) {} - void swap(valinfo_t &r) - { - loc.swap(r.loc); - label.swap(r.label); - type.swap(r.type); - } - DEFINE_MEMORY_ALLOCATION_FUNCS() -}; -DECLARE_TYPE_AS_MOVABLE(valinfo_t); - - -/// Text representation of a data value (value string). -/// This structure is used before we decide how to represent it, -/// on one line or on many lines -class valstr_t -{ -public: - qstring oneline; ///< result if printed on one line in UTF-8 encoding - size_t length; ///< length if printed on one line - struct valstrs_t *members; ///< strings for members, each member separately - valinfo_t *info; ///< additional info - int props; ///< temporary properties, used internally -#define VALSTR_OPEN 0x01 ///< printed opening curly brace '{' - - valstr_t(void) : length(0), members(NULL), info(NULL), props(0) {} - ~valstr_t(void); - DEFINE_MEMORY_ALLOCATION_FUNCS() -private: - struct flatten_args_t - { - const valstr_t *may_not_collapse; - int ptvf; - int max_length; - int margin; - int indent; - }; - friend struct valstr_sink_t; - void update_length(int ptvf); - void set_oneline(const char *line, int len) - { - oneline.append(line, len); - length = oneline.length(); - } - void consume_oneline(const qstring &line) - { - oneline.append(line); - length = oneline.length(); - } - bool append_char(char c, int max_length); - bool convert_to_one_line(int ptvf, int max_length); - bool flatten(const flatten_args_t &flargs, int level); -}; -DECLARE_TYPE_AS_MOVABLE(valstr_t); -typedef qvector<valstr_t> valstrvec_t; - -struct valstrs_t : public valstrvec_t {}; ///< Collection of value strings - -inline valstr_t::~valstr_t(void) -{ - delete members; - delete info; -} - - -/// Format a data value as a C initializer. -/// \param outvec buffer for the formatted string(s). may be NULL -/// \param idc_value value to format -/// \param tif type of the data to format. -/// if NULL and #PTV_DEREF is specified, take tinfo from idb -/// \param vtree more detailed output info -/// \param fdi formatting options -/// \return success. if failed, see qerrno for more info - -idaman bool ida_export format_cdata( - qstrvec_t *outvec, - const idc_value_t &idc_value, - const tinfo_t *tif, - valstr_t *vtree=NULL, - const format_data_info_t *fdi=NULL); - -/// Flush formatted text -struct text_sink_t -{ - /// \return 0-ok, otherwise print_cdata will stop - virtual int idaapi print(const char *str) = 0; -}; - - -/// The same as format_cdata(), but instead of returning the answer in a vector, print it. -/// This function can handle very huge data volume without using too much memory. -/// As soon as the output text becomes too long, the function prints it and -/// flushes its internal buffers. -/// \retval 0 ok -/// \retval -1 printing failed, check qerrno -/// \retval else code returned by text_sink_t::print() - -idaman int ida_export print_cdata( - text_sink_t &printer, - const idc_value_t &idc_value, - const tinfo_t *tif, - const format_data_info_t *fdi=NULL); - -//------------------------------------------------------------------------- -#define PDF_INCL_DEPS 0x1 ///< Include all type dependencies -#define PDF_DEF_FWD 0x2 ///< Allow forward declarations -#define PDF_DEF_BASE 0x4 ///< Include base types: __int8, __int16, etc.. -#define PDF_HEADER_CMT 0x8 ///< Prepend output with a descriptive comment - -typedef qvector<uint32> ordvec_t; - -/// Print types (and possibly their dependencies) in a format suitable -/// for use in a header file. This is the reverse parse_decls(). -/// \param printer a handler for printing text -/// \param til the type library holding the ordinals -/// \param ordinals ordinals of types to export. NULL means: all ordinals in til -/// \param flags flags for the algorithm. A combination of PDF_* constants -/// \retval >0 the number of types exported -/// \retval 0 an error occurred -/// \retval <0 the negated number of types exported. There were minor errors -/// and the resulting output might not be compilable. - -idaman int ida_export print_decls( - text_sink_t &printer, - til_t *til, - const ordvec_t *ordinals, - uint32 flags); - - -/// Calculate max number of lines of a formatted c data, when expanded (#PTV_EXPAND). -/// \param loc location of the data (::ALOC_STATIC or ::ALOC_CUSTOM) -/// \param tif type info -/// \param dont_deref_ptr consider 'ea' as the ptr value -/// \retval 0 data is not expandable -/// \retval -1 error, see qerrno -/// \retval else the max number of lines - -idaman int ida_export calc_number_of_children( - const argloc_t &loc, - const tinfo_t &tif, - bool dont_deref_ptr=false); - - -/// Format a C number. -/// \param buf output buffer -/// \param bufsize size of the output buffer -/// \param value number to format -/// \param size size of the number in bytes (1,2,4,8,16) -/// \param pcn combination of \ref PCN_ - -idaman size_t ida_export format_c_number( - char *buf, - size_t bufsize, - uint128 value, - int size, - int pcn=0); - -/// \defgroup PCN_ C Number formatting flags -/// passed as 'pcn' parameter to format_c_number() -//@{ -#define PCN_RADIX 0x07 ///< number base to use -#define PCN_DEC 0x00 ///< decimal -#define PCN_HEX 0x01 ///< hexadecimal -#define PCN_OCT 0x02 ///< octal -#define PCN_CHR 0x03 ///< character -#define PCN_UNSIGNED 0x08 ///< add 'u' suffix -#define PCN_LZHEX 0x10 ///< print leading zeroes for hexdecimal number -#define PCN_NEGSIGN 0x20 ///< print negated value (-N) for negative numbers -#define PCN_DECSEXT 0x40 ///< automatically extend sign of signed decimal numbers -//@} - - -/// Return a C expression that can be used to represent an enum member. -/// If the value does not correspond to any single enum member, this function tries -/// to find a bitwise combination of enum members that correspond to it. -/// If more than half of value bits do not match any enum members, it fails. -/// \param buf output buffer -/// \param tif enumeration type -/// \param serial which enumeration member to use (0 means the first with the given value) -/// \param value value to search in the enumeration type. only 32-bit number can be handled yet -/// \return success - -idaman bool ida_export get_enum_member_expr( - qstring *buf, - const tinfo_t &tif, - int serial, - uint64 value); - -inline bool idaapi is_autosync(const char *name, const tinfo_t &tif) -{ - type_t decl_type = tif.get_decltype(); - return get_ordinal_from_idb_type(name, &decl_type) != -1; -} - -//------------------------------------------------------------------------- -// Dialogs to choose a symbol from a type library -//------------------------------------------------------------------------ - -/// A symbol in a type library -struct til_symbol_t -{ - const char *name; ///< symbol name - const til_t *til; ///< pointer to til - til_symbol_t(const char *n = NULL, const til_t *t = NULL): name(n), til(t) {} -}; -DECLARE_TYPE_AS_MOVABLE(til_symbol_t); - - -/// Helper class for choose_named_type(). -/// Controls which types are displayed when choosing types. - -struct predicate_t -{ - virtual bool idaapi should_display( - const til_t *til, - const char *name, - const type_t *type, - const p_list *fields) = 0; - DEFINE_VIRTUAL_DTOR(predicate_t) -}; - - -/// Choose a type from a type library. -/// \param out_sym pointer to be filled with the chosen type -/// \param root_til pointer to starting til (the function will inspect the base tils if allowed by flags) -/// \param title title of listbox to display -/// \param ntf_flags combination of \ref NTF_ -/// \param predicate predicate to select types to display (maybe NULL) -/// \return false if nothing is chosen, otherwise true - -idaman bool ida_export choose_named_type( - til_symbol_t *out_sym, - const til_t *root_til, - const char *title, - int ntf_flags, - predicate_t *predicate=NULL); - - -/// Controls which types are displayed/selected when choosing local types. -/// \retval 0 skip type -/// \retval 1 include - -typedef int idaapi local_tinfo_predicate_t(uint32 ord, const tinfo_t &type, void *ud); - - -/// Choose a type from the local type library. -/// \param ti pointer to til -/// \param title title of listbox to display -/// \param func predicate to select types to display (maybe NULL) -/// \param def_ord ordinal to position cursor before choose -/// \param ud user data -/// \return == 0 means nothing is chosen, otherwise an ordinal number - -idaman uint32 ida_export choose_local_tinfo( - const til_t *ti, - const char *title, - local_tinfo_predicate_t *func = NULL, - uint32 def_ord = 0, - void *ud = NULL); - - -/// Choose a type from the local type library and specify the pointer shift value. -/// \param delta pointer shift value -/// \param ti pointer to til -/// \param title title of listbox to display -/// \param func predicate to select types to display (maybe NULL) -/// \param def_ord ordinal to position cursor before choose -/// \param ud user data -/// \return == 0 means nothing is chosen, otherwise an ordinal number - -idaman uint32 ida_export choose_local_tinfo_and_delta( - int32 *delta, - const til_t *ti, - const char *title, - local_tinfo_predicate_t *func = NULL, - uint32 def_ord = 0, - void *ud = NULL); - - -#ifndef NO_OBSOLETE_FUNCS -typedef bool idaapi set_op_tinfo_t(const insn_t &insn, const op_t &x, const tinfo_t &type, const char *name); -typedef bool idaapi is_stkarg_load_t(const insn_t &insn, int *src, int *dst); -typedef bool idaapi has_delay_slot_t(ea_t caller); -idaman DEPRECATED void ida_export gen_use_arg_tinfos(ea_t caller, func_type_data_t *fti, funcargvec_t *rargs, set_op_tinfo_t *set_optype, is_stkarg_load_t *is_stkarg_load, has_delay_slot_t *has_delay_slot); // gen_use_arg_tinfos2 -#endif - -#endif // _TYPEINF_HPP diff --git a/idasdk75/include/ua.hpp b/idasdk75/include/ua.hpp deleted file mode 100644 index 0caabca..0000000 --- a/idasdk75/include/ua.hpp +++ /dev/null @@ -1,1475 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _UA_HPP -#define _UA_HPP - -#include <kernwin.hpp> // for btoa() -#include <lines.hpp> // for colors -#include <xref.hpp> // add_cref() -#include <bytes.hpp> // get_byte(), ... - -/*! \file ua.hpp - - \brief Functions that deal with the disassembling of program instructions. - - There are 2 kinds of functions: - - functions that are called from the kernel - to disassemble an instruction. These functions - call IDP module for it. - - functions that are called from IDP module to - disassemble an instruction. We will call them - 'helper functions'. - - Disassembly of an instruction is made in three steps: - -# analysis: ana.cpp - -# emulation: emu.cpp - -# conversion to text: out.cpp - - The kernel calls the IDP module to perform these steps. - At first, the kernel always calls the analysis. The analyzer - must decode the instruction and fill the insn_t instance - that it receives through its callback. - It must not change anything in the database. - - The second step, the emulation, is called for each instruction. - This step must make necessary changes to the database, - plan analysis of subsequent instructions, track register - values, memory contents, etc. Please keep in mind that the kernel may call - the emulation step for any address in the program - there is no - ordering of addresses. Usually, the emulation is called - for consecutive addresses but this is not guaranteed. - - The last step, conversion to text, is called each time an instruction - is displayed on the screen. The kernel will always call the analysis step - before calling the text conversion step. - The emulation and the text conversion steps should use the information stored - in the insn_t instance they receive. They should not access the bytes - of the instruction and decode it again - this should only be done in - the analysis step. -*/ - -struct procmod_t; -struct processor_t; -struct asm_t; - -/// \defgroup operands Operands -/// Work with instruction operands - -//-------------------------------------------------------------------------- -// T Y P E O F O P E R A N D -//-------------------------------------------------------------------------- -typedef uchar optype_t; ///< see \ref o_ -/// \defgroup o_ Operand types -/// \ingroup operands -/// -/// Various types of instruction operands. -/// The kernel already knows about some operand types and associates them -/// with fields in ::op_t. -/// -/// IDA also allows you define processor specific operand types (o_idpspec...). -/// You are free to give any meaning to these types. We suggest you to create a -/// #define to use mnemonic names. However, don't forget that the kernel will -/// know nothing about operands of those types. -/// You may use any additional fields of ::op_t to store -/// processor specific operand information. -//@{ -const optype_t - o_void = 0, ///< No Operand. - o_reg = 1, ///< General Register (al,ax,es,ds...). - o_mem = 2, ///< Direct Memory Reference (DATA). - o_phrase = 3, ///< Memory Ref [Base Reg + Index Reg]. - o_displ = 4, ///< Memory Ref [Base Reg + Index Reg + Displacement]. - o_imm = 5, ///< Immediate Value. - o_far = 6, ///< Immediate Far Address (CODE). - o_near = 7, ///< Immediate Near Address (CODE). - o_idpspec0 = 8, ///< processor specific type. - o_idpspec1 = 9, ///< processor specific type. - o_idpspec2 = 10, ///< processor specific type. - o_idpspec3 = 11, ///< processor specific type. - o_idpspec4 = 12, ///< processor specific type. - o_idpspec5 = 13; ///< processor specific type. - ///< (there can be more processor specific types) -//@} - -/// \var o_reg -/// The register number should be stored in op_t::reg. -/// All processor registers, including special registers, can be -/// represented by this operand type. -/// -/// \var o_mem -/// A direct memory data reference whose target address is known at compilation time. -/// The target virtual address is stored in op_t::addr and the full address -/// is calculated as to_ea( \insn_t{cs}, op_t::addr ). For the processors with -/// complex memory organization the final address can be calculated -/// using other segment registers. For flat memories, op_t::addr is the final -/// address and \insn_t{cs} is usually equal to zero. In any case, the address -/// within the segment should be stored in op_t::addr. -/// -/// \var o_phrase -/// A memory reference using register contents. Indexed, register based, -/// and other addressing modes can be represented with the operand type. -/// This addressing mode cannot contain immediate values (use ::o_displ instead). -/// The phrase number should be stored in op_t::phrase. To denote the pre-increment -/// and similar features please use additional operand fields like op_t::specflag... -/// Usually op_t::phrase contains the register number and additional information -/// is stored in op_t::specflags... Please note that this operand type cannot -/// contain immediate values (except the scaling coefficients). -/// -/// \var o_displ -/// A memory reference using register contents with displacement. -/// The displacement should be stored in the op_t::addr field. The rest of information -/// is stored the same way as in ::o_phrase. -/// -/// \var o_imm -/// Any operand consisting of only a number is represented by this operand type. -/// The value should be stored in op_t::value. You may sign extend short (1-2 byte) values. -/// In any case don't forget to specify op_t::dtype (should be set for all operand types). -/// -/// \var o_far -/// If the current processor has a special addressing mode for inter-segment -/// references, then this operand type should be used instead of ::o_near. -/// If you want, you may use #PR_CHK_XREF in \ph{flag} to disable inter-segment -/// calls if ::o_near operand type is used. Currently only IBM PC uses this flag. -/// -/// \var o_near -/// A direct memory code reference whose target address is known at the compilation time. -/// The target virtual address is stored in op_t::addr and the final address -/// is always to_ea(\insn_t{cs}, op_t::addr). Usually this operand type is used for -/// the branches and calls whose target address is known. If the current -/// processor has 2 different types of references for inter-segment and intra-segment -/// references, then this should be used only for intra-segment references. -/// -/// If the above operand types do not cover all possible addressing modes, -/// then use o_idpspec... operand types. - -//-------------------------------------------------------------------------- -// O P E R A N D O F I N S T R U C T I O N -//-------------------------------------------------------------------------- -/// \defgroup operands_t Operand structure -/// \ingroup operands -/// Definition of ::op_t and related items. - -/// Operand of an instruction. \ingroup operands_t -/// This structure is filled by the analyzer. -/// Upon entrance to the analyzer, some fields of this structure are initialized: -/// - #type: ::o_void -/// - #offb: 0 -/// - #offo: 0 -/// - #flags: #OF_SHOW -class op_t -{ -public: - - /// Number of operand (0,1,2). Initialized once at the start of work. - /// You have no right to change its value. - uchar n; - - /// Type of operand (see \ref o_) - optype_t type; - - /// Offset of operand value from the instruction start (0 means unknown). - /// Of course this field is meaningful only for certain types of operands. - /// Leave it equal to zero if the operand has no offset. - /// This offset should point to the 'interesting' part of operand. - /// For example, it may point to the address of a function in - /// \v{call func} - /// or it may point to bytes holding '5' in - /// \v{mov ax, [bx+5]} - /// Usually bytes pointed to this offset are relocated (have fixup information). - char offb; - - /// Same as #offb (some operands have 2 numeric values used to form an operand). - /// This field is used for the second part of operand if it exists. - /// Currently this field is used only for outer offsets of Motorola processors. - /// Leave it equal to zero if the operand has no offset. - char offo; - - uchar flags; ///< \ref OF_ -/// \defgroup OF_ Operand flags -/// \ingroup operands_t -/// Used by op_t::flags -//@{ -#define OF_NO_BASE_DISP 0x80 ///< base displacement doesn't exist. - ///< meaningful only for ::o_displ type. - ///< if set, base displacement (op_t::addr) - ///< doesn't exist. -#define OF_OUTER_DISP 0x40 ///< outer displacement exists. - ///< meaningful only for ::o_displ type. - ///< if set, outer displacement (op_t::value) exists. -#define PACK_FORM_DEF 0x20 ///< packed factor defined. - ///< (!::o_reg + #dt_packreal) -#define OF_NUMBER 0x10 ///< the operand can be converted to a number only -#define OF_SHOW 0x08 ///< should the operand be displayed? -//@} - - /// Set operand to be shown - void set_shown() { flags |= OF_SHOW; } - /// Set operand to hidden - void clr_shown() { flags &= ~OF_SHOW; } - /// Is operand set to be shown? - bool shown() const { return (flags & OF_SHOW) != 0; } - - /// Type of operand value (see \ref dt_). Usually first 9 types are used. - /// This is the type of the operand itself, not the size of the addressing mode. - /// for example, byte ptr [epb+32_bit_offset] will have #dt_byte type. - op_dtype_t dtype; -/// \defgroup dt_ Operand value types -/// \ingroup operands_t -/// Used by op_t::dtype -//@{ -// from here.. -#define dt_byte 0 ///< 8 bit integer -#define dt_word 1 ///< 16 bit integer -#define dt_dword 2 ///< 32 bit integer -#define dt_float 3 ///< 4 byte floating point -#define dt_double 4 ///< 8 byte floating point -#define dt_tbyte 5 ///< variable size (\ph{tbyte_size}) floating point -#define dt_packreal 6 ///< packed real format for mc68040 -// ...to here the order should not be changed, see mc68000 -#define dt_qword 7 ///< 64 bit integer -#define dt_byte16 8 ///< 128 bit integer -#define dt_code 9 ///< ptr to code (not used?) -#define dt_void 10 ///< none -#define dt_fword 11 ///< 48 bit -#define dt_bitfild 12 ///< bit field (mc680x0) -#define dt_string 13 ///< pointer to asciiz string -#define dt_unicode 14 ///< pointer to unicode string -#define dt_ldbl 15 ///< long double (which may be different from tbyte) -#define dt_byte32 16 ///< 256 bit integer -#define dt_byte64 17 ///< 512 bit integer -#define dt_half 18 ///< 2-byte floating point -//@} - - // REG - union - { - uint16 reg; ///< number of register (::o_reg) - uint16 phrase; ///< number of register phrase (::o_phrase,::o_displ). - ///< you yourself define numbers of phrases - ///< as you like - }; - - /// Is register operand? - bool is_reg(int r) const { return type == o_reg && reg == r; } - - // Next 12 bytes are used by mc68k for some float types - - // VALUE - union - { - uval_t value; ///< operand value (::o_imm) or - ///< outer displacement (::o_displ+#OF_OUTER_DISP). - ///< integer values should be in IDA's (little-endian) order. - ///< when using ieee_realcvt(), floating point values should be in the processor's native byte order. - ///< #dt_double and #dt_qword values take up 8 bytes (value and addr fields for 32-bit modules). - ///< NB: in case a #dt_dword/#dt_qword immediate is forced to float by user, - ///< the kernel converts it to processor's native order before calling FP conversion routines. - - /// This structure is defined for - /// your convenience only - struct - { - uint16 low; - uint16 high; - } value_shorts; - }; - - /// Is immediate operand? - bool is_imm(uval_t v) const { return type == o_imm && value == v; } - - // VIRTUAL ADDRESS (offset within the segment) - union - { - ea_t addr; ///< virtual address pointed or used by the operand. - ///< (::o_mem,::o_displ,::o_far,::o_near) - - /// This structure is defined for - /// your convenience only - struct - { - uint16 low; - uint16 high; - } addr_shorts; - }; - - // IDP SPECIFIC INFORMATION - union - { - ea_t specval; ///< This field may be used as you want. - /// This structure is defined for - /// your convenience only - struct - { - uint16 low; ///< IBM PC: segment register number (::o_mem,::o_far,::o_near) - uint16 high; ///< IBM PC: segment selector value (::o_mem,::o_far,::o_near) - } specval_shorts; - }; - - /// \name Special flags - /// The following fields are used only in idp modules. - /// You may use them as you want to store additional information about - /// the operand. - //@{ - char specflag1; - char specflag2; - char specflag3; - char specflag4; - //@} -}; - - -//-------------------------------------------------------------------------- -// I N S T R U C T I O N -//-------------------------------------------------------------------------- -/// \defgroup instruction Instruction -/// Definition of ::insn_t and related items. - -/// Structure to hold information about an instruction. \ingroup instruction -/// This structure is filled by the analysis step of IDP and used by -/// the emulation and conversion to text steps. The kernel uses this structure too. -/// All structure fields except #cs, #ip, #ea, and op_t::n,op_t::flags of #ops -/// are initialized to zero by the kernel. The rest should be filled by ana(). - -class insn_t; -#define DECLARE_INSN_HELPERS(decl) \ -decl bool ida_export insn_create_op_data(const insn_t &insn, ea_t ea, int opoff, op_dtype_t dtype); \ -decl void ida_export insn_add_cref(const insn_t &insn, ea_t to, int opoff, cref_t type); \ -decl void ida_export insn_add_dref(const insn_t &insn, ea_t to, int opoff, dref_t type); \ -decl ea_t ida_export insn_add_off_drefs(const insn_t &insn, const op_t &x, dref_t type, int outf); \ -decl bool ida_export insn_create_stkvar(const insn_t &insn, const op_t &x, adiff_t v, int flags); - -DECLARE_INSN_HELPERS(idaman) - -//-V:insn_t:730 not all members of a class are initialized inside the constructor -class insn_t -{ -public: - insn_t() : ea(BADADDR), itype(0), size(0) {} - - /// Current segment base paragraph. Initialized by the kernel. - ea_t cs; - - /// Virtual address of the instruction (address within the segment). - /// Initialized by the kernel. - ea_t ip; - - /// Linear address of the instruction. - /// Initialized by the kernel. - ea_t ea; - - /// Internal code of instruction (only for canonical insns - not user defined!). - /// IDP should define its own instruction codes. These codes are usually - /// defined in ins.hpp. The array of instruction names and features (ins.cpp) - /// is accessed using this code. - uint16 itype; - - inline bool is_canon_insn(const processor_t &ph) const; ///< see \ph{is_canon_insn()} - inline uint32 get_canon_feature(const processor_t &ph) const; ///< see instruc_t::feature - inline const char *get_canon_mnem(const processor_t &ph) const; ///< see instruc_t::name - - /// Size of instruction in bytes. - /// The analyzer should put here the actual size of the instruction. - uint16 size; - - union - { - uint32 auxpref; ///< processor dependent field - uint16 auxpref_u16[2]; - uint8 auxpref_u8[4]; - }; - /*u*/ char segpref; ///< processor dependent field - /*u*/ char insnpref; ///< processor dependent field - - /*u*/ int16 flags; ///< \ref INSN_ - - op_t ops[UA_MAXOP]; ///< array of operands - - /// \defgroup Op_ Operand shortcuts - /// \ingroup instruction - /// Used for accessing members of insn_t::ops - //@{ - #define Op1 ops[0] ///< first operand - #define Op2 ops[1] ///< second operand - #define Op3 ops[2] ///< third operand - #define Op4 ops[3] ///< fourth operand - #define Op5 ops[4] ///< fifth operand - #define Op6 ops[5] ///< sixth operand - #define Op7 ops[6] ///< seventh operand - #define Op8 ops[7] ///< eighth operand - //@} - -/// \defgroup INSN_ Instruction flags -/// \ingroup instruction -/// Used by insn_t::flags -//@{ -#define INSN_MACRO 0x01 ///< macro instruction -#define INSN_MODMAC 0x02 ///< may modify the database to make room for the macro insn -#define INSN_64BIT 0x04 ///< belongs to 64bit segment? -//@} - - /// Is a macro instruction? - bool is_macro(void) const { return (flags & INSN_MACRO) != 0; } - - /// Belongs to a 64bit segment? -#ifdef __EA64__ - bool is_64bit(void) const { return (flags & INSN_64BIT) != 0; } -#else - bool is_64bit(void) const { return false; } -#endif - - /// \name Analysis helpers - /// The following functions return the next byte, 2 bytes, 4 bytes, - /// and 8 bytes of insn. They use and modify the size field (\insn_t{size}). - /// Normally they are used in the analyzer to get bytes of the instruction. - /// \warning These methods work only for normal (8bit) byte processors! - //@{ - uint8 get_next_byte() - { - uint8 x = get_byte(ea + size); - size += 1; - return x; - } - uint16 get_next_word() - { - uint16 x = get_word(ea + size); - size += 2; - return x; - } - uint32 get_next_dword() - { - uint32 x = get_dword(ea + size); - size += 4; - return x; - } - uint64 get_next_qword() - { - uint64 x = get_qword(ea + size); - size += 8; - return x; - } - //@} - - /// \name Emulator helpers - //@{ - - /// Convert to data using information about operand value type (op_t::dtype). - /// Emulator could use this function to convert unexplored bytes to data - /// when an instruction references them. - /// This function creates data only if the address was unexplored. - /// \param ea linear address to be converted to data - /// \param opoff offset of the operand from the start of instruction - /// if the offset is unknown, then 0 - /// \param dtype operand value type (from op_t::dtype) - /// \retval true ok - /// \retval false failed to create data item - - bool create_op_data(ea_t ea_, int opoff, op_dtype_t dtype) const - { - return insn_create_op_data(*this, ea_, opoff, dtype); - } - - /// Convenient alias - bool create_op_data(ea_t ea_, const op_t &op) const - { - return insn_create_op_data(*this, ea_, op.offb, op.dtype); - } - - - /// Create or modify a stack variable in the function frame. - /// The emulator could use this function to create stack variables - /// in the function frame before converting the operand to a stack variable. - /// Please check with may_create_stkvars() before calling this function. - /// \param x operand (used to determine the addressing type) - /// \param v a displacement in the operand - /// \param flags_ \ref STKVAR_2 - /// \retval 1 ok, a stack variable exists now - /// \retval 0 no, couldn't create stack variable - - bool create_stkvar(const op_t &x, adiff_t v, int flags_) const - { - return insn_create_stkvar(*this, x, v, flags_); - } - - /// \defgroup STKVAR_2 Stack variable flags - /// Passed as 'flags' parameter to create_stkvar() - //@{ -#define STKVAR_VALID_SIZE 0x0001 ///< x.dtype contains correct variable type - ///< (for insns like 'lea' this bit must be off) - ///< in general, dr_O references do not allow - ///< to determine the variable size - //@} - - - /// Add a code cross-reference from the instruction. - /// \param opoff offset of the operand from the start of instruction. - /// if the offset is unknown, then 0. - /// \param to target linear address - /// \param type type of xref - - void add_cref(ea_t to, int opoff, cref_t type) const - { - insn_add_cref(*this, to, opoff, type); - } - - - /// Add a data cross-reference from the instruction. - /// See add_off_drefs() - usually it can be used in most cases. - /// \param opoff offset of the operand from the start of instruction - /// if the offset is unknown, then 0 - /// \param to target linear address - /// \param type type of xref - - void add_dref(ea_t to, int opoff, dref_t type) const - { - insn_add_dref(*this, to, opoff, type); - } - - - /// Add xrefs for an operand of the instruction. - /// This function creates all cross references for 'enum', 'offset' and - /// 'structure offset' operands. - /// Use add_off_drefs() in the presence of negative offsets. - /// \param x reference to operand - /// \param type type of xref - /// \param outf out_value() flags. These flags should match - /// the flags used to output the operand - /// \return if is_off(): the reference target address (the same as calc_reference_data). - /// if is_stroff(): #BADADDR because for stroffs the target address is unknown - /// else: #BADADDR because enums do not represent addresses - - ea_t add_off_drefs(const op_t &x, dref_t type, int outf) const - { - return insn_add_off_drefs(*this, x, type, outf); - } - - //@} - -}; -#ifdef __EA64__ -CASSERT(sizeof(insn_t) == 360); -#else -CASSERT(sizeof(insn_t) == 216); -#endif - -//-------------------------------------------------------------------------- -// V A L U E O F O P E R A N D -//-------------------------------------------------------------------------- -#ifndef SWIG -/// This structure is used to pass values of bytes to helper functions. -union value_u -{ - uint8 v_char; - uint16 v_short; - uint32 v_long; - uint64 v_int64; - uval_t v_uval; - struct dq_t { uint32 low; uint32 high; } _dq; - struct dt_t { uint32 low; uint32 high; uint16 upper; } dt; - struct d128_t { uint64 low; uint64 high; } d128; - uint8 byte16[16]; - uint32 dword3[3]; -}; - -#endif // SWIG - -/// Get immediate values at the specified address. -/// This function decodes instruction at the specified address or inspects -/// the data item. It finds immediate values and copies them to 'out'. -/// This function will store the original value of the operands in 'out', -/// unless the last bits of 'F' are "...0 11111111", in which case the -/// transformed values (as needed for printing) will be stored instead. -/// \param out array of immediate values (at least 2*#UA_MAXOP elements) -/// \param ea address to analyze -/// \param n number of operand (0..#UA_MAXOP-1), -1 means all operands -/// \param F flags for the specified address -/// \param cache optional already decoded instruction or buffer for it. -/// if the cache does not contain the decoded instruction, -/// it will be updated (useful if we call get_immvals for the same -/// address multiple times) -/// \return number of immediate values (0..2*#UA_MAXOP) - -idaman size_t ida_export get_immvals( - uval_t *out, - ea_t ea, - int n, - flags_t F, - insn_t *cache=NULL); - - -/// Get immediate ready-to-print values at the specified address -/// \param out array of immediate values (at least 2*#UA_MAXOP elements) -/// \param ea address to analyze -/// \param n number of operand (0..#UA_MAXOP-1), -1 means all operands -/// \param F flags for the specified address -/// \param cache optional already decoded instruction or buffer for it. -/// if the cache does not contain the decoded instruction, -/// it will be updated (useful if we call get_immvals for the same -/// address multiple times) -/// \return number of immediate values (0..2*#UA_MAXOP) - -inline size_t get_printable_immvals( - uval_t *out, - ea_t ea, - int n, - flags_t F, - insn_t *cache=NULL) -{ - F &= ~0x100; // no FF_IVL... - F |= 0xFF; // ...but a value of 0xFF - return get_immvals(out, ea, n, F, cache); -} - - -/// Number of instructions to look back. -/// This variable is not used by the kernel. -/// Its value may be specified in ida.cfg: -/// LOOKBACK = <number>. -/// IDP may use it as you like it. -/// (TMS module uses it) - -idaman int ida_export get_lookback(void); - - -//-------------------------------------------------------------------------- -// I D P H E L P E R F U N C T I O N S - C O M M O N -//-------------------------------------------------------------------------- - -/// \name Address translation -/// The following functions can be used by processor modules to map -/// addresses from one region to another. They are especially useful -/// for microprocessors that map the same memory region to multiple address -/// ranges or use memory bank switching. -/// The user can use the following techniques to desribe address translations: -/// - some processors support the segment transation feature. -/// the user can specify the mapping in Edit, Segments, Change segment translation -/// - the user can specify mapping for an individual direct call instruction -/// by specifying it as an offset (Edit, Operand types, Offset) -/// - specify the value of the data segment virtual register (ds). -/// it will be used to calculate data addresses -//@{ - -/// Get data segment for the instruction operand. -/// 'opnum' and 'rgnum' are meaningful only if the processor -/// has segment registers. - -idaman ea_t ida_export calc_dataseg(const insn_t &insn, int n=-1, int rgnum=-1); - -/// Map a data address. -/// \param insn the current instruction -/// \param addr the referenced address to map -/// \param opnum operand number - -inline ea_t map_data_ea(const insn_t &insn, ea_t addr, int opnum=-1) -{ - return to_ea(calc_dataseg(insn, opnum), addr); -} - -inline ea_t map_data_ea(const insn_t &insn, const op_t &op) -{ - return map_data_ea(insn, op.addr, op.n); -} - -/// Map a code address. -/// This function takes into account the segment translations. -/// \param insn the current instruction -/// \param addr the referenced address to map -/// \param opnum operand number - -idaman ea_t ida_export map_code_ea(const insn_t &insn, ea_t addr, int opnum); - -inline ea_t map_code_ea(const insn_t &insn, const op_t &op) -{ - return map_code_ea(insn, op.addr, op.n); -} - -inline ea_t map_ea(const insn_t &insn, const op_t &op, bool iscode) -{ - return iscode ? map_code_ea(insn, op) : map_data_ea(insn, op); -} - -inline ea_t map_ea(const insn_t &insn, ea_t addr, int opnum, bool iscode) -{ - return iscode ? map_code_ea(insn, addr, opnum) : map_data_ea(insn, addr, opnum); -} - -//@} - -//-------------------------------------------------------------------------- -// I D P H E L P E R F U N C T I O N S - O U T P U T -//-------------------------------------------------------------------------- -struct outctx_base_t -{ - // information for creating one line - ea_t insn_ea; - qstring outbuf; // buffer for the current output line - // once ready, it is moved to lnar - ssize_t regname_idx; // to rename registers - int suspop; // controls color for out_long() - flags_t F; // flag bits for insn_ea - uval_t *outvalues; // at least 2*UA_MAXOP elements - int outvalue_getn_flags; // additional flags for print_operand() - void *user_data; // pointer to be used by the processor module for any purpose - void *kern_data; // internal info used by the kernel - - // information for generating many lines - qstrvec_t *lnar; // vector of output lines - int lnar_maxsize; // max permitted size of lnar - int default_lnnum; // index of the most important line in lnar - - qstring line_prefix; // usually segname:offset - ssize_t prefix_len; // visible length of line_prefix - int ctxflags; // various bits -#define CTXF_MAIN 0x00001 // produce only the essential line(s) -#define CTXF_MULTI 0x00002 // enable multi-line essential lines -#define CTXF_CODE 0x00004 // display as code regardless of the database flags -#define CTXF_STACK 0x00008 // stack view -#define CTXF_GEN_XREFS 0x00010 // generate the xrefs along with the next line -#define CTXF_XREF_STATE 0x00060 // xref state: -#define XREFSTATE_NONE 0x00 // not generated yet -#define XREFSTATE_GO 0x20 // being generated -#define XREFSTATE_DONE 0x40 // have been generated -#define CTXF_GEN_CMT 0x00080 // generate the comment along with the next line -#define CTXF_CMT_STATE 0x00300 // comment state: -#define COMMSTATE_NONE 0x000 // not generated yet -#define COMMSTATE_GO 0x100 // being generated -#define COMMSTATE_DONE 0x200 // have been generated -#define CTXF_VOIDS 0x00400 // display void marks -#define CTXF_NORMAL_LABEL 0x00800 // generate plain label (+demangled label as cmt) -#define CTXF_DEMANGLED_LABEL 0x01000 // generate only demangled label as comment -#define CTXF_LABEL_OK 0x02000 // the label have been generated -#define CTXF_DEMANGLED_OK 0x04000 // the label has been demangled successfully -#define CTXF_OVSTORE_PRNT 0x08000 // out_value should store modified values -#define CTXF_OUTCTX_T 0x10000 // instance is, in fact, a outctx_t -#define CTXF_DBLIND_OPND 0x20000 // an operand was printed with double indirection (e.g. =var in arm) -#define CTXF_BINOP_STATE 0xC0000 // opcode bytes state: -#define BINOPSTATE_NONE 0x00000 // not generated yet -#define BINOPSTATE_GO 0x40000 // being generated -#define BINOPSTATE_DONE 0x80000 // have been generated - - - // internal data used by the kernel - int ind0; - ea_t cmt_ea; // indirectly referenced address (used to generate cmt) - qstring cmtbuf; // indented comment - const char *cmtptr; // rest of indented comment - color_t cmtcolor; // comment color - - inline bool only_main_line() const { return (ctxflags & CTXF_MAIN) != 0; } - inline bool multiline() const { return (ctxflags & CTXF_MULTI) != 0; } - inline bool force_code() const { return (ctxflags & CTXF_CODE) != 0; } - inline bool stack_view() const { return (ctxflags & CTXF_STACK) != 0; } - inline bool display_voids() const { return (ctxflags & CTXF_VOIDS) != 0; } - inline void set_gen_xrefs(bool on=true) { setflag(ctxflags, CTXF_GEN_XREFS, on); } - inline int get_xrefgen_state() const { return ctxflags & CTXF_XREF_STATE; } - inline void set_gen_cmt(bool on=true) { setflag(ctxflags, CTXF_GEN_CMT, on); } - inline int get_cmtgen_state() const { return ctxflags & CTXF_CMT_STATE; } - inline int get_binop_state() const { return ctxflags & CTXF_BINOP_STATE; } - inline void clr_gen_label(void) { ctxflags &= ~(CTXF_NORMAL_LABEL|CTXF_DEMANGLED_LABEL); } - inline void set_gen_label(void) { ctxflags |= CTXF_NORMAL_LABEL; } - inline void set_gen_demangled_label(void) { ctxflags |= CTXF_DEMANGLED_LABEL; ctxflags &= ~CTXF_NORMAL_LABEL; } - inline void set_comment_addr(ea_t ea) { cmt_ea = ea; } - inline void set_dlbind_opnd(void) { ctxflags |= CTXF_DBLIND_OPND; } - inline bool print_label_now() const - { - return (ctxflags & (CTXF_LABEL_OK|CTXF_MAIN)) == 0 // label not ready - && (ctxflags & (CTXF_NORMAL_LABEL|CTXF_DEMANGLED_LABEL)) != 0; // requested it - } - int forbid_annotations() - { // temporarily forbid printing of xrefs, label, cmt - int bits = CTXF_GEN_XREFS|CTXF_NORMAL_LABEL|CTXF_DEMANGLED_LABEL|CTXF_GEN_CMT; - int saved_flags = ctxflags & bits; - ctxflags &= ~bits; - return saved_flags; - } - void restore_ctxflags(int saved_flags) - { - ctxflags |= saved_flags; - } - - outctx_base_t(ea_t ea, flags_t flags, int _suspop=0) - : insn_ea(ea), regname_idx(-1), suspop(_suspop), F(flags), - outvalues(NULL), outvalue_getn_flags(0), user_data(NULL), kern_data(NULL), - lnar(NULL), lnar_maxsize(0), default_lnnum(-1), - prefix_len(0), ctxflags(0), ind0(0), cmt_ea(BADADDR), cmtptr(NULL), cmtcolor(0xFF) - { - outbuf.reserve(MAXSTR); - } - virtual ~outctx_base_t(void); - - ///------------------------------------------------------------------------- - /// Functions to append text to the current output buffer (outbuf) - - /// Append a formatted string to the output string. - /// \return the number of characters appended - AS_PRINTF(2, 3) void out_printf(const char *format, ...) - { - va_list va; - va_start(va, format); - out_vprintf(format, va); - va_end(va); - } - - GCC_DIAG_OFF(format-nonliteral); - void nowarn_out_printf(const char *format, ...) //-V524 body is equal to out_printf - { - va_list va; - va_start(va, format); - out_vprintf(format, va); - va_end(va); - } - GCC_DIAG_ON(format-nonliteral); - - virtual AS_PRINTF(2, 0) void idaapi out_vprintf(const char *format, va_list va); - - /// Output immediate value. - /// Try to use this function to output all constants of instruction operands. - /// This function outputs a number from x.addr or x.value in the form - /// determined by ::uFlag. It outputs a colored text. - /// - -1 is output with #COLOR_ERROR - /// - 0 is output as a number or character or segment - /// \param x value to output - /// \param outflags \ref OOF_ - /// \return flags of the output value - virtual flags_t idaapi out_value(const op_t &x, int outf=0); - - /// \defgroup OOF_ Output value flags - /// Flags passed to out_value(). - /// (don't use #OOF_SIGNMASK and #OOF_WIDTHMASK, they are for the kernel) - //@{ -#define OOF_SIGNMASK 0x0003 ///< sign symbol (+/-) output -#define OOFS_IFSIGN 0x0000 ///< output sign if needed -#define OOFS_NOSIGN 0x0001 ///< don't output sign, forbid the user to change the sign -#define OOFS_NEEDSIGN 0x0002 ///< always out sign (+-) -#define OOF_SIGNED 0x0004 ///< output as signed if < 0 -#define OOF_NUMBER 0x0008 ///< always as a number -#define OOF_WIDTHMASK 0x0070 ///< width of value in bits -#define OOFW_IMM 0x0000 ///< take from x.dtype -#define OOFW_8 0x0010 ///< 8 bit width -#define OOFW_16 0x0020 ///< 16 bit width -#define OOFW_24 0x0030 ///< 24 bit width -#define OOFW_32 0x0040 ///< 32 bit width -#define OOFW_64 0x0050 ///< 64 bit width -#define OOF_ADDR 0x0080 ///< output x.addr, otherwise x.value -#define OOF_OUTER 0x0100 ///< output outer operand -#define OOF_ZSTROFF 0x0200 ///< meaningful only if is_stroff(uFlag) - ///< append a struct field name if - ///< the field offset is zero? - ///< if #AFL_ZSTROFF is set, then this flag - ///< is ignored. -#define OOF_NOBNOT 0x0400 ///< prohibit use of binary not -#define OOF_SPACES 0x0800 ///< do not suppress leading spaces - ///< currently works only for floating point numbers -#define OOF_ANYSERIAL 0x1000 ///< if enum: select first available serial - //@} - - /// Output a character with #COLOR_SYMBOL color. - virtual void idaapi out_symbol(char c); - - /// Append a character multiple times - virtual void idaapi out_chars(char c, int n); - - /// Appends spaces to outbuf until its tag_strlen becomes 'len' - void out_spaces(ssize_t len) { add_spaces(&outbuf, len); } - virtual void idaapi add_spaces(qstring *buf, ssize_t len); - - /// Output a string with the specified color. - virtual void idaapi out_line(const char *str, color_t color=0); - - /// Output a string with #COLOR_KEYWORD color. - inline void out_keyword(const char *str) - { - out_line(str, COLOR_KEYWORD); - } - - /// Output a character with #COLOR_REG color. - inline void out_register(const char *str) - { - out_line(str, COLOR_REG); - } - - /// Output "turn color on" escape sequence - virtual void idaapi out_tagon(color_t tag); - - /// Output "turn color off" escape sequence - virtual void idaapi out_tagoff(color_t tag); - - /// Output "address" escape sequence - virtual void idaapi out_addr_tag(ea_t ea); - - /// Output a colored line with register names in it. - /// The register names will be substituted by user-defined names (regvar_t) - /// Please note that out_tagoff tries to make substitutions too (when called with COLOR_REG) - virtual void idaapi out_colored_register_line(const char *str); - - /// Output one character. - /// The character is output without color codes. - /// see also out_symbol() - virtual void idaapi out_char(char c) { outbuf.append(c); } - - /// Output a number with the specified base (binary, octal, decimal, hex) - /// The number is output without color codes. - /// see also out_long() - virtual void idaapi out_btoa(uval_t Word, char radix=0); - - /// \fn void out_long(sval_t, char) - /// Output a number with appropriate color. - /// Low level function. Use out_value() if you can. - /// if 'suspop' is set then - /// this function uses #COLOR_VOIDOP instead of #COLOR_NUMBER. - /// 'suspop' is initialized: - /// - in out_one_operand() - /// - in ..\ida\gl.cpp (before calling \ph{d_out()}) - /// \param v value to output - /// \param radix base (2,8,10,16) - /// \param suspop ::suspop - /// - suspop==0: operand is ok - /// - suspop==1: operand is suspicious and should be output with #COLOR_VOIDOP - /// - suspop==2: operand can't be output as requested and should be output with #COLOR_ERROR - virtual void idaapi out_long(sval_t v, char radix); - - /// Output a name expression. - /// \param x instruction operand referencing the name expression - /// \param ea address to convert to name expression - /// \param off the value of name expression. this parameter is used only to - /// check that the name expression will have the wanted value. - /// You may pass #BADADDR for this parameter but I discourage it - /// because it prohibits checks. - /// \return true if the name expression has been produced - virtual bool idaapi out_name_expr( - const op_t &x, - ea_t ea, - adiff_t off=BADADDR); - - // Generate the closing comment if if it required by the assembler - - inline void close_comment(void) { out_line(closing_comment()); } - - ///------------------------------------------------------------------------- - /// Functions to populate the output line array (lnar) - - /// Move the contents of the output buffer to the line array (outbuf->lnar) - /// The kernel augments the outbuf contents with additional text like - /// the line prefix, user-defined comments, xrefs, etc at this call. - virtual bool idaapi flush_outbuf(int indent=-1); - - /// Append contents of 'buf' to the line array. - /// Behaves like flush_outbuf but accepts an arbitrary buffer - virtual bool idaapi flush_buf(const char *buf, int indent=-1); - - /// Finalize the output context. - /// \return the number of generated lines. - virtual int idaapi term_outctx(const char *prefix=NULL); - - /// See gen_printf() - virtual AS_PRINTF(3, 0) bool idaapi gen_vprintf( - int indent, - const char *format, - va_list va); - - /// printf-like function to add lines to the line array. - /// \param indent indention of the line. - /// if indent == -1, the kernel will indent the line - /// at \inf{indent}. if indent < 0, -indent will be used for indention. - /// The first line printed with indent < 0 is considered as the - /// most important line at the current address. Usually it is - /// the line with the instruction itself. This line will be - /// displayed in the cross-reference lists and other places. - /// If you need to output an additional line before the main line - /// then pass DEFAULT_INDENT instead of -1. The kernel will know - /// that your line is not the most important one. - /// \param format printf style colored line to generate - /// \return overflow, lnar_maxsize has been reached - - AS_PRINTF(3, 4) inline bool gen_printf(int indent, const char *format, ...) - { - va_list va; - va_start(va, format); - bool code = gen_vprintf(indent, format, va); - va_end(va); - return code; - } -#define DEFAULT_INDENT 0xFFFF - - /// Generate empty line. This function does nothing if generation of empty - /// lines is disabled. - /// \return overflow, lnar_maxsize has been reached - - virtual bool idaapi gen_empty_line(void); - - - /// Generate thin border line. This function does nothing if generation - /// of border lines is disabled. - /// \param solid generate solid border line (with =), otherwise with - - /// \return overflow, lnar_maxsize has been reached - - virtual bool idaapi gen_border_line(bool solid=false); - - /// See gen_cmt_line() - virtual AS_PRINTF(3, 0) bool idaapi gen_colored_cmt_line_v( - color_t color, - const char *format, - va_list va); - - /// See gen_cmt_line() - - AS_PRINTF(2, 0) inline bool gen_cmt_line_v(const char *format, va_list va) - { - return gen_colored_cmt_line_v(COLOR_AUTOCMT, format, va); - } - - /// Generate one non-indented comment line, colored with ::COLOR_AUTOCMT. - /// \param format printf() style format line. The resulting comment line - /// should not include comment character (;) - /// \return overflow, lnar_maxsize has been reached - - AS_PRINTF(2, 3) inline bool gen_cmt_line(const char *format, ...) - { - va_list va; - va_start(va, format); - bool code = gen_cmt_line_v(format, va); - va_end(va); - return code; - } - - /// Generate one non-indented comment line, colored with ::COLOR_COLLAPSED. - /// \param format printf() style format line. The resulting comment line - /// should not include comment character (;) - /// \return overflow, lnar_maxsize has been reached - - AS_PRINTF(2, 3) inline bool gen_collapsed_line(const char *format, ...) - { - va_list va; - va_start(va,format); - bool answer = gen_colored_cmt_line_v(COLOR_COLLAPSED, format, va); - va_end(va); - return answer; - } - - /// Generate big non-indented comment lines. - /// \param cmt comment text. may contain \\n characters to denote new lines. - /// should not contain comment character (;) - /// \param color color of comment text (one of \ref COLOR_) - /// \return overflow, lnar_maxsize has been reached - - virtual bool idaapi gen_block_cmt(const char *cmt, color_t color); - - //------------------------------------------------------------------------- - /// Initialization; normally used only by the kernel - virtual void idaapi setup_outctx(const char *prefix, int makeline_flags); -#define MAKELINE_NONE 0x00 -#define MAKELINE_BINPREF 0x01 // allow display of binary prefix -#define MAKELINE_VOID 0x02 // allow display of '<suspicious>' marks -#define MAKELINE_STACK 0x04 // allow display of sp trace prefix - - virtual ssize_t idaapi retrieve_cmt(void) { return -1; } - virtual ssize_t idaapi retrieve_name(qstring *, color_t *) { return -1; } - virtual bool idaapi gen_xref_lines(void) { return false; } - - virtual void idaapi init_lines_array(qstrvec_t *answers, int maxsize); - - virtual member_t *idaapi get_stkvar(const op_t &, uval_t, sval_t *, int *); - - void gen_empty_line_without_annotations(void) - { - int saved_flags = forbid_annotations(); - gen_empty_line(); - restore_ctxflags(saved_flags); - } - - -protected: - virtual bool idaapi flush_and_reinit(void); - virtual void idaapi append_user_prefix(const char *, int) {} - virtual void idaapi add_aux_prefix(const char *, int) {} - virtual void idaapi out_label_addr_tag(void) {} - virtual void idaapi out_aux_cmts(void) {} -}; - -//-------------------------------------------------------------------------- -// This class is used to print instructions and data items -struct outctx_t : public outctx_base_t -{ - // kernel only data: - ea_t bin_ea; // Current binary format EA - char bin_state; // =0 not generated,1-in process,2-finished - int gl_bpsize = 0; // binary line prefix size - int bin_width = 0; - - // instruction to display: - insn_t insn; // valid only when ph.out_insn() is called - - // colorized and demangled label of the current address - qstring curlabel; - - // opinfo_t to use for out_value() - const printop_t *wif; - - // processor module and its description - procmod_t *procmod; - processor_t &ph; - asm_t &ash; - - outctx_t( - procmod_t *p, - processor_t &ph, - asm_t &ash, - ea_t ea, - flags_t flags=0, - int _suspop=0, - const printop_t *_wif=NULL); - ~outctx_t(void) - { - } - virtual void idaapi setup_outctx(const char *prefix, int flags) override; - virtual ssize_t idaapi retrieve_cmt(void) override; - virtual ssize_t idaapi retrieve_name(qstring *, color_t *) override; - virtual bool idaapi gen_xref_lines(void) override; - void set_bin_state(int value) - { - bin_state = value; - ctxflags &= ~CTXF_BINOP_STATE; - ctxflags |= value == 0 ? BINOPSTATE_NONE - : value == 1 ? BINOPSTATE_GO - : BINOPSTATE_DONE; - } - - /// Output instruction mnemonic for 'insn' using information in 'ph.instruc' array. - /// This function outputs a colored text. - /// It should be called from \ph{ev_out_insn()} or \ph{ev_out_mnem()} handler. - /// It will output at least one space after the instruction. - /// mnemonic even if the specified 'width' is not enough. - /// \param width width of field with mnemonic. - /// if < 0, then 'postfix' will be output before - /// the mnemonic, i.e. as a prefix - /// \param postfix optional postfix added to the instruction mnemonic - virtual void idaapi out_mnem(int width=8, const char *postfix=NULL) newapi; - - /// Output custom mnemonic for 'insn'. - /// E.g. if it should differ from the one in 'ph.instruc'. - /// This function outputs colored text. See \ref out_mnem - /// \param mnem custom mnemonic - /// \param width width of field with mnemonic. - /// if < 0, then 'postfix' will be output before - /// the mnemonic, i.e. as a prefix - /// \param postfix optional postfix added to 'mnem' - virtual void idaapi out_custom_mnem( - const char *mnem, - int width=8, - const char *postfix=NULL) newapi; - - /// Output instruction mnemonic using information in 'insn'. - /// It should be called from \ph{ev_out_insn()} and - /// it will call \ph{ev_out_mnem()} or \ref out_mnem. - /// This function outputs a colored text. - virtual void idaapi out_mnemonic(void) newapi; - - /// Use this function to output an operand of an instruction. - /// This function checks for the existence of a manually defined operand - /// and will output it if it exists. - /// It should be called from \ph{ev_out_insn()} and it will call \ph{ev_out_operand()}. - /// This function outputs a colored text. - /// \param n number of operand - /// \retval 1 operand is displayed - /// \retval 0 operand is hidden - virtual bool idaapi out_one_operand(int n) newapi; - - /// Get the immediate values used at the specified address. - /// This function can handle instructions and data items. - /// \param out array of values, size at least 2*UA_MAXOP - /// \param i operand number - /// \return number of immediate values - virtual size_t idaapi get_immvals(uval_t *out, int i) newapi; - - /// Print all operand values as commented character constants. - /// This function is used to comment void operands with their representation - /// in the form of character constants. - /// This function outputs a colored text. - virtual void idaapi out_immchar_cmts(void) newapi; - - virtual void idaapi gen_func_header(func_t *pfn) newapi; - virtual void idaapi gen_func_footer(const func_t *pfn) newapi; - - // display data items and undefined bytes. - virtual void idaapi out_data(bool analyze_only) newapi; - - // generate declaration for item in a special segment - // return: 0-ok, 1-overflow - virtual bool idaapi out_specea(uchar segtype) newapi; - - // convenience functions for processor modules - // print lines from ash.header - virtual void idaapi gen_header_extra() newapi; - - // flags for gen_header() -#define GH_PRINT_PROC (1 << 0) //processor name -#define GH_PRINT_ASM (1 << 1) //selected assembler -#define GH_PRINT_BYTESEX (1 << 2) //byte sex -#define GH_PRINT_HEADER (1 << 3) //lines from ash.header -#define GH_BYTESEX_HAS_HIGHBYTE (1 << 4) //describe inf.is_wide_high_byte_first() -#define GH_PRINT_PROC_AND_ASM (GH_PRINT_PROC | GH_PRINT_ASM) -#define GH_PRINT_PROC_ASM_AND_BYTESEX (GH_PRINT_PROC_AND_ASM | GH_PRINT_BYTESEX) -#define GH_PRINT_ALL (GH_PRINT_PROC_ASM_AND_BYTESEX | GH_PRINT_HEADER) -#define GH_PRINT_ALL_BUT_BYTESEX (GH_PRINT_PROC_AND_ASM | GH_PRINT_HEADER) - virtual void idaapi gen_header( - int flags = GH_PRINT_PROC_AND_ASM, - const char *proc_name = NULL, - const char *proc_flavour = NULL) newapi; -}; - -//-------------------------------------------------------------------------- -/// Create a new output context. -/// To delete it, just use "delete pctx" - -idaman outctx_base_t *ida_export create_outctx(ea_t ea, flags_t F=0, int suspop=0); - - -/// Print instruction mnemonics. -/// \param out output buffer -/// \param ea linear address of the instruction -/// \return success - -idaman bool ida_export print_insn_mnem(qstring *out, ea_t ea); - - -/// \defgroup FCBF_ format flags -/// Used by format_charlit -//@{ -#define FCBF_CONT 0x00000001 ///< don't stop on decoding, or any other kind of error -#define FCBF_ERR_REPL 0x00000002 ///< in case of an error, use a CP_REPLCHAR instead - ///< of a hex representation of the problematic byte - -#define FCBF_FF_LIT 0x00000004 ///< in case of codepoints == 0xFF, use it as-is (i.e., LATIN SMALL LETTER Y WITH DIAERESIS) - ///< If both this, and FCBF_REPL are specified, - ///< this will take precedence - -#define FCBF_DELIM 0x00000008 ///< add the 'ash'-specified delimiters around the generated data. - ///< Note: if those are not defined and the INFFL_ALLASM is not set, - ///< format_charlit() will return an error -//@} - - -/// Format character literal. -/// -/// Try and format 'size' bytes pointed to by '*ptr', as literal characters, -/// using the 'encidx' encoding, and with the specified 'flags' directives. -/// -/// By default, format_charlit() will fail and return an error, in -/// any of the following cases: -/// - a byte cannot be decoded using the specified (or default) encoding -/// - a codepoint is < 0x20 (i.e., ' ') -/// - a codepoint is present in 'ash.esccodes' -/// - a codepoint is 0xFF -/// - a codepoint is >= 0x80, and AS_NHIAS was specified in ash.flag -/// The function can be told to keep going instead of bailing out, for any -/// of these situations, by using one of the FCBF_*_OK flags. -/// -/// If the function is told to proceed on a specific error, by default -/// it will format the byte as a C-encoded byte value (i.e., '\xNN'), -/// unless the corresponding FCBF_*_REPL flag is passed, in which case -/// the problematic byte/codepoint will be replaced by the Unicode -/// replacement character in the output. -/// -/// \param out output buffer (can be NULL) -/// \param ptr pointer to pointer to bytes to print (will be advanced -/// by the number of bytes that were successfully printed) -/// \param size size of input value in bytes -/// \param flags \ref FCBF_ -/// \param encidx the 1 byte-per-unit encoding to use (or 0 to use the default 1 BPU encoding) -/// \return success - -idaman bool ida_export format_charlit( - qstring *out, - const uchar **ptr, - size_t size, - uint32 flags=0, - int encidx=0); - - -/// Print a floating point value. -/// \param buf output buffer. may be NULL -/// \param bufsize size of the output buffer -/// \param v floating point value in processor native format -/// \param size size of the value in bytes -/// \return true ok -/// \return false can't represent as floating point number - -idaman bool ida_export print_fpval(char *buf, size_t bufsize, const void *v, int size); - - -//-------------------------------------------------------------------------- -// I D P H E L P E R F U N C T I O N S - E M U L A T O R -//-------------------------------------------------------------------------- -/// Get flags for op_t::dtype field -idaman flags_t ida_export get_dtype_flag(op_dtype_t dtype); -/// Get size of opt_::dtype field -idaman size_t ida_export get_dtype_size(op_dtype_t dtype); -/// Get op_t::dtype from size -idaman op_dtype_t ida_export get_dtype_by_size(asize_t size); - -/// Is a floating type operand? -inline bool is_floating_dtype(op_dtype_t dtype) -{ - return dtype == dt_float - || dtype == dt_double - || dtype == dt_tbyte - || dtype == dt_ldbl - || dtype == dt_half; -} - - -//-------------------------------------------------------------------------- -// K E R N E L I N T E R F A C E T O I D P F U N C T I O N S -//-------------------------------------------------------------------------- -/// Create an instruction at the specified address. -/// This function checks if an instruction is present at the specified address -/// and will try to create one if there is none. It will fail if there is -/// a data item or other items hindering the creation of the new instruction. -/// This function will also fill the 'out' structure. -/// \param ea linear address -/// \param out the resulting instruction -/// \return the length of the instruction or 0 -idaman int ida_export create_insn(ea_t ea, insn_t *out=NULL); - - -/// Analyze the specified address and fill 'out'. -/// This function does not modify the database. -/// It just tries to interpret the specified address as an instruction and fills -/// the 'out' structure. -/// \param out the resulting instruction -/// \param ea linear address -/// \return the length of the (possible) instruction or 0 - -idaman int ida_export decode_insn(insn_t *out, ea_t ea); - -/// Can the bytes at address 'ea' be decoded as instruction? -/// \param ea linear address -/// \return whether or not the contents at that address could be a valid instruction - -inline bool can_decode(ea_t ea) { insn_t insn; return decode_insn(&insn, ea) > 0; } - - -/// Generate text representation for operand #n. -/// This function will generate the text representation of the specified -/// operand (includes color codes.) -/// \param out output buffer -/// \param ea the item address (instruction or data) -/// \param n operand number (0,1,2...). meaningful only for instructions -/// \param flags \ref GETN_ -/// Currently only #GETN_NODUMMY is accepted. -/// \param newtype if specified, print the operand using the specified type -/// \return success - -idaman bool ida_export print_operand( - qstring *out, - ea_t ea, - int n, - int getn_flags=0, - struct printop_t *newtype=NULL); - - -//-------------------------------------------------------------------------- -// Helper functions for the processor emulator/analyzer -//-------------------------------------------------------------------------- - -/// Decode previous instruction if it exists, fill 'out'. -/// \param out the resulting instruction -/// \param ea the address to decode the previous instruction from -/// \return the previous instruction address (#BADADDR-no such insn) - -idaman ea_t ida_export decode_prev_insn(insn_t *out, ea_t ea); - - -/// Decode preceding instruction in the execution flow. -/// Prefer far xrefs from addresses < the current to ordinary flows. -/// \param ea the address to decode the preceding instruction from -/// \param out the resulting instruction -/// \return the preceding instruction address (#BADADDR-no such insn) and 'out'. -/// *p_farref will contain 'true' if followed an xref, false otherwise. - -idaman ea_t ida_export decode_preceding_insn(insn_t *out, ea_t ea, bool *p_farref=NULL); - - -/// Helper class for processor modules to build macro instructions. -struct macro_constructor_t -{ - size_t reserved = 0; - - virtual ~macro_constructor_t() {} - - /// Construct a macro instruction. - /// This function may be called from ana() to generate a macro instruction. - /// - /// The real work is done by the 'build_macro()' virtual function. - /// It must be defined by the processor module. - /// - /// construct_macro() modifies the database using the info provided - /// by build_macro(). It verifies if the instruction can really be created - /// (for example, that other items do not hinder), may plan to reanalyze - /// the macro, etc. - /// If the macro instructions are disabled by the user, construct_macro() - /// will destroy the macro instruction. Note: if INSN_MODMAC is not set in - /// insn.flags, the database will not be modified. - /// - /// \param insn the instruction to modify into a macro - /// \param enable enable macro generation - /// \retval true the macro instruction is generated in 'insn' - /// \retval false did not create a macro - inline bool construct_macro(insn_t *insn, bool enable); - - /// Try to extend the instruction. - /// \param insn Instruction to modify, usually the first - /// instruction of the macro - /// \param may_go_forward Is it ok to consider the next instruction for the macro? - /// This argument may be false, for example, if there is - /// a cross reference to the end of INSN. In this case - /// creating a macro is not desired. However, it may still - /// be useful to perform minor tweaks to the instruction - /// using the information about the surrounding instructions. - /// \return true if created an macro instruction. - /// This function may modify 'insn' and return false; these changes will be - /// accepted by the kernel but the instruction will not be considered as a macro. - virtual bool idaapi build_macro(insn_t *insn, bool may_go_forward) = 0; -}; - -// Do not directly call this function, use macro_constructor_t -idaman bool ida_export construct_macro2( - macro_constructor_t *_this, - insn_t *insn, - bool enable); - -inline bool macro_constructor_t::construct_macro(insn_t *insn, bool enable) -{ - return construct_macro2(this, insn, enable); -} - -/// Guess the jump table address (ibm pc specific) - -idaman ea_t ida_export guess_table_address(const insn_t &insn); - -/// Guess the jump table size - -idaman asize_t ida_export guess_table_size(const insn_t &insn, ea_t jump_table); - - -/// Does the instruction spoil any register from 'regs'?. -/// This function checks the \ref CF_ flags from the instructions array. -/// Only ::o_reg operand types are consulted. -/// \param insn the instruction -/// \return index in the 'regs' array or -1 - -idaman int ida_export get_spoiled_reg(const insn_t &insn, const uint32 *regs, size_t n); - - -//------------------------------------------------------------------------- - -#ifndef NO_OBSOLETE_FUNCS -idaman DEPRECATED bool ida_export print_charlit(char *buf, const void *ptr, int size); -idaman DEPRECATED bool ida_export construct_macro(insn_t &insn, bool enable, bool (idaapi *build_macro)(insn_t &insn, bool may_go_forward)); // use construct_macro2() -#endif // NO_OBSOLETE_FUNCS - -#endif // _UA_HPP diff --git a/idasdk75/include/xref.hpp b/idasdk75/include/xref.hpp deleted file mode 100644 index 65ecde2..0000000 --- a/idasdk75/include/xref.hpp +++ /dev/null @@ -1,417 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _XREF_HPP -#define _XREF_HPP - -/*! \file xref.hpp - - \brief Functions that deal with cross-references - - There are 2 types of xrefs: CODE and DATA references. - All xrefs are kept in the bTree except ordinary execution flow - to the next instruction. Ordinary execution flow to - the next instruction is kept in flags (see bytes.hpp) - - The source address of a cross-reference must be an item head (is_head) - or a structure member id. - - Cross-references are automatically sorted. -*/ - -class func_t; // #include <funcs.hpp> -class member_t; // #include <struct.hpp> - -//--------------------------------------------------------------------------- -// C R O S S - R E F E R E N C E T Y P E S -//--------------------------------------------------------------------------- - -/// \defgroup xref_type Cross-Reference types -/// Describe categories of code/data xrefs. -/// \note IDA handles the xrefs automatically and may delete an xref -/// added by the user if it does not contain the #XREF_USER bit. -//@{ - -/// CODE xref types -enum cref_t -{ - fl_U, ///< unknown -- for compatibility with old - ///< versions. Should not be used anymore. - fl_CF = 16, ///< Call Far - ///< This xref creates a function at the - ///< referenced location - fl_CN, ///< Call Near - ///< This xref creates a function at the - ///< referenced location - fl_JF, ///< Jump Far - fl_JN, ///< Jump Near - fl_USobsolete, ///< User specified (obsolete) - fl_F, ///< Ordinary flow: used to specify execution - ///< flow to the next instruction. -}; - -/// DATA xref types -enum dref_t -{ - dr_U, ///< Unknown -- for compatibility with old - ///< versions. Should not be used anymore. - dr_O, ///< Offset - ///< The reference uses 'offset' of data - ///< rather than its value - ///< OR - ///< The reference appeared because the "OFFSET" - ///< flag of instruction is set. - ///< The meaning of this type is IDP dependent. - dr_W, ///< Write access - dr_R, ///< Read access - dr_T, ///< Text (for forced operands only) - ///< Name of data is used in manual operand - dr_I, ///< Informational - ///< (a derived java class references its base - ///< class informationally) - dr_S, ///< Reference to enum member (symbolic constant) -}; - - -/// \defgroup XREF_T Cross-Reference type flags -/// These flags are combined with a ::cref_t or ::dref_t value to describe the -/// type of a cross reference. -/// These bits are accessible to the kernel. -//@{ -#define XREF_USER 0x20 ///< User specified xref. - ///< This xref will not be deleted by IDA. - ///< This bit should be combined with - ///< the existing xref types (::cref_t & ::dref_t) - ///< Cannot be used for fl_F xrefs -#define XREF_TAIL 0x40 ///< Reference to tail byte in extrn symbols -#define XREF_BASE 0x80 ///< Reference to the base part of an offset -#define XREF_MASK 0x1F ///< Mask to get xref type - -#define XREF_PASTEND 0x100 ///< Reference is past item. This bit may be passed to - ///< add_dref() functions but it won't be saved in - ///< the database. It will prevent the destruction - ///< of eventual alignment directives. -//@} - -/// Get character describing the xref type. -/// \param xrtype combination of \ref XREF_T and a ::cref_t of ::dref_t value -idaman char ida_export xrefchar(char xrtype); - -//@} xref_type - -//--------------------------------------------------------------------------- -// A D D / D E L E T E C R O S S - R E F E R E N C E S -//--------------------------------------------------------------------------- - -/// Create a code cross-reference. -/// \param from linear address of referencing instruction -/// \param to linear address of referenced instruction -/// \param type cross-reference type -/// \return success - -idaman bool ida_export add_cref(ea_t from, ea_t to, cref_t type); - - -/// Delete a code cross-reference. -/// \param from linear address of referencing instruction -/// \param to linear address of referenced instruction -/// \param expand policy to delete the referenced instruction -/// - 1: plan to delete the referenced instruction if it has -/// no more references. -/// - 0: don't delete the referenced instruction even if no -/// more cross-references point to it -/// \retval true if the referenced instruction will be deleted - -idaman bool ida_export del_cref(ea_t from, ea_t to, bool expand); - - -/// Create a data cross-reference. -/// \param from linear address of referencing instruction or data -/// \param to linear address of referenced data -/// \param type cross-reference type -/// \return success (may fail if user-defined xref exists from->to) - -idaman bool ida_export add_dref(ea_t from, ea_t to, dref_t type); - - -/// Delete a data cross-reference. -/// \param from linear address of referencing instruction or data -/// \param to linear address of referenced data - -idaman void ida_export del_dref(ea_t from, ea_t to); - - -//------------------------------------------------------------------------- -// E N U M E R A T E ( G E T ) C R O S S - R E F E R E N C E S -//------------------------------------------------------------------------- - -struct xrefblk_t; -/// \name Helper functions -/// Should not be called directly! -//@{ -idaman bool ida_export xrefblk_t_first_from(xrefblk_t *,ea_t from,int flags); -idaman bool ida_export xrefblk_t_next_from(xrefblk_t *); -idaman bool ida_export xrefblk_t_first_to(xrefblk_t *,ea_t to,int flags); -idaman bool ida_export xrefblk_t_next_to(xrefblk_t *); -//@} - -/// Structure to enumerate all xrefs. -/// This structure provides a way to access cross-references from a given address. -/// For example: -/// -/// \code -/// xrefblk_t xb; -/// for ( bool ok=xb.first_from(ea, XREF_ALL); ok; ok=xb.next_from() ) -/// { -/// // xb.to - contains the referenced address -/// } -/// \endcode -/// or: -/// \code -/// xrefblk_t xb; -/// for ( bool ok=xb.first_to(ea, XREF_ALL); ok; ok=xb.next_to() ) -/// { -/// // xb.from - contains the referencing address -/// } -/// \endcode -/// -/// First, all code references will be returned, then all data references. -/// If you need only code references, stop calling next() as soon as you get a dref. -/// -/// If you need only data references, pass #XREF_DATA flag to first(). -/// You may not modify the contents of a xrefblk_t structure! It is read only. -struct xrefblk_t -{ - ea_t from; ///< the referencing address - filled by first_to(),next_to() - ea_t to; ///< the referenced address - filled by first_from(), next_from() - uchar iscode; ///< 1-is code reference; 0-is data reference - uchar type; ///< type of the last returned reference (::cref_t & ::dref_t) - uchar user; ///< 1-is user defined xref, 0-defined by ida - -/// \defgroup XREF_ Xref enumeration flags -/// Passed as 'flags' parameter to functions in ::xrefblk_t -//@{ -#define XREF_ALL 0x00 ///< return all references -#define XREF_FAR 0x01 ///< don't return ordinary flow xrefs -#define XREF_DATA 0x02 ///< return data references only -//@} - - /// \name Get first/next - /// The following functions first return code references, then data references. - /// If you need only code references, you need to check 'iscode' after each call. - /// If you need only data references, use #XREF_DATA bit. - /// \param flags \ref XREF_ - /// \retval 1 ok - /// \retval 0 no more xrefs - //@{ - - /// Get first xref from the given address (store in #to) - bool first_from(ea_t _from, int flags) - { return xrefblk_t_first_from(this, _from, flags); } - - /// Get next xref from address provided to first_from() - bool next_from(void) - { return xrefblk_t_next_from(this); } - - /// Get xref to given address (store in #from) - bool first_to(ea_t _to, int flags) - { return xrefblk_t_first_to(this, _to, flags); } - - /// Get next xref to address provided to first_to() - bool next_to(void) - { return xrefblk_t_next_to(this); } - - /// Get xref from '_from' that comes after '_to' - bool next_from(ea_t _from, ea_t _to, int flags) - { - if ( first_from(_from, flags) ) - { - to = _to; - return next_from(); - } - return false; - } - - /// Get xref to '_to' that comes after '_from' - bool next_to(ea_t _from, ea_t _to, int flags) - { - if ( first_to(_to, flags) ) - { - from = _from; - return next_to(); - } - return false; - } - - //@} -}; - -//------------------------------------------------------------------------- -/// Get first data referenced from the specified address. -/// \param from linear address of referencing instruction or data -/// \return linear address of first (lowest) data referenced from the specified address. -/// Return #BADADDR if the specified instruction/data doesn't reference -/// to anything. - -idaman ea_t ida_export get_first_dref_from(ea_t from); - - -/// Get next data referenced from the specified address. -/// \param from linear address of referencing instruction or data -/// \param current linear address of current referenced data. -/// This value is returned by get_first_dref_from() or -/// previous call to get_next_dref_from() functions. -/// \return linear address of next data or #BADADDR. - -idaman ea_t ida_export get_next_dref_from(ea_t from, ea_t current); - - -/// Get address of instruction/data referencing to the specified data. -/// \param to linear address of referencing instruction or data -/// \return #BADADDR if nobody refers to the specified data. - -idaman ea_t ida_export get_first_dref_to(ea_t to); - - -/// Get address of instruction/data referencing to the specified data -/// \param to linear address of referencing instruction or data -/// \param current current linear address. -/// This value is returned by get_first_dref_to() or -/// previous call to get_next_dref_to() functions. -/// \return #BADADDR if nobody refers to the specified data. - -idaman ea_t ida_export get_next_dref_to(ea_t to, ea_t current); - - -/// Get first instruction referenced from the specified instruction. -/// If the specified instruction passes execution to the next instruction -/// then the next instruction is returned. Otherwise the lowest referenced -/// address is returned (remember that xrefs are kept sorted!). -/// \param from linear address of referencing instruction -/// \return first referenced address. -/// If the specified instruction doesn't reference to other instructions -/// then returns #BADADDR. - -idaman ea_t ida_export get_first_cref_from(ea_t from); - - -/// Get next instruction referenced from the specified instruction. -/// \param from linear address of referencing instruction -/// \param current linear address of current referenced instruction -/// This value is returned by get_first_cref_from() or -/// previous call to get_next_cref_from() functions. -/// \return next referenced address or #BADADDR. - -idaman ea_t ida_export get_next_cref_from(ea_t from, ea_t current); - - -/// Get first instruction referencing to the specified instruction. -/// If the specified instruction may be executed immediately after its -/// previous instruction then the previous instruction is returned. -/// Otherwise the lowest referencing address is returned. -/// (remember that xrefs are kept sorted!). -/// \param to linear address of referenced instruction -/// \return linear address of the first referencing instruction or #BADADDR. - -idaman ea_t ida_export get_first_cref_to(ea_t to); - - -/// Get next instruction referencing to the specified instruction. -/// \param to linear address of referenced instruction -/// \param current linear address of current referenced instruction -/// This value is returned by get_first_cref_to() or -/// previous call to get_next_cref_to() functions. -/// \return linear address of the next referencing instruction or #BADADDR. - -idaman ea_t ida_export get_next_cref_to(ea_t to, ea_t current); - - -/// \name Far code references -/// The following functions are similar to get_{first|next}_cref_{from|to} -/// functions. The only difference is that they don't take into account -/// ordinary flow of execution. Only jump and call xrefs are returned. -/// (fcref means "far code reference") -//@{ -idaman ea_t ida_export get_first_fcref_from(ea_t from); -idaman ea_t ida_export get_next_fcref_from(ea_t from, ea_t current); -idaman ea_t ida_export get_first_fcref_to(ea_t to); -idaman ea_t ida_export get_next_fcref_to(ea_t to, ea_t current); -//@} - - -/// Has a location external to the function references? - -idaman bool ida_export has_external_refs(func_t *pfn, ea_t ea); - - -//------------------------------------------------------------------------- -// S W I T C H T A B L E F U N C T I O N S -//------------------------------------------------------------------------- -#ifdef NALT_HPP - -/// Create switch table from the switch information. -/// Usually there is no need to call this function directly because the kernel -/// will call it for the result of \ph{is_switch()}. -/// \param insn_ea address of the 'indirect jump' instruction -/// \param si switch information -/// \return success - -idaman bool ida_export create_switch_table( - ea_t insn_ea, - const switch_info_t &si); - - -/// Create code xrefs for the switch table. -/// This function creates xrefs from the indirect jump. -/// Usually there is no need to call this function directly because the kernel -/// will call it for switch tables -/// \param insn_ea address of the 'indirect jump' instruction -/// \param si switch information - -idaman void ida_export create_switch_xrefs( - ea_t insn_ea, - const switch_info_t &si); - - -/// Vector of case values - see calc_switch_cases() -typedef qvector<svalvec_t> casevec_t; - - -/// Get detailed information about the switch table cases. -/// \param casevec vector of case values... -/// \param targets ...and corresponding target addresses -/// \param insn_ea address of the 'indirect jump' instruction -/// \param si switch information -/// \return success - -idaman bool ida_export calc_switch_cases( - casevec_t *casevec, - eavec_t *targets, - ea_t insn_ea, - const switch_info_t &si); - -/// Delete information created by the call of create_switch_table(). -/// It delete parent address for each switch target. -/// \param insn_ea address of the 'indirect jump' instruction -/// \param si switch information -idaman void ida_export delete_switch_table( - ea_t jump_ea, - const switch_info_t &si); - -#endif - -//------------------------------------------------------------------------- -// F U N C T I O N S F O R T H E K E R N E L -//------------------------------------------------------------------------- - -/// \cond -idaman bool ida_export create_xrefs_from(ea_t ea); // returns false: no item at ea -idaman void ida_export delete_all_xrefs_from(ea_t ea, bool expand); -/// \endcond - - -#endif // _XREF_HPP diff --git a/idasdk75/install_make.txt b/idasdk75/install_make.txt deleted file mode 100644 index 907bafd..0000000 --- a/idasdk75/install_make.txt +++ /dev/null @@ -1,166 +0,0 @@ - - -Please read "readme.txt" before reading this file! - - -Preparing the build environment on MS Windows ---------------------------------------------- - - Prerequisites - ============= - - In addition to the compiler specified in readme.txt, Cygwin is required - on MS Windows. It is available from: - - https://www.cygwin.com/ - - Make sure to install the 32-bit version of Cygwin (setup-x86.exe) and to - install the 'make' package. - - - Build environment - ================= - - On MS Windows, you may build the SDK using either the Cygwin shell or the - Command Prompt (either cmd.exe or a Developer Command Prompt for Visual - Studio). - - If you wish to use the Cygwin shell to build the SDK, start it with: - - > C:\cygwin\cygwin.bat - - If you wish to use the Command Prompt, you must add Cygwin's bin directory - to your PATH: - - > set PATH=C:\cygwin\bin;%PATH% - - You should then navigate to IDA's SDK directory, for example: - - > cd C:\idasdk - - The MS Windows build automatically generates a configuration file from the - top-level directory of the SDK. To build this configuration file directly, - invoke make from the top-level directory with: - - > make env - - If this file is not generated, you will hit this error message: - - cl : Command line error D8022 : cannot open '../../x64_win_vc_32.cfg' - - - Preparing the SDK - ================= - - The SDK provides a linker wrapper under the 'bin' directory. You may have to - set the executable flag on the 'bin\ld.exe' binary. - - You must add the SDK's bin directory to your PATH. - - On MS Windows' Command Prompt: - - > set PATH=C:\idasdk\bin;%PATH% - - On the Cygwin shell: - - $ export PATH=~/idasdk/bin:$PATH - - You should modify the 'defaults.mk' file to point to your Visual Studio and - Windows SDK paths (The 'VSPATH', 'WSDKPATH', and 'WSDKVER' variables). - - -Preparing the build environment on Linux and Mac OS X ------------------------------------------------------ - - You must add the SDK's bin directory to your PATH. - - $ export PATH=~/idasdk/bin:$PATH - - -Target platform ---------------- - - The target platform must be specified using one of the following environment - variables: - - - MS Windows: __NT__ - - Linux: __LINUX__ - - Mac OS X: __MAC__ - - If no target platform is specified, the build defaults to MS Windows (__NT__). - - It is a good idea to specify the platform directly on your ~/.bashrc file: - - MS Windows (Cygwin): - export __NT__=1 - - Linux: - export __LINUX__=1 - - Mac OS X: - export __MAC__=1 - - -How to build the SDK from the command-line ------------------------------------------- - - All source files are the same for all platforms and are compiled using the - same makefiles. The build commands are different between operating systems. - - - On Linux and Mac OS X - ===================== - - It should suffice to invoke 'make' directly: - - make - - If you did not export the target platform's environment variable, you may - specify the target in the command line, for example: - - make __LINUX__=1 - - To build for IDA64 (64-bit ea_t size): - - make __EA64__=1 - - Please note that both ida32 and ida64 are 64-bit applications. - - To build 32-bit debug servers, you must set the __X86__ variable. This can - be achieved in the command line with: - - make __X86__=1 - - You may also run the 'idamake.pl' script instead of 'make'. It is a post- - processing script for make, and will prevent the printing of some warnings - which cannot be disabled in the compiler. For example, there is this warning - from gcc: - - warning: format ‘%a’ expects argument of type ‘double’, but argument 2 has type ‘ea_t {aka unsigned int}’ [-Wformat=] - - There is also an environment option IDAMAKE_SIMPLIFY which can be passed to - 'idamake.pl', which turns on filtering of compiler command line. - - Some examples: - make __LINUX__=1 -- non-optimized linux build - make NDEBUG=1 __MAC__=1 -- optimized mac build - make NDEBUG=1 __NT__=1 __EA64__=1 -- optimized ida64 windows build - IDAMAKE_SIMPLIFY=1 idamake.pl [...] -- filter build system output - - - On MS Windows - ============= - - The build target is selected by using special bat files, present in the bin/ - directory. - - m.bat ida32 - mm.bat ida64 - -Aliases -------- - - Creating aliases for the build commands is a good idea. I have the following - in my .bashrc file: - - export __LINUX__=1 - export PATH=~/idasdk/bin:$PATH - alias mx='make 2>&1' - alias mmx='__EA64__=1 make 2>&1' diff --git a/idasdk75/ldr/aif/makefile b/idasdk75/ldr/aif/makefile deleted file mode 100644 index 7ae0e2c..0000000 --- a/idasdk75/ldr/aif/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=aif - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)aif$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../aof/aof.h ../idaldr.h aif.cpp aif.h aifcmn.cpp diff --git a/idasdk75/ldr/amiga/amiga.cpp b/idasdk75/ldr/amiga/amiga.cpp deleted file mode 100644 index 3158511..0000000 --- a/idasdk75/ldr/amiga/amiga.cpp +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 by Ilfak Guilfanov, <ig@datarescue.com> - * ALL RIGHTS RESERVED. - * - * AMIGA hunk file loader - * - */ - - -#include "../idaldr.h" -#include "amiga.hpp" - -#define SkipLong(Longs) do { if ( qlseek(li, 4 * qoff64_t(Longs), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 ) -#define SkipWord(Words) do { if ( qlseek(li, 2 * qoff64_t(Words), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 ) -#define SkipByte(Bytes) do { if ( qlseek(li, 1 * qoff64_t(Bytes), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 ) - -//------------------------------------------------------------------------------ -static void ask_for_help(void) -{ - ask_for_feedback("This file contains some untested records"); -} - -//------------------------------------------------------------------------------ -static char *read_name(linput_t *li, char *buf, size_t bufsize, int Longs) -{ - if ( ssize_t(bufsize) > 0 ) - { - size_t sz = Longs; - if ( sz != 0 ) - { - sz *= 4; - if ( sz >= bufsize ) - sz = bufsize-1; - lread(li, buf, sz); - } - buf[sz] = '\0'; - } - return buf; -} - -//------------------------------------------------------------------------------ -void idaapi load_file(linput_t *li,ushort /*_neflags*/,const char * /*fileformatname*/) -{ - set_processor_type("68040", SETPROC_LOADER); - - uint32 Type, Data, i; - int nums; - char NameString[MAXSTR]; - bool has_header = false; - bool shortreloc = false; - ea_t start = to_ea(inf_get_baseaddr(), 0); - ea_t end = start; - -// -// The first pass -// - qoff64_t fsize = qlsize(li); - qlseek(li, 0); - while ( true ) - { - i = (uint32)qlread(li, &Type, sizeof(Type)); - if ( i != sizeof(Type) ) - { - if ( i != 0 ) - warning("There %s %u extra byte%s at end of file.", - i == 1 ? "is" : "are", - i, - i == 1 ? "" : "s"); - break; - } - Type = swap32(Type); - - if ( Type == HUNK_DREL32 && has_header ) - Type = HUNK_DREL32EXE; - - switch ( Type & 0xFFFF ) - { - case HUNK_UNIT: - read_name(li, NameString, sizeof(NameString), mf_readlong(li)); - break; - case HUNK_NAME: - read_name(li, NameString, sizeof(NameString), mf_readlong(li)); - break; - case HUNK_LIB: - SkipLong(1); - break; - case HUNK_INDEX: - SkipLong(mf_readlong(li)); - break; - case HUNK_CODE: - case HUNK_PPC_CODE: - case HUNK_DATA: - case HUNK_BSS: - { - Data = mf_readlong(li); - Data <<= 2; - Data &= 0x7FFFFFFF; - start = free_chunk(end, Data, -0xF); - end = start + Data; - if ( end < start ) - loader_failure("Segment address overlow: %a..%a", start, end); - const char *sname = NULL; - sel_t sel = get_segm_qty() + 1; - set_selector(sel, 0); - switch ( Type & 0xFFFF ) - { - case HUNK_PPC_CODE: - set_processor_type("ppc", SETPROC_LOADER); - sname = "PPC_CODE"; - break; - case HUNK_CODE: - sname = "CODE"; - if ( inf_get_start_cs() == BADSEL ) - { - inf_set_start_cs(sel); - inf_set_start_ip(start); - } - break; - case HUNK_DATA: - sname = "DATA"; - break; - case HUNK_BSS: - sname = "BSS"; - break; - } - bool sparse = true; - if ( (Type & 0xFFFF) != HUNK_BSS ) - { - uint64 rest = fsize - qltell(li); - if ( end-start > rest ) - loader_failure("Too big segment %a..%a", start, end); - sparse = false; - file2base(li, qltell(li), start, end, FILEREG_PATCHABLE); - } - segment_t s; - s.sel = setup_selector(sel); - s.start_ea = start; - s.end_ea = end; - s.align = saRelByte; - s.comb = scPub; - s.bitness = PH.get_segm_bitness(); - add_segm_ex(&s, sname, sname, ADDSEG_NOSREG|(sparse ? ADDSEG_SPARSE : 0)); - } - break; - case HUNK_RELOC32SHORT: - case HUNK_DREL32EXE: - shortreloc = true; - // no break - case HUNK_RELRELOC32: - case HUNK_ABSRELOC16: - case HUNK_RELRELOC26: - case HUNK_RELOC32: - case HUNK_RELOC16: - case HUNK_RELOC8: - case HUNK_DREL32: - case HUNK_DREL16: - case HUNK_DREL8: - nums = 0; - while ( true ) - { - if ( qltell(li) >= fsize ) -TRUNCATED_INPUT: - loader_failure("Truncated file"); - Data = shortreloc ? mf_readshort(li) : mf_readlong(li); - if ( Data == 0 ) - break; - shortreloc ? mf_readshort(li) : mf_readlong(li); - if ( shortreloc ) - SkipWord(Data); - else - SkipLong(Data); - nums += Data; - } - if ( (nums & 1) == 0 && shortreloc ) - SkipWord(1); - shortreloc = false; - break; - case HUNK_EXT: - while ( true ) - { - if ( qltell(li) >= fsize ) - goto TRUNCATED_INPUT; - Data = mf_readlong(li); - if ( Data == 0 ) - break; - /* Is it followed by a symbol name? */ - if ( Data & 0xFFFFFF ) - read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); - - /* Remember extension type. */ - int32 exttype = (Data >> 24) & 0xFF; - - /* Display value of symbol. */ - if ( exttype == EXT_DEF || exttype == EXT_ABS || exttype == EXT_RES ) - mf_readlong(li); - - /* Skip relocation information. */ - if ( exttype == EXT_REF32 - || exttype == EXT_REF16 - || exttype == EXT_REF8 -// || exttype == EXT_DEXT32 -// || exttype == EXT_DEXT16 -// || exttype == EXT_DEXT8 -// || exttype == EXT_RELREF32 - || exttype == EXT_RELREF26 ) - { - SkipLong(mf_readlong(li)); - } - - /* Display size of common block. */ - if ( exttype == EXT_COMMON ) - { - mf_readlong(li); - SkipLong(mf_readlong(li)); - } - } - break; - case HUNK_SYMBOL: - while ( true ) - { - if ( qltell(li) >= fsize ) - goto TRUNCATED_INPUT; - Data = mf_readlong(li); - if ( Data == 0 ) - break; - read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); - mf_readlong(li); - } - break; - case HUNK_DEBUG: - SkipLong(mf_readlong(li)); - break; - case HUNK_END: - break; - case HUNK_HEADER: - { - has_header = true; - while ( true ) - { - if ( qltell(li) >= fsize ) - goto TRUNCATED_INPUT; - Data = mf_readlong(li); - if ( Data == 0 ) - break; - read_name(li, NameString, sizeof(NameString), Data); - } - mf_readlong(li); - int32 From = mf_readlong(li); - int32 To = mf_readlong(li); - SkipLong(To-From+1); - } - break; - case HUNK_OVERLAY: - { - int32 TabSize = mf_readlong(li); - if ( TabSize ) - { - mf_readlong(li); - SkipLong(TabSize); - } - int32 hunktype = mf_readlong(li); - if ( TabSize && hunktype >= HUNK_UNIT && hunktype <= HUNK_ABSRELOC16 ) - qlseek(li, -4, SEEK_CUR); - } - break; - case HUNK_BREAK: - break; - default: - warning("Unknown hunk type %04X - Aborting!", Type & 0xFFFF); - return; - } - } - -// -// The second pass -// - qlseek(li, 0); - int nseg = 0; - while ( true ) - { - i = (uint32)qlread(li, &Type, sizeof(Type)); - if ( i != sizeof(Type) ) - break; - Type = swap32(Type); - - if ( Type == HUNK_DREL32 && has_header ) - Type = HUNK_DREL32EXE; - - switch ( Type & 0xFFFF ) - { - case HUNK_UNIT: - read_name(li, NameString, sizeof(NameString), mf_readlong(li)); - add_pgm_cmt("Unit: %s", NameString); - break; - case HUNK_NAME: - read_name(li, NameString, sizeof(NameString), mf_readlong(li)); - add_pgm_cmt("Title: %s", NameString); - break; - case HUNK_LIB: - mf_readlong(li); - break; - case HUNK_INDEX: - SkipLong(mf_readlong(li)); - break; - case HUNK_CODE: - case HUNK_PPC_CODE: - case HUNK_DATA: - case HUNK_BSS: - Data = mf_readlong(li); - Data <<= 2; - Data &= 0x7FFFFFFF; - if ( (Type & 0xFFFF) != HUNK_BSS ) - SkipByte(Data); - nseg++; - break; - case HUNK_RELOC32SHORT: - case HUNK_DREL32EXE: - shortreloc = true; - // no break - case HUNK_RELRELOC32: - case HUNK_ABSRELOC16: - case HUNK_RELRELOC26: - case HUNK_RELOC32: - case HUNK_RELOC16: - case HUNK_RELOC8: - case HUNK_DREL32: - case HUNK_DREL16: - case HUNK_DREL8: - nums = 0; - while ( (Data=(shortreloc ? mf_readshort(li) : mf_readlong(li))) != 0 ) - { - uint32 dat2 = shortreloc ? mf_readshort(li) : mf_readlong(li); - segment_t *s = get_segm_by_sel(dat2+1); - segment_t *ssrc = get_segm_by_sel(nseg); - ea_t base = BADADDR; - if ( ssrc != NULL ) - base = ssrc->start_ea; - else - s = NULL; - int elsize = shortreloc ? 2 : 4; - validate_array_count_or_die(li, Data, elsize, "Number of relocations"); - for ( uint32 dat3 = Data; dat3; --dat3 ) - { - uint32 off = shortreloc ? mf_readshort(li) : mf_readlong(li); - if ( s != NULL ) - { - ea_t src = base + off; - ea_t dst = s->start_ea; - ea_t target = BADADDR; - fixup_type_t fd_type = 0; - switch ( Type & 0xFFFF ) - { - case HUNK_RELRELOC32: - case HUNK_RELOC32: - case HUNK_DREL32: - case HUNK_RELOC32SHORT: - case HUNK_DREL32EXE: - target = get_dword(src)+dst; - put_dword(src, target); - fd_type = FIXUP_OFF32; - break; - case HUNK_ABSRELOC16: - case HUNK_RELRELOC26: - case HUNK_RELOC16: - case HUNK_DREL16: - target = get_word(src)+dst; - put_word(src, target); - fd_type = FIXUP_OFF16; - break; - case HUNK_RELOC8: - case HUNK_DREL8: - target = get_byte(src)+dst; - put_byte(src, (uint32)target); - fd_type = FIXUP_OFF8; - break; - } - if ( fd_type != 0 ) - { - fixup_data_t fd(fd_type); - fd.sel = dat2 + 1; - fd.off = target; - fd.set(src); - } - } - else - { - ask_for_help(); - } - } - nums += Data; - } - if ( (nums & 1) == 0 && shortreloc ) - SkipWord(1); - shortreloc = false; - break; - case HUNK_EXT: - ask_for_help(); - while ( (Data=mf_readlong(li)) != 0 ) - { - switch ( (Data >> 24) & 0xFF ) - { - case EXT_DEF: msg(" EXT_DEF"); break; - case EXT_ABS: msg(" EXT_ABS"); break; - case EXT_RES: msg(" EXT_RES"); break; - case EXT_REF32: msg(" EXT_REF32"); break; - case EXT_COMMON: msg(" EXT_COMMON"); break; - case EXT_REF16: msg(" EXT_REF16"); break; - case EXT_REF8: msg(" EXT_REF8"); break; -// case EXT_DEXT32: msg(" EXT_DEXT32"); break; -// case EXT_DEXT16: msg(" EXT_DEXT16"); break; -// case EXT_DEXT8: msg(" EXT_DEXT8"); break; -// case EXT_RELREF32: msg(" EXT_RELREF32"); break; -// case EXT_RELREF26: msg(" EXT_RELREF26"); break; -// case EXT_RELCOMMON: msg(" EXT_RELCOMMON"); break; - default: msg(" EXT_??? (%02x)\n",(Data >> 24) & 0xFF); break; - } - - /* Is it followed by a symbol name? */ - - if ( Data & 0xFFFFFF ) - { - read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); - msg(" %s", NameString); - } - - /* Remember extension type. */ - int32 exttype = (Data >> 24) & 0xFF; - - /* Display value of symbol. */ - if ( exttype == EXT_DEF || exttype == EXT_ABS || exttype == EXT_RES ) - { - if ( !(Data & 0xFFFFFF) ) - msg(" ???"); - - Data = mf_readlong(li); - msg("%08X", Data); - } - - /* Skip relocation information. */ - if ( exttype == EXT_REF32 - || exttype == EXT_REF16 - || exttype == EXT_REF8 -// || exttype == EXT_DEXT32 -// || exttype == EXT_DEXT16 -// || exttype == EXT_DEXT8 -// || exttype == EXT_RELREF32 - || exttype == EXT_RELREF26 ) - { - Data = mf_readlong(li); - msg("= %u entr%s", Data, Data == 1 ? "y" : "ies"); - SkipLong(Data); - } - - /* Display size of common block. */ - if ( exttype == EXT_COMMON ) - { - Data = mf_readlong(li); - - msg(" Size = %u bytes", Data << 2); - Data = mf_readlong(li); - SkipLong(Data); - } - msg("\n"); - } - break; - case HUNK_SYMBOL: - while ( (Data=mf_readlong(li)) != 0 ) - { - /* Display name. */ - read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); - - /* Display value. */ - Data = mf_readlong(li); - - segment_t *ssrc = get_segm_by_sel(nseg); - if ( ssrc == NULL ) - ask_for_help(); - else - set_name(ssrc->start_ea+Data, NameString, SN_NOCHECK | SN_NOWARN | SN_IDBENC); - } - break; - case HUNK_DEBUG: - SkipLong(mf_readlong(li)); - break; - case HUNK_END: - break; - case HUNK_HEADER: - { - has_header = true; - while ( (Data=mf_readlong(li)) != 0 ) - read_name(li, NameString, sizeof(NameString), Data); - mf_readlong(li); - int32 From = mf_readlong(li); - int32 To = mf_readlong(li); - SkipLong(To-From+1); - } - break; - case HUNK_OVERLAY: - { - int32 TabSize = mf_readlong(li); - if ( TabSize ) - { - mf_readlong(li); - SkipLong(TabSize); - } - int32 hunktype = mf_readlong(li); - if ( TabSize && hunktype >= HUNK_UNIT && hunktype <= HUNK_ABSRELOC16 ) - qlseek(li, -4, SEEK_CUR); - } - break; - case HUNK_BREAK: - break; - default: - warning("Unknown hunk type %04X - Aborting!", Type & 0xFFFF); - return; - } - } - - create_filename_cmt(); -} - -//-------------------------------------------------------------------------- -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - qlseek(li, 0); - uint32 type; - if ( qlread(li, &type, sizeof(uint32)) == sizeof(uint32) - && swap32(type) == HUNK_HEADER ) - { - *fileformatname = "Amiga hunk file"; - *processor = "68040"; - return 1; - } - return 0; -} - -//-------------------------------------------------------------------------- -int idaapi move_segm_relocs(ea_t from, ea_t to, asize_t size, const char *fileformatname) -{ - qnotused(size); - qnotused(fileformatname); - if ( from == BADADDR ) - { - // The entire program is being rebased. - // In this case, 'to' actually contains a delta value; the number of bytes - // forward (positive) or backward (negative) that the whole database is - // being moved. - ea_t delta = to; - - //fix up relocations - fixup_data_t fd; - - for ( ea_t xEA = get_first_fixup_ea(); xEA != BADADDR; xEA = get_next_fixup_ea(xEA) ) - { - show_addr(xEA); - - get_fixup(&fd, xEA); - fd.off += delta; - - switch ( fd.get_type() ) - { - case FIXUP_OFF8: - put_byte(xEA, fd.off); - break; - case FIXUP_OFF16: - put_word(xEA, fd.off); - break; - case FIXUP_OFF32: - put_dword(xEA, fd.off); - break; - } - - set_fixup(xEA, fd); - } - - // Record the new image base address. - inf_set_baseaddr(inf_get_baseaddr() + delta); - //set_imagebase(new_base); - } - - return 1; -} - -//-------------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - move_segm_relocs, - NULL, -}; diff --git a/idasdk75/ldr/amiga/makefile b/idasdk75/ldr/amiga/makefile deleted file mode 100644 index 276c52d..0000000 --- a/idasdk75/ldr/amiga/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=amiga - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)amiga$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h amiga.cpp amiga.hpp diff --git a/idasdk75/ldr/aof/aof.cpp b/idasdk75/ldr/aof/aof.cpp deleted file mode 100644 index 01e7675..0000000 --- a/idasdk75/ldr/aof/aof.cpp +++ /dev/null @@ -1,724 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-97 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - * ARM Object File Loader - * ---------------------- - * This module allows IDA to load ARM object files into - * its database and to disassemble them correctly. - * - * NOTE 1: for the moment only B/BL instruction relocations are - * supported. I cannot find other relocation examples so - * they are not implemented yet. - * - * NOTE 2: Thumb modules are not supported. - * - * This module automatically detects the byte sex and sets inf.mf - * variable accrodingly. - * - * - */ - -#include "../idaldr.h" -#include "aof.h" - -//-------------------------------------------------------------------------- -static void nomem(void) -{ - nomem("AOF loader"); -} - -//-------------------------------------------------------------------------- -static void *read_chunk(linput_t *li, const chunk_entry_t &ce) -{ - void *chunk = qalloc_array<char>(ce.size); - if ( chunk == NULL ) - nomem(); - qlseek(li, ce.file_offset); - lread(li, chunk, ce.size); - return chunk; -} - -//-------------------------------------------------------------------------- -static void check_chunk_ptr( - const chunk_entry_t &ce, - const void *chunkstart, - const void *chunkptr, - size_t ptrsize) -{ - const char *p0 = (const char*)chunkstart; - const char *p1 = (const char*)chunkptr; - if ( p1 < p0 || p1 + ptrsize < p0 || (p1 + ptrsize - p0) > ce.size ) - loader_failure("Corrupted file"); -} - -//-------------------------------------------------------------------------- -static void check_chunk_str( - const chunk_entry_t &ce, - const void *chunkstart, - const void *chunkptr) -{ - const char *p0 = (const char*)chunkstart; - const char *p1 = (const char*)chunkptr; - if ( p1 >= p0 ) - { - const char *chunk_end = p0 + ce.size; - while ( p1 < chunk_end ) - { - if ( *p1 == '\0' ) - return; - ++p1; - } - } - loader_failure("Corrupted file"); -} - -//-------------------------------------------------------------------------- -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - chunk_header_t hd; - if ( qlread(li, &hd, sizeof(hd)) != sizeof(hd) ) - return 0; - if ( hd.ChunkFileId != AOF_MAGIC && hd.ChunkFileId != AOF_MAGIC_B ) - return 0; - if ( hd.num_chunks > hd.max_chunks ) - return 0; - - *fileformatname = "ARM Object File"; - *processor = "arm"; - return 1; -} - -//-------------------------------------------------------------------------- -static void create32( - sel_t sel, - ea_t start_ea, - ea_t end_ea, - const char *name, - const char *classname) -{ - set_selector(sel, 0); - - segment_t s; - s.sel = sel; - s.start_ea = start_ea; - s.end_ea = end_ea; - s.align = saRelByte; - s.comb = scPub; - s.bitness = 1; // 32-bit - - if ( !add_segm_ex(&s, name, classname, ADDSEG_NOSREG|ADDSEG_SPARSE) ) - loader_failure(); -} - -//-------------------------------------------------------------------------- -static ea_t get_area_base(int idx) -{ - segment_t *s = get_segm_by_sel(idx+1); - if ( s == NULL ) - return BADADDR; - return s->start_ea; -} - -//-------------------------------------------------------------------------- -static ea_t find_area( - const chunk_entry_t &ce, - const area_header_t *ah, - int maxarea, - const char *strings, - const char *areaname) -{ - for ( int i=0; i < maxarea; i++, ah++ ) - { - const char *name = strings + size_t(ah->name); - check_chunk_str(ce, strings, name); - if ( streq(name, areaname) ) - return get_area_base(i); - } - return BADADDR; -} - -//-------------------------------------------------------------------------- -static ea_t create_spec_seg( - int *nsegs, - int nelem, - const char *name, - uchar seg_type) -{ - ea_t ea = BADADDR; - if ( nelem != 0 ) - { - nelem *= 4; - ea = free_chunk(inf_get_max_ea(), nelem, 0xFFF); - (*nsegs)++; - create32(*nsegs, ea, ea+nelem, name, CLASS_DATA); - segment_t *s = getseg(ea); - s->type = seg_type; - s->update(); - set_arm_segm_flags(s->start_ea, 2 << SEGFL_SHIFT); // alignment - } - return ea; -} - -//-------------------------------------------------------------------------- -static void process_name(ea_t ea, const char *name, uint32 flags, bool iscode) -{ - // ignore aux names -- they hinder data creation - if ( strstr(name, "$litpool_e$") != NULL ) - return; - if ( flags & SF_PUB ) - { - add_entry(ea, ea, name, iscode, AEF_IDBENC); - make_name_public(ea); - } - else - { - force_name(ea, name, SN_IDBENC); - } - if ( flags & SF_WEAK ) - make_name_weak(ea); - if ( flags & SF_ICASE ) - add_extra_cmt(ea, true, "Case-insensitive label"); - if ( flags & SF_STRNG ) - add_extra_cmt(ea, true, "Strong name"); -} - -//-------------------------------------------------------------------------- -static void reloc_insn(ea_t ea, uint32 rvalue, uint32 type) -{ - uint32 code = get_dword(ea); - switch ( (code >> 24) & 0xF ) - { - case 0x0A: // B - case 0x0B: // BL - { - int32 off = code & 0x00FFFFFFL; - if ( off & 0x00800000L ) - off |= ~0x00FFFFFFL; // extend sign - off <<= 2; - off += rvalue; - off >>= 2; - off &= 0xFFFFFFL; - code &= 0xFF000000L; - code |= off; - put_dword(ea, code); - } - break; - default: - warning("This relocation type is not implemented yet\n" - "\3%a: reloc insn rvalue=%x, rt=%lx", ea, rvalue, - type & RF_II); - break; - } -} - -//-------------------------------------------------------------------------- -inline void swap_chunk_entry(chunk_entry_t *ce) -{ - ce->file_offset = swap32(ce->file_offset); - ce->size = swap32(ce->size); -} - -//-------------------------------------------------------------------------- -static void swap_aof_header(aof_header_t *ahd) -{ - ahd->obj_file_type = swap32(ahd->obj_file_type); - ahd->version = swap32(ahd->version); - ahd->num_areas = swap32(ahd->num_areas); - ahd->num_syms = swap32(ahd->num_syms); - ahd->entry_area = swap32(ahd->entry_area); - ahd->entry_offset = swap32(ahd->entry_offset); -} - -//-------------------------------------------------------------------------- -static void swap_area_header(area_header_t *ah) -{ - ah->name = swap32(ah->name); - ah->flags = swap32(ah->flags); - ah->size = swap32(ah->size); - ah->num_relocs = swap32(ah->num_relocs); - ah->baseaddr = swap32(ah->baseaddr); -} - -//-------------------------------------------------------------------------- -static void swap_sym(sym_t *s) -{ - s->name = swap32(s->name); - s->flags = swap32(s->flags); - s->value = swap32(s->value); - s->area = swap32(s->area); -} - -//-------------------------------------------------------------------------- -// -// load file into the database. -// -void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) -{ - int i; - chunk_header_t hd; - set_processor_type("arm", SETPROC_LOADER); - lread(li, &hd, sizeof(hd)); - if ( hd.ChunkFileId == AOF_MAGIC_B ) // BIG ENDIAN - { - inf_set_be(true); - hd.max_chunks = swap32(hd.max_chunks); - hd.num_chunks = swap32(hd.num_chunks); - } - - validate_array_count_or_die(li, hd.max_chunks, sizeof(chunk_entry_t), "Number of chunks"); - chunk_entry_t *ce = qalloc_array<chunk_entry_t>(size_t(hd.max_chunks)); - if ( ce == NULL ) - nomem(); - lread(li, ce, sizeof(chunk_entry_t)*size_t(hd.max_chunks)); - if ( inf_is_be() ) - for ( i=0; i < hd.max_chunks; i++ ) - swap_chunk_entry(ce+i); - - int head = -1; // AOF Header - int area = -1; // Areas - int idfn = -1; // Identification - int symt = -1; // Symbol Table - int strt = -1; // String Table - - for ( i=0; i < hd.max_chunks; i++ ) - { - if ( ce[i].file_offset == 0 ) - continue; - if ( strneq(ce[i].chunkId, OBJ_HEAD, sizeof(ce[i].chunkId)) ) - head = i; - if ( strneq(ce[i].chunkId, OBJ_AREA, sizeof(ce[i].chunkId)) ) - area = i; - if ( strneq(ce[i].chunkId, OBJ_IDFN, sizeof(ce[i].chunkId)) ) - idfn = i; - if ( strneq(ce[i].chunkId, OBJ_SYMT, sizeof(ce[i].chunkId)) ) - symt = i; - if ( strneq(ce[i].chunkId, OBJ_STRT, sizeof(ce[i].chunkId)) ) - strt = i; - } - if ( head == -1 || area == -1 || strt == -1 || symt == -1 || idfn == -1 ) - { - qfree(ce); - loader_failure("One of required chunks is missing"); - } - - char *strings = (char *)read_chunk(li, ce[strt]); - aof_header_t *ahd = (aof_header_t *)read_chunk(li, ce[head]); - check_chunk_ptr(ce[head], ahd, ahd, sizeof(aof_header_t)); - if ( inf_is_be() ) - swap_aof_header(ahd); - -// -// Areas -// - - area_header_t *ah = (area_header_t *)(ahd + 1); - if ( inf_is_be() ) - { - for ( i=0; i < ahd->num_areas; i++ ) - { - check_chunk_ptr(ce[head], ahd, ah+i, sizeof(area_header_t)); - swap_area_header(ah+i); - } - } - qoff64_t offset = ce[area].file_offset; - inf_set_specsegs(inf_is_64bit() ? 8 : 4); - ea_t ea = to_ea(inf_get_baseaddr(), 0); - for ( i=0; i < ahd->num_areas; i++, ah++ ) - { - check_chunk_ptr(ce[head], ahd, ah, sizeof(area_header_t)); - if ( ah->flags & AREA_DEBUG ) - { - offset += ah->size; - offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); - continue; - } - if ( ah->flags & AREA_ABS ) - { - ea = ah->baseaddr; - if ( free_chunk(ea, ah->size, 1) != ea ) - error("Cannot allocate area at %a", ea); - } - else - { - ea = free_chunk(ea, ah->size, 0xFFF); - } - if ( (ah->flags & AREA_BSS) == 0 ) - { - ea_t end = ea + ah->size; - uint64 fsize = qlsize(li); - if ( offset > fsize - || fsize-offset < ah->size - || end < ea ) - { - loader_failure("Corrupted file"); - } - file2base(li, offset, ea, end, FILEREG_PATCHABLE); - offset += ah->size; - } - const char *name = strings + size_t(ah->name); - check_chunk_str(ce[strt], strings, name); - const char *classname; - if ( ah->flags & AREA_CODE ) - classname = CLASS_CODE; - else if ( ah->flags & (AREA_BSS|AREA_COMREF) ) - classname = CLASS_BSS; - else - classname = CLASS_DATA; - create32(i+1, ea, ea+ah->size, name, classname); - - segment_t *s = getseg(ea); - ushort sflags = (ah->flags & 0x1F) << SEGFL_SHIFT; // alignment - if ( ah->flags & AREA_BASED ) - sflags |= (SEGFL_BASED|ah->get_based_reg()); - if ( ah->flags & AREA_PIC ) - sflags |= SEGFL_PIC; - if ( ah->flags & AREA_REENTR ) - sflags |= SEGFL_REENTR; - if ( ah->flags & AREA_HALFW ) - sflags |= SEGFL_HALFW; - if ( ah->flags & AREA_INTER ) - sflags |= SEGFL_INTER; - if ( ah->flags & AREA_COMMON ) - sflags |= SEGFL_COMDEF; - if ( ah->flags & (AREA_COMMON|AREA_COMREF) ) - s->comb = scCommon; - if ( ah->flags & AREA_RDONLY ) - s->perm = SEGPERM_READ; - if ( ah->flags & AREA_ABS ) - s->align = saAbs; - s->update(); - set_arm_segm_flags(s->start_ea, sflags); - - if ( i == 0 ) - { - create_filename_cmt(); - char *id = (char *)read_chunk(li, ce[idfn]); - check_chunk_str(ce[idfn], id, id); - add_pgm_cmt("Translator : %s", id); - qfree(id); - } - - if ( ah->flags & AREA_CODE ) - { - if ( (ah->flags & AREA_32BIT) == 0 ) - add_pgm_cmt("The 26-bit area"); - if ( (ah->flags & AREA_EXTFP) != 0 ) - add_pgm_cmt("Extended FP instructions are used"); - if ( (ah->flags & AREA_NOCHK) != 0 ) - add_pgm_cmt("No Software Stack Check"); - if ( (ah->flags & AREA_THUMB) != 0 ) - add_pgm_cmt("Thumb code area"); - } - else - { - if ( (ah->flags & AREA_SHARED) != 0 ) - add_pgm_cmt("Shared Library Stub Data"); - } - ea += ah->size; - offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); - } - int nsegs = i; - -// -// Symbol Table -// - - ah = (area_header_t *)(ahd + 1); - uint32 *delta = qalloc_array<uint32>(size_t(ahd->num_syms)); - if ( delta == NULL ) - nomem(); - memset(delta, 0, sizeof(uint32)*size_t(ahd->num_syms)); - sym_t *syms = (sym_t *)read_chunk(li, ce[symt]); - if ( inf_is_be() ) - { - for ( i=0; i < ahd->num_syms; i++ ) - { - check_chunk_ptr(ce[symt], syms, syms+i, sizeof(sym_t)); - swap_sym(syms+i); - } - } - int n_undef = 0; - int n_abs = 0; - int n_comm = 0; - - for ( i=0; i < ahd->num_syms; i++ ) - { - sym_t *s = syms + i; - check_chunk_ptr(ce[symt], syms, syms+i, sizeof(sym_t)); - if ( s->flags & SF_DEF ) - { - if ( s->flags & SF_ABS ) - { - n_abs++; - } - else - { - const char *areaname = strings + size_t(s->area); - check_chunk_str(ce[strt], strings, areaname); - ea_t areabase = find_area(ce[strt], ah, size_t(ahd->num_areas), strings, areaname); - delta[i] = (uint32)areabase; - ea_t symea = areabase + s->value; - const char *name = strings + size_t(s->name); - check_chunk_str(ce[strt], strings, name); - if ( s->value == 0 && strcmp(areaname, name) == 0 ) - continue; // HACK! - process_name(symea, name, s->flags, segtype(areabase) == SEG_CODE); - } - } - else - { - if ( (s->flags & SF_PUB) && (s->flags & SF_COMM) ) // ref to common - n_comm++; - else - n_undef++; - } - } - - ea_t abs_ea = create_spec_seg(&nsegs, n_abs, NAME_ABS, SEG_ABSSYM); - ea_t undef_ea = create_spec_seg(&nsegs, n_undef, NAME_UNDEF, SEG_XTRN); - ea_t comm_ea = create_spec_seg(&nsegs, n_comm, NAME_COMMON, SEG_COMM); - if ( n_abs+n_undef+n_comm != 0 ) - { - for ( i=0; i < ahd->num_syms; i++ ) - { - sym_t *s = syms + i; - const char *name = strings + size_t(s->name); - check_chunk_str(ce[strt], strings, name); - if ( s->flags & SF_DEF ) - { - if ( s->flags & SF_ABS ) - { - if ( inf_get_specsegs() == 8 ) - { - put_qword(abs_ea, s->value); - create_qword(abs_ea, 8); - } - else - { - put_dword(abs_ea, s->value); - create_dword(abs_ea, 4); - } - process_name(abs_ea, name, s->flags, false); - delta[i] = s->value; - s->value = uint32(abs_ea - delta[i]); - abs_ea += inf_get_specsegs(); - } - } - else - { - if ( (s->flags & SF_PUB) && (s->flags & SF_COMM) ) // ref to common - { - if ( inf_get_specsegs() == 8 ) - put_qword(comm_ea, s->value); - else - put_dword(comm_ea, s->value); - process_name(comm_ea, name, s->flags, false); - delta[i] = (uint32)comm_ea; - comm_ea += inf_get_specsegs(); - } - else - { - put_dword(undef_ea, 0xE1A0F00E); // RET - process_name(undef_ea, name, s->flags, false); - delta[i] = (uint32)undef_ea; - undef_ea += inf_get_specsegs(); - } - s->value = 0; - } - } - } - -// -// Relocations -// - - offset = ce[area].file_offset; - for ( i=0; i < ahd->num_areas; i++, ah++ ) - { - if ( ah->flags & AREA_DEBUG ) - { - offset += ah->size; - offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); - continue; - } - if ( (ah->flags & AREA_BSS) == 0 ) - offset += ah->size; - qlseek(li, offset); - ea_t base = get_area_base(i); - validate_array_count(li, &ah->num_relocs, sizeof(reloc_t), "Number of relocs", offset); - for ( int j=0; j < ah->num_relocs; j++ ) - { - reloc_t r; - lread(li, &r, sizeof(reloc_t)); - if ( inf_is_be() ) - { - r.type = swap32(r.type); - r.offset = swap32(r.offset); - } - size_t sid = r.sid(); - ea_t rvalue; - ea_t target; - fixup_data_t fd; - if ( r.type & RF_A ) - { - if ( sid >= ahd->num_syms ) - loader_failure("Bad relocation record at file offset %" FMT_64 "x", qltell(li)-sizeof(reloc_t)); - rvalue = delta[sid]; - target = syms[sid].value + rvalue; - fd.set_extdef(); - } - else - { - rvalue = get_area_base((int)sid); - target = rvalue; - if ( rvalue == BADADDR ) - loader_failure("Bad reference to area %" FMT_Z " at file offset %" FMT_64 "x", sid, qltell(li)-sizeof(reloc_t)); - } - segment_t *s = getseg(target); - if ( s == NULL ) - loader_failure("Can't find area for relocation target %a at %" FMT_64 "x", target, qltell(li)-sizeof(reloc_t)); - fd.sel = s->sel; - fd.off = target - get_segm_base(s); - if ( (r.type & RF_R) != 0 ) - { - if ( (r.type & RF_A) != 0 ) - { - // R=1 B=0 or R=1 B=1 - // This specifies PC-relative relocation: to the subject field - // is added the difference between the relocation value and - // the base of the area containing the subject field. - // In pseudo C: - // subject_field = subject_field + - // (relocation_value - - // base_of_area_containing(subject_field)) - rvalue -= base; - } - else - { - // - // As a special case, if A is 0, and the relocation value is - // specified as the base of the area containing the subject - // field, it is not added and: - // subject_field = subject_field - - // base_of_area_containing(subject_field) - // This caters for relocatable PC-relative branches to fixed - // target addresses. If R is 1, B is usually 0. A B value of 1 - // is used to denote that the inter-link-unit value of a - // branch destination is to be used, rather than the more - // usual intra-link-unit value. - rvalue = -base; - } - } - else - { - if ( (r.type & RF_B) != 0 ) - { // R=0 B=1 - // This specifies based area relocation. The relocation value - // must be an address within a based data area. The subject - // field is incremented by the difference between this value - // and the base address of the consolidated based area group - // (the linker consolidates all areas based on the same base - // register into a single, contiguous region of the output - // image). In pseudo C: - // subject_field = subject_field + - // (relocation_value - - // base_of_area_group_containing(relocation_value)) - // For example, when generating re-entrant code, the C - // compiler places address constants in an adcon area based - // on register sb, and loads them using sb relative LDRs. - // At link time, separate adcon areas will be merged and sb - // will no longer point where presumed at compile time. B - // type relocation of the LDR instructions corrects for this. - rvalue -= get_area_base((int)sid); - } - else - { // R=0 B=0 - // This specifies plain additive relocation: the relocation - // value is added to the subject field. In pseudo C: - // subject_field = subject_field + relocation_value - /* nothing to do */; - } - } - ea_t relea = base + r.offset; - switch ( r.type & RF_FT ) - { - case RF_FT_BYTE: // 00 the field to be relocated is a byte - fd.set_type(FIXUP_OFF8); - fd.displacement = get_byte(relea); - add_byte(relea, (uint32)rvalue); - break; - case RF_FT_HALF: // 01 the field to be relocated is a halfword (two bytes) - fd.set_type(FIXUP_OFF16); - fd.displacement = get_word(relea); - add_word(relea, rvalue); - break; - case RF_FT_WORD: // 10 the field to be relocated is a word (four bytes) - fd.set_type(FIXUP_OFF32); - fd.displacement = get_dword(relea); - add_dword(relea, rvalue); - break; - case RF_FT_INSN: // 11 the field to be relocated is an instruction or instruction sequence - reloc_insn(relea, (uint32)rvalue, r.type); - break; - } - fd.set(relea); - } - offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); - } - - if ( ahd->entry_area != 0 ) - { - inf_set_start_cs(ahd->entry_area); - inf_set_start_ip(ahd->entry_offset); - inf_set_start_ea(ahd->entry_offset); - } - - qfree(syms); - qfree(delta); - qfree(ahd); - qfree(strings); - qfree(ce); - inf_set_baseaddr(0); -} - -//---------------------------------------------------------------------- -// -// LOADER DESCRIPTION BLOCK -// -//---------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/ldr/aof/makefile b/idasdk75/ldr/aof/makefile deleted file mode 100644 index 7bc3c78..0000000 --- a/idasdk75/ldr/aof/makefile +++ /dev/null @@ -1,20 +0,0 @@ -PROC=aof - -include ../loader.mak - -#---------------------------------------------------------------------- -# the 'unlib' target must be called explicitly -.PHONY: -unlib: $(F)unlib$(B) -$(F)unlib$(B): $(call dumb_target, pro, $(F)unlib$(O)) - -# MAKEDEP dependency list ------------------ -$(F)aof$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h aof.cpp aof.h -$(F)unlib$(O) : $(I)fpro.h $(I)llong.hpp $(I)pro.h aof.h unlib.cpp diff --git a/idasdk75/ldr/aout/aout.cpp b/idasdk75/ldr/aout/aout.cpp deleted file mode 100644 index 60635d5..0000000 --- a/idasdk75/ldr/aout/aout.cpp +++ /dev/null @@ -1,660 +0,0 @@ -/* - * This Loader Module is written by Yury Haron - * - */ - -/* - L O A D E R for a.out (Linux) -*/ - -#include "../idaldr.h" -//#define DEBUG -#include "aout.h" -#include "common.cpp" -#include "../../module/sparc/notify_codes.hpp" - -class aout_t -{ -public: - exec ex; - nlist *symtab; - char *strtab; - uint32 symcount; // number of symbols in symtab - - uint32 text; // first address of each section - uint32 data; - uint32 bss; - uint32 extrn; - uint32 top; // next available address - - uint32 treloff; // file offset of each section - uint32 dreloff; - uint32 symoff; - uint32 stroff; - - bool msb; - - aout_t(void) - { - memset((void*) this, 0, sizeof(*this)); - } - ~aout_t() - { - if ( symtab != NULL ) - { - qfree(symtab); - symtab = NULL; - } - if ( strtab != NULL ) - { - qfree(strtab); - strtab = NULL; - } - } -}; - -//-------------------------------------------------------------------------- -static const char *guess_processor(const exec &ex) -{ - if ( N_MACHTYPE(ex) ) - { - switch ( N_MACHTYPE(ex) ) - { - case M_386: - case M_386_NETBSD: - return "metapc"; - - case M_ARM: - case M_ARM6_NETBSD: - return "arm"; - - case M_SPARC: - return "sparcb"; - - default: - break; - } - } - return NULL; -} - -//-------------------------------------------------------------------------- -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - exec ex; - int i = get_aout_file_format_index(li, &ex); -#ifdef DEBUG - msg("getfmtindex=%d\n", i); -#endif - - if ( i == 0 ) - return 0; - - static const char *const ff[] = - { - "demand-paged executable with NULL-ptr check", //q - "object or impure executable", //o - "demand-paged executable", //z - "core", //c - "pure executable", //n - "OpenBSD demand-paged executable", //zo - }; - fileformatname->sprnt("a.out (%s)", ff[i-1]); - *processor = guess_processor(ex); -#ifdef DEBUG - msg("%s\n", fileformatname.c_str()); -#endif - return f_AOUT; -} - -//-------------------------------------------------------------------------- -static void create32( - processor_t &ph, - ushort sel, - ea_t start_ea, - ea_t end_ea, - const char *name, - const char *classname) -{ - set_selector(sel, 0); - if ( !add_segm(sel, start_ea, end_ea, name, classname) ) - loader_failure(); - if ( ph.id == PLFM_386 ) - set_segm_addressing(getseg(start_ea), 1); -} - -//-------------------------------------------------------------------------- -bool ana_hdr(processor_t &ph, linput_t *li, exec *_ex) -{ - bool msb = false; - exec &ex = *_ex; - lread(li, &ex, sizeof(ex)); - - if ( N_BADMAG(ex) ) - { - swap_exec(ex); - msb = true; - msg("Assuming big-endian...\n"); - } - const char *proc = guess_processor(ex); - if ( proc != NULL ) - { - set_processor_type(proc, SETPROC_LOADER); - if ( N_MACHTYPE(ex) == M_SPARC ) - sparc_module_t::set_v8(true); // set SPARC_V8 parameter - } - else - { - if ( ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "AUTOHIDE REGISTRY\n" - "Missing machine type. Continue?") <= ASKBTN_NO ) - { - loader_failure(); - } - if ( ph.id == -1 ) - set_processor_type(inf_get_procname().c_str(), SETPROC_LOADER); - } - return msb; -} - -//-------------------------------------------------------------------------- -inline fixup_type_t get_hi22_reltype() -{ - static fixup_type_t hi22_reltype = FIXUP_CUSTOM; - if ( hi22_reltype == FIXUP_CUSTOM ) - hi22_reltype = find_custom_fixup("HI22"); - return hi22_reltype; -} - -//-------------------------------------------------------------------------- -inline fixup_type_t get_lo10_reltype() -{ - static fixup_type_t lo10_reltype = FIXUP_CUSTOM; - if ( lo10_reltype == FIXUP_CUSTOM ) - lo10_reltype = find_custom_fixup("LO10"); - return lo10_reltype; -} - -//-------------------------------------------------------------------------- -static void do_fixup(uint32 where, uint32 delta, uint32 target, fixup_type_t type, int external) -{ - fixup_data_t fd(type); - if ( external ) - fd.set_extdef(); - - fd.displacement = delta; - if ( external ) - target -= delta; - - segment_t *s = getseg(target); - if ( s != NULL ) - { - fd.sel = s->sel; - fd.off = target - get_segm_base(s); - } - else - { - fd.off = target; - } - fd.set(where); -} - -#define S_MASK(x) ((1 << (x)) - 1) - -//---------------------------------------------------------------------- -static void do_relocation_sparc( - linput_t *li, - const aout_t &ctx, - uint32 off, - uint32 len, - int seg) -{ - const segment_t *seg_p = getnseg(seg); - if ( seg_p == NULL ) - { - msg("relocation data for missing segment %d ignored\n", seg); - return; - } - uint32 base = seg == 1 ? ctx.text : ctx.data; -#ifdef DEBUG - msg("seg %d base 0x%08X\n", seg, base); -#endif - - // load relocation table - uint32 relcount = len / sizeof(reloc_info_sparc); - validate_array_count(li, &relcount, sizeof(reloc_info_sparc), "Relocation count", off); - if ( relcount == 0 ) - return; - reloc_info_sparc *reltab = qalloc_array<reloc_info_sparc>(relcount); - if ( reltab == NULL ) - loader_failure("Unable to allocate relocation table for %u entries\n", relcount); - qlseek(li, off); - for ( reloc_info_sparc *rel = reltab; rel < reltab + relcount; rel++ ) - { - uint32 temp = 0; - lread4bytes(li, &rel->r_address, ctx.msb); - lread4bytes(li, &temp, ctx.msb); - lread4bytes(li, &rel->r_addend, ctx.msb); - rel->r_index = (temp >> 8) & 0x00FFFFFF; - rel->r_extern = (temp >> 7) & 1; - rel->r_type = (reloc_type_sparc) ((temp) & 0x1F); - -#ifdef DEBUG - if ( rel->r_address >= 0x80C8 && rel->r_address <= 0x8200 ) - msg("%08X: index=0x%06X extern=%d type=%02X addend=0x%08X\n", - rel->r_address, rel->r_index, rel->r_extern, rel->r_type, rel->r_addend); -#endif - } - - - // perform relocation - for ( reloc_info_sparc *rel = reltab; rel < reltab + relcount; rel++ ) - { - uint32 where = base + rel->r_address; - uint32 instr = get_dword(where); - fixup_type_t type = FIXUP_OFF32; - uint32 target = where; - uint32 value; - uint32 merged; -#ifdef DEBUG - value = instr; - merged = instr; -#endif - - if ( rel->r_extern ) - { - if ( rel->r_index >= ctx.symcount ) - { - msg("%08X: relocation to extern symbol idx %08X out of bounds, ignored\n", where, rel->r_index); - continue; - } - nlist *sym = &ctx.symtab[rel->r_index]; - - // The in-database address for this symbol was set when loading the symtab. - target = sym->n_value; - target += rel->r_addend; - -/* - if ( (sym->n_type & N_TYPE ) != N_ABS && - (sym->n_type & N_TYPE) != N_COMM) - target += where; - - if ( (rel->r_type == SPARC_RELOC_PC10 ) || - (rel->r_type == SPARC_RELOC_PC22)) - target -= where; -*/ - } - else - { - if ( rel->r_type == SPARC_RELOC_HI22 || rel->r_type == SPARC_RELOC_LO10 ) - target = rel->r_addend; - if ( seg == 2 && rel->r_type == SPARC_RELOC_32 ) - target = rel->r_addend; -/* - if ( (rel->r_index == N_TEXT ) || - (rel->r_index == N_DATA) || - (rel->r_index == N_BSS)) - target = rel->r_addend; -*/ - } - - uint32 delta = 0; - switch ( rel->r_type ) - { - case SPARC_RELOC_32: - value = instr; - target += value; - merged = target; - break; - case SPARC_RELOC_WDISP30: - value = (instr & S_MASK(30)); - target += value; - merged = (instr & ~S_MASK(30)) | ((target >> 2) & S_MASK(30)); - break; - case SPARC_RELOC_WDISP22: - value = (instr & S_MASK(22)); - target += value; - merged = (instr & ~S_MASK(22)) | ((target >> 2) & S_MASK(22)); - break; - case SPARC_RELOC_HI22: - value = (instr & S_MASK(22)) << 10; - target += value; - merged = (instr & ~S_MASK(22)) | ((target >> 10) & S_MASK(22)); - delta = 0; //-(target & S_MASK(10)); - type = get_hi22_reltype(); - break; - case SPARC_RELOC_LO10: - value = (instr & S_MASK(10)); - target += value; - merged = (instr & ~S_MASK(10)) | ((target) & S_MASK(10)); - type = get_lo10_reltype(); - break; - default: - msg("Unsupported sparc relocation type 0x%02X, ignored\n", rel->r_type); - continue; - } - -#ifdef DEBUG -// if ( rel->r_address < 0x300 ) -// msg("%08X: %08X -> %08X (%08X -> %08X)\n", where, instr, merged, value, target); -#endif - - put_dword(where, merged); - do_fixup(where, rel->r_extern ? rel->r_addend : delta, target, type, rel->r_extern); - } - - qfree(reltab); -} - - -//---------------------------------------------------------------------- -static void do_relocation(linput_t *li, const aout_t &ctx, uint32 off, uint32 len, int seg) -{ - switch ( N_MACHTYPE(ctx.ex) ) - { - case M_SPARC: - do_relocation_sparc(li, ctx, off, len, seg); - break; - default: - msg("Warning: Relocation in image file not supported yet for this processor\n"); - break; - } -} - - -//---------------------------------------------------------------------- -void load_syms(linput_t *li, aout_t &ctx) -{ - // get string table length - uint32 tabsize = 0; - qlseek(li, ctx.stroff); - lread4bytes(li, &tabsize, ctx.msb); -#ifdef DEBUG - msg("symoff=0x%08x symlen=0x%08x stroff=0x%08x strlen=0x%08x\n", - ctx.symoff, ctx.ex.a_syms, ctx.stroff, tabsize); -#endif - - // load string table - char *strtab = (char *)qalloc(tabsize+1); - if ( strtab == NULL ) - loader_failure("Unable to allocate string table for %u bytes\n", tabsize+1); - qlseek(li, ctx.stroff); - lreadbytes(li, strtab, tabsize, false); - strtab[tabsize] = '\0'; // ensure trailing zero - - // load symbol table - ctx.symcount = ctx.ex.a_syms / sizeof(nlist); - validate_array_count_or_die(li, ctx.symcount, sizeof(nlist), - "Number of symbols", ctx.symoff); - nlist *symtab = qalloc_array<nlist>(ctx.symcount); - if ( symtab == NULL ) - loader_failure("Unable to allocate symbol table for %u entries\n", ctx.symcount); - qlseek(li, ctx.symoff); - uint32 extern_count = 0; - for ( nlist *sym = symtab; sym < symtab + ctx.symcount; sym++ ) - { - lread4bytes(li, &sym->n_un.n_strx, ctx.msb); - lreadbytes(li, &sym->n_type, 1, ctx.msb); - lreadbytes(li, &sym->n_other, 1, ctx.msb); - lread2bytes(li, &sym->n_desc, ctx.msb); - lread4bytes(li, &sym->n_value, ctx.msb); - - if ( sym->n_type == N_EXT ) - extern_count++; - } - - // create extern section - uint32 extern_base = ctx.top; - if ( extern_count != 0 ) - { - // create new segment - add_segm(0, extern_base, extern_base + (extern_count * 4), "extern", "XTRN"); - ctx.extrn = extern_base; - ctx.top += extern_count * 4; - } - - - // import symbols -#ifdef DEBUG - int i = 0; -#endif - uint32 i_extern = 0; - for ( nlist *sym = symtab; sym < symtab + ctx.symcount; sym++ ) - { - if ( sym->n_type & N_STAB ) //debug stab info, not a symbol - continue; - - if ( sym->n_type == N_EXT ) - { - sym->n_value = extern_base + (i_extern * 4); - if ( getseg(sym->n_value) ) - put_dword(sym->n_value, 0); - i_extern++; - } - - if ( getseg(sym->n_value) != NULL ) - { - if ( sym->n_un.n_strx < tabsize ) - { - set_name(sym->n_value, strtab + sym->n_un.n_strx, - (sym->n_type & N_EXT ? SN_PUBLIC : SN_NON_PUBLIC)|SN_NOCHECK|SN_NOWARN|SN_IDBENC); - } - else - { - msg("%08X: type=0x%02X other=0x%02X desc=0x%04X: bad str offset %08X\n", - sym->n_value, sym->n_type, sym->n_other, sym->n_desc, - sym->n_un.n_strx); - } - } - - if ( (sym->n_type & N_TYPE) == N_ABS ) - { -#ifdef DEBUG - msg("%04X: %08X: type=0x%02X other=0x%02X desc=0x%04X: %s\n", - i, sym->n_value, sym->n_type, sym->n_other, sym->n_desc, - strtab + sym->n_un.n_strx); -#endif - } -#ifdef DEBUG - i++; -#endif - } - - ctx.strtab = strtab; - ctx.symtab = symtab; -} - -//-------------------------------------------------------------------------- -static void handle_ld_info(linput_t *li, int diroff, int base) -{ - lddir_t lddir; - qlseek(li, diroff); - lread(li, &lddir, sizeof(lddir)); - - ld_info_t ldinfo; - qlseek(li, lddir.ldinfo-base); - lread(li, &ldinfo, sizeof(ldinfo)); - - qoff64_t fpos = ldinfo.symbols - base; - int nsyms = (ldinfo.strings - ldinfo.symbols) / sizeof(ld_symbol_t); - validate_array_count(li, &nsyms, sizeof(ld_symbol_t), "Symbol count", fpos); - qlseek(li, fpos); - for ( int i=0; i < nsyms; i++ ) - { - ld_symbol_t sym; - lread(li, &sym, sizeof(sym)); - - char name[MAXSTR]; - qlgetz(li, ldinfo.strings + sym.nameoff - base, name, sizeof(name)); - - set_name(sym.addr, name, SN_IDBENC); - if ( (sym.flags & (AOUT_LD_FUNC|AOUT_LD_DEF)) == AOUT_LD_FUNC ) - { // imported function - put_byte(sym.addr, 0xC3); // return - if ( sym.addr <= ldinfo.ldentry ) - warning("interr: symbol #%d (%s) is not in the plt", i, name); - } - } -} - -//-------------------------------------------------------------------------- -// -// load file into the database. -// -void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) -{ - processor_t &ph = PH; - aout_t ctx; - exec &ex = ctx.ex; - ctx.msb = ana_hdr(ph, li, &ex); - ctx.symtab = NULL; - ctx.symcount = 0; - ctx.strtab = NULL; - ctx.treloff = N_TRELOFF(ex); - ctx.dreloff = N_DRELOFF(ex); - ctx.symoff = N_SYMOFF(ex); - ctx.stroff = N_STROFF(ex); - - int txtoff = N_TXTOFF(ex); - int txtadr; - - switch ( ph.id ) - { - case PLFM_SPARC: - txtoff = N_TXTOFF_SPARC(ex); - txtadr = N_TXTADDR_SPARC(ex); - ctx.treloff = N_TRELOFF_SPARC(ex); - ctx.dreloff = N_DRELOFF_SPARC(ex); - ctx.symoff = N_SYMOFF_SPARC(ex); - ctx.stroff = N_STROFF_SPARC(ex); - break; - - case PLFM_ARM: - txtadr = N_TXTADDR_ARM(ex); - break; - - default: - txtadr = N_TXTADDR(ex); - switch ( N_MAGIC(ex) ) - { -// case NMAGIC: -// case CMAGIC: - default: - loader_failure("This image type is not supported yet"); - - case ZMAGIC: - if ( qlsize(li) < ex.a_text + ex.a_data + N_SYMSIZE(ex) + txtoff ) - { - txtoff = 0; - txtadr = 0x1000; - } - else if ( txtoff < 512 ) - { - loader_failure("Size of demand page < size of block"); - } - // fallthrough - case QMAGIC: - if ( ex.a_text & 0xFFF || ex.a_data & 0xFFF ) - loader_failure("Executable is not page aligned"); - break; - - case OMAGIC: - txtoff = sizeof(ex); - break; - } - break; - } - - inf_set_baseaddr(0); - - uint32 base, top; - top = base = txtadr; - if ( ex.a_text || ex.a_data ) - { - top += ex.a_text; -// msg("txtoff=%d, base=%d top=%d end=%d\n", txtoff, base, top, top+ex.a_data); - file2base(li, txtoff, base, top + ex.a_data, FILEREG_PATCHABLE); - if ( ex.a_text ) - { - create32(ph, 1, base, top, NAME_CODE, CLASS_CODE); - inf_set_start_cs(1); - inf_set_start_ip(ex.a_entry); - ctx.text = base; - } - if ( ex.a_data ) - { - base = top; - create32(ph, 2, base, top += ex.a_data, NAME_DATA, CLASS_DATA); - set_default_dataseg(2); - ctx.data = base; - } - } - if ( ex.a_bss ) - { - create32(ph, 3, top, top + ex.a_bss, NAME_BSS, CLASS_BSS); - ctx.bss = top; - } - ctx.top = top + ex.a_bss; - - if ( ex.a_syms ) - load_syms(li, ctx); - - if ( N_TRSIZE(ex) ) - do_relocation(li, ctx, ctx.treloff, N_TRSIZE(ex), 1); - if ( N_DRSIZE(ex) ) - do_relocation(li, ctx, ctx.dreloff, N_DRSIZE(ex), 2); - -// We come in here for the regular a.out style of shared libraries */ -// ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || -// return -ENOEXEC; -// } -// For QMAGIC, the starting address is 0x20 into the page. We mask -// this off to get the starting address for the page */ -// start_addr = ex.a_entry & 0xfffff000; -////// - - if ( ph.id != PLFM_SPARC && N_FLAGS(ex) & EX_PIC ) - handle_ld_info(li, ex.a_text, txtadr); - - create_filename_cmt(); - add_pgm_cmt("Flag value: %Xh", N_FLAGS(ex)); -} - -//---------------------------------------------------------------------- -// -// LOADER DESCRIPTION BLOCK -// -//---------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/ldr/aout/aout.h b/idasdk75/ldr/aout/aout.h deleted file mode 100644 index 86ef8a5..0000000 --- a/idasdk75/ldr/aout/aout.h +++ /dev/null @@ -1,283 +0,0 @@ -#ifndef __AOUT_H__ -#define __AOUT_H__ -#pragma pack(push, 1) - -struct exec -{ - uint32 a_info; // Use macros N_MAGIC, etc for access - uint32 a_text; // length of text, in bytes - uint32 a_data; // length of data, in bytes - uint32 a_bss; // length of bss area for file, in bytes - uint32 a_syms; // length of symbol table data in file, in bytes - uint32 a_entry; // start address - uint32 a_trsize; // length of relocation info for text, in bytes - uint32 a_drsize; // length of relocation info for data, in bytes -// Added for i960 -// uint32 a_tload; // Text runtime load adderr -// uint32 a_dload; // Data runtime load address -// uchar a_talign; // Alignment of text segment -// uchar a_dalign; // Alignmrnt of data segment -// uchar a_balign; // Alignment of bss segment -// char a_relaxable;// Enough info for linker relax -}; -//==================== -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000ul) - -#define N_MAGIC(exec) ((exec).a_info & 0xffff) -#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) -#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) -//==================== -enum machine_type -{ -// M_OLDSUN2 = 0, - M_UNKNOWN = 0, - M_68010 = 1, - M_68020 = 2, - M_SPARC = 3, - /*-----------------11.07.98 04:09------------------- - * skip a bunch so we don't run into any of suns numbers */ - /*-----------------11.07.98 04:09------------------- - * make these up for the ns32k*/ - M_NS32032 = (64), /* ns32032 running ? */ - M_NS32532 = (64 + 5), /* ns32532 running mach */ - M_386 = 100, - M_29K = 101, /* AMD 29000 */ - M_386_DYNIX = 102, /* Sequent running dynix */ - M_ARM = 103, /* Advanced Risc Machines ARM */ - M_SPARCLET = 131, /* SPARClet = M_SPARC + 128 */ - M_386_NETBSD = 134, /* NetBSD/i386 binary */ - M_68K_NETBSD = 135, /* NetBSD/m68k binary */ - M_68K4K_NETBSD = 136, /* NetBSD/m68k4k binary */ - M_532_NETBSD = 137, /* NetBSD/ns32k binary */ - M_SPARC_NETBSD = 138, /* NetBSD/sparc binary */ - M_PMAX_NETBSD = 139, /* NetBSD/pmax (MIPS little-endian) binary */ - M_VAX_NETBSD = 140, /* NetBSD/vax binary */ - M_ALPHA_NETBSD = 141, /* NetBSD/alpha binary */ - M_ARM6_NETBSD = 143, /* NetBSD/arm32 binary */ - M_SPARCLET_1 = 147, /* 0x93, reserved */ - M_MIPS1 = 151, /* MIPS R2000/R3000 binary */ - M_MIPS2 = 152, /* MIPS R4000/R6000 binary */ - M_SPARCLET_2 = 163, /* 0xa3, reserved */ - M_SPARCLET_3 = 179, /* 0xb3, reserved */ - M_SPARCLET_4 = 195, /* 0xc3, reserved */ - M_HP200 = 200, /* HP 200 (68010) BSD binary */ - M_HP300 = (300 % 256), /* HP 300 (68020+68881) BSD binary */ - M_HPUX = (0x20c % 256), /* HP 200/300 HPUX binary */ - M_SPARCLET_5 = 211, /* 0xd3, reserved */ - M_SPARCLET_6 = 227, /* 0xe3, reserved */ - M_SPARCLET_7 = 243 /* 0xf3, reserved */ -}; -//==================== -#define OMAGIC 0407 // object file or impure executable -#define NMAGIC 0410 // pure executeable -#define ZMAGIC 0413 // demand-paged executable -#define BMAGIC 0415 // Used by a b.out object -#define QMAGIC 0314 // demand-paged executable with the header in the text. - // The first page is unmapped to help trap NULL pointer - // referenced -#define CMAGIC 0421 // core file -//==================== -// Flags: -#define EX_PIC 0x80 /* contains position independent code */ -#define EX_DYNAMIC 0x40 /* contains run-time link-edit info */ -#define EX_DPMASK 0xC0 /* mask for the above */ -//==================== - -#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ - && N_MAGIC(x) != NMAGIC \ - && N_MAGIC(x) != ZMAGIC \ - && N_MAGIC(x) != QMAGIC) - -#define _N_HDROFF(x) (1024 - sizeof(struct exec)) - -#define N_TXTOFF(x) \ - (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ - (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) - -#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) -#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) -#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x)) -#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x)) -#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) - -// Address of text segment in memory after it is loaded -#define PAGE_SIZE (1UL << 12) -#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0) - -#define PAGE_SIZE_ARM 0x8000UL -#define N_TXTADDR_ARM(x) (N_MAGIC(x) == QMAGIC ? 0 : PAGE_SIZE_ARM) - -// Address of data segment in memory after it is loaded. (for linux) -/* -#define SEGMENT_SIZE 1024 -#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) -#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) -#define N_DATADDR(x) \ - (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) : \ - (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) -// Address of bss segment in memory after it is loaded -#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) -*/ -//======================== -struct nlist -{ - union - { - int32 n_strx; - } n_un; - uchar n_type; - char n_other; - short n_desc; - uint32 n_value; -}; - -#define N_UNDF 0 // Undefined symbol -#define N_ABS 2 // Absolute symbol -- addr -#define N_TEXT 4 // Text sym -- offset in text segment -#define N_DATA 6 // Data sym -- offset in data segment -#define N_BSS 8 // BSS sym -- offset in bss segment -#define N_COMM 0x12 // Common symbol (visible after shared) -#define N_FN 0x1F // File name of .o file -#define N_FN_SEQ 0x0C // N_FN from Sequent compilers - -#define N_EXT 1 // External (ORed wits UNDF, ABS, TEXT, DATA or BSS) -#define N_TYPE 0x1E -#define N_STAB 0xE0 // If present - debug symbol - -#define N_INDR 0xA // symbol refernced to another symbol - -#define N_SETA 0x14 // Absolute set element symbol -#define N_SETT 0x16 // Text set element symbol -#define N_SETD 0x18 // Data set element symbol -#define N_SETB 0x1A // Bss set element symbol - -#define N_SETV 0x1C // Pointer to set vector in data area. (from LD) - -#define N_WARNING 0x1E // Text has warnings - -// Weak symbols -#define N_WEAKU 0x0D // Weak undefined -#define N_WEAKA 0x0E // Weak Absolute -#define N_WEAKT 0x0F // Weak Text -#define N_WEAKD 0x10 // Weak Data -#define N_WEAKB 0x11 // Weak BSS - -//======================= - -struct relocation_info -{ - int32 r_address; // Adress (within segment) to be relocated - uint32 r_symbolnum:24;//The meaning of r_symbolnum depends on r_extern - uint32 r_pcrel:1; // Nonzero means value is a pc-relative offset - uint32 r_length:2; // Length (exp of 2) of the field to be relocated. - uint32 r_extern:1; // 1 => relocate with value of symbol. - // r_symbolnum is the index of the symbol - // in file's the symbol table. - // 0 => relocate with the address of a segment. - // r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS - uint32 r_bsr:1; - uint32 r_disp:1; - uint32 r_pad:2; -}; - -//============================ -// The SPARC_ prefix is added to the canonical names below to avoid a name -// conflict if other architectures are added - -enum reloc_type_sparc -{ - SPARC_RELOC_8, SPARC_RELOC_16, SPARC_RELOC_32, // simplest relocs - SPARC_RELOC_DISP8, SPARC_RELOC_DISP16, SPARC_RELOC_DISP32, // disp's (pc-rel) - SPARC_RELOC_WDISP30, SPARC_RELOC_WDISP22, // SR word disp's - SPARC_RELOC_HI22, SPARC_RELOC_22, // SR 22-bit relocs - SPARC_RELOC_13, SPARC_RELOC_LO10, // SR 13&10-bit relocs - SPARC_RELOC_SFA_BASE, SPARC_RELOC_SFA_OFF13, // SR S.F.A. relocs - SPARC_RELOC_BASE10, SPARC_RELOC_BASE13, SPARC_RELOC_BASE22, // base_relative pic - SPARC_RELOC_PC10, SPARC_RELOC_PC22, // special pc-rel pic - SPARC_RELOC_JMP_TBL, // jmp_tbl_rel in pic - SPARC_RELOC_SEGOFF16, // ShLib offset-in-seg - SPARC_RELOC_GLOB_DAT, SPARC_RELOC_JMP_SLOT, SPARC_RELOC_RELATIVE, // rtld relocs -}; - -struct reloc_info_sparc -{ - uint32 r_address; // relocation address (offset in segment) - uint32 r_index:24; // segment index or symbol index - uint32 r_extern:1; // if F, r_index==SEG#, if T, SYM index - uint32 :2; // unused - uint32 r_type:5; // type of relocation to perform - uint32 r_addend; // addend for relocation value -}; - -CASSERT(sizeof(reloc_info_sparc) == 12); - -#define N_PAGSIZ_SPARC(x) 0x02000 -#define N_SEGSIZ_SPARC(x) N_PAGSIZ_SPARC - -#define N_TXTOFF_SPARC(x) ((N_MAGIC(x) == ZMAGIC) ? 0 : sizeof (struct exec)) -#define N_TXTADDR_SPARC(x) \ - ((N_MAGIC(x) == OMAGIC) ? (x).a_entry \ - : ((N_MAGIC(x) == ZMAGIC) && ((x).a_entry < N_PAGSIZ_SPARC(x)) ? 0 \ - : N_PAGSIZ_SPARC(x)) \ - ) - -#define N_DATOFF_SPARC(x) (N_TXTOFF_SPARC(x) + (x).a_text) -#define N_DATADDR_SPARC(x) \ - ((N_MAGIC(x) == OMAGIC) ? (N_TXTADDR_SPARC(x) + (x).a_text) \ - : (N_SEGSIZ_SPARC(x)+((N_TXTADDR_SPARC(x)+(x).a_text-1) \ - & ~(N_SEGSIZ_SPARC(x)-1)))) - -#define N_BSSADDR_SPARC(x) (N_DATADDR_SPARC(x) + (x).a_data) - -#define N_TRELOFF_SPARC(x) (N_DATOFF_SPARC(x) + (x).a_data) -#define N_DRELOFF_SPARC(x) (N_TRELOFF_SPARC(x) + N_TRSIZE(x)) -#define N_SYMOFF_SPARC(x) (N_DRELOFF_SPARC(x) + N_DRSIZE(x)) -#define N_STROFF_SPARC(x) (N_SYMOFF_SPARC(x) + (x).a_syms) - - -//============================ -// Dynamic loader info (restored from a binary form in pc_bsd.aout, not exact): - -struct lddir_t -{ - uint32 unknown0; // 8 - uint32 unknown1; // offset dword_5010 - uint32 ldinfo; -}; - -struct ld_info_t -{ - uint32 unknown0; // 0 - uint32 onemoretable; - uint32 unknown1; // 0 - uint32 off_5060; // points to the end of this struct - uint32 ldentry; // main dynamic loader entry - uint32 imports; - uint32 pairs; // pairs of symbol numbers - uint32 symbols; - uint32 unknown2; // 0 - uint32 unknown3; // 16h - uint32 strings; - uint32 unknown4; // 310h - uint32 unknown5; // 4000h - uint32 unknown6; // 148h - uint32 unknown7; // offset dword_5000 -}; - -struct ld_symbol_t -{ - uint32 nameoff; // offset from the beginning of the string table - uint32 flags; -#define AOUT_LD_FUNC 0x200 -#define AOUT_LD_DEF 0x004 // defined, otherwise - imported -#define AOUT_LD_DATA 0x002 // data - uint32 addr; // pointer to the object - uint32 zero; // always zero? -}; - -#pragma pack(pop) -#endif diff --git a/idasdk75/ldr/aout/makefile b/idasdk75/ldr/aout/makefile deleted file mode 100644 index 3d48f43..0000000 --- a/idasdk75/ldr/aout/makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROC=aout - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)aout$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/sparc/notify_codes.hpp ../idaldr.h aout.cpp \ - aout.h common.cpp diff --git a/idasdk75/ldr/coff/syms.h b/idasdk75/ldr/coff/syms.h deleted file mode 100644 index 4b77f1f..0000000 --- a/idasdk75/ldr/coff/syms.h +++ /dev/null @@ -1,862 +0,0 @@ -#ifndef _H_SYMS -#define _H_SYMS - -#include <../ldr/coff/storclas.h> -#pragma pack(push, 1) - -#define SYMNMLEN 8 /* Number of characters in a symbol name */ -#define FILNMLEN 14 /* Number of characters in a file name */ -#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */ - -struct coff_sym_t // here for efd(di) and ldr/dbg -{ - union - { - char _n_name[SYMNMLEN]; /* old COFF version */ - struct - { - int32 _n_zeroes; /* new == 0 */ - int32 _n_offset; /* offset into string table */ - } _n_n; -// char *_n_nptr[2]; /* allows for overlaying */ - } _n; - uint32 n_value; /* value of symbol */ - uint16 n_scnum; /* section number */ - uint16 n_type; /* type and derived type */ - uchar n_sclass; /* storage class */ - uchar n_numaux; /* number of aux. entries */ -}; - -struct coff_sym64_t -{ - uint64 n_value64; /* value of symbol */ - uint32 n_offset64; /* offset into string table */ - uint16 n_scnum; /* section number */ - union - { - unsigned short _n_type; /* type and derived type */ - struct - { - unsigned char _n_lang; /* source language id */ - unsigned char _n_cpu; /* cputype id */ - } _n_lc; - } _n_tylc; - char n_sclass; /* storage class */ - char n_numaux; /* number of aux. entries */ -}; - -#define IDA_SYM_SZ (SYMNMLEN + 8 + 4 + 2 + 2*1) - -struct ida_sym_t // internal, translated form -{ - union - { - char _n_name[SYMNMLEN]; /* old for short name (<=8) */ - struct - { - int32 _n_zeroes; /* for long name == 0 */ - int32 _n_offset; /* offset into string table */ - } _n_n; - } _n; - uint64 n_value; /* value of symbol */ - uint32 n_scnum; /* section number */ - uint16 n_type; /* type and derived type */ - uchar n_sclass; /* storage class */ - uchar n_numaux; /* number of aux. entries */ -}; - -DECLARE_TYPE_AS_MOVABLE(ida_sym_t); - -#define COFF_SYM_SZ (SYMNMLEN + 4 + 2*2 + 2*1) -#define COFF_SYM64_SZ (8 + 4 + 2 + 2 + 2*1) -#define n_name _n._n_name -#define n_nptr _n._n_nptr[1] -#define n_zeroes _n._n_n._n_zeroes -#define n_offset _n._n_n._n_offset - -/* - * Relocatable symbols have a section number of the - * section in which they are defined. Otherwise, section - * numbers have the following meanings: - */ -#define N_UNDEF 0 // undefined symbol -#define N_ABS uint16(-1) // value of symbol is absolute -#define N_DEBUG uint16(-2) // special debugging symbol -- value of symbol is meaningless -#define N_TV uint16(-3) // indicates symbol needs transfer vector (preload) -#define P_TV uint16(-4) // indicates symbol needs transfer vector (postload) - -/* - * The fundamental type of a symbol packed into the low - * 4 bits of the word. - */ - -#if 0 -#define _EF ".ef" -#endif - -/* - * Type of a symbol, in low N bits of the word - */ -#define T_NULL 0 -#define T_VOID 1 /* function argument (only used by compiler) */ -#define T_CHAR 2 /* character */ -#define T_SHORT 3 /* short integer */ -#define T_INT 4 /* integer */ -#define T_LONG 5 /* long integer */ -#define T_FLOAT 6 /* floating point */ -#define T_DOUBLE 7 /* double word */ -#define T_STRUCT 8 /* structure */ -#define T_UNION 9 /* union */ -#define T_ENUM 10 /* enumeration */ -#define T_MOE 11 /* member of enumeration*/ -#define T_UCHAR 12 /* unsigned character */ -#define T_USHORT 13 /* unsigned short */ -#define T_UINT 14 /* unsigned integer */ -#define T_ULONG 15 /* unsigned long */ -#define T_LNGDBL 16 /* long double */ - -/* - * derived types, in n_type -*/ -#define DT_NON (0) /* no derived type */ -#define DT_PTR (1) /* pointer */ -#define DT_FCN (2) /* function */ -#define DT_ARY (3) /* array */ - -/* - * type packing constants - */ - -#define IDA_N_BTMASK 017 -#define IDA_N_TMASK 060 -#define IDA_N_TMASK1 0300 -#define IDA_N_TMASK2 0360 -#define IDA_N_BTSHFT 4 -#define IDA_N_TSHIFT 2 - -//-------------------------------------------------------------------------- - /* Basic Type of x */ - -#define IDA_BTYPE(x) ((x) & IDA_N_BTMASK) - - /* Is x a pointer ? */ - -#define IDA_ISPTR(x) (((x) & IDA_N_TMASK) == (DT_PTR << IDA_N_BTSHFT)) - - /* Is x a function ? */ - -#define IDA_ISFCN(x) (((x) & IDA_N_TMASK) == (DT_FCN << IDA_N_BTSHFT)) - - /* Is x an array ? */ - -#define IDA_ISARY(x) (((x) & IDA_N_TMASK) == (DT_ARY << IDA_N_BTSHFT)) - - /* Is x a structure, union, or enumeration TAG? */ - -#define IDA_ISTAG(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG) - -#define IDA_INCREF(x) ((((x)&~IDA_N_BTMASK)<<IDA_N_TSHIFT)|(DT_PTR<<IDA_N_BTSHFT)|(x&IDA_N_BTMASK)) - -#define IDA_DECREF(x) ((((x)>>IDA_N_TSHIFT)&~IDA_N_BTMASK)|((x)&IDA_N_BTMASK)) - -/************************************************************************* - * - * AUXILIARY ENTRY FORMAT - * - *************************************************************************/ - -typedef union auxent -{ - struct - { - int32 x_tagndx; /* str, un, or enum tag indx */ -#define x_exptr x_tagndx /* exception table offset */ - union - { - struct - { - uint16 x_lnno; /* declaration line number */ - uint16 x_size; /* str, union, array size */ - } x_lnsz; - int32 x_fsize; /* size of function */ - } x_misc; - union - { - struct - { /* if ISFCN, tag, or .bb */ - int32 x_lnnoptr; /* ptr to fcn line # */ - int32 x_endndx; /* entry ndx past block end */ - } x_fcn; - struct - { /* if ISARY, up to 4 dimen. */ - uint16 x_dimen[DIMNUM]; - } x_ary; - } x_fcnary; - uint16 x_tvndx; /* tv index */ - } x_sym; - - struct - { - struct - { - struct - { - int x_lnno; - } x_lnsz; - } x_misc; - char pad[13]; - char x_auxtype; - } x_sym64; - - union - { - char x_fname[FILNMLEN]; - struct - { - uint32 x_zeroes; - uint32 x_offset; - } _x; - } x_file; - - struct - { - int32 x_scnlen; /* section length */ - uint16 x_nreloc; /* number of relocation entries */ - uint16 x_nlinno; /* number of line numbers */ - uint32 x_chksum; /* checksumm for comdat's */ - uint16 x_asscnt; /* section number to associate with */ - uchar x_select; /* comdat selection type */ -#define SSEL_NODUPL 1 // no duplicate -#define SSEL_ANY 2 // select any -#define SSEL_SIZE 3 -#define SSEL_EXACT 4 // by checksumm -#define SSEL_ASSOC 5 // associative -#define SSEL_LARGEST 6 -#define SSEL_NEWEST 7 - uchar __align__; /* for COFF+ only */ - uint16 x_asscnt_hi; /* for COFF+ only - hi part of x_asscnt */ - } x_scn; // always <= sizeof(SYMENT) :) - - struct - { - int32 x_tvfill; /* tv fill value */ - uint16 x_tvlen; /* length of .tv */ - uint16 x_tvran[2]; /* tv range */ - } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ - - /****************************************** - * RS/6000-specific auxent - last auxent for every external symbol - ******************************************/ - struct - { - int32 x_scnlen; /* csect length */ - int32 x_parmhash; /* parm type hash index */ - uint16 x_snhash; /* sect num with parm hash */ - uchar x_smtyp; /* symbol align and type */ - /* 0-4 - Log 2 of alignment */ - /* 5-7 - symbol type */ -#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */ -#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ -/* Symbol type values: */ -#define XTY_ER 0 /* External reference */ -#define XTY_SD 1 /* Csect definition */ -#define XTY_LD 2 /* Label definition */ -#define XTY_CM 3 /* .BSS */ -#define XTY_EM 4 /* Error message */ -#define XTY_US 5 /* "Reserved for internal use" */ - uchar x_smclas; /* storage mapping class */ -#define XMC_PR 0 /* Read-only program code */ -#define XMC_RO 1 /* Read-only constant */ -#define XMC_DB 2 /* Read-only debug dictionary table */ -#define XMC_TC 3 /* Read-write general TOC entry */ -#define XMC_UA 4 /* Read-write unclassified */ -#define XMC_RW 5 /* Read-write data */ -#define XMC_GL 6 /* Read-only global linkage */ -#define XMC_XO 7 /* Read-only extended operation */ -#define XMC_SV 8 /* Read-only supervisor call */ -#define XMC_BS 9 /* Read-write BSS */ -#define XMC_DS 10 /* Read-write descriptor csect */ -#define XMC_UC 11 /* Read-write unnamed Fortran common */ -#define XMC_TI 12 /* Read-only traceback index csect */ -#define XMC_TB 13 /* Read-only traceback table csect */ -/* 14 ??? */ -#define XMC_TC0 15 /* Read-write TOC anchor */ -#define XMC_TD 16 /* Read-write data in TOC */ - int32 x_stab; /* dbx stab info index */ - uint16 x_snstab; /* sect num with dbx stab */ - } x_csect; /* csect definition information */\ - -/* XCOFF64 _csect */ - struct - { - uint32 x_scnlen_lo; - int32 x_parmhash; - uint16 x_snhash; - uchar x_smtyp; - uchar x_smclas; -#define XMC_SV64 17 -#define XMC_SV2364 18 - int32 x_scnlen_hi; - char pad; - char x_auxtype; - } x_csect64; - - /****************************************** - * I960-specific *2nd* aux. entry formats - ******************************************/ - struct - { -#define x_stdindx x_stindx /* This is a very old typo that keeps getting propagated. */ - int32 x_stindx; /* sys. table entry */ - } x_sc; /* system call entry */ - - struct - { - uint32 x_balntry; /* BAL entry point */ - } x_bal; /* BAL-callable function */ - -} AUXENT; - -/* Defines for "special" symbols */ - -#if vax -#define _ETEXT "_etext" -#define _EDATA "_edata" -#define _END "_end" -#else -#define _ETEXT "etext" -#define _EDATA "edata" -#define _END "end" -#endif - -#define _START "_start" - -//================================================================================ -// ECOFF symbols -//================================================================================ - -#define estNil 0 /* Nuthin' special */ -#define estGlobal 1 /* external symbol */ -#define estStatic 2 /* static */ -#define estParam 3 /* procedure argument */ -#define estLocal 4 /* local variable */ -#define estLabel 5 /* label */ -#define estProc 6 /* " " Procedure */ -#define estBlock 7 /* beginnning of block */ -#define estEnd 8 /* end (of anything) */ -#define estMember 9 /* member (of anything - struct/union/enum */ -#define estTypedef 10 /* type definition */ -#define estFile 11 /* file name */ -#define estRegReloc 12 /* register relocation */ -#define estForward 13 /* forwarding address */ -#define estStaticProc 14 /* load time only static procs */ -#define estConstant 15 /* const */ -#define estStaParam 16 /* Fortran static parameters */ - /* These new symbol types have been recently added to SGI machines. */ -#define estStruct 26 /* Beginning of block defining a struct type */ -#define estUnion 27 /* Beginning of block defining a union type */ -#define estEnum 28 /* Beginning of block defining an enum type */ -#define estIndirect 34 /* Indirect type specification */ - /* Pseudo-symbols - internal to debugger */ -#define estStr 60 /* string */ -#define estNumber 61 /* pure number (ie. 4 NOR 2+2) */ -#define estExpr 62 /* 2+2 vs. 4 */ -#define estType 63 /* post-coersion SER */ -#define estMax 64 - -#define escNil 0 -#define escText 1 /* text symbol */ -#define escData 2 /* initialized data symbol */ -#define escBss 3 /* un-initialized data symbol */ -#define escRegister 4 /* value of symbol is register number */ -#define escAbs 5 /* value of symbol is absolute */ -#define escUndefined 6 /* who knows? */ -#define escCdbLocal 7 /* variable's value is IN se->va.?? */ -#define escBits 8 /* this is a bit field */ -#define escCdbSystem 9 /* variable's value is IN CDB's address space */ -#define escDbx 9 /* overlap dbx internal use */ -#define escRegImage 10 /* register value saved on stack */ -#define escInfo 11 /* symbol contains debugger information */ -#define escUserStruct 12 /* address in struct user for current process */ -#define escSData 13 /* load time only small data */ -#define escSBss 14 /* load time only small common */ -#define escRData 15 /* load time only read only data */ -#define escVar 16 /* Var parameter (fortran,pascal) */ -#define escCommon 17 /* common variable */ -#define escSCommon 18 /* small common */ -#define escVarRegister 19 /* Var parameter in a register */ -#define escVariant 20 /* Variant record */ -#define escSUndefined 21 /* small undefined(external) data */ -#define escInit 22 /* .init section symbol */ -#define escBasedVar 23 /* Fortran or PL/1 ptr based var */ -#define escXData 24 /* exception handling data */ -#define escPData 25 /* Procedure section */ -#define escFini 26 /* .fini section */ -#define escRConst 27 /* .rconst section */ -#define escMax 32 - -struct ecoff_hdr -{ - uint16 magic; -#define ECOFF_SYM_MAGIC 0x1992 - uint16 vstamp; - uint32 ilineMax; - uint32 idnMax; - uint32 ipdMax; - uint32 isymMax; - uint32 ioptMax; - uint32 iauxMax; - uint32 issMax; - uint32 issExtMax; - uint32 ifdMax; - uint32 crfd; - uint32 iextMax; - uint64 cbLine; - uint64 cbLineOffset; - uint64 cbDnOffset; - uint64 cbPdOffset; - uint64 cbSymOffset; - uint64 cbOptOffset; - uint64 cbAuxOffset; - uint64 cbSsOffset; - uint64 cbSsExtOffset; - uint64 cbFdOffset; - uint64 cbRfdOffset; - uint64 cbExtOffset; -}; - -struct ecoff_fdr -{ - uint64 f_adr; - uint64 f_cbLineOffset; - uint64 f_cbLine; - uint64 f_cbSs; - uint32 f_rss; - uint32 f_issBase; - uint32 f_isymBase; - uint32 f_csym; - uint32 f_ilineBase; - uint32 f_cline; - uint32 f_ioptBase; - uint32 f_copt; - uint32 f_ipdFirst; - uint32 f_cpd; - uint32 f_iauxBase; - uint32 f_caux; - uint32 f_rfdBase; - uint32 f_crfd; - uchar f_bits1; - uchar f_bits2[3]; - uchar f_padding[4]; -}; - -/* Procedure descriptor external record */ - -struct ecoff_pdr -{ - uint64 adr; - uint64 cbLineOffset; - uint32 isym; - uint32 iline; - uint32 regmask; - uint32 regoffset; - uint32 iopt; - uint32 fregmask; - uint32 fregoffset; - uint32 frameoffset; - uint32 lnLow; - uint32 lnHigh; - uchar gp_prologue; - uchar bits1; - uchar bits2; - uchar localoff; - uint16 framereg; - uint16 pcreg; -}; - -/* Line numbers */ - -struct ecoff_line -{ - uint32 l_line; -}; - -/* Symbol external record */ - -#define SYM_BITS1_ST_BIG 0xFC -#define SYM_BITS1_ST_SH_BIG 2 -#define SYM_BITS1_ST_LITTLE 0x3F -#define SYM_BITS1_ST_SH_LITTLE 0 - -#define SYM_BITS1_SC_BIG 0x03 -#define SYM_BITS1_SC_SH_LEFT_BIG 3 -#define SYM_BITS1_SC_LITTLE 0xC0 -#define SYM_BITS1_SC_SH_LITTLE 6 - -#define SYM_BITS2_SC_BIG 0xE0 -#define SYM_BITS2_SC_SH_BIG 5 -#define SYM_BITS2_SC_LITTLE 0x07 -#define SYM_BITS2_SC_SH_LEFT_LITTLE 2 - -#define SYM_BITS2_RESERVED_BIG 0x10 -#define SYM_BITS2_RESERVED_LITTLE 0x08 - -#define SYM_BITS2_INDEX_BIG 0x0F -#define SYM_BITS2_INDEX_SH_LEFT_BIG 16 -#define SYM_BITS2_INDEX_LITTLE 0xF0 -#define SYM_BITS2_INDEX_SH_LITTLE 4 - -#define SYM_BITS3_INDEX_SH_LEFT_BIG 8 -#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4 - -#define SYM_BITS4_INDEX_SH_LEFT_BIG 0 -#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12 - -struct ecoff_sym -{ - uint64 s_value; - uint32 s_iss; - uchar s_bits1; - uchar s_bits2; - uchar s_bits3; - uchar s_bits4; - uchar st(bool mf) - { - return mf - ? ((s_bits1 & SYM_BITS1_ST_BIG ) >> SYM_BITS1_ST_SH_BIG) - : ((s_bits1 & SYM_BITS1_ST_LITTLE) >> SYM_BITS1_ST_SH_LITTLE); - } - uchar sc(bool mf) - { - return mf - ? (((s_bits1 & SYM_BITS1_SC_BIG ) << SYM_BITS1_SC_SH_LEFT_BIG) - | ((s_bits2 & SYM_BITS2_SC_BIG ) >> SYM_BITS2_SC_SH_BIG)) - : (((s_bits1 & SYM_BITS1_SC_LITTLE) >> SYM_BITS1_SC_SH_LITTLE) - | ((s_bits2 & SYM_BITS2_SC_LITTLE) << SYM_BITS2_SC_SH_LEFT_LITTLE)); - } - uint32 index(bool mf) - { - return mf - ? (((s_bits2 & SYM_BITS2_INDEX_BIG) << SYM_BITS2_INDEX_SH_LEFT_BIG) - | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_BIG) - | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_BIG)) - : (((s_bits2 & SYM_BITS2_INDEX_LITTLE) >> SYM_BITS2_INDEX_SH_LITTLE) - | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_LITTLE) - | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_LITTLE)); - } -}; - -/* The auxiliary type information is the same on all known ECOFF - targets. The internal forms are - defined in coff/sym.h, which was originally donated by MIPS - Computer Systems. */ - -/* Type information external record */ - -struct ecoff_tir -{ - uchar t_bits1; - uchar t_tq45; - uchar t_tq01; - uchar t_tq23; - bool fBitfield(bool mf) { return (t_bits1 & (mf ? 0x80 : 0x01)) != 0; } - bool continued(bool mf) { return (t_bits1 & (mf ? 0x40 : 0x02)) != 0; } - uchar bt(bool mf) { return mf ? (t_bits1 & 0x3F) >> 0 : (t_bits1 & 0xFC) >> 2; } - uchar tq4(bool mf) { return mf ? (t_tq45 & 0xF0) >> 4 : (t_tq45 & 0x0F) >> 0; } - uchar tq5(bool mf) { return mf ? (t_tq45 & 0x0F) >> 0 : (t_tq45 & 0xF0) >> 4; } - uchar tq0(bool mf) { return mf ? (t_tq01 & 0xF0) >> 4 : (t_tq01 & 0x0F) >> 0; } - uchar tq1(bool mf) { return mf ? (t_tq01 & 0x0F) >> 0 : (t_tq01 & 0xF0) >> 4; } - uchar tq2(bool mf) { return mf ? (t_tq23 & 0xF0) >> 4 : (t_tq23 & 0x0F) >> 0; } - uchar tq3(bool mf) { return mf ? (t_tq23 & 0x0F) >> 0 : (t_tq23 & 0xF0) >> 4; } -}; - -/* Relative symbol external record */ - -struct ecoff_rndx -{ - uchar r_bits[4]; - uint16 rfd(bool mf) - { - return mf - ? (r_bits[0] << 4) | ((r_bits[1] & 0xF0) >> 4) - : (r_bits[0] << 0) | ((r_bits[1] & 0x0F) << 8); - } - uint32 index(bool mf) - { - return mf - ? ((r_bits[1] & 0x0F) << 16) - | (r_bits[2] << 8) - | (r_bits[3] << 0) - : ((r_bits[1] & 0xF0) >> 4) - | (r_bits[2] << 4) - | (r_bits[3] << 12); - } -}; - -/* Auxiliary symbol information external record */ - -union ecoff_aux -{ - ecoff_tir a_ti; - ecoff_rndx a_rndx; - uint32 a_dnLow; - uint32 a_dnHigh; - uint32 a_isym; - uint32 a_iss; - uint32 a_width; - uint32 a_count; -}; - -/* External symbol external record */ - -struct ecoff_ext -{ - ecoff_sym es_asym; - uchar es_bits1; - uchar es_bits2[3]; - uint32 es_ifd; -}; - -/* Dense numbers external record */ - -struct ecoff_dnr -{ - uint32 d_rfd; - uint32 d_index; -}; - -/* Relative file descriptor */ - -struct ecoff_rfd -{ - uint32 rfd; -}; - -/* Optimizer symbol external record */ - -struct ecoff_opt -{ - uchar o_bits1; - uchar o_bits2; - uchar o_bits3; - uchar o_bits4; - ecoff_rndx o_rndx; - uint32 o_offset; - uchar ot(void) { return o_bits1; } - uint32 value(bool mf) - { - return mf - ? ((uint32(o_bits2) << 16) - | (uint32(o_bits3) << 8) - | (uint32(o_bits4) << 0)) - : ((uint32(o_bits2) << 0) - | (uint32(o_bits3) << 8) - | (uint32(o_bits4) << 16)); - } -}; - -//--------------------------------------------------------------------------- -// MIPS symbolic information -//--------------------------------------------------------------------------- - -struct mips_ecoff_hdr -{ - uint16 magic; -#define MIPS_SYM_MAGIC 0x7002 - uint16 vstamp; - uint32 ilineMax; - uint32 cbLine; - uint32 cbLineOffset; - uint32 idnMax; - uint32 cbDnOffset; - uint32 ipdMax; - uint32 cbPdOffset; - uint32 isymMax; - uint32 cbSymOffset; - uint32 ioptMax; - uint32 cbOptOffset; - uint32 iauxMax; - uint32 cbAuxOffset; - uint32 issMax; - uint32 cbSsOffset; - uint32 issExtMax; - uint32 cbSsExtOffset; - uint32 ifdMax; - uint32 cbFdOffset; - uint32 crfd; - uint32 cbRfdOffset; - uint32 iextMax; - uint32 cbExtOffset; -}; - -struct mips_ecoff_fdr -{ - uint32 f_adr; - uint32 f_rss; - uint32 f_issBase; - uint32 f_cbSs; - uint32 f_isymBase; - uint32 f_csym; - uint32 f_ilineBase; - uint32 f_cline; - uint32 f_ioptBase; - uint32 f_copt; - uint16 f_ipdFirst; - uint16 f_cpd; - uint32 f_iauxBase; - uint32 f_caux; - uint32 f_rfdBase; - uint32 f_crfd; - uchar f_bits1; - uchar f_bits2[3]; - uint32 f_cbLineOffset; - uint32 f_cbLine; -}; - -/* Procedure descriptor external record */ - -struct mips_ecoff_pdr -{ - uint32 adr; - uint32 isym; - uint32 iline; - uint32 regmask; - uint32 regoffset; - uint32 iopt; - uint32 fregmask; - uint32 fregoffset; - uint32 frameoffset; - uint16 framereg; - uint16 pcreg; - uint32 lnLow; - uint32 lnHigh; - uint32 cbLineOffset; -}; - -/* Line numbers */ - -struct mips_ecoff_line -{ - uint32 l_line; -}; - -/* Symbol external record */ - -struct mips_ecoff_sym -{ - uint32 s_iss; - uint32 s_value; - uchar s_bits1; - uchar s_bits2; - uchar s_bits3; - uchar s_bits4; - uchar st(bool mf) - { - return mf - ? ((s_bits1 & SYM_BITS1_ST_BIG ) >> SYM_BITS1_ST_SH_BIG) - : ((s_bits1 & SYM_BITS1_ST_LITTLE) >> SYM_BITS1_ST_SH_LITTLE); - } - uchar sc(bool mf) - { - return mf - ? (((s_bits1 & SYM_BITS1_SC_BIG ) << SYM_BITS1_SC_SH_LEFT_BIG) - | ((s_bits2 & SYM_BITS2_SC_BIG ) >> SYM_BITS2_SC_SH_BIG)) - : (((s_bits1 & SYM_BITS1_SC_LITTLE) >> SYM_BITS1_SC_SH_LITTLE) - | ((s_bits2 & SYM_BITS2_SC_LITTLE) << SYM_BITS2_SC_SH_LEFT_LITTLE)); - } - uint32 index(bool mf) - { - return mf - ? (((s_bits2 & SYM_BITS2_INDEX_BIG) << SYM_BITS2_INDEX_SH_LEFT_BIG) - | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_BIG) - | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_BIG)) - : (((s_bits2 & SYM_BITS2_INDEX_LITTLE) >> SYM_BITS2_INDEX_SH_LITTLE) - | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_LITTLE) - | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_LITTLE)); - } -}; - -#define mips_ecoff_aux ecoff_aux - -/* External symbol external record */ - -struct mips_ecoff_ext -{ - uchar es_bits1; - uchar es_bits2; - uint16 es_ifd; - mips_ecoff_sym es_asym; -}; - -#define mips_ecoff_dnr ecoff_dnr -#define mips_ecoff_rfd ecoff_rfd -#define mips_ecoff_opt ecoff_opt - -//* segment information */ -struct ic_seginfo_t -{ - const ida_sym_t *sym = nullptr; // comdat symbol - ea_t start = BADADDR; // segment start address, BADADDR - not loaded - adiff_t delta = 0; // difference between the loaded address - // and address in the file - ea_t paddr = 0; // s_paddr from the segment descriptor -}; -DECLARE_TYPE_AS_MOVABLE(ic_seginfo_t); -struct ic_seginfos_t : public qvector<ic_seginfo_t> {}; - -//---------------------------------------------------------------------- -inline bool is_arm_switcher(const char *name) -{ - return strncmp(name, "$CODE", 5) == 0 - && (name[5] == '1' || name[5] == '3') - && (name[6] == '6' || name[6] == '2') - && name[7] == '\0'; -} - -struct i960_sym_t; -struct coff_sym_ex_t; -struct ida_filhdr_t; -struct ida_scnhdr_t; - -//---------------------------------------------------------------------- -class ida_syms_t -{ - struct coff_vars_t &ctx; - qstring str_table; // standard COFF string table (includes size in first 4 bytes) - qstring dtable; // XCOFF debug table (does not include size) - - void from_coff960(const i960_sym_t *pc, uint nsyms, bool coff_hdr_mf); - void from_bigcoff(const coff_sym_ex_t *pc, uint nsyms, bool coff_hdr_mf); - void from_xcoff64(const coff_sym64_t *pc, uint nsyms, bool coff_hdr_mf); - void from_coffsym(const coff_sym_t *pc, uint nsyms, bool coff_hdr_mf); -public: - qvector<ida_sym_t> symtab; - - ida_syms_t(coff_vars_t &_ctx) : ctx(_ctx) {} - bool str_table_from_file(linput_t *li, bool coff_hdr_mf); - bool str_table_from_mem(const void *buf, size_t bufsize, bool coff_hdr_mf); - bool load_from_file( - linput_t *li, - const ida_filhdr_t &fh, - bool coff_hdr_mf); - bool load_from_mem(const void *symbuf, size_t bufsize, uint32 nsyms, bool coff_hdr_mf); -#if !defined(COMPILE_DBG_LOADER) - void load_xcoff_debug_table(linput_t *li, const qvector<ida_scnhdr_t> &sechdrs); -#endif - const ida_sym_t *load_external_coff_symbols(linput_t *li, ida_filhdr_t &hf, bool mf); - - void qclear() - { - str_table.qclear(); - dtable.qclear(); - symtab.qclear(); - } - - void copy_from_str_table(char *buf, size_t bufsz, uint32 off, bool use_dtable = false) const; - const char *get_segment_name(const char *name, size_t fixlen, char *buffer, size_t bufsize, uint32 f_magic) const; - bool getaux(uint symidx, AUXENT &aux, uint &n_aux) const; - char *getname(uint symidx, char *buf, size_t bufsize) const; -}; - -#pragma pack(pop) -#endif /* _H_SYMS */ diff --git a/idasdk75/ldr/dos/dos.cpp b/idasdk75/ldr/dos/dos.cpp deleted file mode 100644 index 934eb45..0000000 --- a/idasdk75/ldr/dos/dos.cpp +++ /dev/null @@ -1,763 +0,0 @@ -/* - * This Loader Module is written by Ilfak Guilfanov and - * rewriten by Yury Haron - * - */ -/* - L O A D E R for MS-DOS file format's -*/ - -#include <map> -#include "../idaldr.h" -#include <exehdr.h> -#include <setjmp.h> -#include <typeinf.hpp> -#include "dos_ovr.h" -#include "cv.hpp" - -static const char fn_ovr[] = "MS-DOS executable (perhaps overlayed)", - fn_exe[] = "MS-DOS executable (EXE)", - fn_drv[] = "MS-DOS SYS-file (perhaps device driver)"; -const char e_exe[] = "exe"; - -static jmp_buf jmpb; - -#define R_ss 18 // this comes from intel.hpp - -//-------------------------------------------------------------------------- -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *filename) -{ - static int order = 0; - if ( order >= 4 ) - return 0; - - uint32 fLen = qlsize(li); - const char *file_ext = get_file_ext(filename); - if ( file_ext == NULL ) - file_ext = ""; - - exehdr E; - *processor = "metapc"; - switch ( order ) - { - case 0: - if ( fLen <= sizeof(E) ) - { - order = 3; // check for com - break; - } - - CASSERT(sizeof(E) >= 16); - lread(li, &E, sizeof(E)); - if ( E.exe_ident != EXE_ID && E.exe_ident != EXE_ID2 - || E.HdrSize*16 < sizeof(E) ) - { - order = 2; // check for drv - break; - } - if ( fLen < E.HdrSize*16 ) - return 0; - if ( E.ReloCnt != 0 ) - { - if ( E.TablOff + (E.ReloCnt*4) > fLen - || E.TablOff != 0 && E.TablOff < sizeof(E) - || E.TablOff == 0 ) - { - return 0; - } - } - if ( E.CalcEXE_Length() < fLen - E.HdrSize*16 - && PrepareOverlayType(li, &E) != ovr_noexe ) - { - *fileformatname = fn_ovr; - ++order; - return f_EXE | ACCEPT_CONTINUE; - } - // no break - case 1: - *fileformatname = fn_exe; - order = 5; // done - return f_EXE; - - case 2: - case 3: - break; - - default: - return 0; - } - - if ( ++order == 3 ) - { - if ( strieq(file_ext, "sys") || strieq(file_ext, "drv") ) - { - *fileformatname = fn_drv; - return f_DRV | ACCEPT_CONTINUE; - } - order++; // 4 - } - - if ( strieq(file_ext, "com") ) - { // com files must be readable - // on wince, file .exe files are unreadable. we do not want them to - // be detected as com files - qlseek(li, 0); - if ( qlread(li, &fLen, 1) == 1 ) - { - *fileformatname = "MS-DOS COM-file"; - return f_COM; - } - } - return 0; -} - -//------------------------------------------------------------------------- -NORETURN void errstruct(void) -{ - if ( ask_yn(ASKBTN_CANCEL, - "HIDECANCEL\n" - "Bad file structure or read error.\n" - "Proceed with the loaded infomration?") <= ASKBTN_NO ) - { - loader_failure(); - } - longjmp(jmpb, 1); -#ifdef __CODEGEARC__ - exit(0); // suppress compiler error -#endif -} - -//------------------------------------------------------------------------- -int CheckCtrlBrk(void) -{ - if ( user_cancelled() ) - { - if ( ask_yn(ASKBTN_NO, - "HIDECANCEL\n" - "Do you really want to abort loading?") > ASKBTN_NO ) - { - loader_failure(); - } - clr_cancelled(); - return 1; - } - return 0; -} - -//------------------------------------------------------------------------- -void add_segm_by_selector(sel_t base, const char *sclass) -{ - segment_t *ptr = get_segm_by_sel(base); - - if ( ptr == NULL || ptr->sel != base ) - { - ea_t ea = sel2ea(base); - if ( ea > inf_get_omax_ea() ) - inf_set_omax_ea(ea); - - segment_t s; - s.sel = base; - s.start_ea = sel2ea(base); - s.end_ea = inf_get_omax_ea(); - s.align = saRelByte; - s.comb = sclass != NULL && strcmp(sclass, "STACK") == 0 ? scStack : scPub; - add_segm_ex(&s, NULL, sclass, ADDSEG_SPARSE | ADDSEG_NOSREG); - } -} - -//------------------------------------------------------------------------- -// -// For all addresses in relocation table: -// add 'delta' -// if ( dosegs ) then make segments -// -static void doRelocs(int16 delta, bool dosegs, netnode ovr_info) -{ - - if ( ovr_info == BADNODE ) - return; - - fixup_data_t fd(FIXUP_SEG16); - for ( ea_t xEA = ovr_info.altfirst(); xEA != BADADDR; xEA = ovr_info.altnext(xEA) ) - { - show_addr(xEA); - - uint16 curval = get_word(xEA); - uint16 base = curval + delta; - if ( base < curval && delta > 0 ) - { - ask_for_feedback("%a: fixup overflow; skipping fixup processing", xEA); - break; - } - put_word(xEA, base); - fd.sel = base; - fd.set(xEA); - if ( dosegs ) - add_segm_by_selector(base, NULL); - CheckCtrlBrk(); - } -} - -//-------------------------------------------------------------------------- -static void create_msdos_segments(bool com_mode, netnode ovr_info) -{ - // msg("Creating segments...\n"); - add_segm_by_selector(find_selector(inf_get_start_cs()), CLASS_CODE); - if ( com_mode ) // COM/DRV - { - set_segm_start(inf_get_omin_ea(), inf_get_omin_ea(), SEGMOD_KILL); - inf_set_min_ea(inf_get_omin_ea()); - - segment_t *s = getseg(inf_get_min_ea()); - if ( s ) - { - s->set_comorg(); //i display ORG directive - s->update(); - } - } - if ( inf_get_start_ss() != BADSEL && inf_get_start_ss() != inf_get_start_cs() ) - add_segm_by_selector(inf_get_start_ss(), CLASS_STACK); - else // specify the sp value for the first segment - set_default_sreg_value(get_segm_by_sel(inf_get_start_cs()), R_ss, inf_get_start_cs()); - doRelocs(inf_get_baseaddr(), true, ovr_info); - - ea_t ea = inf_get_omin_ea(); - ea_t omea = inf_get_omax_ea(); - for ( int i = 0; ea < omea; ) - { - segment_t *sptr = getnseg(i); - if ( sptr == NULL || ea < sptr->start_ea ) - { - msg("Dummy segment at 0x%a (next segment at 0x%a)\n", - ea, - sptr == NULL ? BADADDR : sptr->start_ea); - add_segm_by_selector(unsigned(ea>>4), "DUMMY"); - } - else - { - ea = sptr->end_ea; - if ( !is_mapped(ea) ) - ea = next_addr(ea); - ++i; - } - } -} - -//-------------------------------------------------------------------------- -bool pos_read(linput_t *li, uint32 pos, void *buf, size_t size) -{ - qlseek(li, pos); - return qlread(li, buf, size) != size; -} - -//-------------------------------------------------------------------------- -static ea_t FindDseg(void) -{ - ea_t dea = to_ea(inf_get_start_cs(), inf_get_start_ip()); - - if ( get_byte(dea) == 0x9A ) // call far - { - dea = to_ea(sel2para(get_word(dea+3)), get_word(dea+1)); - inf_set_strtype(STRTYPE_PASCAL); - } - // - // Borland startup - // - uchar code = get_byte(dea); - uchar reg = code & 7; - if ( (code & ~7) == 0xB8 // mov reg, ???? - && ((get_byte(dea+3) == 0x8E - && ((code=get_byte(dea+4)) & ~7) == 0xD8 // mov ds, reg - && (code & 7) == reg) - || (get_byte(dea+3) == 0x2E // mov cs:@DGROUP, reg - && get_byte(dea+4) == 0x89 - && ((code = get_byte(dea+5)) & 0x8F) == 6 - && ((code>>3) & 7) == reg)) ) - { - segment_t *s = get_segm_by_sel(get_word(dea + 1)); - return s == NULL ? BADADDR : s->start_ea; - } - // - // Watcom startup - // - if ( get_byte(dea) == 0xE9 ) // jmp ??? - { - dea = dea + 3 + get_word(dea + 1); - if ( get_byte(dea + 0) == 0xFB // sti - && get_byte(dea + 1) == 0xB9 ) // mov cx, ??? - { - segment_t *s = get_segm_by_sel(get_word(dea + 2)); - return s == NULL ? BADADDR : s->start_ea; - } - } - // - // Generic: find copyright notice - // - static const char *const copyr[] = - { - " - Copyright", - // "Borland C++ - Copyright 1991 Borland Intl.", - // "Turbo-C - Copyright (c) 1988 Borland Intl.", - // "Turbo C - Copyright 1989 Borland Intl.", - // "Turbo C++ - Copyright 1990 Borland Intl.", - // "MS Run-Time Library - Copyright (c)", - NULL - }; - for ( const char *const *p = copyr; *p != NULL; ++p ) - { - msg("Looking for '%s'...\n", *p); - ea_t dataea = bin_search2(inf_get_min_ea(), - inf_get_max_ea(), - (uchar *)*p, - NULL, - strlen(*p), - BIN_SEARCH_CASE|BIN_SEARCH_FORWARD); - if ( dataea != BADADDR ) - return dataea; - } - return BADADDR; -} - -//-------------------------------------------------------------------------- -static void setup_default_ds_register(sel_t ds_value) -{ - segment_t *dseg; - - if ( ds_value != BADSEL ) - { - dseg = get_segm_by_sel(ds_value); - goto setname; - } - msg("Searching for the data segment...\n"); - switch ( inf_get_filetype() ) - { - case f_EXE: // Find default data seg - { - ea_t dataea = FindDseg(); - if ( dataea == BADADDR ) - return; - dseg = getseg(dataea); - if ( dseg == NULL ) - return; - } - dseg->align = saRelPara; - ds_value = dseg->sel; -setname: - set_segm_class(dseg, CLASS_DATA); - set_segm_name(dseg, "dseg"); - break; - case f_COM: - ds_value = find_selector(inf_get_start_cs()); - break; - default: - return; - } - msg("Default DS register: 0x%*a\n", 4, ds_value); - set_default_dataseg(ds_value); -} - -//-------------------------------------------------------------------------- -// -// load file into the database. -// -void idaapi load_file(linput_t *li, ushort neflag, const char *fileformatname) -{ - exehdr E; - int type = 0; - netnode ovr_info = BADNODE; - sel_t dseg = BADSEL; - o_type ovr_type = ovr_noexe; - - processor_t &ph = PH; - if ( setjmp(jmpb) == 0 ) - { - set_processor_type("metapc", SETPROC_LOADER); - - type = strieq(fileformatname, fn_ovr) ? 3 - : strieq(fileformatname, fn_exe) ? 2 - : strieq(fileformatname, fn_drv) ? 1 - : 0; - - clr_cancelled(); - - uval_t start_off; - uval_t fcoresize; - cm_t cm = inf_get_cc_cm() & CM_CC_MASK; - if ( type < 2 ) // COM/DRV - { - inf_set_cc_cm(cm | C_PC_SMALL); - if ( !type ) // f_COM - { - inf_set_start_ip(0x100); - inf_set_min_ea(to_ea(inf_get_baseaddr(), inf_get_start_ip())); - } - else - { // f_DRV - inf_set_start_ip(BADADDR); - inf_set_min_ea(to_ea(inf_get_baseaddr(), 0 /*binoff*/)); - //binoff has no sense for COM/DRV - } - inf_set_start_cs(inf_get_baseaddr()); - start_off = 0; - fcoresize = qlsize(li); - inf_set_max_ea(inf_get_min_ea() + fcoresize); - } - else - { // EXE (/OVR) - inf_set_cc_cm(cm | C_PC_LARGE); - lread(li, &E, sizeof(E)); - if ( !E.ReloCnt - && ask_yn(ASKBTN_YES, - "HIDECANCEL\nPossibly packed file, continue?") <= ASKBTN_NO ) - { - loader_failure(); - } - inf_set_start_ss(E.ReloSS); - inf_set_start_cs(E.ReloCS); - inf_set_start_sp(E.ExeSP); - inf_set_start_ip(E.ExeIP); - // take into account pointers like FFF0:0100 - // FFF0 should be treated as signed in this case - if ( inf_get_start_cs() >= 0xFFF0 || inf_get_start_ss() >= 0xFFF0 ) - { - if ( inf_get_baseaddr() < 0x10 ) - inf_set_baseaddr(0x10); - if ( inf_get_start_cs() >= 0xFFF0 ) - inf_set_start_cs(short(inf_get_start_cs())); - if ( inf_get_start_ss() >= 0xFFF0 ) - inf_set_start_ss(short(inf_get_start_ss())); - } - inf_set_start_ss(inf_get_start_ss() + inf_get_baseaddr()); - inf_set_start_cs(inf_get_start_cs() + inf_get_baseaddr()); - inf_set_min_ea(to_ea(inf_get_baseaddr(), 0)); - fcoresize = E.CalcEXE_Length(); - - ovr_info.create(LDR_INFO_NODE); - ovr_info.set((char *)&E, sizeof(E)); - - //i Check for file size - uint32 fsize = qlsize(li) - E.HdrSize*16; - if ( fcoresize > fsize ) - fcoresize = fsize; - if ( type == 2 - && fcoresize < fsize - && ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "The input file has extra information at the end\n" - "(tail %Xh, loaded %ah), continue?", - fsize, - fcoresize) <= ASKBTN_NO ) - { - loader_failure(); - } - inf_set_max_ea(inf_get_min_ea() + fcoresize); - - ea_t stackEA = to_ea(inf_get_start_ss(), inf_get_start_sp()); - if ( inf_get_max_ea() < stackEA ) - inf_set_max_ea(stackEA); - msg("Reading relocation table...\n"); - if ( E.ReloCnt ) - { - qlseek(li, E.TablOff); - for ( int i = 0; i < E.ReloCnt; ++i ) - { - ushort buf[2]; - - lread(li, buf, sizeof(buf)); - - ea_t xEA = to_ea((ushort)(inf_get_baseaddr() + buf[1]), buf[0]); // we need ushort() here! - if ( xEA >= inf_get_max_ea() ) - errstruct(); - ovr_info.altset(xEA, 1); - } - } - start_off = E.HdrSize * 16; - //i preset variable for overlay loading - if ( type == 3 ) - ovr_type = PrepareOverlayType(li, &E); - } - // next 2 strings for create_msdos_segments & CppOverlays - inf_set_omin_ea(inf_get_min_ea()); - inf_set_omax_ea(inf_get_max_ea()); - - file2base(li, start_off, inf_get_min_ea(), inf_get_min_ea() + fcoresize, - FILEREG_PATCHABLE); - - if ( ovr_type != ovr_cpp ) - { - if ( type == 3 || (neflag & NEF_SEGS) ) - create_msdos_segments((type <= 1), ovr_info); - else - doRelocs(inf_get_baseaddr(), false, ovr_info); - } - - create_filename_cmt(); - add_pgm_cmt("Base Address: %ah Range: %ah-%ah Loaded length: %ah", - inf_get_baseaddr(), inf_get_min_ea(), inf_get_max_ea(), fcoresize); - if ( type >= 2 ) - { //f_EXE - linput_t *volatile lio = NULL; - add_pgm_cmt("Entry Point : %a:%a", inf_get_start_cs(), inf_get_start_ip()); - if ( type == 2 // && E.CalcEXE_Length() < qlsize(li) - E.HdrSize*16 - && (lio = CheckExternOverlays()) != NULL ) - { - ++type; - } - if ( type != 3 ) - { - ovr_info.altset(-1, type); //EXE without overlays - } - else - { - switch ( ovr_type ) - { - case ovr_pascal: - lio = li; - // fallthrough - case ovr_noexe: - LoadPascalOverlays(lio); - if ( ovr_type == ovr_noexe ) - close_linput(lio); - break; - - case ovr_cpp: - dseg = LoadCppOverlays(li); - doRelocs(inf_get_baseaddr(), false, ovr_info); - break; - - case ovr_ms: - dseg = LoadMsOverlays(li, E.Overlay == 0); - break; - } - } - } - } - - setup_default_ds_register(dseg); // former SRcreate() - if ( dseg != BADSEL && ovr_type == ovr_ms ) - { - segment_t *s = get_segm_by_sel(find_selector(inf_get_start_cs())); - if ( s != NULL ) - set_default_sreg_value(s, ph.reg_data_sreg, s->sel); - } - inf_set_start_ea((inf_get_start_ip() == BADADDR) - ? BADADDR - : to_ea(sel2para(inf_get_start_cs()), inf_get_start_ip())); - if ( inf_get_start_ip() != BADADDR ) - { - uval_t val; - if ( type < 2 ) - val = find_selector(inf_get_start_cs()); //COM/DRV - else if ( get_str_type_code(inf_get_strtype()) == STRTYPE_PASCAL ) - val = get_sreg(inf_get_start_ea(), ph.reg_data_sreg); //i set in [srareaovl.cpp]FindDseg - else - val = inf_get_baseaddr() - 0x10; - split_sreg_range(inf_get_start_ea(), ph.reg_data_sreg, val, SR_autostart, true); - } - - if ( inf_get_filetype() == f_COM ) - { - inf_set_lowoff(0x100); - } - else - { - // check for the debug information - char debug_magic[4]; - qlseek(li, -8, SEEK_END); - lread(li, debug_magic, 4); - if ( is_codeview_magic(debug_magic) ) - load_dbg_dbginfo(NULL, li); - } -} - -//-------------------------------------------------------------------------- -static int expand_file(FILE *fp, uint32 pos) -{ - // return chsize(li, pos) || qfseek(fp, pos, SEEK_SET); - // but qchsize(), which does not fill with zeroes. - uint32 curpos = qftell(fp); - QASSERT(20041, curpos <= pos); - while ( curpos < pos ) - { - if ( qfputc(0, fp) == EOF ) - return 0; - ++curpos; - } - return 1; -} - -//-------------------------------------------------------------------------- -// -// generate binary file. -// -int idaapi save_file(FILE *fp, const char * /*fileformatname*/) -{ - int retcode; - uint32 codeoff; - netnode ovr_info(LDR_INFO_NODE, 0, 0); - - if ( fp == NULL ) - return ovr_info == BADNODE || ovr_info.altval(-1) == 2; - - if ( ovr_info != BADNODE ) // f_EXE - { - exehdr E; - ovr_info.valobj(&E, sizeof(E)); - - if ( qfwrite(fp, &E, sizeof(E)) != sizeof(E) ) - return 0; - if ( E.ReloCnt ) - { - if ( !expand_file(fp, E.TablOff) ) - return 0; - - for ( uval_t x = ovr_info.altfirst(); - x != BADADDR; - x = ovr_info.altnext(x) ) - { - ushort buf[2]; - - buf[1] = ushort((x >> 4) - inf_get_baseaddr()); - buf[0] = ushort(x) & 0xF; - if ( qfwrite(fp, buf, sizeof(buf)) != sizeof(buf) ) - return 0; - } - } - codeoff = E.HdrSize * 16; - if ( !expand_file(fp, codeoff) ) - return 0; - } - else - { - codeoff = 0; //f_COM, f_DRV - } - - doRelocs(-inf_get_baseaddr(), 0, ovr_info); - retcode = base2file(fp, codeoff, inf_get_omin_ea(), inf_get_omax_ea()); - doRelocs(inf_get_baseaddr(), 0, ovr_info); - return retcode; -} - -//---------------------------------------------------------------------- -static int idaapi move_segm(ea_t from, ea_t to, asize_t /*size*/, const char * /*fileformatname*/) -{ - // Before relocating, we need all of the relocation entries, which were - // part of the original executable file and consequently stored in our - // private loader node. - netnode ovr_info(LDR_INFO_NODE, 0, 0); - if ( ovr_info == BADNODE ) - { - // Can't find our private loader node. - msg("Couldn't find dos.ldr node, assuming file has no relocations.\n"); - return 1; - } - - if ( from == BADADDR ) - { - // The entire program is being rebased. - // In this case, 'to' actually contains a delta value; the number of bytes - // forward (positive) or backward (negative) that the whole database is - // being moved. - int32 delta = to; - - // If the delta is not a multiple of 16 bytes, we can't reliably - // relocate the executable. - if ( (delta % 16) != 0 ) - { - warning("DOS images can only be relocated to 16-byte boundaries."); - return 0; - } - - // Fixup the relocation entry netnode. It contains entries that point - // to locations that needed fixups when the image was located at its - // old address. Change the entries so that they point to the appropriate - // places in the new image location. - ea_t current_base = uint32(inf_get_baseaddr() << 4); - ea_t new_base = current_base + delta; - ovr_info.altshift(current_base, new_base, inf_get_privrange_start_ea()); - - // remember bases for later remapping of segment regs - std::map<ea_t, ea_t> segmap; - - // Now that the relocation entries point to the correct spots, go fix - // those spots up so that they point to the correct places. - doRelocs(delta >> 4, false, ovr_info); - - // IDA has adjusted all segment start and end addresses to cover their - // new effective address ranges, but we, the loader, must finish the - // job by rebasing each segment. - for ( int i = 0; i < get_segm_qty(); ++i ) - { - segment_t *seg = getnseg(i); - ea_t curbase = get_segm_base(seg); // Returns base in EA - ea_t newbase = curbase + delta; - set_segm_base(seg, newbase >> 4); // Expects base in Paragraphs - segmap[curbase >> 4] = newbase >> 4; - seg->update(); - } - - // fix up segment registers - // rebase segment registers - processor_t &ph = PH; - for ( int sr = 0; sr < SREG_NUM; ++sr ) - { - int sra_num = get_sreg_ranges_qty(ph.reg_first_sreg + sr); - for ( int i = 0; i < sra_num; ++i ) - { - sreg_range_t sra; - if ( !getn_sreg_range(&sra, sr, i) ) - break; - sel_t reg = sra.val; - if ( reg != BADSEL ) - { - std::map<ea_t, ea_t>::const_iterator p = segmap.find(reg); - if ( p != segmap.end() ) - split_sreg_range(sra.start_ea, ph.reg_first_sreg + sr, p->second, SR_auto, true); - } - } - } - - // Record the new image base address. - inf_set_baseaddr(new_base >> 4); - set_imagebase(new_base); - } - - return 1; -} - -//---------------------------------------------------------------------- -// -// LOADER DESCRIPTION BLOCK -// -//---------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - // loader flags - 0, - - // check input file format. if recognized, then return 1 - // and fill 'fileformatname'. - // otherwise return 0 - accept_file, - - // load file into the database. - load_file, - - // create output file from the database. - // this function may be absent. - save_file, - - // take care of a moved segment (fix up relocations, for example) - move_segm, - NULL, -}; diff --git a/idasdk75/ldr/dos/dos_ovr.cpp b/idasdk75/ldr/dos/dos_ovr.cpp deleted file mode 100644 index 0ae3ff7..0000000 --- a/idasdk75/ldr/dos/dos_ovr.cpp +++ /dev/null @@ -1,1068 +0,0 @@ -/* - * This Loader Module is written by Ilfak Guilfanov and - * rewriten by Yury Haron - * - */ -/* - L O A D E R pard of MS-DOS file format's (overlayed EXE) -*/ - -#include "../idaldr.h" -#include <struct.hpp> -#include <exehdr.h> -#include "dos_ovr.h" - -static const char *const stub_class = "STUBSEG"; -static const char *const stub_name_fmt = "stub%03d"; -static const char *const ovr_class = "OVERLAY"; -static const char *const ovr_name_fmt = "ovr%03d"; - -static uint32 ovr_off = 0; - -//------------------------------------------------------------------------ -o_type PrepareOverlayType(linput_t *li, exehdr *E) -{ - uint32 flen = qlsize(li); - uint32 base = E->HdrSize * 16; - uint32 loadend = base + E->CalcEXE_Length(); - uint32 fbovoff; - fbov_t fbov; - - ovr_off = 0; - - for ( fbovoff = (loadend + 0xF) & ~0xF; ; fbovoff += 0x10 ) - { - if ( pos_read(li, fbovoff, &fbov, sizeof(fbov)) ) - break; - if ( fbov.fb != FB_MAGIC ) - break; - if ( fbov.ov == OV_MAGIC ) - { - ovr_off = fbovoff; - return (fbov.exeinfo > loadend - || fbov.ovrsize > (flen - fbovoff) - || fbov.segnum <= 0) - ? ovr_pascal - : ovr_cpp; - } - } - - exehdr e1; - fbovoff = (loadend + 511) & ~511; - flen -= fbovoff; - if ( !pos_read(li, fbovoff, &e1, sizeof(e1)) - && e1.exe_ident == EXE_ID //only MZ ! - && flen >= (base = e1.HdrSize*16) - && e1.TablOff + (e1.ReloCnt*4) <= (flen -= base) - && e1.CalcEXE_Length() <= flen ) - { - ovr_off = fbovoff; - return ovr_ms; - } - return ovr_noexe; -} - -//------------------------------------------------------------------------ -static bool isStubPascal(ea_t ea) -{ - return get_word(ea) == 0x3FCD // int 3F - && (int32)get_dword(ea+4) > 0 // fileoff - && get_word(ea+8) != 0 // codesize - && (short)get_word(ea+10) >= 0 // relsize (assume max 32k) - && (short)get_word(ea+12) > 0 // nentries - && (short)get_word(ea+12) < (0x7FFF / sizeof(ovrentry_t)) // nentries - && is_mapped(to_ea(inf_get_baseaddr() + get_word(ea+14), 0)); // prevstub -} - -//------------------------------------------------------------------------ -linput_t *CheckExternOverlays(void) -{ - char buf[MAXSTR]; - const char *p; - if ( get_input_file_path(buf, sizeof(buf)) <= 0 - || (p=strrchr(buf, '.')) == NULL - || stricmp(++p, e_exe) != 0 ) - { - return NULL; - } - - for ( segment_t *s = get_first_seg(); s != NULL; s = get_next_seg(s->start_ea) ) - { - ea_t ea = s->start_ea; - if ( isStubPascal(ea) ) - { - switch ( ask_yn(ASKBTN_NO, - "This file contains reference to Pascal-stype overlays\n" - "Do you want to load it?") ) - { - - case ASKBTN_NO: - return NULL; - case ASKBTN_CANCEL: - loader_failure(); - default: //Yes - break; - } - while ( true ) - { - p = ask_file(false, - set_file_ext(buf, sizeof(buf), buf, "ovr"), - "Please enter pascal overlays file"); - CheckCtrlBrk(); - if ( p == NULL ) - return NULL; - - linput_t *li = open_linput(p, false); - if ( li != NULL ) - return li; - warning("Pascal style overlays file '%s' is not found", p); - } - } - } - return NULL; -} - -//------------------------------------------------------------------------ -static void removeBytes(void) -{ - ea_t ea = inf_get_omin_ea(); - - msg("Deleting bytes which do not belong to any segment...\n"); - for ( int i = 0; ; ++i ) - { - if ( ea >= inf_get_omax_ea() ) - break; - - segment_t *sptr = getnseg(i); - - if ( ea < sptr->start_ea ) - { - show_addr(ea); - deb(IDA_DEBUG_LDR, - "Deleting bytes at %a..%a (they do not belong to any segment)...\n", - ea, - sptr->start_ea); - if ( disable_flags(ea,sptr->start_ea) ) - { - warning("Maximal number of segments is reached, some bytes are out of segments"); - return; - } - CheckCtrlBrk(); - } - ea = sptr->end_ea; - } -} - -//------------------------------------------------------------------------ -static int add_struc_fld( - struc_t *st, - flags_t flag, - size_t sz, - const char *name, - const char *cmt) -{ - int i = add_struc_member(st, name, BADADDR, flag, NULL, sz); - if ( i == 0 && cmt != NULL ) - set_member_cmt(get_member_by_name(st, name), cmt, false); - return i; -} - -//------------------------------------------------------ -static void describeStub(ea_t stubEA) -{ - static const char stubSname[] = "_stub_descr"; - static tid_t id = 0; - - if ( id == 0 - && (id=get_struc_id(stubSname)) == BADNODE ) - { - struc_t *st = get_struc(add_struc(BADADDR, stubSname)); - if ( st == NULL ) - goto badst; - st->props |= SF_NOLIST; - if ( add_struc_fld(st, byte_flag()|hex_flag(), 2, - "int_code", "Overlay manager interrupt") - || add_struc_fld(st, word_flag()|hex_flag(), sizeof(short), - "memswap", "Runtime memory swap address") - || add_struc_fld(st, dword_flag()|hex_flag(), sizeof(int32), - "fileoff", "Offset in the file to the code") - || add_struc_fld(st, word_flag()|hex_flag(), sizeof(short), - "codesize", "Code size") - || add_struc_fld(st, word_flag()|hex_flag(), sizeof(short), - "relsize", "Relocation area size") - || add_struc_fld(st, word_flag()|dec_flag(), sizeof(short), - "nentries", "Number of overlay entries") - || add_struc_fld(st, word_flag()|seg_flag(), sizeof(short), - "prevstub", "Previous stub") - || add_struc_fld(st, byte_flag()|hex_flag(), STUBUNK_SIZE, - "workarea", NULL) ) - { -badst: - warning("Failed to create stub structure descriptor"); - id = BADNODE; - } - else - { - array_parameters_t apt; - apt.flags = AP_ALLOWDUPS; - apt.lineitems = 8; - apt.alignment = -1; // nonalign - set_array_parameters(get_member_id(st, 0), &apt); - set_array_parameters(get_member_id(st,offsetof(stub_t,unknown)), &apt); - // st->props |= SF_NOLIST; - // save_struc(st, true); - id = st->id; - } - } - - ushort tmp = get_word(stubEA + offsetof(stub_t, prevstub)); - if ( tmp != 0 ) - put_word(stubEA + offsetof(stub_t, prevstub), uint16(tmp + inf_get_baseaddr())); - - tmp = get_word(stubEA + offsetof(stub_t, nentries)); - - if ( id != BADNODE ) - { - del_items(stubEA, DELIT_EXPAND, sizeof(stub_t)); - create_struct(stubEA, sizeof(stub_t), id); - } - - stubEA += sizeof(stub_t); - - if ( tmp != 0 ) - { - do - { - auto_make_proc(stubEA); - stubEA += 5; - CheckCtrlBrk(); - } while ( --tmp ); - } -} - -//------------------------------------------------------------------------ -static void load_overlay( - linput_t *li, - uint32 exeinfo, - ea_t stubEA, - segment_t *s, - qoff64_t fboff) -{ - ea_t entEA = stubEA + sizeof(stub_t); - stub_t stub; - - if ( get_bytes(&stub, sizeof(stub), stubEA) != sizeof(stub) ) - errstruct(); - msg("Overlay stub at %a, code at %a...\n", stubEA, s->start_ea); - if ( stub.CDh != 0xCD ) - errstruct(); // bad stub - - //i now load overlay code: - bool waszero = false; - if ( !stub.codesize ) // IDA doesn't allow 0 length segments - { - ++stub.codesize; - waszero = true; - } - s->end_ea = s->start_ea + stub.codesize; - file2base(li, fboff+stub.fileoff, s->start_ea, s->end_ea, - fboff == 0 - ? FILEREG_NOTPATCHABLE - : FILEREG_PATCHABLE); - if ( waszero ) - { - s->type = SEG_NULL; - stub.codesize = 0; - } - - uint i; - for ( i = 0; i < stub.nentries; ++i ) - { - show_addr(entEA); - put_byte(entEA, 0xEA); // jmp far - ushort offset = get_word(entEA+2); - put_word(entEA+1, offset); // offset - put_word(entEA+3, s->sel); // selector - auto_make_proc(to_ea(sel2para(s->sel), offset)); - entEA += sizeof(ovrentry_t); - CheckCtrlBrk(); - } - - qoff64_t fpos = fboff + stub.fileoff + stub.codesize; - qlseek(li, fpos); - - fixup_data_t fd(FIXUP_SEG16); - - uint relcnt = stub.relsize / 2; - validate_array_count(li, &relcnt, sizeof(ushort), "Relocation count", fpos); - if ( relcnt != 0 ) - { - ushort *relb = qalloc_array<ushort>(relcnt); - if ( !relb ) - nomem("overlay relocation table"); - - lread(li, relb, sizeof(ushort)*relcnt); - int32 pos = qltell(li); //must?? - - ushort *relc = relb; - do - { - if ( *relc > stub.codesize ) - errstruct(); - - ea_t xEA = s->start_ea + *relc++; - show_addr(xEA); - ushort relseg = get_word(xEA); - if ( exeinfo != 0 ) - { - seginfo_t si; - - if ( pos_read(li, exeinfo + relseg, &si, sizeof(si)) ) - errstruct(); - relseg = si.seg; - } - - fd.sel = relseg + inf_get_baseaddr(); - fd.set(xEA); - put_word(xEA, ushort(fd.sel)); - CheckCtrlBrk(); - } while ( --relcnt ); - qfree(relb); - qlseek(li, pos); - } -} - -//------------------------------------------------------------------------ -static void add_seg16(ea_t ea) -{ - segment_t s; - s.sel = ea >> 4; - s.start_ea = ea; - s.end_ea = BADADDR; - s.align = saRelByte; - s.comb = scPub; - add_segm_ex(&s, NULL, NULL, ADDSEG_NOSREG); -} - -//------------------------------------------------------------------------ -static sel_t AdjustStub(ea_t ea) // returns prev stub -{ - segment_t *seg = getseg(ea); - - if ( ea != seg->start_ea ) - add_seg16(ea); - - ushort nentries = get_word(ea+12); - uint32 segsize = sizeof(stub_t) + nentries * sizeof(ovrentry_t); - seg = getseg(ea); - - asize_t realsize = seg->end_ea - seg->start_ea; - if ( segsize > realsize ) - return BADSEL; // this stub is bad - - if ( segsize != realsize ) - { - ea_t next = seg->start_ea + segsize; - - set_segm_end(seg->start_ea, next, 0); - next += 0xF; - next &= ~0xF; - if ( is_mapped(next) ) - { - segment_t *s = getseg(next); - if ( s == NULL ) - add_seg16(next); - } - } - return get_word(ea + 14); -} - -//------------------------------------------------------------------------ -void LoadPascalOverlays(linput_t *li) -{ - //AdjustPascalOverlay - ea_t minea = inf_get_min_ea(); - ea_t maxea = inf_get_max_ea(); - for ( ea_t ea = minea; ea < maxea; ) - { - ea &= ~0xF; - if ( isStubPascal(ea) ) - { - AdjustStub(ea); - ea = getseg(ea)->end_ea; - ea += 0xF; - CheckCtrlBrk(); - } - else - { - ea += 0x10; - } - } - //- - ea_t ea; - int i = 0; - for ( segment_t *s0 = get_first_seg(); s0 != NULL; s0 = get_next_seg(ea), ++i ) - { - ea = s0->start_ea; - - if ( get_byte(ea) != 0xCD || get_byte(ea+1) != 0x3F ) - continue; - set_segm_class(s0, stub_class); - char sname[32]; - qsnprintf(sname, sizeof(sname), stub_name_fmt, i); - set_segm_name(s0, sname); - - segment_t s; - s.comb = scPub; - s.align = saRelPara; - s.start_ea = (inf_get_max_ea() + 0xF) & ~0xF; - s.sel = setup_selector(s.start_ea >> 4); - // 04.06.99 ig: what is exeinfo and why it is passed as 0 here? - load_overlay(li, 0/*???*/, ea, &s, ovr_off); //i - qsnprintf(sname, sizeof(sname), ovr_name_fmt, i); - if ( !add_segm_ex(&s, sname, ovr_class, ADDSEG_NOSREG|ADDSEG_SPARSE) ) - loader_failure(); - describeStub(ea); - CheckCtrlBrk(); - } - removeBytes(); -} - -//------------------------------------------------------------------------ -static ea_t CppInfoBase(fbov_t *fbov) -{ - seginfo_t si; - ea_t siEA = get_fileregion_ea(fbov->exeinfo); - - if ( siEA == BADADDR - || get_bytes(&si, sizeof(si), siEA) != sizeof(si) ) - { - errstruct(); - } - - if ( (si.flags & SI_OVR) && si.seg ) //possible truncation - { - ushort lseg = si.seg; - - msg("Probbly the input file was truncated by 'unp -h'. Searching the base...\n"); - do - { - if ( si.seg > lseg ) - errstruct(); - lseg = si.seg; - - if ( siEA < inf_get_omin_ea()+sizeof(si) - || get_bytes(&si, sizeof(si), siEA -= sizeof(si)) != sizeof(si) ) - { - errstruct(); - } - fbov->exeinfo -= sizeof(si); - CheckCtrlBrk(); - } while ( si.seg ); - add_pgm_cmt("Real (before unp -h) EXEinfo=%08X", fbov->exeinfo); - } - return siEA; -} - -//------------------------------------------------------------------------ -sel_t LoadCppOverlays(linput_t *li) -{ - fbov_t fbov; - sel_t dseg = BADSEL; - - if ( pos_read(li, ovr_off, &fbov, sizeof(fbov)) ) - errstruct(); - add_pgm_cmt("Overlays: base=%08X, size=%08X, EXEinfo=%08X", - ovr_off, fbov.ovrsize, fbov.exeinfo); - ovr_off += sizeof(fbov_t); - - if ( fbov.segnum == 0 ) - errstruct(); - - ea_t siEA = CppInfoBase(&fbov); - ushort lseg = 0; - for ( int32 i = 0; i < fbov.segnum; ++i ) - { - seginfo_t si; - - if ( get_bytes(&si, sizeof(si), siEA) != sizeof(si) ) - errstruct(); - siEA += sizeof(si); - - if ( si.maxoff == 0xFFFF ) - continue; // skip EXEINFO & OVRDATA - if ( si.maxoff <= si.minoff ) - continue; - if ( si.seg < lseg ) - errstruct(); - lseg = si.seg; - - si.seg += (ushort)inf_get_baseaddr(); - - const char *sclass = NULL; - segment_t s; //i initialize segment_t with 0s - s.align = saRelByte; - s.comb = scPub; - if ( si.seg == inf_get_start_ss() ) - { - sclass = CLASS_STACK; - s.type = SEG_DATA; - s.comb = scStack; - } - if ( si.flags & SI_COD ) - { - sclass = CLASS_CODE; - s.type = SEG_CODE; - } - if ( si.flags & SI_DAT ) - { - sclass = CLASS_BSS; - s.type = SEG_DATA; - dseg = si.seg; - } - s.name = 0; - if ( si.flags & SI_OVR ) - { - s.align = saRelPara; - s.start_ea = (inf_get_max_ea() + 0xF) & ~0xF; - s.sel = setup_selector(s.start_ea >> 4); - //i end_ea is set in load_overlay() - load_overlay(li, fbov.exeinfo, to_ea(si.seg, 0), &s, ovr_off); - if ( s.type != SEG_NULL ) - s.type = SEG_CODE; - char sname[32]; - qsnprintf(sname, sizeof(sname), ovr_name_fmt, i); - if ( !add_segm_ex(&s, sname, ovr_class, ADDSEG_NOSREG|ADDSEG_SPARSE) ) - loader_failure(); - s.name = 0; - s.type = SEG_NORM; // undefined segment type - sclass = stub_class; - } - s.sel = si.seg; - s.start_ea = to_ea(s.sel, si.minoff); - s.end_ea = to_ea(s.sel, si.maxoff); - if ( !add_segm_ex(&s, NULL, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE) ) - loader_failure(); - if ( si.flags & SI_OVR ) - { - describeStub(s.start_ea); - char sname[32]; - qsnprintf(sname, sizeof(sname), stub_name_fmt, i); - set_segm_name(&s, sname); - } - CheckCtrlBrk(); - } - removeBytes(); - return dseg; -} - -//------------------------------------------------------------------------ -//+ -//------------------------------------------------------------------------ -static netnode msnode; - -struct modsc_t -{ - uint32 bpos; - uint32 size; - ushort Toff; - ushort Hsiz; - ushort Rcnt; - ushort Mpara; -}; - -static ea_t ref_off_EA; -static ea_t ref_ind_EA; -static uint ref_oi_cnt; - -//------------------------------------------------------------------------ -static uint CreateMsOverlaysTable(linput_t *li, bool *PossibleDynamic) -{ - modsc_t o; - uint Count = 0; - uint32 flen = qlsize(li); - - o.bpos = ovr_off; - msnode.create(); - msg("Searching for the overlays in the file...\n"); - while ( o.bpos + sizeof(exehdr) < flen ) - { - exehdr E; - uint32 delta; - - if ( pos_read(li, o.bpos, &E, sizeof(E)) ) - errstruct(); - - o.size = E.CalcEXE_Length(); - delta = (uint32)(o.Hsiz = E.HdrSize) * 16; - o.Toff = E.TablOff; - o.Rcnt = E.ReloCnt; - o.Mpara = (ushort)((o.size + 0xF) >> 4); - - uint32 ost = flen - o.bpos; - if ( E.exe_ident != EXE_ID //only MZ ! - || ost < delta - || (uint32)o.Toff + (E.ReloCnt*4) > (ost -= delta) - || o.size > ost ) - { - return Count; - } - CheckCtrlBrk(); - - msnode.supset(++Count, &o, sizeof(o)); - ovr_off = o.bpos + delta + o.size; - uint32 d2 = align_up(ovr_off, 512); - if ( o.bpos == d2 ) - { - warning("Too small overflay size %u, stopped processing them", delta+o.size); - break; - } - o.bpos = d2; - if ( E.Overlay != Count ) - *PossibleDynamic = false; - } - ovr_off = 0; - return Count; -} - -//------------------------------------------------------------------------ -static void LoadMsOvrData(linput_t *li, uint Count, bool Dynamic) -{ - fixup_data_t fd(FIXUP_SEG16); - for ( uint i = 1; i <= Count; ++i ) - { - modsc_t o; - - // skip dropped overlays - if ( msnode.supval(i, &o, sizeof(o)) != sizeof(o) ) - continue; - - segment_t s; - s.comb = scPub; - s.align = saRelPara; - s.start_ea = (inf_get_max_ea() + 0xF) & ~0xF; - s.sel = setup_selector(s.start_ea >> 4); - msnode.altset(i, s.sel); - s.end_ea = s.start_ea + ((uint32)o.Mpara << 4); - file2base(li, - o.bpos + o.Hsiz*16LL, - s.start_ea, - s.start_ea + o.size, - FILEREG_PATCHABLE); - char sname[32]; - qsnprintf(sname, sizeof(sname), ovr_name_fmt, i); - if ( !add_segm_ex(&s, sname, ovr_class, ADDSEG_NOSREG|ADDSEG_SPARSE) ) - loader_failure(); - - qlseek(li, o.bpos + o.Toff); - - for ( uint j = o.Rcnt; j; --j ) - { - ushort buf[2]; - - lread(li, buf, sizeof(buf)); - -//ATTENTION!!! if Dynamic (ms-autopositioning) segment part of relocation -// address == pseudodata segment to load (from data in ovr!) -// We should checked it but don't have any testcase - ea_t xEA = Dynamic - ? s.start_ea + buf[0] - : s.start_ea + to_ea(buf[1], buf[0]); - - if ( xEA >= s.end_ea ) - errstruct(); - - show_addr(xEA); - - ushort ubs = ushort(get_word(xEA) + inf_get_baseaddr()); - put_word(xEA, ubs); - fd.sel = ubs; - fd.set(xEA); - add_segm_by_selector(ubs, CLASS_CODE); - CheckCtrlBrk(); - } - } -} - -//------------------------------------------------------------------------ -static sel_t SearchMsOvrTable(uint *Cnt) -{ - modsc_t dsc; - if ( msnode.supval(1, &dsc, sizeof(dsc)) != sizeof(dsc) ) - { -interr: - error("Internal error"); - } - - uint32 src[2] = { 0, dsc.bpos }; - ea_t dstea, sea, ea = inf_get_min_ea(); - uint AddSkip, Count = *Cnt; - uint i, j; // watcom ... - segment_t *s; - - msg("Searching the overlay reference data table...\n"); - while ( ea + sizeof(src) < inf_get_max_ea() - && (sea = bin_search2(ea, - inf_get_max_ea(), - (uchar *)src, - NULL, - sizeof(src), - BIN_SEARCH_CASE | BIN_SEARCH_NOBREAK | BIN_SEARCH_FORWARD)) != BADADDR ) - { - ea = sea + sizeof(uint32); - s = getseg(ea); - if ( s == NULL - || ea - s->start_ea < sizeof(uint32)*(Count+1) - || ea + (2*sizeof(uint32) * Count) > s->end_ea ) - { -nextfndadd: - ea += sizeof(uint32); -nextfnd: - continue; - } - - AddSkip = 0; - for ( i = 2; i <= Count + AddSkip; ++i ) - { - ea += sizeof(uint32); - uint32 pos = get_dword(ea); - - if ( pos == 0 ) - { - ++AddSkip; - if ( ea + (2*sizeof(uint32) * (Count+AddSkip-i)) > s->end_ea ) - goto nextfnd; - } - else - { - if ( msnode.supval(i - AddSkip, &dsc, sizeof(dsc)) != sizeof(dsc) ) - goto interr; - if ( pos != dsc.bpos ) - goto nextfndadd; - } - } - goto found; - } -badtable: - ref_oi_cnt = (uint)-1; - return BADSEL; - -found: - if ( AddSkip ) - { - ea = sea + sizeof(uint32); - for ( i = 2; i <= Count; ++i ) - { - if ( !get_dword(ea += sizeof(uint32)) ) - { - if ( !AddSkip ) - goto interr; - --AddSkip; - for ( j = Count; j >= i; --j ) - { - if ( msnode.supval(j, &dsc, sizeof(dsc)) != sizeof(dsc) ) - goto interr; - msnode.supset(j+1, &dsc, sizeof(dsc)); - } - msnode.supdel(i); - ++Count; - CheckCtrlBrk(); - } - } - if ( AddSkip ) - goto interr; - } - - //msg("Found disk blocks table\n"); - ea = sea - ((Count-1) * sizeof(ushort)) - 1; // -1 -- unification - do - { - ea = bin_search2(s->start_ea, - ea+1, - (uchar *)src, - NULL, - sizeof(ushort), - BIN_SEARCH_CASE | BIN_SEARCH_NOBREAK | BIN_SEARCH_BACKWARD); - if ( ea == BADADDR ) - goto badtable; - } while ( (sea - ea) % sizeof(ushort) ); - - ref_oi_cnt = (sea - ea) / sizeof(ushort); - if ( ref_oi_cnt <= 1 ) - goto badtable; - ref_ind_EA = ea; - - //msg("Check all tables...\n"); - j = Count; - while ( (ea += sizeof(ushort)) < sea ) - { - i = get_word(ea); - if ( i > j ) - { - if ( j == *Cnt ) - goto badtable; - j = i; - } - } - if ( (i = j - Count) != 0 ) - { - AddSkip = i; - do - { - if ( get_dword(sea - sizeof(uint32)) ) - break; - if ( (ref_oi_cnt -= 2) <= 1 ) - goto badtable; - sea -= sizeof(uint32); - } while ( --i ); - AddSkip -= i; - for ( j = Count; j; --j ) - { - if ( msnode.supval(j, &dsc, sizeof(dsc)) != sizeof(dsc) ) - msnode.supdel(j + AddSkip); - else - msnode.supset(j + AddSkip, &dsc, sizeof(dsc)); - } - do - { - msnode.supdel(++j); - } - while ( j < AddSkip ); - Count += AddSkip; - CheckCtrlBrk(); - if ( i ) - { - ea = sea + Count*sizeof(uint32); - Count += i; - do - { - if ( get_dword(ea += sizeof(uint32)) ) - goto badtable; - } - while ( --i ); - } - } - - dstea = sea; - - ea = ref_ind_EA - (ref_oi_cnt*sizeof(ushort)); - if ( get_prev_fixup_ea(ea+1) != ea ) - ask_for_feedback("Absent relocation at start of offset table"); - - ref_off_EA = ea; - - sea = ref_ind_EA; - AddSkip = 0; // added 07.04.2015 (bmpcad) - for ( i = 1; i < ref_oi_cnt; ++i ) - { - ea += sizeof(ushort); - sea += sizeof(ushort); - - uint rsz; - j = get_word(sea); - if ( !j ) - { - if ( i <= Count ) - goto badofftb; - ++AddSkip; - continue; - } - - rsz = get_word(ea); - - if ( msnode.supval(j, &dsc, sizeof(dsc)) != sizeof(dsc) ) - { - if ( rsz ) - goto badofftb; - msg("An overlay index %u in the table of indexes points to a missing overlay\n", i); - } - else if ( rsz >= dsc.size ) - { -badofftb: - ask_for_feedback("Incompatible offset table"); - AddSkip = 0; - break; - } - } - - sea = dstea + (Count+1+AddSkip)*sizeof(uint32); - for ( i = 1; i <= Count; ++i ) - { - sea += sizeof(uint32); - uint32 dt = get_dword(sea); - - if ( msnode.supval(i, &dsc, sizeof(dsc)) != sizeof(dsc) ) - { - if ( dt ) - { -badmemtb: - ask_for_feedback("Incompatible mem-size table"); - } - continue; - } - - if ( !dt ) - { - ask_for_feedback("Zero overlay memory size in description table"); - goto badtable; - } - - if ( dt < dsc.Mpara || dt >= 0x1000 ) - goto badmemtb; - - //Possiblee needed for segment with unitialized data at top, but not sampled... - if ( dt > dsc.Mpara ) - { - dsc.Mpara = (ushort)dt; - msnode.supset(i, &dsc, sizeof(dsc)); - } - } - - for ( i = 0; i < AddSkip; i++ ) - { - sea += sizeof(uint32); - if ( get_dword(sea) != 0 ) - { - ask_for_feedback("Incompatible extension in overlay tables"); - break; - } - } - - msg("All tables OK\n"); - create_word(ref_off_EA, i = (ref_oi_cnt - AddSkip)*sizeof(ushort)); - force_name(ref_off_EA, "ovr_off_tbl"); - create_word(ref_ind_EA, i); - force_name(ref_ind_EA, "ovr_index_tbl"); - *Cnt = Count; - i = (Count + 1) * sizeof(uint32); - create_dword(dstea, i); - force_name(dstea, "ovr_start_tbl"); - dstea += i + (AddSkip * sizeof(uint32)); - create_dword(dstea, i); - force_name(dstea, "ovr_memsiz_tbl"); - return s->sel; -} - -//------------------------------------------------------------------------ -static segment_t *MsOvrStubSeg(uint *stub_cnt, ea_t r_top, sel_t dseg) -{ - msg("Searching for the stub segment...\n"); - int count = get_segm_qty(); - for ( int i = 0; i < count; ++i ) - { - segment_t *seg = getnseg(i); - if ( seg->sel == dseg ) - continue; - ea_t ea = seg->start_ea; - uchar buf[3*sizeof(ushort)]; - - if ( ea >= r_top ) - break; - - if ( get_bytes(buf, sizeof(buf), ea) != sizeof(buf) ) - continue; - if ( *(uint32 *)buf || *(ushort *)&buf[sizeof(uint32)] ) - continue; - - uint cnt = 0; - uchar frs = (uchar)-1; - while ( (ea += sizeof(buf)) < seg->end_ea - sizeof(buf) ) - { - if ( (frs = get_byte(ea)) != 0xCD || get_byte(ea+1) != 0x3F ) - break; - ushort ind = get_word(ea + sizeof(ushort)); - if ( !ind || ind > ref_oi_cnt ) - break; - ++cnt; - CheckCtrlBrk(); - } - if ( !frs && cnt >= ref_oi_cnt ) - { - *stub_cnt = cnt; - return seg; - } - } - return NULL; -} - -//------------------------------------------------------------------------ -static void CreateMsStubProc(segment_t *s, uint stub_cnt) -{ - ea_t ea = s->start_ea; - - set_segm_name(s, "STUB"); - set_segm_class(s, CLASS_CODE); - create_byte(ea, 3*sizeof(ushort)); - ea += 3*sizeof(ushort); - msg("Patching the overlay stub-segment...\n"); - for ( uint ind, i = 0; i < stub_cnt; ++i, ea += 3*sizeof(ushort) ) - { - ind = get_word(ea+2); - if ( ind != 0 ) - { - if ( ind >= ref_oi_cnt ) - { -badref: - ask_for_feedback("Illegal reference in overlay call interrupt"); - continue; - } - - ind *= sizeof(ushort); - uint off = (uint)get_word(ea+4) + get_word(ref_off_EA + ind); - ind = get_word(ref_ind_EA + ind); // overlay number - ushort sel = (ushort)msnode.altval(ind); - modsc_t o; - if ( msnode.supval(ind, &o, sizeof(o)) != sizeof(o) ) - goto badref; - if ( off >= o.size ) - goto badref; - - show_addr(ea); - put_byte(ea, 0xEA); // jmp far - put_word(ea+1, off); // offset - put_word(ea+3, sel); // selector - put_byte(ea+5, 0x90); //NOP -> for autoanalisis - auto_make_proc(ea); - auto_make_proc(to_ea(sel2para(sel), off)); - CheckCtrlBrk(); - } - } - create_align(ea, s->end_ea - ea, 0); -} - -//------------------------------------------------------------------------ -sel_t LoadMsOverlays(linput_t *li, bool PossibleDynamic) -{ - sel_t dseg = BADSEL; - uint Cnt = CreateMsOverlaysTable(li, &PossibleDynamic); - - if ( ovr_off ) - warning("File has extra information\n" - "\3Loading 0x%X bytes, total file size 0x%" FMT_64 "X", - ovr_off, qlsize(li)); - - if ( Cnt ) - { - dseg = SearchMsOvrTable(&Cnt); - if ( dseg != BADSEL ) - PossibleDynamic = false; - else if ( !PossibleDynamic ) - ask_for_feedback("Cannot find the overlay call data table"); - - ea_t r_top = inf_get_max_ea(); - LoadMsOvrData(li, Cnt, PossibleDynamic); - - if ( ref_oi_cnt != (uint)-1 ) - { - uint stub_cnt; - segment_t *s = MsOvrStubSeg(&stub_cnt, r_top, dseg); - - if ( s != NULL ) - CreateMsStubProc(s, stub_cnt); - else - ask_for_feedback("The overlay-manager segment not found"); - } - } - msnode.kill(); - return dseg; -} diff --git a/idasdk75/ldr/dos/dos_ovr.h b/idasdk75/ldr/dos/dos_ovr.h deleted file mode 100644 index 4989b38..0000000 --- a/idasdk75/ldr/dos/dos_ovr.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.00 - * Copyright (c) 1990-94 by Ilfak Guilfanov. (2:5020/209@fidonet) - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _DOS_OVR_H_ -#define _DOS_OVR_H_ - -// the following structures are 1-byte aligned (!) -#pragma pack(push,1) - -struct fbov_t -{ - ushort fb; -#define FB_MAGIC 0x4246 - ushort ov; -#define OV_MAGIC 0x564F - uint32 ovrsize; - uint32 exeinfo; - int32 segnum; -}; - -struct seginfo_t -{ - ushort seg; - ushort maxoff; // FFFF - unknown - ushort flags; -#define SI_COD 0x0001 -#define SI_OVR 0x0002 -#define SI_DAT 0x0004 - ushort minoff; -}; - -struct stub_t -{ - uchar CDh; // 0 - uchar intnum; // 1 - ushort memswap; // 2 - int32 fileoff; // 4 - ushort codesize; // 8 - ushort relsize; // 10 - ushort nentries; // 12 - ushort prevstub; // 14 -#define STUBUNK_SIZE (0x20-0x10) - uchar unknown[STUBUNK_SIZE]; -}; - -struct ovrentry_t -{ - ushort int3f; - ushort off; - char segc; -}; - -CASSERT(sizeof(ovrentry_t) == 5); - -struct ms_entry -{ - uchar CDh; - uchar intnum; //normally 3Fh - ushort ovr_index; - ushort entry_off; -}; - -bool pos_read(linput_t *fp, uint32 pos, void *buf, size_t size); -int CheckCtrlBrk(void); -void add_segm_by_selector(sel_t base, const char *sclass); -extern const char e_exe[]; -// -enum o_type { ovr_noexe, ovr_pascal, ovr_cpp, ovr_ms }; - -o_type PrepareOverlayType(linput_t *fp, exehdr *E); -linput_t *CheckExternOverlays(void); -sel_t LoadCppOverlays(linput_t *fp); -sel_t LoadMsOverlays(linput_t *fp, bool PossibleDynamic); -void LoadPascalOverlays(linput_t *fp); - -NORETURN void errstruct(void); - -#pragma pack(pop) - -#endif diff --git a/idasdk75/ldr/dos/makefile b/idasdk75/ldr/dos/makefile deleted file mode 100644 index 7b2d9d9..0000000 --- a/idasdk75/ldr/dos/makefile +++ /dev/null @@ -1,24 +0,0 @@ -PROC=dos -O1=dos_ovr - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)dos$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)typeinf.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaldr.h cv.hpp dos.cpp \ - dos_ovr.h -$(F)dos_ovr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaldr.h dos_ovr.cpp \ - dos_ovr.h diff --git a/idasdk75/ldr/dump/dump.cpp b/idasdk75/ldr/dump/dump.cpp deleted file mode 100644 index eaef8b2..0000000 --- a/idasdk75/ldr/dump/dump.cpp +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov (ig@datarescue.com) - * http://www.datarescue.com - * ALL RIGHTS RESERVED. - * - */ - -#include "../idaldr.h" - -//-------------------------------------------------------------------------- -static int make_words(char *line, char **words, int maxwords) -{ - while ( qisspace(*line) ) - line++; - int i; - for ( i=0; *line && i < maxwords; i++ ) - { - words[i] = line; - while ( !qisspace(*line) && *line != '\0' ) - line++; - if ( *line != '\0' ) - *line++ = '\0'; - while ( qisspace(*line) ) - line++; - } - return i; -} - -//-------------------------------------------------------------------------- -inline uint32 hex(char *&word) -{ - return strtoul(word, &word, 16); -} - -//-------------------------------------------------------------------------- -inline uint32 oct(char *&word) -{ - return strtoul(word, &word, 8); -} - -#define FAILED \ - do \ - { \ - deb(IDA_DEBUG_LDR, \ - "failed at %d (input file line %d)\n", \ - __LINE__, \ - nl); \ - return 0; \ - } while ( false ) - -//-------------------------------------------------------------------------- -static int idaapi accept_file( - qstring *fileformatname, - qstring *, - linput_t *li, - const char *) -{ - char line[MAXSTR]; - char *words[MAXSTR]; - - // We try to interpret the input file as a text - // file with a dump format, i.e. all lines should look like - -//00000020: 59 69 74 54-55 B6 3E F7-D6 B9 C9 B9-45 E6 A4 52 -//0020: 59 69 74 54 55 B6 3E F7 D6 B9 C9 B9 45 E6 A4 52 -//1000: 12 23 34 56 78 -//0100: 31 C7 1D AF 32 04 1E 32 05 1E 3C 32 07 1E 21 D9 -//12 23 34 56 78 - - // and similar lines - // We allow non-ascii characters at the end of the line - // We skip empty lines - - ssize_t p0len = -1; // length of the first word's hex part - char w0sep[10]; // separator after the first word - w0sep[0] = '\0'; - int nl = 0; - int nontrivial_line_count = 0; - bool no_more_lines = false; - bool has_star = false; - uint32 adr, oldadr=0; - while ( qlgets(line, sizeof(line), li) ) - { - nl++; - strrpl(line, '-', ' '); - int nw = make_words(line, words, qnumber(words)); - if ( line[0] == ';' || line[0] == '#' || nw == 0 ) - { - if ( has_star ) - FAILED; - continue; - } - if ( no_more_lines ) - FAILED; - // od -x format may contain '*' lines which mean repetition - if ( strcmp(words[0], "*") == 0 && nw == 1 ) - { - if ( nontrivial_line_count == 0 ) - FAILED; - if ( has_star ) - FAILED; - has_star = true; - continue; - } - has_star = false; - nontrivial_line_count++; - // the first word must be a number (more than one digit) - char *ptr = words[0]; - adr = hex(ptr); - ssize_t p0 = ptr - words[0]; - if ( p0 <= 1 || p0 > 16 ) - FAILED; - if ( nontrivial_line_count > 1 && p0 < p0len ) - FAILED; - p0len = p0; - // take the separator from the first line - if ( nontrivial_line_count == 1 ) - { - qstrncpy(w0sep, ptr, sizeof(w0sep)); - while ( *ptr ) - if ( strchr(":>-.", *ptr++) == NULL ) - FAILED; - } - else - { - if ( strcmp(w0sep, ptr) != 0 ) - FAILED; - } - bool haspref = p0len >= 4 || w0sep[0] != '\0'; - if ( haspref ) - { - // if the line contains only the address, then don't accept lines anymore - if ( nw == 1 ) - { - if ( nontrivial_line_count == 1 ) - FAILED; - no_more_lines = true; - if ( adr <= oldadr ) - FAILED; - } - else - { - // the remaining words should be numbers with at least 1 position - // (at least the second word should be so) - ptr = words[1]; - hex(ptr); - if ( ptr == words[1] ) - FAILED; - } - } - oldadr = adr; - } - if ( nontrivial_line_count == 0 || has_star ) - FAILED; - - *fileformatname = "Dump file"; - return 1; -} - -//-------------------------------------------------------------------------- -static uchar bytes[MAXSTR/2]; -static bool iscode; -static sel_t sel; -static ea_t sea; -static ea_t eea; -static ushort neflag; - -static void copy(const ea_t ea, const ea_t top) -{ - if ( sea == BADADDR ) - { - if ( neflag & NEF_SEGS ) - { - const char *sname = iscode ? "CODE" : "DATA"; - sel = setup_selector(0); - add_segm(sel, ea, top, sname, sname); - } - sea = ea; - eea = top; - } - else - { - if ( eea < top ) - { // if the gap > 256KB, use sparse storage - int flags = top - eea > 256 * 1024 ? SEGMOD_SPARSE : 0; - eea = top; - set_segm_end(sea, eea, flags); - } - } - mem2base(bytes, ea, top, -1); -} - -//-------------------------------------------------------------------------- -void idaapi load_file(linput_t *li, ushort _neflag, const char * /*fileformatname*/) -{ - char line[MAXSTR]; - char *words[MAXSTR]; - - neflag = _neflag; - iscode = (neflag & NEF_CODE) != 0; - sel = BADSEL; - sea = BADADDR; - ea_t ea = 0; - ea_t top= 0; - bool use32 = false; - bool octpref = false; - bool octnum = false; - size_t fill = 0; - - // Since we made all the checks in accept_file, - // here we don't repeat them - - ssize_t p0len = -1; // length of the first word's hex part - char w0sep[10]; // separator after the first word - w0sep[0] = '\0'; - int nontrivial_line_count = 0; - while ( qlgets(line, sizeof(line), li) ) - { - strrpl(line, '-', ' '); - if ( line[0] == ';' || line[0] == '#' ) - continue; - int n = make_words(line, words, qnumber(words)); - if ( n == 0 ) - continue; - nontrivial_line_count++; - ssize_t bi; - // od -x format may contain '*' lines which mean repetition - if ( strcmp(words[0], "*") == 0 && n == 1 ) - { - fill = size_t(top - ea); - octpref = true; // od -x have octal prefixes - continue; - } - // the first word must be a number (more than one digit) - char *ptr = words[0]; - uint32 w0 = octpref ? oct(ptr) : hex(ptr); - p0len = ptr - words[0]; - // take the separator from the first line - if ( nontrivial_line_count == 1 ) - qstrncpy(w0sep, ptr, sizeof(w0sep)); - - // process '*' and fill the gap - if ( fill > 0 ) - { - while ( top < w0 ) - { - ea = top; - top = ea + fill; - copy(ea, top); - } - } - - int idx = 0; - if ( w0sep[0] != '\0' || p0len >= 4 ) - { - if ( nontrivial_line_count > 1 && !octpref && top != w0 ) - { - // strange, the sequence is not contiguous - // check if the prefixes are octal (od -x) - ptr = words[0]; - if ( oct(ptr) == top ) - { - octpref = true; - ptr = words[0]; - w0 = oct(ptr); - } - } - ea = w0; - idx = 1; - } - else - { - ea = top; - } - for ( bi=0; idx < n; idx++ ) //lint !e443 - { - ptr = words[idx]; - if ( nontrivial_line_count == 1 && !octnum && strlen(ptr) == 6 ) - { - oct(ptr); - if ( ptr-words[idx] == 6 ) - octnum = true; - ptr = words[idx]; -// msg("ptr=%s octnum=%d\n", ptr, octnum); - } - uint32 b = octnum ? oct(ptr) : hex(ptr); - ssize_t nc = ptr - words[idx]; - if ( nc < 2 ) - { - // we tolerate one-letter separators between numbers - if ( words[idx][1] == '\0' && strchr("\xA6|-:", words[idx][0]) != NULL ) - continue; - break; - } - nc /= octnum ? 3 : 2; // number of bytes - *(uint32 *)&bytes[bi] = b; - bi += nc; - } - top = ea + bi; - copy(ea, top); - } - - if ( eea >= 0x10000 || p0len > 4 ) - use32 = true; - if ( neflag & NEF_SEGS ) - { - if ( use32 ) - { - set_segm_addressing(getseg(sea), 1); - inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); - } - set_default_dataseg(sel); - } - if ( (neflag & NEF_RELOAD) == 0 ) - create_filename_cmt(); -} - -//-------------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - LDRF_REQ_PROC // requires the target processor to the set -| LDRF_RELOAD, // supports reloading the input file -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, - NULL, - NULL, -}; diff --git a/idasdk75/ldr/dump/makefile b/idasdk75/ldr/dump/makefile deleted file mode 100644 index 740e27f..0000000 --- a/idasdk75/ldr/dump/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=dump - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)dump$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h dump.cpp diff --git a/idasdk75/ldr/elf/elf.h b/idasdk75/ldr/elf/elf.h deleted file mode 100644 index a271ee0..0000000 --- a/idasdk75/ldr/elf/elf.h +++ /dev/null @@ -1,3136 +0,0 @@ -#ifndef __ELF_H__ -#define __ELF_H__ - -#include <map> - -#include <diskio.hpp> -#include <fixup.hpp> - -#pragma pack(push, 4) - -// gcc does not allow to initialize indexless arrays for some reason -// put an arbitrary number here. the same with visual c++ -#if defined(__GNUC__) || defined(_MSC_VER) -#define MAXRELSYMS 64 -#else -#define MAXRELSYMS -#endif - -struct elf_loader_t; -struct elf_file_info_t; -typedef Elf64_Shdr elf_shdr_t; -typedef Elf64_Phdr elf_phdr_t; -struct elf_sym_t : public Elf64_Sym -{ - elf_sym_t() - { - st_name = 0; - st_info = 0; - st_other = 0; - st_shndx = 0; - st_value = 0; - st_size = 0; - } -}; -typedef Elf64_Dyn elf_dyn_t; -typedef Elf64_Rel elf_rel_t; -struct elf_rela_t : public Elf64_Rela -{ - elf_rela_t() - { - r_offset = 0; - r_info = 0; - r_addend = 0; - } -}; - -typedef qvector<elf_rela_t> elf_rela_vec_t; - -class reader_t; -struct sym_rel; -typedef uint32 elf_sym_idx_t; -struct elf_symbol_version_t; -struct dynamic_info_t; - -typedef uint32 elf_shndx_t; -typedef qvector<elf_shdr_t> elf_shdrs_t; -typedef qvector<elf_phdr_t> elf_phdrs_t; - -//---------------------------------------------------------------------------- -struct elf_ehdr_t : public Elf64_Ehdr -{ - elf_shndx_t real_shnum; // number of entries in the SHT - // (may be greater than 0xFF00) - elf_shndx_t real_shstrndx; // section name string table section index - // (may be greater than 0xFF00) - - bool has_pht() const { return e_phoff != 0; } - void set_no_pht() - { - e_phoff = 0; - e_phnum = 0; - } - - bool has_sht() const { return e_shoff != 0; } - void set_no_sht() - { - e_shoff = 0; - e_shnum = 0; - real_shnum = 0; - } - bool is_valid_shndx(elf_shndx_t idx) const - { - return idx < real_shnum; - } - - bool has_shstrtab() const { return real_shstrndx != 0; } -}; - -//------------------------------------------------------------------------- -typedef Elf64_Chdr elf_chdr_t; - -//---------------------------------------------------------------------------- -// rel_data_t holds whatever relocation information appears to be common -// to most ELF relocation "algorithms", as defined in the per-CPU -// addenda. -// Note: Most comments below were picked from the abi386.pdf file. -struct rel_data_t -{ - // Relocation type: R_<processor>_<reloc-type>. - uint32 type; - - // abi386.pdf: This means the place (section offset or address) of - // the storage unit being relocated (computed using r_offset). - ea_t P; - - // abi386.pdf: This means the value of the symbol whose index - // resides in the relocation entry. - uval_t S; - - // S, plus addend - ea_t Sadd; - - // Whether the 'reloc' parameter passed to 'proc_handle_reloc()' - // is a REL, or a RELA (the actual reloc entry object - // itself will always be a elf_rela_t instance). - enum rel_entry_t - { - re_rel, - re_rela - }; - rel_entry_t rel_entry; - bool is_rel() const { return rel_entry == re_rel; } - bool is_rela() const { return !is_rel(); } -}; - - -//-------------------------------------------------------------------------- -enum slice_type_t -{ - SLT_INVALID = 0, - SLT_SYMTAB = 1, - SLT_DYNSYM = 2, - SLT_WHOLE = 3, -}; -struct symrel_idx_t -{ - symrel_idx_t() : type(SLT_INVALID), idx(0) {} - symrel_idx_t(slice_type_t t, elf_sym_idx_t i) : type(t), idx(i) {} - - slice_type_t type; - elf_sym_idx_t idx; - - bool operator==(const symrel_idx_t &other) const - { - return other.type == type - && other.idx == idx; - } - bool operator<(const symrel_idx_t &other) const - { - if ( type < other.type ) - return true; - if ( type > other.type ) - return false; - return idx < other.idx; - } -}; - -//---------------------------------------------------------------------------- -struct got_access_t : public range_t -{ - elf_loader_t &ldr; - // the name _GLOBAL_OFFSET_TABLE_ - static const char gtb_name[]; - - // is the given symbol the _GLOBAL_OFFSET_TABLE_? - static bool is_symbol_got(const sym_rel &sym, const char *name); - - got_access_t(elf_loader_t &_ldr) : range_t(0, 0), ldr(_ldr) {} - - // Get the start address of the GOT. - // If no GOT currently exists, and 'create' is true, one will - // be created in a segment called ".got". - // If no GOT exists or an error occurred while creating .got segment, - // the function returns 0. - ea_t get_start_ea(elf_file_info_t &finfo, bool create = false); - - // - void set_start_ea(ea_t ea) { start_ea = ea; } - - // get .got segment using the storage of well-known sections. - // If it didn't exist and the flag `create' is set then create an empty - // ".got" segment with the given initial size. - // Set the flag `create' if such segment is just created. - // If .got segment doesn't exist or an error occurred while creating it, - // the function returns NULL. - segment_t *get_got_segment(elf_file_info_t &finfo, bool *create, uint32 init_size = 0) const; - - // Some relocations, such as ARM's R_ARM_TLS_IE32, require that a got entry - // be present in the linked file, in order to point to that entry. - // However, when we are loading a simple relocatable ELF object file, - // there's no GOT present. This is problematic because, - // although we _could_ be taking a shortcut and patch the fixup to refer - // to the extern:__variable directly, it is semantically different. - // As as example, when we meet: - // LDR R3, #00000000 ; R_ARM_TLS_IE32; Offset in GOT to __libc_errno - // generating: - // LDR R3, [__libc_errno_tls_offset] - // is not the same as: - // LDR R3, [address, in got, of libc_errno_tls_offset] - // - // This is obviously the last formatting that's correct, as we don't - // even *know* what the address of __libc_errno_tls_offset is; we just - // know where to go and look for it. - // - // The solution is to create a .got section anyway, and allocate an entry - // in there with the name of the symbol, suffixed with '_tpoff'. - // - // - finfo : The elf file info (reader, ...) - // - sym : The symbol. We create the one entry for each symbol of - // each GOT-type. - // - suffix : A suffix, to be added to the symbol name. We consider - // the suffix as a GOT-type of the entry. It is sometimes - // necessary to create multiple entries for the symbol. - // E.g., '_tpoff', '_ptr', ... - // - created : The flag indicating the allocation of the new entry. - // - n : The number of allocated entries. - // - returns : An address in the .got segment. - // 0 is returned in the case of error. - ea_t allocate_entry( - elf_file_info_t &finfo, - const sym_rel &sym, - const char *suffix, - bool *created = NULL, - size_t n = 1); - - // Get the ea in the GOT section, corresponding - // the the 'A' addend. - // - // * If the file already had a GOT section, then - // the returned ea is simply got_segment->start_ea + A. - // * On the other hand, if this file had no GOT - // this calls #allocate_got_entry(). - // - // - finfo : The elf file info (reader, ...) - // - A : The 'addend' (i.e., displacement) in the GOT. - // Ignored if the original file had *no* GOT. - // - sym : The symbol. - // Ignored if the original file *did* have a GOT. - // - suffix : A suffix, to be added to the symbol name. E.g., '_tpoff', '_ptr', ... - // Ignored if the original file *did* have a GOT. - // - // - returns : An address in the GOT segment, possibly creating one. - // 0 is returned in the case of error. - ea_t get_or_allocate_entry( - elf_file_info_t &finfo, - uval_t A, - const sym_rel &sym, - const char *suffix); - - // create GOT entry for the address (used in MIPS local entries) - ea_t allocate_entry( - elf_file_info_t &finfo, - ea_t addr, - bool *created = NULL, - size_t n = 1); - -private: - // used only when original file has no GOT. - // an unique id of the symbol's GOT entry - struct symrel_id_t - { - symrel_idx_t idx; // symbol - const char *suffix; // subtype of the GOT-entry - symrel_id_t(symrel_idx_t idx_, const char *suffix_) - : idx(idx_), suffix(suffix_) {} - bool operator<(const symrel_id_t &rhs) const - { - if ( idx < rhs.idx ) - return true; - if ( !(idx == rhs.idx) ) - return false; - return strcmp(suffix, rhs.suffix) < 0; - } - }; - std::map<symrel_id_t,ea_t> allocated_sym_entries; - std::map<ea_t,ea_t> allocated_addr_entries; -}; - - -//---------------------------------------------------------------------------- -struct reloc_tools_t -{ - // dynamic information - const dynamic_info_t *di; - // reader_t container, with preprocessed data - elf_file_info_t *finfo; - // GOT accessor/creator. - got_access_t got; - - reloc_tools_t(elf_loader_t &_ldr, const dynamic_info_t *di_, elf_file_info_t *finfo_); - bool section_header_overlaps(elf_shndx_t sh_idx) const; - bool has_dlt() const; -}; - -//-------------------------------------------------------------------------- -// GOT support for the relocatable files. -// the addend of the GOT reloc is applied to the insn, -// 'P - A' should point to the current or to the next insn -bool check_got_addend(ea_t P, adiff_t A, adiff_t good_addend); -bool check_got_addend(ea_t P, adiff_t A, adiff_t good1, adiff_t good2); - -//-------------------------------------------------------------------------- -namespace tls_relocs_t -{ - // generic TLS relocs - enum type_t - { - BAD, - NTPOFF, // variant 2: @ntpoff(x) (x86) or @tpoff(x) (x64), calculates - // the negative TLS offset relative to the TLS block end; - // variant 1: TPREL(S+A), resolves to the offset from the - // current thread pointer (TP) of the thread local variable. - DTPOFF, // @dtpoff(x), calculates the TLS offset relative to the - // TLS block; - // DTPREL(S+A), resolves to the offset from its module's TLS - // block of the thread local variable. - PTPOFF, // $x@tpoff (x86 only), calculates the _positive_ TLS - // offset relative to the TLS block end. - DTPMOD, // @dtpmod(x), calculates the object identifier of the - // object containing a TLS symbol; - // LDM(S), resolves to the load module index of the symbol S. - DESC, // TLSDESC(S+A), resolves to a contiguous pair of 64-bit - // values which contain a 'tlsdesc' structure describing the - // thread local variable. The first entry holds a pointer to - // the variable's TLS descriptor resolver function and the - // second entry holds a platform-specific offset or pointer. - GOTGD, // @tlsgd(x) (x86) or @tlsgd(%rip) (x64), allocates two - // contiguous entries in the GOT to hold a `tls_index' - // structure, uses the offset of the first entry. - GOTLD, // @tlsldm(x) (x86) or @tlsld(%rip) (x64), allocates two - // contiguous entries in the GOT to hold a `tls_index' - // structure, uses the offset of the first entry. The - // `ti_tlsoffset' field of the `tls_index' is set to 0. - GOTIE, // @gotntpoff(x) (x86) or @gottpoff(%rip) (x64), allocates - // an entry in the GOT, uses the offset of this entry. The - // entry holds a variable offset in the initial TLS block. - // This negative offset is relative to the TLS blocks end. - // GTPREL(S+A), represents a 64-bit entry in the GOT for the - // offset from the current thread pointer (TP) of the - // thread local variable, see TPREL(S+A). - // @indntpoff(x) (x86), like GOTIE but uses the absolute - // GOT slot address (got_mode_t::ABS). - GOTIEP, // @tpoff(x) (x86 only), allocates an entry in the GOT, - // uses the offset of this entry. The entry holds a - // variable offset in the initial TLS block. This - // _positive_ offset is relative to the TLS blocks end. - GOTDESC, // GTLSDESC(S+A), represents a consecutive pair of 64-bit - // entries in the GOT which contain a 'tlsdesc' structure. - }; - inline bool is_got_reloc(type_t type) - { - return type >= GOTGD; - } - - // GOT slot addressing mode - enum got_mode_t - { - GOT, // offset in GOT - ABS, // absolute address - RIP, // offset relative to P-A (the linker sets the addend - // so that it points to the next insn) - }; -}; - -//-------------------------------------------------------------------------- -struct proc_def_t -{ - elf_loader_t &ldr; - reader_t &reader; - uint32 r_gotentry = 0; // reloc with P inside GOT, usually R_xxx_JUMP_SLOT - uint32 relsyms[MAXRELSYMS] = { 0 }; // relocation types which must be to loaded symbols - -#define E_RELOC_PATCHING (const char *)1 -#define E_RELOC_UNKNOWN (const char *)2 -#define E_RELOC_UNIMPL (const char *)3 -#define E_RELOC_UNTESTED (const char *)4 -#define E_RELOC_NOSYM (const char *)5 -#define E_RELOC_LAST (const char *)6 - const char *stubname = nullptr; - - // order in which relocations should be applied. A name denotes a section - // to which we are applying relocations. NULL means all other sections. - enum { MAXRELORDERS = 5 }; - const char *relsecord[MAXRELORDERS] = { nullptr }; - - // types of supported special segments - enum spec_type_t - { - SPEC_XTRN, - SPEC_COMM, - SPEC_ABS, - SPEC_TLS, - NSPEC_SEGMS - }; - // additional reserved indexes of special segments (see MIPS) - uint16 additional_spec_secidx[NSPEC_SEGMS] = { 0 }; - - // TLS support of the static access model (0 - no static model) - // TP - static thread pointer, TCB - thread control block - // variant 1 (if tls_tcb_size < 0): - // +---+---+----------------------- - // |TCB|xxx| - // +---+---+----------------------- - // ^ TP ^ TLS offset of modules - // variant 2 (if tls_tcb_size > 0): - // +----------------------+---+---+ - // | |xxx|TCB| - // +----------------------+---+---+ - // ^ TLS offset of modules ^ TP - int tls_tcb_size = 0; - int tls_tcb_align = 0; // if bit 0 set then store TP at the start of TCB - -#define AUTO_NO_CTOR 0x01 // disbale ctor/dtor renaming -#define AUTO_NO_DATA 0x02 // disable data coagulation -#define AUTO_NO_NAME 0x04 // disable Alternative name storing -#define AUTO_NO_THUNK 0x08 // disable plt-thunk renaming -// see set_reloc_cmt() for other bits -#define AUTO_NO_CTBL_MASK (AUTO_NO_DATA | AUTO_NO_CTOR) - ushort auto_mode = AUTO_NO_DATA; - ushort patch_mode = 0; - - proc_def_t(elf_loader_t &_ldr, reader_t &reader); - virtual ~proc_def_t() {} - - // the sequence of callbacks during the call of elf_load_file() - // proc_is_acceptable_image_type - // proc_on_start_data_loading - // proc_should_load_section* (for each section before load) - // proc_load_unknown_sec* (for each section with unknown type) - // proc_on_create_section* (for each section before defining segment) - // proc_handle_dynamic_tag* (for each dynamic tag) - // proc_describe_flag_bit* (for each flag from header.e_flags) - // proc_on_loading_symbols* (for each symbol table) - // proc_handle_special_symbol* (for each symbol from unknown section) - // proc_handle_symbol* (for each symbol) - // proc_handle_reloc* (for each relocation) - // proc_create_got_offsets* ( TODO ) - // proc_perform_patching* (up to 2 times, see above) - // proc_convert_pic_got* ( TODO ) - // proc_adjust_entry* (for init_ea, fini_ea, header.e_entry) - // proc_on_end_data_loading - - virtual bool proc_supports_relocs() const; - - // Relocator function. - // Note: symbol might be NULL - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools); - - // Force conversion of all GOT entries to offsets - virtual bool proc_create_got_offsets( - const elf_shdr_t *gotps, - reloc_tools_t *tools); - - // Patcher function - // There are 2 passes distinguishable by function argument gotps: - // 1. ELF_RPL_PTEST NULL - check ".plt" section - // 2. pass 2 gotplt - virtual bool proc_perform_patching( - const elf_shdr_t *plt, - const elf_shdr_t *gotps); - - // Convert PIC form of loading '_GLOBAL_OFFSET_TABLE_[]' of address - virtual bool proc_can_convert_pic_got() const; - virtual size_t proc_convert_pic_got( - const segment_t *gotps, - reloc_tools_t *tools); - - // Return a bit description from e_flags and remove it. - // This function may be called in a loop to document all bits. - virtual const char *proc_describe_flag_bit(uint32 *e_flags); - - // called for processor-specific section types - virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force); - - // called for each dynamic tag. It returns NULL to continue with a - // standard tag processing, or "" to finish tag processing, or the - // description of the tag to show. - virtual const char *proc_handle_dynamic_tag(const Elf64_Dyn *dyn); - - virtual bool proc_is_acceptable_image_type(ushort filetype); - - // called after header loading (before load_pht/load_simage) - virtual void proc_on_start_data_loading(elf_ehdr_t &header); - - // called after loading data from the input file - virtual bool proc_on_end_data_loading(); - - virtual void proc_on_loading_symbols(); - - virtual bool proc_handle_symbol(sym_rel &sym, const char *symname); - - // Handle a dynamic symbol - virtual void proc_handle_dynsym( - const sym_rel &symrel, - elf_sym_idx_t isym, - const char *symname); - - // 0-reaccept, 1-set name only, else: non-existing section - virtual int proc_handle_special_symbol( - sym_rel *st, - const char *name, - ushort type); - - // called from a function should_load_segment for _every_ section. - // It returns 'false' to skip loading of the given section. - virtual bool proc_should_load_section( - const elf_shdr_t &sh, - elf_shndx_t idx, - const qstring &name); - - // called before the segment creation. It may set <sa> to the ea at - // which a given section should be loaded. In the other case the - // default segment ea computation is used. Also it may return 'false' - // to skip creation of a segment for this section. - virtual bool proc_on_create_section( - const elf_shdr_t &sh, - const qstring &name, - ea_t *sa); - - virtual const char *calc_procname(uint32 *e_flags, const char *procname); - - // for some 64-bit architectures e_entry holds not a real entry point - // but a function descriptor - // E.g. 64-bit PowerPC ELF Application Binary Interface Supplement 1.9 - // section 4.1. ELF Header - // "The e_entry field in the ELF header holds the address of a function - // descriptor. This function descriptor supplies both the address of the - // function entry point and the initial value of the TOC pointer - // register." - // this callback should translate this address to the real entry. - virtual ea_t proc_adjust_entry(ea_t entry); - - // helper functions - bool in_relsyms(uint32 r_type) const - { - for ( int i=0; i < MAXRELSYMS; ++i ) - { - if ( relsyms[i] == 0 ) - break; - if ( relsyms[i] == r_type ) - return true; - } - return false; - } - - bool section_in_relsecord(const qstring &name) const - { - for ( int i = 0; i < MAXRELORDERS; ++i ) - { - if ( relsecord[i] == NULL ) - return false; - if ( name == relsecord[i] ) - return true; - } - return false; - } - - void set_reloc( - ea_t P, // The ea of the data to be modified. - ea_t target_ea, // The ea that the instruction would point to, - // if it were interpreted by the CPU. - uval_t patch_data, // The data to be inserted at 'P'. Depending on whether - // 'type' is a 64-bit fixup type or not, either the - // first 32-bits, or the full 64 bits of 'data' will be - // put in the database. Of course, this patch data - // must hold the possible instruction bits, if they - // are interleaved w/ the address data - // (e.g., R_ARM_THM_MOVW_ABS_NC, ...). - adiff_t displ, - fixup_type_t type, // The type of the relocation, see fixup.hpp's FIXUP_*. - // It may be standard or custom. - uval_t offbase = 0, // base of the relative fixup - uint32 flags = 0, // The flags of the relocation, see fixup.hpp's FIXUPF_*. - // You can specify additional flags: -#define FIXUPF_ELF_DO_NOT_PATCH 0x80000000 // do not patch at all -#define FIXUPF_ELF_FIXUP_PATCH 0x40000000 // do not use patch_data, patch - // using patch_fixup_value() -#define FIXUPF_ELF_DISPLACEMENT 0x20000000 // set displacement flag - // (even rel_mode == 1) -#define FIXUPF_ELF_SET_RELATIVE 0x10000000 // set fixup base - // (even offbase == 0) - adiff_t fixup_offset=0); // offset of the fixup relative to P - - // this function patches the relocatable field using patch_fixup_value() - // and store the fixup. - // It set the displacement taking in account the addend, the fact that - // the symbol is external or it is a section. - // It uses static variables `rel_mode' and `prgend'. - void set_reloc_fixup( - ea_t P, // ea of the reloc - ea_t S, // symbol of the reloc - adiff_t A, // addend of the reloc - fixup_type_t type, // type of the fixup to store (see set_reloc().type) - bool do_not_patch = false, // do not patch at all - uval_t offbase = 0, // base of the relative fixup - adiff_t fixup_offset = 0); // offset of the fixup relative to P - void process_TLS( - tls_relocs_t::type_t type, - tls_relocs_t::got_mode_t got_mode, - fixup_type_t fixup_type, - const char *cfh_name, - ea_t P, - ea_t S, - adiff_t A, - const sym_rel *symbol, - const elf_rela_t &reloc_info, - reloc_tools_t *tools); - // allocate GOT-entry and return it in GOT_ENTRY_EA - // \param P relocation address (to show in messages) - // \param S data to place in the entry - // \param symbol symbol of the entry, - // we allocate the single entry for the symbol, - // we create a label for the entry if the symbol has a name, - // if it is NULL we allocate the entry for the S address - bool process_GOT( - ea_t *got_ea, // may be NULL - ea_t *got_entry_ea, // not NULL - ea_t P, - ea_t S, - const sym_rel *symbol, - reloc_tools_t *tools); - - enum reloc_cmt_id_t - { - RCM_NONE = -1, - RCM_PIC = 0, - RCM_ATT = 1, - RCM_COPY = 2, - RCM_TLS = 3, - RCM_IREL = 4, - }; - void set_reloc_cmt(ea_t ea, reloc_cmt_id_t cmt) const; - void set_thunk_name( - ea_t ea, - ea_t name_ea, - const char *prefix = ".", - const char *postfix = ""); -}; - -//---------------------------------------------------------------------------- -struct arm_base_t : public proc_def_t -{ - bool already_parsed = false; - - arm_base_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; - virtual void proc_on_loading_symbols() override; - virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_arm_t : public arm_base_t -{ - fixup_type_t prel31_reltype = FIXUP_CUSTOM; - - elf_arm_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual bool proc_perform_patching( - const elf_shdr_t *plt, - const elf_shdr_t *gotps) override; - virtual bool proc_can_convert_pic_got() const override { return true; } - virtual size_t proc_convert_pic_got( - const segment_t *gotps, - reloc_tools_t *tools) override; - virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; - virtual bool proc_on_create_section( - const elf_shdr_t &sh, - const qstring &name, - ea_t *sa) override; - virtual ea_t proc_adjust_entry(ea_t entry) override; -}; - -//---------------------------------------------------------------------------- -struct elf_aarch64_t : public arm_base_t -{ - elf_aarch64_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual bool proc_perform_patching( - const elf_shdr_t *plt, - const elf_shdr_t *gotps) override; -#ifndef __EA64__ - virtual bool proc_supports_relocs() const override { return false; } -#endif -private: - bool aarch64_process_TLS( - int rel_type, - ea_t P, - ea_t S, - adiff_t A, - const sym_rel *symbol, - const elf_rela_t &reloc_info, - reloc_tools_t *tools); -}; - -//---------------------------------------------------------------------------- -struct elf_alpha_t : public proc_def_t -{ - const elf_shdr_t *sh_plt = nullptr; // for R_ALPHA_JMP_SLOT - - elf_alpha_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; - virtual bool proc_should_load_section( - const elf_shdr_t &sh, - elf_shndx_t idx, - const qstring &name) override; -}; - -//---------------------------------------------------------------------------- -struct elf_avr_t : public proc_def_t -{ - netnode avr_helper; - fixup_type_t avr16_reltype = FIXUP_CUSTOM; - - elf_avr_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -}; - -//-------------------------------------------------------------------------- -struct elf_c166_t : public proc_def_t -{ - elf_c166_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; -}; - -//---------------------------------------------------------------------------- -struct arc_base_t : public proc_def_t -{ - arc_base_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual void proc_handle_dynsym( - const sym_rel &symrel, - elf_sym_idx_t isym, - const char *symname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_arcompact_t : public arc_base_t -{ - elf_arcompact_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -}; - -//---------------------------------------------------------------------------- -struct elf_arc_t : public arc_base_t -{ - elf_arc_t(elf_loader_t &l, reader_t &r) : arc_base_t(l, r) {} - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -}; - -//---------------------------------------------------------------------------- -struct elf_h8_t : public proc_def_t -{ - elf_h8_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_fr_t : public proc_def_t -{ - elf_fr_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -}; - -//---------------------------------------------------------------------------- -struct elf_i960_t : public proc_def_t -{ - elf_i960_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -}; - -//---------------------------------------------------------------------------- -struct elf_ia64_t : public proc_def_t -{ - elf_ia64_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; -}; - -//---------------------------------------------------------------------------- -struct elf_hppa_t : public proc_def_t -{ - fixup_type_t l21_reltype = FIXUP_CUSTOM; - fixup_type_t r11_reltype = FIXUP_CUSTOM; - - elf_hppa_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; -}; - -//---------------------------------------------------------------------------- -struct ppc_base_t : public proc_def_t -{ - fixup_type_t ha16_reltype = FIXUP_CUSTOM; - - // PLT support - enum plt_type_t - { - PLT_UNKNOWN, - PLT_SKIP, // illegal .plt section - PLT_BSS, // PLT entry contains executable code - PLT_SECURE, // PLT entry contains address - PLT_FARCALL, // PLT_BSS + should add .plt_farcall - PLT_64, // PLT entry contains function description - PLT_64V2, // PLT entry contains global entry point - }; - plt_type_t plt_type = PLT_UNKNOWN; - ea_t plt_start = BADADDR; - asize_t plt_size = 0; - bool is_dt_ppc_got_present = false; - - ppc_base_t(elf_loader_t &ldr, reader_t &reader); - virtual bool proc_should_load_section( - const elf_shdr_t &sh, - elf_shndx_t idx, - const qstring &name) override; -protected: - const char *process_JMP_SLOT(const sym_rel *symbol, ea_t P, ea_t target_ea); - int32 calc_plt_entry(adiff_t off) const; - asize_t calc_plt_size(uint32 n) const; -}; - -//---------------------------------------------------------------------------- -struct elf_ppc_t : public ppc_base_t -{ - elf_ppc_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_perform_patching( - const elf_shdr_t *plt, - const elf_shdr_t *gotps) override; - virtual const char *proc_handle_dynamic_tag(const Elf64_Dyn *dyn) override; - virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; - virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; -public: - const char *process_EMB_SDA21(ea_t P, ea_t target_ea, uint32 insn); - const char *process_GOT( - uchar type, - ea_t P, - ea_t S, - const sym_rel *symbol, - reloc_tools_t *tools, - reloc_cmt_id_t got_entry_cmt = RCM_NONE); -}; - -//---------------------------------------------------------------------------- -struct elf_ppc64_t : public ppc_base_t -{ - // how did we define the `toc_base_ea`? - // Doc: "To support position-independent code, a Global Offset Table (GOT) - // shall be constructed by the link editor in the data segment when linking - // code that contains any of the various R_PPC64_GOT* relocations or when - // linking code that references the **.TOC.** address. The GOT consists of - // an 8-byte header that contains **the TOC base** (the first TOC base when - // multiple TOCs are present), followed by an array of 8-byte addresses." - enum toc_type_t - { - TOC_UNK, - // For the relocatable object file: - TOC_CREATED, // it points to the created .tocstart section - // For the executable or shared object file: - TOC_SECTION, // it points to the first TOC's section - TOC_GOT, // we got it as the first GOT entry - TOC_SYMBOL, // it points to the .TOC. symbol - }; - toc_type_t toc_type = TOC_UNK; - - symrel_idx_t toc_sym_idx; // index of the .TOC. symbol - - // the TOC base - // We prepare this address for a relocatable object file because for an - // executable or shared object the linker already defines and uses such - // a symbol. Doc: "relocation types that refer to .TOC. may only appear - // in relocatable object files, not in executables or shared objects". - // For an executable or shared object we get this address in the same way - // but we overwrite it using the .TOC. symbol or the first GOT entry. - ea_t toc_base_ea = BADADDR; - - // offset of the TOC base from the TOC start - adiff_t toc_base_offset = 0x8000; - - bool got_already_checked = false; - - elf_ppc64_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_on_end_data_loading() override; - virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; - virtual bool proc_on_create_section( - const elf_shdr_t &sh, - const qstring &name, - ea_t *sa) override; - virtual ea_t proc_adjust_entry(ea_t entry) override; -private: - const char *process_TOC16( - uchar type, - ea_t P, - ea_t S, - adiff_t A); - void set_offset_to_toc(ea_t ea) const; - void improve_toc_using_got(); -}; - -//-------------------------------------------------------------------------- -struct pc_base_t : public proc_def_t -{ - bool plt_warned = false; - pc_base_t(elf_loader_t &ldr, reader_t &reader); - bool patch_jmp_slot_target( - const reloc_tools_t *reloc_tools, - bool is_64, - ea_t fixup_ea, - ea_t final_ea); - bool patch_irelative_target( - bool is_64, - ea_t fixup_ea, - ea_t final_ea, - const reloc_tools_t *reloc_tools); -}; - -//-------------------------------------------------------------------------- -struct elf_pc_t : public pc_base_t -{ - elf_pc_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -private: - bool convert_got32x( - ea_t P, - ea_t S, - reloc_tools_t *tools); - bool convert_call_jmp(ea_t P, ea_t S); - bool convert_mov_mem_to_imm(ea_t P, ea_t S); - bool convert_test(ea_t P, ea_t S); - bool convert_binop(ea_t P, ea_t S, uchar opcode); - bool convert_mov_to_lea(ea_t P, ea_t S, reloc_tools_t *tools); - bool patch_glob_dat_target( - ea_t fixup_ea, - ea_t final_ea, - const reloc_tools_t *tools); - bool intel_process_TLS( - int rel_type, - ea_t P, - ea_t S, - adiff_t A, - const sym_rel *symbol, - const elf_rela_t &reloc_info, - reloc_tools_t *tools); -}; - -//---------------------------------------------------------------------------- -struct elf_m16c_t : public proc_def_t -{ - elf_m16c_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_on_create_section( - const elf_shdr_t &sh, - const qstring &name, - ea_t *sa) override; - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_m32r_t : public proc_def_t -{ - elf_m32r_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_mc12_t : public proc_def_t -{ - elf_mc12_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -}; - -//---------------------------------------------------------------------------- -struct elf_mc68k_t : public proc_def_t -{ - elf_mc68k_t(elf_loader_t &ldr, reader_t &reader); - virtual bool proc_supports_relocs() const override { return false; } - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -}; - -//---------------------------------------------------------------------------- -struct elf_s390_t : public proc_def_t -{ - fixup_type_t pc16_reltype = FIXUP_CUSTOM; - fixup_type_t pc32_reltype = FIXUP_CUSTOM; - fixup_type_t lo12_reltype = FIXUP_CUSTOM; - fixup_type_t lo20_reltype = FIXUP_CUSTOM; - - elf_s390_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual bool proc_on_end_data_loading() override; -private: - bool s390_process_TLS( - int rel_type, - ea_t P, - ea_t S, - adiff_t A, - const sym_rel *symbol, - const elf_rela_t &reloc_info, - reloc_tools_t *tools); - bool handle_plt1_64(ea_t ea); -}; - -//---------------------------------------------------------------------------- -struct elf_mips_t : public proc_def_t -{ - fixup_type_t ha16_reltype = FIXUP_CUSTOM; - - ea_t save_rsolve = BADADDR; - bool isPS2IRX = false; - bool isPSP = false; - bool use_relocs = true; - // The g_localgotno node will be used twice: - // 1) When processing SHT_DYNSYM syms, to associate a symbol with a .got slot - // 2) After processing symbols, during the 'patch' phase, to create - // all relocs in all "local" .got entries at the beginning of the .got. - int g_localgotno = 0; - elf_sym_idx_t g_gotsym = 0; - // offset of the gp value from the GOT start - const adiff_t gpval_offset = 0x7FF0; - // The "_gp_disp" is a magic symbol designates offset between start of - // function and gp pointer into GOT. Only "R_MIPS_HI16" and "R_MIPS_LO16" - // relocations are permitted with "_gp_disp". - // The special symbol name _gp_disp, used for relocating the calculation of gp - // on entry to a DSO in 32-bit files, is not supported in ELF-64 or in the new - // 32-bit ABI. Instead, these relocations should be composed with R_MIPS_GPREL - // applied to an explicit symbol for the entry point of the subprogram. See the - // examples below. - struct gp_disp_reloc_t - { - ea_t P; // address of R_MIPS_HI16 or R_MIPS_LO16 if orpahend - uint32 AHL; // another type of addend - bool orphaned; // orphaned R_MIPS_LO16 - }; - qvector<gp_disp_reloc_t> gp_disp_relocs; - // initial value of GP (GP0) - // for executable and shared objects it is the actual gp value - // for relocatable objects it is the offset of the gp value from the global area start - ea_t initial_gp = BADADDR; - // start of the global data area. this area should be addressable using $gp. - ea_t global_data_ea = BADADDR; - - ea_t last_hi16_ea = BADADDR; - adiff_t last_hi16_addend = 0; - uchar last_hi16_rel_type = 0; - bool last_hi16_done = false; - - bool got_inited = false; - - elf_mips_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual bool proc_create_got_offsets( - const elf_shdr_t *gotps, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; - virtual int proc_handle_special_symbol( - sym_rel *st, - const char *name, - ushort type) override; - virtual const char *proc_handle_dynamic_tag(const Elf64_Dyn *dyn) override; - virtual bool proc_is_acceptable_image_type(ushort filetype) override; - virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; - virtual bool proc_on_end_data_loading() override; - virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; - virtual void proc_handle_dynsym( - const sym_rel &symrel, - elf_sym_idx_t isym, - const char *symname) override; - virtual bool proc_on_create_section( - const elf_shdr_t &sh, - const qstring &name, - ea_t *sa) override; - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; -private: - void relocate_psp_section1( - off_t file_offset, - size_t sec_size, - const sym_rel *symbol); - void set_initial_gp(uint64 offset, bool options=true); - ea_t get_final_gp(reloc_tools_t *tools); - void verify_got_displ(ea_t P, ea_t got_entry_ea, ea_t got_ea) const; - fixup_type_t get_ha16_reltype(); - void process_ahl_reloc( - uchar rel_type, - ea_t P, - ea_t S, - bool gnu_local_gp, - bool is_rela, - adiff_t A, // only if IS_RELA - uint32 insn, // only if !IS_RELA - reloc_tools_t *tools); - void collect_gp_disp_reloc(ea_t P, uint32 insn, bool is_hi16); - bool get_ssym_ea(ea_t *ssym_ea, uint8 ssym, ea_t P) const; - void relocate_gp_disp(); - bool is_inside_got(reloc_tools_t *tools, ea_t P); -}; - -//---------------------------------------------------------------------------- -struct elf_v800_t : public proc_def_t -{ - elf_v800_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -}; - -//---------------------------------------------------------------------------- -struct elf_v850_t : public proc_def_t -{ - elf_v850_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_sparc_t : public proc_def_t -{ - fixup_type_t hi22_reltype = FIXUP_CUSTOM; - fixup_type_t lo10_reltype = FIXUP_CUSTOM; - - elf_sparc_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; - virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; - virtual bool proc_can_convert_pic_got() const override { return true; } - virtual size_t proc_convert_pic_got( - const segment_t *gotps, - reloc_tools_t *tools) override; - - fixup_type_t get_hi22_reltype(); - fixup_type_t get_lo10_reltype(); -}; - -//---------------------------------------------------------------------------- -struct elf_mn10200_t : public proc_def_t -{ - elf_mn10200_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -}; - -//---------------------------------------------------------------------------- -struct elf_mn10300_t : public proc_def_t -{ - elf_mn10300_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -}; - -//---------------------------------------------------------------------------- -struct elf_sh_t : public proc_def_t -{ - elf_sh_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; - virtual void proc_handle_dynsym( - const sym_rel &symrel, - elf_sym_idx_t isym, - const char *symname) override; -}; - -//---------------------------------------------------------------------------- -struct elf_st9_t : public proc_def_t -{ - elf_st9_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -}; - -//---------------------------------------------------------------------------- -struct elf_x64_t : public pc_base_t -{ - // TODO use this custom fixup in RIP-based relocs - fixup_type_t rip_reltype = FIXUP_CUSTOM; - - elf_x64_t(elf_loader_t &ldr, reader_t &reader); - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; -private: - bool convert_gotpcrelx(int rel_type, ea_t P, ea_t S); - bool x64_process_TLS( - int rel_type, - ea_t P, - ea_t S, - adiff_t A, - const sym_rel *symbol, - const elf_rela_t &reloc_info, - reloc_tools_t *tools); - bool convert_call_jmp(ea_t P, ea_t S); - bool convert_mov_to_lea(ea_t P, ea_t S); - bool convert_mov_mem_to_imm(int rel_type, ea_t P, ea_t S); - bool convert_test_binop(int rel_type, ea_t P, ea_t S, uchar opcode); -}; - -//---------------------------------------------------------------------------- -struct elf_tricore_t : public proc_def_t -{ - fixup_type_t ha16_reltype = FIXUP_CUSTOM; - - elf_tricore_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} - virtual const char *proc_handle_reloc( - const rel_data_t &rel_data, - const sym_rel *symbol, - const elf_rela_t *reloc, - reloc_tools_t *tools) override; - virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; -private: - void make_reloc( - const rel_data_t &rel_data, - ea_t target_ea, - uval_t patch_data, - fixup_type_t type, - bool nodispl = false); - void tricore_handle_reloc(const rel_data_t &rel_data, ea_t target_ea); - void tricore_reloc_relB(const rel_data_t &rel_data, ea_t target_ea); - void tricore_reloc_absB(const rel_data_t &rel_data, ea_t target_ea); - void tricore_reloc_abs(const rel_data_t &rel_data, ea_t target_ea); - void tricore_reloc_br(const rel_data_t &rel_data, ea_t target_ea); - void tricore_reloc_rlc( - const rel_data_t &rel_data, - uint32 patch_data, - fixup_type_t fixup_type); - void tricore_reloc_bol( - const rel_data_t &rel_data, - uint32 patch_data, - fixup_type_t fixup_type); -}; - -//---------------------------------------------------------------------------- -struct sym_rel; -class symrel_cache_t -{ -public: - - symrel_cache_t() - : storage(), - dynsym_index(0) {} - - static void check_type(slice_type_t t) - { - QASSERT(20098, t > SLT_INVALID && t <= SLT_WHOLE); - } - - elf_sym_idx_t slice_size(slice_type_t t) const { return elf_sym_idx_t(slice_end(t) - slice_start(t)); } - const sym_rel &get(slice_type_t t, elf_sym_idx_t idx) const { return storage[slice_start(t) + idx]; } - sym_rel &get(slice_type_t t, elf_sym_idx_t idx) { return storage[slice_start(t) + idx]; } - sym_rel &append(slice_type_t t); - - void qclear(uint64 room) - { - // the number in the section header may be too big (see - // pc_bad_nyms_elf.elf) so we limit it - if ( room > 65536 ) - room = 65536; - storage.qclear(); - storage.reserve(room); - } - - symrel_idx_t get_idx(const sym_rel *symbol) const; - - // this method is used in pattern/pelf.cpp - struct ptr_t : public symrel_idx_t - { - ptr_t() : symrel_idx_t(), symbols(NULL) {} - ptr_t(symrel_cache_t *s, symrel_idx_t i) - : symrel_idx_t(i), - symbols(s) {} - symrel_cache_t *symbols; - sym_rel &deref() const { return symbols->get(type, idx); } - }; - ptr_t get_ptr(const sym_rel &sym) - { - return ptr_t(this, get_idx(&sym)); - } - -private: - qvector<sym_rel> storage; - size_t dynsym_index; - size_t slice_start(slice_type_t t) const; - size_t slice_end(slice_type_t t) const; -}; - -//-------------------------------------------------------------------------- -// relocation speed -struct sym_rel -{ - mutable qstring original_name; - qstring name; // temporary for NOTYPE only - elf_sym_t original; - uint64 size; - uval_t value; // absolute value or addr - elf_shndx_t sec; // index of the section to which this symbol - // applies. For special sections it is 0 (see - // original.st_shndx). - uchar bind; // binding - char type; // type (-1 - not defined, - // -2 UNDEF SYMTAB symbol which probably is - // the same as the DYNSYM symbol, - // -3 to add an additional comment to relocs to - // unloaded symbols) - uchar flags; - - sym_rel() - : original(), - size(0), - value(0), - sec(0), - bind(0), - type(0), - flags(0) {} - - sym_rel(const sym_rel &r) - { - original_name = r.original_name; - name = r.name; - original = r.original; - size = r.size; - value = r.value; - sec = r.sec; - bind = r.bind; - type = r.type; - flags = r.flags; - } - - sym_rel &operator=(const sym_rel &r) - { - if ( this == &r ) - return *this; - this->~sym_rel(); - new (this) sym_rel(r); - return *this; - } - - void swap(sym_rel &r) - { - qswap(*this, r); - } - - void set_section_index(const reader_t &reader); - bool defined_in_special_section() const - { - CASSERT(SHN_HIRESERVE == 0xFFFF); - // assert: original.st_shndx <= SHN_HIRESERVE - return sec == 0 && original.st_shndx >= SHN_LORESERVE; - } - // for debug purpose - const char *get_section_str(char *buf, size_t bufsize) const - { - if ( defined_in_special_section() ) - qsnprintf(buf, bufsize, "%04X", uint(original.st_shndx)); - else - qsnprintf(buf, bufsize, "%u", sec); - return buf; - } - - bool overlaps(elf_shndx_t section_index, uint64 offset) const - { - return sec == section_index - && offset >= value - && offset < value + size; - } - - void set_name(const qstring &n) - { - set_name(n.c_str()); - } - - void set_name(const char *n) - { - name.qclear(); - if ( n != NULL && n[0] != '\0' ) - name = n; - } - - ea_t get_ea(const reader_t &reader, ea_t _debug_segbase=0) const; - - const qstring &get_original_name(const reader_t &reader) const; - - void set_flag(uchar flag) { flags |= flag; } - bool has_flag(uchar flag) const { return (flags & flag) != 0; } - void clr_flag(uchar flag) { flags &= ~flag; } -}; -DECLARE_TYPE_AS_MOVABLE(sym_rel); - -//-------------------------------------------------------------------------- -inline symrel_idx_t symrel_cache_t::get_idx(const sym_rel *symbol) const -{ - qvector<sym_rel>::const_iterator beg = storage.begin(); - if ( symbol == NULL || symbol < beg || symbol > storage.end() ) - return symrel_idx_t(); - size_t idx = symbol - beg; - if ( idx < dynsym_index ) - return symrel_idx_t(SLT_SYMTAB, elf_sym_idx_t(idx)); - else - return symrel_idx_t(SLT_DYNSYM, elf_sym_idx_t(idx - dynsym_index)); -} - -void overflow(ea_t fixaddr, ea_t ea); -void std_handle_dynsym(const sym_rel &symrel, elf_sym_idx_t, const char *symname); - -#define CASE_NAME(n) case n: return # n -const char *get_reloc_name(const reader_t &reader, int type); - -void parse_attributes(reader_t &reader, uint32 offset, size_t size); -int elf_machine_2_proc_module_id(reader_t &reader); - -//-------------------------------------------------------------------------- -// user parameters. these definitions and the input form are interdependent -// if you change the 'dialog_form' string, change these definitions too! -// (and don't forget to update the environment variables in the hints files) - -// IDA_ELF_LOAD_OPTS (may be set by environment variable) -#define ELF_USE_PHT 0x0001 // Use PHT if available -#define ELF_USE_SHT 0x0002 // Use SHT if available -#define ELF_LD_CHNK 0x0004 // Load huge segments by chunks - -// IDA_ELF_PATCH_MODE (may be set by environment variable) -#define ELF_RPL_PLP 0x0001 // Replace PIC form of 'Procedure Linkage Table' to non PIC form -#define ELF_RPL_PLD 0x0002 // Direct jumping from PLT (without GOT) irrespective of its form -#define ELF_RPL_GL 0x0004 // Convert PIC form of loading '_GLOBAL_OFFSET_TABLE_[]' of address -#define ELF_RPL_GOTX 0x0010 // Convert PIC form of name@GOT -#define ELF_AT_LIB 0x0020 // Mark 'allocated' objects as library-objects (MIPS only) -#define ELF_BUG_GOT 0x0040 // Force conversion of all GOT entries to offsets -#define ELF_FORM_MASK 0x0FFF // Mask for 'dialog_form' options - -// noform bits -#define ELF_DIS_GPLT 0x4000 // disable search got reference in plt -#define ELF_DIS_OFFW 0x8000 // can present offset bypass segment's - -#define ELF_RPL_PTEST (ELF_RPL_PLP | ELF_RPL_PLD) - -#define FLAGS_CMT(bit, text) if ( *e_flags & bit ) \ - { \ - *e_flags &= ~bit; \ - return text; \ - } - -//-------------------------------------------------------------------------- -inline uval_t make64(uval_t oldval, uval_t newval, uval_t mask) -{ - return (oldval & ~mask) | (newval & mask); -} - -//-------------------------------------------------------------------------- -inline uint32 make32(uint32 oldval, uint32 newval, uint32 mask) -{ - return (oldval & ~mask) | (newval & mask); -} - -#define MASK(x) ((uval_t(1) << x) - 1) - -const uval_t M32 = uint32(-1); -const uval_t M24 = MASK(24); -const uval_t M16 = MASK(16); -const uval_t M8 = MASK(8); - -inline uval_t extend_sign(uval_t value, uint bits) -{ - uval_t mask = make_mask<uval_t>(bits); - return (value & left_shift<uval_t>(1, bits-1)) != 0 - ? value | ~mask - : value & mask; -} - -#undef MASK - -#pragma pack(pop) - -//---------------------------------------------------------------------------- -struct dynamic_linking_tables_t -{ - dynamic_linking_tables_t() - : offset(0), - addr(0), - size(0), - link(0) {} - - dynamic_linking_tables_t(size_t _o, ea_t _a, size_t _s, elf_shndx_t _l) - : offset(_o), - addr(_a), - size(_s), - link(_l) {} - - bool is_valid() const { return offset != 0; } - - size_t offset; - ea_t addr; - size_t size; - elf_shndx_t link; -}; - -//---------------------------------------------------------------------------- -class dynamic_linking_tables_provider_t -{ -public: - dynamic_linking_tables_provider_t() - : dlt() {} - const dynamic_linking_tables_t &get_dynamic_linking_tables_info() const { return dlt; } - bool has_valid_dynamic_linking_tables_info() const { return dlt.is_valid(); } - void set_dynlink_table_info(size_t offset, ea_t addr, size_t size, int link) - { - dlt = dynamic_linking_tables_t(offset, addr, size, link); - } - -private: - dynamic_linking_tables_t dlt; -}; - -//---------------------------------------------------------------------------- -enum dynamic_info_type_t -{ - DIT_STRTAB, - DIT_SYMTAB, - DIT_REL, - DIT_RELA, - DIT_ANDROID_REL, - DIT_ANDROID_RELA, - DIT_PLT, - DIT_HASH, - DIT_GNU_HASH, - DIT_PREINIT_ARRAY, - DIT_INIT_ARRAY, - DIT_FINI_ARRAY, - DIT_VERDEF, - DIT_VERNEED, - DIT_VERSYM, - DIT_TYPE_COUNT, // number of dyninfo types -}; - -//---------------------------------------------------------------------------- -// various information parsed from the .dynamic section or DYNAMIC segment -struct dynamic_info_t -{ - dynamic_info_t() - { - memset(this, 0, sizeof(dynamic_info_t)); - } - - void initialize(const reader_t &reader); - - struct entry_t - { - entry_t() { clear(); } - bool is_valid() const { return offset > 0 && size != 0; } - int64 offset; - uint64 addr; - uint64 size; - uint16 entsize; - uint32 info; - - void clear() - { - offset = 0; - addr = 0; - size = 0; - entsize = 0; - info = 0; - } - - void guess_size(const sizevec_t &offsets) - { - size = BADADDR; - for ( int i = 0; i < offsets.size(); i++ ) - { - size_t off = offsets[i]; - if ( offset != 0 && off > offset ) - size = qmin(size, off - offset); - } - if ( size == BADADDR ) - size = 0; - } - } entries[DIT_TYPE_COUNT]; - - entry_t &strtab() { return entries[DIT_STRTAB]; } - entry_t &symtab() { return entries[DIT_SYMTAB]; } - const entry_t &strtab() const { return entries[DIT_STRTAB]; } - const entry_t &symtab() const { return entries[DIT_SYMTAB]; } - entry_t &rel() { return entries[DIT_REL]; } - entry_t &rela() { return entries[DIT_RELA]; } - entry_t &plt() { return entries[DIT_PLT]; } - entry_t &hash() { return entries[DIT_HASH]; } - entry_t &gnu_hash() { return entries[DIT_GNU_HASH]; } - entry_t &preinit_array() { return entries[DIT_PREINIT_ARRAY]; } - entry_t &init_array() { return entries[DIT_INIT_ARRAY]; } - entry_t &fini_array() { return entries[DIT_FINI_ARRAY]; } - entry_t &verdef() { return entries[DIT_VERDEF]; } - entry_t &verneed() { return entries[DIT_VERNEED]; } - entry_t &versym() { return entries[DIT_VERSYM]; } - - const entry_t &rel() const { return entries[DIT_REL]; } - const entry_t &rela() const { return entries[DIT_RELA]; } - const entry_t &plt() const { return entries[DIT_PLT]; } - - uint32 plt_rel_type; // type of entries in the PLT relocation table (DT_RELENT) - - static qstring d_un_str(const reader_t &reader, int64 d_tag, int64 d_un); - static const char *d_tag_str(const reader_t &reader, int64 d_tag); // may return null - static qstring d_tag_str_ext(const reader_t &reader, int64 d_tag); - - // Fill a "fake" header, typically to be used w/ - // a buffered_input_t. - bool fill_section_header(elf_shdr_t *sh, dynamic_info_type_t type) const; -}; - -//---------------------------------------------------------------------------- -// Well-known sections -enum wks_t -{ - WKS_BSS = 1, - WKS_BORLANDCOMMENT, - WKS_COMMENT, - WKS_DATA, - WKS_DYNAMIC, - WKS_DYNSYM, - WKS_GOT, - WKS_GOTPLT, - WKS_HASH, - WKS_INTERP, - WKS_NOTE, - WKS_PLT, - WKS_RODATA, - WKS_SYMTAB, - WKS_TEXT, - WKS_OPD, - WKS_SYMTAB_SHNDX, - WKS_DYNSYM_SHNDX, - WKS_PLTGOT, - WKS_VERDEF, - WKS_VERNEED, - WKS_VERSYM, - WKS_PLTSEC, - WKS_LAST -}; - -class section_headers_t : public dynamic_linking_tables_provider_t -{ - elf_shdrs_t headers; - uint32 wks_lut[WKS_LAST]; - reader_t *reader; - bool initialized; - bool got_is_original; // Was .got section present in the input file? - dynamic_info_t::entry_t strtab; - - friend class reader_t; - - section_headers_t(reader_t *_r) - : reader(_r), initialized(false), got_is_original(false), strtab() - { - memset(wks_lut, 0, sizeof(wks_lut)); - } - void assert_initialized() const - { - QASSERT(20099, initialized); - } -public: - bool is_initialized() const { return initialized; } - const elf_shdr_t *getn(elf_shndx_t index) const; - const elf_shdr_t *get_wks(wks_t wks) const - { - elf_shndx_t index = get_index(wks); - return index == 0 ? NULL : getn(index); - } - const elf_shdr_t *get(uint32 sh_type, const char *name) const; - -#define CONST_THIS CONST_CAST(const section_headers_t*)(this) -#define NCONST_SHDR(x) CONST_CAST(elf_shdr_t *)(x) - elf_shdr_t *getn(elf_shndx_t index) { return NCONST_SHDR(CONST_THIS->getn(index)); } - elf_shdr_t *get_wks(wks_t wks) { return NCONST_SHDR(CONST_THIS->get_wks(wks)); } - elf_shdr_t *get(uint32 sh_type, const char *name) { return NCONST_SHDR(CONST_THIS->get(sh_type, name)); } -#undef CONST_THIS -#undef NCONST_SHDR - - // Look for '.rel.<section_name>', or '.rela.<section_name>'. - const elf_shdr_t *get_rel_for(elf_shndx_t index, bool *is_rela = NULL) const; - elf_shndx_t get_index(wks_t wks) const; - void set_index(wks_t wks, elf_shndx_t index); - int add(const elf_shdr_t &); - void clear() // FIXME: This shouldn't be part of the public API - { - headers.clear(); - memset(wks_lut, 0, sizeof(wks_lut)); - } - bool empty() const { return headers.empty(); } - void resize(size_t size) { headers.resize(size); } // FIXME: This shouldn't be part of the public API - bool get_name(qstring *out, elf_shndx_t index) const; - bool get_name(qstring *out, const elf_shdr_t*) const; - bool get_name(qstring *out, const elf_shdr_t &sh) const { return get_name(out, &sh); } - elf_shdrs_t::const_iterator begin() const { return headers.begin(); } - elf_shdrs_t::const_iterator end () const { return headers.end(); } - elf_shdrs_t::iterator begin() { return headers.begin(); } - elf_shdrs_t::iterator end () { return headers.end(); } - size_t size() { return headers.size(); } - - const char *sh_type_str(uint32 sh_type) const; // may return null - qstring sh_type_qstr(uint32 sh_type) const; - - bool is_got_original(void) const { return got_is_original; } - void set_got_original(void) { got_is_original = true; } - - // Get the size of the section. That is, the minimum between - // what is advertized (sh_size) and the number of bytes between - // this, and the next section. - uint64 get_size_in_file(const elf_shdr_t &sh) const; - - // Read the section contents into the 'out' byte vector. - // This doesn't blindly rely on sh.sh_size, but will use - // get_size_in_file() instead. - // Also, the position of the linput_t will be preserved. - void read_file_contents(bytevec_t *out, const elf_shdr_t &sh) const; - - bool read_gnu_debuglink(qstring *out_link, uint32 *out_crc) const; -}; - -//---------------------------------------------------------------------------- -class program_headers_t : public dynamic_linking_tables_provider_t -{ - elf_phdrs_t pheaders; - ea_t image_base; - reader_t *reader; - bool initialized; -public: - program_headers_t(reader_t *_r) - : image_base(BADADDR), reader(_r), initialized(false) - { - } - elf_phdrs_t::const_iterator begin() const { return pheaders.begin(); } - elf_phdrs_t::const_iterator end () const { return pheaders.end(); } - elf_phdrs_t::iterator begin() { return pheaders.begin(); } - elf_phdrs_t::iterator end () { return pheaders.end(); } - elf_phdr_t *get(uint32 index) { assert_initialized(); return &pheaders[index]; } - ea_t get_image_base() const { return image_base; } - void set_image_base(ea_t ea) { image_base = ea; } - inline size_t size() const { return pheaders.size(); } - void resize(size_t sz) { pheaders.resize(sz); } // FIXME: This shouldn't be part of the pu - const char *p_type_str(uint32 p_type) const; // may return null - qstring p_type_qstr(uint32 p_type) const; - - // Get the size of the segment. That is, the minimum between - // what is advertized (p_filesz) and the number of bytes between - // this, and the next segment. - uint64 get_size_in_file(const elf_phdr_t &p) const; - - // Read the segment contents into the 'out' byte vector. - // This doesn't blindly rely on p.p_size, but will use - // get_size_in_file() instead. - // Also, the position of the linput_t will be preserved. - void read_file_contents(bytevec_t *out, const elf_phdr_t &p) const; - -private: - friend class reader_t; - void assert_initialized() const { QASSERT(20100, initialized); } -}; - -//---------------------------------------------------------------------------- -// Note Section -// Sections of type SHT_NOTE and program header elements of type PT_NOTE - -// entry -struct elf_note_t -{ - qstring name; // entry owner or originator - qstring desc; // descriptor - uint32 type; // interpretation of descriptor - - // fill entry and return new start offset - static bool unpack(elf_note_t *entry, uint32 *start, const bytevec_t &buf, bool mf); - -private: - static bool unpack_sz(uint32 *r, uint32 *start, const bytevec_t &buf, bool mf); - static bool unpack_strz(qstring *out, const bytevec_t &buf, uint32 start, uint32 len); - static bool unpack_mem(qstring *out, const bytevec_t &buf, uint32 start, uint32 len, bool as_strz=false); -}; -typedef qvector<elf_note_t> elf_notes_t; - -// entry originators and types -#define NT_NAME_GNU "GNU" -#define NT_GNU_BUILD_ID 3 - -class notes_t -{ -public: - notes_t(reader_t *_r) : reader(_r), initialized(false) - {} - - elf_notes_t::const_iterator begin() const { return notes.begin(); } - elf_notes_t::const_iterator end () const { return notes.end(); } - void clear(void) { notes.clear(); } - void add(const bytevec_t &buf); - - // convenience functions - - // Build ID - bool get_build_id(qstring *out) const; - -private: - reader_t *reader; - elf_notes_t notes; - bool initialized; - - friend class reader_t; - void assert_initialized() const { QASSERT(20082, initialized); } -}; - -const char *d_note_gnu_type_str(uint64 type); -const char *d_note_linux_type_str(uint64 type); -const char *d_note_core_type_str(uint64 type); - -//---------------------------------------------------------------------------- -class arch_specific_t -{ -public: - virtual ~arch_specific_t() {} - virtual void on_start_symbols(reader_t &/*reader*/) {} - virtual void on_symbol_read(reader_t &/*reader*/, sym_rel &/*sym*/) {} -}; - -//---------------------------------------------------------------------------- -//-V:reader_t:730 Not all members of a class are initialized inside the constructor -class reader_t -{ -public: - // Type definitions - // DOCME - enum unhandled_section_handling_t - { - ush_none = 0, - ush_load, - ush_skip - }; - - /* - * The list of notifications to which the user of the reader - * can react. - * It is documented as follows: - * 1) a short description of the notification, and possibly a hint - * on how it should be considered/treated. - * 2) the list of arguments, to be consumed in a vararg fashion. - */ - enum errcode_t - { - /* - * The "class" of the ELF module is not properly defined. It - * should really be one of (ELFCLASS32, ELFCLASS64). - * We will fallback to the ELFCLASS32 class. - * - uint8: the ELF class, as defined in the file. - */ - BAD_CLASS = 1, - - /* - * The size of the ELF header conflicts with what was expected. - * - uint16: the size of the ELF header, as defined in the file - * (i.e., eh_ehsize) - * - uint16: the expected size. - */ - BAD_EHSIZE, - - /* - * The byte ordering is not properly defineed. It should - * really be one of (ELFDATA2LSB, ELFDATA2MSB). - * We will fallback to the ELFDATA2LSB ordering. - * - uint8: the byte ordering, as defined in the file. - */ - BAD_ENDIANNESS, - - /* - * The ELF module defines there are Program Header entries, - * but it defines an entry size to be of an odd size. - * We will fallback to the default size for program header - * entries, which depends on the "class" of this ELF module. - * - uint16: the size of a program header entry, as defined in - * the file. - * - uint16: the expected size (to which we will fallback). - */ - BAD_PHENTSIZE, - - /* - * The ELF module either: - * 1) defines an offset for the Program Header entries data but a - * count of 0 entries, or - * 2) defines no offset for the Program Header entries data but a - * count of 1+ entries. - * We will not use the program header table. - * - uint16: the number of entries, as defined in the file. - * - uint64: the offset for the entries data. - */ - BAD_PHLOC, - - /* - * The ELF module defines there are Section Header entries, - * but it defines an entry size to be of an odd size. - * We will fallback to the default size for section header - * entries, which depends on the "class" of this ELF module. - * - uint16: the size of a section header entry, as defined in - * the file. - * - uint16: the expected size (to which we will fallback). - */ - BAD_SHENTSIZE, - - /* - * The ELF module: - * 1) defines an offset for the Section Header entries data but a - * count of 0 entries, or - * 2) defines no offset for the Section Header entries data but a - * count of 1+ entries, or - * 3) defines too many entries, which would cause an EOF to occur - * while reading those. - * We will not use the section header table. - * - uint32: the number of entries, as defined in the file. - * - uint64: the offset for the entries data. - * - int64 : the size of the file. - */ - BAD_SHLOC, - - /* - * The reader has encountered an unhandled section. - * - uint16 : The index of the section header. - * - Elf64_Shdr*: A pointer to the section header structure. - * If handled, this notification should return a - * "unhandled_section_handling_t", specifying how the - * reader should proceed with it. - */ - UNHANDLED_SECHDR, - - /* - * The reader has encountered an unhandled section, - * which even the reader instance user couldn't handle. - * - uint16 : The index of the section header. - * - Elf64_Shdr*: A pointer to the section header structure. - */ - UNKNOWN_SECHDR, - - /* - * The reader has spotted that the section's address - * in memory (i.e., sh_addr) is not aligned on the - * specified alignment (i.e., sh_addralign). - * - uint16 : The index of the section header. - * - Elf64_Shdr*: A pointer to the section header structure. - */ - BAD_SECHDR_ALIGN, - - /* - * The section header 0 is supposed to be SHT_NULL. But it wasn't. - */ - BAD_SECHDR0, - - /* - * The type of file (e_type) appears to be ET_CORE, and the - * machine is SPARC. Those files usually have wrong SHT's. We - * will rather opt for the PHT view. - */ - USING_PHT_SPARC_CORE, - - /* - * TLS definitions occurred more than once in the file. - */ - EXCESS_TLS_DEF, - - /* - * The section with the given name is being redefined. - * - const char *: The name of the section - */ - SECTION_REDEFINED, - - /* - * While parsing the dynamic_info_t, the reader spotted - * an invalid value for the DT_PLTREL entry. - * - uint32: The 'value' of that entry. - */ - BAD_DYN_PLT_TYPE, - - /* - * One of the symbols in the symbols tables has a bad binding. - * - unsigned char: The binding. - */ - BAD_SYMBOL_BINDING, - - /* - * The ELF module has a Section Header String Table index, but - * it is out-of-bounds. - * - uint32: the section header string table index; - * - uint16: the number of section header entries; - */ - BAD_SHSTRNDX, - - /* - * The ELF module has Program Header entries, which means it's - * ready to be loaded as a process image, but claims it is of - * type ET_REL which makes it a relocatable object file. - */ - CONFLICTING_FILE_TYPE, - - LAST_WARNING = CONFLICTING_FILE_TYPE, - - /* - * Couldn't read as many bytes as required. - * This is a fatal issue, and should be treated as such. - * - size_t: expected bytes. - * - size_t: actually read. - * - int32 : position in file when reading was initiated. - */ - ERR_READ, - - LAST_ERROR = ERR_READ - }; - - // Data members - program_headers_t pheaders; - section_headers_t sections; - symrel_cache_t symbols; - dynamic_info_t::entry_t sym_strtab; // for SYMTAB - dynamic_info_t::entry_t dyn_strtab; // for DYNSYM - - struct standard_sizes_in_file_t - { - int ehdr; - int phdr; - int shdr; - - struct - { - uint sym; - int dyn; - int rel; - int rela; - } entries; - - struct - { - uint sym; // DT_SYMENT - uint rel; // DT_RELENT - uint rela; // DT_RELAENT - } dyn; - - struct - { - int elf_addr; - int elf_off; - int elf_xword; - int elf_sxword; - } types; - } stdsizes; - -private: - linput_t *li; - int64 sif; // ELF start in file - uint64 filesize; - // Handle an error. If this function returns false, the reader will stop. - bool (*handle_error)(const reader_t &reader, errcode_t notif, ...); - elf_ehdr_t header; - - struct mapping_t - { - uint64 offset; - uint64 size; - uint64 ea; - }; - qvector<mapping_t> mappings; - - arch_specific_t *arch_specific; - adiff_t load_bias; // An offset to apply to the ea's - // when loading the program in memory. - // real endianness and bitness of the file - // some loaders (e.g. Linux) ignore values in the ident header - // so we set the effective ones here - bool eff_msb; - bool eff_64; // is elf64? - bool seg_64; // segments are 32bit or 64bit? - - bool check_ident(); -public: - reader_t(linput_t *_li, int64 _start_in_file = 0); - ~reader_t() - { - delete arch_specific; - } - void set_linput(linput_t *_li) { li = _li; } - linput_t *get_linput() const { return li; } - void set_load_bias(adiff_t lb) { load_bias = lb; } - adiff_t get_load_bias() const { return load_bias; } - - bool is_warning(errcode_t notif) const; - bool is_error(errcode_t notif) const; - ssize_t prepare_error_string(char *buf, size_t bufsize, reader_t::errcode_t notif, va_list va) const; - - void set_handler(bool (*_handler)(const reader_t &reader, errcode_t notif, ...)); - - int read_addr(void *buf) const; - int read_off(void *buf) const; - int read_xword(void *buf) const; - int read_sxword(void *buf) const; - int read_word(uint32 *buf) const; - int read_half(uint16 *buf) const; - int read_byte(uint8 *buf) const; - int read_symbol(elf_sym_t *buf) const; - int safe_read(void *buf, size_t size, bool apply_endianness = true) const; - - bool read_ident(); // false - bad elf file - - // Is the file a valid relocatable file? That is, it must have - // the ET_REL ehdr e_type, and have a proper section table. - bool is_valid_rel_file() const - { - return sections.initialized && !sections.empty() && get_header().e_type == ET_REL; - } - const elf_ident_t &get_ident() const { return header.e_ident; } - - bool read_header(); - elf_ehdr_t &get_header () { return header; } - const elf_ehdr_t &get_header () const { return header; } - - bool read_section_headers(); - bool read_program_headers(); - bool read_notes(notes_t *notes); - - // Android elf files can have a prelink. - // If such a prelink was found, this will return 'true' and - // '*base' will be set to that prelink address. - bool read_prelink_base(uint32 *base); - - int64 get_start_in_file() const { return sif; } - - // Seek to section header #index. - // (Note that this does not seek to the section's contents!) - bool seek_to_section_header(elf_shndx_t index) - { - uint64 pos = header.e_shoff + uint64(index) * uint64(header.e_shentsize); - if ( pos < header.e_shoff ) - return false; - if ( seek(pos) == -1 ) - return false; - return true; - } - - // read the section header from the current position - // (should be called after seek_to_section_header) - bool read_section_header(elf_shdr_t *sh); - - // Seek to program header #index. - // (Note that this does not seek to the segment's contents!) - bool seek_to_program_header(uint32 index) - { - uint64 pos = header.e_phoff + uint64(index) * uint64(header.e_phentsize); - if ( pos < header.e_phoff ) - return false; - if ( seek(pos) == -1 ) - return false; - return true; - } - - // read the compression header from the current position - // (should be called after seek_to_compression_header) - bool read_compression_header(elf_chdr_t *out); - - // Get the current position, in the elf module (which could - // start at an offset different than 0 in the file). - int64 tell() const { return qltell(li) - sif; } - int64 size() const { return filesize - sif; } - - // Seek in the elf module, at the given position. If the elf module has an - // offset in the file, it will be added to 'pos' to compose the final - // position in file. - qoff64_t seek(int64 pos) const { return qlseek(li, sif+pos); } - - // - elf_sym_idx_t rel_info_index(const elf_rela_t &r) const; - uint32 rel_info_type(const elf_rela_t &r) const; - void set_rel_info_index(elf_rela_t *r, uint32 symidx) const; - void set_rel_info_type(elf_rela_t *r, uint32 type) const; - - void add_mapping(const elf_phdr_t &p); - // Searches all defined mappings for one that would - // encompass 'ea'. Returns -1 if not found. - int64 file_offset(uint64 ea) const; - // Searches all defined mappings for one that would - // encompass file offset 'offset'. Returns BADADDR if not found. - ea_t file_vaddr(uint64 offset) const; - - elf_shndx_t get_shndx_at(uint64 offset) const; - - // string tables - void set_sh_strtab( - dynamic_info_t::entry_t &strtab, - const elf_shdr_t &strtab_sh, - bool replace); - void set_di_strtab( - dynamic_info_t::entry_t &strtab, - const dynamic_info_t::entry_t &strtab_di); - bool get_string_at(qstring *out, uint64 offset) const; - bool get_name( - qstring *out, - const dynamic_info_t::entry_t &strtab, - uint32 name_idx) const; - bool get_name(qstring *out, slice_type_t slice_type, uint32 name_idx) const; - - // Sets the dynamic info - typedef qvector<elf_dyn_t> dyninfo_tags_t; - bool read_dynamic_info_tags( - dyninfo_tags_t *dyninfo_tags, - const dynamic_linking_tables_t &dlt); - bool parse_dynamic_info( - dynamic_info_t *dyninfo, - const dyninfo_tags_t &dyninfo_tags); - - // Symbol versions - bool read_symbol_versions( - elf_symbol_version_t *symver, - const dynamic_info_t &di, - bool use_pht); - - arch_specific_t *get_arch_specific() const { return arch_specific; } - - // Human-friendly representations of - // header (or ident) values. - const char *file_type_str() const; - const char *os_abi_str() const; - const char *machine_name_str() const; // may return NULL - qstring get_machine_name() const; - - // effective endianness - bool is_msb() const { return eff_msb; } - // effective bitness (elf32 or elf64) - bool is_64() const { return eff_64; } - // effective bitness for segments - int get_seg_bitness() const { return seg_64 ? 2 : 1; } - - // pointer size for some 64bit ABIs may be 32bit - bool is_32_ptr() const - { - return !is_64() - || header.e_machine == EM_PPC64 - && header.e_ident.osabi == ELFOSABI_CELLOSLV2 - || header.e_machine == EM_X86_64 - && header.e_ident.osabi == ELFOSABI_NACL; - } - - bool is_arm() const - { - return header.e_machine == EM_ARM || header.e_machine == EM_AARCH64; - } - // validate section size and return number of elements - void validate_section_size( - uint64 *count, - size_t *entsize, - const elf_shdr_t §ion, - const char *counter_name); -}; - -//---------------------------------------------------------------------------- -struct input_status_t -{ - input_status_t(const reader_t &_reader) - : reader(_reader), - pos(reader.tell()) - { - } - - qoff64_t seek(int64 new_pos) - { - return reader.seek(new_pos); - } - - ~input_status_t() - { - reader.seek(pos); - } -private: - const reader_t &reader; - int64 pos; - input_status_t(); -}; - -//---------------------------------------------------------------------------- -#define _safe(expr) if ( (expr) < 0 ) return false -struct elf_verdef_t : public Elf_Verdef -{ - bool read(const reader_t &reader) - { - _safe(reader.read_half(&vd_version)); - _safe(reader.read_half(&vd_flags)); - _safe(reader.read_half(&vd_ndx)); - _safe(reader.read_half(&vd_cnt)); - _safe(reader.read_word(&vd_hash)); - _safe(reader.read_word(&vd_aux)); - _safe(reader.read_word(&vd_next)); - return true; - } - uint16 cnt() - { - return vd_cnt; - } - uint32 aux() - { - return vd_aux; - } - uint32 next() - { - return vd_next; - } -}; - -//---------------------------------------------------------------------------- -struct elf_verdaux_t : public Elf_Verdaux -{ - bool read(const reader_t &reader) - { - _safe(reader.read_word(&vda_name)); - _safe(reader.read_word(&vda_next)); - return true; - } - uint32 next() - { - return vda_next; - } -}; - -//---------------------------------------------------------------------------- -struct elf_verneed_t : public Elf_Verneed -{ - bool read(const reader_t &reader) - { - _safe(reader.read_half(&vn_version)); - _safe(reader.read_half(&vn_cnt)); - _safe(reader.read_word(&vn_file)); - _safe(reader.read_word(&vn_aux)); - _safe(reader.read_word(&vn_next)); - return true; - } - uint16 cnt() - { - return vn_cnt; - } - uint32 aux() - { - return vn_aux; - } - uint32 next() - { - return vn_next; - } -}; - -//---------------------------------------------------------------------------- -struct elf_vernaux_t : public Elf_Vernaux -{ - bool read(const reader_t &reader) - { - _safe(reader.read_word(&vna_hash)); - _safe(reader.read_half(&vna_flags)); - _safe(reader.read_half(&vna_other)); - _safe(reader.read_word(&vna_name)); - _safe(reader.read_word(&vna_next)); - return true; - } - uint32 next() - { - return vna_next; - } -#undef _safe -}; - -//---------------------------------------------------------------------------- -struct symbol_verdaux_t -{ - int64 offset; - size_t name; // index in symver.version_names -}; -DECLARE_TYPE_AS_MOVABLE(symbol_verdaux_t); -typedef qvector<symbol_verdaux_t> symbol_verdaux_vec_t; - -//---------------------------------------------------------------------------- -struct symbol_verdef_t -{ - int64 offset; - symbol_verdaux_vec_t auxs; - uint16 flags; - uint16 ndx; -}; -DECLARE_TYPE_AS_MOVABLE(symbol_verdef_t); -typedef qvector<symbol_verdef_t> symbol_verdef_vec_t; - -//---------------------------------------------------------------------------- -struct symbol_vernaux_t -{ - int64 offset; - size_t name; // index in symver.version_names - uint16 other; -}; -DECLARE_TYPE_AS_MOVABLE(symbol_vernaux_t); -typedef qvector<symbol_vernaux_t> symbol_vernaux_vec_t; - -//---------------------------------------------------------------------------- -struct symbol_verneed_t -{ - int64 offset; - size_t name; // index in symver.file_names - symbol_vernaux_vec_t auxs; -}; -DECLARE_TYPE_AS_MOVABLE(symbol_verneed_t); -typedef qvector<symbol_verneed_t> symbol_verneed_vec_t; - -//---------------------------------------------------------------------------- -struct vermap_item_t -{ - size_t fname_idx; // index in symver.file_names - size_t vname_idx; // index in symver.version_names -}; - -//---------------------------------------------------------------------------- -typedef std::map<uint16, vermap_item_t> symbol_version_map_t; - -//---------------------------------------------------------------------------- -struct elf_symbol_version_t -{ - // from DT_VERDEF - symbol_verdef_vec_t defs; - // from DT_VERNEED - symbol_verneed_vec_t reqs; - // from DT_VERSYM - qvector<uint16> symbols; - - // item with VER_FLG_BASE in verdaux - size_t def_base; // index in file_names - - // file and version strings referenced throughout this structure - qstrvec_t file_names; - qstrvec_t version_names; - - // map for entries in DT_VERSYM - symbol_version_map_t vermap; - - elf_symbol_version_t() - : def_base(0) - {} -}; - -//---------------------------------------------------------------------------- -template<typename T> class buffered_input_t -{ -protected: - reader_t &reader; - uint64 offset; - uint64 count; - size_t isize; // entry size - - qvector<T> buffer; - uint64 read; // number of items we already read from the input - uint32 cur; // ptr to the next item in 'buffer' to be served - uint32 end; // number of items in 'buffer' - -public: - buffered_input_t(reader_t &_reader, const elf_shdr_t §ion) - : reader(_reader), - offset(section.sh_offset), - count (0), - isize (section.sh_entsize), - read (0), - cur (0), - end (0) - { - count = reader.sections.get_size_in_file(section); - if ( isize != 0 ) - count /= isize; - } - buffered_input_t( - reader_t &_reader, - uint64 _offset, - uint64 _count, - size_t entsize) - : reader(_reader), - offset(_offset), - count (_count), - isize (entsize), - read (0), - cur (0), - end (0) {} - virtual ~buffered_input_t() {} - - virtual bool next(T *&storage) newapi - { - if ( cur >= end ) - { - uint64 left = count - read; - if ( left == 0 ) - return false; - buffer.resize(left); - - cur = 0; - if ( read == 0 ) - start_reading(); - end = read_items(left); - if ( end == 0 ) - return false; - read += end; - } - - if ( cur >= end ) - return false; - - storage = &buffer[cur]; - cur++; - return true; - } - -private: - buffered_input_t(); - // default and dumb implementation of read_items() - // it reads items one by one from the input. - // see other implementations in template specializations - ssize_t read_items(size_t max) - { - size_t i = 0; - if ( is_mul_ok<uint64>(read, isize) && is_mul_ok(max, isize) ) - { - input_status_t save_excursion(reader); - if ( save_excursion.seek(offset + (read * isize)) != -1 ) - for ( ; i < max; i++ ) - if ( !read_item(buffer[i]) ) - break; - } - return i; - } - - bool read_item(T &) { return false; } - void start_reading() {} -}; - -class buffered_rel_t : public buffered_input_t<elf_rel_t> -{ - typedef buffered_input_t<elf_rel_t> inherited; - elf_rela_t rela; // to return from next_rela() - -public: - buffered_rel_t(reader_t &_reader, const elf_shdr_t §ion) - : inherited(_reader, section) {} - buffered_rel_t( - reader_t &_reader, - uint64 _offset, - uint64 _count, - size_t entsize) - : inherited(_reader, _offset, _count, entsize) {} - bool next_rela(elf_rela_t *&storage) - { - elf_rel_t *rel; - if ( !inherited::next(rel) ) - return false; - rela.r_offset = rel->r_offset; - rela.r_info = rel->r_info; - rela.r_addend = 0; - storage = &rela; - return true; - } -}; - -class buffered_rela_t : public buffered_input_t<elf_rela_t> -{ - typedef buffered_input_t<elf_rela_t> inherited; - - bool packed; -public: - buffered_rela_t(reader_t &_reader, const elf_shdr_t §ion, bool _packed) - : inherited(_reader, section), packed(_packed) {} - buffered_rela_t( - reader_t &_reader, - uint64 _offset, - uint64 _count, - size_t entsize, - bool _packed) - : inherited(_reader, _offset, _count, entsize), packed(_packed) {} - virtual bool next(elf_rela_t *&storage) override; - bool next_rela(elf_rela_t *&storage) { return next(storage); } -}; - -//-------------------------------------------------------------------------- -struct shdr_def_t -{ - range_t range; - sel_t sel; // selectors of loaded sections, - // BADSEL-section not loaded - bool may_overlap; // may overlap with other sections. - // no warning is shown, but sh_overlaps is still set. - - shdr_def_t() : sel(BADSEL), may_overlap(false) {} - shdr_def_t(const elf_shdr_t *sh, bool may_overlap_ = false) - : range(ea_t(sh->sh_offset), ea_t(sh->sh_offset + sh->sh_size)), - sel(BADSEL), - may_overlap(may_overlap_) {} -}; -DECLARE_TYPE_AS_MOVABLE(shdr_def_t); -typedef qvector<shdr_def_t> shdr_defs_t; - -//-------------------------------------------------------------------------- -// description of special segments -struct elf_spec_segm_t -{ - //lint --e{958} Padding of ... is required to align member on ... boundary - // description - const char *seg_name = nullptr; - uint16 shn_type = 0; - uchar seg_type = 0; - // allocation - uint32 nsyms = 0; - ea_t start = 0; - ea_t end = 0; - ea_t cur = 0; - - elf_spec_segm_t(uchar seg_type_=0, const char *seg_name_=nullptr, uint16 shn_type_=0) - : seg_name(seg_name_), - shn_type(shn_type_), - seg_type(seg_type_) - { - } - - static proc_def_t::spec_type_t symbol2spec( - const proc_def_t *pd, - uint16 secidx, - ushort type); - bool not_allocated() const { return start == 0 && end == 0; } - - bool allocate_spec_segm(elf_loader_t &ldr, reader_t &reader); - - // it shrinks the segment and returns its new end - ea_t end_seg(); -}; - -//------------------------------------------------------------------------- -struct elf_range_info_t -{ - ea_t start; - ea_t end; - int64 offset; -}; -DECLARE_TYPE_AS_MOVABLE(elf_range_info_t); -typedef std::map<ea_t, elf_range_info_t> range_info_map_t; -typedef range_info_map_t::const_iterator range_info_map_citerator_t; - -struct loaded_ranges_t -{ - bool add(int64 offset, ea_t start, ea_t _end) - { - bool ok = ranges.add(start, _end); - if ( ok ) - { - elf_range_info_t &info = range_info_map[start]; - info.start = start; - info.end = _end; - info.offset = offset; - } - return ok; - } - const range_t *find_range(ea_t ea) const - { - return ranges.find_range(ea); - } - ea_t next_range(ea_t ea) const - { - return ranges.next_range(ea); - } - const elf_range_info_t *range_info(ea_t ea) const - { - const range_t *range = ranges.find_range(ea); - if ( range == NULL ) - return NULL; - range_info_map_citerator_t it = range_info_map.find(range->start_ea); - if ( it == range_info_map.end() ) - return NULL; - return &it->second; - } - -private: - rangeset_t ranges; - range_info_map_t range_info_map; -}; - -//-------------------------------------------------------------------------- -class tlsinfo2_public_t -{ - friend struct process_tls_t; - friend struct elf_loader_t; - struct tlsinfo2_t *pimpl; -public: - tlsinfo2_public_t(elf_loader_t &l); - tlsinfo2_public_t(); - ~tlsinfo2_public_t(); - void set_env(reader_t &reader_, elf_spec_segm_t &spec_tls_); - void set_from_ph(const elf_phdr_t &p); - // should be called after set_from_ph() - void set_from_tdata_sh( - const elf_shdr_t &sh, - elf_shndx_t secidx, - const char *name); - // should be called after set_from_ph() - void set_from_tbss_sh( - const elf_shdr_t &sh, - elf_shndx_t secidx, - const char *name); - void create_tls_template(); - // define 'tls_index' structures - void analyze_tis(); - ea_t get_tls_end() const; - ea_t symbol2ea(const sym_rel &symrel) const; -}; - -//-------------------------------------------------------------------------- -struct elf_loader_t -{ - linput_t *li = nullptr; - struct processor_t &ph; - elf_spec_segm_t spec_segms[proc_def_t::NSPEC_SEGMS]; - - sel_t cursel = 0; - sel_t datasel = 0; - - elf_shndx_t ct_sec = 0; - elf_shndx_t dt_sec = 0; - ea_t init_ea = 0; - ea_t fini_ea = 0; - ea_t init_proc_ea = 0; - ea_t fini_proc_ea = 0; - - eavec_t got_entries; - - tlsinfo2_public_t tlsinfo2; - - proc_def_t *pd = nullptr; - - qstrvec_t implibs; - netnode impnode = BADNODE; - - qstring interpreter; - - netnode elfnode; - - // The program end. Does *not* contain the 'extern' segment. It does, - // however, contain .bss and .tbss data. - ea_t prgend = 0; - - // index of the _GLOBAL_OFFSET_TABLE_ symbol for the relocatable files - symrel_idx_t got_sym_idx; - - // This symbol is used only for debugging purposes. - // It specifies the segment base to be used for all segments. - // Usually it is zero (ELF files use flat memory without any segments) - uval_t debug_segbase = 0; - - loaded_ranges_t loaded_ranges; - - // structure ids for VERDEF, VERDAUX, etc - tid_t verdef_sid = BADADDR; - tid_t verdaux_sid = BADADDR; - tid_t vernaux_sid = BADADDR; - tid_t verneed_sid = BADADDR; - tid_t prstatus_sid = BADADDR; - tid_t prpsinfo_sid = BADADDR; - tid_t elf_sym_sid = BADADDR; - tid_t elf_rel_sid = BADADDR; - tid_t elf_rela_sid = BADADDR; - - size_t stubsize = 0; - ea_t topaddr = 0; - - ushort neflags; - fixup_type_t ptpoff_reltype = FIXUP_CUSTOM; - - bool broken_output_warning_displayed = false; - bool widebyte = false; - bool was_empty_idb = false; - bool gnuunx_loaded = false; // loaded gnuunx.til? - bool rel_present = false; - char rel_mode = 0; // 1 - STT_SECTION - // 0 - !STT_SECTION - //-1 - STT_NOTYPE or undefined - - elf_loader_t(linput_t *li, ushort neflags); - ~elf_loader_t(); - void load_file(); - ushort ana_hdr(reader_t &reader); - void collect_loader_options(struct elf_load_options *load_opts); - const char *get_processor_name( - reader_t &reader, - const elf_ehdr_t &header, - bool msb); - size_t max_loaded_size(ea_t ea, size_t size) const; - bool is_range_loaded(ea_t ea, size_t size) const; - bool load_section_headers(reader_t &reader); - elf_file_info_t *find_companion_file( - const reader_t &main_reader, - const notes_t ¬es, - const elf_load_options &load_opts, - rangevec_t *loaded_notes); - ea_t preload_pht(reader_t &reader); - void load_pht( - reader_t &reader, - const elf_load_options &load_opts, - rangevec_t *loaded_notes); - bool should_load_segment( - reader_t &reader, - const elf_shdr_t *sh, - elf_shndx_t idx, - const qstring &name); - bool is_uniform(reader_t &reader, size_t offset, asize_t size); - void find_and_load_gaps(reader_t &reader); - void load_section_contents( - elf_file_info_t &finfo, - rangevec_t *loaded_notes); - bool belongs_to_skipped_section( - elf_file_info_t &finfo, - const sym_rel &sym); - void detect_overlapping_pht(int64 offset, ea_t startaddr, ea_t endaddr) const; - void validate_dynamic_info(reader_t &reader, dynamic_info_t *di) const; - void annotate_headers(reader_t &reader); - void annotate_loaded_notes(reader_t &reader, const rangevec_t &loaded_notes); - void annotate_note_core(reader_t &reader, const struct print_note_t ¬e); - void make_verdef_section( - reader_t &reader, - const dynamic_info_t::entry_t &entry, - const elf_symbol_version_t &symver); - void make_verneed_section( - reader_t &reader, - const dynamic_info_t::entry_t &entry, - const elf_symbol_version_t &symver); - void make_versym_section( - reader_t &reader, - const dynamic_info_t::entry_t &entry, - const elf_symbol_version_t &symver); - void make_rel_section( - reader_t &reader, - const dynamic_info_t::entry_t &entry, - bool is_rela, - const char *name); - void make_symtab_section(reader_t &reader, const dynamic_info_t::entry_t &entry); - ea_t unwide_ea(ea_t ea, const char *diagn) const; - void preprocess_symbols( - elf_file_info_t &finfo, - const elf_load_options &load_opts); - int load_symbols( - elf_file_info_t &finfo, - slice_type_t slice_type, - uint32 section_symbols_count, - bool skip_undef_symbols); - void apply_file_symbols(elf_file_info_t &finfo); - void check_notype_symbols( - elf_file_info_t &finfo, - slice_type_t slice_type); - void define_gotnode(elf_file_info_t &finfo, const elf_dyn_t &dyn); - void guess_gotnode_size(reader_t &reader); - void describe_public( - ea_t ea, - ushort bind, - int entry_flag, - const char *name, - const elf_symbol_version_t *symver=NULL, - elf_sym_idx_t symidx=0); - ea_t create_addonce_var( - ea_t ea, - uint64 valsiz, - uchar seg_typ, - ushort type, - ushort bind, - bool isfunc, - const char *name, - const elf_symbol_version_t *symver, - elf_sym_idx_t symidx); - ea_t declare_spec( - reader_t &reader, - uint16 secidx, - uint64 size, - ushort type, - ushort bind, - bool isfunc, - const char *name, - const elf_symbol_version_t *symver=NULL, - elf_sym_idx_t symidx=0); - void count_spec_symbols( - reader_t &reader, - slice_type_t slice_type, - bool skip_undef_symbols); - bool call_add_segm_ex( - segment_t *s, - const char *name, - const char *sclass, - int flags) const; - bool add_or_merge_segm( - segment_t *s, - const char *name, - const char *sclass, - int flags); - bool do_define_segment( - reader_t &reader, - ea_t *out_sa, - ea_t *out_topseg, - elf_shdr_t &sh, - const qstring &name); - bool define_segment( - elf_file_info_t &finfo, - elf_shdr_t &sh, - elf_shndx_t idx, - const qstring &name, - bool force_load, - ea_t *startaddr = nullptr, - asize_t *_size = nullptr); - void load_huge_segment( - reader_t &reader, - const segment_t &s, - const elf_phdr_t &p, - const char *sclass, - const char *name, - int flags); - // create a new segment where a previous segment ended (at the top). - // Allocate new selector for the new segment. If the flag use_cursel is - // set then use currently allocated segment selector and allocate a new - // one after creation. - segment_t *create_segment_at_top( - reader_t &reader, - uchar type, - const char *name, - asize_t size, - uchar align, - bool use_cursel = false); - void look_for_prgend_symbols(reader_t &reader); - // for the relocation object file calculate a start address of the - // segment where previous segment ended (at the top). For executable or - // shared objects this function returns the address from <sh>. - ea_t get_default_segment_ea(reader_t &reader, const elf_shdr_t &sh) const; - bool should_rename(ushort type, const char *name) const; - void check_for_gnuc(const char *name); - void convert_sub_table(reader_t &reader, const elf_shdr_t *pps, char lsym); - void elf_get_rebased_eas(reader_t &reader, ea_t *pimagebase, ea_t *pload_base); - void load_ids_info(void); - // get fixup for PTPOFF generic TLS reloc, - // it returns FIXUP_CUSTOM if this reloc isn't supported - fixup_type_t get_ptpoff_reltype(); - void comment_rename(ea_t ea, const char *name); - void broken_output_warning(void); - asize_t map_range_from_file( - reader_t &reader, - int64 offset, - ea_t startaddr, - ea_t endaddr, - const elf_phdr_t *pht_entry = NULL); - // FIXME this is wrong! it will be replaced by process_TLS() - // It is assumed the 'in_out_offset' is relative to the start of - // the TLS block at runtime. Since those blocks have the following layout: - // +---------------+ - // | | - // | .tdata | - // | | - // +---------------+ - // | | - // | .tbss | - // | | - // +---------------+ - // we'll associate 'in_out_offset' to either the '.tdata' segment, - // or the '.tbss' one, depending on whether it overflows - // .tdata or not. - // - // As a side-effect, note that the value pointed to by 'in_out_offset' will - // be different after this function returns, in case it lands into '.tbss'. - // (it will be: in_out_offset_after = in_out_offset - segment_size(".tdata")) - ea_t get_tls_ea_by_offset(uint32 *in_out_offset); - void relocate_rela( - reader_t &reader, - const elf_rela_t &rel, - bool is_rela, - int reloc_idx, // Current index in relocation section - slice_type_t slice_type, - uint32 info_idx, - const char *segname, - reloc_tools_t &tools); - void relocate_section_mips( - reader_t &reader, - const elf_shdr_t §ion, - const char *segname, - slice_type_t slice_type, - reloc_tools_t &tools, - bool packed, - int info_idx, - uint64 count, - size_t entsize); - void relocate_section( - elf_file_info_t &finfo, - const elf_shdr_t §ion, - const char *segname, - slice_type_t slice_type, - reloc_tools_t &tools, - bool packed); - void process_relocations( - elf_file_info_t &finfo, - const dynamic_info_t &di, - reloc_tools_t &tools); - bool use_displ_for_symbol(ea_t S, adiff_t A) - { - if ( S >= prgend ) - return true; - if ( rel_mode == 1 ) // symbol is STT_SECTION ? - { - segment_t *s = getseg(S); - return s == NULL || A < 0 || A >= s->size(); - } - return false; - } -}; - -//-------------------------------------------------------------------------- -inline int check_alignment(uint64 align) -{ - if ( align > 1 && align <= 4096 && (align & (align - 1)) == 0 ) - return int(align); - return 1; // ignore alignment -} - -ushort get_algn_value(uval_t algn); -void get_versioned_symbol_name( - qstring *out, - const char *symname, - const elf_symbol_version_t &symver, - uint16 idx); -void annotate_got0(const reader_t &reader, ea_t got0); -void annotate_loaded_notes( - const reader_t &reader, - const rangevec_t &loaded_notes); -void set_got_entry(ea_t ea, const char *name, int flags, const char *suffix = "_ptr"); - -#endif diff --git a/idasdk75/ldr/elf/elfbase.h b/idasdk75/ldr/elf/elfbase.h deleted file mode 100644 index 20fbe54..0000000 --- a/idasdk75/ldr/elf/elfbase.h +++ /dev/null @@ -1,999 +0,0 @@ -#ifndef __ELFBASE_H__ -#define __ELFBASE_H__ -#pragma pack(push, 4) - -//========================================================================= -struct elf_ident_t -{ - uint32 magic; -#if __MF__ -# define ELF_MAGIC 0x7F454C46 // big endian \x7FELF -#else -# define ELF_MAGIC 0x464C457F // litte endian \x7FELF -#endif - uint8 elf_class; -#define ELFCLASSNONE 0 // Invalid class -#define ELFCLASS32 1 // 32bit object -#define ELFCLASS64 2 // 64bit object - uint8 bytesex; -#define ELFDATANONE 0 // Invalid data encoding -#define ELFDATA2LSB 1 // low byte first -#define ELFDATA2MSB 2 // high byte first - uint8 version; // file version - uint8 osabi; // Operating System/ABI indication -#define ELFOSABI_NONE 0 // UNIX System V ABI -#define ELFOSABI_HPUX 1 // HP-UX operating system -#define ELFOSABI_NETBSD 2 // NetBSD -#define ELFOSABI_LINUX 3 // GNU/Linux -#define ELFOSABI_HURD 4 // GNU/Hurd -#define ELFOSABI_SOLARIS 6 // Solaris -#define ELFOSABI_AIX 7 // AIX -#define ELFOSABI_IRIX 8 // IRIX -#define ELFOSABI_FREEBSD 9 // FreeBSD -#define ELFOSABI_TRU64 10 // TRU64 UNIX -#define ELFOSABI_MODESTO 11 // Novell Modesto -#define ELFOSABI_OPENBSD 12 // OpenBSD -#define ELFOSABI_OPENVMS 13 // OpenVMS -#define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel -#define ELFOSABI_AROS 15 // Amiga Research OS -#define ELFOSABI_C6000_ELFABI 64 // Texas Instruments TMS320C6 bare-metal -#define ELFOSABI_C6000_LINUX 65 // TI TMS320C6 MMU-less Linux platform -#define ELFOSABI_ARM 97 // ARM -#define ELFOSABI_CELLOSLV2 102 // PS3 lv2 OS -#define ELFOSABI_NACL 123 // ChromeOS Native Client -#define ELFOSABI_STANDALONE 255 // Standalone (embedded) application - uint8 abiversion; // ABI version - uint8 pad[7]; - - bool is_valid() const { return magic == ELF_MAGIC; } - bool is_msb() const { return bytesex == ELFDATA2MSB; } - bool is_64() const { return elf_class == ELFCLASS64; } -}; - -struct Elf32_Ehdr -{ - elf_ident_t e_ident; - uint16 e_type; // enum ET - uint16 e_machine; // enum EM - uint32 e_version; // enum EV - uint32 e_entry; // virtual start address - uint32 e_phoff; // off to program header table's (pht) - uint32 e_shoff; // off to section header table's (sht) - uint32 e_flags; // EF_machine_flag - uint16 e_ehsize; // header's size - uint16 e_phentsize; // size of pht element - uint16 e_phnum; // entry counter in pht - uint16 e_shentsize; // size of sht element - uint16 e_shnum; // entry count in sht - uint16 e_shstrndx; // sht index in name table -}; - - -enum elf_ET -{ - ET_NONE = 0, // No file type - ET_REL = 1, // Relocatable file - ET_EXEC = 2, // Executable file - ET_DYN = 3, // Share object file - ET_CORE = 4, // Core file - ET_LOOS = 0xfe00u, // OS specific - ET_HIOS = 0xfeffu, // OS specific - ET_LOPROC = 0xff00u, // Processor specific - ET_HIPROC = 0xffffu // Processor specific -}; - -enum elf_EM -{ - EM_NONE = 0, // No machine - EM_M32 = 1, // AT & T WE 32100 - EM_SPARC = 2, // Sparc - EM_386 = 3, // Intel 80386 - EM_68K = 4, // Motorola 68000 - EM_88K = 5, // Motorola 88000 - EM_486 = 6, - //ATTENTION!!! in documentation present next values - // EM_860 = 6, // Intel 80860 - // EM_MIPS = 7, // MIPS RS3000 - //in linux RS3000 = 8, !!! - // taken from linux - EM_860 = 7, - EM_MIPS = 8, // Mips 3000 (officialy, big-endian only) - EM_S370 = 9, // IBM System370 - EM_MIPS_RS3_BE = 10, // MIPS R3000 Big Endian - // EM_SPARC_64 = 11, // SPARC v9 - EM_PARISC = 15, // HPPA - EM_VPP550 = 17, // Fujitsu VPP500 - EM_SPARC32PLUS = 18, // Sun's v8plus - EM_I960 = 19, // Intel 960 - EM_PPC = 20, // Power PC - EM_PPC64 = 21, // 64-bit PowerPC - EM_S390 = 22, // IBM S/390 - EM_SPU = 23, // Cell Broadband Engine Synergistic Processor Unit - EM_CISCO7200 = 25, // Cisco 7200 Series Router (MIPS) - EM_CISCO3620 = 30, // Cisco 3620/3640 Router (MIPS, IDT R4700) - EM_V800 = 36, // NEC V800 series - EM_FR20 = 37, // Fujitsu FR20 - EM_RH32 = 38, // TRW RH32 - EM_MCORE = 39, // Motorola M*Core (May also be taken by Fujitsu MMA) - EM_ARM = 40, // ARM - EM_OLD_ALPHA = 41, // Digital Alpha - EM_SH = 42, // Renesas (formerly Hitachi) / SuperH SH - EM_SPARC64 = 43, // Sparc v9 64-bit - EM_TRICORE = 44, // Siemens Tricore embedded processor - EM_ARC = 45, // ARC Cores - EM_H8300 = 46, // Renesas (formerly Hitachi) H8/300 - EM_H8300H = 47, // Renesas (formerly Hitachi) H8/300H - EM_H8S = 48, // Renesas (formerly Hitachi) H8S - EM_H8500 = 49, // Renesas (formerly Hitachi) H8/500 - EM_IA64 = 50, // Intel Itanium IA64 - EM_MIPS_X = 51, // Stanford MIPS-X - EM_COLDFIRE = 52, // Motorola Coldfire - EM_6812 = 53, // Motorola MC68HC12 - EM_MMA = 54, // Fujitsu Multimedia Accelerator - EM_PCP = 55, // Siemens PCP - EM_NCPU = 56, // Sony nCPU embedded RISC processor - EM_NDR1 = 57, // Denso NDR1 microprocesspr - EM_STARCORE = 58, // Motorola Star*Core processor - EM_ME16 = 59, // Toyota ME16 processor - EM_ST100 = 60, // STMicroelectronics ST100 processor - EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor - EM_X86_64 = 62, // Advanced Micro Devices X86-64 processor - EM_PDSP = 63, // Sony DSP Processor - EM_PDP10 = 64, // DEC PDP-10 - EM_PDP11 = 65, // DEC PDP-11 - EM_FX66 = 66, // Siemens FX66 microcontroller - EM_ST9 = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller - EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller - EM_68HC16 = 69, // Motorola MC68HC16 - EM_6811 = 70, // Motorola MC68HC11 - EM_68HC08 = 71, // Motorola MC68HC08 - EM_68HC05 = 72, // Motorola MC68HC05 - EM_SVX = 73, // Silicon Graphics SVx - EM_ST19 = 74, // STMicroelectronics ST19 8-bit cpu - EM_VAX = 75, // Digital VAX - EM_CRIS = 76, // Axis Communications 32-bit embedded processor - EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded cpu - EM_FIREPATH = 78, // Element 14 64-bit DSP processor - EM_ZSP = 79, // LSI Logic's 16-bit DSP processor - EM_MMIX = 80, // Donald Knuth's educational 64-bit processor - EM_HUANY = 81, // Harvard's machine-independent format - EM_PRISM = 82, // SiTera Prism - EM_AVR = 83, // Atmel AVR 8-bit microcontroller - EM_FR = 84, // Fujitsu FR Family - EM_D10V = 85, // Mitsubishi D10V - EM_D30V = 86, // Mitsubishi D30V - EM_V850 = 87, // NEC v850 (GNU compiler) - - EM_NECV850E = 0x70FC, // ^ - EM_NECV850 = 0x70FF, // | - EM_NECV850E2 = 0x71EA, // | - EM_NECV850ES = 0x73CE, // | - EM_NECV850E2R1 = 0x73FD, // |This group is used by the Renesas CA850 toolchain - EM_NECV850E2R2 = 0x73FE, // | - EM_NECV850E2R3 = 0x73FF, // | - EM_NECV850E2R4 = 0x7400, // | - EM_NECV850E3V5 = 0x74FB, // v - - EM_CYGNUS_V850 = 0x9080,// V850 backend magic number. Written in the absense of an ABI. - - EM_M32R = 88, // Renesas M32R (formerly Mitsubishi M32R) - EM_MN10300 = 89, // Matsushita MN10300 - EM_MN10200 = 90, // Matsushita MN10200 - EM_PJ = 91, // picoJava - EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor - EM_ARCOMPACT = 93, // ARC Cores (ARCompact ISA) - EM_XTENSA = 94, // Tensilica Xtensa Architecture - EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor - EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor - EM_NS32K = 97, // National Semiconductor 32000 series - EM_TPC = 98, // Tenor Network TPC processor - EM_SNP1K = 99, // Trebia SNP 1000 processor - EM_ST200 = 100, // STMicroelectronics ST200 microcontroller - EM_IP2K = 101, // Ubicom IP2022 micro controller - EM_MAX = 102, // MAX Processor - EM_CR = 103, // National Semiconductor CompactRISC - EM_F2MC16 = 104, // Fujitsu F2MC16 - EM_MSP430 = 105, // TI msp430 micro controller - EM_BLACKFIN = 106, // ADI Blackfin - EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors - EM_SEP = 108, // Sharp embedded microprocessor - EM_ARCA = 109, // Arca RISC Microprocessor - EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University - EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU - EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor - EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor - EM_CRX = 114, // National Semiconductor CRX - EM_XGATE = 115, // Motorola XGATE embedded processor - EM_C166 = 116, // Infineon C16x/XC16x processor - EM_M16C = 117, // Renesas M16C series microprocessors - EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal Controller - EM_CE = 119, // Freescale Communication Engine RISC core - EM_M32C = 120, // Renesas M32C series microprocessors - EM_TSK3000 = 131, // Altium TSK3000 core - EM_RS08 = 132, // Freescale RS08 embedded processor - EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor - EM_SCORE = 135, // Sunplus Score - EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor - EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor - EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture - EM_SE_C17 = 139, // Seiko Epson C17 family - EM_TI_C6000 = 140, // Texas Instruments TMS320C6000 family - EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor - EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor - EM_R32C = 162, // Renesas R32C series microprocessors - EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family - EM_QDSP6 = 164, // QUALCOMM DSP6 Processor - EM_8051 = 165, // Intel 8051 and variants - EM_STXP7X = 166, // STMicroelectronics STxP7x family - EM_NDS32 = 167, // Andes Technology compact code size embedded RISC processor family - EM_ECOG1 = 168, // Cyan Technology eCOG1X family - EM_ECOG1X = 168, // Cyan Technology eCOG1X family - EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers - EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor - EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor - EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture - EM_RX = 173, // Renesas RX family - EM_METAG = 174, // Imagination Technologies META processor architecture - EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture - EM_ECOG16 = 176, // Cyan Technology eCOG16 family - EM_CR16 = 177, // National Semiconductor CompactRISC 16-bit processor - EM_ETPU = 178, // Freescale Extended Time Processing Unit - EM_SLE9X = 179, // Infineon Technologies SLE9X core - EM_L1OM = 180, // Intel L1OM (Larrabee) - EM_K1OM = 181, // Intel K1OM - EM_INTEL182 = 182, // Reserved by Intel - EM_AARCH64 = 183, // ARM 64-bit architecture - EM_ARM184 = 184, // Reserved by ARM - EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family - EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller - EM_TILE64 = 187, // Tilera TILE64 multicore architecture family - EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family - EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor core - EM_CUDA = 190, // NVIDIA CUDA architecture - EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family - EM_CLOUDSHIELD = 192, // CloudShield architecture family - EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family - EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family - EM_ARC_COMPACT2 = 195, //Synopsys ARCompact V2 - EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core - EM_RL78 = 197, // Renesas RL78 family - EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor - EM_78K0R = 199, // Renesas 78K0R family - EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller - EM_BA1 = 201, // Beyond BA1 CPU architecture - EM_BA2 = 202, // Beyond BA2 CPU architecture - EM_XCORE = 203, // XMOS xCORE processor family - - EM_CYGNUS_POWERPC = 0x9025, // Cygnus PowerPC ELF backend - EM_ALPHA = 0x9026, // DEC Alpha - EM_S390_OLD = 0xa390 // old S/390 backend magic number. Written in the absence of an ABI. -}; - -enum elf_EV -{ - EV_NONE = 0, // None version - EV_CURRENT = 1 // Current version - // in linux header - // EV_NUM = 2 -}; - -// special section indexes -enum elh_SHN -{ - SHN_UNDEF = 0, // undefined/missing/... - SHN_LORESERVE = 0xff00, - SHN_LOPROC = 0xff00, - SHN_HIPROC = 0xff1f, - SHN_ABS = 0xfff1, // absolute value - SHN_COMMON = 0xfff2, // common values (fortran/c) - SHN_XINDEX = 0xffff, // the escape value - SHN_HIRESERVE = 0xffff -}; -//========== - -struct Elf32_Shdr -{ - uint32 sh_name; // index in string table - uint32 sh_type; // enum SHT - uint32 sh_flags; // enum SHF - uint32 sh_addr; // address in memory (or 0) - uint32 sh_offset; // offset in file - uint32 sh_size; // section size in bytes - uint32 sh_link; // index in symbol table - uint32 sh_info; // extra information - uint32 sh_addralign; // 0 & 1 => no alignment - uint32 sh_entsize; // size symbol table or eq. -}; - - -enum elf_SHT -{ - SHT_NULL = 0, // inactive - no assoc. section - SHT_PROGBITS = 1, // internal program information - SHT_SYMTAB = 2, // symbol table (static) - SHT_STRTAB = 3, // string table - SHT_RELA = 4, // relocation entries - SHT_HASH = 5, // symbol hash table - SHT_DYNAMIC = 6, // inf. for dynamic linking - SHT_NOTE = 7, // additional info - SHT_NOBITS = 8, // no placed in file - SHT_REL = 9, // relocation entries without explicit address - SHT_SHLIB = 10, // RESERVED - SHT_DYNSYM = 11, // Dynamic Symbol Table - SHT_COMDAT = 12, // COMDAT group directory -> SHT_HP_COMDAT */ - // abi 3 - SHT_INIT_ARRAY = 14, // Array of ptrs to init functions - SHT_FINI_ARRAY = 15, // Array of ptrs to finish functions - SHT_PREINIT_ARRAY = 16, // Array of ptrs to pre-init funcs - SHT_GROUP = 17, // Section contains a section group - SHT_SYMTAB_SHNDX = 18, // Indicies for SHN_XINDEX entries - // SHT_NUM = 12, - SHT_LOOS = 0x60000000ul, - SHT_HIOS = 0x6ffffffful, - SHT_LOPROC = 0x70000000ul, - SHT_HIPROC = 0x7ffffffful, - SHT_LOUSER = 0x80000000ul, - SHT_HIUSER = 0xfffffffful, - - // From binutils-2.27/elfcpp/elfcpp.h - // The remaining values are not in the standard. - // Incremental build data. - SHT_GNU_INCREMENTAL_INPUTS = 0x6fff4700, - SHT_GNU_INCREMENTAL_SYMTAB = 0x6fff4701, - SHT_GNU_INCREMENTAL_RELOCS = 0x6fff4702, - SHT_GNU_INCREMENTAL_GOT_PLT = 0x6fff4703, - SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. - SHT_GNU_HASH = 0x6ffffff6, // GNU style dynamic hash table. - SHT_GNU_LIBLIST = 0x6ffffff7, // List of prelink dependencies. - SHT_GNU_verdef = 0x6ffffffd, // Versions defined by file. - SHT_GNU_verneed = 0x6ffffffe, // Versions needed by file. - SHT_GNU_versym = 0x6fffffff, // Symbol versions. - - // http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-94076.html#OSLLGchapter6-73445 - SHT_SUNW_ancillary = 0x6fffffee, - SHT_SUNW_capchain = 0x6fffffef, - SHT_SUNW_capinfo = 0x6ffffff0, - SHT_SUNW_symsort = 0x6ffffff1, - SHT_SUNW_tlssort = 0x6ffffff2, - SHT_SUNW_LDYNSYM = 0x6ffffff3, - SHT_SUNW_dof = 0x6ffffff4, - SHT_SUNW_cap = 0x6ffffff5, - SHT_SUNW_SIGNATURE = 0x6ffffff6, - SHT_SUNW_ANNOTATE = 0x6ffffff7, - SHT_SUNW_DEBUGSTR = 0x6ffffff8, - SHT_SUNW_DEBUG = 0x6ffffff9, - SHT_SUNW_move = 0x6ffffffa, - SHT_SUNW_COMDAT = 0x6ffffffb, - SHT_SUNW_syminfo = 0x6ffffffc, - SHT_SUNW_verdef = 0x6ffffffd, - SHT_SUNW_verneed = 0x6ffffffe, - SHT_SUNW_versym = 0x6fffffff, - - // http://llvm.org/doxygen/namespacellvm_1_1ELF.html - SHT_ANDROID_REL = 0x60000001, - SHT_ANDROID_RELA = 0x60000002, -}; - -// section by index 0 == -// { 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 }; - -enum elf_SHF -{ - SHF_WRITE = (1 << 0), // writable data - SHF_ALLOC = (1 << 1), // occupies memory - SHF_EXECINSTR = (1 << 2), // machine instruction - - SHF_MERGE = (1 << 4), // can be merged - SHF_STRINGS = (1 << 5), // contains nul-terminated strings - SHF_INFO_LINK = (1 << 6), // sh_info contains SHT index - SHF_LINK_ORDER = (1 << 7), // preserve order after combining - SHF_OS_NONCONFORMING = (1 << 8), // non-standard os specific handling required - SHF_GROUP = (1 << 9), // section is memory of a group - SHF_TLS = (1 << 10), // section holds thread-local data - SHF_COMPRESSED = (1 << 11), // section containing compressed data - - SHF_MASKOS = 0x0ff00000, // os specific - SHF_MASKPROC = 0xf0000000, // processor specific -}; - -enum elf_GRP -{ - GRP_COMDAT = 0x00000001, // This is a COMDAT group. - GRP_MASKOS = 0x0ff00000, // OS-specific flags - GRP_MASKPROC = 0xf0000000, // Processor-specific flags -}; - -// COMDAT selection criteria. -// (value of sh_info of a SHT_COMDAT section) -// ref: OS/2 Application Binary Interface for PowerPC (32-bit) -enum elf_COMDAT -{ - COMDAT_NONE = 0, // Invalid selection criteria. - COMDAT_NOMATCH =1, // Only one instance of a SHT_COMDAT section of the - // given name is allowed. - COMDAT_PICKANY =2, // Pick any instance of a SHT_COMDAT section of the - // given name. - COMDAT_SAMESIZE =3, // Pick any instance of a SHT_COMDAT section of the - // given name but all instances of SHT_COMDAT - // sections of the given name must have the same size. -}; - -struct Elf32_Sym -{ - uint32 st_name; // index in string table - uint32 st_value; // absolute value or addr - uint32 st_size; // 0-unknow or no, elsewere symbol size in bytes - uchar st_info; // type and attribute (thee below) - uchar st_other; // ==0 - uint16 st_shndx; // index in section header table -}; - -#define ELF_ST_BIND(i) ((i)>>4) -#define ELF_ST_TYPE(i) ((i)&0xf) -#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) -/* This macro disassembles and assembles a symbol's visibility into - the st_other field. The STV_ defines specificy the actual visibility. */ -#define ELF_ST_VISIBILITY(v) ((v) & 0x3) - -enum elf_ST_BIND -{ - STB_LOCAL = 0, - STB_GLOBAL = 1, - STB_WEAK = 2, - STB_LOOS = 10, //OS-specific - STB_GNU_UNIQUE = 10, // Symbol is unique in namespace - STB_HIOS = 12, - STB_LOPROC = 13, //processor- - STB_HIPROC = 15, // specific - STB_INVALID = 254 -}; - -enum elf_ST_TYPE -{ - STT_NOTYPE = 0, - STT_OBJECT = 1, // associated with data object - STT_FUNC = 2, // associated with function or execut. code - STT_SECTION = 3, - STT_FILE = 4, // name of source file - STT_COMMON = 5, // Uninitialized common section - STT_TLS = 6, // TLS-data object - STT_LOOS = 10, //OS- - STT_HIOS = 12, // specific - STT_LOPROC = 13, //processor- - STT_HIPROC = 15, // specific - STT_GNU_IFUNC = 10, // Symbol is an indirect code object -}; - -enum elf_ST_VISIBILITY -{ - STV_DEFAULT = 0, /* Visibility is specified by binding type */ - STV_INTERNAL = 1, /* OS specific version of STV_HIDDEN */ - STV_HIDDEN = 2, /* Can only be seen inside currect component */ - STV_PROTECTED = 3, /* Treat as STB_LOCAL inside current component */ -}; - -/* Special values for the st_other field in the symbol table. These - are used in an Irix 5 dynamic symbol table. */ -enum elf_ST_OTHER -{ - STO_DEFAULT = STV_DEFAULT, - STO_INTERNAL = STV_INTERNAL, - STO_HIDDEN = STV_HIDDEN, - STO_PROTECTED = STV_PROTECTED, -/* This bit is used on Irix to indicate a symbol whose definition - is optional - if, at final link time, it cannot be found, no - error message should be produced. */ - STO_OPTIONAL = (1 << 2), -}; - -// relocation -struct Elf32_Rel -{ - uint32 r_offset; // virtual address - uint32 r_info; // type of relocation -}; - -#define ELF32_R_SYM(i) ((i)>>8) -#define ELF32_R_TYPE(i) ((unsigned char)(i)) -#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) - -struct Elf32_Rela -{ - uint32 r_offset; - uint32 r_info; - int32 r_addend; // constant to compute -}; - -struct Elf32_Chdr -{ - uint32 ch_type; - uint32 ch_size; - uint32 ch_addralign; -}; - -//=================Loading & dynamic linking======================== -// program header -struct Elf32_Phdr -{ - uint32 p_type; //Segment type. see below - uint32 p_offset; //from beginning of file at 1 byte of segment resides - uint32 p_vaddr; //virtual addr of 1 byte - uint32 p_paddr; //reserved for system - uint32 p_filesz; //may be 0 - uint32 p_memsz; //my be 0 - uint32 p_flags; // for PT_LOAD access mask (PF_xxx) - uint32 p_align; //0/1-no, -}; - -enum elf_SEGFLAGS -{ - PF_X = (1 << 0), // Segment is executable - PF_W = (1 << 1), // Segment is writable - PF_R = (1 << 2), // Segment is readable - - // PaX flags (for PT_PAX_FLAGS) - PF_PAGEEXEC = (1 << 4), // Enable PAGEEXEC - PF_NOPAGEEXEC = (1 << 5), // Disable PAGEEXEC - PF_SEGMEXEC = (1 << 6), // Enable SEGMEXEC - PF_NOSEGMEXEC = (1 << 7), // Disable SEGMEXEC - PF_MPROTECT = (1 << 8), // Enable MPROTECT - PF_NOMPROTECT = (1 << 9), // Disable MPROTECT - PF_RANDEXEC = (1 << 10), // Enable RANDEXEC - PF_NORANDEXEC = (1 << 11), // Disable RANDEXEC - PF_EMUTRAMP = (1 << 12), // Enable EMUTRAMP - PF_NOEMUTRAMP = (1 << 13), // Disable EMUTRAMP - PF_RANDMMAP = (1 << 14), // Enable RANDMMAP - PF_NORANDMMAP = (1 << 15), // Disable RANDMMAP - - PF_MASKOS = 0x0FF00000, // OS-specific reserved bits - PF_MASKPROC = 0xF0000000, // Processor-specific reserved bits -}; - -enum elf_SEGTYPE -{ - PT_NULL = 0, //ignore entries in program table - PT_LOAD = 1, //loadable segmen described in _filesz & _memsz - PT_DYNAMIC = 2, //dynamic linking information - PT_INTERP = 3, //path name to interpreter (loadable) - PT_NOTE = 4, //auxilarry information - PT_SHLIB = 5, //reserved. Has no specified semantics - PT_PHDR = 6, //location & size program header table - PT_TLS = 7, //Thread local storage segment - PT_LOOS = 0x60000000ul, // OS- - PT_HIOS = 0x6ffffffful, // specific - PT_LOPROC = 0x70000000ul, // processor- - PT_HIPROC = 0x7ffffffful, // specific - // - PT_PAX_FLAGS = (PT_LOOS + 0x5041580), // PaX flags - - // From binutils-2.27/elfcpp/elfcpp.h - // The remaining values are not in the standard. - PT_GNU_EH_FRAME = 0x6474e550, // Frame unwind information. - PT_GNU_STACK = 0x6474e551, // Stack flags. - PT_GNU_RELRO = 0x6474e552, // Read only after relocation. - - // http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-83432.html#OSLLGchapter6-69880 - PT_SUNW_UNWIND = 0x6464e550, - PT_SUNW_EH_FRAME = 0x6474e550, - PT_SUNWBSS = 0x6ffffffa, - PT_SUNWSTACK = 0x6ffffffb, - PT_SUNWDTRACE = 0x6ffffffc, - PT_SUNWCAP = 0x6ffffffd, -}; - -//=================Dynamic section=============================== -struct Elf32_Dyn -{ - int32 d_tag; //see below - union - { - uint32 d_val; //integer value with various interpretation - uint32 d_ptr; //programm virtual adress - } d_un; -}; -//extern Elf32_Dyn _DYNAMIC[]; - -enum elf_DTAG -{ - DT_NULL = 0, //(-) end ofd _DYNAMIC array - DT_NEEDED = 1, //(v) str-table offset name to needed library - DT_PLTRELSZ = 2, //(v) tot.size in bytes of relocation entries - DT_PLTGOT = 3, //(p) see below - DT_HASH = 4, //(p) addr. of symbol hash table - DT_STRTAB = 5, //(p) addr of string table - DT_SYMTAB = 6, //(p) addr of symbol table - DT_RELA = 7, //(p) addr of relocation table - DT_RELASZ = 8, //(v) size in bytes of DT_RELA table - DT_RELAENT = 9, //(v) size in bytes of DT_RELA entry - DT_STRSZ = 10, //(v) size in bytes of string table - DT_SYMENT = 11, //(v) size in byte of symbol table entry - DT_INIT = 12, //(p) addr. of initialization function - DT_FINI = 13, //(p) addr. of termination function - DT_SONAME = 14, //(v) offs in str.-table - name of shared object - DT_RPATH = 15, //(v) offs in str-table - search patch - DT_SYMBOLIC = 16, //(-) start search of shared object - DT_REL = 17, //(p) similar to DT_RELA - DT_RELSZ = 18, //(v) tot.size in bytes of DT_REL - DT_RELENT = 19, //(v) size in bytes of DT_REL entry - DT_PLTREL = 20, //(v) type of relocation (DT_REL or DT_RELA) - DT_DEBUG = 21, //(p) not specified - DT_TEXTREL = 22, //(-) segment permisson - DT_JMPREL = 23, //(p) addr of dlt procedure (if present) - DT_BIND_NOW = 24, - DT_INIT_ARRAY = 25, - DT_FINI_ARRAY = 26, - DT_INIT_ARRAYSZ = 27, - DT_FINI_ARRAYSZ = 28, - DT_RUNPATH = 29, - DT_FLAGS = 30, -#define DF_ORIGIN 0x01 -#define DF_SYMBOLIC 0x02 -#define DF_TEXTREL 0x04 -#define DF_BIND_NOW 0x08 -#define DF_STATIC_TLS 0x10 - DT_ENCODING = 31, - DT_PREINIT_ARRAY = 32, - DT_PREINIT_ARRAYSZ = 33, - DT_LOOS = 0x60000000ul, // OS-specific - DT_HIOS = 0x6ffffffful, // - - // http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-42444.html#OSLLGchapter6-tbl-52 - DT_SUNW_AUXILIARY = 0x6000000d, - DT_SUNW_RTLDINF = 0x6000000e, - DT_SUNW_FILTER = 0x6000000e, - DT_SUNW_CAP = 0x60000010, - DT_SUNW_SYMTAB = 0x60000011, - DT_SUNW_SYMSZ = 0x60000012, - DT_SUNW_ENCODING = 0x60000013, - DT_SUNW_SORTENT = 0x60000013, - DT_SUNW_SYMSORT = 0x60000014, - DT_SUNW_SYMSORTSZ = 0x60000015, - DT_SUNW_TLSSORT = 0x60000016, - DT_SUNW_TLSSORTSZ = 0x60000017, - DT_SUNW_CAPINFO = 0x60000018, - DT_SUNW_STRPAD = 0x60000019, - DT_SUNW_CAPCHAIN = 0x6000001a, - DT_SUNW_LDMACH = 0x6000001b, - DT_SUNW_CAPCHAINENT = 0x6000001d, - DT_SUNW_CAPCHAINSZ = 0x6000001f, - DT_SUNW_PARENT = 0x60000021, - DT_SUNW_ASLR = 0x60000023, - DT_SUNW_RELAX = 0x60000025, - DT_SUNW_NXHEAP = 0x60000029, - DT_SUNW_NXSTACK = 0x6000002b, - - // https://github.com/amplab/ray-core/tree/master/src/tools/relocation_packer - DT_ANDROID_REL = 0x6000000f, - DT_ANDROID_RELSZ = 0x60000010, - DT_ANDROID_RELA = 0x60000011, - DT_ANDROID_RELASZ = 0x60000012, - - // From binutils-2.27/elfcpp/elfcpp.h - // Some of the values below are also present the Oracle documentation. - // All of these types are supported both for GNU and Solaris. - DT_VALRNGLO = 0x6ffffd00ul, - DT_GNU_PRELINKED = 0x6ffffdf5ul, - DT_GNU_CONFLICTSZ = 0x6ffffdf6ul, - DT_GNU_LIBLISTSZ = 0x6ffffdf7ul, - DT_CHECKSUM = 0x6ffffdf8ul, - DT_PLTPADSZ = 0x6ffffdf9ul, - DT_MOVEENT = 0x6ffffdfaul, - DT_MOVESZ = 0x6ffffdfbul, - DT_FEATURE = 0x6ffffdfcul, -#define DTF_1_PARINIT 0x00000001 -#define DTF_1_CONFEXP 0x00000002 - DT_POSFLAG_1 = 0x6ffffdfdul, -#define DF_P1_LAZYLOAD 0x00000001 -#define DF_P1_GROUPPERM 0x00000002 - DT_SYMINSZ = 0x6ffffdfeul, - DT_SYMINENT = 0x6ffffdfful, - DT_VALRNGHI = 0x6ffffdfful, - DT_ADDRRNGLO = 0x6ffffe00ul, - DT_GNU_HASH = 0x6ffffef5ul, // GNU-style hash table. - DT_TLSDESC_PLT = 0x6ffffef6ul, - DT_TLSDESC_GOT = 0x6ffffef7ul, - DT_GNU_CONFLICT = 0x6ffffef8ul, // Start of conflict section - DT_GNU_LIBLIST = 0x6ffffef9ul, - DT_CONFIG = 0x6ffffefaul, - DT_DEPAUDIT = 0x6ffffefbul, - DT_AUDIT = 0x6ffffefcul, - DT_PLTPAD = 0x6ffffefdul, - DT_MOVETAB = 0x6ffffefeul, - DT_SYMINFO = 0x6ffffefful, - DT_ADDRRNGHI = 0x6ffffefful, - DT_RELACOUNT = 0x6ffffff9ul, - DT_RELCOUNT = 0x6ffffffaul, - DT_FLAGS_1 = 0x6ffffffbul, -#define DF_1_NOW 0x00000001 -#define DF_1_GLOBAL 0x00000002 -#define DF_1_GROUP 0x00000004 -#define DF_1_NODELETE 0x00000008 -#define DF_1_LOADFLTR 0x00000010 -#define DF_1_INITFIRST 0x00000020 -#define DF_1_NOOPEN 0x00000040 -#define DF_1_ORIGIN 0x00000080 -#define DF_1_DIRECT 0x00000100 -#define DF_1_TRANS 0x00000200 -#define DF_1_INTERPOSE 0x00000400 -#define DF_1_NODEFLIB 0x00000800 -#define DF_1_NODUMP 0x00001000 -#define DF_1_CONFALT 0x00002000 -#define DF_1_ENDFILTEE 0x00004000 -#define DF_1_DISPRELDNE 0x00008000 -#define DF_1_DISPRELPND 0x00010000 -#define DF_1_NODIRECT 0x00020000 -#define DF_1_IGNMULDEF 0x00040000 -#define DF_1_NOKSYMS 0x00080000 -#define DF_1_NOHDR 0x00100000 -#define DF_1_EDITED 0x00200000 -#define DF_1_NORELOC 0x00400000 -#define DF_1_SYMINTPOSE 0x00800000 -#define DF_1_GLOBAUDIT 0x01000000 -#define DF_1_SINGLETON 0x02000000 -#define DF_1_STUB 0x04000000 -#define DF_1_PIE 0x08000000 -#define DF_1_KMOD 0x10000000 -#define DF_1_WEAKFILTER 0x20000000 -#define DF_1_NOCOMMON 0x40000000 - DT_VERDEF = 0x6ffffffcul, - DT_VERDEFNUM = 0x6ffffffdul, - DT_VERNEED = 0x6ffffffeul, - DT_VERNEEDNUM = 0x6ffffffful, - DT_VERSYM = 0x6ffffff0ul, - - // - DT_LOPROC = 0x70000000ul, //(?) processor- - DT_HIPROC = 0x7ffffffful, //(?) specific - - // - DT_AUXILIARY = 0x7ffffffdul, - DT_USED = 0x7ffffffeul, - DT_FILTER = 0x7ffffffful, -}; - -//---------------------------------------------------------------------- -// ELF Notes - -enum -{ - NT_GNU_ABI_TAG = 1, - NT_GNU_HWCAP = 2, - NT_GNU_BUILD_ID = 3, - NT_GNU_GOLD_VERSION = 4, - NT_GNU_PROPERTY_TYPE_0 = 5, -}; - -#define NT_PRSTATUS 1 -#define NT_FPREGSET 2 -#define NT_PRPSINFO 3 -#define NT_TASKSTRUCT 4 -#define NT_AUXV 6 -#define NT_PRXFPREG 0x46e62b7f -#define NT_PPC_VMX 0x100 -#define NT_PPC_VSX 0x102 -#define NT_PPC_TAR 0x103 -#define NT_PPC_PPR 0x104 -#define NT_PPC_DSCR 0x105 -#define NT_PPC_EBB 0x106 -#define NT_PPC_PMU 0x107 -#define NT_PPC_TM_CGPR 0x108 -#define NT_PPC_TM_CFPR 0x109 -#define NT_PPC_TM_CVMX 0x10a -#define NT_PPC_TM_CVSX 0x10b -#define NT_PPC_TM_SPR 0x10c -#define NT_PPC_TM_CTAR 0x10d -#define NT_PPC_TM_CPPR 0x10e -#define NT_PPC_TM_CDSCR 0x10f -#define NT_386_TLS 0x200 -#define NT_386_IOPERM 0x201 -#define NT_X86_XSTATE 0x202 -#define NT_S390_HIGH_GPRS 0x300 -#define NT_S390_TIMER 0x301 -#define NT_S390_TODCMP 0x302 -#define NT_S390_TODPREG 0x303 -#define NT_S390_CTRS 0x304 -#define NT_S390_PREFIX 0x305 -#define NT_S390_LAST_BREAK 0x306 -#define NT_S390_SYSTEM_CALL 0x307 -#define NT_S390_TDB 0x308 -#define NT_S390_VXRS_LOW 0x309 -#define NT_S390_VXRS_HIGH 0x30a -#define NT_S390_GS_CB 0x30b -#define NT_S390_GS_BC 0x30c -#define NT_ARM_VFP 0x400 -#define NT_ARM_TLS 0x401 -#define NT_ARM_HW_BREAK 0x402 -#define NT_ARM_HW_WATCH 0x403 -#define NT_ARM_SVE 0x405 -#define NT_SIGINFO 0x53494749 -#define NT_FILE 0x46494c45 - -#define NT_PSTATUS 10 -#define NT_FPREGS 12 -#define NT_PSINFO 13 -#define NT_LWPSTATUS 16 -#define NT_LWPSINFO 17 -#define NT_WIN32PSTATUS 18 - -//===============================elf64 types============================= -struct Elf64_Ehdr -{ - elf_ident_t e_ident; - uint16 e_type; - uint16 e_machine; - uint32 e_version; - uint64 e_entry; // Entry point virtual address - uint64 e_phoff; // Program header table file offset - uint64 e_shoff; // Section header table file offset - uint32 e_flags; - uint16 e_ehsize; - uint16 e_phentsize; - uint16 e_phnum; - uint16 e_shentsize; - uint16 e_shnum; - uint16 e_shstrndx; -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Ehdr); - -struct Elf64_Shdr -{ - uint32 sh_name; // Section name, index in string tbl - uint32 sh_type; // Type of section - uint64 sh_flags; // Miscellaneous section attributes - uint64 sh_addr; // Section virtual addr at execution - uint64 sh_offset; // Section file offset - uint64 sh_size; // Size of section in bytes - uint32 sh_link; // Index of another section - uint32 sh_info; // Additional section information - uint64 sh_addralign; // Section alignment - uint64 sh_entsize; // Entry size if section holds table -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Shdr); - -// -struct Elf64_Sym -{ - uint32 st_name; // Symbol name, index in string tbl - uint8 st_info; // Type and binding attributes - uint8 st_other; // No defined meaning, 0 - uint16 st_shndx; // Associated section index - uint64 st_value; // Value of the symbol - uint64 st_size; // Associated symbol size -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Sym); - -struct Elf64_Rel -{ - uint64 r_offset; // Location at which to apply the action - uint64 r_info; // index and type of relocation -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Rel); - -struct Elf64_Rela -{ - uint64 r_offset; // Location at which to apply the action - uint64 r_info; // index and type of relocation - int64 r_addend; // Constant addend used to compute value -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Rela); - -struct Elf64_Chdr -{ - uint32 ch_type; - uint32 ch_reserved; - uint64 ch_size; - uint64 ch_addralign; -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Chdr); - - -//#define ELF64_R_SYM(i) ((i) >> 32) -//#define ELF64_R_TYPE(i) ((i) & 0xffffffff) -//#define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 32) + (bfd_vma) (t)) -#define ELF64_R_SYM(i) uint32((i) >> 32) -#define ELF64_R_TYPE(i) uint32(i) - - -struct Elf64_Phdr -{ - uint32 p_type; - uint32 p_flags; - uint64 p_offset; // Segment file offset - uint64 p_vaddr; // Segment virtual address - uint64 p_paddr; // Segment physical address - uint64 p_filesz; // Segment size in file - uint64 p_memsz; // Segment size in memory - uint64 p_align; // Segment alignment, file & memory -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Phdr); - -struct Elf64_Dyn -{ - uint64 d_tag; // entry tag value - uint64 d_un; -}; -DECLARE_TYPE_AS_MOVABLE(Elf64_Dyn); -//extern Elf64_Dyn _DYNAMIC[]; - -//======================================================================= -// Version information types - -struct Elf_Verdef -{ - uint16 vd_version; - uint16 vd_flags; - uint16 vd_ndx; - uint16 vd_cnt; - uint32 vd_hash; - uint32 vd_aux; - uint32 vd_next; -}; -DECLARE_TYPE_AS_MOVABLE(Elf_Verdef); - -// Flags for vd_flags -#define VER_FLG_BASE 0x1 -#define VER_FLG_WEAK 0x2 -#define VER_FLG_INFO 0x4 - -struct Elf_Verdaux -{ - uint32 vda_name; - uint32 vda_next; -}; -DECLARE_TYPE_AS_MOVABLE(Elf_Verdaux); - -struct Elf_Verneed -{ - uint16 vn_version; - uint16 vn_cnt; - uint32 vn_file; - uint32 vn_aux; - uint32 vn_next; -}; -DECLARE_TYPE_AS_MOVABLE(Elf_Verneed); - -struct Elf_Vernaux -{ - uint32 vna_hash; - uint16 vna_flags; - uint16 vna_other; - uint32 vna_name; - uint32 vna_next; -}; -DECLARE_TYPE_AS_MOVABLE(Elf_Vernaux); - -//======================================================================= -// Definitions for other modules - -#define ELFNODE "$ elfnode" // value: Elf64_Ehdr -#define ELF_PHT_TAG 'p' // supval(idx): Elf64_Phdr -#define ELF_SHT_TAG 's' // supval(idx): Elf64_Shdr -#define GOTNODE "$ got" // altval(0): GOT address + 1 - // altval(-1): size of the local GOT part (MIPS only) -#define TLSNODE "$ tls" // altval(0): the TLS template address + 1 - // altval(-1): size of the TLS template - // see tlsinfo2_t::create_tls_template() -#define ATTRNODE "$ attributes" // hashval(vendorname) - nodeidx of netnode with attribute list - // in that node: - // supval(tag): string value - // altval(tag): integer value + 1 - // Tag_compatibility uses both - // Tag_also_compatible_with (for 'aeabi') stores sub-tag number in default altval - // and its value in supval('c') or altval('c') -#define ELFSEGMMAPPINGS "$ elfsegmmap" // Holds a list of mappings for segments, conceptually of the form: - // (wanted_start_ea, wanted_size, mapped_start_ea) - // Note: Only the segments whose mapped EA is *not* the EA that the - // binary file advertises for that segment will be present in - // this netnode, not all segments. - // This netnode should be iterated on using altfirst/altnext. - // - // idx: wanted_start_ea - // altval(idx): mapped_start_ea - // altval(idx, 's'): wanted_size - -#define ATTR_VENDOR_EABI "aeabi" -#define ATTR_VENDOR_GNU "gnu" -#define ATTR_VENDOR_ARM "ARM" - -#pragma pack(pop) -#endif // __ELFBASE_H__ diff --git a/idasdk75/ldr/elf/elfr_arm.h b/idasdk75/ldr/elf/elfr_arm.h deleted file mode 100644 index 8714585..0000000 --- a/idasdk75/ldr/elf/elfr_arm.h +++ /dev/null @@ -1,548 +0,0 @@ -#ifndef __ELFR_ARM_H__ -#define __ELFR_ARM_H__ - -#include <map> -#include <set> - -#ifndef __ELFBASE_H__ -#include "elfbase.h" -#endif - -// relocation field - word32 with HIGH BYTE FIRST!!! -// A- from Elf32_Rela -// B- Loading address of shared object (REAL section when symbol defined) -// (not) G- offset into global objet table -// (not) GOT- adress of global object table -// (not) L- linkage table entry -// P- place of storage unit (computed using r_offset) -// S- value of symbol -enum elf_RTYPE_arm -{ - - R_ARM_NONE = 0, //No reloc - R_ARM_PC24 = 1, // S-P+A (relative 26 bit branch) - R_ARM_ABS32 = 2, // S+A - R_ARM_REL32 = 3, // S-P+A - R_ARM_LDR_PC_G0 = 4, // S-P+A - R_ARM_ABS16 = 5, // S+A - R_ARM_ABS12 = 6, // S+A - R_ARM_THM_ABS5 = 7, // S+A - R_ARM_ABS8 = 8, // S+A - R_ARM_SBREL32 = 9, // S-B+A - R_ARM_THM_CALL = 10, // S-P+A - R_ARM_THM_PC8 = 11, // S-P+A - R_ARM_BREL_ADJ = 12, // S-B+A - R_ARM_TLS_DESC = 13, // - R_ARM_THM_SWI8 = 14, // S+A (obsolete) - R_ARM_XPC25 = 15, // S-P+A (obsolete) - R_ARM_THM_XPC22 = 16, // S-P+A (obsolete) - R_ARM_TLS_DTPMOD32 = 17, /* ID of module containing symbol */ - R_ARM_TLS_DTPOFF32 = 18, /* Offset in TLS block */ - R_ARM_TLS_TPOFF32 = 19, /* Offset in static TLS block */ -// linux-specific - R_ARM_COPY = 20, // none (copy symbol at runtime) - R_ARM_GLOB_DAT = 21, // S (create .got entry) - R_ARM_JUMP_SLOT = 22, // S (create .plt entry) - R_ARM_RELATIVE = 23, // B+A (adjust by programm base) - R_ARM_GOTOFF32 = 24, // S+A-GOT (32bit offset to .got) - R_ARM_BASE_PREL = 25, // B+A-P - R_ARM_GOT_BREL = 26, // G+A-GOT (32bit .got entry) - R_ARM_PLT32 = 27, // L+A-P (32bit .plt entry) - - R_ARM_CALL = 28, - R_ARM_JUMP24 = 29, - R_ARM_THM_JUMP24 = 30, // ((S + A) | T) - P - R_ARM_BASE_ABS = 31, // B + A - R_ARM_ALU_PCREL7_0 = 32, - R_ARM_ALU_PCREL15_8 = 33, - R_ARM_ALU_PCREL23_15 = 34, - R_ARM_LDR_SBREL_11_0 = 35, - R_ARM_ALU_SBREL_19_12 = 36, - R_ARM_ALU_SBREL_27_20 = 37, - R_ARM_TARGET1 = 38, - R_ARM_ROSEGREL32 = 39, - R_ARM_V4BX = 40, - R_ARM_TARGET2 = 41, - R_ARM_PREL31 = 42, - R_ARM_MOVW_ABS_NC = 43, // Static ARM (S + A) | T - R_ARM_MOVT_ABS = 44, // Static ARM S + A - R_ARM_MOVW_PREL_NC = 45, // Static ARM ((S + A) | T) - P - R_ARM_MOVT_PREL = 46, // Static ARM S + A - P - R_ARM_THM_MOVW_ABS_NC = 47, // Static Thumb32 (S + A) | T - R_ARM_THM_MOVT_ABS = 48, // Static Thumb32 S + A - R_ARM_THM_MOVW_PREL_NC= 49, // Static Thumb32 ((S + A) | T) - P - R_ARM_THM_MOVT_PREL = 50, // Static Thumb32 S + A - P - R_ARM_THM_JUMP19 = 51, // Static Thumb32 ((S + A) | T) - P - R_ARM_THM_JUMP6 = 52, // Static Thumb16 S + A - P - R_ARM_THM_ALU_PREL_11_0= 53, // Static Thumb32 ((S + A) | T) - Pa - R_ARM_THM_PC12 = 54, // Static Thumb32 S + A - Pa - R_ARM_ABS32_NOI = 55, // Static Data S + A - R_ARM_REL32_NOI = 56, // Static Data S + A - P - R_ARM_ALU_PC_G0_NC = 57, // Static ARM ((S + A) | T) - P - R_ARM_ALU_PC_G0 = 58, // Static ARM ((S + A) | T) - P - R_ARM_ALU_PC_G1_NC = 59, // Static ARM ((S + A) | T) - P - R_ARM_ALU_PC_G1 = 60, // Static ARM ((S + A) | T) - P - R_ARM_ALU_PC_G2 = 61, // Static ARM ((S + A) | T) - P - R_ARM_LDR_PC_G1 = 62, // Static ARM S + A - P - R_ARM_LDR_PC_G2 = 63, // Static ARM S + A - P - R_ARM_LDRS_PC_G0 = 64, // Static ARM S + A - P - - R_ARM_LDRS_PC_G1 = 65, // Static ARM S + A - P - R_ARM_LDRS_PC_G2 = 66, // Static ARM S + A - P - R_ARM_LDC_PC_G0 = 67, // Static ARM S + A - P - R_ARM_LDC_PC_G1 = 68, // Static ARM S + A - P - R_ARM_LDC_PC_G2 = 69, // Static ARM S + A - P - R_ARM_ALU_SB_G0_NC = 70, // Static ARM ((S + A) | T) - B(S) - R_ARM_ALU_SB_G0 = 71, // Static ARM ((S + A) | T) - B(S) - R_ARM_ALU_SB_G1_NC = 72, // Static ARM ((S + A) | T) - B(S) - R_ARM_ALU_SB_G1 = 73, // Static ARM ((S + A) | T) - B(S) - R_ARM_ALU_SB_G2 = 74, // Static ARM ((S + A) | T) - B(S) - R_ARM_LDR_SB_G0 = 75, // Static ARM S + A - B(S) - R_ARM_LDR_SB_G1 = 76, // Static ARM S + A - B(S) - R_ARM_LDR_SB_G2 = 77, // Static ARM S + A - B(S) - R_ARM_LDRS_SB_G0 = 78, // Static ARM S + A - B(S) - R_ARM_LDRS_SB_G1 = 79, // Static ARM S + A - B(S) - R_ARM_LDRS_SB_G2 = 80, // Static ARM S + A - B(S) - R_ARM_LDC_SB_G0 = 81, // Static ARM S + A - B(S) - R_ARM_LDC_SB_G1 = 82, // Static ARM S + A - B(S) - R_ARM_LDC_SB_G2 = 83, // Static ARM S + A - B(S) - R_ARM_MOVW_BREL_NC = 84, // Static ARM ((S + A) | T) - B(S) - R_ARM_MOVT_BREL = 85, // Static ARM S + A - B(S) - R_ARM_MOVW_BREL = 86, // Static ARM ((S + A) | T) - B(S) - R_ARM_THM_MOVW_BREL_NC = 87, // Static Thumb32 ((S + A) | T) - B(S) - R_ARM_THM_MOVT_BREL = 88, // Static Thumb32 S + A - B(S) - R_ARM_THM_MOVW_BREL = 89, // Static Thumb32 ((S + A) | T) - B(S) - R_ARM_TLS_GOTDESC = 90, // Static Data - R_ARM_TLS_CALL = 91, // Static ARM - R_ARM_TLS_DESCSEQ = 92, // Static ARM TLS relaxation - R_ARM_THM_TLS_CALL = 93, // Static Thumb32 - R_ARM_PLT32_ABS = 94, // Static Data PLT(S) + A - - R_ARM_GOT_ABS = 95, // G+A - R_ARM_GOT_PREL = 96, // G+A-P - R_ARM_GOT_BREL12 = 97, // G+A-GOT - R_ARM_GOTOFF12 = 98, // S+A-GOT - R_ARM_GOTRELAX = 99, - R_ARM_GNU_VTENTRY = 100, - R_ARM_GNU_VTINHERIT = 101, - - R_ARM_THM_PC11 = 102, /* Cygnus extension to abi: Thumb unconditional branch. */ - R_ARM_THM_PC9 = 103, /* Cygnus extension to abi: Thumb conditional branch. */ - R_ARM_THM_JUMP11 = 102, // Static Thumb16 S + A - P - R_ARM_THM_JUMP8 = 103, // Static Thumb16 S + A - P - R_ARM_TLS_GD32 = 104, // Static Data GOT(S) + A - P - R_ARM_TLS_LDM32 = 105, // Static Data GOT(S) + A - P - R_ARM_TLS_LDO32 = 106, // Static Data S + A - TLS - R_ARM_TLS_IE32 = 107, // Static Data GOT(S) + A - P - R_ARM_TLS_LE32 = 108, // Static Data S + A - tp - R_ARM_TLS_LDO12 = 109, // Static ARM S + A - TLS - R_ARM_TLS_LE12 = 110, // Static ARM S + A - tp - R_ARM_TLS_IE12GP = 111, // Static ARM GOT(S) + A - GOT_ORG - R_ARM_PRIVATE_0 = 112, // Private (n = 0, 1, ... 15) - R_ARM_PRIVATE_1 = 113, - R_ARM_PRIVATE_2 = 114, - R_ARM_PRIVATE_3 = 115, - R_ARM_PRIVATE_4 = 116, - R_ARM_PRIVATE_5 = 117, - R_ARM_PRIVATE_6 = 118, - R_ARM_PRIVATE_7 = 119, - R_ARM_PRIVATE_8 = 120, - R_ARM_PRIVATE_9 = 121, - R_ARM_PRIVATE_10 = 122, - R_ARM_PRIVATE_11 = 123, - R_ARM_PRIVATE_12 = 124, - R_ARM_PRIVATE_13 = 125, - R_ARM_PRIVATE_14 = 126, - R_ARM_PRIVATE_15 = 127, - R_ARM_ME_TOO = 128, // Obsolete - R_ARM_THM_TLS_DESCSEQ16 = 129,// Static Thumb16 - R_ARM_THM_TLS_DESCSEQ32 = 130,// Static Thumb32 - R_ARM_THM_GOT_BREL12 = 131, // GOT entry relative to GOT origin, 12 bit (Thumb32 LDR). - R_ARM_THM_ALU_ABS_G0_NC = 132, - R_ARM_THM_ALU_ABS_G1_NC = 133, - R_ARM_THM_ALU_ABS_G2_NC = 134, - R_ARM_THM_ALU_ABS_G3_NC = 135, - - // 136 - 139 Unallocated - // 140 - 159 Dynamic Reserved for future allocation - - R_ARM_IRELATIVE = 160, - - // 161 - 255 Unallocated - -// -//ATT: R_ARM_RXPC25 used ONLY in OLD_ABI (+ 15 OTHER relocs!) -// dynamic sections only - R_ARM_RXPC25 = 249, // (BLX) call between segments -// - R_ARM_RSBREL32 = 250, // (Word) SBrelative offset - R_ARM_THM_RPC22 = 251, // (Thumb BL/BLX) call between segments - R_ARM_RREL32 = 252, // (Word) inter-segment offset - R_ARM_RABS32 = 253, // (Word) Target segment displacement - R_ARM_RPC24 = 254, // (BL/BLX) call between segment - R_ARM_RBASE = 255 // segment being relocated -}; - -// X is the result of a relocation operation, before any masking or bit-selection -// Page(expr) is the page address of the expression expr, defined as (expr & ~0xFFF) -// GOT is the address of the Global Offset Table -// GDAT(S+A) represents a 64-bit entry in the GOT for address S+A -// G(expr) is the address of the GOT entry for the expression expr -// Delta(S) if S is a normal symbol, resolves to the difference between -// the static link address of S and the execution address of S. -// If S is the null symbol (ELF symbol index 0), resolves to the difference -// between the static link address of P and the execution address of P. -// Indirect(expr) represents the result of calling expr as a function. -// The result is the return value from the function that is returned in r0. -// [msb:lsb] is a bit-mask operation representing the selection of bits in a value -enum elf_RTYPE_aarch64 -{ - R_AARCH64_NONE = 0x100, - - //ILP32 relocations - R_AARCH64_P32_ABS32 = 1,/* Direct 32 bit. */ - R_AARCH64_P32_COPY = 180,/* Copy symbol at runtime. */ - R_AARCH64_P32_GLOB_DAT = 181,/* Create GOT entry. */ - R_AARCH64_P32_JUMP_SLOT = 182,/* Create PLT entry. */ - R_AARCH64_P32_RELATIVE = 183,/* Adjust by program base. */ - R_AARCH64_P32_TLS_DTPMOD = 184,/* Module number, 32 bit. */ - R_AARCH64_P32_TLS_DTPREL = 185,/* Module-relative offset, 32 bit. */ - R_AARCH64_P32_TLS_TPREL = 186,/* TP-relative offset, 32 bit. */ - R_AARCH64_P32_TLSDESC = 187,/* TLS Descriptor. */ - R_AARCH64_P32_IRELATIVE = 188,/* STT_GNU_IFUNC relocation. */ - - // 4.6.5 Static Data relocations - R_AARCH64_ABS64 = 0x101, // S + A - R_AARCH64_ABS32 = 0x102, // S + A - R_AARCH64_ABS16 = 0x103, - R_AARCH64_PREL64 = 0x104, - R_AARCH64_PREL32 = 0x105, - R_AARCH64_PREL16 = 0x106, - - // 4.6.6 Static AArch64 relocations - R_AARCH64_MOVW_UABS_G0 = 0x107, - R_AARCH64_MOVW_UABS_G0_NC = 0x108, - R_AARCH64_MOVW_UABS_G1 = 0x109, - R_AARCH64_MOVW_UABS_G1_NC = 0x10a, - R_AARCH64_MOVW_UABS_G2 = 0x10b, - R_AARCH64_MOVW_UABS_G2_NC = 0x10c, - R_AARCH64_MOVW_UABS_G3 = 0x10d, - R_AARCH64_MOVW_SABS_G0 = 0x10e, - R_AARCH64_MOVW_SABS_G1 = 0x10f, - R_AARCH64_MOVW_SABS_G2 = 0x110, - - R_AARCH64_LD_PREL_LO19 = 0x111, - R_AARCH64_ADR_PREL_LO21 = 0x112, - R_AARCH64_ADR_PREL_PG_HI21 = 0x113, // Page(S+A) - Page(P); Set an ADRP immediate value to bits [32:12] of the X - R_AARCH64_ADR_PREL_PG_HI21_NC = 0x114, - R_AARCH64_ADD_ABS_LO12_NC = 0x115, // S+A; Set an ADD immediate value to bits [11:0] of X - R_AARCH64_LDST8_ABS_LO12_NC = 0x116, - - R_AARCH64_TSTBR14 = 0x117, - R_AARCH64_CONDBR19 = 0x118, - R_AARCH64_JUMP26 = 0x11a, // S+A-P; Set a B immediate field to bits [27:2] of X - R_AARCH64_CALL26 = 0x11b, // S+A-P; Set a CALL immediate field to bits [27:2] of X - - R_AARCH64_LDST16_ABS_LO12_NC = 0x11c, - R_AARCH64_LDST32_ABS_LO12_NC = 0x11d, - R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, // S+A; Set the LD/ST immediate value to bits [11:3] of X - - R_AARCH64_MOVW_PREL_G0 = 0x11f, - R_AARCH64_MOVW_PREL_G0_NC = 0x120, - R_AARCH64_MOVW_PREL_G1 = 0x121, - R_AARCH64_MOVW_PREL_G1_NC = 0x122, - R_AARCH64_MOVW_PREL_G2 = 0x123, - R_AARCH64_MOVW_PREL_G2_NC = 0x124, - R_AARCH64_MOVW_PREL_G3 = 0x125, - - R_AARCH64_LDST128_ABS_LO12_NC = 0x12b, - - R_AARCH64_MOVW_GOTOFF_G0 = 0x12c, - R_AARCH64_MOVW_GOTOFF_G0_NC = 0x12d, - R_AARCH64_MOVW_GOTOFF_G1 = 0x12e, - R_AARCH64_MOVW_GOTOFF_G1_NC = 0x12f, - R_AARCH64_MOVW_GOTOFF_G2 = 0x130, - R_AARCH64_MOVW_GOTOFF_G2_NC = 0x131, - R_AARCH64_MOVW_GOTOFF_G3 = 0x132, - - R_AARCH64_GOTREL64 = 0x133, - R_AARCH64_GOTREL32 = 0x134, - - R_AARCH64_GOT_LD_PREL19 = 0x135, - R_AARCH64_LD64_GOTOFF_LO15 = 0x136, - R_AARCH64_ADR_GOT_PAGE = 0x137, // Page(G(GDAT(S+A)))-Page(P); Set the immediate value of an ADRP to bits [32:12] of X - R_AARCH64_LD64_GOT_LO12_NC = 0x138, // G(GDAT(S+A)); Set the LD/ST immediate field to bits [11:3] of X - R_AARCH64_LD64_GOTPAGE_LO15 = 0x139, - - R_AARCH64_TLSGD_ADR_PREL21 = 0x200, - R_AARCH64_TLSGD_ADR_PAGE21 = 0x201, - R_AARCH64_TLSGD_ADD_LO12_NC = 0x202, - R_AARCH64_TLSGD_MOVW_G1 = 0x203, - R_AARCH64_TLSGD_MOVW_G0_NC = 0x204, - - R_AARCH64_TLSLD_ADR_PREL21 = 0x205, - R_AARCH64_TLSLD_ADR_PAGE21 = 0x206, - R_AARCH64_TLSLD_ADD_LO12_NC = 0x207, - R_AARCH64_TLSLD_MOVW_G1 = 0x208, - R_AARCH64_TLSLD_MOVW_G0_NC = 0x209, - R_AARCH64_TLSLD_LD_PREL19 = 0x20a, - R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b, - R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c, - R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d, - R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e, - R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f, - R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210, - R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211, - R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212, - R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213, - R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214, - R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215, - R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216, - R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217, - R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218, - R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219, - R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a, - - R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b, - R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c, - R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d, - R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e, - R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f, - - R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220, - R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221, - R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222, - R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223, - R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224, - R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225, - R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226, - R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227, - R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228, - R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229, - R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a, - R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b, - R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c, - R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d, - R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e, - R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f, - - R_AARCH64_TLSDESC_LD_PREL19 = 0x230, - R_AARCH64_TLSDESC_ADR_PREL21 = 0x231, - R_AARCH64_TLSDESC_ADR_PAGE21 = 0x232, // R_AARCH64_TLSDESC_ADR_PAGE - R_AARCH64_TLSDESC_LD64_LO12 = 0x233, // R_AARCH64_TLSDESC_LD64_LO12_NC - R_AARCH64_TLSDESC_ADD_LO12 = 0x234, // R_AARCH64_TLSDESC_ADD_LO12_NC - R_AARCH64_TLSDESC_OFF_G1 = 0x235, - R_AARCH64_TLSDESC_OFF_G0_NC = 0x236, - R_AARCH64_TLSDESC_LDR = 0x237, - R_AARCH64_TLSDESC_ADD = 0x238, - R_AARCH64_TLSDESC_CALL = 0x239, - - R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 0x23a, - R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 0x23b, - - R_AARCH64_TLSLD_LDST128_DTPREL_Lo12 = 0x23c, - R_AARCH64_TLSLD_LDST128_DTPREL_Lo12_NC= 0x23d, - - // 4.6.11 Dynamic relocations - R_AARCH64_COPY = 0x400, - R_AARCH64_GLOB_DAT = 0x401, - R_AARCH64_JUMP_SLOT = 0x402, - R_AARCH64_RELATIVE = 0x403, - R_AARCH64_TLS_DTPREL64 = 0x404, - R_AARCH64_TLS_DTPMOD64 = 0x405, - R_AARCH64_TLS_TPREL64 = 0x406, - R_AARCH64_TLSDESC = 0x407, - R_AARCH64_IRELATIVE = 0x408, -}; - -// Flags: -#define EF_ARM_RELEXEC 0x00000001 // dynamic only how to relocation -#define EF_ARM_HASENTRY 0x00000002 // e_entry is real start address - -// GNU flags (EABI version = 0) -#define EF_ARM_INTERWORK 0x00000004 // interworking enabled -#define EF_ARM_APCS_26 0x00000008 // APCS-26 used (otherwise APCS-32) -#define EF_ARM_APCS_FLOAT 0x00000010 // floats passed in float registers -#define EF_ARM_PIC 0x00000020 // Position-independent code -#define EF_ARM_ALIGN8 0x00000040 // 8-bit struct alignment -#define EF_ARM_NEW_ABI 0x00000080 // New ABI -#define EF_ARM_OLD_ABI 0x00000100 // Old ABI -#define EF_ARM_SOFT_FLOAT 0x00000200 // software FP -#define EF_ARM_VFP_FLOAT 0x00000400 // VFP float format -#define EF_ARM_MAVERICK_FLOAT 0x00000800 // Maverick float format - -// ARM flags: -#define EF_ARM_SYMSARESORTED 0x00000004 // Each subsection of the symbol table is sorted by symbol value (NB conflicts with EF_INTERWORK) -#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 // Symbols in dynamic symbol tables that are defined in sections - // included in program segment n have st_shndx = n + 1. (NB conflicts with EF_APCS26) -#define EF_ARM_MAPSYMSFIRST 0x00000010 // Mapping symbols precede other local symbols in the symbol - // table (NB conflicts with EF_APCS_FLOAT) -#define EF_ARM_LE8 0x00400000 // LE-8 code -#define EF_ARM_BE8 0x00800000 // BE-8 code for ARMv6 or later -#define EF_ARM_EABIMASK 0xFF000000 // ARM EABI version - -/* Additional symbol types for Thumb. */ -#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ -#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ - -// patching GOT loading, -// discard auxiliary values in plt/got -// can present offset bypass segment -#define ELF_RPL_ARM_DEFAULT (ELF_RPL_GL | ELF_DIS_OFFW | ELF_DIS_GPLT) - -enum elf_SHT_ARM -{ - SHT_ARM_EXIDX = 0x70000001, // Exception Index table - SHT_ARM_PREEMPTMAP = 0x70000002, // BPABI DLL dynamic linking pre-emption map - SHT_ARM_ATTRIBUTES = 0x70000003, // Object file compatibility attributes - SHT_ARM_DEBUGOVERLAY = 0x70000004, // - SHT_ARM_OVERLAYSECTION = 0x70000005, // -}; - -enum elf_PT_ARM -{ - // From binutils-2.27/elfcpp/elfcpp.h - PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility information - PT_ARM_EXIDX = 0x70000001, // Exception unwind tables -}; - -enum elf_PT_AARCH64 -{ - // From binutils-2.27/elfcpp/elfcpp.h - PT_AARCH64_ARCHEXT = 0x70000000, // Platform architecture compatibility information - PT_AARCH64_UNWIND = 0x70000001, // Exception unwind tables -}; - -enum eabi_tags_t -{ - Tag_NULL, - Tag_File, // (=1) <uint32: byte-size> <attribute>* - Tag_Section, // (=2) <uint32: byte-size> <section number>* 0 <attribute>* - Tag_Symbol, // (=3) <unit32: byte-size> <symbol number>* 0 <attribute>* - Tag_CPU_raw_name, // (=4), NTBS - Tag_CPU_name, // (=5), NTBS - Tag_CPU_arch, // (=6), uleb128 - Tag_CPU_arch_profile, // (=7), uleb128 - Tag_ARM_ISA_use, // (=8), uleb128 - Tag_THUMB_ISA_use, // (=9), uleb128 - Tag_FP_arch, // (=10), uleb128 (formerly Tag_VFP_arch = 10) - Tag_VFP_arch = Tag_FP_arch, - Tag_WMMX_arch, // (=11), uleb128 - Tag_NEON_arch, // (=12), uleb128 - Tag_PCS_config, // (=13), uleb128 - Tag_ABI_PCS_R9_use, // (=14), uleb128 - Tag_ABI_PCS_RW_data, // (=15), uleb128 - Tag_ABI_PCS_RO_data, // (=16), uleb128 - Tag_ABI_PCS_GOT_use, // (=17), uleb128 - Tag_ABI_PCS_wchar_t, // (=18), uleb128 - Tag_ABI_FP_rounding, // (=19), uleb128 - Tag_ABI_FP_denormal, // (=20), uleb128 - Tag_ABI_FP_exceptions, // (=21), uleb128 - Tag_ABI_FP_user_exceptions, // (=22), uleb128 - Tag_ABI_FP_number_model, // (=23), uleb128 - Tag_ABI_align_needed, // (=24), uleb128 - Tag_ABI_align8_needed = Tag_ABI_align_needed, - Tag_ABI_align_preserved, // (=25), uleb128 - Tag_ABI_align8_preserved = Tag_ABI_align_preserved, - Tag_ABI_enum_size, // (=26), uleb128 - Tag_ABI_HardFP_use, // (=27), uleb128 - Tag_ABI_VFP_args, // (=28), uleb128 - Tag_ABI_WMMX_args, // (=29), uleb128 - Tag_ABI_optimization_goals, // (=30), uleb128 - Tag_ABI_FP_optimization_goals, // (=31), uleb128 - Tag_compatibility, // (=32), uleb128: flag, NTBS: vendor-name - Tag_CPU_unaligned_access=34, // (=34), uleb128 - Tag_FP_HP_extension=36, // (=36), uleb128 (formerly Tag_VFP_HP_extension = 36) - Tag_VFP_HP_extension = Tag_FP_HP_extension, - Tag_ABI_FP_16bit_format=38, // (=38), uleb128 - Tag_MPextension_use=42, // (=42), uleb128 - Tag_DIV_use=44, // (=44), uleb128 - Tag_nodefaults=64, // (=64), uleb128: ignored (write as 0) - Tag_also_compatible_with, // (=65), NTBS: data; ULEB128-encoded tag followed by a value of that tag. - Tag_T2EE_use, // (=66), uleb128 - Tag_conformance, // (=67), string: ABI-version - Tag_Virtualization_use, // (=68), uleb128 - Tag_MPextension_use_legacy=70, // (=70), -}; - -//---------------------------------------------------------------------------- -class arm_arch_specific_t : public arch_specific_t -{ -public: - enum isa_t - { - isa_arm = 1, - isa_thumb - }; - typedef void isa_handler_t( - reader_t &reader, - sym_rel &symbol, - isa_t isa, - bool force); -private: - typedef std::map<uint64, isa_t> section_isa_ranges_t; - typedef std::map<elf_shndx_t, section_isa_ranges_t> isa_ranges_t; - - isa_ranges_t isa_ranges; - std::set<ea_t> forced_isas; - - isa_handler_t *isa_handler = nullptr; - ea_t debug_segbase = 0; - bool has_mapsym = false; - bool track_mapsym = false; - bool be8_code = false; - bool thumb_entry = false; - - void notify_isa(reader_t &reader, sym_rel &symbol, isa_t isa, bool force) - { - if ( isa_handler != NULL ) - isa_handler(reader, symbol, isa, force); - } - - isa_t get_isa(const sym_rel &symbol) const; - void set_isa(const sym_rel &symbol, isa_t isa); - - friend void arm_isa_handler( - reader_t &reader, - sym_rel &symbol, - arm_arch_specific_t::isa_t isa, - bool force); - -public: - virtual ~arm_arch_specific_t() {} - virtual void on_start_symbols(reader_t &reader) override; - virtual void on_symbol_read(reader_t &reader, sym_rel &sym) override; - bool is_mapping_symbol(const char *name) const; - bool has_mapping_symbols() const { return has_mapsym; } - - // Tracking mapping symbols can be useful for - // determining whether a certain function is using - // the Thumb or ARM ISA. - // In some ELF files, the only way to know what ISA - // certain functions are in is by looking at some - // mapping symbols (i.e., '$a', '$t'). - // By default, tracking of such symbols in an - // instance of this class is _not_ enabled. - void set_mapping_symbols_tracking(bool track) { track_mapsym = track; } - bool is_mapping_symbols_tracking() const { return track_mapsym; } - - void set_isa_handler(isa_handler_t *ih, ea_t dea) - { - isa_handler = ih; - debug_segbase = dea; - } - - void set_thumb_entry() { thumb_entry = true; } - bool get_thumb_entry() const { return thumb_entry; } - void set_be8(bool be8) { be8_code = be8; } - bool is_be8() { return be8_code; } -}; - -//---------------------------------------------------------------------------- -// Specific flags that will be set on sym_rel instances. -enum arm_sym_rel_flags -{ - thumb_function = 1 -}; - -#endif diff --git a/idasdk75/ldr/elf/elfr_avr.h b/idasdk75/ldr/elf/elfr_avr.h deleted file mode 100644 index 976bd71..0000000 --- a/idasdk75/ldr/elf/elfr_avr.h +++ /dev/null @@ -1,86 +0,0 @@ -#ifndef __ELFR_AVR_H__ -#define __ELFR_AVR_H__ - -#ifndef __ELFBASE_H__ -#include "elfbase.h" -#endif - -enum elf_RTYPE_avr -{ - R_AVR_NONE = 0, - R_AVR_32 = 1, - R_AVR_7_PCREL = 2, - R_AVR_13_PCREL = 3, - R_AVR_16 = 4, - R_AVR_16PM = 5, - R_AVR_LO8_LDI = 6, - R_AVR_HI8_LDI = 7, - R_AVR_HH8_LDI = 8, - R_AVR_LO8_LDI_NEG = 9, - R_AVR_HI8_LDI_NEG = 10, - R_AVR_HH8_LDI_NEG = 11, - R_AVR_LO8_LDI_PM = 12, - R_AVR_HI8_LDI_PM = 13, - R_AVR_HH8_LDI_PM = 14, - R_AVR_LO8_LDI_PM_NEG = 15, - R_AVR_HI8_LDI_PM_NEG = 16, - R_AVR_HH8_LDI_PM_NEG = 17, - R_AVR_CALL = 18, - // *nix obj's specific - R_AVR_LDI = 19, - R_AVR_6 = 20, - R_AVR_6_ADIW = 21, - R_AVR_MS8_LDI = 22, - R_AVR_MS8_LDI_NEG = 23, - R_AVR_LO8_LDI_GS = 24, - R_AVR_HI8_LDI_GS = 25, - R_AVR_8 = 26, - R_AVR_8_LO8 = 27, - R_AVR_8_HI8 = 28, - R_AVR_8_HLO8 = 29, - R_AVR_DIFF8 = 30, - R_AVR_DIFF16 = 31, - R_AVR_DIFF32 = 32, - R_AVR_LDS_STS_16 = 33, - R_AVR_PORT6 = 34, - R_AVR_PORT5 = 35, - R_AVR_32_PCREL = 36, -}; - -// Flags: -// If bit #7 is set, it is assumed that the elf file uses local symbols -// as reference for the relocations so that linker relaxation is possible. -#define EF_AVR_LINKRELAX_PREPARED 0x80 - -// Processor specific flags for the ELF header e_flags field. -#define EF_AVR_MACH 0x7F -#define E_AVR_MACH_AVR1 1 -#define E_AVR_MACH_AVR2 2 -#define E_AVR_MACH_AVR25 25 -#define E_AVR_MACH_AVR3 3 -#define E_AVR_MACH_AVR31 31 -#define E_AVR_MACH_AVR35 35 -#define E_AVR_MACH_AVR4 4 -#define E_AVR_MACH_AVR5 5 -#define E_AVR_MACH_AVR51 51 -#define E_AVR_MACH_AVR6 6 -#define E_AVR_MACH_XMEGA1 101 -#define E_AVR_MACH_XMEGA2 102 -#define E_AVR_MACH_XMEGA3 103 -#define E_AVR_MACH_XMEGA4 104 -#define E_AVR_MACH_XMEGA5 105 -#define E_AVR_MACH_XMEGA6 106 -#define E_AVR_MACH_XMEGA7 107 - -// netnode flag's and constant -#define AVR_INFO_NODENAME "$ atmel" -#define ELF_AVR_TAG 'f' -#define ELF_AVR_LDI_NEG 1 -#define ELF_AVR_RAM_OFF 2 -#define ELF_AVR_EEP_OFF 3 -#define ELF_AVR_ABS_OFF 4 -#define ELF_AVR_RAMBASE 0x800000 -#define ELF_AVR_EEPROMBASE 0x810000 -#define ELF_AVR_ABSBASE 0x1000000 - -#endif diff --git a/idasdk75/ldr/elf/elfr_mips.h b/idasdk75/ldr/elf/elfr_mips.h deleted file mode 100644 index cd7a0ea..0000000 --- a/idasdk75/ldr/elf/elfr_mips.h +++ /dev/null @@ -1,434 +0,0 @@ -#ifndef __ELFR_MIP_H__ -#define __ELFR_MIP_H__ - -#ifndef __ELFBASE_H__ -#include "elfbase.h" -#endif - -#include "elf.h" - -// -// e_flags -// - -#define EF_MIPS_NOREORDER 0x00000001 // At least one .noreorder directive appears in the source. -#define EF_MIPS_PIC 0x00000002 // File contains position independent code. -#define EF_MIPS_CPIC 0x00000004 // Code in file uses the standard calling sequence for calling osition independent code. -#define EF_MIPS_UGEN_ALLOC 0x00000008 -#define EF_MIPS_UCODE 0x00000010 // Code in file uses UCODE (obsolete) -#define EF_MIPS_ABI2 0x00000020 // Code in file uses new ABI (-n32 on Irix 6). -#define EF_MIPS_DYNAMIC 0x00000040 // MIPS dynamic -#define EF_MIPS_OPTIONS_FIRST 0x00000080 -#define EF_MIPS_32BITMODE 0x00000100 // Indicates code compiled for a 64-bit machine in 32-bit mode. (regs are 32-bits wide.) -#define EF_MIPS_FP64 0x00000200 // 32-bit machine but FP registers are 64-bit (gcc -mfp64) -#define EF_MIPS_NAN2008 0x00000400 // Uses IEE 754-2008 NaN encoding -#define EF_MIPS_ARCH 0xF0000000 // Four bit MIPS architecture field. -#define E_MIPS_ARCH_1 0x00000000 // -mips1 code. -#define E_MIPS_ARCH_2 0x10000000 // -mips2 code. -#define E_MIPS_ARCH_3 0x20000000 // -mips3 code. -#define E_MIPS_ARCH_4 0x30000000 // -mips4 code. -#define E_MIPS_ARCH_5 0x40000000 // -mips5 code. -#define E_MIPS_ARCH_32 0x50000000 // -mips32 code. -#define E_MIPS_ARCH_64 0x60000000 // -mips64 code. -#define E_MIPS_ARCH_32R2 0x70000000 // -mips32r2 -#define E_MIPS_ARCH_64R2 0x80000000 // -mips64r2 -#define E_MIPS_ARCH_32R6 0x90000000 // -mips32r6 -#define E_MIPS_ARCH_64R6 0xA0000000 // -mips64r6 -#define EF_MIPS_ABI 0x0000F000 // The ABI of the file. Also see EF_MIPS_ABI2 above. -#define E_MIPS_ABI_O32 0x00001000 // The original o32 abi. -#define E_MIPS_ABI_O64 0x00002000 // O32 extended to work on 64 bit architectures -#define E_MIPS_ABI_EABI32 0x00003000 // EABI in 32 bit mode -#define E_MIPS_ABI_EABI64 0x00004000 // EABI in 64 bit mode -#define EF_MIPS_ARCH_ASE 0x0F000000 // Architectural Extensions used by this file -#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 // Use MDMX multimedia extensions -#define EF_MIPS_ARCH_ASE_M16 0x04000000 // Use MIPS-16 ISA extensions -#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 // Use microMIPS ISA extensions - -/* Machine variant if we know it. This field was invented at Cygnus, - but it is hoped that other vendors will adopt it. If some standard - is developed, this code should be changed to follow it. */ - -#define EF_MIPS_MACH 0x00FF0000 - -/* Cygnus is choosing values between 80 and 9F; - 00 - 7F should be left for a future standard; - the rest are open. */ - -#define E_MIPS_MACH_3900 0x00810000 // R3900/Toshiba TX39 -#define E_MIPS_MACH_4010 0x00820000 // -#define E_MIPS_MACH_4100 0x00830000 -#define E_MIPS_MACH_4650 0x00850000 -#define E_MIPS_MACH_4120 0x00870000 -#define E_MIPS_MACH_4111 0x00880000 -#define E_MIPS_MACH_MIPS32_4K 0x00890000 -#define E_MIPS_MACH_SB1 0x008A0000 // SiByte SB-1 -#define E_MIPS_MACH_OCTEON 0x008B0000 // Cavium Networks OCTEON -#define E_MIPS_MACH_XLR 0x008C0000 // RMI XLR -#define E_MIPS_MACH_OCTEON2 0x008D0000 // Cavium Networks OCTEON 2 -#define E_MIPS_MACH_OCTEON3 0x008E0000 // Cavium Networks OCTEON 3 -#define E_MIPS_MACH_5400 0x00910000 -#define E_MIPS_MACH_5900 0x00920000 // r5900 (Sony Playstation 2 Emotion Engine) -#define E_MIPS_MACH_5500 0x00980000 -#define E_MIPS_MACH_9000 0x00990000 -#define E_MIPS_MACH_LS2E 0x00A00000 // Loongson/Godson 2E -#define E_MIPS_MACH_LS2F 0x00A10000 // Loongson/Godson 2F -#define E_MIPS_MACH_ALLEGREX 0x00A20000 // Allegrex (Sony PlayStation Portable) -#define E_MIPS_MACH_LS3A 0x00A20000 // Loongson/Godson 3A - -// -// p_flags -// - -#define PF_MIPS_LOCAL 0x10000000 // special p_flags - -// relocation field - word32 with HIGH BYTE FIRST!!! -// A- from Elf32_Rela -// B- Loading address of shared object -// G- offset into global objet table -// GOT- adress of global object table -// L- linkage table entry -// P- plase of storage unit (computed using r_offset) -// S- value of symbol -enum elf_RTYPE_mips -{ - R_MIPS_NONE = 0, //No reloc - R_MIPS_16 = 1, - R_MIPS_32 = 2, //S+A-P Direct32 - R_MIPS_REL = 3, //S+A Relative32 - R_MIPS_26 = 4, //S+A Relative26 - R_MIPS_HI16 = 5, - R_MIPS_LO16 = 6, - R_MIPS_GPREL = 7, //S+A Relative16 - R_MIPS_LITERAL = 8, - R_MIPS_GOT = 9, - R_MIPS_PC16 = 10, - R_MIPS_CALL = 11, //Call16 - R_MIPS_GPREL32 = 12, - - R_MIPS_SHIFT5 = 16, - R_MIPS_SHIFT6 = 17, - R_MIPS_64 = 18, - R_MIPS_GOT_DISP = 19, - R_MIPS_GOT_PAGE = 20, - R_MIPS_GOT_OFST = 21, - R_MIPS_GOT_HI16 = 22, - R_MIPS_GOT_LO16 = 23, - R_MIPS_SUB = 24, - R_MIPS_INSERT_A = 25, - R_MIPS_INSERT_B = 26, - R_MIPS_DELETE = 27, - R_MIPS_HIGHER = 28, - R_MIPS_HIGHEST = 29, - R_MIPS_CALL_HI16 = 30, - R_MIPS_CALL_LO16 = 31, - R_MIPS_SCN_DISP = 32, - R_MIPS_REL16 = 33, - R_MIPS_ADD_IMMEDIATE = 34, - R_MIPS_PJUMP = 35, - R_MIPS_RELGOT = 36, - R_MIPS_JALR = 37, - R_MIPS_TLS_DTPMOD32 = 38, - R_MIPS_TLS_DTPREL32 = 39, - R_MIPS_TLS_DTPMOD64 = 40, - R_MIPS_TLS_DTPREL64 = 41, - R_MIPS_TLS_GD = 42, - R_MIPS_TLS_LDM = 43, - R_MIPS_TLS_DTPREL_HI16 = 44, - R_MIPS_TLS_DTPREL_LO16 = 45, - R_MIPS_TLS_GOTTPREL = 46, - R_MIPS_TLS_TPREL32 = 47, - R_MIPS_TLS_TPREL64 = 48, - R_MIPS_TLS_TPREL_HI16 = 49, - R_MIPS_TLS_TPREL_LO16 = 50, - - R_MIPS_GLOB_DAT = 51, - R_MIPS_PC21_S2 = 60, - R_MIPS_PC26_S2 = 61, - R_MIPS_PC18_S3 = 62, - R_MIPS_PC19_S2 = 63, - R_MIPS_PCHI16 = 64, - R_MIPS_PCLO16 = 65, - - R_MIPS16_26 = 100, - R_MIPS16_GPREL = 101, - R_MIPS16_GOT16 = 102, - R_MIPS16_CALL16 = 103, - R_MIPS16_HI16 = 104, - R_MIPS16_LO16 = 105, - - R_MIPS16_TLS_GD = 106, - R_MIPS16_TLS_LDM = 107, - R_MIPS16_TLS_DTPREL_HI16= 108, - R_MIPS16_TLS_DTPREL_LO16= 109, - R_MIPS16_TLS_GOTTPREL = 110, - R_MIPS16_TLS_TPREL_HI16 = 111, - R_MIPS16_TLS_TPREL_LO16 = 112, - R_MIPS16_PC16_S1 = 113, - - // For these two: - // http://sourceware.org/ml/binutils/2008-07/txt00000.txt - R_MIPS_COPY = 126, - R_MIPS_JUMP_SLOT = 127, - - R_MIPS_PC32 = 248, - R_MIPS_EH = 249, - R_MIPS_GNU_REL16_S2 = 250, - R_MIPS_GNU_VTINHERIT = 253, - R_MIPS_GNU_VTENTRY = 254, - - // artificial types for the complex 32bit relocs - R_MIPS_GPDISP_LO16 = 200, - R_MIPS_GPDISP_HI16 = 201, -}; - -enum elf_ET_MIPS -{ - ET_IRX = 0xFF80u, // IRX file for PS2's IOP - ET_PSPEXEC = 0xFFA0u // Sony PSP executable file -}; - -enum elf_PHT_MIPS -{ - PT_MIPS_IOPMOD = 0x70000080, // Sony PS2 IOP module extension - PT_MIPS_EEMOD = 0x70000090, // Sony PS2 EE module extension - PT_MIPS_PSPREL = 0x700000A0, // Sony PRX relocations (ELF-style) - PT_MIPS_PSPREL2 = 0x700000A1, // Sony PRX relocations (packed) - - // From binutils-2.27/elfcpp/elfcpp.h - PT_MIPS_REGINFO = 0x70000000, // Register usage information. Identifies one .reginfo section. - PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. - PT_MIPS_OPTIONS = 0x70000002, // .MIPS.options section. - PT_MIPS_ABIFLAGS = 0x70000003, // .MIPS.abiflags section. -}; - -enum elf_DTAG_MIPS -{ - DT_MIPS_RLD_VERSION = 0x70000001, /* 32 bit version number for runtime linker interface. */ - DT_MIPS_TIME_STAMP = 0x70000002, /* Time stamp. */ - DT_MIPS_ICHECKSUM = 0x70000003, /* Checksum of external strings and common sizes. */ - DT_MIPS_IVERSION = 0x70000004, /* Index of version string in string table. */ - DT_MIPS_FLAGS = 0x70000005, /* 32 bits of flags. */ - DT_MIPS_BASE_ADDRESS = 0x70000006, /* Base address of the segment. */ - DT_MIPS_MSYM = 0x70000007, /* adress of the msym table */ - DT_MIPS_CONFLICT = 0x70000008, /* Address of .conflict section. */ - DT_MIPS_LIBLIST = 0x70000009, /* Address of .liblist section. */ - DT_MIPS_LOCAL_GOTNO = 0x7000000a, /* Number of local global offset table entries. */ - DT_MIPS_CONFLICTNO = 0x7000000b, /* Number of entries in the .conflict section. */ - DT_MIPS_LIBLISTNO = 0x70000010, /* Number of entries in the .liblist section. */ - DT_MIPS_SYMTABNO = 0x70000011, /* Number of entries in the .dynsym section. */ - DT_MIPS_UNREFEXTNO = 0x70000012, /* Index of first external dynamic symbol not referenced locally. */ - DT_MIPS_GOTSYM = 0x70000013, /* Index of first dynamic symbol in global offset table. */ - DT_MIPS_HIPAGENO = 0x70000014, /* Number of page table entries in global offset table. */ - DT_MIPS_RLD_MAP = 0x70000016, /* Address of run time loader map, used for debugging. */ - DT_MIPS_DELTA_CLASS = 0x70000017, /* Delta C++ class definition. */ - DT_MIPS_DELTA_CLASS_NO = 0x70000018, /* Number of entries in DT_MIPS_DELTA_CLASS. */ - DT_MIPS_DELTA_INSTANCE = 0x70000019, /* Delta C++ class instances. */ - DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a, /* Number of entries in DT_MIPS_DELTA_INSTANCE. */ - DT_MIPS_DELTA_RELOC = 0x7000001b, /* Delta relocations. */ - DT_MIPS_DELTA_RELOC_NO = 0x7000001c, /* Number of entries in DT_MIPS_DELTA_RELOC. */ - DT_MIPS_DELTA_SYM = 0x7000001d, /* Delta symbols that Delta relocations refer to. */ - DT_MIPS_DELTA_SYM_NO = 0x7000001e, /* Number of entries in DT_MIPS_DELTA_SYM. */ - DT_MIPS_DELTA_CLASSSYM = 0x70000020, /* Delta symbols that hold class declarations. */ - DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, /* Number of entries in DT_MIPS_DELTA_CLASSSYM. */ - DT_MIPS_CXX_FLAGS = 0x70000022, /* Flags indicating information about C++ flavor. */ - DT_MIPS_PIXIE_INIT = 0x70000023, /* Pixie information (???). */ - DT_MIPS_SYMBOL_LIB = 0x70000024, /* Address of .MIPS.symlib */ - DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, /* The GOT index of the first PTE for a segment */ - DT_MIPS_LOCAL_GOTIDX = 0x70000026, /* The GOT index of the first PTE for a local symbol */ - DT_MIPS_HIDDEN_GOTIDX = 0x70000027, /* The GOT index of the first PTE for a hidden symbol */ - DT_MIPS_PROTECTED_GOTIDX = 0x70000028, /* The GOT index of the first PTE for a protected symbol */ - DT_MIPS_OPTIONS = 0x70000029, /* Address of `.MIPS.options'. */ - DT_MIPS_INTERFACE = 0x7000002a, /* Address of `.interface'. */ - DT_MIPS_DYNSTR_ALIGN = 0x7000002b, /* ??? */ - DT_MIPS_INTERFACE_SIZE = 0x7000002c, /* Size of the .interface section. */ - DT_MIPS_RLD_TEXT_RESOLVE_ADDR= 0x7000002d, /* Size of rld_text_resolve function stored in the GOT. */ - DT_MIPS_PERF_SUFFIX = 0x7000002e, /* Default suffix of DSO to be added by rld on dlopen() calls. */ - DT_MIPS_COMPACT_SIZE = 0x7000002f, /* Size of compact relocation section (O32). */ - DT_MIPS_GP_VALUE = 0x70000030, /* GP value for auxiliary GOTs. */ - DT_MIPS_AUX_DYNAMIC = 0x70000031, /* Address of auxiliary .dynamic. */ - DT_MIPS_PLTGOT = 0x70000032, /* Address of the base of the PLTGOT */ - DT_MIPS_RWPLT = 0x70000034, /* Points to the base of a writable PLT. */ -}; - -enum elf_SHN_MIPS -{ - SHN_MIPS_ACOMMON = 0xff00, // Defined and allocated common symbol. Value is virtual address. - SHN_MIPS_TEXT = 0xff01, // Defined and allocated text symbol. Value is virtual address. - SHN_MIPS_DATA = 0xff02, // Defined and allocated data symbol. Value is virtual address. - SHN_MIPS_SCOMMON = 0xff03, // Small common symbol. - SHN_MIPS_SUNDEFINED = 0xff04 // Small undefined symbol. -}; - -enum elf_SHF_MIPS -{ - SHF_MIPS_GPREL = 0x10000000, // Section must be part of global data area. - SHF_MIPS_MERGE = 0x20000000, // Section data should be merged to eliminate duplication - SHF_MIPS_ADDR = 0x40000000, // Section data is addresses by default. Address size to be inferred from section entry size. - SHF_MIPS_STRING = 0x80000000, // Section data is string data by default - SHF_MIPS_NOSTRIP = 0x08000000, // Section data may not be stripped - SHF_MIPS_LOCAL = 0x04000000, // Section data local to process - SHF_MIPS_NAMES = 0x02000000, // Linker must generate implicit hidden weak names - SHF_MIPS_NODUPE = 0x01000000, // Section contains text/data which may be replicated in other sections. Linker must retain only one copy. -}; - -enum elf_SHT_MIPS -{ - SHT_MIPS_LIBLIST = 0x70000000, // contains the set of dynamic shared objects used when statically linking. - SHT_MIPS_MSYM = 0x70000001, //unknown Irix5 usage - SHT_MIPS_CONFLICT = 0x70000002, // list of confliction symbols - SHT_MIPS_GPTAB = 0x70000003, // Section contains the global pointer table. - SHT_MIPS_UCODE = 0x70000004, //microcode information - SHT_MIPS_DEBUG = 0x70000005, //start of debugging information - SHT_MIPS_REGINFO = 0x70000006, // Section contains register usage information. - SHT_MIPS_RELD = 0x70000009, // Dynamic relocation? - SHT_MIPS_IFACE = 0x7000000B, // Subprogram interface information - SHT_MIPS_CONTENT = 0x7000000C, // Section content classification - SHT_MIPS_OPTIONS = 0x7000000D, // General options - SHT_MIPS_DELTASYM = 0x7000001B, // Delta C++: symbol table - SHT_MIPS_DELTAINST = 0x7000001C, // Delta C++: instance table - SHT_MIPS_DELTACLASS = 0x7000001D, // Delta C++: class table - SHT_MIPS_DWARF = 0x7000001E, // DWARF debugging section. - SHT_MIPS_DELTADECL = 0x7000001F, // Delta C++: declarations - SHT_MIPS_SYMBOL_LIB = 0x70000020, //unknown Irix6 usage - SHT_MIPS_EVENTS = 0x70000021, // Events section. - SHT_MIPS_TRANSLATE = 0x70000022, // ??? - SHT_MIPS_PIXIE = 0x70000023, // Special pixie sections - SHT_MIPS_XLATE = 0x70000024, // Address translation table - SHT_MIPS_XLATE_DEBUG = 0x70000025, // SGI internal address translation table - SHT_MIPS_WHIRL = 0x70000026, // Intermediate code - SHT_MIPS_EH_REGION = 0x70000027, // C++ exception handling region info - SHT_MIPS_XLATE_OLD = 0x70000028, // Obsolete - SHT_MIPS_PDR_EXCEPTION = 0x70000029, // Runtime procedure descriptor table exception information (ucode) - SHT_MIPS_IOPMOD = 0x70000080, // .ipmod section for PS2 IRXs - SHT_MIPS_PSPREL = 0x700000A0, // PSP executable relocation section - // VU overlay table (PS2?) - SHT_DVP_OVERLAY_TABLE = 0x7FFFF420, - SHT_DVP_OVERLAY = 0x7FFFF421, -}; - -// Special values for the st_other field in the symbol table. -enum elf_STO_MIPS -{ - // Two topmost bits denote the MIPS ISA for .text symbols: - // + 00 -- standard MIPS code, - // + 10 -- microMIPS code, - // + 11 -- MIPS16 code; requires the following two bits to be set too. - // Note that one of the MIPS16 bits overlaps with STO_MIPS_PIC. - STO_MIPS_ISA = 0xc0, - - // The MIPS psABI was updated in 2008 with support for PLTs and copy - // relocs. There are therefore two types of nonzero SHN_UNDEF functions: - // PLT entries and traditional MIPS lazy binding stubs. We mark the former - // with STO_MIPS_PLT to distinguish them from the latter. - STO_MIPS_PLT = 0x8, - - // This value is used to mark PIC functions in an object that mixes - // PIC and non-PIC. Note that this bit overlaps with STO_MIPS16, - // although MIPS16 symbols are never considered to be MIPS_PIC. - STO_MIPS_PIC = 0x20, - - // This value is used for a mips16 .text symbol. - STO_MIPS16 = 0xf0, - - // This value is used for a microMIPS .text symbol. To distinguish from - // STO_MIPS16, we set top two bits to be 10 to denote STO_MICROMIPS. The - // mask is STO_MIPS_ISA. - STO_MICROMIPS = 0x80 -}; - -// .MIPS.options descriptor kinds -enum elf_ODK_MIPS -{ - ODK_NULL = 0, // Undefined - ODK_REGINFO = 1, // Register usage information - ODK_EXCEPTIONS = 2, // Exception processing options - ODK_PAD = 3, // Section padding options - ODK_HWPATCH = 4, // Hardware patches applied - ODK_FILL = 5, // Linker fill value - ODK_TAGS = 6, // Space for tool identification - ODK_HWAND = 7, // Hardware AND patches applied - ODK_HWOR = 8, // Hardware OR patches applied - ODK_GP_GROUP = 9, // GP group to use for text/data sections - ODK_IDENT = 10, // ID information - ODK_PAGESIZE = 11, // Page size information -}; - -// PSP-specific encoding of r_info field -// segment in which the relocation resides -// i.e. relocation is at pht[ofs_base].p_vaddr + r_offset -#define ELF32_R_OFS_BASE(i) (((i)>>8) & 0xFF) -// segment number with the target -// i.e. the final address should be adjusted with pht[ofs_base].p_vaddr -#define ELF32_R_ADDR_BASE(i) (((i)>>16) & 0xFF) - - -// MIPS ELF 64 relocation info access macros. -// they assume BE byte order of the packed r_type field -#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff) -#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) -#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) -#define ELF64_MIPS_R_TYPE(i) ((i) & 0xff) - -// Values found in the r_ssym field of a relocation entry. -// No relocation. -#define RSS_UNDEF 0 -// Value of GP. -#define RSS_GP 1 -// Value of GP in object being relocated. -#define RSS_GP0 2 -// Address of location being relocated. -#define RSS_LOC 3 - -// MIPS .msym table entry -struct Elf32_Msym -{ - uint32 ms_hash_value; //Contains the hash value computed from the name of the corresponding dynamic symbol - uint32 ms_info; //Contains both the dynamic relocation index and the symbol flags field. -}; - -#define ELF32_MS_REL_INDEX(i) ((i) >> 8) -#define ELF32_MS_FLAGS(i) ((i) & 0xff) -#define ELF32_MS_INFO(r,f) (((r) << 8) + ((f) & 0xff)) - -//MIPS .liblist entry -typedef struct -{ - uint32 l_name; //Records the name of a shared library dependency. - //The value is a string table index. This name can be a - //full pathname, relative pathname, or file name. - uint32 l_time_stamp;//Records the time stamp of a shared library dependency. - uint32 l_checksum; //Records the checksum of a shared library dependency. - uint32 l_version; //Records the interface version of a shared library dependency. - //The value is a string table index. - uint32 l_flags; -} Elf64_Lib; - -// bits for l_flags: -#define LL_NONE 0 -#define LL_EXACT_MATCH 0x1 //Requires that the run-time dynamic shared library file match - //exactly the shared library file used at static link time. -#define LL_IGNORE_INT_VER 0x2 //Ignores any version incompatibility between the dynamic - // shared library file and the shared library file used at link time. -#define LL_REQUIRE_MINOR 0x4 //Marks shared library dependencies that should be loaded with - //a suffix appended to the name. The DT_SO_SUFFIX entry in - //the .dynamic section records the name of this suffix. This is - //used by object instrumentation tools to distinguish - //instrumented shared libraries. -#define LL_EXPORTS 0x8 //Marks entries for shared libraries that are not loaded as direct - //dependencies of an object. -#define LL_DELAY_LOAD 0x10 -#define LL_DELTA 0x20 - -//.reginfo section -struct Elf32_RegInfo -{ - uint32 ri_gprmask; - uint32 ri_cprmask[4]; - uint32 ri_gp_value; -}; - -void set_mips_compact_encoding(ea_t ea, bool enable); -void relocate_psp_section(Elf64_Shdr *rsh, linput_t *li); -inline bool is_psp_file(reader_t &reader) { return reader.get_header().e_machine == EM_MIPS && reader.get_header().e_type == ET_PSPEXEC; } - -#endif diff --git a/idasdk75/ldr/elf/elfr_ppc.h b/idasdk75/ldr/elf/elfr_ppc.h deleted file mode 100644 index 89b262b..0000000 --- a/idasdk75/ldr/elf/elfr_ppc.h +++ /dev/null @@ -1,383 +0,0 @@ -#ifndef __ELFR_PPC_H__ -#define __ELFR_PPC_H__ - -#ifndef __ELFBASE_H__ -#include "elfbase.h" -#endif - -#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ -#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag */ -#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag */ - -// PowerPC 64 ABI version -#define EF_PPC64_ABI_MASK 3 // original function descriptor using ABI -#define EF_PPC64_UNK_ABI 0 // unspecified or not using any features - // affected by the differences -#define EF_PPC64_AIX_ABI 1 // original function descriptor using ABI -#define EF_PPC64_V2_ABI 2 // revised ABI without function descriptors - -enum elf_ET_PPC -{ - ET_PS3PRX = 0xFFA4, // Sony PS3 PRX -}; - -enum elf_SHT_PPC -{ - SHT_PS3PRX_RELA = 0x700000A4, // Sony PS3 PRX relocations -}; - -enum elf_PHT_PPC -{ - PHT_PS3PRX_RELA = 0x700000A4, // Sony PS3 PRX relocations -}; - -enum elf_DT_PPC -{ - DT_PPC_GOT = (DT_LOPROC + 0x0), // address of _GLOBAL_OFFSET_TABLE_ -}; - -// relocation field - word32 with HIGH BYTE FIRST!!! -// A- from Elf32_Rela -// B- Loading address of shared object -// G- offset into global objet table -// GOT- adress of global object table -// L- linkage table entry -// P- plase of storage unit (computed using r_offset) -// S- value of symbol -enum elf_RTYPE_ppc -{ - R_PPC_NONE = 0, //No reloc - R_PPC_ADDR32 = 1, //S+A-P Direct 32 bit - R_PPC_ADDR24 = 2, - R_PPC_ADDR16 = 3, - R_PPC_ADDR16_LO = 4, - R_PPC_ADDR16_HI = 5, - R_PPC_ADDR16_HA = 6, - R_PPC_ADDR14 = 7, - R_PPC_ADDR14_BRTAKEN = 8, - R_PPC_ADDR14_BRNTAKEN = 9, - R_PPC_REL24 = 10, //S+A relative 24 bit - R_PPC_REL14 = 11, - R_PPC_REL14_BRTAKEN = 12, - R_PPC_REL14_BRNTAKEN = 13, - R_PPC_GOT16 = 14, - R_PPC_GOT16_LO = 15, - R_PPC_GOT16_HI = 16, - R_PPC_GOT16_HA = 17, - R_PPC_PLTREL24 = 18, - R_PPC_COPY = 19, - R_PPC_GLOB_DAT = 20, - R_PPC_JMP_SLOT = 21, - R_PPC_RELATIVE = 22, - R_PPC_LOCAL24PC = 23, - R_PPC_UADDR32 = 24, - R_PPC_UADDR16 = 25, - R_PPC_REL32 = 26, - R_PPC_PLT32 = 27, - R_PPC_PLTREL32 = 28, - R_PPC_PLT16_LO = 29, - R_PPC_PLT16_HI = 30, - R_PPC_PLT16_HA = 31, - R_PPC_SDAREL16 = 32, - R_PPC_SECTOFF = 33, - R_PPC_SECTOFF_LO = 34, - R_PPC_SECTOFF_HI = 35, - R_PPC_SECTOFF_HA = 36, - R_PPC_ADDR30 = 37, // word30 (S + A - P) >> 2 - - - // some undocumented relocs used by freescale - // some seem to be the same as official VLE relocs below - // NB! they conflict with some PPC64 relocations - R_PPC_FVLE_REL8 = 38, // same as R_PPC_VLE_REL8? - R_PPC_FVLE_REL15 = 39, // same as R_PPC_VLE_REL15? - R_PPC_FVLE_REL24 = 40, // same as R_PPC_VLE_REL24? - R_PPC_FVLE_ADDR8 = 44, // ?? - R_PPC_FVLE_ADDR4 = 45, // ?? - R_PPC_FVLE_SDA = 47, // same as R_PPC_VLE_SDA21? - R_PPC_FVLE_LO16A = 49, // same as R_PPC_VLE_LO16A? - R_PPC_FVLE_HI16A = 50, // same as R_PPC_VLE_HI16A? - R_PPC_FVLE_HA16A = 51, // same as R_PPC_VLE_HA16A? - R_PPC_FVLE_LO16D = 56, // same as R_PPC_VLE_LO16D? - R_PPC_FVLE_HI16D = 57, // same as R_PPC_VLE_HI16D? - R_PPC_FVLE_HA16D = 58, // same as R_PPC_VLE_HA16D? - - /* Relocs added to support TLS. */ - R_PPC_TLS = 67, - R_PPC_DTPMOD32 = 68, - R_PPC_TPREL16 = 69, - R_PPC_TPREL16_LO = 70, - R_PPC_TPREL16_HI = 71, - R_PPC_TPREL16_HA = 72, - R_PPC_TPREL32 = 73, - R_PPC_DTPREL16 = 74, - R_PPC_DTPREL16_LO = 75, - R_PPC_DTPREL16_HI = 76, - R_PPC_DTPREL16_HA = 77, - R_PPC_DTPREL32 = 78, - R_PPC_GOT_TLSGD16 = 79, - R_PPC_GOT_TLSGD16_LO = 80, - R_PPC_GOT_TLSGD16_HI = 81, - R_PPC_GOT_TLSGD16_HA = 82, - R_PPC_GOT_TLSLD16 = 83, - R_PPC_GOT_TLSLD16_LO = 84, - R_PPC_GOT_TLSLD16_HI = 85, - R_PPC_GOT_TLSLD16_HA = 86, - R_PPC_GOT_TPREL16 = 87, - R_PPC_GOT_TPREL16_LO = 88, - R_PPC_GOT_TPREL16_HI = 89, - R_PPC_GOT_TPREL16_HA = 90, - R_PPC_GOT_DTPREL16 = 91, - R_PPC_GOT_DTPREL16_LO = 92, - R_PPC_GOT_DTPREL16_HI = 93, - R_PPC_GOT_DTPREL16_HA = 94, - R_PPC_TLSGD = 95, - R_PPC_TLSLD = 96, - - R_PPC_EMB_NADDR32 = 101, // word32 (A - S) - R_PPC_EMB_NADDR16 = 102, // half16* (A - S) - R_PPC_EMB_NADDR16_LO = 103, // half16 #lo(A - S) - R_PPC_EMB_NADDR16_HI = 104, // half16 #hi(A - S) - R_PPC_EMB_NADDR16_HA = 105, // half16 #ha(A - S) - R_PPC_EMB_SDA_I16 = 106, // half16* T - R_PPC_EMB_SDA2_I16 = 107, // half16* U - R_PPC_EMB_SDA2REL = 108, // half16* S + A - _SDA2_BASE_ - R_PPC_EMB_SDA21 = 109, // low21 Y || (X + A) - R_PPC_EMB_MRKREF = 110, // none See below - R_PPC_EMB_RELSEC16 = 111, // half16* V + A - R_PPC_EMB_RELST_LO = 112, // half16 #lo(W + A) - R_PPC_EMB_RELST_HI = 113, // half16 #hi(W + A) - R_PPC_EMB_RELST_HA = 114, // half16 #ha(W + A) - R_PPC_EMB_BIT_FLD = 115, // word32* See below - R_PPC_EMB_RELSDA = 116, // half16* X + A. See below - R_PPC_EMB_RELOC_120 = 120, // half16* S + A - R_PPC_EMB_RELOC_121 = 121, // half16* Same calculation as U, except that the value 0 is used instead of _SDA2_BASE_. - -/* The R_PPC_DIAB_SDA21_xx relocation modes work like the R_PPC_EMB_SDA21 mode - * and the R_PPC_DIAB_RELSDA_xx relocation modes work like the R_PPC_EMB_RELSDA mode - * with the following exceptions: - * If the symbol is in .data, .sdata, .bss, .sbss the symbol is DATA relative - (r13 base pointer/_SDA_BASE_ base address) - * If the symbol is in .text, .sdata2, .sbss2 the symbol is CODE relative - (r2 base pointer/_SDA_BASE2_ base address) - * Otherwise the symbol is absolute (r0 base pointer/0 base address) - */ - R_PPC_DIAB_SDA21_LO = 180, // half21 Y || #lo(X + A) - R_PPC_DIAB_SDA21_HI = 181, // half21 Y || #hi(X + A) - R_PPC_DIAB_SDA21_HA = 182, // half21 Y || #ha(X + A) - R_PPC_DIAB_RELSDA_LO = 183, // half16 #lo(X + A) - R_PPC_DIAB_RELSDA_HI = 184, // half16 #hi(X + A) - R_PPC_DIAB_RELSDA_HA = 185, // half16 #ha(X + A) - R_PPC_DIAB_IMTO = 186, - R_PPC_DIAB_IMT = 187, - R_PPC_DIAB_ADDR0 = 188, - R_PPC_DIAB_OVERRIDE0 = 189, - R_PPC_DIAB_VTBL32 = 190, - R_PPC_DIAB_LAST = 191, - - R_PPC_EMB_SPE_DOUBLE = 201, // mid5* (#lo(S + A)) >> 3 - R_PPC_EMB_SPE_WORD = 202, // mid5* (#lo(S + A)) >> 2 - R_PPC_EMB_SPE_HALF = 203, // mid5* (#lo(S + A)) >> 1 - R_PPC_EMB_SPE_DOUBLE_SDAREL = 204, // mid5* (#lo(S + A - _SDA_BASE_)) >> 3 - R_PPC_EMB_SPE_WORD_SDAREL = 205, // mid5* (#lo(S + A - _SDA_BASE_)) >> 2 - R_PPC_EMB_SPE_HALF_SDAREL = 206, // mid5* (#lo(S + A - _SDA_BASE_)) >> 1 - R_PPC_EMB_SPE_DOUBLE_SDA2REL = 207, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 3 - R_PPC_EMB_SPE_WORD_SDA2REL = 208, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 2 - R_PPC_EMB_SPE_HALF_SDA2REL = 209, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 1 - R_PPC_EMB_SPE_DOUBLE_SDA0REL = 210, // mid5* (#lo(S + A)) >> 3 - R_PPC_EMB_SPE_WORD_SDA0REL = 211, // mid5* (#lo(S + A)) >> 2 - R_PPC_EMB_SPE_HALF_SDA0REL = 212, // mid5* (#lo(S + A)) >> 1 - R_PPC_EMB_SPE_DOUBLE_SDA = 213, // mid10* Y || ((#lo(X + A)) >> 3) - R_PPC_EMB_SPE_WORD_SDA = 214, // mid10* Y || ((#lo(X + A)) >> 2) - R_PPC_EMB_SPE_HALF_SDA = 215, // mid10* Y || ((#lo(X + A)) >> 1) - - R_PPC_VLE_REL8 = 216, // bdh8 (S + A - P) >> 1 - R_PPC_VLE_REL15 = 217, // bdh15 (S + A - P) >> 1 - R_PPC_VLE_REL24 = 218, // bdh24 (S + A - P) >> 1 - R_PPC_VLE_LO16A = 219, // split16a #lo(S + A) - R_PPC_VLE_LO16D = 220, // split16d #lo(S + A) - R_PPC_VLE_HI16A = 221, // split16a #hi(S + A) - R_PPC_VLE_HI16D = 222, // split16d #hi(S + A) - R_PPC_VLE_HA16A = 223, // split16a #ha(S + A) - R_PPC_VLE_HA16D = 224, // split16d #ha(S + A) - R_PPC_VLE_SDA21 = 225, // low21, split20 Y || (X + A) - R_PPC_VLE_SDA21_LO = 226, // low21, split20 Y || #lo(X + A) - R_PPC_VLE_SDAREL_LO16A = 227, // split16a #lo(X + A) - R_PPC_VLE_SDAREL_LO16D = 228, // split16d #lo(X + A) - R_PPC_VLE_SDAREL_HI16A = 229, // split16a #hi(X + A) - R_PPC_VLE_SDAREL_HI16D = 230, // split16d #hi(X + A) - R_PPC_VLE_SDAREL_HA16A = 231, // split16a #ha(X + A) - R_PPC_VLE_SDAREL_HA16D = 232, // split16d #ha(X + A) - - R_PPC_REL16DX_HA = 246, - - R_PPC_IRELATIVE = 248, // GNU extension to support local ifunc. - /* GNU relocs used in PIC code sequences. */ - R_PPC_REL16 = 249, // half16* S + A - P - R_PPC_REL16_LO = 250, // half16 #lo(S + A - P) - R_PPC_REL16_HI = 251, // half16 #hi(S + A - P) - R_PPC_REL16_HA = 252, // half16 #la(S + A - P) - - R_PPC_GNU_VTINHERIT = 253, - R_PPC_GNU_VTENTRY = 254, -/* This is a phony reloc to handle any old fashioned TOC16 references - that may still be in object files. */ - R_PPC_TOC16 = 255, - - // PowerPC64 relocations. Many (but not all) of them are the same as for PPC32 - R_PPC64_NONE = R_PPC_NONE, - R_PPC64_ADDR32 = R_PPC_ADDR32, /* 32bit absolute address. */ - R_PPC64_ADDR24 = R_PPC_ADDR24, /* 26bit address, word aligned. */ - R_PPC64_ADDR16 = R_PPC_ADDR16, /* 16bit absolute address. */ - R_PPC64_ADDR16_LO = R_PPC_ADDR16_LO, /* lower 16bits of abs. address. */ - R_PPC64_ADDR16_HI = R_PPC_ADDR16_HI, /* high 16bits of abs. address. */ - R_PPC64_ADDR16_HA = R_PPC_ADDR16_HA, /* adjusted high 16bits. */ - R_PPC64_ADDR14 = R_PPC_ADDR14, /* 16bit address, word aligned. */ - R_PPC64_ADDR14_BRTAKEN = R_PPC_ADDR14_BRTAKEN, - R_PPC64_ADDR14_BRNTAKEN = R_PPC_ADDR14_BRNTAKEN, - R_PPC64_REL24 = R_PPC_REL24, /* PC relative 26 bit, word aligned. */ - R_PPC64_REL14 = R_PPC_REL14, /* PC relative 16 bit. */ - R_PPC64_REL14_BRTAKEN = R_PPC_REL14_BRTAKEN, - R_PPC64_REL14_BRNTAKEN = R_PPC_REL14_BRNTAKEN, - R_PPC64_GOT16 = R_PPC_GOT16, - R_PPC64_GOT16_LO = R_PPC_GOT16_LO, - R_PPC64_GOT16_HI = R_PPC_GOT16_HI, - R_PPC64_GOT16_HA = R_PPC_GOT16_HA, - R_PPC64_PLTREL24 = R_PPC_PLTREL24, - R_PPC64_COPY = R_PPC_COPY, - R_PPC64_GLOB_DAT = R_PPC_GLOB_DAT, - R_PPC64_JMP_SLOT = R_PPC_JMP_SLOT, - R_PPC64_RELATIVE = R_PPC_RELATIVE, - R_PPC64_LOCAL24PC = R_PPC_LOCAL24PC, - R_PPC64_UADDR32 = R_PPC_UADDR32, - R_PPC64_UADDR16 = R_PPC_UADDR16, - R_PPC64_REL32 = R_PPC_REL32, - R_PPC64_PLT32 = R_PPC_PLT32, - R_PPC64_PLTREL32 = R_PPC_PLTREL32, - R_PPC64_PLT16_LO = R_PPC_PLT16_LO, - R_PPC64_PLT16_HI = R_PPC_PLT16_HI, - R_PPC64_PLT16_HA = R_PPC_PLT16_HA, - R_PPC64_SDAREL16 = R_PPC_SDAREL16, - R_PPC64_SECTOFF = R_PPC_SECTOFF, - R_PPC64_SECTOFF_LO = R_PPC_SECTOFF_LO, - R_PPC64_SECTOFF_HI = R_PPC_SECTOFF_HI, - R_PPC64_SECTOFF_HA = R_PPC_SECTOFF_HA, - - R_PPC64_ADDR30 = 37, /* word30 (S + A - P) >> 2. */ - R_PPC64_ADDR64 = 38, /* doubleword64 S + A. */ - R_PPC64_ADDR16_HIGHER = 39, /* half16 #higher(S + A). */ - R_PPC64_ADDR16_HIGHERA = 40, /* half16 #highera(S + A). */ - R_PPC64_ADDR16_HIGHEST = 41, /* half16 #highest(S + A). */ - R_PPC64_ADDR16_HIGHESTA = 42, /* half16 #highesta(S + A). */ - R_PPC64_UADDR64 = 43, /* doubleword64 S + A. */ - R_PPC64_REL64 = 44, /* doubleword64 S + A - P. */ - R_PPC64_PLT64 = 45, /* doubleword64 L + A. */ - R_PPC64_PLTREL64 = 46, /* doubleword64 L + A - P. */ - R_PPC64_TOC16 = 47, /* half16* S + A - .TOC. */ - R_PPC64_TOC16_LO = 48, /* half16 #lo(S + A - .TOC.). */ - R_PPC64_TOC16_HI = 49, /* half16 #hi(S + A - .TOC.). */ - R_PPC64_TOC16_HA = 50, /* half16 #ha(S + A - .TOC.). */ - R_PPC64_TOC = 51, /* doubleword64 .TOC. */ - R_PPC64_PLTGOT16 = 52, /* half16* M + A. */ - R_PPC64_PLTGOT16_LO = 53, /* half16 #lo(M + A). */ - R_PPC64_PLTGOT16_HI = 54, /* half16 #hi(M + A). */ - R_PPC64_PLTGOT16_HA = 55, /* half16 #ha(M + A). */ - - R_PPC64_ADDR16_DS = 56, /* half16ds* (S + A) >> 2. */ - R_PPC64_ADDR16_LO_DS = 57, /* half16ds #lo(S + A) >> 2. */ - R_PPC64_GOT16_DS = 58, /* half16ds* (G + A) >> 2. */ - R_PPC64_GOT16_LO_DS = 59, /* half16ds #lo(G + A) >> 2. */ - R_PPC64_PLT16_LO_DS = 60, /* half16ds #lo(L + A) >> 2. */ - R_PPC64_SECTOFF_DS = 61, /* half16ds* (R + A) >> 2. */ - R_PPC64_SECTOFF_LO_DS = 62, /* half16ds #lo(R + A) >> 2. */ - R_PPC64_TOC16_DS = 63, /* half16ds* (S + A - .TOC.) >> 2. */ - R_PPC64_TOC16_LO_DS = 64, /* half16ds #lo(S + A - .TOC.) >> 2. */ - R_PPC64_PLTGOT16_DS = 65, /* half16ds* (M + A) >> 2. */ - R_PPC64_PLTGOT16_LO_DS = 66, /* half16ds #lo(M + A) >> 2. */ - -/* PowerPC64 relocations defined for the TLS access ABI. */ - R_PPC64_TLS = 67, /* none (sym+add)@tls */ - R_PPC64_DTPMOD64 = 68, /* doubleword64 (sym+add)@dtpmod */ - R_PPC64_TPREL16 = 69, /* half16* (sym+add)@tprel */ - R_PPC64_TPREL16_LO = 70, /* half16 (sym+add)@tprel@l */ - R_PPC64_TPREL16_HI = 71, /* half16 (sym+add)@tprel@h */ - R_PPC64_TPREL16_HA = 72, /* half16 (sym+add)@tprel@ha */ - R_PPC64_TPREL64 = 73, /* doubleword64 (sym+add)@tprel */ - R_PPC64_DTPREL16 = 74, /* half16* (sym+add)@dtprel */ - R_PPC64_DTPREL16_LO = 75, /* half16 (sym+add)@dtprel@l */ - R_PPC64_DTPREL16_HI = 76, /* half16 (sym+add)@dtprel@h */ - R_PPC64_DTPREL16_HA = 77, /* half16 (sym+add)@dtprel@ha */ - R_PPC64_DTPREL64 = 78, /* doubleword64 (sym+add)@dtprel */ - R_PPC64_GOT_TLSGD16 = 79, /* half16* (sym+add)@got@tlsgd */ - R_PPC64_GOT_TLSGD16_LO = 80, /* half16 (sym+add)@got@tlsgd@l */ - R_PPC64_GOT_TLSGD16_HI = 81, /* half16 (sym+add)@got@tlsgd@h */ - R_PPC64_GOT_TLSGD16_HA = 82, /* half16 (sym+add)@got@tlsgd@ha */ - R_PPC64_GOT_TLSLD16 = 83, /* half16* (sym+add)@got@tlsld */ - R_PPC64_GOT_TLSLD16_LO = 84, /* half16 (sym+add)@got@tlsld@l */ - R_PPC64_GOT_TLSLD16_HI = 85, /* half16 (sym+add)@got@tlsld@h */ - R_PPC64_GOT_TLSLD16_HA = 86, /* half16 (sym+add)@got@tlsld@ha */ - R_PPC64_GOT_TPREL16_DS = 87, /* half16ds* (sym+add)@got@tprel */ - R_PPC64_GOT_TPREL16_LO_DS = 88, /* half16ds (sym+add)@got@tprel@l */ - R_PPC64_GOT_TPREL16_HI = 89, /* half16 (sym+add)@got@tprel@h */ - R_PPC64_GOT_TPREL16_HA = 90, /* half16 (sym+add)@got@tprel@ha */ - R_PPC64_GOT_DTPREL16_DS = 91, /* half16ds* (sym+add)@got@dtprel */ - R_PPC64_GOT_DTPREL16_LO_DS = 92, /* half16ds (sym+add)@got@dtprel@l */ - R_PPC64_GOT_DTPREL16_HI = 93, /* half16 (sym+add)@got@dtprel@h */ - R_PPC64_GOT_DTPREL16_HA = 94, /* half16 (sym+add)@got@dtprel@ha */ - R_PPC64_TPREL16_DS = 95, /* half16ds* (sym+add)@tprel */ - R_PPC64_TPREL16_LO_DS = 96, /* half16ds (sym+add)@tprel@l */ - R_PPC64_TPREL16_HIGHER = 97, /* half16 (sym+add)@tprel@higher */ - R_PPC64_TPREL16_HIGHERA = 98, /* half16 (sym+add)@tprel@highera */ - R_PPC64_TPREL16_HIGHEST = 99, /* half16 (sym+add)@tprel@highest */ - R_PPC64_TPREL16_HIGHESTA = 100, /* half16 (sym+add)@tprel@highesta */ - R_PPC64_DTPREL16_DS = 101, /* half16ds* (sym+add)@dtprel */ - R_PPC64_DTPREL16_LO_DS = 102, /* half16ds (sym+add)@dtprel@l */ - R_PPC64_DTPREL16_HIGHER = 103, /* half16 (sym+add)@dtprel@higher */ - R_PPC64_DTPREL16_HIGHERA = 104, /* half16 (sym+add)@dtprel@highera */ - R_PPC64_DTPREL16_HIGHEST = 105, /* half16 (sym+add)@dtprel@highest */ - R_PPC64_DTPREL16_HIGHESTA = 106, /* half16 (sym+add)@dtprel@highesta */ -#if 0 - // These relocation types appear in David Anderson's libdwarf and - // dwarfdump only. The PPC 64-Bit ELF V2 ABI uses these numbers for - // different types (see below). - R_PPC64_TOC32 = 107, /* word32 (.TOC. & 0xffff_ffff) */ - R_PPC64_DTPMOD32 = 108, /* word32 (@dtpmod & 0xffff_ffff) */ - R_PPC64_TPREL32 = 109, /* word32 (@tprel & 0xffff_ffff) */ - R_PPC64_DTPREL32 = 110, /* word32 (@dtprel & 0xffff_ffff) */ -#else - // The PPC 64-Bit ELF V2 ABI uses these numbers for different types - R_PPC64_TLSGD = 107, // used as markers on thread local - R_PPC64_TLSLD = 108, // storage (TLS) code sequences - R_PPC64_TOCSAVE = 109, // this relocation type indicates a - // position where a TOC save may be - // inserted in the function to avoid a - // TOC save as part of the PLT stub code - R_PPC64_ADDR16_HIGH = 110, // half16 #hi(S + A) - R_PPC64_ADDR16_HIGHA = 111, // half16 #ha(S + A) - R_PPC64_TPREL16_HIGH = 112, // half16 #hi(@tprel) - R_PPC64_TPREL16_HIGHA = 113, // half16 #ha(@tprel) - R_PPC64_DTPREL16_HIGH = 114, // half16 #hi(@dtprel) - R_PPC64_DTPREL16_HIGHA = 115, // half16 #ha(@dtprel) - R_PPC64_REL24_NOTOC = 116, // low24* (S + A - P) >> 2 - R_PPC64_ADDR64_LOCAL = 117, // doubleword64 S + A (see 3.5.4) -#endif - R_PPC64_JMP_IREL = 247, // GNU extension to support local ifunc - // The PPC 64-Bit ELF V2 ABI - R_PPC64_IRELATIVE = 248, // It is used to implement the - // STT_GNU_IFUNC framework - R_PPC64_REL16 = R_PPC_REL16, // half16* S + A - P - R_PPC64_REL16_LO = R_PPC_REL16_LO, // half16 #lo(S + A - P) - R_PPC64_REL16_HI = R_PPC_REL16_HI, // half16* #hi(S + A - P) - R_PPC64_REL16_HA = R_PPC_REL16_HA, // half16* #la(S + A - P) -}; - -// flags for VLE code -#define SHF_PPC_VLE 0x10000000 /* section header flag */ -#define PF_PPC_VLE 0x10000000 /* program header flag */ - -// patching GOT loading, -// discard auxiliary values in plt/got -// can present offset bypass segment -#define ELF_RPL_PPC_DEFAULT (ELF_RPL_GL | ELF_DIS_OFFW | ELF_DIS_GPLT) - -#endif diff --git a/idasdk75/ldr/elf/reader.cpp b/idasdk75/ldr/elf/reader.cpp deleted file mode 100644 index a6f2b5f..0000000 --- a/idasdk75/ldr/elf/reader.cpp +++ /dev/null @@ -1,3550 +0,0 @@ - -#ifndef ELF_READER_CPP -#define ELF_READER_CPP - -#include <set> - -#include <pro.h> -#include <diskio.hpp> -#include <functional> -#include <algorithm> - -#include "elfbase.h" -#include "elf.h" -#include "elfr_arm.h" -#include "elfr_mips.h" -#include "elfr_ia64.h" -#include "elfr_ppc.h" -#ifdef BUILD_LOADER -#include "../idaldr.h" -#endif - -//---------------------------------------------------------------------------- -ssize_t reader_t::prepare_error_string( - char *buf, - size_t bufsize, - reader_t::errcode_t code, - va_list va) const -{ - int len; - switch ( code ) - { - case BAD_CLASS: - { - int eclass = va_arg(va, int); - len = qsnprintf(buf, bufsize, - "Unknown ELF class %d (should be %d for 32-bit, %d for 64-bit)", - eclass, - ELFCLASS32, - ELFCLASS64); - } - break; - case BAD_ENDIANNESS: - { - int endian = va_arg(va, int); - if ( endian != ELFDATA2LSB && endian != ELFDATA2MSB ) - len = qsnprintf(buf, bufsize, - "Unknown ELF byte sex %d (should be %d for LSB, %d for MSB)", - endian, - ELFDATA2LSB, - ELFDATA2MSB); - else - len = qsnprintf(buf, bufsize, - "Bad ELF byte sex %d for the indicated machine", - endian); - } - break; - case BAD_EHSIZE: - { - int sz = va_arg(va, int); - int fb = va_arg(va, int); - len = qsnprintf(buf, bufsize, - "The ELF header entry size is invalid (%d, expected %d)", - sz, fb); - } - break; - case BAD_PHENTSIZE: - { - int sz = va_arg(va, int); - int fb = va_arg(va, int); - len = qsnprintf(buf, bufsize, - "PHT entry size is invalid: %d. Falling back to %d", - sz, fb); - } - break; - case BAD_PHLOC: - len = qstpncpy(buf, "The PHT table size or offset is invalid", bufsize) - buf; - break; - case BAD_SHENTSIZE: - len = qstpncpy(buf, "The SHT entry size is invalid", bufsize) - buf; - break; - case BAD_SHLOC: - len = qstpncpy(buf, "SHT table size or offset is invalid", bufsize) - buf; - break; - case BAD_DYN_PLT_TYPE: - len = qsnprintf(buf, bufsize, "Bad DT_PLTREL value (%d)", va_arg(va, int)); - break; - case CONFLICTING_FILE_TYPE: - len = qstpncpy(buf, "ELF file with PHT cannot be ET_REL", bufsize) - buf; - break; - case BAD_SHSTRNDX: - { - uint idx = va_arg(va, uint); - uint num = va_arg(va, uint); - len = qsnprintf(buf, bufsize, - "Section header string table index %u is out of bounds", - idx); - if ( num > 0 ) - len += qsnprintf(buf + len, bufsize - len, - " (max %u)", num - 1); - } - break; - case ERR_READ: - { - size_t d1 = va_arg(va, size_t); // size - size_t d2 = va_arg(va, size_t); // return code - qnotused(d1); - qnotused(d2); - len = qsnprintf(buf, bufsize, - "Bad file structure or read error (offset %" FMT_64 "u)", - va_arg(va, int64)); - } - break; - default: - if ( is_error(code) ) - INTERR(20034); - len = qsnprintf(buf, bufsize, "Unknown ELF warning %d", code); - break; - } - return len; -} - -//---------------------------------------------------------------------------- -static bool default_error_handler(const reader_t &reader, reader_t::errcode_t code, ...) -{ - va_list va; - va_start(va, code); - char buf[MAXSTR]; - reader.prepare_error_string(buf, sizeof(buf), code, va); - va_end(va); - - warning("%s", buf); - return reader.is_warning(code); // resume after warnings -} - -//---------------------------------------------------------------------------- -const qstring &sym_rel::get_original_name(const reader_t &reader) const -{ - if ( original_name.empty() ) - { - symrel_idx_t sym_idx = reader.symbols.get_idx(this); - reader.get_name(&original_name, sym_idx.type, original.st_name); - } - - return original_name; -} - -//---------------------------------------------------------------------------- -ea_t sym_rel::get_ea(const reader_t &reader, ea_t _debug_segbase) const -{ - ea_t ea = value; - if ( reader.is_valid_rel_file() ) - { - const elf_shdr_t *sh = reader.sections.getn(sec); - if ( sh != NULL ) - ea += sh->sh_addr; - } - else - { - ea += _debug_segbase; - } - return ea; -} - -//---------------------------------------------------------------------------- -void sym_rel::set_section_index(const reader_t &reader) -{ - sec = 0; - if ( original.st_shndx == SHN_XINDEX ) - { - symrel_idx_t sym_idx = reader.symbols.get_idx(this); - const elf_shdr_t *sh_shndx; - switch ( sym_idx.type ) - { - case SLT_SYMTAB: - sh_shndx = reader.sections.get_wks(WKS_SYMTAB_SHNDX); - break; - case SLT_DYNSYM: - sh_shndx = reader.sections.get_wks(WKS_DYNSYM_SHNDX); - break; - default: - INTERR(20088); - } - // doc: "The section is an array of Elf32_Word values." - uint64 offset = sym_idx.idx * sizeof(uint32); - if ( sh_shndx != NULL - && sh_shndx->sh_offset != 0 - && offset < sh_shndx->sh_size ) - { - sec = reader.get_shndx_at(sh_shndx->sh_offset + offset); - } - if ( sec == 0 ) - { - warning("AUTOHIDE SESSION\n" - "Illegal section indirect index for symbol %u", - sym_idx.idx); - } - } - else if ( original.st_shndx < SHN_LORESERVE ) - { - sec = original.st_shndx; - } -} - -//---------------------------------------------------------------------------- -reader_t::reader_t(linput_t *_li, int64 _start_in_file) - : pheaders(this), - sections(this), - sym_strtab(), - dyn_strtab(), - li(_li), - sif(_start_in_file), - mappings(), - arch_specific(NULL), - load_bias(0), - eff_msb(false), - eff_64(false), - seg_64(false) -{ - set_handler(default_error_handler); - filesize = qlsize(li); -} - -//---------------------------------------------------------------------------- -bool reader_t::is_warning(errcode_t code) const -{ - return code <= LAST_WARNING; -} - -//---------------------------------------------------------------------------- -bool reader_t::is_error(errcode_t code) const -{ - QASSERT(20035, code <= LAST_ERROR); - return code > LAST_WARNING; -} - -//------------------------------------------------------------------------- -static bool _silent_handler(const reader_t &reader, reader_t::errcode_t code, ...) -{ - return reader.is_warning(code); // resume after warnings -} - -//---------------------------------------------------------------------------- -void reader_t::set_handler(bool (*_handler)(const reader_t &reader, errcode_t code, ...)) -{ - handle_error = _handler == NULL ? _silent_handler : _handler; -} - -bool reader_t::read_ident() -{ - input_status_t save_excursion(*this); - if ( save_excursion.seek(0) == -1 ) - return false; - - uint64 fsize = size(); - uint64 fpos = tell(); - if ( fpos >= fsize ) - return false; - uint64 bytes_left = fsize - fpos; - if ( bytes_left < sizeof(elf_ident_t) ) - return false; - - memset(&header, 0, sizeof(header)); - - if ( qlread(li, &header.e_ident, sizeof(elf_ident_t)) != sizeof(elf_ident_t) ) - return false; - - if ( !header.e_ident.is_valid() ) - return false; - - size_t ehdr_sz = is_64() ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr); - if ( bytes_left < ehdr_sz ) - return false; - - return true; -} - -//---------------------------------------------------------------------------- -int reader_t::safe_read(void *buf, size_t sz, bool apply_endianness) const -{ - int rc = lreadbytes(li, buf, sz, apply_endianness && is_msb()); - if ( rc < 0 ) - handle_error(*this, ERR_READ, sz, size_t(rc), qltell(li)); - return rc; -} - -//---------------------------------------------------------------------------- -int reader_t::read_addr(void *buf) const -{ - return safe_read(buf, stdsizes.types.elf_addr); -} - -//---------------------------------------------------------------------------- -int reader_t::read_off(void *buf) const -{ - return safe_read(buf, stdsizes.types.elf_off); -} - -//---------------------------------------------------------------------------- -int reader_t::read_xword(void *buf) const -{ - return safe_read(buf, stdsizes.types.elf_xword); -} - -//---------------------------------------------------------------------------- -int reader_t::read_sxword(void *buf) const -{ - return safe_read(buf, stdsizes.types.elf_sxword); -} - -//---------------------------------------------------------------------------- -int reader_t::read_word(uint32 *buf) const -{ - return safe_read(buf, 4); -} - -//---------------------------------------------------------------------------- -int reader_t::read_half(uint16 *buf) const -{ - return safe_read(buf, 2); -} - -//---------------------------------------------------------------------------- -int reader_t::read_byte(uint8 *buf) const -{ - return safe_read(buf, 1); -} - -//------------------------------------------------------------------------- -int reader_t::read_symbol(elf_sym_t *buf) const -{ -#define _safe(expr) if ( (expr) < 0 ) goto FAILED_RS - if ( is_64() ) - { - _safe(read_word(&buf->st_name)); - _safe(read_byte(&buf->st_info)); - _safe(read_byte(&buf->st_other)); - _safe(read_half(&buf->st_shndx)); - _safe(read_addr(&buf->st_value)); - _safe(read_xword(&buf->st_size)); - } - else - { - _safe(read_word(&buf->st_name)); - _safe(read_addr(&buf->st_value)); - _safe(read_word((uint32 *) &buf->st_size)); - _safe(read_byte(&buf->st_info)); - _safe(read_byte(&buf->st_other)); - _safe(read_half(&buf->st_shndx)); - } - return 0; -FAILED_RS: - return -1; -#undef _safe -} - -#define IS_EXEC_OR_DYN(x) ((x) == ET_EXEC || (x) == ET_DYN) - -struct linuxcpu_t -{ - uint16 machine; - bool msb; - bool _64; -}; - -static const linuxcpu_t lincpus[] = -{ -// machine msb 64 - { EM_386, false, false }, - { EM_486, false, false }, - { EM_X86_64, false, true }, -}; - -//---------------------------------------------------------------------------- -// Linux kernel loader ignores class and endian fields for some(?) processors. -// check for such situation and set the effective endiannes/bitness -bool reader_t::check_ident() -{ - for ( unsigned i = 0; i < qnumber(lincpus); i++ ) - { - bool matched = false; - bool swap; - if ( eff_msb == lincpus[i].msb - && header.e_machine == lincpus[i].machine - && IS_EXEC_OR_DYN(header.e_type) ) - { - matched = true; - swap = false; - } - else if ( eff_msb != lincpus[i].msb - && swap16(header.e_machine) == lincpus[i].machine - && IS_EXEC_OR_DYN(swap16(header.e_type)) ) - { - matched = true; - swap = true; - } - if ( matched ) - { - if ( swap ) - { - header.e_machine = swap16(header.e_machine); - header.e_type = swap16(header.e_type); - if ( !handle_error(*this, BAD_ENDIANNESS, header.e_ident.bytesex) ) - return false; - eff_msb = lincpus[i].msb; - } - // segment bitness can be different from elf bitness: apparently there - // are some files like that in the wild (see pc_odd_bitness_64.elf) - seg_64 = lincpus[i]._64; - // assume elf32 for EM_386/EM_486 - if ( !seg_64 ) - eff_64 = false; - break; - } - } - return true; -} - -//---------------------------------------------------------------------------- -bool reader_t::read_header() -{ - // 32/64 - uint8 elf_class = get_ident().elf_class; - if ( elf_class != ELFCLASS32 - && elf_class != ELFCLASS64 ) - { - if ( !handle_error(*this, BAD_CLASS, elf_class) ) - return false; - } - // lsb/msb - uint8 elf_do = get_ident().bytesex; - if ( elf_do != ELFDATA2LSB - && elf_do != ELFDATA2MSB ) - { - if ( !handle_error(*this, BAD_ENDIANNESS, elf_do) ) - return false; - } - - input_status_t save_excursion(*this); - if ( save_excursion.seek(sizeof(elf_ident_t)) == -1 ) - return false; - - // set the default values from ident - eff_msb = elf_do == ELFDATA2MSB; - eff_64 = elf_class == ELFCLASS64; - seg_64 = eff_64; - - // Read the type and machine -#define _safe(expr) if ( (expr) < 0 ) goto FAILED - _safe(read_half(&header.e_type)); - _safe(read_half(&header.e_machine)); - - if ( !check_ident() ) - return false; - - // Define sizes - if ( !is_64() ) - { - stdsizes.ehdr = sizeof(Elf32_Ehdr); - stdsizes.phdr = sizeof(Elf32_Phdr); - stdsizes.shdr = sizeof(Elf32_Shdr); - stdsizes.entries.sym = sizeof(Elf32_Sym); - stdsizes.entries.dyn = sizeof(Elf32_Dyn); - stdsizes.entries.rel = sizeof(Elf32_Rel); - stdsizes.entries.rela = sizeof(Elf32_Rela); - stdsizes.types.elf_addr = 4; - stdsizes.types.elf_off = 4; - stdsizes.types.elf_xword= 4; - stdsizes.types.elf_sxword=4; - } - else - { - stdsizes.ehdr = sizeof(Elf64_Ehdr); - stdsizes.phdr = sizeof(Elf64_Phdr); - stdsizes.shdr = sizeof(Elf64_Shdr); - stdsizes.entries.sym = sizeof(Elf64_Sym); - stdsizes.entries.dyn = sizeof(Elf64_Dyn); - stdsizes.entries.rel = sizeof(Elf64_Rel); - stdsizes.entries.rela = sizeof(Elf64_Rela); - stdsizes.types.elf_addr = 8; - stdsizes.types.elf_off = 8; - stdsizes.types.elf_xword= 8; - stdsizes.types.elf_sxword=8; - } - stdsizes.dyn.sym = stdsizes.entries.sym; - stdsizes.dyn.rel = stdsizes.entries.rel; - stdsizes.dyn.rela = stdsizes.entries.rela; - - // Read the rest of the header - _safe(read_word(&header.e_version)); - _safe(read_addr(&header.e_entry)); - _safe(read_off (&header.e_phoff)); - _safe(read_off (&header.e_shoff)); - _safe(read_word(&header.e_flags)); - _safe(read_half(&header.e_ehsize)); - _safe(read_half(&header.e_phentsize)); - _safe(read_half(&header.e_phnum)); - _safe(read_half(&header.e_shentsize)); - _safe(read_half(&header.e_shnum)); - _safe(read_half(&header.e_shstrndx)); -#undef _safe - - if ( header.e_ehsize != stdsizes.ehdr ) - if ( !handle_error(*this, BAD_EHSIZE, header.e_ehsize, stdsizes.ehdr) ) - { -FAILED: - return false; - } - - // Sanitize PHT parameters - if ( (header.e_phnum == 0) != (header.e_phoff == 0) ) - { - if ( !handle_error(*this, BAD_PHLOC, header.e_phnum, header.e_phoff) ) - goto FAILED; - header.set_no_pht(); - } - if ( header.has_pht() && header.e_phentsize != stdsizes.phdr ) - { - if ( !handle_error(*this, BAD_PHENTSIZE, header.e_phentsize, stdsizes.phdr) - || header.e_phentsize < stdsizes.phdr ) - { - goto FAILED; - } - header.e_phentsize = stdsizes.phdr; - } - - // process large number of sections - // "System V Application Binary Interface - DRAFT - 19 October 2010" - // If the number of sections is greater than or equal to SHN_LORESERVE - // (0xff00), this member has the value zero and the actual number of - // section header table entries is contained in the sh_size field of the - // section header at index 0. (Otherwise, the sh_size member of the - // initial entry contains 0.) - elf_shdr_t sh0; - bool is_sh0_read; - if ( header.e_shnum == 0 - && header.e_shoff != 0 - && seek(header.e_shoff) != -1 - && read_section_header(&sh0) - && sh0.sh_type == SHT_NULL ) - { - is_sh0_read = true; - header.real_shnum = sh0.sh_size; - } - else - { - is_sh0_read = false; - header.real_shnum = header.e_shnum; - } - - // Sanitize SHT parameters - if ( (header.real_shnum == 0) != (header.e_shoff == 0) ) - { - if ( !handle_error(*this, BAD_SHLOC, header.real_shnum, header.e_shoff, size()) ) - goto FAILED; - header.set_no_sht(); // do not use sht - } - if ( header.has_sht() && header.e_shentsize != stdsizes.shdr ) - { - if ( !handle_error(*this, BAD_SHENTSIZE, header.e_shentsize, stdsizes.shdr) - || header.e_shentsize < stdsizes.shdr ) - { - header.set_no_sht(); // do not use sht - } - } - { - uint64 sections_start = header.e_shoff; - uint64 sections_finish = header.e_shoff + uint64(header.real_shnum) * header.e_shentsize; - if ( sections_start > sections_finish || sections_finish > size() ) - { - if ( !handle_error(*this, BAD_SHLOC, header.real_shnum, header.e_shoff, size()) ) - goto FAILED; - header.set_no_sht(); // do not use sht - } - } - - if ( header.has_sht() ) - { - // process large section name string table section index - // "System V Application Binary Interface - DRAFT - 19 October 2010" - // If the section name string table section index is greater than or equal - // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX - // (0xffff) and the actual index of the section name string table section - // is contained in the sh_link field of the section header at index 0. - // (Otherwise, the sh_link member of the initial entry contains 0.) - if ( header.e_shstrndx == SHN_XINDEX && is_sh0_read && sh0.sh_link != 0 ) - header.real_shstrndx = sh0.sh_link; - else - header.real_shstrndx = header.e_shstrndx; - - // Sanitize SHT string table index - if ( header.real_shstrndx > 0 - && header.real_shstrndx >= header.real_shnum ) - { - if ( !handle_error(*this, BAD_SHSTRNDX, uint(header.real_shstrndx), uint(header.real_shnum)) ) - goto FAILED; - header.real_shstrndx = 0; - } - } - - // - if ( header.has_pht() && header.e_type == ET_REL ) - { - if ( !handle_error(*this, CONFLICTING_FILE_TYPE) ) - goto FAILED; - } - - // - switch ( header.e_machine ) - { - case EM_AARCH64: - // AARCH64 files must use 64-bit segments even for ELF32 (ILP32) - seg_64 = true; - // fallthrough - case EM_ARM: - delete arch_specific; - arch_specific = new arm_arch_specific_t; - break; - default: - arch_specific = new arch_specific_t; // Dummy - break; - } - return true; -} - -//---------------------------------------------------------------------------- -bool reader_t::read_section_header(elf_shdr_t *sh) -{ -#define _safe(expr) if ( expr < 0 ) return false; - _safe(read_word (&sh->sh_name)); - _safe(read_word (&sh->sh_type)); - _safe(read_xword(&sh->sh_flags)); - _safe(read_addr (&sh->sh_addr)); - _safe(read_off (&sh->sh_offset)); - _safe(read_xword(&sh->sh_size)); - _safe(read_word (&sh->sh_link)); - _safe(read_word (&sh->sh_info)); - _safe(read_xword(&sh->sh_addralign)); - _safe(read_xword(&sh->sh_entsize)); -#undef _safe - return true; -} - -//------------------------------------------------------------------------- -bool reader_t::read_compression_header(elf_chdr_t *out) -{ -#define _safe(expr) if ( expr < 0 ) return false; - _safe(read_word(&out->ch_type)); - if ( is_64() ) - _safe(read_word(&out->ch_reserved)); - _safe(read_xword(&out->ch_size)); - _safe(read_xword(&out->ch_addralign)); -#undef _safe - return true; -} - -//---------------------------------------------------------------------------- -bool reader_t::read_section_headers() -{ - if ( !header.has_sht() ) - return false; - input_status_t save_excursion(*this); - if ( save_excursion.seek(header.e_shoff) == -1 ) - return false; - - sections.resize(header.real_shnum); - - sections.initialized = true; - - for ( elf_shndx_t i = 0; i < header.real_shnum; i++ ) - { - if ( !seek_to_section_header(i) ) - return false; - - elf_shdr_t *sh = sections.getn(i); - if ( !read_section_header(sh) ) - return false; - } - - // in the first pass we store WKS_SYMTAB/WKS_DYNSYM to process sections - // of type SHT_SYMTAB_SHNDX in the second pass - typedef elf_shdrs_t::const_iterator const_iter; - const_iter it = sections.begin(); - const_iter end = sections.end(); - for ( elf_shndx_t i = 0; it != end; ++it, ++i ) - { - if ( i == 0 ) // Skip first header - continue; - const elf_shdr_t &sh = *it; - if ( sh.sh_size == 0 ) - continue; - - switch ( sh.sh_type ) - { - case SHT_SYMTAB: - { - sections.set_index(WKS_SYMTAB, i); - elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); - if ( strtab_sh == NULL ) - { - msg("Illegal link section %d of the string table " - "for symbols\n", - sh.sh_link); - } - else - { - set_sh_strtab(sym_strtab, *strtab_sh, true); - } - } - break; - - case SHT_DYNSYM: - { - sections.set_index(WKS_DYNSYM, i); - elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); - if ( strtab_sh == NULL ) - { - msg("Illegal link section %d of the string table " - "for dynamic linking symbols\n", - sh.sh_link); - } - else - { - set_sh_strtab(dyn_strtab, *strtab_sh, true); - } - } - break; - - case SHT_DYNAMIC: - { - elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); - if ( strtab_sh == NULL ) - { - msg("Illegal link section %d of the dynamic linking " - "information section\n", - sh.sh_link); - } - else if ( strtab_sh->sh_type == SHT_DYNSYM ) - { - // OAT file: .dynamic section links to .dynsym section - strtab_sh->sh_link = 0; - } - else - { - set_sh_strtab(dyn_strtab, *strtab_sh, true); - } - } - break; - } - } - - // initialize the section name string table - if ( header.real_shstrndx != 0 ) - { - elf_shdr_t *shstrtab = sections.getn(header.real_shstrndx); - if ( shstrtab != NULL ) - { - // we do not check type of this section here - // (in some cases it may be not SHT_STRTAB) - sections.strtab.offset = shstrtab->sh_offset; - sections.strtab.addr = shstrtab->sh_addr; - sections.strtab.size = shstrtab->sh_size; - } - } - - qstring name; - it = sections.begin(); - for ( elf_shndx_t i = 0; it != end; ++it, ++i ) - { - if ( i == 0 ) // Skip first header - continue; - - const elf_shdr_t &sh = *it; - if ( sh.sh_size == 0 ) - continue; - - name.qclear(); - sections.get_name(&name, &sh); - switch ( sh.sh_type ) - { - case SHT_STRTAB: - // we specify replace = false as this section has less priority - // compared to the sh_link section - if ( name == ".strtab" ) - set_sh_strtab(sym_strtab, sh, false); - else if ( name == ".dynstr" ) - set_sh_strtab(dyn_strtab, sh, false); - break; - - case SHT_SYMTAB_SHNDX: - if ( sh.sh_link != 0 ) - { - if ( sh.sh_link == sections.get_index(WKS_SYMTAB) ) - sections.set_index(WKS_SYMTAB_SHNDX, i); - if ( sh.sh_link == sections.get_index(WKS_DYNSYM) ) - sections.set_index(WKS_DYNSYM_SHNDX, i); - } - break; - - case SHT_GNU_verdef: - sections.set_index(WKS_VERDEF, i); - break; - case SHT_GNU_verneed: - sections.set_index(WKS_VERNEED, i); - break; - case SHT_GNU_versym: - sections.set_index(WKS_VERSYM, i); - break; - - case SHT_PROGBITS: - if ( name == ".interp" ) - { - sections.set_index(WKS_INTERP, i); - break; - } - else if ( name == ".got" ) - { - sections.set_index(WKS_GOT, i); - sections.set_got_original(); - break; - } - else if ( name == ".got.plt" ) - { - sections.set_index(WKS_GOTPLT, i); - break; - } - else if ( name == ".plt.got" ) - { - sections.set_index(WKS_PLTGOT, i); - break; - } - else if ( name == ".plt.sec" ) - { - sections.set_index(WKS_PLTSEC, i); - break; - } - // function pointers for PPC64 (may be for IA64, HPPA64) - else if ( is_64() && name == ".opd" ) - { - sections.set_index(WKS_OPD, i); - break; - } - // no break - case SHT_NOBITS: - if ( name == ".plt" ) - sections.set_index(WKS_PLT, i); - break; - } - } - - if ( sections.get_index(WKS_GOTPLT) == 0 ) - sections.set_index(WKS_GOTPLT, sections.get_index(WKS_GOT)); - else if ( sections.get_index(WKS_GOT) == 0 ) - sections.set_index(WKS_GOTPLT, 0); // unsupported format - - return true; -} - -//---------------------------------------------------------------------------- -bool reader_t::read_program_headers() -{ - if ( !header.has_pht() ) - return false; - input_status_t save_excursion(*this); - if ( save_excursion.seek(header.e_phoff) == -1 ) - return false; - - int count = header.e_phnum; -#ifdef BUILD_LOADER - validate_array_count_or_die(get_linput(), count, header.e_phentsize, "PHT entries"); -#endif - pheaders.resize(count); - - pheaders.initialized = true; - - elf_phdr_t *dyn_phdr = NULL; - for ( int i = 0; i < count; i++ ) - { - if ( !seek_to_program_header(i) ) - return false; - - elf_phdr_t *phdr = pheaders.get(i); -#define _safe(expr) \ - do \ - { \ - if ( expr < 0 ) \ - { \ - pheaders.resize(i == 0 ? 0 : i-1); \ - return false; \ - } \ - } while ( false ) - _safe(read_word(&phdr->p_type)); - if ( is_64() ) - _safe(read_word(&phdr->p_flags)); - _safe(read_off(&phdr->p_offset)); - _safe(read_addr(&phdr->p_vaddr)); - _safe(read_addr(&phdr->p_paddr)); - _safe(read_xword(&phdr->p_filesz)); - _safe(read_xword(&phdr->p_memsz)); - if ( !is_64() ) - _safe(read_word(&phdr->p_flags)); - _safe(read_xword(&phdr->p_align)); -#undef _safe - - switch ( phdr->p_type ) - { - case PT_LOAD: - add_mapping(*phdr); - - // ELF_Format.pdf page 2-4 - // The base address in ELF is "the lowest virtual address associated - // with the memory image of the program's object file". - if ( phdr->p_vaddr < pheaders.get_image_base() ) - { - // NOTE The default maximum page size is processor specific. - // The ELF standard vaguely mentions ("Program Loading") - // that 4 KB is the maximum page size for the SYSTEM V - // architecture, so we use this value. - const ea_t maximum_page_size = 0x1000; - // Truncate the memory address to the nearest multiple of the - // maximum page size. - ea_t image_base = phdr->p_vaddr & ~(maximum_page_size - 1); - pheaders.set_image_base(image_base); - } - - break; - case PT_DYNAMIC: - dyn_phdr = phdr; - break; - } - } - - if ( dyn_phdr != NULL ) - { - // in some files, p_filesz is 0, so take max of the two - // TODO: use the size of the surrounding PT_LOAD segment, - // since the dynamic loader does not use the size field - size_t dsize = qmax(dyn_phdr->p_filesz, dyn_phdr->p_memsz); - // p_offset may be wrong, always use p_vaddr - size_t fileoff = file_offset(dyn_phdr->p_vaddr); - pheaders.set_dynlink_table_info(fileoff, dyn_phdr->p_vaddr, dsize, -1); - } - - return true; -} - -//---------------------------------------------------------------------------- -void reader_t::set_sh_strtab( - dynamic_info_t::entry_t &strtab, - const elf_shdr_t &strtab_sh, - bool replace) -{ - // we don't check that type of section should be SHT_STRTAB, - // we just reject illegal section type - if ( strtab_sh.sh_type == SHT_NULL - || strtab_sh.sh_type == SHT_REL - || strtab_sh.sh_type == SHT_RELA - || strtab_sh.sh_type == SHT_DYNAMIC - || strtab_sh.sh_type == SHT_DYNSYM - || strtab_sh.sh_type == SHT_SYMTAB ) - { - msg("Illegal type %s of the string table section\n", - sections.sh_type_qstr(strtab_sh.sh_type).c_str()); - return; - } - if ( strtab_sh.sh_offset == 0 ) - { - msg("Illegal offset of the string table section\n"); - return; - } - // store the string table info - if ( strtab.is_valid() ) - { - if ( strtab.offset == strtab_sh.sh_offset ) - return; - warning("AUTOHIDE SESSION\n" - "More than one string table for %ssymbols, " - "using one at offset %08" FMT_64 "X", - &strtab == &dyn_strtab ? "dynamic linking " : "", - replace ? strtab_sh.sh_offset : strtab.offset); - if ( !replace ) - return; - } - strtab.offset = strtab_sh.sh_offset; - strtab.addr = strtab_sh.sh_addr; - strtab.size = strtab_sh.sh_size; -} - -//---------------------------------------------------------------------------- -void reader_t::set_di_strtab( - dynamic_info_t::entry_t &strtab, - const dynamic_info_t::entry_t &strtab_di) -{ - if ( !strtab_di.is_valid() ) - return; - if ( strtab.is_valid() ) - { - if ( strtab.offset == strtab_di.offset ) - return; - warning("The dynamic section string table " - "from section header (%08" FMT_64 "X) differs " - "from DT_STRTAB's one (%08" FMT_64 "X), " - "using the latter", - strtab.offset, - strtab_di.offset); - } - strtab = strtab_di; -} - -//---------------------------------------------------------------------------- -bool reader_t::read_notes(notes_t *notes) -{ - notes->clear(); - - if ( sections.initialized ) - { - for ( elf_shdrs_t::const_iterator p=sections.begin(); p != sections.end(); ++p ) - { - const elf_shdr_t &sh = *p; - if ( sh.sh_type != SHT_NOTE ) - continue; - bytevec_t buf; - sections.read_file_contents(&buf, sh); - notes->add(buf); - } - } - - if ( pheaders.initialized ) - { - for ( elf_phdrs_t::const_iterator q=pheaders.begin(); q != pheaders.end(); ++q ) - { - const elf_phdr_t &p = *q; - if ( p.p_type != PT_NOTE ) - continue; - bytevec_t buf; - pheaders.read_file_contents(&buf, p); - notes->add(buf); - } - } - - notes->initialized = true; - return true; -} - -//---------------------------------------------------------------------------- -elf_sym_idx_t reader_t::rel_info_index(const elf_rela_t &r) const -{ - if ( is_64() && !is_msb() && header.e_machine == EM_MIPS ) - { - // MIPS64 does not use 64-bit r_info but always puts symbol index at low address - // so for LE we need to return low part of r_info - return uint32(r.r_info); - } - if ( is_64() ) - return ELF64_R_SYM(r.r_info); - else - return ELF32_R_SYM(r.r_info); -} - -//---------------------------------------------------------------------------- -uint32 reader_t::rel_info_type(const elf_rela_t &r) const -{ - if ( is_64() && !is_msb() && header.e_machine == EM_MIPS ) - { - // MIPS64 does not use a 64-bit r_info but always puts symbol index at low address - // so in case of LE we need to return the high part of r_info - // we also need to convert it to BE - // so that macros like ELF64_MIPS_R_TYPE work properly - return swap32(r.r_info>>32); - } - if ( is_64() ) - return ELF64_R_TYPE(r.r_info); - else - return ELF32_R_TYPE(r.r_info); -} - -//---------------------------------------------------------------------------- -void reader_t::set_rel_info_index(elf_rela_t *r, uint32 symidx) const -{ - if ( !is_64() ) - { - r->r_info = ELF32_R_INFO(uint64(symidx), ELF32_R_TYPE(r->r_info)); - } - else if ( !is_msb() && header.e_machine == EM_MIPS ) - { - // MIPS64 does not use the 64-bit r_info, but always puts the symbol - // index at the low address, so for LE we need to update the low part of - // r_info - r->r_info &= ~0xFFFFFFFF; - r->r_info |= uint64(symidx) << 32; - } - else - { - r->r_info &= 0xFFFFFFFF; - r->r_info |= symidx; - } -} - -//---------------------------------------------------------------------------- -void reader_t::set_rel_info_type(elf_rela_t *r, uint32 type) const -{ - if ( !is_64() ) - { - r->r_info = ELF32_R_INFO(ELF32_R_SYM(r->r_info), type); - } - else if ( !is_msb() && header.e_machine == EM_MIPS ) - { - // MIPS64 does not use the 64-bit r_info, but always puts the symbol - // index at the low address, so for LE we need to update the high part - // of r_info. - // we also need to convert it to BE - r->r_info &= 0xFFFFFFFF; - r->r_info |= uint64(swap32(type)) << 32; - } - else - { - r->r_info &= ~0xFFFFFFFF; - r->r_info |= type; - } -} - -//---------------------------------------------------------------------------- -const char *reader_t::file_type_str() const -{ - const char *file_type = "Unknown"; - switch ( header.e_type ) - { - case ET_NONE: file_type = "None"; break; - case ET_REL: file_type = "Relocatable"; break; - case ET_EXEC: file_type = "Executable"; break; - case ET_DYN: file_type = "Shared object"; break; - case ET_CORE: file_type = "Core file"; break; - case ET_LOPROC: file_type = "Processor specific"; break; - case ET_HIPROC: file_type = "Processor specific"; break; - case ET_IRX: - if ( header.e_machine == EM_MIPS ) - file_type = "PS2 IRX"; - break; - case ET_PSPEXEC: - if ( header.e_machine == EM_MIPS ) - file_type = "PSP executable"; - break; - case ET_PS3PRX: - if ( header.e_machine == EM_PPC64 ) - file_type = "Sony PS3 PRX file"; - break; - } - return file_type; -} - -//---------------------------------------------------------------------------- -const char *reader_t::os_abi_str() const -{ - uint8 os_abi = get_ident().osabi; - const char *abi; - switch ( os_abi ) - { - case ELFOSABI_NONE: abi = "UNIX System V ABI"; break; - case ELFOSABI_HPUX: abi = "HP-UX operating system"; break; - case ELFOSABI_NETBSD: abi = "NetBSD"; break; - case ELFOSABI_LINUX: abi = "GNU/Linux"; break; - case ELFOSABI_HURD: abi = "GNU/Hurd"; break; - case ELFOSABI_SOLARIS: abi = "Solaris"; break; - case ELFOSABI_AIX: abi = "AIX"; break; - case ELFOSABI_IRIX: abi = "IRIX"; break; - case ELFOSABI_FREEBSD: abi = "FreeBSD"; break; - case ELFOSABI_TRU64: abi = "TRU64 UNIX"; break; - case ELFOSABI_MODESTO: abi = "Novell Modesto"; break; - case ELFOSABI_OPENBSD: abi = "OpenBSD"; break; - case ELFOSABI_OPENVMS: abi = "OpenVMS"; break; - case ELFOSABI_NSK: abi = "Hewlett-Packard Non-Stop Kernel"; break; - case ELFOSABI_AROS: abi = "Amiga Research OS"; break; - case ELFOSABI_ARM: abi = "ARM"; break; - case ELFOSABI_STANDALONE: abi = "Standalone (embedded) application"; break; - case ELFOSABI_CELLOSLV2: - if ( header.e_machine == EM_PPC64 ) - { - abi = "PS3 Cell OS lv2"; - break; - } - // fall through - default: - abi = "Unknown"; - break; - } - return abi; -} - -//---------------------------------------------------------------------------- -const char *reader_t::machine_name_str() const -{ - uint32 m = get_header().e_machine; - switch ( m ) - { - case EM_NONE: return "<No machine>"; - case EM_M32: return "AT & T WE 32100"; - case EM_SPARC: return "SPARC"; - case EM_386: return "Intel 386"; - case EM_68K: return "Motorola 68000"; - case EM_88K: return "Motorola 88000"; - case EM_486: return "Intel 486"; - case EM_860: return "Intel 860"; - case EM_MIPS: return "MIPS"; - case EM_S370: return "IBM System370"; - case EM_MIPS_RS3_BE: return "MIPS R3000 Big Endian"; - case EM_PARISC: return "PA-RISC"; - case EM_VPP550: return "Fujitsu VPP500"; - case EM_SPARC32PLUS: return "SPARC v8+"; - case EM_I960: return "Intel 960"; - case EM_PPC: return "PowerPC"; - case EM_PPC64: return "PowerPC 64"; - case EM_S390: return "IBM S/390"; - case EM_S390_OLD: return "IBM S/390 (old magic)"; - case EM_SPU: return "Cell BE SPU"; - case EM_CISCO7200: return "Cisco 7200 Series Router (MIPS)"; - case EM_CISCO3620: return "Cisco 3620/3640 Router (MIPS)"; - case EM_V800: return "NEC V800 or Renesas RH850"; - case EM_FR20: return "Fujitsu FR20"; - case EM_RH32: return "TRW RH-22"; - case EM_MCORE: return "Motorola M*Core"; - case EM_ARM: return "ARM"; - case EM_OLD_ALPHA: return "Digital Alpha"; - case EM_SH: return "SuperH"; - case EM_SPARC64: return "SPARC 64"; - case EM_TRICORE: return "Siemens Tricore"; - case EM_ARC: return "ARC"; - case EM_H8300: return "H8/300"; - case EM_H8300H: return "H8/300H"; - case EM_H8S: return "Hitachi H8S"; - case EM_H8500: return "H8/500"; - case EM_IA64: return "Itanium IA64"; - case EM_MIPS_X: return "Stanford MIPS-X"; - case EM_COLDFIRE: return "Coldfire"; - case EM_6812: return "MC68HC12"; - case EM_MMA: return "Fujitsu MMA"; - case EM_PCP: return "Siemens PCP"; - case EM_NCPU: return "Sony nCPU"; - case EM_NDR1: return "Denso NDR1"; - case EM_STARCORE: return "Star*Core"; - case EM_ME16: return "Toyota ME16"; - case EM_ST100: return "ST100"; - case EM_TINYJ: return "TinyJ"; - case EM_X86_64: return "x86-64"; - case EM_PDSP: return "PDSP"; - case EM_PDP10: return "DEC PDP-10"; - case EM_PDP11: return "DEC PDP-11"; - case EM_FX66: return "Siemens FX66"; - case EM_ST9: return "ST9+"; - case EM_ST7: return "ST7"; - case EM_68HC16: return "MC68HC16"; - case EM_6811: return "MC68HC11"; - case EM_68HC08: return "MC68HC08"; - case EM_68HC05: return "MC68HC05"; - case EM_SVX: return "Silicon Graphics SVx"; - case EM_ST19: return "ST19"; - case EM_VAX: return "VAX"; - case EM_CRIS: return "CRIS"; - case EM_JAVELIN: return "Infineon Javelin"; - case EM_FIREPATH: return "Element 14 Firepath"; - case EM_ZSP: return "ZSP"; - case EM_MMIX: return "MMIX"; - case EM_HUANY: return "Harvard HUANY"; - case EM_PRISM: return "SiTera Prism"; - case EM_AVR: return "Atmel"; - case EM_FR: return "Fujitsu FR"; - case EM_D10V: return "Mitsubishi D10V"; - case EM_D30V: return "Mitsubishi D30V"; - case EM_V850: // (GNU compiler) - case EM_CYGNUS_V850: - case EM_NECV850: return "NEC V850"; // (NEC compilers) - case EM_NECV850E: return "NEC v850E"; - case EM_NECV850E2: return "NEC v850E2"; - case EM_NECV850ES: return "NEC v850ES"; - case EM_NECV850E2R1: return "NEC v850E2R1"; - case EM_NECV850E2R2: return "NEC v850E2R2"; - case EM_NECV850E2R3: return "NEC v850E2R3"; - case EM_NECV850E2R4: return "NEC v850E2R4"; - case EM_NECV850E3V5: return "NEC v850E3V5"; - case EM_M32R: return "M32R"; - case EM_MN10300: return "MN10300"; - case EM_MN10200: return "MN10200"; - case EM_PJ: return "picoJava"; - case EM_OPENRISC : return "OpenRISC"; - case EM_ARCOMPACT: return "ARCompact"; - case EM_XTENSA: return "Xtensa"; - case EM_VIDEOCORE: return "VideoCore"; - case EM_TMM_GPP: return "Thompson GPP"; - case EM_NS32K: return "NS 32000"; - case EM_TPC: return "TPC"; - case EM_SNP1K: return "SNP 1000"; - case EM_ST200: return "ST200"; - case EM_IP2K: return "IP2022"; - case EM_MAX: return "MAX"; - case EM_CR: return "CompactRISC"; - case EM_F2MC16: return "F2MC16"; - case EM_MSP430: return "MSP430"; - case EM_BLACKFIN: return "ADI Blackfin"; - case EM_SE_C33: return "S1C33"; - case EM_SEP: return "SEP"; - case EM_ARCA: return "Arca"; - case EM_UNICORE: return "Unicore"; - case EM_EXCESS: return "eXcess"; - case EM_DXP: return "Icera DXP"; - case EM_ALTERA_NIOS2: return "Nios II"; - case EM_CRX: return "CRX"; - case EM_XGATE: return "XGATE"; - case EM_C166: return "C16x/XC16x/ST10"; - case EM_M16C: return "M16C"; - case EM_DSPIC30F: return "dsPIC30F"; - case EM_CE: return "Freescale Communication Engine"; - case EM_M32C: return "M32C"; - case EM_TSK3000: return "TSK3000"; - case EM_RS08: return "RS08"; - case EM_ECOG2: return "eCOG2"; - case EM_SCORE: return "Sunplus Score"; - case EM_DSP24: return "NJR DSP24"; - case EM_VIDEOCORE3: return "VideoCore III"; - case EM_LATTICEMICO32: return "Lattice Mico32"; - case EM_SE_C17: return "C17"; - case EM_MMDSP_PLUS: return "MMDSP"; - case EM_CYPRESS_M8C: return "M8C"; - case EM_R32C: return "R32C"; - case EM_TRIMEDIA: return "TriMedia"; - case EM_QDSP6: return "QDSP6"; - case EM_8051: return "i8051"; - case EM_STXP7X: return "STxP7x"; - case EM_NDS32: return "NDS32"; - case EM_ECOG1X: return "eCOG1X"; - case EM_MAXQ30: return "MAXQ30"; - case EM_XIMO16: return "NJR XIMO16"; - case EM_MANIK: return "M2000"; - case EM_CRAYNV2: return "Cray NV2"; - case EM_RX: return "RX"; - case EM_METAG: return "Imagination Technologies META"; - case EM_MCST_ELBRUS: return "MCST Elbrus"; - case EM_ECOG16: return "eCOG16"; - case EM_CR16: return "CompactRISC 16-bit"; - case EM_ETPU: return "Freescale ETPU"; - case EM_SLE9X: return "SLE9X"; - case EM_L1OM: return "Intel L1OM"; - case EM_K1OM: return "Intel K1OM"; - case EM_INTEL182: return "Intel Reserved (182)"; - case EM_AARCH64: return "ARM64"; - case EM_ARM184: return "ARM Reserved (184)"; - case EM_AVR32: return "AVR32"; - case EM_STM8: return "STM8"; - case EM_TILE64: return "Tilera TILE64"; - case EM_TILEPRO: return "Tilera TILEPro"; - case EM_MICROBLAZE: return "MicroBlaze"; - case EM_CUDA: return "CUDA"; - case EM_TILEGX: return "Tilera TILE-Gx"; - case EM_CLOUDSHIELD: return "CloudShield"; - case EM_COREA_1ST: return "Core-A 1st gen"; - case EM_COREA_2ND: return "Core-A 2nd gen"; - case EM_ARC_COMPACT2: return "ARCompactV2"; - case EM_OPEN8: return "Open8"; - case EM_RL78: return "RL78"; - case EM_VIDEOCORE5: return "VideoCore V"; - case EM_78K0R: return "78K0R"; - case EM_56800EX: return "Freescale 56800EX"; - case EM_BA1: return "Beyond BA1"; - case EM_BA2: return "Beyond BA2"; - case EM_XCORE: return "XMOS xCORE"; - case EM_CYGNUS_POWERPC: return "PowerPC"; - case EM_ALPHA: return "DEC Alpha"; - case EM_TI_C6000: return "TMS320C6"; - default: return nullptr; - } -} - -//---------------------------------------------------------------------------- -qstring reader_t::get_machine_name() const -{ - qstring s = machine_name_str(); - if ( s.empty() ) - s.sprnt("Unknown CPU [%u]", get_header().e_machine); - return s; -} - -//---------------------------------------------------------------------------- -bool reader_t::read_prelink_base(uint32 *base) -{ - int64 fsize = size(); - input_status_t save_excursion(*this); - if ( save_excursion.seek(fsize - 4) == -1 ) - return false; - - char tag[4]; - bool ok = false; - if ( qlread(li, tag, 4) == 4 ) - { - if ( memcmp(tag, "PRE ", 4) == 0 ) - { - if ( qlseek(li, fsize - 8) != -1 && read_word(base) >= 0 ) - ok = true; - } - } - - return ok; -} - -//---------------------------------------------------------------------------- -bool reader_t::get_string_at(qstring *out, uint64 offset) const -{ - input_status_t save_excursion(*this); - if ( save_excursion.seek(offset) == -1 ) - { - out->sprnt("bad offset %08x", low(offset)); - return false; - } - - bool ret = true; - out->clear(); - char buffer[100]; - while ( true ) - { - int read = qlread(li, buffer, sizeof(buffer)); - if ( read < 0 ) - { - out->append("{truncated name}"); - ret = false; - break; - } - - // Find the position of the trailing zero - int pos; - for ( pos = 0; pos < read && buffer[pos] != '\0'; pos++ ) - ; - - out->append(buffer, pos); - if ( pos < sizeof(buffer) ) - break; - } - return ret; -} - -//---------------------------------------------------------------------------- -elf_shndx_t reader_t::get_shndx_at(uint64 offset) const -{ - input_status_t save_excursion(*this); - if ( save_excursion.seek(offset) == -1 ) - return 0; - CASSERT(sizeof(elf_shndx_t) == sizeof(uint32)); - uint32 res; - if ( read_word(&res) < 0 ) - return 0; - return res; -} - -//-------------------------------------------------------------------------- -// Fills 'out' with either a fake entry from the DHT or an entry from the SHT. -static bool get_versym_section( - elf_shdr_t *out, - slice_type_t *slice_type, - const reader_t &reader, - wks_t sht_idx, - const dynamic_info_t &di, - dynamic_info_type_t dht_idx, - bool use_pht) -{ - *slice_type = SLT_INVALID; - if ( use_pht ) - { - if ( di.fill_section_header(out, dht_idx) ) - *slice_type = SLT_DYNSYM; - } - else - { - const elf_shdr_t *sht_entry = reader.sections.get_wks(sht_idx); - if ( sht_entry != NULL ) - { - *out = *sht_entry; - if ( sht_entry->sh_link == reader.sections.get_index(WKS_SYMTAB) - && reader.symbols.slice_size(SLT_SYMTAB) != 0 ) - { - *slice_type = SLT_SYMTAB; - } - else if ( sht_entry->sh_link == reader.sections.get_index(WKS_DYNSYM) - && reader.symbols.slice_size(SLT_DYNSYM) != 0 ) - { - *slice_type = SLT_DYNSYM; - } - } - } - return *slice_type != SLT_INVALID; -} - -//---------------------------------------------------------------------------- -// Helper class for reading version info sections. DT_VERDEF and DT_VERNEED -// have similar structures for reading main and auxiliary entries. -template <class T_entry, class T_aux> -struct elf_ver_parser_t -{ - const reader_t &reader; - - elf_ver_parser_t(const reader_t &_reader) - : reader(_reader) - {} - - virtual void entry_cb(const T_entry &, int64, size_t) = 0; - virtual void aux_cb(const T_aux &, int64, size_t) = 0; - - void parse(int64 offset, size_t size) - { - int64 orig_offset = offset; - input_status_t save_excursion(reader); - int64 end = offset + size; - size_t entry_idx = 0; - std::set<int64> entry_seen; - while ( offset < end && entry_seen.insert(offset).second ) - { - T_entry entry; - if ( save_excursion.seek(offset) == -1 || !entry.read(reader) ) - break; - - entry_cb(entry, offset - orig_offset, entry_idx++); - - int64 aux_offset = offset + entry.aux(); - size_t aux_idx = 0; - std::set<int64> aux_seen; - while ( aux_offset < end - && aux_seen.insert(aux_offset).second - && aux_idx < entry.cnt() ) - { - T_aux aux; - if ( save_excursion.seek(aux_offset) == -1 || !aux.read(reader) ) - break; - - aux_cb(aux, aux_offset - orig_offset, aux_idx++); - - aux_offset += aux.next(); - } - - offset += entry.next(); - } - } -}; - -//---------------------------------------------------------------------------- -bool reader_t::read_symbol_versions( - elf_symbol_version_t *symver, - const dynamic_info_t &di, - bool use_pht) -{ - elf_shdr_t sh; - slice_type_t st; - - // Read version requirement entries from DT_VERNEED - struct elf_verneed_parser_t - : public elf_ver_parser_t<elf_verneed_t, elf_vernaux_t> - { - typedef elf_ver_parser_t<elf_verneed_t, elf_vernaux_t> inherited; - - elf_symbol_version_t &symver; - slice_type_t st; - elf_verneed_parser_t( - const reader_t &_reader, - elf_symbol_version_t &_symver, - slice_type_t _st) - : inherited(_reader), - symver(_symver), - st(_st) - { - } - - virtual void entry_cb(const elf_verneed_t &verneed, int64 offset, size_t) override - { - symbol_verneed_t &reqfile = symver.reqs.push_back(); - reqfile.offset = offset; - // TODO check verneed.vn_version - reqfile.name = symver.file_names.size(); - qstring &fname = symver.file_names.push_back(); - reader.get_name(&fname, st, verneed.vn_file); - } - - virtual void aux_cb(const elf_vernaux_t &vernaux, int64 offset, size_t) override - { - symbol_verneed_t &reqfile = symver.reqs.back(); - symbol_vernaux_t &reqver = reqfile.auxs.push_back(); - reqver.offset = offset; - - reqver.name = symver.version_names.size(); - qstring &vname = symver.version_names.push_back(); - reader.get_name(&vname, st, vernaux.vna_name); - - uint16 idx = vernaux.vna_other & ~0x8000; - if ( idx != 0 ) - { - vermap_item_t &vermap_item = symver.vermap[idx]; - vermap_item.fname_idx = reqfile.name; - vermap_item.vname_idx = reqver.name; - } - } - }; - - if ( get_versym_section(&sh, &st, *this, WKS_VERNEED, di, DIT_VERNEED, use_pht) ) - { - elf_verneed_parser_t parser(*this, *symver, st); - parser.parse(sh.sh_offset, sh.sh_size); - } - - // Read version definition entries from DT_VERDEF - struct elf_verdef_parser_t - : public elf_ver_parser_t<elf_verdef_t, elf_verdaux_t> - { - typedef elf_ver_parser_t<elf_verdef_t, elf_verdaux_t> inherited; - - elf_symbol_version_t &symver; - slice_type_t st; - elf_verdef_parser_t( - const reader_t &_reader, - elf_symbol_version_t &_symver, - slice_type_t _st) - : inherited(_reader), - symver(_symver), - st(_st) - { - } - - virtual void entry_cb(const elf_verdef_t &verdef, int64 offset, size_t) override - { - symbol_verdef_t &deffile = symver.defs.push_back(); - deffile.offset = offset; - // TODO check verdef.vd_version - deffile.flags = verdef.vd_flags; - deffile.ndx = verdef.vd_ndx; - } - - virtual void aux_cb(const elf_verdaux_t &verdaux, int64 offset, size_t) override - { - symbol_verdef_t &deffile = symver.defs.back(); - symbol_verdaux_t &defver = deffile.auxs.push_back(); - defver.offset = offset; - - if ( (deffile.flags & VER_FLG_BASE) != 0 ) - { - symver.def_base = symver.file_names.size(); - qstring &fname = symver.file_names.push_back(); - reader.get_name(&fname, st, verdaux.vda_name); - } - - defver.name = symver.version_names.size(); - qstring &vname = symver.version_names.push_back(); - reader.get_name(&vname, st, verdaux.vda_name); - - uint16 idx = deffile.ndx; - if ( idx != 0 && deffile.auxs.size() == 1 ) - { - vermap_item_t &vermap_item = symver.vermap[idx]; - vermap_item.fname_idx = symver.def_base; - vermap_item.vname_idx = defver.name; - } - } - }; - - if ( get_versym_section(&sh, &st, *this, WKS_VERDEF, di, DIT_VERDEF, use_pht) ) - { - elf_verdef_parser_t parser(*this, *symver, st); - parser.parse(sh.sh_offset, sh.sh_size); - } - - // Read version symbol entries from DT_VERSYM - if ( get_versym_section(&sh, &st, *this, WKS_VERSYM, di, DIT_VERSYM, use_pht) ) - { - input_status_t save_excursion(*this); - if ( save_excursion.seek(sh.sh_offset) != -1 ) - for ( size_t i = 0; i < sh.sh_size / sizeof(uint16); i++ ) - if ( read_half(&symver->symbols.push_back()) < 0 ) - break; - } - - return true; -} - -//---------------------------------------------------------------------------- -void reader_t::validate_section_size( - uint64 *count, - size_t *entsize, - const elf_shdr_t §ion, - const char *counter_name) -{ - *count = 0; - *entsize = section.sh_entsize == 0 ? 1 : section.sh_entsize; - uint64 size = this->sections.get_size_in_file(section); - if ( size == 0 ) - return; - *count = size / *entsize; -#ifdef BUILD_LOADER - validate_array_count( - get_linput(), - count, - *entsize, - counter_name, - section.sh_offset); -#else - qnotused(counter_name); -#endif -} - -//---------------------------------------------------------------------------- -bool reader_t::read_dynamic_info_tags( - dyninfo_tags_t *dyninfo_tags, - const dynamic_linking_tables_t &dlt) -{ - // assert: dlt.is_valid() - if ( dlt.size == 0 ) - return false; - - // read all 'elf_dyn_t' entries - elf_dyn_t *d; - const size_t isize = stdsizes.entries.dyn; - elf_shdr_t fake_section; - fake_section.sh_type = SHT_DYNAMIC; - fake_section.sh_offset = dlt.offset; - fake_section.sh_size = dlt.size; - fake_section.sh_entsize = isize; - uint64 count; - size_t entsize; - validate_section_size(&count, &entsize, fake_section, "Dynamic info size"); - if ( count == 0 ) - return false; - buffered_input_t<elf_dyn_t> dyn_input(*this, fake_section.sh_offset, count, entsize); - while ( dyn_input.next(d) ) - { - dyninfo_tags->push_back(*d); - if ( d->d_tag == DT_NULL ) - break; - } - return true; -} - -//---------------------------------------------------------------------------- -bool reader_t::parse_dynamic_info( - dynamic_info_t *dyninfo, - const dyninfo_tags_t &dyninfo_tags) -{ - dyninfo->initialize(*this); - - sizevec_t offsets; - - // populate dyninfo structure - for ( dyninfo_tags_t::const_iterator dyn = dyninfo_tags.begin(); - dyn != dyninfo_tags.end(); - ++dyn ) - { - dynamic_info_type_t di_type = DIT_TYPE_COUNT; - switch ( dyn->d_tag ) - { - case DT_STRTAB: di_type = DIT_STRTAB; break; - case DT_SYMTAB: di_type = DIT_SYMTAB; break; - case DT_REL: di_type = DIT_REL; break; - case DT_RELA: di_type = DIT_RELA; break; - case DT_JMPREL: di_type = DIT_PLT; break; - case DT_HASH: di_type = DIT_HASH; break; - case DT_GNU_HASH: di_type = DIT_GNU_HASH; break; - case DT_PREINIT_ARRAY: di_type = DIT_PREINIT_ARRAY; break; - case DT_INIT_ARRAY: di_type = DIT_INIT_ARRAY; break; - case DT_FINI_ARRAY: di_type = DIT_FINI_ARRAY; break; - case DT_VERDEF: di_type = DIT_VERDEF; break; - case DT_VERNEED: di_type = DIT_VERNEED; break; - case DT_VERSYM: di_type = DIT_VERSYM; break; - case DT_ANDROID_REL: - if ( is_arm() ) - di_type = DIT_ANDROID_REL; - break; - case DT_ANDROID_RELA: - if ( is_arm() ) - di_type = DIT_ANDROID_RELA; - break; - } - if ( di_type != DIT_TYPE_COUNT ) - { - dynamic_info_t::entry_t &entry = dyninfo->entries[di_type]; - entry.offset = file_offset(dyn->d_un); - offsets.push_back(entry.offset); - entry.addr = dyn->d_un; - continue; - } - - switch ( dyn->d_tag ) - { - case DT_STRSZ: di_type = DIT_STRTAB; break; - case DT_RELSZ: di_type = DIT_REL; break; - case DT_RELASZ: di_type = DIT_RELA; break; - case DT_ANDROID_RELSZ: di_type = DIT_ANDROID_REL; break; - case DT_ANDROID_RELASZ: di_type = DIT_ANDROID_RELA; break; - case DT_PLTRELSZ: di_type = DIT_PLT; break; - case DT_PREINIT_ARRAYSZ: di_type = DIT_PREINIT_ARRAY; break; - case DT_INIT_ARRAYSZ: di_type = DIT_INIT_ARRAY; break; - case DT_FINI_ARRAYSZ: di_type = DIT_FINI_ARRAY; break; - } - if ( di_type != DIT_TYPE_COUNT ) - { - dyninfo->entries[di_type].size = dyn->d_un; - continue; - } - - switch ( dyn->d_tag ) - { - case DT_SYMENT: di_type = DIT_SYMTAB; break; - case DT_RELENT: di_type = DIT_REL; break; - case DT_RELAENT: di_type = DIT_RELA; break; - } - if ( di_type != DIT_TYPE_COUNT ) - { - dyninfo->entries[di_type].entsize = dyn->d_un; - continue; - } - - switch ( dyn->d_tag ) - { - case DT_VERDEFNUM: di_type = DIT_VERDEF; break; - case DT_VERNEEDNUM: di_type = DIT_VERNEED; break; - } - if ( di_type != DIT_TYPE_COUNT ) - { - dyninfo->entries[di_type].info = dyn->d_un; - continue; - } - - switch ( dyn->d_tag ) - { - case DT_PLTREL: - dyninfo->plt_rel_type = uint32(dyn->d_un); - if ( dyninfo->plt_rel_type != DT_REL && dyninfo->plt_rel_type != DT_RELA ) - { - if ( !handle_error(*this, BAD_DYN_PLT_TYPE, dyninfo->plt_rel_type) ) - return false; - } - continue; - - case DT_INIT: - case DT_FINI: - case DT_PLTGOT: - offsets.push_back(file_offset(dyn->d_un)); - continue; - - default: - continue; - - case DT_NULL: - break; // end of list - } - break; - } - - // Guess size of sections that don't have an explicit size - dyninfo->symtab().guess_size(offsets); - dyninfo->hash().guess_size(offsets); - dyninfo->gnu_hash().guess_size(offsets); - dyninfo->verdef().guess_size(offsets); - dyninfo->verneed().guess_size(offsets); - dyninfo->versym().guess_size(offsets); - - return true; -} - -//---------------------------------------------------------------------------- -void reader_t::add_mapping(const elf_phdr_t &p) -{ - mapping_t &m = mappings.push_back(); - m.offset = p.p_offset; - m.size = p.p_filesz; - m.ea = p.p_vaddr; -} - -//---------------------------------------------------------------------------- -int64 reader_t::file_offset(uint64 ea) const -{ - for ( int i=0; i < mappings.size(); i++ ) - { - const mapping_t &cur = mappings[i]; - if ( cur.ea <= ea && (cur.ea + cur.size) > ea ) - return low(ea - cur.ea) + cur.offset; - } - - return -1; -} - -//---------------------------------------------------------------------------- -ea_t reader_t::file_vaddr(uint64 offset) const -{ - for ( int i=0; i < mappings.size(); i++ ) - { - const mapping_t &cur = mappings[i]; - if ( cur.offset <= offset && (cur.offset + cur.size) > offset ) - return low(offset - cur.offset) + cur.ea; - } - - return BADADDR; -} - -//---------------------------------------------------------------------------- -elf_shndx_t section_headers_t::get_index(wks_t wks) const -{ - QASSERT(20054, wks >= WKS_BSS && wks < WKS_LAST); - return wks_lut[int(wks)]; -} - -//---------------------------------------------------------------------------- -void section_headers_t::set_index(wks_t wks, elf_shndx_t index) -{ - QASSERT(20055, wks >= WKS_BSS && wks < WKS_LAST); - wks_lut[int(wks)] = index; -} - -//---------------------------------------------------------------------------- -const elf_shdr_t *section_headers_t::getn(elf_shndx_t index) const -{ - assert_initialized(); - - if ( index >= headers.size() ) - return NULL; - else - return &headers[index]; -} - -//---------------------------------------------------------------------------- -const elf_shdr_t *section_headers_t::get(uint32 sh_type, const char *name) const -{ - assert_initialized(); - - qstring n2; - for ( qvector<elf_shdr_t>::const_iterator it=begin(); it != end(); it++ ) - { - const elf_shdr_t &cur = *it; - if ( cur.sh_type == sh_type ) - { - n2.qclear(); - get_name(&n2, &cur); - if ( n2 == name ) - return &cur; - } - } - return NULL; -} - -//---------------------------------------------------------------------------- -const elf_shdr_t *section_headers_t::get_rel_for(elf_shndx_t index, bool *is_rela) const -{ - assert_initialized(); - if ( is_rela != NULL ) - *is_rela = false; - - QASSERT(20056, index > 0); - for ( elf_shdrs_t::const_iterator it=begin(); it != end(); it++ ) - { - // for REL/RELA sections, sh_info contains the index to which the relocations apply - if ( it->sh_info == index - && (it->sh_type == SHT_RELA || it->sh_type == SHT_REL) ) - { - // found it - if ( is_rela != NULL ) - *is_rela = it->sh_type == SHT_RELA; - return it; - } - } - return NULL; -} - -//---------------------------------------------------------------------------- -int section_headers_t::add(const elf_shdr_t §ion) -{ - headers.push_back(section); - return headers.size() - 1; -} - -//---------------------------------------------------------------------------- -bool section_headers_t::get_name(qstring *out, elf_shndx_t index) const -{ - assert_initialized(); - - if ( index >= headers.size() ) - return false; - else - return get_name(out, &headers[index]); -} - -//---------------------------------------------------------------------------- -bool section_headers_t::get_name(qstring *out, const elf_shdr_t *sh) const -{ - if ( sh == NULL || !strtab.is_valid() ) - return false; - return reader->get_name(out, strtab, sh->sh_name); -} - -//---------------------------------------------------------------------------- -bool reader_t::get_name( - qstring *out, - const dynamic_info_t::entry_t &strtab, - uint32 name_idx) const -{ - if ( !strtab.is_valid() ) - *out = "{no string table}"; - // cisco ios files have size 0 for the string section - else if ( strtab.size != 0 && name_idx >= strtab.size ) - out->sprnt("bad offset %08x", low(strtab.offset + name_idx)); - else - return get_string_at(out, strtab.offset + name_idx); - return false; -} - -//---------------------------------------------------------------------------- -bool reader_t::get_name( - qstring *out, - slice_type_t slice_type, - uint32 name_idx) const -{ - const dynamic_info_t::entry_t *strtab; - switch ( slice_type ) - { - case SLT_SYMTAB: - strtab = &sym_strtab; - break; - case SLT_DYNSYM: - strtab = &dyn_strtab; - break; - default: - INTERR(20086); - } - return get_name(out, *strtab, name_idx); //-V614 Potentially uninitialized pointer 'strtab' used -} - -//---------------------------------------------------------------------------- -const char *section_headers_t::sh_type_str(uint32 sh_type) const -{ -#define NM(tp) case SHT_##tp: return #tp -#define NM2(tp, nm) case SHT_##tp: return #nm - - // OS-specific types - uint8 os_abi = reader->get_ident().osabi; - if ( os_abi == ELFOSABI_SOLARIS ) - { - switch ( sh_type ) - { - NM(SUNW_ancillary); - NM(SUNW_capchain); - NM(SUNW_capinfo); - NM(SUNW_symsort); - NM(SUNW_tlssort); - NM(SUNW_LDYNSYM); - NM(SUNW_dof); - NM(SUNW_cap); - NM(SUNW_SIGNATURE); - NM(SUNW_ANNOTATE); - NM(SUNW_DEBUGSTR); - NM(SUNW_DEBUG); - NM(SUNW_move); - NM(SUNW_COMDAT); - NM(SUNW_syminfo); - NM2(SUNW_verdef, VERDEF); - NM2(SUNW_verneed, VERNEEDED); - NM2(SUNW_versym, VERSYMBOL); - } - } - else - { - switch ( sh_type ) - { - NM(GNU_INCREMENTAL_INPUTS); - NM(GNU_INCREMENTAL_SYMTAB); - NM(GNU_INCREMENTAL_RELOCS); - NM(GNU_INCREMENTAL_GOT_PLT); - NM(GNU_ATTRIBUTES); - NM(GNU_HASH); - NM(GNU_LIBLIST); - NM2(GNU_verdef, VERDEF); - NM2(GNU_verneed, VERNEEDED); - NM2(GNU_versym, VERSYMBOL); - } - } - - switch ( sh_type ) - { - NM(NULL); - NM(PROGBITS); - NM(SYMTAB); - NM(STRTAB); - NM(RELA); - NM(HASH); - NM(DYNAMIC); - NM(NOTE); - NM(NOBITS); - NM(REL); - NM(SHLIB); - NM(DYNSYM); - NM(COMDAT); - NM(INIT_ARRAY); - NM(FINI_ARRAY); - NM(PREINIT_ARRAY); - NM(GROUP); - NM(SYMTAB_SHNDX); - default: - { - uint32 m = reader->get_header().e_machine; - if ( m == EM_ARM || m == EM_AARCH64 ) - { - switch ( sh_type ) - { - NM(ARM_EXIDX); - NM(ARM_PREEMPTMAP); - NM(ARM_ATTRIBUTES); - NM(ARM_DEBUGOVERLAY); - NM(ARM_OVERLAYSECTION); - NM(ANDROID_REL); - NM(ANDROID_RELA); - } - } - else if ( m == EM_MIPS ) - { - switch ( sh_type ) - { - NM(MIPS_LIBLIST); - NM(MIPS_MSYM); - NM(MIPS_CONFLICT); - NM(MIPS_GPTAB); - NM(MIPS_UCODE); - NM(MIPS_DEBUG); - NM(MIPS_REGINFO); - NM(MIPS_IFACE); - NM(MIPS_CONTENT); - NM(MIPS_OPTIONS); - NM(MIPS_DWARF); - NM(MIPS_SYMBOL_LIB); - NM(MIPS_EVENTS); - NM2(DVP_OVERLAY_TABLE, MIPS_DVP_OVERLAY_TABLE); - NM2(DVP_OVERLAY, MIPS_DVP_OVERLAY); - NM(MIPS_IOPMOD); - NM(MIPS_PSPREL); - } - } - else if ( m == EM_PPC64 ) - { - switch ( sh_type ) - { - NM2(PS3PRX_RELA, PRXRELA); - } - } - break; - } - } - return nullptr; -#undef NM2 -#undef NM -} - -//------------------------------------------------------------------------- -qstring section_headers_t::sh_type_qstr(uint32 sh_type) const -{ - qstring s = sh_type_str(sh_type); - if ( s.empty() ) - s.sprnt("%X", sh_type); - return s; -} - -//------------------------------------------------------------------------- -uint64 section_headers_t::get_size_in_file(const elf_shdr_t &sh) const -{ - if ( sh.sh_type == SHT_NOBITS ) - return 0; - uint64 next_boundary = reader->size(); - // It may happen that we receive a section header that is _not_ part - // of the list of original section headers. E.g., when we load symbols - // from the dynamic-provided information. - const elf_shdr_t *next_sh = &sh + 1; - if ( next_sh >= begin() - && next_sh < end() - && next_sh->sh_offset < next_boundary - && next_sh->sh_offset >= sh.sh_offset ) - { - next_boundary = next_sh->sh_offset; - } - if ( sh.sh_offset >= next_boundary ) - return 0; - return qmin(sh.sh_size, next_boundary - sh.sh_offset); -} - -//------------------------------------------------------------------------- -void section_headers_t::read_file_contents( - bytevec_t *out, - const elf_shdr_t &sh) const -{ - uint64 nbytes = sh.sh_size; -#ifdef BUILD_LOADER - qstring hdrname = "?"; - get_name(&hdrname, sh); - qstring text; - text.sprnt("Size of %s", hdrname.c_str()); - validate_array_count( - reader->get_linput(), - &nbytes, - 1, - text.c_str(), - sh.sh_offset); -#endif - out->resize(nbytes); - reader->seek(sh.sh_offset); - reader->safe_read(out->begin(), nbytes, /*apply_endianness=*/ false); -} - -//------------------------------------------------------------------------- -bool section_headers_t::read_gnu_debuglink( - qstring *out_link, - uint32 *out_crc) const -{ - const elf_shdr_t *s = get(SHT_PROGBITS, ".gnu_debuglink"); - bool found = s != NULL; - if ( found ) - { - bytevec_t buf; - read_file_contents(&buf, *s); - size_t sz = buf.size(); - found = sz > 4; - if ( found ) - { - if ( out_crc != NULL ) - { - uint32 crc = *(uint32 *)(buf.begin() + (sz - 4)); - if ( reader->get_ident().bytesex == ELFDATA2MSB ) - crc = swap32(crc); - *out_crc = crc; - } - sz -= 4; - if ( out_link != NULL ) - { - out_link->reserve(sz); - for ( size_t i=0; i < sz; ++i ) - { - uchar ch = buf[i]; - if ( ch == 0 ) - break; - out_link->append(ch); - } - } - } - } - return found; -} - -//------------------------------------------------------------------------- -// program_headers_t -//---------------------------------------------------------------------------- -const char *program_headers_t::p_type_str(uint32 p_type) const -{ -#define NM(tp) case PT_##tp: return #tp -#define NM2(tp, nm) case PT_##tp: return #nm - - // OS-specific types - uint8 os_abi = reader->get_ident().osabi; - if ( os_abi == ELFOSABI_SOLARIS ) - { - switch ( p_type ) - { - NM2(SUNW_UNWIND, UNWIND); - NM2(SUNW_EH_FRAME, EH_FRAME); - NM(SUNWBSS); - NM2(SUNWSTACK, STACK); - NM2(SUNWDTRACE, DTRACE); - NM(SUNWCAP); - } - } - else - { - switch ( p_type ) - { - NM2(GNU_EH_FRAME, EH_FRAME); - NM2(GNU_STACK, STACK); - NM2(GNU_RELRO, RO-AFTER); - } - } - - switch ( p_type ) - { - NM(NULL); - NM(LOAD); - NM(DYNAMIC); - NM(INTERP); - NM(NOTE); - NM(SHLIB); - NM(PHDR); - NM(TLS); - - NM2(PAX_FLAGS, PAX-FLAG); - - default: - { - uint32 m = reader->get_header().e_machine; - if ( m == EM_ARM ) - { - switch ( p_type ) - { - NM2(ARM_ARCHEXT, ARCHEXT); - NM2(ARM_EXIDX, EXIDX); - } - } - else if ( m == EM_AARCH64 ) - { - switch ( p_type ) - { - NM2(AARCH64_ARCHEXT, ARCHEXT); - NM2(AARCH64_UNWIND, EXIDX); - } - } - else if ( m == EM_IA64 ) - { - switch ( p_type ) - { - NM(HP_TLS); - NM(HP_CORE_NONE); - NM(HP_CORE_VERSION); - NM(HP_CORE_KERNEL); - NM(HP_CORE_COMM); - NM(HP_CORE_PROC); - NM(HP_CORE_LOADABLE); - NM(HP_CORE_STACK); - NM(HP_CORE_SHM); - NM(HP_CORE_MMF); - NM(HP_PARALLEL); - NM(HP_FASTBIND); - NM(HP_OPT_ANNOT); - NM(HP_HSL_ANNOT); - NM(HP_STACK); - NM(HP_CORE_UTSNAME); - NM(HP_LINKER_FOOTPRINT); - NM(IA_64_ARCHEXT); - NM(IA_64_UNWIND); - } - } - else if ( m == EM_MIPS ) - { - switch ( p_type ) - { - NM2(MIPS_IOPMOD, IOPMOD); - NM2(MIPS_EEMOD, EEMOD); - NM2(MIPS_PSPREL, PSPREL); - NM2(MIPS_PSPREL2, PSPREL2); - NM2(MIPS_REGINFO, REGINFO); - NM2(MIPS_RTPROC, RTPROC); - NM2(MIPS_OPTIONS, OPTIONS); - NM2(MIPS_ABIFLAGS, ABIFLAGS); - } - } - else if ( m == EM_PPC64 ) - { - switch ( p_type ) - { - case PHT_PS3PRX_RELA : return "PRXRELA"; - } - } - return nullptr; - } - } -#undef NM2 -#undef NM -} - -//---------------------------------------------------------------------------- -qstring program_headers_t::p_type_qstr(uint32 p_type) const -{ - qstring s = p_type_str(p_type); - if ( s.empty() ) - s.sprnt("%08X", p_type); - return s; -} - -//---------------------------------------------------------------------------- -uint64 program_headers_t::get_size_in_file(const elf_phdr_t &p) const -{ - assert_initialized(); - if ( p.p_type != PT_LOAD - && p.p_type != PT_INTERP - && p.p_type != PT_NOTE - && p.p_type != PT_PHDR ) - { - return 0; - } - - uint64 next_boundary = reader->size(); - if ( p.p_offset >= next_boundary ) - return 0; - - int idx = &p - begin(); - if ( idx > -1 && (idx+1) < pheaders.size() ) - { - const elf_phdr_t *np = CONST_CAST(program_headers_t*)(this)->get(idx+1); - if ( np->p_offset >= p.p_offset ) - next_boundary = np->p_offset; - } - return qmin(p.p_filesz, next_boundary - p.p_offset); -} - -//---------------------------------------------------------------------------- -void program_headers_t::read_file_contents( - bytevec_t *out, - const elf_phdr_t &p) const -{ - assert_initialized(); - - uint64 nbytes = p.p_filesz; -#ifdef BUILD_LOADER - qstring text; - text.sprnt("Size of %s", p_type_qstr(p.p_type).c_str()); - validate_array_count( - reader->get_linput(), - &nbytes, - 1, - text.c_str(), - p.p_offset); -#endif - out->resize(nbytes); - reader->seek(p.p_offset); - reader->safe_read(out->begin(), nbytes, /*apply_endianness=*/ false); -} - -//---------------------------------------------------------------------------- -// Note Section -// -bool elf_note_t::unpack_sz(uint32 *r, uint32 *start, const bytevec_t &buf, bool mf) -{ - if ( *start + 4 > buf.size() ) - return false; - - uint32 res = *(uint32 *)&buf[*start]; - if ( mf ) - res = swap32(res); - if ( r != NULL ) - *r = res; - *start += 4; - return true; -} - -//---------------------------------------------------------------------------- -bool elf_note_t::unpack_mem(qstring *out, const bytevec_t &buf, uint32 start, uint32 len, bool as_strz) -{ - if ( start + len > buf.size() ) - return false; - out->qclear(); - if ( as_strz ) - { - out->reserve(len); - for ( int i=0; i < len; ++i ) - { - char ch = buf[start + i]; - if ( ch == '\0' ) - break; - out->append(ch); - } - } - else - { - out->resize(len, '\0'); - memcpy(out->begin(), &buf[start], len); - } - return true; -} - -//---------------------------------------------------------------------------- -bool elf_note_t::unpack_strz(qstring *out, const bytevec_t &buf, uint32 start, uint32 len) -{ - return unpack_mem(out, buf, start, len, /*as_strz=*/ true); -} - -//---------------------------------------------------------------------------- -bool elf_note_t::unpack(elf_note_t *entry, uint32 *start, const bytevec_t &buf, bool mf) -{ - - uint32 end = *start; - uint32 namesz; - uint32 descsz; - uint32 type; - if ( !elf_note_t::unpack_sz(&namesz, &end, buf, mf) - || !elf_note_t::unpack_sz(&descsz, &end, buf, mf) - || !elf_note_t::unpack_sz(&type, &end, buf, mf) ) - { - return false; - } - - qstring name; - if ( !elf_note_t::unpack_strz(&name, buf, end, namesz) ) - return false; - end += align_up(namesz, 4); - - qstring desc; - if ( !elf_note_t::unpack_mem(&desc, buf, end, descsz) ) - return false; - end += align_up(descsz, 4); - - if ( entry != NULL ) - { - entry->name = name; - entry->desc = desc; - entry->type = type; - } - *start = end; - return true; -} - -//---------------------------------------------------------------------------- -void notes_t::add(const bytevec_t &buf) -{ - bool mf = reader->is_msb(); - uint32 start = 0; - while ( start < buf.size() ) - { - elf_note_t &n = notes.push_back(); - if ( !elf_note_t::unpack(&n, &start, buf, mf) ) - { - notes.pop_back(); - break; - } - } -} - -//---------------------------------------------------------------------------- -bool notes_t::get_build_id(qstring *out) const -{ - assert_initialized(); - - for ( elf_notes_t::const_iterator p=notes.begin(); p != notes.end(); ++p ) - { - const elf_note_t &en = *p; - if ( en.name == NT_NAME_GNU && en.type == NT_GNU_BUILD_ID ) - { - int sz = en.desc.length(); - out->qclear(); - out->reserve(2*sz); - for ( int i=0; i < sz; ++i ) - out->cat_sprnt("%02x", (unsigned char)en.desc[i]); - return true; - } - } - return false; -} - -//---------------------------------------------------------------------------- -const char *d_note_gnu_type_str(uint64 type) -{ -#define NM(tp) case tp: return #tp - switch ( type ) - { - NM(NT_GNU_ABI_TAG); - NM(NT_GNU_HWCAP); - NM(NT_GNU_BUILD_ID); - NM(NT_GNU_GOLD_VERSION); - NM(NT_GNU_PROPERTY_TYPE_0); - } - return NULL; -#undef NM -} - -//---------------------------------------------------------------------------- -const char *d_note_linux_type_str(uint64 type) -{ -#define NM(tp) case tp: return #tp - switch ( type ) - { - NM(NT_PRXFPREG); - NM(NT_PPC_VMX); - NM(NT_PPC_VSX); - NM(NT_PPC_TAR); - NM(NT_PPC_PPR); - NM(NT_PPC_DSCR); - NM(NT_PPC_EBB); - NM(NT_PPC_PMU); - NM(NT_PPC_TM_CGPR); - NM(NT_PPC_TM_CFPR); - NM(NT_PPC_TM_CVMX); - NM(NT_PPC_TM_CVSX); - NM(NT_PPC_TM_SPR); - NM(NT_PPC_TM_CTAR); - NM(NT_PPC_TM_CPPR); - NM(NT_PPC_TM_CDSCR); - NM(NT_386_TLS); - NM(NT_386_IOPERM); - NM(NT_X86_XSTATE); - NM(NT_S390_HIGH_GPRS); - NM(NT_S390_TIMER); - NM(NT_S390_TODCMP); - NM(NT_S390_TODPREG); - NM(NT_S390_CTRS); - NM(NT_S390_PREFIX); - NM(NT_S390_LAST_BREAK); - NM(NT_S390_SYSTEM_CALL); - NM(NT_S390_TDB); - NM(NT_S390_VXRS_LOW); - NM(NT_S390_VXRS_HIGH); - NM(NT_S390_GS_CB); - NM(NT_S390_GS_BC); - NM(NT_ARM_VFP); - NM(NT_ARM_TLS); - NM(NT_ARM_HW_BREAK); - NM(NT_ARM_HW_WATCH); - NM(NT_ARM_SVE); - } - return NULL; -#undef NM -} - -//---------------------------------------------------------------------------- -const char *d_note_core_type_str(uint64 type) -{ -#define NM(tp) case tp: return #tp - switch ( type ) - { - NM(NT_PRSTATUS); - NM(NT_FPREGSET); - NM(NT_PRPSINFO); - NM(NT_TASKSTRUCT); - NM(NT_AUXV); - NM(NT_SIGINFO); - NM(NT_FILE); - NM(NT_PSTATUS); - NM(NT_FPREGS); - NM(NT_PSINFO); - NM(NT_LWPSTATUS); - NM(NT_LWPSINFO); - NM(NT_WIN32PSTATUS); - } - return NULL; -#undef NM -} - -//---------------------------------------------------------------------------- -template<> void buffered_input_t<sym_rel>::start_reading() -{ - reader.get_arch_specific()->on_start_symbols(reader); -} - -//---------------------------------------------------------------------------- -template<> bool buffered_input_t<sym_rel>::read_item(sym_rel &storage) -{ - storage = sym_rel(); - - elf_sym_t &orig = storage.original; -#define _safe(expr) \ - do \ - { \ - if ( expr < 0 ) \ - return false; \ - } while ( 0 ) - _safe(reader.read_symbol(&orig)); - - ushort bind = ELF_ST_BIND(orig.st_info); - // assert: bind <= STB_HIPROC - if ( bind > STB_WEAK ) - { - CASSERT(STB_LOCAL < STB_WEAK && STB_GLOBAL < STB_WEAK); //-V590 expression is excessive - if ( reader.get_header().e_machine == EM_ARM && bind == STB_LOPROC+1 ) - // codewarrior for arm seems to use this binding type similar to local or weak - bind = STB_WEAK; - else if ( bind < STB_LOOS ) - bind = STB_INVALID; - } - - storage.bind = (uchar) bind; - storage.sec = 0; - storage.type = ELF_ST_TYPE(orig.st_info); - storage.value = orig.st_value + reader.get_load_bias(); - storage.size = orig.st_size; - return true; -} - -//---------------------------------------------------------------------------- -static inline void swap_64_at(uint64 *ptr) -{ - *ptr = swap64(*ptr); -} - -//---------------------------------------------------------------------------- -static inline void swap_64_at(int64 *ptr) -{ - *ptr = swap64(*ptr); -} - -//---------------------------------------------------------------------------- -#define swap_addr(ptr) swap_64_at(ptr); -#define swap_xword(ptr) swap_64_at(ptr); -#define swap_sxword(ptr) swap_64_at(ptr); - -//---------------------------------------------------------------------------- -template<> ssize_t buffered_input_t<elf_rel_t>::read_items(size_t max) -{ - if ( isize != sizeof(Elf32_Rel) && isize != sizeof(Elf64_Rel) ) - return 0; - if ( !is_mul_ok<uint64>(read, isize) || !is_mul_ok(max, isize) ) - return 0; - input_status_t save_excursion(reader); - if ( save_excursion.seek(offset + (read * isize)) == -1 ) - return 0; - ssize_t bytes = max * isize; - if ( qlread(reader.get_linput(), buffer.begin(), bytes) != bytes ) - return 0; - -#if __MF__ - bool swap = !reader.is_msb(); -#else - bool swap = reader.is_msb(); -#endif - - if ( isize == sizeof(Elf32_Rel) ) - { - Elf32_Rel *rel32 = (Elf32_Rel *) buffer.begin(); - Elf64_Rel *rel64 = (Elf64_Rel *) buffer.begin(); - rel32 += max - 1; - rel64 += max - 1; - uint64 inf64, off64; - for ( size_t i = 0; i < max; i++, rel32--, rel64-- ) - { - if ( swap ) - { - inf64 = swap32(rel32->r_info); - off64 = swap32(rel32->r_offset); - } - else - { - inf64 = rel32->r_info; - off64 = rel32->r_offset; - } - rel64->r_info = inf64; - rel64->r_offset = off64; - } - } - else - { - if ( swap ) - { - elf_rel_t *rel64 = (elf_rel_t *)buffer.begin(); - for ( size_t i = 0; i < max; i++, rel64++ ) - { - swap_addr(&rel64->r_offset); - swap_xword(&rel64->r_info); - } - } - } - - return max; -} - -//---------------------------------------------------------------------------- -template<> ssize_t buffered_input_t<elf_rela_t>::read_items(size_t max) -{ - if ( isize != sizeof(Elf32_Rela) && isize != sizeof(Elf64_Rela) ) - return 0; - if ( !is_mul_ok<uint64>(read, isize) || !is_mul_ok(max, isize) ) - return 0; - input_status_t save_excursion(reader); - if ( save_excursion.seek(offset + (read * isize)) == -1 ) - return 0; - ssize_t bytes = max * isize; - if ( qlread(reader.get_linput(), buffer.begin(), bytes) != bytes ) - return 0; - -#if __MF__ - bool swap = !reader.is_msb(); -#else - bool swap = reader.is_msb(); -#endif - - if ( isize == sizeof(Elf32_Rela) ) - { - Elf32_Rela *rela32 = (Elf32_Rela *) buffer.begin(); - Elf64_Rela *rela64 = (Elf64_Rela *) buffer.begin(); - rela32 += max - 1; - rela64 += max - 1; - uint64 inf64, off64; - int64 addend; - for ( size_t i = 0; i < max; i++, rela32--, rela64-- ) - { - if ( swap ) - { - inf64 = swap32(rela32->r_info); - off64 = swap32(rela32->r_offset); - addend = swap32(rela32->r_addend); - } - else - { - inf64 = rela32->r_info; - off64 = rela32->r_offset; - addend = rela32->r_addend; - } - rela64->r_info = inf64; - rela64->r_offset = off64; - rela64->r_addend = addend; - } - } - else - { - if ( swap ) - { - elf_rela_t *rela64 = (elf_rela_t *)buffer.begin(); - for ( size_t i = 0; i < max; i++, rela64++ ) - { - swap_addr(&rela64->r_offset); - swap_xword(&rela64->r_info); - swap_sxword(&rela64->r_addend); - } - } - } - - return max; -} - -//-------------------------------------------------------------------------- -class aps2_unpacker_t -{ - enum - { - RELOCATION_GROUPED_BY_INFO_FLAG = 1, - RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2, - RELOCATION_GROUPED_BY_ADDEND_FLAG = 4, - RELOCATION_GROUP_HAS_ADDEND_FLAG = 8 - }; - - const uchar *ptr; - const uchar *end; - int flags; - bool ok; - - bool grouped_by_offset_delta() const { return (flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0; } - bool grouped_by_info() const { return (flags & RELOCATION_GROUPED_BY_INFO_FLAG) != 0; } - bool grouped_by_addend() const { return (flags & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0; } - bool group_has_addend() const { return (flags & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0; } - int64 getval() - { - int64 v; - if ( !unpack_sleb128(&v, &ptr, end) ) - ok = false; - return v; - } - -public: - aps2_unpacker_t(const uchar *p, const uchar *e) - : ptr(p), end(e), flags(0), ok(true) {} - - //-------------------------------------------------------------------------- - void unpack(elf_rela_vec_t *out, int64 nrelocs) - { - elf_rela_t rela; - rela.r_offset = getval(); - rela.r_addend = 0; - rela.r_info = 0; - - out->resize(nrelocs); - size_t n = 0; - - while ( ok ) // repeat for all groups - { - int64 nrels = getval(); // number of relocs in the group - flags = getval(); // flags for the group - - int64 offset_delta = 0; - if ( grouped_by_offset_delta() ) - offset_delta = getval(); - - if ( grouped_by_info() ) - rela.r_info = getval(); - - if ( grouped_by_addend() && group_has_addend() ) - rela.r_addend += getval(); - else if ( !group_has_addend() ) - rela.r_addend = 0; - - // unpack all relocs in the group - for ( int64 i=0; i < nrels; i++ ) - { - if ( !grouped_by_offset_delta() ) - offset_delta = getval(); - rela.r_offset += offset_delta; - - if ( !grouped_by_info() ) - rela.r_info = getval(); - - if ( group_has_addend() && !grouped_by_addend() ) - rela.r_addend += getval(); - - if ( !ok ) - { // some kind of error occurred, remove the uninitialized relocs - out->resize(n); - return; - } - if ( n == nrelocs ) - return; // safety check - out->at(n++) = rela; - } - } - } -}; - -//---------------------------------------------------------------------------- -bool buffered_rela_t::next(elf_rela_t *&storage) -{ - if ( !packed ) - return inherited::next(storage); - - if ( cur >= end ) - { - if ( end != 0 ) - return false; - - // read everything at once and unpack - bytevec_t bytes; - bytes.resize(count); - input_status_t save_excursion(reader); - if ( save_excursion.seek(offset) == -1 ) - return false; - ssize_t nread = qlread(reader.get_linput(), bytes.begin(), count); - if ( nread < count ) - { - msg("READ ERROR: read only %" FMT_ZS " bytes instead of %" FMT_64 "d bytes\n", - nread, count); - if ( nread <= 8 ) - return false; - bytes.resize(nread); - } - if ( bytes.size() < sizeof(uint32) ) - return false; - - const uchar *ptr = bytes.begin(); - const uchar *endp = bytes.end(); - uint32 magic = *(uint32*)ptr; - ptr += 4; - -#define PKREL_APR1 MC4('A','P','R','1') -#define PKREL_APA1 MC4('A','P','A','1') -#define PKREL_APS2 MC4('A','P','S','2') - - int64 n; - if ( !unpack_sleb128(&n, &ptr, endp) ) - return false; - if ( n <= 0 || n >= count ) // sanity check - return false; - - switch ( magic ) - { - default: // unknown magic -// case PKREL_APR1: -// case PKREL_APA1: - ask_for_feedback( - "The relocation packing method '%4.4s' is not supported yet.", - (const char *)bytes.begin()); - return false; - case PKREL_APS2: - aps2_unpacker_t unp(ptr, endp); - unp.unpack(&buffer, n); - break; - } - - end = n; - } - storage = &buffer[cur++]; - return true; -} - -//---------------------------------------------------------------------------- -template<> bool buffered_input_t<elf_dyn_t>::read_item(elf_dyn_t &storage) -{ - // FIXME: Load bias? - memset(&storage, 0, sizeof(storage)); - _safe(reader.read_sxword(&storage.d_tag)); - _safe(reader.read_addr(&storage.d_un)); -#undef _safe - return true; -} - -//------------------------------------------------------------------------- -void dynamic_info_t::initialize(const reader_t &reader) -{ - symtab().entsize = reader.stdsizes.entries.sym; - rel().entsize = reader.stdsizes.dyn.rel; - rela().entsize = reader.stdsizes.dyn.rela; - QASSERT(20037, symtab().entsize != 0 && rel().entsize != 0 && rela().entsize != 0); -} - -//---------------------------------------------------------------------------- -bool dynamic_info_t::fill_section_header( - elf_shdr_t *sh, - dynamic_info_type_t type) const -{ - int shtype; - switch ( type ) - { - case DIT_SYMTAB: shtype = SHT_DYNSYM; break; - case DIT_REL: shtype = SHT_REL; break; - case DIT_RELA: shtype = SHT_RELA; break; - case DIT_ANDROID_REL: shtype = SHT_REL; break; - case DIT_ANDROID_RELA: shtype = SHT_RELA; break; - case DIT_VERDEF: shtype = SHT_GNU_verdef; break; - case DIT_VERNEED: shtype = SHT_GNU_verneed; break; - case DIT_VERSYM: shtype = SHT_GNU_versym; break; - case DIT_PLT: - shtype = plt_rel_type == DT_RELA ? SHT_RELA : SHT_REL; - break; - default: - QASSERT(20101, false); - }; - const entry_t &entry = entries[type]; - if ( !entry.is_valid() ) - return false; - memset(sh, 0, sizeof(*sh)); - sh->sh_addr = entry.addr; - sh->sh_offset = entry.offset; - sh->sh_size = entry.size; - sh->sh_info = entry.info; - sh->sh_type = shtype; - if ( type != DIT_ANDROID_REL && type != DIT_ANDROID_RELA ) - { - sh->sh_entsize = sh->sh_type == SHT_DYNSYM ? entry.entsize - : sh->sh_type == SHT_RELA ? rela().entsize - : rel().entsize; - } - return true; -} - -//---------------------------------------------------------------------------- -qstring dynamic_info_t::d_tag_str_ext(const reader_t &reader, int64 d_tag) -{ - qstring buf = d_tag_str(reader, d_tag); - if ( buf.empty() ) - { - buf.sprnt("DT_???? Unknown (%08" FMT_64 "X)", d_tag); - return buf; - } - if ( buf.length() < 12 ) - buf.resize(12, ' '); - - uint16 e_machine = reader.get_header().e_machine; - const char *ext = NULL; - switch ( d_tag ) - { - case DT_NULL: - ext = "end of _DYNAMIC array"; - break; - case DT_NEEDED: - ext = "str-table offset name to needed library"; - break; - case DT_PLTRELSZ: - ext = "tot.size in bytes of relocation entries"; - break; - case DT_HASH: - ext = "addr. of symbol hash table"; - break; - case DT_STRTAB: - ext = "addr of string table"; - break; - case DT_SYMTAB: - ext = "addr of symbol table"; - break; - case DT_RELA: - ext = "addr of relocation table"; - break; - case DT_RELASZ: - ext = "size in bytes of DT_RELA table"; - break; - case DT_RELAENT: - ext = "size in bytes of DT_RELA entry"; - break; - case DT_STRSZ: - ext = "size in bytes of string table"; - break; - case DT_SYMENT: - ext = "size in bytes of symbol table entry"; - break; - case DT_INIT: - ext = "addr. of initialization function"; - break; - case DT_FINI: - ext = "addr. of termination function"; - break; - case DT_SONAME: - ext = "offs in str.-table - name of shared object"; - break; - case DT_RPATH: - ext = "offs in str-table - search path"; - break; - case DT_RUNPATH: - ext = "array of search pathes"; - break; - case DT_SYMBOLIC: - ext = "start search of shared object"; - break; - case DT_REL: - ext = "addr of relocation table"; - break; - case DT_RELSZ: - ext = "tot.size in bytes of DT_REL"; - break; - case DT_RELENT: - ext = "size in bytes of DT_REL entry"; - break; - case DT_PLTREL: - ext = "type of relocation (DT_REL or DT_RELA)"; - break; - case DT_DEBUG: - ext = "not specified"; - break; - case DT_TEXTREL: - ext = "segment permisson"; - break; - case DT_PLTGOT: - if ( e_machine == EM_PPC ) - ext = "addr of PLT"; - break; - case DT_JMPREL: - if ( e_machine == EM_PPC ) - ext = "addr of JMP_SLOT relocation table"; - else - ext = "addr of dlt procedure (if present)"; - break; - case DT_PPC_GOT: - if ( e_machine == EM_PPC ) - ext = "addr of _GLOBAL_OFFSET_TABLE_"; - break; - } - if ( ext == NULL && reader.is_arm() ) - { - switch ( d_tag ) - { - case DT_ANDROID_REL: - ext = " offset of packed REL data"; - break; - case DT_ANDROID_RELSZ: - ext = " size of DT_ANDROID_REL"; - break; - case DT_ANDROID_RELA: - ext = " offset of packed RELA data"; - break; - case DT_ANDROID_RELASZ: - ext = " size of DT_ANDROID_RELA"; - break; - } - } - buf.append(ext); - return buf; -} - -//---------------------------------------------------------------------------- -const char *dynamic_info_t::d_tag_str(const reader_t &reader, int64 d_tag) -{ - uint16 e_machine = reader.get_header().e_machine; -#define NM(tp) case tp: return #tp - - // OS-specific types - uint8 os_abi = reader.get_ident().osabi; - if ( os_abi == ELFOSABI_SOLARIS ) - { - switch ( d_tag ) - { - NM(DT_SUNW_AUXILIARY); -// NM(DT_SUNW_RTLDINF); - NM(DT_SUNW_FILTER); - NM(DT_SUNW_CAP); - NM(DT_SUNW_SYMTAB); - NM(DT_SUNW_SYMSZ); - NM(DT_SUNW_ENCODING); -// NM(DT_SUNW_SORTENT); - NM(DT_SUNW_SYMSORT); - NM(DT_SUNW_SYMSORTSZ); - NM(DT_SUNW_TLSSORT); - NM(DT_SUNW_TLSSORTSZ); - NM(DT_SUNW_CAPINFO); - NM(DT_SUNW_STRPAD); - NM(DT_SUNW_CAPCHAIN); - NM(DT_SUNW_LDMACH); - NM(DT_SUNW_CAPCHAINENT); - NM(DT_SUNW_CAPCHAINSZ); - NM(DT_SUNW_PARENT); - NM(DT_SUNW_ASLR); - NM(DT_SUNW_RELAX); - NM(DT_SUNW_NXHEAP); - NM(DT_SUNW_NXSTACK); - } - } - - switch ( d_tag ) - { - NM(DT_NULL); - NM(DT_NEEDED); - NM(DT_PLTRELSZ); - NM(DT_HASH); - NM(DT_STRTAB); - NM(DT_SYMTAB); - NM(DT_RELA); - NM(DT_RELASZ); - NM(DT_RELAENT); - NM(DT_STRSZ); - NM(DT_SYMENT); - NM(DT_INIT); - NM(DT_FINI); - NM(DT_SONAME); - NM(DT_RPATH); - NM(DT_RUNPATH); - NM(DT_SYMBOLIC); - NM(DT_REL); - NM(DT_RELSZ); - NM(DT_RELENT); - NM(DT_PLTREL); - NM(DT_DEBUG); - NM(DT_TEXTREL); - - NM(DT_PLTGOT); - NM(DT_JMPREL); - - NM(DT_BIND_NOW); - NM(DT_PREINIT_ARRAY); - NM(DT_INIT_ARRAY); - NM(DT_FINI_ARRAY); - NM(DT_INIT_ARRAYSZ); - NM(DT_FINI_ARRAYSZ); - NM(DT_PREINIT_ARRAYSZ); - NM(DT_FLAGS); - - NM(DT_VALRNGLO); - NM(DT_GNU_PRELINKED); - NM(DT_GNU_CONFLICTSZ); - NM(DT_GNU_LIBLISTSZ); - NM(DT_CHECKSUM); - NM(DT_PLTPADSZ); - NM(DT_MOVEENT); - NM(DT_MOVESZ); - NM(DT_FEATURE); - NM(DT_POSFLAG_1); - NM(DT_SYMINSZ); - NM(DT_SYMINENT); -// NM(DT_VALRNGHI); - NM(DT_ADDRRNGLO); - NM(DT_GNU_HASH); - NM(DT_TLSDESC_PLT); - NM(DT_TLSDESC_GOT); - NM(DT_GNU_CONFLICT); - NM(DT_GNU_LIBLIST); - NM(DT_CONFIG); - NM(DT_DEPAUDIT); - NM(DT_AUDIT); - NM(DT_PLTPAD); - NM(DT_MOVETAB); - NM(DT_SYMINFO); -// NM(DT_ADDRRNGHI); - NM(DT_RELACOUNT); - NM(DT_RELCOUNT); - NM(DT_FLAGS_1); - NM(DT_VERDEF); - NM(DT_VERDEFNUM); - NM(DT_VERNEED); - NM(DT_VERNEEDNUM); - NM(DT_VERSYM); - - NM(DT_AUXILIARY); - NM(DT_USED); - NM(DT_FILTER); - } - if ( e_machine == EM_MIPS ) - { - switch ( d_tag ) - { - NM(DT_MIPS_RLD_VERSION); - NM(DT_MIPS_TIME_STAMP); - NM(DT_MIPS_ICHECKSUM); - NM(DT_MIPS_IVERSION); - NM(DT_MIPS_FLAGS); - NM(DT_MIPS_BASE_ADDRESS); - NM(DT_MIPS_MSYM); - NM(DT_MIPS_CONFLICT); - NM(DT_MIPS_LIBLIST); - NM(DT_MIPS_LOCAL_GOTNO); - NM(DT_MIPS_CONFLICTNO); - NM(DT_MIPS_LIBLISTNO); - NM(DT_MIPS_SYMTABNO); - NM(DT_MIPS_UNREFEXTNO); - NM(DT_MIPS_GOTSYM); - NM(DT_MIPS_HIPAGENO); - NM(DT_MIPS_RLD_MAP); - NM(DT_MIPS_DELTA_CLASS); - NM(DT_MIPS_DELTA_CLASS_NO); - NM(DT_MIPS_DELTA_INSTANCE); - NM(DT_MIPS_DELTA_INSTANCE_NO); - NM(DT_MIPS_DELTA_RELOC); - NM(DT_MIPS_DELTA_RELOC_NO); - NM(DT_MIPS_DELTA_SYM); - NM(DT_MIPS_DELTA_SYM_NO); - NM(DT_MIPS_DELTA_CLASSSYM); - NM(DT_MIPS_DELTA_CLASSSYM_NO); - NM(DT_MIPS_CXX_FLAGS); - NM(DT_MIPS_PIXIE_INIT); - NM(DT_MIPS_SYMBOL_LIB); - NM(DT_MIPS_LOCALPAGE_GOTIDX); - NM(DT_MIPS_LOCAL_GOTIDX); - NM(DT_MIPS_HIDDEN_GOTIDX); - NM(DT_MIPS_PROTECTED_GOTIDX); - NM(DT_MIPS_OPTIONS); - NM(DT_MIPS_INTERFACE); - NM(DT_MIPS_DYNSTR_ALIGN); - NM(DT_MIPS_INTERFACE_SIZE); - NM(DT_MIPS_RLD_TEXT_RESOLVE_ADDR); - NM(DT_MIPS_PERF_SUFFIX); - NM(DT_MIPS_COMPACT_SIZE); - NM(DT_MIPS_GP_VALUE); - NM(DT_MIPS_AUX_DYNAMIC); - NM(DT_MIPS_PLTGOT); - NM(DT_MIPS_RWPLT); - } - } - else if ( e_machine == EM_IA64 ) - { - switch ( d_tag ) - { - NM(DT_HP_LOAD_MAP); - NM(DT_HP_DLD_FLAGS); - NM(DT_HP_DLD_HOOK); - NM(DT_HP_UX10_INIT); - NM(DT_HP_UX10_INITSZ); - NM(DT_HP_PREINIT); - NM(DT_HP_PREINITSZ); - NM(DT_HP_NEEDED); - NM(DT_HP_TIME_STAMP); - NM(DT_HP_CHECKSUM); - NM(DT_HP_GST_SIZE); - NM(DT_HP_GST_VERSION); - NM(DT_HP_GST_HASHVAL); - NM(DT_HP_EPLTREL); - NM(DT_HP_EPLTRELSZ); - NM(DT_HP_FILTERED); - NM(DT_HP_FILTER_TLS); - NM(DT_HP_COMPAT_FILTERED); - NM(DT_HP_LAZYLOAD); - NM(DT_HP_BIND_NOW_COUNT); - NM(DT_PLT); - NM(DT_PLT_SIZE); - NM(DT_DLT); - NM(DT_DLT_SIZE); - NM(DT_HP_SYM_CHECKSUM); - NM(DT_IA_64_PLT_RESERVE); - } - } - else if ( e_machine == EM_PPC ) - { - switch ( d_tag ) - { - NM(DT_PPC_GOT); - } - } - else if ( reader.is_arm() ) - { - switch ( d_tag ) - { - NM(DT_ANDROID_REL); - NM(DT_ANDROID_RELSZ); - NM(DT_ANDROID_RELA); - NM(DT_ANDROID_RELASZ); - } - } - -#undef NM - return NULL; -} - -//---------------------------------------------------------------------------- -qstring dynamic_info_t::d_un_str(const reader_t &reader, int64 d_tag, int64 d_un) -{ - qstring name; - switch ( d_tag ) - { - case DT_SONAME: - case DT_RPATH: - case DT_RUNPATH: - case DT_NEEDED: - case DT_AUXILIARY: - case DT_FILTER: - case DT_CONFIG: - case DT_DEPAUDIT: - case DT_AUDIT: - reader.get_name(&name, reader.dyn_strtab, uint32(d_un)); - break; - } - return name; -} - -//---------------------------------------------------------------------------- -size_t symrel_cache_t::slice_start(slice_type_t t) const -{ - check_type(t); - return t == SLT_DYNSYM ? dynsym_index : 0; -} - -//---------------------------------------------------------------------------- -size_t symrel_cache_t::slice_end(slice_type_t t) const -{ - check_type(t); - return t == SLT_SYMTAB ? dynsym_index : storage.size(); -} - -//---------------------------------------------------------------------------- -sym_rel &symrel_cache_t::append(slice_type_t t) -{ - check_type(t); - size_t idx = slice_end(t); - if ( t == SLT_SYMTAB ) - ++dynsym_index; - if ( idx == storage.size() ) - { - return storage.push_back(); - } - else - { - QASSERT(20133, idx <= storage.size()); - qvector<sym_rel>::iterator it = storage.begin() + idx; - storage.insert(it, sym_rel()); - return *it; - } -} - -// =========================================================================== -// ARM-specific code. -// =========================================================================== - -//---------------------------------------------------------------------------- -bool arm_arch_specific_t::is_mapping_symbol(const char *name) const -{ - if ( name == NULL ) - return false; - - if ( name[0] == '$' - && (name[2] == '\0' || name[2] == '.') ) - { - switch ( name[1] ) - { - case 'a': // labels the first byte of a sequence of ARM instructions. Its type is STT_FUNC. - case 't': // labels the first byte of a sequence of Thumb instructions. Its type is STT_FUNC. - case 'b': // labels a Thumb BL instruction. Its type is STT_FUNC. - case 'd': // labels the first byte of a sequence of data items. Its type is STT_OBJECT. - case 'p': // labels the final, PC-modifying instruction of an - // indirect function call. Its type is STT_FUNC. - // (An indirect call is a call through a function pointer - // variable). $p does not label the PC-modifying - // instruction of a function return sequence. - case 'f': // labels a function pointer constant (static pointer to code). - // Its type is STT_OBJECT. - case 'x': // Start of a sequence of A64 instructions - return true; - } - } - return false; -} - -//---------------------------------------------------------------------------- -void arm_arch_specific_t::on_start_symbols(reader_t &) -{ - has_mapsym = false; -} - -//---------------------------------------------------------------------------- -void arm_arch_specific_t::on_symbol_read(reader_t &reader, sym_rel &sym) -{ - const char *name = sym.get_original_name(reader).c_str(); - if ( is_mapping_symbol(name) ) - { - has_mapsym = true; - - // assert: name != NULL - char name1 = name[1]; - if ( name1 == 'a' || name1 == 't' || name1 == 'x' ) - { - isa_t isa = name1 == 'a' || name1 == 'x' ? isa_arm : isa_thumb; - if ( name1 == 't' ) - sym.set_flag(thumb_function); - notify_isa(reader, sym, isa, true); - if ( is_mapping_symbols_tracking() ) - set_isa(sym, isa); - } - } - else - { - uchar bind = sym.bind; - - // Keep going _only_ if function - ushort orig_type = ELF_ST_TYPE(sym.original.st_info); - if ( (orig_type != STT_FUNC - && orig_type != STT_ARM_TFUNC - && orig_type != STT_ARM_16BIT ) - || (bind != STB_GLOBAL - && bind != STB_LOCAL - && bind != STB_WEAK) ) - { - return; - } - - sym.value &= ~1; - - // If original type is ARM_TFUNC, make it FUNC, - // so it gets treated as a regular FUNC by - // upstream code. - if ( orig_type == STT_ARM_TFUNC ) - sym.type = STT_FUNC; - - if ( (orig_type == STT_ARM_TFUNC - || orig_type == STT_ARM_16BIT - || (sym.original.st_value & 1) != 0) ) - { - sym.set_flag(thumb_function); - notify_isa(reader, sym, isa_thumb, false); - } - - if ( !sym.has_flag(thumb_function) - && is_mapping_symbols_tracking() - && get_isa(sym) == isa_thumb ) - { - sym.set_flag(thumb_function); - notify_isa(reader, sym, isa_thumb, false); - } - - if ( !sym.has_flag(thumb_function) ) - notify_isa(reader, sym, isa_arm, false); - } -} - -//---------------------------------------------------------------------------- -void arm_arch_specific_t::set_isa(const sym_rel &symbol, isa_t isa) -{ - isa_ranges_t::iterator it = isa_ranges.find(symbol.sec); - if ( it == isa_ranges.end() ) - { - isa_ranges[symbol.sec] = section_isa_ranges_t(); - it = isa_ranges.find(symbol.sec); - } - - section_isa_ranges_t §ion_isa_ranges = it->second; - section_isa_ranges[symbol.original.st_value] = isa; -} - -//---------------------------------------------------------------------------- -arm_arch_specific_t::isa_t arm_arch_specific_t::get_isa(const sym_rel &symbol) const -{ - isa_t current_isa = isa_arm; - isa_ranges_t::const_iterator it = isa_ranges.find(symbol.sec); - if ( it != isa_ranges.end() ) - { - const section_isa_ranges_t §ion_isa_ranges = it->second; - section_isa_ranges_t::const_iterator p; - section_isa_ranges_t::const_iterator end = section_isa_ranges.end(); - for ( p = section_isa_ranges.begin(); p != end; ++p ) - { - uint64 offset_in_section = p->first; - if ( offset_in_section > symbol.original.st_value ) - break; - - current_isa = p->second; - } - } - return current_isa; -} - -#endif // ELF_READER_CPP diff --git a/idasdk75/ldr/geos/geos.cpp b/idasdk75/ldr/geos/geos.cpp deleted file mode 100644 index 7b9a5de..0000000 --- a/idasdk75/ldr/geos/geos.cpp +++ /dev/null @@ -1,795 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2000 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - */ - -#include "../idaldr.h" -#include "geos2.h" -#include "common.cpp" -#include <struct.hpp> -#include <enum.hpp> -#include <typeinf.hpp> - -//-------------------------------------------------------------------------- -static int create_seg( - ea_t base, - ea_t start, - ea_t end, - const char *name, - const char *sclass) -{ - if ( start != BADADDR && end < start ) - return 0; - segment_t s; - s.sel = setup_selector(base); - s.start_ea = start; - s.end_ea = end; - s.align = saRelByte; - s.comb = (sclass != NULL && strcmp(sclass,"STACK") == 0) ? scStack : scPub; - s.bitness = 0; - return add_segm_ex(&s,name,sclass,ADDSEG_NOSREG); -} - -//-------------------------------------------------------------------------- -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - union - { - GEOSheader h1; - GEOS2header h2; - } h; - qlseek(li, 0); - if ( qlread(li, &h, sizeof(h)) != sizeof(h) ) - return 0; - - qoff64_t apppos; - int version; - if ( h.h1.ID == GEOS_ID && h.h1.fclass == 0 ) - { - apppos = 0xC8; - version = 1; - } - else if ( h.h2.ID == GEOS2_ID && h.h2.fclass == 1 ) - { - apppos = sizeof(GEOS2header); - version = 2; - } - else - { - return 0; - } - - GEOSappheader ah; - qlseek(li, apppos, SEEK_SET); - if ( qlread(li, &ah, sizeof(ah)) != sizeof(ah) ) - return 0; - const char *stype; - switch ( ah.type ) - { - case 1: stype = "Application"; break; - case 2: stype = "Library"; break; - case 3: stype = "Driver"; break; - default: stype = "Unknown type";break; - } - fileformatname->sprnt("GEOS%d %s", version, stype); - *processor = "metapc"; - return 1; -} - -//-------------------------------------------------------------------------- -static ea_t get_segea(const GEOSappheader &ah, const uint32 *segea, uint16 s) -{ - if ( s >= ah.numseg ) - { - ask_for_feedback("Bad segment number %d", s); - return BADADDR; - } - return segea[s] == uint32(BADADDR) ? BADADDR : segea[s]; -} - -//-------------------------------------------------------------------------- -static netnode get_node(const GEOSappheader &ah, const netnode *modnode, uint16 libn) -{ - if ( libn >= ah.numlib ) - { - ask_for_feedback("Bad library number %d", libn); - return BADNODE; - } - return modnode[libn]; -} - -//-------------------------------------------------------------------------- -static tid_t get_class_struct_flags_enum() -{ - static const char enum_name[] = "ClassFlags"; - enum_t id = get_enum(enum_name); - if ( id != BADNODE ) - return id; - id = add_enum(-1, enum_name, hex_flag()); - set_enum_bf(id, true); - add_enum_member(id, "CLASSF_HAS_DEFAULT", (1<<0), (1<<0)); - add_enum_member(id, "CLASSF_MASTER_CLASS", (1<<1), (1<<1)); - add_enum_member(id, "CLASSF_VARIANT_CLASS", (1<<2), (1<<2)); - add_enum_member(id, "CLASSF_DISCARD_ON_SAVE", (1<<3), (1<<3)); - add_enum_member(id, "CLASSF_NEVER_SAVED", (1<<4), (1<<4)); - add_enum_member(id, "CLASSF_HAS_RELOC", (1<<5), (1<<5)); - add_enum_member(id, "CLASSF_C_HANDLERS", (1<<6), (1<<6)); - return id; -} - -//-------------------------------------------------------------------------- -#if 0 -static void declare_parameter_types(ea_t ea, int count) -{ - static const char class_name[] = "CMethodDef"; - struc_t *sptr = get_struc(get_struc_id(class_name)); - if ( sptr == NULL ) - { - sptr = get_struc(add_struc(-1, class_name)); - if ( sptr == NULL ) - return; - add_struc_member(sptr, "methodParameterDef", -1, word_flag(), NULL, 2); - add_struc_member(sptr, "handlerTypeDef", -1, byte_flag(), NULL, 1); - } - size_t size = get_struc_size(sptr); - create_struct(ea, size*count, sptr->id); -} -#endif - -//-------------------------------------------------------------------------- -static void declare_class(ea_t ea, const char *entryname) -{ - static const char class_name[] = "ClassStruct"; - struc_t *sptr = get_struc(get_struc_id(class_name)); - if ( sptr == NULL ) - { - sptr = get_struc(add_struc(BADADDR, class_name)); - if ( sptr == NULL ) - return; - opinfo_t mt; - mt.ri.flags = REF_OFF32; - mt.ri.target = BADADDR; - mt.ri.base = 0; - mt.ri.tdelta = 0; - add_struc_member(sptr, "superClass", BADADDR, off_flag()|dword_flag(), &mt, 4); - add_struc_member(sptr, "masterOffset", BADADDR, word_flag(), NULL, 2); - add_struc_member(sptr, "methodCount", BADADDR, dec_flag()|word_flag(), NULL, 2); - add_struc_member(sptr, "instanceSize", BADADDR, dec_flag()|word_flag(), NULL, 2); - add_struc_member(sptr, "vdRelocTable", BADADDR, word_flag(), NULL, 2); - add_struc_member(sptr, "relocTable", BADADDR, word_flag(), NULL, 2); - mt.ec.tid = get_class_struct_flags_enum(); - mt.ec.serial = 0; - add_struc_member(sptr, "flags", BADADDR, enum_flag()|byte_flag(), &mt, 1); - add_struc_member(sptr, "masterMethods",BADADDR, byte_flag(), NULL, 1); - } - asize_t size = get_struc_size(sptr); - create_struct(ea, size, sptr->id); - - segment_t *s = getseg(ea); - if ( s == NULL ) - return; - int count = get_word(ea+6); -// bool c_handlers = get_byte(ea+14) & (1<<6); - ea += size; - if ( ea+2*count >= s->end_ea ) - return; - ea_t messages = ea; - create_word(ea, count*2); - op_dec(ea, 0); - ea += 2*count; - if ( ea+4*count > s->end_ea ) - return; - create_dword(ea, count*4); - op_plain_offset(ea, 0, 0); - for ( int i=0; i < count; i++ ) - { - ea_t idx = ea + 4*i; - ea_t pea = to_ea(get_word(idx+2), get_word(idx)); - auto_make_proc(pea); - char name[MAXSTR]; - qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i)); - add_entry(pea, pea, name, true, AEF_IDBENC); - } -// commented out because it doesn't work properly -// see geoplan.geo, entry number 1 for example -// if ( c_handlers ) -// declare_parameter_types(ea+count*4, count); -} - -//-------------------------------------------------------------------------- -static void describe_app(const GEOSappheader &ah, const uint32 *segea) -{ - char buf[MAXSTR]; - char *end = buf + sizeof(buf); - char *ptr = buf + qsnprintf(buf, sizeof(buf), "Pgm attrs :"); - if ( ah.attr & GA_PROCESS ) APPEND(ptr, end, " GA_PROCESS"); - if ( ah.attr & GA_LIBRARY ) APPEND(ptr, end, " GA_LIBRARY"); - if ( ah.attr & GA_DRIVER ) APPEND(ptr, end, " GA_DRIVER"); - if ( ah.attr & GA_KEEP_FILE_OPEN ) APPEND(ptr, end, " GA_KEEP_FILE_OPEN"); - if ( ah.attr & GA_SYSTEM ) APPEND(ptr, end, " GA_SYSTEM"); - if ( ah.attr & GA_MULTI_LAUNCHABLE ) APPEND(ptr, end, " GA_MULTI_LAUNCHABLE"); - if ( ah.attr & GA_APPLICATION ) APPEND(ptr, end, " GA_APPLICATION"); - if ( ah.attr & GA_DRIVER_INITIALIZED ) APPEND(ptr, end, " GA_DRIVER_INITIALIZED"); - if ( ah.attr & GA_LIBRARY_INITIALIZED ) APPEND(ptr, end, " GA_LIBRARY_INITIALIZED"); - if ( ah.attr & GA_GEODE_INITIALIZED ) APPEND(ptr, end, " GA_GEODE_INITIALIZED"); - if ( ah.attr & GA_USES_COPROC ) APPEND(ptr, end, " GA_USES_COPROC"); - if ( ah.attr & GA_REQUIRES_COPROC ) APPEND(ptr, end, " GA_REQUIRES_COPROC"); - if ( ah.attr & GA_HAS_GENERAL_CONSUMER_MODE ) APPEND(ptr, end, " GA_HAS_GENERAL_CONSUMER_MODE"); - if ( ah.attr & GA_ENTRY_POINTS_IN_C ) APPEND(ptr, end, " GA_ENTRY_POINTS_IN_C"); - add_pgm_cmt("%s", buf); - - if ( ah.attr & GA_PROCESS ) - { - ea_t entry = get_segea(ah, segea, ah.classptr_seg) + ah.classptr_ofs; - set_name(entry, "ProcessClass", SN_NOCHECK|SN_NOWARN); - declare_class(entry, "ProcessClass"); -// inf_set_start_cs(get_segea(ah,segea,ah.classptr_seg) >> 4); -// inf_set_start_ip (ah.classptr_ofs); - entry = get_segea(ah, segea, ah.tokenres_seg) + ah.tokenres_item; - set_name(entry, "ApplicationObject"); - add_pgm_cmt("ProcessClass: %d:%04X", ah.classptr_seg, ah.classptr_ofs); - add_pgm_cmt("App object : %d:%04X", ah.tokenres_seg, ah.tokenres_item); - } - if ( ah.attr & GA_LIBRARY && ah.initseg != 0 ) - { - inf_set_start_cs(get_segea(ah, segea, ah.initseg) >> 4); - inf_set_start_ip(ah.initofs); - add_pgm_cmt("Library init: %d:%04X", ah.initseg, ah.initofs); - } - if ( ah.attr & GA_DRIVER && ah.startseg != 0 ) - { - ea_t entry = get_segea(ah, segea, ah.startseg) + ah.startofs; - set_name(entry, "DriverTable"); -// inf_set_start_cs(get_segea(ah, segea, ah.startseg) >> 4); -// inf_set_start_ip (ah.startofs); - add_pgm_cmt("Driver Table: %d:%04X", ah.startseg, ah.startofs); -// add_jmplist(ah.startseg,ah.startofs,4,4); - // Add entry point as "jmplist" - } -} - -//-------------------------------------------------------------------------- -static void bad_lib_reloc(int i, uint16 off) -{ - ask_for_feedback("Strange library relocation at %d:%04X", i, off); -} - -//-------------------------------------------------------------------------- -static void create_fixup(ea_t ea, fixup_data_t &fd, ea_t target) -{ - segment_t *s = getseg(target); - if ( s != NULL ) - { - fd.sel = s->sel; - fd.off = target - get_segm_base(s); - } - else - { - fd.sel = sel_t(target >> 4); - fd.off = target & 0xF; - } - fd.displacement = 0; - fd.set(ea); - if ( fd.get_type() == FIXUP_PTR16 ) - { - put_word(ea, fd.off); - put_word(ea+2, fd.sel); - } - else if ( fd.get_type() == FIXUP_OFF16 ) - { - put_word(ea, fd.off); - } - else // SEG16 - { - put_word(ea, fd.sel); - } -} - -//-------------------------------------------------------------------------- -static void apply_relocations( - linput_t *li, - const GEOSappheader &ah, - const netnode *modnode, - const uint16 *seglen, - const int32 *segpos, - const uint16 *segfix, - const uint32 *segea) -{ - // apply relocation information - for ( int i=0; i < ah.numseg; i++ ) - { - if ( segfix[i] == 0 ) - continue; - GEOSfixup *fix = (GEOSfixup *)qalloc(segfix[i]); - if ( fix == NULL ) - nomem("fix"); - qlseek(li, segpos[i]+((seglen[i]+0xF)&~0xF)); - lread(li, fix, segfix[i]); - int n = segfix[i]/sizeof(GEOSfixup); - sel_t oldsel = BADSEL; - sel_t oldoff = BADSEL; - ea_t oldea = BADADDR; - for ( int j=0; j < n; j++ ) - { - ea_t ea = get_segea(ah, segea, (uint16)i) + fix[j].ofs; - int ftype = fix[j].type & 0xF0; - if ( ftype != 0x10 && ftype != 0x20 ) - ask_for_feedback("Unknown fixup type %02X", ftype); - netnode libnode = BADNODE; - if ( ftype == 0x10 ) - libnode = get_node(ah, modnode, fix[j].type>>8); - uint16 w1 = get_word(ea); - ea_t target = BADADDR; - fixup_data_t fd(FIXUP_SEG16); - switch ( fix[j].type & 0x0F ) - { - case 0x0: case 0x4: - fd.set_type_and_flags(FIXUP_PTR16); - if ( ftype == 0x20 ) // program - target = get_segea(ah, segea, w1) + get_word(ea+2); - else // library - { - target = node2ea(libnode.altval(w1+1)); - fd.set_extdef(); - } - break; - case 0x1: // off - if ( ftype == 0x20 ) // program - { - ask_for_feedback("Program offset relocation encountered"); - continue; - } - oldoff = w1; - if ( oldsel != BADSEL ) - { -LIB_PTR: - target = node2ea(libnode.altval(oldoff+1)); - if ( oldea == ea+2 ) - { - fd.set_type_and_flags(FIXUP_PTR16, FIXUPF_EXTDEF); - } - else - { - fd.set_type_and_flags(FIXUP_SEG16, FIXUPF_EXTDEF); - create_fixup(oldea, fd, target); - fd.set_type_and_flags(FIXUP_OFF16, FIXUPF_EXTDEF); - } - oldsel = BADSEL; - oldoff = BADSEL; - oldea = BADSEL; - break; - } - oldea = ea; - continue; - case 0x2: case 0x3: - if ( ftype == 0x20 ) // program - target = get_segea(ah, segea, w1); - else - { - oldsel = w1; - if ( oldoff != BADSEL ) - { - ea_t tmp = ea; - ea = oldea; - oldea = tmp; - goto LIB_PTR; - } - oldea = ea; - continue; - } - break; - default: - ask_for_feedback("Unknown relocation type %02X", fix[j].type); - } - create_fixup(ea, fd, target); - } - qfree(fix); - } -} - -//-------------------------------------------------------------------------- -static void find_imports_in_relocations( - linput_t *li, - const GEOSappheader &ah, - const netnode *modnode, - const uint16 *seglen, - const int32 *segpos, - const uint16 *segfix) -{ - for ( int i=0; i < ah.numseg; i++ ) - { - if ( segfix[i] == 0 ) - continue; - GEOSfixup *fix = (GEOSfixup *)qalloc(segfix[i]); - if ( fix == NULL ) - nomem("fix"); - qlseek(li, segpos[i]+((seglen[i]+0xF)&~0xF)); - lread(li, fix, segfix[i]); -// i don't understand why this should be done -// besides, if we uncomment it, the library fixups are -// not handled properly -// if ( fix[0].ofs == 0 ) -// fix[0].ofs = 0xFFFF; - int num = segfix[i]/sizeof(GEOSfixup); - sel_t oldseg = BADSEL; - sel_t oldoff = BADSEL; - sel_t oldlib = BADSEL; - for ( int j=0; j < num; j++ ) - { - if ( fix[j].ofs == 0xFFFF ) - continue; - if ( (fix[j].type & 0xF0) != 0x10 ) - continue; // only library! - int libn = fix[j].type>>8; - if ( libn >= ah.numlib ) - { - ask_for_feedback("Illegal library number in relocations"); - continue; - } - netnode n = modnode[libn]; - uint16 ofs = fix[j].ofs; - qlseek(li, segpos[i]+ofs); - uint16 w1; - lread(li, &w1, sizeof(w1)); - switch ( fix[j].type & 0x0F ) - { - case 0x0: case 0x4: // exported entry - n.altset(w1+1, 1); - oldseg = BADSEL; - oldoff = BADSEL; - oldlib = BADSEL; - break; - case 0x1: // off - if ( oldseg != BADSEL ) - { - if ( libn != oldlib || oldseg != w1 ) - bad_lib_reloc(i, ofs); - n.altset(w1+1, 1); - oldseg = BADSEL; - break; - } - oldoff = w1; - oldlib = libn; - break; - case 0x2: case 0x3: // seg # - if ( oldoff != BADSEL ) - { - if ( libn != oldlib || oldoff != w1 ) - bad_lib_reloc(i, ofs); - n.altset(w1+1, 1); - oldoff = BADSEL; - break; - } - oldseg = w1; - oldlib = libn; - break; - default: - ask_for_feedback("Unknown relocation type %02X", fix[j].type); - } - } - if ( oldseg != BADSEL && oldoff != BADSEL ) - ask_for_feedback("Some library relocations are strange"); - qfree(fix); - } -} - -//-------------------------------------------------------------------------- -static void create_extern_segments( - const GEOSappheader &ah, - const GEOSliblist *lib, - const netnode *modnode) -{ - inf_set_specsegs(inf_is_64bit() ? 8 : 4); - for ( int i=0; i < ah.numlib; i++ ) - { - char libname[8+1]; - qstrncpy(libname, lib[i].name, sizeof(libname)); - trim(libname); - netnode n = modnode[i]; - uval_t x; - int nimps = 0; - for ( x=n.altfirst(); x != BADNODE; x=n.altnext(x) ) - nimps++; - if ( nimps == 0 ) - continue; - - ea_t ea = free_chunk(inf_get_max_ea(), nimps*4, -15); - ea_t end = ea + nimps*4; - create_seg(ea>>4, ea, end, libname, "XTRN"); - for ( x=n.altfirst(); x != BADNODE; x=n.altnext(x),ea+=4 ) - { - char buf[MAXSTR]; - qsnprintf(buf, sizeof(buf), "%s_%u", libname, uint16(x)-1); - put_dword(ea, 0xCB); - create_insn(ea); - force_name(ea, buf, SN_IDBENC); - nodeidx_t ndx = ea2node(ea); - n.altset(x, ndx); - } - import_module(libname, NULL /*windir*/, n, NULL, "geos"); - } -} - -//-------------------------------------------------------------------------- -static void create_exports( - const GEOSappheader &ah, - const GEOSexplist *explist, - const uint32 *segea, - const char *modname) -{ - int i; - netnode n; - n.create(); - for ( i=0; i < ah.numexp; i++ ) - { - ea_t ea = get_segea(ah, segea, explist[i].seg) + explist[i].ofs; - add_extra_cmt(ea, true, "Exported entry %d", i); - nodeidx_t ndx = ea2node(ea); - n.altset(i+1, ndx); - } - import_module(modname, NULL /*windir*/, n, NULL, "geos"); - for ( i=0; i < ah.numexp; i++ ) - { - ea_t ea = get_segea(ah, segea, explist[i].seg) + explist[i].ofs; - qstring name; - if ( get_name(&name, ea, GN_NOT_DUMMY) <= 0 ) - name.sprnt("%s_%d", modname, i); - bool makecode = segtype(ea) == SEG_CODE; - add_entry(i, ea, name.begin(), makecode, AEF_IDBENC); - if ( !makecode ) - declare_class(ea, name.begin()); - } -} - -//-------------------------------------------------------------------------- -void load_application(linput_t *li, int32 fpos, int32 fdelta) -{ - GEOSappheader ah; - - qlseek(li, fpos); - lread(li, &ah, sizeof(ah)); - - // build our name - char modname[sizeof(ah.name)+1]; - qstrncpy(modname, ah.name, sizeof(ah.name)); - trim(modname); - - // read in library information - GEOSliblist *lib = NULL; - netnode *modnode = NULL; - validate_array_count(li, &ah.numlib, sizeof(GEOSliblist), "The library count"); - if ( ah.numlib != 0 ) - { - lib = qalloc_array<GEOSliblist>(ah.numlib); - if ( lib == NULL ) - nomem("libs"); - lread(li, lib, ah.numlib*sizeof(GEOSliblist)); - modnode = qalloc_array<netnode>(ah.numlib); - if ( modnode == NULL ) - nomem("libnode"); - for ( int i=0; i < ah.numlib; i++ ) - { - char libname[8+1]; - qstrncpy(libname, lib[i].name, sizeof(libname)); - trim(libname); - char buf[20]; - qsnprintf(buf, sizeof(buf), "$lib %.8s", libname); - modnode[i].create(buf); - } - } - - // read in export information - GEOSexplist *explist = NULL; - validate_array_count(li, &ah.numexp, sizeof(GEOSexplist), "Number of exports"); - if ( ah.numexp != 0 ) - { - explist = qalloc_array<GEOSexplist>(ah.numexp); - if ( explist == NULL ) - nomem("exp"); - lread(li, explist, ah.numexp*sizeof(GEOSexplist)); - } - - // read in segment information - void *segd = NULL; - uint16 *seglen = NULL; - int32 *segpos = NULL; - uint16 *segfix = NULL; - uint16 *segflg; - sel_t ds_sel = BADSEL; - uint32 *segea = NULL; - validate_array_count(li, &ah.numseg, 14, "Number of segments"); - if ( ah.numseg != 0 ) - { - if ( !is_mul_ok<ushort>(ah.numseg, 14) ) -NOMEM: - nomem("geos_segments"); - segd = qalloc(ah.numseg*14); - if ( segd == NULL ) - goto NOMEM; - lread(li, segd, ah.numseg*10); - seglen = (uint16 *)segd; - segpos = (int32 *)(seglen + ah.numseg); - segfix = (uint16 *)(segpos + ah.numseg); - segflg = (uint16 *)(segfix + ah.numseg); - segea = (uint32 *)(segflg + ah.numseg); - ea_t ea = to_ea(inf_get_baseaddr(), 0); - for ( int i=0; i < ah.numseg; i++ ) - { - uint16 f = segflg[i]; - segpos[i] += fdelta; - - segea[i] = uint32(BADADDR); - if ( seglen[i] == 0 ) - continue; - size_t bss_size = 0; - // if this is the data segment, increase its size by stacksize. - // i'm not aware of a reliable way to find it, so use heuristics - bool found_data_segment = false; - if ( ds_sel == BADSEL - && (f & (HF_READ_ONLY|HF_SHARABLE|HF_CODE)) == 0 - && (f & HF_FIXED) != 0 ) - { - found_data_segment = true; - bss_size = ah.stacksize; - } - ea = free_chunk(ea, bss_size + seglen[i], -15); - ea_t endea = ea + seglen[i] + bss_size; - if ( (f & HF_ZERO_INIT) == 0 ) - file2base(li, segpos[i], ea, endea - bss_size, FILEREG_PATCHABLE); - create_seg(ea>>4, ea, endea, NULL, (f & HF_CODE) ? "CODE" : "DATA"); - - if ( found_data_segment ) - ds_sel = find_selector(ea>>4); - - char buf[MAXSTR]; - char *end = buf + sizeof(buf); - char *ptr = buf + qsnprintf(buf, sizeof(buf), "Segm attrs :"); - if ( f & HF_ZERO_INIT ) APPEND(ptr, end, " ZEROINIT"); - if ( f & HF_LOCK ) APPEND(ptr, end, " LOCK"); - if ( f & HF_NO_ERR ) APPEND(ptr, end, " NO_ERR"); - if ( f & HF_UI ) APPEND(ptr, end, " UI"); - if ( f & HF_READ_ONLY ) APPEND(ptr, end, " RONLY"); - if ( f & HF_OBJECT_RESOURCE ) APPEND(ptr, end, " OBJ_RES"); - if ( f & HF_CODE ) APPEND(ptr, end, " CODE"); - if ( f & HF_CONFORMING ) APPEND(ptr, end, " CONFORMING"); - if ( f & HF_FIXED ) APPEND(ptr, end, " FIXED"); - if ( f & HF_SHARABLE ) APPEND(ptr, end, " SHARABLE"); - if ( f & HF_DISCARDABLE ) APPEND(ptr, end, " DISCARDABLE"); - if ( f & HF_SWAPABLE ) APPEND(ptr, end, " SWAPABLE"); - if ( f & HF_LMEM ) APPEND(ptr, end, " LMEM"); - if ( f & HF_DEBUG ) APPEND(ptr, end, " DEBUG"); - if ( f & HF_DISCARDED ) APPEND(ptr, end, " DISCARDED"); - if ( f & HF_SWAPPED ) APPEND(ptr, end, " SWAPPED"); - add_extra_cmt(ea, true, "%s", buf); - - segea[i] = (uint32)ea; - ea = endea; - } - } - - find_imports_in_relocations(li, ah, modnode, seglen, segpos, segfix); - create_extern_segments(ah, lib, modnode); - set_default_dataseg(ds_sel); - - if ( !qgetenv("IDA_NORELOC") ) - apply_relocations(li, ah, modnode, seglen, segpos, segfix, segea); - - create_exports(ah, explist, segea, modname); - - describe_app(ah, segea); - qfree(lib); - qfree(modnode); - qfree(explist); - qfree(segd); -} - -//-------------------------------------------------------------------------- -static void show_geos1(GEOSheader &h) -{ - char buf[MAXSTR]; - add_pgm_cmt("Name : %s", geos2ibm(buf, h.name, sizeof(h.name))); - add_pgm_cmt("Token : %s", token2str(buf, sizeof(buf), h.token)); - add_pgm_cmt("Creator : %s", token2str(buf, sizeof(buf), h.appl)); - add_pgm_cmt("Release : %u.%u.%u.%u", - h.release.versmaj, - h.release.versmin, - h.release.revmaj, - h.release.revmin); - add_pgm_cmt("Protocol : %u.%03u", - h.protocol.vers, - h.protocol.rev); - add_pgm_cmt("Flags : %04X", h.flags); - add_pgm_cmt("User info : %s", geos2ibm(buf, h.info, sizeof(h.info))); - add_pgm_cmt("Copyright : %s", geos2ibm(buf, h._copyright, sizeof(h._copyright))); -} - -//-------------------------------------------------------------------------- -static void show_geos2(GEOS2header &h) -{ - char buf[MAXSTR]; - add_pgm_cmt("Name : %s", geos2ibm(buf, h.name, sizeof(h.name))); - add_pgm_cmt("Token : %s", token2str(buf, sizeof(buf), h.token)); - add_pgm_cmt("Creator : %s", token2str(buf, sizeof(buf), h.appl)); - add_pgm_cmt("Release : %u.%u.%u.%u", - h.release.versmaj, - h.release.versmin, - h.release.revmaj, - h.release.revmin); - add_pgm_cmt("Protocol : %u.%03u", - h.protocol.vers, - h.protocol.rev); - add_pgm_cmt("Flags : %04X", h.flags); - add_pgm_cmt("Password : %.*s", int(sizeof(h.password)), h.password); - add_pgm_cmt("User info : %s", geos2ibm(buf, h.info, sizeof(h.info))); - add_pgm_cmt("Copyright : %s", geos2ibm(buf, h._copyright, sizeof(h._copyright))); -} - -//-------------------------------------------------------------------------- -void idaapi load_file(linput_t *li, uint16 /*neflag*/, const char * /*fileformatname*/) -{ - set_processor_type("metapc", SETPROC_LOADER); - - union - { - GEOSheader h1; - GEOS2header h2; - } h; - qlseek(li, 0); - lread(li, &h, sizeof(h)); - - int32 apppos; - int32 fdelta; - if ( h.h1.ID == GEOS_ID ) - { - apppos = 0xC8; - fdelta = 0; - } - else - { - apppos = sizeof(GEOS2header); - fdelta = apppos; - } - - load_application(li, apppos, fdelta); - - create_filename_cmt(); - if ( h.h1.ID == GEOS_ID ) - show_geos1(h.h1); - else - show_geos2(h.h2); - - inf_set_cc_cm(inf_get_cc_cm() | C_PC_LARGE); - add_til("geos", ADDTIL_DEFAULT); -} - -//-------------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/ldr/geos/makefile b/idasdk75/ldr/geos/makefile deleted file mode 100644 index 31dc0b2..0000000 --- a/idasdk75/ldr/geos/makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROC=geos - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)geos$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)enum.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ - common.cpp geos.cpp geos.h geos2.h diff --git a/idasdk75/ldr/hex/hex.cpp b/idasdk75/ldr/hex/hex.cpp deleted file mode 100644 index d967362..0000000 --- a/idasdk75/ldr/hex/hex.cpp +++ /dev/null @@ -1,624 +0,0 @@ -#define BUFFSIZE ((255+6)*2+76) // buffer to read the string -#define MAX_BYTES 24 // Max number of bytes per line for write -#define SEGMENTGAP (1*1024*1024) // make new segment if gap between addresses - // is greater than this value -#define SPARSE_GAP (256*1024) // switch to sparse storage if the gap - // is greater than this value - -/* - * This Loader Module is written by Ilfak Guilfanov and - * rewriten by Yury Haron - * - */ - -/* - Interesting documentation: - - http://www.intel.com/design/zapcode/Intel_HEX_32_Format.doc - http://www.keil.com/support/docs/1584.htm - -*/ - -#include "../idaldr.h" - -//-------------------------------------------------------------------------- -static int idaapi accept_file( - qstring *fileformatname, - qstring *, - linput_t *li, - const char *) -{ - char str[80]; - if ( qlgets(str, sizeof(str), li) == NULL ) - return 0; - - const char *p = str; - while ( *p == ' ' ) - p++; - - int type = 0; - if ( qisxdigit((uchar)*(p+1)) && qisxdigit((uchar)*(p+2)) ) - { - switch ( *p ) - { - case ':': - p = "Intel Hex Object Format"; - type = f_HEX; - break; - - case ';': - p = "MOS Technology Hex Object Format"; - type = f_MEX; - break; - - case 'S': - p = "Motorola S-record Format"; - type = f_SREC; - default: - break; - - } - } - if ( type != 0 ) - *fileformatname = p; - return type; -} - -//-------------------------------------------------------------------------- -// this struct was created to save space in the data segment (yes, we were -// counting each byte at that time) -static struct local_data -{ - union - { - char *ptr; //load - int sz; //write - }; - union - { - uint32 ln; //load - int size; //write - }; - ushort sum; //load/write - uchar len; //load -} lc; - -//-------------------------------------------------------------------------- -static void errfmt(void) -{ - loader_failure("Bad hex input file format, line %u", lc.ln); -} - -//-------------------------------------------------------------------------- -// reads the specified number of bytes from the input line -// if size==0, then initializes itself for a new line -static uint32 hexdata(int size) -{ - int i = size; - if ( i == 0 ) - { - i = 2; - } - else - { - if ( lc.len < i ) - errfmt(); - lc.len -= (uchar)i; - i <<= 1; - } - char n[10]; - char *p = n; - while ( i-- ) - *p++ = *lc.ptr++; - *p = '\0'; - char *endp; - uint32 data = strtoul(n, &endp, 16); - if ( endp != p ) - errfmt(); - switch ( size ) - { - case 0: - lc.len = (uchar)data; - lc.sum = lc.len; - break; - - case 4: - lc.sum += (uchar)(data >> 24); - case 3: - lc.sum += (uchar)(data >> 16); - case 2: - lc.sum += (uchar)(data >> 8); - default: //1 - lc.sum += (uchar)data; - break; - } - return data; -} - -//-------------------------------------------------------------------------- -void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/) -{ - memset(&lc, 0, sizeof(local_data)); - inf_set_start_ip(BADADDR); // f_SREC without start record - - processor_t &ph = PH; - bool iscode = (neflag & NEF_CODE) != 0; - uint bs = iscode ? ph.cbsize() : ph.dbsize(); // number of bytes - ea_t start_ea = to_ea(inf_get_baseaddr(), 0); - sel_t sel = setup_selector(start_ea >> 4); - bool segment_created = false; - - bool cvt_to_bytes = false; - if ( ph.id == PLFM_PIC ) - { - // pic12xx and pic16xx use 12-bit and 14-bit words in program memory - // pic18xx uses 16-bit opcodes but byte addressing - if ( strncmp(inf_get_procname().c_str(), "PIC18", 5) != 0 ) - { - static const char *const form = -// "PIC HEX file addressing mode\n" -// "\n" - "There are two flavors of HEX files for PIC: with word addressing\n" - "and with byte addressing. It is not possible to recognize the\n" - "flavor automatically. Please specify what addressing mode should\n" - "be used to load the input file. If you don't know, try both and\n" - "choose the one which produces the more meaningful result\n"; - int code = ask_buttons("~B~yte addressing", - "~W~ord addressing", - "~C~ancel", - 1, - form); - switch ( code ) - { - case 1: - break; - case 0: - cvt_to_bytes = true; - break; - default: - loader_failure(); - } - } - } - - bool bs_addr_scale = true; - if ( ph.id == PLFM_TMS320C28 ) - bs_addr_scale = false; - - filetype_t ftype = inf_get_filetype(); - char rstart = (ftype == f_SREC) ? 'S' - : (ftype == f_HEX) ? ':' - : ';'; - ea_t addr; - ea_t end_ea = 0; - ea_t seg_start = 0; - ea_t subs_addr20 = 0; - ea_t subs_addr32 = 0; - bool bigaddr = false; - char line[BUFFSIZE]; - for ( lc.ln = 1; qlgets(line, BUFFSIZE, li); lc.ln++ ) - { - char *p = line; - while ( *p == ' ' ) - ++p; - if ( *p == '\n' || *p == '\r' ) - continue; - if ( *p++ != rstart ) - errfmt(); - - int sz = 2; - int mode = (ftype == f_SREC) ? (uchar)*p++ : 0x100; - lc.ptr = p; - hexdata(0); - if ( mode == 0x100 ) - { - if ( !lc.len ) - break; - lc.len += 2; - if ( ftype == f_HEX ) - ++lc.len; - } - else - { - switch ( mode ) - { - default: - errfmt(); - - case '0': - case '5': - continue; - - case '3': - case '7': - ++sz; - // fallthrough - case '2': - case '8': - ++sz; - // fallthrough - case '1': - case '9': - if ( mode > '3' ) - mode = 0; - --lc.len; - break; - } - } - addr = hexdata(sz); - if ( ftype != f_SREC && bs_addr_scale ) - addr = addr / bs; - if ( !mode ) - { - inf_set_start_ip(addr); - continue; - } - - if ( ftype == f_HEX ) - { - int type = hexdata(1); // record type - switch ( type ) - { - case 0xFF: // mitsubishi hex format - case 4: // Extended linear address record (bits 16..31 of the start address) - { - uint32 seg_addr = uint32(hexdata(2) << 16); - if ( bs_addr_scale ) - seg_addr /= bs; - subs_addr32 = seg_addr; - } - break; - case 2: // Extended segment address record (bits 4..19 of the start address) - { - uint32 seg_addr = uint32(hexdata(2) << 4); - if ( bs_addr_scale ) - seg_addr /= bs; - subs_addr20 = seg_addr; - } - break; - case 5: //start address (ARM) - { - uint32 start_addr = hexdata(4); - if ( ph.has_code16_bit() && (start_addr & 1) != 0 ) - { - processor_t::set_code16_mode(start_addr, true); - start_addr &= ~1; - } - inf_set_start_ip(start_addr); - inf_set_start_ea(start_addr); - } - break; - } - if ( type != 0 ) - { - if ( type == 1 ) - break; // end of file record - continue; // not a data record - } - } - // add the extended address bits - addr += subs_addr20; - addr += subs_addr32; - if ( lc.len ) - { - ea_t top = addr + lc.len / bs; - p = line; - while ( lc.len ) - { - *p++ = (uchar)hexdata(1); - if ( cvt_to_bytes ) // pic - *p++ = '\0'; - } - if ( top >= 0x10000 ) - bigaddr = true; - addr += start_ea; - show_addr(addr); - top += start_ea; - if ( top > end_ea || !segment_created ) - { - asize_t delta = addr - end_ea; - if ( delta >= SEGMENTGAP ) - segment_created = false; // force creation of new segment - - end_ea = top; - if ( neflag & NEF_SEGS ) - { - if ( !segment_created ) - { - if ( !add_segm(sel, addr, end_ea, NULL, iscode ? CLASS_CODE : CLASS_DATA) ) - loader_failure(); - segment_created = true; - seg_start = addr; - } - else - { - int flags = delta > SPARSE_GAP ? SEGMOD_SPARSE : 0; - set_segm_end(seg_start, end_ea, flags); - } - } - } - if ( seg_start > addr ) - { - if ( (neflag & NEF_SEGS) != 0 ) - { - int flags = seg_start-addr > SPARSE_GAP ? SEGMOD_SPARSE : 0; - set_segm_start(seg_start, addr, flags); - } - seg_start = addr; - } - mem2base(line, addr, top, -1); - } - { - ushort chi; // checksum - ++lc.len; - switch ( ftype ) - { - case f_SREC: - chi = (uchar)(~lc.sum); - chi ^= (uchar)hexdata(1); - break; - case f_HEX: - hexdata(1); - chi = (uchar)lc.sum; - break; - default: //MEX - ++lc.len; - chi = lc.sum; - chi -= (ushort)hexdata(2); - break; - } - if ( chi ) - { - static bool displayed = false; - if ( !displayed ) - { - displayed = true; - warning("Bad hex input file checksum, line %u. Ignore?", lc.ln); - } - } - } - } - - if ( (neflag & NEF_SEGS) != 0 ) - { - if ( bigaddr ) - { - set_segm_addressing(get_first_seg(), 1); - if ( ph.id == PLFM_386 ) - inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); - } - set_default_dataseg(sel); - inf_set_start_cs(sel); - } - else - { - enable_flags(start_ea, end_ea, STT_CUR); - } - inf_set_af(inf_get_af() & ~AF_FINAL); // behave as a binary file - - create_filename_cmt(); -} - -//-------------------------------------------------------------------------- -static int set_s_type(ea_t addr) -{ - int off = 0; - lc.sz = 4; - lc.size += 3; - if ( addr >= 0x10000 ) - { - ++off; - lc.sz += 2; - lc.sum += (uchar)(addr >> 16); - ++lc.size; - if ( addr >= 0x01000000 ) - { - ++off; - lc.sz += 2; - lc.sum += (uchar)(addr >> 24); - ++lc.size; - } - } - return off; -} - -//-------------------------------------------------------------------------- -GCC_DIAG_OFF(format-nonliteral); -int idaapi write_file(FILE *fp, const char * /*fileformatname*/) -{ -//#define TEST_COMPILATION -#ifdef TEST_COMPILATION -# define DECL_FMT(x, y) static const char *const x = y -#else -# define DECL_FMT(x, y) static char x[] = y -#endif - DECL_FMT(fmt0, "%02X%0*" FMT_EA "X%s%0?X\r\n"); - DECL_FMT(fmt1, "?00?00001FF\r\n"); - DECL_FMT(fone, "%02X"); - - ea_t base = to_ea(inf_get_baseaddr(), 0); - if ( inf_get_min_ea() < base ) - base = BADADDR; - - if ( fp == NULL ) - { - if ( inf_get_filetype() == f_SREC ) - return 1; - ea_t ea1 = inf_get_max_ea() - inf_get_min_ea(); - if ( ea1 <= 0x10000 ) - return 1; - ea_t strt = 0; - ea_t addr; - for ( addr = inf_get_min_ea(); addr < inf_get_max_ea(); ) - { - segment_t *ps = getseg(addr); - if ( ps == NULL || ps->type != SEG_IMEM ) - { - if ( is_loaded(addr) ) - break; - if ( base != BADADDR ) - { - if ( --ea1 <= 0x10000 ) - return 1; - } - else - { - ++strt; - } - ++addr; - continue; - } - if ( strt ) - { - ea1 -= strt; - if ( ea1 != 0x10000 ) - return 1; - strt = 0; - } - ea1 -= (ps->end_ea - addr); - if ( ea1 < 0x10000 ) - return 1; - ++ea1; - addr = ps->end_ea; - } - if ( base == BADADDR ) - { - segment_t *ps = getseg(addr); - ea1 -= (ps == NULL) ? addr : ps->start_ea; - if ( ea1 <= 0x10000 ) - return 1; - } - if ( addr == inf_get_max_ea() ) - return 0; - for ( base = inf_get_max_ea()-1; base > addr; ) - { - segment_t *ps = getseg(base); - if ( ps == NULL || ps->type != SEG_IMEM ) - { - if ( is_loaded(base) ) - break; - if ( --ea1 <= 0x10000 ) - return 1; - --base; - continue; - } - ea1 -= (base - ps->start_ea); - if ( ea1 < 0x10000 ) - return 1; - ++ea1; - base = ps->start_ea; - } - return 0; - } - - char ident; - const char *found = qstrrchr(fmt0, '?'); - QASSERT(20067, found != NULL); - int fmt0_marker = ((char *) found) - fmt0; - fmt0[fmt0_marker] = '2'; - switch ( inf_get_filetype() ) - { - case f_SREC: - ident = 'S'; - break; - case f_HEX: - ident = ':'; - fmt1[3] = '0'; - break; - default: - ident = ';'; - fmt0[fmt0_marker] = '4'; - fmt1[3] = '\0'; - break; - } - fmt1[0] = ident; - lc.sz = 4; - - ea_t strt = inf_get_start_ip(); - for ( ea_t ea1 = inf_get_min_ea(); ea1 < inf_get_max_ea(); ) - { - char str[(2 * MAX_BYTES) + 3]; - char *const end = str + sizeof(str); - if ( !is_loaded(ea1) || segtype(ea1) == SEG_IMEM ) - { - ++ea1; - continue; - } - if ( base == BADADDR ) - { - segment_t *ps = getseg(ea1); - base = ps == NULL ? ea1 : ps->start_ea; - if ( strt != BADADDR ) - strt += inf_get_min_ea() - base; - } - ea_t addr = ea1 - base; - lc.sum = (uchar)addr + (uchar)(addr >> 8); - char *p = str; - if ( inf_get_filetype() == f_HEX ) - { - *p++ = '0'; - *p++ = '0'; - } - lc.size = 0; - do - { - uchar b = get_byte(ea1++); - p += qsnprintf(p, end-p, fone, (unsigned)b); - lc.sum += b; - } while ( ++lc.size < MAX_BYTES - && ea1 < inf_get_max_ea() - && is_loaded(ea1) - && segtype(ea1) != SEG_IMEM ); - qfputc(ident, fp); - if ( inf_get_filetype() == f_SREC ) - { - char type = '1' + (char)set_s_type(addr); - qfputc(type, fp); - ++lc.sum; //correct to NOT - } // else addr = (ushort)addr; // force check - lc.sum += (ushort)lc.size; - if ( inf_get_filetype() != f_MEX ) - lc.sum = (uchar)(0-lc.sum); - qfprintf(fp, fmt0, lc.size, lc.sz, addr, str, lc.sum); - } - if ( inf_get_filetype() != f_SREC ) - { - qfprintf(fp, "%s", fmt1); - } - else if ( strt != BADADDR ) - { - qfputc(ident, fp); - lc.sum = 0; - lc.size = 0; - char type = '9' - (char)set_s_type(strt); - qfputc(type, fp); - lc.sum = (~(lc.size + lc.sum)) & 0xFF; - qfprintf(fp, fmt0, lc.size, lc.sz, strt, &fone[sizeof(fone)-1], lc.sum); - } - return 1; -} -GCC_DIAG_ON(format-nonliteral); - -//-------------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - LDRF_REQ_PROC, // requires the target processor to the set -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - write_file, - NULL, - NULL, -}; diff --git a/idasdk75/ldr/hex/makefile b/idasdk75/ldr/hex/makefile deleted file mode 100644 index 5ba4350..0000000 --- a/idasdk75/ldr/hex/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=hex - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)hex$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h hex.cpp diff --git a/idasdk75/ldr/hpsom/makefile b/idasdk75/ldr/hpsom/makefile deleted file mode 100644 index 95e68f2..0000000 --- a/idasdk75/ldr/hpsom/makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROC=hpsom - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)hpsom$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)typeinf.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaldr.h common.cpp hpsom.cpp \ - hpsom.hpp diff --git a/idasdk75/ldr/idaldr.h b/idasdk75/ldr/idaldr.h deleted file mode 100644 index 7f3392f..0000000 --- a/idasdk75/ldr/idaldr.h +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef __IDALDR_H__ -#define __IDALDR_H__ - -#include <ida.hpp> -#include <fpro.h> -#include <idp.hpp> -#include <loader.hpp> -#include <name.hpp> -#include <bytes.hpp> -#include <offset.hpp> -#include <segment.hpp> -#include <segregs.hpp> -#include <fixup.hpp> -#include <entry.hpp> -#include <auto.hpp> -#include <diskio.hpp> -#include <kernwin.hpp> - -//---------------------------------- - -#define CLASS_CODE "CODE" -#define NAME_CODE ".text" -#define CLASS_DATA "DATA" -#define CLASS_CONST "CONST" -#define NAME_DATA ".data" -#define CLASS_BSS "BSS" -#define NAME_BSS ".bss" -#define NAME_EXTERN "extern" -#define NAME_COMMON "common" -#define NAME_ABS "abs" -#define NAME_UNDEF "UNDEF" -#define CLASS_STACK "STACK" -#define CLASS_RES16 "RESOURCE" -#define LDR_NODE "$ IDALDR node for ids loading $" -#define LDR_INFO_NODE "$ IDALDR node for unload $" - -//-------------------------------------------------------------------------- -template <class T> bool _validate_array_count( - linput_t *li, - T *p_cnt, - size_t elsize, - int64 current_offset=-1, - int64 max_offset=-1) -{ - if ( current_offset == -1 ) - current_offset = qltell(li); - if ( max_offset == -1 ) - max_offset = qlsize(li); - int64 rest = max_offset - current_offset; - T cnt = *p_cnt; - if ( current_offset >= 0 && rest >= 0 ) - { -#ifndef __X86__ - typedef size_t biggest_t; -#else - typedef ea_t biggest_t; -#endif - if ( is_mul_ok<biggest_t>(elsize, cnt) ) - { - biggest_t needed = elsize * cnt; -#ifdef __X86__ - if ( needed == size_t(needed) ) -#endif - if ( rest >= needed ) - return true; // all ok - } - cnt = rest / elsize; - } - else - { - cnt = 0; - } - *p_cnt = cnt; - return false; -} - -//-------------------------------------------------------------------------- -// Validate a counter taken from the input file. If there are not enough bytes -// in the input file, ask the user if we may continue and fix the counter. -template <class T> void validate_array_count( - linput_t *li, - T *p_cnt, - size_t elsize, - const char *counter_name, - int64 curoff=-1, - int64 maxoff=-1) -{ - T old = *p_cnt; - if ( !_validate_array_count(li, p_cnt, elsize, curoff, maxoff) ) - { - static const char *const format = - "AUTOHIDE SESSION\n" - "HIDECANCEL\n" - "%s %" FMT_64 "u is incorrect, maximum possible value is %" FMT_64 "u%s"; -#ifndef __KERNEL__ - if ( ask_yn(ASKBTN_YES, - format, - counter_name, - uint64(old), - uint64(*p_cnt), - ". Do you want to continue with the new value?") != ASKBTN_YES ) - { - loader_failure(NULL); - } -#else - warning(format, counter_name, uint64(old), uint64(*p_cnt), ""); -#endif - } -} - -//-------------------------------------------------------------------------- -// Validate a counter taken from the input file. If there are not enough bytes -// in the input file, die. -template <class T> void validate_array_count_or_die( - linput_t *li, - T cnt, - size_t elsize, - const char *counter_name, - int64 curoff=-1, - int64 maxoff=-1) -{ - if ( !_validate_array_count(li, &cnt, elsize, curoff, maxoff) ) - { - static const char *const format = - "%s is incorrect, maximum possible value is %u%s"; -#ifndef __KERNEL__ - loader_failure(format, counter_name, uint(cnt), ""); -#else - error(format, counter_name, uint(cnt), ""); -#endif - } -} - -//---------------------------------- -inline uchar readchar(linput_t *li) -{ - uchar x; - lread(li, &x, sizeof(x)); - return x; -} - -//---------------------------------- -inline uint16 readshort(linput_t *li) -{ - uint16 x; - lread(li, &x, sizeof(x)); - return x; -} - -//---------------------------------- -inline uint32 readlong(linput_t *li) -{ - uint32 x; - lread(li, &x, sizeof(x)); - return x; -} - -inline uint32 mf_readlong(linput_t *li) { return swap32(readlong(li)); } -inline uint16 mf_readshort(linput_t *li) { return swap16(readshort(li)); } - -// each loader must declare and export this symbol: -idaman loader_t ida_module_data LDSC; - -#endif // __IDALDR_H__ diff --git a/idasdk75/ldr/intelomf/makefile b/idasdk75/ldr/intelomf/makefile deleted file mode 100644 index 8626a12..0000000 --- a/idasdk75/ldr/intelomf/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=intelomf - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)intelomf$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h common.cpp intelomf.cpp intelomf.hpp diff --git a/idasdk75/ldr/javaldr/makefile b/idasdk75/ldr/javaldr/makefile deleted file mode 100644 index 6877d37..0000000 --- a/idasdk75/ldr/javaldr/makefile +++ /dev/null @@ -1,15 +0,0 @@ -PROC=javaldr - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)javaldr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/java/classfil.hpp \ - ../../module/java/notify_codes.hpp ../idaldr.h \ - javaldr.cpp diff --git a/idasdk75/ldr/loader.mak b/idasdk75/ldr/loader.mak deleted file mode 100644 index 4277224..0000000 --- a/idasdk75/ldr/loader.mak +++ /dev/null @@ -1,13 +0,0 @@ - -#__FUZZ_LOADERS__=1 - -SRC_PATH = $(IDA)ldr/ -BIN_PATH = $(R)loaders/ - -BASE_OBJS += $(F)$(PROC)$(O) - -ifdef __NT__ - DLLFLAGS += /BASE:0x140000000 -endif - -include ../../module.mak diff --git a/idasdk75/ldr/mach-o/base.cpp b/idasdk75/ldr/mach-o/base.cpp deleted file mode 100644 index 10b3244..0000000 --- a/idasdk75/ldr/mach-o/base.cpp +++ /dev/null @@ -1,159 +0,0 @@ - -#define is_magic(a) ( ((a) == MH_MAGIC) || ((a) == MH_MAGIC_64) ) -#define is_cigam(a) ( ((a) == MH_CIGAM) || ((a) == MH_CIGAM_64) ) - - -//-------------------------------------------------------------------------- -static void swap_fat_header(fat_header *fh) -{ - fh->magic = swap32(fh->magic); - fh->nfat_arch = swap32(fh->nfat_arch); -} - -//-------------------------------------------------------------------------- -static void swap_fat_arch(fat_arch *fa) -{ - fa->cputype = swap32(fa->cputype); - fa->cpusubtype = swap32(fa->cpusubtype); - fa->offset = swap32(fa->offset); - fa->size = swap32(fa->size); - fa->align = swap32(fa->align); -} - -#if defined(LOADER_COMPILE) || defined(BUILD_DWARF) || defined(DWARFER) || defined(BUILD_EFD) || defined(BUILD_DEBUGGER) -// --------------------------------------------------------------------------- -int macho_arch_to_ida_arch(cpu_type_t cputype, cpu_subtype_t /*cpusubtype*/, bool *is_64) -{ - bool _64 = false; - int target = -1; - switch ( cputype ) - { - default: - case CPU_TYPE_VAX: - case CPU_TYPE_ROMP: - case CPU_TYPE_NS32032: - case CPU_TYPE_NS32332: - case CPU_TYPE_MC88000: - break; - case CPU_TYPE_MC680x0: - target = PLFM_68K; - break; - case CPU_TYPE_I860: - target = PLFM_I860; - break; - case CPU_TYPE_I386: - target = PLFM_386; - break; - case CPU_TYPE_POWERPC: - target = PLFM_PPC; - break; - case CPU_TYPE_HPPA: - target = PLFM_HPPA; - break; - case CPU_TYPE_SPARC: - target = PLFM_SPARC; - break; - case CPU_TYPE_MIPS: - target = PLFM_MIPS; - break; - case CPU_TYPE_ARM: - case CPU_TYPE_ARM64_32: - target = PLFM_ARM; - break; -#ifdef __EA64__ // see also below, the error message for it - case CPU_TYPE_ARM64: - _64 = true; - target = PLFM_ARM; - break; - case CPU_TYPE_X86_64: - _64 = true; - target = PLFM_386; - break; -#endif - case CPU_TYPE_POWERPC64: - target = PLFM_PPC; - break; - } - if ( is_64 != NULL ) - *is_64 = _64; //-V547 'A = false' - return target; -} -#endif - -//-------------------------------------------------------------------------- -bool macho_file_t::parse_header() -{ - qlseek(li, start_offset); - uint32 magic; - if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) ) - return false; - if ( magic == FAT_MAGIC || magic == FAT_CIGAM ) - return parse_fat_header(); - else - return is_magic(magic) || is_cigam(magic); -} - -//-------------------------------------------------------------------------- -bool macho_file_t::parse_fat_header() -{ - qlseek(li, start_offset); - if ( qlread(li, &fheader, sizeof(fheader)) != sizeof(fheader) ) - return false; - int code = (fheader.magic == FAT_MAGIC); - if ( fheader.magic == FAT_CIGAM ) - { - swap_fat_header(&fheader); - code = 2; - } - if ( code == 0 || fheader.nfat_arch > 16 ) - return false; - - uint64 fsize = qlsize(li); - uint32 archs_size = fheader.nfat_arch * sizeof(fat_arch); - if ( sizeof(fat_header) + archs_size >= fsize ) - return false; - - fat_archs.resize(fheader.nfat_arch); - - if ( qlread(li, fat_archs.begin(), archs_size) != archs_size ) - { - fat_archs.clear(); - return false; - } - - for ( uint32_t i=0; i < fheader.nfat_arch; i++ ) - { - fat_arch *parch = &fat_archs[i]; - if ( code == 2 ) - swap_fat_arch(parch); - if ( parch->size <= sizeof(mach_header) - || parch->size >= fsize - || parch->offset < sizeof(fat_header) + archs_size - || parch->offset + parch->size > fsize ) - { - fat_archs.clear(); - return false; - } - } - return true; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_fat_header(fat_header *fh) -{ - if ( fat_archs.empty() ) - return false; - *fh = fheader; - return true; -} -//-------------------------------------------------------------------------- -bool macho_file_t::get_fat_arch(uint n, fat_arch *fa) -{ - if ( n >= fat_archs.size() ) - { - memset(fa, 0, sizeof(*fa)); - return false; - } - *fa = fat_archs[n]; - return true; -} diff --git a/idasdk75/ldr/mach-o/common.cpp b/idasdk75/ldr/mach-o/common.cpp deleted file mode 100644 index d5555a7..0000000 --- a/idasdk75/ldr/mach-o/common.cpp +++ /dev/null @@ -1,6547 +0,0 @@ -#include "../idaldr.h" -#include "common.h" -#include <range.hpp> -#include <kernwin.hpp> -#include <err.h> -#include <numeric> - -#include "../ar/ar.hpp" - -#include <mach/kmod.h> - -// note that this code is used when building idapyswitch for mac. -// we must avoid including irrxml junk for idapyswitch because it will ultimately be published -// with the public idapython source, which must not depend on irrxml (which we don't publish). -#ifndef BUILD_IDAPYSWITCH -#include <irrXML.h> -#include <CXMLReaderImpl.h> -using namespace irr; -using namespace io; -#endif - -//-------------------------------------------------------------------------- -bool isPair(const struct mach_header_64 *mh, int type) -{ - return (mh->cputype == CPU_TYPE_ARM && type == ARM_RELOC_PAIR) - || (mh->cputype == CPU_TYPE_MC680x0 && type == GENERIC_RELOC_PAIR) - || (mh->cputype == CPU_TYPE_I386 && type == GENERIC_RELOC_PAIR) - || (mh->cputype == CPU_TYPE_MC88000 && type == M88K_RELOC_PAIR) - || ((mh->cputype == CPU_TYPE_POWERPC - || mh->cputype == CPU_TYPE_POWERPC64 - || mh->cputype == CPU_TYPE_VEO) && type == PPC_RELOC_PAIR) - || (mh->cputype == CPU_TYPE_HPPA && type == HPPA_RELOC_PAIR) - || (mh->cputype == CPU_TYPE_SPARC && type == SPARC_RELOC_PAIR) - || (mh->cputype == CPU_TYPE_I860 && type == I860_RELOC_PAIR); -} - -//-------------------------------------------------------------------------- -bool isSectdiff(const struct mach_header_64 *mh, int type) -{ - return (mh->cputype == CPU_TYPE_MC680x0 && (type == GENERIC_RELOC_SECTDIFF || type == GENERIC_RELOC_LOCAL_SECTDIFF)) - || (mh->cputype == CPU_TYPE_I386 && (type == GENERIC_RELOC_SECTDIFF || type == GENERIC_RELOC_LOCAL_SECTDIFF)) - || (mh->cputype == CPU_TYPE_ARM - && (type == ARM_RELOC_SECTDIFF - || type == ARM_RELOC_LOCAL_SECTDIFF - || type == ARM_RELOC_HALF_SECTDIFF)) - || (mh->cputype == CPU_TYPE_MC88000 && type == M88K_RELOC_SECTDIFF) - || ((mh->cputype == CPU_TYPE_POWERPC - || mh->cputype == CPU_TYPE_POWERPC64 - || mh->cputype == CPU_TYPE_VEO) - && (type == PPC_RELOC_SECTDIFF - || type == PPC_RELOC_LOCAL_SECTDIFF - || type == PPC_RELOC_HI16_SECTDIFF - || type == PPC_RELOC_LO16_SECTDIFF - || type == PPC_RELOC_LO14_SECTDIFF - || type == PPC_RELOC_HA16_SECTDIFF)) - || (mh->cputype == CPU_TYPE_I860 && type == I860_RELOC_SECTDIFF) - || (mh->cputype == CPU_TYPE_HPPA - && (type == HPPA_RELOC_SECTDIFF - || type == HPPA_RELOC_HI21_SECTDIFF - || type == HPPA_RELOC_LO14_SECTDIFF)) - || (mh->cputype == CPU_TYPE_SPARC - && (type == SPARC_RELOC_SECTDIFF - || type == SPARC_RELOC_HI22_SECTDIFF - || type == SPARC_RELOC_LO10_SECTDIFF)); -} - -//-------------------------------------------------------------------------- -static void swap_mach_header_64(struct mach_header_64 *mh) -{ - mh->magic = swap32(mh->magic); - mh->cputype = swap32(mh->cputype); - mh->cpusubtype = swap32(mh->cpusubtype); - mh->filetype = swap32(mh->filetype); - mh->ncmds = swap32(mh->ncmds); - mh->sizeofcmds = swap32(mh->sizeofcmds); - mh->flags = swap32(mh->flags); - mh->reserved = swap32(mh->reserved); -} - -//-------------------------------------------------------------------------- -static void swap_load_command(load_command *lc) -{ - lc->cmd = swap32(lc->cmd); - lc->cmdsize = swap32(lc->cmdsize); -} - -//-------------------------------------------------------------------------- -static void swap_segment_command(segment_command *sg) -{ - /* segname[16] */ - sg->cmd = swap32(sg->cmd); - sg->cmdsize = swap32(sg->cmdsize); - sg->vmaddr = swap32(sg->vmaddr); - sg->vmsize = swap32(sg->vmsize); - sg->fileoff = swap32(sg->fileoff); - sg->filesize = swap32(sg->filesize); - sg->maxprot = swap32(sg->maxprot); - sg->initprot = swap32(sg->initprot); - sg->nsects = swap32(sg->nsects); - sg->flags = swap32(sg->flags); -} - -static void swap_segment_command(segment_command_64 *sg) -{ - /* segname[16] */ - sg->cmd = swap32(sg->cmd); - sg->cmdsize = swap32(sg->cmdsize); - sg->vmaddr = swap64(sg->vmaddr); - sg->vmsize = swap64(sg->vmsize); - sg->fileoff = swap64(sg->fileoff); - sg->filesize = swap64(sg->filesize); - sg->maxprot = swap32(sg->maxprot); - sg->initprot = swap32(sg->initprot); - sg->nsects = swap32(sg->nsects); - sg->flags = swap32(sg->flags); -} - -//-------------------------------------------------------------------------- -static void swap_section(section *s, uint32 nsects) -{ - for ( uint32 i = 0; i < nsects; i++ ) - { - /* sectname[16] */ - /* segname[16] */ - s[i].addr = swap32(s[i].addr); - s[i].size = swap32(s[i].size); - s[i].offset = swap32(s[i].offset); - s[i].align = swap32(s[i].align); - s[i].reloff = swap32(s[i].reloff); - s[i].nreloc = swap32(s[i].nreloc); - s[i].flags = swap32(s[i].flags); - s[i].reserved1 = swap32(s[i].reserved1); - s[i].reserved2 = swap32(s[i].reserved2); - } -} - -//-------------------------------------------------------------------------- -static void swap_section(section_64 *s, uint32 nsects) -{ - for ( uint32 i = 0; i < nsects; i++ ) - { - /* sectname[16] */ - /* segname[16] */ - s[i].addr = swap64(s[i].addr); - s[i].size = swap64(s[i].size); - s[i].offset = swap32(s[i].offset); - s[i].align = swap32(s[i].align); - s[i].reloff = swap32(s[i].reloff); - s[i].nreloc = swap32(s[i].nreloc); - s[i].flags = swap32(s[i].flags); - s[i].reserved1 = swap32(s[i].reserved1); - s[i].reserved2 = swap32(s[i].reserved2); - } -} - -//-------------------------------------------------------------------------- -static void swap_symtab_command(symtab_command *st) -{ - st->cmd = swap32(st->cmd); - st->cmdsize = swap32(st->cmdsize); - st->symoff = swap32(st->symoff); - st->nsyms = swap32(st->nsyms); - st->stroff = swap32(st->stroff); - st->strsize = swap32(st->strsize); -} - -//-------------------------------------------------------------------------- -static void swap_dysymtab_command(dysymtab_command *dyst) -{ - dyst->cmd = swap32(dyst->cmd); - dyst->cmdsize = swap32(dyst->cmdsize); - dyst->ilocalsym = swap32(dyst->ilocalsym); - dyst->nlocalsym = swap32(dyst->nlocalsym); - dyst->iextdefsym = swap32(dyst->iextdefsym); - dyst->nextdefsym = swap32(dyst->nextdefsym); - dyst->iundefsym = swap32(dyst->iundefsym); - dyst->nundefsym = swap32(dyst->nundefsym); - dyst->tocoff = swap32(dyst->tocoff); - dyst->ntoc = swap32(dyst->ntoc); - dyst->modtaboff = swap32(dyst->modtaboff); - dyst->nmodtab = swap32(dyst->nmodtab); - dyst->extrefsymoff = swap32(dyst->extrefsymoff); - dyst->nextrefsyms = swap32(dyst->nextrefsyms); - dyst->indirectsymoff = swap32(dyst->indirectsymoff); - dyst->nindirectsyms = swap32(dyst->nindirectsyms); - dyst->extreloff = swap32(dyst->extreloff); - dyst->nextrel = swap32(dyst->nextrel); - dyst->locreloff = swap32(dyst->locreloff); - dyst->nlocrel = swap32(dyst->nlocrel); -} - -//-------------------------------------------------------------------------- -static void swap_symseg_command(symseg_command *ss) -{ - ss->cmd = swap32(ss->cmd); - ss->cmdsize = swap32(ss->cmdsize); - ss->offset = swap32(ss->offset); - ss->size = swap32(ss->size); -} - -//-------------------------------------------------------------------------- -static void swap_fvmlib_command(fvmlib_command *fl) -{ - fl->cmd = swap32(fl->cmd); - fl->cmdsize = swap32(fl->cmdsize); - fl->fvmlib.name.offset = swap32(fl->fvmlib.name.offset); - fl->fvmlib.minor_version = swap32(fl->fvmlib.minor_version); - fl->fvmlib.header_addr = swap32(fl->fvmlib.header_addr); -} - -//-------------------------------------------------------------------------- -static void swap_thread_command(thread_command *tc) -{ - tc->cmd = swap32(tc->cmd); - tc->cmdsize = swap32(tc->cmdsize); -} - -//-------------------------------------------------------------------------- -static void swap_dylib_command(dylib_command *dl) -{ - dl->cmd = swap32(dl->cmd); - dl->cmdsize = swap32(dl->cmdsize); - dl->dylib.name.offset = swap32(dl->dylib.name.offset); - dl->dylib.timestamp = swap32(dl->dylib.timestamp); - dl->dylib.current_version = swap32(dl->dylib.current_version); - dl->dylib.compatibility_version = swap32(dl->dylib.compatibility_version); -} - -//-------------------------------------------------------------------------- -static void swap_sub_framework_command(sub_framework_command *sub) -{ - sub->cmd = swap32(sub->cmd); - sub->cmdsize = swap32(sub->cmdsize); - sub->umbrella.offset = swap32(sub->umbrella.offset); -} - -//-------------------------------------------------------------------------- -static void swap_sub_umbrella_command(sub_umbrella_command *usub) -{ - usub->cmd = swap32(usub->cmd); - usub->cmdsize = swap32(usub->cmdsize); - usub->sub_umbrella.offset = swap32(usub->sub_umbrella.offset); -} - -//-------------------------------------------------------------------------- -static void swap_sub_library_command(struct sub_library_command *lsub) -{ - lsub->cmd = swap32(lsub->cmd); - lsub->cmdsize = swap32(lsub->cmdsize); - lsub->sub_library.offset = swap32(lsub->sub_library.offset); -} - -//-------------------------------------------------------------------------- -static void swap_sub_client_command(sub_client_command *csub) -{ - csub->cmd = swap32(csub->cmd); - csub->cmdsize = swap32(csub->cmdsize); - csub->client.offset = swap32(csub->client.offset); -} - -//-------------------------------------------------------------------------- -static void swap_prebound_dylib_command(prebound_dylib_command *pbdylib) -{ - pbdylib->cmd = swap32(pbdylib->cmd); - pbdylib->cmdsize = swap32(pbdylib->cmdsize); - pbdylib->name.offset = swap32(pbdylib->name.offset); - pbdylib->nmodules = swap32(pbdylib->nmodules); - pbdylib->linked_modules.offset = swap32(pbdylib->linked_modules.offset); -} - -//-------------------------------------------------------------------------- -static void swap_dylinker_command(dylinker_command *dyld) -{ - dyld->cmd = swap32(dyld->cmd); - dyld->cmdsize = swap32(dyld->cmdsize); - dyld->name.offset = swap32(dyld->name.offset); -} - -//-------------------------------------------------------------------------- -static void swap_fvmfile_command(fvmfile_command *ff) -{ - ff->cmd = swap32(ff->cmd); - ff->cmdsize = swap32(ff->cmdsize); - ff->name.offset = swap32(ff->name.offset); - ff->header_addr = swap32(ff->header_addr); -} - -//-------------------------------------------------------------------------- -/* -#ifndef EFD_COMPILE -static void swap_thread_command(thread_command *ut) -{ - ut->cmd = swap32(ut->cmd); - ut->cmdsize = swap32(ut->cmdsize); -} -#endif // EFD_COMPILE -*/ - -//-------------------------------------------------------------------------- -/* -static void swap_m68k_thread_state_regs(struct m68k_thread_state_regs *cpu) -{ - uint32 i; - for ( i = 0; i < 8; i++ ) - cpu->dreg[i] = swap32(cpu->dreg[i]); - for ( i = 0; i < 8; i++ ) - cpu->areg[i] = swap32(cpu->areg[i]); - cpu->pad0 = swap16(cpu->pad0); - cpu->sr = swap16(cpu->sr); - cpu->pc = swap32(cpu->pc); -} - -//-------------------------------------------------------------------------- -static void swap_m68k_thread_state_68882(struct m68k_thread_state_68882 *fpu) -{ - uint32 i, tmp; - - for ( i = 0; i < 8; i++ ) - { - tmp = swap32(fpu->regs[i].fp[0]); - fpu->regs[i].fp[1] = swap32(fpu->regs[i].fp[1]); - fpu->regs[i].fp[0] = swap32(fpu->regs[i].fp[2]); - fpu->regs[i].fp[2] = tmp; - } - fpu->cr = swap32(fpu->cr); - fpu->sr = swap32(fpu->sr); - fpu->iar = swap32(fpu->iar); - fpu->state = swap32(fpu->state); -} - -//-------------------------------------------------------------------------- -static void swap_m68k_thread_state_user_reg(struct m68k_thread_state_user_reg *user_reg) -{ - user_reg->user_reg = swap32(user_reg->user_reg); -} - -//-------------------------------------------------------------------------- -static void swap_m88k_thread_state_grf_t(m88k_thread_state_grf_t *cpu) -{ - cpu->r1 = swap32(cpu->r1); - cpu->r2 = swap32(cpu->r2); - cpu->r3 = swap32(cpu->r3); - cpu->r4 = swap32(cpu->r4); - cpu->r5 = swap32(cpu->r5); - cpu->r6 = swap32(cpu->r6); - cpu->r7 = swap32(cpu->r7); - cpu->r8 = swap32(cpu->r8); - cpu->r9 = swap32(cpu->r9); - cpu->r10 = swap32(cpu->r10); - cpu->r11 = swap32(cpu->r11); - cpu->r12 = swap32(cpu->r12); - cpu->r13 = swap32(cpu->r13); - cpu->r14 = swap32(cpu->r14); - cpu->r15 = swap32(cpu->r15); - cpu->r16 = swap32(cpu->r16); - cpu->r17 = swap32(cpu->r17); - cpu->r18 = swap32(cpu->r18); - cpu->r19 = swap32(cpu->r19); - cpu->r20 = swap32(cpu->r20); - cpu->r21 = swap32(cpu->r21); - cpu->r22 = swap32(cpu->r22); - cpu->r23 = swap32(cpu->r23); - cpu->r24 = swap32(cpu->r24); - cpu->r25 = swap32(cpu->r25); - cpu->r26 = swap32(cpu->r26); - cpu->r27 = swap32(cpu->r27); - cpu->r28 = swap32(cpu->r28); - cpu->r29 = swap32(cpu->r29); - cpu->r30 = swap32(cpu->r30); - cpu->r31 = swap32(cpu->r31); - cpu->xip = swap32(cpu->xip); - cpu->xip_in_bd = swap32(cpu->xip_in_bd); - cpu->nip = swap32(cpu->nip); -} - -//-------------------------------------------------------------------------- -static void swap_m88k_thread_state_xrf_t(m88k_thread_state_xrf_t *fpu) -{ - struct swapped_m88k_fpsr - { - union - { - struct - { - unsigned afinx:BIT_WIDTH(0); - unsigned afovf:BIT_WIDTH(1); - unsigned afunf:BIT_WIDTH(2); - unsigned afdvz:BIT_WIDTH(3); - unsigned afinv:BIT_WIDTH(4); - unsigned :BITS_WIDTH(15,5); - unsigned xmod :BIT_WIDTH(16); - unsigned :BITS_WIDTH(31,17); - } fields; - uint32 word; - } u; - } ssr; - struct swapped_m88k_fpcr - { - union - { - struct - { - unsigned efinx:BIT_WIDTH(0); - unsigned efovf:BIT_WIDTH(1); - unsigned efunf:BIT_WIDTH(2); - unsigned efdvz:BIT_WIDTH(3); - unsigned efinv:BIT_WIDTH(4); - unsigned :BITS_WIDTH(13,5); - m88k_fpcr_rm_t rm:BITS_WIDTH(15,14); - unsigned :BITS_WIDTH(31,16); - } fields; - uint32 word; - } u; - } scr; - - fpu->x1.x[0] = swap32(fpu->x1.x[0]); - fpu->x1.x[1] = swap32(fpu->x1.x[1]); - fpu->x1.x[2] = swap32(fpu->x1.x[2]); - fpu->x1.x[3] = swap32(fpu->x1.x[3]); - fpu->x2.x[0] = swap32(fpu->x2.x[0]); - fpu->x2.x[1] = swap32(fpu->x2.x[1]); - fpu->x2.x[2] = swap32(fpu->x2.x[2]); - fpu->x2.x[3] = swap32(fpu->x2.x[3]); - fpu->x3.x[0] = swap32(fpu->x3.x[0]); - fpu->x3.x[1] = swap32(fpu->x3.x[1]); - fpu->x3.x[2] = swap32(fpu->x3.x[2]); - fpu->x3.x[3] = swap32(fpu->x3.x[3]); - fpu->x4.x[0] = swap32(fpu->x4.x[0]); - fpu->x4.x[1] = swap32(fpu->x4.x[1]); - fpu->x4.x[2] = swap32(fpu->x4.x[2]); - fpu->x4.x[3] = swap32(fpu->x4.x[3]); - fpu->x5.x[0] = swap32(fpu->x5.x[0]); - fpu->x5.x[1] = swap32(fpu->x5.x[1]); - fpu->x5.x[2] = swap32(fpu->x5.x[2]); - fpu->x5.x[3] = swap32(fpu->x5.x[3]); - fpu->x6.x[0] = swap32(fpu->x6.x[0]); - fpu->x6.x[1] = swap32(fpu->x6.x[1]); - fpu->x6.x[2] = swap32(fpu->x6.x[2]); - fpu->x6.x[3] = swap32(fpu->x6.x[3]); - fpu->x7.x[0] = swap32(fpu->x7.x[0]); - fpu->x7.x[1] = swap32(fpu->x7.x[1]); - fpu->x7.x[2] = swap32(fpu->x7.x[2]); - fpu->x7.x[3] = swap32(fpu->x7.x[3]); - fpu->x8.x[0] = swap32(fpu->x8.x[0]); - fpu->x8.x[1] = swap32(fpu->x8.x[1]); - fpu->x8.x[2] = swap32(fpu->x8.x[2]); - fpu->x8.x[3] = swap32(fpu->x8.x[3]); - fpu->x9.x[0] = swap32(fpu->x9.x[0]); - fpu->x9.x[1] = swap32(fpu->x9.x[1]); - fpu->x9.x[2] = swap32(fpu->x9.x[2]); - fpu->x9.x[3] = swap32(fpu->x9.x[3]); - fpu->x10.x[0] = swap32(fpu->x10.x[0]); - fpu->x10.x[1] = swap32(fpu->x10.x[1]); - fpu->x10.x[2] = swap32(fpu->x10.x[2]); - fpu->x10.x[3] = swap32(fpu->x10.x[3]); - fpu->x11.x[0] = swap32(fpu->x11.x[0]); - fpu->x11.x[1] = swap32(fpu->x11.x[1]); - fpu->x11.x[2] = swap32(fpu->x11.x[2]); - fpu->x11.x[3] = swap32(fpu->x11.x[3]); - fpu->x12.x[0] = swap32(fpu->x12.x[0]); - fpu->x12.x[1] = swap32(fpu->x12.x[1]); - fpu->x12.x[2] = swap32(fpu->x12.x[2]); - fpu->x12.x[3] = swap32(fpu->x12.x[3]); - fpu->x13.x[0] = swap32(fpu->x13.x[0]); - fpu->x13.x[1] = swap32(fpu->x13.x[1]); - fpu->x13.x[2] = swap32(fpu->x13.x[2]); - fpu->x13.x[3] = swap32(fpu->x13.x[3]); - fpu->x14.x[0] = swap32(fpu->x14.x[0]); - fpu->x14.x[1] = swap32(fpu->x14.x[1]); - fpu->x14.x[2] = swap32(fpu->x14.x[2]); - fpu->x14.x[3] = swap32(fpu->x14.x[3]); - fpu->x15.x[0] = swap32(fpu->x15.x[0]); - fpu->x15.x[1] = swap32(fpu->x15.x[1]); - fpu->x15.x[2] = swap32(fpu->x15.x[2]); - fpu->x15.x[3] = swap32(fpu->x15.x[3]); - fpu->x16.x[0] = swap32(fpu->x16.x[0]); - fpu->x16.x[1] = swap32(fpu->x16.x[1]); - fpu->x16.x[2] = swap32(fpu->x16.x[2]); - fpu->x16.x[3] = swap32(fpu->x16.x[3]); - fpu->x17.x[0] = swap32(fpu->x17.x[0]); - fpu->x17.x[1] = swap32(fpu->x17.x[1]); - fpu->x17.x[2] = swap32(fpu->x17.x[2]); - fpu->x17.x[3] = swap32(fpu->x17.x[3]); - fpu->x18.x[0] = swap32(fpu->x18.x[0]); - fpu->x18.x[1] = swap32(fpu->x18.x[1]); - fpu->x18.x[2] = swap32(fpu->x18.x[2]); - fpu->x18.x[3] = swap32(fpu->x18.x[3]); - fpu->x19.x[0] = swap32(fpu->x19.x[0]); - fpu->x19.x[1] = swap32(fpu->x19.x[1]); - fpu->x19.x[2] = swap32(fpu->x19.x[2]); - fpu->x19.x[3] = swap32(fpu->x19.x[3]); - fpu->x20.x[0] = swap32(fpu->x20.x[0]); - fpu->x20.x[1] = swap32(fpu->x20.x[1]); - fpu->x20.x[2] = swap32(fpu->x20.x[2]); - fpu->x20.x[3] = swap32(fpu->x20.x[3]); - fpu->x21.x[0] = swap32(fpu->x21.x[0]); - fpu->x21.x[1] = swap32(fpu->x21.x[1]); - fpu->x21.x[2] = swap32(fpu->x21.x[2]); - fpu->x21.x[3] = swap32(fpu->x21.x[3]); - fpu->x22.x[0] = swap32(fpu->x22.x[0]); - fpu->x22.x[1] = swap32(fpu->x22.x[1]); - fpu->x22.x[2] = swap32(fpu->x22.x[2]); - fpu->x22.x[3] = swap32(fpu->x22.x[3]); - fpu->x23.x[0] = swap32(fpu->x23.x[0]); - fpu->x23.x[1] = swap32(fpu->x23.x[1]); - fpu->x23.x[2] = swap32(fpu->x23.x[2]); - fpu->x23.x[3] = swap32(fpu->x23.x[3]); - fpu->x24.x[0] = swap32(fpu->x24.x[0]); - fpu->x24.x[1] = swap32(fpu->x24.x[1]); - fpu->x24.x[2] = swap32(fpu->x24.x[2]); - fpu->x24.x[3] = swap32(fpu->x24.x[3]); - fpu->x25.x[0] = swap32(fpu->x25.x[0]); - fpu->x25.x[1] = swap32(fpu->x25.x[1]); - fpu->x25.x[2] = swap32(fpu->x25.x[2]); - fpu->x25.x[3] = swap32(fpu->x25.x[3]); - fpu->x26.x[0] = swap32(fpu->x26.x[0]); - fpu->x26.x[1] = swap32(fpu->x26.x[1]); - fpu->x26.x[2] = swap32(fpu->x26.x[2]); - fpu->x26.x[3] = swap32(fpu->x26.x[3]); - fpu->x27.x[0] = swap32(fpu->x27.x[0]); - fpu->x27.x[1] = swap32(fpu->x27.x[1]); - fpu->x27.x[2] = swap32(fpu->x27.x[2]); - fpu->x27.x[3] = swap32(fpu->x27.x[3]); - fpu->x28.x[0] = swap32(fpu->x28.x[0]); - fpu->x28.x[1] = swap32(fpu->x28.x[1]); - fpu->x28.x[2] = swap32(fpu->x28.x[2]); - fpu->x28.x[3] = swap32(fpu->x28.x[3]); - fpu->x29.x[0] = swap32(fpu->x29.x[0]); - fpu->x29.x[1] = swap32(fpu->x29.x[1]); - fpu->x29.x[2] = swap32(fpu->x29.x[2]); - fpu->x29.x[3] = swap32(fpu->x29.x[3]); - fpu->x30.x[0] = swap32(fpu->x30.x[0]); - fpu->x30.x[1] = swap32(fpu->x30.x[1]); - fpu->x30.x[2] = swap32(fpu->x30.x[2]); - fpu->x30.x[3] = swap32(fpu->x30.x[3]); - fpu->x31.x[0] = swap32(fpu->x31.x[0]); - fpu->x31.x[1] = swap32(fpu->x31.x[1]); - fpu->x31.x[2] = swap32(fpu->x31.x[2]); - fpu->x31.x[3] = swap32(fpu->x31.x[3]); - - if ( !mf ) - { - memcpy(&ssr, &(fpu->fpsr), sizeof(struct swapped_m88k_fpsr)); - ssr.u.word = swap32(ssr.u.word); - fpu->fpsr.afinx = ssr.u.fields.afinx; - fpu->fpsr.afovf = ssr.u.fields.afovf; - fpu->fpsr.afunf = ssr.u.fields.afunf; - fpu->fpsr.afdvz = ssr.u.fields.afdvz; - fpu->fpsr.afinv = ssr.u.fields.afinv; - fpu->fpsr.xmod = ssr.u.fields.xmod; - - memcpy(&scr, &(fpu->fpcr), sizeof(struct swapped_m88k_fpcr)); - scr.u.word = swap32(scr.u.word); - fpu->fpcr.efinx = scr.u.fields.efinx; - fpu->fpcr.efovf = scr.u.fields.efovf; - fpu->fpcr.efunf = scr.u.fields.efunf; - fpu->fpcr.efdvz = scr.u.fields.efdvz; - fpu->fpcr.efinv = scr.u.fields.efinv; - fpu->fpcr.rm = scr.u.fields.rm; - } - else - { - ssr.u.fields.afinx = fpu->fpsr.afinx; - ssr.u.fields.afovf = fpu->fpsr.afovf; - ssr.u.fields.afunf = fpu->fpsr.afunf; - ssr.u.fields.afdvz = fpu->fpsr.afdvz; - ssr.u.fields.afinv = fpu->fpsr.afinv; - ssr.u.fields.xmod = fpu->fpsr.xmod; - ssr.u.word = swap32(ssr.u.word); - memcpy(&(fpu->fpsr), &ssr, sizeof(struct swapped_m88k_fpsr)); - - scr.u.fields.efinx = fpu->fpcr.efinx; - scr.u.fields.efovf = fpu->fpcr.efovf; - scr.u.fields.efunf = fpu->fpcr.efunf; - scr.u.fields.efdvz = fpu->fpcr.efdvz; - scr.u.fields.efinv = fpu->fpcr.efinv; - scr.u.fields.rm = fpu->fpcr.rm; - scr.u.word = swap32(scr.u.word); - memcpy(&(fpu->fpcr), &scr, sizeof(struct swapped_m88k_fpcr)); - } -} - -//-------------------------------------------------------------------------- -static void swap_m88k_thread_state_user_t(m88k_thread_state_user_t *user) -{ - user->user = swap32(user->user); -} - -//-------------------------------------------------------------------------- -static void swap_m88110_thread_state_impl_t(m88110_thread_state_impl_t *spu) -{ - uint32 i; - - struct swapped_m88110_bp_ctrl - { - union - { - struct - { - unsigned v:BIT_WIDTH(0); - m88110_match_t addr_match:BITS_WIDTH(12,1); - unsigned :BITS_WIDTH(26,13); - unsigned rwm:BIT_WIDTH(27); - unsigned rw:BIT_WIDTH(28); - unsigned :BITS_WIDTH(31,29); - } fields; - uint32 word; - } u; - } sbpc; - - struct swap_m88110_psr - { - union - { - struct - { - unsigned :BITS_WIDTH(1,0); - unsigned mxm_dis:BIT_WIDTH(2); - unsigned sfu1dis:BIT_WIDTH(3); - unsigned :BITS_WIDTH(22,4); - unsigned trace :BIT_WIDTH(23); - unsigned :BIT_WIDTH(24); - unsigned sm :BIT_WIDTH(25); - unsigned sgn_imd:BIT_WIDTH(26); - unsigned :BIT_WIDTH(27); - unsigned c :BIT_WIDTH(28); - unsigned se :BIT_WIDTH(29); - unsigned le :BIT_WIDTH(30); - unsigned supr :BIT_WIDTH(31); - } fields; - uint32 word; - } u; - } spsr; - - struct swapped_m88110_fp_trap_status - { - union - { - struct - { - unsigned efinx:BIT_WIDTH(0); - unsigned efovf:BIT_WIDTH(1); - unsigned efunf:BIT_WIDTH(2); - unsigned efdvz:BIT_WIDTH(3); - unsigned efinv:BIT_WIDTH(4); - unsigned priv:BIT_WIDTH(5); - unsigned unimp:BIT_WIDTH(6); - unsigned int:BIT_WIDTH(7); - unsigned sfu1_disabled:BIT_WIDTH(8); - unsigned :BITS_WIDTH(13,9); - m88110_iresult_size_t iresult_size:BITS_WIDTH(15,14); - unsigned :BITS_WIDTH(31,16); - } fields; - uint32 word; - } u; - } sfps; - - if ( !mf ) - { - for ( i = 0; i < M88110_N_DATA_BP; i++ ) - { - spu->data_bp[i].addr = swap32(spu->data_bp[i].addr); - memcpy(&sbpc, &(spu->data_bp[i].ctrl), - sizeof(struct swapped_m88110_bp_ctrl)); - sbpc.u.word = swap32(sbpc.u.word); - spu->data_bp[i].ctrl.v = sbpc.u.fields.v; - spu->data_bp[i].ctrl.addr_match = sbpc.u.fields.addr_match; - spu->data_bp[i].ctrl.rwm = sbpc.u.fields.rwm; - spu->data_bp[i].ctrl.rw = sbpc.u.fields.rw; - } - - memcpy(&spsr, &(spu->psr), sizeof(struct swap_m88110_psr)); - spsr.u.word = swap32(spsr.u.word); - spu->psr.mxm_dis = spsr.u.fields.mxm_dis; - spu->psr.sfu1dis = spsr.u.fields.sfu1dis; - spu->psr.trace = spsr.u.fields.trace; - spu->psr.sm = spsr.u.fields.sm; - spu->psr.sgn_imd = spsr.u.fields.sgn_imd; - spu->psr.c = spsr.u.fields.c; - spu->psr.se = spsr.u.fields.se; - spu->psr.le = spsr.u.fields.le; - spu->psr.supr = spsr.u.fields.supr; - - memcpy(&sfps, &(spu->fp_trap_status), - sizeof(struct swapped_m88110_fp_trap_status)); - sfps.u.word = swap32(sfps.u.word); - spu->fp_trap_status.efinx = sfps.u.fields.efinx; - spu->fp_trap_status.efovf = sfps.u.fields.efovf; - spu->fp_trap_status.efunf = sfps.u.fields.efunf; - spu->fp_trap_status.efdvz = sfps.u.fields.efdvz; - spu->fp_trap_status.efinv = sfps.u.fields.efinv; - spu->fp_trap_status.priv = sfps.u.fields.priv; - spu->fp_trap_status.unimp = sfps.u.fields.unimp; - spu->fp_trap_status.sfu1_disabled = sfps.u.fields.sfu1_disabled; - spu->fp_trap_status.iresult_size = sfps.u.fields.iresult_size; - } - else - { - for ( i = 0; i < M88110_N_DATA_BP; i++ ) - { - spu->data_bp[i].addr = swap32(spu->data_bp[i].addr); - sbpc.u.fields.v = spu->data_bp[i].ctrl.v; - sbpc.u.fields.addr_match = spu->data_bp[i].ctrl.addr_match; - sbpc.u.fields.rwm = spu->data_bp[i].ctrl.rwm; - sbpc.u.fields.rw = spu->data_bp[i].ctrl.rw; - sbpc.u.word = swap32(sbpc.u.word); - memcpy(&(spu->data_bp[i].ctrl), &sbpc, - sizeof(struct swapped_m88110_bp_ctrl)); - } - - spsr.u.fields.mxm_dis = spu->psr.mxm_dis; - spsr.u.fields.sfu1dis = spu->psr.sfu1dis; - spsr.u.fields.trace = spu->psr.trace; - spsr.u.fields.sm = spu->psr.sm; - spsr.u.fields.sgn_imd = spu->psr.sgn_imd; - spsr.u.fields.c = spu->psr.c; - spsr.u.fields.se = spu->psr.se; - spsr.u.fields.le = spu->psr.le; - spsr.u.fields.supr = spu->psr.supr; - spsr.u.word = swap32(spsr.u.word); - memcpy(&(spu->psr), &spsr, sizeof(struct swap_m88110_psr)); - - sfps.u.fields.efinx = spu->fp_trap_status.efinx; - sfps.u.fields.efovf = spu->fp_trap_status.efovf; - sfps.u.fields.efunf = spu->fp_trap_status.efunf; - sfps.u.fields.efdvz = spu->fp_trap_status.efdvz; - sfps.u.fields.efinv = spu->fp_trap_status.efinv; - sfps.u.fields.priv = spu->fp_trap_status.priv; - sfps.u.fields.unimp = spu->fp_trap_status.unimp; - sfps.u.fields.sfu1_disabled = spu->fp_trap_status.sfu1_disabled; - sfps.u.fields.iresult_size = spu->fp_trap_status.iresult_size; - sfps.u.word = swap32(sfps.u.word); - memcpy(&(spu->fp_trap_status), &sfps, - sizeof(struct swapped_m88110_fp_trap_status)); - } - spu->intermediate_result.x[0] = - swap32(spu->intermediate_result.x[0]); - spu->intermediate_result.x[1] = - swap32(spu->intermediate_result.x[1]); - spu->intermediate_result.x[2] = - swap32(spu->intermediate_result.x[2]); - spu->intermediate_result.x[3] = - swap32(spu->intermediate_result.x[3]); -} - -//-------------------------------------------------------------------------- -static void swap_i860_thread_state_regs(struct i860_thread_state_regs *cpu) -{ - uint32 i; - - for ( i = 0; i < 31; i++ ) - cpu->ireg[i] = swap32(cpu->ireg[i]); - for ( i = 0; i < 30; i++ ) - cpu->freg[i] = swap32(cpu->freg[i]); - cpu->psr = swap32(cpu->psr); - cpu->epsr = swap32(cpu->epsr); - cpu->db = swap32(cpu->db); - cpu->pc = swap32(cpu->pc); - cpu->_padding_ = swap32(cpu->_padding_); - cpu->Mres3 = SWAP_DOUBLE(cpu->Mres3); - cpu->Ares3 = SWAP_DOUBLE(cpu->Ares3); - cpu->Mres2 = SWAP_DOUBLE(cpu->Mres2); - cpu->Ares2 = SWAP_DOUBLE(cpu->Ares2); - cpu->Mres1 = SWAP_DOUBLE(cpu->Mres1); - cpu->Ares1 = SWAP_DOUBLE(cpu->Ares1); - cpu->Ires1 = SWAP_DOUBLE(cpu->Ires1); - cpu->Lres3m = SWAP_DOUBLE(cpu->Lres3m); - cpu->Lres2m = SWAP_DOUBLE(cpu->Lres2m); - cpu->Lres1m = SWAP_DOUBLE(cpu->Lres1m); - cpu->KR = SWAP_DOUBLE(cpu->KR); - cpu->KI = SWAP_DOUBLE(cpu->KI); - cpu->T = SWAP_DOUBLE(cpu->T); - cpu->Fsr3 = swap32(cpu->Fsr3); - cpu->Fsr2 = swap32(cpu->Fsr2); - cpu->Fsr1 = swap32(cpu->Fsr1); - cpu->Mergelo32 = swap32(cpu->Mergelo32); - cpu->Mergehi32 = swap32(cpu->Mergehi32); -} -*/ - -#if defined(EFD_COMPILE) -//-------------------------------------------------------------------------- -static void swap_arm_thread_state(arm_thread_state_t *cpu) -{ - for ( int i = 0; i < 13; i++ ) - cpu->__r[i] = swap32(cpu->__r[i]); - cpu->__sp = swap32(cpu->__sp); - cpu->__lr = swap32(cpu->__lr); - cpu->__pc = swap32(cpu->__pc); - cpu->__cpsr = swap32(cpu->__cpsr); -} - -//-------------------------------------------------------------------------- -static void swap_arm_thread_state64(arm_thread_state64_t *cpu) -{ - for ( int i = 0; i < 29; i++ ) - cpu->__x[i] = swap64(cpu->__x[i]); - cpu->__fp = swap64(cpu->__fp); - cpu->__lr = swap64(cpu->__lr); - cpu->__sp = swap64(cpu->__sp); - cpu->__pc = swap64(cpu->__pc); - cpu->__cpsr = swap32(cpu->__cpsr); -} - -//-------------------------------------------------------------------------- -static void swap_i386_thread_state(i386_thread_state_t *cpu) -{ - cpu->__eax = swap32(cpu->__eax); - cpu->__ebx = swap32(cpu->__ebx); - cpu->__ecx = swap32(cpu->__ecx); - cpu->__edx = swap32(cpu->__edx); - cpu->__edi = swap32(cpu->__edi); - cpu->__esi = swap32(cpu->__esi); - cpu->__ebp = swap32(cpu->__ebp); - cpu->__esp = swap32(cpu->__esp); - cpu->__ss = swap32(cpu->__ss); - cpu->__eflags = swap32(cpu->__eflags); - cpu->__eip = swap32(cpu->__eip); - cpu->__cs = swap32(cpu->__cs); - cpu->__ds = swap32(cpu->__ds); - cpu->__es = swap32(cpu->__es); - cpu->__fs = swap32(cpu->__fs); - cpu->__gs = swap32(cpu->__gs); -} - -//-------------------------------------------------------------------------- -static void swap_x86_thread_state64(x86_thread_state64_t *cpu) -{ - cpu->__rax = swap64(cpu->__rax); - cpu->__rbx = swap64(cpu->__rbx); - cpu->__rcx = swap64(cpu->__rcx); - cpu->__rdx = swap64(cpu->__rdx); - cpu->__rdi = swap64(cpu->__rdi); - cpu->__rsi = swap64(cpu->__rsi); - cpu->__rbp = swap64(cpu->__rbp); - cpu->__rsp = swap64(cpu->__rsp); - cpu->__rflags = swap64(cpu->__rflags); - cpu->__rip = swap64(cpu->__rip); - cpu->__r8 = swap64(cpu->__r8); - cpu->__r9 = swap64(cpu->__r9); - cpu->__r10 = swap64(cpu->__r10); - cpu->__r11 = swap64(cpu->__r11); - cpu->__r12 = swap64(cpu->__r12); - cpu->__r13 = swap64(cpu->__r13); - cpu->__r14 = swap64(cpu->__r14); - cpu->__r15 = swap64(cpu->__r15); - cpu->__cs = swap64(cpu->__cs); - cpu->__fs = swap64(cpu->__fs); - cpu->__gs = swap64(cpu->__gs); -} -#endif - -//-------------------------------------------------------------------------- -#if 0 // !defined(EFD_COMPILE) && !defined(LOADER_COMPILE) -static void swap_x86_state_hdr(x86_state_hdr_t *hdr) -{ - hdr->flavor = swap32(hdr->flavor); - hdr->count = swap32(hdr->count); -} - -//-------------------------------------------------------------------------- -static void swap_x86_float_state64(x86_float_state64_t *fpu) -{ - struct swapped_fp_control - { - union - { - struct - { - unsigned short - :3, - /*inf*/ :1, - rc :2, - pc :2, - :2, - precis :1, - undfl :1, - ovrfl :1, - zdiv :1, - denorm :1, - invalid :1; - } fields; - unsigned short half; - } u; - } sfpc; - - struct swapped_fp_status - { - union - { - struct - { - unsigned short - busy :1, - c3 :1, - tos :3, - c2 :1, - c1 :1, - c0 :1, - errsumm :1, - stkflt :1, - precis :1, - undfl :1, - ovrfl :1, - zdiv :1, - denorm :1, - invalid :1; - } fields; - unsigned short half; - } u; - } sfps; - - fpu->__fpu_reserved[0] = swap32(fpu->__fpu_reserved[0]); - fpu->__fpu_reserved[1] = swap32(fpu->__fpu_reserved[1]); - - if ( !mf ) - { - memcpy(&sfpc, &(fpu->__fpu_fcw), - sizeof(struct swapped_fp_control)); - sfpc.u.half = swap16(sfpc.u.half); - fpu->__fpu_fcw.__rc = sfpc.u.fields.rc; - fpu->__fpu_fcw.__pc = sfpc.u.fields.pc; - fpu->__fpu_fcw.__precis = sfpc.u.fields.precis; - fpu->__fpu_fcw.__undfl = sfpc.u.fields.undfl; - fpu->__fpu_fcw.__ovrfl = sfpc.u.fields.ovrfl; - fpu->__fpu_fcw.__zdiv = sfpc.u.fields.zdiv; - fpu->__fpu_fcw.__denorm = sfpc.u.fields.denorm; - fpu->__fpu_fcw.__invalid = sfpc.u.fields.invalid; - - memcpy(&sfps, &(fpu->__fpu_fsw), - sizeof(struct swapped_fp_status)); - sfps.u.half = swap16(sfps.u.half); - fpu->__fpu_fsw.__busy = sfps.u.fields.busy; - fpu->__fpu_fsw.__c3 = sfps.u.fields.c3; - fpu->__fpu_fsw.__tos = sfps.u.fields.tos; - fpu->__fpu_fsw.__c2 = sfps.u.fields.c2; - fpu->__fpu_fsw.__c1 = sfps.u.fields.c1; - fpu->__fpu_fsw.__c0 = sfps.u.fields.c0; - fpu->__fpu_fsw.__errsumm = sfps.u.fields.errsumm; - fpu->__fpu_fsw.__stkflt = sfps.u.fields.stkflt; - fpu->__fpu_fsw.__precis = sfps.u.fields.precis; - fpu->__fpu_fsw.__undfl = sfps.u.fields.undfl; - fpu->__fpu_fsw.__ovrfl = sfps.u.fields.ovrfl; - fpu->__fpu_fsw.__zdiv = sfps.u.fields.zdiv; - fpu->__fpu_fsw.__denorm = sfps.u.fields.denorm; - fpu->__fpu_fsw.__invalid = sfps.u.fields.invalid; - } - else - { - sfpc.u.fields.rc = fpu->__fpu_fcw.__rc; - sfpc.u.fields.pc = fpu->__fpu_fcw.__pc; - sfpc.u.fields.precis = fpu->__fpu_fcw.__precis; - sfpc.u.fields.undfl = fpu->__fpu_fcw.__undfl; - sfpc.u.fields.ovrfl = fpu->__fpu_fcw.__ovrfl; - sfpc.u.fields.zdiv = fpu->__fpu_fcw.__zdiv; - sfpc.u.fields.denorm = fpu->__fpu_fcw.__denorm; - sfpc.u.fields.invalid = fpu->__fpu_fcw.__invalid; - sfpc.u.half = swap16(sfpc.u.half); - memcpy(&(fpu->__fpu_fcw), &sfpc, - sizeof(struct swapped_fp_control)); - - sfps.u.fields.busy = fpu->__fpu_fsw.__busy; - sfps.u.fields.c3 = fpu->__fpu_fsw.__c3; - sfps.u.fields.tos = fpu->__fpu_fsw.__tos; - sfps.u.fields.c2 = fpu->__fpu_fsw.__c2; - sfps.u.fields.c1 = fpu->__fpu_fsw.__c1; - sfps.u.fields.c0 = fpu->__fpu_fsw.__c0; - sfps.u.fields.errsumm = fpu->__fpu_fsw.__errsumm; - sfps.u.fields.stkflt = fpu->__fpu_fsw.__stkflt; - sfps.u.fields.precis = fpu->__fpu_fsw.__precis; - sfps.u.fields.undfl = fpu->__fpu_fsw.__undfl; - sfps.u.fields.ovrfl = fpu->__fpu_fsw.__ovrfl; - sfps.u.fields.zdiv = fpu->__fpu_fsw.__zdiv; - sfps.u.fields.denorm = fpu->__fpu_fsw.__denorm; - sfps.u.fields.invalid = fpu->__fpu_fsw.__invalid; - sfps.u.half = swap16(sfps.u.half); - memcpy(&(fpu->__fpu_fsw), &sfps, - sizeof(struct swapped_fp_status)); - } - fpu->__fpu_fop = swap16(fpu->__fpu_fop); - fpu->__fpu_ip = swap32(fpu->__fpu_ip); - fpu->__fpu_cs = swap16(fpu->__fpu_cs); - fpu->__fpu_rsrv2 = swap16(fpu->__fpu_rsrv2); - fpu->__fpu_dp = swap32(fpu->__fpu_dp); - fpu->__fpu_ds = swap16(fpu->__fpu_ds); - fpu->__fpu_rsrv3 = swap16(fpu->__fpu_rsrv3); - fpu->__fpu_mxcsr = swap32(fpu->__fpu_mxcsr); - fpu->__fpu_mxcsrmask = swap32(fpu->__fpu_mxcsrmask); - fpu->__fpu_reserved1 = swap32(fpu->__fpu_reserved1); -} - -//-------------------------------------------------------------------------- -static void swap_x86_exception_state64(x86_exception_state64_t *exc) -{ - exc->__trapno = swap32(exc->__trapno); - exc->__err = swap32(exc->__err); - exc->__faultvaddr = swap64(exc->__faultvaddr); -} - -//-------------------------------------------------------------------------- -static void swap_x86_debug_state32(x86_debug_state32_t *debug) -{ - debug->__dr0 = swap32(debug->__dr0); - debug->__dr1 = swap32(debug->__dr1); - debug->__dr2 = swap32(debug->__dr2); - debug->__dr3 = swap32(debug->__dr3); - debug->__dr4 = swap32(debug->__dr4); - debug->__dr5 = swap32(debug->__dr5); - debug->__dr6 = swap32(debug->__dr6); - debug->__dr7 = swap32(debug->__dr7); -} - -//-------------------------------------------------------------------------- -static void swap_x86_debug_state64(x86_debug_state64_t *debug) -{ - debug->__dr0 = swap64(debug->__dr0); - debug->__dr1 = swap64(debug->__dr1); - debug->__dr2 = swap64(debug->__dr2); - debug->__dr3 = swap64(debug->__dr3); - debug->__dr4 = swap64(debug->__dr4); - debug->__dr5 = swap64(debug->__dr5); - debug->__dr6 = swap64(debug->__dr6); - debug->__dr7 = swap64(debug->__dr7); -} -#endif // !EFD_COMPILE && !LOADER_COMPILE - -/* current i386 thread states */ -#if i386_THREAD_STATE == 1 -void swap_i386_float_state(i386_float_state_t *fpu) -{ -#ifndef i386_EXCEPTION_STATE_COUNT - /* this routine does nothing as their are currently no non-byte fields */ -#else /* !defined(i386_EXCEPTION_STATE_COUNT) */ - struct swapped_fp_control - { - union - { - struct - { - unsigned short - :3, - /*inf*/ :1, - rc :2, - pc :2, - :2, - precis :1, - undfl :1, - ovrfl :1, - zdiv :1, - denorm :1, - invalid :1; - } fields; - unsigned short half; - } u; - } sfpc; - - struct swapped_fp_status - { - union - { - struct - { - unsigned short - busy :1, - c3 :1, - tos :3, - c2 :1, - c1 :1, - c0 :1, - errsumm :1, - stkflt :1, - precis :1, - undfl :1, - ovrfl :1, - zdiv :1, - denorm :1, - invalid :1; - } fields; - unsigned short half; - } u; - } sfps; - -// enum NXByteOrder host_byte_sex; - - fpu->__fpu_reserved[0] = swap32(fpu->__fpu_reserved[0]); - fpu->__fpu_reserved[1] = swap32(fpu->__fpu_reserved[1]); - - sfpc.u.fields.rc = fpu->__fpu_fcw.__rc; - sfpc.u.fields.pc = fpu->__fpu_fcw.__pc; - sfpc.u.fields.precis = fpu->__fpu_fcw.__precis; - sfpc.u.fields.undfl = fpu->__fpu_fcw.__undfl; - sfpc.u.fields.ovrfl = fpu->__fpu_fcw.__ovrfl; - sfpc.u.fields.zdiv = fpu->__fpu_fcw.__zdiv; - sfpc.u.fields.denorm = fpu->__fpu_fcw.__denorm; - sfpc.u.fields.invalid = fpu->__fpu_fcw.__invalid; - sfpc.u.half = swap16(sfpc.u.half); - memcpy(&(fpu->__fpu_fcw), &sfpc, sizeof(struct swapped_fp_control)); //-V512 A call of the 'memcpy' function will lead to underflow of the buffer - - sfps.u.fields.busy = fpu->__fpu_fsw.__busy; - sfps.u.fields.c3 = fpu->__fpu_fsw.__c3; - sfps.u.fields.tos = fpu->__fpu_fsw.__tos; - sfps.u.fields.c2 = fpu->__fpu_fsw.__c2; - sfps.u.fields.c1 = fpu->__fpu_fsw.__c1; - sfps.u.fields.c0 = fpu->__fpu_fsw.__c0; - sfps.u.fields.errsumm = fpu->__fpu_fsw.__errsumm; - sfps.u.fields.stkflt = fpu->__fpu_fsw.__stkflt; - sfps.u.fields.precis = fpu->__fpu_fsw.__precis; - sfps.u.fields.undfl = fpu->__fpu_fsw.__undfl; - sfps.u.fields.ovrfl = fpu->__fpu_fsw.__ovrfl; - sfps.u.fields.zdiv = fpu->__fpu_fsw.__zdiv; - sfps.u.fields.denorm = fpu->__fpu_fsw.__denorm; - sfps.u.fields.invalid = fpu->__fpu_fsw.__invalid; - sfps.u.half = swap16(sfps.u.half); - memcpy(&(fpu->__fpu_fsw), &sfps, sizeof(struct swapped_fp_status)); - - fpu->__fpu_fop = swap16(fpu->__fpu_fop); - fpu->__fpu_ip = swap32(fpu->__fpu_ip); - fpu->__fpu_cs = swap16(fpu->__fpu_cs); - fpu->__fpu_rsrv2 = swap16(fpu->__fpu_rsrv2); - fpu->__fpu_dp = swap32(fpu->__fpu_dp); - fpu->__fpu_ds = swap16(fpu->__fpu_ds); - fpu->__fpu_rsrv3 = swap16(fpu->__fpu_rsrv3); - fpu->__fpu_mxcsr = swap32(fpu->__fpu_mxcsr); - fpu->__fpu_mxcsrmask = swap32(fpu->__fpu_mxcsrmask); - fpu->__fpu_reserved1 = swap32(fpu->__fpu_reserved1); - -#endif /* !defined(i386_EXCEPTION_STATE_COUNT) */ -} - -void swap_i386_exception_state(i386_exception_state_t *exc) -{ - exc->__trapno = swap32(exc->__trapno); - exc->__err = swap32(exc->__err); - exc->__faultvaddr = swap32(exc->__faultvaddr); -} -#endif /* i386_THREAD_STATE == 1 */ - -//-------------------------------------------------------------------------- -/* -static void swap_hppa_integer_thread_state(struct hp_pa_integer_thread_state *regs) -{ - regs->ts_gr1 = swap32(regs->ts_gr1); - regs->ts_gr2 = swap32(regs->ts_gr2); - regs->ts_gr3 = swap32(regs->ts_gr3); - regs->ts_gr4 = swap32(regs->ts_gr4); - regs->ts_gr5 = swap32(regs->ts_gr5); - regs->ts_gr6 = swap32(regs->ts_gr6); - regs->ts_gr7 = swap32(regs->ts_gr7); - regs->ts_gr8 = swap32(regs->ts_gr8); - regs->ts_gr9 = swap32(regs->ts_gr9); - regs->ts_gr10 = swap32(regs->ts_gr10); - regs->ts_gr11 = swap32(regs->ts_gr11); - regs->ts_gr12 = swap32(regs->ts_gr12); - regs->ts_gr13 = swap32(regs->ts_gr13); - regs->ts_gr14 = swap32(regs->ts_gr14); - regs->ts_gr15 = swap32(regs->ts_gr15); - regs->ts_gr16 = swap32(regs->ts_gr16); - regs->ts_gr17 = swap32(regs->ts_gr17); - regs->ts_gr18 = swap32(regs->ts_gr18); - regs->ts_gr19 = swap32(regs->ts_gr19); - regs->ts_gr20 = swap32(regs->ts_gr20); - regs->ts_gr21 = swap32(regs->ts_gr21); - regs->ts_gr22 = swap32(regs->ts_gr22); - regs->ts_gr23 = swap32(regs->ts_gr23); - regs->ts_gr24 = swap32(regs->ts_gr24); - regs->ts_gr25 = swap32(regs->ts_gr25); - regs->ts_gr26 = swap32(regs->ts_gr26); - regs->ts_gr27 = swap32(regs->ts_gr27); - regs->ts_gr28 = swap32(regs->ts_gr28); - regs->ts_gr29 = swap32(regs->ts_gr29); - regs->ts_gr30 = swap32(regs->ts_gr30); - regs->ts_gr31 = swap32(regs->ts_gr31); - regs->ts_sr0 = swap32(regs->ts_sr0); - regs->ts_sr1 = swap32(regs->ts_sr1); - regs->ts_sr2 = swap32(regs->ts_sr2); - regs->ts_sr3 = swap32(regs->ts_sr3); - regs->ts_sar = swap32(regs->ts_sar); -} - -//-------------------------------------------------------------------------- -static void swap_hppa_frame_thread_state( struct hp_pa_frame_thread_state *frame) -{ - frame->ts_pcsq_front = swap32(frame->ts_pcsq_front); - frame->ts_pcsq_back = swap32(frame->ts_pcsq_back); - frame->ts_pcoq_front = swap32(frame->ts_pcoq_front); - frame->ts_pcoq_back = swap32(frame->ts_pcoq_back); - frame->ts_psw = swap32(frame->ts_psw); - frame->ts_unaligned_faults = swap32(frame->ts_unaligned_faults); - frame->ts_fault_address = swap32(frame->ts_fault_address); - frame->ts_step_range_start = swap32(frame->ts_step_range_start); - frame->ts_step_range_stop = swap32(frame->ts_step_range_stop); -} - -//-------------------------------------------------------------------------- -static void swap_hppa_fp_thread_state( struct hp_pa_fp_thread_state *fp) -{ - fp->ts_fp0 = SWAP_DOUBLE(fp->ts_fp0); - fp->ts_fp1 = SWAP_DOUBLE(fp->ts_fp1); - fp->ts_fp2 = SWAP_DOUBLE(fp->ts_fp2); - fp->ts_fp3 = SWAP_DOUBLE(fp->ts_fp3); - fp->ts_fp4 = SWAP_DOUBLE(fp->ts_fp4); - fp->ts_fp5 = SWAP_DOUBLE(fp->ts_fp5); - fp->ts_fp6 = SWAP_DOUBLE(fp->ts_fp6); - fp->ts_fp7 = SWAP_DOUBLE(fp->ts_fp7); - fp->ts_fp8 = SWAP_DOUBLE(fp->ts_fp8); - fp->ts_fp9 = SWAP_DOUBLE(fp->ts_fp9); - fp->ts_fp10 = SWAP_DOUBLE(fp->ts_fp10); - fp->ts_fp11 = SWAP_DOUBLE(fp->ts_fp11); - fp->ts_fp12 = SWAP_DOUBLE(fp->ts_fp12); - fp->ts_fp13 = SWAP_DOUBLE(fp->ts_fp13); - fp->ts_fp14 = SWAP_DOUBLE(fp->ts_fp14); - fp->ts_fp15 = SWAP_DOUBLE(fp->ts_fp15); - fp->ts_fp16 = SWAP_DOUBLE(fp->ts_fp16); - fp->ts_fp17 = SWAP_DOUBLE(fp->ts_fp17); - fp->ts_fp18 = SWAP_DOUBLE(fp->ts_fp18); - fp->ts_fp19 = SWAP_DOUBLE(fp->ts_fp19); - fp->ts_fp20 = SWAP_DOUBLE(fp->ts_fp20); - fp->ts_fp21 = SWAP_DOUBLE(fp->ts_fp21); - fp->ts_fp22 = SWAP_DOUBLE(fp->ts_fp22); - fp->ts_fp23 = SWAP_DOUBLE(fp->ts_fp23); - fp->ts_fp24 = SWAP_DOUBLE(fp->ts_fp24); - fp->ts_fp25 = SWAP_DOUBLE(fp->ts_fp25); - fp->ts_fp26 = SWAP_DOUBLE(fp->ts_fp26); - fp->ts_fp27 = SWAP_DOUBLE(fp->ts_fp27); - fp->ts_fp28 = SWAP_DOUBLE(fp->ts_fp28); - fp->ts_fp29 = SWAP_DOUBLE(fp->ts_fp29); - fp->ts_fp30 = SWAP_DOUBLE(fp->ts_fp30); - fp->ts_fp31 = SWAP_DOUBLE(fp->ts_fp31); -} - -//-------------------------------------------------------------------------- -static void swap_sparc_thread_state_regs(struct sparc_thread_state_regs *cpu) -{ - struct swapped_psr - { - union - { - struct - { - unsigned int - cwp:BITS_WIDTH(4,0), - et:BIT_WIDTH(5), - ps:BIT_WIDTH(6), - s:BIT_WIDTH(7), - pil:BITS_WIDTH(11,8), - ef:BIT_WIDTH(12), - ec:BIT_WIDTH(13), - reserved:BITS_WIDTH(19,14), - icc:BITS_WIDTH(23,20), - ver:BITS_WIDTH(27,24), - impl:BITS_WIDTH(31,28); - } fields; - unsigned int word; - } u; - } spsr; - struct p_status *pr_status; - - cpu->regs.r_pc = swap32(cpu->regs.r_pc); - cpu->regs.r_npc = swap32(cpu->regs.r_npc); - cpu->regs.r_y = swap32(cpu->regs.r_y); - cpu->regs.r_g1 = swap32(cpu->regs.r_g1); - cpu->regs.r_g2 = swap32(cpu->regs.r_g2); - cpu->regs.r_g3 = swap32(cpu->regs.r_g3); - cpu->regs.r_g4 = swap32(cpu->regs.r_g4); - cpu->regs.r_g5 = swap32(cpu->regs.r_g5); - cpu->regs.r_g6 = swap32(cpu->regs.r_g6); - cpu->regs.r_g7 = swap32(cpu->regs.r_g7); - cpu->regs.r_o0 = swap32(cpu->regs.r_o0); - cpu->regs.r_o1 = swap32(cpu->regs.r_o1); - cpu->regs.r_o2 = swap32(cpu->regs.r_o2); - cpu->regs.r_o3 = swap32(cpu->regs.r_o3); - cpu->regs.r_o4 = swap32(cpu->regs.r_o4); - cpu->regs.r_o5 = swap32(cpu->regs.r_o5); - cpu->regs.r_o6 = swap32(cpu->regs.r_o6); - cpu->regs.r_o7 = swap32(cpu->regs.r_o7); - - pr_status = (struct p_status *) &(cpu->regs.r_psr); - if ( !mf ) - { - memcpy(&spsr, &(cpu->regs.r_psr), sizeof(struct swapped_psr)); - spsr.u.word = swap32(spsr.u.word); - pr_status->PSRREG.psr_bits.cwp = spsr.u.fields.cwp; - pr_status->PSRREG.psr_bits.ps = spsr.u.fields.ps; - pr_status->PSRREG.psr_bits.s = spsr.u.fields.s; - pr_status->PSRREG.psr_bits.pil = spsr.u.fields.pil; - pr_status->PSRREG.psr_bits.ef = spsr.u.fields.ef; - pr_status->PSRREG.psr_bits.ec = spsr.u.fields.ec; - pr_status->PSRREG.psr_bits.reserved = spsr.u.fields.reserved; - pr_status->PSRREG.psr_bits.icc = spsr.u.fields.icc; - pr_status->PSRREG.psr_bits.et = spsr.u.fields.ver; - pr_status->PSRREG.psr_bits.impl = spsr.u.fields.impl; - } - else - { - spsr.u.fields.cwp = pr_status->PSRREG.psr_bits.cwp; - spsr.u.fields.ps = pr_status->PSRREG.psr_bits.ps; - spsr.u.fields.s = pr_status->PSRREG.psr_bits.s; - spsr.u.fields.pil = pr_status->PSRREG.psr_bits.pil; - spsr.u.fields.ef = pr_status->PSRREG.psr_bits.ef; - spsr.u.fields.ec = pr_status->PSRREG.psr_bits.ec; - spsr.u.fields.reserved = pr_status->PSRREG.psr_bits.reserved; - spsr.u.fields.icc = pr_status->PSRREG.psr_bits.icc; - spsr.u.fields.ver = pr_status->PSRREG.psr_bits.et; - spsr.u.fields.impl = pr_status->PSRREG.psr_bits.impl; - spsr.u.word = swap32(spsr.u.word); - memcpy(&(cpu->regs.r_psr), &spsr, sizeof(struct swapped_psr)); - } -} - -//-------------------------------------------------------------------------- -static void swap_sparc_thread_state_fpu(struct sparc_thread_state_fpu *fpu) -{ - struct swapped_fsr - { - union - { - struct - { - unsigned int - cexc:BITS_WIDTH(4,0), - aexc:BITS_WIDTH(9,5), - fcc:BITS_WIDTH(11,10), - pr:BIT_WIDTH(12), - qne:BIT_WIDTH(13), - ftt:BITS_WIDTH(16,14), - res:BITS_WIDTH(22,17), - tem:BITS_WIDTH(27,23), - rp:BITS_WIDTH(29,28), - rd:BITS_WIDTH(31,30); - } fields; - unsigned int word; - } u; - } sfsr; - uint32 i; - struct f_status *fpu_status; - - // floating point registers - for ( i = 0; i < 16; i++ ) // 16 doubles - fpu->fpu.fpu_fr.Fpu_dregs[i] = SWAP_DOUBLE(fpu->fpu.fpu_fr.Fpu_dregs[i]); - - fpu->fpu.Fpu_q[0].FQu.whole = SWAP_DOUBLE(fpu->fpu.Fpu_q[0].FQu.whole); - fpu->fpu.Fpu_q[1].FQu.whole = SWAP_DOUBLE(fpu->fpu.Fpu_q[1].FQu.whole); - fpu->fpu.Fpu_flags = swap32(fpu->fpu.Fpu_flags); - fpu->fpu.Fpu_extra = swap32(fpu->fpu.Fpu_extra); - fpu->fpu.Fpu_qcnt = swap32(fpu->fpu.Fpu_qcnt); - - fpu_status = (struct f_status *) &(fpu->fpu.Fpu_fsr); - if ( !mf ) - { - memcpy(&sfsr, &(fpu->fpu.Fpu_fsr), sizeof(unsigned int)); - sfsr.u.word = swap32(sfsr.u.word); - fpu_status->FPUREG.Fpu_fsr_bits.rd = sfsr.u.fields.rd; - fpu_status->FPUREG.Fpu_fsr_bits.rp = sfsr.u.fields.rp; - fpu_status->FPUREG.Fpu_fsr_bits.tem = sfsr.u.fields.tem; - fpu_status->FPUREG.Fpu_fsr_bits.res = sfsr.u.fields.res; - fpu_status->FPUREG.Fpu_fsr_bits.ftt = sfsr.u.fields.ftt; - fpu_status->FPUREG.Fpu_fsr_bits.qne = sfsr.u.fields.qne; - fpu_status->FPUREG.Fpu_fsr_bits.pr = sfsr.u.fields.pr; - fpu_status->FPUREG.Fpu_fsr_bits.fcc = sfsr.u.fields.fcc; - fpu_status->FPUREG.Fpu_fsr_bits.aexc = sfsr.u.fields.aexc; - fpu_status->FPUREG.Fpu_fsr_bits.cexc = sfsr.u.fields.cexc; - } - else - { - sfsr.u.fields.rd = fpu_status->FPUREG.Fpu_fsr_bits.rd; - sfsr.u.fields.rp = fpu_status->FPUREG.Fpu_fsr_bits.rp; - sfsr.u.fields.tem = fpu_status->FPUREG.Fpu_fsr_bits.tem; - sfsr.u.fields.res = fpu_status->FPUREG.Fpu_fsr_bits.res; - sfsr.u.fields.ftt = fpu_status->FPUREG.Fpu_fsr_bits.ftt; - sfsr.u.fields.qne = fpu_status->FPUREG.Fpu_fsr_bits.qne; - sfsr.u.fields.pr = fpu_status->FPUREG.Fpu_fsr_bits.pr; - sfsr.u.fields.fcc = fpu_status->FPUREG.Fpu_fsr_bits.fcc; - sfsr.u.fields.aexc = fpu_status->FPUREG.Fpu_fsr_bits.aexc; - sfsr.u.fields.cexc = fpu_status->FPUREG.Fpu_fsr_bits.cexc; - sfsr.u.word = swap32(sfsr.u.word); - memcpy(&(fpu->fpu.Fpu_fsr), &sfsr, sizeof(struct swapped_fsr)); - } -} -*/ -//-------------------------------------------------------------------------- -static void swap_ident_command(struct ident_command *id_cmd) -{ - id_cmd->cmd = swap32(id_cmd->cmd); - id_cmd->cmdsize = swap32(id_cmd->cmdsize); -} - -//-------------------------------------------------------------------------- -static void swap_routines_command(struct routines_command *r_cmd) -{ - r_cmd->cmd = swap32(r_cmd->cmd); - r_cmd->cmdsize = swap32(r_cmd->cmdsize); - r_cmd->init_address = swap32(r_cmd->init_address); - r_cmd->init_module = swap32(r_cmd->init_module); - r_cmd->reserved1 = swap32(r_cmd->reserved1); - r_cmd->reserved2 = swap32(r_cmd->reserved2); - r_cmd->reserved3 = swap32(r_cmd->reserved3); - r_cmd->reserved4 = swap32(r_cmd->reserved4); - r_cmd->reserved5 = swap32(r_cmd->reserved5); - r_cmd->reserved6 = swap32(r_cmd->reserved6); -} - -//-------------------------------------------------------------------------- -static void swap_routines_command_64(struct routines_command_64 *r_cmd) -{ - r_cmd->cmd = swap32(r_cmd->cmd); - r_cmd->cmdsize = swap32(r_cmd->cmdsize); - r_cmd->init_address = swap64(r_cmd->init_address); - r_cmd->init_module = swap64(r_cmd->init_module); - r_cmd->reserved1 = swap64(r_cmd->reserved1); - r_cmd->reserved2 = swap64(r_cmd->reserved2); - r_cmd->reserved3 = swap64(r_cmd->reserved3); - r_cmd->reserved4 = swap64(r_cmd->reserved4); - r_cmd->reserved5 = swap64(r_cmd->reserved5); - r_cmd->reserved6 = swap64(r_cmd->reserved6); -} -//-------------------------------------------------------------------------- -static void swap_twolevel_hints_command(twolevel_hints_command *hints_cmd) -{ - hints_cmd->cmd = swap32(hints_cmd->cmd); - hints_cmd->cmdsize = swap32(hints_cmd->cmdsize); - hints_cmd->offset = swap32(hints_cmd->offset); - hints_cmd->nhints = swap32(hints_cmd->nhints); -} - -//-------------------------------------------------------------------------- -static void swap_prebind_cksum_command(prebind_cksum_command *cksum_cmd) -{ - cksum_cmd->cmd = swap32(cksum_cmd->cmd); - cksum_cmd->cmdsize = swap32(cksum_cmd->cmdsize); - cksum_cmd->cksum = swap32(cksum_cmd->cksum); -} - - -//---------------------------------------------------------------------- -static void swap_uuid_command(struct uuid_command *uuid_cmd) -{ - uuid_cmd->cmd = swap32(uuid_cmd->cmd); - uuid_cmd->cmdsize = swap32(uuid_cmd->cmdsize); -} - -//-------------------------------------------------------------------------- -static void swap_linkedit_data_command(struct linkedit_data_command *ld) -{ - ld->cmd = swap32(ld->cmd); - ld->cmdsize = swap32(ld->cmdsize); - ld->dataoff = swap32(ld->dataoff); - ld->datasize = swap32(ld->datasize); -} - -//-------------------------------------------------------------------------- -static void swap_entry_point_command(struct entry_point_command *ep) -{ - ep->cmd = swap32(ep->cmd); - ep->cmdsize = swap32(ep->cmdsize); - ep->entryoff = swap64(ep->entryoff); - ep->stacksize = swap64(ep->stacksize); -} - -//-------------------------------------------------------------------------- -static void swap_source_version_command(struct source_version_command *sv) -{ - sv->cmd = swap32(sv->cmd); - sv->cmdsize = swap32(sv->cmdsize); - sv->version = swap64(sv->version); -} - -//-------------------------------------------------------------------------- -static void swap_rpath_command(struct rpath_command *rpath_cmd) -{ - rpath_cmd->cmd = swap32(rpath_cmd->cmd); - rpath_cmd->cmdsize = swap32(rpath_cmd->cmdsize); - rpath_cmd->path.offset = swap32(rpath_cmd->path.offset); -} - -//-------------------------------------------------------------------------- -static void swap_encryption_info_command(struct encryption_info_command *ec) -{ - ec->cmd = swap32(ec->cmd); - ec->cmdsize = swap32(ec->cmdsize); - ec->cryptoff = swap32(ec->cryptoff); - ec->cryptsize = swap32(ec->cryptsize); - ec->cryptid = swap32(ec->cryptid); -} - -//-------------------------------------------------------------------------- -static void swap_encryption_info_command_64(struct encryption_info_command_64 *ec) -{ - ec->cmd = swap32(ec->cmd); - ec->cmdsize = swap32(ec->cmdsize); - ec->cryptoff = swap32(ec->cryptoff); - ec->cryptsize = swap32(ec->cryptsize); - ec->cryptid = swap32(ec->cryptid); - ec->pad = swap32(ec->pad); -} -//-------------------------------------------------------------------------- -static void swap_dyld_info_command(struct dyld_info_command *ed) -{ - ed->cmd = swap32(ed->cmd); - ed->cmdsize = swap32(ed->cmdsize); - ed->rebase_off = swap32(ed->rebase_off); - ed->rebase_size = swap32(ed->rebase_size); - ed->bind_off = swap32(ed->bind_off); - ed->bind_size = swap32(ed->bind_size); - ed->weak_bind_off = swap32(ed->weak_bind_off); - ed->weak_bind_size = swap32(ed->weak_bind_size); - ed->lazy_bind_off = swap32(ed->lazy_bind_off); - ed->lazy_bind_size = swap32(ed->lazy_bind_size); - ed->export_off = swap32(ed->export_off); - ed->export_size = swap32(ed->export_size); -} - -//-------------------------------------------------------------------------- -static void swap_version_min_command(struct version_min_command *ec) -{ - ec->cmd = swap32(ec->cmd); - ec->cmdsize = swap32(ec->cmdsize); - ec->version = swap32(ec->version); - ec->sdk = swap32(ec->sdk); -} - -//-------------------------------------------------------------------------- -static void swap_build_version_command(struct build_version_command *bv) -{ - bv->cmd = swap32(bv->cmd); - bv->platform = swap32(bv->platform); - bv->minos = swap32(bv->minos); - bv->sdk = swap32(bv->sdk); - bv->ntools = swap32(bv->ntools); -} - -//-------------------------------------------------------------------------- -static void swap_build_tool_version(struct build_tool_version *bt) -{ - bt->tool = swap32(bt->tool); - bt->version = swap32(bt->version); -} - -//-------------------------------------------------------------------------- -static void swap_nlist_64(struct nlist_64 *symbols_from, struct nlist_64 *symbols_to, uint32 nsymbols) -{ - uint32 i; - for ( i = 0; i < nsymbols; i++ ) - { - symbols_to[i].n_un.n_strx = swap32(symbols_from[i].n_un.n_strx); - if ( symbols_to != symbols_from ) - { - symbols_to[i].n_type = symbols_from[i].n_type; - symbols_to[i].n_sect = symbols_from[i].n_sect; - } - symbols_to[i].n_desc = swap16(symbols_from[i].n_desc); - symbols_to[i].n_value = swap64(symbols_from[i].n_value); - } -} - -//-------------------------------------------------------------------------- -static void nlist_to64( - const struct nlist *symbols_from, - struct nlist_64 *symbols_to, - size_t nsymbols, - bool swap) -{ - if ( swap ) - { - for ( size_t i = 0; i < nsymbols; i++ ) - { - symbols_to[i].n_un.n_strx = swap32(symbols_from[i].n_un.n_strx); - symbols_to[i].n_type = symbols_from[i].n_type; - symbols_to[i].n_sect = symbols_from[i].n_sect; - symbols_to[i].n_desc = swap16(symbols_from[i].n_desc); - symbols_to[i].n_value = swap32(symbols_from[i].n_value); - } - } - else - { - for ( size_t i = 0; i < nsymbols; i++ ) - { - symbols_to[i].n_un.n_strx = symbols_from[i].n_un.n_strx; - symbols_to[i].n_type = symbols_from[i].n_type; - symbols_to[i].n_sect = symbols_from[i].n_sect; - symbols_to[i].n_desc = symbols_from[i].n_desc; - symbols_to[i].n_value = symbols_from[i].n_value; - } - } -} - -//-------------------------------------------------------------------------- -static void swap_dylib_module_64(struct dylib_module_64 *mods, uint32 nmods) -{ - uint32 i; - for ( i = 0; i < nmods; i++ ) - { - mods[i].module_name = swap32(mods[i].module_name); - mods[i].iextdefsym = swap32(mods[i].iextdefsym); - mods[i].nextdefsym = swap32(mods[i].nextdefsym); - mods[i].irefsym = swap32(mods[i].irefsym); - mods[i].nrefsym = swap32(mods[i].nrefsym); - mods[i].ilocalsym = swap32(mods[i].ilocalsym); - mods[i].nlocalsym = swap32(mods[i].nlocalsym); - mods[i].iextrel = swap32(mods[i].iextrel); - mods[i].nextrel = swap32(mods[i].nextrel); - mods[i].iinit_iterm = swap32(mods[i].iinit_iterm); - mods[i].ninit_nterm = swap32(mods[i].ninit_nterm); - mods[i].objc_module_info_size = - swap32(mods[i].objc_module_info_size); - mods[i].objc_module_info_addr = - swap64(mods[i].objc_module_info_addr); - } -} - -//-------------------------------------------------------------------------- -static void dylib_module_to64( - const struct dylib_module *mods_from, - struct dylib_module_64 *mods_to, - size_t nmods, - bool swap) -{ - if ( swap ) - { - for ( size_t i = 0; i < nmods; i++ ) - { - mods_to[i].module_name = swap32(mods_from[i].module_name); - mods_to[i].iextdefsym = swap32(mods_from[i].iextdefsym); - mods_to[i].nextdefsym = swap32(mods_from[i].nextdefsym); - mods_to[i].irefsym = swap32(mods_from[i].irefsym); - mods_to[i].nrefsym = swap32(mods_from[i].nrefsym); - mods_to[i].ilocalsym = swap32(mods_from[i].ilocalsym); - mods_to[i].nlocalsym = swap32(mods_from[i].nlocalsym); - mods_to[i].iextrel = swap32(mods_from[i].iextrel); - mods_to[i].nextrel = swap32(mods_from[i].nextrel); - mods_to[i].iinit_iterm = swap32(mods_from[i].iinit_iterm); - mods_to[i].ninit_nterm = swap32(mods_from[i].ninit_nterm); - mods_to[i].objc_module_info_size = - swap32(mods_from[i].objc_module_info_size); - mods_to[i].objc_module_info_addr = - swap32(mods_from[i].objc_module_info_addr); - } - } - else - { - for ( size_t i = 0; i < nmods; i++ ) - { - mods_to[i].module_name = mods_from[i].module_name; - mods_to[i].iextdefsym = mods_from[i].iextdefsym; - mods_to[i].nextdefsym = mods_from[i].nextdefsym; - mods_to[i].irefsym = mods_from[i].irefsym; - mods_to[i].nrefsym = mods_from[i].nrefsym; - mods_to[i].ilocalsym = mods_from[i].ilocalsym; - mods_to[i].nlocalsym = mods_from[i].nlocalsym; - mods_to[i].iextrel = mods_from[i].iextrel; - mods_to[i].nextrel = mods_from[i].nextrel; - mods_to[i].iinit_iterm = mods_from[i].iinit_iterm; - mods_to[i].ninit_nterm = mods_from[i].ninit_nterm; - mods_to[i].objc_module_info_size = - mods_from[i].objc_module_info_size; - mods_to[i].objc_module_info_addr = - mods_from[i].objc_module_info_addr; - } - } -} - -//-------------------------------------------------------------------------- -static void swap_dylib_table_of_contents(struct dylib_table_of_contents *tocs, uint32 ntocs) -{ - for ( uint32 i = 0; i < ntocs; i++ ) - { - tocs[i].symbol_index = swap32(tocs[i].symbol_index); - tocs[i].module_index = swap32(tocs[i].module_index); - } -} - -//-------------------------------------------------------------------------- -static void swap_dylib_reference(struct dylib_reference *refs, uint32 nrefs) -{ - struct swapped_dylib_reference - { - union - { - struct - { - uint32 - flags:8, - isym:24; - } fields; - uint32 word; - } u; - } sref; - - - for ( uint32 i = 0; i < nrefs; i++ ) - { - sref.u.fields.isym = refs[i].isym; - sref.u.fields.flags = refs[i].flags; - sref.u.word = swap32(sref.u.word); - memcpy(refs + i, &sref, sizeof(struct swapped_dylib_reference)); - } -} - -//-------------------------------------------------------------------------- -static void swap_indirect_symbols(uint32 *indirect_symbols, uint32 nindirect_symbols) -{ - for ( uint32 i = 0; i < nindirect_symbols; i++ ) - indirect_symbols[i] = swap32(indirect_symbols[i]); -} - -//-------------------------------------------------------------------------- -static void swap_relocation_info(struct relocation_info *relocs, uint32 nrelocs) -{ - uint32 i; - bool scattered; - - struct swapped_relocation_info - { - int32 r_address; - union - { - struct - { - unsigned int - r_type:4, - r_extern:1, - r_length:2, - r_pcrel:1, - r_symbolnum:24; - } fields; - uint32 word; - } u; - } sr; - CASSERT(sizeof(swapped_relocation_info) == sizeof(relocation_info)); - - struct swapped_scattered_relocation_info - { - uint32 word; - int32 r_value; - } *ssr; - - for ( i = 0; i < nrelocs; i++ ) - { - scattered = (bool)((swap32(relocs[i].r_address) & R_SCATTERED) != 0); - if ( scattered == FALSE ) - { - memcpy(&sr, relocs + i, sizeof(struct swapped_relocation_info)); - sr.r_address = swap32(sr.r_address); - sr.u.word = swap32(sr.u.word); - relocs[i].r_address = sr.r_address; - relocs[i].r_symbolnum = sr.u.fields.r_symbolnum; - relocs[i].r_pcrel = sr.u.fields.r_pcrel; - relocs[i].r_length = sr.u.fields.r_length; - relocs[i].r_extern = sr.u.fields.r_extern; - relocs[i].r_type = sr.u.fields.r_type; - } - else - { - ssr = (struct swapped_scattered_relocation_info *)(relocs + i); - ssr->word = swap32(ssr->word); - ssr->r_value = swap32(ssr->r_value); - } - } -} - -struct segment_command_64 segment_to64(const struct segment_command &sg) -{ - struct segment_command_64 res; - res.cmd = sg.cmd; - res.cmdsize = sg.cmdsize; - memcpy(res.segname, sg.segname, 16); - res.vmaddr = sg.vmaddr; - res.vmsize = sg.vmsize; - res.fileoff = sg.fileoff; - res.filesize = sg.filesize; - res.maxprot = sg.maxprot; - res.initprot = sg.initprot; - res.nsects = sg.nsects; - res.flags = sg.flags; - return res; -} - -struct section_64 section_to64(const struct section &sec) -{ - struct section_64 res; - memcpy(res.sectname, sec.sectname, 16); - memcpy(res.segname, sec.segname, 16); - res.addr = sec.addr; - res.size = sec.size; - res.offset = sec.offset; - res.align = sec.align; - res.reloff = sec.reloff; - res.nreloc = sec.nreloc; - res.flags = sec.flags; - res.reserved1 = sec.reserved1; - res.reserved2 = sec.reserved2; - res.reserved3 = 0; - return res; -} - -// load commands for prelinked kexts might contain tagged addresses -static void untag_lc_addr(uint64_t *untagged, uint64_t addr) -{ - if ( (addr & 0xFFFF000000000000) != 0 ) - { - // looks like a kernel address, check if it's tagged - if ( (addr & (1ull << 62)) == 0 ) - { - // assume non-PAC, 51-bit sign extend - *untagged = UNTAG_51BIT_SE(addr); - } - } -} - -void untag_segment_command(struct segment_command *) {} -void untag_segment_command(struct segment_command_64 *sg) -{ - untag_lc_addr(&sg->vmaddr, sg->vmaddr); -} - -void untag_section(struct section *) {} -void untag_section(struct section_64 *s) -{ - untag_lc_addr(&s->addr, s->addr); -} - -#include "base.cpp" - -#ifdef LOADER_COMPILE -//-------------------------------------------------------------------------- -static const char *convert_cpu(cpu_type_t cputype, cpu_subtype_t cpusubtype, int *p_target, bool mf) -{ - const char *name = NULL; - switch ( cputype ) - { - default: - case CPU_TYPE_VAX: - case CPU_TYPE_ROMP: - case CPU_TYPE_NS32032: - case CPU_TYPE_NS32332: - case CPU_TYPE_MC88000: - break; - case CPU_TYPE_MC680x0: - name = "68K"; - switch ( cpusubtype ) - { - case CPU_SUBTYPE_MC680x0_ALL: - break; - case CPU_SUBTYPE_MC68030_ONLY: - name = "68030"; - break; - case CPU_SUBTYPE_MC68040: - name = "68040"; - break; - } - break; - case CPU_TYPE_I860: - name = "860xp"; - switch ( cpusubtype ) - { - case CPU_SUBTYPE_I860_ALL: - break; - case CPU_SUBTYPE_I860_860: - name = "860xr"; - break; - } - break; - case CPU_TYPE_I386: - name = "metapc"; - switch ( cpusubtype ) - { - case CPU_SUBTYPE_I386_ALL: - break; - case CPU_SUBTYPE_486: - case CPU_SUBTYPE_486SX: - name = "80486p"; - break; - case CPU_SUBTYPE_PENT: /* same as 586 */ - case CPU_SUBTYPE_PENTPRO: - case CPU_SUBTYPE_PENTII_M3: - case CPU_SUBTYPE_PENTII_M5: - break; - } - break; - case CPU_TYPE_POWERPC: - name = "ppc"; - break; - case CPU_TYPE_HPPA: - name = "hppa"; - break; - case CPU_TYPE_SPARC: - name = mf ? "sparcb" : "sparcl"; - break; - case CPU_TYPE_MIPS: - name = mf ? "mipsb" : "mipsl"; - break; - case CPU_TYPE_ARM: - name = mf ? "armb" : "arm"; - break; -#ifdef __EA64__ // see also below, the error message for it - case CPU_TYPE_X86_64: - name = "metapc"; - break; - case CPU_TYPE_ARM64: - case CPU_TYPE_ARM64_32: // ARM64_32 can only be disassembled with ida64 - name = "arm"; - break; -#endif - case CPU_TYPE_POWERPC64: - name = "ppc"; - break; - } - if ( p_target != NULL ) - *p_target = macho_arch_to_ida_arch(cputype, cpusubtype, NULL); - return name; -} - -//-------------------------------------------------------------------------- -static size_t get_cpu_name(cpu_type_t cputype, cpu_subtype_t subtype, char *buf, size_t bufsize) -{ - const char *name; - const char *subname = ""; - char subbuf[32]; - if ( subtype != 0 ) - { - qsnprintf(subbuf, sizeof(subbuf), " (subtype 0x%02X)", subtype); - subname = subbuf; - } - switch ( cputype & ~CPU_ARCH_ABI64_MASK ) - { - case CPU_TYPE_VAX: name = "VAX"; break; - case CPU_TYPE_ROMP: name = "ROMP"; break; - case CPU_TYPE_NS32032: name = "NS32032"; break; - case CPU_TYPE_NS32332: name = "NS32332"; break; - case CPU_TYPE_VEO: name = "VEO"; break; - case CPU_TYPE_MC680x0: name = "MC680x0"; break; - case CPU_TYPE_MC88000: name = "MC88000"; break; - case CPU_TYPE_I860: name = "I860"; break; - case CPU_TYPE_POWERPC: name = "POWERPC"; break; - case CPU_TYPE_HPPA: name = "HPPA"; break; - case CPU_TYPE_SPARC: name = "SPARC"; break; - case CPU_TYPE_I386: name = "I386"; - if ( subtype == CPU_SUBTYPE_I386_ALL ) // same as CPU_SUBTYPE_386 - subname = ""; - break; - case CPU_TYPE_ARM: - name = "ARM"; - switch ( subtype ) - { - case CPU_SUBTYPE_ARM_A500_ARCH: - case CPU_SUBTYPE_ARM_A500: - subname = "500"; - break; - case CPU_SUBTYPE_ARM_A440: - subname = "440"; - break; - case CPU_SUBTYPE_ARM_M4: - subname = " M4"; - break; - case CPU_SUBTYPE_ARM_V4T: - subname = "v4T"; - break; - case CPU_SUBTYPE_ARM_V6: - subname = "v6"; - break; - case CPU_SUBTYPE_ARM_V5TEJ: - subname = "v5TEJ"; - break; - case CPU_SUBTYPE_ARM_XSCALE: - subname = " XScale"; - break; - case CPU_SUBTYPE_ARM_V7: - subname = "v7"; - break; - case CPU_SUBTYPE_ARM_V7F: - subname = "v7F"; - break; - case CPU_SUBTYPE_ARM_V7K: - subname = "v7K"; - break; - case CPU_SUBTYPE_ARM_V7S: - subname = "v7S"; - break; - case CPU_SUBTYPE_ARM_V8: - subname = "v8"; - break; - } - break; - default: - return qsnprintf(buf, bufsize, "0x%02X%s", cputype, subname); - } - if ( cputype & CPU_ARCH_ABI64 ) - { - switch ( cputype ) - { - case CPU_TYPE_X86_64: - name = "X86_64"; - switch ( subtype & ~CPU_SUBTYPE_MASK ) - { - case CPU_SUBTYPE_X86_ALL: - subname = ""; - break; - case CPU_SUBTYPE_X86_ARCH1: - subname = " (arch1)"; - break; - case CPU_SUBTYPE_X86_64_H: - subname = " (x86_64h)"; - break; - } - break; - case CPU_TYPE_POWERPC64: - name = "POWERPC64"; - break; - case CPU_TYPE_ARM64: - name = "ARM64"; - switch ( subtype & ~CPU_SUBTYPE_MASK ) - { - case CPU_SUBTYPE_ARM64_ALL: - subname = ""; - break; - case CPU_SUBTYPE_ARM64_V8: - subname = "v8"; - break; - case CPU_SUBTYPE_ARM64E: - subname = "e"; - break; - default: - break; - } - break; - default: - return qsnprintf(buf, bufsize, "%s64%s", name, subname); - } - } - if ( cputype & CPU_ARCH_ABI64_32 ) - { - switch ( cputype ) - { - case CPU_TYPE_ARM64_32: - name = "ARM64_32"; - switch ( subtype & ~CPU_SUBTYPE_MASK ) - { - case CPU_SUBTYPE_ARM64_32_ALL: - subname = ""; - break; - case CPU_SUBTYPE_ARM64_32_V8: - subname = "_V8"; - break; - default: - break; - } - break; - default: - return qsnprintf(buf, bufsize, "%s64%s", name, subname); - } - } - return qsnprintf(buf, bufsize, "%s%s", name, subname); -} -#endif - -// --------------------------------------------------------------------------- -bool macho_file_t::seek_to_subfile(uint n, size_t filesize) -{ - int64 fsize = filesize == 0 ? qlsize(li) : filesize; - if ( fsize <= 0 ) - return false; - - if ( n == 0 && fat_archs.size() == 0 ) - { - mach_offset = 0; - mach_size = size_t(fsize); - } - else if ( n < fat_archs.size() ) - { - mach_offset = fat_archs[n].offset; - mach_size = fat_archs[n].size; - if ( mach_offset >= size_t(fsize) ) - { - msg("Fat subfile %i is outside the file\n", n); - return false; - } - if ( mach_offset + mach_size > size_t(fsize) ) - { - msg("Fat subfile %i is truncated\n", n); - mach_size = qlsize(li) - mach_offset; - } - } - else - { - return false; - } - - qoff64_t pos = mach_offset + start_offset; - return qlseek(li, pos) == pos; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::is_loaded_addr(uint64 addr) -{ - const segcmdvec_t &cmds = get_segcmds(); - for ( const segment_command_64 &sg : cmds ) - { - if ( addr >= sg.vmaddr && addr < sg.vmaddr + sg.vmsize ) - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -// select a module from the current FAT submodule (the current submodule is an archive) -// 1. create a temporary file from the FAT subfile -// 2. let the user select a module from it -// 3. load it -bool macho_file_t::select_ar_module(size_t offset, size_t size) -{ - if ( extractor == NULL ) - return false; - // copy the submodule into a separate file - char *tmp_fname = qtmpnam(NULL, 0); - FILE *out = fopenWB(tmp_fname); - if ( out == NULL ) - { - warning("%s", get_errdesc(tmp_fname)); - return false; - } - qlseek(li, offset, SEEK_SET); - char buf[4096]; - int rest = size; - while ( rest > 0 ) - { - int chunk = rest > sizeof(buf) ? sizeof(buf) : rest; - if ( qlread(li, buf, chunk) != chunk ) - break; - if ( qfwrite(out, buf, chunk) != chunk ) - break; - rest -= chunk; - } - qfclose(out); - bool ok = false; - if ( rest == 0 ) // read the whole file, good - { - // let the user select - char *tmpfname = NULL; - qstrncpy(buf, tmp_fname, sizeof(buf)); - if ( extractor->extract(buf, sizeof(buf), &tmpfname, false) ) - { // the selected file is in tmpfile, switch to it and try to load it - if ( should_close_linput ) - close_linput(li); - li = open_linput(tmpfname, false); - QASSERT(20028, li != NULL); - should_close_linput = true; - start_offset = 0; - fat_archs.clear(); - if ( parse_header() && set_subfile(0) ) - ok = true; - } - } - qunlink(tmp_fname); - return ok; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::set_subfile(uint n, size_t filesize, bool silent) -{ - // clear various cached tables - mach_header_data.clear(); - load_commands.clear(); - mach_segcmds.clear(); - mach_sections.clear(); - mach_dylibs.clear(); - mach_modtable.clear(); - mach_toc.clear(); - mach_reftable.clear(); - parsed_section_info = false; - base_addr = BADADDR64; - - size_t mh_len; - subfile_type_t type = get_subfile_type(n, filesize); - switch ( type ) - { - default: - INTERR(20026); - - case SUBFILE_UNKNOWN: - return false; - - case SUBFILE_AR: - return select_ar_module(mach_offset, mach_size); - - case SUBFILE_MACH: // 32-bit file - m64 = false; - mh_len = sizeof(mach_header); - break; - - case SUBFILE_MACH_64: // 64-bit file - m64 = true; - mh_len = sizeof(mach_header_64); - break; - } - - mach_header_data.resize(mh_len); - if ( qlread(li, mach_header_data.begin(), mh_len) != mh_len ) - return false; - - memcpy(&mh, mach_header_data.begin(), mh_len); - if ( !m64 ) - mh.reserved = 0; - - mf = is_cigam(mh.magic); - if ( mf ) - swap_mach_header_64(&mh); - - size_t size = mh_len + mh.sizeofcmds; - if ( size > mach_size || size < mh_len ) // overflow? - return false; - mach_header_data.resize(size); - if ( qlread(li, &mach_header_data[mh_len], mh.sizeofcmds) != mh.sizeofcmds ) - { - mach_header_data.clear(); - return false; - } - - return parse_load_commands(silent); -} - -//-------------------------------------------------------------------------- -bool macho_file_t::select_subfile(cpu_type_t cputype, cpu_subtype_t cpusubtype) -{ - if ( fat_archs.empty() && set_subfile(0) ) - { - // single file; check if it matches what we need - if ( mh.cputype == cputype && (mh.cpusubtype == cpusubtype || cpusubtype == 0) ) - return true; - } - for ( size_t i = 0; i < fat_archs.size(); i++ ) - { - // fat file; enumerate architectures - const fat_arch &fa = fat_archs[i]; - if ( fa.cputype == cputype - && (fa.cpusubtype == cpusubtype || cpusubtype == 0) - && set_subfile(i) ) - { - if ( mh.cputype == cputype && (mh.cpusubtype == cpusubtype || cpusubtype == 0) ) - return true; - } - } - return false; -} - -// --------------------------------------------------------------------------- -// upon return: file position after at the beginning of the subfile -macho_file_t::subfile_type_t macho_file_t::get_subfile_type(uint n, size_t filesize) -{ - if ( !seek_to_subfile(n, filesize) ) - return SUBFILE_UNKNOWN; - - uint32_t magic; - if ( qlread(li, &magic, sizeof(magic)) != sizeof(magic) ) - return SUBFILE_UNKNOWN; - qlseek(li, -int(sizeof(magic)), SEEK_CUR); - - subfile_type_t type = SUBFILE_UNKNOWN; - if ( magic == MH_CIGAM || magic == MH_MAGIC ) - { - type = SUBFILE_MACH; - } - else if ( magic == MH_CIGAM_64 || magic == MH_MAGIC_64 ) - { - type = SUBFILE_MACH_64; - } - else if ( strncmp(ARMAG, (const char *)&magic, sizeof(magic)) == 0 ) - { - qoff64_t fpos = qltell(li); - if ( is_ar_file(li, fpos, false) ) - type = SUBFILE_AR; - qlseek(li, fpos, SEEK_SET); - } - - return type; -} - -//-------------------------------------------------------------------------- -const mach_header_64 &macho_file_t::get_mach_header() -{ - QASSERT(20005, mach_offset != -1); // macho_file_t::get_mach_header: set_subfile() must be called first - return mh; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::parse_load_commands(bool silent) -{ - struct load_command l; - const char *begin = (const char*)&mach_header_data[0]; - size_t delta = m64 ? sizeof(mach_header_64) : sizeof(mach_header); - const struct load_command *lc = (load_command *)(begin + delta); - - const char *commands_end = begin + mach_header_data.size(); - begin = (const char*)lc; - load_commands.clear(); - if ( begin >= commands_end && mh.ncmds != 0 ) - { - if ( !silent ) - warning("Inconsistent mh.ncmds %u", mh.ncmds); - return false; - } - for ( uint32 i = 0; i < mh.ncmds && begin < commands_end; i++ ) - { - safecopy(begin, commands_end, &l); - if ( mf ) - swap_load_command(&l); - if ( l.cmdsize % sizeof(int32) != 0 ) - { - if ( !silent ) - warning("load command %u size not a multiple of 4\n", i); - return false; - } - begin = (const char *)lc; - const char *end = begin + l.cmdsize; - if ( end > commands_end ) - { - if ( !silent ) - warning("load command %u extends past end of load commands\n", i); - return false; - } - if ( begin > end ) - { - if ( !silent ) - warning("load command %u: cmdsize overflow", i); - return false; - } - if ( l.cmdsize == 0 ) - { - if ( !silent ) - warning("load command %u size zero (can't advance to next load commands)", i); - return false; - } - load_commands.push_back(lc); - begin = end; - lc = (struct load_command *)begin; - } - if ( commands_end != begin ) - { - if ( !silent ) - warning("Inconsistent mh.sizeofcmds"); - } - - parsed_section_info = false; - return !load_commands.empty(); -} - -//-------------------------------------------------------------------------- -#define HANDLE_SIMPLE_COMMAND(name) \ - { \ - name##_command cmd##name; \ - safecopy(begin, end, &cmd##name); \ - if ( mf ) \ - swap_##name##_command(&cmd##name); \ - result = v.visit_##name (&cmd##name, cmd_begin, end); \ - } - -//-------------------------------------------------------------------------- -template <class generic_segment_command, class generic_section> -int handle_lc_segment(const char *begin, const char *end, macho_lc_visitor_t &v, bool _mf) -{ - generic_segment_command sg; - safecopy(begin, end, &sg); - if ( _mf ) - swap_segment_command(&sg); - untag_segment_command(&sg); - const char *cmd_begin = begin; - int result = v.visit_segment(&sg, cmd_begin, end); - if ( result == 0 && sg.nsects > 0 ) - { - generic_section s; - for ( uint32_t j=0; j < sg.nsects; j++ ) - { - if ( begin >= end ) - { - static bool complained = false; - if ( !complained ) - warning("Inconsistent number of sections %u in a segment", sg.nsects); - complained = true; - break; - } - cmd_begin = begin; - safecopy(begin, end, &s); - if ( _mf ) - swap_section(&s, 1); - untag_section(&s); - // ignore sections outside of the segment - result = v.visit_section(&s, cmd_begin, end); - if ( result != 0 ) - break; - } - } - return result; -} - -//-------------------------------------------------------------------------- -// build_version_command is variable-sized so we need to handle it separately -int handle_build_version(const char *begin, const char *end, macho_lc_visitor_t &v, bool _mf) -{ - build_version_command bv; - safecopy(begin, end, &bv); - if ( _mf ) - swap_build_version_command(&bv); - const char *cmd_begin = begin; - int result = v.visit_build_version(&bv, cmd_begin, end); - //followed by 'ntools'*build_tool_version structures - if ( result == 0 && bv.ntools > 0 ) - { - build_tool_version bt; - for ( uint32_t j = 0; j < bv.ntools; j++ ) - { - if ( begin >= end ) - { - static bool complained = false; - if ( !complained ) - warning("Inconsistent number of tools %u in LC_BUILD_VERSION command", bv.ntools); - complained = true; - break; - } - cmd_begin = begin; - safecopy(begin, end, &bt); - if ( _mf ) - swap_build_tool_version(&bt); - // ignore entries outside of the command - result = v.visit_build_tool_version(&bt, cmd_begin, end); - if ( result != 0 ) - break; - } - } - return result; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::visit_load_commands(macho_lc_visitor_t &v) -{ - struct load_command l; - int result = 0; - const char *begin = (const char*)&mach_header_data[0], *end; - const char *commands_end = begin + mach_header_data.size(); - - for ( size_t i=0; result == 0 && i < load_commands.size(); i++ ) - { - const struct load_command *lc = load_commands[i]; - l = *lc; - if ( mf ) - swap_load_command(&l); - begin = (const char*)lc; - const char *cmd_begin = begin; - end = begin + l.cmdsize; - if ( end > commands_end || begin >= end ) - { - msg("Inconsistency in load commands"); - break; - } - result = v.visit_any_load_command(&l, cmd_begin, end); - if ( result == 2 ) - { - // don't call specific callback and continue - result = 0; - continue; - } - else if ( result != 0 ) - { - // stop enumeration - break; - } - switch ( l.cmd ) - { - case LC_SEGMENT: - result = handle_lc_segment<segment_command, section>(begin, end, v, mf); - break; - case LC_SEGMENT_64: - result = handle_lc_segment<segment_command_64, section_64>(begin, end, v, mf); - break; - case LC_SYMTAB: - HANDLE_SIMPLE_COMMAND(symtab); - break; - case LC_SYMSEG: - HANDLE_SIMPLE_COMMAND(symseg); - break; - case LC_THREAD: - case LC_UNIXTHREAD: - HANDLE_SIMPLE_COMMAND(thread); - break; - case LC_IDFVMLIB: - case LC_LOADFVMLIB: - HANDLE_SIMPLE_COMMAND(fvmlib); - break; - case LC_IDENT: - HANDLE_SIMPLE_COMMAND(ident); - break; - case LC_FVMFILE: - HANDLE_SIMPLE_COMMAND(fvmfile); - break; - case LC_DYSYMTAB: - HANDLE_SIMPLE_COMMAND(dysymtab); - break; - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_ID_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LAZY_LOAD_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - HANDLE_SIMPLE_COMMAND(dylib); - break; - case LC_ID_DYLINKER: - case LC_LOAD_DYLINKER: - case LC_DYLD_ENVIRONMENT: - HANDLE_SIMPLE_COMMAND(dylinker); - break; - case LC_PREBOUND_DYLIB: - HANDLE_SIMPLE_COMMAND(prebound_dylib); - break; - case LC_ROUTINES: - HANDLE_SIMPLE_COMMAND(routines); - break; - case LC_SUB_FRAMEWORK: - HANDLE_SIMPLE_COMMAND(sub_framework); - break; - case LC_SUB_UMBRELLA: - HANDLE_SIMPLE_COMMAND(sub_umbrella); - break; - case LC_SUB_CLIENT: - HANDLE_SIMPLE_COMMAND(sub_client); - break; - case LC_SUB_LIBRARY: - HANDLE_SIMPLE_COMMAND(sub_library); - break; - case LC_TWOLEVEL_HINTS: - HANDLE_SIMPLE_COMMAND(twolevel_hints); - break; - case LC_PREBIND_CKSUM: - HANDLE_SIMPLE_COMMAND(prebind_cksum); - break; - case LC_ROUTINES_64: - { - routines_command_64 rc; - safecopy(begin, end, &rc); - if ( mf ) - swap_routines_command_64(&rc); - result = v.visit_routines_64(&rc, cmd_begin, end); - } - break; - case LC_UUID: - HANDLE_SIMPLE_COMMAND(uuid); - break; - case LC_RPATH: - HANDLE_SIMPLE_COMMAND(rpath); - break; - case LC_CODE_SIGNATURE: - case LC_SEGMENT_SPLIT_INFO: - case LC_FUNCTION_STARTS: - case LC_DATA_IN_CODE: - case LC_DYLIB_CODE_SIGN_DRS: - HANDLE_SIMPLE_COMMAND(linkedit_data); - break; - case LC_ENCRYPTION_INFO: - HANDLE_SIMPLE_COMMAND(encryption_info); - break; - case LC_ENCRYPTION_INFO_64: - { - encryption_info_command_64 ec; - safecopy(begin, end, &ec); - if ( mf ) - swap_encryption_info_command_64(&ec); - result = v.visit_encryption_info_64(&ec, cmd_begin, end); - } - break; - case LC_DYLD_INFO: - case LC_DYLD_INFO_ONLY: - HANDLE_SIMPLE_COMMAND(dyld_info); - break; - case LC_VERSION_MIN_MACOSX: - case LC_VERSION_MIN_IPHONEOS: - case LC_VERSION_MIN_WATCHOS: - case LC_VERSION_MIN_TVOS: - HANDLE_SIMPLE_COMMAND(version_min); - break; - case LC_BUILD_VERSION: - result = handle_build_version(begin, end, v, mf); - break; - case LC_MAIN: - HANDLE_SIMPLE_COMMAND(entry_point); - break; - case LC_SOURCE_VERSION: - HANDLE_SIMPLE_COMMAND(source_version); - break; - default: - result = v.visit_unknown_load_command(&l, cmd_begin, end); - break; - } - } - return result != 0; -} - -//-------------------------------------------------------------------------- -int macho_file_t::is_encrypted() -{ - struct myvisitor: macho_lc_visitor_t - { - int is_encrypted; - myvisitor(): is_encrypted(0) {} - virtual int visit_segment( - const struct segment_command *sg, - const char *, - const char *) override - { - if ( is_protected(*sg) ) - { - is_encrypted = 1; - return 1; - } - return 0; - } - - virtual int visit_segment( - const struct segment_command_64 *sg, - const char *, - const char *) override - { - if ( is_protected(*sg) ) - { - is_encrypted = 1; - return 1; - } - return 0; - } - - virtual int visit_encryption_info( - const struct encryption_info_command *ec, - const char *, - const char *) override - { - if ( ec->cryptsize != 0 && ec->cryptid != 0 ) - { - is_encrypted = 2; - return 1; - } - return 0; - } - virtual int visit_encryption_info_64( - const struct encryption_info_command_64 *ec, - const char *, - const char *) override - { - if ( ec->cryptsize != 0 && ec->cryptid != 0 ) - { - is_encrypted = 2; - return 1; - } - return 0; - } - }; - - myvisitor v; - - visit_load_commands(v); - return v.is_encrypted; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::is_kernel() -{ - if ( mh.filetype != MH_EXECUTE ) - return false; - // look for the __KLD segment. it contains the kernel bootstrap code. - // if the macho file is executable and bootable, it is likely the mach kernel. - struct myvisitor: macho_lc_visitor_t - { - bool is_kernel; - myvisitor(): is_kernel(false) {} -#define CHECK_KLD(sc) \ - do \ - { \ - if ( streq(sc->segname, "__KLD") ) \ - { \ - is_kernel = true; \ - return 1; \ - } \ - } \ - while ( false ) - virtual int visit_segment(const segment_command *sc, const char *, const char *) override - { - CHECK_KLD(sc); - return 0; - } - virtual int visit_segment(const segment_command_64 *sc, const char *, const char *) override - { - CHECK_KLD(sc); - return 0; - } -#undef CHECK_KLD - }; - myvisitor v; - visit_load_commands(v); - return v.is_kernel; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::is_kcache() -{ - if ( mh.filetype != MH_EXECUTE ) - return false; - // look for a nontrivial __PRELINK_INFO:__info section. - // such a file will likely contain prelinked KEXTs. - struct myvisitor: macho_lc_visitor_t - { - bool is_kcache; - myvisitor(): is_kcache(false) {} -#define CHECK_PRELINK_INFO(s) \ - do \ - { \ - if ( is_prelink_info(*s) ) \ - { \ - is_kcache = true; \ - return 1; \ - } \ - } \ - while ( false ) - virtual int visit_section(const section *s, const char *, const char *) override - { - CHECK_PRELINK_INFO(s); - return 0; - } - virtual int visit_section(const section_64 *s, const char *, const char *) override - { - CHECK_PRELINK_INFO(s); - return 0; - } -#undef CHECK_PRELINK_INFO - }; - myvisitor v; - visit_load_commands(v); - return v.is_kcache; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::is_kext() const -{ - return mh.filetype == MH_KEXT_BUNDLE; -} - -//-------------------------------------------------------------------------- -// check for LC_MAIN and/or LC_THREAD/LC_UNIXTHREAD commands -static void _get_thread_info(macho_file_t *mfile, const char **thr_begin, const char **thr_end, uint64_t *entryoff) -{ - struct ida_local myvisitor: macho_lc_visitor_t - { - const char *begin, *end; - uint64_t entryoff; - - myvisitor(): begin(NULL), end(NULL), entryoff(0) {} - - virtual int visit_thread( - const struct thread_command *, - const char *_begin, - const char *_end) override - { - safeskip(_begin, _end, sizeof(thread_command)); - if ( _begin >= _end ) - { - // bad command, try to continue - return 0; - } - begin = _begin; - end = _end; - return 0; - } - - //-------------------------------------------------------------------------- - virtual int visit_entry_point( - const struct entry_point_command *ei, - const char *_begin, - const char *_end) override - { - if ( !safeskip(_begin, _end, sizeof(entry_point_command)) ) - { - // bad command - return 0; - } - entryoff = ei->entryoff; - return 0; - } - - }; - - myvisitor v; - mfile->visit_load_commands(v); - if ( thr_begin != NULL ) - *thr_begin = v.begin; - if ( thr_end != NULL ) - *thr_end = v.end; - if ( entryoff != NULL ) - *entryoff = v.entryoff; -} - -//-------------------------------------------------------------------------- -void macho_file_t::get_thread_state(const char *&begin, const char *&end) -{ - _get_thread_info(this, &begin, &end, NULL); -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::get_entry_address() -{ - const char *begin, *end; - uint64_t entryoff; - _get_thread_info(this, &begin, &end, &entryoff); - if ( entryoff != 0 ) - { - if ( base_addr == BADADDR64 ) - parse_section_info(); - return base_addr == BADADDR64 ? entryoff : base_addr + entryoff; - } - - // no LC_MAIN, go the long way - // fun fact: dyld does not check if the thread context actually has the correct flavor or even size - // it just does stuff like: - // const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16); - // void* entry = (void*)(registers->eip + fSlide); - uint32 offset; - switch ( mh.cputype ) - { - case CPU_TYPE_POWERPC: - case CPU_TYPE_POWERPC64: - case CPU_TYPE_VEO: - // __srr0 is at the start of the context - offset = 0; - break; - case CPU_TYPE_ARM: - offset = qoffsetof(arm_thread_state32_t, __pc); - break; - case CPU_TYPE_ARM64: - case CPU_TYPE_ARM64_32: - offset = qoffsetof(arm_thread_state64_t, __pc); - break; - case CPU_TYPE_I386: - offset = qoffsetof(i386_thread_state_t, __eip); - break; - case CPU_TYPE_X86_64: - offset = qoffsetof(x86_thread_state64_t, __rip); - break; - default: - // unhandled - return BADADDR64; - } - // 8: skip flavor and count - begin += 8 + offset; - if ( m64 ) - { - uint64 val; - if ( !safecopy(begin, end, &val) ) - return BADADDR64; - if ( mf ) - val = swap64(val); - return val; - } - else - { - uint32 val; - if ( !safecopy(begin, end, &val) ) - return BADADDR64; - if ( mf ) - val = swap32(val); - return val; - } -} - -//-------------------------------------------------------------------------- -bool has_contiguous_segments(const segcmdvec_t &segcmds) -{ - size_t ncmds = segcmds.size(); - if ( ncmds <= 1 ) - return true; - - for ( size_t i = 0; i < ncmds - 1; i++ ) - { - const segment_command_64 &s1 = segcmds[i]; - const segment_command_64 &s2 = segcmds[i+1]; - - if ( (s1.vmaddr + s1.vmsize) != s2.vmaddr ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -void macho_file_t::parse_section_info() -{ - /* - * Create an array of section structures in the host byte sex so it - * can be processed and indexed into directly. - */ - - struct myvisitor: macho_lc_visitor_t - { - secvec_t §ions; - segcmdvec_t &segcmds; - intvec_t &seg2section; - bool m64; - int32 nsecs_to_check; - - myvisitor(secvec_t &_sections, segcmdvec_t &_segcmds, intvec_t &seg2section_, bool _m64) - : sections(_sections), segcmds(_segcmds), seg2section(seg2section_), m64(_m64), nsecs_to_check(0) {} - - virtual int visit_segment( - const struct segment_command *sg, - const char *, - const char *) override - { - if ( m64 ) - { - warning("Found a 32-bit segment in 64-bit program, ignoring it"); - return 0; - } - else - { - segcmds.push_back(segment_to64(*sg)); - seg2section.push_back(sections.size()); - nsecs_to_check = sg->nsects; - } - return 0; - } - - virtual int visit_segment( - const struct segment_command_64 *sg, - const char *, - const char *) override - { - if ( !m64 ) - { - warning("Found a 64-bit segment in 32-bit program, ignoring it"); - return 0; - } - else - { - segcmds.push_back(*sg); - seg2section.push_back(sections.size()); - nsecs_to_check = sg->nsects; - } - return 0; - } - - bool check_section(const struct section_64 *s) - { - if ( --nsecs_to_check <= 0 ) // We have already visited all the sections of last good segment - return true; - const struct segment_command_64 &curseg = segcmds.back(); - if ( curseg.vmsize == 0 ) - return true; - ea_t start = s->addr; - ea_t end = s->addr+s->size; - for ( int i = 0; i < sections.size(); i++ ) - { - ea_t si_start = sections[i].addr; - ea_t si_end = sections[i].addr + sections[i].size; - if ( start > si_start && start < si_end - || end > si_start && end < si_end ) - { - warning("Section 0x%" FMT_64 "X of size %" FMT_64 "X intersects " - "with existing section(0x%" FMT_64 "X, size %" FMT_64 "X). Skipped", - s->addr, s->size, sections[i].addr, sections[i].size); - return false; - } - } - return true; - } - - virtual int visit_section( - const struct section *s, - const char *, - const char *) override - { - section_64 s64 = section_to64(*s); - if ( check_section(&s64) ) - sections.push_back(s64); - return 0; - } - - virtual int visit_section( - const struct section_64 *s, - const char *, - const char *) override - { - if ( check_section(s) ) - sections.push_back(*s); - return 0; - } - }; - - if ( !parsed_section_info ) - { - mach_sections.clear(); - mach_segcmds.clear(); - seg2section.clear(); - myvisitor v(mach_sections, mach_segcmds, seg2section, m64); - visit_load_commands(v); - parsed_section_info = true; - if ( is_shared_cache_lib() && !mach_segcmds.empty() ) - { - segment_command_64 &sg = mach_segcmds[0]; - // kludge: for most dyldcache subfiles, the __TEXT segment will have fileoff=0. - // thus, file reads will be realitve to the start offset of the subfile within the cache - // (see dyld_single_macho_linput_t::read()). however, some dyldcaches use absolute offsets - // in the __TEXT segments. to avoid guessing whether or not a given text offset is relative, - // we enforce the use of relative offsets. - if ( streq(sg.segname, SEG_TEXT) && sg.fileoff != 0 ) - { - for ( size_t i = 0; i < mach_sections.size(); i++ ) - { - // normalize the section offsets so they are 0-based - section_64 § = mach_sections[i]; - if ( streq(sect.segname, SEG_TEXT) ) - sect.offset -= sg.fileoff; - } - sg.fileoff = 0; - } - } - for ( size_t i = 0; i < mach_segcmds.size(); i++ ) - { - const segment_command_64 &sg64 = mach_segcmds[i]; - if ( base_addr == BADADDR64 && sg64.fileoff == 0 && sg64.filesize != 0 ) - { - base_addr = sg64.vmaddr; - break; - } - } - } -} - -//-------------------------------------------------------------------------- -const segcmdvec_t &macho_file_t::get_segcmds() -{ - parse_section_info(); - return mach_segcmds; -} - -//-------------------------------------------------------------------------- -const secvec_t &macho_file_t::get_sections() -{ - parse_section_info(); - return mach_sections; -} - -//-------------------------------------------------------------------------- -// get section by 1-based index (0 for header pseudo-section) -bool macho_file_t::get_section_or_hdr(section_64 *psect, size_t sectIndex) -{ - memset(psect, 0, sizeof(*psect)); - if ( sectIndex == 0 ) - { - // header - psect->addr = 0; - qstrncpy(psect->segname, SEG_TEXT, sizeof(psect->segname)); - return true; - } - sectIndex--; - if ( sectIndex >= mach_sections.size() ) - return false; - *psect = mach_sections[sectIndex]; - return true; -} - -//-------------------------------------------------------------------------- -// get segment by index -bool macho_file_t::get_segment(size_t segIndex, segment_command_64 *pseg) -{ - parse_section_info(); - if ( segIndex < mach_segcmds.size() ) - { - if ( pseg != NULL ) - *pseg = mach_segcmds[segIndex]; - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -// get section by segment index and virtual address inside section -bool macho_file_t::get_section(size_t segIndex, uint64_t vaddr, section_64 *psect) -{ - if ( segIndex < seg2section.size() ) - { - const segment_command_64 &seg = mach_segcmds[segIndex]; - for ( size_t i = seg2section[segIndex]; i < seg2section[segIndex] + seg.nsects; i++ ) - { - const section_64 § = mach_sections[i]; - if ( sect.addr <= vaddr && vaddr < sect.addr + sect.size ) - { - if ( psect != NULL ) - *psect = sect; - return true; - } - } - } - return false; -} - -//-------------------------------------------------------------------------- -// find segment by name -bool macho_file_t::get_segment(const char *segname, segment_command_64 *pseg) -{ - parse_section_info(); - for ( size_t idx = 0; idx < mach_segcmds.size(); ++idx ) - { - const segment_command_64 &seg = mach_segcmds[idx]; - if ( strncmp(seg.segname, segname, sizeof(seg.segname)) == 0 ) - { - if ( pseg != NULL ) - *pseg = seg; - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -// get section by segment name and section name -bool macho_file_t::get_section(const char *segname, const char *sectname, section_64 *psect) -{ - parse_section_info(); - for ( size_t idx = 0; idx < mach_segcmds.size(); ++idx ) - { - const segment_command_64 &seg = mach_segcmds[idx]; - if ( strncmp(seg.segname, segname, sizeof(seg.segname)) == 0 ) - { - for ( size_t i = seg2section[idx]; i < seg2section[idx] + seg.nsects; i++ ) - { - QASSERT(20027, i < mach_sections.size()); - const section_64 § = mach_sections[i]; - if ( strncmp(sect.sectname, sectname, sizeof(sect.sectname)) == 0 ) - { - if ( psect != NULL ) - *psect = sect; - return true; - } - } - } - } - return false; -} - -//-------------------------------------------------------------------------- -// get section's data by segment name and section name -bool macho_file_t::get_section(const char *segname, const char *sectname, bytevec_t *data) -{ - section_64 secthdr; - if ( !get_section(segname, sectname, §hdr) ) - return false; - uint64 offset; - if ( !is_mem_image() && mh.filetype == MH_OBJECT ) - { - // we should use section's file offsets - offset = secthdr.offset; - } - else - { - // we should use section's vaddr and use segment to find the corresponding file offset - segment_command_64 seghdr; - if ( !get_segment(segname, &seghdr) ) - return false; - if ( is_mem_image() ) - offset = secthdr.addr - base_addr; - else - offset = seghdr.fileoff + (secthdr.addr - seghdr.vmaddr); - } - qlseek(li, start_offset + mach_offset + offset); - data->resize(secthdr.size); - qlread(li, data->begin(), secthdr.size); - return true; -} - -//-------------------------------------------------------------------------- -const dyliblist_t macho_file_t::get_dylib_list(int kind) -{ - - struct myvisitor: macho_lc_visitor_t - { - dyliblist_t &dylibs; - int kind; - - myvisitor(dyliblist_t &_dylibs, int _kind): dylibs(_dylibs), kind(_kind) {} - - virtual int visit_dylib( - const struct dylib_command *d, - const char *begin, - const char *end) override - { - switch ( d->cmd ) - { - case LC_LOAD_DYLIB: - case LC_LOAD_WEAK_DYLIB: - case LC_REEXPORT_DYLIB: - case LC_LAZY_LOAD_DYLIB: - case LC_LOAD_UPWARD_DYLIB: - { - // check if it's the kind of dylib we're looking for - if ( kind != 0 && kind != d->cmd ) - return 0; // nope, continue - // sanity check - size_t off = d->dylib.name.offset; - const char *namestart = begin + off; - if ( off < sizeof(*d) || namestart < begin || namestart >= end ) - { - dylibs.push_back("<bad dylib name>"); - break; - } - qstring dlname(namestart, end - namestart); - dlname.rtrim('\0'); - dylibs.push_back(dlname); - } - break; - } - // continue enumeration - return 0; - } - }; - - if ( mach_dylibs.empty() || kind != 0 ) - { - myvisitor v(mach_dylibs, kind); - visit_load_commands(v); - if ( kind != 0 ) - { - dyliblist_t copy = mach_dylibs; - mach_dylibs.clear(); - return copy; - } - } - return mach_dylibs; -} - -//-------------------------------------------------------------------------- -const mod_table_t &macho_file_t::get_module_table() -{ - struct dysymtab_command dyst; - - if ( mach_modtable.empty() && get_dyst(&dyst) ) - { - if ( dyst.modtaboff >= mach_size ) - { - msg("module table offset is past end of file\n"); - } - else - { - size_t entrysize = (m64 ? sizeof(struct dylib_module_64) : sizeof(struct dylib_module)); - size_t nmods = dyst.nmodtab; - size_t size = nmods * entrysize; - if ( dyst.modtaboff + size > mach_size ) - { - msg("module table extends past end of file\n"); - size = mach_size - dyst.modtaboff; - nmods = size / entrysize; - size = nmods * entrysize; - } - qlseek(li, start_offset + mach_offset + dyst.modtaboff); - mach_modtable.resize(nmods); - if ( m64 ) - { - qlread(li, mach_modtable.begin(), size); - if ( mf ) - swap_dylib_module_64(mach_modtable.begin(), nmods); - } - else - { - qvector<struct dylib_module> mods32; - mods32.resize(nmods); - qlread(li, mods32.begin(), size); - dylib_module_to64(mods32.begin(), mach_modtable.begin(), nmods, mf); - } - } - } - return mach_modtable; -} - -//-------------------------------------------------------------------------- -const tocvec_t &macho_file_t::get_toc() -{ - struct dysymtab_command dyst; - - if ( mach_toc.empty() && get_dyst(&dyst) ) - { - if ( dyst.tocoff >= mach_size ) - { - msg("table of contents offset is past end of file\n"); - } - else - { - size_t entrysize = sizeof(struct dylib_table_of_contents); - size_t ntocs = dyst.ntoc; - size_t size = ntocs * entrysize; - if ( dyst.tocoff + size > mach_size ) - { - msg("table of contents table extends past end of file\n"); - size = mach_size - dyst.tocoff; - ntocs = size / entrysize; - size = ntocs * entrysize; - } - qlseek(li, start_offset + mach_offset + dyst.tocoff); - mach_toc.resize(ntocs); - qlread(li, mach_toc.begin(), size); - if ( mf ) - swap_dylib_table_of_contents(mach_toc.begin(), ntocs); - } - } - return mach_toc; -} - -//-------------------------------------------------------------------------- -const refvec_t &macho_file_t::get_ref_table() -{ - struct dysymtab_command dyst; - - if ( mach_reftable.empty() && get_dyst(&dyst) ) - { - if ( dyst.extrefsymoff >= mach_size ) - { - msg("reference table offset is past end of file\n"); - } - else - { - size_t entrysize = sizeof(struct dylib_reference); - size_t nrefs = dyst.nextrefsyms; - size_t size = nrefs * entrysize; - if ( dyst.extrefsymoff + size > mach_size ) - { - msg("table of contents table extends past end of file\n"); - size = mach_size - dyst.extrefsymoff; - nrefs = size / entrysize; - size = nrefs * entrysize; - } - qlseek(li, start_offset + mach_offset + dyst.extrefsymoff); - mach_reftable.resize(nrefs); - qlread(li, mach_reftable.begin(), size); - if ( mf ) - swap_dylib_reference(&mach_reftable[0], nrefs); - } - } - return mach_reftable; -} - -//-------------------------------------------------------------------------- -inline bool is_zeropage(const segment_command_64 &sg) -{ - return sg.vmaddr == 0 && sg.fileoff == 0 && sg.initprot == 0; -} - -//-------------------------------------------------------------------------- -inline bool is_text_segment(const segment_command_64 &sg) -{ - if ( is_zeropage(sg) ) - return false; - const char *name = sg.segname; - for ( int i=0; i < sizeof(sg.segname); i++, name++ ) - if ( *name != '_' ) - break; - return strnicmp(name, "TEXT", 4) == 0; -} - -//-------------------------------------------------------------------------- -inline bool is_linkedit_segment(const segment_command_64 &sg) -{ - return strnicmp(sg.segname, SEG_LINKEDIT, sizeof(SEG_LINKEDIT)-1) == 0; -} - -//-------------------------------------------------------------------------- -// load chunk of data from the linkedit section -bool macho_file_t::load_linkedit_data( - uint32 offset, - size_t *size, - void *buffer) -{ - if ( *size == 0 ) - return true; - - sval_t linkedit_shift = 0; - if ( is_mem_image() ) - { - // calculate shift between linkedit's segment file offset and memory address - // so that we will seek to the correct address in memory - for ( size_t i = 0; i < mach_segcmds.size(); i++ ) - { - const segment_command_64 &sg64 = mach_segcmds[i]; - if ( base_addr == BADADDR64 && sg64.fileoff == 0 && sg64.filesize != 0 ) - base_addr = sg64.vmaddr; - else if ( is_linkedit_segment(sg64) && linkedit_shift == 0 ) - linkedit_shift = sval_t(sg64.vmaddr - base_addr - sg64.fileoff); - } - } - if ( offset >= mach_size ) - return false; // outside file - if ( offset + *size > mach_size ) - *size = mach_size - offset; - if ( *size == 0 ) - return false; - qlseek(li, start_offset + mach_offset + linkedit_shift + offset); - *size = qlread(li, buffer, *size); - return true; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_uuid(uint8 uuid[16]) -{ - struct ida_local uuid_getter_t : public macho_lc_visitor_t - { - uint8 *buf; - bool retrieved; - uuid_getter_t(uint8 *_buf) : buf(_buf), retrieved(false) {} - virtual int visit_uuid( - const struct uuid_command *cmnd, - const char *, - const char *) override - { - memmove(buf, cmnd->uuid, 16); - retrieved = true; - return 0; - } - }; - uuid_getter_t uuid_getter(uuid); - visit_load_commands(uuid_getter); - return uuid_getter.retrieved; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::match_uuid(const bytevec_t &bytes) -{ - if ( bytes.size() != 16 ) - return false; - - uint8 uuid[16]; - - return get_uuid(uuid) && memcmp(uuid, bytes.begin(), sizeof(uuid)) == 0; -} - -//-------------------------------------------------------------------------- -static void get_platform_version( - macho_platform_version_t *mpv, - uint32 version_mask, - uint32 platform_id) -{ - mpv->plfm = platform_id; - mpv->major = uint16(version_mask >> 16); - mpv->minor = uint8(version_mask >> 8); - mpv->micro = uint8(version_mask); -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_platform_version_info(macho_platform_version_info_t *mpvi) -{ - struct ida_local version_finder_t : public macho_lc_visitor_t - { - macho_platform_version_info_t *mpvi; - bool has_version_info; - - version_finder_t(macho_platform_version_info_t *_mpvi) - : mpvi(_mpvi), has_version_info(false) {} - - int visit_build_version( - const struct build_version_command *bvc, - const char *, - const char *) override - { - get_platform_version(&mpvi->build_minos, bvc->minos, bvc->platform); - get_platform_version(&mpvi->build_sdk, bvc->sdk, bvc->platform); - has_version_info = true; - return 0; - } - - int visit_version_min( - const struct version_min_command *vmc, - const char *, - const char *) override - { - uint32 plfm; - switch ( vmc->cmd ) - { - case LC_VERSION_MIN_MACOSX: plfm = PLATFORM_MACOS; break; - case LC_VERSION_MIN_IPHONEOS: plfm = PLATFORM_IOS; break; - case LC_VERSION_MIN_WATCHOS: plfm = PLATFORM_WATCHOS; break; - case LC_VERSION_MIN_TVOS: plfm = PLATFORM_TVOS; break; - default: return 0; - } - get_platform_version(&mpvi->min_version, vmc->version, plfm); - get_platform_version(&mpvi->min_sdk, vmc->sdk, plfm); - has_version_info = true; - return 0; - } - }; - - version_finder_t vf(mpvi); - visit_load_commands(vf); - - return vf.has_version_info; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_symtab_command(struct symtab_command *st) -{ - struct myvisitor: macho_lc_visitor_t - { - struct symtab_command *st; - - myvisitor(struct symtab_command *st_): st(st_) {} - - virtual int visit_symtab( - const struct symtab_command *s, - const char *, - const char *) override - { - *st = *s; - return 1; - } - }; - - myvisitor v(st); - return visit_load_commands(v); -} - -//-------------------------------------------------------------------------- -void macho_file_t::get_symbol_table( - const struct symtab_command &st, - nlistvec_t *symbols) -{ - if ( st.symoff >= mach_size ) - { - // dyldcache branch islands tend to have bogus symbol info. it is not interesting. - if ( !is_branch_island() ) - msg("WARNING: symbol table offset is past end of file\n"); - } - else - { - size_t size = st.nsyms * (m64 ? sizeof(struct nlist_64) : sizeof(struct nlist)); - size_t nsymbols; - size_t stend = st.symoff + size; - if ( stend < st.symoff || stend > mach_size ) - { - if ( !is_branch_island() ) - msg("WARNING: symbol table extends past end of file\n"); - size = mach_size - st.symoff; - nsymbols = size / (m64 ? sizeof(struct nlist_64) : sizeof(struct nlist)); - } - else - { - nsymbols = st.nsyms; - } - - if ( nsymbols != 0 ) - { - symbols->resize(nsymbols); - struct nlist_64 *symbeg = symbols->begin(); - if ( m64 ) - { - size = sizeof(struct nlist_64) * nsymbols; - load_linkedit_data(st.symoff, &size, symbeg); - if ( mf ) - swap_nlist_64(symbeg, symbeg, nsymbols); - } - else - { - qvector<struct nlist> syms32; - syms32.resize(nsymbols); - size = sizeof(struct nlist) * nsymbols; - load_linkedit_data(st.symoff, &size, &syms32[0]); - nlist_to64(&syms32[0], symbeg, nsymbols, mf); - } - } - } -} - -//-------------------------------------------------------------------------- -void macho_file_t::get_string_table( - const struct symtab_command &st, - qstring *strings) -{ - if ( st.stroff >= mach_size ) - { - // dyldcache branch islands tend to have bogus symbol info. it is not interesting. - if ( !is_branch_island() ) - msg("WARNING: string table offset is past end of file\n"); - } - else - { - size_t strings_size; - size_t stend = st.stroff + st.strsize; - if ( stend < st.stroff || stend > mach_size ) - { - if ( !is_branch_island() ) - msg("WARNING: string table extends past end of file\n"); - strings_size = mach_size - st.stroff; - } - else - { - strings_size = st.strsize; - } - - string_table_waitbox_t wb(*this); - - for ( size_t off = 0; off < strings_size && !wb.cancelled(); ) - { - size_t chunksize = qmin(32*1024, strings_size - off); - strings->resize(strings->size()+chunksize); - - size_t newsize = chunksize; - load_linkedit_data(st.stroff+off, &newsize, &strings->at(off)); - - off += chunksize; - } - } -} - -//-------------------------------------------------------------------------- -void macho_file_t::get_symbol_table_info(nlistvec_t *symbols, qstring *strings) -{ - symbols->clear(); - strings->clear(); - - struct symtab_command st = { 0 }; - if ( get_symtab_command(&st) ) - { - get_symbol_table(st, symbols); - get_string_table(st, strings); - } -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_dyst(struct dysymtab_command *dyst) -{ - struct myvisitor: macho_lc_visitor_t - { - struct dysymtab_command *dyst; - - myvisitor(struct dysymtab_command *dyst_): dyst(dyst_) - { - dyst->cmd = 0; - } - - virtual int visit_dysymtab( - const struct dysymtab_command *s, - const char *, - const char *) override - { - *dyst = *s; - return 1; - } - }; - - myvisitor v(dyst); - return visit_load_commands(v); -} - -//-------------------------------------------------------------------------- -/* - * get_indirect_symbol_table_info() returns indirect symbols. It handles the - * problems related to the file being truncated and only returns valid info. - * This routine may return misaligned pointers and it is up to - * the caller to deal with alignment issues. - */ -void macho_file_t::get_indirect_symbol_table_info(qvector<uint32> *indirect_symbols) -{ - struct dysymtab_command dyst; - - indirect_symbols->clear(); - - if ( !get_dyst(&dyst) ) - return; - - if ( dyst.indirectsymoff >= mach_size ) - { - // dyldcache branch islands tend to have bogus symbol info. it is not interesting. - if ( !is_branch_island() ) - msg("indirect symbol table offset is past end of file\n"); - } - else - { - size_t size = dyst.nindirectsyms * sizeof(uint32); - size_t nindirect_symbols = dyst.nindirectsyms; - if ( dyst.indirectsymoff + size > mach_size ) - { - if ( !is_branch_island() ) - msg("indirect symbol table extends past end of file\n"); - size = mach_size - dyst.indirectsymoff; - nindirect_symbols = size / sizeof(uint32); - size = nindirect_symbols * sizeof(uint32); - } - indirect_symbols->resize(nindirect_symbols); - qlseek(li, start_offset + mach_offset + dyst.indirectsymoff); - qlread(li, indirect_symbols->begin(), size); - if ( mf ) - swap_indirect_symbols(indirect_symbols->begin(), nindirect_symbols); - } -} - -//-------------------------------------------------------------------------- -size_t macho_file_t::get_import_info( - impvec_t *imports, - dyliblist_t *dylibs, - rangeset_t *ranges, - bool verbose) -{ - bool l64 = is64(); - - imports->qclear(); - const secvec_t §ions = get_sections(); - *dylibs = get_dylib_list(); - - // get the symbol table - nlistvec_t symbols; - qstring strings; - get_symbol_table_info(&symbols, &strings); - - // get indirect symbol table - qvector<uint32> indirect_symbols; - get_indirect_symbol_table_info(&indirect_symbols); - uint32 ptrsize = l64 ? 8 : 4; - uint32 stride; - for ( size_t i = 0; i < sections.size(); i++ ) - { - const section_64 § = sections[i]; - ranges->add(range_t(sect.addr, sect.addr+sect.size)); - - uint32 section_type = sections[i].flags & SECTION_TYPE; - if ( section_type != S_LAZY_SYMBOL_POINTERS - && section_type != S_NON_LAZY_SYMBOL_POINTERS ) - { - continue; - } - - stride = ptrsize; - size_t count = sect.size / stride; - if ( verbose ) - msg("\n\nChecking indirect symbols for (%.16s,%.16s): %" FMT_Z " entries", - sect.segname, - sect.sectname, - count); - - uint32 n = sections[i].reserved1; - if ( verbose ) - msg("\naddress index name\n"); - for ( size_t j = 0; j < count && n + j < indirect_symbols.size(); j++ ) - { - uint64_t addr = sect.addr + uint64_t(j) * stride; - if ( verbose ) - { - if ( l64 ) - msg("0x%016" FMT_64 "x ", addr); - else - msg("0x%08x ", (uint)addr); - } - uint32 symidx = indirect_symbols[j + n]; - if ( ( symidx & ( INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS ) ) != 0 ) - continue; - if ( verbose ) - msg("%5u ", symidx); - if ( symidx >= symbols.size() ) - continue; - const struct nlist_64 &nl = symbols[symidx]; - int type = nl.n_type & N_TYPE; - if ( type == N_UNDF ) - { - uint32 libno = GET_LIBRARY_ORDINAL(nl.n_desc); - if ( libno != SELF_LIBRARY_ORDINAL - && libno != DYNAMIC_LOOKUP_ORDINAL - && libno != EXECUTABLE_ORDINAL ) - { - if ( nl.n_un.n_strx >= strings.size() ) - { - if ( verbose ) - msg("?\n"); - } - else - { - const char *symname = &strings[nl.n_un.n_strx]; - if ( verbose ) - msg("UNDF: %s from dylib %u\n", symname, libno); - import_info_t &ii = imports->push_back(); - ii.impea = addr; - ii.dylib = libno; - ii.name = symname; - } - } - } - } - } - return imports->size(); -} - -//-------------------------------------------------------------------------- -// load array of relocs from file with range checking and endianness swapping -bool macho_file_t::load_relocs( - uint32 reloff, - uint32 nreloc, - relocvec_t *relocs, - const char *desc) -{ - validate_array_count(NULL, &nreloc, sizeof(relocation_info), desc, reloff, mach_size); - relocs->qclear(); - relocs->resize(nreloc); - size_t size = nreloc * sizeof(relocation_info); - qlseek(li, start_offset + mach_offset + reloff); - if ( qlread(li, relocs->begin(), size) != size ) - { - relocs->qclear(); - return false; - } - if ( mf ) - swap_relocation_info(relocs->begin(), nreloc); - return true; -} - -//-------------------------------------------------------------------------- -void macho_file_t::visit_relocs(macho_reloc_visitor_t &v) -{ - if ( qgetenv("IDA_NORELOC") ) - return; - - struct dysymtab_command dyst; - uint64 baseea = 0; -/* - (from Mach-O spec) - r_address - In images used by the dynamic linker, this is an offset from the virtual memory address of the - data of the first segment_command (page 20) that appears in the file (not necessarily the one - with the lowest address). For images with the MH_SPLIT_SEGS flag set, this is an offset from - the virtual memory address of data of the first read/write segment_command (page 20). -*/ - - // we check for first writable segment if MH_SPLIT_SEGS is set - // or on x64 (see ImageLoaderMachOClassic::getRelocBase() in dyld sources) - // NB: in MH_KEXT_BUNDLE (processed by kernel kxld) r_address is still based on the first segment/0! - - bool need_writable = false; - bool is_dyld_file = mh.filetype == MH_EXECUTE - || mh.filetype == MH_DYLINKER - || mh.filetype == MH_BUNDLE; - if ( (mh.flags & MH_SPLIT_SEGS) != 0 || is_dyld_file && mh.cputype == CPU_TYPE_X86_64 ) - { - need_writable = true; - } - for ( size_t i=0; i < mach_segcmds.size(); i++ ) - { - if ( !need_writable - || (mach_segcmds[i].initprot & (VM_PROT_WRITE|VM_PROT_READ)) == (VM_PROT_WRITE|VM_PROT_READ) ) - { - baseea = mach_segcmds[i].vmaddr; - break; - } - } - - relocvec_t relocs; - if ( get_dyst(&dyst) && dyst.cmd != 0 ) - { - // External relocation information - uint32 nrelocs = dyst.nextrel; - if ( nrelocs > 0 && load_relocs(dyst.extreloff, nrelocs, &relocs, "Number of dynamic external relocs") ) - { - v.visit_relocs(baseea, relocs, macho_reloc_visitor_t::mach_reloc_external); - } - // Local relocation information - nrelocs = dyst.nlocrel; - if ( nrelocs > 0 && load_relocs(dyst.locreloff, nrelocs, &relocs, "Number of dynamic local relocs") ) - { - v.visit_relocs(baseea, relocs, macho_reloc_visitor_t::mach_reloc_local); - } - } - - // Section relocation information - for ( size_t i = 0; i < mach_sections.size(); i++ ) - { - if ( mach_sections[i].nreloc == 0 ) - continue; - - char name[80]; - qsnprintf(name, sizeof(name), "Number of relocs for section (%.16s,%.16s)", mach_sections[i].segname, mach_sections[i].sectname); - uint32 nrelocs = mach_sections[i].nreloc; - if ( nrelocs > 0 && load_relocs(mach_sections[i].reloff, nrelocs, &relocs, name) ) - { - v.visit_relocs(mach_sections[i].addr, relocs, i); - } - } -} - -//-------------------------------------------------------------------------- -bool macho_file_t::getSegInfo(uint64_t *segStartAddr, uint64_t *segSize, int segIndex) -{ - segment_command_64 seg; - if ( !get_segment(segIndex, &seg) ) - return false; - *segStartAddr = seg.vmaddr; - *segSize = seg.vmsize; - return true; -} - -//-------------------------------------------------------------------------- -static bool display_wrong_uleb(const uchar *p) -{ -#ifdef EFD_COMPILE - - printf( - "wrong uleb128/sleb128 encoding: %02X %02X %02X %02X %02X\n", - p[0], p[1], p[2], p[3], p[4]); - -#else - - deb(IDA_DEBUG_LDR, - "wrong uleb128/sleb128 encoding: %02X %02X %02X %02X %02X\n", - p[0], p[1], p[2], p[3], p[4]); - -#endif - - return false; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::visit_rebase_opcodes(const bytevec_t &data, dyld_info_visitor_t &v) -{ - const uchar *begin = &data[0]; - const uchar *end = begin + data.size(); - const uchar *p = begin; - bool done = false; - uint64_t ulebv, ulebv2; - const int ptrsize = is64() ? 8 : 4; - - int segIndex; - uint64_t segOffset = 0; - uchar type = REBASE_TYPE_POINTER; - uint64_t segStartAddr = BADADDR64; - uint64_t segSize = BADADDR64; - - while ( !done && p < end ) - { - uchar opcode = *p & REBASE_OPCODE_MASK; - uchar imm = *p & REBASE_IMMEDIATE_MASK; - p++; - switch ( opcode ) - { - case REBASE_OPCODE_DONE: - done = true; - break; - case REBASE_OPCODE_SET_TYPE_IMM: - type = imm; - break; - case REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: - if ( !unpack_uleb128(&ulebv, &p, end) ) -WRONG_ULEB: - return display_wrong_uleb(p); - segIndex = imm; - segOffset = ulebv; - segStartAddr = BADADDR64; - segSize = BADADDR64; - getSegInfo(&segStartAddr, &segSize, segIndex); - break; - case REBASE_OPCODE_ADD_ADDR_ULEB: - { - uint64 delta; - if ( !unpack_uleb128(&delta, &p, end) ) - goto WRONG_ULEB; - segOffset += delta; - } - break; - case REBASE_OPCODE_ADD_ADDR_IMM_SCALED: - segOffset += imm * ptrsize; - break; - case REBASE_OPCODE_DO_REBASE_IMM_TIMES: - if ( imm > segSize ) - { - deb(IDA_DEBUG_LDR, "bad immediate value %02X in rebase info!\n", imm); - return false; - } - if ( segStartAddr == BADADDR64 ) - { -WRONG_REBASE: - msg("Wrong rebase info, file possibly corrupted!\n"); - return false; - } - for ( int i = 0; i < imm; i++ ) - { - uint64 addr = segStartAddr + segOffset; - if ( !is_loaded_addr(addr) ) - goto WRONG_REBASE; - v.visit_rebase(addr, type); - segOffset += ptrsize; - } - break; - case REBASE_OPCODE_DO_REBASE_ULEB_TIMES: - if ( !unpack_uleb128(&ulebv, &p, end) ) - goto WRONG_ULEB; - if ( ulebv > segSize ) - goto WRONG_ULEB; - if ( segStartAddr == BADADDR64 ) - goto WRONG_REBASE; - for ( size_t i = 0; i < ulebv; i++ ) - { - uint64 addr = segStartAddr + segOffset; - if ( !is_loaded_addr(addr) ) - goto WRONG_REBASE; - v.visit_rebase(addr, type); - segOffset += ptrsize; - } - break; - case REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: - if ( !unpack_uleb128(&ulebv, &p, end) ) - goto WRONG_ULEB; - v.visit_rebase(uint64_t(segStartAddr + segOffset), type); - segOffset += ulebv + ptrsize; - break; - case REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: - if ( !unpack_uleb128(&ulebv, &p, end) ) - goto WRONG_ULEB; - if ( !unpack_uleb128(&ulebv2, &p, end) ) - goto WRONG_ULEB; - if ( ulebv > segSize || ulebv2 > segSize ) - goto WRONG_ULEB; - if ( segStartAddr == BADADDR64 ) - goto WRONG_REBASE; - for ( size_t i = 0; i < ulebv; i++ ) - { - uint64 addr = segStartAddr + segOffset; - if ( !is_loaded_addr(addr) ) - goto WRONG_REBASE; - v.visit_rebase(addr, type); - segOffset += ptrsize + ulebv2; - } - break; - default: - deb(IDA_DEBUG_LDR, "bad opcode %02X in rebase info!\n", opcode); - return false; - } - } - return true; -} - - -struct ThreadedBindData -{ - const char *symbolName; - int64 addend; - int64 libraryOrdinal; - uchar type; - uchar symboFlags; -}; - -//-------------------------------------------------------------------------- -bool macho_file_t::visit_bind_opcodes( - dyld_info_visitor_t::bind_kind_t bind_kind, - const bytevec_t &data, - dyld_info_visitor_t &v) -{ - const uchar *begin = &data[0]; - const uchar *end = begin + data.size(); - const uchar *p = begin; - uint64 skip; - uint64 count; - const int ptrsize = is64() ? 8 : 4; - - int segIndex; - char type = BIND_TYPE_POINTER; - uchar flags = 0; - uint64 libOrdinal = BIND_SPECIAL_DYLIB_SELF; - int64_t addend = 0; - const char *symbolName = NULL; - uint64_t segStartAddr = BADADDR64; - uint64_t segOffset = 0; - uint64_t segSize = BADADDR64; - - bool done = false; - bool threaded = false; - qvector<ThreadedBindData> allsyms; - while ( !done && p < end ) - { - uchar opcode = *p & BIND_OPCODE_MASK; - uchar imm = *p & BIND_IMMEDIATE_MASK; - p++; - switch ( opcode ) - { - case BIND_OPCODE_DONE: - if ( bind_kind != dyld_info_visitor_t::bind_kind_lazy ) - done = true; - break; - case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: - libOrdinal = imm; - break; - case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: - if ( !unpack_uleb128(&libOrdinal, &p, end) ) -WRONG_ULEB: - return display_wrong_uleb(p); - break; - case BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: - // the special ordinals are negative numbers - if ( imm == 0 ) - { - libOrdinal = 0; - } - else - { - int8_t signExtended = BIND_OPCODE_MASK | imm; - libOrdinal = signExtended; - } - break; - case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: - flags = imm; - symbolName = (const char*)p; - while ( *p != '\0' ) - ++p; - ++p; - break; - case BIND_OPCODE_SET_TYPE_IMM: - type = imm; - break; - case BIND_OPCODE_SET_ADDEND_SLEB: - if ( !unpack_sleb128(&addend, &p, end) ) - goto WRONG_ULEB; - break; - case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: - segIndex = imm; - if ( !unpack_uleb128(&segOffset, &p, end) ) - goto WRONG_ULEB; - segStartAddr = BADADDR64; - segSize = BADADDR64; - getSegInfo(&segStartAddr, &segSize, segIndex); - break; - case BIND_OPCODE_ADD_ADDR_ULEB: - if ( !unpack_uleb128(&skip, &p, end) ) - goto WRONG_ULEB; - segOffset += skip; - break; - case BIND_OPCODE_DO_BIND: - { - uint64 addr = segStartAddr + segOffset; - if ( threaded ) - { - ThreadedBindData &d = allsyms.push_back(); - d.addend = addend; - d.symbolName = symbolName; - d.libraryOrdinal = libOrdinal; - d.symboFlags = flags; - d.type = type; - } - else - { - v.visit_bind(bind_kind, addr, type, flags, libOrdinal, addend, symbolName); - } - segOffset += ptrsize; - } - break; - case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: - { - uint64 addr = segStartAddr + segOffset; - if ( !unpack_uleb128(&skip, &p, end) ) - goto WRONG_ULEB; - v.visit_bind(bind_kind, addr, type, flags, libOrdinal, addend, symbolName); - segOffset += skip + ptrsize; - } - break; - case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: - { - uint64 addr = segStartAddr + segOffset; - skip = imm*ptrsize + ptrsize; - v.visit_bind(bind_kind, addr, type, flags, libOrdinal, addend, symbolName); - segOffset += skip; - } - break; - case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: - if ( !unpack_uleb128(&count, &p, end) ) - goto WRONG_ULEB; - if ( !unpack_uleb128(&skip, &p, end) ) - goto WRONG_ULEB; - if ( count > segSize || skip > segSize ) - goto WRONG_ULEB; - { - int i = 0; - if ( symbolName != NULL && segStartAddr != BADADDR64 ) - { - for ( ; i < count; i++ ) - { - uint64 addr = segStartAddr + segOffset; - if ( !is_loaded_addr(addr) ) - { - msg("Warning: reference to wrong address %" FMT_64 "x\n", addr); - break; // exported function must have initialized bytes - } - v.visit_bind(bind_kind, addr, type, flags, libOrdinal, addend, symbolName); - segOffset += skip + ptrsize; - } - } - segOffset += (count - i) * (skip + ptrsize); - } - break; - case BIND_OPCODE_THREADED: - if ( imm == BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB ) - { - threaded = true; - uint64 maxnum; - if ( !unpack_uleb128(&maxnum, &p, end) ) - count = -1; - - allsyms.clear(); - } - else if ( imm == BIND_SUBOPCODE_THREADED_APPLY ) - { - int delta = 0; - do - { - uint64 addr = segStartAddr + segOffset; - uint64 raw_value = read_addr_at_va(addr); - if ( raw_value != BADADDR64 ) - { - tagged_pointer64 tp(raw_value); - if ( tp.is_auth() ) - { - static const char *key_names[4] = { "IA", "IB", "DA", "DB" }; - deb(IDA_DEBUG_LDR, "%a: JOP diversity 0x%04X, address %s, key %s", ea_t(addr), tp.diversity(), tp.is_addr() ? "true" : "false", key_names[tp.key_index()]); - } - if ( tp.is_bind() ) - { - uint16 symidx = uint16(raw_value); - if ( symidx < allsyms.size() ) - { - const ThreadedBindData &d = allsyms[symidx]; - type = tp.is_auth() ? BIND_TYPE_THREADED_POINTER_AUTH : BIND_TYPE_THREADED_POINTER; - v.visit_bind(bind_kind, addr, type, d.symboFlags, d.libraryOrdinal, d.addend, d.symbolName); - } - } - else - { - type = tp.is_auth() ? BIND_TYPE_THREADED_REBASE_AUTH : BIND_TYPE_THREADED_REBASE; - v.visit_bind(bind_kind, addr, type, 0, -3, tp.untag(get_base()), (const char*)&tp); - } - delta = tp.skip_count(); - segOffset += delta * 8; - } - } while ( delta != 0 ); - } - break; - default: - msg("Warning: bad rebase opcode found (0x%02X), file possibly corrupted!\n", opcode); - return false; - } - } - return true; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::processExportNode( - const uchar *start, - const uchar *p, - const uchar *end, - char *symname, - int symnameoff, - size_t symnamelen, - dyld_info_visitor_t &v, - int level) -{ - if ( symnameoff >= symnamelen || p >= end || p < start ) - return false; - if ( level >= MAX_DEPTH ) - return false; - const uchar terminalSize = unpack_db(&p, end); - const uchar *children = p + terminalSize; - if ( children >= end ) - return false; - if ( terminalSize != 0 ) - { - if ( symnameoff == 0 ) // no name?? - return false; - uint64_t flags; - uint64_t address; - if ( !unpack_uleb128(&flags, &p, end) || !unpack_uleb128(&address, &p, end) ) - return display_wrong_uleb(p); - if ( base_addr != BADADDR64 && (flags & EXPORT_SYMBOL_FLAGS_REEXPORT) == 0 ) - address += base_addr; - if ( v.visit_export(address, uint32(flags), symname) != 0 ) - return true; - } - const uchar childrenCount = unpack_db(&children, end); - const uchar *s = children; - for ( int i=0; i < childrenCount && s < end; ++i ) - { - int edgeStrLen = 0; - int maxlen = symnamelen - symnameoff; - for ( uchar c = unpack_db(&s, end); - c != '\0' && edgeStrLen < maxlen; - ++edgeStrLen, c = unpack_db(&s, end) ) - { - symname[symnameoff+edgeStrLen] = c; - } - if ( edgeStrLen >= maxlen ) - return false; - if ( symnameoff == 0 && edgeStrLen == 0 ) // empty symbol?? - return false; - symname[symnameoff+edgeStrLen] = '\0'; - uint64 ulebv; - if ( !unpack_uleb128(&ulebv, &s, end) ) - return display_wrong_uleb(s); - uint32_t childNodeOffset = (uint32_t)ulebv; - if ( childNodeOffset == 0 - || childNodeOffset != ulebv - || !processExportNode(start, start+childNodeOffset, end, - symname, symnameoff+edgeStrLen, symnamelen, - v, level+1) ) - { - return false; - } - } - return true; -} - -//-------------------------------------------------------------------------- -bool macho_file_t::visit_export_info(const bytevec_t &data, dyld_info_visitor_t &v) -{ - char symname[MAXSTR*2]; - const uchar *begin = &data[0]; - const uchar *end = begin + data.size(); - symname[0] = '\0'; - if ( !processExportNode(begin, begin, end, symname, 0, sizeof(symname), v) ) - { - warning("Bad information in exports, it will be ignored."); - return false; - } - return true; -} - - -//-------------------------------------------------------------------------- -void macho_file_t::visit_dyld_info(dyld_info_visitor_t &v) -{ - struct ida_local myvisitor: macho_lc_visitor_t - { - struct dyld_info_command *di; - - myvisitor(struct dyld_info_command *di_): di(di_) - { - di->cmd = 0; - } - - virtual int visit_dyld_info( - const struct dyld_info_command *lc, - const char *, - const char *) override - { - *di = *lc; - return 1; - } - }; - - dyld_info_command di; - myvisitor vdi(&di); - if ( visit_load_commands(vdi) ) - { - bytevec_t data; - if ( di.rebase_size != 0 ) - { - data.resize(di.rebase_size); - size_t newsize = di.rebase_size; - if ( load_linkedit_data(di.rebase_off, &newsize, &data[0]) && newsize != 0 ) - visit_rebase_opcodes(data, v); - else - msg("Error loading dyld rebase info\n"); - } - if ( di.bind_size != 0 ) - { - data.resize(di.bind_size); - size_t newsize = di.bind_size; - if ( load_linkedit_data(di.bind_off, &newsize, &data[0]) && newsize != 0 ) - visit_bind_opcodes(dyld_info_visitor_t::bind_kind_normal, data, v); - else - msg("Error loading dyld bind info\n"); - } - if ( di.weak_bind_size != 0 ) - { - data.resize(di.weak_bind_size); - size_t newsize = di.weak_bind_size; - if ( load_linkedit_data(di.weak_bind_off, &newsize, &data[0]) && newsize != 0 ) - visit_bind_opcodes(dyld_info_visitor_t::bind_kind_weak, data, v); - else - msg("Error loading dyld weak bind info\n"); - } - if ( di.lazy_bind_size != 0 ) - { - data.resize(di.lazy_bind_size); - size_t newsize = di.lazy_bind_size; - if ( load_linkedit_data(di.lazy_bind_off, &newsize, &data[0]) && newsize != 0 ) - visit_bind_opcodes(dyld_info_visitor_t::bind_kind_lazy, data, v); - else - msg("Error loading dyld lazy bind info\n"); - } - if ( di.export_size != 0 ) - { - data.resize(di.export_size); - size_t newsize = di.export_size; - if ( load_linkedit_data(di.export_off, &newsize, &data[0]) && newsize != 0 ) - visit_export_info(data, v); - else - msg("Error loading dyld export info\n"); - } - } -} - -//-------------------------------------------------------------------------- -void function_starts_visitor_t::handle_error() -{ - msg("Error loading function starts info\n"); -} - -//-------------------------------------------------------------------------- -void macho_file_t::visit_function_starts(function_starts_visitor_t &v) -{ - struct myvisitor: macho_lc_visitor_t - { - struct linkedit_data_command *fs; - - myvisitor(struct linkedit_data_command *fs_): fs(fs_) - { - fs->cmd = 0; - } - - virtual int visit_linkedit_data( - const struct linkedit_data_command *lc, - const char *, - const char *) override - { - if ( lc->cmd == LC_FUNCTION_STARTS ) - { - *fs = *lc; - return 1; - } - return 0; - } - }; - - linkedit_data_command fs; - myvisitor vfs(&fs); - if ( visit_load_commands(vfs) && fs.datasize != 0 ) - { - bytevec_t data; - data.resize(fs.datasize); - size_t newsize = fs.datasize; - if ( !load_linkedit_data(fs.dataoff, &newsize, data.begin()) || newsize == 0 ) - { - v.handle_error(); - return; - } - uint64_t address = base_addr != BADADDR64 ? base_addr : 0; - const uchar *p = data.begin(); - const uchar *end = p + newsize; - while ( p < end ) - { - uint64_t delta; - if ( !unpack_uleb128(&delta, &p, end) ) - { - display_wrong_uleb(p); - v.handle_error(); - return; - } - address += delta; - v.visit_start(address); - } - } -} - -//-------------------------------------------------------------------------- -void macho_file_t::visit_shared_regions(shared_region_visitor_t &v) -{ - struct myvisitor: macho_lc_visitor_t - { - struct linkedit_data_command *sr; - - myvisitor(struct linkedit_data_command *sr_): sr(sr_) - { - sr->cmd = 0; - } - - virtual int visit_linkedit_data( - const struct linkedit_data_command *lc, - const char *, - const char *) override - { - if ( lc->cmd == LC_SEGMENT_SPLIT_INFO ) - { - *sr = *lc; - return 1; - } - return 0; - } - }; - - linkedit_data_command sr; - myvisitor vsr(&sr); - if ( visit_load_commands(vsr) && sr.datasize != 0 ) - { - bytevec_t data; - data.resize(sr.datasize); - size_t newsize = sr.datasize; - if ( !load_linkedit_data(sr.dataoff, &newsize, &data[0]) || newsize == 0 ) - { - msg("Error loading segment split info\n"); - return; - } - uint64_t base = base_addr != BADADDR64 ? base_addr : 0; - const uchar *p = &data[0]; - const uchar *end = p + data.size(); - // see void DyldInfoPrinter<A>::printSharedRegionInfo() in ld64 src/other/dyldinfo.cpp - if ( *p == DYLD_CACHE_ADJ_V2_FORMAT ) - { - p++; - // Whole :== <count> FromToSection+ - // FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+ - // ToOffset :== <to-sect-offset-delta> <count> FromOffset+ - // FromOffset :== <kind> <count> <from-sect-offset-delta> - uint64 sectionCount; - if ( !unpack_uleb128(§ionCount, &p, end) ) - { -WRONG_ULEB2: - display_wrong_uleb(p); - return; - } - for ( uint64 i = 0; i < sectionCount; i++ ) - { - uint64 fromSectionIndex, toSectionIndex, toOffsetCount; - section_64 fromsect, tosect; - memset(&fromsect, 0, sizeof(fromsect)); - memset(&tosect, 0, sizeof(tosect)); - - if ( !unpack_uleb128(&fromSectionIndex, &p, end) - || !unpack_uleb128(&toSectionIndex, &p, end) - || !unpack_uleb128(&toOffsetCount, &p, end) ) - { - goto WRONG_ULEB2; - } - - if ( !get_section_or_hdr(&fromsect, fromSectionIndex) - || !get_section_or_hdr(&tosect, toSectionIndex) ) - { -#ifdef EFD_COMPILE - printf("from sect=%" FMT_64 "d, to sect=%" FMT_64 "d, count=%" FMT_64 "d:\n", fromSectionIndex, toSectionIndex, toOffsetCount); - printf(" bad section index!\n"); -#endif - return; - } - uint64 toSectionOffset = 0; - for ( uint64 j = 0; j < toOffsetCount; ++j ) - { - uint64 toSectionDelta; - uint64 fromOffsetCount; - if ( !unpack_uleb128(&toSectionDelta, &p, end) - || !unpack_uleb128(&fromOffsetCount, &p, end) ) - { - goto WRONG_ULEB2; - } - toSectionOffset += toSectionDelta; - for ( uint64 k = 0; k < fromOffsetCount; ++k ) - { - uint64 kind, fromSectDeltaCount; - uint64 fromSectionOffset = 0; - if ( !unpack_uleb128(&kind, &p, end) - || !unpack_uleb128(&fromSectDeltaCount, &p, end) ) - { - goto WRONG_ULEB2; - } - for ( uint64 l = 0; l < fromSectDeltaCount; ++l ) - { - uint64_t delta; - if ( !unpack_uleb128(&delta, &p, end) ) - goto WRONG_ULEB2; - fromSectionOffset += delta; - int ok = v.visit_regionv2(kind, fromsect.addr + fromSectionOffset, tosect.addr + toSectionOffset); - if ( ok != 0 ) - return; - } - } - } - } - } - while ( p < end ) - { - uchar kind = unpack_db(&p, end); - if ( p >= end ) - return; - uint64_t address = 0; - uint64_t delta; - if ( !unpack_uleb128(&delta, &p, end) ) - { -WRONG_ULEB1: - display_wrong_uleb(p); - return; - } - while ( p < end && delta != 0 ) - { - address += delta; - int ok = v.visit_region(kind, base + address); - if ( ok != 0 ) - return; - if ( !unpack_uleb128(&delta, &p, end) ) - goto WRONG_ULEB1; - } - } - } -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_id_dylib(qstring *id) -{ - struct myvisitor: macho_lc_visitor_t - { - qstring *dyld_id; - bool found; - myvisitor(qstring *_id): dyld_id(_id), found(false) {} - - virtual int visit_dylib( - const struct dylib_command *dl, - const char *begin, - const char *end) override - { - if ( dl->cmd == LC_ID_DYLIB ) - { - const char *p = begin + dl->dylib.name.offset; - if ( p < end ) - *dyld_id = qstring(p, end-p); - found = true; - return 0; - } - return 1; - } - }; - - if ( id == NULL ) - return false; - myvisitor v(id); - visit_load_commands(v); - return v.found; -} - -//-------------------------------------------------------------------------- -/*const DYLDCache::ArchType DYLDCache::architectures[] = -{ - { CPU_TYPE_X86_64, CPU_SUBTYPE_MULTIPLE, "dyld_v1 x86_64", "x86_64", littleEndian }, - { CPU_TYPE_X86, CPU_SUBTYPE_MULTIPLE, "dyld_v1 i386", "i386", littleEndian }, - { CPU_TYPE_POWERPC, CPU_SUBTYPE_MULTIPLE, "dyld_v1 ppc", "rosetta", bigEndian }, - { CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V6, "dyld_v1 armv6", "armv6", littleEndian }, - { CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7, "dyld_v1 armv7", "armv7", littleEndian }, - { CPU_TYPE_ARM64, CPU_SUBTYPE_MULTIPLE, "dyld_v1 armv64","armv64", littleEndian }, - { 0 } -};*/ - -//-------------------------------------------------------------------------- -bool dyld_cache_t::open(const char *path) -{ - li = open_linput(path, false); - if ( li == NULL ) - return false; - should_close_linput = true; - return true; -} - -//-------------------------------------------------------------------------- -bool dyld_cache_t::parse_header(uint32 flags) -{ - if ( li == NULL ) - return false; - - qlseek(li, 0); - if ( qlread(li, &header, sizeof(header)) != sizeof(header) ) - return false; - if ( !strneq(header.magic, "dyld_v", strlen("dyld_v")) ) - return false; - if ( strneq(header.magic, "dyld_v0", strlen("dyld_v0")) ) - return false; - - // deduce endianness and bitness from the arch name - const char *p = strchr(header.magic, ' '); - while ( *p == ' ' ) - p++; - mf = strneq(p, "ppc", 3); - m64 = strneq(p, "x86_64", 6) || strneq(p, "arm64", 5); // x86_64(h) or arm64(e) - if ( header.mappingOffset <= offsetof(dyld_cache_header, slideInfoOffset) ) - { - // old format, without slide info - header.slideInfoOffset = header.slideInfoSize = 0; - } - if ( header.mappingOffset <= offsetof(dyld_cache_header, branchPoolsCount) ) - { - // no island info - header.branchPoolsOffset = header.branchPoolsCount = 0; - } - if ( header.mappingOffset <= offsetof(dyld_cache_header, imagesTextOffset) ) - { - // no text info - header.imagesTextOffset = header.imagesTextCount = 0; - } - - if ( (flags & PHF_MAPPINGS) != 0 ) - { - if ( qlseek(li, header.mappingOffset) != header.mappingOffset ) - return false; - mappings.resize(header.mappingCount); - validate_array_count_or_die(li, header.mappingCount, sizeof(dyld_cache_mapping_info), "count of cache mapping infos"); - if ( qlread(li, mappings.begin(), sizeof(dyld_cache_mapping_info) * header.mappingCount) != sizeof(dyld_cache_mapping_info) * header.mappingCount ) - return false; - - if ( header.mappingOffset <= offsetof(dyld_cache_header, maxSlide) + sizeof(uint64_t) ) - { - // no shared region/max slide info, set defaults - if ( mappings.size() > 2 ) - { - header.sharedRegionStart = mappings[0].address; - header.sharedRegionSize = 0x100000000LL; - header.maxSlide = header.sharedRegionSize - mappings[2].address - mappings[2].size + header.sharedRegionStart; - } - } - } - - if ( (flags & PHF_IMAGES) != 0 ) - { - if ( qlseek(li, header.imagesOffset) != header.imagesOffset ) - return false; - image_infos.resize(header.imagesCount); - validate_array_count_or_die(li, header.imagesCount, sizeof(dyld_cache_image_info), "count of images in the cache file"); - if ( qlread(li, image_infos.begin(), sizeof(dyld_cache_image_info) * header.imagesCount) != sizeof(dyld_cache_image_info) * header.imagesCount ) - return false; - for ( size_t i = 0; i < header.imagesCount; i++ ) - { - size_t name_off = image_infos[i].pathFileOffset; - char namebuf[MAXSTR]; - if ( qlgetz(li, name_off, namebuf, sizeof(namebuf)) == NULL ) - return false; - image_names.push_back(namebuf); - } - } - - if ( (flags & PHF_SYMBOLS) != 0 ) - { - parse_local_symbols(); - } - - if ( (flags & PHF_ISLANDS) != 0 && header.branchPoolsCount != 0 && header.branchPoolsOffset != 0 ) - { - if ( qlseek(li, header.branchPoolsOffset) != header.branchPoolsOffset ) - return false; - validate_array_count(li, &header.branchPoolsCount, sizeof(uint64), "branch islands entries count"); - island_addrs.resize(header.branchPoolsCount); - if ( qlread(li, island_addrs.begin(), sizeof(uint64) * header.branchPoolsCount) != sizeof(uint64) * header.branchPoolsCount ) - return false; - } - - if ( (flags & PHF_SLIDE) != 0 && header.slideInfoOffset != 0 && header.slideInfoSize != 0 ) - { - if ( qlseek(li, header.slideInfoOffset) != header.slideInfoOffset ) - return false; - if ( qlread(li, &slide_version, sizeof(slide_version)) != sizeof(slide_version) ) - return false; - if ( qlseek(li, header.slideInfoOffset) != header.slideInfoOffset ) - return false; - - if ( slide_version == 1 ) - { - dyld_cache_slide_info si; - if ( qlread(li, &si, sizeof(si)) != sizeof(si) ) - return false; - - slide_toc.resize(si.toc_count); - if ( qlseek(li, header.slideInfoOffset + si.toc_offset) != header.slideInfoOffset + si.toc_offset ) - return false; - validate_array_count_or_die(li, si.toc_count, sizeof(uint16), "Slide info TOC entries count"); - if ( qlread(li, slide_toc.begin(), sizeof(uint16) * si.toc_count) != sizeof(uint16) * si.toc_count ) - return false; - - slide_entries_size = si.entries_size; - slide_entries.resize(si.entries_count*si.entries_size); - if ( qlseek(li, header.slideInfoOffset + si.entries_offset) != header.slideInfoOffset + si.entries_offset ) - return false; - if ( qlread(li, slide_entries.begin(), slide_entries.size()) != slide_entries.size() ) - return false; - } - else if ( slide_version == 2 ) - { - dyld_cache_slide_info2 si; - if ( qlread(li, &si, sizeof(si)) != sizeof(si) ) - return false; - if ( si.page_size == 0 ) - return false; - - slide_page_size = si.page_size; - slide_delta_mask = si.delta_mask; - slide_value_add = si.value_add; - - slide_page_starts.resize(si.page_starts_count); - if ( qlseek(li, header.slideInfoOffset + si.page_starts_offset) != header.slideInfoOffset + si.page_starts_offset ) - return false; - validate_array_count_or_die(li, si.page_starts_count, sizeof(uint16), "Slide info page starts count"); - if ( qlread(li, slide_page_starts.begin(), sizeof(uint16) * si.page_starts_count) != sizeof(uint16) * si.page_starts_count ) - return false; - - slide_page_extras.resize(si.page_extras_count); - if ( qlseek(li, header.slideInfoOffset + si.page_extras_offset) != header.slideInfoOffset + si.page_extras_offset ) - return false; - validate_array_count_or_die(li, si.page_extras_count, sizeof(uint16), "Slide info page extras count"); - if ( qlread(li, slide_page_extras.begin(), sizeof(uint16) * si.page_extras_count) != sizeof(uint16) * si.page_extras_count ) - return false; - } - else if ( slide_version == 3 ) - { - dyld_cache_slide_info3 si; - if ( qlread(li, &si, sizeof(si)) != sizeof(si) ) - return false; - if ( si.page_size == 0 ) - return false; - - slide_page_size = si.page_size; - slide_delta_mask = 0x7FFull << 51; - slide_value_add = si.auth_value_add; - - slide_page_starts.resize(si.page_starts_count); - validate_array_count_or_die(li, si.page_starts_count, sizeof(uint16), "Slide info page starts count"); - if ( qlread(li, slide_page_starts.begin(), sizeof(uint16) * si.page_starts_count) != sizeof(uint16) * si.page_starts_count ) - return false; - } - } - - if ( (flags & PHF_TEXT) != 0 && header.imagesTextOffset != 0 && header.imagesTextCount != 0 ) - { - if ( qlseek(li, header.imagesTextOffset) != header.imagesTextOffset ) - return false; - text_infos.resize(header.imagesTextCount); - validate_array_count_or_die(li, header.imagesTextCount, sizeof(dyld_cache_image_text_info), "count of image text infos in the cache file"); - if ( qlread(li, text_infos.begin(), sizeof(dyld_cache_image_text_info) * header.imagesTextCount) != sizeof(dyld_cache_image_text_info) * header.imagesTextCount ) - return false; - } - - return true; -} - -//-------------------------------------------------------------------------- -const char *dyld_cache_t::get_arch() const -{ - const char *p = strchr(header.magic, ' '); - if ( p != NULL ) - while ( *p == ' ' ) - p++; - return p; -} - -//-------------------------------------------------------------------------- -static int tzcnt(uint64 x) -{ - int b = 0; - for ( ; x != 0 && (x & 1) == 0; x >>= 1 ) - b++; - return b; -} - -//-------------------------------------------------------------------------- -uint64 dyld_cache_t::untag(uint64 v) const -{ - if ( slide_version == 2 ) - return (v & ~slide_delta_mask) + slide_value_add; - else if ( slide_version == 3 ) - return tagged_pointer64(v).untag(slide_value_add); - return v; -} - -//-------------------------------------------------------------------------- -int dyld_cache_t::parse_slid_chain(dyld_cache_slide_visitor_t *v, uint64 start) -{ - QASSERT(20104, slide_version == 2 || slide_version == 3); - - uint64 off = 0; - uint64 delta = 1; - int code = 0; - - while ( code == 0 && delta != 0 && off < slide_page_size ) - { - uint64 addr = start + off; - uint64 raw_value = read_addr_at_va(addr); - if ( raw_value == BADADDR64 ) - break; - - uint64 untagged = untag(raw_value); - code = v->visit_pointer(addr, untagged); - - if ( slide_version == 2 ) - delta = (raw_value & slide_delta_mask) >> (tzcnt(slide_delta_mask) - 2); - else - delta = ((raw_value & slide_delta_mask) >> 51) * 8; - - off += delta; - } - - return code; -} - -//-------------------------------------------------------------------------- -int dyld_cache_t::visit_slid_pointers(dyld_cache_slide_visitor_t *v) -{ - QASSERT(20068, mappings.size() > 1); - - int code = 0; - uint64 dataStartAddress = mappings[1].address; - if ( slide_version == 1 ) - { - size_t pagesize = slide_entries_size*8*4; - for ( size_t i = 0, size = slide_toc.size(); code == 0 && i < size; i++ ) - { - size_t off = slide_toc[i] * slide_entries_size; - if ( off >= slide_entries.size() ) - { - msg("Corrupted DYLD slide info"); - break; - } - const uchar *entry = &slide_entries[off]; - for ( size_t j = 0; code == 0 && j < slide_entries_size; j++ ) - { - uint64 page = dataStartAddress+i*pagesize; - uchar b = entry[j]; - if ( b != 0 ) - { - for ( int k = 0; code == 0 && k < 8; k++ ) - { - if ( ((1u<<k) & entry[j]) != 0 ) - { - uint64 addr = page+j*8*4+k*4; - uint64 value = read_addr_at_va(addr); - if ( value != BADADDR64 ) - code = v->visit_pointer(addr, value); - } - } - } - } - } - } - else if ( slide_version == 2 ) - { - for ( size_t i = 0; code == 0 && i < slide_page_starts.size(); i++ ) - { - uint64 page = dataStartAddress + (i * slide_page_size); - - uint16 start = slide_page_starts[i]; - if ( start == DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE ) - { - deb(IDA_DEBUG_LDR, "page %llx has no pointers for sliding\n", page); - continue; - } - else if ( (start & DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA) == 0 ) - { - uint64 chain = page + (start * 4); - deb(IDA_DEBUG_LDR, "page %llx: single slide chain at %llx\n", page, chain); - code = parse_slid_chain(v, chain); - } - else - { - for ( size_t j = start & 0x3FFF, size = slide_page_extras.size(); code == 0 && j < size; j++ ) - { - uint16 extra = slide_page_extras[j]; - if ( (extra & DYLD_CACHE_SLIDE_PAGE_ATTR_END) != 0 ) - break; - - uint64 chain = page + (extra * 4); - deb(IDA_DEBUG_LDR, "page %llx: extra slide chain at %llx\n", page, chain); - code = parse_slid_chain(v, chain); - } - } - } - } - else if ( slide_version == 3 ) - { - for ( size_t i = 0; code == 0 && i < slide_page_starts.size(); i++ ) - { - uint64 page = dataStartAddress + (i * slide_page_size); - - uint16 start = slide_page_starts[i]; - if ( start == DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE ) - { - deb(IDA_DEBUG_LDR, "page %llx has no pointers for sliding\n", page); - continue; - } - else - { - uint64 chain = page + start; - deb(IDA_DEBUG_LDR, "page %llx: slide chain at %llx\n", page, chain); - code = parse_slid_chain(v, chain); - } - } - } - else - { - code = -1; - } - - return code; -} - -//-------------------------------------------------------------------------- -// Detecting the ASLR slide in dyld_shared_cache dumps. -// Reference: http://www.iphonedevwiki.net/index.php?title=Dyld_shared_cache -// Most of the caches retrieved from devices have the ASLR slide applied. This means most pointers are off by the slide amount. -// We use a simple algorithm to detect it: -// 1. In any cache module, find an import from another dylib -// 2. Read the current pointer value (impptr) -// 3. Find the exported symbol in the target dylib and get its address (expea) -// 4. The difference between impptr and expea is the slide value -// Once we know the slide value, we can walk all pointers in the cache (helpfully indexed in the slide info tables) and repair them by subtracting the slide value. -//-------------------------------------------------------------------------- -bool dyld_cache_t::calc_aslr_slide(int64 *slide, int n, bool verbose, qstring *errbuf) const -{ - linput_t *dli = create_single_macho_input(n); - if ( dli == NULL ) - { - if ( errbuf != NULL ) - errbuf->sprnt("could not load image %d from the cache", n); - return false; - } - linput_janitor_t li_janitor(dli); - - macho_file_t mfile(dli, 0, MACHO_HINT_SHARED_CACHE_LIB); - if ( !mfile.parse_header() || !mfile.set_subfile(0) ) - { - if ( errbuf != NULL ) - errbuf->sprnt("failed to parse macho header for image %d", n); - return false; - } - - impvec_t ximports; - dyliblist_t dylibs; - rangeset_t ranges; - - if ( mfile.get_import_info(&ximports, &dylibs, &ranges, verbose) == 0 ) - { - if ( errbuf != NULL ) - errbuf->sprnt("no import info found for image %d", n); - return false; - } - - for ( size_t j = 0; j < ximports.size(); j++ ) - { - const import_info_t &iinf = ximports[j]; - if ( iinf.dylib == 0 || iinf.dylib > dylibs.size() ) - continue; - - qstring &dylibname = dylibs[iinf.dylib - 1]; - uint64 expaddr = find_exported_symbol(dylibname.begin(), iinf.name.begin(), verbose); - if ( expaddr == BADADDR64 ) - { - if ( verbose ) - msg("WARNING: could not resolve symbol '%s' from dylib '%s'!\n", iinf.name.c_str(), dylibname.c_str()); - continue; - } - - uint64 _impptr = read_addr_at_va(iinf.impea); - uint64 impptr = untag(_impptr); - if ( verbose ) - msg("0x%08" FMT_64 "X: symbol=%s expaddr=0x%08" FMT_64 "X, impptr(raw)=0x%08" FMT_64 "X, impptr(clean)=0x%08" FMT_64 "X\n", iinf.impea, iinf.name.begin(), expaddr, _impptr, impptr); - - QASSERT(1332, impptr != BADADDR64); - - if ( !ranges.contains(impptr) ) - { - *slide = impptr - expaddr; - if ( verbose ) - msg("detected dyld slide for symbol '%s' : 0x%08" FMT_64 "X\n", iinf.name.c_str(), *slide); - return true; - } - } - - if ( errbuf != NULL ) - errbuf->sprnt("failed to find an exported symbol for all imports in image %d", n); - - return false; -} - -//-------------------------------------------------------------------------- -void dyld_cache_t::parse_local_symbols() -{ - if ( header.localSymbolsOffset == 0 || header.localSymbolsSize == 0 ) - return; - - if ( qlseek(li, header.localSymbolsOffset) != header.localSymbolsOffset ) - return; - - dyld_cache_local_symbols_info si; - if ( qlread(li, &si, sizeof(si)) != sizeof(si) ) - return; - - nlistvec_t symbols; - qstring strings; - - uint64_t symoff = header.localSymbolsOffset + si.nlistOffset; - uint64_t stroff = header.localSymbolsOffset + si.stringsOffset; - size_t nsymbols = si.nlistCount; - - size_t size = si.nlistCount * ( m64 ? sizeof(struct nlist_64) : sizeof(struct nlist)); - uint64_t stend = symoff + size; - uint64 mach_size = qlsize(li); - if ( stend < symoff || stend > mach_size ) - { - msg("WARNING: local symbol table extends past end of file\n"); - size = mach_size - symoff; - nsymbols = size / ( m64 ? sizeof(struct nlist_64) : sizeof(struct nlist)); - } - - if ( nsymbols != 0 ) - { - symbols.resize(nsymbols); - if ( m64 ) - { - size = sizeof(struct nlist_64) * nsymbols; - qlseek(li, symoff); - qlread(li, &symbols[0], size); - if ( mf ) - swap_nlist_64(&symbols[0], &symbols[0], nsymbols); - } - else - { - qvector<struct nlist> syms32; - syms32.resize(nsymbols); - size = sizeof(struct nlist) * nsymbols; - qlseek(li, symoff); - qlread(li, &syms32[0], size); - nlist_to64(&syms32[0], &symbols[0], nsymbols, mf); - } - } - if ( stroff >= mach_size ) - { - msg("WARNING: string table offset is past end of file\n"); - } - else - { - size_t strings_size; - size_t strend = stroff + si.stringsSize; - if ( strend < stroff || strend > mach_size ) - { - msg("WARNING: string table extends past end of file\n"); - strings_size = mach_size - stroff; - } - else - { - strings_size = si.stringsSize; - } - - strings.resize(strings_size); - if ( strings_size != 0 ) - { - qlseek(li, stroff); - qlread(li, &strings[0], strings_size); - } - } - - localst_symbols = symbols; - localst_strings = strings; - - uint64 entries_off = header.localSymbolsOffset + si.entriesOffset; - if ( qlseek(li, entries_off) != entries_off ) - return; - - localst_entries.resize(si.entriesCount); - size_t entries_size = sizeof(dyld_cache_local_symbols_entry) * si.entriesCount; - if ( qlread(li, localst_entries.begin(), entries_size) != entries_size ) - return; -} - -//-------------------------------------------------------------------------- -const dyld_cache_local_symbols_entry *dyld_cache_t::get_symbols_entry(int n) const -{ - if ( n < 0 || n >= image_infos.size() ) - return NULL; - - uint64 off = va2off(get_image_info(n).address); - - for ( size_t i = 0, size = localst_entries.size(); i < size; i++ ) - { - const dyld_cache_local_symbols_entry *entry = &localst_entries[i]; - if ( entry->dylibOffset == off ) - return entry; - } - - return NULL; -} - -//-------------------------------------------------------------------------- -const dyld_cache_mapping_info *dyld_cache_t::get_text_mapping(void) const -{ - for ( size_t i = 0, n = mappings.size(); i < n; i++ ) - { - const dyld_cache_mapping_info *mi = &mappings[i]; - if ( (mi->maxProt & (VM_PROT_EXECUTE|VM_PROT_READ)) == (VM_PROT_EXECUTE|VM_PROT_READ) ) - return mi; - } - return NULL; -} - -//-------------------------------------------------------------------------- -uint32 dyld_cache_t::get_max_text_segm(void) const -{ - uint32 text_segm_max = 0; - for ( size_t i = 0, n = text_infos.size(); i < n; i++ ) - { - if ( text_infos[i].textSegmentSize > text_segm_max ) - text_segm_max = text_infos[i].textSegmentSize; - } - return text_segm_max; -} - -//-------------------------------------------------------------------------- -uint64 dyld_cache_t::get_min_image_address(void) const -{ - uint64 minea = BADADDR64; - for ( size_t i = 0, n = image_infos.size(); i < n; i++ ) - { - const dyld_cache_image_info &ii = image_infos[i]; - if ( ii.address < minea ) - minea = ii.address; - } - return minea; -} - -//-------------------------------------------------------------------------- -bool dyld_cache_t::get_header_range(uint64 *start, uint64 *end) const -{ - const dyld_cache_mapping_info *mtext = get_text_mapping(); - if ( mtext == NULL ) - return false; - - uint64 minea = get_min_image_address(); - if ( minea == BADADDR64 ) - return false; - - if ( minea < mtext->address || minea >= mtext->address + mtext->size ) - return false; - - if ( start != NULL ) - *start = mtext->address; - if ( end != NULL ) - *end = minea; - - return true; -} - -//-------------------------------------------------------------------------- -bool dyld_cache_t::is_header_address(uint64 address) const -{ - if ( address == BADADDR64 ) - return false; - - uint64 start, end; - if ( !get_header_range(&start, &end) ) - return false; - - return address >= start && address < end; -} - -//-------------------------------------------------------------------------- -struct dyld_single_macho_linput_t : public generic_linput_t -{ - linput_t *li_dyld; - qoff64_t max_rel_off; - qoff64_t start_off; - dyld_single_macho_linput_t(linput_t *li_dyld_, const dyld_cache_t &cache, const dyld_cache_image_info &ii) - : li_dyld(li_dyld_) - { - // find the text (r-x) region - const dyld_cache_mapping_info *mtext = cache.get_text_mapping(); - if ( mtext == NULL ) - { - msg("Read/execute region not found in the cache"); - max_rel_off = 0; - filesize = 0; - } - else - { - const dyld_cache_mapping_info &mlast = cache.get_mapping_info(cache.get_nummappings()-1); - start_off = ii.address - mtext->address + mtext->fileOffset; - filesize = mlast.fileOffset + mlast.size; - max_rel_off = cache.get_max_text_segm(); - if ( max_rel_off == 0 ) - max_rel_off = mtext->size; - } - blocksize = 0; // don't cache - } - virtual ssize_t idaapi read(qoff64_t off, void *buffer, size_t nbytes) override - { - // offsets for the __TEXT segment are relative to the start offset of the subfile. - // other segments (__DATA and __LINKEDIT) seem to use absolute offsets. - if ( off < max_rel_off ) - off += start_off; - if ( qlseek(li_dyld, off, 0) != off ) - return -1; - return qlread(li_dyld, buffer, nbytes); - } -}; - -//-------------------------------------------------------------------------- -linput_t *dyld_cache_t::create_single_macho_input(size_t imgindex) const -{ - if ( get_nummappings() < 1 ) - return NULL; - QASSERT(20069, imgindex < image_infos.size()); - const dyld_cache_image_info &ii = get_image_info(imgindex); - dyld_single_macho_linput_t *dsmli = new dyld_single_macho_linput_t(li, *this, ii); - return create_generic_linput(dsmli); -} - -//-------------------------------------------------------------------------- -linput_t *dyld_cache_t::create_single_island_input(size_t n) const -{ - if ( get_nummappings() < 1 ) - return NULL; - dyld_cache_image_info ii; - QASSERT(20119, n < island_addrs.size()); - ii.address = get_island_addr(n); - dyld_single_macho_linput_t *dsmli = new dyld_single_macho_linput_t(li, *this, ii); - return create_generic_linput(dsmli); -} - -//-------------------------------------------------------------------------- -// Object that will free an linput_t upon deletion -class linput_janitor_verbose_t -{ -public: - linput_janitor_verbose_t(linput_t *r, const qstring &filename): name(filename), resource(r) - { -#if 0 - msg("got linput %s(%p)\n", name.c_str(), resource); -#endif - } - ~linput_janitor_verbose_t() - { -#if 0 - msg("closing linput %s(%p)\n", name.c_str(), resource); -#endif - close_linput(resource); - } -private: - qstring name; - linput_t *resource; -}; - -//-------------------------------------------------------------------------- -uint64 dyld_cache_t::find_exported_symbol( - const char *_dylib, - const char *symname, - bool verbose) const -{ - if ( _dylib == NULL || _dylib[0] == '\0' || symname == NULL || symname[0] == '\0' ) - return BADADDR64; - - qstack<qstring> dylibs; - dylibs.push(_dylib); - linput_t *dlj = NULL; - while ( !dylibs.empty() ) - { - const qstring &dylibname = dylibs.pop(); - ssize_t j = get_image_index(dylibname); - dlj = create_single_macho_input(j); - QASSERT(1331, dlj != NULL); - linput_janitor_verbose_t li_janitor(dlj, dylibname); - macho_file_t mfile(dlj, 0, MACHO_HINT_SHARED_CACHE_LIB); - if ( mfile.parse_header() && mfile.set_subfile(0) ) - { - if ( verbose ) - msg("2 searching for symbol %s in %s\n", symname, dylibname.c_str()); - uint64 tmp = mfile.find_exported_symbol(symname, verbose, this); - if ( tmp != BADADDR64 ) - return tmp; - } - // not found in this dylib; check linked reexported dylibs - if ( (mfile.get_mach_header().flags & MH_NO_REEXPORTED_DYLIBS) == 0 ) - { - dyliblist_t wlibs = mfile.get_dylib_list(LC_REEXPORT_DYLIB); - for ( dyliblist_t::const_iterator p = wlibs.begin(); p != wlibs.end(); ++p ) - { - if ( verbose ) - msg("2 checking reexported dylib %s for %s\n", p->c_str(), dylibname.c_str()); - dylibs.add_unique(*p); - } - } - } - return BADADDR64; -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::find_exported_symbol( - const char *symname, - bool verbose, - const dyld_cache_t *dcache) -{ - if ( symname == NULL || symname[0] == '\0' ) - return BADADDR64; - - // first try using dyld export info (which is faster and also handles tricky - // reexported symbols like _memset) - uint64 tmp = find_exported_symbol_dyld(symname, verbose, dcache); - if ( tmp != BADADDR64 ) - return tmp; - - // else try the symtab approach - - bool arm32 = !m64 && get_mach_header().cputype == CPU_TYPE_ARM; - qstring strings; - nlistvec_t symbols; - get_symbol_table_info(&symbols, &strings); - size_t nsymbols = symbols.size(); - size_t strings_size = strings.size(); - for ( uint32 i = 0; i < nsymbols; i++ ) - { - const struct nlist_64 &nl = symbols[i]; - int stype = nl.n_type & N_TYPE; - if ( stype == N_UNDF || stype == N_PBUD ) - continue; - if ( nl.n_un.n_strx >= strings_size ) - continue; - const char *sname = &strings[nl.n_un.n_strx]; - if ( streq(symname, sname) ) - { - uint64 v = nl.n_value; - // add thumb bit if needed - if ( arm32 && (nl.n_desc & N_ARM_THUMB_DEF) != 0 ) - v |= 1; - return v; - } - } - - return BADADDR64; -} - -//-------------------------------------------------------------------------- -void dyld_cache_t::get_dependencies(dyldlib_set_t *p, int n, int _max) -{ - int max = _max == -1 ? get_numfiles() : _max; - - if ( p == NULL || n < 0 || n >= max ) - return; - if ( p->find(n) != p->end() ) - return; - p->insert(n); - - linput_t *dli = create_single_macho_input(n); - macho_file_t mfile(dli); - if ( !mfile.parse_header() // accept_file() must have verified it - || !mfile.set_subfile(0, qlsize(dli), true) ) - { - return; - } - dyliblist_t dl = mfile.get_dylib_list(); - close_linput(dli); // free the linput slot before we recurse - - for ( size_t idl = 0; idl < dl.size(); idl++ ) - { - const char *dfname = dl[idl].c_str(); - int l; - for ( l = 0; l < max; l++ ) - { - const char *filename = get_image_name(l).c_str(); - if ( streq(filename, dfname) ) - break; - } - if ( l != max ) - get_dependencies(p, l, max); - } -} - -//-------------------------------------------------------------------------- -static bool is_valid_sym(const nlist_64 *s) -{ - return (s->n_type & N_TYPE) == N_SECT && (s->n_type & N_STAB) == 0; -} - -// binary search in symbols[start..s+n] -static const nlist_64 *find_sym(const nlistvec_t &symbols, uint32 start, uint32 n, uint64 address,int sectionidx) -{ - const nlist_64 *best = NULL; - uint32 l = start; - uint32 r = l + n; - if ( r > symbols.size() ) - return NULL; - while ( l < r ) - { - uint32_t m = ( r + l ) / 2; - const nlist_64 *s = &symbols[m]; - if ( is_valid_sym(s) ) - { - if ( s->n_value <= address - && ( s->n_sect == sectionidx || sectionidx == 0 ) ) - { - if ( best == NULL || best->n_value < s->n_value ) - best = s; - } - } - if ( s->n_value < address ) - l = m + 1; - else if ( m < start + 1 ) - break; - else - r = m - 1; - } - return best; -} -//-------------------------------------------------------------------------- -bool macho_file_t::get_symbol_name( - qstring *name, - uint64 *offset, - uint64 address, - int sectionidx, - bool verbose, - const dyld_cache_t *dcache) -{ - // inspired by DyldInfoPrinter<A>::closestSymbolNameForAddress in dyldinfo.cpp - dysymtab_command dyst; - // get the symbol table - nlistvec_t symbols; - qstring strings; - get_symbol_table_info(&symbols, &strings); - const nlist_64 *best = NULL; - if ( get_dyst(&dyst) ) - { - // find closest match in globals - best = find_sym(symbols, dyst.iextdefsym,dyst.nextdefsym, address, sectionidx); - // find closest match in locals - const nlist_64 *s = find_sym(symbols, dyst.ilocalsym, dyst.nlocalsym, address, sectionidx); - // take the best of the two - if ( best == NULL || (s != NULL ) && best->n_value < s->n_value ) - best = s; - } - else - { - //search the whole symbol table - best = find_sym(symbols, 0, symbols.size(), address, sectionidx); - } - // TODO: use dcache and check local symbol table? - qnotused(dcache); - qnotused(verbose); - if ( best != NULL ) - { - // check if a neighboring symbol is a closer match - uint32 m = best - &symbols[0]; - if ( m < symbols.size() ) - { - nlist_64 *s = &symbols[m+1]; - if ( is_valid_sym(s) && address - s->n_value < address - best->n_value ) - best = s; - } - *offset = address - best->n_value; - const char *sname = &strings[best->n_un.n_strx]; - *name = sname; - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -uint64 dyld_cache_t::find_exported_symbol_dyld( - const char *_dylib, - const char *symname, - bool verbose) const -{ - if ( _dylib == NULL || _dylib[0] == '\0' || symname == NULL || symname[0] == '\0' ) - return BADADDR64; - - qstack<qstring> dylibs; - dylibs.push(_dylib); - linput_t *dlj = NULL; - while ( !dylibs.empty() ) - { - const qstring &dylibname = dylibs.pop(); - ssize_t j = get_image_index(dylibname); - dlj = create_single_macho_input(j); - QASSERT(1330, dlj != NULL); - linput_janitor_verbose_t li_janitor(dlj, dylibname); - macho_file_t mfile(dlj, 0, MACHO_HINT_SHARED_CACHE_LIB); - if ( mfile.parse_header() && mfile.set_subfile(0) ) - { - if ( verbose ) - msg("1 searching for symbol %s in %s\n", symname, dylibname.c_str()); - uint64 tmp = mfile.find_exported_symbol_dyld(symname, verbose, this); - if ( tmp != BADADDR64 ) - { - if ( verbose && dylibname != _dylib ) - msg("symbol '%s' found in dylib '%s', address: 0x%08" FMT_64"X\n", - symname, dylibname.c_str(), tmp); - return tmp; - } - } - // not found in this dylib; check linked reexported dylibs - dyliblist_t wlibs = mfile.get_dylib_list(LC_REEXPORT_DYLIB); - for ( dyliblist_t::const_iterator p = wlibs.begin(); p != wlibs.end(); ++p ) - { - if ( verbose ) - msg("1 checking reexported dylib %s for %s\n", p->c_str(), dylibname.c_str()); - dylibs.add_unique(*p); - } - } - return BADADDR64; -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::find_exported_symbol_dyld( - const char *symname, - bool verbose, - const dyld_cache_t *dcache) -{ - if ( symname == NULL || symname[0] == '\0' ) - return BADADDR64; - - struct ida_local find_export_visitor_t : public macho_lc_visitor_t - { - macho_file_t &mfile; - qstring symbol; - const dyld_cache_t *dyldcache; - uint64 expaddr; - bool verbose; - - find_export_visitor_t( - macho_file_t &_mfile, - const char *_symbol, - const dyld_cache_t *_dyldcache, - bool _verbose) - : mfile(_mfile), - symbol(_symbol), - dyldcache(_dyldcache), - expaddr(-1), - verbose(_verbose) - { - } - virtual ~find_export_visitor_t() {} - - bool load_data(uint32_t offset, uint32_t size, bytevec_t &data) - { - if ( size == 0 ) - return false; - data.resize(size); - size_t newsize = size; - if ( !mfile.load_linkedit_data(offset, &newsize, &data[0]) || newsize == 0 ) - { - return false; - } - return true; - } - - const uchar *trieWalk(const uchar *start, const uchar *end, const char *s) const - { - const uchar *p = start; - bytevec_t visited; - size_t len = end - start; - visited.resize((len+7)/8, 0); - - uint32 nodeOffset = 0; - while ( p != NULL ) - { - if ( p >= end || p < start ) - return NULL; - - if ( visited.test_bit(nodeOffset) ) - return NULL; // endless loop - visited.set_bit(nodeOffset); - - uint32_t terminalSize = unpack_db(&p, end); - if ( terminalSize > 127 ) - { - // except for re-export-with-rename, all terminal sizes fit in one byte - --p; - if ( !unpack_uleb128(&terminalSize, &p, end) ) - return NULL; - } - - if ( *s == '\0' && terminalSize != 0 ) - return p; - - if ( p >= end || p < start ) - return NULL; - const uchar *children = p + terminalSize; - if ( children >= end || children < start ) - return NULL; - uint8_t childrenRemaining = *children++; - p = children; - nodeOffset = 0; - if ( p >= end || p < start ) - return NULL; - for ( ; childrenRemaining > 0; --childrenRemaining ) - { - const char *ss = s; - bool wrongEdge = false; - // scan whole edge to get to next edge - // if edge is longer than target symbol name, don't read past end of symbol name - char c = *p; - while ( c != '\0' ) - { - if ( !wrongEdge ) - { - if ( c != *ss ) - wrongEdge = true; - ++ss; - } - ++p; - c = *p; - } - if ( wrongEdge ) - { - // advance to next child - ++p; // skip over zero terminator - // skip over uleb128 until last byte is found - while ( ( *p & 0x80 ) != 0 ) - ++p; - ++p; // skil over last byte of uleb128 - } - else - { - // the symbol so far matches this edge (child) - // so advance to the child's node - ++p; - if ( !unpack_uleb128(&nodeOffset, &p, end) ) - return NULL; - s = ss; - break; - } - } - p = &start[nodeOffset]; - } - return p; - } - - bool process_export_info(const bytevec_t &data) - { - const uchar *begin = &data[0]; - const uchar *end = begin + data.size(); - const uchar *foundNodeStart = trieWalk(begin, end, symbol.c_str()); - if ( foundNodeStart == NULL ) - return false; - const uchar *p = foundNodeStart; - uint32 flags; - if ( !unpack_uleb128(&flags, &p, end) ) - return false; - if ( (flags & EXPORT_SYMBOL_FLAGS_REEXPORT) != 0 ) - { - // re-export from another dylib, lookup there - if ( dyldcache == NULL ) - { - if ( verbose ) - msg("symbol '%s' is reexported but cannot follow without the dyld cache!\n", symbol.c_str()); - return false; - } - uint32 ordinal; - if ( !unpack_uleb128(&ordinal, &p, end) ) - return false; - qstring importedName = (char*)p; - if ( importedName[0] == '\0' ) - importedName = symbol; - dyliblist_t dylibs = mfile.get_dylib_list(); - if ( ordinal > 0 && ordinal <= dylibs.size() ) - { - const qstring &rdylib = dylibs[ordinal - 1]; - if ( verbose ) - msg("symbol '%s': looking up in reexported dylib '%s'\n", importedName.c_str(), rdylib.c_str()); - expaddr = dyldcache->find_exported_symbol(rdylib.begin(), importedName.begin(), verbose); - if ( verbose ) - msg("symbol '%s' found in dylib '%s', address: 0x%08" FMT_64"X\n", - importedName.c_str(), rdylib.c_str(), expaddr); - } - } - else - { - if ( !unpack_uleb128(&expaddr, &p, end) ) - return false; - expaddr += mfile.get_base(); - } - - return true; - } - - virtual int visit_dyld_info( - const struct dyld_info_command *lc, - const char *, - const char *) override - { - bytevec_t data; - if ( !load_data(lc->export_off, lc->export_size, data) - || !process_export_info(data) ) - { - expaddr = BADADDR64; - } - return 1; - } - }; - - find_export_visitor_t v(*this, symname, dcache, verbose); - visit_load_commands(v); - return v.expaddr; -} - -//------------------------------------------------------------------------ -uint64 macho_file_t::va2off(uint64 addr) -{ - const segcmdvec_t &segs = get_segcmds(); - for ( auto s : segs ) - { - if ( addr >= s.vmaddr ) - { - uint64 off = addr - s.vmaddr; - if ( off >= s.vmsize ) - continue; - return s.fileoff + off + mach_offset; - } - } - return BADADDR64; -} - -//------------------------------------------------------------------------ -uint64 macho_file_t::read_dword_at_va(uint64 addr) -{ - uint32 v; - uint64 off = va2off(addr); - if ( off != BADADDR64 - && qlseek(li, off, 0) == off - && qlread(li, &v, sizeof(v)) == sizeof(v) ) - { - return v; - } - return BADADDR64; -} - -//------------------------------------------------------------------------ -uint64 macho_file_t::read_qword_at_va(uint64 addr) -{ - uint64 v; - uint64 off = va2off(addr); - if ( off != BADADDR64 - && qlseek(li, off, 0) == off - && qlread(li, &v, sizeof(v)) == sizeof(v) ) - { - return v; - } - return BADADDR64; -} - -//------------------------------------------------------------------------ -uint64 macho_file_t::read_addr_at_va(uint64 addr) -{ - return m64 ? read_qword_at_va(addr) : read_dword_at_va(addr); -} - -//------------------------------------------------------------------------ -char *macho_file_t::read_string_at_va(uint64 addr, char *buf, size_t bufsize) -{ - uint64 off = va2off(addr); - if ( off != BADADDR64 && qlseek(li, off, 0) == off ) - return qlgetz(li, off, buf, bufsize); - return buf; -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::get_kmod_ver(uint64 kinfo_ea) -{ - if ( m64 ) - return read_dword_at_va(kinfo_ea + offsetof(kmod_info_64_v1, info_version)); - else - return read_dword_at_va(kinfo_ea + offsetof(kmod_info_32_v1, info_version)); -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::get_kmod_start(uint64 kinfo_ea) -{ - if ( m64 ) - return read_qword_at_va(kinfo_ea + offsetof(kmod_info_64_v1, address)); - else - return read_dword_at_va(kinfo_ea + offsetof(kmod_info_32_v1, address)); -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::get_kmod_size(uint64 kinfo_ea) -{ - if ( m64 ) - return read_qword_at_va(kinfo_ea + offsetof(kmod_info_64_v1, size)); - else - return read_dword_at_va(kinfo_ea + offsetof(kmod_info_32_v1, size)); -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::get_kmod_hdr_size(uint64 kinfo_ea) -{ - if ( m64 ) - return read_qword_at_va(kinfo_ea + offsetof(kmod_info_64_v1, hdr_size)); - else - return read_dword_at_va(kinfo_ea + offsetof(kmod_info_32_v1, hdr_size)); -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::get_kmod_start_func(uint64 kinfo_ea) -{ - if ( m64 ) - return read_qword_at_va(kinfo_ea + offsetof(kmod_info_64_v1, start_addr)); - else - return read_dword_at_va(kinfo_ea + offsetof(kmod_info_32_v1, start_addr)); -} - -//-------------------------------------------------------------------------- -qstring macho_file_t::get_kmod_name(uint64 kinfo_ea) -{ - char name[KMOD_MAX_NAME + 1]; - uint64 name_ea = kinfo_ea + (m64 ? offsetof(kmod_info_64_v1, name) : offsetof(kmod_info_32_v1, name)); - return read_string_at_va(name_ea, name, sizeof(name)); -} - -//------------------------------------------------------------------------ -uint64 dyld_cache_t::va2off(uint64 addr) const -{ - for ( size_t i = 0; i < mappings.size(); i++ ) - { - const dyld_cache_mapping_info &m = mappings[i]; - if ( addr >= m.address ) - { - uint64 off = addr - m.address; - if ( off > m.size ) - continue; - return m.fileOffset + off; - } - } - return BADADDR64; -} - -//------------------------------------------------------------------------ -uint64 dyld_cache_t::read_addr_at_va(uint64 addr) const -{ - uint64 off = va2off(addr); - if ( off != BADADDR64 && qlseek(li, off, 0) == off ) - { - if ( m64 ) - { - uint64 v; - if ( qlread(li, &v, 8) != 8 ) - return BADADDR64; - return v; - } - else - { - uint32 v; - if ( qlread(li, &v, 4) != 4 ) - return BADADDR64; - return v; - } - } - return BADADDR64; -} - -//------------------------------------------------------------------------ -char *dyld_cache_t::read_string_at_va(uint64 addr, char *buf, size_t bufsize) const -{ - uint64 off = va2off(addr); - if ( off != BADADDR64 && qlseek(li, off, 0) == off ) - return qlgetz(li, off, buf, bufsize); - return buf; -} - -//-------------------------------------------------------------------------- -void dyld_cache_t::get_modules(intvec_t *out) const -{ - out->resize(image_infos.size()); - std::iota(out->begin(), out->end(), 0); -} - -//-------------------------------------------------------------------------- -void dyld_cache_t::get_islands(intvec_t *out) const -{ - out->resize(island_addrs.size()); - std::iota(out->begin(), out->end(), 0); -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_prelink_info(section_64 *prelink_info) -{ - return get_section("__PRELINK_INFO", "__info", prelink_info) - || get_section("__PRELINK", "__info", prelink_info); -} - -//-------------------------------------------------------------------------- -bool macho_file_t::get_prelink_text(section_64 *prelink_text) -{ - return get_section("__PRELINK_TEXT", SECT_TEXT, prelink_text) - || get_section("__PRELINK", SECT_TEXT, prelink_text); -} - -//------------------------------------------------------------------------ -bool macho_file_t::get_prelink_data(section_64 *prelink_data) -{ - return get_section("__PRELINK_DATA", SECT_DATA, prelink_data); -} - -//-------------------------------------------------------------------------- -uint64 macho_file_t::find_next_magic(uint64 off, uint64 endoff) -{ - char buf[0x1000]; - uint64 size = endoff - off; - while ( size > 0 ) - { - if ( qlseek(li, off, 0) != off ) - return endoff; - - size_t n = qmin(size, sizeof(buf)); - size_t nread = qlread(li, buf, n); - if ( nread != n || nread % 4 != 0 ) - return endoff; - - const char *ptr = buf; - const char *end = buf + nread; - - for ( ; ptr < end; ptr += sizeof(uint32) ) - { - uint32 magic = *(const uint32 *)ptr; - if ( is_magic(magic) || is_cigam(magic) ) - return off + (ptr-buf); - } - - size -= nread; - off += nread; - } - - return endoff; -} - -//------------------------------------------------------------------------ -void macho_file_t::scan_for_kexts(void) -{ - section_64 prelink_text; - if ( !get_prelink_text(&prelink_text) || prelink_text.size == 0 ) - return; - - uint64 startoff = prelink_text.offset + mach_offset; - uint64 curoff = startoff; - size_t maxsize = prelink_text.size; - uint64 end = curoff + maxsize; - - for ( size_t i = 0; maxsize > 0 && curoff < end; i++ ) - { - uint64 nextoff = find_next_magic(curoff, end); - if ( nextoff == end ) - break; - - maxsize = end - nextoff; - curoff = nextoff; - size_t ksize = maxsize; - - // determine the subfile's size - linput_t *kmodli = create_single_kmod_input(curoff); - QASSERT(20125, kmodli != NULL); - linput_janitor_t li_janitor(kmodli); - macho_file_t mfile(kmodli); - - uint64 base = BADADDR64; - uint64 maxea = 0; - uint64 filesize = 0; - - if ( mfile.parse_header() && mfile.set_subfile(0, ksize, true) ) - { - const segcmdvec_t &segcmds = mfile.get_segcmds(); - for ( size_t si = 0; si < segcmds.size(); si++ ) - { - // walk the segments, look for the base address - const segment_command_64 &sg = segcmds[si]; - if ( base == BADADDR64 && sg.fileoff == 0 ) - base = sg.vmaddr; - filesize += sg.filesize; - uint64 send = sg.vmaddr + sg.vmsize; - if ( maxea < send ) - maxea = send; - } - } - - if ( filesize == 0 || maxea == 0 ) - { - // parsing failed. skip this macho magic - maxsize -= sizeof(uint32); - curoff += sizeof(uint32); - continue; - } - - // save the base address of the kext within the prelink text segment. - // this is not necessarily the same as the final base address that is specified - // in the kext's header, since it could be relocated. - uint64 loadaddr = prelink_text.addr + (curoff - startoff); - - if ( base == BADADDR64 ) - { - // no segment had file offset of 0 - // find the next mach-o to figure out the size of the current one - uint64 next = find_next_magic(curoff+sizeof(uint32), end); - ksize = next - curoff; - base = loadaddr; - } - else - { - // align on page boundary - maxea = (maxea + 0xFFF) & ~uint64(0xFFFu); - ksize = maxea - base; - } - - // see if we have a kmod_info - uint64 kea = mfile.find_exported_symbol("_kmod_info"); - - kmod_params &kp = kpv.push_back(); - kp.kstart = base; - kp.kinfo_ea = kea; - kp.ksize = ksize; - kp.off = curoff; - kp.loadaddr = loadaddr; - mfile.get_uuid(kp.uuid); - - if ( kea != BADADDR64 && mfile.get_kmod_ver(kea) == 1 ) - kp.name = mfile.get_kmod_name(kea); - - if ( kp.name.empty() ) - kp.name.sprnt("prelink_mod_%u", int(i)); - - if ( ksize <= maxsize ) - maxsize -= ksize; - - curoff += filesize; - } -} - -#ifndef BUILD_IDAPYSWITCH -//-------------------------------------------------------------------------- -// implementation of the file read callback for qstrings -class qstring_read_callback_t : public IFileReadCallBack -{ - qstring text; - size_t pos; - -public: - // construct from string - qstring_read_callback_t(const qstring &t): text(t), pos(0) {} - - // read the specificed amount of bytes from the file - virtual int read(void *buffer, int sizeToRead) override - { - if ( sizeToRead < 0 ) - return 0; - size_t end = pos + sizeToRead; - if ( end < pos ) // overflow - return 0; - if ( end > text.length() ) - { - end = text.length(); - sizeToRead = end - pos; - } - if ( sizeToRead > 0 ) - memcpy(buffer, &text[pos], sizeToRead); - pos += sizeToRead; - return sizeToRead; - } - - // return size of file in bytes - virtual int getSize() override { return text.length(); } -}; - -//--------------------------------------------------------------------------- -static IrrXMLReader *createPrelinkReaderQstring(const qstring &text) -{ - return new CXMLReaderImpl<char, IXMLBase>(new qstring_read_callback_t(text)); -} - -//-------------------------------------------------------------------------- -bool macho_file_t::parse_prelink_xml(void) -{ - section_64 prelink_info; - if ( !get_prelink_info(&prelink_info) ) - return false; - - uint64 size = prelink_info.size; - if ( size == 0 ) - return false; - - qstring xml; - xml.resize(size, '\0'); - - uint64 off = prelink_info.offset + mach_offset; - - if ( qlseek(li, off, 0) != off || qlread(li, xml.begin(), size) != size ) - return false; - - xml.resize(qstrlen(xml.c_str())); - - if ( xml.empty() ) - return false; - - struct ida_local prelink_xml_parser_t - { - IrrXMLReader *reader; - macho_file_t *kcache; - kmod_params_vec_t *kpv; - qstring curnode; - qstring curkey; - - prelink_xml_parser_t(const qstring &_xml, macho_file_t *_kcache, kmod_params_vec_t *_kpv) - : reader(createPrelinkReaderQstring(_xml)), kcache(_kcache), kpv(_kpv) {} - ~prelink_xml_parser_t(void) { delete reader; kpv = NULL; } - - bool parse_element(void) - { - while ( reader->read() ) - { - switch ( reader->getNodeType() ) - { - case EXN_ELEMENT: - { - if ( !reader->isEmptyElement() ) - { - curnode = reader->getNodeName(); - parse_element(); - } - } - break; - case EXN_TEXT: - { - uint64 num = 0; - qstring text = reader->getNodeData(); - if ( curnode == "key" ) - { - curkey = text; - } - else if ( curnode == "integer" && curkey == "_PrelinkKmodInfo" ) - { - num = strtoull(text.c_str(), NULL, 0); - } - else if ( curnode == "data" && curkey == "OSBundlePrelink" ) - { - // get a big-endian uint32 from string - bytevec_t kidata; - if ( base64_decode(&kidata, text.c_str(), text.length()) && kidata.size() >= 16 ) - swap_value(&num, kidata.begin(), 4); - } - // parse the kmod_info struct - if ( num != 0 && kcache->get_kmod_ver(num) == 1 ) - { - kmod_params &kp = kpv->push_back(); - - kp.kinfo_ea = num; - kp.ksize = kcache->get_kmod_size(num); - kp.kstart = kcache->get_kmod_start(num); - kp.name = kcache->get_kmod_name(num); - kp.off = kcache->va2off(kp.kstart); - kp.loadaddr = kp.kstart; // TODO: we assume the kext isn't relocated. this might be incorrect, but I don't have an example that proves it. - - // extract the UUID - linput_t *kli = kcache->create_single_kmod_input(kp.off); - QASSERT(20126, kli != NULL); - linput_janitor_t lij(kli); - - macho_file_t mfile(kli); - if ( mfile.parse_header() && mfile.set_subfile(0) ) - mfile.get_uuid(kp.uuid); - } - } - break; - case EXN_ELEMENT_END: - return true; - default: - break; - } - } - return false; - } - }; - - prelink_xml_parser_t parser(xml, this, &kpv); - - bool ok = true; - while ( ok ) - ok = parser.parse_element(); - - return true; -} -#else -bool macho_file_t::parse_prelink_xml(void) { return false; } -#endif // BUILD_IDAPYSWITCH - -//------------------------------------------------------------------------ -bool macho_file_t::parse_kmod_starts(void) -{ - if ( !m64 ) - return false; - - section_64 kmod_start; - section_64 kmod_info; - section_64 text_exec; - - if ( !get_section("__PRELINK_INFO", "__kmod_start", &kmod_start) || kmod_start.size == 0 ) - return false; - if ( !get_section("__PRELINK_INFO", "__kmod_info", &kmod_info) || kmod_info.size == 0 ) - return false; - if ( !get_section("__TEXT_EXEC", SECT_TEXT, &text_exec) || text_exec.size == 0 ) - return false; - - uint32 off1 = kmod_start.offset + mach_offset; - uint32 off2 = kmod_info.offset + mach_offset; - - uint32 end1 = off1 + kmod_start.size; - uint32 end2 = off2 + kmod_info.size; - - // parse the array of kmod start addresses in __kmod_start. - // assume an ordered 1-1 mapping between the start eas in __kmod_start - // and the kmod_info structures __kmod_info. - for ( ; off1 < end1 && off2 < end2; off1 += 8, off2 += 8 ) - { - uint64 kstart = 0; - uint64 kinfo_ea = 0; - - if ( qlseek(li, off1, 0) != off1 - || qlread(li, &kstart, sizeof(kstart)) != sizeof(kstart) - || qlseek(li, off2, 0) != off2 - || qlread(li, &kinfo_ea, sizeof(kinfo_ea)) != sizeof(kinfo_ea) ) - { - break; - } - - kstart = untag(kstart); - kinfo_ea = untag(kinfo_ea); - - // sanity check - if ( kstart < text_exec.addr - || kstart >= text_exec.addr + text_exec.size ) - { - continue; - } - - uint64 off = va2off(kstart); - - linput_t *kmodli = create_single_kmod_input(off); - QASSERT(20122, kmodli != NULL); - linput_janitor_t li_janitor(kmodli); - macho_file_t mfile(kmodli); - - if ( !mfile.parse_header() || !mfile.set_subfile(0) ) - continue; - - // found a valid kext, determine its size - uint64 ksize = 0; - const segcmdvec_t &segcmds = mfile.get_segcmds(); - for ( size_t si = 0; si < segcmds.size(); si++ ) - { - const segment_command_64 &sg = segcmds[si]; - if ( sg.fileoff == 0 ) - { - ksize = sg.vmsize; - break; - } - } - - if ( ksize == 0 ) - continue; - - // append to list of kexts - kmod_params &kp = kpv.push_back(); - kp.kstart = kstart; - kp.ksize = ksize; - kp.kinfo_ea = kinfo_ea; - kp.name = get_kmod_name(kinfo_ea); - kp.off = off; - kp.loadaddr = kp.kstart; // iOS 12 kexts aren't relocated - mfile.get_uuid(kp.uuid); - } - - return true; -} - -//------------------------------------------------------------------------ -void macho_file_t::parse_kmod_info(void) -{ - // try to populate the array of kmod_params - if ( !parsed_kmod_info ) - { - // There are 3 ways to detect prelinked KEXTs: - // - // 1. parse __kmod_start/__kmod_info. - // these sections make our life easy, but they are only present in kernelcaches - // for iOS 12 and later. - // - // 2. parse the XML in __PRELINK_INFO. - // this approach would be ok if Apple didn't change the XML format - // all the goddamn time. - // - // 3. if steps 1 and 2 fail, we fall back to scanning the __PRELINK_TEXT/__TEXT_EXEC - // segment for Mach-O magic, and parse the subfiles. - // - if ( !parse_kmod_starts() || kpv.empty() ) - { - // the XML is highly unstable, allow users to override it - if ( qgetenv("IDA_KCACHE_IGNORE_XML", NULL) || !parse_prelink_xml() || kpv.empty() ) - scan_for_kexts(); - } - parsed_kmod_info = true; - } -} - -//------------------------------------------------------------------------ -const kmod_params_vec_t &macho_file_t::get_kmod_info(void) -{ - parse_kmod_info(); - return kpv; -} - -//-------------------------------------------------------------------------- -int macho_file_t::get_kmod_idx(const qstring &name) const -{ - for ( size_t i = 0, size = kpv.size(); i < size; i++ ) - { - if ( kpv[i].name == name ) - return i; - } - return -1; -} - -//-------------------------------------------------------------------------- -// process tagged pointers in an ARM64 kernelcache -// initial analysis was based on http://bazad.github.io/2018/06/ios-12-kernelcache-tagged-pointers/ -// but it did not take into account the final format that includes PAC support. -// the actual format is like following: -// __TEXT:__thread_starts is an array of 32-bit ints -// first one is flags, determining the skip size (4 or 8) -// the rest are offsets to starts of tagged pointer chains from the image base -// each chain contains pointers with tags in upper bits. -// bit 63: 1 if pointer is authenticated (protected with PAC) -// bit 62: 0 if pointer is tagged and needs to be rebased -// bits 51..61: skip count to the next pointer in chain (0 if last one) -// for PAC pointers: -// 49..50: key index (IA/IB/DA/DB) -// 32..47: diversity -// 0..31: offset from base -// for non-PAC pointers: -// 50..0: sign-extended pointer value -// TODO: unify processing with dyld_cache_t::parse_slid_chain/untag -//------------------------------------------------------------------------ -int macho_file_t::visit_threaded_pointers(kcache_pointer_visitor_t &v) -{ - bytevec_t data; - if ( !get_section(SEG_TEXT, "__thread_starts", &data) || data.empty() ) - return -1; - - uint32 *items = (uint32*)data.begin(); - size_t count = data.size() / sizeof(uint32); - if ( count <= 1 ) - return -1; // need to have at least one thread - - uint32 flags = items[0]; - int skipsize = (flags & 1) ? 8 : 4; - - for ( size_t i=1; i < count; i++ ) - { - uint32 off = items[i]; - if ( off == uint32(-1) ) - break; - - uint64 ea = base_addr + off; - int delta = 0; - do - { - uint64 raw_value = read_addr_at_va(ea); - if ( raw_value == BADADDR64 ) - break; - - int code = v.visit_pointer(ea, raw_value, untag(raw_value)); - if ( code != 0 ) - return code; - - delta = (raw_value >> 51) & 0x7FF; - ea += delta * skipsize; - } while ( delta != 0 ); - } - - return 0; -} - -//------------------------------------------------------------------------ -uint64 macho_file_t::untag(uint64 value) const -{ - uint64 untagged = value; - if ( (value & (1ull << 62)) == 0 ) - { - // signed pointer? - if ( value & (1ull << 63) ) - { - // use low 32 bits as offset from imagebase - untagged = base_addr + uint32(value); - } - else - { - // non-signed, adjust with 51-bit sign extension - untagged = UNTAG_51BIT_SE(value); - } - } - return untagged; -} - -//------------------------------------------------------------------------ -struct kcache_single_kmod_input_t : public generic_linput_t -{ - linput_t *kcache_li; - qoff64_t start_off; - qoff64_t prelink_data_off; - - kcache_single_kmod_input_t(linput_t *_kcache_li, qoff64_t _start_off, uint64 _prelink_data_off) - : kcache_li(_kcache_li), - start_off(_start_off), - prelink_data_off(_prelink_data_off) - { - filesize = qlsize(kcache_li); // kexts can have indeterminate size - blocksize = 0; - } - - virtual ssize_t idaapi read(qoff64_t off, void *buffer, size_t nbytes) override - { - // offsets in a kext's load commands are _usually_ relative to the base offset of the kext. - // it seems there is one exception: if the kernelcache has a common data segment for all kexts. - // offsets into this segment are absolute. - if ( prelink_data_off == 0 || off < prelink_data_off ) - off += start_off; - if ( qlseek(kcache_li, off, 0) != off ) - return -1; - return qlread(kcache_li, buffer, nbytes); - } -}; - -//------------------------------------------------------------------------ -linput_t *macho_file_t::create_single_kmod_input(qoff64_t start_off) -{ - section_64 s; - uint64 prelink_data_off = get_prelink_data(&s) ? s.offset : 0; - kcache_single_kmod_input_t *kli = new kcache_single_kmod_input_t( - li, - start_off, - prelink_data_off); - return create_generic_linput(kli); -} - -#if defined(LOADER_COMPILE) || defined(BUILD_DWARF) -//---------------------------------------------------------------------- -static linput_t *ida_export create_idb_linput(ea_t start, asize_t size) -{ - struct idb_linput_t : public generic_linput_t - { - ea_t start; - idb_linput_t(ea_t _start, asize_t _size) : start(_start) - { - filesize = _size; - blocksize = 0; - } - virtual ssize_t idaapi read(qoff64_t off, void *buffer, size_t nbytes) override - { - return get_bytes(buffer, nbytes, start+off); - } - }; - idb_linput_t *dml = new idb_linput_t(start, size); - linput_t *li = create_generic_linput(dml); - return li; -} -#endif diff --git a/idasdk75/ldr/mach-o/common.h b/idasdk75/ldr/mach-o/common.h deleted file mode 100644 index dd68d24..0000000 --- a/idasdk75/ldr/mach-o/common.h +++ /dev/null @@ -1,1145 +0,0 @@ -#ifndef MACHO_COMMON_H -#define MACHO_COMMON_H -#include <netnode.hpp> -#include <diskio.hpp> -#include <set> -#define IDA_SEG_DATA SEG_DATA -#define __inline__ inline -#ifndef __MAC__ -# define __DARWIN_UNIX03 1 -#endif -#if !__DARWIN_UNIX03 -#define __eax eax -#define __ebx ebx -#define __ecx ecx -#define __edx edx -#define __edi edi -#define __esi esi -#define __ebp ebp -#define __esp esp -#define __ss ss -#define __eflags eflags -#define __eip eip -#define __cs cs -#define __ds ds -#define __es es -#define __fs fs -#define __gs gs -#define __rax rax -#define __rbx rbx -#define __rcx rcx -#define __rdx rdx -#define __rdi rdi -#define __rsi rsi -#define __rbp rbp -#define __rsp rsp -#define __rflags rflags -#define __rip rip -#define __r8 r8 -#define __r9 r9 -#define __r10 r10 -#define __r11 r11 -#define __r12 r12 -#define __r13 r13 -#define __r14 r14 -#define __r15 r15 -#define __r r -#define __sp sp -#define __lr lr -#define __pc pc -#define __cpsr cpsr -#define __fpu_reserved fpu_reserved -#define __fpu_fcw fpu_fcw -#define __fpu_fsw fpu_fsw -#define __fpu_ftw fpu_ftw -#define __fpu_fop fpu_fop -#define __fpu_ip fpu_ip -#define __fpu_cs fpu_cs -#define __fpu_rsrv1 fpu_rsrv1 -#define __fpu_rsrv2 fpu_rsrv2 -#define __fpu_rsrv3 fpu_rsrv3 -#define __fpu_rsrv4 fpu_rsrv4 -#define __fpu_stmm0 fpu_stmm0 -#define __fpu_stmm1 fpu_stmm1 -#define __fpu_stmm2 fpu_stmm2 -#define __fpu_stmm3 fpu_stmm3 -#define __fpu_stmm4 fpu_stmm4 -#define __fpu_stmm5 fpu_stmm5 -#define __fpu_stmm6 fpu_stmm6 -#define __fpu_stmm7 fpu_stmm7 -#define __fpu_xmm0 fpu_xmm0 -#define __fpu_xmm1 fpu_xmm1 -#define __fpu_xmm2 fpu_xmm2 -#define __fpu_xmm3 fpu_xmm3 -#define __fpu_xmm4 fpu_xmm4 -#define __fpu_xmm5 fpu_xmm5 -#define __fpu_xmm6 fpu_xmm6 -#define __fpu_xmm7 fpu_xmm7 -#define __fpu_dp fpu_dp -#define __fpu_ds fpu_ds -#define __fpu_mxcsr fpu_mxcsr -#define __fpu_mxcsrmask fpu_mxcsrmask -#define __fpu_reserved fpu_reserved -#define __fpu_reserved1 fpu_reserved1 -#define __rc rc -#define __precis precis -#define __undfl undfl -#define __ovrfl ovrfl -#define __zdiv zdiv -#define __denorm denorm -#define __invalid invalid -#define __busy busy -#define __c3 c3 -#define __tos tos -#define __c2 c2 -#define __c1 c1 -#define __c0 c0 -#define __errsumm errsumm -#define __stkflt stkflt -#define __trapno trapno -#define __err err -#define __faultvaddr faultvaddr -#define __darwin_mmst_reg mmst_reg -#define __darwin_xmm_reg xmm_reg -#endif -#if __MF__ -#ifndef __BIG_ENDIAN__ -#define __BIG_ENDIAN__ 1 -#endif -#else -#ifndef __LITTLE_ENDIAN__ -#define __LITTLE_ENDIAN__ 1 -#endif -#endif -#ifdef __NT__ -#ifndef __ppc__ -#define __i386__ 1 -#endif -#define __attribute__(x) -#endif -#ifdef __LINUX__ -#define _DARWIN_C_SOURCE -#endif -#include <mach-o/fat.h> -#include <mach-o/loader.h> -#include <mach-o/reloc.h> -#include <mach-o/i860/reloc.h> -#include <mach-o/m88k/reloc.h> -#include <mach-o/ppc/reloc.h> -#include <mach-o/hppa/reloc.h> -#include <mach-o/sparc/reloc.h> -#include <mach-o/arm/reloc.h> -#include <mach-o/arm64/reloc.h> -#include <mach-o/x86_64/reloc.h> -#include <mach-o/nlist.h> -#include <mach-o/stab.h> -// these definitions are processor specific but are redefined in header files -// we undefine and never use them -#undef THREAD_STATE_NONE -#undef VALID_THREAD_STATE_FLAVOR -#undef MACHINE_THREAD_STATE -#undef MACHINE_THREAD_STATE_COUNT -#undef THREAD_STATE_MAX -#include <mach/i386/thread_status.h> -#undef THREAD_STATE_NONE -#undef VALID_THREAD_STATE_FLAVOR -#undef MACHINE_THREAD_STATE -#undef MACHINE_THREAD_STATE_COUNT -#undef THREAD_STATE_MAX -#define __arm__ 1 -#include <mach/arm/thread_status.h> -#undef __arm__ -#undef THREAD_STATE_NONE -#undef VALID_THREAD_STATE_FLAVOR -#undef MACHINE_THREAD_STATE -#undef MACHINE_THREAD_STATE_COUNT -#undef THREAD_STATE_MAX -CASSERT(sizeof(uint64_t) == 8); -#define SWAP_SHORT swap16 -#define SWAP_LONG swap32 -#define SWAP_LONG_LONG swap64 -inline double SWAP_DOUBLE(double d) -{ - CASSERT(sizeof(uint64) == sizeof(double)); - uint64 x = swap64(*(uint64*)&d); - return *(double *)&x; -} -#ifdef __LINUX__ -inline uint64_t swap64(uint64_t x) -{ - // This is supposed to call pro.a's llong.cpp's swap64(ulonglong), - // and thus _not_ endlessly recurse on itself --and maybe it does - // in IDA-- but in some other tools, this is causing a problem. - // For example, in EFD, we'd get segfaults because of - // stack overflows. - return make_ulonglong(swap32(high((ulonglong) x)), swap32(low((ulonglong) x))); - /* return swap64((ulonglong)x); */ -} -#endif -#define LC_ROUTINES_VALUE LC_ROUTINES_64 -#define LC_ROUTINES_NAME "LC_ROUTINES_64" -#include "macho_node.h" -#define MAX_DEPTH 1024 -// copy memory with range checking and auto sizing -template<class T> bool safecopy(const char *&begin, const char *end, T *dest) -{ - if ( end <= begin || (end - begin) < sizeof(T) ) - { - memset(dest, 0, sizeof(T)); - begin = end; - return false; - } - memcpy((char*)dest, begin, sizeof(T)); - begin += sizeof(T); - return true; -} -// advance the pointer with range and overflow checking -inline bool safeskip(const char *&begin, const char *end, size_t amount) -{ - if ( end <= begin || (end - begin) < amount ) - { - begin = end; - return false; - } - begin += amount; - return true; -} -void use_ppc_thread_state(const char *begin, const char *end, int mf); -void print_ppc_thread_state(const char *begin, const char *end, int mf); -DECLARE_TYPE_AS_MOVABLE(section_64); -DECLARE_TYPE_AS_MOVABLE(segment_command_64); -DECLARE_TYPE_AS_MOVABLE(nlist_64); -DECLARE_TYPE_AS_MOVABLE(relocation_info); -DECLARE_TYPE_AS_MOVABLE(dylib_module_64); -DECLARE_TYPE_AS_MOVABLE(dylib_table_of_contents); -DECLARE_TYPE_AS_MOVABLE(dylib_reference); -typedef qvector<struct section_64> secvec_t; -typedef qvector<struct segment_command_64> segcmdvec_t; -typedef qvector<struct nlist_64> nlistvec_t; -typedef qvector<struct relocation_info> relocvec_t; -typedef qvector<struct dylib_module_64> mod_table_t; -typedef qvector<struct dylib_table_of_contents> tocvec_t; -typedef qvector<struct dylib_reference> refvec_t; -typedef qstrvec_t dyliblist_t; -#define VISIT_COMMAND(name) virtual int visit_##name (const struct name##_command *, const char *, const char *) { return 0; } -#define VISIT_COMMAND64(name) virtual int visit_##name##_64 (const struct name##_command_64 *, const char *, const char *) { return 0; } -// callbacks for visit_load_commands() -struct macho_lc_visitor_t -{ - // called for all load commands - // lc: swapped load_command - // begin, end: pointers to raw (unswapped) command - // returns - // 0: call specific callback - // 1: stop enumeration - // 2: don't call specific callback and continue - virtual int visit_any_load_command(const struct load_command *, const char *, const char *) { return 0; } - // unknown load command - // return nonzero to stop enumeration - // NB: lc is swapped - virtual int visit_unknown_load_command(const struct load_command *, const char *, const char *) { return 0; } - // the following functions get cmd already in native byte order (at least headers) - // begin and end are pointers to raw, unswapped data - // virtual int visit_XX (const struct XX_command *cmd, char *begin, char *end) { return 0; } - // LC_SYMTAB - VISIT_COMMAND(symtab); - // LC_SYMSEG - VISIT_COMMAND(symseg); - // LC_THREAD, LC_UNIXTHREAD - VISIT_COMMAND(thread); - // LC_IDFVMLIB, LC_LOADFVMLIB - VISIT_COMMAND(fvmlib); - // LC_IDENT - VISIT_COMMAND(ident); - // LC_FVMFILE - VISIT_COMMAND(fvmfile); - // LC_DYSYMTAB - VISIT_COMMAND(dysymtab); - // LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, LC_ID_DYLIB, LC_REEXPORT_DYLIB, LC_LAZY_LOAD_DYLIB - VISIT_COMMAND(dylib); - // LC_ID_DYLINKER, LC_LOAD_DYLINKER - VISIT_COMMAND(dylinker); - // LC_PREBOUND_DYLIB - VISIT_COMMAND(prebound_dylib); - // LC_ROUTINES - VISIT_COMMAND(routines); - // LC_SUB_FRAMEWORK - VISIT_COMMAND(sub_framework); - // LC_SUB_UMBRELLA - VISIT_COMMAND(sub_umbrella); - // LC_SUB_CLIENT - VISIT_COMMAND(sub_client); - // LC_SUB_LIBRARY - VISIT_COMMAND(sub_library); - // LC_TWOLEVEL_HINTS - VISIT_COMMAND(twolevel_hints); - // LC_PREBIND_CKSUM - VISIT_COMMAND(prebind_cksum); - // LC_ROUTINES_64 - VISIT_COMMAND64(routines); - // LC_UUID - VISIT_COMMAND(uuid); - // LC_RPATH - VISIT_COMMAND(rpath); - // LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO, LC_FUNCTION_STARTS, LC_DATA_IN_CODE - // LC_DYLIB_CODE_SIGN_DRS - VISIT_COMMAND(linkedit_data); - // LC_ENCRYPTION_INFO - VISIT_COMMAND(encryption_info); - // LC_ENCRYPTION_INFO64 - virtual int visit_encryption_info_64(const struct encryption_info_command_64 *, const char *, const char *) { return 0; } - // LC_DYLD_INFO, LC_DYLD_INFO_ONLY - VISIT_COMMAND(dyld_info); - // LC_VERSION_MIN_MACOSX, LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_WATCHOS - VISIT_COMMAND(version_min); - // LC_BUILD_VERSION - VISIT_COMMAND(build_version); - virtual int visit_build_tool_version(const build_tool_version *, const char *, const char *) { return 0; } - // LC_SOURCE_VERSION - VISIT_COMMAND(source_version); - // LC_MAIN - VISIT_COMMAND(entry_point); - virtual int visit_segment(const segment_command *, const char *, const char *) { return 0; } - virtual int visit_segment(const segment_command_64 *, const char *, const char *) { return 0; } - // even though they're not strictly load commands, we also parse sections for convenience - virtual int visit_section(const struct section *, const char *, const char *) { return 0; } - virtual int visit_section(const struct section_64 *, const char *, const char *) { return 0; } - virtual ~macho_lc_visitor_t() {}; -}; -struct macho_reloc_visitor_t -{ - // magic values for section number - enum - { - mach_reloc_external = -2, - mach_reloc_local = -1, - }; - // callback for visit_relocs() - virtual void visit_relocs(uint64 baseea, const relocvec_t &relocs, int section_no) = 0; -}; -struct dyld_info_visitor_t -{ - // visit a rebase location - // type: type of rebasing (REBASE_TYPE_XXX) - virtual void visit_rebase(uint64_t /*address*/, uchar /*type*/) {} - enum bind_kind_t - { - bind_kind_normal = 0, - bind_kind_weak = 1, - bind_kind_lazy = 2, - }; - // visit a bind location - // bind_kind: which of bind directories are we walking - // type: bind type (BIND_TYPE_XXX) - // flags: BIND_SYMBOL_FLAGS_xxx - // addend: value added to symbol's address - // name: symbol name - virtual int visit_bind( - bind_kind_t /*bind_kind*/, - uint64_t /*address*/, - char /*type*/, - uchar /*flags*/, - int64_t /*libOrdinal*/, - int64_t /*addend*/, - const char * /*name*/) - { - return 0; - } - // visit an exported name - // flags: EXPORT_SYMBOL_FLAGS_XXX - virtual int visit_export( - uint64_t /*address*/, - uint32 /*flags*/, - const char * /*name*/) - { - return 0; - } -}; -struct function_starts_visitor_t -{ - // visit a function start - virtual int visit_start(uint64_t /*address*/) { return 0; } - // callback for when info could not be found/loaded - virtual void handle_error(); -}; -struct shared_region_visitor_t -{ - // kind: DYLD_CACHE_ADJ_V1_xx - virtual int visit_region(uint8 /* kind */, uint64_t /*address*/) { return 0; } - // kind: DYLD_CACHE_ADJ_V2_xx - virtual int visit_regionv2(uint8 /*kind*/, uint64_t /*from*/, uint64_t /*to*/) { return 0; } -}; - -bool has_contiguous_segments(const segcmdvec_t &segcmds); - -//-------------------------------------------------------------------------- -// from mach_loader.c -/* -* The first APPLE_UNPROTECTED_HEADER_SIZE bytes (from offset 0 of -* this part of a Universal binary) are not protected... -* The rest needs to be "transformed". -*/ -#define APPLE_UNPROTECTED_HEADER_SIZE (3 * PAGE_SIZE) -#define APPLE_PROTECTED_MAGIC_AES 0xc2286295 -#define APPLE_PROTECTED_MAGIC_BLOWFISH 0x2e69cf40 -#define IS_PROTECTED(sg) ((sg.flags & SG_PROTECTED_VERSION_1) != 0 \ - && sg.vmsize > 0 \ - && (sg.fileoff > APPLE_UNPROTECTED_HEADER_SIZE \ - || sg.fileoff + sg.filesize > APPLE_UNPROTECTED_HEADER_SIZE)) - -inline bool is_protected(const segment_command &sg) { return IS_PROTECTED(sg); } -inline bool is_protected(const segment_command_64 &sg) { return IS_PROTECTED(sg); } - -//-------------------------------------------------------------------------- -#define IS_PRELINK_INFO(s) (s.size > 0 && (strneq(s.sectname, "__info", 6) && strneq(s.segname, "__PRELINK", 9))) - -inline bool is_prelink_info(const section &s) { return IS_PRELINK_INFO(s); } -inline bool is_prelink_info(const section_64 &s) { return IS_PRELINK_INFO(s); } - -//-------------------------------------------------------------------------- -struct kmod_params -{ - uint64 kinfo_ea; // address of the kmod_info structure - uint64 kstart; // base vm address of this kext's __TEXT segment - uint64 ksize; // size of the kext - uint64 loadaddr; // vm address of the kext after it is initially loaded as part of the __PRELINK_TEXT segment - // (not always the same as kstart, since it might be relocated) - uint64 off; // start offset within the kernelcache file - qstring name; // name of the kext - uchar uuid[16]; // UUID of the kext - - kmod_params(void) : kinfo_ea(0), kstart(0), ksize(0), loadaddr(0), off(0) - { - memset(uuid, 0, sizeof(uuid)); - } -}; -DECLARE_TYPE_AS_MOVABLE(kmod_params); -typedef qvector<kmod_params> kmod_params_vec_t; - -//-------------------------------------------------------------------------- -struct kcache_pointer_visitor_t -{ - virtual int visit_pointer(uint64 ea, uint64 raw_value, uint64 untagged) = 0; -}; - -//-------------------------------------------------------------------------- -struct import_info_t -{ - uint64 impea; // addrress of the import pointer - qstring name; // name of the imported symbol - uint32 dylib; // index of the dylib providing the symbol (1-based) -}; -DECLARE_TYPE_AS_MOVABLE(import_info_t); -typedef qvector<import_info_t> impvec_t; -typedef std::set<int> dyldlib_set_t; - -class dyld_cache_t; - -//-------------------------------------------------------------------------- -// extract a module from an archive when loading a macho file into the database -struct macho_module_extractor_t -{ - virtual bool extract( - char *filename, - size_t bufsize, - char **temp_file_ptr, - bool is_remote) const = 0; -}; - -// for some idiotic reason these are macros in linux system headers -#undef major -#undef minor - -//-------------------------------------------------------------------------- -struct macho_platform_version_t -{ - uint32 plfm; // platform id: one of PLATFORM_... in mach-o/h/loader.h - uint32 major; // major version - uint32 minor; // minor version - uint32 micro; // revision - - macho_platform_version_t(void) - : plfm(0), major(0), minor(0), micro(0) {} -}; - -//-------------------------------------------------------------------------- -// information about the target platform for a given macho binary. -// -// version info is provided in the LC_VERSION_MIN_* and LC_BUILD_VERSION -// load commands. one, all, or none of these load commands could appear -// in any given macho file. -// -// each version can be useful in different situations. -struct macho_platform_version_info_t -{ - macho_platform_version_t build_minos; // build_version_command.minos - macho_platform_version_t build_sdk; // build_version_command.sdk - macho_platform_version_t min_version; // version_min_command.version - macho_platform_version_t min_sdk; // version_min_command.sdk -}; - -//-------------------------------------------------------------------------- -//-V:macho_file_t:730 not all members of a class are initialized inside the constructor -class macho_file_t -{ -protected: - // input file reference - linput_t *li; - bool should_close_linput; - // fat header (for fat files) - fat_header fheader; - // infos about available architecures - qvector<fat_arch> fat_archs; - // offset of main file in the stream - size_t start_offset; - // offset of the selected subfile - size_t mach_offset; - // size of the selected subfile - size_t mach_size; - // mach header + load commands - // NB: non-swapped - bytevec_t mach_header_data; - // do we need to swap endianness? - bool mf; - // is file 64-bit? - bool m64; - // header of currently selecte file (swapped) - mach_header_64 mh; - // list of load commands in the header - // pointers point into mach_header_data - qvector<const load_command *> load_commands; - // list of segment command (swapped) - segcmdvec_t mach_segcmds; - // list of section infos (swapped) - secvec_t mach_sections; - // seg2section[i] = index of the first section of segment i in the mach_sections array - intvec_t seg2section; - // list of prelinked kexts - kmod_params_vec_t kpv; - // list of dylibs (swapped) - dyliblist_t mach_dylibs; - // module table (swapped) - mod_table_t mach_modtable; - // toc (swapped) - tocvec_t mach_toc; - // reference table - refvec_t mach_reftable; - // are mach_sections and mach_segcmds valid? - bool parsed_section_info; - // are prelinked kext infos valid? - bool parsed_kmod_info; - // expected base address (vmaddr of the segment that includes the mach header) - uint64 base_addr; - // helper for extracting an archived mach-o file - macho_module_extractor_t *extractor; - // hints about this macho file - uint32 hints; -#define MACHO_HINT_MEM_IMAGE 0x0001 // macho file represents an image in memory -#define MACHO_HINT_SHARED_CACHE_LIB 0x0002 // macho file is a lib from dyld_shared_cache -#define MACHO_HINT_BRANCH_ISLAND 0x0004 // macho file is a dyldcache branch island - //load array of relocs from file with range checking and endianness swapping - bool load_relocs(uint32 reloff, uint32 nreloc, relocvec_t *relocs, const char *descr); - bool parse_fat_header(); - bool parse_load_commands(bool silent=false); - void parse_section_info(); - bool getSegInfo(uint64_t *segStartAddr, uint64_t *segSize, int segIndex); - void parse_kmod_info(void); - bool parse_kmod_starts(void); - bool parse_prelink_xml(void); - uint64 find_next_magic(uint64 off, uint64 end); - void scan_for_kexts(void); - bool visit_rebase_opcodes(const bytevec_t &data, dyld_info_visitor_t &v); - bool visit_bind_opcodes( - dyld_info_visitor_t::bind_kind_t bind_kind, - const bytevec_t &data, - dyld_info_visitor_t &v); - bool processExportNode( - const uchar *start, - const uchar *p, - const uchar *end, - char *symname, - int symnameoff, - size_t symnamelen, - dyld_info_visitor_t &v, - int level=0); - bool visit_export_info(const bytevec_t &data, dyld_info_visitor_t &v); - uint64 find_exported_symbol_dyld( - const char *symname, - bool verbose, - const dyld_cache_t *dcache = NULL); - uint64 va2off(uint64 addr); - friend class dyld_cache_t; -public: - macho_file_t(linput_t *_li, size_t _start_offset = 0, uint32 _hints = 0, macho_module_extractor_t *_extractor = NULL) - : li(_li), - should_close_linput(false), - start_offset(_start_offset), - mach_offset(-1), - mach_size(0), - mf(false), - m64(false), - parsed_section_info(false), - parsed_kmod_info(false), - base_addr(BADADDR), - extractor(_extractor), - hints(_hints) {} - virtual ~macho_file_t(void) - { - if ( should_close_linput ) - close_linput(li); - } - // check if file begins either with fat header or mach header - // must be called first - bool parse_header(); - // get fat header - // returns false if it's not a fat file - bool get_fat_header(fat_header *fh); - // get number of subfiles in a fat file - // 0 means it's a not fat file - size_t get_fat_subfiles() { return fat_archs.size(); } - // get fat_arch structure for subfile n - bool get_fat_arch(uint n, fat_arch *fa); - // set subfile for the following functions - // 0 works for non-fat files - // filesize: limit reads to this size; if 0, use linput's size - bool set_subfile(uint n, size_t filesize = 0, bool silent=false); - // select subfile of a specific cpu type (and subtype) - // cpusubtype of 0 matches any subtype - bool select_subfile(cpu_type_t cputype, cpu_subtype_t cpusubtype = (cpu_subtype_t)0); - // if the current submodule is an ar library, select a module from it and switch to it - bool select_ar_module(size_t offset, size_t size); - // get mach header for the current subfile - const mach_header_64 &get_mach_header(); - void get_mach_header_data(bytevec_t *out) const { *out = mach_header_data; } - bool is64() const { return m64; } - bool ismf() const { return mf; } - size_t get_subfile_offset() const { return mach_offset; } - size_t get_subfile_size() const { return mach_size; } - enum subfile_type_t - { - SUBFILE_UNKNOWN, - SUBFILE_MACH, - SUBFILE_MACH_64, - SUBFILE_AR - }; - subfile_type_t get_subfile_type(uint n, size_t filesize=0); - // Move the linput_t to the beginning of the n-th subfile. - // - // If this is not a FAT file, this will - // rewind the linput_t to the beginning of the file - // (plus a potential start_offset). - // - // returns true if successful, false otherwise. - bool seek_to_subfile(uint n, size_t filesize = 0); - // enumerate load commands and call visitor on each - // return true if visitor returned a non-zero - bool visit_load_commands(macho_lc_visitor_t &v); - // get segments and sections info - const segcmdvec_t &get_segcmds(); - const secvec_t &get_sections(); - size_t get_seg2section(size_t segidx) const { return seg2section[segidx]; } - // get section by 1-based index (0 for header pseudo-section) - bool get_section_or_hdr(section_64 *psect, size_t sectIndex); - // get segment by index - bool get_segment(size_t segIndex, segment_command_64 *pseg); - // get section by segment index and virtual address inside section - bool get_section(size_t segIndex, uint64_t vaddr, section_64 *psect); - // find segment by name - bool get_segment(const char *segname, segment_command_64 *pseg = NULL); - // get section by segment name and section name - bool get_section(const char *segname, const char *sectname, section_64 *psect = NULL); - // get section contents by segment name and section name - bool get_section(const char *segname, const char *sectname, bytevec_t *data); - // get list of dylibs (LC_LOAD_DYLIB) - // kind: which kind of dylibs to enumerate (LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB or LC_LAZY_LOAD_DYLIB) - // 0 = get all of them - const dyliblist_t get_dylib_list(int kind = 0); - // get dylib module table - const mod_table_t &get_module_table(); - // get dylib table of contents - const tocvec_t &get_toc(); - // get reference table - const refvec_t &get_ref_table(); - // get thread state (LC_THREAD/LC_UNIXTHREAD) - void get_thread_state(const char *&begin, const char *&end); - // get entrypoint (either from LC_MAIN, or from the thread state - uint64 get_entry_address(); - // check if file is encrypted - // returns: 0-no, 1-apple protected, 2-iOS encrypted - int is_encrypted(); - // load a chunk of data from the linkedit section - // size: number of bytes to load - // it is updated to the actual number of bytes loaded - bool load_linkedit_data(uint32 offset, size_t *size, void *buffer); - // get symbol table load command - bool get_symtab_command(struct symtab_command *st); - // load symbol table and string table - void get_symbol_table_info(nlistvec_t *symbols, qstring *strings); - void get_symbol_table(const struct symtab_command &st, nlistvec_t *symbols); - void get_string_table(const struct symtab_command &st, qstring *strings); - // gather all symbols imported from other dylibs together with the import pointers' addresses - size_t get_import_info(impvec_t *imports, dyliblist_t *dylibs, rangeset_t *ranges, bool verbose); - // get 16-bit uuid for this file - bool get_uuid(uint8 uuid[16]); - // get information about the target operating system - bool get_platform_version_info(macho_platform_version_info_t *mpvi); - // compare this macho file's uuid against the given bytes - bool match_uuid(const bytevec_t &bytes); - // gets the dysymtab_command from load commands - // return false if not found - bool get_dyst(struct dysymtab_command *dyst); - // load indirect symbols table - void get_indirect_symbol_table_info(qvector<uint32> *indirect_symbols); - // enumerate relocations and call visitor on each - void visit_relocs(macho_reloc_visitor_t &v); - // enumerate dyld_info structures - void visit_dyld_info(dyld_info_visitor_t &v); - // enumerate LC_FUNCTION_STARTS data - void visit_function_starts(function_starts_visitor_t &v); - // enumerate LC_SEGMENT_SPLIT_INFO data - void visit_shared_regions(shared_region_visitor_t &v); - // get preferrable base address - uint64 get_base() - { - if ( !parsed_section_info ) - parse_section_info(); - // default to 0 if we couldn't find it - return base_addr != BADADDR64 ? base_addr : 0; - } - // get the address of an exported symbol 'symname' - // will first try LC_DYLD_INFO_ONLY (if present), otherwise LC_SYMTAB - // returns BADADDR64 on error/not found - uint64 find_exported_symbol( - const char *symname, - bool verbose=false, - const dyld_cache_t *dcache=NULL); - // get the name of a symbol from its address - bool get_symbol_name( - qstring *name, - uint64 *offset, - uint64 address, - int sectionidx, - bool verbose = false, - const dyld_cache_t *dcache = NULL); - // return dylib ID, if present - bool get_id_dylib(qstring *id); - // get the linput pointer - linput_t *get_linput(void) const { return li; } - // test hint flags - bool is_mem_image() const { return (hints & MACHO_HINT_MEM_IMAGE) != 0; } - bool is_shared_cache_lib() const { return (hints & MACHO_HINT_SHARED_CACHE_LIB) != 0; } - bool is_branch_island() const { return (hints & MACHO_HINT_BRANCH_ISLAND) != 0; } - // is the address valid? - bool is_valid_addr(uint64 addr) const; - // does the address have an initialized byte? - bool is_loaded_addr(uint64 addr); - // read values by virtual address - uint64 read_dword_at_va(uint64 addr); - uint64 read_qword_at_va(uint64 addr); - uint64 read_addr_at_va(uint64 addr); - // read string by virtual address - char *read_string_at_va(uint64 addr, char *buf, size_t bufsize); - // is the linput a mach kernel executable? - bool is_kernel(); - // is the linput a prelinked kernelcache? - bool is_kcache(); - // is the linput a kernel extention? - bool is_kext() const; - // detect all prelinked KEXTs - const kmod_params_vec_t &get_kmod_info(void); - // get the index of the kmod_info for the kext with the given name (-1 if not found) - int get_kmod_idx(const qstring &name) const; - // get the section containing the prelink xml description - bool get_prelink_info(section_64 *prelink_info); - // get the data section common to all kexts - bool get_prelink_data(section_64 *prelink_data); - // get the section that contains the prelinked kexts - bool get_prelink_text(section_64 *prelink_text); - // create an linput for a given KEXT - linput_t *create_single_kmod_input(qoff64_t start_off); - // untag a threaded pointer - uint64 untag(uint64 value) const; - // visit all threaded pointers - int visit_threaded_pointers(kcache_pointer_visitor_t &pv); - // read fields from a kmod_info structure - uint64 get_kmod_ver(uint64 kinfo_ea); - uint64 get_kmod_start(uint64 kinfo_ea); - uint64 get_kmod_size(uint64 kinfo_ea); - uint64 get_kmod_hdr_size(uint64 kinfo_ea); - uint64 get_kmod_start_func(uint64 kinfo_ea); - qstring get_kmod_name(uint64 kinfo_ea); -}; - -struct dyld_cache_header -{ - char magic[16]; // e.g. "dyld_v0 ppc" - uint32_t mappingOffset; // file offset to first dyld_cache_mapping_info - uint32_t mappingCount; // number of dyld_cache_mapping_info entries - uint32_t imagesOffset; // file offset to first dyld_cache_image_info - uint32_t imagesCount; // number of dyld_cache_image_info entries - uint64_t dyldBaseAddress; // base address of dyld when cache was built - uint64_t codeSignatureOffset; // file offset in of code signature blob - uint64_t codeSignatureSize; // size of code signature blob (zero means to end of file) - uint64_t slideInfoOffset; // file offset of kernel slide info - uint64_t slideInfoSize; // size of kernel slide info - uint64_t localSymbolsOffset; // file offset of where local symbols are stored - uint64_t localSymbolsSize; // size of local symbols information - uint8_t uuid[16]; // unique value for each shared cache file - uint64_t cacheType; // 1 for development, 0 for optimized - uint32_t branchPoolsOffset; // file offset to table of uint64_t pool addresses - uint32_t branchPoolsCount; // number of uint64_t entries - uint64_t accelerateInfoAddr; // (unslid) address of optimization info - uint64_t accelerateInfoSize; // size of optimization info - uint64_t imagesTextOffset; // file offset to first dyld_cache_image_text_info - uint64_t imagesTextCount; // number of dyld_cache_image_text_info entries - uint64_t dylibsImageGroupAddr; // (unslid) address of ImageGroup for dylibs in this cache - uint64_t dylibsImageGroupSize; // size of ImageGroup for dylibs in this cache - uint64_t otherImageGroupAddr; // (unslid) address of ImageGroup for other OS dylibs - uint64_t otherImageGroupSize; // size of oImageGroup for other OS dylibs - uint64_t progClosuresAddr; // (unslid) address of list of program launch closures - uint64_t progClosuresSize; // size of list of program launch closures - uint64_t progClosuresTrieAddr; // (unslid) address of trie of indexes into program launch closures - uint64_t progClosuresTrieSize; // size of trie of indexes into program launch closures - uint32_t platform; // platform number (macOS=1, etc) - uint32_t flags; // formatVersion:8; dylibsExpectedOnDisk:1, simulator:1 - uint64_t sharedRegionStart; // base load address of cache if not slid - uint64_t sharedRegionSize; // overall size of region cache can be mapped into - uint64_t maxSlide; // runtime slide of cache can be between zero and this value -}; - -struct dyld_cache_mapping_info -{ - uint64_t address; - uint64_t size; - uint64_t fileOffset; - uint32_t maxProt; - uint32_t initProt; -}; - -struct dyld_cache_image_info -{ - uint64_t address; - uint64_t modTime; - uint64_t inode; - uint32_t pathFileOffset; - uint32_t pad; -}; - -struct dyld_cache_slide_info -{ - uint32_t version; // currently 1 - uint32_t toc_offset; - uint32_t toc_count; - uint32_t entries_offset; - uint32_t entries_count; - uint32_t entries_size; // currently 128 - // uint16_t toc[toc_count]; - // entrybitmap entries[entries_count]; -}; - -struct dyld_cache_slide_info2 -{ - uint32_t version; // currently 2 - uint32_t page_size; // currently 4096 (may also be 16384) - uint32_t page_starts_offset; - uint32_t page_starts_count; - uint32_t page_extras_offset; - uint32_t page_extras_count; - uint64_t delta_mask; // which (contiguous) set of bits contains the delta to the next rebase location - uint64_t value_add; - //uint16_t page_starts[page_starts_count]; - //uint16_t page_extras[page_extras_count]; -}; - -#define DYLD_CACHE_SLIDE_PAGE_ATTRS 0xC000 // high bits of uint16_t are flags -#define DYLD_CACHE_SLIDE_PAGE_ATTR_EXTRA 0x8000 // index is into extras array (not starts array) -#define DYLD_CACHE_SLIDE_PAGE_ATTR_NO_REBASE 0x4000 // page has no rebasing -#define DYLD_CACHE_SLIDE_PAGE_ATTR_END 0x8000 // last chain entry for page - -#define DYLD_CACHE_SLIDE_V3_PAGE_ATTR_NO_REBASE 0xFFFF // page has no rebasing - -struct dyld_cache_slide_info3 -{ - uint32_t version; // currently 3 - uint32_t page_size; // currently 4096 - uint32_t page_starts_count; - uint32_t padding; - uint64_t auth_value_add; - //uint16_t page_starts[page_starts_count]; -}; - -struct dyld_cache_local_symbols_info -{ - uint32_t nlistOffset; // offset into this chunk of nlist entries - uint32_t nlistCount; // count of nlist entries - uint32_t stringsOffset; // offset into this chunk of string pool - uint32_t stringsSize; // byte count of string pool - uint32_t entriesOffset; // offset into this chunk of array of dyld_cache_local_symbols_entry - uint32_t entriesCount; // number of elements in dyld_cache_local_symbols_entry array -}; - -struct dyld_cache_local_symbols_entry -{ - uint32_t dylibOffset; // offset in cache file of start of dylib - uint32_t nlistStartIndex; // start index of locals for this dylib - uint32_t nlistCount; // number of local symbols for this dylib -}; - -struct dyld_cache_image_text_info -{ - uint8_t uuid[16]; - uint64_t loadAddress; // unslid address of start of __TEXT - uint32_t textSegmentSize; - uint32_t pathOffset; // offset from start of cache file -}; - -// callback for visit_slid_pointers -struct dyld_cache_slide_visitor_t -{ - // dyld slide should be applied to the sanitized pointer at address 'addr' - // return: 0- ok, 1- stop iterating - virtual int visit_pointer(uint64 /*addr*/, uint64 /*untagged*/) { return 0; } - - DEFINE_VIRTUAL_DTOR(dyld_cache_slide_visitor_t); -}; - -//-------------------------------------------------------------------------- -//-V:dyld_cache_t:730 not all members of a class are initialized inside the constructor: header -class dyld_cache_t -{ -private: - // input file reference - linput_t *li; - - // header - dyld_cache_header header; - // mappings - qvector<dyld_cache_mapping_info> mappings; - // image infos - qvector<dyld_cache_image_info> image_infos; - // image text infos - qvector<dyld_cache_image_text_info> text_infos; - // image names - qvector<qstring> image_names; - - // branch islands - qvector<uint64> island_addrs; - - // slide info version - uint32 slide_version; - - // slide info v1: TOC - qvector<uint16> slide_toc; - // slide info v1: entry size (should be 128: 1 bit per 4 bytes per page) - uint32 slide_entries_size; - // slide info v1: bitmap TOC - bytevec_t slide_entries; - - // slide info v2: page starts - qvector<uint16> slide_page_starts; - // slide info v2: page extras - qvector<uint16> slide_page_extras; - // slide info v2: slide page size - uint32 slide_page_size; - // slide info v2: delta mask - uint64 slide_delta_mask; - // slide info v2: adjust pointer value - uint64 slide_value_add; - - // local symbol info - nlistvec_t localst_symbols; - qstring localst_strings; - qvector<dyld_cache_local_symbols_entry> localst_entries; - - // do we need to swap endianness? - bool mf; - // is file 64-bit? - bool m64; - - // manage linput: see open() - bool should_close_linput; - - void parse_local_symbols(); - - uint64 find_exported_symbol_dyld( - const char *dylib, - const char *symname, - bool verbose) const; - - int parse_slid_chain(dyld_cache_slide_visitor_t *v, uint64 start); - -public: - dyld_cache_t(linput_t *_li = NULL) - : li(_li), - slide_version(0), - slide_entries_size(0), - slide_page_size(0), - slide_delta_mask(0), - slide_value_add(0), - mf(false), - m64(false), - should_close_linput(false) {} - - ~dyld_cache_t() - { - if ( li != NULL && should_close_linput ) - close_linput(li); - } - - bool open(const char *path); - bool is64() const { return m64; } - bool ismf() const { return mf; } - -#define PHF_MAPPINGS 0x01 -#define PHF_IMAGES 0x02 -#define PHF_SYMBOLS 0x04 -#define PHF_ISLANDS 0x08 -#define PHF_SLIDE 0x10 -#define PHF_TEXT 0x20 -#define PHF_ALL 0xFF - - // check if file begins with a dyld cache header - // must be called first - bool parse_header(uint32 flags = PHF_ALL); - - const char *get_arch() const; - - const dyld_cache_header &get_header(void) const { return header; } - - const qstring &get_image_name(int n) const { return image_names[n]; } - const dyld_cache_mapping_info &get_mapping_info(int n) const { return mappings[n]; } - const dyld_cache_image_info &get_image_info(int n) const { return image_infos[n]; } - - uint64 get_island_addr(int n) const { return island_addrs[n]; } - - // return an linput which can be used for parsing a single Mach-O from the cache - // call close_linput() to close and free it - linput_t *create_single_macho_input(size_t imgindex) const; - linput_t *create_single_island_input(size_t index) const; - - // get an image's index in the list of images by full path - // returns -1 if not found - ssize_t get_image_index(const qstring &name) const - { - const qvector <qstring>::const_iterator p = image_names.find(name); - if ( p != image_names.end() ) - return p - image_names.begin(); - return -1; - }; - - int get_numfiles() const { return image_infos.size(); } - int get_nummappings() const { return mappings.size(); } - int get_numislands() const { return island_addrs.size(); } - - // load local symbol table and string table - void get_symbol_table_info(nlistvec_t *symbols, qstring *strings) const - { - *symbols = localst_symbols; - *strings = localst_strings; - } - // the the local symbols entry for the given image - const dyld_cache_local_symbols_entry *get_symbols_entry(int n) const; - - // get the address of a symbol 'symname' exported by dylib 'dylib' - // returns BADADDR64 on error/not found - uint64 find_exported_symbol( - const char *dylib, - const char *symname, - bool verbose=false) const; - - uint64 va2off(uint64 addr) const; - uint64 read_addr_at_va(uint64 addr) const; - char *read_string_at_va(uint64 addr, char *buf, size_t bufsize) const; - - linput_t *get_linput(void) const { return li; } - - bool has_slide_info() const { return !slide_toc.empty() || !slide_page_starts.empty(); } - bool calc_aslr_slide(int64 *slide, int n, bool verbose = false, qstring *errbuf = NULL) const; - int visit_slid_pointers(dyld_cache_slide_visitor_t *v); - uint32 get_slide_info_version() const { return slide_version; } - uint64 untag(uint64 v) const; - - uint64 get_shared_region_start() const { return header.sharedRegionStart; } - bytevec_t get_uuid() const { return bytevec_t(header.uuid, sizeof(header.uuid)); } - - void get_dependencies(dyldlib_set_t *p, int n, int max = -1); - - const dyld_cache_mapping_info *get_text_mapping(void) const; - bool get_header_range(uint64 *start, uint64 *end) const; - bool is_header_address(uint64 address) const; - - uint32 get_max_text_segm(void) const; - uint64 get_min_image_address(void) const; - - void get_modules(intvec_t *out) const; - void get_islands(intvec_t *out) const; -}; - -#define LOW50(v) (v & 0x7FFFFFFFFFFFFLL) -#define UNTAG_51BIT_SE(v) ((LOW50(v) << 13) & 0xFF00000000000000LL) | (((int64)(LOW50(v) << 21) >> 21) & 0xFFFFFFFFFFFFFFLL) - -// tagged pointer (ios12+) layout: -// bit 63: 1 if pointer is authenticated (protected with PAC) -// bit 62: 1: import/bound pointer (0: just rebase) -// bits 61..51: skip count to the next pointer in chain (0 if last one) -// for PAC pointers: -// 50..49: key index (IA/IB/DA/DB) -// 48: is address? -// 47..32: diversity -// 31..0: offset from base -// for non-PAC pointers: -// 50..0: sign-extended pointer value -class tagged_pointer64 -{ - uint64 raw_value; - bool bit(int n) { return (raw_value & (1ull << n)) != 0; } - uint64 bits(int high, int low) - { - return (raw_value >> low) & ((1ull << (high - low + 1)) - 1); - } - public: - tagged_pointer64(uint64 v) : raw_value(v) {}; - bool is_auth() { return bit(63); } - bool is_bind() { return bit(62); } - bool is_rebase() { return !bit(62); } - int skip_count() { return bits(61, 51); } - int key_index() { return bits(50, 49); } - bool is_addr() { return bit(48); } - int diversity() { return bits(47, 32); } - uint64 untag(uint64 base) - { - if ( is_auth() ) - { - //signed pointer: low 32 bits are offset from base - return base + bits(31, 0); - } - else - { - //non-signed, sign-extend low 51 bits - return UNTAG_51BIT_SE(raw_value); - } - } -}; - -struct string_table_waitbox_t -{ - bool displayed; - string_table_waitbox_t(const macho_file_t &mfile) : displayed(false) - { - // all dyld_shared_cache libs in memory share a common string table. - // since this table can be huge, be sure to show a wait dialog when parsing it. - if ( mfile.is_shared_cache_lib() && mfile.is_mem_image() ) - { - show_wait_box("Loading shared strings table"); - displayed = true; - } - } - ~string_table_waitbox_t() - { - if ( displayed ) - hide_wait_box(); - } - bool cancelled() { return user_cancelled(); } -}; -#endif // MACHO_COMMON_H - diff --git a/idasdk75/ldr/mach-o/h/LICENSE b/idasdk75/ldr/mach-o/h/LICENSE deleted file mode 100644 index 22eaacc..0000000 --- a/idasdk75/ldr/mach-o/h/LICENSE +++ /dev/null @@ -1,100 +0,0 @@ -APPLE PUBLIC SOURCE LICENSE -Version 2.0 - August 6, 2003 - -Please read this License carefully before downloading this software. By downloading or using this software, you are agreeing to be bound by the terms of this License. If you do not or cannot agree to the terms of this License, please do not download or use the software. - -Apple Note: In January 2007, Apple changed its corporate name from "Apple Computer, Inc." to "Apple Inc." This change has been reflected below and copyright years updated, but no other changes have been made to the APSL 2.0. - -1. General; Definitions. This License applies to any program or other work which Apple Inc. ("Apple") makes publicly available and which contains a notice placed by Apple identifying such program or work as "Original Code" and stating that it is subject to the terms of this Apple Public Source License version 2.0 ("License"). As used in this License: - -1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to Apple and (ii) that cover subject matter contained in the Original Code, but only to the extent necessary to use, reproduce and/or distribute the Original Code without infringement; and (b) in the case where You are the grantor of rights, (i) claims of patents that are now or hereafter acquired, owned by or assigned to You and (ii) that cover subject matter in Your Modifications, taken alone or in combination with Original Code. - -1.2 "Contributor" means any person or entity that creates or contributes to the creation of Modifications. - -1.3 "Covered Code" means the Original Code, Modifications, the combination of Original Code and any Modifications, and/or any respective portions thereof. - -1.4 "Externally Deploy" means: (a) to sublicense, distribute or otherwise make Covered Code available, directly or indirectly, to anyone other than You; and/or (b) to use Covered Code, alone or as part of a Larger Work, in any way to provide a service, including but not limited to delivery of content, through electronic communication with a client other than You. - -1.5 "Larger Work" means a work which combines Covered Code or portions thereof with code not governed by the terms of this License. - -1.6 "Modifications" mean any addition to, deletion from, and/or change to, the substance and/or structure of the Original Code, any previous Modifications, the combination of Original Code and any previous Modifications, and/or any respective portions thereof. When code is released as a series of files, a Modification is: (a) any addition to or deletion from the contents of a file containing Covered Code; and/or (b) any new file or other representation of computer program statements that contains any part of Covered Code. - -1.7 "Original Code" means (a) the Source Code of a program or other work as originally made available by Apple under this License, including the Source Code of any updates or upgrades to such programs or works made available by Apple under this License, and that has been expressly identified by Apple as such in the header file(s) of such work; and (b) the object code compiled from such Source Code and originally made available by Apple under this License - -1.8 "Source Code" means the human readable form of a program or other work that is suitable for making modifications to it, including all modules it contains, plus any associated interface definition files, scripts used to control compilation and installation of an executable (object code). - -1.9 "You" or "Your" means an individual or a legal entity exercising rights under this License. For legal entities, "You" or "Your" includes any entity which controls, is controlled by, or is under common control with, You, where "control" means (a) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (b) ownership of fifty percent (50%) or more of the outstanding shares or beneficial ownership of such entity. - -2. Permitted Uses; Conditions & Restrictions. Subject to the terms and conditions of this License, Apple hereby grants You, effective on the date You accept this License and download the Original Code, a world-wide, royalty-free, non-exclusive license, to the extent of Apple's Applicable Patent Rights and copyrights covering the Original Code, to do the following: - -2.1 Unmodified Code. You may use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy verbatim, unmodified copies of the Original Code, for commercial or non-commercial purposes, provided that in each instance: - -(a) You must retain and reproduce in all copies of Original Code the copyright and other proprietary notices and disclaimers of Apple as they appear in the Original Code, and keep intact all notices in the Original Code that refer to this License; and - -(b) You must include a copy of this License with every copy of Source Code of Covered Code and documentation You distribute or Externally Deploy, and You may not offer or impose any terms on such Source Code that alter or restrict this License or the recipients' rights hereunder, except as permitted under Section 6. - -2.2 Modified Code. You may modify Covered Code and use, reproduce, display, perform, internally distribute within Your organization, and Externally Deploy Your Modifications and Covered Code, for commercial or non-commercial purposes, provided that in each instance You also meet all of these conditions: - -(a) You must satisfy all the conditions of Section 2.1 with respect to the Source Code of the Covered Code; - -(b) You must duplicate, to the extent it does not already exist, the notice in Exhibit A in each file of the Source Code of all Your Modifications, and cause the modified files to carry prominent notices stating that You changed the files and the date of any change; and - -(c) If You Externally Deploy Your Modifications, You must make Source Code of all Your Externally Deployed Modifications either available to those to whom You have Externally Deployed Your Modifications, or publicly available. Source Code of Your Externally Deployed Modifications must be released under the terms set forth in this License, including the license grants set forth in Section 3 below, for as long as you Externally Deploy the Covered Code or twelve (12) months from the date of initial External Deployment, whichever is longer. You should preferably distribute the Source Code of Your Externally Deployed Modifications electronically (e.g. download from a web site). - -2.3 Distribution of Executable Versions. In addition, if You Externally Deploy Covered Code (Original Code and/or Modifications) in object code, executable form only, You must include a prominent notice, in the code itself as well as in related documentation, stating that Source Code of the Covered Code is available under the terms of this License with information on how and where to obtain such Source Code. - -2.4 Third Party Rights. You expressly acknowledge and agree that although Apple and each Contributor grants the licenses to their respective portions of the Covered Code set forth herein, no assurances are provided by Apple or any Contributor that the Covered Code does not infringe the patent or other intellectual property rights of any other entity. Apple and each Contributor disclaim any liability to You for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, You hereby assume sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow You to distribute the Covered Code, it is Your responsibility to acquire that license before distributing the Covered Code. - -3. Your Grants. In consideration of, and as a condition to, the licenses granted to You under this License, You hereby grant to any person or entity receiving or distributing Covered Code under this License a non-exclusive, royalty-free, perpetual, irrevocable license, under Your Applicable Patent Rights and other intellectual property rights (other than patent) owned or controlled by You, to use, reproduce, display, perform, modify, sublicense, distribute and Externally Deploy Your Modifications of the same scope and extent as Apple's licenses under Sections 2.1 and 2.2 above. - -4. Larger Works. You may create a Larger Work by combining Covered Code with other code not governed by the terms of this License and distribute the Larger Work as a single product. In each such instance, You must make sure the requirements of this License are fulfilled for the Covered Code or any portion thereof. - -5. Limitations on Patent License. Except as expressly stated in Section 2, no other patent rights, express or implied, are granted by Apple herein. Modifications and/or Larger Works may require additional patent licenses from Apple which Apple may grant in its sole discretion. - -6. Additional Terms. You may choose to offer, and to charge a fee for, warranty, support, indemnity or liability obligations and/or other rights consistent with the scope of the license granted herein ("Additional Terms") to one or more recipients of Covered Code. However, You may do so only on Your own behalf and as Your sole responsibility, and not on behalf of Apple or any Contributor. You must obtain the recipient's agreement that any such Additional Terms are offered by You alone, and You hereby agree to indemnify, defend and hold Apple and every Contributor harmless for any liability incurred by or claims asserted against Apple or such Contributor by reason of any such Additional Terms. - -7. Versions of the License. Apple may publish revised and/or new versions of this License from time to time. Each version will be given a distinguishing version number. Once Original Code has been published under a particular version of this License, You may continue to use it under the terms of that version. You may also choose to use such Original Code under the terms of any subsequent version of this License published by Apple. No one other than Apple has the right to modify the terms applicable to Covered Code created under this License. - -8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in part pre-release, untested, or not fully tested works. The Covered Code may contain errors that could cause failures or loss of data, and may be incomplete or contain inaccuracies. You expressly acknowledge and agree that use of the Covered Code, or any portion thereof, is at Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS, THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY. You acknowledge that the Covered Code is not intended for use in the operation of nuclear facilities, aircraft navigation, communication systems, or air traffic control machines in which case the failure of the Covered Code could lead to death, personal injury, or severe physical or environmental damage. - -9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY TO YOU. In no event shall Apple's total liability to You for all damages (other than as may be required by applicable law) under this License exceed the amount of fifty dollars ($50.00). - -10. Trademarks. This License does not grant any rights to use the trademarks or trade names "Apple", "Mac", "Mac OS", "QuickTime", "QuickTime Streaming Server" or any other trademarks, service marks, logos or trade names belonging to Apple (collectively "Apple Marks") or to any trademark, service mark, logo or trade name belonging to any Contributor. You agree not to use any Apple Marks in or as part of the name of products derived from the Original Code or to endorse or promote products derived from the Original Code other than as expressly permitted by and in strict compliance at all times with Apple's third party trademark usage guidelines which are posted at http://www.apple.com/legal/guidelinesfor3rdparties.html. - -11. Ownership. Subject to the licenses granted under this License, each Contributor retains all rights, title and interest in and to any Modifications made by such Contributor. Apple retains all rights, title and interest in and to the Original Code and any Modifications made by or on behalf of Apple ("Apple Modifications"), and such Apple Modifications will not be automatically subject to this License. Apple may, at its sole discretion, choose to license such Apple Modifications under this License, or on different terms from those contained in this License or may choose not to license them at all. - -12. Termination. - -12.1 Termination. This License and the rights granted hereunder will terminate: - -(a) automatically without notice from Apple if You fail to comply with any term(s) of this License and fail to cure such breach within 30 days of becoming aware of such breach; -(b) immediately in the event of the circumstances described in Section 13.5(b); or -(c) automatically without notice from Apple if You, at any time during the term of this License, commence an action for patent infringement against Apple; provided that Apple did not first commence an action for patent infringement against You in that instance. - -12.2 Effect of Termination. Upon termination, You agree to immediately stop any further use, reproduction, modification, sublicensing and distribution of the Covered Code. All sublicenses to the Covered Code which have been properly granted prior to termination shall survive any termination of this License. Provisions which, by their nature, should remain in effect beyond the termination of this License shall survive, including but not limited to Sections 3, 5, 8, 9, 10, 11, 12.2 and 13. No party will be liable to any other for compensation, indemnity or damages of any sort solely as a result of terminating this License in accordance with its terms, and termination of this License will be without prejudice to any other right or remedy of any party. - -13. Miscellaneous. - -13.1 Government End Users. The Covered Code is a "commercial item" as defined in FAR 2.101. Government software and technical data rights in the Covered Code include only those rights customarily provided to the public as defined in this License. This customary commercial license in technical data and software is provided in accordance with FAR 12.211 (Technical Data) and 12.212 (Computer Software) and, for Department of Defense purchases, DFAR 252.227-7015 (Technical Data -- Commercial Items) and 227.7202-3 (Rights in Commercial Computer Software or Computer Software Documentation). Accordingly, all U.S. Government End Users acquire Covered Code with only those rights set forth herein. - -13.2 Relationship of Parties. This License will not be construed as creating an agency, partnership, joint venture or any other form of legal association between or among You, Apple or any Contributor, and You will not represent to the contrary, whether expressly, by implication, appearance or otherwise. - -13.3 Independent Development. Nothing in this License will impair Apple's right to acquire, license, develop, have others develop for it, market and/or distribute technology or products that perform the same or similar functions as, or otherwise compete with, Modifications, Larger Works, technology or products that You may develop, produce, market or distribute. - -13.4 Waiver; Construction. Failure by Apple or any Contributor to enforce any provision of this License will not be deemed a waiver of future enforcement of that or any other provision. Any law or regulation which provides that the language of a contract shall be construed against the drafter will not apply to this License. - -13.5 Severability. (a) If for any reason a court of competent jurisdiction finds any provision of this License, or portion thereof, to be unenforceable, that provision of the License will be enforced to the maximum extent permissible so as to effect the economic benefits and intent of the parties, and the remainder of this License will continue in full force and effect. (b) Notwithstanding the foregoing, if applicable law prohibits or restricts You from fully and/or specifically complying with Sections 2 and/or 3 or prevents the enforceability of either of those Sections, this License will immediately terminate and You must immediately discontinue any use of the Covered Code and destroy all copies of it that are in your possession or control. - -13.6 Dispute Resolution. Any litigation or other dispute resolution between You and Apple relating to this License shall take place in the Northern District of California, and You and Apple hereby consent to the personal jurisdiction of, and venue in, the state and federal courts within that District with respect to this License. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. - -13.7 Entire Agreement; Governing Law. This License constitutes the entire agreement between the parties with respect to the subject matter hereof. This License shall be governed by the laws of the United States and the State of California, except that body of California law concerning conflicts of law. - -Where You are located in the province of Quebec, Canada, the following clause applies: The parties hereby confirm that they have requested that this License and all related documents be drafted in English. Les parties ont exigé que le présent contrat et tous les documents connexes soient rédigés en anglais. - -EXHIBIT A. - -"Portions Copyright (c) 1999-2007 Apple Inc. All Rights Reserved. - -This file contains Original Code and/or Modifications of Original Code as defined in and that are subject to the Apple Public Source License Version 2.0 (the 'License'). You may not use this file except in compliance with the License. Please obtain a copy of the License at http://www.opensource.apple.com/apsl/ and read it before using this file. - -The Original Code and all software distributed under the License are distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the specific language governing rights and limitations under the License." diff --git a/idasdk75/ldr/mach-o/h/architecture/byte_order.h b/idasdk75/ldr/mach-o/h/architecture/byte_order.h deleted file mode 100644 index fe1e785..0000000 --- a/idasdk75/ldr/mach-o/h/architecture/byte_order.h +++ /dev/null @@ -1,381 +0,0 @@ -/* - * Copyright (c) 1999-2008 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1992 NeXT Computer, Inc. - * - * Byte ordering conversion. - * - */ - -#ifndef _ARCHITECTURE_BYTE_ORDER_H_ -#define _ARCHITECTURE_BYTE_ORDER_H_ - -/* - * Please note that the byte ordering functions in this file are deprecated. - * A replacement API exists in libkern/OSByteOrder.h - */ - -#include <libkern/OSByteOrder.h> - -typedef unsigned long NXSwappedFloat; -typedef unsigned long long NXSwappedDouble; - -__inline__ -unsigned short -NXSwapShort( - unsigned short inv -) -{ - return (unsigned short)OSSwapInt16((uint16_t)inv); -} - -__inline__ -unsigned int -NXSwapInt( - unsigned int inv -) -{ - return (unsigned int)OSSwapInt32((uint32_t)inv); -} - -__inline__ -unsigned long -NXSwapLong( - unsigned long inv -) -{ - return (unsigned long)OSSwapInt32((uint32_t)inv); -} - -__inline__ -unsigned long long -NXSwapLongLong( - unsigned long long inv -) -{ - return (unsigned long long)OSSwapInt64((uint64_t)inv); -} - -__inline__ -NXSwappedFloat -NXConvertHostFloatToSwapped(float x) -{ - union fconv { - float number; - NXSwappedFloat sf; - } u; - u.number = x; - return u.sf; -} - -__inline__ -float -NXConvertSwappedFloatToHost(NXSwappedFloat x) -{ - union fconv { - float number; - NXSwappedFloat sf; - } u; - u.sf = x; - return u.number; -} - -__inline__ -NXSwappedDouble -NXConvertHostDoubleToSwapped(double x) -{ - union dconv { - double number; - NXSwappedDouble sd; - } u; - u.number = x; - return u.sd; -} - -__inline__ -double -NXConvertSwappedDoubleToHost(NXSwappedDouble x) -{ - union dconv { - double number; - NXSwappedDouble sd; - } u; - u.sd = x; - return u.number; -} - -__inline__ -NXSwappedFloat -NXSwapFloat(NXSwappedFloat x) -{ - return (NXSwappedFloat)OSSwapInt32((uint32_t)x); -} - -__inline__ -NXSwappedDouble -NXSwapDouble(NXSwappedDouble x) -{ - return (NXSwappedDouble)OSSwapInt64((uint64_t)x); -} - -/* - * Identify the byte order - * of the current host. - */ - -enum NXByteOrder { - NX_UnknownByteOrder, - NX_LittleEndian, - NX_BigEndian -}; - -__inline__ -enum NXByteOrder -NXHostByteOrder(void) -{ -#if defined(__LITTLE_ENDIAN__) - return NX_LittleEndian; -#elif defined(__BIG_ENDIAN__) - return NX_BigEndian; -#else - return NX_UnknownByteOrder; -#endif -} - -__inline__ -unsigned short -NXSwapBigShortToHost( - unsigned short x -) -{ - return (unsigned short)OSSwapBigToHostInt16((uint16_t)x); -} - -__inline__ -unsigned int -NXSwapBigIntToHost( - unsigned int x -) -{ - return (unsigned int)OSSwapBigToHostInt32((uint32_t)x); -} - -__inline__ -unsigned long -NXSwapBigLongToHost( - unsigned long x -) -{ - return (unsigned long)OSSwapBigToHostInt32((uint32_t)x); -} - -__inline__ -unsigned long long -NXSwapBigLongLongToHost( - unsigned long long x -) -{ - return (unsigned long long)OSSwapBigToHostInt64((uint64_t)x); -} - -__inline__ -double -NXSwapBigDoubleToHost( - NXSwappedDouble x -) -{ - return NXConvertSwappedDoubleToHost((NXSwappedDouble)OSSwapBigToHostInt64((uint64_t)x)); -} - -__inline__ -float -NXSwapBigFloatToHost( - NXSwappedFloat x -) -{ - return NXConvertSwappedFloatToHost((NXSwappedFloat)OSSwapBigToHostInt32((uint32_t)x)); -} - -__inline__ -unsigned short -NXSwapHostShortToBig( - unsigned short x -) -{ - return (unsigned short)OSSwapHostToBigInt16((uint16_t)x); -} - -__inline__ -unsigned int -NXSwapHostIntToBig( - unsigned int x -) -{ - return (unsigned int)OSSwapHostToBigInt32((uint32_t)x); -} - -__inline__ -unsigned long -NXSwapHostLongToBig( - unsigned long x -) -{ - return (unsigned long)OSSwapHostToBigInt32((uint32_t)x); -} - -__inline__ -unsigned long long -NXSwapHostLongLongToBig( - unsigned long long x -) -{ - return (unsigned long long)OSSwapHostToBigInt64((uint64_t)x); -} - -__inline__ -NXSwappedDouble -NXSwapHostDoubleToBig( - double x -) -{ - return (NXSwappedDouble)OSSwapHostToBigInt64((uint64_t)NXConvertHostDoubleToSwapped(x)); -} - -__inline__ -NXSwappedFloat -NXSwapHostFloatToBig( - float x -) -{ - return (NXSwappedFloat)OSSwapHostToBigInt32((uint32_t)NXConvertHostFloatToSwapped(x)); -} - -__inline__ -unsigned short -NXSwapLittleShortToHost( - unsigned short x -) -{ - return (unsigned short)OSSwapLittleToHostInt16((uint16_t)x); -} - -__inline__ -unsigned int -NXSwapLittleIntToHost( - unsigned int x -) -{ - return (unsigned int)OSSwapLittleToHostInt32((uint32_t)x); -} - -__inline__ -unsigned long -NXSwapLittleLongToHost( - unsigned long x -) -{ - return (unsigned long)OSSwapLittleToHostInt32((uint32_t)x); -} - -__inline__ -unsigned long long -NXSwapLittleLongLongToHost( - unsigned long long x -) -{ - return (unsigned long long)OSSwapLittleToHostInt64((uint64_t)x); -} - -__inline__ -double -NXSwapLittleDoubleToHost( - NXSwappedDouble x -) -{ - return NXConvertSwappedDoubleToHost((NXSwappedDouble)OSSwapLittleToHostInt64((uint64_t)x)); -} - -__inline__ -float -NXSwapLittleFloatToHost( - NXSwappedFloat x -) -{ - return NXConvertSwappedFloatToHost((NXSwappedFloat)OSSwapLittleToHostInt32((uint32_t)x)); -} - -__inline__ -unsigned short -NXSwapHostShortToLittle( - unsigned short x -) -{ - return (unsigned short)OSSwapHostToLittleInt16((uint16_t)x); -} - -__inline__ -unsigned int -NXSwapHostIntToLittle( - unsigned int x -) -{ - return (unsigned int)OSSwapHostToLittleInt32((uint32_t)x); -} - -__inline__ -unsigned long -NXSwapHostLongToLittle( - unsigned long x -) -{ - return (unsigned long)OSSwapHostToLittleInt32((uint32_t)x); -} - -__inline__ -unsigned long long -NXSwapHostLongLongToLittle( - unsigned long long x -) -{ - return (unsigned long long)OSSwapHostToLittleInt64((uint64_t)x); -} - -__inline__ -NXSwappedDouble -NXSwapHostDoubleToLittle( - double x -) -{ - return (NXSwappedDouble)OSSwapHostToLittleInt64((uint64_t)NXConvertHostDoubleToSwapped(x)); -} - -__inline__ -NXSwappedFloat -NXSwapHostFloatToLittle( - float x -) -{ - return (NXSwappedFloat)OSSwapHostToLittleInt32((uint32_t)NXConvertHostFloatToSwapped(x)); -} - -#endif /* _ARCHITECTURE_BYTE_ORDER_H_ */ diff --git a/idasdk75/ldr/mach-o/h/architecture/i386/fpu.h b/idasdk75/ldr/mach-o/h/architecture/i386/fpu.h deleted file mode 100644 index 2e8ff8f..0000000 --- a/idasdk75/ldr/mach-o/h/architecture/i386/fpu.h +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1992 NeXT Computer, Inc. - * - * Intel386 Family: Floating Point unit. - * - * HISTORY - * - * 5 October 1992 ? at NeXT - * Added names to previously unamed fields in the mantissa. - * - * 5 April 1992 ? at NeXT - * Created. - */ - -#ifndef _ARCH_I386_FPU_H_ -#define _ARCH_I386_FPU_H_ - -/* - * Data register. - */ - -typedef struct fp_data_reg { - unsigned short mant; - unsigned short mant1 :16, - mant2 :16, - mant3 :16; - unsigned short exp :15, - sign :1; -} fp_data_reg_t; - -/* - * Data register stack. - */ - -typedef struct fp_stack { - fp_data_reg_t ST[8]; -} fp_stack_t; - -/* - * Register stack tag word. - */ - -typedef struct fp_tag { - unsigned short tag0 :2, - tag1 :2, - tag2 :2, - tag3 :2, - tag4 :2, - tag5 :2, - tag6 :2, - tag7 :2; -#define FP_TAG_VALID 0 -#define FP_TAG_ZERO 1 -#define FP_TAG_SPEC 2 -#define FP_TAG_EMPTY 3 -} fp_tag_t; - -/* - * Status word. - */ - -typedef struct fp_status { - unsigned short invalid :1, - denorm :1, - zdiv :1, - ovrfl :1, - undfl :1, - precis :1, - stkflt :1, - errsumm :1, - c0 :1, - c1 :1, - c2 :1, - tos :3, - c3 :1, - busy :1; -} fp_status_t; - -/* - * Control word. - */ - -typedef struct fp_control { - unsigned short invalid :1, - denorm :1, - zdiv :1, - ovrfl :1, - undfl :1, - precis :1, - :2, - pc :2, -#define FP_PREC_24B 0 -#define FP_PREC_53B 2 -#define FP_PREC_64B 3 - rc :2, -#define FP_RND_NEAR 0 -#define FP_RND_DOWN 1 -#define FP_RND_UP 2 -#define FP_CHOP 3 - /*inf*/ :1, - :3; -} fp_control_t; - -#include <architecture/i386/sel.h> - -/* - * Floating point 'environment' - * used by FSTENV/FLDENV instructions. - */ - -typedef struct fp_env { - fp_control_t control; - unsigned short :16; - fp_status_t status; - unsigned short :16; - fp_tag_t tag; - unsigned short :16; - unsigned int ip; - sel_t cs; - unsigned short opcode; - unsigned int dp; - sel_t ds; - unsigned short :16; -} fp_env_t; - -/* - * Floating point state - * used by FSAVE/FRSTOR instructions. - */ - -/* - * To allow the the common idiom of: - * #define environ (*_NSGetEnviron()) - * to be used these fields were renamed. Old code that that does - * not use this idiom can use the old field names by defining - * _ARCHITECTURE_I386_FPU_FPSTATE_LEGACY_FIELD_NAMES_ . - */ -typedef struct fp_state { -#if _ARCHITECTURE_I386_FPU_FPSTATE_LEGACY_FIELD_NAMES_ - fp_env_t environ; - fp_stack_t stack; -#else - fp_env_t fp_environ; - fp_stack_t fp_stack; -#endif -} fp_state_t; - -#endif /* _ARCH_I386_FPU_H_ */ diff --git a/idasdk75/ldr/mach-o/h/architecture/i386/frame.h b/idasdk75/ldr/mach-o/h/architecture/i386/frame.h deleted file mode 100644 index 9395e86..0000000 --- a/idasdk75/ldr/mach-o/h/architecture/i386/frame.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1992 NeXT Computer, Inc. - * - * Intel386 Family: Processor exception frame. - * - * HISTORY - * - * 31 August 1992 ? at NeXT - * Added v86 mode stuff. - * - * 8 June 1992 ? at NeXT - * Changed name of write field in err_code_t - * which collided with write() in shlib. - * - * 30 March 1992 ? at NeXT - * Created. - */ - -#ifndef _ARCH_I386_FRAME_H_ -#define _ARCH_I386_FRAME_H_ - -/* - * Format of the error code - * generated by the hardware - * for certain exceptions. - */ - -typedef union err_code { - struct err_code_normal { - unsigned int ext :1, - tbl :2, -#define ERR_GDT 0 -#define ERR_IDT 1 -#define ERR_LDT 2 - index :13, - :16; - } normal; - struct err_code_pgfault { - unsigned int prot :1, - wrtflt :1, - user :1, - :29; - } pgfault; -} err_code_t; - -#include <architecture/i386/sel.h> - -/* - * The actual hardware exception frame - * is variable in size. An error code is - * only pushed for certain exceptions. - * Previous stack information is only - * pushed for exceptions that cause a - * change in privilege level. The dpl - * field of the saved CS selector can be - * used to determine whether this is the - * case. If the interrupted task was - * executing in v86 mode, then the data - * segment registers are also present in - * the exception frame (in addition to - * previous stack information). This - * case can be determined by examining - * eflags. - */ - -typedef struct except_frame { - err_code_t err; - unsigned int eip; - sel_t cs; - unsigned int :0; - unsigned int eflags; - unsigned int esp; - sel_t ss; - unsigned int :0; - unsigned short v_es; - unsigned int :0; - unsigned short v_ds; - unsigned int :0; - unsigned short v_fs; - unsigned int :0; - unsigned short v_gs; - unsigned int :0; -} except_frame_t; - -/* - * Values in eflags. - */ - -#define EFL_CF 0x00001 -#define EFL_PF 0x00004 -#define EFL_AF 0x00010 -#define EFL_ZF 0x00040 -#define EFL_SF 0x00080 -#define EFL_TF 0x00100 -#define EFL_IF 0x00200 -#define EFL_DF 0x00400 -#define EFL_OF 0x00800 -#define EFL_IOPL 0x03000 -#define EFL_NT 0x04000 -#define EFL_RF 0x10000 -#define EFL_VM 0x20000 -#define EFL_AC 0x40000 - -#define EFL_CLR 0xfff88028 -#define EFL_SET 0x00000002 - -#endif /* _ARCH_I386_FRAME_H_ */ diff --git a/idasdk75/ldr/mach-o/h/architecture/i386/sel.h b/idasdk75/ldr/mach-o/h/architecture/i386/sel.h deleted file mode 100644 index 9bd4da5..0000000 --- a/idasdk75/ldr/mach-o/h/architecture/i386/sel.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1992 NeXT Computer, Inc. - * - * Intel386 Family: Segment selector. - * - * HISTORY - * - * 29 March 1992 ? at NeXT - * Created. - */ - -#ifndef _ARCH_I386_SEL_H_ -#define _ARCH_I386_SEL_H_ - -/* - * Segment selector. - */ - -typedef struct sel { - unsigned short rpl :2, -#define KERN_PRIV 0 -#define USER_PRIV 3 - ti :1, -#define SEL_GDT 0 -#define SEL_LDT 1 - index :13; -} sel_t; - -#define NULL_SEL ((sel_t) { 0, 0, 0 } ) - -#endif /* _ARCH_I386_SEL_H_ */ diff --git a/idasdk75/ldr/mach-o/h/arm/_structs.h b/idasdk75/ldr/mach-o/h/arm/_structs.h deleted file mode 100644 index 3a9af6b..0000000 --- a/idasdk75/ldr/mach-o/h/arm/_structs.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2006-2007 Apple Inc. All rights reserved. - */ - -#include <sys/appleapiopts.h> - -#ifdef __need_mcontext_t -#ifndef __need_struct_mcontext -#define __need_struct_mcontext -#endif /* __need_struct_mcontext */ -#endif /* __need_mcontext_t */ - -#if defined(__need_struct_mcontext) -#include <mach/arm/_structs.h> -#endif /* __need_struct_mcontext */ - -#ifdef __need_struct_mcontext -#undef __need_struct_mcontext - -#ifndef _STRUCT_MCONTEXT -#if __DARWIN_UNIX03 -#define _STRUCT_MCONTEXT struct __darwin_mcontext -_STRUCT_MCONTEXT -{ - _STRUCT_ARM_EXCEPTION_STATE __es; - _STRUCT_ARM_THREAD_STATE __ss; - _STRUCT_ARM_VFP_STATE __fs; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_MCONTEXT struct mcontext -_STRUCT_MCONTEXT -{ - _STRUCT_ARM_EXCEPTION_STATE es; - _STRUCT_ARM_THREAD_STATE ss; - _STRUCT_ARM_VFP_STATE fs; -}; -#endif /* __DARWIN_UNIX03 */ -#endif /* _STRUCT_MCONTEXT */ -#endif /* __need_struct_mcontext */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#ifndef ARM_MCONTEXT_SIZE -#define ARM_MCONTEXT_SIZE (ARM_THREAD_STATE_COUNT + ARM_VFP_STATE_COUNT + ARM_EXCEPTION_STATE_COUNT) * sizeof(int) -#endif /* ARM_MCONTEXT_SIZE */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ diff --git a/idasdk75/ldr/mach-o/h/arm/_types.h b/idasdk75/ldr/mach-o/h/arm/_types.h deleted file mode 100644 index 8077022..0000000 --- a/idasdk75/ldr/mach-o/h/arm/_types.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - */ -#ifndef _BSD_ARM__TYPES_H_ -#define _BSD_ARM__TYPES_H_ - -/* - * This header file contains integer types. It's intended to also contain - * flotaing point and other arithmetic types, as needed, later. - */ - -#ifdef __GNUC__ -typedef __signed char __int8_t; -#else /* !__GNUC__ */ -typedef char __int8_t; -#endif /* !__GNUC__ */ -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; -typedef long long __int64_t; -typedef unsigned long long __uint64_t; - -typedef long __darwin_intptr_t; -typedef unsigned int __darwin_natural_t; - -/* - * The rune type below is declared to be an ``int'' instead of the more natural - * ``unsigned long'' or ``long''. Two things are happening here. It is not - * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, - * it looks like 10646 will be a 31 bit standard. This means that if your - * ints cannot hold 32 bits, you will be in trouble. The reason an int was - * chosen over a long is that the is*() and to*() routines take ints (says - * ANSI C), but they use __darwin_ct_rune_t instead of int. By changing it - * here, you lose a bit of ANSI conformance, but your programs will still - * work. - * - * NOTE: rune_t is not covered by ANSI nor other standards, and should not - * be instantiated outside of lib/libc/locale. Use wchar_t. wchar_t and - * rune_t must be the same type. Also wint_t must be no narrower than - * wchar_t, and should also be able to hold all members of the largest - * character set plus one extra value (WEOF). wint_t must be at least 16 bits. - */ - -typedef int __darwin_ct_rune_t; /* ct_rune_t */ - -/* - * mbstate_t is an opaque object to keep conversion state, during multibyte - * stream conversions. The content must not be referenced by user programs. - */ -typedef union { - char __mbstate8[128]; - long long _mbstateL; /* for alignment */ -} __mbstate_t; - -typedef __mbstate_t __darwin_mbstate_t; /* mbstate_t */ - -#if defined(__GNUC__) && defined(__PTRDIFF_TYPE__) -typedef __PTRDIFF_TYPE__ __darwin_ptrdiff_t; /* ptr1 - ptr2 */ -#else -typedef int __darwin_ptrdiff_t; /* ptr1 - ptr2 */ -#endif /* __GNUC__ */ - -#if defined(__GNUC__) && defined(__SIZE_TYPE__) -typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */ -#else -typedef unsigned long __darwin_size_t; /* sizeof() */ -#endif - -#if (__GNUC__ > 2) -typedef __builtin_va_list __darwin_va_list; /* va_list */ -#else -typedef void * __darwin_va_list; /* va_list */ -#endif - -#if defined(__GNUC__) && defined(__WCHAR_TYPE__) -typedef __WCHAR_TYPE__ __darwin_wchar_t; /* wchar_t */ -#else -typedef __darwin_ct_rune_t __darwin_wchar_t; /* wchar_t */ -#endif - -typedef __darwin_wchar_t __darwin_rune_t; /* rune_t */ - -#if defined(__GNUC__) && defined(__WINT_TYPE__) -typedef __WINT_TYPE__ __darwin_wint_t; /* wint_t */ -#else -typedef __darwin_ct_rune_t __darwin_wint_t; /* wint_t */ -#endif - -typedef unsigned long __darwin_clock_t; /* clock() */ -typedef __uint32_t __darwin_socklen_t; /* socklen_t (duh) */ -typedef long __darwin_ssize_t; /* byte count or error */ -typedef long __darwin_time_t; /* time() */ - -#endif /* _BSD_ARM__TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/i386/_structs.h b/idasdk75/ldr/mach-o/h/i386/_structs.h deleted file mode 100644 index 9e41981..0000000 --- a/idasdk75/ldr/mach-o/h/i386/_structs.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include <sys/appleapiopts.h> - -#ifdef __need_mcontext_t -#ifndef __need_struct_mcontext -#define __need_struct_mcontext -#endif /* __need_struct_mcontext */ -#endif /* __need_mcontext_t */ - -#if defined(__need_struct_mcontext) -#include <mach/i386/_structs.h> -#endif /* __need_struct_mcontext */ - - -#ifdef __need_struct_mcontext -#undef __need_struct_mcontext - -#ifndef _STRUCT_MCONTEXT32 -#if __DARWIN_UNIX03 -#define _STRUCT_MCONTEXT32 struct __darwin_mcontext32 -_STRUCT_MCONTEXT32 -{ - _STRUCT_X86_EXCEPTION_STATE32 __es; - _STRUCT_X86_THREAD_STATE32 __ss; - _STRUCT_X86_FLOAT_STATE32 __fs; -}; - -#define _STRUCT_MCONTEXT_AVX32 struct __darwin_mcontext_avx32 -_STRUCT_MCONTEXT_AVX32 -{ - _STRUCT_X86_EXCEPTION_STATE32 __es; - _STRUCT_X86_THREAD_STATE32 __ss; - _STRUCT_X86_AVX_STATE32 __fs; -}; - -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_MCONTEXT32 struct mcontext32 -_STRUCT_MCONTEXT32 -{ - _STRUCT_X86_EXCEPTION_STATE32 es; - _STRUCT_X86_THREAD_STATE32 ss; - _STRUCT_X86_FLOAT_STATE32 fs; -}; - -#define _STRUCT_MCONTEXT_AVX32 struct mcontext_avx32 -_STRUCT_MCONTEXT_AVX32 -{ - _STRUCT_X86_EXCEPTION_STATE32 es; - _STRUCT_X86_THREAD_STATE32 ss; - _STRUCT_X86_AVX_STATE32 fs; -}; - -#endif /* __DARWIN_UNIX03 */ -#endif /* _STRUCT_MCONTEXT32 */ - -#ifndef _STRUCT_MCONTEXT64 -#if __DARWIN_UNIX03 -#define _STRUCT_MCONTEXT64 struct __darwin_mcontext64 -_STRUCT_MCONTEXT64 -{ - _STRUCT_X86_EXCEPTION_STATE64 __es; - _STRUCT_X86_THREAD_STATE64 __ss; - _STRUCT_X86_FLOAT_STATE64 __fs; -}; - -#define _STRUCT_MCONTEXT_AVX64 struct __darwin_mcontext_avx64 -_STRUCT_MCONTEXT_AVX64 -{ - _STRUCT_X86_EXCEPTION_STATE64 __es; - _STRUCT_X86_THREAD_STATE64 __ss; - _STRUCT_X86_AVX_STATE64 __fs; -}; - -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_MCONTEXT64 struct mcontext64 -_STRUCT_MCONTEXT64 -{ - _STRUCT_X86_EXCEPTION_STATE64 es; - _STRUCT_X86_THREAD_STATE64 ss; - _STRUCT_X86_FLOAT_STATE64 fs; -}; - -#define _STRUCT_MCONTEXT_AVX64 struct mcontext_avx64 -_STRUCT_MCONTEXT_AVX64 -{ - _STRUCT_X86_EXCEPTION_STATE64 es; - _STRUCT_X86_THREAD_STATE64 ss; - _STRUCT_X86_AVX_STATE64 fs; -}; - -#endif /* __DARWIN_UNIX03 */ -#endif /* _STRUCT_MCONTEXT64 */ -#endif /* __need_struct_mcontext */ - -#ifdef __need_mcontext_t -#undef __need_mcontext_t -#ifndef _MCONTEXT_T -#define _MCONTEXT_T -#if defined(__LP64__) -typedef _STRUCT_MCONTEXT64 *mcontext_t; -#define _STRUCT_MCONTEXT _STRUCT_MCONTEXT64 -#else -typedef _STRUCT_MCONTEXT32 *mcontext_t; -#define _STRUCT_MCONTEXT _STRUCT_MCONTEXT32 -#endif -#endif /* _MCONTEXT_T */ -#endif /* __need_mcontext_t */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#ifndef I386_MCONTEXT_SIZE -#define I386_MCONTEXT_SIZE sizeof(struct mcontext) -#endif /* I386_MCONTEXT_SIZE */ -#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ - diff --git a/idasdk75/ldr/mach-o/h/i386/_types.h b/idasdk75/ldr/mach-o/h/i386/_types.h deleted file mode 100644 index 06217b4..0000000 --- a/idasdk75/ldr/mach-o/h/i386/_types.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -#ifndef _BSD_I386__TYPES_H_ -#define _BSD_I386__TYPES_H_ - -/* - * This header file contains integer types. It's intended to also contain - * flotaing point and other arithmetic types, as needed, later. - */ - -#ifndef __LINUX__ -#ifdef __GNUC__ -typedef __signed char __int8_t; -#else /* !__GNUC__ */ -typedef char __int8_t; -#endif /* !__GNUC__ */ -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; -typedef long long __int64_t; -typedef unsigned long long __uint64_t; -#endif - -typedef long __darwin_intptr_t; -typedef unsigned int __darwin_natural_t; - -/* - * The rune type below is declared to be an ``int'' instead of the more natural - * ``unsigned long'' or ``long''. Two things are happening here. It is not - * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, - * it looks like 10646 will be a 31 bit standard. This means that if your - * ints cannot hold 32 bits, you will be in trouble. The reason an int was - * chosen over a long is that the is*() and to*() routines take ints (says - * ANSI C), but they use __darwin_ct_rune_t instead of int. By changing it - * here, you lose a bit of ANSI conformance, but your programs will still - * work. - * - * NOTE: rune_t is not covered by ANSI nor other standards, and should not - * be instantiated outside of lib/libc/locale. Use wchar_t. wchar_t and - * rune_t must be the same type. Also wint_t must be no narrower than - * wchar_t, and should also be able to hold all members of the largest - * character set plus one extra value (WEOF). wint_t must be at least 16 bits. - */ - -typedef int __darwin_ct_rune_t; /* ct_rune_t */ - -#ifndef __LINUX__ -/* - * mbstate_t is an opaque object to keep conversion state, during multibyte - * stream conversions. The content must not be referenced by user programs. - */ -typedef union { - char __mbstate8[128]; - long long _mbstateL; /* for alignment */ -} __mbstate_t; -#endif - -typedef __mbstate_t __darwin_mbstate_t; /* mbstate_t */ - -#if defined(__GNUC__) && defined(__PTRDIFF_TYPE__) -typedef __PTRDIFF_TYPE__ __darwin_ptrdiff_t; /* ptr1 - ptr2 */ -#else -typedef int __darwin_ptrdiff_t; /* ptr1 - ptr2 */ -#endif /* __GNUC__ */ - -#if defined(__GNUC__) && defined(__SIZE_TYPE__) -typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */ -#else -typedef unsigned long __darwin_size_t; /* sizeof() */ -#endif - -#if (__GNUC__ > 2) -typedef __builtin_va_list __darwin_va_list; /* va_list */ -#else -typedef void * __darwin_va_list; /* va_list */ -#endif - -#if defined(__GNUC__) && defined(__WCHAR_TYPE__) -typedef __WCHAR_TYPE__ __darwin_wchar_t; /* wchar_t */ -#else -typedef __darwin_ct_rune_t __darwin_wchar_t; /* wchar_t */ -#endif - -typedef __darwin_wchar_t __darwin_rune_t; /* rune_t */ - -#if defined(__GNUC__) && defined(__WINT_TYPE__) -typedef __WINT_TYPE__ __darwin_wint_t; /* wint_t */ -#else -typedef __darwin_ct_rune_t __darwin_wint_t; /* wint_t */ -#endif - -typedef unsigned long __darwin_clock_t; /* clock() */ -typedef __uint32_t __darwin_socklen_t; /* socklen_t (duh) */ -typedef long __darwin_ssize_t; /* byte count or error */ -typedef long __darwin_time_t; /* time() */ - -#endif /* _BSD_I386__TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/i386/eflags.h b/idasdk75/ldr/mach-o/h/i386/eflags.h deleted file mode 100644 index f9f625e..0000000 --- a/idasdk75/ldr/mach-o/h/i386/eflags.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -#ifndef _I386_EFLAGS_H_ -#define _I386_EFLAGS_H_ - -/* - * i386 flags register - */ - -#ifndef EFL_CF -#define EFL_CF 0x00000001 /* carry */ -#define EFL_PF 0x00000004 /* parity of low 8 bits */ -#define EFL_AF 0x00000010 /* carry out of bit 3 */ -#define EFL_ZF 0x00000040 /* zero */ -#define EFL_SF 0x00000080 /* sign */ -#define EFL_TF 0x00000100 /* trace trap */ -#define EFL_IF 0x00000200 /* interrupt enable */ -#define EFL_DF 0x00000400 /* direction */ -#define EFL_OF 0x00000800 /* overflow */ -#define EFL_IOPL 0x00003000 /* IO privilege level: */ -#define EFL_IOPL_KERNEL 0x00000000 /* kernel */ -#define EFL_IOPL_USER 0x00003000 /* user */ -#define EFL_NT 0x00004000 /* nested task */ -#define EFL_RF 0x00010000 /* resume without tracing */ -#define EFL_VM 0x00020000 /* virtual 8086 mode */ -#define EFL_AC 0x00040000 /* alignment check */ -#define EFL_VIF 0x00080000 /* virtual interrupt flag */ -#define EFL_VIP 0x00100000 /* virtual interrupt pending */ -#define EFL_ID 0x00200000 /* cpuID instruction */ -#endif - -#define EFL_CLR 0xfff88028 -#define EFL_SET 0x00000002 - -#define EFL_USER_SET (EFL_IF) -#define EFL_USER_CLEAR (EFL_IOPL|EFL_NT|EFL_RF) - -#endif /* _I386_EFLAGS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/libkern/OSByteOrder.h b/idasdk75/ldr/mach-o/h/libkern/OSByteOrder.h deleted file mode 100644 index 58bb245..0000000 --- a/idasdk75/ldr/mach-o/h/libkern/OSByteOrder.h +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _OS_OSBYTEORDER_H -#define _OS_OSBYTEORDER_H - -#include <stdint.h> - -/* Macros for swapping constant values in the preprocessing stage. */ -#define OSSwapConstInt16(x) \ - ((uint16_t)((((uint16_t)(x) & 0xff00) >> 8) | \ - (((uint16_t)(x) & 0x00ff) << 8))) - -#define OSSwapConstInt32(x) \ - ((uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x000000ff) << 24))) - -#define OSSwapConstInt64(x) \ - ((uint64_t)((((uint64_t)(x) & 0xff00000000000000ULL) >> 56) | \ - (((uint64_t)(x) & 0x00ff000000000000ULL) >> 40) | \ - (((uint64_t)(x) & 0x0000ff0000000000ULL) >> 24) | \ - (((uint64_t)(x) & 0x000000ff00000000ULL) >> 8) | \ - (((uint64_t)(x) & 0x00000000ff000000ULL) << 8) | \ - (((uint64_t)(x) & 0x0000000000ff0000ULL) << 24) | \ - (((uint64_t)(x) & 0x000000000000ff00ULL) << 40) | \ - (((uint64_t)(x) & 0x00000000000000ffULL) << 56))) - -#if defined(__GNUC__) - -#if (defined(__ppc__) || defined(__ppc64__)) -#include <libkern/ppc/OSByteOrder.h> -#elif (defined(__i386__) || defined(__x86_64__)) -#include <libkern/i386/OSByteOrder.h> -#elif defined(__arm__) -#include <libkern/arm/OSByteOrder.h> -#else -#include <libkern/machine/OSByteOrder.h> -#endif - -#define OSSwapInt16(x) \ - (__builtin_constant_p(x) ? OSSwapConstInt16(x) : _OSSwapInt16(x)) - -#define OSSwapInt32(x) \ - (__builtin_constant_p(x) ? OSSwapConstInt32(x) : _OSSwapInt32(x)) - -#define OSSwapInt64(x) \ - (__builtin_constant_p(x) ? OSSwapConstInt64(x) : _OSSwapInt64(x)) - -#else /* ! __GNUC__ */ - -#include <libkern/machine/OSByteOrder.h> - -#define OSSwapInt16(x) OSSwapConstInt16(x) - -#define OSSwapInt32(x) OSSwapConstInt32(x) - -#define OSSwapInt64(x) OSSwapConstInt64(x) - -#endif /* __GNUC__ */ - -enum { - OSUnknownByteOrder, - OSLittleEndian, - OSBigEndian -}; - -OS_INLINE -int32_t -OSHostByteOrder(void) { -#if defined(__LITTLE_ENDIAN__) - return OSLittleEndian; -#elif defined(__BIG_ENDIAN__) - return OSBigEndian; -#else - return OSUnknownByteOrder; -#endif -} - -#define OSReadBigInt(x, y) OSReadBigInt32(x, y) -#define OSWriteBigInt(x, y, z) OSWriteBigInt32(x, y, z) -#define OSSwapBigToHostInt(x) OSSwapBigToHostInt32(x) -#define OSSwapHostToBigInt(x) OSSwapHostToBigInt32(x) -#define OSReadLittleInt(x, y) OSReadLittleInt32(x, y) -#define OSWriteLittleInt(x, y, z) OSWriteLittleInt32(x, y, z) -#define OSSwapHostToLittleInt(x) OSSwapHostToLittleInt32(x) -#define OSSwapLittleToHostInt(x) OSSwapLittleToHostInt32(x) - -/* Functions for loading native endian values. */ - -OS_INLINE -uint16_t -_OSReadInt16( - const volatile void * base, - uintptr_t byteOffset -) -{ - return *(volatile uint16_t *)((uintptr_t)base + byteOffset); -} - -OS_INLINE -uint32_t -_OSReadInt32( - const volatile void * base, - uintptr_t byteOffset -) -{ - return *(volatile uint32_t *)((uintptr_t)base + byteOffset); -} - -OS_INLINE -uint64_t -_OSReadInt64( - const volatile void * base, - uintptr_t byteOffset -) -{ - return *(volatile uint64_t *)((uintptr_t)base + byteOffset); -} - -/* Functions for storing native endian values. */ - -OS_INLINE -void -_OSWriteInt16( - volatile void * base, - uintptr_t byteOffset, - uint16_t data -) -{ - *(volatile uint16_t *)((uintptr_t)base + byteOffset) = data; -} - -OS_INLINE -void -_OSWriteInt32( - volatile void * base, - uintptr_t byteOffset, - uint32_t data -) -{ - *(volatile uint32_t *)((uintptr_t)base + byteOffset) = data; -} - -OS_INLINE -void -_OSWriteInt64( - volatile void * base, - uintptr_t byteOffset, - uint64_t data -) -{ - *(volatile uint64_t *)((uintptr_t)base + byteOffset) = data; -} - -#if defined(__BIG_ENDIAN__) - -/* Functions for loading big endian to host endianess. */ - -#define OSReadBigInt16(base, byteOffset) _OSReadInt16(base, byteOffset) -#define OSReadBigInt32(base, byteOffset) _OSReadInt32(base, byteOffset) -#define OSReadBigInt64(base, byteOffset) _OSReadInt64(base, byteOffset) - -/* Functions for storing host endianess to big endian. */ - -#define OSWriteBigInt16(base, byteOffset, data) _OSWriteInt16(base, byteOffset, data) -#define OSWriteBigInt32(base, byteOffset, data) _OSWriteInt32(base, byteOffset, data) -#define OSWriteBigInt64(base, byteOffset, data) _OSWriteInt64(base, byteOffset, data) - -/* Functions for loading little endian to host endianess. */ - -#define OSReadLittleInt16(base, byteOffset) OSReadSwapInt16(base, byteOffset) -#define OSReadLittleInt32(base, byteOffset) OSReadSwapInt32(base, byteOffset) -#define OSReadLittleInt64(base, byteOffset) OSReadSwapInt64(base, byteOffset) - -/* Functions for storing host endianess to little endian. */ - -#define OSWriteLittleInt16(base, byteOffset, data) OSWriteSwapInt16(base, byteOffset, data) -#define OSWriteLittleInt32(base, byteOffset, data) OSWriteSwapInt32(base, byteOffset, data) -#define OSWriteLittleInt64(base, byteOffset, data) OSWriteSwapInt64(base, byteOffset, data) - -/* Host endianess to big endian byte swapping macros for constants. */ - -#define OSSwapHostToBigConstInt16(x) (x) -#define OSSwapHostToBigConstInt32(x) (x) -#define OSSwapHostToBigConstInt64(x) (x) - -/* Generic host endianess to big endian byte swapping functions. */ - -#define OSSwapHostToBigInt16(x) ((uint16_t)(x)) -#define OSSwapHostToBigInt32(x) ((uint32_t)(x)) -#define OSSwapHostToBigInt64(x) ((uint64_t)(x)) - -/* Host endianess to little endian byte swapping macros for constants. */ - -#define OSSwapHostToLittleConstInt16(x) OSSwapConstInt16(x) -#define OSSwapHostToLittleConstInt32(x) OSSwapConstInt32(x) -#define OSSwapHostToLittleConstInt64(x) OSSwapConstInt64(x) - -/* Generic host endianess to little endian byte swapping functions. */ - -#define OSSwapHostToLittleInt16(x) OSSwapInt16(x) -#define OSSwapHostToLittleInt32(x) OSSwapInt32(x) -#define OSSwapHostToLittleInt64(x) OSSwapInt64(x) - -/* Big endian to host endianess byte swapping macros for constants. */ - -#define OSSwapBigToHostConstInt16(x) (x) -#define OSSwapBigToHostConstInt32(x) (x) -#define OSSwapBigToHostConstInt64(x) (x) - -/* Generic big endian to host endianess byte swapping functions. */ - -#define OSSwapBigToHostInt16(x) ((uint16_t)(x)) -#define OSSwapBigToHostInt32(x) ((uint32_t)(x)) -#define OSSwapBigToHostInt64(x) ((uint64_t)(x)) - -/* Little endian to host endianess byte swapping macros for constants. */ - -#define OSSwapLittleToHostConstInt16(x) OSSwapConstInt16(x) -#define OSSwapLittleToHostConstInt32(x) OSSwapConstInt32(x) -#define OSSwapLittleToHostConstInt64(x) OSSwapConstInt64(x) - -/* Generic little endian to host endianess byte swapping functions. */ - -#define OSSwapLittleToHostInt16(x) OSSwapInt16(x) -#define OSSwapLittleToHostInt32(x) OSSwapInt32(x) -#define OSSwapLittleToHostInt64(x) OSSwapInt64(x) - -#elif defined(__LITTLE_ENDIAN__) - -/* Functions for loading big endian to host endianess. */ - -#define OSReadBigInt16(base, byteOffset) OSReadSwapInt16(base, byteOffset) -#define OSReadBigInt32(base, byteOffset) OSReadSwapInt32(base, byteOffset) -#define OSReadBigInt64(base, byteOffset) OSReadSwapInt64(base, byteOffset) - -/* Functions for storing host endianess to big endian. */ - -#define OSWriteBigInt16(base, byteOffset, data) OSWriteSwapInt16(base, byteOffset, data) -#define OSWriteBigInt32(base, byteOffset, data) OSWriteSwapInt32(base, byteOffset, data) -#define OSWriteBigInt64(base, byteOffset, data) OSWriteSwapInt64(base, byteOffset, data) - -/* Functions for loading little endian to host endianess. */ - -#define OSReadLittleInt16(base, byteOffset) _OSReadInt16(base, byteOffset) -#define OSReadLittleInt32(base, byteOffset) _OSReadInt32(base, byteOffset) -#define OSReadLittleInt64(base, byteOffset) _OSReadInt64(base, byteOffset) - -/* Functions for storing host endianess to little endian. */ - -#define OSWriteLittleInt16(base, byteOffset, data) _OSWriteInt16(base, byteOffset, data) -#define OSWriteLittleInt32(base, byteOffset, data) _OSWriteInt32(base, byteOffset, data) -#define OSWriteLittleInt64(base, byteOffset, data) _OSWriteInt64(base, byteOffset, data) - -/* Host endianess to big endian byte swapping macros for constants. */ - -#define OSSwapHostToBigConstInt16(x) OSSwapConstInt16(x) -#define OSSwapHostToBigConstInt32(x) OSSwapConstInt32(x) -#define OSSwapHostToBigConstInt64(x) OSSwapConstInt64(x) - -/* Generic host endianess to big endian byte swapping functions. */ - -#define OSSwapHostToBigInt16(x) OSSwapInt16(x) -#define OSSwapHostToBigInt32(x) OSSwapInt32(x) -#define OSSwapHostToBigInt64(x) OSSwapInt64(x) - -/* Host endianess to little endian byte swapping macros for constants. */ - -#define OSSwapHostToLittleConstInt16(x) (x) -#define OSSwapHostToLittleConstInt32(x) (x) -#define OSSwapHostToLittleConstInt64(x) (x) - -/* Generic host endianess to little endian byte swapping functions. */ - -#define OSSwapHostToLittleInt16(x) ((uint16_t)(x)) -#define OSSwapHostToLittleInt32(x) ((uint32_t)(x)) -#define OSSwapHostToLittleInt64(x) ((uint64_t)(x)) - -/* Big endian to host endianess byte swapping macros for constants. */ - -#define OSSwapBigToHostConstInt16(x) OSSwapConstInt16(x) -#define OSSwapBigToHostConstInt32(x) OSSwapConstInt32(x) -#define OSSwapBigToHostConstInt64(x) OSSwapConstInt64(x) - -/* Generic big endian to host endianess byte swapping functions. */ - -#define OSSwapBigToHostInt16(x) OSSwapInt16(x) -#define OSSwapBigToHostInt32(x) OSSwapInt32(x) -#define OSSwapBigToHostInt64(x) OSSwapInt64(x) - -/* Little endian to host endianess byte swapping macros for constants. */ - -#define OSSwapLittleToHostConstInt16(x) (x) -#define OSSwapLittleToHostConstInt32(x) (x) -#define OSSwapLittleToHostConstInt64(x) (x) - -/* Generic little endian to host endianess byte swapping functions. */ - -#define OSSwapLittleToHostInt16(x) ((uint16_t)(x)) -#define OSSwapLittleToHostInt32(x) ((uint32_t)(x)) -#define OSSwapLittleToHostInt64(x) ((uint64_t)(x)) - -#else -#error Unknown endianess. -#endif - -#endif /* ! _OS_OSBYTEORDER_H */ - - diff --git a/idasdk75/ldr/mach-o/h/libkern/i386/OSByteOrder.h b/idasdk75/ldr/mach-o/h/libkern/i386/OSByteOrder.h deleted file mode 100644 index 6dd9026..0000000 --- a/idasdk75/ldr/mach-o/h/libkern/i386/OSByteOrder.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 1999-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _OS_OSBYTEORDERI386_H -#define _OS_OSBYTEORDERI386_H - -#include <stdint.h> -#include <libkern/i386/_OSByteOrder.h> - -#if !defined(OS_INLINE) -#define OS_INLINE __DARWIN_OS_INLINE -#endif - -/* Functions for byte reversed loads. */ - -OS_INLINE -uint16_t -OSReadSwapInt16( - const volatile void * base, - uintptr_t byteOffset -) -{ - uint16_t result; - - result = *(volatile uint16_t *)((uintptr_t)base + byteOffset); - return _OSSwapInt16(result); -} - -OS_INLINE -uint32_t -OSReadSwapInt32( - const volatile void * base, - uintptr_t byteOffset -) -{ - uint32_t result; - - result = *(volatile uint32_t *)((uintptr_t)base + byteOffset); - return _OSSwapInt32(result); -} - -OS_INLINE -uint64_t -OSReadSwapInt64( - const volatile void * base, - uintptr_t byteOffset -) -{ - uint64_t result; - - result = *(volatile uint64_t *)((uintptr_t)base + byteOffset); - return _OSSwapInt64(result); -} - -/* Functions for byte reversed stores. */ - -OS_INLINE -void -OSWriteSwapInt16( - volatile void * base, - uintptr_t byteOffset, - uint16_t data -) -{ - *(volatile uint16_t *)((uintptr_t)base + byteOffset) = _OSSwapInt16(data); -} - -OS_INLINE -void -OSWriteSwapInt32( - volatile void * base, - uintptr_t byteOffset, - uint32_t data -) -{ - *(volatile uint32_t *)((uintptr_t)base + byteOffset) = _OSSwapInt32(data); -} - -OS_INLINE -void -OSWriteSwapInt64( - volatile void * base, - uintptr_t byteOffset, - uint64_t data -) -{ - *(volatile uint64_t *)((uintptr_t)base + byteOffset) = _OSSwapInt64(data); -} - -#endif /* ! _OS_OSBYTEORDERI386_H */ diff --git a/idasdk75/ldr/mach-o/h/libkern/i386/_OSByteOrder.h b/idasdk75/ldr/mach-o/h/libkern/i386/_OSByteOrder.h deleted file mode 100644 index 51477bb..0000000 --- a/idasdk75/ldr/mach-o/h/libkern/i386/_OSByteOrder.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _OS__OSBYTEORDERI386_H -#define _OS__OSBYTEORDERI386_H - -#if !defined(__DARWIN_OS_INLINE) -# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -# define __DARWIN_OS_INLINE static inline -# elif defined(__MWERKS__) || defined(__cplusplus) -# define __DARWIN_OS_INLINE static inline -# else -# define __DARWIN_OS_INLINE static __inline__ -# endif -#endif - -/* Generic byte swapping functions. */ - -__DARWIN_OS_INLINE -__uint16_t -_OSSwapInt16( - __uint16_t _data -) -{ - return ((_data << 8) | (_data >> 8)); -} - -__DARWIN_OS_INLINE -__uint32_t -_OSSwapInt32( - __uint32_t _data -) -{ -#if defined(__llvm__) - return __builtin_bswap32(_data); -#else - __asm__ ("bswap %0" : "+r" (_data)); - return _data; -#endif -} - -#if defined(__llvm__) -__DARWIN_OS_INLINE -__uint64_t -_OSSwapInt64( - __uint64_t _data -) -{ - return __builtin_bswap64(_data); -} - -#elif defined(__i386__) -__DARWIN_OS_INLINE -__uint64_t -_OSSwapInt64( - __uint64_t _data -) -{ - __asm__ ("bswap %%eax\n\t" - "bswap %%edx\n\t" - "xchgl %%eax, %%edx" - : "+A" (_data)); - return _data; -} -#elif defined(__x86_64__) -__DARWIN_OS_INLINE -__uint64_t -_OSSwapInt64( - __uint64_t _data -) -{ - __asm__ ("bswap %0" : "+r" (_data)); - return _data; -} -#else -#error Unknown architecture -#endif - -#endif /* ! _OS__OSBYTEORDERI386_H */ diff --git a/idasdk75/ldr/mach-o/h/libkern/machine/OSByteOrder.h b/idasdk75/ldr/mach-o/h/libkern/machine/OSByteOrder.h deleted file mode 100644 index 97f2a6f..0000000 --- a/idasdk75/ldr/mach-o/h/libkern/machine/OSByteOrder.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * The contents of this file constitute Original Code as defined in and - * are subject to the Apple Public Source License Version 1.1 (the - * "License"). You may not use this file except in compliance with the - * License. Please obtain a copy of the License at - * http://www.apple.com/publicsource and read it before using this file. - * - * This Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _OS_OSBYTEORDERMACHINE_H -#define _OS_OSBYTEORDERMACHINE_H - -#include <stdint.h> - -#if !defined(OS_INLINE) -# if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -# define OS_INLINE static inline -# elif defined(__MWERKS__) || defined(__cplusplus) -# define OS_INLINE static inline -# else -# define OS_INLINE static __inline__ -# endif -#endif - -/* Generic byte swapping functions. */ - -OS_INLINE -uint16_t -_OSSwapInt16( - uint16_t data -) -{ - return OSSwapConstInt16(data); -} - -OS_INLINE -uint32_t -_OSSwapInt32( - uint32_t data -) -{ - return OSSwapConstInt32(data); -} - -OS_INLINE -uint64_t -_OSSwapInt64( - uint64_t data -) -{ - return OSSwapConstInt64(data); -} - -/* Functions for byte reversed loads. */ - -OS_INLINE -uint16_t -OSReadSwapInt16( - const volatile void * base, - uintptr_t byteOffset -) -{ - uint16_t data = *(volatile uint16_t *)((uintptr_t)base + byteOffset); - return _OSSwapInt16(data); -} - -OS_INLINE -uint32_t -OSReadSwapInt32( - const volatile void * base, - uintptr_t byteOffset -) -{ - uint32_t data = *(volatile uint32_t *)((uintptr_t)base + byteOffset); - return _OSSwapInt32(data); -} - -OS_INLINE -uint64_t -OSReadSwapInt64( - const volatile void * base, - uintptr_t byteOffset -) -{ - uint64_t data = *(volatile uint64_t *)((uintptr_t)base + byteOffset); - return _OSSwapInt64(data); -} - -/* Functions for byte reversed stores. */ - -OS_INLINE -void -OSWriteSwapInt16( - volatile void * base, - uintptr_t byteOffset, - uint16_t data -) -{ - *(volatile uint16_t *)((uintptr_t)base + byteOffset) = _OSSwapInt16(data); -} - -OS_INLINE -void -OSWriteSwapInt32( - volatile void * base, - uintptr_t byteOffset, - uint32_t data -) -{ - *(volatile uint32_t *)((uintptr_t)base + byteOffset) = _OSSwapInt32(data); -} - -OS_INLINE -void -OSWriteSwapInt64( - volatile void * base, - uintptr_t byteOffset, - uint64_t data -) -{ - *(volatile uint64_t *)((uintptr_t)base + byteOffset) = _OSSwapInt64(data); -} - -#endif /* ! _OS_OSBYTEORDERMACHINE_H */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/arm/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/arm/reloc.h deleted file mode 100644 index 52892bf..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/arm/reloc.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Relocation types used in the arm implementation. Relocation entries for - * things other than instructions use the same generic relocation as discribed - * in <mach-o/reloc.h> and their r_type is ARM_RELOC_VANILLA, one of the - * *_SECTDIFF or the *_PB_LA_PTR types. The rest of the relocation types are - * for instructions. Since they are for instructions the r_address field - * indicates the 32 bit instruction that the relocation is to be preformed on. - */ -enum reloc_type_arm -{ - ARM_RELOC_VANILLA, /* generic relocation as discribed above */ - ARM_RELOC_PAIR, /* the second relocation entry of a pair */ - ARM_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */ - ARM_RELOC_LOCAL_SECTDIFF, /* like ARM_RELOC_SECTDIFF, but the symbol - referenced was local. */ - ARM_RELOC_PB_LA_PTR,/* prebound lazy pointer */ - ARM_RELOC_BR24, /* 24 bit branch displacement (to a word address) */ - ARM_THUMB_RELOC_BR22, /* 22 bit branch displacement (to a half-word - address) */ - ARM_THUMB_32BIT_BRANCH, /* obsolete - a thumb 32-bit branch instruction - possibly needing page-spanning branch workaround */ - - /* - * For these two r_type relocations they always have a pair following them - * and the r_length bits are used differently. The encoding of the - * r_length is as follows: - * low bit of r_length: - * 0 - :lower16: for movw instructions - * 1 - :upper16: for movt instructions - * high bit of r_length: - * 0 - arm instructions - * 1 - thumb instructions - * the other half of the relocated expression is in the following pair - * relocation entry in the the low 16 bits of r_address field. - */ - ARM_RELOC_HALF, - ARM_RELOC_HALF_SECTDIFF -}; diff --git a/idasdk75/ldr/mach-o/h/mach-o/arm64/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/arm64/reloc.h deleted file mode 100644 index bcd5aeb..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/arm64/reloc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2010 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -#ifndef _MACHO_ARM64_RELOC_H_ -#define _MACHO_ARM64_RELOC_H_ - -/* - * Relocation types used in the arm64 implementation. - */ -enum reloc_type_arm64 -{ - ARM64_RELOC_UNSIGNED, // for pointers - ARM64_RELOC_SUBTRACTOR, // must be followed by a ARM64_RELOC_UNSIGNED - ARM64_RELOC_BRANCH26, // a B/BL instruction with 26-bit displacement - ARM64_RELOC_PAGE21, // pc-rel distance to page of target - ARM64_RELOC_PAGEOFF12, // offset within page, scaled by r_length - ARM64_RELOC_GOT_LOAD_PAGE21, // pc-rel distance to page of GOT slot - ARM64_RELOC_GOT_LOAD_PAGEOFF12, // offset within page of GOT slot, - // scaled by r_length - ARM64_RELOC_POINTER_TO_GOT, // for pointers to GOT slots - ARM64_RELOC_TLVP_LOAD_PAGE21, // pc-rel distance to page of TLVP slot - ARM64_RELOC_TLVP_LOAD_PAGEOFF12, // offset within page of TLVP slot, - // scaled by r_length - ARM64_RELOC_ADDEND, // must be followed by PAGE21 or PAGEOFF12 - - // An arm64e authenticated pointer. - // - // Represents a pointer to a symbol (like ARM64_RELOC_UNSIGNED). - // Additionally, the resulting pointer is signed. The signature is - // specified in the target location: the addend is restricted to the lower - // 32 bits (instead of the full 64 bits for ARM64_RELOC_UNSIGNED): - // - // |63|62|61-51|50-49| 48 |47 - 32|31 - 0| - // | 1| 0| 0 | key | addr | discriminator | addend | - // - // The key is one of: - // IA: 00 IB: 01 - // DA: 10 DB: 11 - // - // The discriminator field is used as extra signature diversification. - // - // The addr field indicates whether the target address should be blended - // into the discriminator. - // - ARM64_RELOC_AUTHENTICATED_POINTER, -}; - -#endif /* #ifndef _MACHO_ARM64_RELOC_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/fat.h b/idasdk75/ldr/mach-o/h/mach-o/fat.h deleted file mode 100644 index aaf03e0..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/fat.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _MACH_O_FAT_H_ -#define _MACH_O_FAT_H_ -/* - * This header file describes the structures of the file format for "fat" - * architecture specific file (wrapper design). At the begining of the file - * there is one fat_header structure followed by a number of fat_arch - * structures. For each architecture in the file, specified by a pair of - * cputype and cpusubtype, the fat_header describes the file offset, file - * size and alignment in the file of the architecture specific member. - * The padded bytes in the file to place each member on it's specific alignment - * are defined to be read as zeros and can be left as "holes" if the file system - * can support them as long as they read as zeros. - * - * All structures defined here are always written and read to/from disk - * in big-endian order. - */ - -/* - * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types - * and contains the constants for the possible values of these types. - */ -#include <stdint.h> -#include <mach/machine.h> -#include <architecture/byte_order.h> - -#define FAT_MAGIC 0xcafebabe -#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */ - -struct fat_header { - uint32_t magic; /* FAT_MAGIC */ - uint32_t nfat_arch; /* number of structs that follow */ -}; - -struct fat_arch { - cpu_type_t cputype; /* cpu specifier (int) */ - cpu_subtype_t cpusubtype; /* machine specifier (int) */ - uint32_t offset; /* file offset to this object file */ - uint32_t size; /* size of this object file */ - uint32_t align; /* alignment as a power of 2 */ -}; - -/* - * The support for the 64-bit fat file format described here is a work in - * progress and not yet fully supported in all the Apple Developer Tools. - * - * When a slice is greater than 4mb or an offset to a slice is greater than 4mb - * then the 64-bit fat file format is used. - */ -#define FAT_MAGIC_64 0xcafebabf -#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */ - -struct fat_arch_64 { - cpu_type_t cputype; /* cpu specifier (int) */ - cpu_subtype_t cpusubtype; /* machine specifier (int) */ - uint64_t offset; /* file offset to this object file */ - uint64_t size; /* size of this object file */ - uint32_t align; /* alignment as a power of 2 */ - uint32_t reserved; /* reserved */ -}; - -#endif /* _MACH_O_FAT_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/hppa/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/hppa/reloc.h deleted file mode 100644 index ded32e8..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/hppa/reloc.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* reloc.h - assemble for HP-PA */ -/* Defines machine specific relocation entries */ - -#ifndef HPPA_RELOC_INCLUDED -#define HPPA_RELOC_INCLUDED - -/* - * Relocation types used in the hppa implementation. Relocation entries for - * things other than instructions use the same generic relocation as discribed - * in <mach-o/reloc.h> and their r_type is HPPA_RELOC_VANILLA. The rest of the - * relocation types are for instructions. Since they are for instructions the - * r_address field indicates the 32 bit instruction that the relocation is to - * be preformed on. The field r_pcrel is set only for the HPPA_RELOC_BR17. - * And r_length is set to long for all non-RELOC_VANILLA r_types. - */ -enum reloc_type_hppa -{ - HPPA_RELOC_VANILLA, /* generic relocation as discribed in <mach-o/reloc.h>*/ - HPPA_RELOC_PAIR, /* the second relocation entry of a pair */ - HPPA_RELOC_HI21, /* a PAIR follows with the low part */ - HPPA_RELOC_LO14, /* a PAIR follows with the high part */ - HPPA_RELOC_BR17, /* 17 bit branch displacement (to a word address) - a PAIR follows with the high part */ - HPPA_RELOC_BL17, /* a bl instruction (overlow causes an error) */ - HPPA_RELOC_JBSR, /* a bl instruction that is targeted at a long branch - stub, a PAIR follows with the high part */ - HPPA_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */ - HPPA_RELOC_HI21_SECTDIFF, /* a PAIR follows with subtract symbol value */ - HPPA_RELOC_LO14_SECTDIFF, /* a PAIR follows with subtract symbol value */ - HPPA_RELOC_PB_LA_PTR /* prebound lazy pointer */ -}; - -/* - * For the HI and LO relocation types the two parts of the relocated expression - * (symbol + offset) are calculated as follows: - * - * rounded = round(offset, 0x2000); - * left21 = (symbol + rounded) & 0xfffff800; - * right14 = ((symbol + rounded) & 0x000007ff) + (offset - rounded); - * - * This allows the left part to be shared between references with different - * offsets as long as the rounded offsets are the same. - * - * The HPPA_RELOC_BR17 r_type also uses the above calculation and the right14 - * bits, sign extened to fill the displacement, and converted to a word - * displacement by droping the low bits (after checking they are zero). - */ - -/* - * For relocation types that use pairs the part of the relocated expression that - * is not stored in the instruction is stored in the r_address feild of the - * PAIR's entry. - * - * All low parts are stored as sign extened byte addressed values in the PAIR's - * r_address field as 32 bit values. This allows the HI21 not to have to know - * which type of low it is used with. - * - * The high parts are left justified 21 bit values zero filled to 32 bits and - * stored in the PAIR's r_address field. - */ - -/* - * The instructions that use the non-RELOC_VANILLA r_types are and the r_types - * they use are as follows: - * instructions r_type - * - * LDIL,ADDIL HPPA_RELOC_HI21 - * LDx, STx, LDO HPPA_RELOC_LO14 - * BE, BLE HPPA_RELOC_BR17 - * BL HPPA_RELOC_BL17 - * - * For the HPPA_RELOC_JBSR the BL instruction must be targeted at a long branch - * stub that can be reached with 17 bits of signed word displacement. Also the - * stub must be in the same block as the BL instruction so that scattered - * loading done by the link editor will not move them apart. For example in - * assembly code: - * jbsr foo,%r2,L1 ; creates a bl inst with a HPPA_RELOC_JBSR - * ; relocation entry for the symbol foo and the - * ; instruction is targeted to L1 - * ... - * L1: ldil L'foo,%r1 ; a HPPA_RELOC_HI21 entry for symbol foo - * ble,n R'foo(%sr4,%r1) ; a HPPA_RELOC_BR17 entry for symbol foo - */ - -#endif /* HPPA_RELOC_INCLUDED */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/i860/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/i860/reloc.h deleted file mode 100644 index 94f958d..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/i860/reloc.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Relocation types used in the I860 implementation. Relocation entries for - * things other than instructions use the same generic relocation as discribed - * above and their r_type is RELOC_VANILLA. The rest of the relocation types - * are for instructions. Since they are for instructions the r_address field - * indicates the 32 bit instruction that the relocation is to be preformed on. - * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types - * except RELOC_SPLIT0 as discribed below. - */ -enum reloc_type_i860 -{ - I860_RELOC_VANILLA, /* generic relocation as discribed above */ - - I860_RELOC_PAIR, /* Only follows a I860_RELOC_HIGH or a - * I860_RELOC_HIGHADJ and only the r_address has any - * meaning. - */ - I860_RELOC_HIGH, /* The low 16 bits of the instruction contains the high - * 16 bits of the item being refered to. This - * relocation type must be followed by a I860_RELOC_PAIR - * relocation type. The low 16 bits of the item being - * refered to is stored in the r_address of the - * I860_RELOC_PAIR entry. - */ - I860_RELOC_LOW0, /* For all of these the low 16 bits of the instruction*/ - I860_RELOC_LOW1, /* (minus the low 0, 1, 2, 3, or 4 bits) contain the */ - I860_RELOC_LOW2, /* low 16 bits of the item being refered to. The bits*/ - I860_RELOC_LOW3, /* of the reference that are missing are 0 and the */ - I860_RELOC_LOW4, /* bits in the instruction are part of the encoding of*/ - /* instruction. The resulting low 16 bits of the item*/ - /* being refered to is sign extended to 32 bits. */ - - I860_RELOC_SPLIT0, /* For all of these the bits 20-14 and bits 10-0 of */ - I860_RELOC_SPLIT1, /* the instruction (minus the low 0, 1 or 2 bits) */ - I860_RELOC_SPLIT2, /* contain the low 16 bits of the item to being */ - /* refered to. The bits of the reference that are */ - /* missing are 0 and the bits of the instruction are */ - /* part of the encoding of the instruction. The */ - /* resulting low 16 bits of the item being relocated */ - /* is sign extened to 32 bits. A special case of the */ - /* I860_RELOC_SPLIT0 is when r_pcrel is non-zero (for */ - /* branch displacements). In this case the 16 bits */ - /* from the instruction is a 32 bit word displacement.*/ - - I860_RELOC_HIGHADJ, /* Same as the RELOC_HIGH except the low 16 bits and the - * high 16 bits are added together with the low 16 bits - * sign extened first. This means if bit 15 of the low - * 16 bits is set the high 16 bits stored in the - * instruction will be adjusted. - */ - I860_RELOC_BRADDR, /* The low 26 bits of the instruction is a 32 bit - * word displacement from the pc to the item to being - * refered to. - */ - I860_RELOC_SECTDIFF /* a PAIR follows with subtract symbol value */ -}; diff --git a/idasdk75/ldr/mach-o/h/mach-o/loader.h b/idasdk75/ldr/mach-o/h/mach-o/loader.h deleted file mode 100644 index 7913106..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/loader.h +++ /dev/null @@ -1,1597 +0,0 @@ -/* - * Copyright (c) 1999-2008 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _MACHO_LOADER_H_ -#define _MACHO_LOADER_H_ - -/* - * This file describes the format of mach object files. - */ -#include <stdint.h> - -/* - * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types - * and contains the constants for the possible values of these types. - */ -#include <mach/machine.h> - -/* - * <mach/vm_prot.h> is needed here for the vm_prot_t type and contains the - * constants that are or'ed together for the possible values of this type. - */ -#include <mach/vm_prot.h> - -/* - * <machine/thread_status.h> is expected to define the flavors of the thread - * states and the structures of those flavors for each machine. - */ -#include <mach/machine/thread_status.h> -#include <architecture/byte_order.h> - -/* - * The 32-bit mach header appears at the very beginning of the object file for - * 32-bit architectures. - */ -struct mach_header { - uint32_t magic; /* mach magic number identifier */ - cpu_type_t cputype; /* cpu specifier */ - cpu_subtype_t cpusubtype; /* machine specifier */ - uint32_t filetype; /* type of file */ - uint32_t ncmds; /* number of load commands */ - uint32_t sizeofcmds; /* the size of all the load commands */ - uint32_t flags; /* flags */ -}; - -/* Constant for the magic field of the mach_header (32-bit architectures) */ -#define MH_MAGIC 0xfeedface /* the mach magic number */ -#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */ - -/* - * The 64-bit mach header appears at the very beginning of object files for - * 64-bit architectures. - */ -struct mach_header_64 { - uint32_t magic; /* mach magic number identifier */ - cpu_type_t cputype; /* cpu specifier */ - cpu_subtype_t cpusubtype; /* machine specifier */ - uint32_t filetype; /* type of file */ - uint32_t ncmds; /* number of load commands */ - uint32_t sizeofcmds; /* the size of all the load commands */ - uint32_t flags; /* flags */ - uint32_t reserved; /* reserved */ -}; - -/* Constant for the magic field of the mach_header_64 (64-bit architectures) */ -#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */ -#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */ - -/* - * The layout of the file depends on the filetype. For all but the MH_OBJECT - * file type the segments are padded out and aligned on a segment alignment - * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB, - * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part - * of their first segment. - * - * The file type MH_OBJECT is a compact format intended as output of the - * assembler and input (and possibly output) of the link editor (the .o - * format). All sections are in one unnamed segment with no segment padding. - * This format is used as an executable format when the file is so small the - * segment padding greatly increases its size. - * - * The file type MH_PRELOAD is an executable format intended for things that - * are not executed under the kernel (proms, stand alones, kernels, etc). The - * format can be executed under the kernel but may demand paged it and not - * preload it before execution. - * - * A core file is in MH_CORE format and can be any in an arbritray legal - * Mach-O file. - * - * Constants for the filetype field of the mach_header - */ -#define MH_OBJECT 0x1 /* relocatable object file */ -#define MH_EXECUTE 0x2 /* demand paged executable file */ -#define MH_FVMLIB 0x3 /* fixed VM shared library file */ -#define MH_CORE 0x4 /* core file */ -#define MH_PRELOAD 0x5 /* preloaded executable file */ -#define MH_DYLIB 0x6 /* dynamically bound shared library */ -#define MH_DYLINKER 0x7 /* dynamic link editor */ -#define MH_BUNDLE 0x8 /* dynamically bound bundle file */ -#define MH_DYLIB_STUB 0x9 /* shared library stub for static */ - /* linking only, no section contents */ -#define MH_DSYM 0xa /* companion file with only debug */ - /* sections */ -#define MH_KEXT_BUNDLE 0xb /* x86_64 kexts */ - -/* Constants for the flags field of the mach_header */ -#define MH_NOUNDEFS 0x1 /* the object file has no undefined - references */ -#define MH_INCRLINK 0x2 /* the object file is the output of an - incremental link against a base file - and can't be link edited again */ -#define MH_DYLDLINK 0x4 /* the object file is input for the - dynamic linker and can't be staticly - link edited again */ -#define MH_BINDATLOAD 0x8 /* the object file's undefined - references are bound by the dynamic - linker when loaded. */ -#define MH_PREBOUND 0x10 /* the file has its dynamic undefined - references prebound. */ -#define MH_SPLIT_SEGS 0x20 /* the file has its read-only and - read-write segments split */ -#define MH_LAZY_INIT 0x40 /* the shared library init routine is - to be run lazily via catching memory - faults to its writeable segments - (obsolete) */ -#define MH_TWOLEVEL 0x80 /* the image is using two-level name - space bindings */ -#define MH_FORCE_FLAT 0x100 /* the executable is forcing all images - to use flat name space bindings */ -#define MH_NOMULTIDEFS 0x200 /* this umbrella guarantees no multiple - defintions of symbols in its - sub-images so the two-level namespace - hints can always be used. */ -#define MH_NOFIXPREBINDING 0x400 /* do not have dyld notify the - prebinding agent about this - executable */ -#define MH_PREBINDABLE 0x800 /* the binary is not prebound but can - have its prebinding redone. only used - when MH_PREBOUND is not set. */ -#define MH_ALLMODSBOUND 0x1000 /* indicates that this binary binds to - all two-level namespace modules of - its dependent libraries. only used - when MH_PREBINDABLE and MH_TWOLEVEL - are both set. */ -#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000/* safe to divide up the sections into - sub-sections via symbols for dead - code stripping */ -#define MH_CANONICAL 0x4000 /* the binary has been canonicalized - via the unprebind operation */ -#define MH_WEAK_DEFINES 0x8000 /* the final linked image contains - external weak symbols */ -#define MH_BINDS_TO_WEAK 0x10000 /* the final linked image uses - weak symbols */ - -#define MH_ALLOW_STACK_EXECUTION 0x20000/* When this bit is set, all stacks - in the task will be given stack - execution privilege. Only used in - MH_EXECUTE filetypes. */ -#define MH_ROOT_SAFE 0x40000 /* When this bit is set, the binary - declares it is safe for use in - processes with uid zero */ - -#define MH_SETUID_SAFE 0x80000 /* When this bit is set, the binary - declares it is safe for use in - processes when issetugid() is true */ - -#define MH_NO_REEXPORTED_DYLIBS 0x100000 /* When this bit is set on a dylib, - the static linker does not need to - examine dependent dylibs to see - if any are re-exported */ -#define MH_PIE 0x200000 /* When this bit is set, the OS will - load the main executable at a - random address. Only used in - MH_EXECUTE filetypes. */ -#define MH_DEAD_STRIPPABLE_DYLIB 0x400000 /* Only for use on dylibs. When - linking against a dylib that - has this bit set, the static linker - will automatically not create a - LC_LOAD_DYLIB load command to the - dylib if no symbols are being - referenced from the dylib. */ -#define MH_HAS_TLV_DESCRIPTORS 0x800000 /* Contains a section of type - S_THREAD_LOCAL_VARIABLES */ - -#define MH_NO_HEAP_EXECUTION 0x1000000 /* When this bit is set, the OS will - run the main executable with - a non-executable heap even on - platforms (e.g. i386) that don't - require it. Only used in MH_EXECUTE - filetypes. */ -#define MH_APP_EXTENSION_SAFE 0x02000000 /* The code was linked for use in an - application extension. */ - -#define MH_NLIST_OUTOFSYNC_WITH_DYLDINFO 0x04000000 /* The external symbols - listed in the nlist symbol table do - not include all the symbols listed in - the dyld info. */ - -#define MH_SIM_SUPPORT 0x08000000 /* Allow LC_MIN_VERSION_MACOS and - LC_BUILD_VERSION load commands with - the platforms macOS, macCatalyst, - iOSSimulator, tvOSSimulator and - watchOSSimulator. */ - -#define MH_DYLIB_IN_CACHE 0x80000000 /* Only for use on dylibs. When this bit - is set, the dylib is part of the dyld - shared cache, rather than loose in - the filesystem. */ - -/* - * The load commands directly follow the mach_header. The total size of all - * of the commands is given by the sizeofcmds field in the mach_header. All - * load commands must have as their first two fields cmd and cmdsize. The cmd - * field is filled in with a constant for that command type. Each command type - * has a structure specifically for it. The cmdsize field is the size in bytes - * of the particular load command structure plus anything that follows it that - * is a part of the load command (i.e. section structures, strings, etc.). To - * advance to the next load command the cmdsize can be added to the offset or - * pointer of the current load command. The cmdsize for 32-bit architectures - * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple - * of 8 bytes (these are forever the maximum alignment of any load commands). - * The padded bytes must be zero. All tables in the object file must also - * follow these rules so the file can be memory mapped. Otherwise the pointers - * to these tables will not work well or at all on some machines. With all - * padding zeroed like objects will compare byte for byte. - */ -struct load_command { - uint32_t cmd; /* type of load command */ - uint32_t cmdsize; /* total size of command in bytes */ -}; - -/* - * After MacOS X 10.1 when a new load command is added that is required to be - * understood by the dynamic linker for the image to execute properly the - * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic - * linker sees such a load command it it does not understand will issue a - * "unknown load command required for execution" error and refuse to use the - * image. Other load commands without this bit that are not understood will - * simply be ignored. - */ -#define LC_REQ_DYLD 0x80000000 - -/* Constants for the cmd field of all load commands, the type */ -#define LC_SEGMENT 0x1 /* segment of this file to be mapped */ -#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */ -#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */ -#define LC_THREAD 0x4 /* thread */ -#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */ -#define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */ -#define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */ -#define LC_IDENT 0x8 /* object identification info (obsolete) */ -#define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */ -#define LC_PREPAGE 0xa /* prepage command (internal use) */ -#define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */ -#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */ -#define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */ -#define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */ -#define LC_ID_DYLINKER 0xf /* dynamic linker identification */ -#define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */ - /* linked shared library */ -#define LC_ROUTINES 0x11 /* image routines */ -#define LC_SUB_FRAMEWORK 0x12 /* sub framework */ -#define LC_SUB_UMBRELLA 0x13 /* sub umbrella */ -#define LC_SUB_CLIENT 0x14 /* sub client */ -#define LC_SUB_LIBRARY 0x15 /* sub library */ -#define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */ -#define LC_PREBIND_CKSUM 0x17 /* prebind checksum */ - -/* - * load a dynamically linked shared library that is allowed to be missing - * (all symbols are weak imported). - */ -#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD) - -#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be - mapped */ -#define LC_ROUTINES_64 0x1a /* 64-bit image routines */ -#define LC_UUID 0x1b /* the uuid */ -#define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */ -#define LC_CODE_SIGNATURE 0x1d /* local of code signature */ -#define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */ -#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */ -#define LC_LAZY_LOAD_DYLIB 0x20 /* delay load of dylib until first use */ -#define LC_ENCRYPTION_INFO 0x21 /* encrypted segment information */ -#define LC_DYLD_INFO 0x22 /* compressed dyld information */ -#define LC_DYLD_INFO_ONLY (0x22|LC_REQ_DYLD) /* compressed dyld information only */ -#define LC_LOAD_UPWARD_DYLIB (0x23 | LC_REQ_DYLD) /* load upward dylib */ -#define LC_VERSION_MIN_MACOSX 0x24 /* build for MacOSX min OS version */ -#define LC_VERSION_MIN_IPHONEOS 0x25 /* build for iPhoneOS min OS version */ -#define LC_FUNCTION_STARTS 0x26 /* compressed table of function start addresses */ -#define LC_DYLD_ENVIRONMENT 0x27 /* string for dyld to treat - like environment variable */ -#define LC_MAIN (0x28|LC_REQ_DYLD) /* replacement for LC_UNIXTHREAD */ -#define LC_DATA_IN_CODE 0x29 /* table of non-instructions in __text */ -#define LC_SOURCE_VERSION 0x2A /* source version used to build binary */ -#define LC_DYLIB_CODE_SIGN_DRS 0x2B /* Code signing DRs copied from linked dylibs */ -#define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */ -#define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */ -#define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */ -#define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */ -#define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */ -#define LC_NOTE 0x31 /* arbitrary data included within a Mach-O file */ -#define LC_BUILD_VERSION 0x32 /* build for platform min OS version */ -#define LC_DYLD_EXPORTS_TRIE (0x33 | LC_REQ_DYLD) /* used with linkedit_data_command, payload is trie */ -#define LC_DYLD_CHAINED_FIXUPS (0x34 | LC_REQ_DYLD) /* used with linkedit_data_command */ - -/* - * A variable length string in a load command is represented by an lc_str - * union. The strings are stored just after the load command structure and - * the offset is from the start of the load command structure. The size - * of the string is reflected in the cmdsize field of the load command. - * Once again any padded bytes to bring the cmdsize field to a multiple - * of 4 bytes must be zero. - */ -union lc_str { - uint32_t offset; /* offset to the string */ -}; - -/* - * The segment load command indicates that a part of this file is to be - * mapped into the task's address space. The size of this segment in memory, - * vmsize, maybe equal to or larger than the amount to map from this file, - * filesize. The file is mapped starting at fileoff to the beginning of - * the segment in memory, vmaddr. The rest of the memory of the segment, - * if any, is allocated zero fill on demand. The segment's maximum virtual - * memory protection and initial virtual memory protection are specified - * by the maxprot and initprot fields. If the segment has sections then the - * section structures directly follow the segment command and their size is - * reflected in cmdsize. - */ -struct segment_command { /* for 32-bit architectures */ - uint32_t cmd; /* LC_SEGMENT */ - uint32_t cmdsize; /* includes sizeof section structs */ - char segname[16]; /* segment name */ - uint32_t vmaddr; /* memory address of this segment */ - uint32_t vmsize; /* memory size of this segment */ - uint32_t fileoff; /* file offset of this segment */ - uint32_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ - uint32_t nsects; /* number of sections in segment */ - uint32_t flags; /* flags */ -}; - -/* - * The 64-bit segment load command indicates that a part of this file is to be - * mapped into a 64-bit task's address space. If the 64-bit segment has - * sections then section_64 structures directly follow the 64-bit segment - * command and their size is reflected in cmdsize. - */ -struct segment_command_64 { /* for 64-bit architectures */ - uint32_t cmd; /* LC_SEGMENT_64 */ - uint32_t cmdsize; /* includes sizeof section_64 structs */ - char segname[16]; /* segment name */ - uint64_t vmaddr; /* memory address of this segment */ - uint64_t vmsize; /* memory size of this segment */ - uint64_t fileoff; /* file offset of this segment */ - uint64_t filesize; /* amount to map from the file */ - vm_prot_t maxprot; /* maximum VM protection */ - vm_prot_t initprot; /* initial VM protection */ - uint32_t nsects; /* number of sections in segment */ - uint32_t flags; /* flags */ -}; - -/* Constants for the flags field of the segment_command */ -#define SG_HIGHVM 0x1 /* the file contents for this segment is for - the high part of the VM space, the low part - is zero filled (for stacks in core files) */ -#define SG_FVMLIB 0x2 /* this segment is the VM that is allocated by - a fixed VM library, for overlap checking in - the link editor */ -#define SG_NORELOC 0x4 /* this segment has nothing that was relocated - in it and nothing relocated to it, that is - it maybe safely replaced without relocation*/ -#define SG_PROTECTED_VERSION_1 0x8 /* This segment is protected. If the - segment starts at file offset 0, the - first page of the segment is not - protected. All other pages of the - segment are protected. */ -#define SG_READ_ONLY 0x10 /* This segment is made read-only after fixups */ - - - -/* - * A segment is made up of zero or more sections. Non-MH_OBJECT files have - * all of their segments with the proper sections in each, and padded to the - * specified segment alignment when produced by the link editor. The first - * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header - * and load commands of the object file before its first section. The zero - * fill sections are always last in their segment (in all formats). This - * allows the zeroed segment padding to be mapped into memory where zero fill - * sections might be. The gigabyte zero fill sections, those with the section - * type S_GB_ZEROFILL, can only be in a segment with sections of this type. - * These segments are then placed after all other segments. - * - * The MH_OBJECT format has all of its sections in one segment for - * compactness. There is no padding to a specified segment boundary and the - * mach_header and load commands are not part of the segment. - * - * Sections with the same section name, sectname, going into the same segment, - * segname, are combined by the link editor. The resulting section is aligned - * to the maximum alignment of the combined sections and is the new section's - * alignment. The combined sections are aligned to their original alignment in - * the combined section. Any padded bytes to get the specified alignment are - * zeroed. - * - * The format of the relocation entries referenced by the reloff and nreloc - * fields of the section structure for mach object files is described in the - * header file <reloc.h>. - */ -struct section { /* for 32-bit architectures */ - char sectname[16]; /* name of this section */ - char segname[16]; /* segment this section goes in */ - uint32_t addr; /* memory address of this section */ - uint32_t size; /* size in bytes of this section */ - uint32_t offset; /* file offset of this section */ - uint32_t align; /* section alignment (power of 2) */ - uint32_t reloff; /* file offset of relocation entries */ - uint32_t nreloc; /* number of relocation entries */ - uint32_t flags; /* flags (section type and attributes)*/ - uint32_t reserved1; /* reserved (for offset or index) */ - uint32_t reserved2; /* reserved (for count or sizeof) */ -}; - -struct section_64 { /* for 64-bit architectures */ - char sectname[16]; /* name of this section */ - char segname[16]; /* segment this section goes in */ - uint64_t addr; /* memory address of this section */ - uint64_t size; /* size in bytes of this section */ - uint32_t offset; /* file offset of this section */ - uint32_t align; /* section alignment (power of 2) */ - uint32_t reloff; /* file offset of relocation entries */ - uint32_t nreloc; /* number of relocation entries */ - uint32_t flags; /* flags (section type and attributes)*/ - uint32_t reserved1; /* reserved (for offset or index) */ - uint32_t reserved2; /* reserved (for count or sizeof) */ - uint32_t reserved3; /* reserved */ -}; - -/* - * The flags field of a section structure is separated into two parts a section - * type and section attributes. The section types are mutually exclusive (it - * can only have one type) but the section attributes are not (it may have more - * than one attribute). - */ -#define SECTION_TYPE 0x000000ff /* 256 section types */ -#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */ - -/* Constants for the type of a section */ -#define S_REGULAR 0x0 /* regular section */ -#define S_ZEROFILL 0x1 /* zero fill on demand section */ -#define S_CSTRING_LITERALS 0x2 /* section with only literal C strings*/ -#define S_4BYTE_LITERALS 0x3 /* section with only 4 byte literals */ -#define S_8BYTE_LITERALS 0x4 /* section with only 8 byte literals */ -#define S_LITERAL_POINTERS 0x5 /* section with only pointers to */ - /* literals */ -/* - * For the two types of symbol pointers sections and the symbol stubs section - * they have indirect symbol table entries. For each of the entries in the - * section the indirect symbol table entries, in corresponding order in the - * indirect symbol table, start at the index stored in the reserved1 field - * of the section structure. Since the indirect symbol table entries - * correspond to the entries in the section the number of indirect symbol table - * entries is inferred from the size of the section divided by the size of the - * entries in the section. For symbol pointers sections the size of the entries - * in the section is 4 bytes and for symbol stubs sections the byte size of the - * stubs is stored in the reserved2 field of the section structure. - */ -#define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* section with only non-lazy - symbol pointers */ -#define S_LAZY_SYMBOL_POINTERS 0x7 /* section with only lazy symbol - pointers */ -#define S_SYMBOL_STUBS 0x8 /* section with only symbol - stubs, byte size of stub in - the reserved2 field */ -#define S_MOD_INIT_FUNC_POINTERS 0x9 /* section with only function - pointers for initialization*/ -#define S_MOD_TERM_FUNC_POINTERS 0xa /* section with only function - pointers for termination */ -#define S_COALESCED 0xb /* section contains symbols that - are to be coalesced */ -#define S_GB_ZEROFILL 0xc /* zero fill on demand section - (that can be larger than 4 - gigabytes) */ -#define S_INTERPOSING 0xd /* section with only pairs of - function pointers for - interposing */ -#define S_16BYTE_LITERALS 0xe /* section with only 16 byte - literals */ -#define S_DTRACE_DOF 0xf /* section contains - DTrace Object Format */ -#define S_LAZY_DYLIB_SYMBOL_POINTERS 0x10 /* section with only lazy - symbol pointers to lazy - loaded dylibs */ -/* - * Section types to support thread local variables - */ -#define S_THREAD_LOCAL_REGULAR 0x11 /* template of initial - values for TLVs */ -#define S_THREAD_LOCAL_ZEROFILL 0x12 /* template of initial - values for TLVs */ -#define S_THREAD_LOCAL_VARIABLES 0x13 /* TLV descriptors */ -#define S_THREAD_LOCAL_VARIABLE_POINTERS 0x14 /* pointers to TLV - descriptors */ -#define S_THREAD_LOCAL_INIT_FUNCTION_POINTERS 0x15 /* functions to call - to initialize TLV - values */ -#define S_INIT_FUNC_OFFSETS 0x16 /* 32-bit offsets to - initializers */ - -/* - * Constants for the section attributes part of the flags field of a section - * structure. - */ -#define SECTION_ATTRIBUTES_USR 0xff000000 /* User setable attributes */ -#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section contains only true - machine instructions */ -#define S_ATTR_NO_TOC 0x40000000 /* section contains coalesced - symbols that are not to be - in a ranlib table of - contents */ -#define S_ATTR_STRIP_STATIC_SYMS 0x20000000 /* ok to strip static symbols - in this section in files - with the MH_DYLDLINK flag */ -#define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */ -#define S_ATTR_LIVE_SUPPORT 0x08000000 /* blocks are live if they - reference live blocks */ -#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 /* Used with i386 code stubs - written on by dyld */ -/* - * If a segment contains any sections marked with S_ATTR_DEBUG then all - * sections in that segment must have this attribute. No section other than - * a section marked with this attribute may reference the contents of this - * section. A section with this attribute may contain no symbols and must have - * a section type S_REGULAR. The static linker will not copy section contents - * from sections with this attribute into its output file. These sections - * generally contain DWARF debugging info. - */ -#define S_ATTR_DEBUG 0x02000000 /* a debug section */ -#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */ -#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some - machine instructions */ -#define S_ATTR_EXT_RELOC 0x00000200 /* section has external - relocation entries */ -#define S_ATTR_LOC_RELOC 0x00000100 /* section has local - relocation entries */ - - -/* - * The names of segments and sections in them are mostly meaningless to the - * link-editor. But there are few things to support traditional UNIX - * executables that require the link-editor and assembler to use some names - * agreed upon by convention. - * - * The initial protection of the "__TEXT" segment has write protection turned - * off (not writeable). - * - * The link-editor will allocate common symbols at the end of the "__common" - * section in the "__DATA" segment. It will create the section and segment - * if needed. - */ - -/* The currently known segment names and the section names in those segments */ - -#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */ - /* protections and catches NULL */ - /* references for MH_EXECUTE files */ - - -#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment */ -#define SECT_TEXT "__text" /* the real text part of the text */ - /* section no headers, and no padding */ -#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */ - /* section */ -#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */ - /* fvmlib initialization */ - /* section */ - -#define MACH_SEG_DATA "__DATA" /* the tradition UNIX data segment */ -#define SECT_DATA "__data" /* the real initialized data section */ - /* no padding, no bss overlap */ -#define SECT_BSS "__bss" /* the real uninitialized data section*/ - /* no padding */ -#define SECT_COMMON "__common" /* the section common symbols are */ - /* allocated in by the link editor */ - -#define SEG_OBJC "__OBJC" /* objective-C runtime segment */ -#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */ -#define SECT_OBJC_MODULES "__module_info" /* module information */ -#define SECT_OBJC_STRINGS "__selector_strs" /* string table */ -#define SECT_OBJC_REFS "__selector_refs" /* string table */ - -#define SEG_ICON "__ICON" /* the icon segment */ -#define SECT_ICON_HEADER "__header" /* the icon headers */ -#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */ - -#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */ - /* created and maintained by the link */ - /* editor. Created with -seglinkedit */ - /* option to ld(1) for MH_EXECUTE and */ - /* FVMLIB file types only */ - -#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */ - -#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */ - /* modifing code stubs that has read, */ - /* write and execute permissions */ - -/* - * Fixed virtual memory shared libraries are identified by two things. The - * target pathname (the name of the library as found for execution), and the - * minor version number. The address of where the headers are loaded is in - * header_addr. (THIS IS OBSOLETE and no longer supported). - */ -struct fvmlib { - union lc_str name; /* library's target pathname */ - uint32_t minor_version; /* library's minor version number */ - uint32_t header_addr; /* library's header address */ -}; - -/* - * A fixed virtual shared library (filetype == MH_FVMLIB in the mach header) - * contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library. - * An object that uses a fixed virtual shared library also contains a - * fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses. - * (THIS IS OBSOLETE and no longer supported). - */ -struct fvmlib_command { - uint32_t cmd; /* LC_IDFVMLIB or LC_LOADFVMLIB */ - uint32_t cmdsize; /* includes pathname string */ - struct fvmlib fvmlib; /* the library identification */ -}; - -/* - * Dynamicly linked shared libraries are identified by two things. The - * pathname (the name of the library as found for execution), and the - * compatibility version number. The pathname must match and the compatibility - * number in the user of the library must be greater than or equal to the - * library being used. The time stamp is used to record the time a library was - * built and copied into user so it can be use to determined if the library used - * at runtime is exactly the same as used to built the program. - */ -struct dylib { - union lc_str name; /* library's path name */ - uint32_t timestamp; /* library's build time stamp */ - uint32_t current_version; /* library's current version number */ - uint32_t compatibility_version; /* library's compatibility vers number*/ -}; - -/* - * A dynamically linked shared library (filetype == MH_DYLIB in the mach header) - * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library. - * An object that uses a dynamically linked shared library also contains a - * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or - * LC_REEXPORT_DYLIB) for each library it uses. - */ -struct dylib_command { - uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB, - LC_REEXPORT_DYLIB */ - uint32_t cmdsize; /* includes pathname string */ - struct dylib dylib; /* the library identification */ -}; - -/* - * A dynamically linked shared library may be a subframework of an umbrella - * framework. If so it will be linked with "-umbrella umbrella_name" where - * Where "umbrella_name" is the name of the umbrella framework. A subframework - * can only be linked against by its umbrella framework or other subframeworks - * that are part of the same umbrella framework. Otherwise the static link - * editor produces an error and states to link against the umbrella framework. - * The name of the umbrella framework for subframeworks is recorded in the - * following structure. - */ -struct sub_framework_command { - uint32_t cmd; /* LC_SUB_FRAMEWORK */ - uint32_t cmdsize; /* includes umbrella string */ - union lc_str umbrella; /* the umbrella framework name */ -}; - -/* - * For dynamically linked shared libraries that are subframework of an umbrella - * framework they can allow clients other than the umbrella framework or other - * subframeworks in the same umbrella framework. To do this the subframework - * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load - * command is created for each -allowable_client flag. The client_name is - * usually a framework name. It can also be a name used for bundles clients - * where the bundle is built with "-client_name client_name". - */ -struct sub_client_command { - uint32_t cmd; /* LC_SUB_CLIENT */ - uint32_t cmdsize; /* includes client string */ - union lc_str client; /* the client name */ -}; - -/* - * A dynamically linked shared library may be a sub_umbrella of an umbrella - * framework. If so it will be linked with "-sub_umbrella umbrella_name" where - * Where "umbrella_name" is the name of the sub_umbrella framework. When - * staticly linking when -twolevel_namespace is in effect a twolevel namespace - * umbrella framework will only cause its subframeworks and those frameworks - * listed as sub_umbrella frameworks to be implicited linked in. Any other - * dependent dynamic libraries will not be linked it when -twolevel_namespace - * is in effect. The primary library recorded by the static linker when - * resolving a symbol in these libraries will be the umbrella framework. - * Zero or more sub_umbrella frameworks may be use by an umbrella framework. - * The name of a sub_umbrella framework is recorded in the following structure. - */ -struct sub_umbrella_command { - uint32_t cmd; /* LC_SUB_UMBRELLA */ - uint32_t cmdsize; /* includes sub_umbrella string */ - union lc_str sub_umbrella; /* the sub_umbrella framework name */ -}; - -/* - * A dynamically linked shared library may be a sub_library of another shared - * library. If so it will be linked with "-sub_library library_name" where - * Where "library_name" is the name of the sub_library shared library. When - * staticly linking when -twolevel_namespace is in effect a twolevel namespace - * shared library will only cause its subframeworks and those frameworks - * listed as sub_umbrella frameworks and libraries listed as sub_libraries to - * be implicited linked in. Any other dependent dynamic libraries will not be - * linked it when -twolevel_namespace is in effect. The primary library - * recorded by the static linker when resolving a symbol in these libraries - * will be the umbrella framework (or dynamic library). Zero or more sub_library - * shared libraries may be use by an umbrella framework or (or dynamic library). - * The name of a sub_library framework is recorded in the following structure. - * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc". - */ -struct sub_library_command { - uint32_t cmd; /* LC_SUB_LIBRARY */ - uint32_t cmdsize; /* includes sub_library string */ - union lc_str sub_library; /* the sub_library name */ -}; - -/* - * A program (filetype == MH_EXECUTE) that is - * prebound to its dynamic libraries has one of these for each library that - * the static linker used in prebinding. It contains a bit vector for the - * modules in the library. The bits indicate which modules are bound (1) and - * which are not (0) from the library. The bit for module 0 is the low bit - * of the first byte. So the bit for the Nth module is: - * (linked_modules[N/8] >> N%8) & 1 - */ -struct prebound_dylib_command { - uint32_t cmd; /* LC_PREBOUND_DYLIB */ - uint32_t cmdsize; /* includes strings */ - union lc_str name; /* library's path name */ - uint32_t nmodules; /* number of modules in library */ - union lc_str linked_modules; /* bit vector of linked modules */ -}; - -/* - * A program that uses a dynamic linker contains a dylinker_command to identify - * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker - * contains a dylinker_command to identify the dynamic linker (LC_ID_DYLINKER). - * A file can have at most one of these. - */ -struct dylinker_command { - uint32_t cmd; /* LC_ID_DYLINKER or LC_LOAD_DYLINKER */ - uint32_t cmdsize; /* includes pathname string */ - union lc_str name; /* dynamic linker's path name */ -}; - -/* - * Thread commands contain machine-specific data structures suitable for - * use in the thread state primitives. The machine specific data structures - * follow the struct thread_command as follows. - * Each flavor of machine specific data structure is preceded by an unsigned - * long constant for the flavor of that data structure, an uint32_t - * that is the count of longs of the size of the state data structure and then - * the state data structure follows. This triple may be repeated for many - * flavors. The constants for the flavors, counts and state data structure - * definitions are expected to be in the header file <machine/thread_status.h>. - * These machine specific data structures sizes must be multiples of - * 4 bytes The cmdsize reflects the total size of the thread_command - * and all of the sizes of the constants for the flavors, counts and state - * data structures. - * - * For executable objects that are unix processes there will be one - * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor. - * This is the same as a LC_THREAD, except that a stack is automatically - * created (based on the shell's limit for the stack size). Command arguments - * and environment variables are copied onto that stack. - */ -struct thread_command { - uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */ - uint32_t cmdsize; /* total size of this command */ - /* uint32_t flavor flavor of thread state */ - /* uint32_t count count of longs in thread state */ - /* struct XXX_thread_state state thread state for this flavor */ - /* ... */ -}; - -/* - * The routines command contains the address of the dynamic shared library - * initialization routine and an index into the module table for the module - * that defines the routine. Before any modules are used from the library the - * dynamic linker fully binds the module that defines the initialization routine - * and then calls it. This gets called before any module initialization - * routines (used for C++ static constructors) in the library. - */ -struct routines_command { /* for 32-bit architectures */ - uint32_t cmd; /* LC_ROUTINES */ - uint32_t cmdsize; /* total size of this command */ - uint32_t init_address; /* address of initialization routine */ - uint32_t init_module; /* index into the module table that */ - /* the init routine is defined in */ - uint32_t reserved1; - uint32_t reserved2; - uint32_t reserved3; - uint32_t reserved4; - uint32_t reserved5; - uint32_t reserved6; -}; - -/* - * The 64-bit routines command. Same use as above. - */ -struct routines_command_64 { /* for 64-bit architectures */ - uint32_t cmd; /* LC_ROUTINES_64 */ - uint32_t cmdsize; /* total size of this command */ - uint64_t init_address; /* address of initialization routine */ - uint64_t init_module; /* index into the module table that */ - /* the init routine is defined in */ - uint64_t reserved1; - uint64_t reserved2; - uint64_t reserved3; - uint64_t reserved4; - uint64_t reserved5; - uint64_t reserved6; -}; - -/* - * The symtab_command contains the offsets and sizes of the link-edit 4.3BSD - * "stab" style symbol table information as described in the header files - * <nlist.h> and <stab.h>. - */ -struct symtab_command { - uint32_t cmd; /* LC_SYMTAB */ - uint32_t cmdsize; /* sizeof(struct symtab_command) */ - uint32_t symoff; /* symbol table offset */ - uint32_t nsyms; /* number of symbol table entries */ - uint32_t stroff; /* string table offset */ - uint32_t strsize; /* string table size in bytes */ -}; - -/* - * This is the second set of the symbolic information which is used to support - * the data structures for the dynamically link editor. - * - * The original set of symbolic information in the symtab_command which contains - * the symbol and string tables must also be present when this load command is - * present. When this load command is present the symbol table is organized - * into three groups of symbols: - * local symbols (static and debugging symbols) - grouped by module - * defined external symbols - grouped by module (sorted by name if not lib) - * undefined external symbols (sorted by name if MH_BINDATLOAD is not set, - * and in order the were seen by the static - * linker if MH_BINDATLOAD is set) - * In this load command there are offsets and counts to each of the three groups - * of symbols. - * - * This load command contains a the offsets and sizes of the following new - * symbolic information tables: - * table of contents - * module table - * reference symbol table - * indirect symbol table - * The first three tables above (the table of contents, module table and - * reference symbol table) are only present if the file is a dynamically linked - * shared library. For executable and object modules, which are files - * containing only one module, the information that would be in these three - * tables is determined as follows: - * table of contents - the defined external symbols are sorted by name - * module table - the file contains only one module so everything in the - * file is part of the module. - * reference symbol table - is the defined and undefined external symbols - * - * For dynamically linked shared library files this load command also contains - * offsets and sizes to the pool of relocation entries for all sections - * separated into two groups: - * external relocation entries - * local relocation entries - * For executable and object modules the relocation entries continue to hang - * off the section structures. - */ -struct dysymtab_command { - uint32_t cmd; /* LC_DYSYMTAB */ - uint32_t cmdsize; /* sizeof(struct dysymtab_command) */ - - /* - * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command - * are grouped into the following three groups: - * local symbols (further grouped by the module they are from) - * defined external symbols (further grouped by the module they are from) - * undefined symbols - * - * The local symbols are used only for debugging. The dynamic binding - * process may have to use them to indicate to the debugger the local - * symbols for a module that is being bound. - * - * The last two groups are used by the dynamic binding process to do the - * binding (indirectly through the module table and the reference symbol - * table when this is a dynamically linked shared library file). - */ - uint32_t ilocalsym; /* index to local symbols */ - uint32_t nlocalsym; /* number of local symbols */ - - uint32_t iextdefsym;/* index to externally defined symbols */ - uint32_t nextdefsym;/* number of externally defined symbols */ - - uint32_t iundefsym; /* index to undefined symbols */ - uint32_t nundefsym; /* number of undefined symbols */ - - /* - * For the for the dynamic binding process to find which module a symbol - * is defined in the table of contents is used (analogous to the ranlib - * structure in an archive) which maps defined external symbols to modules - * they are defined in. This exists only in a dynamically linked shared - * library file. For executable and object modules the defined external - * symbols are sorted by name and is use as the table of contents. - */ - uint32_t tocoff; /* file offset to table of contents */ - uint32_t ntoc; /* number of entries in table of contents */ - - /* - * To support dynamic binding of "modules" (whole object files) the symbol - * table must reflect the modules that the file was created from. This is - * done by having a module table that has indexes and counts into the merged - * tables for each module. The module structure that these two entries - * refer to is described below. This exists only in a dynamically linked - * shared library file. For executable and object modules the file only - * contains one module so everything in the file belongs to the module. - */ - uint32_t modtaboff; /* file offset to module table */ - uint32_t nmodtab; /* number of module table entries */ - - /* - * To support dynamic module binding the module structure for each module - * indicates the external references (defined and undefined) each module - * makes. For each module there is an offset and a count into the - * reference symbol table for the symbols that the module references. - * This exists only in a dynamically linked shared library file. For - * executable and object modules the defined external symbols and the - * undefined external symbols indicates the external references. - */ - uint32_t extrefsymoff; /* offset to referenced symbol table */ - uint32_t nextrefsyms; /* number of referenced symbol table entries */ - - /* - * The sections that contain "symbol pointers" and "routine stubs" have - * indexes and (implied counts based on the size of the section and fixed - * size of the entry) into the "indirect symbol" table for each pointer - * and stub. For every section of these two types the index into the - * indirect symbol table is stored in the section header in the field - * reserved1. An indirect symbol table entry is simply a 32bit index into - * the symbol table to the symbol that the pointer or stub is referring to. - * The indirect symbol table is ordered to match the entries in the section. - */ - uint32_t indirectsymoff; /* file offset to the indirect symbol table */ - uint32_t nindirectsyms; /* number of indirect symbol table entries */ - - /* - * To support relocating an individual module in a library file quickly the - * external relocation entries for each module in the library need to be - * accessed efficiently. Since the relocation entries can't be accessed - * through the section headers for a library file they are separated into - * groups of local and external entries further grouped by module. In this - * case the presents of this load command who's extreloff, nextrel, - * locreloff and nlocrel fields are non-zero indicates that the relocation - * entries of non-merged sections are not referenced through the section - * structures (and the reloff and nreloc fields in the section headers are - * set to zero). - * - * Since the relocation entries are not accessed through the section headers - * this requires the r_address field to be something other than a section - * offset to identify the item to be relocated. In this case r_address is - * set to the offset from the vmaddr of the first LC_SEGMENT command. - * For MH_SPLIT_SEGS images r_address is set to the the offset from the - * vmaddr of the first read-write LC_SEGMENT command. - * - * The relocation entries are grouped by module and the module table - * entries have indexes and counts into them for the group of external - * relocation entries for that the module. - * - * For sections that are merged across modules there must not be any - * remaining external relocation entries for them (for merged sections - * remaining relocation entries must be local). - */ - uint32_t extreloff; /* offset to external relocation entries */ - uint32_t nextrel; /* number of external relocation entries */ - - /* - * All the local relocation entries are grouped together (they are not - * grouped by their module since they are only used if the object is moved - * from it staticly link edited address). - */ - uint32_t locreloff; /* offset to local relocation entries */ - uint32_t nlocrel; /* number of local relocation entries */ - -}; - -/* - * An indirect symbol table entry is simply a 32bit index into the symbol table - * to the symbol that the pointer or stub is refering to. Unless it is for a - * non-lazy symbol pointer section for a defined symbol which strip(1) as - * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the - * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. - */ -#define INDIRECT_SYMBOL_LOCAL 0x80000000 -#define INDIRECT_SYMBOL_ABS 0x40000000 - - -/* a table of contents entry */ -struct dylib_table_of_contents { - uint32_t symbol_index; /* the defined external symbol - (index into the symbol table) */ - uint32_t module_index; /* index into the module table this symbol - is defined in */ -}; - -/* a module table entry */ -struct dylib_module { - uint32_t module_name; /* the module name (index into string table) */ - - uint32_t iextdefsym; /* index into externally defined symbols */ - uint32_t nextdefsym; /* number of externally defined symbols */ - uint32_t irefsym; /* index into reference symbol table */ - uint32_t nrefsym; /* number of reference symbol table entries */ - uint32_t ilocalsym; /* index into symbols for local symbols */ - uint32_t nlocalsym; /* number of local symbols */ - - uint32_t iextrel; /* index into external relocation entries */ - uint32_t nextrel; /* number of external relocation entries */ - - uint32_t iinit_iterm; /* low 16 bits are the index into the init - section, high 16 bits are the index into - the term section */ - uint32_t ninit_nterm; /* low 16 bits are the number of init section - entries, high 16 bits are the number of - term section entries */ - - uint32_t /* for this module address of the start of */ - objc_module_info_addr; /* the (__OBJC,__module_info) section */ - uint32_t /* for this module size of */ - objc_module_info_size; /* the (__OBJC,__module_info) section */ -}; - -/* a 64-bit module table entry */ -struct dylib_module_64 { - uint32_t module_name; /* the module name (index into string table) */ - - uint32_t iextdefsym; /* index into externally defined symbols */ - uint32_t nextdefsym; /* number of externally defined symbols */ - uint32_t irefsym; /* index into reference symbol table */ - uint32_t nrefsym; /* number of reference symbol table entries */ - uint32_t ilocalsym; /* index into symbols for local symbols */ - uint32_t nlocalsym; /* number of local symbols */ - - uint32_t iextrel; /* index into external relocation entries */ - uint32_t nextrel; /* number of external relocation entries */ - - uint32_t iinit_iterm; /* low 16 bits are the index into the init - section, high 16 bits are the index into - the term section */ - uint32_t ninit_nterm; /* low 16 bits are the number of init section - entries, high 16 bits are the number of - term section entries */ - - uint32_t /* for this module size of */ - objc_module_info_size; /* the (__OBJC,__module_info) section */ - uint64_t /* for this module address of the start of */ - objc_module_info_addr; /* the (__OBJC,__module_info) section */ -}; - -/* - * The entries in the reference symbol table are used when loading the module - * (both by the static and dynamic link editors) and if the module is unloaded - * or replaced. Therefore all external symbols (defined and undefined) are - * listed in the module's reference table. The flags describe the type of - * reference that is being made. The constants for the flags are defined in - * <mach-o/nlist.h> as they are also used for symbol table entries. - */ -struct dylib_reference { - uint32_t isym:24, /* index into the symbol table */ - flags:8; /* flags to indicate the type of reference */ -}; - -/* - * The twolevel_hints_command contains the offset and number of hints in the - * two-level namespace lookup hints table. - */ -struct twolevel_hints_command { - uint32_t cmd; /* LC_TWOLEVEL_HINTS */ - uint32_t cmdsize; /* sizeof(struct twolevel_hints_command) */ - uint32_t offset; /* offset to the hint table */ - uint32_t nhints; /* number of hints in the hint table */ -}; - -/* - * The entries in the two-level namespace lookup hints table are twolevel_hint - * structs. These provide hints to the dynamic link editor where to start - * looking for an undefined symbol in a two-level namespace image. The - * isub_image field is an index into the sub-images (sub-frameworks and - * sub-umbrellas list) that made up the two-level image that the undefined - * symbol was found in when it was built by the static link editor. If - * isub-image is 0 the the symbol is expected to be defined in library and not - * in the sub-images. If isub-image is non-zero it is an index into the array - * of sub-images for the umbrella with the first index in the sub-images being - * 1. The array of sub-images is the ordered list of sub-images of the umbrella - * that would be searched for a symbol that has the umbrella recorded as its - * primary library. The table of contents index is an index into the - * library's table of contents. This is used as the starting point of the - * binary search or a directed linear search. - */ -struct twolevel_hint { - uint32_t - isub_image:8, /* index into the sub images */ - itoc:24; /* index into the table of contents */ -}; - -/* - * The prebind_cksum_command contains the value of the original check sum for - * prebound files or zero. When a prebound file is first created or modified - * for other than updating its prebinding information the value of the check sum - * is set to zero. When the file has it prebinding re-done and if the value of - * the check sum is zero the original check sum is calculated and stored in - * cksum field of this load command in the output file. If when the prebinding - * is re-done and the cksum field is non-zero it is left unchanged from the - * input file. - */ -struct prebind_cksum_command { - uint32_t cmd; /* LC_PREBIND_CKSUM */ - uint32_t cmdsize; /* sizeof(struct prebind_cksum_command) */ - uint32_t cksum; /* the check sum or zero */ -}; - -/* - * The uuid load command contains a single 128-bit unique random number that - * identifies an object produced by the static link editor. - */ -struct uuid_command { - uint32_t cmd; /* LC_UUID */ - uint32_t cmdsize; /* sizeof(struct uuid_command) */ - uint8_t uuid[16]; /* the 128-bit uuid */ -}; - -/* - * The rpath_command contains a path which at runtime should be added to - * the current run path used to find @rpath prefixed dylibs. - */ -struct rpath_command { - uint32_t cmd; /* LC_RPATH */ - uint32_t cmdsize; /* includes string */ - union lc_str path; /* path to add to run path */ -}; - -/* - * The linkedit_data_command contains the offsets and sizes of a blob - * of data in the __LINKEDIT segment. - */ -struct linkedit_data_command { - uint32_t cmd; /* LC_CODE_SIGNATURE or LC_SEGMENT_SPLIT_INFO, - or LC_FUNCTION_STARTS */ - uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */ - uint32_t dataoff; /* file offset of data in __LINKEDIT segment */ - uint32_t datasize; /* file size of data in __LINKEDIT segment */ -}; - -/* - * The encryption_info_command contains the file offset and size of an - * of an encrypted segment. - */ -struct encryption_info_command { - uint32_t cmd; /* LC_ENCRYPTION_INFO */ - uint32_t cmdsize; /* sizeof(struct encryption_info_command) */ - uint32_t cryptoff; /* file offset of encrypted range */ - uint32_t cryptsize; /* file size of encrypted range */ - uint32_t cryptid; /* which enryption system, - 0 means not-encrypted yet */ -}; - -/* - * The encryption_info_command_64 contains the file offset and size of an - * of an encrypted segment (for use in x86_64 targets). - */ -struct encryption_info_command_64 { - uint32_t cmd; /* LC_ENCRYPTION_INFO_64 */ - uint32_t cmdsize; /* sizeof(struct encryption_info_command_64) */ - uint32_t cryptoff; /* file offset of encrypted range */ - uint32_t cryptsize; /* file size of encrypted range */ - uint32_t cryptid; /* which enryption system, - 0 means not-encrypted yet */ - uint32_t pad; /* padding to make this struct's size a multiple - of 8 bytes */ -}; - -/* - * The version_min_command contains the min OS version on which this - * binary was built to run. - */ -struct version_min_command { - uint32_t cmd; /* LC_VERSION_MIN_MACOSX or - LC_VERSION_MIN_IPHONEOS */ - uint32_t cmdsize; /* sizeof(struct min_version_command) */ - uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ -}; -struct build_version_command { - uint32_t cmd; /* LC_BUILD_VERSION */ - uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ - /* ntools * sizeof(struct build_tool_version) */ - uint32_t platform; /* platform */ - uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ - uint32_t ntools; /* number of tool entries following this */ -}; - -struct build_tool_version { - uint32_t tool; /* enum for the tool */ - uint32_t version; /* version number of the tool */ -}; - -/* Known values for the platform field above. */ -#define PLATFORM_MACOS 1 -#define PLATFORM_IOS 2 -#define PLATFORM_TVOS 3 -#define PLATFORM_WATCHOS 4 -#define PLATFORM_BRIDGEOS 5 -#define PLATFORM_MACCATALYST 6 -#if (!defined(PLATFORM_MACCATALYST)) -#define PLATFORM_MACCATALYST 6 -#endif -#define PLATFORM_IOSSIMULATOR 7 -#define PLATFORM_TVOSSIMULATOR 8 -#define PLATFORM_WATCHOSSIMULATOR 9 -#define PLATFORM_DRIVERKIT 10 - -/* Known values for the tool field above. */ -#define TOOL_CLANG 1 -#define TOOL_SWIFT 2 -#define TOOL_LD 3 - -/* - * The dyld_info_command contains the file offsets and sizes of - * the new compressed form of the information dyld needs to - * load the image. This information is used by dyld on Mac OS X - * 10.6 and later. All information pointed to by this command - * is encoded using byte streams, so no endian swapping is needed - * to interpret it. - */ -struct dyld_info_command { - uint32_t cmd; /* LC_DYLD_INFO or LC_DYLD_INFO_ONLY */ - uint32_t cmdsize; /* sizeof(struct dyld_info_command) */ - - /* - * Dyld rebases an image whenever dyld loads it at an address different - * from its preferred address. The rebase information is a stream - * of byte sized opcodes whose symbolic names start with REBASE_OPCODE_. - * Conceptually the rebase information is a table of tuples: - * <seg-index, seg-offset, type> - * The opcodes are a compressed way to encode the table by only - * encoding when a column changes. In addition simple patterns - * like "every n'th offset for m times" can be encoded in a few - * bytes. - */ - uint32_t rebase_off; /* file offset to rebase info */ - uint32_t rebase_size; /* size of rebase info */ - - /* - * Dyld binds an image during the loading process, if the image - * requires any pointers to be initialized to symbols in other images. - * The bind information is a stream of byte sized - * opcodes whose symbolic names start with BIND_OPCODE_. - * Conceptually the bind information is a table of tuples: - * <seg-index, seg-offset, type, symbol-library-ordinal, symbol-name, addend> - * The opcodes are a compressed way to encode the table by only - * encoding when a column changes. In addition simple patterns - * like for runs of pointers initialzed to the same value can be - * encoded in a few bytes. - */ - uint32_t bind_off; /* file offset to binding info */ - uint32_t bind_size; /* size of binding info */ - - /* - * Some C++ programs require dyld to unique symbols so that all - * images in the process use the same copy of some code/data. - * This step is done after binding. The content of the weak_bind - * info is an opcode stream like the bind_info. But it is sorted - * alphabetically by symbol name. This enable dyld to walk - * all images with weak binding information in order and look - * for collisions. If there are no collisions, dyld does - * no updating. That means that some fixups are also encoded - * in the bind_info. For instance, all calls to "operator new" - * are first bound to libstdc++.dylib using the information - * in bind_info. Then if some image overrides operator new - * that is detected when the weak_bind information is processed - * and the call to operator new is then rebound. - */ - uint32_t weak_bind_off; /* file offset to weak binding info */ - uint32_t weak_bind_size; /* size of weak binding info */ - - /* - * Some uses of external symbols do not need to be bound immediately. - * Instead they can be lazily bound on first use. The lazy_bind - * are contains a stream of BIND opcodes to bind all lazy symbols. - * Normal use is that dyld ignores the lazy_bind section when - * loading an image. Instead the static linker arranged for the - * lazy pointer to initially point to a helper function which - * pushes the offset into the lazy_bind area for the symbol - * needing to be bound, then jumps to dyld which simply adds - * the offset to lazy_bind_off to get the information on what - * to bind. - */ - uint32_t lazy_bind_off; /* file offset to lazy binding info */ - uint32_t lazy_bind_size; /* size of lazy binding infs */ - - /* - * The symbols exported by a dylib are encoded in a trie. This - * is a compact representation that factors out common prefixes. - * It also reduces LINKEDIT pages in RAM because it encodes all - * information (name, address, flags) in one small, contiguous range. - * The export area is a stream of nodes. The first node sequentially - * is the start node for the trie. - * - * Nodes for a symbol start with a uleb128 that is the length of - * the exported symbol information for the string so far. - * If there is no exported symbol, the node starts with a zero byte. - * If there is exported info, it follows the length. First is - * a uleb128 containing flags. Normally, it is followed by a - * uleb128 encoded offset which is location of the content named - * by the symbol from the mach_header for the image. If the flags - * is EXPORT_SYMBOL_FLAGS_REEXPORT, then following the flags is - * a uleb128 encoded library ordinal, then a zero terminated - * UTF8 string. If the string is zero length, then the symbol - * is re-export from the specified dylib with the same name. - * - * After the optional exported symbol information is a byte of - * how many edges (0-255) that this node has leaving it, - * followed by each edge. - * Each edge is a zero terminated UTF8 of the addition chars - * in the symbol, followed by a uleb128 offset for the node that - * edge points to. - * - */ - uint32_t export_off; /* file offset to lazy binding info */ - uint32_t export_size; /* size of lazy binding infs */ -}; - -/* - * The following are used to encode rebasing information - */ -#define REBASE_TYPE_POINTER 1 -#define REBASE_TYPE_TEXT_ABSOLUTE32 2 -#define REBASE_TYPE_TEXT_PCREL32 3 - -#define REBASE_OPCODE_MASK 0xF0 -#define REBASE_IMMEDIATE_MASK 0x0F -#define REBASE_OPCODE_DONE 0x00 -#define REBASE_OPCODE_SET_TYPE_IMM 0x10 -#define REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x20 -#define REBASE_OPCODE_ADD_ADDR_ULEB 0x30 -#define REBASE_OPCODE_ADD_ADDR_IMM_SCALED 0x40 -#define REBASE_OPCODE_DO_REBASE_IMM_TIMES 0x50 -#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES 0x60 -#define REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB 0x70 -#define REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB 0x80 - - -/* - * The following are used to encode binding information - */ -#define BIND_TYPE_POINTER 1 -#define BIND_TYPE_TEXT_ABSOLUTE32 2 -#define BIND_TYPE_TEXT_PCREL32 3 - -//FIXME: unofficial names, not actually used in the bytecode stream -#define BIND_TYPE_THREADED_POINTER 100 -#define BIND_TYPE_THREADED_POINTER_AUTH 101 -#define BIND_TYPE_THREADED_REBASE 102 -#define BIND_TYPE_THREADED_REBASE_AUTH 103 - -#define BIND_SPECIAL_DYLIB_SELF 0 -#define BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE -1 -#define BIND_SPECIAL_DYLIB_FLAT_LOOKUP -2 -#define BIND_SPECIAL_DYLIB_WEAK_LOOKUP -3 - -#define BIND_SYMBOL_FLAGS_WEAK_IMPORT 0x1 -#define BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION 0x8 - -#define BIND_OPCODE_MASK 0xF0 -#define BIND_IMMEDIATE_MASK 0x0F -#define BIND_OPCODE_DONE 0x00 -#define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM 0x10 -#define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB 0x20 -#define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM 0x30 -#define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM 0x40 -#define BIND_OPCODE_SET_TYPE_IMM 0x50 -#define BIND_OPCODE_SET_ADDEND_SLEB 0x60 -#define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB 0x70 -#define BIND_OPCODE_ADD_ADDR_ULEB 0x80 -#define BIND_OPCODE_DO_BIND 0x90 -#define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB 0xA0 -#define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED 0xB0 -#define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xC0 - -#define BIND_OPCODE_THREADED 0xD0 -#define BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB 0 -#define BIND_SUBOPCODE_THREADED_APPLY 1 - - - - -/* - * The following are used on the flags byte of a terminal node - * in the export information. - */ -#define EXPORT_SYMBOL_FLAGS_KIND_MASK 0x03 -#define EXPORT_SYMBOL_FLAGS_KIND_REGULAR 0x00 -#define EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL 0x01 -#define EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION 0x04 -#define EXPORT_SYMBOL_FLAGS_REEXPORT 0x08 -#define EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER 0x10 - - -//opcodes used for shared region info (LC_SEGMENT_SPLIT_INFO) - -// version 1: -/// ( <opcode> (delta-uleb128)+ <zero> )+ <zero> -#define DYLD_CACHE_ADJ_V1_POINTER_32 0x01 // 32-bit pointer -#define DYLD_CACHE_ADJ_V1_POINTER_64 0x02 // 64-bit pointer -#define DYLD_CACHE_ADJ_V1_ADRP 0x03 // arm64 ADRP -#define DYLD_CACHE_ADJ_V1_PPC_HI16 0x03 // ppc hi16 -#define DYLD_CACHE_ADJ_V1_IMP32 0x04 //32-bit offset to IMPORT -#define DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVW 0x05 //thumb2 movw -#define DYLD_CACHE_ADJ_V1_ARM_MOVW 0x06 //ARM movw -#define DYLD_CACHE_ADJ_V1_ARM_THUMB_MOVT 0x10 // thru 0x1F thumb2 movt low high 4 bits=0..15 -#define DYLD_CACHE_ADJ_V1_ARM_MOVT 0x20 // thru 0x2F arm movt low high 4 bits=0..15 - -// version 2: -// Whole :== <new-marker> <count> FromToSection+ -// FromToSection :== <from-sect-index> <to-sect-index> <count> ToOffset+ -// ToOffset :== <to-sect-offset-delta> <count> FromOffset+ -// FromOffset :== <kind> <count> <from-sect-offset-delta> -#define DYLD_CACHE_ADJ_V2_FORMAT 0x7F - -#define DYLD_CACHE_ADJ_V2_POINTER_32 0x01 -#define DYLD_CACHE_ADJ_V2_POINTER_64 0x02 -#define DYLD_CACHE_ADJ_V2_DELTA_32 0x03 -#define DYLD_CACHE_ADJ_V2_DELTA_64 0x04 -#define DYLD_CACHE_ADJ_V2_ARM64_ADRP 0x05 -#define DYLD_CACHE_ADJ_V2_ARM64_OFF12 0x06 -#define DYLD_CACHE_ADJ_V2_ARM64_BR26 0x07 -#define DYLD_CACHE_ADJ_V2_ARM_MOVW_MOVT 0x08 -#define DYLD_CACHE_ADJ_V2_ARM_BR24 0x09 -#define DYLD_CACHE_ADJ_V2_THUMB_MOVW_MOVT 0x0A -#define DYLD_CACHE_ADJ_V2_THUMB_BR22 0x0B -#define DYLD_CACHE_ADJ_V2_IMAGE_OFF_32 0x0C -#define DYLD_CACHE_ADJ_V2_THREADED_POINTER_64 0x0D - -/* - * The linker_option_command contains linker options embedded in object files. - */ -struct linker_option_command { - uint32_t cmd; /* LC_LINKER_OPTION only used in MH_OBJECT filetypes */ - uint32_t cmdsize; - uint32_t count; /* number of strings */ - /* concatenation of zero terminated UTF8 strings. - Zero filled at end to align */ -}; - -/* - * The symseg_command contains the offset and size of the GNU style - * symbol table information as described in the header file <symseg.h>. - * The symbol roots of the symbol segments must also be aligned properly - * in the file. So the requirement of keeping the offsets aligned to a - * multiple of a 4 bytes translates to the length field of the symbol - * roots also being a multiple of a long. Also the padding must again be - * zeroed. (THIS IS OBSOLETE and no longer supported). - */ -struct symseg_command { - uint32_t cmd; /* LC_SYMSEG */ - uint32_t cmdsize; /* sizeof(struct symseg_command) */ - uint32_t offset; /* symbol segment offset */ - uint32_t size; /* symbol segment size in bytes */ -}; - -/* - * The ident_command contains a free format string table following the - * ident_command structure. The strings are null terminated and the size of - * the command is padded out with zero bytes to a multiple of 4 bytes/ - * (THIS IS OBSOLETE and no longer supported). - */ -struct ident_command { - uint32_t cmd; /* LC_IDENT */ - uint32_t cmdsize; /* strings that follow this command */ -}; - -/* - * The fvmfile_command contains a reference to a file to be loaded at the - * specified virtual address. (Presently, this command is reserved for - * internal use. The kernel ignores this command when loading a program into - * memory). - */ -struct fvmfile_command { - uint32_t cmd; /* LC_FVMFILE */ - uint32_t cmdsize; /* includes pathname string */ - union lc_str name; /* files pathname */ - uint32_t header_addr; /* files virtual address */ -}; - - -/* - * The entry_point_command is a replacement for thread_command. - * It is used for main executables to specify the location (file offset) - * of main(). If -stack_size was used at link time, the stacksize - * field will contain the stack size need for the main thread. - */ -struct entry_point_command { - uint32_t cmd; /* LC_MAIN only used in MH_EXECUTE filetypes */ - uint32_t cmdsize; /* 24 */ - uint64_t entryoff; /* file (__TEXT) offset of main() */ - uint64_t stacksize;/* if not zero, initial stack size */ -}; - - -/* - * The source_version_command is an optional load command containing - * the version of the sources used to build the binary. - */ -struct source_version_command { - uint32_t cmd; /* LC_SOURCE_VERSION */ - uint32_t cmdsize; /* 16 */ - uint64_t version; /* A.B.C.D.E packed as a24.b10.c10.d10.e10 */ -}; - - -/* - * The LC_DATA_IN_CODE load commands uses a linkedit_data_command - * to point to an array of data_in_code_entry entries. Each entry - * describes a range of data in a code section. - */ -struct data_in_code_entry { - uint32_t offset; /* from mach_header to start of data range*/ - uint16_t length; /* number of bytes in data range */ - uint16_t kind; /* a DICE_KIND_* value */ -}; -#define DICE_KIND_DATA 0x0001 /* L$start$data$... label */ -#define DICE_KIND_JUMP_TABLE8 0x0002 /* L$start$jt8$... label */ -#define DICE_KIND_JUMP_TABLE16 0x0003 /* L$start$jt16$... label */ -#define DICE_KIND_JUMP_TABLE32 0x0004 /* L$start$jt32$... label */ -#define DICE_KIND_ABS_JUMP_TABLE32 0x0005 /* L$start$jta32$... label */ - - - -/* - * Sections of type S_THREAD_LOCAL_VARIABLES contain an array - * of tlv_descriptor structures. - */ -struct tlv_descriptor -{ - void* (*thunk)(struct tlv_descriptor*); - unsigned long key; - unsigned long offset; -}; - -/* - * LC_NOTE commands describe a region of arbitrary data included in a Mach-O - * file. Its initial use is to record extra data in MH_CORE files. - */ -struct note_command { - uint32_t cmd; /* LC_NOTE */ - uint32_t cmdsize; /* sizeof(struct note_command) */ - char data_owner[16]; /* owner name for this LC_NOTE */ - uint64_t offset; /* file offset of this data */ - uint64_t size; /* length of data region */ -}; - -#endif /* _MACHO_LOADER_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/m88k/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/m88k/reloc.h deleted file mode 100644 index 81575c7..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/m88k/reloc.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Relocation types used in the m88k implementation. Relocation entries for - * things other than instructions use the same generic relocation as discribed - * above and their r_type is RELOC_VANILLA. The rest of the relocation types - * are for instructions. Since they are for instructions the r_address field - * indicates the 32 bit instruction that the relocation is to be preformed on. - * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types. - */ -enum reloc_type_m88k -{ - M88K_RELOC_VANILLA, /* generic relocation as discribed above */ - M88K_RELOC_PAIR, /* the second relocation entry of a pair */ - M88K_RELOC_PC16, - M88K_RELOC_PC26, - M88K_RELOC_HI16, /* a PAIR follows with the low half */ - M88K_RELOC_LO16, /* a PAIR follows with the high half */ - M88K_RELOC_SECTDIFF,/* a PAIR follows with subtract symbol value */ - M88K_RELOC_PB_LA_PTR/* prebound lazy pointer */ -}; diff --git a/idasdk75/ldr/mach-o/h/mach-o/nlist.h b/idasdk75/ldr/mach-o/h/mach-o/nlist.h deleted file mode 100644 index 86fac59..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/nlist.h +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _MACHO_NLIST_H_ -#define _MACHO_NLIST_H_ -/* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */ - -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * (c) UNIX System Laboratories, Inc. - * All or some portions of this file are derived from material licensed - * to the University of California by American Telephone and Telegraph - * Co. or Unix System Laboratories, Inc. and are reproduced herein with - * the permission of UNIX System Laboratories, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)nlist.h 8.2 (Berkeley) 1/21/94 - */ -#include <stdint.h> - -/* - * Format of a symbol table entry of a Mach-O file for 32-bit architectures. - * Modified from the BSD format. The modifications from the original format - * were changing n_other (an unused field) to n_sect and the addition of the - * N_SECT type. These modifications are required to support symbols in a larger - * number of sections not just the three sections (text, data and bss) in a BSD - * file. - */ -struct nlist { - union { - uint32_t n_strx; /* index into the string table */ - } n_un; - uint8_t n_type; /* type flag, see below */ - uint8_t n_sect; /* section number or NO_SECT */ - int16_t n_desc; /* see <mach-o/stab.h> */ - uint32_t n_value; /* value of this symbol (or stab offset) */ -}; - -/* - * This is the symbol table entry structure for 64-bit architectures. - */ -struct nlist_64 { - union { - uint32_t n_strx; /* index into the string table */ - } n_un; - uint8_t n_type; /* type flag, see below */ - uint8_t n_sect; /* section number or NO_SECT */ - uint16_t n_desc; /* see <mach-o/stab.h> */ - uint64_t n_value; /* value of this symbol (or stab offset) */ -}; - -/* - * Symbols with a index into the string table of zero (n_un.n_strx == 0) are - * defined to have a null, "", name. Therefore all string indexes to non null - * names must not have a zero string index. This is bit historical information - * that has never been well documented. - */ - -/* - * The n_type field really contains four fields: - * unsigned char N_STAB:3, - * N_PEXT:1, - * N_TYPE:3, - * N_EXT:1; - * which are used via the following masks. - */ -#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */ -#define N_PEXT 0x10 /* private external symbol bit */ -#define N_TYPE 0x0e /* mask for the type bits */ -#define N_EXT 0x01 /* external symbol bit, set for external symbols */ - -/* - * Only symbolic debugging entries have some of the N_STAB bits set and if any - * of these bits are set then it is a symbolic debugging entry (a stab). In - * which case then the values of the n_type field (the entire field) are given - * in <mach-o/stab.h> - */ - -/* - * Values for N_TYPE bits of the n_type field. - */ -#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */ -#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */ -#define N_SECT 0xe /* defined in section number n_sect */ -#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */ -#define N_INDR 0xa /* indirect */ - -/* - * If the type is N_INDR then the symbol is defined to be the same as another - * symbol. In this case the n_value field is an index into the string table - * of the other symbol's name. When the other symbol is defined then they both - * take on the defined type and value. - */ - -/* - * If the type is N_SECT then the n_sect field contains an ordinal of the - * section the symbol is defined in. The sections are numbered from 1 and - * refer to sections in order they appear in the load commands for the file - * they are in. This means the same ordinal may very well refer to different - * sections in different files. - * - * The n_value field for all symbol table entries (including N_STAB's) gets - * updated by the link editor based on the value of it's n_sect field and where - * the section n_sect references gets relocated. If the value of the n_sect - * field is NO_SECT then it's n_value field is not changed by the link editor. - */ -#define NO_SECT 0 /* symbol is not in any section */ -#define MAX_SECT 255 /* 1 thru 255 inclusive */ - -/* - * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types - * who's values (n_value) are non-zero. In which case the value of the n_value - * field is the size (in bytes) of the common symbol. The n_sect field is set - * to NO_SECT. The alignment of a common symbol may be set as a power of 2 - * between 2^1 and 2^15 as part of the n_desc field using the macros below. If - * the alignment is not set (a value of zero) then natural alignment based on - * the size is used. - */ -#define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f) -#define SET_COMM_ALIGN(n_desc,align) \ - (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8)) - -/* - * To support the lazy binding of undefined symbols in the dynamic link-editor, - * the undefined symbols in the symbol table (the nlist structures) are marked - * with the indication if the undefined reference is a lazy reference or - * non-lazy reference. If both a non-lazy reference and a lazy reference is - * made to the same symbol the non-lazy reference takes precedence. A reference - * is lazy only when all references to that symbol are made through a symbol - * pointer in a lazy symbol pointer section. - * - * The implementation of marking nlist structures in the symbol table for - * undefined symbols will be to use some of the bits of the n_desc field as a - * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field - * of an nlist structure for an undefined symbol to determine the type of - * undefined reference (lazy or non-lazy). - * - * The constants for the REFERENCE FLAGS are propagated to the reference table - * in a shared library file. In that case the constant for a defined symbol, - * REFERENCE_FLAG_DEFINED, is also used. - */ -/* Reference type bits of the n_desc field of undefined symbols */ -#define REFERENCE_TYPE 0x7 -/* types of references */ -#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0 -#define REFERENCE_FLAG_UNDEFINED_LAZY 1 -#define REFERENCE_FLAG_DEFINED 2 -#define REFERENCE_FLAG_PRIVATE_DEFINED 3 -#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4 -#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5 - -/* - * To simplify stripping of objects that use are used with the dynamic link - * editor, the static link editor marks the symbols defined an object that are - * referenced by a dynamicly bound object (dynamic shared libraries, bundles). - * With this marking strip knows not to strip these symbols. - */ -#define REFERENCED_DYNAMICALLY 0x0010 - -/* - * For images created by the static link editor with the -twolevel_namespace - * option in effect the flags field of the mach header is marked with - * MH_TWOLEVEL. And the binding of the undefined references of the image are - * determined by the static link editor. Which library an undefined symbol is - * bound to is recorded by the static linker in the high 8 bits of the n_desc - * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded - * references the libraries listed in the Mach-O's LC_LOAD_DYLIB load commands - * in the order they appear in the headers. The library ordinals start from 1. - * For a dynamic library that is built as a two-level namespace image the - * undefined references from module defined in another use the same nlist struct - * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For - * defined symbols in all images they also must have the library ordinal set to - * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable - * image for references from plugins that refer to the executable that loads - * them. - * - * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace - * image that are looked up by the dynamic linker with flat namespace semantics. - * This ordinal was added as a feature in Mac OS X 10.3 by reducing the - * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries - * or binaries built with older tools to have 0xfe (254) dynamic libraries. In - * this case the ordinal value 0xfe (254) must be treated as a library ordinal - * for compatibility. - */ -#define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff) -#define SET_LIBRARY_ORDINAL(n_desc,ordinal) \ - (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8)) -#define SELF_LIBRARY_ORDINAL 0x0 -#define MAX_LIBRARY_ORDINAL 0xfd -#define DYNAMIC_LOOKUP_ORDINAL 0xfe -#define EXECUTABLE_ORDINAL 0xff - -/* - * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes - * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED. - */ - -/* - * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a - * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the - * static link editor it is never to dead strip the symbol. - */ -#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */ - -/* - * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image. - * But is used in very rare cases by the dynamic link editor to mark an in - * memory symbol as discared and longer used for linking. - */ -#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */ - -/* - * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that - * the undefined symbol is allowed to be missing and is to have the address of - * zero when missing. - */ -#define N_WEAK_REF 0x0040 /* symbol is weak referenced */ - -/* - * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic - * linkers that the symbol definition is weak, allowing a non-weak symbol to - * also be used which causes the weak definition to be discared. Currently this - * is only supported for symbols in coalesed sections. - */ -#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */ - -/* - * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker - * that the undefined symbol should be resolved using flat namespace searching. - */ -#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */ - -/* - * The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is - * a defintion of a Thumb function. - */ -#define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */ - -/* - * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the - * that the function is actually a resolver function and should - * be called to get the address of the real function to use. - * This bit is only available in .o files (MH_OBJECT filetype) - */ -#define N_SYMBOL_RESOLVER 0x0100 - -/* - * The N_ALT_ENTRY bit of the n_desc field indicates that the - * symbol is pinned to the previous content. - */ -#define N_ALT_ENTRY 0x0200 - -/* - * The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used - * infrequently and the linker should order it towards the end of the section. - */ -#define N_COLD_FUNC 0x0400 - -#ifndef __STRICT_BSD__ -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __STRICT_BSD__ */ - -#endif /* _MACHO_LIST_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/ppc/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/ppc/reloc.h deleted file mode 100644 index 871dc27..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/ppc/reloc.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Relocation types used in the ppc implementation. Relocation entries for - * things other than instructions use the same generic relocation as discribed - * above and their r_type is RELOC_VANILLA. The rest of the relocation types - * are for instructions. Since they are for instructions the r_address field - * indicates the 32 bit instruction that the relocation is to be preformed on. - * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types - * except for PPC_RELOC_BR14. - * - * For PPC_RELOC_BR14 if the r_length is the unused value 3, then the branch was - * statically predicted setting or clearing the Y-bit based on the sign of the - * displacement or the opcode. If this is the case the static linker must flip - * the value of the Y-bit if the sign of the displacement changes for non-branch - * always conditions. - */ -enum reloc_type_ppc -{ - PPC_RELOC_VANILLA, /* generic relocation as discribed above */ - PPC_RELOC_PAIR, /* the second relocation entry of a pair */ - PPC_RELOC_BR14, /* 14 bit branch displacement (to a word address) */ - PPC_RELOC_BR24, /* 24 bit branch displacement (to a word address) */ - PPC_RELOC_HI16, /* a PAIR follows with the low half */ - PPC_RELOC_LO16, /* a PAIR follows with the high half */ - PPC_RELOC_HA16, /* Same as the RELOC_HI16 except the low 16 bits and the - * high 16 bits are added together with the low 16 bits - * sign extened first. This means if bit 15 of the low - * 16 bits is set the high 16 bits stored in the - * instruction will be adjusted. - */ - PPC_RELOC_LO14, /* Same as the LO16 except that the low 2 bits are not - * stored in the instruction and are always zero. This - * is used in double word load/store instructions. - */ - PPC_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */ - PPC_RELOC_PB_LA_PTR,/* prebound lazy pointer */ - PPC_RELOC_HI16_SECTDIFF, /* section difference forms of above. a PAIR */ - PPC_RELOC_LO16_SECTDIFF, /* follows these with subtract symbol value */ - PPC_RELOC_HA16_SECTDIFF, - PPC_RELOC_JBSR, - PPC_RELOC_LO14_SECTDIFF, - PPC_RELOC_LOCAL_SECTDIFF /* like PPC_RELOC_SECTDIFF, but the symbol - referenced was local. */ -}; diff --git a/idasdk75/ldr/mach-o/h/mach-o/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/reloc.h deleted file mode 100644 index 75a1206..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/reloc.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */ - -/* - * Copyright (c) 1993 Christopher G. Demetriou - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _MACHO_RELOC_H_ -#define _MACHO_RELOC_H_ -#include <stdint.h> - -/* - * Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD - * format. The modifications from the original format were changing the value - * of the r_symbolnum field for "local" (r_extern == 0) relocation entries. - * This modification is required to support symbols in an arbitrary number of - * sections not just the three sections (text, data and bss) in a 4.3BSD file. - * Also the last 4 bits have had the r_type tag added to them. - */ -struct relocation_info { - int32_t r_address; /* offset in the section to what is being - relocated */ - uint32_t r_symbolnum:24, /* symbol index if r_extern == 1 or section - ordinal if r_extern == 0 */ - r_pcrel:1, /* was relocated pc relative already */ - r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ - r_extern:1, /* does not include value of sym referenced */ - r_type:4; /* if not 0, machine specific relocation type */ -}; -#define R_ABS 0 /* absolute relocation type for Mach-O files */ - -/* - * The r_address is not really the address as it's name indicates but an offset. - * In 4.3BSD a.out objects this offset is from the start of the "segment" for - * which relocation entry is for (text or data). For Mach-O object files it is - * also an offset but from the start of the "section" for which the relocation - * entry is for. See comments in <mach-o/loader.h> about the r_address feild - * in images for used with the dynamic linker. - * - * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal - * for the segment the symbol being relocated is in. These ordinals are the - * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these - * ordinals refer to the sections in the object file in the order their section - * structures appear in the headers of the object file they are in. The first - * section has the ordinal 1, the second 2, and so on. This means that the - * same ordinal in two different object files could refer to two different - * sections. And further could have still different ordinals when combined - * by the link-editor. The value R_ABS is used for relocation entries for - * absolute symbols which need no further relocation. - */ - -/* - * For RISC machines some of the references are split across two instructions - * and the instruction does not contain the complete value of the reference. - * In these cases a second, or paired relocation entry, follows each of these - * relocation entries, using a PAIR r_type, which contains the other part of the - * reference not contained in the instruction. This other part is stored in the - * pair's r_address field. The exact number of bits of the other part of the - * reference store in the r_address field is dependent on the particular - * relocation type for the particular architecture. - */ - -/* - * To make scattered loading by the link editor work correctly "local" - * relocation entries can't be used when the item to be relocated is the value - * of a symbol plus an offset (where the resulting expresion is outside the - * block the link editor is moving, a blocks are divided at symbol addresses). - * In this case. where the item is a symbol value plus offset, the link editor - * needs to know more than just the section the symbol was defined. What is - * needed is the actual value of the symbol without the offset so it can do the - * relocation correctly based on where the value of the symbol got relocated to - * not the value of the expression (with the offset added to the symbol value). - * So for the NeXT 2.0 release no "local" relocation entries are ever used when - * there is a non-zero offset added to a symbol. The "external" and "local" - * relocation entries remain unchanged. - * - * The implemention is quite messy given the compatibility with the existing - * relocation entry format. The ASSUMPTION is that a section will never be - * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption - * allows the r_address (which is really an offset) to fit in 24 bits and high - * bit of the r_address field in the relocation_info structure to indicate - * it is really a scattered_relocation_info structure. Since these are only - * used in places where "local" relocation entries are used and not where - * "external" relocation entries are used the r_extern field has been removed. - * - * For scattered loading to work on a RISC machine where some of the references - * are split across two instructions the link editor needs to be assured that - * each reference has a unique 32 bit reference (that more than one reference is - * NOT sharing the same high 16 bits for example) so it move each referenced - * item independent of each other. Some compilers guarantees this but the - * compilers don't so scattered loading can be done on those that do guarantee - * this. - */ -#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) -/* - * The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that - * when stattered relocation entries were added the mistake of using a mask - * against a structure that is made up of bit fields was used. To make this - * design work this structure must be laid out in memory the same way so the - * mask can be applied can check the same bit each time (r_scattered). - */ -#endif /* defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) */ -#define R_SCATTERED 0x80000000 /* mask to be applied to the r_address field - of a relocation_info structure to tell that - is is really a scattered_relocation_info - stucture */ -struct scattered_relocation_info { -#ifdef __BIG_ENDIAN__ - uint32_t r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */ - r_pcrel:1, /* was relocated pc relative already */ - r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ - r_type:4, /* if not 0, machine specific relocation type */ - r_address:24; /* offset in the section to what is being - relocated */ - int32_t r_value; /* the value the item to be relocated is - refering to (without any offset added) */ -#endif /* __BIG_ENDIAN__ */ -#ifdef __LITTLE_ENDIAN__ - uint32_t - r_address:24, /* offset in the section to what is being - relocated */ - r_type:4, /* if not 0, machine specific relocation type */ - r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */ - r_pcrel:1, /* was relocated pc relative already */ - r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */ - int32_t r_value; /* the value the item to be relocated is - refering to (without any offset added) */ -#endif /* __LITTLE_ENDIAN__ */ -}; - -/* - * Relocation types used in a generic implementation. Relocation entries for - * normal things use the generic relocation as discribed above and their r_type - * is GENERIC_RELOC_VANILLA (a value of zero). - * - * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support - * the difference of two symbols defined in different sections. That is the - * expression "symbol1 - symbol2 + constant" is a relocatable expression when - * both symbols are defined in some section. For this type of relocation the - * both relocations entries are scattered relocation entries. The value of - * symbol1 is stored in the first relocation entry's r_value field and the - * value of symbol2 is stored in the pair's r_value field. - * - * A special case for a prebound lazy pointer is needed to beable to set the - * value of the lazy pointer back to its non-prebound state. This is done - * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation - * entry where the r_value feild is the value of the lazy pointer not prebound. - */ -enum reloc_type_generic -{ - GENERIC_RELOC_VANILLA, /* generic relocation as discribed above */ - GENERIC_RELOC_PAIR, /* Only follows a GENERIC_RELOC_SECTDIFF */ - GENERIC_RELOC_SECTDIFF, - GENERIC_RELOC_PB_LA_PTR, /* prebound lazy pointer */ - GENERIC_RELOC_LOCAL_SECTDIFF, - GENERIC_RELOC_TLV /* thread local variables */ -}; - -#endif /* _MACHO_RELOC_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/sparc/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/sparc/reloc.h deleted file mode 100644 index 64d3bfd..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/sparc/reloc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.1 (the "License"). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* reloc.h - assemble for Sparc */ -/* Defines machine specific relocation entries */ - -#ifndef SPARC_RELOC_INCLUDED -#define SPARC_RELOC_INCLUDED - -/* - * Relocation types used in the sparc implementation. Relocation entries for - * things other than instructions use the same generic relocation as discribed - * in <mach-o/reloc.h> and their r_type is SPARC_RELOC_VANILLA. The rest of the - * relocation types are for instructions. Since they are for instructions the - * r_address field indicates the 32 bit instruction that the relocation is to - * be preformed on. The field r_pcrel is set only for the SPARC_RELOC_WDISP22 - * and SPARC_RELOC_WDISP30. And r_length is set to long for all - * non-RELOC_VANILLA r_types. - */ -enum reloc_type_sparc -{ - SPARC_RELOC_VANILLA, /* vanilla relocation */ - SPARC_RELOC_PAIR, /* the second relocation entry of a pair */ - SPARC_RELOC_HI22, /* 22 high bits (sethi) (has pair) */ - SPARC_RELOC_LO10, /* 10 low bits (has pair) */ - SPARC_RELOC_WDISP22, /* 22 bit PC relative displacement */ - SPARC_RELOC_WDISP30, /* 30 bit PC relative displacement */ - SPARC_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */ - SPARC_RELOC_HI22_SECTDIFF, - SPARC_RELOC_LO10_SECTDIFF, - SPARC_RELOC_PB_LA_PTR /* prebound lazy pointer */ -}; -#endif /* SPARC_RELOC_INCLUDED */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/stab.h b/idasdk75/ldr/mach-o/h/mach-o/stab.h deleted file mode 100644 index 08e53bf..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/stab.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -#ifndef _MACHO_STAB_H_ -#define _MACHO_STAB_H_ -/* $NetBSD: stab.h,v 1.4 1994/10/26 00:56:25 cgd Exp $ */ - -/*- - * Copyright (c) 1991 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)stab.h 5.2 (Berkeley) 4/4/91 - */ - -/* - * This file gives definitions supplementing <nlist.h> for permanent symbol - * table entries of Mach-O files. Modified from the BSD definitions. The - * modifications from the original definitions were changing what the values of - * what was the n_other field (an unused field) which is now the n_sect field. - * These modifications are required to support symbols in an arbitrary number of - * sections not just the three sections (text, data and bss) in a BSD file. - * The values of the defined constants have NOT been changed. - * - * These must have one of the N_STAB bits on. The n_value fields are subject - * to relocation according to the value of their n_sect field. So for types - * that refer to things in sections the n_sect field must be filled in with the - * proper section ordinal. For types that are not to have their n_value field - * relocatated the n_sect field must be NO_SECT. - */ - -/* - * Symbolic debugger symbols. The comments give the conventional use for - * - * .stabs "n_name", n_type, n_sect, n_desc, n_value - * - * where n_type is the defined constant and not listed in the comment. Other - * fields not listed are zero. n_sect is the section ordinal the entry is - * refering to. - */ -#define N_GSYM 0x20 /* global symbol: name,,NO_SECT,type,0 */ -#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,NO_SECT,0,0 */ -#define N_FUN 0x24 /* procedure: name,,n_sect,linenumber,address */ -#define N_STSYM 0x26 /* static symbol: name,,n_sect,type,address */ -#define N_LCSYM 0x28 /* .lcomm symbol: name,,n_sect,type,address */ -#define N_BNSYM 0x2e /* begin nsect sym: 0,,n_sect,0,address */ -#define N_AST 0x32 /* AST file path: name,,NO_SECT,0,0 */ -#define N_OPT 0x3c /* emitted with gcc2_compiled and in gcc source */ -#define N_RSYM 0x40 /* register sym: name,,NO_SECT,type,register */ -#define N_SLINE 0x44 /* src line: 0,,n_sect,linenumber,address */ -#define N_ENSYM 0x4e /* end nsect sym: 0,,n_sect,0,address */ -#define N_SSYM 0x60 /* structure elt: name,,NO_SECT,type,struct_offset */ -#define N_SO 0x64 /* source file name: name,,n_sect,0,address */ -#define N_OSO 0x66 /* object file name: name,,0,0,st_mtime */ -#define N_LSYM 0x80 /* local sym: name,,NO_SECT,type,offset */ -#define N_BINCL 0x82 /* include file beginning: name,,NO_SECT,0,sum */ -#define N_SOL 0x84 /* #included file name: name,,n_sect,0,address */ -#define N_PARAMS 0x86 /* compiler parameters: name,,NO_SECT,0,0 */ -#define N_VERSION 0x88 /* compiler version: name,,NO_SECT,0,0 */ -#define N_OLEVEL 0x8A /* compiler -O level: name,,NO_SECT,0,0 */ -#define N_PSYM 0xa0 /* parameter: name,,NO_SECT,type,offset */ -#define N_EINCL 0xa2 /* include file end: name,,NO_SECT,0,0 */ -#define N_ENTRY 0xa4 /* alternate entry: name,,n_sect,linenumber,address */ -#define N_LBRAC 0xc0 /* left bracket: 0,,NO_SECT,nesting level,address */ -#define N_EXCL 0xc2 /* deleted include file: name,,NO_SECT,0,sum */ -#define N_RBRAC 0xe0 /* right bracket: 0,,NO_SECT,nesting level,address */ -#define N_BCOMM 0xe2 /* begin common: name,,NO_SECT,0,0 */ -#define N_ECOMM 0xe4 /* end common: name,,n_sect,0,0 */ -#define N_ECOML 0xe8 /* end common (local name): 0,,n_sect,0,address */ -#define N_LENG 0xfe /* second stab entry with length information */ - -/* - * for the berkeley pascal compiler, pc(1): - */ -#define N_PC 0x30 /* global pascal symbol: name,,NO_SECT,subtype,line */ - -#endif /* _MACHO_STAB_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach-o/x86_64/reloc.h b/idasdk75/ldr/mach-o/h/mach-o/x86_64/reloc.h deleted file mode 100644 index a00d6ac..0000000 --- a/idasdk75/ldr/mach-o/h/mach-o/x86_64/reloc.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (c) 2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Relocations for x86_64 are a bit different than for other architectures in - * Mach-O: Scattered relocations are not used. Almost all relocations produced - * by the compiler are external relocations. An external relocation has the - * r_extern bit set to 1 and the r_symbolnum field contains the symbol table - * index of the target label. - * - * When the assembler is generating relocations, if the target label is a local - * label (begins with 'L'), then the previous non-local label in the same - * section is used as the target of the external relocation. An addend is used - * with the distance from that non-local label to the target label. Only when - * there is no previous non-local label in the section is an internal - * relocation used. - * - * The addend (i.e. the 4 in _foo+4) is encoded in the instruction (Mach-O does - * not have RELA relocations). For PC-relative relocations, the addend is - * stored directly in the instruction. This is different from other Mach-O - * architectures, which encode the addend minus the current section offset. - * - * The relocation types are: - * - * X86_64_RELOC_UNSIGNED // for absolute addresses - * X86_64_RELOC_SIGNED // for signed 32-bit displacement - * X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement - * X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry - * X86_64_RELOC_GOT // other GOT references - * X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED - * - * The following are sample assembly instructions, followed by the relocation - * and section content they generate in an object file: - * - * call _foo - * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * E8 00 00 00 00 - * - * call _foo+4 - * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * E8 04 00 00 00 - * - * movq _foo@GOTPCREL(%rip), %rax - * r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * 48 8B 05 00 00 00 00 - * - * pushq _foo@GOTPCREL(%rip) - * r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * FF 35 00 00 00 00 - * - * movl _foo(%rip), %eax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * 8B 05 00 00 00 00 - * - * movl _foo+4(%rip), %eax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * 8B 05 04 00 00 00 - * - * movb $0x12, _foo(%rip) - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * C6 05 FF FF FF FF 12 - * - * movl $0x12345678, _foo(%rip) - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo - * C7 05 FC FF FF FF 78 56 34 12 - * - * .quad _foo - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 00 00 00 00 00 00 00 00 - * - * .quad _foo+4 - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 04 00 00 00 00 00 00 00 - * - * .quad _foo - _bar - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 00 00 00 00 00 00 00 00 - * - * .quad _foo - _bar + 4 - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 04 00 00 00 00 00 00 00 - * - * .long _foo - _bar - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar - * r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * 00 00 00 00 - * - * lea L1(%rip), %rax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev - * 48 8d 05 12 00 00 00 - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * lea L0(%rip), %rax - * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3 - * 48 8d 05 56 00 00 00 - * // assumes L0 is in third section and there is no previous non-local label. - * // The rip-relative-offset of 0x00000056 is L0-address_of_next_instruction. - * // address_of_next_instruction is the address of the relocation + 4. - * - * add $6,L0(%rip) - * r_type=X86_64_RELOC_SIGNED_1, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3 - * 83 05 18 00 00 00 06 - * // assumes L0 is in third section and there is no previous non-local label. - * // The rip-relative-offset of 0x00000018 is L0-address_of_next_instruction. - * // address_of_next_instruction is the address of the relocation + 4 + 1. - * // The +1 comes from SIGNED_1. This is used because the relocation is not - * // at the end of the instruction. - * - * .quad L1 - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev - * 12 00 00 00 00 00 00 00 - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * .quad L0 - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3 - * 56 00 00 00 00 00 00 00 - * // assumes L0 is in third section, has an address of 0x00000056 in .o - * // file, and there is no previous non-local label - * - * .quad _foo - . - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * EE FF FF FF FF FF FF FF - * // assumes _prev is the first non-local label 0x12 bytes before this - * // .quad - * - * .quad _foo - L1 - * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo - * EE FF FF FF FF FF FF FF - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * .quad L1 - _prev - * // No relocations. This is an assembly time constant. - * 12 00 00 00 00 00 00 00 - * // assumes _prev is the first non-local label 0x12 bytes before L1 - * - * - * - * In final linked images, there are only two valid relocation kinds: - * - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index - * This tells dyld to add the address of a symbol to a pointer sized (8-byte) - * piece of data (i.e on disk the 8-byte piece of data contains the addend). The - * r_symbolnum contains the index into the symbol table of the target symbol. - * - * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0 - * This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount - * the containing image was loaded from its base address (e.g. slide). - * - */ -enum reloc_type_x86_64 -{ - X86_64_RELOC_UNSIGNED, // for absolute addresses - X86_64_RELOC_SIGNED, // for signed 32-bit displacement - X86_64_RELOC_BRANCH, // a CALL/JMP instruction with 32-bit displacement - X86_64_RELOC_GOT_LOAD, // a MOVQ load of a GOT entry - X86_64_RELOC_GOT, // other GOT references - X86_64_RELOC_SUBTRACTOR, // must be followed by a X86_64_RELOC_UNSIGNED - X86_64_RELOC_SIGNED_1, // for signed 32-bit displacement with a -1 addend - X86_64_RELOC_SIGNED_2, // for signed 32-bit displacement with a -2 addend - X86_64_RELOC_SIGNED_4, // for signed 32-bit displacement with a -4 addend - X86_64_RELOC_TLV, // for thread local variables -}; diff --git a/idasdk75/ldr/mach-o/h/mach/arm/_structs.h b/idasdk75/ldr/mach-o/h/mach/arm/_structs.h deleted file mode 100644 index bf4f0bd..0000000 --- a/idasdk75/ldr/mach-o/h/mach/arm/_structs.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2004-2007 Apple Inc. All rights reserved. - */ -/* - * @OSF_COPYRIGHT@ - */ -#ifndef _MACH_ARM__STRUCTS_H_ -#define _MACH_ARM__STRUCTS_H_ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_EXCEPTION_STATE struct __darwin_arm_exception_state -_STRUCT_ARM_EXCEPTION_STATE -{ - __uint32_t __exception; /* number of arm exception taken */ - __uint32_t __fsr; /* Fault status */ - __uint32_t __far; /* Virtual Fault Address */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_EXCEPTION_STATE struct arm_exception_state -_STRUCT_ARM_EXCEPTION_STATE -{ - __uint32_t exception; /* number of arm exception taken */ - __uint32_t fsr; /* Fault status */ - __uint32_t far; /* Virtual Fault Address */ -}; -#endif /* __DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_EXCEPTION_STATE64 struct __darwin_arm_exception_state64 -_STRUCT_ARM_EXCEPTION_STATE64 -{ - __uint64_t __far; /* Virtual Fault Address */ - __uint32_t __esr; /* Exception syndrome */ - __uint32_t __exception; /* number of arm exception taken */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_EXCEPTION_STATE64 struct arm_exception_state64 -_STRUCT_ARM_EXCEPTION_STATE64 -{ - __uint64_t far; /* Virtual Fault Address */ - __uint32_t esr; /* Exception syndrome */ - __uint32_t exception; /* number of arm exception taken */ -}; -#endif /* __DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_THREAD_STATE struct __darwin_arm_thread_state -_STRUCT_ARM_THREAD_STATE -{ - __uint32_t __r[13]; /* General purpose register r0-r12 */ - __uint32_t __sp; /* Stack pointer r13 */ - __uint32_t __lr; /* Link register r14 */ - __uint32_t __pc; /* Program counter r15 */ - __uint32_t __cpsr; /* Current program status register */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_THREAD_STATE struct arm_thread_state -_STRUCT_ARM_THREAD_STATE -{ - __uint32_t r[13]; /* General purpose register r0-r12 */ - __uint32_t sp; /* Stack pointer r13 */ - __uint32_t lr; /* Link register r14 */ - __uint32_t pc; /* Program counter r15 */ - __uint32_t cpsr; /* Current program status register */ -}; -#endif /* __DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_THREAD_STATE64 struct __darwin_arm_thread_state64 -_STRUCT_ARM_THREAD_STATE64 -{ - __uint64_t __x[29]; /* General purpose registers x0-x28 */ - __uint64_t __fp; /* Frame pointer x29 */ - __uint64_t __lr; /* Link register x30 */ - __uint64_t __sp; /* Stack pointer x31 */ - __uint64_t __pc; /* Program counter */ - __uint32_t __cpsr; /* Current program status register */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_THREAD_STATE64 struct arm_thread_state64 -_STRUCT_ARM_THREAD_STATE64 -{ - __uint64_t x[29]; /* General purpose registers x0-x28 */ - __uint64_t fp; /* Frame pointer x29 */ - __uint64_t lr; /* Link register x30 */ - __uint64_t sp; /* Stack pointer x31 */ - __uint64_t pc; /* Program counter */ - __uint32_t cpsr; /* Current program status register */ -}; -#endif /* __DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_VFP_STATE struct __darwin_arm_vfp_state -_STRUCT_ARM_VFP_STATE -{ - __uint32_t __r[64]; - __uint32_t __fpscr; - -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_VFP_STATE struct arm_vfp_state -_STRUCT_ARM_VFP_STATE -{ - __uint32_t r[64]; - __uint32_t fpscr; -}; -#endif /* __DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_NEON_STATE64 struct __darwin_arm_neon_state64 -#define _STRUCT_ARM_NEON_STATE struct __darwin_arm_neon_state - -#if defined(__arm64__) -_STRUCT_ARM_NEON_STATE64 -{ - __uint128_t __v[32]; - __uint32_t __fpsr; - __uint32_t __fpcr; -}; - -_STRUCT_ARM_NEON_STATE -{ - __uint128_t __v[16]; - __uint32_t __fpsr; - __uint32_t __fpcr; -}; - -#elif defined(__arm__) -/* - * No 128-bit intrinsic for ARM; leave it opaque for now. - */ -_STRUCT_ARM_NEON_STATE64 -{ - char opaque[(32 * 16) + (2 * sizeof(__uint32_t))]; -} __attribute__((aligned(16))); - -_STRUCT_ARM_NEON_STATE -{ - char opaque[(16 * 16) + (2 * sizeof(__uint32_t))]; -} __attribute__((aligned(16))); - -#else -#error Unknown architecture. -#endif - -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_NEON_STATE64 struct arm_neon_state64 -#define _STRUCT_ARM_NEON_STATE struct arm_neon_state - -#if defined(__arm64__) -_STRUCT_ARM_NEON_STATE64 -{ - __uint128_t q[32]; - uint32_t fpsr; - uint32_t fpcr; - -}; -_STRUCT_ARM_NEON_STATE -{ - __uint128_t q[16]; - uint32_t fpsr; - uint32_t fpcr; - -}; -#elif defined(__arm__) -/* - * No 128-bit intrinsic for ARM; leave it opaque for now. - */ -_STRUCT_ARM_NEON_STATE64 -{ - char opaque[(32 * 16) + (2 * sizeof(__uint32_t))]; -} __attribute__((aligned(16))); - -_STRUCT_ARM_NEON_STATE -{ - char opaque[(16 * 16) + (2 * sizeof(__uint32_t))]; -} __attribute__((aligned(16))); - -#else -#error Unknown architecture. -#endif - -#endif /* __DARWIN_UNIX03 */ - -/* - * Debug State - */ -#if defined(__arm__) -/* Old-fashioned debug state is only for ARM */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_DEBUG_STATE struct __darwin_arm_debug_state -_STRUCT_ARM_DEBUG_STATE -{ - __uint32_t __bvr[16]; - __uint32_t __bcr[16]; - __uint32_t __wvr[16]; - __uint32_t __wcr[16]; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_DEBUG_STATE struct arm_debug_state -_STRUCT_ARM_DEBUG_STATE -{ - __uint32_t bvr[16]; - __uint32_t bcr[16]; - __uint32_t wvr[16]; - __uint32_t wcr[16]; -}; -#endif /* __DARWIN_UNIX03 */ - -#elif defined(__arm64__) - -/* ARM's arm_debug_state is ARM64's arm_legacy_debug_state */ - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_LEGACY_DEBUG_STATE struct arm_legacy_debug_state -_STRUCT_ARM_LEGACY_DEBUG_STATE -{ - __uint32_t __bvr[16]; - __uint32_t __bcr[16]; - __uint32_t __wvr[16]; - __uint32_t __wcr[16]; -}; -#else /* __DARWIN_UNIX03 */ -#define _STRUCT_ARM_LEGACY_DEBUG_STATE struct arm_legacy_debug_state -_STRUCT_ARM_LEGACY_DEBUG_STATE -{ - __uint32_t bvr[16]; - __uint32_t bcr[16]; - __uint32_t wvr[16]; - __uint32_t wcr[16]; -}; -#endif /* __DARWIN_UNIX03 */ -#else -#error unknown architecture -#endif - -#if __DARWIN_UNIX03 -#define _STRUCT_ARM_DEBUG_STATE32 struct __darwin_arm_debug_state32 -_STRUCT_ARM_DEBUG_STATE32 -{ - __uint32_t __bvr[16]; - __uint32_t __bcr[16]; - __uint32_t __wvr[16]; - __uint32_t __wcr[16]; - __uint64_t __mdscr_el1; /* Bit 0 is SS (Hardware Single Step) */ -}; - -#define _STRUCT_ARM_DEBUG_STATE64 struct __darwin_arm_debug_state64 -_STRUCT_ARM_DEBUG_STATE64 -{ - __uint64_t __bvr[16]; - __uint64_t __bcr[16]; - __uint64_t __wvr[16]; - __uint64_t __wcr[16]; - __uint64_t __mdscr_el1; /* Bit 0 is SS (Hardware Single Step) */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_ARM_DEBUG_STATE32 struct arm_debug_state32 -_STRUCT_ARM_DEBUG_STATE32 -{ - __uint32_t bvr[16]; - __uint32_t bcr[16]; - __uint32_t wvr[16]; - __uint32_t wcr[16]; - __uint64_t mdscr_el1; /* Bit 0 is SS (Hardware Single Step) */ -}; - -#define _STRUCT_ARM_DEBUG_STATE64 struct arm_debug_state64 -_STRUCT_ARM_DEBUG_STATE64 -{ - __uint64_t bvr[16]; - __uint64_t bcr[16]; - __uint64_t wvr[16]; - __uint64_t wcr[16]; - __uint64_t mdscr_el1; /* Bit 0 is SS (Hardware Single Step) */ -}; -#endif /* __DARWIN_UNIX03 */ - -#endif /* _MACH_ARM__STRUCTS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/arm/boolean.h b/idasdk75/ldr/mach-o/h/mach/arm/boolean.h deleted file mode 100644 index cc539a2..0000000 --- a/idasdk75/ldr/mach-o/h/mach/arm/boolean.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: boolean.h - * - * Boolean type, for ARM. - */ - -#ifndef _MACH_ARM_BOOLEAN_H_ -#define _MACH_ARM_BOOLEAN_H_ - -typedef int boolean_t; - -#endif /* _MACH_ARM_BOOLEAN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/arm/exception.h b/idasdk75/ldr/mach-o/h/mach/arm/exception.h deleted file mode 100644 index 4a583e2..0000000 --- a/idasdk75/ldr/mach-o/h/mach/arm/exception.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2007 Apple Inc. All rights reserved. - */ - -#ifndef _MACH_ARM_EXCEPTION_H_ -#define _MACH_ARM_EXCEPTION_H_ - -#define EXC_TYPES_COUNT 13 /* incl. illegal exception 0 */ - -#define EXC_MASK_MACHINE 0 - -#define EXCEPTION_CODE_MAX 2 /* code and subcode */ - -/* - * Trap numbers as defined by the hardware exception vectors. - */ - -/* - * EXC_BAD_INSTRUCTION - */ - -#define EXC_ARM_UNDEFINED 1 /* Undefined */ - - -/* - * EXC_BAD_ACCESS - * Note: do not conflict with kern_return_t values returned by vm_fault - */ - -#define EXC_ARM_DA_ALIGN 0x101 /* Alignment Fault */ -#define EXC_ARM_DA_DEBUG 0x102 /* Debug (watch/break) Fault */ -#define EXC_ARM_SP_ALIGN 0x103 /* SP Alignment Fault */ -#define EXC_ARM_SWP 0x104 /* SWP instruction */ - -/* - * EXC_BREAKPOINT - */ - -#define EXC_ARM_BREAKPOINT 1 /* breakpoint trap */ - - -#endif /* _MACH_ARM_EXCEPTION_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/arm/thread_state.h b/idasdk75/ldr/mach-o/h/mach/arm/thread_state.h deleted file mode 100644 index 85c8be4..0000000 --- a/idasdk75/ldr/mach-o/h/mach/arm/thread_state.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - */ -/* - * @OSF_COPYRIGHT@ - */ - -#ifndef _MACH_ARM_THREAD_STATE_H_ -#define _MACH_ARM_THREAD_STATE_H_ - -/* Size of maximum exported thread state in words */ -#define ARM_THREAD_STATE_MAX (144) /* Size of biggest state possible */ - -#if defined (__arm__) || defined(__arm64__) -#define THREAD_STATE_MAX ARM_THREAD_STATE_MAX -#else -#error Unsupported arch -#endif - -#endif /* _MACH_ARM_THREAD_STATE_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/arm/thread_status.h b/idasdk75/ldr/mach-o/h/mach/arm/thread_status.h deleted file mode 100644 index bc62801..0000000 --- a/idasdk75/ldr/mach-o/h/mach/arm/thread_status.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright (c) 2007 Apple Inc. All rights reserved. - */ -/* - * FILE_ID: thread_status.h - */ - - -#ifndef _ARM_THREAD_STATUS_H_ -#define _ARM_THREAD_STATUS_H_ - -#include <mach/arm/_structs.h> -#include <mach/message.h> -#include <mach/arm/thread_state.h> - -/* - * Support for determining the state of a thread - */ - - -/* - * Flavors - */ -#define ARM_THREAD_STATE 1 -#define ARM_UNIFIED_THREAD_STATE ARM_THREAD_STATE -#define ARM_VFP_STATE 2 -#define ARM_EXCEPTION_STATE 3 -#define ARM_DEBUG_STATE 4 /* pre-armv8 */ -#define THREAD_STATE_NONE 5 -#define ARM_THREAD_STATE64 6 -#define ARM_EXCEPTION_STATE64 7 -// ARM_THREAD_STATE_LAST (legacy) 8 -#define ARM_THREAD_STATE32 9 - -/* API */ -#define ARM_DEBUG_STATE32 14 -#define ARM_DEBUG_STATE64 15 -#define ARM_NEON_STATE 16 -#define ARM_NEON_STATE64 17 - - -#define VALID_THREAD_STATE_FLAVOR(x)\ -((x == ARM_THREAD_STATE) || \ - (x == ARM_VFP_STATE) || \ - (x == ARM_EXCEPTION_STATE) || \ - (x == ARM_DEBUG_STATE) || \ - (x == THREAD_STATE_NONE) || \ - (x == ARM_THREAD_STATE32) || \ - (x == ARM_THREAD_STATE64) || \ - (x == ARM_EXCEPTION_STATE64) || \ - (x == ARM_NEON_STATE) || \ - (x == ARM_NEON_STATE64) || \ - (x == ARM_DEBUG_STATE32) || \ - (x == ARM_DEBUG_STATE64)) - -struct arm_state_hdr { - uint32_t flavor; - uint32_t count; -}; -typedef struct arm_state_hdr arm_state_hdr_t; - -typedef _STRUCT_ARM_THREAD_STATE arm_thread_state_t; -typedef _STRUCT_ARM_THREAD_STATE arm_thread_state32_t; -typedef _STRUCT_ARM_THREAD_STATE64 arm_thread_state64_t; - -struct arm_unified_thread_state { - arm_state_hdr_t ash; - union { - arm_thread_state32_t ts_32; - arm_thread_state64_t ts_64; - } uts; -}; -#define ts_32 uts.ts_32 -#define ts_64 uts.ts_64 -typedef struct arm_unified_thread_state arm_unified_thread_state_t; - -#define ARM_THREAD_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_thread_state_t)/sizeof(uint32_t))) -#define ARM_THREAD_STATE32_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_thread_state32_t)/sizeof(uint32_t))) -#define ARM_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_thread_state64_t)/sizeof(uint32_t))) -#define ARM_UNIFIED_THREAD_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_unified_thread_state_t)/sizeof(uint32_t))) - - -typedef _STRUCT_ARM_VFP_STATE arm_vfp_state_t; -typedef _STRUCT_ARM_NEON_STATE arm_neon_state_t; -typedef _STRUCT_ARM_NEON_STATE arm_neon_state32_t; -typedef _STRUCT_ARM_NEON_STATE64 arm_neon_state64_t; - -typedef _STRUCT_ARM_EXCEPTION_STATE arm_exception_state_t; -typedef _STRUCT_ARM_EXCEPTION_STATE arm_exception_state32_t; -typedef _STRUCT_ARM_EXCEPTION_STATE64 arm_exception_state64_t; - -typedef _STRUCT_ARM_DEBUG_STATE32 arm_debug_state32_t; -typedef _STRUCT_ARM_DEBUG_STATE64 arm_debug_state64_t; - -/* - * Otherwise not ARM64 kernel and we must preserve legacy ARM definitions of - * arm_debug_state for binary compatability of userland consumers of this file. - */ -#if defined(__arm__) -typedef _STRUCT_ARM_DEBUG_STATE arm_debug_state_t; -#elif defined(__arm64__) -typedef _STRUCT_ARM_LEGACY_DEBUG_STATE arm_debug_state_t; -#else -#error Undefined architecture -#endif - -#define ARM_VFP_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_vfp_state_t)/sizeof(uint32_t))) - -#define ARM_EXCEPTION_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_exception_state_t)/sizeof(uint32_t))) - -#define ARM_EXCEPTION_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_exception_state64_t)/sizeof(uint32_t))) - -#define ARM_DEBUG_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_debug_state_t)/sizeof(uint32_t))) - -#define ARM_DEBUG_STATE32_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_debug_state32_t)/sizeof(uint32_t))) - -#define ARM_DEBUG_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_debug_state64_t)/sizeof(uint32_t))) - -#define ARM_NEON_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_neon_state_t)/sizeof(uint32_t))) - -#define ARM_NEON_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof (arm_neon_state64_t)/sizeof(uint32_t))) - -#define MACHINE_THREAD_STATE ARM_THREAD_STATE -#define MACHINE_THREAD_STATE_COUNT ARM_UNIFIED_THREAD_STATE_COUNT - - - -/* - * Largest state on this machine: - */ -#define THREAD_MACHINE_STATE_MAX THREAD_STATE_MAX - - -#endif /* _ARM_THREAD_STATUS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/arm/vm_types.h b/idasdk75/ldr/mach-o/h/mach/arm/vm_types.h deleted file mode 100644 index 2f0b489..0000000 --- a/idasdk75/ldr/mach-o/h/mach/arm/vm_types.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: vm_types.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * Header file for VM data types. ARM version. - */ - -#ifndef _MACH_ARM_VM_TYPES_H_ -#define _MACH_ARM_VM_TYPES_H_ - -#ifndef ASSEMBLER - -#include <arm/_types.h> -#include <stdint.h> - -/* - * natural_t and integer_t are Mach's legacy types for machine- - * independent integer types (unsigned, and signed, respectively). - * Their original purpose was to define other types in a machine/ - * compiler independent way. - * - * They also had an implicit "same size as pointer" characteristic - * to them (i.e. Mach's traditional types are very ILP32 or ILP64 - * centric). We will likely support x86 ABIs that do not follow - * either ofthese models (specifically LP64). Therefore, we had to - * make a choice between making these types scale with pointers or stay - * tied to integers. Because their use is predominantly tied to - * to the size of an integer, we are keeping that association and - * breaking free from pointer size guarantees. - * - * New use of these types is discouraged. - */ -typedef __darwin_natural_t natural_t; -typedef int integer_t; - -/* - * A vm_offset_t is a type-neutral pointer, - * e.g. an offset into a virtual memory space. - */ -typedef natural_t vm_offset_t; - -/* - * A vm_size_t is the proper type for e.g. - * expressing the difference between two - * vm_offset_t entities. - */ -typedef natural_t vm_size_t; - -/* - * This new type is independent of a particular vm map's - * implementation size - and represents appropriate types - * for all possible maps. This is used for interfaces - * where the size of the map is not known - or we don't - * want to have to distinguish. - */ -typedef uint32_t mach_vm_address_t; -typedef uint32_t mach_vm_offset_t; -typedef uint32_t mach_vm_size_t; - -typedef uint32_t vm_map_offset_t; -typedef uint32_t vm_map_address_t; -typedef uint32_t vm_map_size_t; -#define VM_MAP_MIN_ADDRESS VM_MIN_ADDRESS -#define VM_MAP_MAX_ADDRESS VM_MAX_ADDRESS - - -#endif /* ASSEMBLER */ - -/* - * If composing messages by hand (please do not) - */ -#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32 - -#endif /* _MACH_ARM_VM_TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/boolean.h b/idasdk75/ldr/mach-o/h/mach/boolean.h deleted file mode 100644 index 53030b7..0000000 --- a/idasdk75/ldr/mach-o/h/mach/boolean.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ -/* - * File: mach/boolean.h - * - * Boolean data type. - * - */ - -#ifndef _MACH_BOOLEAN_H_ -#define _MACH_BOOLEAN_H_ - -/* - * Pick up "boolean_t" type definition - */ - -#ifndef ASSEMBLER -#include <mach/machine/boolean.h> -#endif /* ASSEMBLER */ - -/* - * Define TRUE and FALSE if not defined. - */ - -#ifndef TRUE -#define TRUE 1 -#endif /* TRUE */ - -#ifndef FALSE -#define FALSE 0 -#endif /* FALSE */ - -#endif /* _MACH_BOOLEAN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/_structs.h b/idasdk75/ldr/mach-o/h/mach/i386/_structs.h deleted file mode 100644 index 13070ce..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/_structs.h +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ - -#ifndef _MACH_I386__STRUCTS_H_ -#define _MACH_I386__STRUCTS_H_ - -/* - * i386 is the structure that is exported to user threads for - * use in status/mutate calls. This structure should never change. - * - */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_THREAD_STATE32 struct __darwin_i386_thread_state -_STRUCT_X86_THREAD_STATE32 -{ - unsigned int __eax; - unsigned int __ebx; - unsigned int __ecx; - unsigned int __edx; - unsigned int __edi; - unsigned int __esi; - unsigned int __ebp; - unsigned int __esp; - unsigned int __ss; - unsigned int __eflags; - unsigned int __eip; - unsigned int __cs; - unsigned int __ds; - unsigned int __es; - unsigned int __fs; - unsigned int __gs; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_THREAD_STATE32 struct i386_thread_state -_STRUCT_X86_THREAD_STATE32 -{ - unsigned int eax; - unsigned int ebx; - unsigned int ecx; - unsigned int edx; - unsigned int edi; - unsigned int esi; - unsigned int ebp; - unsigned int esp; - unsigned int ss; - unsigned int eflags; - unsigned int eip; - unsigned int cs; - unsigned int ds; - unsigned int es; - unsigned int fs; - unsigned int gs; -}; -#endif /* !__DARWIN_UNIX03 */ - -/* This structure should be double-word aligned for performance */ - -#if __DARWIN_UNIX03 -#define _STRUCT_FP_CONTROL struct __darwin_fp_control -_STRUCT_FP_CONTROL -{ - unsigned short __invalid :1, - __denorm :1, - __zdiv :1, - __ovrfl :1, - __undfl :1, - __precis :1, - :2, - __pc :2, -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define FP_PREC_24B 0 -#define FP_PREC_53B 2 -#define FP_PREC_64B 3 -#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */ - __rc :2, -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define FP_RND_NEAR 0 -#define FP_RND_DOWN 1 -#define FP_RND_UP 2 -#define FP_CHOP 3 -#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */ - /*inf*/ :1, - :3; -}; -typedef _STRUCT_FP_CONTROL __darwin_fp_control_t; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_FP_CONTROL struct fp_control -_STRUCT_FP_CONTROL -{ - unsigned short invalid :1, - denorm :1, - zdiv :1, - ovrfl :1, - undfl :1, - precis :1, - :2, - pc :2, -#define FP_PREC_24B 0 -#define FP_PREC_53B 2 -#define FP_PREC_64B 3 - rc :2, -#define FP_RND_NEAR 0 -#define FP_RND_DOWN 1 -#define FP_RND_UP 2 -#define FP_CHOP 3 - /*inf*/ :1, - :3; -}; -typedef _STRUCT_FP_CONTROL fp_control_t; -#endif /* !__DARWIN_UNIX03 */ - -/* - * Status word. - */ - -#if __DARWIN_UNIX03 -#define _STRUCT_FP_STATUS struct __darwin_fp_status -_STRUCT_FP_STATUS -{ - unsigned short __invalid :1, - __denorm :1, - __zdiv :1, - __ovrfl :1, - __undfl :1, - __precis :1, - __stkflt :1, - __errsumm :1, - __c0 :1, - __c1 :1, - __c2 :1, - __tos :3, - __c3 :1, - __busy :1; -}; -typedef _STRUCT_FP_STATUS __darwin_fp_status_t; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_FP_STATUS struct fp_status -_STRUCT_FP_STATUS -{ - unsigned short invalid :1, - denorm :1, - zdiv :1, - ovrfl :1, - undfl :1, - precis :1, - stkflt :1, - errsumm :1, - c0 :1, - c1 :1, - c2 :1, - tos :3, - c3 :1, - busy :1; -}; -typedef _STRUCT_FP_STATUS fp_status_t; -#endif /* !__DARWIN_UNIX03 */ - -/* defn of 80bit x87 FPU or MMX register */ - -#if __DARWIN_UNIX03 -#define _STRUCT_MMST_REG struct __darwin_mmst_reg -_STRUCT_MMST_REG -{ - char __mmst_reg[10]; - char __mmst_rsrv[6]; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_MMST_REG struct mmst_reg -_STRUCT_MMST_REG -{ - char mmst_reg[10]; - char mmst_rsrv[6]; -}; -#endif /* !__DARWIN_UNIX03 */ - - -/* defn of 128 bit XMM regs */ - -#if __DARWIN_UNIX03 -#define _STRUCT_XMM_REG struct __darwin_xmm_reg -_STRUCT_XMM_REG -{ - char __xmm_reg[16]; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_XMM_REG struct xmm_reg -_STRUCT_XMM_REG -{ - char xmm_reg[16]; -}; -#endif /* !__DARWIN_UNIX03 */ - -/* - * Floating point state. - */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define FP_STATE_BYTES 512 /* number of chars worth of data from fpu_fcw */ -#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_FLOAT_STATE32 struct __darwin_i386_float_state -_STRUCT_X86_FLOAT_STATE32 -{ - int __fpu_reserved[2]; - _STRUCT_FP_CONTROL __fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS __fpu_fsw; /* x87 FPU status word */ - __uint8_t __fpu_ftw; /* x87 FPU tag word */ - __uint8_t __fpu_rsrv1; /* reserved */ - __uint16_t __fpu_fop; /* x87 FPU Opcode */ - __uint32_t __fpu_ip; /* x87 FPU Instruction Pointer offset */ - __uint16_t __fpu_cs; /* x87 FPU Instruction Pointer Selector */ - __uint16_t __fpu_rsrv2; /* reserved */ - __uint32_t __fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */ - __uint16_t __fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */ - __uint16_t __fpu_rsrv3; /* reserved */ - __uint32_t __fpu_mxcsr; /* MXCSR Register state */ - __uint32_t __fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG __fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG __fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG __fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG __fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG __fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG __fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG __fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG __fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG __fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG __fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG __fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG __fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG __fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG __fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG __fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG __fpu_xmm7; /* XMM 7 */ - char __fpu_rsrv4[14*16]; /* reserved */ - int __fpu_reserved1; -}; - -#define _STRUCT_X86_AVX_STATE32 struct __darwin_i386_avx_state -_STRUCT_X86_AVX_STATE32 -{ - int __fpu_reserved[2]; - _STRUCT_FP_CONTROL __fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS __fpu_fsw; /* x87 FPU status word */ - __uint8_t __fpu_ftw; /* x87 FPU tag word */ - __uint8_t __fpu_rsrv1; /* reserved */ - __uint16_t __fpu_fop; /* x87 FPU Opcode */ - __uint32_t __fpu_ip; /* x87 FPU Instruction Pointer offset */ - __uint16_t __fpu_cs; /* x87 FPU Instruction Pointer Selector */ - __uint16_t __fpu_rsrv2; /* reserved */ - __uint32_t __fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */ - __uint16_t __fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */ - __uint16_t __fpu_rsrv3; /* reserved */ - __uint32_t __fpu_mxcsr; /* MXCSR Register state */ - __uint32_t __fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG __fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG __fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG __fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG __fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG __fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG __fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG __fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG __fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG __fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG __fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG __fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG __fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG __fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG __fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG __fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG __fpu_xmm7; /* XMM 7 */ - char __fpu_rsrv4[14*16]; /* reserved */ - int __fpu_reserved1; - char __avx_reserved1[64]; - _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ - _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ - _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ - _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ - _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ - _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ - _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ - _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ -}; - -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_FLOAT_STATE32 struct i386_float_state -_STRUCT_X86_FLOAT_STATE32 -{ - int fpu_reserved[2]; - _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */ - __uint8_t fpu_ftw; /* x87 FPU tag word */ - __uint8_t fpu_rsrv1; /* reserved */ - __uint16_t fpu_fop; /* x87 FPU Opcode */ - __uint32_t fpu_ip; /* x87 FPU Instruction Pointer offset */ - __uint16_t fpu_cs; /* x87 FPU Instruction Pointer Selector */ - __uint16_t fpu_rsrv2; /* reserved */ - __uint32_t fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */ - __uint16_t fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */ - __uint16_t fpu_rsrv3; /* reserved */ - __uint32_t fpu_mxcsr; /* MXCSR Register state */ - __uint32_t fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ - char fpu_rsrv4[14*16]; /* reserved */ - int fpu_reserved1; -}; - -#define _STRUCT_X86_AVX_STATE32 struct i386_avx_state -_STRUCT_X86_AVX_STATE32 -{ - int fpu_reserved[2]; - _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */ - __uint8_t fpu_ftw; /* x87 FPU tag word */ - __uint8_t fpu_rsrv1; /* reserved */ - __uint16_t fpu_fop; /* x87 FPU Opcode */ - __uint32_t fpu_ip; /* x87 FPU Instruction Pointer offset */ - __uint16_t fpu_cs; /* x87 FPU Instruction Pointer Selector */ - __uint16_t fpu_rsrv2; /* reserved */ - __uint32_t fpu_dp; /* x87 FPU Instruction Operand(Data) Pointer offset */ - __uint16_t fpu_ds; /* x87 FPU Instruction Operand(Data) Pointer Selector */ - __uint16_t fpu_rsrv3; /* reserved */ - __uint32_t fpu_mxcsr; /* MXCSR Register state */ - __uint32_t fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ - char fpu_rsrv4[14*16]; /* reserved */ - int fpu_reserved1; - char __avx_reserved1[64]; - _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ - _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ - _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ - _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ - _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ - _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ - _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ - _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ -}; - -#endif /* !__DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_EXCEPTION_STATE32 struct __darwin_i386_exception_state -_STRUCT_X86_EXCEPTION_STATE32 -{ - __uint16_t __trapno; - __uint16_t __cpu; - __uint32_t __err; - __uint32_t __faultvaddr; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_EXCEPTION_STATE32 struct i386_exception_state -_STRUCT_X86_EXCEPTION_STATE32 -{ - __uint16_t trapno; - __uint16_t cpu; - __uint32_t err; - __uint32_t faultvaddr; -}; -#endif /* !__DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_DEBUG_STATE32 struct __darwin_x86_debug_state32 -_STRUCT_X86_DEBUG_STATE32 -{ - unsigned int __dr0; - unsigned int __dr1; - unsigned int __dr2; - unsigned int __dr3; - unsigned int __dr4; - unsigned int __dr5; - unsigned int __dr6; - unsigned int __dr7; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_DEBUG_STATE32 struct x86_debug_state32 -_STRUCT_X86_DEBUG_STATE32 -{ - unsigned int dr0; - unsigned int dr1; - unsigned int dr2; - unsigned int dr3; - unsigned int dr4; - unsigned int dr5; - unsigned int dr6; - unsigned int dr7; -}; -#endif /* !__DARWIN_UNIX03 */ - -/* - * 64 bit versions of the above - */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_THREAD_STATE64 struct __darwin_x86_thread_state64 -_STRUCT_X86_THREAD_STATE64 -{ - __uint64_t __rax; - __uint64_t __rbx; - __uint64_t __rcx; - __uint64_t __rdx; - __uint64_t __rdi; - __uint64_t __rsi; - __uint64_t __rbp; - __uint64_t __rsp; - __uint64_t __r8; - __uint64_t __r9; - __uint64_t __r10; - __uint64_t __r11; - __uint64_t __r12; - __uint64_t __r13; - __uint64_t __r14; - __uint64_t __r15; - __uint64_t __rip; - __uint64_t __rflags; - __uint64_t __cs; - __uint64_t __fs; - __uint64_t __gs; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_THREAD_STATE64 struct x86_thread_state64 -_STRUCT_X86_THREAD_STATE64 -{ - __uint64_t rax; - __uint64_t rbx; - __uint64_t rcx; - __uint64_t rdx; - __uint64_t rdi; - __uint64_t rsi; - __uint64_t rbp; - __uint64_t rsp; - __uint64_t r8; - __uint64_t r9; - __uint64_t r10; - __uint64_t r11; - __uint64_t r12; - __uint64_t r13; - __uint64_t r14; - __uint64_t r15; - __uint64_t rip; - __uint64_t rflags; - __uint64_t cs; - __uint64_t fs; - __uint64_t gs; -}; -#endif /* !__DARWIN_UNIX03 */ - -/* - * 64 bit versions of the above (complete) - */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_THREAD_FULL_STATE64 struct __darwin_x86_thread_full_state64 -_STRUCT_X86_THREAD_FULL_STATE64 -{ - _STRUCT_X86_THREAD_STATE64 ss64; - __uint64_t __ds; - __uint64_t __es; - __uint64_t __ss; - __uint64_t __gsbase; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_THREAD_FULL_STATE64 struct x86_thread_full_state64 -_STRUCT_X86_THREAD_FULL_STATE64 -{ - _STRUCT_X86_THREAD_STATE64 ss64; - __uint64_t ds; - __uint64_t es; - __uint64_t ss; - __uint64_t gsbase; -}; -#endif /* !__DARWIN_UNIX03 */ - - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_FLOAT_STATE64 struct __darwin_x86_float_state64 -_STRUCT_X86_FLOAT_STATE64 -{ - int __fpu_reserved[2]; - _STRUCT_FP_CONTROL __fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS __fpu_fsw; /* x87 FPU status word */ - __uint8_t __fpu_ftw; /* x87 FPU tag word */ - __uint8_t __fpu_rsrv1; /* reserved */ - __uint16_t __fpu_fop; /* x87 FPU Opcode */ - - /* x87 FPU Instruction Pointer */ - __uint32_t __fpu_ip; /* offset */ - __uint16_t __fpu_cs; /* Selector */ - - __uint16_t __fpu_rsrv2; /* reserved */ - - /* x87 FPU Instruction Operand(Data) Pointer */ - __uint32_t __fpu_dp; /* offset */ - __uint16_t __fpu_ds; /* Selector */ - - __uint16_t __fpu_rsrv3; /* reserved */ - __uint32_t __fpu_mxcsr; /* MXCSR Register state */ - __uint32_t __fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG __fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG __fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG __fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG __fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG __fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG __fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG __fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG __fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG __fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG __fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG __fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG __fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG __fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG __fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG __fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG __fpu_xmm7; /* XMM 7 */ - _STRUCT_XMM_REG __fpu_xmm8; /* XMM 8 */ - _STRUCT_XMM_REG __fpu_xmm9; /* XMM 9 */ - _STRUCT_XMM_REG __fpu_xmm10; /* XMM 10 */ - _STRUCT_XMM_REG __fpu_xmm11; /* XMM 11 */ - _STRUCT_XMM_REG __fpu_xmm12; /* XMM 12 */ - _STRUCT_XMM_REG __fpu_xmm13; /* XMM 13 */ - _STRUCT_XMM_REG __fpu_xmm14; /* XMM 14 */ - _STRUCT_XMM_REG __fpu_xmm15; /* XMM 15 */ - char __fpu_rsrv4[6*16]; /* reserved */ - int __fpu_reserved1; -}; - -#define _STRUCT_X86_AVX_STATE64 struct __darwin_x86_avx_state64 -_STRUCT_X86_AVX_STATE64 -{ - int __fpu_reserved[2]; - _STRUCT_FP_CONTROL __fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS __fpu_fsw; /* x87 FPU status word */ - __uint8_t __fpu_ftw; /* x87 FPU tag word */ - __uint8_t __fpu_rsrv1; /* reserved */ - __uint16_t __fpu_fop; /* x87 FPU Opcode */ - - /* x87 FPU Instruction Pointer */ - __uint32_t __fpu_ip; /* offset */ - __uint16_t __fpu_cs; /* Selector */ - - __uint16_t __fpu_rsrv2; /* reserved */ - - /* x87 FPU Instruction Operand(Data) Pointer */ - __uint32_t __fpu_dp; /* offset */ - __uint16_t __fpu_ds; /* Selector */ - - __uint16_t __fpu_rsrv3; /* reserved */ - __uint32_t __fpu_mxcsr; /* MXCSR Register state */ - __uint32_t __fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG __fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG __fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG __fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG __fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG __fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG __fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG __fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG __fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG __fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG __fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG __fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG __fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG __fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG __fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG __fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG __fpu_xmm7; /* XMM 7 */ - _STRUCT_XMM_REG __fpu_xmm8; /* XMM 8 */ - _STRUCT_XMM_REG __fpu_xmm9; /* XMM 9 */ - _STRUCT_XMM_REG __fpu_xmm10; /* XMM 10 */ - _STRUCT_XMM_REG __fpu_xmm11; /* XMM 11 */ - _STRUCT_XMM_REG __fpu_xmm12; /* XMM 12 */ - _STRUCT_XMM_REG __fpu_xmm13; /* XMM 13 */ - _STRUCT_XMM_REG __fpu_xmm14; /* XMM 14 */ - _STRUCT_XMM_REG __fpu_xmm15; /* XMM 15 */ - char __fpu_rsrv4[6*16]; /* reserved */ - int __fpu_reserved1; - char __avx_reserved1[64]; - _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ - _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ - _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ - _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ - _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ - _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ - _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ - _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ - _STRUCT_XMM_REG __fpu_ymmh8; /* YMMH 8 */ - _STRUCT_XMM_REG __fpu_ymmh9; /* YMMH 9 */ - _STRUCT_XMM_REG __fpu_ymmh10; /* YMMH 10 */ - _STRUCT_XMM_REG __fpu_ymmh11; /* YMMH 11 */ - _STRUCT_XMM_REG __fpu_ymmh12; /* YMMH 12 */ - _STRUCT_XMM_REG __fpu_ymmh13; /* YMMH 13 */ - _STRUCT_XMM_REG __fpu_ymmh14; /* YMMH 14 */ - _STRUCT_XMM_REG __fpu_ymmh15; /* YMMH 15 */ -}; - -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_FLOAT_STATE64 struct x86_float_state64 -_STRUCT_X86_FLOAT_STATE64 -{ - int fpu_reserved[2]; - _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */ - __uint8_t fpu_ftw; /* x87 FPU tag word */ - __uint8_t fpu_rsrv1; /* reserved */ - __uint16_t fpu_fop; /* x87 FPU Opcode */ - - /* x87 FPU Instruction Pointer */ - __uint32_t fpu_ip; /* offset */ - __uint16_t fpu_cs; /* Selector */ - - __uint16_t fpu_rsrv2; /* reserved */ - - /* x87 FPU Instruction Operand(Data) Pointer */ - __uint32_t fpu_dp; /* offset */ - __uint16_t fpu_ds; /* Selector */ - - __uint16_t fpu_rsrv3; /* reserved */ - __uint32_t fpu_mxcsr; /* MXCSR Register state */ - __uint32_t fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ - _STRUCT_XMM_REG fpu_xmm8; /* XMM 8 */ - _STRUCT_XMM_REG fpu_xmm9; /* XMM 9 */ - _STRUCT_XMM_REG fpu_xmm10; /* XMM 10 */ - _STRUCT_XMM_REG fpu_xmm11; /* XMM 11 */ - _STRUCT_XMM_REG fpu_xmm12; /* XMM 12 */ - _STRUCT_XMM_REG fpu_xmm13; /* XMM 13 */ - _STRUCT_XMM_REG fpu_xmm14; /* XMM 14 */ - _STRUCT_XMM_REG fpu_xmm15; /* XMM 15 */ - char fpu_rsrv4[6*16]; /* reserved */ - int fpu_reserved1; -}; - -#define _STRUCT_X86_AVX_STATE64 struct x86_avx_state64 -_STRUCT_X86_AVX_STATE64 -{ - int fpu_reserved[2]; - _STRUCT_FP_CONTROL fpu_fcw; /* x87 FPU control word */ - _STRUCT_FP_STATUS fpu_fsw; /* x87 FPU status word */ - __uint8_t fpu_ftw; /* x87 FPU tag word */ - __uint8_t fpu_rsrv1; /* reserved */ - __uint16_t fpu_fop; /* x87 FPU Opcode */ - - /* x87 FPU Instruction Pointer */ - __uint32_t fpu_ip; /* offset */ - __uint16_t fpu_cs; /* Selector */ - - __uint16_t fpu_rsrv2; /* reserved */ - - /* x87 FPU Instruction Operand(Data) Pointer */ - __uint32_t fpu_dp; /* offset */ - __uint16_t fpu_ds; /* Selector */ - - __uint16_t fpu_rsrv3; /* reserved */ - __uint32_t fpu_mxcsr; /* MXCSR Register state */ - __uint32_t fpu_mxcsrmask; /* MXCSR mask */ - _STRUCT_MMST_REG fpu_stmm0; /* ST0/MM0 */ - _STRUCT_MMST_REG fpu_stmm1; /* ST1/MM1 */ - _STRUCT_MMST_REG fpu_stmm2; /* ST2/MM2 */ - _STRUCT_MMST_REG fpu_stmm3; /* ST3/MM3 */ - _STRUCT_MMST_REG fpu_stmm4; /* ST4/MM4 */ - _STRUCT_MMST_REG fpu_stmm5; /* ST5/MM5 */ - _STRUCT_MMST_REG fpu_stmm6; /* ST6/MM6 */ - _STRUCT_MMST_REG fpu_stmm7; /* ST7/MM7 */ - _STRUCT_XMM_REG fpu_xmm0; /* XMM 0 */ - _STRUCT_XMM_REG fpu_xmm1; /* XMM 1 */ - _STRUCT_XMM_REG fpu_xmm2; /* XMM 2 */ - _STRUCT_XMM_REG fpu_xmm3; /* XMM 3 */ - _STRUCT_XMM_REG fpu_xmm4; /* XMM 4 */ - _STRUCT_XMM_REG fpu_xmm5; /* XMM 5 */ - _STRUCT_XMM_REG fpu_xmm6; /* XMM 6 */ - _STRUCT_XMM_REG fpu_xmm7; /* XMM 7 */ - _STRUCT_XMM_REG fpu_xmm8; /* XMM 8 */ - _STRUCT_XMM_REG fpu_xmm9; /* XMM 9 */ - _STRUCT_XMM_REG fpu_xmm10; /* XMM 10 */ - _STRUCT_XMM_REG fpu_xmm11; /* XMM 11 */ - _STRUCT_XMM_REG fpu_xmm12; /* XMM 12 */ - _STRUCT_XMM_REG fpu_xmm13; /* XMM 13 */ - _STRUCT_XMM_REG fpu_xmm14; /* XMM 14 */ - _STRUCT_XMM_REG fpu_xmm15; /* XMM 15 */ - char fpu_rsrv4[6*16]; /* reserved */ - int fpu_reserved1; - char __avx_reserved1[64]; - _STRUCT_XMM_REG __fpu_ymmh0; /* YMMH 0 */ - _STRUCT_XMM_REG __fpu_ymmh1; /* YMMH 1 */ - _STRUCT_XMM_REG __fpu_ymmh2; /* YMMH 2 */ - _STRUCT_XMM_REG __fpu_ymmh3; /* YMMH 3 */ - _STRUCT_XMM_REG __fpu_ymmh4; /* YMMH 4 */ - _STRUCT_XMM_REG __fpu_ymmh5; /* YMMH 5 */ - _STRUCT_XMM_REG __fpu_ymmh6; /* YMMH 6 */ - _STRUCT_XMM_REG __fpu_ymmh7; /* YMMH 7 */ - _STRUCT_XMM_REG __fpu_ymmh8; /* YMMH 8 */ - _STRUCT_XMM_REG __fpu_ymmh9; /* YMMH 9 */ - _STRUCT_XMM_REG __fpu_ymmh10; /* YMMH 10 */ - _STRUCT_XMM_REG __fpu_ymmh11; /* YMMH 11 */ - _STRUCT_XMM_REG __fpu_ymmh12; /* YMMH 12 */ - _STRUCT_XMM_REG __fpu_ymmh13; /* YMMH 13 */ - _STRUCT_XMM_REG __fpu_ymmh14; /* YMMH 14 */ - _STRUCT_XMM_REG __fpu_ymmh15; /* YMMH 15 */ -}; - -#endif /* !__DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_EXCEPTION_STATE64 struct __darwin_x86_exception_state64 -_STRUCT_X86_EXCEPTION_STATE64 -{ - __uint16_t __trapno; - __uint16_t __cpu; - __uint32_t __err; - __uint64_t __faultvaddr; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_EXCEPTION_STATE64 struct x86_exception_state64 -_STRUCT_X86_EXCEPTION_STATE64 -{ - __uint16_t trapno; - __uint16_t cpu; - __uint32_t err; - __uint64_t faultvaddr; -}; -#endif /* !__DARWIN_UNIX03 */ - -#if __DARWIN_UNIX03 -#define _STRUCT_X86_DEBUG_STATE64 struct __darwin_x86_debug_state64 -_STRUCT_X86_DEBUG_STATE64 -{ - __uint64_t __dr0; - __uint64_t __dr1; - __uint64_t __dr2; - __uint64_t __dr3; - __uint64_t __dr4; - __uint64_t __dr5; - __uint64_t __dr6; - __uint64_t __dr7; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_X86_DEBUG_STATE64 struct x86_debug_state64 -_STRUCT_X86_DEBUG_STATE64 -{ - __uint64_t dr0; - __uint64_t dr1; - __uint64_t dr2; - __uint64_t dr3; - __uint64_t dr4; - __uint64_t dr5; - __uint64_t dr6; - __uint64_t dr7; -}; -#endif /* !__DARWIN_UNIX03 */ - -#endif /* _MACH_I386__STRUCTS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/boolean.h b/idasdk75/ldr/mach-o/h/mach/i386/boolean.h deleted file mode 100644 index ee00ae5..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/boolean.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: boolean.h - * - * Boolean type, for I386. - */ - -#ifndef _MACH_I386_BOOLEAN_H_ -#define _MACH_I386_BOOLEAN_H_ - -#if defined(__x86_64__) && !defined(KERNEL) -typedef unsigned int boolean_t; -#else -typedef int boolean_t; -#endif - -#endif /* _MACH_I386_BOOLEAN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/fp_reg.h b/idasdk75/ldr/mach-o/h/mach/i386/fp_reg.h deleted file mode 100644 index 6451955..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/fp_reg.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1992-1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -#ifndef _I386_FP_SAVE_H_ -#define _I386_FP_SAVE_H_ - - -/* note when allocating this data structure, it must be 16 byte aligned. */ -struct x86_fx_save { - unsigned short fx_control; /* control */ - unsigned short fx_status; /* status */ - unsigned char fx_tag; /* register tags */ - unsigned char fx_bbz1; /* better be zero when calling fxrtstor */ - unsigned short fx_opcode; - unsigned int fx_eip; /* eip instruction */ - unsigned short fx_cs; /* cs instruction */ - unsigned short fx_bbz2; /* better be zero when calling fxrtstor */ - unsigned int fx_dp; /* data address */ - unsigned short fx_ds; /* data segment */ - unsigned short fx_bbz3; /* better be zero when calling fxrtstor */ - unsigned int fx_MXCSR; - unsigned int fx_MXCSR_MASK; - unsigned short fx_reg_word[8][8]; /* STx/MMx registers */ - unsigned short fx_XMM_reg[8][16]; /* XMM0-XMM15 on 64 bit processors */ - /* XMM0-XMM7 on 32 bit processors... unused storage reserved */ - unsigned char fx_reserved[16*6]; /* reserved by intel for future expansion */ -}; - - -/* - * Control register - */ -#define FPC_IE 0x0001 /* enable invalid operation - exception */ -#define FPC_IM FPC_IE -#define FPC_DE 0x0002 /* enable denormalized operation - exception */ -#define FPC_DM FPC_DE -#define FPC_ZE 0x0004 /* enable zero-divide exception */ -#define FPC_ZM FPC_ZE -#define FPC_OE 0x0008 /* enable overflow exception */ -#define FPC_OM FPC_OE -#define FPC_UE 0x0010 /* enable underflow exception */ -#define FPC_PE 0x0020 /* enable precision exception */ -#define FPC_PC 0x0300 /* precision control: */ -#define FPC_PC_24 0x0000 /* 24 bits */ -#define FPC_PC_53 0x0200 /* 53 bits */ -#define FPC_PC_64 0x0300 /* 64 bits */ -#define FPC_RC 0x0c00 /* rounding control: */ -#define FPC_RC_RN 0x0000 /* round to nearest or even */ -#define FPC_RC_RD 0x0400 /* round down */ -#define FPC_RC_RU 0x0800 /* round up */ -#define FPC_RC_CHOP 0x0c00 /* chop */ -#define FPC_IC 0x1000 /* infinity control (obsolete) */ -#define FPC_IC_PROJ 0x0000 /* projective infinity */ -#define FPC_IC_AFF 0x1000 /* affine infinity (std) */ - -/* - * Status register - */ -#define FPS_IE 0x0001 /* invalid operation */ -#define FPS_DE 0x0002 /* denormalized operand */ -#define FPS_ZE 0x0004 /* divide by zero */ -#define FPS_OE 0x0008 /* overflow */ -#define FPS_UE 0x0010 /* underflow */ -#define FPS_PE 0x0020 /* precision */ -#define FPS_SF 0x0040 /* stack flag */ -#define FPS_ES 0x0080 /* error summary */ -#define FPS_C0 0x0100 /* condition code bit 0 */ -#define FPS_C1 0x0200 /* condition code bit 1 */ -#define FPS_C2 0x0400 /* condition code bit 2 */ -#define FPS_TOS 0x3800 /* top-of-stack pointer */ -#define FPS_TOS_SHIFT 11 -#define FPS_C3 0x4000 /* condition code bit 3 */ -#define FPS_BUSY 0x8000 /* FPU busy */ - -/* - * Kind of floating-point support provided by kernel. - */ -#define FP_NO 0 /* no floating point */ -#define FP_SOFT 1 /* software FP emulator */ -#define FP_287 2 /* 80287 */ -#define FP_387 3 /* 80387 or 80486 */ -#define FP_FXSR 4 /* Fast save/restore SIMD Extension */ - -#endif /* _I386_FP_SAVE_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/kern_return.h b/idasdk75/ldr/mach-o/h/mach/i386/kern_return.h deleted file mode 100644 index 9d511e3..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/kern_return.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: kern_return.h - * Author: Avadis Tevanian, Jr., Michael Wayne Young - * Date: 1985 - * - * Machine-dependent kernel return definitions. - */ - -#ifndef _MACH_I386_KERN_RETURN_H_ -#define _MACH_I386_KERN_RETURN_H_ - -#ifndef ASSEMBLER -typedef int kern_return_t; -#endif /* ASSEMBLER */ - -#endif /* _MACH_I386_KERN_RETURN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/thread_state.h b/idasdk75/ldr/mach-o/h/mach/i386/thread_state.h deleted file mode 100644 index 13da50b..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/thread_state.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ - -#ifndef _MACH_I386_THREAD_STATE_H_ -#define _MACH_I386_THREAD_STATE_H_ - -/* Size of maximum exported thread state in words */ -#define I386_THREAD_STATE_MAX (224) /* Size of biggest state possible */ - -#if defined (__i386__) || defined(__x86_64__) -#define THREAD_STATE_MAX I386_THREAD_STATE_MAX -#endif - -#endif /* _MACH_I386_THREAD_STATE_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/thread_status.h b/idasdk75/ldr/mach-o/h/mach/i386/thread_status.h deleted file mode 100644 index b34a1ac..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/thread_status.h +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ -/* - * File: thread_status.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * This file contains the structure definitions for the thread - * state as applied to I386 processors. - */ - -#ifndef _MACH_I386_THREAD_STATUS_H_ -#define _MACH_I386_THREAD_STATUS_H_ - -#include <mach/i386/_structs.h> -#include <mach/message.h> -#include <mach/i386/fp_reg.h> -#include <mach/i386/thread_state.h> -#include <i386/eflags.h> - -/* - * the i386_xxxx form is kept for legacy purposes since these types - * are externally known... eventually they should be deprecated. - * our internal implementation has moved to the following naming convention - * - * x86_xxxx32 names are used to deal with 32 bit states - * x86_xxxx64 names are used to deal with 64 bit states - * x86_xxxx names are used to deal with either 32 or 64 bit states - * via a self-describing mechanism - */ - -/* - * these are the legacy names which should be deprecated in the future - * they are externally known which is the only reason we don't just get - * rid of them - */ -#define i386_THREAD_STATE 1 -#define i386_FLOAT_STATE 2 -#define i386_EXCEPTION_STATE 3 - -/* - * THREAD_STATE_FLAVOR_LIST 0 - * these are the supported flavors - */ -#define x86_THREAD_STATE32 1 -#define x86_FLOAT_STATE32 2 -#define x86_EXCEPTION_STATE32 3 -#define x86_THREAD_STATE64 4 -#define x86_FLOAT_STATE64 5 -#define x86_EXCEPTION_STATE64 6 -#define x86_THREAD_STATE 7 -#define x86_FLOAT_STATE 8 -#define x86_EXCEPTION_STATE 9 -#define x86_DEBUG_STATE32 10 -#define x86_DEBUG_STATE64 11 -#define x86_DEBUG_STATE 12 -#define THREAD_STATE_NONE 13 -/* 15 and 16 are used for the internal x86_SAVED_STATE flavours */ -#define x86_AVX_STATE32 16 -#define x86_AVX_STATE64 17 - - -/* - * Largest state on this machine: - * (be sure mach/machine/thread_state.h matches!) - */ -#define THREAD_MACHINE_STATE_MAX THREAD_STATE_MAX - -/* - * VALID_THREAD_STATE_FLAVOR is a platform specific macro that when passed - * an exception flavor will return if that is a defined flavor for that - * platform. The macro must be manually updated to include all of the valid - * exception flavors as defined above. - */ -#define VALID_THREAD_STATE_FLAVOR(x) \ - ((x == x86_THREAD_STATE32) || \ - (x == x86_FLOAT_STATE32) || \ - (x == x86_EXCEPTION_STATE32) || \ - (x == x86_DEBUG_STATE32) || \ - (x == x86_THREAD_STATE64) || \ - (x == x86_FLOAT_STATE64) || \ - (x == x86_EXCEPTION_STATE64) || \ - (x == x86_DEBUG_STATE64) || \ - (x == x86_THREAD_STATE) || \ - (x == x86_FLOAT_STATE) || \ - (x == x86_EXCEPTION_STATE) || \ - (x == x86_DEBUG_STATE) || \ - (x == x86_AVX_STATE32) || \ - (x == x86_AVX_STATE64) || \ - (x == THREAD_STATE_NONE)) - -struct x86_state_hdr { - int flavor; - int count; -}; -typedef struct x86_state_hdr x86_state_hdr_t; - -/* - * Default segment register values. - */ - -#define USER_CODE_SELECTOR 0x0017 -#define USER_DATA_SELECTOR 0x001f -#define KERN_CODE_SELECTOR 0x0008 -#define KERN_DATA_SELECTOR 0x0010 - -/* - * to be deprecated in the future - */ -typedef _STRUCT_X86_THREAD_STATE32 i386_thread_state_t; -#define i386_THREAD_STATE_COUNT ((mach_msg_type_number_t) \ - ( sizeof (i386_thread_state_t) / sizeof (int) )) - -typedef _STRUCT_X86_THREAD_STATE32 x86_thread_state32_t; -#define x86_THREAD_STATE32_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_thread_state32_t) / sizeof (int) )) - -/* - * to be deprecated in the future - */ -typedef _STRUCT_X86_FLOAT_STATE32 i386_float_state_t; -#define i386_FLOAT_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(i386_float_state_t)/sizeof(unsigned int))) - -typedef _STRUCT_X86_FLOAT_STATE32 x86_float_state32_t; -#define x86_FLOAT_STATE32_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_float_state32_t)/sizeof(unsigned int))) - -typedef _STRUCT_X86_AVX_STATE32 x86_avx_state32_t; -#define x86_AVX_STATE32_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_avx_state32_t)/sizeof(unsigned int))) - -/* - * to be deprecated in the future - */ -typedef _STRUCT_X86_EXCEPTION_STATE32 i386_exception_state_t; -#define i386_EXCEPTION_STATE_COUNT ((mach_msg_type_number_t) \ - ( sizeof (i386_exception_state_t) / sizeof (int) )) - -typedef _STRUCT_X86_EXCEPTION_STATE32 x86_exception_state32_t; -#define x86_EXCEPTION_STATE32_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_exception_state32_t) / sizeof (int) )) - -#define I386_EXCEPTION_STATE_COUNT i386_EXCEPTION_STATE_COUNT - -typedef _STRUCT_X86_DEBUG_STATE32 x86_debug_state32_t; -#define x86_DEBUG_STATE32_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_debug_state32_t) / sizeof (int) )) - -#define X86_DEBUG_STATE32_COUNT x86_DEBUG_STATE32_COUNT - -typedef _STRUCT_X86_THREAD_STATE64 x86_thread_state64_t; -#define x86_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_thread_state64_t) / sizeof (int) )) - -typedef _STRUCT_X86_FLOAT_STATE64 x86_float_state64_t; -#define x86_FLOAT_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_float_state64_t)/sizeof(unsigned int))) - -typedef _STRUCT_X86_AVX_STATE64 x86_avx_state64_t; -#define x86_AVX_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_avx_state64_t)/sizeof(unsigned int))) - -typedef _STRUCT_X86_EXCEPTION_STATE64 x86_exception_state64_t; -#define x86_EXCEPTION_STATE64_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_exception_state64_t) / sizeof (int) )) - -#define X86_EXCEPTION_STATE64_COUNT x86_EXCEPTION_STATE64_COUNT - -typedef _STRUCT_X86_DEBUG_STATE64 x86_debug_state64_t; -#define x86_DEBUG_STATE64_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_debug_state64_t) / sizeof (int) )) - -#define X86_DEBUG_STATE64_COUNT x86_DEBUG_STATE64_COUNT - -/* - * Combined thread, float and exception states - */ -struct x86_thread_state { - x86_state_hdr_t tsh; - union { - x86_thread_state32_t ts32; - x86_thread_state64_t ts64; - } uts; -}; - -struct x86_float_state { - x86_state_hdr_t fsh; - union { - x86_float_state32_t fs32; - x86_float_state64_t fs64; - } ufs; -}; - -struct x86_exception_state { - x86_state_hdr_t esh; - union { - x86_exception_state32_t es32; - x86_exception_state64_t es64; - } ues; -}; - -struct x86_debug_state { - x86_state_hdr_t dsh; - union { - x86_debug_state32_t ds32; - x86_debug_state64_t ds64; - } uds; -}; - -typedef struct x86_thread_state x86_thread_state_t; -#define x86_THREAD_STATE_COUNT ((mach_msg_type_number_t) \ - ( sizeof (x86_thread_state_t) / sizeof (int) )) - -typedef struct x86_float_state x86_float_state_t; -#define x86_FLOAT_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_float_state_t)/sizeof(unsigned int))) - -typedef struct x86_exception_state x86_exception_state_t; -#define x86_EXCEPTION_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_exception_state_t)/sizeof(unsigned int))) - -typedef struct x86_debug_state x86_debug_state_t; -#define x86_DEBUG_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(x86_debug_state_t)/sizeof(unsigned int))) - -/* - * Machine-independent way for servers and Mach's exception mechanism to - * choose the most efficient state flavor for exception RPC's: - */ -#define MACHINE_THREAD_STATE x86_THREAD_STATE -#define MACHINE_THREAD_STATE_COUNT x86_THREAD_STATE_COUNT - -/* - * when reloading the segment registers on - * a return out of the kernel, we may take - * a GeneralProtection or SegmentNotPresent - * fault if one or more of the segment - * registers in the saved state was improperly - * specified via an x86_THREAD_STATE32 call - * the frame we push on top of the existing - * save area looks like this... we need to - * carry this as part of the save area - * in case we get hit so that we have a big - * enough stack - */ -struct x86_seg_load_fault32 { - uint16_t trapno; - uint16_t cpu; - uint32_t err; - uint32_t eip; - uint32_t cs; - uint32_t efl; -}; - - -#endif /* _MACH_I386_THREAD_STATUS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/vm_param.h b/idasdk75/ldr/mach-o/h/mach/i386/vm_param.h deleted file mode 100644 index 0651e85..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/vm_param.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ - -/* - * Copyright (c) 1994 The University of Utah and - * the Computer Systems Laboratory at the University of Utah (CSL). - * All rights reserved. - * - * Permission to use, copy, modify and distribute this software is hereby - * granted provided that (1) source code retains these copyright, permission, - * and disclaimer notices, and (2) redistributions including binaries - * reproduce the notices in supporting documentation, and (3) all advertising - * materials mentioning features or use of this software display the following - * acknowledgement: ``This product includes software developed by the - * Computer Systems Laboratory at the University of Utah.'' - * - * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS - * IS" CONDITION. THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF - * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * CSL requests users of this software to return to csl-dist@cs.utah.edu any - * improvements that they make and grant CSL redistribution rights. - * - */ - -/* - * File: vm_param.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * I386 machine dependent virtual memory parameters. - * Most of the declarations are preceeded by I386_ (or i386_) - * which is OK because only I386 specific code will be using - * them. - */ - -#ifndef _MACH_I386_VM_PARAM_H_ -#define _MACH_I386_VM_PARAM_H_ - -#define BYTE_SIZE 8 /* byte size in bits */ - -#define I386_PGBYTES 4096 /* bytes per 80386 page */ -#define I386_PGSHIFT 12 /* bitshift for pages */ - -#define PAGE_SIZE I386_PGBYTES -#define PAGE_SHIFT I386_PGSHIFT -#define PAGE_MASK (PAGE_SIZE - 1) - -#define I386_LPGBYTES 2*1024*1024 /* bytes per large page */ -#define I386_LPGSHIFT 21 /* bitshift for large pages */ -#define I386_LPGMASK (I386_LPGBYTES-1) - -/* - * Convert bytes to pages and convert pages to bytes. - * No rounding is used. - */ - -#define i386_btop(x) ((ppnum_t)((x) >> I386_PGSHIFT)) -#define machine_btop(x) i386_btop(x) -#define i386_ptob(x) (((pmap_paddr_t)(x)) << I386_PGSHIFT) - -/* - * Round off or truncate to the nearest page. These will work - * for either addresses or counts. (i.e. 1 byte rounds to 1 page - * bytes. - */ - -#define i386_round_page(x) ((((pmap_paddr_t)(x)) + I386_PGBYTES - 1) & \ - ~(I386_PGBYTES-1)) -#define i386_trunc_page(x) (((pmap_paddr_t)(x)) & ~(I386_PGBYTES-1)) - - - -#define VM_MIN_ADDRESS64 ((user_addr_t) 0x0000000000000000ULL) -/* - * default top of user stack... it grows down from here - */ -#define VM_USRSTACK64 ((user_addr_t) 0x00007FFF5FC00000ULL) -#define VM_DYLD64 ((user_addr_t) 0x00007FFF5FC00000ULL) -#define VM_LIB64_SHR_DATA ((user_addr_t) 0x00007FFF60000000ULL) -#define VM_LIB64_SHR_TEXT ((user_addr_t) 0x00007FFF80000000ULL) -/* - * the end of the usable user address space , for now about 47 bits. - * the 64 bit commpage is past the end of this - */ -#define VM_MAX_PAGE_ADDRESS ((user_addr_t) 0x00007FFFFFE00000ULL) -/* - * canonical end of user address space for limits checking - */ -#define VM_MAX_USER_PAGE_ADDRESS ((user_addr_t)0x00007FFFFFFFF000ULL) - - -/* system-wide values */ -#define MACH_VM_MIN_ADDRESS ((mach_vm_offset_t) 0) -#define MACH_VM_MAX_ADDRESS ((mach_vm_offset_t) VM_MAX_PAGE_ADDRESS) - -/* process-relative values (all 32-bit legacy only for now) */ -#define VM_MIN_ADDRESS ((vm_offset_t) 0) -#define VM_USRSTACK32 ((vm_offset_t) 0xC0000000) -#define VM_MAX_ADDRESS ((vm_offset_t) 0xFFE00000) - - - -#endif /* _MACH_I386_VM_PARAM_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/i386/vm_types.h b/idasdk75/ldr/mach-o/h/mach/i386/vm_types.h deleted file mode 100644 index b61be1a..0000000 --- a/idasdk75/ldr/mach-o/h/mach/i386/vm_types.h +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: vm_types.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * Header file for VM data types. I386 version. - */ - -#ifndef _MACH_I386_VM_TYPES_H_ -#define _MACH_I386_VM_TYPES_H_ - -#ifndef ASSEMBLER - -#include <i386/_types.h> -#include <mach/i386/vm_param.h> -#include <stdint.h> - -/* - * natural_t and integer_t are Mach's legacy types for machine- - * independent integer types (unsigned, and signed, respectively). - * Their original purpose was to define other types in a machine/ - * compiler independent way. - * - * They also had an implicit "same size as pointer" characteristic - * to them (i.e. Mach's traditional types are very ILP32 or ILP64 - * centric). We support x86 ABIs that do not follow either of - * these models (specifically LP64). Therefore, we had to make a - * choice between making these types scale with pointers or stay - * tied to integers. Because their use is predominantly tied to - * to the size of an integer, we are keeping that association and - * breaking free from pointer size guarantees. - * - * New use of these types is discouraged. - */ -typedef __darwin_natural_t natural_t; -typedef int integer_t; - -/* - * A vm_offset_t is a type-neutral pointer, - * e.g. an offset into a virtual memory space. - */ -#ifdef __LP64__ -typedef uintptr_t vm_offset_t; -#else /* __LP64__ */ -typedef natural_t vm_offset_t; -#endif /* __LP64__ */ - -/* - * A vm_size_t is the proper type for e.g. - * expressing the difference between two - * vm_offset_t entities. - */ -#ifdef __LP64__ -typedef uintptr_t vm_size_t; -#else /* __LP64__ */ -typedef natural_t vm_size_t; -#endif /* __LP64__ */ - -/* - * This new type is independent of a particular vm map's - * implementation size - and represents appropriate types - * for all possible maps. This is used for interfaces - * where the size of the map is not known - or we don't - * want to have to distinguish. - */ -typedef uint64_t mach_vm_address_t; -typedef uint64_t mach_vm_offset_t; -typedef uint64_t mach_vm_size_t; - -typedef uint64_t vm_map_offset_t; -typedef uint64_t vm_map_address_t; -typedef uint64_t vm_map_size_t; - -typedef mach_vm_address_t mach_port_context_t; - -#endif /* ASSEMBLER */ - -/* - * If composing messages by hand (please do not) - */ -#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32 - -#endif /* _MACH_I386_VM_TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/kern_return.h b/idasdk75/ldr/mach-o/h/mach/kern_return.h deleted file mode 100644 index 92daed0..0000000 --- a/idasdk75/ldr/mach-o/h/mach/kern_return.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ -/* - * File: h/kern_return.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * Kernel return codes. - * - */ - -#ifndef _MACH_KERN_RETURN_H_ -#define _MACH_KERN_RETURN_H_ - -#include <mach/machine/kern_return.h> - -#define KERN_SUCCESS 0 - -#define KERN_INVALID_ADDRESS 1 - /* Specified address is not currently valid. - */ - -#define KERN_PROTECTION_FAILURE 2 - /* Specified memory is valid, but does not permit the - * required forms of access. - */ - -#define KERN_NO_SPACE 3 - /* The address range specified is already in use, or - * no address range of the size specified could be - * found. - */ - -#define KERN_INVALID_ARGUMENT 4 - /* The function requested was not applicable to this - * type of argument, or an argument is invalid - */ - -#define KERN_FAILURE 5 - /* The function could not be performed. A catch-all. - */ - -#define KERN_RESOURCE_SHORTAGE 6 - /* A system resource could not be allocated to fulfill - * this request. This failure may not be permanent. - */ - -#define KERN_NOT_RECEIVER 7 - /* The task in question does not hold receive rights - * for the port argument. - */ - -#define KERN_NO_ACCESS 8 - /* Bogus access restriction. - */ - -#define KERN_MEMORY_FAILURE 9 - /* During a page fault, the target address refers to a - * memory object that has been destroyed. This - * failure is permanent. - */ - -#define KERN_MEMORY_ERROR 10 - /* During a page fault, the memory object indicated - * that the data could not be returned. This failure - * may be temporary; future attempts to access this - * same data may succeed, as defined by the memory - * object. - */ - -#define KERN_ALREADY_IN_SET 11 - /* The receive right is already a member of the portset. - */ - -#define KERN_NOT_IN_SET 12 - /* The receive right is not a member of a port set. - */ - -#define KERN_NAME_EXISTS 13 - /* The name already denotes a right in the task. - */ - -#define KERN_ABORTED 14 - /* The operation was aborted. Ipc code will - * catch this and reflect it as a message error. - */ - -#define KERN_INVALID_NAME 15 - /* The name doesn't denote a right in the task. - */ - -#define KERN_INVALID_TASK 16 - /* Target task isn't an active task. - */ - -#define KERN_INVALID_RIGHT 17 - /* The name denotes a right, but not an appropriate right. - */ - -#define KERN_INVALID_VALUE 18 - /* A blatant range error. - */ - -#define KERN_UREFS_OVERFLOW 19 - /* Operation would overflow limit on user-references. - */ - -#define KERN_INVALID_CAPABILITY 20 - /* The supplied (port) capability is improper. - */ - -#define KERN_RIGHT_EXISTS 21 - /* The task already has send or receive rights - * for the port under another name. - */ - -#define KERN_INVALID_HOST 22 - /* Target host isn't actually a host. - */ - -#define KERN_MEMORY_PRESENT 23 - /* An attempt was made to supply "precious" data - * for memory that is already present in a - * memory object. - */ - -#define KERN_MEMORY_DATA_MOVED 24 - /* A page was requested of a memory manager via - * memory_object_data_request for an object using - * a MEMORY_OBJECT_COPY_CALL strategy, with the - * VM_PROT_WANTS_COPY flag being used to specify - * that the page desired is for a copy of the - * object, and the memory manager has detected - * the page was pushed into a copy of the object - * while the kernel was walking the shadow chain - * from the copy to the object. This error code - * is delivered via memory_object_data_error - * and is handled by the kernel (it forces the - * kernel to restart the fault). It will not be - * seen by users. - */ - -#define KERN_MEMORY_RESTART_COPY 25 - /* A strategic copy was attempted of an object - * upon which a quicker copy is now possible. - * The caller should retry the copy using - * vm_object_copy_quickly. This error code - * is seen only by the kernel. - */ - -#define KERN_INVALID_PROCESSOR_SET 26 - /* An argument applied to assert processor set privilege - * was not a processor set control port. - */ - -#define KERN_POLICY_LIMIT 27 - /* The specified scheduling attributes exceed the thread's - * limits. - */ - -#define KERN_INVALID_POLICY 28 - /* The specified scheduling policy is not currently - * enabled for the processor set. - */ - -#define KERN_INVALID_OBJECT 29 - /* The external memory manager failed to initialize the - * memory object. - */ - -#define KERN_ALREADY_WAITING 30 - /* A thread is attempting to wait for an event for which - * there is already a waiting thread. - */ - -#define KERN_DEFAULT_SET 31 - /* An attempt was made to destroy the default processor - * set. - */ - -#define KERN_EXCEPTION_PROTECTED 32 - /* An attempt was made to fetch an exception port that is - * protected, or to abort a thread while processing a - * protected exception. - */ - -#define KERN_INVALID_LEDGER 33 - /* A ledger was required but not supplied. - */ - -#define KERN_INVALID_MEMORY_CONTROL 34 - /* The port was not a memory cache control port. - */ - -#define KERN_INVALID_SECURITY 35 - /* An argument supplied to assert security privilege - * was not a host security port. - */ - -#define KERN_NOT_DEPRESSED 36 - /* thread_depress_abort was called on a thread which - * was not currently depressed. - */ - -#define KERN_TERMINATED 37 - /* Object has been terminated and is no longer available - */ - -#define KERN_LOCK_SET_DESTROYED 38 - /* Lock set has been destroyed and is no longer available. - */ - -#define KERN_LOCK_UNSTABLE 39 - /* The thread holding the lock terminated before releasing - * the lock - */ - -#define KERN_LOCK_OWNED 40 - /* The lock is already owned by another thread - */ - -#define KERN_LOCK_OWNED_SELF 41 - /* The lock is already owned by the calling thread - */ - -#define KERN_SEMAPHORE_DESTROYED 42 - /* Semaphore has been destroyed and is no longer available. - */ - -#define KERN_RPC_SERVER_TERMINATED 43 - /* Return from RPC indicating the target server was - * terminated before it successfully replied - */ - -#define KERN_RPC_TERMINATE_ORPHAN 44 - /* Terminate an orphaned activation. - */ - -#define KERN_RPC_CONTINUE_ORPHAN 45 - /* Allow an orphaned activation to continue executing. - */ - -#define KERN_NOT_SUPPORTED 46 - /* Empty thread activation (No thread linked to it) - */ - -#define KERN_NODE_DOWN 47 - /* Remote node down or inaccessible. - */ - -#define KERN_NOT_WAITING 48 - /* A signalled thread was not actually waiting. */ - -#define KERN_OPERATION_TIMED_OUT 49 - /* Some thread-oriented operation (semaphore_wait) timed out - */ - -#define KERN_CODESIGN_ERROR 50 - /* During a page fault, indicates that the page was rejected - * as a result of a signature check. - */ - -#define KERN_RETURN_MAX 0x100 - /* Maximum return value allowable - */ - -#endif /* _MACH_KERN_RETURN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/kmod.h b/idasdk75/ldr/mach-o/h/mach/kmod.h deleted file mode 100644 index 3b3c97a..0000000 --- a/idasdk75/ldr/mach-o/h/mach/kmod.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce - * support for mandatory and extensible security protections. This notice - * is included in support of clause 2.2 (b) of the Apple Public License, - * Version 2.0. - */ - -#ifndef _MACH_KMOD_H_ -#define _MACH_KMOD_H_ - -#include <mach/kern_return.h> -#include <mach/vm_types.h> -//#include <mach/mach_types.h> - -#include <sys/cdefs.h> - -__BEGIN_DECLS - -#if PRAGMA_MARK -#pragma mark Basic macros & typedefs -#endif -/*********************************************************************** -* Basic macros & typedefs -***********************************************************************/ -#define KMOD_MAX_NAME 64 - -#define KMOD_RETURN_SUCCESS KERN_SUCCESS -#define KMOD_RETURN_FAILURE KERN_FAILURE - -typedef int kmod_t; - -struct kmod_info; -typedef kern_return_t kmod_start_func_t(struct kmod_info * ki, void * data); -typedef kern_return_t kmod_stop_func_t(struct kmod_info * ki, void * data); - -#if PRAGMA_MARK -#pragma mark Structure definitions -#endif -/*********************************************************************** -* Structure definitions -* -* All structures must be #pragma pack(4). -***********************************************************************/ -#pragma pack(4) - -/* Run-time struct only; never saved to a file */ -typedef struct kmod_reference { - struct kmod_reference * next; - struct kmod_info * info; -} kmod_reference_t; - -/*********************************************************************** -* Warning: Any changes to the kmod_info structure affect the -* KMOD_..._DECL macros below. -***********************************************************************/ - -/* The kmod_info_t structure is only safe to use inside the running - * kernel. If you need to work with a kmod_info_t structure outside - * the kernel, please use the compatibility definitions below. - */ -typedef struct kmod_info { - struct kmod_info * next; - int32_t info_version; // version of this structure - uint32_t id; - char name[KMOD_MAX_NAME]; - char version[KMOD_MAX_NAME]; - int32_t reference_count; // # linkage refs to this - kmod_reference_t * reference_list; // who this refs (links on) - vm_address_t address; // starting address - vm_size_t size; // total size - vm_size_t hdr_size; // unwired hdr size - kmod_start_func_t * start; - kmod_stop_func_t * stop; -} kmod_info_t; - -/* A compatibility definition of kmod_info_t for 32-bit kexts. - */ -typedef struct kmod_info_32_v1 { - uint32_t next_addr; - int32_t info_version; - uint32_t id; - uint8_t name[KMOD_MAX_NAME]; - uint8_t version[KMOD_MAX_NAME]; - int32_t reference_count; - uint32_t reference_list_addr; - uint32_t address; - uint32_t size; - uint32_t hdr_size; - uint32_t start_addr; - uint32_t stop_addr; -} kmod_info_32_v1_t; - -/* A compatibility definition of kmod_info_t for 64-bit kexts. - */ -typedef struct kmod_info_64_v1 { - uint64_t next_addr; - int32_t info_version; - uint32_t id; - uint8_t name[KMOD_MAX_NAME]; - uint8_t version[KMOD_MAX_NAME]; - int32_t reference_count; - uint64_t reference_list_addr; - uint64_t address; - uint64_t size; - uint64_t hdr_size; - uint64_t start_addr; - uint64_t stop_addr; -} kmod_info_64_v1_t; - -#pragma pack() - -#if PRAGMA_MARK -#pragma mark Kmod structure declaration macros -#endif -/*********************************************************************** -* Kmod structure declaration macros -***********************************************************************/ -#define KMOD_INFO_NAME kmod_info -#define KMOD_INFO_VERSION 1 - -#define KMOD_DECL(name, version) \ - static kmod_start_func_t name ## _module_start; \ - static kmod_stop_func_t name ## _module_stop; \ - kmod_info_t KMOD_INFO_NAME = { 0, KMOD_INFO_VERSION, -1U, \ - { #name }, { version }, -1, 0, 0, 0, 0, \ - name ## _module_start, \ - name ## _module_stop }; - -#define KMOD_EXPLICIT_DECL(name, version, start, stop) \ - kmod_info_t KMOD_INFO_NAME = { 0, KMOD_INFO_VERSION, -1U, \ - { #name }, { version }, -1, 0, 0, 0, 0, \ - start, stop }; - -#if PRAGMA_MARK -#pragma mark Kernel private declarations -#endif -/*********************************************************************** -* Kernel private declarations. -***********************************************************************/ -#ifdef KERNEL_PRIVATE - -/* Implementation now in libkern/OSKextLib.cpp. */ -extern void kmod_panic_dump(vm_offset_t * addr, unsigned int dump_cnt); - -#endif /* KERNEL_PRIVATE */ - - -#if PRAGMA_MARK -#pragma mark Obsolete kmod stuff -#endif -/*********************************************************************** -* These 3 should be dropped but they're referenced by MIG declarations. -***********************************************************************/ -typedef void * kmod_args_t; -typedef int kmod_control_flavor_t; -typedef kmod_info_t * kmod_info_array_t; - -__END_DECLS - -#endif /* _MACH_KMOD_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/machine.h b/idasdk75/ldr/mach-o/h/mach/machine.h deleted file mode 100644 index 8543f2e..0000000 --- a/idasdk75/ldr/mach-o/h/mach/machine.h +++ /dev/null @@ -1,464 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* File: machine.h - * Author: Avadis Tevanian, Jr. - * Date: 1986 - * - * Machine independent machine abstraction. - */ - -#ifndef _MACH_MACHINE_H_ -#define _MACH_MACHINE_H_ - -#include <stdint.h> -#include <mach/machine/vm_types.h> -#include <mach/boolean.h> - -typedef integer_t cpu_type_t; -typedef integer_t cpu_subtype_t; -typedef integer_t cpu_threadtype_t; - -#define CPU_STATE_MAX 4 - -#define CPU_STATE_USER 0 -#define CPU_STATE_SYSTEM 1 -#define CPU_STATE_IDLE 2 -#define CPU_STATE_NICE 3 - - - -/* - * Capability bits used in the definition of cpu_type. - */ -#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */ -#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */ -#define CPU_ARCH_ABI64_32 0x02000000 /* ABI for 64-bit hardware with 32-bit types; LP32 */ -#define CPU_ARCH_ABI64_MASK 0x03000000 - -/* - * Machine types known by all. - */ - -#define CPU_TYPE_ANY ((cpu_type_t) -1) - -#define CPU_TYPE_VAX ((cpu_type_t) 1) -#define CPU_TYPE_ROMP ((cpu_type_t) 2) -#define CPU_TYPE_NS32032 ((cpu_type_t) 4) -#define CPU_TYPE_NS32332 ((cpu_type_t) 5) -#define CPU_TYPE_MC680x0 ((cpu_type_t) 6) -#define CPU_TYPE_X86 ((cpu_type_t) 7) -#define CPU_TYPE_I386 CPU_TYPE_X86 /* compatibility */ -#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64) - -#define CPU_TYPE_MIPS ((cpu_type_t) 8) -#define CPU_TYPE_NS32532 ((cpu_type_t) 9) -#define CPU_TYPE_MC98000 ((cpu_type_t) 10) -#define CPU_TYPE_HPPA ((cpu_type_t) 11) -#define CPU_TYPE_ARM ((cpu_type_t) 12) -#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) -#define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32) -#define CPU_TYPE_MC88000 ((cpu_type_t) 13) -#define CPU_TYPE_SPARC ((cpu_type_t) 14) -#define CPU_TYPE_I860 ((cpu_type_t) 15) // big-endian -#define CPU_TYPE_I860_LITTLE ((cpu_type_t) 16) // little-endian -#define CPU_TYPE_ALPHA ((cpu_type_t) 16) -#define CPU_TYPE_RS6000 ((cpu_type_t) 17) -#define CPU_TYPE_POWERPC ((cpu_type_t) 18) -#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64) -#define CPU_TYPE_VEO ((cpu_type_t) 255) - -/* - * Machine subtypes (these are defined here, instead of in a machine - * dependent directory, so that any program can get all definitions - * regardless of where is it compiled). - */ - -/* - * Capability bits used in the definition of cpu_subtype. - */ -#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */ -#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */ - - -/* - * Object files that are hand-crafted to run on any - * implementation of an architecture are tagged with - * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as - * the "ALL" subtype of an architecture except that it allows us - * to easily find object files that may need to be modified - * whenever a new implementation of an architecture comes out. - * - * It is the responsibility of the implementor to make sure the - * software handles unsupported implementations elegantly. - */ -#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1) -#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1) - -/* - * Machine threadtypes. - * This is none - not defined - for most machine types/subtypes. - */ -#define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0) - -/* - * VAX subtypes (these do *not* necessary conform to the actual cpu - * ID assigned by DEC available via the SID register). - */ - -#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4) -#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6) -#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7) -#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8) -#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9) -#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10) -#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11) -#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12) - -/* - * ROMP subtypes. - */ - -#define CPU_SUBTYPE_RT_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_RT_PC ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_RT_APC ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_RT_135 ((cpu_subtype_t) 3) - -/* - * 32032/32332/32532 subtypes. - */ - -#define CPU_SUBTYPE_MMAX_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MMAX_DPC ((cpu_subtype_t) 1) /* 032 CPU */ -#define CPU_SUBTYPE_SQT ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_MMAX_APC_FPU ((cpu_subtype_t) 3) /* 32081 FPU */ -#define CPU_SUBTYPE_MMAX_APC_FPA ((cpu_subtype_t) 4) /* Weitek FPA */ -#define CPU_SUBTYPE_MMAX_XPC ((cpu_subtype_t) 5) /* 532 CPU */ - -/* - * Mips subtypes. - */ - -#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) - -/* - * 680x0 subtypes - * - * The subtype definitions here are unusual for historical reasons. - * NeXT used to consider 68030 code as generic 68000 code. For - * backwards compatability: - * - * CPU_SUBTYPE_MC68030 symbol has been preserved for source code - * compatability. - * - * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same - * subtype as CPU_SUBTYPE_MC68030 for binary comatability. - * - * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object - * files to be tagged as containing 68030-specific instructions. - */ - -#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */ -#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3) - -/* - * I386 subtypes - */ - -#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4)) - -#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0) -#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0) -#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0) -#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) // 8 << 4 = 128 -#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0) -#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0) -#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1) -#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3) -#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5) -#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6) -#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7) -#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0) -#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1) -#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2) -#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0) -#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0) -#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1) -#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0) -#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1) -#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0) -#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1) - -#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15) -#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15 - -#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4) -#define CPU_SUBTYPE_INTEL_MODEL_ALL 0 - -/* - * X86 subtypes. - */ - -#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3) -#define CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3) -#define CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4) -#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) - - -#define CPU_THREADTYPE_INTEL_HTT ((cpu_threadtype_t) 1) - -/* - * Mips subtypes. - */ - -#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) /* pmax */ -#define CPU_SUBTYPE_MIPS_R2000 ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_MIPS_R3000a ((cpu_subtype_t) 6) /* 3max */ -#define CPU_SUBTYPE_MIPS_R3000 ((cpu_subtype_t) 7) - -/* - * MC98000 (PowerPC) subtypes - */ -#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1) - -/* - * HPPA subtypes for Hewlett-Packard HP-PA family of - * risc processors. Port by NeXT to 700 series. - */ - -#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */ -#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1) - -/* - * MC88000 subtypes. - */ -#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2) - -/* - * SPARC subtypes - */ -#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0) - -/* - * I860 subtypes - */ -#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1) - -/* - * I860 subtypes for NeXT-internal backwards compatability. - * These constants will be going away. DO NOT USE THEM!!! - */ -#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1) - -/* - * I860_LITTLE subtypes - */ -#define CPU_SUBTYPE_I860_LITTLE_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_I860_LITTLE ((cpu_subtype_t) 1) - -/* - * RS6000 subtypes - */ -#define CPU_SUBTYPE_RS6000_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_RS6000 ((cpu_subtype_t) 1) - -/* - * Sun4 subtypes - port done at CMU - */ -#define CPU_SUBTYPE_SUN4_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_SUN4_260 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_SUN4_110 ((cpu_subtype_t) 2) - -#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0) - -/* - * PowerPC subtypes - */ -#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4) -#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6) -#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7) -#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8) -#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9) -#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10) -#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11) -#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100) - -/* - * ARM subtypes - */ -#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_ARM_A500_ARCH ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_ARM_A500 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_ARM_A440 ((cpu_subtype_t) 3) -#define CPU_SUBTYPE_ARM_M4 ((cpu_subtype_t) 4) -#define CPU_SUBTYPE_ARM_A680 ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5) -#define CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6) -#define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7) -#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8) -#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) /* ARMv7-A and ARMv7-R */ -#define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) /* Cortex A9 */ -#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) /* Swift */ -#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12) /* Kirkwood40 */ -#define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13) -#define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) /* Not meant to be run under xnu */ -#define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) /* Not meant to be run under xnu */ -#define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) /* Not meant to be run under xnu */ -#define CPU_SUBTYPE_ARM_V8M ((cpu_subtype_t) 17) /* Not meant to be run under xnu */ - -/* - * ARM64 subtypes - */ -#define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2) - -/* CPU subtype feature flags for ptrauth on arm64e platforms */ -#define CPU_SUBTYPE_ARM64_PTR_AUTH_MASK 0x0f000000 -#define CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(x) (((x) & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) >> 24) - -/* - * ARM64_32 subtypes - */ -#define CPU_SUBTYPE_ARM64_32_ALL ((cpu_subtype_t) 0) -#define CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t) 1) - - -/* - * VEO subtypes - * Note: the CPU_SUBTYPE_VEO_ALL will likely change over time to be defined as - * one of the specific subtypes. - */ -#define CPU_SUBTYPE_VEO_1 ((cpu_subtype_t) 1) -#define CPU_SUBTYPE_VEO_2 ((cpu_subtype_t) 2) -#define CPU_SUBTYPE_VEO_ALL CPU_SUBTYPE_VEO_2 - -/* - * CPU families (sysctl hw.cpufamily) - * - * These are meant to identify the CPU's marketing name - an - * application can map these to (possibly) localized strings. - * NB: the encodings of the CPU families are intentionally arbitrary. - * There is no ordering, and you should never try to deduce whether - * or not some feature is available based on the family. - * Use feature flags (eg, hw.optional.altivec) to test for optional - * functionality. - */ -#define CPUFAMILY_UNKNOWN 0 -#define CPUFAMILY_POWERPC_G3 0xcee41549 -#define CPUFAMILY_POWERPC_G4 0x77c184ae -#define CPUFAMILY_POWERPC_G5 0xed76d8aa -#define CPUFAMILY_INTEL_6_13 0xaa33392b -#define CPUFAMILY_INTEL_YONAH 0x73d67300 -#define CPUFAMILY_INTEL_MEROM 0x426f69ef -#define CPUFAMILY_INTEL_PENRYN 0x78ea4fbc -#define CPUFAMILY_INTEL_NEHALEM 0x6b5a4cd2 -#define CPUFAMILY_INTEL_WESTMERE 0x573b5eec -#define CPUFAMILY_INTEL_SANDYBRIDGE 0x5490b78c -#define CPUFAMILY_INTEL_IVYBRIDGE 0x1f65e835 -#define CPUFAMILY_INTEL_HASWELL 0x10b282dc -#define CPUFAMILY_INTEL_BROADWELL 0x582ed09c -#define CPUFAMILY_INTEL_SKYLAKE 0x37fc219f -#define CPUFAMILY_INTEL_KABYLAKE 0x0f817246 -#define CPUFAMILY_ARM_9 0xe73283ae -#define CPUFAMILY_ARM_11 0x8ff620d8 -#define CPUFAMILY_ARM_XSCALE 0x53b005f5 -#define CPUFAMILY_ARM_12 0xbd1b0ae9 -#define CPUFAMILY_ARM_13 0x0cc90e64 -#define CPUFAMILY_ARM_14 0x96077ef1 -#define CPUFAMILY_ARM_15 0xa8511bca -#define CPUFAMILY_ARM_SWIFT 0x1e2d6381 -#define CPUFAMILY_ARM_CYCLONE 0x37a09642 -#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e -#define CPUFAMILY_ARM_TWISTER 0x92fb37c8 -#define CPUFAMILY_ARM_HURRICANE 0x67ceee93 -#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6 -#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f -#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2 - -/* The following synonyms are deprecated: */ -#define CPUFAMILY_INTEL_6_14 CPUFAMILY_INTEL_YONAH -#define CPUFAMILY_INTEL_6_15 CPUFAMILY_INTEL_MEROM -#define CPUFAMILY_INTEL_6_23 CPUFAMILY_INTEL_PENRYN -#define CPUFAMILY_INTEL_6_26 CPUFAMILY_INTEL_NEHALEM - -#define CPUFAMILY_INTEL_CORE CPUFAMILY_INTEL_YONAH -#define CPUFAMILY_INTEL_CORE2 CPUFAMILY_INTEL_MEROM - -#endif /* _MACH_MACHINE_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/machine/boolean.h b/idasdk75/ldr/mach-o/h/mach/machine/boolean.h deleted file mode 100644 index 1bec00d..0000000 --- a/idasdk75/ldr/mach-o/h/mach/machine/boolean.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _MACH_MACHINE_BOOLEAN_H_ -#define _MACH_MACHINE_BOOLEAN_H_ - -#if defined (__ppc__) || defined (__ppc64__) -#include "mach/ppc/boolean.h" -#elif defined (__i386__) || defined(__x86_64__) -#include "mach/i386/boolean.h" -#elif defined (__arm__) -#include "mach/arm/boolean.h" -#else -#error architecture not supported -#endif - -#endif /* _MACH_MACHINE_BOOLEAN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/machine/kern_return.h b/idasdk75/ldr/mach-o/h/mach/machine/kern_return.h deleted file mode 100644 index df37396..0000000 --- a/idasdk75/ldr/mach-o/h/mach/machine/kern_return.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _MACH_MACHINE_KERN_RETURN_H_ -#define _MACH_MACHINE_KERN_RETURN_H_ - -#if defined (__ppc__) || defined (__ppc64__) -#include "mach/ppc/kern_return.h" -#elif defined (__i386__) || defined(__x86_64__) -#include "mach/i386/kern_return.h" -#elif defined (__arm__) -#include "mach/arm/kern_return.h" -#else -#error architecture not supported -#endif - -#endif /* _MACH_MACHINE_KERN_RETURN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/machine/thread_status.h b/idasdk75/ldr/mach-o/h/mach/machine/thread_status.h deleted file mode 100644 index ad5eff0..0000000 --- a/idasdk75/ldr/mach-o/h/mach/machine/thread_status.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _MACH_MACHINE_THREAD_STATUS_H_ -#define _MACH_MACHINE_THREAD_STATUS_H_ - -#if defined (__ppc__) || defined (__ppc64__) -#include "mach/ppc/thread_status.h" -#elif defined (__i386__) || defined(__x86_64__) -#include "mach/i386/thread_status.h" -#elif defined (__arm__) -#include "mach/arm/thread_status.h" -#else -#error architecture not supported -#endif - -#endif /* _MACH_MACHINE_THREAD_STATUS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/machine/vm_types.h b/idasdk75/ldr/mach-o/h/mach/machine/vm_types.h deleted file mode 100644 index b366092..0000000 --- a/idasdk75/ldr/mach-o/h/mach/machine/vm_types.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2000-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _MACH_MACHINE_VM_TYPES_H_ -#define _MACH_MACHINE_VM_TYPES_H_ - -#if defined (__ppc__) || defined(__ppc64__) -#include "mach/ppc/vm_types.h" -#elif defined (__i386__) || defined(__x86_64__) -#include "mach/i386/vm_types.h" -#elif defined (__arm__) -#include "mach/arm/vm_types.h" -#else -#error architecture not supported -#endif - -#endif /* _MACH_MACHINE_VM_TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/message.h b/idasdk75/ldr/mach-o/h/mach/message.h deleted file mode 100644 index 4d30507..0000000 --- a/idasdk75/ldr/mach-o/h/mach/message.h +++ /dev/null @@ -1,784 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * NOTICE: This file was modified by McAfee Research in 2004 to introduce - * support for mandatory and extensible security protections. This notice - * is included in support of clause 2.2 (b) of the Apple Public License, - * Version 2.0. - * Copyright (c) 2005 SPARTA, Inc. - */ -/* - */ -/* - * File: mach/message.h - * - * Mach IPC message and primitive function definitions. - */ - -#ifndef _MACH_MESSAGE_H_ -#define _MACH_MESSAGE_H_ - -#include <stdint.h> -#include <mach/port.h> -#include <mach/boolean.h> -#include <mach/kern_return.h> -#include <mach/machine/vm_types.h> - -#include <sys/cdefs.h> - -/* - * The timeout mechanism uses mach_msg_timeout_t values, - * passed by value. The timeout units are milliseconds. - * It is controlled with the MACH_SEND_TIMEOUT - * and MACH_RCV_TIMEOUT options. - */ - -typedef natural_t mach_msg_timeout_t; - -/* - * The value to be used when there is no timeout. - * (No MACH_SEND_TIMEOUT/MACH_RCV_TIMEOUT option.) - */ - -#define MACH_MSG_TIMEOUT_NONE ((mach_msg_timeout_t) 0) - -/* - * The kernel uses MACH_MSGH_BITS_COMPLEX as a hint. If it isn't on, it - * assumes the body of the message doesn't contain port rights or OOL - * data. The field is set in received messages. A user task must - * use caution in interpreting the body of a message if the bit isn't - * on, because the mach_msg_type's in the body might "lie" about the - * contents. If the bit isn't on, but the mach_msg_types - * in the body specify rights or OOL data, the behavior is undefined. - * (Ie, an error may or may not be produced.) - * - * The value of MACH_MSGH_BITS_REMOTE determines the interpretation - * of the msgh_remote_port field. It is handled like a msgt_name. - * - * The value of MACH_MSGH_BITS_LOCAL determines the interpretation - * of the msgh_local_port field. It is handled like a msgt_name. - * - * MACH_MSGH_BITS() combines two MACH_MSG_TYPE_* values, for the remote - * and local fields, into a single value suitable for msgh_bits. - * - * MACH_MSGH_BITS_CIRCULAR should be zero; is is used internally. - * - * The unused bits should be zero and are reserved for the kernel - * or for future interface expansion. - */ - -#define MACH_MSGH_BITS_ZERO 0x00000000 -#define MACH_MSGH_BITS_REMOTE_MASK 0x000000ff -#define MACH_MSGH_BITS_LOCAL_MASK 0x0000ff00 -#define MACH_MSGH_BITS_COMPLEX 0x80000000U -#define MACH_MSGH_BITS_USER 0x8000ffffU - -#define MACH_MSGH_BITS_CIRCULAR 0x40000000 /* internal use only */ -#define MACH_MSGH_BITS_USED 0xc000ffffU - -#define MACH_MSGH_BITS_PORTS_MASK \ - (MACH_MSGH_BITS_REMOTE_MASK|MACH_MSGH_BITS_LOCAL_MASK) - -#define MACH_MSGH_BITS(remote, local) \ - ((remote) | ((local) << 8)) -#define MACH_MSGH_BITS_REMOTE(bits) \ - ((bits) & MACH_MSGH_BITS_REMOTE_MASK) -#define MACH_MSGH_BITS_LOCAL(bits) \ - (((bits) & MACH_MSGH_BITS_LOCAL_MASK) >> 8) -#define MACH_MSGH_BITS_PORTS(bits) \ - ((bits) & MACH_MSGH_BITS_PORTS_MASK) -#define MACH_MSGH_BITS_OTHER(bits) \ - ((bits) &~ MACH_MSGH_BITS_PORTS_MASK) - -/* - * Every message starts with a message header. - * Following the message header, if the message is complex, are a count - * of type descriptors and the type descriptors themselves - * (mach_msg_descriptor_t). The size of the message must be specified in - * bytes, and includes the message header, descriptor count, descriptors, - * and inline data. - * - * The msgh_remote_port field specifies the destination of the message. - * It must specify a valid send or send-once right for a port. - * - * The msgh_local_port field specifies a "reply port". Normally, - * This field carries a send-once right that the receiver will use - * to reply to the message. It may carry the values MACH_PORT_NULL, - * MACH_PORT_DEAD, a send-once right, or a send right. - * - * The msgh_seqno field carries a sequence number associated with the - * received-from port. A port's sequence number is incremented every - * time a message is received from it. In sent messages, the field's - * value is ignored. - * - * The msgh_id field is uninterpreted by the message primitives. - * It normally carries information specifying the format - * or meaning of the message. - */ - -typedef unsigned int mach_msg_bits_t; -typedef natural_t mach_msg_size_t; -typedef integer_t mach_msg_id_t; - - -#define MACH_MSG_SIZE_NULL (mach_msg_size_t *) 0 - -typedef unsigned int mach_msg_type_name_t; - -#define MACH_MSG_TYPE_MOVE_RECEIVE 16 /* Must hold receive rights */ -#define MACH_MSG_TYPE_MOVE_SEND 17 /* Must hold send rights */ -#define MACH_MSG_TYPE_MOVE_SEND_ONCE 18 /* Must hold sendonce rights */ -#define MACH_MSG_TYPE_COPY_SEND 19 /* Must hold send rights */ -#define MACH_MSG_TYPE_MAKE_SEND 20 /* Must hold receive rights */ -#define MACH_MSG_TYPE_MAKE_SEND_ONCE 21 /* Must hold receive rights */ -#define MACH_MSG_TYPE_COPY_RECEIVE 22 /* Must hold receive rights */ - -typedef unsigned int mach_msg_copy_options_t; - -#define MACH_MSG_PHYSICAL_COPY 0 -#define MACH_MSG_VIRTUAL_COPY 1 -#define MACH_MSG_ALLOCATE 2 -#define MACH_MSG_OVERWRITE 3 -#ifdef MACH_KERNEL -#define MACH_MSG_KALLOC_COPY_T 4 -#endif /* MACH_KERNEL */ - -/* - * In a complex mach message, the mach_msg_header_t is followed by - * a descriptor count, then an array of that number of descriptors - * (mach_msg_*_descriptor_t). The type field of mach_msg_type_descriptor_t - * (which any descriptor can be cast to) indicates the flavor of the - * descriptor. - * - * Note that in LP64, the various types of descriptors are no longer all - * the same size as mach_msg_descriptor_t, so the array cannot be indexed - * as expected. - */ - -typedef unsigned int mach_msg_descriptor_type_t; - -#define MACH_MSG_PORT_DESCRIPTOR 0 -#define MACH_MSG_OOL_DESCRIPTOR 1 -#define MACH_MSG_OOL_PORTS_DESCRIPTOR 2 -#define MACH_MSG_OOL_VOLATILE_DESCRIPTOR 3 - -#pragma pack(4) - -typedef struct -{ - natural_t pad1; - mach_msg_size_t pad2; - unsigned int pad3 : 24; - mach_msg_descriptor_type_t type : 8; -} mach_msg_type_descriptor_t; - -typedef struct -{ - mach_port_t name; -#if !(defined(KERNEL) && defined(__LP64__)) -// Pad to 8 bytes everywhere except the K64 kernel where mach_port_t is 8 bytes - mach_msg_size_t pad1; -#endif - unsigned int pad2 : 16; - mach_msg_type_name_t disposition : 8; - mach_msg_descriptor_type_t type : 8; -} mach_msg_port_descriptor_t; - -typedef struct -{ - uint32_t address; - mach_msg_size_t size; - boolean_t deallocate: 8; - mach_msg_copy_options_t copy: 8; - unsigned int pad1: 8; - mach_msg_descriptor_type_t type: 8; -} mach_msg_ool_descriptor32_t; - -typedef struct -{ - uint64_t address; - boolean_t deallocate: 8; - mach_msg_copy_options_t copy: 8; - unsigned int pad1: 8; - mach_msg_descriptor_type_t type: 8; - mach_msg_size_t size; -} mach_msg_ool_descriptor64_t; - -typedef struct -{ - void* address; -#if !defined(__LP64__) - mach_msg_size_t size; -#endif - boolean_t deallocate: 8; - mach_msg_copy_options_t copy: 8; - unsigned int pad1: 8; - mach_msg_descriptor_type_t type: 8; -#if defined(__LP64__) - mach_msg_size_t size; -#endif -#if defined(KERNEL) && !defined(__LP64__) - uint32_t pad_end; -#endif -} mach_msg_ool_descriptor_t; - -typedef struct -{ - uint32_t address; - mach_msg_size_t count; - boolean_t deallocate: 8; - mach_msg_copy_options_t copy: 8; - mach_msg_type_name_t disposition : 8; - mach_msg_descriptor_type_t type : 8; -} mach_msg_ool_ports_descriptor32_t; - -typedef struct -{ - uint64_t address; - boolean_t deallocate: 8; - mach_msg_copy_options_t copy: 8; - mach_msg_type_name_t disposition : 8; - mach_msg_descriptor_type_t type : 8; - mach_msg_size_t count; -} mach_msg_ool_ports_descriptor64_t; - -typedef struct -{ - void* address; -#if !defined(__LP64__) - mach_msg_size_t count; -#endif - boolean_t deallocate: 8; - mach_msg_copy_options_t copy: 8; - mach_msg_type_name_t disposition : 8; - mach_msg_descriptor_type_t type : 8; -#if defined(__LP64__) - mach_msg_size_t count; -#endif -#if defined(KERNEL) && !defined(__LP64__) - uint32_t pad_end; -#endif -} mach_msg_ool_ports_descriptor_t; - -/* - * LP64support - This union definition is not really - * appropriate in LP64 mode because not all descriptors - * are of the same size in that environment. - */ -#if defined(__LP64__) && defined(KERNEL) -typedef union -{ - mach_msg_port_descriptor_t port; - mach_msg_ool_descriptor32_t out_of_line; - mach_msg_ool_ports_descriptor32_t ool_ports; - mach_msg_type_descriptor_t type; -} mach_msg_descriptor_t; -#else -typedef union -{ - mach_msg_port_descriptor_t port; - mach_msg_ool_descriptor_t out_of_line; - mach_msg_ool_ports_descriptor_t ool_ports; - mach_msg_type_descriptor_t type; -} mach_msg_descriptor_t; -#endif - -typedef struct -{ - mach_msg_size_t msgh_descriptor_count; -} mach_msg_body_t; - -#define MACH_MSG_BODY_NULL (mach_msg_body_t *) 0 -#define MACH_MSG_DESCRIPTOR_NULL (mach_msg_descriptor_t *) 0 - -typedef struct -{ - mach_msg_bits_t msgh_bits; - mach_msg_size_t msgh_size; - mach_port_t msgh_remote_port; - mach_port_t msgh_local_port; - mach_msg_size_t msgh_reserved; - mach_msg_id_t msgh_id; -} mach_msg_header_t; - -#define MACH_MSG_NULL (mach_msg_header_t *) 0 - -typedef struct -{ - mach_msg_header_t header; - mach_msg_body_t body; -} mach_msg_base_t; - -typedef unsigned int mach_msg_trailer_type_t; -typedef char *mach_msg_trailer_info_t; - -#define MACH_MSG_TRAILER_FORMAT_0 0 - -typedef unsigned int mach_msg_trailer_size_t; - -typedef struct -{ - mach_msg_trailer_type_t msgh_trailer_type; - mach_msg_trailer_size_t msgh_trailer_size; -} mach_msg_trailer_t; - -typedef struct -{ - mach_msg_trailer_type_t msgh_trailer_type; - mach_msg_trailer_size_t msgh_trailer_size; - mach_port_seqno_t msgh_seqno; -} mach_msg_seqno_trailer_t; - -typedef struct -{ - unsigned int val[2]; -} security_token_t; - -typedef struct -{ - mach_msg_trailer_type_t msgh_trailer_type; - mach_msg_trailer_size_t msgh_trailer_size; - mach_port_seqno_t msgh_seqno; - security_token_t msgh_sender; -} mach_msg_security_trailer_t; - -/* - * The audit token is an opaque token which identifies - * Mach tasks and senders of Mach messages as subjects - * to the BSM audit system. Only the appropriate BSM - * library routines should be used to interpret the - * contents of the audit token as the representation - * of the subject identity within the token may change - * over time. - */ -typedef struct -{ - unsigned int val[8]; -} audit_token_t; - -typedef struct -{ - mach_msg_trailer_type_t msgh_trailer_type; - mach_msg_trailer_size_t msgh_trailer_size; - mach_port_seqno_t msgh_seqno; - security_token_t msgh_sender; - audit_token_t msgh_audit; -} mach_msg_audit_trailer_t; - -typedef struct -{ - mach_msg_trailer_type_t msgh_trailer_type; - mach_msg_trailer_size_t msgh_trailer_size; - mach_port_seqno_t msgh_seqno; - security_token_t msgh_sender; - audit_token_t msgh_audit; - mach_vm_address_t msgh_context; -} mach_msg_context_trailer_t; - - -typedef struct -{ - mach_port_name_t sender; -} msg_labels_t; - -/* - Trailer type to pass MAC policy label info as a mach message trailer. - -*/ - -typedef struct -{ - mach_msg_trailer_type_t msgh_trailer_type; - mach_msg_trailer_size_t msgh_trailer_size; - mach_port_seqno_t msgh_seqno; - security_token_t msgh_sender; - audit_token_t msgh_audit; - mach_vm_address_t msgh_context; - int msgh_ad; - msg_labels_t msgh_labels; -} mach_msg_mac_trailer_t; - -#define MACH_MSG_TRAILER_MINIMUM_SIZE sizeof(mach_msg_trailer_t) - -/* - * These values can change from release to release - but clearly - * code cannot request additional trailer elements one was not - * compiled to understand. Therefore, it is safe to use this - * constant when the same module specified the receive options. - * Otherwise, you run the risk that the options requested by - * another module may exceed the local modules notion of - * MAX_TRAILER_SIZE. - */ -typedef mach_msg_mac_trailer_t mach_msg_max_trailer_t; -#define MAX_TRAILER_SIZE ((mach_msg_size_t)sizeof(mach_msg_max_trailer_t)) - -/* - * Legacy requirements keep us from ever updating these defines (even - * when the format_0 trailers gain new option data fields in the future). - * Therefore, they shouldn't be used going forward. Instead, the sizes - * should be compared against the specific element size requested using - * REQUESTED_TRAILER_SIZE. - */ -typedef mach_msg_security_trailer_t mach_msg_format_0_trailer_t; - -/*typedef mach_msg_mac_trailer_t mach_msg_format_0_trailer_t; -*/ - -#define MACH_MSG_TRAILER_FORMAT_0_SIZE sizeof(mach_msg_format_0_trailer_t) - -#define KERNEL_SECURITY_TOKEN_VALUE { {0, 1} } -extern security_token_t KERNEL_SECURITY_TOKEN; - -#define KERNEL_AUDIT_TOKEN_VALUE { {0, 0, 0, 0, 0, 0, 0, 0} } -extern audit_token_t KERNEL_AUDIT_TOKEN; - -typedef integer_t mach_msg_options_t; - -typedef struct -{ - mach_msg_header_t header; -} mach_msg_empty_send_t; - -typedef struct -{ - mach_msg_header_t header; - mach_msg_trailer_t trailer; -} mach_msg_empty_rcv_t; - -typedef union -{ - mach_msg_empty_send_t send; - mach_msg_empty_rcv_t rcv; -} mach_msg_empty_t; - -#pragma pack() - -/* utility to round the message size - will become machine dependent */ -#define round_msg(x) (((mach_msg_size_t)(x) + sizeof (natural_t) - 1) & \ - ~(sizeof (natural_t) - 1)) - -/* - * There is no fixed upper bound to the size of Mach messages. - */ - -#define MACH_MSG_SIZE_MAX ((mach_msg_size_t) ~0) - -/* - * Compatibility definitions, for code written - * when there was a msgh_kind instead of msgh_seqno. - */ -#define MACH_MSGH_KIND_NORMAL 0x00000000 -#define MACH_MSGH_KIND_NOTIFICATION 0x00000001 -#define msgh_kind msgh_seqno -#define mach_msg_kind_t mach_port_seqno_t - -typedef natural_t mach_msg_type_size_t; -typedef natural_t mach_msg_type_number_t; - -/* - * Values received/carried in messages. Tells the receiver what - * sort of port right he now has. - * - * MACH_MSG_TYPE_PORT_NAME is used to transfer a port name - * which should remain uninterpreted by the kernel. (Port rights - * are not transferred, just the port name.) - */ - -#define MACH_MSG_TYPE_PORT_NONE 0 - -#define MACH_MSG_TYPE_PORT_NAME 15 -#define MACH_MSG_TYPE_PORT_RECEIVE MACH_MSG_TYPE_MOVE_RECEIVE -#define MACH_MSG_TYPE_PORT_SEND MACH_MSG_TYPE_MOVE_SEND -#define MACH_MSG_TYPE_PORT_SEND_ONCE MACH_MSG_TYPE_MOVE_SEND_ONCE - -#define MACH_MSG_TYPE_LAST 22 /* Last assigned */ - -/* - * A dummy value. Mostly used to indicate that the actual value - * will be filled in later, dynamically. - */ - -#define MACH_MSG_TYPE_POLYMORPHIC ((mach_msg_type_name_t) -1) - -/* - * Is a given item a port type? - */ - -#define MACH_MSG_TYPE_PORT_ANY(x) \ - (((x) >= MACH_MSG_TYPE_MOVE_RECEIVE) && \ - ((x) <= MACH_MSG_TYPE_MAKE_SEND_ONCE)) - -#define MACH_MSG_TYPE_PORT_ANY_SEND(x) \ - (((x) >= MACH_MSG_TYPE_MOVE_SEND) && \ - ((x) <= MACH_MSG_TYPE_MAKE_SEND_ONCE)) - -#define MACH_MSG_TYPE_PORT_ANY_RIGHT(x) \ - (((x) >= MACH_MSG_TYPE_MOVE_RECEIVE) && \ - ((x) <= MACH_MSG_TYPE_MOVE_SEND_ONCE)) - -typedef integer_t mach_msg_option_t; - -#define MACH_MSG_OPTION_NONE 0x00000000 - -#define MACH_SEND_MSG 0x00000001 -#define MACH_RCV_MSG 0x00000002 -#define MACH_RCV_LARGE 0x00000004 - -#define MACH_SEND_TIMEOUT 0x00000010 -#define MACH_SEND_INTERRUPT 0x00000040 /* libmach implements */ -#define MACH_SEND_NOTIFY 0x00000080 /* arm send-possible notify */ -#define MACH_SEND_ALWAYS 0x00010000 /* internal use only */ -#define MACH_SEND_TRAILER 0x00020000 - -#define MACH_RCV_TIMEOUT 0x00000100 -#define MACH_RCV_NOTIFY 0x00000200 /* reserved - legacy */ -#define MACH_RCV_INTERRUPT 0x00000400 /* libmach implements */ -#define MACH_RCV_OVERWRITE 0x00001000 - -/* - * NOTE: a 0x00------ RCV mask implies to ask for - * a MACH_MSG_TRAILER_FORMAT_0 with 0 Elements, - * which is equivalent to a mach_msg_trailer_t. - * - * XXXMAC: unlike the rest of the MACH_RCV_* flags, MACH_RCV_TRAILER_LABELS - * needs its own private bit since we only calculate its fields when absolutely - * required. - */ -#define MACH_RCV_TRAILER_NULL 0 -#define MACH_RCV_TRAILER_SEQNO 1 -#define MACH_RCV_TRAILER_SENDER 2 -#define MACH_RCV_TRAILER_AUDIT 3 -#define MACH_RCV_TRAILER_CTX 4 -#define MACH_RCV_TRAILER_AV 7 -#define MACH_RCV_TRAILER_LABELS 8 - -#define MACH_RCV_TRAILER_TYPE(x) (((x) & 0xf) << 28) -#define MACH_RCV_TRAILER_ELEMENTS(x) (((x) & 0xf) << 24) -#define MACH_RCV_TRAILER_MASK ((0xff << 24)) - -#define GET_RCV_ELEMENTS(y) (((y) >> 24) & 0xf) - -/* - * XXXMAC: note that in the case of MACH_RCV_TRAILER_LABELS, - * we just fall through to mach_msg_max_trailer_t. - * This is correct behavior since mach_msg_max_trailer_t is defined as - * mac_msg_mac_trailer_t which is used for the LABELS trailer. - * It also makes things work properly if MACH_RCV_TRAILER_LABELS is ORed - * with one of the other options. - */ -#define REQUESTED_TRAILER_SIZE(y) \ - ((mach_msg_trailer_size_t) \ - ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_NULL) ? \ - sizeof(mach_msg_trailer_t) : \ - ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_SEQNO) ? \ - sizeof(mach_msg_seqno_trailer_t) : \ - ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_SENDER) ? \ - sizeof(mach_msg_security_trailer_t) : \ - ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_AUDIT) ? \ - sizeof(mach_msg_audit_trailer_t) : \ - ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_CTX) ? \ - sizeof(mach_msg_context_trailer_t) : \ - ((GET_RCV_ELEMENTS(y) == MACH_RCV_TRAILER_AV) ? \ - sizeof(mach_msg_mac_trailer_t) : \ - sizeof(mach_msg_max_trailer_t)))))))) - -/* - * Much code assumes that mach_msg_return_t == kern_return_t. - * This definition is useful for descriptive purposes. - * - * See <mach/error.h> for the format of error codes. - * IPC errors are system 4. Send errors are subsystem 0; - * receive errors are subsystem 1. The code field is always non-zero. - * The high bits of the code field communicate extra information - * for some error codes. MACH_MSG_MASK masks off these special bits. - */ - -typedef kern_return_t mach_msg_return_t; - -#define MACH_MSG_SUCCESS 0x00000000 - - -#define MACH_MSG_MASK 0x00003e00 - /* All special error code bits defined below. */ -#define MACH_MSG_IPC_SPACE 0x00002000 - /* No room in IPC name space for another capability name. */ -#define MACH_MSG_VM_SPACE 0x00001000 - /* No room in VM address space for out-of-line memory. */ -#define MACH_MSG_IPC_KERNEL 0x00000800 - /* Kernel resource shortage handling an IPC capability. */ -#define MACH_MSG_VM_KERNEL 0x00000400 - /* Kernel resource shortage handling out-of-line memory. */ - -#define MACH_SEND_IN_PROGRESS 0x10000001 - /* Thread is waiting to send. (Internal use only.) */ -#define MACH_SEND_INVALID_DATA 0x10000002 - /* Bogus in-line data. */ -#define MACH_SEND_INVALID_DEST 0x10000003 - /* Bogus destination port. */ -#define MACH_SEND_TIMED_OUT 0x10000004 - /* Message not sent before timeout expired. */ -#define MACH_SEND_INTERRUPTED 0x10000007 - /* Software interrupt. */ -#define MACH_SEND_MSG_TOO_SMALL 0x10000008 - /* Data doesn't contain a complete message. */ -#define MACH_SEND_INVALID_REPLY 0x10000009 - /* Bogus reply port. */ -#define MACH_SEND_INVALID_RIGHT 0x1000000a - /* Bogus port rights in the message body. */ -#define MACH_SEND_INVALID_NOTIFY 0x1000000b - /* Bogus notify port argument. */ -#define MACH_SEND_INVALID_MEMORY 0x1000000c - /* Invalid out-of-line memory pointer. */ -#define MACH_SEND_NO_BUFFER 0x1000000d - /* No message buffer is available. */ -#define MACH_SEND_TOO_LARGE 0x1000000e - /* Send is too large for port */ -#define MACH_SEND_INVALID_TYPE 0x1000000f - /* Invalid msg-type specification. */ -#define MACH_SEND_INVALID_HEADER 0x10000010 - /* A field in the header had a bad value. */ -#define MACH_SEND_INVALID_TRAILER 0x10000011 - /* The trailer to be sent does not match kernel format. */ -#define MACH_SEND_INVALID_RT_OOL_SIZE 0x10000015 - /* compatibility: no longer a returned error */ - -#define MACH_RCV_IN_PROGRESS 0x10004001 - /* Thread is waiting for receive. (Internal use only.) */ -#define MACH_RCV_INVALID_NAME 0x10004002 - /* Bogus name for receive port/port-set. */ -#define MACH_RCV_TIMED_OUT 0x10004003 - /* Didn't get a message within the timeout value. */ -#define MACH_RCV_TOO_LARGE 0x10004004 - /* Message buffer is not large enough for inline data. */ -#define MACH_RCV_INTERRUPTED 0x10004005 - /* Software interrupt. */ -#define MACH_RCV_PORT_CHANGED 0x10004006 - /* compatibility: no longer a returned error */ -#define MACH_RCV_INVALID_NOTIFY 0x10004007 - /* Bogus notify port argument. */ -#define MACH_RCV_INVALID_DATA 0x10004008 - /* Bogus message buffer for inline data. */ -#define MACH_RCV_PORT_DIED 0x10004009 - /* Port/set was sent away/died during receive. */ -#define MACH_RCV_IN_SET 0x1000400a - /* compatibility: no longer a returned error */ -#define MACH_RCV_HEADER_ERROR 0x1000400b - /* Error receiving message header. See special bits. */ -#define MACH_RCV_BODY_ERROR 0x1000400c - /* Error receiving message body. See special bits. */ -#define MACH_RCV_INVALID_TYPE 0x1000400d - /* Invalid msg-type specification in scatter list. */ -#define MACH_RCV_SCATTER_SMALL 0x1000400e - /* Out-of-line overwrite region is not large enough */ -#define MACH_RCV_INVALID_TRAILER 0x1000400f - /* trailer type or number of trailer elements not supported */ -#define MACH_RCV_IN_PROGRESS_TIMED 0x10004011 - /* Waiting for receive with timeout. (Internal use only.) */ - - -__BEGIN_DECLS - -/* - * Routine: mach_msg_overwrite - * Purpose: - * Send and/or receive a message. If the message operation - * is interrupted, and the user did not request an indication - * of that fact, then restart the appropriate parts of the - * operation silently (trap version does not restart). - * - * Distinct send and receive buffers may be specified. If - * no separate receive buffer is specified, the msg parameter - * will be used for both send and receive operations. - * - * In addition to a distinct receive buffer, that buffer may - * already contain scatter control information to direct the - * receiving of the message. - */ - -extern mach_msg_return_t mach_msg_overwrite( - mach_msg_header_t *msg, - mach_msg_option_t option, - mach_msg_size_t send_size, - mach_msg_size_t rcv_size, - mach_port_name_t rcv_name, - mach_msg_timeout_t timeout, - mach_port_name_t notify, - mach_msg_header_t *rcv_msg, - mach_msg_size_t rcv_limit); - - -/* - * Routine: mach_msg - * Purpose: - * Send and/or receive a message. If the message operation - * is interrupted, and the user did not request an indication - * of that fact, then restart the appropriate parts of the - * operation silently (trap version does not restart). - */ -extern mach_msg_return_t mach_msg( - mach_msg_header_t *msg, - mach_msg_option_t option, - mach_msg_size_t send_size, - mach_msg_size_t rcv_size, - mach_port_name_t rcv_name, - mach_msg_timeout_t timeout, - mach_port_name_t notify); - - -__END_DECLS - -#endif /* _MACH_MESSAGE_H_ */ - diff --git a/idasdk75/ldr/mach-o/h/mach/port.h b/idasdk75/ldr/mach-o/h/mach/port.h deleted file mode 100644 index cb007b7..0000000 --- a/idasdk75/ldr/mach-o/h/mach/port.h +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - * NOTICE: This file was modified by McAfee Research in 2004 to introduce - * support for mandatory and extensible security protections. This notice - * is included in support of clause 2.2 (b) of the Apple Public License, - * Version 2.0. - */ -/* - */ -/* - * File: mach/port.h - * - * Definition of a Mach port - * - * Mach ports are the endpoints to Mach-implemented communications - * channels (usually uni-directional message queues, but other types - * also exist). - * - * Unique collections of these endpoints are maintained for each - * Mach task. Each Mach port in the task's collection is given a - * [task-local] name to identify it - and the the various "rights" - * held by the task for that specific endpoint. - * - * This header defines the types used to identify these Mach ports - * and the various rights associated with them. For more info see: - * - * <mach/mach_port.h> - manipulation of port rights in a given space - * <mach/message.h> - message queue [and port right passing] mechanism - * - */ - -#ifndef _MACH_PORT_H_ -#define _MACH_PORT_H_ - -#include <sys/cdefs.h> -#include <stdint.h> -#include <mach/boolean.h> -#include <mach/machine/vm_types.h> - -/* - * mach_port_name_t - the local identity for a Mach port - * - * The name is Mach port namespace specific. It is used to - * identify the rights held for that port by the task whose - * namespace is implied [or specifically provided]. - * - * Use of this type usually implies just a name - no rights. - * See mach_port_t for a type that implies a "named right." - * - */ - -typedef natural_t mach_port_name_t; -typedef mach_port_name_t *mach_port_name_array_t; - - -/* - * mach_port_t - a named port right - * - * In user-space, "rights" are represented by the name of the - * right in the Mach port namespace. Even so, this type is - * presented as a unique one to more clearly denote the presence - * of a right coming along with the name. - * - * Often, various rights for a port held in a single name space - * will coalesce and are, therefore, be identified by a single name - * [this is the case for send and receive rights]. But not - * always [send-once rights currently get a unique name for - * each right]. - * - */ - -#ifndef _MACH_PORT_T -#define _MACH_PORT_T -typedef mach_port_name_t mach_port_t; -#endif - - -typedef mach_port_t *mach_port_array_t; - -/* - * MACH_PORT_NULL is a legal value that can be carried in messages. - * It indicates the absence of any port or port rights. (A port - * argument keeps the message from being "simple", even if the - * value is MACH_PORT_NULL.) The value MACH_PORT_DEAD is also a legal - * value that can be carried in messages. It indicates - * that a port right was present, but it died. - */ - -#define MACH_PORT_NULL 0 /* intentional loose typing */ -#define MACH_PORT_DEAD ((mach_port_name_t) ~0) -#define MACH_PORT_VALID(name) \ - (((name) != MACH_PORT_NULL) && \ - ((name) != MACH_PORT_DEAD)) - - -/* - * For kernel-selected [assigned] port names, the name is - * comprised of two parts: a generation number and an index. - * This approach keeps the exact same name from being generated - * and reused too quickly [to catch right/reference counting bugs]. - * The dividing line between the constituent parts is exposed so - * that efficient "mach_port_name_t to data structure pointer" - * conversion implementation can be made. But it is possible - * for user-level code to assign their own names to Mach ports. - * These are not required to participate in this algorithm. So - * care should be taken before "assuming" this model. - * - */ - -#ifndef NO_PORT_GEN - -#define MACH_PORT_INDEX(name) ((name) >> 8) -#define MACH_PORT_GEN(name) (((name) & 0xff) << 24) -#define MACH_PORT_MAKE(index, gen) \ - (((index) << 8) | (gen) >> 24) - -#else /* NO_PORT_GEN */ - -#define MACH_PORT_INDEX(name) (name) -#define MACH_PORT_GEN(name) (0) -#define MACH_PORT_MAKE(index, gen) (index) - -#endif /* NO_PORT_GEN */ - - -/* - * These are the different rights a task may have for a port. - * The MACH_PORT_RIGHT_* definitions are used as arguments - * to mach_port_allocate, mach_port_get_refs, etc, to specify - * a particular right to act upon. The mach_port_names and - * mach_port_type calls return bitmasks using the MACH_PORT_TYPE_* - * definitions. This is because a single name may denote - * multiple rights. - */ - -typedef natural_t mach_port_right_t; - -#define MACH_PORT_RIGHT_SEND ((mach_port_right_t) 0) -#define MACH_PORT_RIGHT_RECEIVE ((mach_port_right_t) 1) -#define MACH_PORT_RIGHT_SEND_ONCE ((mach_port_right_t) 2) -#define MACH_PORT_RIGHT_PORT_SET ((mach_port_right_t) 3) -#define MACH_PORT_RIGHT_DEAD_NAME ((mach_port_right_t) 4) -#define MACH_PORT_RIGHT_LABELH ((mach_port_right_t) 5) -#define MACH_PORT_RIGHT_NUMBER ((mach_port_right_t) 6) - -typedef natural_t mach_port_type_t; -typedef mach_port_type_t *mach_port_type_array_t; - -#define MACH_PORT_TYPE(right) \ - ((mach_port_type_t)(((mach_port_type_t) 1) \ - << ((right) + ((mach_port_right_t) 16)))) -#define MACH_PORT_TYPE_NONE ((mach_port_type_t) 0L) -#define MACH_PORT_TYPE_SEND MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND) -#define MACH_PORT_TYPE_RECEIVE MACH_PORT_TYPE(MACH_PORT_RIGHT_RECEIVE) -#define MACH_PORT_TYPE_SEND_ONCE MACH_PORT_TYPE(MACH_PORT_RIGHT_SEND_ONCE) -#define MACH_PORT_TYPE_PORT_SET MACH_PORT_TYPE(MACH_PORT_RIGHT_PORT_SET) -#define MACH_PORT_TYPE_DEAD_NAME MACH_PORT_TYPE(MACH_PORT_RIGHT_DEAD_NAME) -#define MACH_PORT_TYPE_LABELH MACH_PORT_TYPE(MACH_PORT_RIGHT_LABELH) - -/* Convenient combinations. */ - -#define MACH_PORT_TYPE_SEND_RECEIVE \ - (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_RECEIVE) -#define MACH_PORT_TYPE_SEND_RIGHTS \ - (MACH_PORT_TYPE_SEND|MACH_PORT_TYPE_SEND_ONCE) -#define MACH_PORT_TYPE_PORT_RIGHTS \ - (MACH_PORT_TYPE_SEND_RIGHTS|MACH_PORT_TYPE_RECEIVE) -#define MACH_PORT_TYPE_PORT_OR_DEAD \ - (MACH_PORT_TYPE_PORT_RIGHTS|MACH_PORT_TYPE_DEAD_NAME) -#define MACH_PORT_TYPE_ALL_RIGHTS \ - (MACH_PORT_TYPE_PORT_OR_DEAD|MACH_PORT_TYPE_PORT_SET) - -/* Dummy type bits that mach_port_type/mach_port_names can return. */ - -#define MACH_PORT_TYPE_DNREQUEST 0x80000000 -#define MACH_PORT_TYPE_SPREQUEST 0x40000000 -#define MACH_PORT_TYPE_SPREQUEST_DELAYED 0x20000000 - -/* User-references for capabilities. */ - -typedef natural_t mach_port_urefs_t; -typedef integer_t mach_port_delta_t; /* change in urefs */ - -/* Attributes of ports. (See mach_port_get_receive_status.) */ - -typedef natural_t mach_port_seqno_t; /* sequence number */ -typedef natural_t mach_port_mscount_t; /* make-send count */ -typedef natural_t mach_port_msgcount_t; /* number of msgs */ -typedef natural_t mach_port_rights_t; /* number of rights */ - -/* - * Are there outstanding send rights for a given port? - */ -#define MACH_PORT_SRIGHTS_NONE 0 /* no srights */ -#define MACH_PORT_SRIGHTS_PRESENT 1 /* srights */ -typedef unsigned int mach_port_srights_t; /* status of send rights */ - -typedef struct mach_port_status { - mach_port_rights_t mps_pset; /* count of containing port sets */ - mach_port_seqno_t mps_seqno; /* sequence number */ - mach_port_mscount_t mps_mscount; /* make-send count */ - mach_port_msgcount_t mps_qlimit; /* queue limit */ - mach_port_msgcount_t mps_msgcount; /* number in the queue */ - mach_port_rights_t mps_sorights; /* how many send-once rights */ - boolean_t mps_srights; /* do send rights exist? */ - boolean_t mps_pdrequest; /* port-deleted requested? */ - boolean_t mps_nsrequest; /* no-senders requested? */ - natural_t mps_flags; /* port flags */ -} mach_port_status_t; - -/* System-wide values for setting queue limits on a port */ -#define MACH_PORT_QLIMIT_ZERO ((mach_port_msgcount_t) 0) -#define MACH_PORT_QLIMIT_BASIC ((mach_port_msgcount_t) 5) -#define MACH_PORT_QLIMIT_SMALL ((mach_port_msgcount_t) 16) -#define MACH_PORT_QLIMIT_LARGE ((mach_port_msgcount_t) 1024) -#define MACH_PORT_QLIMIT_KERNEL ((mach_port_msgcount_t) 65536) -#define MACH_PORT_QLIMIT_MIN MACH_PORT_QLIMIT_ZERO -#define MACH_PORT_QLIMIT_DEFAULT MACH_PORT_QLIMIT_BASIC -#define MACH_PORT_QLIMIT_MAX MACH_PORT_QLIMIT_LARGE - -typedef struct mach_port_limits { - mach_port_msgcount_t mpl_qlimit; /* number of msgs */ -} mach_port_limits_t; - -typedef integer_t *mach_port_info_t; /* varying array of natural_t */ - -/* Flavors for mach_port_get/set_attributes() */ -typedef int mach_port_flavor_t; -#define MACH_PORT_LIMITS_INFO 1 /* uses mach_port_status_t */ -#define MACH_PORT_RECEIVE_STATUS 2 /* uses mach_port_limits_t */ -#define MACH_PORT_DNREQUESTS_SIZE 3 /* info is int */ - -#define MACH_PORT_LIMITS_INFO_COUNT ((natural_t) \ - (sizeof(mach_port_limits_t)/sizeof(natural_t))) -#define MACH_PORT_RECEIVE_STATUS_COUNT ((natural_t) \ - (sizeof(mach_port_status_t)/sizeof(natural_t))) -#define MACH_PORT_DNREQUESTS_SIZE_COUNT 1 - -/* - * Structure used to pass information about port allocation requests. - * Must be padded to 64-bits total length. - */ -typedef struct mach_port_qos { - unsigned int name:1; /* name given */ - unsigned int prealloc:1; /* prealloced message */ - boolean_t pad1:30; - natural_t len; -} mach_port_qos_t; - -/* Mach Port Guarding definitions */ - -/* - * Flags for mach_port_options (used for - * invocation of mach_port_construct). - * Indicates attributes to be set for the newly - * allocated port. - */ -#define MPO_CONTEXT_AS_GUARD 0x01 /* Add guard to the port */ -#define MPO_QLIMIT 0x02 /* Set qlimit for the port msg queue */ -#define MPO_TEMPOWNER 0x04 /* Set the tempowner bit of the port */ -#define MPO_IMPORTANCE_RECEIVER 0x08 /* Mark the port as importance receiver */ -#define MPO_INSERT_SEND_RIGHT 0x10 /* Insert a send right for the port */ -#define MPO_STRICT 0x20 /* Apply strict guarding for port */ - -/* - * Structure to define optional attributes for a newly - * constructed port. - */ -typedef struct mach_port_options { - uint32_t flags; /* Flags defining attributes for port */ - mach_port_limits_t mpl; /* Message queue limit for port */ - uint64_t reserved[2]; /* Reserved */ -}mach_port_options_t; - -typedef mach_port_options_t *mach_port_options_ptr_t; - -/* - * EXC_GUARD represents a guard violation for both - * mach ports and file descriptors. GUARD_TYPE_ is used - * to differentiate among them. - */ -#define GUARD_TYPE_MACH_PORT 0x1 - -/* Reasons for exception for a guarded mach port */ -enum mach_port_guard_exception_codes { - kGUARD_EXC_DESTROY = 1u << 0, - kGUARD_EXC_MOD_REFS = 1u << 1, - kGUARD_EXC_SET_CONTEXT = 1u << 2, - kGUARD_EXC_UNGUARDED = 1u << 3, - kGUARD_EXC_INCORRECT_GUARD = 1u << 4 -}; - -#if !__DARWIN_UNIX03 && !defined(_NO_PORT_T_FROM_MACH) -/* - * Mach 3.0 renamed everything to have mach_ in front of it. - * These types and macros are provided for backward compatibility - * but are deprecated. - */ -typedef mach_port_t port_t; -typedef mach_port_name_t port_name_t; -typedef mach_port_name_t *port_name_array_t; - -#define PORT_NULL ((port_t) 0) -#define PORT_DEAD ((port_t) ~0) -#define PORT_VALID(name) \ - ((port_t)(name) != PORT_NULL && (port_t)(name) != PORT_DEAD) - -#endif /* !__DARWIN_UNIX03 && !_NO_PORT_T_FROM_MACH */ - -#endif /* _MACH_PORT_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/ppc/_structs.h b/idasdk75/ldr/mach-o/h/mach/ppc/_structs.h deleted file mode 100644 index 0e3bbf3..0000000 --- a/idasdk75/ldr/mach-o/h/mach/ppc/_structs.h +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright (c) 2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ - -#ifndef _MACH_PPC__STRUCTS_H_ -#define _MACH_PPC__STRUCTS_H_ - -#include <sys/cdefs.h> - -/* - * ppc_thread_state is the structure that is exported to user threads for - * use in status/mutate calls. This structure should never change. - * - */ - -#if __DARWIN_UNIX03 -#define _STRUCT_PPC_THREAD_STATE struct __darwin_ppc_thread_state -_STRUCT_PPC_THREAD_STATE -{ - unsigned int __srr0; /* Instruction address register (PC) */ - unsigned int __srr1; /* Machine state register (supervisor) */ - unsigned int __r0; - unsigned int __r1; - unsigned int __r2; - unsigned int __r3; - unsigned int __r4; - unsigned int __r5; - unsigned int __r6; - unsigned int __r7; - unsigned int __r8; - unsigned int __r9; - unsigned int __r10; - unsigned int __r11; - unsigned int __r12; - unsigned int __r13; - unsigned int __r14; - unsigned int __r15; - unsigned int __r16; - unsigned int __r17; - unsigned int __r18; - unsigned int __r19; - unsigned int __r20; - unsigned int __r21; - unsigned int __r22; - unsigned int __r23; - unsigned int __r24; - unsigned int __r25; - unsigned int __r26; - unsigned int __r27; - unsigned int __r28; - unsigned int __r29; - unsigned int __r30; - unsigned int __r31; - - unsigned int __cr; /* Condition register */ - unsigned int __xer; /* User's integer exception register */ - unsigned int __lr; /* Link register */ - unsigned int __ctr; /* Count register */ - unsigned int __mq; /* MQ register (601 only) */ - - unsigned int __vrsave; /* Vector Save Register */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_PPC_THREAD_STATE struct ppc_thread_state -_STRUCT_PPC_THREAD_STATE -{ - unsigned int srr0; /* Instruction address register (PC) */ - unsigned int srr1; /* Machine state register (supervisor) */ - unsigned int r0; - unsigned int r1; - unsigned int r2; - unsigned int r3; - unsigned int r4; - unsigned int r5; - unsigned int r6; - unsigned int r7; - unsigned int r8; - unsigned int r9; - unsigned int r10; - unsigned int r11; - unsigned int r12; - unsigned int r13; - unsigned int r14; - unsigned int r15; - unsigned int r16; - unsigned int r17; - unsigned int r18; - unsigned int r19; - unsigned int r20; - unsigned int r21; - unsigned int r22; - unsigned int r23; - unsigned int r24; - unsigned int r25; - unsigned int r26; - unsigned int r27; - unsigned int r28; - unsigned int r29; - unsigned int r30; - unsigned int r31; - - unsigned int cr; /* Condition register */ - unsigned int xer; /* User's integer exception register */ - unsigned int lr; /* Link register */ - unsigned int ctr; /* Count register */ - unsigned int mq; /* MQ register (601 only) */ - - unsigned int vrsave; /* Vector Save Register */ -}; -#endif /* __DARWIN_UNIX03 */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) - -#pragma pack(4) /* Make sure the structure stays as we defined it */ - -#if __DARWIN_UNIX03 -#define _STRUCT_PPC_THREAD_STATE64 struct __darwin_ppc_thread_state64 -_STRUCT_PPC_THREAD_STATE64 -{ - unsigned long long __srr0; /* Instruction address register (PC) */ - unsigned long long __srr1; /* Machine state register (supervisor) */ - unsigned long long __r0; - unsigned long long __r1; - unsigned long long __r2; - unsigned long long __r3; - unsigned long long __r4; - unsigned long long __r5; - unsigned long long __r6; - unsigned long long __r7; - unsigned long long __r8; - unsigned long long __r9; - unsigned long long __r10; - unsigned long long __r11; - unsigned long long __r12; - unsigned long long __r13; - unsigned long long __r14; - unsigned long long __r15; - unsigned long long __r16; - unsigned long long __r17; - unsigned long long __r18; - unsigned long long __r19; - unsigned long long __r20; - unsigned long long __r21; - unsigned long long __r22; - unsigned long long __r23; - unsigned long long __r24; - unsigned long long __r25; - unsigned long long __r26; - unsigned long long __r27; - unsigned long long __r28; - unsigned long long __r29; - unsigned long long __r30; - unsigned long long __r31; - - unsigned int __cr; /* Condition register */ - unsigned long long __xer; /* User's integer exception register */ - unsigned long long __lr; /* Link register */ - unsigned long long __ctr; /* Count register */ - - unsigned int __vrsave; /* Vector Save Register */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_PPC_THREAD_STATE64 struct ppc_thread_state64 -_STRUCT_PPC_THREAD_STATE64 -{ - unsigned long long srr0; /* Instruction address register (PC) */ - unsigned long long srr1; /* Machine state register (supervisor) */ - unsigned long long r0; - unsigned long long r1; - unsigned long long r2; - unsigned long long r3; - unsigned long long r4; - unsigned long long r5; - unsigned long long r6; - unsigned long long r7; - unsigned long long r8; - unsigned long long r9; - unsigned long long r10; - unsigned long long r11; - unsigned long long r12; - unsigned long long r13; - unsigned long long r14; - unsigned long long r15; - unsigned long long r16; - unsigned long long r17; - unsigned long long r18; - unsigned long long r19; - unsigned long long r20; - unsigned long long r21; - unsigned long long r22; - unsigned long long r23; - unsigned long long r24; - unsigned long long r25; - unsigned long long r26; - unsigned long long r27; - unsigned long long r28; - unsigned long long r29; - unsigned long long r30; - unsigned long long r31; - - unsigned int cr; /* Condition register */ - unsigned long long xer; /* User's integer exception register */ - unsigned long long lr; /* Link register */ - unsigned long long ctr; /* Count register */ - - unsigned int vrsave; /* Vector Save Register */ -}; -#endif /* __DARWIN_UNIX03 */ - -#pragma pack() - -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -/* This structure should be double-word aligned for performance */ - -#if __DARWIN_UNIX03 -#define _STRUCT_PPC_FLOAT_STATE struct __darwin_ppc_float_state -_STRUCT_PPC_FLOAT_STATE -{ - double __fpregs[32]; - - unsigned int __fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ - unsigned int __fpscr; /* floating point status register */ -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_PPC_FLOAT_STATE struct ppc_float_state -_STRUCT_PPC_FLOAT_STATE -{ - double fpregs[32]; - - unsigned int fpscr_pad; /* fpscr is 64 bits, 32 bits of rubbish */ - unsigned int fpscr; /* floating point status register */ -}; -#endif /* __DARWIN_UNIX03 */ - -#pragma pack(4) /* Make sure the structure stays as we defined it */ - -#if __DARWIN_UNIX03 -#define _STRUCT_PPC_VECTOR_STATE struct __darwin_ppc_vector_state -_STRUCT_PPC_VECTOR_STATE -{ -#if defined(__LP64__) - unsigned int __save_vr[32][4]; - unsigned int __save_vscr[4]; -#else - unsigned long __save_vr[32][4]; - unsigned long __save_vscr[4]; -#endif - unsigned int __save_pad5[4]; - unsigned int __save_vrvalid; /* VRs that have been saved */ - unsigned int __save_pad6[7]; -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_PPC_VECTOR_STATE struct ppc_vector_state -_STRUCT_PPC_VECTOR_STATE -{ -#if defined(__LP64__) - unsigned int save_vr[32][4]; - unsigned int save_vscr[4]; -#else - unsigned long save_vr[32][4]; - unsigned long save_vscr[4]; -#endif - unsigned int save_pad5[4]; - unsigned int save_vrvalid; /* VRs that have been saved */ - unsigned int save_pad6[7]; -}; -#endif /* __DARWIN_UNIX03 */ - -#pragma pack() - -/* - * ppc_exception_state - * - * This structure corresponds to some additional state of the user - * registers as saved in the PCB upon kernel entry. They are only - * available if an exception is passed out of the kernel, and even - * then not all are guaranteed to be updated. - * - * Some padding is included in this structure which allows space for - * servers to store temporary values if need be, to maintain binary - * compatiblity. - */ - -/* Exception state for 32-bit thread (on 32-bit processor) */ -/* Still available on 64-bit processors, but may fall short */ -/* of covering the full potential state (hi half available). */ - -#pragma pack(4) /* Make sure the structure stays as we defined it */ - -#if __DARWIN_UNIX03 -#define _STRUCT_PPC_EXCEPTION_STATE struct __darwin_ppc_exception_state -_STRUCT_PPC_EXCEPTION_STATE -{ -#if defined(__LP64__) - unsigned int __dar; /* Fault registers for coredump */ - unsigned int __dsisr; - unsigned int __exception; /* number of powerpc exception taken */ - unsigned int __pad0; /* align to 16 bytes */ - unsigned int __pad1[4]; /* space in PCB "just in case" */ -#else - unsigned long __dar; /* Fault registers for coredump */ - unsigned long __dsisr; - unsigned long __exception; /* number of powerpc exception taken */ - unsigned long __pad0; /* align to 16 bytes */ - unsigned long __pad1[4]; /* space in PCB "just in case" */ -#endif -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_PPC_EXCEPTION_STATE struct ppc_exception_state -_STRUCT_PPC_EXCEPTION_STATE -{ -#if defined(__LP64__) - unsigned int dar; /* Fault registers for coredump */ - unsigned int dsisr; - unsigned int exception; /* number of powerpc exception taken */ - unsigned int pad0; /* align to 16 bytes */ - unsigned int pad1[4]; /* space in PCB "just in case" */ -#else - unsigned long dar; /* Fault registers for coredump */ - unsigned long dsisr; - unsigned long exception; /* number of powerpc exception taken */ - unsigned long pad0; /* align to 16 bytes */ - unsigned long pad1[4]; /* space in PCB "just in case" */ -#endif -}; -#endif /* __DARWIN_UNIX03 */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#if __DARWIN_UNIX03 -#define _STRUCT_PPC_EXCEPTION_STATE64 struct __darwin_ppc_exception_state64 -_STRUCT_PPC_EXCEPTION_STATE64 -{ - unsigned long long __dar; /* Fault registers for coredump */ -#if defined(__LP64__) - unsigned int __dsisr; - unsigned int __exception; /* number of powerpc exception taken */ - unsigned int __pad1[4]; /* space in PCB "just in case" */ -#else - unsigned long __dsisr; - unsigned long __exception; /* number of powerpc exception taken */ - unsigned long __pad1[4]; /* space in PCB "just in case" */ -#endif -}; -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_PPC_EXCEPTION_STATE64 struct ppc_exception_state64 -_STRUCT_PPC_EXCEPTION_STATE64 -{ - unsigned long long dar; /* Fault registers for coredump */ -#if defined(__LP64__) - unsigned int dsisr; - unsigned int exception; /* number of powerpc exception taken */ - unsigned int pad1[4]; /* space in PCB "just in case" */ -#else - unsigned long dsisr; - unsigned long exception; /* number of powerpc exception taken */ - unsigned long pad1[4]; /* space in PCB "just in case" */ -#endif -}; -#endif /* __DARWIN_UNIX03 */ -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -#pragma pack() - -#endif /* _MACH_PPC__STRUCTS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/ppc/boolean.h b/idasdk75/ldr/mach-o/h/mach/ppc/boolean.h deleted file mode 100644 index cfa70c5..0000000 --- a/idasdk75/ldr/mach-o/h/mach/ppc/boolean.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: boolean.h - * - * Boolean type, for ppc. - */ - -#ifndef _MACH_PPC_BOOLEAN_H_ -#define _MACH_PPC_BOOLEAN_H_ - -#if defined(__ppc64__) -typedef unsigned int boolean_t; -#else -typedef int boolean_t; -#endif - -#endif /* _MACH_PPC_BOOLEAN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/ppc/kern_return.h b/idasdk75/ldr/mach-o/h/mach/ppc/kern_return.h deleted file mode 100644 index 9697513..0000000 --- a/idasdk75/ldr/mach-o/h/mach/ppc/kern_return.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: kern_return.h - * Author: Avadis Tevanian, Jr., Michael Wayne Young - * Date: 1985 - * - * Machine-dependent kernel return definitions. - */ - -#ifndef _MACH_PPC_KERN_RETURN_H_ -#define _MACH_PPC_KERN_RETURN_H_ - -#ifndef ASSEMBLER -typedef int kern_return_t; -#endif /* ASSEMBLER */ - -#endif /* _MACH_PPC_KERN_RETURN_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/ppc/thread_status.h b/idasdk75/ldr/mach-o/h/mach/ppc/thread_status.h deleted file mode 100644 index c165314..0000000 --- a/idasdk75/ldr/mach-o/h/mach/ppc/thread_status.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ - -#ifndef _MACH_PPC_THREAD_STATUS_H_ -#define _MACH_PPC_THREAD_STATUS_H_ - -#include <mach/ppc/_structs.h> -#include <mach/message.h> - -/* - * ppc_thread_state is the structure that is exported to user threads for - * use in status/mutate calls. This structure should never change. - * - */ - -#define PPC_THREAD_STATE 1 -#define PPC_FLOAT_STATE 2 -#define PPC_EXCEPTION_STATE 3 -#define PPC_VECTOR_STATE 4 -#define PPC_THREAD_STATE64 5 -#define PPC_EXCEPTION_STATE64 6 -#define THREAD_STATE_NONE 7 - -/* - * VALID_THREAD_STATE_FLAVOR is a platform specific macro that when passed - * an exception flavor will return whether that is a defined flavor for - * that platform. - * The macro must be manually updated to include all of the valid exception - * flavors as defined above. - */ -#define VALID_THREAD_STATE_FLAVOR(x) \ - ((x == PPC_THREAD_STATE) || \ - (x == PPC_FLOAT_STATE) || \ - (x == PPC_EXCEPTION_STATE) || \ - (x == PPC_VECTOR_STATE) || \ - (x == PPC_THREAD_STATE64) || \ - (x == PPC_EXCEPTION_STATE64) || \ - (x == THREAD_STATE_NONE)) - -typedef _STRUCT_PPC_THREAD_STATE ppc_thread_state_t; -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -typedef _STRUCT_PPC_THREAD_STATE64 ppc_thread_state64_t; -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ -typedef _STRUCT_PPC_FLOAT_STATE ppc_float_state_t; -typedef _STRUCT_PPC_VECTOR_STATE ppc_vector_state_t; - -/* - * saved state structure - * - * This structure corresponds to the saved state. - * - */ - -#ifdef MACH__POSIX_C_SOURCE_PRIVATE - -#include <ppc/savearea.h> - -typedef struct savearea ppc_saved_state_t; - -#else /* MACH__POSIX_C_SOURCE_PRIVATE */ - -typedef struct ppc_thread_state ppc_saved_state_t; - -#endif /* MACH__POSIX_C_SOURCE_PRIVATE */ - -/* - * ppc_exception_state - * - * This structure corresponds to some additional state of the user - * registers as saved in the PCB upon kernel entry. They are only - * available if an exception is passed out of the kernel, and even - * then not all are guaranteed to be updated. - * - * Some padding is included in this structure which allows space for - * servers to store temporary values if need be, to maintain binary - * compatiblity. - */ - -/* Exception state for 32-bit thread (on 32-bit processor) */ -/* Still available on 64-bit processors, but may fall short */ -/* of covering the full potential state (hi half available). */ - -typedef _STRUCT_PPC_EXCEPTION_STATE ppc_exception_state_t; -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -typedef _STRUCT_PPC_EXCEPTION_STATE64 ppc_exception_state64_t; -#endif /* (_POSIX_C_SOURCE && !_DARWIN_C_SOURCE) */ - -/* - * Save State Flags - */ - -#define PPC_THREAD_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(ppc_thread_state_t) / sizeof(int))) - -#define PPC_THREAD_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof(ppc_thread_state64_t) / sizeof(int))) - -#define PPC_EXCEPTION_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(ppc_exception_state_t) / sizeof(int))) - -#define PPC_EXCEPTION_STATE64_COUNT ((mach_msg_type_number_t) \ - (sizeof(ppc_exception_state64_t) / sizeof(int))) - -#define PPC_FLOAT_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(ppc_float_state_t) / sizeof(int))) - -#define PPC_VECTOR_STATE_COUNT ((mach_msg_type_number_t) \ - (sizeof(ppc_vector_state_t) / sizeof(int))) - -/* - * Machine-independent way for servers and Mach's exception mechanism to - * choose the most efficient state flavor for exception RPC's: - */ -#define MACHINE_THREAD_STATE PPC_THREAD_STATE -#define MACHINE_THREAD_STATE_COUNT PPC_THREAD_STATE_COUNT - -/* - * Largest state on this machine: - */ -#define THREAD_MACHINE_STATE_MAX THREAD_STATE_MAX - -#endif /* _MACH_PPC_THREAD_STATUS_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/ppc/vm_param.h b/idasdk75/ldr/mach-o/h/mach/ppc/vm_param.h deleted file mode 100644 index 15a1afb..0000000 --- a/idasdk75/ldr/mach-o/h/mach/ppc/vm_param.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ - -#ifndef _MACH_PPC_VM_PARAM_H_ -#define _MACH_PPC_VM_PARAM_H_ - -/* - * These are the global definitions - */ - -#define BYTE_SIZE 8 /* byte size in bits */ - -#define PPC_PGBYTES 4096 /* bytes per ppc page */ -#define PPC_PGSHIFT 12 /* number of bits to shift for pages */ - -#define PAGE_SIZE PPC_PGBYTES -#define PAGE_SHIFT PPC_PGSHIFT -#define PAGE_MASK (PAGE_SIZE - 1) - -#if 0 -#define VM_MAX_PAGE_ADDRESS 0xFFFFFFFFFFFFF000ULL -#else -/* - * LP64todo - For now, we are limited to 51-bits of user addressing - */ -#define VM_MAX_PAGE_ADDRESS 0x0007FFFFFFFFF000ULL -#endif - -#define MACH_VM_MIN_ADDRESS ((mach_vm_offset_t) 0) -#define MACH_VM_MAX_ADDRESS ((mach_vm_offset_t) VM_MAX_PAGE_ADDRESS) - -/* - * These are the values relative to the local process. - */ -#if defined (__ppc64__) -/* - * LP64todo - We don't have the 64-bit address space layout yet. - * Use the 32-bit stack layout for now. - */ -#define VM_MIN_ADDRESS ((vm_offset_t) MACH_VM_MIN_ADDRESS) -#define VM_MAX_ADDRESS ((vm_offset_t) MACH_VM_MAX_ADDRESS) -#define USER_STACK_END ((vm_offset_t) 0x00000000ffff0000ULL) -#else -#define VM_MIN_ADDRESS ((vm_offset_t) 0) -#define VM_MAX_ADDRESS ((vm_offset_t) (VM_MAX_PAGE_ADDRESS & 0xFFFFFFFF)) -#define USER_STACK_END ((vm_offset_t) 0xffff0000U) -#endif /* defined(__ppc64__) */ - - -#endif /* _MACH_PPC_VM_PARAM_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/ppc/vm_types.h b/idasdk75/ldr/mach-o/h/mach/ppc/vm_types.h deleted file mode 100644 index bc01386..0000000 --- a/idasdk75/ldr/mach-o/h/mach/ppc/vm_types.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ - -/* - * File: vm_types.h - * Author: Avadis Tevanian, Jr. - * Date: 1985 - * - * Header file for VM data types. PPC version. - */ - -#ifndef _MACH_PPC_VM_TYPES_H_ -#define _MACH_PPC_VM_TYPES_H_ - -#ifndef ASSEMBLER - -#include <ppc/_types.h> -#include <mach/ppc/vm_param.h> -#include <stdint.h> - -/* - * natural_t and integer_t are Mach's legacy types for machine- - * independent integer types (unsigned, and signed, respectively). - * Their original purpose was to define other types in a machine/ - * compiler independent way. - * - * They also had an implicit "same size as pointer" characteristic - * to them (i.e. Mach's traditional types are very ILP32 or ILP64 - * centric). We support PowerPC ABIs that do not follow either of - * these models (specifically LP64). Therefore, we had to make a - * choice between making these types scale with pointers or stay - * tied to integers. Because their use is predominantly tied to - * to the size of an integer, we are keeping that association and - * breaking free from pointer size guarantees. - * - * New use of these types is discouraged. - */ -typedef __darwin_natural_t natural_t; -typedef int integer_t; - -#if defined(__ppc__) - -/* - * For 32-bit PowerPC ABIs, the scalable types were - * always based upon natural_t (unsigned int). - * Because of potential legacy issues with name mangling, - * we cannot use the stdint uintptr_t type. - */ -typedef natural_t vm_offset_t; -typedef natural_t vm_size_t; - -#else /* __ppc64__ */ - -/* - * For 64-bit PowerPC ABIs, we have no legacy name mangling - * issues, so we use the stdint types for scaling these - * types to the same size as a pointer. - */ -typedef uintptr_t vm_offset_t; -typedef uintptr_t vm_size_t; - -#endif - -/* - * This new type is independent of a particular vm map's - * implementation size - and represents appropriate types - * for all possible maps. This is used for interfaces - * where the size of the map is not known - or we don't - * want to have to distinguish. - */ -typedef uint64_t mach_vm_address_t; -typedef uint64_t mach_vm_offset_t; -typedef uint64_t mach_vm_size_t; - -typedef uint64_t vm_map_offset_t; -typedef uint64_t vm_map_address_t; -typedef uint64_t vm_map_size_t; - - -#endif /* ASSEMBLER */ - -/* - * If composing messages by hand (please do not) - */ -#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32 - -#endif /* _MACH_PPC_VM_TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/shared_region.h b/idasdk75/ldr/mach-o/h/mach/shared_region.h deleted file mode 100644 index 073844f..0000000 --- a/idasdk75/ldr/mach-o/h/mach/shared_region.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2007 Apple Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * - * File: mach/shared_region.h - * - * protos and struct definitions for shared region - */ - -#ifndef _MACH_SHARED_REGION_H_ -#define _MACH_SHARED_REGION_H_ - -#include <sys/cdefs.h> -#include <mach/vm_prot.h> -#include <mach/vm_types.h> -#include <mach/mach_types.h> - -#define SHARED_REGION_BASE_I386 0x90000000ULL -#define SHARED_REGION_SIZE_I386 0x20000000ULL -#define SHARED_REGION_NESTING_BASE_I386 0x90000000ULL -#define SHARED_REGION_NESTING_SIZE_I386 0x20000000ULL -#define SHARED_REGION_NESTING_MIN_I386 0x00200000ULL -#define SHARED_REGION_NESTING_MAX_I386 0xFFE00000ULL - -#define SHARED_REGION_BASE_X86_64 0x00007FFF70000000ULL -#define SHARED_REGION_SIZE_X86_64 0x000000008FE00000ULL -#define SHARED_REGION_NESTING_BASE_X86_64 0x00007FFF80000000ULL -#define SHARED_REGION_NESTING_SIZE_X86_64 0x0000000040000000ULL -#define SHARED_REGION_NESTING_MIN_X86_64 0x0000000000200000ULL -#define SHARED_REGION_NESTING_MAX_X86_64 0xFFFFFFFFFFE00000ULL - -#define SHARED_REGION_BASE_PPC 0x90000000ULL -#define SHARED_REGION_SIZE_PPC 0x20000000ULL -#define SHARED_REGION_NESTING_BASE_PPC 0x90000000ULL -#define SHARED_REGION_NESTING_SIZE_PPC 0x10000000ULL -#define SHARED_REGION_NESTING_MIN_PPC 0x10000000ULL -#define SHARED_REGION_NESTING_MAX_PPC 0x10000000ULL - -#define SHARED_REGION_BASE_PPC64 0x00007FFF60000000ULL -#define SHARED_REGION_SIZE_PPC64 0x00000000A0000000ULL -#define SHARED_REGION_NESTING_BASE_PPC64 0x00007FFF60000000ULL -#define SHARED_REGION_NESTING_SIZE_PPC64 0x00000000A0000000ULL -#define SHARED_REGION_NESTING_MIN_PPC64 0x0000000010000000ULL -#define SHARED_REGION_NESTING_MAX_PPC64 0x0000000010000000ULL - -#define SHARED_REGION_BASE_ARM 0x30000000ULL -#define SHARED_REGION_SIZE_ARM 0x10000000ULL -#define SHARED_REGION_NESTING_BASE_ARM 0x30000000ULL -#define SHARED_REGION_NESTING_SIZE_ARM 0x10000000ULL -#define SHARED_REGION_NESTING_MIN_ARM ? -#define SHARED_REGION_NESTING_MAX_ARM ? - -#if defined(__i386__) -#define SHARED_REGION_BASE SHARED_REGION_BASE_I386 -#define SHARED_REGION_SIZE SHARED_REGION_SIZE_I386 -#define SHARED_REGION_NESTING_BASE SHARED_REGION_NESTING_BASE_I386 -#define SHARED_REGION_NESTING_SIZE SHARED_REGION_NESTING_SIZE_I386 -#define SHARED_REGION_NESTING_MIN SHARED_REGION_NESTING_MIN_I386 -#define SHARED_REGION_NESTING_MAX SHARED_REGION_NESTING_MAX_I386 -#elif defined(__x86_64__) -#define SHARED_REGION_BASE SHARED_REGION_BASE_X86_64 -#define SHARED_REGION_SIZE SHARED_REGION_SIZE_X86_64 -#define SHARED_REGION_NESTING_BASE SHARED_REGION_NESTING_BASE_X86_64 -#define SHARED_REGION_NESTING_SIZE SHARED_REGION_NESTING_SIZE_X86_64 -#define SHARED_REGION_NESTING_MIN SHARED_REGION_NESTING_MIN_X86_64 -#define SHARED_REGION_NESTING_MAX SHARED_REGION_NESTING_MAX_X86_64 -#elif defined(__ppc__) -#define SHARED_REGION_BASE SHARED_REGION_BASE_PPC -#define SHARED_REGION_SIZE SHARED_REGION_SIZE_PPC -#define SHARED_REGION_NESTING_BASE SHARED_REGION_NESTING_BASE_PPC -#define SHARED_REGION_NESTING_SIZE SHARED_REGION_NESTING_SIZE_PPC -#define SHARED_REGION_NESTING_MIN SHARED_REGION_NESTING_MIN_PPC -#define SHARED_REGION_NESTING_MAX SHARED_REGION_NESTING_MAX_PPC -#elif defined(__ppc64__) -#define SHARED_REGION_BASE SHARED_REGION_BASE_PPC64 -#define SHARED_REGION_SIZE SHARED_REGION_SIZE_PPC64 -#define SHARED_REGION_NESTING_BASE SHARED_REGION_NESTING_BASE_PPC64 -#define SHARED_REGION_NESTING_SIZE SHARED_REGION_NESTING_SIZE_PPC64 -#define SHARED_REGION_NESTING_MIN SHARED_REGION_NESTING_MIN_PPC64 -#define SHARED_REGION_NESTING_MAX SHARED_REGION_NESTING_MAX_PPC64 -#elif defined(__arm__) -#define SHARED_REGION_BASE SHARED_REGION_BASE_ARM -#define SHARED_REGION_SIZE SHARED_REGION_SIZE_ARM -#define SHARED_REGION_NESTING_BASE SHARED_REGION_NESTING_BASE_ARM -#define SHARED_REGION_NESTING_SIZE SHARED_REGION_NESTING_SIZE_ARM -#define SHARED_REGION_NESTING_MIN SHARED_REGION_NESTING_MIN_ARM -#define SHARED_REGION_NESTING_MAX SHARED_REGION_NESTING_MAX_ARM -#endif - -/* - * All shared_region_* declarations are a private interface - * between dyld and the kernel. - * - */ -struct shared_file_mapping_np { - mach_vm_address_t sfm_address; - mach_vm_size_t sfm_size; - mach_vm_offset_t sfm_file_offset; - vm_prot_t sfm_max_prot; - vm_prot_t sfm_init_prot; -}; -#define VM_PROT_COW 0x8 /* must not interfere with normal prot assignments */ -#define VM_PROT_ZF 0x10 /* must not interfere with normal prot assignments */ -#define VM_PROT_SLIDE 0x20 /* must not interfere with normal prot assignments */ - - -__BEGIN_DECLS -int shared_region_check_np(uint64_t *startaddress); -int shared_region_map_np(int fd, - uint32_t mappingCount, - const struct shared_file_mapping_np *mappings); -int shared_region_slide_np(void); -__END_DECLS - - -#endif /* _MACH_SHARED_REGION_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/vm_prot.h b/idasdk75/ldr/mach-o/h/mach/vm_prot.h deleted file mode 100644 index 2a5c54f..0000000 --- a/idasdk75/ldr/mach-o/h/mach/vm_prot.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - */ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie Mellon - * the rights to redistribute these changes. - */ -/* - */ -/* - * File: mach/vm_prot.h - * Author: Avadis Tevanian, Jr., Michael Wayne Young - * - * Virtual memory protection definitions. - * - */ - -#ifndef _MACH_VM_PROT_H_ -#define _MACH_VM_PROT_H_ - -/* - * Types defined: - * - * vm_prot_t VM protection values. - */ - -typedef int vm_prot_t; - -/* - * Protection values, defined as bits within the vm_prot_t type - */ - -#define VM_PROT_NONE ((vm_prot_t) 0x00) - -#define VM_PROT_READ ((vm_prot_t) 0x01) /* read permission */ -#define VM_PROT_WRITE ((vm_prot_t) 0x02) /* write permission */ -#define VM_PROT_EXECUTE ((vm_prot_t) 0x04) /* execute permission */ - -/* - * The default protection for newly-created virtual memory - */ - -#define VM_PROT_DEFAULT (VM_PROT_READ|VM_PROT_WRITE) - -/* - * The maximum privileges possible, for parameter checking. - */ - -#define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE) - -/* - * An invalid protection value. - * Used only by memory_object_lock_request to indicate no change - * to page locks. Using -1 here is a bad idea because it - * looks like VM_PROT_ALL and then some. - */ - -#define VM_PROT_NO_CHANGE ((vm_prot_t) 0x08) - -/* - * When a caller finds that he cannot obtain write permission on a - * mapped entry, the following flag can be used. The entry will - * be made "needs copy" effectively copying the object (using COW), - * and write permission will be added to the maximum protections - * for the associated entry. - */ - -#define VM_PROT_COPY ((vm_prot_t) 0x10) - - -/* - * Another invalid protection value. - * Used only by memory_object_data_request upon an object - * which has specified a copy_call copy strategy. It is used - * when the kernel wants a page belonging to a copy of the - * object, and is only asking the object as a result of - * following a shadow chain. This solves the race between pages - * being pushed up by the memory manager and the kernel - * walking down the shadow chain. - */ - -#define VM_PROT_WANTS_COPY ((vm_prot_t) 0x10) - - -/* - * Another invalid protection value. - * Indicates that the other protection bits are to be applied as a mask - * against the actual protection bits of the map entry. - */ -#define VM_PROT_IS_MASK ((vm_prot_t) 0x40) - -#endif /* _MACH_VM_PROT_H_ */ diff --git a/idasdk75/ldr/mach-o/h/mach/vm_types.h b/idasdk75/ldr/mach-o/h/mach/vm_types.h deleted file mode 100644 index 37f4bd5..0000000 --- a/idasdk75/ldr/mach-o/h/mach/vm_types.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* - * @OSF_COPYRIGHT@ - * - */ -#ifndef _MACH_VM_TYPES_H_ -#define _MACH_VM_TYPES_H_ - -#include <mach/port.h> -#include <mach/machine/vm_types.h> - -#include <stdint.h> - -typedef vm_offset_t pointer_t; -typedef vm_offset_t vm_address_t; - -/* - * We use addr64_t for 64-bit addresses that are used on both - * 32 and 64-bit machines. On PPC, they are passed and returned as - * two adjacent 32-bit GPRs. We use addr64_t in places where - * common code must be useable both on 32 and 64-bit machines. - */ -typedef uint64_t addr64_t; /* Basic effective address */ - -/* - * We use reg64_t for addresses that are 32 bits on a 32-bit - * machine, and 64 bits on a 64-bit machine, but are always - * passed and returned in a single GPR on PPC. This type - * cannot be used in generic 32-bit c, since on a 64-bit - * machine the upper half of the register will be ignored - * by the c compiler in 32-bit mode. In c, we can only use the - * type in prototypes of functions that are written in and called - * from assembly language. This type is basically a comment. - */ -typedef uint32_t reg64_t; - -/* - * To minimize the use of 64-bit fields, we keep some physical - * addresses (that are page aligned) as 32-bit page numbers. - * This limits the physical address space to 16TB of RAM. - */ -typedef uint32_t ppnum_t; /* Physical page number */ -#define PPNUM_MAX UINT32_MAX - - - -typedef mach_port_t vm_map_t; - - -#define VM_MAP_NULL ((vm_map_t) 0) - -/* - * Evolving definitions, likely to change. - */ - -typedef uint64_t vm_object_offset_t; -typedef uint64_t vm_object_size_t; - - -typedef mach_port_t upl_t; -typedef mach_port_t vm_named_entry_t; - - -#define UPL_NULL ((upl_t) 0) -#define VM_NAMED_ENTRY_NULL ((vm_named_entry_t) 0) - -#endif /* _MACH_VM_TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/machine/_types.h b/idasdk75/ldr/mach-o/h/machine/_types.h deleted file mode 100644 index 9f2d6d2..0000000 --- a/idasdk75/ldr/mach-o/h/machine/_types.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -#ifndef _BSD_MACHINE__TYPES_H_ -#define _BSD_MACHINE__TYPES_H_ - -#if defined (__ppc__) || defined (__ppc64__) -#include "ppc/_types.h" -#elif defined (__i386__) || defined(__x86_64__) -#include "i386/_types.h" -#elif defined (__arm__) -#include "arm/_types.h" -#else -#error architecture not supported -#endif - -#endif /* _BSD_MACHINE__TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/ppc/_types.h b/idasdk75/ldr/mach-o/h/ppc/_types.h deleted file mode 100644 index 9fd6b20..0000000 --- a/idasdk75/ldr/mach-o/h/ppc/_types.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -#ifndef _BSD_PPC__TYPES_H_ -#define _BSD_PPC__TYPES_H_ - -/* - * This header file contains integer types. It's intended to also contain - * flotaing point and other arithmetic types, as needed, later. - */ - -#ifndef __LINUX__ -#ifdef __GNUC__ -typedef __signed char __int8_t; -#else /* !__GNUC__ */ -typedef char __int8_t; -#endif /* !__GNUC__ */ -typedef unsigned char __uint8_t; -typedef short __int16_t; -typedef unsigned short __uint16_t; -typedef int __int32_t; -typedef unsigned int __uint32_t; -typedef long long __int64_t; -typedef unsigned long long __uint64_t; -#endif - -typedef long __darwin_intptr_t; -typedef unsigned int __darwin_natural_t; - -/* - * The rune type below is declared to be an ``int'' instead of the more natural - * ``unsigned long'' or ``long''. Two things are happening here. It is not - * unsigned so that EOF (-1) can be naturally assigned to it and used. Also, - * it looks like 10646 will be a 31 bit standard. This means that if your - * ints cannot hold 32 bits, you will be in trouble. The reason an int was - * chosen over a long is that the is*() and to*() routines take ints (says - * ANSI C), but they use __darwin_ct_rune_t instead of int. By changing it - * here, you lose a bit of ANSI conformance, but your programs will still - * work. - * - * NOTE: rune_t is not covered by ANSI nor other standards, and should not - * be instantiated outside of lib/libc/locale. Use wchar_t. wchar_t and - * rune_t must be the same type. Also wint_t must be no narrower than - * wchar_t, and should also be able to hold all members of the largest - * character set plus one extra value (WEOF). wint_t must be at least 16 bits. - */ - -typedef int __darwin_ct_rune_t; /* ct_rune_t */ - -#ifndef __LINUX__ -/* - * mbstate_t is an opaque object to keep conversion state, during multibyte - * stream conversions. The content must not be referenced by user programs. - */ -typedef union { - char __mbstate8[128]; - long long _mbstateL; /* for alignment */ -} __mbstate_t; -#endif - -typedef __mbstate_t __darwin_mbstate_t; /* mbstate_t */ - -#if defined(__GNUC__) && defined(__PTRDIFF_TYPE__) -typedef __PTRDIFF_TYPE__ __darwin_ptrdiff_t; /* ptr1 - ptr2 */ -#else -typedef int __darwin_ptrdiff_t; /* ptr1 - ptr2 */ -#endif /* __GNUC__ */ - -#if defined(__GNUC__) && defined(__SIZE_TYPE__) -typedef __SIZE_TYPE__ __darwin_size_t; /* sizeof() */ -#else -typedef unsigned long __darwin_size_t; /* sizeof() */ -#endif - -#if (__GNUC__ > 2) -typedef __builtin_va_list __darwin_va_list; /* va_list */ -#else -typedef char * __darwin_va_list; /* va_list */ -#endif - -#if defined(__GNUC__) && defined(__WCHAR_TYPE__) -typedef __WCHAR_TYPE__ __darwin_wchar_t; /* wchar_t */ -#else -typedef __darwin_ct_rune_t __darwin_wchar_t; /* wchar_t */ -#endif - -typedef __darwin_wchar_t __darwin_rune_t; /* rune_t */ - -#if defined(__GNUC__) && defined(__WINT_TYPE__) -typedef __WINT_TYPE__ __darwin_wint_t; /* wint_t */ -#else -typedef __darwin_ct_rune_t __darwin_wint_t; /* wint_t */ -#endif - -typedef unsigned long __darwin_clock_t; /* clock() */ -typedef __uint32_t __darwin_socklen_t; /* socklen_t (duh) */ -typedef long __darwin_ssize_t; /* byte count or error */ -typedef long __darwin_time_t; /* time() */ - -#endif /* _BSD_PPC__TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/ppc/vmparam.h b/idasdk75/ldr/mach-o/h/ppc/vmparam.h deleted file mode 100644 index 8f0ff82..0000000 --- a/idasdk75/ldr/mach-o/h/ppc/vmparam.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _BSD_PPC_VMPARAM_H_ -#define _BSD_PPC_VMPARAM_H_ 1 - -#include <sys/resource.h> - -#define USRSTACK (0xc0000000) - -/* - * put the default 64-bit stack at the max address - * (minus one 32-bit address space for other incidentals) - */ -#define USRSTACK64 (0x00007FFF5FC00000ULL) - -/* - * Virtual memory related constants, all in bytes - */ -#ifndef DFLDSIZ -#define DFLDSIZ (RLIM_INFINITY) /* initial data size limit */ -// XXX Not enforced -//#define DFLDSIZ (6*1024*1024) /* initial data size limit */ -#endif -#ifndef MAXDSIZ -#define MAXDSIZ (RLIM_INFINITY) /* max data size */ -#endif -#ifndef DFLSSIZ -#define DFLSSIZ (8*1024*1024) /* initial stack size limit */ -#endif -#ifndef MAXSSIZ -#define MAXSSIZ (64*1024*1024) /* max stack size */ -#endif -#ifndef DFLCSIZ -#define DFLCSIZ (0) /* initial core size limit */ -#endif -#ifndef MAXCSIZ -#define MAXCSIZ (RLIM_INFINITY) /* max core size */ -#endif - -#endif /* _BSD_PPC_VMPARAM_H_ */ diff --git a/idasdk75/ldr/mach-o/h/sys/_posix_availability.h b/idasdk75/ldr/mach-o/h/sys/_posix_availability.h deleted file mode 100644 index a540f26..0000000 --- a/idasdk75/ldr/mach-o/h/sys/_posix_availability.h +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (c) 2010 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _CDEFS_H_ -# error "Never use <sys/_posix_availability.h> directly. Use <sys/cdefs.h> instead." -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 198808L -#define ___POSIX_C_DEPRECATED_STARTING_198808L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_198808L -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199009L -#define ___POSIX_C_DEPRECATED_STARTING_199009L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_199009L -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199209L -#define ___POSIX_C_DEPRECATED_STARTING_199209L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_199209L -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199309L -#define ___POSIX_C_DEPRECATED_STARTING_199309L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_199309L -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 199506L -#define ___POSIX_C_DEPRECATED_STARTING_199506L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_199506L -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200112L -#define ___POSIX_C_DEPRECATED_STARTING_200112L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_200112L -#endif - -#if !defined(_DARWIN_C_SOURCE) && defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE >= 200809L -#define ___POSIX_C_DEPRECATED_STARTING_200809L __deprecated -#else -#define ___POSIX_C_DEPRECATED_STARTING_200809L -#endif - diff --git a/idasdk75/ldr/mach-o/h/sys/_structs.h b/idasdk75/ldr/mach-o/h/sys/_structs.h deleted file mode 100644 index 96aec55..0000000 --- a/idasdk75/ldr/mach-o/h/sys/_structs.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2004-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include <sys/cdefs.h> -#include <sys/_types.h> - -#ifdef __need_ucontext_t -#ifndef __need_struct_ucontext -#define __need_struct_ucontext -#endif /* __need_struct_ucontext */ -#endif /* __need_ucontext_t */ - -#ifdef __need_ucontext64_t -#ifndef __need_struct_ucontext64 -#define __need_struct_ucontext64 -#endif /* __need_struct_ucontext64 */ -#endif /* __need_ucontext64_t */ - -#ifdef __need_struct_ucontext -#ifndef __need_struct_mcontext -#define __need_struct_mcontext -#endif /* __need_struct_mcontext */ -#endif /* __need_struct_ucontext */ - -#ifdef __need_struct_ucontext64 -#ifndef __need_struct_mcontext64 -#define __need_struct_mcontext64 -#endif /* __need_struct_mcontext64 */ -#endif /* __need_struct_ucontext64 */ - -#if defined(__need_struct_mcontext) || defined(__need_struct_mcontext64) -#include <machine/_structs.h> -#endif /* __need_struct_mcontext || __need_struct_mcontext64 */ - -#if defined(__need_stack_t) || defined(__need_struct_ucontext) || defined(__need_struct_ucontext64) -#ifndef __need_struct_sigaltstack -#define __need_struct_sigaltstack -#endif /* __need_struct_sigaltstack */ -#endif /* __need_stack_t || __need_struct_ucontext || __need_struct_ucontext64 */ - -#ifdef __need_struct_sigaltstack -#undef __need_struct_sigaltstack -/* Structure used in sigaltstack call. */ -#ifndef _STRUCT_SIGALTSTACK -#if __DARWIN_UNIX03 -#define _STRUCT_SIGALTSTACK struct __darwin_sigaltstack -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_SIGALTSTACK struct sigaltstack -#endif /* __DARWIN_UNIX03 */ -_STRUCT_SIGALTSTACK -{ - void *ss_sp; /* signal stack base */ - __darwin_size_t ss_size; /* signal stack length */ - int ss_flags; /* SA_DISABLE and/or SA_ONSTACK */ -}; -#endif /* _STRUCT_SIGALTSTACK */ -#endif /* __need_struct_sigaltstack */ - -#ifdef __need_struct_timespec -#undef __need_struct_timespec -#ifndef _STRUCT_TIMESPEC -#define _STRUCT_TIMESPEC struct timespec -_STRUCT_TIMESPEC -{ - __darwin_time_t tv_sec; - long tv_nsec; -}; -#endif /* _STRUCT_TIMESPEC */ -#endif /* __need_struct_timespec */ - -#ifdef __need_struct_timeval -#undef __need_struct_timeval -#ifndef _STRUCT_TIMEVAL -#define _STRUCT_TIMEVAL struct timeval -_STRUCT_TIMEVAL -{ - __darwin_time_t tv_sec; /* seconds */ - __darwin_suseconds_t tv_usec; /* and microseconds */ -}; -#endif /* _STRUCT_TIMEVAL */ -#endif /* __need_struct_timeval */ - -#ifdef __need_struct_timeval32 -#undef __need_struct_timeval32 -#ifndef _STRUCT_TIMEVAL32 -#define _STRUCT_TIMEVAL32 struct timeval32 -_STRUCT_TIMEVAL32 -{ - __int32_t tv_sec; /* seconds */ - __int32_t tv_usec; /* and microseconds */ -}; -#endif /* _STRUCT_TIMEVAL32 */ -#endif /* __need_struct_timeval32 */ - -#ifdef __need_struct_ucontext -#undef __need_struct_ucontext -#ifndef _STRUCT_UCONTEXT -#if __DARWIN_UNIX03 -#define _STRUCT_UCONTEXT struct __darwin_ucontext -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_UCONTEXT struct ucontext -#endif /* __DARWIN_UNIX03 */ -_STRUCT_UCONTEXT -{ - int uc_onstack; - __darwin_sigset_t uc_sigmask; /* signal mask used by this context */ - _STRUCT_SIGALTSTACK uc_stack; /* stack used by this context */ - _STRUCT_UCONTEXT *uc_link; /* pointer to resuming context */ - __darwin_size_t uc_mcsize; /* size of the machine context passed in */ - _STRUCT_MCONTEXT *uc_mcontext; /* pointer to machine specific context */ -#ifdef _XOPEN_SOURCE - _STRUCT_MCONTEXT __mcontext_data; -#endif /* _XOPEN_SOURCE */ -}; -#endif /* _STRUCT_UCONTEXT */ -#endif /* __need_struct_ucontext */ - -#ifdef __need_struct_ucontext64 -#undef __need_struct_ucontext64 -#ifndef _STRUCT_UCONTEXT64 -#if __DARWIN_UNIX03 -#define _STRUCT_UCONTEXT64 struct __darwin_ucontext64 -#else /* !__DARWIN_UNIX03 */ -#define _STRUCT_UCONTEXT64 struct ucontext64 -#endif /* __DARWIN_UNIX03 */ -_STRUCT_UCONTEXT64 -{ - int uc_onstack; - __darwin_sigset_t uc_sigmask; /* signal mask used by this context */ - _STRUCT_SIGALTSTACK uc_stack; /* stack used by this context */ - _STRUCT_UCONTEXT64 *uc_link; /* pointer to resuming context */ - __darwin_size_t uc_mcsize; /* size of the machine context passed in */ - _STRUCT_MCONTEXT64 *uc_mcontext64; /* pointer to machine specific context */ -}; -#endif /* _STRUCT_UCONTEXT64 */ -#endif /* __need_struct_ucontext64 */ - - -#ifdef __need_fd_set -#undef __need_fd_set -#ifndef _FD_SET -#define _FD_SET -/* - * Select uses bit masks of file descriptors in longs. These macros - * manipulate such bit fields (the filesystem macros use chars). The - * extra protection here is to permit application redefinition above - * the default size. - */ -#ifdef FD_SETSIZE -#define __DARWIN_FD_SETSIZE FD_SETSIZE -#else /* !FD_SETSIZE */ -#define __DARWIN_FD_SETSIZE 1024 -#endif /* FD_SETSIZE */ -#define __DARWIN_NBBY 8 /* bits in a byte */ -#define __DARWIN_NFDBITS (sizeof(__int32_t) * __DARWIN_NBBY) /* bits per mask */ -#define __DARWIN_howmany(x, y) ((((x) % (y)) == 0) ? ((x) / (y)) : (((x) / (y)) + 1)) /* # y's == x bits? */ - -__BEGIN_DECLS -typedef struct fd_set { - __int32_t fds_bits[__DARWIN_howmany(__DARWIN_FD_SETSIZE, __DARWIN_NFDBITS)]; -} fd_set; -__END_DECLS - -/* This inline avoids argument side-effect issues with FD_ISSET() */ -static __inline int -__darwin_fd_isset(int _n, const struct fd_set *_p) -{ - return (_p->fds_bits[_n/__DARWIN_NFDBITS] & (1<<(_n % __DARWIN_NFDBITS))); -} - -#define __DARWIN_FD_SET(n, p) do { int __fd = (n); ((p)->fds_bits[__fd/__DARWIN_NFDBITS] |= (1<<(__fd % __DARWIN_NFDBITS))); } while(0) -#define __DARWIN_FD_CLR(n, p) do { int __fd = (n); ((p)->fds_bits[__fd/__DARWIN_NFDBITS] &= ~(1<<(__fd % __DARWIN_NFDBITS))); } while(0) -#define __DARWIN_FD_ISSET(n, p) __darwin_fd_isset((n), (p)) - -#if __GNUC__ > 3 || __GNUC__ == 3 && __GNUC_MINOR__ >= 3 -/* - * Use the built-in bzero function instead of the library version so that - * we do not pollute the namespace or introduce prototype warnings. - */ -#define __DARWIN_FD_ZERO(p) __builtin_bzero(p, sizeof(*(p))) -#else -#define __DARWIN_FD_ZERO(p) bzero(p, sizeof(*(p))) -#endif - -#define __DARWIN_FD_COPY(f, t) bcopy(f, t, sizeof(*(f))) -#endif /* _FD_SET */ -#endif /* __need_fd_set */ - -#ifdef __need_stack_t -#undef __need_stack_t -#ifndef _STACK_T -#define _STACK_T -typedef _STRUCT_SIGALTSTACK stack_t; /* [???] signal stack */ -#endif /* _STACK_T */ -#endif /* __need_stack_t */ - -#ifdef __need_ucontext_t -#undef __need_ucontext_t -/* user context */ -#ifndef _UCONTEXT_T -#define _UCONTEXT_T -typedef _STRUCT_UCONTEXT ucontext_t; /* [???] user context */ -#endif /* _UCONTEXT_T */ -#endif /* __need_ucontext_t */ - -#ifdef __need_ucontext64_t -#undef __need_ucontext64_t -#ifndef _UCONTEXT64_T -#define _UCONTEXT64_T -typedef _STRUCT_UCONTEXT64 ucontext64_t; /* [???] user context */ -#endif /* _UCONTEXT64_T */ -#endif /* __need_ucontext64_t */ diff --git a/idasdk75/ldr/mach-o/h/sys/_symbol_aliasing.h b/idasdk75/ldr/mach-o/h/sys/_symbol_aliasing.h deleted file mode 100644 index e40cbbf..0000000 --- a/idasdk75/ldr/mach-o/h/sys/_symbol_aliasing.h +++ /dev/null @@ -1,157 +0,0 @@ -/* Copyright (c) 2010 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _CDEFS_H_ -# error "Never use <sys/_symbol_aliasing.h> directly. Use <sys/cdefs.h> instead." -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20000 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_2_0(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_2_0(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20100 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_2_1(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_2_1(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 20200 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_2_2(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_2_2(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 30000 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_3_0(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_3_0(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 30100 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_3_1(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_3_1(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 30200 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_3_2(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_3_2(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 40000 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_0(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_0(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 40100 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_1(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_1(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 40200 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_2(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_2(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 40300 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_3(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_4_3(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 50000 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_5_0(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_5_0(x) -#endif - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ >= 50100 -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_5_1(x) x -#else -#define __DARWIN_ALIAS_STARTING_IPHONE___IPHONE_5_1(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1000 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_0(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_0(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1010 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_1(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_1(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1020 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_2(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_2(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1030 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_3(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_3(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1040 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_4(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_4(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_5(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_5(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1060 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_6(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_6(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1070 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_7(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_7(x) -#endif - -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1080 -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_8(x) x -#else -#define __DARWIN_ALIAS_STARTING_MAC___MAC_10_8(x) -#endif - diff --git a/idasdk75/ldr/mach-o/h/sys/_types.h b/idasdk75/ldr/mach-o/h/sys/_types.h deleted file mode 100644 index 90e19a2..0000000 --- a/idasdk75/ldr/mach-o/h/sys/_types.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2003-2007 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef _SYS__TYPES_H_ -#define _SYS__TYPES_H_ - -#include <sys/cdefs.h> -#include <machine/_types.h> -#include <sys/_pthread/_pthread_types.h> - -/* - * Type definitions; takes common type definitions that must be used - * in multiple header files due to [XSI], removes them from the system - * space, and puts them in the implementation space. - */ - -#ifdef __cplusplus -#ifdef __GNUG__ -#define __DARWIN_NULL __null -#else /* ! __GNUG__ */ -#ifdef __LP64__ -#define __DARWIN_NULL (0L) -#else /* !__LP64__ */ -#define __DARWIN_NULL 0 -#endif /* __LP64__ */ -#endif /* __GNUG__ */ -#else /* ! __cplusplus */ -#define __DARWIN_NULL ((void *)0) -#endif /* __cplusplus */ - -typedef __int64_t __darwin_blkcnt_t; /* total blocks */ -typedef __int32_t __darwin_blksize_t; /* preferred block size */ -typedef __int32_t __darwin_dev_t; /* dev_t */ -typedef unsigned int __darwin_fsblkcnt_t; /* Used by statvfs and fstatvfs */ -typedef unsigned int __darwin_fsfilcnt_t; /* Used by statvfs and fstatvfs */ -typedef __uint32_t __darwin_gid_t; /* [???] process and group IDs */ -typedef __uint32_t __darwin_id_t; /* [XSI] pid_t, uid_t, or gid_t*/ -typedef __uint64_t __darwin_ino64_t; /* [???] Used for 64 bit inodes */ -#if __DARWIN_64_BIT_INO_T -typedef __darwin_ino64_t __darwin_ino_t; /* [???] Used for inodes */ -#else /* !__DARWIN_64_BIT_INO_T */ -typedef __uint32_t __darwin_ino_t; /* [???] Used for inodes */ -#endif /* __DARWIN_64_BIT_INO_T */ -typedef __darwin_natural_t __darwin_mach_port_name_t; /* Used by mach */ -typedef __darwin_mach_port_name_t __darwin_mach_port_t; /* Used by mach */ -typedef __uint16_t __darwin_mode_t; /* [???] Some file attributes */ -typedef __int64_t __darwin_off_t; /* [???] Used for file sizes */ -typedef __int32_t __darwin_pid_t; /* [???] process and group IDs */ -typedef __uint32_t __darwin_sigset_t; /* [???] signal set */ -typedef __int32_t __darwin_suseconds_t; /* [???] microseconds */ -typedef __uint32_t __darwin_uid_t; /* [???] user IDs */ -typedef __uint32_t __darwin_useconds_t; /* [???] microseconds */ -typedef unsigned char __darwin_uuid_t[16]; -typedef char __darwin_uuid_string_t[37]; - -#endif /* _SYS__TYPES_H_ */ diff --git a/idasdk75/ldr/mach-o/h/sys/appleapiopts.h b/idasdk75/ldr/mach-o/h/sys/appleapiopts.h deleted file mode 100644 index 2055701..0000000 --- a/idasdk75/ldr/mach-o/h/sys/appleapiopts.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#ifndef __SYS_APPLEAPIOPTS_H__ -#define __SYS_APPLEAPIOPTS_H__ - - -#ifndef __APPLE_API_STANDARD -#define __APPLE_API_STANDARD -#endif /* __APPLE_API_STANDARD */ - -#ifndef __APPLE_API_STABLE -#define __APPLE_API_STABLE -#endif /* __APPLE_API_STABLE */ - -#ifndef __APPLE_API_STRICT_CONFORMANCE - -#ifndef __APPLE_API_EVOLVING -#define __APPLE_API_EVOLVING -#endif /* __APPLE_API_EVOLVING */ - -#ifndef __APPLE_API_UNSTABLE -#define __APPLE_API_UNSTABLE -#endif /* __APPLE_API_UNSTABLE */ - -#ifndef __APPLE_API_PRIVATE -#define __APPLE_API_PRIVATE -#endif /* __APPLE_API_PRIVATE */ - -#ifndef __APPLE_API_OBSOLETE -#define __APPLE_API_OBSOLETE -#endif /* __APPLE_API_OBSOLETE */ - -#endif /* __APPLE_API_STRICT_CONFORMANCE */ - -#endif /* __SYS_APPLEAPIOPTS_H__ */ - diff --git a/idasdk75/ldr/mach-o/h/sys/cdefs.h b/idasdk75/ldr/mach-o/h/sys/cdefs.h deleted file mode 100644 index 70423e9..0000000 --- a/idasdk75/ldr/mach-o/h/sys/cdefs.h +++ /dev/null @@ -1,780 +0,0 @@ -/* - * Copyright (c) 2000-2009 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* Copyright 1995 NeXT Computer, Inc. All rights reserved. */ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Berkeley Software Design, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 - */ - -#ifndef __LINUX__ - -#ifndef _CDEFS_H_ -#define _CDEFS_H_ - -#if defined(__cplusplus) -#define __BEGIN_DECLS extern "C" { -#define __END_DECLS } -#else -#define __BEGIN_DECLS -#define __END_DECLS -#endif - -/* This SDK is designed to work with clang and specific versions of - * gcc >= 4.0 with Apple's patch sets */ -//#if !defined(__GNUC__) || __GNUC__ < 4 -//#warning "Unsupported compiler detected" -//#endif - -/* - * The __CONCAT macro is used to concatenate parts of symbol names, e.g. - * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. - * The __CONCAT macro is a bit tricky -- make sure you don't put spaces - * in between its arguments. __CONCAT can also concatenate double-quoted - * strings produced by the __STRING macro, but this only works with ANSI C. - */ -#if defined(__STDC__) || defined(__cplusplus) -#define __P(protos) protos /* full-blown ANSI C */ -#define __CONCAT(x,y) x ## y -#define __STRING(x) #x - -#define __const const /* define reserved names to standard */ -#define __signed signed -#ifndef __volatile -#define __volatile volatile -#endif -#if defined(__cplusplus) -#define __inline inline /* convert to C++ keyword */ -#else -#ifndef __GNUC__ -#define __inline /* delete GCC keyword */ -#endif /* !__GNUC__ */ -#endif /* !__cplusplus */ - -#else /* !(__STDC__ || __cplusplus) */ -#define __P(protos) () /* traditional C preprocessor */ -#define __CONCAT(x,y) x/**/y -#define __STRING(x) "x" - -#ifndef __GNUC__ -#define __const /* delete pseudo-ANSI C keywords */ -#define __inline -#define __signed -#define __volatile -#endif /* !__GNUC__ */ - -/* - * In non-ANSI C environments, new programs will want ANSI-only C keywords - * deleted from the program and old programs will want them left alone. - * When using a compiler other than gcc, programs using the ANSI C keywords - * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. - * When using "gcc -traditional", we assume that this is the intent; if - * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. - */ -#ifndef NO_ANSI_KEYWORDS -#define const __const /* convert ANSI C keywords */ -#define inline __inline -#define signed __signed -#define volatile __volatile -#endif /* !NO_ANSI_KEYWORDS */ -#endif /* !(__STDC__ || __cplusplus) */ - -#define __dead2 __attribute__((noreturn)) -#define __pure2 __attribute__((const)) - -/* __unused denotes variables and functions that may not be used, preventing - * the compiler from warning about it if not used. - */ -#define __unused __attribute__((unused)) - -/* __used forces variables and functions to be included even if it appears - * to the compiler that they are not used (and would thust be discarded). - */ -#define __used __attribute__((used)) - -/* __cold marks code used for debugging or that is rarely taken - * and tells the compiler to optimize for size and outline code. - * in IDA we define to nothing since it's mac-specific. - */ -//#if __has_attribute(cold) -//#define __cold __attribute__((__cold__)) -//#else -#define __cold -//#endif - -/* __deprecated causes the compiler to produce a warning when encountering - * code using the deprecated functionality. - * __deprecated_msg() does the same, and compilers that support it will print - * a message along with the deprecation warning. - * This may require turning on such warning with the -Wdeprecated flag. - * __deprecated_enum_msg() should be used on enums, and compilers that support - * it will print the deprecation warning. - */ -#define __deprecated __attribute__((deprecated)) - -#ifdef __has_extension - #if __has_extension(attribute_deprecated_with_message) - #define __deprecated_msg(_msg) __attribute__((deprecated(_msg))) - #else - #define __deprecated_msg(_msg) __attribute__((deprecated)) - #endif -#elif defined(__GNUC__) && ((__GNUC__ >= 5) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5))) - #define __deprecated_msg(_msg) __attribute__((deprecated(_msg))) -#else - #define __deprecated_msg(_msg) __attribute__((deprecated)) -#endif - -#ifdef __has_extension - #if __has_extension(enumerator_attributes) - #define __deprecated_enum_msg(_msg) __deprecated_msg(_msg) - #else - #define __deprecated_enum_msg(_msg) - #endif -#else - #define __deprecated_enum_msg(_msg) -#endif - -/* __unavailable causes the compiler to error out when encountering - * code using the tagged function of variable. - */ -#define __unavailable __attribute__((unavailable)) - -/* Delete pseudo-keywords wherever they are not available or needed. */ -#ifndef __dead -#define __dead -#define __pure -#endif - -/* - * We use `__restrict' as a way to define the `restrict' type qualifier - * without disturbing older software that is unaware of C99 keywords. - */ -#if __STDC_VERSION__ < 199901 -#define __restrict -#else -#define __restrict restrict -#endif - -#ifdef __MAC__ - -// compile with SDK version <= 10.7 -#ifndef __has_attribute -#define __has_attribute(X) 0 -#endif - -#ifndef __has_feature -#define __has_feature(X) 0 -#endif - -/* - * __disable_tail_calls causes the compiler to not perform tail call - * optimization inside the marked function. - */ -#if __has_attribute(disable_tail_calls) -#define __disable_tail_calls __attribute__((__disable_tail_calls__)) -#else -#define __disable_tail_calls -#endif - -/* - * __not_tail_called causes the compiler to prevent tail call optimization - * on statically bound calls to the function. It has no effect on indirect - * calls. Virtual functions, objective-c methods, and functions marked as - * "always_inline" cannot be marked as __not_tail_called. - */ -#if __has_attribute(not_tail_called) -#define __not_tail_called __attribute__((__not_tail_called__)) -#else -#define __not_tail_called -#endif - -/* - * __result_use_check warns callers of a function that not using the function - * return value is a bug, i.e. dismissing malloc() return value results in a - * memory leak. - */ -#if __has_attribute(warn_unused_result) -#define __result_use_check __attribute__((__warn_unused_result__)) -#else -#define __result_use_check -#endif - -/* - * __swift_unavailable causes the compiler to mark a symbol as specifically - * unavailable in Swift, regardless of any other availability in C. - */ -#if __has_feature(attribute_availability_swift) -#define __swift_unavailable(_msg) __attribute__((__availability__(swift, unavailable, message=_msg))) -#else -#define __swift_unavailable(_msg) -#endif - -#endif // __MAC__ - - -/* Declaring inline functions within headers is error-prone due to differences - * across various versions of the C language and extensions. __header_inline - * can be used to declare inline functions within system headers. In cases - * where you want to force inlining instead of letting the compiler make - * the decision, you can use __header_always_inline. - * - * Be aware that using inline for functions which compilers may also provide - * builtins can behave differently under various compilers. If you intend to - * provide an inline version of such a function, you may want to use a macro - * instead. - * - * The check for !__GNUC__ || __clang__ is because gcc doesn't correctly - * support c99 inline in some cases: - * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55965 - */ - -#if defined(__cplusplus) || \ - (__STDC_VERSION__ >= 199901L && \ - !defined(__GNUC_GNU_INLINE__) && \ - (!defined(__GNUC__) || defined(__clang__))) -# define __header_inline inline -#elif defined(__GNUC__) && defined(__GNUC_STDC_INLINE__) -# define __header_inline extern __inline __attribute__((__gnu_inline__)) -#elif defined(__GNUC__) -# define __header_inline extern __inline -#else - /* If we land here, we've encountered an unsupported compiler, - * so hopefully it understands static __inline as a fallback. - */ -# define __header_inline static __inline -#endif - -#ifdef __GNUC__ -# define __header_always_inline __header_inline __attribute__ ((__always_inline__)) -#else - /* Unfortunately, we're using a compiler that we don't know how to force to - * inline. Oh well. - */ -# define __header_always_inline __header_inline -#endif - -/* - * Compiler-dependent macros to declare that functions take printf-like - * or scanf-like arguments. They are null except for versions of gcc - * that are known to support the features properly. Functions declared - * with these attributes will cause compilation warnings if there is a - * mismatch between the format string and subsequent function parameter - * types. - */ -#define __printflike(fmtarg, firstvararg) \ - __attribute__((__format__ (__printf__, fmtarg, firstvararg))) -#define __scanflike(fmtarg, firstvararg) \ - __attribute__((__format__ (__scanf__, fmtarg, firstvararg))) - -#define __IDSTRING(name,string) static const char name[] __used = string - -#ifndef __COPYRIGHT -#define __COPYRIGHT(s) __IDSTRING(copyright,s) -#endif - -#ifndef __RCSID -#define __RCSID(s) __IDSTRING(rcsid,s) -#endif - -#ifndef __SCCSID -#define __SCCSID(s) __IDSTRING(sccsid,s) -#endif - -#ifndef __PROJECT_VERSION -#define __PROJECT_VERSION(s) __IDSTRING(project_version,s) -#endif - -/* Source compatibility only, ID string not emitted in object file */ -#ifndef __FBSDID -#define __FBSDID(s) -#endif - -#ifndef __DECONST -#define __DECONST(type, var) __CAST_AWAY_QUALIFIER(var, const, type) -#endif - -#ifndef __DEVOLATILE -#define __DEVOLATILE(type, var) __CAST_AWAY_QUALIFIER(var, volatile, type) -#endif - -#ifndef __DEQUALIFY -#define __DEQUALIFY(type, var) __CAST_AWAY_QUALIFIER(var, const volatile, type) -#endif - -/* - * __alloc_size can be used to label function arguments that represent the - * size of memory that the function allocates and returns. The one-argument - * form labels a single argument that gives the allocation size (where the - * arguments are numbered from 1): - * - * void *malloc(size_t __size) __alloc_size(1); - * - * The two-argument form handles the case where the size is calculated as the - * product of two arguments: - * - * void *calloc(size_t __count, size_t __size) __alloc_size(1,2); - */ -#ifndef __alloc_size -#if !defined(_MSC_VER) -#if __has_attribute(alloc_size) -#define __alloc_size(...) __attribute__((alloc_size(__VA_ARGS__))) -#else -#define __alloc_size(...) -#endif -#endif // _MSC_VER -#endif // __alloc_size - -/* - * COMPILATION ENVIRONMENTS -- see compat(5) for additional detail - * - * DEFAULT By default newly complied code will get POSIX APIs plus - * Apple API extensions in scope. - * - * Most users will use this compilation environment to avoid - * behavioral differences between 32 and 64 bit code. - * - * LEGACY Defining _NONSTD_SOURCE will get pre-POSIX APIs plus Apple - * API extensions in scope. - * - * This is generally equivalent to the Tiger release compilation - * environment, except that it cannot be applied to 64 bit code; - * its use is discouraged. - * - * We expect this environment to be deprecated in the future. - * - * STRICT Defining _POSIX_C_SOURCE or _XOPEN_SOURCE restricts the - * available APIs to exactly the set of APIs defined by the - * corresponding standard, based on the value defined. - * - * A correct, portable definition for _POSIX_C_SOURCE is 200112L. - * A correct, portable definition for _XOPEN_SOURCE is 600L. - * - * Apple API extensions are not visible in this environment, - * which can cause Apple specific code to fail to compile, - * or behave incorrectly if prototypes are not in scope or - * warnings about missing prototypes are not enabled or ignored. - * - * In any compilation environment, for correct symbol resolution to occur, - * function prototypes must be in scope. It is recommended that all Apple - * tools users add either the "-Wall" or "-Wimplicit-function-declaration" - * compiler flags to their projects to be warned when a function is being - * used without a prototype in scope. - */ - -/* These settings are particular to each product. */ -/* Platform: MacOSX */ -#define __DARWIN_ONLY_64_BIT_INO_T 0 -/* #undef __DARWIN_ONLY_UNIX_CONFORMANCE (automatically set for 64-bit) */ -#define __DARWIN_ONLY_VERS_1050 0 - -/* - * The __DARWIN_ALIAS macros are used to do symbol renaming; they allow - * legacy code to use the old symbol, thus maintaining binary compatibility - * while new code can use a standards compliant version of the same function. - * - * __DARWIN_ALIAS is used by itself if the function signature has not - * changed, it is used along with a #ifdef check for __DARWIN_UNIX03 - * if the signature has changed. Because the __LP64__ environment - * only supports UNIX03 semantics it causes __DARWIN_UNIX03 to be - * defined, but causes __DARWIN_ALIAS to do no symbol mangling. - * - * As a special case, when XCode is used to target a specific version of the - * OS, the manifest constant __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ - * will be defined by the compiler, with the digits representing major version - * time 100 + minor version times 10 (e.g. 10.5 := 1050). If we are targeting - * pre-10.5, and it is the default compilation environment, revert the - * compilation environment to pre-__DARWIN_UNIX03. - */ -#if !defined(__DARWIN_ONLY_UNIX_CONFORMANCE) -# if defined(__LP64__) -# define __DARWIN_ONLY_UNIX_CONFORMANCE 1 -# else /* !__LP64__ */ -# define __DARWIN_ONLY_UNIX_CONFORMANCE 0 -# endif /* __LP64__ */ -#endif /* !__DARWIN_ONLY_UNIX_CONFORMANCE */ - -#if !defined(__DARWIN_UNIX03) -# if __DARWIN_ONLY_UNIX_CONFORMANCE -# if defined(_NONSTD_SOURCE) -# error "Can't define _NONSTD_SOURCE when only UNIX conformance is available." -# endif /* _NONSTD_SOURCE */ -# define __DARWIN_UNIX03 1 -# elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1040) -# define __DARWIN_UNIX03 0 -# elif defined(_DARWIN_C_SOURCE) || defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE) -# if defined(_NONSTD_SOURCE) -# error "Can't define both _NONSTD_SOURCE and any of _DARWIN_C_SOURCE, _XOPEN_SOURCE or _POSIX_C_SOURCE." -# endif /* _NONSTD_SOURCE */ -# define __DARWIN_UNIX03 1 -# elif defined(_NONSTD_SOURCE) -# define __DARWIN_UNIX03 0 -# else /* default */ -# if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1050) -# define __DARWIN_UNIX03 0 -# else /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 */ -# define __DARWIN_UNIX03 1 -# endif /* __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050 */ -# endif /* _DARWIN_C_SOURCE || _XOPEN_SOURCE || _POSIX_C_SOURCE || __LP64__ */ -#endif /* !__DARWIN_UNIX03 */ - -#if !defined(__DARWIN_64_BIT_INO_T) -# if defined(_DARWIN_USE_64_BIT_INODE) -# if defined(_DARWIN_NO_64_BIT_INODE) -# error "Can't define both _DARWIN_USE_64_BIT_INODE and _DARWIN_NO_64_BIT_INODE." -# endif /* _DARWIN_NO_64_BIT_INODE */ -# define __DARWIN_64_BIT_INO_T 1 -# elif defined(_DARWIN_NO_64_BIT_INODE) -# if __DARWIN_ONLY_64_BIT_INO_T -# error "Can't define _DARWIN_NO_64_BIT_INODE when only 64-bit inodes are available." -# endif /* __DARWIN_ONLY_64_BIT_INO_T */ -# define __DARWIN_64_BIT_INO_T 0 -# else /* default */ -# if __DARWIN_ONLY_64_BIT_INO_T -# define __DARWIN_64_BIT_INO_T 1 -# elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1060) || __DARWIN_UNIX03 == 0 -# define __DARWIN_64_BIT_INO_T 0 -# else /* default */ -# define __DARWIN_64_BIT_INO_T 1 -# endif /* __DARWIN_ONLY_64_BIT_INO_T */ -# endif -#endif /* !__DARWIN_64_BIT_INO_T */ - -#if !defined(__DARWIN_VERS_1050) -# if __DARWIN_ONLY_VERS_1050 -# define __DARWIN_VERS_1050 1 -# elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1050) || __DARWIN_UNIX03 == 0 -# define __DARWIN_VERS_1050 0 -# else /* default */ -# define __DARWIN_VERS_1050 1 -# endif -#endif /* !__DARWIN_VERS_1050 */ - -#if !defined(__DARWIN_NON_CANCELABLE) -# define __DARWIN_NON_CANCELABLE 0 -#endif /* !__DARWIN_NON_CANCELABLE */ - -/* - * symbol suffixes used for symbol versioning - */ -#if __DARWIN_UNIX03 -# if __DARWIN_ONLY_UNIX_CONFORMANCE -# define __DARWIN_SUF_UNIX03 /* nothing */ -# else /* !__DARWIN_ONLY_UNIX_CONFORMANCE */ -# define __DARWIN_SUF_UNIX03 "$UNIX2003" -# endif /* __DARWIN_ONLY_UNIX_CONFORMANCE */ - -# if __DARWIN_64_BIT_INO_T -# if __DARWIN_ONLY_64_BIT_INO_T -# define __DARWIN_SUF_64_BIT_INO_T /* nothing */ -# else /* !__DARWIN_ONLY_64_BIT_INO_T */ -# define __DARWIN_SUF_64_BIT_INO_T "$INODE64" -# endif /* __DARWIN_ONLY_64_BIT_INO_T */ -# else /* !__DARWIN_64_BIT_INO_T */ -# define __DARWIN_SUF_64_BIT_INO_T /* nothing */ -# endif /* __DARWIN_64_BIT_INO_T */ - -# if __DARWIN_VERS_1050 -# if __DARWIN_ONLY_VERS_1050 -# define __DARWIN_SUF_1050 /* nothing */ -# else /* !__DARWIN_ONLY_VERS_1050 */ -# define __DARWIN_SUF_1050 "$1050" -# endif /* __DARWIN_ONLY_VERS_1050 */ -# else /* !__DARWIN_VERS_1050 */ -# define __DARWIN_SUF_1050 /* nothing */ -# endif /* __DARWIN_VERS_1050 */ - -# if __DARWIN_NON_CANCELABLE -# define __DARWIN_SUF_NON_CANCELABLE "$NOCANCEL" -# else /* !__DARWIN_NON_CANCELABLE */ -# define __DARWIN_SUF_NON_CANCELABLE /* nothing */ -# endif /* __DARWIN_NON_CANCELABLE */ - -#else /* !__DARWIN_UNIX03 */ -# define __DARWIN_SUF_UNIX03 /* nothing */ -# define __DARWIN_SUF_64_BIT_INO_T /* nothing */ -# define __DARWIN_SUF_NON_CANCELABLE /* nothing */ -# define __DARWIN_SUF_1050 /* nothing */ -#endif /* __DARWIN_UNIX03 */ - -#define __DARWIN_SUF_EXTSN "$DARWIN_EXTSN" - -/* - * symbol versioning macros - */ -#define __DARWIN_ALIAS(sym) __asm("_" __STRING(sym) __DARWIN_SUF_UNIX03) -#define __DARWIN_ALIAS_C(sym) __asm("_" __STRING(sym) __DARWIN_SUF_NON_CANCELABLE __DARWIN_SUF_UNIX03) -#define __DARWIN_ALIAS_I(sym) __asm("_" __STRING(sym) __DARWIN_SUF_64_BIT_INO_T __DARWIN_SUF_UNIX03) -#define __DARWIN_INODE64(sym) __asm("_" __STRING(sym) __DARWIN_SUF_64_BIT_INO_T) - -#define __DARWIN_1050(sym) __asm("_" __STRING(sym) __DARWIN_SUF_1050) -#define __DARWIN_1050ALIAS(sym) __asm("_" __STRING(sym) __DARWIN_SUF_1050 __DARWIN_SUF_UNIX03) -#define __DARWIN_1050ALIAS_C(sym) __asm("_" __STRING(sym) __DARWIN_SUF_1050 __DARWIN_SUF_NON_CANCELABLE __DARWIN_SUF_UNIX03) -#define __DARWIN_1050ALIAS_I(sym) __asm("_" __STRING(sym) __DARWIN_SUF_1050 __DARWIN_SUF_64_BIT_INO_T __DARWIN_SUF_UNIX03) -#define __DARWIN_1050INODE64(sym) __asm("_" __STRING(sym) __DARWIN_SUF_1050 __DARWIN_SUF_64_BIT_INO_T) - -#define __DARWIN_EXTSN(sym) __asm("_" __STRING(sym) __DARWIN_SUF_EXTSN) -#define __DARWIN_EXTSN_C(sym) __asm("_" __STRING(sym) __DARWIN_SUF_EXTSN __DARWIN_SUF_NON_CANCELABLE) - -/* - * symbol release macros - */ -#include "_symbol_aliasing.h" - -#if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__) -#define __DARWIN_ALIAS_STARTING(_mac, _iphone, x) __DARWIN_ALIAS_STARTING_IPHONE_##_iphone(x) -#elif defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) -#define __DARWIN_ALIAS_STARTING(_mac, _iphone, x) __DARWIN_ALIAS_STARTING_MAC_##_mac(x) -#else -#define __DARWIN_ALIAS_STARTING(_mac, _iphone, x) -#endif - -/* - * symbol release macros - */ -#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && ((__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0) < 1060) -#undef __DARWIN_10_6_AND_LATER -#define __DARWIN_10_6_AND_LATER_ALIAS(x) /* nothing */ -#else /* 10.6 and beyond */ -#define __DARWIN_10_6_AND_LATER -#define __DARWIN_10_6_AND_LATER_ALIAS(x) x -#endif - -#define __DARWIN_NOCANCEL(sym) __asm("_" __STRING(sym) __DARWIN_SUF_NON_CANCELABLE) - -/* - * POSIX.1 requires that the macros we test be defined before any standard - * header file is included. This permits us to convert values for feature - * testing, as necessary, using only _POSIX_C_SOURCE. - * - * Here's a quick run-down of the versions: - * defined(_POSIX_SOURCE) 1003.1-1988 - * _POSIX_C_SOURCE == 1L 1003.1-1990 - * _POSIX_C_SOURCE == 2L 1003.2-1992 C Language Binding Option - * _POSIX_C_SOURCE == 199309L 1003.1b-1993 - * _POSIX_C_SOURCE == 199506L 1003.1c-1995, 1003.1i-1995, - * and the omnibus ISO/IEC 9945-1: 1996 - * _POSIX_C_SOURCE == 200112L 1003.1-2001 - * _POSIX_C_SOURCE == 200809L 1003.1-2008 - * - * In addition, the X/Open Portability Guide, which is now the Single UNIX - * Specification, defines a feature-test macro which indicates the version of - * that specification, and which subsumes _POSIX_C_SOURCE. - */ - -/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1L. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1L -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199009L -#endif - -/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2L. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2L -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199209L -#endif - -/* Deal with various X/Open Portability Guides and Single UNIX Spec. */ -#ifdef _XOPEN_SOURCE -#if _XOPEN_SOURCE - 0L >= 700L && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE - 0L < 200809L) -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200809L -#elif _XOPEN_SOURCE - 0L >= 600L && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE - 0L < 200112L) -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112L -#elif _XOPEN_SOURCE - 0L >= 500L && (!defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE - 0L < 199506L) -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199506L -#endif -#endif - -/* - * Deal with all versions of POSIX. The ordering relative to the tests above is - * important. - */ -#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 198808L -#endif - -/* POSIX C deprecation macros */ -#include "_posix_availability.h" - -#define __POSIX_C_DEPRECATED(ver) ___POSIX_C_DEPRECATED_STARTING_##ver - -/* - * Set a single macro which will always be defined and can be used to determine - * the appropriate namespace. For POSIX, these values will correspond to - * _POSIX_C_SOURCE value. Currently there are two additional levels corresponding - * to ANSI (_ANSI_SOURCE) and Darwin extensions (_DARWIN_C_SOURCE) - */ -#define __DARWIN_C_ANSI 010000L -#define __DARWIN_C_FULL 900000L - -#if defined(_ANSI_SOURCE) -#define __DARWIN_C_LEVEL __DARWIN_C_ANSI -#elif defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE) && !defined(_NONSTD_SOURCE) -#define __DARWIN_C_LEVEL _POSIX_C_SOURCE -#else -#define __DARWIN_C_LEVEL __DARWIN_C_FULL -#endif - -/* - * Long double compatibility macro allow selecting variant symbols based - * on the old (compatible) 64-bit long doubles, or the new 128-bit - * long doubles. This applies only to ppc; i386 already has long double - * support, while ppc64 doesn't have any backwards history. - */ -#if defined(__arm__) -# define __DARWIN_LDBL_COMPAT(x) /* nothing */ -# define __DARWIN_LDBL_COMPAT2(x) /* nothing */ -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 1 -#elif defined(__ppc__) -# if defined(__LDBL_MANT_DIG__) && defined(__DBL_MANT_DIG__) && \ - __LDBL_MANT_DIG__ > __DBL_MANT_DIG__ -# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 < 1040 -# define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBLStub") -# else -# define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBL128") -# endif -# define __DARWIN_LDBL_COMPAT2(x) __asm("_" __STRING(x) "$LDBL128") -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0 -# else -# define __DARWIN_LDBL_COMPAT(x) /* nothing */ -# define __DARWIN_LDBL_COMPAT2(x) /* nothing */ -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 1 -# endif -#elif defined(__i386__) || defined(__ppc64__) || defined(__x86_64__) -# define __DARWIN_LDBL_COMPAT(x) /* nothing */ -# define __DARWIN_LDBL_COMPAT2(x) /* nothing */ -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0 -#else -# error Unknown architecture -#endif - -/* - * long long is not supported in c89 (__STRICT_ANSI__), but g++ -ansi and - * c99 still want long longs. While not perfect, we allow long longs for - * g++. - */ -#define __DARWIN_NO_LONG_LONG (defined(__STRICT_ANSI__) \ - && (__STDC_VERSION__-0 < 199901L) \ - && !defined(__GNUG__)) - -/***************************************** - * Public darwin-specific feature macros - *****************************************/ - -/* - * _DARWIN_FEATURE_64_BIT_INODE indicates that the ino_t type is 64-bit, and - * structures modified for 64-bit inodes (like struct stat) will be used. - */ -#if __DARWIN_64_BIT_INO_T -#define _DARWIN_FEATURE_64_BIT_INODE 1 -#endif - -/* - * _DARWIN_FEATURE_64_ONLY_BIT_INODE indicates that the ino_t type may only - * be 64-bit; there is no support for 32-bit ino_t when this macro is defined - * (and non-zero). There is no struct stat64 either, as the regular - * struct stat will already be the 64-bit version. - */ -#if __DARWIN_ONLY_64_BIT_INO_T -#define _DARWIN_FEATURE_ONLY_64_BIT_INODE 1 -#endif - -/* - * _DARWIN_FEATURE_ONLY_VERS_1050 indicates that only those APIs updated - * in 10.5 exists; no pre-10.5 variants are available. - */ -#if __DARWIN_ONLY_VERS_1050 -#define _DARWIN_FEATURE_ONLY_VERS_1050 1 -#endif - -/* - * _DARWIN_FEATURE_ONLY_UNIX_CONFORMANCE indicates only UNIX conforming API - * are available (the legacy BSD APIs are not available) - */ -#if __DARWIN_ONLY_UNIX_CONFORMANCE -#define _DARWIN_FEATURE_ONLY_UNIX_CONFORMANCE 1 -#endif - -/* - * _DARWIN_FEATURE_UNIX_CONFORMANCE indicates whether UNIX conformance is on, - * and specifies the conformance level (3 is SUSv3) - */ -#if __DARWIN_UNIX03 -#define _DARWIN_FEATURE_UNIX_CONFORMANCE 3 -#endif - -/* - * This macro casts away the qualifier from the variable - * - * Note: use at your own risk, removing qualifiers can result in - * catastrophic run-time failures. - */ -#ifndef __CAST_AWAY_QUALIFIER -#define __CAST_AWAY_QUALIFIER(variable, qualifier, type) (type) (long)(variable) -#endif - -#endif /* !_CDEFS_H_ */ -#else - -#include_next <sys/cdefs.h> - -#endif /* !__LINUX__ */ diff --git a/idasdk75/ldr/mach-o/h/sys/ptrace.h b/idasdk75/ldr/mach-o/h/sys/ptrace.h deleted file mode 100644 index 4b5b403..0000000 --- a/idasdk75/ldr/mach-o/h/sys/ptrace.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ -/*- - * Copyright (c) 1984, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ptrace.h 8.2 (Berkeley) 1/4/94 - */ - -#ifndef _SYS_PTRACE_H_ -#define _SYS_PTRACE_H_ - -#include <sys/appleapiopts.h> -#include <sys/cdefs.h> - -#define PT_TRACE_ME 0 /* child declares it's being traced */ -#define PT_READ_I 1 /* read word in child's I space */ -#define PT_READ_D 2 /* read word in child's D space */ -#define PT_READ_U 3 /* read word in child's user structure */ -#define PT_WRITE_I 4 /* write word in child's I space */ -#define PT_WRITE_D 5 /* write word in child's D space */ -#define PT_WRITE_U 6 /* write word in child's user structure */ -#define PT_CONTINUE 7 /* continue the child */ -#define PT_KILL 8 /* kill the child process */ -#define PT_STEP 9 /* single step the child */ -#define PT_ATTACH 10 /* trace some running process */ -#define PT_DETACH 11 /* stop tracing a process */ -#define PT_SIGEXC 12 /* signals as exceptions for current_proc */ -#define PT_THUPDATE 13 /* signal for thread# */ -#define PT_ATTACHEXC 14 /* attach to running process with signal exception */ - -#define PT_FORCEQUOTA 30 /* Enforce quota for root */ -#define PT_DENY_ATTACH 31 - -#define PT_FIRSTMACH 32 /* for machine-specific requests */ - -__BEGIN_DECLS - - -int ptrace(int _request, pid_t _pid, caddr_t _addr, int _data); - - -__END_DECLS - -#endif /* !_SYS_PTRACE_H_ */ diff --git a/idasdk75/ldr/mach-o/h/sys/resource.h b/idasdk75/ldr/mach-o/h/sys/resource.h deleted file mode 100644 index f17e660..0000000 --- a/idasdk75/ldr/mach-o/h/sys/resource.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (c) 2000-2008 Apple Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ -/* - * Copyright (c) 1982, 1986, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)resource.h 8.2 (Berkeley) 1/4/94 - */ - -#ifndef _SYS_RESOURCE_H_ -#define _SYS_RESOURCE_H_ - -#include <sys/appleapiopts.h> -#include <sys/cdefs.h> -#include <sys/_types.h> - - -/* [XSI] The timeval structure shall be defined as described in - * <sys/time.h> - */ -#define __need_struct_timeval -#include <sys/_structs.h> - -/* The id_t type shall be defined as described in <sys/types.h> */ -#ifndef _ID_T -#define _ID_T -typedef __darwin_id_t id_t; /* can hold pid_t, gid_t, or uid_t */ -#endif - - -/* - * Resource limit type (low 63 bits, excluding the sign bit) - */ -typedef __uint64_t rlim_t; - - -/***** - * PRIORITY - */ - -/* - * Possible values of the first parameter to getpriority()/setpriority(), - * used to indicate the type of the second parameter. - */ -#define PRIO_PROCESS 0 /* Second argument is a PID */ -#define PRIO_PGRP 1 /* Second argument is a GID */ -#define PRIO_USER 2 /* Second argument is a UID */ - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define PRIO_DARWIN_THREAD 3 /* Second argument is always 0 (current thread) */ -#define PRIO_DARWIN_PROCESS 4 /* Second argument is a PID */ - -/* - * Range limitations for the value of the third parameter to setpriority(). - */ -#define PRIO_MIN -20 -#define PRIO_MAX 20 - -/* use PRIO_DARWIN_BG to set the current thread into "background" state - * which lowers CPU, disk IO, and networking priorites until thread terminates - * or "background" state is revoked - */ -#define PRIO_DARWIN_BG 0x1000 - -/* - * use PRIO_DARWIN_NONUI to restrict a process's ability to make calls to - * the GPU. - */ -#define PRIO_DARWIN_NONUI 0x1001 - -#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ - - - -/***** - * RESOURCE USAGE - */ - -/* - * Possible values of the first parameter to getrusage(), used to indicate - * the scope of the information to be returned. - */ -#define RUSAGE_SELF 0 /* Current process information */ -#define RUSAGE_CHILDREN -1 /* Current process' children */ - -/* - * A structure representing an accounting of resource utilization. The - * address of an instance of this structure is the second parameter to - * getrusage(). - * - * Note: All values other than ru_utime and ru_stime are implementaiton - * defined and subject to change in a future release. Their use - * is discouraged for standards compliant programs. - */ -struct rusage { - struct timeval ru_utime; /* user time used (PL) */ - struct timeval ru_stime; /* system time used (PL) */ -#if defined(_POSIX_C_SOURCE) && !defined(_DARWIN_C_SOURCE) - long ru_opaque[14]; /* implementation defined */ -#else /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ - /* - * Informational aliases for source compatibility with programs - * that need more information than that provided by standards, - * and which do not mind being OS-dependent. - */ - long ru_maxrss; /* max resident set size (PL) */ -#define ru_first ru_ixrss /* internal: ruadd() range start */ - long ru_ixrss; /* integral shared memory size (NU) */ - long ru_idrss; /* integral unshared data (NU) */ - long ru_isrss; /* integral unshared stack (NU) */ - long ru_minflt; /* page reclaims (NU) */ - long ru_majflt; /* page faults (NU) */ - long ru_nswap; /* swaps (NU) */ - long ru_inblock; /* block input operations (atomic) */ - long ru_oublock; /* block output operations (atomic) */ - long ru_msgsnd; /* messages sent (atomic) */ - long ru_msgrcv; /* messages received (atomic) */ - long ru_nsignals; /* signals received (atomic) */ - long ru_nvcsw; /* voluntary context switches (atomic) */ - long ru_nivcsw; /* involuntary " */ -#define ru_last ru_nivcsw /* internal: ruadd() range end */ -#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ -}; - - - - -/***** - * RESOURCE LIMITS - */ - -/* - * Symbolic constants for resource limits; since all limits are representable - * as a type rlim_t, we are permitted to define RLIM_SAVED_* in terms of - * RLIM_INFINITY. - */ -#define RLIM_INFINITY (((__uint64_t)1 << 63) - 1) /* no limit */ -#define RLIM_SAVED_MAX RLIM_INFINITY /* Unrepresentable hard limit */ -#define RLIM_SAVED_CUR RLIM_INFINITY /* Unrepresentable soft limit */ - -/* - * Possible values of the first parameter to getrlimit()/setrlimit(), to - * indicate for which resource the operation is being performed. - */ -#define RLIMIT_CPU 0 /* cpu time per process */ -#define RLIMIT_FSIZE 1 /* file size */ -#define RLIMIT_DATA 2 /* data segment size */ -#define RLIMIT_STACK 3 /* stack size */ -#define RLIMIT_CORE 4 /* core file size */ -#define RLIMIT_AS 5 /* address space (resident set size) */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define RLIMIT_RSS RLIMIT_AS /* source compatibility alias */ -#define RLIMIT_MEMLOCK 6 /* locked-in-memory address space */ -#define RLIMIT_NPROC 7 /* number of processes */ -#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ -#define RLIMIT_NOFILE 8 /* number of open files */ -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -#define RLIM_NLIMITS 9 /* total number of resource limits */ -#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */ -#define _RLIMIT_POSIX_FLAG 0x1000 /* Set bit for strict POSIX */ - -/* - * A structure representing a resource limit. The address of an instance - * of this structure is the second parameter to getrlimit()/setrlimit(). - */ -struct rlimit { - rlim_t rlim_cur; /* current (soft) limit */ - rlim_t rlim_max; /* maximum value for rlim_cur */ -}; - -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -/* I/O type */ -#define IOPOL_TYPE_DISK 0 - -/* scope */ -#define IOPOL_SCOPE_PROCESS 0 -#define IOPOL_SCOPE_THREAD 1 - -/* I/O Priority */ -#define IOPOL_DEFAULT 0 -#define IOPOL_NORMAL 1 -#define IOPOL_PASSIVE 2 -#define IOPOL_THROTTLE 3 -#define IOPOL_UTILITY 4 - -#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */ - - -__BEGIN_DECLS -int getpriority(int, id_t); -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -int getiopolicy_np(int, int); -#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */ -int getrlimit(int, struct rlimit *) __DARWIN_ALIAS(getrlimit); -int getrusage(int, struct rusage *); -int setpriority(int, id_t, int); -#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) -int setiopolicy_np(int, int, int); -#endif /* !_POSIX_C_SOURCE || _DARWIN_C_SOURCE */ -int setrlimit(int, const struct rlimit *) __DARWIN_ALIAS(setrlimit); -__END_DECLS - -#endif /* !_SYS_RESOURCE_H_ */ diff --git a/idasdk75/ldr/mach-o/h/sys/resourcevar.h b/idasdk75/ldr/mach-o/h/sys/resourcevar.h deleted file mode 100644 index a36c8b7..0000000 --- a/idasdk75/ldr/mach-o/h/sys/resourcevar.h +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */ -/* - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)resourcevar.h 8.4 (Berkeley) 1/9/95 - */ - -#ifndef _SYS_RESOURCEVAR_H_ -#define _SYS_RESOURCEVAR_H_ - -#include <sys/appleapiopts.h> - -/* - * Kernel per-process accounting / statistics - * (not necessarily resident except when running). - */ -struct pstats { -#define pstat_startzero p_ru - struct rusage p_ru; /* stats for this proc */ - struct rusage p_cru; /* (PL) sum of stats for reaped children */ - - struct uprof { /* profile arguments */ - struct uprof *pr_next; /* multiple prof buffers allowed */ - caddr_t pr_base; /* buffer base */ - u_int32_t pr_size; /* buffer size */ - u_int32_t pr_off; /* pc offset */ - u_int32_t pr_scale; /* pc scaling */ - u_int32_t pr_addr; /* temp storage for addr until AST */ - u_int32_t pr_ticks; /* temp storage for ticks until AST */ - } p_prof; -#define pstat_endzero p_start - - struct timeval p_start; /* starting time ; compat only */ -}; - -/* - * Kernel shareable process resource limits. Because this structure - * is moderately large but changes infrequently, it is normally - * shared copy-on-write after forks. If a group of processes - * ("threads") share modifications, the PL_SHAREMOD flag is set, - * and a copy must be made for the child of a new fork that isn't - * sharing modifications to the limits. - */ -/* - * Modifications are done with the list lock held (p_limit as well)and access indv - * limits can be done without limit as we keep the old copy in p_olimit. Which is - * dropped in proc_exit. This way all access will have a valid kernel address - */ -struct plimit { - struct rlimit pl_rlimit[RLIM_NLIMITS]; - int pl_refcnt; /* number of references */ -}; - - - -#endif /* !_SYS_RESOURCEVAR_H_ */ diff --git a/idasdk75/ldr/mach-o/h/sys/user.h b/idasdk75/ldr/mach-o/h/sys/user.h deleted file mode 100644 index be85bb4..0000000 --- a/idasdk75/ldr/mach-o/h/sys/user.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ -/* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */ -/* - * Copyright (c) 1982, 1986, 1989, 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)user.h 8.2 (Berkeley) 9/23/93 - */ - -#ifndef _SYS_USER_H_ -#define _SYS_USER_H_ - -#include <sys/appleapiopts.h> -/* stuff that *used* to be included by user.h, or is now needed */ -#include <errno.h> -#include <sys/time.h> -#include <sys/resource.h> -#include <sys/ucred.h> -#include <sys/uio.h> -#include <sys/vm.h> /* XXX */ -#include <sys/sysctl.h> - - -/* - * Per process structure containing data that isn't needed in core - * when the process isn't running (esp. when swapped out). - * This structure may or may not be at the same kernel address - * in all processes. - */ - -struct user { - /* NOT USED ANYMORE */ -}; - -#endif /* !_SYS_USER_H_ */ diff --git a/idasdk75/ldr/mach-o/macho_node.h b/idasdk75/ldr/mach-o/macho_node.h deleted file mode 100644 index d16adf4..0000000 --- a/idasdk75/ldr/mach-o/macho_node.h +++ /dev/null @@ -1,13 +0,0 @@ -#ifndef MACHO_NODE_H -#define MACHO_NODE_H - -#define MACHO_NODE "$ macho" // supval(0) - mach_header - -#define MACHO_ALT_IMAGEBASE nodeidx_t(-1) // image base of the input file -#define MACHO_ALT_UUID nodeidx_t(-2) // uuid of the input file (supval) - -#define CODE_TAG 'C' // charvals: code -> data rebase info -#define DATA_TAG 'D' // charvals: data -> code rebase info -#define SEGM_TAG 's' // hashvals: segm name -> segm start ea - -#endif // MACHO_NODE_H diff --git a/idasdk75/ldr/mas/makefile b/idasdk75/ldr/mas/makefile deleted file mode 100644 index a36717b..0000000 --- a/idasdk75/ldr/mas/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=mas - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)mas$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h mas.cpp mas.hpp diff --git a/idasdk75/ldr/mas/mas.cpp b/idasdk75/ldr/mas/mas.cpp deleted file mode 100644 index 7f6695b..0000000 --- a/idasdk75/ldr/mas/mas.cpp +++ /dev/null @@ -1,407 +0,0 @@ - -// Loader for the Macro-assembler-related binary format - -#include "../idaldr.h" -#include "mas.hpp" - -// undefine this to print some debugging information -// in the IDA console. -//#define DEBUG - -//----------------------------------------------------------------------------- -struct gas_family -{ - uchar code; - const char *processor; //lint !e958 padding is required to align members -}; - -static const struct gas_family families[] = -{ - { 0x01, "68k" }, - // 0x03 : M*Core - { 0x05, "ppc" }, - { 0x09, "dsp56k" }, - { 0x11, "m740" }, - // 0x12 : MELPS-4500 - // 0x13 : M16 - // 0x14 : M16C - // 0x15 : F2MC8L - { 0x16, "f2mc16l" }, - { 0x19, "m7700" }, - // 0x21 : MCS-48 - // 0x25 : SYM53C8xx - // 0x29 : 29xxx - { 0x2A, "i960b" }, // little or big endian ???? - // 0x31 : MCS-51 - { 0x32, "st9" }, - { 0x33, "st7" }, - // 0x38 : 1802/1805 - // 0x39 : MCS-96/196/296 - // 0x3A : 8X30x - { 0x3B, "avr" }, - // 0x3C : XA - // 0x3F : 4004/4040 - { 0x41, "8085" }, - { 0x42, "8086" }, - { 0x47, "tms320c6" }, - // 0x48 : TMS9900 - // 0x49 : TMS370xxx - // 0x4A : MSP430 - { 0x4B, "tms32054" }, - { 0x4C, "c166" }, - { 0x51, "z80" }, - // 0x52 : TLCS-900 - // 0x53 : TLCS-90 - // 0x54 : TLCS-870 - // 0x55 : TLCS-47 - // 0x56 : TLCS-9000 - { 0x61, "6800" }, - { 0x62, "6805" }, - { 0x63, "6809" }, - // 0x64 : 6804 - // 0x65 : 68HC16 - // 0x66 : 68HC12 - // 0x67 : ACE - { 0x68, "h8300" }, - { 0x69, "h8500" }, - // 0x6C : SH7000 - // 0x6C : SC14xxx - // 0x6C : SC/MP - // 0x6C : COP8 - { 0x70, "pic16cxx" }, - { 0x71, "pic16cxx" }, - // 0x72 : PIC17C4x - // 0x73 : TMS-7000 - // 0x74 : TSM3201x - // 0x75 : TSM320C2x - // 0x76 : TSM320C3x - { 0x77, "tms320c2" }, - // 0x78 : ST6uPD772 - { 0x79, "z8" } - // 0x7A : uPD78(C)10 - // 0x7B : 75K0 - // 0x7C : 78K0 - // 0x7D : uPD7720 - // 0x7E : uPD7725 - // 0x7F : uPD77230 -}; - -static char creator[MAXSTR]; // program name which created the binary -static int entry_point; // address of the entry point -static const char *set_proc = NULL; - -//----------------------------------------------------------------------------- -// output an error and exit loader. -AS_PRINTF(1, 2) NORETURN static void mas_error(const char *format, ...) -{ - char b[MAXSTR]; - va_list va; - - va_start(va, format); - qvsnprintf(b, sizeof(b), format, va); - va_end(va); - loader_failure("mas loader critical error: %s", b); -} - -//----------------------------------------------------------------------------- -// set the current processor type according to "cpu_type". -static bool mas_set_cpu(uchar cpu_type) -{ - for ( int i = 0; i < qnumber(families); i++ ) - { - if ( families[i].code != cpu_type ) - continue; - - const char *proc = families[i].processor; - if ( set_proc != NULL && !streq(proc, set_proc) ) - mas_error("only one processor record is allowed"); - - set_proc = proc; - set_processor_type(proc, SETPROC_LOADER); -#if defined(DEBUG) - msg("MAS: detected processor %s\n", proc); -#endif - return true; - } - return false; -} - -//----------------------------------------------------------------------------- -// return a segment name according to its "segment_type". -static const char *mas_get_segname(uchar segment_type) -{ - switch ( segment_type ) - { - case 0x00: return "UNDEFINED"; - case 0x01: return "CODE"; - case 0x02: return "DATA"; - case 0x03: return "IDATA"; - case 0x04: return "XDATA"; - case 0x05: return "YDATA"; - case 0x06: return "BDATA"; - case 0x07: return "IO"; - case 0x08: return "REG"; - case 0x09: return "ROMDATA"; - } - return NULL; -} - -//----------------------------------------------------------------------------- -// write comments. -static void mas_write_comments(void) -{ - create_filename_cmt(); - - char entry_point_str[20]; - if ( entry_point == -1 ) - qstrncpy(entry_point_str, "NOT DETECTED", sizeof(entry_point_str)); - else - qsnprintf(entry_point_str, sizeof(entry_point_str), "0x%X", entry_point); - - // write name of the creator program - add_pgm_cmt("Creator program : %s", creator); - // write address of the entry point - add_pgm_cmt("Entry point : %s", entry_point_str); -} - -//----------------------------------------------------------------------------- -// detect macro assembler files using the start sequence. -static int idaapi accept_file( - qstring *fileformatname, - qstring *, // too difficult to determine the processor - linput_t *li, - const char *) -{ - // read the first word - uint16 word = 0; - if ( qlread(li, &word, 2) != 2 ) - return 0; - -#if defined(DEBUG) - msg("MAS: 2 first bytes : 0x%X\n", word); -#endif - - // first word must match the start_sequence - if ( word != START_SEQUENCE ) - return 0; - - *fileformatname = "Macro Assembler by Alfred Arnold"; -#if defined(DEBUG) - msg("MAS: detected mas binary file !\n"); -#endif - return 1; -} - -//----------------------------------------------------------------------------- -static void load_bytes(linput_t *li, ea_t ea, asize_t size, const char *segname) -{ - // validate the segment size - ea_t end = ea + size; - qoff64_t curpos = qltell(li); - qoff64_t endpos = curpos + size; - if ( ea == BADADDR || end < ea || endpos < curpos || endpos > qlsize(li) ) - mas_error("wrong or too big segment %a..%a", ea, end); - - // send code in the database - file2base(li, curpos, ea, end, FILEREG_PATCHABLE); - - // set selector - sel_t selector = allocate_selector(0); - - // create data segment - add_segm(selector, ea, end, segname, segname); -} - -//----------------------------------------------------------------------------- -static void check_target_processor() -{ - if ( PH.id == -1 ) - loader_failure("Failed to determine the target processor, please specify it manually"); -} - -//----------------------------------------------------------------------------- -// process a file record according to its "record_type". -// return true if there is no more records to process. -static bool process_record(linput_t *li, const uchar record_type, bool load) -{ - bool finished = false; - - switch ( record_type ) - { - // A record with a header byte of $81 is a record that may contain code or - // data from arbitrary segments. - // - // header : 1 byte - // segment : 1 byte - // gran : 1 byte - // start_addr : 4 bytes (entry point) - // length : 2 bytes - // data : length bytes - case 0x81: - { - mas_header_t header; - memset(&header, 0, sizeof(header)); - - // read the header - if ( qlread(li, &header, sizeof(header)) != sizeof(header) ) - mas_error("unable to read header (%" FMT_Z " bytes)", sizeof(header)); - - // granularities that differ from 1 are rare and mostly appear - // in DSP CPU's that are not designed for byte processing. - if ( header.gran != 1 ) - mas_error("unsupported granularity (%d)", header.gran); - - // set processor - if ( !mas_set_cpu(header.header) ) - mas_error("processor type '0x%X' is currently unsupported", header.header); - if ( !load ) // we have the processor, nothing else to do - { - finished = true; - break; - } - - // get segment name - const char *segname = mas_get_segname(header.segment); - if ( segname == NULL ) - mas_error("invalid segment '0x%X'", header.segment); - -#if defined(DEBUG) - msg("MAS: ready to read %d bytes (0x%X -> 0x%X)\n", - header.length, header.start_addr, header.start_addr + header.length); -#endif - load_bytes(li, header.start_addr, header.length, segname); - } - break; - - // The last record in a file bears the Header $00 and has only a string as - // data field. This string does not have an explicit length specification; - // its end is equal to the file's end. - // - // The string contains only the name of the program that created the file - // and has no further meaning. - // - // creator : x bytes - case 0x00: - { - uint32 length = qlsize(li) - qltell(li); -#if defined(DEBUG) - msg("MAS: creator length : %ld bytes\n", length); -#endif - if ( length >= sizeof(creator) ) - mas_error("creator length is too large (%u >= %" FMT_Z, - length, sizeof(creator)); - ssize_t tmp = qlread(li, creator, length); - if ( tmp != length ) - mas_error("unable to read creator string (i read %" FMT_ZS")", tmp); - creator[length] = '\0'; - } - finished = true; - break; - - // entry_point : 4 bytes - case 0x80: - { - if ( qlread(li, &entry_point, 4) != 4 ) - mas_error("unable to read entry_point"); - if ( load ) - { -#if defined(DEBUG) - msg("MAS: detected entry point : 0x%X\n", entry_point); -#endif - inf_set_start_ip(entry_point); // entry point - segment_t *s = getseg(entry_point); - inf_set_start_cs(s ? s->sel : 0); // selector of code - } - } - break; - - default: - // start_addr : 4 bytes - // length : 2 bytes - // data : length bytes - if ( record_type >= 0x01 && record_type <= 0x7F ) - { - check_target_processor(); - - struct - { - int start_addr; - short length; - } header; - - memset(&header, 0, sizeof(header)); - - // read the header - if ( qlread(li, &header, sizeof(header)) != sizeof(header) ) - mas_error("unable to read header (%" FMT_Z " bytes)", sizeof(header)); - - if ( load ) - load_bytes(li, header.start_addr, header.length, "DATA"); - else - qlseek(li, qltell(li)+header.length); - } - else - { - mas_error("invalid record type '0x%X'\n", record_type); - } - } - return finished; -} - -//----------------------------------------------------------------------------- -// load a macro assembler file in IDA. -void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) -{ - // already read the 2 first bytes - qlseek(li, 2); - - // initialize static variables - qstrncpy(creator, "UNKNOWN", sizeof(creator)); - entry_point = -1; - - bool finished = false; - while ( !finished ) - { - uchar record_type = 0; - - // read the record type - if ( qlread(li, &record_type, 1) != 1 ) - mas_error("unable to read the record type"); - - finished = process_record(li, record_type, true); - } - -#if defined(DEBUG) - msg("MAS: reading complete\n"); -#endif - - check_target_processor(); - - mas_write_comments(); -} - -//----------------------------------------------------------------------------- -// Loader description block -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/ldr/nlm/makefile b/idasdk75/ldr/nlm/makefile deleted file mode 100644 index c2081cd..0000000 --- a/idasdk75/ldr/nlm/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=nlm - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)nlm$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)typeinf.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaldr.h nlm.cpp nlm.h diff --git a/idasdk75/ldr/nlm/nlm.cpp b/idasdk75/ldr/nlm/nlm.cpp deleted file mode 100644 index ce59497..0000000 --- a/idasdk75/ldr/nlm/nlm.cpp +++ /dev/null @@ -1,1023 +0,0 @@ -/* - * This Loader Module is written by Ilfak Guilfanov and - * rewriten by Yury Haron - * - */ -/* - L O A D E R for Netware Loadable Module (NLM) -*/ - -#include <stddef.h> -#include "../idaldr.h" -#include "nlm.h" -#include <typeinf.hpp> - -#pragma pack(push, 1) - -//-------------------------------------------------------------------------- -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - char magic[NLM_MAGIC_SIZE]; - - if ( qlread(li, magic, sizeof(magic)) != sizeof(magic ) - || memcmp(magic, NLM_MAGIC, sizeof(magic)) != 0 ) - { - return 0; - } - - *fileformatname = "Netware Loadable Module (NLM)"; - *processor = "metapc"; - return f_NLM; -} - -//-------------------------------------------------------------------------- -static void _errstruct(int lnnum) -{ - loader_failure("Bad file structure or read error (line %d)", lnnum); -} -#define errstruct() _errstruct(__LINE__) - -//-------------------------------------------------------------------------- -//lint -e{958} padding needed -static struct local_data -{ - struct unp_data - { - FILE *fo; - uint32 pos, size; - uchar *buff; - ushort b_pos, b_val; - }; - - linput_t *li; - nlmexe_t nlm; - union - { - char buf[MAXSTR]; - unp_data unp; - }; //lint !e958 padding is required to align members - ea_t start, cbase, csize, dbase, dsize; - netnode impnode; -} lc; - -//-------------------------------------------------------------------------- -static int mread(void *buf, size_t size) -{ - if ( qlread(lc.li, buf, size) == size ) - return 0; - if ( ask_yn(ASKBTN_NO, - "HIDECANCEL\n" - "Read error or bad file structure. Continue loading?") <= ASKBTN_NO ) - { - loader_failure(); - } - return 1; -} - -//-------------------------------------------------------------------------- -static int getstr(void) -{ - uchar len; -#if MAXSTR < 256 -#error -#endif - - if ( mread(&len, sizeof(len)) || (len && mread(lc.buf, len)) ) - return 1; - lc.buf[len] = '\0'; - return 0; -} - -//---------------------------------------------------------------------- -static void set_reloc(ushort sel, ea_t fixaddr, ea_t toea, bool self_flag) -{ - sval_t displ = int32(get_dword(fixaddr)); - - fixup_data_t fd(FIXUP_OFF32); - fd.off = toea; - fd.sel = sel; - if ( sel == 3 ) - { - fd.set_extdef(); - fd.displacement = displ; - } - if ( self_flag ) - toea -= fixaddr; - put_dword(fixaddr, uint32(toea + displ)); - fd.set(fixaddr); -} - -//---------------------------------------------------------------------- -static void add_imports(void) -{ - if ( lc.nlm.impoff == 0 || lc.nlm.impnum == 0 ) - return; - uint32 i = lc.nlm.impnum; - msg("Creating imported names and relocating it...\n"); - lc.impnode.create(LDR_NODE); - qlseek(lc.li, lc.nlm.impoff, SEEK_SET); - ea_t ebase = lc.start; - ea_t eend = ebase + (i * sizeof(int32)); - uint64 fsize = qlsize(lc.li); - if ( lc.nlm.impoff >= fsize ) - loader_failure("Bad import offset"); - uint64 rest = fsize - lc.nlm.impoff; - if ( !is_mul_ok<uint32>(i, sizeof(int32)) - || eend <= ebase - || qoff64_t(i)*2 > rest ) // each name requires at least 2 bytes - { - loader_failure("Bad import count"); - } - - set_selector(3, 0); - if ( add_segm(3, ebase, eend, NAME_EXTERN, NULL) ) - { - segment_t *ps = getseg(ebase); - ps->type = SEG_XTRN; - ps->update(); - } - else - { - loader_failure(); - } - - uchar ss = inf_get_specsegs(); - for ( ; i; i--, ebase += ss ) - { - if ( getstr() ) - break; - show_addr(ebase); - set_name(ebase, lc.buf, SN_NOCHECK | SN_PUBLIC | SN_IDBENC); - if ( ss == 8 ) - put_qword(ebase, 0); - else - put_dword(ebase, 0); - if ( lc.impnode ) - netnode(lc.impnode).supset_ea(ebase, lc.buf); - uint32 fnum; - if ( mread(&fnum, sizeof(fnum)) ) - { -FORCE_END: - if ( (ebase += ss) < eend ) - set_segm_end(ebase, ebase, SEGMOD_KILL); - return; - } - int sff = 0; - while ( fnum-- ) - { - uint32 ent; - if ( mread(&ent, sizeof(ent)) ) - goto FORCE_END; - ea_t ea, sz; - bool self = (ent & 0x80000000) == 0; - if ( ent & 0x40000000 ) - { - ea = lc.cbase; - sz = lc.csize; - } - else - { - ea = lc.dbase; - sz = lc.dsize; - } - ent &= ~0xC0000000; - if ( ent >= sz ) - { - msg("Skip reference to extern '%s' with illegal offset 0x%X\n", - lc.buf, ent); - } - else - { - set_reloc(3, ea + ent, ebase, self); - if ( sff == 0 && self ) - { - ++sff; - add_func(ebase, ebase+ss-1); - } - } - } - } -} - -//-------------------------------------------------------------------------- -static void add_fixups(void) -{ - if ( lc.nlm.fixupoff == 0 || lc.nlm.fixupnum == 0 ) - return; - uint32 i = lc.nlm.fixupnum; - msg("Applying internal fixup records...\n"); - qlseek(lc.li, lc.nlm.fixupoff, SEEK_SET); - - validate_array_count_or_die(lc.li, i, 4, "Number of fixups", lc.nlm.fixupoff); - while ( i-- != 0 ) - { - uint32 ent; - if ( mread(&ent, sizeof(ent)) ) - break; - ea_t base, toea; - asize_t size; - if ( ent & 0x40000000 ) - { - base = lc.cbase; - size = lc.csize; - } - else - { - base = lc.dbase; - size = lc.dsize; - } - ushort sel; - if ( ent & 0x80000000 ) - { - toea = lc.cbase; - sel = 1; - } - else - { - toea = lc.dbase; - sel = 2; - } - ent &= ~0xC0000000; - if ( ent >= size || !toea ) - msg("Skip invalid relocation for offset 0x%X (to base %a)\n", ent, toea); - else - set_reloc(sel, ent + base, toea, 0); - } -} - -//-------------------------------------------------------------------------- -static void add_exports_and_publics(void) -{ - uint32 i, foff; - int pfl; - - for ( pfl = 0, foff = lc.nlm.expoff, i = lc.nlm.expnum; - pfl < 2; - pfl++, foff = lc.nlm.puboff, i = lc.nlm.pubnum ) - { - if ( foff == 0 || i == 0 ) - continue; - msg("Applying %s names...\n", pfl ? "public" : "exported"); - qlseek(lc.li, foff, SEEK_SET); - validate_array_count_or_die(lc.li, i, 4, - pfl ? "Number of publics" : "Number of exports", - foff); - while ( i-- != 0 ) - { - bool flag; - ea_t ea; - CASSERT(sizeof(flag) == 1); - if ( !pfl ) - { - if ( getstr() || mread(&ea, sizeof(uint32)) ) - break; - flag = (ea & 0x80000000) != 0; - } - else if ( mread(&flag, sizeof(flag)) - || mread(&ea, sizeof(uint32)) - || getstr() ) - { - break; - } - ea &= ~0xC0000000L; - ea_t base; - asize_t size; - if ( flag ) - { - base = lc.cbase; - size = lc.csize; - } - else - { - base = lc.dbase; - size = lc.dsize; - } - if ( ea >= size ) - { - msg("Skip name '%s' with illegal offset (0x%a)\n", lc.buf, ea); - } - else - { - ea += base; - add_entry(ea, ea, lc.buf, flag, AEF_IDBENC); - } - } - } -} - -//-------------------------------------------------------------------------- -static int LoadMsgString(void) -{ - int c, i; - for ( i = 0; i < sizeof(lc.buf)-1; i++ ) - { - if ( (c = qlgetc(lc.li)) == EOF ) - return 0; - if ( !c ) - break; - if ( c == 0xFF ) - { - c = '.'; - } - else if ( c < ' ' ) - { - static const char rpts[] = "\t\n\r\a\v\f"; - static const char rptc[] = "tnravf"; - const char *p = strchr(rpts, c); - if ( p ) - { - if ( i == sizeof(lc.buf)-2 ) - break; - lc.buf[i++] = '\\'; - c = (int)(uchar)rptc[(int)(p-rpts)]; - } - } - lc.buf[i] = (char)c; - } - lc.buf[i] = '\0'; - return 1; -} - -//-------------------------------------------------------------------------- -static uint32 addSpecialComment(void) -{ - uchar vp = 0, cp = 0; - uint32 mp = 0; - qoff64_t pos = qltell(lc.li); - ea_t loadbase = lc.nlm.codeoff; - if ( lc.nlm.datalen && loadbase > lc.nlm.dataoff ) - loadbase = lc.nlm.dataoff; - if ( loadbase > 0x1000 ) - loadbase = 0x1000; - - while ( pos + 12 < loadbase ) - { - if ( mread(lc.buf, 12) ) - break; - if ( !mp && !memcmp(lc.buf, "MeSsAgEs", 8) ) - { - mp = pos + 8; - pos += 0x7C; - goto repos; - } - if ( !vp && !memcmp(lc.buf, "VeRsIoN#", 8) ) - { - if ( mread(&lc.buf[12], 32-12) ) - break; - ++vp; - pos += 32 - 1; - qsnprintf(&lc.buf[32], sizeof(lc.buf)-32, "%u.%02u%c (%02u.%02u.%04u)", - *(uint32 *)&lc.buf[8], (uchar)lc.buf[8+4], - *(uint32 *)&lc.buf[8+8] ? (char)(lc.buf[8+8] + ('A'-1)) : ' ', - (uchar)lc.buf[8+20], (uchar)lc.buf[8+16], - *(ushort *)&lc.buf[8+12]); - add_pgm_cmt("Version : %s", &lc.buf[32]); - goto check; - } - if ( !cp && !memcmp(lc.buf, "CoPyRiGhT=", 10) ) - { - pos += 10; - pos += (uchar)lc.buf[10]; - qlseek(lc.li, -2L, SEEK_CUR); - if ( getstr() ) - break; - add_pgm_cmt("Copyright : %s", lc.buf); - ++cp; - goto check; - } - if ( !memcmp(lc.buf, "CuStHeAd", 8) ) - { - pos += 8; - pos += *(uint32 *)&lc.buf[8]; - goto repos; - } -check: - if ( mp && vp && cp ) - break; - ++pos; -repos: - qlseek(lc.li, pos, SEEK_SET); - } - return mp; -} - -//-------------------------------------------------------------------------- -static void addComments(int flg) -{ - uint32 clst = (uint32)-1, msgpos = 0; - char *cl1 = NULL; - char *cl2 = NULL; - - create_filename_cmt(); - qlseek(lc.li, NLM_MODNAMOFF, SEEK_SET); - if ( lc.nlm.fname[0] ) - add_pgm_cmt("Module Name : %.12s", lc.nlm.fname); - if ( !getstr() ) - { - add_pgm_cmt("Description : %s", lc.buf); - qlseek(lc.li, 1, SEEK_CUR); - if ( mread(&clst, sizeof(clst)) ) - { - clst = (uint32)-1; - } - else - { - qlseek(lc.li, 0xD-sizeof(clst), SEEK_CUR); - if ( !getstr() ) - { - cl1 = qstrdup(lc.buf); - qlseek(lc.li, 1, SEEK_CUR); - if ( !getstr() ) - { - cl2 = qstrdup(lc.buf); - msgpos = addSpecialComment(); - } - } - } - } - add_pgm_cmt("File Format Version : %08Xh%s", lc.nlm.version, - (lc.nlm.version & NLM_COMPRESSED) ? " (compressed)" : ""); - { - static const char *const tt[15] = - { - "Generic", - "LAN Driver", - "Disk Driver", - "Name Space", - "Patch/Utility", - "Mirrored Server Link", - "OS", - "High OS", - "Host Adapter", - "Custom Device", - "FS Engine", - "Real Mode", - "OS", //duplicate 6 - "Platform Support", - "Unknown" - }; - int type = (int)lc.nlm.modType; - if ( lc.nlm.modType > 14 ) - type = 14; - add_pgm_cmt("Module type : %s (%d)", tt[type], type); - } - if ( lc.nlm.bssSize ) - add_pgm_cmt("Unitialized data size : %08Xh", lc.nlm.bssSize); - if ( lc.nlm.custoff && lc.nlm.custlen ) - add_pgm_cmt("Custom data : off=%08Xh len=%08Xh", - lc.nlm.custoff, lc.nlm.custlen); - lc.buf[0]= '\0'; - if ( lc.nlm.flags ) - { - static const char *const ff[4] = - { - "reentrant", - "multiply loadable", - "synchronize", - "pseudo-preemptable" - }; - char *ptr = lc.buf; - char *end = lc.buf + sizeof(lc.buf); - int cn = 0; - APPCHAR(ptr, end, ' '); - APPCHAR(ptr, end, '('); - for ( int i = 0; i < 4; i++ ) - { - if ( lc.nlm.flags & (1 << i) ) - { - if ( cn ) - { - APPCHAR(ptr, end, ','); - APPCHAR(ptr, end, ' '); - } - ++cn; - APPEND(ptr, end, ff[i]); - } - } - if ( cn ) - APPCHAR(ptr, end, ')'); - else - ptr = lc.buf; - APPZERO(ptr, end); - } - add_pgm_cmt("Flags : %08Xh%s", lc.nlm.flags, lc.buf); - if ( clst != (uint32)-1 ) - add_pgm_cmt("CLIB Stack Size : %08Xh", clst); - if ( cl1 ) - { - if ( *cl1 ) - add_pgm_cmt("CLIB Screen Name : %s", cl1); - qfree(cl1); - } - if ( cl2 ) - { - if ( *cl2 ) - add_pgm_cmt("CLIB Thread Name : %s", cl2); - qfree(cl2); - } - if ( lc.nlm.autoliboff && lc.nlm.autolibnum ) - { - qlseek(lc.li, lc.nlm.autoliboff, SEEK_SET); - for ( uint i = 0; i < lc.nlm.autolibnum; i++ ) - { - if ( getstr() ) - break; - add_pgm_cmt("Referenced Modules : '%s'", lc.buf); - if ( lc.impnode ) - { - char *p1, *p2; - for ( p1 = lc.buf; p1 && *trim(p1); p1 = p2 ) - { - if ( (p2 = strchr(p1, '|')) != NULL ) - { - *p2++ = '\0'; - if ( !*trim(p1) ) - continue; - } - import_module(p1, NULL, lc.impnode, NULL, "netware"); - } - } - } - } - - if ( !msgpos ) - return; - - qlseek(lc.li, msgpos, SEEK_SET); - if ( mread(lc.buf, 0x7C-8) ) - return; - - uint32 id = *(uint32 *)&lc.buf[0x60-8]; - if ( id ) - add_pgm_cmt("Product ID : %08Xh", id); - id = *(uint32 *)&lc.buf[0]; - if ( id ) - add_pgm_cmt("Language ID : %u", id); - id = *(uint32 *)&lc.buf[0x34-8]; - if ( id ) - add_pgm_cmt("Shared Data : off=%08Xh, size=%08Xh", - *(uint32 *)&lc.buf[0x30-8], id); - id = *(uint32 *)&lc.buf[0x2C-8]; - if ( id ) - { - add_pgm_cmt("Shared Code : off=%08Xh, size=%08Xh", - *(uint32 *)&lc.buf[0x28-8], id); - add_pgm_cmt("Shared Start Procedure : off=%08Xh", - *(uint32 *)&lc.buf[0x58-8]); - add_pgm_cmt("Shared Exit Procedure : off=%08Xh", - *(uint32 *)&lc.buf[0x5C-8]); - } - id = *(uint32 *)&lc.buf[0x1C-8]; - if ( id ) - add_pgm_cmt("Help : off=%08Xh, size=%08Xh", - *(uint32 *)&lc.buf[0x18-8], id); - id = *(uint32 *)&lc.buf[0x24-8]; - if ( id ) - add_pgm_cmt("RPC & BAG : off=%08Xh, size=%08Xh", - *(uint32 *)&lc.buf[0x20-8], id); - id = *(uint32 *)&lc.buf[0x10-8]; - - if ( id ) - { - add_pgm_cmt("Message : off=%08Xh, size=%08Xh", - msgpos = *(uint32 *)&lc.buf[0xC-8], id); - - if ( !flg ) - return; - - uint32 mlng, mcnt; - qlseek(lc.li, msgpos + 0x6A, SEEK_SET); - if ( mread(&mlng, sizeof(mlng)) || mread(&mcnt, sizeof(mcnt)) ) - return; - - add_pgm_cmt("Message Language : %08Xh", mlng); - msgpos += 0x76; - for ( clst = 0; clst < mcnt; clst++ ) - { - qlseek(lc.li, msgpos + qoff64_t(clst)*4, SEEK_SET); - if ( mread(&mlng, sizeof(mlng)) ) - break; - qlseek(lc.li, msgpos + mlng, SEEK_SET); - if ( !LoadMsgString() ) - break; - add_pgm_cmt(" %08X : %s", clst, lc.buf); - } -//4C - Shared Exported Symbols -//44 - Shared Imported Symbols -//3C - Shared Fixups -//54 - Shared Debug Records - } -} - -//-------------------------------------------------------------------------- -static void load_image(void) -{ - uint32 lend = 0; - uint32 addbss = 0; - - qoff64_t off = lc.nlm.codeoff; - if ( off != 0 ) - { - lend = lc.nlm.codelen; - if ( lend != 0 ) - { - lc.csize = lend; - lc.cbase = lc.start; - } - } - for ( int i = 1; ; ) - { - const char *pn, *pc; - segment_t s; - s.start_ea = lc.start; - s.end_ea = lc.start; - s.align = saRel4K; - s.bitness = 1; - s.comb = scPub; - s.sel = i; - if ( i == 1 ) - { - s.type = SEG_CODE; - pn = NAME_BSS; - pc = CLASS_CODE; - } - else - { - if ( lend == 0 ) - { - pn = NAME_BSS; - pc = CLASS_BSS; - } - else - { - pn = NAME_DATA; - pc = CLASS_DATA; - } - if ( lend != 0 || addbss ) - { - s.type = SEG_DATA; - lc.dbase = lc.start; - lc.dsize = lend; - } - } - if ( lend == 0 && !addbss ) - { - s.type = SEG_NULL; - lc.start += 0x1000; - } - else - { - if ( lend != 0 ) - { - s.end_ea += lend; - uint64 fsize = qlsize(lc.li); - if ( s.end_ea < s.start_ea || off > fsize || s.size() > fsize-off ) - loader_failure("Truncated input file"); - file2base(lc.li, off, s.start_ea, s.end_ea, FILEREG_PATCHABLE); - } - s.end_ea += addbss; - lc.start = (s.end_ea + 0xFFF) & ~0xFFF; - } - set_selector(s.sel, 0); - if ( !add_segm_ex(&s, pn, pc, ADDSEG_NOSREG | ADDSEG_SPARSE) ) - loader_failure(); -//- - if ( ++i > 2 ) - break; - addbss = lc.nlm.bssSize; - lend = ((off = lc.nlm.dataoff) == 0) ? 0 : lc.nlm.datalen; - } -} - -//-------------------------------------------------------------------------- -static void Unpack(void); -//-------------------------------------------------------------------------- -// -// load file into the database. -// -void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/) -{ - set_processor_type("metapc", SETPROC_LOADER); - add_til("nlm", ADDTIL_DEFAULT); - inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); - - if ( qlread(lc.li = li, &lc.nlm, sizeof(lc.nlm)) != sizeof(lc.nlm) ) - errstruct(); - if ( lc.nlm.version & NLM_COMPRESSED ) - Unpack(); - - lc.start = to_ea(inf_get_baseaddr(), 0); - memset(&lc.cbase, 0, sizeof(local_data) - qoffsetof(local_data, cbase)); - - load_image(); - set_default_dataseg(2); - - if ( lc.nlm.startIP < lc.csize ) - { - uval_t bip = lc.cbase + lc.nlm.startIP; - inf_set_start_cs(1); - inf_set_start_ip(bip); - add_entry(bip, bip, "nlm_start", 1); - } - if ( (lc.nlm.endIP || lc.nlm.startIP) && lc.nlm.endIP < lc.csize ) - { - uval_t eip = lc.cbase + lc.nlm.endIP; - add_entry(eip, eip, "nlm_terminate", 1); - } - if ( lc.nlm.auxIP && lc.nlm.auxIP < lc.csize ) - { - uval_t aip = lc.cbase + lc.nlm.auxIP; - add_entry(aip, aip, "nlm_check_unload", 1); - } - -// inf.nametype = NM_EA; -// inf.s_prefflag &= ~PREF_SEGADR; -// inf.start_ss = BADSEL; -// inf.start_sp = BADADDR; - inf_set_specsegs(inf_is_64bit() ? 8 : 4); - - add_imports(); - add_exports_and_publics(); - add_fixups(); - addComments(neflag & NEF_RSCS); - if ( lc.impnode ) - import_module("nlm_root", NULL, lc.impnode, NULL, "netware"); - inf_set_lowoff(inf_get_min_ea()); - - if ( lc.li != li ) - close_linput(lc.li); // close & delete tmp (unpack) file - - split_sreg_range(inf_get_start_ea(), PH.reg_data_sreg, 2, SR_autostart, true); -} - -//---------------------------------------------------------------------- -// -// LOADER DESCRIPTION BLOCK -// -//---------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; - -//===============unpack===================================================== -NORETURN static void memerr(void) -{ - nomem("NLM-loader (for unpacking)"); -} - -//========================================================================== -#define OUTSIZE 8192 //2**13 - -static void unp_process(void); - -static void Unpack(void) -{ - uint32 fsize; - FILE *fo; - - CASSERT(sizeof(lc) - qoffsetof(local_data, nlm) > 0x196); //-V658 value is being subtracted from the unsigned - CASSERT(qoffsetof(local_data,buf) == qoffsetof(local_data,nlm)+sizeof(lc.nlm)); - - if ( qlread(lc.li, lc.buf, 0x196-sizeof(lc.nlm)) != (0x196-sizeof(lc.nlm)) ) - errstruct(); - if ( lc.buf[0x190 - sizeof(lc.nlm )] != 1 - || lc.buf[0x191 - sizeof(lc.nlm)] != 10 ) - { - loader_failure("Unknown compressing method"); - } - if ( (fsize = *((uint32 *)&lc.buf[0x192 - sizeof(lc.nlm)])) <= 0x190 ) - errstruct(); - - if ( (fo = qtmpfile()) == NULL ) - loader_failure("Cannot create temporary file for decompressing"); - qfwrite(fo, &lc.nlm, 0x190); //lint !e426 - - lc.unp.buff = (uchar *)qalloc(OUTSIZE); - if ( lc.unp.buff == NULL ) - memerr(); - lc.unp.b_pos = 0x190; - lc.unp.pos = 0x190; - lc.unp.b_val = 0; - lc.unp.fo = fo; - lc.unp.size = fsize; - - msg("Decompressing module..."); - unp_process(); - - qfree(lc.unp.buff); - if ( qflush(lc.unp.fo) || ferror(lc.unp.fo) || feof(lc.unp.fo) ) - loader_failure("disk full or cannot write temporary file"); -// qlseek(fo, sizeof(nlm), SEEK_SET); - msg("Ok\n"); - lc.li = make_linput(lc.unp.fo); -} - -//========================================================================= -struct record -{ - record *left; - union - { - record *right; - uchar data; - }; -}; - -//===================================================================== -static void putUnpByte(uchar data) -{ - qfputc(data, lc.unp.fo); - ++lc.unp.pos; - lc.unp.buff[lc.unp.b_pos] = data; - if ( ++lc.unp.b_pos == OUTSIZE ) - lc.unp.b_pos = 0; -} - -//===================================================================== -static void putUnpRepeatBlk(ushort off, ushort sizeBlk) -{ - if ( !off || !sizeBlk || (uint32)off >= lc.unp.pos ) - errstruct(); - int pos = lc.unp.b_pos - off; - if ( pos < 0 ) - pos += OUTSIZE; - while ( true ) - { - putUnpByte(lc.unp.buff[pos]); - if ( --sizeBlk == 0 ) - break; - if ( ++pos == OUTSIZE ) - pos = 0; - } -} - -//===================================================================== -inline ushort nextbyte(void) -{ - uchar i; - if ( qlread(lc.li, &i, sizeof(i)) != sizeof(i) ) - errstruct(); - return i; -} - -//===================================================================== -ushort getNbit(int cnt) -{ - ushort res = 0; - ushort val = lc.unp.b_val; - int i = cnt; - do - { - if ( val <= 0xFF ) - val = nextbyte() | 0x8000; - res >>= 1; - if ( val & 1 ) - res |= 0x8000; - val >>= 1; - } while ( --i != 0 ); - lc.unp.b_val = val; - return res >> (16-cnt); -} - -//===================================================================== -static int getbit(void) -{ - if ( lc.unp.b_val <= 0xFF ) - lc.unp.b_val = nextbyte() | 0x8000; - int i = lc.unp.b_val & 1; - lc.unp.b_val >>= 1; - return i; -} - -//===================================================================== -inline uchar getbyte(void) -{ - if ( lc.unp.b_val <= 0xFF ) - return (uchar)nextbyte(); - return (uchar)getNbit(8); -} - -//===================================================================== -static uchar extractByte(const record *p) -{ - while ( p->left ) - p = getbit() ? p->right : p->left; - return p->data; -} - -//===================================================================== -static void free_record(record *p) -{ - if ( p->left ) - { - free_record(p->left); - free_record(p->right); - } - qfree(p); -} - -//===================================================================== -static record *load_record(void) -{ - record *p = (record *)qalloc(sizeof(record)); - if ( p == NULL ) - memerr(); - if ( getbit() ) - { - p->left = NULL; - p->data = getbyte(); - } - else - { - p->left = load_record(); - p->right = load_record(); - } - return p; -} - -//===================================================================== -static void unp_process(void) -{ - record *rOne = load_record(); - record *rKey = load_record(); - record *rPos = load_record(); - - while ( lc.unp.pos < lc.unp.size ) - { - if ( getbit() ) - { - putUnpByte(extractByte(rOne)); - continue; - } - ushort data = extractByte(rKey); - switch ( data ) - { - case 255: - { - uint32 cnt = 0; - lc.unp.b_val = 0; - int i = 8; - do - putUnpByte((uchar)nextbyte()); - while ( --i != 0 ); - do - { - uchar c; - putUnpByte(c = (uchar)nextbyte()); - cnt |= ((uint32)c << (i*8)); - } while ( ++i < 4 ); - while ( cnt-- ) - putUnpByte((uchar)nextbyte()); - } - break; - - case 254: - data = getNbit(13); - // fallthrough - default: - { - ushort off = getNbit(5); - off |=((ushort)extractByte(rPos) << 5); - putUnpRepeatBlk(off, data); - } - break; - } - } // while - if ( lc.unp.pos != lc.unp.size ) - errstruct(); - - free_record(rOne); - free_record(rKey); - free_record(rPos); -} - -#pragma pack(pop) diff --git a/idasdk75/ldr/os9/makefile b/idasdk75/ldr/os9/makefile deleted file mode 100644 index e896804..0000000 --- a/idasdk75/ldr/os9/makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROC=os9 - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)os9$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/mc68xx/notify_codes.hpp ../idaldr.h os9.cpp \ - os9.hpp diff --git a/idasdk75/ldr/pe/common.cpp b/idasdk75/ldr/pe/common.cpp deleted file mode 100644 index cac0b98..0000000 --- a/idasdk75/ldr/pe/common.cpp +++ /dev/null @@ -1,717 +0,0 @@ - -// unfortunately we cannot include map here because vs32 bombs trying to compile efd\di.cpp -//#include <map> -#include <auto.hpp> -#include "common.h" -#include "../idaldr.h" - -//------------------------------------------------------------------------ -#ifdef LOADER_SOURCE // building a loader? -AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...) -{ - va_list va; - va_start(va, format); - qstring question("AUTOHIDE REGISTRY\n"); - question.cat_vsprnt(format, va); - question.append("\nDo you wish to continue?"); - if ( ask_yn(ASKBTN_YES, "%s", question.c_str()) != ASKBTN_YES ) - { - loader_failure(NULL); - } - va_end(va); -} -#else -// for other purposes: just print the error message and continue -AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...) -{ - va_list va; - va_start(va, format); - qvprintf(format, va); - qprintf("\n"); - va_end(va); -} -#endif - -//------------------------------------------------------------------------ -inline bool pe64_to_pe(peheader_t &pe, const peheader64_t &pe64, bool silent, bool zero_bad_data) -{ - bool ok = true; - switch ( pe64.magic ) - { - default: - if ( !silent ) - { - ask_for_feedback("The input file has non-standard magic number (%x)", - pe64.magic); - } - ok = false; - /* no break */ - case MAGIC_P32: - case MAGIC_ROM: - case 0: - memcpy(&pe, &pe64, sizeof(pe)); - break; - case MAGIC_P32_PLUS: - // Copy the constant part - memcpy(&pe, &pe64, offsetof(peheader_t, stackres)); - - // Copy after the changed part - memcpy(&pe.loaderflags, &pe64.loaderflags, - sizeof(pe) - qoffsetof(peheader_t, loaderflags)); - - // Truncate the 64bit to 32bit - pe.stackres = low(pe64.stackres); - pe.stackcom = low(pe64.stackcom); - pe.heapres = low(pe64.heapres); - pe.heapcom = low(pe64.heapcom); - break; - } - // Do various checks - if ( !pe.is_efi() - && (pe.objalign < pe.filealign - || pe.filealign != 0 && (pe.filealign & (pe.filealign-1)) != 0 // check for power of 2 - || pe.objalign != 0 && (pe.objalign & (pe.objalign -1)) != 0) ) // check for power of 2 - { - if ( !silent ) - pe_failure("Invalid file: bad alignment value specified (section alignment: %08X, file alignment: %08X)", pe.objalign, pe.filealign); - } - if ( pe.imagesize > 0x77000000 || pe.imagesize < pe.allhdrsize ) - { - if ( !silent ) - pe_failure("Invalid file: bad ImageSize value %x", pe.imagesize); - } - - if ( zero_bad_data ) - { - if ( pe.nrvas != 0 && pe.nrvas < total_rvatab_count ) - memset(&pe.expdir + pe.nrvas, 0, total_rvatab_size - pe.nrvas * sizeof(petab_t)); - size_t fullhdrsize = pe.is_pe_plus() ? sizeof(pe64) : sizeof(pe); - size_t sectblstart = pe.first_section_pos(0); - // clear items covered by section table - if ( sectblstart < fullhdrsize - && total_rvatab_size < fullhdrsize - && sectblstart >= fullhdrsize - total_rvatab_size ) - { - if ( !silent ) - msg("Warning: image directories are covered by the section table, some entries will be ignored\n"); - size_t clearcount = (fullhdrsize - sectblstart + sizeof(petab_t) -1 )/ sizeof(petab_t); - memset(&pe.expdir + (total_rvatab_count- clearcount), 0, clearcount * sizeof(petab_t)); - } - } - return ok; -} - -//------------------------------------------------------------------------ -inline bool te_to_pe(peheader_t &pe, const teheader_t &te) -{ - bool ok = true; - memset(&pe, 0, sizeof(pe)); - pe.signature = te.signature; - pe.machine = te.machine; - pe.nobjs = te.nobjs; - pe.magic = pe.is_64bit_cpu() ? MAGIC_P32_PLUS : MAGIC_P32; - pe.entry = te.entry; - pe.text_start = te.text_start; - pe.allhdrsize = te.text_start + te.te_adjust(); - if ( pe.is_pe_plus() ) - pe.imagebase64 = te.imagebase64; - else - pe.imagebase32 = te.imagebase64; - pe.subsys = te.subsys; - pe.reltab = te.reltab; - pe.debdir = te.debdir; - pe.objalign = 1; - pe.filealign = 1; - return ok; -} - -//------------------------------------------------------------------------ -inline bool pe_loader_t::read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data) -{ - peoff = _peoff; - qlseek(li, peoff); - memset(&pe64, 0, sizeof(pe64)); - qlseek(li, peoff); - size_t size = qlread(li, &pe64, sizeof(pe64)); - size_t minsize = pe64.magic == MAGIC_P32_PLUS - ? qoffsetof(peheader64_t, subsys) - : qoffsetof(peheader_t, subsys); - bool ok = size > minsize - && size <= sizeof(pe64) - && (pe64.signature == PEEXE_ID || pe64.signature == BPEEXE_ID || pe64.signature == PLEXE_ID) - && pe64_to_pe(pe, pe64, silent, zero_bad_data); - if ( ok ) - { - //initialize imagebase for loading - set_imagebase((ea_t)pe.imagebase()); - } - return ok; -} - -//------------------------------------------------------------------------ -inline bool pe_loader_t::read_header(linput_t *li, bool silent, bool zero_bad_data) -{ - uint32 hdroff = 0; - link_ulink = false; - - qlseek(li, hdroff); - if ( qlread(li, &exe, sizeof(exe)) != sizeof(exe) ) - return false; - if ( exe.exe_ident != PEEXE_ID ) - { - if ( exe.exe_ident == TEEXE_ID ) - { - qlseek(li, hdroff); - if ( qlread(li, &te, sizeof(te)) != sizeof(te) ) - return false; - bool ok = te_to_pe(pe, te); - if ( ok ) - { - //initialize imagebase for loading - set_imagebase((ea_t)pe.imagebase()); - peoff = hdroff; - } - return ok; - } - if ( exe.exe_ident == EXE_ID || exe.exe_ident == EXE_ID2 ) - { - char tmp[8]; - if ( qlread(li, tmp, sizeof(tmp)) == sizeof(tmp) - && memcmp(tmp, "UniLink", 8) == 0 ) - { - link_ulink = true; - } - qlseek(li, PE_PTROFF); - if ( qlread(li, &hdroff, sizeof(hdroff)) != sizeof(hdroff) ) - return false; - } - } - return read_header(li, hdroff, silent, zero_bad_data); -} - -//------------------------------------------------------------------------ -// NB! We need to walk the mapping backwards, because -// the later sections take priority over earlier ones -// -// e.g. consider -// section 0: start=1000, end=5000, pos=1000 -// section 1: start=3000, end=4000, pos=5000 -// for byte at RVA 3500: -// section 0 maps it from the file offset 3500 -// but section 1 overrides it with the byte from file offset 5500! -// -inline ea_t pe_loader_t::map_ea(ea_t rva, const transl_t **tl) -{ - for ( ssize_t i=transvec.size()-1; i >= 0; i-- ) - { - const transl_t &trans = transvec[i]; - if ( trans.start <= rva && trans.end > rva ) - { - if ( tl != NULL ) - *tl = &trans; - return rva-trans.start + trans.pos; - } - } - return BADADDR; -} - -//------------------------------------------------------------------------ -inline bool pe_loader_t::vseek(linput_t *li, uint32 rva) -{ - ea_t fpos = get_linput_type(li) == LINPUT_PROCMEM ? rva : map_ea(rva); - if ( fpos != BADADDR ) - { - qlseek(li, fpos); - return true; - } - qlseek(li, rva, SEEK_SET); - return false; -} - -//------------------------------------------------------------------------ -inline char *pe_loader_t::asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok) -{ - vseek(li, rva); - buf[0] = '\0'; - char *ret = qlgetz(li, -1, buf, bufsize); - *ok = buf[0] != '\0'; - return ret; -} - -//------------------------------------------------------------------------ -// same as asciiz() but don't set ok to false for successfully read empty strings -inline char *pe_loader_t::asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok) -{ - vseek(li, rva); - buf[0] = '\0'; - //do not use qlgetz() here because we won't distinguish empty strings from read errors - ssize_t readsize = qlread(li, buf, bufsize-1); - if ( readsize < 0 || readsize >= bufsize ) - *ok = false; - else - buf[readsize] = '\0'; - return buf; -} - -//------------------------------------------------------------------------ -inline int pe_loader_t::process_sections( - linput_t *li, - off_t first_sec_pos, - int nobjs, - pe_section_visitor_t &psv) -{ - transvec.qclear(); - qvector<pesection_t> sec_headers; - // does the file layout match memory layout? - bool alt_align = pe.objalign == pe.filealign && pe.objalign < PAGE_SIZE; - qlseek(li, first_sec_pos); - validate_array_count(li, &nobjs, sizeof(pesection_t), "Number of sections", first_sec_pos); - for ( int i=0; i < nobjs; i++ ) - { - pesection_t &sh = sec_headers.push_back(); - if ( qlread(li, &sh, sizeof(sh)) != sizeof(sh) ) - return -1; - if ( sh.s_vaddr != uint32(sh.s_scnptr) || sh.s_vsize > sh.s_psize ) - alt_align = false; - } - if ( alt_align || pe.is_te() ) - { - // according to Ivan Teblin from AVERT Labs, such files are - // mapped by Windows as-is and not section by section - // we mimic that behaviour - int code = psv.load_all(); - if ( code != 0 ) - return code; - } - - int off_align = alt_align ? pe.filealign : FILEALIGN; - if ( pe.is_efi() || pe.is_te() ) - off_align = 1; - - uint32 max_va = 0; - for ( int i=0; i < nobjs; i++ ) - { - pesection_t &sh = sec_headers[i]; - uint32 scnptr = align_down(sh.s_scnptr, off_align);//pe.align_down_in_file(sh.s_scnptr); - transl_t &tr = transvec.push_back(); - tr.start = sh.s_vaddr; - tr.psize = sh.get_psize(pe); - tr.end = pe.align_up_in_file(uint32(sh.s_vaddr + tr.psize)); - tr.pos = scnptr; - if ( pe.is_te() ) - tr.pos += te.te_adjust(); - int code = psv.visit_section(sh, scnptr); - if ( code != 0 ) - return code; - if ( max_va < sh.s_vaddr + sh.s_vsize ) - max_va = sh.s_vaddr + sh.s_vsize; - } - if ( pe.is_te() ) - pe.imagesize = max_va; - if ( nobjs == 0 || alt_align ) - { - // add mapping for the header - transl_t tr; - tr.start = 0; - tr.psize = qlsize(li); - tr.end = pe.align_up_in_file(pe.imagesize); - tr.pos = 0; - // insert at the front so that it's always consulted last - transvec.insert(transvec.begin(), tr); - } - return 0; -} - -//------------------------------------------------------------------------ -inline int pe_loader_t::process_sections(linput_t *li, pe_section_visitor_t &psv) -{ - off_t first_sec_pos = pe.is_te() ? te.first_section_pos(peoff) : pe.first_section_pos(peoff); - return process_sections(li, first_sec_pos, pe.nobjs, psv); -} - -//------------------------------------------------------------------------ -inline int pe_loader_t::process_sections(linput_t *li) -{ - pe_section_visitor_t v; - return process_sections(li, v); -} - -//------------------------------------------------------------------------- -inline void to_utf8(char *buf, size_t bufsz, bool force=false) -{ - if ( force || !is_valid_utf8(buf) ) - { - qstring qbuf; - if ( idb_utf8(&qbuf, buf) ) - qstrncpy(buf, qbuf.c_str(), bufsz); - } -} - -//------------------------------------------------------------------------ -// process import table for one dll -inline int pe_loader_t::process_import_table( - linput_t *li, - ea_t atable, - ea_t ltable, - pe_import_visitor_t &piv) -{ - bool is_pe_plus = pe.is_pe_plus(); - uint32 elsize = piv.elsize = is_pe_plus ? 8 : 4; - const uint64 mask = is_pe_plus ? IMP_BY_ORD64 : IMP_BY_ORD32; - bool ok = true; - uint32 i; - for ( i=0; ok; i++, atable += elsize ) - { - char buf[MAXSTR]; - if ( !is_mul_ok(i, elsize) ) - return 1; - uval_t rva_off = i * elsize; - if ( !is_add_ok(ltable, rva_off) ) - return 1; - ea_t rva = ltable + rva_off; - if ( piv.withbase ) - rva -= (uval_t)pe.imagebase(); - uint32 fof = uint32(rva); - uint64 entry = is_pe_plus ? vaint64(li, fof, &ok) : valong(li, fof, &ok); - if ( entry == 0 ) - break; - show_addr(atable); - - int code; - if ( (entry & mask) == 0 ) // by name - { - ea_t nrva = (uval_t)entry + sizeof(short); - if ( piv.withbase ) - nrva -= (uval_t)pe.imagebase(); - fof = uint32(nrva); - asciiz2(li, fof, buf, sizeof(buf), &ok); - to_utf8(buf, sizeof(buf)); - code = piv.visit_import(atable, entry, buf); - } - else - { - // ordinals are always 32bit, even in pe64 - uint32 ord = entry & ~mask; - code = piv.visit_import(atable, ord, NULL); - } - if ( code != 0 ) - return code; - } - return piv.leave_module(i); -} - -//------------------------------------------------------------------------ -// this function tries to read from a file as if it was reading from memory -// if translation not found for the given RVA then ZEROs are returned -// in addition, if it tries to read beyond a translation physical size -// the additional bytes will be returned as zeros -inline bool pe_loader_t::vmread(linput_t *li, uint32 rva, void *buf, size_t sz) -{ - // clear whole user buffer - memset(buf, 0, sz); - - size_t may_read = sz; - if ( get_linput_type(li) == LINPUT_PROCMEM ) - { - qlseek(li, rva, SEEK_SET); - } - else - { - const transl_t *tr; - ea_t fpos = map_ea(rva, &tr); - - // cannot find translation? - if ( fpos == BADADDR ) - { - qlseek(li, int32(rva), SEEK_SET); - return true; - } - uint32 sectend = tr->pos + tr->psize; // section end - if ( fpos >= sectend ) - return false; // data not present in the input file - qlseek(li, fpos); - - // reading beyond section's limit? - uint32 after_read_pos = fpos + sz; - if ( after_read_pos < fpos ) - return false; // integer overflow - if ( after_read_pos >= sectend ) - { - // check if position belongs to the header and if reading beyond the limit - if ( uint32(fpos) < pe.allhdrsize && after_read_pos > pe.allhdrsize ) - may_read = pe.allhdrsize - size_t(fpos); - else - may_read = sectend - fpos; // just read as much as section limit allows - } - } - QASSERT(20045, ssize_t(may_read) >= 0); - return qlread(li, buf, may_read) == (ssize_t)may_read; -} - -//------------------------------------------------------------------------ -// process all imports of a pe file -// returns: -1:could not read an impdir; 0-ok; -// other values can be returned by the visitor -inline int pe_loader_t::process_imports(linput_t *li, pe_import_visitor_t &piv) -{ - if ( pe.impdir.rva == 0 ) - return 0; - - if ( transvec.empty() ) - process_sections(li); - - int code = 0; - for ( int ni=0; ; ni++ ) - { - off_t off = pe.impdir.rva + ni*sizeof(peimpdir_t); - peimpdir_t &id = piv.id; - - if ( !vmread(li, off, &id, sizeof(id)) ) - { - memset(&id, 0, sizeof(id)); - // we continue if the import descriptor is within the page belonging - // to the program - if ( map_ea(off) == BADADDR || map_ea(off+sizeof(id)-1) == BADADDR ) - { - code = piv.impdesc_error(off); - if ( code != 0 ) - break; - } - } - if ( id.dllname == 0 || id.looktab == 0 ) - break; - ea_t ltable = id.table1; // OriginalFirstThunk - ea_t atable = id.looktab; // FirstThunk - bool ok = true; - char dll[MAXSTR]; - asciiz(li, id.dllname, dll, sizeof(dll), &ok); - if ( !ok ) - break; - to_utf8(dll, sizeof(dll), /*force=*/ true); - if ( map_ea(ltable) == BADADDR - || ltable < pe.allhdrsize - || pe.imagesize != 0 && ltable >= pe.imagesize ) - { - ltable = atable; - } - atable += get_imagebase(); - code = piv.visit_module(dll, atable, ltable); - if ( code != 0 ) - break; - code = process_import_table(li, atable, ltable, piv); - if ( code != 0 ) - break; - } - return code; -} - -//------------------------------------------------------------------------ -inline int pe_loader_t::process_delayed_imports(linput_t *li, pe_import_visitor_t &il) -{ - if ( pe.didtab.rva == 0 ) - return 0; - - if ( transvec.empty() ) - process_sections(li); - - int code = 0; - uint32 ni = 0; - bool ok = true; - while ( true ) - { - uint32 table = pe.didtab.rva + ni*uint32(sizeof(dimpdir_t)); - if ( !vseek(li, table) ) - break; - dimpdir_t &id = il.did; - if ( qlread(li, &id, sizeof(id)) != sizeof(id) ) - return -1; - if ( !id.dllname ) - break; - il.withbase = (id.attrs & DIMP_NOBASE) == 0; - uval_t base = il.withbase ? 0 : uval_t(get_imagebase()); - ea_t atable = id.diat + base; - ea_t ltable = id.dint; - char dll[MAXSTR]; - uint32 off = uint32(il.withbase ? id.dllname - (ea_t)pe.imagebase() : id.dllname); - asciiz(li, off, dll, sizeof(dll), &ok); - if ( !ok ) - break; - to_utf8(dll, sizeof(dll), /*force=*/ true); - code = il.visit_module(dll, atable, ltable); - if ( code != 0 ) - break; - code = process_import_table(li, atable, ltable, il); - if ( code != 0 ) - break; - ni++; - } - return ok || code != 0 ? code : -1; -} - -//------------------------------------------------------------------------ -// process all exports of a pe file -// returns -2: could not read expdir, -1: other read errors, 0-ok, -// other values can be returned by the visitor -inline int pe_loader_t::process_exports(linput_t *li, pe_export_visitor_t &pev) -{ - if ( pe.expdir.rva == 0 ) - return 0; - if ( transvec.empty() ) - process_sections(li); - if ( !vseek(li, pe.expdir.rva) ) - return -2; - - // process export directory - bool fok = true; - char buf[MAXSTR]; - peexpdir_t ed; - if ( qlread(li, &ed, sizeof(ed)) != sizeof(ed) ) - return -1; - asciiz2(li, ed.dllname, buf, sizeof(buf), &fok); - to_utf8(buf, sizeof(buf), /*force=*/ true); - int code = pev.visit_expdir(ed, buf); - if ( code != 0 ) - return code; - - // I'd like to have a better validation - uint64 maxsize = qlsize(li) + 4096; - if ( maxsize > pe.expdir.size && pe.expdir.size != 0 ) - maxsize = pe.expdir.size; - validate_array_count(NULL, &ed.nnames, 6, "Number of exported names", - pe.expdir.rva, pe.expdir.rva+maxsize); - validate_array_count(NULL, &ed.naddrs, 4, "Number of exported addresses", - pe.expdir.rva, pe.expdir.rva+maxsize); - - // gather name information - typedef std::map<int, qstring> names_t; - names_t names; - int rcode = fok ? 0 : -1; - for ( uint32 i=0; i < ed.nnames; i++ ) - { - fok = true; - uint32 ordidx = vashort(li, ed.ordtab + i*sizeof(ushort), &fok); - if ( !fok ) - { - if ( rcode == 0 ) - rcode = -1; - continue; - } - ushort ord = ushort(ordidx + ed.ordbase); - uint32 rva = valong(li, ed.namtab + i*sizeof(uint32), &fok); - if ( !fok ) - { - if ( rcode == 0 ) - rcode = -1; - continue; - } - asciiz2(li, rva, buf, sizeof(buf), &fok); - if ( !fok ) - { - if ( rcode == 0 ) - rcode = -1; - continue; - } - to_utf8(buf, sizeof(buf)); - names[ord] = buf; - } - - // visit all exports - uint32 expdir_start_rva = pe.expdir.rva; - uint32 expdir_end_rva = pe.expdir.rva + maxsize; - - for ( uint32 i = 0; i < ed.naddrs; i++ ) - { - fok = true; - uint32 rva = valong(li, ed.adrtab + i*sizeof(uint32), &fok); - if ( rva != 0 && fok ) - { - uint32 ord = i + ed.ordbase; - names_t::iterator p = names.find(ord); - const char *name = p != names.end() ? p->second.c_str() : ""; - const char *forwarder = NULL; - if ( rva >= expdir_start_rva && rva < expdir_end_rva ) - { - // string inside export directory: this is a forwarded export - asciiz(li, rva, buf, sizeof(buf), &fok); - if ( !fok ) - { - if ( rcode == 0 ) - rcode = -1; - continue; - } - char *dot = strrchr(buf, '.'); - if ( dot != NULL ) - { - char before_dot[MAXSTR]; - char after_dot[MAXSTR]; - *dot = '\0'; - qstrncpy(before_dot, buf, sizeof(before_dot)); - qstrncpy(after_dot, dot+1, sizeof(after_dot)); - to_utf8(before_dot, sizeof(before_dot), /*force=*/ true); - to_utf8(after_dot, sizeof(after_dot), /*force=*/ false); - qsnprintf(buf, sizeof(buf), "%s.%s", before_dot, after_dot); - } - else - { - to_utf8(buf, sizeof(buf), /*force=*/ true); - } - forwarder = buf; - } - code = pev.visit_export(rva, ord, name, forwarder); - if ( code != 0 ) - { - if ( rcode == 0 ) - rcode = code; - } - } - else if ( !fok ) - rcode = -1; - } - - return rcode; -} - -//------------------------------------------------------------------------ -inline const char *get_pe_machine_name(uint16 machine) -{ - switch ( machine ) - { - case PECPU_80386: return "80386"; - case PECPU_80486: return "80486"; - case PECPU_80586: return "80586"; - case PECPU_SH3: return "SH3"; - case PECPU_SH3DSP: return "SH3DSP"; - case PECPU_SH3E: return "SH3E"; - case PECPU_SH4: return "SH4"; - case PECPU_SH5: return "SH5"; - case PECPU_ARM: return "ARM"; - case PECPU_ARMI: return "ARMI"; - case PECPU_ARMV7: return "ARMv7"; - case PECPU_EPOC: return "ARM EPOC"; - case PECPU_PPC: return "PPC"; - case PECPU_PPCFP: return "PPC FP"; - case PECPU_PPCBE: return "PPC BE"; - case PECPU_IA64: return "IA64"; - case PECPU_R3000: return "MIPS R3000"; - case PECPU_R4000: return "MIPS R4000"; - case PECPU_R6000: return "MIPS R6000"; - case PECPU_R10000: return "MIPS R10000"; - case PECPU_MIPS16: return "MIPS16"; - case PECPU_WCEMIPSV2: return "MIPS WCEv2"; - case PECPU_ALPHA: return "ALPHA"; - case PECPU_ALPHA64: return "ALPHA 64"; - case PECPU_AMD64: return "AMD64"; - case PECPU_ARM64: return "ARM64"; - case PECPU_M68K: return "M68K"; - case PECPU_MIPSFPU: return "MIPS FPU"; - case PECPU_MIPSFPU16: return "MIPS16 FPU"; - case PECPU_EBC: return "EFI Bytecode"; - case PECPU_AM33: return "AM33"; - case PECPU_M32R: return "M32R"; - case PECPU_CEF: return "CEF"; - case PECPU_CEE: return "CEE"; - case PECPU_TRICORE: return "TRICORE"; - } - return NULL; -} - diff --git a/idasdk75/ldr/pe/common.h b/idasdk75/ldr/pe/common.h deleted file mode 100644 index 1dda965..0000000 --- a/idasdk75/ldr/pe/common.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef _PE_LDR_COMMON_H_ -#define _PE_LDR_COMMON_H_ - -#define PAGE_SIZE 0x1000 -//------------------------------------------------------------------------ -struct pe_section_visitor_t -{ - virtual int idaapi visit_section(const pesection_t &, off_t /*file_offset*/) { return 0; } - virtual int idaapi load_all() { return 0; } - virtual ~pe_section_visitor_t(void) {} -}; - -//------------------------------------------------------------------------ -//-V:pe_import_visitor_t:730 not all members of a class are initialized inside the constructor -struct pe_import_visitor_t -{ - bool withbase; - int elsize; // initialized by process_import_table() - peimpdir_t id; - dimpdir_t did; - - pe_import_visitor_t(void) : withbase(false) {} - virtual int idaapi visit_module(const char * /*dll*/, ea_t /*iat_start*/, ea_t /*int_rva*/) { return 0; } - virtual int idaapi leave_module(uint32 /*nprocessed_imports*/) { return 0; } - // buf==NULL:by ordinal - virtual int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) = 0; - virtual int idaapi impdesc_error(off_t /*file_offset*/) { return 0; } - virtual ~pe_import_visitor_t(void) {} -}; - -//------------------------------------------------------------------------ -struct pe_export_visitor_t -{ - // this function will be called once at the start. - // it must return 0 to continue - virtual int idaapi visit_expdir(const peexpdir_t & /*ed*/, const char * /*modname*/) { return 0; } - // this function is called for each export. name is never NULL, forwarder may point to the forwarder function - // it must return 0 to continue - virtual int idaapi visit_export(uint32 rva, uint32 ord, const char *name, const char *forwarder) = 0; - virtual ~pe_export_visitor_t(void) {} -}; - -//------------------------------------------------------------------------ -class pe_loader_t -{ - int process_import_table( - linput_t *li, - ea_t atable, - ea_t ltable, - pe_import_visitor_t &piv); - template <class T> - T varead(linput_t *li, uint32 rva, bool *ok) - { - T x = 0; - bool _ok = vseek(li, rva) && qlread(li, &x, sizeof(x)) == sizeof(x); - if ( ok != NULL ) - *ok = _ok; - return x; - } -public: - struct transl_t - { - ea_t start; - ea_t end; - off_t pos; - size_t psize; - }; - typedef qvector<transl_t> transvec_t; - transvec_t transvec; - union - { - exehdr exe; - teheader_t te; - }; - peheader_t pe; - peheader64_t pe64; // original 64bit header, should not be used - // because all fields are copied to pe - // nb: imagebase is truncated during the copy! - ea_t load_imagebase; // imagebase used during loading; initialized from the PE header but can be changed by the user - off_t peoff; // offset to pe header - bool link_ulink; // linked with unilink? - - // low level functions - ea_t map_ea(ea_t rva, const transl_t **tr = NULL); - ea_t get_imagebase(void) const { return load_imagebase; } - void set_imagebase(ea_t newimagebase) { load_imagebase=newimagebase; } - virtual bool vseek(linput_t *li, uint32 rva); - inline uint16 vashort(linput_t *li, uint32 addr, bool *ok) { return varead<uint16>(li, addr, ok); } - inline uint32 valong(linput_t *li, uint32 addr, bool *ok) { return varead<uint32>(li, addr, ok); } - inline uint64 vaint64(linput_t *li, uint32 addr, bool *ok) { return varead<uint64>(li, addr, ok); } - char *asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok); - char *asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok); - int process_sections(linput_t *li, off_t fist_sec_pos, int nojbs, pe_section_visitor_t &psv); - int process_sections(linput_t *li, pe_section_visitor_t &psv); - // If 'zero_bad_data==true' (i.e., the default), extra 'directories' - // in the pe/pe64 headers will be set to zero. - bool read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data = true); - - // high level functions - bool read_header(linput_t *li, bool silent=false, bool zero_bad_data = true); - int process_sections(linput_t *li); - - int process_delayed_imports(linput_t *li, pe_import_visitor_t &il); - int process_imports(linput_t *li, pe_import_visitor_t &piv); - int process_exports(linput_t *li, pe_export_visitor_t &pev); - bool vmread(linput_t *li, uint32 rva, void *buf, size_t sz); - - virtual ~pe_loader_t(void) {} -}; - -#endif diff --git a/idasdk75/ldr/pe/pe.h b/idasdk75/ldr/pe/pe.h deleted file mode 100644 index 5ebbdc1..0000000 --- a/idasdk75/ldr/pe/pe.h +++ /dev/null @@ -1,1106 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. (2:5020/209@fidonet) - * ALL RIGHTS RESERVED. - * - */ - -// -// Portable Executable file format (MS Windows 95, MS Windows NT) -// - -#ifndef _PE_H_ -#define _PE_H_ - -#include <time.h> -#include <stddef.h> - -#pragma pack(push, 1) -//----------------------------------------------------------------------- -// -// 32-bit Portable EXE Header -// -//----------------------------------------------------------------------- -struct petab_t -{ - uint32 rva; // relative virtual address - uint32 size; // size -}; // PE va/size array element - -template <class pointer_t> -struct peheader_tpl -{ - int32 signature; // 00 Current value is "PE/0/0". - -#define PEEXE_ID 0x4550 // 'PE' followed by two zeroes -#define BPEEXE_ID 0x455042 // Borland's extenson for DPMI'host -#define PLEXE_ID 0x4C50 // 'PL', PharLap TNT DOS-Extender Lite file that uses real mode APIs -#define TEEXE_ID 0x5A56 // 'VZ', EFI Terse Executable - uint16 machine; // 04 This field specifies the type of CPU - // compatibility required by this image to run. - // The values are: -#define PECPU_UNKNOWN 0x0000 // unknown - -#define PECPU_80386 0x014C // 80386 -#define PECPU_80486 0x014D // 80486 -#define PECPU_80586 0x014E // 80586 - -#define PECPU_R3000 0x0162 // MIPS Mark I (R2000, R3000) -#define PECPU_R6000 0x0163 // MIPS Mark II (R6000) -#define PECPU_R4000 0x0166 // MIPS Mark III (R4000) -#define PECPU_R10000 0x0168 // MIPS Mark IV (R10000) -#define PECPU_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 -#define PECPU_MIPS16 0x0266 // MIPS16 -#define PECPU_MIPSFPU 0x0366 // MIPS with FPU -#define PECPU_MIPSFPU16 0x0466 // MIPS16 with FPU - -#define PECPU_ALPHA 0x0184 // DEC Alpha -#define PECPU_ALPHA64 0x0284 // Dec Alpha 64-bit - -#define PECPU_SH3 0x01A2 // SH3 -#define PECPU_SH3DSP 0x01A3 // SH3DSP -#define PECPU_SH3E 0x01A4 // SH3E -#define PECPU_SH4 0x01A6 // SH4 -#define PECPU_SH5 0x01A8 // SH5 - -#define PECPU_ARM 0x01C0 // ARM -#define PECPU_ARMI 0x01C2 // ARM with Thumb -#define PECPU_ARMV7 0x01C4 // ARMv7 (or higher) Thumb mode only - -#define PECPU_AM33 0x01D3 // Matsushita (Panasonic) AM33/MN10300 - -#define PECPU_PPC 0x01F0 // PowerPC -#define PECPU_PPCFP 0x01F1 // PowerPC with floating-point -#define PECPU_PPCBE 0x01F2 // PowerPC Big-Endian - -#define PECPU_M32R 0x9041 // M32R little-endian - -#define PECPU_IA64 0x0200 // Intel Itanium IA64 -#define PECPU_EPOC 0x0A00 // ARM EPOC -#define PECPU_AMD64 0x8664 // AMD64 (x64) -#define PECPU_ARM64 0xaa64 // ARMv8 in 64-bit mode -#define PECPU_M68K 0x0268 // Motorola 68000 series -#define PECPU_EBC 0x0EBC // EFI Bytecode -#define PECPU_CEF 0x0CEF // ? -#define PECPU_CEE 0xC0EE // ? -#define PECPU_TRICORE 0x0520 // TRICORE (Infineon) - - bool is_64bit_cpu(void) const - { - return machine == PECPU_AMD64 - || machine == PECPU_IA64 - || machine == PECPU_ARM64; - } - bool is_pc(void) const - { - return machine == PECPU_80386 - || machine == PECPU_80486 - || machine == PECPU_80586 - || machine == PECPU_AMD64; - } - bool is_mips(void) const - { - return machine == PECPU_R3000 - || machine == PECPU_R6000 - || machine == PECPU_R4000 - || machine == PECPU_R10000 - || machine == PECPU_WCEMIPSV2 - || machine == PECPU_MIPS16 - || machine == PECPU_MIPSFPU - || machine == PECPU_MIPSFPU16; - } - - bool is_arm(void) const - { - return machine == PECPU_ARM - || machine == PECPU_ARMI - || machine == PECPU_ARMV7; - } - - bool has_code16_bit(void) const - { - return is_arm() || is_mips(); - } - - uint16 nobjs; // 06 This field specifies the number of entries - // in the Object Table. - qtime32_t datetime; // 08 Used to store the time and date the file was - // created or modified by the linker. - uint32 symtof; // 0C Symbol Table Offset - uint32 nsyms; // 10 Number of Symbols in Symbol Table - uint16 hdrsize; // 14 This is the number of remaining bytes in the NT - // header that follow the FLAGS field. - uint16 flags; // 16 Flag bits for the image. 0000h Program image. -#define PEF_BRVHI 0x8000 // Big endian: MSB precedes LSB in memory -#define PEF_UP 0x4000 // File should be run only on a UP machine -#define PEF_DLL 0x2000 // Dynamic Link Library (DLL) -#define PEF_SYS 0x1000 // System file -#define PEF_NSWAP 0x0800 // If the image is on network media, fully load it and copy it to the swap file. -#define PEF_SWAP 0x0400 // If image is on removable media, - // copy and run from swap file -#define PEF_NODEB 0x0200 // Debugging info stripped -#define PEF_32BIT 0x0100 // 32-bit word machine -#define PEF_BRVLO 0x0080 // Little endian: LSB precedes MSB in memory -#define PEF_16BIT 0x0040 // 16-bit word machine -#define PEF_2GB 0x0020 // App can handle > 2gb addresses -#define PEF_TMWKS 0x0010 // Aggressively trim working set -#define PEF_NOSYM 0x0008 // Local symbols stripped -#define PEF_NOLIN 0x0004 // Line numbers stripped -#define PEF_EXEC 0x0002 // Image is executable -#define PEF_NOFIX 0x0001 // Relocation info stripped - - int32 first_section_pos(int32 peoff) const - { return peoff + offsetof(peheader_tpl, magic) + hdrsize; } - - // COFF fields: - - uint16 magic; // 18 Magic -#define MAGIC_ROM 0x107 // ROM image -#define MAGIC_P32 0x10B // Normal PE file -#define MAGIC_P32_PLUS 0x20B // 64-bit image - bool is_pe_plus(void) const { return magic == MAGIC_P32_PLUS; } - uchar vstamp_major; // 1A Major Linker Version - uchar vstamp_minor; // 1B Minor Linker Version - uint32 tsize; // 1C TEXT size (padded) - uint32 dsize; // 20 DATA size (padded) - uint32 bsize; // 24 BSS size (padded) - uint32 entry; // 28 Entry point - uint32 text_start; // 2C Base of text - union - { - struct - { - uint32 data_start; // 30 Base of data - - // Win32/NT extensions: - - uint32 imagebase32; // 34 Virtual base of the image. - }; - uint64 imagebase64; - }; - uint64 imagebase() const - { - if ( is_pe_plus() ) - return imagebase64; - else - return imagebase32; - } - // This will be the virtual address of the first - // byte of the file (Dos Header). This must be - // a multiple of 64K. - uint32 objalign; // 38 The alignment of the objects. This must be a power - // of 2 between 512 and 256M inclusive. The default - // is 64K. - uint32 filealign; // 3C Alignment factor used to align image pages. - // The alignment factor (in bytes) used to align the - // base of the image pages and to determine the - // granularity of per-object trailing zero pad. - // Larger alignment factors will cost more file space; - // smaller alignment factors will impact demand load - // performance, perhaps significantly. Of the two, - // wasting file space is preferable. This value - // should be a power of 2 between 512 and 64K inclusive. - // Get the file position aligned: -#define FILEALIGN 512 // IDA5.1: it seems that for standard object alignment (if 4096) - // the Windows kernel does not use filealign - // (just checks that it is in the valid range) but uses 512 - uint32 get_align_mask(void) const { return ((objalign == 4096 || filealign == 0) ? FILEALIGN : filealign) - 1; } - uint32 align_up_in_file(uint32 pos) const - { - if ( is_efi() ) //apparently EFI images are not aligned - return pos; - uint32 mask = get_align_mask(); - return (pos+mask) & ~mask; - } - uint32 align_down_in_file(uint32 pos) const - { - return is_efi() ? pos : (pos & ~get_align_mask()); - } - uint16 osmajor; // 40 OS version number required to run this image. - uint16 osminor; // 42 OS version number required to run this image. - uint16 imagemajor; // 44 User major version number. - uint16 imageminor; // 46 User minor version number. - uint16 subsysmajor; // 48 Subsystem major version number. - uint16 subsysminor; // 4A Subsystem minor version number. - - uint32 subsystem_version(void) const - { - return (subsysmajor << 16) | subsysminor; - } - - uint32 reserved; // 4C - uint32 imagesize; // 50 The virtual size (in bytes) of the image. - // This includes all headers. The total image size - // must be a multiple of Object Align. - uint32 allhdrsize; // 54 Total header size. The combined size of the Dos - // Header, PE Header and Object Table. - uint32 checksum; // 58 Checksum for entire file. Set to 0 by the linker. - uint16 subsys; // 5C NT Subsystem required to run this image. -#define PES_UNKNOWN 0x0000 // Unknown -#define PES_NATIVE 0x0001 // Native -#define PES_WINGUI 0x0002 // Windows GUI -#define PES_WINCHAR 0x0003 // Windows Character -#define PES_OS2CHAR 0x0005 // OS/2 Character -#define PES_POSIX 0x0007 // Posix Character -#define PES_NAT9x 0x0008 // image is a native Win9x driver -#define PES_WINCE 0x0009 // Runs on Windows CE. -#define PES_EFI_APP 0x000A // EFI application. -#define PES_EFI_BDV 0x000B // EFI driver that provides boot services. -#define PES_EFI_RDV 0x000C // EFI driver that provides runtime services. -#define PES_EFI_ROM 0x000D // EFI ROM image -#define PES_XBOX 0x000E // Xbox system -#define PES_BOOTAPP 0x0010 // Windows Boot Application - - bool is_efi(void) const - { - return subsys == PES_EFI_APP - || subsys == PES_EFI_BDV - || subsys == PES_EFI_RDV - || subsys == PES_EFI_ROM; - } - bool is_console_app(void) const - { - return subsys == PES_WINCHAR - || subsys == PES_OS2CHAR - || subsys == PES_POSIX; - } - bool is_userland(void) const - { - return subsys == PES_WINGUI - || subsys == PES_WINCHAR - || subsys == PES_OS2CHAR - || subsys == PES_POSIX - || subsys == PES_WINCE; - } - uint16 dllflags; // 5E Indicates special loader requirements. -#define PEL_PINIT 0x0001 // Per-Process Library Initialization. -#define PEL_PTERM 0x0002 // Per-Process Library Termination. -#define PEL_TINIT 0x0004 // Per-Thread Library Initialization. -#define PEL_TTERM 0x0008 // Per-Thread Library Termination. -#define PEL_HIGH_ENT 0x0020 // Image can handle a high entropy 64-bit virtual address space. -#define PEL_DYNAMIC_BASE 0x0040 // The DLL can be relocated at load time. -#define PEL_FORCE_INTEGRITY 0x0080 // Code integrity checks are forced. -#define PEF_NX 0x0100 // The image is compatible with data execution prevention (DEP). -#define PEF_NO_ISOLATION 0x0200 // The image is isolation aware, but should not be isolated. -#define PEF_NO_SEH 0x0400 // The image does not use structured exception handling (SEH). No handlers can be called in this image. -#define PEL_NO_BIND 0x0800 // Do not bind image -#define PEL_APPCONTAINER 0x1000 // Image should execute in an AppContainer -#define PEL_WDM_DRV 0x2000 // Driver is a WDM Driver -#define PEL_GUARDCF 0x4000 // Image supports Control Flow Guard checking -#define PEL_TSRVAWA 0x8000 // Image is Terminal Server aware - - pointer_t stackres; // 60 Stack size needed for image. The memory is - // reserved, but only the STACK COMMIT SIZE is - // committed. The next page of the stack is a - // 'guarded page'. When the application hits the - // guarded page, the guarded page becomes valid, - // and the next page becomes the guarded page. - // This continues until the RESERVE SIZE is reached. - pointer_t stackcom; // 64 Stack commit size. - pointer_t heapres; // 68 Size of local heap to reserve. - pointer_t heapcom; // 6C Amount to commit in local heap. - uint32 loaderflags; // 70 ? - uint32 nrvas; // 74 Indicates the size of the VA/SIZE array - // that follows. - petab_t expdir; // 0 78 Export Directory - petab_t impdir; // 1 80 Import Directory - petab_t resdir; // 2 88 Resource Directory - petab_t excdir; // 3 90 Exception Directory - petab_t secdir; // 4 98 Security Directory - // The Certificate Table entry points to a table of - // attribute certificates. These certificates are not - // loaded into memory as part of the image. As such, - // the first field of this entry, which is normally - // an RVA, is a File Pointer instead - petab_t reltab; // 5 A0 Relocation Table - petab_t debdir; // 6 A8 Debug Directory - petab_t desstr; // 7 B0 Description String - petab_t cputab; // 8 B8 Machine Value - petab_t tlsdir; // 9 C0 TLS Directory - petab_t loddir; //10 Load Configuration Directory - petab_t bimtab; //11 Bound Import Table address and size. - petab_t iat; //12 Import Address Table address and size. - petab_t didtab; //13 Address and size of the Delay Import Descriptor. - petab_t comhdr; //14 COM+ Runtime Header address and size - petab_t x00tab; //15 Reserved - - bool is_te() const - { return signature == TEEXE_ID; } - inline bool has_debdir() const; -}; - -typedef peheader_tpl<uint32> peheader_t; -typedef peheader_tpl<uint64> peheader64_t; - -constexpr size_t total_rvatab_size = sizeof(peheader_t) - offsetof(peheader_t, expdir); -constexpr size_t total_rvatab_count = total_rvatab_size / sizeof(petab_t); - -//----------------------------------------------------------------------- -struct diheader_t -{ - uint16 signature; // 00 Current value is "DI" -#define DBG_ID 0x4944 - uint16 flags2; // 02 ?? pedump mentions about this - // I've never seen something other than 0 - uint16 machine; // 04 This field specifies the type of CPU - // compatibility required by this image to run. - uint16 flags; // 06 Flag bits for the image. - qtime32_t datetime; // 08 Used to store the time and date the file was - // created or modified by the linker. - uint32 checksum; // 12 Checksum - uint32 imagebase; // 16 Virtual base of the image. - // This will be the virtual address of the first - // byte of the file (Dos Header). This must be - // a multiple of 64K. - uint32 imagesize; // 20 The virtual size (in bytes) of the image. - // This includes all headers. The total image size - // must be a multiple of Object Align. - uint32 n_secs; // 24 Number of sections - uint32 exp_name_size; // 28 Exported Names Size - uint32 dbg_dir_size; // 32 Debug Directory Size - uint32 reserved[3]; // 36 Reserved fields -}; - -//------------------------------------------------------------------------- -// -// S E C T I O N S -// -struct pesection_t -{ - char s_name[8]; /* section name */ - uint32 s_vsize; /* virtual size */ - uint32 s_vaddr; /* virtual address */ - uint32 s_psize; /* physical size */ - int32 s_scnptr; /* file ptr to raw data for section */ - int32 s_relptr; /* file ptr to relocation */ - int32 s_lnnoptr; /* file ptr to line numbers */ - uint16 s_nreloc; /* number of relocation entries */ - uint16 s_nlnno; /* number of line number entries */ - int32 s_flags; /* flags */ -#define PEST_REG 0x00000000 // obsolete: regular: allocated, relocated, loaded -#define PEST_DUMMY 0x00000001 // obsolete: dummy: not allocated, relocated, not loaded -#define PEST_NOLOAD 0x00000002 // obsolete: noload: allocated, relocated, not loaded -#define PEST_GROUP 0x00000004 // obsolete: grouped: formed of input sections -#define PEST_PAD 0x00000008 // obsolete: padding: not allocated, not relocated, loaded -#define PEST_COPY 0x00000010 // obsolete: copy: for decision function used - // by field update; not - // allocated, not relocated, - // loaded; reloc & lineno - // entries processed normally */ -#define PEST_TEXT 0x00000020L// section contains text only -#define PEST_DATA 0x00000040L// section contains data only -#define PEST_BSS 0x00000080L// section contains bss only -#define PEST_EXCEPT 0x00000100L// obsolete: Exception section -#define PEST_INFO 0x00000200L// Comment: not allocated, not relocated, not loaded -#define PEST_OVER 0x00000400L// obsolete: Overlay: not allocated, relocated, not loaded -#define PEST_LIB 0x00000800L// ".lib" section: treated like PEST_INFO - -#define PEST_LOADER 0x00001000L// Loader section: COMDAT -#define PEST_DEBUG 0x00002000L// Debug section: -#define PEST_TYPCHK 0x00004000L// Type check section: -#define PEST_OVRFLO 0x00008000L// obsolete: RLD and line number overflow sec hdr -#define PEST_F0000 0x000F0000L// Unknown -#define PEST_ALIGN 0x00F00000L// Alignment 2^(x-1): - uint32 get_sect_alignment(void) const - { - int align = ((s_flags >> 20) & 15); - return align == 0 ? 0 : (1 << (align-1)); - } - - asize_t get_vsize(const peheader_t &pe) const - { - return align_up(s_vsize ? s_vsize : s_psize, pe.objalign ? pe.objalign : 1); - } - - asize_t get_psize(const peheader_t &pe) const - { - return qmin(s_psize, get_vsize(pe)); - } - -#define PEST_1000000 0x01000000L// Unknown -#define PEST_DISCARD 0x02000000L// Discardable -#define PEST_NOCACHE 0x04000000L// Not cachable -#define PEST_NOPAGE 0x08000000L// Not pageable -#define PEST_SHARED 0x10000000L// Shareable -#define PEST_EXEC 0x20000000L// Executable -#define PEST_READ 0x40000000L// Readable -#define PEST_WRITE 0x80000000L// Writable -}; - -//------------------------------------------------------------------------- -// -// E X P O R T S -// -struct peexpdir_t -{ - uint32 flags; // Currently set to zero. - qtime32_t datetime; // Time/Date the export data was created. - uint16 major; // A user settable major/minor version number. - uint16 minor; - uint32 dllname; // Relative Virtual Address of the Dll asciiz Name. - // This is the address relative to the Image Base. - uint32 ordbase; // First valid exported ordinal. This field specifies - // the starting ordinal number for the export - // address table for this image. Normally set to 1. - uint32 naddrs; // Indicates number of entries in the Export Address - // Table. - uint32 nnames; // This indicates the number of entries in the Name - // Ptr Table (and parallel Ordinal Table). - uint32 adrtab; // Relative Virtual Address of the Export Address - // Table. This address is relative to the Image Base. - uint32 namtab; // Relative Virtual Address of the Export Name Table - // Pointers. This address is relative to the - // beginning of the Image Base. This table is an - // array of RVA's with # NAMES entries. - uint32 ordtab; // Relative Virtual Address of Export Ordinals - // Table Entry. This address is relative to the - // beginning of the Image Base. -}; - -//------------------------------------------------------------------------- -// -// I M P O R T S -// -struct peimpdir_t -{ - uint32 table1; //aka OriginalFirstThunk - qtime32_t datetime; // Time/Date the import data was pre-snapped or - // zero if not pre-snapped. - uint32 fchain; // Forwarder chain - uint32 dllname; // Relative Virtual Address of the Dll asciiz Name. - // This is the address relative to the Image Base. - uint32 looktab; // aka FirstThunk - // This field contains the address of the start of - // the import lookup table for this image. The address - // is relative to the beginning of the Image Base. -#define hibit(type) ((type(-1)>>1) ^ type(-1)) -#define IMP_BY_ORD32 hibit(uint32) // Import by ordinal, otherwise by name -#define IMP_BY_ORD64 hibit(uint64) // Import by ordinal, otherwise by name - - peimpdir_t(void) { memset(this, 0, sizeof(peimpdir_t)); } -}; - -struct dimpdir_t // delayed load import table -{ - uint32 attrs; // Attributes. -#define DIMP_NOBASE 0x0001 // pe.imagebase was not added to addresses - uint32 dllname; // Relative virtual address of the name of the DLL - // to be loaded. The name resides in the read-only - // data section of the image. - uint32 handle; // Relative virtual address of the module handle - // (in the data section of the image) of the DLL to - // be delay-loaded. Used for storage by the routine - // supplied to manage delay-loading. - uint32 diat; // Relative virtual address of the delay-load import - // address table. See below for further details. - uint32 dint; // Relative virtual address of the delay-load name - // table, which contains the names of the imports - // that may need to be loaded. Matches the layout of - // the Import Name Table, Section 6.4.3. Hint/Name Table. - uint32 dbiat; // Bound Delay Import Table. Relative virtual address - // of the bound delay-load address table, if it exists. - uint32 duiat; // Unload Delay Import Table. Relative virtual address - // of the unload delay-load address table, if it exists. - // This is an exact copy of the Delay Import Address - // Table. In the event that the caller unloads the DLL, - // this table should be copied back over the Delay IAT - // such that subsequent calls to the DLL continue to - // use the thunking mechanism correctly. - qtime32_t datetime; // Time stamp of DLL to which this image has been bound. -}; - - -// Bound Import Table format: - -struct BOUND_IMPORT_DESCRIPTOR -{ - qtime32_t TimeDateStamp; - uint16 OffsetModuleName; - uint16 NumberOfModuleForwarderRefs; -// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows -}; - -struct BOUND_FORWARDER_REF -{ - qtime32_t TimeDateStamp; - uint16 OffsetModuleName; - uint16 Reserved; -}; - - -//------------------------------------------------------------------------- -// -// T H R E A D L O C A L D A T A -// - -struct image_tls_directory64 -{ - uint64 StartAddressOfRawData; - uint64 EndAddressOfRawData; - uint64 AddressOfIndex; // PDWORD - uint64 AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; - uint32 SizeOfZeroFill; - uint32 Characteristics; -}; - -struct image_tls_directory32 -{ - uint32 StartAddressOfRawData; - uint32 EndAddressOfRawData; - uint32 AddressOfIndex; // PDWORD - uint32 AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * - uint32 SizeOfZeroFill; - uint32 Characteristics; -}; - -//------------------------------------------------------------------------- -// -// Exception Tables (.pdata) -// - -//ARM, PowerPC, SH3 and SH4 WindowsCE platforms -struct function_entry_ce -{ - uint32 FuncStart; // Virtual address of the corresponding function. - uint32 PrologLen : 8; // Number of instructions in the function's prolog. - uint32 FuncLen : 22; // Number of instructions in the function. - uint32 ThirtyTwoBit : 1; // Set if the function is comprised of 32-bit instructions, cleared for a 16-bit function. - uint32 ExceptionFlag : 1; // Set if an exception handler exists for the function. -}; - -// ARMv7 -struct function_entry_armv7 -{ - uint32 BeginAddress; // The RVA of the corresponding function - uint32 UnwindInfo; // The RVA of the unwind information, including function length. - // If the low 2 bits are non-zero, then this word represents a - // compacted inline form of the unwind information, - // including function length. -}; - -//for MIPS and 32-bit Alpha -struct function_entry_alpha -{ - uint32 BeginAddress; // Virtual address of the corresponding function. - uint32 EndAddress; // Virtual address of the end of the function. - uint32 ExceptionHandler; // Pointer to the exception handler to be executed. - uint32 HandlerData; // Pointer to additional information to be passed to the handler. - uint32 PrologEndAddress; // Virtual address of the end of the function's prolog. -}; - -//x64 -typedef enum _UNWIND_OP_CODES -{ - UWOP_PUSH_NONVOL = 0, // info == register number - UWOP_ALLOC_LARGE =1, // alloc size/8 in next 1(info=0) or 2(info=1) slots - UWOP_ALLOC_SMALL =2, // info == size of allocation / 8 - 1 - UWOP_SET_FPREG = 3, // FP = RSP + UNWIND_INFO.FPRegOffset*16 - UWOP_SAVE_NONVOL = 4, // info == register number, offset/8 in next slot - UWOP_SAVE_NONVOL_FAR=5,// info == register number, offset/8 in next 2 slots - UWOP_SAVE_XMM = 6, // Version 1: info == XMM reg number, offset/8 in next slot - UWOP_EPILOG = 6, // Version 2; code offset is epilog size; - UWOP_SAVE_XMM_FAR=7, // version 1:info == XMM reg number, offset/8 in next 2 slots - UWOP_SPARE_CODE = 7, // unused ("previously 64-bit UWOP_SAVE_XMM_FAR"); skip 2 slots - UWOP_SAVE_XMM128 = 8, // info == XMM reg number, offset/16 in next slot - UWOP_SAVE_XMM128_FAR = 9,// info == XMM reg number, offset/16 in next 2 slots - UWOP_PUSH_MACHFRAME = 10,// info == 0: no error-code, 1: with error code -} UNWIND_CODE_OPS; - - -// Define unwind information flags. -// - -#define UNW_FLAG_NHANDLER 0x0 -#define UNW_FLAG_EHANDLER 0x1 -#define UNW_FLAG_UHANDLER 0x2 -#define UNW_FLAG_CHAININFO 0x4 - -//------------------------------------------------------------------------- -// -// F I X U P S -// -struct pefixup_t -{ - uint32 page;// The image base plus the page rva is added to each offset - // to create the virtual address of where the fixup needs to - // be applied. - uint32 size;// Number of bytes in the fixup block. This includes the - // PAGE RVA and SIZE fields. -}; - -#define PER_OFF 0x0FFF -#define PER_TYPE 0xF000 -#define PER_ABS 0x0000 // This is a NOP. The fixup is skipped. -#define PER_HIGH 0x1000 // Add the high 16-bits of the delta to the - // 16-bit field at Offset. The 16-bit field - // represents the high value of a 32-bit word. -#define PER_LOW 0x2000 // Add the low 16-bits of the delta to the - // 16-bit field at Offset. The 16-bit field - // represents the low half value of a - // 32-bit word. This fixup will only be - // emitted for a RISC machine when the image - // Object Align isn't the default of 64K. -#define PER_HIGHLOW 0x3000 // Apply the 32-bit delta to the 32-bit field - // at Offset. -#define PER_HIGHADJUST 0x4000 // This fixup requires a full 32-bit value. - // The high 16-bits is located at Offset, and - // the low 16-bits is located in the next - // Offset array element (this array element - // is included in the SIZE field). The two - // need to be combined into a signed variable. - // Add the 32-bit delta. Then add 0x8000 and - // store the high 16-bits of the signed - // variable to the 16-bit field at Offset. -#define PER_REL5000 0x5000 // Machine-specific -#define PER_SECTION 0x6000 // Reserved for future use -#define PER_REL32 0x7000 // Relative intrasection -#define PER_REL7000 0x7000 // Machine-specific -#define PER_REL8000 0x8000 // Machine-specific -#define PER_REL9000 0x9000 // Machine-specific -#define PER_DIR64 0xA000 // This fixup applies the delta to the 64-bit - // field at Offset -#define PER_HIGH3ADJ 0xB000 // The fixup adds the high 16 bits of the delta - // to the 16-bit field at Offset. The 16-bit - // field represents the high value of a 48-bit - // word. The low 32 bits of the 48-bit value are - // stored in the 32-bit word that follows this - // base relocation. This means that this base - // relocation occupies three slots. - -// Platform-specific based relocation types. - -#define PER_IA64_IMM64 0x9000 - -#define PER_MIPS_JMPADDR 0x5000 // base relocation applies to a MIPS jump instruction. -#define PER_MIPS_JMPADDR16 0x9000 // base relocation applies to a MIPS16 jump instruction. - -#define PER_ARM_MOV32A 0x5000 // base relocation applies the difference to the - // 32-bit value encoded in the immediate fields of - // a contiguous MOVW+MOVT pair in ARM mode at offset. -#define PER_ARM_MOV32T 0x7000 // base relocation applies the difference to the - // 32-bit value encoded in the immediate fields of - // a contiguous MOVW+MOVT pair in Thumb mode at offset. - - -//------------------------------------------------------------------------- -// -// DBG file debug entry format -// -struct debug_entry_t -{ - uint32 flags; // usually zero - qtime32_t datetime; - uint16 major; - uint16 minor; - int32 type; -#define DBG_COFF 1 -#define DBG_CV 2 -#define DBG_FPO 3 -#define DBG_MISC 4 -#define DBG_EXCEPTION 5 -#define DBG_FIXUP 6 -#define DBG_OMAP_TO_SRC 7 -#define DBG_OMAP_FROM_SRC 8 -#define DBG_BORLAND 9 -#define DBG_RES10 10 -#define DBG_CLSID 11 -#define DBG_VCFEATURE 12 -#define DBG_POGO 13 -#define DBG_ILTCG 14 -#define DBG_MPX 15 - uint32 size; - uint32 rva; // virtual address - uint32 seek; // ptr to data in the file -}; - -// now we can define has_debdir() because we have debug_entry_t defined -template<> -inline bool peheader_t::has_debdir() const - { return debdir.size >= sizeof(debug_entry_t) && debdir.rva != 0; } - -//------------------------------------------------------------------------- -// -// DBG file COFF debug information header -// -struct coff_debug_t -{ - uint32 NumberOfSymbols; - uint32 LvaToFirstSymbol; - uint32 NumberOfLinenumbers; - uint32 LvaToFirstLinenumber; - uint32 RvaToFirstByteOfCode; - uint32 RvaToLastByteOfCode; - uint32 RvaToFirstByteOfData; - uint32 RvaToLastByteOfData; -}; - -//------------------------------------------------------------------------- -// -// DBG file FPO debug information -// -struct fpo_t -{ - uint32 address; - uint32 size; - uint32 locals; - uint16 params; - uchar prolog; - uchar regs; -#define FPO_REGS 0x07 // register number -#define FPO_SEH 0x08 // -#define FPO_BP 0x10 // has BP frame? -#define FPO_TYPE 0xC0 -#define FPO_T_FPO 0x00 -#define FPO_T_TRAP 0x40 -#define FPO_T_TSS 0x80 -#define FPO_T_NONFPO 0xC0 -}; - - -// DBG file OMAP debug information - -struct omap_t -{ - uint32 a1; - uint32 a2; -}; - -// misc entry format -struct misc_debug_t -{ - uint32 type; // type of misc data, see defines -#define MISC_EXENAME 1 - uint32 length; // total length of record, rounded to four - // byte multiple. - uchar unicode; // TRUE if data is unicode string - uchar reserved[3]; // padding - uchar data[1]; // Actual data -}; - -//---------------------------------------------------------------------- -// Resource information -struct rsc_dir_t -{ - uint32 Characteristics; - uint32 TimeDateStamp; - uint16 MajorVersion; - uint16 MinorVersion; - uint16 NumberOfNamedEntries; - uint16 NumberOfIdEntries; -}; - -struct rsc_dir_entry_t -{ - union - { - struct - { - uint32 NameOffset:31; - uint32 NameIsString:1; - }; - uint32 Name; - uint16 Id; - }; - union - { - uint32 OffsetToData; - struct - { - uint32 OffsetToDirectory:31; - uint32 DataIsDirectory:1; - }; - }; -}; - -struct rsc_data_entry_t -{ - uint32 OffsetToData; - uint32 Size; - uint32 CodePage; - uint32 Reserved; -}; - - -// Resource types -#define PE_RT_CURSOR 1 -#define PE_RT_BITMAP 2 -#define PE_RT_ICON 3 -#define PE_RT_MENU 4 -#define PE_RT_DIALOG 5 -#define PE_RT_STRING 6 -#define PE_RT_FONTDIR 7 -#define PE_RT_FONT 8 -#define PE_RT_ACCELERATOR 9 -#define PE_RT_RCDATA 10 -#define PE_RT_MESSAGETABLE 11 -#define PE_RT_GROUP_CURSOR 12 -#define PE_RT_GROUP_ICON 14 -#define PE_RT_VERSION 16 -#define PE_RT_DLGINCLUDE 17 -#define PE_RT_PLUGPLAY 19 -#define PE_RT_VXD 20 -#define PE_RT_ANICURSOR 21 -#define PE_RT_ANIICON 22 -#define PE_RT_HTML 23 -#define PE_RT_MANIFEST 24 - -// Language codes -#define PE_LANG_NEUTRAL 0x00 -#define PE_LANG_INVARIANT 0x7f - -#define PE_LANG_AFRIKAANS 0x36 -#define PE_LANG_ALBANIAN 0x1c -#define PE_LANG_ARABIC 0x01 -#define PE_LANG_ARMENIAN 0x2b -#define PE_LANG_ASSAMESE 0x4d -#define PE_LANG_AZERI 0x2c -#define PE_LANG_BASQUE 0x2d -#define PE_LANG_BELARUSIAN 0x23 -#define PE_LANG_BENGALI 0x45 -#define PE_LANG_BULGARIAN 0x02 -#define PE_LANG_CATALAN 0x03 -#define PE_LANG_CHINESE 0x04 -#define PE_LANG_CROATIAN 0x1a -#define PE_LANG_CZECH 0x05 -#define PE_LANG_DANISH 0x06 -#define PE_LANG_DIVEHI 0x65 -#define PE_LANG_DUTCH 0x13 -#define PE_LANG_ENGLISH 0x09 -#define PE_LANG_ESTONIAN 0x25 -#define PE_LANG_FAEROESE 0x38 -#define PE_LANG_FARSI 0x29 -#define PE_LANG_FINNISH 0x0b -#define PE_LANG_FRENCH 0x0c -#define PE_LANG_GALICIAN 0x56 -#define PE_LANG_GEORGIAN 0x37 -#define PE_LANG_GERMAN 0x07 -#define PE_LANG_GREEK 0x08 -#define PE_LANG_GUJARATI 0x47 -#define PE_LANG_HEBREW 0x0d -#define PE_LANG_HINDI 0x39 -#define PE_LANG_HUNGARIAN 0x0e -#define PE_LANG_ICELANDIC 0x0f -#define PE_LANG_INDONESIAN 0x21 -#define PE_LANG_ITALIAN 0x10 -#define PE_LANG_JAPANESE 0x11 -#define PE_LANG_KANNADA 0x4b -#define PE_LANG_KASHMIRI 0x60 -#define PE_LANG_KAZAK 0x3f -#define PE_LANG_KONKANI 0x57 -#define PE_LANG_KOREAN 0x12 -#define PE_LANG_KYRGYZ 0x40 -#define PE_LANG_LATVIAN 0x26 -#define PE_LANG_LITHUANIAN 0x27 -#define PE_LANG_MACEDONIAN 0x2f // the Former Yugoslav Republic of Macedonia -#define PE_LANG_MALAY 0x3e -#define PE_LANG_MALAYALAM 0x4c -#define PE_LANG_MANIPURI 0x58 -#define PE_LANG_MARATHI 0x4e -#define PE_LANG_MONGOLIAN 0x50 -#define PE_LANG_NEPALI 0x61 -#define PE_LANG_NORWEGIAN 0x14 -#define PE_LANG_ORIYA 0x48 -#define PE_LANG_POLISH 0x15 -#define PE_LANG_PORTUGUESE 0x16 -#define PE_LANG_PUNJABI 0x46 -#define PE_LANG_ROMANIAN 0x18 -#define PE_LANG_RUSSIAN 0x19 -#define PE_LANG_SANSKRIT 0x4f -#define PE_LANG_SINDHI 0x59 -#define PE_LANG_SLOVAK 0x1b -#define PE_LANG_SLOVENIAN 0x24 -#define PE_LANG_SPANISH 0x0a -#define PE_LANG_SWAHILI 0x41 -#define PE_LANG_SWEDISH 0x1d -#define PE_LANG_SYRIAC 0x5a -#define PE_LANG_TAMIL 0x49 -#define PE_LANG_TATAR 0x44 -#define PE_LANG_TELUGU 0x4a -#define PE_LANG_THAI 0x1e -#define PE_LANG_TURKISH 0x1f -#define PE_LANG_UKRAINIAN 0x22 -#define PE_LANG_URDU 0x20 -#define PE_LANG_UZBEK 0x43 -#define PE_LANG_VIETNAMESE 0x2a - -//---------------------------------------------------------------------- - -#define PE_NODE "$ PE header" // netnode name for PE header - // value() -> peheader_t - // altval(segnum) -> s->start_ea -#define PE_ALT_DBG_FPOS nodeidx_t(-1) // altval() -> translated fpos of debuginfo -#define PE_ALT_IMAGEBASE nodeidx_t(-2) // altval() -> loading address (usually pe.imagebase) -#define PE_ALT_PEHDR_OFF nodeidx_t(-3) // altval() -> offset of PE header -#define PE_ALT_NEFLAGS nodeidx_t(-4) // altval() -> neflags -#define PE_ALT_TDS_LOADED nodeidx_t(-5) // altval() -> tds already loaded(1) or invalid(-1) -#define PE_ALT_PSXDLL nodeidx_t(-6) // altval() -> if POSIX(x86) imports from PSXDLL netnode -#define PE_ALT_OVRVA nodeidx_t(-7) // altval() -> overlay rva (if present) -#define PE_ALT_OVRSZ nodeidx_t(-8) // altval() -> overlay size (if present) -#define PE_SUPSTR_PDBNM nodeidx_t(-9) // supstr() -> pdb file name - // supval(segnum) -> pesection_t - // blob(0, PE_NODE_RELOC) -> relocation info - // blob(0, RSDS_TAG) -> rsds_t structure - // blob(0, NB10_TAG) -> cv_info_pdb20_t structure -#define PE_ALT_NTAPI nodeidx_t(-10) // altval() -> uses Native API -#define PE_NODE_RELOC 'r' -#define RSDS_TAG 's' -#define NB10_TAG 'n' -#define UTDS_TAG 't' - -struct load_config_t -{ - uint32 Size; - uint32 TimeDateStamp; - uint16 MajorVersion; - uint16 MinorVersion; - uint32 GlobalFlagsClear; - uint32 GlobalFlagsSet; - uint32 CriticalSectionDefaultTimeout; - uint32 DeCommitFreeBlockThreshold; - uint32 DeCommitTotalFreeThreshold; - uint32 LockPrefixTable; // VA - uint32 MaximumAllocationSize; - uint32 VirtualMemoryThreshold; - uint32 ProcessHeapFlags; - uint32 ProcessAffinityMask; - uint16 CSDVersion; - uint16 Reserved1; - uint32 EditList; // VA - uint32 SecurityCookie; // VA - // Version 2 - uint32 SEHandlerTable; // VA - uint32 SEHandlerCount; - // Version 3 - uint32 GuardCFCheckFunctionPointer; // VA - uint32 GuardCFDispatchFunctionPointer; //VA - uint32 GuardCFFunctionTable; // VA - uint32 GuardCFFunctionCount; - uint32 GuardFlags; -}; - -struct load_config64_t -{ - uint32 Size; - uint32 TimeDateStamp; - uint16 MajorVersion; - uint16 MinorVersion; - uint32 GlobalFlagsClear; - uint32 GlobalFlagsSet; - uint32 CriticalSectionDefaultTimeout; - uint64 DeCommitFreeBlockThreshold; - uint64 DeCommitTotalFreeThreshold; - uint64 LockPrefixTable; // VA - uint64 MaximumAllocationSize; - uint64 VirtualMemoryThreshold; - uint64 ProcessAffinityMask; - uint32 ProcessHeapFlags; - uint16 CSDVersion; - uint16 Reserved1; - uint64 EditList; // VA - uint64 SecurityCookie; // VA - // Version 2 - uint64 SEHandlerTable; // VA - uint64 SEHandlerCount; - // Version 3 - uint64 GuardCFCheckFunctionPointer; // VA - uint64 GuardCFDispatchFunctionPointer; //VA - uint64 GuardCFFunctionTable; // VA - uint64 GuardCFFunctionCount; - uint32 GuardFlags; -}; - -#ifndef IMAGE_GUARD_CF_INSTRUMENTED -#define IMAGE_GUARD_CF_INSTRUMENTED 0x000000100 // Module performs control flow integrity checks using system-supplied support -#define IMAGE_GUARD_CFW_INSTRUMENTED 0x000000200 // Module performs control flow and write integrity checks -#define IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT 0x000000400 // Module contains valid control flow target metadata -#define IMAGE_GUARD_SECURITY_COOKIE_UNUSED 0x000000800 // Module does not make use of the /GS security cookie -#define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT 0x00001000 // Module supports read only delay load IAT -#define IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION 0x00002000 // Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected -#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK 0xF0000000 // Stride of Guard CF function table encoded in these bits (additional count of bytes per element) -#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT 28 // Shift to right-justify Guard CF function table stride -#endif - -//---------------------------------------------------------------------- -// MS Windows CLSID, GUID -struct clsid_t -{ - uint32 id1; - uint16 id2; - uint16 id3; - uchar id4[8]; - bool operator == (const struct clsid_t &r) const - { return memcmp(this, &r, sizeof(r)) == 0; } -}; - -//---------------------------------------------------------------------- -// RSDS debug information -struct rsds_t -{ - uint32 magic; -#define RSDS_MAGIC MC4('R','S','D','S') -#define UTDS_MAGIC MC4('u','T','D','S') - clsid_t guid; - uint32 age; -// char name[]; // followed by a zero-terminated UTF8 file name -}; - -//---------------------------------------------------------------------- -// NB10 debug information -struct cv_info_pdb20_t -{ - uint32 magic; // 'NB10' -#define NB10_MAGIC MC4('N', 'B', '1', '0') - uint32 offset; - uint32 signature; - uint32 age; - //char pdb_file_name[]; -}; - -//---------------------------------------------------------------------- -// MTOC debug information. -// denotes EFI binaries that were built on OSX as Mach-O, then converted to PE by the 'mtoc' utility. -// see https://opensource.apple.com/source/cctools/cctools-921/efitools/mtoc.c.auto.html -struct mtoc_info_t -{ - uint32 magic; // 'MTOC' -#define MTOC_MAGIC MC4('M', 'T', 'O', 'C') - uchar uuid[16]; // UUID of original Mach-O file - // char debug_filename[]; -}; - -// TE (Terse Executable) -struct teheader_t -{ - uint16 signature; // 00 - uint16 machine; // 02 same as in PE - - bool is_64bit_cpu(void) const { return machine == PECPU_AMD64 || machine == PECPU_IA64 || machine == PECPU_ARM64; } - - uint8 nobjs; // 04 number of sections - uint8 subsys; // 05 target subsystem - uint16 strippedsize; // 06 number of bytes removed from the base of the original image - - int32 first_section_pos(int32 peoff) const - { return peoff + sizeof(teheader_t); } - - // value which should be added to the sections' file offsets and RVAs - int32 te_adjust() const - { return sizeof(teheader_t) - strippedsize; } - - uint32 entry; // 08 Entry point - uint32 text_start; // 0C Base of code - uint64 imagebase64; // 10 Virtual base of the image. - uint64 imagebase() const - { - return imagebase64; - } - petab_t reltab; // 18 Relocation Table - petab_t debdir; // 20 Debug Directory -}; - -const char *get_pe_machine_name(uint16 machine); -void print_pe_flags(uint16 flags); - -#pragma pack(pop) -#endif diff --git a/idasdk75/ldr/pef/makefile b/idasdk75/ldr/pef/makefile deleted file mode 100644 index d7a3881..0000000 --- a/idasdk75/ldr/pef/makefile +++ /dev/null @@ -1,16 +0,0 @@ -PROC=pef - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)pef$(O) : $(I)../ldr/coff/dbxstcla.h $(I)../ldr/coff/storclas.h \ - $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)typeinf.hpp \ - $(I)ua.hpp $(I)xref.hpp \ - ../../module/ppc/notify_codes.hpp ../coff/syms.h \ - ../idaldr.h common.cpp pef.cpp pef.hpp diff --git a/idasdk75/ldr/pef/pef.cpp b/idasdk75/ldr/pef/pef.cpp deleted file mode 100644 index b8024b0..0000000 --- a/idasdk75/ldr/pef/pef.cpp +++ /dev/null @@ -1,766 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * FIDO: 2:5020/209 - * - * PEF Loader - * ---------- - * - */ - -#include "../idaldr.h" -#include <typeinf.hpp> -#include "pef.hpp" -#include "../coff/syms.h" -#include "../../module/ppc/notify_codes.hpp" -#include "common.cpp" - -static ea_t toc_ea; -static netnode toc; -//---------------------------------------------------------------------- -static const char *get_sec_share_name(uint8 share, char *buf, size_t bufsize) -{ - switch ( share ) - { - case PEF_SH_PROCESS: return "Shared within process"; - case PEF_SH_GLOBAL : return "Shared between all processes"; - case PEF_SH_PROTECT: return "Shared between all processes but protected"; - default: - qsnprintf(buf, bufsize, "Unknown code %d", share); - return buf; - } -} - -//---------------------------------------------------------------------- -static void process_vector(uint32 ea, const char *name) -{ - op_plain_offset(ea, 0, 0); - op_plain_offset(ea+4, 0, 0); - uint32 mintoc = get_dword(ea+4); - if ( segtype(mintoc) == SEG_DATA && mintoc < toc_ea ) - { - toc_ea = mintoc; - ppc_module_t::set_toc(toc_ea); - } - set_name(ea, name, SN_IDBENC); - char buf[MAXSTR]; - qsnprintf(buf, sizeof(buf), ".%s", name); - uint32 code = get_dword(ea); - add_entry(code, code, buf, true, AEF_IDBENC); - make_name_auto(code); -} - -//---------------------------------------------------------------------- -static void process_symbol_class(uint32 ea, uchar sclass, const char *name) -{ - switch ( sclass ) - { - case kPEFCodeSymbol: - case kPEFGlueSymbol: - add_entry(ea, ea, name, true, AEF_IDBENC); - break; - case kPEFTVectSymbol: - process_vector(ea, name); - break; - case kPEFTOCSymbol: - if ( segtype(ea) == SEG_DATA && ea < toc_ea ) - { - toc_ea = ea; - ppc_module_t::set_toc(toc_ea); - } - toc.charset_ea(ea, XMC_TD+1, 1); - /* fall thru */ - case kPEFDataSymbol: - set_name(ea, name, SN_IDBENC); - break; - } -} - -//---------------------------------------------------------------------- -static void fixup(uint32 ea, uint32 delta, int extdef) -{ - fixup_data_t fd(FIXUP_OFF32); - if ( extdef ) - fd.set_extdef(); - segment_t *s = getseg(delta); - fd.displacement = get_dword(ea); - if ( s == NULL ) - { - fd.off = delta; - } - else - { - fd.sel = s->sel; - fd.off = delta - get_segm_base(s); - } - fd.set(ea); - uint32 target = get_dword(ea) + delta; - put_dword(ea, target); - op_plain_offset(ea, 0, 0); - //cmd.ea = ea; ua_add_dref(0, target, dr_O); cmd.ea = BADADDR; - if ( target != toc_ea - && !has_name(get_flags(ea)) - && has_name(get_flags(target)) ) - { - qstring buf; - if ( get_name(&buf, target) > 0 ) - { - buf.insert("TC_"); - force_name(ea, buf.begin()); - make_name_auto(ea); - } - } -// toc.charset_ea(ea, XMC_TC+1, 1); -} - -//---------------------------------------------------------------------- -static NORETURN void bad_loader_data(void) -{ - loader_failure("Bad loader data"); -} - -//---------------------------------------------------------------------- -static NORETURN void bad_reloc_data(void) -{ - loader_failure("Bad relocation info"); -} - -//---------------------------------------------------------------------- -inline bool good_string(const char *begin, const uchar *end, const char *p) -{ - if ( p >= begin ) - { - while ( p < (const char *)end ) - { - if ( *p == '\0' ) - return true; - ++p; - } - } - return false; -} - -//---------------------------------------------------------------------- -static void process_loader_data(bytevec_t &ldrdata, const qvector<pef_section_t> &sec) -{ - pef_loader_data_t pd; - elderr_t errcode = extract_loader_data(&pd, ldrdata, sec); - if ( errcode != ELDERR_OK ) - bad_loader_data(); - - pef_loader_t &pl = pd.pl; - if ( pl.totalImportedSymbolCount != 0 ) - { - uint32 size = pl.totalImportedSymbolCount*4; - ea_t undef = free_chunk(inf_get_max_ea(), size, -0xF); - ea_t end = undef + size; - set_selector(sec.size()+1, 0); - if ( !add_segm(sec.size()+1, undef, end, "IMPORT", "XTRN") ) - loader_failure(); - - for ( int i=0; i < pl.importLibraryCount; i++ ) - { - const pef_library_t &pil = pd.pil[i]; - ea_t ea = undef + 4 * pil.firstImportedSymbol; - const char *libname = pd.stable + pil.nameOffset; - if ( !good_string(pd.stable, ldrdata.end(), libname) ) - bad_loader_data(); - add_extra_cmt(ea, true, "Imports from library %s", libname); - if ( (pil.options & PEF_LIB_WEAK) != 0 ) - add_extra_cmt(ea, true, "Library is weak"); - } - - inf_set_specsegs(inf_is_64bit() ? 8 : 4); - for ( int i=0; i < pl.totalImportedSymbolCount; i++ ) - { - uint32 sym = mflong(pd.impsym[i]); - uchar sclass = uchar(sym >> 24); - ea_t ea = undef + 4*i; - const char *iname = get_impsym_name(pd.stable, ldrdata.end(), pd.impsym, i); - if ( iname == NULL ) - bad_loader_data(); - set_name(ea, iname, SN_IDBENC); - if ( (sclass & kPEFWeak) != 0 ) - make_name_weak(ea); - create_dword(ea, 4); - put_dword(ea, 0); - pd.impsym[i] = (uint32)ea; - } - } - - if ( pl.mainSection != -1 ) - { - uint32 ea = sec[pl.mainSection].defaultAddress + pl.mainOffset; - toc_ea = sec[1].defaultAddress + get_dword(ea+4); - ppc_module_t::set_toc(toc_ea); - } - else if ( pl.initSection != -1 ) - { - uint32 ea = sec[pl.initSection].defaultAddress + pl.initOffset; - toc_ea = sec[1].defaultAddress + get_dword(ea+4); - ppc_module_t::set_toc(toc_ea); - } - - if ( qgetenv("IDA_NORELOC") ) - goto EXPORTS; - - msg("Processing relocation information... "); - for ( int i=0; i < pl.relocSectionCount; i++ ) - { - const pef_reloc_header_t &prh = pd.prh[i]; - int sidx = prh.sectionIndex; - if ( sidx >= sec.size() ) - bad_reloc_data(); - uint32 sea = sec[sidx].defaultAddress; - const uint16 *ptr = pd.relptr + prh.firstRelocOffset; - if ( !inside(ldrdata, ptr, prh.relocCount, sizeof(*ptr)) ) - bad_reloc_data(); - uint32 reladdr = sea; - uint32 import = 0; - uint32 code = sec.size() > 0 ? sec[0].defaultAddress : 0; - uint32 data = sec.size() > 1 ? sec[1].defaultAddress : 0; - int32 repeat = -1; - for ( int j=0; j < prh.relocCount; ) - { - uint16 insn = mfshort(ptr[j++]); - uint16 cnt = insn & 0x1FF; - switch ( insn >> 9 ) - { - default: // kPEFRelocBySectDWithSkip= 0x00,/* binary: 00xxxxx */ - if ( (insn & 0xC000) == 0 ) - { - int skipCount = (insn >> 6) & 0xFF; - int relocCount = insn & 0x3F; - reladdr += skipCount * 4; - while ( relocCount > 0 ) - { - relocCount--; - fixup(reladdr, data, 0); - reladdr += 4; - } - break; - } - bad_reloc_data(); - - case kPEFRelocBySectC: // = 0x20, /* binary: 0100000 */ - cnt++; - while ( cnt > 0 ) - { - cnt--; - fixup(reladdr, code, 0); - reladdr += 4; - } - break; - case kPEFRelocBySectD: - cnt++; - while ( cnt > 0 ) - { - cnt--; - fixup(reladdr, data, 0); - reladdr += 4; - } - break; - case kPEFRelocTVector12: - cnt++; - while ( cnt > 0 ) - { - cnt--; - fixup(reladdr, code, 0); - reladdr += 4; - fixup(reladdr, data, 0); - reladdr += 4; - reladdr += 4; - } - break; - case kPEFRelocTVector8: - cnt++; - while ( cnt > 0 ) - { - cnt--; - fixup(reladdr, code, 0); - reladdr += 4; - fixup(reladdr, data, 0); - reladdr += 4; - } - break; - case kPEFRelocVTable8: - cnt++; - while ( cnt > 0 ) - { - cnt--; - fixup(reladdr, data, 0); - reladdr += 4; - reladdr += 4; - } - break; - case kPEFRelocImportRun: - cnt++; - if ( import+cnt > pl.totalImportedSymbolCount ) - bad_reloc_data(); - while ( cnt > 0 ) - { - cnt--; - fixup(reladdr, pd.impsym[import], 1); - import++; - reladdr += 4; - } - break; - case kPEFRelocSmByImport: - if ( cnt >= pl.totalImportedSymbolCount ) - bad_reloc_data(); - fixup(reladdr, pd.impsym[cnt], 1); - reladdr += 4; - import = cnt + 1; - break; - case kPEFRelocSmSetSectC: - if ( cnt >= sec.size() ) - bad_reloc_data(); - code = sec[cnt].defaultAddress; - break; - case kPEFRelocSmSetSectD: - if ( cnt >= sec.size() ) - bad_reloc_data(); - data = sec[cnt].defaultAddress; - break; - case kPEFRelocSmBySection: - if ( cnt >= sec.size() ) - bad_reloc_data(); - fixup(reladdr, sec[cnt].defaultAddress, 0); - reladdr += 4; - break; - - case kPEFRelocIncrPosition: /* binary: 1000xxx */ - case kPEFRelocIncrPosition+1: - case kPEFRelocIncrPosition+2: - case kPEFRelocIncrPosition+3: - case kPEFRelocIncrPosition+4: - case kPEFRelocIncrPosition+5: - case kPEFRelocIncrPosition+6: - case kPEFRelocIncrPosition+7: - reladdr += (insn & 0x0FFF)+1; - break; - - case kPEFRelocSmRepeat: /* binary: 1001xxx */ - case kPEFRelocSmRepeat+1: - case kPEFRelocSmRepeat+2: - case kPEFRelocSmRepeat+3: - case kPEFRelocSmRepeat+4: - case kPEFRelocSmRepeat+5: - case kPEFRelocSmRepeat+6: - case kPEFRelocSmRepeat+7: - if ( repeat == -1 ) - repeat = (insn & 0xFF)+1; - repeat--; - if ( repeat != -1 ) - j -= ((insn>>8) & 15)+1 + 1; - break; - - case kPEFRelocSetPosition: /* binary: 101000x */ - case kPEFRelocSetPosition+1: - { - ushort next = mfshort(ptr[j++]); - uint32 offset = next | (uint32(insn & 0x3FF) << 16); - reladdr = sea + offset; - } - break; - - case kPEFRelocLgByImport: /* binary: 101001x */ - case kPEFRelocLgByImport+1: - { - ushort next = mfshort(ptr[j++]); - uint32 index = next | (uint32(insn & 0x3FF) << 16); - if ( index >= pl.totalImportedSymbolCount ) - bad_reloc_data(); - fixup(reladdr, pd.impsym[index], 1); - reladdr += 4; - import = index + 1; - } - break; - - case kPEFRelocLgRepeat: /* binary: 101100x */ - case kPEFRelocLgRepeat+1: - { - ushort next = mfshort(ptr[j++]); - if ( repeat == -1 ) - repeat = next | (uint32(insn & 0x3F) << 16); - repeat--; - if ( repeat != -1 ) - j -= ((insn >> 6) & 15) + 1 + 2; - } - break; - - case kPEFRelocLgSetOrBySection: /* binary: 101101x */ - case kPEFRelocLgSetOrBySection+1: - { - ushort next = mfshort(ptr[j++]); - uint32 index = next | (uint32(insn & 0x3F) << 16); - if ( index >= sec.size() ) - bad_reloc_data(); - int subcode = (insn >> 6) & 15; - switch ( subcode ) - { - case 0: - fixup(reladdr, sec[index].defaultAddress, 0); - reladdr += 4; - break; - case 1: - code = sec[index].defaultAddress; - break; - case 2: - data = sec[index].defaultAddress; - break; - } - } - break; - } - } - } - -EXPORTS: - for ( int i=0; i < pl.exportedSymbolCount; i++ ) - { - const pef_export_t &pe = pd.pe[i]; - uchar sclass = uchar(pe.classAndName >> 24); - char name[MAXSTR]; - uint32 ea; - switch ( pe.sectionIndex ) - { - case -3: - { - uint symidx = pe.symbolValue; - if ( symidx >= pl.totalImportedSymbolCount ) - bad_reloc_data(); - ea = pd.impsym[symidx]; - } - break; - case -2: // absolute symbol - ask_for_feedback("Absolute symbols are not implemented"); - continue; - default: - { - uint secidx = pe.sectionIndex; - if ( secidx >= sec.size() ) - bad_reloc_data(); - ea = sec[secidx].defaultAddress + pe.symbolValue; - } - break; - } - if ( !get_expsym_name(pd.stable, pd.keytable, pd.pe, i, ldrdata.end(), name, sizeof(name)) ) - bad_loader_data(); - process_symbol_class(ea, sclass & 0xF, name); - } - msg("done.\n"); - - if ( pl.mainSection >= 0 && pl.mainSection < sec.size() ) - { - uint32 ea = sec[pl.mainSection].defaultAddress + pl.mainOffset; - process_vector(ea, "start"); - inf_set_start_cs(0); - inf_set_start_ip(get_dword(ea)); - } - if ( pl.initSection >= 0 && pl.initSection < sec.size() ) - { - uint32 ea = sec[pl.initSection].defaultAddress + pl.initOffset; - process_vector(ea, "INIT_VECTOR"); - } - if ( pl.termSection >= 0 && pl.termSection < sec.size() ) - { - uint32 ea = sec[pl.termSection].defaultAddress + pl.termOffset; - process_vector(ea, "TERM_VECTOR"); - } - - if ( toc_ea != BADADDR ) - set_name(toc_ea, "TOC"); -} - -//-------------------------------------------------------------------------- -static NORETURN void bad_packed_data(void) -{ - loader_failure("Illegal compressed data"); -} - -//-------------------------------------------------------------------------- -static uint32 read_number(const uchar *&packed, const uchar *end) -{ - uint32 arg = 0; - for ( int i=0; ; i++ ) - { - if ( packed >= end ) - bad_packed_data(); - uchar b = *packed++; - arg <<= 7; - arg |= (b & 0x7F); - if ( (b & 0x80) == 0 ) - break; - if ( i > 4 ) - bad_packed_data(); - } - return arg; -} - -//-------------------------------------------------------------------------- -static void unpack_section( - const bytevec_t &packedvec, - ea_t start, - uint32 usize) -{ - bytevec_t unpacked; - const uchar *packed = packedvec.begin(); - const uchar *pckend = packedvec.begin() + packedvec.size(); - while ( packed < pckend ) - { - uchar code = *packed++; - uint32 arg = code & 0x1F; - if ( arg == 0 ) - arg = read_number(packed, pckend); - switch ( code >> 5 ) - { - case 0: // Zero - unpacked.growfill(arg); - break; - - case 1: // blockCopy - { - const uchar *end = packed + arg; - if ( end < packed || end > pckend ) - bad_packed_data(); - unpacked.append(packed, arg); - packed += arg; - } - break; - - case 2: // repeatedBlock - { - int32 repeat = read_number(packed, pckend) + 1; - const uchar *end = packed + arg; - if ( end < packed || end > pckend ) - bad_packed_data(); - while ( --repeat >= 0 ) - unpacked.append(packed, arg); - packed += arg; - } - break; - - case 3: // interleaveRepeatBlockWithBlockCopy - { - int32 commonSize = arg; - int32 customSize = read_number(packed, pckend); - int32 repeatCount = read_number(packed, pckend); - const uchar *common = packed; - packed += commonSize; - if ( packed < common || packed > pckend ) - bad_packed_data(); - while ( --repeatCount >= 0 ) - { - const uchar *end = packed + customSize; - if ( end < packed || end > pckend ) - bad_packed_data(); - unpacked.append(common, commonSize); - unpacked.append(packed, customSize); - packed += customSize; - } - unpacked.append(common, commonSize); - } - break; - - case 4: // interleaveRepeatBlockWithZero - { - int32 commonSize = arg; - int32 customSize = read_number(packed, pckend); - int32 repeatCount = read_number(packed, pckend); - while ( --repeatCount >= 0 ) - { - const uchar *end = packed + customSize; - if ( end < packed || end > pckend ) - bad_packed_data(); - unpacked.growfill(commonSize); - unpacked.append(packed, customSize); - packed += customSize; - } - unpacked.growfill(commonSize); - } - break; - - default: - bad_packed_data(); - } - } - if ( unpacked.size() < usize ) - unpacked.growfill(usize-unpacked.size()); - if ( unpacked.size() != usize ) - bad_packed_data(); - mem2base(unpacked.begin(), start, start+unpacked.size(), FILEREG_NOTPATCHABLE); -} - -//-------------------------------------------------------------------------- -static void load_section( - int i, - linput_t *li, - pef_section_t &ps, - const char *sname, - const char *classname, - int is_packed) -{ - uint32 size = ps.totalSize; - ea_t base = ps.defaultAddress ? ps.defaultAddress : to_ea(inf_get_baseaddr(), 0); - ea_t start = free_chunk(base, size, 1-(1 << ps.alignment)); - ea_t end = start + size; - if ( is_packed ) - { - bytevec_t packed; - packed.resize(ps.packedSize); - qlseek(li, ps.containerOffset); - lread(li, packed.begin(), packed.size()); - unpack_section(packed, start, ps.unpackedSize); - } - else - { - file2base(li, ps.containerOffset, - start, start+ps.unpackedSize, FILEREG_PATCHABLE); - } - set_selector(i+1, 0); - if ( !add_segm(i+1, start, end, sname, classname) ) - loader_failure(); - ps.defaultAddress = start; - if ( start < inf_get_lowoff() ) - inf_set_lowoff(start); -} - -//-------------------------------------------------------------------------- -// -// load file into the database. -// -void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) -{ - pef_t pef; - toc_ea = BADADDR; - toc.create("$ toc"); - qlseek(li, 0); - lread(li, &pef, sizeof(pef_t)); - swap_pef(pef); - - const char *proc = get_pef_processor(pef); - if ( proc != NULL ) - { - set_processor_type(proc, SETPROC_LOADER); - if ( PH.id == PLFM_PPC ) - { - // Mac OS Runtime Architecture for the PowerPC is very similar to AIX - set_abi_name("aix"); - } - } - - // read section headers - qvector<pef_section_t> sec; - if ( pef.sectionCount != 0 ) - { - sec.resize(pef.sectionCount); - lread(li, sec.begin(), sec.size()*sizeof(pef_section_t)); - } - - // swap section headers and find the loader section - pef_section_t *loader = NULL; - for ( int i=0; i < sec.size(); i++ ) - { - swap_pef_section(sec[i]); - if ( sec[i].sectionKind == PEF_SEC_LOADER ) - loader = &sec[i]; - } - - int32 snames_table = sizeof(pef_t) + sizeof(pef_section_t)*sec.size(); - for ( int i=0; i < sec.size(); i++ ) - { - char buf[MAXSTR]; - char *secname = get_string(li, snames_table, sec[i].nameOffset, buf, sizeof(buf)); - switch ( sec[i].sectionKind ) - { - case PEF_SEC_PDATA : // Pattern initialized data segment - load_section(i, li, sec[i], secname, CLASS_DATA, 1); - break; - case PEF_SEC_CODE : // Code segment - case PEF_SEC_EDATA : // Executable data segment - load_section(i, li, sec[i], secname, CLASS_CODE, 0); - break; - case PEF_SEC_DATA: // Unpacked data segment - load_section(i, li, sec[i], secname, - sec[i].unpackedSize != 0 ? CLASS_DATA : CLASS_BSS, 0); - break; - case PEF_SEC_CONST: // Read only data - load_section(i, li, sec[i], secname, CLASS_CONST, 0); - break; - case PEF_SEC_LOADER: // Loader section - case PEF_SEC_DEBUG : // Reserved for future use - case PEF_SEC_EXCEPT: // Reserved for future use - case PEF_SEC_TRACEB: // Reserved for future use - continue; - default: - ask_for_feedback("Unknown section type"); - continue; - } - if ( i == 0 ) - create_filename_cmt(); - add_extra_cmt(sec[i].defaultAddress, true, "Segment share type: %s\n", - get_sec_share_name(sec[i].shareKind, buf, sizeof(buf))); - } - if ( loader != NULL ) - { - bytevec_t ldrdata; - ldrdata.resize(loader->packedSize); - qlseek(li, loader->containerOffset); - lread(li, ldrdata.begin(), ldrdata.size()); - process_loader_data(ldrdata, sec); - } -} - - -//-------------------------------------------------------------------------- -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - const char *proc = get_pef_processor(li); - if ( proc == NULL ) - return 0; - - *fileformatname = "PEF (Mac OS or Be OS executable)"; - *processor = proc; - return 1; -} - -//---------------------------------------------------------------------- -// -// LOADER DESCRIPTION BLOCK -// -//---------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/ldr/pilot/common.cpp b/idasdk75/ldr/pilot/common.cpp deleted file mode 100644 index fec5745..0000000 --- a/idasdk75/ldr/pilot/common.cpp +++ /dev/null @@ -1,144 +0,0 @@ - -//------------------------------------------------------------------------- -static void swap_prc(DatabaseHdrType &h) -{ - h.attributes = swap16(h.attributes); - h.version = swap16(h.version); - h.creationDate = swap32(h.creationDate); - h.modificationDate = swap32(h.modificationDate); - h.lastBackupDate = swap32(h.lastBackupDate); - h.modificationNumber = swap32(h.modificationNumber); - h.appInfoID = swap32(h.appInfoID); - h.sortInfoID = swap32(h.sortInfoID); -// h.type = swap32(h.type); -// h.id = swap32(h.id); - h.uniqueIDSeed = swap32(h.uniqueIDSeed); - h.nextRecordListID = swap32(h.nextRecordListID); - h.numRecords = swap16(h.numRecords); -} - -//------------------------------------------------------------------------- -static void swap_resource_map_entry(ResourceMapEntry &re) -{ - re.id = swap16(re.id); - re.ulOffset = swap32(re.ulOffset); -} - -//------------------------------------------------------------------------- -void swap_bitmap(pilot_bitmap_t *b) -{ - b->cx = swap16(b->cx); - b->cy = swap16(b->cy); - b->cbRow = swap16(b->cbRow); - b->ausUnk[0] = swap16(b->ausUnk[0]); - b->ausUnk[1] = swap16(b->ausUnk[1]); - b->ausUnk[2] = swap16(b->ausUnk[2]); - b->ausUnk[3] = swap16(b->ausUnk[3]); -} - -//------------------------------------------------------------------------- -void swap_code0000(code0000_t *cp) -{ - cp->nBytesAboveA5 = swap32(cp->nBytesAboveA5); - cp->nBytesBelowA5 = swap32(cp->nBytesBelowA5); -} - -//------------------------------------------------------------------------- -void swap_pref0000(pref0000_t *pp) -{ - pp->flags = swap16(pp->flags); - pp->stack_size = swap32(pp->stack_size); - pp->heap_size = swap32(pp->heap_size); -} - -//------------------------------------------------------------------------- -// Since the Palm Pilot programs are really poorly recognized by usual -// methods, we are forced to read the resource tablee to determine -// if everying is ok -//return 0 if not a PRC, 2 if has ARM code segments, 1 otherwise -int is_prc_file(linput_t *li) -{ - DatabaseHdrType h; - if ( qlread(li,&h,sizeof(h)) != sizeof(h) ) - return 0; - swap_prc(h); - if ( (h.attributes & dmHdrAttrResDB) == 0 ) - return 0; - if ( short(h.numRecords) <= 0 ) - return 0; - const uint64 filesize = qlsize(li); - const uint64 lowestpos = uint64(h.numRecords)*sizeof(ResourceMapEntry) + sizeof(h); - if ( lowestpos > filesize ) - return 0; - - // the dates can be plain wrong, so don't check them: - //uint32 now = time(NULL); - //&& uint32(h.lastBackupDate) <= now // use unsigned comparition! - //&& uint32(h.creationDate) <= now // use unsigned comparition! - //&& uint32(h.modificationDate) <= now // use unsigned comparition! - - qvector<ResourceMapEntry> re; - re.resize(h.numRecords); - size_t size = sizeof(ResourceMapEntry) * h.numRecords; - if ( qlread(li, re.begin(), size) != size ) - return 0; - - bool hasArmCode = false; - for ( int i=0; i < h.numRecords; i++ ) - { - swap_resource_map_entry(re[i]); - if ( re[i].ulOffset >= filesize || re[i].ulOffset < lowestpos ) - return 0; - if ( re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL ) - hasArmCode = true; - } - return hasArmCode ? 2 : 1; -} - -bool isKnownResource(uint32 resId) -{ - switch ( resId ) - { - case MC4('t', 'F', 'R', 'M'): - case MC4('t', 'B', 'T', 'N'): - case MC4('t', 'C', 'B', 'X'): - case MC4('t', 'F', 'B', 'M'): - case MC4('t', 'F', 'L', 'D'): - case MC4('t', 'g', 'b', 'n'): - case MC4('t', 'G', 'D', 'T'): - case MC4('t', 'g', 'p', 'b'): - case MC4('t', 'g', 'r', 'b'): - case MC4('t', 'G', 'S', 'I'): - case MC4('t', 'L', 'B', 'L'): - case MC4('t', 'L', 'S', 'T'): - case MC4('t', 'P', 'B', 'N'): - case MC4('t', 'P', 'U', 'L'): - case MC4('t', 'P', 'U', 'T'): - case MC4('t', 'R', 'E', 'P'): - case MC4('t', 'S', 'C', 'L'): - case MC4('t', 's', 'l', 'd'): - case MC4('t', 's', 'l', 'f'): - case MC4('t', 'S', 'L', 'T'): - case MC4('t', 'T', 'B', 'L'): - case MC4('T', 'a', 'l', 't'): - case MC4('M', 'B', 'A', 'R'): - case MC4('M', 'E', 'N', 'U'): - case MC4('t', 'S', 'T', 'R'): - case MC4('t', 'S', 'T', 'L'): - case MC4('T', 'b', 'm', 'p'): - case MC4('t', 'b', 'm', 'f'): - case MC4('P', 'I', 'C', 'T'): - case MC4('t', 'v', 'e', 'r'): - case MC4('t', 'A', 'I', 'N'): - case MC4('t', 'a', 'i', 'c'): - case MC4('t', 'A', 'I', 'S'): - case MC4('t', 'A', 'I', 'B'): - case MC4('t', 'a', 'i', 'f'): - case MC4('I', 'C', 'O', 'N'): - case MC4('c', 'i', 'c', 'n'): - case MC4('p', 'r', 'e', 'f'): - case MC4('x', 'p', 'r', 'f'): - return true; - } - return false; -} diff --git a/idasdk75/ldr/pilot/makefile b/idasdk75/ldr/pilot/makefile deleted file mode 100644 index d43bd15..0000000 --- a/idasdk75/ldr/pilot/makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROC=pilot -IDCS=pilot.idc - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)pilot$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)expr.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h common.cpp pilot.cpp pilot.hpp diff --git a/idasdk75/ldr/pilot/pilot.cpp b/idasdk75/ldr/pilot/pilot.cpp deleted file mode 100644 index 9a7603d..0000000 --- a/idasdk75/ldr/pilot/pilot.cpp +++ /dev/null @@ -1,912 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - */ - -#include "../idaldr.h" -#include <expr.hpp> -#include "pilot.hpp" - -#include "common.cpp" -//------------------------------------------------------------------------ -static void describe_all(DatabaseHdrType &h) -{ - create_filename_cmt(); - add_pgm_cmt("Version : %04X",h.version); - add_pgm_cmt("DatabaseType: %4.4s",(char*)&h.type); - add_pgm_cmt("\n appl \"%s\", '%4.4s'", h.name, (char*)&h.id); -} - -//------------------------------------------------------------------------ -// -// Structure of the DATA 0 resource: -// -// +--------------------------------------------+ -// | long: offset of CODE 1 xrefs? |- -+ -// +--------------------------------------------+ | -// | char[]: Initialized near data (below A5) | | -// +--------------------------------------------+ | -// | char[]: Uninitialized near data (below A5) | | -// +--------------------------------------------+ | -// | char[]: Initialized far data (above A5) | | -// +--------------------------------------------+ | -// | char[]: DATA 0 xrefs | | -// +--------------------------------------------+ | -// | char[]: CODE 1 xrefs |<--+ -// +--------------------------------------------+ -// - -static uchar *apply_relocs(uchar *packed, size_t &packlen, ea_t relocbase, ea_t targetbase, bool code=false) -{ - if ( packlen < 4 ) - { -BADDATA: - warning("Bad packed data"); - return NULL; - } - uint32 nrelocs = swap32(*(uint32*)packed); - packed += 4; - packlen -= 4; - ea_t offset = relocbase; - fixup_data_t fd(FIXUP_OFF32); - if ( code ) - fd.set_sel(getseg(targetbase)); - //msg("%d relocations\n", nrelocs); - for ( uint i=0; i < nrelocs; i++ ) - { - if ( packlen < 1 ) - goto BADDATA; - uchar c = *packed; - if ( c&0x80 ) - { - //signed 8-bit delta - offset+=(char)(c<<1); - packed++; - packlen--; - } - else if ( c&0x40 ) - { - if ( packlen < 2 ) - goto BADDATA; - //15-bit unsigned(?) delta - //comment in PalmOS_Startup.cpp says "unsigned" but they cast it to a signed short... - uint32 o1 = swap16(*(ushort*)packed); - packed += 2; - packlen -= 2; - offset += (short)(o1<<2)>>1; - } - else - { - if ( packlen < 4 ) - goto BADDATA; - //direct signed 31-bit offset - offset = relocbase+(int32(swap32(*(int32*)packed)<<2)>>1); - packed += 4; - packlen -= 4; - } - for ( int j=0; j < 4; j++ ) - if ( !is_loaded(offset+j) ) - put_byte(offset+j, 0); - fd.off = get_dword(offset); - if ( code ) - { - fd.set(offset); - auto_make_proc(targetbase+fd.off); - if ( get_word(offset-2) == 0x4EF9 ) //jump opcode? - auto_make_proc(offset-2); - } - else - { - fd.set_base(targetbase); - fd.set(offset); - } -// msg("Relocation %d at %08X: %08X -> %08X\n", i, offset-relocbase, fd.off, targetbase+fd.off); - } - return packed; -} - -//------------------------------------------------------------------------ -//unpack rle data from the buffer packed at file position fpos to ea cea -//return new position in the buffer and update cea -static uchar *unpack_rle(uchar *packed, size_t &packlen, ea_t &cea, qoff64_t fpos) -{ - const uchar *packed_sav = packed; - while ( 1 ) - { - if ( packlen < 1 ) - { -BADDATA: - warning("Bad packed data"); - return NULL; - } - uchar buf[256]; - buf[0] = '\0'; // shutup lint - uchar cnt = *packed++; - packlen--; - if ( cnt == 0 ) - break; - if ( cnt & 0x80 ) - { - cnt = (cnt & 0x7F) + 1; - if ( packlen < cnt ) - goto BADDATA; - mem2base(packed, cea, cea+cnt, fpos+(packed-packed_sav)); - packed += cnt; - packlen -= cnt; - cea += cnt; - continue; - } - if ( cnt & 0x40 ) - { - cnt = (cnt & 0x3F) + 1; - memset(buf, 0, cnt); - } - else if ( cnt & 0x20 ) - { - if ( packlen < 1 ) - goto BADDATA; - cnt = (cnt & 0x1F) + 2; - memset(buf, *packed++, cnt); - packlen--; - } - else if ( cnt & 0x10 ) - { - cnt = (cnt & 0x0F) + 1; - memset(buf, 0xFF, cnt); - } - else if ( cnt == 1 ) - { - if ( packlen < 2 ) - goto BADDATA; - buf[0] = 0x00; - buf[1] = 0x00; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0xFF; - buf[5] = 0xFF; - buf[6] = *packed++; - buf[7] = *packed++; - packlen -= 2; - cnt = 8; - } - else if ( cnt == 2 ) - { - if ( packlen < 3 ) - goto BADDATA; - buf[0] = 0x00; - buf[1] = 0x00; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = 0xFF; - buf[5] = *packed++; - buf[6] = *packed++; - buf[7] = *packed++; - cnt = 8; - packlen -= 3; - } - else if ( cnt == 3 ) - { - if ( packlen < 3 ) - goto BADDATA; - buf[0] = 0xA9; - buf[1] = 0xF0; - buf[2] = 0x00; - buf[3] = 0x00; - buf[4] = *packed++; - buf[5] = *packed++; - buf[6] = 0x00; - buf[7] = *packed++; - cnt = 8; - packlen -= 3; - } - else if ( cnt == 4 ) - { - if ( packlen < 4 ) - goto BADDATA; - buf[0] = 0xA9; - buf[1] = 0xF0; - buf[2] = 0x00; - buf[3] = *packed++; - buf[4] = *packed++; - buf[5] = *packed++; - buf[6] = 0x00; - buf[7] = *packed++; - cnt = 8; - packlen -= 4; - } - mem2base(buf, cea, cea+cnt, -1); - cea += cnt; - } - return packed; -} - -//------------------------------------------------------------------------ -static size_t unpack_data0000( - linput_t *li, - qoff64_t fpos, - size_t size, - ea_t ea, - const code0000_t &code0000, - ea_t code1ea, - ea_t &a5) -{ - if ( size < 4 ) - { -BADDATA: - warning("Bad packed data"); - return 0; - } - bytevec_t packed_buf; - packed_buf.resize(size); - uchar *packed = packed_buf.begin(); - qlseek(li, fpos); - lread(li, packed, size); - size_t usize = code0000.nBytesAboveA5 + code0000.nBytesBelowA5; // total data size - enable_flags(ea, ea+usize, STT_CUR); - - packed += sizeof(uint32); // skip initializers size - size -= sizeof(uint32); - - a5 = ea+code0000.nBytesBelowA5; - ea_t cea; - for ( int i=0; i < 3; i++ ) - { - if ( size < 4 ) - goto BADDATA; - int32 offset = swap32(*(uint32*)packed); //offset from A5 - packed += sizeof(uint32); - size -= sizeof(uint32); - cea = a5 + offset; - if ( cea < ea ) - { - //can happen when code 0 resource is not present (e.g. prc-tools GLib-type shared libs) - if ( i != 0 ) - loader_failure("Error while decompressing data 0"); - cea = ea; - a5 = ea-offset; - } - if ( size > 0 ) - { - packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); - if ( packed == NULL ) - return 0; - } - if ( usize < cea-ea ) - usize = size_t(cea-ea); - } - - if ( a5 > ea + usize - 1 ) - { - // allocate one extra byte for A5 - enable_flags(ea+usize, ea+usize+1, STT_CUR); - usize++; - } - create_byte(a5,1); - if ( a5 != ea ) - add_pgm_cmt("A5 register does not point to the start of the data segment\n" - "The file should not be recompiled using Pila\n"); - set_name(a5,"A5BASE",SN_NOCHECK|SN_AUTO); - set_cmt(a5,"A5 points here",0); - //TODO: find undefined bytes and set them to zero - //this is done by Palm OS loader and some programs depend on it - - // process relocations - if ( size > 0 ) - { - //a5 to a5 - //msg("Relocations: data to data\n"); - packed = apply_relocs(packed, size, a5, a5); - if ( packed == NULL ) - return 0; - //packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); - } - if ( size > 0 ) - { - //a5 to code - //msg("Relocations: data to code1\n"); - packed = apply_relocs(packed, size, a5, code1ea, true); - if ( packed == NULL ) - return 0; - //packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); - } - return usize; -} - -//------------------------------------------------------------------------ -// CodeWarrior A4 data layout: -// -// 0..3: 0x00000000 -// 4..7: size of "above A4" region -// 8..11: size of "below A4" region -// 12..N-1: compressed "below A4" data -// N..N+3: size of "near above A4" region -// N+4..O-1: compressed "near above A4" data -// O..O+3: size of "far above A4" region -// O+4..P-1: compressed "far above A4" data -// then the relocations: -// 1) A4 -> A4 -// 2) A4 -> A5 -// 3) A4 -> code0001 -// 4) A5 -> A4 - -static size_t unpack_data0001(linput_t *li, qoff64_t fpos, size_t size, ea_t ea, ea_t a5, ea_t code1ea, ea_t &a4) -{ - if ( size < 3 * sizeof(uint32) ) - { -BADDATA: - warning("Bad packed data"); - return 0; - } - bytevec_t packed_buf; - packed_buf.resize(size); - uchar *packed = packed_buf.begin(); - qlseek(li, fpos); - lread(li, packed, size); - packed += sizeof(uint32); // skip the 0 - size -= sizeof(uint32); - - int32 above = swap32(*(int32*)packed); - packed += sizeof(int32); - size -= sizeof(uint32); - int32 below = swap32(*(int32*)packed); - packed += sizeof(int32); - size -= sizeof(uint32); - size_t usize = above - below; // unpacked size - if ( below & 1 ) - usize++; - - ea_t cea = ea; - a4 = ea-below; - if ( below & 1 ) - a4++; - enable_flags(ea, ea+usize, STT_CUR); - create_byte(a4,1); - set_name(a4,"A4BASE",SN_NOCHECK|SN_AUTO); - set_cmt(a4,"A4 points here",0); - - //unpack below a4 - packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); - if ( packed == NULL ) - return 0; - - //unpack near above a4 - if ( size < sizeof(int32) ) - goto BADDATA; - cea = a4 + swap32(*(int32*)packed); - packed += sizeof(int32); - size -= sizeof(uint32); - packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); - if ( packed == NULL ) - return 0; - - //unpack far above a4 - if ( size < sizeof(int32) ) - goto BADDATA; - cea = a4 + swap32(*(int32*)packed); - packed += sizeof(int32); - size -= sizeof(uint32); - packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); - if ( packed == NULL ) - return 0; - - cea -= ea; - if ( usize < cea ) - usize = (size_t)cea; - - // process relocations - if ( size > 0 ) - { - //a4 to a4 - //msg("Relocations: a4 to a4\n"); - packed = apply_relocs(packed, size, a4, a4); - if ( packed == NULL ) - return 0; - //packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); - } - if ( size > 0 ) - { - //a4 to a5 - //msg("Relocations: a4 to a5\n"); - packed = apply_relocs(packed, size, a4, a5); - if ( packed == NULL ) - return 0; - //packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); - } - if ( size > 0 ) - { - //a4 to code1 - //msg("Relocations: a4 to code1\n"); - packed = apply_relocs(packed, size, a4, code1ea, true); - if ( packed == NULL ) - return 0; - //packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); - } - if ( size > 0 ) - { - //a5 to a4 - //msg("Relocations: a5 to a4\n"); - packed = apply_relocs(packed, size, a5, a4); - if ( packed == NULL ) - return 0; - //packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); - } - return usize; -} - -//------------------------------------------------------------------------ -void fix_jumptables(ea_t ea1, ea_t /*ea2*/, sel_t sel, ea_t a5, ea_t a4) -{ - //msg("Fixing additional code segment at %08X\n",ea1); - //from PalmOS_Startup.cpp - /* - struct SegmentHeader { // the structure of a segment header - short jtsoffset; // A5 relative offset of this segments jump table (short version) - short jtentries; // number of entries in this segments jump table - int32 jtloffset; // A5 relative offset of this segments jump table (long version) - int32 xrefoffset; // offset of xref data in this CODE resource - char code[]; // the code - }; - struct JumpTableEntry { // the structure of a jumptable entry - short jumpinstruction; // instruction: jmp routine - int32 jumpaddress; // absolute or relative address of rountine - };*/ - - short jtsoffset = get_word(ea1); - int32 jtloffset = get_dword(ea1+4); - if ( jtsoffset != jtloffset ) - { - //msg("Doesn't look like a CodeWarrior code segment\n"); - return; - } - //find the jumptable - ea_t jt_start; - if ( a4 != BADADDR && get_word(a4+jtloffset) == 0x4EF9 ) //jmp opcode - { - jt_start = a4+jtloffset; - create_word(ea1,2); - create_dword(ea1+4,4); - op_offset(ea1, 0, REF_OFF16, BADADDR, a4); - op_offset(ea1+4, 0, REF_OFF32, BADADDR, a4); - } - else if ( get_word(a5+jtloffset) == 0x4EF9 ) //jmp opcode - { - jt_start = a5+jtloffset; - create_word(ea1,2); - create_dword(ea1+4,4); - op_offset(ea1, 0, REF_OFF16, BADADDR, a5); - op_offset(ea1+4, 0, REF_OFF32, BADADDR, a5); - } - else - { - //msg("Could not find the jump table!\n"); - return; - } - - create_word(ea1+2,2); - create_dword(ea1+8,4); - op_offset(ea1+8, 0, REF_OFF32, BADADDR, ea1); - set_cmt(ea1, "Short jump table offset", 0); - set_cmt(ea1+2, "Number of jump table entries", 0); - set_cmt(ea1+4, "Long jump table offset", 0); - set_cmt(ea1+8, "Offset to xref data", 0); - - fixup_data_t fd(FIXUP_OFF32); - fd.sel = sel; - ea_t jt_addr=jt_start; - short jtentries = get_word(ea1+2); - while ( jtentries-- ) - { - fd.off = get_dword(jt_addr+2); - fd.set(jt_addr+2); - //a little heuristic: does the jump point to code? - if ( get_word(ea1+fd.off) == 0x4E56 //link a6,x - || get_word(ea1+fd.off) == 0x06AF ) //addi.l x, 4(sp) - { - auto_make_proc(ea1+fd.off); - auto_make_proc(jt_addr); - } - jt_addr+=6; - } - //TODO: hide the table? - //add_hidden_range(jt_start, jt_addr, "Jumptable for segment NNN", "", "", 0); -} - -//------------------------------------------------------------------------ -void doCodeOffset(ea_t ea, ea_t base) -{ - create_dword(ea,4); - uint32 off = get_dword(ea); - op_offset(ea, 0, REF_OFF32, BADADDR, base, off&1); - ea_t target = base+off; - if ( off&1 )//last bit set: offset to thumb code - { - target &= (~1); //remove last bit - //set_sreg_at_next_code(target,BADADDR,str2reg("T"),1); - split_sreg_range(target,str2reg("T"),1,SR_auto,true); - } - auto_make_proc(target); -} - -//------------------------------------------------------------------------ -void fixArmCW(ea_t start_ea, ea_t end_ea) -{ - //check for codewarrior relocation info - /* - typedef struct PnoHeaderType { - 00 UInt32 startupCode[8]; // changes based on the instruction count in startup code - 20 UInt32 pnoMain; // offset to ARMletMain routine - 24 UInt32 signature; // special PNO signature value - 28 UInt32 dataStart; // offset to start of initialized data - 2C UInt32 roDataStart; // offset to start of read-only initialized data - 30 UInt32 bssStart; // offset to start of uninitialized data - 34 UInt32 bssEnd; // offset to end of uninitialized data - 38 UInt32 codeRelocsStart; // offset to start of data-to-code relocation list - 3C UInt32 codeRelocsEnd; // offset to end of data-to-code relocation list - 40 UInt32 dataRelocsStart; // offset to start of data-to-data relocation list - 44 UInt32 dataRelocsEnd; // offset to end of data-to-data relocation list - 48 UInt32 altEntryCode[8]; // changes based on the instruction count in alternate entry code - 68 - } PnoHeaderType; - */ - const char *const comments[] = - { - "offset to ARMletMain routine", - "special PNO signature value", - "offset to start of initialized data", - "offset to start of read-only initialized data", - "offset to start of uninitialized data", - "offset to end of uninitialized data", - "offset to start of data-to-code relocation list", - "offset to end of data-to-code relocation list", - "offset to start of data-to-data relocation list", - "offset to end of data-to-data relocation list", - }; - - if ( end_ea-start_ea < 0x68 ) - return; - for ( int i=0x20; i < 0x48; i+=4 ) - { - create_dword(start_ea+i,4); - if ( i == 0x24 ) - op_chr(start_ea+i, 0); - else - op_offset(start_ea+i, 0, REF_OFF32, BADADDR, start_ea); - set_cmt(start_ea+i, comments[(i-0x20)/4],0); - } - auto_make_proc(start_ea); - auto_make_proc(start_ea+0x48); - doCodeOffset(start_ea+0x20,start_ea); - - //do relocs - ea_t cur = start_ea+get_dword(start_ea+0x38); - ea_t end = start_ea+get_dword(start_ea+0x3C); - for ( ; cur < end; cur+=4 ) - { - create_dword(cur,4); - op_offset(cur, 0, REF_OFF32, BADADDR, start_ea); - doCodeOffset(start_ea+get_dword(cur), start_ea); - } - cur = start_ea+get_dword(start_ea+0x40); - end = start_ea+get_dword(start_ea+0x44); - for ( ; cur < end; cur+=4 ) - { - create_dword(cur,4); - op_offset(cur, 0, REF_OFF32, BADADDR, start_ea); - ea_t o = start_ea+get_dword(cur); - create_dword(o,4); - op_offset(o, 0, REF_OFF32, BADADDR, start_ea); - } -} - -//------------------------------------------------------------------------ -//check for 'cdwr' signature -bool isCWseg(linput_t *li, uint32 offset) -{ - qlseek(li, offset + 0x24); - uchar sig[4]; - qlread(li, sig, 4); - return sig[0] == 'r' - && sig[1] == 'w' - && sig[2] == 'd' - && sig[3] == 'c'; -} - -//------------------------------------------------------------------------ -void idaapi load_file(linput_t *li, ushort neflags, const char * fileformatname) -{ - int i; - bool armCode = strcmp(fileformatname, PRC_ARM) == 0; - bool manualMode = (neflags & NEF_MAN) != 0; //don't do any extra processing if set - sel_t dgroup = BADSEL; - - set_processor_type(armCode ? "ARM" : "68K", SETPROC_LOADER); - set_target_assembler(armCode ? 0 : 2); // Generic ARM assembler/PalmPilot assembler Pila - DatabaseHdrType h; - lread(li,&h,sizeof(h)); - swap_prc(h); - - qvector<ResourceMapEntry> re; - re.resize(h.numRecords); - lread(li, re.begin(), sizeof(ResourceMapEntry) * h.numRecords); - for ( i=0; i < h.numRecords; i++ ) - swap_resource_map_entry(re[i]); - - code0000_t code0000 = { 0, 0 }; - if ( !armCode ) - { - //sortResources(re, h.numRecords); - // determine the bss size - for ( i=0; i < h.numRecords; i++ ) - { - if ( re[i].fcType == PILOT_RSC_CODE && re[i].id == 0 ) // code0000 - { - qlseek(li, re[i].ulOffset); - lread(li, &code0000, sizeof(code0000)); - swap_code0000(&code0000); - break; - } - } - } - - ea_t a5 = BADADDR, a4 = BADADDR, code1ea = BADADDR; - ea_t datastart = BADADDR; - - // load the segments - for ( i=0; i < h.numRecords; i++ ) - { - //don't load known UI resources when asked not to - if ( !(NEF_RSCS & neflags) && isKnownResource(re[i].fcType) ) - continue; - //skip ARM chunks in 68K mode - if ( !armCode && (re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL) ) - continue; - - uint64 size; - if ( i == (h.numRecords-1) ) - size = qlsize(li); - else - size = re[i+1].ulOffset; - if ( size < re[i].ulOffset ) - loader_failure("Invalid file structure"); - size -= re[i].ulOffset; - ea_t ea1 = (inf_get_max_ea() + 0xF) & ~0xF; - ea_t ea2 = ea1 + size; - - char segname[10]; - qsnprintf(segname, sizeof(segname), "%4.4s%04X", (char*)&re[i].fcType, re[i].id); - const char *sclass = "RSC"; - - if ( armCode ) - { - //load only ARM segments in ARM mode - if ( re[i].fcType != PILOT_RSC_ARMC && re[i].fcType != PILOT_RSC_ARMCL ) - continue; - - bool bCodeWarrior = isCWseg(li, re[i].ulOffset); - - ea_t start_ea=ea1; - file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE); - int sel = i+1; - if ( bCodeWarrior && !manualMode ) - { - //load all sequential chunks as one segment - while ( i < h.numRecords-1 && re[i].fcType == re[i+1].fcType && re[i].id + 1 == re[i+1].id && !isCWseg(li, re[i+1].ulOffset) ) - { - i++; - if ( i == (h.numRecords-1) ) - size = qlsize(li); - else - size = re[i+1].ulOffset; - if ( size < re[i].ulOffset ) - loader_failure("Invalid file structure"); - size -= re[i].ulOffset; - ea1 = ea2; //TODO: check if pnoloader.c does alignment - ea2 = ea1 + size; - file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE); - } - } - set_selector(sel, start_ea >> 4); - if ( !add_segm(sel, start_ea, ea2, segname, CLASS_CODE) ) - loader_failure(); - - //set DS for the segment to itself - set_default_sreg_value(get_segm_by_sel(sel), str2reg("DS"), sel); - if ( bCodeWarrior ) - fixArmCW(start_ea, ea2); - continue; - } - - if ( re[i].fcType == PILOT_RSC_CODE ) - { - if ( re[i].id == 0 && !manualMode ) - continue; // skip code0000 resource - sclass = CLASS_CODE; - if ( re[i].id == 1 ) - { - inf_set_start_cs(i + 1); - inf_set_start_ip(0); - code1ea = ea1; - } - } - else if ( re[i].fcType == PILOT_RSC_LIBR || re[i].fcType == PILOT_RSC_GLIB ) - { - sclass = CLASS_CODE; - if ( re[i].id == 0 ) - { - inf_set_start_cs(i + 1); - inf_set_start_ip(0); - code1ea = ea1; - } - } - - //check if we need to decompress stuff - if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 0 ) - { - sclass = CLASS_DATA; - dgroup = i + 1; - size_t usize = unpack_data0000(li, re[i].ulOffset, size, ea1, code0000, code1ea, a5); - ea2 = ea1 + usize; - datastart = ea1; - } - else if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 1 && !manualMode ) - { - sclass = CLASS_DATA; - size_t usize = unpack_data0001(li, re[i].ulOffset, size, ea1, a5, code1ea, a4); - ea2 = ea1 + usize; - } - else - { - //otherwise just load it as-is - file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE); - } - - { - segment_t s; - s.start_ea = ea1; - s.end_ea = ea2; - s.sel = i+1; - s.bitness = 1; // 32bit - set_selector(i+1, ea1 >> 4); - if ( !add_segm_ex(&s, segname, sclass, ADDSEG_FILLGAP|ADDSEG_OR_DIE) ) - loader_failure(); - } - } - - if ( !manualMode && !armCode ) - { - //check if first dword is 1; if so, skip it - if ( get_dword(code1ea) == 1 ) - { - //codewarrior startup - static const uchar pattern[] = - { - 0x00, 0x00, 0x00, 0x01, //dc.l 1 - 0x48, 0x7A, 0x00, 0x04, //pea $A - 0x06, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, //addi.l #(__Startup__-$A),(sp) - 0x4E, 0x75, //rts - }; - if ( equal_bytes(code1ea, pattern, SKIP_FF_MASK, sizeof(pattern), true) ) - { - plan_to_apply_idasgn("cwpalm.sig"); - } - create_dword(code1ea, 4); - inf_set_start_ip(4); - } - //is main code segment GLib? - if ( inf_get_start_cs() > 0 - && re[int(inf_get_start_cs()-1)].fcType == PILOT_RSC_GLIB - && a4 == BADADDR - && datastart != BADADDR ) - { - //GLib's a4 points at the start of data segment - a4 = datastart; - create_byte(a4, 1); - set_name(a4, "A4BASE", SN_NOCHECK|SN_AUTO); - set_cmt(a4, "A4 points here", 0); - } - //check for CodeWarrior's jumptables in additional code segments and fix them up - for ( i=0; i < h.numRecords; i++ ) - { - if ( re[i].fcType == PILOT_RSC_CODE && re[i].id > 1 ) - { - segment_t *seg = get_segm_by_sel(i+1); - if ( seg != NULL ) - fix_jumptables(seg->start_ea, seg->end_ea, i+1, a5, a4); - } - } - //TODO: handle prc-tools and multilink's 'rloc' segments - } - - if ( dgroup != BADSEL ) - set_default_dataseg(dgroup); // input: selector - describe_all(h); - exec_system_script("pilot.idc"); -} - -//-------------------------------------------------------------------------- -// it is impossible to use ph.id, -// the processor module is not loaded yet -inline bool is_arm_specified(void) -{ - return strnieq(inf_get_procname().c_str(), "ARM", 3); -} - -inline bool is_68k_specified(void) -{ - char pname[IDAINFO_PROCNAME_SIZE]; - inf_get_procname(pname, sizeof(pname)); - return strnieq(pname, "68K", 3) - || strnieq(pname, "68000", 5) - || strnieq(pname, "68010", 5) - || strnieq(pname, "68020", 5) - || strnieq(pname, "68030", 5) - || strnieq(pname, "68040", 5) - || strnieq(pname, "68330", 5) - || strnieq(pname, "68882", 5) - || strnieq(pname, "68851", 5) - || strnieq(pname, "ColdFire", 8); -} - -//-------------------------------------------------------------------------- -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - static int n = 0; - int k = is_prc_file(li); - if ( k == 0 ) - return 0; - int ftype = 0; - if ( n == 1 ) - { - if ( k == 2 ) // has ARM segments? - { - *fileformatname = PRC_ARM; - *processor = "ARM"; - ftype = f_PRC; - if ( is_arm_specified() ) - ftype |= ACCEPT_FIRST; - } - } - else - { - n++; - *fileformatname = PRC_68K; - *processor = "68K"; - ftype = f_PRC|ACCEPT_CONTINUE; - if ( is_68k_specified() ) - ftype |= ACCEPT_FIRST; - } - return ftype; -} - -//-------------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/ldr/pilot/pilot.hpp b/idasdk75/ldr/pilot/pilot.hpp deleted file mode 100644 index ff95e0b..0000000 --- a/idasdk75/ldr/pilot/pilot.hpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - */ - -#ifndef __PILOT_H -#define __PILOT_H -#pragma pack(push, 1) - -#include <time.h> - -#define PRC_68K "PalmPilot program file (68K)" -#define PRC_ARM "PalmPilot program file (ARM)" - -//Regular resources: - -#define PILOT_RSC_CODE 0x65646F63L // "code\0\0\0\1" program code -#define PILOT_RSC_PREF 0x66657270L // "pref\0\0\0\0" preferences (not used yet) -#define PILOT_RSC_DATA 0x61746164L // "data\0\0\0\0" image of global data -#define PILOT_RSC_LIBR 0x7262696CL // "libr" SysLib-type shared library code -#define PILOT_RSC_GLIB 0x62694C47L // "GLib" PRC-Tools GLib-type shared library code -#define PILOT_RSC_RLOC 0x636F6C72L // "rloc" PRC-Tools and Multilink relocations -#define PILOT_RSC_ARMC 0x434D5241L // "ARMC" ARM native code -#define PILOT_RSC_ARMCL 0x636D7261L // "armc" ARM native code - -// UI resources: - -#define PILOT_RSC_MBAR 0x5241424DL // "MBAR" Menu bar -#define PILOT_RSC_MENU 0x554E454DL // "MENU" Menu options -#define PILOT_RSC_ICON 0x4E494174L // "tAIN" Application icon name -#define PILOT_RSC_AIB 0x42494174L // "tAIB" Application icon bitmap -#define PILOT_RSC_AIS 0x53494174L // "tAIS" Application information string -#define PILOT_RSC_ALERT 0x746C6154L // "Talt" Alert -#define PILOT_RSC_BITMAP 0x706D6254L // "Tbmp" Bitmap -#define PILOT_RSC_BUTTON 0x4E544274L // "tBTN" Button -#define PILOT_RSC_CHECK 0x58424374L // "tCBX" Check box -#define PILOT_RSC_FBM 0x4D424674L // "tFBM" Form bitmap -#define PILOT_RSC_FIELD 0x444C4674L // "tFLD" Field -#define PILOT_RSC_FORM 0x4D524674L // "tFRM" Form -#define PILOT_RSC_GADGET 0x54444774L // "tGDT" Gadget -#define PILOT_RSC_GRAFF 0x49534774L // "tGSI" Graffiti Shift -#define PILOT_RSC_LABEL 0x4C424C74L // "tLBL" Label -#define PILOT_RSC_LIST 0x54534C74L // "tLST" List box -#define PILOT_RSC_PUSH 0x4E425074L // "tPBN" Push button -#define PILOT_RSC_POPUPL 0x4C555074L // "tPUL" Popup list -#define PILOT_RSC_POPUPT 0x54555074L // "tPUT" Popup trigger -#define PILOT_RSC_REPEAT 0x50455274L // "tREP" Repeating control -#define PILOT_RSC_SELECT 0x544C5374L // "tSLT" Selector trigger -#define PILOT_RSC_STRING 0x52545374L // "tSTR" String -#define PILOT_RSC_TABLE 0x4C425474L // "tTBL" Table -#define PILOT_RSC_TITLE 0x4C545474L // "tTTL" Title -#define PILOT_RSC_VER 0x72657674L // "tver" Version number string - - -typedef uchar Byte; -typedef ushort Word; -typedef uint32 DWord; -typedef DWord LocalID; - -// -// Header of PRC file: -// - -struct DatabaseHdrType -{ - Byte name[32]; // name of database -#define PILOT_CREATOR_PILA 0x616C6950L // "Pila" - Word attributes; // database attributes -#define dmHdrAttrResDB 0x0001 // Resource database -#define dmHdrAttrReadOnly 0x0002 // Read Only database -#define dmHdrAttrAppInfoDirty 0x0004 // Set if Application Info block is dirty - // Optionally supported by an App's conduit -#define dmHdrAttrBackup 0x0008 // Set if database should be backed up to PC if - // no app-specific synchronization conduit has - // been supplied. -#define dmHdrAttrOpen 0x8000 // Database not closed properly - Word version; // version of database - DWord creationDate; // creation date of database - DWord modificationDate; // latest modification date - DWord lastBackupDate; // latest backup date - DWord modificationNumber; // modification number of database - LocalID appInfoID; // application specific info - LocalID sortInfoID; // app specific sorting info - DWord type; // database type -#define PILOT_TYPE_APPL 0x6C707061L // "appl" - DWord id; // program id - DWord uniqueIDSeed; // used to generate unique IDs. - // Note that only the low order - // 3 bytes of this is used (in - // RecordEntryType.uniqueID). - // We are keeping 4 bytes for - // alignment purposes. - LocalID nextRecordListID; // local chunkID of next list - Word numRecords; // number of records in this list -}; - -// -// Each resource has the following entry: -// -struct ResourceMapEntry -{ - uint32 fcType; - ushort id; - uint32 ulOffset; -}; - - -// Pilot bitmap format (also format of icon) -struct pilot_bitmap_t -{ - ushort cx; - ushort cy; - ushort cbRow; - ushort ff; - ushort ausUnk[4]; -}; - - -/* - * code0000[long 0] nBytesAboveA5 - * code0000[long 1] nBytesBelowA5 - */ -struct code0000_t -{ - uint32 nBytesAboveA5; - uint32 nBytesBelowA5; -}; - -// pref0000 - -struct pref0000_t -{ - ushort flags; -#define sysAppLaunchFlagNewThread 0x0001 -#define sysAppLaunchFlagNewStack 0x0002 -#define sysAppLaunchFlagNewGlobals 0x0004 -#define sysAppLaunchFlagUIApp 0x0008 -#define sysAppLaunchFlagSubCall 0x0010 - uint32 stack_size; - uint32 heap_size; -}; - -#pragma pack(pop) -#endif // __PILOT_H diff --git a/idasdk75/ldr/qnx/makefile b/idasdk75/ldr/qnx/makefile deleted file mode 100644 index c76f7f2..0000000 --- a/idasdk75/ldr/qnx/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=qnx - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)qnx$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h lmf.h qnx.cpp diff --git a/idasdk75/ldr/rt11/makefile b/idasdk75/ldr/rt11/makefile deleted file mode 100644 index 20f0ad3..0000000 --- a/idasdk75/ldr/rt11/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=rt11 - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)rt11$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/pdp11/pdp_ml.h ../idaldr.h rt11.cpp diff --git a/idasdk75/ldr/script_ldrs/pdfldr.py b/idasdk75/ldr/script_ldrs/pdfldr.py deleted file mode 100644 index c964f8d..0000000 --- a/idasdk75/ldr/script_ldrs/pdfldr.py +++ /dev/null @@ -1,319 +0,0 @@ -""" -A script that extracts shellcode from PDF files - -The script uses very basic shellcode extraction algorithm - -Copyright (c) 1990-2020 Hex-Rays -ALL RIGHTS RESERVED. - -Revision history -========================= -v1.0 - initial version - - -Possible enhancements: -========================= -1. From Didier: ------------------ -FYI: the regex you use to match /JavaScript /JS will fail to match -name obfuscation. Name obuscation use a feature of the PDF language -that allows a character in a name (like /JavaScript) to be replaced -with its hexcode. Example: /#4AavaScript -http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/ - -It's something that's used in-the-wild. - -I've updated your regex to support name obfuscation. The JavaScript -itself is now captured in group 13. - -\/S\s*\/(J|#4A|#4a)(a|#61)(v|#76)(a|#61)(S|#53)(c|#63)(r|#72)(i|#69)(p|#70)(t|#74)\s*\/(J|#4A|#4a)(S|#53) -\((.+?)>> - -2. ---------------- - -""" - -import sys -import re -import zlib - -SAMPLE1 = 'malware1.pdf.vir' -SAMPLE2 = 'heapspray-simpler-calc.pdf.vir' - -try: - import idaapi - import idc - import ida_idp - ida = True -except: - ida = False - -# ----------------------------------------------------------------------- -# Tries to find shellcode inside JavaScript statements -# The seach algorithm is simple: it searchs for anything between unescape() -# if it encounters %u or %x it correctly decodes them to characters -def extract_shellcode(lines): - p = 0 - shellcode = [] # accumulate shellcode - while True: - p = lines.find(b'unescape("', p) - if p == -1: - break - e = lines.find(b')', p) - if e == -1: - break - expr = lines[p+9:e] - data = [] - def put_byte(b): - if sys.version_info.major >= 3: - data.append(b) - else: - data.append(chr(b)) - - for i in range(0, len(expr)): - if expr[i:i+2] == b"%u": - i += 2 - put_byte(int(expr[i+2:i+4], 16)) - put_byte(int(expr[i:i+2], 16)) - i += 4 - elif expr[i] == b"%": - i += 1 - put_byte(int(expr[i:i+2], 16)) - i += 2 - # advance the match pos - p += 8 - if sys.version_info.major >= 3: - shellcode.append(bytes(data)) - else: - shellcode.append("".join(data)) - - # That's it - return shellcode - -# ----------------------------------------------------------------------- -# Given a PDF object id and version, we return the object declaration -def find_obj(buf, id, ver): - stream = re.search(b'%d %d obj(.*?)endobj' % (id, ver), buf, re.MULTILINE | re.DOTALL) - if not stream: - return None - return buf[stream.start(1):stream.end(1)] - -# ----------------------------------------------------------------------- -# Find JavaScript objects and extract the referenced script object id/ver -def find_js_ref_streams(buf): - o = [] - js_ref_streams = re.finditer(r'\/S\s*\/JavaScript\/JS (\d+) (\d+) R'.encode("UTF-8"), buf) - for g in js_ref_streams: - id = int(g.group(1)) - ver = int(g.group(2)) - o.append([id, ver]) - return o - -# ----------------------------------------------------------------------- -# Find JavaScript objects and extract the embedded script -def find_embedded_js(buf): - r = re.finditer(r'\/S\s*\/JavaScript\s*\/JS \((.+?)>>'.encode("UTF-8"), buf, re.MULTILINE | re.DOTALL) - if not r: - return None - - ret = [] - for js in r: - p = buf.rfind(b'obj', 0, js.start(1)) - if p == -1: - return None - - scs = extract_shellcode(js.group(1)) - if not scs: - return None - - t = buf[p - min(20, len(buf)): p + 3] - obj = re.search('(\d+) (\d+) obj'.encode("UTF-8"), t) - if not obj: - id, ver = 0 - else: - id = int(obj.group(1)) - ver = int(obj.group(2)) - n = 0 - for sc in scs: - n += 1 - ret.append([id, ver, n, sc]) - return ret - -# ----------------------------------------------------------------------- -# Given a gzipped stream object, it returns the decompressed contents -def decompress_stream(buf): - if buf.find(b'Filter[/FlateDecode]') == -1: - return None - m = re.search(b'stream\s*(.+?)\s*endstream', buf, re.DOTALL | re.MULTILINE) - if not m: - return None - # Decompress and return - return zlib.decompress(m.group(1)) - - -# ----------------------------------------------------------------------- -def read_whole_file(li): - li.seek(0) - return li.read(li.size()) - -# ----------------------------------------------------------------------- -def extract_pdf_shellcode(buf): - ret = [] - - # find all JS stream references - r = find_js_ref_streams(buf) - for id, ver in r: - # extract the JS stream object - obj = find_obj(buf, id, ver) - - # decode the stream - stream = decompress_stream(obj) - - # extract shell code - scs = extract_shellcode(stream) - i = 0 - for sc in scs: - i += 1 - ret.append([id, ver, i, sc]) - - # find all embedded JS - r = find_embedded_js(buf) - if r: - ret.extend(r) - - return ret - -# ----------------------------------------------------------------------- -def accept_file(li, filename): - """ - Check if the file is of supported format - - @param li: a file-like object which can be used to access the input data - @param filename: name of the file, if it is an archive member name then the actual file doesn't exist - @return: 0 - no more supported formats - string "name" - format name to display in the chooser dialog - dictionary { 'format': "name", 'options': integer } - options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000) - to indicate preferred format - """ - - # we support only one format per file - li.seek(0) - if li.read(5) != b'%PDF-': - return 0 - - buf = read_whole_file(li) - r = extract_pdf_shellcode(buf) - if not r: - return 0 - - return {'format': 'PDF with shellcode', 'processor': 'metapc'} - -# ----------------------------------------------------------------------- -def load_file(li, neflags, format): - - """ - Load the file into database - - @param li: a file-like object which can be used to access the input data - @param neflags: options selected by the user, see loader.hpp - @return: 0-failure, 1-ok - """ - - # Select the PC processor module - idaapi.set_processor_type("metapc", ida_idp.SETPROC_LOADER) - - buf = read_whole_file(li) - r = extract_pdf_shellcode(buf) - if not r: - return 0 - - # Load all shellcode into different segments - start = 0x10000 - seg = idaapi.segment_t() - for id, ver, n, sc in r: - size = len(sc) - end = start + size - - # Create the segment - seg.start_ea = start - seg.end_ea = end - seg.bitness = 1 # 32-bit - idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0) - - # Copy the bytes - idaapi.mem2base(sc, start, end) - - # Mark for analysis - idc.AutoMark(start, idc.AU_CODE) - - # Compute next loading address - start = ((end // 0x1000) + 1) * 0x1000 - - # Select the bochs debugger - idc.load_debugger("bochs", 0) - - return 1 - -# ----------------------------------------------------------------------- -def test1(sample = SAMPLE1): - # open the file - f = file(sample, 'rb') - buf = f.read() - f.close() - - # find all JS stream references - r = find_js_ref_streams(buf) - if not r: - return - - for id, ver in r: - obj = find_obj(buf, id, ver) - - # extract the JS stream object - f = file('obj_%d_%d.bin' % (id, ver), 'wb') - f.write(obj) - f.close() - - # decode the stream - stream = decompress_stream(obj) - f = file('dec_%d_%d.bin' % (id, ver), 'wb') - f.write(stream) - f.close() - - # extract shell code - scs = extract_shellcode(stream) - i = 0 - for sc in scs: - i += 1 - f = file('sh_%d_%d_%d.bin' % (id, ver, i), 'wb') - f.write(sc) - f.close() - -# ----------------------------------------------------------------------- -def test2(sample = SAMPLE1): - # open the file - f = file(sample, 'rb') - buf = f.read() - f.close() - - r = extract_pdf_shellcode(buf) - for id, ver, n, sc in r: - print("sc %d.%d[%d]=%d" % (id, ver, n, len(sc))) - -# ----------------------------------------------------------------------- -def test3(sample = SAMPLE2): - # open the file - f = file(sample, 'rb') - buf = f.read() - f.close() - t = find_embedded_js(buf) - print(t) - -# ----------------------------------------------------------------------- -def main(): - test1(SAMPLE1) - -if not ida: - main() diff --git a/idasdk75/ldr/script_ldrs/uimage.py b/idasdk75/ldr/script_ldrs/uimage.py deleted file mode 100644 index 25221ca..0000000 --- a/idasdk75/ldr/script_ldrs/uimage.py +++ /dev/null @@ -1,218 +0,0 @@ -# a file loader for U-Boot "uImage" flash images -# Copyright (c) 2011-2020 Hex-Rays -# ALL RIGHTS RESERVED. - -import idaapi -import idc -import zlib -import ida_idp -import ida_typeinf - -IH_TYPE_INVALID = 0 # /* Invalid Image */ -IH_TYPE_STANDALONE = 1 # /* Standalone Program */ -IH_TYPE_KERNEL = 2 # /* OS Kernel Image */ -IH_TYPE_RAMDISK = 3 # /* RAMDisk Image */ -IH_TYPE_MULTI = 4 # /* Multi-File Image */ -IH_TYPE_FIRMWARE = 5 # /* Firmware Image */ -IH_TYPE_SCRIPT = 6 # /* Script file */ -IH_TYPE_FILESYSTEM = 7 # /* Filesystem Image (any type) */ - -ImageTypeNames = [ "Invalid", "Standalone Program", "OS Kernel", "RAMDisk", - "Multi-File", "Firmware", "Script file", "Filesystem" ] - -IH_ARCH_INVALID = 0 # /* Invalid CPU */ -IH_ARCH_ALPHA = 1 # /* Alpha */ -IH_ARCH_ARM = 2 # /* ARM */ -IH_ARCH_I386 = 3 # /* Intel x86 */ -IH_ARCH_IA64 = 4 # /* IA64 */ -IH_ARCH_MIPS = 5 # /* MIPS */ -IH_ARCH_MIPS64 = 6 # /* MIPS 64 Bit */ -IH_ARCH_PPC = 7 # /* PowerPC */ -IH_ARCH_S390 = 8 # /* IBM S390 */ -IH_ARCH_SH = 9 # /* SuperH */ -IH_ARCH_SPARC = 10 # /* Sparc */ -IH_ARCH_SPARC64 = 11 # /* Sparc 64 Bit */ -IH_ARCH_M68K = 12 # /* M68K */ -IH_ARCH_NIOS = 13 # /* Nios-32 */ -IH_ARCH_MICROBLAZE = 14 # /* MicroBlaze */ -IH_ARCH_NIOS2 = 15 # /* Nios-II */ -IH_ARCH_BLACKFIN = 16 # /* */ -IH_ARCH_AVR32 = 17 # /* */ -IH_ARCH_ST200 = 18 # /* */ -IH_ARCH_SANDBOX = 19 # /* */ -IH_ARCH_NDS32 = 20 # /* */ -IH_ARCH_OPENRISC = 21 # /* */ -IH_ARCH_ARM64 = 22 # /* */ -IH_ARCH_ARC = 23 # /* */ - -CPUNames = [ "Invalid", "Alpha", "ARM", "x86", "IA64", "MIPS", "MIPS64", "PowerPC", - "IBM S390", "SuperH", "Sparc", "Sparc64", "M68K", "Nios-32", "MicroBlaze", "Nios-II", - "Blackfin", "AVR32", "ST200","Sandbox","NDS32", "OpenRISC", "ARM64", "ARC" ] - -IDACPUNames = { IH_ARCH_ALPHA: "alphab", - IH_ARCH_ARM:"ARM", - IH_ARCH_I386: "metapc", - IH_ARCH_IA64: "ia64b", - IH_ARCH_MIPS:"mipsl", - IH_ARCH_MIPS64:"mipsl", - IH_ARCH_PPC: "ppc", - IH_ARCH_SH: "SH4", - IH_ARCH_SPARC: "sparcb", - IH_ARCH_SPARC64:"sparcb", - IH_ARCH_M68K:"68K", - IH_ARCH_ARM64:"ARM", - IH_ARCH_ARC: "arcmpct" } - -IDAABINames = { IH_ARCH_MIPS:"n32", - IH_ARCH_MIPS64:"n64" } - -IH_COMP_NONE = 0 # /* No Compression Used */ -IH_COMP_GZIP = 1 # /* gzip Compression Used */ -IH_COMP_BZIP2 = 2 # /* bzip2 Compression Used */ -IH_COMP_LZMA = 3 # /* lzma Compression Used */ -IH_COMP_LZO = 4 # /* lzo Compression Used */ -CompTypeNames = [ "", "gzip", "bzip2", "lzma", "lzo" ] - -IH_MAGIC = 0x27051956 # Image Magic Number -IH_NMLEN = 32 # Image Name Length - -import ctypes - -uint8_t = ctypes.c_byte -uint32_t = ctypes.c_uint - -class image_header(ctypes.BigEndianStructure): - _fields_ = [ - ("ih_magic", uint32_t), # Image Header Magic Number - ("ih_hcrc", uint32_t), # Image Header CRC Checksum - ("ih_time", uint32_t), # Image Creation Timestamp - ("ih_size", uint32_t), # Image Data Size - ("ih_load", uint32_t), # Data Load Address - ("ih_ep", uint32_t), # Entry Point Address - ("ih_dcrc", uint32_t), # Image Data CRC Checksum - ("ih_os", uint8_t), # Operating System - ("ih_arch", uint8_t), # CPU architecture - ("ih_type", uint8_t), # Image Type - ("ih_comp", uint8_t), # Compression Type - ("ih_name", uint8_t * IH_NMLEN), # Image Name - ] -RomFormatName = "U-Boot image" - -# ----------------------------------------------------------------------- -def dwordAt(li, off): - li.seek(off) - s = li.read(4) - if len(s) < 4: - return 0 - return struct.unpack('<I', s)[0] - -def read_struct(li, struct): - s = struct() - s.ih_magic = 0 - slen = ctypes.sizeof(s) - if li.size() >= slen: - bytes = li.read(slen) - fit = min(len(bytes), slen) - ctypes.memmove(ctypes.addressof(s), bytes, fit) - return s - -# ----------------------------------------------------------------------- -def accept_file(li, filename): - """ - Check if the file is of supported format - - @param li: a file-like object which can be used to access the input data - @param filename: name of the file, if it is an archive member name then the actual file doesn't exist - @return: 0 - no more supported formats - string "name" - format name to display in the chooser dialog - dictionary { 'format': "name", 'options': integer } - options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000) - to indicate preferred format - """ - - header = read_struct(li, image_header) - # check the signature - if header.ih_magic == IH_MAGIC: - # accept the file - t = header.ih_type - c = header.ih_arch - if t >= len(ImageTypeNames): - t = "unknown type(%d)" % t - else: - t = ImageTypeNames[t] - - if c >= len(CPUNames): - cname = "unknown CPU(%d)" % c - else: - cname = CPUNames[c] - - fmt = "%s (%s for %s)" % (RomFormatName, t, cname) - comp = header.ih_comp - if comp != IH_COMP_NONE: - if comp >= len (CompTypeNames): - cmpname = "unknown compression(%d)" - else: - cmpname = "%s compressed" % CompTypeNames[comp] - fmt += " [%s]" % cmpname - - proc = '' - if c in IDACPUNames: - proc = IDACPUNames[c] - - return {'format': fmt, 'processor': proc} - - # unrecognized format - return 0 - -# ----------------------------------------------------------------------- -def load_file(li, neflags, format): - - """ - Load the file into database - - @param li: a file-like object which can be used to access the input data - @param neflags: options selected by the user, see loader.hpp - @return: 0-failure, 1-ok - """ - - if format.startswith(RomFormatName): - li.seek(0) - header = read_struct(li, image_header) - c = header.ih_arch - cname = IDACPUNames.get(c) - if not cname: - idc.warning("Unsupported CPU") - #return - - if not header.ih_comp in (IH_COMP_NONE, IH_COMP_GZIP): - idc.warning("Can only handle uncompressed or gzip-compressed images") - return - - if cname: - idaapi.set_processor_type(cname, ida_idp.SETPROC_LOADER) - - idc.AddSeg(header.ih_load, header.ih_load + header.ih_size, 0, 1, idaapi.saRelPara, idaapi.scPub) - - # copy bytes to the database - - if header.ih_comp == IH_COMP_NONE: - li.file2base(ctypes.sizeof(header), header.ih_load, header.ih_load + header.ih_size, 0) - else: - cdata = li.read(header.ih_size) - d = zlib.decompressobj(zlib.MAX_WBITS|32) - udata = d.decompress(cdata) - udata += d.flush() - # expand segment to fit uncompressed data - idc.set_segment_bounds(header.ih_load, header.ih_load, header.ih_load+len(udata), idc.SEGMOD_KEEP) - idaapi.put_bytes(header.ih_load, udata) - - if cname == "ARM" and (header.ih_ep & 1) != 0: - # Thumb entry point - header.ih_ep -= 1 - split_sreg_range(header.ih_ep, "T", 1) - idaapi.add_entry(header.ih_ep, header.ih_ep, "start", 1) - aname = IDAABINames.get(header.ih_arch) - if aname: - ida_typeinf.set_abi_name(aname) - print("Load OK") - return 1 diff --git a/idasdk75/ldr/snes/makefile b/idasdk75/ldr/snes/makefile deleted file mode 100644 index ef6fc28..0000000 --- a/idasdk75/ldr/snes/makefile +++ /dev/null @@ -1,13 +0,0 @@ -PROC=snes - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)snes$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaldr.h addr.cpp snes.cpp super-famicom.hpp diff --git a/idasdk75/ldr/snes/snes.cpp b/idasdk75/ldr/snes/snes.cpp deleted file mode 100644 index cb92335..0000000 --- a/idasdk75/ldr/snes/snes.cpp +++ /dev/null @@ -1,716 +0,0 @@ - -#include "../idaldr.h" -#include "addr.cpp" - -//---------------------------------------------------------------------------- -static void map_io_seg(ea_t start, ea_t end, const char *const name) -{ - segment_t s; - s.start_ea = start; - s.end_ea = end; - s.type = SEG_IMEM; - s.sel = allocate_selector(start >> 4); - if ( !add_segm_ex(&s, name, NULL, ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", name); -} - - -//---------------------------------------------------------------------------- -static void map_hwregs() -{ - map_io_seg(0x2100, 0x2140, "ppu"); - map_io_seg(0x2140, 0x2144, "apu"); - map_io_seg(0x2180, 0x2184, "wramrw"); - map_io_seg(0x4016, 0x4018, "joypad"); - map_io_seg(0x4200, 0x4220, "misc"); - map_io_seg(0x4300, 0x4380, "dma"); -} - - -//---------------------------------------------------------------------------- -static void map_wram() -{ - segment_t s; - s.start_ea = 0x7e0000; - s.end_ea = 0x800000; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), "wram"); - if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); -} - -//---------------------------------------------------------------------------- -static void map_lorom_sram_offset(uint32 ram_size, uint8 start_bank) -{ - // Usually, the lower half of bank (0x8000 bytes) is SRAM, and the upper half is ROM mirror. - // However, some cartridges maps the whole of bank (0x10000 bytes) to SRAM. - // In that case, the upper half is probably mirrored as same as the lower half. - - // create ram banks - const uint32 bank_size = 0x8000; - uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; - for ( uint32 mapped = 0, bank = start_bank; mapped < ram_chunks; bank++, mapped++ ) - { - if ( bank == 0x7e ) - bank = 0xfe; - - segment_t s; - s.start_ea = uint32(bank << 16); - s.end_ea = s.start_ea + bank_size; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); - if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); - } -} - -//---------------------------------------------------------------------------- -static void map_hirom_sram_offset(uint32 ram_size, uint8 start_bank) -{ - // create ram banks - const uint32 bank_size = 0x2000; - uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; - for ( uint32 mapped = 0, bank = start_bank; mapped < ram_chunks; bank++, mapped++ ) - { - segment_t s; - s.start_ea = uint32((bank << 16) + 0x6000); - s.end_ea = s.start_ea + bank_size; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); - if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); - } -} - -//---------------------------------------------------------------------------- -static void map_lorom_sram(uint32 ram_size) -{ - // create ram banks 70-7d (and fe-ff) - map_lorom_sram_offset(ram_size, 0x70); -} - -//---------------------------------------------------------------------------- -static void map_hirom_sram(uint32 ram_size) -{ - // create ram banks 20-3f - map_hirom_sram_offset(ram_size, 0x20); -} - -//---------------------------------------------------------------------------- -static void map_superfx_sram(uint32 ram_size) -{ - // create ram banks 70-71 - const uint32 bank_size = 0x10000; - uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; - for ( uint32 mapped = 0, bank = 0x70; mapped < ram_chunks; bank++, mapped++ ) - { - segment_t s; - s.start_ea = uint32(bank << 16); - s.end_ea = s.start_ea + bank_size; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); - if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); - } -} - -//---------------------------------------------------------------------------- -static void map_superfx_workram() -{ - segment_t s; - s.start_ea = 0x6000; - s.end_ea = 0x8000; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), "sfxram"); - if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); -} - -//---------------------------------------------------------------------------- -static void map_superfx_hwregs() -{ - map_io_seg(0x3000, 0x3500, "superfx"); -} - -//---------------------------------------------------------------------------- -static void map_sa1_bwram(uint32 ram_size) -{ - // create ram banks 40-41 - const uint32 bank_size = 0x10000; - uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; - for ( uint32 mapped = 0, bank = 0x40; mapped < ram_chunks; bank++, mapped++ ) - { - segment_t s; - s.start_ea = uint32(bank << 16); - s.end_ea = s.start_ea + bank_size; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); - if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); - } -} - -//---------------------------------------------------------------------------- -static void map_sa1_iram() -{ - segment_t s; - s.start_ea = 0x3000; - s.end_ea = 0x3800; - s.type = SEG_IMEM; - s.sel = allocate_selector(s.start_ea >> 4); - - char seg_name[0x10]; - qsnprintf(seg_name, sizeof(seg_name), "iram"); - if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG) ) - loader_failure("Failed adding %s segment\n", seg_name); -} - -//---------------------------------------------------------------------------- -static void map_sa1_hwregs() -{ - map_io_seg(0x2200, 0x2400, "sa1"); -} - -//---------------------------------------------------------------------------- -static void map_cx4_hwregs() -{ - map_io_seg(0x6000, 0x8000, "cx4"); -} - -//---------------------------------------------------------------------------- -static void map_spc7110_hwregs() -{ - map_io_seg(0x4800, 0x4840, "spc7110"); - map_io_seg(0x500000, 0x600000, "decomprom"); -} - -//---------------------------------------------------------------------------- -static void map_sdd1_hwregs() -{ - map_io_seg(0x4800, 0x4808, "sdd1"); -} - -//---------------------------------------------------------------------------- -static sel_t map_lorom_offset(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint8 start_bank, uint32 offset) -{ - // 32KB chunks count - uint32 chunks = (rom_size + 0x8000 - 1) / 0x8000; - - // map rom to banks - sel_t start_sel = 0; - for ( uint32 mapped = 0, bank = start_bank; mapped < chunks; bank++, mapped++ ) - { - if ( bank == 0x7e || bank == 0x7f ) - continue; - - uint32 map_size = qmin(0x8000, rom_size - (0x8000 * mapped)); - - ea_t start = uint32((bank << 16) + 0x8000); - ea_t end = start + 0x8000; - uint32 off_in_file = rom_start_in_file + offset + (mapped << 15); - - if ( !file2base(li, off_in_file, start, start + map_size, FILEREG_PATCHABLE) ) - loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", off_in_file, start, end); - - char seg_name[0x10]; - sel_t selector = allocate_selector((start - 0x8000) >> 4); - qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); - if ( !add_segm(selector, start, end, seg_name, "BANK_ROM") ) - loader_failure("Failed adding .BANK segment\n"); - - if ( bank == start_bank ) - start_sel = selector; - } - - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_hirom_offset(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint8 start_bank, uint32 offset) -{ - sel_t start_sel = 0; - - // map rom to banks - uint32 chunks = (rom_size + 0x10000 - 1) / 0x10000; - for ( uint32 mapped = 0, bank = start_bank; mapped < chunks; bank++, mapped++ ) - { - if ( bank == 0x7e || bank == 0x7f ) - continue; - - uint32 map_size = qmin(0x10000, rom_size - (0x10000 * mapped)); - - ea_t start = uint32(bank << 16); - ea_t end = start + 0x10000; - uint32 off_in_file = rom_start_in_file + offset + (mapped << 16); - if ( !file2base(li, off_in_file, start, start + map_size, FILEREG_PATCHABLE) ) - loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", off_in_file, start, end); - - char seg_name[0x10]; - sel_t selector = allocate_selector((start) >> 4); - qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); - if ( !add_segm(selector, start, end, seg_name, "BANK_ROM") ) - loader_failure("Failed adding .BANK segment\n"); - - if ( bank == start_bank ) - start_sel = selector; - } - - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_lorom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) -{ - // map rom to banks 80-ff - return map_lorom_offset(li, rom_start_in_file, rom_size, 0x80, 0); -} - -//---------------------------------------------------------------------------- -static sel_t map_hirom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) -{ - // map rom to banks c0-ff - return map_hirom_offset(li, rom_start_in_file, rom_size, 0xc0, 0); -} - -//---------------------------------------------------------------------------- -static sel_t map_exhirom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) -{ - if ( rom_size <= 0x400000 ) - return BADSEL; - - // map rom to banks 40-7f - sel_t start_sel = map_hirom_offset(li, rom_start_in_file, rom_size - 0x400000, 0x40, 0x400000); - - // map rom to banks c0-ff - map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0xc0, 0); - - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_superfx(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) -{ - // map rom to banks 00-3f (LoROM layout) - sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x00, 0); - - // map rom to banks c0-df (HiROM layout) - map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0xc0, 0); - - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_sa1(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) -{ - // map rom to banks 00-3f (LoROM layout) - sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x00, 0); - - // map rom to banks c0-ff (HiROM layout) - map_hirom_offset(li, rom_start_in_file, rom_size, 0xc0, 0); - - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_sdd1rom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) -{ - // map rom to banks 80-bf (LoROM layout) - sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x80, 0); - - // map rom to banks c0-ff (HiROM layout) - map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0xc0, 0); - - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_lorom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_lorom(li, rom_start_in_file, qmin(rom_size, 0x400000)); - map_lorom_sram(ram_size); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_hirom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_hirom(li, rom_start_in_file, qmin(rom_size, 0x400000)); - map_hirom_sram(ram_size); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_exlorom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - // S-DD1 cartridge should be handled by map_sdd1_cartridge - sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x80, 0); - map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0x40, 0); - map_lorom_sram(ram_size); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_exhirom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_exhirom(li, rom_start_in_file, rom_size); - map_hirom_sram(ram_size); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_superfx_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_superfx(li, rom_start_in_file, rom_size); - map_superfx_sram(ram_size); - map_superfx_workram(); - map_superfx_hwregs(); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_sa1_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_sa1(li, rom_start_in_file, rom_size); - map_sa1_bwram(ram_size); - map_sa1_iram(); - map_sa1_hwregs(); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_cx4_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_lorom(li, rom_start_in_file, qmin(rom_size, 0x400000)); - map_lorom_sram(ram_size); - map_cx4_hwregs(); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_spc7110_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x100000), 0xc0, 0); - // create ram banks 00-3f - map_hirom_sram_offset(ram_size, 0x00); - map_spc7110_hwregs(); - return start_sel; -} - -//---------------------------------------------------------------------------- -static sel_t map_sdd1_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) -{ - sel_t start_sel = map_sdd1rom(li, rom_start_in_file, rom_size); - map_lorom_sram(ram_size); - map_sdd1_hwregs(); - return start_sel; -} - -//---------------------------------------------------------------------------- -static void map_sharprtc() -{ - map_io_seg(0x2800, 0x2802, "sharprtc"); -} - -//---------------------------------------------------------------------------- -static void map_epsonrtc() -{ - map_io_seg(0x4840, 0x4843, "epsonrtc"); -} - -//---------------------------------------------------------------------------- -static void map_obc1() -{ - // TODO: Add OBC-1 registers -} - -//---------------------------------------------------------------------------- -static void map_dsp1(SuperFamicomCartridge::DSP1MemoryMapper /*dsp1_mapper*/) -{ - // TODO: Add DSP-1 registers -} - -//---------------------------------------------------------------------------- -static void map_dsp2() -{ - // TODO: Add DSP-2 registers -} - -//---------------------------------------------------------------------------- -static void map_dsp3() -{ - // TODO: Add DSP-3 registers -} - -//---------------------------------------------------------------------------- -static void map_dsp4() -{ - // TODO: Add DSP-4 registers -} - -//---------------------------------------------------------------------------- -static void map_st010() -{ - // TODO: Add ST-010 registers -} - -//---------------------------------------------------------------------------- -static void map_st011() -{ - // TODO: Add ST-011 registers -} - -//---------------------------------------------------------------------------- -static void map_st018() -{ - // TODO: Add ST-018 registers -} - -//---------------------------------------------------------------------------- -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - SuperFamicomCartridge cartridge(li); - unsigned score = SuperFamicomCartridge::score_header(li, cartridge.header_offset); - - // It is enough to have the first byte of the supposed 'reset vector' match - // one of 6 values, to have a treshold of 8. arm_eep0.bin has such a byte. - // Thus a treshold of 9 (or more) seems in order. Here are some scores: - // - m65816_ffVI.snes: 20 - // - m65816_pacman.snes: 14 - // - m65816_z2ybd.snes: 14 - const int ACCEPTABLE_SCORE_TRESHOLD = 9; - if ( score >= ACCEPTABLE_SCORE_TRESHOLD - && cartridge.type != SuperFamicomCartridge::TypeUnknown ) - { - *fileformatname = "SNES ROM"; - *processor = "m65816"; - return 1; - } - - return 0; -} - -//---------------------------------------------------------------------------- -static void add_interrupt_vector(snes_addr_t &sa, uint16 addr, const char *name, bool make_code) -{ - // Set 'addr' as dword - ea_t real_ea = sa.xlat(addr); - create_word(real_ea, 2); - - ea_t orig_vector_addr = get_word(real_ea); - ea_t vector_addr = sa.xlat(orig_vector_addr); - if ( orig_vector_addr != 0 && orig_vector_addr != 0xffff ) - { - // Set 'vector_addr' name to be 'name' - if ( !has_user_name(get_flags(vector_addr)) ) - set_name(vector_addr, name, SN_NOCHECK); - - // Push the vector_addr into the autoanalysis queue. - // Do not make use of auto_make_proc(), because some - // interrupt handler functions are ``overlaid''. Thus, - // we'd break a procedure w/ inserting another - // procedure right into the previous procedure's code. - if ( make_code ) - auto_make_code(vector_addr); - - // Set 'real_ea' as offset - refinfo_t ri; - ri.init(REF_OFF16, vector_addr - orig_vector_addr); - op_offset_ex(real_ea, OPND_MASK, &ri); - - set_cmt(real_ea, name, false); - } -} - -//---------------------------------------------------------------------------- -void idaapi load_file(linput_t *li, ushort /*neflags*/, const char * /*ffn*/) -{ - // One should always set the processor type - // as early as possible: IDA will draw some - // informations from it; e.g., the size of segments. - // - // Should this instruction be placed after the calls to - // map_mode_2x(), IDA would create 32-bits segments, - // because, until the processor type is specified, IDA - // assumes x86. - set_processor_type("m65816", SETPROC_LOADER); - - SuperFamicomCartridge cartridge(li); - - // Determine whether ROM has a header - int32 start = cartridge.has_copier_header ? 512 : 0; - - // Store information for the cpu module - netnode node; - node.create("$ m65816"); - node.hashset("device", "snes"); - cartridge.write_hash(node); - - snes_addr_t sa; - sa.addr_init(cartridge); - - sel_t start_cs; - - if ( cartridge.has_cx4 ) - { - start_cs = map_cx4_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - } - else if ( cartridge.has_spc7110 ) - { - start_cs = map_spc7110_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - } - else if ( cartridge.has_sdd1 ) - { - start_cs = map_sdd1_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - } - else - { - switch ( cartridge.mapper ) - { - case SuperFamicomCartridge::LoROM: - start_cs = map_lorom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - break; - case SuperFamicomCartridge::HiROM: - start_cs = map_hirom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - break; - case SuperFamicomCartridge::ExLoROM: - start_cs = map_exlorom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - break; - case SuperFamicomCartridge::ExHiROM: - start_cs = map_exhirom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - break; - case SuperFamicomCartridge::SuperFXROM: - start_cs = map_superfx_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - break; - case SuperFamicomCartridge::SA1ROM: - start_cs = map_sa1_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); - break; - default: - loader_failure("Unsupported mapper: %s", cartridge.mapper_string()); - } - } - inf_set_start_cs(start_cs); - - // Hardware registers - map_hwregs(); - - // WRAM - map_wram(); - - if ( cartridge.has_sharprtc ) - map_sharprtc(); - - if ( cartridge.has_epsonrtc ) - map_epsonrtc(); - - if ( cartridge.has_obc1 ) - map_obc1(); - - if ( cartridge.has_dsp1 ) - map_dsp1(cartridge.dsp1_mapper); - - if ( cartridge.has_dsp2 ) - map_dsp2(); - - if ( cartridge.has_dsp3 ) - map_dsp3(); - - if ( cartridge.has_dsp4 ) - map_dsp4(); - - if ( cartridge.has_st010 ) - map_st010(); - - if ( cartridge.has_st011 ) - map_st011(); - - if ( cartridge.has_st018 ) - map_st018(); - - ea_t reset_vector_loc = sa.xlat(0xfffc); - uint16 start_pc = get_word(reset_vector_loc); - ea_t start_address = sa.xlat(start_pc); - inf_set_start_ip(start_address & 0xffff); - - // ------- Most important vectors - // http://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map - add_interrupt_vector(sa, 0xfffc, "Emulation-mode RESET", true); - add_interrupt_vector(sa, 0xffea, "Native-mode NMI", true); - add_interrupt_vector(sa, 0xffee, "Native-mode IRQ", true); - add_interrupt_vector(sa, 0xfffe, "Emulation-mode IRQ", true); - - // ------- Native-mode vectors - add_interrupt_vector(sa, 0xffe4, "Native-mode COP", false); - add_interrupt_vector(sa, 0xffe6, "Native-mode BRK", false); - add_interrupt_vector(sa, 0xffe8, "Native-mode ABORT", false); - add_interrupt_vector(sa, 0xffec, "Native-mode RESET", false); - - // ------- Emulation-mode vectors - add_interrupt_vector(sa, 0xfff4, "Emulation-mode COP", false); - add_interrupt_vector(sa, 0xfff8, "Emulation-mode ABORT", false); - add_interrupt_vector(sa, 0xfffa, "Emulation-mode NMI", false); - - // ------- Undefined vectors - create_word(sa.xlat(0xffe0), 2); - create_word(sa.xlat(0xffe2), 2); - create_word(sa.xlat(0xfff0), 2); - create_word(sa.xlat(0xfff2), 2); - create_word(sa.xlat(0xfff6), 2); - - // Header info - ea_t header = sa.xlat(0xffc0); - set_name(header, "snes_header"); - create_strlit(header, 21, STRTYPE_C); - set_cmt(header, "Game Title", false); - create_byte(header + 0x15, 1); - set_cmt(header + 0x15, "ROM Makeup / ROM Speed and Map Mode", false); - create_byte(header + 0x16, 1); - set_cmt(header + 0x16, "Chipset", false); - create_byte(header + 0x17, 1); - set_cmt(header + 0x17, "ROM Size", false); - create_byte(header + 0x18, 1); - set_cmt(header + 0x18, "RAM Size", false); - create_byte(header + 0x19, 1); - set_cmt(header + 0x19, "Country", false); - create_byte(header + 0x1a, 1); - set_cmt(header + 0x1a, "Developer ID", false); - create_byte(header + 0x1b, 1); - set_cmt(header + 0x1b, "ROM Version", false); - create_word(header + 0x1c, 2); - set_cmt(header + 0x1c, "Checksum Complement", false); - create_word(header + 0x1e, 2); - set_cmt(header + 0x1e, "Checksum", false); -} - -//---------------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - LDRF_RELOAD, - accept_file, - load_file, - NULL, - NULL, - NULL, -}; diff --git a/idasdk75/ldr/w32run/makefile b/idasdk75/ldr/w32run/makefile deleted file mode 100644 index 7c7acfb..0000000 --- a/idasdk75/ldr/w32run/makefile +++ /dev/null @@ -1,14 +0,0 @@ -PROC=w32run - -include ../loader.mak - -# MAKEDEP dependency list ------------------ -$(F)w32run$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ - w32run.cpp w32run.h diff --git a/idasdk75/ldr/w32run/w32run.cpp b/idasdk75/ldr/w32run/w32run.cpp deleted file mode 100644 index e80b8a6..0000000 --- a/idasdk75/ldr/w32run/w32run.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * Watcom DosExtender loader. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -/* - L O A D E R for Watcom W32RUN DOS32-extender -*/ - -#include "../idaldr.h" -#include <exehdr.h> -#include <problems.hpp> -#include "w32run.h" -//lint !e451 header file 'stddef.h' repeatedly included but has no header guard -#include <stddef.h> //offsetof - -//-------------------------------------------------------------------------- -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// -static int idaapi accept_file( - qstring *fileformatname, - qstring *processor, - linput_t *li, - const char *) -{ - union - { - exehdr ex; - w32_hdr wh; - }; - uint32 pos; - - if ( qlread(li, &ex, sizeof(ex)) != sizeof(ex) - || ex.exe_ident != EXE_ID - || (pos = ex.HdrSize) == 0 ) - { - return 0; - } - uint64 fsize = qlsize(li); - qlseek(li, pos *= 16, SEEK_SET); - if ( qlread(li, &wh, sizeof(wh)) != sizeof(wh) ) - return 0; - if ( wh.ident != W32_ID || wh.beg_fileoff < pos+sizeof(wh) -// || ph->memsize >= MAXLOADMEM - || wh.read_size > wh.mem_size - || wh.start_offset >= wh.reltbl_offset - || wh.beg_fileoff > fsize - || wh.read_size > fsize - wh.beg_fileoff - || wh.reltbl_offset > wh.read_size - 2 ) - { - return 0; - } - *fileformatname = "Watcom DOS32-extender file"; - *processor = "metapc"; - return f_W32RUN; -} - -//-------------------------------------------------------------------------- -static w32_hdr wh; -static uint32 minea, topea; -static linput_t *li; - -//------------------------------------------------------------------------- -static int mread(void *buf, size_t size) -{ - if ( qlread(li, buf, size) == size ) - return 0; - if ( ask_yn(ASKBTN_NO, - "HIDECANCEL\n" - "Read error or bad file structure. Continue loading?") <= ASKBTN_NO ) - { - loader_failure(); - } - return 1; -} - -//------------------------------------------------------------------------- -static void realize_relocation(void) -{ - char first = 0; - ushort cnt, tmp; - uint32 offset; - uint32 curv, maxv = 0, ost = wh.read_size - wh.reltbl_offset; - - fixup_data_t fd(FIXUP_OFF32); - - msg("Reading relocation table...\n"); - - for ( ; ; ) - { - if ( ost < sizeof(short) ) - { - first = -1; - break; - } - ost -= sizeof(short); - if ( mread(&cnt, sizeof(cnt)) ) - return; - if ( cnt == 0 ) - break; - if ( ost < sizeof(int32) ) - { - first = -1; - break; - } - ost -= sizeof(int32); - if ( mread(&tmp, sizeof(tmp)) ) - return; - offset = (uint32)tmp << 16; - if ( mread(&tmp, sizeof(tmp)) ) - return; - offset |= tmp; - while ( true ) - { - if ( offset > wh.reltbl_offset - 4 ) - { - if ( !first ) - { - ++first; - warning("Bad value(s) in relocation table!"); - } - } - else - { - uint32 ea = minea + offset; - show_addr(ea); - curv = get_dword(ea); - if ( curv >= wh.mem_size ) - { - msg("Doubtful value after relocation! (%x=>%x)\n", ea, curv + minea); - remember_problem(PR_ATTN, ea); - } - else if ( curv > maxv ) - { - maxv = curv; - } - curv += minea; - put_dword(ea, curv); - fd.off = offset; - fd.sel = curv >= topea ? 2 : 1; - fd.set(ea); - } - if ( --cnt == 0 ) - break; - if ( ost < sizeof(short) ) - { - first = -1; - break; - } - ost -= sizeof(short); - if ( mread(&tmp, sizeof(tmp)) ) - return; - offset += tmp; - } - } - if ( first < 0 ) - warning("Truncated relocation table!"); - if ( !first && ost ) - warning("Information after relocation table!"); - if ( ost == 0 - && !first - && maxv > wh.start_offset - && (maxv += minea) < topea ) - { - set_segm_end(topea, maxv, SEGMOD_KILL); - } -} - -//-------------------------------------------------------------------------- -static void add_all_comments(void) -{ - create_filename_cmt(); - add_pgm_cmt("Full size of allocation memory: %08Xh", wh.mem_size); - add_pgm_cmt("Calling convention for W32RUN\n\n" - " ah - OS type\n" - " ecx - low stack limit\n" - " bx:edx - int 21h interface\n" - " edi - struct {"); - add_pgm_cmt(" char * ModuleFileName;\n" - " char * CommandLine;\n" - " char * Environment;"); - add_pgm_cmt(" char * ExeTrademarkString;\n" - " long SystemDepenced_1;\n" - " long SystemDepenced_2;"); - add_pgm_cmt(" }"); - - set_cmt(inf_get_start_ip(), "Calling convention declared in file header", 1); -} - -//-------------------------------------------------------------------------- -static void create32( - sel_t sel, - ea_t start_ea, - ea_t end_ea, - const char *name, - const char *sclass) -{ - set_selector(sel, 0); - - segment_t s; - s.sel = sel; - s.start_ea = start_ea; - s.end_ea = end_ea; - s.align = saRelByte; - s.comb = scPub; - s.bitness = 1; // 32-bit - - if ( !add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE) ) - loader_failure(); -} - -//-------------------------------------------------------------------------- -// -// load file into the database. -// -void idaapi load_file(linput_t *_li, ushort /*neflag*/, const char * /*fileformatname*/) -{ - ushort pos; - - set_processor_type("metapc", SETPROC_LOADER); - - li = _li; - qlseek(li, offsetof(exehdr, HdrSize)); - lread(li, &pos, sizeof(pos)); - qlseek(li, (uint32)pos * 16); - lread(li, &wh, sizeof(wh)); - - inf_set_baseaddr(0); -// inf.s_prefflag &= ~PREF_SEGADR; -// inf.nametype = NM_EA4; - inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); - minea = (uint32)to_ea(W32_DOS_LOAD_BASE, 0); - inf_set_start_ip(minea + wh.start_offset); - inf_set_start_cs(1); //selector of code - topea = minea + wh.reltbl_offset; - uint64 fsize = qlsize(li); - if ( wh.beg_fileoff > fsize || topea-minea > fsize-wh.beg_fileoff ) - loader_failure("Corrupted file"); - file2base(li, wh.beg_fileoff, minea, topea, FILEREG_PATCHABLE); - create32(1, minea, topea, NAME_CODE, CLASS_CODE); - create32(2, topea, minea+wh.mem_size, NAME_BSS, CLASS_BSS); - set_default_dataseg(1); - realize_relocation(); - add_all_comments(); -} - -//---------------------------------------------------------------------- -// -// LOADER DESCRIPTION BLOCK -// -//---------------------------------------------------------------------- -loader_t LDSC = -{ - IDP_INTERFACE_VERSION, - 0, // loader flags -// -// check input file format. if recognized, then return 1 -// and fill 'fileformatname'. -// otherwise return 0 -// - accept_file, -// -// load file into the database. -// - load_file, -// -// create output file from the database. -// this function may be absent. -// - NULL, -// take care of a moved segment (fix up relocations, for example) - NULL, - NULL, -}; diff --git a/idasdk75/lib/x64_linux_gcc_32/libida.so b/idasdk75/lib/x64_linux_gcc_32/libida.so deleted file mode 100644 index 4b171f4..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_32/libida.so and /dev/null differ diff --git a/idasdk75/lib/x64_linux_gcc_32/network.a b/idasdk75/lib/x64_linux_gcc_32/network.a deleted file mode 100644 index f7277d9..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_32/network.a and /dev/null differ diff --git a/idasdk75/lib/x64_linux_gcc_64/compress.a b/idasdk75/lib/x64_linux_gcc_64/compress.a deleted file mode 100644 index 8b39f5b..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_64/compress.a and /dev/null differ diff --git a/idasdk75/lib/x64_linux_gcc_64/dumb.o b/idasdk75/lib/x64_linux_gcc_64/dumb.o deleted file mode 100644 index b3ec1b9..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_64/dumb.o and /dev/null differ diff --git a/idasdk75/lib/x64_linux_gcc_64/libida64.so b/idasdk75/lib/x64_linux_gcc_64/libida64.so deleted file mode 100644 index 2d1c2a7..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_64/libida64.so and /dev/null differ diff --git a/idasdk75/lib/x64_linux_gcc_64/network.a b/idasdk75/lib/x64_linux_gcc_64/network.a deleted file mode 100644 index 9351b4c..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_64/network.a and /dev/null differ diff --git a/idasdk75/lib/x64_linux_gcc_64/pro.a b/idasdk75/lib/x64_linux_gcc_64/pro.a deleted file mode 100644 index 05b8586..0000000 Binary files a/idasdk75/lib/x64_linux_gcc_64/pro.a and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_32/libida.dylib b/idasdk75/lib/x64_mac_clang_32/libida.dylib deleted file mode 100644 index 9d84ca0..0000000 Binary files a/idasdk75/lib/x64_mac_clang_32/libida.dylib and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_32/network.a b/idasdk75/lib/x64_mac_clang_32/network.a deleted file mode 100644 index 79fa61c..0000000 Binary files a/idasdk75/lib/x64_mac_clang_32/network.a and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_64/compress.a b/idasdk75/lib/x64_mac_clang_64/compress.a deleted file mode 100644 index e1a70ef..0000000 Binary files a/idasdk75/lib/x64_mac_clang_64/compress.a and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_64/dumb.o b/idasdk75/lib/x64_mac_clang_64/dumb.o deleted file mode 100644 index 7f82ac8..0000000 Binary files a/idasdk75/lib/x64_mac_clang_64/dumb.o and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_64/libida64.dylib b/idasdk75/lib/x64_mac_clang_64/libida64.dylib deleted file mode 100644 index 75b8b78..0000000 Binary files a/idasdk75/lib/x64_mac_clang_64/libida64.dylib and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_64/network.a b/idasdk75/lib/x64_mac_clang_64/network.a deleted file mode 100644 index ffa9ecd..0000000 Binary files a/idasdk75/lib/x64_mac_clang_64/network.a and /dev/null differ diff --git a/idasdk75/lib/x64_mac_clang_64/pro.a b/idasdk75/lib/x64_mac_clang_64/pro.a deleted file mode 100644 index 360b76c..0000000 Binary files a/idasdk75/lib/x64_mac_clang_64/pro.a and /dev/null differ diff --git a/idasdk75/lib/x86_linux_gcc_32/compress.a b/idasdk75/lib/x86_linux_gcc_32/compress.a deleted file mode 100644 index 57dc2af..0000000 Binary files a/idasdk75/lib/x86_linux_gcc_32/compress.a and /dev/null differ diff --git a/idasdk75/lib/x86_linux_gcc_32/dumb.o b/idasdk75/lib/x86_linux_gcc_32/dumb.o deleted file mode 100644 index 0dcee6f..0000000 Binary files a/idasdk75/lib/x86_linux_gcc_32/dumb.o and /dev/null differ diff --git a/idasdk75/lib/x86_linux_gcc_32/network.a b/idasdk75/lib/x86_linux_gcc_32/network.a deleted file mode 100644 index a07603f..0000000 Binary files a/idasdk75/lib/x86_linux_gcc_32/network.a and /dev/null differ diff --git a/idasdk75/lib/x86_linux_gcc_32/pro.a b/idasdk75/lib/x86_linux_gcc_32/pro.a deleted file mode 100644 index b1ef28d..0000000 Binary files a/idasdk75/lib/x86_linux_gcc_32/pro.a and /dev/null differ diff --git a/idasdk75/lib/x86_mac_clang_32/compress.a b/idasdk75/lib/x86_mac_clang_32/compress.a deleted file mode 100644 index 4188c26..0000000 Binary files a/idasdk75/lib/x86_mac_clang_32/compress.a and /dev/null differ diff --git a/idasdk75/lib/x86_mac_clang_32/dumb.o b/idasdk75/lib/x86_mac_clang_32/dumb.o deleted file mode 100644 index 7851eb6..0000000 Binary files a/idasdk75/lib/x86_mac_clang_32/dumb.o and /dev/null differ diff --git a/idasdk75/lib/x86_mac_clang_32/network.a b/idasdk75/lib/x86_mac_clang_32/network.a deleted file mode 100644 index d520383..0000000 Binary files a/idasdk75/lib/x86_mac_clang_32/network.a and /dev/null differ diff --git a/idasdk75/lib/x86_mac_clang_32/pro.a b/idasdk75/lib/x86_mac_clang_32/pro.a deleted file mode 100644 index 6417798..0000000 Binary files a/idasdk75/lib/x86_mac_clang_32/pro.a and /dev/null differ diff --git a/idasdk75/makeenv_vc.mak b/idasdk75/makeenv_vc.mak deleted file mode 100644 index 0238524..0000000 --- a/idasdk75/makeenv_vc.mak +++ /dev/null @@ -1,288 +0,0 @@ - -# Create configuration files - -include allmake.mak - -define CFG0 # Common flags -/I$(shell cygpath -am $(IDA)include) -/DMAXSTR=1024 -/DNO_TV_STREAMS -/D__NT__ -# Directory for PDB files -/Fd$(F) -endef - -############################################################################ -# Visual Studio for Intel -define CFG1 -# Merge duplicate strings -/GF -# Exception handling (try/catch can handle only C++ exceptions; use __except for SEH) -/EHs -# Separate functions for linker -/Gy -# show full paths -/FC -# All warnings on -/Wall -# warning C4018: >= : signed/unsigned mismatch -/wd4018 -# warning C4061: enumerator xxx in switch of enum yyy is not explicitly handled by a case label -/wd4061 -# warning C4121: xxx: alignment of a member was sensitive to packing -/wd4121 -# warning C4127: conditional expression is constant -/wd4127 -# warning C4146: unary minus operator applied to unsigned type, result still unsigned -/wd4146 -# warning C4200: nonstandard extension used: zero-sized array in struct/union -/wd4200 -# warning C4201: nonstandard extension used : nameless struct/union -/wd4201 -# warning C4239: nonstandard extension used : non-const refernece=>lvalue -/wd4239 -# warning C4242: initializing : conversion from a to b, possible loss of data -/wd4242 -# warning C4244: xxx : conversion from a to b, possible loss of data -/wd4244 -# warning C4245: xxx : conversion from a to b, signed/unsigned mismatch -/wd4245 -# warning C4267: xxx : conversion from size_t to b, possible loss of data -/wd4267 -# warning C4310: cast truncates constant value -/wd4310 -# warning C4324: xxx : structure was padded due to __declspec(align()) -/wd4324 -# warning C4350: behavior change: '' called instead of '' -# for some reason vc11 started to complain about it and i do not see -# how to shut it up -/wd4350 -# warning C4355: this : used in base member initializer list -/wd4355 -# warning C4365: xx : signed/unsigned mismatch (= or return) -/wd4365 -endef -define CFG1a -# warning C4366: The result of the unary & operator may be unaligned -/wd4366 -# warning C4371: xxx : layout of class may have changed from a previous version of the compiler due to better packing of member xxx -/wd4371 -# warning C4388: != : signed/unsigned mismatch -/wd4388 -# warning C4389: != : signed/unsigned mismatch -/wd4389 -# warning C4458: declaration of '' hides class member -/wd4458 -# warning C4480: != : nonstandard extension used: .... -/wd4480 -# warning C4512: xxx : assignment operator could not be generated -/wd4512 -# warning C4514: xxx : unreferenced inline function has been removed -/wd4514 -# warning C4548: expression before comma has no effect; expected expression with side-effect -/wd4548 -# warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught -/wd4571 -# warning C4574: yvals.h(vc10): '_SECURE_SCL' is defined to be '0': did you mean to use '#if _SECURE_SCL'? -# warning C4574: ws2tcpicp.h(vc14): 'INCL_WINSOCK_API_TYPEDEFS' is defined to be '0': did you mean to use '#if INCL_WINSOCK_API_TYPEDEFS'? -/wd4574 -# warning C4611: interaction between _setjmp and C++ object destruction is non-portable -/wd4611 -# warning C4619: pragma warning : there is no warning number xxx -/wd4619 -# warning C4623: xxx : default constructor was implicitly defined as deleted -/wd4623 -# warning C4625: xxx : copy constructor could not be generated because a base class copy constructor is inaccessible -/wd4625 -# warning C4626: xxx : assignment operator could not be generated because a base class assignment operator is inaccessible -/wd4626 -# warning C4640: p : construction of local static object is not thread-safe -/wd4640 -# warning C4668: xxx is not defined as a preprocessor macro, replacing with 0 for #if/#elif -/wd4668 -# warning C4686: xxx : possible change in behavior, change in UDT return calling convention -/wd4686 -# warning C4701: xxx : potentially uninitialized local variable -/wd4701 -# warning C4710: xxx : function not inlined -/wd4710 -# warning C4711: xxx : function select for automatic inline expansion -/wd4711 -# warning C4738: storing 32-bit float result in memory, possible loss of performance -/wd4738 -# warning C4820: xxx : x bytes padding added after member xxx -/wd4820 -# warning C4917: xxx : a GUID can only be associated with a class, interface or namespace -/wd4917 -# warning C4986: operator new[]: exception specification does not match previous declaration entered the game. -/wd4986 -# warning C4987: setjmp.h(vc10) nonstandard extension used: throw(...) -/wd4987 -# -# treat as errors: -# warning C4541: 'dynamic_cast' used on polymorphic type 'xxx' with /GR-; unpredictable behavior may result -/we4541 -# warning C4715: 'function' : not all control paths return a value -/we4715 -# warning C4296: '' : expression is always false -/we4296 -# warning C4315: 'class' : 'this' pointer for member 'class::member' may not be aligned 8 as expected by the constructor -/we4315 -# warning C4805: 'operation' : unsafe mix of type 'type' and type 'type' in operation -/we4805 -# -endef - -define CFG2 -# Separate data for linker -/Gw -# warning C4091: 'typedef ': ignored on left of '' when no variable is declared -# skd.../um/dbghelp/h -/wd4091 -# warning C4435: Object layout under /vd2 will change due to virtual base '' -/wd4435 -# warning C4456: declaration of '' hides previous local declaration -/wd4456 -# warning C4457: declaration of '' hides function parameter -/wd4457 -# warning C4459: declaration of '' hides global declaration -/wd4459 -# warning C4464: relative include path contains '..' -/wd4464 -# warning C4774: '' : format string expected in argument 1 is not a string literal -# this warning cannot handle cnd ? "fmt1" : "fmt2" while gcc can -/wd4774 -# warning C4589: Constructor of abstract class '' ignores initializer for virtual base class -# completely wrong warning -/wd4589 -# warning C5025: move assignment operator was implicitly defined as deleted -/wd5025 -# warning C5026: move constructor was implicitly defined as deleted because a base class move constructor is inaccessible or deleted -/wd5026 -# warning C5027: move assignment operator was implicitly defined as deleted because a base class move assignment operator is inaccessible or deleted -/wd5027 -# warning C5039: '': pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception. -/wd5039 -# warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified -/wd5045 -# warning C6323: Use of arithmetic operator on Boolean type(s). -/wd6323 -# warning C5038: data member '' will be initialized after data member '' -/wd5038 -# warning C6340: Mismatch on sign: '' passed as '' when some signed type is required in call to '' -/wd6340 -endef - -ifdef NDEBUG # Optimization flags -define CFG3 -/DNDEBUG -# Do not use checked iterators -/D_SECURE_SCL=0 -# Maximum optimization -/Ox -# Enable intrinsic functions -/Oi -endef -else # Debug flags -define CFG3 -/D_DEBUG -# Enable security checks -/GS -# Disable optimizations -/Od -endef -endif - -ifdef USE_VS15 - VSCFG = vs15paths.cfg -else - ifdef __XPCOMPAT__ - VSCFG = vs17paths_xp.cfg - else - VSCFG = vs17paths.cfg - endif -endif - -all: $(SYSDIR).cfg $(VSCFG) -$(SYSDIR).cfg: makeenv_vc.mak allmake.mak defaults.mk makefile - @echo -e '$(subst $(newline),\n,${CFG0})' | grep -v '^#' >$@ - @echo -e '$(subst $(newline),\n,${CFG1})' | grep -v '^#' >>$@ - @echo -e '$(subst $(newline),\n,${CFG1a})'| grep -v '^#' >>$@ - @echo -e '$(subst $(newline),\n,${CFG2})' | grep -v '^#' >>$@ - @echo -e '$(subst $(newline),\n,${CFG3})' | grep -v '^#' >>$@ -ifdef __EA64__ - @echo /D__EA64__ >>$@ -endif -ifdef __X86__ - @echo /D__X86__ >>$@ -endif -ifdef USE_STATIC_RUNTIME - @echo /D__NOEXPORT__ >>$@ -endif -ifdef __XPCOMPAT__ - @echo /D_USING_V110_SDK71_ >>$@ - @echo /Zc:threadSafeInit- >>$@ -endif - -# these cfg files speed up the build process by caching compiler/sdk paths. -# this allows the build system to avoid calling cygpath multiple times on every run. - -define VS15PATHS_CFG -export MSVC_PATH = $(MSVC_PATH) -export MSVC_INCLUDE = $(MSVC_INCLUDE) -export MSVC_BIN-X86 = $(MSVC_BIN-X86) -export MSVC_BIN-X64 = $(MSVC_BIN-X64) -export WSDK_PATH = $(WSDK_PATH) -export WSDK_VER = $(WSDK_VER) -export INCLUDE_UCRT_PATH = $(INCLUDE_UCRT_PATH) -export LIB_UCRT_PATH = $(LIB_UCRT_PATH) -export INCLUDE_UCRT = $(INCLUDE_UCRT) -export LIB_UCRT = $(LIB_UCRT) -endef -vs15paths.cfg: - @echo -e '$(subst $(newline),\n,$(VS15PATHS_CFG))' >$@ - -define VS17PATHS_CFG -export MSVC_ROOT = $(MSVC_ROOT) -export MSVC_TOOLSVER = $(MSVC_TOOLSVER) -export MSVC_PATH = $(MSVC_PATH) -export MSVC_INCLUDE = $(MSVC_INCLUDE) -export MSVC_BIN-X86 = $(MSVC_BIN-X86) -export MSVC_BIN-X64 = $(MSVC_BIN-X64) -export WSDK_PATH = $(WSDK_PATH) -export WSDK_VER = $(WSDK_VER) -export INCLUDE_UCRT_PATH = $(INCLUDE_UCRT_PATH) -export LIB_UCRT_PATH = $(LIB_UCRT_PATH) -export INCLUDE_UCRT = $(INCLUDE_UCRT) -export LIB_UCRT = $(LIB_UCRT) -export INCLUDE_SHARED_PATH = $(INCLUDE_SHARED_PATH) -export INCLUDE_UM_PATH = $(INCLUDE_UM_PATH) -export LIB_UM_PATH = $(LIB_UM_PATH) -export SDK_BIN_PATH = $(SDK_BIN_PATH) -export INCLUDE_SHARED = $(INCLUDE_SHARED) -export INCLUDE_UM = $(INCLUDE_UM) -export LIB_UM = $(LIB_UM) -export SDK_BIN = $(SDK_BIN) -endef -vs17paths.cfg: - @echo -e '$(subst $(newline),\n,$(VS17PATHS_CFG))' >$@ - -define VS17PATHS_XP_CFG -export MSVC_ROOT = $(MSVC_ROOT) -export MSVC_TOOLSVER = $(MSVC_TOOLSVER) -export MSVC_PATH = $(MSVC_PATH) -export MSVC_INCLUDE = $(MSVC_INCLUDE) -export MSVC_BIN-X86 = $(MSVC_BIN-X86) -export MSVC_BIN-X64 = $(MSVC_BIN-X64) -export WSDK_PATH = $(WSDK_PATH) -export WSDK_VER = $(WSDK_VER) -export INCLUDE_UCRT_PATH = $(INCLUDE_UCRT_PATH) -export LIB_UCRT_PATH = $(LIB_UCRT_PATH) -export INCLUDE_UCRT = $(INCLUDE_UCRT) -export LIB_UCRT = $(LIB_UCRT) -export INCLUDE_MSSDK71 = $(INCLUDE_MSSDK71) -export LIB_MSSDK71 = $(LIB_MSSDK71) -export SDK_BIN = $(SDK_BIN) -endef -vs17paths_xp.cfg: - @echo -e '$(subst $(newline),\n,$(VS17PATHS_XP_CFG))' >$@ diff --git a/idasdk75/module.mak b/idasdk75/module.mak deleted file mode 100644 index 5875282..0000000 --- a/idasdk75/module.mak +++ /dev/null @@ -1,86 +0,0 @@ - -# This file is included by: -# - ldr/loader.mak -# - module/module.mak -# - plugins/plugin.mak - -ifdef __LINT__ - # Info 785 Too few initializers for aggregate - CFLAGS += -e785 -endif - -#---------------------------------------------------------------------- -# include allmake.mak and prepare default goal if needed -ifndef NO_DEFAULT_TARGETS - include ../../allmake.mak - - # prepare targets - GOALS += modules - GOALS += $(addprefix $(RI),$(IDCS)) - GOALS += configs - all: $(GOALS) - - # create default target and add it to the list of targets - ifdef BUILD_STATIC_LIBRARY - DEFAULT_TARGET = $(L)$(PROC)$(A) - STATIC_LIBS += $(DEFAULT_TARGET) - else - DEFAULT_TARGET = $(call module_dll,$(PROC)) - MODULES += $(DEFAULT_TARGET) - endif - - # create lists of object files for default target (shared or static) - OBJS += $(BASE_OBJS) - OBJS += $(call objs,$(foreach n,1 2 3 4 5 6 7 8 9,$(O$(n)))) - $(DEFAULT_TARGET): MODULE_OBJS += $(OBJS) - # object file dependencies must be explicitly added to each module - $(DEFAULT_TARGET): $(OBJS) -endif - -#---------------------------------------------------------------------- -# prepare ldflags for all modules -MODULE_LDFLAGS += $(OUTMAP)$(F)$(@F).map -ifdef __LINUX__ - DEFFILE ?= $(SRC_PATH)exports.def - MODULE_LDFLAGS += -Wl,--version-script=$(DEFFILE) -else ifdef __MAC__ - INSTALL_NAME ?= $(@F) - MODULE_LDFLAGS += -Wl,-install_name,$(INSTALL_NAME) -endif - -#---------------------------------------------------------------------- -# main rule for modules -.PHONY: modules -modules: $(MODULES) $(STATIC_LIBS) - -# shared libraries -$(MODULES): LDFLAGS += $(MODULE_LDFLAGS) -$(MODULES): $(LIBS) $(IDALIB) $(MAKEFILE_DEP) $(DEFFILE) - $(call link_dll, $(MODULE_OBJS), $(LIBS) $(LINKIDA)) -ifdef __NT__ - ifndef DONT_ERASE_LIB - $(Q)$(RM) $(@:$(DLLEXT)=.exp) $(@:$(DLLEXT)=.lib) - endif -endif - $(CHECKSYMS_CMD) - $(POSTACTION) - -# static libraries -$(STATIC_LIBS): $(call lib, $(MODULE_OBJS)) - -#---------------------------------------------------------------------- -# auxiliary rules -CFG_CONFIGS = $(addprefix $(C),$(CONFIGS)) -configs: $(CFG_CONFIGS) - -$(RI)%.idc: %.idc - $(CP) $? $@ - -#---------------------------------------------------------------------- -# removes installed binaries from the $(BIN_PATH)/ directory -.PHONY: uninstall -uninstall:: - rm -rf $(MODULES) $(STATIC_LIBS) - -#---------------------------------------------------------------------- -include $(IDA)objdir.mak diff --git a/idasdk75/module/6502/ana.cpp b/idasdk75/module/6502/ana.cpp deleted file mode 100644 index d813ebc..0000000 --- a/idasdk75/module/6502/ana.cpp +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "m65.hpp" - -static const uchar nmos[256] = -{ -// 0 1 2 3 4 5 6 7 8 9 A B C D E F -/* 00 */ M65_brk, M65_ora, M65_null,M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, M65_php, M65_ora, M65_asl, M65_anc, M65_nop, M65_ora, M65_asl, M65_slo, /* 00 */ -/* 10 */ M65_bpl, M65_ora, M65_null,M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, M65_clc, M65_ora, M65_nop, M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, /* 10 */ -/* 20 */ M65_jsr, M65_and, M65_null,M65_rla, M65_bit, M65_and, M65_rol, M65_rla, M65_plp, M65_and, M65_rol, M65_anc, M65_bit, M65_and, M65_rol, M65_rla, /* 20 */ -/* 30 */ M65_bmi, M65_and, M65_null,M65_rla, M65_nop, M65_and, M65_rol, M65_rla, M65_sec, M65_and, M65_nop, M65_rla, M65_nop, M65_and, M65_rol, M65_rla, /* 30 */ -/* 40 */ M65_rti, M65_eor, M65_null,M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, M65_pha, M65_eor, M65_lsr, M65_asr, M65_jmp, M65_eor, M65_lsr, M65_sre, /* 40 */ -/* 50 */ M65_bvc, M65_eor, M65_null,M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, M65_cli, M65_eor, M65_nop, M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, /* 50 */ -/* 60 */ M65_rts, M65_adc, M65_null,M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, M65_pla, M65_adc, M65_ror, M65_arr, M65_jmpi,M65_adc, M65_ror, M65_rra, /* 60 */ -/* 70 */ M65_bvs, M65_adc, M65_null,M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, M65_sei, M65_adc, M65_nop, M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, /* 70 */ -/* 80 */ M65_nop, M65_sta, M65_nop, M65_sax, M65_sty, M65_sta, M65_stx, M65_sax, M65_dey, M65_nop, M65_txa, M65_ane, M65_sty, M65_sta, M65_stx, M65_sax, /* 80 */ -/* 90 */ M65_bcc, M65_sta, M65_null,M65_sha, M65_sty, M65_sta, M65_stx, M65_sax, M65_tya, M65_sta, M65_txs, M65_shs, M65_shy, M65_sta, M65_shx, M65_sha, /* 90 */ -/* A0 */ M65_ldy, M65_lda, M65_ldx, M65_lax, M65_ldy, M65_lda, M65_ldx, M65_lax, M65_tay, M65_lda, M65_tax, M65_lxa, M65_ldy, M65_lda, M65_ldx, M65_lax, /* A0 */ -/* B0 */ M65_bcs, M65_lda, M65_null,M65_lax, M65_ldy, M65_lda, M65_ldx, M65_lax, M65_clv, M65_lda, M65_tsx, M65_lae, M65_ldy, M65_lda, M65_ldx, M65_lax, /* B0 */ -/* C0 */ M65_cpy, M65_cmp, M65_nop, M65_dcp, M65_cpy, M65_cmp, M65_dec, M65_dcp, M65_iny, M65_cmp, M65_dex, M65_sbx, M65_cpy, M65_cmp, M65_dec, M65_dcp, /* C0 */ -/* D0 */ M65_bne, M65_cmp, M65_null,M65_dcp, M65_nop, M65_cmp, M65_dec, M65_dcp, M65_cld, M65_cmp, M65_nop, M65_dcp, M65_nop, M65_cmp, M65_dec, M65_dcp, /* D0 */ -/* E0 */ M65_cpx, M65_sbc, M65_nop, M65_isb, M65_cpx, M65_sbc, M65_inc, M65_isb, M65_inx, M65_sbc, M65_nop, M65_sbc, M65_cpx, M65_sbc, M65_inc, M65_isb, /* E0 */ -/* F0 */ M65_beq, M65_sbc, M65_null,M65_isb, M65_nop, M65_sbc, M65_inc, M65_isb, M65_sed, M65_sbc, M65_nop, M65_isb, M65_nop, M65_sbc, M65_inc, M65_isb /* F0 */ -}; - -static const uchar cmos[256] = -{ -// 0 1 2 3 4 5 6 7 8 9 A B C D E F -/* 00 */ M65_brk, M65_ora, M65_null,M65_null,M65_tsb, M65_ora, M65_asl, M65_rmb0,M65_php, M65_ora, M65_asl, M65_null,M65_tsb, M65_ora, M65_asl, M65_bbr0, /* 00 */ -/* 10 */ M65_bpl, M65_ora, M65_ora, M65_null,M65_trb, M65_ora, M65_asl, M65_rmb1,M65_clc, M65_ora, M65_inc, M65_null,M65_trb, M65_ora, M65_asl, M65_bbr1, /* 10 */ -/* 20 */ M65_jsr, M65_and, M65_null,M65_null,M65_bit, M65_and, M65_rol, M65_rmb2,M65_plp, M65_and, M65_rol, M65_null,M65_bit, M65_and, M65_rol, M65_bbr2, /* 20 */ -/* 30 */ M65_bmi, M65_and, M65_and, M65_null,M65_bit, M65_and, M65_rol, M65_rmb3,M65_sec, M65_and, M65_dec, M65_null,M65_bit, M65_and, M65_rol, M65_bbr3, /* 30 */ -/* 40 */ M65_rti, M65_eor, M65_null,M65_null,M65_null,M65_eor, M65_lsr, M65_rmb4,M65_pha, M65_eor, M65_lsr, M65_null,M65_jmp, M65_eor, M65_lsr, M65_bbr4, /* 40 */ -/* 50 */ M65_bvc, M65_eor, M65_eor, M65_null,M65_null,M65_eor, M65_lsr, M65_rmb5,M65_cli, M65_eor, M65_phy, M65_null,M65_null,M65_eor, M65_lsr, M65_bbr5, /* 50 */ -/* 60 */ M65_rts, M65_adc, M65_null,M65_null,M65_stz, M65_adc, M65_ror, M65_rmb6,M65_pla, M65_adc, M65_ror, M65_null,M65_jmpi,M65_adc, M65_ror, M65_bbr6, /* 60 */ -/* 70 */ M65_bvs, M65_adc, M65_adc, M65_null,M65_stz, M65_adc, M65_ror, M65_rmb7,M65_sei, M65_adc, M65_ply, M65_null,M65_jmpi,M65_adc, M65_ror, M65_bbr7, /* 70 */ -/* 80 */ M65_bra, M65_sta, M65_null,M65_null,M65_sty, M65_sta, M65_stx, M65_smb0,M65_dey, M65_bit, M65_txa, M65_null,M65_sty, M65_sta, M65_stx, M65_bbs0, /* 80 */ -/* 90 */ M65_bcc, M65_sta, M65_sta, M65_null,M65_sty, M65_sta, M65_stx, M65_smb1,M65_tya, M65_sta, M65_txs, M65_null,M65_stz, M65_sta, M65_stz, M65_bbs1, /* 90 */ -/* A0 */ M65_ldy, M65_lda, M65_ldx, M65_null,M65_ldy, M65_lda, M65_ldx, M65_smb2,M65_tay, M65_lda, M65_tax, M65_null,M65_ldy, M65_lda, M65_ldx, M65_bbs2, /* A0 */ -/* B0 */ M65_bcs, M65_lda, M65_lda, M65_null,M65_ldy, M65_lda, M65_ldx, M65_smb3,M65_clv, M65_lda, M65_tsx, M65_null,M65_ldy, M65_lda, M65_ldx, M65_bbs3, /* B0 */ -/* C0 */ M65_cpy, M65_cmp, M65_null,M65_null,M65_cpy, M65_cmp, M65_dec, M65_smb4,M65_iny, M65_cmp, M65_dex, M65_null,M65_cpy, M65_cmp, M65_dec, M65_bbs4, /* C0 */ -/* D0 */ M65_bne, M65_cmp, M65_cmp, M65_null,M65_null,M65_cmp, M65_dec, M65_smb5,M65_cld, M65_cmp, M65_phx, M65_null,M65_null,M65_cmp, M65_dec, M65_bbs5, /* D0 */ -/* E0 */ M65_cpx, M65_sbc, M65_null,M65_null,M65_cpx, M65_sbc, M65_inc, M65_smb6,M65_inx, M65_sbc, M65_nop, M65_null,M65_cpx, M65_sbc, M65_inc, M65_bbs6, /* E0 */ -/* F0 */ M65_beq, M65_sbc, M65_sbc, M65_null,M65_null,M65_sbc, M65_inc, M65_smb7,M65_sed, M65_sbc, M65_plx, M65_null,M65_null,M65_sbc, M65_inc, M65_bbs7 /* F0 */ -// 0 1 2 3 4 5 6 7 8 9 A B C D E F -}; - -//---------------------------------------------------------------------- -int m6502_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - insn.Op1.dtype = dt_byte; - uchar code = insn.get_next_byte(); - insn.itype = (is_cmos ? cmos : nmos)[code]; - if ( insn.itype == M65_null ) - return 0; - - switch ( code & 0x1F ) - { -// +08 PHP PLP PHA PLA DEY TAY INY INX Implied -// +18 CLC SEC CLI SEI TYA CLV CLD SED Implied -// +1a NOP* NOP* NOP* NOP* TXS TSX NOP* NOP* Implied -// +1a inc dec phy ply txs tsx phx ply - case 0x1A: - case 0x08: - case 0x18: - switch ( insn.itype ) - { - case M65_inc: - case M65_dec: - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - } - break; -// +0a ASL ROL LSR ROR TXA TAX DEX NOP Accu/impl - case 0x0A: - switch ( insn.itype ) - { - case M65_asl: - case M65_rol: - case M65_lsr: - case M65_ror: - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - } - break; -// +00 BRK JSR RTI RTS NOP*/bra LDY CPY CPX Impl/immed -// +02 t t t t NOP*t LDX NOP*t NOP*t ? /immed -// +09 ORA AND EOR ADC NOP* LDA CMP SBC Immediate -// +0b ANC** ANC** ASR** ARR** ANE** LXA** SBX** SBC* Immediate - case 0x00: - case 0x02: - case 0x09: - case 0x0B: - switch ( insn.itype ) - { - case M65_jsr: - insn.Op1.dtype = dt_code; - insn.Op1.type = o_near; - insn.Op1.addr = insn.get_next_word(); - break; - case M65_brk: - case M65_rti: - case M65_rts: - break; - case M65_bra: - goto M65_RELATIVE; - default: - insn.Op1.type = o_imm; - insn.Op1.value = insn.get_next_byte(); - break; - } - break; -// +0c NOP*/tsb BIT JMP JMP () STY LDY CPY CPX Absolute -// +0d ORA AND EOR ADC STA LDA CMP SBC Absolute -// +0e ASL ROL LSR ROR STX LDX DEC INC Absolute -// +0f SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Absolute -// +0f bbr0 bbr2 bbr4 bbr6 bbs0 bbs2 bbs4 bbs6 Zero page relative - case 0x0F: - if ( is_cmos ) - goto ZP_RELATIVE; - case 0x0C: - case 0x0D: - case 0x0E: -M65_ABSOLUTE: - switch ( insn.itype ) - { - case M65_jmp: - insn.Op1.dtype = dt_code; - insn.Op1.type = o_near; - break; - case M65_jmpi: - insn.Op1.dtype = dt_word; - insn.indirect = 1; - /* no break */ - default: - insn.Op1.type = o_mem; - break; - } - insn.Op1.addr = insn.get_next_word(); - break; -// +1c NOP*/trb NOP*/bit NOP* NOP*/jmp SHY**/stz LDY NOP* NOP* Absolute, x -// +1d ORA AND EOR ADC STA LDA CMP SBC Absolute, x -// +1e ASL ROL LSR ROR SHX**y) LDX y) DEC INC Absolute, x -// +1f SLO* RLA* SRE* RRA* SHA**y) LAX* y) DCP ISB Absolute, x -// +0f bbr1 bbr3 bbr5 bbr7 bbs1 bbs3 bbs5 bbs7 Zero page relative - case 0x1F: - if ( is_cmos ) - { -ZP_RELATIVE: - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - insn.Op2.dtype = dt_code; - insn.Op2.type = o_near; - char x = insn.get_next_byte(); - insn.Op2.addr = insn.ip + insn.size + x; - break; - } - /* fall thru */ - case 0x1C: - case 0x1D: - case 0x1E: - insn.Op1.type = o_displ; - insn.Op1.phrase = rX; - switch ( insn.itype ) - { - case M65_stz: - if ( code == 0x9E ) - break; - // no break - case M65_trb: - goto M65_ABSOLUTE; - case M65_shx: - case M65_sha: - case M65_ldx: - case M65_lax: - insn.Op1.phrase = rY; - break; - case M65_jmpi: - insn.Op1.phrase = riX; - break; - } - insn.Op1.addr = insn.get_next_word(); - break; -// +19 ORA AND EOR ADC STA LDA CMP SBC Absolute, y -// +1b SLO* RLA* SRE* RRA* SHS** LAS** DCP* ISB* Absolute, y - case 0x19: - case 0x1B: - insn.Op1.type = o_displ; - insn.Op1.phrase = rY; - insn.Op1.addr = insn.get_next_word(); - break; -// +10 BPL BMI BVC BVS BCC BCS BNE BEQ Relative - case 0x10: -M65_RELATIVE: - insn.Op1.dtype = dt_code; - insn.Op1.type = o_near; - { - char x = insn.get_next_byte(); - insn.Op1.addr = insn.ip + insn.size + x; - } - break; -// +01 ORA AND EOR ADC STA LDA CMP SBC (indir, x) -// +03 SLO* RLA* SRE* RRA* SAX* LAX* y) DCP* ISB* (indir, x) - case 0x01: - case 0x03: - insn.Op1.type = o_displ; - insn.Op1.phrase = uint16((insn.itype == M65_lax) ? riY : riX); - insn.Op1.addr = insn.get_next_byte(); // what about LAX? - break; -// +11 ORA AND EOR ADC STA LDA CMP SBC (indir), y -// +13 SLO* RLA* SRE* RRA* SHA** LAX* DCP* ISB* (indir), y - case 0x11: - case 0x13: - insn.Op1.type = o_displ; - insn.Op1.phrase = riY; - insn.Op1.addr = insn.get_next_byte(); - break; -// +04 NOP*/tsb BIT NOP* NOP*/stz STY LDY CPY CPX Zeropage -// +05 ORA AND EOR ADC STA LDA CMP SBC Zeropage -// +06 ASL ROL LSR ROR STX LDX DEC INC Zeropage -// +07 SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Zeropage -// +07 rmb0 rmb2 rmb4 rmb6 smb0 smb2 smb4 smb6 Zeropage - case 0x04: - case 0x05: - case 0x06: - case 0x07: -ZEROPAGE: - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - break; -// +14 NOP*/trb NOP*/bit NOP* NOP*/stz STY LDY NOP* NOP* Zeropage, x -// +15 ORA AND EOR ADC STA LDA CMP SBC Zeropage, x -// +16 ASL ROL LSR ROR STX y) LDX y) DEC INC Zeropage, x -// +17 SLO* RLA* SRE* RRA* SAX* y) LAX* y) DCP ISB Zeropage, x -// +17 rmb1 rmb3 rmb5 rmb7 smb1 smb3 smb5 smb7 Zeropage - case 0x17: - if ( is_cmos ) - goto ZEROPAGE; - /* fall thru */ - case 0x14: - case 0x15: - case 0x16: - insn.Op1.type = o_displ; - insn.Op1.phrase = zX; - switch ( insn.itype ) - { - case M65_trb: - goto ZEROPAGE; - case M65_stx: - case M65_sax: - case M65_ldx: - case M65_lax: - insn.Op1.phrase = zY; - break; - } - insn.Op1.addr = insn.get_next_byte(); - break; -// +12 ora and eor adc sta lda cmp sbc Zeropage, indirect - case 0x12: - insn.indirect = 1; - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - break; - default: - error("ana: bad code %x",code); - } - if ( insn.itype == M65_nop ) - insn.Op1.type = o_void; - return insn.size; -} diff --git a/idasdk75/module/6502/emu.cpp b/idasdk75/module/6502/emu.cpp deleted file mode 100644 index d725287..0000000 --- a/idasdk75/module/6502/emu.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "m65.hpp" - -//---------------------------------------------------------------------- -void m6502_t::handle_operand( - const op_t &x, - bool isload, - const insn_t &insn, - bool *flow) const -{ - ea_t ea; - dref_t xreftype; - switch ( x.type ) - { - case o_reg: - break; - case o_imm: - if ( !isload ) - goto badTouch; - xreftype = dr_O; - goto MAKE_IMMD; - case o_displ: - xreftype = isload ? dr_R : dr_W; -MAKE_IMMD: - set_immd(insn.ea); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, xreftype, m65_opflags(x)); - break; - case o_mem: - ea = map_data_ea(insn, x); - insn.create_op_data(ea, x); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - break; - case o_near: - { - ea = map_code_ea(insn, x); - ea_t segbase = (ea - x.addr) >> 4; - ea_t thisseg = insn.cs; - bool iscall = has_insn_feature(insn.itype, CF_CALL); - insn.add_cref( - ea, - x.offb, - iscall ? (segbase == thisseg ? fl_CN : fl_CF) - : (segbase == thisseg ? fl_JN : fl_JF)); - if ( iscall && *flow ) - *flow = func_does_return(ea); - } - break; - default: -badTouch: - const char *mnem = insn.get_canon_mnem(ph); - warning("%a: %s,%d: bad optype %d", insn.ea, mnem, x.n, x.type); - break; - } -} - -//---------------------------------------------------------------------- -int m6502_t::emu(const insn_t &insn) const -{ - uint32 Feature = insn.get_canon_feature(ph); - bool flow = ((Feature & CF_STOP) == 0); - - if ( Feature & CF_USE1 ) handle_operand(insn.Op1, 1, insn, &flow); - if ( Feature & CF_USE2 ) handle_operand(insn.Op2, 1, insn, &flow); - if ( Feature & CF_CHG1 ) handle_operand(insn.Op1, 0, insn, &flow); - if ( Feature & CF_CHG2 ) handle_operand(insn.Op2, 0, insn, &flow); - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - return 1; -} diff --git a/idasdk75/module/6502/ins.cpp b/idasdk75/module/6502/ins.cpp deleted file mode 100644 index 5796d1b..0000000 --- a/idasdk75/module/6502/ins.cpp +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "m65.hpp" - -const instruc_t Instructions[] = -{ - { "", 0 }, - { "ADC", CF_USE1 }, // A <- (A) + M + C - { "ANC", CF_USE1 }, // A <- A /\ M, C <- ~A7 - { "AND", CF_USE1 }, // A <- (A) /\ M - { "ANE", CF_USE1 }, // M <-[(A)\/$EE] /\ (X)/\(M) - { "ARR", CF_USE1 }, // A <- [(A /\ M) >> 1] - { "ASL", CF_CHG1 }, // C <- A7, A <- (A) << 1 - { "ASR", CF_USE1 }, // A <- [(A /\ M) >> 1] - { "BCC", CF_USE1 }, // if C=0, PC = PC + offset - { "BCS", CF_USE1 }, // if C=1, PC = PC + offset - { "BEQ", CF_USE1 }, // if Z=1, PC = PC + offset - { "BIT", CF_USE1 }, // Z <- ~(A /\ M) N<-M7 V<-M6 - { "BMI", CF_USE1 }, // if N=1, PC = PC + offset - { "BNE", CF_USE1 }, // if Z=0, PC = PC + offset - { "BPL", CF_USE1 }, // if N=0, PC = PC + offset - { "BRK", CF_STOP }, // Stack <- PC, PC <- ($fffe) - { "BVC", CF_USE1 }, // if V=0, PC = PC + offset - { "BVS", CF_USE1 }, // if V=1, PC = PC + offset - { "CLC", 0 }, // C <- 0 - { "CLD", 0 }, // D <- 0 - { "CLI", 0 }, // I <- 0 - { "CLV", 0 }, // V <- 0 - { "CMP", CF_USE1 }, // (A - M) -> NZC - { "CPX", CF_USE1 }, // (X - M) -> NZC - { "CPY", CF_USE1 }, // (Y - M) -> NZC - { "DCP", CF_USE1|CF_CHG1 }, // M <- (M)-1, (A-M) -> NZC - { "DEC", CF_USE1|CF_CHG1 }, // M <- (M) - 1 - { "DEX", 0 }, // X <- (X) - 1 - { "DEY", 0 }, // Y <- (Y) - 1 - { "EOR", CF_USE1 }, // A <- (A) \-/ M - { "INC", CF_USE1|CF_CHG1 }, // M <- (M) + 1 - { "INX", 0 }, // X <- (X) +1 - { "INY", 0 }, // Y <- (Y) + 1 - { "ISB", CF_USE1|CF_CHG1 }, // M <- (M) - 1,A <- (A)-M-~C - { "JMP", CF_USE1|CF_STOP }, // PC <- Address - { "JMP", CF_USE1|CF_JUMP|CF_STOP }, // PC <- (Address) - { "JSR", CF_USE1|CF_CALL }, // Stack <- PC, PC <- Address - { "LAE", CF_USE1 }, // X,S,A <- (S /\ M) - { "LAX", CF_USE1 }, // A <- M, X <- M - { "LDA", CF_USE1 }, // A <- M - { "LDX", CF_USE1 }, // X <- M - { "LDY", CF_USE1 }, // Y <- M - { "LSR", CF_CHG1 }, // C <- A0, A <- (A) >> 1 - { "LXA", CF_USE1 }, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04 - { "NOP", 0 }, // [no operation] - { "ORA", CF_USE1 }, // A <- (A) V M - { "PHA", 0 }, // Stack <- (A) - { "PHP", 0 }, // Stack <- (P) - { "PLA", 0 }, // A <- (Stack) - { "PLP", 0 }, // A <- (Stack) - { "RLA", CF_USE1|CF_CHG1 }, // M <- (M << 1) /\ (A) - { "ROL", CF_CHG1 }, // C <- A7 & A <- A << 1 + C - { "ROR", CF_CHG1 }, // C<-A0 & A<- (A7=C + A>>1) - { "RRA", CF_USE1|CF_CHG1 }, // M <- (M >> 1) + (A) + C - { "RTI", CF_STOP }, // P <- (Stack), PC <-(Stack) - { "RTS", CF_STOP }, // PC <- (Stack) - { "SAX", CF_CHG1 }, // M <- (A) /\ (X) - { "SBC", CF_USE1 }, // A <- (A) - M - ~C - { "SBX", CF_USE1 }, // X <- (X)/\(A) - M - { "SEC", 0 }, // C <- 1 - { "SED", 0 }, // D <- 1 - { "SEI", 0 }, // I <- 1 - { "SHA", CF_CHG1 }, // M <- (A) /\ (X) /\ (PCH+1) - { "SHS", CF_CHG1 }, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1) - { "SHX", CF_CHG1 }, // M <- (X) /\ (PCH+1) - { "SHY", CF_CHG1 }, // M <- (Y) /\ (PCH+1) - { "SLO", CF_USE1|CF_CHG1 }, // M <- (M >> 1) + A + C - { "SRE", CF_USE1|CF_CHG1 }, // M <- (M >> 1) \-/ A - { "STA", CF_CHG1 }, // M <- (A) - { "STX", CF_CHG1 }, // M <- (X) - { "STY", CF_CHG1 }, // M <- (Y) - { "TAX", 0 }, // X <- (A) - { "TAY", 0 }, // Y <- (A) - { "TSX", 0 }, // X <- (S) - { "TXA", 0 }, // A <- (X) - { "TXS", 0 }, // S <- (X) - { "TYA", 0 }, // A <- (Y) - - - // CMOS instructions - - { "BBR0", CF_USE1|CF_USE2 }, // Branch if bit 0 reset - { "BBR1", CF_USE1|CF_USE2 }, // Branch if bit 1 reset - { "BBR2", CF_USE1|CF_USE2 }, // Branch if bit 2 reset - { "BBR3", CF_USE1|CF_USE2 }, // Branch if bit 3 reset - { "BBR4", CF_USE1|CF_USE2 }, // Branch if bit 4 reset - { "BBR5", CF_USE1|CF_USE2 }, // Branch if bit 5 reset - { "BBR6", CF_USE1|CF_USE2 }, // Branch if bit 6 reset - { "BBR7", CF_USE1|CF_USE2 }, // Branch if bit 7 reset - { "BBS0", CF_USE1|CF_USE2 }, // Branch if bit 0 set - { "BBS1", CF_USE1|CF_USE2 }, // Branch if bit 1 set - { "BBS2", CF_USE1|CF_USE2 }, // Branch if bit 2 set - { "BBS3", CF_USE1|CF_USE2 }, // Branch if bit 3 set - { "BBS4", CF_USE1|CF_USE2 }, // Branch if bit 4 set - { "BBS5", CF_USE1|CF_USE2 }, // Branch if bit 5 set - { "BBS6", CF_USE1|CF_USE2 }, // Branch if bit 6 set - { "BBS7", CF_USE1|CF_USE2 }, // Branch if bit 7 set - { "RMB0", CF_CHG1 }, // Reset memory bit 0 - { "RMB1", CF_CHG1 }, // Reset memory bit 1 - { "RMB2", CF_CHG1 }, // Reset memory bit 2 - { "RMB3", CF_CHG1 }, // Reset memory bit 3 - { "RMB4", CF_CHG1 }, // Reset memory bit 4 - { "RMB5", CF_CHG1 }, // Reset memory bit 5 - { "RMB6", CF_CHG1 }, // Reset memory bit 6 - { "RMB7", CF_CHG1 }, // Reset memory bit 7 - { "SMB0", CF_CHG1 }, // Set memory bit 0 - { "SMB1", CF_CHG1 }, // Set memory bit 1 - { "SMB2", CF_CHG1 }, // Set memory bit 2 - { "SMB3", CF_CHG1 }, // Set memory bit 3 - { "SMB4", CF_CHG1 }, // Set memory bit 4 - { "SMB5", CF_CHG1 }, // Set memory bit 5 - { "SMB6", CF_CHG1 }, // Set memory bit 6 - { "SMB7", CF_CHG1 }, // Set memory bit 7 - { "STZ", CF_CHG1 }, // Store zero - { "TSB", CF_USE1|CF_CHG1 }, // Test and set bits - { "TRB", CF_USE1|CF_CHG1 }, // Test and reset bits - { "PHY", 0 }, // Push Y register - { "PLY", 0 }, // Pull Y register - { "PHX", 0 }, // Push X register - { "PLX", 0 }, // Pull X register - { "BRA", CF_USE1|CF_STOP }, // Branch always - -}; - -CASSERT(qnumber(Instructions) == M65_last); diff --git a/idasdk75/module/6502/ins.hpp b/idasdk75/module/6502/ins.hpp deleted file mode 100644 index 7e30b0b..0000000 --- a/idasdk75/module/6502/ins.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - M65_null = 0, // Unknown Operation - - // NMOS instructions - - M65_adc, // A <- (A) + M + C - M65_anc, // A <- A /\ M, C <- ~A7 - M65_and, // A <- (A) /\ M - M65_ane, // M <-[(A)\/$EE] /\ (X)/\(M) - M65_arr, // A <- [(A /\ M) >> 1] - M65_asl, // C <- A7, A <- (A) << 1 - M65_asr, // A <- [(A /\ M) >> 1] - M65_bcc, // if C=0, PC = PC + offset - M65_bcs, // if C=1, PC = PC + offset - M65_beq, // if Z=1, PC = PC + offset - M65_bit, // Z <- ~(A /\ M) N<-M7 V<-M6 - M65_bmi, // if N=1, PC = PC + offset - M65_bne, // if Z=0, PC = PC + offset - M65_bpl, // if N=0, PC = PC + offset - M65_brk, // Stack <- PC, PC <- ($fffe) - M65_bvc, // if V=0, PC = PC + offset - M65_bvs, // if V=1, PC = PC + offset - M65_clc, // C <- 0 - M65_cld, // D <- 0 - M65_cli, // I <- 0 - M65_clv, // V <- 0 - M65_cmp, // (A - M) -> NZC - M65_cpx, // (X - M) -> NZC - M65_cpy, // (Y - M) -> NZC - M65_dcp, // M <- (M)-1, (A-M) -> NZC - M65_dec, // M <- (M) - 1 - M65_dex, // X <- (X) - 1 - M65_dey, // Y <- (Y) - 1 - M65_eor, // A <- (A) \-/ M - M65_inc, // M <- (M) + 1 - M65_inx, // X <- (X) +1 - M65_iny, // Y <- (Y) + 1 - M65_isb, // M <- (M) - 1,A <- (A)-M-~C - M65_jmp, // PC <- Address - M65_jmpi, // (PC <- Address) - M65_jsr, // Stack <- PC, PC <- Address - M65_lae, // X,S,A <- (S /\ M) - M65_lax, // A <- M, X <- M - M65_lda, // A <- M - M65_ldx, // X <- M - M65_ldy, // Y <- M - M65_lsr, // C <- A0, A <- (A) >> 1 - M65_lxa, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04 - M65_nop, // [no operation] - M65_ora, // A <- (A) V M - M65_pha, // Stack <- (A) - M65_php, // Stack <- (P) - M65_pla, // A <- (Stack) - M65_plp, // A <- (Stack) - M65_rla, // M <- (M << 1) /\ (A) - M65_rol, // C <- A7 & A <- A << 1 + C - M65_ror, // C<-A0 & A<- (A7=C + A>>1) - M65_rra, // M <- (M >> 1) + (A) + C - M65_rti, // P <- (Stack), PC <-(Stack) - M65_rts, // PC <- (Stack) - M65_sax, // M <- (A) /\ (X) - M65_sbc, // A <- (A) - M - ~C - M65_sbx, // X <- (X)/\(A) - M - M65_sec, // C <- 1 - M65_sed, // D <- 1 - M65_sei, // I <- 1 - M65_sha, // M <- (A) /\ (X) /\ (PCH+1) - M65_shs, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1) - M65_shx, // M <- (X) /\ (PCH+1) - M65_shy, // M <- (Y) /\ (PCH+1) - M65_slo, // M <- (M >> 1) + A + C - M65_sre, // M <- (M >> 1) \-/ A - M65_sta, // M <- (A) - M65_stx, // M <- (X) - M65_sty, // M <- (Y) - M65_tax, // X <- (A) - M65_tay, // Y <- (A) - M65_tsx, // X <- (S) - M65_txa, // A <- (X) - M65_txs, // S <- (X) - M65_tya, // A <- (Y) - - // CMOS instructions - - M65_bbr0, // Branch if bit 0 reset - M65_bbr1, // Branch if bit 1 reset - M65_bbr2, // Branch if bit 2 reset - M65_bbr3, // Branch if bit 3 reset - M65_bbr4, // Branch if bit 4 reset - M65_bbr5, // Branch if bit 5 reset - M65_bbr6, // Branch if bit 6 reset - M65_bbr7, // Branch if bit 7 reset - M65_bbs0, // Branch if bit 0 set - M65_bbs1, // Branch if bit 1 set - M65_bbs2, // Branch if bit 2 set - M65_bbs3, // Branch if bit 3 set - M65_bbs4, // Branch if bit 4 set - M65_bbs5, // Branch if bit 5 set - M65_bbs6, // Branch if bit 6 set - M65_bbs7, // Branch if bit 7 set - M65_rmb0, // Reset memory bit 0 - M65_rmb1, // Reset memory bit 1 - M65_rmb2, // Reset memory bit 2 - M65_rmb3, // Reset memory bit 3 - M65_rmb4, // Reset memory bit 4 - M65_rmb5, // Reset memory bit 5 - M65_rmb6, // Reset memory bit 6 - M65_rmb7, // Reset memory bit 7 - M65_smb0, // Set memory bit 0 - M65_smb1, // Set memory bit 1 - M65_smb2, // Set memory bit 2 - M65_smb3, // Set memory bit 3 - M65_smb4, // Set memory bit 4 - M65_smb5, // Set memory bit 5 - M65_smb6, // Set memory bit 6 - M65_smb7, // Set memory bit 7 - M65_stz, // Store zero - M65_tsb, // Test and set bits - M65_trb, // Test and reset bits - M65_phy, // Push Y register - M65_ply, // Pull Y register - M65_phx, // Push X register - M65_plx, // Pull X register - M65_bra, // Branch always - - M65_last, -}; - -#endif diff --git a/idasdk75/module/6502/makefile b/idasdk75/module/6502/makefile deleted file mode 100644 index 9a900f2..0000000 --- a/idasdk75/module/6502/makefile +++ /dev/null @@ -1,40 +0,0 @@ -PROC=m65 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp ins.hpp m65.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp ins.hpp m65.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.cpp ins.hpp m65.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp m65.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp m65.hpp reg.cpp diff --git a/idasdk75/module/6502/reg.cpp b/idasdk75/module/6502/reg.cpp deleted file mode 100644 index f46d528..0000000 --- a/idasdk75/module/6502/reg.cpp +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "m65.hpp" - -//-------------------------------------------------------------------------- -static const char *const regnames[] = -{ - "A", "X", "Y", "cs", "ds" -}; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new m6502_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi m6502_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_ending_undo: - is_cmos = ph.get_proc_index(); - break; - - case processor_t::ev_newprc: - is_cmos = va_arg(va, int) != 0; - break; - - case processor_t::ev_creating_segm: - { // default DS is equal to CS - segment_t *sptr = va_arg(va, segment_t *); - sptr->defsr[rVds-ph.reg_first_sreg] = sptr->sel; - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const char *const ps_headers[] = -{ - ".code", - NULL -}; - -static const asm_t pseudosam = -{ - AS_COLON | ASH_HEXF1 | AS_N2CHR | AS_NOXRF, - UAS_SELSG, - "PseudoSam by PseudoCode", - 0, - ps_headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".rs %s", // uninited arrays - ".equ", // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//----------------------------------------------------------------------- -// SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988 -//----------------------------------------------------------------------- -static const asm_t svasm = -{ - AS_COLON | ASH_HEXF4, - UAS_NOSEG, - "SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988", - 0, - NULL, // headers - "* = ", - ".END", - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "\\'", // special symbols in char and string constants - - ".BYTE", // ascii string directive - ".BYTE", // byte directive - ".WORD", // word directive -}; - -//----------------------------------------------------------------------- -// TASM assembler definiton -//----------------------------------------------------------------------- -static const asm_t tasm = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_NOENS | UAS_NOSEG, - "Table Driven Assembler (TASM) by Speech Technology Inc.", - 0, - NULL, // headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".text", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".block %s", // uninited arrays - ".equ", - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - "and", // and - "or", // or - NULL, // xor - "not", // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//----------------------------------------------------------------------- -// Avocet assembler definiton -//----------------------------------------------------------------------- -static const asm_t avocet = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_NOENS | UAS_NOSEG, - "Avocet Systems 2500AD 6502 Assembler", - 0, - NULL, // headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".fcc", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".ds %s", // uninited arrays -}; - -static const asm_t *const asms[] = { &svasm, &tasm, &pseudosam, &avocet, NULL }; -//----------------------------------------------------------------------- -#define FAMILY "MOS Technology 65xx series:" -static const char *const shnames[] = { "M6502", "M65C02", NULL }; -static const char *const lnames[] = { FAMILY"MOS Technology 6502", "MOS Technology 65C02", NULL }; - -//-------------------------------------------------------------------------- -static const uchar retcode_1[] = { 0x60 }; -static const uchar retcode_2[] = { 0x40 }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_6502, // id - PR_SEGS // flag - | PR_SEGTRANS, - 0, // flag2 - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - regnames, // Register names - qnumber(regnames), // Number of registers - - rVcs, // first - rVds, // last - 0, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0, M65_last, - Instructions, // instruc -}; diff --git a/idasdk75/module/65816/m65816.hpp b/idasdk75/module/65816/m65816.hpp deleted file mode 100644 index 940a259..0000000 --- a/idasdk75/module/65816/m65816.hpp +++ /dev/null @@ -1,258 +0,0 @@ - -#ifndef __M65816_HPP__ -#define __M65816_HPP__ - -#include "../../module/idaidp.hpp" -#include <segregs.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -// Direct Memory Reference with full-length address -#define o_mem_far o_idpspec0 - -// If there is an address in 'Op[N].full_target_ea', -// it means the target address of a branch/jump -// is already known. That's there to help the 'emu' -// module propagate M&X flags & status. -#define full_target_ea specval - - -// Is indirect memory reference? -#define indirect segpref - -// These defines are used by some 6502 asm_t descriptors. -// Although this is primarily a 65816 module, they'll -// remain here since at some point, this CPU module /might/ -// supersede the 6502 one. -// Should that happen, we wouldn't want to waste the -// set of asm_t's that are defined for 6502. -#define UAS_SECT 0x0002 // Segments are named .SECTION -#define UAS_NOSEG 0x0004 // No 'segment' directives -#define UAS_SELSG 0x0010 // Segment should be selected by its name -#define UAS_CDSEG 0x0080 // Only DSEG,CSEG,XSEG -#define UAS_NOENS 0x0200 // don't specify start addr in the .end directive - - -enum M65816_registers -{ - rA, // Accumulator - rX, // X index - rY, // Y index - rS, // Stack - rCs, // code segment - rDs, // data segment - - // This will hold the value of B, the - // data bank register. We won't make use of Ds - // directly, as it is typically used, in computation, - // as a 16-byte paragraph register, while B is a - // 64KB pages register. Also, by having a dedicated - // B, the user will be able to modify it more - // easily (without having to manually shift the value by - // 12 bits). - // Note: Also, we won't have this register ``mapped'' to a sel_t. - // We'll stuff the B value in there directly, which allows - // it to be more versatile, and access banks where there's - // no ROM loaded (such as [S|W]RAM bank(s)). - rB, - - // Direct page register. Same note as that of rB applies. - rD, - - // These will be considered segment - // registers by IDA (just as rCs, rDs, rB and rD), - // but we'll actually use them to keep information - // about the 'm', 'x' and 'e' flags, determining - // what's the accumulator & indices mode, and whether - // we run in 6502 emulation or 65816 native mode. - rFm, - rFx, - rFe, - - // program bank register - rPB -}; - - -// Addressing modes -enum m65_addrmode_t -{ - ABS = 0, - ABS_IX, - ABS_IY, - ABS_IX_INDIR, - ABS_INDIR, - ABS_INDIR_LONG, - ABS_LONG, - ABS_LONG_IX, - ACC, - BLK_MOV, - DP, - DP_IX, - DP_IY, - DP_IX_INDIR, - DP_INDIR, - DP_INDIR_LONG, - DP_INDIR_IY, - DP_INDIR_LONG_IY, - IMM, - IMPLIED, - PC_REL, - PC_REL_LONG, - STACK_ABS, - STACK_DP_INDIR, - STACK_INT, - STACK_PC_REL, - STACK_PULL, - STACK_PUSH, - STACK_RTI, - STACK_RTL, - STACK_RTS, - STACK_REL, - STACK_REL_INDIR_IY, - ADDRMODE_last -}; - -// The various phrases that can be used in case -// an operand is of type 'o_displ'. -enum odispl_phrases_t -{ - rDX = 100, // "dp, X" DP_IX - rDY, // "dp, Y" DP_IY - riDX, // "(dp, X)" DP_IX_INDIR - rAbsi, // "(abs)" ABS_INDIR - rAbsiL, // "long(abs)" ABS_INDIR_LONG - rAbsX, // "abs, X" ABS_IX - rAbsY, // "abs, Y" ABS_IY - rAbsLX, // "long abs, X" ABS_LONG_IX - rAbsXi, // "(abs,X)" ABS_IX_INDIR - rDi, // "(dp,n)" DP_INDIR - rDiL, // "long(dp,n)" DP_INDIR_LONG - rDiY, // "(dp,n), Y" DP_INDIR_IY - rDiLY, // "long(dp,n), Y" DP_INDIR_LONG_IY - rSiY, // (s,n),Y STACK_REL_INDIR_IY - rSDi // "(dp,n)" STACK_DP_INDIR -}; - - -// Information about addressing modes. -struct addrmode_info_t -{ - const char *name; -}; - -extern const struct addrmode_info_t AddressingModes[]; - - -// The type of m65* processors. Used -// to declare availability of certain opcodes depending -// on the processor. -enum m65_variant_t -{ - M6502 = 1, - M65C02 = 2, - M65802 = 4, - M65816 = 8, - M6X = 1 | 2 | 4 | 8 -}; - - -// Special flags, for certain opcodes -enum opcode_flags_t -{ - // Increment instruction's byte count - // if accumulator is in 16-bits mode. - ACC16_INCBC = 1, - - // Increment instruction's byte count - // if X/Y registers are in 16-bits mode. - XY16_INCBC = 2 -}; - -// Information about an opcode -struct opcode_info_t -{ - m65_itype_t itype; - m65_addrmode_t addr; - uint8 cpu_variants; // OR'd m65_variant_t - uint16 flags; // OR'd opcode_flags_t -}; - -inline bool is_acc_16_bits(ea_t ea) { return (get_sreg(ea, rFm) == 0); } -inline bool is_xy_16_bits(ea_t ea) { return (get_sreg(ea, rFx) == 0); } -inline bool is_acc_16_bits(const insn_t &insn) { return is_acc_16_bits(insn.ea); } -inline bool is_xy_16_bits(const insn_t &insn) { return is_xy_16_bits(insn.ea); } - -const struct opcode_info_t &get_opcode_info(uint8 opcode); - -// Determines whether an m65_itype_t is of type 'push' -#define M65_ITYPE_PUSH(op) \ - (((op) == M65816_pea) \ - || ((op) == M65816_pei) \ - || ((op) == M65816_per) \ - || ((op) == M65816_pha) \ - || ((op) == M65816_phb) \ - || ((op) == M65816_phd) \ - || ((op) == M65816_phk) \ - || ((op) == M65816_php) \ - || ((op) == M65816_phx) \ - || ((op) == M65816_phy)) - -// Determines whether an m65_itype_t is of type 'pull' -#define M65_ITYPE_PULL(op) \ - (((op) == M65816_pla) \ - || ((op) == M65816_plb) \ - || ((op) == M65816_pld) \ - || ((op) == M65816_plp) \ - || ((op) == M65816_plx) \ - || ((op) == M65816_ply)) - -//------------------------------------------------------------------------ -int idaapi ana(insn_t *_insn); -int idaapi emu(const insn_t &insn); - -//------------------------------------------------------------------------ -class snes_addr_t; - -struct m65816_iohandler_t : public iohandler_t -{ - m65816_iohandler_t(netnode &nn) : iohandler_t(nn) {} - - virtual bool check_ioresp() const override - { - if ( inf_like_binary() ) - return true; - else - return get_segm_by_name("ppu") != NULL; - } -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct m65816_t); - -struct m65816_t : public procmod_t -{ - netnode helper; - m65816_iohandler_t ioh = m65816_iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - struct SuperFamicomCartridge *cartridge = nullptr; - snes_addr_t *sa = nullptr; - bool flow = false; - - m65816_t(); - DECLARE_VIRTUAL_DTOR(m65816_t); - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - ea_t xlat(ea_t address); - - void handle_operand(const op_t &x, bool read_access, const insn_t &insn); - int emu(const insn_t &insn); - - void m65816_assumes(outctx_t &ctx); - ea_t calc_addr(const op_t &x, ea_t *orig_ea, const insn_t &insn); - void m65816_header(outctx_t &ctx) const; - void m65816_segstart(outctx_t &ctx, segment_t *Srange) const; - void m65816_footer(outctx_t &ctx) const; -}; - -#endif diff --git a/idasdk75/module/65816/makefile b/idasdk75/module/65816/makefile deleted file mode 100644 index fae354c..0000000 --- a/idasdk75/module/65816/makefile +++ /dev/null @@ -1,62 +0,0 @@ -PROC=m65816 -CONFIGS=m65816.cfg -O1=bt - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/idaidp.hpp ../iohandler.hpp ana.cpp ins.hpp \ - m65816.hpp -$(F)bt$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/idaidp.hpp ../iohandler.hpp bt.cpp bt.hpp \ - ins.hpp m65816.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/idaidp.hpp ../iohandler.hpp bt.hpp emu.cpp \ - ins.hpp m65816.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/idaidp.hpp ../iohandler.hpp ins.cpp ins.hpp \ - m65816.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../module/idaidp.hpp ../iohandler.hpp bt.hpp ins.hpp \ - m65816.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/snes/addr.cpp ../../ldr/snes/super-famicom.hpp \ - ../../module/idaidp.hpp ../iohandler.hpp ins.hpp \ - m65816.hpp reg.cpp diff --git a/idasdk75/module/65816/out.cpp b/idasdk75/module/65816/out.cpp deleted file mode 100644 index f3ab7d6..0000000 --- a/idasdk75/module/65816/out.cpp +++ /dev/null @@ -1,485 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "m65816.hpp" -#include "bt.hpp" - -//---------------------------------------------------------------------- -class out_m65816_t : public outctx_t -{ - out_m65816_t(void) = delete; // not used - m65816_t &pm() { return *static_cast<m65816_t *>(procmod); } -public: - void out_dp(const op_t &x); - void out_addr_near_b(const op_t &x); - void out_addr_near(const op_t &x); - void out_addr_far(const op_t &x); - void print_orig_ea(const op_t &x); - - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_m65816_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_m65816_t) - -//---------------------------------------------------------------------- -void out_m65816_t::out_dp(const op_t &x) -{ - sel_t dp = get_sreg(insn.ea, rD); - if ( dp != BADSEL ) - { - ea_t orig_ea = dp + x.addr; - ea_t ea = pm().xlat(orig_ea); - - //if ( dp != 0 ) - // out_symbol('('); - - if ( !out_name_expr(x, ea, BADADDR) ) - { - out_tagon(COLOR_ERROR); - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - - //if ( dp != 0 ) - //{ - // out_symbol(' '); - // out_symbol('-'); - // out_symbol(' '); - // out_btoa(dp << 8, 16); - // out_symbol(')'); - //} - } - else - { - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); - } -} - -//---------------------------------------------------------------------- -void out_m65816_t::out_addr_near_b(const op_t &x) -{ - sel_t db = get_sreg(insn.ea, rB); - if ( db != BADSEL ) - { - ea_t orig_ea = (db << 16) + x.addr; - ea_t ea = pm().xlat(orig_ea); - - if ( !out_name_expr(x, ea, BADADDR) ) - { - out_tagon(COLOR_ERROR); - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - } - else - { - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_16); - } -} - -//------------------------------------------------------------------------- -void out_m65816_t::out_addr_near(const op_t &x) -{ - ea_t orig_ea = map_code_ea(insn, x); - ea_t ea = pm().xlat(orig_ea); - if ( !out_name_expr(x, ea, BADADDR) ) - { - out_tagon(COLOR_ERROR); - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } -} - -//---------------------------------------------------------------------- -void out_m65816_t::out_addr_far(const op_t &x) -{ - ea_t orig_ea = x.addr; - ea_t ea = pm().xlat(orig_ea); - - if ( !out_name_expr(x, ea, BADADDR) ) - { - out_tagon(COLOR_ERROR); - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_24); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } -} - -//---------------------------------------------------------------------- -void out_m65816_t::print_orig_ea(const op_t &x) -{ - if ( !has_cmt(F) ) - { - char buf[64]; - qsnprintf(buf, sizeof(buf), - COLSTR(" %s orig=0x%0*a", SCOLOR_AUTOCMT), - ash.cmnt, - (x.type == o_far || x.type == o_mem_far) ? 6 : 4, - x.addr); - out_line(buf); - } -} - -//---------------------------------------------------------------------- -ea_t m65816_t::calc_addr(const op_t &x, ea_t *orig_ea, const insn_t &insn) -{ - ea_t ea; - switch ( x.type ) - { - case o_near: - ea = map_code_ea(insn, x); - goto XLAT_ADDR; - case o_far: - case o_mem_far: - ea = x.addr; - goto XLAT_ADDR; - case o_mem: - ea = map_data_ea(insn, x); -XLAT_ADDR: - if ( orig_ea != NULL ) - *orig_ea = ea; - return xlat(ea); - default: - INTERR(559); - } -} - -//---------------------------------------------------------------------- -bool out_m65816_t::out_operand(const op_t &x) -{ - ea_t ea, orig_ea; - switch ( x.type ) - { - case o_reg: - out_register(ph.reg_names[x.reg]); - break; - case o_imm: - out_symbol('#'); - out_value(x, 0); - break; - case o_near: - case o_far: - if ( insn.indirect ) - out_symbol('('); - ea = pm().calc_addr(x, &orig_ea, insn); - if ( !out_name_expr(x, ea, BADADDR) ) - { - uint32 v = x.addr; - if ( x.type == o_far ) - v &= 0xFFFFFF; - else - v &= 0xFFFF; - out_tagon(COLOR_ERROR); - out_btoa(v, 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - if ( insn.indirect ) - out_symbol(')'); - if ( orig_ea != ea ) - print_orig_ea(x); - break; - case o_mem: - case o_mem_far: - { - if ( insn.indirect ) - out_symbol('('); - - if ( x.type == o_mem_far ) - { - ea = pm().calc_addr(x, &orig_ea, insn); - out_addr_far(x); - } - else - { - sel_t db = get_sreg(insn.ea, rB); - if ( db == BADSEL ) - ea = orig_ea = x.addr; - else - ea = pm().calc_addr(x, &orig_ea, insn); - out_addr_near_b(x); - } - - if ( insn.indirect ) - out_symbol(')'); - - if ( orig_ea != ea ) - print_orig_ea(x); - } - break; - case o_displ: - switch ( x.phrase ) - { - case rS: - out_register(ph.reg_names[x.phrase]); - out_symbol(','); - out_char(' '); - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); - break; - case rD: - out_register(ph.reg_names[x.phrase]); - out_symbol(','); - out_char(' '); - out_dp(x); - break; - case rSiY: - out_symbol('('); - out_register("S"); - out_symbol(','); - out_char(' '); - out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); - out_symbol(','); - out_char(' '); - out_register("Y"); - out_symbol(')'); - break; - case rDi: - case rSDi: - out_symbol('('); - out_register("D"); - out_symbol(','); - out_char(' '); - out_dp(x); - out_symbol(')'); - break; - case rDiL: - out_symbol('['); - out_register("D"); - out_symbol(','); - out_char(' '); - out_dp(x); - out_symbol(']'); - break; - case rDX: - case rDY: - out_register("D"); - out_symbol(','); - out_char(' '); - out_dp(x); - out_symbol(','); - out_char(' '); - out_register((x.phrase == rDX) ? "X" : "Y"); - break; - case riDX: - out_symbol('('); - out_register("D"); - out_symbol(','); - out_char(' '); - out_dp(x); - out_symbol(','); - out_char(' '); - out_register("X"); - out_symbol(')'); - break; - case rDiY: - case rDiLY: - out_symbol(x.phrase == rDiLY ? '[' : '('); - out_register("D"); - out_symbol(','); - out_char(' '); - out_dp(x); - out_symbol(x.phrase == rDiLY ? ']' : ')'); - out_symbol(','); - out_char(' '); - out_register("Y"); - break; - case rAbsi: - out_symbol('('); - out_addr_near_b(x); - out_symbol(')'); - break; - case rAbsiL: - out_symbol('['); - out_addr_near_b(x); - out_symbol(']'); - break; - case rAbsX: - case rAbsY: - out_addr_near_b(x); - out_symbol(','); - out_char(' '); - out_register(x.phrase == rAbsY ? "Y" : "X"); - break; - case rAbsLX: - { - ea_t lorig_ea = x.addr; - ea_t lea = pm().xlat(lorig_ea); - - out_addr_far(x); - out_symbol(','); - out_char(' '); - out_register("X"); - - if ( lorig_ea != lea ) - print_orig_ea(x); - } - break; - case rAbsXi: - out_symbol('('); - out_addr_near(x); // jmp, jsr - out_symbol(','); - out_char(' '); - out_register("X"); - out_symbol(')'); - break; - default: - goto err; - } - break; - case o_void: - return 0; - default: - err: - warning("out: %a: bad optype %d", insn.ea, x.type); - break; - } - return 1; -} - - -//---------------------------------------------------------------------- -static bool forced_print(flags_t F, int reg) -{ - return (reg == rFm || reg == rFx) && is_func(F); -} - -//---------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -void m65816_t::m65816_assumes(outctx_t &ctx) -{ - ea_t ea = ctx.insn_ea; - char buf[MAXSTR]; - char *ptr = buf; - char *end = buf + sizeof(buf); - segment_t *seg = getseg(ea); - bool seg_started = (ea == seg->start_ea); - for ( int reg=ph.reg_first_sreg; reg <= ph.reg_last_sreg; reg++ ) - { - if ( reg == rCs ) - continue; - sreg_range_t srrange; - if ( !get_sreg_range(&srrange, ea, reg) ) - continue; - sel_t curval = srrange.val; - if ( seg_started || srrange.start_ea == ea ) - { - sreg_range_t prev; - bool prev_exists = get_sreg_range(&prev, ea - 1, reg); - if ( seg_started - || (prev_exists && prev.val != curval) - || forced_print(ctx.F, reg) ) - { - if ( reg == rFm || reg == rFx ) - { - ctx.gen_printf(0, ".%c%d", reg == rFm ? 'A' : 'I', curval > 0 ? 8 : 16); - } - else - { - if ( ptr != buf ) - APPCHAR(ptr, end, ' '); - ptr += qsnprintf(ptr, end-ptr, "%s=%a", ph.reg_names[reg], curval); - } - } - } - } - if ( ptr != buf ) - ctx.gen_cmt_line("%s", buf); -} - -//---------------------------------------------------------------------- -void out_m65816_t::out_insn(void) -{ - out_mnemonic(); - out_one_operand(0); - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void m65816_t::m65816_header(outctx_t &ctx) const -{ - ctx.gen_cmt_line("%s Processor: %s", ash.cmnt, inf_get_procname().c_str()); - ctx.gen_cmt_line("%s Target assembler: %s", ash.cmnt, ash.name); - if ( ash.header != NULL ) - for ( const char *const *ptr=ash.header; *ptr != NULL; ptr++ ) - ctx.flush_buf(*ptr,0); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Srange) could be made const -void m65816_t::m65816_segstart(outctx_t &ctx, segment_t *Srange) const -{ - qstring name; - get_visible_segm_name(&name, Srange); - if ( ash.uflag & UAS_SECT ) - { - ctx.gen_printf(0, COLSTR("%s: .section",SCOLOR_ASMDIR), name.c_str()); - } - else - { - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s.segment %s",SCOLOR_ASMDIR), - (ash.uflag & UAS_NOSEG) ? ash.cmnt : "", - name.c_str()); - if ( ash.uflag & UAS_SELSG ) - ctx.flush_buf(name.c_str(), DEFAULT_INDENT); - if ( ash.uflag & UAS_CDSEG ) - ctx.flush_buf(COLSTR("CSEG",SCOLOR_ASMDIR), DEFAULT_INDENT); // XSEG - eXternal memory - } - if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) - { - ea_t org = ctx.insn_ea - get_segm_base(Srange); - if ( org != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), org); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s",SCOLOR_ASMDIR), ash.origin, buf); - } - } -} - -//-------------------------------------------------------------------------- -void m65816_t::m65816_footer(outctx_t &ctx) const -{ - char buf[MAXSTR]; - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - char *ptr = buf; - char *end = buf + sizeof(buf); - APPEND(ptr, end, ash.end); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - if ( ash.uflag & UAS_NOENS ) - APPEND(ptr, end, ash.cmnt); - APPCHAR(ptr, end, ' '); - APPEND(ptr, end, name.begin()); - } - ctx.flush_buf(buf, DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} diff --git a/idasdk75/module/65816/reg.cpp b/idasdk75/module/65816/reg.cpp deleted file mode 100644 index 7617ed9..0000000 --- a/idasdk75/module/65816/reg.cpp +++ /dev/null @@ -1,704 +0,0 @@ - -#include <ida.hpp> -#include <idp.hpp> -#include <segregs.hpp> -#include <diskio.hpp> - -#include "m65816.hpp" - -#include "../../ldr/snes/addr.cpp" -//-------------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "A", // Accumulator - "X", // Index - "Y", // Index - "S", // Stack register (used?) - "cs", - "ds", - - "B", // Data bank - "D", // Direct page register (used?) - - "m", // Holds accumulator-is-8-bits flag - "x", // Holds indices-are-8-bits flag - "e", // Holds emulation mode flag - - "PB" // Program bank -}; - - -// --------------------------------------------------------------------------- -ea_t m65816_t::xlat(ea_t address) -{ - return sa->xlat(address); -} - -// --------------------------------------------------------------------------- -m65816_t::m65816_t() -{ - cartridge = new SuperFamicomCartridge; - sa = new snes_addr_t; -} - -m65816_t::~m65816_t() -{ - delete cartridge; - cartridge = nullptr; - delete sa; - sa = nullptr; -} - -// --------------------------------------------------------------------------- -// Handler for: get_autocmt. -// Will possibly store a comment in 'buf', -// depending on whether an autocmt is deemed necessary -// for the current line. -// -// For the moment this will just print, in a user-friendly -// way, information about the addressing mode, if needed. -static bool make_insn_cmt(qstring *buf, const insn_t &insn) -{ - uint8 opcode = get_byte(insn.ea); - const struct opcode_info_t &opcode_info = get_opcode_info(opcode); - static const bool addressing_info_required[] = - { - false, // ABS - false, // ABS_IX, - false, // ABS_IY, - false, // ABS_IX_INDIR, - false, // ABS_INDIR, - false, // ABS_INDIR_LONG, - false, // ABS_LONG, - false, // ABS_LONG_IX, - false, // ACC, - true, // BLK_MOV, - false, // DP, - false, // DP_IX, - false, // DP_IY, - false, // DP_IX_INDIR, - false, // DP_INDIR, - false, // DP_INDIR_LONG, - false, // DP_INDIR_IY, - false, // DP_INDIR_LONG_IY, - false, // IMM, - false, // IMPLIED, - true, // PC_REL, - true, // PC_REL_LONG, - false, // STACK_ABS, - false, // STACK_DP_INDIR, - false, // STACK_INT, - false, // STACK_PC_REL, - false, // STACK_PULL, - false, // STACK_PUSH, - false, // STACK_RTI, - false, // STACK_RTL, - false, // STACK_RTS, - false, // STACK_REL, - false // STACK_REL_INDIR_IY, - }; - - if ( !addressing_info_required[opcode_info.addr] ) - return false; - - const struct addrmode_info_t &addrmode_info = AddressingModes[opcode_info.addr]; - *buf = addrmode_info.name; - return true; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case idb_event::sgr_changed: - { - ea_t start_ea = va_arg(va, ea_t); - ea_t dummy = va_arg(va, ea_t); qnotused(dummy); - int regnum = va_arg(va, int); - sel_t value = va_arg(va, sel_t); - if ( regnum == rB ) - { -// sel_t d2 = va_arg(va, sel_t); qnotused(d2); - if ( value == BADSEL ) - split_sreg_range(start_ea, rDs, BADSEL, SR_auto); - else - split_sreg_range(start_ea, rDs, value << 12, SR_auto); - } - else if ( regnum == rPB ) - { - uint16 offset = start_ea & 0xffff; - ea_t newEA = pm.xlat((value << 16) + offset); - if ( start_ea != newEA ) - warning("Inconsistent program bank number ($%02X:%04X != $%02X:%04X)", - uint32(start_ea >> 16), - offset, - uint8(value), - offset); - } - } - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new m65816_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi m65816_t::on_event(ssize_t msgid, va_list va) -{ - int retcode = 1; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ m65816"); - break; - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - case processor_t::ev_newprc: - break; - case processor_t::ev_creating_segm: - { - segment_t *sptr = va_arg(va, segment_t *); - - // default DS is equal to CS - sptr->defsr[rDs - ph.reg_first_sreg] = sptr->sel; - - // detect SNES bank 0 - if ( xlat(0) == (sptr->start_ea & 0xff0000) ) - { - // initial bank must be $00 (especially important on HiROM) - // Example: Donkey Kong Country 2 - Emulation_mode_RESET - sptr->defsr[rB - ph.reg_first_sreg] = 0; - sptr->defsr[rPB - ph.reg_first_sreg] = 0; - } - else - { - // otherwise, set the default bank number from EA - uint8 pb = sptr->start_ea >> 16; - sptr->defsr[rB - ph.reg_first_sreg] = pb; - sptr->defsr[rPB - ph.reg_first_sreg] = pb; - } - } - break; - case processor_t::ev_oldfile: - case processor_t::ev_newfile: - { - cartridge->read_hash(helper); - //cartridge.print(); - - // read rommode_t for backward compatibility - nodeidx_t mode = helper.hashval_long("rommode_t"); - if ( mode != 0 ) - { - switch ( mode ) - { - case 0x20: - cartridge->mapper = SuperFamicomCartridge::LoROM; - break; - - case 0x21: - cartridge->mapper = SuperFamicomCartridge::HiROM; - break; - } - - helper.hashdel("rommode_t"); - cartridge->write_hash(helper); - } - - if ( !sa->addr_init(*cartridge) ) - { - warning("Unsupported mapper: %s", cartridge->mapper_string()); - } - - char buf[MAXSTR]; - const char *device_ptr = buf; - ssize_t len = helper.hashstr("device", buf, sizeof(buf)); - if ( len <= 0 ) - device_ptr = "65816"; - - if ( msgid == processor_t::ev_newfile ) - { - if ( cartridge->has_superfx ) - ioh.set_device_name("superfx", IORESP_ALL); - - if ( cartridge->has_sa1 ) - ioh.set_device_name("sa1", IORESP_ALL); - - if ( cartridge->has_cx4 ) - ioh.set_device_name("cx4", IORESP_ALL); - - if ( cartridge->has_spc7110 ) - ioh.set_device_name("spc7110", IORESP_ALL); - - if ( cartridge->has_sdd1 ) - ioh.set_device_name("sdd1", IORESP_ALL); - - if ( cartridge->has_sharprtc ) - ioh.set_device_name("sharprtc", IORESP_ALL); - - if ( cartridge->has_epsonrtc ) - ioh.set_device_name("epsonrtc", IORESP_ALL); - - if ( cartridge->has_obc1 ) - ioh.set_device_name("obc1", IORESP_ALL); - - if ( cartridge->has_dsp1 ) - ioh.set_device_name("dsp1", IORESP_ALL); - - if ( cartridge->has_dsp2 ) - ioh.set_device_name("dsp2", IORESP_ALL); - - if ( cartridge->has_dsp3 ) - ioh.set_device_name("dsp3", IORESP_ALL); - - if ( cartridge->has_dsp4 ) - ioh.set_device_name("dsp4", IORESP_ALL); - - if ( cartridge->has_st010 ) - ioh.set_device_name("st010", IORESP_ALL); - - if ( cartridge->has_st011 ) - ioh.set_device_name("st011", IORESP_ALL); - - if ( cartridge->has_st018 ) - ioh.set_device_name("st018", IORESP_ALL); - - ioh.set_device_name(device_ptr, IORESP_ALL); - - set_default_sreg_value(NULL, rFm, 1); - set_default_sreg_value(NULL, rFx, 1); - set_default_sreg_value(NULL, rFe, 1); - set_default_sreg_value(NULL, rD, 0); - - // see processor_t::ev_creating_segm for the following registers - //set_default_sreg_value(NULL, rPB, 0); - //set_default_sreg_value(NULL, rB, 0); - //set_default_sreg_value(NULL, rDs, 0); - - if ( inf_get_start_ip() != BADADDR ) - { - ea_t reset_ea = xlat(inf_get_start_ip()); - ea_t sea = getseg(reset_ea)->start_ea; - split_sreg_range(reset_ea, rFm, get_sreg(sea, rFm), SR_auto); - split_sreg_range(reset_ea, rFx, get_sreg(sea, rFx), SR_auto); - split_sreg_range(reset_ea, rFe, get_sreg(sea, rFe), SR_auto); - split_sreg_range(reset_ea, rPB, 0, SR_auto); - split_sreg_range(reset_ea, rB, 0, SR_auto); - split_sreg_range(reset_ea, rD, get_sreg(sea, rD), SR_auto); - } - } - } - break; - case processor_t::ev_get_autocmt: - { - qstring *buf = va_arg(va, qstring *); - const insn_t *insn = va_arg(va, insn_t *); - if ( make_insn_cmt(buf, *insn) ) - retcode = 1; - } - break; - case processor_t::ev_may_be_func: - { - const insn_t *insn = va_arg(va, insn_t *); - retcode = 0; - ea_t cref_addr; - for ( cref_addr = get_first_cref_to(insn->ea); - cref_addr != BADADDR; - cref_addr = get_next_cref_to(insn->ea, cref_addr) ) - { - uint8 opcode = get_byte(cref_addr); - const struct opcode_info_t &opinfo = get_opcode_info(opcode); - if ( opinfo.itype == M65816_jsl - || opinfo.itype == M65816_jsr - || opinfo.itype == M65816_jml ) - { - retcode = 100; - break; - } - } - } - break; - case processor_t::ev_is_call_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - const struct opcode_info_t &opinfo = get_opcode_info(get_byte(insn->ea)); - if ( opinfo.itype == M65816_jsr - || opinfo.itype == M65816_jsl ) - retcode = 1; - else - retcode = -1; - } - break; - case processor_t::ev_is_ret_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - const struct opcode_info_t &opinfo = get_opcode_info(get_byte(insn->ea)); - if ( opinfo.itype == M65816_rti - || opinfo.itype == M65816_rtl - || opinfo.itype == M65816_rts ) - retcode = 1; - else - retcode = -1; - } - break; - case processor_t::ev_is_indirect_jump: - { - const insn_t *insn = va_arg(va, insn_t *); - const struct opcode_info_t &opinfo = get_opcode_info(get_byte(insn->ea)); - if ( opinfo.itype == M65816_jmp - || opinfo.itype == M65816_jml ) - { - if ( opinfo.addr == ABS_INDIR - || opinfo.addr == ABS_IX_INDIR - || opinfo.addr == ABS_INDIR_LONG ) - retcode = 2; - else - retcode = 1; - } - else - retcode = 0; - } - break; - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m65816_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m65816_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - m65816_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m65816_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - default: - retcode = 0; - break; - } - return retcode; -} - - -//----------------------------------------------------------------------- -// CA65 ASSEMBLER -// -// http://www.cc65.org/doc/ca65-4.html#ss4.1 -//----------------------------------------------------------------------- -static const asm_t ca65asm = -{ - AS_COLON | ASH_HEXF4, // Assembler features - 0, // User-defined flags - "CA65 ASSEMBLER", // Name - 0, - NULL, // headers - ".ORG", // origin directive - ".END", // end directive - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "\\'", // special symbols in char and string constants - - ".BYTE", // ascii string directive - ".BYTE", // byte directive - ".WORD", // word directive -}; - -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const char *const ps_headers[] = -{ - ".code", - NULL -}; - -static const asm_t pseudosam = -{ - AS_COLON | ASH_HEXF1 | AS_N2CHR | AS_NOXRF, - UAS_SELSG, - "PseudoSam by PseudoCode", - 0, - ps_headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".rs %s", // uninited arrays - ".equ", // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988 -//----------------------------------------------------------------------- -static const asm_t svasm = -{ - AS_COLON | ASH_HEXF4, - UAS_NOSEG, - "SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988", - 0, - NULL, // headers - "* = ", - ".END", - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "\\'", // special symbols in char and string constants - - ".BYTE", // ascii string directive - ".BYTE", // byte directive - ".WORD", // word directive -}; - -//----------------------------------------------------------------------- -// TASM assembler definiton -//----------------------------------------------------------------------- -static const asm_t tasm = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_NOENS | UAS_NOSEG, - "Table Driven Assembler (TASM) by Speech Technology Inc.", - 0, - NULL, // headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".text", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".block %s", // uninited arrays - ".equ", - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - "and", // and - "or", // or - NULL, // xor - "not", // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//----------------------------------------------------------------------- -// Avocet assembler definiton -//----------------------------------------------------------------------- -static const asm_t avocet = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_NOENS | UAS_NOSEG, - "Avocet Systems 2500AD 6502 Assembler", - 0, - NULL, // headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".fcc", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".ds %s", // uninited arrays -}; - -static const asm_t *const asms[] = -{ - &ca65asm, - - // 6502 asm_t; imported from the 6502 CPU module. - &svasm, - &tasm, - &pseudosam, - &avocet, - NULL -}; - -//----------------------------------------------------------------------- -#define FAMILY "MOS Technology 658xx series:" -static const char *const shnames[] = { "m65816", "m65c816", NULL }; -static const char *const lnames[] = { FAMILY"MOS Technology 65816", "MOS Technology 65C816", NULL }; - -static const uchar retcode_1[] = { 0x60 }; // RTS -static const uchar retcode_2[] = { 0x40 }; // RTI -static const uchar retcode_3[] = { 0x6b }; // RTL - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- - -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_65C816, // id - // flag - PR_SEGS - | PR_SEGTRANS, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Register names - qnumber(RegNames), // Number of registers - - rCs, // first segreg - rPB, // last segreg - 0, // size of a segment register - rCs, // number of CS register - rDs, // number of DS register - - NULL, // No known code start sequences - retcodes, - - 0, - M65816_last, - Instructions, // instruc - 3, // int tbyte_size; -- doesn't exist - - { 0, 0, 0, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - M65816_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; - diff --git a/idasdk75/module/78k0/78k0.hpp b/idasdk75/module/78k0/78k0.hpp deleted file mode 100644 index 9e8622f..0000000 --- a/idasdk75/module/78k0/78k0.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * NEC 78K0 processor module for IDA. - * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#ifndef _78K0_HPP -#define _78K0_HPP - -#include <ida.hpp> -#include <idp.hpp> - -#include "../idaidp.hpp" -#include "ins.hpp" -#include "../iohandler.hpp" - -struct nec78k0_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - bool flow = false; // stop flag - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit); - void N78K_header(outctx_t &ctx); - int N78K_emu(const insn_t &insn); - void handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn); - void N78K_segstart(outctx_t &ctx, segment_t *Sarea) const; - void N78K_footer(outctx_t &ctx) const; -}; -bool idaapi out_opnd(outctx_t &ctx, const op_t &x); - -// subtype of out format -#define FormOut specflag1 -//o_mem, o_near -#define FORM_OUT_VSK (0x01) -// o_mem, o_reg, o_near -#define FORM_OUT_SKOBA (0x02) -// o_reg -#define FORM_OUT_PLUS (0x04) -#define FORM_OUT_DISP (0x08) -#define FORM_OUT_REG (0x10) -// o_bit -#define FORM_OUT_HL (0x04) -#define FORM_OUT_PSW (0x08) -#define FORM_OUT_A (0x10) -#define FORM_OUT_SFR (0x20) -#define FORM_OUT_S_ADDR (0x40) -// o_reg -#define SecondReg specflag2 - -//bit operand -#define o_bit o_idpspec0 - -//------------------------------------------------------------------------ -enum N78K_registers { rX, rA, rC, rB, rE, rD, rL, rH, rAX, rBC, rDE, rHL, - rPSW, rSP, bCY, rRB0, rRB1, rRB2, rRB3, - rVcs, rVds }; - -//------------------------------------------------------------------------ -int idaapi N78K_ana(insn_t *_insn); -int idaapi N78K_emu(const insn_t &insn); - -#endif - diff --git a/idasdk75/module/78k0/ana.cpp b/idasdk75/module/78k0/ana.cpp deleted file mode 100644 index b2ea382..0000000 --- a/idasdk75/module/78k0/ana.cpp +++ /dev/null @@ -1,1491 +0,0 @@ -/* - * NEC 78K0 processor module for IDA. - * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "78k0.hpp" - -//---------------------------------------------------------------------- -inline uint32 Get_Data_16bits(insn_t &insn) -{ - uint32 low = insn.get_next_byte(); - uint32 high = insn.get_next_byte(); - return low | (high << 8); -} - -//---------------------------------------------------------------------- -inline void Operand_Sfr(insn_t &insn, op_t &x) -{ - x.type = o_mem; - x.dtype = dt_byte; - x.offb = (uchar)insn.size; - x.value = - x.addr = 0xFF00 + insn.get_next_byte(); -} - -//---------------------------------------------------------------------- -inline void Operand_Registr(op_t &x, int rReg, uchar Flags) -{ - x.type = o_reg; - x.reg = (uint16)rReg; - x.FormOut = Flags; -} - -//---------------------------------------------------------------------- -inline void Operand_Bit(op_t &x, uchar TypeOrd, int Bit) -{ - x.type = o_bit; - x.FormOut = TypeOrd; - x.value = Bit & 7; - x.offb = 0; -} - -//---------------------------------------------------------------------- -// convert short address to full address -inline uint32 GetFullAddress(uchar addr) -{ - if ( addr < 0x20 ) - return 0xFF00 + addr; - return 0xFE00 + addr; -} - -//---------------------------------------------------------------------- -inline void Operand_Saddr(op_t &x, uchar addr, const insn_t &insn) -{ - x.type = o_mem; - x.dtype = dt_byte; - x.offb = uchar(insn.size - 1); - x.addr = GetFullAddress(addr); - x.value = x.addr; -} - -//---------------------------------------------------------------------- -inline void Operand_Saddr1(insn_t &insn, op_t &x) -{ - Operand_Saddr(x, insn.get_next_byte(), insn); -} - -//---------------------------------------------------------------------- -inline void Operand_SaddrSP(insn_t &insn, op_t &x) -{ - uchar bt = insn.get_next_byte(); - if ( bt == 0x1C ) - { - Operand_Registr(x, rSP, 0); - } - else - { - Operand_Saddr(x, bt, insn); - x.dtype = dt_word; - } -} - -//---------------------------------------------------------------------- -inline void Operand_SaddrPSW(insn_t &insn, op_t &x) -{ - uchar bt = insn.get_next_byte(); - if ( bt == 0x1E ) - Operand_Registr(x, rPSW, 0); - else - Operand_Saddr(x, bt, insn); -} - -//---------------------------------------------------------------------- -inline void Operand_SA_Bit(insn_t &insn, op_t &x, uchar Bit) -{ - uchar bt; - x.offb = (uchar)insn.size; - x.type = o_bit; - x.dtype = dt_byte; - bt = insn.get_next_byte(); - if ( bt == 0x1E ) - { - x.FormOut = FORM_OUT_PSW; - } - else - { - x.addr = GetFullAddress(bt); - x.FormOut = FORM_OUT_S_ADDR; - } - x.value = Bit & 7; -} - -//---------------------------------------------------------------------- -inline void Operand_SFR_Bit(insn_t &insn, op_t &x, uchar Bit) -{ - x.offb = (uchar)insn.size; - x.addr = 0xFF00 + insn.get_next_byte(); - x.type = o_bit; - x.FormOut = FORM_OUT_SFR; - x.value = Bit & 7; -} - -//---------------------------------------------------------------------- -inline void Operand_Data_8bits(op_t &x, uchar Data) -{ - x.type = o_imm; - x.addr = Data; - x.value = Data; - x.dtype = dt_byte; -} - -//---------------------------------------------------------------------- -inline void Operand_Data_8bitsI(insn_t &insn, op_t &x) -{ - x.offb = (uchar)insn.size; - Operand_Data_8bits(x, insn.get_next_byte()); -} - -//---------------------------------------------------------------------- -inline void Operand_Data_16bitsI(insn_t &insn, op_t &x) -{ - x.type = o_imm; - x.dtype = dt_word; - x.offb = (uchar)insn.size; - x.value = Get_Data_16bits(insn); - x.addr = x.value; -} - -//---------------------------------------------------------------------- -inline void Operand_Addr16(op_t &x, uint32 Res, char Target_data_type) -{ - x.type = o_mem; - x.value = Res; - x.addr = Res; - x.dtype = Target_data_type; - x.FormOut = FORM_OUT_VSK; -} - -//---------------------------------------------------------------------- -inline void Operand_Addr16I(insn_t &insn, op_t &x, char Target_data_type) -{ - x.offb = (uchar)insn.size; - Operand_Addr16(x, Get_Data_16bits(insn),Target_data_type); -} - -//---------------------------------------------------------------------- -// [HL+XXX] -inline void Operand_HL_OffI(insn_t &insn, op_t &x) -{ - Operand_Registr(x, rHL, FORM_OUT_SKOBA | FORM_OUT_PLUS | FORM_OUT_DISP); - x.offb = (uchar)insn.size; - x.addr = x.value = insn.get_next_byte(); -} - -//---------------------------------------------------------------------- -// [HL+Reg] -inline void Operand_HL_OffReg(op_t &x, int rReg) -{ - Operand_Registr(x, rHL, FORM_OUT_SKOBA | FORM_OUT_PLUS | FORM_OUT_REG); - x.SecondReg = (uchar)rReg; -} - -//---------------------------------------------------------------------- -inline void Operand_NearByteI(insn_t &insn, op_t &x) -{ - x.type = o_near; - x.offb = (uchar)insn.size; - x.addr = insn.ip + (signed char)insn.get_next_byte(); - x.addr += insn.size; - x.value = x.addr; -} - -//---------------------------------------------------------------------- -static const uchar icode[16] = -{ - NEC_78K_0_add, NEC_78K_0_sub, NEC_78K_0_addc, - NEC_78K_0_subc, NEC_78K_0_cmp, NEC_78K_0_and, - NEC_78K_0_or, NEC_78K_0_xor, NEC_78K_0_xch -}; - -//---------------------------------------------------------------------- -static int Opcode_61(insn_t &insn) -{ - uchar code = insn.get_next_byte(); - uchar nib = (code >> 4) & 0xF; - uchar cd = code & 0xF; - - //sel RBx - // 11R1 R000 - if ( (code & 0xD7) == 0xD0 ) - { - insn.itype = NEC_78K_0_sel; - Operand_Registr(insn.Op1, - (rRB0 + ((code >>4) & 0x2)) | ((code>>3) & 0x1), - 0); - return insn.size; - } - if ( (code & 0x80) == 0 ) - { - //add A, r ( 0000 1RRR ) - //add r, A ( 0000 0RRR ) - //sub A, r ( 0001 1RRR ) - //sub r, A ( 0001 0RRR ) - //addc A, r ( 0010 1RRR ) - //addc r, A ( 0010 0RRR ) - //subc A, r ( 0011 1RRR ) - //subc r, A ( 0011 0RRR ) - //cmp A, r ( 0100 1RRR ) - //cmp r, A ( 0100 0RRR ) - //and A, r ( 0101 1RRR ) - //and r, A ( 0101 0RRR ) - //or A, r ( 0110 1RRR ) - //or r, A ( 0110 0RRR ) - //xor A, r ( 0111 1RRR ) - //xor r, A ( 0111 0RRR ) - insn.itype = icode[nib]; - if ( code & 0x8 ) - { - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, code & 0x7, 0); - } - else - { - Operand_Registr(insn.Op1, code & 0x7, 0); - Operand_Registr(insn.Op2, rA, 0); - } - return insn.size; - } - - switch ( code ) - { - //adjba ( 0110 0001 1000 0000 ) - case 0x80: - insn.itype = NEC_78K_0_adjba; - break; - //adjbs ( 0110 0001 1000 0000 ) - case 0x90: - insn.itype = NEC_78K_0_adjbs; - break; - default: - switch ( cd ) - { - //mov1 A.bit, CY - case 0x9: - insn.itype = NEC_78K_0_mov1; - Operand_Bit(insn.Op1, FORM_OUT_A, nib); - Operand_Registr(insn.Op2, bCY, 0); - break; - - case 0xA: - insn.itype = NEC_78K_0_set1; - Operand_Bit(insn.Op1, FORM_OUT_A, nib); - break; - - case 0xB: - insn.itype = NEC_78K_0_clr1; - Operand_Bit(insn.Op1, FORM_OUT_A, nib); - break; - - //mov1 CY, A.bit - case 0xC: - insn.itype = NEC_78K_0_mov1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_A, nib); - break; - case 0xD: - insn.itype = NEC_78K_0_and1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_A, nib); - break; - case 0xE: - insn.itype = NEC_78K_0_or1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_A, nib); - break; - case 0xF: - insn.itype = NEC_78K_0_xor1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_A, nib); - break; - default: - return 0; - } - } - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_71(insn_t &insn) -{ - uchar code = insn.get_next_byte(); - uchar nib = code >> 4; - // analyze the high bit by 1 - switch ( code & 0x8F ) - { - //mov1 [HL].bit, CY - case 0x81: - insn.itype = NEC_78K_0_mov1; - Operand_Bit(insn.Op1, FORM_OUT_HL, nib); - Operand_Registr(insn.Op2, bCY, 0); - break; - //set1 [HL].bit - case 0x82: - insn.itype = NEC_78K_0_set1; - Operand_Bit(insn.Op1, FORM_OUT_HL, nib); - break; - //clr1 [HL].bit - case 0x83: - insn.itype = NEC_78K_0_clr1; - Operand_Bit(insn.Op1, FORM_OUT_HL, nib); - break; - //mov1 CY,[HL].bit - case 0x84: - insn.itype = NEC_78K_0_mov1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_HL, nib); - break; - //and1 CY,[HL].bit - case 0x85: - insn.itype = NEC_78K_0_and1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_HL, nib); - break; - //or1 CY,[HL].bit - case 0x86: - insn.itype = NEC_78K_0_or1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_HL, nib); - break; - //xor1 CY,[HL].bit - case 0x87: - insn.itype = NEC_78K_0_xor1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_HL, nib); - break; - - //mov1 CY, A.bit - case 0x8C: - insn.itype = NEC_78K_0_mov1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_Bit(insn.Op2, FORM_OUT_A, nib); - break; - - case 0x0: - switch ( nib & 7 ) - { - case 0: insn.itype = NEC_78K_0_STOP; break; - case 1: insn.itype = NEC_78K_0_HALT; break; - default: return 0; - } - break; - //mov1 PSW.bit, CY - //mov1 saddr.bit, CY - case 0x1: - insn.itype = NEC_78K_0_mov1; - Operand_SA_Bit(insn, insn.Op1, nib); - Operand_Registr(insn.Op2, bCY, 0); - break; - //mov1 CY, saddr.bit - //mov1 CY, PSW.bit - case 0x4: - insn.itype = NEC_78K_0_mov1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_SA_Bit(insn, insn.Op2, nib); - break; - //and1 CY, saddr.bit - //and1 CY, PSW.bit - case 0x5: - insn.itype = NEC_78K_0_and1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_SA_Bit(insn, insn.Op2, nib); - break; - //or1 CY, addr.bit - //or1 CY, PSW.bit - case 0x6: - insn.itype = NEC_78K_0_or1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_SA_Bit(insn, insn.Op2, nib); - break; - //xor1 CY, addr.bit - //xor1 CY, PSW.bit - case 0x7: - insn.itype = NEC_78K_0_xor1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_SA_Bit(insn, insn.Op2, nib); - break; -//????? -// case 0x8: -// insn.itype = NEC_78K_0_EI; -// insn.get_next_byte(); -// break; - - //mov1 sfr.bit, CY - case 0x9: - insn.itype = NEC_78K_0_mov1; - Operand_SFR_Bit(insn, insn.Op1, nib); - Operand_Registr(insn.Op2, bCY, 0); - break; - //set1 sfr.bit - case 0xA: - insn.itype = NEC_78K_0_set1; - Operand_SFR_Bit(insn, insn.Op1, nib); - break; - //clr1 sfr.bit - case 0xB: - insn.itype = NEC_78K_0_clr1; - Operand_SFR_Bit(insn, insn.Op1, nib); - break; - - //and1 CY, sfr.bit - case 0xD: - insn.itype = NEC_78K_0_and1; - Operand_Registr(insn.Op1, bCY, 0); - Operand_SFR_Bit(insn, insn.Op2, nib); - break; - // bad instruction - default: - return 0; - } - return insn.size; -} -//---------------------------------------------------------------------- -static int Opcode_31(insn_t &insn) -{ - uchar code = insn.get_next_byte(); - uchar nib = (code >> 4) & 0xF; - switch ( code ) - { - case 0x0B://add A,[HL+B] ( 0000 1011 ) - case 0x1B://sub A,[HL+B] ( 0001 1011 ) - case 0x2B://addc A,[HL+B] ( 0010 1011 ) - case 0x3B://subc A,[HL+B] ( 0011 1011 ) - case 0x4B://cmp A,[HL+B] ( 0100 1011 ) - case 0x5B://and A,[HL+B] ( 0101 1011 ) - case 0x6B://or A,[HL+B] ( 0110 1011 ) - case 0x7B://xor A,[HL+B] ( 0111 1011 ) - case 0x8B://xch A,[HL+B] ( 1000 1011 ) - insn.itype = icode[nib]; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffReg(insn.Op2, rB); - break; - - case 0x0A://add A,[HL+C] ( 0000 1010 ) - case 0x1A://sub A,[HL+C] ( 0001 1010 ) - case 0x2A://addc A,[HL+C] ( 0010 1010 ) - case 0x3A://subc A,[HL+C] ( 0011 1010 ) - case 0x4A://cmp A,[HL+C] ( 0100 1010 ) - case 0x5A://and A,[HL+C] ( 0101 1010 ) - case 0x6A://or A,[HL+C] ( 0110 1010 ) - case 0x7A://xor A,[HL+C] ( 0111 1010 ) - case 0x8A://xch A,[HL+C] ( 1000 1010 ) - insn.itype = icode[nib]; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffReg(insn.Op2, rC); - break; - - case 0x98://br AX (0011 0001 1001 1000) - insn.itype = NEC_78K_0_br; - Operand_Registr(insn.Op1, rAX, 0); - break; - - case 0x88://mulu X ( 0011 0001 1000 1000) - insn.itype = NEC_78K_0_mulu; - Operand_Registr(insn.Op1, rX, 0); - break; - - case 0x82://divuw X ( 0011 0001 1000 0010) - insn.itype = NEC_78K_0_divuw; - Operand_Registr(insn.Op1, rC, 0); - break; - - case 0x90://ror4 [HL] ( 0011 0001 1001 0000) - insn.itype = NEC_78K_0_ror4; - Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); - break; - - case 0x80://rol4 [HL] ( 0011 0001 1000 0000) - insn.itype = NEC_78K_0_rol4; - Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); - break; - - default: - switch ( code & 0x8F ) - { - //sfr.bit, $addr16 - //A.bit, $addr16 - //PSW.bit,$addr16 - // 0xxx 0001 - case 0x1: - insn.itype = NEC_78K_0_btclr; - Operand_SA_Bit(insn, insn.Op1, nib); - Operand_NearByteI(insn, insn.Op2); - break; - - // 0xxx 0011 - case 0x3: - insn.itype = NEC_78K_0_bf; - Operand_SA_Bit(insn, insn.Op1, nib); - Operand_NearByteI(insn, insn.Op2); - break; - - // 0xxx 0101 - case 0x5: - insn.itype = NEC_78K_0_btclr; - Operand_SFR_Bit(insn, insn.Op1, nib); - Operand_NearByteI(insn, insn.Op2); - break; - // 0xxx 0110 - case 0x6: - insn.itype = NEC_78K_0_bt; - Operand_SFR_Bit(insn, insn.Op1, nib); - Operand_NearByteI(insn, insn.Op2); - break; - // 0xxx 0111 - case 0x7: - insn.itype = NEC_78K_0_bf; - Operand_SFR_Bit(insn, insn.Op1, nib); - Operand_NearByteI(insn, insn.Op2); - break; - - // 0xxx 1101 - case 0xD: - insn.itype = NEC_78K_0_btclr; - Operand_Bit(insn.Op1, FORM_OUT_A, nib); - Operand_NearByteI(insn, insn.Op2); - break; - - // 0xxx 1110 - case 0xE: - insn.itype = NEC_78K_0_bt; - Operand_Bit(insn.Op1, FORM_OUT_A, nib); - Operand_NearByteI(insn, insn.Op2); - break; - - // 0xxx 1111 - bf - case 0xF: - insn.itype = NEC_78K_0_bf; - Operand_Bit(insn.Op1, FORM_OUT_A, nib); - Operand_NearByteI(insn, insn.Op2); - break; - // 1xxx 01xx - //btclr - case 0x85: - insn.itype = NEC_78K_0_btclr; - Operand_Bit(insn.Op1, FORM_OUT_HL, nib); - Operand_NearByteI(insn, insn.Op2); - break; - //bt - case 0x86: - insn.itype = NEC_78K_0_bt; - Operand_Bit(insn.Op1, FORM_OUT_HL, nib); - Operand_NearByteI(insn, insn.Op2); - break; - //bf - case 0x87: - insn.itype = NEC_78K_0_bf; - Operand_Bit(insn.Op1, FORM_OUT_HL, nib); - Operand_NearByteI(insn, insn.Op2); - break; - - default: - return 0; - } - } - return insn.size; -} - -//---------------------------------------------------------------------- -int idaapi N78K_ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - uchar code = insn.get_next_byte(); - switch ( code ) - { - //nop ( 0000 0000 ) - case 0x00: - insn.itype = NEC_78K_0_nop; - break; - //not1 CY ( 0000 0001 ) - case 0x01: - insn.itype = NEC_78K_0_not1; - Operand_Registr(insn.Op1, bCY, 0); - break; - //movw AX,!addr16 ( 0000 0010) - case 0x02: - insn.itype = NEC_78K_0_movw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Addr16I(insn, insn.Op2, dt_word); - break; - //movw !addr16, AX ( 0000 0011) - case 0x03: - insn.itype = NEC_78K_0_movw; - Operand_Addr16I(insn, insn.Op1, dt_word); - Operand_Registr(insn.Op2, rAX, 0); - break; - //dbnz saddr,$addr16 (0000 0100) - case 0x04: - insn.itype = NEC_78K_0_dbnz; - Operand_Saddr1(insn, insn.Op1); - Operand_NearByteI(insn, insn.Op2); - break; - //xch A,[DE] ( 0000 0101 ) - case 0x05: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op1, rDE, FORM_OUT_SKOBA); - break; - // Bad command - case 0x06: - return 0; - //xch A,[HL] ( 0000 0111 ) - case 0x07: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); - break; - // add A, addr16 - case 0x08: - insn.itype = NEC_78K_0_add; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // add A, [HL+off] - case 0x09: - insn.itype = NEC_78K_0_add; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - //set1 saddr.bit (0xxx 1010) - //set1 PSW.bit (0xxx 1010) - case 0x0A: - case 0x1A: - case 0x2A: - case 0x3A: - case 0x4A: - case 0x5A: - case 0x6A: - case 0x7A: - insn.itype = NEC_78K_0_set1; - Operand_SA_Bit(insn, insn.Op1, code >> 4); - // convert set PSW.EI to EI - if ( code == 0x7A && insn.Op1.FormOut == FORM_OUT_PSW ) - { - insn.itype = NEC_78K_0_EI; - insn.Op1.type = o_void; - } - break; - //clr1 saddr.bit (0BBB 1011) - //clr1 PSW.bit (0BBB 1011) - case 0x0B: - case 0x1B: - case 0x2B: - case 0x3B: - case 0x4B: - case 0x5B: - case 0x6B: - case 0x7B: - insn.itype = NEC_78K_0_clr1; - Operand_SA_Bit(insn, insn.Op1, code >> 4); - // convert clr PSW.EI to DI - if ( code == 0x7B && insn.Op1.FormOut == FORM_OUT_PSW ) - { - insn.itype = NEC_78K_0_DI; - insn.Op1.type = o_void; - } - break; - //call11 (0x800-0xFFF) - case 0x0C: - case 0x1C: - case 0x2C: - case 0x3C: - case 0x4C: - case 0x5C: - case 0x6C: - case 0x7C: - insn.itype = NEC_78K_0_callf; - insn.Op1.type = o_near; - insn.Op1.addr = (uint32(( code & 0xF0 )<<8) | (uint32)insn.get_next_byte()) + 0x800; - insn.Op1.FormOut = FORM_OUT_VSK; - break; - // add A, #byte - case 0x0D: - insn.itype = NEC_78K_0_add; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // add A, saddr - case 0x0E: - insn.itype = NEC_78K_0_add; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // add A, [HL] - case 0x0F: - insn.itype = NEC_78K_0_add; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //movw rp,#word - case 0x10: - case 0x12: - case 0x14: - case 0x16: - insn.itype = NEC_78K_0_movw; - Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); - Operand_Data_16bitsI(insn, insn.Op2); - break; - //mov saddr,#byte ( 0001 0001 SADDR DATA) - //mov PSW,#byte ( 0001 0001 SADDR DATA) - case 0x11: - insn.itype = NEC_78K_0_mov; - Operand_SaddrPSW(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //case 0x12 - movw rp,#word - //mov sfr,#byte ( 0001 0011 SFR DATA) - case 0x13: - insn.itype = NEC_78K_0_mov; - Operand_Sfr(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //case 0x14 - movw rp,#word - // Bad Opcode - case 0x15: - return 0; - //case 0x16 - movw rp,#word - // Bad Opcode - case 0x17: - return 0; - // sub A, addr16 - case 0x18: - insn.itype = NEC_78K_0_sub; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // sub A, [HL+off] - case 0x19: - insn.itype = NEC_78K_0_sub; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // sub A, #byte - case 0x1D: - insn.itype = NEC_78K_0_sub; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // sub A, saddr - case 0x1E: - insn.itype = NEC_78K_0_sub; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // sub A, [HL] - case 0x1F: - insn.itype = NEC_78K_0_sub; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //set1 CY ( 0010 0000 ) - case 0x20: - insn.itype = NEC_78K_0_set1; - Operand_Registr(insn.Op1, bCY, 0); - break; - //clr1 CY ( 0010 0001 ) - case 0x21: - insn.itype = NEC_78K_0_clr1; - Operand_Registr(insn.Op1, bCY, 0); - break; - //push PSW ( 0010 0010 ) - case 0x22: - insn.itype = NEC_78K_0_push; - Operand_Registr(insn.Op1, rPSW, 0); - break; - //pop PSW ( 0010 0011 ) - case 0x23: - insn.itype = NEC_78K_0_pop; - Operand_Registr(insn.Op1, rPSW, 0); - break; - //ror A,1 ( 0010 0100 ) - case 0x24: - insn.itype = NEC_78K_0_ror; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bits(insn.Op2, 1); - break; - //rorc A,1 ( 0010 0101 ) - case 0x25: - insn.itype = NEC_78K_0_rorc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bits(insn.Op2, 1); - break; - //rol A,1 ( 0010 0110 ) - case 0x26: - insn.itype = NEC_78K_0_rol; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bits(insn.Op2, 1); - break; - //rolc A,1 ( 0010 0111 ) - case 0x27: - insn.itype = NEC_78K_0_rolc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bits(insn.Op2, 1); - break; - // addc A, addr16 - case 0x28: - insn.itype = NEC_78K_0_addc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // addc A, [HL+off] - case 0x29: - insn.itype = NEC_78K_0_addc; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // addc A, #byte - case 0x2D: - insn.itype = NEC_78K_0_addc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // addc A, saddr - case 0x2E: - insn.itype = NEC_78K_0_addc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // addc A, [HL] - case 0x2F: - insn.itype = NEC_78K_0_addc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //xch A, r (0011 0RRR) - case 0x30: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, code & 7, 0); - break; - //xxx A,[HL+B], xxx A,[HL+C] - case 0x31: - return Opcode_31(insn); - // subc A, addr16 - case 0x38: - insn.itype = NEC_78K_0_subc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // subc A, [HL+off] - case 0x39: - insn.itype = NEC_78K_0_subc; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // subc A, #byte - case 0x3D: - insn.itype = NEC_78K_0_subc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // subc A, saddr - case 0x3E: - insn.itype = NEC_78K_0_subc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // subc A, [HL] - case 0x3F: - insn.itype = NEC_78K_0_subc; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //inc r (0100 0RRR) - case 0x40: - case 0x41: - case 0x42: - case 0x43: - case 0x44: - case 0x45: - case 0x46: - case 0x47: - insn.itype = NEC_78K_0_inc; - Operand_Registr(insn.Op1, code & 7, 0); - break; - // cmp A, addr16 - case 0x48: - insn.itype = NEC_78K_0_cmp; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // cmp A, [HL+off] - case 0x49: - insn.itype = NEC_78K_0_cmp; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // cmp A, #byte - case 0x4D: - insn.itype = NEC_78K_0_cmp; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // cmp A, saddr - case 0x4E: - insn.itype = NEC_78K_0_cmp; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // cmp A, [HL] - case 0x4F: - insn.itype = NEC_78K_0_cmp; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //dec r (0101 0RRR) - case 0x50: - case 0x51: - case 0x52: - case 0x53: - case 0x54: - case 0x55: - case 0x56: - case 0x57: - insn.itype = NEC_78K_0_dec; - Operand_Registr(insn.Op1, code & 7, 0); - break; - // and A, addr16 - case 0x58: - insn.itype = NEC_78K_0_and; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // and A, [HL+off] - case 0x59: - insn.itype = NEC_78K_0_and; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // and A, #byte - case 0x5D: - insn.itype = NEC_78K_0_and; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // and A, saddr - case 0x5E: - insn.itype = NEC_78K_0_and; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // and A, [HL] - case 0x5F: - insn.itype = NEC_78K_0_and; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //mov A, r (0110 0RRR) - case 0x60: - case 0x62: - case 0x63: - case 0x64: - case 0x65: - case 0x66: - case 0x67: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, code & 7, 0); - break; - case 0x61: - return Opcode_61(insn); - // or A, addr16 - case 0x68: - insn.itype = NEC_78K_0_or; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // or A, [HL+off] - case 0x69: - insn.itype = NEC_78K_0_or; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // or A, #byte - case 0x6D: - insn.itype = NEC_78K_0_or; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // or A, saddr - case 0x6E: - insn.itype = NEC_78K_0_or; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // or A, [HL] - case 0x6F: - insn.itype = NEC_78K_0_or; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - // mov r, A (0111 0RRR) - case 0x70: - case 0x72: - case 0x73: - case 0x74: - case 0x75: - case 0x76: - case 0x77: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, code & 7, 0); - Operand_Registr(insn.Op2, rA, 0); - break; - case 0x71: - return Opcode_71(insn); - // xor A, addr16 - case 0x78: - insn.itype = NEC_78K_0_xor; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - // xor A, [HL+off] - case 0x79: - insn.itype = NEC_78K_0_xor; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - // xor A, #byte - case 0x7D: - insn.itype = NEC_78K_0_xor; - Operand_Registr(insn.Op1, rA, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // xor A, saddr - case 0x7E: - insn.itype = NEC_78K_0_xor; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - // xor A, [HL] - case 0x7F: - insn.itype = NEC_78K_0_xor; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - //incw rp (1000 0PP0) - case 0x80: - case 0x82: - case 0x84: - case 0x86: - insn.itype = NEC_78K_0_incw; - Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); - break; - //inc saddr ( 1000 0001 SADDR) - case 0x81: - insn.itype = NEC_78K_0_inc; - Operand_Saddr1(insn, insn.Op1); - break; - //xch A, saddr ( 1000 0011 SADDR ) - case 0x83: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_Saddr1(insn, insn.Op2); - break; - //mov A,[DE] ( 1000 0101) - case 0x85: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rDE, FORM_OUT_SKOBA); - break; - //mov A,[HL] ( 1000 0111) - case 0x87: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); - break; - // add saddr, #byte - case 0x88: - insn.itype = NEC_78K_0_add; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //movw AX, SP ( 1000 1001 0001 1100 ) - //movw AX, SADDRP ( 1000 1001 SADDRP ) - case 0x89: - insn.itype = NEC_78K_0_movw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_SaddrSP(insn, insn.Op2); - break; - //dbnz C,$addr16 (1000 1010 JDISP ) - case 0x8A: - insn.itype = NEC_78K_0_dbnz; - Operand_Registr(insn.Op1, rC, 0); - Operand_NearByteI(insn, insn.Op2); - break; - //dbnz B,$addr16 (1000 1011 JDISP ) - case 0x8B: - insn.itype = NEC_78K_0_dbnz; - Operand_Registr(insn.Op1, rB, 0); - Operand_NearByteI(insn, insn.Op2); - break; - //bt xxxxxxxx - case 0x8C: - case 0x9C: - case 0xAC: - case 0xBC: - case 0xCC: - case 0xDC: - case 0xEC: - case 0xFC: - insn.itype = NEC_78K_0_bt; - Operand_SA_Bit(insn, insn.Op1, code >> 4); - Operand_NearByteI(insn, insn.Op2); - break; - //bc $addr16 (1000 1101 JDISP ) - case 0x8D: - insn.itype = NEC_78K_0_bc; - Operand_NearByteI(insn, insn.Op1); - break; - //mov A,!addr16 ( 1000 1110 LOW HIGH) - case 0x8E: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - //ret ( 1000 1111 ) - case 0x8F: - insn.itype = NEC_78K_0_reti; - break; - // decw - case 0x90: - case 0x92: - case 0x94: - case 0x96: - insn.itype = NEC_78K_0_decw; - Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); - break; - //dec saddr ( 1001 0001 SADDR) - case 0x91: - insn.itype = NEC_78K_0_dec; - Operand_Saddr1(insn, insn.Op1); - break; - //xch A, sfr ( 1001 0011 SFR ) - case 0x93: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_Sfr(insn, insn.Op2); - break; - //mov [DE], A ( 1001 0101) - case 0x95: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rDE, FORM_OUT_SKOBA); - Operand_Registr(insn.Op2, rA, 0); - break; - - //mov [HL], A ( 1001 0111) - case 0x97: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); - Operand_Registr(insn.Op2, rA, 0); - break; - // sub saddr, #byte - case 0x98: - insn.itype = NEC_78K_0_sub; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //movw SP, AX ( 1001 1001 0001 1100 ) - //movw SADDRP, AX ( 1001 1001 SADDRP ) - case 0x99: - insn.itype = NEC_78K_0_movw; - Operand_SaddrSP(insn, insn.Op1); - Operand_Registr(insn.Op2, rAX, 0); - break; - //call !addr16 ( 1001 1010 LOW HIGH ) - case 0x9A: - insn.itype = NEC_78K_0_call; - insn.Op1.FormOut = FORM_OUT_VSK;// outputting char '!' - insn.Op1.type = o_near; - insn.Op1.dtype = dt_word; - insn.Op1.offb = (uchar)insn.size; - insn.Op1.addr = Get_Data_16bits(insn); - break; - //br !addr16 (1111 1011 LOW HIGH) - case 0x9B: - insn.itype = NEC_78K_0_br; - insn.Op1.FormOut = FORM_OUT_VSK; - insn.Op1.type = o_near; - insn.Op1.dtype = dt_word; - insn.Op1.offb = (uchar)insn.size; - insn.Op1.value = - insn.Op1.addr = Get_Data_16bits(insn); - break; - // case 9C - bt - //bnc $addr16 (1001 1101 JDISP ) - case 0x9D: - insn.itype = NEC_78K_0_bnc; - Operand_NearByteI(insn, insn.Op1); - break; - //mov !addr16, A ( 1001 1110 LOW HIGH) - case 0x9E: - insn.itype = NEC_78K_0_mov; - Operand_Addr16I(insn, insn.Op1, dt_byte); - Operand_Registr(insn.Op2, rA, 0); - break; - //retb ( 1001 1111 ) - case 0x9F: - insn.itype = NEC_78K_0_retb; - break; - //mov r,#byte (1010 0RRR) - case 0xA0: - case 0xA1: - case 0xA2: - case 0xA3: - case 0xA4: - case 0xA5: - case 0xA6: - case 0xA7: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, code & 7, 0); - Operand_Data_8bitsI(insn, insn.Op2); - break; - // addc saddr, #byte - case 0xA8: - insn.itype = NEC_78K_0_addc; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //movw AX, SFR ( 1010 1001 SFR ) - case 0xA9: - insn.itype = NEC_78K_0_movw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Sfr(insn, insn.Op2); - break; - //mov A,[HL+C] ( 1010 1010) - case 0xAA: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffReg(insn.Op2, rC); - break; - //mov A,[HL+B] ( 1010 1011) - case 0xAB: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffReg(insn.Op2, rB); - break; - // case 0xAC - bt - //bz $addr16 (1010 1101 JDISP ) - case 0xAD: - insn.itype = NEC_78K_0_bz; - Operand_NearByteI(insn, insn.Op1); - break; - //mov A,[HL+byte] ( 1010 1110) - case 0xAE: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - //ret ( 1010 1111 ) - case 0xAF: - insn.itype = NEC_78K_0_ret; - break; - // pop - case 0xB0: - case 0xB2: - case 0xB4: - case 0xB6: - insn.itype=NEC_78K_0_pop; - Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); - break; - // Push - case 0xB1: - case 0xB3: - case 0xB5: - case 0xB7: - insn.itype=NEC_78K_0_push; - Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); - break; - // subc saddr, #byte - case 0xB8: - insn.itype = NEC_78K_0_subc; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //movw SFR, AX ( 1011 1001 SFR ) - case 0xB9: - insn.itype = NEC_78K_0_movw; - Operand_Sfr(insn, insn.Op1); - Operand_Registr(insn.Op2, rAX, 0); - break; - //mov [HL+B], A ( 1011 1010) - case 0xBA: - insn.itype = NEC_78K_0_mov; - Operand_HL_OffReg(insn.Op1, rC); - Operand_Registr(insn.Op2, rA, 0); - break; - //mov [HL+B], A ( 1011 1011) - case 0xBB: - insn.itype = NEC_78K_0_mov; - Operand_HL_OffReg(insn.Op1, rB); - Operand_Registr(insn.Op2, rA, 0); - break; - // case 0xBC - bt - //bnz $addr16 (1011 1101 JDISP ) - case 0xBD: - insn.itype = NEC_78K_0_bnz; - Operand_NearByteI(insn, insn.Op1); - break; - //mov [HL+byte], A ( 1011 1110) - case 0xBE: - insn.itype = NEC_78K_0_mov; - Operand_HL_OffI(insn, insn.Op1); - Operand_Registr(insn.Op2, rA, 0); - break; - //brk ( 1011 1111 ) - case 0xBF: - insn.itype = NEC_78K_0_brk; - break; - //movw AX, rp (1100 0PP0) - case 0xC0: - case 0xC2: - case 0xC4: - case 0xC6: - insn.itype = NEC_78K_0_movw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Registr(insn.Op2, rAX+((code>>1)&7), 0); - break; - // cmp saddr, #byte - case 0xC8: - insn.itype = NEC_78K_0_cmp; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //addw AX,#word ( 1100 1010 LOW HIGH) - case 0xCA: - insn.itype = NEC_78K_0_addw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Data_16bitsI(insn, insn.Op2); - break; - // case 0xCC - bt - //xch A,!addr ( 1100 1110 LOW HIGH ) - case 0xCE: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_Addr16I(insn, insn.Op2, dt_byte); - break; - //movw rp, AX (1101 0PP0) - case 0xD0: - case 0xD2: - case 0xD4: - case 0xD6: - insn.itype = NEC_78K_0_movw; - Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); - Operand_Registr(insn.Op2, rAX, 0); - break; - // and saddr, #byte - case 0xD8: - insn.itype = NEC_78K_0_and; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //subw AX,#word ( 1101 1010 LOW HIGH) - case 0xDA: - insn.itype = NEC_78K_0_subw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Data_16bitsI(insn, insn.Op2); - break; - // case 0xDC - bt - //xch A,[HL+byte] ( 1101 1110 DATA ) - case 0xDE: - insn.itype = NEC_78K_0_xch; - Operand_Registr(insn.Op1, rA, 0); - Operand_HL_OffI(insn, insn.Op2); - break; - //xchw AX, rp (1101 0PP0) - case 0xE0: - case 0xE2: - case 0xE4: - case 0xE6: - insn.itype = NEC_78K_0_xchw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Registr(insn.Op2, rAX+((code>>1)&7), 0); - break; - // or saddr, #byte - case 0xE8: - insn.itype = NEC_78K_0_or; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //cmpw AX,#word ( 1110 1010 LOW HIGH) - case 0xEA: - insn.itype = NEC_78K_0_cmpw; - Operand_Registr(insn.Op1, rAX, 0); - Operand_Data_16bitsI(insn, insn.Op2); - break; - // case 0xEC - bt - //movw SP,#word ( 1110 1110 0001 1100 LOW HIGH) - //movw saddrp,#word ( 1110 1110 SADDR LOW HIGH) - case 0xEE: - insn.itype = NEC_78K_0_movw; - Operand_SaddrSP(insn, insn.Op1); - Operand_Data_16bitsI(insn, insn.Op2); - break; - //mov A, saddr ( 1111 0000 A SADDRR ) - //mov A, PSW ( 1111 0000 A PSW ) - case 0xF0: - insn.itype = NEC_78K_0_mov; - Operand_SaddrPSW(insn, insn.Op2); - Operand_Registr(insn.Op1, rA, 0); - break; - //mov saddr, A ( 1111 0010 SADDRR A) - //mov PSW, A ( 1111 0010 SADDRR A) - case 0xF2: - insn.itype = NEC_78K_0_mov; - Operand_SaddrPSW(insn, insn.Op1); - Operand_Registr(insn.Op2, rA, 0); - break; - //mov A, sfr ( 1111 0100 A SFR ) - case 0xF4: - insn.itype = NEC_78K_0_mov; - Operand_Registr(insn.Op1, rA, 0); - Operand_Sfr(insn, insn.Op2); - break; - //mov saddr, A ( 1111 0110 SFR A) - case 0xF6: - insn.itype = NEC_78K_0_mov; - Operand_Sfr(insn, insn.Op1); - Operand_Registr(insn.Op2, rA, 0); - break; - // xor saddr, #byte - case 0xF8: - insn.itype = NEC_78K_0_xor; - Operand_Saddr1(insn, insn.Op1); - Operand_Data_8bitsI(insn, insn.Op2); - break; - //br $addr16 (1111 01010 JDISP) - case 0xFA: - insn.itype = NEC_78K_0_br; - Operand_NearByteI(insn, insn.Op1); - break; - // case 0xFC - bt - //movw sfr,#word ( 1111 1110 SFR LOW HIGH) - case 0xFE: - insn.itype = NEC_78K_0_movw; - Operand_Sfr(insn, insn.Op1); - Operand_Data_16bitsI(insn, insn.Op2); - break; - // callt - case 0xC1:case 0xC3:case 0xC5:case 0xC7:case 0xC9:case 0xCB:case 0xCD:case 0xCF: - case 0xD1:case 0xD3:case 0xD5:case 0xD7:case 0xD9:case 0xDB:case 0xDD:case 0xDF: - case 0xE1:case 0xE3:case 0xE5:case 0xE7:case 0xE9:case 0xEB:case 0xED:case 0xEF: - case 0xF1:case 0xF3:case 0xF5:case 0xF7:case 0xF9:case 0xFB:case 0xFD:case 0xFF: - insn.itype = NEC_78K_0_callt; - Operand_Addr16(insn.Op1,0x40 + (code & 0x3E), dt_word); - // change format - insn.Op1.FormOut = FORM_OUT_SKOBA; - break; - // unknown code - return error - default: - return 0; - } - return insn.size; -} diff --git a/idasdk75/module/78k0/emu.cpp b/idasdk75/module/78k0/emu.cpp deleted file mode 100644 index 393200c..0000000 --- a/idasdk75/module/78k0/emu.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * NEC 78K0 processor module for IDA. - * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "78k0.hpp" - -//---------------------------------------------------------------------- -// usage/change of operands -void nec78k0_t::handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn) -{ - ea_t ea = map_code_ea(insn, x.addr, x.n); - ea_t ev = map_code_ea(insn, x.value, x.n); - switch ( x.type ) - { - // unused! - case o_void: - break; - - case o_reg: - if ( forced_op ) - break; - if ( is_off(get_flags(insn.ea), x.n) ) - insn.add_dref(ev, x.n, dr_O); - break; - - case o_imm: // immediate can't be changed - if ( !isload ) - goto badTouch; - // set immediate flag - set_immd(insn.ea); - // if not forced and not offset - if ( !forced_op && is_off(get_flags(insn.ea), x.n) ) - insn.add_dref(ev, x.offb, dr_O); // it's an offset! - break; - - case o_mem: - insn.create_op_data(ea, x); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - break; - - - case o_near:// a call or jump - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - // add a code xref - insn.add_cref(ea, x.offb, fl_CN); - flow = func_does_return(ea); - } - else - { - insn.add_cref(ea, x.offb, fl_JN); - } - break; - - case o_bit: - switch ( x.FormOut ) - { - case FORM_OUT_S_ADDR: - case FORM_OUT_SFR: - insn.create_op_data(ea, x); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - break; - } - break; - // other - show a warning - default: -badTouch: - warning("%a %s,%d: bad optype %d", - insn.ea, insn.get_canon_mnem(ph), - x.n, x.type); - break; - } -} - - -//---------------------------------------------------------------------- -// emulator -int nec78k0_t::N78K_emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - // get operand types - int flag1 = is_forced_operand(insn.ea, 0); - int flag2 = is_forced_operand(insn.ea, 1); - - flow = (Feature & CF_STOP) == 0; - - // handle xrefs for the two operands - if ( Feature & CF_USE1) handle_operand(insn.Op1, flag1, 1, insn); - if ( Feature & CF_USE2) handle_operand(insn.Op2, flag2, 1, insn); - // add xref to the queue - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - // handle changing operands - if ( Feature & CF_CHG1) handle_operand(insn.Op1, flag1, 0, insn); - if ( Feature & CF_CHG2) handle_operand(insn.Op2, flag2, 0, insn); - // if not stop, continue with the next instruction - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - return 1; -} diff --git a/idasdk75/module/78k0/makefile b/idasdk75/module/78k0/makefile deleted file mode 100644 index 22a9807..0000000 --- a/idasdk75/module/78k0/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=78k0 -CONFIGS=78k0.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k0.hpp ana.cpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k0.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k0.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k0.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp 78k0.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/78k0/reg.cpp b/idasdk75/module/78k0/reg.cpp deleted file mode 100644 index d797adc..0000000 --- a/idasdk75/module/78k0/reg.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/* - * NEC 78K0 processor module for IDA. - * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "78k0.hpp" -#include <diskio.hpp> -#include <segregs.hpp> - -//---------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "X", "A", "C", "B", "E", "D", "L", "H", "AX", "BC", "DE","HL", - "PSW", "SP", "CY", "RB0", "RB1", "RB2", "RB3", - "cs", "ds" -}; - -//---------------------------------------------------------------------- -static const asm_t nec78k0 = -{ - AS_COLON | ASB_BINF4 | AS_N2CHR, - 0, - "NEC 78K0 Assembler", - 0, - NULL, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".dw", // word directive - ".dd", // no double words - NULL, // no qwords - NULL, // oword (16 bytes) - NULL, // no float - NULL, // no double - NULL, // no tbytes - NULL, // no packreal - "#d dup(#v)", //".db.#s(b,w) #d,#v", // #h - header(.byte,.word) - // #d - size of array - // #v - value of array elements - // #s - size specifier - ".rs %s",// uninited data (reserve space) - ".equ", - NULL, // seg prefix - "$", // a_curip - - NULL, // returns function header line - NULL, // returns function footer line - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - - '(', ')',// lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//---------------------------------------------------------------------- -#define FAMILY "NEC series:" -static const char *const shnames[] = -{ - "78k0", - NULL -}; -static const char *const lnames[] = -{ - FAMILY"NEC 78K0", - NULL -}; - -static const asm_t *const asms[] = -{ - &nec78k0, - NULL -}; - -//-------------------------------------------------------------------------- -static const uchar retcNEC78K0_0[] = { 0xAF }; //ret -static const uchar retcNEC78K0_1[] = { 0x9F }; //retb -static const uchar retcNEC78K0_2[] = { 0x8F }; //reti -static const uchar retcNEC78K0_3[] = { 0xBF }; //brk -static const bytes_t retcodes[] = -{ - { sizeof(retcNEC78K0_0), retcNEC78K0_0 }, - { sizeof(retcNEC78K0_1), retcNEC78K0_1 }, - { sizeof(retcNEC78K0_2), retcNEC78K0_2 }, - { sizeof(retcNEC78K0_3), retcNEC78K0_3 }, - { 0, NULL } -}; - - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new nec78k0_t); - return 0; -} - -//------------------------------------------------------------------ -bool nec78k0_t::nec_find_ioport_bit(outctx_t &ctx, int port, int bit) -{ - - const ioport_bit_t *b = find_ioport_bit(ioh.ports, port, bit); - if ( b != NULL && !b->name.empty() ) - { - ctx.out_line(b->name.c_str(), COLOR_IMPNAME); - return true; - } - return false; -} - -//---------------------------------------------------------------------- - -void set_dopolnit_info(void) -{ - for ( int banknum = 0; banknum < 4; banknum++ ) - { - for ( int Regs = 0; Regs < 8; Regs++ ) - { - char temp[100]; - qsnprintf(temp, sizeof(temp), "Bank%d_%s", banknum, RegNames[Regs]); - ushort Addr = ushort(0xFEE0+((banknum*8)+Regs)); - set_name(Addr, temp); - qsnprintf(temp, sizeof(temp), "Internal high-speed RAM (Bank %d registr %s)", banknum, RegNames[Regs]); - set_cmt(Addr, temp, true); - } - } -} - -//---------------------------------------------------------------------- -ssize_t idaapi nec78k0_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - inf_set_be(false); - inf_set_gen_lzero(true); - helper.create("$ 78k0"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - { - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - set_dopolnit_info(); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - N78K_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - N78K_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - N78K_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return N78K_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return N78K_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_NEC_78K0, - // flag - PRN_HEX - | PR_SEGTRANS - | PR_SEGS, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs, rVds, - 2, // size of a segment register - rVcs, rVds, - NULL, - retcodes, - 0, NEC_78K_0_last, - Instructions, // instruc - 3, - { 0,0,0,0 }, - 0, - NULL, // micro virtual mashine -}; diff --git a/idasdk75/module/78k0s/78k_0s.hpp b/idasdk75/module/78k0s/78k_0s.hpp deleted file mode 100644 index 0e8d46a..0000000 --- a/idasdk75/module/78k0s/78k_0s.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _NEC78K0S_HPP -#define _NEC78K0S_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include "../iohandler.hpp" - -struct nec78k0s_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit); - void nec78k0s_header(outctx_t &ctx); - int emu(const insn_t &insn); - void handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn); - void nec78k0s_footer(outctx_t &ctx) const; -}; -bool idaapi out_opnd(outctx_t &ctx, const op_t &x); - -#define UAS_NOSPA 0x0001 // no space after comma -//#define UAS_ZVBIT 0x0002 // '*' prefixes name in bit command -//#define UAS_AREAS 0x0004 // '.area' segment directive -//#define UAS_CCR 0x0008 // "ccr" register is named "cc" -// // "dpr" register is named "dp" -// // "pcr" register is named "pc" -//#define UAS_ORA 0x0010 // ORAA is named ORA -// // ORAB is named ORB -//#define UAS_CODE 0x0020 // "code", "data", "bss" directives -//#define UAS_AUTOPC 0x0040 // Automatic relative addressing by PC -// // (no need to substract PC value) -//#define UAS_ALL 0x0080 // "all" keyword is recognized as -// // a synonim for all registers -//#define UAS_OS9 0x0100 // has OS9 directive -//---------------------------------------------------------------------- -// Redefine temporary names -// -#define exten segpref -#define xmode specflag1 -#define prepost specflag2 -#define addr16 specflag3 - -//bit operand -#define regmode specflag1 -#define regdata specflag2 - -//callt -#define form specflag1 - -#define o_bit o_idpspec0 -//------------------------------------------------------------------------ -enum nec_registers { rX, rA, rC, rB, rE, rD, rL, rH, rAX, rBC, rDE, rHL, - rPSW, rSP, rS, rCC, rDPR, - bCY, - Rcs, Rds }; - -enum bitOper { SADDR=0, SFR, A, PSW, HL, CY }; -//------------------------------------------------------------------------ -extern qstring deviceparams; -extern qstring device; - -struct ioport_bit_t; -bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit); -uint32 Get_Data_16bits(); -//------------------------------------------------------------------------ -void idaapi nec78k0s_header(outctx_t &ctx); -void idaapi nec78k0s_footer(outctx_t &ctx); - -void idaapi nec78k0s_segstart(outctx_t &ctx, segment_t *seg); - -int idaapi ana(insn_t *_insn); -int idaapi emu(const insn_t &insn); - - -#endif - diff --git a/idasdk75/module/78k0s/ana.cpp b/idasdk75/module/78k0s/ana.cpp deleted file mode 100644 index eeacb29..0000000 --- a/idasdk75/module/78k0s/ana.cpp +++ /dev/null @@ -1,1710 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "78k_0s.hpp" - -//---------------------------------------------------------------------- -inline uint32 sfr(uchar sfr_offset) -{ - return 0xFF00 + sfr_offset; -} -//---------------------------------------------------------------------- -inline uint32 saddr(uchar Saddr_offset) -{ - if ( Saddr_offset < 0x20 ) - return 0xFF00 + Saddr_offset; - else - return 0xFE00 + Saddr_offset; -} - -//---------------------------------------------------------------------- -inline void addr16(insn_t &insn, op_t &x) -{ - //x.offb = insn.size; - uint32 low = insn.get_next_byte(); - uint32 high = insn.get_next_byte(); - - //x.type = o_near; - x.addr = low | (high << 8); - x.addr16 = 1; -} - -//---------------------------------------------------------------------- -inline void jdisp(op_t &x, uchar addr, int previons_len, const insn_t &insn) -{ - x.type = o_near; - x.addr = insn.ip + (signed char)addr + previons_len; - //x.offb = insn.size - 1; -} - -//---------------------------------------------------------------------- -inline void imm16(insn_t &insn, op_t &x) -{ - x.type = o_imm; - x.dtype = dt_word; - uchar b1 = insn.get_next_byte(); - uchar b2 = insn.get_next_byte(); - x.value = b1 | (b2<<8); -} - -//---------------------------------------------------------------------- -int idaapi ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - - // get one byte - uchar code = insn.get_next_byte(); - - switch ( code ) - { - // Mnemonic Operand Instruction Code - // B1 B2 B3 B4 - case 0x00: - //ROR A, 1 0000 0000 - insn.itype = NEC_78K_0S_ror; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = 1; - insn.Op2.regmode = 1; - break; - - case 0x02: - //RORC A, 1 0000 0010 - insn.itype = NEC_78K_0S_rorc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = 1; - insn.Op2.regmode = 1; - break; - - case 0x04: - //CLR1 CY 0000 0100 - insn.itype = NEC_78K_0S_clr1; - insn.Op1.type = o_phrase; - insn.Op1.reg = bCY; - break; - - case 0x05: - //XCH A, saddr 0000 0101 Saddr-offset - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x06: - //NOT1 CY 0000 0110 - insn.itype = NEC_78K_0S_not1; - insn.Op1.type = o_phrase; - insn.Op1.reg = bCY; - break; - - case 0x07: - //XCH A, sfr 0000 0111 Sfr-offset - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = sfr(insn.get_next_byte()); - break; - - case 0x08: - //NOP 0000 1000 - insn.itype = NEC_78K_0S_nop; - break; - - case 0x0A: // All 0x0A commands - { - uchar code2 = insn.get_next_byte(); - switch ( code2 ) - { - case 0x88: - case 0x98: - case 0xA8: - case 0xB8: - case 0xC8: - case 0xD8: - case 0xE8: - case 0xF8: - //BT saddr.bit, $addr16 0000 1010 1 B2 B1 B0 1000 Saddr-offset jdisp - insn.itype = NEC_78K_0S_bt; - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op1.value = (code2>>4) & 0x07; - jdisp(insn.Op2, insn.get_next_byte(), 4, insn); - break; - - case 0x84: - case 0x94: - case 0xA4: - case 0xB4: - case 0xC4: - case 0xD4: - case 0xE4: - case 0xF4: - { - //BT sfr.bit, $addr16 0000 1010 1 B2 B1 B0 0100 Sfr-offset jdisp - //BT PSW.bit, $addr16 0000 1010 1 B2 B1 B0 1000 0001 1110 jdisp - insn.itype = NEC_78K_0S_bt; - uchar code3 = insn.get_next_byte(); - if ( code3 == 0x1E ) - { - insn.Op1.type = o_bit; - insn.Op1.reg = rPSW; - insn.Op1.value = (code2>>4)&0x07; - jdisp(insn.Op2, code3, 4, insn); - } - else - { - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = sfr(code3); - insn.Op1.value = (code2>>4) & 0x07; - jdisp(insn.Op2, insn.get_next_byte(), 4, insn); - } - } - break; - - case 0x08: - case 0x18: - case 0x28: - case 0x38: - case 0x48: - case 0x58: - case 0x68: - case 0x78: - { - //BF saddr.bit, $addr16 0000 1010 0 B2 B1 B0 1000 Saddr-offset jdisp - //BF PSW.bit, $addr16 0000 1010 0 B2 B1 B0 1000 0001 1110 jdisp - insn.itype = NEC_78K_0S_bf; - uchar code3=insn.get_next_byte(); - if ( code3 == 0x1E ) - { - insn.Op1.type = o_bit; - insn.Op1.reg = rPSW; - insn.Op1.value = (code2>>4)&0x07; - jdisp(insn.Op2, insn.get_next_byte(), 4, insn); - } - else - { - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(code3); - insn.Op1.value = (code2>>4) & 0x07; - jdisp(insn.Op2, insn.get_next_byte(), 4, insn); - } - } - break; - - case 0x04: - case 0x14: - case 0x24: - case 0x34: - case 0x44: - case 0x54: - case 0x64: - case 0x74: - //BF sfr.bit, $addr16 0000 1010 0 B2 B1 B0 0100 Sfr-offset jdisp - insn.itype = NEC_78K_0S_bf; - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = sfr(insn.get_next_byte()); - insn.Op1.value = (code2>>4) & 0x07; - jdisp(insn.Op2, insn.get_next_byte(), 4, insn); - break; - - case 0x00: - case 0x10: - case 0x20: - case 0x30: - case 0x40: - case 0x50: - case 0x60: - case 0x70: - //BF A.bit, $addr16 0000 1010 0 B2 B1 B0 0000 jdisp - insn.itype = NEC_78K_0S_bf; - insn.Op1.type = o_bit; - insn.Op1.reg = rA; - insn.Op1.value = (code2>>4) & 0x07; - jdisp(insn.Op2, insn.get_next_byte(), 3, insn); - break; - - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - case 0xC0: - case 0xD0: - case 0xE0: - case 0xF0: - //BT A.bit, $addr16 0000 1010 1 B2 B1 B0 0000 jdisp - insn.itype = NEC_78K_0S_bt; - insn.Op1.type = o_bit; - insn.Op1.reg = rA; - insn.Op1.value = (code2>>4) & 0x07; - jdisp(insn.Op2, insn.get_next_byte(), 3, insn); - break; - - case 0x0A: - case 0x1A: - case 0x2A: - case 0x3A: - case 0x4A: - case 0x5A: - case 0x6A: - case 0x7A: - { - //SET1 saddr.bit 0000 1010 0 B2 B1 B0 1010 Saddr-offset - //SET1 PSW.bit 0000 1010 0 B2 B1 B0 1010 0001 1110 - //EI 0000 1010 0 1 1 1 1010 0001 1110 - uchar code3 = insn.get_next_byte(); - if ( code3 == 0x1E ) - { - if ( code2 == 0x7A ) //EI - { - insn.itype = NEC_78K_0S_EI; - } - else //SET1 PSW.bit - { - insn.itype = NEC_78K_0S_set1; - insn.Op1.type = o_bit; - insn.Op1.reg = rPSW; - insn.Op1.value = (code2>>4)&0x07; - } - } - else //SET1 saddr.bit - { - insn.itype = NEC_78K_0S_set1; - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(code3); - insn.Op1.value = (code2>>4)&0x07; - } - } - break; - - case 0x06: - case 0x16: - case 0x26: - case 0x36: - case 0x46: - case 0x56: - case 0x66: - case 0x76: - //SET1 sfr.bit 0000 1010 0 B2 B1 B0 0110 Sfr-offset - insn.itype = NEC_78K_0S_set1; - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = sfr(insn.get_next_byte()); - insn.Op1.value = (code2>>4)&0x07; - break; - - case 0x02: - case 0x12: - case 0x22: - case 0x32: - case 0x42: - case 0x52: - case 0x62: - case 0x72: - //SET1 A.bit 0000 1010 0 B2 B1 B0 0010 - insn.itype = NEC_78K_0S_set1; - insn.Op1.type = o_bit; - insn.Op1.reg = rA; - insn.Op1.value = (code2>>4)&0x07; - break; - - case 0x0E: - case 0x1E: - case 0x2E: - case 0x3E: - case 0x4E: - case 0x5E: - case 0x6E: - case 0x7E: - //SET1 [HL].bit 0000 1010 0 B2 B1 B0 1110 - insn.itype = NEC_78K_0S_set1; - insn.Op1.type = o_bit; - insn.Op1.reg = rHL; - insn.Op1.prepost = 1; - insn.Op1.value = (code2>>4)&0x07; - break; - - case 0x8A: - case 0x9A: - case 0xAA: - case 0xBA: - case 0xCA: - case 0xDA: - case 0xEA: - case 0xFA: - { - //CLR1 saddr.bit 0000 1010 1 B2 B1 B0 1010 Saddr-offset - //CLR1 PSW.bit 0000 1010 1 B2 B1 B0 1010 0001 1110 - //DI 0000 1010 1 1 1 1 1010 0001 1110 - uchar code3 = insn.get_next_byte(); - if ( code3 == 0x1E ) - { - if ( code2 == 0xFA ) //DI - { - insn.itype = NEC_78K_0S_DI; - } - else //CLR1 PSW.bit - { - insn.itype = NEC_78K_0S_clr1; - insn.Op1.type = o_bit; - insn.Op1.reg = rPSW; - insn.Op1.value = (code2>>4)&0x07; - } - } - else //CLR1 saddr.bit - { - insn.itype = NEC_78K_0S_clr1; - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(code3); - insn.Op1.value = (code2>>4)&0x07; - } - } - break; - - case 0x86: - case 0x96: - case 0xA6: - case 0xB6: - case 0xC6: - case 0xD6: - case 0xE6: - case 0xF6: - //CLR1 sfr.bit 0000 1010 1 B2 B1 B0 0110 Sfr-offset - insn.itype = NEC_78K_0S_clr1; - insn.Op1.type = o_bit; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = sfr(insn.get_next_byte()); - insn.Op1.value = (code2>>4)&0x07; - break; - - case 0x82: - case 0x92: - case 0xA2: - case 0xB2: - case 0xC2: - case 0xD2: - case 0xE2: - case 0xF2: - //CLR1 A.bit 0000 1010 1 B2 B1 B0 0010 - insn.itype = NEC_78K_0S_clr1; - insn.Op1.type = o_bit; - insn.Op1.reg = rA; - insn.Op1.value = (code2>>4)&0x07; - break; - - case 0x8E: - case 0x9E: - case 0xAE: - case 0xBE: - case 0xCE: - case 0xDE: - case 0xEE: - case 0xFE: - //CLR1 [HL].bit 0000 1010 1 B2 B1 B0 1110 - insn.itype = NEC_78K_0S_clr1; - insn.Op1.type = o_bit; - insn.Op1.reg = rHL; - insn.Op1.prepost = 1; - insn.Op1.value = (code2>>4)&0x07; - break; - - case 0xF1: - case 0xF3: - case 0xF5: - case 0xF7: - case 0xF9: - case 0xFB: - case 0xFD: - case 0xFF: - //MOV r, #byte 0000 1010 1111 R2R1R0 1 Data - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code2>>1)&0x07)+rX; - insn.Op2.type = o_imm; - insn.Op2.dtype = dt_byte; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x21: - case 0x25: - case 0x27: - case 0x29: - case 0x2B: - case 0x2D: - case 0x2F: - //MOV A, r 0000 1010 0010 R2R1R0 1 Except r = A. - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0xE1: - case 0xE5: - case 0xE7: - case 0xE9: - case 0xEB: - case 0xED: - case 0xEF: - //MOV r, A 0000 1010 1110 R2R1R0 1 Except r = A. - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code2>>1)&0x07)+rX; - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - break; - - case 0x05: - case 0x07: - case 0x09: - case 0x0B: - case 0x0D: - case 0x0F: - //XCH A, r 0000 1010 0000 R2R1R0 1 Except r = A, X. - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0x81: - case 0x83: - case 0x85: - case 0x87: - case 0x89: - case 0x8B: - case 0x8D: - case 0x8F: - //ADD A, r 0000 1010 1000 R2R1R0 1 - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0xA1: - case 0xA3: - case 0xA5: - case 0xA7: - case 0xA9: - case 0xAB: - case 0xAD: - case 0xAF: - //ADDC A, r 0000 1010 1010 R2R1R0 1 - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0x91: - case 0x93: - case 0x95: - case 0x97: - case 0x99: - case 0x9B: - case 0x9D: - case 0x9F: - //SUB A, r 0000 1010 1001 R2R1R0 1 - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0xB1: - case 0xB3: - case 0xB5: - case 0xB7: - case 0xB9: - case 0xBB: - case 0xBD: - case 0xBF: - //SUBC A, r 0000 1010 1011 R2R1R0 1 - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0x61: - case 0x63: - case 0x65: - case 0x67: - case 0x69: - case 0x6B: - case 0x6D: - case 0x6F: - //AND A, r 0000 1010 0110 R2R1R0 1 - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0x71: - case 0x73: - case 0x75: - case 0x77: - case 0x79: - case 0x7B: - case 0x7D: - case 0x7F: - //OR A, r 0000 1010 0111 R2R1R0 1 - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0x41: - case 0x43: - case 0x45: - case 0x47: - case 0x49: - case 0x4B: - case 0x4D: - case 0x4F: - //XOR A, r 0000 1010 0100 R2R1R0 1 - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0x11: - case 0x13: - case 0x15: - case 0x17: - case 0x19: - case 0x1B: - case 0x1D: - case 0x1F: - //CMP A, r 0000 1010 0001 R2R1R0 1 - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code2>>1)&0x07)+rX; - break; - - case 0xC1: - case 0xC3: - case 0xC5: - case 0xC7: - case 0xC9: - case 0xCB: - case 0xCD: - case 0xCF: - //INC r 0000 1010 1100 R2R1R0 1 - insn.itype = NEC_78K_0S_inc; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code2>>1)&0x07)+rX; - break; - - case 0xD1: - case 0xD3: - case 0xD5: - case 0xD7: - case 0xD9: - case 0xDB: - case 0xDD: - case 0xDF: - //DEC r 0000 1010 1101 R2R1R0 1 - insn.itype = NEC_78K_0S_dec; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code2>>1)&0x07)+rX; - break; - - default: - // return with the error ERROR - return 0; - } // END switch 0x0A commands - } - break; // END case 0x0A - - case 0x0B: - //XCH A, [DE] 0000 1011 - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rDE; - insn.Op2.prepost =1; - break; - - case 0x0C: - //HALT 0000 1100 - insn.itype = NEC_78K_0S_HALT; - break; - - case 0x0D: - //XCH A, [HL+byte] 0000 1101 Data - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x0E: - //STOP 0000 1110 - insn.itype = NEC_78K_0S_STOP; - break; - - case 0x0F: - //XCH A, [HL] 0000 1111 - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x10: - //ROL A, 1 0001 0000 - insn.itype = NEC_78K_0S_rol; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = 1; - insn.Op2.regmode = 1; - break; - - case 0x11: - //CMP saddr, #byte 0001 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x12: - //ROLC A, 1 0001 0010 - insn.itype = NEC_78K_0S_rolc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = 1; - insn.Op2.regmode = 1; - break; - - case 0x13: - //CMP A, #byte 0001 0011 Data - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x14: - //SET1 CY 0001 0100 - insn.itype = NEC_78K_0S_set1; - insn.Op1.type = o_phrase; - insn.Op1.reg = bCY; - break; - - case 0x15: - //CMP A, saddr 0001 0101 Saddr-offset - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x19: - //CMP A, !addr16 0001 1001 Low addr High addr - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0x1D: - //CMP A, [HL+byte] 0001 1101 Data - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x1F: - //CMP A, [HL] 0001 1111 - insn.itype = NEC_78K_0S_cmp; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x20: - //RET 0010 0000 - insn.itype = NEC_78K_0S_ret; - break; - - case 0x22: - //CALL !addr16 0010 0010 Low addr High addr - insn.itype = NEC_78K_0S_call; - //insn.Op1.offb = insn.size; - insn.Op1.type = o_near; - insn.Op1.addr16 = 1; - addr16(insn, insn.Op1); - break; - - case 0x24: - //RETI 0010 0100 - insn.itype = NEC_78K_0S_reti; - break; - - case 0x25: - { - //MOV A, PSW 0010 0101 00011110 - //MOV A, saddr 0010 0101 Saddr-offset - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - uchar tst = insn.get_next_byte(); - if ( tst == 0x1E ) - { - insn.Op2.type = o_reg; - insn.Op2.reg = rPSW; - } - else - { - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(tst); - } - } - break; - - case 0x27: - //MOV A, sfr 0010 0111 Sfr-offset - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = sfr(insn.get_next_byte()); - break; - - case 0x29: - //MOV A, !addr16 0010 1001 Low addr High addr - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0x2B: - //MOV A, [DE] 0010 1011 - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rDE; - insn.Op2.prepost = 1; - break; - - case 0x2C: - //POP PSW 0010 1100 - insn.itype = NEC_78K_0S_pop; - insn.Op1.type = o_phrase; - insn.Op1.reg = rPSW; - break; - - case 0x2D: - //MOV A, [HL+byte] 0010 1101 Data - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x2E: - //PUSH PSW 0010 1110 - insn.itype = NEC_78K_0S_push; - insn.Op1.type = o_phrase; - insn.Op1.reg = rPSW; - break; - - case 0x2F: - //MOV A, [HL] 0010 1111 - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x30: - //BR $addr16 0011 0000 jdisp - insn.itype = NEC_78K_0S_br; - jdisp(insn.Op1, insn.get_next_byte(), 2, insn); - break; - - case 0x32: - //DBNZ saddr, $addr16 0011 0010 Saddr-offset jdisp - insn.itype = NEC_78K_0S_dbnz; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - jdisp(insn.Op2, insn.get_next_byte(), 3, insn); - break; - - case 0x34: - //DBNZ C, $addr16 0011 0100 jdisp - insn.itype = NEC_78K_0S_dbnz; - insn.Op1.type = o_reg; - insn.Op1.reg = rC; - jdisp(insn.Op2, insn.get_next_byte(), 2, insn); - break; - - case 0x36: - //DBNZ B, $addr16 0011 0110 jdisp - insn.itype = NEC_78K_0S_dbnz; - insn.Op1.type = o_reg; - insn.Op1.reg = rB; - jdisp(insn.Op2, insn.get_next_byte(), 2, insn); - break; - - case 0x38: - //BC $addr16 0011 1000 jdisp - insn.itype = NEC_78K_0S_bc; - jdisp(insn.Op1, insn.get_next_byte(), 2, insn); - break; - - case 0x3A: - //BNC $addr16 0011 1010 jdisp - insn.itype = NEC_78K_0S_bnc; - jdisp(insn.Op1, insn.get_next_byte(), 2, insn); - break; - - case 0x3C: - //BZ $addr16 0011 1100 jdisp - insn.itype = NEC_78K_0S_bz; - jdisp(insn.Op1, insn.get_next_byte(), 2, insn); - break; - - case 0x3E: - //BNZ $addr16 0011 1110 jdisp - insn.itype = NEC_78K_0S_bnz; - jdisp(insn.Op1, insn.get_next_byte(), 2, insn); - break; - - case 0x41: - //XOR saddr, #byte 0100 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x43: - //XOR A, #byte 0100 0011 Data - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x45: - //XOR A, saddr 0100 0101 Saddr-offset - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x49: - //XOR A, !addr16 0100 1001 Low addr High addr - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0x4D: - //XOR A, [HL+byte] 0100 1101 Data - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x4F: - //XOR A, [HL] 0100 1111 - insn.itype = NEC_78K_0S_xor; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x61: - //AND saddr, #byte 0110 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x63: - //AND A, #byte 0110 0011 Data - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x65: - //AND A, saddr 0110 0101 Saddr-offset - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x69: - //AND A, !addr16 0110 1001 Low addr High addr - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0x6D: - //AND A, [HL+byte] 0110 1101 Data - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x6F: - //AND A, [HL] 0110 1111 - insn.itype = NEC_78K_0S_and; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x71: - //OR saddr, #byte 0111 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_mem; - insn.Op1.dtype = o_mem; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x73: - //OR A, #byte 0111 0011 Data - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x75: - //OR A, saddr 0111 0101 Saddr-offset - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x79: - //OR A, !addr16 0111 1001 Low addr High addr - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - addr16(insn, insn.Op2); - break; - - case 0x7D: - //OR A, [HL+byte] 0111 1101 Data - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x7F: - //OR A, [HL] 0111 1111 - insn.itype = NEC_78K_0S_or; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x81: - //ADD saddr, #byte 1000 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x83: - //ADD A, #byte 1000 0011 Data - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x85: - //ADD A, saddr 1000 0101 Saddr-offset - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x89: - //ADD A, !addr16 1000 1001 Low addr High addr - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0x8D: - //ADD A, [HL+byte] 1000 1101 Data - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x8F: - //ADD A, [HL] 1000 1111 - insn.itype = NEC_78K_0S_add; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x80: - case 0x84: - case 0x88: - case 0x8C: - //INCW rp 1000 P1 P0 00 - insn.itype = NEC_78K_0S_incw; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code>>2)&0x03)+rAX; - break; - - case 0x91: - //SUB saddr, #byte 1001 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x93: - //SUB A, #byte 1001 0011 Data - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0x95: - //SUB A, saddr 1001 0101 Saddr-offset - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0x99: - //SUB A, !addr16 1001 1001 Low addr High addr - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0x9D: - //SUB A, [HL+byte] 1001 1101 Data - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0x9F: - //SUB A, [HL] 1001 1111 - insn.itype = NEC_78K_0S_sub; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0x90: - case 0x94: - case 0x98: - case 0x9C: - //DECW rp 1001 P1 P0 00 - insn.itype = NEC_78K_0S_decw; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code>>2)&0x03)+rAX; - break; - - case 0xA1: - //ADDC saddr,#byte 1010 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0xA3: - //ADDC A, #byte 1010 0011 Data - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0xA5: - //ADDC A, saddr 1010 0101 Saddr-offset - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0xA9: - //ADDC A, !addr16 1010 1001 Low addr High addr - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0xAD: - //ADDC A,[HL+byte] 1010 1101 Data - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost = 1; - insn.Op2.xmode = 1; - break; - - case 0xAF: - //ADDC A,[HL] 1010 1111 - insn.itype = NEC_78K_0S_addc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost = 1; - break; - - case 0xA0: - case 0xA4: - case 0xA8: - case 0xAC: - //POP rp 1010 P1 P0 00 - insn.itype = NEC_78K_0S_pop; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX + ((code>>2)&0x03); - break; - - case 0xA2: - case 0xA6: - case 0xAA: - case 0xAE: - //PUSH rp 1010 P1 P0 10 - insn.itype = NEC_78K_0S_push; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX + ((code>>2)&0x03); - break; - - case 0xB0: - //BR AX 1011 0000 - insn.itype = NEC_78K_0S_br; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - break; - - case 0xB1: - //SUBC saddr,#byte 1011 0001 Saddr-offset Data - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0xB2: - //BR !addr16 1011 0010 Low addr High addr - insn.itype = NEC_78K_0S_br; - insn.Op1.type = o_near; - insn.Op1.addr16 = 1; - addr16(insn, insn.Op1); - break; - - case 0xB3: - //SUBC A, #byte 1011 0011 Data - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0xB5: - //SUBC A, saddr 1011 0101 Saddr-offset - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = saddr(insn.get_next_byte()); - break; - - case 0xB9: - //SUBC A, !addr16 1011 1001 Low addr High addr - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr16 = 1; - addr16(insn, insn.Op2); - break; - - case 0xBD: - //SUBC A, [HL+byte] 1011 1101 Data - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.addr = insn.get_next_byte(); - insn.Op2.prepost =1; - insn.Op2.xmode =1; - break; - - case 0xBF: - //SUBC A, [HL] 1011 1111 - insn.itype = NEC_78K_0S_subc; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rHL; - insn.Op2.prepost =1; - break; - - - case 0xC0: - //XCH A, X 1100 0000 - insn.itype = NEC_78K_0S_xch; - insn.Op1.type = o_reg; - insn.Op1.reg = rA; - insn.Op2.type = o_reg; - insn.Op2.reg = rX; - break; - - case 0xC2: - //SUBW AX, #word 1100 0010 Low byte High byte - insn.itype = NEC_78K_0S_subw; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - imm16(insn, insn.Op2); - break; - - case 0xC5: - //INC saddr 1100 0101 Saddr-offset - insn.itype = NEC_78K_0S_inc; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - break; - - case 0xC4: - case 0xC8: - case 0xCC: - //XCHW AX, rp 1100 P1 P0 00 Only when rp = BC, DE, or HL. - insn.itype = NEC_78K_0S_xchw; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code>>2)&0x03)+rAX; - break; - - case 0xD2: - //ADDW AX, #word 1101 0010 Low byte High byte - insn.itype = NEC_78K_0S_addw; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - imm16(insn, insn.Op2); - break; - - case 0xD5: - //DEC saddr 1101 0101 Saddr-offset - insn.itype = NEC_78K_0S_inc; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(insn.get_next_byte()); - break; - - case 0xD6: - { - //MOVW AX, saddrp 1101 0110 Saddr-offset - //MOVW AX, SP 1101 0110 0001 1100 - insn.itype = NEC_78K_0S_movw; - uchar tst = insn.get_next_byte(); - if ( tst == 0x1C ) - { - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - insn.Op2.type = o_reg; - insn.Op2.reg = rSP; - } - else - { - if ( (tst & 0x01) != 0 ) // return with the error ERROR - return 0; - // movw AX,saddrp - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_word; - insn.Op2.addr = saddr(tst); - } - } - break; - - case 0xD4: - case 0xD8: - case 0xDC: - //MOVW AX, rp 1101 P1 P0 00 Only when rp = BC, DE, or HL. - insn.itype = NEC_78K_0S_movw; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - insn.Op2.type = o_reg; - insn.Op2.reg = ((code>>2)&0x03)+rAX; - break; - - case 0xE2: - //CMPW AX, #word 1110 0010 Low byte High byte - insn.itype = NEC_78K_0S_cmpw; - insn.Op1.type = o_reg; - insn.Op1.reg = rAX; - insn.Op2.type = o_imm; - imm16(insn, insn.Op2); - break; - - case 0xEB: - //MOV [DE], A 1110 1011 - insn.itype = NEC_78K_0S_mov; - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - insn.Op1.type = o_reg; - insn.Op1.reg = rDE; - insn.Op1.prepost = 1; - break; - - case 0xEF: - //MOV [HL], A 1110 1111 - insn.itype = NEC_78K_0S_mov; - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - insn.Op1.type = o_reg; - insn.Op1.reg = rHL; - insn.Op1.prepost = 1; - break; - - case 0xE9: - //MOV !addr16, A 1110 1001 Low addr High addr - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr16 = 1; - addr16(insn, insn.Op1); - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - break; - - case 0xE5: - { - //MOV saddr, A 1110 0101 Saddr-offset - //MOV PSW, A 1110 0101 00011110 - insn.itype = NEC_78K_0S_mov; - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - uchar tst = insn.get_next_byte(); - if ( tst == 0x1E ) - { - insn.Op1.type = o_reg; - insn.Op1.reg = rPSW; - } - else - { - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(tst); - } - } - break; - - case 0xE6: - { - //MOVW saddrp, AX 1110 0110 Saddr-offset - //MOVW SP, AX 1110 0110 0001 1100 - insn.itype = NEC_78K_0S_movw; - uchar byte2 = insn.get_next_byte(); - if ( byte2 == 0x1C ) - { - insn.Op1.type = o_reg; - insn.Op1.reg = rSP; - insn.Op2.type = o_reg; - insn.Op2.reg = rAX; - } - else - { - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_word; - insn.Op1.addr = saddr(byte2); - insn.Op2.type = o_reg; - insn.Op2.reg = rAX; - } - } - break; - - case 0xED: - //MOV [HL+byte], A 1110 1101 Data - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_reg; - insn.Op1.reg = rHL; - insn.Op1.addr = insn.get_next_byte(); - insn.Op1.prepost = 1; - insn.Op1.xmode = 1; - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - break; - - case 0xE7: - //MOV sfr, A 1110 0111 Sfr-offset - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = sfr(insn.get_next_byte()); - insn.Op2.type = o_reg; - insn.Op2.reg = rA; - break; - - case 0xE4: - case 0xE8: - case 0xEC: - //MOVW rp, AX 1110 P1 P0 00 Only when rp = BC, DE, or HL. - insn.itype = NEC_78K_0S_movw; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code>>2)&0x03)+rAX; - insn.Op2.type = o_reg; - insn.Op2.reg = rAX; - break; - - case 0xF5: - { - //MOV saddr, #byte 1111 0101 Saddr-offset Data - //MOV PSW, #byte 1111 0101 00011110 Data - insn.itype = NEC_78K_0S_mov; - uchar tst = insn.get_next_byte(); - if ( tst != 0x1E ) - { - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = saddr(tst); - } - else - { - insn.Op1.type = o_reg; - insn.Op1.reg = rPSW; - } - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - } - break; - - case 0xF7: - //MOV sfr, #byte 1111 0111 Sfr-offset Data - insn.itype = NEC_78K_0S_mov; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = sfr(insn.get_next_byte()); - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - - case 0xF0: - case 0xF4: - case 0xF8: - case 0xFC: - //MOVW rp, #word 1111 P1 P0 00 Low byte High byte - insn.itype = NEC_78K_0S_movw; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code>>2)&0x03)+rAX; - insn.Op2.type = o_imm; - imm16(insn, insn.Op2); - break; - - default: - if ( (code&0xC1) == 0x40 ) - { - //CALLT [addr5] 01 ta4 to 0 0 - insn.itype = NEC_78K_0S_callt; - uint32 addr = (code&0x3E)+0x40; - insn.Op1.type = o_near; - insn.Op1.form = 1; - insn.Op1.addr = get_byte(addr)|(get_byte(addr+1)<<8); - } - else - { - // return with the error ERROR - return 0; - } - break; - } // END main switch - return insn.size; -} diff --git a/idasdk75/module/78k0s/emu.cpp b/idasdk75/module/78k0s/emu.cpp deleted file mode 100644 index 0224dc2..0000000 --- a/idasdk75/module/78k0s/emu.cpp +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "78k_0s.hpp" - -//------------------------------------------------------------------------ -void DataSet(const insn_t &insn, const op_t &x, ea_t EA, int isload) -{ - insn.create_op_data(EA, x); - insn.add_dref(EA, x.offb, isload ? dr_R : dr_W); -} - -//---------------------------------------------------------------------- -void nec78k0s_t::handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn) -{ - switch ( x.type ) - { - case o_phrase: - case o_void: - case o_reg: - break; - - case o_imm: - case o_displ: - set_immd(insn.ea); - if ( !forced_op ) - { - ushort addr = ushort(x.addr); - if ( x.type == o_displ ) - { - addr += (ushort)insn.ip; - addr += insn.size; - uint32 offb = map_code_ea(insn, addr, x.n); - DataSet(insn, x, offb, isload); - } - else if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - { - insn.add_off_drefs(x, dr_O, 0); - } - } - break; - - case o_bit: - case o_mem: - DataSet(insn, x, map_code_ea(insn, x), isload); - break; - - case o_near: - { - ea_t ea = to_ea(insn.cs, x.addr); - int iscall = has_insn_feature(insn.itype, CF_CALL); - insn.add_cref(ea, x.offb, iscall ? fl_CN : fl_JN); - if ( iscall ) - flow = func_does_return(ea); - } - break; - - default: - warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); - break; - } -} -//---------------------------------------------------------------------- -int nec78k0s_t::emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - flow = (Feature & CF_STOP) == 0; - - int flag1 = is_forced_operand(insn.ea, 0); - int flag2 = is_forced_operand(insn.ea, 1); - int flag3 = is_forced_operand(insn.ea, 2); - - if ( Feature & CF_USE1 ) handle_operand(insn.Op1, flag1, 1, insn); - if ( Feature & CF_USE2 ) handle_operand(insn.Op2, flag2, 1, insn); - if ( Feature & CF_USE3 ) handle_operand(insn.Op3, flag3, 1, insn); - if ( Feature & CF_CHG1 ) handle_operand(insn.Op1, flag1, 0, insn); - if ( Feature & CF_CHG2 ) handle_operand(insn.Op2, flag2, 0, insn); - if ( Feature & CF_CHG3 ) handle_operand(insn.Op3, flag3, 0, insn); - - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - return 1; -} diff --git a/idasdk75/module/78k0s/ins.hpp b/idasdk75/module/78k0s/ins.hpp deleted file mode 100644 index 4f3b25e..0000000 --- a/idasdk75/module/78k0s/ins.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - NEC_78K_0S_null = 0, // Unknown Operation - NEC_78K_0S_cmp, // Compare Byte Data Comparison - NEC_78K_0S_xor, // Exclusive Or Exclusive Logical Sum of Byte Data - NEC_78K_0S_and, // AND Logical Product of Byte Data - NEC_78K_0S_or, // OR Logical Sum of Byte Data - NEC_78K_0S_add, // ADD Byte Data Addition - NEC_78K_0S_sub, // Subtract Byte Data Subtraction - NEC_78K_0S_addc, // Add with Carry Addition of Byte Data with Carry - NEC_78K_0S_subc, // Subtract with Carry Subtraction of Byte Data with Carry - NEC_78K_0S_subw, // Subtract Word Data Subtraction - NEC_78K_0S_addw, // Add Word Data Addition - NEC_78K_0S_cmpw, // Compare Word Data Comparison - NEC_78K_0S_inc, // Increment Byte Data Increment - NEC_78K_0S_dec, // Decrement Byte Data Decrement - NEC_78K_0S_incw, // Increment Word Data Increment - NEC_78K_0S_decw, // Decrement Word Data Decrement - NEC_78K_0S_ror, // Rotate Right Byte Data Rotation to the Right - NEC_78K_0S_rol, // Rotate Left Byte Data Rotation to the Left - NEC_78K_0S_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry - NEC_78K_0S_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry - NEC_78K_0S_call, // CALL Subroutine Call (16 Bit Direct) - NEC_78K_0S_callt, // Call Table Subroutine Call (Call Table Reference) - NEC_78K_0S_ret, // Return from Subroutine - NEC_78K_0S_reti, // Return from Interrupt / Return from Hardware Vectored Interrupt - NEC_78K_0S_mov, // Move Byte Data Transfer - NEC_78K_0S_xch, // Exchange Byte Data Exchange - NEC_78K_0S_xchw, // Exchange Word Data Exchange - NEC_78K_0S_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set - NEC_78K_0S_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear - NEC_78K_0S_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation - NEC_78K_0S_push, // Push - NEC_78K_0S_pop, // Pop - NEC_78K_0S_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer - NEC_78K_0S_br, // Unconditional Branch - NEC_78K_0S_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1) - NEC_78K_0S_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0) - NEC_78K_0S_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1) - NEC_78K_0S_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0) - NEC_78K_0S_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1) - NEC_78K_0S_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0) - NEC_78K_0S_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1 != 0) - NEC_78K_0S_nop, // No Operation - NEC_78K_0S_EI, // Enable Interrupt - NEC_78K_0S_DI, // Disable Interrupt - NEC_78K_0S_HALT, // HALT Mode Set - NEC_78K_0S_STOP, // Stop Mode Set - NEC_78K_0S_last -}; - -#endif diff --git a/idasdk75/module/78k0s/makefile b/idasdk75/module/78k0s/makefile deleted file mode 100644 index e0a121e..0000000 --- a/idasdk75/module/78k0s/makefile +++ /dev/null @@ -1,43 +0,0 @@ -PROC=78k0s -CONFIGS=78k0s.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k_0s.hpp ana.cpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k_0s.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - 78k_0s.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp 78k_0s.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/78k0s/out.cpp b/idasdk75/module/78k0s/out.cpp deleted file mode 100644 index f43c17b..0000000 --- a/idasdk75/module/78k0s/out.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "78k_0s.hpp" - -//---------------------------------------------------------------------- -class out_nec78k0s_t : public outctx_t -{ - out_nec78k0s_t(void) = delete; // not used -public: - void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); } - int OutVarName(const op_t &x, bool iscode); - - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_nec78k0s_t) == sizeof(outctx_t)); - -//---------------------------------------------------------------------- -void idaapi out_insn(outctx_t &ctx) -{ - out_nec78k0s_t *p = (out_nec78k0s_t *)&ctx; - p->out_insn(); -} - -bool idaapi out_opnd(outctx_t &ctx, const op_t &x) -{ - out_nec78k0s_t *p = (out_nec78k0s_t *)&ctx; - return p->out_operand(x); -} - -//---------------------------------------------------------------------- -int out_nec78k0s_t::OutVarName(const op_t &x, bool iscode) -{ - ushort addr = ushort(x.addr); - //get linear address - ea_t toea = map_ea(insn, addr, x.n, iscode); - //get its string representation - return out_name_expr(x, toea, x.addr); -} - -//---------------------------------------------------------------------- -bool out_nec78k0s_t::out_operand(const op_t &x) -{ - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - if ( x.prepost ) - out_symbol('['); - OutReg(x.reg); - if ( x.xmode ) - { - out_symbol('+'); - out_value(x, OOF_ADDR | OOF_NUMBER | OOFW_8); - } - if ( x.prepost ) - out_symbol(']'); - break; - - case o_phrase: - out_line(ph.reg_names[x.reg]); - break; - - case o_bit: - switch ( x.reg ) - { - case rPSW: - out_line("PSW."); - switch ( x.value ) - { - case 0: - out_line("CY"); - break; - case 4: - out_line("AC"); - break; - case 6: - out_line("Z"); - break; - case 7: - out_line("IE"); - break; - default: - out_value(x, OOFW_IMM); - break; - } - break; - - case rA: - out_line("A."); - out_char(char('0'+x.value)); - break; - - default: - if ( !OutVarName(x, true) ) - out_value(x, OOF_ADDR | OOFW_16); - out_symbol('.'); - //Look for a bit using its address - nec78k0s_t &pm = *static_cast<nec78k0s_t *>(procmod); - if ( !pm.nec_find_ioport_bit(*this, (int)x.addr, (int)x.value) ) - out_char(char('0'+x.value)); //output data as immediate - break; - } - break; - - case o_imm: - if ( !x.regmode ) - { - out_symbol('#'); - out_value(x, OOFW_IMM); - } - else - { - out_symbol('1'); - } - break; - - case o_mem: - //output a memory address (e.g. byte_98) - if ( x.addr16 ) - out_symbol('!'); - //output a name - if ( !OutVarName(x, false) ) - out_value(x, OOF_ADDR | OOFW_16); //output just an address - break; - - case o_near: - { - if ( x.addr16 ) - out_symbol('!'); - if ( x.form ) - out_symbol('['); - //get linear address - ea_t v = to_ea(insn.cs,x.addr); - if ( !out_name_expr(x, v, x.addr) ) - { - //print its value - out_value(x, OOF_ADDR | OOF_NUMBER | OOFW_16); - remember_problem(PR_NONAME, insn.ea); - } - if ( x.form ) - out_symbol(']'); - } - break; - - default: - warning("out: %a: bad optype %d", insn.ip, x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -void out_nec78k0s_t::out_insn(void) -{ - out_mnemonic(); - - out_one_operand(0); - - //more operands? - if ( insn.Op2.type != o_void ) - { - out_symbol(',');//print delimiter - //unless UAS_NOSPA is set, add a space - if ( !(ash.uflag & UAS_NOSPA) ) - out_char(' '); - out_one_operand(1); - } - - if ( insn.Op3.type != o_void ) - { - out_symbol(','); - if ( !(ash.uflag & UAS_NOSPA) ) - out_char(' '); - out_one_operand(2); - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void nec78k0s_t::nec78k0s_header(outctx_t &ctx) -{ - ctx.gen_cmt_line("Processor: %s [%s]", - !ioh.device.empty() - ? ioh.device.c_str() - : inf_get_procname().c_str(), - ioh.deviceparams.c_str()); - ctx.gen_cmt_line("Target assebler: %s", ash.name); - if ( ash.header != NULL ) - for ( const char *const *ptr=ash.header; *ptr != NULL; ptr++ ) - ctx.flush_buf(*ptr, 0); -} - -//-------------------------------------------------------------------------- -void idaapi nec78k0s_segstart(outctx_t &, segment_t *) -{ -} - -//-------------------------------------------------------------------------- -void nec78k0s_t::nec78k0s_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - size_t i = strlen(ash.end); - do - ctx.out_char(' '); - while ( ++i < 8 ); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} diff --git a/idasdk75/module/78k0s/reg.cpp b/idasdk75/module/78k0s/reg.cpp deleted file mode 100644 index 85974c7..0000000 --- a/idasdk75/module/78k0s/reg.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "78k_0s.hpp" -#include <segregs.hpp> -#include <diskio.hpp> - -//---------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "X", "A", "C", "B", "E", "D", "L", "H", "AX", "BC", "DE","HL", - "PSW", "SP", "s", "cc", "dpr", - "CY", - "cs", "ds" -}; -//---------------------------------------------------------------------- -static const asm_t nec78k0s = -{ - AS_COLON | ASH_HEXF0 | ASD_DECF0 | ASO_OCTF0 | ASB_BINF4 | AS_N2CHR | AS_ONEDUP | AS_NOXRF, - UAS_NOSPA, - "NEC _78K_0S Assembler", - 0, - NULL, // header - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // no double words - NULL, // no qwords - NULL, // oword (16 bytes) - NULL, // no float - NULL, // no double - NULL, // no tbytes - NULL, // no packreal - NULL, //".db.#s(b,w) #d,#v", // #h - header(.byte,.word) - // #d - size of array - // #v - value of array elements - // #s - size specifier - ".rs %s", // uninited data (reserve space) - ".equ", - NULL, // seg prefix - "*", // a_curip - NULL, // returns function header line - NULL, // returns function footer line - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; -//---------------------------------------------------------------------- -#define FAMILY "NEC series:" -static const char *const shnames[] = -{ - "78k0s", - NULL -}; -static const char *const lnames[] = -{ - FAMILY"NEC 78K/0S", - NULL -}; -static const asm_t *const asms[] = -{ - &nec78k0s, - NULL -}; -//-------------------------------------------------------------------------- -//return opcodes -static const uchar retcNEC78K0S_0[] = { 0x24 }; //reti -static const uchar retcNEC78K0S_1[] = { 0x20 }; //ret - -static const bytes_t retcodes[] = -{ - { sizeof(retcNEC78K0S_0), retcNEC78K0S_0 }, - { sizeof(retcNEC78K0S_1), retcNEC78K0S_1 }, - { 0, NULL } -}; - -//------------------------------------------------------------------ -bool nec78k0s_t::nec_find_ioport_bit(outctx_t &ctx, int port, int bit) -{ - // find bit register in the ports list - const ioport_bit_t *b = find_ioport_bit(ioh.ports, port, bit); - if ( b != NULL && !b->name.empty() ) - { - // output bit register name - ctx.out_line(b->name.c_str(), COLOR_IMPNAME); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new nec78k0s_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi nec78k0s_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - inf_set_be(false); - helper.create("$ 78k0s"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - { - inf_set_gen_lzero(true); - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: // new segment - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - nec78k0s_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - nec78k0s_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - nec78k0s_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_NEC_78K0S, // id - // flag - PRN_HEX - | PR_SEGTRANS, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - Rcs,Rds, - 0, // size of a segment register - Rcs,Rds, - - NULL, // No known code start sequences - retcodes, - - 0, - NEC_78K_0S_last, - Instructions, // instruc -}; diff --git a/idasdk75/module/80196/ana.cpp b/idasdk75/module/80196/ana.cpp deleted file mode 100644 index 5773394..0000000 --- a/idasdk75/module/80196/ana.cpp +++ /dev/null @@ -1,597 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Intel 80196 module - * - */ - -#include "i196.hpp" -#include "ins.hpp" - -//---------------------------------------------------------------------- -struct wsr_mapping_t -{ - ushort base; - uchar wsr; - uchar wsrbase; - uchar wsr1base; -}; - -static const wsr_mapping_t mappings[] = -{ - { 0x0000, 0x10, 0x80, 0xFF }, // 0080-00FF - { 0x0080, 0x11, 0x80, 0xFF }, - { 0x0100, 0x12, 0x80, 0xFF }, - { 0x0180, 0x13, 0x80, 0xFF }, - { 0x0200, 0x14, 0x80, 0xFF }, - { 0x0280, 0x15, 0x80, 0xFF }, - { 0x0300, 0x16, 0x80, 0xFF }, - { 0x0380, 0x17, 0x80, 0xFF }, - { 0x1F00, 0x1E, 0x80, 0xFF }, - { 0x1F80, 0x1F, 0x80, 0xFF }, - { 0x0000, 0x20, 0xC0, 0x40 }, // 00C0-00FF or 0040-007F - { 0x0040, 0x21, 0xC0, 0x40 }, - { 0x0080, 0x22, 0xC0, 0x40 }, - { 0x00C0, 0x23, 0xC0, 0x40 }, - { 0x0100, 0x24, 0xC0, 0x40 }, - { 0x0140, 0x25, 0xC0, 0x40 }, - { 0x0180, 0x26, 0xC0, 0x40 }, - { 0x01C0, 0x27, 0xC0, 0x40 }, - { 0x0200, 0x28, 0xC0, 0x40 }, - { 0x0240, 0x29, 0xC0, 0x40 }, - { 0x0280, 0x2A, 0xC0, 0x40 }, - { 0x02C0, 0x2B, 0xC0, 0x40 }, - { 0x0300, 0x2C, 0xC0, 0x40 }, - { 0x0340, 0x2D, 0xC0, 0x40 }, - { 0x0380, 0x2E, 0xC0, 0x40 }, - { 0x03C0, 0x2F, 0xC0, 0x40 }, - { 0x1F00, 0x3C, 0xC0, 0x40 }, - { 0x1F40, 0x3D, 0xC0, 0x40 }, - { 0x1F80, 0x3E, 0xC0, 0x40 }, - { 0x1FC0, 0x3F, 0xC0, 0x40 }, - { 0x0000, 0x40, 0xE0, 0x60 }, // 00E0-00FF or 0060-007F - { 0x0020, 0x41, 0xE0, 0x60 }, - { 0x0040, 0x42, 0xE0, 0x60 }, - { 0x0060, 0x43, 0xE0, 0x60 }, - { 0x0080, 0x44, 0xE0, 0x60 }, - { 0x00A0, 0x45, 0xE0, 0x60 }, - { 0x00C0, 0x46, 0xE0, 0x60 }, - { 0x00E0, 0x47, 0xE0, 0x60 }, - { 0x0100, 0x48, 0xE0, 0x60 }, - { 0x0120, 0x49, 0xE0, 0x60 }, - { 0x0140, 0x4A, 0xE0, 0x60 }, - { 0x0160, 0x4B, 0xE0, 0x60 }, - { 0x0180, 0x4C, 0xE0, 0x60 }, - { 0x01A0, 0x4D, 0xE0, 0x60 }, - { 0x01C0, 0x4E, 0xE0, 0x60 }, - { 0x01E0, 0x4F, 0xE0, 0x60 }, - { 0x0200, 0x50, 0xE0, 0x60 }, - { 0x0220, 0x51, 0xE0, 0x60 }, - { 0x0240, 0x52, 0xE0, 0x60 }, - { 0x0260, 0x53, 0xE0, 0x60 }, - { 0x0280, 0x54, 0xE0, 0x60 }, - { 0x02A0, 0x55, 0xE0, 0x60 }, - { 0x02C0, 0x56, 0xE0, 0x60 }, - { 0x02E0, 0x57, 0xE0, 0x60 }, - { 0x0300, 0x58, 0xE0, 0x60 }, - { 0x0320, 0x59, 0xE0, 0x60 }, - { 0x0340, 0x5A, 0xE0, 0x60 }, - { 0x0360, 0x5B, 0xE0, 0x60 }, - { 0x0380, 0x5C, 0xE0, 0x60 }, - { 0x03A0, 0x5D, 0xE0, 0x60 }, - { 0x03C0, 0x5E, 0xE0, 0x60 }, - { 0x03E0, 0x5F, 0xE0, 0x60 }, - { 0x1F00, 0x78, 0xE0, 0x60 }, - { 0x1F20, 0x79, 0xE0, 0x60 }, - { 0x1F40, 0x7A, 0xE0, 0x60 }, - { 0x1F60, 0x7B, 0xE0, 0x60 }, - { 0x1F80, 0x7C, 0xE0, 0x60 }, - { 0x1FA0, 0x7D, 0xE0, 0x60 }, - { 0x1FC0, 0x7E, 0xE0, 0x60 }, - { 0x1FE0, 0x7F, 0xE0, 0x60 }, -}; - -static int NT_CDECL cmp(const void *x, const void *y) -{ - const wsr_mapping_t *a = (const wsr_mapping_t *)x; - const wsr_mapping_t *b = (const wsr_mapping_t *)y; - return a->wsr - b->wsr; -} - -//---------------------------------------------------------------------- -// perform WSR/WSR1 mapping -ea_t i196_t::map(ea_t iea, ea_t v) const -{ - if ( !extended ) - return v; - if ( v < 0x40 ) - return v; - sel_t wsr = get_sreg(iea, v < 0x80 ? WSR1 : WSR) & 0x7F; - if ( wsr < 0x10 ) - return v; - - wsr_mapping_t key; - key.wsr = (char)wsr; - wsr_mapping_t *p = (wsr_mapping_t *) - bsearch(&key, mappings, qnumber(mappings), sizeof(key), cmp); - if ( p == NULL ) - return v; - - int delta = v < 0x80 ? p->wsr1base : p->wsrbase; - if ( v < delta ) - return v; - return v - delta + p->base; -} - -//---------------------------------------------------------------------- -void i196_t::aop(insn_t &insn, uint code, op_t &op) -{ - switch ( code & 3 ) - { - case 0: // direct - op.type = o_mem; - op.addr = map(insn.ea, insn.get_next_byte()); - break; - - case 1: // immediate - op.type = o_imm; - if ( (code & 0x10) == 0 && (code & 0xFC) != 0xAC ) // ldbze always baop - { - op.dtype = dt_word; - op.value = insn.get_next_word(); - } - else - { - op.value = insn.get_next_byte(); - } - break; - - case 2: // indirect - op.dtype = dt_word; - op.addr = insn.get_next_byte(); - op.type = (op.addr & 1) ? o_indirect_inc : o_indirect; - op.addr = map(insn.ea, op.addr & ~1); - break; - - case 3: // indexed - op.dtype = dt_word; - op.type = o_indexed; - op.value = insn.get_next_byte(); // short (reg file) - op.addr = (op.value & 1) ? insn.get_next_word() : insn.get_next_byte(); - op.value = map(insn.ea, op.value & ~1); - } -} - -//---------------------------------------------------------------------- -int i196_t::ld_st(insn_t &insn, ushort itype, char dtype, bool indirect, op_t ®, op_t &mem) -{ - if ( !extended ) - return 0; - insn.itype = itype; - reg.dtype = dtype; - mem.dtype = dtype; - mem.addr = insn.get_next_byte(); - if ( indirect ) // indirect - { - mem.type = (mem.addr & 1) ? o_indirect_inc : o_indirect; - mem.addr = map(insn.ea, mem.addr & ~1); - } - else - { - mem.type = o_indexed; - mem.value = map(insn.ea, mem.addr); - mem.addr = insn.get_next_word(); - mem.addr |= insn.get_next_byte() << 16; - } - reg.type = o_mem; - reg.addr = map(insn.ea, insn.get_next_byte()); - return insn.size; -} - -//---------------------------------------------------------------------- -int i196_t::ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - - insn.Op1.dtype = dt_byte; - insn.Op2.dtype = dt_byte; - insn.Op3.dtype = dt_byte; - - uint code = insn.get_next_byte(); - - uint nibble0 = (code & 0xF); - uint nibble1 = (code >> 4); - - char offc; - int32 off; - uint tmp; - - if ( nibble1 < 2 ) // 0,1 - { - static const char cmd01[] = - { - I196_skip, I196_clr, I196_not, I196_neg, - I196_xch, I196_dec, I196_ext, I196_inc, - I196_shr, I196_shl, I196_shra, I196_xch, - I196_shrl, I196_shll, I196_shral, I196_norml, - I196_null, I196_clrb, I196_notb, I196_negb, - I196_xchb, I196_decb, I196_extb, I196_incb, - I196_shrb, I196_shlb, I196_shrab, I196_xchb, - I196_est, I196_est, I196_estb, I196_estb - }; - - insn.itype = cmd01[code & 0x1F]; - - if ( insn.itype == I196_null ) - return 0; // unknown instruction - - switch ( code ) - { - case 0x4: case 0x14: //xch reg,aop direct - case 0xB: case 0x1B: //xch reg,aop indexed - if ( (code & 0x10) == 0 ) - insn.Op2.dtype = dt_word; - aop(insn, code, insn.Op2); - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - break; - - case 0xF: //norml lreg,breg - insn.Op2.addr = map(insn.ea, insn.get_next_byte()); - insn.Op2.type = o_mem; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - break; - - case 0x1C: // est.indirect - case 0x1D: // est.indexed - return ld_st(insn, I196_est, dt_word, code == 0x1C, insn.Op1, insn.Op2); - - case 0x1E: // estb.indirect - case 0x1F: // estb.indexed - return ld_st(insn, I196_estb, dt_byte, code == 0x1E, insn.Op1, insn.Op2); - - default: // shifts - tmp = insn.get_next_byte(); - if ( tmp < 16 ) - { - insn.Op2.value = tmp; - insn.Op2.type = o_imm; - } - else - { - insn.Op2.addr = map(insn.ea, tmp); - insn.Op2.type = o_mem; - } - // fallthrough - - case 0x0: case 0x1: case 0x2: case 0x3: - case 0x5: case 0x6: case 0x7: case 0x11: - case 0x12: case 0x13: case 0x15: case 0x16: case 0x17: - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - } - - switch ( code ) - { - case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: - case 0x7: case 0x8: case 0x9: case 0xA: case 0xB: case 0x16: - insn.Op1.dtype = dt_word; - break; - - case 0x6: case 0xC: case 0xD: case 0xE: case 0xF: - insn.Op1.dtype = dt_dword; - break; - } - } - else if ( nibble1 < 4 ) // 2,3 - { - static const char cmd23[] = { I196_sjmp, I196_scall, I196_jbc, I196_jbs }; - - insn.itype = cmd23[ ((code - 0x20) >> 3) & 3 ]; - - if ( nibble1 == 2 ) // sjmp/scall - { - insn.Op1.type = o_near; - off = insn.get_next_byte() + ((code & 7) << 8); - if ( off & 0x400 ) - off |= ~0x7FF; - else - off &= 0x7FF; // make signed - insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition -// insn.Op1.dtype = dt_word; - } - else // jbc/jbs - { - insn.Op2.type = o_bit; - insn.Op2.reg = code & 7; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - insn.Op3.type = o_near; - offc = insn.get_next_byte(); - insn.Op3.addr = truncate(insn.ip + insn.size + offc); // signed addition -// insn.Op3.dtype = dt_word; - } - } - else if ( nibble1 < 6 ) // 4,5 - { - static const char cmd45[] = - { - I196_and3, I196_add3, I196_sub3, I196_mulu3, - I196_andb3, I196_addb3, I196_subb3, I196_mulub3 - }; - - insn.itype = cmd45[ ((code - 0x40) >> 2) & 7 ]; - - if ( (code & 0x10) == 0 ) - insn.Op1.dtype = insn.Op2.dtype = insn.Op3.dtype = dt_word; - - if ( (code & 0xc) == 0xc ) // mulu/mulub - insn.Op1.dtype++; // word->dword/byte->word - - aop(insn, code, insn.Op3); - insn.Op2.addr = map(insn.ea, insn.get_next_byte()); - insn.Op2.type = o_mem; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - } - else if ( nibble1 < 0xD ) // 6,7,8,9,A,B,C - { - static const char cmd6c[] = - { - I196_and2, I196_add2, I196_sub2, I196_mulu2, - I196_andb2, I196_addb2, I196_subb2, I196_mulub2, - I196_or, I196_xor, I196_cmp, I196_divu, - I196_orb, I196_xorb, I196_cmpb, I196_divub, - I196_ld, I196_addc, I196_subc, I196_ldbze, - I196_ldb, I196_addcb, I196_subcb, I196_ldbse, - I196_st, I196_stb, I196_push, I196_pop, - I196_null, I196_null, I196_null, I196_null, - }; - - insn.itype = cmd6c[ ((code - 0x60) >> 2) & 31 ]; - - switch ( nibble1 ) - { - case 6: // and/add/sub/mulu - case 8: // or/xor/cmp/duvu - insn.Op1.dtype = insn.Op2.dtype = dt_word; - if ( (nibble0 & 0xC) == 0xC ) - insn.Op1.dtype++; //mulu/divu - break; - - case 0xA: // ld/addc/subc/ldbze - insn.Op1.dtype = insn.Op2.dtype = dt_word; - if ( (nibble0 & 0xC) == 0xC ) - insn.Op2.dtype = dt_byte; //ldbze - break; - } - - switch ( code & 0xFC ) - { - case 0xC0: // st - insn.Op2.dtype = dt_word; - - case 0x7C: case 0x9C: case 0xBC: case 0xC8: case 0xCC: - insn.Op1.dtype = dt_word; - } - - switch ( code ) - { - case 0xC1: - insn.itype = I196_bmov; - goto cont1; - - case 0xC5: - insn.itype = I196_cmpl; - insn.Op2.dtype = dt_dword; - goto cont2; - - case 0xCD: - insn.itype = I196_bmovi; -cont1: - insn.Op2.dtype = dt_word; -cont2: - insn.Op2.addr = map(insn.ea, insn.get_next_byte()); - insn.Op2.type = o_mem; - insn.Op1.dtype = dt_dword; -// insn.Op1.addr = insn.get_next_byte(); -// insn.Op1.type = o_mem; - goto cont3; - - default: - if ( code > 0xC7 ) - { - aop(insn, code, insn.Op1); - } - else - { - aop(insn, code, insn.Op2); -cont3: - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - } - } - } - else if ( nibble1 == 0xD ) // jcc - { - static const char cmdd[] = - { - I196_jnst, I196_jnh, I196_jgt, I196_jnc, - I196_jnvt, I196_jnv, I196_jge, I196_jne, - I196_jst, I196_jh, I196_jle, I196_jc, - I196_jvt, I196_jv, I196_jlt, I196_je - }; - - insn.itype = cmdd[nibble0]; - - insn.Op1.type = o_near; - offc = insn.get_next_byte(); - insn.Op1.addr = truncate(insn.ip + insn.size + offc); // signed addition -// insn.Op1.dtype = dt_word; - } - else if ( nibble1 == 0xE ) // Ex - { - switch ( nibble0 ) - { - case 0x0: case 0x1: // djnz, djnzw - if ( nibble0 & 1 ) - { - insn.itype = I196_djnzw; - insn.Op1.dtype = dt_word; - } - else - { - insn.itype = I196_djnz; - } - insn.Op1.type = o_mem; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - offc = insn.get_next_byte(); - insn.Op2.type = o_near; - insn.Op2.addr = truncate(insn.ip + insn.size + offc); // signed addition - break; - - case 0x2: // tijmp - insn.itype = I196_tijmp; - insn.Op1.dtype = insn.Op2.dtype = dt_word; - insn.Op2.type = o_indirect; - insn.Op2.addr = map(insn.ea, insn.get_next_byte()); - insn.Op3.type = o_imm; - insn.Op3.value = insn.get_next_byte(); - insn.Op1.type = o_mem; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - break; - - case 0x3: // br - insn.itype = extended ? I196_ebr : I196_br; - aop(insn, 2, insn.Op1); - break; - - case 0x4: // ebmovi - if ( !extended ) - return 0; - insn.itype = I196_ebmovi; - insn.Op1.type = o_mem; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op2.type = o_mem; - insn.Op2.addr = map(insn.ea, insn.get_next_byte()); - break; - - case 0x6: // ejmp - if ( !extended ) - return 0; - insn.itype = I196_ejmp; - insn.Op1.type = o_near; - off = insn.get_next_word(); - off |= int32(insn.get_next_byte()) << 16; - insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition - break; - - case 0x8: // eld.indirect - case 0x9: // eld.indexed - return ld_st(insn, I196_eld, dt_word, nibble0 == 0x8, insn.Op1, insn.Op2); - - case 0xA: // eldb.indirect - case 0xB: // eldb.indexed - return ld_st(insn, I196_eldb, dt_byte, nibble0 == 0xA, insn.Op1, insn.Op2); - - case 0xC: // dpts - insn.itype = I196_dpts; - break; - - case 0xD: // epts - insn.itype = I196_epts; - break; - - case 0x7: case 0xF: // ljmp, lcall - insn.itype = (nibble0 & 8) ? I196_lcall : I196_ljmp; - insn.Op1.type = o_near; - off = short(insn.get_next_word()); - insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition - insn.Op1.dtype = dt_word; - break; - - default: - return 0; - } - } - else - { - static const char cmdf[] = - { - I196_ret, I196_ecall,I196_pushf, I196_popf, - I196_pusha, I196_popa, I196_idlpd, I196_trap, - I196_clrc, I196_setc, I196_di, I196_ei, - I196_clrvt, I196_nop, I196_null, I196_rst - }; - - insn.itype = cmdf[nibble0]; - if ( nibble0 == 1 ) // ecall - { - if ( !extended ) - return 0; - off = insn.get_next_word(); - off |= int32(insn.get_next_byte()) << 16; - insn.Op1.type = o_near; - insn.Op1.addr = truncate(insn.ip + insn.size + off); - } - else if ( nibble0 == 6 ) // idlpd - { - insn.Op1.type = o_imm; - insn.Op1.value = insn.get_next_byte(); - } - else if ( nibble0 == 0xE ) // prefix - { - code = insn.get_next_byte(); - - switch ( code & 0xFC ) - { - case 0x4C: case 0x5C: - if ( code & 0x10 ) - { - insn.itype = I196_mulb3; - insn.Op1.dtype = dt_word; - } - else - { - insn.itype = I196_mul3; - insn.Op3.dtype = insn.Op2.dtype = dt_word; - insn.Op1.dtype = dt_dword; - } - - aop(insn, code, insn.Op3); - insn.Op2.addr = map(insn.ea, insn.get_next_byte()); - insn.Op2.type = o_mem; - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - break; - - case 0x6C: case 0x7C: case 0x8C: case 0x9C: - insn.itype = (code & 0x80) - ? (code & 0x10) ? I196_divb : I196_div - : (code & 0x10) ? I196_mulb2 : I196_mul2; - - if ( code & 0x10 ) - { - insn.Op1.dtype = dt_word; - } - else - { - insn.Op1.dtype = dt_dword; - insn.Op2.dtype = dt_word; - } - - aop(insn, code, insn.Op2); - insn.Op1.addr = map(insn.ea, insn.get_next_byte()); - insn.Op1.type = o_mem; - break; - - default: - return 0; - } - } - } - - return insn.size; -} diff --git a/idasdk75/module/80196/makefile b/idasdk75/module/80196/makefile deleted file mode 100644 index 0635cac..0000000 --- a/idasdk75/module/80196/makefile +++ /dev/null @@ -1,40 +0,0 @@ -PROC=i196 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ana.cpp i196.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp emu.cpp i196.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp i196.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp i196.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp i196.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/arc/ana.cpp b/idasdk75/module/arc/ana.cpp deleted file mode 100644 index 2de8fc3..0000000 --- a/idasdk75/module/arc/ana.cpp +++ /dev/null @@ -1,2779 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 2012-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * ARC (Argonaut RISC Core) processor module - * - * Based on code contributed by by Felix Domke <tmbinc@gmx.net> - */ - -#include "arc.hpp" -#include <frame.hpp> - -/* -doRegisterOperand converts the 6 bit field 'code' to an IDA-"op_t"-operand. - -'d' is the maybe-used (signed) immediate in the lowest 9 bits, li is the -long-immediate which is loaded in the instruction decoding, since it's -loaded only once, even if an instructions uses multiple times a long immediate - -when it's all about a branch (isbranch is true), we have to multiply the absolute -address by 4, since it's granularity are words then (and not bytes) - -FYI: -register code 61 means "short immediate with .f-flag set", 63 "short immediate -without .f-flag" and 62 means "long immediate (4 bytes following the instruction, -making the instruction 8 bytes long (insn.size)). -*/ - -//---------------------------------------------------------------------- -void doRegisterOperand(int code, op_t &op, int d, int li, int isbranch) -{ - /* we always deal with double words, exceptions are load/stores - with 8 or 16 bits. these are covered by the instruction decoding */ - - op.dtype = dt_dword; - if ( code == SHIMM_F || code == SHIMM ) // short immediate with/wo flags - { - if ( isbranch ) - { - op.type = o_near; - op.addr = d * 4; - } - else - { - op.type = o_imm; - op.value = d; - } - } - else if ( code == LIMM ) // long immediate - { - if ( isbranch ) - { - op.type = o_near; - /* the upper 7 bits containing processor flags to set */ - /* they are handled in the instruction decoding, since */ - /* they produce a second (ida-)operand */ - op.addr = (li & 0x1FFFFFF) * 4; - } - else - { - op.type = o_imm; - op.value = li; - } - op.offb = 4; - } - else /* just a register */ - { - op.type = o_reg; - op.reg = uint16(code); - } -} - -//---------------------------------------------------------------------- -// make indirect [b,c] operand -// b c -// imm imm mem: [imm1+imm2] -// reg imm displ: [reg, imm] -// imm reg displ: [imm, reg] (membase=1) -// reg reg phrase: [reg, reg] -void arc_t::doIndirectOperand(const insn_t &insn, int b, int c, op_t &op, int d, int li, bool special) -{ - if ( is_imm(b) && is_imm(c) ) - { - // [#imm, #imm] - int imm1 = b == LIMM ? li : d; - int imm2 = c == LIMM ? li : d; - if ( special ) - { - // use a simple immediate for AUX reg numbers - op.type = o_imm; - op.value = imm1; - } - else - { - op.type = o_mem; - op.immdisp = is_a4() ? 0 : imm2; - op.addr = imm1 + imm2 * get_scale_factor(insn); - } - } - else if ( !is_imm(b) && !is_imm(c) ) - { - // [reg, reg] - op.type = o_phrase; - op.reg = b; - op.secreg = c; - } - else - { - op.type = o_displ; - if ( is_imm(c) ) - { - // [reg, #imm] - op.reg = b; - op.addr = c == LIMM ? li : d; - if ( special ) - op.addr = 0; - op.membase = 0; - } - else - { - // [#imm, reg] - op.reg = c; - op.addr = b == LIMM ? li : d; - op.membase = 1; - } - } - switch ( insn.auxpref & aux_zmask ) - { - default: - op.dtype = dt_dword; - break; - case aux_b: - op.dtype = dt_byte; - break; - case aux_w: - op.dtype = dt_word; - break; - } -} - -//---------------------------------------------------------------------- -// doBranchOperand handles pc-relative word offsets. -// nothing special here. -void doBranchOperand(const insn_t &insn, op_t &op, int l) -{ - op.dtype = dt_dword; - op.type = o_near; - op.addr = insn.ip + l * 4 + 4; - op.offb = 0; -} - -//---------------------------------------------------------------------- -void arc_t::doRegisterInstruction(insn_t &insn, uint32 code) -{ - - int i = (code >> 27) & 31; - int a = (code >> 21) & 63; - int b = (code >> 15) & 63; - int c = (code >> 9) & 63; - - /* the (maybe used?) short immediate value */ - uint32 d = code & 0x1FF; - - // sign-extend - if ( d >= 0x100 ) - d -= 0x200; - - /* store the flags. if there are actually no flags at that place, they */ - /* will be reconstructed later */ - insn.auxpref = code & (aux_cmask|aux_f); - - switch ( i ) - { - case 0: // LD register+register - insn.itype = ARC_ld; - insn.auxpref |= (code & aux_di); - break; - case 1: // LD register+offset, LR - if ( code & (1 << 13) ) - insn.itype = ARC_lr; - else - insn.itype = ARC_ld; - break; - case 2: // ST, SR - if ( code & (1 << 25) ) - { - insn.itype = ARC_sr; - } - else - { - insn.itype = ARC_st; - // 26 = Di - // 24 = A - // 23..22 = ZZ - insn.auxpref = (code >> 20) & (aux_di|aux_amask|aux_zmask); - } - break; - case 3: // single operand instructions - switch ( c ) - { - case 0: - insn.itype = ARC_flag; - a = b; // flag has no 'a' operand, so we're moving the b-operand to a. - break; - case 1: - insn.itype = ARC_asr; - break; - case 2: - insn.itype = ARC_lsr; - break; - case 3: - insn.itype = ARC_ror; - break; - case 4: - insn.itype = ARC_rrc; - break; - case 5: - insn.itype = ARC_sexb; - break; - case 6: - insn.itype = ARC_sexw; - break; - case 7: - insn.itype = ARC_extb; - break; - case 8: - insn.itype = ARC_extw; - break; - case 9: - insn.itype = ARC_swap; - break; - case 10: - insn.itype = ARC_norm; - break; - case 0x3F: - switch ( d ) - { - case 0: - insn.itype = ARC_brk; - break; - case 1: - insn.itype = ARC_sleep; - break; - case 2: - insn.itype = ARC_swi; - break; - default: - return; - } - a = b = -1; - insn.auxpref = 0; - break; - } - c = -1; // c operand is no real operand, so don't try to convert it. - break; - case 7: // Jcc, JLcc - insn.itype = ARC_j; - if ( code & (1<<9) ) - insn.itype = ARC_jl; - else - insn.itype = ARC_j; - // copy the NN bits - insn.auxpref |= (code & aux_nmask); - break; - case 8: // ADD - insn.itype = ARC_add; - break; - case 9: // ADC - insn.itype = ARC_adc; - break; - case 10: // SUB - insn.itype = ARC_sub; - break; - case 11: // SBC - insn.itype = ARC_sbc; - break; - case 12: // AND - insn.itype = ARC_and; - break; - case 13: // OR - insn.itype = ARC_or; - break; - case 14: // BIC - insn.itype = ARC_bic; - break; - case 15: // XOR - insn.itype = ARC_xor; - break; - case 0x10: - insn.itype = ARC_asl; - break; - case 0x11: - insn.itype = ARC_lsr; - break; - case 0x12: - insn.itype = ARC_asr; - break; - case 0x13: - insn.itype = ARC_ror; - break; - case 0x14: - insn.itype = ARC_mul64; - break; - case 0x15: - insn.itype = ARC_mulu64; - break; - case 0x1E: - insn.itype = ARC_max; - break; - case 0x1F: - insn.itype = ARC_min; - break; - } - - uint32 immediate = 0; - int noop3 = 0, isnop = 0; - - if ( a == SHIMM_F || b == SHIMM_F || c == SHIMM_F ) - insn.auxpref = aux_f; // .f - - if ( b == SHIMM || c == SHIMM ) - insn.auxpref = 0; - - if ( b == LIMM || c == LIMM ) - immediate = insn.get_next_dword(); - - /* - pseudo instruction heuristic: - - we have some types of pseudo-instructions: - - (rS might be an immediate) - insn will be coded as - move rD, rS and rD, rS, rS - asl rD, rS add rD, rS, rS - lsl rD, rS add rD, rS, rS (the same as asl, of course...) - rlc rD, rS adc.f rD, rS, rS - rol rD, rS add.f rD, rS, rS; adc rD, rD, 0 - nop xxx 0, 0, 0 - */ - - switch ( insn.itype ) - { - case ARC_flag: - // special handling for flag, since its a-operand is a source here - b = -1; - break; - - case ARC_and: - case ARC_or: - if ( b == c ) - { - noop3 = 1; - insn.itype = ARC_mov; - } - break; - - case ARC_add: - if ( b == c ) - { - noop3 = 1; - if ( b >= SHIMM_F ) - { - // add rD, imm, imm -> move rD, imm*2 - insn.itype = ARC_mov; - d <<= 1; - immediate <<= 1; - } - else - { - insn.itype = ARC_lsl; - } - } - break; - - case ARC_adc: - if ( b == c ) - { - noop3 = 1; - insn.itype = ARC_rlc; - } - break; - - case ARC_xor: - if ( code == 0x7FFFFFFF ) // XOR 0x1FF, 0x1FF, 0x1FF - isnop = 1; - break; - } - - //if ( (i>=8) && (i != 0x14) && (i!=0x15) && (a>62) && !(insn.auxpref&(1<<8)) ) // 3 operands, but target is immediate and no flags to set - // isnop=1; - - if ( !isnop ) - { - if ( i == 0 ) - { - // ld a, [b,c] - doRegisterOperand(a, insn.Op1, d, immediate, 0); - doIndirectOperand(insn, b, c, insn.Op2, d, immediate, false); - } - else if ( i == 1 || i == 2 ) - { - /* fetch the flag-bits from the right location */ - if ( insn.itype == ARC_ld ) - insn.auxpref = (code >> 9) & 0x3F; - else if ( insn.itype == ARC_st ) - insn.auxpref = (code >> 21) & 0x3F; - else - insn.auxpref = 0; - if ( insn.itype == ARC_st || insn.itype == ARC_sr ) - { - /* in a move to special register or load from special register, - we have the target operand somewhere else */ - a = c; - /* c=-1; not used anyway */ - } - doRegisterOperand(a, insn.Op1, d, immediate, 0); - doIndirectOperand(insn, b, SHIMM, insn.Op2, d, immediate, insn.itype == ARC_lr || insn.itype == ARC_sr); - } - else if ( i == 7 ) - { - /* the jump (absolute) instruction, with a special imm-encoding */ - doRegisterOperand(b, insn.Op1, d, immediate, 1); - } - else - { - if ( a != -1 ) - doRegisterOperand(a, insn.Op1, 0, immediate, 0); - /* this is a bugfix for the gnu-as: long immediate must be equal, while short */ - /* immediates don't have to. */ - if ( b != -1 ) - doRegisterOperand(b, insn.Op2, d, immediate, 0); - if ( c != -1 && !noop3 ) - doRegisterOperand(c, insn.Op3, d, immediate, 0); - } - } - else - { - insn.itype = ARC_nop; - insn.auxpref = 0; - } -} - -//---------------------------------------------------------------------- -void doBranchInstruction(insn_t &insn, uint32 code) -{ - int i = (code >> 27) & 31; - - int l = (code >> 7) & 0xFFFFF; // note: bits 21..2, so it's in WORDS - - if ( l >= 0x80000 ) // sign-extend - l = l - 0x100000; - - doBranchOperand(insn, insn.Op1, l); - - switch ( i ) - { - case 4: // Bcc - insn.itype = ARC_b; - break; - case 5: // BLcc - insn.itype = ARC_bl; - break; - case 6: // LPcc - insn.itype = ARC_lp; - break; - } - insn.auxpref = code & (aux_cmask | aux_nmask); -} - -//---------------------------------------------------------------------- -// analyze ARCTangent-A4 (32-bit) instruction -int arc_t::ana_old(insn_t &insn) -{ - if ( insn.ea & 3 ) - return 0; - - insn.Op1.dtype = dt_dword; - insn.Op2.dtype = dt_dword; - insn.Op3.dtype = dt_dword; - - uint32 code = insn.get_next_dword(); - - int i = (code >> 27) & 31; - - insn.itype = 0; - - switch ( i ) - { - case 0: // LD register+register - case 1: // LD register+offset, LR - case 2: // ST, SR - case 3: // single operand instructions - doRegisterInstruction(insn, code); - break; - case 4: // Bcc - case 5: // BLcc - case 6: // LPcc - doBranchInstruction(insn, code); - break; - case 7: // Jcc, JLcc - case 8: // ADD - case 9: // ADC - case 10: // SUB - case 11: // ADC - case 12: // AND - case 13: // OR - case 14: // BIC - case 15: // XOR - default: - doRegisterInstruction(insn, code); - break; - } - - return insn.size; -} - -#define SUBTABLE(high, low, name) (0x80000000 | (high << 8) | low), 0, { 0,0,0 }, name -#define SUBTABLE2(high1, low1, high2, low2, name) (0x80000000 | (high1 << 24) | (low1 << 16) | (high2 << 8) | low2), 0, { 0,0,0 }, name - -//---------------------------------------------------------------------- -struct arcompact_opcode_t -{ - uint32 mnem; // instruction itype, or indicator of sub-field decoding - uint32 aux; // auxpref and other flags - uint32 ops[3]; // description of operands - const arcompact_opcode_t *subtable; //lint !e958 padding is required to align members -}; - -enum aux_flags_t ENUM_SIZE(uint32) -{ - AUX_B = 1, // implicit byte size access - AUX_W = 2, // implicit word size access - Q_4_0 = 4, // 4..0 QQQQQ condition code - AAZZXD_23_15 = 8, // 23..22,18..15 aa, ZZ, X, D flags (load reg+reg) - DAAZZX_11_6 = 0x10, // 11..6 Di, aa, ZZ, X flags (load) - DAAZZ_5_1 = 0x20, // 5..0 Di, aa, ZZ, R flags (store) - AUX_D = 0x40, // implicit delay slot (.d) - AUX_X = 0x80, // implicit sign extend (.x) - AUX_CND = 0x100, // implicit condition (in low 5 bits) - N_5 = 0x200, // 5..5 N delay slot bit - AUX_GEN = 0x400, // 4..0 = Q if 23..22=0x3, bit 15 = F - AUX_GEN2 = 0x800, // 4..0 = Q if 23..22=0x3 - AUX_GEN3 = - AUX_GEN|AUX_GEN2, // 4..0 = Q if 23..22=0x3, bit 15 = Di - AUX_V2 = 0x1000, // only available on ARCv2 - AUX_F = 0x2000, // use alternative instruction when F = 1 - AUX_AS = 0x8000, // implicit scaled access - Q_5_0 = 0x10000, // 5..0 0QQQQQ condition code - Y_3 = 0x20000, // 3 Y static branch prediction bit -}; - -enum op_fields_t ENUM_SIZE(uint32) -{ - fA32=1, // 5..0 a register operand (6 bits, r0-r63) - fA16, // 2..0 a register operand (3 bits, r0-r3, r12-r15) - fB32, // 14..12 & 26..24 b register operand (6 bits) - fB16, // 10..8 b register operand (3 bits) - fC32, // 11..6 c register operand (6 bits) - fC32_w6, // 11..6 & 0 c/w6 register/immediate operand (6 bits) - fC16, // 7..5 c register operand (3 bits) - fH16, // 2..0 & 7..5 h register operand (6 bits) - fH16v2, // 1..0 & 7..5 h register operand (5 bits) - fH16v2_U5, // 1..0 & 7..5, 10&4..3 [h, u5] (u5=u3*4) - fG16, // 4..3 & 10..8 g register operand (5 bits) - fR16_2, // 9..8 R register operand (2 bits) - fR16_1, // 7 R register operand (1 bit) - S25, // 15..6 & 26..17 & 0..3 s25 signed branch displacement - S21, // 15..6 & 26..17 s21 signed branch displacement - S25L, // 15..6 & 26..18 & 0..3 s25 signed branch displacement for branch and link - S21L, // 15..6 & 26..18 s21 signed branch displacement for branch and link - S10, // 8..0 s10 signed branch displacement - S9, // 15..15 & 23..17 s9 signed branch displacement - S8, // 6..0 s8 signed branch displacement - S7, // 5..0 s7 signed branch displacement - S13, // 10..0 s13 signed branch displacement - U3, // 2..0 u2 unsigned immediate - U5, // 4..0 u5 unsigned immediate - U6, // 11..6 u6 unsigned immediate - U6_SWI, // 10..5 u6 unsigned immediate - U7, // 6..0 u7 unsigned immediate - U7L, // 4..0 u7 unsigned immediate (u5*4) - U8, // 7..0 u8 unsigned immediate - U6_16, // 6..4 & 2..0 u6 unsigned immediate - U7_16, // 7..4 & 2..0 u7 unsigned immediate - U10_16, // 9..0 u10 unsigned immediate - SP_U7, // 4..0 [SP, u7] stack + offset (u7 = u5*4) - PCL_U10, // 7..0 [PCL, u10] PCL + offset (u8*4) - fB_U5, // 10..8 & 4..0 [b, u5] - fB_U6, // 10..8 & 4..0 [b, u6] (u6=u5*2) - fB_U7, // 10..8 & 4..0 [b, u7] (u6=u5*4) - fB_S9, // 14..12&26..26, 15&23..16 [b, s9] - GENA, // 5..0 - GENB, // 14..12 & 26..24 - GENC, // 11..6 or 5..0 & 11..6 - GENC_PCREL, // 11..6 or 5..0 & 11..6 - fBC_IND, // 14..12 & 26..24, 11..6 [b, c] - fBC16_IND, // 10..8, 7..5 [b, c] - R_SP, // implicit SP - R_BLINK, // implicit BLINK - O_ZERO, // implicit immediate 0 - R_R0, // implicit R0 - R_R1, // implicit R1 - R_GP, // implicit GP - GP_S9, // 8..0 [GP, s9] GP + offset - GP_S10, // 8..0 [GP, s10] GP + offset (s10 = s9*2) - GP_S11, // 8..0 [GP, s11] GP + offset (s11 = s9*4) - S11, // 8..0 s11 signed immediate (s11 = s9*4) - GP_S11_16, // 10..5 & 4..2 [GP, s11] GP + offset (s11 = s9*4) - S3, // 10..8 s3 signed immediate - EL, // 4..1 & 10..8 enter / leave register set - - O_IND = 0x80000000, // [reg], [imm] (jumps: only [reg]) - O_WIDE = 0x40000000, // register pair rNrN+1 with N even - O_IDX = 0x20000000, // instruction specific index - - O_FLAGS = O_IND|O_WIDE|O_IDX, -}; - -// indexed by bit 16 (maj = 0) -static const arcompact_opcode_t arcompact_maj0[2] = -{ - { ARC_b, Q_4_0 | N_5, {S21, 0, 0}, NULL }, // 0 - { ARC_b, N_5, {S25, 0, 0}, NULL }, // 1 -}; - -// indexed by bit 17 (maj = 1, b16 = 0) -static const arcompact_opcode_t arcompact_bl[2] = -{ - { ARC_bl, Q_4_0 | N_5, {S21L, 0, 0}, NULL }, // 0 - { ARC_bl, N_5, {S25L, 0, 0}, NULL }, // 1 -}; - -// indexed by bits 3..0 (maj = 1, b16 = 1, b4 = 0) -static const arcompact_opcode_t arcompact_br_regreg[0x10] = -{ - { ARC_br, AUX_CND|cEQ|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x00 - { ARC_br, AUX_CND|cNE|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x01 - { ARC_br, AUX_CND|cLT|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x02 - { ARC_br, AUX_CND|cGE|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x03 - { ARC_br, AUX_CND|cLO|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x04 - { ARC_br, AUX_CND|cHS|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x05 - { ARC_bbit0, N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x06 - { ARC_bbit1, N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x07 - { ARC_br, AUX_CND|cEQ|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x08 - { ARC_br, AUX_CND|cNE|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x09 - { ARC_br, AUX_CND|cLT|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0A - { ARC_br, AUX_CND|cGE|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0B - { ARC_br, AUX_CND|cLO|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0C - { ARC_br, AUX_CND|cHS|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0D - { ARC_bbit0, N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x0E - { ARC_bbit1, N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x0F -}; - -// indexed by bits 3..0 (maj = 1, b16 = 1, b4 = 1) -static const arcompact_opcode_t arcompact_br_regimm[0x10] = -{ - { ARC_br, AUX_CND|cEQ|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x00 - { ARC_br, AUX_CND|cNE|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x01 - { ARC_br, AUX_CND|cLT|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x02 - { ARC_br, AUX_CND|cGE|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x03 - { ARC_br, AUX_CND|cLO|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x04 - { ARC_br, AUX_CND|cHS|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x05 - { ARC_bbit0, N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x06 - { ARC_bbit1, N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x07 - { ARC_br, AUX_CND|cEQ|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x08 - { ARC_br, AUX_CND|cNE|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x09 - { ARC_br, AUX_CND|cLT|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0A - { ARC_br, AUX_CND|cGE|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0B - { ARC_br, AUX_CND|cLO|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0C - { ARC_br, AUX_CND|cHS|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0D - { ARC_bbit0, N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x0E - { ARC_bbit1, N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x0F -}; - -// indexed by bit 4 (maj = 1, b16 = 1) -static const arcompact_opcode_t arcompact_br[4] = -{ - { SUBTABLE( 3, 0, arcompact_br_regreg) }, // 0 - { SUBTABLE( 3, 0, arcompact_br_regimm) }, // 1 -}; - -// indexed by bit 16 (maj = 1) -static const arcompact_opcode_t arcompact_maj1[0x40] = -{ - { SUBTABLE(17, 17, arcompact_bl) }, // 0 - { SUBTABLE( 4, 4, arcompact_br) }, // 1 -}; - -// indexed by bits 14..12 & 26..24 (maj = 4, 21..16=0x2F, 5..0=0x3F) -static const arcompact_opcode_t arcompact_zop[0x40] = -{ - { 0 }, // 0x00 - { ARC_sleep, 0, {GENC, 0, 0}, NULL }, // 0x01 - { ARC_swi, 0, { 0, 0, 0}, NULL }, // 0x02 - { ARC_sync, 0, { 0, 0, 0}, NULL }, // 0x03 - { ARC_rtie, 0, { 0, 0, 0}, NULL }, // 0x04 - { ARC_brk, 0, { 0, 0, 0}, NULL }, // 0x05 - { ARC_seti,AUX_V2,{GENC, 0, 0}, NULL }, // 0x06 - { ARC_clri,AUX_V2,{GENC, 0, 0}, NULL }, // 0x07 - { ARC_wevt, 0, {GENC, 0, 0}, NULL }, // 0x08 - { 0 }, // 0x09 - { 0 }, // 0x0A - { 0 }, // 0x0B - { 0 }, // 0x0C - { 0 }, // 0x0D - { 0 }, // 0x0E - { 0 }, // 0x0F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { 0 }, // 0x28 - { 0 }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { 0 }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F -}; - -// indexed by bits 5..0 (maj = 4, 21..16=0x2F) -static const arcompact_opcode_t arcompact_sop[0x40] = -{ - { ARC_asl, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x00 - { ARC_asr, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x01 - { ARC_lsr, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x02 - { ARC_ror, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x03 - { ARC_rrc, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x04 - { ARC_sexb, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x05 - { ARC_sexw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x06 - { ARC_extb, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x07 - { ARC_extw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x08 - { ARC_abs, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x09 - { ARC_not, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0A - { ARC_rlc, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0B - { ARC_ex, AUX_GEN, {GENB, GENC|O_IND,0},NULL}, // 0x0C - { ARC_rol, AUX_V2|AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0D - { 0 }, // 0x0E - { 0 }, // 0x0F - { ARC_llock,AUX_GEN, {GENB, GENC|O_IND, 0}, NULL }, // 0x10 - { ARC_scond,AUX_GEN, {GENB, GENC|O_IND, 0}, NULL }, // 0x11 - { 0 }, // 0x12 - { 0 }, // 0x13 - { 0 }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { 0 }, // 0x18 - { 0 }, // 0x19 - { 0 }, // 0x1A - { 0 }, // 0x1B - { 0 }, // 0x1C - { 0 }, // 0x1D - { 0 }, // 0x1E - { 0 }, // 0x1F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { 0 }, // 0x28 - { 0 }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { 0 }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { SUBTABLE2(14, 12, 26, 24, arcompact_zop) },// 0x3F -}; - -// indexed by bits 21..16 (maj = 4) -static const arcompact_opcode_t arcompact_maj4[0x40] = -{ - { ARC_add, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00 - { ARC_adc, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01 - { ARC_sub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02 - { ARC_sbc, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03 - { ARC_and, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x04 - { ARC_or, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x05 - { ARC_bic, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06 - { ARC_xor, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07 - { ARC_max, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08 - { ARC_min, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x09 - { ARC_mov, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0A - { ARC_tst, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x0B - { ARC_cmp, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x0C - { ARC_rcmp, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0D - { ARC_rsub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E - { ARC_bset, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F - { ARC_bclr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10 - { ARC_btst, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x11 - { ARC_bxor, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x12 - { ARC_bmsk, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x13 - { ARC_add1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x14 - { ARC_add2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x15 - { ARC_add3, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x16 - { ARC_sub1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x17 - { ARC_sub2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x18 - { ARC_sub3, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x19 - { ARC_mpy, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1A - { ARC_mpyh, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1B - { ARC_mpyhu,AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C - { ARC_mpyu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D - { ARC_mpyw, AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1E - { ARC_mpyuw,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1F - { ARC_j, AUX_GEN, {GENC|O_IND, 0, 0}, NULL }, // 0x20 - { ARC_j, AUX_GEN|AUX_D, {GENC|O_IND, 0, 0}, NULL }, // 0x21 - { ARC_jl, AUX_GEN, {GENC|O_IND, 0, 0}, NULL }, // 0x22 - { ARC_jl, AUX_GEN|AUX_D, {GENC|O_IND, 0, 0}, NULL }, // 0x23 - { ARC_bi, AUX_V2, {fC32|O_IDX, 0, 0}, NULL }, // 0x24 - { ARC_bih, AUX_V2, {fC32|O_IDX, 0, 0}, NULL }, // 0x25 - { ARC_ldi, AUX_V2|Q_5_0, {GENB, GENC|O_IDX, 0}, NULL }, // 0x26 - { ARC_aex, AUX_V2|AUX_GEN2, {fB32, GENC|O_IND, 0}, NULL }, // 0x27 - { ARC_lp, AUX_GEN2, {GENC_PCREL, 0, 0}, NULL }, // 0x28 - { ARC_flag, AUX_GEN2, {GENC, 0, 0}, NULL }, // 0x29 - { ARC_lr, 0, {GENB, GENC|O_IND, 0}, NULL }, // 0x2A - { ARC_sr, 0, {GENB, GENC|O_IND, 0}, NULL }, // 0x2B - { ARC_bmskn,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C - { ARC_null, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C - { ARC_null, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D - { SUBTABLE(5, 0, arcompact_sop) }, // 0x2F - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x30 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x31 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x32 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x33 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x34 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x35 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x36 - { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x37 - { ARC_seteq,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x38 - { ARC_setne,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x39 - { ARC_setlt,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3A - { ARC_setge,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3B - { ARC_setlo,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3C - { ARC_seths,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3D - { ARC_setle,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3E - { ARC_setgt,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3F -}; - -// indexed by bits 14..12 & 26..24 (maj = 5, 21..16=0x2F, 5..0=0x3F) -static const arcompact_opcode_t arcompact_zop5[0x40 * 2] = -{ - { ARC_aslacc, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x00 - { ARC_aslsacc, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x01 - { 0 }, // 0x02 - { 0 }, // 0x03 - { 0, AUX_F, {0, 0, 0}, NULL }, // 0x04(F=0) - { ARC_modif, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x05 - { 0 }, // 0x06 - { 0 }, // 0x07 - { 0 }, // 0x08 - { 0 }, // 0x09 - { 0 }, // 0x0A - { 0 }, // 0x0B - { 0 }, // 0x0C - { 0 }, // 0x0D - { 0 }, // 0x0E - { 0 }, // 0x0F - { 0 }, // 0x10 - { 0 }, // 0x11 - { 0 }, // 0x12 - { 0 }, // 0x13 - { 0 }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { 0 }, // 0x18 - { 0 }, // 0x19 - { 0 }, // 0x1A - { 0 }, // 0x1B - { 0 }, // 0x1C - { 0 }, // 0x1D - { 0 }, // 0x1E - { 0 }, // 0x1F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { 0 }, // 0x28 - { 0 }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { 0 }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F - - { 0 }, // 0x00 - { 0 }, // 0x01 - { 0 }, // 0x02 - { 0 }, // 0x03 - { ARC_flagacc, AUX_V2, {GENC, 0, 0}, NULL }, // 0x04(F=1) - { 0 }, // 0x05 - { 0 }, // 0x06 - { 0 }, // 0x07 - { 0 }, // 0x08 - { 0 }, // 0x09 - { 0 }, // 0x0A - { 0 }, // 0x0B - { 0 }, // 0x0C - { 0 }, // 0x0D - { 0 }, // 0x0E - { 0 }, // 0x0F - { 0 }, // 0x10 - { 0 }, // 0x11 - { 0 }, // 0x12 - { 0 }, // 0x13 - { 0 }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { 0 }, // 0x18 - { 0 }, // 0x19 - { 0 }, // 0x1A - { 0 }, // 0x1B - { 0 }, // 0x1C - { 0 }, // 0x1D - { 0 }, // 0x1E - { 0 }, // 0x1F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { 0 }, // 0x28 - { 0 }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { 0 }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F -}; - -// indexed by bits 5..0 (maj = 5, 21..16=0x2F) -static const arcompact_opcode_t arcompact_sop5[0x40] = -{ - { ARC_swap, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x00 - { ARC_norm, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x01 - { ARC_sat16, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x02 - { ARC_rnd16, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x03 - { ARC_abssw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x04 - { ARC_abss, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x05 - { ARC_negsw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x06 - { ARC_negs, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x07 - { ARC_normw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x08 - { ARC_swape, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x09 - { ARC_lsl16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0A - { ARC_lsr16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0B - { ARC_asr16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0C - { ARC_asr8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0D - { ARC_lsr8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0E - { ARC_lsl8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0F - { ARC_rol8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x10 - { ARC_ror8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x11 - { ARC_ffs, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x12 - { ARC_fls, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x13 - { 0 }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { ARC_getacc, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x18 - { ARC_normacc, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x19 - { ARC_satf, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1A - { 0 }, // 0x1B - { ARC_vpack2hbl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1C - { ARC_vpack2hbm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1D - { ARC_vpack2hblf,AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1E - { ARC_vpack2hbmf,AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1F - { ARC_vext2bhlf, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x20 - { ARC_vext2bhmf, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x21 - { ARC_vrep2hl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x22 - { ARC_vrep2hm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x23 - { ARC_vext2bhl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x24 - { ARC_vext2bhm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x25 - { ARC_vsext2bhl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x26 - { ARC_vsext2bhm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x27 - { ARC_vabs2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x28 - { ARC_vabss2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x29 - { ARC_vneg2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2A - { ARC_vnegs2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2B - { ARC_vnorm2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2C - { 0 }, // 0x2D - { ARC_bspeek, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2E - { ARC_bspop, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2F - { ARC_sqrt, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x30 - { ARC_sqrtf, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { SUBTABLE2(14, 12, 26, 24, arcompact_zop5) }, // 0x3F -}; - -// indexed by bits 21..16 (maj = 5) -static const arcompact_opcode_t arcompact_maj5[0x40] = -{ - { ARC_asl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00 - { ARC_lsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01 - { ARC_asr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02 - { ARC_ror, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03 - { ARC_mul64, AUX_GEN, {O_ZERO,GENB,GENC}, NULL }, // 0x04 - { ARC_mulu64, AUX_GEN, {O_ZERO,GENB,GENC}, NULL }, // 0x05 - { ARC_adds, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06 - { ARC_subs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07 - { ARC_divaw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08 - { 0 }, // 0x09 - { ARC_asls, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A - { ARC_asrs, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0B - { ARC_muldw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0C - { ARC_muludw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0D - { ARC_mulrdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0E - { 0 }, // 0x0F - { ARC_macdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x10 - { ARC_macudw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x11 - { ARC_macrdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x12 - { 0 }, // 0x13 - { ARC_msubdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { 0 }, // 0x18 - { 0 }, // 0x19 - { 0 }, // 0x1A - { 0 }, // 0x1B - { 0 }, // 0x1C - { 0 }, // 0x1D - { 0 }, // 0x1E - { 0 }, // 0x1F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { ARC_addsdw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28 - { ARC_subsdw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { SUBTABLE(5, 0, arcompact_sop5) }, // 0x2F - { ARC_mululw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x30 - { ARC_mullw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x31 - { ARC_mulflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x32 - { ARC_maclw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x33 - { ARC_macflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x34 - { ARC_machulw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x35 - { ARC_machlw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x36 - { ARC_machflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x37 - { ARC_mulhlw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x38 - { ARC_mulhflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F -}; - -// indexed by bits 21..16 (maj = 5) -static const arcompact_opcode_t arcv2_maj5[0x40 * 2] = -{ - { ARC_asl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00 - { ARC_lsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01 - { ARC_asr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02 - { ARC_ror, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03 - { ARC_div, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x04 - { ARC_divu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x05 - { ARC_adds, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06 - { ARC_subs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07 - { ARC_rem, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08 - { ARC_remu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x09 - { ARC_asls, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A - { ARC_asrs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0B - { ARC_asrsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0C - { ARC_valgn2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x0D(F=0) - { ARC_mac, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E - { ARC_macu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F - { ARC_dmpyh, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10 - { ARC_dmpyhu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x11 - { ARC_dmach, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x12 - { ARC_dmachu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x13 - { ARC_vadd2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x14(F=0) - { ARC_vsub2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x15(F=0) - { ARC_vaddsub2h,AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x16(F=0) - { ARC_vsubadd2h,AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x17(F=0) - { ARC_mpyd, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x18 - { ARC_mpydu, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x19 - { ARC_macd, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1A - { ARC_macdu, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1B - { ARC_vmpy2h, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1C(F=0) - { ARC_vmpy2hu, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1D(F=0) - { ARC_vmac2h, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1E(F=0) - { ARC_vmac2hu, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1F(F=0) - { ARC_vmpy2hwf, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x20(F=0) - { ARC_vasl2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x21(F=0) - { ARC_vasr2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x22(F=0) - { ARC_vlsr2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x23(F=0) - { ARC_vadd4b, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x24(F=0) - { ARC_vsub4b, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x25(F=0) - { ARC_adcs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x26 - { ARC_sbcs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x27 - { ARC_dmpyhwf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28 - { ARC_vpack2hl, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x29(F=0) - { ARC_dmpyhf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2A - { ARC_dmpyhfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2B - { ARC_dmachf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C - { ARC_dmachfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2D - { ARC_vperm, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x2E - { SUBTABLE(5, 0, arcompact_sop5) }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F - - { 0 }, // 0x00(F=1) - { 0 }, // 0x01(F=1) - { 0 }, // 0x02(F=1) - { 0 }, // 0x03(F=1) - { 0 }, // 0x04(F=1) - { 0 }, // 0x05(F=1) - { 0 }, // 0x06(F=1) - { 0 }, // 0x07(F=1) - { 0 }, // 0x08(F=1) - { 0 }, // 0x09(F=1) - { 0 }, // 0x0A(F=1) - { 0 }, // 0x0B(F=1) - { 0 }, // 0x0C(F=1) - { ARC_setacc, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x0D(F=1) - { 0 }, // 0x0E(F=1) - { 0 }, // 0x0F(F=1) - { 0 }, // 0x10(F=1) - { 0 }, // 0x11(F=1) - { 0 }, // 0x12(F=1) - { 0 }, // 0x13(F=1) - { ARC_vadds2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x14(F=1) - { ARC_vsubs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x15(F=1) - { ARC_vaddsubs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x16(F=1) - { ARC_vsubadds2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x17(F=1) - { 0 }, // 0x18(F=1) - { 0 }, // 0x19(F=1) - { 0 }, // 0x1A(F=1) - { 0 }, // 0x1B(F=1) - { ARC_vmpy2hf, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1C(F=1) - { ARC_vmpy2hfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1D(F=1) - { ARC_vmac2hf, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1E(F=1) - { ARC_vmac2hfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1F(F=1) - { 0 }, // 0x20(F=1) - { ARC_vasls2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x21(F=1) - { ARC_vasrs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x22(F=1) - { ARC_vasrsr2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x23(F=1) - { ARC_vmax2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x24(F=1) - { ARC_vmin2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x25(F=1) - { 0 }, // 0x26(F=1) - { 0 }, // 0x27(F=1) - { 0 }, // 0x28(F=1) - { ARC_vpack2hm, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x29(F=1) - { 0 }, // 0x2A(F=1) - { 0 }, // 0x2B(F=1) - { 0 }, // 0x2C(F=1) - { 0 }, // 0x2D(F=1) - { ARC_bspush, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x2E(F=1) - { 0 }, // 0x2F(F=1) - { 0 }, // 0x30(F=1) - { 0 }, // 0x31(F=1) - { 0 }, // 0x32(F=1) - { 0 }, // 0x33(F=1) - { 0 }, // 0x34(F=1) - { 0 }, // 0x35(F=1) - { 0 }, // 0x36(F=1) - { 0 }, // 0x37(F=1) - { 0 }, // 0x38(F=1) - { 0 }, // 0x39(F=1) - { 0 }, // 0x3A(F=1) - { 0 }, // 0x3B(F=1) - { 0 }, // 0x3C(F=1) - { 0 }, // 0x3D(F=1) - { 0 }, // 0x3E(F=1) - { 0 }, // 0x3F(F=1) -}; - -// indexed by bits 21..16 -static const arcompact_opcode_t arcompact_maj6_1[0x40] = -{ - { ARC_fmul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 00 - { ARC_fadd, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 01 - { ARC_fsub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 02 - { 0 }, // 03 - { 0 }, // 04 - { 0 }, // 05 - { 0 }, // 06 - { 0 }, // 07 - { ARC_dmulh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 08 - { ARC_dmulh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 09 - { ARC_dmulh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0a - { ARC_dmulh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0b - { ARC_daddh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0c - { ARC_daddh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0d - { ARC_daddh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0e - { ARC_daddh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0f - { ARC_dsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 10 - { ARC_dsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 11 - { ARC_dsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 12 - { ARC_dsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 13 - { ARC_drsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 14 - { ARC_drsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 15 - { ARC_drsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 16 - { ARC_drsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 17 - { ARC_dexcl1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 18 - { ARC_dexcl2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 19 - { 0 }, // 1a - { 0 }, // 1b - { 0 }, // 1c - { 0 }, // 1d - { 0 }, // 1e - { 0 }, // 1f - { ARC_pkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 20 - { ARC_upkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 21 - { ARC_xpkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 22 - { ARC_avgqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 23 - { ARC_addqbs, AUX_GEN, {GENA, GENB, GENC}, NULL },// 24 - { ARC_mpyqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 25 - { ARC_fxtr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 26 - { ARC_iaddr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 27 - { ARC_acm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 28 - { ARC_sfxtr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 29 - { ARC_clamp, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 2a - { 0 }, // 2b - { 0 }, // 2c - { 0 }, // 2d - { 0 }, // 2e - { 0 }, // 2f - { 0 }, // 30 - { 0 }, // 31 - { 0 }, // 32 - { 0 }, // 33 - { 0 }, // 34 - { 0 }, // 35 - { 0 }, // 36 - { 0 }, // 37 - { 0 }, // 38 - { 0 }, // 39 - { 0 }, // 3a - { 0 }, // 3b - { 0 }, // 3c - { 0 }, // 3d - { 0 }, // 3e - { 0 } // 3f -}; - -// indexed by bits 23..22 -static const arcompact_opcode_t arcompact_maj6[4] = -{ - { SUBTABLE(21, 16, arcompact_maj6_1) }, // 00 - { SUBTABLE(21, 16, arcompact_maj6_1) }, // 01 - { SUBTABLE(21, 16, arcompact_maj6_1) }, // 02 - { 0 } // to be implemented -}; - -// indexed by bits 5..0 (maj = 6, 21..16=0x2F) -static const arcompact_opcode_t arcv2_sop6[0x40] = -{ - { ARC_fssqrt, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x00(F=0) reference doesn't specify minor opcode - { 0 }, // 0x01 - { 0 }, // 0x02 - { 0 }, // 0x03 - { 0 }, // 0x04 - { 0 }, // 0x05 - { 0 }, // 0x06 - { 0 }, // 0x07 - { 0 }, // 0x08 - { 0 }, // 0x09 - { 0 }, // 0x0A - { 0 }, // 0x0B - { 0 }, // 0x0C - { 0 }, // 0x0D - { 0 }, // 0x0E - { 0 }, // 0x0F - { 0 }, // 0x10 - { 0 }, // 0x11 - { 0 }, // 0x12 - { 0 }, // 0x13 - { 0 }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { 0 }, // 0x18 - { 0 }, // 0x18 - { 0 }, // 0x1A - { ARC_cbflyhf1r, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x1B(F=0) according to reference - { 0 }, // 0x1C - { 0 }, // 0x1D - { 0 }, // 0x1E - { 0 }, // 0x1F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { 0 }, // 0x28 - { 0 }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { 0 }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { ARC_cbflyhf1r, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x39(F=0) as encoded by the toolchain - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F -}; - -static const arcompact_opcode_t arcv2_maj6[0x40 * 2] = -{ - { ARC_fmul, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x00(F=0) - { ARC_fadd, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x01(F=0) - { ARC_fsub, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x02(F=0) - { ARC_vmsub2hfr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x03(F=0) - { ARC_vmsub2hf, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x04(F=0) - { ARC_fsmadd, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x05(F=0) - { ARC_fsmsub, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x06(F=0) - { ARC_fsdiv, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x07(F=0) - { ARC_fcvt32, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x08(F=0) - { 0, AUX_F, {0, 0, 0}, NULL }, // 0x09(F=0) - { ARC_mpyf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A - { ARC_mpyfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0B - { ARC_macf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0C - { ARC_macfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0D - { ARC_msubf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E - { ARC_msubfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F - { ARC_divf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10 - { ARC_vmac2hnfr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x11 - { ARC_mpydf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x12 - { ARC_macdf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x13 - { ARC_msubwhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x14 - { ARC_msubdf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x15 - { ARC_dmpyhbl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x16 - { ARC_dmpyhbm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x17 - { ARC_dmachbl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x18 - { ARC_dmachbm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x19 - { ARC_msubwhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1A - { ARC_cmpyhfmr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x1B - { ARC_mpywhl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C - { ARC_macwhl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D - { ARC_mpywhul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1E - { ARC_macwhul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1F - { ARC_mpywhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x20 - { ARC_mpywhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x21 - { ARC_macwhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x22 - { ARC_macwhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x23 - { ARC_mpywhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x24 - { ARC_mpywhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x25 - { ARC_macwhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x26 - { ARC_macwhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x27 - { ARC_macwhkl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28 - { ARC_macwhkul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x29 - { ARC_mpywhkl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2A - { ARC_mpywhkul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2B - { ARC_msubwhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C - { ARC_msubwhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2D - { 0 }, // 0x2E - { SUBTABLE(5, 0, arcv2_sop6) }, // 0x2F - { ARC_dmulh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x30 - { ARC_dmulh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x31 - { ARC_dmulh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x32 - { ARC_dmulh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x33 - { ARC_daddh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x34 - { ARC_daddh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x35 - { ARC_daddh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x36 - { ARC_daddh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x37 - { ARC_dsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x38 - { ARC_dsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x39 - { ARC_dsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3A - { ARC_dsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3B - { ARC_dexcl1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3C - { ARC_dexcl2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F - - { ARC_cmpyhnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x00 - { ARC_cmpyhfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x01 - { ARC_cmpychnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x02 - { ARC_fscmp, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x03 - { ARC_fscmpf, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x04 - { ARC_cmpychfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x05 - { ARC_cmachnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x06 - { ARC_cmachfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x07 - { ARC_cmacchnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x08 - { ARC_cmacchfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x09 - { 0 }, // 0x0A - { 0 }, // 0x0B - { 0 }, // 0x0C - { 0 }, // 0x0D - { 0 }, // 0x0E - { 0 }, // 0x0F - { 0 }, // 0x10 - { ARC_vmsub2hnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x11 - { 0 }, // 0x12 - { 0 }, // 0x13 - { 0 }, // 0x14 - { 0 }, // 0x15 - { 0 }, // 0x16 - { 0 }, // 0x17 - { 0 }, // 0x18 - { 0 }, // 0x19 - { 0 }, // 0x1A - { ARC_cbflyhf0r, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1B - { 0 }, // 0x1C - { 0 }, // 0x1D - { 0 }, // 0x1E - { 0 }, // 0x1F - { 0 }, // 0x20 - { 0 }, // 0x21 - { 0 }, // 0x22 - { 0 }, // 0x23 - { 0 }, // 0x24 - { 0 }, // 0x25 - { 0 }, // 0x26 - { 0 }, // 0x27 - { 0 }, // 0x28 - { 0 }, // 0x29 - { 0 }, // 0x2A - { 0 }, // 0x2B - { 0 }, // 0x2C - { 0 }, // 0x2D - { 0 }, // 0x2E - { 0 }, // 0x2F - { 0 }, // 0x30 - { 0 }, // 0x31 - { 0 }, // 0x32 - { 0 }, // 0x33 - { 0 }, // 0x34 - { 0 }, // 0x35 - { 0 }, // 0x36 - { 0 }, // 0x37 - { 0 }, // 0x38 - { 0 }, // 0x39 - { 0 }, // 0x3A - { 0 }, // 0x3B - { 0 }, // 0x3C - { 0 }, // 0x3D - { 0 }, // 0x3E - { 0 }, // 0x3F -}; - -// indexed by bits 4..3 (maj = 0xC) -static const arcompact_opcode_t arcompact_maj0C[4] = -{ - { ARC_ld, 0, { fA16, fBC16_IND, 0}, NULL }, // 0x0 - { ARC_ld, AUX_B, { fA16, fBC16_IND, 0}, NULL }, // 0x1 - { ARC_ld, AUX_W, { fA16, fBC16_IND, 0}, NULL }, // 0x2 - { ARC_add, 0, { fA16, fB16, fC16 }, NULL }, // 0x3 -}; - -// indexed by bits 4..3 (maj = 0xD) -static const arcompact_opcode_t arcompact_maj0D[4] = -{ - { ARC_add, 0, {fC16, fB16, U3 }, NULL }, // 0x00 - { ARC_sub, 0, {fC16, fB16, U3 }, NULL }, // 0x01 - { ARC_asl, 0, {fC16, fB16, U3 }, NULL }, // 0x02 - { ARC_asr, 0, {fC16, fB16, U3 }, NULL }, // 0x03 -}; - -// indexed by bits 4..3 (maj = 0xE) -static const arcompact_opcode_t arcompact_maj0E[4] = -{ - { ARC_add, 0, {fB16, fB16, fH16}, NULL }, // 0x00 - { ARC_mov, 0, {fB16, fH16, 0 }, NULL }, // 0x01 - { ARC_cmp, 0, {fB16, fH16, 0 }, NULL }, // 0x02 - { ARC_mov, 0, {fH16, fB16, 0 }, NULL }, // 0x03 -}; - -// indexed by bits 4..3 (maj = 0xE) -static const arcompact_opcode_t arcv2_maj0E[8] = -{ - { ARC_add, 0, {fB16, fB16, fH16v2}, NULL }, // 0x00 - { ARC_add, 0, {fH16v2, fH16v2, S3 }, NULL }, // 0x01 - { 0 }, // 0x02 - { ARC_mov, 0, {fH16v2, S3, 0 }, NULL }, // 0x03 - { ARC_cmp, 0, {fB16, fH16v2, 0 }, NULL }, // 0x04 - { ARC_cmp, 0, {fH16v2, S3, 0 }, NULL }, // 0x05 - { 0 }, // 0x06 - { ARC_mov, AUX_CND|cNE, {fB16, fH16v2, 0 }, NULL }, // 0x07 -}; - -// indexed by bits 10..8 (maj = 0xF, 4..0 = 0x0, 7..5=0x7) -// 01111 iii 111 00000 -static const arcompact_opcode_t arcompact_zop16[8] = -{ - { ARC_nop, 0, { 0, 0, 0}, NULL }, // 0x00 - { ARC_unimp, 0, { 0, 0, 0}, NULL }, // 0x01 - { ARC_swi, 0, { 0, 0, 0}, NULL }, // 0x02 - { 0 }, // 0x03 - { ARC_j, AUX_CND|cEQ, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x04 - { ARC_j, AUX_CND|cNE, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x05 - { ARC_j, 0, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x06 - { ARC_j, AUX_D, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x07 -}; - -// indexed by bits 7..5 (maj = 0xF, 4..0 = 0x0) -// 01111 bbb iii 00000 -static const arcompact_opcode_t arcompact_sop16[8] = -{ - { ARC_j, 0, {fB16|O_IND, 0, 0}, NULL }, // 0x00 - { ARC_j, AUX_D, {fB16|O_IND, 0, 0}, NULL }, // 0x01 - { ARC_jl, 0, {fB16|O_IND, 0, 0}, NULL }, // 0x02 - { ARC_jl, AUX_D, {fB16|O_IND, 0, 0}, NULL }, // 0x03 - { 0 }, // 0x04 - { 0 }, // 0x05 - { ARC_sub, AUX_CND|cNE, {fB16, fB16, fB16}, NULL }, // 0x06 - { SUBTABLE(10, 8, arcompact_zop16) }, // 0x07 -}; - -// indexed by bits 4..0 (maj = 0xF) -// 01111 bbb ccc iiiii -static const arcompact_opcode_t arcompact_maj0F[0x20] = -{ - { SUBTABLE(7, 5, arcompact_sop16) }, // 0x00 - { 0 }, // 0x01 - { ARC_sub, 0, {fB16, fB16, fC16}, NULL }, // 0x02 - { 0 }, // 0x03 - { ARC_and, 0, {fB16, fB16, fC16}, NULL }, // 0x04 - { ARC_or, 0, {fB16, fB16, fC16}, NULL }, // 0x05 - { ARC_bic, 0, {fB16, fB16, fC16}, NULL }, // 0x06 - { ARC_xor, 0, {fB16, fB16, fC16}, NULL }, // 0x05 - { 0 }, // 0x08 - { 0 }, // 0x09 - { 0 }, // 0x0A - { ARC_tst, 0, {fB16, fC16, 0 }, NULL }, // 0x0B - { ARC_mul64, 0, {fB16, fC16, 0 }, NULL }, // 0x0C - { ARC_sexb, 0, {fB16, fC16, 0 }, NULL }, // 0x0D - { ARC_sexw, 0, {fB16, fC16, 0 }, NULL }, // 0x0E - { ARC_extb, 0, {fB16, fC16, 0 }, NULL }, // 0x0F - { ARC_extw, 0, {fB16, fC16, 0 }, NULL }, // 0x10 - { ARC_abs, 0, {fB16, fC16, 0 }, NULL }, // 0x11 - { ARC_not, 0, {fB16, fC16, 0 }, NULL }, // 0x12 - { ARC_neg, 0, {fB16, fC16, 0 }, NULL }, // 0x13 - { ARC_add1, 0, {fB16, fB16, fC16}, NULL }, // 0x14 - { ARC_add2, 0, {fB16, fB16, fC16}, NULL }, // 0x15 - { ARC_add3, 0, {fB16, fB16, fC16}, NULL }, // 0x16 - { 0 }, // 0x17 - { ARC_asl, 0, {fB16, fB16, fC16}, NULL }, // 0x18 - { ARC_lsr, 0, {fB16, fB16, fC16}, NULL }, // 0x19 - { ARC_asr, 0, {fB16, fB16, fC16}, NULL }, // 0x1A - { ARC_asl, 0, {fB16, fC16, 0 }, NULL }, // 0x1B - { ARC_asr, 0, {fB16, fC16, 0 }, NULL }, // 0x1C - { ARC_lsr, 0, {fB16, fC16, 0 }, NULL }, // 0x1D - { ARC_trap, 0, { 0, 0, 0 }, NULL }, // 0x1E - { ARC_brk, 0, { 0, 0, 0 }, NULL }, // 0x1F -}; - -// indexed by bits 4..0 (maj = 0xF) -// 01111 bbb ccc iiiii -static const arcompact_opcode_t arcv2_maj0F[0x20] = -{ - { SUBTABLE(7, 5, arcompact_sop16) }, // 0x00 - { 0 }, // 0x01 - { ARC_sub, 0, {fB16, fB16, fC16}, NULL }, // 0x02 - { 0 }, // 0x03 - { ARC_and, 0, {fB16, fB16, fC16}, NULL }, // 0x04 - { ARC_or, 0, {fB16, fB16, fC16}, NULL }, // 0x05 - { ARC_bic, 0, {fB16, fB16, fC16}, NULL }, // 0x06 - { ARC_xor, 0, {fB16, fB16, fC16}, NULL }, // 0x05 - { 0 }, // 0x08 - { ARC_mpyw, 0, {fB16, fB16, fC16}, NULL }, // 0x09 - { ARC_mpyuw, 0, {fB16, fB16, fC16}, NULL }, // 0x0A - { ARC_tst, 0, {fB16, fC16, 0 }, NULL }, // 0x0B - { ARC_mpy, 0, {fB16, fB16, fC16}, NULL }, // 0x0C breaking change - { ARC_sexb, 0, {fB16, fC16, 0 }, NULL }, // 0x0D - { ARC_sexw, 0, {fB16, fC16, 0 }, NULL }, // 0x0E - { ARC_extb, 0, {fB16, fC16, 0 }, NULL }, // 0x0F - { ARC_extw, 0, {fB16, fC16, 0 }, NULL }, // 0x10 - { ARC_abs, 0, {fB16, fC16, 0 }, NULL }, // 0x11 - { ARC_not, 0, {fB16, fC16, 0 }, NULL }, // 0x12 - { ARC_neg, 0, {fB16, fC16, 0 }, NULL }, // 0x13 - { ARC_add1, 0, {fB16, fB16, fC16}, NULL }, // 0x14 - { ARC_add2, 0, {fB16, fB16, fC16}, NULL }, // 0x15 - { ARC_add3, 0, {fB16, fB16, fC16}, NULL }, // 0x16 - { 0 }, // 0x17 - { ARC_asl, 0, {fB16, fB16, fC16}, NULL }, // 0x18 - { ARC_lsr, 0, {fB16, fB16, fC16}, NULL }, // 0x19 - { ARC_asr, 0, {fB16, fB16, fC16}, NULL }, // 0x1A - { ARC_asl, 0, {fB16, fC16, 0 }, NULL }, // 0x1B - { ARC_asr, 0, {fB16, fC16, 0 }, NULL }, // 0x1C - { ARC_lsr, 0, {fB16, fC16, 0 }, NULL }, // 0x1D - { ARC_trap, 0, {U6_SWI, 0, 0 }, NULL }, // 0x1E - { ARC_swi, 0, {U6_SWI, 0, 0 }, NULL }, // 0x1F -}; - -// indexed by bits 7..5 (maj = 0x17) -static const arcompact_opcode_t arcompact_maj17[8] = -{ - { ARC_asl, 0, {fB16, fB16, U5}, NULL }, // 0x00 - { ARC_lsr, 0, {fB16, fB16, U5}, NULL }, // 0x01 - { ARC_asr, 0, {fB16, fB16, U5}, NULL }, // 0x02 - { ARC_sub, 0, {fB16, fB16, U5}, NULL }, // 0x03 - { ARC_bset, 0, {fB16, fB16, U5}, NULL }, // 0x04 - { ARC_bclr, 0, {fB16, fB16, U5}, NULL }, // 0x05 - { ARC_bmsk, 0, {fB16, fB16, U5}, NULL }, // 0x06 - { ARC_btst, 0, {fB16, U5, 0}, NULL }, // 0x07 -}; - -// indexed by bits 10..8 (maj = 0x18, i=5) -static const arcompact_opcode_t arcompact_sp_addsub[8] = -{ - { ARC_add, 0, {R_SP, R_SP, U7L }, NULL }, // 0x00 - { ARC_sub, 0, {R_SP, R_SP, U7L }, NULL }, // 0x01 - { 0 }, // 0x02 - { 0 }, // 0x03 - { 0 }, // 0x04 - { 0 }, // 0x05 - { 0 }, // 0x06 - { 0 }, // 0x07 -}; - -// indexed by bits 4..0 (maj = 0x18, i=6) -static const arcompact_opcode_t arcompact_sp_pops[0x20] = -{ - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x00 - { ARC_pop, 0, {fB16, 0, 0}, NULL }, // 0x01 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x02 - { 0 }, // 0x03 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x04 - { 0 }, // 0x05 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x06 - { 0 }, // 0x07 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x08 - { 0 }, // 0x09 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0A - { 0 }, // 0x0B - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0C - { 0 }, // 0x0D - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0E - { 0 }, // 0x0F - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x10 - { ARC_pop, 0, {R_BLINK, 0, 0}, NULL }, // 0x11 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x12 - { 0 }, // 0x13 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x14 - { 0 }, // 0x15 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x16 - { 0 }, // 0x17 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x18 - { 0 }, // 0x19 - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1A - { 0 }, // 0x1B - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1C - { 0 }, // 0x1D - { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1E - { 0 }, // 0x1F -}; - -// indexed by bits 4..0 (maj = 0x18, i=7) -static const arcompact_opcode_t arcompact_sp_pushs[0x20] = -{ - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x00 - { ARC_push, 0, {fB16, 0, 0}, NULL }, // 0x01 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x02 - { 0 }, // 0x03 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x04 - { 0 }, // 0x05 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x06 - { 0 }, // 0x07 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x08 - { 0 }, // 0x09 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0A - { 0 }, // 0x0B - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0C - { 0 }, // 0x0D - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0E - { 0 }, // 0x0F - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x10 - { ARC_push, 0, {R_BLINK, 0, 0}, NULL }, // 0x11 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x12 - { 0 }, // 0x13 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x14 - { 0 }, // 0x15 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x16 - { 0 }, // 0x17 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x18 - { 0 }, // 0x19 - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1A - { 0 }, // 0x1B - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1C - { 0 }, // 0x1D - { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1E - { 0 }, // 0x1F -}; - -// indexed by bits 7..5 (maj = 0x18) -// sp-based instructions -static const arcompact_opcode_t arcompact_maj18[8] = -{ - { ARC_ld, 0, {fB16, SP_U7, 0 }, NULL }, // 0x00 - { ARC_ld, AUX_B, {fB16, SP_U7, 0 }, NULL }, // 0x01 - { ARC_st, 0, {fB16, SP_U7, 0 }, NULL }, // 0x02 - { ARC_st, AUX_B, {fB16, SP_U7, 0 }, NULL }, // 0x03 - { ARC_add, 0, {fB16, R_SP, U7L }, NULL }, // 0x04 - { SUBTABLE( 10, 8, arcompact_sp_addsub) }, // 0x05 - { SUBTABLE( 4, 0, arcompact_sp_pops) }, // 0x06 - { SUBTABLE( 4, 0, arcompact_sp_pushs) }, // 0x07 -}; - -// indexed by bits 10..9 (maj = 0x19) -// gp-based ld/add (data aligned offset) -static const arcompact_opcode_t arcompact_maj19[4] = -{ - { ARC_ld, 0, {R_R0, GP_S11, 0 }, NULL }, // 0x00 - { ARC_ld, AUX_B, {R_R0, GP_S9, 0 }, NULL }, // 0x01 - { ARC_ld, AUX_W, {R_R0, GP_S10, 0 }, NULL }, // 0x02 - { ARC_add, 0, {R_R0, R_GP, S11 }, NULL }, // 0x03 -}; - -// indexed by bits 7..7 (maj = 0x1C) -static const arcompact_opcode_t arcompact_maj1C[2] = -{ - { ARC_add, 0, { fB16, fB16, U7}, NULL }, // 0x00 - { ARC_cmp, 0, { fB16, U7, 0}, NULL }, // 0x01 -}; - -// indexed by bits 7..7 (maj = 0x1D) -static const arcompact_opcode_t arcompact_maj1D[2] = -{ - { ARC_br, AUX_CND|cEQ, { fB16, O_ZERO, S8}, NULL }, // 0x00 - { ARC_br, AUX_CND|cNE, { fB16, O_ZERO, S8}, NULL }, // 0x01 -}; - -// indexed by bits 8..6 (maj = 0x1E, 10..9=0x3) -static const arcompact_opcode_t arcompact_bcc16[8] = -{ - { ARC_b, AUX_CND|cGT, { S7, 0, 0}, NULL }, // 0x00 - { ARC_b, AUX_CND|cGE, { S7, 0, 0}, NULL }, // 0x01 - { ARC_b, AUX_CND|cLT, { S7, 0, 0}, NULL }, // 0x02 - { ARC_b, AUX_CND|cLE, { S7, 0, 0}, NULL }, // 0x03 - { ARC_b, AUX_CND|cHI, { S7, 0, 0}, NULL }, // 0x04 - { ARC_b, AUX_CND|cHS, { S7, 0, 0}, NULL }, // 0x05 - { ARC_b, AUX_CND|cLO, { S7, 0, 0}, NULL }, // 0x06 - { ARC_b, AUX_CND|cLS, { S7, 0, 0}, NULL }, // 0x07 -}; - -// indexed by bits 10..9 (maj = 0x1E) -static const arcompact_opcode_t arcompact_maj1E[4] = -{ - { ARC_b, 0, { S10, 0, 0}, NULL }, // 0x00 - { ARC_b, AUX_CND|cEQ, { S10, 0, 0}, NULL }, // 0x01 - { ARC_b, AUX_CND|cNE, { S10, 0, 0}, NULL }, // 0x02 - { SUBTABLE(8, 6, arcompact_bcc16) }, // 0x03 -}; - -// indexed by major opcode (bits 15..11) -static const arcompact_opcode_t arcompact_major[0x20] = -{ - { SUBTABLE(16, 16, arcompact_maj0) }, // 0x00 - { SUBTABLE(16, 16, arcompact_maj1) }, // 0x01 - { ARC_ld, DAAZZX_11_6, {fA32, fB_S9, 0}, NULL},// 0x02 - { ARC_st, DAAZZ_5_1, {fC32, fB_S9, 0}, NULL},// 0x03 - { SUBTABLE(21, 16, arcompact_maj4) }, // 0x04 - { SUBTABLE(21, 16, arcompact_maj5) }, // 0x05 - { SUBTABLE(23, 22, arcompact_maj6) }, // 0x06 - { 0 }, // 0x07 - { 0 }, // 0x08 - { 0 }, // 0x09 - { 0 }, // 0x0A - { 0 }, // 0x0B - { SUBTABLE( 4, 3, arcompact_maj0C) }, // 0x0C - { SUBTABLE( 4, 3, arcompact_maj0D) }, // 0x0D - { SUBTABLE( 4, 3, arcompact_maj0E) }, // 0x0E - { SUBTABLE( 4, 0, arcompact_maj0F) }, // 0x0F - { ARC_ld, 0, { fC16, fB_U7, 0}, NULL }, // 0x10 - { ARC_ld, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x11 - { ARC_ld, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x12 - { ARC_ld, AUX_W|AUX_X, { fC16, fB_U6, 0}, NULL },// 0x13 - { ARC_st, 0, { fC16, fB_U7, 0}, NULL }, // 0x14 - { ARC_st, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x15 - { ARC_st, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x16 - { SUBTABLE( 7, 5, arcompact_maj17) }, // 0x17 - { SUBTABLE( 7, 5, arcompact_maj18) }, // 0x18 - { SUBTABLE(10, 9, arcompact_maj19) }, // 0x19 - { ARC_ld, 0, { fB16, PCL_U10, 0}, NULL }, // 0x1A - { ARC_mov, 0, { fB16, U8, 0}, NULL }, // 0x1B - { SUBTABLE( 7, 7, arcompact_maj1C) }, // 0x1C - { SUBTABLE( 7, 7, arcompact_maj1D) }, // 0x1D - { SUBTABLE(10, 9, arcompact_maj1E) }, // 0x1E - { ARC_bl, 0, { S13, 0, 0}, NULL }, // 0x1F -}; - -// indexed by bit 2 (maj = 8) -static const arcompact_opcode_t arcv2_maj8[2] = -{ - { ARC_mov, 0, {fG16, fH16v2, 0}, NULL }, // 0x00 - { ARC_ld, 0, {fR16_2, fH16v2_U5, 0}, NULL }, // 0x01 -}; - -// indexed by bits 4..3 (maj = 8) -static const arcompact_opcode_t arcv2_maj9[4] = -{ - { ARC_ld, AUX_AS, {fA16, fBC16_IND, 0}, NULL }, // 0x00 - { ARC_add, 0, {fR16_1, fB16, U6_16}, NULL }, // 0x01 - { ARC_sub, 0, {fA16, fB16, fC16}, NULL }, // 0x02 - { ARC_add, 0, {fR16_1, fB16, U6_16}, NULL }, // 0x03 -}; - -// indexed by bits 4..3 (maj = 0x0A) -static const arcompact_opcode_t arcv2_maj0A[4] = -{ - { ARC_ld, 0, {R_R1, GP_S11_16, 0}, NULL }, // 0x00 - { ARC_ldi, 0, {fB16, U7_16|O_IDX, 0}, NULL }, // 0x01 - { ARC_st, 0, {R_R0, GP_S11_16, 0}, NULL }, // 0x02 - { ARC_ldi, 0, {fB16, U7_16|O_IDX, 0}, NULL }, // 0x03 -}; - -// indexed by bit 10 (maj = 0x0B) -static const arcompact_opcode_t arcv2_maj0B[2] = -{ - { ARC_jli, 0, {U10_16|O_IDX, 0, 0}, NULL }, // 0x00 - { ARC_ei, 0, {U10_16|O_IDX, 0, 0}, NULL }, // 0x01 -}; - - -// indexed by major opcode (bits 15..11) -static const arcompact_opcode_t arcv2_major[0x20] = -{ - { SUBTABLE(16, 16, arcompact_maj0) }, // 0x00 - { SUBTABLE(16, 16, arcompact_maj1) }, // 0x01 - { ARC_ld, DAAZZX_11_6, {fA32, fB_S9, 0}, NULL},// 0x02 - { ARC_st, DAAZZ_5_1, {fC32_w6, fB_S9, 0}, NULL},// 0x03 - { SUBTABLE(21, 16, arcompact_maj4) }, // 0x04 - { SUBTABLE(21, 16, arcv2_maj5) }, // 0x05 - { SUBTABLE(21, 16, arcv2_maj6) }, // 0x06 - { 0 }, // 0x07 - { SUBTABLE( 2, 2, arcv2_maj8) }, // 0x08 - { SUBTABLE( 4, 3, arcv2_maj9) }, // 0x09 - { SUBTABLE( 4, 3, arcv2_maj0A) }, // 0x0A - { SUBTABLE(10, 10, arcv2_maj0B) }, // 0x0B - { SUBTABLE( 4, 3, arcompact_maj0C) }, // 0x0C - { SUBTABLE( 4, 3, arcompact_maj0D) }, // 0x0D - { SUBTABLE( 4, 2, arcv2_maj0E) }, // 0x0E - { SUBTABLE( 4, 0, arcv2_maj0F) }, // 0x0F - { ARC_ld, 0, { fC16, fB_U7, 0}, NULL }, // 0x10 - { ARC_ld, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x11 - { ARC_ld, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x12 - { ARC_ld, AUX_W|AUX_X, { fC16, fB_U6, 0}, NULL }, // 0x13 - { ARC_st, 0, { fC16, fB_U7, 0}, NULL }, // 0x14 - { ARC_st, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x15 - { ARC_st, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x16 - { SUBTABLE( 7, 5, arcompact_maj17) }, // 0x17 - { SUBTABLE( 7, 5, arcompact_maj18) }, // 0x18 - { SUBTABLE(10, 9, arcompact_maj19) }, // 0x19 - { ARC_ld, 0, { fB16, PCL_U10, 0}, NULL }, // 0x1A - { ARC_mov, 0, { fB16, U8, 0}, NULL }, // 0x1B - { SUBTABLE( 7, 7, arcompact_maj1C) }, // 0x1C - { SUBTABLE( 7, 7, arcompact_maj1D) }, // 0x1D - { SUBTABLE(10, 9, arcompact_maj1E) }, // 0x1E - { ARC_bl, 0, { S13, 0, 0}, NULL }, // 0x1F -}; - -// extract bit numbers high..low from val (inclusive, start from 0) -#define BITS(val, high, low) ( ((val)>>low) & ( (1<<(high-low+1))-1) ) -// sign extend b low bits in x -// from "Bit Twiddling Hacks" -static sval_t SIGNEXT(sval_t x, int b) -{ - uint32 m = 1 << (b - 1); - x &= ((sval_t(1) << b) - 1); - return (x ^ m) - m; -} - -// extract bitfield with sign extension -#define SBITS(val, high, low) SIGNEXT(BITS(val, high, low), high-low+1) - -//---------------------------------------------------------------------- -int arc_t::get_limm(insn_t &insn) -{ - if ( !got_limm ) - { - g_limm = (insn.get_next_word() << 16); - g_limm |= insn.get_next_word(); - got_limm = true; - } - return g_limm; -} - -//---------------------------------------------------------------------- -// register, or a reference to long immediate (r62) -inline void arc_t::opreg(insn_t &insn, op_t &x, int rgnum, int limm) -{ - if ( rgnum != limm ) - { - x.reg = uint16(rgnum); - x.type = o_reg; - } - else - { - x.type = o_imm; - // limm as destination is not used - // so check for instructions where first operand is source - if ( x.n == 0 && (insn.get_canon_feature(ph) & CF_CHG1) != 0 ) - x.value = 0; - else - x.value = get_limm(insn); - } - x.dtype = dt_dword; -} - -//---------------------------------------------------------------------- -inline void opimm(op_t &x, uval_t val) -{ - x.value = val; - x.type = o_imm; - x.dtype = dt_dword; -} - -//---------------------------------------------------------------------- -inline void arc_t::opdisp(insn_t &insn, op_t &x, int rgnum, ea_t disp) -{ - if ( rgnum != LIMM ) - { - x.type = o_displ; - x.addr = disp; - x.reg = rgnum; - } - else - { - x.type = o_mem; - x.immdisp = disp; - x.addr = get_limm(insn) + disp * get_scale_factor(insn); - } - x.dtype = dt_dword; -} - -//---------------------------------------------------------------------- -inline int reg16(int rgnum) -{ - // 0..3 r0-r3 - // 4..7 r12-r15 - return ( rgnum > 3 ) ? (rgnum + 8) : rgnum; -} - -//---------------------------------------------------------------------- -inline void opbranch(const insn_t &insn, op_t &x, sval_t delta) -{ - // cPC <- (cPCL+delta) - // PCL is current instruction address with 2 low bits set to 0 - ea_t pcl = insn.ip & ~3ul; - x.type = o_near; - x.dtype = dt_code; - x.addr = pcl + delta; -} - -//---------------------------------------------------------------------- -void arc_t::decode_operand( - insn_t &insn, - uint32 code, - int &op_pos, - uint32 opkind) -{ - op_t &x = insn.ops[op_pos]; - ++op_pos; - if ( opkind == 0 ) - { - x.type = o_void; - return; - } - int reg, p; - sval_t displ; - switch ( opkind & ~O_FLAGS ) - { - case fA16: - opreg(insn, x, reg16(BITS(code, 2, 0))); - break; - case fB16: - opreg(insn, x, reg16(BITS(code, 10, 8))); - break; - case fC16: - opreg(insn, x, reg16(BITS(code, 7, 5))); - break; - - case fA32: // 5..0 a register operand (6 bits, r0-r63) - opreg(insn, x, BITS(code, 5, 0)); - break; - case fB32: // 14..12 & 26..24 b register operand (6 bits) - opreg(insn, x, (BITS(code, 14, 12)<<3) | BITS(code, 26, 24)); - break; - case fC32: // 11..6 c register operand (6 bits) - opreg(insn, x, BITS(code, 11, 6)); - break; - case fC32_w6: // 11..6 & 0 c/w6 register/immediate operand (6 bits) - if ( BITS(code, 0, 0) != 0 ) - opimm(x, SBITS(code, 11, 6)); - else - opreg(insn, x, BITS(code, 11, 6)); - break; - case fH16: // 2..0 & 7..5 h register operand (6 bits) - reg = (BITS(code, 2, 0) << 3) | BITS(code, 7, 5); - opreg(insn, x, reg); - break; - case fH16v2: // 1..0 & 7..5 h register operand (5 bits) - reg = (BITS(code, 1, 0) << 3) | BITS(code, 7, 5); - opreg(insn, x, reg, LIMM5); - break; - case fH16v2_U5: // 1..0 & 7..5, 10&4..3 [h, u5] (u5=u3*4) - displ = ((BITS(code, 10, 10) << 2) | BITS(code, 4, 3)) * 4; - reg = (BITS(code, 1, 0) << 3) | BITS(code, 7, 5); - opdisp(insn, x, reg, displ); - break; - case fG16: // 4..3 & 10..8 g register operand (5 bits) - reg = (BITS(code, 4, 3) << 3) | BITS(code, 10, 8); - opreg(insn, x, reg, LIMM5); - break; - case fR16_2: // 9..8 R register operand (2 bits) - opreg(insn, x, BITS(code, 9, 8)); - break; - case fR16_1: // 7 R register operand (1 bits) - opreg(insn, x, BITS(code, 7, 7)); - break; - - case S25L: // 15..6 & 26..18 & 0..3 s25 signed branch displacement for branch and link - case S21L: // 15..6 & 26..18 s21 signed branch displacement for branch and link - case S25: // 15..6 & 26..17 & 3..0 s25 signed branch displacement - case S21: // 15..6 & 26..17 s21 signed branch displacement - displ = (BITS(code, 15, 6) << 10) | BITS(code, 26, 17); - if ( opkind == S25 || opkind == S25L ) - { - displ |= BITS(code, 3, 0) << 20; - if ( displ & (1ul<<23) ) - displ -= (1ul<<24); - } - else - { - if ( displ & (1ul<<19) ) - displ -= (1ul<<20); - } - if ( opkind == S25L || opkind == S21L ) - { - // branch-and-link uses 32-bit aligned target - displ &= ~1ul; - } - opbranch(insn, x, displ * 2); - break; - - case S9: // 15&23..17 s9 signed branch displacement (16-bit aligned) - displ = BITS(code, 23, 17); - if ( BITS(code, 15, 15) ) // sign bit - displ -= (1ul<<7); - opbranch(insn, x, displ * 2); - break; - - case S7: // 5..0 s7 signed branch displacement (16-bit aligned) - displ = SBITS(code, 5, 0); - opbranch(insn, x, displ * 2); - break; - - case S8: // 6..0 s8 signed branch displacement (16-bit aligned) - displ = SBITS(code, 6, 0); - opbranch(insn, x, displ * 2); - break; - - case S10: // 8..0 s10 signed branch displacement (16-bit aligned) - displ = SBITS(code, 8, 0); - opbranch(insn, x, displ * 2); - break; - - case S13: // 10..0 s13 signed branch displacement (32-bit aligned) - displ = SBITS(code, 10, 0); - opbranch(insn, x, displ * 4); - break; - - case PCL_U10: - displ = BITS(code, 7, 0); - opdisp(insn, x, PCL, displ*4); - break; - - case SP_U7: // 4..0 [SP, u7] stack + offset (u7 = u5*4) - displ = BITS(code, 4, 0); - opdisp(insn, x, SP, displ*4); - break; - - case S3: // 10..8 s3 signed immediate - p = BITS(code, 10, 8); - opimm(x, p == 7 ? -1 : p); - break; - - case U3: // 2..0 u2 unsigned immediate - opimm(x, BITS(code, 2, 0)); - break; - - case U7: - opimm(x, BITS(code, 6, 0)); - break; - - case U6: - opimm(x, BITS(code, 11, 6)); - break; - - case U6_SWI: - opimm(x, BITS(code, 10, 5)); - break; - - case U5: - case U7L: - displ = BITS(code, 4, 0); - if ( opkind == U7L ) - displ *= 4; - opimm(x, displ); - break; - - case U8: - opimm(x, BITS(code, 7, 0)); - break; - - case U6_16: // 6..4 & 2..0 u6 unsigned immediate - opimm(x, (BITS(code, 6, 4) << 3) | BITS(code, 2, 0)); - break; - - case U7_16: // 7..4 & 2..0 u7 unsigned immediate - opimm(x, (BITS(code, 7, 4) << 3) | BITS(code, 2, 0)); - break; - - case U10_16: - opimm(x, BITS(code, 9, 0)); - break; - - case fB_U5: // 10..8 & 4..0 [b, u5] - case fB_U6: // 10..8 & 4..0 [b, u6] (u6=u5*2) - case fB_U7: // 10..8 & 4..0 [b, u7] (u6=u5*4) - displ = BITS(code, 4, 0); - if ( opkind == fB_U6 ) - displ *= 2; - else if ( opkind == fB_U7 ) - displ *= 4; - reg = reg16(BITS(code, 10, 8)); - opdisp(insn, x, reg, displ); - break; - - case fB_S9: // 14..12&26..26, 15&23..16 [b, s9] - displ = BITS(code, 23, 16); - if ( BITS(code, 15, 15) ) // sign bit - displ -= (1ul<<8); - reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); - opdisp(insn, x, reg, displ); - break; - - // handing of the "gen" format: - // P M - // REG_REG 00 N/A Destination and both sources are registers - // REG_U6IMM 01 N/A Source 2 is a 6-bit unsigned immediate - // REG_S12IMM 10 N/A Source 2 is a 12-bit signed immediate - // COND_REG 11 0 Conditional instruction. Destination (if any) is source 1. Source 2 is a register - // COND_REG_U6IMM 11 1 Conditional instruction. Destination (if any) is source 1. Source 2 is a 6-bit unsigned immediate - // P=23..22, M=5 - // 0x04, [0x00 - 0x3F] - // 00100 bbb 00 iiiiii F BBB CCCCCC AAAAAA reg-reg op<.f> a,b,c - // 00100 bbb 01 iiiiii F BBB UUUUUU AAAAAA reg-u6imm op<.f> a,b,u6 - // 00100 bbb 10 iiiiii F BBB ssssss SSSSSS reg-s12imm op<.f> b,b,s12 - // 00100 bbb 11 iiiiii F BBB CCCCCC 0 QQQQQ cond reg-reg op<.cc><.f> b,b,c - // 00100 bbb 11 iiiiii F BBB UUUUUU 1 QQQQQ cond reg-u6 op<.cc><.f> b,b,u6 - // 0x04, [0x30 - 0x37] - // 00100 bbb aa 110 ZZ X D BBB CCCCCC AAAAAA LD<zz><.x><.aa><.di> a,[b,c] - - case GENA: // 5..0 - p = BITS(code, 23, 22); - if ( p <= 1 ) - reg = BITS(code, 5, 0); - else - reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); - opreg(insn, x, reg); - break; - - case GENB: // 14..12 & 26..24 - reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); - opreg(insn, x, reg); - break; - - case GENC: // 11..6 reg/u6 or 0..5&11..6 s12 - case GENC_PCREL: // 11..6 u6 or 0..5&11..6 s12 pc-relative displacement - p = BITS(code, 23, 22); - if ( p != 2 ) - { - reg = BITS(code, 11, 6); - if ( p == 0 || (p == 3 && BITS(code, 5, 5) == 0) ) - opreg(insn, x, reg); - else - opimm(x, reg); - } - else - { - // s12 - reg = (BITS(code, 5, 0) << 6) | BITS(code, 11, 6); - reg = SIGNEXT(reg, 12); - opimm(x, reg); - } - if ( (opkind & ~O_IND) == GENC_PCREL && x.type == o_imm ) - opbranch(insn, x, reg * 2); - break; - - case fBC_IND: - { - int b = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); - int c = BITS(code, 11, 6); - int li = 0; - if ( b == LIMM || c == LIMM ) - li = get_limm(insn); - doIndirectOperand(insn, b, c, x, 0, li, false); - } - break; - - case fBC16_IND: - { - int b = BITS(code, 10, 8); - int c = BITS(code, 7, 5); - doIndirectOperand(insn, reg16(b), reg16(c), x, 0, 0, false); - } - break; - - case O_ZERO: - opimm(x, 0); - break; - - case R_SP: // implicit SP - opreg(insn, x, SP); - break; - - case R_BLINK: // implicit BLINK - opreg(insn, x, BLINK); - break; - - case R_R0: // implicit R0 - opreg(insn, x, R0); - break; - - case R_R1: // implicit R1 - opreg(insn, x, R1); - break; - - case R_GP: // implicit GP - opreg(insn, x, GP); - break; - - case GP_S9: // 8..0 [GP, s9] GP + offset - case GP_S10: // 8..0 [GP, s10] GP + offset (s10 = s9*2) - case GP_S11: // 8..0 [GP, s11] GP + offset (s11 = s9*4) - case S11: // 8..0 s11 signed immediate (s11 = s9*4) - displ = SBITS(code, 8, 0); - if ( opkind == GP_S10 ) - displ *= 2; - else if ( opkind != GP_S9 ) - displ *= 4; - if ( opkind == S11 ) - opimm(x, displ); - else - opdisp(insn, x, GP, displ); - break; - - case GP_S11_16: - displ = (SBITS(code, 10, 5) << 5) | (BITS(code, 2, 0) << 2); - opdisp(insn, x, GP, displ); - break; - - case EL: // 4..1 & 10..8 enter / leave register set - x.type = o_reglist; - x.reglist = BITS(code, 4, 1) | (BITS(code, 10, 8) << 4); - x.dtype = dt_dword; - break; - - default: - msg("%a: cannot decode operand %d (opkind=%u)\n", insn.ea, x.n, opkind); - return; - } - if ( opkind & O_IND ) - { - // indirect access - if ( x.type == o_reg ) - { - x.type = o_displ; - x.addr = 0; - } - else if ( x.type == o_imm && insn.itype != ARC_lr && insn.itype != ARC_sr ) - { - if ( insn.itype == ARC_j || insn.itype == ARC_jl ) - x.type = o_near; - else - x.type = o_mem; - x.addr = x.value; - x.immdisp = 0; - } - } - if ( opkind & O_WIDE ) - { - // register pair for 64-bit values - op_t &y = insn.ops[op_pos]; - ++op_pos; - if ( x.type == o_reg && (x.reg & 1) == 0 && x.reg <= R58 ) - { - y.type = o_reg; - y.reg = x.reg + 1; - y.regpair = true; - } - else - { - y.type = o_void; - } - } - if ( opkind & O_IDX ) - { - int base; - switch ( insn.itype ) - { - case ARC_bi: - case ARC_bih: - base = NEXT_PC; - break; - - case ARC_ldi: - base = LDI_BASE; - break; - - case ARC_jli: - base = JLI_BASE; - break; - - case ARC_ei: - base = EI_BASE; - break; - - default: - msg("%a: unknown implicit base for indexed access\n", insn.ea); - return; - } - if ( x.type == o_reg ) - { - x.type = o_phrase; - x.secreg = x.reg; - x.reg = base; - } - else if ( x.type == o_imm ) - { - x.type = o_displ; - x.addr = x.value; - x.reg = base; - } - else - { - msg("%a: unknown operand type for indexed access\n", insn.ea); - } - } -} - -//---------------------------------------------------------------------- -// decode non-operand bits of the instruction -static void decode_aux(insn_t &insn, uint32 code, uint32 aux) -{ - aux &= ~AUX_V2 & ~AUX_F; - if ( aux & AUX_CND ) - { - // condition in low bits of 'aux' - insn.auxpref = (insn.auxpref & ~aux_cmask) | (aux & aux_cmask); - aux &= ~(AUX_CND | aux_cmask); - } - if ( aux & Q_4_0 ) - { - // condition in low bits of instruction - insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask); - aux &= ~Q_4_0; - } - if ( aux & Q_5_0 ) - { - // condition in low bits of instruction if the next higer bit is 1 - if ( BITS(code, 5, 5) == 1 ) - insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask); - aux &= ~Q_5_0; - } - if ( aux & AUX_GEN3 ) - { - // bit 15 = F/Di, 4..0 = Q if 23..22=0x3 - if ( BITS(code, 15, 15) ) - { - if ( (aux & AUX_GEN3) == AUX_GEN ) - insn.auxpref |= aux_f; - else if ( (aux & AUX_GEN3) == AUX_GEN3 ) - insn.auxpref |= aux_di; - } - if ( BITS(code, 23, 22) == 3 ) - insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask); - aux &= ~AUX_GEN3; - } - if ( aux & N_5 ) - { - insn.auxpref = (insn.auxpref & ~aux_d) | (code & aux_d); - aux &= ~N_5; - } - if ( aux & AUX_W ) - { - insn.auxpref = (insn.auxpref & ~aux_zmask) | aux_w; - aux &= ~AUX_W; - } - if ( aux & AUX_B ) - { - insn.auxpref = (insn.auxpref & ~aux_zmask) | aux_b; - aux &= ~AUX_B; - } - if ( aux & AUX_X ) - { - insn.auxpref |= aux_x; - aux &= ~AUX_X; - } - if ( aux & AUX_D ) - { - insn.auxpref = (insn.auxpref & ~aux_nmask) | aux_d; - aux &= ~AUX_D; - } - if ( aux & DAAZZX_11_6 ) // 11..6 Di, aa, ZZ, X flags (load) - { - insn.auxpref = (insn.auxpref & ~0x3F) | (BITS(code, 11, 6)); - aux &= ~DAAZZX_11_6; - } - if ( aux & DAAZZ_5_1 ) // 5..1 Di, aa, ZZ (store) - { - insn.auxpref = (insn.auxpref & ~0x3F) | (BITS(code, 5, 1) << 1); - aux &= ~DAAZZ_5_1; - } - if ( aux & AAZZXD_23_15 ) // 23..22,18..15 aa, ZZ, X, D flags (load reg+reg) - { - // load instructions flags: Di.AA.ZZ.X - insn.auxpref &= ~0x3F; - insn.auxpref |= BITS(code, 15, 15) << 5; // Di - insn.auxpref |= BITS(code, 23, 22) << 3; // aa - insn.auxpref |= BITS(code, 18, 17) << 1; // ZZ - insn.auxpref |= BITS(code, 16, 16) << 0; // X - aux &= ~AAZZXD_23_15; - } - if ( aux & AUX_AS ) - { - insn.auxpref |= aux_as; - aux &= ~AUX_AS; - } - if ( aux & Y_3 ) - { - // static prediction bit Y is bit 3 - // in default case (no hint specified) it's 0 for BRcc and 1 for BBITn - if ( (BITS(code, 3, 3) == 0) != (insn.itype == ARC_br) ) - { - insn.auxpref |= aux_bhint; - } - aux &= ~Y_3; - } - if ( aux != 0 ) - msg("%a: unhandled aux bits: %08X\n", insn.ea, aux); -} - -//---------------------------------------------------------------------- -int arc_t::analyze_compact(insn_t &insn, uint32 code, int idx, const arcompact_opcode_t *table) -{ - const arcompact_opcode_t *line = &table[idx]; - while ( (line->mnem & 0x80000000) != 0 ) - { - // it's a pointer into subtable - // indexed by some of the instruction's bits - int high1 = (line->mnem >> 24) & 0x1F; - int low1 = (line->mnem >> 16) & 0x1F; - int high2 = (line->mnem >> 8) & 0x1F; - int low2 = (line->mnem >> 0) & 0x1F; - idx = BITS(code, high2, low2); - if ( high1 != 0 && low1 != 0 ) - idx |= BITS(code, high1, low1) << (high2-low2+1); - line = &(line->subtable[idx]); - } - if ( line->aux & AUX_F && BITS(code, 15, 15) ) - line += 0x40; - if ( (line->mnem == 0 && line->aux == 0) || !is_arcv2() && line->aux & AUX_V2 ) - { - return 0; - } - - insn.itype = line->mnem; - decode_aux(insn, code, line->aux); - - if ( is_arcv2() && insn.itype == ARC_flag && BITS(code, 15, 15) ) - insn.itype = ARC_kflag; - - int j = 0; - for ( int i = 0; i < 3; i++ ) - decode_operand(insn, code, j, line->ops[i]); - for ( ; j < PROC_MAXOP; ++j ) - insn.ops[j].type = o_void; - - if ( insn.itype == ARC_swi - && insn.Op1.type == o_imm - && insn.Op1.value == 0x3f ) - { - insn.itype = ARC_brk; - insn.Op1.type = o_void; - } - - return insn.size; -} - -//---------------------------------------------------------------------- -// analyze ARCompact instruction -int arc_t::ana_compact(insn_t &insn) -{ - // must be 16-bit aligned - if ( insn.ea & 1 ) - return 0; - uint32 code = insn.get_next_word(); - got_limm = false; - // first 5 bits is the major opcode - int i = (code >> 11) & 0x1F; - if ( i < 0x8 ) - { - // this is a 32-bit instruction - // get the full word - code = (code << 16) | insn.get_next_word(); - } - else - { - insn.auxpref |= aux_s; - } - return analyze_compact(insn, code, i, - is_arcv2() ? arcv2_major : arcompact_major); -} - -//---------------------------------------------------------------------- -static void simplify(insn_t &insn) -{ - for ( int i = 0; i < PROC_MAXOP; ++i ) - { - if ( insn.ops[i].type == o_mem ) - insn.ops[i].immdisp = 0; - } - - switch ( insn.itype ) - { - case ARC_st: - case ARC_ld: - // ld.as r1, [r2, delta] -> ld r1, [r2, delta*size] - if ( insn.Op2.type == o_displ - && insn.Op2.membase == 0 - && (insn.auxpref & aux_amask) == aux_as ) - { - insn.Op2.addr *= get_scale_factor(insn); - insn.auxpref &= ~aux_amask; - } - else if ( insn.Op2.type == o_mem - && (insn.auxpref & aux_amask) == aux_as ) - { - insn.Op2.immdisp = 0; - insn.auxpref &= ~aux_amask; - } - break; - case ARC_add1: - case ARC_add2: - case ARC_add3: - case ARC_sub1: - case ARC_sub2: - case ARC_sub3: - // addN a, b, c -> add a, b, c<<N - if ( insn.Op3.type == o_imm ) - { - switch ( insn.itype ) - { - case ARC_add1: - case ARC_sub1: - insn.Op3.value *= 2; - break; - case ARC_add2: - case ARC_sub2: - insn.Op3.value *= 4; - break; - case ARC_add3: - case ARC_sub3: - insn.Op3.value *= 8; - break; - } - switch ( insn.itype ) - { - case ARC_add1: - case ARC_add2: - case ARC_add3: - insn.itype = ARC_add; - break; - case ARC_sub3: - case ARC_sub2: - case ARC_sub1: - insn.itype = ARC_sub; - break; - } - } - break; - case ARC_sub: - // sub.f 0, a, b -> cmp a, b - if ( insn.Op1.is_imm(0) && (insn.auxpref & aux_f) != 0 ) - { - insn.auxpref &= ~aux_f; - insn.itype = ARC_cmp; - insn.Op1 = insn.Op2; - insn.Op2 = insn.Op3; - insn.Op3.type = o_void; - } - break; - } -} - -//---------------------------------------------------------------------- -// fix operand size for byte or word loads/stores -inline void fix_ldst(insn_t &insn) -{ - if ( insn.itype == ARC_ld || insn.itype == ARC_st ) - { - switch ( insn.auxpref & aux_zmask ) - { - case aux_b: - insn.Op2.dtype = dt_byte; - break; - case aux_w: - insn.Op2.dtype = dt_word; - break; - } - } -} - -//---------------------------------------------------------------------- -// convert pc-relative loads -// ld r1, [pc,#delta] -> ld r1, [memaddr] -static void inline_const(insn_t &insn) -{ - if ( insn.itype == ARC_ld - && insn.Op2.type == o_displ - && insn.Op2.reg == PCL - && (insn.auxpref & (aux_a|aux_zmask)) == 0 ) // no .a and 32-bit access - { - ea_t val_ea = (insn.ea & ~3ul) + insn.Op2.addr; - if ( is_mapped(val_ea) ) - { - insn.Op2.type = o_mem; - insn.Op2.addr = val_ea; - insn.Op2.immdisp = 0; - insn.auxpref |= aux_pcload; - } - } -} - -//---------------------------------------------------------------------- -// analyze an instruction -int arc_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - int sz = is_a4() ? ana_old(insn) : ana_compact(insn); - if ( sz != 0 ) - { - fix_ldst(insn); - if ( (idpflags & ARC_SIMPLIFY) != 0 ) - simplify(insn); - if ( (idpflags & ARC_INLINECONST) != 0 ) - inline_const(insn); - } - return insn.size; -} diff --git a/idasdk75/module/arc/arc.hpp b/idasdk75/module/arc/arc.hpp deleted file mode 100644 index acf15f6..0000000 --- a/idasdk75/module/arc/arc.hpp +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 2012-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * ARC (Argonaut RISC Core) processor module - * - * Based on code contributed by by Felix Domke <tmbinc@gmx.net> - */ - -#ifndef _ARC_HPP -#define _ARC_HPP - -#include <set> -#include "../idaidp.hpp" -#include "ins.hpp" -#include <typeinf.hpp> -#include <diskio.hpp> -#include "../iohandler.hpp" - -//------------------------------------------------------------------------ -// customization of the 'cmd' structure: - -enum processor_subtype_t -{ - prc_arc = 0, // ARCTangent-A4 (old 32-bit ISA) - prc_arcompact = 1, // ARCtangent-A5 and later (32/16-bit mixed) - prc_arcv2 = 2, // ARC EM (ARCompact successor) -}; - -//------------------------------------------------------------------------ -enum RegNo -{ - R0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, R11, R12, R13, R14, R15, - R16, R17, R18, R19, R20, R21, R22, R23, - R24, R25, R26, R27, R28, R29, R30, R31, - - R32, R33, R34, R35, R36, R37, R38, R39, - R40, R41, R42, R43, R44, R45, R46, R47, - R48, R49, R50, R51, R52, R53, R54, R55, - R56, R57, R58, R59, R60, R61, R62, R63, - - CF, ZF, NF, VF, - - // registers used for indexed instructions - // keep these consecutive - NEXT_PC, - LDI_BASE, JLI_BASE, EI_BASE, - - GP_SEG, // virtual segment register for global pointer value - - rVcs, rVds, // virtual registers for code and data segments - - // aliases - - GP = R26, // Global Pointer - FP = R27, // Frame Pointer - SP = R28, // Stack Pointer - ILINK1 = R29, // Level 1 interrupt link register - ILINK2 = R30, // Level 2 interrupt link register - BLINK = R31, // Branch link register - LP_COUNT = R60, // Loop count register - PCL = R63, // 32-bit aligned PC value (ARCompact) - - // optional extension - MLO = R57, // Multiply low 32 bits, read only - MMID = R58, // Multiply middle 32 bits, read only - MHI = R59, // Multiply high 32 bits, read only -}; - -#define SHIMM_F 61 // Short immediate data indicator setting flags -#define LIMM 62 // Long immediate data indicator -#define SHIMM 63 // Short immediate data indicator not setting flags (NB: not used in ARCompact) -#define LIMM5 30 // 5-bit long immediate data indicator (used in ARCv2) - -//------------------------------------------------------------------------ -const ioport_t *find_port(ea_t address); - -#define PROC_MAXOP 4 // max number of operands -CASSERT(PROC_MAXOP <= UA_MAXOP); - -//--------------------------------- - -inline int getreg(const op_t &x) -{ - return x.type == o_reg ? x.reg : -1; -} - -inline bool isreg(const op_t &x, int reg) -{ - return getreg(x) == reg; -} - -inline bool issp(const op_t &x) { return isreg(x, SP); } - -//--------------------------------- -// cmd.auxpref bits -// instructions that use condition flags (Bcc, Jcc) -#define aux_f 0x0100 // Flags set field (.f postfix) -#define aux_nmask 0x0060 // Jump/Call nullify instruction mode -#define aux_nd 0x00 // No Delayed instruction slot (only execute next instruction when not jumping) -#define aux_d 0x20 // Delayed instruction slot (always execute next instruction) -#define aux_jd 0x40 // Jump Delayed instruction slot (only execute next instruction when jumping) -#define aux_cmask 0x001F // condition code mask -// load/store instructions flags (Di.AA.ZZ.X) -#define aux_di 0x0020 // direct to memory (cache bypass) (.di suffix) -#define aux_amask 0x0018 // Address write-back -#define aux_anone 0x00 // no writeback -#define aux_a 0x08 // pre-increment (.a or .aw) -#define aux_ab 0x10 // post-increment (.ab) -#define aux_as 0x18 // scaled access (.as) -#define aux_zmask 0x0006 // size mask -#define aux_l 0x0 // long size (no suffix) -#define aux_w 0x4 // word size (.w suffix) -#define aux_b 0x2 // byte size (.b suffix) -#define aux_x 0x0001 // Sign extend field (.x suffix) - -#define aux_pcload 0x0200 // converted pc-relative to memory load (used when ARC_INLINECONST is set) -#define aux_bhint 0x0400 // non-default static branch prediction hint (.t or .nt suffix) -#define aux_s 0x0800 // 16-bit encoded instruction - -// Operand types: -#define o_reglist o_idpspec0 // register list for enter/leave - -#define reglist specval // o_reglist: registers to save/restore -#define REGLIST_REGS 0x0F // number of core registers to save/restore -#define REGLISTR_MAX 0x0E // max number of core registers to save/restore -#define REGLIST_FP 0x10 // save/restore stack frame -#define REGLIST_BLINK 0x20 // save/restore blink register -#define REGLIST_PCL 0x40 // jump to blink register after restore (leave only) - -// o_phrase -#define secreg specflag1 // o_phrase: the second register is here: [op.phrase, op.secreg] - -// o_displ -#define membase specflag1 // o_displ: if set, displacement is the base value: [op.addr, op.reg] - // this is important for scaled loads, e.g. ld.as r1, [0x23445, r2] -// o_reg -#define regpair specflag1 // o_reg: if set, this operand is the second register of a register pair - // the previous operand contains the other register of the pair -// o_mem -#define immdisp specval // o_mem: immediate displacement to immediate address. - // addr contains the already displaced address. - // addr - get_scale_factor(insn) * immdisp is the base address for immdisp - -//------------------------------------------------------------------ -// Condition codes: -enum cond_t -{ - cAL=0, cRA=0, // Always 1 0x00 - cEQ=1, cZ=1, // Zero Z 0x01 - cNE=2, cNZ=2, // Non-Zero /Z 0x02 - cPL=3, cP=3, // Positive /N 0x03 - cMI=4, cN=4, // Negative N 0x04 - cCS=5, cC=5, cLO=5, // Carry set, lower than (unsigned) C 0x05 - cCC=6, cNC=6, cHS=6, // Carry clear, higher or same (unsigned) /C 0x06 - cVS=7, cV=7, // Over-flow set V 0x07 - cVC=8, cNV=8, // Over-flow clear /V 0x08 - cGT=9, // Greater than (signed) (N and V and /Z) or (/N and /V and /Z) 0x09 - cGE=0x0A, // Greater than or equal to (signed) (N and V) or (/N and /V) 0x0A - cLT=0x0B, // Less than (signed) (N and /V) or (/N and V) 0x0B - cLE=0x0C, // Less than or equal to (signed) Z or (N and /V) or (/N and V) 0x0C - cHI=0x0D, // Higher than (unsigned) /C and /Z 0x0D - cLS=0x0E, // Lower than or same (unsigned) C or Z 0x0E - cPNZ=0x0F, // Positive non-zero /N and /Z 0x0F - cLAST -}; -inline uint8 get_cond(const insn_t &insn) -{ - if ( insn.itype <= ARC_store_instructions ) - return cAL; - return uint8(insn.auxpref & aux_cmask); -} -inline bool has_cond(const insn_t &insn) -{ - if ( insn.itype <= ARC_store_instructions ) - return false; - return (insn.auxpref & aux_cmask) != cAL; -} -inline cond_t get_core_cond(const insn_t &insn) -{ - if ( insn.itype <= ARC_store_instructions ) - return cAL; - uint8 cond = insn.auxpref & aux_cmask; - if ( cond >= cLAST ) - return cLAST; - return cond_t(cond); -} -inline bool has_core_cond(const insn_t &insn) -{ - if ( insn.itype <= ARC_store_instructions ) - return false; - uint8 cond = insn.auxpref & aux_cmask; - return cond != cAL && cond < cLAST; -} -inline cond_t invert_cond(cond_t cond) -{ - switch ( cond ) - { - case cNE: return cEQ; - case cEQ: return cNE; - case cCC: return cCS; - case cCS: return cCC; - case cPL: return cMI; - case cMI: return cPL; - case cVC: return cVS; - case cVS: return cVC; - case cHI: return cLS; - case cLS: return cHI; - case cGE: return cLT; - case cLT: return cGE; - case cGT: return cLE; - case cLE: return cGT; - default: return cLAST; - } -} - -// ARC ABI conventions from gdb/arc-tdep.h -#define ARC_ABI_GLOBAL_POINTER 26 -#define ARC_ABI_FRAME_POINTER 27 -#define ARC_ABI_STACK_POINTER 28 - -#define ARC_ABI_FIRST_CALLEE_SAVED_REGISTER 13 -#define ARC_ABI_LAST_CALLEE_SAVED_REGISTER 26 - -#define ARC_ABI_FIRST_ARGUMENT_REGISTER 0 -#define ARC_ABI_LAST_ARGUMENT_REGISTER 7 - -#define ARC_ABI_RETURN_REGNUM 0 -#define ARC_ABI_RETURN_LOW_REGNUM 0 -#define ARC_ABI_RETURN_HIGH_REGNUM 1 - -//------------------------------------------------------------------------ -// does 'ins' have a delay slot? (next instruction is executed before branch/jump) -inline bool has_dslot(const insn_t &ins) -{ - // EXCEPTION: jl.jd <addr> uses delay slot to - // hide the long immediate used for the address - if ( ins.itype == ARC_jl - && (ins.auxpref & aux_nmask) == aux_jd - && ins.Op1.type == o_near ) - return false; - return ins.itype > ARC_store_instructions && (ins.auxpref & aux_nmask) != 0; -} - -//------------------------------------------------------------------------ -// Scale factor for indexed memory access -inline int get_scale_factor(const insn_t &ins) -{ - switch ( ins.itype ) - { - case ARC_st: - case ARC_ld: - if ( (ins.auxpref & aux_amask) == aux_as ) - { - if ( (ins.auxpref & aux_zmask) == aux_w ) - return 2; - if ( (ins.auxpref & aux_zmask) == aux_l ) - return 4; - } - break; - - case ARC_bih: - return 2; - - case ARC_bi: - case ARC_ldi: - case ARC_jli: - case ARC_ei: - return 4; - } - return 1; -} - -//------------------------------------------------------------------------ -// Should the register be hidden when used as base in o_displ/o_phrase? -// -// 0 output normally -// 1 hide base reg -// -1 hide base reg and output as immediate -inline int is_hidden_base_reg(int reg) -{ - if ( reg >= NEXT_PC && reg <= EI_BASE ) - { - return reg == JLI_BASE || reg == EI_BASE ? -1 : 1; - } - return 0; -} - -//------------------------------------------------------------------------ -// The sreg that contains the current value for the given register -// -// Returns -1 if there is no such sreg -inline int get_base_sreg(int reg) -{ - if ( reg == GP ) - return GP_SEG; - else if ( reg >= LDI_BASE && reg <= GP_SEG ) - return reg; - return -1; -} - -//------------------------------------------------------------------------ -void idaapi arc_header(outctx_t &ctx); -void idaapi arc_footer(outctx_t &ctx); - -int idaapi is_sp_based(const insn_t &insn, const op_t & x); -bool idaapi create_func_frame(func_t * pfn); -int idaapi arc_get_frame_retsize(const func_t * pfn); -bool is_arc_return_insn(const insn_t &insn); -bool arc_is_switch(switch_info_t *si, const insn_t &insn); -inline bool is_arc_simple_branch(uint16 itype) -{ - return itype == ARC_bl - || itype == ARC_jl - || itype == ARC_b - || itype == ARC_j; -} - -int get_arc_fastcall_regs(const int **regs); -bool calc_arc_arglocs(func_type_data_t *fti); -bool calc_arc_varglocs( - func_type_data_t *fti, - regobjs_t *regargs, - int nfixed); -bool calc_arc_retloc(argloc_t *retloc, const tinfo_t &tif, cm_t cc); -void use_arc_arg_types( - ea_t ea, - func_type_data_t *fti, - funcargvec_t *rargs); - -//------------------------------------------------------------------------ -struct arc_iohandler_t : public iohandler_t -{ - struct arc_t ± - arc_iohandler_t(arc_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual const char *iocallback(const ioports_t &iop, const char *line) override; - virtual void get_cfg_filename(char *buf, size_t bufsize) override; -}; - -DECLARE_PROC_LISTENER(pm_idb_listener_t, struct arc_t); - -struct arc_t : public procmod_t -{ - netnode helper; // altval(-1): idp flags -#define CALLEE_TAG 'A' // altval(ea): callee address for indirect calls -#define DXREF_TAG 'd' // altval(ea): resolved address for complex calculation (e.g. ADD R1, PC) -#define DSLOT_TAG 's' // altval(ea): 1: delay slot of an unconditional jump/branch - // 2: delay slot of a conditional jump/branch - // 3: delay slot of a jl/bl - inline void set_callee(ea_t ea, ea_t callee) { helper.easet(ea, callee, CALLEE_TAG); } - inline ea_t get_callee(ea_t ea) { return helper.eaget(ea, CALLEE_TAG); } - inline void del_callee(ea_t ea) { helper.eadel(ea, CALLEE_TAG); } - - inline void set_dxref(ea_t ea, ea_t dxref) { helper.easet(ea, dxref, DXREF_TAG); } - inline ea_t get_dxref(ea_t ea) { return helper.eaget(ea, DXREF_TAG); } - inline void del_dxref(ea_t ea) { helper.eadel(ea, DXREF_TAG); } - - ioports_t auxregs; - arc_iohandler_t ioh = arc_iohandler_t(*this, helper); - pm_idb_listener_t idb_listener = pm_idb_listener_t(*this); - - processor_subtype_t ptype = prc_arc; - inline bool is_a4() { return ptype == prc_arc; } - inline bool is_arcv2() { return ptype == prc_arcv2; } - - int arc_respect_info = IORESP_ALL; - - int ref_arcsoh_id = 0; - int ref_arcsol_id = 0; - -#define ARC_SIMPLIFY 0x01 -#define ARC_INLINECONST 0x02 -#define ARC_TRACKREGS 0x04 - ushort idpflags = ARC_SIMPLIFY | ARC_INLINECONST | ARC_TRACKREGS; - - int g_limm = 0; - bool got_limm = false; - - std::set<ea_t> renamed; - int islast = 0; - - // is 'ea' in a delay slot of a branch/jump? - inline bool is_dslot(ea_t ea, bool including_calls = true) - { - nodeidx_t v = helper.altval_ea(ea, DSLOT_TAG); - if ( including_calls ) - return v != 0; - else - return v == 1 || v == 2; - } - - inline bool is_imm(int regno) - { - if ( regno == LIMM ) - return true; - if ( regno == SHIMM_F || regno == SHIMM ) - return is_a4(); - return false; - } - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - bool select_device(int resp_info); - inline void add_dxref(const insn_t &insn, ea_t target); - int emu(const insn_t &insn); - bool is_arc_basic_block_end( - const insn_t &insn, - bool call_insn_stops_block); - void del_insn_info(ea_t ea); - const char *set_idp_options( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded); - void set_codeseqs() const; - void set_instruc_names(); - void ptype_changed(); - void doIndirectOperand(const insn_t &insn, int b, int c, op_t &op, int d, int li, bool special); - void doRegisterInstruction(insn_t &insn, uint32 code); - int ana_old(insn_t &insn); - void decode_operand( - insn_t &insn, - uint32 code, - int &op_pos, - uint32 opkind); - int analyze_compact(insn_t &insn, uint32 code, int idx, const struct arcompact_opcode_t *table); - int ana_compact(insn_t &insn); - int ana(insn_t *_insn); - int is_align_insn(ea_t ea) const; - bool good_target(const insn_t &insn, ea_t target) const; - bool copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, void *value = NULL, bool force = false) const; - void handle_operand(const insn_t &insn, const op_t & x, bool loading); - int get_limm(insn_t &insn); - inline void opreg(insn_t &insn, op_t &x, int rgnum, int limm=LIMM); - inline void opdisp(insn_t &insn, op_t &x, int rgnum, ea_t disp); - void rename_if_not_set(ea_t ea, const char *name); - bool check_ac_pop_chain(int *regno, ea_t ea); - bool detect_millicode(qstring *mname, ea_t ea); - bool is_millicode(ea_t ea, sval_t *spdelta=nullptr); - sval_t calc_sp_delta(const insn_t &insn); - void trace_sp(const insn_t &insn); - bool arc_calc_spdelta(sval_t *spdelta, const insn_t &insn); - int arc_may_be_func(const insn_t &insn, int state); - void force_offset( - ea_t ea, - int n, - ea_t base, - bool issub = false, - int scale = 1); - bool spoils(const insn_t &insn, int reg) const; - int spoils(const insn_t &insn, const uint32 *regs, int n) const; - bool is_arc_call_insn(const insn_t &insn); - bool find_op_value_ex( - const insn_t &insn, - const op_t &x, - struct ldr_value_info_t *lvi, - bool /*check_fbase_reg*/); - bool find_ldr_value_ex( - const insn_t &insn, - ea_t ea, - int reg, - struct ldr_value_info_t *lvi, - bool /*check_fbase_reg*/); - bool find_op_value( - const insn_t &insn, - const op_t &x, - uval_t *p_val, - ea_t *p_val_ea=NULL, - bool check_fbase_reg=true, - bool *was_const_load=NULL); - bool find_ldr_value( - const insn_t &insn, - ea_t ea, - int reg, - uval_t *p_val, - ea_t *p_val_ea=NULL, - bool check_fbase_reg=true, - bool *was_const_load=NULL); - int use_arc_regarg_type(ea_t ea, const funcargvec_t &rargs); - bool arc_set_op_type( - const insn_t &insn, - const op_t &x, - const tinfo_t &tif, - const char *name, - eavec_t *visited); - void use_arc_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs); - - void arc_segstart(outctx_t &ctx, segment_t *Sarea) const; -}; -extern int data_id; - -#endif diff --git a/idasdk75/module/arc/emu.cpp b/idasdk75/module/arc/emu.cpp deleted file mode 100644 index 9fbf971..0000000 --- a/idasdk75/module/arc/emu.cpp +++ /dev/null @@ -1,2890 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su, ig@datarescue.com - * FIDO: 2:5020/209 - * - */ - -#include <map> -#include <set> - -#include "arc.hpp" -#include <frame.hpp> -#include <xref.hpp> -#include <jumptable.hpp> -#include <segregs.hpp> - -//#define DEBUG_ARGLOC - -//---------------------------------------------------------------------- -#ifdef DEBUG_ARGLOC -static void debug_print_argloc(int i, const argloc_t &argloc, const tinfo_t &type) -{ - qstring typestr; - type.print(&typestr); - char varstr[MAXSTR]; - if ( argloc.is_stkoff() ) - qsnprintf(varstr, sizeof(varstr), "STK_%x", int(argloc.stkoff())); - else - print_argloc(varstr, sizeof(varstr), argloc, type.get_size()); - if ( i == -1 ) - msg("RET: %s %s\n", typestr.c_str(), varstr); - else - msg("%d: %s %s\n", i, typestr.c_str(), varstr); -} -#else -inline void debug_print_argloc(int, const argloc_t &, const tinfo_t &) {} -#endif - -// does the expression [reg, xxx] point to the stack? -static bool is_stkptr(const insn_t &insn, int reg) -{ - if ( reg == SP ) - return true; - if ( reg == FP ) - { - func_t *pfn = get_func(insn.ea); - - if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) - return true; - } - return false; -} - -void arc_t::handle_operand(const insn_t &insn, const op_t & x, bool loading) -{ - flags_t F; - switch ( x.type ) - { - case o_reg: - break; - case o_imm: - set_immd(insn.ea); - F = get_flags(insn.ea); - if ( op_adds_xrefs(F, x.n) ) - { - insn.add_off_drefs(x, dr_O, OOFS_IFSIGN); - } - else if ( x.n == 2 && may_create_stkvars() && !is_defarg(F, x.n) - && insn.itype == ARC_add && !insn.Op1.is_reg(SP) && !insn.Op1.is_reg(FP) - && (insn.Op2.is_reg(SP) || insn.Op2.is_reg(FP)) ) - { - // add rx, sp, #imm - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL ) - { - adiff_t sp_off = x.value; - if ( insn.create_stkvar(x, sp_off, 0) ) - op_stkvar(insn.ea, x.n); - } - } - break; - case o_mem: - if ( insn.itype != ARC_lr && insn.itype != ARC_sr ) - { - ea_t ea = to_ea(insn.cs, x.addr); - insn.create_op_data(ea, x); // create the data item of the correct size - insn.add_dref(ea, x.offb, loading ? dr_R : dr_W); - if ( (idpflags & ARC_INLINECONST) != 0 && insn.itype == ARC_ld ) - copy_insn_optype(insn, x, ea); - } - break; - case o_near: - { - int iscall = has_insn_feature(insn.itype, CF_CALL); - - insn.add_cref(to_ea(insn.cs, x.addr), x.offb, iscall ? fl_CN : fl_JN); - if ( !islast && iscall ) - { - if ( !func_does_return(x.addr) ) // delay slot?! - islast = 1; - } - } - break; - case o_displ: - set_immd(insn.ea); - F = get_flags(insn.ea); - if ( !is_defarg(F, x.n) ) - { - ea_t base = BADADDR; - if ( x.reg == PCL ) - base = insn.ea & (~3ul); - else if ( x.reg == NEXT_PC ) - base = insn.ea + insn.size; - int sreg = get_base_sreg(x.reg); - if ( sreg > 0 ) - base = get_sreg(insn.ea, sreg); - if ( base != BADADDR ) - { - int scale = get_scale_factor(insn); - reftype_t reftype = REF_OFF32; - if ( scale == 2 ) - reftype = ref_arcsoh_id | REFINFO_CUSTOM; - else if ( scale == 4 ) - reftype = ref_arcsol_id | REFINFO_CUSTOM; - op_offset(insn.ea, x.n, reftype | REFINFO_NOBASE, BADADDR, base); - } - } - if ( op_adds_xrefs(F, x.n) ) // create an xref for offset expressions - { - if ( insn.itype == ARC_jli ) - { - // for jli the reference target is called, not read - ea_t base = get_sreg(insn.ea, JLI_BASE); - insn.add_cref(base + 4 * x.addr, 0, fl_CF); - } - else if ( insn.itype == ARC_bi || insn.itype == ARC_bih ) - { - // for bi/bih the reference target is jumped to, not read - ea_t next_pc = insn.ea + insn.size; - int scale = insn.itype == ARC_bi ? 4 : 2; - insn.add_cref(next_pc + scale * x.addr, 0, fl_JN); - } - else - { - ea_t target = insn.add_off_drefs(x, loading ? dr_R : dr_W, OOF_ADDR|OOF_SIGNED|OOFW_32); - if ( target != BADADDR ) - insn.create_op_data(target, x); // create the data item of the correct size - } - } - else if ( is_stkptr(insn, x.phrase) && may_create_stkvars() && !is_defarg(F, x.n) ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL ) - { - // if it's [sp, xxx] we make a stackvar out of it - adiff_t sp_off = x.addr; - if ( insn.create_stkvar(x, sp_off, STKVAR_VALID_SIZE) ) - op_stkvar(insn.ea, x.n); - } - } - break; - } -} - -//---------------------------------------------------------------------- -inline bool is_callee_saved(int reg) -{ - return reg >= ARC_ABI_FIRST_CALLEE_SAVED_REGISTER - && reg <= ARC_ABI_LAST_CALLEE_SAVED_REGISTER; -} - -//---------------------------------------------------------------------- -// Is register 'reg' spoiled by the current instruction? -#define PROC_MAXCHGOP 2 -bool arc_t::spoils(const insn_t &insn, int reg) const -{ - switch ( insn.itype ) - { - case ARC_pop: - case ARC_push: - if ( reg == SP ) - return true; - break;// otherwise check flags - - case ARC_ld: // ld Rx, [reg, #imm] - case ARC_st: // st.a R1, [R2, #imm] - if ( insn.Op2.reg == reg && ((insn.auxpref & aux_amask) == aux_a || (insn.auxpref & aux_amask) == aux_ab) ) - return true; - break;// otherwise check flags - - case ARC_bl: - case ARC_jl: - return !is_callee_saved(reg); - - case ARC_enter: - case ARC_leave: - { - if ( insn.Op1.reglist == 0 ) - return false; - if ( reg == SP ) - return true; - // FP is set to SP on enter and restored on leave - if ( (insn.Op1.reglist & REGLIST_FP) != 0 && reg == FP ) - return true; - if ( insn.itype == ARC_enter ) - return false; - int regs = insn.Op1.reglist & REGLIST_REGS; - return (insn.Op1.reglist & REGLIST_BLINK) != 0 && reg == BLINK - || reg >= R13 && reg < R13 + regs; - } - } - - uint32 feature = insn.get_canon_feature(ph); - if ( feature != 0 ) - { - for ( int i = 0; i < PROC_MAXOP; ++i ) - { - if ( has_cf_chg(feature, i) && insn.ops[i].is_reg(reg) ) - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -// does the instruction spoil the flags? -static bool spoils_flags(const insn_t &insn) -{ - return insn.itype == ARC_cmp - || insn.itype == ARC_flag - || insn.itype == ARC_modif - || insn.itype == ARC_fscmp - || insn.itype == ARC_fscmpf - || (insn.auxpref & aux_f) != 0; -} - -// info about a single register -struct ldr_value_info_t -{ - uval_t value; // value loaded into the register - ea_t val_ea; // where the value comes from (for constant pool or immediate loads) - eavec_t insn_eas; // insns that were involved in calculating the value - char n; // operand number - char state; -#define LVI_STATE 0x03 // state mask -#define LVI_UNKNOWN 0x00 // unknown state -#define LVI_VALID 0x01 // value known to be valid -#define LVI_INVALID 0x02 // value known to be invalid -#define LVI_CONST 0x04 // is the value constant? (e.g. immediate or const pool) - - ldr_value_info_t(void) - : value(0), val_ea(BADADDR), n(0), state(LVI_UNKNOWN) - {} - bool is_const(void) const { return (state & LVI_CONST) != 0; } - bool is_valid(void) const { return (state & LVI_STATE) == LVI_VALID; } - bool is_known(void) const { return (state & LVI_STATE) != LVI_UNKNOWN; } - void set_valid(bool valid) - { - state &= ~LVI_STATE; - state |= valid ? LVI_VALID : LVI_INVALID; - } - void set_const(void) { state |= LVI_CONST; } -}; - -//---------------------------------------------------------------------- -// helper class for find_op_value/find_ldr_value -// we keep a cache of discovered register values to avoid unnecessary recursion -struct reg_tracker_t -{ - // map cannot store an array directly, so wrap it in a class - struct reg_values_t - { - ldr_value_info_t regs[R60+1]; // values for registers R0 to R60 for a specific ea - }; - - typedef std::map<ea_t, reg_values_t> reg_values_cache_t; - - arc_t ± - // we save both valid and invalid values into in the cache. - reg_values_cache_t regcache; - - reg_tracker_t(arc_t *p) : pm(*p) {} - // recursive functions; they can call each other, so we limit the nesting level - bool do_find_op_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level); - bool do_find_ldr_value(const insn_t &insn, ea_t ea, int reg, ldr_value_info_t *p_lvi, int nest_level); - bool do_calc_complex_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level); - - bool is_call_insn(const insn_t &insn) const; -}; - -//---------------------------------------------------------------------- -bool reg_tracker_t::is_call_insn(const insn_t &insn) const -{ - switch ( insn.itype ) - { - case ARC_bl: - case ARC_jli: - return true; - - case ARC_jl: - if ( insn.Op1.reg != BLINK && insn.Op1.reg != ILINK1 && insn.Op1.reg != ILINK2 ) - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool arc_t::is_arc_call_insn(const insn_t &insn) -{ - reg_tracker_t tr(this); - return tr.is_call_insn(insn); -} - -//---------------------------------------------------------------------- -bool reg_tracker_t::do_find_op_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level) -{ - switch ( x.type ) - { - case o_reg: - return do_find_ldr_value(insn, insn.ea, x.reg, lvi, nest_level); - case o_imm: - if ( lvi != NULL ) - { - lvi->value = x.value & 0xFFFFFFFF; - lvi->set_const(); - lvi->set_valid(true); - lvi->insn_eas.push_back(insn.ea); - } - return true; - case o_displ: - case o_phrase: - { - ldr_value_info_t val2; - if ( do_calc_complex_value(insn, x, &val2, nest_level+1) && val2.is_valid() ) - { - if ( lvi != NULL ) - { - *lvi = val2; - if ( lvi->is_valid() ) - lvi->insn_eas.push_back(insn.ea); - } - return true; - } - } - break; - case o_mem: - if ( lvi != NULL ) - { - ea_t value = to_ea(insn.cs, x.addr); - ea_t val_ea = BADADDR; - if ( insn.itype == ARC_ld && insn.Op2.dtype == dt_dword ) - { - val_ea = value; - value = BADADDR; - if ( is_loaded(val_ea) ) - { - value = get_dword(val_ea); - lvi->set_const(); - lvi->set_valid(true); - lvi->insn_eas.push_back(insn.ea); - } - } - lvi->val_ea = uint32(val_ea); - lvi->value = uint32(value); - } - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// check if ea is in a const segment, and so we can use the pointer value -static bool is_const_seg(ea_t ea) -{ - if ( !is_loaded(ea) ) - return false; - - const char *const *names = NULL; - int ncnt = 0; - if ( inf_get_filetype() == f_MACHO ) - { - static const char *const macho_segs[] = - { - "__const", "__const_coal", - "__text", "__dyld", - "__la_symbol_ptr", "__nl_symbol_ptr", - "__class", "__cls_refs", "__message_refs", - "__inst_meth", "__cat_inst_meth", "__cat_cls_meth", - "__constructor", "__destructor", "__pointers", - "__objc_protorefs", - "__objc_selrefs", - "__objc_classrefs", - "__objc_superrefs", - "__objc_const", - }; - names = macho_segs; - ncnt = qnumber(macho_segs); - } - else if ( inf_get_filetype() == f_ELF ) - { - static const char *const elf_segs[] = - { - ".got", ".text", ".rodata", - ".got.plt", ".plt", - ".init", ".fini" - }; - names = elf_segs; - ncnt = qnumber(elf_segs); - } - if ( names != NULL ) - { - segment_t *seg = getseg(ea); - if ( seg != NULL ) - { - qstring segname; - if ( get_segm_name(&segname, seg) > 0 ) - { - for ( size_t i = 0; i < ncnt; i++ ) - if ( segname == names[i] ) - return true; - } - } - } - - if ( segtype(ea) == SEG_CODE ) - return true; - - segment_t *seg = getseg(ea); - if ( seg != NULL && (seg->perm & (SEGPERM_WRITE|SEGPERM_READ)) == SEGPERM_READ ) - return true; - - return false; -} - -//---------------------------------------------------------------------- -// calculate value of a complex operand -// ld [<Rn>, #+/-<offset>] -// ld [<Rn>, <Rm>] -// ld.a [<Rn>, #+/-<offset>] -// ld.ab [<Rn>, #+/-<offset>] (post-increment) -// val_ea is always calculated, val only for dword accesses to const segments -// returns true is val_ea is ok; value may be still wrong! set is_valid() for the value -bool reg_tracker_t::do_calc_complex_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level) -{ - ldr_value_info_t val1; - ea_t val_ea = BADADDR; - uval_t value = BADADDR; - bool ok = false; - if ( do_find_ldr_value(insn, insn.ea, x.reg, &val1, nest_level+1) ) - { - ldr_value_info_t val2; - if ( (insn.auxpref & aux_amask) == aux_ab ) // post-increment - { - ok = true; - val2.value = 0; - } - else - { - if ( x.type == o_phrase ) - { - ok = do_find_ldr_value(insn, insn.ea, x.secreg, &val2, nest_level+1); - } - else if ( x.type == o_displ ) - { - ok = true; - val2.value = (int32)x.addr; - } - if ( !ok ) - return false; - } - int scale1 = 1; - int scale2 = 1; - if ( x.membase ) - scale1 = get_scale_factor(insn); - else - scale2 = get_scale_factor(insn); - val_ea = to_ea(insn.cs, scale1 * val1.value + scale2 * val2.value); - if ( x.dtype == dt_dword && is_const_seg(val_ea) ) - value = get_dword(val_ea); - } - if ( ok && lvi != NULL ) - { - lvi->value = uint32(value); - if ( value != BADADDR ) - lvi->set_valid(true); - lvi->val_ea = uint32(val_ea); - lvi->n = x.n; - } - return ok; -} - -//---------------------------------------------------------------------- -bool reg_tracker_t::do_find_ldr_value( - const insn_t &insn, - ea_t ea, - int reg, - ldr_value_info_t *p_lvi, - int nest_level) -{ - if ( nest_level > 200 ) - return false; - bool ok = false; - ldr_value_info_t lvi; - do - { - if ( reg == PCL || reg == NEXT_PC ) - { - lvi.value = reg == PCL ? insn.ip & ~3ul : insn.ip + insn.size; - lvi.value &= 0xFFFFFFFF; - lvi.set_valid(true); - lvi.set_const(); - lvi.insn_eas.push_back(insn.ea); - ok = true; - break; - } - - int sreg = get_base_sreg(reg); - if ( sreg >= 0 ) - { - lvi.value = get_sreg(ea, sreg); - if ( lvi.value != BADADDR ) - { - lvi.set_valid(true); - lvi.set_const(); - ok = true; - break; - } - } - - if ( reg >= R60 || reg < 0 ) - { - // not handled - break; - } - - // check if it's in the cache - reg_values_cache_t::iterator regs_it = regcache.find(ea); - if ( regs_it != regcache.end() ) - { - const ldr_value_info_t &cached = regs_it->second.regs[reg]; - if ( cached.is_known() ) - { - ok = lvi.is_valid(); - if ( ok ) - lvi = cached; - break; - } - } - - /* - ushort fbase_reg; - if ( check_fbase_reg && get_fbase_info(&lvi.value, &fbase_reg) && fbase_reg == reg ) - { - lvi.value -= to_ea(insn.cs, 0); - ok = true; - } - */ - - const insn_t *pinsn = &insn; - insn_t curr_insn; - while ( !ok ) - { - flags_t F = get_flags(pinsn->ea); - if ( has_xref(F) || !is_flow(F) ) - { - // count xrefs to the current instruction - xrefblk_t xb; - int numxrefs = 0; - ea_t xref_from = BADADDR; - for ( bool ok2 = xb.first_to(pinsn->ea, XREF_ALL); - ok2 && numxrefs < 2; - ok2 = xb.next_to() ) - { - if ( xb.iscode && xb.from < pinsn->ea ) // count only xrefs from above - { - // call xref => bad - if ( xb.type == fl_CN || xb.type == fl_CF ) - { - numxrefs = 0; - break; - } - xref_from = xb.from; - numxrefs++; - } - } - // if we have a single xref, use it - if ( numxrefs != 1 || xref_from == BADADDR || decode_insn(&curr_insn, xref_from) == 0 ) - break; - - } - else - { - if ( decode_prev_insn(&curr_insn, pinsn->ea) == BADADDR ) - break; - } - pinsn = &curr_insn; - - // we started with a conditional instruction? - // (BR.cc does not actually use a condition code) - if ( has_cond(insn) && insn.itype != ARC_br ) - { - // ignore instructions which belong to different condition branches - if ( !has_cond(*pinsn) || pinsn->itype == ARC_br ) - continue; - if ( get_cond(*pinsn) != get_cond(insn) ) - continue; - // if current instruction changes flags, stop tracking - if ( spoils_flags(*pinsn) ) - break; - } - - if ( pinsn->Op1.is_reg(reg) ) - { - switch ( pinsn->itype ) - { - case ARC_ld: - if ( pinsn->Op2.type == o_mem && pinsn->Op2.dtype == dt_dword ) - { - lvi.val_ea = to_ea(pinsn->cs, pinsn->Op2.addr); - if ( is_loaded(lvi.val_ea) && is_const_seg(lvi.val_ea) ) - { - lvi.value = get_dword(lvi.val_ea); - lvi.set_const(); - ok = true; - } - } - else if ( pinsn->Op2.type == o_displ || pinsn->Op2.type == o_phrase ) - { - ok = do_calc_complex_value(*pinsn, pinsn->Op2, &lvi, nest_level+1) && lvi.is_valid(); - } - if ( ok ) - lvi.insn_eas.push_back(pinsn->ea); - break; - case ARC_mov: - ok = do_find_op_value(*pinsn, pinsn->Op2, &lvi, nest_level+1); - if ( ok ) - { - if ( pinsn->itype == ARC_mov && pinsn->Op2.type == o_imm ) - { - // MOV Rx, #ABCD - lvi.val_ea = pinsn->ea; - lvi.n = 1; - } - } - break; - case ARC_asr: - case ARC_lsl: - case ARC_lsr: - case ARC_ror: - case ARC_and: - case ARC_xor: - case ARC_add: - case ARC_sub: - case ARC_rsub: - case ARC_or: - case ARC_bic: - { - ldr_value_info_t v1; - ldr_value_info_t v2; - const op_t *op1 = &pinsn->Op1; - const op_t *op2 = &pinsn->Op2; - if ( pinsn->Op3.type != o_void ) - { // arm mode - op1++; // points to pinsn->Op2 - op2++; // points to pinsn->Op3 - } - if ( !do_find_op_value(*pinsn, *op1, &v1, nest_level+1) ) - break; - if ( !do_find_op_value(*pinsn, *op2, &v2, nest_level+1) ) - break; - switch ( pinsn->itype ) - { - case ARC_add: - lvi.value = v1.value + v2.value; - break; - case ARC_sub: - lvi.value = v1.value - v2.value; - break; - case ARC_rsub: - lvi.value = v2.value - v1.value; - break; - case ARC_or: - lvi.value = v1.value | v2.value; - break; - case ARC_asr: - lvi.value = ((int32)v1.value) >> v2.value; - break; - case ARC_lsl: - lvi.value = v1.value << v2.value; - break; - case ARC_lsr: - lvi.value = ((uint32)v1.value) >> v2.value; - break; - case ARC_ror: - v2.value %= 32; - lvi.value = (v1.value >> v2.value) | left_shift(v1.value, 32-v2.value); - break; - case ARC_and: - lvi.value = v1.value & v2.value; - break; - case ARC_xor: - lvi.value = v1.value ^ v2.value; - break; - case ARC_bic: - lvi.value = v1.value & ~v2.value; - break; - } - ok = true; - if ( v1.is_const() && v2.is_const() ) - lvi.set_const(); - // we do not take into account the insns that calculate .got - /* - if ( got_ea == BADADDR || v1.value != got_ea ) - add_eavec(&lvi.insn_eas, v1.insn_eas); - if ( got_ea == BADADDR || v2.value != got_ea ) - add_eavec(&lvi.insn_eas, v2.insn_eas);*/ - lvi.insn_eas.push_back(pinsn->ea); - } - break; - } - } - else if ( (pinsn->itype == ARC_ld || pinsn->itype == ARC_st) - && pinsn->Op2.type == o_displ && pinsn->Op2.reg == reg - && ((pinsn->auxpref & aux_amask) == aux_a || (pinsn->auxpref & aux_amask) == aux_ab) ) - { - // writeback of the base reg - // find the previous value - op_t x = pinsn->Op2; - x.type = o_reg; - ok = do_find_op_value(*pinsn, x, &lvi, nest_level+1); - if ( ok ) - { - // add the immediate - lvi.value += pinsn->Op2.addr; - lvi.insn_eas.push_back(pinsn->ea); - } - } - if ( pm.spoils(*pinsn, reg) ) - break; - } -#ifdef __EA64__ - lvi.value &= 0xFFFFFFFF; -#endif - lvi.set_valid(ok); - regcache[ea].regs[reg] = lvi; - } - while ( false ); - - if ( ok && p_lvi != NULL ) - *p_lvi = lvi; - return ok; -} - -//---------------------------------------------------------------------- -bool arc_t::find_op_value_ex( - const insn_t &insn, - const op_t &x, - struct ldr_value_info_t *lvi, - bool /*check_fbase_reg*/) -{ - reg_tracker_t tr(this); - return tr.do_find_op_value(insn, x, lvi, 0); -} - -//---------------------------------------------------------------------- -// find the value loaded into reg -bool arc_t::find_ldr_value_ex( - const insn_t &insn, - ea_t ea, - int reg, - struct ldr_value_info_t *lvi, - bool /*check_fbase_reg*/) -{ - reg_tracker_t tr(this); - return tr.do_find_ldr_value(insn, ea, reg, lvi, 0); -} - -//---------------------------------------------------------------------- -bool arc_t::find_op_value( - const insn_t &insn, - const op_t &x, - uval_t *p_val, - ea_t *p_val_ea, - bool check_fbase_reg, - bool *was_const_load) -{ - ldr_value_info_t tmp; - if ( find_op_value_ex(insn, x, &tmp, check_fbase_reg) ) - { - if ( p_val != NULL ) - *p_val = tmp.value; - if ( p_val_ea != NULL ) - *p_val_ea = tmp.val_ea; - if ( was_const_load != NULL ) - *was_const_load = tmp.is_const(); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool arc_t::find_ldr_value( - const insn_t &insn, - ea_t ea, - int reg, - uval_t *p_val, - ea_t *p_val_ea, - bool check_fbase_reg, - bool *was_const_load) -{ - ldr_value_info_t tmp; - if ( find_ldr_value_ex(insn, ea, reg, &tmp, check_fbase_reg) ) - { - if ( p_val != NULL ) - *p_val = tmp.value; - if ( p_val_ea != NULL ) - *p_val_ea = tmp.val_ea; - if ( was_const_load != NULL ) - *was_const_load = tmp.is_const(); - return true; - } - return false; -} - -//------------------------------------------------------------------------- -// 4 sub rA, rA', #minv (optional) -// 3 cmp rA, #size | brhs rA, #size, default -// bhi default or | -// bls body with optional 'b default' -// body: -// 2 ldb.x rA, [rJumps,rA'] | ld.as rA, [#jumps,rA'] (if not using bi/bih) -// 1 add1 rA, rElbase, rA' (optional) -// 0 j [rA] | bi [rA] | bih [rA] - -static const char arc_depends[][4] = -{ - { 1 | JPT_OPT }, // 0 - { 2 }, // 1 optional - { 3 }, // 2 if and only if not using bi/bih - { 4 | JPT_OPT | JPT_NEAR }, // 3 - { 0 }, // 4 optional -}; - -struct arc_jump_pattern_t : public jump_pattern_t -{ -protected: - enum { rA, rC }; - enum - { - BODY_NJPI = 2, // ldb.x rA, [rJumps,rA'] - ELBASE_NJPI = 1, // add1 rA, rElbase, rA' - }; - arc_t ± - ea_t jumps_offset_ea; - int jumps_offset_n; - ea_t elbase_offset_ea; //lint !e958 padding is required - int elbase_offset_n; - -public: - arc_jump_pattern_t(procmod_t *_pm, switch_info_t *_si) - : jump_pattern_t(_si, arc_depends, rC), - pm(*(arc_t *)_pm), - jumps_offset_ea(BADADDR), - jumps_offset_n(-1), - elbase_offset_ea(BADADDR), - elbase_offset_n(-1) - { - modifying_r32_spoils_r64 = false; - si->flags |= SWI_HXNOLOWCASE; - non_spoiled_reg = rA; - } - - virtual void process_delay_slot(ea_t &ea, bool branch) const override; - virtual bool equal_ops(const op_t &x, const op_t &y) const override; - virtual bool handle_mov(tracked_regs_t &_regs) override; - virtual void check_spoiled(tracked_regs_t *_regs) const override; - - bool jpi4() override; // sub rA, rA', #minv - bool jpi3() override; // cmp followed by the conditional jump or 'brhi/lo' - bool jpi2() override; // ldb.x rA, [rJumps,rA'] - bool jpi1() override; // add1 rA, rElbase, rA' - bool jpi0() override; // j [rA] | bi [rA] | bih [rA] - - //lint -esym(1762, arc_jump_pattern_t::finish) member function could be made const - bool finish(); - -protected: - static inline bool optype_supported(const op_t &x); - - // helpers - // brhs rA, #size, default | brlo rA, #size, body - bool jpi_cmp_jump(const op_t **op_var); - // bhi default | bls body with optional 'b default' - bool jpi_condjump(); - // cmp rA, #size - bool jpi_cmp_ncases(const op_t **op_var); - - // prepare and track rC - bool analyze_cond(cond_t cond, ea_t jump); -}; - -//------------------------------------------------------------------------- -void arc_jump_pattern_t::process_delay_slot(ea_t &ea, bool branch) const -{ - flags_t F = get_flags(ea); - if ( !is_code(F) ) - return; - insn_t insn2; - if ( branch ) - { - if ( decode_insn(&insn2, ea) != 0 && has_dslot(insn2) ) - ea += insn2.size; - } - /*else - { - return; // no 'likely' insn in ARC - }*/ -} - -//------------------------------------------------------------------------- -bool arc_jump_pattern_t::equal_ops(const op_t &x, const op_t &y) const -{ - if ( x.type != y.type ) - return false; - // ignore difference in the data size of registers - switch ( x.type ) - { - case o_void: - // consider spoiled values as not equal - return false; - case o_reg: - return x.reg == y.reg; - case o_displ: - return x.phrase == y.phrase && x.addr == y.addr; - case o_condjump: - // we do not track the condition flags - return true; - } - return false; -} - -//------------------------------------------------------------------------- -inline bool arc_jump_pattern_t::optype_supported(const op_t &x) -{ - // we can work with the following types only - return x.type == o_reg && x.reg <= R63 - || x.type == o_displ; -} - -//------------------------------------------------------------------------- -bool arc_jump_pattern_t::handle_mov(tracked_regs_t &_regs) -{ - const op_t *src = &insn.Op2; - const op_t *dst = &insn.Op1; - switch ( insn.itype ) - { - case ARC_add: - case ARC_lsl: - case ARC_lsr: - case ARC_sub: - case ARC_xor: - case ARC_or: - if ( insn.Op3.type != o_imm || insn.Op3.value != 0 ) - return false; - // no break - case ARC_ld: - case ARC_mov: - break; - case ARC_st: - std::swap(src, dst); - break; - default: - return false; - } - if ( !optype_supported(*src) || optype_supported(*dst) ) - return false; - return set_moved(*dst, *src, _regs); -} - -//------------------------------------------------------------------------- -void arc_jump_pattern_t::check_spoiled(tracked_regs_t *__regs) const -{ - tracked_regs_t &_regs = *__regs; - for ( uint i = 0; i < _regs.size(); ++i ) - { - const op_t &x = _regs[i]; - if ( x.type == o_reg && pm.spoils(insn, x.reg) - || x.type == o_condjump && spoils_flags(insn) ) - { - set_spoiled(&_regs, x); - } - } - check_spoiled_not_reg(&_regs, PROC_MAXCHGOP); -} - -//---------------------------------------------------------------------- -// j [rA] -bool arc_jump_pattern_t::jpi0() -{ - if ( insn.itype == ARC_bi || insn.itype == ARC_bih ) - { - si->jumps = insn.ea + insn.size; - si->flags |= SWI_JMPINSN; - si->set_jtable_element_size(insn.itype == ARC_bi ? 4 : 2); - - skip[1] = true; // no jpi2 - skip[2] = true; // no jpi2 - track(insn.Op1.secreg, rA, dt_dword); - return true; - } - - if ( insn.itype != ARC_j - || insn.Op1.type != o_displ - || insn.Op1.addr != 0 - || has_cond(insn) ) - { - return false; - } - track(insn.Op1.phrase, rA, dt_dword); - return true; -} - -//---------------------------------------------------------------------- -// add1 rA, rElbase, rA' -bool arc_jump_pattern_t::jpi1() -{ - if ( insn.itype != ARC_add1 - && insn.itype != ARC_add2 - && insn.itype != ARC_add - || has_cond(insn) - || !is_equal(insn.Op1, rA) ) - { - return false; - } - - ea_t elbase; - const op_t *op_var; - if ( insn.Op2.type == o_imm && optype_supported(insn.Op3) ) - { - elbase = insn.Op2.value; - elbase_offset_ea = insn.ea; - elbase_offset_n = 1; - op_var = &insn.Op3; - } - else if ( insn.itype == ARC_add - && insn.Op3.type == o_imm - && optype_supported(insn.Op2) ) - { - elbase = insn.Op3.value; - elbase_offset_ea = insn.ea; - elbase_offset_n = 2; - op_var = &insn.Op2; - } - else - { - ldr_value_info_t lvi; - if ( insn.Op2.type == o_reg - && optype_supported(insn.Op3) - && pm.find_ldr_value_ex(insn, insn.ea, insn.Op2.reg, &lvi, true) ) - { - op_var = &insn.Op3; - } - else if ( insn.itype == ARC_add - && insn.Op3.type == o_reg - && optype_supported(insn.Op2) - && pm.find_ldr_value_ex(insn, insn.ea, insn.Op3.reg, &lvi, true) ) - { - op_var = &insn.Op2; - } - else - { - return false; - } - elbase = lvi.value; - elbase_offset_ea = lvi.val_ea; - elbase_offset_n = lvi.n; - } - - si->set_elbase(elbase); - if ( insn.itype == ARC_add1 ) - si->set_shift(1); - else if ( insn.itype == ARC_add2 ) - si->set_shift(2); - trackop(*op_var, rA); - return true; -} - -//---------------------------------------------------------------------- -// ldb.x rA, [rJumps,rA'] -// ldb.x rA, [rA',rJumps] -// ldw.as rA, [rJumps,rA'] -// ldw.x rA, [rA',rJumps] -// ld.x.as rA, [#jumps,rA'] -// ldb rA, [rA',#jumps] -bool arc_jump_pattern_t::jpi2() -{ - if ( insn.itype != ARC_ld - || insn.Op2.type != o_displ && insn.Op2.type != o_phrase - || !is_equal(insn.Op1, rA) ) - { - return false; - } - - int elsize; - switch ( insn.auxpref & aux_zmask ) - { - case aux_b: - elsize = 1; - break; - case aux_w: - elsize = 2; - break; - case aux_l: - elsize = 4; - break; - default: - return false; - } - - int reg_var = -1; - - // do we have scaled load? - switch ( insn.auxpref & aux_amask ) - { - case aux_anone: - if ( elsize != 1 ) - { - //check for preceding scale instruction - //2: asl r12, r1 (shift by one) - //4: asl r12, r1, 2 - insn_t prev; - if ( decode_prev_insn(&prev, insn.ea) != BADADDR - && prev.itype == ARC_asl - && is_equal(prev.Op1, rA) ) - { - if ( elsize == 2 && prev.Op3.type == o_void - || elsize == 2 && prev.Op3.type == o_imm && prev.Op3.value == 2 ) - { - reg_var = prev.Op2.reg; - break; - } - } - return false; - - } - break; - case aux_as: - //nothing to do, index is scaled during load - break; - default: - //writeback or pre-increment: not valid here - return false; - } - - const op_t &x = insn.Op2; - ea_t jumps; - if ( x.type == o_phrase ) - { - ldr_value_info_t lvi; - if ( reg_var == -1 ) - { - if ( pm.find_ldr_value_ex(insn, insn.ea, x.phrase, &lvi, true) ) - { - reg_var = x.secreg; - } - else if ( elsize == 1 - && pm.find_ldr_value_ex(insn, insn.ea, x.secreg, &lvi, true) ) - { - reg_var = x.phrase; - } - else - { - return false; - } - } - jumps = lvi.value; - jumps_offset_ea = lvi.val_ea; - jumps_offset_n = lvi.n; - } - // x.type == o_displ - else if ( x.type == o_displ ) - { - if ( reg_var == -1 ) - { - if ( x.membase != 1 && elsize != 1 ) - return false; - reg_var = x.phrase; - } - jumps = x.addr; - jumps_offset_ea = insn.ea; - jumps_offset_n = 1; - } - else - { - return false; - } - - si->jumps = jumps; - si->set_jtable_element_size(elsize); - if ( (insn.auxpref & aux_x) != 0 ) - si->flags |= SWI_SIGNED; - track(reg_var, rA, dt_dword); - return true; -} - -//---------------------------------------------------------------------- -// cmp followed by the conditional jump or 'brhi/lo' -bool arc_jump_pattern_t::jpi3() -{ - // var should not be spoiled - QASSERT(10312, !is_spoiled(rA)); - - const op_t *op_var; - if ( !jpi_cmp_jump(&op_var) - && (jpi_condjump() // continue matching if found - || is_spoiled(rC) - || !jpi_cmp_ncases(&op_var)) ) - { - return false; - } - op_t &op = regs[rC]; - // assert: op.type == o_condjump - if ( (op.value & cc_inc_ncases) != 0 ) - ++si->ncases; - si->defjump = op.specval; - si->set_expr(op_var->reg, op_var->dtype); - return true; -} - -//---------------------------------------------------------------------- -// sub rA, rA', #minv -bool arc_jump_pattern_t::jpi4() -{ - if ( insn.itype != ARC_sub - || has_cond(insn) - || insn.Op3.type != o_imm - || !is_equal(insn.Op1, rA) ) - { - return false; - } - si->lowcase = insn.Op3.value; - return true; -} - -//------------------------------------------------------------------------- -bool arc_jump_pattern_t::finish() -{ - if ( !skip[2] ) - { - if ( eas[ELBASE_NJPI] != BADADDR && elbase_offset_ea != BADADDR ) - op_offset(elbase_offset_ea, elbase_offset_n, REF_OFF32); - if ( jumps_offset_ea != BADADDR ) - op_offset(jumps_offset_ea, jumps_offset_n, REF_OFF32); - } - return true; -} - -//------------------------------------------------------------------------- -// brhs rA, #size, default -// brlo #size, rA, default -// brlo rA, #size, body -// brhs #size, rA, body -bool arc_jump_pattern_t::jpi_cmp_jump(const op_t **op_var) -{ - if ( insn.itype != ARC_br - || insn.Op3.type != o_near - || !has_core_cond(insn) ) - { - return false; - } - cond_t cond = get_core_cond(insn); - if ( cond != cLO && cond != cHS ) - return false; - uval_t size; - if ( insn.Op1.type == o_reg && insn.Op2.type == o_imm ) - { - *op_var = &insn.Op1; - size = insn.Op2.value; - } - else if ( insn.Op1.type == o_imm && insn.Op2.type == o_reg ) - { - cond = invert_cond(cond); - *op_var = &insn.Op2; - size = insn.Op1.value; - } - else - { - return false; - } - if ( !analyze_cond(cond, to_ea(insn.cs, insn.Op3.addr)) ) - return false; - si->ncases = ushort(size); - trackop(**op_var, rA); - return true; -} - -//------------------------------------------------------------------------- -// bhi default | bls body with optional 'b default' -bool arc_jump_pattern_t::jpi_condjump() -{ - if ( insn.itype != ARC_b - || insn.Op1.type != o_near - || !has_core_cond(insn) ) - { - return false; - } - return analyze_cond(get_core_cond(insn), to_ea(insn.cs, insn.Op1.addr)); -} - -//------------------------------------------------------------------------- -// cmp rA, #size -bool arc_jump_pattern_t::jpi_cmp_ncases(const op_t **op_var) -{ - // assert: !is_spoiled(rA) because rA is non spoiled register - if ( insn.itype != ARC_cmp - || has_cond(insn) - || insn.Op2.type != o_imm - || !same_value(insn.Op1, rA) ) - { - return false; - } - si->ncases = ushort(insn.Op2.value); - // continue to track rA - *op_var = &insn.Op1; - return true; -} - -//------------------------------------------------------------------------- -// prepare and track rC -bool arc_jump_pattern_t::analyze_cond(cond_t cond, ea_t jump) -{ - op_t op; - op.type = o_condjump; - op.value = 0; - switch ( cond ) - { - case cHI: // higher - case cLS: // lower or same - case cGT: - case cLE: - op.value |= cc_inc_ncases; - break; - case cLO: // lower - case cHS: // higher or same - case cLT: - case cGE: - break; - default: - return false; - } - - switch ( cond ) - { - case cHI: // higher - case cHS: // higher or same - case cGT: - case cGE: - op.specval = jump; - break; - case cLO: // lower - case cLS: // lower or same - case cLT: - case cLE: - // we have conditional jump to the switch body - { - ea_t body = eas[BODY_NJPI]; - // assert: body != BADADDR - if ( jump > body ) - return false; - op.specval = insn.ea + insn.size; - - // possibly followed by 'b default' - insn_t dflt; - if ( decode_insn(&dflt, op.specval) > 0 - && dflt.itype == ARC_b - && !has_cond(insn) - && !has_dslot(insn) - && dflt.Op1.type == o_near ) - { - op.specval = to_ea(dflt.cs, dflt.Op1.addr); - } - } - break; - default: - return false; - } - op.addr = insn.ea; - trackop(op, rC); - return true; -} - -//---------------------------------------------------------------------- -static int is_jump_pattern(switch_info_t *si, const insn_t &insn, procmod_t *pm) -{ - arc_jump_pattern_t jp(pm, si); - if ( !jp.match(insn) || !jp.finish() ) - return JT_NONE; - return JT_SWITCH; -} - -//---------------------------------------------------------------------- -bool arc_is_switch(switch_info_t *si, const insn_t &insn) -{ - if ( insn.itype != ARC_j - && insn.itype != ARC_bi - && insn.itype != ARC_bih ) - return false; - - static is_pattern_t *const patterns[] = - { - is_jump_pattern, - }; - return check_for_table_jump(si, insn, patterns, qnumber(patterns)); -} - -//---------------------------------------------------------------------- -// Trace the value of the SP and create an SP change point if the current -// instruction modifies the SP. -sval_t arc_t::calc_sp_delta(const insn_t &insn) -{ - if ( has_cond(insn) ) // trace only unconditional instructions - return 0; // conditional instructions may be - // corrected manually - switch ( insn.itype ) - { - case ARC_add: - case ARC_sub: - if ( insn.Op1.is_reg(SP) && insn.Op2.is_reg(SP) ) - { - // add sp, sp, #imm - // add sp, sp, r1 - uval_t spofs; - if ( find_op_value(insn, insn.Op3, &spofs, NULL, false) && (spofs & 3) == 0 ) - return insn.itype == ARC_sub ? -spofs : spofs; - } - break; - case ARC_push: // push [reg] - return -4; - case ARC_pop: // pop [reg] - return +4; - case ARC_ld: // ld.ab fp, [sp,4] - case ARC_st: // st.a fp, [sp,-4] - if ( insn.Op2.type == o_displ - && insn.Op2.reg == SP - && ((insn.auxpref & aux_amask) == aux_a || (insn.auxpref & aux_amask) == aux_ab) ) - { - if ( (insn.Op2.addr & 3) == 0 ) - return insn.Op2.addr; - } - break; - case ARC_bl: // bl __ac_push_13_to_NN: push 13..NN - case ARC_b: // b __ac_pop_13_to_NN: pop 13..NN,blink - { - ea_t call_ea = to_ea(insn.cs, insn.Op1.addr); - sval_t delta; - if ( is_millicode(call_ea, &delta) ) - { - if ( delta == BADADDR ) - break; - return delta; - } - } - break; - case ARC_enter: - case ARC_leave: - { - sval_t nregs = insn.Op1.reglist & REGLIST_REGS; - nregs += (insn.Op1.reglist & REGLIST_FP) != 0; - nregs += (insn.Op1.reglist & REGLIST_BLINK) != 0; - - return 4 * (insn.itype == ARC_enter ? -nregs : nregs); - } - default: - if ( insn.Op1.is_reg(SP) && insn.itype != ARC_mov ) - { - // msg("??? illegal access mode sp @ %a\n", insn.ea); - } - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// Add a SP change point. We assume that SP is always divisible by 4 -inline void add_stkpnt(const insn_t &insn, func_t *pfn, sval_t v) -{ - add_auto_stkpnt(pfn, insn.ea+insn.size, v); -} - -//---------------------------------------------------------------------- -// Trace the value of the SP and create an SP change point if the current -// instruction modifies the SP. -void arc_t::trace_sp(const insn_t &insn) -{ - func_t *pfn = get_func(insn.ea); - if ( pfn == NULL ) - return; // no function -> we don't care about SP - - sval_t delta = calc_sp_delta(insn); - if ( delta != 0 ) - add_stkpnt(insn, pfn, delta); -} - -//---------------------------------------------------------------------- -bool arc_t::arc_calc_spdelta(sval_t *spdelta, const insn_t &insn) -{ - *spdelta = calc_sp_delta(insn); - return true; -} - -//-------------------------------------------------------------------------- -// is the input file object file? -// in such files, the references will be fixed up by the linker -static bool is_object_file(void) -{ - // Currently we know only about ELF relocatable files - if ( inf_get_filetype() == f_ELF ) - { - char buf[MAXSTR]; - if ( get_file_type_name(buf, sizeof(buf)) > 0 - && stristr(buf, "reloc") != NULL ) // ELF (Relocatable) - { - return true; - } - } - - return false; -} - -//-------------------------------------------------------------------------- -// force the offset by the calculated base -void arc_t::force_offset( - ea_t ea, - int n, - ea_t base, - bool issub, - int scale) -{ - if ( !is_off(get_flags(ea), n) - || !is_object_file() && get_offbase(ea, n) != base ) - { - refinfo_t ri; - - reftype_t reftype = REF_OFF32; - if ( scale == 2 ) - reftype = ref_arcsoh_id | REFINFO_CUSTOM; - else if ( scale == 4 ) - reftype = ref_arcsol_id | REFINFO_CUSTOM; - - ri.init(reftype|REFINFO_NOBASE|(issub ? REFINFO_SUBTRACT : 0), base); - op_offset_ex(ea, n, &ri); - } -} - -//-------------------------------------------------------------------------- -// add resolved target address, to be displayed as a comment -inline void arc_t::add_dxref(const insn_t &insn, ea_t target) -{ - // only add it if the comment would not be displayed otherwise - // ASCII xrefs show up as comments - if ( (inf_get_strlit_flags() & STRF_COMMENT) && is_strlit(get_flags(target)) ) - return; - - // repeatable comments follow xrefs - if ( get_cmt(NULL, target, true) > 0 ) - return; - - // demangled names show as comments - // FIXME: get rid of GN_INSNLOC -#define MY_GN_INSNLOC 0x0080 - if ( get_demangled_name(NULL, target, inf_get_short_demnames(), - DEMNAM_CMNT, GN_STRICT|MY_GN_INSNLOC) > 0 ) - return; - - set_dxref(insn.ea, target); -} - -//---------------------------------------------------------------------- -static bool is_good_target(ea_t ea) -{ - // address must exist - if ( !is_mapped(ea) ) - return false; - - flags_t F = get_flags(ea); - if ( !is_code(F) ) - return true; - - // don't point into middle of instructions - return !is_tail(F); -} - -//---------------------------------------------------------------------- -// Emulate an instruction -int arc_t::emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - - islast = Feature & CF_STOP; - - ea_t cmdend = insn.ea + insn.size; - - if ( helper.altval_ea(insn.ea, DSLOT_TAG) == 1 ) - islast = 1; // previous instruction was an unconditional jump/branch - - // you may emulate selected instructions with a greater care: - switch ( insn.itype ) - { - case ARC_j: - case ARC_b: - if ( !has_cond(insn) ) // branch always - islast = 1; - break; - case ARC_bi: - case ARC_bih: - islast = 1; - break; - case ARC_leave: - if ( (insn.Op1.reglist & REGLIST_PCL) != 0 ) // branch to blink - islast = 1; - break; - case ARC_add: // add r1, r2, #imm - case ARC_sub: // sub r1, r2, #imm - if ( (idpflags & ARC_TRACKREGS) != 0 - && insn.Op1.type == o_reg - && !is_stkptr(insn, insn.Op2.reg) - && !is_defarg(get_flags(insn.ea), 2) ) - { - bool issub = insn.itype == ARC_sub; - ea_t val1 = BADADDR; - if ( find_op_value(insn, insn.Op2, &val1) && val1 != 0 ) - { - if ( insn.Op3.type == o_imm && insn.Op3.value > 3 && is_good_target(val1 + insn.Op3.value) ) - { - force_offset(insn.ea, 2, val1, issub); - } - else if ( insn.Op2.reg != insn.Op3.reg ) - { - // mov r12, #imm - // sub r3, r15, r12 - ldr_value_info_t lvi; - if ( find_op_value_ex(insn, insn.Op3, &lvi, false) && lvi.value > 3 ) - { - ea_t target = issub ? (val1 - lvi.value) : (val1 + lvi.value); - if ( is_good_target(target) ) - { - force_offset(lvi.val_ea, lvi.n, val1, issub); - add_dxref(insn, target & 0xFFFFFFFF); - } - } - } - } - } - break; - case ARC_ld: // ld r1, [r2, #imm] - case ARC_st: // st r1, [r2, #imm] - if ( (idpflags & ARC_TRACKREGS) != 0 - && insn.Op2.type == o_displ - && !is_stkptr(insn, insn.Op2.reg) - && !is_defarg(get_flags(insn.ea), 1) ) - { - ea_t val1 = BADADDR; - if ( insn.Op2.addr > 3 && find_ldr_value(insn, insn.ea, insn.Op2.reg, &val1) && val1 != 0 ) - { - if ( (insn.auxpref & aux_amask) == aux_ab ) // post-increment - val1 -= insn.Op2.addr; - if ( is_good_target(val1 + insn.Op2.addr) ) - force_offset(insn.ea, 1, val1, false, get_scale_factor(insn)); - } - } - break; - } - - // trace the stack pointer if: - // - it is the second analysis pass - // - the stack pointer tracing is allowed - if ( may_trace_sp() ) - { - if ( !islast ) - trace_sp(insn); // trace modification of SP register - else - recalc_spd(insn.ea); // recalculate SP register for the next insn - } - - for ( int i = 0; i < PROC_MAXOP; ++i ) - { - if ( has_cf_use(Feature, i) ) - handle_operand(insn, insn.ops[i], true); - } - - for ( int i = 0; i < PROC_MAXOP; ++i ) - { - if ( has_cf_chg(Feature, i) ) - handle_operand(insn, insn.ops[i], false); - } - - // if the execution flow is not stopped here, then create - // a xref to the next instruction. - // Thus we plan to analyze the next instruction. - - if ( !islast || has_dslot(insn) ) - add_cref(insn.ea, cmdend, fl_F); - else if ( get_auto_state() == AU_USED ) - recalc_spd(insn.ea); - - if ( has_dslot(insn) ) - { - // mark the following address as a delay slot - int slotkind; - if ( insn.itype == ARC_bl || insn.itype == ARC_jl ) - slotkind = 3; - else - slotkind = islast ? 1 : 2; - helper.altset_ea(cmdend, slotkind, DSLOT_TAG); - } - else - { - helper.altdel_ea(cmdend, DSLOT_TAG); - } - return 1; // actually the return value is unimportant, but let's it be so -} - -//---------------------------------------------------------------------- -bool idaapi create_func_frame(func_t * pfn) -{ - ea_t ea = pfn->start_ea; - - insn_t insn; - for ( int i = 0; i < 10 && ea < pfn->end_ea; i++ ) - { - if ( !decode_insn(&insn, ea) ) - break; - // move fp, sp - // enter_s [...,fp,...] - if ( insn.itype == ARC_mov - && insn.Op1.is_reg(FP) - && insn.Op2.is_reg(SP) - || insn.itype == ARC_enter - && (insn.Op1.reglist & REGLIST_FP) != 0 ) - { - pfn->flags |= FUNC_FRAME; - update_func(pfn); - } - // sub sp, sp - if ( insn.itype == ARC_sub - && insn.Op1.is_reg(SP) - && insn.Op2.is_reg(SP) - && insn.Op3.type == o_imm ) - { - return add_frame(pfn, insn.Op3.value, 0, 0); - } - ea += insn.size; - } - return 0; -} - -//---------------------------------------------------------------------- -int idaapi is_sp_based(const insn_t &insn, const op_t & x) -{ - int flag = OP_FP_BASED; - if ( x.type == o_displ && x.reg == SP - || (x.type == o_imm && x.n == 2 && insn.itype == ARC_add && !insn.Op2.is_reg(FP)) ) - { - // add rx, sp, #imm - flag = OP_SP_BASED; - } - return OP_SP_ADD | flag; -} - -//---------------------------------------------------------------------- -int idaapi arc_get_frame_retsize(const func_t * /*pfn */ ) -{ - return 0; -} - -// #processor_t.is_align_insn -//---------------------------------------------------------------------- -// Is the instruction created only for alignment purposes? -// returns: number of bytes in the instruction -int arc_t::is_align_insn(ea_t ea) const -{ - if ( ptype == prc_arcompact ) - { - if ( (ea & 3) != 0 ) - return 0; - if ( get_word(ea) == 0x78E0 ) // nop_s - return 2; - if ( get_word(ea) == 0x264A && get_word(ea+2) == 0x7000 ) // mov 0, 0 - return 4; - } - return 0; -} - -//---------------------------------------------------------------------- -static bool can_be_data(ea_t target) -{ - if ( (target & 3) == 0 ) - { - segment_t *seg = getseg(target); - if ( seg == NULL ) - return false; - if ( seg->start_ea == target ) - return true; - ea_t prev = prev_head(target, seg->start_ea); - if ( prev != BADADDR && is_data(get_flags(prev)) ) - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// we have a possible reference from current instruction to 'target' -// check if we should make it an offset -bool arc_t::good_target(const insn_t &insn, ea_t target) const -{ - if ( target <= ' ' ) - return false; - - // check if it points to code - flags_t F = get_flags(target&~1); - if ( is_code(F) ) - { - // arcompact code references should have bit 0 set - if ( ptype == prc_arcompact && ((target & 1) == 0) ) - return false; - - // arc4 should be word-aligned - if ( ptype == prc_arc && ((target & 3) != 0) ) - return false; - - if ( !is_head(F) ) // middle of instruction? - return false; - - // if we're referencing middle of a function, it should be the same function - func_t *pfn = get_func(target); - if ( pfn == NULL && is_flow(F) ) - return false; - if ( pfn != NULL && pfn->start_ea != target && !func_contains(pfn, insn.ea) ) - return false; - - return true; - } - else if ( is_data(F) || segtype(target) == SEG_DATA || can_be_data(target) ) - { - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// returns target address -bool arc_t::copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, void *value, bool force) const -{ - flags_t F = get_flags(ea); - flags_t iflag = get_flags(insn.ea); - if ( is_dword(F) && x.dtype == dt_dword - || is_word(F) && x.dtype == dt_word - || is_byte(F) && x.dtype == dt_byte - || is_float(F) && x.dtype == dt_float - || is_double(F) && x.dtype == dt_double ) - { - if ( force || is_defarg(F, 0) && is_defarg(iflag, x.n) ) - { - // both are defined - check that the data types are the same - // if not, copy insntype -> dwordtype - flags_t fd = get_optype_flags0(F); - flags_t fi = get_optype_flags0(x.n ? (iflag>>4) : iflag); - if ( fd != fi ) - { - F = (F ^ fd) | fi; - opinfo_t ti; - get_opinfo(&ti, insn.ea, x.n, iflag); - set_opinfo(ea, 0, F, &ti); - set_op_type(ea, F, 0); - plan_ea(insn.ea); - plan_ea(ea); - } - } - if ( x.dtype == dt_dword ) - { - if ( !is_defarg(F, 0) || (is_off(F, 0) && get_offbase(ea, 0) == to_ea(insn.cs, 0)) ) - { - uint32 pcval = get_dword(ea); - ea_t target = to_ea(insn.cs, pcval); - // if the data is a 32-bit value which can be interpreted as an address - // then convert it to an offset expression - if ( get_auto_state() == AU_USED - // && (inf.af & AF_DATOFF) != 0 - // && target > ' ' - && good_target(insn, target) ) - { - if ( !is_defarg(F, 0) ) - op_plain_offset(ea, 0, to_ea(insn.cs, 0)); - if ( !is_defarg(get_flags(insn.ea), x.n) ) - { - op_plain_offset(insn.ea, x.n, to_ea(insn.cs, 0)); - } - } - // add xref from "LDR Rx,=addr" to addr. - if ( is_off(F, 0) ) - { - // NB: insn_t::add_dref uses insn.ea to calculate the target - // of a reloc so we can't use it here - ea_t newto = get_name_base_ea(ea, target); - dref_t type = dr_O; - if ( newto != target ) - { - type = dref_t(type | XREF_TAIL); - target = newto; - } - add_dref(insn.ea, target, type); - // helper.altdel_ea(ea, DELAY_TAG); - } - else - { - // analyze later for a possible offset - // helper.altset_ea(ea, 1, DELAY_TAG); - } - } - } - if ( value != NULL ) - { - switch ( x.dtype ) - { - case dt_dword: - *(uint32*)value = get_dword(ea); - break; - case dt_word: - *(uint16*)value = get_word(ea); - break; - case dt_byte: - *(uint8*)value = get_byte(ea); - break; - case dt_float: - *(uint32*)value = 0; - get_bytes(value, 4, ea); - break; - case dt_double: - *(uint64*)value = 0; - get_bytes(value, 8, ea); - break; - } - } - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -// Is the current instruction "return"? (conditional or not) -bool is_arc_return_insn(const insn_t &insn) -{ - switch ( insn.itype ) - { - case ARC_j: - // j blink (A4) or j [blink] (compact) is a return - return insn.Op1.reg == BLINK; - case ARC_leave: - // leave [..,pcl,...] is a return - return insn.Op1.reglist & REGLIST_PCL; - } - return false; -} - -//-------------------------------------------------------------------------- -static const int rv_arc[] = { R0, R1, R2, R3, R4, R5, R6, R7, -1 }; - -int get_arc_fastcall_regs(const int **regs) -{ - *regs = rv_arc; - return qnumber(rv_arc) - 1; -} - -//---------------------------------------------------------------------- -static void add_argregs(argloc_t *argloc, int r, int nregs, int size, bool force_scattered) -{ - QASSERT(10306, size > (nregs-1) * 4); - QASSERT(10307, r + nregs < qnumber(rv_arc)); - if ( force_scattered || nregs >= 2 && size != 8 ) - { - scattered_aloc_t *scloc = new scattered_aloc_t; - int off = 0; - for ( int i = 0; i < nregs; ++i, ++r, off += 4 ) - { - argpart_t ®loc = scloc->push_back(); - regloc.off = off; - regloc.set_reg1(rv_arc[r]); - regloc.size = qmin(size, 4); - size -= 4; - } - argloc->consume_scattered(scloc); - } - else if ( size == 8 ) - { - argloc->set_reg2(rv_arc[r], rv_arc[r+1]); - } - else - { - argloc->set_reg1(rv_arc[r]); - } -} - -//------------------------------------------------------------------------- -bool calc_arc_retloc(argloc_t *retloc, const tinfo_t &tif, cm_t /*cc*/) -{ - if ( !tif.is_void() ) - { - int size = tif.get_size(); - int nregs = (size + 3) / 4; - if ( nregs >= qnumber(rv_arc) ) - return false; - add_argregs(retloc, 0, nregs, size, false); - } - debug_print_argloc(-1, *retloc, tif); - return true; -} - -//---------------------------------------------------------------------- -// note: currently we do not support partial allocation (when part of -// the argument is in a register and another part is on the stack) -// fixme, but how? we need a means of telling the kernel about partial allocations -static bool alloc_args(func_type_data_t *fti, int nfixed) -{ - if ( !calc_arc_retloc(&fti->retloc, fti->rettype, 0 /*fti->get_cc()*/) ) - return false; - - int r = 0; - int fr = 0; - const int NUMREGARGS = 8; - - // if function returns its value in the memory - size_t retsize = fti->rettype.get_size(); - if ( retsize != BADSIZE && retsize > 8 && !fti->rettype.is_floating() ) - r++; // R0 is used to point to the result - - sval_t spoff = 0; - for ( int i=0; i < fti->size(); i++ ) - { - size_t size; - uint32 align; - funcarg_t &fa = fti->at(i); - const tinfo_t &type = fa.type; - if ( type.empty() && i >= nfixed ) - { - size = fa.argloc.stkoff(); - align = size; - } - else - { - size = type.get_size(&align); - } - if ( size == BADSIZE ) - return false; - // XXX: does ARC ABI align 64-bit params? so far doesn't look like it - if ( size == 8 && align > 4 ) - align = 4; -#ifndef FP_ABI_HARD - qnotused(fr); -#else - // currently we support only soft fpu abi - // todo: add config option to switch between abis - if ( (size == 4 || size == 8 || size == 16) - && type.is_floating() ) - { - // use floating point registers - int fpr; - switch ( size ) - { - case 4: - fpr = S0 + fr; - fr++; - break; - case 8: - case 16: // we do not have Q.. registers yet - fr = align_up(fr, 2); - fpr = D0 + fr/2; - fr += 2; - break; - } - if ( fr > 16 ) - goto ALLOC_ON_STACK; // no more fpregs - fa.argloc.set_reg1(fpr); - debug_print_argloc(i, fa.argloc, fa.type); - continue; - } -#endif - size = align_up(size, 4); - // XXX: align regs to even pairs? - /*if ( align > 4 && r < NUMREGARGS ) - r = align_up(r, 2);*/ - if ( r < NUMREGARGS && size <= 16 ) - { - int nregs = (size+3) / 4; - int start_reg = r; - r += nregs; - if ( nregs == 1 ) - { - fa.argloc.set_reg1(rv_arc[start_reg]); - } - else if ( r <= NUMREGARGS ) - { - add_argregs(&fa.argloc, start_reg, nregs, size, false); - } - else - { // part of the argument is passed on the stack: mixed scattered - int nr = NUMREGARGS - start_reg; - add_argregs(&fa.argloc, start_reg, nr, nr * 4, true); - scattered_aloc_t &scloc = fa.argloc.scattered(); - argpart_t &stkloc = scloc.push_back(); - stkloc.off = nr * 4; - stkloc.size = size - stkloc.off; - stkloc.set_stkoff(0); - spoff += align_up(stkloc.size, 4); - } - } - else - { -// ALLOC_ON_STACK: - if ( align > 4 ) - spoff = align_up(spoff, 8); - fa.argloc.set_stkoff(spoff); - spoff += size; - } - debug_print_argloc(i, fa.argloc, fa.type); - } - fti->stkargs = spoff; - return true; -} - -//---------------------------------------------------------------------- -bool calc_arc_arglocs(func_type_data_t *fti) -{ - return alloc_args(fti, fti->size()); -} - -//------------------------------------------------------------------------- -bool calc_arc_varglocs( - func_type_data_t *fti, - regobjs_t * /*regargs*/, - int nfixed) -{ - return alloc_args(fti, nfixed); -} - -//------------------------------------------------------------------------- -// returns: -// -1: doesn't spoil anything -// -2: spoils everything -// >=0: the number of the spoiled register -int arc_t::spoils(const insn_t &insn, const uint32 *regs, int n) const -{ - if ( is_call_insn(insn) ) - return -2; - - for ( int i=0; i < n; i++ ) - if ( spoils(insn, regs[i]) ) - return i; - - return -1; -} - -//------------------------------------------------------------------------- -bool arc_t::arc_set_op_type( - const insn_t &insn, - const op_t &x, - const tinfo_t &tif, - const char *name, - eavec_t *visited) -{ - tinfo_t type = tif; - switch ( x.type ) - { - case o_imm: - if ( type.is_ptr() - && x.value != 0 - && !is_defarg(get_flags(insn.ea), x.n) ) - { - op_plain_offset(insn.ea, x.n, to_ea(insn.cs, 0)); - return true; - } - break; - case o_mem: - { - ea_t dea = to_ea(insn.cs, x.addr); - return apply_once_tinfo_and_name(dea, type, name); - } - case o_displ: - return apply_tinfo_to_stkarg(insn, x, x.addr, type, name); - case o_reg: - { - uint32 r = x.reg; - func_t *pfn = get_func(insn.ea); - if ( pfn == NULL ) - return false; - bool ok; - bool farref; - func_item_iterator_t fii; - insn_t insn1; - for ( ok=fii.set(pfn, insn.ea); - ok && (ok=fii.decode_preceding_insn(visited, &farref, &insn1)) != false; - ) - { - if ( visited->size() > 4096 ) - break; // decoded enough of it, abandon - if ( farref ) - continue; - switch ( insn1.itype ) - { - case ARC_mov: - case ARC_ld: - if ( insn1.Op1.reg != r ) - continue; - return arc_set_op_type(insn, insn1.Op2, type, name, visited); - case ARC_add: - case ARC_sub: - // SUB R3, R11, #-var_12C - // ADD R1, SP, #var_1C - if ( insn1.Op1.reg != r ) - continue; - if ( (issp(insn1.Op2) /*|| isfp(insn1.Op2)*/ ) - && insn1.Op3.type != o_void ) - { - if ( remove_tinfo_pointer(&type, &name) ) - return apply_tinfo_to_stkarg(insn, insn1.Op3, insn1.Op3.value, type, name); - } - // no break - default: - { - int code = spoils(insn, &r, 1); - if ( code == -1 ) - continue; - } - break; - } - break; - } - } - break; - } - return false; -} - -//------------------------------------------------------------------------- -int arc_t::use_arc_regarg_type(ea_t ea, const funcargvec_t &rargs) -{ - int idx = -1; - insn_t insn; - if ( decode_insn(&insn, ea) ) - { - qvector<uint32> regs; - int n = rargs.size(); - regs.resize(n); - for ( int i=0; i < n; i++ ) - regs[i] = rargs[i].argloc.reg1(); - - idx = spoils(insn, regs.begin(), n); - if ( idx >= 0 ) - { - tinfo_t type = rargs[idx].type; - const char *name = rargs[idx].name.begin(); - switch ( insn.itype ) - { - - case ARC_add: // add r1, sp, #stkvar - case ARC_sub: // sub r1, r11, #0x15C - if ( (issp(insn.Op2) /*|| isfp(insn.Op2)*/) - && insn.Op3.type != o_void ) - if ( remove_tinfo_pointer(&type, &name) ) - apply_tinfo_to_stkarg(insn, insn.Op3, insn.Op3.value, type, name); - break; - case ARC_mov: - case ARC_ld: - { - eavec_t visited; - arc_set_op_type(insn, insn.Op2, type, name, &visited); - } - break; - default: // unknown instruction changed the register, stop tracing it - idx |= REG_SPOIL; - break; - } - } - } - return idx; -} - -//------------------------------------------------------------------------- -struct arc_argtinfo_helper_t : public argtinfo_helper_t -{ - arc_t ± - arc_argtinfo_helper_t(arc_t &_pm) : pm(_pm) {} - bool idaapi set_op_tinfo( - const insn_t &insn, - const op_t &x, - const tinfo_t &tif, - const char *name) override - { - eavec_t visited; - return pm.arc_set_op_type(insn, x, tif, name, &visited); - } - - // does the current instruction prepare a stack argument? - bool idaapi is_stkarg_load(const insn_t &insn, int *src, int *dst) override - { - if ( insn.itype == ARC_st && is_sp_based(insn, insn.Op2) ) - { - *src = 0; - *dst = 1; - return true; - } - return false; - } - - bool idaapi has_delay_slot(ea_t caller) override - { - insn_t insn; - return decode_insn(&insn, caller) != 0 - && pm.is_dslot(insn.ea+insn.size, true); - } -}; - -//------------------------------------------------------------------------- -void arc_t::use_arc_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs) -{ - arc_argtinfo_helper_t argtypes_helper(*this); - argtypes_helper.use_arg_tinfos(ea, fti, rargs); -} - -//---------------------------------------------------------------------- -// does the current instruction end a basic block? -bool arc_t::is_arc_basic_block_end( - const insn_t &insn, - bool call_insn_stops_block) -{ - // is this a delay slot of a branch? - if ( is_dslot(insn.ea, false) ) - return true; - - // do we flow into next instruction? - if ( !is_flow(get_flags(insn.ea+insn.size)) ) - return true; - - if ( is_call_insn(insn) ) - return call_insn_stops_block; - - // are there jump xrefs from here? - xrefblk_t xb; - bool has_jumps = false; - for ( bool ok=xb.first_from(insn.ea, XREF_FAR); ok && xb.iscode; ok=xb.next_from() ) - { - if ( xb.type == fl_JF || xb.type == fl_JN ) - { - has_jumps = true; - break; - } - } - - if ( has_jumps ) - { - // delayed jump does not end a basic block - return !has_dslot(insn); - } - return false; -} - -//---------------------------------------------------------------------- -void arc_t::del_insn_info(ea_t ea) -{ - // delete delay slot info - // NB: may not clobber cmd here! - nodeidx_t ndx = ea2node(ea); - helper.altdel(ndx, DSLOT_TAG); - if ( is_code(get_flags(ea)) ) - helper.altdel(ndx + get_item_size(ea), DSLOT_TAG); - del_callee(ea); - del_dxref(ea); -} - -//---------------------------------------------------------------------- -///< \param insn (const ::insn_t*) the instruction -///< \param state (int) autoanalysis phase -///< 0: creating functions -///< 1: creating chunks -///< \return probability 0..100 -int arc_t::arc_may_be_func(const insn_t &insn, int state) -{ - // don't add millicode thunks as chunks - if ( state == 1 && is_millicode(insn.ea) ) - return 100; - return 0; -} - -//====================================================================== -// millicode handling -//====================================================================== - -//---------------------------------------------------------------------- -void arc_t::rename_if_not_set(ea_t ea, const char *name) -{ - if ( renamed.find(ea) != renamed.end() ) - return; - - qstring curname; - if ( get_name(&curname, ea, GN_NOT_DUMMY) > 0 - && (is_uname(curname.c_str()) || curname.find(name) != qstring::npos) ) - return; - force_name(ea, name); -} - -//---------------------------------------------------------------------- -static int match_ac_pop_ld(const insn_t &insn) -{ - // ld rNN, [sp, #mm] - // mm = (NN-13)*4 - if ( ( insn.auxpref & aux_amask ) == aux_anone - && insn.Op1.type == o_reg - && insn.Op2.type == o_displ - && insn.Op2.reg == SP - && insn.Op2.membase == 0 - && ( insn.Op2.addr % 4 ) == 0 ) - { - int reg = insn.Op1.reg; - if ( reg == 13 + insn.Op2.addr / 4 ) - { - return reg; - } - } - // ld.ab r13, [sp, r13] - if ( ( insn.auxpref & aux_amask ) == aux_ab - && insn.Op1.is_reg(R13) - && insn.Op2.type == o_phrase - && insn.Op2.reg == SP - && insn.Op2.secreg == R13 ) - { - return 13; - } - // ld.ab blink, [sp, r12] - if ( ( insn.auxpref & aux_amask ) == aux_ab - && insn.Op1.is_reg(BLINK) - && insn.Op2.type == o_phrase - && insn.Op2.reg == SP - && insn.Op2.secreg == R12 ) - { - return BLINK; - } - return -1; - -} - -//---------------------------------------------------------------------- -bool arc_t::check_ac_pop_chain(int *regno, ea_t ea) -{ - //__ac_pop_26: - // ld gp, [sp, 0x34] - //__ac_pop_25: - // ld r25, [sp, 0x30] - // [..] - //__ac_pop_14: - // ld r14, [sp, 4] - // __ac_pop_13: - // ld.ab r13, [sp, r13] - // __ac_pop_blink: - // ld.ab blink, [sp, r12] - // j [blink] - insn_t insn; - bool ok = false; - if ( decode_insn(&insn, ea) > 0 ) - { - int reg = match_ac_pop_ld(insn); - if ( reg == BLINK ) - { - // j [blink] should follow - if ( decode_insn(&insn, insn.ea + insn.size) > 0 - && insn.itype == ARC_j - && insn.Op1.type == o_displ - && insn.Op1.reg == BLINK - && insn.Op1.addr == 0 ) - { - ok = true; - } - } - else if ( reg == R13 ) - { - int r2; - ok = check_ac_pop_chain(&r2, insn.ea + insn.size) && r2 == BLINK; - } - else if ( reg > R13 && reg <= R26 ) - { - // recurse to the lower addresses - int r2; - ok = check_ac_pop_chain(&r2, insn.ea + insn.size) && r2 == reg - 1; - } - if ( ok ) - { - qstring tmp; - if ( reg == BLINK ) - tmp = "__ac_pop_blink"; - else - tmp.sprnt("__ac_pop_%d", reg); - rename_if_not_set(ea, tmp.c_str()); - *regno = reg; - } - } - return ok; -} - -//---------------------------------------------------------------------- -static int match_ac_push_st(const insn_t &insn) -{ - // st.a rN, [sp,-4] - if ( insn.itype == ARC_st - && insn.auxpref == aux_a - && insn.Op2.type == o_displ - && insn.Op2.reg == SP - && insn.Op2.membase == 0 - && insn.Op2.addr == ea_t(-4) ) - { - return insn.Op1.reg; - } - return -1; -} - -//---------------------------------------------------------------------- -//__ac_mc_va: -// FC 1C 88 B1 st.a r6, [sp,-4] -// FC 1C 48 B1 st.a r5, [sp,-4] -// FC 1C 08 B1 st.a r4, [sp,-4] -// E1 C3 push r3 -// E1 C2 push r2 -// E1 C1 push r1 -// E1 C0 push r0 -// 07 C0 ld r0, [sp,0x1C] -// 1C 1C C0 31 st r7, [sp,0x1C] -// E1 C0 push r0 -// 01 C0 ld r0, [sp,4] | E0 7F j.d [blink] -// E0 7E j [blink] | 01 C0 ld r0, [sp,4] -static bool check_ac_mc_va(ea_t ea) -{ - // version with j.d - static const unsigned char sig_d[] = - { - 0xFC, 0x1C, 0x88, 0xB1, 0xFC, 0x1C, 0x48, 0xB1, 0xFC, 0x1C, - 0x08, 0xB1, 0xE1, 0xC3, 0xE1, 0xC2, 0xE1, 0xC1, 0xE1, 0xC0, - 0x07, 0xC0, 0x1C, 0x1C, 0xC0, 0x31, 0xE1, 0xC0, 0xE0, 0x7F, - 0x01, 0xC0 - }; - - //version with non-delayed j - static const unsigned char sig_nd[] = - { - 0xFC, 0x1C, 0x88, 0xB1, 0xFC, 0x1C, 0x48, 0xB1, 0xFC, 0x1C, - 0x08, 0xB1, 0xE1, 0xC3, 0xE1, 0xC2, 0xE1, 0xC1, 0xE1, 0xC0, - 0x07, 0xC0, 0x1C, 0x1C, 0xC0, 0x31, 0xE1, 0xC0, 0x01, 0xC0, - 0xE0, 0x7E - }; - - CASSERT(sizeof(sig_d) == sizeof(sig_nd)); - const int patlen = sizeof(sig_d); - uint8 buf[patlen]; - if ( get_bytes(buf, patlen, ea, GMB_READALL) == patlen ) - { - return memcmp(buf,sig_d, patlen) == 0 - || memcmp(buf,sig_nd, patlen) == 0; - } - return false; - -} -//---------------------------------------------------------------------- -static bool check_ac_push_chain(int *regno, ea_t ea) -{ - //__ac_push_13_to_26: - // st.a gp, [sp,-4] - //__ac_push_13_to_25: - // st.a r25, [sp,-4] - // [..] - // __ac_push_13_to_14: - // st.a r14, [sp,-4] - // __ac_push_13_to_13: - // j.d [blink] - // st.a r13, [sp,-4] - // VARIATION: - // __ac_push_13_to_13: - // st.a r13, [sp,-4] - // j [blink] - - insn_t insn; - bool ok = false; - int reg; - if ( decode_insn(&insn, ea) > 0 ) - { - if ( insn.itype == ARC_j - && insn.auxpref == aux_d - && insn.Op1.type == o_displ - && insn.Op1.reg == BLINK - && insn.Op1.addr == 0 ) - { - // j.d [blink] - // must be followed by st.a r13, [sp,-4] - if ( decode_insn(&insn, insn.ea + insn.size) > 0 - && match_ac_push_st(insn) == 13 ) - { - reg = 13; - ok = true; - } - } - else - { - // st.a rN, [sp,-4] - reg = match_ac_push_st(insn); - if ( reg == R13 ) - { - // j [blink] should follow - if ( decode_insn(&insn, insn.ea + insn.size) > 0 - && insn.itype == ARC_j - && insn.auxpref == 0 - && insn.Op1.type == o_displ - && insn.Op1.reg == BLINK - && insn.Op1.addr == 0 ) - { - ok = true; - } - } - if ( reg > R13 && reg <= R26 ) - { - // recurse to the lower addresses - int r2; - ok = check_ac_push_chain(&r2, insn.ea + insn.size) && r2 == reg - 1; - } - } - if ( ok ) - { - *regno = reg; - } - } - return ok; -} - -//---------------------------------------------------------------------- -bool arc_t::detect_millicode(qstring *mname, ea_t ea) -{ - // MetaWare arcompact millicode - // __ac_pop_13_to_26: - // mov r12, 4 - // __ac_pop_13_to_26v: - // mov r13, 0x38 - // b __ac_pop_26 - // [...] - // __ac_pop_13_to_13: - // mov r12, 4 - // __ac_pop_13_to_13v: - // mov r13, 4 - // b __ac_pop_13 - // __ac_pop_none: - // mov r12, 4 - // __ac_pop_nonev: - // b __ac_pop_blink - insn_t insn; - bool ok = false; - if ( decode_insn(&insn, ea) > 0 ) - { - if ( insn.itype == ARC_mov ) - { - if ( insn.Op1.is_reg(R13) && insn.Op2.type == o_imm && (insn.Op2.value % 4) == 0 ) - { - // mov r13, 0x38 - int regno = 12 + insn.Op2.value / 4; - if ( decode_insn(&insn, insn.ea + insn.size) > 0 && insn.itype == ARC_b && insn.Op1.type == o_near ) - { - // b __ac_pop_N - ea_t dest = insn.Op1.addr; - int regno2; - if ( check_ac_pop_chain(®no2, dest) && regno == regno2 ) - { - mname->sprnt("__ac_pop_13_to_%dv", regno); - ok = true; - } - } - } - else if ( insn.Op1.is_reg(R12) && insn.Op2.type == o_imm && insn.Op2.value == 4 ) - { - //mov r12, 4 - // check for fall through into __ac_pop_13_to_NNv - if ( detect_millicode(mname, insn.ea + insn.size) && mname->last() == 'v' ) - { - // erase the last 'v' - mname->resize(mname->length() - 1); - ok = true; - } - } - } - else if ( insn.itype == ARC_b && insn.Op1.type == o_near ) - { - // b __ac_pop_blink ? - int regno2; - if ( check_ac_pop_chain(®no2, insn.Op1.addr) && regno2 == BLINK ) - { - *mname = "__ac_pop_nonev"; - ok = true; - } - } - else if ( insn.itype == ARC_st ) - { - int reg; - if ( check_ac_push_chain(®, ea) ) - { - mname->sprnt("__ac_push_13_to_%d", reg); - ok = true; - } - else if ( check_ac_mc_va(ea) ) - { - *mname = "__ac_mc_va"; - ok = true; - } - } - } - if ( ok ) - { - rename_if_not_set(ea, mname->c_str()); - } - return ok; -} - -//---------------------------------------------------------------------- -static bool check_millicode_name(const qstring &name, ea_t ea, sval_t *spdelta) -{ - qstring cname; - if ( cleanup_name(&cname, ea, name.c_str(), CN_KEEP_TRAILING__DIGITS) ) - { - const char *p = cname.c_str(); - if ( streq(p, "ac_push_none") - || streq(p, "ac_pop_none") ) - { - *spdelta = 0; - return true; - } - else if ( streq(p, "ac_mc_va") ) - { - //pushes r0-r7 - *spdelta = -4*8; - return true; - } - else if ( streq(p, "ac_push_nonev") ) - { - //adjusts sp by r12 - *spdelta = BADADDR; - return true; - } - -#define SKIP_PREFIX(x) (strneq(p, x, strlen(x)) && (p+=strlen(x), true)) - if ( SKIP_PREFIX("ac_push_13_to_") ) - { - int reg = atoi(p); - if ( reg >= 13 && reg <= 26 ) - { - // pushes 13..reg - *spdelta = -4 * (reg-13+1); - return true; - } - } - else if ( SKIP_PREFIX("ac_pop_13_to_") ) - { - char *p2; - uint64 reg = strtoull(p, &p2, 10); - if ( reg >= 13 && reg <= 26 - && ( *p2 == '\0' || *p2 == 'v' || *p2 == '_' ) ) - { - // pops 13..reg - *spdelta = 4 * (reg - 12); - return true; - } - } - else if ( SKIP_PREFIX("prolog_save") ) - { - char *p2; - uint64 reg = strtoull(p, &p2, 10); - if ( ( reg == 0 || reg >= 13 && reg <= 26 ) - && ( *p2 == '\0' || strneq(p2, "_sub4", 5) || strneq(p2, "sp", 2) || strneq(p2, "sp_sub4", 7) ) ) - { - // different suffixes affect the fp value but sp remains unchanged - *spdelta = 0; - return true; - } - } - else if ( SKIP_PREFIX("epilog_load") - || SKIP_PREFIX("epilog_restore") ) - { - char *p2; - uint64 reg = strtoull(p, &p2, 10); - if ( ( reg == 0 || reg >= 13 && reg <= 26 ) - && ( *p2 == '\0' || strneq(p2, "_add4", 5) ) ) - { - // sp delta depends on r12 value - *spdelta = BADADDR; - return true; - } - } - else if ( SKIP_PREFIX("st_r13_to_r") ) - { - char *p2; - uint64 reg = strtoull(p, &p2, 10); - if ( reg >= 13 && reg <= 26 ) - { - *spdelta = 0; - return true; - } - } - else if ( SKIP_PREFIX("ld_r13_to_r") ) - { - char *p2; - uint64 reg = strtoull(p, &p2, 10); - if ( reg >= 13 && reg <= 26 ) - { - if ( *p2 == '\0' ) - { - *spdelta = 0; - return true; - } - else if ( strneq(p2, "_ret", 4) ) - { - // sp delta depends on r12 value - *spdelta = BADADDR; - return true; - } - } - } - } - return false; -} - -//---------------------------------------------------------------------- -bool arc_t::is_millicode(ea_t ea, sval_t *spdelta) -{ - //MetaWare arcompact names (N=13..26): - // __ac_push_13_to_N - // __ac_push_none - // __ac_pop_13_to_N - // __ac_pop_13_to_Nv - // __ac_pop_none - // __ac_pop_nonev - // __ac_mc_va - // MetaWare ARC4 names (N=0,13..26) - // __prolog_saveNsp_sub4 - // __prolog_saveN_sub4 - // __prolog_saveN - // __prolog_saveNsp - // __epilog_loadN - // __epilog_restoreN - // __epilog_loadN_add4 - // __epilog_restoreN_add4 - // __store_va - // GCC names (N=15..26) - // __st_r13_to_rN - // __ld_r13_to_rN - // N=14..26 - // __ld_r13_to_rN_ret - bool detected = false; - qstring name; - if ( get_name(&name, ea, GN_NOT_DUMMY) > 0 ) - { -CHECK_NAME: - sval_t tmp; - if ( check_millicode_name(name, ea, &tmp) ) - { - if ( spdelta != NULL ) - *spdelta = tmp; - return true; - } - if ( !detected ) - return false; - } - qstring mname; - if ( detect_millicode(&mname, ea) ) - { - if ( name.empty() ) - { - msg("%a: detected millicode thunk %s\n", ea, mname.c_str()); - force_name(ea, mname.c_str()); - } - else if ( is_uname(name.c_str()) && name.find(mname) == qstring::npos ) - { - msg("%a: detected millicode thunk %s but current name is %s, rename for better analysis\n", ea, mname.c_str(), name.c_str()); - } - name = mname; - detected = true; - goto CHECK_NAME; - } - return false; -} diff --git a/idasdk75/module/arc/ins.hpp b/idasdk75/module/arc/ins.hpp deleted file mode 100644 index aa4bd18..0000000 --- a/idasdk75/module/arc/ins.hpp +++ /dev/null @@ -1,387 +0,0 @@ - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INS_HPP -#define __INS_HPP - -extern instruc_t Instructions[]; - -enum nameNum -{ - - ARC_null = 0, // Unknown Operation - - ARC_ld, // Load - ARC_lr, // Load from auxiliary register - ARC_st, // Store - ARC_sr, // Store to auxiliary register - ARC_store_instructions = ARC_sr, - ARC_flag, // Set flags - ARC_asr, // Arithmetic shift right - ARC_lsr, // Logical shift right - ARC_sexb, // Sign extend byte - ARC_sexw, // Sign extend word - ARC_sexh = ARC_sexw, - ARC_extb, // Zero extend byte - ARC_extw, // Zero extend word - ARC_exth = ARC_extw, - ARC_ror, // Rotate right - ARC_rrc, // Rotate right through carry - ARC_b, // Branch - ARC_bl, // Branch and link - ARC_lp, // Zero-overhead loop setup - ARC_j, // Jump - ARC_jl, // Jump and link - ARC_add, // Add - ARC_adc, // Add with carry - ARC_sub, // Subtract - ARC_sbc, // Subtract with carry - ARC_and, // Logical bitwise AND - ARC_or, // Logical bitwise OR - ARC_bic, // Logical bitwise AND with invert - ARC_xor, // Logical bitwise exclusive-OR - - // pseudo instructions - ARC_mov, // Move - ARC_nop, // No operation - ARC_lsl, // Logical shift left - ARC_rlc, // Rotate left through carry - - // arc7 - ARC_brk, // Breakpoint - ARC_sleep, // Sleep until interrupt or restart - - // arc8 - ARC_swi, // Software interrupt - - // extra optional instrutions - ARC_asl, // Arithmetic shift left - ARC_mul64, // Signed 32x32 multiply - ARC_mulu64, // Unsigned 32x32 multiply - ARC_max, // Maximum of two signed integers - ARC_min, // Minimum of two signed integers - ARC_swap, // Exchange upper and lower 16 bits - ARC_norm, // Normalize (find-first-bit) - - // ARCompact instructions - ARC_bbit0, // Branch if bit cleared to 0 - ARC_bbit1, // Branch if bit set to 1 - ARC_br, // Branch on compare - ARC_pop, // Restore register value from stack - ARC_push, // Store register value on stack - - ARC_abs, // Absolute value - ARC_add1, // Add with left shift by 1 bit - ARC_add2, // Add with left shift by 2 bits - ARC_add3, // Add with left shift by 3 bits - ARC_bclr, // Clear specified bit (to 0) - ARC_bmsk, // Bit Mask - ARC_bset, // Set specified bit (to 1) - ARC_btst, // Test value of specified bit - ARC_bxor, // Bit XOR - ARC_cmp, // Compare - ARC_ex, // Atomic Exchange - ARC_mpy, // Signed 32x32 multiply (low) - ARC_mpyh, // Signed 32x32 multiply (high) - ARC_mpym = ARC_mpyh, - ARC_mpyhu, // Unsigned 32x32 multiply (high) - ARC_mpyhm = ARC_mpyhu, - ARC_mpyu, // Unsigned 32x32 multiply (low) - ARC_neg, // Negate - ARC_not, // Logical bit inversion - ARC_rcmp, // Reverse Compare - ARC_rsub, // Reverse Subtraction - ARC_rtie, // Return from Interrupt/Exception - ARC_sub1, // Subtract with left shift by 1 bit - ARC_sub2, // Subtract with left shift by 2 bits - ARC_sub3, // Subtract with left shift by 3 bits - ARC_sync, // Synchronize - ARC_trap, // Raise an exception - ARC_tst, // Test - ARC_unimp, // Unimplemented instruction - - ARC_abss, // Absolute and saturate - ARC_abssw, // Absolute and saturate of word - ARC_abssh = ARC_abssw, - ARC_adds, // Add and saturate - ARC_addsdw, // Add and saturate dual word - ARC_asls, // Arithmetic shift left and saturate - ARC_asrs, // Arithmetic shift right and saturate - ARC_divaw, // Division assist - ARC_negs, // Negate and saturate - ARC_negsw, // Negate and saturate of word - ARC_negsh = ARC_negsw, - ARC_normw, // Normalize to 16 bits - ARC_normh = ARC_normw, - ARC_rnd16, // Round to word - ARC_rndh = ARC_rnd16, - ARC_sat16, // Saturate to word - ARC_sath = ARC_sat16, - ARC_subs, // Subtract and saturate - ARC_subsdw, // Subtract and saturate dual word - - // mac d16 - ARC_muldw, - ARC_muludw, - ARC_mulrdw, - ARC_macdw, - ARC_macudw, - ARC_macrdw, - ARC_msubdw, - - // 32x16 MUL/MAC - ARC_mululw, - ARC_mullw, - ARC_mulflw, - ARC_maclw, - ARC_macflw, - ARC_machulw, - ARC_machlw, - ARC_machflw, - ARC_mulhlw, - ARC_mulhflw, - - // Major 6 compact insns - ARC_acm, - ARC_addqbs, - ARC_avgqb, - ARC_clamp, - ARC_daddh11, - ARC_daddh12, - ARC_daddh21, - ARC_daddh22, - ARC_dexcl1, - ARC_dexcl2, - ARC_dmulh11, - ARC_dmulh12, - ARC_dmulh21, - ARC_dmulh22, - ARC_dsubh11, - ARC_dsubh12, - ARC_dsubh21, - ARC_dsubh22, - ARC_drsubh11, - ARC_drsubh12, - ARC_drsubh21, - ARC_drsubh22, - ARC_fadd, - ARC_fsadd = ARC_fadd, - ARC_fmul, - ARC_fsmul = ARC_fmul, - ARC_fsub, - ARC_fssub = ARC_fsub, - ARC_fxtr, - ARC_iaddr, - ARC_mpyqb, - ARC_sfxtr, - ARC_pkqb, - ARC_upkqb, - ARC_xpkqb, - - // ARCv2 only major 4 instructions - ARC_mpyw, // Signed 16x16 multiply - ARC_mpyuw, // Unsigned 16x16 multiply - ARC_bi, // Branch indexed - ARC_bih, // Branch indexed half-word - ARC_ldi, // Load indexed - ARC_aex, // Exchange with auxiliary register - ARC_bmskn, // Bit mask negated - ARC_seteq, // Set if equal - ARC_setne, // Set if not equal - ARC_setlt, // Set if less than - ARC_setge, // Set if greater or equal - ARC_setlo, // Set if lower than - ARC_seths, // Set if higher or same - ARC_setle, // Set if less than or equal - ARC_setgt, // Set if greater than - - ARC_rol, // Rotate left - ARC_llock, // Load locked - ARC_scond, // Store conditional - - ARC_seti, // Set interrupt enable and priority level - ARC_clri, // Cler and get interrupt enable and priority level - - // ARCv2 compact prolog / epilog instructions - ARC_enter, // Function prologue sequence - ARC_leave, // Function epilogue sequence - - // ARCv2 32-bit extension major 5 DOP instructions - ARC_div, // Signed integer divsion - ARC_divu, // Unsigned integer divsion - ARC_rem, // Signed integer remainder - ARC_remu, // Unsigned integer remainder - ARC_asrsr, // Shift right rounding and saturating - ARC_valgn2h, // Two-way 16-bit vector align - ARC_setacc, // Set the accumulator - ARC_mac, // Signed 32x32 multiply accumulate - ARC_macu, // Unsigned 32x32 multiply accumulate - ARC_dmpyh, // Sum of dual signed 16x16 multiplication - ARC_dmpyhu, // Sum of dual unsigned 16x16 multiplication - ARC_dmach, // Dual signed 16x16 multiply accumulate - ARC_dmachu, // Dual unsigned 16x16 multiply accumulate - ARC_vadd2h, // Dual 16-bit addition - ARC_vadds2h, // Dual 16-bit saturating addition - ARC_vsub2h, // Dual 16-bit subtraction - ARC_vsubs2h, // Dual 16-bit saturating subtraction - ARC_vaddsub2h, // Dual 16-bit addition/subtraction - ARC_vaddsubs2h, // Dual 16-bit saturating addition/subtraction - ARC_vsubadd2h, // Dual 16-bit subtraction/addition - ARC_vsubadds2h, // Dual 16-bit saturating subtraction/addition - ARC_mpyd, // Signed 32x32 multiply (wide) - ARC_mpydu, // Unsigned 32x32 multiply (wide) - ARC_macd, // Signed 32x32 multiply accumulate (wide) - ARC_macdu, // Unsigned 32x32 multiply accumulate (wide) - ARC_vmpy2h, // Dual signed 16x16 multiply (wide) - ARC_vmpy2hf, // Dual 16x16 saturating fractional multiply - ARC_vmpy2hu, // Dual unsigned 16x16 multiply (wide) - ARC_vmpy2hfr, // Dual 16x16 saturating rounded fractional multiply - ARC_vmac2h, // Dual signed 16x16 multiply (wide) - ARC_vmac2hf, // Dual 16x16 saturating fractional multiply - ARC_vmac2hu, // Dual unsigned 16x16 multiply (wide) - ARC_vmac2hfr, // Dual 16x16 saturating rounded fractional multiply - ARC_vmpy2hwf, // Dual 16x16 saturating fractional multiply (wide) - ARC_vasl2h, // Dual 16-bit arithmetic shift left - ARC_vasls2h, // Dual 16-bit saturating arithmetic shift left - ARC_vasr2h, // Dual 16-bit arithmetic shift right - ARC_vasrs2h, // Dual 16-bit saturating arithmetic shift right - ARC_vlsr2h, // Dual 16-bit logical shift right - ARC_vasrsr2h, // Dual 16-bit saturating rounded arithmetic shift right - ARC_vadd4b, // Quad 8-bit addition - ARC_vmax2h, // Dual 16-bit maximum - ARC_vsub4b, // Quad 8-bit subtraction - ARC_vmin2h, // Dual 16-bit minimum - ARC_adcs, // Signed saturating addition with carry in - ARC_sbcs, // Signed saturating subtraction with carry in - ARC_dmpyhwf, // Fractional saturating sum of dual 16x16 signed fractional multiply - ARC_vpack2hl, // Compose lower 16-bits - ARC_vpack2hm, // Compose upper 16-bits - ARC_dmpyhf, // Saturating sum of dual 16x16 signed fractional multiply - ARC_dmpyhfr, // Saturating rounded sum of dual 16x16 signed fractional multiply - ARC_dmachf, // Saturating sum of dual 16x16 signed fractional multiply accumulate - ARC_dmachfr, // Saturating rounded sum of dual 16x16 signed fractional multiply accumulate - ARC_vperm, // Byte permutation with zero or sign extension - ARC_bspush, // Bitstream push - - // ARCv2 32-bit extension major 5 SOP instructions - ARC_swape, // Swap byte ordering - ARC_lsl16, // Logical shift left by 16 bits - ARC_lsr16, // Logical shift right by 16 bits - ARC_asr16, // Arithmetic shift right by 16 bits - ARC_asr8, // Arithmetic shift right by 8 bits - ARC_lsr8, // Logical shift right by 8 bits - ARC_lsl8, // Logical shift left by 8 bits - ARC_rol8, // Rotate left by 8 bits - ARC_ror8, // Rotate right by 8 bits - ARC_ffs, // Find first set bit - ARC_fls, // Find last set bit - - ARC_getacc, // Get accumulator - ARC_normacc, // Normalize accumulator - ARC_satf, // Saturate according to flags - ARC_vpack2hbl, // Pack lower bytes into lower 16 bits - ARC_vpack2hbm, // Pack upper bytes into upper 16 bits - ARC_vpack2hblf, // Pack upper bytes into lower 16 bits - ARC_vpack2hbmf, // Pack lower bytes into upper 16 bits - ARC_vext2bhlf, // Pack lower 2 bytes into upper byte of 16 bits each - ARC_vext2bhmf, // Pack upper 2 bytes into upper byte of 16 bits each - ARC_vrep2hl, // Repeat lower 16 bits - ARC_vrep2hm, // Repeat upper 16 bits - ARC_vext2bhl, // Pack lower 2 bytes into zero extended 16 bits - ARC_vext2bhm, // Pack upper 2 bytes into zero extended 16 bits - ARC_vsext2bhl, // Pack lower 2 bytes into sign extended 16 bits - ARC_vsext2bhm, // Pack upper 2 bytes into sign extended 16 bits - ARC_vabs2h, // Dual 16-bit absolute value - ARC_vabss2h, // Dual saturating 16-bit absolute value - ARC_vneg2h, // Dual 16-bit negation - ARC_vnegs2h, // Dual saturating 16-bit negation - ARC_vnorm2h, // Dual 16-bit normalization - ARC_bspeek, // Bitstream peek - ARC_bspop, // Bitstream pop - ARC_sqrt, // Integer square root - ARC_sqrtf, // Fractional square root - - // ARCv2 32-bit extension major 5 ZOP instructions - ARC_aslacc, // Arithmetic shift of accumulator - ARC_aslsacc, // Saturating arithmetic shift of accumulator - ARC_flagacc, // Copy accumulator flags to status32 register - ARC_modif, // Update address pointer - - // ARCv2 32-bit extension major 6 DOP instructions - ARC_cmpyhnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply - ARC_cmpyhfr, // Fractional 16+16 bit complex saturating rounded multiply - ARC_cmpychfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply - ARC_vmsub2hf, // Dual 16x16 saturating fractional multiply subtract - ARC_vmsub2hfr, // Dual 16x16 saturating rounded fractional multiply subtract - ARC_cmpychnfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply - ARC_cmachnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply accumulate - ARC_cmachfr, // Fractional 16+16 bit complex saturating rounded unshifted accumulate - ARC_cmacchnfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply accumulate - ARC_cmacchfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply accumulate - ARC_mpyf, // Signed 32-bit fractional saturating multiply - ARC_mpyfr, // Signed 32-bit fractional saturating rounded multiply - ARC_macf, // Signed 32-bit fractional saturating multiply accumulate - ARC_macfr, // Signed 32-bit fractional saturating rounded multiply accumulate - ARC_msubf, // Signed 32-bit fractional saturating multiply subtract - ARC_msubfr, // Signed 32-bit fractional saturating rounded multiply subtract - ARC_divf, // Signed 32-bit fractional division - ARC_vmac2hnfr, // Dual signed 16-bit fractional saturating rounded multiply accumulate - ARC_vmsub2hnfr, // Dual signed 16-bit fractional saturating rounded multiply subtract - ARC_mpydf, // Signed 32-bit fractional multiply (wide) - ARC_macdf, // Signed 32-bit fractional multiply accumulate (wide) - ARC_msubwhfl, // Signed 32 x 16 (lower) fractional saturating multiply subtract - ARC_msubdf, // Signed 32-bit fractional multiply subtract (wide) - ARC_dmpyhbl, // Dual 16x8 signed multiply with lower two bytes - ARC_dmpyhbm, // Dual 16x8 signed multiply with upper two bytes - ARC_dmachbl, // Dual 16x8 signed multiply accumulate with lower two bytes - ARC_dmachbm, // Dual 16x8 signed multiply accumulate with upper two bytes - ARC_msubwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply subtract - ARC_cmpyhfmr, // Fractional 16+16 bit complex x 16bit real (upper) saturating rounded multiply - ARC_cbflyhf0r, // Fractional 16+16 bit complex FFT butterfly, first half - ARC_mpywhl, // Signed 32 x 16 (lower) multiply - ARC_macwhl, // Signed 32 x 16 (lower) multiply accumulate - ARC_mpywhul, // Unsigned 32 x 16 (lower) multiply - ARC_macwhul, // Unsigned 32 x 16 (lower) multiply accumulate - ARC_mpywhfm, // Signed 32 x 16 (upper) fractional saturating multiply - ARC_mpywhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply - ARC_macwhfm, // Signed 32 x 16 (upper) fractional saturating multiply accumulate - ARC_macwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply accumulate - ARC_mpywhfl, // Signed 32 x 16 (lower) fractional saturating multiply - ARC_mpywhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply - ARC_macwhfl, // Signed 32 x 16 (lower) fractional saturating multiply accumulate - ARC_macwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply accumulate - ARC_macwhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply accumulate - ARC_macwhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply accumulate - ARC_mpywhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply - ARC_mpywhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply - ARC_msubwhfm, // Signed 32 x 16 (upper) fractional saturating multiply subtract - ARC_msubwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply subtract - - // ARCv2 32-bit extension major 6 SOP instructions - ARC_cbflyhf1r, // Fractional 16+16 bit complex FFT butterfly, second half - - // ARCv2 FPU instructions - ARC_fscmp, // Single precision floating point compare - ARC_fscmpf, // Single precision floating point compare (IEEE 754 flag generation) - ARC_fsmadd, // Single precision floating point fused multiply add - ARC_fsmsub, // Single precision floating point fused multiply subtract - ARC_fsdiv, // Single precision floating point division - ARC_fcvt32, // Single precision floating point / integer conversion - ARC_fssqrt, // Single precision floating point square root - - // ARCv2 jump / execute indexed instructions - ARC_jli, // Jump and link indexed - ARC_ei, // Execute indexed - - ARC_kflag, // Set kernel flags - ARC_wevt, // Enter sleep state - - ARC_last, -}; - -#endif diff --git a/idasdk75/module/arc/makefile b/idasdk75/module/arc/makefile deleted file mode 100644 index 6d9116a..0000000 --- a/idasdk75/module/arc/makefile +++ /dev/null @@ -1,47 +0,0 @@ -PROC=arc -CONFIGS=arc.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ana.cpp arc.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)jumptable.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp arc.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp arc.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp arc.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp arc.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/arc/out.cpp b/idasdk75/module/arc/out.cpp deleted file mode 100644 index beee0ac..0000000 --- a/idasdk75/module/arc/out.cpp +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su, ig@datarescue.com - * FIDO: 2:5020/209 - * - */ - -#include "arc.hpp" - -// generic condition codes -static const char *const ccode[] = -{ - "", ".z", ".nz", ".p", - ".n", ".c", ".nc", ".v", - ".nv", ".gt", ".ge", ".lt", - ".le", ".hi", ".ls", ".pnz", - ".ss", ".sc", ".c0x12", ".c0x13", - ".c0x14", ".c0x15", ".c0x16", ".c0x17", - ".c0x18", ".c0x19", ".c0x1A", ".c0x1B", - ".c0x1C", ".c0x1D", ".c0x1E", ".c0x1F", -}; - -// generic condition codes for ARCv2 -static const char *const ccode_v2[] = -{ - "", ".eq", ".ne", ".p", - ".n", ".c", ".nc", ".v", - ".nv", ".gt", ".ge", ".lt", - ".le", ".hi", ".ls", ".pnz", - ".c0x10", ".c0x11", ".c0x12", ".c0x13", - ".c0x14", ".c0x15", ".c0x16", ".c0x17", - ".c0x18", ".c0x19", ".c0x1A", ".c0x1B", - ".c0x1C", ".c0x1D", ".c0x1E", ".c0x1F", -}; - - -// condition codes for branches -static const char *const ccode_b[] = -{ - "", "eq", "ne", "pl", - "mi", "lo", "hs", "vs", - "vc", "gt", "ge", "lt", - "le", "hi", "ls", "pnz", - "ss", "sc", "c0x12", "c0x13", - "c0x14", "c0x15", "c0x16", "c0x17", - "c0x18", "c0x19", "c0x1A", "c0x1B", - "c0x1C", "c0x1D", "c0x1E", "c0x1F", -}; - -// condition codes for ARCv2 branches -static const char *const ccode_b_v2[] = -{ - "", "eq", "ne", "p", - "n", "lo", "hs", "v", - "nv", "gt", "ge", "lt", - "le", "hi", "ls", "pnz", - "c0x10", "c0x11", "c0x12", "c0x13", - "c0x14", "c0x15", "c0x16", "c0x17", - "c0x18", "c0x19", "c0x1A", "c0x1B", - "c0x1C", "c0x1D", "c0x1E", "c0x1F", -}; - - -/* jump delay slot codes */ -static const char ncode[][4] = { "", ".d", ".jd", ".d?" }; - -//---------------------------------------------------------------------- -class out_arc_t : public outctx_t -{ - out_arc_t(void) = delete; // not used - void set_gr_cmt(const char *cmt) { user_data = (void *)cmt; } - const char *get_gr_cmt(void) const { return (const char *)user_data; } -public: - void outreg(int rn); - - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); - void out_specreg(const ioports_t &table, uval_t n); - void out_aux(uval_t n) - { - arc_t &pm = *static_cast<arc_t *>(procmod); - out_specreg(pm.auxregs, n); - } -}; -CASSERT(sizeof(out_arc_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_arc_t) - -//---------------------------------------------------------------------- -void out_arc_t::outreg(int rn) -{ - const char *regname = (rn < ph.regs_num) ? ph.reg_names[rn] : "<bad register>"; - out_register(regname); -} - -//---------------------------------------------------------------------- -void out_arc_t::out_specreg(const ioports_t &table, uval_t n) -{ - const ioport_t *reg = find_ioport(table, n); - if ( reg == NULL ) - { - op_t x; - x.value = n; - x.dtype = dt_dword; - out_symbol('['); - out_value(x, OOFS_IFSIGN | OOFW_IMM); - out_symbol(']'); - } - else - { - out_register(reg->name.c_str()); - if ( !reg->cmt.empty() && !has_cmt(F) ) - set_gr_cmt(reg->cmt.c_str()); - } -} - -//---------------------------------------------------------------------- -/* outputs an operand 'x' */ -bool out_arc_t::out_operand(const op_t & x) -{ - arc_t &pm = *static_cast<arc_t *>(procmod); - ea_t v; - switch ( x.type ) - { - case o_reg: - outreg(x.reg); - break; - - case o_phrase: - { - int hidden_base = is_hidden_base_reg(x.reg); - if ( hidden_base != -1 ) - out_symbol('['); - if ( hidden_base == 0 ) - { - outreg(x.reg); - out_symbol(','); - } - outreg(x.secreg); - if ( hidden_base != -1 ) - out_symbol(']'); - } - break; - - case o_imm: - // check for: LR <dest>, [aux] - // SR <src>, [aux] - // don't use aux register if op type is set - if ( !is_defarg(F, x.n) - && ((insn.itype == ARC_lr && x.n == 1 ) - || (insn.itype == ARC_sr && x.n == 1 )) ) - out_aux(x.value); - else - out_value(x, OOFS_IFSIGN | OOFW_IMM); - break; - - case o_mem: - { - ea_t ea = to_ea(insn.cs, x.addr); - if ( (insn.auxpref & aux_pcload) != 0 ) - { - // A little hack to make the output - // more readable... - op_t y = {0}; //lint !e708 union initialization - if ( pm.copy_insn_optype(insn, x, ea, &y.value) ) - { - y.dtype = x.dtype; - y.flags = OF_SHOW; - out_symbol('='); - set_dlbind_opnd(); - ea_t insn_ea_sav = insn_ea; - flags_t savedF = F; - insn_ea = ea; // change context - F = get_flags(ea); - out_value(y, OOFS_IFSIGN|OOFW_IMM); - insn_ea = insn_ea_sav; // restore context - F = savedF; - break; - } - } - out_symbol('['); - if ( insn.itype != ARC_lr && insn.itype != ARC_sr ) - { - if ( !out_name_expr(x, ea, x.addr) ) - { - out_tagon(COLOR_ERROR); - out_btoa(uint32(x.addr), 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - } - else - { - out_btoa(uint32(x.addr), 16); - } - if ( x.immdisp != 0 ) - { - out_symbol('-'); - out_btoa(uint32(x.immdisp * get_scale_factor(insn)), 16); - out_symbol(','); - out_btoa(uint32(x.immdisp), 16); - } - out_symbol(']'); - } - break; - - case o_near: - v = to_ea(insn.cs, x.addr); - if ( !out_name_expr(x, v, x.addr) ) - { - out_value(x, OOF_ADDR|OOF_NUMBER|OOFS_NOSIGN|OOFW_32); - remember_problem(PR_NONAME, insn.ea); - break; - } - break; - - case o_displ: - { - // membase=0: [reg, #addr] - // membase=1: [#addr, reg] - int hidden_base = is_hidden_base_reg(x.reg); - if ( hidden_base != -1 ) - out_symbol('['); - if ( x.membase == 0 && hidden_base == 0 ) - outreg(x.reg); - if ( x.addr != 0 - || hidden_base != 0 - || is_off(F, x.n) - || is_stkvar(F, x.n) - || is_enum(F, x.n) - || is_stroff(F, x.n) ) - { - if ( x.membase == 0 && hidden_base == 0 ) - out_symbol(','); - out_value(x, OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED|OOFW_32); - if ( x.membase != 0 ) - out_symbol(','); - } - if ( x.membase != 0 ) - outreg(x.reg); - if ( hidden_base != -1 ) - out_symbol(']'); - } - break; - - case o_reglist: - { - out_symbol('{'); - bool need_comma = false; - int regs = x.reglist & REGLIST_REGS; - if ( regs > REGLISTR_MAX ) - { - out_tagon(COLOR_ERROR); - out_btoa(regs, 16); - out_tagoff(COLOR_ERROR); - need_comma = true; - } - else if ( regs > 0 ) - { - outreg(R13); - if ( regs > 1 ) - { - out_symbol('-'); - outreg(R13 + regs - 1); - } - need_comma = true; - } - if ( (x.reglist & REGLIST_FP) != 0 ) - { - if ( need_comma ) - out_symbol(','); - outreg(FP); - need_comma = true; - } - if ( (x.reglist & REGLIST_BLINK) != 0 ) - { - if ( need_comma ) - out_symbol(','); - outreg(BLINK); - need_comma = true; - } - if ( (x.reglist & REGLIST_PCL) != 0 ) - { - if ( need_comma ) - out_symbol(','); - outreg(PCL); - need_comma = true; - } - out_symbol('}'); - } - break; - - default: - out_symbol('?'); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -inline bool is_branch(const insn_t &insn) -{ - switch ( insn.itype ) - { - case ARC_b: - case ARC_lp: - case ARC_bl: - case ARC_j: - case ARC_jl: - case ARC_br: - case ARC_bbit0: - case ARC_bbit1: - return true; - } -#ifndef NDEBUG - // delay slot bits must be only set for branches - QASSERT(10184, !has_dslot(insn)); -#endif - return false; -} - -//---------------------------------------------------------------------- -void out_arc_t::out_proc_mnem(void) -{ - arc_t &pm = *static_cast<arc_t *>(procmod); - char postfix[MAXSTR]; - postfix[0] = '\0'; - if ( insn.itype == ARC_null ) - { - uint32 code = get_dword(insn.ea); - - int i = (code>>27)&31; - if ( i == 3 ) - { - int c = (code>>9)&63; - qsnprintf(postfix, sizeof(postfix), "ext%02X_%02X", i, c); - } - else - { - qsnprintf(postfix, sizeof(postfix), "ext%02X", i); - } - } - - /* if we have a load or store instruction, flags are used a bit different */ - if ( insn.itype <= ARC_store_instructions ) - { - switch ( insn.auxpref & aux_zmask ) - { - case 0: - break; - case aux_b: - qstrncat(postfix, "b", sizeof(postfix)); - break; - case aux_w: - qstrncat(postfix, pm.is_arcv2() ? "h" : "w", sizeof(postfix)); - break; - default: - qstrncat(postfix, "?", sizeof(postfix)); - break; - } - if ( (insn.auxpref & aux_s) != 0 ) - qstrncat(postfix, "_s", sizeof(postfix)); - if ( insn.auxpref & aux_x ) - qstrncat(postfix, ".x", sizeof(postfix)); - switch ( insn.auxpref & aux_amask ) - { - case 0: - break; - case aux_a: - qstrncat(postfix, ".a", sizeof(postfix)); - break; - case aux_as: - qstrncat(postfix, ".as", sizeof(postfix)); - break; - case aux_ab: - qstrncat(postfix, ".ab", sizeof(postfix)); - break; - default: - qstrncat(postfix, "?", sizeof(postfix)); - break; - } - if ( insn.auxpref & aux_di ) - qstrncat(postfix, ".di", sizeof(postfix)); - } - else - { - uint8 cond = insn.auxpref & aux_cmask; - if ( cond != cAL && is_branch(insn) ) - { - if ( pm.is_arcv2() ) - qstrncat(postfix, ccode_b_v2[cond], sizeof(postfix)); - else - qstrncat(postfix, ccode_b[cond], sizeof(postfix)); - } - - if ( (insn.auxpref & aux_s) != 0 ) - qstrncat(postfix, "_s", sizeof(postfix)); - - if ( cond != cAL && !is_branch(insn) ) - { - if ( pm.is_arcv2() ) - qstrncat(postfix, ccode_v2[cond], sizeof(postfix)); - else - qstrncat(postfix, ccode[cond], sizeof(postfix)); - } - } - if ( is_branch(insn) ) // delay slot code - qstrncat(postfix, ncode[(insn.auxpref >> 5) & 3], sizeof(postfix)); - else if ( (insn.auxpref & aux_f) != 0 ) - { - // for these load/store like instructions, the f bit is used for the .di - if ( insn.itype == ARC_ex - || insn.itype == ARC_llock - || insn.itype == ARC_scond ) - { - qstrncat(postfix, ".di", sizeof(postfix)); - } - else if ( insn.itype != ARC_flag // flag implicitly sets this bit - && insn.itype != ARC_rcmp ) // rcmp implicitly sets this bit - { - qstrncat(postfix, ".f", sizeof(postfix)); - } - } - - if ( pm.is_arcv2() && ( insn.auxpref & aux_bhint ) != 0 ) - { - // print static prediction hint - /* - from "Assembler Syntax for Static Branch Predictions" - The default static prediction, in the absence of any <.T> syntax, is always BTFN (Backwards Taken, Forwards Not Taken). - Therefore, a BRcc instruction always has the Y bit set to 0 by default, whereas a BBITn instruction always has the Y bit set to 1 - by default. - */ - bool backwards = insn.Op3.addr <= insn.ea; - const char *suf = NULL; - if ( insn.itype == ARC_br ) - suf = backwards ? ".t" : ".nt"; - else - suf = backwards ? ".nt" : ".t"; - qstrncat(postfix, suf, sizeof(postfix)); - } - - out_mnem(8, postfix); // output instruction mnemonics -} - -//---------------------------------------------------------------------- -void out_arc_t::out_insn(void) -{ - arc_t &pm = *static_cast<arc_t *>(procmod); - out_mnemonic(); - if ( insn.Op1.type != o_void ) - out_one_operand(0); // output the first operand - - for ( int i = 1; i < PROC_MAXOP; ++i ) - { - if ( insn.ops[i].type != o_void ) - { - if ( !(insn.ops[i].type == o_reg && insn.ops[i].regpair) ) - { - out_symbol(','); - out_char(' '); - } - out_one_operand(i); // output the current operand - } - } - - // output a character representation of the immediate values - // embedded in the instruction as comments - out_immchar_cmts(); - - // add comments for indirect calls or calculated data xrefs - nodeidx_t callee = pm.get_callee(insn.ea); - if ( callee == BADADDR ) - callee = pm.get_dxref(insn.ea); - if ( callee != BADADDR ) - set_comment_addr(callee & ~1); - const char *gr_cmt = get_gr_cmt(); - if ( gr_cmt != NULL ) - { - out_char(' '); - out_line(ash.cmnt, COLOR_AUTOCMT); - out_char(' '); - - out_line(gr_cmt, COLOR_AUTOCMT); - if ( ash.cmnt2 != NULL ) - { - out_char(' '); - out_line(ash.cmnt2, COLOR_AUTOCMT); - } - } - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -// generate start of the disassembly - -void idaapi arc_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX); -} - -//-------------------------------------------------------------------------- -// generate start of a segment -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Sarea) could be made const -void arc_t::arc_segstart(outctx_t &ctx, segment_t *Sarea) const -{ - qstring name; - get_visible_segm_name(&name, Sarea); - ctx.gen_printf(0, COLSTR(".section %s", SCOLOR_ASMDIR), name.c_str()); - if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) - { - adiff_t org = ctx.insn_ea - get_segm_base(Sarea); - - if ( org != 0 ) - { - char buf[MAX_NUMBUF]; - - btoa(buf, sizeof(buf), org); - ctx.gen_printf(0, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } - } -} - -//-------------------------------------------------------------------------- -// generate end of the disassembly -void idaapi arc_footer(outctx_t &ctx) -{ - ctx.gen_empty_line(); - - ctx.out_line(".end", COLOR_ASMDIR); - - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - ctx.out_line(" #"); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); -} diff --git a/idasdk75/module/arc/reg.cpp b/idasdk75/module/arc/reg.cpp deleted file mode 100644 index 870ad75..0000000 --- a/idasdk75/module/arc/reg.cpp +++ /dev/null @@ -1,896 +0,0 @@ - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * - * E-mail: ig@estar.msk.su, ig@datarescue.com - * FIDO: 2:5020/209 - * - */ - -#include "arc.hpp" -int data_id; - -//-------------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // 0 .. 7 - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", // 8 .. 15 - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", // 16 .. 23 - "r24", "r25", "gp", "fp", "sp", "ilink1", "ilink2", "blink", // 23 .. 31 - - "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", // 31 .. 39 - "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", // 40 .. 47 - "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", // 48 .. 55 - "r56", "mlo", "mmid", "mhi","lp_count", "r61", "<limm>", "pcl", // 56 .. 63 - // condition codes - "CF", "ZF", "NF", "VF", - - // registers used for indexed instructions - "next_pc", - "ldi_base", "jli_base", "ei_base", - - "gp_base", - - "cs", "ds" -}; - -static const uchar codeseq_arcompact[] = { 0xF1, 0xC0 }; // push blink -static const uchar codeseq_arctg4[] = { 0x04, 0x3E, 0x0E, 0x10 }; // st blink, [sp,4] - -static const bytes_t codestart_arcompact[] = -{ - { sizeof(codeseq_arcompact), codeseq_arcompact }, - { 0, NULL } -}; - -static const bytes_t codestart_arctg4[] = -{ - { sizeof(codeseq_arctg4), codeseq_arctg4 }, - { 0, NULL } -}; - -//---------------------------------------------------------------------- -void arc_t::set_codeseqs() const -{ - switch ( ptype ) - { - case prc_arc: - ph.codestart = codestart_arctg4; - break; - case prc_arcompact: - case prc_arcv2: - ph.codestart = codestart_arcompact; - break; - } -} - -//----------------------------------------------------------------------- -// new names for old instructions in ARCv2 -//lint -e{958} padding of 6 bytes needed to align member on a 8 byte boundary -struct instruc_alt_name_t -{ - uint16 itype; - const char *old_name; //ARCompact name - const char *new_name; //ARCv2 name -}; - -static const instruc_alt_name_t InstructionNamesARCv2[] = -{ - { ARC_mpyh, "mpyh", "mpym" }, - { ARC_mpyhu, "mpyhu", "mpymu" }, - { ARC_sexw, "sexw", "sexh" }, - { ARC_extw, "extw", "exth" }, - { ARC_sat16, "sat16", "sath" }, - { ARC_rnd16, "rnd16", "rndh" }, - { ARC_abssw, "abssw", "abssh" }, - { ARC_negsw, "negsw", "negsh" }, - { ARC_normw, "normw", "normh" }, - { ARC_fadd, "fadd", "fsadd" }, - { ARC_fmul, "fmul", "fsmul" }, - { ARC_fsub, "fsub", "fssub" }, -}; - -//---------------------------------------------------------------------- -// updates names in Instruction array to match the subtype -void arc_t::set_instruc_names() -{ - for ( int i = 0; i < qnumber(InstructionNamesARCv2); ++i ) - { - const instruc_alt_name_t &name = InstructionNamesARCv2[i]; - Instructions[name.itype].name = is_arcv2() ? name.new_name : name.old_name; - } -} - -//---------------------------------------------------------------------- -// updates affected global state after a ptype change -void arc_t::ptype_changed() -{ - set_codeseqs(); - set_instruc_names(); -} - -//-------------------------------------------------------------------------- -// handler for some IDB events -ssize_t idaapi pm_idb_listener_t::on_event(ssize_t notification_code, va_list va) -{ - switch ( notification_code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(-1, pm.idpflags); - break; - - case idb_event::op_type_changed: - // An operand type (offset, hex, etc...) has been set or deleted - { - ea_t ea = va_arg(va, ea_t); - int n = va_arg(va, int); - if ( n < UA_MAXOP && is_code(get_flags(ea)) ) - { - insn_t insn; - decode_insn(&insn, ea); - op_t &x = insn.ops[n]; - if ( x.type == o_mem ) - { - ea = to_ea(insn.cs, x.addr); - pm.copy_insn_optype(insn, x, ea, NULL, true); - } - } - } - break; - } - return 0; -} - -//----------------------------------------------------------------------- -// ASMI -//----------------------------------------------------------------------- -static const asm_t gnuas = -{ - AS_COLON | AS_N2CHR | AS_1TEXT | ASH_HEXF3 | ASO_OCTF1 | ASB_BINF3 - |AS_ONEDUP | AS_ASCIIC, - 0, - "GNU assembler", - 0, - NULL, // no headers - ".org", // org directive - 0, // end directive - "#", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".long", // dword (4 bytes) - ".quad", // qword (8 bytes) - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // seg prefix - ".", // curent ip - NULL, // func_header - NULL, // func_footer - ".global", // public - NULL, // weak - ".extern", // extrn - ".comm", // comm - NULL, // get_type_name - ".align", // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - - -static const asm_t *const asms[] = { &gnuas, NULL }; - -static int idaapi choose_device(int, form_actions_t &); - -//----------------------------------------------------------------------- -const char *arc_t::set_idp_options( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded) -{ - if ( keyword == NULL ) - { - static const char form[] = - "HELP\n" - "ARC specific options\n" - "\n" - " Simplify instructions\n" - "\n" - " If this option is on, IDA will simplify instructions and replace\n" - " them by more natural pseudo-instructions or alternative mnemonics.\n" - " For example,\n" - "\n" - " sub.f 0, a, b\n" - "\n" - " will be replaced by\n" - "\n" - " cmp a, b\n" - "\n" - "\n" - " Inline constant pool loads\n" - "\n" - " If this option is on, IDA will use =label syntax for\n" - " pc-relative loads (commonly used to load constants)\n" - " For example,\n" - "\n" - " ld r1, [pcl,0x1C]\n" - " ...\n" - " .long 0x2051D1C8\n" - "\n" - " will be replaced by\n" - "\n" - " ld r1, =0x2051D1C8\n" - "\n" - "\n" - " Track register accesses\n" - "\n" - " This option tells IDA to track values loaded\n" - " into registers and use it to improve the listing.\n" - " For example,\n" - "\n" - " mov r13, 0x172C\n" - " ...\n" - " add r0, r13, 0x98\n" - "\n" - " will be replaced by\n" - "\n" - " add r0, r13, (dword_17C4 - 0x172C)\n" - "\n" - "\n" - "ENDHELP\n" - "ARC specific options\n" - "%*\n" - " <~S~implify instructions:C>\n" - " <~I~nline constant pool loads:C>\n" - " <Track ~r~egister accesses:C>>\n" - " <~C~hoose core variant:B:0::>\n" - "\n"; - CASSERT(sizeof(idpflags) == sizeof(ushort)); - ask_form(form, this, &idpflags, choose_device); - return IDPOPT_OK; - } - else - { - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - if ( strcmp(keyword, "ARC_SIMPLIFY") == 0 ) - { - setflag(idpflags, ARC_SIMPLIFY, *(int*)value != 0); - } - else if ( strcmp(keyword, "ARC_INLINECONST") == 0 ) - { - setflag(idpflags, ARC_INLINECONST, *(int*)value != 0); - } - else if ( strcmp(keyword, "ARC_TRACKREGS") == 0 ) - { - setflag(idpflags, ARC_TRACKREGS, *(int*)value != 0); - } - else - { - return IDPOPT_BADKEY; - } - if ( idb_loaded ) - helper.altset(-1, idpflags); - return IDPOPT_OK; - } -} - -//----------------------------------------------------------------------- -// The short and long names of the supported processors -#define FAMILY "Argonaut RISC Core:" - -static const char *const shnames[] = -{ - "arc", - "arcmpct", - "arcv2", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Argonaut RISC Core ARCtangent-A4", - "Argonaut RISC Core ARCompact", - "Argonaut RISC Core ARCv2", - NULL -}; - -//-------------------------------------------------------------------------- -// Opcodes of "return" instructions. This information will be used in 2 ways: -// - if an instruction has the "return" opcode, its autogenerated label -// will be "locret" rather than "loc". -// - IDA will use the first "return" opcode to create empty subroutines. - -static const bytes_t retcodes[] = -{ - { 0, NULL } // NULL terminated array -}; - -//-------------------------------------------------------------------------- -void arc_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) -{ - qstrncpy(buf, "arc.cfg", bufsize); -} - -//-------------------------------------------------------------------------- -const char *arc_iohandler_t::iocallback(const ioports_t &iop, const char *line) -{ - int len; - sval_t ea1; - char word[MAXSTR]; - word[MAXSTR-1] = '\0'; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "aux %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) - { - const char *cmt = &line[len]; - cmt = skip_spaces(cmt); - ioport_t &port = pm.auxregs.push_back(); - port.address = ea1; - port.name = word; - if ( cmt[0] != '\0' ) - port.cmt = cmt; - return NULL; - } - return standard_callback(iop, line); -} - -//-------------------------------------------------------------------------- -bool arc_t::select_device(int resp_info) -{ - char cfgfile[QMAXFILE]; - arc_respect_info = resp_info; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( !choose_ioport_device(&ioh.device, cfgfile) ) - { - ioh.device = NONEPROC; - return false; - } - - if ( !ioh.display_infotype_dialog(IORESP_ALL, &arc_respect_info, cfgfile) ) - return false; - - ioh.set_device_name(ioh.device.c_str(), arc_respect_info); - return true; -} - - -//-------------------------------------------------------------------------- -static int idaapi choose_device(int, form_actions_t &fa) -{ - arc_t &pm = *(arc_t *)fa.get_ud(); - if ( pm.select_device(IORESP_ALL) ) - { - //load_symbols(IORESP_ALL); - //apply_symbols(); - } - return 0; -} - -//-------------------------------------------------------------------------- -static int idaapi arcso_gen_scaled_expr( - qstring * /*buf*/, - qstring *format, - ea_t /*ea*/, - int /*numop*/, - const refinfo_t &ri, - ea_t /*from*/, - adiff_t * /*opval*/, - ea_t * /*target*/, - ea_t * /*fullvalue*/, - int /*getn_flags*/) -{ - arc_t &pm = *GET_MODULE_DATA(arc_t); - int scale = ri.type() == pm.ref_arcsoh_id ? 2 : 4; - format->sprnt("%%s " COLSTR("/", SCOLOR_SYMBOL) " %i", scale); - return 4; // normal processing with custom format -} - -//-------------------------------------------------------------------------- -static bool idaapi arcso_calc_reference_data( - ea_t *target, - ea_t *base, - ea_t from, - const refinfo_t &ri, - adiff_t opval) -{ - arc_t &pm = *GET_MODULE_DATA(arc_t); - qnotused(from); - if ( ri.base == BADADDR || ri.is_subtract() ) - return false; - - int scale = ri.type() == pm.ref_arcsoh_id ? 2 : 4; - - *base = ri.base; - *target = ri.base + scale * opval; - - if ( ri.target != BADADDR && ri.target != *target ) - return false; - - return true; -} - -//-------------------------------------------------------------------------- -static const custom_refinfo_handler_t ref_arcsoh = -{ - sizeof(custom_refinfo_handler_t), - "ARCSOH", - "ARC 16-bit scaled offset", - RHF_TGTOPT, // properties: target be calculated using operand value - arcso_gen_scaled_expr, // gen_expr - arcso_calc_reference_data, // calc_reference_data - NULL, // get_format -}; - -//-------------------------------------------------------------------------- -static const custom_refinfo_handler_t ref_arcsol = -{ - sizeof(custom_refinfo_handler_t), - "ARCSOL", - "ARC 32-bit scaled offset", - RHF_TGTOPT, // properties: target be calculated using operand value - arcso_gen_scaled_expr, // gen_expr - arcso_calc_reference_data, // calc_reference_data - NULL, // get_format -}; - - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(arc_t)); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi arc_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - helper.create("$ arc"); - inf_set_be(false); // Set little-endian mode of the IDA kernel - set_codeseqs(); - hook_event_listener(HT_IDB, &idb_listener, &LPH); - ref_arcsol_id = register_custom_refinfo(&ref_arcsol); - ref_arcsoh_id = register_custom_refinfo(&ref_arcsoh); - break; - - case processor_t::ev_term: - unregister_custom_refinfo(ref_arcsoh_id); - unregister_custom_refinfo(ref_arcsol_id); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: - set_codeseqs(); - if ( inf_like_binary() ) - { - // ask the user - select_device(IORESP_ALL); - } - else - { - // load the default AUX regs - ioh.set_device_name(is_a4() ? "ARC4": "ARCompact", IORESP_NONE); - } - break; - - case processor_t::ev_ending_undo: - // restore ptype - ptype = processor_subtype_t(ph.get_proc_index()); - ptype_changed(); - //fall through - case processor_t::ev_oldfile: - idpflags = (ushort)helper.altval(-1); - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: - break; - - case processor_t::ev_newprc: - ptype = va_argi(va, processor_subtype_t); - //bool keep_cfg = va_argi(va, bool); - if ( uint(ptype) > prc_arcv2 ) //lint !e685 //-V547 is always false - { - code = -1; - break; - } - ptype_changed(); - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_is_call_insn: - // Is the instruction a "call"? - // ea_t ea - instruction address - // returns: 1-unknown, 0-no, 2-yes - { - const insn_t *insn = va_arg(va, insn_t *); - code = is_arc_call_insn(*insn) ? 1 : -1; - return code; - } - - case processor_t::ev_is_ret_insn: - { - const insn_t *insn = va_arg(va, insn_t *); -// bool strict = va_argi(va, bool); - code = is_arc_return_insn(*insn) ? 1 : -1; - return code; - } - - case processor_t::ev_is_basic_block_end: - { - const insn_t *insn = va_arg(va, insn_t *); - bool call_insn_stops_block = va_argi(va, bool); - return is_arc_basic_block_end(*insn, call_insn_stops_block) ? 1 : -1; - } - - case processor_t::ev_delay_slot_insn: - // Get delay slot instruction - // ea_t *ea in: instruction address in question, - // it may point to the instruction with a - // delay slot or to the delay slot - // instruction itself - // out: (if the answer is positive) - // if the delay slot contains valid insn: - // the address of the delay slot insn - // else: - // BADADDR (invalid insn, e.g. a branch) - // bool *bexec execute slot if jumping - // bool *fexec execute slot if not jumping - // returns: 1 positive answer - // <=0 ordinary insn - { - ea_t *ea = va_arg(va, ea_t *); - bool *bexec = va_arg(va, bool *); - bool *fexec = va_arg(va, bool *); - insn_t insn; - if ( decode_insn(&insn, *ea) == 0 ) - return -1; - if ( has_dslot(insn) ) - { - // the current instruction is a delayed slot instruction - // set EA to the address of the delay slot - *ea = insn.ea + insn.size; - // check the insn in the delay slot - // doc: "The Illegal Instruction Sequence type also occurs when - // any of the following instructions are attempted in an executed - // delay slot of a jump or branch: - // * Another jump or branch instruction (Bcc, BLcc, Jcc, JLcc) - // * Conditional loop instruction (LPcc) - // * Return from interrupt (RTIE) - // * Any instruction with long-immediate data as a source operand" - insn_t dslot_insn; - if ( decode_insn(&dslot_insn, *ea) == 0 - || is_arc_simple_branch(dslot_insn.itype) - || dslot_insn.itype == ARC_lp - || dslot_insn.itype == ARC_rtie - || dslot_insn.size > 4 ) - { - *ea = BADADDR; - } - } - else - { - if ( !is_flow(get_flags(*ea)) - || decode_prev_insn(&insn, *ea) == BADADDR - || !has_dslot(insn) ) - { - return -1; - } - // the previous instruction is a delayed slot instruction - // EA already has the address of the delay slot - } - *bexec = true; - *fexec = (insn.auxpref & aux_nmask) != aux_jd; - return 1; - } - - case processor_t::ev_is_switch: - { - switch_info_t *si = va_arg(va, switch_info_t *); - const insn_t *insn = va_arg(va, const insn_t *); - return arc_is_switch(si, *insn) ? 1 : 0; - } - - case processor_t::ev_may_be_func: - // can a function start here? - ///< \param insn (const ::insn_t*) the instruction - ///< \param state (int) autoanalysis phase - ///< 0: creating functions - ///< 1: creating chunks - ///< \return probability 0..100 - { - const insn_t *insn = va_arg(va, insn_t *); - int state = va_arg(va, int); - return arc_may_be_func(*insn, state); - } - - case processor_t::ev_undefine: - { - // an item is being undefined; delete data attached to it - ea_t ea = va_arg(va, ea_t); - del_insn_info(ea); - } - return 1; - -// +++ TYPE CALLBACKS - case processor_t::ev_decorate_name: - { - qstring *outbuf = va_arg(va, qstring *); - const char *name = va_arg(va, const char *); - bool mangle = va_argi(va, bool); - cm_t cc = va_argi(va, cm_t); - tinfo_t *type = va_arg(va, tinfo_t *); - return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; - } - - case processor_t::ev_max_ptr_size: - return 4; - - case processor_t::ev_calc_arglocs: - { - func_type_data_t *fti = va_arg(va, func_type_data_t *); - return calc_arc_arglocs(fti) ? 1 : -1; - } - - case processor_t::ev_calc_varglocs: - { - func_type_data_t *fti = va_arg(va, func_type_data_t *); - regobjs_t *regargs = va_arg(va, regobjs_t *); - /*relobj_t *stkargs =*/ va_arg(va, relobj_t *); - int nfixed = va_arg(va, int); - return calc_arc_varglocs(fti, regargs, nfixed) ? 1 : -1; - } - - case processor_t::ev_calc_retloc: - { - argloc_t *retloc = va_arg(va, argloc_t *); - const tinfo_t *type = va_arg(va, const tinfo_t *); - cm_t cc = va_argi(va, cm_t); - return calc_arc_retloc(retloc, *type, cc) ? 1 : -1; - } - - case processor_t::ev_use_stkarg_type: - return 0; - - case processor_t::ev_use_regarg_type: - { - int *used = va_arg(va, int *); - ea_t ea = va_arg(va, ea_t); - const funcargvec_t *rargs = va_arg(va, const funcargvec_t *); - *used = use_arc_regarg_type(ea, *rargs); - return 1; - } - - case processor_t::ev_use_arg_types: - { - ea_t ea = va_arg(va, ea_t); - func_type_data_t *fti = va_arg(va, func_type_data_t *); - funcargvec_t *rargs = va_arg(va, funcargvec_t *); - use_arc_arg_types(ea, fti, rargs); - return 1; - } - - case processor_t::ev_get_cc_regs: - { - callregs_t *callregs = va_arg(va, callregs_t *); - cm_t cc = va_argi(va, cm_t); - if ( cc == CM_CC_FASTCALL || cc == CM_CC_ELLIPSIS ) - { - const int *regs; - get_arc_fastcall_regs(®s); - callregs->set(ARGREGS_INDEPENDENT, regs, NULL); - return 1; - } - else if ( cc == CM_CC_THISCALL ) - { - callregs->reset(); - return 1; - } - } - break; - - case processor_t::ev_calc_cdecl_purged_bytes: - // calculate number of purged bytes after call - { - // ea_t ea = va_arg(va, ea_t); - return 0; - } - - case processor_t::ev_get_stkarg_offset: - // get offset from SP to the first stack argument - // args: none - // returns: the offset+2 - return 0; - -// --- TYPE CALLBACKS - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - arc_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - arc_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - arc_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_calc_spdelta: - { - sval_t *spdelta = va_arg(va, sval_t *); - const insn_t *insn = va_arg(va, const insn_t *); - return arc_calc_spdelta(spdelta, *insn); - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = arc_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_ARC, // id - // flag - PR_USE32 // 32-bit processor - | PR_DEFSEG32 // create 32-bit segments by default - | PRN_HEX // Values are hexadecimal by default - | PR_TYPEINFO // Support the type system notifications - | PR_CNDINSNS // Has conditional instructions - | PR_DELAYED // Has delay slots - | PR_USE_ARG_TYPES // use ph.use_arg_types callback - | PR_RNAMESOK // register names can be reused for location names - | PR_SEGS // has segment registers - | PR_SGROTHER, // the segment registers don't contain the segment selectors. - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - RegNames, // Register names - qnumber(RegNames), // Number of registers - - LDI_BASE, // first - rVds, // last - 4, // size of a segment register - rVcs, rVds, - - codestart_arcompact, // code start sequences - retcodes, - - 0, ARC_last, - Instructions, // instruc - 0, // size of tbyte - {0}, // real width - 0, // Icode of a return instruction - NULL, // Micro virtual machine description -}; diff --git a/idasdk75/module/arm/arm.hpp b/idasdk75/module/arm/arm.hpp deleted file mode 100644 index 0963b54..0000000 --- a/idasdk75/module/arm/arm.hpp +++ /dev/null @@ -1,1712 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2002 by Ilfak Guilfanov, Datarescue. - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _ARM_HPP -#define _ARM_HPP - -#include "../idaidp.hpp" -#include <idd.hpp> -#include <dbg.hpp> -#include <segregs.hpp> -#include <typeinf.hpp> -#include <fixup.hpp> -#include <set> -#include <map> -#include "../calcrel_common.hpp" -struct arm_t; - -//------------------------------------------------------------------ -struct fptr_info_t -{ - ea_t addr; // address where the fp register is set - ushort reg; // frame pointer for current function (usually R11 or R7) -}; - -//--------------------------------- -// ARM insn.auxpref bits -#define aux_cond 0x0001 // set condition codes (S postfix is required) -#define aux_byte 0x0002 // byte transfer (B postfix is required) -#define aux_npriv 0x0004 // non-privileged transfer (T postfix is required) -#define aux_regsh 0x0008 // shift count is held in a register (see o_shreg) -#define aux_negoff 0x0010 // memory offset is negated in LDR,STR -#define aux_immcarry 0x0010 // carry flag is set to bit 31 of the immediate operand (see may_set_carry) -#define aux_wback 0x0020 // write back (! postfix is required) -#define aux_wbackldm 0x0040 // write back for LDM/STM (! postfix is required) -#define aux_postidx 0x0080 // post-indexed mode in LDR,STR -#define aux_ltrans 0x0100 // long transfer in LDC/STC (L postfix is required) -#define aux_wimm 0x0200 // thumb32 wide encoding of immediate constant (MOVW) -#define aux_sb 0x0400 // signed byte (SB postfix) -#define aux_sh 0x0800 // signed halfword (SH postfix) -#define aux_sw (aux_sb|aux_sh) // signed word (SW postfix) -#define aux_h 0x1000 // halfword (H postfix) -#define aux_x (aux_h|aux_byte) // doubleword (X postfix in A64) -#define aux_d aux_x // dual (D postfix in A32/T32) -#define aux_p 0x2000 // priviledged (P postfix) -#define aux_coproc 0x4000 // coprocessor instruction -#define aux_wide 0x8000 // wide (32-bit) thumb instruction (.W suffix) -#define aux_pac 0x10000 // Pointer Authentication Code instruction (see PAC_ flags) -#define aux_ns 0x20000 // non-secure branch (NS suffix) - -//assembler flags -#define UAS_GNU 0x0001 // GNU assembler -#define UAS_LEGACY 0x0002 // Legacy (pre-UAL) assembler - -//--------------------------------- - -#define it_mask insnpref // mask field of IT-insn - -// data type of NEON and vector VFP instructions (for the suffix) -enum neon_datatype_t ENUM_SIZE(char) -{ - DT_NONE = 0, - DT_8, - DT_16, - DT_32, - DT_64, - DT_S8, - DT_S16, - DT_S32, - DT_S64, - DT_U8, - DT_U16, - DT_U32, - DT_U64, - DT_I8, - DT_I16, - DT_I32, - DT_I64, - DT_P8, - DT_P16, - DT_F16, - DT_F32, - DT_F64, - DT_P32, //unused? - DT_P64, //for 128-bit form of PMULL instruction -}; - -//------------------------------------------------------------------------- -// we will store the suffix in insnpref, since it's used only by the IT instruction -// if we need two suffixes (VCVTxx), we'll store the second one in Op1.specflag1 -inline void set_neon_suffix(insn_t &insn, neon_datatype_t suf1, neon_datatype_t suf2 = DT_NONE) -{ - if ( suf1 != DT_NONE ) - { - insn.insnpref = char(0x80 | suf1); - if ( suf2 != DT_NONE ) - insn.Op1.specflag1 = suf2; - } -} - -//------------------------------------------------------------------------- -inline neon_datatype_t get_neon_suffix(const insn_t &insn) -{ - if ( insn.insnpref & 0x80 ) - return neon_datatype_t(insn.insnpref & 0x7F); - else - return DT_NONE; -} - -//------------------------------------------------------------------------- -inline neon_datatype_t get_neon_suffix2(const insn_t &insn) -{ - return neon_datatype_t(insn.Op1.specflag1); -} - -//---------------------------------------------------------------------- -inline char dtype_from_dt(neon_datatype_t dt) -{ - switch ( dt ) - { - case DT_8: - case DT_S8: - case DT_U8: - case DT_I8: - case DT_P8: - return dt_byte; - case DT_16: - case DT_S16: - case DT_U16: - case DT_I16: - case DT_P16: - return dt_word; - case DT_32: - case DT_S32: - case DT_U32: - case DT_I32: - return dt_dword; - case DT_64: - case DT_S64: - case DT_U64: - case DT_I64: - case DT_NONE: - default: - return dt_qword; - case DT_F16: - return dt_half; - case DT_F32: - return dt_float; - case DT_F64: - return dt_double; - } -} - -#define PROC_MAXOP 5 -CASSERT(PROC_MAXOP <= UA_MAXOP); - -// Operand types: -#define o_shreg o_idpspec0 // Shifted register - // op.reg - register -#define shtype specflag2 // op.shtype - shift type -#define shreg(x) uchar(x.specflag1) // op.shreg - shift register -#define shcnt value // op.shcnt - shift counter - -#define ishtype specflag2 // o_imm - shift type -#define ishcnt specval // o_imm - shift counter - -#define secreg(x) uchar(x.specflag1) // o_phrase: the second register is here -#define ralign specflag3 // o_phrase, o_displ: NEON alignment (power-of-two bytes, i.e. 8*(1<<a)) - // minimal alignment is 16 (a==1) - -#define simd_sz specflag1 // o_reg: SIMD vector element size - // 0=scalar, 1=8 bits, 2=16 bits, 3=32 bits, 4=64 bits, 5=128 bits) - // number of lanes is derived from the vector size (dtype) -#define simd_idx specflag3 // o_reg: SIMD scalar index plus 1 (Vn.H[i]) - -// o_phrase: the second register is held in secreg (specflag1) -// the shift type is in shtype (specflag2) -// the shift counter is in shcnt (value) - -#define o_reglist o_idpspec1 // Register list (for LDM/STM) -#define reglist specval // The list is in op.specval -#define uforce specflag1 // PSR & force user bit (^ suffix) - -#define o_creglist o_idpspec2 // Coprocessor register list (for CDP) -#define CRd reg // -#define CRn specflag1 // -#define CRm specflag2 // - -#define o_creg o_idpspec3 // Coprocessor register (for LDC/STC) - -#define o_fpreglist o_idpspec4 // Floating point register list -#define fpregstart reg // First register -#define fpregcnt value // number of registers; 0: single register (NEON scalar) -#define fpregstep specflag2 // register spacing (0: {Dd, Dd+1,... }, 1: {Dd, Dd+2, ...} etc) -#define fpregindex specflag3 // NEON scalar index plus 1 (Dd[x]) -#define NOINDEX (char)254 // no index - all lanes (Dd[]) - -#define o_text o_idpspec5 // Arbitrary text stored in the operand - // structure starting at the 'value' field - // up to 16 bytes (with terminating zero) -#define o_cond o_idpspec5+1 // ARM condition as an operand - // condition is stored in 'value' field - -// The processor number of coprocessor instructions is held in cmd.Op1.specflag1: -#define procnum specflag1 - -// bits stored in specflag1 for APSR register -#define APSR_nzcv 0x01 -#define APSR_q 0x02 -#define APSR_g 0x04 -// for SPSR/CPSR -#define CPSR_c 0x01 -#define CPSR_x 0x02 -#define CPSR_s 0x04 -#define CPSR_f 0x08 -// for banked registers (R8-R12, SP, LR/ELR, SPSR), this flag is set -#define BANKED_MODE 0x80 // the mode is in low 5 bits (arm_mode_t) - -//------------------------------------------------------------------ -// Shift types: -enum shift_t -{ - LSL, // logical left LSL #0 - don't shift - LSR, // logical right LSR #0 means LSR #32 - ASR, // arithmetic right ASR #0 means ASR #32 - ROR, // rotate right ROR #0 means RRX - RRX, // extended rotate right - - // ARMv8 shifts - MSL, // masked shift left (ones are shifted in from the right) - - // extending register operations - UXTB, - UXTH, - UXTW, - UXTX, // alias for LSL - SXTB, - SXTH, - SXTW, - SXTX, -}; - -//------------------------------------------------------------------ -// Bit definitions. Just for convenience: -#define BIT0 0x00000001L -#define BIT1 0x00000002L -#define BIT2 0x00000004L -#define BIT3 0x00000008L -#define BIT4 0x00000010L -#define BIT5 0x00000020L -#define BIT6 0x00000040L -#define BIT7 0x00000080L -#define BIT8 0x00000100L -#define BIT9 0x00000200L -#define BIT10 0x00000400L -#define BIT11 0x00000800L -#define BIT12 0x00001000L -#define BIT13 0x00002000L -#define BIT14 0x00004000L -#define BIT15 0x00008000L -#define BIT16 0x00010000L -#define BIT17 0x00020000L -#define BIT18 0x00040000L -#define BIT19 0x00080000L -#define BIT20 0x00100000L -#define BIT21 0x00200000L -#define BIT22 0x00400000L -#define BIT23 0x00800000L -#define BIT24 0x01000000L -#define BIT25 0x02000000L -#define BIT26 0x04000000L -#define BIT27 0x08000000L -#define BIT28 0x10000000L -#define BIT29 0x20000000L -#define BIT30 0x40000000L -#define BIT31 0x80000000L - -#define HEX__(n) 0x##n##LU - -/* 8-bit conversion function */ -#define B8__(x) ((x&0x0000000FLU)?1:0) \ -+((x&0x000000F0LU)?2:0) \ -+((x&0x00000F00LU)?4:0) \ -+((x&0x0000F000LU)?8:0) \ -+((x&0x000F0000LU)?16:0) \ -+((x&0x00F00000LU)?32:0) \ -+((x&0x0F000000LU)?64:0) \ -+((x&0xF0000000LU)?128:0) - -// for upto 8-bit binary constants -#define B8(d) ((unsigned char)B8__(HEX__(d))) - -// for upto 16-bit binary constants, MSB first -#define B16(dmsb,dlsb) (((uint16)B8(dmsb)<< 8) | (uint16)B8(dlsb)) - -// for upto 32-bit binary constants, MSB first -#define B32(dmsb,db2,db3,dlsb) (((uint32)B8(dmsb)<<24) \ - | ((uint32)B8(db2 )<<16) \ - | ((uint32)B8(db3 )<< 8) \ - | (uint32)B8(dlsb)) - -// extract bit numbers high..low from val (inclusive, start from 0) -#define BITS(val, high, low) ( ((val)>>low) & ( (1<<(high-low+1))-1) ) - -// extract one bit -#define BIT(val, bit) ( ((val)>>bit) & 1 ) - -// return if mask matches the value -// mask has 1s for important bits and 0s for don't-care bits -// match has actual values for important bits -// e.g. : xx0x0 means mask is 11010 and match is aa0a0 -#define MATCH(value, mask, match) ( ((value) & (mask)) == (match) ) - -//------------------------------------------------------------------ -// The condition code of instruction will be kept in cmd.segpref: - -#define cond segpref - -//--------------------------------- -//PAC (Pointer Authentication Code) instruction suffix flags are stored in insnpref -// NB: we have only 8 bits! -#define pac_flags insnpref - -//bits 0..2: key used -//The Pointer Authentication specification defines five keys. Four -//keys for PAC* and AUT* instructions (combination of instruction/data -//and A/B keys), and a fifth key for use with the general purpose PACGA -//instruction -#define PAC_KEYMASK 0x07 -#define PAC_KEY_IA 0x00 // Instruction address, using key A -#define PAC_KEY_IB 0x01 // Instruction address, using key B -#define PAC_KEY_DA 0x02 // Data address, using key A -#define PAC_KEY_DB 0x03 // Data address, using key B -#define PAC_KEY_GA 0x04 // Generic key (PACGA) -#define PAC_KEY_RES5 0x05 // reserved for future -#define PAC_KEY_RES6 0x06 // reserved for future -//bits 3..4: address used -#define PAC_ADRMASK (3<<3) //address is: -#define PAC_ADR_GPR (0<<3) //in general-purpose register that is specified by <Xd> -#define PAC_ADR_X17 (1<<3) //in X17 -#define PAC_ADR_X30 (2<<3) //in X30(XLR) -//bits 5..7: modifier used -#define PAC_MODMASK (3<<5) //modifier is : -#define PAC_MOD_GPR (0<<5) //in general-purpose register or stack pointer that is specified by <Xn|SP> -#define PAC_MOD_ZR (1<<5) //zero -#define PAC_MOD_X16 (2<<5) //in X16 -#define PAC_MOD_SP (3<<5) //in SP - -//---------------------------------------------------------------------- -// build a suffix for a PAC instruction -static inline bool get_pac_suffix(qstring *suf, const insn_t &insn) -{ -// - int key = insn.pac_flags & PAC_KEYMASK; - const char *id = NULL, *ab = NULL; - switch ( key ) - { - case PAC_KEY_IA: id= "I"; ab="A"; break; - case PAC_KEY_IB: id= "I"; ab="B"; break; - case PAC_KEY_DA: id= "D"; ab="A"; break; - case PAC_KEY_DB: id= "D"; ab="B"; break; - case PAC_KEY_GA: id= "G"; ab="A"; break; - default: return false; - } - int adr = insn.pac_flags & PAC_ADRMASK; - int mod = insn.pac_flags & PAC_MODMASK; - bool pre_ab = adr == PAC_ADR_X30 || adr == PAC_ADR_X17; - switch ( insn.itype ) - { - case ARM_pac: - case ARM_aut: - suf->append(id); - if ( pre_ab ) - suf->append(ab); - - if ( adr == PAC_ADR_X17 ) - suf->append("17"); - else if ( adr != PAC_ADR_X30 && adr != PAC_ADR_GPR ) - return false; - - if ( mod == PAC_MOD_SP ) - suf->append("SP"); - else if ( mod == PAC_MOD_ZR ) - suf->append("Z"); - else if ( mod == PAC_MOD_X16 ) - suf->append("16"); - else if ( mod != PAC_MOD_GPR ) - return false; - if ( !pre_ab ) - suf->append(ab); - break; - case ARM_xpac: - if ( adr == PAC_ADR_X30 ) - suf->append("LR");//XPACLRI - else if ( adr != PAC_ADR_GPR ) - return 0; - suf->append(id); // XPACD, XPACI, - break; - default: - // AA, AB, AAZ, ABZ - suf->append("A"); - suf->append(ab); - if ( mod == PAC_MOD_ZR ) - suf->append("Z"); - break; - } - return true; -} - - - -//------------------------------------------------------------------ -enum RegNo -{ - R0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, R11, R12, R13, R14, R15, - CPSR, CPSR_flg, - SPSR, SPSR_flg, - T, rVcs, rVds, // virtual registers for code and data segments - Racc0, // Intel xScale coprocessor accumulator - FPSID, FPSCR, FPEXC, // VFP system registers - FPINST, FPINST2, MVFR0, MVFR1, - // msr system registers - SYSM_APSR, - SYSM_IAPSR, - SYSM_EAPSR, - SYSM_XPSR, - SYSM_IPSR, - SYSM_EPSR, - SYSM_IEPSR, - SYSM_MSP, - SYSM_PSP, - SYSM_PRIMASK, - SYSM_BASEPRI, - SYSM_BASEPRI_MAX, - SYSM_FAULTMASK, - SYSM_CONTROL, - Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, - Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, - D0, D1, D2, D3, D4, D5, D6, D7, - D8, D9, D10, D11, D12, D13, D14, D15, - D16, D17, D18, D19, D20, D21, D22, D23, - D24, D25, D26, D27, D28, D29, D30, D31, - S0, S1, S2, S3, S4, S5, S6, S7, - S8, S9, S10, S11, S12, S13, S14, S15, - S16, S17, S18, S19, S20, S21, S22, S23, - S24, S25, S26, S27, S28, S29, S30, S31, - FIRST_FPREG=Q0, - LAST_FPREG=S31, - CF, ZF, NF, VF, - - // AArch64 registers - // general-purpose registers - X0, X1, X2, X3, X4, X5, X6, X7, - X8, X9, X10, X11, X12, X13, X14, X15, - X16, X17, X18, X19, X20, X21, X22, X23, - X24, X25, X26, X27, X28, - X29, XFP = X29, // frame pointer - X30, XLR = X30, // link register - - XZR, // zero register (special case of GPR=31) - - XSP, // stack pointer (special case of GPR=31) - - XPC, // PC (not available as actual register) - - // 128-bit SIMD registers - V0, V1, V2, V3, V4, V5, V6, V7, - V8, V9, V10, V11, V12, V13, V14, V15, - V16, V17, V18, V19, V20, V21, V22, V23, - V24, V25, V26, V27, V28, V29, V30, V31, - - ARM_MAXREG, // must be the last entry -}; - -// we use specflag1 to store register values -// so they must fit into a byte -CASSERT(ARM_MAXREG < 0x100); - -extern const char *const arm_regnames[]; - -//------------------------------------------------------------------ -// r0 * argument word/integer result -// r1-r3 argument word -// -// r4-r8 S register variable -// r9 S (rfp) register variable (real frame pointer) -// -// r10 F S (sl) stack limit (used by -mapcs-stack-check) -// r11 F S (fp) argument pointer -// r12 (ip) temp workspace -// r13 F S (sp) lower end of current stack frame -// r14 (lr) link address/workspace -// r15 F (pc) program counter -// -// f0 floating point result -// f1-f3 floating point scratch -// -// f4-f7 S floating point variable - -#define PC R15 -#define LR R14 -#define SP R13 -#define FP R11 -#define FP2 R7 // in thumb mode - -inline int getreg(const op_t &x) -{ - return x.type == o_reg - || x.type == o_shreg - && x.shtype == LSL - && x.shcnt == 0 ? x.reg : -1; -} - -inline bool isreg(const op_t &x, int reg) -{ - return getreg(x) == reg; -} - -// is it simply [Rx, Ry]? -// no shift, no negation, no post-index, no writeback -inline bool is_simple_phrase(const insn_t &insn, const op_t &x) -{ - return x.type == o_phrase - && x.shtype == LSL - && x.shcnt == 0 - && (insn.auxpref & (aux_negoff|aux_postidx|aux_wback)) == 0; -} - -inline bool issp(const op_t &x) { return isreg(x, SP) || isreg(x, XSP); } -inline bool issp(int reg) { return reg == SP || reg == XSP; } - -#define is_a64reg(reg) ((reg) >= X0 && (reg) < ARM_MAXREG) - -inline bool is_gr(int reg) -{ - return reg >= R0 && reg <= R14 - || reg >= X0 && reg <= X30; -} - -inline bool is_thread_id_sysreg(const insn_t &insn, int op) -{ - // assert: insn.ops[op+0].type == o_imm - // && insn.ops[op+1].type == o_creg - // && insn.ops[op+2].type == o_creg - // && insn.ops[op+3].type == o_imm - // TPIDR_EL0 - return insn.ops[op+0].value == 3 - && insn.ops[op+1].reg == 13 - && insn.ops[op+2].reg == 0 - && insn.ops[op+3].value == 2; -} - -// is callee-saved (preserved) register? (according to Procedure Call Standard) -/* Procedure Call Standard for the ARM Architecture: -5.1.1. A subroutine must preserve the contents of the registers r4-r8, -r10, r11 and SP (and r9 in PCS variants that designate r9 as v6). -Procedure Call Standard for the ARM 64-bit Architecture: -5.1.1. A subroutine invocation must preserve the contents of the -registers r19-r29 and SP. -*/ -inline bool is_callee_saved_gr(int reg) -{ - return reg >= R4 && reg <= R11 - || reg >= X19 && reg <= X29; -} -/* Procedure Call Standard for the ARM Architecture: -5.1.2.1 Registers s16-s31 (d8-d15, q4-q7) must be preserved across -subroutine calls; registers s0-s15 (d0-d7, q0-q3) do not need to be -preserved (and can be used for passing arguments or returning results in -standard procedure-call variants) -Procedure Call Standard for the ARM 64-bit Architecture: -5.1.2. Registers v8-v15 must be preserved by a callee across subroutine -calls. -*/ -inline bool is_callee_saved_vr(int reg) -{ - return reg >= S16 && reg <= S31 - || reg >= D8 && reg <= D15 - || reg >= Q4 && reg <= Q7 - || reg >= V8 && reg <= V15; -} - -//---------------------------------------------------------------------- -// get full value of the immediate operand -// (performing optional shift operator) -inline uval_t get_immfull(const op_t &x) -{ - // FIXME support other types of shift - return x.type != o_imm ? 0 - : x.value == 0 ? 0 - : x.ishcnt == 0 ? x.value - : x.ishtype == LSL ? x.value << x.ishcnt - : x.ishtype == MSL ? ((x.value + 1) << x.ishcnt) - 1 - : 0; -} -//---------------------------------------------------------------------- -// check if 'reg' is present in 'reglist' (only ARM32 GPRs supported!) -inline bool in_reglist(uint32 reglist, int reg) -{ - return (reg <= R15) && (reglist & (1u << reg)) != 0; -} -//---------------------------------------------------------------------- -// calculate the total number of bytes represented by a register list -inline uval_t calc_reglist_size(uint32 reglist) -{ - return uval_t(4) * bitcount(reglist & 0xFFFF); -} - -//---------------------------------------------------------------------- -// find out pre- or post-indexed addressing mode of given operand <op>; -// if <delta> arg is specified than we check o_displ operand only and -// return register offset in <delta>; -// returns base register or -1 -inline int get_pre_post_delta(const insn_t &insn, const op_t &op, sval_t *delta = NULL) -{ - if ( (insn.auxpref & (aux_wback | aux_postidx)) != 0 - && (op.type == o_displ && op.addr != 0 - || op.type == o_phrase && delta == NULL) ) - { - if ( delta != NULL ) - *delta = op.addr; - return op.reg; - } - return -1; -} - -//------------------------------------------------------------------ -// PSR format: -// bit name description -// 0 M0 M4..M0 are mode bits: -// 1 M1 10000 User -// 2 M2 10001 FIQ (fast interrupt request) -// 3 M3 10010 IRQ (interrupt request) -// 4 M4 10011 Supervisor -// 10110 Monitor (security extensions) -// 10111 Abort -// 11010 Hyp (Hypervisor; virtualization extensions) -// 11011 Undefined -// 11111 System -// 5 T Thumb state -// 6 F FIQ disable -// 7 I IRQ disable -// 8 A Asynchronous abort disable -// 9 E Endianness (0=little endian, 1=big endian) -// 10 IT2 IT7...IT0 If-Then execution state bits (ITSTATE) -// 11 IT3 -// 12 IT4 -// 13 IT5 -// 14 IT6 -// 15 IT7 -// 16 GE0 GE3..GE0 Greater than or Equal flags (for SIMD instructions) -// 17 GE1 -// 18 GE2 -// 19 GE3 -// 24 J Jazelle state -// 25 IT0 -// 26 IT1 -// 27 Q Cumulative saturation flag -// 28 V Overflow -// 29 C Carry/Borrow/Extend -// 30 Z Zero -// 31 N Negative/Less Than - -enum arm_mode_t -{ - M_usr = B8(10000), - M_fiq = B8(10001), - M_irq = B8(10010), - M_svc = B8(10011), - M_mon = B8(10110), - M_abt = B8(10111), - M_hyp = B8(11010), - M_und = B8(11011), - M_sys = B8(11111), -}; - -//------------------------------------------------------------------ -// Vector summary: -// Address Exception Mode on Entry -// ------- --------- ------------- -// 0000 Reset Supervisor -// 0004 Undefined instruction Undefined -// 0008 Software interrupt Supervisor -// 000C Abort (prefetch) Abort -// 0010 Abort (data) Abort -// 0014 Hypervisor trap Hyp -// 0018 IRQ IRQ -// 001C FIQ FIQ - -//------------------------------------------------------------------ -// Condition codes: -enum cond_t -{ - cEQ, // 0000 Z Equal - cNE, // 0001 !Z Not equal - cCS, // 0010 C Unsigned higher or same - cCC, // 0011 !C Unsigned lower - cMI, // 0100 N Negative - cPL, // 0101 !N Positive or Zero - cVS, // 0110 V Overflow - cVC, // 0111 !V No overflow - cHI, // 1000 C & !Z Unsigned higher - cLS, // 1001 !C | Z Unsigned lower or same - cGE, // 1010 (N & V) | (!N & !V) Greater or equal - cLT, // 1011 (N & !V) | (!N & V) Less than - cGT, // 1100 !Z & ((N & V)|(!N & !V)) Greater than - cLE, // 1101 Z | (N & !V) | (!N & V) Less than or equal - cAL, // 1110 Always - cNV, // 1111 Never - cLAST -}; -inline cond_t get_cond(const insn_t &insn) -{ - return cond_t(insn.cond); -} -inline bool has_cond(const insn_t &insn) -{ - return insn.cond != cAL; -} -inline bool is_negated_cond(cond_t cond) -{ - return (cond & 1) != 0; -} -inline cond_t invert_cond(cond_t cond) -{ - if ( cond < cLAST ) - return cond_t(cond ^ 1); - return cLAST; -} - -//---------------------------------------------------------------------- -// see ARMExpandImm_C/ThumbExpandImm_C in ARM ARM -inline bool may_set_carry(ushort itype) -{ - switch ( itype ) - { - case ARM_and: - case ARM_bic: - case ARM_eor: - case ARM_mov: - case ARM_mvn: - case ARM_orn: - case ARM_orr: - case ARM_teq: - case ARM_tst: - return true; - } - return false; -} - -//---------------------------------------------------------------------- -// if true, then ASPR.C is set to bit 31 of the immediate constant -inline bool imm_sets_carry(const insn_t &insn) -{ - switch ( insn.itype ) - { - case ARM_and: - case ARM_bic: - case ARM_eor: - case ARM_mov: - case ARM_mvn: - case ARM_orn: - case ARM_orr: - // flags are updated if S suffix is used - return (insn.auxpref & (aux_immcarry|aux_cond)) == (aux_immcarry|aux_cond); - case ARM_teq: - case ARM_tst: - // these two always update flags - return (insn.auxpref & aux_immcarry) != 0; - } - return false; -} - - -//---------------------------------------------------------------------- -struct pushreg_t -{ - ea_t ea; // instruction ea - uval_t off; // offset from the frame top (sp delta) - uval_t width; // size of allocated area in bytes - int reg; // register number (-1 means stack space allocation) - DECLARE_COMPARISONS(pushreg_t); -}; -typedef qvector<pushreg_t> pushregs_t; - -struct pushinfo_t : public pushregs_t -{ - enum { PUSHINFO_VERSION = 2 }; - uint32 flags; -#define APSI_VARARG 0x01 // is vararg function? -#define APSI_FIRST_VARG_MASK 0x06 // index of the first register in push {rx..r3} -#define APSI_HAVE_SSIZE 0x08 // pushinfo_t structure contains its own size (field 'cb') -#define APSI_OFFSET_WO_DELTA 0x10 // do not use delta-coding for <off> - inline int get_first_vararg_reg(void) { return (flags & APSI_FIRST_VARG_MASK) >> 1; } - uval_t savedregs; // size of the 'saved regs' area - eavec_t prolog_insns; // additional prolog instruction addresses - // (in addition to instructions from pushregs_t) - uval_t fpd; // frame pointer delta - - int cb; // size of this structure (it would be better if - // this field was the first one) - - // vararg info - uval_t gr_top; // offset from the frame top general registers - // vararg save area - uval_t vr_top; // offset from the frame top FP/SIMD registers - // vararg save area - uval_t gr_width; // size of general registers vararg save area - uval_t vr_width; // size of FP/SIMD registers vararg save area - - pushinfo_t(void) - : flags(APSI_HAVE_SSIZE), - savedregs(0), fpd(0), - cb(sizeof(pushinfo_t)), - gr_top(0), vr_top(0), gr_width(0), vr_width(0) - {} - DECLARE_COMPARISONS(pushinfo_t); - - void serialize(bytevec_t *packed, ea_t ea) const; - bool deserialize(memory_deserializer_t *mmdsr, ea_t ea); - - void save_to_idb(arm_t &pm, ea_t ea) const; - bool restore_from_idb(arm_t &pm, ea_t ea); - - void mark_prolog_insns(arm_t &pm); -}; - -//---------------------------------------------------------------------- -enum arm_base_arch_t -{ - // values taken from ARM IHI 0045C, Tag_CPU_arch - arch_ARM_old = 0, // Pre-v4 - arch_ARMv4 = 1, // e.g. SA110 - arch_ARMv4T = 2, // e.g. ARM7TDMI - arch_ARMv5T = 3, // e.g. ARM9TDMI - arch_ARMv5TE = 4, // e.g. ARM946E-S - arch_ARMv5TEJ = 5, // e.g. ARM926EJ-S - arch_ARMv6 = 6, // e.g. ARM1136J-S - arch_ARMv6KZ = 7, // e.g. ARM1176JZ-S - arch_ARMv6T2 = 8, // e.g. ARM1156T2F-S - arch_ARMv6K = 9, // e.g. ARM1136J-S - arch_ARMv7 = 10, // e.g. Cortex A8, Cortex M3 - arch_ARMv6M = 11, // e.g. Cortex M1 - arch_ARMv6SM = 12, // v6-M with the System extensions - arch_ARMv7EM = 13, // v7-M with DSP extensions - arch_ARMv8 = 14, // v8 - arch_curr_max = arch_ARMv8, - arch_ARM_meta = 9999, // decode everything -}; - -enum arm_arch_profile_t -{ - arch_profile_unkn = 0, // Architecture profile is not applicable (e.g. pre v7, or cross-profile code) - arch_profile_A = 'A', // The application profile (e.g. for Cortex A8) - arch_profile_R = 'R', // The real-time profile (e.g. for Cortex R4) - arch_profile_M = 'M', // The microcontroller profile (e.g. for Cortex M3) - arch_profile_S = 'S', // Application or real-time profile (i.e. the 'classic' programmer's model) -}; - -enum fp_arch_t -{ - fp_arch_none = 0, // The user did not permit this entity to use instructions requiring FP hardware - fp_arch_v1 = 1, // The user permitted use of instructions from v1 of the floating point (FP) ISA - fp_arch_v2 = 2, // Use of the v2 FP ISA was permitted (implies use of the v1 FP ISA) - fp_arch_v3 = 3, // Use of the v3 FP ISA was permitted (implies use of the v2 FP ISA) - fp_arch_v3_16 = 4, // Use of the v3 FP ISA was permitted, but only citing registers D0-D15, S0-S31 - fp_arch_v4 = 5, // Use of the v4 FP ISA was permitted (implies use of the non-vector v3 FP ISA) - fp_arch_v4_16 = 6, // Use of the v4 FP ISA was permitted, but only citing registers D0-D15, S0-S31 - fp_arch_v8 = 7, // Use of the ARM v8-A FP ISA was permitted - fp_arch_v8_16 = 8, // Use of the ARM v8-A FP ISA was permitted, but only citing registers D0-D15, S0-S31 -}; - -enum adv_simd_arch_t -{ - adv_simd_arch_none = 0, // The user did not permit this entity to use the Advanced SIMD Architecture (Neon) - adv_simd_arch_base = 1, // Use of the Advanced SIMD Architecture (Neon) was permitted - adv_simd_arch_fma = 2, // Use of Advanced SIMD Architecture (Neon) with fused MAC operations was permitted - adv_simd_arch_v8 = 3, // Use of the ARM v8-A Advanced SIMD Architecture (Neon) was permitted -}; - -struct arm_arch_t -{ - arm_base_arch_t base_arch; - arm_arch_profile_t profile; - fp_arch_t fp_arch; - adv_simd_arch_t neon_arch; - - int arm_isa_use; // 0 = no ARM instructions (e.g. v7-M) - // 1 = allow ARM instructions - int thumb_isa_use; // 0 = no Thumb instructions - // 1 = 16-bit Thumb instructions + BL - // 2 = plus 32-bit Thumb instructions - int xscale_arch; // 0 = no XScale extension - // 1 = XScale extension (MAR/MRA etc) - int wmmx_arch; // 0 = no WMMX - // 1 = WMMX v1 - // 2 = WMMX v2 - int hp_ext; // 0 = no half-precision extension - // 1 = VFPv3/Advanced SIMD optional half-precision extension - int t2_ee; // 0 = no Thumb2-EE extension - // 1 = Thumb2-EE extension (ENTERX and LEAVEX) - qstring arch_name; // e.g. ARMv7-M - qstring core_name; // e.g. ARM1176JZF-S - - bool be8; // image is BE-8, i.e. little-endian code but big-endian data - bool arm64_32; // 32-bit address space, ARM64 instructions - - static const char *get_canonical_name(unsigned archno); - bool set_from_name(const char *name); // arch name or core name - bool set_options(const char *opts); // semicolon-delimited option string - void save_to_idb(arm_t &pm) const; - bool restore_from_idb(arm_t &pm); - qstring to_string() const; - arm_arch_t(void) - : base_arch(arch_ARM_old), - profile(arch_profile_unkn), - fp_arch(fp_arch_none), - neon_arch(adv_simd_arch_none), - arm_isa_use(0), - thumb_isa_use(0), - xscale_arch(0), - wmmx_arch(0), - hp_ext(0), - t2_ee(0), - be8(false), - arm64_32(false) - {} - - bool is_mprofile() - { - if ( profile == arch_profile_unkn ) - { - return base_arch >= arch_ARMv6M && base_arch <= arch_ARMv7EM; - } - return profile == arch_profile_M; - } -}; - -//------------------------------------------------------------------ -struct mmtype_t -{ - const char *name; - const type_t *type; - const type_t *fields; - tinfo_t tif; -}; - -//------------------------------------------------------------------ -void term_ana(void); -void move_it_blocks(ea_t from, ea_t to, asize_t size); -int get_it_size(const insn_t &insn); - -uint64 expand_imm_vfp(uint8 imm8, int sz); -bool idaapi equal_ops(const op_t &x, const op_t &y); - -int may_be_func(const insn_t &insn); -bool is_branch_insn(const insn_t &insn); -bool is_push_insn(const insn_t &insn, uint32 *reglist=NULL); -bool is_pop_insn(const insn_t &insn, uint32 *reglist=NULL, bool allow_ed=false); -int arm_create_switch_xrefs(ea_t insn_ea, const switch_info_t &si); -void mark_arm_codeseqs(void); -bool can_resolve_seg(ea_t ea); -#if defined(NALT_HPP) && defined(_XREF_HPP) -int arm_calc_switch_cases(casevec_t *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si); -#endif - -bool create_func_frame64(func_t *pfn, bool reanalyze); -int arm_get_frame_retsize(const func_t *pfn); -bool get_insn_op_literal(const insn_t &insn, const op_t &x, ea_t ea, void *value, bool force=false); - -void use_arm_arg_types( - ea_t ea, - func_type_data_t *fti, - funcargvec_t *rargs); - -//---------------------------------------------------------------------- -typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); - -ea_t arm_calc_step_over(ea_t ip); -ea_t arm_get_macro_insn_head(ea_t ip); -int arm_get_dbr_opnum(const insn_t &insn); -ssize_t arm_get_reg_name(qstring *buf, int _reg, size_t width, int reghi); -ssize_t arm_get_one_reg_name(qstring *buf, int _reg, size_t width); -bool ana_neon(insn_t &insn, uint32 code, bool thumb); -void opimm_vfp(op_t &x, uint32 imm8, int sz); -void ana_hint(insn_t &insn, int hint); -int get_it_info(ea_t ea); -int arm_get_reg_index(const char *name, bool as_mainreg, bitrange_t *pbitrange, bool is_a64); - -//====================================================================== -// common inline functions used by analyzer -//---------------------------------------------------------------------- -inline void oreglist(op_t &x, int regs) -{ - x.type = o_reglist; - x.dtype = dt_dword; - x.reglist = regs; -} - -//---------------------------------------------------------------------- -inline void onear(op_t &x, uval_t target, bool arm64=false) -{ - x.type = o_near; - x.dtype = dt_code; - x.addr = arm64 ? target : uint32(target); -} - -//---------------------------------------------------------------------- -inline void otext(op_t &x, const char *txt) -{ - x.type = o_text; - qstrncpy((char *)&x.value, txt, sizeof(x) - qoffsetof(op_t, value)); -} - -//---------------------------------------------------------------------- -// Get register number -inline uchar getreg(uint32 code, int lbit) -{ - return uchar((code >> lbit) & 0xF); -} - -//---------------------------------------------------------------------- -// Create operand of register type -inline void fillreg(op_t &x, uint32 code, int lbit) -{ - x.reg = getreg(code, lbit); - x.type = o_reg; - x.dtype = dt_dword; -} - -//---------------------------------------------------------------------- -inline void opreg(op_t &x, int rgnum) -{ - x.reg = uint16(rgnum); - x.type = o_reg; - x.dtype = dt_dword; -} - -struct reg_mode_t -{ - uint16 reg; - uchar mode; -}; - -//---------------------------------------------------------------------- -// Create operand of banked_reg type -extern const reg_mode_t banked0[32]; -extern const reg_mode_t banked1[32]; -inline bool opbanked(op_t &x, int R, uchar sysm) -{ - const reg_mode_t &rm = R ? banked1[sysm] : banked0[sysm]; - if ( rm.reg == 0xFFFF ) - return false; - x.reg = rm.reg; - x.specflag1 = rm.mode | BANKED_MODE; - x.type = o_reg; - x.dtype = dt_dword; - return true; -} - -//---------------------------------------------------------------------- -// Create operand of immediate type -inline void op_imm(op_t &x, uval_t value) -{ - x.type = o_imm; - x.dtype = dt_dword; - x.value = value; - x.ishtype = LSL; - x.ishcnt = 0; -} - -//---------------------------------------------------------------------- -// Create operand of immediate type (4 bits) -inline void op_imm4(op_t &x, uint32 code, int lbit) -{ - op_imm(x, getreg(code, lbit)); -} - -//---------------------------------------------------------------------- -inline void barrier_op(op_t &x, int code) -{ - const char *op = NULL; - switch ( code ) - { - case B8(0001): op = "OSHLD"; break; - case B8(0010): op = "OSHST"; break; - case B8(0011): op = "OSH"; break; - case B8(0101): op = "NSHLD"; break; - case B8(0110): op = "NSHST"; break; - case B8(0111): op = "NSH"; break; - case B8(1001): op = "ISHLD"; break; - case B8(1010): op = "ISHST"; break; - case B8(1011): op = "ISH"; break; - case B8(1101): op = "LD"; break; - case B8(1110): op = "ST"; break; - case B8(1111): op = "SY"; break; - } - if ( op != NULL ) - otext(x, op); - else - op_imm(x, code & 0xF); -} - -// is the current insn inside an it-block? -inline bool inside_itblock(int itcnd) -{ - return itcnd != -1; -} - -//====================================================================== -// common data sructures and functions for emulator -//---------------------------------------------------------------------- - -// since these is a lot of recursion in this module, we will keep -// all data as local as possible. no static data since we will have -// to save/restore it a lot -struct arm_saver_t -{ - arm_t ± - insn_t insn; // current instruction - bool flow; - - arm_saver_t(arm_t &_pm) : pm(_pm), insn(), flow(true) {} - arm_saver_t(arm_t &_pm, const insn_t &insn_) : pm(_pm), insn(insn_), flow(true) {} - - void handle_operand(const op_t &x, bool isload); - void emulate(void); - void handle_code_ref(const op_t &x, ea_t ea, bool iscall); - ea_t match_arm64_glue(void); - bool detect_glue_code( - ea_t ea, - int flags, -#define DGC_HANDLE 0x0001 // create offsets and names -#define DGC_FIND 0x0002 // ea points to the end of the glue code - ea_t *p_target = NULL, - ea_t *p_fptr = NULL, - size_t *p_glue_size = NULL); - bool detect_glue_code( - int flags, - ea_t *p_target = NULL, - ea_t *p_fptr = NULL, - size_t *p_glue_size = NULL); - bool arm_is_switch(void); - // try to decode instruction at ea as arm or thumb - //-V:try_decode:501 identical sub-expressions - bool try_decode(ea_t ea, bool is_thumb, bool check_sane = true); -}; - -// SPD value for security_push_cookie/security_pop_cookie -inline sval_t security_cookie_spd() -{ - return inf_is_64bit() ? 0x10 : 0x4; -} - -// SPD value for a special function -inline sval_t special_func_spd(special_func_t spf) -{ - return spf == SPF_GNU_MCOUNT_NC ? 4 - : spf == SPF_SECURITY_POP_COOKIE ? security_cookie_spd() - : spf == SPF_SECURITY_PUSH_COOKIE ? -security_cookie_spd() - : 0; -} - -int calc_fpreglist_size(const insn_t &ins); -int calc_advsimdlist_size(const insn_t &ins); - -// return true if 'x' is 'const' in LDR Rd, =const -inline bool is_ldr_literal(const insn_t &insn, const op_t &x) -{ - return x.type == o_mem - && (insn.itype == ARM_ldr || insn.itype == ARM_ldrpc - || insn.itype == ARM_ldur || insn.itype == ARM_ldxr - || insn.itype == ARM_fldd || insn.itype == ARM_flds - || insn.itype == ARM_vldr); -} - -//---------------------------------------------------------------------- -inline bool creglist_is_crd_cref(const insn_t &insn) -{ - return insn.itype == ARM_cdp || insn.itype == ARM_cdp2; -} -inline bool creglist_is_crn_cref(const insn_t &insn) -{ - return insn.itype != ARM_mcrr - && insn.itype != ARM_mrrc - && insn.itype != ARM_mcrr2 - && insn.itype != ARM_mrrc2; -} - -//---------------------------------------------------------------------- -// tuning parameters for reg_tracker_t -struct regtrack_info_t -{ - uint16 vals_size; // max number of possible values returned by - // find_op_values, find_reg_values; - // 0 - no limit; - uint16 op_recursion; // max level of recursion when calculating - // operands of the emulated instruction, e.g. - // LDR R0, =addr - // LDR R0, [R0,#4] - // ADD R0, #4 - // needs 2 levels (one for addressing, one for - // addition); - // 0 - no limit; - uint16 bblk_recursion; // max level of recursion when reconstructing - // the execution flow; - // 0 - no limit; - uint16 cache_size; // max size of the cache for one register; - // 0 - no limit; - uint16 max_xrefs; // max number of xrefs to analyze - // 0 - no limit; -}; - -//---------------------------------------------------------------------- -// Since we have to know if an instruction belongs to an IT-block or not, -// we keep all this information in a map -struct it_info_t -{ - uint8 size; - uint8 cond; - uint8 mask; - it_info_t(void) : size(0), cond(0), mask(0) {} - it_info_t(uval_t x) : - size(x&0xFF), - cond((x >> 8)&0xFF), - mask((x >> 16)&0xFF) - { - } - it_info_t(uint8 s, uint8 c, uint8 m) : size(s), cond(c), mask(m) {} - operator uval_t(void) const { return size | (cond << 8) | (mask << 16); } -}; -using it_blocks_t = std::map<ea_t, it_info_t>; // first_it_block_ea -> info - -//------------------------------------------------------------------ -#if defined(__LINUX__) && defined(__ARM__) || defined(ENABLE_LOWCNDS) -inline bool is_arm64_ea(ea_t ea) -{ - qnotused(ea); -#if defined(__EA64__) - return true; -#else - return false; -#endif -} -#endif - -//------------------------------------------------------------------ -#define BL_FORCE_JUMP 0 -#define BL_FORCE_CALL 1 -bool idaapi arm_bl_force(ea_t ea, int option, bool hide_errors); - -struct bl_force_flow_ah_t : public action_handler_t -{ - bool is_jump; - bl_force_flow_ah_t(bool _is_jump) : is_jump(_is_jump) {} - virtual int idaapi activate(action_activation_ctx_t *) override - { - return arm_bl_force( - get_screen_ea(), - is_jump ? BL_FORCE_JUMP : BL_FORCE_CALL, - false); - } - - virtual action_state_t idaapi update(action_update_ctx_t *) override - { - return AST_ENABLE_ALWAYS; - } -}; - -//------------------------------------------------------------------ -struct reg_tracker_t; -struct opinfo_helpers_t; -struct cfh_t; -struct rvi_vec_t; - -DECLARE_PROC_LISTENER(pm_idb_listener_t, struct arm_t); - -#define PROCMOD_T arm_t -struct arm_t : public procmod_t -{ - arm_t(); - DECLARE_VIRTUAL_DTOR(arm_t); - - pm_idb_listener_t idb_listener = pm_idb_listener_t(*this); - - //---------------------------------------------------------------------- - netnode helper; // altval(-1): idp flags -#define CALLEE_TAG 'A' // altval(ea): callee address for indirect calls -#define DXREF_TAG 'd' // altval(ea): resolved address for complex calculation (e.g. ADD R1, PC) -#define DELAY_TAG 'D' // altval(ea) == DELAY_MARK: analyze ea for a possible offset -#define ITBLOCK_TAG 'I' // altval(ea): packed it_info_t -#define FPTR_REG_TAG 'F' // supval(ea): frame pointer info fptr_info_t -#define FIXED_STKPNT 'x' // charval(ea): may not modify sp value at this address -#define PUSHINFO_TAG 's' // blob(ea): packed pushinfo_t -#define ARCHINFO_TAG 'a' // blob(0): packed arm_arch_t -#define LITERAL_EA 'L' // charval(insn_ea): =const operand number of load literal instruction -#define MAYBE_STKVAR 't' // charval(ea) == opno+1: may create stkvar for the operand - -#define DELAY_MARK 1 // possible offset marked for reanalysis -#define DELAY_DONE 2 // reanalysis completed, don't mark again to prevent endless loops - - inline void set_callee(ea_t ea, ea_t callee) { helper.easet(ea, callee, CALLEE_TAG); } - inline ea_t get_callee(ea_t ea) { return helper.eaget(ea, CALLEE_TAG); } - inline void del_callee(ea_t ea) { helper.eadel(ea, CALLEE_TAG); } - - inline void set_dxref(ea_t ea, ea_t dxref) { helper.easet(ea, dxref, DXREF_TAG); } - inline ea_t get_dxref(ea_t ea) { return helper.eaget(ea, DXREF_TAG); } - inline void del_dxref(ea_t ea) { helper.eadel(ea, DXREF_TAG); } - - // literal intsruction - inline void set_lit_opnum(ea_t insn_ea, uchar nop) { helper.charset_ea(insn_ea, nop, LITERAL_EA); } - inline uchar get_lit_opnum(ea_t insn_ea) { return helper.charval_ea(insn_ea, LITERAL_EA); } - inline void del_lit_opnum(ea_t insn_ea) { helper.chardel_ea(insn_ea, LITERAL_EA); } - - // possible stkvar - inline void set_possible_stkvar(ea_t insn_ea, int nop) { helper.charset_ea(insn_ea, uchar(nop + 1), MAYBE_STKVAR); } - inline int get_possible_stkvar(ea_t insn_ea) { return helper.charval_ea(insn_ea, MAYBE_STKVAR) - 1; } - inline void del_possible_stkvar(ea_t insn_ea) { helper.chardel_ea(insn_ea, MAYBE_STKVAR); } - - //---------------------------------------------------------------------- -#define IDP_SIMPLIFY 0x0001 -#define IDP_NO_PTR_DEREF 0x0002 -// 0x0004 // reserved, see reg.cpp -#define IDP_ARM5 0x0008 -#define IDP_NO_SETSGR 0x0010 -#define IDP_NO_BL_JUMPS 0x0020 -#define IDP_MOVT_MASK 0x0F00 // handling of MOV(W)/MOVT pairs -#define IDP_MOVT_SHIFT 8 // see MOVT_ - -// MOVT pair handling options -#define MOVT_NONE 0 //do nothing (old behavior) -#define MOVT_ADDR 1 //only convert if resulting value is valid address -#define MOVT_ALL 2 //convert all pairs regardless of the value - // default: convert valid addresses - ushort idpflags = MOVT_ADDR<<IDP_MOVT_SHIFT; - - inline bool simplify(void) { return (idpflags & IDP_SIMPLIFY) != 0; } - inline bool deref_ptrs(void) { return (idpflags & IDP_NO_PTR_DEREF) == 0; } - inline bool may_setsgr(void) { return (idpflags & IDP_NO_SETSGR) == 0; } - inline bool no_bl_jumps(void) { return (idpflags & IDP_NO_BL_JUMPS) != 0; } - inline uint8 arm_movt_convert(void) { return (idpflags & IDP_MOVT_MASK) >> 8; } - - bool convert_movw_movt(const insn_t &_insn, ea_t ea_movt, ea_t ea_movw, ea_t base); - - //---------------------------------------------------------------------- - arm_arch_t arch; - arm_arch_t tarch; // temporary (unsaved) arch info that's being changed by the user - qstring default_arch; - qstring arm_arch; - - inline bool has_arm() { return arch.arm_isa_use != 0; } - inline bool has_thumb() { return arch.thumb_isa_use != 0; } - inline bool has_thumb2() { return arch.thumb_isa_use >= 2; } - inline bool has_xscale() { return arch.xscale_arch != 0; } - inline bool has_vfp() { return arch.fp_arch != fp_arch_none; } - inline bool has_neon() { return arch.neon_arch != adv_simd_arch_none; } -#ifndef ENABLE_LOWCNDS - inline bool has_armv5() { return arch.base_arch >= arch_ARMv5T; } - inline bool has_armv7a() { return arch.base_arch == arch_ARMv7 || arch.base_arch > arch_ARMv7EM; } - inline bool has_armv8() { return arch.base_arch >= arch_ARMv8; } - inline bool is_mprofile() { return arch.is_mprofile(); } -#endif - inline bool is_be8() { return arch.be8 != 0; } - inline bool is_thumb_ea(ea_t ea) - { - if ( !has_arm() ) - return true; - sel_t t = get_sreg(ea, T); - return t != BADSEL && t != 0; - } - - intvec_t custom_format_fids; - bl_force_flow_ah_t bl_force_jump = bl_force_flow_ah_t(true); - bl_force_flow_ah_t bl_force_call = bl_force_flow_ah_t(false); - ea_t got_ea = BADADDR; // .got start address - int mnem_width = 0; - bool file_loaded = 0; - bool initing = false; - bool warn_about_max_xrefs = true; - bool recursing = false; - - it_blocks_t it_blocks; - - //---------------------------------------------------------------------- - // tuning parameters for reg_tracker_t (set from configuration file by - // set_idp_options) - regtrack_info_t regtrack_inf = - { - 100, // vals_size - 100, // op_recursion - 2000, // bblk_recursion - 5000, // cache_size - 256, // max_xrefs - }; - reg_tracker_t *reg_tracker = nullptr; - - //---------------------------------------------------------------------- - // clear the cache of calculated register values from <ea> until the - // next function; - // if <ea> is BADADDR the clear the whole cache - void clear_reg_cache(ea_t ea, int msgid); - // clear all - void term_reg_cache(); - // find all values loaded into register - void find_reg_values(rvi_vec_t *ret, ea_t ea, int reg); - - //---------------------------------------------------------------------- - mmtype_t *mmtypes = nullptr; - size_t mmtypes_cnt = 0; - mmtype_t *mm_array_types = nullptr; - size_t mm_array_types_cnt = 0; - - int get_arm_simd_types( - simd_info_vec_t *outtypes, - const simd_info_t *pattern, - const argloc_t *argloc, - bool do_create); - void term_arm_simdtypes(); - void register_custom_formats(void); - void unregister_custom_formats(void); - - //---------------------------------------------------------------------- - cfh_t *cfh = nullptr; -#ifdef __EA64__ - fixup_type_t cfh_pg21_id = 0; // ids of fixup handlers - fixup_type_t cfh_hi12_id = 0; - fixup_type_t cfh_lo12_id = 0; - fixup_type_t cfh_lo21_id = 0; - fixup_type_t cfh_b14_id = 0; - fixup_type_t cfh_b19_id = 0; - fixup_type_t cfh_b26_id = 0; - int ref_pg21_id = 0; // ids of refinfo handlers - int ref_hi12_id = 0; - int ref_lo12_id = 0; - int ref_lo21_id = 0; - - bool emulate_ldr_str_add_operand(const insn_t &insn, const op_t &op); -#else - // ids of fixup handlers - fixup_type_t cfh_prel31_id = 0; - // ids of refinfo handlers - int ref_prel31_id = 0; -#endif - - void init_custom_refs(); - void term_custom_refs(); - - //---------------------------------------------------------------------- -#include "../msvc_common.hpp" - - //---------------------------------------------------------------------- - inline bool is_gas(void) const - { - return (ash.uflag & UAS_GNU) != 0; - } - inline bool is_ual(void) const - { - return (ash.uflag & UAS_LEGACY) == 0; - } - - //---------------------------------------------------------------------- - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void arm_set_gotea(ea_t ea); - void arm_get_abi_info(qstrvec_t *abi_names, qstrvec_t *abi_opts, comp_t); - void arm_set_compiler(bool init_abibits); - void header(outctx_t &ctx); - void assumes(outctx_t &ctx); - void segstart(outctx_t &ctx, segment_t *seg); - void segend(outctx_t &ctx, segment_t *seg); - void del_function_marks(const func_t *pfn); - const char *get_regname(int rn); - - void init_ana(void); - void term_ana(void); - int ana64(insn_t &insn, calcrel_helper_t *crh); - int ana_arm(insn_t &insn, calcrel_helper_t *crh=nullptr); - int ana_thumb(insn_t &insn, calcrel_helper_t *crh=nullptr); - bool ana_coproc(insn_t &insn, uint32 code); - bool ana_vfp_insns(insn_t &insn, uint32 code); - bool ana_neon(insn_t &insn, uint32 code, bool thumb); - inline bool is_undef_vfp(uint32 code, bool thumb); - inline bool supported_vfp_neon_insn(uint32 code); - void check_displ(const insn_t &insn, op_t &x, bool alignPC=false); - void addressing_mode( - insn_t &insn, - op_t &x, - uint32 code, - calcrel_helper_t *crh); - bool thumb32(insn_t &insn, int code1, int code2, calcrel_helper_t *crh); - int do_ana(insn_t &insn, calcrel_helper_t *crh); - int ana(insn_t *out_ins); - int get_it_info(ea_t ea); - void move_it_blocks(ea_t from, ea_t to, asize_t size); - bool build_movl_macro(insn_t *s, const insn_t &insn); - bool build_adrl_macro(insn_t *s, const insn_t &insn); - bool build_movl_macro2(insn_t *s, const insn_t &insn); - bool build_macro(insn_t &insn, bool may_go_forward); - bool is_arm64(const insn_t &insn) const; - bool is_arm64(void) const; -#if defined(__LINUX__) && defined(__ARM__) - // see above, global def -#else - bool is_arm64_ea(ea_t ea) const; -#endif - bool check_for_t_changes(ea_t start, size_t size); - int a64_branch(insn_t &insn, uint32 code, calcrel_helper_t *crh); - int decode64(insn_t &insn, calcrel_helper_t *crh); - - int emu(const insn_t &insn); - void add_it_block(const insn_t &insn); - void del_insn_info(ea_t ea); - bool copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, bool force=false); - inline void fix_stkpnt(ea_t ea); - inline bool is_fixed_stkpnt(ea_t ea) const; - inline void add_stkpnt(const insn_t &insn, func_t *pfn, sval_t v) const; - void trace_sp(const insn_t &insn); - bool verify_sp(func_t *pfn); - inline void save_idpflags() { helper.altset(-1, idpflags); } - void add_dxref(ea_t from, ea_t target); - ea_t find_callee(const insn_t &insn, const op_t &x); - void emulate_ldr_str_base_offset( - const insn_t &insn, - ea_t base, - const struct rvi_vec_t &offs, - char op_dtyp, - bool swap_base_off, - bool only_dxref = false); - bool emulate_ldr_str_reg_based(const insn_t &insn, const op_t &op); - bool emulate_ldr_str_with_displ(const insn_t &insn, const op_t &op); - bool emulate_add_reg_based(const insn_t &insn, int reg1, int reg2); - void arm_splitSRrange1(ea_t from, ea_t to, sel_t v, uchar tag); - bool is_arm_call_insn(const insn_t &insn); - bool range_uses_lr(ea_t ea1, ea_t ea2); - bool is_bl_call(const insn_t &_insn, ea_t ea); - void propagate_t_bit_to(const insn_t &insn, ea_t ea, bool use_low_bit); - bool same_reg_value( - ea_t ea, - const op_t &op, - int r1, - const op_t *r1_moved, - bool ignore_r1_changes = false); - void set_arch_from_loader_arch_info(); - bool is_sp_alias(ea_t ea, int reg); - int arm_calc_next_eas(eavec_t *res, const insn_t &insn, bool over); - bool is_return_insn(const insn_t &insn, bool only_lr=false); - bool try_code_start(ea_t ea, bool respect_low_bit); - int try_offset(ea_t ea); - ea_t calc_next_exec_insn( - const insn_t &ins, - const regval_t *regvalues, - const opinfo_helpers_t &oh, - bool is_mprofile); - void mark_switch_insns(const eavec_t &eas); - bool try_switch_branch_stmt2(switch_info_t *_si, const insn_t &strt); - bool try_switch_branch_stmt3(switch_info_t *_si, const insn_t &strt); - bool try_switch_ofs_stmt(switch_info_t *_si, const insn_t &strt); - - //---------------------------------------------------------------------- - // Is register 'reg' spoiled by the current instruction? - // If flag <use_pcs> is set then it is assumed that call instruction - // doesn't spoil callee-saved registers (according to Procedure Call - // Standard the are r4-r8, r10, r11, SP for AArch32, r19-r29, SP for - // AArch64). If this flag is not set then this function assumes that - // call instruction spoils LR and r0 (why?). - bool spoils(const insn_t &insn, int reg, bool use_pcs = false); - // If flag <use_pcs> is set then it is assumed that call instruction - // doesn't spoil callee-saved registers else this function assumes that - // call instruction spoils everything (why?). - int spoils(const insn_t &insn, const uint32 *regs, int n, bool use_pcs = false); - // is PSR (Program Status Register) spoiled by the instruction ? - bool spoils_psr(const insn_t &insn) const; - - - bool get_fptr_info(fptr_info_t *fpi, ea_t func_ea) const; - inline ushort get_fptr_reg(ea_t func_ea) - { - fptr_info_t fpi; - return get_fptr_info(&fpi, func_ea) ? fpi.reg : ushort(-1); - } - inline ea_t get_fp_ea(ea_t func_ea) - { - fptr_info_t fpi; - return get_fptr_info(&fpi, func_ea) ? fpi.addr : BADADDR; - } - void set_fptr_info(ea_t func_ea, ushort reg, ea_t addr); - - bool is_sub_rn_fp(const insn_t &insn); - sval_t calc_sp_delta(func_t *pfn, const insn_t &insn); - bool arm_calc_spdelta(sval_t *spdelta, const insn_t &insn); - inline bool isfp(const insn_t &insn, const op_t &x); - inline bool is_sp_based(const insn_t &insn, const op_t &x); - void try_delay_offset(ea_t ea); - int sp_based(const insn_t &insn, const op_t &x); - bool uses(const insn_t &insn, int reg) const; - bool arm_set_op_type( - const insn_t &insn, - const op_t &x, - const tinfo_t &tif, - const char *name); - bool arm_set_op_type( - const insn_t &insn, - const op_t &x, - const tinfo_t &tif, - const char *name, - eavec_t *visited); - int use_arm_regarg_type(ea_t ea, const funcargvec_t &rargs); - void use_arm_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs); - bool is_glue_adr_insn(const insn_t &insn); - flags_t set_immd_bit(const insn_t &insn, int n, flags_t F); - bool good_target(ea_t from, ea_t target); - ea_t get_thumb_glue_target(ea_t ea); - bool handle_thunk(const insn_t &insn); - void handle_pc_offset(ea_t ea, int reg); - bool try_switch_word_stmt(switch_info_t *_si, const insn_t &strt); - int is_jump_func(func_t *pfn, ea_t *jump_target, ea_t *function_pointer); - int is_arm_sane_insn(const insn_t &insn, int asn_flags); -#define ASN_NOCREFS 0x01 // there are no crefs to the insn -#define ASN_THUMB 0x02 // use thumb mode -#define ASN_CHECK_MODE 0x04 // check thumb/arm mode of the next insn - int arm_is_align_insn(ea_t ea); - bool is_rt_switch8(switch_info_t *_si, const insn_t &insn); - bool lr_points_to_next_insn(const insn_t &insn, ea_t *value=nullptr); - bool arm_get_operand_info( - idd_opinfo_t *opinf, - ea_t ea, - int n, - int tid, - getreg_t *getreg, - const regval_t *rv); - ea_t arm_next_exec_insn( - ea_t ea, - int tid, - getreg_t *getreg, - const regval_t *regvalues); - void force_offset(ea_t ea, int n, ea_t base) const; - int may_be_func(const insn_t &_insn); - void get_reg_accesses(reg_accesses_t *accvec, const insn_t &insn) const; - void test_get_reg_accesses() const; - bool find_reg_diff(sval_t *delta, const insn_t &insn); - bool get_arm_callregs(callregs_t *callregs, cm_t cc); - bool is_big_udt(const tinfo_t &tif, bool as_retval); - bool alloc_args(func_type_data_t *fti, int nfixed); - bool calc_arm_arglocs(func_type_data_t *fti); - bool calc_arm_varglocs(func_type_data_t *fti, regobjs_t *regargs, int nfixed); - bool calc_arm_retloc(argloc_t *retloc, const tinfo_t &rettype, cm_t cc); - bool adjust_arm_argloc(argloc_t *argloc, const tinfo_t *tif, int size); - bool alloc_args64(func_type_data_t *fti, int nfixed); - void arm_lower_func_arg_types(intvec_t *argnums, const func_type_data_t &fti); - bool arm_get_reg_info(const char **main_name, bitrange_t *pbitrange, const char *name); - bool create_func_frame32(func_t *pfn, bool reanalyze); - bool create_func_frame64(func_t *pfn, bool reanalyze); - bool create_func_frame(func_t *pfn, bool reanalyze = false); - sval_t find_subsp_ofs(const insn_t &insn); - sval_t check_fp_changes(const insn_t &strt, int fpreg, int *finalreg); - bool adjust_frame_size( - func_t *pfn, - const insn_t &insn, - int reg, - sval_t spoff); - - void arm_move_segm(ea_t from, const segment_t *s, bool changed_netmap); - void arm_erase_info(ea_t ea1, ea_t ea2); - const char *set_idp_options( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded); - void correct_code_sequences(void); - bool is_be_proc() const; - - ushort basearch_to_field() const; - ushort vfp_to_field() const; - - void arm_upgrade_fbase_to700(); - void arm_upgrade_fptr_to700(); - - const char *cond2str(cond_t cond) const; - void footer(outctx_t &ctx) const; - bool outspec(outctx_t &ctx, uchar stype) const; -}; -extern int data_id; - -//---------------------------------------------------------------------- -class reg_formatter_t -{ - const processor_t &ph; - qstring outbuf; - - const char *regname(int rn) const; - void format_with_suffix(int rn, int fields); - -public: - reg_formatter_t(const processor_t &_ph) : ph(_ph) {} - void format_a64(int regnum, char dtype, int elsize = 0, int index = -1); - void format_with_index(int rn, int index=-1); - void format_any_reg(int rn, const op_t &x, bool ignore_suffix=false); - op_dtype_t format_phreg(const op_t &x, int regidx); - const qstring &get_regname() const { return outbuf; } -}; - -//------------------------------------------------------------------ -reg_tracker_t *alloc_reg_tracker(arm_t &pm); -void free_reg_tracker(reg_tracker_t *rt); -cfh_t *alloc_cfh(); -void free_cfh(cfh_t *ptr); - -#endif // _ARM_HPP diff --git a/idasdk75/module/arm/notify_codes.hpp b/idasdk75/module/arm/notify_codes.hpp deleted file mode 100644 index f08949d..0000000 --- a/idasdk75/module/arm/notify_codes.hpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __ARM_NOTIFY_CODES_HPP -#define __ARM_NOTIFY_CODES_HPP - -struct pushinfo_t; -struct arm_arch_t; -//---------------------------------------------------------------------- -// The following events are supported by the ARM module in the ph.notify() function -namespace arm_module_t -{ - enum event_codes_t - { - // obsolete, use processor_t::set_code16_mode() - ev_set_thumb_mode = processor_t::ev_loader, - ev_set_arm_mode, - // obsolete, use processor_t::get_code16_mode() - ev_get_thumb_mode, - ev_restore_pushinfo, // Restore function prolog info from the database - // in: pushinfo_t *pi - // ea_t func_start - // Returns: 1-ok, otherwise-failed - ev_save_pushinfo, // Save function prolog info to the database - // in: ea_t func_start - // const pushinfo_t *pi - // Returns: 1-ok, otherwise-failed - ev_is_push_insn, // Is push instruction? - // in: uint32 *reglist - // const insn_t* insn - // Returns: 1-yes, -1-no - ev_is_pop_insn, // Is pop instruction? - // in: uint32 *reglist - // const insn_t* insn - // bool allow_ldmed - // Returns: 1-yes, -1-no - ev_is_gnu_mcount_nc, // Is __gnu_mcount_nc function? - // in: ea_t ea - // Returns: 1-yes, -1-no - ev_is_special_func, // Is special function? - // in: ea_t ea - // Returns: special_func_t - ev_get_arch_settings, // in: arm_arch_t *arch to be filled in - // size_t strucsize;(init to sizeof(arm_arch_t) - // Returns: 1-ok, otherwise-failed - ev_get_fptr_info, // Get frame pointer info for given function - // in: ushort *reg (out) FP register number - // ea_t *addr (out) address where the fp register is set - // ea_t func_start - // Returns: 1-ok, 0-no FP register - ev_serialize_pushinfo, // Save function prolog info to the buffer - // in: bytevec_t *buf - // ea_t func_start - // const pushinfo_t *pi - // int flags (reserved) - // Returns: 1-ok, otherwise-failed - ev_deserialize_pushinfo, - // Restore function prolog info from the buffer - // in: pushinfo_t *pi - // memory_deserializer_t *buf - // ea_t func_start - // int flags (reserved) - // Returns: 1-ok, otherwise-failed - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline bool restore_pushinfo(pushinfo_t *pi, ea_t func_start) - { - return processor_t::notify(idp_ev(ev_restore_pushinfo), pi, func_start) == 1; - } - - inline bool save_pushinfo(ea_t func_start, const pushinfo_t &pi) - { - return processor_t::notify(idp_ev(ev_save_pushinfo), func_start, &pi) == 1; - } - - inline bool is_push_insn(uint32 *reglist, const insn_t &insn) - { - return processor_t::notify(idp_ev(ev_is_push_insn), reglist, &insn) == 1; - } - - inline bool is_pop_insn(uint32 *reglist, const insn_t &insn, bool allow_ldmed) - { - return processor_t::notify(idp_ev(ev_is_pop_insn), reglist, &insn, allow_ldmed) == 1; - } - - inline bool is_gnu_mcount_nc(ea_t ea) - { - return processor_t::notify(idp_ev(ev_is_gnu_mcount_nc), ea) == 1; - } - - inline int is_special_func(ea_t ea) - { - return processor_t::notify(idp_ev(ev_is_special_func), ea); - } - - inline bool get_arch_settings(arm_arch_t *arch) - { - return processor_t::notify(idp_ev(ev_get_arch_settings), arch) == 1; - } - - inline bool get_fptr_info(ushort *reg, ea_t *addr, ea_t func_start) - { - return processor_t::notify(idp_ev(ev_get_fptr_info), reg, addr, func_start) == 1; - } - - inline bool serialize_pushinfo( - bytevec_t *buf, - ea_t func_start, - const pushinfo_t &pi, - int flags = 0) - { - return processor_t::notify(idp_ev(ev_serialize_pushinfo), - buf, - func_start, - &pi, - flags) == 1; - } - - inline bool deserialize_pushinfo( - pushinfo_t *pi, - memory_deserializer_t *buf, - ea_t func_start, - int flags = 0) - { - return processor_t::notify(idp_ev(ev_deserialize_pushinfo), - pi, - buf, - func_start, - flags) == 1; - } -} - -#endif // __NOTIFY_CODES_HPP diff --git a/idasdk75/module/avr/ana.cpp b/idasdk75/module/avr/ana.cpp deleted file mode 100644 index 59c8bbc..0000000 --- a/idasdk75/module/avr/ana.cpp +++ /dev/null @@ -1,814 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#include "avr.hpp" -#include <fixup.hpp> -#include "../../ldr/elf/elfr_avr.h" - -//-------------------------------------------------------------------------- -/* - -0000 0000 0000 0000 nop -0000 0001 dddd rrrr movw Rd,Rr -0000 0010 dddd rrrr muls Rd,Rr -0000 0011 0ddd 0rrr mulsu Rd,Rr -0000 0011 0ddd 1rrr fmul Rd,Rr -0000 0011 1ddd 0rrr fmuls Rd,Rr -0000 0011 1ddd 1rrr fmulsu Rd,Rr -0000 01rd dddd rrrr cpc rd, rr -0000 10rd dddd rrrr sbc rd, rr -0000 11rd dddd rrrr add rd, rr lsl rd if rd==rr -0001 00rd dddd rrrr cpse rd, rr -0001 01rd dddd rrrr cp rd, rr -0001 10rd dddd rrrr sub rd, rr -0001 11rd dddd rrrr adc rd, rr rol rd if rd==rr -0010 00rd dddd rrrr and rd, rr tst rd if rd==rr -0010 01rd dddd rrrr eor rd, rr clr rd if rd==rr -0010 10rd dddd rrrr or rd, rr -0010 11rd dddd rrrr mov rd, rr -0011 kkkk dddd kkkk cpi rd, k (16<=d<=31) -0100 kkkk dddd kkkk sbci rd, k (16<=d<=31) -0101 kkkk dddd kkkk subi rd, k (16<=d<=31) -0110 kkkk dddd kkkk ori/sbr rd, k (16<=d<=31) -0111 kkkk dddd kkkk andi rd, k (16<=d<=31) cbr rd, k if op2 is bitwise negated -1000 000d dddd 0000 ld rd, Z -1000 000d dddd 1000 ld rd, Y -1000 001r rrrr 0000 st Z, rr -1000 001r rrrr 1000 st Y, rr -1001 000d dddd 0000(1*k)lds rd, k -1001 000d dddd 0001 ld rd, Z+ -1001 000d dddd 0010 ld rd, -Z -1001 000d dddd 0100 lpm Rd, Z -1001 000d dddd 0101 lpm Rd, Z+ -1001 000d dddd 0110 elpm Rd, Z -1001 000d dddd 0111 elpm Rd, Z+ -1001 000d dddd 1001 ld rd, Y+ -1001 000d dddd 1010 ld rd, -Y -1001 000d dddd 1100 ld rd, X -1001 000d dddd 1101 ld rd, X+ -1001 000d dddd 1110 ld rd, -X -1001 000d dddd 1111 pop rd -1001 001d dddd 0000(1*k)sts k, rd -1001 001d dddd 1111 push rd -1001 001r rrrr 0001 st Z+, rr -1001 001r rrrr 0010 st -Z, rr -1001 001r rrrr 0100 xch Z, rr -1001 001r rrrr 0101 las Z, rr -1001 001r rrrr 0110 lac Z, rr -1001 001r rrrr 0111 lat Z, rr -1001 001r rrrr 1001 st Y+, rr -1001 001r rrrr 1010 st -Y, rr -1001 001r rrrr 1100 st X, rr -1001 001r rrrr 1101 st X+, rr -1001 001r rrrr 1110 st -X, rr -1001 0100 0000 1000 sec -1001 0100 0001 1000 sez -1001 0100 0010 1000 sen -1001 0100 0011 1000 sev -1001 0100 0100 1000 ses -1001 0100 0101 1000 seh -1001 0100 0110 1000 set -1001 0100 0111 1000 sei -1001 0100 0sss 1000 bset s -1001 0100 1000 1000 clc -1001 0100 1001 1000 clz -1001 0100 1010 1000 cln -1001 0100 1011 1000 clv -1001 0100 1100 1000 cls -1001 0100 1101 1000 clh -1001 0100 1110 1000 clt -1001 0100 1111 1000 cli -1001 0100 1sss 1000 bclr s -1001 0100 0000 1001 ijmp -1001 0100 0001 1001 eijmp -1001 0100 KKKK 1011 des K -1001 0101 0xx0 1000 ret -1001 0101 0xx1 1000 reti -1001 0101 100x 1000 sleep -1001 0101 101x 1000 wdr -1001 0101 110x 1000 lpm -1001 0101 1101 1000 elpm -1001 0101 1110 1000 spm -1001 0101 1111 1000 espm -1001 0101 0000 1001 icall -1001 0101 0001 1001 eicall -1001 010d dddd 0000 com rd -1001 010d dddd 0001 neg rd -1001 010d dddd 0010 swap rd -1001 010d dddd 0011 inc rd -1001 010d dddd 0101 asr rd -1001 010d dddd 0110 lsr rd -1001 010d dddd 0111 ror rd -1001 010d dddd 1010 dec rd -1001 010k kkkk 110k(1*k)jmp k -1001 010k kkkk 111k(1*k)call k -1001 0110 kkdd kkkk adiw rd, k (d=24,26,28,30) -1001 0111 kkdd kkkk sbiw rd, k (d=24,26,28,30) -1001 1000 pppp pbbb cbi p, b -1001 1001 pppp pbbb sbic p, b -1001 1010 pppp pbbb sbi p, b -1001 1011 pppp pbbb sbis p, b -1001 11rd dddd rrrr mul rd, rr -1011 0ppd dddd pppp in rd, p -1011 1ppr rrrr pppp out p, rr -10q0 qq0d dddd 0qqq ldd rd, Z+q -10q0 qq0d dddd 1qqq ldd rd, Y+q -10q0 qq1r rrrr 0qqq std Z+d, rr -10q0 qq1r rrrr 1qqq std Y+d, rr -1100 kkkk kkkk kkkk rjmp k -1101 kkkk kkkk kkkk rcall k -1110 1111 dddd 1111 ser rd (16<=d<=31) -1110 kkkk dddd kkkk ldi rd, k -1111 00kk kkkk k000 brcs/brlo k -1111 00kk kkkk k001 brne k -1111 00kk kkkk k010 brmi k -1111 00kk kkkk k011 brvs k -1111 00kk kkkk k100 brlt k -1111 00kk kkkk k101 brhs k -1111 00kk kkkk k110 brts k -1111 00kk kkkk k111 brie k -1111 00kk kkkk ksss brbs s, k -1111 01kk kkkk k000 brcc/brsh k -1111 01kk kkkk k001 breq k -1111 01kk kkkk k010 brpl k -1111 01kk kkkk k011 brvc k -1111 01kk kkkk k100 brge k -1111 01kk kkkk k101 brhc k -1111 01kk kkkk k110 brtc k -1111 01kk kkkk k111 brid k -1111 01kk kkkk ksss brbc s, k -1111 100d dddd 0bbb bld rd, b -1111 101d dddd Xbbb bst rd, b -1111 110r rrrr xbbb sbrc rr, b -1111 111r rrrr xbbb sbrs rr, b -*/ - -inline uint32 avr_t::code_address(const insn_t &insn, signed int delta) const -{ - ea_t newip = insn.ip + 1 + delta; - uint32 size = romsize != 0 ? romsize : 0x10000; - return newip % size; -} - -//------------------------------------------------------------------------ -inline ushort ua_next_full_byte(insn_t &insn) -{ - return (ushort)get_wide_byte(insn.ea + insn.size++); -} - -//-------------------------------------------------------------------------- -inline void opreg(op_t &x, uint16 n) -{ - x.type = o_reg; - x.dtype = dt_byte; - x.reg = n; -} - -//-------------------------------------------------------------------------- -inline void avr_t::opimm(const insn_t &insn, op_t &x, int value) const -{ - x.type = o_imm; - x.dtype = dt_byte; - x.value = value; - x.specflag1 = uchar(helper.charval_ea(insn.ea, ELF_AVR_TAG) == ELF_AVR_LDI_NEG); -} - -//-------------------------------------------------------------------------- -inline void opnear(op_t &x, ea_t addr) -{ - x.type = o_near; - x.dtype = dt_code; - x.addr = addr; -} - -//-------------------------------------------------------------------------- -inline void opmem(insn_t &insn, op_t &x) -{ - x.type = o_mem; - x.dtype = dt_byte; - x.offb = (char)insn.size; - x.addr = ua_next_full_byte(insn); -} - -//-------------------------------------------------------------------------- -// 0001 10rd dddd rrrr sub rd, rr 6 -static void tworegs(insn_t &insn, int code) -{ - opreg(insn.Op1, (code >> 4) & 31); - opreg(insn.Op2, (code & 15) | ((code >> 5) & 16)); -} - -//-------------------------------------------------------------------------- -// 1000 000d dddd 1000 ld rd, Y -inline void opregd(op_t &x, int code) -{ - opreg(x, (code >> 4) & 31); -} - -//-------------------------------------------------------------------------- -inline void opphr(op_t &x, phrase_t phrase) -{ - x.type = o_phrase; - x.phrase = phrase; - x.dtype = dt_byte; -} - -//-------------------------------------------------------------------------- -inline void opport(op_t &x, int portnum) -{ - x.type = o_port; - x.addr = portnum; - x.dtype = dt_byte; -} - -//-------------------------------------------------------------------------- -inline void opdisp(op_t &x, phrase_t phrase, int delta) -{ - if ( delta ) - { - x.type = o_displ; - x.phrase = phrase; - x.addr = delta; - x.dtype = dt_byte; - } - else - { - opphr(x, phrase); - } -} - -//-------------------------------------------------------------------------- -int avr_t::ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - // if ( insn.ip & 1 ) return 0; // alignment error - int code = ua_next_full_byte(insn); - switch ( code >> 12 ) - { - case 0: - case 1: - case 2: -// 0000 0000 0000 0000 nop 0 -// 0000 0001 dddd rrrr movw Rd, Rr 0 -// 0000 0010 dddd rrrr muls Rd, Rr 0 -// 0000 0011 0ddd 0rrr mulsu Rd, Rr 0 -// 0000 0011 0ddd 1rrr fmul Rd, Rr 0 -// 0000 0011 1ddd 0rrr fmuls Rd, Rr 0 -// 0000 0011 1ddd 1rrr fmulsu Rd, Rr 0 -// 0000 01rd dddd rrrr cpc rd, rr 1 -// 0000 10rd dddd rrrr sbc rd, rr 2 -// 0000 11rd dddd rrrr add rd, rr 3 lsl rd if rd==rr -// 0001 00rd dddd rrrr cpse rd, rr 4 -// 0001 01rd dddd rrrr cp rd, rr 5 -// 0001 10rd dddd rrrr sub rd, rr 6 -// 0001 11rd dddd rrrr adc rd, rr 7 rol rd if rd==rr -// 0010 00rd dddd rrrr and rd, rr 8 tst rd if rd==rr -// 0010 01rd dddd rrrr eor rd, rr 9 clr rd if rd==rr -// 0010 10rd dddd rrrr or rd, rr A -// 0010 11rd dddd rrrr mov rd, rr B - { - static const uchar itypes[] = - { - AVR_nop, // 0 - AVR_cpc, // 1 - AVR_sbc, // 2 - AVR_add, // 3 - AVR_cpse, // 4 - AVR_cp, // 5 - AVR_sub, // 6 - AVR_adc, // 7 - AVR_and, // 8 - AVR_eor, // 9 - AVR_or, // A - AVR_mov // B - }; - int idx = (code >> 10) & 15; - insn.itype = itypes[idx]; - tworegs(insn, code); - switch ( idx ) - { - case 0: - switch ( (code>>8) & 3 ) - { - case 0: // nop - if ( code != 0 ) - return 0; - insn.Op1.type = insn.Op2.type = o_void; - break; - case 1: // movw - insn.itype = AVR_movw; - opreg(insn.Op1, ((code >> 3) & 30)); - opreg(insn.Op2, ((code << 1) & 30)); - break; - case 2: // muls - insn.itype = AVR_muls; - opreg(insn.Op1, 16 + (((code >> 4) & 15))); - opreg(insn.Op2, 16 + (((code >> 0) & 15))); - break; -// 0000 0011 0ddd 0rrr mulsu Rd, Rr 0 -// 0000 0011 0ddd 1rrr fmul Rd, Rr 0 -// 0000 0011 1ddd 0rrr fmuls Rd, Rr 0 -// 0000 0011 1ddd 1rrr fmulsu Rd, Rr 0 - case 3: // mulsu, fmul, fmuls, fmulsu - { - idx = ((code >> 6) & 2) | ((code>>3) & 1); - static const uchar subtypes[] = - { AVR_mulsu, AVR_fmul, AVR_fmuls, AVR_fmulsu }; - insn.itype = subtypes[idx]; - } - opreg(insn.Op1, 16 + (((code >> 4) & 7))); - opreg(insn.Op2, 16 + (((code >> 0) & 7))); - break; - } - break; - case 3: // lsl - if ( insn.Op1.reg == insn.Op2.reg ) - { - insn.itype = AVR_lsl; - insn.Op2.type = o_void; - } - break; - case 7: // rol - if ( insn.Op1.reg == insn.Op2.reg ) - { - insn.itype = AVR_rol; - insn.Op2.type = o_void; - } - break; - case 8: // tst - if ( insn.Op1.reg == insn.Op2.reg ) - { - insn.itype = AVR_tst; - insn.Op2.type = o_void; - } - break; - case 9: // clr - if ( insn.Op1.reg == insn.Op2.reg ) - { - insn.itype = AVR_clr; - insn.Op2.type = o_void; - } - break; - } - } - break; - - case 3: - case 4: - case 5: - case 6: - case 7: -// 0011 kkkk dddd kkkk cpi rd, k (16<=d<=31) -// 0100 kkkk dddd kkkk sbci rd, k (16<=d<=31) -// 0101 kkkk dddd kkkk subi rd, k (16<=d<=31) -// 0110 kkkk dddd kkkk ori/sbr rd, k (16<=d<=31) -// 0111 kkkk dddd kkkk andi rd, k (16<=d<=31) cbr rd, k if op2 is bitwise negated - { - static const uchar itypes[] = - { - AVR_cpi, - AVR_sbci, - AVR_subi, - AVR_ori, - AVR_andi, - }; - insn.itype = itypes[(code >> 12) - 3]; - opreg(insn.Op1, ((code >> 4) & 15) + 16); - opimm(insn, insn.Op2, (code & 0x0F) | ((code >> 4) & 0xF0)); - } - break; - - case 8: - case 10: -// 10q0 qq0d dddd 0qqq ldd rd, Z+q -// 10q0 qq0d dddd 1qqq ldd rd, Y+q -// 10q0 qq1r rrrr 0qqq std Z+d, rr -// 10q0 qq1r rrrr 1qqq std Y+d, rr -// 1000 000d dddd 0000 ld rd, Z -// 1000 000d dddd 1000 ld rd, Y -// 1000 001r rrrr 0000 st Z, rr -// 1000 001r rrrr 1000 st Y, rr - { - int delta = ((code & 0x2000) >> 8) - | ((code & 0x0C00) >> 7) - | (code & 0x0007); - if ( code & 0x200 ) - { - insn.itype = delta ? AVR_std : AVR_st; - opdisp(insn.Op1, (code & 8) ? PH_Y : PH_Z, delta); - opregd(insn.Op2, code); - } - else - { - insn.itype = delta ? AVR_ldd : AVR_ld; - opregd(insn.Op1, code); - opdisp(insn.Op2, (code & 8) ? PH_Y : PH_Z, delta); - } - } - break; - - case 9: - switch ( (code >> 8) & 15 ) - { - case 0: - case 1: - case 2: - case 3: -// 1001 000d dddd 0000(8*k)lds rd, k 0 -// 1001 000d dddd 0001 ld rd, Z+ 1 -// 1001 000d dddd 0010 ld rd, -Z 2 -// 1001 000d dddd 0100 lpm Rd, Z 4 -// 1001 000d dddd 0101 lpm Rd, Z+ 5 -// 1001 000d dddd 0110 elpm Rd, Z 6 -// 1001 000d dddd 0111 elpm Rd, Z+ 7 -// 1001 000d dddd 1001 ld rd, Y+ 9 -// 1001 000d dddd 1010 ld rd, -Y A -// 1001 000d dddd 1100 ld rd, X C -// 1001 000d dddd 1101 ld rd, X+ D -// 1001 000d dddd 1110 ld rd, -X E -// 1001 000d dddd 1111 pop rd F - -// 1001 001d dddd 0000(8*k)sts k, rd 0 -// 1001 001r rrrr 0001 st Z+, rr 1 -// 1001 001r rrrr 0010 st -Z, rr 2 -// 1001 001r rrrr 0011 <unallocated> 3 -// 1001 001r rrrr 0100 xch Z, rr 4 -// 1001 001r rrrr 0101 las Z, rr 5 -// 1001 001r rrrr 0110 lac Z, rr 6 -// 1001 001r rrrr 0111 lat Z, rr 7 -// 1001 001r rrrr 1000 <unallocated> 8 -// 1001 001r rrrr 1001 st Y+, rr 9 -// 1001 001r rrrr 1010 st -Y, rr A -// 1001 001r rrrr 1100 st X, rr C -// 1001 001r rrrr 1101 st X+, rr D -// 1001 001r rrrr 1110 st -X, rr E -// 1001 001d dddd 1111 push rd F - { - static const uchar itypes[] = - { - AVR_lds, AVR_ld, AVR_ld, 0, - AVR_lpm, AVR_lpm, AVR_elpm, AVR_elpm, - 0, AVR_ld, AVR_ld, 0, - AVR_ld, AVR_ld, AVR_ld, AVR_pop - }; - insn.itype = itypes[code & 15]; - opregd(insn.Op1, code); - switch ( code & 15 ) - { - case 0x0: - opmem(insn, insn.Op2); - switch ( helper.charval_ea(insn.ea+1, ELF_AVR_TAG) ) - { - case ELF_AVR_EEP_OFF: - insn.Op2.addr += ELF_AVR_EEPROMBASE-ELF_AVR_RAMBASE; - case ELF_AVR_RAM_OFF: - insn.Op2.addr += ELF_AVR_RAMBASE; - default: - break; - } - break; - case 0x1: opphr(insn.Op2, PH_ZPLUS); break; - case 0x2: opphr(insn.Op2, PH_MINUSZ); break; - case 0x4: opphr(insn.Op2, PH_Z); break; - case 0x5: opphr(insn.Op2, PH_ZPLUS); break; - case 0x6: opphr(insn.Op2, PH_Z); break; - case 0x7: opphr(insn.Op2, PH_ZPLUS); break; - case 0x9: opphr(insn.Op2, PH_YPLUS); break; - case 0xA: opphr(insn.Op2, PH_MINUSY); break; - case 0xC: opphr(insn.Op2, PH_X); break; - case 0xD: opphr(insn.Op2, PH_XPLUS); break; - case 0xE: opphr(insn.Op2, PH_MINUSX); break; - case 0xF: break; - default: - return 0; - } - if ( code & 0x200 ) - { - switch ( insn.itype ) - { - case AVR_pop: - insn.itype = AVR_push; - break; - case AVR_lds: - insn.itype = AVR_sts; - goto SWAP_OPERANDS; - case AVR_ld: - insn.itype = AVR_st; -SWAP_OPERANDS: - { - op_t tmp = insn.Op1; - insn.Op1 = insn.Op2; - insn.Op2 = tmp; - } - break; - case AVR_lpm: - case AVR_elpm: -// 1001 001r rrrr 0100 xch Z, rr 4 -// 1001 001r rrrr 0101 las Z, rr 5 -// 1001 001r rrrr 0110 lac Z, rr 6 -// 1001 001r rrrr 0111 lat Z, rr 7 - { - static const uchar itypes2[] = - { - AVR_xch, AVR_las, AVR_lac, AVR_lat, - }; - insn.itype = itypes2[code & 3]; - opphr(insn.Op1, PH_Z); - opregd(insn.Op2, code); - } - break; - } - } - } - break; - - case 4: - case 5: - switch ( code & 0xF ) - { - case 11: -// 1001 0100 KKKK 1011 des K - switch ( code & 0x0F00 ) - { - case 0x0400: - insn.itype = AVR_des; - opimm(insn, insn.Op1, (code >> 4) & 0xF); - break; - default: return 0; - } - break; - case 9: -// 1001 0100 0000 1001 ijmp -// 1001 0100 0001 1001 eijmp -// 1001 0101 0000 1001 icall -// 1001 0101 0001 1001 eicall - switch ( code & 0xFF0 ) - { - case 0x400: insn.itype = AVR_ijmp; break; - case 0x410: insn.itype = AVR_eijmp; break; - case 0x500: insn.itype = AVR_icall; break; - case 0x510: insn.itype = AVR_eicall; break; - default: return 0; - } - break; - case 8: -// 1001 0101 0xx0 1000 ret -// 1001 0101 0xx1 1000 reti -// 1001 0101 100x 1000 sleep -// 1001 0101 101x 1000 wdr -// 1001 0101 1100 1000 lpm -// 1001 0101 1101 1000 elpm -// 1001 0101 1110 1000 spm -// 1001 0101 1111 1000 espm - if ( (code & 0x0F00) == 0x0500 ) - { - if ( (code & 0x0090) == 0x0000 ) - insn.itype = AVR_ret; - else if ( (code & 0x0090) == 0x0010 ) - insn.itype = AVR_reti; - else if ( (code & 0x00E0) == 0x0080 ) - insn.itype = AVR_sleep; - else if ( (code & 0x00E0) == 0x00A0 ) - insn.itype = AVR_wdr; - else if ( (code & 0x00F0) == 0x00C0 ) - insn.itype = AVR_lpm; - else if ( (code & 0x00F0) == 0x00D0 ) - insn.itype = AVR_elpm; - else if ( (code & 0x00F0) == 0x00E0 ) - insn.itype = AVR_spm; - else if ( (code & 0x00F0) == 0x00F0 ) - insn.itype = AVR_espm; - break; - } -// 1001 0100 0000 1000 sec 0 -// 1001 0100 0001 1000 sez 1 -// 1001 0100 0010 1000 sen 2 -// 1001 0100 0011 1000 sev 3 -// 1001 0100 0100 1000 ses 4 -// 1001 0100 0101 1000 seh 5 -// 1001 0100 0110 1000 set 6 -// 1001 0100 0111 1000 sei 7 -// 1001 0100 0sss 1000 bset s -// 1001 0100 1000 1000 clc 8 -// 1001 0100 1001 1000 clz 9 -// 1001 0100 1010 1000 cln a -// 1001 0100 1011 1000 clv b -// 1001 0100 1100 1000 cls c -// 1001 0100 1101 1000 clh d -// 1001 0100 1110 1000 clt e -// 1001 0100 1111 1000 cli f -// 1001 0100 1sss 1000 bclr s - { - static const uchar itypes[] = - { - AVR_sec, AVR_sez, AVR_sen, AVR_sev, - AVR_ses, AVR_seh, AVR_set, AVR_sei, - AVR_clc, AVR_clz, AVR_cln, AVR_clv, - AVR_cls, AVR_clh, AVR_clt, AVR_cli, - }; - insn.itype = itypes[(code >> 4) & 15]; - } - break; // case 8 - - case 0: - case 1: - case 2: - case 3: - case 5: - case 6: - case 7: - case 10: -// 1001 010d dddd 0000 com rd 0 -// 1001 010d dddd 0001 neg rd 1 -// 1001 010d dddd 0010 swap rd 2 -// 1001 010d dddd 0011 inc rd 3 -// 1001 010d dddd 0101 asr rd 5 -// 1001 010d dddd 0110 lsr rd 6 -// 1001 010d dddd 0111 ror rd 7 -// 1001 010d dddd 1010 dec rd 10 - { - static const uchar itypes[] = - { - AVR_com, AVR_neg, AVR_swap, AVR_inc, - 0, AVR_asr, AVR_lsr, AVR_ror, - 0, 0, AVR_dec, - }; - insn.itype = itypes[code & 15]; - opregd(insn.Op1, code); - } - break; // case 8 - - case 12: - case 13: - case 14: - case 15: -// 1001 010k kkkk 110k(1*k)jmp k -// 1001 010k kkkk 111k(1*k)call k - insn.itype = (code & 2) ? AVR_call : AVR_jmp; - opnear(insn.Op1, (ea_t((code & 1) | ((code >> 3) & 0x3E)) << 16) - | ua_next_full_byte(insn)); - if ( helper.charval_ea(insn.ea+1, ELF_AVR_TAG) == ELF_AVR_ABS_OFF ) - insn.Op1.addr += ELF_AVR_ABSBASE; - break; - } - break; - - case 6: - case 7: -// 1001 0110 kkdd kkkk adiw rd, k (d=24,26,28,30) -// 1001 0111 kkdd kkkk sbiw rd, k (d=24,26,28,30) - insn.itype = (code & 0x100) ? AVR_sbiw : AVR_adiw; - opreg(insn.Op1, R24 + ((code >> 3) & 6)); - opimm(insn, insn.Op2, ((code >> 2) & 0x30) | (code & 0x0F)); - break; - - case 8: - case 9: - case 10: - case 11: -// 1001 1000 pppp pbbb cbi p, b -// 1001 1001 pppp pbbb sbic p, b -// 1001 1010 pppp pbbb sbi p, b -// 1001 1011 pppp pbbb sbis p, b - { - static const uchar itypes[] = { AVR_cbi, AVR_sbic, AVR_sbi, AVR_sbis }; - insn.itype = itypes[(code >> 8) & 3]; - opport(insn.Op1, (code >> 3) & 0x1F); - opimm(insn, insn.Op2, code & 7); - } - break; - - case 12: - case 13: - case 14: - case 15: -// 1001 11rd dddd rrrr mul rd, rr - insn.itype = AVR_mul; - tworegs(insn, code); - break; - } - break; - - case 11: -// 1011 0ppd dddd pppp in rd, p -// 1011 1ppr rrrr pppp out p, rr - if ( code & 0x800 ) - { - insn.itype = AVR_out; - opport(insn.Op1, ((code & 0x0600) >> 5) | (code & 15)); - opregd(insn.Op2, code); - } - else - { - insn.itype = AVR_in; - opregd(insn.Op1, code); - opport(insn.Op2, ((code & 0x0600) >> 5) | (code & 15)); - } - break; - - case 12: - case 13: -// 1100 kkkk kkkk kkkk rjmp k -// 1101 kkkk kkkk kkkk rcall k - { - insn.itype = (code & 0x1000) ? AVR_rcall : AVR_rjmp; - signed int delta = (code & 0xFFF); - if ( delta & 0x800 ) - delta |= ~0xFFF; - opnear(insn.Op1, code_address(insn, delta)); - } - break; - - case 14: -// 1110 1111 dddd 1111 ser rd (16<=d<=31) -// 1110 kkkk dddd kkkk ldi rd, k - { - insn.itype = AVR_ldi; - opreg(insn.Op1, ((code >> 4) & 15) + 16); - int x = ((code >> 4) & 0xF0) | (code & 0x0F); - if ( x == 0xFF && !exists_fixup(insn.ea) ) - { - insn.itype = AVR_ser; - break; - } - opimm(insn, insn.Op2, x); - } - break; - - case 15: - switch ( (code >> 9) & 7 ) - { - case 0: - case 1: - case 2: - case 3: -// 1111 00kk kkkk k000 brcs/brlo k -// 1111 00kk kkkk k001 breq k -// 1111 00kk kkkk k010 brmi k -// 1111 00kk kkkk k011 brvs k -// 1111 00kk kkkk k100 brlt k -// 1111 00kk kkkk k101 brhs k -// 1111 00kk kkkk k110 brts k -// 1111 00kk kkkk k111 brie k -// 1111 00kk kkkk ksss brbs s, k -// 1111 01kk kkkk k000 brcc/brsh k -// 1111 01kk kkkk k001 brne k -// 1111 01kk kkkk k010 brpl k -// 1111 01kk kkkk k011 brvc k -// 1111 01kk kkkk k100 brge k -// 1111 01kk kkkk k101 brhc k -// 1111 01kk kkkk k110 brtc k -// 1111 01kk kkkk k111 brid k -// 1111 01kk kkkk ksss brbc s, k - { - static const uchar itypes[] = - { - AVR_brcs, AVR_breq, AVR_brmi, AVR_brvs, - AVR_brlt, AVR_brhs, AVR_brts, AVR_brie, - AVR_brcc, AVR_brne, AVR_brpl, AVR_brvc, - AVR_brge, AVR_brhc, AVR_brtc, AVR_brid, - }; - insn.itype = itypes[((code >> 7) & 8) | (code & 7)]; - signed int delta = (code >> 3) & 0x7F; - if ( delta & 0x40 ) - delta |= ~0x7F; - opnear(insn.Op1, code_address(insn, delta)); - } - break; - case 4: -// 1111 100d dddd 0bbb bld rd, b - if ( code & 8 ) - return 0; - insn.itype = AVR_bld; - goto REGBIT; - case 5: -// 1111 101d dddd Xbbb bst rd, b - insn.itype = AVR_bst; - goto REGBIT; - case 6: -// 1111 110r rrrr xbbb sbrc rr, b - insn.itype = AVR_sbrc; - goto REGBIT; - case 7: - insn.itype = AVR_sbrs; -// 1111 111r rrrr xbbb sbrs rr, b -REGBIT: - opregd(insn.Op1, code); - opimm(insn, insn.Op2, code & 7); - break; - } - break; - } - if ( insn.itype == AVR_null ) - return 0; - return insn.size; -} diff --git a/idasdk75/module/avr/avr.cfg b/idasdk75/module/avr/avr.cfg deleted file mode 100644 index 269a705..0000000 --- a/idasdk75/module/avr/avr.cfg +++ /dev/null @@ -1,17790 +0,0 @@ -; -; New directives: -; -; RAM=xxxx ;Maximum # bytes of RAM for this part -; ROM=xxxx ;# 8-bit bytes of ROM for this part -; EEPROM=xxxx ;# 8-bit bytes of EEPROM for this part -; -; Please note that the ROM size must be declared as the double of the addressable -; size because it is in bytes -; -; Information in this file came from the August, 1999 Atmel AVR databook -; - -; -; this file defines the i/o port definitions for amtel's avr processors. -; the i/o port definitions are provided for each avr device -; each device definition begins with a line like this: -; -; .devicename -; -; after it go the port definitions in this format: -; -; portname address -; -; lines beginning with a space are ignored. -; comment lines should be started with ';' character. -; -; the default device is specified at the start of the file -; -; SUBARCH corresponds to the __AVR_ARCH__ value used in GCC toolchain -; -; The following values are defined: -; -; 1: avr1 - classic AVR core without data RAM -; MCU types: at90s1200, attiny11, attiny12, attiny15, attiny28 -; -; 2: avr2 - classic AVR core with up to 8K program memory -; MCU types: at90s2313, at90s2323, at90s2333, at90s2343, attiny22, attiny26, -; at90s4414, at90s4433, at90s4434, at90s8515, at90c8534, at90s8535 -; -; 25: avr25 - classic AVR core with up to 8K program memory plus the MOVW instruction -; MCU types: attiny13, attiny13a, attiny2313, attiny2313a, attiny24, attiny24a, -; attiny4313, attiny44, attiny44a, attiny84, attiny84a, attiny25, -; attiny45, attiny85, attiny261, attiny261a, attiny461, attiny461a, -; attiny861, attiny861a, attiny87, attiny43u, attiny48, attiny88, at86rf401, ata6289 -; -; 3: avr3 - classic AVR core with up to 64K program memory -; MCU types: at43usb355, at76c711 -; -; 31: avr31 - classic AVR core with 128K program memory -; MCU types: atmega103, at43usb320 -; -; 35: avr35 - classic AVR core with up to 64K program memory plus MOVW, CALL, and JMP instructions -; MCU types: attiny167, at90usb82, at90usb162, atmega8u2, atmega16u2, atmega32u2 -; -; 4: avr4 - enhanced AVR core with up to 8K program memory -; MCU types: atmega48, atmega48a, atmega48p, atmega8, atmega88, atmega88a, atmega88p, -; atmega88pa, atmega8515, atmega8535, atmega8hva, at90pwm1, at90pwm2, -; at90pwm2b, at90pwm3, at90pwm3b, at90pwm81 -; -; 5: avr5 - enhanced AVR core with up to 128K program memory -; MCU types: atmega16, atmega16a, atmega161, atmega162, atmega163, -; atmega164a, atmega164p, atmega165, atmega165a, atmega165p, atmega168, -; atmega168a, atmega168p, atmega169, atmega169a, atmega169p, atmega169pa, -; atmega32, atmega323, atmega324a, atmega324p, atmega325, atmega325a, -; atmega325p, atmega3250, atmega3250a, atmega3250p, atmega328, atmega328p, -; atmega329, atmega329a, atmega329p, atmega329pa, atmega3290, atmega3290a, -; atmega3290p, atmega406, atmega64, atmega640, atmega644, atmega644a, -; atmega644p, atmega644pa, atmega645, atmega645a, atmega645p, atmega6450, -; atmega6450a, atmega6450p, atmega649, atmega649a, atmega649p, atmega6490, -; atmega6490a, atmega6490p, atmega16hva, atmega16hva2, atmega16hvb, -; atmega32hvb, atmega64hve, at90can32, at90can64, at90pwm216, at90pwm316, -; atmega32c1, atmega64c1, atmega16m1, atmega32m1, atmega64m1, atmega16u4, -; atmega32u4, atmega32u6, at90usb646, at90usb647, at94k, at90scr100 -; -; 51: avr51 - enhanced AVR core with 128K program memory -; MCU types: atmega128, atmega1280, atmega1281, atmega1284p, atmega128rfa1, -; at90can128, at90usb1286, at90usb1287, m3000 -; -; 6: avr6 - enhanced AVR core with up to 256K program memory and a 3-byte PC -; MCU types: atmega2560, atmega2561 -; -; 101: avrxmega1 - XMega core with up to 8K program memory -; -; 102: avrxmega2 - XMega core with 8K to 64K program memory and less than 64K RAM -; MCU types: atxmega16a4, atxmega16d4, atxmega32d4 -; -; 103: avrxmega3 - XMega core with 8K to 64K program memory and more than 64K RAM -; MCU types: atxmega32a4 -; -; 104: avrxmega4 - XMega core with 64K to 128K program memory and less than 64K RAM -; MCU types: atxmega64a3, atxmega64d3 -; -; 105: avrxmega5 - XMega core with 64K to 128K program memory and more than 64K RAM -; MCU types: atxmega64a1 -; -; 106: avrxmega6 - XMega core with 128K to 256K program memory and less than 64K RAM -; MCU types: atxmega128a3, atxmega128d3, atxmega192a3, atxmega192d3, atxmega256a3, atxmega256a3b, atxmega192d3 -; -; 107: avrxmega7 - XMega core with 128K to 256K program memory and more than 64K RAM -; MCU types: atxmega128a1 - -.default AT90S8515 - -.AT90C8534 -SUBARCH=2 -; doc1229.pdf -; - -RAM=256 -ROM=8192 -EEPROM=512 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0060 I/O registers -area DATA I_SRAM 0x0060:0x0160 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_OVF 0x0003 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0004 Timer/Counter0 Overflow -entry ADC_ 0x0005 ADC Conversion Complete -entry EE_RDY 0x0006 EEPROM Ready - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -ADCL 0x0004 ADC Data Register Low -ADCH 0x0005 ADC Data Register High -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Run Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Select Register -ADMUX.MUX2 2 Analog Channel Select Bit 2 -ADMUX.MUX1 1 Analog Channel Select Bit 1 -ADMUX.MUX0 0 Analog Channel Select Bit 0 -RESERVED0008 0x0008 RESERVED -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -GIPR 0x0010 General Interrupt Pin Register -GIPR.IPIN1 3 External Interrupt Pin 1 -GIPR.IPIN0 2 External Interrupt Pin 0 -RESERVED0011 0x0011 RESERVED -RESERVED0012 0x0012 RESERVED -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -RESERVED0016 0x0016 RESERVED -RESERVED0017 0x0017 RESERVED -RESERVED0018 0x0018 RESERVED -RESERVED0019 0x0019 RESERVED -DDRA 0x001A Port A Data Direction Register -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 -EEARL.EEAR6 6 -EEARL.EEAR5 5 -EEARL.EEAR4 4 -EEARL.EEAR3 3 -EEARL.EEAR2 2 -EEARL.EEAR1 1 -EEARL.EEAR0 0 -EEARH 0x001F EEPROM Address Register High -RESERVED0020 0x0020 RESERVED -RESERVED0021 0x0021 RESERVED -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -TCNT1L 0x002C Timer/Counter1 Low -TCNT1H 0x002D Timer/Counter1 High -TCCR1 0x002E Timer/Counter1 Control Register -TCCR1.CS12 2 Clock Select1, Bit 2 -TCCR1.CS11 1 Clock Select1, Bit 1 -TCCR1.CS10 0 Clock Select1, Bit 0 -RESERVED002F 0x002F RESERVED -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -RESERVED0034 0x0034 RESERVED -MCUCR 0x0035 MCU Control Register -MCUCR.SE 6 Sleep Enable -MCUCR.SM 5 Sleep Mode -MCUCR.ISC1 2 Interrupt Sense Control 1 -MCUCR.ISC0 0 Interrupt Sense Control 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer Low -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; RESERVED0023 0x0023 RESERVED -; ADCL 0x0024 ADC Data Register Low -; ADCH 0x0025 ADC Data Register High -; ADCSR 0x0026 ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADFR 5 ADC Free Run Select -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Select Register -; ADMUX.MUX2 2 Analog Channel Select Bit 2 -; ADMUX.MUX1 1 Analog Channel Select Bit 1 -; ADMUX.MUX0 0 Analog Channel Select Bit 0 -; RESERVED0028 0x0028 RESERVED -; RESERVED0029 0x0029 RESERVED -; RESERVED002A 0x002A RESERVED -; RESERVED002B 0x002B RESERVED -; RESERVED002C 0x002C RESERVED -; RESERVED002D 0x002D RESERVED -; RESERVED002E 0x002E RESERVED -; RESERVED002F 0x002F RESERVED -; GIPR 0x0030 General Interrupt Pin Register -; GIPR.IPIN1 3 External Interrupt Pin 1 -; GIPR.IPIN0 2 External Interrupt Pin 0 -; RESERVED0031 0x0031 RESERVED -; RESERVED0032 0x0032 RESERVED -; RESERVED0033 0x0033 RESERVED -; RESERVED0034 0x0034 RESERVED -; RESERVED0035 0x0035 RESERVED -; RESERVED0036 0x0036 RESERVED -; RESERVED0037 0x0037 RESERVED -; RESERVED0038 0x0038 RESERVED -; RESERVED0039 0x0039 RESERVED -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 -; EEARL.EEAR6 6 -; EEARL.EEAR5 5 -; EEARL.EEAR4 4 -; EEARL.EEAR3 3 -; EEARL.EEAR2 2 -; EEARL.EEAR1 1 -; EEARL.EEAR0 0 -; EEARH 0x003F EEPROM Address Register High -; RESERVED0040 0x0040 RESERVED -; RESERVED0041 0x0041 RESERVED -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; RESERVED0044 0x0044 RESERVED -; RESERVED0045 0x0045 RESERVED -; RESERVED0046 0x0046 RESERVED -; RESERVED0047 0x0047 RESERVED -; RESERVED0048 0x0048 RESERVED -; RESERVED0049 0x0049 RESERVED -; RESERVED004A 0x004A RESERVED -; RESERVED004B 0x004B RESERVED -; TCNT1L 0x004C Timer/Counter1 Low -; TCNT1H 0x004D Timer/Counter1 High -; TCCR1 0x004E Timer/Counter1 Control Register -; TCCR1.CS12 2 Clock Select1, Bit 2 -; TCCR1.CS11 1 Clock Select1, Bit 1 -; TCCR1.CS10 0 Clock Select1, Bit 0 -; RESERVED004F 0x004F RESERVED -; RESERVED0050 0x0050 RESERVED -; RESERVED0051 0x0051 RESERVED -; TCNT0 0x0052 Timer Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; RESERVED0054 0x0054 RESERVED -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 6 Sleep Enable -; MCUCR.SM 5 Sleep Mode -; MCUCR.ISC1 2 Interrupt Sense Control 1 -; MCUCR.ISC0 0 Interrupt Sense Control 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED005C 0x005C RESERVED -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer Low -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.AT90S1200 -SUBARCH=1 -; doc0838.pdf -; - -RAM=0 -ROM=1024 -EEPROM=64 - - -; MEMORY MAP - - -; Interrupt and reset vector assignments - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -PIND 0x0010 Port D Input Pins Address -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pin Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.MSB 7 -EEDR.LSB 0 -EEAR 0x001E EEPROM Address Register -EEAR.EEAR5 5 EEPROM Address 5 -EEAR.EEAR4 4 EEPROM Address 4 -EEAR.EEAR3 3 EEPROM Address 3 -EEAR.EEAR2 2 EEPROM Address 2 -EEAR.EEAR1 1 EEPROM Address 1 -EEAR.EEAR0 0 EEPROM Address 0 -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -RESERVED002C 0x002C RESERVED -RESERVED002D 0x002D RESERVED -RESERVED002E 0x002E RESERVED -RESERVED002F 0x002F RESERVED -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer/Counter0 -TCNT0.MSB 7 -TCNT0.LSB 0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -RESERVED0034 0x0034 RESERVED -MCUCR 0x0035 MCU Control Register -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC01 1 Interrupt Sense Control Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt FLAG Register -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -RESERVED003A 0x003A RESERVED -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -RESERVED003D 0x003D RESERVED -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - - -.AT90S2313 -SUBARCH=2 -; doc0839.pdf -; - -RAM=128 -ROM=2048 -EEPROM=128 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0080 I/O registers -area DATA SRAM_ 0x0080:0x00E0 SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Processor reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_CAPT1 0x0003 Timer/Counter1 Capture Event -entry TIMER1_COMP1 0x0004 Timer/Counter1 Compare Match -entry TIMER1_OVF1 0x0005 Timer/Counter1 Overflow -entry TIMER0_OVF0 0x0006 Timer/Counter0 Overflow -entry UART_RX 0x0007 UART, RX Complete -entry UART_UDRE 0x0008 UART Data Register Empty -entry UART_TX 0x0009 UART, TX Complete -entry ANA_COMP 0x000A Analog Comparator - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR 0x0009 UART Baud Rate Register -UCR 0x000A UART Control Register -UCR.RXCIE 7 RX Complete Interrupt Enable -UCR.TXCIE 6 TX Complete Interrupt Enable -UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -UCR.RXEN 4 Receiver Enable -UCR.TXEN 3 Transmitter Enable -UCR.CHR9 2 9 Bit Characters -UCR.RXB8 1 Receive Data Bit 8 -UCR.TXB8 0 Transmit Data Bit 8 -USR 0x000B UART Status Register -USR.RXC 7 UART Receive Complete -USR.TXC 6 UART Transmit Complete -USR.UDRE 5 UART Data Register Empty -USR.FE 4 Framing Error -USR.OR 3 OverRun -UDR 0x000C The UART I/O Data Register -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -PIND 0x0010 Port D Input Pins Address -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEAR 0x001E EEPROM Address Register -EEAR.EEAR6 6 EEPROM Address 6 -EEAR.EEAR5 5 EEPROM Address 5 -EEAR.EEAR4 4 EEPROM Address 4 -EEAR.EEAR3 3 EEPROM Address 3 -EEAR.EEAR2 2 EEPROM Address 2 -EEAR.EEAR1 1 EEPROM Address 1 -EEAR.EEAR0 0 EEPROM Address 0 -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -ICR1L 0x0024 Timer/Counter1 Input Capture Register low -ICR1H 0x0025 Timer/Counter1 Input Capture Register high -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -OCR1AL 0x002A Timer/Counter1 Output Compare Register A low -OCR1AH 0x002B Timer/Counter1 Output Compare Register A high -TCNT1L 0x002C Timer/Counter1 low -TCNT1H 0x002D Timer/Counter1 high -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1 Bit 2 -TCCR1B.CS11 1 Clock Select1 Bit 1 -TCCR1B.CS10 0 Clock Select1 Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1, Bits 1 -TCCR1A.COM1A0 6 Compare Output Mode1, Bits 0 -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 11 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 10 -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -RESERVED0034 0x0034 RESERVED -MCUCR 0x0035 MCU Control Register -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC11 3 InterruptSense Control 1 Bit 1 -MCUCR.ISC10 2 InterruptSense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt FLAG Register -TIFR.TOV1 7 Timer/Counter1 Overflow Flag -TIFR.OCF1A 6 Output Compare Flag 1A -TIFR.ICF1 3 Input Capture Flag 1 -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Match Interrupt Enable -TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt FLAG Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; RESERVED0023 0x0023 RESERVED -; RESERVED0024 0x0024 RESERVED -; RESERVED0025 0x0025 RESERVED -; RESERVED0026 0x0026 RESERVED -; RESERVED0027 0x0027 RESERVED -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR 0x0029 UART Baud Rate Register -; UCR 0x002A UART Control Register -; UCR.RXCIE 7 RX Complete Interrupt Enable -; UCR.TXCIE 6 TX Complete Interrupt Enable -; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -; UCR.RXEN 4 Receiver Enable -; UCR.TXEN 3 Transmitter Enable -; UCR.CHR9 2 9 Bit Characters -; UCR.RXB8 1 Receive Data Bit 8 -; UCR.TXB8 0 Transmit Data Bit 8 -; USR 0x002B UART Status Register -; USR.RXC 7 UART Receive Complete -; USR.TXC 6 UART Transmit Complete -; USR.UDRE 5 UART Data Register Empty -; USR.FE 4 Framing Error -; USR.OR 3 OverRun -; UDR 0x002C The UART I/O Data Register -; RESERVED002D 0x002D RESERVED -; RESERVED002E 0x002E RESERVED -; RESERVED002F 0x002F RESERVED -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; RESERVED0033 0x0033 RESERVED -; RESERVED0034 0x0034 RESERVED -; RESERVED0035 0x0035 RESERVED -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; RESERVED0039 0x0039 RESERVED -; RESERVED003A 0x003A RESERVED -; RESERVED003B 0x003B RESERVED -; EECR 0x003C EEPROM Control Register -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEAR 0x003E EEPROM Address Register -; EEAR.EEAR6 6 EEPROM Address 6 -; EEAR.EEAR5 5 EEPROM Address 5 -; EEAR.EEAR4 4 EEPROM Address 4 -; EEAR.EEAR3 3 EEPROM Address 3 -; EEAR.EEAR2 2 EEPROM Address 2 -; EEAR.EEAR1 1 EEPROM Address 1 -; EEAR.EEAR0 0 EEPROM Address 0 -; RESERVED003F 0x003F RESERVED -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; ICR1L 0x0044 Timer/Counter1 Input Capture Register low -; ICR1H 0x0045 Timer/Counter1 Input Capture Register high -; RESERVED0046 0x0046 RESERVED -; RESERVED0047 0x0047 RESERVED -; RESERVED0048 0x0048 RESERVED -; RESERVED0049 0x0049 RESERVED -; OCR1AL 0x004A Timer/Counter1 Output Compare Register A low -; OCR1AH 0x004B Timer/Counter1 Output Compare Register A high -; TCNT1L 0x004C Timer/Counter1 low -; TCNT1H 0x004D Timer/Counter1 high -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1 Bit 2 -; TCCR1B.CS11 1 Clock Select1 Bit 1 -; TCCR1B.CS10 0 Clock Select1 Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1, Bits 1 -; TCCR1A.COM1A0 6 Compare Output Mode1, Bits 0 -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 11 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 10 -; RESERVED0050 0x0050 RESERVED -; RESERVED0051 0x0051 RESERVED -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; RESERVED0054 0x0054 RESERVED -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM 4 Sleep Mode -; MCUCR.ISC11 3 InterruptSense Control 1 Bit 1 -; MCUCR.ISC10 2 InterruptSense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt FLAG Register -; TIFR.TOV1 7 Timer/Counter1 Overflow Flag -; TIFR.OCF1A 6 Output Compare Flag 1A -; TIFR.ICF1 3 Input Capture Flag 1 -; TIFR.TOV0 1 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Match Interrupt Enable -; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt FLAG Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED005C 0x005C RESERVED -; SPL 0x005D Stack Pointer -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; RESERVED005E 0x005E RESERVED -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.AT90S2323_43 -SUBARCH=2 -; doc1004.pdf -; - -RAM=128 -ROM=2048 -EEPROM=128 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0080 I/O registers -area DATA SRAM_ 0x0080:0x00E0 SRAM - - -; Interrupt and reset vector assignments - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -RESERVED0008 0x0008 RESERVED -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -RESERVED0010 0x0010 RESERVED -RESERVED0011 0x0011 RESERVED -RESERVED0012 0x0012 RESERVED -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEAR 0x001E EEPROM Address Register -EEAR.EEAR6 6 EEPROM Address 6 -EEAR.EEAR5 5 EEPROM Address 5 -EEAR.EEAR4 4 EEPROM Address 4 -EEAR.EEAR3 3 EEPROM Address 3 -EEAR.EEAR2 2 EEPROM Address 2 -EEAR.EEAR1 1 EEPROM Address 1 -EEAR.EEAR0 0 EEPROM Address 0 -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -RESERVED002C 0x002C RESERVED -RESERVED002D 0x002D RESERVED -RESERVED002E 0x002E RESERVED -RESERVED002F 0x002F RESERVED -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0 Bit 2 -TCCR0.CS01 1 Clock Select0 Bit 1 -TCCR0.CS00 0 Clock Select0 Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt FLAG Register -TIFR.TOV0 1 Timer/Counter 0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE0 1 Timer/Counter 0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF0 6 External Interrupt Flag 0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; RESERVED0023 0x0023 RESERVED -; RESERVED0024 0x0024 RESERVED -; RESERVED0025 0x0025 RESERVED -; RESERVED0026 0x0026 RESERVED -; RESERVED0027 0x0027 RESERVED -; RESERVED0028 0x0028 RESERVED -; RESERVED0029 0x0029 RESERVED -; RESERVED002A 0x002A RESERVED -; RESERVED002B 0x002B RESERVED -; RESERVED002C 0x002C RESERVED -; RESERVED002D 0x002D RESERVED -; RESERVED002E 0x002E RESERVED -; RESERVED002F 0x002F RESERVED -; RESERVED0030 0x0010 RESERVED -; RESERVED0031 0x0031 RESERVED -; RESERVED0032 0x0032 RESERVED -; RESERVED0033 0x0033 RESERVED -; RESERVED0034 0x0034 RESERVED -; RESERVED0035 0x0035 RESERVED -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; RESERVED0039 0x0039 RESERVED -; RESERVED003A 0x003A RESERVED -; RESERVED003B 0x003B RESERVED -; EECR 0x003C EEPROM Control Register -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEAR 0x003E EEPROM Address Register -; EEAR.EEAR6 6 EEPROM Address 6 -; EEAR.EEAR5 5 EEPROM Address 5 -; EEAR.EEAR4 4 EEPROM Address 4 -; EEAR.EEAR3 3 EEPROM Address 3 -; EEAR.EEAR2 2 EEPROM Address 2 -; EEAR.EEAR1 1 EEPROM Address 1 -; EEAR.EEAR0 0 EEPROM Address 0 -; RESERVED003F 0x003F RESERVED -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; RESERVED0044 0x0044 RESERVED -; RESERVED0045 0x0045 RESERVED -; RESERVED0046 0x0046 RESERVED -; RESERVED0047 0x0047 RESERVED -; RESERVED0048 0x0048 RESERVED -; RESERVED0049 0x0049 RESERVED -; RESERVED004A 0x004A RESERVED -; RESERVED004B 0x004B RESERVED -; RESERVED004C 0x004C RESERVED -; RESERVED004D 0x004D RESERVED -; RESERVED004E 0x004E RESERVED -; RESERVED004F 0x004F RESERVED -; RESERVED0050 0x0050 RESERVED -; RESERVED0051 0x0051 RESERVED -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.CS02 2 Clock Select0 Bit 2 -; TCCR0.CS01 1 Clock Select0 Bit 1 -; TCCR0.CS00 0 Clock Select0 Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM 4 Sleep Mode -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt FLAG Register -; TIFR.TOV0 1 Timer/Counter 0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE0 1 Timer/Counter 0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED005C 0x005C RESERVED -; SPL 0x005D Stack Pointer -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; RESERVED005E 0x005E RESERVED -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.AT90S8515 -SUBARCH=2 -; doc0841.pdf -; - -RAM=512 -ROM=8192 -EEPROM=512 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0060 I/O registers -area DATA I_SRAM 0x0060:0x0260 Internal SRAM -area DATA E_SRAM 0x0260:0x10000 External SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Reset, Power-on Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0005 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0006 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0007 Timer/Counter0 Overflow -entry SPI_STC 0x0008 Serial Transfer Complete -entry UART_RX 0x0009 UART, Rx Complete -entry UART_UDRE 0x000A UART Data Register Empty -entry UART_TX 0x000B UART, Tx Complete -entry ANA_COMP 0x000C Analog Comparator - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR 0x0009 UART BAUD Rate Register -UCR 0x000A UART Control Register -UCR.RXCIE 7 RX Complete Interrupt Enable -UCR.TXCIE 6 TX Complete Interrupt Enable -UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -UCR.RXEN 4 Receiver Enable -UCR.TXEN 3 Transmitter Enable -UCR.CHR9 2 9-bit Characters -UCR.RXB8 1 Receive Data Bit 8 -UCR.TXB8 0 Transmit Data Bit 8 -USR 0x000B UART Status Register -USR.RXC 7 UART Receive Complete -USR.TXC 6 UART Transmit Complete -USR.UDRE 5 UART Data Register Empty -USR.FE 4 Framing Error -USR.OR 3 Overrun -UDR 0x000C UART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write Collision Flag -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 -EEARL.EEAR6 6 -EEARL.EEAR5 5 -EEARL.EEAR4 4 -EEARL.EEAR3 3 -EEARL.EEAR2 2 -EEARL.EEAR1 1 -EEARL.EEAR0 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR8 8 -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -ICR1L 0x0024 Timer/Counter1 Input Capture Register Low -ICR1H 0x0025 Timer/Counter1 Input Capture Register High -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -OCR1BL 0x0028 Timer/Counter1 Output Compare Register Low -OCR1BH 0x0029 Timer/Counter1 Output Compare Register High -OCR1AL 0x002A Timer/Counter1 Output Compare Register Low -OCR1AH 0x002B Timer/Counter1 Output Compare Register High -TCNT1L 0x002C Timer/Counter1 Low -TCNT1H 0x002D Timer/Counter1 High -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1, Bit 2 -TCCR1B.CS11 1 Clock Select1, Bit 1 -TCCR1B.CS10 0 Clock Select1, Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -RESERVED0034 0x0034 RESERVED -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM Enable -MCUCR.SRW 6 External SRAM Wait State -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC11 3 Interrupt Sense Control 1, Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1, Bit -MCUCR.ISC01 1 Interrupt Sense Control 0, Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0, Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter1 Overflow Flag -TIFR.OCF1A 6 Output Compare Flag 1A -TIFR.OCIFB 5 Output Compare Flag 1B -TIFR.ICF1 3 Input Capture Flag 1 -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable -TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag1 -GIFR.INTF0 6 External Interrupt Flag0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; RESERVED0023 0x0023 RESERVED -; RESERVED0024 0x0024 RESERVED -; RESERVED0025 0x0025 RESERVED -; RESERVED0026 0x0026 RESERVED -; RESERVED0027 0x0027 RESERVED -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR 0x0029 UART BAUD Rate Register -; UCR 0x002A UART Control Register -; UCR.RXCIE 7 RX Complete Interrupt Enable -; UCR.TXCIE 6 TX Complete Interrupt Enable -; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -; UCR.RXEN 4 Receiver Enable -; UCR.TXEN 3 Transmitter Enable -; UCR.CHR9 2 9-bit Characters -; UCR.RXB8 1 Receive Data Bit 8 -; UCR.TXB8 0 Transmit Data Bit 8 -; USR 0x002B UART Status Register -; USR.RXC 7 UART Receive Complete -; USR.TXC 6 UART Transmit Complete -; USR.UDRE 5 UART Data Register Empty -; USR.FE 4 Framing Error -; USR.OR 3 Overrun -; UDR 0x002C UART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write Collision Flag -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 -; EEARL.EEAR6 6 -; EEARL.EEAR5 5 -; EEARL.EEAR4 4 -; EEARL.EEAR3 3 -; EEARL.EEAR2 2 -; EEARL.EEAR1 1 -; EEARL.EEAR0 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR8 8 -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; ICR1L 0x0044 Timer/Counter1 Input Capture Register Low -; ICR1H 0x0045 Timer/Counter1 Input Capture Register High -; RESERVED0046 0x0046 RESERVED -; RESERVED0047 0x0047 RESERVED -; OCR1BL 0x0048 Timer/Counter1 Output Compare Register Low -; OCR1BH 0x0049 Timer/Counter1 Output Compare Register High -; OCR1AL 0x004A Timer/Counter1 Output Compare Register Low -; OCR1AH 0x004B Timer/Counter1 Output Compare Register High -; TCNT1L 0x004C Timer/Counter1 Low -; TCNT1H 0x004D Timer/Counter1 High -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1, Bit 2 -; TCCR1B.CS11 1 Clock Select1, Bit 1 -; TCCR1B.CS10 0 Clock Select1, Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; RESERVED0050 0x0050 RESERVED -; RESERVED0051 0x0051 RESERVED -; TCNT0 0x0052 Timer Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; RESERVED0054 0x0054 RESERVED -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM Enable -; MCUCR.SRW 6 External SRAM Wait State -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM 4 Sleep Mode -; MCUCR.ISC11 3 Interrupt Sense Control 1, Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1, Bit -; MCUCR.ISC01 1 Interrupt Sense Control 0, Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0, Bit 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.TOV1 7 Timer/Counter1 Overflow Flag -; TIFR.OCF1A 6 Output Compare Flag 1A -; TIFR.OCIFB 5 Output Compare Flag 1B -; TIFR.ICF1 3 Input Capture Flag 1 -; TIFR.TOV0 1 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable -; TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable -; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag1 -; GIFR.INTF0 6 External Interrupt Flag0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED005C 0x005C RESERVED -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.AT90S_L4433 -SUBARCH=2 -; doc1042.pdf -; - -RAM=128 -ROM=4096 -EEPROM=256 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0080 I/O registers -area DATA SRAM_ 0x0080:0x00E0 SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event -entry TIMER1_COMP 0x0004 Timer/Counter1 Compare Match -entry TIMER1_OVF 0x0005 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0006 Timer/Counter0 Overflow -entry SPI_STC 0x0007 Serial Transfer Complete -entry UART_RX 0x0008 UART, Rx Complete -entry UART_UDRE 0x0009 UART Data Register Empty -entry UART_TX 0x000A UART, Tx Complete -entry ADC_ 0x000B ADC Conversion Complete -entry EE_RDY 0x000C EEPROM Ready -entry ANA_COMP 0x000D Analog Comparator - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -UBRRHI 0x0003 UART Baud Rate Register High -ADCL 0x0004 ADC Data Register low -ADCL.ADC7 7 -ADCL.ADC6 6 -ADCL.ADC5 5 -ADCL.ADC4 4 -ADCL.ADC3 3 -ADCL.ADC2 2 -ADCL.ADC1 1 -ADCL.ADC0 0 -ADCH 0x0005 ADC Data Register high -ADCH.ADC9 9 -ADCH.ADC8 8 -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Run Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Select Register -ADMUX.ADCBG 6 ADC Bandgap Select -ADMUX.MUX2 2 Analog Channel Select Bit 2 -ADMUX.MUX1 1 Analog Channel Select Bit 1 -ADMUX.MUX0 0 Analog Channel Select Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.AINBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR 0x0009 UART Baud Rate Register Low -UCSRB 0x000A UART Control and Status Register -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.CHR9 2 9-bit Characters -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B UART Control and Status Register A -UCSRA.RXC 7 UART Receive Complete -UCSRA.TXC 6 UART Transmit Complete -UCSRA.UDRE 5 UART Data Register Empty -UCSRA.FE 4 Framing Error -UCSRA.OR 3 OverRun -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C UART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write Collision Flag -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEAR 0x001E EEPROM Address Register -EEAR.EEAR7 7 -EEAR.EEAR6 6 -EEAR.EEAR5 5 -EEAR.EEAR4 4 -EEAR.EEAR3 3 -EEAR.EEAR2 2 -EEAR.EEAR1 1 -EEAR.EEAR0 0 -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -ICR1L 0x0026 Timer/Counter1 Input Capture Register Low -ICR1H 0x0027 Timer/Counter1 Input Capture Register High -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -OCR1L 0x002A Timer/Counter1 Output Compare Register Low -OCR1H 0x002B Timer/Counter1 Output Compare Register High -TCNT1L 0x002C Timer/Counter1 Low -TCNT1H 0x002D Timer/Counter1 High -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1 Bit 2 -TCCR1B.CS11 1 Clock Select1 Bit 1 -TCCR1B.CS10 0 Clock Select1 Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM11 7 Compare Output Mode1, Bit 1 -TCCR1A.COM10 6 Compare Output Mode1, Bit 0 -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer Counter 0 -TCCR0 0x0033 Timer/Counter 0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.WDRF 3 Watchdog Reset Flag -MCUSR.BORF 2 Brown-out Reset Flag -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter 1 Overflow Flag -TIFR.OCF1 6 Output Compare Flag 1 -TIFR.ICF1 3 Input Capture Flag 1 -TIFR.TOV0 1 Timer/Counter 0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -TIMSK.OCIE1 6 Timer/Counter1 Output Compare Match Interrupt Enable -TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SP 0x003D Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; UBRRHI 0x0023 UART Baud Rate Register High -; ADCL 0x0024 ADC Data Register low -; ADCL.ADC7 7 -; ADCL.ADC6 6 -; ADCL.ADC5 5 -; ADCL.ADC4 4 -; ADCL.ADC3 3 -; ADCL.ADC2 2 -; ADCL.ADC1 1 -; ADCL.ADC0 0 -; ADCH 0x0025 ADC Data Register high -; ADCH.ADC8 8 -; ADCH.ADC9 9 -; ADCSR 0x0026 ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADFR 5 ADC Free Run Select -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Select Register -; ADMUX.ADCBG 6 ADC Bandgap Select -; ADMUX.MUX2 2 Analog Channel Select Bit 2 -; ADMUX.MUX1 1 Analog Channel Select Bit 1 -; ADMUX.MUX0 0 Analog Channel Select Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.AINBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR 0x0029 UART Baud Rate Register Low -; UCSRB 0x002A UART Control and Status Register -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.CHR9 2 9-bit Characters -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B UART Control and Status Register A -; UCSRA.RXC 7 UART Receive Complete -; UCSRA.TXC 6 UART Transmit Complete -; UCSRA.UDRE 5 UART Data Register Empty -; UCSRA.FE 4 Framing Error -; UCSRA.OR 3 OverRun -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C UART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write Collision Flag -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; RESERVED0039 0x0039 RESERVED -; RESERVED003A 0x003A RESERVED -; RESERVED003B 0x003B RESERVED -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEAR 0x003E EEPROM Address Register -; EEAR.EEAR7 7 -; EEAR.EEAR6 6 -; EEAR.EEAR5 5 -; EEAR.EEAR4 4 -; EEAR.EEAR3 3 -; EEAR.EEAR2 2 -; EEAR.EEAR1 1 -; EEAR.EEAR0 0 -; RESERVED003F 0x003F RESERVED -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; RESERVED0044 0x0044 RESERVED -; RESERVED0045 0x0045 RESERVED -; ICR1L 0x0046 Timer/Counter1 Input Capture Register Low -; ICR1H 0x0047 Timer/Counter1 Input Capture Register High -; RESERVED0048 0x0048 RESERVED -; RESERVED0049 0x0049 RESERVED -; OCR1L 0x004A Timer/Counter1 Output Compare Register Low -; OCR1H 0x004B Timer/Counter1 Output Compare Register High -; TCNT1L 0x004C Timer/Counter1 Low -; TCNT1H 0x004D Timer/Counter1 High -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1 Bit 2 -; TCCR1B.CS11 1 Clock Select1 Bit 1 -; TCCR1B.CS10 0 Clock Select1 Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM11 7 Compare Output Mode1, Bit 1 -; TCCR1A.COM10 6 Compare Output Mode1, Bit 0 -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; RESERVED0050 0x0050 RESERVED -; RESERVED0051 0x0051 RESERVED -; TCNT0 0x0052 Timer Counter 0 -; TCCR0 0x0053 Timer/Counter 0 Control Register -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.WDRF 3 Watchdog Reset Flag -; MCUSR.BORF 2 Brown-out Reset Flag -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM 4 Sleep Mode -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.TOV1 7 Timer/Counter 1 Overflow Flag -; TIFR.OCF1 6 Output Compare Flag 1 -; TIFR.ICF1 3 Input Capture Flag 1 -; TIFR.TOV0 1 Timer/Counter 0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.OCIE1 6 Timer/Counter1 Output Compare Match Interrupt Enable -; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED005C 0x005C RESERVED -; SP 0x005D Stack Pointer -; SP.SP7 7 -; SP.SP6 6 -; SP.SP5 5 -; SP.SP4 4 -; SP.SP3 3 -; SP.SP2 2 -; SP.SP1 1 -; SP.SP0 0 -; RESERVED005E 0x005E RESERVED -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.AT90S_LS8535 -SUBARCH=2 -; doc1041.pdf -; - -RAM=512 -ROM=8192 -EEPROM=512 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0060 I/O registers -area DATA SRAM_ 0x0060:0x0260 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER2_COMP 0x0003 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0004 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0005 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0006 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0007 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0008 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0009 Timer/Counter0 Overflow -entry SPI_STC 0x000A SPI Serial Transfer Complete -entry UART_RX 0x000B UART, Rx Complete - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -ADCL 0x0004 ADC Data Register Low -ADCL.ADC7 7 Conversion result 7 -ADCL.ADC6 6 Conversion result 6 -ADCL.ADC5 5 Conversion result 5 -ADCL.ADC4 4 Conversion result 4 -ADCL.ADC3 3 Conversion result 3 -ADCL.ADC2 2 Conversion result 2 -ADCL.ADC1 1 Conversion result 1 -ADCL.ADC0 0 Conversion result 0 -ADCH 0x0005 ADC Data Register High -ADCH.ADC8 8 Conversion result 8 -ADCH.ADC9 9 Conversion result 9 -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Running Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Select Register -ADMUX.MUX2 2 Analog Channel Select Bit 2 -ADMUX.MUX1 1 Analog Channel Select Bit 1 -ADMUX.MUX0 0 Analog Channel Select Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR 0x0009 UART Baud Rate Register -UCR 0x000A UART Control Register -UCR.RXCIE 7 RX Complete Interrupt Enable -UCR.TXCIE 6 TX Complete Interrupt Enable -UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -UCR.RXEN 4 Receiver Enable -UCR.TXEN 3 Transmitter Enable -UCR.CHR9 2 9 Bit Characters -UCR.RXB8 1 Receive Data Bit 8 -UCR.TXB8 0 Transmit Data Bit 8 -USR 0x000B UART Status Register -USR.RXC 7 UART Receive Complete -USR.TXC 6 UART Transmit Complete -USR.UDRE 5 UART Data Register Empty -USR.FE 4 Framing Error -USR.OR 3 OverRun -UDR 0x000C UART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write Collision flag -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARH 0x001F EEPROM Address Register High -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -OCR2 0x0023 Timer/Counter2 Output Compare Register -TCNT2 0x0024 Timer/Counter2 -TCCR2 0x0025 Timer/Counter2 Control Register -TCCR2.PWM2 6 Pulse Width Modulator Enable -TCCR2.COM21 5 Compare Output Mode, Bits 1 -TCCR2.COM20 4 Compare Output Mode, Bits 0 -TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -TCCR2.CS22 2 Clock Select Bit 2 -TCCR2.CS21 1 Clock Select Bit 1 -TCCR2.CS20 0 Clock Select Bit 0 -ICR1L 0x0026 Timer/Counter1 Input Capture Register Low -ICR1H 0x0027 Timer/Counter1 Input Capture Register High -OCR1BL 0x0028 Timer/Counter1 Output Compare Register Low -OCR1BH 0x0029 Timer/Counter1 Output Compare Register High -OCR1AL 0x002A Timer/Counter1 Output Compare Register Low -OCR1AH 0x002B Timer/Counter1 Output Compare Register High -TCNT1L 0x002C Timer/Counter1 Low -TCNT1H 0x002D Timer/Counter1 High -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1, Bit 2 -TCCR1B.CS11 1 Clock Select1, Bit 1 -TCCR1B.CS10 0 Clock Select1, Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer Counter 0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 6 Sleep Enable -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Input Capture Flag 1 -TIFR.OCF1A 4 Output Compare Flag 1A -TIFR.OCF1B 3 Output Compare Flag 1B -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag1 -GIFR.INTF0 6 External Interrupt Flag0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; RESERVED0023 0x0023 RESERVED -; ADCL 0x0024 ADC Data Register Low -; ADCL.ADC7 7 Conversion result 7 -; ADCL.ADC6 6 Conversion result 6 -; ADCL.ADC5 5 Conversion result 5 -; ADCL.ADC4 4 Conversion result 4 -; ADCL.ADC3 3 Conversion result 3 -; ADCL.ADC2 2 Conversion result 2 -; ADCL.ADC1 1 Conversion result 1 -; ADCL.ADC0 0 Conversion result 0 -; ADCH 0x0025 ADC Data Register High -; ADCH.ADC8 8 Conversion result 8 -; ADCH.ADC9 9 Conversion result 9 -; ADCSR 0x0026 ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADFR 5 ADC Free Running Select -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Select Register -; ADMUX.MUX2 2 Analog Channel Select Bit 2 -; ADMUX.MUX1 1 Analog Channel Select Bit 1 -; ADMUX.MUX0 0 Analog Channel Select Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR 0x0029 UART Baud Rate Register -; UCR 0x002A UART Control Register -; UCR.RXCIE 7 RX Complete Interrupt Enable -; UCR.TXCIE 6 TX Complete Interrupt Enable -; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -; UCR.RXEN 4 Receiver Enable -; UCR.TXEN 3 Transmitter Enable -; UCR.CHR9 2 9 Bit Characters -; UCR.RXB8 1 Receive Data Bit 8 -; UCR.TXB8 0 Transmit Data Bit 8 -; USR 0x002B UART Status Register -; USR.RXC 7 UART Receive Complete -; USR.TXC 6 UART Transmit Complete -; USR.UDRE 5 UART Data Register Empty -; USR.FE 4 Framing Error -; USR.OR 3 OverRun -; UDR 0x002C UART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write Collision flag -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARH 0x003F EEPROM Address Register High -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; OCR2 0x0043 Timer/Counter2 Output Compare Register -; TCNT2 0x0044 Timer/Counter2 -; TCCR2 0x0045 Timer/Counter2 Control Register -; TCCR2.PWM2 6 Pulse Width Modulator Enable -; TCCR2.COM21 5 Compare Output Mode, Bits 1 -; TCCR2.COM20 4 Compare Output Mode, Bits 0 -; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -; TCCR2.CS22 2 Clock Select Bit 2 -; TCCR2.CS21 1 Clock Select Bit 1 -; TCCR2.CS20 0 Clock Select Bit 0 -; ICR1L 0x0046 Timer/Counter1 Input Capture Register Low -; ICR1H 0x0047 Timer/Counter1 Input Capture Register High -; OCR1BL 0x0048 Timer/Counter1 Output Compare Register Low -; OCR1BH 0x0049 Timer/Counter1 Output Compare Register High -; OCR1AL 0x004A Timer/Counter1 Output Compare Register Low -; OCR1AH 0x004B Timer/Counter1 Output Compare Register High -; TCNT1L 0x004C Timer/Counter1 Low -; TCNT1H 0x004D Timer/Counter1 High -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1, Bit 2 -; TCCR1B.CS11 1 Clock Select1, Bit 1 -; TCCR1B.CS10 0 Clock Select1, Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; RESERVED0050 0x0050 RESERVED -; RESERVED0051 0x0051 RESERVED -; TCNT0 0x0052 Timer Counter 0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 6 Sleep Enable -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Input Capture Flag 1 -; TIFR.OCF1A 4 Output Compare Flag 1A -; TIFR.OCF1B 3 Output Compare Flag 1B -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag1 -; GIFR.INTF0 6 External Interrupt Flag0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED003C 0x005C RESERVED -; SPL 0x005D Stack Pointer -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega103_L -SUBARCH=31 -; doc0945.pdf -; - -RAM=4096 -ROM=131072 -EEPROM=4096 - - -; MEMORY MAP -; Memory Configuration A -area DATA FSR_ 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x1000 Internal SRAM -; Memory Configuration B -; area DATA FSR_ 0x0000:0x0060 -; area DATA I_SRAM 0x0060:0x1000 Internal SRAM -; area DATA E_SRAM 0x1000:0x10000 External SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry INT3_ 0x0008 External Interrupt Request 3 -entry INT4_ 0x000A External Interrupt Request 4 -entry INT5_ 0x000C External Interrupt Request 5 -entry INT6_ 0x000E External Interrupt Request 6 -entry INT7_ 0x0010 External Interrupt Request 7 -entry TIMER2_COMP 0x0012 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0014 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0016 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0018 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x001A Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x001C Timer/Counter1 Overflow -entry TIMER0_COMP 0x001E Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow -entry SPI_STC 0x0022 SPI Serial Transfer Complete -entry UART_RX 0x0024 UART, Rx Complete -entry UART_UDRE 0x0026 UART Data Register Empty -entry UART_TX 0x0028 UART, Tx Complete -entry ADC_ 0x002A ADC Conversion Complete -entry EE_READY 0x002C EEPROM Ready -entry ANALOG_COMP 0x002E Analog Comparator - - -; INPUT/OUTPUT PORTS -PINF 0x0000 Port F Input Pins Address -PINF.PINF7 7 -PINF.PINF6 6 -PINF.PINF5 5 -PINF.PINF4 4 -PINF.PINF3 3 -PINF.PINF2 2 -PINF.PINF1 1 -PINF.PINF0 0 -PINE 0x0001 Port E Input Pins Address -PINE.PINE7 7 -PINE.PINE6 6 -PINE.PINE5 5 -PINE.PINE4 4 -PINE.PINE3 3 -PINE.PINE2 2 -PINE.PINE1 1 -PINE.PINE0 0 -DDRE 0x0002 Port E Data Direction Register -DDRE.DDE7 7 Port E Data Direction Register bit 7 -DDRE.DDE6 6 Port E Data Direction Register bit 6 -DDRE.DDE5 5 Port E Data Direction Register bit 5 -DDRE.DDE4 4 Port E Data Direction Register bit 4 -DDRE.DDE3 3 Port E Data Direction Register bit 3 -DDRE.DDE2 2 Port E Data Direction Register bit 2 -DDRE.DDE1 1 Port E Data Direction Register bit 1 -DDRE.DDE0 0 Port E Data Direction Register bit 0 -PORTE 0x0003 Port E Data Register -PORTE.PORTE7 7 Port E Data Register bit 7 -PORTE.PORTE6 6 Port E Data Register bit 6 -PORTE.PORTE5 5 Port E Data Register bit 5 -PORTE.PORTE4 4 Port E Data Register bit 4 -PORTE.PORTE3 3 Port E Data Register bit 3 -PORTE.PORTE2 2 Port E Data Register bit 2 -PORTE.PORTE1 1 Port E Data Register bit 1 -PORTE.PORTE0 0 Port E Data Register bit 0 -ADCL 0x0004 ADC Data Register Low -ADCL.ADC7 7 -ADCL.ADC6 6 -ADCL.ADC5 5 -ADCL.ADC4 4 -ADCL.ADC3 3 -ADCL.ADC2 2 -ADCL.ADC1 1 -ADCL.ADC0 0 -ADCH 0x0005 ADC Data Register High -ADCH.ADC9 9 -ADCH.ADC8 8 -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Select Register -ADMUX.MUX2 2 Analog Channel Select Bit 2 -ADMUX.MUX1 1 Analog Channel Select Bit 1 -ADMUX.MUX0 0 Analog Channel Select Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 6 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR 0x0009 UART Baud Rate Register -UCR 0x000A UART Control Register -UCR.RXCIE 7 RX Complete Interrupt Enable -UCR.TXCIE 6 TX Complete Interrupt Enable -UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -UCR.RXEN 4 Receiver Enable -UCR.TXEN 3 Transmitter Enable -UCR.CHR9 2 9-bit Characters -UCR.RXB8 1 Receive Data Bit 8 -UCR.TXB8 0 Transmit Data Bit 8 -USR 0x000B UART Status Register -USR.RXC 7 UART Receive Complete -USR.TXC 6 UART Transmit Complete -USR.UDRE 5 UART Data Register Empty -USR.FE 4 Framing Error -USR.OR 3 OverRun -UDR 0x000C UART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write Collision Flag -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -PORTC 0x0015 The Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 -EEARL.EEAR6 6 -EEARL.EEAR5 5 -EEARL.EEAR4 4 -EEARL.EEAR3 3 -EEARL.EEAR2 2 -EEARL.EEAR1 1 -EEARL.EEAR0 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR11 11 -EEARH.EEAR10 10 -EEARH.EEAR9 9 -EEARH.EEAR8 8 -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -OCR2 0x0023 Timer/Counter2 Output Compare Register -TCNT2 0x0024 Timer/Counter2 -TCCR2 0x0025 Timer/Counter2 Control Register -TCCR2.PWM2 6 Pulse Width Modulator Enable -TCCR2.COM21 5 Compare Output Mode, Bit 1 -TCCR2.COM20 4 Compare Output Mode, Bits0 -TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -TCCR2.CS22 2 Clock Select Bit 2 -TCCR2.CS21 1 Clock Select Bit 1 -TCCR2.CS20 0 Clock Select Bit 0 -ICR1L 0x0026 Timer/Counter1 Input Capture Register Low -ICR1H 0x0027 Timer/Counter1 Input Capture Register High -OCR1BL 0x0028 Timer/Counter1 Output Compare Register Low -OCR1BH 0x0029 Timer/Counter1 Output Compare Register High -OCR1AL 0x002A Timer/Counter1 Output Compare Register Low -OCR1AH 0x002B Timer/Counter1 Output Compare Register High -TCNT1L 0x002C Timer/Counter1 Low -TCNT1H 0x002D Timer/Counter1 High -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1, Bit 2 -TCCR1B.CS11 1 Clock Select1, Bit 1 -TCCR1B.CS10 0 Clock Select1, Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -ASSR 0x0030 Asynchronous Status Register -ASSR.AS0 3 Asynchronous Timer/Counter0 -ASSR.TCN0UB 2 Timer/Counter0 Update Busy -ASSR.OCR0UB 1 Output Compare Register0 Update Busy -ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy -OCR0 0x0031 Timer/Counter0 Output Compare Register -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.PWM0 6 Pulse Width Modulator Enable -TCCR0.COM01 5 Compare Output Mode, Bit 1 -TCCR0.COM00 4 Compare Output Mode, Bit 0 -TCCR0.CTC0 3 Clear Timer/Counter on Compare Match -TCCR0.CS02 2 Clock Select Bit 2 -TCCR0.CS01 1 Clock Select Bit 1 -TCCR0.CS00 0 Clock Select Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM Enable -MCUCR.SRW 6 External SRAM Wait State -MCUCR.SE 5 Sleep Enable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.SM0 3 Sleep Mode Select Bit 0 -TIFR 0x0036 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Input Capture Flag 1 -TIFR.OCF1A 4 Output Compare Flag 1A -TIFR.OCF1B 3 Output Compare Flag 1B -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0037 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -TIMSK.OCIE0 1 Timer/Counter0 Output Compare Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -EIFR 0x0038 External Interrupt Flag Register -EIFR.INTF7 7 External Interrupt 7 Flag -EIFR.INTF6 6 External Interrupt 6 Flag -EIFR.INTF5 5 External Interrupt 5 Flag -EIFR.INTF4 4 External Interrupt 4 Flag -EIMSK 0x0039 External Interrupt Mask Register -EIMSK.INT7 7 External Interrupt Request 7 Enable -EIMSK.INT6 6 External Interrupt Request 6 Enable -EIMSK.INT5 5 External Interrupt Request 5 Enable -EIMSK.INT4 4 External Interrupt Request 4 Enable -EIMSK.INT3 3 External Interrupt Request 3 Enable -EIMSK.INT2 2 External Interrupt Request 2 Enable -EIMSK.INT1 1 External Interrupt Request 1 Enable -EIMSK.INT0 0 External Interrupt Request 0 Enable -EICR 0x003A External Interrupt Control Register -EICR.ISC71 7 External Interrupt 7 Sense Control Bit 1 -EICR.ISC70 6 External Interrupt 7 Sense Control Bit 0 -EICR.ISC61 5 External Interrupt 6 Sense Control Bit 1 -EICR.ISC60 4 External Interrupt 6 Sense Control Bit 0 -EICR.ISC51 3 External Interrupt 5 Sense Control Bit 1 -EICR.ISC50 2 External Interrupt 5 Sense Control Bit 0 -EICR.ISC41 1 External Interrupt 4 Sense Control Bit 1 -EICR.ISC40 0 External Interrupt 4 Sense Control Bit 0 -RAMPZ 0x003B RAM Page Z Select Register -RAMPZ.RAMPZ0 0 -XDIV 0x003C XTAL Divide Control Register -XDIV.XDIVEN 7 XTAL Divide Enable -XDIV.XDIV6 6 XTAL Divide Select Bit 6 -XDIV.XDIV5 5 XTAL Divide Select Bit 5 -XDIV.XDIV4 4 XTAL Divide Select Bit 4 -XDIV.XDIV3 3 XTAL Divide Select Bit 3 -XDIV.XDIV2 2 XTAL Divide Select Bit 2 -XDIV.XDIV1 1 XTAL Divide Select Bit 1 -XDIV.XDIV0 0 XTAL Divide Select Bit 0 -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half-carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; PINF 0x0020 Port F Input Pins Address -; PINF.PINF7 7 -; PINF.PINF6 6 -; PINF.PINF5 5 -; PINF.PINF4 4 -; PINF.PINF3 3 -; PINF.PINF2 2 -; PINF.PINF1 1 -; PINF.PINF0 0 -; PINE 0x0021 Port E Input Pins Address -; PINE.PINE7 7 -; PINE.PINE6 6 -; PINE.PINE5 5 -; PINE.PINE4 4 -; PINE.PINE3 3 -; PINE.PINE2 2 -; PINE.PINE1 1 -; PINE.PINE0 0 -; DDRE 0x0022 Port E Data Direction Register -; DDRE.DDE7 7 Port E Data Direction Register bit 7 -; DDRE.DDE6 6 Port E Data Direction Register bit 6 -; DDRE.DDE5 5 Port E Data Direction Register bit 5 -; DDRE.DDE4 4 Port E Data Direction Register bit 4 -; DDRE.DDE3 3 Port E Data Direction Register bit 3 -; DDRE.DDE2 2 Port E Data Direction Register bit 2 -; DDRE.DDE1 1 Port E Data Direction Register bit 1 -; DDRE.DDE0 0 Port E Data Direction Register bit 0 -; PORTE 0x0023 Port E Data Register -; PORTE.PORTE7 7 Port E Data Register bit 7 -; PORTE.PORTE6 6 Port E Data Register bit 6 -; PORTE.PORTE5 5 Port E Data Register bit 5 -; PORTE.PORTE4 4 Port E Data Register bit 4 -; PORTE.PORTE3 3 Port E Data Register bit 3 -; PORTE.PORTE2 2 Port E Data Register bit 2 -; PORTE.PORTE1 1 Port E Data Register bit 1 -; PORTE.PORTE0 0 Port E Data Register bit 0 -; ADCL 0x0024 ADC Data Register Low -; ADCL.ADC7 7 -; ADCL.ADC6 6 -; ADCL.ADC5 5 -; ADCL.ADC4 4 -; ADCL.ADC3 3 -; ADCL.ADC2 2 -; ADCL.ADC1 1 -; ADCL.ADC0 0 -; ADCH 0x0025 ADC Data Register High -; ADCH.ADC9 9 -; ADCH.ADC8 8 -; ADCSR 0x0026 ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Select Register -; ADMUX.MUX2 2 Analog Channel Select Bit 2 -; ADMUX.MUX1 1 Analog Channel Select Bit 1 -; ADMUX.MUX0 0 Analog Channel Select Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACO 6 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR 0x0029 UART Baud Rate Register -; UCR 0x002A UART Control Register -; UCR.RXCIE 7 RX Complete Interrupt Enable -; UCR.TXCIE 6 TX Complete Interrupt Enable -; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable -; UCR.RXEN 4 Receiver Enable -; UCR.TXEN 3 Transmitter Enable -; UCR.CHR9 2 9-bit Characters -; UCR.RXB8 1 Receive Data Bit 8 -; UCR.TXB8 0 Transmit Data Bit 8 -; USR 0x002B UART Status Register -; USR.RXC 7 UART Receive Complete -; USR.TXC 6 UART Transmit Complete -; USR.UDRE 5 UART Data Register Empty -; USR.FE 4 Framing Error -; USR.OR 3 OverRun -; UDR 0x002C UART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write Collision Flag -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; RESERVED0033 0x0033 RESERVED -; RESERVED0034 0x0034 RESERVED -; PORTC 0x0035 The Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 -; EEARL.EEAR6 6 -; EEARL.EEAR5 5 -; EEARL.EEAR4 4 -; EEARL.EEAR3 3 -; EEARL.EEAR2 2 -; EEARL.EEAR1 1 -; EEARL.EEAR0 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR11 11 -; EEARH.EEAR10 10 -; EEARH.EEAR9 9 -; EEARH.EEAR8 8 -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; OCR2 0x0043 Timer/Counter2 Output Compare Register -; TCNT2 0x0044 Timer/Counter2 -; TCCR2 0x0045 Timer/Counter2 Control Register -; TCCR2.PWM2 6 Pulse Width Modulator Enable -; TCCR2.COM21 5 Compare Output Mode, Bit 1 -; TCCR2.COM20 4 Compare Output Mode, Bits0 -; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -; TCCR2.CS22 2 Clock Select Bit 2 -; TCCR2.CS21 1 Clock Select Bit 1 -; TCCR2.CS20 0 Clock Select Bit 0 -; ICR1L 0x0046 Timer/Counter1 Input Capture Register Low -; ICR1H 0x0047 Timer/Counter1 Input Capture Register High -; OCR1BL 0x0048 Timer/Counter1 Output Compare Register Low -; OCR1BH 0x0049 Timer/Counter1 Output Compare Register High -; OCR1AL 0x004A Timer/Counter1 Output Compare Register Low -; OCR1AH 0x004B Timer/Counter1 Output Compare Register High -; TCNT1L 0x004C Timer/Counter1 Low -; TCNT1H 0x004D Timer/Counter1 High -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1, Bit 2 -; TCCR1B.CS11 1 Clock Select1, Bit 1 -; TCCR1B.CS10 0 Clock Select1, Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; ASSR 0x0050 Asynchronous Status Register -; ASSR.AS0 3 Asynchronous Timer/Counter0 -; ASSR.TCN0UB 2 Timer/Counter0 Update Busy -; ASSR.OCR0UB 1 Output Compare Register0 Update Busy -; ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy -; OCR0 0x0051 Timer/Counter0 Output Compare Register -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.PWM0 6 Pulse Width Modulator Enable -; TCCR0.COM01 5 Compare Output Mode, Bit 1 -; TCCR0.COM00 4 Compare Output Mode, Bit 0 -; TCCR0.CTC0 3 Clear Timer/Counter on Compare Match -; TCCR0.CS02 2 Clock Select Bit 2 -; TCCR0.CS01 1 Clock Select Bit 1 -; TCCR0.CS00 0 Clock Select Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM Enable -; MCUCR.SRW 6 External SRAM Wait State -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.SM0 3 Sleep Mode Select Bit 0 -; TIFR 0x0056 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Input Capture Flag 1 -; TIFR.OCF1A 4 Output Compare Flag 1A -; TIFR.OCF1B 3 Output Compare Flag 1B -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0057 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; EIFR 0x0058 External Interrupt Flag Register -; EIFR.INTF7 7 External Interrupt 7 Flag -; EIFR.INTF6 6 External Interrupt 6 Flag -; EIFR.INTF5 5 External Interrupt 5 Flag -; EIFR.INTF4 4 External Interrupt 4 Flag -; EIMSK 0x0059 External Interrupt Mask Register -; EIMSK.INT7 7 External Interrupt Request 7 Enable -; EIMSK.INT6 6 External Interrupt Request 6 Enable -; EIMSK.INT5 5 External Interrupt Request 5 Enable -; EIMSK.INT4 4 External Interrupt Request 4 Enable -; EIMSK.INT3 3 External Interrupt Request 3 Enable -; EIMSK.INT2 2 External Interrupt Request 2 Enable -; EIMSK.INT1 1 External Interrupt Request 1 Enable -; EIMSK.INT0 0 External Interrupt Request 0 Enable -; EICR 0x005A External Interrupt Control Register -; EICR.ISC71 7 External Interrupt 7 Sense Control Bit 1 -; EICR.ISC70 6 External Interrupt 7 Sense Control Bit 0 -; EICR.ISC61 5 External Interrupt 6 Sense Control Bit 1 -; EICR.ISC60 4 External Interrupt 6 Sense Control Bit 0 -; EICR.ISC51 3 External Interrupt 5 Sense Control Bit 1 -; EICR.ISC50 2 External Interrupt 5 Sense Control Bit 0 -; EICR.ISC41 1 External Interrupt 4 Sense Control Bit 1 -; EICR.ISC40 0 External Interrupt 4 Sense Control Bit 0 -; RAMPZ 0x005B RAM Page Z Select Register -; RAMPZ.RAMPZ0 0 -; XDIV 0x005C XTAL Divide Control Register -; XDIV.XDIVEN 7 XTAL Divide Enable -; XDIV.XDIV6 6 XTAL Divide Select Bit 6 -; XDIV.XDIV5 5 XTAL Divide Select Bit 5 -; XDIV.XDIV4 4 XTAL Divide Select Bit 4 -; XDIV.XDIV3 3 XTAL Divide Select Bit 3 -; XDIV.XDIV2 2 XTAL Divide Select Bit 2 -; XDIV.XDIV1 1 XTAL Divide Select Bit 1 -; XDIV.XDIV0 0 XTAL Divide Select Bit 0 -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half-carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega128_L -SUBARCH=51 -; doc2467.pdf -; - -ROM=131072 -RAM=4096 -EEPROM=4096 - -; MEMORY MAP -; Memory Configuration A -area DATA FSR_1 0x0000:0x0020 32 Registers -area DATA FSR_2 0x0020:0x0060 64 I/O Registers -area DATA FSR_3 0x0060:0x00A0 160 Ext I/O Reg. -area BSS RESERVED 0x00A0:0x0100 -area DATA I_SRAM 0x0100:0x1100 Internal SRAM -area DATA E_SRAM 0x1100:0x10000 External SRAM -; Memory Configuration B -; area DATA FSR_1 0x0000:0x0020 32 Registers -; area DATA FSR_2 0x0020:0x0060 64 I/O Registers -; area DATA I_SRAM 0x0060:0x1000 Internal SRAM -; area DATA E_SRAM 0x1000:0x10000 External SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry INT3_ 0x0008 External Interrupt Request 3 -entry INT4_ 0x000A External Interrupt Request 4 -entry INT5_ 0x000C External Interrupt Request 5 -entry INT6_ 0x000E External Interrupt Request 6 -entry INT7_ 0x0010 External Interrupt Request 7 -entry TIMER2_COMP 0x0012 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0014 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0016 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0018 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x001A Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x001C Timer/Counter1 Overflow -entry TIMER0_COMP 0x001E Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow -entry SPI_STC 0x0022 SPI Serial Transfer Complete -entry USART0_RX 0x0024 USART0, Rx Complete -entry USART0_UDRE 0x0026 USART0 Data Register Empty -entry USART0_TX 0x0028 USART0, Tx Complete -entry ADC_ 0x002A ADC Conversion Complete -entry EE_READY 0x002C EEPROM Ready -entry ANALOG_COMP 0x002E Analog Comparator -entry TIMER1_COMPC 0x0030 Timer/Countre1 Compare Match C -entry TIMER3_CAPT 0x0032 Timer/Counter3 Capture Event -entry TIMER3_COMPA 0x0034 Timer/Counter3 Compare Match A -entry TIMER3_COMPB 0x0036 Timer/Counter3 Compare Match B -entry TIMER3_COMPC 0x0038 Timer/Counter3 Compare Match C -entry TIMER3_OVF 0x003A Timer/Counter3 Overflow -entry USART1_RX 0x003C USART1, Rx Complete -entry USART1_UDRE 0x003E USART1 Data Register Empty -entry USART1_TX 0x0040 USART1, Tx Complete -entry TWI_ 0x0042 Two-wire Serial Interface -entry SPM_READY 0x0044 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -PINF 0x0000 Port F Input Pins Address -PINF.PINF7 7 -PINF.PINF6 6 -PINF.PINF5 5 -PINF.PINF4 4 -PINF.PINF3 3 -PINF.PINF2 2 -PINF.PINF1 1 -PINF.PINF0 0 -PINE 0x0001 Port E Input Pins Address -PINE.PINE7 7 -PINE.PINE6 6 -PINE.PINE5 5 -PINE.PINE4 4 -PINE.PINE3 3 -PINE.PINE2 2 -PINE.PINE1 1 -PINE.PINE0 0 -DDRE 0x0002 Port E Data Direction Register -DDRE.DDE7 7 Port E Data Direction Register bit 7 -DDRE.DDE6 6 Port E Data Direction Register bit 6 -DDRE.DDE5 5 Port E Data Direction Register bit 5 -DDRE.DDE4 4 Port E Data Direction Register bit 4 -DDRE.DDE3 3 Port E Data Direction Register bit 3 -DDRE.DDE2 2 Port E Data Direction Register bit 2 -DDRE.DDE1 1 Port E Data Direction Register bit 1 -DDRE.DDE0 0 Port E Data Direction Register bit 0 -PORTE 0x0003 Port E Data Register -PORTE.PORTE7 7 Port E Data Register bit 7 -PORTE.PORTE6 6 Port E Data Register bit 6 -PORTE.PORTE5 5 Port E Data Register bit 5 -PORTE.PORTE4 4 Port E Data Register bit 4 -PORTE.PORTE3 3 Port E Data Register bit 3 -PORTE.PORTE2 2 Port E Data Register bit 2 -PORTE.PORTE1 1 Port E Data Register bit 1 -PORTE.PORTE0 0 Port E Data Register bit 0 -ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 -ADCL.ADC6 6 -ADCL.ADC5 5 -ADCL.ADC4 4 -ADCL.ADC3 3 -ADCL.ADC2 2 -ADCL.ADC1 1 -ADCL.ADC0 0 -ADCH 0x0005 The ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 -ADCH.ADC8 8 -; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 -; ADCL.ADC0 6 -; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 -; ADCH.ADC8 14 -; ADCH.ADC7 13 -; ADCH.ADC6 12 -; ADCH.ADC5 11 -; ADCH.ADC4 10 -; ADCH.ADC3 9 -; ADCH.ADC2 8 -ADCSRA 0x0006 ADC Control and Status Register A -ADCSRA.ADEN 7 ADC Enable -ADCSRA.ADSC 6 ADC Start Conversion -ADCSRA.ADFR 5 ADC Free Running Select -ADCSRA.ADIF 4 ADC Interrupt Flag -ADCSRA.ADIE 3 ADC Interrupt Enable -ADCSRA.ADPS2 2 ADC Prescaler Select Bit -ADCSRA.ADPS1 1 ADC Prescaler Select Bit -ADCSRA.ADPS0 0 ADC Prescaler Select Bit -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR0L 0x0009 USART Baud Rate Register -UBRR0L.UBRR7 7 -UBRR0L.UBRR6 6 -UBRR0L.UBRR5 5 -UBRR0L.UBRR4 4 -UBRR0L.UBRR3 3 -UBRR0L.UBRR2 2 -UBRR0L.UBRR1 1 -UBRR0L.UBRR0 0 -UCSR0B 0x000A USART Control and Status Register -UCSR0B.RXCIE 7 RX Complete Interrupt Enable -UCSR0B.TXCIE 6 TX Complete Interrupt Enable -UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSR0B.RXEN 4 Receiver Enable -UCSR0B.TXEN 3 Transmitter Enable -UCSR0B.UCSZ2 2 Character Size -UCSR0B.RXB8 1 Receive Data Bit 8 -UCSR0B.TXB8 0 Transmit Data Bit8 -UCSR0A 0x000B USART Control and Status Register -UCSR0A.RXC 7 USART Receive Complete -UCSR0A.TXC 6 USART Transmit Complete -UCSR0A.UDRE 5 USART Data Register Empty -UCSR0A.FE 4 Frame Error -UCSR0A.DOR 3 Data OverRun -UCSR0A.UPE 2 Parity Error -UCSR0A.U2X 1 Double the USART Transmission Speed -UCSR0A.MPCM 0 Multi-Processor Communication Mode -UDR0 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 -EEARL.EEAR6 6 -EEARL.EEAR5 5 -EEARL.EEAR4 4 -EEARL.EEAR3 3 -EEARL.EEAR2 2 -EEARL.EEAR1 1 -EEARL.EEAR0 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR11 11 -EEARH.EEAR10 10 -EEARH.EEAR9 9 -EEARH.EEAR8 8 -SFIOR 0x0020 Special Function IO Register -SFIOR.TSM 7 Timer/Counter Synchronization Mode -SFIOR.ADHSM 4 ADC High Speed Mode -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up disable -SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 -SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -OCDR 0x0022 On-chip Debug Register -OCDR.IDRD_OCDR7 7 -OCDR.OCDR6 6 -OCDR.OCDR5 5 -OCDR.OCDR4 4 -OCDR.OCDR3 3 -OCDR.OCDR2 2 -OCDR.OCDR1 1 -OCDR.OCDR0 0 -OCR2 0x0023 Output Compare Register -OCR2.OCR2_7 7 -OCR2.OCR2_6 6 -OCR2.OCR2_5 5 -OCR2.OCR2_4 4 -OCR2.OCR2_3 3 -OCR2.OCR2_2 2 -OCR2.OCR2_1 1 -OCR2.OCR2_0 0 -TCNT2 0x0024 Timer/Counter Register -TCNT2.TCNT2_7 7 -TCNT2.TCNT2_6 6 -TCNT2.TCNT2_5 5 -TCNT2.TCNT2_4 4 -TCNT2.TCNT2_3 3 -TCNT2.TCNT2_2 2 -TCNT2.TCNT2_1 1 -TCNT2.TCNT2_0 0 -TCCR2 0x0025 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Compare Match Output Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Waveform Generation Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -ICR1L 0x0026 Input Capture Register Low Byte -ICR1H 0x0027 Input Capture Register High Byte -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input CaptureEdgeSelect -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 -TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -ASSR 0x0030 Asynchronous Status Register -ASSR.AS0 3 Asynchronous Timer/Counter0 -ASSR.TCN0UB 2 Timer/Counter0 Update Busy -ASSR.OCR0UB 1 Output Compare Register0 Update Busy -ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy -OCR0 0x0031 Timer/Counter0 Output Compare Register -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.JTD 7 JTAG Interface Disable -MCUCSR.JTRF 4 JTAG Reset Flag -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-On Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM/XMEM Enable -MCUCR.SRW10 6 Wait-state Select Bit -MCUCR.SE 5 Sleep Enable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.SM0 3 Sleep Mode Select Bit 0 -MCUCR.SM2 2 Sleep Mode Select Bit 2 -MCUCR.IVSEL 1 Interrupt Vector Select -MCUCR.IVCE 0 Interrupt Vector Change Enable -TIFR 0x0036 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0037 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -EIFR 0x0038 External Interrupt Flag Register -EIFR.INTF7 7 External Interrupt Flag 7 -EIFR.INTF6 6 External Interrupt Flag 6 -EIFR.INTF5 5 External Interrupt Flag 5 -EIFR.INTF4 4 External Interrupt Flag 4 -EIFR.INTF3 3 External Interrupt Flag 3 -EIFR.INTF2 2 External Interrupt Flag 2 -EIFR.INTF1 1 External Interrupt Flag 1 -EIFR.INTF0 0 External Interrupt Flag 0 -EIMSK 0x0039 External Interrupt Mask Register -EIMSK.INT7 7 External Interrupt Request 7 Enable -EIMSK.INT6 6 External Interrupt Request 6 Enable -EIMSK.INT5 5 External Interrupt Request 5 Enable -EIMSK.INT4 4 External Interrupt Request 4 Enable -EIMSK.INT3 3 External Interrupt Request 3 Enable -EIMSK.INT2 2 External Interrupt Request 2 Enable -EIMSK.INT1 1 External Interrupt Request 1 Enable -EIMSK.INT0 0 External Interrupt Request 0 Enable -EICRB 0x003A External Interrupt Control Register B -EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 -EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 -EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 -EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 -EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 -EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 -EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 -EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 -RAMPZ 0x003B RAM Page Z Select Register -RAMPZ.RAMPZ0 0 Extended RAM Page Z-pointer -XDIV 0x003C XTAL Divide Control Register -XDIV.XDIVEN 7 XTAL Divide Enable -XDIV.XDIV6 6 XTAL Divide Select Bit 6 -XDIV.XDIV5 5 XTAL Divide Select Bit 5 -XDIV.XDIV4 4 XTAL Divide Select Bit 4 -XDIV.XDIV3 3 XTAL Divide Select Bit 3 -XDIV.XDIV2 2 XTAL Divide Select Bit 2 -XDIV.XDIV1 1 XTAL Divide Select Bit 1 -XDIV.XDIV0 0 XTAL Divide Select Bit 0 -SPL 0x003D Stack Pointer Register Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer Register High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 CarryFlag - -; PINF 0x0020 Port F Input Pins Address -; PINF.PINF7 7 -; PINF.PINF6 6 -; PINF.PINF5 5 -; PINF.PINF4 4 -; PINF.PINF3 3 -; PINF.PINF2 2 -; PINF.PINF1 1 -; PINF.PINF0 0 -; PINE 0x0021 Port E Input Pins Address -; PINE.PINE7 7 -; PINE.PINE6 6 -; PINE.PINE5 5 -; PINE.PINE4 4 -; PINE.PINE3 3 -; PINE.PINE2 2 -; PINE.PINE1 1 -; PINE.PINE0 0 -; DDRE 0x0022 Port E Data Direction Register -; DDRE.DDE7 7 Port E Data Direction Register bit 7 -; DDRE.DDE6 6 Port E Data Direction Register bit 6 -; DDRE.DDE5 5 Port E Data Direction Register bit 5 -; DDRE.DDE4 4 Port E Data Direction Register bit 4 -; DDRE.DDE3 3 Port E Data Direction Register bit 3 -; DDRE.DDE2 2 Port E Data Direction Register bit 2 -; DDRE.DDE1 1 Port E Data Direction Register bit 1 -; DDRE.DDE0 0 Port E Data Direction Register bit 0 -; PORTE 0x0023 Port E Data Register -; PORTE.PORTE7 7 Port E Data Register bit 7 -; PORTE.PORTE6 6 Port E Data Register bit 6 -; PORTE.PORTE5 5 Port E Data Register bit 5 -; PORTE.PORTE4 4 Port E Data Register bit 4 -; PORTE.PORTE3 3 Port E Data Register bit 3 -; PORTE.PORTE2 2 Port E Data Register bit 2 -; PORTE.PORTE1 1 Port E Data Register bit 1 -; PORTE.PORTE0 0 Port E Data Register bit 0 -; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 -; ADCL.ADC6 6 -; ADCL.ADC5 5 -; ADCL.ADC4 4 -; ADCL.ADC3 3 -; ADCL.ADC2 2 -; ADCL.ADC1 1 -; ADCL.ADC0 0 -; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 -; ADCH.ADC8 8 -; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 -; ; ADCL.ADC0 6 -; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 -; ; ADCH.ADC8 14 -; ; ADCH.ADC7 13 -; ; ADCH.ADC6 12 -; ; ADCH.ADC5 11 -; ; ADCH.ADC4 10 -; ; ADCH.ADC3 9 -; ; ADCH.ADC2 8 -; ADCSRA 0x0026 ADC Control and Status Register A -; ADCSRA.ADEN 7 ADC Enable -; ADCSRA.ADSC 6 ADC Start Conversion -; ADCSRA.ADFR 5 ADC Free Running Select -; ADCSRA.ADIF 4 ADC Interrupt Flag -; ADCSRA.ADIE 3 ADC Interrupt Enable -; ADCSRA.ADPS2 2 ADC Prescaler Select Bit -; ADCSRA.ADPS1 1 ADC Prescaler Select Bit -; ADCSRA.ADPS0 0 ADC Prescaler Select Bit -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR0L 0x0029 USART Baud Rate Register -; UBRR0L.UBRR7 7 -; UBRR0L.UBRR6 6 -; UBRR0L.UBRR5 5 -; UBRR0L.UBRR4 4 -; UBRR0L.UBRR3 3 -; UBRR0L.UBRR2 2 -; UBRR0L.UBRR1 1 -; UBRR0L.UBRR0 0 -; UCSR0B 0x002A USART Control and Status Register -; UCSR0B.RXCIE 7 RX Complete Interrupt Enable -; UCSR0B.TXCIE 6 TX Complete Interrupt Enable -; UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSR0B.RXEN 4 Receiver Enable -; UCSR0B.TXEN 3 Transmitter Enable -; UCSR0B.UCSZ2 2 Character Size -; UCSR0B.RXB8 1 Receive Data Bit 8 -; UCSR0B.TXB8 0 Transmit Data Bit8 -; UCSR0A 0x002B USART Control and Status Register -; UCSR0A.RXC 7 USART Receive Complete -; UCSR0A.TXC 6 USART Transmit Complete -; UCSR0A.UDRE 5 USART Data Register Empty -; UCSR0A.FE 4 Frame Error -; UCSR0A.DOR 3 Data OverRun -; UCSR0A.UPE 2 Parity Error -; UCSR0A.U2X 1 Double the USART Transmission Speed -; UCSR0A.MPCM 0 Multi-Processor Communication Mode -; UDR0 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 -; EEARL.EEAR6 6 -; EEARL.EEAR5 5 -; EEARL.EEAR4 4 -; EEARL.EEAR3 3 -; EEARL.EEAR2 2 -; EEARL.EEAR1 1 -; EEARL.EEAR0 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR11 11 -; EEARH.EEAR10 10 -; EEARH.EEAR9 9 -; EEARH.EEAR8 8 -; SFIOR 0x0040 Special Function IO Register -; SFIOR.TSM 7 Timer/Counter Synchronization Mode -; SFIOR.ADHSM 4 ADC High Speed Mode -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up disable -; SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 -; SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; OCDR 0x0042 On-chip Debug Register -; OCDR.IDRD_OCDR7 7 -; OCDR.OCDR6 6 -; OCDR.OCDR5 5 -; OCDR.OCDR4 4 -; OCDR.OCDR3 3 -; OCDR.OCDR2 2 -; OCDR.OCDR1 1 -; OCDR.OCDR0 0 -; OCR2 0x0043 Output Compare Register -; OCR2.OCR2_7 7 -; OCR2.OCR2_6 6 -; OCR2.OCR2_5 5 -; OCR2.OCR2_4 4 -; OCR2.OCR2_3 3 -; OCR2.OCR2_2 2 -; OCR2.OCR2_1 1 -; OCR2.OCR2_0 0 -; TCNT2 0x0044 Timer/Counter Register -; TCNT2.TCNT2_7 7 -; TCNT2.TCNT2_6 6 -; TCNT2.TCNT2_5 5 -; TCNT2.TCNT2_4 4 -; TCNT2.TCNT2_3 3 -; TCNT2.TCNT2_2 2 -; TCNT2.TCNT2_1 1 -; TCNT2.TCNT2_0 0 -; TCCR2 0x0045 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Compare Match Output Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Waveform Generation Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; ICR1L 0x0046 Input Capture Register Low Byte -; ICR1H 0x0047 Input Capture Register High Byte -; OCR1BL 0x0048 Output Compare Register B Low Byte -; OCR1BH 0x0049 Output Compare Register B High Byte -; OCR1AL 0x004A Output Compare Register A Low Byte -; OCR1AH 0x004B Output Compare Register A High Byte -; TCNT1L 0x004C Counter Register Low Byte -; TCNT1H 0x004D Counter Register High Byte -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input CaptureEdgeSelect -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -; TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 -; TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; ASSR 0x0050 Asynchronous Status Register -; ASSR.AS0 3 Asynchronous Timer/Counter0 -; ASSR.TCN0UB 2 Timer/Counter0 Update Busy -; ASSR.OCR0UB 1 Output Compare Register0 Update Busy -; ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy -; OCR0 0x0051 Timer/Counter0 Output Compare Register -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.JTD 7 JTAG Interface Disable -; MCUCSR.JTRF 4 JTAG Reset Flag -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-On Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM/XMEM Enable -; MCUCR.SRW10 6 Wait-state Select Bit -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.SM0 3 Sleep Mode Select Bit 0 -; MCUCR.SM2 2 Sleep Mode Select Bit 2 -; MCUCR.IVSEL 1 Interrupt Vector Select -; MCUCR.IVCE 0 Interrupt Vector Change Enable -; TIFR 0x0056 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0057 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; EIFR 0x0058 External Interrupt Flag Register -; EIFR.INTF7 7 External Interrupt Flag 7 -; EIFR.INTF6 6 External Interrupt Flag 6 -; EIFR.INTF5 5 External Interrupt Flag 5 -; EIFR.INTF4 4 External Interrupt Flag 4 -; EIFR.INTF3 3 External Interrupt Flag 3 -; EIFR.INTF2 2 External Interrupt Flag 2 -; EIFR.INTF1 1 External Interrupt Flag 1 -; EIFR.INTF0 0 External Interrupt Flag 0 -; EIMSK 0x0059 External Interrupt Mask Register -; EIMSK.INT7 7 External Interrupt Request 7 Enable -; EIMSK.INT6 6 External Interrupt Request 6 Enable -; EIMSK.INT5 5 External Interrupt Request 5 Enable -; EIMSK.INT4 4 External Interrupt Request 4 Enable -; EIMSK.INT3 3 External Interrupt Request 3 Enable -; EIMSK.INT2 2 External Interrupt Request 2 Enable -; EIMSK.INT1 1 External Interrupt Request 1 Enable -; EIMSK.INT0 0 External Interrupt Request 0 Enable -; EICRB 0x005A External Interrupt Control Register B -; EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 -; EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 -; EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 -; EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 -; EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 -; EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 -; EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 -; EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 -; RAMPZ 0x005B RAM Page Z Select Register -; RAMPZ.RAMPZ0 0 Extended RAM Page Z-pointer -; XDIV 0x005C XTAL Divide Control Register -; XDIV.XDIVEN 7 XTAL Divide Enable -; XDIV.XDIV6 6 XTAL Divide Select Bit 6 -; XDIV.XDIV5 5 XTAL Divide Select Bit 5 -; XDIV.XDIV4 4 XTAL Divide Select Bit 4 -; XDIV.XDIV3 3 XTAL Divide Select Bit 3 -; XDIV.XDIV2 2 XTAL Divide Select Bit 2 -; XDIV.XDIV1 1 XTAL Divide Select Bit 1 -; XDIV.XDIV0 0 XTAL Divide Select Bit 0 -; SPL 0x005D Stack Pointer Register Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer Register High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 CarryFlag -; RESERVED0060 0x0060 RESERVED -; DDRF 0x0061 Port F Data Direction Register -; DDRF.DDF7 7 Port F Data Direction Register bit 7 -; DDRF.DDF6 6 Port F Data Direction Register bit 6 -; DDRF.DDF5 5 Port F Data Direction Register bit 5 -; DDRF.DDF4 4 Port F Data Direction Register bit 4 -; DDRF.DDF3 3 Port F Data Direction Register bit 3 -; DDRF.DDF2 2 Port F Data Direction Register bit 2 -; DDRF.DDF1 1 Port F Data Direction Register bit 1 -; DDRF.DDF0 0 Port F Data Direction Register bit 0 -; PORTF 0x0062 Port F Data Register -; PORTF.PORTF7 7 Port F Data Register bit 7 -; PORTF.PORTF6 6 Port F Data Register bit 6 -; PORTF.PORTF5 5 Port F Data Register bit 5 -; PORTF.PORTF4 4 Port F Data Register bit 4 -; PORTF.PORTF3 3 Port F Data Register bit 3 -; PORTF.PORTF2 2 Port F Data Register bit 2 -; PORTF.PORTF1 1 Port F Data Register bit 1 -; PORTF.PORTF0 0 Port F Data Register bit 0 -; PING 0x0063 Port G Input Pins Address -; PING.PING4 4 -; PING.PING3 3 -; PING.PING2 2 -; PING.PING1 1 -; PING.PING0 0 -; DDRG 0x0064 Port G Data Direction Register -; DDRG.DDG4 4 Port G Data Direction Register bit 4 -; DDRG.DDG3 3 Port G Data Direction Register bit 3 -; DDRG.DDG2 2 Port G Data Direction Register bit 2 -; DDRG.DDG1 1 Port G Data Direction Register bit 1 -; DDRG.DDG0 0 Port G Data Direction Register bit 0 -; PORTG 0x0065 Port G Data Register -; PORTG.PORTG4 4 Port G Data Register bit 4 -; PORTG.PORTG3 3 Port G Data Register bit 3 -; PORTG.PORTG2 2 Port G Data Register bit 2 -; PORTG.PORTG1 1 Port G Data Register bit 1 -; PORTG.PORTG0 0 Port G Data Register bit 0 -; RESERVED0066 0x0066 RESERVED -; RESERVED0067 0x0067 RESERVED -; SPMCSR 0x0068 Store Program Memory Control Register -; SPMCSR.SPMIE 7 SPM Interrupt Enable -; SPMCSR.RWWSB 6 Read-While-Write Section Busy -; SPMCSR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCSR.BLBSET 3 Boot Lock Bit Set -; SPMCSR.PGWRT 2 Page Write -; SPMCSR.PGERS 1 Page Erase -; SPMCSR.SPMEN 0 Store Program Memory Enable -; RESERVED0069 0x0069 RESERVED -; EICRA 0x006A External Interrupt Control Register A -; EICRA.ISC31 7 External Interrupt 3 Sense Control Bit 1 -; EICRA.ISC30 6 External Interrupt 3 Sense Control Bit 0 -; EICRA.ISC21 5 External Interrupt 2 Sense Control Bit 1 -; EICRA.ISC20 4 External Interrupt 2 Sense Control Bit 0 -; EICRA.ISC11 3 External Interrupt 1 Sense Control Bit 1 -; EICRA.ISC10 2 External Interrupt 1 Sense Control Bit 0 -; EICRA.ISC01 1 External Interrupt 0 Sense Control Bit 1 -; EICRA.ISC00 0 External Interrupt 0 Sense Control Bit 0 -; RESERVED006B 0x006B RESERVED -; XMCRB 0x006C External Memory Control Register B -; XMCRB.XMBK 7 External Memory Bus-keeper Enable -; XMCRB.XMM2 2 External Memory High Mask 2 -; XMCRB.XMM1 1 External Memory High Mask 1 -; XMCRB.XMM0 0 External Memory High Mask 0 -; RESERVED006D 0x006D RESERVED -; OSCCAL 0x006F Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TWBR 0x0070 TWI Bit Rate Register -; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -; TWSR 0x0071 TWI Status Register -; TWSR.TWS7 7 TWI Status 7 -; TWSR.TWS6 6 TWI Status 6 -; TWSR.TWS5 5 TWI Status 5 -; TWSR.TWS4 4 TWI Status 4 -; TWSR.TWS3 3 TWI Status 3 -; TWSR.TWS1 1 TWI Status 1 -; TWSR.TWS0 0 TWI Status 0 -; TWAR 0x0072 TWI (Slave) Address Register -; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -; TWDR 0x0073 TWI Data Register -; TWDR.TWD7 7 TWI Data Register bit 7 -; TWDR.TWD6 6 TWI Data Register bit 6 -; TWDR.TWD5 5 TWI Data Register bit 5 -; TWDR.TWD4 4 TWI Data Register bit 4 -; TWDR.TWD3 3 TWI Data Register bit 3 -; TWDR.TWD2 2 TWI Data Register bit 2 -; TWDR.TWD1 1 TWI Data Register bit 1 -; TWDR.TWD0 0 TWI Data Register bit 0 -; TWCR 0x0074 TWI Control Register -; TWCR.TWINT 7 TWI Interrupt Flag -; TWCR.TWEA 6 TWI Enable Acknowledge Bit -; TWCR.TWSTA 5 TWI START Condition Bit -; TWCR.TWSTO 4 TWI STOP Condition Bit -; TWCR.TWWC 3 TWI Write Collision Flag -; TWCR.TWEN 2 TWI Enable Bit -; TWCR.TWIE 0 TWI Interrupt Enable -; RESERVED0075 0x0075 RESERVED -; RESERVED0076 0x0076 RESERVED -; RESERVED0077 0x0077 RESERVED -; OCR1CL 0x0078 Output Compare Register C Low Byte -; OCR1CH 0x0079 Output Compare Register C High Byte -; TCCR1C 0x007A Timer/Counter1 Control Register C -; TCCR1C.FOC1A 7 Force Output Compare for Channel A -; TCCR1C.FOC1B 6 Force Output Compare for Channel B -; TCCR1C.FOC1C 5 Force Output Compare for Channel C -; RESERVED007B 0x007B RESERVED -; ETIFR 0x007C Extended Timer/Counter Interrupt Flag Register -; ETIFR.ICF3 5 Timer/Counter3, Input Capture Flag -; ETIFR.OCF3A 4 Timer/Counter3, Output Compare A Match Flag -; ETIFR.OCF3B 3 Timer/Counter3, Output Compare B Match Flag -; ETIFR.TOV3 2 Timer/Counter3, Overflow Flag -; ETIFR.OCF3C 1 Timer/Counter3, Output Compare C Match Flag -; ETIFR.OCF1C 0 Timer/Counter1, Output Compare C Match Flag -; ETIMSK 0x007D Extended Timer/Counter Interrupt Mask Register -; ETIMSK.TICIE3 5 Timer/Counter3, Input Capture Interrupt Enable -; ETIMSK.OCIE3A 4 Timer/Counter3, Output Compare A Match Interrupt Enable -; ETIMSK.OCIE3B 3 Timer/Counter3, Output Compare B Match Interrupt Enable -; ETIMSK.TOIE3 2 Timer/Counter3, Overflow Interrupt Enable -; ETIMSK.OCIE3C 1 Timer/Counter3, Output Compare C Match Interrupt Enable -; ETIMSK.OCIE1C 0 Timer/Counter1, Output Compare C Match Interrupt Enable -; RESERVED007E 0x007E RESERVED -; RESERVED007F 0x007F RESERVED -; ICR3L 0x0080 Input Capture Register Low Byte -; ICR3H 0x0081 Input Capture Register High Byte -; OCR3CL 0x0082 Output Compare Register C Low Byte -; OCR3CH 0x0083 Output Compare Register C High Byte -; OCR3BL 0x0084 Output Compare Register B Low Byte -; OCR3BH 0x0085 Output Compare Register B High Byte -; OCR3AL 0x0086 Output Compare Register A Low Byte -; OCR3AH 0x0087 Output Compare Register A High Byte -; TCNT3L 0x0088 Counter Register Low Byte -; TCNT3H 0x0089 Counter Register High Byte -; TCCR3B 0x008A Timer/Counter3 Control Register B -; TCCR3B.ICNC3 7 Input Capture Noise Canceler -; TCCR3B.ICES3 6 Input CaptureEdgeSelect -; TCCR3B.WGM33 4 Waveform Generation Mode 3 -; TCCR3B.WGM32 3 Waveform Generation Mode 2 -; TCCR3B.CS32 2 Clock Select 2 -; TCCR3B.CS31 1 Clock Select 1 -; TCCR3B.CS30 0 Clock Select 0 -; TCCR3A 0x008B Timer/Counter3 Control Register A -; TCCR3A.COM3A1 7 Compare Output Mode for Channel A 1 -; TCCR3A.COM3A0 6 Compare Output Mode for Channel A 0 -; TCCR3A.COM3B1 5 Compare Output Mode for Channel B 1 -; TCCR3A.COM3B0 4 Compare Output Mode for Channel B 0 -; TCCR3A.COM3C1 3 Compare Output Mode for Channel C 1 -; TCCR3A.COM3C0 2 Compare Output Mode for Channel C 0 -; TCCR3A.WGM31 1 Waveform Generation Mode 1 -; TCCR3A.WGM30 0 Waveform Generation Mode 0 -; TCCR3C 0x008C Timer/Counter3 Control Register C -; TCCR3C.FOC3A 7 Force Output Compare for Channel A -; TCCR3C.FOC3B 6 Force Output Compare for Channel B -; TCCR3C.FOC3C 5 Force Output Compare for Channel C -; RESERVED008D 0x008D RESERVED -; RESERVED008E 0x008E RESERVED -; RESERVED008F 0x008F RESERVED -; UBRR0H 0x0090 USART0 Baud Rate Register High -; RESERVED0091 0x0091 RESERVED -; RESERVED0092 0x0092 RESERVED -; RESERVED0093 0x0093 RESERVED -; RESERVED0094 0x0094 RESERVED -; UCSR0C 0x0095 USART Control and Status Register C -; UCSR0C.UMSEL 6 USART Mode Select -; UCSR0C.UPM1 5 Parity Mode 1 -; UCSR0C.UPM0 4 Parity Mode 0 -; UCSR0C.USBS 3 Stop Bit Select -; UCSR0C.UCSZ1 2 Character Size 1 -; UCSR0C.UCSZ0 1 Character Size 0 -; UCSR0C.UCPOL 0 Clock Polarity -; RESERVED0096 0x0096 RESERVED -; RESERVED0097 0x0097 RESERVED -; UBRR1H 0x0098 USART1 Baud Rate Register High -; UBRR1L 0x0099 USART1 Baud Rate Register Low -; UCSR1B 0x009A USART Control and Status Register B -; UCSR1B.RXCIE 7 RX Complete Interrupt Enable -; UCSR1B.TXCIE 6 TX Complete Interrupt Enable -; UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSR1B.RXEN 4 Receiver Enable -; UCSR1B.TXEN 3 Transmitter Enable -; UCSR1B.UCSZ2 2 Character Size -; UCSR1B.RXB8 1 Receive Data Bit 8 -; UCSR1B.TXB8 0 Transmit Data Bit8 -; UCSR1A 0x009B USART Control and Status Register A -; UCSR1A.RXC 7 USART Receive Complete -; UCSR1A.TXC 6 USART Transmit Complete -; UCSR1A.UDRE 5 USART Data Register Empty -; UCSR1A.FE 4 Frame Error -; UCSR1A.DOR 3 Data OverRun -; UCSR1A.UPE 2 Parity Error -; UCSR1A.U2X 1 Double the USART Transmission Speed -; UCSR1A.MPCM 0 Multi-Processor Communication Mode -; UDR1 0x009C USART1 I/O Data Register -; UCSR1C 0x009D USART Control and Status Register C -; UCSR1C.UMSEL 6 USART Mode Select -; UCSR1C.UPM1 5 Parity Mode 1 -; UCSR1C.UPM0 4 Parity Mode 0 -; UCSR1C.USBS 3 Stop Bit Select -; UCSR1C.UCSZ1 2 Character Size 1 -; UCSR1C.UCSZ0 1 Character Size 0 -; UCSR1C.UCPOL 0 Clock Polarity -; RESERVED009E 0x009E RESERVED -; RESERVED009F 0x009F RESERVED - - -.ATmega161_L -SUBARCH=5 -; doc1228.pdf -; - -RAM=1024 -ROM=16384 -EEPROM=512 - - -; MEMORY MAP -area DATA FSR 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x0460 Internal SRAM -area DATA E_SRAM 0x0460:0x10000 External SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x000A Timer/Counter2 Overflow -entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow -entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow -entry SPI_STC 0x0018 Serial Transfer Complete -entry UART0_RX 0x001A UART0, Rx Complete -entry UART1_RX 0x001C UART1, Rx Complete -entry UART0_UDRE 0x001E UART0 Data Register Empty -entry UART1_UDRE 0x0020 UART1 Data Register Empty -entry UART0_TX 0x0022 UART0, Tx Complete -entry UART1_TX 0x0024 UART1, Tx Complete -entry EE_RDY 0x0026 EEPROM Ready -entry ANA_COMP 0x0028 Analog Comparator - - -; INPUT/OUTPUT PORTS -UBRR1 0x0000 UART1 Baud Rate Register Low Byte -UCSR1B 0x0001 UART1 Control and Status Register -UCSR1B.RXCIE1 7 RX Complete Interrupt Enable -UCSR1B.TXCIE1 6 TX Complete Interrupt Enable -UCSR1B.UDRIE1 5 UART Data Register Empty Interrupt Enable -UCSR1B.RXEN1 4 Receiver Enable -UCSR1B.TXEN1 3 Transmitter Enable -UCSR1B.CHR91 2 9-bit Characters -UCSR1B.RXB81 1 Receive Data Bit 8 -UCSR1B.TXB81 0 Transmit Data Bit 8 -UCSR1A 0x0002 UART1 Control and Status Register -UCSR1A.RXC1 7 UART Receive Complete -UCSR1A.TXC1 6 UART Transmit Complete -UCSR1A.UDRE1 5 UART Data Register Empty -UCSR1A.FE1 4 Framing Error -UCSR1A.OR1 3 OverRun -UCSR1A.U2X1 1 Double the UART Transmission Speed -UCSR1A.MPCM1 0 Multi-processor Communication Mode -UDR1 0x0003 UART1 I/O Data Register -RESERVED0004 0x0004 RESERVED -PINE 0x0005 Port E Input Pins Address -PINE.PINE2 2 -PINE.PINE1 1 -PINE.PINE0 0 -DDRE 0x0006 Port E Data Direction Register -DDRE.DDE2 2 Port E Data Direction Register bit 2 -DDRE.DDE1 1 Port E Data Direction Register bit 1 -DDRE.DDE0 0 Port E Data Direction Register bit 0 -PORTE 0x0007 Port E Data Register -PORTE.PORTE2 2 Port E Data Register bit 2 -PORTE.PORTE1 1 Port E Data Register bit 1 -PORTE.PORTE0 0 Port E Data Register bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.AINBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR0 0x0009 UART0 Baud Rate Register Low Byte -UCSR0B 0x000A UART0 Control and StatusRegister -UCSR0B.RXCIE0 7 RX Complete Interrupt Enable -UCSR0B.TXCIE0 6 TX Complete Interrupt Enable -UCSR0B.UDRIE0 5 UART Data Register Empty Interrupt Enable -UCSR0B.RXEN0 4 Receiver Enable -UCSR0B.TXEN0 3 Transmitter Enable -UCSR0B.CHR90 2 9-bit Characters -UCSR0B.RXB80 1 Receive Data Bit 8 -UCSR0B.TXB80 0 Transmit Data Bit 8 -UCSR0A 0x000B UART0 Control and Status Register -UCSR0A.RXC0 7 UART Receive Complete -UCSR0A.TXC0 6 UART Transmit Complete -UCSR0A.UDRE0 5 UART Data Register Empty -UCSR0A.FE0 4 Framing Error -UCSR0A.OR0 3 OverRun -UCSR0A.U2X0 1 Double the UART Transmission Speed -UCSR0A.MPCM0 0 Multi-processor Communication Mode -UDR0 0x000C UART0 I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write Collision Flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low Byte -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High Byte -UBRRHI 0x0020 UART0 and UART1 High Byte Baud Rate Register -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -OCR2 0x0022 Timer/Counter2 Output Compare Register -TCNT2 0x0023 Timer/Counter2 Counter Register -ICR1L 0x0024 Input Capture Register Low Byte -ICR1H 0x0025 Input Capture Register High Byte -ASSR 0x0026 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 Mode -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -TCCR2 0x0027 Timer/Counter2 Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.PWM2 6 Pulse Width Modulator Enable -TCCR2.COM21 5 Compare Output Mode, Bit 1 -TCCR2.COM20 4 Compare Output Mode, Bit 0 -TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -TCCR2.CS22 2 Clock Select Bit 2 -TCCR2.CS21 1 Clock Select Bit 1 -TCCR2.CS20 0 Clock Select Bit 0 -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1, Bit 2 -TCCR1B.CS11 1 Clock Select1, Bit 1 -TCCR1B.CS10 0 Clock Select1, Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -TCCR1A.FOC1A 3 Force Output Compare1A -TCCR1A.FOC1B 2 Force Output Compare1B -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -SFIOR 0x0030 Special Function IO Register -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OCR0 0x0031 Timer/Counter0 Output Compare Register -TCNT0 0x0032 Timer/Counter0 Counter Register -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.PWM0 6 Pulse Width Modulator Enable -TCCR0.COM01 5 Compare Output Mode, Bit 1 -TCCR0.COM00 4 Compare Output Mode, Bit 0 -TCCR0.CTC0 3 Clear Timer/Counter on Compare Match -TCCR0.CS02 2 Clock Select Bit 2 -TCCR0.CS01 1 Clock Select Bit 1 -TCCR0.CS00 0 Clock Select Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.WDRF 3 Watchdog Reset Flag -MCUSR.BORF 2 Brown-out Reset Flag -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM Enable -MCUCR.SRW10 6 External SRAM Wait State -MCUCR.SE 5 Sleep Enable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -EMCUCR 0x0036 Extended MCU Control Register -EMCUCR.SM0 7 Sleep Mode Bit 0 -EMCUCR.SRL2 6 External SRAM Limit 2 -EMCUCR.SRL1 5 External SRAM Limit 1 -EMCUCR.SRL0 4 External SRAM Limit 0 -EMCUCR.SRW01 3 External SRAM Wait State Select Bit 01 -EMCUCR.SRW00 2 External SRAM Wait State Select Bit 00 -EMCUCR.SRW11 1 External SRAM Wait State Select Bit 11 -EMCUCR.ISC2 0 Interrupt Sense Control 2 -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter1 Overflow Flag -TIFR.OCF1A 6 Output Compare Flag 1A -TIFR.OCIFB 5 Output Compare Flag 1B -TIFR.TOV2 4 Timer/Counter2 Overflow Flag -TIFR.ICF1 3 Input Capture Flag 1 -TIFR.OCF2 2 Output Compare Flag 2 -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIFR.OCF0 0 Output Compare Flag 0 -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable -TIMSK.TOIE2 4 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.OCIE2 2 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable -GIFR 0x003A General Interrupt Flag -GIFR.INTF1 7 External Interrupt Flag1 -GIFR.INTF0 6 External Interrupt Flag0 -GIFR.INTF2 5 External Interrupt Flag2 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.INT2 5 External Interrupt Request 2 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 CarryFlag - -; UBRR1 0x0020 UART1 Baud Rate Register Low Byte -; UCSR1B 0x0021 UART1 Control and Status Register -; UCSR1B.RXCIE1 7 RX Complete Interrupt Enable -; UCSR1B.TXCIE1 6 TX Complete Interrupt Enable -; UCSR1B.UDRIE1 5 UART Data Register Empty Interrupt Enable -; UCSR1B.RXEN1 4 Receiver Enable -; UCSR1B.TXEN1 3 Transmitter Enable -; UCSR1B.CHR91 2 9-bit Characters -; UCSR1B.RXB81 1 Receive Data Bit 8 -; UCSR1B.TXB81 0 Transmit Data Bit 8 -; UCSR1A 0x0022 UART1 Control and Status Register -; UCSR1A.RXC1 7 UART Receive Complete -; UCSR1A.TXC1 6 UART Transmit Complete -; UCSR1A.UDRE1 5 UART Data Register Empty -; UCSR1A.FE1 4 Framing Error -; UCSR1A.OR1 3 OverRun -; UCSR1A.U2X1 1 Double the UART Transmission Speed -; UCSR1A.MPCM1 0 Multi-processor Communication Mode -; UDR1 0x0023 UART1 I/O Data Register -; RESERVED0024 0x0024 RESERVED -; PINE 0x0025 Port E Input Pins Address -; PINE.PINE2 2 -; PINE.PINE1 1 -; PINE.PINE0 0 -; DDRE 0x0026 Port E Data Direction Register -; DDRE.DDE2 2 Port E Data Direction Register bit 2 -; DDRE.DDE1 1 Port E Data Direction Register bit 1 -; DDRE.DDE0 0 Port E Data Direction Register bit 0 -; PORTE 0x0027 Port E Data Register -; PORTE.PORTE2 2 Port E Data Register bit 2 -; PORTE.PORTE1 1 Port E Data Register bit 1 -; PORTE.PORTE0 0 Port E Data Register bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.AINBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR0 0x0029 UART0 Baud Rate Register Low Byte -; UCSR0B 0x002A UART0 Control and StatusRegister -; UCSR0B.RXCIE0 7 RX Complete Interrupt Enable -; UCSR0B.TXCIE0 6 TX Complete Interrupt Enable -; UCSR0B.UDRIE0 5 UART Data Register Empty Interrupt Enable -; UCSR0B.RXEN0 4 Receiver Enable -; UCSR0B.TXEN0 3 Transmitter Enable -; UCSR0B.CHR90 2 9-bit Characters -; UCSR0B.RXB80 1 Receive Data Bit 8 -; UCSR0B.TXB80 0 Transmit Data Bit 8 -; UCSR0A 0x002B UART0 Control and Status Register -; UCSR0A.RXC0 7 UART Receive Complete -; UCSR0A.TXC0 6 UART Transmit Complete -; UCSR0A.UDRE0 5 UART Data Register Empty -; UCSR0A.FE0 4 Framing Error -; UCSR0A.OR0 3 OverRun -; UCSR0A.U2X0 1 Double the UART Transmission Speed -; UCSR0A.MPCM0 0 Multi-processor Communication Mode -; UDR0 0x002C UART0 I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write Collision Flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low Byte -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High Byte -; UBRRHI 0x0040 UART0 and UART1 High Byte Baud Rate Register -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; OCR2 0x0042 Timer/Counter2 Output Compare Register -; TCNT2 0x0043 Timer/Counter2 Counter Register -; ICR1L 0x0044 Input Capture Register Low Byte -; ICR1H 0x0045 Input Capture Register High Byte -; ASSR 0x0046 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 Mode -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; TCCR2 0x0047 Timer/Counter2 Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.PWM2 6 Pulse Width Modulator Enable -; TCCR2.COM21 5 Compare Output Mode, Bit 1 -; TCCR2.COM20 4 Compare Output Mode, Bit 0 -; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -; TCCR2.CS22 2 Clock Select Bit 2 -; TCCR2.CS21 1 Clock Select Bit 1 -; TCCR2.CS20 0 Clock Select Bit 0 -; OCR1BL 0x0048 Output Compare Register B Low Byte -; OCR1BH 0x0049 Output Compare Register B High Byte -; OCR1AL 0x004A Output Compare Register A Low Byte -; OCR1AH 0x004B Output Compare Register A High Byte -; TCNT1L 0x004C Counter Register Low Byte -; TCNT1H 0x004D Counter Register High Byte -; TCCR1B 0x004E Timer/Counter1 Control Register -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1, Bit 2 -; TCCR1B.CS11 1 Clock Select1, Bit 1 -; TCCR1B.CS10 0 Clock Select1, Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -; TCCR1A.FOC1A 3 Force Output Compare1A -; TCCR1A.FOC1B 2 Force Output Compare1B -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; SFIOR 0x0050 Special Function IO Register -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OCR0 0x0051 Timer/Counter0 Output Compare Register -; TCNT0 0x0052 Timer/Counter0 Counter Register -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.PWM0 6 Pulse Width Modulator Enable -; TCCR0.COM01 5 Compare Output Mode, Bit 1 -; TCCR0.COM00 4 Compare Output Mode, Bit 0 -; TCCR0.CTC0 3 Clear Timer/Counter on Compare Match -; TCCR0.CS02 2 Clock Select Bit 2 -; TCCR0.CS01 1 Clock Select Bit 1 -; TCCR0.CS00 0 Clock Select Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.WDRF 3 Watchdog Reset Flag -; MCUSR.BORF 2 Brown-out Reset Flag -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM Enable -; MCUCR.SRW10 6 External SRAM Wait State -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; EMCUCR 0x0056 Extended MCU Control Register -; EMCUCR.SM0 7 Sleep Mode Bit 0 -; EMCUCR.SRL2 6 External SRAM Limit 2 -; EMCUCR.SRL1 5 External SRAM Limit 1 -; EMCUCR.SRL0 4 External SRAM Limit 0 -; EMCUCR.SRW01 3 External SRAM Wait State Select Bit 01 -; EMCUCR.SRW00 2 External SRAM Wait State Select Bit 00 -; EMCUCR.SRW11 1 External SRAM Wait State Select Bit 11 -; EMCUCR.ISC2 0 Interrupt Sense Control 2 -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.TOV1 7 Timer/Counter1 Overflow Flag -; TIFR.OCF1A 6 Output Compare Flag 1A -; TIFR.OCIFB 5 Output Compare Flag 1B -; TIFR.TOV2 4 Timer/Counter2 Overflow Flag -; TIFR.ICF1 3 Input Capture Flag 1 -; TIFR.OCF2 2 Output Compare Flag 2 -; TIFR.TOV0 1 Timer/Counter0 Overflow Flag -; TIFR.OCF0 0 Output Compare Flag 0 -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable -; TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable -; TIMSK.TOIE2 4 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.OCIE2 2 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable -; GIFR 0x005A General Interrupt Flag -; GIFR.INTF1 7 External Interrupt Flag1 -; GIFR.INTF0 6 External Interrupt Flag0 -; GIFR.INTF2 5 External Interrupt Flag2 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; GIMSK.INT2 5 External Interrupt Request 2 Enable -; RESERVED003C 0x005C RESERVED -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 CarryFlag - - -.ATmega162_L_V -SUBARCH=5 -; doc2513.pdf -; - -RAM=1024 -ROM=16384 -EEPROM=512 - -; MEMORY MAP -; Memory configuration A -area DATA FSR1 0x0000:0x0060 -area DATA FSR2 0x0060:0x008C Ext I/O Reg. -area BSS RESERVED 0x008C:0x0100 -area DATA I_SRAM 0x0100:0x0500 Internal SRAM -area DATA E_SRAM 0x0500:0x10000 External SRAM -; Memory configuration B -; area DATA FSR 0x0000:0x0060 -; area DATA I_SRAM 0x0060:0x0460 Internal SRAM -; area DATA E_SRAM 0x0460:0x10000 External SRAM - - -; Interrupt and reset vector assignments -; if M161C is unprogrammed -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry PCINT0_ 0x0008 Pin Change Interrupt Request 0 -entry PCINT1_ 0x000A Pin Change Interrupt Request 1 -entry TIMER3_CAPT 0x000C Timer/Counter3 Capture Event -entry TIMER3_COMPA 0x000E Timer/Counter3 Compare Match A -entry TIMER3_COMPB 0x0010 Timer/Counter3 Compare Match B -entry TIMER3_OVF 0x0012 Timer/Counter3 Overflow -entry TIMER2_COMP 0x0014 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0016 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0018 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x001A Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x001C Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x001E Timer/Counter1 Overflow -entry TIMER0_COMP 0x0020 Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0022 Timer/Counter0 Overflow -entry SPI_STC 0x0024 Serial Transfer Complete -entry USART0_RXC 0x0026 USART0, Rx Complete -entry USART1_RXC 0x0028 USART1, Rx Complete -entry USART0_UDRE 0x002A USART0 Data Register Empty -entry USART1_UDRE 0x002C USART1 Data Register Empty -entry USART0_TXC 0x002E USART0, Tx Complete -entry USART1_TXC 0x0030 USART1, Tx Complete -entry EE_RDY 0x0032 EEPROM Ready -entry ANA_COMP 0x0034 Analog Comparator -entry SPM_RDY 0x0036 Store Program Memory Ready - -; if M161C is programmed -; entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset -; entry INT0_ 0x0002 External Interrupt Request 0 -; entry INT1_ 0x0004 External Interrupt Request 1 -; entry INT2_ 0x0006 External Interrupt Request 2 -; entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match -; entry TIMER2_OVF 0x000A Timer/Counter2 Overflow -; entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event -; entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A -; entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B -; entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow -; entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match -; entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow -; entry SPI_STC 0x0018 Serial Transfer Complete -; entry USART0_RXC 0x001A USART0, Rx Complete -; entry USART1_RXC 0x001C USART1, Rx Complete -; entry USART0_UDRE 0x001E USART0 Data Register Empty -; entry USART1_UDRE 0x0020 USART1 Data Register Empty -; entry USART0_TXC 0x0022 USART0, Tx Complete -; entry USART1_TXC 0x0024 USART1, Tx Complete -; entry EE_RDY 0x0026 EEPROM Ready -; entry ANA_COMP 0x0028 Analog Comparator -; entry SPM_RDY 0x002A Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -UBRR1L 0x0000 USART1 Baud Rate Register Low Byte -UCSR1B 0x0001 USART Control and Status Register B -UCSR1B.RXCIE 7 RX Complete Interrupt Enable -UCSR1B.TXCIE 6 TX Complete Interrupt Enable -UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSR1B.RXEN 4 Receiver Enable -UCSR1B.TXEN 3 Transmitter Enable -UCSR1B.UCSZ2 2 Character Size -UCSR1B.RXB8 1 Receive Data Bit 8 -UCSR1B.TXB8 0 Transmit Data Bit8 -UCSR1A 0x0002 USART Control and Status Register A -UCSR1A.RXC 7 USART Receive Complete -UCSR1A.TXC 6 USART Transmit Complete -UCSR1A.UDRE 5 USART Data Register Empty -UCSR1A.FE 4 Frame Error -UCSR1A.DOR 3 Data OverRun -UCSR1A.PE 2 Parity Error -UCSR1A.U2X 1 Double the USART Transmission Speed -UCSR1A.MPCM 0 Multi-processor Communication Mode -UDR1 0x0003 USART I/O Data Register -OCDR 0x0004 On-chip Debug Register -; OSCCAL 0x0004 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -PINE 0x0005 Port E Input Pins Address -PINE.PINE2 2 -PINE.PINE1 1 -PINE.PINE0 0 -DDRE 0x0006 Port E Data Direction Register -DDRE.DDE2 2 Port E Data Direction Register bit 2 -DDRE.DDE1 1 Port E Data Direction Register bit 1 -DDRE.DDE0 0 Port E Data Direction Register bit 0 -PORTE 0x0007 Port E Data Register -PORTE.PORTE2 2 Port E Data Register bit 2 -PORTE.PORTE1 1 Port E Data Register bit 1 -PORTE.PORTE0 0 Port E Data Register bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR0L 0x0009 USART0 Baud Rate Register Low Byte -UCSR0B 0x000A USART Control and Status Register B -UCSR0B.RXCIE 7 RX Complete Interrupt Enable -UCSR0B.TXCIE 6 TX Complete Interrupt Enable -UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSR0B.RXEN 4 Receiver Enable -UCSR0B.TXEN 3 Transmitter Enable -UCSR0B.UCSZ2 2 Character Size -UCSR0B.RXB8 1 Receive Data Bit 8 -UCSR0B.TXB8 0 Transmit Data Bit8 -UCSR0A 0x000B USART Control and Status Register A -UCSR0A.RXC 7 USART Receive Complete -UCSR0A.TXC 6 USART Transmit Complete -UCSR0A.UDRE 5 USART Data Register Empty -UCSR0A.FE 4 Frame Error -UCSR0A.DOR 3 Data OverRun -UCSR0A.PE 2 Parity Error -UCSR0A.U2X 1 Double the USART Transmission Speed -UCSR0A.MPCM 0 Multi-processor Communication Mode -UDR0 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register- -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision Flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C The EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low Byte -EEARH 0x001F The EEPROM Address Register High -EEARH.EEAR8 8 EEPROM Address 8 -UCSR0C 0x0020 USART Control and Status Register C (page 180) -UCSR0C.URSEL 7 Register Select -UCSR0C.UMSEL 6 USART Mode Select -UCSR0C.UPM1 5 Parity Mode 1 -UCSR0C.UPM0 4 Parity Mode 0 -UCSR0C.USBS 3 Stop Bit Select -UCSR0C.UCSZ1 2 Character Size 1 -UCSR0C.UCSZ0 1 Character Size 0 -UCSR0C.UCPOL 0 Clock Polarity -; UBRR0H 0x0020 USART Baud Rate Register High -; UBRR0H.URSEL 15 Register Select -; UBRR0H.UBRR11 11 USART Baud Rate Register bit 11 -; UBRR0H.UBRR10 10 USART Baud Rate Register bit 10 -; UBRR0H.UBRR9 9 USART Baud Rate Register bit 9 -; UBRR0H.UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -OCR2 0x0022 Output Compare Register -TCNT2 0x0023 Timer/Counter2 -ICR1L 0x0024 Input Capture Register Low Byte -ICR1H 0x0025 Input Capture Register High Byte -ASSR 0x0026 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -TCCR2 0x0027 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Compare Match Output Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Waveform Generation Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input CaptureEdgeSelect -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 -TCCR1A.FOC1A 3 Force Output Compare for channel A -TCCR1A.FOC1B 2 Force Output Compare for channel B -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -SFIOR 0x0030 Special Function IO Register -SFIOR.TSM 7 Timer/Counter Synchronization Mode -SFIOR.XMBK 6 External Memory Bus Keeper Enable -SFIOR.XMM2 5 External Memory High Mask 2 -SFIOR.XMM1 4 External Memory High Mask 1 -SFIOR.XMM0 3 External Memory High Mask 0 -SFIOR.PUD 2 Pull-up Disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR310 0 Prescaler Reset Timer/Counter3, Timer/Counter1, and Timer/Counter0 -OCR0 0x0031 Timer/Counter0 Output Compare Register -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.JTD 7 JTAG Interface Disable -MCUCSR.SM2 5 Sleep Mode Select Bit 2 -MCUCSR.JTRF 4 JTAG Reset Flag -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM/XMEM Enable -MCUCR.SRW10 6 Wait State Select Bit -MCUCR.SE 5 Sleep Enable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -EMCUCR 0x0036 Extended MCU Control Register -EMCUCR.SM0 7 Sleep Mode Select Bit 0 -EMCUCR.SRL2 6 Wait State Sector Limit 2 -EMCUCR.SRL1 5 Wait State Sector Limit 1 -EMCUCR.SRL0 4 Wait State Sector Limit 0 -EMCUCR.SRW01 3 Wait-state Select Bits for Lower Sector 1 -EMCUCR.SRW00 2 Wait-state Select Bits for Lower Sector 0 -EMCUCR.SRW11 1 Wait-state Select Bits for Upper Sector -EMCUCR.ISC2 0 Interrupt Sense Control 2 -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.SPMIE 7 SPM Interrupt Enable -SPMCR.RWWSB 6 Read-While-Write Section Busy -SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter1, Overflow Flag -TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag -TIFR.OCF2 4 Output Compare Flag 2 -TIFR.ICF1 3 Timer/Counter1, Input Capture Flag -TIFR.TOV2 2 Timer/Counter2 Overflow Flag -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIFR.OCF0 0 Output Compare Flag 0 -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.OCIE2 4 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.TOIE2 2 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -TIMSK.OCIE0 0 Timer/Counter0 Overflow Flag -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIFR.INTF2 5 External Interrupt Flag 2 -GIFR.PCIF1 4 Pin Change Interrupt Flag 1 -GIFR.PCIF0 3 Pin Change Interrupt Flag 0 -GICR 0x003B General Interrupt Control Register -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.INT2 5 External Interrupt Request 2 Enable -GICR.PCIE1 4 Pin Change Interrupt Enable 1 -GICR.PCIE0 3 Pin Change Interrupt Enable 0 -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -UCSR1C 0x003C USART Control and Status Register C (page 180) -UCSR1C.URSEL 7 Register Select -UCSR1C.UMSEL 6 USART Mode Select -UCSR1C.UPM1 5 Parity Mode 1 -UCSR1C.UPM0 4 Parity Mode 0 -UCSR1C.USBS 3 Stop Bit Select -UCSR1C.UCSZ1 2 Character Size 1 -UCSR1C.UCSZ0 1 Character Size 0 -UCSR1C.UCPOL 0 Clock Polarity -; UBRR1H 0x003C USART Baud Rate Register High -; UBRR1H.URSEL 15 Register Select -; UBRR1H.UBRR11 11 USART Baud Rate Register 11 -; UBRR1H.UBRR10 10 USART Baud Rate Register 10 -; UBRR1H.UBRR9 9 USART Baud Rate Register 9 -; UBRR1H.UBRR8 8 USART Baud Rate Register 8 -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 CarryFlag - -; UBRR1L 0x0020 USART1 Baud Rate Register Low Byte -; UCSR1B 0x0021 USART Control and Status Register B -; UCSR1B.RXCIE 7 RX Complete Interrupt Enable -; UCSR1B.TXCIE 6 TX Complete Interrupt Enable -; UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSR1B.RXEN 4 Receiver Enable -; UCSR1B.TXEN 3 Transmitter Enable -; UCSR1B.UCSZ2 2 Character Size -; UCSR1B.RXB8 1 Receive Data Bit 8 -; UCSR1B.TXB8 0 Transmit Data Bit8 -; UCSR1A 0x0022 USART Control and Status Register A -; UCSR1A.RXC 7 USART Receive Complete -; UCSR1A.TXC 6 USART Transmit Complete -; UCSR1A.UDRE 5 USART Data Register Empty -; UCSR1A.FE 4 Frame Error -; UCSR1A.DOR 3 Data OverRun -; UCSR1A.PE 2 Parity Error -; UCSR1A.U2X 1 Double the USART Transmission Speed -; UCSR1A.MPCM 0 Multi-processor Communication Mode -; UDR1 0x0023 USART I/O Data Register -; OCDR 0x0024 On-chip Debug Register -; ; OSCCAL 0x0024 Oscillator Calibration Register -; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; PINE 0x0025 Port E Input Pins Address -; PINE.PINE2 2 -; PINE.PINE1 1 -; PINE.PINE0 0 -; DDRE 0x0026 Port E Data Direction Register -; DDRE.DDE2 2 Port E Data Direction Register bit 2 -; DDRE.DDE1 1 Port E Data Direction Register bit 1 -; DDRE.DDE0 0 Port E Data Direction Register bit 0 -; PORTE 0x0027 Port E Data Register -; PORTE.PORTE2 2 Port E Data Register bit 2 -; PORTE.PORTE1 1 Port E Data Register bit 1 -; PORTE.PORTE0 0 Port E Data Register bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR0L 0x0029 USART0 Baud Rate Register Low Byte -; UCSR0B 0x002A USART Control and Status Register B -; UCSR0B.RXCIE 7 RX Complete Interrupt Enable -; UCSR0B.TXCIE 6 TX Complete Interrupt Enable -; UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSR0B.RXEN 4 Receiver Enable -; UCSR0B.TXEN 3 Transmitter Enable -; UCSR0B.UCSZ2 2 Character Size -; UCSR0B.RXB8 1 Receive Data Bit 8 -; UCSR0B.TXB8 0 Transmit Data Bit8 -; UCSR0A 0x002B USART Control and Status Register A -; UCSR0A.RXC 7 USART Receive Complete -; UCSR0A.TXC 6 USART Transmit Complete -; UCSR0A.UDRE 5 USART Data Register Empty -; UCSR0A.FE 4 Frame Error -; UCSR0A.DOR 3 Data OverRun -; UCSR0A.PE 2 Parity Error -; UCSR0A.U2X 1 Double the USART Transmission Speed -; UCSR0A.MPCM 0 Multi-processor Communication Mode -; UDR0 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register- -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision Flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C The EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low Byte -; EEARH 0x003F The EEPROM Address Register High -; EEARH.EEAR8 8 EEPROM Address 8 -; UCSR0C 0x0040 USART Control and Status Register C (page 180) -; UCSR0C.URSEL 7 Register Select -; UCSR0C.UMSEL 6 USART Mode Select -; UCSR0C.UPM1 5 Parity Mode 1 -; UCSR0C.UPM0 4 Parity Mode 0 -; UCSR0C.USBS 3 Stop Bit Select -; UCSR0C.UCSZ1 2 Character Size 1 -; UCSR0C.UCSZ0 1 Character Size 0 -; UCSR0C.UCPOL 0 Clock Polarity -; ; UBRR0H 0x0040 USART Baud Rate Register High -; ; UBRR0H.URSEL 15 Register Select -; ; UBRR0H.UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRR0H.UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRR0H.UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRR0H.UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; OCR2 0x0042 Output Compare Register -; TCNT2 0x0043 Timer/Counter2 -; ICR1L 0x0044 Input Capture Register Low Byte -; ICR1H 0x0045 Input Capture Register High Byte -; ASSR 0x0046 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; TCCR2 0x0047 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Compare Match Output Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Waveform Generation Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; OCR1BL 0x0048 Output Compare Register B Low Byte -; OCR1BH 0x0049 Output Compare Register B High Byte -; OCR1AL 0x004A Output Compare Register A Low Byte -; OCR1AH 0x004B Output Compare Register A High Byte -; TCNT1L 0x004C Counter Register Low Byte -; TCNT1H 0x004D Counter Register High Byte -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input CaptureEdgeSelect -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 -; TCCR1A.FOC1A 3 Force Output Compare for channel A -; TCCR1A.FOC1B 2 Force Output Compare for channel B -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; SFIOR 0x0050 Special Function IO Register -; SFIOR.TSM 7 Timer/Counter Synchronization Mode -; SFIOR.XMBK 6 External Memory Bus Keeper Enable -; SFIOR.XMM2 5 External Memory High Mask 2 -; SFIOR.XMM1 4 External Memory High Mask 1 -; SFIOR.XMM0 3 External Memory High Mask 0 -; SFIOR.PUD 2 Pull-up Disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR310 0 Prescaler Reset Timer/Counter3, Timer/Counter1, and Timer/Counter0 -; OCR0 0x0051 Timer/Counter0 Output Compare Register -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.JTD 7 JTAG Interface Disable -; MCUCSR.SM2 5 Sleep Mode Select Bit 2 -; MCUCSR.JTRF 4 JTAG Reset Flag -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM/XMEM Enable -; MCUCR.SRW10 6 Wait State Select Bit -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; EMCUCR 0x0056 Extended MCU Control Register -; EMCUCR.SM0 7 Sleep Mode Select Bit 0 -; EMCUCR.SRL2 6 Wait State Sector Limit 2 -; EMCUCR.SRL1 5 Wait State Sector Limit 1 -; EMCUCR.SRL0 4 Wait State Sector Limit 0 -; EMCUCR.SRW01 3 Wait-state Select Bits for Lower Sector 1 -; EMCUCR.SRW00 2 Wait-state Select Bits for Lower Sector 0 -; EMCUCR.SRW11 1 Wait-state Select Bits for Upper Sector -; EMCUCR.ISC2 0 Interrupt Sense Control 2 -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.TOV1 7 Timer/Counter1, Overflow Flag -; TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag -; TIFR.OCF2 4 Output Compare Flag 2 -; TIFR.ICF1 3 Timer/Counter1, Input Capture Flag -; TIFR.TOV2 2 Timer/Counter2 Overflow Flag -; TIFR.TOV0 1 Timer/Counter0 Overflow Flag -; TIFR.OCF0 0 Output Compare Flag 0 -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.OCIE2 4 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.TOIE2 2 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; TIMSK.OCIE0 0 Timer/Counter0 Overflow Flag -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIFR.INTF2 5 External Interrupt Flag 2 -; GIFR.PCIF1 4 Pin Change Interrupt Flag 1 -; GIFR.PCIF0 3 Pin Change Interrupt Flag 0 -; GICR 0x005B General Interrupt Control Register -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.INT2 5 External Interrupt Request 2 Enable -; GICR.PCIE1 4 Pin Change Interrupt Enable 1 -; GICR.PCIE0 3 Pin Change Interrupt Enable 0 -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; UCSR1C 0x005C USART Control and Status Register C (page 180) -; UCSR1C.URSEL 7 Register Select -; UCSR1C.UMSEL 6 USART Mode Select -; UCSR1C.UPM1 5 Parity Mode 1 -; UCSR1C.UPM0 4 Parity Mode 0 -; UCSR1C.USBS 3 Stop Bit Select -; UCSR1C.UCSZ1 2 Character Size 1 -; UCSR1C.UCSZ0 1 Character Size 0 -; UCSR1C.UCPOL 0 Clock Polarity -; ; UBRR1H 0x005C USART Baud Rate Register High -; ; UBRR1H.URSEL 15 Register Select -; ; UBRR1H.UBRR11 11 USART Baud Rate Register 11 -; ; UBRR1H.UBRR10 10 USART Baud Rate Register 10 -; ; UBRR1H.UBRR9 9 USART Baud Rate Register 9 -; ; UBRR1H.UBRR8 8 USART Baud Rate Register 8 -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 CarryFlag -; RESERVED0060 0x0060 RESERVED -; CLKPR 0x0061 Clock Prescale Register -; CLKPR.CPCE 7 Clock Prescaler Change Enable -; CLKPR.CLKPS3 3 Clock Prescaler Select Bit 3 -; CLKPR.CLKPS2 2 Clock Prescaler Select Bit 2 -; CLKPR.CLKPS1 1 Clock Prescaler Select Bit 1 -; CLKPR.CLKPS0 0 Clock Prescaler Select Bit 0 -; RESERVED0062 0x0062 RESERVED -; RESERVED0063 0x0063 RESERVED -; RESERVED0064 0x0064 RESERVED -; RESERVED0065 0x0065 RESERVED -; RESERVED0066 0x0066 RESERVED -; RESERVED0067 0x0067 RESERVED -; RESERVED0068 0x0068 RESERVED -; RESERVED0069 0x0069 RESERVED -; RESERVED006A 0x006A RESERVED -; PCMSK0 0x006B Pin Change Mask Register 0 -; PCMSK0.PCINT7 7 Pin Change Enable Mask 7 -; PCMSK0.PCINT6 6 Pin Change Enable Mask 6 -; PCMSK0.PCINT5 5 Pin Change Enable Mask 5 -; PCMSK0.PCINT4 4 Pin Change Enable Mask 4 -; PCMSK0.PCINT3 3 Pin Change Enable Mask 3 -; PCMSK0.PCINT2 2 Pin Change Enable Mask 2 -; PCMSK0.PCINT1 1 Pin Change Enable Mask 1 -; PCMSK0.PCINT0 0 Pin Change Enable Mask 0 -; PCMSK1 0x006C Pin Change Mask Register 1 -; PCMSK1.PCINT15 15 Pin Change Enable Mask 15 -; PCMSK1.PCINT14 14 Pin Change Enable Mask 14 -; PCMSK1.PCINT13 13 Pin Change Enable Mask 13 -; PCMSK1.PCINT12 12 Pin Change Enable Mask 12 -; PCMSK1.PCINT11 11 Pin Change Enable Mask 11 -; PCMSK1.PCINT10 10 Pin Change Enable Mask 10 -; PCMSK1.PCINT9 9 Pin Change Enable Mask 9 -; PCMSK1.PCINT8 8 Pin Change Enable Mask 8 -; RESERVED006D 0x006D RESERVED -; RESERVED006E 0x006E RESERVED -; RESERVED006F 0x006F RESERVED -; RESERVED0070 0x0070 RESERVED -; RESERVED0071 0x0071 RESERVED -; RESERVED0072 0x0072 RESERVED -; RESERVED0073 0x0073 RESERVED -; RESERVED0074 0x0074 RESERVED -; RESERVED0075 0x0075 RESERVED -; RESERVED0076 0x0076 RESERVED -; RESERVED0077 0x0077 RESERVED -; RESERVED0078 0x0078 RESERVED -; RESERVED0079 0x0079 RESERVED -; RESERVED007A 0x007A RESERVED -; RESERVED007B 0x007B RESERVED -; ETIFR 0x007C Extended Timer/Counter Interrupt Flag Register -; ETIFR.ICF3 5 Timer/Counter3, Input Capture Flag -; ETIFR.OCF3A 4 Timer/Counter3, Output Compare A Match Flag -; ETIFR.OC3FB 3 Timer/Counter3, Output Compare B Match Flag -; ETIFR.TOV3 2 Timer/Counter3, Overflow Flag -; ETIMSK 0x007D Extended Timer/Counter Interrupt Mask Register -; ETIMSK.TICIE3 5 Timer/Counter3, Input Capture Interrupt Enable -; ETIMSK.OCIE3A 4 Timer/Counter3, Output Compare A Match Interrupt Enable -; ETIMSK.OCIE3B 3 Timer/Counter3, Output Compare B Match Interrupt Enable -; ETIMSK.TOIE3 2 Timer/Counter3, Overflow Interrupt Enable -; RESERVED007E 0x007E RESERVED -; RESERVED007F 0x007F RESERVED -; ICR3L 0x0080 Input Capture Register Low Byte -; ICR3H 0x0081 Input Capture Register High Byte -; RESERVED0082 0x0082 RESERVED -; RESERVED0083 0x0083 RESERVED -; OCR3BL 0x0084 Output Compare Register B Low Byte -; OCR3BH 0x0085 Output Compare Register B High Byte -; OCR3AL 0x0086 Output Compare Register A Low Byte -; OCR3AH 0x0087 Output Compare Register A High Byte -; TCNT3L 0x0088 Counter Register Low Byte -; TCNT3H 0x0089 Counter Register High Byte -; TCCR3B 0x008A Timer/Counter3 Control Register A -; TCCR3B.COM3A1 7 Compare Output Mode for channel A 1 -; TCCR3B.COM3A0 6 Compare Output Mode for channel A 0 -; TCCR3B.COM3B1 5 Compare Output Mode for channel B 1 -; TCCR3B.COM3B0 4 Compare Output Mode for channel B 0 -; TCCR3B.FOC3A 3 Force Output Compare for channel A -; TCCR3B.FOC3B 2 Force Output Compare for channel B -; TCCR3B.WGM31 1 Waveform Generation Mode 1 -; TCCR3B.WGM30 0 Waveform Generation Mode 0 -; TCCR3A 0x008B Timer/Counter3 Control Register B -; TCCR3A.ICNC3 7 Input Capture Noise Canceler -; TCCR3A.ICES3 6 Input CaptureEdgeSelect -; TCCR3A.WGM33 4 Waveform Generation Mode 3 -; TCCR3A.WGM32 3 Waveform Generation Mode 2 -; TCCR3A.CS32 2 Clock Select 2 -; TCCR3A.CS31 1 Clock Select 1 -; TCCR3A.CS30 0 Clock Select 0 - - -.ATmega163_L -SUBARCH=5 -; doc1142.pdf -; - -RAM=1024 -ROM=16384 -EEPROM=512 - -; MEMORY MAP - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry TIMER2_COMP 0x0006 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0008 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x000A Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x000C Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x000E Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0010 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0012 Timer/Counter0 Overflow -entry SPI_STC 0x0014 Serial Transfer Complete -entry UART_RXC 0x0016 UART, Rx Complete -entry UART_UDRE 0x0018 UART Data Register Empty -entry UART_TXC 0x001A UART, Tx Complete -entry ADC_ 0x001C ADC Conversion Complete -entry EE_RDY 0x001E EEPROM Ready -entry ANA_COMP 0x0020 Analog Comparator -entry TWI_ 0x0022 2-wire Serial Interface - - -; INPUT/OUTPUT PORTS -TWBR 0x0000 The 2-wire Serial Interface Bit Rate Register -TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 -TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 -TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 -TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 -TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 -TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 -TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 -TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 -TWSR 0x0001 The 2-wire Serial Interface Status Register -TWSR.TWS7 7 2-wire Serial Interface Status bit 7 -TWSR.TWS6 6 2-wire Serial Interface Status bit 6 -TWSR.TWS5 5 2-wire Serial Interface Status bit 5 -TWSR.TWS4 4 2-wire Serial Interface Status bit 4 -TWSR.TWS3 3 2-wire Serial Interface Status bit 3 -TWAR 0x0002 The 2-wire Serial Interface (Slave) Address Register -TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 -TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 -TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 -TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 -TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 -TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 -TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 -TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable Bit -TWDR 0x0003 The 2-wire Serial Interface Data Register -TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 -TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 -TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 -TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 -TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 -TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 -TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 -TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 -ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion result 7 -ADCL.ADC6 6 ADC Conversion result 6 -ADCL.ADC5 5 ADC Conversion result 5 -ADCL.ADC4 4 ADC Conversion result 4 -ADCL.ADC3 3 ADC Conversion result 3 -ADCL.ADC2 2 ADC Conversion result 2 -ADCL.ADC1 1 ADC Conversion result 1 -ADCL.ADC0 0 ADC Conversion result 0 -ADCH 0x0005 The ADC Data Register High (ADLAR = 0) -ADCH.SIGN 15 -ADCH.ADC9 9 ADC Conversion result 9 -ADCH.ADC8 8 ADC Conversion result 8 -; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion result 1 -; ADCL.ADC0 6 ADC Conversion result 0 -; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion result 9 -; ADCH.ADC8 14 ADC Conversion result 8 -; ADCH.ADC7 13 ADC Conversion result 7 -; ADCH.ADC6 12 ADC Conversion result 6 -; ADCH.ADC5 11 ADC Conversion result 5 -; ADCH.ADC4 10 ADC Conversion result 4 -; ADCH.ADC3 9 ADC Conversion result 3 -; ADCH.ADC2 8 ADC Conversion result 2 -ADCSR 0x0006 The ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Running Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 The ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control And Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR 0x0009 UART Baud Rate Register -UCSRB 0x000A UART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.CHR9 2 9 Bit Characters -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B UART Control and Status Register A -UCSRA.RXC 7 UART Receive Complete -UCSRA.TXC 6 UART Transmit Complete -UCSRA.UDRE 5 UART Data Register Empty -UCSRA.FE 4 Framing Error -UCSRA.OR 3 OverRun -UCSRA.U2X 1 Double the UART Transmission Speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C UART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E The SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision Flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C The EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Address 7 -EEARL.EEAR6 6 EEPROM Address 6 -EEARL.EEAR5 5 EEPROM Address 5 -EEARL.EEAR4 4 EEPROM Address 4 -EEARL.EEAR3 3 EEPROM Address 3 -EEARL.EEAR2 2 EEPROM Address 2 -EEARL.EEAR1 1 EEPROM Address 1 -EEARL.EEAR0 0 EEPROM Address 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR8 8 EEPROM Address 8 -UBRRHI 0x0020 UART Baud Rate Register -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -OCR2 0x0023 Timer/Counter2 Output Compare Register -TCNT2 0x0024 Timer/Counter2 -TCCR2 0x0025 Timer/Counter2 Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.PWM2 6 Pulse Width Modulator Enable -TCCR2.COM21 5 Compare Output Mode, bit 1 -TCCR2.COM20 4 Compare Output Mode, bit 0 -TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -TCCR2.CS22 2 Clock Select Bit 2 -TCCR2.CS21 1 Clock Select Bit 1 -TCCR2.CS20 0 Clock Select Bit 0 -ICR1L 0x0026 Input Capture Register Low Byte -ICR1H 0x0027 Input Capture Register High Byte -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1, Bit 2 -TCCR1B.CS11 1 Clock Select1, Bit 1 -TCCR1B.CS10 0 Clock Select1, Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -TCCR1A.FOC1A 3 Force Output Compare1A -TCCR1A.FOC1B 2 Force Output Compare1B -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -SFIOR 0x0030 Special Function I/O Register -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up Disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter 0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.WDRF 3 Watchdog Reset Flag -MCUSR.BORF 2 Brown-out Reset Flag -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 6 Sleep Enable -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -TWCR 0x0036 2-wire Serial Interface Control Register -TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag -TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag -TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag -TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag -TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag -TWCR.TWEN 2 2-wire Serial Interface Enable Bit -TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.ASB 6 Application Section Busy -SPMCR.ASRE 4 Application Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Input Capture Flag 1 -TIFR.OCF1A 4 Output Compare Flag 1A -TIFR.OCF1B 3 Output Compare Flag 1B -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag1 -GIFR.INTF0 6 External Interrupt Flag0 -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; TWBR 0x0020 The 2-wire Serial Interface Bit Rate Register -; TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 -; TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 -; TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 -; TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 -; TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 -; TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 -; TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 -; TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 -; TWSR 0x0021 The 2-wire Serial Interface Status Register -; TWSR.TWS7 7 2-wire Serial Interface Status bit 7 -; TWSR.TWS6 6 2-wire Serial Interface Status bit 6 -; TWSR.TWS5 5 2-wire Serial Interface Status bit 5 -; TWSR.TWS4 4 2-wire Serial Interface Status bit 4 -; TWSR.TWS3 3 2-wire Serial Interface Status bit 3 -; TWAR 0x0022 The 2-wire Serial Interface (Slave) Address Register -; TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 -; TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 -; TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 -; TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 -; TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 -; TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 -; TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 -; TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable Bit -; TWDR 0x0023 The 2-wire Serial Interface Data Register -; TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 -; TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 -; TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 -; TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 -; TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 -; TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 -; TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 -; TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 -; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion result 7 -; ADCL.ADC6 6 ADC Conversion result 6 -; ADCL.ADC5 5 ADC Conversion result 5 -; ADCL.ADC4 4 ADC Conversion result 4 -; ADCL.ADC3 3 ADC Conversion result 3 -; ADCL.ADC2 2 ADC Conversion result 2 -; ADCL.ADC1 1 ADC Conversion result 1 -; ADCL.ADC0 0 ADC Conversion result 0 -; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) -; ADCH.SIGN 15 -; ADCH.ADC9 9 ADC Conversion result 9 -; ADCH.ADC8 8 ADC Conversion result 8 -; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion result 1 -; ; ADCL.ADC0 6 ADC Conversion result 0 -; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion result 9 -; ; ADCH.ADC8 14 ADC Conversion result 8 -; ; ADCH.ADC7 13 ADC Conversion result 7 -; ; ADCH.ADC6 12 ADC Conversion result 6 -; ; ADCH.ADC5 11 ADC Conversion result 5 -; ; ADCH.ADC4 10 ADC Conversion result 4 -; ; ADCH.ADC3 9 ADC Conversion result 3 -; ; ADCH.ADC2 8 ADC Conversion result 2 -; ADCSR 0x0026 The ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADFR 5 ADC Free Running Select -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 The ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control And Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR 0x0029 UART Baud Rate Register -; UCSRB 0x002A UART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.CHR9 2 9 Bit Characters -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B UART Control and Status Register A -; UCSRA.RXC 7 UART Receive Complete -; UCSRA.TXC 6 UART Transmit Complete -; UCSRA.UDRE 5 UART Data Register Empty -; UCSRA.FE 4 Framing Error -; UCSRA.OR 3 OverRun -; UCSRA.U2X 1 Double the UART Transmission Speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C UART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E The SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision Flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C The EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Address 7 -; EEARL.EEAR6 6 EEPROM Address 6 -; EEARL.EEAR5 5 EEPROM Address 5 -; EEARL.EEAR4 4 EEPROM Address 4 -; EEARL.EEAR3 3 EEPROM Address 3 -; EEARL.EEAR2 2 EEPROM Address 2 -; EEARL.EEAR1 1 EEPROM Address 1 -; EEARL.EEAR0 0 EEPROM Address 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR8 8 EEPROM Address 8 -; UBRRHI 0x0040 UART Baud Rate Register -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; OCR2 0x0043 Timer/Counter2 Output Compare Register -; TCNT2 0x0044 Timer/Counter2 -; TCCR2 0x0045 Timer/Counter2 Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.PWM2 6 Pulse Width Modulator Enable -; TCCR2.COM21 5 Compare Output Mode, bit 1 -; TCCR2.COM20 4 Compare Output Mode, bit 0 -; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -; TCCR2.CS22 2 Clock Select Bit 2 -; TCCR2.CS21 1 Clock Select Bit 1 -; TCCR2.CS20 0 Clock Select Bit 0 -; ICR1L 0x0046 Input Capture Register Low Byte -; ICR1H 0x0047 Input Capture Register High Byte -; OCR1BL 0x0048 Output Compare Register B Low Byte -; OCR1BH 0x0049 Output Compare Register B High Byte -; OCR1AL 0x004A Output Compare Register A Low Byte -; OCR1AH 0x004B Output Compare Register A High Byte -; TCNT1L 0x004C Counter Register Low Byte -; TCNT1H 0x004D Counter Register High Byte -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1, Bit 2 -; TCCR1B.CS11 1 Clock Select1, Bit 1 -; TCCR1B.CS10 0 Clock Select1, Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 -; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 -; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 -; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 -; TCCR1A.FOC1A 3 Force Output Compare1A -; TCCR1A.FOC1B 2 Force Output Compare1B -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; SFIOR 0x0050 Special Function I/O Register -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up Disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OSCCAL 0x0051 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter 0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.WDRF 3 Watchdog Reset Flag -; MCUSR.BORF 2 Brown-out Reset Flag -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 6 Sleep Enable -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; TWCR 0x0056 2-wire Serial Interface Control Register -; TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag -; TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag -; TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag -; TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag -; TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag -; TWCR.TWEN 2 2-wire Serial Interface Enable Bit -; TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.ASB 6 Application Section Busy -; SPMCR.ASRE 4 Application Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Input Capture Flag 1 -; TIFR.OCF1A 4 Output Compare Flag 1A -; TIFR.OCF1B 3 Output Compare Flag 1B -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag1 -; GIFR.INTF0 6 External Interrupt Flag0 -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT1 7 External Interrupt Request 1 Enable -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; RESERVED003C 0x005C RESERVED -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega16_L -SUBARCH=5 -; doc2466.pdf -; - -RAM=1024 -ROM=16384 -EEPROM=512 - -; MEMORY MAP -area DATA FSR 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x0460 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry TIMER2_COMP 0x0006 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0008 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x000A Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x000C Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x000E Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0010 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0012 Timer/Counter0 Overflow -entry SPI_STC 0x0014 Serial Transfer Complete -entry USART_RXC 0x0016 USART, Rx Complete -entry USART_UDRE 0x0018 USART Data Register Empty -entry USART_TXC 0x001A USART, Tx Complete -entry ADC_ 0x001C ADC Conversion Complete -entry EE_RDY 0x001E EEPROM Ready -entry ANA_COMP 0x0020 Analog Comparator -entry TWI_ 0x0022 Two-wire Serial Interface -entry INT2 0x0024 External Interrupt Request 2 -entry TIMER0_COMP 0x0026 Timer/Counter0 Compare Match -entry SPM_RDY 0x0028 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -TWBR 0x0000 TWI Bit Rate Register -TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -TWSR 0x0001 TWI Status Register -TWSR.TWS7 7 TWI Status 7 -TWSR.TWS6 6 TWI Status 6 -TWSR.TWS5 5 TWI Status 5 -TWSR.TWS4 4 TWI Status 4 -TWSR.TWS3 3 TWI Status 3 -TWSR.TWS1 1 TWI Status 1 -TWSR.TWS0 0 TWI Status 0 -TWAR 0x0002 TWI (Slave) Address Register -TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -TWDR 0x0003 TWI Data Register -TWDR.TWD7 7 TWI Data Register bit 7 -TWDR.TWD6 6 TWI Data Register bit 6 -TWDR.TWD5 5 TWI Data Register bit 5 -TWDR.TWD4 4 TWI Data Register bit 4 -TWDR.TWD3 3 TWI Data Register bit 3 -TWDR.TWD2 2 TWI Data Register bit 2 -TWDR.TWD1 1 TWI Data Register bit 1 -TWDR.TWD0 0 TWI Data Register bit 0 -ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 -ADCL.ADC6 6 -ADCL.ADC5 5 -ADCL.ADC4 4 -ADCL.ADC3 3 -ADCL.ADC2 2 -ADCL.ADC1 1 -ADCL.ADC0 0 -ADCH 0x0005 The ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 -ADCH.ADC8 8 -; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 -; ADCL.ADC0 6 -; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 7 -; ADCH.ADC8 6 -; ADCH.ADC7 5 -; ADCH.ADC6 4 -; ADCH.ADC5 3 -; ADCH.ADC4 2 -; ADCH.ADC3 1 -; ADCH.ADC2 0 -ADCSRA 0x0006 ADC Control and Status Register A -ADCSRA.ADEN 7 ADC Enable -ADCSRA.ADSC 6 ADC Start Conversion -ADCSRA.ADATE 5 ADC Auto Trigger Enable -ADCSRA.ADIF 4 ADC Interrupt Flag -ADCSRA.ADIE 3 ADC Interrupt Enable -ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register Low Byte -UCSRB 0x000A USART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B USART Control and Status Register A -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.PE 2 Parity Error -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR8 8 EEPROM Addres 8 -UCSRC 0x0020 USART Control and Status Register C (page 155) -UCSRC.URSEL 7 Register Select -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -; UBRRH 0x0020 USART Baud Rate Register High (page 155) -; UBRRH.URSEL 15 Register Select -; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -OCR2 0x0023 Output Compare Register -TCNT2 0x0024 Timer/Counter Register -TCCR2 0x0025 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Waveform Generation Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Compare Match Output Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -ICR1L 0x0026 Input Capture Register Low Byte -ICR1H 0x0027 Input Capture Register High Byte -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input Capture Edge Select -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.FOC1A 3 Force Output Compare for Channel A -TCCR1A.FOC1B 2 Force Output Compare for Channel B -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -SFIOR 0x0030 Special Function I/O Register -SFIOR.ADTS2 7 ADC Auto Trigger Source 2 -SFIOR.ADTS1 6 ADC Auto Trigger Source 1 -SFIOR.ADTS0 5 ADC Auto Trigger Source 0 -SFIOR.ADHSM 4 ADC High Speed Mode -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OCDR 0x0031 On-chip Debug Register -; OSCCAL 0x0031 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter Register -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.JTD 7 JTAG Interface Disable -MCUCSR.ISC2 6 Interrupt Sense Control 2 -MCUCSR.JTRF 4 JTAG Reset Flag -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SM2 7 Sleep Mode Select Bit 2 -MCUCR.SE 6 Sleep Enable -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -TWCR 0x0036 TWI Control Register -TWCR.TWINT 7 TWI Interrupt Flag -TWCR.TWEA 6 TWI Enable Acknowledge Bit -TWCR.TWSTA 5 TWI START Condition Bit -TWCR.TWSTO 4 TWI STOP Condition Bit -TWCR.TWWC 3 TWI Write Collision Flag -TWCR.TWEN 2 TWI Enable Bit -TWCR.TWIE 0 TWI Interrupt Enable -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.SPMIE 7 SPM Interrupt Enable -SPMCR.RWWSB 6 Read-While-Write Section Busy -SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter0 Overflow Flag 2 -TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -TIFR.TOV1 2 Timer/Counter0 Overflow Flag 1 -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag 0 -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIFR.INTF2 5 External Interrupt Flag 2 -GICR 0x003B General Interrupt Control Register -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.INT2 5 External Interrupt Request 2 Enable -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -OCR0 0x003C Output Compare Register -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 CarryFlag - -; TWBR 0x0020 TWI Bit Rate Register -; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -; TWSR 0x0021 TWI Status Register -; TWSR.TWS7 7 TWI Status 7 -; TWSR.TWS6 6 TWI Status 6 -; TWSR.TWS5 5 TWI Status 5 -; TWSR.TWS4 4 TWI Status 4 -; TWSR.TWS3 3 TWI Status 3 -; TWSR.TWS1 1 TWI Status 1 -; TWSR.TWS0 0 TWI Status 0 -; TWAR 0x0022 TWI (Slave) Address Register -; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -; TWDR 0x0023 TWI Data Register -; TWDR.TWD7 7 TWI Data Register bit 7 -; TWDR.TWD6 6 TWI Data Register bit 6 -; TWDR.TWD5 5 TWI Data Register bit 5 -; TWDR.TWD4 4 TWI Data Register bit 4 -; TWDR.TWD3 3 TWI Data Register bit 3 -; TWDR.TWD2 2 TWI Data Register bit 2 -; TWDR.TWD1 1 TWI Data Register bit 1 -; TWDR.TWD0 0 TWI Data Register bit 0 -; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 -; ADCL.ADC6 6 -; ADCL.ADC5 5 -; ADCL.ADC4 4 -; ADCL.ADC3 3 -; ADCL.ADC2 2 -; ADCL.ADC1 1 -; ADCL.ADC0 0 -; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 -; ADCH.ADC8 8 -; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 -; ; ADCL.ADC0 6 -; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 7 -; ; ADCH.ADC8 6 -; ; ADCH.ADC7 5 -; ; ADCH.ADC6 4 -; ; ADCH.ADC5 3 -; ; ADCH.ADC4 2 -; ; ADCH.ADC3 1 -; ; ADCH.ADC2 0 -; ADCSRA 0x0026 ADC Control and Status Register A -; ADCSRA.ADEN 7 ADC Enable -; ADCSRA.ADSC 6 ADC Start Conversion -; ADCSRA.ADATE 5 ADC Auto Trigger Enable -; ADCSRA.ADIF 4 ADC Interrupt Flag -; ADCSRA.ADIE 3 ADC Interrupt Enable -; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRRL 0x0029 USART Baud Rate Register Low Byte -; UCSRB 0x002A USART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.UCSZ2 2 Character Size -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B USART Control and Status Register A -; UCSRA.RXC 7 USART Receive Complete -; UCSRA.TXC 6 USART Transmit Complete -; UCSRA.UDRE 5 USART Data Register Empty -; UCSRA.FE 4 Frame Error -; UCSRA.DOR 3 Data OverRun -; UCSRA.PE 2 Parity Error -; UCSRA.U2X 1 Double the USART Transmission Speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR8 8 EEPROM Addres 8 -; UCSRC 0x0040 USART Control and Status Register C (page 155) -; UCSRC.URSEL 7 Register Select -; UCSRC.UMSEL 6 USART Mode Select -; UCSRC.UPM1 5 Parity Mode 1 -; UCSRC.UPM0 4 Parity Mode 0 -; UCSRC.USBS 3 Stop Bit Select -; UCSRC.UCSZ1 2 Character Size 1 -; UCSRC.UCSZ0 1 Character Size 0 -; UCSRC.UCPOL 0 Clock Polarity -; ; UBRRH 0x0040 USART Baud Rate Register High (page 155) -; ; UBRRH.URSEL 15 Register Select -; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; OCR2 0x0043 Output Compare Register -; TCNT2 0x0044 Timer/Counter Register -; TCCR2 0x0045 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Waveform Generation Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Compare Match Output Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; ICR1L 0x0046 Input Capture Register Low Byte -; ICR1H 0x0047 Input Capture Register High Byte -; OCR1BL 0x0048 Output Compare Register B Low Byte -; OCR1BH 0x0049 Output Compare Register B High Byte -; OCR1AL 0x004A Output Compare Register A Low Byte -; OCR1AH 0x004B Output Compare Register A High Byte -; TCNT1L 0x004C Counter Register Low Byte -; TCNT1H 0x004D Counter Register High Byte -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input Capture Edge Select -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -; TCCR1A.FOC1A 3 Force Output Compare for Channel A -; TCCR1A.FOC1B 2 Force Output Compare for Channel B -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; SFIOR 0x0050 Special Function I/O Register -; SFIOR.ADTS2 7 ADC Auto Trigger Source 2 -; SFIOR.ADTS1 6 ADC Auto Trigger Source 1 -; SFIOR.ADTS0 5 ADC Auto Trigger Source 0 -; SFIOR.ADHSM 4 ADC High Speed Mode -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OCDR 0x0051 On-chip Debug Register -; ; OSCCAL 0x0051 Oscillator Calibration Register -; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter Register -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.JTD 7 JTAG Interface Disable -; MCUCSR.ISC2 6 Interrupt Sense Control 2 -; MCUCSR.JTRF 4 JTAG Reset Flag -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SM2 7 Sleep Mode Select Bit 2 -; MCUCR.SE 6 Sleep Enable -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; TWCR 0x0056 TWI Control Register -; TWCR.TWINT 7 TWI Interrupt Flag -; TWCR.TWEA 6 TWI Enable Acknowledge Bit -; TWCR.TWSTA 5 TWI START Condition Bit -; TWCR.TWSTO 4 TWI STOP Condition Bit -; TWCR.TWWC 3 TWI Write Collision Flag -; TWCR.TWEN 2 TWI Enable Bit -; TWCR.TWIE 0 TWI Interrupt Enable -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter0 Overflow Flag 2 -; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -; TIFR.TOV1 2 Timer/Counter0 Overflow Flag 1 -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag 0 -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIFR.INTF2 5 External Interrupt Flag 2 -; GICR 0x005B General Interrupt Control Register -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.INT2 5 External Interrupt Request 2 Enable -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; OCR0 0x005C Output Compare Register -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 CarryFlag - - -.ATmega323_L -SUBARCH=5 -; doc1457.pdf -; - -RAM=2048 -ROM=32768 -EEPROM=1024 - - -; MEMORY MAP - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x000A Timer/Counter2 Overflow -entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow -entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow -entry SPI_STC 0x0018 Serial Transfer Complete -entry USART_RXC 0x001A USART, Rx Complete -entry USART_UDRE 0x001C USART Data Register Empty -entry USART_TXC 0x001E USART, Tx Complete -entry ADC_ 0x0020 ADC Conversion Complete -entry EE_RDY 0x0022 EEPROM Ready -entry ANA_COMP 0x0024 Analog Comparator -entry TWSI_ 0x0026 2-wire Serial Interface - - -; INPUT/OUTPUT PORTS -TWBR 0x0000 2-wire Serial Interface Bit vRate Register -TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 -TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 -TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 -TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 -TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 -TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 -TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 -TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 -TWSR 0x0001 2-wire Serial Interface Status Register -TWSR.TWS7 7 2-wire Serial Interface Status bit 7 -TWSR.TWS6 6 2-wire Serial Interface Status bit 6 -TWSR.TWS5 5 2-wire Serial Interface Status bit 5 -TWSR.TWS4 4 2-wire Serial Interface Status bit 4 -TWSR.TWS3 3 2-wire Serial Interface Status bit 3 -TWAR 0x0002 2-wire Serial Interface (Slave) Address Register -TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 -TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 -TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 -TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 -TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 -TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 -TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 -TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable bit -TWDR 0x0003 2-wire Serial Interface Data Register -TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 -TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 -TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 -TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 -TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 -TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 -TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 -TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 -ADCL 0x0004 ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion Result 7 -ADCL.ADC6 6 ADC Conversion Result 6 -ADCL.ADC5 5 ADC Conversion Result 5 -ADCL.ADC4 4 ADC Conversion Result 4 -ADCL.ADC3 3 ADC Conversion Result 3 -ADCL.ADC2 2 ADC Conversion Result 2 -ADCL.ADC1 1 ADC Conversion Result 1 -ADCL.ADC0 0 ADC Conversion Result 0 -ADCH 0x0005 ADC Data Register High (ADLAR = 0) -ADCH.SIGN 15 -ADCH.ADC9 9 ADC Conversion Result 9 -ADCH.ADC8 8 ADC Conversion Result 8 -; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion Result 1 -; ADCL.ADC0 6 ADC Conversion Result 0 -; ADCH 0x0005 ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion Result 9 -; ADCH.ADC8 14 ADC Conversion Result 8 -; ADCH.ADC7 13 ADC Conversion Result 7 -; ADCH.ADC6 12 ADC Conversion Result 6 -; ADCH.ADC5 11 ADC Conversion Result 5 -; ADCH.ADC4 10 ADC Conversion Result 4 -; ADCH.ADC3 9 ADC Conversion Result 3 -; ADCH.ADC2 8 ADC Conversion Result 2 -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Running Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel Selection Bit 4 -ADMUX.MUX3 3 Analog Channel Selection Bit 3 -ADMUX.MUX2 2 Analog Channel Selection Bit 2 -ADMUX.MUX1 1 Analog Channel Selection Bit 1 -ADMUX.MUX0 0 Analog Channel Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register Low -UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -UCSRB 0x000A USART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B USART Control and Status Register A -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.PE 2 Parity Error -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR9 9 EEPROM Addres 9 -EEARH.EEAR8 8 EEPROM Addres 8 -UCSRC 0x0020 USART Control and Status Register (page 91) -UCSRC.URSEL 7 Register Select -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -; UBRRH 0x0020 USART Baud Rate Register High (page 91) -; UBRRH.URSEL 15 Register Select -; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watch Dog Turn-off Enable -WDTCR.WDE 3 Watch Dog Enable -WDTCR.WDP2 2 Watch Dog Timer Prescaler 2 -WDTCR.WDP1 1 Watch Dog Timer Prescaler 1 -WDTCR.WDP0 0 Watch Dog Timer Prescaler 0 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -OCR2 0x0023 Timer/Counter2 Output Compare Register -TCNT2 0x0024 Timer/Counter2 -TCCR2 0x0025 Timer/Counter2 Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.PWM2 6 Pulse Width Modulator Enable -TCCR2.COM21 5 Compare Output Mode, Bit 1 -TCCR2.COM20 4 Compare Output Mode, Bit 0 -TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -TCCR2.CS22 2 Clock Select bit 2 -TCCR2.CS21 1 Clock Select bit 1 -TCCR2.CS20 0 Clock Select bit 0 -ICR1L 0x0026 Input Capture Register Low Byte -ICR1H 0x0027 Input Capture Register High Byte -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -TCCR1B.ICES1 6 Input Capture1 Edge Select -TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -TCCR1B.CS12 2 Clock Select1, Bit 2 -TCCR1B.CS11 1 Clock Select1, Bit 1 -TCCR1B.CS10 0 Clock Select1, Bit 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode1A, bit 1 -TCCR1A.COM1A0 6 Compare Output Mode1A, bit 0 -TCCR1A.COM1B1 5 Compare Output Mode1B, bit 1 -TCCR1A.COM1B0 4 Compare Output Mode1B, bit 0 -TCCR1A.FOC1A 3 Force Output Compare1A -TCCR1A.FOC1B 2 Force Output Compare1B -TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -SFIOR 0x0030 Special Function IO Register -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up Disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OCRD 0x0031 On-chip Debug Register -; OSCCAL 0x0031 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.PWM0 6 Pulse Width Modulator Enable -TCCR0.COM01 5 Compare Output Mode, Bit 1 -TCCR0.COM00 4 Compare Output Mode, Bit 0 -TCCR0.CTC0 3 Clear Timer/Counter on Compare Match -TCCR0.CS02 2 Clock Select bit 2 -TCCR0.CS01 1 Clock Select bit 1 -TCCR0.CS00 0 Clock Select bit 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.JTD 7 JTAG interface disable -MCUCSR.ISC2 6 Interrupt Sense Control 2 -MCUCSR.JTRF 4 JTAG Reset Flag -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 7 Sleep Enable -MCUCR.SM2 6 Sleep Mode Select Bit 2 -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -TWCR 0x0036 2-wire Serial Interface Control Register -TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag -TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag -TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag -TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag -TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag -TWCR.TWEN 2 2-wire Serial Interface Enable Bit -TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.ASB 6 Application Section Busy -SPMCR.ASRE 4 Application Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Input Capture Flag 1 -TIFR.OCF1A 4 Output Compare Flag 1A -TIFR.OCF1B 3 Output Compare Flag 1B -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Flag Register -TIMSK.OCF2 7 Output Compare Flag 2 -TIMSK.TOV2 6 Timer/Counter2 Overflow Flag -TIMSK.ICF1 5 Input Capture Flag 1 -TIMSK.OCF1A 4 Output Compare Flag 1A -TIMSK.OCF1B 3 Output Compare Flag 1B -TIMSK.TOV1 2 Timer/Counter1 Overflow Flag -TIMSK.OCF0 1 Output Compare Flag 0 -TIMSK.TOV0 0 Timer/Counter0 Overflow Flag -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag1 -GIFR.INTF0 6 External Interrupt Flag0 -GIFR.INTF2 5 External Interrupt Flag2 -GICR 0x003B General Interrupt Control Register -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.INT2 5 External Interrupt Request 2 Enable -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -OCR0 0x003C Timer/Counter0 Output Compare Register -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; TWBR 0x0020 2-wire Serial Interface Bit vRate Register -; TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 -; TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 -; TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 -; TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 -; TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 -; TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 -; TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 -; TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 -; TWSR 0x0021 2-wire Serial Interface Status Register -; TWSR.TWS7 7 2-wire Serial Interface Status bit 7 -; TWSR.TWS6 6 2-wire Serial Interface Status bit 6 -; TWSR.TWS5 5 2-wire Serial Interface Status bit 5 -; TWSR.TWS4 4 2-wire Serial Interface Status bit 4 -; TWSR.TWS3 3 2-wire Serial Interface Status bit 3 -; TWAR 0x0022 2-wire Serial Interface (Slave) Address Register -; TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 -; TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 -; TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 -; TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 -; TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 -; TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 -; TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 -; TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable bit -; TWDR 0x0023 2-wire Serial Interface Data Register -; TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 -; TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 -; TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 -; TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 -; TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 -; TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 -; TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 -; TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 -; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion Result 7 -; ADCL.ADC6 6 ADC Conversion Result 6 -; ADCL.ADC5 5 ADC Conversion Result 5 -; ADCL.ADC4 4 ADC Conversion Result 4 -; ADCL.ADC3 3 ADC Conversion Result 3 -; ADCL.ADC2 2 ADC Conversion Result 2 -; ADCL.ADC1 1 ADC Conversion Result 1 -; ADCL.ADC0 0 ADC Conversion Result 0 -; ADCH 0x0025 ADC Data Register High (ADLAR = 0) -; ADCH.SIGN 15 -; ADCH.ADC9 9 ADC Conversion Result 9 -; ADCH.ADC8 8 ADC Conversion Result 8 -; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion Result 1 -; ; ADCL.ADC0 6 ADC Conversion Result 0 -; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion Result 9 -; ; ADCH.ADC8 14 ADC Conversion Result 8 -; ; ADCH.ADC7 13 ADC Conversion Result 7 -; ; ADCH.ADC6 12 ADC Conversion Result 6 -; ; ADCH.ADC5 11 ADC Conversion Result 5 -; ; ADCH.ADC4 10 ADC Conversion Result 4 -; ; ADCH.ADC3 9 ADC Conversion Result 3 -; ; ADCH.ADC2 8 ADC Conversion Result 2 -; ADCSR 0x0026 ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADFR 5 ADC Free Running Select -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRRL 0x0029 USART Baud Rate Register Low -; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -; UCSRB 0x002A USART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.UCSZ2 2 Character Size -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B USART Control and Status Register A -; UCSRA.RXC 7 USART Receive Complete -; UCSRA.TXC 6 USART Transmit Complete -; UCSRA.UDRE 5 USART Data Register Empty -; UCSRA.FE 4 Frame Error -; UCSRA.DOR 3 Data OverRun -; UCSRA.PE 2 Parity Error -; UCSRA.U2X 1 Double the USART Transmission Speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEDR.EEDR7 7 EEPROM Data 7 -; EEDR.EEDR6 6 EEPROM Data 6 -; EEDR.EEDR5 5 EEPROM Data 5 -; EEDR.EEDR4 4 EEPROM Data 4 -; EEDR.EEDR3 3 EEPROM Data 3 -; EEDR.EEDR2 2 EEPROM Data 2 -; EEDR.EEDR1 1 EEPROM Data 1 -; EEDR.EEDR0 0 EEPROM Data 0 -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR9 9 EEPROM Addres 9 -; EEARH.EEAR8 8 EEPROM Addres 8 -; UCSRC 0x0040 USART Control and Status Register (page 91) -; UCSRC.URSEL 7 Register Select -; UCSRC.UMSEL 6 USART Mode Select -; UCSRC.UPM1 5 Parity Mode 1 -; UCSRC.UPM0 4 Parity Mode 0 -; UCSRC.USBS 3 Stop Bit Select -; UCSRC.UCSZ1 2 Character Size 1 -; UCSRC.UCSZ0 1 Character Size 0 -; UCSRC.UCPOL 0 Clock Polarity -; ; UBRRH 0x0040 USART Baud Rate Register High (page 91) -; ; UBRRH.URSEL 15 Register Select -; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watch Dog Turn-off Enable -; WDTCR.WDE 3 Watch Dog Enable -; WDTCR.WDP2 2 Watch Dog Timer Prescaler 2 -; WDTCR.WDP1 1 Watch Dog Timer Prescaler 1 -; WDTCR.WDP0 0 Watch Dog Timer Prescaler 0 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; OCR2 0x0043 Timer/Counter2 Output Compare Register -; TCNT2 0x0044 Timer/Counter2 -; TCCR2 0x0045 Timer/Counter2 Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.PWM2 6 Pulse Width Modulator Enable -; TCCR2.COM21 5 Compare Output Mode, Bit 1 -; TCCR2.COM20 4 Compare Output Mode, Bit 0 -; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match -; TCCR2.CS22 2 Clock Select bit 2 -; TCCR2.CS21 1 Clock Select bit 1 -; TCCR2.CS20 0 Clock Select bit 0 -; ICR1L 0x0026 Input Capture Register Low Byte -; ICR1H 0x0027 Input Capture Register High Byte -; OCR1BL 0x0028 Output Compare Register B Low Byte -; OCR1BH 0x0029 Output Compare Register B High Byte -; OCR1AL 0x002A Output Compare Register A Low Byte -; OCR1AH 0x002B Output Compare Register A High Byte -; TCNT1L 0x002C Counter Register Low Byte -; TCNT1H 0x002D Counter Register High Byte -; TCCR1B 0x002E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) -; TCCR1B.ICES1 6 Input Capture1 Edge Select -; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match -; TCCR1B.CS12 2 Clock Select1, Bit 2 -; TCCR1B.CS11 1 Clock Select1, Bit 1 -; TCCR1B.CS10 0 Clock Select1, Bit 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode1A, bit 1 -; TCCR1A.COM1A0 6 Compare Output Mode1A, bit 0 -; TCCR1A.COM1B1 5 Compare Output Mode1B, bit 1 -; TCCR1A.COM1B0 4 Compare Output Mode1B, bit 0 -; TCCR1A.FOC1A 3 Force Output Compare1A -; TCCR1A.FOC1B 2 Force Output Compare1B -; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 -; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 -; SFIOR 0x0050 Special Function IO Register -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up Disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OCRD 0x0051 On-chip Debug Register -; ; OSCCAL 0x0051 Oscillator Calibration Register -; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.PWM0 6 Pulse Width Modulator Enable -; TCCR0.COM01 5 Compare Output Mode, Bit 1 -; TCCR0.COM00 4 Compare Output Mode, Bit 0 -; TCCR0.CTC0 3 Clear Timer/Counter on Compare Match -; TCCR0.CS02 2 Clock Select bit 2 -; TCCR0.CS01 1 Clock Select bit 1 -; TCCR0.CS00 0 Clock Select bit 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.JTD 7 JTAG interface disable -; MCUCSR.ISC2 6 Interrupt Sense Control 2 -; MCUCSR.JTRF 4 JTAG Reset Flag -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 7 Sleep Enable -; MCUCR.SM2 6 Sleep Mode Select Bit 2 -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; TWCR 0x0056 2-wire Serial Interface Control Register -; TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag -; TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag -; TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag -; TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag -; TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag -; TWCR.TWEN 2 2-wire Serial Interface Enable Bit -; TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.ASB 6 Application Section Busy -; SPMCR.ASRE 4 Application Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Input Capture Flag 1 -; TIFR.OCF1A 4 Output Compare Flag 1A -; TIFR.OCF1B 3 Output Compare Flag 1B -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Flag Register -; TIMSK.OCF2 7 Output Compare Flag 2 -; TIMSK.TOV2 6 Timer/Counter2 Overflow Flag -; TIMSK.ICF1 5 Input Capture Flag 1 -; TIMSK.OCF1A 4 Output Compare Flag 1A -; TIMSK.OCF1B 3 Output Compare Flag 1B -; TIMSK.TOV1 2 Timer/Counter1 Overflow Flag -; TIMSK.OCF0 1 Output Compare Flag 0 -; TIMSK.TOV0 0 Timer/Counter0 Overflow Flag -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag1 -; GIFR.INTF0 6 External Interrupt Flag0 -; GIFR.INTF2 5 External Interrupt Flag2 -; GICR 0x005B General Interrupt Control Register -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.INT2 5 External Interrupt Request 2 Enable -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; OCR0 0x005C Timer/Counter0 Output Compare Register -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega32_L -SUBARCH=5 -; doc2503.pdf -; - -RAM=2048 -ROM=32768 -EEPROM=1024 - -; MEMORY MAP - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x000A Timer/Counter2 Overflow -entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow -entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow -entry SPI_STC 0x0018 Serial Transfer Complete -entry USART_RXC 0x001A USART, Rx Complete -entry USART_UDRE 0x001C USART Data Register Empty -entry USART_TXC 0x001E USART, Tx Complete -entry ADC_ 0x0020 ADC Conversion Complete -entry EE_RDY 0x0022 EEPROM Ready -entry ANA_COMP 0x0024 Analog Comparator -entry TWI_ 0x0026 Two-wire Serial Interface -entry SPM_RDY 0x0028 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -TWBR 0x0000 Two-wire Serial Interface Bit Rate Register -TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -TWSR 0x0001 TWI Status Register -TWSR.TWS7 7 TWI Status 7 -TWSR.TWS6 6 TWI Status 6 -TWSR.TWS5 5 TWI Status 5 -TWSR.TWS4 4 TWI Status 4 -TWSR.TWS3 3 TWI Status 3 -TWSR.TWS1 1 TWI Prescaler Bit 1 -TWSR.TWS0 0 TWI Prescaler Bit 0 -TWAR 0x0002 TWI (Slave) Address Register -TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -TWDR 0x0003 TWI Data Register -TWDR.TWD7 7 TWI Data Register bit 7 -TWDR.TWD6 6 TWI Data Register bit 6 -TWDR.TWD5 5 TWI Data Register bit 5 -TWDR.TWD4 4 TWI Data Register bit 4 -TWDR.TWD3 3 TWI Data Register bit 3 -TWDR.TWD2 2 TWI Data Register bit 2 -TWDR.TWD1 1 TWI Data Register bit 1 -TWDR.TWD0 0 TWI Data Register bit 0 -ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion result 7 -ADCL.ADC6 6 ADC Conversion result 6 -ADCL.ADC5 5 ADC Conversion result 5 -ADCL.ADC4 4 ADC Conversion result 4 -ADCL.ADC3 3 ADC Conversion result 3 -ADCL.ADC2 2 ADC Conversion result 2 -ADCL.ADC1 1 ADC Conversion result 1 -ADCL.ADC0 0 ADC Conversion result 0 -ADCH 0x0005 The ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 ADC Conversion result 9 -ADCH.ADC8 8 ADC Conversion result 8 -; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion result 1 -; ADCL.ADC0 6 ADC Conversion result 0 -; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion result 9 -; ADCH.ADC8 14 ADC Conversion result 8 -; ADCH.ADC7 13 ADC Conversion result 7 -; ADCH.ADC6 12 ADC Conversion result 6 -; ADCH.ADC5 11 ADC Conversion result 5 -; ADCH.ADC4 10 ADC Conversion result 4 -; ADCH.ADC3 9 ADC Conversion result 3 -; ADCH.ADC2 8 ADC Conversion result 2 -ADCSRA 0x0006 ADC Control and Status Register A -ADCSRA.ADEN 7 ADC Enable -ADCSRA.ADSC 6 ADC Start Conversion -ADCSRA.ADATE 5 ADC Auto Trigger Enable -ADCSRA.ADIF 4 ADC Interrupt Flag -ADCSRA.ADIE 3 ADC Interrupt Enable -ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit -ADMUX.REFS0 6 Reference Selection Bit -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register Low -UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -UCSRB 0x000A USART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B USART Control and Status Register A -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.PE 2 Parity Error -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C The EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D The EEPROM Data Register -SPSR 0x001E SPI Status Register -;SPSR.SPIF 7 SPI Interrupt Flag -;SPSR.WCOL 6 Write COLlision flag -;SPSR.SPI2X 0 Double SPI Speed Bit -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR9 9 EEPROM Addres 9 -EEARH.EEAR8 8 EEPROM Addres 8 -UCSRC 0x0020 USART Control and Status Register C (page 155) -UCSRC.URSEL 7 Register Select -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -; UBRRH 0x0020 USART Baud Rate Register (page 155) -; URSEL 15 Register Select -; UBRR11 11 USART Baud Rate Register bit 11 -; UBRR10 10 USART Baud Rate Register bit 10 -; UBRR9 9 USART Baud Rate Register bit 9 -; UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 9 Watchdog Timer Prescaler 9 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -OCR2 0x0023 Timer/Counter2 Output Compare Register -TCNT2 0x0024 Timer/Counter Register -TCNT2.TCNT2_7 7 -TCNT2.TCNT2_6 6 -TCNT2.TCNT2_5 5 -TCNT2.TCNT2_4 4 -TCNT2.TCNT2_3 3 -TCNT2.TCNT2_2 2 -TCNT2.TCNT2_1 1 -TCNT2.TCNT2_0 0 -TCCR2 0x0025 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Compare Match Output Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Waveform Generation Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -ICR1L 0x0026 Input Capture Register Low Byte -ICR1H 0x0027 Input Capture Register High Byte -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input Capture Edge Select -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.FOC1A 3 Force Output Compare for Channel A -TCCR1A.FOC1B 2 Force Output Compare for Channel B -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -SFIOR 0x0030 Special Function I/O Register -SFIOR.ADTS2 7 ADC Auto Trigger Source 2 -SFIOR.ADTS1 6 ADC Auto Trigger Source 1 -SFIOR.ADTS0 5 ADC Auto Trigger Source 0 -SFIOR.ADHSM 4 ADC High Speed Mode -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OCDR 0x0031 On-Chip Debug Register -; OSCCAL 0x0031 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter Register -TCNT0.TCNT0_7 7 -TCNT0.TCNT0_6 6 -TCNT0.TCNT0_5 5 -TCNT0.TCNT0_4 4 -TCNT0.TCNT0_3 3 -TCNT0.TCNT0_2 2 -TCNT0.TCNT0_1 1 -TCNT0.TCNT0_0 0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.JTD 7 JTAG Interface Disable -MCUCSR.ISC2 6 Interrupt Sense Control 2 -MCUCSR.JTRF 4 JTAG Reset Flag -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 7 Sleep Enable -MCUCR.SM2 6 Sleep Mode Select Bit 2 -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 CInterrupt Sense Control 0 Bit 0 -TWCR 0x0036 TWI Control Register -TWCR.TWINT 7 TWI Interrupt Flag -TWCR.TWEA 6 TWI Enable Acknowledge Bit -TWCR.TWSTA 5 TWI START Condition Bit -TWCR.TWSTO 4 TWI STOP Condition Bit -TWCR.TWWC 3 TWI Write Collision Flag -TWCR.TWEN 2 TWI Enable Bit -TWCR.TWIE 0 TWI Interrupt Enable -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.SPMIE 7 SPM Interrupt Enable -SPMCR.RWWSB 6 Read-While-Write Section Busy -SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -TIFR.TOV1 2 Timer/Counter1, Overflow Flag -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIFR.INTF2 5 External Interrupt Flag 2 -GICR 0x003B General Interrupt Control -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.INT2 5 External Interrupt Request 2 Enable -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -OCR0 0x003C Timer/Counter0 Output Compare Register -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; TWBR 0x0020 Two-wire Serial Interface Bit Rate Register -; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -; TWSR 0x0021 TWI Status Register -; TWSR.TWS7 7 TWI Status 7 -; TWSR.TWS6 6 TWI Status 6 -; TWSR.TWS5 5 TWI Status 5 -; TWSR.TWS4 4 TWI Status 4 -; TWSR.TWS3 3 TWI Status 3 -; TWSR.TWS1 1 TWI Prescaler Bit 1 -; TWSR.TWS0 0 TWI Prescaler Bit 0 -; TWAR 0x0022 TWI (Slave) Address Register -; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -; TWDR 0x0023 TWI Data Register -; TWDR.TWD7 7 TWI Data Register bit 7 -; TWDR.TWD6 6 TWI Data Register bit 6 -; TWDR.TWD5 5 TWI Data Register bit 5 -; TWDR.TWD4 4 TWI Data Register bit 4 -; TWDR.TWD3 3 TWI Data Register bit 3 -; TWDR.TWD2 2 TWI Data Register bit 2 -; TWDR.TWD1 1 TWI Data Register bit 1 -; TWDR.TWD0 0 TWI Data Register bit 0 -; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion result 7 -; ADCL.ADC6 6 ADC Conversion result 6 -; ADCL.ADC5 5 ADC Conversion result 5 -; ADCL.ADC4 4 ADC Conversion result 4 -; ADCL.ADC3 3 ADC Conversion result 3 -; ADCL.ADC2 2 ADC Conversion result 2 -; ADCL.ADC1 1 ADC Conversion result 1 -; ADCL.ADC0 0 ADC Conversion result 0 -; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 ADC Conversion result 9 -; ADCH.ADC8 8 ADC Conversion result 8 -; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion result 1 -; ; ADCL.ADC0 6 ADC Conversion result 0 -; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion result 9 -; ; ADCH.ADC8 14 ADC Conversion result 8 -; ; ADCH.ADC7 13 ADC Conversion result 7 -; ; ADCH.ADC6 12 ADC Conversion result 6 -; ; ADCH.ADC5 11 ADC Conversion result 5 -; ; ADCH.ADC4 10 ADC Conversion result 4 -; ; ADCH.ADC3 9 ADC Conversion result 3 -; ; ADCH.ADC2 8 ADC Conversion result 2 -; ADCSRA 0x0026 ADC Control and Status Register A -; ADCSRA.ADEN 7 ADC Enable -; ADCSRA.ADSC 6 ADC Start Conversion -; ADCSRA.ADATE 5 ADC Auto Trigger Enable -; ADCSRA.ADIF 4 ADC Interrupt Flag -; ADCSRA.ADIE 3 ADC Interrupt Enable -; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit -; ADMUX.REFS0 6 Reference Selection Bit -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRRL 0x0029 USART Baud Rate Register Low -; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -; UCSRB 0x002A USART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.UCSZ2 2 Character Size -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B USART Control and Status Register A -; UCSRA.RXC 7 USART Receive Complete -; UCSRA.TXC 6 USART Transmit Complete -; UCSRA.UDRE 5 USART Data Register Empty -; UCSRA.FE 4 Frame Error -; UCSRA.DOR 3 Data OverRun -; UCSRA.PE 2 Parity Error -; UCSRA.U2X 1 Double the USART Transmission Speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C The EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D The EEPROM Data Register -; SPSR 0x003E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR9 9 EEPROM Addres 9 -; EEARH.EEAR8 8 EEPROM Addres 8 -; UCSRC 0x0040 USART Control and Status Register C (page 155) -; UCSRC.URSEL 7 Register Select -; UCSRC.UMSEL 6 USART Mode Select -; UCSRC.UPM1 5 Parity Mode 1 -; UCSRC.UPM0 4 Parity Mode 0 -; UCSRC.USBS 3 Stop Bit Select -; UCSRC.UCSZ1 2 Character Size 1 -; UCSRC.UCSZ0 1 Character Size 0 -; UCSRC.UCPOL 0 Clock Polarity -; ; UBRRH 0x0040 USART Baud Rate Register (page 155) -; ; URSEL 15 Register Select -; ; UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDTOE 4 Watchdog Turn-off Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 9 Watchdog Timer Prescaler 9 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; OCR2 0x0043 Timer/Counter2 Output Compare Register -; TCNT2 0x0044 Timer/Counter Register -; TCNT2.TCNT2_7 7 -; TCNT2.TCNT2_6 6 -; TCNT2.TCNT2_5 5 -; TCNT2.TCNT2_4 4 -; TCNT2.TCNT2_3 3 -; TCNT2.TCNT2_2 2 -; TCNT2.TCNT2_1 1 -; TCNT2.TCNT2_0 0 -; TCCR2 0x0045 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Compare Match Output Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Waveform Generation Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; ICR1L 0x0046 Input Capture Register Low Byte -; ICR1H 0x0047 Input Capture Register High Byte -; OCR1BL 0x0048 Output Compare Register B Low Byte -; OCR1BH 0x0049 Output Compare Register B High Byte -; OCR1AL 0x004A Output Compare Register A Low Byte -; OCR1AH 0x004B Output Compare Register A High Byte -; TCNT1L 0x004C Counter Register Low Byte -; TCNT1H 0x004D Counter Register High Byte -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input Capture Edge Select -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -; TCCR1A.FOC1A 3 Force Output Compare for Channel A -; TCCR1A.FOC1B 2 Force Output Compare for Channel B -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; SFIOR 0x0050 Special Function I/O Register -; SFIOR.ADTS2 7 ADC Auto Trigger Source 2 -; SFIOR.ADTS1 6 ADC Auto Trigger Source 1 -; SFIOR.ADTS0 5 ADC Auto Trigger Source 0 -; SFIOR.ADHSM 4 ADC High Speed Mode -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OCDR 0x0051 On-Chip Debug Register -; ; OSCCAL 0x0051 Oscillator Calibration Register -; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter Register -; TCNT0.TCNT0_7 7 -; TCNT0.TCNT0_6 6 -; TCNT0.TCNT0_5 5 -; TCNT0.TCNT0_4 4 -; TCNT0.TCNT0_3 3 -; TCNT0.TCNT0_2 2 -; TCNT0.TCNT0_1 1 -; TCNT0.TCNT0_0 0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.JTD 7 JTAG Interface Disable -; MCUCSR.ISC2 6 Interrupt Sense Control 2 -; MCUCSR.JTRF 4 JTAG Reset Flag -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 7 Sleep Enable -; MCUCR.SM2 6 Sleep Mode Select Bit 2 -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 CInterrupt Sense Control 0 Bit 0 -; TWCR 0x0056 TWI Control Register -; TWCR.TWINT 7 TWI Interrupt Flag -; TWCR.TWEA 6 TWI Enable Acknowledge Bit -; TWCR.TWSTA 5 TWI START Condition Bit -; TWCR.TWSTO 4 TWI STOP Condition Bit -; TWCR.TWWC 3 TWI Write Collision Flag -; TWCR.TWEN 2 TWI Enable Bit -; TWCR.TWIE 0 TWI Interrupt Enable -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -; TIFR.TOV1 2 Timer/Counter1, Overflow Flag -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIFR.INTF2 5 External Interrupt Flag 2 -; GICR 0x005B General Interrupt Control -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.INT2 5 External Interrupt Request 2 Enable -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; OCR0 0x005C Timer/Counter0 Output Compare Register -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega64_L -SUBARCH=5 -; doc2490.pdf -; -RAM=4096 -ROM=65536 -EEPROM=2048 - -; MEMORY MAP -; Memory configuration A -area DATA FSR1 0x0000:0x0060 -area DATA FSR2 0x0060:0x009E Ext I/O Reg. -area BSS RESERVED 0x009E:0x0100 -area DATA I_SRAM 0x0100:0x1100 Internal SRAM -area DATA E_SRAM 0x1100:0x10000 External SRAM -; Memory configuration B -; area DATA FSR 0x0000:0x0060 -; area DATA I_SRAM 0x0060:0x1000 Internal SRAM -; area DATA E_SRAM 0x1000:0x10000 External SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry INT3_ 0x0008 External Interrupt Request 3 -entry INT4_ 0x000A External Interrupt Request 4 -entry INT5_ 0x000C External Interrupt Request 5 -entry INT6_ 0x000E External Interrupt Request 6 -entry INT7_ 0x0010 External Interrupt Request 7 -entry TIMER2_COMP 0x0012 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0014 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0016 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0018 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x001A Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x001C Timer/Counter1 Overflow -entry TIMER0_COMP 0x001E Timer/Counter0 Compare Match -entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow -entry SPI_STC 0x0022 SPI Serial Transfer Complete -entry USART0_RX 0x0024 USART0, Rx Complete -entry USART0_UDRE 0x0026 USART0 Data Register Empty -entry USART0_TX 0x0028 USART0, Tx Complete -entry ADC_ 0x002A ADC Conversion Complete -entry EE_READY 0x002C EEPROM Ready -entry ANALOG_COMP 0x002E Analog Comparator -entry TIMER1_COMPC 0x0030 Timer/Countre1 Compare Match C -entry TIMER3_CAPT 0x0032 Timer/Counter3 Capture Event -entry TIMER3_COMPA 0x0034 Timer/Counter3 Compare Match A -entry TIMER3_COMPB 0x0036 Timer/Counter3 Compare Match B -entry TIMER3_COMPC 0x0038 Timer/Counter3 Compare Match C -entry TIMER3_OVF 0x003A Timer/Counter3 Overflow -entry USART1_RX 0x003C USART1, Rx Complete -entry USART1_UDRE 0x003E USART1 Data Register Empty -entry USART1_TX 0x0040 USART1, Tx Complete -entry TWI_ 0x0042 2-wire Serial Interface -entry SPM_READY 0x0044 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -PINF 0x0000 Port F Input Pins Address -PINF.PINF7 7 -PINF.PINF6 6 -PINF.PINF5 5 -PINF.PINF4 4 -PINF.PINF3 3 -PINF.PINF2 2 -PINF.PINF1 1 -PINF.PINF0 0 -PINE 0x0001 Port E Input Pins Address -PINE.PINE7 7 -PINE.PINE6 6 -PINE.PINE5 5 -PINE.PINE4 4 -PINE.PINE3 3 -PINE.PINE2 2 -PINE.PINE1 1 -PINE.PINE0 0 -DDRE 0x0002 Port E Data Direction Register -DDRE.DDE7 7 Port E Data Direction Register bit 7 -DDRE.DDE6 6 Port E Data Direction Register bit 6 -DDRE.DDE5 5 Port E Data Direction Register bit 5 -DDRE.DDE4 4 Port E Data Direction Register bit 4 -DDRE.DDE3 3 Port E Data Direction Register bit 3 -DDRE.DDE2 2 Port E Data Direction Register bit 2 -DDRE.DDE1 1 Port E Data Direction Register bit 1 -DDRE.DDE0 0 Port E Data Direction Register bit 0 -PORTE 0x0003 Port E Data Register -PORTE.PORTE7 7 Port E Data Register bit 7 -PORTE.PORTE6 6 Port E Data Register bit 6 -PORTE.PORTE5 5 Port E Data Register bit 5 -PORTE.PORTE4 4 Port E Data Register bit 4 -PORTE.PORTE3 3 Port E Data Register bit 3 -PORTE.PORTE2 2 Port E Data Register bit 2 -PORTE.PORTE1 1 Port E Data Register bit 1 -PORTE.PORTE0 0 Port E Data Register bit 0 -ADCL 0x0004 ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion Result 7 -ADCL.ADC6 6 ADC Conversion Result 6 -ADCL.ADC5 5 ADC Conversion Result 5 -ADCL.ADC4 4 ADC Conversion Result 4 -ADCL.ADC3 3 ADC Conversion Result 3 -ADCL.ADC2 2 ADC Conversion Result 2 -ADCL.ADC1 1 ADC Conversion Result 1 -ADCL.ADC0 0 ADC Conversion Result 0 -ADCH 0x0005 ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 ADC Conversion Result 9 -ADCH.ADC8 8 ADC Conversion Result 8 -; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion Result 1 -; ADCL.ADC0 6 ADC Conversion Result 0 -; ADCH 0x0005 ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion Result 9 -; ADCH.ADC8 14 ADC Conversion Result 8 -; ADCH.ADC7 13 ADC Conversion Result 7 -; ADCH.ADC6 12 ADC Conversion Result 6 -; ADCH.ADC5 11 ADC Conversion Result 5 -; ADCH.ADC4 10 ADC Conversion Result 4 -; ADCH.ADC3 9 ADC Conversion Result 3 -; ADCH.ADC2 8 ADC Conversion Result 2 -ADCSRA 0x0006 ADC Control and Status Register A -ADCSRA.ADEN 7 ADC Enable -ADCSRA.ADSC 6 ADC Start Conversion -ADCSRA.ADATE 5 ADC Auto Trigger Enable -ADCSRA.ADIF 4 ADC Interrupt Flag -ADCSRA.ADIE 3 ADC Interrupt Enable -ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRR0L 0x0009 USART Baud Rate Register -UBRR0L.UBRR7 7 USART Baud Rate Register bit 7 -UBRR0L.UBRR6 6 USART Baud Rate Register bit 6 -UBRR0L.UBRR5 5 USART Baud Rate Register bit 5 -UBRR0L.UBRR4 4 USART Baud Rate Register bit 4 -UBRR0L.UBRR3 3 USART Baud Rate Register bit 3 -UBRR0L.UBRR2 2 USART Baud Rate Register bit 2 -UBRR0L.UBRR1 1 USART Baud Rate Register bit 1 -UBRR0L.UBRR0 0 USART Baud Rate Register bit 0 -UCSR0B 0x000A USART Control and Status Register B -UCSR0B.RXCIE 7 RX Complete Interrupt Enable -UCSR0B.TXCIE 6 TX Complete Interrupt Enable -UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSR0B.RXEN 4 Receiver Enable -UCSR0B.TXEN 3 Transmitter Enable -UCSR0B.UCSZ2 2 Character Size -UCSR0B.RXB8 1 Receive Data Bit 8 -UCSR0B.TXB8 0 Transmit Data Bit 8 -UCSR0A 0x000B USART Control and Status Register A -UCSR0A.RXC 7 USART Receive Complete -UCSR0A.TXC 6 USART Transmit Complete -UCSR0A.UDRE 5 USART Data Register Empty -UCSR0A.FE 4 Frame Error -UCSR0A.DOR 3 Data OverRun -UCSR0A.UPE 2 USART Parity Error -UCSR0A.U2X 1 Double the USART Transmission Speed -UCSR0A.MPCM 0 Multi-processor Communication Mode -UDR0 0x000C USART0 I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision Flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR10 10 EEPROM Addres 10 -EEARH.EEAR9 9 EEPROM Addres 9 -EEARH.EEAR8 8 EEPROM Addres 8 -SFIOR 0x0020 Special Function IO Register -SFIOR.TSM 7 Timer/Counter Synchronization Mode -SFIOR.ADHSM 4 ADC High Speed Mode -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up disable -SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 -SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -OCDR 0x0022 On-chip Debug Register -OCDR.IDRD_OCDR7 7 -OCDR.OCDR6 6 -OCDR.OCDR5 5 -OCDR.OCDR4 4 -OCDR.OCDR3 3 -OCDR.OCDR2 2 -OCDR.OCDR1 1 -OCDR.OCDR0 0 -OCR2 0x0023 Output Compare Register -OCR2.OCR2_7 7 -OCR2.OCR2_6 6 -OCR2.OCR2_5 5 -OCR2.OCR2_4 4 -OCR2.OCR2_3 3 -OCR2.OCR2_2 2 -OCR2.OCR2_1 1 -OCR2.OCR2_0 0 -TCNT2 0x0024 Timer/Counter Register -TCNT2.TCNT2_7 7 -TCNT2.TCNT2_6 6 -TCNT2.TCNT2_5 5 -TCNT2.TCNT2_4 4 -TCNT2.TCNT2_3 3 -TCNT2.TCNT2_2 2 -TCNT2.TCNT2_1 1 -TCNT2.TCNT2_0 0 -TCCR2 0x0025 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Compare Match Output Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Waveform Generation Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -ICR1L 0x0026 Input Capture Register 1 Low -ICR1L.ICR1_7 7 -ICR1L.ICR1_6 6 -ICR1L.ICR1_5 5 -ICR1L.ICR1_4 4 -ICR1L.ICR1_3 3 -ICR1L.ICR1_2 2 -ICR1L.ICR1_1 1 -ICR1L.ICR1_0 0 -ICR1H 0x0027 Input Capture Register 1 High -ICR1H.ICR1_15 15 -ICR1H.ICR1_14 14 -ICR1H.ICR1_13 13 -ICR1H.ICR1_12 12 -ICR1H.ICR1_11 11 -ICR1H.ICR1_10 10 -ICR1H.ICR1_9 9 -ICR1H.ICR1_8 8 -OCR1BL 0x0028 Output Compare Register 1 B Low -OCR1BL.OCR1B_7 7 -OCR1BL.OCR1B_6 6 -OCR1BL.OCR1B_5 5 -OCR1BL.OCR1B_4 4 -OCR1BL.OCR1B_3 3 -OCR1BL.OCR1B_2 2 -OCR1BL.OCR1B_1 1 -OCR1BL.OCR1B_0 0 -OCR1BH 0x0029 Output Compare Register 1 B High -OCR1BH.OCR1B_15 15 -OCR1BH.OCR1B_14 14 -OCR1BH.OCR1B_13 13 -OCR1BH.OCR1B_12 12 -OCR1BH.OCR1B_11 11 -OCR1BH.OCR1B_10 10 -OCR1BH.OCR1B_9 9 -OCR1BH.OCR1B_8 8 -OCR1AL 0x002A Output Compare Register 1 A Low -OCR1AL.OCR1A_7 7 -OCR1AL.OCR1A_6 6 -OCR1AL.OCR1A_5 5 -OCR1AL.OCR1A_4 4 -OCR1AL.OCR1A_3 3 -OCR1AL.OCR1A_2 2 -OCR1AL.OCR1A_1 1 -OCR1AL.OCR1A_0 0 -OCR1AH 0x002B Output Compare Register 1 A High -OCR1AH.OCR1A_15 15 -OCR1AH.OCR1A_14 14 -OCR1AH.OCR1A_13 13 -OCR1AH.OCR1A_12 12 -OCR1AH.OCR1A_11 11 -OCR1AH.OCR1A_10 10 -OCR1AH.OCR1A_9 9 -OCR1AH.OCR1A_8 8 -TCNT1L 0x002C Timer/Counter 1 Low -TCNT1L.TCNT1_7 7 -TCNT1L.TCNT1_6 6 -TCNT1L.TCNT1_5 5 -TCNT1L.TCNT1_4 4 -TCNT1L.TCNT1_3 3 -TCNT1L.TCNT1_2 2 -TCNT1L.TCNT1_1 1 -TCNT1L.TCNT1_0 0 -TCNT1H 0x002D Timer/Counter 1 High -TCNT1H.TCNT1_15 15 -TCNT1H.TCNT1_14 14 -TCNT1H.TCNT1_13 13 -TCNT1H.TCNT1_12 12 -TCNT1H.TCNT1_11 11 -TCNT1H.TCNT1_10 10 -TCNT1H.TCNT1_9 9 -TCNT1H.TCNT1_8 8 -TCCR1B 0x002E Timer/Counter 1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input Capture Edge Select -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter 1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 -TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -ASSR 0x0030 Asynchronous Status Register -ASSR.AS0 3 Asynchronous Timer/Counter0 -ASSR.TCN0UB 2 Timer/Counter0 Update Busy -ASSR.OCR0UB 1 Output Compare Register0 Update Busy -ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy -OCR0 0x0031 Output Compare Register -OCR0.OCR0_7 7 -OCR0.OCR0_6 6 -OCR0.OCR0_5 5 -OCR0.OCR0_4 4 -OCR0.OCR0_3 3 -OCR0.OCR0_2 2 -OCR0.OCR0_1 1 -OCR0.OCR0_0 0 -TCNT0 0x0032 Timer/Counter Register -TCNT0.TCNT0_7 7 -TCNT0.TCNT0_6 6 -TCNT0.TCNT0_5 5 -TCNT0.TCNT0_4 4 -TCNT0.TCNT0_3 3 -TCNT0.TCNT0_2 2 -TCNT0.TCNT0_1 1 -TCNT0.TCNT0_0 0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.JTD 7 JTAG interface disable -MCUCSR.JTRF 4 JTAG Reset Flag -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM/XMEM Enable -MCUCR.SRW10 6 Wait State Select Bit -MCUCR.SE 5 Sleep Enable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.SM0 3 Sleep Mode Select Bit 0 -MCUCR.SM2 2 Sleep Mode Select Bit 2 -MCUCR.IVSEL 1 Interrupt Vector Select -MCUCR.IVCE 0 Interrupt Vector Change Enable -TIFR 0x0036 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -TIFR.TOV1 2 Timer/Counter1, Overflow Flag -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0037 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -EIFR 0x0038 External Interrupt Flag Register -EIFR.INTF7 7 External Interrupt Flag 7 -EIFR.INTF6 6 External Interrupt Flag 6 -EIFR.INTF5 5 External Interrupt Flag 5 -EIFR.INTF4 4 External Interrupt Flag 4 -EIFR.INTF3 3 External Interrupt Flag 3 -EIFR.INTF2 2 External Interrupt Flag 2 -EIFR.INTF1 1 External Interrupt Flag 1 -EIFR.INTF0 0 External Interrupt Flag 0 -EIMSK 0x0039 External Interrupt Mask Register -EIMSK.INT7 7 External Interrupt Request 7 Enable -EIMSK.INT6 6 External Interrupt Request 6 Enable -EIMSK.INT5 5 External Interrupt Request 5 Enable -EIMSK.INT4 4 External Interrupt Request 4 Enable -EIMSK.INT3 3 External Interrupt Request 3 Enable -EIMSK.INT2 2 External Interrupt Request 2 Enable -EIMSK.INT1 1 External Interrupt Request 1 Enable -EIMSK.INT0 0 External Interrupt Request 0 Enable -EICRB 0x003A External Interrupt Control Register B -EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 -EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 -EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 -EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 -EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 -EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 -EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 -EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 -RESERVED003B 0x003B RESERVED -XDIV 0x003C XTAL Divide Control Register -XDIV.XDIVEN 7 XTAL Divide Enable -XDIV.XDIV6 6 XTAL Divide Select Bit 6 -XDIV.XDIV5 5 XTAL Divide Select Bit 5 -XDIV.XDIV4 4 XTAL Divide Select Bit 4 -XDIV.XDIV3 3 XTAL Divide Select Bit 3 -XDIV.XDIV2 2 XTAL Divide Select Bit 2 -XDIV.XDIV1 1 XTAL Divide Select Bit 1 -XDIV.XDIV0 0 XTAL Divide Select Bit 0 -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; PINF 0x0020 Port F Input Pins Address -; PINF.PINF7 7 -; PINF.PINF6 6 -; PINF.PINF5 5 -; PINF.PINF4 4 -; PINF.PINF3 3 -; PINF.PINF2 2 -; PINF.PINF1 1 -; PINF.PINF0 0 -; PINE 0x0021 Port E Input Pins Address -; PINE.PINE7 7 -; PINE.PINE6 6 -; PINE.PINE5 5 -; PINE.PINE4 4 -; PINE.PINE3 3 -; PINE.PINE2 2 -; PINE.PINE1 1 -; PINE.PINE0 0 -; DDRE 0x0022 Port E Data Direction Register -; DDRE.DDE7 7 Port E Data Direction Register bit 7 -; DDRE.DDE6 6 Port E Data Direction Register bit 6 -; DDRE.DDE5 5 Port E Data Direction Register bit 5 -; DDRE.DDE4 4 Port E Data Direction Register bit 4 -; DDRE.DDE3 3 Port E Data Direction Register bit 3 -; DDRE.DDE2 2 Port E Data Direction Register bit 2 -; DDRE.DDE1 1 Port E Data Direction Register bit 1 -; DDRE.DDE0 0 Port E Data Direction Register bit 0 -; PORTE 0x0023 Port E Data Register -; PORTE.PORTE7 7 Port E Data Register bit 7 -; PORTE.PORTE6 6 Port E Data Register bit 6 -; PORTE.PORTE5 5 Port E Data Register bit 5 -; PORTE.PORTE4 4 Port E Data Register bit 4 -; PORTE.PORTE3 3 Port E Data Register bit 3 -; PORTE.PORTE2 2 Port E Data Register bit 2 -; PORTE.PORTE1 1 Port E Data Register bit 1 -; PORTE.PORTE0 0 Port E Data Register bit 0 -; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion Result 7 -; ADCL.ADC6 6 ADC Conversion Result 6 -; ADCL.ADC5 5 ADC Conversion Result 5 -; ADCL.ADC4 4 ADC Conversion Result 4 -; ADCL.ADC3 3 ADC Conversion Result 3 -; ADCL.ADC2 2 ADC Conversion Result 2 -; ADCL.ADC1 1 ADC Conversion Result 1 -; ADCL.ADC0 0 ADC Conversion Result 0 -; ADCH 0x0025 ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 ADC Conversion Result 9 -; ADCH.ADC8 8 ADC Conversion Result 8 -; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion Result 1 -; ; ADCL.ADC0 6 ADC Conversion Result 0 -; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion Result 9 -; ; ADCH.ADC8 14 ADC Conversion Result 8 -; ; ADCH.ADC7 13 ADC Conversion Result 7 -; ; ADCH.ADC6 12 ADC Conversion Result 6 -; ; ADCH.ADC5 11 ADC Conversion Result 5 -; ; ADCH.ADC4 10 ADC Conversion Result 4 -; ; ADCH.ADC3 9 ADC Conversion Result 3 -; ; ADCH.ADC2 8 ADC Conversion Result 2 -; ADCSRA 0x0026 ADC Control and Status Register A -; ADCSRA.ADEN 7 ADC Enable -; ADCSRA.ADSC 6 ADC Start Conversion -; ADCSRA.ADATE 5 ADC Auto Trigger Enable -; ADCSRA.ADIF 4 ADC Interrupt Flag -; ADCSRA.ADIE 3 ADC Interrupt Enable -; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRR0L 0x0029 USART Baud Rate Register -; UBRR0L.UBRR7 7 USART Baud Rate Register bit 7 -; UBRR0L.UBRR6 6 USART Baud Rate Register bit 6 -; UBRR0L.UBRR5 5 USART Baud Rate Register bit 5 -; UBRR0L.UBRR4 4 USART Baud Rate Register bit 4 -; UBRR0L.UBRR3 3 USART Baud Rate Register bit 3 -; UBRR0L.UBRR2 2 USART Baud Rate Register bit 2 -; UBRR0L.UBRR1 1 USART Baud Rate Register bit 1 -; UBRR0L.UBRR0 0 USART Baud Rate Register bit 0 -; UCSR0B 0x002A USART Control and Status Register B -; UCSR0B.RXCIE 7 RX Complete Interrupt Enable -; UCSR0B.TXCIE 6 TX Complete Interrupt Enable -; UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSR0B.RXEN 4 Receiver Enable -; UCSR0B.TXEN 3 Transmitter Enable -; UCSR0B.UCSZ2 2 Character Size -; UCSR0B.RXB8 1 Receive Data Bit 8 -; UCSR0B.TXB8 0 Transmit Data Bit 8 -; UCSR0A 0x002B USART Control and Status Register A -; UCSR0A.RXC 7 USART Receive Complete -; UCSR0A.TXC 6 USART Transmit Complete -; UCSR0A.UDRE 5 USART Data Register Empty -; UCSR0A.FE 4 Frame Error -; UCSR0A.DOR 3 Data OverRun -; UCSR0A.UPE 2 USART Parity Error -; UCSR0A.U2X 1 Double the USART Transmission Speed -; UCSR0A.MPCM 0 Multi-processor Communication Mode -; UDR0 0x002C USART0 I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision Flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEDR.EEDR7 7 EEPROM Data 7 -; EEDR.EEDR6 6 EEPROM Data 6 -; EEDR.EEDR5 5 EEPROM Data 5 -; EEDR.EEDR4 4 EEPROM Data 4 -; EEDR.EEDR3 3 EEPROM Data 3 -; EEDR.EEDR2 2 EEPROM Data 2 -; EEDR.EEDR1 1 EEPROM Data 1 -; EEDR.EEDR0 0 EEPROM Data 0 -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR10 10 EEPROM Addres 10 -; EEARH.EEAR9 9 EEPROM Addres 9 -; EEARH.EEAR8 8 EEPROM Addres 8 -; SFIOR 0x0040 Special Function IO Register -; SFIOR.TSM 7 Timer/Counter Synchronization Mode -; SFIOR.ADHSM 4 ADC High Speed Mode -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up disable -; SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 -; SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; OCDR 0x0042 On-chip Debug Register -; OCDR.IDRD_OCDR7 7 -; OCDR.OCDR6 6 -; OCDR.OCDR5 5 -; OCDR.OCDR4 4 -; OCDR.OCDR3 3 -; OCDR.OCDR2 2 -; OCDR.OCDR1 1 -; OCDR.OCDR0 0 -; OCR2 0x0043 Output Compare Register -; OCR2.OCR2_7 7 -; OCR2.OCR2_6 6 -; OCR2.OCR2_5 5 -; OCR2.OCR2_4 4 -; OCR2.OCR2_3 3 -; OCR2.OCR2_2 2 -; OCR2.OCR2_1 1 -; OCR2.OCR2_0 0 -; TCNT2 0x0044 Timer/Counter Register -; TCNT2.TCNT2_7 7 -; TCNT2.TCNT2_6 6 -; TCNT2.TCNT2_5 5 -; TCNT2.TCNT2_4 4 -; TCNT2.TCNT2_3 3 -; TCNT2.TCNT2_2 2 -; TCNT2.TCNT2_1 1 -; TCNT2.TCNT2_0 0 -; TCCR2 0x0045 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Compare Match Output Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Waveform Generation Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; ICR1L 0x0046 Input Capture Register 1 Low -; ICR1L.ICR1_7 7 -; ICR1L.ICR1_6 6 -; ICR1L.ICR1_5 5 -; ICR1L.ICR1_4 4 -; ICR1L.ICR1_3 3 -; ICR1L.ICR1_2 2 -; ICR1L.ICR1_1 1 -; ICR1L.ICR1_0 0 -; ICR1H 0x0047 Input Capture Register 1 High -; ICR1H.ICR1_15 15 -; ICR1H.ICR1_14 14 -; ICR1H.ICR1_13 13 -; ICR1H.ICR1_12 12 -; ICR1H.ICR1_11 11 -; ICR1H.ICR1_10 10 -; ICR1H.ICR1_9 9 -; ICR1H.ICR1_8 8 -; OCR1BL 0x0048 Output Compare Register 1 B Low -; OCR1BL.OCR1B_7 7 -; OCR1BL.OCR1B_6 6 -; OCR1BL.OCR1B_5 5 -; OCR1BL.OCR1B_4 4 -; OCR1BL.OCR1B_3 3 -; OCR1BL.OCR1B_2 2 -; OCR1BL.OCR1B_1 1 -; OCR1BL.OCR1B_0 0 -; OCR1BH 0x0049 Output Compare Register 1 B High -; OCR1BH.OCR1B_15 15 -; OCR1BH.OCR1B_14 14 -; OCR1BH.OCR1B_13 13 -; OCR1BH.OCR1B_12 12 -; OCR1BH.OCR1B_11 11 -; OCR1BH.OCR1B_10 10 -; OCR1BH.OCR1B_9 9 -; OCR1BH.OCR1B_8 8 -; OCR1AL 0x004A Output Compare Register 1 A Low -; OCR1AL.OCR1A_7 7 -; OCR1AL.OCR1A_6 6 -; OCR1AL.OCR1A_5 5 -; OCR1AL.OCR1A_4 4 -; OCR1AL.OCR1A_3 3 -; OCR1AL.OCR1A_2 2 -; OCR1AL.OCR1A_1 1 -; OCR1AL.OCR1A_0 0 -; OCR1AH 0x004B Output Compare Register 1 A High -; OCR1AH.OCR1A_15 15 -; OCR1AH.OCR1A_14 14 -; OCR1AH.OCR1A_13 13 -; OCR1AH.OCR1A_12 12 -; OCR1AH.OCR1A_11 11 -; OCR1AH.OCR1A_10 10 -; OCR1AH.OCR1A_9 9 -; OCR1AH.OCR1A_8 8 -; TCNT1L 0x004C Timer/Counter 1 Low -; TCNT1L.TCNT1_7 7 -; TCNT1L.TCNT1_6 6 -; TCNT1L.TCNT1_5 5 -; TCNT1L.TCNT1_4 4 -; TCNT1L.TCNT1_3 3 -; TCNT1L.TCNT1_2 2 -; TCNT1L.TCNT1_1 1 -; TCNT1L.TCNT1_0 0 -; TCNT1H 0x004D Timer/Counter 1 High -; TCNT1H.TCNT1_15 15 -; TCNT1H.TCNT1_14 14 -; TCNT1H.TCNT1_13 13 -; TCNT1H.TCNT1_12 12 -; TCNT1H.TCNT1_11 11 -; TCNT1H.TCNT1_10 10 -; TCNT1H.TCNT1_9 9 -; TCNT1H.TCNT1_8 8 -; TCCR1B 0x004E Timer/Counter 1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input Capture Edge Select -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter 1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -; TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 -; TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; ASSR 0x0050 Asynchronous Status Register -; ASSR.AS0 3 Asynchronous Timer/Counter0 -; ASSR.TCN0UB 2 Timer/Counter0 Update Busy -; ASSR.OCR0UB 1 Output Compare Register0 Update Busy -; ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy -; OCR0 0x0051 Output Compare Register -; OCR0.OCR0_7 7 -; OCR0.OCR0_6 6 -; OCR0.OCR0_5 5 -; OCR0.OCR0_4 4 -; OCR0.OCR0_3 3 -; OCR0.OCR0_2 2 -; OCR0.OCR0_1 1 -; OCR0.OCR0_0 0 -; TCNT0 0x0052 Timer/Counter Register -; TCNT0.TCNT0_7 7 -; TCNT0.TCNT0_6 6 -; TCNT0.TCNT0_5 5 -; TCNT0.TCNT0_4 4 -; TCNT0.TCNT0_3 3 -; TCNT0.TCNT0_2 2 -; TCNT0.TCNT0_1 1 -; TCNT0.TCNT0_0 0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.JTD 7 JTAG interface disable -; MCUCSR.JTRF 4 JTAG Reset Flag -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM/XMEM Enable -; MCUCR.SRW10 6 Wait State Select Bit -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.SM0 3 Sleep Mode Select Bit 0 -; MCUCR.SM2 2 Sleep Mode Select Bit 2 -; MCUCR.IVSEL 1 Interrupt Vector Select -; MCUCR.IVCE 0 Interrupt Vector Change Enable -; TIFR 0x0056 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -; TIFR.TOV1 2 Timer/Counter1, Overflow Flag -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0057 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; EIFR 0x0058 External Interrupt Flag Register -; EIFR.INTF7 7 External Interrupt Flag 7 -; EIFR.INTF6 6 External Interrupt Flag 6 -; EIFR.INTF5 5 External Interrupt Flag 5 -; EIFR.INTF4 4 External Interrupt Flag 4 -; EIFR.INTF3 3 External Interrupt Flag 3 -; EIFR.INTF2 2 External Interrupt Flag 2 -; EIFR.INTF1 1 External Interrupt Flag 1 -; EIFR.INTF0 0 External Interrupt Flag 0 -; EIMSK 0x0059 External Interrupt Mask Register -; EIMSK.INT7 7 External Interrupt Request 7 Enable -; EIMSK.INT6 6 External Interrupt Request 6 Enable -; EIMSK.INT5 5 External Interrupt Request 5 Enable -; EIMSK.INT4 4 External Interrupt Request 4 Enable -; EIMSK.INT3 3 External Interrupt Request 3 Enable -; EIMSK.INT2 2 External Interrupt Request 2 Enable -; EIMSK.INT1 1 External Interrupt Request 1 Enable -; EIMSK.INT0 0 External Interrupt Request 0 Enable -; EICRB 0x005A External Interrupt Control Register B -; EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 -; EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 -; EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 -; EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 -; EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 -; EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 -; EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 -; EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 -; RESERVED005B 0x005B RESERVED -; XDIV 0x005C XTAL Divide Control Register -; XDIV.XDIVEN 7 XTAL Divide Enable -; XDIV.XDIV6 6 XTAL Divide Select Bit 6 -; XDIV.XDIV5 5 XTAL Divide Select Bit 5 -; XDIV.XDIV4 4 XTAL Divide Select Bit 4 -; XDIV.XDIV3 3 XTAL Divide Select Bit 3 -; XDIV.XDIV2 2 XTAL Divide Select Bit 2 -; XDIV.XDIV1 1 XTAL Divide Select Bit 1 -; XDIV.XDIV0 0 XTAL Divide Select Bit 0 -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag -; RESERVED0060 0x0060 RESERVED -; DDRF 0x0061 Port F Data Direction Register -; DDRF.DDF7 7 Port F Data Direction Register bit 7 -; DDRF.DDF6 6 Port F Data Direction Register bit 6 -; DDRF.DDF5 5 Port F Data Direction Register bit 5 -; DDRF.DDF4 4 Port F Data Direction Register bit 4 -; DDRF.DDF3 3 Port F Data Direction Register bit 3 -; DDRF.DDF2 2 Port F Data Direction Register bit 2 -; DDRF.DDF1 1 Port F Data Direction Register bit 1 -; DDRF.DDF0 0 Port F Data Direction Register bit 0 -; PORTF 0x0062 Port F Data Register -; PORTF.PORTF 7 Port F Data Register bit 7 -; PORTF.PORTF 6 Port F Data Register bit 6 -; PORTF.PORTF 5 Port F Data Register bit 5 -; PORTF.PORTF 4 Port F Data Register bit 4 -; PORTF.PORTF 3 Port F Data Register bit 3 -; PORTF.PORTF 2 Port F Data Register bit 2 -; PORTF.PORTF 1 Port F Data Register bit 1 -; PORTF.PORTF 0 Port F Data Register bit 0 -; PING 0x0063 Port G Input Pins Address -; PING.PING4 4 -; PING.PING3 3 -; PING.PING2 2 -; PING.PING1 1 -; PING.PING0 0 -; DDRG 0x0064 Port G Data Direction Register -; DDRG.DDG4 4 Port G Data Direction Register bit 4 -; DDRG.DDG3 3 Port G Data Direction Register bit 3 -; DDRG.DDG2 2 Port G Data Direction Register bit 2 -; DDRG.DDG1 1 Port G Data Direction Register bit 1 -; DDRG.DDG0 0 Port G Data Direction Register bit 0 -; PORTG 0x0065 Port G Data Register -; PORTG.PORTG4 4 Port G Data Register bit 4 -; PORTG.PORTG3 3 Port G Data Register bit 3 -; PORTG.PORTG2 2 Port G Data Register bit 2 -; PORTG.PORTG1 1 Port G Data Register bit 1 -; PORTG.PORTG0 0 Port G Data Register bit 0 -; RESERVED0066 0x0066 RESERVED -; RESERVED0067 0x0067 RESERVED -; SPMCR 0x0068 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; RESERVED0069 0x0069 RESERVED -; EICRA 0x006A External Interrupt Control Register A -; EICRA.ISC31 7 External Interrupt 3 Sense Control Bit 1 -; EICRA.ISC30 6 External Interrupt 3 Sense Control Bit 0 -; EICRA.ISC21 5 External Interrupt 2 Sense Control Bit 1 -; EICRA.ISC20 4 External Interrupt 2 Sense Control Bit 0 -; EICRA.ISC11 3 External Interrupt 1 Sense Control Bit 1 -; EICRA.ISC10 2 External Interrupt 1 Sense Control Bit 0 -; EICRA.ISC01 1 External Interrupt 0 Sense Control Bit 1 -; EICRA.ISC00 0 External Interrupt 0 Sense Control Bit 0 -; RESERVED006B 0x006B RESERVED -; XMCRB 0x006C External Memory Control Register B -; XMCRB.XMBK 7 External Memory Bus-keeper Enable -; XMCRB.XMM2 2 External Memory High Mask 2 -; XMCRB.XMM1 1 External Memory High Mask 1 -; XMCRB.XMM0 0 External Memory High Mask 0 -; XMCRA 0x006D External Memory Control Register A -; XMCRA.SRL2 6 Wait State Sector Limit 2 -; XMCRA.SRL1 5 Wait State Sector Limit 1 -; XMCRA.SRL0 4 Wait State Sector Limit 0 -; XMCRA.SRW01 3 Wait State Select Bits for Lower Sector -; XMCRA.SRW00 2 Wait State Select Bits for Lower Sector -; XMCRA.SRW11 1 Wait State Select Bits for Upper Sector -; RESERVED006E 0x006E RESERVED -; OSCCAL 0x006F Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TWBR 0x0070 TWI Bit Rate Register -; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -; TWSR 0x0071 TWI Status Register -; TWSR.TWS7 7 TWI Status bit 7 -; TWSR.TWS6 6 TWI Status bit 6 -; TWSR.TWS5 5 TWI Status bit 5 -; TWSR.TWS4 4 TWI Status bit 4 -; TWSR.TWS3 3 TWI Status bit 3 -; TWSR.TWS1 1 TWI Status bit 1 -; TWSR.TWS0 0 TWI Status bit 0 -; TWAR 0x0072 TWI (Slave) Address Register -; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -; TWDR 0x0073 TWI Data Register -; TWDR.TWD7 7 TWI Data Register bit 7 -; TWDR.TWD6 6 TWI Data Register bit 6 -; TWDR.TWD5 5 TWI Data Register bit 5 -; TWDR.TWD4 4 TWI Data Register bit 4 -; TWDR.TWD3 3 TWI Data Register bit 3 -; TWDR.TWD2 2 TWI Data Register bit 2 -; TWDR.TWD1 1 TWI Data Register bit 1 -; TWDR.TWD0 0 TWI Data Register bit 0 -; TWCR 0x0074 TWI Control Register -; TWCR.TWINT 7 TWI Interrupt Flag -; TWCR.TWEA 6 TWI Enable Acknowledge Bit -; TWCR.TWSTA 5 TWI START Condition Bit -; TWCR.TWSTO 4 TWI STOP Condition Bit -; TWCR.TWWC 3 TWI Write Collision Flag -; TWCR.TWEN 2 TWI Enable Bit -; TWCR.TWIE 0 TWI Interrupt Enable -; RESERVED0075 0x0075 RESERVED -; RESERVED0076 0x0076 RESERVED -; RESERVED0077 0x0077 RESERVED -; OCR1CL 0x0078 Output Compare Register 1 C Low -; OCR1CL.OCR1C7 7 -; OCR1CL.OCR1C6 6 -; OCR1CL.OCR1C5 5 -; OCR1CL.OCR1C4 4 -; OCR1CL.OCR1C3 3 -; OCR1CL.OCR1C2 2 -; OCR1CL.OCR1C1 1 -; OCR1CL.OCR1C0 0 -; OCR1CH 0x0079 Output Compare Register 1 C High -; OCR1CH.OCR1C15 15 -; OCR1CH.OCR1C14 14 -; OCR1CH.OCR1C13 13 -; OCR1CH.OCR1C12 12 -; OCR1CH.OCR1C11 11 -; OCR1CH.OCR1C10 10 -; OCR1CH.OCR1C9 9 -; OCR1CH.OCR1C8 8 -; TCCR1C 0x007A Timer/Counter 1 Control Register C -; TCCR1C.FOC1A 7 Force Output Compare for Channel A -; TCCR1C.FOC1B 6 Force Output Compare for Channel B -; TCCR1C.FOC1C 5 Force Output Compare for Channel C -; RESERVED007B 0x007B RESERVED -; ETIFR 0x007C Extended Timer/Counter Interrupt Flag Register -; ETIFR.ICF3 5 Timer/Counter3, Input Capture Flag -; ETIFR.OCF3A 4 Timer/Counter3, Output Compare A Match Flag -; ETIFR.OCF3B 3 Timer/Counter3, Output Compare B Match Flag -; ETIFR.TOV3 2 Timer/Counter3, Overflow Flag -; ETIFR.OCF3C 1 Timer/Counter3, Output Compare C Match Flag -; ETIFR.OCF1C 0 Timer/Counter1, Output Compare C Match Flag -; ETIMSK 0x007D Extended Timer/Counter Interrupt Mask Register -; ETIMSK.TICIE3 5 Timer/Counter3, Input Capture Interrupt Enable -; ETIMSK.OCIE3A 4 Timer/Counter3, Output Compare A Match Interrupt Enable -; ETIMSK.OCIE3B 3 Timer/Counter3, Output Compare B Match Interrupt Enable -; ETIMSK.TOIE3 2 Timer/Counter3, Overflow Interrupt Enable -; ETIMSK.OCIE3C 1 Timer/Counter3, Output Compare C Match Interrupt Enable -; ETIMSK.OCIE1C 0 Timer/Counter1, Output Compare C Match Interrupt Enable -; RESERVED007E 0x007E RESERVED -; RESERVED007F 0x007F RESERVED -; ICR3L 0x0080 Input Capture Register 3 Low -; ICR3L.ICR3_7 7 -; ICR3L.ICR3_6 6 -; ICR3L.ICR3_5 5 -; ICR3L.ICR3_4 4 -; ICR3L.ICR3_3 3 -; ICR3L.ICR3_2 2 -; ICR3L.ICR3_1 1 -; ICR3L.ICR3_0 0 -; ICR3H 0x0081 Input Capture Register 3 High -; ICR3H.ICR3_15 15 -; ICR3H.ICR3_14 14 -; ICR3H.ICR3_13 13 -; ICR3H.ICR3_12 12 -; ICR3H.ICR3_11 11 -; ICR3H.ICR3_10 10 -; ICR3H.ICR3_9 9 -; ICR3H.ICR3_8 8 -; OCR3CL 0x0082 Output Compare Register 3 C Low -; OCR3CL.OCR3C_7 7 -; OCR3CL.OCR3C_6 6 -; OCR3CL.OCR3C_5 5 -; OCR3CL.OCR3C_4 4 -; OCR3CL.OCR3C_3 3 -; OCR3CL.OCR3C_2 2 -; OCR3CL.OCR3C_1 1 -; OCR3CL.OCR3C_0 0 -; OCR3CH 0x0083 Output Compare Register 3 C High -; OCR3CH.OCR3C_15 15 -; OCR3CH.OCR3C_14 14 -; OCR3CH.OCR3C_13 13 -; OCR3CH.OCR3C_12 12 -; OCR3CH.OCR3C_11 11 -; OCR3CH.OCR3C_10 10 -; OCR3CH.OCR3C_9 9 -; OCR3CH.OCR3C_8 8 -; OCR3BL 0x0084 Output Compare Register 3 B Low -; OCR3BL.OCR3B_7 7 -; OCR3BL.OCR3B_6 6 -; OCR3BL.OCR3B_5 5 -; OCR3BL.OCR3B_4 4 -; OCR3BL.OCR3B_3 3 -; OCR3BL.OCR3B_2 2 -; OCR3BL.OCR3B_1 1 -; OCR3BL.OCR3B_0 0 -; OCR3BH 0x0085 Output Compare Register 3 B High -; OCR3BH.OCR3B_15 15 -; OCR3BH.OCR3B_14 14 -; OCR3BH.OCR3B_13 13 -; OCR3BH.OCR3B_12 12 -; OCR3BH.OCR3B_11 11 -; OCR3BH.OCR3B_10 10 -; OCR3BH.OCR3B_9 9 -; OCR3BH.OCR3B_8 8 -; OCR3AL 0x0086 Output Compare Register 3 A Low -; OCR3AL.OCR3A_7 7 -; OCR3AL.OCR3A_6 6 -; OCR3AL.OCR3A_5 5 -; OCR3AL.OCR3A_4 4 -; OCR3AL.OCR3A_3 3 -; OCR3AL.OCR3A_2 2 -; OCR3AL.OCR3A_1 1 -; OCR3AL.OCR3A_0 0 -; OCR3AH 0x0087 Output Compare Register 3 A High -; OCR3AH.OCR3A_15 15 -; OCR3AH.OCR3A_14 14 -; OCR3AH.OCR3A_13 13 -; OCR3AH.OCR3A_12 12 -; OCR3AH.OCR3A_11 11 -; OCR3AH.OCR3A_10 10 -; OCR3AH.OCR3A_9 9 -; OCR3AH.OCR3A_8 8 -; TCNT3L 0x0088 Timer/Counter 3 Low -; TCNT3L.TCNT3_7 7 -; TCNT3L.TCNT3_6 6 -; TCNT3L.TCNT3_5 5 -; TCNT3L.TCNT3_4 4 -; TCNT3L.TCNT3_3 3 -; TCNT3L.TCNT3_2 2 -; TCNT3L.TCNT3_1 1 -; TCNT3L.TCNT3_0 0 -; TCNT3H 0x0089 Timer/Counter 3 High -; TCNT3H.TCNT3_15 15 -; TCNT3H.TCNT3_14 14 -; TCNT3H.TCNT3_13 13 -; TCNT3H.TCNT3_12 12 -; TCNT3H.TCNT3_11 11 -; TCNT3H.TCNT3_10 10 -; TCNT3H.TCNT3_9 9 -; TCNT3H.TCNT3_8 8 -; TCCR3B 0x008A Timer/Counter 3 Control Register B -; TCCR3B.ICNC3 7 Input Capture Noise Canceler -; TCCR3B.ICES3 6 Input Capture Edge Select -; TCCR3B.WGM33 4 Waveform Generation Mode 3 -; TCCR3B.WGM32 3 Waveform Generation Mode 2 -; TCCR3B.CS32 2 Clock Select 2 -; TCCR3B.CS31 1 Clock Select 1 -; TCCR3B.CS30 0 Clock Select 0 -; TCCR3A 0x008B Timer/Counter 3 Control Register A -; TCCR3A.COM3A1 7 Compare Output Mode for Channel A 1 -; TCCR3A.COM3A0 6 Compare Output Mode for Channel A 0 -; TCCR3A.COM3B1 5 Compare Output Mode for Channel B 1 -; TCCR3A.COM3B0 4 Compare Output Mode for Channel B 0 -; TCCR3A.COM3C1 3 Compare Output Mode for Channel C 1 -; TCCR3A.COM3C0 2 Compare Output Mode for Channel C 0 -; TCCR3A.WGM31 1 Waveform Generation Mode 1 -; TCCR3A.WGM30 0 Waveform Generation Mode 0 -; TCCR3C 0x008C Timer/Counter 3 Control Register C -; TCCR3C.FOC3A 7 Force Output Compare for Channel A -; TCCR3C.FOC3B 6 Force Output Compare for Channel B -; TCCR3C.FOC3C 5 Force Output Compare for Channel C -; RESERVED008D 0x008D RESERVED -; ADCSRB 0x008E ADC Control and Status Register B -; ADCSRB.ADTS2 2 ADC Auto Trigger Source 2 -; ADCSRB.ADTS1 1 ADC Auto Trigger Source 1 -; ADCSRB.ADTS0 0 ADC Auto Trigger Source 0 -; RESERVED008F 0x008F RESERVED -; UBRR0H 0x0090 USART Baud Rate Register High -; UBRR0H.UBRR11 11 USART Baud Rate Register bit 11 -; UBRR0H.UBRR10 10 USART Baud Rate Register bit 10 -; UBRR0H.UBRR9 9 USART Baud Rate Register bit 9 -; UBRR0H.UBRR8 8 USART Baud Rate Register bit 8 -; RESERVED0091 0x0091 RESERVED -; RESERVED0092 0x0092 RESERVED -; RESERVED0093 0x0093 RESERVED -; RESERVED0094 0x0094 RESERVED -; UCSR0C 0x0095 USART Control and Status Register C -; UCSR0C.UMSEL 6 USART Mode Select -; UCSR0C.UPM1 5 Parity Mode 1 -; UCSR0C.UPM0 4 Parity Mode 0 -; UCSR0C.USBS 3 Stop Bit Select -; UCSR0C.UCSZ1 2 Character Size 1 -; UCSR0C.UCSZ0 1 Character Size 0 -; UCSR0C.UCPOL 0 Clock Polarity -; RESERVED0096 0x0096 RESERVED -; RESERVED0097 0x0097 RESERVED -; UBRR1H 0x0098 USART Baud Rate Register High -; UBRR1H.UBRR11 11 USART Baud Rate Register bit 11 -; UBRR1H.UBRR10 10 USART Baud Rate Register bit 10 -; UBRR1H.UBRR9 9 USART Baud Rate Register bit 9 -; UBRR1H.UBRR8 8 USART Baud Rate Register bit 8 -; UBRR1L 0x0099 USART Baud Rate Register Low -; UBRR1L.UBRR7 7 USART Baud Rate Register bit 7 -; UBRR1L.UBRR6 6 USART Baud Rate Register bit 6 -; UBRR1L.UBRR5 5 USART Baud Rate Register bit 5 -; UBRR1L.UBRR4 4 USART Baud Rate Register bit 4 -; UBRR1L.UBRR3 3 USART Baud Rate Register bit 3 -; UBRR1L.UBRR2 2 USART Baud Rate Register bit 2 -; UBRR1L.UBRR1 1 USART Baud Rate Register bit 1 -; UBRR1L.UBRR0 0 USART Baud Rate Register bit 0 -; UCSR1B 0x009A USART Control and Status Register B -; UCSR1B.RXCIE 7 RX Complete Interrupt Enable -; UCSR1B.TXCIE 6 TX Complete Interrupt Enable -; UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSR1B.RXEN 4 Receiver Enable -; UCSR1B.TXEN 3 Transmitter Enable -; UCSR1B.UCSZ2 2 Character Size -; UCSR1B.RXB8 1 Receive Data Bit 8 -; UCSR1B.TXB8 0 Transmit Data Bit 8 -; UCSR1A 0x009B USART Control and Status Register A -; UCSR1A.RXC 7 USART Receive Complete -; UCSR1A.TXC 6 USART Transmit Complete -; UCSR1A.UDRE 5 USART Data Register Empty -; UCSR1A.FE 4 Frame Error -; UCSR1A.DOR 3 Data OverRun -; UCSR1A.UPE 2 USART Parity Error -; UCSR1A.U2X 1 Double the USART Transmission Speed -; UCSR1A.MPCM 0 Multi-processor Communication Mode -; UDR1 0x009C USART1 I/O Data Register -; UCSR1C 0x009D USART Control and Status Register C -; UCSR1C.UMSEL 6 USART Mode Select -; UCSR1C.UPM1 5 Parity Mode 1 -; UCSR1C.UPM0 4 Parity Mode 0 -; UCSR1C.USBS 3 Stop Bit Select -; UCSR1C.UCSZ1 2 Character Size 1 -; UCSR1C.UCSZ0 1 Character Size 0 -; UCSR1C.UCPOL 0 Clock Polarity - -.ATmega644P -SUBARCH=5 - -RAM=4096 -ROM=65536 -EEPROM=2048 - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 32 General Purpose Working Registers -area DATA FSR1 0x0020:0x0060 64 I/O registers -area DATA FSR2 0x0060:0x0100 160 Ext I/O Reg. -area DATA I_SRAM 0x0100:0x1100 Internal SRAM - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry INT2_ 0x0006 External Interrupt Request 2 -entry PCINT0 0x0008 Pin Change Interrupt Request 0 -entry PCINT1 0x000A Pin Change Interrupt Request 1 -entry PCINT2 0x000C Pin Change Interrupt Request 2 -entry PCINT3 0x000E Pin Change Interrupt Request 3 -entry WDT 0x0010 Watchdog Time-out Interrupt -entry TIMER2_COMPA 0x0012 Timer/Counter2 Comapare Match A -entry TIMER2_COMPB 0x0014 Timer/Counter2 Comapare Match B -entry TIMER2_OVF 0x0016 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0018 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x001A Timer/Counter1 Comapare Match A -entry TIMER1_COMPB 0x001C Timer/Counter1 Comapare Match B -entry TIMER1_OVF 0x001E Timer/Counter1 Overflow -entry TIMER0_COMPA 0x0020 Timer/Counter0 Comapare Match A -entry TIMER0_COMPB 0x0022 Timer/Counter0 Comapare Match B -entry TIMER0_OVF 0x0024 Timer/Counter0 Overflow -entry SPI_STC 0x0026 SPI Serial Transfer Complete -entry USART0_RX 0x0028 USART0 RX Complete -entry USART0_UDRE 0x002A USART0 Data register empty -entry USART0_TX 0x002C USART0 TX Complete -entry ANALOG_COMP 0x002E Analog Comparator -entry ADC_ 0x0030 ADC Conversion Complete -entry EEREADY 0x0032 EEPROM Ready -entry TWI_ 0x0034 2-wire Serial Interface -entry SPM_READY 0x0036 Store Program Memory Ready -entry USART1_RX 0x0038 USART1 RX Complete -entry USART1_UDRE 0x003A USART1 Data register empty -entry USART1_TX 0x003C USART1 TX Complete - - -; INPUT/OUTPUT PORTS -; CHECK ALL REGISTERS FROM REGISTERS SUMMARY - -UDR1 0x00AE USART1 I/O Data Register -UBRR1H 0x00AD USART1 Baud Rate Register High Byte -UBRR1L 0x00AC USART1 Baud Rate Register Low Byte - -UCSR1C 0x00AA -UCSR1C.UMSEL11 7 -UCSR1C.UMSEL10 6 -UCSR1C.UCORD1 2 -UCSR1C.UCPHA1 1 -UCSR1C.UCPOL1 0 - -UCSR1B 0x00A9 -UCSR1B.RXCIE1 7 -UCSR1B.TXCIE1 6 -UCSR1B.UDRIE1 5 -UCSR1B.RXEN1 4 -UCSR1B.TXEN1 3 -UCSR1B.UCSZ12 2 -UCSR1B.RXB81 1 -UCSR1B.TXB81 0 - -UCSR1A 0x00A8 -UCSR1A.RXC1 7 -UCSR1A.TXC1 6 -UCSR1A.UDRE1 5 -UCSR1A.FE1 4 -UCSR1A.DOR1 3 -UCSR1A.UPE1 2 -UCSR1A.U2X1 1 -UCSR1A.MPCM1 0 - -UDR0 0x00A6 USART0 I/O Data Register -UBRR0H 0x00A5 USART0 Baud Rate Register High Byte -UBRR0L 0x00A4 USART0 Baud Rate Register Low Byte - -UCSR0C 0x00A2 -UCSR0C.UMSEL01 7 -UCSR0C.UMSEL00 6 -UCSR0C.UDORD0 2 -UCSR0C.UCPHA0 1 -UCSR0C.UCPOL0 0 - -UCSR0B 0x00A1 -UCSR0B.RXCIE0 7 -UCSR0B.TXCIE0 6 -UCSR0B.UDRIE0 5 -UCSR0B.RXEN0 4 -UCSR0B.TXEN0 3 -UCSR0B.UCSZ02 2 -UCSR0B.RXB80 1 -UCSR0B.TXB80 0 - -UCSR0A 0x00A0 -UCSR0A.RXC0 7 -UCSR0A.TXC0 6 -UCSR0A.UDRE0 5 -UCSR0A.FE0 4 -UCSR0A.DOR0 3 -UCSR0A.UPE0 2 -UCSR0A.U2X0 1 -UCSR0A.MPCM0 0 - -TWAMR 0x009D TWI (Slave) Address Mask Register -TWAMR.TWAM6 7 TWAM: TWI Address Mask bit 6 -TWAMR.TWAM5 6 TWAM: TWI Address Mask bit 5 -TWAMR.TWAM4 5 TWAM: TWI Address Mask bit 4 -TWAMR.TWAM3 4 TWAM: TWI Address Mask bit 3 -TWAMR.TWAM2 3 TWAM: TWI Address Mask bit 2 -TWAMR.TWAM1 2 TWAM: TWI Address Mask bit 1 -TWAMR.TWAM0 1 TWAM: TWI Address Mask bit 0 - -TWCR 0x009C TWI Control Register -TWCR.TWINT 7 TWINT: TWI Interrupt Flag -TWCR.TWEA 6 TWEA: TWI Enable Acknowledge Bit -TWCR.TWSTA 5 TWSTA: TWI START Condition Bit -TWCR.TWSTO 4 TWSTO: TWI STOP Condition Bit -TWCR.TWWC 3 TWWC: TWI Write Collision Flag -TWCR.TWEN 2 TWEN: TWI Enable Bit -TWCR.TWIE 0 TWIE: TWI Interrupt Enable - -TWDR 0x009B 2-wire Serial Interface Data Register - -TWAR 0x009A TWI (Slave) Address Register -TWAR.TWA6 7 TWA: TWI (Slave) Address Register bit 6 -TWAR.TWA5 6 TWA: TWI (Slave) Address Register bit 5 -TWAR.TWA4 5 TWA: TWI (Slave) Address Register bit 4 -TWAR.TWA3 4 TWA: TWI (Slave) Address Register bit 3 -TWAR.TWA2 3 TWA: TWI (Slave) Address Register bit 2 -TWAR.TWA1 2 TWA: TWI (Slave) Address Register bit 1 -TWAR.TWA0 1 TWA: TWI (Slave) Address Register bit 0 -TWAR.TWGCE 0 TWGCE: TWI General Call Recognition Enable Bit - -TWSR 0x0099 TWI Status Register -TWSR.TWS7 7 TWS: TWI Status bit 4 -TWSR.TWS6 6 TWS: TWI Status bit 3 -TWSR.TWS5 5 TWS: TWI Status bit 2 -TWSR.TWS4 4 TWS: TWI Status bit 1 -TWSR.TWS3 3 TWS: TWI Status bit 0 -TWSR.TWPS1 1 TWPS: TWI Prescaler bit 1 -TWSR.TWPS0 0 TWPS: TWI Prescaler bit 0 - -TWBR 0x0098 2-wire Serial Interface Bit Rate Register - -ASSR 0x0096 Asynchronous Status Register -ASSR.EXCLK 6 EXCLK: Enable External Clock Input -ASSR.AS2 5 AS2: Asynchronous Timer/Counter2 -ASSR.TCN2UB 4 TCN2UB: Timer/Counter2 Update Busy -ASSR.OCR2AUB 3 OCR2AUB: Output Compare Register2 Update Busy -ASSR.OCR2BUB 2 OCR2BUB: Output Compare Register2 Update Busy -ASSR.TCR2AUB 1 TCR2AUB: Timer/Counter Control Register2 Update Busy -ASSR.TCR2BUB 0 TCR2BUB: Timer/Counter Control Register2 Update Busy - -OCR2B 0x0094 Timer/Counter2 Output Compare Register B - -OCR2A 0x0093 Timer/Counter2 Output Compare Register A - -TCNT2 0x0092 Timer/Counter2 (8 Bit) - -TCCR2B 0x0091 Timer/Counter Control Register B -TCCR2B.FOC2A 7 FOC2A: Force Output Compare A -TCCR2B.FOC2B 6 FOC2B: Force Output Compare B -TCCR2B.WGM22 3 WGM22: Waveform Generation Mode -TCCR2B.CS22 2 CS22 Clock Select -TCCR2B.CS21 1 CS21 Clock Select -TCCR2B.CS20 0 CS20 Clock Select - -TCCR2A 0x0090 Timer/Counter Control Register A -TCCR2A.COM2A1 7 COM2A1 Compare Match Output A Mode -TCCR2A.COM2A0 6 COM2A0 Compare Match Output A Mode -TCCR2A.COM2B1 5 COM2B1 Compare Match Output B Mode -TCCR2A.COM2B0 4 COM2B0 Compare Match Output B Mode -TCCR2A.WGM21 1 WGM21 Waveform Generation Mode -TCCR2A.WGM20 0 WGM20 Waveform Generation Mode - -OCR1BH 0x006B Timer/Counter1 - Output Compare Register B High Byte -OCR1BH.Timer_Counter1 7 -OCR1BH.Output 5 -OCR1BH.Compare 4 -OCR1BH.Register 3 -OCR1BH.B 2 -OCR1BH.High 1 -OCR1BH.Byte 0 - -OCR1BL 0x006A Timer/Counter1 - Output Compare Register B Low Byte -OCR1BL.Timer_Counter1 7 -OCR1BL.Output 5 -OCR1BL.Compare 4 -OCR1BL.Register 3 -OCR1BL.B 2 -OCR1BL.Low 1 -OCR1BL.Byte 0 - -OCR1AH 0x0069 Timer/Counter1 - Output Compare Register A High Byte -OCR1AH.Timer_Counter1 7 -OCR1AH.Output 5 -OCR1AH.Compare 4 -OCR1AH.Register 3 -OCR1AH.A 2 -OCR1AH.High 1 -OCR1AH.Byte 0 - -OCR1AL 0x0068 Timer/Counter1 - Output Compare Register A Low Byte -OCR1AL.Timer_Counter1 7 -OCR1AL.Output 5 -OCR1AL.Compare 4 -OCR1AL.Register 3 -OCR1AL.A 2 -OCR1AL.Low 1 -OCR1AL.Byte 0 - -ICR1H 0x0067 Timer/Counter1 - Input Capture Register High Byte -ICR1H.Timer_Counter1 7 -ICR1H.Input 5 -ICR1H.Capture 4 -ICR1H.Register 3 -ICR1H.High 2 -ICR1H.Byte 1 -ICR1H.136 0 - -ICR1L 0x0066 Timer/Counter1 - Input Capture Register Low Byte -ICR1L.Timer_Counter1 7 -ICR1L.Input 5 -ICR1L.Capture 4 -ICR1L.Register 3 -ICR1L.Low 2 -ICR1L.Byte 1 -ICR1L.136 0 - -TCNT1H 0x0065 Timer/Counter1 - Counter Register High Byte - -TCNT1L 0x0064 Timer/Counter1 - Counter Register Low Byte - -TCCR1C 0x0062 Timer/Counter1 Control Register C -TCCR1C.FOC1A 7 FOC1A: Force Output Compare for Channel A -TCCR1C.FOC1B 6 FOC1B: Force Output Compare for Channel B - -TCCR1B 0x0061 Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 ICNC1: Input Capture Noise Canceler -TCCR1B.ICES1 6 ICES1: Input Capture Edge Select -TCCR1B.WGM13 4 WGM13 Waveform Generation Mode -TCCR1B.WGM12 3 WGM12 Waveform Generation Mode -TCCR1B.CS12 2 CS12 Clock Select -TCCR1B.CS11 1 CS11 Clock Select -TCCR1B.CS10 0 CS10 Clock Select - -TCCR1A 0x0060 Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 COM1A1 Compare Output Mode for Channel A -TCCR1A.COM1A0 6 COM1A0 Compare Output Mode for Channel A -TCCR1A.COM1B1 5 COM1B1 Compare Output Mode for Channel B -TCCR1A.COM1B0 4 COM1B0 Compare Output Mode for Channel B -TCCR1A.WGM11 1 WGM11 Waveform Generation Mode -TCCR1A.WGM10 0 WGM10 Waveform Generation Mode - -DIDR1 0x005F Digital Input Disable Register 1 -DIDR1.AIN1D 1 AIN1D: AIN1 Digital Input Disable -DIDR1.AIN0D 0 AIN0D: AIN0 Digital Input Disable - -DIDR0 0x005E Digital Input Disable Register 0 -DIDR0.ADC7D 7 ADC7D: ADC7 Digital Input Disable -DIDR0.ADC6D 6 ADC6D: ADC6 Digital Input Disable -DIDR0.ADC5D 5 ADC5D: ADC5 Digital Input Disable -DIDR0.ADC4D 4 ADC4D: ADC4 Digital Input Disable -DIDR0.ADC3D 3 ADC3D: ADC3 Digital Input Disable -DIDR0.ADC2D 2 ADC2D: ADC2 Digital Input Disable -DIDR0.ADC1D 1 ADC1D: ADC1 Digital Input Disable -DIDR0.ADC0D 0 ADC0D: ADC0 Digital Input Disable - -ADMUX 0x005C ADC Multiplexer Selection Register -ADMUX.REFS1 7 REFS1 Reference Selection Bits -ADMUX.REFS0 6 REFS0 Reference Selection Bits -ADMUX.ADLAR 5 ADLAR: ADC Left Adjust Result -ADMUX.MUX4 4 MUX4 Analog Channel and Gain Selection bit 4 -ADMUX.MUX3 3 MUX3 Analog Channel and Gain Selection bit 3 -ADMUX.MUX2 2 MUX2 Analog Channel and Gain Selection bit 2 -ADMUX.MUX1 1 MUX1 Analog Channel and Gain Selection bit 1 -ADMUX.MUX0 0 MUX0 Analog Channel and Gain Selection bit 0 - -ADCSRB 0x005B ADC Control and Status Register B -ADCSRB.ACME 6 -ADCSRB.ADTS2 2 -ADCSRB.ADTS1 1 -ADCSRB.ADTS0 0 - -ADCSRA 0x005A ADC Control and Status Register A -ADCSRA.ADEN 7 ADEN: ADC Enable -ADCSRA.ADSC 6 ADSC: ADC Start Conversion -ADCSRA.ADATE 5 ADATE: ADC Auto Trigger Enable -ADCSRA.ADIF 4 ADIF: ADC Interrupt Flag -ADCSRA.ADIE 3 ADIE: ADC Interrupt Enable -ADCSRA.ADPS2 2 ADPS2 ADC Prescaler Select bit 2 -ADCSRA.ADPS1 1 ADPS1 ADC Prescaler Select bit 1 -ADCSRA.ADPS0 0 ADPS0 ADC Prescaler Select bit 0 - -ADCH 0x0059 ADC Data Register High byte - -ADCL 0x0058 ADC Data Register Low byte - -PCMSK3 0x0053 Pin Change Mask Register 3 -PCMSK3.PCINT31 7 PCINT31 Pin Change Enable Mask -PCMSK3.PCINT30 6 PCINT30 Pin Change Enable Mask -PCMSK3.PCINT29 5 PCINT29 Pin Change Enable Mask -PCMSK3.PCINT28 4 PCINT28 Pin Change Enable Mask -PCMSK3.PCINT27 3 PCINT27 Pin Change Enable Mask -PCMSK3.PCINT26 2 PCINT26 Pin Change Enable Mask -PCMSK3.PCINT25 1 PCINT25 Pin Change Enable Mask -PCMSK3.PCINT24 0 PCINT24 Pin Change Enable Mask - -TIMSK2 0x0050 Timer/Counter2 Interrupt Mask Register -TIMSK2.OCIE2B 2 OCIE2B: Timer/Counter2 Output Compare Match B Interrupt Enable -TIMSK2.OCIE2A 1 OCIE2A: Timer/Counter2 Output Compare Match A Interrupt Enable -TIMSK2.TOIE2 0 TOIE2: Timer/Counter2 Overflow Interrupt Enable - -TIMSK1 0x004F Timer/Counter1 Interrupt Mask Register -TIMSK1.ICIE1 5 ICIE1: Timer/Counter1, Input Capture Interrupt Enable -TIMSK1.OCIE1B 2 OCIE1B: Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK1.OCIE1A 1 OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK1.TOIE1 0 TOIE1: Timer/Counter1, Overflow Interrupt Enable - -TIMSK0 0x004E Timer/Counter Interrupt Mask Register -TIMSK0.OCIE0B 2 OCIE0B: Timer/Counter Output Compare Match B Interrupt Enable -TIMSK0.OCIE0A 1 OCIE0A: Timer/Counter0 Output Compare Match A Interrupt Enable -TIMSK0.TOIE0 0 TOIE0: Timer/Counter0 Overflow Interrupt Enable - -PCMSK2 0x004D Pin Change Mask Register 2 -PCMSK2.PCINT23 7 PCINT23 Pin Change Enable Mask -PCMSK2.PCINT22 6 PCINT22 Pin Change Enable Mask -PCMSK2.PCINT21 5 PCINT21 Pin Change Enable Mask -PCMSK2.PCINT20 4 PCINT20 Pin Change Enable Mask -PCMSK2.PCINT19 3 PCINT19 Pin Change Enable Mask -PCMSK2.PCINT18 2 PCINT18 Pin Change Enable Mask -PCMSK2.PCINT17 1 PCINT17 Pin Change Enable Mask -PCMSK2.PCINT16 0 PCINT16 Pin Change Enable Mask - -PCMSK1 0x004C Pin Change Mask Register 1 -PCMSK1.PCINT15 7 PCINT15 Pin Change Enable Mask -PCMSK1.PCINT14 6 PCINT14 Pin Change Enable Mask -PCMSK1.PCINT13 5 PCINT13 Pin Change Enable Mask -PCMSK1.PCINT12 4 PCINT12 Pin Change Enable Mask -PCMSK1.PCINT11 3 PCINT11 Pin Change Enable Mask -PCMSK1.PCINT10 2 PCINT10 Pin Change Enable Mask -PCMSK1.PCINT9 1 PCINT9 Pin Change Enable Mask -PCMSK1.PCINT8 0 PCINT8 Pin Change Enable Mask - -PCMSK0 0x004B Pin Change Mask Register 0 -PCMSK0.PCINT7 7 PCINT7 Pin Change Enable Mask -PCMSK0.PCINT6 6 PCINT6 Pin Change Enable Mask -PCMSK0.PCINT5 5 PCINT5 Pin Change Enable Mask -PCMSK0.PCINT4 4 PCINT4 Pin Change Enable Mask -PCMSK0.PCINT3 3 PCINT3 Pin Change Enable Mask -PCMSK0.PCINT2 2 PCINT2 Pin Change Enable Mask -PCMSK0.PCINT1 1 PCINT1 Pin Change Enable Mask -PCMSK0.PCINT0 0 PCINT0 Pin Change Enable Mask - -EICRA 0x0049 External Interrupt Control Register A -EICRA.ISC21 5 ISC21: External Interrupt Sense Control Bits -EICRA.ISC20 4 ISC20: External Interrupt Sense Control Bits -EICRA.ISC11 3 ISC11: External Interrupt Sense Control Bits -EICRA.ISC10 2 ISC10: External Interrupt Sense Control Bits -EICRA.ISC01 1 ISC01: External Interrupt Sense Control Bits -EICRA.ISC00 0 ISC00: External Interrupt Sense Control Bits - -PCICR 0x0048 Pin Change Interrupt Control Register -PCICR.PCIE3 3 PCIE3: Pin Change Interrupt Enable 3 -PCICR.PCIE2 2 PCIE2: Pin Change Interrupt Enable 2 -PCICR.PCIE1 1 PCIE1: Pin Change Interrupt Enable 1 -PCICR.PCIE0 0 PCIE0: Pin Change Interrupt Enable 0 - -OSCCAL 0x0046 Oscillator Calibration Register - -PRR 0x0044 Power Reduction Register -PRR.PRTWI 7 PRTWI: Power Reduction TWI -PRR.PRTIM2 6 PRTIM2: Power Reduction Timer/Counter2 -PRR.PRTIM0 5 PRTIM0: Power Reduction Timer/Counter0 -PRR.PRUSART1 4 PRUSART1: Power Reduction USART1 -PRR.PRTIM1 3 PRTIM1: Power Reduction Timer/Counter1 -PRR.PRSPI 2 PRSPI: Power Reduction Serial Peripheral Interface -PRR.PRUSART0 1 PRUSART0: Power Reduction USART0 -PRR.PRADC 0 PRADC: Power Reduction ADC - -CLKPR 0x0041 Clock Prescale Register -CLKPR.CLKPCE 7 CLKPCE: Clock Prescaler Change Enable -CLKPR.CLKPS3 3 CLKPS3 Clock Prescaler Select bit 3 -CLKPR.CLKPS2 2 CLKPS2 Clock Prescaler Select bit 2 -CLKPR.CLKPS1 1 CLKPS1 Clock Prescaler Select bit 1 -CLKPR.CLKPS0 0 CLKPS0 Clock Prescaler Select bit 0 - -WDTCSR 0x0040 Watchdog Timer Control Register -WDTCSR.WDIF 7 WDIF: Watchdog Interrupt Flag -WDTCSR.WDIE 6 WDIE: Watchdog Interrupt Enable -WDTCSR.WDP3 5 WDP3: Watchdog Timer Prescaler 3 -WDTCSR.WDCE 4 WDCE: Watchdog Change Enable -WDTCSR.WDE 3 WDCE: Watchdog Change Enable -WDTCSR.WDP2 2 WDP2: Watchdog Timer Prescaler 3 -WDTCSR.WDP1 1 WDP1: Watchdog Timer Prescaler 3 -WDTCSR.WDP0 0 WDP0: Watchdog Timer Prescaler 3 - -SREG 0x003F Status Register -SREG.I 7 I: Global Interrupt Enable -SREG.T 6 T: Bit Copy Storage -SREG.H 5 H: Half Carry Flag -SREG.S 4 S: Sign Bit -SREG.V 3 V: Two’s Complement Overflow Flag -SREG.N 2 N: Negative Flag -SREG.Z 1 Z: Zero Flag -SREG.C 0 C: Carry Flag - -SPH 0x003E Stack Pointer High -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 - -SPL 0x003D Stack pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 - -SPMCSR 0x0037 Store Program Memory Control and Status Register -SPMCSR.SPMIE 7 SPMIE: SPM Interrupt Enable -SPMCSR.RWWSB 6 RWWSB: Read-While-Write Section Busy -SPMCSR.SIGRD 5 SIGRD: Signature Row Read -SPMCSR.RWWSRE 4 RWWSRE: Read-While-Write Section Read Enable -SPMCSR.BLBSET 3 BLBSET: Boot Lock Bit Set -SPMCSR.PGWRT 2 PGWRT: Page Write -SPMCSR.PGERS 1 PGERS: Page Erase -SPMCSR.SPMEN 0 SPMEN: Store Program Memory Enable - -MCUCR 0x0035 MCU Control Register -MCUCR.JTD 7 -MCUCR.BODS 6 BODS: BOD Sleep -MCUCR.BODSE 5 BODSE: BOD Sleep Enable -MCUCR.PUD 4 -MCUCR.IVSEL 1 -MCUCR.IVCE 0 - -MCUSR 0x0034 MCU Status Register -MCUSR.JTRF 4 JTRF: JTAG Reset Flag -MCUSR.WDRF 3 WDRF: Watchdog Reset Flag -MCUSR.BORF 2 BORF: Brown-out Reset Flag -MCUSR.EXTRF 1 EXTRF: External Reset Flag -MCUSR.PORF 0 PORF: Power-on Reset Flag - -SMCR 0x0033 Sleep Mode Control Register -SMCR.SM2 3 SM2 Sleep Mode Select bit 2 -SMCR.SM1 2 SM1 Sleep Mode Select bit 1 -SMCR.SM0 1 SM0 Sleep Mode Select bit 0 -SMCR.SE 0 SE: Sleep Enable - -OCDR 0x0031 On-Chip Debug Register - -ACSR 0x0030 Analog Comparator Control and Status Register -ACSR.ACD 7 ACD: Analog Comparator Disable -ACSR.ACBG 6 ACBG: Analog Comparator Bandgap Select -ACSR.ACO 5 ACO: Analog Comparator Output -ACSR.ACI 4 ACI: Analog Comparator Interrupt Flag -ACSR.ACIE 3 ACIE: Analog Comparator Interrupt Enable -ACSR.ACIC 2 ACIC: Analog Comparator Input Capture Enable -ACSR.ACIS1 1 ACIS1: Analog Comparator Interrupt Mode Select -ACSR.ACIS0 0 ACIS0: Analog Comparator Interrupt Mode Select - -SPDR 0x002E SPI Data Register - -SPSR 0x002D SPI Status Register -SPSR.SPIF 7 SPIF: SPI Interrupt Flag -SPSR.WCOL 6 WCOL: Write COLlision Flag -SPSR.SPI2X 0 SPI2X: Double SPI Speed Bit - -SPCR 0x002C SPI Control Register -SPCR.SPIE 7 SPIE: SPI Interrupt Enable -SPCR.SPE 6 SPE: SPI Enable -SPCR.DORD 5 DORD: Data Order -SPCR.MSTR 4 MSTR: Master/Slave Select -SPCR.CPOL 3 CPOL: Clock Polarity -SPCR.CPHA 2 CPHA: Clock Phase -SPCR.SPR1 1 SPR1: SPI Clock Rate Select 1 -SPCR.SPR0 0 SPR0: SPI Clock Rate Select 0 - -GPIOR2 0x002B General Purpose I/O Register 2 - -GPIOR1 0x002A General Purpose I/O Register 1 - -OCR0B 0x0028 Timer/Counter0 Output Compare Register B - -OCR0A 0x0027 Timer/Counter0 Output Compare Register A - -TCNT0 0x0026 Timer/Counter0 (8 Bit) - -TCCR0B 0x0025 Timer/Counter Control Register B -TCCR0B.FOC0A 7 FOC0A: Force Output Compare A -TCCR0B.FOC0B 6 FOC0B: Force Output Compare B -TCCR0B.WGM02 3 WGM02: Waveform Generation Mode -TCCR0B.CS02 2 CS02: Clock Select -TCCR0B.CS01 1 CS01: Clock Select -TCCR0B.CS00 0 CS00: Clock Select - -TCCR0A 0x0024 Timer/Counter Control Register A -TCCR0A.COM0A1 7 COM0A1: Compare Match Output A Mode -TCCR0A.COM0A0 6 COM0A0: Compare Match Output A Mode -TCCR0A.COM0B1 5 COM0B1: Compare Match Output B Mode -TCCR0A.COM0B0 4 COM0B0: Compare Match Output B Mode -TCCR0A.WGM01 1 WGM01: Waveform Generation Mode -TCCR0A.WGM00 0 WGM00: Waveform Generation Mode - -GTCCR 0x0023 General Timer/Counter Control Register -GTCCR.TSM 7 TSM: Timer/Counter Synchronization mode -GTCCR.PSRASY 1 PSRASY: Prescaler Reset Timer/Counter2 -GTCCR.PSRSYNC 0 PSRSYNC: Prescaler Reset - -EEARH 0x0022 EEPROM Address Register High Byte -EEARL 0x0021 EEPROM Address Register Low Byte -EEDR 0x0020 EEPROM Data Register - -EECR 0x001F The EEPROM Control Register -EECR.EEPM1 5 EEPM1: EEPROM Programming Mode Bits -EECR.EEPM0 4 EEPM0: EEPROM Programming Mode Bits -EECR.EERIE 3 EERIE: EEPROM Ready Interrupt Enable -EECR.EEMPE 2 EEMPE: EEPROM Master Programming Enable -EECR.EEPE 1 EEPE: EEPROM Programming Enable -EECR.EERE 0 EERE: EEPROM Read Enable - -GPIOR0 0x001E General Purpose I/O Register 0 - -EIMSK 0x001D External Interrupt Mask Register -EIMSK.INT2 2 INT2 External Interrupt Request 2 -EIMSK.INT1 1 INT1 External Interrupt Request 1 -EIMSK.INT0 0 INT0 External Interrupt Request 0 - -EIFR 0x001C External Interrupt Flag Register -EIFR.INTF2 2 INTF2 External Interrupt Flags 2 -EIFR.INTF1 1 INTF1 External Interrupt Flags 1 -EIFR.INTF0 0 INTF0 External Interrupt Flags 0 - -PCIFR 0x001B Pin Change Interrupt Flag Register -PCIFR.PCIF3 3 PCIF3: Pin Change Interrupt Flag 3 -PCIFR.PCIF2 2 PCIF2: Pin Change Interrupt Flag 2 -PCIFR.PCIF1 1 PCIF1: Pin Change Interrupt Flag 1 -PCIFR.PCIF0 0 PCIF0: Pin Change Interrupt Flag 0 - -TIFR2 0x0017 Timer/Counter2 Interrupt Flag Register -TIFR2.OCF2B 2 OCF2B: Output Compare Flag 2 B -TIFR2.OCF2A 1 OCF2A: Output Compare Flag 2 A -TIFR2.TOV2 0 TOV2: Timer/Counter2 Overflow Flag - -TIFR1 0x0016 Timer/Counter1 Interrupt Flag Register -TIFR1.ICF1 5 ICF1: Timer/Counter1, Input Capture Flag -TIFR1.OCF1B 2 OCF1B: Timer/Counter1, Output Compare B Match Flag -TIFR1.OCF1A 1 OCF1A: Timer/Counter1, Output Compare A Match Flag -TIFR1.TOV1 0 TOV1: Timer/Counter1, Overflow Flag - -TIFR0 0x0015 Timer/Counter 0 Interrupt Flag Register -TIFR0.OCF0B 2 OCF0B: Timer/Counter 0 Output Compare B Match Flag -TIFR0.OCF0A 1 OCF0A: Timer/Counter 0 Output Compare A Match Flag -TIFR0.TOV0 0 TOV0: Timer/Counter0 Overflow Flag - -PORTD 0x000B Port D Data Register -PORTD.PORTD7 7 PORT D7 -PORTD.PORTD6 6 PORT D6 -PORTD.PORTD5 5 PORT D5 -PORTD.PORTD4 4 PORT D4 -PORTD.PORTD3 3 PORT D3 -PORTD.PORTD2 2 PORT D2 -PORTD.PORTD1 1 PORT D1 -PORTD.PORTD0 0 PORT D0 - -DDRD 0x000A Port D Data Direction Register -DDRD.DDD7 7 -DDRD.DDD6 6 -DDRD.DDD5 5 -DDRD.DDD4 4 -DDRD.DDD3 3 -DDRD.DDD2 2 -DDRD.DDD1 1 -DDRD.DDD0 0 - -PIND 0x0009 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 - -PORTC 0x0008 Port C Data Register -PORTC.PORTC7 7 -PORTC.PORTC6 6 -PORTC.PORTC5 5 -PORTC.PORTC4 4 -PORTC.PORTC3 3 -PORTC.PORTC2 2 -PORTC.PORTC1 1 -PORTC.PORTC0 0 - -DDRC 0x0007 Port C Data Direction Register -DDRC.DDC7 7 -DDRC.DDC6 6 -DDRC.DDC5 5 -DDRC.DDC4 4 -DDRC.DDC3 3 -DDRC.DDC2 2 -DDRC.DDC1 1 -DDRC.DDC0 0 - -PINC 0x0006 Port C Input Pins Address -PINC.PINC6 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 - -PORTB 0x0005 Port B Data Register -PORTB.PORTB7 7 -PORTB.PORTB6 6 -PORTB.PORTB5 5 -PORTB.PORTB4 4 -PORTB.PORTB3 3 -PORTB.PORTB2 2 -PORTB.PORTB1 1 -PORTB.PORTB0 0 - -DDRB 0x0004 Port B Data Direction Register -DDRB.DDB7 7 -DDRB.DDB6 6 -DDRB.DDB5 5 -DDRB.DDB4 4 -DDRB.DDB3 3 -DDRB.DDB2 2 -DDRB.DDB1 1 -DDRB.DDB0 0 - -PINB 0x0003 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 - -PORTA 0x0002 Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 - -DDRA 0x0001 Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 - -PINA 0x0000 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 - -.ATmega8515_L -SUBARCH=2 -; doc2512.pdf -; - -RAM=512 -ROM=8192 -EEPROM=512 - -; MEMORY MAP -area DATA FSR_ 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x0260 Internal SRAM -area DATA E_SRAM 0x0260:0x10000 External SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset,Brown-out Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0005 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0006 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0007 Timer/Counter0 Overflow -entry SPI_STC 0x0008 Serial Transfer Complete -entry USART_RXC 0x0009 USART, Rx Complete -entry USART_UDRE 0x000A USART Data Register Empty -entry USART_TXC 0x000B USART, Tx Complete -entry ANA_COMP 0x000C Analog Comparator -entry INT2_ 0x000D External Interrupt Request 2 -entry TIMER0_COMP 0x000E Timer/Counter0 Compare Match -entry EE_RDY 0x000F EEPROM Ready -entry SPM_RDY 0x0010 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -OSCCAL 0x0004 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -PINE 0x0005 Port E Input Pins Address -PINE.PINE2 2 -PINE.PINE1 1 -PINE.PINE0 0 -DDRE 0x0006 Port E Data Direction Register -DDRE.DDE2 2 Port E Data Direction Register bit 2 -DDRE.DDE1 1 Port E Data Direction Register bit 1 -DDRE.DDE0 0 Port E Data Direction Register bit 0 -PORTE 0x0007 Port E Data Register -PORTE.PORTE2 2 Port E Data Register bit 2 -PORTE.PORTE1 1 Port E Data Register bit 1 -PORTE.PORTE0 0 Port E Data Register bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register Low -UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -UCSRB 0x000A USART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit8 -UCSRA 0x000B USART Control and Status Register A -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.PE 2 ParityError -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision Flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR9 9 EEPROM Addres 9 -UCSRC 0x0020 USART Control and Status Register C -UCSRC.URSEL 7 Register Select -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -; UBRRH 0x0020 USART Baud Rate Register High -; UBRRH.URSEL 15 Register Select -; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -ICR1L 0x0024 Input Capture Register 1 Low -ICR1L.ICR1_7 7 -ICR1L.ICR1_6 6 -ICR1L.ICR1_5 5 -ICR1L.ICR1_4 4 -ICR1L.ICR1_3 3 -ICR1L.ICR1_2 2 -ICR1L.ICR1_1 1 -ICR1L.ICR1_0 0 -ICR1H 0x0025 Input Capture Register 1 High -ICR1H.ICR1_15 15 -ICR1H.ICR1_14 14 -ICR1H.ICR1_13 13 -ICR1H.ICR1_12 12 -ICR1H.ICR1_11 11 -ICR1H.ICR1_10 10 -ICR1H.ICR1_9 9 -ICR1H.ICR1_8 8 -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -OCR1BL 0x0028 Output Compare Register 1 B Low -OCR1BL.OCR1B_7 7 -OCR1BL.OCR1B_6 6 -OCR1BL.OCR1B_5 5 -OCR1BL.OCR1B_4 4 -OCR1BL.OCR1B_3 3 -OCR1BL.OCR1B_2 2 -OCR1BL.OCR1B_1 1 -OCR1BL.OCR1B_0 0 -OCR1BH 0x0029 Output Compare Register 1 B High -OCR1BH.OCR1B_15 15 -OCR1BH.OCR1B_14 14 -OCR1BH.OCR1B_13 13 -OCR1BH.OCR1B_12 12 -OCR1BH.OCR1B_11 11 -OCR1BH.OCR1B_10 10 -OCR1BH.OCR1B_9 9 -OCR1BH.OCR1B_8 8 -OCR1AL 0x002A Output Compare Register 1 A Low -OCR1AL.OCR1A_7 7 -OCR1AL.OCR1A_6 6 -OCR1AL.OCR1A_5 5 -OCR1AL.OCR1A_4 4 -OCR1AL.OCR1A_3 3 -OCR1AL.OCR1A_2 2 -OCR1AL.OCR1A_1 1 -OCR1AL.OCR1A_0 0 -OCR1AH 0x002B Output Compare Register 1 A High -OCR1AH.OCR1A_15 15 -OCR1AH.OCR1A_14 14 -OCR1AH.OCR1A_13 13 -OCR1AH.OCR1A_12 12 -OCR1AH.OCR1A_11 11 -OCR1AH.OCR1A_10 10 -OCR1AH.OCR1A_9 9 -OCR1AH.OCR1A_8 8 -TCNT1L 0x002C Timer/Counter 1 Low -TCNT1L.TCNT1_7 7 -TCNT1L.TCNT1_6 6 -TCNT1L.TCNT1_5 5 -TCNT1L.TCNT1_4 4 -TCNT1L.TCNT1_3 3 -TCNT1L.TCNT1_2 2 -TCNT1L.TCNT1_1 1 -TCNT1L.TCNT1_0 0 -TCNT1H 0x002D Timer/Counter 1 High -TCNT1H.TCNT1_15 15 -TCNT1H.TCNT1_14 14 -TCNT1H.TCNT1_13 13 -TCNT1H.TCNT1_12 12 -TCNT1H.TCNT1_11 11 -TCNT1H.TCNT1_10 10 -TCNT1H.TCNT1_9 9 -TCNT1H.TCNT1_8 8 -TCCR1B 0x002E Timer/Counter 1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input Capture Edge Select -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter 1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 -TCCR1A.FOC1A 3 Force Output Compare for channel A -TCCR1A.FOC1B 2 Force Output Compare for channel B -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -SFIOR 0x0030 Special Function IO Register -SFIOR.XMBK 6 External Memory Bus Keeper Enable -SFIOR.XMM2 5 External Memory High Mask 2 -SFIOR.XMM1 4 External Memory High Mask 1 -SFIOR.XMM0 3 External Memory High Mask 0 -SFIOR.PUD 2 Pull-up Disable -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OCR0 0x0031 Output Compare Register -OCR0.OCR0_7 7 -OCR0.OCR0_6 6 -OCR0.OCR0_5 5 -OCR0.OCR0_4 4 -OCR0.OCR0_3 3 -OCR0.OCR0_2 2 -OCR0.OCR0_1 1 -OCR0.OCR0_0 0 -TCNT0 0x0032 Timer/Counter Register -TCNT0.TCNT0_7 7 -TCNT0.TCNT0_6 6 -TCNT0.TCNT0_5 5 -TCNT0.TCNT0_4 4 -TCNT0.TCNT0_3 3 -TCNT0.TCNT0_2 2 -TCNT0.TCNT0_1 1 -TCNT0.TCNT0_0 0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.SM2 5 Sleep Mode Select Bit 2 -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SRE 7 External SRAM/XMEM Enable -MCUCR.SRW10 6 Wait State Select Bit -MCUCR.SE 5 SleepEnable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -EMCUCR 0x0036 Extended MCU Control Register -EMCUCR.SM0 7 Sleep Mode Select Bit 0 -EMCUCR.SRL2 6 Wait State Sector Limit 2 -EMCUCR.SRL1 5 Wait State Sector Limit 1 -EMCUCR.SRL0 4 Wait State Sector Limit 0 -EMCUCR.SRW01 3 Wait State Select Bits for Lower Sector 1 -EMCUCR.SRW00 2 Wait State Select Bits for Lower Sector 0 -EMCUCR.SRW11 1 Wait State Select Bits for Upper 1 -EMCUCR.ISC2 0 Interrupt Sense Control 2 -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.SPMIE 7 SPM Interrupt Enable -SPMCR.RWWSB 6 Read-While-Write Section Busy -SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -SPMCR.BLBSET 3 Boot Lock BitSet -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter1, Overflow Flag -TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag -TIFR.ICF1 3 Timer/Counter1, Input Capture Flag -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIFR.OCF0 0 OutputCompare Flag0 -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIFR.INTF2 5 External Interrupt Flag 2 -GICR 0x003B General Interrupt Control Register -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.INT2 5 External Interrupt Request 2 Enable -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP15 15 -SPH.SP14 14 -SPH.SP13 13 -SPH.SP12 12 -SPH.SP11 11 -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; OSCCAL 0x0024 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; PINE 0x0025 Port E Input Pins Address -; PINE.PINE2 2 -; PINE.PINE1 1 -; PINE.PINE0 0 -; DDRE 0x0026 Port E Data Direction Register -; DDRE.DDE2 2 Port E Data Direction Register bit 2 -; DDRE.DDE1 1 Port E Data Direction Register bit 1 -; DDRE.DDE0 0 Port E Data Direction Register bit 0 -; PORTE 0x0027 Port E Data Register -; PORTE.PORTE2 2 Port E Data Register bit 2 -; PORTE.PORTE1 1 Port E Data Register bit 1 -; PORTE.PORTE0 0 Port E Data Register bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRRL 0x0029 USART Baud Rate Register Low -; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -; UCSRB 0x002A USART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.UCSZ2 2 Character Size -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit8 -; UCSRA 0x002B USART Control and Status Register A -; UCSRA.RXC 7 USART Receive Complete -; UCSRA.TXC 6 USART Transmit Complete -; UCSRA.UDRE 5 USART Data Register Empty -; UCSRA.FE 4 Frame Error -; UCSRA.DOR 3 Data OverRun -; UCSRA.PE 2 ParityError -; UCSRA.U2X 1 Double the USART Transmission Speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision Flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEDR.EEDR7 7 EEPROM Data 7 -; EEDR.EEDR6 6 EEPROM Data 6 -; EEDR.EEDR5 5 EEPROM Data 5 -; EEDR.EEDR4 4 EEPROM Data 4 -; EEDR.EEDR3 3 EEPROM Data 3 -; EEDR.EEDR2 2 EEPROM Data 2 -; EEDR.EEDR1 1 EEPROM Data 1 -; EEDR.EEDR0 0 EEPROM Data 0 -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR9 9 EEPROM Addres 9 -; UCSRC 0x0040 USART Control and Status Register C -; UCSRC.URSEL 7 Register Select -; UCSRC.UMSEL 6 USART Mode Select -; UCSRC.UPM1 5 Parity Mode 1 -; UCSRC.UPM0 4 Parity Mode 0 -; UCSRC.USBS 3 Stop Bit Select -; UCSRC.UCSZ1 2 Character Size 1 -; UCSRC.UCSZ0 1 Character Size 0 -; UCSRC.UCPOL 0 Clock Polarity -; ; UBRRH 0x0040 USART Baud Rate Register High -; ; UBRRH.URSEL 15 Register Select -; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; ICR1L 0x0044 Input Capture Register 1 Low -; ICR1L.ICR1_7 7 -; ICR1L.ICR1_6 6 -; ICR1L.ICR1_5 5 -; ICR1L.ICR1_4 4 -; ICR1L.ICR1_3 3 -; ICR1L.ICR1_2 2 -; ICR1L.ICR1_1 1 -; ICR1L.ICR1_0 0 -; ICR1H 0x0045 Input Capture Register 1 High -; ICR1H.ICR1_15 15 -; ICR1H.ICR1_14 14 -; ICR1H.ICR1_13 13 -; ICR1H.ICR1_12 12 -; ICR1H.ICR1_11 11 -; ICR1H.ICR1_10 10 -; ICR1H.ICR1_9 9 -; ICR1H.ICR1_8 8 -; RESERVED0046 0x0046 RESERVED -; RESERVED0047 0x0047 RESERVED -; OCR1BL 0x0048 Output Compare Register 1 B Low -; OCR1BL.OCR1B_7 7 -; OCR1BL.OCR1B_6 6 -; OCR1BL.OCR1B_5 5 -; OCR1BL.OCR1B_4 4 -; OCR1BL.OCR1B_3 3 -; OCR1BL.OCR1B_2 2 -; OCR1BL.OCR1B_1 1 -; OCR1BL.OCR1B_0 0 -; OCR1BH 0x0049 Output Compare Register 1 B High -; OCR1BH.OCR1B_15 15 -; OCR1BH.OCR1B_14 14 -; OCR1BH.OCR1B_13 13 -; OCR1BH.OCR1B_12 12 -; OCR1BH.OCR1B_11 11 -; OCR1BH.OCR1B_10 10 -; OCR1BH.OCR1B_9 9 -; OCR1BH.OCR1B_8 8 -; OCR1AL 0x004A Output Compare Register 1 A Low -; OCR1AL.OCR1A_7 7 -; OCR1AL.OCR1A_6 6 -; OCR1AL.OCR1A_5 5 -; OCR1AL.OCR1A_4 4 -; OCR1AL.OCR1A_3 3 -; OCR1AL.OCR1A_2 2 -; OCR1AL.OCR1A_1 1 -; OCR1AL.OCR1A_0 0 -; OCR1AH 0x004B Output Compare Register 1 A High -; OCR1AH.OCR1A_15 15 -; OCR1AH.OCR1A_14 14 -; OCR1AH.OCR1A_13 13 -; OCR1AH.OCR1A_12 12 -; OCR1AH.OCR1A_11 11 -; OCR1AH.OCR1A_10 10 -; OCR1AH.OCR1A_9 9 -; OCR1AH.OCR1A_8 8 -; TCNT1L 0x004C Timer/Counter 1 Low -; TCNT1L.TCNT1_7 7 -; TCNT1L.TCNT1_6 6 -; TCNT1L.TCNT1_5 5 -; TCNT1L.TCNT1_4 4 -; TCNT1L.TCNT1_3 3 -; TCNT1L.TCNT1_2 2 -; TCNT1L.TCNT1_1 1 -; TCNT1L.TCNT1_0 0 -; TCNT1H 0x004D Timer/Counter 1 High -; TCNT1H.TCNT1_15 15 -; TCNT1H.TCNT1_14 14 -; TCNT1H.TCNT1_13 13 -; TCNT1H.TCNT1_12 12 -; TCNT1H.TCNT1_11 11 -; TCNT1H.TCNT1_10 10 -; TCNT1H.TCNT1_9 9 -; TCNT1H.TCNT1_8 8 -; TCCR1B 0x004E Timer/Counter 1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input Capture Edge Select -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter 1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 -; TCCR1A.FOC1A 3 Force Output Compare for channel A -; TCCR1A.FOC1B 2 Force Output Compare for channel B -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; SFIOR 0x0050 Special Function IO Register -; SFIOR.XMBK 6 External Memory Bus Keeper Enable -; SFIOR.XMM2 5 External Memory High Mask 2 -; SFIOR.XMM1 4 External Memory High Mask 1 -; SFIOR.XMM0 3 External Memory High Mask 0 -; SFIOR.PUD 2 Pull-up Disable -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OCR0 0x0051 Output Compare Register -; OCR0.OCR0_7 7 -; OCR0.OCR0_6 6 -; OCR0.OCR0_5 5 -; OCR0.OCR0_4 4 -; OCR0.OCR0_3 3 -; OCR0.OCR0_2 2 -; OCR0.OCR0_1 1 -; OCR0.OCR0_0 0 -; TCNT0 0x0052 Timer/Counter Register -; TCNT0.TCNT0_7 7 -; TCNT0.TCNT0_6 6 -; TCNT0.TCNT0_5 5 -; TCNT0.TCNT0_4 4 -; TCNT0.TCNT0_3 3 -; TCNT0.TCNT0_2 2 -; TCNT0.TCNT0_1 1 -; TCNT0.TCNT0_0 0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.SM2 5 Sleep Mode Select Bit 2 -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SRE 7 External SRAM/XMEM Enable -; MCUCR.SRW10 6 Wait State Select Bit -; MCUCR.SE 5 SleepEnable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; EMCUCR 0x0056 Extended MCU Control Register -; EMCUCR.SM0 7 Sleep Mode Select Bit 0 -; EMCUCR.SRL2 6 Wait State Sector Limit 2 -; EMCUCR.SRL1 5 Wait State Sector Limit 1 -; EMCUCR.SRL0 4 Wait State Sector Limit 0 -; EMCUCR.SRW01 3 Wait State Select Bits for Lower Sector 1 -; EMCUCR.SRW00 2 Wait State Select Bits for Lower Sector 0 -; EMCUCR.SRW11 1 Wait State Select Bits for Upper 1 -; EMCUCR.ISC2 0 Interrupt Sense Control 2 -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock BitSet -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.TOV1 7 Timer/Counter1, Overflow Flag -; TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag -; TIFR.ICF1 3 Timer/Counter1, Input Capture Flag -; TIFR.TOV0 1 Timer/Counter0 Overflow Flag -; TIFR.OCF0 0 OutputCompare Flag0 -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIFR.INTF2 5 External Interrupt Flag 2 -; GICR 0x005B General Interrupt Control Register -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.INT2 5 External Interrupt Request 2 Enable -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; RESERVED005C 0x005C RESERVED -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP15 15 -; SPH.SP14 14 -; SPH.SP13 13 -; SPH.SP12 12 -; SPH.SP11 11 -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega8535_L -SUBARCH=2 -; doc2502.pdf -; - -RAM=512 -ROM=8192 -EEPROM=512 - -; MEMORY MAP -area DATA FSR 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x0260 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER2_COMP 0x0003 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0004 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0005 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0006 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0007 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0008 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0009 Timer/Counter0 Overflow -entry SPI_STC 0x000A Serial Transfer Complete -entry USART_RXC 0x000B USART, Rx Complete -entry USART_UDRE 0x000C USART Data Register Empty -entry USART_TXC 0x000D USART, Tx Complete -entry ADC_ 0x000E ADC Conversion Complete -entry EE_RDY 0x000F EEPROM Ready -entry ANA_COMP 0x0010 Analog Comparator -entry TWI_ 0x0011 Two-wire Serial Interface -entry INT2_ 0x0012 External Interrupt Request 2 -entry TIMER0_COMP 0x0013 Timer/Counter0 Compare Match -entry SPM_RDY 0x0014 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -TWBR 0x0000 TWI Bit Rate Register -TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -TWSR 0x0001 TWI Status Register -TWSR.TWS7 7 TWI Status -TWSR.TWS6 6 TWI Status -TWSR.TWS5 5 TWI Status -TWSR.TWS4 4 TWI Status -TWSR.TWS3 3 TWI Status -TWSR.TWPS1 1 TWI Prescaler Bit 1 -TWSR.TWPS0 0 TWI Prescaler Bit 0 -TWAR 0x0002 TWI (Slave) Address Register -TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -TWDR 0x0003 TWI Data Register -TWDR.TWD7 7 TWI Data Register bit 7 -TWDR.TWD6 6 TWI Data Register bit 6 -TWDR.TWD5 5 TWI Data Register bit 5 -TWDR.TWD4 4 TWI Data Register bit 4 -TWDR.TWD3 3 TWI Data Register bit 3 -TWDR.TWD2 2 TWI Data Register bit 2 -TWDR.TWD1 1 TWI Data Register bit 1 -TWDR.TWD0 0 TWI Data Register bit 0 -ADCL 0x0004 ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion Result 7 -ADCL.ADC6 6 ADC Conversion Result 6 -ADCL.ADC5 5 ADC Conversion Result 5 -ADCL.ADC4 4 ADC Conversion Result 4 -ADCL.ADC3 3 ADC Conversion Result 3 -ADCL.ADC2 2 ADC Conversion Result 2 -ADCL.ADC1 1 ADC Conversion Result 1 -ADCL.ADC0 0 ADC Conversion Result 0 -ADCH 0x0005 ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 ADC Conversion Result 9 -ADCH.ADC8 8 ADC Conversion Result 8 -; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion Result 1 -; ADCL.ADC0 6 ADC Conversion Result 0 -; ADCH 0x0005 ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion Result 9 -; ADCH.ADC8 14 ADC Conversion Result 8 -; ADCH.ADC7 13 ADC Conversion Result 7 -; ADCH.ADC6 12 ADC Conversion Result 6 -; ADCH.ADC5 11 ADC Conversion Result 5 -; ADCH.ADC4 10 ADC Conversion Result 4 -; ADCH.ADC3 9 ADC Conversion Result 3 -; ADCH.ADC2 8 ADC Conversion Result 2 -ADCSRA 0x0006 ADC Control and Status Register A -ADCSRA.ADEN 7 ADC Enable -ADCSRA.ADSC 6 ADC Start Conversion -ADCSRA.ADATE 5 ADC Auto Trigger Enable -ADCSRA.ADIF 4 ADC Interrupt Flag -ADCSRA.ADIE 3 ADC Interrupt Enable -ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register Low -UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -UCSRB 0x000A USART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B USART Control and Status Register A -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.PE 2 Parity Error -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC7 7 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC7 7 Port C Data Direction Register bit 7 -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC7 7 Port C Data Register bit 7 -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR8 8 EEPROM Addres 8 -UCSRC 0x0020 USART Control and Status Register (page 159) -UCSRC.URSEL 7 Register Select -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -; UBRRH 0x0020 USART Baud Rate Register High (page 159) -; UBRRH.URSEL 15 Register Select -; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register 2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register 2 Update Busy -OCR2 0x0023 Output Compare Register -OCR2.OCR2_7 7 -OCR2.OCR2_6 6 -OCR2.OCR2_5 5 -OCR2.OCR2_4 4 -OCR2.OCR2_3 3 -OCR2.OCR2_2 2 -OCR2.OCR2_1 1 -OCR2.OCR2_0 0 -TCNT2 0x0024 Timer/Counter Register -TCNT2.TCNT2_7 7 -TCNT2.TCNT2_6 6 -TCNT2.TCNT2_5 5 -TCNT2.TCNT2_4 4 -TCNT2.TCNT2_3 3 -TCNT2.TCNT2_2 2 -TCNT2.TCNT2_1 1 -TCNT2.TCNT2_0 0 -TCCR2 0x0025 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Compare Match Output Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Waveform Generation Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -ICR1L 0x0026 Input Capture Register 1 Low -ICR1L.ICR1_7 7 -ICR1L.ICR1_6 6 -ICR1L.ICR1_5 5 -ICR1L.ICR1_4 4 -ICR1L.ICR1_3 3 -ICR1L.ICR1_2 2 -ICR1L.ICR1_1 1 -ICR1L.ICR1_0 0 -ICR1H 0x0027 Input Capture Register 1 High -ICR1H.ICR1_15 15 -ICR1H.ICR1_14 14 -ICR1H.ICR1_13 13 -ICR1H.ICR1_12 12 -ICR1H.ICR1_11 11 -ICR1H.ICR1_10 10 -ICR1H.ICR1_9 9 -ICR1H.ICR1_8 8 -OCR1BL 0x0028 Output Compare Register 1 B Low -OCR1BL.OCR1B_7 7 -OCR1BL.OCR1B_6 6 -OCR1BL.OCR1B_5 5 -OCR1BL.OCR1B_4 4 -OCR1BL.OCR1B_3 3 -OCR1BL.OCR1B_2 2 -OCR1BL.OCR1B_1 1 -OCR1BL.OCR1B_0 0 -OCR1BH 0x0029 Output Compare Register 1 B High -OCR1BH.OCR1B_15 15 -OCR1BH.OCR1B_14 14 -OCR1BH.OCR1B_13 13 -OCR1BH.OCR1B_12 12 -OCR1BH.OCR1B_11 11 -OCR1BH.OCR1B_10 10 -OCR1BH.OCR1B_9 9 -OCR1BH.OCR1B_8 8 -OCR1AL 0x002A Output Compare Register 1 A Low -OCR1AL.OCR1A_7 7 -OCR1AL.OCR1A_6 6 -OCR1AL.OCR1A_5 5 -OCR1AL.OCR1A_4 4 -OCR1AL.OCR1A_3 3 -OCR1AL.OCR1A_2 2 -OCR1AL.OCR1A_1 1 -OCR1AL.OCR1A_0 0 -OCR1AH 0x002B Output Compare Register 1 A High -OCR1AH.OCR1A_15 15 -OCR1AH.OCR1A_14 14 -OCR1AH.OCR1A_13 13 -OCR1AH.OCR1A_12 12 -OCR1AH.OCR1A_11 11 -OCR1AH.OCR1A_10 10 -OCR1AH.OCR1A_9 9 -OCR1AH.OCR1A_8 8 -TCNT1L 0x002C Timer/Counter 1 Low -TCNT1L.TCNT1_7 7 -TCNT1L.TCNT1_6 6 -TCNT1L.TCNT1_5 5 -TCNT1L.TCNT1_4 4 -TCNT1L.TCNT1_3 3 -TCNT1L.TCNT1_2 2 -TCNT1L.TCNT1_1 1 -TCNT1L.TCNT1_0 0 -TCNT1H 0x002D Timer/Counter 1 High -TCNT1H.TCNT1_15 15 -TCNT1H.TCNT1_14 14 -TCNT1H.TCNT1_13 13 -TCNT1H.TCNT1_12 12 -TCNT1H.TCNT1_11 11 -TCNT1H.TCNT1_10 10 -TCNT1H.TCNT1_9 9 -TCNT1H.TCNT1_8 8 -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input Capture Edge Select -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.FOC1A 3 Force Output Compare for Channel A -TCCR1A.FOC1B 2 Force Output Compare for Channel B -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -SFIOR 0x0030 Special Function IO Register -SFIOR.ADTS2 7 ADC Auto Trigger Source 2 -SFIOR.ADTS1 6 ADC Auto Trigger Source 1 -SFIOR.ADTS0 5 ADC Auto Trigger Source 0 -SFIOR.ADHSM 4 ADC High Speed Mode -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter Register -TCNT0.TCNT0_7 7 -TCNT0.TCNT0_6 6 -TCNT0.TCNT0_5 5 -TCNT0.TCNT0_4 4 -TCNT0.TCNT0_3 3 -TCNT0.TCNT0_2 2 -TCNT0.TCNT0_1 1 -TCNT0.TCNT0_0 0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.FOC0 7 Force Output Compare -TCCR0.WGM00 6 Waveform Generation Mode 0 -TCCR0.COM01 5 Compare Match Output Mode 1 -TCCR0.COM00 4 Compare Match Output Mode 0 -TCCR0.WGM01 3 Waveform Generation Mode 1 -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.ISC2 6 Interrupt Sense Control 2 -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SM2 7 Sleep Mode Select Bit 2 -MCUCR.SE 6 Sleep Enable -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -TWCR 0x0036 TWI Control Register -TWCR.TWINT 7 TWI Interrupt Flag -TWCR.TWEA 6 TWI Enable Acknowledge Bit -TWCR.TWSTA 5 TWI START Condition Bit -TWCR.TWSTO 4 TWI STOP Condition Bit -TWCR.TWWC 3 TWI Write Collision Flag -TWCR.TWEN 2 TWI Enable Bit -TWCR.TWIE 0 TWI Interrupt Enable -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.SPMIE 7 SPM Interrupt Enable -SPMCR.RWWSB 6 Read-While-Write Section Busy -SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -TIFR.TOV1 2 Timer/Counter1, Overflow Flag -TIFR.OCF0 1 Output Compare Flag 0 -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GIFR.INTF2 5 External Interrupt Flag 2 -GICR 0x003B General Interrupt Control Register -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.INT2 5 External Interrupt Request 2 Enable -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -OCR0 0x003C Output Compare Register -OCR0.OCR0_7 7 -OCR0.OCR0_6 6 -OCR0.OCR0_5 5 -OCR0.OCR0_4 4 -OCR0.OCR0_3 3 -OCR0.OCR0_2 2 -OCR0.OCR0_1 1 -OCR0.OCR0_0 0 -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; TWBR 0x0020 TWI Bit Rate Register -; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -; TWSR 0x0021 TWI Status Register -; TWSR.TWS7 7 TWI Status -; TWSR.TWS6 6 TWI Status -; TWSR.TWS5 5 TWI Status -; TWSR.TWS4 4 TWI Status -; TWSR.TWS3 3 TWI Status -; TWSR.TWPS1 1 TWI Prescaler Bit 1 -; TWSR.TWPS0 0 TWI Prescaler Bit 0 -; TWAR 0x0022 TWI (Slave) Address Register -; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -; TWDR 0x0023 TWI Data Register -; TWDR.TWD7 7 TWI Data Register bit 7 -; TWDR.TWD6 6 TWI Data Register bit 6 -; TWDR.TWD5 5 TWI Data Register bit 5 -; TWDR.TWD4 4 TWI Data Register bit 4 -; TWDR.TWD3 3 TWI Data Register bit 3 -; TWDR.TWD2 2 TWI Data Register bit 2 -; TWDR.TWD1 1 TWI Data Register bit 1 -; TWDR.TWD0 0 TWI Data Register bit 0 -; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion Result 7 -; ADCL.ADC6 6 ADC Conversion Result 6 -; ADCL.ADC5 5 ADC Conversion Result 5 -; ADCL.ADC4 4 ADC Conversion Result 4 -; ADCL.ADC3 3 ADC Conversion Result 3 -; ADCL.ADC2 2 ADC Conversion Result 2 -; ADCL.ADC1 1 ADC Conversion Result 1 -; ADCL.ADC0 0 ADC Conversion Result 0 -; ADCH 0x0025 ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 ADC Conversion Result 9 -; ADCH.ADC8 8 ADC Conversion Result 8 -; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion Result 1 -; ; ADCL.ADC0 6 ADC Conversion Result 0 -; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion Result 9 -; ; ADCH.ADC8 14 ADC Conversion Result 8 -; ; ADCH.ADC7 13 ADC Conversion Result 7 -; ; ADCH.ADC6 12 ADC Conversion Result 6 -; ; ADCH.ADC5 11 ADC Conversion Result 5 -; ; ADCH.ADC4 10 ADC Conversion Result 4 -; ; ADCH.ADC3 9 ADC Conversion Result 3 -; ; ADCH.ADC2 8 ADC Conversion Result 2 -; ADCSRA 0x0026 ADC Control and Status Register A -; ADCSRA.ADEN 7 ADC Enable -; ADCSRA.ADSC 6 ADC Start Conversion -; ADCSRA.ADATE 5 ADC Auto Trigger Enable -; ADCSRA.ADIF 4 ADC Interrupt Flag -; ADCSRA.ADIE 3 ADC Interrupt Enable -; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRRL 0x0029 USART Baud Rate Register Low -; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -; UCSRB 0x002A USART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.UCSZ2 2 Character Size -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B USART Control and Status Register A -; UCSRA.RXC 7 USART Receive Complete -; UCSRA.TXC 6 USART Transmit Complete -; UCSRA.UDRE 5 USART Data Register Empty -; UCSRA.FE 4 Frame Error -; UCSRA.DOR 3 Data OverRun -; UCSRA.PE 2 Parity Error -; UCSRA.U2X 1 Double the USART Transmission Speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC7 7 -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC7 7 Port C Data Direction Register bit 7 -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC7 7 Port C Data Register bit 7 -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEDR.EEDR7 7 EEPROM Data 7 -; EEDR.EEDR6 6 EEPROM Data 6 -; EEDR.EEDR5 5 EEPROM Data 5 -; EEDR.EEDR4 4 EEPROM Data 4 -; EEDR.EEDR3 3 EEPROM Data 3 -; EEDR.EEDR2 2 EEPROM Data 2 -; EEDR.EEDR1 1 EEPROM Data 1 -; EEDR.EEDR0 0 EEPROM Data 0 -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR8 8 EEPROM Addres 8 -; UCSRC 0x0040 USART Control and Status Register (page 159) -; UCSRC.URSEL 7 Register Select -; UCSRC.UMSEL 6 USART Mode Select -; UCSRC.UPM1 5 Parity Mode 1 -; UCSRC.UPM0 4 Parity Mode 0 -; UCSRC.USBS 3 Stop Bit Select -; UCSRC.UCSZ1 2 Character Size 1 -; UCSRC.UCSZ0 1 Character Size 0 -; UCSRC.UCPOL 0 Clock Polarity -; ; UBRRH 0x0040 USART Baud Rate Register High (page 159) -; ; UBRRH.URSEL 15 Register Select -; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register 2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register 2 Update Busy -; OCR2 0x0043 Output Compare Register -; OCR2.OCR2_7 7 -; OCR2.OCR2_6 6 -; OCR2.OCR2_5 5 -; OCR2.OCR2_4 4 -; OCR2.OCR2_3 3 -; OCR2.OCR2_2 2 -; OCR2.OCR2_1 1 -; OCR2.OCR2_0 0 -; TCNT2 0x0044 Timer/Counter Register -; TCNT2.TCNT2_7 7 -; TCNT2.TCNT2_6 6 -; TCNT2.TCNT2_5 5 -; TCNT2.TCNT2_4 4 -; TCNT2.TCNT2_3 3 -; TCNT2.TCNT2_2 2 -; TCNT2.TCNT2_1 1 -; TCNT2.TCNT2_0 0 -; TCCR2 0x0045 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Compare Match Output Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Waveform Generation Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; ICR1L 0x0046 Input Capture Register 1 Low -; ICR1L.ICR1_7 7 -; ICR1L.ICR1_6 6 -; ICR1L.ICR1_5 5 -; ICR1L.ICR1_4 4 -; ICR1L.ICR1_3 3 -; ICR1L.ICR1_2 2 -; ICR1L.ICR1_1 1 -; ICR1L.ICR1_0 0 -; ICR1H 0x0047 Input Capture Register 1 High -; ICR1H.ICR1_15 15 -; ICR1H.ICR1_14 14 -; ICR1H.ICR1_13 13 -; ICR1H.ICR1_12 12 -; ICR1H.ICR1_11 11 -; ICR1H.ICR1_10 10 -; ICR1H.ICR1_9 9 -; ICR1H.ICR1_8 8 -; OCR1BL 0x0048 Output Compare Register 1 B Low -; OCR1BL.OCR1B_7 7 -; OCR1BL.OCR1B_6 6 -; OCR1BL.OCR1B_5 5 -; OCR1BL.OCR1B_4 4 -; OCR1BL.OCR1B_3 3 -; OCR1BL.OCR1B_2 2 -; OCR1BL.OCR1B_1 1 -; OCR1BL.OCR1B_0 0 -; OCR1BH 0x0049 Output Compare Register 1 B High -; OCR1BH.OCR1B_15 15 -; OCR1BH.OCR1B_14 14 -; OCR1BH.OCR1B_13 13 -; OCR1BH.OCR1B_12 12 -; OCR1BH.OCR1B_11 11 -; OCR1BH.OCR1B_10 10 -; OCR1BH.OCR1B_9 9 -; OCR1BH.OCR1B_8 8 -; OCR1AL 0x004A Output Compare Register 1 A Low -; OCR1AL.OCR1A_7 7 -; OCR1AL.OCR1A_6 6 -; OCR1AL.OCR1A_5 5 -; OCR1AL.OCR1A_4 4 -; OCR1AL.OCR1A_3 3 -; OCR1AL.OCR1A_2 2 -; OCR1AL.OCR1A_1 1 -; OCR1AL.OCR1A_0 0 -; OCR1AH 0x004B Output Compare Register 1 A High -; OCR1AH.OCR1A_15 15 -; OCR1AH.OCR1A_14 14 -; OCR1AH.OCR1A_13 13 -; OCR1AH.OCR1A_12 12 -; OCR1AH.OCR1A_11 11 -; OCR1AH.OCR1A_10 10 -; OCR1AH.OCR1A_9 9 -; OCR1AH.OCR1A_8 8 -; TCNT1L 0x004C Timer/Counter 1 Low -; TCNT1L.TCNT1_7 7 -; TCNT1L.TCNT1_6 6 -; TCNT1L.TCNT1_5 5 -; TCNT1L.TCNT1_4 4 -; TCNT1L.TCNT1_3 3 -; TCNT1L.TCNT1_2 2 -; TCNT1L.TCNT1_1 1 -; TCNT1L.TCNT1_0 0 -; TCNT1H 0x004D Timer/Counter 1 High -; TCNT1H.TCNT1_15 15 -; TCNT1H.TCNT1_14 14 -; TCNT1H.TCNT1_13 13 -; TCNT1H.TCNT1_12 12 -; TCNT1H.TCNT1_11 11 -; TCNT1H.TCNT1_10 10 -; TCNT1H.TCNT1_9 9 -; TCNT1H.TCNT1_8 8 -; TCCR1B 0x004E Timer/Counter1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input Capture Edge Select -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -; TCCR1A.FOC1A 3 Force Output Compare for Channel A -; TCCR1A.FOC1B 2 Force Output Compare for Channel B -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; SFIOR 0x0050 Special Function IO Register -; SFIOR.ADTS2 7 ADC Auto Trigger Source 2 -; SFIOR.ADTS1 6 ADC Auto Trigger Source 1 -; SFIOR.ADTS0 5 ADC Auto Trigger Source 0 -; SFIOR.ADHSM 4 ADC High Speed Mode -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OSCCAL 0x0051 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter Register -; TCNT0.TCNT0_7 7 -; TCNT0.TCNT0_6 6 -; TCNT0.TCNT0_5 5 -; TCNT0.TCNT0_4 4 -; TCNT0.TCNT0_3 3 -; TCNT0.TCNT0_2 2 -; TCNT0.TCNT0_1 1 -; TCNT0.TCNT0_0 0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.FOC0 7 Force Output Compare -; TCCR0.WGM00 6 Waveform Generation Mode 0 -; TCCR0.COM01 5 Compare Match Output Mode 1 -; TCCR0.COM00 4 Compare Match Output Mode 0 -; TCCR0.WGM01 3 Waveform Generation Mode 1 -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.ISC2 6 Interrupt Sense Control 2 -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SM2 7 Sleep Mode Select Bit 2 -; MCUCR.SE 6 Sleep Enable -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; TWCR 0x0056 TWI Control Register -; TWCR.TWINT 7 TWI Interrupt Flag -; TWCR.TWEA 6 TWI Enable Acknowledge Bit -; TWCR.TWSTA 5 TWI START Condition Bit -; TWCR.TWSTO 4 TWI STOP Condition Bit -; TWCR.TWWC 3 TWI Write Collision Flag -; TWCR.TWEN 2 TWI Enable Bit -; TWCR.TWIE 0 TWI Interrupt Enable -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -; TIFR.TOV1 2 Timer/Counter1, Overflow Flag -; TIFR.OCF0 1 Output Compare Flag 0 -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GIFR.INTF2 5 External Interrupt Flag 2 -; GICR 0x005B General Interrupt Control Register -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.INT2 5 External Interrupt Request 2 Enable -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; OCR0 0x005C Output Compare Register -; OCR0.OCR0_7 7 -; OCR0.OCR0_6 6 -; OCR0.OCR0_5 5 -; OCR0.OCR0_4 4 -; OCR0.OCR0_3 3 -; OCR0.OCR0_2 2 -; OCR0.OCR0_1 1 -; OCR0.OCR0_0 0 -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATmega8_L -SUBARCH=4 -; doc2486.pdf -; - -RAM=1024 -ROM=8192 -EEPROM=512 - -; MEMORY MAP -area DATA FSR 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x0460 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER2_COMP 0x0003 Timer/Counter2 Compare Match -entry TIMER2_OVF 0x0004 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0005 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0006 Timer/Counter1 Compare Match A -entry TIMER1_COMPB 0x0007 Timer/Counter1 Compare Match B -entry TIMER1_OVF 0x0008 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0009 Timer/Counter0 Overflow -entry SPI_STC 0x000A Serial Transfer Complete -entry USART_RXC 0x000B USART, Rx Complete -entry USART_UDRE 0x000C USART Data Register Empty -entry USART_TXC 0x000D USART, Tx Complete -entry ADC_ 0x000E ADC Conversion Complete -entry EE_RDY 0x000F EEPROM Ready -entry ANA_COMP 0x0010 Analog Comparator -entry TWI_ 0x0011 Two-wire Serial Interface -entry SPM_RDY 0x0012 Store Program Memory Ready - - -; INPUT/OUTPUT PORTS -TWBR 0x0000 Two-wire Serial Interface Bit Rate Register -TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -TWSR 0x0001 TWI Status Register -TWSR.TWS7 7 TWI Status 7 -TWSR.TWS6 6 TWI Status 6 -TWSR.TWS5 5 TWI Status 5 -TWSR.TWS4 4 TWI Status 4 -TWSR.TWS3 3 TWI Status 3 -TWSR.TWS1 1 TWI Status 1 -TWSR.TWS0 0 TWI Status 0 -TWAR 0x0002 TWI (Slave) Address Register -TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -TWDR 0x0003 TWI Data Register -TWDR.TWD7 7 TWI Data Register bit 7 -TWDR.TWD6 6 TWI Data Register bit 6 -TWDR.TWD5 5 TWI Data Register bit 5 -TWDR.TWD4 4 TWI Data Register bit 4 -TWDR.TWD3 3 TWI Data Register bit 3 -TWDR.TWD2 2 TWI Data Register bit 2 -TWDR.TWD1 1 TWI Data Register bit 1 -TWDR.TWD0 0 TWI Data Register bit 0 -ADCL 0x0004 ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion Result 7 -ADCL.ADC6 6 ADC Conversion Result 6 -ADCL.ADC5 5 ADC Conversion Result 5 -ADCL.ADC4 4 ADC Conversion Result 4 -ADCL.ADC3 3 ADC Conversion Result 3 -ADCL.ADC2 2 ADC Conversion Result 2 -ADCL.ADC1 1 ADC Conversion Result 1 -ADCL.ADC0 0 ADC Conversion Result 0 -ADCH 0x0005 ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 ADC Conversion Result 9 -ADCH.ADC8 8 ADC Conversion Result 8 -; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion Result 1 -; ADCL.ADC0 6 ADC Conversion Result 0 -; ADCH 0x0005 ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion Result 9 -; ADCH.ADC8 14 ADC Conversion Result 8 -; ADCH.ADC7 13 ADC Conversion Result 7 -; ADCH.ADC6 12 ADC Conversion Result 6 -; ADCH.ADC5 11 ADC Conversion Result 5 -; ADCH.ADC4 10 ADC Conversion Result 4 -; ADCH.ADC3 9 ADC Conversion Result 3 -; ADCH.ADC2 8 ADC Conversion Result 2 -ADCSRA 0x0006 ADC Control and Status Register A -ADCSRA.ADEN 7 ADC Enable -ADCSRA.ADSC 6 ADC Start Conversion -ADCSRA.ADFR 5 ADC Free Running Select -ADCSRA.ADIF 4 ADC Interrupt Flag -ADCSRA.ADIE 3 ADC Interrupt Enable -ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX3 3 Analog Channel Selection Bit 3 -ADMUX.MUX2 2 Analog Channel Selection Bit 2 -ADMUX.MUX1 1 Analog Channel Selection Bit 1 -ADMUX.MUX0 0 Analog Channel Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register Low -UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -UCSRB 0x000A USART Control and Status Register B -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit 8 -UCSRA 0x000B USART Control and Status Register A -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.PE 2 Parity Error -UCSRA.U2X 1 Double the USART transmission speed -UCSRA.MPCM 0 Multi-processor Communication Mode -UDR 0x000C USART I/O Data Register -SPCR 0x000D SPI Control Register -SPCR.SPIE 7 SPI Interrupt Enable -SPCR.SPE 6 SPI Enable -SPCR.DORD 5 Data Order -SPCR.MSTR 4 Master/Slave Select -SPCR.CPOL 3 Clock Polarity -SPCR.CPHA 2 Clock Phase -SPCR.SPR1 1 SPI Clock Rate Select 1 -SPCR.SPR0 0 SPI Clock Rate Select 0 -SPSR 0x000E SPI Status Register -SPSR.SPIF 7 SPI Interrupt Flag -SPSR.WCOL 6 Write COLlision flag -SPSR.SPI2X 0 Double SPI Speed Bit -SPDR 0x000F SPI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -PINC 0x0013 Port C Input Pins Address -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -DDRC 0x0014 Port C Data Direction Register -DDRC.DDC6 6 Port C Data Direction Register bit 6 -DDRC.DDC5 5 Port C Data Direction Register bit 5 -DDRC.DDC4 4 Port C Data Direction Register bit 4 -DDRC.DDC3 3 Port C Data Direction Register bit 3 -DDRC.DDC2 2 Port C Data Direction Register bit 2 -DDRC.DDC1 1 Port C Data Direction Register bit 1 -DDRC.DDC0 0 Port C Data Direction Register bit 0 -PORTC 0x0015 Port C Data Register -PORTC.PORTC6 6 Port C Data Register bit 6 -PORTC.PORTC5 5 Port C Data Register bit 5 -PORTC.PORTC4 4 Port C Data Register bit 4 -PORTC.PORTC3 3 Port C Data Register bit 3 -PORTC.PORTC2 2 Port C Data Register bit 2 -PORTC.PORTC1 1 Port C Data Register bit 1 -PORTC.PORTC0 0 Port C Data Register bit 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEARL 0x001E EEPROM Address Register Low -EEARL.EEAR7 7 EEPROM Addres 7 -EEARL.EEAR6 6 EEPROM Addres 6 -EEARL.EEAR5 5 EEPROM Addres 5 -EEARL.EEAR4 4 EEPROM Addres 4 -EEARL.EEAR3 3 EEPROM Addres 3 -EEARL.EEAR2 2 EEPROM Addres 2 -EEARL.EEAR1 1 EEPROM Addres 1 -EEARL.EEAR0 0 EEPROM Addres 0 -EEARH 0x001F EEPROM Address Register High -EEARH.EEAR8 8 EEPROM Addres 8 -UCSRC 0x0020 USART Control and Status Register (page 148) -UCSRC.URSEL 7 Register Select -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -; UBRRH 0x0020 USART Baud Rate Register High (page 148) -; UBRRH.URSEL 15 Register Select -; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -ASSR 0x0022 Asynchronous Status Register -ASSR.AS2 3 Asynchronous Timer/Counter2 -ASSR.TCN2UB 2 Timer/Counter2 Update Busy -ASSR.OCR2UB 1 Output Compare Register2 Update Busy -ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -OCR2 0x0023 Output Compare Register -OCR2.OCR2_7 7 -OCR2.OCR2_6 6 -OCR2.OCR2_5 5 -OCR2.OCR2_4 4 -OCR2.OCR2_3 3 -OCR2.OCR2_2 2 -OCR2.OCR2_1 1 -OCR2.OCR2_0 0 -TCNT2 0x0024 Timer/Counter Register -TCNT2.TCNT2_7 7 -TCNT2.TCNT2_6 6 -TCNT2.TCNT2_5 5 -TCNT2.TCNT2_4 4 -TCNT2.TCNT2_3 3 -TCNT2.TCNT2_2 2 -TCNT2.TCNT2_1 1 -TCNT2.TCNT2_0 0 -TCCR2 0x0025 Timer/Counter Control Register -TCCR2.FOC2 7 Force Output Compare -TCCR2.WGM20 6 Waveform Generation Mode 0 -TCCR2.COM21 5 Compare Match Output Mode 1 -TCCR2.COM20 4 Compare Match Output Mode 0 -TCCR2.WGM21 3 Waveform Generation Mode 1 -TCCR2.CS22 2 Clock Select 2 -TCCR2.CS21 1 Clock Select 1 -TCCR2.CS20 0 Clock Select 0 -ICR1L 0x0026 Input Capture Register 1 Low -ICR1L.ICR1_7 7 -ICR1L.ICR1_6 6 -ICR1L.ICR1_5 5 -ICR1L.ICR1_4 4 -ICR1L.ICR1_3 3 -ICR1L.ICR1_2 2 -ICR1L.ICR1_1 1 -ICR1L.ICR1_0 0 -ICR1H 0x0027 Input Capture Register 1 High -ICR1H.ICR1_15 15 -ICR1H.ICR1_14 14 -ICR1H.ICR1_13 13 -ICR1H.ICR1_12 12 -ICR1H.ICR1_11 11 -ICR1H.ICR1_10 10 -ICR1H.ICR1_9 9 -ICR1H.ICR1_8 8 -OCR1BL 0x0028 Output Compare Register 1 B Low -OCR1BL.OCR1B_7 7 -OCR1BL.OCR1B_6 6 -OCR1BL.OCR1B_5 5 -OCR1BL.OCR1B_4 4 -OCR1BL.OCR1B_3 3 -OCR1BL.OCR1B_2 2 -OCR1BL.OCR1B_1 1 -OCR1BL.OCR1B_0 0 -OCR1BH 0x0029 Output Compare Register 1 B High -OCR1BH.OCR1B_15 15 -OCR1BH.OCR1B_14 14 -OCR1BH.OCR1B_13 13 -OCR1BH.OCR1B_12 12 -OCR1BH.OCR1B_11 11 -OCR1BH.OCR1B_10 10 -OCR1BH.OCR1B_9 9 -OCR1BH.OCR1B_8 8 -OCR1AL 0x002A Output Compare Register 1 A Low -OCR1AL.OCR1A_7 7 -OCR1AL.OCR1A_6 6 -OCR1AL.OCR1A_5 5 -OCR1AL.OCR1A_4 4 -OCR1AL.OCR1A_3 3 -OCR1AL.OCR1A_2 2 -OCR1AL.OCR1A_1 1 -OCR1AL.OCR1A_0 0 -OCR1AH 0x002B Output Compare Register 1 A High -OCR1AH.OCR1A_15 15 -OCR1AH.OCR1A_14 14 -OCR1AH.OCR1A_13 13 -OCR1AH.OCR1A_12 12 -OCR1AH.OCR1A_11 11 -OCR1AH.OCR1A_10 10 -OCR1AH.OCR1A_9 9 -OCR1AH.OCR1A_8 8 -TCNT1L 0x002C Timer/Counter 1 Low -TCNT1L.TCNT1_7 7 -TCNT1L.TCNT1_6 6 -TCNT1L.TCNT1_5 5 -TCNT1L.TCNT1_4 4 -TCNT1L.TCNT1_3 3 -TCNT1L.TCNT1_2 2 -TCNT1L.TCNT1_1 1 -TCNT1L.TCNT1_0 0 -TCNT1H 0x002D Timer/Counter 1 High -TCNT1H.TCNT1_15 15 -TCNT1H.TCNT1_14 14 -TCNT1H.TCNT1_13 13 -TCNT1H.TCNT1_12 12 -TCNT1H.TCNT1_11 11 -TCNT1H.TCNT1_10 10 -TCNT1H.TCNT1_9 9 -TCNT1H.TCNT1_8 8 -TCCR1B 0x002E Timer/Counter 1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input Capture Edge Select -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter 1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 -TCCR1A.FOC1A 3 Force Output Compare for channel A -TCCR1A.FOC1B 2 Force Output Compare for channel B -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -SFIOR 0x0030 Special Function IO Register -SFIOR.ADHSM 4 ADC High Speed Mode -SFIOR.ACME 3 Analog Comparator Multiplexer Enable -SFIOR.PUD 2 Pull-up Disable -SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter Register -TCNT0.TCNT0_7 7 -TCNT0.TCNT0_6 6 -TCNT0.TCNT0_5 5 -TCNT0.TCNT0_4 4 -TCNT0.TCNT0_3 3 -TCNT0.TCNT0_2 2 -TCNT0.TCNT0_1 1 -TCNT0.TCNT0_0 0 -TCCR0 0x0033 Timer/Counter Control Register -TCCR0.CS02 2 Clock Select 2 -TCCR0.CS01 1 Clock Select 1 -TCCR0.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 7 Sleep Enable -MCUCR.SM2 6 Sleep Mode Select Bit 2 -MCUCR.SM1 5 Sleep Mode Select Bit 1 -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -TWCR 0x0036 TWI Control Register -TWCR.TWINT 7 TWI Interrupt Flag -TWCR.TWEA 6 TWI Enable Acknowledge Bit -TWCR.TWSTA 5 TWI START Condition Bit -TWCR.TWSTO 4 TWI STOP Condition Bit -TWCR.TWWC 3 TWI Write Collision Flag -TWCR.TWEN 2 TWI Enable Bit -TWCR.TWIE 0 TWI Interrupt Enable -SPMCR 0x0037 Store Program Memory Control Register -SPMCR.SPMIE 7 SPM Interrupt Enable -SPMCR.RWWSB 6 Read-While-Write Section Busy -SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -SPMCR.BLBSET 3 Boot Lock Bit Set -SPMCR.PGWRT 2 Page Write -SPMCR.PGERS 1 Page Erase -SPMCR.SPMEN 0 Store Program Memory Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF2 7 Output Compare Flag 2 -TIFR.TOV2 6 Timer/Counter2 Overflow Flag -TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -TIFR.TOV1 2 Timer/Counter1, Overflow Flag -TIFR.TOV0 0 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF1 7 External Interrupt Flag 1 -GIFR.INTF0 6 External Interrupt Flag 0 -GICR 0x003B General Interrupt Control Register -GICR.INT1 7 External Interrupt Request 1 Enable -GICR.INT0 6 External Interrupt Request 0 Enable -GICR.IVSEL 1 Interrupt Vector Select -GICR.IVCE 0 Interrupt Vector Change Enable -RESERVED003C 0x003C RESERVED -SPL 0x003D Stack Pointer Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPH 0x003E Stack Pointer High -SPH.SP10 10 -SPH.SP9 9 -SPH.SP8 8 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; TWBR 0x0020 Two-wire Serial Interface Bit Rate Register -; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 -; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 -; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 -; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 -; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 -; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 -; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 -; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 -; TWSR 0x0021 TWI Status Register -; TWSR.TWS7 7 TWI Status 7 -; TWSR.TWS6 6 TWI Status 6 -; TWSR.TWS5 5 TWI Status 5 -; TWSR.TWS4 4 TWI Status 4 -; TWSR.TWS3 3 TWI Status 3 -; TWSR.TWS1 1 TWI Status 1 -; TWSR.TWS0 0 TWI Status 0 -; TWAR 0x0022 TWI (Slave) Address Register -; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 -; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 -; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 -; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 -; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 -; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 -; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 -; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit -; TWDR 0x0023 TWI Data Register -; TWDR.TWD7 7 TWI Data Register bit 7 -; TWDR.TWD6 6 TWI Data Register bit 6 -; TWDR.TWD5 5 TWI Data Register bit 5 -; TWDR.TWD4 4 TWI Data Register bit 4 -; TWDR.TWD3 3 TWI Data Register bit 3 -; TWDR.TWD2 2 TWI Data Register bit 2 -; TWDR.TWD1 1 TWI Data Register bit 1 -; TWDR.TWD0 0 TWI Data Register bit 0 -; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion Result 7 -; ADCL.ADC6 6 ADC Conversion Result 6 -; ADCL.ADC5 5 ADC Conversion Result 5 -; ADCL.ADC4 4 ADC Conversion Result 4 -; ADCL.ADC3 3 ADC Conversion Result 3 -; ADCL.ADC2 2 ADC Conversion Result 2 -; ADCL.ADC1 1 ADC Conversion Result 1 -; ADCL.ADC0 0 ADC Conversion Result 0 -; ADCH 0x0025 ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 ADC Conversion Result 9 -; ADCH.ADC8 8 ADC Conversion Result 8 -; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion Result 1 -; ; ADCL.ADC0 6 ADC Conversion Result 0 -; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion Result 9 -; ; ADCH.ADC8 14 ADC Conversion Result 8 -; ; ADCH.ADC7 13 ADC Conversion Result 7 -; ; ADCH.ADC6 12 ADC Conversion Result 6 -; ; ADCH.ADC5 11 ADC Conversion Result 5 -; ; ADCH.ADC4 10 ADC Conversion Result 4 -; ; ADCH.ADC3 9 ADC Conversion Result 3 -; ; ADCH.ADC2 8 ADC Conversion Result 2 -; ADCSRA 0x0026 ADC Control and Status Register A -; ADCSRA.ADEN 7 ADC Enable -; ADCSRA.ADSC 6 ADC Start Conversion -; ADCSRA.ADFR 5 ADC Free Running Select -; ADCSRA.ADIF 4 ADC Interrupt Flag -; ADCSRA.ADIE 3 ADC Interrupt Enable -; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX3 3 Analog Channel Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACIC 2 Analog Comparator Input Capture Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; UBRRL 0x0029 USART Baud Rate Register Low -; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 -; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 -; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 -; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 -; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 -; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 -; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 -; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 -; UCSRB 0x002A USART Control and Status Register B -; UCSRB.RXCIE 7 RX Complete Interrupt Enable -; UCSRB.TXCIE 6 TX Complete Interrupt Enable -; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -; UCSRB.RXEN 4 Receiver Enable -; UCSRB.TXEN 3 Transmitter Enable -; UCSRB.UCSZ2 2 Character Size -; UCSRB.RXB8 1 Receive Data Bit 8 -; UCSRB.TXB8 0 Transmit Data Bit 8 -; UCSRA 0x002B USART Control and Status Register A -; UCSRA.RXC 7 USART Receive Complete -; UCSRA.TXC 6 USART Transmit Complete -; UCSRA.UDRE 5 USART Data Register Empty -; UCSRA.FE 4 Frame Error -; UCSRA.DOR 3 Data OverRun -; UCSRA.PE 2 Parity Error -; UCSRA.U2X 1 Double the USART transmission speed -; UCSRA.MPCM 0 Multi-processor Communication Mode -; UDR 0x002C USART I/O Data Register -; SPCR 0x002D SPI Control Register -; SPCR.SPIE 7 SPI Interrupt Enable -; SPCR.SPE 6 SPI Enable -; SPCR.DORD 5 Data Order -; SPCR.MSTR 4 Master/Slave Select -; SPCR.CPOL 3 Clock Polarity -; SPCR.CPHA 2 Clock Phase -; SPCR.SPR1 1 SPI Clock Rate Select 1 -; SPCR.SPR0 0 SPI Clock Rate Select 0 -; SPSR 0x002E SPI Status Register -; SPSR.SPIF 7 SPI Interrupt Flag -; SPSR.WCOL 6 Write COLlision flag -; SPSR.SPI2X 0 Double SPI Speed Bit -; SPDR 0x002F SPI Data Register -; PIND 0x0030 Port D Input Pins Address -; PIND.PIND7 7 -; PIND.PIND6 6 -; PIND.PIND5 5 -; PIND.PIND4 4 -; PIND.PIND3 3 -; PIND.PIND2 2 -; PIND.PIND1 1 -; PIND.PIND0 0 -; DDRD 0x0031 Port D Data Direction Register -; DDRD.DDD7 7 Port D Data Direction Register bit 7 -; DDRD.DDD6 6 Port D Data Direction Register bit 6 -; DDRD.DDD5 5 Port D Data Direction Register bit 5 -; DDRD.DDD4 4 Port D Data Direction Register bit 4 -; DDRD.DDD3 3 Port D Data Direction Register bit 3 -; DDRD.DDD2 2 Port D Data Direction Register bit 2 -; DDRD.DDD1 1 Port D Data Direction Register bit 1 -; DDRD.DDD0 0 Port D Data Direction Register bit 0 -; PORTD 0x0032 Port D Data Register -; PORTD.PORTD7 7 Port D Data Register bit 7 -; PORTD.PORTD6 6 Port D Data Register bit 6 -; PORTD.PORTD5 5 Port D Data Register bit 5 -; PORTD.PORTD4 4 Port D Data Register bit 4 -; PORTD.PORTD3 3 Port D Data Register bit 3 -; PORTD.PORTD2 2 Port D Data Register bit 2 -; PORTD.PORTD1 1 Port D Data Register bit 1 -; PORTD.PORTD0 0 Port D Data Register bit 0 -; PINC 0x0033 Port C Input Pins Address -; PINC.PINC6 6 -; PINC.PINC5 5 -; PINC.PINC4 4 -; PINC.PINC3 3 -; PINC.PINC2 2 -; PINC.PINC1 1 -; PINC.PINC0 0 -; DDRC 0x0034 Port C Data Direction Register -; DDRC.DDC6 6 Port C Data Direction Register bit 6 -; DDRC.DDC5 5 Port C Data Direction Register bit 5 -; DDRC.DDC4 4 Port C Data Direction Register bit 4 -; DDRC.DDC3 3 Port C Data Direction Register bit 3 -; DDRC.DDC2 2 Port C Data Direction Register bit 2 -; DDRC.DDC1 1 Port C Data Direction Register bit 1 -; DDRC.DDC0 0 Port C Data Direction Register bit 0 -; PORTC 0x0035 Port C Data Register -; PORTC.PORTC6 6 Port C Data Register bit 6 -; PORTC.PORTC5 5 Port C Data Register bit 5 -; PORTC.PORTC4 4 Port C Data Register bit 4 -; PORTC.PORTC3 3 Port C Data Register bit 3 -; PORTC.PORTC2 2 Port C Data Register bit 2 -; PORTC.PORTC1 1 Port C Data Register bit 1 -; PORTC.PORTC0 0 Port C Data Register bit 0 -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; RESERVED0039 0x0039 RESERVED -; RESERVED003A 0x003A RESERVED -; RESERVED003B 0x003B RESERVED -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEDR.EEDR7 7 EEPROM Data 7 -; EEDR.EEDR6 6 EEPROM Data 6 -; EEDR.EEDR5 5 EEPROM Data 5 -; EEDR.EEDR4 4 EEPROM Data 4 -; EEDR.EEDR3 3 EEPROM Data 3 -; EEDR.EEDR2 2 EEPROM Data 2 -; EEDR.EEDR1 1 EEPROM Data 1 -; EEDR.EEDR0 0 EEPROM Data 0 -; EEARL 0x003E EEPROM Address Register Low -; EEARL.EEAR7 7 EEPROM Addres 7 -; EEARL.EEAR6 6 EEPROM Addres 6 -; EEARL.EEAR5 5 EEPROM Addres 5 -; EEARL.EEAR4 4 EEPROM Addres 4 -; EEARL.EEAR3 3 EEPROM Addres 3 -; EEARL.EEAR2 2 EEPROM Addres 2 -; EEARL.EEAR1 1 EEPROM Addres 1 -; EEARL.EEAR0 0 EEPROM Addres 0 -; EEARH 0x003F EEPROM Address Register High -; EEARH.EEAR8 8 EEPROM Addres 8 -; UCSRC 0x0040 USART Control and Status Register (page 148) -; UCSRC.URSEL 7 Register Select -; UCSRC.UMSEL 6 USART Mode Select -; UCSRC.UPM1 5 Parity Mode 1 -; UCSRC.UPM0 4 Parity Mode 0 -; UCSRC.USBS 3 Stop Bit Select -; UCSRC.UCSZ1 2 Character Size 1 -; UCSRC.UCSZ0 1 Character Size 0 -; UCSRC.UCPOL 0 Clock Polarity -; ; UBRRH 0x0040 USART Baud Rate Register High (page 148) -; ; UBRRH.URSEL 15 Register Select -; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 -; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 -; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 -; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; ASSR 0x0042 Asynchronous Status Register -; ASSR.AS2 3 Asynchronous Timer/Counter2 -; ASSR.TCN2UB 2 Timer/Counter2 Update Busy -; ASSR.OCR2UB 1 Output Compare Register2 Update Busy -; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy -; OCR2 0x0043 Output Compare Register -; OCR2.OCR2_7 7 -; OCR2.OCR2_6 6 -; OCR2.OCR2_5 5 -; OCR2.OCR2_4 4 -; OCR2.OCR2_3 3 -; OCR2.OCR2_2 2 -; OCR2.OCR2_1 1 -; OCR2.OCR2_0 0 -; TCNT2 0x0044 Timer/Counter Register -; TCNT2.TCNT2_7 7 -; TCNT2.TCNT2_6 6 -; TCNT2.TCNT2_5 5 -; TCNT2.TCNT2_4 4 -; TCNT2.TCNT2_3 3 -; TCNT2.TCNT2_2 2 -; TCNT2.TCNT2_1 1 -; TCNT2.TCNT2_0 0 -; TCCR2 0x0045 Timer/Counter Control Register -; TCCR2.FOC2 7 Force Output Compare -; TCCR2.WGM20 6 Waveform Generation Mode 0 -; TCCR2.COM21 5 Compare Match Output Mode 1 -; TCCR2.COM20 4 Compare Match Output Mode 0 -; TCCR2.WGM21 3 Waveform Generation Mode 1 -; TCCR2.CS22 2 Clock Select 2 -; TCCR2.CS21 1 Clock Select 1 -; TCCR2.CS20 0 Clock Select 0 -; ICR1L 0x0046 Input Capture Register 1 Low -; ICR1L.ICR1_7 7 -; ICR1L.ICR1_6 6 -; ICR1L.ICR1_5 5 -; ICR1L.ICR1_4 4 -; ICR1L.ICR1_3 3 -; ICR1L.ICR1_2 2 -; ICR1L.ICR1_1 1 -; ICR1L.ICR1_0 0 -; ICR1H 0x0047 Input Capture Register 1 High -; ICR1H.ICR1_15 15 -; ICR1H.ICR1_14 14 -; ICR1H.ICR1_13 13 -; ICR1H.ICR1_12 12 -; ICR1H.ICR1_11 11 -; ICR1H.ICR1_10 10 -; ICR1H.ICR1_9 9 -; ICR1H.ICR1_8 8 -; OCR1BL 0x0048 Output Compare Register 1 B Low -; OCR1BL.OCR1B_7 7 -; OCR1BL.OCR1B_6 6 -; OCR1BL.OCR1B_5 5 -; OCR1BL.OCR1B_4 4 -; OCR1BL.OCR1B_3 3 -; OCR1BL.OCR1B_2 2 -; OCR1BL.OCR1B_1 1 -; OCR1BL.OCR1B_0 0 -; OCR1BH 0x0049 Output Compare Register 1 B High -; OCR1BH.OCR1B_15 15 -; OCR1BH.OCR1B_14 14 -; OCR1BH.OCR1B_13 13 -; OCR1BH.OCR1B_12 12 -; OCR1BH.OCR1B_11 11 -; OCR1BH.OCR1B_10 10 -; OCR1BH.OCR1B_9 9 -; OCR1BH.OCR1B_8 8 -; OCR1AL 0x004A Output Compare Register 1 A Low -; OCR1AL.OCR1A_7 7 -; OCR1AL.OCR1A_6 6 -; OCR1AL.OCR1A_5 5 -; OCR1AL.OCR1A_4 4 -; OCR1AL.OCR1A_3 3 -; OCR1AL.OCR1A_2 2 -; OCR1AL.OCR1A_1 1 -; OCR1AL.OCR1A_0 0 -; OCR1AH 0x004B Output Compare Register 1 A High -; OCR1AH.OCR1A_15 15 -; OCR1AH.OCR1A_14 14 -; OCR1AH.OCR1A_13 13 -; OCR1AH.OCR1A_12 12 -; OCR1AH.OCR1A_11 11 -; OCR1AH.OCR1A_10 10 -; OCR1AH.OCR1A_9 9 -; OCR1AH.OCR1A_8 8 -; TCNT1L 0x004C Timer/Counter 1 Low -; TCNT1L.TCNT1_7 7 -; TCNT1L.TCNT1_6 6 -; TCNT1L.TCNT1_5 5 -; TCNT1L.TCNT1_4 4 -; TCNT1L.TCNT1_3 3 -; TCNT1L.TCNT1_2 2 -; TCNT1L.TCNT1_1 1 -; TCNT1L.TCNT1_0 0 -; TCNT1H 0x004D Timer/Counter 1 High -; TCNT1H.TCNT1_15 15 -; TCNT1H.TCNT1_14 14 -; TCNT1H.TCNT1_13 13 -; TCNT1H.TCNT1_12 12 -; TCNT1H.TCNT1_11 11 -; TCNT1H.TCNT1_10 10 -; TCNT1H.TCNT1_9 9 -; TCNT1H.TCNT1_8 8 -; TCCR1B 0x004E Timer/Counter 1 Control Register B -; TCCR1B.ICNC1 7 Input Capture Noise Canceler -; TCCR1B.ICES1 6 Input Capture Edge Select -; TCCR1B.WGM13 4 Waveform Generation Mode 3 -; TCCR1B.WGM12 3 Waveform Generation Mode 2 -; TCCR1B.CS12 2 Clock Select 2 -; TCCR1B.CS11 1 Clock Select 1 -; TCCR1B.CS10 0 Clock Select 0 -; TCCR1A 0x004F Timer/Counter 1 Control Register A -; TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 -; TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 -; TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 -; TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 -; TCCR1A.FOC1A 3 Force Output Compare for channel A -; TCCR1A.FOC1B 2 Force Output Compare for channel B -; TCCR1A.WGM11 1 Waveform Generation Mode 1 -; TCCR1A.WGM10 0 Waveform Generation Mode 0 -; SFIOR 0x0050 Special Function IO Register -; SFIOR.ADHSM 4 ADC High Speed Mode -; SFIOR.ACME 3 Analog Comparator Multiplexer Enable -; SFIOR.PUD 2 Pull-up Disable -; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 -; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 -; OSCCAL 0x0051 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter Register -; TCNT0.TCNT0_7 7 -; TCNT0.TCNT0_6 6 -; TCNT0.TCNT0_5 5 -; TCNT0.TCNT0_4 4 -; TCNT0.TCNT0_3 3 -; TCNT0.TCNT0_2 2 -; TCNT0.TCNT0_1 1 -; TCNT0.TCNT0_0 0 -; TCCR0 0x0053 Timer/Counter Control Register -; TCCR0.CS02 2 Clock Select 2 -; TCCR0.CS01 1 Clock Select 1 -; TCCR0.CS00 0 Clock Select 0 -; MCUCSR 0x0054 MCU Control and Status Register -; MCUCSR.WDRF 3 Watchdog Reset Flag -; MCUCSR.BORF 2 Brown-out Reset Flag -; MCUCSR.EXTRF 1 External Reset Flag -; MCUCSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.SE 7 Sleep Enable -; MCUCR.SM2 6 Sleep Mode Select Bit 2 -; MCUCR.SM1 5 Sleep Mode Select Bit 1 -; MCUCR.SM0 4 Sleep Mode Select Bit 0 -; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; TWCR 0x0056 TWI Control Register -; TWCR.TWINT 7 TWI Interrupt Flag -; TWCR.TWEA 6 TWI Enable Acknowledge Bit -; TWCR.TWSTA 5 TWI START Condition Bit -; TWCR.TWSTO 4 TWI STOP Condition Bit -; TWCR.TWWC 3 TWI Write Collision Flag -; TWCR.TWEN 2 TWI Enable Bit -; TWCR.TWIE 0 TWI Interrupt Enable -; SPMCR 0x0057 Store Program Memory Control Register -; SPMCR.SPMIE 7 SPM Interrupt Enable -; SPMCR.RWWSB 6 Read-While-Write Section Busy -; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable -; SPMCR.BLBSET 3 Boot Lock Bit Set -; SPMCR.PGWRT 2 Page Write -; SPMCR.PGERS 1 Page Erase -; SPMCR.SPMEN 0 Store Program Memory Enable -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF2 7 Output Compare Flag 2 -; TIFR.TOV2 6 Timer/Counter2 Overflow Flag -; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag -; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag -; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag -; TIFR.TOV1 2 Timer/Counter1, Overflow Flag -; TIFR.TOV0 0 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable -; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable -; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable -; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable -; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable -; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF1 7 External Interrupt Flag 1 -; GIFR.INTF0 6 External Interrupt Flag 0 -; GICR 0x005B General Interrupt Control Register -; GICR.INT1 7 External Interrupt Request 1 Enable -; GICR.INT0 6 External Interrupt Request 0 Enable -; GICR.IVSEL 1 Interrupt Vector Select -; GICR.IVCE 0 Interrupt Vector Change Enable -; RESERVED005C 0x005C RESERVED -; SPL 0x005D Stack Pointer Low -; SPL.SP7 7 -; SPL.SP6 6 -; SPL.SP5 5 -; SPL.SP4 4 -; SPL.SP3 3 -; SPL.SP2 2 -; SPL.SP1 1 -; SPL.SP0 0 -; SPH 0x005E Stack Pointer High -; SPH.SP10 10 -; SPH.SP9 9 -; SPH.SP8 8 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATtiny15L -SUBARCH=1 -; doc1187.pdf -; - -RAM=0 -ROM=1024 -EEPROM=64 - -; MEMORY MAP - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Reset, Power-on Reset, Brown-out Reset, and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry I_O_Pins 0x0002 Pin Change Interrupt -entry TIMER1_COMPA 0x0003 Timer/Counter1 Compare Match A -entry TIMER1_OVF 0x0004 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0005 Timer/Counter0 Overflow -entry EE_RDY 0x0006 EEPROM Ready -entry ANA_COMP 0x0007 Analog Comparator -entry ADC_ 0x0008 ADC Conversion Complete - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion result 7 -ADCL.ADC6 6 ADC Conversion result 6 -ADCL.ADC5 5 ADC Conversion result 5 -ADCL.ADC4 4 ADC Conversion result 4 -ADCL.ADC3 3 ADC Conversion result 3 -ADCL.ADC2 2 ADC Conversion result 2 -ADCL.ADC1 1 ADC Conversion result 1 -ADCL.ADC0 0 ADC Conversion result 0 -ADCH 0x0005 The ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 ADC Conversion result 9 -ADCH.ADC8 8 ADC Conversion result 8 -; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion result 1 -; ADCL.ADC0 6 ADC Conversion result 0 -; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion result 9 -; ADCH.ADC8 14 ADC Conversion result 8 -; ADCH.ADC7 13 ADC Conversion result 7 -; ADCH.ADC6 12 ADC Conversion result 6 -; ADCH.ADC5 11 ADC Conversion result 5 -; ADCH.ADC4 10 ADC Conversion result 4 -; ADCH.ADC3 9 ADC Conversion result 3 -; ADCH.ADC2 8 ADC Conversion result 2 -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Running Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -RESERVED0010 0x0010 RESERVED -RESERVED0011 0x0011 RESERVED -RESERVED0012 0x0012 RESERVED -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEAR 0x001E EEPROM Address Register -EEAR.EEAR5 5 EEPROM Addres 5 -EEAR.EEAR4 4 EEPROM Addres 4 -EEAR.EEAR3 3 EEPROM Addres 3 -EEAR.EEAR2 2 EEPROM Addres 2 -EEAR.EEAR1 1 EEPROM Addres 1 -EEAR.EEAR0 0 EEPROM Addres 0 -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -SFIOR 0x002C Special Function IO Register -SFIOR.FOC1A 2 Force Output Compare 1A -SFIOR.PSR1 1 Prescaler Reset Timer/Counter1 -SFIOR.PSR0 0 Prescaler Reset Timer/Counter0 -OCR1B 0x002D Timer/Counter1 Output Compare RegisterB -OCR1A 0x002E Timer/Counter1 Output Compare Register A -TCNT1 0x002F Timer/Counter1 -TCCR1 0x0030 Timer/Counter1 Control Register -TCCR1.CTC1 7 Clear Timer/Counter on Compare Match -TCCR1.PWM1 6 Pulse Width Modulator Enable -TCCR1.COM1A1 5 Compare Output Mode, Bit 1 -TCCR1.COM1A0 4 Compare Output Mode, Bit 0 -TCCR1.CS13 3 Clock Select Bit 3 -TCCR1.CS12 2 Clock Select Bit 2 -TCCR1.CS11 1 Clock Select Bit 1 -TCCR1.CS10 0 Clock Select Bit 0 -OSCCAL 0x0031 System Clock Oscillator Calibration Register -OSCCAL.CAL7 7 -OSCCAL.CAL6 6 -OSCCAL.CAL5 5 -OSCCAL.CAL4 4 -OSCCAL.CAL3 3 -OSCCAL.CAL2 2 -OSCCAL.CAL1 1 -OSCCAL.CAL0 0 -TCNT0 0x0032 Timer Counter 0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.WDRF 3 Watchdog Reset Flag -MCUSR.BORF 2 Brown-out Reset Flag -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.PUD 6 Pull-up Disable -MCUCR.SE 5 SleepEnable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.SM0 3 Sleep Mode Select Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF1A 6 Output Compare Flag 1A -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF0 6 External Interrupt Flag0 -GIFR.PCIF 5 Pin Change Interrupt Flag -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.PCIE 5 PinChange InterruptEnable -RESERVED003C 0x003C RESERVED -RESERVED003D 0x003D RESERVED -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - - -.ATtiny26L -SUBARCH=2 -; doc1477.pdf -; - -RAM=128 -ROM=2048 -EEPROM=128 - -; MEMORY MAP -area DATA FSR_ 0x0000:0x0060 -area DATA I_SRAM 0x0060:0x00E0 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry I_O_Pins 0x0002 Pin Change Interrupt -entry TIMER1_CMPA 0x0003 Timer/Counter1 Compare Match 1A -entry TIMER1_CMPB 0x0004 Timer/Counter1 Compare Match 1B -entry TIMER1_OVF1 0x0005 Timer/Counter1 Overflow -entry TIMER0_OVF0 0x0006 Timer/Counter0 Overflow -entry USI_STRT 0x0007 USI Start -entry USI_OVF 0x0008 USI Overflow -entry EE_RDY 0x0009 EEPROM Ready -entry ANA_COMP 0x000A Analog Comparator -entry ADC_ 0x000B ADC Conversion Complete - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) -ADCL.ADC7 7 ADC Conversion result 7 -ADCL.ADC6 6 ADC Conversion result 6 -ADCL.ADC5 5 ADC Conversion result 5 -ADCL.ADC4 4 ADC Conversion result 4 -ADCL.ADC3 3 ADC Conversion result 3 -ADCL.ADC2 2 ADC Conversion result 2 -ADCL.ADC1 1 ADC Conversion result 1 -ADCL.ADC0 0 ADC Conversion result 0 -ADCH 0x0005 The ADC Data Register High (ADLAR = 0) -ADCH.ADC9 9 ADC Conversion result 9 -ADCH.ADC8 8 ADC Conversion result 8 -; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) -; ADCL.ADC1 7 ADC Conversion result 1 -; ADCL.ADC0 6 ADC Conversion result 0 -; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) -; ADCH.ADC9 15 ADC Conversion result 9 -; ADCH.ADC8 14 ADC Conversion result 8 -; ADCH.ADC7 13 ADC Conversion result 7 -; ADCH.ADC6 12 ADC Conversion result 6 -; ADCH.ADC5 11 ADC Conversion result 5 -; ADCH.ADC4 10 ADC Conversion result 4 -; ADCH.ADC3 9 ADC Conversion result 3 -; ADCH.ADC2 8 ADC Conversion result 2 -ADCSR 0x0006 ADC Control and Status Register -ADCSR.ADEN 7 ADC Enable -ADCSR.ADSC 6 ADC Start Conversion -ADCSR.ADFR 5 ADC Free Running Select -ADCSR.ADIF 4 ADC Interrupt Flag -ADCSR.ADIE 3 ADC Interrupt Enable -ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -ADMUX 0x0007 ADC Multiplexer Selection Register -ADMUX.REFS1 7 Reference Selection Bit 1 -ADMUX.REFS0 6 Reference Selection Bit 0 -ADMUX.ADLAR 5 ADC Left Adjust Result -ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACME 2 Analog Comparator Multiplexer Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -USICR 0x000D USI Control Register -USICR.USISIE 7 Start Condition Interrupt Enable -USICR.USIOIE 6 Counter Overflow Interrupt Enable -USICR.USIWM1 5 Wire Mode 1 -USICR.USIWM0 4 Wire Mode 0 -USICR.USICS1 3 Clock Source Select 1 -USICR.USICS0 2 Clock Source Select 0 -USICR.USICLK 1 Clock Strobe -USICR.USITC 0 Toggle Clock Port Pin -USISR 0x000E USI Status Register -USISR.USISIF 7 Start Condition Interrupt Flag -USISR.USIOIF 6 Counter Overflow Interrupt Flag -USISR.USIPF 5 Stop Condition Flag -USISR.USIDC 4 Data Output Collision -USISR.USICNT3 3 Counter Value 3 -USISR.USICNT2 2 Counter Value 2 -USISR.USICNT1 1 Counter Value 1 -USISR.USICNT0 0 Counter Value 0 -USIDR 0x000F USI Data Register -RESERVED0010 0x0010 RESERVED -RESERVED0011 0x0011 RESERVED -RESERVED0012 0x0012 RESERVED -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEAR 0x001E EEPROM Address Register -EEAR.EEAR6 6 EEPROM Addres 6 -EEAR.EEAR5 5 EEPROM Addres 5 -EEAR.EEAR4 4 EEPROM Addres 4 -EEAR.EEAR3 3 EEPROM Addres 3 -EEAR.EEAR2 2 EEPROM Addres 2 -EEAR.EEAR1 1 EEPROM Addres 1 -EEAR.EEAR0 0 EEPROM Addres 0 -RESERVED0001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDCE 4 Watchdog Change Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -PLLCSR 0x0029 PLL Control and Status Register -PLLCSR.PCKE 2 PCK Enable -PLLCSR.PLLE 1 PLL Enable -PLLCSR.PLOCK 0 PLL Lock Detector -RESERVED002A 0x002A RESERVED -OCR1C 0x002B Timer/Counter1 Output Compare Register C -OCR1B 0x002C Timer/Counter1 Output Compare Register B -OCR1A 0x002D Timer/Counter1 Output Compare Register A -TCNT1 0x002E Timer/Counter1 -TCCR1B 0x002F Timer/Counter1 Control Register B -TCCR1B.CTC1 7 Clear Timer/Counter on Compare Match -TCCR1B.PSR1 6 Prescaler Reset Timer/Counter1 -TCCR1B.CS13 3 Clock Select Bit 3 -TCCR1B.CS12 2 Clock Select Bit 2 -TCCR1B.CS11 1 Clock Select Bit 1 -TCCR1B.CS10 0 Clock Select Bit 0 -TCCR1A 0x0030 Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Comparator A Output Mode, Bit 1 -TCCR1A.COM1A0 6 Comparator A Output Mode, Bit 0 -TCCR1A.COM1B1 5 Comparator B Output Mode, Bit 1 -TCCR1A.COM1B0 4 Comparator B Output Mode, Bit 0 -TCCR1A.FOC1A 3 Force Output Compare Match 1A -TCCR1A.FOC1B 2 Force Output Compare Match 1B -TCCR1A.PWM1A 1 Pulse Width Modulator A Enable -TCCR1A.PWM1B 0 Pulse Width Modulator B Enable -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.PSR0 3 Prescaler Reset Timer/Counter0 -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.WDRF 3 Watchdog Reset Flag -MCUSR.BORF 2 Brown-out Reset Flag -MCUSR.EXTRF 1 External Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.PUD 6 Pull-up Disable -MCUCR.SE 5 Sleep Enable -MCUCR.SM1 4 Sleep Mode Select Bit 1 -MCUCR.SM0 3 Sleep Mode Select Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.OCF1A 6 Output Compare Flag 1A -TIFR.OCF1B 5 Output Compare Flag 1B -TIFR.TOV1 2 Timer/Counter1 Overflow Flag -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1 Output Compare Interrupt Enable -TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF0 6 External Interrupt Flag0 -GIFR.PCIF 5 Pin Change Interrupt Flag -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.PCIE1 5 Pin Change Interrupt Enable1 -GIMSK.PCIE0 4 Pin Change Interrupt Enable0 -RESERVED003C 0x003C RESERVED -SP 0x003D Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -; RESERVED0020 0x0020 RESERVED -; RESERVED0021 0x0021 RESERVED -; RESERVED0022 0x0022 RESERVED -; RESERVED0023 0x0023 RESERVED -; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) -; ADCL.ADC7 7 ADC Conversion result 7 -; ADCL.ADC6 6 ADC Conversion result 6 -; ADCL.ADC5 5 ADC Conversion result 5 -; ADCL.ADC4 4 ADC Conversion result 4 -; ADCL.ADC3 3 ADC Conversion result 3 -; ADCL.ADC2 2 ADC Conversion result 2 -; ADCL.ADC1 1 ADC Conversion result 1 -; ADCL.ADC0 0 ADC Conversion result 0 -; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) -; ADCH.ADC9 9 ADC Conversion result 9 -; ADCH.ADC8 8 ADC Conversion result 8 -; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) -; ; ADCL.ADC1 7 ADC Conversion result 1 -; ; ADCL.ADC0 6 ADC Conversion result 0 -; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) -; ; ADCH.ADC9 15 ADC Conversion result 9 -; ; ADCH.ADC8 14 ADC Conversion result 8 -; ; ADCH.ADC7 13 ADC Conversion result 7 -; ; ADCH.ADC6 12 ADC Conversion result 6 -; ; ADCH.ADC5 11 ADC Conversion result 5 -; ; ADCH.ADC4 10 ADC Conversion result 4 -; ; ADCH.ADC3 9 ADC Conversion result 3 -; ; ADCH.ADC2 8 ADC Conversion result 2 -; ADCSR 0x0026 ADC Control and Status Register -; ADCSR.ADEN 7 ADC Enable -; ADCSR.ADSC 6 ADC Start Conversion -; ADCSR.ADFR 5 ADC Free Running Select -; ADCSR.ADIF 4 ADC Interrupt Flag -; ADCSR.ADIE 3 ADC Interrupt Enable -; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 -; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 -; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 -; ADMUX 0x0027 ADC Multiplexer Selection Register -; ADMUX.REFS1 7 Reference Selection Bit 1 -; ADMUX.REFS0 6 Reference Selection Bit 0 -; ADMUX.ADLAR 5 ADC Left Adjust Result -; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 -; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 -; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 -; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 -; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 -; ACSR 0x0028 Analog Comparator Control and Status Register -; ACSR.ACD 7 Analog Comparator Disable -; ACSR.ACBG 6 Analog Comparator Bandgap Select -; ACSR.ACO 5 Analog Comparator Output -; ACSR.ACI 4 Analog Comparator Interrupt Flag -; ACSR.ACIE 3 Analog Comparator Interrupt Enable -; ACSR.ACME 2 Analog Comparator Multiplexer Enable -; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -; RESERVED0029 0x0029 RESERVED -; RESERVED002A 0x002A RESERVED -; RESERVED002B 0x002B RESERVED -; RESERVED002C 0x002C RESERVED -; USICR 0x002D USI Control Register -; USICR.USISIE 7 Start Condition Interrupt Enable -; USICR.USIOIE 6 Counter Overflow Interrupt Enable -; USICR.USIWM1 5 Wire Mode 1 -; USICR.USIWM0 4 Wire Mode 0 -; USICR.USICS1 3 Clock Source Select 1 -; USICR.USICS0 2 Clock Source Select 0 -; USICR.USICLK 1 Clock Strobe -; USICR.USITC 0 Toggle Clock Port Pin -; USISR 0x002E USI Status Register -; USISR.USISIF 7 Start Condition Interrupt Flag -; USISR.USIOIF 6 Counter Overflow Interrupt Flag -; USISR.USIPF 5 Stop Condition Flag -; USISR.USIDC 4 Data Output Collision -; USISR.USICNT3 3 Counter Value 3 -; USISR.USICNT2 2 Counter Value 2 -; USISR.USICNT1 1 Counter Value 1 -; USISR.USICNT0 0 Counter Value 0 -; USIDR 0x002F USI Data Register -; RESERVED0030 0x0030 RESERVED -; RESERVED0031 0x0031 RESERVED -; RESERVED0032 0x0032 RESERVED -; RESERVED0033 0x0033 RESERVED -; RESERVED0034 0x0034 RESERVED -; RESERVED0035 0x0035 RESERVED -; PINB 0x0036 Port B Input Pins Address -; PINB.PINB7 7 -; PINB.PINB6 6 -; PINB.PINB5 5 -; PINB.PINB4 4 -; PINB.PINB3 3 -; PINB.PINB2 2 -; PINB.PINB1 1 -; PINB.PINB0 0 -; DDRB 0x0037 Port B Data Direction Register -; DDRB.DDB7 7 Port B Data Direction Register bit 7 -; DDRB.DDB6 6 Port B Data Direction Register bit 6 -; DDRB.DDB5 5 Port B Data Direction Register bit 5 -; DDRB.DDB4 4 Port B Data Direction Register bit 4 -; DDRB.DDB3 3 Port B Data Direction Register bit 3 -; DDRB.DDB2 2 Port B Data Direction Register bit 2 -; DDRB.DDB1 1 Port B Data Direction Register bit 1 -; DDRB.DDB0 0 Port B Data Direction Register bit 0 -; PORTB 0x0038 Port B Data Register -; PORTB.PORTB7 7 Port B Data Register bit 7 -; PORTB.PORTB6 6 Port B Data Register bit 6 -; PORTB.PORTB5 5 Port B Data Register bit 5 -; PORTB.PORTB4 4 Port B Data Register bit 4 -; PORTB.PORTB3 3 Port B Data Register bit 3 -; PORTB.PORTB2 2 Port B Data Register bit 2 -; PORTB.PORTB1 1 Port B Data Register bit 1 -; PORTB.PORTB0 0 Port B Data Register bit 0 -; PINA 0x0039 Port A Input Pins Address -; PINA.PINA7 7 -; PINA.PINA6 6 -; PINA.PINA5 5 -; PINA.PINA4 4 -; PINA.PINA3 3 -; PINA.PINA2 2 -; PINA.PINA1 1 -; PINA.PINA0 0 -; DDRA 0x003A Port A Data Direction Register -; DDRA.DDA7 7 Port A Data Direction Register bit 7 -; DDRA.DDA6 6 Port A Data Direction Register bit 6 -; DDRA.DDA5 5 Port A Data Direction Register bit 5 -; DDRA.DDA4 4 Port A Data Direction Register bit 4 -; DDRA.DDA3 3 Port A Data Direction Register bit 3 -; DDRA.DDA2 2 Port A Data Direction Register bit 2 -; DDRA.DDA1 1 Port A Data Direction Register bit 1 -; DDRA.DDA0 0 Port A Data Direction Register bit 0 -; PORTA 0x003B Port A Data Register -; PORTA.PORTA7 7 Port A Data Register bit 7 -; PORTA.PORTA6 6 Port A Data Register bit 6 -; PORTA.PORTA5 5 Port A Data Register bit 5 -; PORTA.PORTA4 4 Port A Data Register bit 4 -; PORTA.PORTA3 3 Port A Data Register bit 3 -; PORTA.PORTA2 2 Port A Data Register bit 2 -; PORTA.PORTA1 1 Port A Data Register bit 1 -; PORTA.PORTA0 0 Port A Data Register bit 0 -; EECR 0x003C EEPROM Control Register -; EECR.EERIE 3 EEPROM Ready Interrupt Enable -; EECR.EEMWE 2 EEPROM Master Write Enable -; EECR.EEWE 1 EEPROM Write Enable -; EECR.EERE 0 EEPROM Read Enable -; EEDR 0x003D EEPROM Data Register -; EEDR.EEDR7 7 EEPROM Data 7 -; EEDR.EEDR6 6 EEPROM Data 6 -; EEDR.EEDR5 5 EEPROM Data 5 -; EEDR.EEDR4 4 EEPROM Data 4 -; EEDR.EEDR3 3 EEPROM Data 3 -; EEDR.EEDR2 2 EEPROM Data 2 -; EEDR.EEDR1 1 EEPROM Data 1 -; EEDR.EEDR0 0 EEPROM Data 0 -; EEAR 0x003E EEPROM Address Register -; EEAR.EEAR6 6 EEPROM Addres 6 -; EEAR.EEAR5 5 EEPROM Addres 5 -; EEAR.EEAR4 4 EEPROM Addres 4 -; EEAR.EEAR3 3 EEPROM Addres 3 -; EEAR.EEAR2 2 EEPROM Addres 2 -; EEAR.EEAR1 1 EEPROM Addres 1 -; EEAR.EEAR0 0 EEPROM Addres 0 -; RESERVED003F 0x003F RESERVED -; RESERVED0040 0x0040 RESERVED -; WDTCR 0x0041 Watchdog Timer Control Register -; WDTCR.WDCE 4 Watchdog Change Enable -; WDTCR.WDE 3 Watchdog Enable -; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -; RESERVED0042 0x0042 RESERVED -; RESERVED0043 0x0043 RESERVED -; RESERVED0044 0x0044 RESERVED -; RESERVED0045 0x0045 RESERVED -; RESERVED0046 0x0046 RESERVED -; RESERVED0047 0x0047 RESERVED -; RESERVED0048 0x0048 RESERVED -; PLLCSR 0x0049 PLL Control and Status Register -; PLLCSR.PCKE 2 PCK Enable -; PLLCSR.PLLE 1 PLL Enable -; PLLCSR.PLOCK 0 PLL Lock Detector -; RESERVED004A 0x004A RESERVED -; OCR1C 0x004B Timer/Counter1 Output Compare Register C -; OCR1B 0x004C Timer/Counter1 Output Compare Register B -; OCR1A 0x004D Timer/Counter1 Output Compare Register A -; TCNT1 0x004E Timer/Counter1 -; TCCR1B 0x004F Timer/Counter1 Control Register B -; TCCR1B.CTC1 7 Clear Timer/Counter on Compare Match -; TCCR1B.PSR1 6 Prescaler Reset Timer/Counter1 -; TCCR1B.CS13 3 Clock Select Bit 3 -; TCCR1B.CS12 2 Clock Select Bit 2 -; TCCR1B.CS11 1 Clock Select Bit 1 -; TCCR1B.CS10 0 Clock Select Bit 0 -; TCCR1A 0x0050 Timer/Counter1 Control Register A -; TCCR1A.COM1A1 7 Comparator A Output Mode, Bit 1 -; TCCR1A.COM1A0 6 Comparator A Output Mode, Bit 0 -; TCCR1A.COM1B1 5 Comparator B Output Mode, Bit 1 -; TCCR1A.COM1B0 4 Comparator B Output Mode, Bit 0 -; TCCR1A.FOC1A 3 Force Output Compare Match 1A -; TCCR1A.FOC1B 2 Force Output Compare Match 1B -; TCCR1A.PWM1A 1 Pulse Width Modulator A Enable -; TCCR1A.PWM1B 0 Pulse Width Modulator B Enable -; OSCCAL 0x0051 Oscillator Calibration Register -; OSCCAL.CAL7 7 Oscillator Calibration Value 7 -; OSCCAL.CAL6 6 Oscillator Calibration Value 6 -; OSCCAL.CAL5 5 Oscillator Calibration Value 5 -; OSCCAL.CAL4 4 Oscillator Calibration Value 4 -; OSCCAL.CAL3 3 Oscillator Calibration Value 3 -; OSCCAL.CAL2 2 Oscillator Calibration Value 2 -; OSCCAL.CAL1 1 Oscillator Calibration Value 1 -; OSCCAL.CAL0 0 Oscillator Calibration Value 0 -; TCNT0 0x0052 Timer/Counter0 -; TCCR0 0x0053 Timer/Counter0 Control Register -; TCCR0.PSR0 3 Prescaler Reset Timer/Counter0 -; TCCR0.CS02 2 Clock Select0, Bit 2 -; TCCR0.CS01 1 Clock Select0, Bit 1 -; TCCR0.CS00 0 Clock Select0, Bit 0 -; MCUSR 0x0054 MCU Status Register -; MCUSR.WDRF 3 Watchdog Reset Flag -; MCUSR.BORF 2 Brown-out Reset Flag -; MCUSR.EXTRF 1 External Reset Flag -; MCUSR.PORF 0 Power-on Reset Flag -; MCUCR 0x0055 MCU Control Register -; MCUCR.PUD 6 Pull-up Disable -; MCUCR.SE 5 Sleep Enable -; MCUCR.SM1 4 Sleep Mode Select Bit 1 -; MCUCR.SM0 3 Sleep Mode Select Bit 0 -; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -; RESERVED0056 0x0056 RESERVED -; RESERVED0057 0x0057 RESERVED -; TIFR 0x0058 Timer/Counter Interrupt Flag Register -; TIFR.OCF1A 6 Output Compare Flag 1A -; TIFR.OCF1B 5 Output Compare Flag 1B -; TIFR.TOV1 2 Timer/Counter1 Overflow Flag -; TIFR.TOV0 1 Timer/Counter0 Overflow Flag -; TIMSK 0x0059 Timer/Counter Interrupt Mask Register -; TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Interrupt Enable -; TIMSK.OCIE1B 5 Timer/Counter1 Output Compare Interrupt Enable -; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable -; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -; GIFR 0x005A General Interrupt Flag Register -; GIFR.INTF0 6 External Interrupt Flag0 -; GIFR.PCIF 5 Pin Change Interrupt Flag -; GIMSK 0x005B General Interrupt Mask Register -; GIMSK.INT0 6 External Interrupt Request 0 Enable -; GIMSK.PCIE1 5 Pin Change Interrupt Enable1 -; GIMSK.PCIE0 4 Pin Change Interrupt Enable0 -; RESERVED005C 0x005C RESERVED -; SP 0x005D Stack Pointer -; SP.SP7 7 -; SP.SP6 6 -; SP.SP5 5 -; SP.SP4 4 -; SP.SP3 3 -; SP.SP2 2 -; SP.SP1 1 -; SP.SP0 0 -; SREG 0x005F Status Register -; SREG.I 7 Global Interrupt Enable -; SREG.T 6 Bit Copy Storage -; SREG.H 5 Half Carry Flag -; SREG.S 4 Sign Bit -; SREG.V 3 Two's Complement Overflow Flag -; SREG.N 2 Negative Flag -; SREG.Z 1 Zero Flag -; SREG.C 0 Carry Flag - - -.ATtiny28L_V -SUBARCH=1 -; doc1062.pdf -; - -RAM=0 -ROM=2048 -EEPROM=0 - -; MEMORY MAP - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry Input_Pins 0x0003 Low-level Input on Port B -entry TIMER0_OVF0 0x0004 Timer/Counter0 Overflow -entry ANA_COMP 0x0005 Analog Comparator - - -; INPUT/OUTPUT PORTS -OSCCAL 0x0000 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -WDTCR 0x0001 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -MODCR 0x0002 Modulation Control Register -MODCR.ONTIM4 7 Modulation On-time 4 -MODCR.ONTIM3 6 Modulation On-time 3 -MODCR.ONTIM2 5 Modulation On-time 2 -MODCR.ONTIM1 4 Modulation On-time 1 -MODCR.ONTIM0 3 Modulation On-time 0 -MODCR.MCONF2 2 Modulation Configuration Bit 2 -MODCR.MCONF1 1 Modulation Configuration Bit 1 -MODCR.MCONF0 0 Modulation Configuration Bit 0 -TCNT0 0x0003 Timer Counter 0 -TCCR0 0x0004 Timer/Counter0 Control Register -TCCR0.FOV0 7 Force Overflow -TCCR0.OOM01 4 Overflow Output Mode, Bit 1 -TCCR0.OOM00 3 Overflow Output Mode, Bit 0 -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -IFR 0x0005 Interrupt Flag Register -IFR.INTF1 7 External Interrupt Flag1 -IFR.INTF0 6 External Interrupt Flag0 -IFR.TOV0 4 Timer/Counter0 Overflow Flag -ICR 0x0006 Interrupt Control Register -ICR.INT1 7 External Interrupt Request 1 Enable -ICR.INT0 6 External Interrupt Request 0 Enable -ICR.LLIE 5 Low-level Input Interrupt Enable -ICR.TOIE0 4 Timer/Counter0 Overflow Interrupt Enable -ICR.ISC11 3 Interrupt Sense Control 1 Bit 1 -ICR.ISC10 2 Interrupt Sense Control 1 Bit 0 -ICR.ISC01 1 Interrupt Sense Control 0 Bit 1 -ICR.ISC00 0 Interrupt Sense Control 0 Bit 0 -MCUCS 0x0007 MCU Control and Status Register -MCUCS.PLUPB 7 Pull-up Enable Port B -MCUCS.SE 5 Sleep Enable -MCUCS.SM 4 Sleep Mode -MCUCS.WDRF 3 Watchdog Reset Flag -MCUCS.EXTRF 1 External Reset Flag -MCUCS.PORF 0 Power-on Reset Flag -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -RESERVED0017 0x0017 RESERVED -RESERVED0018 0x0018 RESERVED -PINA 0x0019 Port A Input Pins Address -PINA.PINA3 3 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -RESERVED001C 0x001C RESERVED -RESERVED001D 0x001D RESERVED -RESERVED001E 0x001E RESERVED -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -RESERVED0021 0x0021 RESERVED -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -RESERVED002C 0x002C RESERVED -RESERVED002D 0x002D RESERVED -RESERVED002E 0x002E RESERVED -RESERVED002F 0x002F RESERVED -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -RESERVED0032 0x0032 RESERVED -RESERVED0033 0x0033 RESERVED -RESERVED0034 0x0034 RESERVED -RESERVED0035 0x0035 RESERVED -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -RESERVED0038 0x0038 RESERVED -RESERVED0039 0x0039 RESERVED -RESERVED003A 0x003A RESERVED -RESERVED003B 0x003B RESERVED -RESERVED003C 0x003C RESERVED -RESERVED003D 0x003D RESERVED -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - - -.ATtiny_11 -SUBARCH=1 -; doc1006.pdf -; - -RAM=0 -ROM=1024 -EEPROM=0 - -; MEMORY MAP - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry I_O_Pins 0x0002 Pin Change Interrupt -entry TIMER0_OVF0 0x0003 Timer/Counter0 Overflow -entry ANA_COMP 0x0004 Analog Comparator - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -RESERVED0010 0x0010 RESERVED -RESERVED0011 0x0011 RESERVED -RESERVED0012 0x0012 RESERVED -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -RESERVED001C 0x001C RESERVED -RESERVED001D 0x001D RESERVED -RESERVED001E 0x001E RESERVED -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -RESERVED002C 0x002C RESERVED -RESERVED002D 0x002D RESERVED -RESERVED002E 0x002E RESERVED -RESERVED002F 0x002F RESERVED -RESERVED0030 0x0030 RESERVED -RESERVED0031 0x0031 RESERVED -TCNT0 0x0032 Timer Counter 0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.EXTRF 1 EXTernal Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC01 1 Interrupt Sense Control0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF0 6 External Interrupt Flag0 -GIFR.PCIF 5 Pin Change Interrupt Flag -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.PCIE 5 Pin Change Interrupt Enable -RESERVED003C 0x003C RESERVED -RESERVED003D 0x003D RESERVED -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - - -.ATtiny_11_12 -SUBARCH=1 -; doc1006.pdf -; - -RAM=0 -ROM=1024 -EEPROM=64 - -; MEMORY MAP - -; Interrupt and reset vector assignments -entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset -entry INT0_ 0x0001 External Interrupt Request 0 -entry I_O_Pins 0x0002 Pin Change Interrupt -entry TIMER0_OVF0 0x0003 Timer/Counter0 Overflow -entry EE_RDY 0x0004 EEPROM Ready -entry ANA_COMP 0x0005 Analog Comparator - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -RESERVED0001 0x0001 RESERVED -RESERVED0002 0x0002 RESERVED -RESERVED0003 0x0003 RESERVED -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.AINBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -RESERVED0009 0x0009 RESERVED -RESERVED000A 0x000A RESERVED -RESERVED000B 0x000B RESERVED -RESERVED000C 0x000C RESERVED -RESERVED000D 0x000D RESERVED -RESERVED000E 0x000E RESERVED -RESERVED000F 0x000F RESERVED -RESERVED0010 0x0010 RESERVED -RESERVED0011 0x0011 RESERVED -RESERVED0012 0x0012 RESERVED -RESERVED0013 0x0013 RESERVED -RESERVED0014 0x0014 RESERVED -RESERVED0015 0x0015 RESERVED -PINB 0x0016 Port B Input Pins Address -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -RESERVED0019 0x0019 RESERVED -RESERVED001A 0x001A RESERVED -RESERVED001B 0x001B RESERVED -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEDR.EEDR7 7 EEPROM Data 7 -EEDR.EEDR6 6 EEPROM Data 6 -EEDR.EEDR5 5 EEPROM Data 5 -EEDR.EEDR4 4 EEPROM Data 4 -EEDR.EEDR3 3 EEPROM Data 3 -EEDR.EEDR2 2 EEPROM Data 2 -EEDR.EEDR1 1 EEPROM Data 1 -EEDR.EEDR0 0 EEPROM Data 0 -EEAR 0x001E EEPROM Address Register -EEAR.EEAR5 5 -EEAR.EEAR4 4 -EEAR.EEAR3 3 -EEAR.EEAR2 2 -EEAR.EEAR1 1 -EEAR.EEAR0 0 -RESERVED001F 0x001F RESERVED -RESERVED0020 0x0020 RESERVED -WDTCR 0x0021 Watchdog Timer Control Register -WDTCR.WDTOE 4 Watchdog Turn-off Enable -WDTCR.WDE 3 Watchdog Enable -WDTCR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCR.WDP0 0 Watchdog Timer Prescaler 0 -RESERVED0022 0x0022 RESERVED -RESERVED0023 0x0023 RESERVED -RESERVED0024 0x0024 RESERVED -RESERVED0025 0x0025 RESERVED -RESERVED0026 0x0026 RESERVED -RESERVED0027 0x0027 RESERVED -RESERVED0028 0x0028 RESERVED -RESERVED0029 0x0029 RESERVED -RESERVED002A 0x002A RESERVED -RESERVED002B 0x002B RESERVED -RESERVED002C 0x002C RESERVED -RESERVED002D 0x002D RESERVED -RESERVED002E 0x002E RESERVED -RESERVED002F 0x002F RESERVED -RESERVED0030 0x0030 RESERVED -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL7 7 Oscillator Calibration Value 7 -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer Counter 0 -TCCR0 0x0033 Timer/Counter0 Control Register -TCCR0.CS02 2 Clock Select0, Bit 2 -TCCR0.CS01 1 Clock Select0, Bit 1 -TCCR0.CS00 0 Clock Select0, Bit 0 -MCUSR 0x0034 MCU Status Register -MCUSR.WDRF 3 Watchdog Reset Flag -MCUSR.BORF 2 Brown-out Reset Flag -MCUSR.EXTRF 1 EXTernal Reset Flag -MCUSR.PORF 0 Power-on Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.PUD 6 Pull-up Disable -MCUCR.SE 5 Sleep Enable -MCUCR.SM 4 Sleep Mode -MCUCR.ISC01 1 Interrupt Sense Control0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control0 Bit 0 -RESERVED0036 0x0036 RESERVED -RESERVED0037 0x0037 RESERVED -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -GIFR 0x003A General Interrupt Flag Register -GIFR.INTF0 6 External Interrupt Flag0 -GIFR.PCIF 5 Pin Change Interrupt Flag -GIMSK 0x003B General Interrupt Mask Register -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.PCIE 5 Pin Change Interrupt Enable -RESERVED003C 0x003C RESERVED -RESERVED003D 0x003D RESERVED -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 Carry Flag - -.ATmega168P -; doc8025.pdf -; - -RAM=1024 -ROM=16384 -EEPROM=512 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0060 I/O registers -area DATA I_SRAM 0x0060:0x0160 Internal SRAM - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin -entry INT0_ 0x0002 External Interrupt Request 0 -entry INT1_ 0x0004 External Interrupt Request 1 -entry PCINT0 0x0006 Pin Change Interrupt Request 0 -entry PCINT1 0x0008 Pin Change Interrupt Request 1 -entry PCINT2 0x000A Pin Change Interrupt Request 2 -entry WDT 0x000C Watchdog Time-out -entry TIMER2_COMPA 0x000E Timer/Counter2 Comapare Match A -entry TIMER2_COMPB 0x0010 Timer/Counter2 Comapare Match B -entry TIMER2_OVF 0x0012 Timer/Counter2 Overflow -entry TIMER1_CAPT 0x0014 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0016 Timer/Counter1 Comapare Match A -entry TIMER1_COMPB 0x0018 Timer/Counter1 Comapare Match B -entry TIMER1_OVF 0x001A Timer/Counter1 Overflow -entry TIMER0_COMPA 0x001C Timer/Counter0 Comapare Match A -entry TIMER0_COMPB 0x001E Timer/Counter0 Comapare Match B -entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow -entry SPI_STC 0x0022 SPI Serial Transfer Complete -entry USART_RX 0x0024 USART RX Complete -entry USART_UDRE 0x0026 USART Data register empty -entry USART_TX 0x0028 USART TX Complete -entry ADC 0x002A ADC Conversion Complete -entry EEREADY 0x002C EEPROM Ready - -; INPUT/OUTPUT PORTS -UDR0 0x00A6 -UBRR0H 0x00A5 -UBRR0L 0x00A4 -UCSR0C 0x00A2 -UCSR0C.UMSEL01 7 -UCSR0C.UMSEL00 6 -UCSR0C.UPM01 5 -UCSR0C.UPM00 4 -UCSR0C.USBS0 3 -UCSR0C.UCSZ01 2 -UCSR0C._UDORD0 1 -UCSR0C.UCSZ00 0 -UCSR0B 0x00A1 -UCSR0B.RXCIE0 7 -UCSR0B.TXCIE0 6 -UCSR0B.UDRIE0 5 -UCSR0B.RXEN0 4 -UCSR0B.TXEN0 3 -UCSR0B.UCSZ02 2 -UCSR0B.RXB80 1 -UCSR0B.TXB80 0 -UCSR0A 0x00A0 -UCSR0A.RXC0 7 -UCSR0A.TXC0 6 -UCSR0A.UDRE0 5 -UCSR0A.FE0 4 -UCSR0A.DOR0 3 -UCSR0A.UPE0 2 -UCSR0A.U2X0 1 -UCSR0A.MPCM0 0 -TWAMR 0x009D -TWAMR.TWAM6 7 -TWAMR.TWAM5 6 -TWAMR.TWAM4 5 -TWAMR.TWAM3 4 -TWAMR.TWAM2 3 -TWAMR.TWAM1 2 -TWAMR.TWAM0 1 -TWCR 0x009C -TWCR.TWINT 7 -TWCR.TWEA 6 -TWCR.TWSTA 5 -TWCR.TWSTO 4 -TWCR.TWWC 3 -TWCR.TWEN 2 -TWCR.TWIE 0 -TWDR 0x009B -TWAR 0x009A -TWAR.TWA6 7 -TWAR.TWA5 6 -TWAR.TWA4 5 -TWAR.TWA3 4 -TWAR.TWA2 3 -TWAR.TWA1 2 -TWAR.TWA0 1 -TWAR.TWGCE 0 -TWSR 0x0099 -TWSR.TWS7 7 -TWSR.TWS6 6 -TWSR.TWS5 5 -TWSR.TWS4 4 -TWSR.TWS3 3 -TWSR.TWPS1 1 -TWSR.TWPS0 0 -TWBR 0x0098 -ASSR 0x0096 -ASSR.EXCLK 6 -ASSR.AS2 5 -ASSR.TCN2UB 4 -ASSR.OCR2AUB 3 -ASSR.OCR2BUB 2 -ASSR.TCR2AUB 1 -ASSR.TCR2BUB 0 -OCR2B 0x0094 -OCR2A 0x0093 -TCNT2 0x0092 -TCCR2B 0x0091 -TCCR2B.FOC2A 7 -TCCR2B.FOC2B 6 -TCCR2B.WGM22 3 -TCCR2B.CS22 2 -TCCR2B.CS21 1 -TCCR2B.CS20 0 -TCCR2A 0x0090 -TCCR2A.COM2A1 7 -TCCR2A.COM2A0 6 -TCCR2A.COM2B1 5 -TCCR2A.COM2B0 4 -TCCR2A.WGM21 1 -TCCR2A.WGM20 0 -OCR1BH 0x006B -OCR1BH.Timer_Counter1 7 -OCR1BH.Output 5 -OCR1BH.Compare 4 -OCR1BH.Register 3 -OCR1BH.B 2 -OCR1BH.High 1 -OCR1BH.Byte 0 -OCR1BL 0x006A -OCR1BL.Timer_Counter1 7 -OCR1BL.Output 5 -OCR1BL.Compare 4 -OCR1BL.Register 3 -OCR1BL.B 2 -OCR1BL.Low 1 -OCR1BL.Byte 0 -OCR1AH 0x0069 -OCR1AH.Timer_Counter1 7 -OCR1AH.Output 5 -OCR1AH.Compare 4 -OCR1AH.Register 3 -OCR1AH.A 2 -OCR1AH.High 1 -OCR1AH.Byte 0 -OCR1AL 0x0068 -OCR1AL.Timer_Counter1 7 -OCR1AL.Output 5 -OCR1AL.Compare 4 -OCR1AL.Register 3 -OCR1AL.A 2 -OCR1AL.Low 1 -OCR1AL.Byte 0 -ICR1H 0x0067 -ICR1H.Timer_Counter1 7 -ICR1H.Input 5 -ICR1H.Capture 4 -ICR1H.Register 3 -ICR1H.High 2 -ICR1H.Byte 1 -ICR1H.136 0 -ICR1L 0x0066 -ICR1L.Timer_Counter1 7 -ICR1L.Input 5 -ICR1L.Capture 4 -ICR1L.Register 3 -ICR1L.Low 2 -ICR1L.Byte 1 -ICR1L.136 0 -TCNT1H 0x0065 -TCNT1L 0x0064 -TCCR1C 0x0062 -TCCR1C.FOC1A 7 -TCCR1C.FOC1B 6 -TCCR1B 0x0061 -TCCR1B.ICNC1 7 -TCCR1B.ICES1 6 -TCCR1B.WGM13 4 -TCCR1B.WGM12 3 -TCCR1B.CS12 2 -TCCR1B.CS11 1 -TCCR1B.CS10 0 -TCCR1A 0x0060 -TCCR1A.COM1A1 7 -TCCR1A.COM1A0 6 -TCCR1A.COM1B1 5 -TCCR1A.COM1B0 4 -TCCR1A.WGM11 1 -TCCR1A.WGM10 0 -DIDR1 0x005F -DIDR1.AIN1D 1 -DIDR1.AIN0D 0 -DIDR0 0x005E -DIDR0.ADC5D 5 -DIDR0.ADC4D 4 -DIDR0.ADC3D 3 -DIDR0.ADC2D 2 -DIDR0.ADC1D 1 -DIDR0.ADC0D 0 -ADMUX 0x005C -ADMUX.REFS1 7 -ADMUX.REFS0 6 -ADMUX.ADLAR 5 -ADMUX.MUX3 3 -ADMUX.MUX2 2 -ADMUX.MUX1 1 -ADMUX.MUX0 0 -ADCSRB 0x005B -ADCSRB.ACME 6 -ADCSRB.ADTS2 2 -ADCSRB.ADTS1 1 -ADCSRB.ADTS0 0 -ADCSRA 0x005A -ADCSRA.ADEN 7 -ADCSRA.ADSC 6 -ADCSRA.ADATE 5 -ADCSRA.ADIF 4 -ADCSRA.ADIE 3 -ADCSRA.ADPS2 2 -ADCSRA.ADPS1 1 -ADCSRA.ADPS0 0 -ADCH 0x0059 -ADCL 0x0058 -TIMSK2 0x0050 -TIMSK2.OCIE2B 2 -TIMSK2.OCIE2A 1 -TIMSK2.TOIE2 0 -TIMSK1 0x004F -TIMSK1.ICIE1 5 -TIMSK1.OCIE1B 2 -TIMSK1.OCIE1A 1 -TIMSK1.TOIE1 0 -TIMSK0 0x004E -TIMSK0.OCIE0B 2 -TIMSK0.OCIE0A 1 -TIMSK0.TOIE0 0 -PCMSK2 0x004D -PCMSK2.PCINT23 7 -PCMSK2.PCINT22 6 -PCMSK2.PCINT21 5 -PCMSK2.PCINT20 4 -PCMSK2.PCINT19 3 -PCMSK2.PCINT18 2 -PCMSK2.PCINT17 1 -PCMSK2.PCINT16 0 -PCMSK1 0x004C -PCMSK1.PCINT14 6 -PCMSK1.PCINT13 5 -PCMSK1.PCINT12 4 -PCMSK1.PCINT11 3 -PCMSK1.PCINT10 2 -PCMSK1.PCINT9 1 -PCMSK1.PCINT8 0 -PCMSK0 0x004B -PCMSK0.PCINT7 7 -PCMSK0.PCINT6 6 -PCMSK0.PCINT5 5 -PCMSK0.PCINT4 4 -PCMSK0.PCINT3 3 -PCMSK0.PCINT2 2 -PCMSK0.PCINT1 1 -PCMSK0.PCINT0 0 -EICRA 0x0049 -EICRA.ISC11 3 -EICRA.ISC10 2 -EICRA.ISC01 1 -EICRA.ISC00 0 -PCICR 0x0048 -PCICR.PCIE2 2 -PCICR.PCIE1 1 -PCICR.PCIE0 0 -OSCCAL 0x0046 -PRR 0x0044 -PRR.PRTWI 7 -PRR.PRTIM2 6 -PRR.PRTIM0 5 -PRR.PRTIM1 3 -PRR.PRSPI 2 -PRR.PRUSART0 1 -PRR.PRADC 0 -CLKPR 0x0041 -CLKPR.CLKPCE 7 -CLKPR.CLKPS3 3 -CLKPR.CLKPS2 2 -CLKPR.CLKPS1 1 -CLKPR.CLKPS0 0 -WDTCSR 0x0040 -WDTCSR.WDIF 7 -WDTCSR.WDIE 6 -WDTCSR.WDP3 5 -WDTCSR.WDCE 4 -WDTCSR.WDE 3 -WDTCSR.WDP2 2 -WDTCSR.WDP1 1 -WDTCSR.WDP0 0 -SREG 0x003F -SREG.I 7 -SREG.T 6 -SREG.H 5 -SREG.S 4 -SREG.V 3 -SREG.N 2 -SREG.Z 1 -SREG.C 0 -SPH 0x003E -SPH.(SP10) 2 -SPH.5. 1 -SPH.SP9 0 -SPL 0x003D -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -SPMCSR 0x0037 -SPMCSR.SPMIE 7 -SPMCSR.(RWWSB)5. 6 -SPMCSR.(RWWSRE)5. 4 -SPMCSR.BLBSET 3 -SPMCSR.PGWRT 2 -SPMCSR.PGERS 1 -SPMCSR.SELFPRGEN 0 -MCUCR 0x0035 -MCUCR.BODS 6 -MCUCR.BODSE 5 -MCUCR.PUD 4 -MCUCR.IVSEL 1 -MCUCR.IVCE 0 -MCUSR 0x0034 -MCUSR.WDRF 3 -MCUSR.BORF 2 -MCUSR.EXTRF 1 -MCUSR.PORF 0 -SMCR 0x0033 -SMCR.SM2 3 -SMCR.SM1 2 -SMCR.SM0 1 -SMCR.SE 0 -ACSR 0x0030 -ACSR.ACD 7 -ACSR.ACBG 6 -ACSR.ACO 5 -ACSR.ACI 4 -ACSR.ACIE 3 -ACSR.ACIC 2 -ACSR.ACIS1 1 -ACSR.ACIS0 0 -SPDR 0x002E -SPSR 0x002D -SPSR.SPIF 7 -SPSR.WCOL 6 -SPSR.SPI2X 0 -SPCR 0x002C -SPCR.SPIE 7 -SPCR.SPE 6 -SPCR.DORD 5 -SPCR.MSTR 4 -SPCR.CPOL 3 -SPCR.CPHA 2 -SPCR.SPR1 1 -SPCR.SPR0 0 -GPIOR2 0x002B -GPIOR1 0x002A -OCR0B 0x0028 -OCR0A 0x0027 -TCNT0 0x0026 -TCCR0B 0x0025 -TCCR0B.FOC0A 7 -TCCR0B.FOC0B 6 -TCCR0B.WGM02 3 -TCCR0B.CS02 2 -TCCR0B.CS01 1 -TCCR0B.CS00 0 -TCCR0A 0x0024 -TCCR0A.COM0A1 7 -TCCR0A.COM0A0 6 -TCCR0A.COM0B1 5 -TCCR0A.COM0B0 4 -TCCR0A.WGM01 1 -TCCR0A.WGM00 0 -GTCCR 0x0023 -GTCCR.TSM 7 -GTCCR.PSRASY 1 -GTCCR.PSRSYNC 0 -EEARH 0x0022 -EEARL 0x0021 -EEDR 0x0020 -EECR 0x001F -EECR.EEPM1 5 -EECR.EEPM0 4 -EECR.EERIE 3 -EECR.EEMPE 2 -EECR.EEPE 1 -EECR.EERE 0 -GPIOR0 0x001E -EIMSK 0x001D -EIMSK.INT1 1 -EIMSK.INT0 0 -EIFR 0x001C -EIFR.INTF1 1 -EIFR.INTF0 0 -PCIFR 0x001B -PCIFR.PCIF2 2 -PCIFR.PCIF1 1 -PCIFR.PCIF0 0 -TIFR2 0x0017 -TIFR2.OCF2B 2 -TIFR2.OCF2A 1 -TIFR2.TOV2 0 -TIFR1 0x0016 -TIFR1.ICF1 5 -TIFR1.OCF1B 2 -TIFR1.OCF1A 1 -TIFR1.TOV1 0 -TIFR0 0x0015 -TIFR0.OCF0B 2 -TIFR0.OCF0A 1 -TIFR0.TOV0 0 -PORTD 0x000B -PORTD.PORTD7 7 -PORTD.PORTD6 6 -PORTD.PORTD5 5 -PORTD.PORTD4 4 -PORTD.PORTD3 3 -PORTD.PORTD2 2 -PORTD.PORTD1 1 -PORTD.PORTD0 0 -DDRD 0x000A -DDRD.DDD7 7 -DDRD.DDD6 6 -DDRD.DDD5 5 -DDRD.DDD4 4 -DDRD.DDD3 3 -DDRD.DDD2 2 -DDRD.DDD1 1 -DDRD.DDD0 0 -PIND 0x0009 -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -PORTC 0x0008 -PORTC.PORTC6 6 -PORTC.PORTC5 5 -PORTC.PORTC4 4 -PORTC.PORTC3 3 -PORTC.PORTC2 2 -PORTC.PORTC1 1 -PORTC.PORTC0 0 -DDRC 0x0007 -DDRC.DDC6 6 -DDRC.DDC5 5 -DDRC.DDC4 4 -DDRC.DDC3 3 -DDRC.DDC2 2 -DDRC.DDC1 1 -DDRC.DDC0 0 -PINC 0x0006 -PINC.PINC6 6 -PINC.PINC5 5 -PINC.PINC4 4 -PINC.PINC3 3 -PINC.PINC2 2 -PINC.PINC1 1 -PINC.PINC0 0 -PORTB 0x0005 -PORTB.PORTB7 7 -PORTB.PORTB6 6 -PORTB.PORTB5 5 -PORTB.PORTB4 4 -PORTB.PORTB3 3 -PORTB.PORTB2 2 -PORTB.PORTB1 1 -PORTB.PORTB0 0 -DDRB 0x0004 -DDRB.DDB7 7 -DDRB.DDB6 6 -DDRB.DDB5 5 -DDRB.DDB4 4 -DDRB.DDB3 3 -DDRB.DDB2 2 -DDRB.DDB1 1 -DDRB.DDB0 0 -PINB 0x0003 -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 - -.ATtiny2313 -SUBARCH=25 -; doc2543.pdf -; - -RAM=128 -ROM=2048 -EEPROM=128 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0060 I/O registers -area DATA I_SRAM 0x0060:0x00E0 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A -entry TIMER1_OVF 0x0005 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0006 Timer/Counter0 Overflow -entry USART0_RX 0x0007 USART0, Rx Complete -entry USART0_UDRE 0x0008 USART0 Data Register Empty -entry USART0_TX 0x0009 USART0, Tx Complete -entry ANALOG_COMP 0x000A Analog Comparator -entry PCINT0 0x000B Pin Change Interrupt Request 0 -entry TIMER1_COMPB 0x000C Timer/Counter1 Compare Match B -entry TIMER0_COMPA 0x000D Timer/Counter0 Compare Match A -entry TIMER0_COMPB 0x000E Timer/Counter0 Compare Match B -entry USI_START 0x000F USI Start Condition -entry USI_OVERFLOW 0x0010 USI Overflow -entry EE_READY 0x0011 EEPROM Ready -entry WDT_OVERFLOW 0x0012 Watchdog Timer Overflow - - -; INPUT/OUTPUT PORTS -RESERVED0000 0x0000 RESERVED -DIDR 0x0001 Digital Input Disable Register -DIDR.AIND0 1 AIN0 Digital Input Disable -DIDR.AIND1 2 AIN1 Digital Input Disable -UBRRH 0x0002 USART Baud Rate Registers High -UCSRC 0x0003 USART Control and Status Register C -UCSRC.UMSEL 6 USART Mode Select -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -RESERVED0004 0x0004 RESERVED -RESERVED0005 0x0005 RESERVED -RESERVED0006 0x0006 RESERVED -RESERVED0007 0x0007 RESERVED -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register -UBRRL.UBRR7 7 -UBRRL.UBRR6 6 -UBRRL.UBRR5 5 -UBRRL.UBRR4 4 -UBRRL.UBRR3 3 -UBRRL.UBRR2 2 -UBRRL.UBRR1 1 -UBRRL.UBRR0 0 -UCSRB 0x000A USART Control and Status Register -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit8 -UCSRA 0x000B USART Control and Status Register -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.UPE 2 Parity Error -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-Processor Communication Mode -UDR 0x000C USART I/O Data Register -USICR 0x000D USI Control Register -USICR.USISIE 7 Start Condition Interrupt Enable -USICR.USIOIE 6 Counter Overflow Interrupt Enable -USICR.USIWM1 5 Wire Mode 1 -USICR.USIWM0 4 Wire Mode 0 -USICR.USICS1 3 Clock Source Select 1 -USICR.USICS0 2 Clock Source Select 0 -USICR.USICLK 1 Clock Strobe -USICR.USITC 0 Toggle Clock Port Pin -USISR 0x000E USI Status Register -USISR.USISIF 7 Start Condition Interrupt Flag -USISR.USIOIF 6 Counter Overflow Interrupt Flag -USISR.USIPF 5 Stop Condition Flag -USISR.USIDC 4 Data Output Collision -USISR.USICNT3 3 Counter Value 3 -USISR.USICNT2 2 Counter Value 2 -USISR.USICNT1 1 Counter Value 1 -USISR.USICNT0 0 Counter Value 0 -USIDR 0x000F USI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -GPIOR0 0x0013 General Purpose I/O Register 0 -GPIOR1 0x0014 General Purpose I/O Register 0 -GPIOR2 0x0015 General Purpose I/O Register 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEAR 0x001E EEPROM Address Register -EEAR.EEAR7 7 -EEAR.EEAR6 6 -EEAR.EEAR5 5 -EEAR.EEAR4 4 -EEAR.EEAR3 3 -EEAR.EEAR2 2 -EEAR.EEAR1 1 -EEAR.EEAR0 0 -RESERVED001F 0x001F RESERVED -PCMSK 0x0020 Pin Change Mask Register 0 -PCMSK.PCINT7 7 Pin Change Enable Mask 7 -PCMSK.PCINT6 6 Pin Change Enable Mask 6 -PCMSK.PCINT5 5 Pin Change Enable Mask 5 -PCMSK.PCINT4 4 Pin Change Enable Mask 4 -PCMSK.PCINT3 3 Pin Change Enable Mask 3 -PCMSK.PCINT2 2 Pin Change Enable Mask 2 -PCMSK.PCINT1 1 Pin Change Enable Mask 1 -PCMSK.PCINT0 0 Pin Change Enable Mask 0 -WDTCSR 0x0021 Watchdog Timer Control Register -WDTCSR.WDIF 7 Watchdog Interrupt Flag -WDTCSR.WDIE 6 Watchdog Interrupt Enable -WDTCSR.WDP3 5 Watchdog Timer Prescaler 3 -WDTCSR.WDCE 4 Watchdog Change Enable -WDTCSR.WDE 3 Watchdog Enable -WDTCSR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCSR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCSR.WDP0 0 Watchdog Timer Prescaler 0 -TCCR1C 0x0022 Timer/Counter1 Control Register C -TCCR1C.FOC1A 7 Force Output Compare for Channel A -TCCR1C.FOC1B 6 Force Output Compare for Channel B -GTCCR 0x0023 General Timer/Counter Control Register -GTCCR.PSR10 1 Prescaler Reset Timer/Counter1 and Timer/Counter0 -ICR1L 0x0024 Input Capture Register Low Byte -ICR1H 0x0025 Input Capture Register High Byte -CLKPR 0x0026 Clock Prescale Register -CLKPR.CPCE 7 Clock Prescaler Change Enable -CLKPR.CLKPS3 3 Clock Prescaler Select Bit 3 -CLKPR.CLKPS2 2 Clock Prescaler Select Bit 2 -CLKPR.CLKPS1 1 Clock Prescaler Select Bit 1 -CLKPR.CLKPS0 0 Clock Prescaler Select Bit 0 -RESERVED0027 0x0027 RESERVED -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input CaptureEdgeSelect -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -TCCR0A 0x0030 Timer/Counter0 Control Register A -TCCR0A.COM0A1 7 Compare Output Mode for Channel A 1 -TCCR0A.COM0A0 6 Compare Output Mode for Channel A 0 -TCCR0A.COM0B1 5 Compare Output Mode for Channel B 1 -TCCR0A.COM0B0 4 Compare Output Mode for Channel B 0 -TCCR0A.WGM01 1 Waveform Generation Mode 1 -TCCR0A.WGM00 0 Waveform Generation Mode 0 -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter0 -TCCR0B 0x0033 Timer/Counter Control Register -TCCR0B.FOC0A 7 Force Output Compare A -TCCR0B.FOC0B 6 Force Output Compare B -TCCR0B.WGM02 3 Waveform Generation Mode -TCCR0B.CS02 2 Clock Select 2 -TCCR0B.CS01 1 Clock Select 1 -TCCR0B.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-On Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.PUD 7 Pull-up Disable -MCUCR.SM1 6 Sleep Mode Select Bit 1 -MCUCR.SE 5 SleepEnable -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -OCR0A 0x0036 Timer/Counter0 Compare Register A -SPMCSR 0x0037 Store Program Memory Control Register -SPMCSR.CTPB 4 Clear Temporary Page Buffer -SPMCSR.RFLB 3 Read Fuse and Lock Bits -SPMCSR.PGWRT 2 Page Write -SPMCSR.PGERS 1 Page Erase -SPMCSR.SELFPRGEN 0 Self Programming Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter1 Overflow Flag -TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag -TIFR.ICF1 3 Timer/Counter1, Input Capture Flag -TIFR.OCF0B 2 Timer/Counter0, Output Compare B Match Flag -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIFR.OCF0A 0 Timer/Counter0, Output Compare A Match Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.ICIE1 3 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE0A 2 Timer/Counter0, Output Compare A Match Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -TIMSK.OCIE0B 0 Timer/Counter0, Output Compare B Match Interrupt Enable -EIFR 0x003A External Interrupt Flag Register -EIFR.INTF1 7 External Interrupt Flag 1 -EIFR.INTF0 6 External Interrupt Flag 0 -EIFR.PCIF 5 Pin Change Interrupt Flag -GIMSK 0x003B External Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.PCIE 5 Pin Change Interrupt Request Enable -OCR0B 0x003C Output Compare Register B Low Byte -SPL 0x003D Stack Pointer Register Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 CarryFlag - - -.ATtiny2313A -SUBARCH=25 -; doc8246.pdf -; - -RAM=128 -ROM=2048 -EEPROM=128 - - -; MEMORY MAP -area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers -area DATA FSR_ 0x0020:0x0060 I/O registers -area DATA I_SRAM 0x0060:0x00E0 Internal SRAM - - -; Interrupt and reset vector assignments -entry __RESET 0x0000 Hardware Pin -entry INT0_ 0x0001 External Interrupt Request 0 -entry INT1_ 0x0002 External Interrupt Request 1 -entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event -entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A -entry TIMER1_OVF 0x0005 Timer/Counter1 Overflow -entry TIMER0_OVF 0x0006 Timer/Counter0 Overflow -entry USART0_RX 0x0007 USART0, Rx Complete -entry USART0_UDRE 0x0008 USART0 Data Register Empty -entry USART0_TX 0x0009 USART0, Tx Complete -entry ANALOG_COMP 0x000A Analog Comparator -entry PCINT0 0x000B Pin Change Interrupt Request 0 -entry TIMER1_COMPB 0x000C Timer/Counter1 Compare Match B -entry TIMER0_COMPA 0x000D Timer/Counter0 Compare Match A -entry TIMER0_COMPB 0x000E Timer/Counter0 Compare Match B -entry USI_START 0x000F USI Start Condition -entry USI_OVERFLOW 0x0010 USI Overflow -entry EE_READY 0x0011 EEPROM Ready -entry WDT_OVERFLOW 0x0012 Watchdog Timer Overflow -entry PCINT1 0x0013 Pin Change Interrupt Request 1 -entry PCINT2 0x0014 Pin Change Interrupt Request 2 - - -; INPUT/OUTPUT PORTS -USIBR 0x0000 USI Buffer Register -DIDR 0x0001 Digital Input Disable Register -DIDR.AIND0 1 AIN0 Digital Input Disable -DIDR.AIND1 2 AIN1 Digital Input Disable -UBRRH 0x0002 USART Baud Rate Registers High -UCSRC 0x0003 USART Control and Status Register C -UCSRC.UMSEL1 7 USART Mode Select 1 -UCSRC.UMSEL0 6 USART Mode Select 0 -UCSRC.UPM1 5 Parity Mode 1 -UCSRC.UPM0 4 Parity Mode 0 -UCSRC.USBS 3 Stop Bit Select -UCSRC.UCSZ1 2 Character Size 1 -UCSRC.UCSZ0 1 Character Size 0 -UCSRC.UCPOL 0 Clock Polarity -PCMSK1 0x0004 Pin Change Mask Register 1 -PCMSK1.PCINT10 2 Pin Change Enable Mask 10 -PCMSK1.PCINT9 1 Pin Change Enable Mask 9 -PCMSK1.PCINT8 0 Pin Change Enable Mask 8 -PCMSK2 0x0005 Pin Change Mask Register 2 -PCMSK2.PCINT17 6 Pin Change Enable Mask 17 -PCMSK2.PCINT16 5 Pin Change Enable Mask 16 -PCMSK2.PCINT15 4 Pin Change Enable Mask 15 -PCMSK2.PCINT14 3 Pin Change Enable Mask 14 -PCMSK2.PCINT13 2 Pin Change Enable Mask 13 -PCMSK2.PCINT12 1 Pin Change Enable Mask 12 -PCMSK2.PCINT11 0 Pin Change Enable Mask 11 -PRR 0x0006 Power Reduction Register -PRR.PRTIM1 3 Power Reduction Timer/Counter1 -PRR.PRTIM0 2 Power Reduction Timer/Counter0 -PRR.PRUSI 1 Power Reduction USI -PRR.PRUSART 0 Power Reduction USART -BODCR 0x0007 Brown-Out Detector Control Register -BODCR.BODS 1 BOD Sleep -BODCR.BODSE 0 BOD Sleep Enable -ACSR 0x0008 Analog Comparator Control and Status Register -ACSR.ACD 7 Analog Comparator Disable -ACSR.ACBG 6 Analog Comparator Bandgap Select -ACSR.ACO 5 Analog Comparator Output -ACSR.ACI 4 Analog Comparator Interrupt Flag -ACSR.ACIE 3 Analog Comparator Interrupt Enable -ACSR.ACIC 2 Analog Comparator Input Capture Enable -ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 -ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 -UBRRL 0x0009 USART Baud Rate Register -UBRRL.UBRR7 7 -UBRRL.UBRR6 6 -UBRRL.UBRR5 5 -UBRRL.UBRR4 4 -UBRRL.UBRR3 3 -UBRRL.UBRR2 2 -UBRRL.UBRR1 1 -UBRRL.UBRR0 0 -UCSRB 0x000A USART Control and Status Register -UCSRB.RXCIE 7 RX Complete Interrupt Enable -UCSRB.TXCIE 6 TX Complete Interrupt Enable -UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable -UCSRB.RXEN 4 Receiver Enable -UCSRB.TXEN 3 Transmitter Enable -UCSRB.UCSZ2 2 Character Size -UCSRB.RXB8 1 Receive Data Bit 8 -UCSRB.TXB8 0 Transmit Data Bit8 -UCSRA 0x000B USART Control and Status Register -UCSRA.RXC 7 USART Receive Complete -UCSRA.TXC 6 USART Transmit Complete -UCSRA.UDRE 5 USART Data Register Empty -UCSRA.FE 4 Frame Error -UCSRA.DOR 3 Data OverRun -UCSRA.UPE 2 Parity Error -UCSRA.U2X 1 Double the USART Transmission Speed -UCSRA.MPCM 0 Multi-Processor Communication Mode -UDR 0x000C USART I/O Data Register -USICR 0x000D USI Control Register -USICR.USISIE 7 Start Condition Interrupt Enable -USICR.USIOIE 6 Counter Overflow Interrupt Enable -USICR.USIWM1 5 Wire Mode 1 -USICR.USIWM0 4 Wire Mode 0 -USICR.USICS1 3 Clock Source Select 1 -USICR.USICS0 2 Clock Source Select 0 -USICR.USICLK 1 Clock Strobe -USICR.USITC 0 Toggle Clock Port Pin -USISR 0x000E USI Status Register -USISR.USISIF 7 Start Condition Interrupt Flag -USISR.USIOIF 6 Counter Overflow Interrupt Flag -USISR.USIPF 5 Stop Condition Flag -USISR.USIDC 4 Data Output Collision -USISR.USICNT3 3 Counter Value 3 -USISR.USICNT2 2 Counter Value 2 -USISR.USICNT1 1 Counter Value 1 -USISR.USICNT0 0 Counter Value 0 -USIDR 0x000F USI Data Register -PIND 0x0010 Port D Input Pins Address -PIND.PIND7 7 -PIND.PIND6 6 -PIND.PIND5 5 -PIND.PIND4 4 -PIND.PIND3 3 -PIND.PIND2 2 -PIND.PIND1 1 -PIND.PIND0 0 -DDRD 0x0011 Port D Data Direction Register -DDRD.DDD7 7 Port D Data Direction Register bit 7 -DDRD.DDD6 6 Port D Data Direction Register bit 6 -DDRD.DDD5 5 Port D Data Direction Register bit 5 -DDRD.DDD4 4 Port D Data Direction Register bit 4 -DDRD.DDD3 3 Port D Data Direction Register bit 3 -DDRD.DDD2 2 Port D Data Direction Register bit 2 -DDRD.DDD1 1 Port D Data Direction Register bit 1 -DDRD.DDD0 0 Port D Data Direction Register bit 0 -PORTD 0x0012 Port D Data Register -PORTD.PORTD7 7 Port D Data Register bit 7 -PORTD.PORTD6 6 Port D Data Register bit 6 -PORTD.PORTD5 5 Port D Data Register bit 5 -PORTD.PORTD4 4 Port D Data Register bit 4 -PORTD.PORTD3 3 Port D Data Register bit 3 -PORTD.PORTD2 2 Port D Data Register bit 2 -PORTD.PORTD1 1 Port D Data Register bit 1 -PORTD.PORTD0 0 Port D Data Register bit 0 -GPIOR0 0x0013 General Purpose I/O Register 0 -GPIOR1 0x0014 General Purpose I/O Register 0 -GPIOR2 0x0015 General Purpose I/O Register 0 -PINB 0x0016 Port B Input Pins Address -PINB.PINB7 7 -PINB.PINB6 6 -PINB.PINB5 5 -PINB.PINB4 4 -PINB.PINB3 3 -PINB.PINB2 2 -PINB.PINB1 1 -PINB.PINB0 0 -DDRB 0x0017 Port B Data Direction Register -DDRB.DDB7 7 Port B Data Direction Register bit 7 -DDRB.DDB6 6 Port B Data Direction Register bit 6 -DDRB.DDB5 5 Port B Data Direction Register bit 5 -DDRB.DDB4 4 Port B Data Direction Register bit 4 -DDRB.DDB3 3 Port B Data Direction Register bit 3 -DDRB.DDB2 2 Port B Data Direction Register bit 2 -DDRB.DDB1 1 Port B Data Direction Register bit 1 -DDRB.DDB0 0 Port B Data Direction Register bit 0 -PORTB 0x0018 Port B Data Register -PORTB.PORTB7 7 Port B Data Register bit 7 -PORTB.PORTB6 6 Port B Data Register bit 6 -PORTB.PORTB5 5 Port B Data Register bit 5 -PORTB.PORTB4 4 Port B Data Register bit 4 -PORTB.PORTB3 3 Port B Data Register bit 3 -PORTB.PORTB2 2 Port B Data Register bit 2 -PORTB.PORTB1 1 Port B Data Register bit 1 -PORTB.PORTB0 0 Port B Data Register bit 0 -PINA 0x0019 Port A Input Pins Address -PINA.PINA7 7 -PINA.PINA6 6 -PINA.PINA5 5 -PINA.PINA4 4 -PINA.PINA3 3 -PINA.PINA2 2 -PINA.PINA1 1 -PINA.PINA0 0 -DDRA 0x001A Port A Data Direction Register -DDRA.DDA7 7 Port A Data Direction Register bit 7 -DDRA.DDA6 6 Port A Data Direction Register bit 6 -DDRA.DDA5 5 Port A Data Direction Register bit 5 -DDRA.DDA4 4 Port A Data Direction Register bit 4 -DDRA.DDA3 3 Port A Data Direction Register bit 3 -DDRA.DDA2 2 Port A Data Direction Register bit 2 -DDRA.DDA1 1 Port A Data Direction Register bit 1 -DDRA.DDA0 0 Port A Data Direction Register bit 0 -PORTA 0x001B Port A Data Register -PORTA.PORTA7 7 Port A Data Register bit 7 -PORTA.PORTA6 6 Port A Data Register bit 6 -PORTA.PORTA5 5 Port A Data Register bit 5 -PORTA.PORTA4 4 Port A Data Register bit 4 -PORTA.PORTA3 3 Port A Data Register bit 3 -PORTA.PORTA2 2 Port A Data Register bit 2 -PORTA.PORTA1 1 Port A Data Register bit 1 -PORTA.PORTA0 0 Port A Data Register bit 0 -EECR 0x001C EEPROM Control Register -EECR.EERIE 3 EEPROM Ready Interrupt Enable -EECR.EEMWE 2 EEPROM Master Write Enable -EECR.EEWE 1 EEPROM Write Enable -EECR.EERE 0 EEPROM Read Enable -EEDR 0x001D EEPROM Data Register -EEAR 0x001E EEPROM Address Register -EEAR.EEAR7 7 -EEAR.EEAR6 6 -EEAR.EEAR5 5 -EEAR.EEAR4 4 -EEAR.EEAR3 3 -EEAR.EEAR2 2 -EEAR.EEAR1 1 -EEAR.EEAR0 0 -RESERVED001F 0x001F RESERVED -PCMSK0 0x0020 Pin Change Mask Register 0 -PCMSK0.PCINT7 7 Pin Change Enable Mask 7 -PCMSK0.PCINT6 6 Pin Change Enable Mask 6 -PCMSK0.PCINT5 5 Pin Change Enable Mask 5 -PCMSK0.PCINT4 4 Pin Change Enable Mask 4 -PCMSK0.PCINT3 3 Pin Change Enable Mask 3 -PCMSK0.PCINT2 2 Pin Change Enable Mask 2 -PCMSK0.PCINT1 1 Pin Change Enable Mask 1 -PCMSK0.PCINT0 0 Pin Change Enable Mask 0 -WDTCSR 0x0021 Watchdog Timer Control Register -WDTCSR.WDIF 7 Watchdog Interrupt Flag -WDTCSR.WDIE 6 Watchdog Interrupt Enable -WDTCSR.WDP3 5 Watchdog Timer Prescaler 3 -WDTCSR.WDCE 4 Watchdog Change Enable -WDTCSR.WDE 3 Watchdog Enable -WDTCSR.WDP2 2 Watchdog Timer Prescaler 2 -WDTCSR.WDP1 1 Watchdog Timer Prescaler 1 -WDTCSR.WDP0 0 Watchdog Timer Prescaler 0 -TCCR1C 0x0022 Timer/Counter1 Control Register C -TCCR1C.FOC1A 7 Force Output Compare for Channel A -TCCR1C.FOC1B 6 Force Output Compare for Channel B -GTCCR 0x0023 General Timer/Counter Control Register -GTCCR.PSR10 1 Prescaler Reset Timer/Counter1 and Timer/Counter0 -ICR1L 0x0024 Input Capture Register Low Byte -ICR1H 0x0025 Input Capture Register High Byte -CLKPR 0x0026 Clock Prescale Register -CLKPR.CPCE 7 Clock Prescaler Change Enable -CLKPR.CLKPS3 3 Clock Prescaler Select Bit 3 -CLKPR.CLKPS2 2 Clock Prescaler Select Bit 2 -CLKPR.CLKPS1 1 Clock Prescaler Select Bit 1 -CLKPR.CLKPS0 0 Clock Prescaler Select Bit 0 -RESERVED0027 0x0027 RESERVED -OCR1BL 0x0028 Output Compare Register B Low Byte -OCR1BH 0x0029 Output Compare Register B High Byte -OCR1AL 0x002A Output Compare Register A Low Byte -OCR1AH 0x002B Output Compare Register A High Byte -TCNT1L 0x002C Counter Register Low Byte -TCNT1H 0x002D Counter Register High Byte -TCCR1B 0x002E Timer/Counter1 Control Register B -TCCR1B.ICNC1 7 Input Capture Noise Canceler -TCCR1B.ICES1 6 Input CaptureEdgeSelect -TCCR1B.WGM13 4 Waveform Generation Mode 3 -TCCR1B.WGM12 3 Waveform Generation Mode 2 -TCCR1B.CS12 2 Clock Select 2 -TCCR1B.CS11 1 Clock Select 1 -TCCR1B.CS10 0 Clock Select 0 -TCCR1A 0x002F Timer/Counter1 Control Register A -TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 -TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 -TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 -TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 -TCCR1A.WGM11 1 Waveform Generation Mode 1 -TCCR1A.WGM10 0 Waveform Generation Mode 0 -TCCR0A 0x0030 Timer/Counter0 Control Register A -TCCR0A.COM0A1 7 Compare Output Mode for Channel A 1 -TCCR0A.COM0A0 6 Compare Output Mode for Channel A 0 -TCCR0A.COM0B1 5 Compare Output Mode for Channel B 1 -TCCR0A.COM0B0 4 Compare Output Mode for Channel B 0 -TCCR0A.WGM01 1 Waveform Generation Mode 1 -TCCR0A.WGM00 0 Waveform Generation Mode 0 -OSCCAL 0x0031 Oscillator Calibration Register -OSCCAL.CAL6 6 Oscillator Calibration Value 6 -OSCCAL.CAL5 5 Oscillator Calibration Value 5 -OSCCAL.CAL4 4 Oscillator Calibration Value 4 -OSCCAL.CAL3 3 Oscillator Calibration Value 3 -OSCCAL.CAL2 2 Oscillator Calibration Value 2 -OSCCAL.CAL1 1 Oscillator Calibration Value 1 -OSCCAL.CAL0 0 Oscillator Calibration Value 0 -TCNT0 0x0032 Timer/Counter0 -TCCR0B 0x0033 Timer/Counter Control Register -TCCR0B.FOC0A 7 Force Output Compare A -TCCR0B.FOC0B 6 Force Output Compare B -TCCR0B.WGM02 3 Waveform Generation Mode -TCCR0B.CS02 2 Clock Select 2 -TCCR0B.CS01 1 Clock Select 1 -TCCR0B.CS00 0 Clock Select 0 -MCUCSR 0x0034 MCU Control and Status Register -MCUCSR.WDRF 3 Watchdog Reset Flag -MCUCSR.BORF 2 Brown-out Reset Flag -MCUCSR.EXTRF 1 External Reset Flag -MCUCSR.PORF 0 Power-On Reset Flag -MCUCR 0x0035 MCU Control Register -MCUCR.PUD 7 Pull-up Disable -MCUCR.SM1 6 Sleep Mode Select Bit 1 -MCUCR.SE 5 SleepEnable -MCUCR.SM0 4 Sleep Mode Select Bit 0 -MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 -MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 -MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 -MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 -OCR0A 0x0036 Timer/Counter0 Compare Register A -SPMCSR 0x0037 Store Program Memory Control Register -SPMCSR.RSIG 5 Read Device Signature Imprint Table -SPMCSR.CTPB 4 Clear Temporary Page Buffer -SPMCSR.RFLB 3 Read Fuse and Lock Bits -SPMCSR.PGWRT 2 Page Write -SPMCSR.PGERS 1 Page Erase -SPMCSR.SPMEN 0 Self Programming Enable -TIFR 0x0038 Timer/Counter Interrupt Flag Register -TIFR.TOV1 7 Timer/Counter1 Overflow Flag -TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag -TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag -TIFR.ICF1 3 Timer/Counter1, Input Capture Flag -TIFR.OCF0B 2 Timer/Counter0, Output Compare B Match Flag -TIFR.TOV0 1 Timer/Counter0 Overflow Flag -TIFR.OCF0A 0 Timer/Counter0, Output Compare A Match Flag -TIMSK 0x0039 Timer/Counter Interrupt Mask Register -TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable -TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable -TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable -TIMSK.ICIE1 3 Timer/Counter1, Input Capture Interrupt Enable -TIMSK.OCIE0A 2 Timer/Counter0, Output Compare A Match Interrupt Enable -TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable -TIMSK.OCIE0B 0 Timer/Counter0, Output Compare B Match Interrupt Enable -EIFR 0x003A External Interrupt Flag Register -EIFR.INTF1 7 External Interrupt Flag 1 -EIFR.INTF0 6 External Interrupt Flag 0 -EIFR.PCIF0 5 Pin Change Interrupt Flag 0 -EIFR.PCIF2 4 Pin Change Interrupt Flag 2 -EIFR.PCIF1 3 Pin Change Interrupt Flag 1 -GIMSK 0x003B External Interrupt Mask Register -GIMSK.INT1 7 External Interrupt Request 1 Enable -GIMSK.INT0 6 External Interrupt Request 0 Enable -GIMSK.PCIE0 5 Pin Change Interrupt Request Enable 0 -GIMSL.PCIE2 4 Pin Change Interrupt Request Enable 2 -GIMSL.PCIE1 3 Pin Change Interrupt Request Enable 1 -OCR0B 0x003C Output Compare Register B Low Byte -SPL 0x003D Stack Pointer Register Low -SPL.SP7 7 -SPL.SP6 6 -SPL.SP5 5 -SPL.SP4 4 -SPL.SP3 3 -SPL.SP2 2 -SPL.SP1 1 -SPL.SP0 0 -RESERVED003E 0x003E RESERVED -SREG 0x003F Status Register -SREG.I 7 Global Interrupt Enable -SREG.T 6 Bit Copy Storage -SREG.H 5 Half Carry Flag -SREG.S 4 Sign Bit -SREG.V 3 Two's Complement Overflow Flag -SREG.N 2 Negative Flag -SREG.Z 1 Zero Flag -SREG.C 0 CarryFlag diff --git a/idasdk75/module/avr/avr.hpp b/idasdk75/module/avr/avr.hpp deleted file mode 100644 index a45fd0a..0000000 --- a/idasdk75/module/avr/avr.hpp +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#ifndef _AVR_HPP -#define _AVR_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include <fixup.hpp> -#include "../iohandler.hpp" - -//--------------------------------- -// Operand types: - -enum phrase_t ENUM_SIZE(uint16) -{ - PH_X, // X - PH_XPLUS, // X+ - PH_MINUSX, // -X - PH_Y, // Y - PH_YPLUS, // Y+ - PH_MINUSY, // -Y - PH_Z, // Z - PH_ZPLUS, // Z+ - PH_MINUSZ, // -Z -}; - - -#define o_port o_idpspec0 // port number in x.addr - -//------------------------------------------------------------------ -enum RegNo -{ - R0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, R11, R12, R13, R14, R15, - R16, R17, R18, R19, R20, R21, R22, R23, - R24, R25, R26, R27, R28, R29, R30, R31, - rVcs, rVds, // virtual registers for code and data segments -}; - -//------------------------------------------------------------------ -void idaapi avr_segend(outctx_t &ctx, segment_t *seg); -void idaapi avr_assumes(outctx_t &ctx); // function to produce assume directives - -int idaapi is_align_insn(ea_t ea); - -//------------------------------------------------------------------ -struct avr_iohandler_t : public iohandler_t -{ - struct avr_t ± - avr_iohandler_t(avr_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual const char *iocallback(const ioports_t &iop, const char *line) override; - virtual bool entry_processing(ea_t &, const char * /*word*/, const char * /*cmt*/) override; - virtual bool check_ioresp() const override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct avr_t); - -struct avr_t : public procmod_t -{ - netnode helper; - avr_iohandler_t ioh = avr_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - //-------------------------------------------------------------------------- - // not tested - fixup_handler_t cfh_avr16 = - { - sizeof(fixup_handler_t), - "AVR16", // Format name, must be unique - 0, // props - 2, 16, 0, 0, // size, width, shift - REFINFO_CUSTOM, // reftype - nullptr, // apply, will be inited in processor_t::ev_init - NULL, // get_value - NULL, // patch_value - }; - fixup_type_t cfh_avr16_id = 0; - int ref_avr16_id = 0; - - int subarch = 0; - - // memory configuration - ea_t ram = BADADDR; - uint32 ramsize = 0; - uint32 romsize = 0; - uint32 eepromsize = 0; - - bool imageFile = false; - bool nonBinary = false; - - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const ioport_t *find_port(ea_t address); - const char *find_bit(ea_t address, size_t bit); - void setup_avr_device(int resp_info); - const char *set_idp_options( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded); - bool set_param_by_arch(void); - bool is_possible_subarch(int addr) const; - - void handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload); - int emu(const insn_t &insn); - - void avr_header(outctx_t &ctx); - - inline void opimm(const insn_t &insn, op_t &x, int value) const; - inline uint32 code_address(const insn_t &insn, signed int delta) const; - int ana(insn_t *_insn); - - void avr_segstart(outctx_t &ctx, segment_t *Sarea) const; - void avr_footer(outctx_t &ctx) const; -}; -extern int data_id; - -#endif // _AVR_HPP diff --git a/idasdk75/module/avr/emu.cpp b/idasdk75/module/avr/emu.cpp deleted file mode 100644 index 7cd3fd2..0000000 --- a/idasdk75/module/avr/emu.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#include "avr.hpp" - -//------------------------------------------------------------------------ -static void set_immd_bit(const insn_t &insn, int n) -{ - set_immd(insn.ea); - if ( is_defarg(get_flags(insn.ea), n) ) - return; - switch ( insn.itype ) - { - case AVR_andi: - case AVR_ori: - op_num(insn.ea, n); - } -} - -//---------------------------------------------------------------------- -void avr_t::handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload) -{ - switch ( x.type ) - { - case o_reg: - case o_phrase: - break; - case o_imm: - if ( !isload ) - goto WRONG_CALL; - set_immd_bit(insn, x.n); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, dr_O, OOF_SIGNED); - break; - case o_displ: - set_immd_bit(insn, x.n); - if ( !isAlt && op_adds_xrefs(get_flags(insn.ea), x.n) ) - { - ea_t ea = insn.add_off_drefs(x, isload ? dr_R : dr_W, OOF_ADDR); - if ( ea != BADADDR ) - insn.create_op_data(ea, x); - } - break; - case o_near: - { - cref_t ftype = fl_JN; - ea_t ea = to_ea(insn.cs, x.addr); - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - if ( !func_does_return(ea) ) - flow = false; - ftype = fl_CN; - } - insn.add_cref(ea, x.offb, ftype); - } - break; - case o_port: - if ( ram != BADADDR ) - { - ea_t ea = ram + x.addr + 0x20; - if ( x.type == o_port ) - { // verify that the calculated address corresponds the register name - const ioport_t *port = find_port(x.addr); - if ( port == NULL || port->name.empty() ) - break; - ea_t rev = get_name_ea(BADADDR, port->name.c_str()); - if ( rev != ea ) - break; - } - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - } - break; - case o_mem: - { - ea_t ea = map_data_ea(insn, x); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - } - break; - default: -WRONG_CALL: - if ( insn.itype != AVR_lpm && insn.itype != AVR_elpm ) - warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); - break; - } -} - -//---------------------------------------------------------------------- -static bool may_be_skipped(const insn_t &insn) -{ - ea_t ea = insn.ea - 1; - if ( is_code(get_flags(ea)) ) - { - int code = get_wide_byte(ea); - switch ( code & 0xFC00 ) - { -// 0001 00rd dddd rrrr cpse rd, rr 4 Compare, Skip if Equal - case 0x1000: -// 1111 110r rrrr xbbb sbrc rr, b Skip if Bit in I/O Register Cleared -// 1111 111r rrrr xbbb sbrs rr, b Skip if Bit in I/O Register Set - case 0xFC00: - return true; -// 1001 1001 pppp pbbb sbic p, b Skip if Bit in Register Cleared -// 1001 1011 pppp pbbb sbis p, b Skip if Bit in Register Set - case 0x9800: - return (code & 0x0100) != 0; - } - } - return false; -} - -//---------------------------------------------------------------------- - -int avr_t::emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - bool flag1 = is_forced_operand(insn.ea, 0); - bool flag2 = is_forced_operand(insn.ea, 1); - bool flag3 = is_forced_operand(insn.ea, 2); - - flow = (Feature & CF_STOP) == 0; - - if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true); - if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true); - if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true); - - if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false); - if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false); - if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false); - -// -// Determine if the next instruction should be executed -// - if ( !flow ) - flow = may_be_skipped(insn); - if ( segtype(insn.ea) == SEG_XTRN ) - flow = false; - if ( flow ) - add_cref(insn.ea,insn.ea+insn.size, fl_F); - - return 1; -} - -//---------------------------------------------------------------------- -int idaapi is_align_insn(ea_t ea) -{ - insn_t insn; - decode_insn(&insn, ea); - switch ( insn.itype ) - { - case AVR_mov: - if ( insn.Op1.reg == insn.Op2.reg ) - break; - default: - return 0; - case AVR_nop: - break; - } - return insn.size; -} diff --git a/idasdk75/module/avr/ins.cpp b/idasdk75/module/avr/ins.cpp deleted file mode 100644 index a2e3707..0000000 --- a/idasdk75/module/avr/ins.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#include "avr.hpp" - -const instruc_t Instructions[] = -{ - - { "", 0 }, // Unknown Operation - - // ARITHMETIC AND LOGIC INSTRUCTIONS - { "add", CF_USE1|CF_USE2|CF_CHG1 }, // Add without Carry - { "adc", CF_USE1|CF_USE2|CF_CHG1 }, // Add with Carry - { "adiw", CF_USE1|CF_USE2|CF_CHG1 }, // Add Immediate to Word - { "sub", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract without Carry - { "subi", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract Immediate - { "sbc", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract with Carry - { "sbci", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract Immediate with Carry - { "sbiw", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract Immediate from Word - { "and", CF_USE1|CF_USE2|CF_CHG1 }, // Logical AND - { "andi", CF_USE1|CF_USE2|CF_CHG1 }, // Logical AND with Immediate - { "or", CF_USE1|CF_USE2|CF_CHG1 }, // Logical OR - { "ori", CF_USE1|CF_USE2|CF_CHG1 }, // Logical OR with Immediate - { "eor", CF_USE1|CF_USE2|CF_CHG1 }, // Exclusive OR - { "com", CF_USE1| CF_CHG1 }, // One's Complement - { "neg", CF_USE1| CF_CHG1 }, // Two's Complement - { "sbr", CF_USE1|CF_USE2|CF_CHG1 }, // Set Bit(s) in Register - { "cbr", CF_USE1|CF_USE2|CF_CHG1 }, // Clear Bit(s) in Register - { "inc", CF_USE1| CF_CHG1 }, // Increment - { "dec", CF_USE1| CF_CHG1 }, // Decrement - { "tst", CF_USE1| CF_CHG1 }, // Test for Zero or Minus - { "clr", CF_CHG1 }, // Clear Register - { "ser", CF_CHG1 }, // Set Register - { "cp", CF_USE1|CF_USE2 }, // Compare - { "cpc", CF_USE1|CF_USE2 }, // Compare with Carry - { "cpi", CF_USE1|CF_USE2 }, // Compare with Immediate - { "mul", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply - - // BRANCH INSTRUCTIONS - { "rjmp", CF_USE1|CF_STOP }, // Relative Jump - { "ijmp", CF_STOP|CF_JUMP }, // Indirect Jump to (Z) - { "jmp", CF_USE1|CF_STOP }, // Jump - { "rcall", CF_USE1 |CF_CALL }, // Relative Call Subroutine - { "icall", CF_JUMP|CF_CALL }, // Indirect Call to (Z) - { "call", CF_USE1 |CF_CALL }, // Call Subroutine - { "ret", CF_STOP }, // Subroutine Return - { "reti", CF_STOP }, // Interrupt Return - { "cpse", CF_USE1|CF_USE2 }, // Compare", Skip if Equal - { "sbrc", CF_USE1|CF_USE2 }, // Skip if Bit in Register Cleared - { "sbrs", CF_USE1|CF_USE2 }, // Skip if Bit in Register Set - { "sbic", CF_USE1|CF_USE2 }, // Skip if Bit in I/O Register Cleared - { "sbis", CF_USE1|CF_USE2 }, // Skip if Bit in I/O Register Set - { "brbs", CF_USE1|CF_USE2 }, // Branch if Status Flag Set - { "brbc", CF_USE1|CF_USE2 }, // Branch if Status Flag Cleared - { "breq", CF_USE1 }, // Branch if Equal - { "brne", CF_USE1 }, // Branch if Not Equal - { "brcs", CF_USE1 }, // Branch if Carry Set - { "brcc", CF_USE1 }, // Branch if Carry Cleared - { "brsh", CF_USE1 }, // Branch if Same or Higher - { "brlo", CF_USE1 }, // Branch if Lower - { "brmi", CF_USE1 }, // Branch if Minus - { "brpl", CF_USE1 }, // Branch if Plus - { "brge", CF_USE1 }, // Branch if Greater or Equal - { "brlt", CF_USE1 }, // Branch if Less Than - { "brhs", CF_USE1 }, // Branch if Half Carry Flag Set - { "brhc", CF_USE1 }, // Branch if Half Carry Flag Cleared - { "brts", CF_USE1 }, // Branch if T Flag Set - { "brtc", CF_USE1 }, // Branch if T Flag Cleared - { "brvs", CF_USE1 }, // Branch if Overflow Flag is Set - { "brvc", CF_USE1 }, // Branch if Overflow Flag is Cleared - { "brie", CF_USE1 }, // Branch if Interrupt Enabled - { "brid", CF_USE1 }, // Branch if Interrupt Disabled - - // DATA TRANSFER INSTRUCTIONS - { "mov", CF_CHG1|CF_USE2 }, // Copy Register - { "ldi", CF_CHG1|CF_USE2 }, // Load Immediate - { "lds", CF_CHG1|CF_USE2 }, // Load Direct - { "ld", CF_CHG1|CF_USE2 }, // Load Indirect - { "ldd", CF_CHG1|CF_USE2 }, // Load Indirect with Displacement - { "sts", CF_CHG1|CF_USE2 }, // Store Direct to SRAM - { "st", CF_USE1|CF_USE2 }, // Store Indirect - { "std", CF_USE1|CF_USE2 }, // Store Indirect with Displacement - { "lpm", CF_USE1|CF_USE2|CF_CHG1 }, // Load Program Memory - { "in", CF_CHG1|CF_USE2 }, // In Port - { "out", CF_USE1|CF_USE2 }, // Out Port - { "push", CF_USE1 }, // Push Register on Stack - { "pop", CF_CHG1 }, // Pop Register from Stack - - // BIT AND BIT-TEST INSTRUCTIONS - { "lsl", CF_USE1|CF_CHG1 }, // Logical Shift Left - { "lsr", CF_USE1|CF_CHG1 }, // Logical Shift Right - { "rol", CF_USE1|CF_CHG1 }, // Rotate Left Through Carry - { "ror", CF_USE1|CF_CHG1 }, // Rotate Right Through Carry - { "asr", CF_USE1|CF_CHG1 }, // Arithmetic Shift Right - { "swap", CF_USE1|CF_CHG1 }, // Swap Nibbles - { "bset", CF_USE1 }, // Flag Set - { "bclr", CF_USE1 }, // Flag Clear - { "sbi", CF_USE1|CF_USE2 }, // Set Bit in I/O Register - { "cbi", CF_USE1|CF_USE2 }, // Clear Bit in I/O Register - { "bst", CF_USE1|CF_USE2 }, // Bit Store from Register to T - { "bld", CF_USE1|CF_USE2 }, // Bit load from T to Register - { "sec", 0 }, // Set Carry - { "clc", 0 }, // Clear Carry - { "sen", 0 }, // Set Negative Flag - { "cln", 0 }, // Clear Negative Flag - { "sez", 0 }, // Set Zero Flag - { "clz", 0 }, // Clear Zero Flag - { "sei", 0 }, // Global Interrupt Enable - { "cli", 0 }, // Global Interrupt Disable - { "ses", 0 }, // Set Signed Test Flag - { "cls", 0 }, // Clear Signed Test Flag - { "sev", 0 }, // Set Two's Complement Overflow - { "clv", 0 }, // Clear Two's Complement Overflow - { "set", 0 }, // Set T in SREG - { "clt", 0 }, // Clear T in SREG - { "seh", 0 }, // Set Half Carry Flag in SREG - { "clh", 0 }, // Clear Half Carry Flag in SREG - { "nop", 0 }, // No Operation - { "sleep", 0 }, // Sleep - { "wdr", 0 }, // Watchdog Reset - - // New MegaAVR instructions - { "elpm", CF_USE2|CF_CHG1 }, // Extended Load Program Memory - { "espm", 0 }, // Extended Store Program Memory - { "fmul", CF_USE1|CF_USE2|CF_CHG1 }, // Fractional Multiply Unsigned - { "fmuls", CF_USE1|CF_USE2|CF_CHG1 }, // Fractional Multiply Signed - { "fmulsu", CF_USE1|CF_USE2|CF_CHG1 }, // Fractional Multiply Signed with Unsigned - { "movw", CF_USE1|CF_USE2|CF_CHG1 }, // Copy Register Word - { "muls", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply Signed - { "mulsu", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply Signed with Unsigned - { "spm", 0 }, // Store Program Memory - { "eicall", 0 }, // Extended Indirect Call to Subroutine - { "eijmp", 0 }, // Extended Indirect Jump - { "des", CF_USE1|CF_USE2|CF_CHG1 }, // Data Encryption Standard - { "lac", CF_USE1|CF_USE2|CF_CHG1 }, // Load And Clear - { "las", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Load And Set - { "lat", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Load And Toggle - { "xch", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Exchange -}; - -CASSERT(qnumber(Instructions) == AVR_last); diff --git a/idasdk75/module/avr/ins.hpp b/idasdk75/module/avr/ins.hpp deleted file mode 100644 index 7c36163..0000000 --- a/idasdk75/module/avr/ins.hpp +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - -AVR_null = 0, // Unknown Operation - -// ARITHMETIC AND LOGIC INSTRUCTIONS -AVR_add, // Add without Carry -AVR_adc, // Add with Carry -AVR_adiw, // Add Immediate to Word -AVR_sub, // Subtract without Carry -AVR_subi, // Subtract Immediate -AVR_sbc, // Subtract with Carry -AVR_sbci, // Subtract Immediate with Carry -AVR_sbiw, // Subtract Immediate from Word -AVR_and, // Logical AND -AVR_andi, // Logical AND with Immediate -AVR_or, // Logical OR -AVR_ori, // Logical OR with Immediate -AVR_eor, // Exclusive OR -AVR_com, // One's Complement -AVR_neg, // Two's Complement -AVR_sbr, // Set Bit(s) in Register -AVR_cbr, // Clear Bit(s) in Register -AVR_inc, // Increment -AVR_dec, // Decrement -AVR_tst, // Test for Zero or Minus -AVR_clr, // Clear Register -AVR_ser, // Set Register -AVR_cp, // Compare -AVR_cpc, // Compare with Carry -AVR_cpi, // Compare with Immediate -AVR_mul, // Multiply - -// BRANCH INSTRUCTIONS -AVR_rjmp, // Relative Jump -AVR_ijmp, // Indirect Jump to (Z) -AVR_jmp, // Jump -AVR_rcall, // Relative Call Subroutine -AVR_icall, // Indirect Call to (Z) -AVR_call, // Call Subroutine -AVR_ret, // Subroutine Return -AVR_reti, // Interrupt Return -AVR_cpse, // Compare, Skip if Equal -AVR_sbrc, // Skip if Bit in Register Cleared -AVR_sbrs, // Skip if Bit in Register Set -AVR_sbic, // Skip if Bit in I/O Register Cleared -AVR_sbis, // Skip if Bit in I/O Register Set -AVR_brbs, // Branch if Status Flag Set -AVR_brbc, // Branch if Status Flag Cleared -AVR_breq, // Branch if Equal -AVR_brne, // Branch if Not Equal -AVR_brcs, // Branch if Carry Set -AVR_brcc, // Branch if Carry Cleared -AVR_brsh, // Branch if Same or Higher -AVR_brlo, // Branch if Lower -AVR_brmi, // Branch if Minus -AVR_brpl, // Branch if Plus -AVR_brge, // Branch if Greater or Equal -AVR_brlt, // Branch if Less Than -AVR_brhs, // Branch if Half Carry Flag Set -AVR_brhc, // Branch if Half Carry Flag Cleared -AVR_brts, // Branch if T Flag Set -AVR_brtc, // Branch if T Flag Cleared -AVR_brvs, // Branch if Overflow Flag is Set -AVR_brvc, // Branch if Overflow Flag is Cleared -AVR_brie, // Branch if Interrupt Enabled -AVR_brid, // Branch if Interrupt Disabled - -// DATA TRANSFER INSTRUCTIONS -AVR_mov, // Copy Register -AVR_ldi, // Load Immediate -AVR_lds, // Load Direct -AVR_ld, // Load Indirect -AVR_ldd, // Load Indirect with Displacement -AVR_sts, // Store Direct to SRAM -AVR_st, // Store Indirect -AVR_std, // Store Indirect with Displacement -AVR_lpm, // Load Program Memory -AVR_in, // In Port -AVR_out, // Out Port -AVR_push, // Push Register on Stack -AVR_pop, // Pop Register from Stack - -// BIT AND BIT-TEST INSTRUCTIONS -AVR_lsl, // Logical Shift Left -AVR_lsr, // Logical Shift Right -AVR_rol, // Rotate Left Through Carry -AVR_ror, // Rotate Right Through Carry -AVR_asr, // Arithmetic Shift Right -AVR_swap, // Swap Nibbles -AVR_bset, // Flag Set -AVR_bclr, // Flag Clear -AVR_sbi, // Set Bit in I/O Register -AVR_cbi, // Clear Bit in I/O Register -AVR_bst, // Bit Store from Register to T -AVR_bld, // Bit load from T to Register -AVR_sec, // Set Carry -AVR_clc, // Clear Carry -AVR_sen, // Set Negative Flag -AVR_cln, // Clear Negative Flag -AVR_sez, // Set Zero Flag -AVR_clz, // Clear Zero Flag -AVR_sei, // Global Interrupt Enable -AVR_cli, // Global Interrupt Disable -AVR_ses, // Set Signed Test Flag -AVR_cls, // Clear Signed Test Flag -AVR_sev, // Set Two's Complement Overflow -AVR_clv, // Clear Two's Complement Overflow -AVR_set, // Set T in SREG -AVR_clt, // Clear T in SREG -AVR_seh, // Set Half Carry Flag in SREG -AVR_clh, // Clear Half Carry Flag in SREG -AVR_nop, // No Operation -AVR_sleep, // Sleep -AVR_wdr, // Watchdog Reset - -// New MegaAVR instructions - -AVR_elpm, // Extended Load Program Memory -AVR_espm, // Extended Store Program Memory -AVR_fmul, // Fractional Multiply Unsigned -AVR_fmuls, // Fractional Multiply Signed -AVR_fmulsu, // Fractional Multiply Signed with Unsigned -AVR_movw, // Copy Register Word -AVR_muls, // Multiply Signed -AVR_mulsu, // Multiply Signed with Unsigned -AVR_spm, // Store Program Memory -AVR_eicall, // Extended Indirect Call to Subroutine -AVR_eijmp, // Extended Indirect Jump - -// New XMega instructions - -AVR_des, // Data Encryption Standard -AVR_lac, // Load And Clear -AVR_las, // Load And Set -AVR_lat, // Load And Toggle -AVR_xch, // Exchange - -AVR_last, - - }; - -#endif diff --git a/idasdk75/module/avr/makefile b/idasdk75/module/avr/makefile deleted file mode 100644 index 6c81999..0000000 --- a/idasdk75/module/avr/makefile +++ /dev/null @@ -1,49 +0,0 @@ -PROC=avr -CONFIGS=avr.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/elf/elfbase.h ../../ldr/elf/elfr_avr.h \ - ../idaidp.hpp ../iohandler.hpp ana.cpp avr.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp avr.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp avr.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp avr.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ - $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../../ldr/elf/elfbase.h ../../ldr/elf/elfr_avr.h \ - ../idaidp.hpp ../iohandler.hpp avr.hpp ins.hpp \ - notify_codes.hpp reg.cpp diff --git a/idasdk75/module/avr/notify_codes.hpp b/idasdk75/module/avr/notify_codes.hpp deleted file mode 100644 index 4ce5e7d..0000000 --- a/idasdk75/module/avr/notify_codes.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __AVR_NOTIFY_CODES_HPP -#define __AVR_NOTIFY_CODES_HPP - -#include <idp.hpp> - -//---------------------------------------------------------------------- -// The following events are supported by the AVR module in the ph.notify() function -namespace avr_module_t -{ - enum event_codes_t - { - ev_set_machine_type = processor_t::ev_loader, - // elf-loader 'set machine type' and file type - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline void set_machine_type(int subarch, bool image_file) - { - processor_t::notify(idp_ev(ev_set_machine_type), subarch, image_file); - } -} - -#endif // __AVR_NOTIFY_CODES_HPP diff --git a/idasdk75/module/avr/out.cpp b/idasdk75/module/avr/out.cpp deleted file mode 100644 index c814917..0000000 --- a/idasdk75/module/avr/out.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#include "avr.hpp" - -//---------------------------------------------------------------------- -class out_avr_t : public outctx_t -{ - out_avr_t(void) = delete; // not used -public: - void out_phrase(int phn); - void out_bad_address(ea_t addr); - - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_avr_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_avr_t) - -//---------------------------------------------------------------------- -void out_avr_t::out_phrase(int phn) -{ - switch ( phn ) - { - case PH_XPLUS: // X+ - out_register("X"); - out_symbol('+'); - break; - case PH_MINUSX: // -X - out_symbol('-'); - case PH_X: // X - out_register("X"); - break; - case PH_YPLUS: // Y+ - out_register("Y"); - out_symbol('+'); - break; - case PH_MINUSY: // -Y - out_symbol('-'); - case PH_Y: // Y - out_register("Y"); - break; - case PH_ZPLUS: // Z+ - out_register("Z"); - out_symbol('+'); - break; - case PH_MINUSZ: // -Z - out_symbol('-'); - case PH_Z: // Z - out_register("Z"); - break; - default: - error("%a: bad phrase number", insn.ea); - } -} - -//---------------------------------------------------------------------- -void out_avr_t::out_bad_address(ea_t addr) -{ - out_tagon(COLOR_ERROR); - out_btoa(addr, 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); -} - -//---------------------------------------------------------------------- -bool out_avr_t::out_operand(const op_t &x) -{ - avr_t &pm = *static_cast<avr_t *>(procmod); - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - if ( pm.ram != BADADDR ) - { - qstring name; - if ( get_visible_name(&name, pm.ram+x.reg) > 0 ) - { - out_register(name.begin()); - break; - } - } - out_register(ph.reg_names[x.reg]); - break; - - case o_imm: - { - if ( insn.itype == AVR_cbi - || insn.itype == AVR_sbic - || insn.itype == AVR_sbi - || insn.itype == AVR_sbis ) - { - const char *bit = pm.find_bit(insn.Op1.addr, (size_t)x.value); - if ( bit != NULL && bit[0] != '\0' ) - { - out_line(bit, COLOR_REG); - break; - } - } - if ( x.specflag1 && is_off1(F) && !is_invsign(insn.ea, F, 1) ) - out_symbol('-'); - int flags = OOFS_IFSIGN|OOFW_8; - if ( insn.itype == AVR_subi || insn.itype == AVR_sbci ) - flags |= OOF_SIGNED; - out_value(x, flags); - } - break; - - case o_near: - { - ea_t ea = to_ea(insn.cs, x.addr); - if ( !out_name_expr(x, ea, x.addr) ) - out_bad_address(x.addr); - } - break; - - case o_mem: - { - ea_t ea = map_data_ea(insn, x); - if ( !out_name_expr(x, ea, x.addr) ) - out_bad_address(x.addr); - } - break; - - case o_phrase: - out_phrase(x.phrase); - break; - - case o_displ: - out_phrase(x.phrase); - out_value(x, OOF_ADDR|OOFS_NEEDSIGN|OOFW_IMM); - break; - - case o_port: - { - const ioport_t *port = pm.find_port(x.addr); - if ( port != NULL && !port->name.empty() ) - out_register(port->name.c_str()); - else - out_bad_address(x.addr); - } - break; - - default: - warning("out: %a: bad optype %d", insn.ea, x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -void out_avr_t::out_insn(void) -{ - avr_t &pm = *static_cast<avr_t *>(procmod); - // output .org for enties without any labels - if ( !has_any_name(F) && pm.helper.altval_ea(insn.ea) ) - { - char buf[MAXSTR]; - btoa(buf, sizeof(buf), insn.ip); - int saved_flags = forbid_annotations(); - gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - restore_ctxflags(saved_flags); - } - - out_mnemonic(); - - out_one_operand(0); - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Sarea) could be made const -void avr_t::avr_segstart(outctx_t &ctx, segment_t *Sarea) const -{ - if ( is_spec_segm(Sarea->type) ) - return; - qstring sname; - qstring sclas; - get_visible_segm_name(&sname, Sarea); - get_segm_class(&sclas, Sarea); - ctx.gen_printf(0, - COLSTR("%s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), - sclas == "CODE" - ? ".CSEG" - : sclas == "DATA" - ? ".DSEG" - : ".ESEG", - ash.cmnt, - sname.c_str()); - if ( Sarea->orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), Sarea->orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -void idaapi avr_segend(outctx_t &, segment_t *) -{ -} - -//-------------------------------------------------------------------------- -void avr_t::avr_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); -} - -//-------------------------------------------------------------------------- -void avr_t::avr_footer(outctx_t &ctx) const -{ - qstring name = get_visible_name(inf_get_start_ea()); - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), - ash.end, ash.cmnt, name.c_str()); -} diff --git a/idasdk75/module/avr/reg.cpp b/idasdk75/module/avr/reg.cpp deleted file mode 100644 index ee3c98a..0000000 --- a/idasdk75/module/avr/reg.cpp +++ /dev/null @@ -1,775 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Atmel AVR - 8-bit RISC processor - * - */ - -#include "avr.hpp" -#include <segregs.hpp> -#include <diskio.hpp> -#include <loader.hpp> -#include <fixup.hpp> -#include "notify_codes.hpp" -#include "../../ldr/elf/elfr_avr.h" -int data_id; - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", - "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", - "cs","ds", // virtual registers for code and data segments -}; - -//----------------------------------------------------------------------- -// AVR assembler -//----------------------------------------------------------------------- -static const asm_t avrasm = -{ - AS_COLON|AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF0|AS_ONEDUP, - 0, - "AVR Assembler", - 0, - NULL, // header lines - ".org", // org - ".exit", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".dw", // word directive - ".dd", // double words - NULL, // no qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".byte %s", // uninited arrays - ".equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - NULL, // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - NULL, // "public" name keyword - NULL, // "weak" name keyword - NULL, // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - NULL, // "align" keyword - '(', ')', // lbrace, rbrace - NULL, // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &avrasm, NULL }; - -//-------------------------------------------------------------------------- -static const char cfgname[] = "avr.cfg"; - -//-------------------------------------------------------------------------- -bool avr_iohandler_t::entry_processing(ea_t &ea1, const char * /*word*/, const char * /*cmt*/) -{ - pm.helper.altset_ea(ea1, 1); - create_insn(ea1); - ea_t ea = get_first_fcref_from(ea1); - if ( ea != BADADDR ) - ea1 = ea; - return false; // continue processing -} - -//-------------------------------------------------------------------------- -bool avr_iohandler_t::check_ioresp() const -{ - return inf_like_binary() || pm.imageFile; -} - -//-------------------------------------------------------------------------- -bool avr_t::is_possible_subarch(int addr) const -{ - // old version of gcc-arm don't use 31/51/etc subarches - only 3/5/... :( - // maybe make option? - return subarch == 0 || subarch == addr || (addr/10 == subarch); -} - -//-------------------------------------------------------------------------- -const char *avr_iohandler_t::iocallback(const ioports_t &_ports, const char *line) -{ - int addr; - char word[MAXSTR]; - word[MAXSTR-1] = '\0'; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "%1023[^=] = %d", word, &addr) == 2 ) - { - if ( streq(word, "RAM") ) - { - pm.ramsize = addr; - return NULL; - } - if ( streq(word, "ROM") ) - { - pm.romsize = addr >> 1; - return NULL; - } - if ( streq(word, "EEPROM") ) - { - pm.eepromsize = addr; - return NULL; - } - if ( streq(word, "SUBARCH") ) - { - return pm.is_possible_subarch(addr) ? NULL : IOPORT_SKIP_DEVICE; - } - } - return standard_callback(_ports, line); -} - -//-------------------------------------------------------------------------- -struct avr_ioport_parser_t : public choose_ioport_parser_t -{ - avr_t ± - - avr_ioport_parser_t(avr_t &_pm) : pm(_pm) {} - virtual bool parse(qstring *, const char *line) override - { - int addr; - char word[MAXSTR]; - word[MAXSTR-1] = '\0'; - CASSERT(MAXSTR == 1024); - bool skip = qsscanf(line, "%1023[^=] = %d", word, &addr) == 2 - && strcmp(word, "SUBARCH") == 0 - && !pm.is_possible_subarch(addr); - return !skip; - } -}; - -//-------------------------------------------------------------------------- -const ioport_t *avr_t::find_port(ea_t address) -{ - return find_ioport(ioh.ports, address); -} - -//-------------------------------------------------------------------------- -const char *avr_t::find_bit(ea_t address, size_t bit) -{ - const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit); - return b ? b->name.c_str() : NULL; -} - -//-------------------------------------------------------------------------- -void avr_t::setup_avr_device(int resp_info) -{ - if ( !choose_ioport_device(&ioh.device, cfgname) ) - return; - - ioh.set_device_name(ioh.device.c_str(), resp_info); - if ( get_first_seg() == NULL ) // set processor options before load file - return; - plan_range(0, BADADDR); // reanalyze program - - // resize the ROM segment - { - segment_t *s = getseg(node2ea(helper.altval(-1))); - if ( s == NULL ) - s = get_first_seg(); // for the old databases - if ( s != NULL ) //-V547 's != 0' is always true - { - if ( s->size() > romsize ) - warning("The input file is bigger than the ROM size of the current device"); - set_segm_end(s->start_ea, s->start_ea+romsize, SEGMOD_KILL); - } - } - // resize the RAM segment - { - segment_t *s = get_segm_by_name("RAM"); - if ( s == NULL && ramsize != 0 ) - { - ea_t start = (inf_get_max_ea() + 0xFFFFF) & ~0xFFFFF; - add_segm(start>>4, start, start+ramsize, "RAM", "DATA"); - s = getseg(start); - } - ram = BADADDR; - if ( s != NULL ) - { - int i; - ram = s->start_ea; - set_segm_end(ram, ram+ramsize, SEGMOD_KILL); - // set register names - for ( i=0; i < 32; i++ ) - if ( !has_any_name(get_flags(ram+i)) ) - set_name(ram+i, register_names[i], SN_NODUMMY); - // set I/O port names - for ( i=0; i < ioh.ports.size(); i++ ) - { - const ioport_t &p = ioh.ports[i]; - set_name(ram+p.address+0x20, p.name.c_str(), SN_NODUMMY); - set_cmt(ram+p.address+0x20, p.cmt.c_str(), true); - } - } - } -} - -//-------------------------------------------------------------------------- -const char *avr_t::set_idp_options( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded) -{ - if ( keyword == NULL ) - { - setup_avr_device(IORESP_INT); - return IDPOPT_OK; - } - else if ( strcmp(keyword, "AVR_MCPU") == 0 ) - { - if ( value_type != IDPOPT_STR ) - return IDPOPT_BADTYPE; - - ioh.device = (const char *) value; - if ( idb_loaded ) - ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); - return IDPOPT_OK; - } - - return IDPOPT_BADKEY; -} - -//-------------------------------------------------------------------------- -bool avr_t::set_param_by_arch(void) -{ - int max_rom, max_ram, max_eeprom; - // preset MAXIMUM's of memory size's by mcpu subtype - switch ( subarch ) - { - default: - subarch = 0; - return false; // LOGICAL ERROR? - - // at90s1200, attiny10, attiny11, attiny12, attiny15, attiny28 - case E_AVR_MACH_AVR1: // ROM<=1k - max_rom = 1024; - max_ram = 32; - max_eeprom = 64; - break; - // at90s2313, at90s2323, at90s2333, at90s2343, attiny22, attiny26, - // at90s4414 /* XXX -> 8515 */, at90s4433, at90s4434 /* XXX -> 8535 */, - // at90s8515, at90c8534, at90s8535 - case E_AVR_MACH_AVR2: // ROM<=8k - // attiny13, attiny13a, attiny2313, attiny24, attiny44, attiny84, - // attiny25, attiny45, attiny85, attiny261, attiny461, attiny861, - // attiny43u, attiny48, attiny88, at86rf401 - // PASS THRU - case E_AVR_MACH_AVR25: // ROM<=8k - max_rom = 8*1024; - max_ram = 512; - max_eeprom = 512; - break; - // at43usb355, at76c711 - case E_AVR_MACH_AVR3: // ROM>=8k<=64k - max_rom = 64*1024; - max_ram = 1024; - max_eeprom = 0; - break; - // atmega103, at43usb320, - case E_AVR_MACH_AVR31: // ROM>=65k&&<=128k, (RAM=65k, EEPROM=4k) - max_rom = 128*1024; - max_ram = 4*1024; - max_eeprom = 4*1024; - break; - // attiny167, at90usb82, at90usb162 - case E_AVR_MACH_AVR35: // ROM>=8k&&<=64k, - max_rom = 64*1024; - max_ram = 512; - max_eeprom = 512; - break; - // atmega8, atmega48, atmega48p, atmega88, atmega88p, atmega8515, - // atmega8535, atmega8hva, at90pwm1, at90pwm2, at90pwm2b, at90pwm3, - // at90pwm3b - case E_AVR_MACH_AVR4: // ROM<=8k - max_rom = 8*1024; - max_ram = 1024; - max_eeprom = 512; - break; - // atmega16, atmega161, atmega162, atmega163, atmega164p, atmega165, - // atmega165p, atmega168, atmega168p, atmega169, atmega169p, atmega32, - // atmega323, atmega324p, atmega325, atmega325p, atmega3250, atmega3250p, - // atmega328p, atmega329, atmega329p, atmega3290, atmega3290p, atmega406, - // atmega64, atmega640, atmega644, atmega644p, atmega645, atmega649, - // atmega6450, atmega6490, atmega16hva, at90can32, at90can64, at90pwm216, - // at90pwm316, atmega32c1, atmega32m1, atmega32u4, at90usb646, at90usb647, - // at94k - case E_AVR_MACH_AVR5: // ROM>=8k&&<=64k - max_rom = 64*1024; - max_ram = 4*1024; - max_eeprom = 2*1024; - break; - // atmega128, atmega1280, atmega1281, atmega1284p, - // at90can128, at90usb1286, at90usb1287 - case E_AVR_MACH_AVR51: // ROM=128k - max_rom = 128*1024; - max_ram = 16*1024; - max_eeprom = 4*1024; - break; - // atmega2560, atmega2561 - case E_AVR_MACH_AVR6: // ROM=256k (3-byte pc -- is supported?) - max_rom = 256*1024; - max_ram = 8*1024; - max_eeprom = 4*1024; - break; - case E_AVR_MACH_XMEGA1: // ROM < 8K, ram=? - max_rom = 8*1024; - max_ram = 1024; - max_eeprom = 512; - break; - // ATxmega16A4, ATxmega16D4, ATxmega32D4 - case E_AVR_MACH_XMEGA2: // 8K < FLASH <= 64K, RAM <= 64K - max_rom = 64*1024; - max_ram = 64*1024; - max_eeprom = 1024; - break; - // ATxmega32A4 - case E_AVR_MACH_XMEGA3: // 8K < FLASH <= 64K, RAM > 64K - max_rom = 64*1024; - max_ram = 128*1024; // ? - max_eeprom = 1024; - break; - // ATxmega64A3, ATxmega64D3 - case E_AVR_MACH_XMEGA4: // 64K < FLASH <= 128K, RAM <= 64K - max_rom = 128*1024; - max_ram = 64*1024; - max_eeprom = 2048; - break; - // ATxmega64A1 - case E_AVR_MACH_XMEGA5: // 64K < FLASH <= 128K, RAM > 64K - max_rom = 128*1024; - max_ram = 128*1024; - max_eeprom = 2048; - break; - // ATxmega128A3, ATxmega128D3, ATxmega192A3, ATxmega192D3, - // ATxmega256A3B, ATxmega256A3, ATxmega256D3 - case E_AVR_MACH_XMEGA6: // 128K < FLASH <= 256K, RAM <= 64K - max_rom = 256*1024; - max_ram = 64*1024; - max_eeprom = 4096; - break; - // ATxmega128A1 - case E_AVR_MACH_XMEGA7: // 128K < FLASH <= 256K, RAM > 64K - max_rom = 256*1024; - max_ram = 128*1024; - max_eeprom = 4096; - break; - } - avr_ioport_parser_t parser(*this); - if ( !choose_ioport_device2(&ioh.device, cfgname, &parser) ) - { - ioh.device.sprnt("avr%d", subarch); - ioh.device[sizeof("avrX")-1] = '\0'; - romsize = max_rom >> 1; - ramsize = max_ram; - eepromsize = max_eeprom; - } - else - { - ioh.set_device_name(ioh.device.c_str(), IORESP_INT); - plan_range(0, BADADDR); // reanalyze program - } - return true; -} - -//-------------------------------------------------------------------------- -static inline ea_t get16bit(ea_t ea) -{ - if ( segtype(ea) == SEG_CODE ) - return get_wide_byte(ea); - - return get_word(ea); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case idb_event::segm_added: - { - segment_t *s = va_arg(va, segment_t *); - qstring sclass; - if ( get_segm_class(&sclass, s) > 0 && sclass == "DATA" ) - set_default_dataseg(s->sel); - } - break; - - case idb_event::segm_moved: // A segment is moved - // Fix processor dependent address sensitive information - { - ea_t from = va_arg(va, ea_t); - ea_t to = va_arg(va, ea_t); - asize_t size = va_arg(va, asize_t); - //bool changed_netmap = va_argi(va, bool); - - nodeidx_t ndx1 = ea2node(from); - nodeidx_t ndx2 = ea2node(to); - pm.helper.altshift(ndx1, ndx2, size); // move address information - } - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -static bool idaapi avr16_apply( - const fixup_handler_t *fh, - ea_t item_ea, - ea_t fixup_ea, - int opnum, - bool /*is_macro*/, - const fixup_data_t &fd) -{ - avr_t &pm = *GET_MODULE_DATA(avr_t); - if ( !pm.nonBinary - || fd.has_base() - || fd.is_unused() - || fd.displacement != 0 ) - { - msg("%a: Unexpected or incorrect CUSTOM_FIXUP\n", fixup_ea); - return false; - } - - if ( is_unknown(get_flags(item_ea)) ) - create_16bit_data(item_ea, 2); - - refinfo_t ri; - ri.flags = fh->reftype; - ri.base = fd.get_base(); - ri.target = ri.base + fd.off; - ri.tdelta = fd.displacement; - op_offset_ex(item_ea, opnum, &ri); - return true; -} - -//-------------------------------------------------------------------------- -//lint -e{818} could be declared const -static int idaapi avr16_gen_expr( - qstring * /*buf*/, - qstring * /*format*/, - ea_t ea, - int numop, - const refinfo_t &ri, - ea_t /*from*/, - adiff_t *opval, - ea_t * /*target*/, - ea_t * /*fullvalue*/, - int /*getn_flags*/) -{ - avr_t &pm = *GET_MODULE_DATA(avr_t); - if ( !pm.nonBinary - || numop != 0 - || ri.type() == (pm.ref_avr16_id | REFINFO_CUSTOM) - || ri.tdelta != 0 - || ri.target == BADADDR - || *opval != get16bit(ea) ) - { - msg("%a: Unexpected or incorrect CUSTOM offset\n", ea); - return 0; - } - return 3; // process as a regular fixup -} - -//-------------------------------------------------------------------------- -static const custom_refinfo_handler_t ref_avr16 = -{ - sizeof(custom_refinfo_handler_t), - "AVR16", - "AVR 16-bit offset", - 0, // properties (currently 0) - avr16_gen_expr, // gen_expr - NULL, // calc_reference_data - NULL, // get_format -}; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(avr_t)); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi avr_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - helper.create(AVR_INFO_NODENAME); - hook_event_listener(HT_IDB, &idb_listener, &LPH); - cfh_avr16.apply = avr16_apply; - cfh_avr16_id = register_custom_fixup(&cfh_avr16); - ref_avr16_id = register_custom_refinfo(&ref_avr16); - cfh_avr16.reftype = REFINFO_CUSTOM | ref_avr16_id; - break; - - case processor_t::ev_term: - cfh_avr16.reftype = REFINFO_CUSTOM; - unregister_custom_refinfo(ref_avr16_id); - unregister_custom_fixup(cfh_avr16_id); - unhook_event_listener(HT_IDB, &idb_listener); - ioh.ports.clear(); - clr_module_data(data_id); - break; - - case avr_module_t::ev_set_machine_type: // elf-loader 'set machine type' and file type - subarch = va_arg(va, int); - imageFile = va_argi(va, bool); - nonBinary = true; - break; - - case processor_t::ev_newfile: // new file loaded - // remember the ROM segment - { - segment_t *s = get_first_seg(); - if ( s != NULL ) - { - if ( subarch == 0 ) - set_segm_name(s, "ROM"); - helper.altset(-1, ea2node(s->start_ea)); - } - } - if ( subarch != 0 && set_param_by_arch() ) - break; - setup_avr_device(/*IORESP_AREA|*/IORESP_INT); // allow the user to select the device - if ( subarch != 0 ) - break; - // create additional segments - { - ea_t start = (inf_get_max_ea() + 0xFFFFF) & ~0xFFFFF; - if ( eepromsize != 0 ) - { - char *file = ask_file(false, "*.bin", "Please enter the binary EEPROM image file"); - if ( file != NULL ) - { - add_segm(start>>4, start, start+eepromsize, "EEPROM", "DATA"); - linput_t *li = open_linput(file, false); - if ( li != NULL ) - { - uint64 size = qlsize(li); - if ( size > eepromsize ) - size = eepromsize; - file2base(li, 0, start, start+size, FILEREG_NOTPATCHABLE); - close_linput(li); - } - } - } - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: // old file loaded - { - ioh.restore_device(); - segment_t *s = get_segm_by_name("RAM"); - if ( s != NULL ) - ram = s->start_ea; - } - break; - - case processor_t::ev_newprc: // new processor type - break; - - case processor_t::ev_newasm: // new assembler type - break; - - case processor_t::ev_out_label: // The kernel is going to generate an instruction - // label line or a function header - { - outctx_t *ctx = va_arg(va, outctx_t *); - if ( helper.altval_ea(ctx->insn_ea) ) // if entry point - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), ctx->insn_ea); - ctx->gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - avr_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - avr_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - avr_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - avr_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -// 1001 0101 0xx0 1000 ret -// 1001 0101 0xx1 1000 reti -static const uchar retcode_1[] = { 0x08, 0x95 }; // ret -static const uchar retcode_2[] = { 0x18, 0x95 }; // reti -static const uchar retcode_3[] = { 0x28, 0x95 }; // ret -static const uchar retcode_4[] = { 0x38, 0x95 }; // reti -static const uchar retcode_5[] = { 0x48, 0x95 }; // ret -static const uchar retcode_6[] = { 0x58, 0x95 }; // reti -static const uchar retcode_7[] = { 0x68, 0x95 }; // ret -static const uchar retcode_8[] = { 0x78, 0x95 }; // reti - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { sizeof(retcode_4), retcode_4 }, - { sizeof(retcode_5), retcode_5 }, - { sizeof(retcode_6), retcode_6 }, - { sizeof(retcode_7), retcode_7 }, - { sizeof(retcode_8), retcode_8 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -#define FAMILY "Atmel AVR series:" - -static const char *const shnames[] = -{ - "AVR", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Atmel AVR", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_AVR, // id - // flag - PRN_HEX - | PR_RNAMESOK, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 16, // 16 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - rVcs, // first - rVds, // last - 0, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - AVR_null, - AVR_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - AVR_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/c39/ana.cpp b/idasdk75/module/c39/ana.cpp deleted file mode 100644 index d904c6e..0000000 --- a/idasdk75/module/c39/ana.cpp +++ /dev/null @@ -1,442 +0,0 @@ -/* - * Rockwell C39 processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "c39.hpp" - -/* -Operand types: -1) none -2) Register a, x, y -3) address $xx address may be 8 or 16 bits -4) indirect address ($xx) address of the cell with the target address -5) immediate #$xx constant -6) label Label target label of the jump -*/ - -//---------------------------------------------------------------------- -// current byte(s) is immediate data, 1 byte -static void SetImmData(op_t &op, uchar code) -{ - op.type = o_imm; - // always in the second byte - op.offb = 1; - // element size - op.dtype = dt_byte; - // value - op.addr = op.value = code; - // it can't be an offset! - op.flags |= OF_NUMBER; // only number -} - -//---------------------------------------------------------------------- -// registres are considered byte-sized -static void SetReg(op_t &op, uchar reg_n) -{ - op.type = o_reg; // only register - op.reg = reg_n; // register number - op.dtype = dt_byte; // size is always 8 bits -} - -//---------------------------------------------------------------------- -// memory cell -static void SetMemVar(op_t &op, ushort addr) -{ - op.type = o_mem; - op.addr = op.value = addr; - op.dtype = dt_word; -} - -//---------------------------------------------------------------------- -// memory cell with an address -static void SetMemVarI(op_t &op, ushort addr) -{ - op.type = o_mem; - op.specflag1 |= URR_IND; - op.addr = op.value = addr; - op.dtype = dt_word; -} - -//---------------------------------------------------------------------- -// relative branch -static void SetRelative(const insn_t &insn, op_t &op, signed char disp) -{ - op.type = o_near; - op.dtype = dt_word; - op.offb = 1; // in fact, not always... - // calculate indirect value - op.addr = op.value = insn.ip + insn.size + (int32)disp; -} - -//---------------------------------------------------------------------- -// absolute branch -static void SetAbs(op_t &op, unsigned short disp) -{ - op.type = o_near; - op.dtype = dt_word; - op.offb = 1; // in fact, not always... - // calculate final value - op.addr = op.value = disp; -} - -//---------------------------------------------------------------------- -// analyzer -int idaapi C39_ana(insn_t *_insn) -{ - static const uchar Dt[] = - { - C39_brk, C39_ora, C39_mpy, C39_tip, 0, C39_ora, C39_asl, C39_rmb, // 00 - C39_php, C39_ora, C39_asl, C39_jsb, C39_jpi, C39_ora, C39_asl, C39_bbr, // 08 - - C39_bpl, C39_ora, C39_mpa, C39_lab, 0, C39_ora, C39_asl, C39_rmb, // 10 - C39_clc, C39_ora, C39_neg, C39_jsb, 0, C39_ora, C39_asl, C39_bbr, // 18 - - C39_jsr, C39_and, C39_psh, C39_phw, C39_bit, C39_and, C39_rol, C39_rmb, // 20 - C39_plp, C39_and, C39_rol, C39_jsb, C39_bit, C39_and, C39_rol, C39_bbr, // 28 - - C39_bmi, C39_and, C39_pul, C39_plw, 0, C39_and, C39_rol, C39_rmb, // 30 - C39_sec, C39_and, C39_asr, C39_jsb, 0, C39_and, C39_rol, C39_bbr, // 38 - - C39_rti, C39_eor, C39_rnd, 0, 0, C39_eor, C39_lsr, C39_rmb, // 40 - C39_pha, C39_eor, C39_lsr, C39_jsb, C39_jmp, C39_eor, C39_lsr, C39_bbr, // 48 - - C39_bvc, C39_eor, C39_clw, 0, 0, C39_eor, C39_lsr, C39_rmb, // 50 - C39_cli, C39_eor, C39_phy, C39_jsb, 0, C39_eor, C39_lsr, C39_bbr, // 58 - - C39_rts, C39_adc, C39_taw, 0, C39_add, C39_adc, C39_ror, C39_rmb, // 60 - C39_pla, C39_adc, C39_ror, C39_jsb, C39_jmp, C39_adc, C39_ror, C39_bbr, // 68 - - C39_bvs, C39_adc, C39_twa, 0, C39_add, C39_adc, C39_ror, C39_rmb, // 70 - C39_sei, C39_adc, C39_ply, C39_jsb, C39_jmp, C39_adc, C39_ror, C39_bbr, // 78 - - C39_bra, C39_sta, 0, 0, C39_sty, C39_sta, C39_stx, C39_smb, // 80 - C39_dey, C39_add, C39_txa, C39_nxt, C39_sty, C39_sta, C39_stx, C39_bbs, // 88 - - C39_bcc, C39_sta, 0, 0, C39_sty, C39_sta, C39_stx, C39_smb, // 90 - C39_tya, C39_sta, C39_txs, C39_lii, 0, C39_sta, 0, C39_bbs, // 98 - - C39_ldy, C39_lda, C39_ldx, 0, C39_ldy, C39_lda, C39_ldx, C39_smb, // A0 - C39_tay, C39_lda, C39_tax, C39_lan, C39_ldy, C39_lda, C39_ldx, C39_bbs, // A8 - - C39_bcs, C39_lda, C39_sti, 0, C39_ldy, C39_lda, C39_ldx, C39_smb, // B0 - C39_clv, C39_lda, C39_tsx, C39_ini, C39_ldy, C39_lda, C39_ldx, C39_bbs, // B8 - - - C39_cpy, C39_cmp, C39_rba, 0, C39_cpy, C39_cmp, C39_dec, C39_smb, // C0 - C39_iny, C39_cmp, C39_dex, C39_phi, C39_cpy, C39_cmp, C39_dec, C39_bbs, // C8 - - C39_bne, C39_cmp, C39_sba, 0, C39_exc, C39_cmp, C39_dec, C39_smb, // D0 - C39_cld, C39_cmp, C39_phx, C39_pli, 0, C39_cmp, C39_dec, C39_bbs, // D8 - - C39_cpx, C39_sbc, C39_bar, 0, C39_cpx, C39_sbc, C39_inc, C39_smb, // E0 - C39_inx, C39_sbc, C39_nop, C39_lai, C39_cpx, C39_sbc, C39_inc, C39_bbs, // E8 - - C39_beq, C39_sbc, C39_bas, 0, 0, C39_sbc, C39_inc, C39_smb, // F0 - C39_sed, C39_sbc, C39_plx, C39_pia, 0, C39_sbc, C39_inc, C39_bbs // F8 - }; - - // get instruction byte - insn_t &insn = *_insn; - uchar code = insn.get_next_byte(); - // get instruction code - insn.itype = Dt[code]; - // analyze instruction type - switch ( insn.itype ) - { - // unknown instruction - case 0: - return 0; - // smb/rmb - case C39_smb: - case C39_rmb: - SetImmData(insn.Op1, (code>>4) & 7); - SetMemVar(insn.Op2, insn.get_next_byte()); - break; - // bbs/bbr - case C39_bbs: - case C39_bbr: - SetImmData(insn.Op1, (code>>4)&7); - SetMemVar(insn.Op2, insn.get_next_byte()); - SetRelative(insn, insn.Op3, insn.get_next_byte()); - break; - - // bpl/bmi/bvc/bvs/bra/bcc/bcs/bne/beq - case C39_beq: - case C39_bne: - case C39_bcs: - case C39_bcc: - case C39_bra: - case C39_bvs: - case C39_bvc: - case C39_bmi: - case C39_bpl: - SetRelative(insn, insn.Op1, insn.get_next_byte()); - break; - - // jsb - case C39_jsb: - SetMemVar(insn.Op1,0xFFE0+((code>>4) & 7)*2); - break; - - // ora, and, eor, adc, sta, lda, cmp, sbc - case C39_sbc: - case C39_cmp: - case C39_lda: - case C39_sta: - case C39_adc: - case C39_eor: - case C39_and: - case C39_ora: - switch ( code&0x1E ) - { - // 01 - xxx ($b) - case 0x00: - SetMemVarI(insn.Op1, insn.get_next_byte()); - break; - // 05 - xxx $b - case 0x04: - SetMemVar(insn.Op1, insn.get_next_byte()); - break; - // 09 - xxx #$b - case 0x08: - SetImmData(insn.Op1, insn.get_next_byte()); - break; - // 0D - xxx $w - case 0x0C: - SetMemVar(insn.Op1, insn.get_next_word()); - break; - // 11 - xxx ($b), x - case 0x10: - SetMemVarI(insn.Op1, insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - // 15 - xxx $b, x - case 0x14: - SetMemVar(insn.Op1, insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - // 19 - xxx $w, y - case 0x18: - SetMemVar(insn.Op1, insn.get_next_word()); - SetReg(insn.Op2,rY); - break; - // 1d - xxx $w, x - case 0x1C: - SetMemVar(insn.Op1, insn.get_next_word()); - SetReg(insn.Op2,rX); - break; - } - break; - - // asl, rol, lsr, ror, asr - case C39_asr: // this one has a single variant (asr a) - case C39_ror: - case C39_lsr: - case C39_rol: - case C39_asl: - switch ( code & 0x1C ) - { - // 6 - xxx $b - case 0x04: - SetMemVar(insn.Op1, insn.get_next_byte()); - break; - // A - xxx a - case 0x08: - SetReg(insn.Op1,rA); - break; - // E - xxx $w - case 0x0C: - SetMemVar(insn.Op1, insn.get_next_word()); - break; - //16 - xxx $b, x - case 0x14: - SetMemVar(insn.Op1, insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - //1E - xxx $w, x - case 0x1C: - SetMemVar(insn.Op1, insn.get_next_word()); - SetReg(insn.Op2,rX); - break; - } - break; - - // inc, dec - case C39_dec: - case C39_inc: - switch ( code&0x18 ) - { - // e6 - xxx $b - case 0x00: - SetMemVar(insn.Op1, insn.get_next_byte()); - break; - // ee - xxx $w - case 0x08: - SetMemVar(insn.Op1, insn.get_next_word()); - break; - // f6 - xxx $b, x - case 0x10: - SetMemVar(insn.Op1, insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - // fe - xxx $w, x - case 0x18: - SetMemVar(insn.Op1, insn.get_next_word()); - SetReg(insn.Op2,rX); - break; - } - break; - - // rba/sba $b, $w - case C39_rba: - case C39_sba: - SetImmData(insn.Op1, insn.get_next_byte()); - SetMemVar(insn.Op2, insn.get_next_word()); - break; - - // cpy/cpx - case C39_cpx: - case C39_cpy: - switch ( code & 0x1C ) - { - //a0 - xxx #$b - case 0x00: - SetImmData(insn.Op1, insn.get_next_byte()); - break; - //a4 - xxx $b - case 0x04: - SetMemVar(insn.Op1, insn.get_next_byte()); - break; - //ac - xxx $w - case 0x0C: - SetMemVar(insn.Op1, insn.get_next_word()); - break; - //14 - xxx $b, x - case 0x14: - SetMemVar(insn.Op1, insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - //1C - xxx $w, x - case 0x1C: - SetMemVar(insn.Op1, insn.get_next_word()); - SetReg(insn.Op2,rX); - break; - } - break; - - // lab/neg - case C39_neg: - case C39_lab: - SetReg(insn.Op1,rA); - break; - - // jpi ($w) - case C39_jpi: - SetMemVarI(insn.Op1, insn.get_next_word()); - break; - - // jsr $w - case C39_jsr: - SetAbs(insn.Op1, insn.get_next_word()); - break; - - // bar/bas $w, $b ,$rel - case C39_bar: - case C39_bas: - SetMemVar(insn.Op1, insn.get_next_word()); - SetImmData(insn.Op2, insn.get_next_byte()); - SetRelative(insn, insn.Op3, insn.get_next_byte()); - break; - - // bit - case C39_bit: - if ( code & 8 ) - SetMemVar(insn.Op1, insn.get_next_word()); // bit $w - else - SetMemVar(insn.Op1, insn.get_next_byte()); // bit $b - break; - - // jmp - case C39_jmp: - switch ( code ) - { - case 0x4C: - SetAbs(insn.Op1, insn.get_next_word()); - break; - case 0x6C: - SetMemVarI(insn.Op1, insn.get_next_word()); - break; - case 0x7C: - SetMemVarI(insn.Op1, insn.get_next_word()); - SetReg(insn.Op2, rX); - break; - } - break; - - // sti - case C39_sti: - SetImmData(insn.Op1,insn.get_next_byte()); - SetMemVar(insn.Op2,insn.get_next_byte()); - break; - - // exc - case C39_exc: - SetMemVar(insn.Op1,insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - - // add - case C39_add: - switch ( code ) - { - case 0x64: - SetMemVar(insn.Op1,insn.get_next_byte()); - break; - case 0x74: - SetMemVar(insn.Op1,insn.get_next_byte()); - SetReg(insn.Op2,rX); - break; - case 0x89: - SetImmData(insn.Op1,insn.get_next_byte()); - break; - } - break; - - // sty - case C39_stx: - case C39_ldx: - case C39_ldy: - case C39_sty: - switch ( code & 0x1C ) - { - // A0 xxx #$b - case 0x00: - SetImmData(insn.Op1,insn.get_next_byte()); - break; - // A4 xxx $b - case 0x04: - SetMemVar(insn.Op1,insn.get_next_byte()); - break; - // AC xxx $w - case 0x0C: - SetMemVar(insn.Op1,insn.get_next_word()); - break; - // B4 xxx $b, x - case 0x14: - SetMemVar(insn.Op1,insn.get_next_byte()); - SetReg(insn.Op2, - insn.itype == C39_sty || insn.itype == C39_ldy ? rX : rY); - break; - // BC xxx $w, x - case 0x1C: - SetMemVar(insn.Op1,insn.get_next_word()); - SetReg(insn.Op2, - insn.itype == C39_sty || insn.itype == C39_ldy ? rX : rY); - break; - } - break; - } - return insn.size; -} diff --git a/idasdk75/module/c39/c39.hpp b/idasdk75/module/c39/c39.hpp deleted file mode 100644 index c4c655c..0000000 --- a/idasdk75/module/c39/c39.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Rockwell C39 processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#ifndef _C39_HPP -#define _C39_HPP - -#include <ida.hpp> -#include <idp.hpp> - -#include "../idaidp.hpp" -#define near -#define far -#include "ins.hpp" -#include "../iohandler.hpp" - -// ============================================================ -// aditional bits for specflags1 (specflag2 not used) -//----------------------------------------------- -// additional bits for memory access -#define URR_IND (0x01) // indirect via a register - -//------------------------------------------------------------------------ -// list of processor registers -#ifdef _MSC_VER -#define ENUM8BIT : uint8 -#else -#define ENUM8BIT -#endif -enum C39_registers ENUM8BIT -{ - rNULLReg, - rA, - rX, rY, - rVcs, rVds -}; - -//------------------------------------------------------------------------ -int idaapi C39_ana(insn_t *insn); -int idaapi C39_emu(const insn_t &insn); -void idaapi C39_data(outctx_t &ctx, bool analyze_only); - -//------------------------------------------------------------------------ -struct c39_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - bool flow = false; // stop flag - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void C39_header(outctx_t &ctx); - void handle_operand( - const insn_t &insn, - const op_t &x, - bool is_forced, - bool isload); - int C39_emu(const insn_t &insn); - - void C39_segstart(outctx_t &ctx, segment_t *Sarea) const; - void C39_footer(outctx_t &ctx) const; -}; - -#endif diff --git a/idasdk75/module/c39/emu.cpp b/idasdk75/module/c39/emu.cpp deleted file mode 100644 index 55054d7..0000000 --- a/idasdk75/module/c39/emu.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Rockwell C39 processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "c39.hpp" - -//---------------------------------------------------------------------- -// use/change of operands -void c39_t::handle_operand( - const insn_t &insn, - const op_t &x, - bool is_forced, - bool isload) -{ - ea_t ea = map_code_ea(insn, x); - switch ( x.type ) - { - case o_void: - break; - // nothing to do here - case o_reg: - break; - - case o_imm: - if ( !isload ) - goto badTouch; - set_immd(insn.ea); - if ( !is_forced && is_off(get_flags(insn.ea), x.n) ) - insn.add_dref(ea, x.offb, dr_O); //offset! - break; - - // jump or call - case o_near: - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - // add xref to code - insn.add_cref(ea, x.offb, fl_CN); - // is nonreturning function? - flow = func_does_return(ea); - } - else - { - insn.add_cref(ea, x.offb, fl_JN); - } - break; - - // memory reference - case o_mem: - insn.create_op_data(ea, x); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - break; - - default: -badTouch: - warning("%a %s,%d: bad optype %d", - insn.ea, insn.get_canon_mnem(ph), - x.n, x.type); - break; - } -} - -//---------------------------------------------------------------------- -int c39_t::C39_emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - bool flag1 = is_forced_operand(insn.ea, 0); - bool flag2 = is_forced_operand(insn.ea, 1); - bool flag3 = is_forced_operand(insn.ea, 2); - - flow = ((Feature & CF_STOP) == 0); - - if ( Feature & CF_USE1) handle_operand(insn, insn.Op1, flag1, true); - if ( Feature & CF_USE2) handle_operand(insn, insn.Op2, flag2, true); - if ( Feature & CF_USE3) handle_operand(insn, insn.Op3, flag3, true); - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP,insn.ea); - - if ( Feature & CF_CHG1) handle_operand(insn, insn.Op1, flag1, false); - if ( Feature & CF_CHG2) handle_operand(insn, insn.Op2, flag2, false); - if ( Feature & CF_CHG3) handle_operand(insn, insn.Op3, flag3, false); - if ( flow ) - add_cref(insn.ea, insn.ea+insn.size, fl_F); - - return 1; -} diff --git a/idasdk75/module/c39/makefile b/idasdk75/module/c39/makefile deleted file mode 100644 index 7e2af76..0000000 --- a/idasdk75/module/c39/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=c39 -CONFIGS=c39.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp c39.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - c39.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - c39.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - c39.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp c39.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/c39/reg.cpp b/idasdk75/module/c39/reg.cpp deleted file mode 100644 index b0aa291..0000000 --- a/idasdk75/module/c39/reg.cpp +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Rockwell C39 processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "c39.hpp" -#include <diskio.hpp> -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -static const char *const RegNames[] = -{ - // empty place - "", - // general registers - "A","X","Y", - // pseudo-segment registers - "cs","ds" -}; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new c39_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi c39_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - inf_set_gen_lzero(true); - helper.create("$ C39"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - { - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - C39_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - C39_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - C39_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return C39_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return C39_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - C39_data(*ctx, analyze_only); - return 1; - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const asm_t pseudosam = -{ - AS_COLON | AS_UDATA | ASH_HEXF3 | ASD_DECF0, - 0, - "Generic C39 assembler", // Assembler name - 0, // Help screen number, 0 - no help - NULL, // array of automatically generated header lines - "org", // ORG - "end", // end - - ";", // comment - '"', // string literal delimiter - '\'', // char constant delimiter - "\\\"'", // special chars that cannot appear - - "db", // ascii string directive - ".DATA.B", // byte directive - ".DATA.W", // word directive - ".DATA.L", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "#d dup(#v)", // arrays (#h,#d,#v,#s(...) - "db ?", // uninited arrays - ".equ", // equ - NULL, // seg prefix - "$", // current IP - NULL, // Generate function header lines - NULL, // Generate function footer lines - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // Get name of type of item at ea or id - ".ALIGN", // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &pseudosam, NULL }; -//----------------------------------------------------------------------- -#define FAMILY "Rockwell C39:" -static const char *const shnames[] = { "C39", NULL }; -static const char *const lnames[] = { FAMILY"Rockwell C39", NULL }; - -//-------------------------------------------------------------------------- -static const uchar retcode_1[] = { 0x00, 0x0B }; // RTS -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_C39, // processor's id - // flag - PR_USE32 - | PR_BINMEM - | PR_SEGTRANS, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte - - shnames, // short processor names - lnames, // long processor names - - asms, // assembler definitions - - notify, // Event notification handler - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 2, // size of a segment register - rVcs,rVds, - NULL, // typical code start sequences - retcodes, // 'return' instruction opcodes - 0,C39_last, // icode of the first and the last instruction - Instructions, // instruc - 3, // Size of long double (tbyte) - 24 bits - {0,0,0,0}, // Number of digits in floating numbers after the decimal point - 0, // Icode of return instruction - NULL, // Reserved, currently equals to NULL -}; diff --git a/idasdk75/module/cfh_ha16.cpp b/idasdk75/module/cfh_ha16.cpp deleted file mode 100644 index d84a974..0000000 --- a/idasdk75/module/cfh_ha16.cpp +++ /dev/null @@ -1,149 +0,0 @@ - -// This file contains a custom fixup handler for the HA16 fixup type. -// It is used by PPC, MIPS, and similar processors. -// Also thie file contains a custom refinfo handler for the HA16 type. - -#include <fixup.hpp> - -//-------------------------------------------------------------------------- -// 'apply' a fixup: take it into account while analyzing the file -// usually it consists of converting the operand into an offset expression -static bool idaapi ha16_apply( - const fixup_handler_t *fh, - ea_t item_ea, - ea_t fixup_ea, - int opnum, - bool is_macro, - const fixup_data_t &fd) -{ - if ( is_unknown(get_flags(item_ea)) ) - create_16bit_data(fixup_ea, 2); - - refinfo_t ri; - ri.base = fd.get_base(); - ri.target = ri.base + fd.off; - ri.tdelta = fd.displacement; - ri.flags = REFINFO_CUSTOM; - - if ( is_macro ) - { // it is a macro instruction, check for the second fixup within it - fixup_data_t fdl; - ea_t end = get_item_end(item_ea); - while ( true ) - { - fixup_ea = get_next_fixup_ea(fixup_ea); - if ( fixup_ea >= end ) - return false; // could not find the fixup for the low part - if ( fdl.get(fixup_ea) && fdl.get_type() == FIXUP_LOW16 ) - break; // found the pair! - } -// if ( int16(fdl.off + fdl.displacement) < 0 ) -// ri->tdelta -= 0x10000; - ri.flags = REF_OFF32; - ri.target = BADADDR; - } - else - { - ri.set_type(fh->reftype); - } - if ( processor_t::adjust_refinfo(&ri, fixup_ea, opnum, fd) < 0 ) - return false; - op_offset_ex(item_ea, opnum, &ri); - return true; -} - -//-------------------------------------------------------------------------- -static uval_t idaapi ha16_get_value(const fixup_handler_t * /*fh*/, ea_t ea) -{ - // we can't get the exact value of this fixup as it depends on the low - // part - return get_word(ea) << 16; -} - -//---------------------------------------------------------------------------- -static bool idaapi ha16_patch_value( - const fixup_handler_t * /*fh*/, - ea_t ea, - const fixup_data_t &fd) -{ - // compensate signed low part - ea_t expr = fd.off + fd.displacement + 0x8000; -#ifdef __EA64__ - // in the case of 32-bit reloc we have to check overflow, - // for simplicity we don't do. - // overflow = is32bit_reloc && expr > UINT_MAX; -#endif - put_word(ea, expr >> 16); - return true; -} - -//-------------------------------------------------------------------------- -#define DEF_CFH_HA16(name) fixup_handler_t name = \ -{ \ - sizeof(fixup_handler_t), \ - "HIGHA16", /* name */ \ - 0, /* props */ \ - 2, 0, 0, 0, /* size, width, shift */ \ - REFINFO_CUSTOM, /* reftype */ \ - ha16_apply, /* apply */ \ - ha16_get_value, /* get_value */ \ - ha16_patch_value, /* patch_value */ \ -} - -// ALPHA, MIPS, PPC, TRICORE include this file but do not use fixup handler. -static QUNUSED DEF_CFH_HA16(cfh_ha16); -//lint -esym(2466,cfh_ha16) was used despite being marked as 'unused' - -//-------------------------------------------------------------------------- -inline bool was_displacement_generated(const char *buf) -{ - const char *ptr = strchr(buf, COLOR_SYMBOL); // is there a displacement? - return ptr != NULL && (ptr[1] == '+' || ptr[1] == '-'); -} - -//-------------------------------------------------------------------------- -// get reference data from ri, -// check compliance of opval and the full value -static bool idaapi ha16_calc_reference_data( - ea_t *target, - ea_t *base, - ea_t /*from*/, - const refinfo_t &ri, - adiff_t opval) -{ - if ( ri.target == BADADDR - || ri.base == BADADDR - || ri.is_subtract() ) - { - return false; - } - ea_t fullvalue = ri.target + ri.tdelta - ri.base; - int16 calc_opval = (fullvalue >> 16) & 0xFFFF; - if ( (fullvalue & 0x8000) != 0 ) - calc_opval += 1; - if ( calc_opval != int16(opval) ) - return false; - - *target = ri.target; - *base = ri.base; - return true; -} - -//-------------------------------------------------------------------------- -// simple format -static void idaapi ha16_get_format(qstring *format) -{ - *format = COLSTR("%s@ha", SCOLOR_KEYWORD); -} - -//-------------------------------------------------------------------------- -static const custom_refinfo_handler_t ref_ha16 = -{ - sizeof(custom_refinfo_handler_t), - "HIGHA16", - "high adjusted 16 bits of 32-bit offset", - 0, // properties (currently 0) - NULL, // gen_expr - ha16_calc_reference_data, // calc_reference_data - ha16_get_format, // get_format -}; diff --git a/idasdk75/module/cr16/cr16.hpp b/idasdk75/module/cr16/cr16.hpp deleted file mode 100644 index 7298e4c..0000000 --- a/idasdk75/module/cr16/cr16.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * National Semiconductor Corporation CR16 processor module for IDA. - * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#ifndef _CR16_HPP -#define _CR16_HPP - -#include <ida.hpp> -#include <idp.hpp> - -#include "../idaidp.hpp" -#define near -#define far -#include "ins.hpp" -#include "../iohandler.hpp" - -// ============================================================ -// specflags1 bits -//----------------------------------------------- -#define URR_PAIR (0x01) // indirect reference via reg pair - -//------------------------------------------------------------------------ -// processor registers -enum CR16_registers -{ - rNULLReg, - rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7, - rR8, rR9, rR10, rR11, rR12, rR13, rRA, rSP, - // special registers - rPC, rISP, rINTBASE, rPSR, rCFG, rDSR, rDCR, - rCARL, rCARH, rINTBASEL, rINTBASEH, - rVcs, rVds -}; - -//------------------------------------------------------------------------ -int idaapi CR16_ana(insn_t *_insn); -int idaapi CR16_emu(const insn_t &insn); - -//------------------------------------------------------------------------ -struct cr16_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - bool flow = false; // flow stop flag - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void CR16_header(outctx_t &ctx); - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - int CR16_emu(const insn_t &insn); - - void CR16_segstart(outctx_t &ctx, segment_t *Sarea) const; - void CR16_footer(outctx_t &ctx) const; -}; - - -#endif diff --git a/idasdk75/module/cr16/emu.cpp b/idasdk75/module/cr16/emu.cpp deleted file mode 100644 index a177976..0000000 --- a/idasdk75/module/cr16/emu.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - * National Semiconductor Corporation CR16 processor module for IDA. - * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "cr16.hpp" - -//---------------------------------------------------------------------- -// handle using/changing of operands -void cr16_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) -{ - ea_t ea = map_code_ea(insn, x); - - switch ( x.type ) - { - // nothing to do - case o_void: - case o_reg: - case o_displ: - break; - - // immediate operand - case o_imm: - // can't be changed - if ( !isload ) - goto badTouch; - set_immd(insn.ea); - // if not forced and marked as offset - if ( !is_forced && is_off(get_flags(insn.ea), x.n) ) - { - // it's an offset - if ( x.dtype == dt_word ) - ea &= 0xFFFF; - else if ( x.dtype == dt_byte ) - ea &= 0xFF; - insn.add_dref(ea, x.offb, dr_O); - } - break; - - // jump or call - case o_near: - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - // add cross-reference - insn.add_cref(ea, x.offb, fl_CN); - // doesn't return? - flow = func_does_return(ea); - } - else - { - insn.add_cref(ea, x.offb, fl_JN); - } - break; - - // memory reference - case o_mem: - // make data at target address - insn.create_op_data(ea, x); - // add xref to memory - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - break; - - // other - report error - default: - badTouch: - warning("%a %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); - break; - } -} - -//---------------------------------------------------------------------- -// emulator -int cr16_t::CR16_emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - - // get operand types - bool flag1 = is_forced_operand(insn.ea, 0); - bool flag2 = is_forced_operand(insn.ea, 1); - - flow = ((Feature & CF_STOP) == 0); - - // handle reads - if ( Feature & CF_USE1 ) - handle_operand(insn, insn.Op1, flag1, true); - if ( Feature & CF_USE2 ) - handle_operand(insn, insn.Op2, flag2, true); - - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - // handle writes - if ( Feature & CF_CHG1 ) - handle_operand(insn, insn.Op1, flag1, false); - if ( Feature & CF_CHG2 ) - handle_operand(insn, insn.Op2, flag2, false); - // if not stopping, add flow xref - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - return 1; -} diff --git a/idasdk75/module/cr16/makefile b/idasdk75/module/cr16/makefile deleted file mode 100644 index 5f89762..0000000 --- a/idasdk75/module/cr16/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=cr16 -CONFIGS=cr16.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp cr16.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - cr16.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - cr16.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - cr16.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp cr16.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/cr16/out.cpp b/idasdk75/module/cr16/out.cpp deleted file mode 100644 index b93d7de..0000000 --- a/idasdk75/module/cr16/out.cpp +++ /dev/null @@ -1,195 +0,0 @@ - -/* - * National Semiconductor Corporation CR16 processor module for IDA. - * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "cr16.hpp" - -//---------------------------------------------------------------------- -class out_CR16_t : public outctx_t -{ - out_CR16_t(void) = delete; // not used -public: - void OutVarName(const op_t &x); - - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_CR16_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_CR16_t) - -//---------------------------------------------------------------------- -void out_CR16_t::OutVarName(const op_t &x) -{ - ea_t toea = map_code_ea(insn, x); - - if ( !out_name_expr(x, toea, x.addr) ) - { - out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); - remember_problem(PR_NONAME, insn.ea); - } -} - -//---------------------------------------------------------------------- -// output one operand -bool out_CR16_t::out_operand(const op_t &x) -{ - int flags; - switch ( x.type ) - { - case o_displ: - //out_value(insn, x, OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED|OOFW_32); - out_value(x, /*OOFS_NOSIGN | */ OOF_ADDR | OOF_SIGNED | OOFW_IMM); - out_symbol('('); - if ( x.specflag1 & URR_PAIR ) - { - out_register(ph.reg_names[x.reg + 1]); - out_symbol(','); - out_register(ph.reg_names[x.reg]); - } - else - { - out_register(ph.reg_names[x.reg]); - } - out_symbol(')'); - break; - - case o_reg: - if ( x.specflag1 & URR_PAIR ) - { - out_symbol('('); - out_register(ph.reg_names[x.reg + 1]); - out_symbol(','); - out_register(ph.reg_names[x.reg]); - out_symbol(')'); - } - else - { - out_register(ph.reg_names[x.reg]); - } - break; - - case o_imm: - out_symbol('$'); - flags = /*OOFS_NOSIGN | OOF_SIGNED | */OOFW_IMM; - switch ( insn.itype ) - { - case CR16_addb: - case CR16_addw: - case CR16_addub: - case CR16_adduw: - case CR16_addcb: - case CR16_addcw: - case CR16_ashub: - case CR16_ashuw: - case CR16_lshb: - case CR16_lshw: - flags |= OOF_SIGNED; - break; - } - out_value(x, flags); - break; - - case o_near: - OutVarName(x); - break; - - case o_mem: - OutVarName(x); - break; - - case o_void: - return 0; - - default: - warning("out: %a: bad optype %d", insn.ea, x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -// main output function -void out_CR16_t::out_insn(void) -{ - // print mnemonic - out_mnemonic(); - - // print first operand - if ( insn.Op1.type != o_void ) - out_one_operand(0); - - // print second operand - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -// header of the listing -void cr16_t::CR16_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, ioh.device.c_str(), ioh.deviceparams.c_str()); -} - -//-------------------------------------------------------------------------- -// segment start -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Sarea) could be made const -void cr16_t::CR16_segstart(outctx_t &ctx, segment_t *Sarea) const -{ - const char *SegType = Sarea->type == SEG_CODE ? "CSEG" - : Sarea->type == SEG_DATA ? "DSEG" - : "RSEG"; - // print RSEG <NAME> - qstring sn; - - get_visible_segm_name(&sn, Sarea); - ctx.gen_printf(-1, "%s %s ", SegType, sn.c_str()); - // if offset not zero, print it (ORG XXXX) - if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) - { - ea_t org = ctx.insn_ea - get_segm_base(Sarea); - - if ( org != 0 ) - { - char bufn[MAX_NUMBUF]; - btoa(bufn, sizeof(bufn), org); - ctx.gen_printf(-1, "%s %s", ash.origin, bufn); - } - } -} - -//-------------------------------------------------------------------------- -// end of listing -void cr16_t::CR16_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - size_t i = strlen(ash.end); - do - ctx.out_char(' '); - while ( ++i < 8 ); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} diff --git a/idasdk75/module/cr16/reg.cpp b/idasdk75/module/cr16/reg.cpp deleted file mode 100644 index c8bbb37..0000000 --- a/idasdk75/module/cr16/reg.cpp +++ /dev/null @@ -1,246 +0,0 @@ - -/* - * National Semiconductor Corporation CR16 processor module for IDA. - * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "cr16.hpp" -#include <diskio.hpp> -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -// list of registers -static const char *const RegNames[] = -{ - // empty - "", - // general purpose - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "ra", "sp", - // special - "pc", "isp", "intbase", "psr", "cfg", "dsr", "dcr", "carl", "carh", - "intbaseh", "intbasel", - - // pseudo segments - "cs", "ds" -}; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new cr16_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi cr16_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - inf_set_be(false); - inf_set_gen_lzero(true); - helper.create("$ CR16"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - // ask for a processor from the config file - // use it to handle ports and registers - { - char cfgfile[QMAXFILE]; - - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - break; - - case processor_t::ev_ending_undo: - //fall through - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - CR16_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - CR16_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - CR16_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return CR16_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return CR16_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const asm_t pseudosam = -{ - AS_COLON | AS_UDATA | ASH_HEXF3 | ASD_DECF0, - // user flags - 0, - "Generic CR16 assembler", // title - 0, // help id - NULL, // header - "org", // ORG directive - "end", // end directive - - ";", // comment - '"', // string delimiter - '\'', // character constant - "\\\"'", // special characters - - "db", // ascii string directive - ".byte", // byte directive - ".word", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "#d dup(#v)", // arrays (#h,#d,#v,#s(...) - "db ?", // uninited arrays - ".equ", // equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - NULL, // Generate function header lines - NULL, // Generate function footer lines - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // Get name of type of item at ea or id - ".ALIGN", // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -// list of assemblers -static const asm_t *const asms[] = { &pseudosam, NULL }; - -//----------------------------------------------------------------------- -#define FAMILY "NSC CR16:" - -// short names -static const char *const shnames[] = { "CR16", NULL }; - -// long names -static const char *const lnames[] = { FAMILY"NSC CR16", NULL }; - -//-------------------------------------------------------------------------- -// return instructions -static const uchar retcode_1[] = { 0x00, 0x0B }; // RTS - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_CR16, // processor ID - // flag - PR_USE32 - | PR_BINMEM - | PR_SEGTRANS, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for data segments - - shnames, // short processor names (NULL terminated) - lnames, // long processor names (NULL terminated) - - asms, // assemblers - - notify, // Event notification handler - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs, rVds, - 2, // size of a segment register - rVcs, rVds, - NULL, // Array of typical code start sequences - retcodes, // Array of 'return' instruction opcodes - 0, CR16_last, // icode of the first and the last instruction - Instructions, // instruc - 3, // Size of long double (tbyte) for this processor - 24 bits - {0, 0, 0, 0}, // Number of digits in floating numbers after the decimal point - 0, // Icode of return instruction - NULL, // micro virtual mashine -}; diff --git a/idasdk75/module/dsp56k/ana.cpp b/idasdk75/module/dsp56k/ana.cpp deleted file mode 100644 index c66f5b1..0000000 --- a/idasdk75/module/dsp56k/ana.cpp +++ /dev/null @@ -1,2945 +0,0 @@ -/* - Motorola DSP56K processor module for IDA. - The instruction decoder of this processor module is based on the disassembler - for DSP5600x processor by Miloslaw Smyk. - - The source code was modified to conform IDA by Ilfak Guilfanov. - Support for DSP 563xx was added by Ivan Litvin <ltv@microset.ru> (December 2003) - Support for DSP 561xx was added by Ivan Litvin <ltv@microset.ru> (January 2004) - -*/ - -/* - * Copyright (c) 1998 Miloslaw Smyk - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Miloslaw Smyk - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include "dsp56k.hpp" - -#define FUNCS_COUNT 5 -#define F_SWITCH nullptr -//lint -e1762 member function 'dsp56k_t::' could be made const - - -struct funcdesc_t -{ - bool (dsp56k_t:: *func)(insn_t &, int); - uint32 mask; - uint32 shift; -}; - -struct opcode_t -{ - ushort proc; -#define p5600x 0x01 // valid for 5600x -#define p561xx 0x02 // valid for 561xx -#define p563xx 0x04 // valid for 563xx -#define p566xx 0x08 // valid for 566xx - -#define pall (p5600x|p561xx|p563xx|p566xx) -#define p_1 p561xx -#define p_0_3 (p5600x|p563xx) -#define p_3_6 (p563xx|p566xx) - - ushort itype; - const char *recog; //lint !e958 padding is required to align members - char pmov_cl; // class of acceptable parallel movs for the instruction - funcdesc_t funcs[FUNCS_COUNT]; //lint !e958 padding is required to align members - uint32 mask; - uint32 value; -}; - -struct par_move -{ - ushort proc; - const char *recog; //lint !e958 padding is required to align members - funcdesc_t funcs[FUNCS_COUNT]; - ushort mask; - ushort value; -}; - -//---------------------------------------------------------------------- -static uint32 ua_next_24bits(insn_t &insn) -{ - uint32 x = get_wide_byte(insn.ea+insn.size); - insn.size++; - return x; -} - -//---------------------------------------------------------------------- -static uint32 ua_32bits(const insn_t &insn) -{ - - uint32 x = ((get_wide_byte(insn.ea) ) & 0x0000FFFF) - | ((get_wide_byte(insn.ea+1) << 16) & 0xFFFF0000); - return x; -} - - -//---------------------------------------------------------------------- -// make sure that the additional args are good -void dsp56k_t::fill_additional_args(const insn_t &insn) const -{ - if ( aa.ea != insn.ea ) - { - insn_t tmp; - decode_insn(&tmp, insn.ea); - } -} - -//---------------------------------------------------------------------- -void dsp56k_t::switch_to_additional_args(insn_t &) -{ - op = aa.args[aa.nargs++]; - op[0].flags = OF_SHOW; - op[1].flags = OF_SHOW; - op[0].n = 1; // just something else than 0 - op[1].n = 1; // just something else than 0 -} - -//---------------------------------------------------------------------- -inline void dsp56k_t::opreg(insn_t &, int reg) -{ - op->type = o_reg; - op->reg = (uint16)reg; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_EE(insn_t &insn, int value) -{ - uchar reg; - if ( is561xx() ) - { - static const char regs[] = { -1, MR, CCR, OMR }; - - if ( value < 1 ) - return false; - - reg = regs[value]; - } - else - { - static const char regs[] = { MR, CCR, OMR }; - - if ( value == 3 ) - return false; - - reg = regs[value]; - } - opreg(insn, reg); - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_DDDDD(insn_t &insn, int value) -{ - if ( is561xx() ) - { - static const uchar regs[] = - { - X0, Y0, X1, Y1, A, B, A0, B0, - uchar(-1), SR, OMR,SP, A1, B1, A2, B2, - R0, R1, R2, R3, M0, M1, M2, M3, - SSH,SSL,LA, LC, N0, N1, N2, N3 - }; - - if ( value >= qnumber(regs) ) - return false; - opreg(insn, regs[value]); - if ( op->reg == uchar(-1) ) - return false; - } - else - { - static const uchar regs[] = { 0, SR, OMR, SP, SSH, SSL, LA, LC }; - if ( value < 8 ) - { - opreg(insn, M0 + (value & 7)); - } - else - { - value &= 7; - if ( value == 0 ) - return false; - opreg(insn, regs[value & 7]); - } - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_ff(const insn_t &insn, int value, int reg_bank) -{ - op->type = o_reg; - switch ( value ) - { - case 0: - op->reg = reg_bank ? Y0 : X0; - break; - case 1: - op->reg = reg_bank ? Y1 : X1; - break; - case 2: - op->reg = A; - break; - case 3: - op->reg = B; - break; - default: - interr(&insn, "D_ff"); - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_df(insn_t &insn, int value, int reg_bank) -{ - opreg(insn, value & 0x02 ? B : A); - op++; - opreg(insn, reg_bank - ? (value & 1) ? X1 : X0 - : (value & 1) ? Y1 : Y0); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_xi(insn_t &, int value) -{ - op->type = o_imm; - op->value = is561xx() ? (value & 0xFF) : value; - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_ximm(insn_t &insn, int /*value*/) -{ - op->type = o_imm; - op->value = ua_next_24bits(insn); - if ( is566xx() ) - op->value &= 0xffff; - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_ximm(insn_t &insn, int value) -{ - if ( D_ximm(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_sssss(insn_t &, int value) -{ - static const int vals[] = - { - 0x800000, 0x400000, 0x200000, 0x100000, - 0x080000, 0x040000, 0x020000, 0x010000, - 0x008000, 0x004000, 0x002000, 0x001000, - 0x000800, 0x000400, 0x000200, 0x000100, - 0x000080, 0x000040, 0x000020, 0x000010, - 0x000008, 0x000004, 0x000002, 0x000001, - 0x000000, 0x000000, 0x000000, 0x000000, - 0x000000, 0x000000, 0x000000, 0x000000, - }; - - op->type = o_imm; - op->value = vals[value & 0x1f]; - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_ssss(insn_t &, int value) -{ - static const int vals[] = - { - 0x8000, 0x4000, 0x2000, 0x1000, - 0x0800, 0x0400, 0x0200, 0x0100, - 0x0080, 0x0040, 0x0020, 0x0010, - 0x0008, 0x0004, 0x0002, 0x0001 - }; - - op->type = o_imm; - op->value = vals[value & 0xf]; - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_xih(insn_t &, int value) -{ - op->type = o_imm; - op->value = (value & 0xF) << 8; - op->value |= (value >> 8) & 0xFF; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_xih(insn_t &insn, int value) -{ - if ( D_xih(insn, value) ) - { - op++; - return true; - } - return false; -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_d(insn_t &insn, int value) -{ - if ( value ) - { - opreg(insn, A); - op++; - opreg(insn, B); - } - else - { - opreg(insn, B); - op++; - opreg(insn, A); - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::SS_JJJd(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - - if ( value > 1 && value < 8 ) - return false; - - switch ( value >> 1 ) - { - case 0: - return SD_d(insn, value & 0x01); - - default: - opreg(insn, regs[(value >> 1) - 4]); - op++; - break; - } - opreg(insn, value & 0x01 ? B : A); - return true; -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_JJJd(insn_t &insn, int value) -{ - static const uchar regs[] = { X, Y, X0, Y0, X1, Y1 }; - switch ( value >> 1 ) - { - case 0: - return false; - - case 1: - return SD_d(insn, value & 0x01); - - default: - opreg(insn, regs[(value >> 1) - 2]); - op++; - break; - } - opreg(insn, value & 0x01 ? B : A); - return true; -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_Jd(insn_t &insn, int value) -{ - opreg(insn, (value & 2) ? Y : X); - op++; - opreg(insn, (value & 1) ? B : A); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_d(insn_t &insn, int value) -{ - opreg(insn, value ? B : A); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_S(insn_t &insn, int value) -{ - if ( D_d(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_JJd(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - opreg(insn, regs[value>>1]); - op++; - return D_d(insn, value & 0x01); -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_dddd(insn_t &insn, int value) -{ - opreg(insn, ((value & 8) ? N0 : R0) + (value & 0xF)); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_ddddd(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, X1, Y0, Y1, A0, B0, A2, B2, A1, B1, A, B }; - - if ( value >= 4 ) - { - if ( value < 16 ) - opreg(insn, regs[value - 4]); - else - opreg(insn, ((value < 24) ? R0 : N0) + (value & 7)); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_ddddd(insn_t &insn, int value) -{ - if ( D_ddddd(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_LLL(insn_t &insn, int value) -{ - static const uchar regs[] = { A10, B10, X, Y, A, B, AB, BA }; - opreg(insn, regs[value]); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_sss(insn_t &insn, int value) -{ - static const char regs[] = { -1, -1, A1, B1, X0, Y0, X1, Y1 }; - - if ( value > 1 ) - { - opreg(insn, regs[value]); - return true; - } - else - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_sss(insn_t &insn, int value) -{ - if ( D_sss(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_qqq(insn_t &insn, int value) -{ - static const char regs[] = { -1, -1, A0, B0, X0, Y0, X1, Y1 }; - - if ( value > 1 ) - { - opreg(insn, regs[value]); - return true; - } - else - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_qqq(insn_t &insn, int value) -{ - if ( D_qqq(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_qq(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - - opreg(insn, regs[value & 0x03]); - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_QQ(insn_t &insn, int value) -{ - int idx = value & 0x03; - if ( is561xx() ) - { - static const uchar regs1[] = { X0, X0, X1, X1 }; - static const uchar regs2[] = { Y0, Y1, Y0, Y1 }; - opreg(insn, regs1[idx]); - op++; - opreg(insn, regs2[idx]); - } - else - { - static const uchar regs[] = { Y1, X0, Y0, X1 }; - opreg(insn, regs[idx]); - } - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_gggd(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - - if ( value < 2 ) - { - opreg(insn, value == 0 ? B : A); - } - else - { - opreg(insn, regs[(value>>1) & 0x03]); - } - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_MMRRR(insn_t &, int value) -{ - op->type = o_phrase; - op->phrase = value & 0x07; - op->phtype = uchar(value >> 3); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_MMRRR(insn_t &insn, int value) -{ - if ( D_MMRRR(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_MMRRR_XY(insn_t &, int value) -{ - static const char phtypes[] = - { - 4, // (Rn) - 1, // (Rn)+Nn - 2, // (Rn)- - 3 // (Rn)+ - }; - op->type = o_phrase; - op->phrase = value & 0x07; - op->phtype = phtypes[value >> 3]; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_pppppp(insn_t &, int value) -{ - int base = is563xx() ? 0xFFFFC0 : 0xFFC0; - - value += base; - - op->amode |= amode_ioshort; - op->type = o_mem; - op->addr = value; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_pppppp(insn_t &insn, int value) -{ - if ( D_pppppp(insn, value) ) - { - op++; - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_qqqqqq(insn_t &, int value) -{ - int base = is563xx() ? 0xFFFF80 : 0xFF80; - - value += base; - - op->amode |= amode_ioshort; - op->type = o_mem; - op->addr = value; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_qqqqqq(insn_t &insn, int value) -{ - if ( D_qqqqqq(insn, value) ) - { - op++; - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_qXqqqqq(insn_t &insn, int value) -{ - return D_qqqqqq(insn, (value & 0x1f) + ((value & 0x40)>>1)); -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_DDDDDD(insn_t &insn, int value) -{ - static const char regs[] = - { - -1, -1, -1, -1, X0, X1, Y0, Y1, - A0, B0, A2, B2, A1, B1, A, B, - R0, R1, R2, R3, R4, R5, R6, R7, - N0, N1, N2, N3, N4, N5, N6, N7, - M0, M1, M2, M3, M4, M5, M6, M7, - -1, -1, EP, -1, -1, -1, -1, -1, - VBA, SC, -1,-1, -1, -1, -1, -1, - SZ, SR, OMR,SP, SSH,SSL,LA, LC - }; - - if ( value >= qnumber(regs) ) - return false; - char r = regs[value]; - if ( r == -1 ) - return false; - opreg(insn, r); - //if ( op->reg >= SZ && !is563xx() ) return false; - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_DDDDDD(insn_t &insn, int value) -{ - if ( D_DDDDDD(insn, value) ) - { - op++; - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_DDDD(insn_t &insn, int value) -{ - if ( D_DDDDDD(insn, value & 0x0f) ) - return true; - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_RRR(insn_t &insn, int value) -{ - opreg(insn, R0 + value); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_RRR(insn_t &insn, int value) -{ - opreg(insn, R0 + value); - op++; - return true; -} - -//---------------------------------------------------------------------- -//lint -e{1764} insn could be const -void dsp56k_t::make_o_mem(insn_t &insn) -{ - if ( !(op->amode & (amode_x|amode_y)) ) switch ( insn.itype ) - { - case DSP56_do: - case DSP56_do_f: - case DSP56_dor: - case DSP56_dor_f: - if ( !is561xx() ) - op->addr++; - // no break - case DSP56_jcc: - case DSP56_jclr: - case DSP56_jmp: - case DSP56_jscc: - case DSP56_jsclr: - case DSP56_jsr: - case DSP56_jsset: - case DSP56_jset: - - case DSP56_bcc: - case DSP56_bra: - case DSP56_brclr: - case DSP56_brset: - case DSP56_bscc: - case DSP56_bsclr: - case DSP56_bsr: - case DSP56_bsset: - op->type = o_near; - op->dtype = dt_code; - return; - } - op->type = o_mem; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_mMMMRRR(insn_t &insn, int value) -{ - if ( !(value & 0x40) ) - { - op->amode |= amode_short; // < - op->addr = value & 0x3F; - make_o_mem(insn); - return true; - } - - value &= ~0x40; - - D_MMRRR(insn, value); // phrase - if ( op->phtype == 6 ) - { - if ( value & 0x4 ) - { - op->type = o_imm; - op->value = ua_next_24bits(insn); - if ( is566xx() ) - op->value &= 0xffff; - } - else - { - op->addr = ua_next_24bits(insn); - if ( is566xx() ) - op->addr &= 0xffff; - make_o_mem(insn); - } - } - return true; -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::S_mMMMRRR(insn_t &insn, int value) -{ - if ( D_mMMMRRR(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_aaaaaa(insn_t &insn, int value) -{ - if ( D_mMMMRRR(insn, value & 0x3f) == true ) - { - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_aaaaaa(insn_t &insn, int value) -{ - if ( D_aaaaaa(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_MMMRRR(insn_t &insn, int value) -{ - if ( D_mMMMRRR(insn, value | 0x40) == true ) - { - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_MMMRRR(insn_t &insn, int value) -{ - if ( D_MMMRRR(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::P_type(insn_t &, int) -{ - op->amode |= amode_p; - return true; -} - -//------------------------------------------------------------------ -bool dsp56k_t::X_type(insn_t &, int) -{ - op->amode |= amode_x; - return true; -} - -//------------------------------------------------------------------ -bool dsp56k_t::Y_type(insn_t &, int) -{ - op->amode |= amode_y; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::mem_type(insn_t &, int value) -{ - if ( value == 1 ) - op->amode |= amode_y; - else - op->amode |= amode_x; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::space(insn_t &insn, int) -{ - switch_to_additional_args(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::sign(insn_t &, int value) -{ - if ( value == 1 ) - op->amode |= amode_neg; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::AAE(insn_t &insn, int) -{ - op->addr = ushort(ua_next_24bits(insn)); - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_PC_dispL(insn_t &insn, int value) -{ - if ( is561xx() ) - { - op->addr = insn.ea + short(value) + 2; // +2 - PC should point to next instruction - } - else - { - value = ua_next_24bits(insn); - if ( is566xx() ) - { - op->addr = insn.ea + short(value); - } - else - { - if ( value & 0x00800000 ) - value |= ~0x007FFFFF; - op->addr = insn.ea + value; - } - } - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_PC_dispL(insn_t &insn, int value) -{ - if ( D_PC_dispL(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_PC_dispS(insn_t &insn, int value) -{ - value = (value & 0x1f) + ((value & 0x3c0) >> 1); - - if ( value & 0x100 ) - { - value = (value^0x1ff) + 1; - op->addr = insn.ea - value; - } - else - { - op->addr = insn.ea + value; - } - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_PC_RRR(insn_t &, int value) -{ - op->type = o_phrase; - op->phrase = (uint16)value; - op->phtype = 8; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_RRR_dispL(insn_t &insn, int value) -{ - op->type = o_displ; - op->reg = value & 0x07; - op->phtype = 0; // "R + displ" - - value = ua_next_24bits(insn); - if ( is566xx() ) - op->value &= 0xffff; - - if ( is566xx() ) - { - if ( value & 0x8000 ) - { - value = (value^0xffff) + 1; - op->phtype = 1; // "R - displ" - } - } - else - { - if ( value & 0x800000 ) - { - value = (value^0xffffff) + 1; - op->phtype = 1; // "R - displ" - } - } - - - op->addr = value; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_RRR_dispS(insn_t &, int value) -{ - op->type = o_displ; - op->reg = (value >> 2) & 0x07; - op->phtype = 0; // "R + displ" - - value = (value & 0x1) + ((value & 0x7e0) >> 4); - - if ( value & 0x40 ) - { - op->phtype = 1; // "R - displ" - value = (value^0x7f) + 1; - } - - op->addr = value; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_RR_dispS(insn_t &, int value) -{ - - op->type = o_displ; - op->reg = (value >> 4) & 0x07; - op->phtype = 0; // "R + displ" - - value = (value & 0x0f) + ((value & 0x380) >> 3); - - if ( value & 0x40 ) - { - op->phtype = 1; // "R - displ" - value = (value^0x7f) + 1; - } - - op->addr = value; - op++; - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::AA(insn_t &, int value) -{ - op->amode |= amode_short; - - op->type = o_near; - op->dtype = dt_code; - op->addr = value; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_F(insn_t &insn, int value) -{ - opreg(insn, value ? B : A); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_F(insn_t &insn, int value) -{ - if ( D_F(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::CCCC(insn_t &insn, int value) -{ - insn.auxpref |= value & 0xF; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::s(insn_t &insn, int value) -{ - static const char s_u[] = { s_SU, s_UU }; - - insn.auxpref |= s_u[value & 0x01]; - return true; -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::ss(insn_t &insn, int value) -{ - static const char s_u[] = { s_SS, s_SS, s_SU, s_UU }; - - int idx = is561xx() - ? ((value & 0x08)>>2) + (value & 0x01) - : ((value & 0x04)>>1) + (value & 0x01); - insn.auxpref |= s_u[idx]; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_IIII(insn_t &insn, int value) -{ - //0100IIII----F--- - static const char regs1[] = - { - X0, Y0, X1, Y1, - A, B, A0, B0, - -1, -1, -1, -1, - A, B, A0, B0 - }; - - static const char regs2[] = - { - -1, -1, -1, -1, - X0, Y0, X0, Y0, - -1, -1, -1, -1, - X1, Y1, X1, Y1 - }; - - unsigned idx = ((value >> 8) & 0x0f); - - if ( idx < 4 ) - { - op->type = o_reg; - op->reg = regs1[idx]; - op++; - D_F(insn, ((value & 0x08)>>3) ^ 0x01); - return true; - } - - if ( ( idx == 8 ) || ( idx == 9 ) ) - { - S_F(insn, ((value & 0x08)>>3)); - D_F(insn, ((value & 0x08)>>3) ^ 0x01); - return true; - } - - - if ( ( idx == 0x0a ) || ( idx == 0x0b ) ) - return false; - - op->type = o_reg; - op->reg = regs1[idx]; - if ( regs1[idx] == -1 ) - return false; - op++; - op->type = o_reg; - op->reg = regs2[idx]; - if ( regs2[idx] == -1 ) - return false; - - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_zRR(insn_t &, int value) -{ - //00110zRR----F--- - - op->type = o_phrase; - op->phrase = (value >> 8) & 0x03; - if ( ((value >> 10) & 0x01) == 1 ) - op->phtype = 1; - else - op->phtype = 2; - - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_mRR(insn_t &, int value) -{ - op->type = o_phrase; - op->phrase = value & 0x03; - - if ( (value >> 2) & 0x01 ) - op->phtype = 1; - else - op->phtype = 3; - - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_RRm(insn_t &insn, int value) -{ - return D_mRR(insn, ((value & 0x06)>>1) + ((value & 0x01)<<2)); -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_RR11m(insn_t &insn, int value) -{ - return D_mRR(insn, ((value & 0x18)>>3) + (value <<2)); -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_MMRR(insn_t &, int value) -{ - op->type = o_phrase; - op->phrase = value & 0x03; - - switch ( (value & 0x0c)>>2 ) - { - case 0: - op->phtype = 4; - break; - case 1: - op->phtype = 3; - break; - case 2: - op->phtype = 2; - break; - case 3: - op->phtype = 1; - break; - } - - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::S_MMRR(insn_t &insn, int value) -{ - if ( D_MMRR(insn, value) ) - { - op++; - return true; - } - return false; -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_RR0MM(insn_t &insn, int value) -{ - return D_MMRR(insn, ((value & 0x18)>>3) + ((value & 0x03)<<2)); -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_qRR(insn_t &, int value) -{ - op->type = o_phrase; - op->phrase = value & 0x03; - - switch ( (value & 0x08)>>3 ) - { - case 0: - op->phtype = 1; - break; - case 1: - op->phtype = 7; - break; - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_HHH(insn_t &, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1, A, B, A0, B0 }; - - int idx = value & 0x07; - - op->type = o_reg; - op->reg = regs[idx]; - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_HH(insn_t &, int value) -{ - static const uchar regs[] = { X0, Y0, A, B }; - - int idx = value & 0x03; - - op->type = o_reg; - op->reg = regs[idx]; - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_mWRRHHH(insn_t &insn, int value) -//001001mWRRDDFHHH -{ - if ( value & 0x0100 ) - { - X_type(insn, 0); - D_mRR(insn, ((value & 0xc0)>>6) + ((value & 0x200)>>7)); - op++; - D_HHH(insn, value & 0x07); - } - else - { - D_HHH(insn, value & 0x07); - op++; - X_type(insn, 0); - D_mRR(insn, ((value & 0xc0)>>6) + ((value & 0x200)>>7)); - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_FJJJ(insn_t &insn, int value) -{ - static const char regs[] = { -1, -1, X, Y, X0, Y0, X1, Y1 }; - - int idx = value & 0x07; - - if ( idx != 0x01 ) - { - if ( idx ) - { - op->type = o_reg; - op->reg = regs[idx]; - } - else - { - opreg(insn, (value & 0x08) ? A : B); - } - op++; - return true; - } - else - { - return false; - } -} -//---------------------------------------------------------------------- -bool dsp56k_t::S_QQQ(insn_t &, int value) -{ - int idx = value & 0x07; - - if ( is561xx() ) - { - static const uchar regs1_61[] = { X0, X1, A1, B1, Y0, Y1, Y0, Y1 }; - static const uchar regs2_61[] = { X0, X0, Y0, X0, X0, X0, X1, X1 }; - op->type = o_reg; - op->reg = regs1_61[idx]; - op++; - op->type = o_reg; - op->reg = regs2_61[idx]; - op++; - } - else - { - static const uchar regs1_6x[] = { X0, Y0, X1, Y1, X0, Y0, X1, Y1 }; - static const uchar regs2_6x[] = { X0, Y0, X0, Y0, Y1, X0, Y0, X1 }; - op->type = o_reg; - op->reg = regs1_6x[idx]; - op++; - op->type = o_reg; - op->reg = regs2_6x[idx]; - op++; - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_QQ2(insn_t &, int value) -{ - static const uchar regs1[] = { Y0, Y1, Y0, Y1 }; - static const uchar regs2[] = { X0, X0, X1, X1 }; - - int idx = value & 0x03; - - op->type = o_reg; - op->reg = regs1[idx]; - op++; - op->type = o_reg; - op->reg = regs2[idx]; - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_QQQQ(insn_t &, int value) -{ - static const uchar regs1[] = { X0, Y0, X1, Y1, X0, Y0, X1, Y1, - X1, Y1, X0, Y0, Y1, X0, Y0, X1 }; - static const uchar regs2[] = { X0, Y0, X0, Y0, Y1, X0, Y0, X1, - X1, Y1, X1, Y1, X0, Y0, X1, Y1 }; - - int idx = value & 0xf; - op->type = o_reg; - op->reg = regs1[idx]; - op++; - op->type = o_reg; - op->reg = regs2[idx]; - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_Fh0h(insn_t &insn, int value) -{ - //000100ccccTTFh0h - static const char regs[] = { -1, -1, X0, Y0 }; - - if ( (((value & 0x04)>>1) + (value & 0x01)) > 1 ) - opreg(insn, regs[(((value & 0x04)>>1) + (value & 0x01))]); - else - opreg(insn, ((value & 0x08)>>3) == (value & 0x01) ? B : A); - - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_uFuuu_add(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - - if ( ((value & 0x07) + ((value & 0x10)>>1)) == 0x0c ) - { - opreg(insn, (value & 0x08) ? A : B); - op++; - return true; - } - if ( ((value & 0x07) + ((value & 0x10)>>1)) > 0x03 ) - return false; - - opreg(insn, regs[value & 0x03]); - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_uFuuu_sub(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - - if ( ((value & 0x07) + ((value & 0x10)>>1)) == 0x0d ) - { - opreg(insn, (value & 0x08) ? A : B); - op++; - return true; - } - if ( ((value & 0x07) + ((value & 0x10)>>1)) < 0x04 ) - return false; - - opreg(insn, regs[value & 0x03]); - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_RR(insn_t &insn, int value) -{ - opreg(insn, R0 + (value & 0x03)); - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::D_NN(insn_t &insn, int value) -{ - opreg(insn, N0 + (value & 0x03)); - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::DB_RR(insn_t &, int value) -{ - // P_type(0); - op->type = o_phrase; - op->phrase = (uint16)value; - op->phtype = 4; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_PC_RR(insn_t &, int value) -{ - // P_type(0); - op->type = o_phrase; - op->phrase = (uint16)value; - op->phtype = 8; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::DX_RR(insn_t &insn, int value) -{ - X_type(insn, 0); - op->type = o_phrase; - op->phrase = (uint16)value; - op->phtype = 4; - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_RR(insn_t &insn, int value) -{ - if ( D_RR(insn, value) ) - { - op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::m_A_B(insn_t &, int /*value*/) -{ - op->type = o_reg; - op->reg = A; - op++; - op->type = o_reg; - op->reg = B; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::IF(insn_t &, int /*value*/) -{ - op->type = o_iftype; - op->imode = imode_if; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::IFU(insn_t &, int /*value*/) -{ - op->type = o_iftype; - op->imode = imode_ifu; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_i(insn_t &insn, int value) -{ - op->type = o_vsltype; - insn.auxpref |= (value & 0x01); - op++; - op->amode |= amode_l; // set L type for last operand - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_TT(insn_t &insn, int value) -{ - //000100ccccTTFh0h >> 4 - - if ( (value & 0x03) == 0 ) // exclude bogus transfer R0 -> R0 - return true; - - opreg(insn, R0); - op++; - - if ( D_RR(insn, value & 0x03) ) - return true; - - return false; -} -//---------------------------------------------------------------------- -bool dsp56k_t::S_BBBiiiiiiii(insn_t &, int value) -{ - //BBB10010iiiiiiii0001010011Pppppp >> 16 - op->type = o_imm; - op->value = uint32((value & 0xff) << (((value & 0xe000) >> 14) * 4)); - op++; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_Pppppp(insn_t &insn, int value) -{ - X_type(insn, 0); - if ( value & 0x20 ) - { - op->amode |= amode_ioshort; // << - value = 0xffe0 + (value & 0x1f); - } - else - { - value = value & 0x1f; - } - - op->addr = value; - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_ppppp(insn_t &insn, int value) -{ - return D_Pppppp(insn, (value & 0x1f) + 0x20); -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_aaaaa(insn_t &insn, int value) -{ - return D_Pppppp(insn, value & 0x1f); -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_DDDDD(insn_t &insn, int value) -{ - if ( D_DDDDD(insn, value) ) - { - op++; - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_xi(insn_t &, int value) -{ - op->type = o_imm; - op->value = value & 0xff; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_xi16(insn_t &, int value) -{ - op->type = o_imm; - op->value = value & 0xffff; - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_xi_adr_16(insn_t &insn, int value) -{ - op->addr = value & 0xffff; - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_DD(insn_t &insn, int value) -{ - static const uchar regs[] = { X0, Y0, X1, Y1 }; - opreg(insn, regs[value & 0x03]); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::S_DD(insn_t &insn, int value) -{ - if ( D_DD(insn, value) ) - { - op++; - return true; - } - - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_Z(insn_t &, int value) -{ - op->type = o_phrase; - op->phrase = 0; - op->phtype = (value ? 9 : 10); - return true; -} - -//---------------------------------------------------------------------- -//new -bool dsp56k_t::D_t(insn_t &insn, int value) -{ - //xxxxxxxxxxxxxxxx00111WDDDDD1t10- >>3 - if ( value & 0x01 ) - { - D_xi16(insn, (value >> 13) & 0xffff); - } - else - { - X_type(insn, 0); - op->addr = (value >> 13) & 0xffff; - make_o_mem(insn); - } - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::SD_F00J(insn_t &insn, int value) -{ - opreg(insn, (value & 0x08) ? B : A); - op++; - opreg(insn, (value & 0x01) ? Y : X); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_PC_eeeeee(insn_t &insn, int value) -{ - if ( value & 0x20 ) - { - value = (value^0x3f) + 1; - op->addr = insn.ea - value + 1; // +1 - PC should point to next instruction - } - else - { - op->addr = insn.ea + value + 1; - } - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_PC_aaaaaaaa(insn_t &insn, int value) -{ - if ( value & 0x80 ) - { - value = (value^0xff) + 1; - op->addr = insn.ea - value + 1;// +1 - PC should point to next instruction - } - else - { - op->addr = insn.ea + value + 1; - } - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::D_BBBBBBBB(insn_t &, int value) -{ - op->type = o_displ; - op->reg = 2; - op->phtype = 0; // "R + displ" - - if ( value & 0x80 ) - { - value = ((value & 0xff) ^ 0xff) + 1; - op->phtype = 1; // "R - displ" - } - else - { - value = value & 0xff; - } - - op->addr = value; - return true; -} - -//---------------------------------------------------------------------- -static par_move pmoves_6x[] = -{ - { pall, "0010000000000000", },// no movement - { pall, "001dddddiiiiiiii", {{ &dsp56k_t::S_xi, 0x00ff }, { &dsp56k_t::D_ddddd, 0x1f00 }}, },// imm short move - { pall, "001000eeeeeddddd", {{ &dsp56k_t::S_ddddd, 0x03e0 }, { &dsp56k_t::D_ddddd, 0x001f }}, },// regto reg move - { pall, "00100000010MMRRR", {{ &dsp56k_t::D_MMRRR, 0x001f } }, },// Register update - { p563xx, "001000000010CCCC", {{ &dsp56k_t::IF, 0x0000 }, { &dsp56k_t::CCCC, 0x000f }}, },// Execute conditionally without CCR Update - { p563xx, "001000000011CCCC", {{ &dsp56k_t::IFU, 0x0000 }, { &dsp56k_t::CCCC, 0x000f }}, },// Execute conditionally with CCR Update -}; - -static opcode_t table_6x_24[] = -{ -// No Parallel move -//A - { p_3_6, DSP56_add, "0000000101iiiiii1000d000", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_add, "00000001010000001100d000", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_and, "0000000101iiiiii1000d110", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_and, "00000001010000001100d110", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_andi, "00000000iiiiiiii101110EE", 0, {{ &dsp56k_t::S_xi, 0x00ff00 }, { &dsp56k_t::D_EE, 0x000003 }, }}, - { p_3_6, DSP56_asl, "0000110000011101SiiiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00007e }, { &dsp56k_t::S_S, 0x000080 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_asl, "0000110000011110010SsssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_asr, "0000110000011100SiiiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00007e }, { &dsp56k_t::S_S, 0x000080 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_asr, "0000110000011110011SsssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, -//B - { p563xx, DSP56_bcc, "00001101000100000100CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, - { p_3_6, DSP56_bcc, "00000101CCCC01aaaa0aaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::D_PC_dispS, 0x03ff }, }}, - { p_3_6, DSP56_bcc, "0000110100011RRR0100CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_RRR, 0x000700 }, }}, - { p_0_3, DSP56_bchg, "000010110mMMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p566xx, DSP56_bchg, "000010110mMMMRRR0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p_0_3, DSP56_bchg, "0000101110pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p566xx, DSP56_bchg, "0000101110pppppp0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p563xx, DSP56_bchg, "0000000101qqqqqq0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p566xx, DSP56_bchg, "0000000101qqqqqq0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p_0_3, DSP56_bchg, "0000101111DDDDDD010bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p566xx, DSP56_bchg, "0000101111DDDDDD0100bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p_0_3, DSP56_bclr, "0000101011DDDDDD010bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p566xx, DSP56_bclr, "0000101011DDDDDD0100bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p_0_3, DSP56_bclr, "000010100mMMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p566xx, DSP56_bclr, "000010100mMMMRRR0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p563xx, DSP56_bclr, "0000000100qqqqqq0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p566xx, DSP56_bclr, "0000000100qqqqqq0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p_0_3, DSP56_bclr, "0000101010pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p566xx, DSP56_bclr, "0000101010pppppp0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p563xx, DSP56_bra, "000011010001000011000000", 0, {{ &dsp56k_t::D_PC_dispL,0x000000}, }}, - { p_3_6, DSP56_bra, "00000101000011aaaa0aaaaa", 0, {{ &dsp56k_t::D_PC_dispS,0x0003df}, }}, - { p_3_6, DSP56_bra, "0000110100011RRR11000000", 0, {{ &dsp56k_t::D_PC_RRR, 0x000700 }, }}, - { p563xx, DSP56_brclr, "0000110010MMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brclr, "0000110010aaaaaa1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brclr, "0000110011pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brclr, "0000010010qqqqqq0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brclr, "0000110011DDDDDD100bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x000 }, }}, - { p_3_6, DSP56_brkcc, "00000000000000100001CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, }}, - { p563xx, DSP56_brset, "0000110010MMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brset, "0000110010aaaaaa1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brset, "0000110011pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brset, "0000010010qqqqqq0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_brset, "0000110011DDDDDD101bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x001 }, }}, - { p563xx, DSP56_bscc, "00001101000100000000CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, - { p_3_6, DSP56_bscc, "00000101CCCC00aaaa0aaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::D_PC_dispS, 0x03df }, }}, - { p_3_6, DSP56_bscc, "0000110100011RRR0000CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_RRR, 0x0700 }, }}, - { p563xx, DSP56_bsclr, "0000110110MMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsclr, "0000110110aaaaaa1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsclr, "0000110111pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsclr, "0000010010qqqqqq1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsclr, "0000110111DDDDDD100bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p_0_3, DSP56_bset, "0000101011DDDDDD011bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p566xx, DSP56_bset, "0000101011DDDDDD0110bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p_0_3, DSP56_bset, "000010100mMMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p566xx, DSP56_bset, "000010100mMMMRRR0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p563xx, DSP56_bset, "0000000100qqqqqq0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p566xx, DSP56_bset, "0000000100qqqqqq0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p_0_3, DSP56_bset, "0000101010pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p566xx, DSP56_bset, "0000101010pppppp0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p563xx, DSP56_bsr, "000011010001000010000000", 0, {{ &dsp56k_t::D_PC_dispL,0x000000}, }}, - { p_3_6, DSP56_bsr, "00000101000010aaaa0aaaaa", 0, {{ &dsp56k_t::D_PC_dispS,0x0003df}, }}, - { p_3_6, DSP56_bsr, "0000110100011RRR10000000", 0, {{ &dsp56k_t::D_PC_RRR, 0x000700 }, }}, - { p563xx, DSP56_bsset, "0000110110MMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsset, "0000110110aaaaaa1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsset, "0000110111pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsset, "0000010010qqqqqq1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p563xx, DSP56_bsset, "0000110111DDDDDD101bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, - { p_0_3, DSP56_btst, "000010110mMMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p566xx, DSP56_btst, "000010110mMMMRRR0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, - { p_0_3, DSP56_btst, "0000101110pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p566xx, DSP56_btst, "0000101110pppppp0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, - { p563xx, DSP56_btst, "0000000101qqqqqq0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p566xx, DSP56_btst, "0000000101qqqqqq0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, - { p_0_3, DSP56_btst, "0000101111DDDDDD011bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { p566xx, DSP56_btst, "0000101111DDDDDD0110bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, -//C - { p_3_6, DSP56_clb, "0000110000011110000000SD", 0, {{ &dsp56k_t::S_S, 0x000002 }, { &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_cmp, "0000000101iiiiii1000d101", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_cmp, "00000001010000001100d101", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_cmpu, "00001100000111111111gggd", 0, {{ &dsp56k_t::S_gggd, 0x00000f }, { &dsp56k_t::D_d, 0x000001 }, }}, -//D - { pall, DSP56_debug, "000000000000001000000000", 0, {{ 0 } }}, - { pall, DSP56_debugcc, "00000000000000110000CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, }}, - { pall, DSP56_dec, "00000000000000000000101d", 0, {{ &dsp56k_t::D_d, 0x000001 }, }}, - { pall, DSP56_div, "000000011000000001JJd000", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, - { p_3_6, DSP56_dmac, "000000010010010s1sdkQQQQ", 0, {{ &dsp56k_t::ss, 0x000140 }, { &dsp56k_t::sign, 0x000010 }, { &dsp56k_t::S_QQQQ, 0x000f }, { &dsp56k_t::D_d, 0x00020 }, }}, - { pall, DSP56_do, "000001100mMMMRRR0S000000", 0, {{ &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR,0x007f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { pall, DSP56_do, "00000110iiiiiiii1000hhhh", 0, {{ &dsp56k_t::S_xih, 0x00ff0f }, { &dsp56k_t::AAE, 0x000000 }, }}, - { pall, DSP56_do, "0000011011DDDDDD00000000", 0, {{ &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x000000 }, }}, - { p_3_6, DSP56_do_f, "000000000000001000000011", 0, {{ &dsp56k_t::AAE, 0x000000 }, }}, - { p563xx, DSP56_dor, "000001100mMMMRRR0S010000", 0, {{ &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR,0x007f00 }, { &dsp56k_t::D_PC_dispL,0x0000 }, }}, - { p563xx, DSP56_dor, "00000110iiiiiiii1001hhhh", 0, {{ &dsp56k_t::S_xih, 0x00ff0f }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, - { p563xx, DSP56_dor, "0000011011DDDDDD00010000", 0, {{ &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, - { p563xx, DSP56_dor_f, "000000000000001000000010", 0, {{ &dsp56k_t::D_PC_dispL,0x00000 }, }}, -//E - { pall, DSP56_enddo, "000000000000000010001100", 0, {{ 0 } }}, - { p_3_6, DSP56_eor, "0000000101iiiiii1000d011", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_eor, "00000001010000001100d011", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_extract, "0000110000011010000sSSSD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_extract, "0000110000011000000s000D", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_extractu,"0000110000011010100sSSSD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_extractu,"0000110000011000100s000D", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, -//I - { pall, DSP56_ill, "000000000000000000000101", 0, {{ 0 } }}, - { pall, DSP56_inc, "00000000000000000000100d", 0, {{ &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_insert, "00001100000110110qqqSSSD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_qqq, 0x000070 }, { &dsp56k_t::D_d, 0x0001 }, }}, - { p_3_6, DSP56_insert, "00001100000110010qqq000D", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_qqq, 0x000070 }, { &dsp56k_t::D_d, 0x0001 }, }}, -//J - { pall, DSP56_jcc, "0000101011MMMRRR1010CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, - { pall, DSP56_jcc, "00001110CCCCaaaaaaaaaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::AA, 0x000fff }, }}, -//exception is possible, it should be moved lower, after move -// { DSP56_jclr, "000010100mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, - { p_0_3, DSP56_jclr, "0000101010pppppp1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jclr, "0000101010pppppp1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p563xx, DSP56_jclr, "0000000110qqqqqq1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jclr, "0000000110qqqqqq1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jclr, "0000101011DDDDDD000bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { p566xx, DSP56_jclr, "0000101011DDDDDD0000bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { pall, DSP56_jmp, "0000101011MMMRRR10000000", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, - { pall, DSP56_jmp, "000011000000aaaaaaaaaaaa", 0, {{ &dsp56k_t::AA, 0x000fff }, }}, - { pall, DSP56_jscc, "0000101111MMMRRR1010CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, - { pall, DSP56_jscc, "00001111CCCCaaaaaaaaaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::AA, 0x000fff }, }}, -//exception is possible, it should be moved lower, after move -// { DSP56_jsclr, "000010110mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, - { p_0_3, DSP56_jsclr, "0000101110pppppp1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jsclr, "0000101110pppppp1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p563xx, DSP56_jsclr, "0000000111qqqqqq1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jsclr, "0000000111qqqqqq1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jsclr, "0000101111DDDDDD000bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { p566xx, DSP56_jsclr, "0000101111DDDDDD0000bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, -//exception is possible, it should be moved lower, after move -// { DSP56_jset, "000010100mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, - { p_0_3, DSP56_jset, "0000101010pppppp1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jset, "0000101010pppppp1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p563xx, DSP56_jset, "0000000110qqqqqq1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jset, "0000000110qqqqqq1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jset, "0000101011DDDDDD001bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { p566xx, DSP56_jset, "0000101011DDDDDD0010bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { pall, DSP56_jsr, "0000101111MMMRRR10000000", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, - { pall, DSP56_jsr, "000011010000aaaaaaaaaaaa", 0, {{ &dsp56k_t::AA, 0x000fff }, }}, -//exception is possible, it should be moved lower, after move -// { DSP56_jsset, "000010110mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, - { p_0_3, DSP56_jsset, "0000101110pppppp1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jsset, "0000101110pppppp1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p563xx, DSP56_jsset, "0000000111qqqqqq1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jsset, "0000000111qqqqqq1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jsset, "0000101111DDDDDD001bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, - { p566xx, DSP56_jsset, "0000101111DDDDDD0010bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, -//L - { p_3_6, DSP56_lra, "0000010011000RRR000ddddd", 0, {{ &dsp56k_t::S_RRR, 0x000700 }, { &dsp56k_t::D_ddddd, 0x00001f }, }}, - { p_3_6, DSP56_lra, "0000010001000000010ddddd", 0, {{ &dsp56k_t::S_PC_dispL,0x000000}, { &dsp56k_t::D_ddddd, 0x00001f }, }}, - { p_3_6, DSP56_lsl, "000011000001111010iiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00003e }, { &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_lsl, "00001100000111100001sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_lsr, "000011000001111011iiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00003e }, { &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_lsr, "00001100000111100011sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_lua, "0000010000aaaRRRaaaadddd", 0, {{ &dsp56k_t::S_RR_dispS,0x003ff0}, { &dsp56k_t::D_dddd, 0x00000f }, }}, - { p_3_6, DSP56_lua, "00000100010MMRRR000ddddd", 0, {{ &dsp56k_t::S_MMRRR, 0x001f00 }, { &dsp56k_t::D_ddddd, 0x00001f }, }}, - { p5600x, DSP56_lua, "00000100010MMRRR0001dddd", 0, {{ &dsp56k_t::S_MMRRR, 0x001f00 }, { &dsp56k_t::D_dddd, 0x00000f }, }}, -//M - { p_0_3, DSP56_mac, "00000001000sssss11QQdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p566xx, DSP56_mac, "000000010000ssss11QQdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_3_6, DSP56_maci, "000000010100000111qqdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_3_6, DSP56_mac_s_u, "00000001001001101sdkQQQQ", 0, {{ &dsp56k_t::s, 0x000040 }, { &dsp56k_t::sign, 0x000010 }, { &dsp56k_t::S_QQQQ, 0x000f }, { &dsp56k_t::D_d, 0x00020 }, }}, - { p_0_3, DSP56_macr, "00000001000sssss11QQdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p566xx, DSP56_macr, "000000010000ssss11QQdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_3_6, DSP56_macri, "000000010100000111qqdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_3_6, DSP56_merge, "00001100000110111000sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, - { p_3_6, DSP56_move, "0000101s01110RRR1Wdddddd", 0, {{ F_SWITCH, 0x000040 }, { &dsp56k_t::mem_type, 0x010000 }, { &dsp56k_t::D_RRR_dispL, 0x000700 }, { &dsp56k_t::D_DDDDDD,0x3f }, }}, - { p_3_6, DSP56_move, "0000001aaaaaaRRR1asWdddd", 0, {{ F_SWITCH, 0x000010 }, { &dsp56k_t::mem_type, 0x000020 }, { &dsp56k_t::D_RRR_dispS, 0x01ff40 }, { &dsp56k_t::D_DDDD, 0x0f }, }}, -//moved lower due to potential opcode overlap - { p_0_3, DSP56_jclr, "000010100mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jclr, "000010100mMMMRRR1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jsclr, "000010110mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jsclr, "000010110mMMMRRR1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jset, "000010100mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jset, "000010100mMMMRRR1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p_0_3, DSP56_jsset, "000010110mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { p566xx, DSP56_jsset, "000010110mMMMRRR1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, - { pall, DSP56_movec, "00000100W1eeeeee101ddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::D_DDDDD, 0x0001f }, }}, - { pall, DSP56_movec, "00000101WmMMMRRR0s1ddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, { &dsp56k_t::D_DDDDD, 0x0001f }, }}, - { pall, DSP56_movec, "00000101iiiiiiii101ddddd", 0, {{ &dsp56k_t::S_xi, 0x00ff00 }, { &dsp56k_t::D_DDDDD, 0x00001f }, }}, - { pall, DSP56_movem, "00000111WmMMMRRR10dddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, { &dsp56k_t::D_DDDDDD, 0x0003f }, }}, - { pall, DSP56_movem, "00000111W0aaaaaa00dddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_aaaaaa, 0x3f00 }, { &dsp56k_t::D_DDDDDD, 0x0003f }, }}, - { pall, DSP56_movep, "0000100SW1MMMRRR01pppppp", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::mem_type, 0x10000 }, { &dsp56k_t::D_pppppp, 0x3f }}}, - { pall, DSP56_movep, "0000100SW1dddddd00pppppp", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::mem_type, 0x10000 }, { &dsp56k_t::D_pppppp, 0x3f }}}, - { pall, DSP56_movep, "0000100sW1MMMRRR1spppppp", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::mem_type, 0x10000 }, { &dsp56k_t::D_pppppp, 0x3f }}}, - { p_3_6, DSP56_movep, "00000111W1MMMRRR0sqqqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::X_type, 0x00000 }, { &dsp56k_t::D_qqqqqq, 0x3f }}}, - { p_3_6, DSP56_movep, "00000111W0MMMRRR1sqqqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::Y_type, 0x00000 }, { &dsp56k_t::D_qqqqqq, 0x3f }}}, - { p_3_6, DSP56_movep, "00000100W1dddddd1q0qqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::X_type, 0x00000 }, { &dsp56k_t::D_qXqqqqq,0x5f }}}, - { p_3_6, DSP56_movep, "00000100W1dddddd0q1qqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::Y_type, 0x00000 }, { &dsp56k_t::D_qXqqqqq,0x5f }}}, - { p_3_6, DSP56_movep, "000000001WMMMRRR0sqqqqqq", 0, {{ F_SWITCH, 0x004000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::mem_type, 0x00040 }, { &dsp56k_t::D_qqqqqq, 0x3f }}}, - { p_0_3, DSP56_mpy, "00000001000sssss11QQdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p566xx, DSP56_mpy, "000000010000ssss11QQdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_3_6, DSP56_mpy_s_u, "00000001001001111sdkQQQQ", 0, {{ &dsp56k_t::s, 0x000040 }, { &dsp56k_t::sign, 0x000010,}, { &dsp56k_t::S_QQQQ, 0x000f }, { &dsp56k_t::D_d, 0x00020 }, }}, - { p_3_6, DSP56_mpyi, "000000010100000111qqdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000,}, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_0_3, DSP56_mpyr, "00000001000sssss11QQdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p566xx, DSP56_mpyr, "000000010000ssss11QQdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, - { p_3_6, DSP56_mpyri, "000000010100000111qqdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000,}, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, -//N - { pall, DSP56_nop, "000000000000000000000000", 0, {{ 0 } }}, - { pall, DSP56_norm, "0000000111011RRR0001d101", 0, {{ &dsp56k_t::S_RRR, 0x000700 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_normf, "00001100000111100010sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, -//O - { p_3_6, DSP56_or, "0000000101iiiiii1000d010", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_or, "00000001010000001100d010", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_ori, "00000000iiiiiiii111110EE", 0, {{ &dsp56k_t::S_xi, 0x00ff00 }, { &dsp56k_t::D_EE, 0x000003 }, }}, -//P - { p563xx, DSP56_pflush, "000000000000000000000011", 0, {{ 0 } }}, - { p563xx, DSP56_pflushun,"000000000000000000000001", 0, {{ 0 } }}, - { p563xx, DSP56_pfree, "000000000000000000000010", 0, {{ 0 } }}, - { p563xx, DSP56_plock, "0000101111MMMRRR10000001", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, - { p563xx, DSP56_plockr, "000000000000000000001111", 0, {{ &dsp56k_t::D_PC_dispL,0x00000 }, }}, - { p563xx, DSP56_punlock, "0000101011MMMRRR10000001", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, - { p563xx, DSP56_punlockr,"000000000000000000001110", 0, {{ &dsp56k_t::D_PC_dispL,0x00000 }, }}, -//R - { pall, DSP56_rep, "000001100mMMMRRR0S100000", 0, {{ &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR,0x007f00 }, }}, - { pall, DSP56_rep, "0000011011dddddd00100000", 0, {{ &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, - { pall, DSP56_rep, "00000110iiiiiiii1010hhhh", 0, {{ &dsp56k_t::D_xih, 0x00ff0f }, }}, - { pall, DSP56_reset, "000000000000000010000100", 0, {{ 0 } }}, - { pall, DSP56_rti, "000000000000000000000100", 0, {{ 0 } }}, - { pall, DSP56_rts, "000000000000000000001100", 0, {{ 0 } }}, -//S - { pall, DSP56_stop, "000000000000000010000111", 0, {{ 0 } }}, - { p_3_6, DSP56_sub, "0000000101iiiiii1000d100", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p_3_6, DSP56_sub, "00000001010000001100d100", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, - { p5600x, DSP56_swi, "000000000000000000000110", 0, {{ 0 } }}, -//T - { pall, DSP56_tcc, "00000010CCCC00000JJJD000", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::SS_JJJd, 0x000078 }, }}, - { pall, DSP56_tcc, "00000011CCCC0ttt0JJJDTTT", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::SS_JJJd, 0x000078 }, { &dsp56k_t::space, 0x0000 }, { &dsp56k_t::S_RRR, 0x00700 }, { &dsp56k_t::D_RRR, 0x07 }}}, - { p_3_6, DSP56_tcc, "00000010CCCC1ttt00000TTT", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::S_RRR, 0x000700 }, { &dsp56k_t::D_RRR, 0x0007 }, }}, - { p_3_6, DSP56_trap, "000000000000000000000110", 0, {{ 0 } }}, - { p_3_6, DSP56_trapcc, "00000000000000000001CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, }}, -//V - { p_3_6, DSP56_vsl, "0000101S11MMMRRR110i0000", 0, {{ &dsp56k_t::S_S, 0x010000 }, { &dsp56k_t::S_i, 0x000010 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, }}, -//W - { pall, DSP56_wait, "000000000000000010000110", 0, {{ 0 } }}, - -// Parallel move - - { pall, DSP56_move, "00000000", 0, {{ 0 } }}, - { p_3_6, DSP56_max, "00011101", 0, {{ &dsp56k_t::m_A_B, 0x000001 }, }}, - { p_3_6, DSP56_maxm, "00010101", 0, {{ &dsp56k_t::m_A_B, 0x000001 }, }}, - { pall, DSP56_addr, "0000d010", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, - { pall, DSP56_tst, "0000d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_subr, "0000d110", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, - { pall, DSP56_rnd, "0001d001", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_addl, "0001d010", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, - { pall, DSP56_clr, "0001d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_subl, "0001d110", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, - { pall, DSP56_not, "0001d111", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_asr, "0010d010", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_lsr, "0010d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_abs, "0010d110", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_ror, "0010d111", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_asl, "0011d010", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_lsl, "0011d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_neg, "0011d110", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_rol, "0011d111", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, - { pall, DSP56_adc, "001Jd001", 0, {{ &dsp56k_t::SD_Jd, 0x000018 }, }}, - { pall, DSP56_sbc, "001Jd101", 0, {{ &dsp56k_t::SD_Jd, 0x000018 }, }}, - { pall, DSP56_or, "01JJd010", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, - { pall, DSP56_eor, "01JJd011", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, - { pall, DSP56_and, "01JJd110", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, - { pall, DSP56_add, "0JJJd000", 0, {{ &dsp56k_t::SD_JJJd, 0x000078 }, }}, - { pall, DSP56_tfr, "0JJJd001", 0, {{ &dsp56k_t::SS_JJJd, 0x000078 }, }}, - { pall, DSP56_sub, "0JJJd100", 0, {{ &dsp56k_t::SD_JJJd, 0x000078 }, }}, - { pall, DSP56_cmp, "0JJJd101", 0, {{ &dsp56k_t::SS_JJJd, 0x000078 }, }}, - { pall, DSP56_cmpm, "0JJJd111", 0, {{ &dsp56k_t::SS_JJJd, 0x000078 }, }}, - { pall, DSP56_mpy, "1QQQdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, - { pall, DSP56_mpyr, "1QQQdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, - { pall, DSP56_mac, "1QQQdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, - { pall, DSP56_macr, "1QQQdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, -}; -static opcode_t table_6x_32[qnumber(table_6x_24)]; - -//---------------------------------------------------------------------- -static par_move pmoves_61[] = -{ - { p_1, "01001010----F---" },//No Parallel Data Move - { p_1, "0100IIII----F---", {{&dsp56k_t::SD_IIII, 0x0fff }}, },//Register to Register Data Move - { p_1, "00110zRR----F---", {{&dsp56k_t::D_zRR, 0x07ff }}, },//Address Register Update -}; - -//---------------------------------------------------------------------- -static opcode_t table_61_24[] = -{ -//Warning! All 32-masks have swapped halves (compared to the documentation) -//Cmd with No Parallel move - { p_1, DSP56_bfchg, "BBB10010iiiiiiii0001010011Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}},//added - { p_1, DSP56_bfchg, "BBB10010iiiiiiii00010100101---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}},//added - { p_1, DSP56_bfchg, "BBB10010iiiiiiii00010100100DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}},//added - { p_1, DSP56_bfclr, "BBB00100iiiiiiii0001010011Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}},//added - { p_1, DSP56_bfclr, "BBB00100iiiiiiii00010100101---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}},//added - { p_1, DSP56_bfclr, "BBB00100iiiiiiii00010100100DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}},//added - { p_1, DSP56_bfset, "BBB11000iiiiiiii0001010011Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}},//added - { p_1, DSP56_bfset, "BBB11000iiiiiiii00010100101---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}},//added - { p_1, DSP56_bfset, "BBB11000iiiiiiii00010100100DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}},//added - { p_1, DSP56_bftsth, "BBB10000iiiiiiii0001010001Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}},//added - { p_1, DSP56_bftsth, "BBB10000iiiiiiii00010100001---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}},//added - { p_1, DSP56_bftsth, "BBB10000iiiiiiii00010100000DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}},//added - { p_1, DSP56_bftstl, "BBB00000iiiiiiii0001010001Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}},//added - { p_1, DSP56_bftstl, "BBB00000iiiiiiii00010100001---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}},//added - { p_1, DSP56_bftstl, "BBB00000iiiiiiii00010100000DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}},//added - { p_1, DSP56_movec, "00111WDDDDD0----00000101BBBBBBBB", cl_0, {{F_SWITCH, 0x04000000}, {&dsp56k_t::X_type, 0 },{&dsp56k_t::D_BBBBBBBB, 0xff}, {&dsp56k_t::D_DDDDD, 0x03e00000 }}},//added - { p_1, DSP56_movem, "0000001W--0--HHH00000101BBBBBBBB", cl_0, {{F_SWITCH, 0x01000000}, {&dsp56k_t::P_type, 0 },{&dsp56k_t::D_BBBBBBBB, 0xff}, {&dsp56k_t::D_HHH, 0x00070000 }}},//added - { p_1, DSP56_adc, "000101010000F01J", cl_0, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_asl4, "000101010011F001", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_asr4, "000101010011F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_asr16, "000101010111F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_asr16, "000101010111F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_bcc, "xxxxxxxxxxxxxxxx00000111--11cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_bcc, "001011cccceeeeee", cl_0, {{&dsp56k_t::CCCC, 0x000003c0}, {&dsp56k_t::D_PC_eeeeee, 0x3f}}},//added - { p_1, DSP56_bcc, "00000111RR10cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_RR, 0xc0}}},//added - { p_1, DSP56_bra, "xxxxxxxxxxxxxxxx00000001001111--", cl_0, {{&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_bra, "00001011aaaaaaaa", cl_0, {{&dsp56k_t::D_PC_aaaaaaaa, 0x000000ff}}},//added - { p_1, DSP56_bra, "00000001001011RR", cl_0, {{&dsp56k_t::D_PC_RR, 0x00000003}}},//added - { p_1, DSP56_brkcc, "000000010001cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}}},//added - { p_1, DSP56_bscc, "xxxxxxxxxxxxxxxx00000111--01cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_bscc, "00000111RR00cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_RR, 0xc0}}},//added - { p_1, DSP56_bsr, "xxxxxxxxxxxxxxxx00000001001110--", cl_0, {{&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_bsr, "00000001001010RR", cl_0, {{&dsp56k_t::D_PC_RR, 0x00000003}}},//added - { p_1, DSP56_chkaau, "0000000000000100", cl_0},//added - { p_1, DSP56_debug, "0000000000000001", cl_0},//added - { p_1, DSP56_debugcc, "000000000101cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}}},//added - { p_1, DSP56_div, "000101010--0F1DD", cl_0, {{&dsp56k_t::S_DD, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_dmac, "0001010110s1FsQQ", cl_0, {{&dsp56k_t::ss, 0x00000024}, {&dsp56k_t::S_QQ2, 0x03}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_do, "xxxxxxxxxxxxxxxx00000000110---RR", cl_0, {{&dsp56k_t::D_RR, 0x00000003}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_do, "xxxxxxxxxxxxxxxx00001110iiiiiiii", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_do, "xxxxxxxxxxxxxxxx00000100000DDDDD", cl_0, {{&dsp56k_t::S_DDDDD, 0x0000001f}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_do_f, "xxxxxxxxxxxxxxxx0000000000000010", cl_0, {{&dsp56k_t::D_PC_dispL, 0xffff0000}}},//added - { p_1, DSP56_enddo, "0000000000001001", cl_0},//added - { p_1, DSP56_ext, "000101010101F010", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_ill, "0000000000001111", cl_0},//added - { p_1, DSP56_imac, "000101011010FQQQ", cl_0, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_impy, "000101011000FQQQ", cl_0, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_jcc, "xxxxxxxxxxxxxxxx00000110--11cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_xi_adr_16, 0xffff0000}}},//added - { p_1, DSP56_jcc, "00000110RR10cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::DB_RR, 0xc0}}},//added - { p_1, DSP56_jmp, "xxxxxxxxxxxxxxxx00000001001101--", cl_0, {{&dsp56k_t::D_xi_adr_16, 0xffff0000}}},//added - { p_1, DSP56_jmp, "00000001001001RR", cl_0, {{&dsp56k_t::DB_RR, 0x00000003}}},//added - { p_1, DSP56_jscc, "xxxxxxxxxxxxxxxx00000110--01cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_xi_adr_16, 0xffff0000}}},//added - { p_1, DSP56_jscc, "00000110RR00cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::DB_RR, 0xc0}}},//added - { p_1, DSP56_jsr, "xxxxxxxxxxxxxxxx00000001001100--", cl_0, {{&dsp56k_t::D_xi_adr_16, 0xffff0000}}},//added - { p_1, DSP56_jsr, "00001010AAAAAAAA", cl_0, {{&dsp56k_t::D_xi, 0x000000ff}}},//added - { p_1, DSP56_jsr, "00000001001000RR", cl_0, {{&dsp56k_t::DB_RR, 0x00000003}}},//added - { p_1, DSP56_lea, "0000000111TTMMRR", cl_0, {{&dsp56k_t::S_MMRR, 0x0000000f}, {&dsp56k_t::D_RR, 0x30}}},//added - { p_1, DSP56_lea, "0000000110NNMMRR", cl_0, {{&dsp56k_t::S_MMRR, 0x0000000f}, {&dsp56k_t::D_NN, 0x30}}},//added - { p_1, DSP56_mac_s_u, "000101011110FsQQ", cl_0, {{&dsp56k_t::s, 0x00000004}, {&dsp56k_t::S_QQ2, 0x03}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_movec, "00111WDDDDD0MMRR", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::X_type, 0}, {&dsp56k_t::D_MMRR,0x0f}, {&dsp56k_t::D_DDDDD, 0x3e0}}},//added - { p_1, DSP56_movec, "00111WDDDDD1q0RR", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::X_type, 0}, {&dsp56k_t::D_qRR, 0x0b}, {&dsp56k_t::D_DDDDD, 0x3e0}}},//added - { p_1, DSP56_movec, "00111WDDDDD1Z11-", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::X_type, 0}, {&dsp56k_t::D_Z, 0x08}, {&dsp56k_t::D_DDDDD, 0x3e0}}},//added - { p_1, DSP56_movec, "xxxxxxxxxxxxxxxx00111WDDDDD1t10-", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::D_t, 0xffff0008}, {0,0}, {&dsp56k_t::D_DDDDD, 0x3e0}}},//added - { p_1, DSP56_movec, "001010dddddDDDDD", cl_0, {{&dsp56k_t::S_DDDDD, 0x000003e0}, {&dsp56k_t::D_DDDDD, 0x1f}}},//added - { p_1, DSP56_movei, "001000DDBBBBBBBB", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_DD, 0x300}}},//added - { p_1, DSP56_movem, "0000001WRR0MMHHH", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::P_type, 0}, {&dsp56k_t::D_RR0MM, 0xd8}, {&dsp56k_t::D_HHH, 0x07}}},//added - { p_1, DSP56_movem, "0000001WRR11mmRR", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::P_type, 0}, {&dsp56k_t::D_RR11m, 0xc8}, {&dsp56k_t::X_type,0}, {&dsp56k_t::D_mRR, 0x07}}},//added - { p_1, DSP56_movep, "0001100WHH1ppppp", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::D_ppppp, 0x1f}, {0, 0}, {&dsp56k_t::D_HH, 0xc0}}},//added - { p_1, DSP56_movep, "0000110WRRmppppp", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::D_ppppp, 0x1f}, {0, 0}, {&dsp56k_t::D_RRm, 0xe0}}},//added - { p_1, DSP56_moves, "0001100WHH0aaaaa", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::D_aaaaa, 0x1f}, {0, 0}, {&dsp56k_t::D_HH, 0xc0}}},//added - { p_1, DSP56_mpy_s_u, "000101011100FsQQ", cl_0, {{&dsp56k_t::s, 0x00000004}, {&dsp56k_t::S_QQ2, 0x03}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_negc, "000101010110F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_nop, "0000000000000000", cl_0},//added - { p_1, DSP56_norm, "000101010010F0RR", cl_0, {{&dsp56k_t::S_RR, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_andi, "00011EE0iiiiiiii", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_EE, 0x0600}}},//added - { p_1, DSP56_ori, "00011EE1iiiiiiii", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_EE, 0x0600}}},//added - { p_1, DSP56_rep, "00000000111---RR", cl_0, {{&dsp56k_t::D_RR, 0x00000003}}},//added - { p_1, DSP56_rep, "00001111iiiiiiii", cl_0, {{&dsp56k_t::D_xi, 0x000000ff}}},//added - { p_1, DSP56_rep, "00000100001DDDDD", cl_0, {{&dsp56k_t::D_DDDDD, 0x0000001f}}},//added - { p_1, DSP56_repcc, "000000010101cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}}},//added - { p_1, DSP56_reset, "0000000000001000", cl_0},//added - { p_1, DSP56_rti, "0000000000000111", cl_0},//added - { p_1, DSP56_rts, "0000000000000110", cl_0},//added - { p_1, DSP56_stop, "0000000000001010", cl_0},//added - { p_1, DSP56_swap, "000101010111F001", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_swi, "0000000000000101", cl_0},//added - { p_1, DSP56_tcc, "000100ccccTTFh0h", cl_0, {{&dsp56k_t::CCCC, 0x000003c0}, {&dsp56k_t::S_Fh0h, 0x0d}, {&dsp56k_t::D_F, 0x08}, {&dsp56k_t::space, 0}, {&dsp56k_t::SD_TT, 0x30}}},//added - { p_1, DSP56_tfr2, "000101010000F00J", cl_0, {{&dsp56k_t::SD_F00J, 0x00000009}}},//added - { p_1, DSP56_tfr3, "001001mWRRDDFHHH", cl_0, {{&dsp56k_t::S_F, 0x00000008}, {&dsp56k_t::D_DD, 0x30}, {&dsp56k_t::space, 0}, {&dsp56k_t::SD_mWRRHHH, 0x03ff}}},//added - { p_1, DSP56_tst2, "000101010001-1DD", cl_0, {{&dsp56k_t::D_DD, 0x00000003}}},//added - { p_1, DSP56_wait, "0000000000001011", cl_0},//added - { p_1, DSP56_zero, "000101010101F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}},//added -//Cmd with Parallel move -//32-bit mask - { p_1, DSP56_pmov, "----HHHW--------00000101BBBBBBBB", cl_1_3 },//X Memory Data Move with short displacement -//16-bit mask - { p_1, DSP56_mac, "00010111RRDDFQQQ", cl_3, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mpy, "00010110RRDDFQQQ", cl_3, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mpy, "011mmKKK1--0F0QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mpyr, "011mmKKK1--1F0QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mac, "011mmKKK1--0F1QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_macr, "011mmKKK1--1F1QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_move, "011mmKKK0rr10000", cl_2 },//added - { p_1, DSP56_tfr, "011mmKKK0rr1F0DD", cl_2, {{&dsp56k_t::S_DD, 0x00000003}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_sub, "011mmKKK0rruF1uu", cl_2, {{&dsp56k_t::S_uFuuu_sub, 0x0000001f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_add, "011mmKKK0rruFuuu", cl_2, {{&dsp56k_t::S_uFuuu_add, 0x0000001f}, {&dsp56k_t::D_F, 0x08}}},//added -//8-bit mask - { p_1, DSP56_clr, "0000F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_add, "0000FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_move, "00010001", cl_1 },//added - { p_1, DSP56_tfr, "0001FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_rnd, "0010F000", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_tst, "0010F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_inc, "0010F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_inc24, "0010F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_inc, "0010F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_or, "0010F1JJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_asr, "0011F000", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_asl, "0011F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_lsr, "0011F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_lsl, "0011F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_eor, "0011F1JJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_subl, "0100F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_sub, "0100FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_clr24, "0101F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_sbc, "0101F01J", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_cmp, "0101FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_neg, "0110F000", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_not, "0110F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_dec, "0110F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_dec24, "0110F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_and, "0110F1JJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_abs, "0111F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_ror, "0111F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_rol, "0111F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}},//added - { p_1, DSP56_cmpm, "0111FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mpy, "1k00FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mpyr, "1k01FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_mac, "1k10FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}},//added - { p_1, DSP56_macr, "1k11FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}},//added -}; -static opcode_t table_61_32[qnumber(table_61_24)]; - -static void make_masks(opcode_t *table, int qty, int n_bits) -{ - for ( int i = 0; i < qty; i++ ) - { - for ( int b = 0; b < strlen(table[i].recog); b++ ) - { - table[i].value <<= 1; - table[i].mask <<= 1; - - if ( table[i].recog[b] == '1' || table[i].recog[b] == '0' ) - table[i].mask++; - - if ( table[i].recog[b] == '1' ) - table[i].value++; - } - - //int n_bits = is561xx() ? 32 : 24; - for ( int j = 0; j < FUNCS_COUNT; j++ ) - { - if ( table[i].funcs[j].func ) - { - for ( int b = 0; b < n_bits; b++ ) - { - if ( table[i].funcs[j].mask & (1 << b) ) - break; - table[i].funcs[j].shift++; - } - } - } - } -} - -//---------------------------------------------------------------------- -static void make_masks2(par_move *pmoves, int qty) -{ - for ( int i = 0; i < qty; i++ ) - { - for ( int b = 0; b < 16; b++ ) - { - pmoves[i].value <<= 1; - pmoves[i].mask <<= 1; - - if ( pmoves[i].recog[b] == '1' || pmoves[i].recog[b] == '0' ) - pmoves[i].mask++; - - if ( pmoves[i].recog[b] == '1' ) - pmoves[i].value++; - } - - for ( int j = 0; j < FUNCS_COUNT; j++ ) - { - if ( pmoves[i].funcs[j].func ) - { - for ( int b = 0; b < 16; b++ ) - { - if ( pmoves[i].funcs[j].mask & (1 << b) ) - break; - pmoves[i].funcs[j].shift++; - } - } - } - } -} - - -//---------------------------------------------------------------------- -// singletons to init tables thread-aware -struct table_61_24_t -{ - static const opcode_t *get() - { - static table_61_24_t instance; //lint !e1788 only by its constructor/destructor - return table_61_24; - } -private: - table_61_24_t() - { - make_masks(table_61_24, qnumber(table_61_24), 24); - } - ~table_61_24_t() = default; - table_61_24_t(const table_61_24_t&) = delete; - table_61_24_t &operator=(const table_61_24_t&) = delete; -}; - -struct table_61_32_t -{ - static const opcode_t *get() - { - static table_61_32_t instance; //lint !e1788 only by its constructor/destructor - return table_61_32; - } -private: - table_61_32_t() - { - memcpy(table_61_32, table_61_24, sizeof(table_61_24)); - make_masks(table_61_32, qnumber(table_61_32), 32); - } - ~table_61_32_t() = default; - table_61_32_t(const table_61_32_t&) = delete; - table_61_32_t &operator=(const table_61_32_t&) = delete; -}; - -struct table_6x_24_t -{ - static const opcode_t *get() - { - static table_6x_24_t instance; //lint !e1788 only by its constructor/destructor - return table_6x_24; - } -private: - table_6x_24_t() - { - make_masks(table_6x_24, qnumber(table_6x_24), 24); - } - ~table_6x_24_t() = default; - table_6x_24_t(const table_6x_24_t&) = delete; - table_6x_24_t &operator=(const table_6x_24_t&) = delete; -}; - -struct table_6x_32_t -{ - static const opcode_t *get() - { - static table_6x_32_t instance; //lint !e1788 only by its constructor/destructor - return table_6x_32; - } -private: - table_6x_32_t() - { - memcpy(table_6x_32, table_6x_24, sizeof(table_6x_24)); - make_masks(table_6x_32, qnumber(table_6x_32), 32); - } - ~table_6x_32_t() = default; - table_6x_32_t(const table_6x_32_t&) = delete; - table_6x_32_t &operator=(const table_6x_32_t&) = delete; -}; - -struct pmoves_61_t -{ - static const par_move *get() - { - static pmoves_61_t instance; //lint !e1788 only by its constructor/destructor - return pmoves_61; - } -private: - pmoves_61_t() - { - make_masks2(pmoves_61, qnumber(pmoves_61)); - } - ~pmoves_61_t() = default; - pmoves_61_t(const pmoves_61_t&) = delete; - pmoves_61_t &operator=(const pmoves_61_t&) = delete; -}; - -struct pmoves_6x_t -{ - static const par_move *get() - { - static pmoves_6x_t instance; //lint !e1788 only by its constructor/destructor - return pmoves_6x; - } -private: - pmoves_6x_t() - { - make_masks2(pmoves_6x, qnumber(pmoves_6x)); - } - ~pmoves_6x_t() = default; - pmoves_6x_t(const pmoves_6x_t&) = delete; - pmoves_6x_t &operator=(const pmoves_6x_t&) = delete; -}; - -//---------------------------------------------------------------------- -// check if the instruction may be disassembled for the current processor -bool dsp56k_t::is_valid_insn(ushort proc) -{ - if ( is566xx() ) - { - if ( (proc & p566xx) == 0 ) - return false; - } - else if ( is563xx() ) - { - if ( (proc & p563xx) == 0 ) - return false; - } - else if ( is561xx() ) - { - if ( (proc & p561xx) == 0 ) - return false; - } - else - { - if ( (proc & p5600x) == 0 ) - return false; - } - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::disassemble_parallel_move(insn_t &insn, int i, int value) -{ - switch_to_additional_args(insn); - - const par_move *pmoves = is561xx() ? pmoves_61_t::get() : pmoves_6x_t::get(); - const par_move &ptr = pmoves[i]; - if ( !is_valid_insn(ptr.proc) ) - return false; - for ( int j = 0; j < FUNCS_COUNT; j++ ) - { - if ( ptr.funcs[j].func != NULL ) - { - int v = (value & ptr.funcs[j].mask) >> ptr.funcs[j].shift; - (this->*ptr.funcs[j].func)(insn, v); - } - } - return true; -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::decode_XY_R_mem(insn_t &insn, int value) -{ - /* order of operands depends on whether we are writing or reading */ - - if ( value & 0x0080 ) - { - mem_type(insn, (value >> 6) & 0x01); - - D_mMMMRRR(insn, (value & 0x3f) | 0x40); - op++; - - if ( value & 0x40 ) - D_ff(insn, (value >> 8) & 0x03, value & 0x40); - else - D_ff(insn, (value >> 10) & 0x03, value & 0x40); - } - else - { - if ( value & 0x40 ) - D_ff(insn, (value >> 8) & 0x03, value & 0x40); - else - D_ff(insn, (value >> 10) & 0x03, value & 0x40); - op++; - - mem_type(insn, (value >> 6) & 0x01); - - D_mMMMRRR(insn, (value & 0x3f) | 0x40); - } - - return true; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::recognize_parallel_move_class1(insn_t &insn, int value) -{ - int index = -1; - - if ( (value & 0xff00) == 0x4a00 ) - { - index = 0; //No Parallel Data Move 01001010----F--- - } - else if ( (value & 0xf000) == 0x4000 ) - { - index = 1; //Register to Register Data Move 0100IIII----F--- - } - else if ( (value & 0xf800) == 0x3000 ) - { - index = 2; //Address Register Update 00110zRR----F--- - } - else if ( (value & 0x8000) == 0x8000 ) //X Memory Data Move 1 1mRRHHHW----F--- - { - switch_to_additional_args(insn); - - if ( value & 0x0100 ) - { - X_type(insn, 0); - D_mRR(insn, (value >>12) & 0x07); - op++; - D_HHH(insn, (value >>9) & 0x07); - } - else - { - D_HHH(insn, (value >>9) & 0x07); - op++; - X_type(insn, 0); - D_mRR(insn, (value >>12) & 0x07); - } - return true; - } - else if ( (value & 0xf000) == 0x5000 ) //X Memory Data Move 2 0101HHHW----F--- - { - switch_to_additional_args(insn); - - if ( value & 0x0100 ) - { - X_type(insn, 0); - op->type = o_phrase; - op->phrase = 0; - op->phtype = ((value & 0x08) ? 9 : 10); - op++; - D_HHH(insn, (value >>9) & 0x07); - } - else - { - D_HHH(insn, (value >>9) & 0x07); - op++; - X_type(insn, 0); - op->type = o_phrase; - op->phrase = 0; - op->phtype = ((value & 0x08) ? 9 : 10); - } - return true; - } - - if ( index != -1 ) - return disassemble_parallel_move(insn, index, value); - return false; -} -//---------------------------------------------------------------------- -bool dsp56k_t::recognize_parallel_move_class1_3(insn_t &insn, int value) -{ - //X Memory Data Move with short displacement - //----HHHW--------00000101BBBBBBBB - - switch_to_additional_args(insn); - if ( (value >> 24) & 0x01 ) - { - X_type(insn, 0); - D_BBBBBBBB(insn, value & 0x0ff); - op++; - D_HHH(insn, (value >> 25 ) & 0x07); - } - else - { - D_HHH(insn, (value >> 25 ) & 0x07); - op++; - X_type(insn, 0); - D_BBBBBBBB(insn, value & 0x0ff); - } - return true; -} -//---------------------------------------------------------------------- -bool dsp56k_t::recognize_parallel_move_class2(insn_t &insn, int value) -{ - //Dual X Memory Data Read - //011mmKKKXrrXXXXX - - static const char regs1[] = { -1, Y0, X1, Y1, X0, Y0, -1, Y1 }; - static const char regs2[] = { X0, X0, X0, X0, X1, X1, Y0, X1 }; - - switch_to_additional_args(insn); - - X_type(insn, 0); - D_mRR(insn, ((value >> 10) & 0x04) + ((value >> 5) & 0x03)); - op++; - char r = regs1[(value >>8) & 0x07]; - if ( r != -1 ) - opreg(insn, r); - else - D_F(insn, ((value & 0x08)>>3) ^ 0x01); - - - switch_to_additional_args(insn); - - X_type(insn, 0); - op->type = o_phrase; - op->phrase = 3; - - if ( (value >> 11) & 0x01 ) - op->phtype = 1; - else - op->phtype = 3; - - op++; - opreg(insn, regs2[(value >>8) & 0x07]); - - return true; - -} -//---------------------------------------------------------------------- -bool dsp56k_t::recognize_parallel_move_class3(insn_t &insn, int value) -{ - //X Memory Data Write and Register Data Move - //0001011kRRDDXXXX - - - switch_to_additional_args(insn); - opreg(insn, ((value >>8) & 0x01) == 1 ? A : B); - op++; - X_type(insn, 0); - D_mRR(insn, 0x04 + ((value >> 6) & 0x03)); - - - switch_to_additional_args(insn); - S_DD(insn, (value >>4) & 0x03); - opreg(insn, ((value >>8) & 0x01) == 1 ? A : B); - - return true; - -} - - -//---------------------------------------------------------------------- -bool dsp56k_t::is_parallel_move(insn_t &insn, int value) -{ - int index = -1; - - if ( value == 0x2000 ) - index = 0; /* NOP */ - else if ( ((value & 0xe000) == 0x2000) && (((value >> 8) & 0x1f) >= 4) ) - index = 1; /* I */ - else if ( ((value >> 10) == 0x08) && (((value >> 5) & 0x1f) >= 4) && ((value & 0x1f) >= 4) ) - index = 2; /* R */ - else if ( (value >> 5) == 0x102 ) - index = 3; /* U */ - else if ( (value >> 4) == 0x202 ) - index = 4; /* IF */ - else if ( (value >> 4) == 0x203 ) - index = 5; /* IF.U */ - else if ( ((value & 0xc000) == 0x4000) && (((value >> 8) & 0x37) >= 4) ) - { - switch_to_additional_args(insn); - - if ( value & 0x0080 ) - { - mem_type(insn, (value >> 11) & 0x01); - D_mMMMRRR(insn, value & 0x7f); - op++; - D_ddddd(insn, ((value >> 8) & 0x07) | ((value >> 9) & 0x18)); - } - else - { - D_ddddd(insn, ((value >> 8) & 0x07) | ((value >> 9) & 0x18)); - op++; - mem_type(insn, (value >> 11) & 0x01); - D_mMMMRRR(insn, value & 0x7f); - } - - return true; - } - else if ( (value & 0xf000) == 0x1000 ) /* class I */ - { - switch_to_additional_args(insn); - - if ( value & 0x40 ) /* Y:R */ - { - D_df(insn, (value >> 10) & 0x03, value & 0x40); - switch_to_additional_args(insn); - decode_XY_R_mem(insn, value); - } - else /* X:R */ - { - decode_XY_R_mem(insn, value); - switch_to_additional_args(insn); - D_df(insn, (value >> 8) & 0x03, value & 0x40); - } - - return true; - } - else if ( (value & 0xfe40) == 0x0800 ) /* class II */ - { - switch_to_additional_args(insn); - - if ( value & 0x0080 ) /* Y:R */ - { - opreg(insn, Y0); - op++; - opreg(insn, (value & 0x0100) ? B : A); - - switch_to_additional_args(insn); - - D_d(insn, (value >> 8) & 0x01); - op++; - op->amode |= amode_y; - D_mMMMRRR(insn, (value & 0x3f) | 0x40); - } - else /* X:R */ - { - D_d(insn, (value >> 8) & 0x01); - op++; - op->amode |= amode_x; - D_mMMMRRR(insn, (value & 0x3f) | 0x40); - - switch_to_additional_args(insn); - - opreg(insn, X0); - op++; - opreg(insn, (value & 0x0100) ? B : A); - } - - return true; - } - else if ( (value & 0xf400) == 0x4000 ) /* L: */ - { - switch_to_additional_args(insn); - - if ( value & 0x0080 ) - { - op->amode |= amode_l; - D_mMMMRRR(insn, value & 0x7f); - op++; - D_LLL(insn, ((value & 0x0800) >> 9) | ((value & 0x0300) >> 8)); - } - else - { - D_LLL(insn, ((value & 0x0800) >> 9) | ((value & 0x0300) >> 8)); - op++; - op->amode |= amode_l; - D_mMMMRRR(insn, value & 0x7f); - } - - return true; - } - else if ( value & 0x8000 ) /* X: Y: */ - { - switch_to_additional_args(insn); - - /* X: */ - if ( value & 0x0080 ) - { - op->amode |= amode_x; - D_MMRRR_XY(insn, value & 0x1f); - op++; - D_ff(insn, (value >> 10) & 0x3, false); - } - else - { - D_ff(insn, (value >> 10) & 0x3, false); - op++; - op->amode |= amode_x; - D_MMRRR_XY(insn, value & 0x1f); - } - - switch_to_additional_args(insn); - - /* Y: */ - if ( value & 0x4000 ) - { - op->amode |= amode_y; - D_MMRRR_XY(insn, ((value >> 5) & 0x03) | (~value & 0x04) | ((value >> 9) & 0x18)); - op++; - D_ff(insn, (value >> 8) & 0x3, true); - } - else - { - D_ff(insn, (value >> 8) & 0x3, true); - op++; - op->amode |= amode_y; - D_MMRRR_XY(insn, ((value >> 5) & 0x03) | (~value & 0x04) | ((value >> 9) & 0x18)); - } - - return true; - } - - if ( index != -1 ) - return disassemble_parallel_move(insn, index, value); - return false; -} - -//---------------------------------------------------------------------- -bool dsp56k_t::use_table( - insn_t &insn, - const opcode_t *table, - uint32 code, - int entry, - int start, - int end) -{ - const opcode_t &ptr = table[entry]; - for ( int j = start; j <= end; j++ ) - { - if ( ptr.funcs[j].func == NULL ) - break; - int value = (code & ptr.funcs[j].mask) >> ptr.funcs[j].shift; - if ( !(this->*ptr.funcs[j].func)(insn, value) ) - return false; - } - return true; -} - -//---------------------------------------------------------------------- -void dsp56k_t::reset_ops(insn_t &insn) -{ - op = &insn.Op1; - for ( int i=0; i < UA_MAXOP; i++ ) - insn.ops[i].type = o_void; - memset(&aa, 0, sizeof(aa)); -} - -//---------------------------------------------------------------------- -int dsp56k_t::ana_61(insn_t &insn) -{ - int prev_insn_p_class = cl_0; - int insn_p_class; - uint code = ua_32bits(insn); - op = &insn.Op1; - memset(&aa, 0, sizeof(aa)); - aa.ea = insn.ea; - - const opcode_t *table_61_xx = is561xx() ? table_61_32_t::get() : table_61_24_t::get(); - for ( int i = 0; i < qnumber(table_61_24); i++ ) - { - const auto &te = table_61_xx[i]; - if ( (code & te.mask) == te.value ) - { - insn.itype = te.itype; - insn.size = 1; - insn_p_class = te.pmov_cl; - if ( strlen(te.recog) > 16 ) - insn.size = 2; - - // X Memory Data Move with short displacement - if ( prev_insn_p_class == cl_1_3 ) - { - insn.size = 2; - insn_p_class = cl_1_3; - } - else if ( insn_p_class == cl_1_3 ) - { - prev_insn_p_class = insn_p_class; - code >>= 16; - continue; - } - - - if ( te.funcs[0].func == F_SWITCH ) - { - int first, second; - if ( (code & te.funcs[0].mask) >> te.funcs[0].shift ) - { - first = 1; - second = 3; - } - else - { - first = 3; - second = 1; - } - if ( !use_table(insn, table_61_xx, code, i, first, first + 1) ) - { - reset_ops(insn); - continue; - } - op++; - if ( !use_table(insn, table_61_xx, code, i, second, second + 1) ) - { - reset_ops(insn); - continue; - } - } - else - { - if ( !use_table(insn, table_61_xx, code, i, 0, FUNCS_COUNT - 1) ) - { - reset_ops(insn); - continue; - } - } - - // analyze additional operands of parallel moves - switch ( insn_p_class ) - { - case cl_0://No Parallel move - break; - case cl_1://X Memory Data Move (common) - code = ushort(code & 0xffff); - recognize_parallel_move_class1(insn, code); - break; - case cl_1_3://X Memory Data Move with short displacement - code = ua_32bits(insn); - recognize_parallel_move_class1_3(insn, code); - break; - case cl_2://Dual X Memory Data Read - code = ushort(code & 0xffff); - recognize_parallel_move_class2(insn, code); - break; - case cl_3://X Memory Data Write and Register Data Move - code = ushort(code & 0xffff); - recognize_parallel_move_class3(insn, code); - break; - } - - if ( insn.Op1.type == o_void && aa.nargs != 0 ) - { - insn.Op1 = aa.args[0][0]; - insn.Op2 = aa.args[0][1]; - aa.args[0][0].type = o_void; - aa.args[0][1].type = o_void; - } - return insn.size; - } - } - return 0; -} - -//---------------------------------------------------------------------- -int dsp56k_t::ana_6x(insn_t &insn) -{ - uint32 code = ua_next_24bits(insn); - op = &insn.Op1; - memset(&aa, 0, sizeof(aa)); - aa.ea = insn.ea; - - const opcode_t *table_6x_xx = is561xx() ? table_6x_32_t::get() : table_6x_24_t::get(); - for ( int i = 0; i < qnumber(table_6x_24); i++ ) - { - const auto &te = table_6x_xx[i]; - if ( (code & te.mask) == te.value - && is_valid_insn(te.proc) ) - { - insn.itype = te.itype; - if ( te.funcs[0].func == F_SWITCH ) - { - int first, second; - if ( (code & te.funcs[0].mask) >> te.funcs[0].shift ) - { - first = 1; - second = 3; - } - else - { - first = 3; - second = 1; - } - if ( !use_table(insn, table_6x_xx, code, i, first, first + 1) ) - { - reset_ops(insn); - continue; - } - op++; - if ( !use_table(insn, table_6x_xx, code, i, second, second + 1) ) - { - reset_ops(insn); - continue; - } - } - else - { - if ( !use_table(insn, table_6x_xx, code, i, 0, FUNCS_COUNT - 1) ) - { - reset_ops(insn); - continue; - } - } - - if ( te.recog[8] == '\0' ) - { - code = ushort(code>>8); - is_parallel_move(insn, code); - } - if ( insn.Op1.type == o_void && aa.nargs != 0 ) - { - insn.Op1 = aa.args[0][0]; - insn.Op2 = aa.args[0][1]; - aa.args[0][0].type = o_void; - aa.args[0][1].type = o_void; - } - return insn.size; - } - } - return 0; -} - -//-------------------------------------------------------------------------- -int dsp56k_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - return is561xx() ? ana_61(insn) : ana_6x(insn); -} - -//-------------------------------------------------------------------------- -void interr(const insn_t *insn, const char *module) -{ - const char *name = NULL; - if ( insn->itype < DSP56_last ) - name = Instructions[insn->itype].name; - warning("%a(%s): internal error in %s", insn->ea, name, module); -} diff --git a/idasdk75/module/dsp56k/dsp56k.hpp b/idasdk75/module/dsp56k/dsp56k.hpp deleted file mode 100644 index 9a779d5..0000000 --- a/idasdk75/module/dsp56k/dsp56k.hpp +++ /dev/null @@ -1,346 +0,0 @@ - -#ifndef _DSP56K_HPP -#define _DSP56K_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -// DSP56K instruction may have many operands. We keep them separately -// in the following structure. - -struct addargs_t -{ - ea_t ea; - int nargs; - op_t args[4][2]; - - addargs_t() : ea(BADADDR), nargs(0) { memset(args, 0, sizeof(args)); } -}; - -//------------------------------------------------------------------ -struct dsp56k_iohandler_t : public iohandler_t -{ - struct dsp56k_t ± - dsp56k_iohandler_t(dsp56k_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual const char *iocallback(const ioports_t &iop, const char *line) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct dsp56k_t); - -struct dsp56k_t : public procmod_t -{ - netnode helper; - dsp56k_iohandler_t ioh = dsp56k_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - ea_t xmem = BADADDR; - ea_t ymem = BADADDR; - op_t *op = nullptr; // current operand - addargs_t aa; - int xmemsize = 0x10000; - int ymemsize = 0x10000; - int procnum = -1; // 0 - dsp56k, 1 - dsp561xx, 2 - dsp563xx, 3 - dsp566xx - bool flow = false; - - inline bool is561xx(void) const { return procnum == 1; } - inline bool is563xx(void) const { return procnum == 2; } - inline bool is566xx(void) const { return procnum == 3; } - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - const ioport_t *find_port(ea_t address); - void create_xmem_ymem(void); - void select_device(const char *dname, int resp_info); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - ea_t calc_mem(const insn_t &insn, const op_t &x) const; - ea_t AdditionalSegment(asize_t size, int offset, const char *name) const; - void handle_operand( - const insn_t &insn, - const op_t &x, - flags_t F, - bool is_forced, - bool isload); - int emu(const insn_t &insn); - void header(outctx_t &ctx); - void set_cpu(int procno); - bool D_EE(insn_t &insn, int value); - bool D_DDDDD(insn_t &insn, int value); - bool D_ff(const insn_t &insn, int value, int reg_bank); - bool D_df(insn_t &insn, int value, int reg_bank); - bool S_xi(insn_t &, int value); - bool D_ximm(insn_t &insn, int /*value*/); - bool S_ximm(insn_t &insn, int value); - bool S_sssss(insn_t &, int value); - bool S_ssss(insn_t &, int value); - bool D_xih(insn_t &, int value); - bool S_xih(insn_t &insn, int value); - bool SD_d(insn_t &insn, int value); - bool SS_JJJd(insn_t &insn, int value); - bool SD_JJJd(insn_t &insn, int value); - bool SD_Jd(insn_t &insn, int value); - bool D_d(insn_t &insn, int value); - bool S_S(insn_t &insn, int value); - bool SD_JJd(insn_t &insn, int value); - bool D_dddd(insn_t &insn, int value); - bool D_ddddd(insn_t &insn, int value); - bool S_ddddd(insn_t &insn, int value); - bool D_LLL(insn_t &insn, int value); - bool D_sss(insn_t &insn, int value); - bool S_sss(insn_t &insn, int value); - bool D_qqq(insn_t &insn, int value); - bool S_qqq(insn_t &insn, int value); - bool S_qq(insn_t &insn, int value); - bool S_QQ(insn_t &insn, int value); - bool S_gggd(insn_t &insn, int value); - bool D_MMRRR(insn_t &, int value); - bool S_MMRRR(insn_t &insn, int value); - bool D_MMRRR_XY(insn_t &, int value); - bool D_pppppp(insn_t &, int value); - bool S_pppppp(insn_t &insn, int value); - bool D_qqqqqq(insn_t &, int value); - bool S_qqqqqq(insn_t &insn, int value); - bool D_qXqqqqq(insn_t &insn, int value); - bool D_DDDDDD(insn_t &insn, int value); - bool S_DDDDDD(insn_t &insn, int value); - bool D_DDDD(insn_t &insn, int value); - bool D_RRR(insn_t &insn, int value); - bool S_RRR(insn_t &insn, int value); - void make_o_mem(insn_t &insn); - bool D_mMMMRRR(insn_t &insn, int value); - bool S_mMMMRRR(insn_t &insn, int value); - bool D_aaaaaa(insn_t &insn, int value); - bool S_aaaaaa(insn_t &insn, int value); - bool D_MMMRRR(insn_t &insn, int value); - bool S_MMMRRR(insn_t &insn, int value); - bool P_type(insn_t &, int); - bool AAE(insn_t &insn, int); - bool D_PC_dispL(insn_t &insn, int value); - bool S_PC_dispL(insn_t &insn, int value); - bool D_PC_dispS(insn_t &insn, int value); - bool D_PC_RRR(insn_t &, int value); - bool D_RRR_dispL(insn_t &insn, int value); - bool D_RRR_dispS(insn_t &, int value); - bool S_RR_dispS(insn_t &, int value); - bool AA(insn_t &, int value); - bool D_F(insn_t &insn, int value); - bool S_F(insn_t &insn, int value); - bool CCCC(insn_t &insn, int value); - bool s(insn_t &insn, int value); - bool ss(insn_t &insn, int value); - bool SD_IIII(insn_t &insn, int value); - bool D_zRR(insn_t &, int value); - bool D_mRR(insn_t &, int value); - bool D_RRm(insn_t &insn, int value); - bool D_RR11m(insn_t &insn, int value); - bool D_MMRR(insn_t &, int value); - bool S_MMRR(insn_t &insn, int value); - bool D_RR0MM(insn_t &insn, int value); - bool D_qRR(insn_t &, int value); - bool D_HHH(insn_t &, int value); - bool D_HH(insn_t &, int value); - bool SD_mWRRHHH(insn_t &insn, int value); - bool S_FJJJ(insn_t &insn, int value); - bool S_QQQ(insn_t &, int value); - bool S_QQ2(insn_t &, int value); - bool S_QQQQ(insn_t &, int value); - bool S_Fh0h(insn_t &insn, int value); - bool S_uFuuu_add(insn_t &insn, int value); - bool S_uFuuu_sub(insn_t &insn, int value); - bool D_RR(insn_t &insn, int value); - bool D_NN(insn_t &insn, int value); - bool DB_RR(insn_t &, int value); - bool D_PC_RR(insn_t &, int value); - bool DX_RR(insn_t &insn, int value); - bool S_RR(insn_t &insn, int value); - bool m_A_B(insn_t &, int /*value*/); - bool IF(insn_t &, int /*value*/); - bool IFU(insn_t &, int /*value*/); - bool S_i(insn_t &insn, int value); - bool SD_TT(insn_t &insn, int value); - bool S_BBBiiiiiiii(insn_t &, int value); - bool D_Pppppp(insn_t &insn, int value); - bool D_ppppp(insn_t &insn, int value); - bool D_aaaaa(insn_t &insn, int value); - bool S_DDDDD(insn_t &insn, int value); - bool D_xi(insn_t &, int value); - bool D_xi16(insn_t &, int value); - bool D_xi_adr_16(insn_t &insn, int value); - bool D_DD(insn_t &insn, int value); - bool S_DD(insn_t &insn, int value); - bool D_Z(insn_t &, int value); - bool D_t(insn_t &insn, int value); - bool SD_F00J(insn_t &insn, int value); - bool D_PC_eeeeee(insn_t &insn, int value); - bool D_PC_aaaaaaaa(insn_t &insn, int value); - bool D_BBBBBBBB(insn_t &, int value); - bool is_valid_insn(ushort proc); - bool disassemble_parallel_move(insn_t &insn, int i, int value); - bool decode_XY_R_mem(insn_t &insn, int value); - bool recognize_parallel_move_class1(insn_t &insn, int value); - bool recognize_parallel_move_class1_3(insn_t &insn, int value); - bool recognize_parallel_move_class2(insn_t &insn, int value); - bool recognize_parallel_move_class3(insn_t &insn, int value); - bool is_parallel_move(insn_t &insn, int value); - bool use_table( - insn_t &insn, - const struct opcode_t *table, - uint32 code, - int entry, - int start, - int end); - int ana_61(insn_t &insn); - int ana_6x(insn_t &insn); - int ana(insn_t *_insn); - bool X_type(insn_t &, int); - bool Y_type(insn_t &, int); - bool mem_type(insn_t &, int value); - bool space(insn_t &insn, int); - bool sign(insn_t &, int value); - int is_sane_insn(const insn_t &insn, int /*nocrefs*/) const; - void fill_additional_args(const insn_t &insn) const; - void switch_to_additional_args(insn_t &); - inline void opreg(insn_t &, int reg); - void reset_ops(insn_t &insn); - void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); - - void segstart(outctx_t &ctx, segment_t *seg) const; - void segend(outctx_t &ctx, segment_t *seg) const; - void footer(outctx_t &ctx) const; -}; - -//------------------------------------------------------------------ - -#define aux_cc 0x000F // condition code -#define aux_su 0x0003 // sign/unsing code - -#define phtype specflag1 // o_phrase: phrase type -// 0 (Rn)-n -// 1 (Rn)+Nn -// 2 (Rn)- -// 3 (Rn)+ -// 4 (Rn) -// 5 (Rn+Nn) -// 7 -(Rn) -// 8 $+Rn -// 9 (a1) -// 10 (b1) - -#define amode specflag2 // addressing mode -#define amode_ioshort 0x01 // << -#define amode_short 0x02 // < -#define amode_long 0x04 // > -#define amode_neg 0x08 // - -#define amode_x 0x10 // X: -#define amode_y 0x20 // Y: -#define amode_p 0x40 // P: -#define amode_l 0x80 // L: - -#define imode specflag3 // IF mode -#define imode_if 0x01 // IFcc -#define imode_ifu 0x02 // IFUcc - -#define o_iftype o_idpspec0 //IF type - -#define o_vsltype o_idpspec1 //VSL 2-nd operand type - -//------------------------------------------------------------------ -#define UAS_GNU 0x0001 // GNU assembler -//------------------------------------------------------------------ -enum RegNo ENUM_SIZE(uint16) -{ - // data arithmetic logic unit - X, X0, X1, - Y, Y0, Y1, - // accumulator registers - A, A0, A1, A2, - B, B0, B1, B2, - AB, // a1:b1 - BA, // b1:a1 - A10, // a1:a0 - B10, // b1:b0 - // address generation unit (AGU) - R0, R1, R2, R3, R4, R5, R6, R7, // pointers - N0, N1, N2, N3, N4, N5, N6, N7, // offsets - M0, M1, M2, M3, M4, M5, M6, M7, // modifiers - // Program Control Unit - PC, // Program Counter (16 Bits) - MR, // Mode Register (8 Bits) - CCR, // Condition Code Register (8 Bits) - SR, // Status Register (MR:CCR, 16 Bits) - OMR, // Operating Mode Register (8 Bits) - LA, // Hardware Loop Address Register (16 Bits) - LC, // Hardware Loop Counter (16 Bits) - SP, // System Stack Pointer (6 Bits) - SS, // System Stack RAM (15X32 Bits) - SSH, // Upper 16 Bits of the Contents of the Current Top of Stack - SSL, // Lower 16 Bits of the Contents of the Current Top of Stack - SZ, // Stack Size register - SC, // Stack Counter register - EP, // Extension Pointer register - VBA, // Vector Base Address Register - - vCS, vDS, // virtual registers for code and data segments - -}; - - -//------------------------------------------------------------------ -// condition codes -enum cc_t -{ - cc_CC, // carry clear (higher or same) C=0 - cc_GE, // greater than or equal N xor V=0 - cc_NE, // not equal Z=0 - cc_PL, // plus N=0 - cc_NN, // not normalized Z+(^U&^E)=0 - cc_EC, // extension clear E=0 - cc_LC, // limit clear L=0 - cc_GT, // greater than Z+(N xor V)=0 - cc_CS, // carry set (lower) C=1 - cc_LT, // less than N xor V=1 - cc_EQ, // equal Z=1 - cc_MI, // minus N=1 - cc_NR, // normalized Z+(^U&^E)=1 - cc_ES, // extension set E=1 - cc_LS, // limit set L=1 - cc_LE, // less than or equal Z+(N xor V)=1 -}; - -//------------------------------------------------------------------ - -enum PMoveClass -{ - cl_0 = 0, //No Parallel move - cl_1, //X Memory Data Move (common) - cl_1_3, //X Memory Data Move with short displacement - cl_2, //Dual X Memory Data Read - cl_3, //X Memory Data Write and Register Data Move -}; - -//------------------------------------------------------------------ -// signed/unsigned codes -enum su_t -{ - s_SS, // signed * signed - s_SU, // signed * unsigned - s_UU, // unsigned * unsigned -}; - -// Make sure that the 'aa' structure is up to date. -void fill_additional_args(const insn_t &insn); - -//------------------------------------------------------------------ -void interr(const insn_t *insn, const char *module); - -int idaapi ana(insn_t *insn); -int idaapi emu(const insn_t &insn); - -int idaapi is_align_insn(ea_t ea); -int idaapi is_sp_based(const insn_t &insn, const op_t &x); - -#endif // _DSP56K_HPP diff --git a/idasdk75/module/dsp56k/makefile b/idasdk75/module/dsp56k/makefile deleted file mode 100644 index f427aa6..0000000 --- a/idasdk75/module/dsp56k/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=dsp56k -CONFIGS=dsp56k.cfg dsp563xx.cfg dsp566xx.cfg dsp561xx.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp dsp56k.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp dsp56k.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - dsp56k.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - dsp56k.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - dsp56k.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/dsp56k/reg.cpp b/idasdk75/module/dsp56k/reg.cpp deleted file mode 100644 index 16c4180..0000000 --- a/idasdk75/module/dsp56k/reg.cpp +++ /dev/null @@ -1,566 +0,0 @@ - -#include "dsp56k.hpp" -#include <diskio.hpp> - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - // data arithmetic logic unit - "x", "x0", "x1", - "y", "y0", "y1", - // accumulator registers - "a", "a0", "a1", "a2", - "b", "b0", "b1", "b2", - "ab", // a1:b1 - "ba", // b1:a1 - "a10", // a1:a0 - "b10", // b1:b0 - // address generation unit (AGU) - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // pointers - "n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", // offsets - "m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", // modifiers - // Program Control Unit - "pc", // Program Counter (16 Bits) - "mr", // Mode Register (8 Bits) - "ccr", // Condition Code Register (8 Bits) - "sr", // Status Register (MR:CCR, 16 Bits) - "omr", // Operating Mode Register (8 Bits) - "la", // Hardware Loop Address Register (16 Bits) - "lc", // Hardware Loop Counter (16 Bits) - "sp", // System Stack Pointer (6 Bits) - "ss", // System Stack RAM (15X32 Bits) - "ssh", // Upper 16 Bits of the Contents of the Current Top of Stack - "ssl", // Lower 16 Bits of the Contents of the Current Top of Stack - "sz", // Stack Size register - "sc", // Stack Counter register - "ep", // Extension Pointer register - "vba", // Vector Base Address Register - - "cs","ds", // virtual registers for code and data segments -}; - -//-------------------------------------------------------------------------- -//6x -static const uchar retcode_0[] = { 0x0C, 0x00, 0x00 }; -static const uchar retcode_1[] = { 0x04, 0x00, 0x00 }; -//61 -static const uchar retcode_2[] = { 0x06, 0x00 }; -static const uchar retcode_3[] = { 0x07, 0x00 }; - -static const bytes_t retcodes6x[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -static const bytes_t retcodes61[] = -{ - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Motorola DSP56000 Assembler -//----------------------------------------------------------------------- -static const asm_t motasm = -{ -// AS_ASCIIC - ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASB_BINF2 // %01010 - |ASO_OCTF1 // 0123 - |AS_COLON - |AS_N2CHR - |AS_NCMAS - |AS_ONEDUP, - 0, - "Motorola DSP56K Assembler", - 0, - NULL, // header lines - "org", // org - "end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - "dc", // ascii string directive - "dcb", // byte directive - "dc", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "*", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - "global", // "public" name keyword - NULL, // "weak" name keyword - "xref", // "extrn" name keyword - // .extern directive requires an explicit object size - NULL, // "comm" (communal variable) - NULL, // get_type_name - NULL, // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_BYTE1CHAR,// One symbol per processor byte -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gas = -{ - AS_ASCIIC - |ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASB_BINF3 // 0b01010 - |ASO_OCTF1 // 0123 - |AS_COLON - |AS_N2CHR - |AS_NCMAS - |AS_ONEDUP, - UAS_GNU, - "GNU-like hypothetical assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".long", // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - ".", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "mod", // mod - "and", // and - "or", // or - "xor", // xor - "not", // not - "shl", // shl - "shr", // shr - NULL, // sizeof - AS2_BYTE1CHAR,// One symbol per processor byte - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt -}; - -static const asm_t *const asms[] = { &motasm, &gas, NULL }; - -//---------------------------------------------------------------------- -ea_t dsp56k_t::AdditionalSegment(asize_t size, int offset, const char *name) const -{ - segment_t s; - int step = is561xx() ? 0xF : 0x1000000-1; - s.start_ea = free_chunk(0x1000000, size, step); - s.end_ea = s.start_ea + size; - s.sel = allocate_selector((s.start_ea-offset) >> 4); - s.type = SEG_DATA; - s.bitness = ph.dnbits > 16; - add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE); - return s.start_ea - offset; -} - -inline ea_t get_start(const segment_t *s) -{ - return s ? s->start_ea : BADADDR; -} - -//-------------------------------------------------------------------------- -const char *dsp56k_iohandler_t::iocallback(const ioports_t &iop, const char *line) -{ - int size; - if ( qsscanf(line, "XMEMSIZE = %i", &size) == 1 ) - { - pm.xmemsize = size; -RETOK: - pm.ioh.deviceparams.sprnt("XMEM=0x%X YMEM=0x%X", pm.xmemsize, pm.ymemsize); - return NULL; - } - if ( !pm.is561xx() && qsscanf(line, "YMEMSIZE = %i", &size) == 1 ) - { - pm.ymemsize = size; - goto RETOK; - } - return pm.ioh.standard_callback(iop, line); -} - -const ioport_t *dsp56k_t::find_port(ea_t address) -{ - return find_ioport(ioh.ports, address); -} - -//-------------------------------------------------------------------------- -void dsp56k_t::create_xmem_ymem(void) -{ - if ( xmem == BADADDR ) - { - xmem = AdditionalSegment(xmemsize, 0, "XMEM"); - - if ( !is561xx() ) - ymem = AdditionalSegment(ymemsize, 0, "YMEM"); - } -} - -//-------------------------------------------------------------------------- -void dsp56k_t::select_device(const char *dname, int resp_info) -{ - ioh.set_device_name(dname, resp_info); - - create_xmem_ymem(); - - for ( int i=0; i < ioh.ports.size(); i++ ) - { - const ioport_t &p = ioh.ports[i]; - ea_t ea = xmem + p.address; - const char *name = p.name.c_str(); - ea_t nameea = get_name_ea(BADADDR, name); - if ( nameea != ea ) - { - set_name(nameea, ""); - if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) - set_cmt(ea, name, 0); - } - } -} - -//-------------------------------------------------------------------------- -const char *dsp56k_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( choose_ioport_device(&ioh.device, cfgfile) ) - select_device(ioh.device.c_str(), IORESP_INT); - return IDPOPT_OK; -} - -//----------------------------------------------------------------------- -// We always return "yes" because of the messy problem that -// there are additional operands with a wrong operand number (always 1) -static bool idaapi can_have_type(const op_t &) -{ - return true; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.supset(0, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -void dsp56k_t::set_cpu(int procno) -{ - procnum = procno; - ph.cnbits = (is561xx() ) ? 16 : 24; - ph.dnbits = (is561xx() || is566xx()) ? 16 : 24; - ph.retcodes = (is561xx() ) ? retcodes61 : retcodes6x; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new dsp56k_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi dsp56k_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ dsp56k"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: // new file loaded - { - // data memory could already be present, check it - xmem = get_start(get_segm_by_name("XMEM")); - if ( !is561xx() ) - ymem = get_start(get_segm_by_name("YMEM")); - - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - select_device(ioh.device.c_str(), IORESP_AREA|IORESP_INT); - else - create_xmem_ymem(); - } - break; - - case processor_t::ev_ending_undo: - // restore ptype - set_cpu(ph.get_proc_index()); - //fall through - case processor_t::ev_oldfile: // old file loaded - xmem = get_start(get_segm_by_name("XMEM")); - if ( !is561xx() ) - ymem = get_start(get_segm_by_name("YMEM")); - ioh.restore_device(); - break; - - case processor_t::ev_newprc: // new processor type - { - int n = va_arg(va, int); - // bool keep_cfg = va_argi(va, bool); - if ( procnum == -1 ) - { - set_cpu(n); - } - else if ( procnum != n ) // can't change the processor type - { // after the initial set up - warning("Sorry, processor type cannot be changed after loading"); - code = -1; - break; - } - } - break; - - case processor_t::ev_is_sane_insn: - { - const insn_t &insn = *va_arg(va, const insn_t *); - int nocrefs = va_arg(va, int); - return is_sane_insn(insn, nocrefs) == 1 ? 1 : -1; - } - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *_op = va_arg(va, const op_t *); - return out_opnd(*ctx, *_op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *_op = va_arg(va, const op_t *); - return can_have_type(*_op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *_op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *_op); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "Motorola DSP 5600x:" - -static const char *const shnames[] = -{ - "dsp56k", - "dsp561xx", - "dsp563xx", - "dsp566xx", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Motorola DSP 5600x", - "Motorola DSP 561xx", - "Motorola DSP 563xx", - "Motorola DSP 566xx", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_DSP56K, // id - // flag - PRN_HEX - | PR_ALIGN - | PR_BINMEM, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 24, // 24 bits in a byte for code segments - 24, // 24 bits in a byte for other segments - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - vCS, // first - vDS, // last - 0, // size of a segment register - vCS, vDS, - - NULL, // No known code start sequences - retcodes6x, - - DSP56_null, - DSP56_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - DSP56_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/f2mc/ana.cpp b/idasdk75/module/f2mc/ana.cpp deleted file mode 100644 index f4cdfc1..0000000 --- a/idasdk75/module/f2mc/ana.cpp +++ /dev/null @@ -1,1217 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Fujitsu's F2MC - * - */ - -#include "f2mc.hpp" -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -// function to generate an operand -typedef void (*func_op_t)(const struct map_t *, int offset, op_t &op, insn_t &insn); - -struct map_t -{ - const map_t *next; // map for next opcode byte - int code; // first opcode of instruction range - ushort itype; // itype of instruction - func_op_t op1; //lint !e958 padding is required to align members - // function to set Op1 - func_op_t op2; // function to set Op2 - func_op_t op3; // function to set Op3 - char priority1; // first operand to inc (1..3) - char size1; // maximum size of the first operand - char priority2; - char size2; - char priority3; - char size3; -}; -// operands increments priority (OP_first_second_...) -#define OP_NULL 0, 0, 0, 0, 0, 0 -#define OP_1_2(SIZE1) 1, SIZE1, 2, 0, 0, 0 -#define OP_2_1(SIZE2) 2, SIZE2, 1, 0, 0, 0 -#define OP_3_1(SIZE3) 3, SIZE3, 1, 0, 0, 0 -#define OP_3_2(SIZE3) 3, SIZE3, 2, 0, 0, 0 - - -//-------------------------------------------------------------------------- -// analyze code by processing map - -static const map_t *process_map(insn_t &insn, int code, const map_t *map, int itype_null) -{ - // search for the good opcode range - const map_t *p = map; - while ( ((p+1)->code != 0 || (p+1)->itype != 0) - && code >= (p+1)->code ) - { - p++; // loop until p->code <= code < (p+1)->code - } - if ( insn.itype == itype_null ) - insn.itype = p->itype; // define itype if not already defined - - // compute operand offsets - int offset = code - p->code, offsets[3]; - for ( int i=0; i < 3; i++ ) - offsets[i] = offset; - if ( p->priority1 ) - { - if ( p->size1 ) - offsets[p->priority1 - 1] = offset % p->size1; - if ( p->priority2 ) - { - offset /= p->size1; - offsets[p->priority2 - 1] = offset; - if ( p->size2 ) - offsets[p->priority2 - 1] = offset % p->size2; - if ( p->priority3 ) - { - offset /= p->size2; - offsets[p->priority3 - 1] = offset; - if ( p->size3 ) - offsets[p->priority3 - 1] = offset % p->size3; - } - } - } - - // process operands - if ( p->op1 != NULL ) - p->op1(p, offsets[0], insn.Op1, insn); - if ( p->op2 != NULL ) - p->op2(p, offsets[1], insn.Op2, insn); - if ( p->op3 != NULL ) - p->op3(p, offsets[2], insn.Op3, insn); - return p->next; -} - -//-------------------------------------------------------------------------- -// analyze code by processing all necessary maps -static void process_maps(insn_t &insn, const map_t *map,uint16 itype_null) -{ - insn.itype = itype_null; - insn.size = 0; - while ( map ) // while we must analyze a new map - { - int code = insn.get_next_byte(); - map = process_map(insn, code, map, itype_null); // analyze this byte - } -} - -//-------------------------------------------------------------------------- -// class to store an instructions cache -#define CMDS_SIZE 3 // maximum cache size (maximum number of instructions) -class cmds_t -{ -private: - insn_t insns[CMDS_SIZE]; - int size; - int i; -public: - void reset(void) { i = 0; } - //lint -sem(cmds_t::reload,initializer) - void reload(const insn_t &insn) { insns[0] = insn; size = 1; reset(); } - cmds_t(const insn_t &insn) { reload(insn); } //lint !e1566 'cmds_t::i' may have been initialized in a separate method - const insn_t *get_next(void); - const insn_t *get(int j) const; -}; - -// get the next instruction -const insn_t *cmds_t::get_next(void) -{ - if ( i == size ) - { - // if ( size >= CACHE_SIZE ) return NULL; - // load a new instruction into the cache - if ( size <= 0 ) - return NULL; - ea_t ea = insns[size-1].ea + insns[size-1].size; - if ( decode_insn(&insns[size], ea) < 1 ) - return NULL; - size++; - } - return &insns[i++]; -} - -//-------------------------------------------------------------------------- -// get an instruction already in the cache -const insn_t *cmds_t::get(int j) const -{ - // if ( j >= size ) return NULL; - return &insns[j]; -} - -// function to check the validity of an operand -typedef bool (*func_is_op_t)(const insn_t *insn, const op_t &op); - -struct macro_insn_t -{ - func_is_op_t op1; // function to check Op1 - func_is_op_t op2; // function to check Op2 - func_is_op_t op3; // function to check Op3 - ushort itype; // itype of instruction -}; - -struct macro_t -{ - const macro_insn_t *insns; // array of instructions - ushort itype; // itype of macro - char cmd; // indice (1..n) of the "base" cmd - char op1_cmd; // indice (1..n) of the cmd containing the 1st operand - char op1_cmd_op; // indice of the operand from the cmd containing the 1st operand - char op2_cmd; - char op2_cmd_op; - char op3_cmd; - char op3_cmd_op; -}; -#define OP_VOID 0, 0 -#define OP_CMD(CMD,OP) CMD, OP - - -//-------------------------------------------------------------------------- -// build a macro and return true, or return cmd and return false -static bool build_macro(const macro_t *macros, int itype_null, insn_t &build, const insn_t &insn) -{ - build = insn; - cmds_t cmds(insn); - const macro_t *macro = macros; - while ( macro->itype != itype_null ) // loop into macros array - { - const macro_insn_t *mdef = macro->insns; - cmds.reset(); - int size = 0; - while ( mdef->itype != itype_null ) // loop into instructions of the macro - { - const insn_t *pcmds = cmds.get_next(); // get the instruction - if ( pcmds == NULL ) - break; - size += pcmds->size; - // check if instructions and operands correspond - if ( pcmds->itype != mdef->itype ) - break; - if ( mdef->op1 && !mdef->op1(pcmds, pcmds->Op1) ) - break; - if ( mdef->op2 && !mdef->op2(pcmds, pcmds->Op2) ) - break; - if ( mdef->op3 && !mdef->op2(pcmds, pcmds->Op3) ) - break; - if ( (mdef+1)->itype == itype_null ) // macro founded - { - ea_t ea = cmds.get(0)->ea; - // check if an external Xrefs exists - xrefblk_t xb; - for ( ea_t i = ea; i < ea+size; i++ ) - for ( int ok = xb.first_to(i,XREF_FAR); ok; ok=xb.next_to() ) - if ( xb.from < ea || xb.from >= ea+size ) - return false; // external Xref founded - - // fill resulting insn_t - build = *cmds.get(macro->cmd-1); - build.ea = ea; - build.size = (uint16)size; - build.itype = macro->itype; - if ( macro->op1_cmd ) - build.Op1 = cmds.get(macro->op1_cmd-1)->ops[macro->op1_cmd_op-1]; - else - build.Op1.type = o_void; - build.Op1.n = 1; - if ( macro->op2_cmd ) - build.Op2 = cmds.get(macro->op2_cmd-1)->ops[macro->op2_cmd_op-1]; - else - build.Op2.type = o_void; - build.Op2.n = 2; - if ( macro->op3_cmd ) - build.Op3 = cmds.get(macro->op3_cmd-1)->ops[macro->op3_cmd_op-1]; - else - build.Op3.type = o_void; - build.Op3.n = 3; - return true; - } - mdef++; - } - macro++; - } - return false; -} - -//-------------------------------------------------------------------------- -// analyze cmd and next instructions to eventually detect a macro and update database -static void process_macros(insn_t &insn, const macro_t *macros, int itype_null, bool macro_on) -{ - if ( macro_on ) // try to build a macro - { - insn_t macro; - if ( build_macro(macros, itype_null, macro, insn) ) - insn = macro; // a macro can be built - } - if ( is_head(get_flags(insn.ea)) // if not the first analyze - && insn.size != get_item_size(insn.ea) ) // and the size of the instruction just changed - { - // reanalyze - del_items(insn.ea, DELIT_SIMPLE, insn.size); // undefine preceding instructions - auto_make_code(insn.ea); - } -} - -//-------------------------------------------------------------------------- -// get the value of a bank -static sel_t get_bank_value(const insn_t &insn, int bank) -{ - sel_t sel; - if ( bank != PCB ) - { - if ( bank == SPB ) - { - sel_t ccr = get_sreg(insn.ea, CCR); - if ( ccr == BADSEL ) - ccr = 0; - if ( ccr & 0x20 ) - bank = SSB; - else - bank = USB; - } - - sel = get_sreg(insn.ea, bank); - if ( sel == BADSEL ) - sel = 0; - } - else - { - sel = insn.cs; - } - return sel & 0xFF; -} - -//-------------------------------------------------------------------------- -// get the value of the bank used by the instruction (eventually with a prefix) -static sel_t get_insn_bank_value(const insn_t &insn) -{ - int bank = 0; - if ( insn.prefix_bank ) - bank = insn.prefix_bank; - else if ( insn.default_bank ) - bank = insn.default_bank; - else - error("interr: emu: get_insn_bank_value()"); - return get_bank_value(insn, bank); -} - -//-------------------------------------------------------------------------- -#define op_reg(REG,DTYP) \ - static void op_##REG(const map_t *, int, op_t &op, insn_t &) \ - { \ - op.type = o_reg; \ - op.reg = REG; \ - op.dtype = dt_##DTYP; \ - } -op_reg(A,dword) // op_A -op_reg(AH,word) // op_AH -op_reg(AL,word) // op_AL -op_reg(SP,word) // op_SP -op_reg(PC,word) // op_PC -op_reg(PCB,byte) // op_PCB -op_reg(DTB,byte) // op_DTB -op_reg(ADB,byte) // op_ADB -op_reg(SPB,byte) // op_SPB -op_reg(SSB,byte) // op_SSB -op_reg(USB,byte) // op_USB -op_reg(DPR,byte) // op_DPR -op_reg(PS,word) // op_PS -op_reg(ILM,byte) // op_ILM -op_reg(RP,byte) // op_RP -op_reg(CCR,byte) // op_CCR - -#define op_regi(NAME,REG,DTYP) \ - static void op_##NAME(const map_t *, int offset, op_t &op, insn_t &) \ - { \ - op.type = o_reg; \ - op.reg = uint16(REG + offset); \ - op.dtype = dt_##DTYP; \ - } -op_regi(Ri,R0,byte) // op_Ri -op_regi(RWi,RW0,word) // op_RWi -op_regi(RLi,RL0,dword) // op_RLi -// special for EA RLi adressing mode - -static void op_RLi2(const map_t *, int offset, op_t &op, insn_t &) -{ - op.type = o_reg; - op.reg = uint16(RL0 + (offset>>1)); - op.dtype = dt_dword; -} - -#define op_at(OP,DEFAULT_BANK,DTYP) \ - static void op_##DTYP##_at_##OP(const map_t *map, int offset, op_t &op, insn_t &insn) \ - { \ - op_##OP(map,offset,op,insn); \ - insn.default_bank = DEFAULT_BANK; \ - insn.op_bank = op.n; \ - op.type = o_phrase; \ - op.at++; \ - op.dtype = dt_##DTYP; \ - } -op_at(A,DTB,byte) // op_byte_at_A -op_at(A,DTB,word) // op_word_at_A -op_at(A,DTB,code) // op_code_at_A -op_at(AL,DTB,byte) // op_byte_at_AL -op_at(AL,DTB,word) // op_word_at_AL -// op_DTYP_at_RWi -op_at(RLi,0,byte) // op_byte_at_RLi -op_at(RLi,0,word) // op_word_at_RLi -//op_at(RLi,0,dword) // op_dword_at_RLi -op_at(PC,PCB,byte) // op_byte_at_PC -op_at(PC,PCB,word) // op_word_at_PC -op_at(PC,PCB,dword) // op_dword_at_PC - -#define op_at_RWi(DTYP) \ - static void op_##DTYP##_at_RWi(const map_t *map, int offset, op_t &op, insn_t &insn) \ - { \ - op_RWi(map,offset,op,insn); \ - op.type = o_phrase; \ - op.at++; \ - op.dtype = dt_##DTYP; \ - switch ( offset ) \ - { \ - case 0: \ - case 1: \ - case 4: \ - case 5: \ - insn.default_bank = DTB; \ - break; \ - case 3: \ - case 7: \ - insn.default_bank = SPB; \ - break; \ - case 2: \ - case 6: \ - insn.default_bank = ADB; \ - break; \ - } \ - insn.op_bank = op.n; \ - } -op_at_RWi(byte) -op_at_RWi(word) -op_at_RWi(dword) - -#define op_imm(NAME,VALUE,DTYP,IN) \ - static void op_##NAME(const map_t *, int offset, op_t &op, insn_t &IN) \ - { \ - op.type = o_imm; \ - op.value = VALUE; \ - op.dtype = dt_##DTYP; \ - } -op_imm(imm4,offset,byte, /*insn*/) // op_imm4 -#define offset -op_imm(imm8,insn.get_next_byte(),byte,insn) // op_imm8 -op_imm(imm16,insn.get_next_word(),word,insn) // op_imm16 -op_imm(imm32,insn.get_next_dword(),dword,insn) // op_imm32 -#undef offset - -#define op_dir(DTYP) \ - static void op_dir_##DTYP(const map_t *, int, op_t &op, insn_t &insn) \ - { \ - insn.default_bank = DTB; \ - insn.op_bank = op.n; \ - op.type = o_mem; \ - op.dtype = dt_##DTYP; \ - sel_t dpr = get_sreg(insn.ea, DPR); \ - if ( dpr == BADSEL ) \ - dpr = 0; \ - op.addr = (get_insn_bank_value(insn) << 16) | ((dpr&0xFF) << 8) | insn.get_next_byte(); \ - op.addr_dtyp = 's'; \ - } -op_dir(byte) // op_dir_byte -op_dir(word) // op_dir_word -//op_dir(dword) // op_dir_dword - -#define op_io(DTYP) \ - static void op_io_##DTYP(const map_t *, int, op_t &op, insn_t &insn) \ - { \ - op.type = o_mem; \ - op.dtype = dt_##DTYP; \ - op.addr = insn.get_next_byte(); \ - op.addr_dtyp = 'i'; \ - } -op_io(byte) // op_io_byte -op_io(word) // op_io_word -//op_io(dword) // op_io_dword - -#define op_addr16(DEFAULT_BANK,TYPE,DTYP) \ - static void op_addr16_##DTYP(const map_t *, int, op_t &op, insn_t &insn) \ - { \ - insn.default_bank = DEFAULT_BANK; \ - insn.op_bank = op.n; \ - op.type = o_##TYPE; \ - op.addr = (get_insn_bank_value(insn) << 16) | insn.get_next_word(); \ - op.dtype = dt_##DTYP; \ - } -op_addr16(PCB, near, code) // op_addr16_code -op_addr16(DTB, mem, byte) // op_addr16_byte -op_addr16(DTB, mem, word) // op_addr16_word -op_addr16(DTB, mem, dword) // op_addr16_dword - -#define op_bp(NAME,OP) \ - static void op_bp_##NAME(const map_t *map, int offset, op_t &op, insn_t &insn) \ - { \ - op_##OP(map,offset,op,insn); \ - op.special_mode = MODE_BIT; \ - op.byte_bit = uchar(offset); \ - } -op_bp(io,io_byte) // op_bp_io -op_bp(dir,dir_byte) // op_bp_dir -op_bp(addr16,addr16_byte) // op_bp_addr16 - -#define op_at_RWi_inc(DTYP) \ - static void op_##DTYP##_at_RWi_inc(const map_t *map, int offset, op_t &op, insn_t &insn) \ - { \ - op_##DTYP##_at_RWi(map, offset, op, insn); \ - op.special_mode = MODE_INC; \ - } -op_at_RWi_inc(byte) // op_byte_at_RWi_inc -op_at_RWi_inc(word) // op_word_at_RWi_inc -op_at_RWi_inc(dword) // op_dword_at_RWi_inc - -#define op_at_reg_displ(NAME,REG,VALUE,VALUE_DTYP,DTYP) \ - static void op_##DTYP##_at_##REG##_##NAME(const map_t *map, int offset, op_t &op, insn_t &insn) \ - { \ - op_##DTYP##_at_##REG(map,offset,op,insn); \ - op.type = o_displ; \ - op.addr = VALUE; \ - op.addr_dtyp = dt_##VALUE_DTYP; \ - } -op_at_reg_displ(disp8,RWi,get_signed(insn.get_next_byte(),0xFF),byte,byte) // op_byte_at_RWi_disp8 -op_at_reg_displ(disp8,RWi,get_signed(insn.get_next_byte(),0xFF),byte,word) // op_word_at_RWi_disp8 -op_at_reg_displ(disp8,RWi,get_signed(insn.get_next_byte(),0xFF),byte,dword) // op_dword_at_RWi_disp8 -op_at_reg_displ(disp16,RWi,get_signed(insn.get_next_word(),0xFFFF),word,byte) // op_byte_at_RWi_disp16 -op_at_reg_displ(disp16,RWi,get_signed(insn.get_next_word(),0xFFFF),word,word) // op_word_at_RWi_disp16 -op_at_reg_displ(disp16,RWi,get_signed(insn.get_next_word(),0xFFFF),word,dword) // op_dword_at_RWi_disp16 -op_at_reg_displ(disp8,RLi,get_signed(insn.get_next_byte(),0xFF),byte,byte) // op_byte_at_RLi_disp8 -op_at_reg_displ(disp8,RLi,get_signed(insn.get_next_byte(),0xFF),byte,word) // op_word_at_RLi_disp8 -//op_at_reg_displ(disp8,RLi,get_signed(insn.get_next_byte(),0xFF),byte,dword) // op_dword_at_RLi_disp8 -op_at_reg_displ(disp16,PC,get_signed(insn.get_next_word(),0xFFFF),word,byte) // op_byte_at_PC_disp16 -op_at_reg_displ(disp16,PC,get_signed(insn.get_next_word(),0xFFFF),word,word) // op_word_at_PC_disp16 -op_at_reg_displ(disp16,PC,get_signed(insn.get_next_word(),0xFFFF),word,dword) // op_dword_at_PC_disp16 - -#define op_ea(REG,DTYP) \ -static void op_ea_##DTYP(const map_t *map, int offset, op_t &op, insn_t &insn) \ -{ \ - if ( offset < 8 ) \ - op_##REG(map, offset, op, insn); \ - else if ( offset < 0x0C ) \ - op_##DTYP##_at_RWi(map, offset-0x08, op, insn); \ - else if ( offset < 0x10 ) \ - op_##DTYP##_at_RWi_inc(map, offset-0x0C, op, insn); \ - else if ( offset < 0x18 ) \ - op_##DTYP##_at_RWi_disp8(map, offset-0x10, op, insn); \ - else if ( offset < 0x1C ) \ - op_##DTYP##_at_RWi_disp16(map, offset-0x18, op, insn); \ - else if ( offset < 0x1E ) \ - { \ - op_##DTYP##_at_RWi(map, offset-0x1C, op, insn); \ - op.special_mode = MODE_INDEX; \ - op.index = RW7; \ - } \ - else if ( offset == 0x1E ) \ - op_##DTYP##_at_PC_disp16(map, offset-0x18, op, insn); \ - else \ - op_addr16_##DTYP(map, offset-0x1F, op, insn); \ -} - -op_ea(Ri,byte) // op_ea_byte -op_ea(RWi,word) // op_ea_word -op_ea(RLi2,dword) // op_ea_dword - -#define op_code_at_ea(DEFAULT_BANK,DTYP) \ - static void op_code_at_ea_##DTYP(const map_t *map, int offset, op_t &op, insn_t &insn) \ - { \ - op_ea_##DTYP(map,offset,op, insn); \ - insn.default_bank = DEFAULT_BANK; \ - insn.op_bank = op.n; \ - op.at++; \ - op.dtype = dt_code; \ - } -op_code_at_ea(PCB,word) // op_code_at_ea_word -op_code_at_ea(0,dword) // op_code_at_ea_dword - - -//-------------------------------------------------------------------------- -static void op_addr24(const map_t *, int, op_t &op, insn_t &insn) -{ - op.type = o_far; - op.addr = insn.get_next_word(); - op.addr |= insn.get_next_byte() << 16; - op.dtype = dt_code; -} - -//-------------------------------------------------------------------------- -static void op_rel(const map_t *, int, op_t &op, insn_t &insn) -{ - int offset = get_signed(insn.get_next_byte(), 0xFF); - op.type = o_near; - op.addr = (insn.ip & ~0xFFFF) | ((insn.ip + insn.size + offset) & 0xFFFF); - op.dtype = dt_code; -} - -//------------------------------------------------------------------------- -static void op_rlst(const map_t *, int, op_t &op, insn_t &insn) -{ - op.type = o_reglist; - op.reg = insn.get_next_byte(); - op.dtype = dt_byte; -} - -//-------------------------------------------------------------------------- -// used for string instructions -static void op_PCB_DTB_ADB_SPB(const map_t *map, int offset, op_t &op, insn_t &insn) -{ - static const func_op_t banks[4] = { op_PCB, op_DTB, op_ADB, op_SPB }; - banks[offset&3](map, offset, op, insn); -} - -//-------------------------------------------------------------------------- -// used for writing/reading values to/from bank registers -static void op_DTB_ADB_SSB_USB_DPR(const map_t *map, int offset, op_t &op, insn_t &insn) -{ - static const func_op_t banks[5] = { op_DTB, op_ADB, op_SSB, op_USB, op_DPR }; - banks[offset%5](map, offset, op, insn); -} - -//-------------------------------------------------------------------------- -static const map_t bitop_map[] = // bit operations -{ - { NULL, 0x00, F2MC_movb, op_A, op_bp_io, 0, OP_NULL }, - { NULL, 0x08, F2MC_movb, op_A, op_bp_dir, 0, OP_NULL }, - { NULL, 0x10, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x18, F2MC_movb, op_A, op_bp_addr16, 0, OP_NULL }, - { NULL, 0x20, F2MC_movb, op_bp_io, op_A, 0, OP_NULL }, - { NULL, 0x28, F2MC_movb, op_bp_dir, op_A, 0, OP_NULL }, - { NULL, 0x30, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x38, F2MC_movb, op_bp_addr16, op_A, 0, OP_NULL }, - { NULL, 0x40, F2MC_clrb, op_bp_io, 0, 0, OP_NULL }, - { NULL, 0x48, F2MC_clrb, op_bp_dir, 0, 0, OP_NULL }, - { NULL, 0x50, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x58, F2MC_clrb, op_bp_addr16, 0, 0, OP_NULL }, - { NULL, 0x60, F2MC_setb, op_bp_io, 0, 0, OP_NULL }, - { NULL, 0x68, F2MC_setb, op_bp_dir, 0, 0, OP_NULL }, - { NULL, 0x70, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x78, F2MC_setb, op_bp_addr16, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_bbc, op_bp_io, op_rel, 0, OP_NULL }, - { NULL, 0x88, F2MC_bbc, op_bp_dir, op_rel, 0, OP_NULL }, - { NULL, 0x90, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x98, F2MC_bbc, op_bp_addr16, op_rel, 0, OP_NULL }, - { NULL, 0xA0, F2MC_bbs, op_bp_io, op_rel, 0, OP_NULL }, - { NULL, 0xA8, F2MC_bbs, op_bp_dir, op_rel, 0, OP_NULL }, - { NULL, 0xB0, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xB8, F2MC_bbs, op_bp_addr16, op_rel, 0, OP_NULL }, - { NULL, 0xC0, F2MC_wbts, op_bp_io, 0, 0, OP_NULL }, - { NULL, 0xC8, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xE0, F2MC_wbtc, op_bp_io, 0, 0, OP_NULL }, - { NULL, 0xE8, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xF8, F2MC_sbbs, op_bp_addr16, op_rel, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t strop_map[] = // string operations -{ - { NULL, 0x00, F2MC_movsi, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, - { NULL, 0x10, F2MC_movsd, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, - { NULL, 0x20, F2MC_movswi, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, - { NULL, 0x30, F2MC_movswd, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, - { NULL, 0x40, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_sceqi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, - { NULL, 0x84, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x90, F2MC_sceqd, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, - { NULL, 0x94, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xA0, F2MC_scweqi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, - { NULL, 0xA4, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xB0, F2MC_scweqd, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, - { NULL, 0xB4, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xC0, F2MC_filsi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, - { NULL, 0xC4, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0xE0, F2MC_filswi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, - { NULL, 0xE4, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t twobyte_map[] = -{ - { NULL, 0x00, F2MC_mov, op_A, op_DTB_ADB_SSB_USB_DPR, 0, OP_NULL }, - { NULL, 0x05, F2MC_mov, op_A, op_byte_at_A, 0, OP_NULL }, - { NULL, 0x06, F2MC_mov, op_A, op_PCB, 0, OP_NULL }, - { NULL, 0x07, F2MC_rolc, op_A, 0, 0, OP_NULL }, - { NULL, 0x08, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x0C, F2MC_lslw2, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x0D, F2MC_movw, op_A, op_word_at_A, 0, OP_NULL }, - { NULL, 0x0E, F2MC_asrw2, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x0F, F2MC_lsrw2, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x10, F2MC_mov, op_DTB_ADB_SSB_USB_DPR, op_A, 0, OP_NULL }, - { NULL, 0x15, F2MC_mov, op_byte_at_AL, op_AH, 0, OP_NULL }, - { NULL, 0x16, F2MC_movx, op_A, op_byte_at_A, 0, OP_NULL }, - { NULL, 0x17, F2MC_rorc, op_A, 0, 0, OP_NULL }, - { NULL, 0x18, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x1C, F2MC_lsll, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x1D, F2MC_movw, op_word_at_AL, op_AH, 0, OP_NULL }, - { NULL, 0x1E, F2MC_asrl, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x1F, F2MC_lsrl, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x20, F2MC_movx, op_A, op_byte_at_RLi_disp8, 0, OP_3_2(2) }, - { NULL, 0x27, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x2C, F2MC_lsl, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x2D, F2MC_nrml, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x2E, F2MC_asr, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x2F, F2MC_lsr, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x30, F2MC_mov, op_byte_at_RLi_disp8, op_A, 0, OP_3_1(2) }, - { NULL, 0x38, F2MC_movw, op_word_at_RLi_disp8, op_A, 0, OP_3_1(2) }, - { NULL, 0x40, F2MC_mov, op_A, op_byte_at_RLi_disp8, 0, OP_3_2(2) }, - { NULL, 0x48, F2MC_movw, op_A, op_word_at_RLi_disp8, 0, OP_3_2(2) }, - { NULL, 0x50, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x78, F2MC_mul1, op_A, 0, 0, OP_NULL }, - { NULL, 0x79, F2MC_mulw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x7A, F2MC_div1, op_A, 0, 0, OP_NULL }, - { NULL, 0x7B, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_1_map[] = -{ - { NULL, 0x00, F2MC_addl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0x20, F2MC_subl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0x40, F2MC_cwbne, op_ea_word, op_imm16, op_rel, OP_NULL }, - { NULL, 0x60, F2MC_cmpl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0x80, F2MC_andl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0xA0, F2MC_orl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0xC0, F2MC_xorl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0xE0, F2MC_cbne, op_ea_byte, op_imm8, op_rel, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_2_map[] = -{ - { NULL, 0x00, F2MC_jmpp, op_code_at_ea_dword, 0, 0, OP_NULL }, - { NULL, 0x20, F2MC_callp, op_code_at_ea_dword, 0, 0, OP_NULL }, - { NULL, 0x40, F2MC_incl, op_ea_dword, 0, 0, OP_NULL }, - { NULL, 0x60, F2MC_decl, op_ea_dword, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_movl, op_A, op_ea_dword, 0, OP_NULL }, - { NULL, 0xA0, F2MC_movl, op_ea_dword, op_A, 0, OP_NULL }, - { NULL, 0xC0, F2MC_mov, op_ea_byte, op_imm8, 0, OP_NULL }, - { NULL, 0xE0, F2MC_movea, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_3_map[] = -{ - { NULL, 0x00, F2MC_rolc, op_ea_byte, 0, 0, OP_NULL }, - { NULL, 0x20, F2MC_rorc, op_ea_byte, 0, 0, OP_NULL }, - { NULL, 0x40, F2MC_inc, op_ea_byte, 0, 0, OP_NULL }, - { NULL, 0x60, F2MC_dec, op_ea_byte, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_mov, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xA0, F2MC_mov, op_ea_byte, op_A, 0, OP_NULL }, - { NULL, 0xC0, F2MC_movx, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xE0, F2MC_xch, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_4_map[] = -{ - { NULL, 0x00, F2MC_jmp, op_code_at_ea_word, 0, 0, OP_NULL }, - { NULL, 0x20, F2MC_call, op_code_at_ea_word, 0, 0, OP_NULL }, - { NULL, 0x40, F2MC_incw, op_ea_word, 0, 0, OP_NULL }, - { NULL, 0x60, F2MC_decw, op_ea_word, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_movw, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0xA0, F2MC_movw, op_ea_word, op_A, 0, OP_NULL }, - { NULL, 0xC0, F2MC_movw, op_ea_word, op_imm16, 0, OP_NULL }, - { NULL, 0xE0, F2MC_xchw, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_5_map[] = -{ - { NULL, 0x00, F2MC_add, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x20, F2MC_sub, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x40, F2MC_addc2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x60, F2MC_cmp2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x80, F2MC_and, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xA0, F2MC_or, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xC0, F2MC_xor, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xE0, F2MC_dbnz, op_ea_byte, op_rel, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_6_map[] = -{ - { NULL, 0x00, F2MC_add, op_ea_byte, op_A, 0, OP_NULL }, - { NULL, 0x20, F2MC_sub, op_ea_byte, op_A, 0, OP_NULL }, - { NULL, 0x40, F2MC_subc2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x60, F2MC_neg, op_ea_byte, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_and, op_ea_byte, op_A, 0, OP_NULL }, - { NULL, 0xA0, F2MC_or, op_ea_byte, op_A, 0, OP_NULL }, - { NULL, 0xC0, F2MC_xor, op_ea_byte, op_A, 0, OP_NULL }, - { NULL, 0xE0, F2MC_not, op_ea_byte, 0, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_7_map[] = -{ - { NULL, 0x00, F2MC_addw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x20, F2MC_subw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x40, F2MC_addcw, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x60, F2MC_cmpw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x80, F2MC_andw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0xA0, F2MC_orw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0xC0, F2MC_xorw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0xE0, F2MC_dwbnz, op_ea_word, op_rel, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_8_map[] = -{ - { NULL, 0x00, F2MC_addw2, op_ea_word, op_A, 0, OP_NULL }, - { NULL, 0x20, F2MC_subw2, op_ea_word, op_A, 0, OP_NULL }, - { NULL, 0x40, F2MC_subcw, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x60, F2MC_negw, op_ea_word, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_andw2, op_ea_word, op_A, 0, OP_NULL }, - { NULL, 0xA0, F2MC_orw2, op_ea_word, op_A, 0, OP_NULL }, - { NULL, 0xC0, F2MC_xorw2, op_ea_word, op_A, 0, OP_NULL }, - { NULL, 0xE0, F2MC_notw, op_ea_word, 0, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_9_map[] = -{ - { NULL, 0x00, F2MC_mulu2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x20, F2MC_muluw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x40, F2MC_mul2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0x60, F2MC_mulw2, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0x80, F2MC_divu2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xA0, F2MC_divuw, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0xC0, F2MC_div2, op_A, op_ea_byte, 0, OP_NULL }, - { NULL, 0xE0, F2MC_divw, op_A, op_ea_word, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t RWi_ea_map[] = -{ - { NULL, 0x00, F2MC_null, op_RWi, op_ea_word, 0, OP_2_1(32) }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t Ri_ea_map[] = -{ - { NULL, 0x00, F2MC_null, op_Ri, op_ea_byte, 0, OP_2_1(32) }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_Ri_map[] = -{ - { NULL, 0x00, F2MC_null, op_ea_byte, op_Ri, 0, OP_1_2(32) }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t ea_RWi_map[] = -{ - { NULL, 0x00, F2MC_null, op_ea_word, op_RWi, 0, OP_1_2(32) }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -static const map_t basic_map[] = -{ - { NULL, 0x00, F2MC_nop, 0, 0, 0, OP_NULL }, - { NULL, 0x01, F2MC_int9, 0, 0, 0, OP_NULL }, - { NULL, 0x02, F2MC_adddc, op_A, 0, 0, OP_NULL }, - { NULL, 0x03, F2MC_neg, op_A, 0, 0, OP_NULL }, - { NULL, 0x04, F2MC_pcb, 0, 0, 0, OP_NULL }, - { NULL, 0x05, F2MC_dtb, 0, 0, 0, OP_NULL }, - { NULL, 0x06, F2MC_adb, 0, 0, 0, OP_NULL }, - { NULL, 0x07, F2MC_spb, 0, 0, 0, OP_NULL }, - { NULL, 0x08, F2MC_link, op_imm8, 0, 0, OP_NULL }, - { NULL, 0x09, F2MC_unlink, 0, 0, 0, OP_NULL }, - { NULL, 0x0A, F2MC_mov, op_RP, op_imm8, 0, OP_NULL }, - { NULL, 0x0B, F2MC_negw, op_A, 0, 0, OP_NULL }, - { NULL, 0x0C, F2MC_lslw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x0D, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x0E, F2MC_asrw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x0F, F2MC_lsrw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x10, F2MC_cmr, 0, 0, 0, OP_NULL }, - { NULL, 0x11, F2MC_ncc, 0, 0, 0, OP_NULL }, - { NULL, 0x12, F2MC_subdc, op_A, 0, 0, OP_NULL }, - { NULL, 0x13, F2MC_jctx, op_byte_at_A, 0, 0, OP_NULL }, - { NULL, 0x14, F2MC_ext, 0, 0, 0, OP_NULL }, - { NULL, 0x15, F2MC_zext, 0, 0, 0, OP_NULL }, - { NULL, 0x16, F2MC_swap, 0, 0, 0, OP_NULL }, - { NULL, 0x17, F2MC_addsp, op_imm8, 0, 0, OP_NULL }, - { NULL, 0x18, F2MC_addl, op_A, op_imm32, 0, OP_NULL }, - { NULL, 0x19, F2MC_subl, op_A, op_imm32, 0, OP_NULL }, - { NULL, 0x1A, F2MC_mov, op_ILM, op_imm8, 0, OP_NULL }, - { NULL, 0x1B, F2MC_cmpl, op_A, op_imm32, 0, OP_NULL }, - { NULL, 0x1C, F2MC_extw, 0, 0, 0, OP_NULL }, - { NULL, 0x1D, F2MC_zextw, 0, 0, 0, OP_NULL }, - { NULL, 0x1E, F2MC_swapw, 0, 0, 0, OP_NULL }, - { NULL, 0x1F, F2MC_addsp, op_imm16, 0, 0, OP_NULL }, - { NULL, 0x20, F2MC_add, op_A, op_dir_byte, 0, OP_NULL }, - { NULL, 0x21, F2MC_sub, op_A, op_dir_byte, 0, OP_NULL }, - { NULL, 0x22, F2MC_addc1, op_A, 0, 0, OP_NULL }, - { NULL, 0x23, F2MC_cmp1, op_A, 0, 0, OP_NULL }, - { NULL, 0x24, F2MC_and, op_CCR, op_imm8, 0, OP_NULL }, - { NULL, 0x25, F2MC_or, op_CCR, op_imm8, 0, OP_NULL }, - { NULL, 0x26, F2MC_divu1, op_A, 0, 0, OP_NULL }, - { NULL, 0x27, F2MC_mulu1, op_A, 0, 0, OP_NULL }, - { NULL, 0x28, F2MC_addw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x29, F2MC_subw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x29, F2MC_subw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x2A, F2MC_cbne, op_A, op_imm8, op_rel, OP_NULL }, - { NULL, 0x2B, F2MC_cmpw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x2C, F2MC_andw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x2D, F2MC_orw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x2E, F2MC_xorw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x2F, F2MC_muluw1, op_A, 0, 0, OP_NULL }, - { NULL, 0x30, F2MC_add, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x31, F2MC_sub, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x32, F2MC_subc1, op_A, 0, 0, OP_NULL }, - { NULL, 0x33, F2MC_cmp2, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x34, F2MC_and, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x35, F2MC_or, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x36, F2MC_xor, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x37, F2MC_not, op_A, 0, 0, OP_NULL }, - { NULL, 0x38, F2MC_addw2, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x39, F2MC_subw2, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x3A, F2MC_cwbne, op_A, op_imm16, op_rel, OP_NULL }, - { NULL, 0x3B, F2MC_cmpw2, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x3C, F2MC_andw2, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x3D, F2MC_orw2, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x3E, F2MC_xorw2, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x3F, F2MC_notw, op_A, 0, 0, OP_NULL }, - { NULL, 0x40, F2MC_mov, op_A, op_dir_byte, 0, OP_NULL }, - { NULL, 0x41, F2MC_mov, op_dir_byte, op_A, 0, OP_NULL }, - { NULL, 0x42, F2MC_mov, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x43, F2MC_movx, op_A, op_imm8, 0, OP_NULL }, - { NULL, 0x44, F2MC_mov, op_dir_byte, op_imm8, 0, OP_NULL }, - { NULL, 0x45, F2MC_movx, op_A, op_dir_byte, 0, OP_NULL }, - { NULL, 0x46, F2MC_movw, op_A, op_SP, 0, OP_NULL }, - { NULL, 0x47, F2MC_movw, op_SP, op_A, 0, OP_NULL }, - { NULL, 0x48, F2MC_movw, op_A, op_dir_word, 0, OP_NULL }, - { NULL, 0x49, F2MC_movw, op_dir_word, op_A, 0, OP_NULL }, - { NULL, 0x4A, F2MC_movw, op_A, op_imm16, 0, OP_NULL }, - { NULL, 0x4B, F2MC_movl, op_A, op_imm32, 0, OP_NULL }, - { NULL, 0x4C, F2MC_pushw, op_A, 0, 0, OP_NULL }, - { NULL, 0x4D, F2MC_pushw, op_AH, 0, 0, OP_NULL }, - { NULL, 0x4E, F2MC_pushw, op_PS, 0, 0, OP_NULL }, - { NULL, 0x4F, F2MC_pushw, op_rlst, 0, 0, OP_NULL }, - { NULL, 0x50, F2MC_mov, op_A, op_io_byte, 0, OP_NULL }, - { NULL, 0x51, F2MC_mov, op_io_byte, op_A, 0, OP_NULL }, - { NULL, 0x52, F2MC_mov, op_A, op_addr16_byte, 0, OP_NULL }, - { NULL, 0x53, F2MC_mov, op_addr16_byte, op_A, 0, OP_NULL }, - { NULL, 0x54, F2MC_mov, op_io_byte, op_imm8, 0, OP_NULL }, - { NULL, 0x55, F2MC_movx, op_A, op_io_byte, 0, OP_NULL }, - { NULL, 0x56, F2MC_movw, op_io_word, op_imm16, 0, OP_NULL }, - { NULL, 0x57, F2MC_movx, op_A, op_addr16_byte, 0, OP_NULL }, - { NULL, 0x58, F2MC_movw, op_A, op_io_word, 0, OP_NULL }, - { NULL, 0x59, F2MC_movw, op_io_word, op_A, 0, OP_NULL }, - { NULL, 0x5A, F2MC_movw, op_A, op_addr16_word, 0, OP_NULL }, - { NULL, 0x5B, F2MC_movw, op_addr16_word, op_A, 0, OP_NULL }, - { NULL, 0x5C, F2MC_popw, op_A, 0, 0, OP_NULL }, - { NULL, 0x5D, F2MC_popw, op_AH, 0, 0, OP_NULL }, - { NULL, 0x5E, F2MC_popw, op_PS, 0, 0, OP_NULL }, - { NULL, 0x5F, F2MC_popw, op_rlst, 0, 0, OP_NULL }, - { NULL, 0x60, F2MC_bra, op_rel, 0, 0, OP_NULL }, - { NULL, 0x61, F2MC_jmp, op_code_at_A, 0, 0, OP_NULL }, - { NULL, 0x62, F2MC_jmp, op_addr16_code, 0, 0, OP_NULL }, - { NULL, 0x63, F2MC_jmpp, op_addr24, 0, 0, OP_NULL }, - { NULL, 0x64, F2MC_call, op_addr16_code, 0, 0, OP_NULL }, - { NULL, 0x65, F2MC_callp, op_addr24, 0, 0, OP_NULL }, - { NULL, 0x66, F2MC_retp, 0, 0, 0, OP_NULL }, - { NULL, 0x67, F2MC_ret, 0, 0, 0, OP_NULL }, - { NULL, 0x68, F2MC_int, op_imm8, 0, 0, OP_NULL }, - { NULL, 0x69, F2MC_int, op_addr16_code, 0, 0, OP_NULL }, - { NULL, 0x6A, F2MC_intp, op_addr24, 0, 0, OP_NULL }, - { NULL, 0x6B, F2MC_reti, 0, 0, 0, OP_NULL }, - { bitop_map, 0x6C, F2MC_null, 0, 0, 0, OP_NULL }, - { NULL, 0x6D, F2MC_null, 0, 0, 0, OP_NULL }, - { strop_map, 0x6E, F2MC_null, 0, 0, 0, OP_NULL }, - { twobyte_map,0x6F, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_1_map, 0x70, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_2_map, 0x71, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_3_map, 0x72, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_4_map, 0x73, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_5_map, 0x74, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_6_map, 0x75, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_7_map, 0x76, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_8_map, 0x77, F2MC_null, 0, 0, 0, OP_NULL }, - { ea_9_map, 0x78, F2MC_null, 0, 0, 0, OP_NULL }, - { RWi_ea_map, 0x79, F2MC_movea, 0, 0, 0, OP_NULL }, - { Ri_ea_map, 0x7A, F2MC_mov, 0, 0, 0, OP_NULL }, - { RWi_ea_map, 0x7B, F2MC_movw, 0, 0, 0, OP_NULL }, - { ea_Ri_map, 0x7C, F2MC_mov, 0, 0, 0, OP_NULL }, - { ea_RWi_map, 0x7D, F2MC_movw, 0, 0, 0, OP_NULL }, - { Ri_ea_map, 0x7E, F2MC_xch, 0, 0, 0, OP_NULL }, - { RWi_ea_map, 0x7F, F2MC_xchw, 0, 0, 0, OP_NULL }, - { NULL, 0x80, F2MC_mov, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0x88, F2MC_movw, op_A, op_RWi, 0, OP_NULL }, - { NULL, 0x90, F2MC_mov, op_Ri, op_A, 0, OP_NULL }, - { NULL, 0x98, F2MC_movw, op_RWi, op_A, 0, OP_NULL }, - { NULL, 0xA0, F2MC_mov, op_Ri, op_imm8, 0, OP_NULL }, - { NULL, 0xA8, F2MC_movw, op_RWi, op_imm16, 0, OP_NULL }, - { NULL, 0xB0, F2MC_movx, op_A, op_Ri, 0, OP_NULL }, - { NULL, 0xB8, F2MC_movw, op_A, op_word_at_RWi_disp8, 0, OP_NULL }, - { NULL, 0xC0, F2MC_movx, op_A, op_byte_at_RWi_disp8, 0, OP_NULL }, - { NULL, 0xC8, F2MC_movw, op_word_at_RWi_disp8, op_A, 0, OP_NULL }, - { NULL, 0xD0, F2MC_movn, op_A, op_imm4, 0, OP_NULL }, - { NULL, 0xE0, F2MC_callv, op_imm4, 0, 0, OP_NULL }, - { NULL, 0xF0, F2MC_bz, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF1, F2MC_bnz, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF2, F2MC_bc, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF3, F2MC_bnc, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF4, F2MC_bn, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF5, F2MC_bp, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF6, F2MC_bv, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF7, F2MC_bnv, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF8, F2MC_bt, op_rel, 0, 0, OP_NULL }, - { NULL, 0xF9, F2MC_bnt, op_rel, 0, 0, OP_NULL }, - { NULL, 0xFA, F2MC_blt, op_rel, 0, 0, OP_NULL }, - { NULL, 0xFB, F2MC_bge, op_rel, 0, 0, OP_NULL }, - { NULL, 0xFC, F2MC_ble, op_rel, 0, 0, OP_NULL }, - { NULL, 0xFD, F2MC_bgt, op_rel, 0, 0, OP_NULL }, - { NULL, 0xFE, F2MC_bls, op_rel, 0, 0, OP_NULL }, - { NULL, 0xFF, F2MC_bhi, op_rel, 0, 0, OP_NULL }, - { NULL, 0, 0, 0, 0, 0, OP_NULL } -}; - -//-------------------------------------------------------------------------- -static bool is_A(const insn_t *, const op_t &op) -{ - return op.type == o_reg && op.reg == A; -} - -//-------------------------------------------------------------------------- -static bool is_1(const insn_t *, const op_t &op) -{ - return op.type == o_imm && op.value == 1; -} - -//-------------------------------------------------------------------------- -#define is_rel(REL) \ -static bool is_rel##REL(const insn_t *insn, const op_t &op) \ -{ \ - return op.type == o_near && op.addr == insn->ea + REL; \ -} -is_rel(5) // is_rel5 -is_rel(7) // is_rel7 - -//-------------------------------------------------------------------------- -static bool is_imm(const insn_t *, const op_t &op) -{ - return op.type == o_imm; -} - -//-------------------------------------------------------------------------- -// can't be A (if A then this is a dec/decw MACRO) -static bool is_ea_and_not_A(const insn_t *, const op_t &op) -{ - return op.type != o_reg || op.reg != A; -} - -//-------------------------------------------------------------------------- -static bool is_bp(const insn_t *, const op_t &op) -{ - return op.special_mode == MODE_BIT; -} - -//-------------------------------------------------------------------------- -static bool is_bp_addr16(const insn_t *insn, const op_t &op) -{ - return op.type == o_mem && op.dtype == dt_byte && is_bp(insn, op); -} - -//-------------------------------------------------------------------------- -#define macro_incdec(ITYPE) \ - static const macro_insn_t macro_##ITYPE[] = \ - { \ - { is_A, is_1, 0, F2MC_##ITYPE }, \ - { 0, 0, 0, F2MC_null } \ - } -macro_incdec(add); // macro_add -macro_incdec(addw2); // macro_addw2 -macro_incdec(addl); // macro_addl -macro_incdec(sub); // macro_sub -macro_incdec(subw2); // macro_subw2 -macro_incdec(subl); // macro_subl - -#define macro_bXX16(ITYPE) \ - static const macro_insn_t macro_##ITYPE##_jmp[] = \ - { \ - { is_rel5, 0, 0, F2MC_##ITYPE }, \ - { 0, 0, 0, F2MC_jmp }, \ - { 0, 0, 0, F2MC_null } \ - } -macro_bXX16(bnz); // macro_bnz_jmp -macro_bXX16(bz); // macro_bz_jmp -macro_bXX16(bnc); // macro_bnc_jmp -macro_bXX16(bc); // macro_bc_jmp -macro_bXX16(bp); // macro_bp_jmp -macro_bXX16(bn); // macro_bn_jmp -macro_bXX16(bnv); // macro_bnv_jmp -macro_bXX16(bv); // macro_bv_jmp -macro_bXX16(bnt); // macro_bnt_jmp -macro_bXX16(bt); // macro_bt_jmp -macro_bXX16(bge); // macro_bge_jmp -macro_bXX16(blt); // macro_blt_jmp -macro_bXX16(bgt); // macro_bgt_jmp -macro_bXX16(ble); // macro_ble_jmp -macro_bXX16(bhi); // macro_bhi_jmp -macro_bXX16(bls); // macro_bls_jmp - -#define macro_cXbne16(ITYPE) \ - static const macro_insn_t macro_##ITYPE##_bnz16[] = \ - { \ - { is_A, is_imm, 0, F2MC_##ITYPE }, \ - { 0, 0, 0, F2MC_bnz16 }, \ - { 0, 0, 0, F2MC_null } \ - } -macro_cXbne16(cmp2); // macro_cmp2_bnz16 -macro_cXbne16(cmpw2); // macro_cmpw2_bnz16 - -#define macro_dXbnz16(ITYPE) \ - static const macro_insn_t macro_##ITYPE##_bnz16[] = \ - { \ - { is_ea_and_not_A, 0, 0, F2MC_##ITYPE }, \ - { 0, 0, 0, F2MC_bnz16 }, \ - { 0, 0, 0, F2MC_null } \ - } -macro_dXbnz16(dec); // macro_dec_bnz16 -macro_dXbnz16(decw); // macro_decw_bnz16 - -#define macro_bbX16(ITYPE) \ - static const macro_insn_t macro_##ITYPE##_jmp[] = \ - { \ - { is_bp, is_rel7, 0, F2MC_##ITYPE }, \ - { 0, 0, 0, F2MC_jmp }, \ - { 0, 0, 0, F2MC_null } \ - } -macro_bbX16(bbc); // macro_bbc_jmp -macro_bbX16(bbs); // macro_bbs_jmp - -static const macro_insn_t macro_sbbs_bra_jmp[] = -{ - { is_bp_addr16, is_rel7, 0, F2MC_sbbs }, - { is_rel5, 0, 0, F2MC_bra }, - { 0, 0, 0, F2MC_jmp }, - { 0, 0, 0, F2MC_null } -}; - - -static const macro_t macros[] = -{ - { macro_add, F2MC_inc, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, - { macro_addw2, F2MC_incw, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, - { macro_addl, F2MC_incl, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, - { macro_sub, F2MC_dec, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, - { macro_subw2, F2MC_decw, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, - { macro_subl, F2MC_decl, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, - { macro_bnz_jmp, F2MC_bz16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bz_jmp, F2MC_bnz16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bnc_jmp, F2MC_bc16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bc_jmp, F2MC_bnc16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bp_jmp, F2MC_bn16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bn_jmp, F2MC_bp16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bnv_jmp, F2MC_bv16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bv_jmp, F2MC_bnv16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bnt_jmp, F2MC_bt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bt_jmp, F2MC_bnt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bge_jmp, F2MC_blt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_blt_jmp, F2MC_bge16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bgt_jmp, F2MC_ble16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_ble_jmp, F2MC_bgt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bhi_jmp, F2MC_bls16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_bls_jmp, F2MC_bhi16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, - { macro_cmp2_bnz16, F2MC_cbne16, 1, OP_CMD(1,1), OP_CMD(1,2), OP_CMD(2,1) }, - { macro_cmpw2_bnz16, F2MC_cwbne16, 1, OP_CMD(1,1), OP_CMD(1,2), OP_CMD(2,1) }, - { macro_dec_bnz16, F2MC_dbnz16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, - { macro_decw_bnz16, F2MC_dwbnz16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, - { macro_bbs_jmp, F2MC_bbc16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, - { macro_bbc_jmp, F2MC_bbs16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, - { macro_sbbs_bra_jmp, F2MC_sbbs16, 1, OP_CMD(1,1), OP_CMD(3,1), OP_VOID }, - { NULL, F2MC_null, OP_VOID, OP_VOID, OP_VOID, 0 } -}; - -//-------------------------------------------------------------------------- -void f2mc_t::ana_F2MC16LX(insn_t &insn) -{ - process_maps(insn, basic_map, F2MC_null); // analyze opcode - - // analyze prefix - char prefix; - switch ( insn.itype ) - { - case F2MC_pcb: prefix = PCB; break; - case F2MC_dtb: prefix = DTB; break; - case F2MC_adb: prefix = ADB; break; - case F2MC_spb: prefix = SPB; break; - default: prefix = 0; break; - } - if ( prefix ) - { - insn_t next; - if ( decode_insn(&next, insn.ea + insn.size) > 0 && next.default_bank - && (prefix != next.default_bank) ) // if next instruction need prefix - { - next.ea = insn.ea; - next.size += insn.size; - next.prefix_bank = prefix; - insn = next; - } - } - - process_macros(insn, macros, F2MC_null, (idpflags & F2MC_MACRO) != 0); -} - -//-------------------------------------------------------------------------- -int f2mc_t::ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - - switch ( ptype ) - { - case F2MC16L: - ana_F2MC16LX(insn); - switch ( insn.itype ) - { - case F2MC_div1: - case F2MC_div2: - case F2MC_divw: - case F2MC_mul1: - case F2MC_mul2: - case F2MC_mulw1: - case F2MC_mulw2: - insn.itype = F2MC_null; - break; - } - break; - case F2MC16LX: - ana_F2MC16LX(insn); - break; - default: - error("interr: ana: ana()"); - } - if ( insn.itype == F2MC_null ) - return 0; - return insn.size; -} - -//-------------------------------------------------------------------------- -int get_signed(int byte, int mask) -{ - int bits = mask >> 1; - int sign = bits + 1; - if ( byte & sign ) // offset < 0 - { - byte = ( byte & bits ) - sign; - } - else // offset >= 0 - { - byte = byte & mask; - } - return byte; -} diff --git a/idasdk75/module/f2mc/emu.cpp b/idasdk75/module/f2mc/emu.cpp deleted file mode 100644 index 92a1824..0000000 --- a/idasdk75/module/f2mc/emu.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "f2mc.hpp" -#include <segregs.hpp> -#include <frame.hpp> - -//------------------------------------------------------------------------ -static int get_reglist_size(ushort reglist) -{ - int size = 0; - for ( int i = 0; i < 8; i++ ) - if ( (reglist >> i) & 1 ) - size++; - return size; -} - -//------------------------------------------------------------------------ -static bool is_bank(const op_t &op) -{ - if ( op.type != o_reg ) - return false; - - return op.reg == DTB - || op.reg == ADB - || op.reg == SSB - || op.reg == USB - || op.reg == DPR - || op.reg == PCB; -} - -//---------------------------------------------------------------------- -static void process_imm(const insn_t &insn, const op_t &x) -{ - set_immd(insn.ea); - - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, dr_O, calc_outf(x)); - - if ( is_defarg(get_flags(insn.ea), x.n) ) - return; // if already defined by user - - switch ( insn.itype ) - { - case F2MC_add: - case F2MC_addl: - case F2MC_addsp: - case F2MC_addw2: - case F2MC_and: - case F2MC_andw2: - case F2MC_callv: - case F2MC_cbne: - case F2MC_cmp2: - case F2MC_cmpl: - case F2MC_cmpw2: - case F2MC_cwbne: - case F2MC_int: - case F2MC_link: - case F2MC_mov: - case F2MC_movl: - case F2MC_movn: - case F2MC_movw: - case F2MC_movx: - case F2MC_or: - case F2MC_orw2: - case F2MC_sub: - case F2MC_subl: - case F2MC_subw2: - case F2MC_xor: - case F2MC_xorw2: - op_num(insn.ea, x.n); - } -} - -//---------------------------------------------------------------------- -void f2mc_t::handle_operand(const insn_t &insn, const op_t &x, bool use) -{ - switch ( x.type ) - { - case o_reg: - case o_phrase: - case o_reglist: - return; - - case o_near: - case o_far: - { - cref_t ftype = fl_JN; - ea_t ea = x.addr; - //24-bit (far) operands store the full address. - // so this calculation is needed only for near jumps/calls - if ( x.type == o_near ) - ea = calc_code_mem(insn, x.addr); - - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - if ( !func_does_return(ea) ) - flow = false; - ftype = fl_CN; - } - insn.add_cref(ea, x.offb, ftype); - } - break; - - case o_imm: - QASSERT(10102, use); - process_imm(insn, x); - break; - - case o_mem: - { - ea_t ea = calc_data_mem(x.addr); - insn.add_dref(ea, x.offb, use ? dr_R : dr_W); - insn.create_op_data(ea, x); - } - break; - case o_displ: - process_imm(insn, x); - if ( may_create_stkvars() && x.reg == RW3 ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL - && (pfn->flags & FUNC_FRAME) != 0 - && insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) ) - { - op_stkvar(insn.ea, x.n); - } - } - break; - - default: - warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); - } -} - -//---------------------------------------------------------------------- -inline bool add_stkpnt(func_t *pfn, sval_t delta, const insn_t &insn) -{ - return add_auto_stkpnt(pfn, insn.ea + insn.size, delta); -} - -//---------------------------------------------------------------------- -static void trace_sp(const insn_t &insn) -{ - func_t *pfn = get_func(insn.ea); - if ( pfn == NULL ) - return; - - switch ( insn.itype ) - { - case F2MC_int: - case F2MC_intp: - case F2MC_int9: - add_stkpnt(pfn, -6*2, insn); - break; - case F2MC_reti: - add_stkpnt(pfn, 6*2, insn); - break; - case F2MC_link: - add_stkpnt(pfn, -2-insn.Op1.value, insn); - break; - case F2MC_unlink: - add_stkpnt(pfn, -get_spd(pfn, insn.ea), insn); - break; - case F2MC_ret: - add_stkpnt(pfn, 2, insn); - break; - case F2MC_retp: - add_stkpnt(pfn, 2*2, insn); - break; - case F2MC_pushw: - if ( insn.Op1.type == o_reglist ) - add_stkpnt(pfn, -get_reglist_size(insn.Op1.reg)*2, insn); - else - add_stkpnt(pfn, -2, insn); - break; - case F2MC_popw: - if ( insn.Op1.type == o_reglist ) - add_stkpnt(pfn, get_reglist_size(insn.Op1.reg)*2, insn); - else - add_stkpnt(pfn, 2, insn); - break; - case F2MC_addsp: - add_stkpnt(pfn, insn.Op1.value, insn); - break; - } -} - -//---------------------------------------------------------------------- - -int f2mc_t::emu(const insn_t &insn) -{ - uint32 feature = insn.get_canon_feature(ph); - flow = (feature & CF_STOP) == 0; - - if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, true); - if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, true); - if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, true); - - if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false); - if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false); - if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, false); - - // check for CCR changes - if ( insn.Op1.type == o_reg && insn.Op1.reg == CCR ) - { - op_bin(insn.ea, 1); - - sel_t ccr = get_sreg(insn.ea, CCR); - if ( ccr == BADSEL ) - ccr = 0; - - if ( insn.itype == F2MC_and ) - ccr &= insn.Op2.value; // and ccr,imm8 - else if ( insn.itype == F2MC_or ) - ccr |= insn.Op2.value; // or ccr,imm8 - split_sreg_range(get_item_end(insn.ea), CCR, ccr, SR_auto); - } - - - // check for DTB,ADB,SSB,USB,DPR changes - if ( insn.itype == F2MC_mov && is_bank(insn.Op1) - && insn.Op2.type == o_reg && insn.Op2.reg == A ) // mov dtb|adb|ssb|usb|dpr,a - { - sel_t bank = BADSEL; - insn_t l; - if ( decode_prev_insn(&l, insn.ea) != BADADDR && l.itype == F2MC_mov - && l.Op1.type == o_reg && l.Op1.reg == A ) - { - if ( l.Op2.type == o_imm ) // mov a,imm8 - bank = l.Op2.value; - else if ( is_bank(l.Op2) ) // mov a,dtb|adb|ssb|usb|dpr|pcb - { - bank = get_sreg(l.ea, l.Op2.reg); - if ( bank == BADSEL ) - bank = 0; - } - } - if ( bank != BADSEL ) - split_sreg_range(get_item_end(insn.ea), insn.Op1.reg, bank, SR_auto); - } - - - // determine if the next instruction should be executed - if ( segtype(insn.ea) == SEG_XTRN ) - flow = false; - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - if ( may_trace_sp() ) - { - if ( !flow ) - recalc_spd(insn.ea); // recalculate SP register for the next insn - else - trace_sp(insn); - } - - return 1; -} - -//---------------------------------------------------------------------- -bool idaapi create_func_frame(func_t *pfn) -{ - if ( pfn != NULL ) - { - if ( pfn->frame == BADNODE ) - { - ea_t ea = pfn->start_ea; - if ( ea + 4 < pfn->end_ea ) // minimum 2+1+1 bytes needed - { - insn_t insn; - decode_insn(&insn, ea); - if ( insn.itype == F2MC_link ) - { - size_t localsize = (size_t)insn.Op1.value; - ushort regsize = 2; - decode_insn(&insn, ea + 2); - pfn->flags |= FUNC_FRAME; - return add_frame(pfn, localsize, regsize, 0); - } - } - } - } - return 0; -} - -//---------------------------------------------------------------------- -int idaapi is_sp_based(const insn_t &, const op_t &) -{ - return OP_SP_ADD | OP_FP_BASED; -} diff --git a/idasdk75/module/f2mc/f2mc.hpp b/idasdk75/module/f2mc/f2mc.hpp deleted file mode 100644 index 2c4492c..0000000 --- a/idasdk75/module/f2mc/f2mc.hpp +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _F2MC_HPP -#define _F2MC_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include <segregs.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -enum regnum_t -{ - A, // accumulator - AL, // accumulator - AH, // accumulator - PC, // program counter - SP, // stack pointer - R0, - R1, - R2, - R3, - R4, - R5, - R6, - R7, - RW0, - RW1, - RW2, - RW3, - RW4, - RW5, - RW6, - RW7, - RL0, - RL1, - RL2, - RL3, - - PCB, // program bank register - DTB, // data bank register - ADB, // additional data bank register - SSB, // system stack bank register - USB, // user stack bank register - CCR, // condition code register - DPR, // direct page register - rVcs, rVds, // virtual registers for code and data segments - - SPB, // stack pointer bank register - PS, // processor status - ILM, // interrupt level mask register - RP // register bank pointer -}; - -//------------------------------------------------------------------ -// specific processor records - -#define default_bank segpref -#define prefix_bank auxpref_u8[1] -#define op_bank auxpref_u8[0] -// o_phrase = @reg+(index) (index if PHRASE_INDEX) - #define at specflag1 // number of @ indirections (dtype @ = op.dtype) - #define special_mode specflag2 - #define MODE_INC 1 - #define MODE_INDEX 2 - #define index specval_shorts.high -#define o_reglist o_idpspec0 -// o_disp = @reg+value -#define addr_dtyp specflag3 - #define MODE_BIT 1 - #define byte_bit specflag4 - -//------------------------------------------------------------------ -// processor types - -typedef uchar proctype_t; - -const proctype_t F2MC16L = 0; -const proctype_t F2MC16LX = 1; - -extern ea_t dataseg; -//------------------------------------------------------------------ -#define F2MC_MACRO 0x0001 // use instruction macros -inline ea_t calc_code_mem(const insn_t &insn, ea_t ea) { return to_ea(insn.cs, ea); } -inline ea_t calc_data_mem(ea_t ea) { return (get_sreg(ea, DTB) << 16) | ea; } - -int get_signed(int byte,int mask); - -ea_t map_port(ea_t from); -int calc_outf(const op_t &x); -//------------------------------------------------------------------ -void idaapi f2mc_segend(outctx_t &ctx, segment_t *seg); - -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_sp_based(const insn_t &insn, const op_t &x); - -//------------------------------------------------------------------ -struct f2mc_iohandler_t : public iohandler_t -{ - struct f2mc_t ± - f2mc_iohandler_t(f2mc_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual const char *aux_segm() const override { return "FSR"; } - virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override; - virtual const char *iocallback(const ioports_t &iop, const char *line) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct f2mc_t); - -struct f2mc_t : public procmod_t -{ - netnode helper; - f2mc_iohandler_t ioh = f2mc_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - const char *cfgname = nullptr; - proctype_t ptype = F2MC16LX; // contains processor type - ushort idpflags = F2MC_MACRO; - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void load_symbols(int _respect_info); - const char *find_sym(ea_t address); - const char *find_bit(ea_t address, int bit); - bool exist_bits(ea_t ea, int bitl, int bith); - void f2mc_set_device_name(const char *dev, int _respect_info); - void choose_and_set_device(int flags); - inline void choose_device(); - const char *set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - void adjust_ea_bit(ea_t &ea, int &bit); - void handle_operand(const insn_t &insn, const op_t &x, bool use); - int emu(const insn_t &insn); - - void ana_F2MC16LX(insn_t &insn); - int ana(insn_t *_insn); - - void f2mc_header(outctx_t &ctx); - void f2mc_assumes(outctx_t &ctx); - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void f2mc_segstart(outctx_t &ctx, segment_t *Srange) const; - void f2mc_footer(outctx_t &ctx) const; -}; - -#endif // _F2MC_HPP diff --git a/idasdk75/module/f2mc/ins.hpp b/idasdk75/module/f2mc/ins.hpp deleted file mode 100644 index 6d17e14..0000000 --- a/idasdk75/module/f2mc/ins.hpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ - -F2MC_null = 0, // Unknown Operation - -// TRANSFER INSTRUCTIONS - -F2MC_mov, // Move byte data from source to destination -F2MC_movn, // Move immediate nibble data to A -F2MC_movx, // Move byte data with sign extension from source to A -F2MC_xch, // Exchange byte data of source to destination -F2MC_movw, // Move word data from source to destination -F2MC_xchw, // Exchange word data of source to destination -F2MC_movl, // Move long word data from source to destination - -// NUMERIC DATA OPERATIONS INSTRUCTIONS - -F2MC_add, // Add byte data of destination and source to destination -F2MC_addc1, // Add byte data of AL and AH with Carry to AL -F2MC_addc2, // Add byte data of A and effective address with Carry to A -F2MC_adddc, // Add decimal data of AL and AH with Carry to AL -F2MC_sub, // Subtract byte data of source from festination to destination -F2MC_subc1, // Subtract byte data of AL from AH with Carry to AL -F2MC_subc2, // Subtract byte data of effective address from A with Carry to A -F2MC_subdc, // Subtract decimal data of AL from AH with Carry to AL -F2MC_addw1, // Add word data of AH and AL to AL -F2MC_addw2, // Add word data of destination and source to destination -F2MC_addcw, // Add word data of A and effective address from A with Carry to A -F2MC_subw1, // Subtract word data of AL from AH to AL -F2MC_subw2, // Subtract word data of source from festination to destination -F2MC_subcw, // Subtract word data of A and effective address from A with carry to A -F2MC_addl, // Add long word data of destination and source to destination -F2MC_subl, // Subtract long word data of source from festination to destination -F2MC_inc, // Increment byte data -F2MC_dec, // Decrement byte data -F2MC_incw, // Increment word data -F2MC_decw, // Decrement word data -F2MC_incl, // Increment long word data -F2MC_decl, // Decrement long word data -F2MC_cmp1, // Compare byte data of AH and AL -F2MC_cmp2, // Compare byte data of destination and source -F2MC_cmpw1, // Compare word data of AH and AL -F2MC_cmpw2, // Compare word data of destination and source -F2MC_cmpl, // Compare long word data of destination and source -F2MC_divu1, // Divide unsigned AH by AL -F2MC_divu2, // Divide unsigned word data by unsigned byte data -F2MC_divuw, // Divide unsigned long word data by unsigned word data -F2MC_mulu1, // Multiply unsigned byte AH by AL -F2MC_mulu2, // Multiply unsigned byte data -F2MC_muluw1, // Multiply unsigned word AH by AL -F2MC_muluw2, // Multiply unsigned word data -F2MC_div1, // Divide AH by AL -F2MC_div2, // Divide word data by byte data -F2MC_divw, // Divide long word data by word data -F2MC_mul1, // Multiply byte AH by AL -F2MC_mul2, // Multiply byte data -F2MC_mulw1, // Multiply word AH by AL -F2MC_mulw2, // Multiply word data - -// LOGICAL DATA OPERATION INSTRUCTIONS - -F2MC_and, // And byte data of destination and source to destination -F2MC_or, // Or byte data of destination and source to destination -F2MC_xor, // Exclusive or byte data of destination and source to destination -F2MC_not, // Not byte data of destination -F2MC_andw1, // And word data of AH and AL to AL -F2MC_andw2, // And word data of destination and source to destination -F2MC_orw1, // Or word data of AH and AL to AL -F2MC_orw2, // Or word data of destination and source to destination -F2MC_xorw1, // Exclusive or word data of AH and AL to AL -F2MC_xorw2, // Exclusive or word data of destination and source to destination -F2MC_notw, // Not word data of destination -F2MC_andl, // And long word data of destination and source to destination -F2MC_orl, // Or long word data of destination and source to destination -F2MC_xorl, // Exclusive or long word data of destination and source to destination -F2MC_neg, // Negate byte data of destination -F2MC_negw, // Negate word data of destination -F2MC_nrml, // Normalize long word - -// SHIFT INSTRUCTIONS - -F2MC_rorc, // Rotate byte data of A with Carry to right -F2MC_rolc, // Rotate byte data of A with Carry to left -F2MC_asr, // Arithmetic shift byte data of A to right -F2MC_lsr, // Logical shift byte data of A to right -F2MC_lsl, // Logical shift byte data of A to left -F2MC_asrw1, // Arithmetic shift word data of A to right -F2MC_asrw2, // Arithmetic shift word data of A to right -F2MC_lsrw1, // Logical shift word data of A to right -F2MC_lsrw2, // Logical shift word data of A to right -F2MC_lslw1, // Logical shift word data of A to left -F2MC_lslw2, // Logical shift word data of A to left -F2MC_asrl, // Arithmetic shift long word data of A to right -F2MC_lsrl, // Logical shift long word data of A to right -F2MC_lsll, // Logical shift long word data of A to left - -// BRANCH INSTRUCTIONS - -F2MC_bz, // Branch if Zero -F2MC_bnz, // Branch if Not Zero -F2MC_bc, // Branch if Carry -F2MC_bnc, // Branch if Not Carry -F2MC_bn, // Branch if Negative -F2MC_bp, // Branch if Not Negative -F2MC_bv, // Branch if Overflow -F2MC_bnv, // Branch if Not Overflow -F2MC_bt, // Branch if Sticky -F2MC_bnt, // Branch if Not Sticky -F2MC_blt, // Branch if Overflow or Negative -F2MC_bge, // Branch if Not (Overflow or Negative) -F2MC_ble, // Branch if (Overflow xor Negative) or Zero -F2MC_bgt, // Branch if Not ((Overflow xor Negative) or Zero) -F2MC_bls, // Branch if Carry or Zero -F2MC_bhi, // Branch if Not (Carry or Zero) -F2MC_bra, // Branch unconditionally -F2MC_jmp, // Jump destination address -F2MC_jmpp, // Jump destination physical address -F2MC_call, // Call subroutine -F2MC_callv, // Call vectored subroutine -F2MC_callp, // Call physical address -F2MC_cbne, // Compare byte data and branch if not Equal -F2MC_cwbne, // Compare word data and branch if not Equal -F2MC_dbnz, // Decrement byte data and branch if not Zero -F2MC_dwbnz, // Decrement word data and branch if not Zero -F2MC_int, // Software interrupt -F2MC_intp, // Software interrupt -F2MC_int9, // Software interrupt -F2MC_reti, // Return from interrupt -F2MC_link, // Link and create new stack frame -F2MC_unlink, // Unlink and create new stack frame -F2MC_ret, // Return from subroutine -F2MC_retp, // Return from physical address - -// OTHER INSTRUCTIONS - -F2MC_pushw, // Push to stack memory -F2MC_popw, // Pop from stack memory -F2MC_jctx, // Jump context -// F2MC_and, -// F2MC_or, -// F2MC_mov, -F2MC_movea, // Move effective address to destination -F2MC_addsp, // Add word data of SP and immediate data to SP -// F2MC_mov, -F2MC_nop, // No operation -F2MC_adb, // ADB register -F2MC_dtb, // DTB register -F2MC_pcb, // PCB register -F2MC_spb, // SPB register -F2MC_ncc, // Flag change inhibit -F2MC_cmr, // Common register bank -F2MC_movb, // Move bit data -F2MC_setb, // Set bit -F2MC_clrb, // Clear bit -F2MC_bbc, // Branch if bit condition satisfied -F2MC_bbs, // Branch if bit condition satisfied -F2MC_sbbs, // Set bit and branch if bit set -F2MC_wbts, // Wait until bit condition satisfied -F2MC_wbtc, // Wait until bit condition satisfied -F2MC_swap, // Swap byte data of A -F2MC_swapw, // Swap word data of A -F2MC_ext, // Sign extend from byte data to word data -F2MC_extw, // Sign extend from word data to long word data -F2MC_zext, // Zero extendfrom byte data to word data -F2MC_zextw, // Zero extendfrom word data to long word data -F2MC_movsi, // Move string byte with addresses incremented -F2MC_movsd, // Move string byte with addresses decremented -F2MC_sceqi, // Scan string byte until Equal with address incremented -F2MC_sceqd, // Scan string byte until Equal with address decremented -F2MC_filsi, // Fill string byte -F2MC_movswi, // Move string word with address incremented -F2MC_movswd, // Move string word with address decremented -F2MC_scweqi, // Scan string word until Equal with address incremented -F2MC_scweqd, // Scan string word until Equal with address decremented -F2MC_filswi, // Fill string word - -// MACROS - -F2MC_bz16, // Branch if Zero -F2MC_bnz16, // Branch if Not Zero -F2MC_bc16, // Branch if Carry -F2MC_bnc16, // Branch if Not Carry -F2MC_bn16, // Branch if Negative -F2MC_bp16, // Branch if Not Negative -F2MC_bv16, // Branch if Overflow -F2MC_bnv16, // Branch if Not Overflow -F2MC_bt16, // Branch if Sticky -F2MC_bnt16, // Branch if Not Sticky -F2MC_blt16, // Branch if Overflow or Negative -F2MC_bge16, // Branch if Not (Overflow or Negative) -F2MC_ble16, // Branch if (Overflow xor Negative) or Zero -F2MC_bgt16, // Branch if Not ((Overflow xor Negative) or Zero) -F2MC_bls16, // Branch if Carry or Zero -F2MC_bhi16, // Branch if Not (Carry or Zero) - -F2MC_cbne16, // Compare byte data and branch if not Equal -F2MC_cwbne16, // Compare word data and branch if not Equal - -F2MC_dbnz16, // Decrement byte data and branch if not Zero -F2MC_dwbnz16, // Decrement word data and branch if not Zero - -F2MC_bbc16, // Branch if bit condition satisfied -F2MC_bbs16, // Branch if bit condition satisfied -F2MC_sbbs16, // Set bit and branch if bit set - -F2MC_last, - -}; - -#endif diff --git a/idasdk75/module/f2mc/makefile b/idasdk75/module/f2mc/makefile deleted file mode 100644 index 270857e..0000000 --- a/idasdk75/module/f2mc/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=f2mc -CONFIGS=f2mc16l.cfg f2mc16lx.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp f2mc.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp f2mc.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp f2mc.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp f2mc.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp f2mc.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/f2mc/out.cpp b/idasdk75/module/f2mc/out.cpp deleted file mode 100644 index 0b05e81..0000000 --- a/idasdk75/module/f2mc/out.cpp +++ /dev/null @@ -1,358 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "f2mc.hpp" -#include <frame.hpp> -#include <segregs.hpp> - -//---------------------------------------------------------------------- -class out_f2mc_t : public outctx_t -{ - out_f2mc_t(void) = delete; // not used -public: - void out_address(ea_t ea, const op_t &x); - void out_reglist(ushort reglist); - - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_f2mc_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_f2mc_t) - -//---------------------------------------------------------------------- -void out_f2mc_t::out_address(ea_t ea, const op_t &x) -{ - if ( !out_name_expr(x, ea, x.addr & 0xffff) ) - { - out_tagon(COLOR_ERROR); - out_btoa(x.addr, 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } -} - -//---------------------------------------------------------------------- -void out_f2mc_t::out_reglist(ushort reglist) -{ - out_symbol('('); - bool first = true; - int i = 0; - while ( i < 8 ) - { - int size = 1; - if ( (reglist>>i) & 1 ) - { - while ( (i + size < 8) && ((reglist>>(i+size)) & 1 ) ) - size++; - if ( first ) - first = false; - else - out_symbol(','); - out_register(ph.reg_names[RW0+i]); - if ( size > 1 ) - { - out_symbol('-'); - out_register(ph.reg_names[RW0+i+size-1]); - } - } - i+=size; - } - out_symbol(')'); -} - -//---------------------------------------------------------------------- -bool f2mc_t::exist_bits(ea_t ea, int bitl, int bith) -{ - for ( int i = bitl; i <= bith; i++ ) - { - const char *name = find_bit(ea, i); - if ( name != NULL && name[0] != '\0' ) - return true; - } - return false; -} - -// adjust to respect 16 bits an 32 bits definitions -void f2mc_t::adjust_ea_bit(ea_t &ea, int &bit) -{ - const char *name = find_sym(ea); - if ( name != NULL && name[0] != '\0' ) - return; - name = find_sym(ea-1); - if ( name != NULL && name[0] != '\0' && exist_bits(ea-1, 8, 15) ) - { - ea--; - bit+=8; - return; - } - name = find_sym(ea-2); - if ( name != NULL && name[0] != '\0' && exist_bits(ea-2, 16, 31) ) - { - ea-=2; - bit+=16; - return; - } - name = find_sym(ea-3); - if ( name != NULL && name[0] != '\0' && exist_bits(ea-3, 16, 31) ) - { - ea-=3; - bit+=24; - return; - } -} - -//---------------------------------------------------------------------- -int calc_outf(const op_t &x) -{ - if ( x.type == o_imm ) - return OOFS_IFSIGN|OOFW_IMM; - - QASSERT(10103, x.type == o_displ); - if ( x.addr_dtyp == dt_byte ) - return OOF_ADDR|OOFS_NEEDSIGN|OOF_SIGNED|OOFW_8; - if ( x.addr_dtyp == dt_word ) - return OOF_ADDR|OOFS_NEEDSIGN|OOF_SIGNED|OOFW_16; - INTERR(10104); -} - -//---------------------------------------------------------------------- -bool out_f2mc_t::out_operand(const op_t &x) -{ - f2mc_t &pm = *static_cast<f2mc_t *>(procmod); - ea_t ea; - - if ( insn.prefix_bank && (insn.op_bank == x.n) - && (insn.prefix_bank != insn.default_bank) ) - { - out_register(ph.reg_names[insn.prefix_bank]); - out_symbol(':'); - } - - for ( int i = 0; i < x.at; i++ ) - out_symbol('@'); - - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - out_register(ph.reg_names[x.reg]); - break; - - case o_near: - case o_far: - { - ea_t addr = x.addr; - if ( x.type == o_near ) - addr = calc_code_mem(insn, addr); - out_address(addr, x); - } - break; - - case o_imm: - out_symbol('#'); - out_value(x, calc_outf(x)); - break; - - case o_mem: - { - ea = calc_data_mem(x.addr); - if ( x.addr_dtyp != 'i' ) // data address - { - if ( x.addr_dtyp ) - { - out_symbol(x.addr_dtyp); - out_symbol(':'); - } - out_address(ea, x); - if ( x.special_mode == MODE_BIT ) - { - out_symbol(':'); - out_symbol('0' + x.byte_bit); - } - } - else // IO address - { - int bit = x.byte_bit; - out_symbol('i'); out_symbol(':'); - if ( x.special_mode == MODE_BIT ) - pm.adjust_ea_bit(ea, bit); - const char *name = pm.find_sym(ea); - if ( name != NULL && name[0] != '\0' ) - { - out_addr_tag(ea); - out_line(name, COLOR_IMPNAME); - } - else - { - out_address(ea, x); - } - if ( x.special_mode == MODE_BIT ) - { - name = pm.find_bit(ea,bit); - if ( name != NULL && name[0] != '\0' ) - { - out_symbol('_'); - out_line(name, COLOR_IMPNAME); - } - else - { - out_symbol(':'); - out_tagon(COLOR_SYMBOL); - out_btoa(bit, 10); - out_tagoff(COLOR_SYMBOL); - } - } - } - } - break; - - case o_phrase: - out_register(ph.reg_names[x.reg]); - switch ( x.special_mode ) - { - case MODE_INC: - out_symbol('+'); - break; - case MODE_INDEX: - out_symbol('+'); - out_register(ph.reg_names[x.index]); - break; - } - break; - - case o_displ: - out_register(ph.reg_names[x.reg]); - out_value(x, calc_outf(x)); - break; - - case o_reglist: - out_reglist(x.reg); - break; - - default: - error("interr: out"); - } - return 1; -} - -//---------------------------------------------------------------------- -void out_f2mc_t::out_insn(void) -{ - out_mnemonic(); - out_one_operand(0); - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - if ( insn.Op3.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(2); - } - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void f2mc_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) -{ - if ( reg == ph.reg_data_sreg ) - return; - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), value); - ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); -} - -//-------------------------------------------------------------------------- -// function to produce assume directives -//lint -esym(1764, ctx) could be made const -void f2mc_t::f2mc_assumes(outctx_t &ctx) -{ - ea_t ea = ctx.insn_ea; - segment_t *seg = getseg(ea); - if ( seg == NULL || (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 ) - return; - - for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) - { - if ( i == ph.reg_code_sreg ) - continue; - sreg_range_t sra; - if ( !get_sreg_range(&sra, ea, i) ) - continue; - sel_t now = get_sreg(ea, i); - bool seg_started = (ea == seg->start_ea); - if ( seg_started || sra.start_ea == ea ) - { - sreg_range_t prev_sra; - bool prev_exists = get_sreg_range(&prev_sra, ea - 1, i); - if ( seg_started || (prev_exists && get_sreg(prev_sra.start_ea, i) != now) ) - print_segment_register(ctx, i, now); - } - } -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Srange) could be made const -void f2mc_t::f2mc_segstart(outctx_t &ctx, segment_t *Srange) const -{ - if ( is_spec_segm(Srange->type) ) - return; - - qstring sname; - qstring sclas; - get_visible_segm_name(&sname, Srange); - get_segm_class(&sclas, Srange); - - ctx.gen_printf(DEFAULT_INDENT, - COLSTR(".section %s, %s", SCOLOR_ASMDIR), - sname.c_str(), - sclas == "CODE" ? "code" - : sclas == "BSS" ? "data" - : "const"); - if ( Srange->orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), Srange->orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -void idaapi f2mc_segend(outctx_t &, segment_t *) {} - -//-------------------------------------------------------------------------- -void f2mc_t::f2mc_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_PROC_AND_ASM, ioh.device.c_str(), ioh.deviceparams.c_str()); - ctx.gen_printf(0, ""); - ctx.gen_printf(0, COLSTR("#include <_ffmc16_a.asm>", SCOLOR_ASMDIR)); - ctx.gen_header_extra(); - ctx.gen_empty_line(); -} - -//-------------------------------------------------------------------------- -void f2mc_t::f2mc_footer(outctx_t &ctx) const -{ - qstring nbuf = get_colored_name(inf_get_start_ea()); - const char *name = nbuf.c_str(); - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), - ash.end, - ash.cmnt, - name); -} diff --git a/idasdk75/module/f2mc/reg.cpp b/idasdk75/module/f2mc/reg.cpp deleted file mode 100644 index 98e0a2a..0000000 --- a/idasdk75/module/f2mc/reg.cpp +++ /dev/null @@ -1,563 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include <ctype.h> -#include "f2mc.hpp" -#include <diskio.hpp> -#include <segregs.hpp> -static int data_id; - -static const proctype_t ptypes[] = -{ - F2MC16L, - F2MC16LX -}; - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "A", // accumulator - "AL", // accumulator - "AH", // accumulator - "PC", // program counter - "SP", // stack pointer - "R0", - "R1", - "R2", - "R3", - "R4", - "R5", - "R6", - "R7", - "RW0", - "RW1", - "RW2", - "RW3", - "RW4", - "RW5", - "RW6", - "RW7", - "RL0", - "RL1", - "RL2", - "RL3", - - "PCB", // program bank register - "DTB", // data bank register - "ADB", // additional data bank register - "SSB", // system stack bank register - "USB", // user stack bank register - "CCR", // condition code register - "DPR", // direct page register - "cs","ds", // virtual registers for code and data segments - - "SPB", // stack pointer bank register - "PS", // processor status - "ILM", // interrupt level mask register - "RP" // register bank pointer -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0x66 }; // retp -static const uchar retcode_1[] = { 0x67 }; // ret -static const uchar retcode_2[] = { 0x6B }; // reti - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Fujitsu FASM -//----------------------------------------------------------------------- -static const asm_t fasm = -{ - AS_N2CHR|AS_NCMAS|ASH_HEXF3|ASD_DECF0|ASO_OCTF1|ASB_BINF3|AS_ONEDUP, - 0, - "Fujitsu FASM", - 0, - NULL, // header lines - ".org", // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".data.b", // byte directive - ".data.w", // word directive - ".data.l", // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".res.b %s", // uninited arrays - ".equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - NULL, // "public" name keyword - NULL, // "weak" name keyword - NULL, // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &fasm, NULL }; - -//-------------------------------------------------------------------------- -bool f2mc_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass) -{ - const bool split = end > start && (end - start) > 0x10000; - for ( ea_t chunk_ea = start; chunk_ea < end; chunk_ea += 0x10000 ) - { - ea_t segbase = (chunk_ea >> 16) << 12; - sel_t sel = allocate_selector(segbase); - qstring nm(name); - if ( split ) - nm.cat_sprnt("_%02X", uint32((chunk_ea >> 16) & 0xFF)); - ea_t chunk_end = chunk_ea + 0x10000; - if ( chunk_end > end ) - chunk_end = end; - add_segm(sel, chunk_ea, chunk_end, nm.c_str(), aclass); - } - return true; -} - -//------------------------------------------------------------------------- -const char *f2mc_iohandler_t::iocallback(const ioports_t &iop, const char *line) -{ - const char *ret = NULL; - bool handled = false; - int len; - ea_t ea1; - char word[MAXSTR]; - word[MAXSTR-1] = '\0'; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "interrupt %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) //lint !e706 nominally inconsistent format - { - if ( (respect_info & IORESP_INT) != 0 ) - { - segment_t *s = getseg(ea1); - ea_t proc; - if ( s != NULL ) - { - create_dword(ea1, 4); - proc = get_dword(ea1); - if ( proc != 0xFFFFFFFF ) - { - op_plain_offset(ea1, 0, 0); - add_entry(proc, proc, word, true); - - const char *ptr = &line[len]; - ptr = skip_spaces(ptr); - if ( ptr[0] != '\0' ) - set_cmt(ea1, ptr, true); - - handled = true; - } - } - } - } - if ( !handled ) - ret = standard_callback(iop, line); - return ret; -} - -//------------------------------------------------------------------------- -void f2mc_t::load_symbols(int _respect_info) -{ - if ( cfgname != NULL ) - { - ioh.deviceparams.qclear(); - ioh.respect_info = _respect_info; - if ( !inf_like_binary() ) - ioh.respect_info &= ~2; - ioh.ports.clear(); - iohandler_t::ioports_loader_t ldr(&ioh); - read_ioports2(&ioh.ports, &ioh.device, cfgname, &ldr); - if ( ioh.respect_info ) - { - for ( int i=0; i < ioh.ports.size(); i++ ) - { - ea_t ea = ioh.ports[i].address; - create_byte(ea, 1); - const char *name = ioh.ports[i].name.c_str(); - if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) - set_cmt(ea, name, 0); - else - set_cmt(ea, ioh.ports[i].cmt.c_str(), true); - } - } - } -} - -const char *f2mc_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port ? port->name.c_str() : NULL; -} - -const char *f2mc_t::find_bit(ea_t address, int bit) -{ - const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit); - return b ? b->name.c_str() : NULL; -} - -//-------------------------------------------------------------------------- -void f2mc_t::f2mc_set_device_name(const char *dev, int _respect_info) -{ - if ( dev != NULL ) - { - ioh.device = dev; - helper.supset(0, dev); - } - load_symbols(_respect_info); -} - -//------------------------------------------------------------------------- -void f2mc_t::choose_and_set_device(int flags) -{ - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) - f2mc_set_device_name(ioh.device.c_str(), flags); -} - -//-------------------------------------------------------------------------- -inline void f2mc_t::choose_device() -{ - choose_and_set_device(IORESP_PORT|IORESP_INT); -} - -//-------------------------------------------------------------------------- -static int idaapi choose_device_cb(int, form_actions_t &fa) -{ - f2mc_t &pm = *(f2mc_t *)fa.get_ud(); - pm.choose_device(); - return 0; -} - -//-------------------------------------------------------------------------- -const char *f2mc_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - if ( keyword == NULL ) - { - static const char form[] = - "HELP\n" - "F2MC specific options\n" - "\n" - " Use macro instructions\n" - "\n" - " If this option is on, IDA will try to combine several instructions\n" - " into a macro instruction\n" - " For example,\n" - "\n" - " sbbs data:7, $1\n" - " bra $2\n" - " $1:\n" - " jmp LABEL\n" - " $2:\n" - "\n" - " will be replaced by\n" - "\n" - " sbbs16 data:7, LABEL\n" - "\n" - "ENDHELP\n" - "F2MC specific options\n" - "%*\n" - " <Use ~m~acro instructions:C>>\n" - "\n" - " <~C~hoose device name:B:0::>\n" - "\n" - "\n"; - CASSERT(sizeof(idpflags) == sizeof(ushort)); - ask_form(form, this, &idpflags, choose_device_cb); - return IDPOPT_OK; - } - else - { - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - if ( streq(keyword, "F2MC_MACRO") ) - { - setflag(idpflags, F2MC_MACRO, *(int*)value != 0); - if ( idb_loaded ) - helper.altset(-1, idpflags); - return IDPOPT_OK; - } - return IDPOPT_BADKEY; - } -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(-1, pm.idpflags); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(f2mc_t)); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi f2mc_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ f2mc"); - if ( helper.supstr(&ioh.device, 0) > 0 ) - f2mc_set_device_name(ioh.device.c_str(), IORESP_NONE); - inf_set_wide_high_byte_first(true); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: // new file loaded - set_segm_name(get_first_seg(), "CODE"); - choose_and_set_device(IORESP_ALL); - for ( int i = DTB; i <= rVds; i++ ) - { - for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) - set_default_sreg_value(s, i, 0); - } - break; - - case processor_t::ev_ending_undo: - // restore ptype - ptype = ptypes[ph.get_proc_index()]; - //fall through - case processor_t::ev_oldfile: // old file loaded - idpflags = (ushort)helper.altval(-1); - break; - - case processor_t::ev_newprc: // new processor type - { - ptype = ptypes[va_arg(va, int)]; - // bool keep_cfg = va_argi(va, bool); - switch ( ptype ) - { - case F2MC16L: - cfgname = "f2mc16l.cfg"; - break; - case F2MC16LX: - cfgname = "f2mc16lx.cfg"; - break; - default: - error("interr: setprc"); - } - ioh.device.qclear(); - if ( get_first_seg() != NULL ) - choose_device(); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - f2mc_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - f2mc_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - f2mc_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - f2mc_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - f2mc_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -#define FAMILY "Fujitsu F2MC:" - -static const char *const shnames[] = -{ "F2MC16L", - "F2MC16LX", - NULL -}; -static const char *const lnames[] = -{ FAMILY"Fujitsu F2MC 16L", - "Fujitsu F2MC 16LX", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_F2MC, // id - // flag - PRN_HEX - | PR_SEGS - | PR_SGROTHER, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - DTB, // first. We don't start at PCB, because - // PCB == cs, and the way to get addresses - // right is not to modify PCB, but rather - // create the segmentation correctly. - rVds, // last - 1, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - F2MC_null, - F2MC_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 0, 0, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - F2MC_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/fr/fr.hpp b/idasdk75/module/fr/fr.hpp deleted file mode 100644 index 9cdcc60..0000000 --- a/idasdk75/module/fr/fr.hpp +++ /dev/null @@ -1,141 +0,0 @@ - -#ifndef __FR_HPP -#define __FR_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include <frame.hpp> -#include "../iohandler.hpp" - -// uncomment this for the final release -//#define __DEBUG__ - -// FR registers -enum fr_registers -{ - // general purpose registers : - - rR0, - rR1, - rR2, - rR3, - rR4, - rR5, - rR6, - rR7, - rR8, - rR9, - rR10, - rR11, - rR12, - rR13, - rR14, - rR15, - - // coprocessor registers : - - rCR0, - rCR1, - rCR2, - rCR3, - rCR4, - rCR5, - rCR6, - rCR7, - rCR8, - rCR9, - rCR10, - rCR11, - rCR12, - rCR13, - rCR14, - rCR15, - - // dedicated registers : - - rPC, // program counter - rPS, // program status - rTBR, // table base register - rRP, // return pointer - rSSP, // system stack pointer - rUSP, // user stack pointer - rMDL, // multiplication/division register (LOW) - rMDH, // multiplication/division register (HIGH) - - // system use dedicated registers - rReserved6, - rReserved7, - rReserved8, - rReserved9, - rReserved10, - rReserved11, - rReserved12, - rReserved13, - rReserved14, - rReserved15, - - // these 2 registers are required by the IDA kernel : - - rVcs, - rVds -}; - -enum fr_phrases -{ - fIGR, // indirect general register - fIRA, // indirect relative address - fIGRP, // indirect general register with post-increment - fIGRM, // indirect general register with pre-decrement - fR13RI, // indirect displacement between R13 and a general register -}; - -// shortcut for a new operand type -#define o_reglist o_idpspec0 - -// flags for insn.auxpref -#define INSN_DELAY_SHOT 0x00000001 // postfix insn mnem by ":D" - -// flags for opt.specflag1 -#define OP_DISPL_IMM_R14 0x00000001 // @(R14, #i) -#define OP_DISPL_IMM_R15 0x00000002 // @(R15, #i) -#define OP_ADDR_R 0x00000010 // read-access to memory -#define OP_ADDR_W 0x00000012 // write-access to memory - -inline bool op_displ_imm_r14(const op_t &op) { return (op.specflag1 & OP_DISPL_IMM_R14) != 0; } -inline bool op_displ_imm_r15(const op_t &op) { return (op.specflag1 & OP_DISPL_IMM_R15) != 0; } - -// exporting our routines -int idaapi ana(insn_t *_insn); -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_sp_based(const insn_t &, const op_t &x); -int idaapi is_align_insn(ea_t ea); - -DECLARE_PROC_LISTENER(idb_listener_t, struct fr_t); - -struct fr_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - bool print_comma = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - int choose_device(); - const ioport_t *find_sym(ea_t address); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - void fr_header(outctx_t &ctx); - - int emu(const insn_t &insn) const; - bool is_stop(const insn_t &insn) const; - - void fr_footer(outctx_t &ctx) const; - void fr_segstart(outctx_t &ctx, segment_t *Sarea) const; -}; - -#endif /* __FR_HPP */ diff --git a/idasdk75/module/fr/makefile b/idasdk75/module/fr/makefile deleted file mode 100644 index d568642..0000000 --- a/idasdk75/module/fr/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=fr -CONFIGS=fr.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp fr.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp emu.cpp fr.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp fr.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp fr.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp fr.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/fr/out.cpp b/idasdk75/module/fr/out.cpp deleted file mode 100644 index e8ebf9f..0000000 --- a/idasdk75/module/fr/out.cpp +++ /dev/null @@ -1,298 +0,0 @@ - -#include "fr.hpp" - -//---------------------------------------------------------------------- -class out_fr_t : public outctx_t -{ - out_fr_t(void) = delete; // not used -public: - void out_reg(ushort reg) { out_register(ph.reg_names[reg]); } - void out_reg(const op_t &op) { out_reg(op.reg); } - void out_imm(const op_t &op, bool no_sharp = false); - void out_addr(const op_t &op); - void out_reglist(const op_t &op); - - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); -private: - void out_reg_if_bit(ushort reg, uval_t value, int bit); -}; -CASSERT(sizeof(out_fr_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_fr_t) - -//---------------------------------------------------------------------- -// Output an operand as an immediate value -void out_fr_t::out_imm(const op_t &op, bool no_sharp) -{ - if ( !no_sharp ) - out_symbol('#'); - out_value(op, OOFW_IMM); -} - -//---------------------------------------------------------------------- -// Output an operand as an address -void out_fr_t::out_addr(const op_t &op) -{ - if ( !out_name_expr(op, to_ea(insn.cs, op.addr), op.addr) ) - out_value(op, OOF_ADDR | OOFS_NOSIGN); -} - -//---------------------------------------------------------------------- -void out_fr_t::out_reg_if_bit(ushort reg, uval_t value, int bit) -{ - fr_t &pm = *static_cast<fr_t *>(procmod); - if ( (value & bit) == bit ) - { - if ( pm.print_comma ) - { - out_symbol(','); - out_char(' '); - } - out_reg(reg); - pm.print_comma = true; - } -} - -void out_fr_t::out_reglist(const op_t &op) -{ - static const uint16 regs_ldm0[] = { rR7, rR6, rR5, rR4, rR3, rR2, rR1, rR0 }; - static const uint16 regs_stm0[] = { rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7 }; - static const uint16 regs_ldm1[] = { rR15, rR14, rR13, rR12, rR11, rR10, rR9, rR8 }; - static const uint16 regs_stm1[] = { rR8, rR9, rR10, rR11, rR12, rR13, rR14, rR15 }; - fr_t &pm = *static_cast<fr_t *>(procmod); - const uint16 *regs; - bool left; - - switch ( insn.itype ) - { - case fr_ldm0: regs = regs_ldm0; left = false; break; - case fr_stm0: regs = regs_stm0; left = true; break; - case fr_ldm1: regs = regs_ldm1; left = false; break; - case fr_stm1: regs = regs_stm1; left = true; break; - default: - INTERR(10018); - } - - pm.print_comma = false; - - out_symbol('('); - if ( left ) //-V614 uninitialized variable 'left' - { - for ( int i = 0, bit = 128; bit != 0; bit >>= 1, i++ ) - out_reg_if_bit(regs[i], op.value, bit); - } - else - { - for ( int i = 7, bit = 1; bit <= 128; bit <<= 1, i-- ) - out_reg_if_bit(regs[i], op.value, bit); - } - out_symbol(')'); -} - -//---------------------------------------------------------------------- -// Generate disassembly header -void fr_t::fr_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); -} - -//---------------------------------------------------------------------- -// Generate disassembly footer -void fr_t::fr_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - ctx.out_char(' '); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} - -//---------------------------------------------------------------------- -// Generate a segment header -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Sarea) could be made const -void fr_t::fr_segstart(outctx_t &ctx, segment_t *Sarea) const -{ - qstring sname; - if ( get_visible_segm_name(&sname, Sarea) <= 0 ) - return; - - const char *segname = sname.c_str(); - if ( *segname == '_' ) - segname++; - - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".section .%s", SCOLOR_ASMDIR), segname); - - ea_t orgbase = ctx.insn_ea - get_segm_para(Sarea); - - if ( orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//---------------------------------------------------------------------- -// Output an operand. -bool out_fr_t::out_operand(const op_t & op) -{ - fr_t &pm = *static_cast<fr_t *>(procmod); - switch ( op.type ) - { - case o_near: - case o_mem: - out_addr(op); - break; - - // immediate value - case o_imm: - { - const ioport_t *port = pm.find_sym(op.value); - - // this immediate is represented in the .cfg file - // output the port name instead of the numeric value - if ( port != NULL ) - out_line(port->name.c_str(), COLOR_IMPNAME); - else // otherwise, simply print the value - out_imm(op); - } - break; - - // register - case o_reg: - out_reg(op); - break; - - // phrase - case o_phrase: - out_symbol('@'); - switch ( op.specflag2 ) - { - case fIGR: // indirect general register - out_reg(op); - break; - - case fIRA: // indirect relative address - out_value(op, OOF_ADDR | OOFS_NOSIGN); - break; - - case fIGRP: // indirect general register with post-increment - out_reg(op); - out_symbol('+'); - break; - - case fIGRM: // indirect general register with pre-decrement - out_symbol('-'); - out_reg(op); - break; - - case fR13RI: // indirect displacement between R13 and a general register - out_symbol('('); - out_reg(rR13); - out_symbol(','); - out_char(' '); - out_reg(op); - out_symbol(')'); - break; - - default: - INTERR(10019); - } - break; - - // displacement - case o_displ: - out_symbol('@'); - out_symbol('('); - - // @(R14, #i) - if ( op_displ_imm_r14(op) ) - { - out_reg(rR14); - out_symbol(','); - out_char(' '); - out_imm(op, true); - } - // @(R15, #i) - else if ( op_displ_imm_r15(op) ) - { - out_reg(rR15); - out_symbol(','); - out_char(' '); - out_imm(op, true); - } - else - INTERR(10020); - - out_symbol(')'); - break; - - // reglist - case o_reglist: - out_reglist(op); - break; - - // void operand - case o_void: - break; - - default: - INTERR(10021); - } - return 1; -} - - -//---------------------------------------------------------------------- -void out_fr_t::out_proc_mnem(void) -{ - char postfix[5]; - postfix[0] = '\0'; - - if ( insn.auxpref & INSN_DELAY_SHOT ) - qstrncpy(postfix, ":D", sizeof(postfix)); - out_mnem(8, postfix); -} - -//---------------------------------------------------------------------- -// Output an instruction -void out_fr_t::out_insn(void) -{ - - // - // print insn mnemonic - // - out_mnemonic(); - - for ( int i=0; i < 4; i++ ) - { - if ( insn.ops[i].type != o_void ) - { - if ( i != 0 ) - { - out_symbol(','); - out_char(' '); - } - out_one_operand(i); - } - } - - // output a character representation of the immediate values - // embedded in the instruction as comments - out_immchar_cmts(); - flush_outbuf(); -} diff --git a/idasdk75/module/fr/reg.cpp b/idasdk75/module/fr/reg.cpp deleted file mode 100644 index 00f828e..0000000 --- a/idasdk75/module/fr/reg.cpp +++ /dev/null @@ -1,448 +0,0 @@ - -#include "fr.hpp" -#include <segregs.hpp> - -// FR registers names -static const char *const RegNames[] = -{ - // general purpose registers : - - "r0", - "r1", - "r2", - "r3", - "r4", - "r5", - "r6", - "r7", - "r8", - "r9", - "r10", - "r11", - "r12", - "r13", - "r14", - "r15", - - // coprocessor registers : - - "cr0", - "cr1", - "cr2", - "cr3", - "cr4", - "cr5", - "cr6", - "cr7", - "cr8", - "cr9", - "cr10", - "cr11", - "cr12", - "cr13", - "cr14", - "cr15", - - // dedicated registers : - - "pc", // program counter - "ps", // program status - "tbr", // table base register - "rp", // return pointer - "ssp", // system stack pointer - "usp", // user stack pointer - "mdl", // multiplication/division register (LOW) - "mdh", // multiplication/division register (HIGH) - - // system use dedicated registers - "reserved6", - "reserved7", - "reserved8", - "reserved9", - "reserved10", - "reserved11", - "reserved12", - "reserved13", - "reserved14", - "reserved15", - - // these 2 registers are required by the IDA kernel : - - "cs", - "ds" -}; - -int fr_t::choose_device() -{ - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( choose_ioport_device(&ioh.device, cfgfile) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); - return 0; -} - -// returns a pointer to a ioport_t object if address was found in the config file. -// otherwise, returns NULL. -const ioport_t *fr_t::find_sym(ea_t address) -{ - return find_ioport(ioh.ports, address); -} - -const char *fr_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( !choose_ioport_device(&ioh.device, cfgfile) - && ioh.device == NONEPROC ) - { - warning("No devices are defined in the configuration file %s", cfgfile); - } - else - { - ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); - } - return IDPOPT_OK; -} - - -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.ioh.helper.supset(-1, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new fr_t); - return 0; -} - -ssize_t idaapi fr_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - inf_set_be(true); - helper.create("$ fr"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: - choose_device(); - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - break; - - case processor_t::ev_ending_undo: - //fall through - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - fr_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - fr_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - fr_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return 0; -} - -// -// GNU assembler for fujitsu FR -// - -//----------------------------------------------------------------------- -// gets a function's name -//lint -e{818} could be declared const -static bool fr_get_func_name(qstring *name, func_t *pfn) -{ - ea_t ea = pfn->start_ea; - if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 ) - return false; - - tag_addr(name, ea, true); - return true; -} - -//----------------------------------------------------------------------- -// prints function header -static void idaapi gnu_func_header(outctx_t &ctx, func_t *pfn) -{ - ctx.gen_func_header(pfn); - - qstring namebuf; - if ( fr_get_func_name(&namebuf, pfn) ) - { - const char *name = namebuf.begin(); - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".type %s, @function", SCOLOR_ASMDIR), name); - ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name); - ctx.ctxflags |= CTXF_LABEL_OK; - } -} - -//----------------------------------------------------------------------- -// prints function footer -static void idaapi gnu_func_footer(outctx_t &ctx, func_t *pfn) -{ - qstring namebuf; - if ( fr_get_func_name(&namebuf, pfn) ) - { - const char *name = namebuf.begin(); - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".size %s, .-%s", SCOLOR_ASMDIR), name, name); - } -} - -//----------------------------------------------------------------------- -static const asm_t gnu_asm = -{ - AS_COLON - |ASH_HEXF3 // hex 0x123 format - |ASB_BINF0 // bin 0110b format - |ASO_OCTF1 // oct 012345 format - // don't display the final 0 in string declarations - |/*AS_1TEXT |*/ AS_NCMAS, - 0, - "GNU Assembler for the Fujitsu FR Family", - 0, - NULL, // no headers - ".org", // origin directive - NULL, // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - ".ascii", // ascii string directive - ".byte", // byte directive - ".word", // word directive - ".long", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - gnu_func_header, // func_header - gnu_func_footer, // func_footer - ".globl", // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - ".align", // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -// -// Supported assemblers : -// - -static const asm_t *const asms[] = { &gnu_asm, NULL }; - -// -// Short and long name for our module -// -#define FAMILY "Fujitsu FR 32-Bit Family:" - -static const char *const shnames[] = -{ - "fr", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Fujitsu FR 32-Bit Family", - NULL -}; - -static const uchar retcode_1[] = { 0x97, 0x20 }; // ret -static const uchar retcode_2[] = { 0x9F, 0x20 }; // ret with delay shot -static const uchar retcode_3[] = { 0x9F, 0x30 }; // reti - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } // NULL terminated array -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_FR, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_USE32 // supports 32-bit addressing - | PR_DEFSEG32 // segments are 32-bit by default - | PR_BINMEM, // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs, rVds, - 0, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - 0, fr_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - fr_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/h8/h8.hpp b/idasdk75/module/h8/h8.hpp deleted file mode 100644 index 32f27b9..0000000 --- a/idasdk75/module/h8/h8.hpp +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _H8_HPP -#define _H8_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" - -//------------------------------------------------------------------ -// processor types - -typedef uint16 proctype_t; - -static const proctype_t none = 0; -static const proctype_t P300 = 0x0001; // H8/300, H8/300H -static const proctype_t P2000 = 0x0002; // H8S/2000 -static const proctype_t P2600 = 0x0004; // H8S/2600 -static const proctype_t PSX = 0x0008; // H8SX - -// assume 'Normal mode' as the default -static const proctype_t MODE_MASK= 0xF000; -static const proctype_t MODE_MID = 0x1000; // H8SX -static const proctype_t MODE_ADV = 0x2000; // H8/300H (!), H8S, H8SX -static const proctype_t MODE_MAX = 0x3000; // H8SX - -// submodel -static const proctype_t SUBM_MASK= 0x0F00; -static const proctype_t SUBM_TINY= 0x0100; // H8/300H Tiny model - // full insn set and normal mode - -static const proctype_t P30A = P300 | MODE_ADV; -static const proctype_t P26A = P2600 | MODE_ADV; - -//------------------------------------------------------------------ -#ifdef _MSC_VER -#define ENUM8BIT : uint8 -#else -#define ENUM8BIT -#endif -enum regnum_t ENUM8BIT -{ - R0, R1, R2, R3, R4, R5, R6, R7, SP=R7, - E0, E1, E2, E3, E4, E5, E6, E7, - R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H, - R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L, - ER0, ER1, ER2, ER3, ER4, ER5, ER6, ER7, - // don't change registers order above this line - MACL, MACH, - PC, - CCR, EXR, - rVcs, rVds, // virtual registers for code and data segments - VBR, SBR, // base or segment registers -}; - -//--------------------------------- -// Operand types: - -/* -o_reg 1 Register direct - Rn - x.reg -o_phrase 2 Register indirect - @ERn - x.phrase contains register number - x.phtype contains phrase type (normal, post, pre) -o_displ 3 Register indirect with displacement - @(d:2,ERn)/@(d:16,ERn)/@(d:32,ERn) - x.reg, x.addr, disp_16, disp_32, disp_2 -o_displ 4 Index register indirect with displacement - @(d:16, RnL.B)/@(d:16,Rn.W)/@(d:16,ERn.L) - @(d:32, RnL.B)/@(d:32,Rn.W)/@(d:32,ERn.L) - x.displtype = dt_regidx, - x.reg, - x.addr - disp_16, disp_32, idx_byte/word/long -o_phrase 5 Register indirect with post-inc/pre-dec/pre-inc/post-dec - @ERn+/@-ERn/@+ERn/@ERn- -o_mem 6 Absolute address - @aa:8/@aa:16/@aa:24/@aa:32 - x.memtype = @aa:8 ? mem_sbr : mem_direct - x.addr -o_imm 7 Immediate - #x:2/#xx:3/#xx:4/#xx:5/#xx:8/#xx:16/#xx:32 - #1/#2/#4/#8/#16 - x.value -o_near 8 Program-counter relative - @(d:8,PC)/@(d:16,PC) -o_pcidx 9 Program-counter relative with index register - @(RnL.B,PC)/@(Rn.W,PC)/@(ERn.L,PC) - x.reg -o_mem 10 Memory indirect - @@aa:8 - x.memtype = mem_ind - x.addr -o_mem 11 Extended memory indirect - @@vec:7 - x.memtype = mem_vec7 - x.addr -o_reglist Register list - x.reg, x.nregs -o_displ first operand of MOVA insn - @(d16,<EA>.[BW])/@(d32:<EA>.[BW]) - x.displtype = dt_movaop1, - x.addr, - x.szfl - disp_16/disp_32/idx_byte/idx_word - x.idxt - <EA> type - <EA> type: - o_reg - x.reg EQ to o_regidx - o_phrase - x.phrase,x.idxdt - o_displ - x.reg,x.value,x.idxsz,x.idxdt - o_regidx - x.reg,x.value,x.idxsz,x.idxdt - o_mem - x.value,x.idsz,x.idxdt -*/ - -#define o_reglist o_idpspec0 -#define o_pcidx o_idpspec1 - -#define phtype specflag1 // phrase type: -const int ph_normal = 0; // just simple indirection -const int ph_pre_dec = 0x10; // -@Rn ^ 3 -> @Rn+ -const int ph_post_inc = 0x13; // @Rn+ -const int ph_pre_inc = 0x11; // +@ERn -const int ph_post_dec = 0x12; // @ERn- - -#define displtype specflag1 // displ type: -const int dt_normal = 0; // Register indirect with displacement -const int dt_regidx = 1; // Index register indirect with displacement -const int dt_movaop1 = 2; // first operand of MOVA insn - -#define szfl specflag2 // various operand size flags - // index target -const int idx_byte = 0x01; // .b -const int idx_word = 0x02; // .w -const int idx_long = 0x04; // .l - // size of operand displ -const int disp_16 = 0x10; // 16bit displacement -const int disp_24 = 0x20; // 24bit displacement -const int disp_32 = 0x40; // 32bit displacement -const int disp_2 = 0x80; // 2bit displacement - -#define memtype specflag1 // mem type: -const int mem_direct = 0; // x.addr - direct memory ref -const int mem_sbr = 1; // SBR based @aa:8 -const int mem_vec7 = 2; // @@vec:7 -const int mem_ind = 3; // @@aa:8 - -#define nregs specflag1 // o_reglist: number of registers - -// MOVA Op1 store -#define idxt specflag3 // MOVA: optype_t of index -#define idxsz specflag4 // MOVA: size of index -#define idxdt specval // MOVA: index phtype,displtype,memtype - -//------------------------------------------------------------------ -const uint16 aux_none = 0; // no postfix -const uint16 aux_byte = 1; // .b postfix -const uint16 aux_word = 2; // .w postfix -const uint16 aux_long = 3; // .l postfix - -//------------------------------------------------------------------ -#define UAS_HEW 0x0001 // HEW assembler - -//------------------------------------------------------------------ -ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea -ea_t calc_mem_sbr_based(const insn_t &insn, ea_t ea); // map virtual @aa:8 physical ea - -void idaapi h8_segend(outctx_t &ctx, segment_t *seg); - -int idaapi h8_is_align_insn(ea_t ea); -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_sp_based(const insn_t &insn, const op_t &x); -bool idaapi is_return_insn(const insn_t &insn); - -int is_jump_func(const func_t *pfn, ea_t *jump_target); -int may_be_func(const insn_t &insn); // can a function start here? -int is_sane_insn(const insn_t &insn, int nocrefs); -bool idaapi h8_is_switch(switch_info_t *si, const insn_t &insn); - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct h8_t); - -struct h8_t : public procmod_t -{ - netnode helper; - idb_listener_t idb_listener = idb_listener_t(*this); - qstring device; - ioports_t ports; - proctype_t ptype = none; // contains all bits which correspond - // to the supported processors set - char show_sizer = -1; - uchar code = 0; - uchar code3 = 0; - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - inline bool advanced(void) { return (ptype & MODE_MASK) != 0; } - inline bool is_h8s(void) { return (ptype & (P2000|P2600)) != 0; } - inline bool is_h8sx(void) { return (ptype & PSX) != 0; } - inline bool is_tiny(void) { return (ptype & SUBM_TINY) != 0; } - - inline regnum_t r0(void) { return advanced() ? ER0 : R0; } - - inline bool is_hew_asm(void) const - { - return (ash.uflag & UAS_HEW) != 0; - } - - void load_symbols(void); - const char *find_sym(ea_t address); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - void set_cpu(int cpuno); - int get_displ_outf(const op_t &x, flags_t F); - ea_t trim_ea_branch(ea_t ea) const; // trim address according to proc mode - void h8_header(outctx_t &ctx); - void trimaddr(op_t &x); - void opatHL(op_t &x, op_dtype_t dtyp); - void opdsp16(insn_t &insn, op_t &x, op_dtype_t dtyp); - void opdsp32(insn_t &insn, op_t &x, op_dtype_t dtyp); - bool read_operand(insn_t &insn, op_t &x, ushort flags); - bool map014(insn_t &insn); - bool map4(insn_t &insn); - int ana(insn_t *pinsn); - int exit_40(insn_t &insn); - int exit_54_56(insn_t &insn, uint8 rts, uint8 rtsl); - int exit_59_5D(insn_t &insn, uint16 jump, uint16 branch); - int exit_7B(insn_t &insn); - int h8sx_03(insn_t &insn); - int h8sx_0A(insn_t &insn); - int h8sx_1A(insn_t &insn); - int h8sx_6A(insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - int h8sx_6B(insn_t &insn); - int h8sx_78(insn_t &insn); - int h8sx_79(insn_t &insn); - int h8sx_7A(insn_t &insn); - bool h8sx_010D(insn_t &insn); - bool h8sx_010E(insn_t &insn); - bool insn_ldc(insn_t &insn, uint8 byte2, regnum_t reg); - bool h8sx_01_exr(insn_t &insn); - bool insn_mova(insn_t &insn); - int insn_mova_reg(insn_t &insn, uint8 opcode, uint8 rs, bool is_reg_equal); - bool h8sx_01_other(insn_t &insn); - bool insn_addx_imm(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, bool check_byte3); - bool insn_bra(insn_t &insn, uint8 byte2, uint8 byte3); - bool insn_bfld_bfst(insn_t &insn, uint8 byte2, uint8 byte3, bool is_bfld); - bool use_leaf_map(insn_t &insn, const struct map_t *m, uint8 idx); - bool op_from_byte(insn_t &insn, op_t &x, uint8 byte2); - bool read_1st_op(insn_t &insn, uint8 byte2, uint8 byte3_hiNi); - bool op_phrase(const insn_t &insn, op_t &x, uint8 reg, int pht, op_dtype_t dtype=dt_byte); - bool op_displ_regidx(insn_t &insn, op_t &x, uint8 selector, bool is_32, uint8 reg); - int emu(const insn_t &insn); - int h8_get_frame_retsize(const func_t *); - int h8sx_7C(insn_t &insn); - int h8sx_7D(insn_t &insn); - bool h8sx_010_01dd(insn_t &insn, uint16 postfix); - bool h8sx_ldm(insn_t &insn); - bool insn_mac(insn_t &insn); - bool insn_tas(insn_t &insn); - bool op_phrase_prepost(const insn_t &insn, op_t &x, uint8 reg, uint8 selector); - bool op_phrase_displ2(const insn_t &insn, op_t &x, uint8 reg, uint8 displ); - int h8sx_01(insn_t &insn); - bool h8sx_010_00dd(insn_t &insn); - int h8sx_7E(insn_t &insn); - int h8sx_7F(insn_t &insn); - int unpack_8bit_shift(const map_t *m, insn_t &insn, uint16 itype, uint16 itype2); - int h8sx_10(insn_t &insn); - int h8sx_11(insn_t &insn); - bool h8sx_0108(insn_t &insn); - bool h8sx_0109_010A(insn_t &insn,op_t ®op, op_t &genop); - int h8sx_0F(insn_t &insn); - int h8sx_1F(insn_t &insn); - void add_code_xref(const insn_t &insn, const op_t &x, ea_t ea); - - void h8_assumes(outctx_t &ctx); - void trace_sp(const insn_t &insn) const; - bool get_op_value(uval_t *value, const insn_t &_insn, const op_t &x) const; - bool spoils(const insn_t &insn, int reg) const; - void check_base_reg_change_value(const insn_t &insn) const; - void h8_segstart(outctx_t &ctx, segment_t *Srange) const; - void h8_gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; - void h8_footer(outctx_t &ctx) const; -}; - -#endif // _H8_HPP diff --git a/idasdk75/module/h8/ins.hpp b/idasdk75/module/h8/ins.hpp deleted file mode 100644 index 13fb481..0000000 --- a/idasdk75/module/h8/ins.hpp +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - -H8_null = 0, // Unknown Operation - -H8_add, // Add binary -H8_adds, // Add with sign extension -H8_addx, // Add with extend carry -H8_and, // Logical AND -H8_andc, // Logical AND with control register -H8_band, // Bit AND -H8_bra, // Branch always -H8_brn, // Branch never -H8_bhi, // Branch if higher -H8_bls, // Branch if lower or same -H8_bcc, // Branch if carry clear (higher or same) -H8_bcs, // Branch if carry set (lower) -H8_bne, // Branch if not equal -H8_beq, // Branch if equal -H8_bvc, // Branch if overflow clear -H8_bvs, // Branch if overflow set -H8_bpl, // Branch if plus -H8_bmi, // Branch if minus -H8_bge, // Branch if greates or equal -H8_blt, // Branch if less -H8_bgt, // Branch if greater -H8_ble, // Branch if less or equal -H8_bclr, // Bit clear -H8_biand, // Bit invert AND -H8_bild, // Bit invert load -H8_bior, // Bit invert OR -H8_bist, // Bit invert store -H8_bixor, // Bit invert XOR -H8_bld, // Bit load -H8_bnot, // Bit NOT -H8_bor, // Bit OR -H8_bset, // Bit set -H8_bsr, // Branch to subroutine -H8_bst, // Bit store -H8_btst, // Bit test -H8_bxor, // Bit XOR -H8_clrmac, // Clear MAC register -H8_cmp, // Compare -H8_daa, // Decimal adjust add -H8_das, // Decimal adjust subtract -H8_dec, // Decrement -H8_divxs, // Divide extended as signed -H8_divxu, // Divide extended as unsigned -H8_eepmov, // Move data to EEPROM -H8_exts, // Extend as signed -H8_extu, // Extend as unsigned -H8_inc, // Increment -H8_jmp, // Jump -H8_jsr, // Jump to subroutine -H8_ldc, // Load to control register -H8_ldm, // Load to multiple registers -H8_ldmac, // Load to MAC register -H8_mac, // Multiply and accumulate -H8_mov, // Move data -H8_movfpe, // Move from peripheral with E clock -H8_movtpe, // Move to peripheral with E clock -H8_mulxs, // Multiply extend as signed -H8_mulxu, // Multiply extend as unsigned -H8_neg, // Negate -H8_nop, // No operation -H8_not, // Logical complement -H8_or, // Logical OR -H8_orc, // Logical OR with control register -H8_pop, // Pop data from stack -H8_push, // Push data on stack -H8_rotl, // Rotate left -H8_rotr, // Rotate right -H8_rotxl, // Rotate with extend carry left -H8_rotxr, // Rotate with extend carry right -H8_rte, // Return from exception -H8_rts, // Return from subroutine -H8_shal, // Shift arithmetic left -H8_shar, // Shift arithmetic right -H8_shll, // Shift logical left -H8_shlr, // Shift logical right -H8_sleep, // Power down mode -H8_stc, // Store from control register -H8_stm, // Store from multiple registers -H8_stmac, // Store from MAC register -H8_sub, // Subtract binary -H8_subs, // Subtract with sign extension -H8_subx, // Subtract with extend carry -H8_tas, // Test and set -H8_trapa, // Trap always -H8_xor, // Logical XOR -H8_xorc, // Logical XOR with control register - -// H8SX -H8_rtel, // Returns from an exception, restoring data to multiple general registers -H8_rtsl, // Returns from a subroutine, restoring data to multiple general registers -H8_movmd, // Transfers a data block -H8_movsd, // Transfers a data block with zero detection -H8_bras, // Branch always after the next instruction (delay slot) -H8_movab, // MOVe effective Address/B -H8_movaw, // MOVe effective Address/W -H8_moval, // MOVe effective Address/L -H8_bsetne, // Bit SET if Not Equal -H8_bseteq, // Bit SET if EQual -H8_bclrne, // Bit CLeaR if Not Equal -H8_bclreq, // Bit CLeaR if Equal -H8_bstz, // Bit STore Zero flag -H8_bistz, // Bit Invert STore Zero flag -H8_bfld, // Bit Field LoaD -H8_bfst, // Bit Field STore -H8_muls, // MULtiply as Signed -H8_divs, // DIVide as Signed -H8_mulu, // MULtiply as Unsigned -H8_divu, // DIVide as Unsigned -H8_mulsu, // MULtiply as Signed -H8_muluu, // MULtiply as Unsigned -H8_brabc, // BRAnch if Bit Cleared -H8_brabs, // BRAnch if Bit Set -H8_bsrbc, // Branch to SubRoutine if Bit Cleared -H8_bsrbs, // Branch to SubRoutine if Bit Set - -H8_last, - -}; - -#endif diff --git a/idasdk75/module/h8/makefile b/idasdk75/module/h8/makefile deleted file mode 100644 index ac84547..0000000 --- a/idasdk75/module/h8/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=h8 -CONFIGS=h8.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp h8.hpp \ - ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)frame.hpp \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)jumptable.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp emu.cpp h8.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp h8.hpp ins.cpp \ - ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp h8.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)frame.hpp \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp h8.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/h8/reg.cpp b/idasdk75/module/h8/reg.cpp deleted file mode 100644 index 67d2416..0000000 --- a/idasdk75/module/h8/reg.cpp +++ /dev/null @@ -1,595 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@datarescue.com - * - */ - -#include "h8.hpp" -#include <diskio.hpp> -#include <frame.hpp> -#include <segregs.hpp> - -#include <ieee.h> - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", - "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", - "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", - "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7", - "macl", "mach", - "pc", - "ccr", "exr", - "cs","ds", // virtual registers for code and data segments - "vbr", "sbr", -}; - -//-------------------------------------------------------------------------- -static const char *const register_names_sp_er7[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", - "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", - "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", - "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", - "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7", - "macl", "mach", - "pc", - "ccr", "exr", - "cs","ds", // virtual registers for code and data segments - "vbr", "sbr", -}; - -//-------------------------------------------------------------------------- -static const char *const register_names_r7_sp[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", - "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", - "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", - "er0", "er1", "er2", "er3", "er4", "er5", "er6", "sp", - "macl", "mach", - "pc", - "ccr", "exr", - "cs","ds", // virtual registers for code and data segments - "vbr", "sbr", -}; - -//-------------------------------------------------------------------------- -static const uchar startcode_0[] = { 0x01, 0x00, 0x6D, 0xF3 }; // push.l er3 -static const uchar startcode_1[] = { 0x6D, 0xF3 }; // push.w r3 - -static const bytes_t startcodes[] = -{ - { sizeof(startcode_0), startcode_0 }, - { sizeof(startcode_1), startcode_1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gas = -{ - AS_ASCIIC|AS_ALIGN2|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, - 0, - "GNU assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - ";", // comment string - '"', // string delimiter - '"', // char delimiter - "\"", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".byte", // byte directive - ".word", // word directive - ".long", // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - NULL, // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".globl", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof_fmt - 0, // flag2 - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt - NULL, // a_vstruc_fmt - NULL, // a_rva - NULL, // a_yword -}; - -//----------------------------------------------------------------------- -// HEW ASM -//----------------------------------------------------------------------- -const asm_t hew = -{ - AS_ASCIIC|AS_ALIGN2|ASH_HEXF1|ASD_DECF0|ASO_OCTF7|ASB_BINF4|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, - UAS_HEW, - "HEW assembler", - 0, - NULL, // header lines - ".org", // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '"', // char delimiter - "\"", // special symbols in char and string constants - - ".sdata", // ascii string directive - ".data.b", // byte directive - ".data.w", // word directive - ".data.l", // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".res %s", // uninited arrays - ": .assign", // equ that allows set/reset values -//": .equ", // equ (does not allow for reuse) -//": .reg (%s)",// equ for regs (does not allow for reuse) -//": .bequ", // equ for bits (does not allow for reuse) - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".global", // "extrn" name keyword - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "~", // xor - "~", // not - "<<", // shl - ">>", // shr - "sizeof", // sizeof_fmt - 0, // flag2 - NULL, // cmnt2 - "low", // low8 - "high", // high8 - "lword", // low16 - "hword", // high16 - ".include \"%s\"", // a_include_fmt - NULL, // a_vstruc_fmt - NULL, // a_rva - NULL, // a_yword -}; - -static const asm_t *const asms[] = { &gas, &hew, NULL }; - -//-------------------------------------------------------------------------- -static const char cfgname[] = "h8.cfg"; - -void h8_t::load_symbols(void) -{ - ports.clear(); - read_ioports(&ports, &device, cfgname); -} - -//-------------------------------------------------------------------------- -const char *h8_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ports, address); - return port ? port->name.c_str() : NULL; -} - -//-------------------------------------------------------------------------- -const char *h8_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - if ( choose_ioport_device(&device, cfgname) ) - load_symbols(); - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -static const proctype_t ptypes[] = -{ - P300, // h8300 - P300 | MODE_ADV, // h8300a - P300 | P2000 | P2600, // h8s300 - P300 | MODE_ADV | P2000 | P2600, // h8s300a - P300 | P2000 | P2600 | PSX, // h8sxn - P300 | MODE_MID | P2000 | P2600 | PSX, // h8sxm - P300 | MODE_ADV | P2000 | P2600 | PSX, // h8sxa - P300 | MODE_MAX | P2000 | P2600 | PSX, // h8sx - P300 | MODE_ADV | SUBM_TINY, // h8368 -}; - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.supset(0, pm.device.c_str()); - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -void h8_t::set_cpu(int cpuno) -{ - ptype = ptypes[cpuno]; - // bool keep_cfg = va_argi(va, bool); - if ( advanced() && !is_tiny() ) - { - ph.flag |= PR_DEFSEG32; - } - if ( is_h8sx() ) - { - ph.flag |= PR_SEGS; - ph.reg_last_sreg = SBR; - ph.segreg_size = 4; - } -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new h8_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi h8_t::on_event(ssize_t msgid, va_list va) -{ - int ret = 0; - switch ( msgid ) - { - case processor_t::ev_init: -// __emit__(0xCC); // debugger trap - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ h8"); - helper.supstr(&device, 0); - inf_set_be(true); - break; - - case processor_t::ev_term: - ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newasm: // new assembler type selected - { - int asmnum = va_arg(va, int); - bool hew_asm = asmnum == 1; - if ( advanced() ) - ph.reg_names = hew_asm ? register_names : register_names_r7_sp; - else - ph.reg_names = hew_asm ? register_names : register_names_sp_er7; - } - break; - - case processor_t::ev_newfile: // new file loaded - load_symbols(); - if ( is_h8sx() ) - { - set_default_sreg_value(NULL, VBR, 0); - set_default_sreg_value(NULL, SBR, 0xFFFFFF00); - } - break; - - case processor_t::ev_ending_undo: - // restore ptype - set_cpu(ph.get_proc_index()); - //fall through - case processor_t::ev_oldfile: // old file loaded - load_symbols(); - break; - - case processor_t::ev_newprc: // new processor type - set_cpu(va_arg(va, int)); - break; - - case processor_t::ev_creating_segm: // new segment - break; - - case processor_t::ev_is_jump_func: - { - const func_t *pfn = va_arg(va, const func_t *); - ea_t *jump_target = va_arg(va, ea_t *); - ret = is_jump_func(pfn, jump_target); - } - break; - - case processor_t::ev_is_sane_insn: - { - const insn_t &insn = *va_arg(va, insn_t *); - int no_crefs = va_arg(va, int); - ret = is_sane_insn(insn, no_crefs) == 1 ? 1 : -1; - } - break; - - case processor_t::ev_may_be_func: - // can a function start here? - // arg: none, the instruction is in 'cmd' - // returns: probability 0..100 - // 'cmd' structure is filled upon the entrace - // the idp module is allowed to modify 'cmd' - { - const insn_t &insn = *va_arg(va, insn_t *); - ret = may_be_func(insn); - } - break; - - case processor_t::ev_gen_regvar_def: - { - outctx_t *ctx = va_arg(va, outctx_t *); - regvar_t *v = va_arg(va, regvar_t*); - if ( is_hew_asm() ) - { - ctx->gen_printf(0, - COLSTR("%s", SCOLOR_REG) - COLSTR(": .reg (", SCOLOR_SYMBOL) - COLSTR("%s", SCOLOR_REG) - COLSTR(")", SCOLOR_SYMBOL), - v->user, v->canon); - ret = 1; - } - } - break; - - case processor_t::ev_is_ret_insn: - { - const insn_t &insn = *va_arg(va, insn_t *); - ret = is_return_insn(insn) ? 1 : -1; - } - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - h8_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - h8_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - h8_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - h8_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - h8_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_is_switch: - { - switch_info_t *si = va_arg(va, switch_info_t *); - const insn_t *insn = va_arg(va, const insn_t *); - return h8_is_switch(si, *insn) ? 1 : 0; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = h8_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_gen_stkvar_def: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const member_t *mptr = va_arg(va, const member_t *); - sval_t v = va_arg(va, sval_t); - h8_gen_stkvar_def(*ctx, mptr, v); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *retstr = set_idp_options(keyword, value_type, value, idb_loaded); - if ( retstr == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = retstr; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return h8_is_align_insn(ea); - } - - default: - break; - } - return ret; -} - -//----------------------------------------------------------------------- -#define FAMILY "Hitachi H8:" -static const char *const shnames[] = -{ - "h8300", "h8300a", "h8s300", "h8s300a", - "h8sxn", "h8sxm", "h8sxa", "h8sx", "h8368", NULL -}; -static const char *const lnames[] = -{ - FAMILY"Hitachi H8/300H normal", - "Hitachi H8/300H advanced", - "Hitachi H8S normal", - "Hitachi H8S advanced", - "Hitachi H8SX normal", - "Hitachi H8SX middle", - "Hitachi H8SX advanced", - "Hitachi H8SX maximum", - "Renesas H8/3687 Group", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_H8, // id - // flag - PRN_HEX - | PR_USE32 - | PR_WORD_INS, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - rVcs, // first - rVds, // last - 0, // size of a segment register - rVcs, rVds, - - startcodes, // start sequences - NULL, // see is_ret_insn callback in the notify() function - - H8_null, - H8_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - H8_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/h8500/ana.cpp b/idasdk75/module/h8500/ana.cpp deleted file mode 100644 index d29ed70..0000000 --- a/idasdk75/module/h8500/ana.cpp +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Hitchi H8 - * - */ - -#include "h8500.hpp" - -//-------------------------------------------------------------------------- -#define MAP3 ushort(-3) -#define MAP4 ushort(-4) -#define MAP5 ushort(-5) -#define MAP6 ushort(-6) - -static const ushort A2[] = -{ -/* 00 */ H8500_nop, MAP6, H8500_ldm, H8500_pjsr, MAP5, MAP4, MAP6, MAP6, -/* 08 */ H8500_trapa, H8500_trap_vs, H8500_rte, H8500_bpt, MAP5, MAP4, H8500_bsr, H8500_unlk, -/* 10 */ H8500_jmp, MAP6, H8500_stm, H8500_pjmp, H8500_rtd, MAP4, H8500_null, H8500_link, -/* 18 */ H8500_jsr, H8500_rts, H8500_sleep, H8500_null, H8500_rtd, MAP4, H8500_bsr, H8500_link, -/* 20 */ H8500_bra, H8500_brn, H8500_bhi, H8500_bls, H8500_bcc, H8500_bcs, H8500_bne, H8500_beq, -/* 28 */ H8500_bvc, H8500_bvs, H8500_bpl, H8500_bmi, H8500_bge, H8500_blt, H8500_bgt, H8500_ble, -/* 30 */ H8500_bra, H8500_brn, H8500_bhi, H8500_bls, H8500_bcc, H8500_bcs, H8500_bne, H8500_beq, -/* 38 */ H8500_bvc, H8500_bvs, H8500_bpl, H8500_bmi, H8500_bge, H8500_blt, H8500_bgt, H8500_ble, -/* 40 */ H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, -/* 48 */ H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, -/* 50 */ H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, -/* 58 */ H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, -}; - -static const ushort A2tail[] = -{ -/* 60 */ H8500_mov_l, -/* 70 */ H8500_mov_s, -/* 80 */ H8500_mov_f, -/* 90 */ H8500_mov_f, -/* A0 */ MAP3, -/* B0 */ MAP4, -/* C0 */ MAP4, -/* D0 */ MAP4, -/* E0 */ MAP4, -/* F0 */ MAP4, -}; - -static const ushort A3[] = -{ -/* 00 */ MAP6, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -/* 08 */ H8500_add_q, H8500_add_q, H8500_null, H8500_null, H8500_add_q, H8500_add_q, H8500_null, H8500_null, -/* 10 */ H8500_swap, H8500_exts, H8500_extu, H8500_clr, H8500_neg, H8500_not, H8500_tst, H8500_tas, -/* 18 */ H8500_shal, H8500_shar, H8500_shll, H8500_shlr, H8500_rotl, H8500_rotr, H8500_rotxl, H8500_rotxr, -}; - -static const ushort A3tail[] = -{ -/* 20 */ H8500_add_g, H8500_adds, -/* 30 */ H8500_sub, H8500_subs, -/* 40 */ H8500_or, H8500_bset, -/* 50 */ H8500_and, H8500_bclr, -/* 60 */ H8500_xor, H8500_bnot, -/* 70 */ H8500_cmp_g, H8500_btst, -/* 80 */ H8500_mov_g, H8500_ldc, -/* 90 */ H8500_xch, H8500_stc, -/* A0 */ H8500_addx, H8500_mulxu, -/* B0 */ H8500_subx, H8500_divxu, -/* C0 */ H8500_bset, H8500_bset, -/* D0 */ H8500_bclr, H8500_bclr, -/* E0 */ H8500_bnot, H8500_bnot, -/* F0 */ H8500_btst, H8500_btst, -}; - -static const ushort A4[] = -{ -/* 00 */ MAP6, H8500_null, H8500_null, H8500_null, H8500_cmp_g, H8500_cmp_g, H8500_mov_g, H8500_mov_g, -/* 08 */ H8500_add_q, H8500_add_q, H8500_null, H8500_null, H8500_add_q, H8500_add_q, H8500_null, H8500_null, -/* 10 */ H8500_null, H8500_null, H8500_null, H8500_clr, H8500_neg, H8500_not, H8500_tst, H8500_tas, -/* 18 */ H8500_shal, H8500_shar, H8500_shll, H8500_shlr, H8500_rotl, H8500_rotr, H8500_rotxl, H8500_rotxr, -}; - -static const ushort A4tail[] = -{ -/* 20 */ H8500_add_g, H8500_adds, -/* 30 */ H8500_sub, H8500_subs, -/* 40 */ H8500_or, H8500_bset, -/* 50 */ H8500_and, H8500_bclr, -/* 60 */ H8500_xor, H8500_bnot, -/* 70 */ H8500_cmp_g, H8500_btst, -/* 80 */ H8500_mov_g, H8500_ldc, -/* 90 */ H8500_mov_g, H8500_stc, -/* A0 */ H8500_addx, H8500_mulxu, -/* B0 */ H8500_subx, H8500_divxu, -/* C0 */ H8500_bset, H8500_bset, -/* D0 */ H8500_bclr, H8500_bclr, -/* E0 */ H8500_bnot, H8500_bnot, -/* F0 */ H8500_btst, H8500_btst, -}; - -static const ushort A5[] = -{ -/* 00 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -/* 08 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -/* 10 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -/* 18 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -}; - -static const ushort A5tail[] = -{ -/* 20 */ H8500_add_g, H8500_adds, -/* 30 */ H8500_sub, H8500_subs, -/* 40 */ H8500_or, H8500_orc, -/* 50 */ H8500_and, H8500_andc, -/* 60 */ H8500_xor, H8500_xorc, -/* 70 */ H8500_cmp_g, H8500_null, -/* 80 */ H8500_mov_g, H8500_ldc, -/* 90 */ H8500_null, H8500_null, -/* A0 */ H8500_addx, H8500_mulxu, -/* B0 */ H8500_subx, H8500_divxu, -/* C0 */ H8500_null, H8500_null, -/* D0 */ H8500_null, H8500_null, -/* E0 */ H8500_null, H8500_null, -/* F0 */ H8500_null, H8500_null, -}; - -static const ushort A6[] = -{ -/* 00 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -/* 08 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, -/* 10 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_prtd, H8500_null, H8500_null, H8500_null, -/* 18 */ H8500_null, H8500_prts, H8500_null, H8500_null, H8500_prtd, H8500_null, H8500_null, H8500_null, -}; - -static const ushort A6tail[] = -{ -/* 20 */ H8500_null, H8500_null, -/* 30 */ H8500_null, H8500_null, -/* 40 */ H8500_null, H8500_null, -/* 50 */ H8500_null, H8500_null, -/* 60 */ H8500_null, H8500_null, -/* 70 */ H8500_null, H8500_null, -/* 80 */ H8500_movfpe, H8500_null, -/* 90 */ H8500_movtpe, H8500_null, -/* A0 */ H8500_dadd, H8500_null, -/* B0 */ H8500_dsub, H8500_scb, -/* C0 */ H8500_pjmp, H8500_pjsr, -/* D0 */ H8500_jmp, H8500_jsr, -/* E0 */ H8500_jmp, H8500_jsr, -/* F0 */ H8500_jmp, H8500_jsr, -}; - -struct tables_t -{ - const ushort *head; - const ushort *tail; -}; - -static const tables_t tables[] = -{ - { A3, A3tail }, - { A4, A4tail }, - { A5, A5tail }, - { A6, A6tail }, -}; - -//-------------------------------------------------------------------------- -inline void immv(op_t &x, int v) -{ - x.type = o_imm; - x.dtype = dt_dword; - x.value = v; -} - -//-------------------------------------------------------------------------- -inline void imm8(insn_t &insn, op_t &x) -{ - insn.auxpref |= aux_disp8; - x.type = o_imm; - x.dtype = dt_byte; - x.value = insn.get_next_byte(); -} - -//-------------------------------------------------------------------------- -inline void imm16(insn_t &insn, op_t &x) -{ - insn.auxpref |= aux_disp16; - x.type = o_imm; - x.dtype = dt_word; - x.value = insn.get_next_word(); -} - -//-------------------------------------------------------------------------- -inline void opreg(op_t &x, int code, char dtype) -{ - x.type = o_reg; - x.dtype = dtype; - x.reg = code & 7; -} - -//-------------------------------------------------------------------------- -inline void aa8(insn_t &insn, op_t &x, char dtype) -{ - insn.auxpref |= aux_page|aux_disp8; - x.type = o_mem; - x.dtype = dtype; - x.addr = insn.get_next_byte(); -} - -//-------------------------------------------------------------------------- -inline void aa16(insn_t &insn, op_t &x, char dtype) -{ - insn.auxpref |= aux_disp16; - x.type = o_mem; - x.dtype = dtype; - x.addr = insn.get_next_word(); -} - -//-------------------------------------------------------------------------- -inline void ds8(insn_t &insn, op_t &x, int reg, char dtype) -{ - insn.auxpref |= aux_disp8; - x.type = o_displ; - x.dtype = dtype; - x.reg = reg & 7; - x.addr = insn.get_next_byte(); -} - -//-------------------------------------------------------------------------- -inline void ds16(insn_t &insn, op_t &x, int reg, char dtype) -{ - insn.auxpref |= aux_disp16; - x.type = o_displ; - x.dtype = dtype; - x.reg = reg & 7; - x.addr = insn.get_next_word(); -} - -//-------------------------------------------------------------------------- -inline void phrase(op_t &x, int code, uchar pht, char dtype) -{ - x.type = o_phrase; - x.dtype = dtype; - x.phrase = code & 7; - x.phtype = pht; -} - -//-------------------------------------------------------------------------- -inline void d8(insn_t &insn, op_t &x) -{ - insn.auxpref |= aux_disp8; - int32 disp = char(insn.get_next_byte()); - x.type = o_near; - x.dtype = dt_code; - x.addr = insn.ip + insn.size + disp; -} - -//-------------------------------------------------------------------------- -int h8500_t::h8500_ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - uint8 code = insn.get_next_byte(); - uint8 saved_code = code; - char dtype = dt_byte; - if ( code < 0x60 ) - { - insn.itype = A2[code]; - } - else - { - if ( code & 8 ) - { - insn.auxpref |= aux_word; - dtype = dt_word; - } - else - { - insn.auxpref |= aux_byte; - dtype = dt_byte; - } - insn.itype = A2tail[(code>>4)-6]; - } - if ( insn.itype == H8500_null ) - return 0; - switch ( code ) - { - case 0x02: // ldm.w @sp+, <reglist> -// insn.auxpref |= aux_word; - phrase(insn.Op1, SP, ph_post, dt_word); - insn.Op2.type = o_reglist; - insn.Op2.reg = insn.get_next_byte(); - if ( !insn.Op2.reg ) - return 0; - break; - case 0x12: // stm.w <reglist>, @-sp -// insn.auxpref |= aux_word; - insn.Op1.type = o_reglist; - insn.Op1.reg = insn.get_next_byte(); - if ( !insn.Op1.reg ) - return 0; - phrase(insn.Op2, SP, ph_pre, dt_word); - break; - case 0x01: // scb/f - insn.auxpref |= aux_f; - break; - case 0x06: // scb/ne - insn.auxpref |= aux_ne; - break; - case 0x07: // scb/eq - insn.auxpref |= aux_eq; - break; - case 0x08: // trapa #xx - code = insn.get_next_byte(); - if ( (code & 0xF0) != 0x10 ) - return 0; - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_byte; - insn.Op1.value = code & 15; - break; - case 0x0F: // unlk - opreg(insn.Op1, FP, dt_word); - break; - case 0x10: // jmp @aa:16 - case 0x18: // jsr @aa:16 - aa16(insn, insn.Op1, dt_code); - insn.Op1.type = o_near; - insn.Op1.addr += insn.ea & ~0xFFFF; - break; - case 0x17: // link #xx:8 - opreg(insn.Op1, FP, dt_word); - imm8(insn, insn.Op2); - break; - case 0x1F: // link #xx:16 - opreg(insn.Op1, FP, dt_word); - imm16(insn, insn.Op2); - break; - case 0x03: // pjsr @aa:24 - case 0x13: // pjmp @aa:24 - { - insn.auxpref |= aux_disp24; - uint32 page = insn.get_next_byte(); - insn.Op1.type = o_far; - insn.Op1.dtype = dt_code; - insn.Op1.addr = (page<<16) | insn.get_next_word(); - } - break; - case 0x04: // #xx:8 - insn.auxpref |= aux_byte; - // fallthrough - case 0x14: // #xx:8 - imm8(insn, insn.Op1); - break; - case 0x05: // #aa:8.B - insn.auxpref |= aux_byte; - aa8(insn, insn.Op1, dt_byte); - break; - case 0x15: // #aa:16.B - insn.auxpref |= aux_byte; - aa16(insn, insn.Op1, dt_byte); - break; - case 0x0C: // #xx:16 - insn.auxpref |= aux_word; - // fallthrough - case 0x1C: // #xx:16 - imm16(insn, insn.Op1); - break; - case 0x0D: // #aa:8.W - insn.auxpref |= aux_word; - aa8(insn, insn.Op1, dt_word); - dtype = dt_word; - break; - case 0x1D: // #aa:16.W - insn.auxpref |= aux_word; - aa16(insn, insn.Op1, dt_word); - dtype = dt_word; - break; - case 0x0E: // bsr d:8 - case 0x20: case 0x21: case 0x22: case 0x23: // d:8 - case 0x24: case 0x25: case 0x26: case 0x27: - case 0x28: case 0x29: case 0x2A: case 0x2B: - case 0x2C: case 0x2D: case 0x2E: case 0x2F: - d8(insn, insn.Op1); - break; - case 0x1E: // bsr d:16 - case 0x30: case 0x31: case 0x32: case 0x33: // d:16 - case 0x34: case 0x35: case 0x36: case 0x37: - case 0x38: case 0x39: case 0x3A: case 0x3B: - case 0x3C: case 0x3D: case 0x3E: case 0x3F: - { - insn.auxpref |= aux_disp16; - int32 disp = short(insn.get_next_word()); - insn.Op1.type = o_near; - insn.Op1.dtype = dt_code; - insn.Op1.addr = insn.ip + insn.size + disp; - } - break; - case 0x40: case 0x41: case 0x42: case 0x43: // cmp:e #xx:8, Rn - case 0x44: case 0x45: case 0x46: case 0x47: - case 0x50: case 0x51: case 0x52: case 0x53: // mov:e #xx:8, Rn - case 0x54: case 0x55: case 0x56: case 0x57: - insn.auxpref |= aux_byte; - imm8(insn, insn.Op1); - opreg(insn.Op2, code, dtype); - break; - case 0x48: case 0x49: case 0x4A: case 0x4B: // cmp:i #xx:16, Rn - case 0x4C: case 0x4D: case 0x4E: case 0x4F: - case 0x58: case 0x59: case 0x5A: case 0x5B: // mov:i #xx:16, Rn - case 0x5C: case 0x5D: case 0x5E: case 0x5F: - insn.auxpref |= aux_word; - imm16(insn, insn.Op1); - opreg(insn.Op2, code, dtype); - break; - case 0x60: case 0x61: case 0x62: case 0x63: // @aa:8, Rn - case 0x64: case 0x65: case 0x66: case 0x67: - case 0x68: case 0x69: case 0x6A: case 0x6B: - case 0x6C: case 0x6D: case 0x6E: case 0x6F: - aa8(insn, insn.Op1, dtype); - opreg(insn.Op2, code, dtype); - break; - case 0x70: case 0x71: case 0x72: case 0x73: // Rn, @aa:8 - case 0x74: case 0x75: case 0x76: case 0x77: - case 0x78: case 0x79: case 0x7A: case 0x7B: - case 0x7C: case 0x7D: case 0x7E: case 0x7F: - opreg(insn.Op1, code, dtype); - aa8(insn, insn.Op2, dtype); - break; - case 0x80: case 0x81: case 0x82: case 0x83: // mov:f @(d:8, R6), Rn - case 0x84: case 0x85: case 0x86: case 0x87: - case 0x88: case 0x89: case 0x8A: case 0x8B: - case 0x8C: case 0x8D: case 0x8E: case 0x8F: - ds8(insn, insn.Op1, R6, dtype); - opreg(insn.Op2, code, dtype); - break; - case 0x90: case 0x91: case 0x92: case 0x93: // mov:f Rn, @(d:8, R6) - case 0x94: case 0x95: case 0x96: case 0x97: - case 0x98: case 0x99: case 0x9A: case 0x9B: - case 0x9C: case 0x9D: case 0x9E: case 0x9F: - opreg(insn.Op1, code, dtype); - ds8(insn, insn.Op2, R6, dtype); - break; - case 0xA0: case 0xA1: case 0xA2: case 0xA3: // Rn, Rn - case 0xA4: case 0xA5: case 0xA6: case 0xA7: - case 0xA8: case 0xA9: case 0xAA: case 0xAB: - case 0xAC: case 0xAD: case 0xAE: case 0xAF: - opreg(insn.Op1, code, dtype); - break; - case 0xB0: case 0xB1: case 0xB2: case 0xB3: // @-Rn, Rn - case 0xB4: case 0xB5: case 0xB6: case 0xB7: - case 0xB8: case 0xB9: case 0xBA: case 0xBB: - case 0xBC: case 0xBD: case 0xBE: case 0xBF: - phrase(insn.Op1, code, ph_pre, dtype); - break; - case 0xC0: case 0xC1: case 0xC2: case 0xC3: // @Rn+, Rn - case 0xC4: case 0xC5: case 0xC6: case 0xC7: - case 0xC8: case 0xC9: case 0xCA: case 0xCB: - case 0xCC: case 0xCD: case 0xCE: case 0xCF: - phrase(insn.Op1, code, ph_post, dtype); - break; - case 0xD0: case 0xD1: case 0xD2: case 0xD3: // @Rn, Rn - case 0xD4: case 0xD5: case 0xD6: case 0xD7: - case 0xD8: case 0xD9: case 0xDA: case 0xDB: - case 0xDC: case 0xDD: case 0xDE: case 0xDF: - phrase(insn.Op1, code, ph_normal, dtype); - break; - case 0xE0: case 0xE1: case 0xE2: case 0xE3: // @(d:8,Rn), Rn - case 0xE4: case 0xE5: case 0xE6: case 0xE7: - case 0xE8: case 0xE9: case 0xEA: case 0xEB: - case 0xEC: case 0xED: case 0xEE: case 0xEF: - ds8(insn, insn.Op1, code, dtype); - break; - case 0xF0: case 0xF1: case 0xF2: case 0xF3: // @(d:16,Rn), Rn - case 0xF4: case 0xF5: case 0xF6: case 0xF7: - case 0xF8: case 0xF9: case 0xFA: case 0xFB: - case 0xFC: case 0xFD: case 0xFE: case 0xFF: - ds16(insn, insn.Op1, code, dtype); - break; - } - while ( insn.itype > H8500_last ) // while MAPs are not resolved - { - int index = -(3+short(insn.itype)); - if ( index < 0 || index >= qnumber(tables) ) - INTERR(10089); - code = insn.get_next_byte(); - if ( code < 0x20 ) - { - insn.itype = tables[index].head[code]; - } - else - { - insn.itype = tables[index].tail[(code>>3)-4]; - opreg(insn.Op2, code, dtype); - } - if ( index == 3 ) switch ( saved_code ) // MAP6 - { - case 0x01: - case 0x06: - case 0x07: - if ( insn.itype != H8500_scb ) - return 0; - break; - case 0x11: - if ( insn.itype != H8500_prts - && insn.itype != H8500_prtd - && insn.itype != H8500_jmp - && insn.itype != H8500_pjmp - && insn.itype != H8500_jsr - && insn.itype != H8500_pjsr ) - { - return 0; - } - break; - default: - if ( insn.itype != H8500_movfpe - && insn.itype != H8500_movtpe - && insn.itype != H8500_dadd - && insn.itype != H8500_dsub ) - { - return 0; - } - } - switch ( insn.itype ) - { - case H8500_null: - return 0; - case H8500_add_q: - insn.Op2 = insn.Op1; - switch ( code ) - { - case 0x08: immv(insn.Op1, 1); break; - case 0x09: immv(insn.Op1, 2); break; - case 0x0C: immv(insn.Op1, -1); break; - case 0x0D: immv(insn.Op1, -2); break; - } - break; - case H8500_bset: - case H8500_bclr: - case H8500_bnot: - case H8500_btst: - insn.Op2 = insn.Op1; - if ( code < 0xC0 ) - opreg(insn.Op1, code, dtype); - else - immv(insn.Op1, code & 15); - break; - case H8500_mov_g: - if ( (code & 0xF8) == 0x80 ) - break; - insn.Op2 = insn.Op1; - if ( code == 0x06 ) - { - if ( (insn.auxpref & aux_word) == 0 ) - insn.auxpref |= aux_byte; - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_byte; - insn.Op1.value = insn.get_next_byte(); - } - else if ( code == 0x07 ) - { - if ( (insn.auxpref & aux_byte) == 0 ) - insn.auxpref |= aux_word; - insn.auxpref |= aux_mov16; - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_word; - insn.Op1.value = insn.get_next_word(); - } - else - opreg(insn.Op1, code, dtype); - break; - case H8500_cmp_g: - if ( code > 5 ) - break; - insn.Op2 = insn.Op1; - if ( code == 0x04 ) - { - insn.auxpref |= aux_byte; - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_byte; - insn.Op1.value = insn.get_next_byte(); - } - else - { - insn.auxpref |= aux_word; - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_word; - insn.Op1.value = insn.get_next_word(); - } - break; - case H8500_andc: - case H8500_orc: - case H8500_xorc: - case H8500_ldc: - case H8500_stc: - insn.Op2.reg += SR; - if ( insn.Op2.reg == RES1 || insn.Op2.reg == CP ) - return 0; - if ( ((insn.auxpref & aux_word) != 0) != (insn.Op2.reg == SR) ) - return 0; - if ( insn.itype != H8500_stc ) - break; - // no break - case H8500_movtpe: - { - op_t x = insn.Op1; - insn.Op1 = insn.Op2; - insn.Op2 = x; - } - break; - case H8500_pjmp: - case H8500_pjsr: - case H8500_jmp: - case H8500_jsr: - insn.Op2.type = o_void; - switch ( code & 0xF0 ) - { - case 0xC0: - case 0xD0: phrase(insn.Op1, code, ph_normal, dt_code); break; - case 0xE0: ds8(insn, insn.Op1, code, dt_code); break; - case 0xF0: ds16(insn, insn.Op1, code, dt_code); break; - } - break; - case H8500_rtd: - case H8500_prtd: - if ( code == 0x14 ) - imm8(insn, insn.Op1); - else - imm16(insn, insn.Op1); - break; - case H8500_scb: - insn.Op1 = insn.Op2; - d8(insn, insn.Op2); - break; - case H8500_dadd: - case H8500_dsub: - if ( (insn.auxpref & aux_byte) == 0 ) - return 0; - insn.auxpref &= ~aux_byte; - break; - } - } - if ( (idpflags & AFIDP_MIXSIZE) == 0 ) // Disassemble mixed size instructions? - { - if ( (insn.auxpref & aux_word) && insn.Op1.dtype == dt_byte - || (insn.auxpref & aux_byte) && insn.Op1.dtype == dt_word ) - { - if ( insn.itype != H8500_mov_g ) - return 0; - } - } - return insn.size; -} diff --git a/idasdk75/module/h8500/h8500.hpp b/idasdk75/module/h8500/h8500.hpp deleted file mode 100644 index c6e840b..0000000 --- a/idasdk75/module/h8500/h8500.hpp +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _H8500_HPP -#define _H8500_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <segregs.hpp> -#include <diskio.hpp> - -//------------------------------------------------------------------ -#define AFIDP_MIXSIZE 0x0001 // Disassemble mixed size instructions - -//--------------------------------- -// Operand types: - -/* -o_reg 1 Register direct Rn - x.reg -o_phrase 2 Register indirect @Rn - x.phrase contains register number - x.phtype contains phrase type (normal, post, pre) -o_displ 3 Register indirect with displacement @(d:8,Rn)/@(d:16,Rn) - x.reg, x.addr, aux_disp16, aux_disp32 -o_mem 5 Absolute address @aa:8/@aa:16/@aa:24 - x.page, x.addr -o_imm 6 Immediate #xx:8/#xx:16/#xx:32 - x.value -o_displ 7 Program-counter relative @(d:8,PC)/@(d:16,PC) -o_reglist Register list - x.reg -*/ - -#define o_reglist o_idpspec0 - -#define phtype specflag1 // phrase type: -const int ph_normal = 0; // just simple indirection -const int ph_pre = 1; // predecrement -const int ph_post = 2; // postincrement - -#define page specflag1 // o_mem, page number if aux_page -//------------------------------------------------------------------ -#define aux_byte 0x0001 // .b postfix -#define aux_word 0x0002 // .w postfix -#define aux_disp8 0x0004 // 8bit displacement -#define aux_disp16 0x0008 // 16bit displacement -#define aux_disp24 0x0010 // 24bit displacement -#define aux_page 0x0020 // implicit page using BR -#define aux_f 0x0040 // /f postfix -#define aux_ne 0x0080 // /ne postfix -#define aux_eq 0x0100 // /eq postfix -#define aux_mov16 0x0200 // mov #xx:16, ... - -//------------------------------------------------------------------ -enum regnum_t -{ - R0, R1, R2, R3, R4, R5, R6, FP=R6, R7, SP=R7, - SR, CCR, RES1, BR, EP, DP, CP, TP, // RES1 is forbidden -}; - - -ea_t calc_mem(const insn_t &insn, const op_t &x); // map virtual to physical ea -//------------------------------------------------------------------ -int calc_opimm_flags(const insn_t &insn); -int calc_opdispl_flags(const insn_t &insn); - -void idaapi h8500_header(outctx_t &ctx); - -void idaapi h8500_segend(outctx_t &ctx, segment_t *seg); - -int idaapi is_align_insn(ea_t ea); -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_sp_based(const insn_t &insn, const op_t &x); - -int idaapi h8500_get_frame_retsize(const func_t *); -int is_jump_func(const func_t *pfn, ea_t *jump_target); -int is_sane_insn(const insn_t &insn, int nocrefs); -int may_be_func(const insn_t &insn); // can a function start here? - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct h8500_t); - -struct h8500_t : public procmod_t -{ - netnode helper; - idb_listener_t idb_listener = idb_listener_t(*this); - ioports_t ports; - ushort idpflags = AFIDP_MIXSIZE; - bool flow = false; - char show_sizer = -1; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void load_symbols(const char *file); - const char *find_sym(int address); - const char *set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - - int h8500_ana(insn_t *_insn); - - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - int h8500_emu(const insn_t &insn); - - void h8500_assume(outctx_t &ctx); - void h8500_segstart(outctx_t &ctx, segment_t *Srange) const; - void h8500_footer(outctx_t &ctx) const; -}; - -#endif // _H8500_HPP diff --git a/idasdk75/module/h8500/ins.hpp b/idasdk75/module/h8500/ins.hpp deleted file mode 100644 index 6442cb3..0000000 --- a/idasdk75/module/h8500/ins.hpp +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ - -H8500_null = 0, // Unknown Operation - -// Data transfer - -H8500_mov_g, // B/W Move data -H8500_mov_e, // B Move data -H8500_mov_i, // W Move data -H8500_mov_f, // B/W Move data -H8500_mov_l, // B/W Move data -H8500_mov_s, // B/W Move data -H8500_ldm, // W Pop data from the stack to one or more registers -H8500_stm, // W Push data from one or more registers onto the stack -H8500_xch, // W Exchange data between two general registers -H8500_swap, // B Exchange the upper and lower bytes in a general register -H8500_movtpe, // B Transfer data from a general register to memory -H8500_movfpe, // B Transfer data from memory to a general register - -// Arithmetic operations - -H8500_add_g, // B/W Addition -H8500_add_q, // B/W Addition -H8500_sub, // B/W Subtraction -H8500_adds, // B/W Addition -H8500_subs, // B/W Subtraction -H8500_addx, // B/W Addition with carry -H8500_subx, // B/W Subtraction with borrow -H8500_dadd, // B Decimal addition -H8500_dsub, // B Decimal subtraction -H8500_mulxu, // B/W Unsigned multiplication -H8500_divxu, // B/W Unsigned division -H8500_cmp_g, // B/W Compare data -H8500_cmp_e, // B Compare data -H8500_cmp_i, // W Compare data -H8500_exts, // B Convert byte to word by extending the sign bit -H8500_extu, // B Convert byte to word data by padding with zero bits -H8500_tst, // B/W Compare with 0 -H8500_neg, // B/W Negate -H8500_clr, // B/W Make zero -H8500_tas, // B Test and set - -// Logic Operations - -H8500_and, // B/W Logical AND -H8500_or, // B/W Logical OR -H8500_xor, // B/W Exclusive OR -H8500_not, // B/W Bitwise NOT - -// Shift Operations - -H8500_shal, // B/W Arithmetic shift left -H8500_shar, // B/W Arithmetic shift right -H8500_shll, // B/W Logical shift left -H8500_shlr, // B/W Logical shift right -H8500_rotl, // B/W Rotate left -H8500_rotr, // B/W Rotate right -H8500_rotxl, // B/W Rotate through carry left -H8500_rotxr, // B/W Rotate through carry right - -// Bit Manipulations - -H8500_bset, // B/W Test bit and set -H8500_bclr, // B/W Test bit and clear -H8500_bnot, // B/W Test bit and invert -H8500_btst, // B/W Test bit - -// Branching Instructions - -H8500_bra, // Branch Always -H8500_brn, // Branch Never -H8500_bhi, // Branch if High (C|Z = 0) -H8500_bls, // Branch if Low or Same (C|Z = 1) -H8500_bcc, // Branch if Carry Clear (C = 0) -H8500_bcs, // Branch if Carry Set (C = 1) -H8500_bne, // Branch if Not Equal (Z = 0) -H8500_beq, // Branch if Equal (Z = 1) -H8500_bvc, // Branch if Overflow Clear (V = 0) -H8500_bvs, // Branch if Overflow Set (V = 1) -H8500_bpl, // Branch if Plus (N = 0) -H8500_bmi, // Branch if Minus (N = 1) -H8500_bge, // Branch if Greater or Equal (N^V = 0) -H8500_blt, // Branch if Less Than (N^V = 1) -H8500_bgt, // Branch if Greater Than (Z|(N^V) = 0) -H8500_ble, // Branch if Less or Equal (Z|(N^V) = 1) -H8500_jmp, // Branch unconditionally (same page) -H8500_pjmp, // Branch unconditionally (specified page) -H8500_bsr, // Branch to subroutine (same page) -H8500_jsr, // Branch to subroutine (same page) -H8500_pjsr, // Branch to subroutine (specified page) -H8500_rts, // Return from subroutine (same page) -H8500_prts, // Return from subroutine (different page) -H8500_rtd, // Return from subroutine (same page) and adjust SP -H8500_prtd, // Return from subroutine (different page) and adjust SP -H8500_scb, // Control loop - -// System Control Instructions - -H8500_trapa, // Generate trap exception -H8500_trap_vs, // Generate trap exception if the V bit is set -H8500_rte, // Return from exception-handling routine -H8500_link, // Create stack frame -H8500_unlk, // Deallocate stack frame -H8500_sleep, // Go to power-down state -H8500_ldc, // B/W Move to control register -H8500_stc, // B/W Move from control register -H8500_andc, // B/W Logically AND control register -H8500_orc, // B/W Logically OR control register -H8500_xorc, // B/W Logically exclusive-OR control register -H8500_nop, // No operation -H8500_bpt, // - -H8500_last, - - }; - -#endif diff --git a/idasdk75/module/h8500/makefile b/idasdk75/module/h8500/makefile deleted file mode 100644 index 1d1f081..0000000 --- a/idasdk75/module/h8500/makefile +++ /dev/null @@ -1,45 +0,0 @@ -PROC=h8500 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp h8500.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)frame.hpp \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp h8500.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - h8500.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - h8500.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - h8500.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/h8500/reg.cpp b/idasdk75/module/h8500/reg.cpp deleted file mode 100644 index 8db6076..0000000 --- a/idasdk75/module/h8500/reg.cpp +++ /dev/null @@ -1,498 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "h8500.hpp" -#include <fpro.h> -#include <diskio.hpp> - -#include <ieee.h> - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", "fp", "sp", - "sr", "ccr", "?", "br", "ep", "dp", "cp", "tp", -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0x56, 0x70 }; // rte -static const uchar retcode_1[] = { 0x54, 0x70 }; // rts - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//------------------------------------------------------------------ -static void idaapi func_header(outctx_t &ctx, func_t *pfn) -{ - ctx.gen_func_header(pfn); - - if ( ctx.curlabel.empty() ) - return; - - ctx.gen_printf(0, "%s" COLSTR(":", SCOLOR_SYMBOL) " " - SCOLOR_ON SCOLOR_AUTOCMT - "%s %s" - SCOLOR_OFF SCOLOR_AUTOCMT, - ctx.curlabel.begin(), - ASH.cmnt, - (pfn->flags & FUNC_FAR) != 0 ? "far" : "near"); - ctx.ctxflags |= CTXF_LABEL_OK; -} - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gas = -{ - AS_ASCIIC|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, - 0, - "GNU assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - "!", // comment string - '"', // string delimiter - '"', // char delimiter - "\"", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".byte", // byte directive - ".word", // word directive - ".long", // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - NULL, // current IP (instruction pointer) - func_header, // func_header - NULL, // func_footer - ".globl", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_COLONSUF, // flag2 - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt -}; - -static const asm_t *const asms[] = { &gas, NULL }; - -//-------------------------------------------------------------------------- -void h8500_t::load_symbols(const char *file) -{ - ports.clear(); - - // KLUDGE: read_ioports() will complain if the file is - // not present, but we don't want that. - char cfgpath[QMAXPATH]; - const char *rfile = getsysfile(cfgpath, sizeof(cfgpath), file, CFG_SUBDIR); - if ( rfile != NULL ) - read_ioports(&ports, NULL, file); -} - -//-------------------------------------------------------------------------- -const char *h8500_t::find_sym(int address) -{ - const ioport_t *port = find_ioport(ports, address); - return port != NULL ? port->name.c_str() : NULL; -} - -//------------------------------------------------------------------ -const char *h8500_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - static const char form[] = - "HELP\n" - "H8/500 specific analyzer options\n" - "\n" - "Disassemble mixed size instructions\n" - "\n" - " According to the documentation, instructions like\n" - "\n" - " cmp:g.b #1:16, @0x222:16\n" - "\n" - " are not allowed. The correct instruction is:\n" - "\n" - " cmp:g.b #1:8, @0x222:16\n" - "\n" - " The size of the first operand should agree with the size\n" - " of the instruction. (exception mov:g)\n" - "\n" - "ENDHELP\n" - "H8/500 specific analyzer options\n" - "\n" - // m - " <Disassemble ~m~ixed size instructions:C>>\n" - "\n" - "\n"; - - if ( keyword == NULL ) - { - CASSERT(sizeof(idpflags) == sizeof(ushort)); - ask_form(form, &idpflags); - } - if ( streq(keyword,"H8500_MIXED_SIZE") ) - { - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - setflag(idpflags, AFIDP_MIXSIZE, *(int*)value != 0); - } - else - { - return IDPOPT_BADKEY; - } - if ( idb_loaded ) - helper.altset(-1, idpflags - 1); - return IDPOPT_OK; - -} - -//----------------------------------------------------------------------- -#define FAMILY "Hitachi H8/500:" -static const char *const shnames[] = { "h8500", NULL }; -static const char *const lnames[] = -{ - FAMILY"Hitachi H8/500", - NULL -}; - -//----------------------------------------------------------------------- -// temporary solution for v4.7 -static ea_t idaapi h8_extract_address(ea_t screen_ea, const char *string, size_t x) -{ - size_t len = strlen(string); - if ( len == 0 || x > len ) - return BADADDR; - if ( x == len ) - x--; - const char *ptr = string + x; - while ( ptr > string && qisxdigit(ptr[-1]) ) - ptr--; - const char *start = ptr; - while ( qisxdigit(ptr[0]) ) - ptr++; - len = ptr - start; - char buf[MAXSTR]; - memcpy(buf, start, len); - buf[len] = '\0'; - ea_t ea = BADADDR; - str2ea(&ea, buf, screen_ea); - return ea; -} - -//------------------------------------------------------------------------ -static bool idaapi can_have_type(const op_t &x) // returns 1 - operand can have -{ - switch ( x.type ) - { - case o_void: - case o_reg: - case o_reglist: - return false; - case o_phrase: - return x.phtype == ph_normal; - } - return true; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(-1, pm.idpflags - 1); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new h8500_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi h8500_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ h8/500"); - inf_set_be(true); - break; - - case processor_t::ev_term: - ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: // old file loaded - idpflags = ushort(helper.altval(-1) + 1); - // no break - case processor_t::ev_newfile: // new file loaded - load_symbols("h8500.cfg"); - inf_set_be(true); - break; - - case processor_t::ev_creating_segm: // new segment - { - segment_t *sptr = va_arg(va, segment_t *); - sptr->defsr[BR-ph.reg_first_sreg] = 0; - sptr->defsr[DP-ph.reg_first_sreg] = 0; - } - break; - - case processor_t::ev_is_jump_func: - { - const func_t *pfn = va_arg(va, const func_t *); - ea_t *jump_target = va_arg(va, ea_t *); - return is_jump_func(pfn, jump_target); - } - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - int no_crefs = va_arg(va, int); - return is_sane_insn(*insn, no_crefs) == 1 ? 1 : -1; - } - - case processor_t::ev_may_be_func: - { - const insn_t *insn = va_arg(va, insn_t *); - return may_be_func(*insn); - } - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - h8500_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - h8500_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - h8500_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - h8500_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - h8500_assume(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return h8500_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return h8500_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *op = va_arg(va, const op_t *); - return can_have_type(*op) ? 1 : -1; - } - - case processor_t::ev_extract_address: - { - ea_t *out_ea = va_arg(va, ea_t *); - ea_t screen_ea = va_arg(va, ea_t); - const char *str = va_arg(va, const char *); - size_t pos = va_arg(va, size_t); - ea_t ea = h8_extract_address(screen_ea, str, pos); - if ( ea == BADADDR ) - return -1; - if ( ea == (BADADDR-1) ) - return 0; - *out_ea = ea; - return 1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = h8500_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_H8500, // id - // flag - PRN_HEX - | PR_SEGS - | PR_SGROTHER, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - BR, // first - TP, // last - 1, // size of a segment register - CP, DP, - - NULL, // No known code start sequences - retcodes, - - H8500_null, - H8500_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - H8500_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/hppa/ana.cpp b/idasdk75/module/hppa/ana.cpp deleted file mode 100644 index 84ccd77..0000000 --- a/idasdk75/module/hppa/ana.cpp +++ /dev/null @@ -1,1334 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - */ - -#include "hppa.hpp" - -//-------------------------------------------------------------------------- -static void simplify(insn_t &insn, uint32 code) -{ - switch ( insn.itype ) - { - // B,L,n target, %r0 => B,n target - // B,L,n target, %r2 => CALL,n target - case HPPA_b: - { - int sub = (code>>13) & 7; - if ( sub == 1 || sub == 4 ) - break; // ,gate or ,push - switch ( insn.Op2.reg ) - { - case R0: - insn.Op2.type = o_void; - break; - case R2: - insn.itype = HPPA_call; - insn.Op2.type = o_void; - break; - } - } - break; - - // BVE,L,n (b), %r2 => CALL,n (b) - // BVE,n (%r2) => RET,n - case HPPA_bve: - if ( code & BIT31 ) - break; // ,push or ,pop - if ( insn.Op2.type == o_reg ) - { - insn.itype = HPPA_call; - insn.Op1.type = o_void; - break; - } - if ( insn.Op1.phrase == R2 ) - { - insn.itype = HPPA_ret; - insn.Op1.type = o_void; - } - break; - - // DEPD,Z,cond r,63-sa,64-sa,t => SHLD,cond r,sa,t - // DEPW,Z,cond r,31-sa,32-sa,t => SHLW,cond r,sa,t - case HPPA_depd: - case HPPA_depw: - if ( code & BIT21 ) - break; // no Z flag - if ( insn.Op2.type == o_imm - && insn.Op3.type == o_imm - && (insn.Op2.value+1) == insn.Op3.value ) - { - insn.itype += (HPPA_shld-HPPA_depd); - insn.Op2.value = (insn.itype == HPPA_shld ? 63 : 31) - insn.Op2.value; - insn.Op3 = insn.Op4; - insn.Op4.type = o_void; - } - break; - - // DEPWI,Z,cond -1,31,x,t => LDI,cond (1<<x)-1,t - case HPPA_depwi: - if ( code & BIT21 ) - break; // no Z flag - if ( insn.Op2.type == o_imm && insn.Op2.value == 31 - && insn.Op3.type == o_imm && insn.Op3.value <= 16 ) - { - insn.itype = HPPA_ldi; - insn.Op1.value = (uval_t(1) << insn.Op3.value) - 1; - insn.Op2 = insn.Op4; - insn.Op3.type = o_void; - insn.Op4.type = o_void; - } - break; - // EXTRD,S,cond r,63-sa,64-sa,t => SHRD,S,cond r,sa,t - // EXTRD,U,cond r,63-sa,64-sa,t => SHRD,U,cond r,sa,t - // EXTRW,S,cond r,31-sa,32-sa,t => SHRW,S,cond r,sa,t - // EXTRW,U,cond r,31-sa,32-sa,t => SHRW,U,cond r,sa,t - case HPPA_extrd: - case HPPA_extrw: - if ( insn.Op2.type == o_imm - && insn.Op3.type == o_imm - && (insn.Op2.value+1) == insn.Op3.value ) - { - insn.itype += HPPA_shrd - HPPA_extrd; - insn.Op2.value = (insn.itype == HPPA_shrd ? 63 : 31) - insn.Op2.value; - insn.Op3 = insn.Op4; - insn.Op4.type = o_void; - } - break; - - // LDO i(%r0), t => LDI i, t - // LDO 0(r), t => COPY r, t - case HPPA_ldo: - if ( insn.Op1.reg == R0 ) - { - insn.itype = HPPA_ldi; - insn.Op1.type = o_imm; - insn.Op1.value = insn.Op1.addr; - break; - } - if ( insn.Op1.addr == 0 ) - { - insn.itype = HPPA_copy; - insn.Op1.type = o_reg; - } - break; - - // MTCTL r, %sar => MTSAR r - case HPPA_mtctl: - if ( insn.Op2.reg == CR11 ) - { - insn.itype = HPPA_mtsar; - insn.Op2.type = o_void; - } - break; - - // OR %r0, %r0, %r0 => NOP - // OR %r, %r0, %t => COPY r, t - // OR %r0, %r, %t => COPY r, t - case HPPA_or: - if ( ((code>>13) & 7) ) - break; // condition codes not zero - if ( insn.Op1.reg == R0 ) - { - if ( insn.Op2.reg == R0 && insn.Op3.reg == R0 ) - { - insn.itype = HPPA_nop; - insn.Op1.type = o_void; - insn.Op2.type = o_void; - insn.Op3.type = o_void; - break; - } - insn.itype = HPPA_copy; - insn.Op1 = insn.Op2; - insn.Op2 = insn.Op3; - insn.Op3.type = o_void; - break; - } - if ( insn.Op2.reg == R0 ) - { - insn.itype = HPPA_copy; - insn.Op2 = insn.Op3; - insn.Op3.type = o_void; - } - break; - } -} - -//-------------------------------------------------------------------------- -struct table1_t -{ - ushort itype; - char dtype; -}; - -static const table1_t C1[] = -{ - { 0, dt_qword }, // 00 - { 0, dt_qword }, // 01 - { 0, dt_qword }, // 02 - { 0, dt_qword }, // 03 - { 0, dt_qword }, // 04 - { HPPA_diag, dt_qword }, // 05 - { HPPA_fmpyadd, dt_qword }, // 06 - { HPPA_null, dt_qword }, // 07 - { HPPA_ldil, dt_qword }, // 08 - { 0, dt_qword }, // 09 - { HPPA_addil, dt_qword }, // 0A - { 0, dt_qword }, // 0B - { HPPA_copr, dt_qword }, // 0C - { HPPA_ldo, dt_dword }, // 0D - { 0, dt_qword }, // 0E - { HPPA_null, dt_qword }, // 0F - { HPPA_ldb, dt_byte }, // 10 - { HPPA_ldh, dt_word }, // 11 - { HPPA_ldw, dt_dword }, // 12 - { HPPA_ldw, dt_dword }, // 13 - { 0, dt_qword }, // 14 - { HPPA_null, dt_dword }, // 15 - { HPPA_fldw, dt_dword }, // 16 - { 0, dt_dword }, // 17 - { HPPA_stb, dt_byte }, // 18 - { HPPA_sth, dt_word }, // 19 - { HPPA_stw, dt_dword }, // 1A - { HPPA_stw, dt_dword }, // 1B - { 0, dt_qword }, // 1C - { HPPA_null, dt_dword }, // 1D - { HPPA_fstw, dt_dword }, // 1E - { 0, dt_dword }, // 1F - { HPPA_cmpb, dt_byte }, // 20 - { HPPA_cmpib, dt_byte }, // 21 - { HPPA_cmpb, dt_byte }, // 22 - { HPPA_cmpib, dt_dword }, // 23 - { HPPA_cmpiclr, dt_qword }, // 24 - { HPPA_subi, dt_dword }, // 25 - { HPPA_fmpysub, dt_dword }, // 26 - { HPPA_cmpb, dt_byte }, // 27 - { HPPA_addb, dt_byte }, // 28 - { HPPA_addib, dt_byte }, // 29 - { HPPA_addb, dt_byte }, // 2A - { HPPA_addib, dt_byte }, // 2B - { HPPA_addi, dt_dword }, // 2C - { HPPA_addi, dt_dword }, // 2D - { 0, dt_dword }, // 2E - { HPPA_cmpb, dt_byte }, // 2F - { HPPA_bb, dt_dword }, // 30 - { HPPA_bb, dt_dword }, // 31 - { HPPA_movb, dt_byte }, // 32 - { HPPA_movib, dt_byte }, // 33 - { 0, dt_dword }, // 34 - { 0, dt_dword }, // 35 - { HPPA_extrd, dt_qword }, // 36 - { HPPA_null, dt_dword }, // 37 - { HPPA_be, dt_dword }, // 38 - { HPPA_be, dt_dword }, // 39 - { 0, dt_dword }, // 3A - { HPPA_cmpib, dt_byte }, // 3B - { 0, dt_dword }, // 3C - { 0, dt_dword }, // 3D - { 0, dt_dword }, // 3E - { HPPA_null, dt_dword }, // 3F -}; - -struct ldst_t -{ - ushort itype; - char dtype; -}; - -static const ldst_t C6[] = -{ - { HPPA_ldb, dt_byte }, // 0 - { HPPA_ldh, dt_word }, // 1 - { HPPA_ldw, dt_dword }, // 2 - { HPPA_ldd, dt_qword }, // 3 - { HPPA_ldda, dt_qword }, // 4 - { HPPA_ldcd, dt_qword }, // 5 - { HPPA_ldwa, dt_dword }, // 6 - { HPPA_ldcw, dt_dword }, // 7 - { HPPA_stb, dt_byte }, // 8 - { HPPA_sth, dt_word }, // 9 - { HPPA_stw, dt_dword }, // A - { HPPA_std, dt_qword }, // B - { HPPA_stby, dt_byte }, // C - { HPPA_stdby, dt_qword }, // D - { HPPA_stwa, dt_dword }, // E - { HPPA_stda, dt_qword }, // F -}; - -//-------------------------------------------------------------------------- -static void opr(op_t &x, uint32 rgnum) -{ - x.reg = (uint16)rgnum; -/* if ( rgnum == 0 ) - { - x.type = o_imm; - x.value = 0; - x.dtype = dt_dword; - } - else*/ - { - x.type = o_reg; - x.dtype = dt_qword; - } -} - -//-------------------------------------------------------------------------- -inline void opi(op_t &x, uval_t v) -{ - x.type = o_imm; - x.value = v; - x.dtype = dt_dword; -} - -//-------------------------------------------------------------------------- -inline void opb(op_t &x, int r) -{ - x.type = o_based; - x.phrase = (uint16)r; - x.dtype = dt_dword; -} - -//-------------------------------------------------------------------------- -inline void opbs(insn_t &insn, op_t &x, int sr, int r) -{ - opb(x, r); - x.sid = uchar(SR0+sr); - if ( sr != 0 ) - insn.auxpref |= aux_space; -} - -//-------------------------------------------------------------------------- -inline void opx(op_t &x, int b, int xx, char dtype) -{ - x.type = o_phrase; - x.phrase = uint16(b); - x.secreg = uchar(xx); - x.dtype = dtype; -} - -//-------------------------------------------------------------------------- -inline void opxs(insn_t &insn, op_t &x, int sr, int b, int xx, char dtype) -{ - opx(x, b, xx, dtype); - x.sid = uchar(SR0+sr); - if ( sr != 0 ) - insn.auxpref |= aux_space; -} - -//-------------------------------------------------------------------------- -inline void opd(op_t &x, int b, uval_t value, char dtype) -{ - x.type = o_displ; - x.phrase = uint16(b); - x.addr = value; - x.dtype = dtype; -} - -//-------------------------------------------------------------------------- -inline void opds(insn_t &insn, op_t &x, int sr, int b, uval_t value, char dtype) -{ - opd(x, b, value, dtype); - x.sid = uchar(SR0+sr); - if ( sr != 0 ) - insn.auxpref |= aux_space; -} - -//-------------------------------------------------------------------------- -struct table_t -{ - char code; - ushort itype; //lint !e958 padding is required to align members -}; - -static const table_t C5[] = -{ - { 0x18, HPPA_add }, - { 0x28, HPPA_add }, - { 0x38, HPPA_add }, - { 0x1C, HPPA_add }, - { 0x3C, HPPA_add }, - { 0x19, HPPA_shladd }, - { 0x29, HPPA_shladd }, - { 0x39, HPPA_shladd }, - { 0x1A, HPPA_shladd }, - { 0x2A, HPPA_shladd }, - { 0x3A, HPPA_shladd }, - { 0x1B, HPPA_shladd }, - { 0x2B, HPPA_shladd }, - { 0x3B, HPPA_shladd }, - { 0x10, HPPA_sub }, - { 0x30, HPPA_sub }, - { 0x13, HPPA_sub }, - { 0x33, HPPA_sub }, - { 0x14, HPPA_sub }, - { 0x34, HPPA_sub }, - { 0x11, HPPA_ds }, - { 0x00, HPPA_andcm }, - { 0x08, HPPA_and }, - { 0x09, HPPA_or }, - { 0x0A, HPPA_xor }, - { 0x0E, HPPA_uxor }, - { 0x22, HPPA_cmpclr }, - { 0x26, HPPA_uaddcm }, - { 0x27, HPPA_uaddcm }, - { 0x2E, HPPA_dcor }, - { 0x2F, HPPA_dcor }, - { 0x0F, HPPA_hadd }, - { 0x0D, HPPA_hadd }, - { 0x0C, HPPA_hadd }, - { 0x07, HPPA_hsub }, - { 0x05, HPPA_hsub }, - { 0x04, HPPA_hsub }, - { 0x0B, HPPA_havg }, - { 0x1D, HPPA_hshladd }, - { 0x1E, HPPA_hshladd }, - { 0x1F, HPPA_hshladd }, - { 0x15, HPPA_hshladd }, - { 0x16, HPPA_hshladd }, - { 0x17, HPPA_hshladd }, - { 0, HPPA_null }, -}; - -static ushort find_itype(const table_t *table, int code) -{ - while ( table->itype ) - { - if ( table->code == code ) - return table->itype; - table++; - } - return HPPA_null; -} - -//-------------------------------------------------------------------------- -inline sval_t ls5(int i5) { return (( i5>>1)&15) | (( i5 & 1) ? ~sval_t(15) : 0); } -inline sval_t ls11(int i11) { return ((i11>>1)&0x3FF) | ((i11 & 1) ? ~sval_t(0x1FF) : 0); } -inline sval_t s12(int imm12) { return (imm12 & 0x0800) ? (imm12 | ~sval_t(0x0FFF)) : imm12; } -inline sval_t s16(int imm16) { return (imm16 & 0x8000) ? (imm16 | ~sval_t(0xFFFF)) : imm16; } -inline sval_t s17(uint32 i17) { return (i17 & 0x10000) ? (i17 | ~sval_t(0x1FFFF)) : i17; } -inline sval_t s22(uint32 i22) { return (i22 & 0x200000) ? (i22 | ~sval_t(0x3FFFFF)) : i22; } -inline int mfr(int r, bool d) { return (d ? F0 : F16L) + r; } -inline int as3(int s) -{ - return ((s>>1) & 3) | ((s&1) << 2); -} -inline int fr(int r, int y) -{ - return F0 + r + ((y&1)<<5); -} - -//-------------------------------------------------------------------------- -static void handle_float_0C(insn_t &insn, uint32 code) -{ - int uid = (code>> 6) & 7; - if ( uid == 2 ) // performance coprocessor - { - int sub = (code>>9) & 0x1F; - switch ( sub ) - { - case 1: - insn.itype = HPPA_pmdis; - break; - case 3: - insn.itype = (code & BIT26) ? HPPA_null : HPPA_pmenb; - break; - default: - insn.itype = HPPA_null; - break; - } - return; - } - if ( uid != 0 ) - return; // other coprocessors - - // floating-point coprocessor - int cls = (code>>9) & 3; - switch ( cls ) - { - case 0: - { - static const ushort itypes[] = - { - HPPA_fid, HPPA_null, HPPA_fcpy, HPPA_fabs, - HPPA_fsqrt, HPPA_frnd, HPPA_fneg, HPPA_fnegabs - }; - insn.itype = itypes[(code>>13)&7]; - if ( insn.itype != HPPA_fid ) - { - opr(insn.Op1, F0 + r06(code)); - opr(insn.Op2, F0 + r27(code)); - } - } - break; - case 1: - insn.itype = HPPA_fcnv; - opr(insn.Op1, F0 + r06(code)); - opr(insn.Op2, F0 + r27(code)); - break; - case 2: - if ( code & BIT26 ) - { - insn.itype = HPPA_ftest; - int y = (code>>13) & 7; - if ( y != 1 ) - opr(insn.Op1, CA0+(y^1)-1); - } - else - { - insn.itype = HPPA_fcmp; - opr(insn.Op1, F0 + r06(code)); - opr(insn.Op2, F0 + r11(code)); - int y = (code>>13) & 7; - if ( y ) - opr(insn.Op3, CA0+y-1); - } - break; - case 3: - { - static const ushort itypes[] = - { - HPPA_fadd, HPPA_fsub, HPPA_fmpy, HPPA_fdiv, - HPPA_frem, HPPA_null, HPPA_null, HPPA_null - }; - int sub = (code>>13) & 7; - insn.itype = (code & BIT26) ? HPPA_null : itypes[sub]; - opr(insn.Op1, F0 + r06(code)); - opr(insn.Op2, F0 + r11(code)); - opr(insn.Op3, F0 + r27(code)); - } - break; - } -} - -//-------------------------------------------------------------------------- -static void handle_float_0E(insn_t &insn, uint32 code) -{ - int cls = (code>>9) & 3; - switch ( cls ) - { - case 0: - { - static const ushort itypes[] = - { - HPPA_null, HPPA_null, HPPA_fcpy, HPPA_fabs, - HPPA_fsqrt, HPPA_frnd, HPPA_fneg, HPPA_fnegabs - }; - insn.itype = itypes[(code>>13)&7]; - opr(insn.Op1, fr(r06(code), (code>>7)&1)); - opr(insn.Op2, fr(r27(code), (code>>6)&1)); - } - break; - case 1: - insn.itype = HPPA_fcnv; - opr(insn.Op1, fr(r06(code), (code>>7)&1)); - opr(insn.Op2, fr(r27(code), (code>>6)&1)); - break; - case 2: - { - insn.itype = HPPA_fcmp; - opr(insn.Op1, fr(r06(code), (code>>7)&1)); - opr(insn.Op2, fr(r11(code), (code>>12)&1)); - int y = (code>>13) & 7; - if ( y ) - opr(insn.Op3, CA0+y-1); - } - break; - case 3: - { - static const ushort itypes[] = - { - HPPA_fadd, HPPA_fsub, HPPA_fmpy, HPPA_fdiv, - HPPA_null, HPPA_null, HPPA_null, HPPA_null - }; - int sub = (code>>13) & 7; - insn.itype = itypes[sub]; - if ( code & BIT23 ) - { - insn.itype = (sub == 2) ? HPPA_xmpyu : HPPA_null; - } - opr(insn.Op1, fr(r06(code), (code>>7)&1)); - opr(insn.Op2, fr(r11(code), (code>>12)&1)); - opr(insn.Op3, fr(r27(code), (code>>6)&1)); - } - break; - } -} - -//-------------------------------------------------------------------------- -inline void opn(op_t &x, sval_t disp, ea_t ip) -{ - disp <<= 2; - x.type = o_near; - x.addr = ip + 8 + disp; -} - -//-------------------------------------------------------------------------- -int hppa_t::ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - if ( insn.ip & 3 ) - return 0; // alignment error - - uint32 code = insn.get_next_dword(); - - int op = opcode(code); - insn.itype = C1[op].itype; - char dtype = C1[op].dtype; - switch ( op ) - { - case 0x00: - switch ( (code>>5) & 0xFF ) - { - case 0x00: - insn.itype = HPPA_break; - opi(insn.Op1, r27(code)); - opi(insn.Op2, (code>>13) & 0x1FFF); - break; - case 0x20: - insn.itype = (code & BIT11) ? HPPA_syncdma : HPPA_sync; - break; - case 0x60: - case 0x65: - insn.itype = HPPA_rfi; - break; - case 0x6B: - insn.itype = HPPA_ssm; -RSM_SSM: - opi(insn.Op1, (code>>16)&0x3FF); - opr(insn.Op2, r27(code)); - break; - case 0x73: - insn.itype = HPPA_rsm; - goto RSM_SSM; - case 0xC3: - insn.itype = HPPA_mtsm; - opr(insn.Op1, r11(code)); - break; - case 0x85: - insn.itype = HPPA_ldsid; - opbs(insn, insn.Op1, (code>>14)&3, r06(code)); - opr(insn.Op2, r27(code)); - break; - case 0xC1: - insn.itype = HPPA_mtsp; - opr(insn.Op1, r11(code)); - opr(insn.Op2, SR0+((code>>13)&7)); - break; - case 0x25: - insn.itype = HPPA_mfsp; - opr(insn.Op1, SR0+((code>>13)&7)); - opr(insn.Op2, r27(code)); - break; - case 0xA5: - insn.itype = HPPA_mfia; - opr(insn.Op1, r27(code)); - break; - case 0xC2: - insn.itype = HPPA_mtctl; - opr(insn.Op1, r11(code)); - opr(insn.Op2, CR0+r06(code)); - break; - case 0xC6: - if ( r06(code) != 0xB ) - return 0; - insn.itype = HPPA_mtsarcm; - opr(insn.Op1, r11(code)); - break; - case 0x45: - insn.itype = HPPA_mfctl; - opr(insn.Op1, CR0+r06(code)); - opr(insn.Op2, r27(code)); - break; - default: - return 0; - } - break; - - case 0x01: - if ( code & BIT19 ) - { - switch ( (code>>6) & 0xFF ) - { - case 0x60: - insn.itype = HPPA_idtlbt; - opr(insn.Op1, CR0+r06(code)); - opr(insn.Op2, r27(code)); - break; - case 0x48: - case 0x58: - insn.itype = HPPA_pdtlb; - goto PDT; - case 0x49: - insn.itype = HPPA_pdtlbe; -PDT: - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); - break; - case 0x4A: - insn.itype = HPPA_fdc; - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); - break; - case 0xCA: - insn.itype = HPPA_fdc; - opds(insn, insn.Op1, (code>>14)&3, r06(code), ls5(r11(code)), dt_dword); - if ( code & BIT26 ) - return 0; - break; - case 0x4B: - insn.itype = HPPA_fdce; - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); - break; - case 0x4E: - insn.itype = HPPA_pdc; - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); - break; - case 0x4F: - insn.itype = HPPA_fic; - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); - break; - case 0x46: - case 0x47: - insn.itype = HPPA_probe; - opbs(insn, insn.Op1, (code>>14)&3, r06(code)); - opr(insn.Op2, r11(code)); - opr(insn.Op3, r27(code)); - break; - case 0xC6: - case 0xC7: - insn.itype = HPPA_probei; - opbs(insn, insn.Op1, (code>>14)&3, r06(code)); - opi(insn.Op2, r11(code)); - opr(insn.Op3, r27(code)); - break; - case 0x4D: - insn.itype = HPPA_lpa; -MAKE_LPA: - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); - opr(insn.Op2, r27(code)); - break; - case 0x4C: - insn.itype = HPPA_lci; - if ( code & BIT26 ) - return 0; - goto MAKE_LPA; - default: - return 0; - } - } - else - { - switch ( (code>>6) & 0x7F ) - { - case 0x20: - insn.itype = HPPA_iitlbt; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - break; - case 0x18: - case 0x08: - insn.itype = HPPA_pitlb; -PIT: - opxs(insn, insn.Op1, as3((code>>13)&7), r06(code), r11(code), dt_dword); - insn.auxpref |= aux_space; - break; - case 0x09: - insn.itype = HPPA_pitlbe; - goto PIT; - case 0x0A: - insn.itype = HPPA_fic; - goto PIT; - case 0x0B: - insn.itype = HPPA_fice; - goto PIT; - default: - return 0; - } - } - break; - - case 0x02: - insn.auxpref = (code>>13) & aux_cndc; // condition - insn.itype = find_itype(C5, (code>>6)&0x3F); - switch ( insn.itype ) - { - default: - //case HPPA_add: - //case HPPA_sub: - //case HPPA_ds: - //case HPPA_and: - //case HPPA_andcm: - //case HPPA_or: - //case HPPA_xor: - //case HPPA_uxor: - //case HPPA_cmpclr: - //case HPPA_uaddcm: - //case HPPA_hadd: - //case HPPA_hsub: - //case HPPA_havg: - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - opr(insn.Op3, r27(code)); - break; - case HPPA_dcor: - opr(insn.Op1, r06(code)); - opr(insn.Op2, r27(code)); - break; - case HPPA_shladd: - opr(insn.Op1, r11(code)); - opi(insn.Op2, (code>>6)&3); - if ( ((code>>6) & 3) == 0 ) - return 0; - opr(insn.Op3, r06(code)); - opr(insn.Op4, r27(code)); - break; - case HPPA_hshladd: - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - if ( ((code>>6) & 3) == 0 ) - return 0; - if ( insn.auxpref ) - return 0; // condition should be never - opi(insn.Op3, (code>>6)&3); - opr(insn.Op4, r27(code)); - break; - } - break; - - case 0x03: - { - int idx = (code>>6) & 0xF; - if ( (code & BIT19) == 0 && idx > 7 ) - return 0; - insn.itype = C6[idx].itype; - dtype = C6[idx].dtype; - if ( code & BIT19 ) // short - { - if ( idx > 7 ) // store - { - opr(insn.Op1, r11(code)); - opds(insn, insn.Op2, (code>>14)&3, r06(code), ls5(r27(code)), dtype); - } - else // load - { - opds(insn, insn.Op1, (code>>14)&3, r06(code), ls5(r11(code)), dtype); - opr(insn.Op2, r27(code)); - } - } - else // index - { - opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dtype); - opr(insn.Op2, r27(code)); - } - if ( (idx & 7) == 6 ) - insn.auxpref &= ~aux_space; // ldwa, stwa - } - break; - - case 0x04: - switch ( (code>>9) & 3 ) - { - case 0: - insn.itype = HPPA_spop0; - break; - case 1: - insn.itype = HPPA_spop1; - opr(insn.Op1, r27(code)); - break; - case 2: - insn.itype = HPPA_spop2; - opr(insn.Op1, r06(code)); - break; - case 3: - insn.itype = HPPA_spop3; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - break; - } - break; - - case 0x05: // diag - opi(insn.Op1, code & 0x3FFFFFF); - break; - - case 0x06: // fmpyadd - case 0x26: // fmpysub - { - bool d = !((code>>5) & 1); - opr(insn.Op1, mfr(r06(code),d)); - opr(insn.Op2, mfr(r11(code),d)); - opr(insn.Op3, mfr(r27(code),d)); - opr(insn.Op4, mfr((code>>6)&0x1F,d)); - opr(insn.Op5, mfr((code>>11)&0x1F,d)); - } - break; - - case 0x07: - return 0; - - case 0x08: // ldil - opi(insn.Op1, as21(code & 0x1FFFFF)); - opr(insn.Op2, r06(code)); - break; - - case 0x09: // cldw, cstw, fstd, fstw - case 0x0B: // cldd, cstd, fldd, fldw - { - op_t *x; - int uid = (code>> 6) & 7; - if ( code & BIT22 ) - { - insn.itype = HPPA_cstd; - opr(insn.Op1, r27(code)); - x = &insn.Op2; - if ( uid < 2 ) - { - insn.itype = HPPA_fstd; - insn.Op1.reg += F0 + ((code>>1)&0x20); - } - } - else - { - insn.itype = HPPA_cldd; - opr(insn.Op2, r27(code)); - x = &insn.Op1; - if ( uid < 2 ) - { - insn.itype = HPPA_fldd; - insn.Op2.reg += F0 + ((code>>1)&0x20); - } - } - dtype = dt_qword; - if ( op == 0x09 ) - { - insn.itype++; // cldw, cstw - dtype = dt_dword; - } - if ( code & BIT19 ) - opds(insn, *x, (code>>14)&3, r06(code), ls5(r11(code)), dtype); - else - opxs(insn, *x, (code>>14)&3, r06(code), r11(code), dtype); - } - break; - - case 0x0A: // addil - opi(insn.Op1, as21(code & 0x1FFFFF)); - opr(insn.Op2, r06(code)); - opr(insn.Op3, R1); - break; - - case 0x0C: // copr - handle_float_0C(insn, code); - break; - - case 0x0D: // ldo - if ( getseg(insn.ea)->use64() ) - dtype = dt_qword; - opd(insn.Op1, r06(code), s16(get_ldo(code)), dtype); - opr(insn.Op2, r11(code)); - break; - - case 0x0E: - handle_float_0E(insn, code); - break; - - case 0x0F: - return 0; - - case 0x10: // ldb - case 0x11: // ldh - case 0x12: // ldw - case 0x13: // ldw (mod) - { - int s = (code>>14) & 3; - opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,code & 0x3FFF)), dtype); - opr(insn.Op2, r11(code)); - } - break; - - case 0x14: - { - int s = (code>>14) & 3; - insn.itype = (code & BIT30) ? HPPA_fldd : HPPA_ldd; - int im10a = ((code>>3) & 0x7FE) | (code & 1); - opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,im10a)), dtype); - opr(insn.Op2, r11(code)); - if ( code & BIT30 ) - insn.Op2.reg += F0; - } - break; - - case 0x1C: - { - int s = (code>>14) & 3; - insn.itype = (code & BIT30) ? HPPA_fstd : HPPA_std; - int im10a = ((code>>3) & 0x7FE) | (code & 1); - opr(insn.Op1, r11(code)); - if ( code & BIT30 ) - insn.Op1.reg += F0; - opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,im10a)), dtype); - } - break; - - case 0x16: - case 0x17: - { - int s = (code>>14) & 3; - insn.itype = op & 1 && (code & BIT29) ? HPPA_ldw : HPPA_fldw; - int im11a = ((code>>3) & 0xFFE) | (code & 1); - opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,im11a)), dtype); - opr(insn.Op2, r11(code)); - if ( code & BIT29 ) - insn.Op2.reg += F0 + ((code<<4) & 0x20); - } - break; - - case 0x1E: - case 0x1F: - { - int s = (code>>14) & 3; - insn.itype = op & 1 && (code & BIT29) ? HPPA_stw : HPPA_fstw; - int im11a = ((code>>3) & 0xFFE) | (code & 1); - opr(insn.Op1, r11(code)); - if ( code & BIT29 ) - insn.Op1.reg += F0 + ((code<<4) & 0x20); - opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,im11a)), dtype); - } - break; - - case 0x18: // stb - case 0x19: // sth - case 0x1A: // stw - case 0x1B: // stw (mod) - { - int s = (code>>14) & 3; - opr(insn.Op1, r11(code)); - opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,code & 0x3FFF)), dtype); - } - break; - - case 0x15: - case 0x1D: - return 0; - - case 0x20: // cmpb - case 0x22: // cmpb - case 0x27: // cmpb - case 0x2F: // cmpb - case 0x28: // addb - case 0x2A: // addb - case 0x32: // movb - insn.auxpref = (code>>13) & aux_cndc; // condition - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip); - break; - - case 0x21: // cmpib - case 0x23: // cmpib - case 0x3B: // cmpib - case 0x29: // addib - case 0x2B: // addib - case 0x33: // movib - insn.auxpref = (code>>13) & aux_cndc; // condition - opi(insn.Op1, ls5(r11(code))); - opr(insn.Op2, r06(code)); - opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip); - break; - - case 0x24: // cmpiclr - case 0x25: // subi - case 0x2C: // addi - case 0x2D: // addi - insn.auxpref = (code>>13) & aux_cndc; // condition - opi(insn.Op1, ls11(code & 0x7FF)); - opr(insn.Op2, r06(code)); - opr(insn.Op3, r11(code)); - break; - - case 0x2E: - { - insn.itype = (code & BIT26) ? HPPA_fmpynfadd : HPPA_fmpyfadd; - bool d = (code>>11) & 1; - opr(insn.Op1, mfr(r06(code),d)); - opr(insn.Op2, mfr(r11(code),d)); - int ra = ((code>>10) & 0x38) | ((code>>8) & 0x7); - opr(insn.Op3, F0+ra); - opr(insn.Op4, mfr(r27(code),d)); - } - break; - - case 0x30: // bb - case 0x31: - opr(insn.Op1, r11(code)); - if ( op & 1 ) - { - int pos = r06(code) | ((code>>8) & 0x20); - opi(insn.Op2, pos); - } - else - { - opr(insn.Op2, CR11); - } - opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip); - break; - - case 0x34: - insn.auxpref = (code>>13) & aux_cndc; // condition - switch ( (code>>11) & 3 ) // bits 19, 20 - { - case 0: - if ( (code & BIT21) == 0 ) // format 11 - { - insn.itype = (code & BIT22) ? HPPA_shrpd : HPPA_shrpw; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - opr(insn.Op3, CR11); - opr(insn.Op4, r27(code)); - break; - } - // no break - case 1: // format 14 - { - insn.itype = (code & BIT21) ? HPPA_shrpd : HPPA_shrpw; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - int sa = (insn.itype == HPPA_shrpd ? 63 : 31) - (r22(code)|((code>>10)&1)); - opi(insn.Op3, sa); - opr(insn.Op4, r27(code)); - } - break; - case 2: // format 12 - { - insn.itype = (code & BIT22) ? HPPA_extrd : HPPA_extrw; - opr(insn.Op1, r06(code)); - opr(insn.Op2, CR11); - int cl = (code>>3) & 0x20; - if ( (code & BIT22) == 0 && cl ) - return 0; - opi(insn.Op3, (32-r27(code))|cl); - opr(insn.Op4, r11(code)); - } - break; - case 3: // format 15 - insn.itype = HPPA_extrw; - opr(insn.Op1, r06(code)); - opi(insn.Op2, r22(code)); - opi(insn.Op3, 32-r27(code)); - opr(insn.Op4, r11(code)); - break; - } - break; - - case 0x35: - insn.auxpref = (code>>13) & aux_cndc; // condition - if ( code & BIT20 ) // format 16 - { - if ( code & BIT19 ) - { - insn.itype = HPPA_depwi; - opi(insn.Op1, ls5(r11(code))); - } - else - { - insn.itype = HPPA_depw; - opr(insn.Op1, r11(code)); - } - opi(insn.Op2, 31-r22(code)); - opi(insn.Op3, 32-r27(code)); - opr(insn.Op4, r06(code)); - } - else // format 13 - { - if ( code & BIT19 ) - { - insn.itype = (code & BIT22) ? HPPA_depdi : HPPA_depwi; - opi(insn.Op1, ls5(r11(code))); - opr(insn.Op2, CR11); - } - else - { - insn.itype = (code & BIT22) ? HPPA_depd : HPPA_depw; - opr(insn.Op1, r11(code)); - opr(insn.Op2, CR11); - } - int cl = (code>>3) & 0x20; - if ( (code & BIT22) == 0 && cl ) - return 0; - opi(insn.Op3, (32-r27(code))|cl); - opr(insn.Op4, r06(code)); - } - break; - - case 0x36: // extrd - { - insn.auxpref = (code>>13) & aux_cndc; // condition - opr(insn.Op1, r06(code)); - opi(insn.Op2, ((code>>6)&0x20)|r22(code)); - int cl = (code>>7) & 0x20; - opi(insn.Op3, (32-r27(code))|cl); - opr(insn.Op4, r11(code)); - } - break; - - case 0x37: - return 0; - - case 0x38: // be - case 0x39: // be - { - int32 w = get17(code); - opds(insn, insn.Op1, as3((code>>13)&7), r06(code), s17(w)<<2, dt_code); - insn.auxpref |= aux_space; - if ( op & 1 ) - { - opr(insn.Op2, SR0); - opr(insn.Op3, R31); - } - } - break; - - case 0x3A: - { - int sub = (code>>13) & 7; - switch ( sub ) - { - case 0x2: - if ( code & BIT19 ) - return 0; - insn.itype = HPPA_blr; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - break; - case 0x6: - insn.itype = (code & BIT19) ? HPPA_bve : HPPA_bv; - if ( insn.itype == HPPA_bv ) - opx(insn.Op1, r06(code), r11(code), dt_code); - else - opb(insn.Op1, r06(code)); - break; - case 0x7: - if ( !(code & BIT19) ) - return 0; - insn.itype = HPPA_bve; - opb(insn.Op1, r06(code)); - opr(insn.Op1, R2); - break; - case 0x0: - case 0x1: - { - insn.itype = HPPA_b; - int32 w = get17(code); - opn(insn.Op1, s17(w), insn.ip); - opr(insn.Op2, r06(code)); - } - break; - case 0x4: - case 0x5: - { - insn.itype = HPPA_b; - int32 w = ((code&1) << 21) - | (r06(code) << 16) - | (r11(code) << 11) - | get11(code); - opn(insn.Op1, s22(w), insn.ip); - opr(insn.Op2, R2); - } - break; - } - } - break; - - case 0x3C: - insn.itype = HPPA_depd; - opr(insn.Op1, r11(code)); -DEPD: - opi(insn.Op2, (32-r22(code))|((code>>7)&0x20)); - opi(insn.Op3, r27(code)); - opr(insn.Op4, r06(code)); - insn.auxpref = (code>>13) & aux_cndc; // condition - break; - - case 0x3D: - insn.itype = HPPA_depdi; - opi(insn.Op1, ls5(r11(code))); - goto DEPD; - - case 0x3E: - if ( code & BIT16 ) - { - switch ( (code>>10) & 3 ) - { - case 0: - insn.itype = HPPA_mixw; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - opr(insn.Op3, r27(code)); - break; - case 1: - insn.itype = HPPA_mixh; - opr(insn.Op1, r11(code)); - opr(insn.Op2, r06(code)); - opr(insn.Op3, r27(code)); - break; - case 2: - if ( ((code>>13)&3) == 0 ) - { - insn.itype = HPPA_hshl; - opr(insn.Op1, r11(code)); - opi(insn.Op2, (code>>6) & 0xF); - opr(insn.Op3, r27(code)); - break; - } - // no break; - case 3: - insn.itype = HPPA_hshr; - opr(insn.Op1, r06(code)); - opi(insn.Op2, (code>>6) & 0xF); - opr(insn.Op3, r27(code)); - break; - default: - return 0; - } - } - else - { - insn.itype = HPPA_permh; - if ( r06(code) != r11(code) ) - return 0; - opr(insn.Op1, r06(code)); - opr(insn.Op2, r27(code)); - } - break; - - case 0x3F: - return 0; - - default: - interr(insn, "ana"); - } - if ( insn.itype == 0 ) - return 0; - - if ( dosimple() ) - simplify(insn, code); - - char buf[80]; - if ( !build_insn_completer(insn, code, buf, sizeof(buf)) ) - return 0; - - return insn.size; -} - -//-------------------------------------------------------------------------- -void interr(const insn_t &insn, const char *module) -{ - const char *name = NULL; - if ( insn.itype < HPPA_last ) - name = Instructions[insn.itype].name; - warning("%a(%s): internal error in %s", insn.ea, name, module); -} - diff --git a/idasdk75/module/hppa/hppa.hpp b/idasdk75/module/hppa/hppa.hpp deleted file mode 100644 index 4dc0979..0000000 --- a/idasdk75/module/hppa/hppa.hpp +++ /dev/null @@ -1,235 +0,0 @@ - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _HPPA_HPP -#define _HPPA_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <segregs.hpp> -#include <typeinf.hpp> -#include <diskio.hpp> -#include <fixup.hpp> - -//------------------------------------------------------------------ -#define PROC_MAXOP 5 // max number of operands -CASSERT(PROC_MAXOP <= UA_MAXOP); - -#define aux_cndc 0x0007 // condition bits c -#define aux_cndf 0x0008 // condition bits f -#define aux_cndd 0x0010 // condition bits d -#define aux_space 0x0020 // space register present - -#define o_based o_idpspec2 // (%r5) - // o_phrase: %r4(%r5) - // o_displ: 55(%r5) -#define sid specflag1 -#define secreg specflag2 // for o_phrase, the index register -//------------------------------------------------------------------ -enum RegNo -{ - // general registers - R0, R1, R2, R3, R4, R5, R6, R7, - R8, R9, R10, R11, R12, R13, R14, R15, - R16, R17, R18, R19, R20, R21, R22, R23, - R24, R25, R26, DP, R28, R29, SP, R31, - // space registers - SR0, SR1, SR2, SR3, SR4, SR5, SR6, SR7, - // control registers - CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7, - CR8, CR9, CR10, CR11, CR12, CR13, CR14, CR15, - CR16, CR17, CR18, CR19, CR20, CR21, CR22, CR23, - CR24, CR25, CR26, CR27, CR28, CR29, CR30, CR31, - // floating-point registers - F0, F1, F2, F3, F4, F5, F6, F7, - F8, F9, F10, F11, F12, F13, F14, F15, - F16, F17, F18, F19, F20, F21, F22, F23, - F24, F25, F26, F27, F28, F29, F30, F31, - // register halves (valid only for fmpyadd/sub) - F16L, F17L, F18L, F19L, F20L, F21L, F22L, F23L, - F24L, F25L, F26L, F27L, F28L, F29L, F30L, F31L, - F16R, F17R, F18R, F19R, F20R, F21R, F22R, F23R, - F24R, F25R, F26R, F27R, F28R, F29R, F30R, F31R, - // condition bits - CA0, CA1, CA2, CA3, CA4, CA5, CA6, - - DPSEG, rVcs, rVds, // virtual registers for code and data segments -}; - -//------------------------------------------------------------------ -// Bit definitions. -// Note that the bit order is unusual: the LSB is BIT31 -// This is a so-called big-endian bit order. -#define BIT31 0x00000001L -#define BIT30 0x00000002L -#define BIT29 0x00000004L -#define BIT28 0x00000008L -#define BIT27 0x00000010L -#define BIT26 0x00000020L -#define BIT25 0x00000040L -#define BIT24 0x00000080L -#define BIT23 0x00000100L -#define BIT22 0x00000200L -#define BIT21 0x00000400L -#define BIT20 0x00000800L -#define BIT19 0x00001000L -#define BIT18 0x00002000L -#define BIT17 0x00004000L -#define BIT16 0x00008000L -#define BIT15 0x00010000L -#define BIT14 0x00020000L -#define BIT13 0x00040000L -#define BIT12 0x00080000L -#define BIT11 0x00100000L -#define BIT10 0x00200000L -#define BIT9 0x00400000L -#define BIT8 0x00800000L -#define BIT7 0x01000000L -#define BIT6 0x02000000L -#define BIT5 0x04000000L -#define BIT4 0x08000000L -#define BIT3 0x10000000L -#define BIT2 0x20000000L -#define BIT1 0x40000000L -#define BIT0 0x80000000L - -//------------------------------------------------------------------ -ea_t calc_mem(ea_t ea); // map virtual to phisycal ea - -typedef int proc_t; -const proc_t PROC_HPPA = 0; // HPPA big endian - -//------------------------------------------------------------------ -void interr(const insn_t &insn, const char *module); - -void idaapi hppa_header(outctx_t &ctx); - -void idaapi hppa_segend(outctx_t &ctx, segment_t *seg); - -int idaapi is_align_insn(ea_t ea); -int idaapi hppa_get_frame_retsize(const func_t *); - -int idaapi is_sp_based(const insn_t &insn, const op_t &x); -int is_sane_insn(const insn_t &insn, int nocrefs); -int may_be_func(const insn_t &insn); // can a function start here? -bool is_basic_block_end(const insn_t &insn); - -//-------------------------------------------------------------------------- -// functions to get various fields from the instruction code -inline int opcode(uint32 code) { return (code>>26) & 0x3F; } -inline int r06(uint32 code) { return (code>>21) & 0x1F; } -inline int r11(uint32 code) { return (code>>16) & 0x1F; } -inline int r22(uint32 code) { return (code>> 5) & 0x1F; } -inline int r27(uint32 code) { return (code>> 0) & 0x1F; } -inline int get11(uint32 code) // 11bit field for branches -{ - return ((code>>3) & 0x3FF) | ((code&4)<<(10-2)); -} -inline int32 get17(uint32 code) -{ - return ((code&1) << 16) - | (r11(code) << 11) - | get11(code); -} -inline sval_t as21(uint32 x) -{ - // 1 2 - // 012345678901234567890 bit number - // 2 1 - // 098765432109876543210 shift amount - x = (((x>>12) & 0x003) << 0) // 2: x{7..8} - | (((x>>16) & 0x01F) << 2) // 5: x{0..4} - | (((x>>14) & 0x003) << 7) // 2: x{5..6} - | (((x>> 1) & 0x7FF) << 9) // 11: x{9..19} - | (((x>> 0) & 0x001) <<20); // 1: x{20} - return int32(x << 11); -} -//-------------------------------------------------------------------------- -// type system functions -bool calc_hppa_arglocs(func_type_data_t *fti); -int use_hppa_regarg_type(ea_t ea, const funcargvec_t &rargs); -void use_hppa_arg_types( - ea_t ea, - func_type_data_t *fti, - funcargvec_t *rargs); - -//-------------------------------------------------------------------------- -struct hppa_cf_t; -struct hppa_t : public procmod_t -{ - netnode helper; // altval(-1) -> idpflags - // altval(ea) -> function frame register or 0 - inline void save_idpflags() { helper.altset(-1, idpflags); } - - ioports_t syscalls; - -#define IDP_SIMPLIFY 0x0001 // simplify instructions -#define IDP_PSW_W 0x0002 // W-bit in PSW is set -#define IDP_MNEMONIC 0x0004 // use mnemonic register names - ushort idpflags = IDP_SIMPLIFY; - inline bool dosimple(void) { return (idpflags & IDP_SIMPLIFY) != 0; } - inline bool psw_w(void) { return (idpflags & IDP_PSW_W) != 0; } - inline bool mnemonic(void) { return (idpflags & IDP_MNEMONIC) != 0; } - inline int assemble_16(int x, int y) - { - if ( psw_w() ) - { - int r = 0; - if ( y & 1 ) - { - x ^= 3; - r = 0x8000; - } - return ((y>>1) & 0x1FFF) | (x<<13) | r; - } - return ((y>>1) & 0x1FFF) | ((y&1) ? 0xE000 : 0); - } - inline int get_ldo(uint32 code) { return assemble_16((code>>14)&3,code & 0x3FFF); } - - int ptype = 0; // processor type - ea_t got = BADADDR; - // custom fixups and refinfo - hppa_cf_t *hppa_cf = nullptr; - - bool flow = false; - ea_t oldea = BADADDR; - int oldreg = -1; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *get_syscall_name(int syscall); - const char *set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - void handle_new_flags(void); - void init_custom_refs(); - void term_custom_refs(); - void setup_got(void); - int ana(insn_t *_insn); - int emu(const insn_t &insn); - bool is_frreg(const insn_t &insn, int reg); - void process_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload); - void trace_sp(const insn_t &insn); - bool create_func_frame(func_t *pfn); - void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); - ea_t get_dp(const insn_t &insn) const; - ea_t calc_possible_memref(const insn_t &insn, const op_t &x); - uval_t idaapi r11_get_value(const fixup_handler_t * /*fh*/, ea_t ea); - char *build_insn_completer(const insn_t &insn, uint32 code, char *buf, size_t bufsize); - void hppa_assumes(outctx_t &ctx); // function to produce assume directives - void hppa_segstart(outctx_t &ctx, segment_t *Srange) const; - void hppa_footer(outctx_t &ctx) const; - void use_hppa_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs); -}; -extern int data_id; - -#endif // _HPPA_HPP diff --git a/idasdk75/module/hppa/hppa_cfh.cpp b/idasdk75/module/hppa/hppa_cfh.cpp deleted file mode 100644 index 20dfb56..0000000 --- a/idasdk75/module/hppa/hppa_cfh.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -// This file contains custom fixup handlers for simplified fixups with high -// and low parts. The word "simplified" means that we don't use LR and RR -// rounding modes as prescribed in the documentation. We replace them by " -// and R rounding modes. -// They are used for the relocations: -// - R_PARISC_DIR21L, R_PARISC_DPREL21L -// - R_PARISC_DIR14R, R_PARISC_DPREL14R - -#include <fixup.hpp> - -//-------------------------------------------------------------------------- -static uval_t idaapi l21_get_value(const fixup_handler_t * /*fh*/, ea_t ea) -{ - uint32 insn = get_dword(ea); - // extract `im21' from "Long immediate" instruction - return as21(insn); -} - -//---------------------------------------------------------------------------- -static bool idaapi l21_patch_value( - const fixup_handler_t * /*fh*/, - ea_t ea, - const fixup_data_t &fd) -{ - uint32 insn = get_dword(ea); - ea_t expr = fd.off + fd.displacement; - // 33222222222211111111110000000000 - // 10987654321098765432109876543210 - // abbbbbbbbbbbccdddddee___________ expr - // ___________dddddcceebbbbbbbbbbba insn - // 10987654321098765432109876543210 - uint32 im21 = (((expr >> 31) & 0x001) << 0) // a - | (((expr >> 20) & 0x7FF) << 1) // b - | (((expr >> 18) & 0x003) << 14) // c - | (((expr >> 13) & 0x01F) << 16) // d - | (((expr >> 11) & 0x003) << 12); // e - put_dword(ea, (insn & 0xFFE00000) | im21); - return true; -} - -//-------------------------------------------------------------------------- -static bool idaapi l21_calc_reference_data( - ea_t *target, - ea_t *base, - ea_t /*from*/, - const refinfo_t &ri, - adiff_t opval) -{ - if ( ri.target == BADADDR - || ri.base == BADADDR - || ri.is_subtract() ) - { - return false; - } - ea_t fullvalue = ri.target + ri.tdelta - ri.base; - uint32 calc_opval = fullvalue & 0xFFFFF800; - if ( calc_opval != uint32(opval) ) - return false; - - *target = ri.target; - *base = ri.base; - return true; -} - -//-------------------------------------------------------------------------- -static void idaapi l21_get_format(qstring *format) -{ - *format = COLSTR("l%%%s", SCOLOR_KEYWORD); -} - -//-------------------------------------------------------------------------- -static const custom_refinfo_handler_t ref_l21 = -{ - sizeof(custom_refinfo_handler_t), - "L21", - "right-justified, high-order 21 bits", - 0, // properties (currently 0) - NULL, // gen_expr - l21_calc_reference_data, // calc_reference_data - l21_get_format, // get_format -}; - - -//-------------------------------------------------------------------------- -// we use the R rounding mode (11-bit) in this fixup -// but here we return the full immediated value (14-bit or 16-bit) -static uval_t idaapi r11_get_value(const fixup_handler_t * /*fh*/, ea_t ea) -{ - hppa_t &pm = *GET_MODULE_DATA(hppa_t); - uint32 insn = get_dword(ea); - // extract `im14' from "Load/Store" instruction - return sval_t(int16(pm.get_ldo(insn))); -} - -//---------------------------------------------------------------------------- -static bool idaapi r11_patch_value( - const fixup_handler_t * /*fh*/, - ea_t ea, - const fixup_data_t &fd) -{ - hppa_t &pm = *GET_MODULE_DATA(hppa_t); - uint32 insn = get_dword(ea); - // we use the R rounding mode (11-bit) in this fixup - ea_t expr = (fd.off + fd.displacement) & 0x7FF; - if ( pm.psw_w() ) - { - // 33222222222211111111110000000000 - // 10987654321098765432109876543210 - // ________________abbccccccccccccc expr - // ________________BBccccccccccccca insn - // 10987654321098765432109876543210 - // B = a == 0 ? b : ~b; - uint32 a = (expr >> 15) & 0x0001; - uint32 b = (expr >> 13) & 0x0003; - if ( a != 0 ) //-V547 'a != 0' is always false - b = ~b; - uint32 c = expr & 0x1FFF; - uint32 im16 = a | (b << 14) | (c << 1); - put_dword(ea, (insn & 0xFFFF0000) | im16); - } - else - { - // 33222222222211111111110000000000 - // 10987654321098765432109876543210 - // __________________abbbbbbbbbbbbb expr - // __________________bbbbbbbbbbbbba insn - // 10987654321098765432109876543210 - uint32 im14 = (((expr >> 13) & 0x0001) << 0) // a - | ((expr & 0x1FFF) << 1); // b - put_dword(ea, (insn & 0xFFFFC000) | im14); - } - return true; -} - -//-------------------------------------------------------------------------- -static bool idaapi r11_calc_reference_data( - ea_t *target, - ea_t *base, - ea_t /*from*/, - const refinfo_t &ri, - adiff_t opval) -{ - if ( ri.target == BADADDR - || ri.base == BADADDR - || ri.is_subtract() ) - { - return false; - } - ea_t fullvalue = ri.target + ri.tdelta - ri.base; - uint32 calc_opval = fullvalue & 0x7FF; - if ( calc_opval != uint32(opval) ) - return false; - - *target = ri.target; - *base = ri.base; - return true; -} - -//-------------------------------------------------------------------------- -static void idaapi r11_get_format(qstring *format) -{ - *format = COLSTR("r%%%s", SCOLOR_KEYWORD); -} - -//-------------------------------------------------------------------------- -static const custom_refinfo_handler_t ref_r11 = -{ - sizeof(custom_refinfo_handler_t), - "R11", - "low-order 11 bits", - 0, // properties (currently 0) - NULL, // gen_expr - r11_calc_reference_data, // calc_reference_data - r11_get_format, // get_format -}; - -//-------------------------------------------------------------------------- -struct hppa_cf_t -{ - fixup_handler_t cfh_l21 = - { - sizeof(fixup_handler_t), - "L21", // name - FHF_CODE // verify that fixup points to code - | FHF_FORCE_CODE, // convert unknonw item to code - 4, 0, 0, 0, // size, width, shift - REFINFO_CUSTOM, // reftype - NULL, // apply - l21_get_value, // get_value - l21_patch_value, // patch_value - }; - - fixup_handler_t cfh_r11 = - { - sizeof(fixup_handler_t), - "R11", // name - FHF_CODE // verify that fixup points to code - | FHF_FORCE_CODE, // convert unknonw item to code - 4, 0, 0, 0, // size, width, shift - REFINFO_CUSTOM, // reftype - NULL, // apply - r11_get_value, // get_value - r11_patch_value, // patch_value - }; - - fixup_type_t cfh_l21_id = 0; // ids of fixup handlers - fixup_type_t cfh_r11_id = 0; - int ref_l21_id = 0; // ids of refinfo handlers - int ref_r11_id = 0; -}; - -//-------------------------------------------------------------------------- -void hppa_t::init_custom_refs() -{ - if ( hppa_cf == nullptr ) - { - hppa_cf = new hppa_cf_t; - hppa_cf->cfh_l21_id = register_custom_fixup(&hppa_cf->cfh_l21); - hppa_cf->cfh_r11_id = register_custom_fixup(&hppa_cf->cfh_r11); - hppa_cf->ref_l21_id = register_custom_refinfo(&ref_l21); - hppa_cf->ref_r11_id = register_custom_refinfo(&ref_r11); - hppa_cf->cfh_l21.reftype = REFINFO_CUSTOM | hppa_cf->ref_l21_id; - hppa_cf->cfh_r11.reftype = REFINFO_CUSTOM | hppa_cf->ref_r11_id; - } -} - -//-------------------------------------------------------------------------- -void hppa_t::term_custom_refs() -{ - if ( hppa_cf != nullptr ) - { - hppa_cf->cfh_l21.reftype = REFINFO_CUSTOM; - hppa_cf->cfh_r11.reftype = REFINFO_CUSTOM; - unregister_custom_refinfo(hppa_cf->ref_r11_id); - unregister_custom_refinfo(hppa_cf->ref_l21_id); - unregister_custom_fixup(hppa_cf->cfh_r11_id); - unregister_custom_fixup(hppa_cf->cfh_l21_id); - delete hppa_cf; - hppa_cf = nullptr; - } -} diff --git a/idasdk75/module/hppa/ins.hpp b/idasdk75/module/hppa/ins.hpp deleted file mode 100644 index 6ea80a7..0000000 --- a/idasdk75/module/hppa/ins.hpp +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ -HPPA_null = 0, // Unknown Operation - -HPPA_add, // Add -HPPA_addb, // Add and Branch -HPPA_addi, // Add to Immediate -HPPA_addib, // Add Immediate and Branch -HPPA_addil, // Add to Immediate Left -HPPA_and, // AND -HPPA_andcm, // AND complement -HPPA_b, // Branch -HPPA_bb, // Branch on Bit -HPPA_be, // Branch External -HPPA_blr, // Branch and Link Register -HPPA_break, // Break -HPPA_bv, // Branch Vectored -HPPA_bve, // Branch Vectored External -HPPA_cldd, // Coprocessor Load Doubleword -HPPA_cldw, // Coprocessor Load Word -HPPA_clrbts, // Clear Branch Target Stack -HPPA_cmpb, // Compare and Branch -HPPA_cmpclr, // Compare and Clear -HPPA_cmpib, // Compare Immediate and Branch -HPPA_cmpiclr, // Compare Immediate and Clear -HPPA_copr, // Coprocessor Operation -HPPA_cstd, // Coprocessor Store Doubleword -HPPA_cstw, // Coprocessor Store Word -HPPA_dcor, // Decimal Correct -HPPA_depd, // Deposit Doubleword -HPPA_depdi, // Deposit Doubleword Immediate -HPPA_depw, // Deposit Word -HPPA_depwi, // Deposit Word Immediate -HPPA_diag, // Diagnose -HPPA_ds, // Divide Step -HPPA_extrd, // Extract Doubleword -HPPA_extrw, // Extract Word -HPPA_fdc, // Flush Data Cache -HPPA_fdce, // Flush Data Cache Entry -HPPA_fic, // Flush Instruction Cache -HPPA_fice, // Flush Instruction Cache Entry -HPPA_hadd, // Halfword Parallel Add -HPPA_havg, // Halfword Parallel Average -HPPA_hshl, // Halfword Parallel Shift Left -HPPA_hshladd, // Halfword Parallel Shift Left and Add -HPPA_hshr, // Halfword Parallel Shift Right -HPPA_hshradd, // Halfword Parallel Shift Right and Add -HPPA_hsub, // Halfword Parallel Subtract -HPPA_idtlbt, // Insert Data TLB Translation -HPPA_iitlbt, // Insert Instruction TLB Translation -HPPA_lci, // Load Coherence Index -HPPA_ldb, // Load Byte -HPPA_ldcd, // Load and Clear Doubleword -HPPA_ldcw, // Load and Clear Word -HPPA_ldd, // Load Doubleword -HPPA_ldda, // Load Doubleword Absolute -HPPA_ldh, // Load Halfword -HPPA_ldil, // Load Immediate Left -HPPA_ldo, // Load Offset -HPPA_ldsid, // Load Space Identifier -HPPA_ldw, // Load Word -HPPA_ldwa, // Load Word Absolute -HPPA_lpa, // Load Physical Address -HPPA_mfctl, // Move From Control Register -HPPA_mfia, // Move From Instruction Address -HPPA_mfsp, // Move From Space Register -HPPA_mixh, // Mix Halfwords -HPPA_mixw, // Mix Words -HPPA_movb, // Move and Branch -HPPA_movib, // Move Immediate and Branch -HPPA_mtctl, // Move To Control Register -HPPA_mtsarcm, // Move To Shift Amount Register Complement -HPPA_mtsm, // Move To System Mask -HPPA_mtsp, // Move To Space Register -HPPA_or, // Inclusive OR -HPPA_pdc, // Purge Data Cache -HPPA_pdtlb, // Purge Data TLB -HPPA_pdtlbe, // Purge Data TLB Entry -HPPA_permh, // Permute Halfwords -HPPA_pitlb, // Purge Instruction TLB -HPPA_pitlbe, // Purge Instruction TLB Entry -HPPA_popbts, // Pop Branch Target Stack -HPPA_probe, // Probe Access -HPPA_probei, // Probe Access Immediate -HPPA_pushbts, // Push Branch Target Stack -HPPA_pushnom, // Push Nominated -HPPA_rfi, // Return From Interruption -HPPA_rsm, // Reset System Mask -HPPA_shladd, // Shift Left and Add -HPPA_shrpd, // Sihft Right Pair Doubleword -HPPA_shrpw, // Sihft Right Pair Word -HPPA_spop0, // Special Operation Zero -HPPA_spop1, // Special Operation One -HPPA_spop2, // Special Operation Two -HPPA_spop3, // Special Operation Three -HPPA_ssm, // Set System Mask -HPPA_stb, // Store Byte -HPPA_stby, // Store Bytes -HPPA_std, // Store Doubleword -HPPA_stda, // Store Doubleword Absolute -HPPA_stdby, // Store Doubleword Bytes -HPPA_sth, // Store Halfword -HPPA_stw, // Store Word -HPPA_stwa, // Store Word Absolute -HPPA_sub, // Subtract -HPPA_subi, // Subtract from Immediate -HPPA_sync, // Synchronize Caches -HPPA_syncdma, // Synchronize DMA -HPPA_uaddcm, // Unit Add Complement -HPPA_uxor, // Unit XOR -HPPA_xor, // Exclusive OR - -// Floating point instructions - -HPPA_fabs, // Floating-Point Absolute Value -HPPA_fadd, // Floating-Point Add -HPPA_fcmp, // Floating-Point Compare -HPPA_fcnv, // Floating-Point Convert -HPPA_fcpy, // Floating-Point Copy -HPPA_fdiv, // Floating-Point Divide -HPPA_fid, // Floating-Point Identity -HPPA_fldd, // Floating-Point Load Doubleword -HPPA_fldw, // Floating-Point Load Word -HPPA_fmpy, // Floating-Point Multiply -HPPA_fmpyadd, // Floating-Point Multiply/Add -HPPA_fmpyfadd, // Floating-Point Multiply Fused Add -HPPA_fmpynfadd, // Floating-Point Multiply Negate Fused Add -HPPA_fmpysub, // Floating-Point Multiply/Subtract -HPPA_fneg, // Floating-Point Negate -HPPA_fnegabs, // Floating-Point Negate Absolute Value -HPPA_frem, // Floating-Point Remainder -HPPA_frnd, // Floating-Point Round to Integer -HPPA_fsqrt, // Floating-Point Square Root -HPPA_fstd, // Floating-Point Store Doubleword -HPPA_fstw, // Floating-Point Store Word -HPPA_fsub, // Floating-Point Subtract -HPPA_ftest, // Floating-Point Test -HPPA_xmpyu, // Fixed-Point Multiply Unsigned - -// Performance Monitor Coprocessor - -HPPA_pmdis, // Performance Monitor Disable -HPPA_pmenb, // Performance Monitor Enable - -// Macros - -HPPA_call, // Call Subroutine -HPPA_ret, // Return From Subroutine -HPPA_shld, // Shift Left Doubleword -HPPA_shlw, // Shift Left Word -HPPA_shrd, // Shift Right Doubleword -HPPA_shrw, // Shift Right Word -HPPA_ldi, // Load Immediate -HPPA_copy, // Copy Register -HPPA_mtsar, // Move To %SAR -HPPA_nop, // No Operation - -HPPA_last, - -}; - -#endif diff --git a/idasdk75/module/hppa/makefile b/idasdk75/module/hppa/makefile deleted file mode 100644 index 16b1659..0000000 --- a/idasdk75/module/hppa/makefile +++ /dev/null @@ -1,48 +0,0 @@ -PROC=hppa -CONFIGS=hpux.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fixup.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ana.cpp hppa.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fixup.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp hppa.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fixup.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp hppa.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fixup.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp hppa.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fixup.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)typeinf.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp hppa.hpp \ - hppa_cfh.cpp ins.hpp notify_codes.hpp reg.cpp diff --git a/idasdk75/module/hppa/notify_codes.hpp b/idasdk75/module/hppa/notify_codes.hpp deleted file mode 100644 index b7d2e33..0000000 --- a/idasdk75/module/hppa/notify_codes.hpp +++ /dev/null @@ -1,31 +0,0 @@ - -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ -#pragma once - -#include <idp.hpp> - -//---------------------------------------------------------------------- -// The following events are supported by the PPC module in the ph.notify() function -namespace hppa_module_t -{ - enum event_codes_t - { - ev_dummy = processor_t::ev_loader, // was used before - ev_is_psw_w, // W-bit in PSW is set - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline bool is_psw_w() - { - return processor_t::notify(idp_ev(ev_is_psw_w)) == 1; - } -} diff --git a/idasdk75/module/hppa/out.cpp b/idasdk75/module/hppa/out.cpp deleted file mode 100644 index 89fe49b..0000000 --- a/idasdk75/module/hppa/out.cpp +++ /dev/null @@ -1,1304 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "hppa.hpp" - -//-------------------------------------------------------------------------- -struct cond_text_t -{ - const char *text; - char c; // -1 means any value - char f; // -1 means any value -}; - -static const cond_text_t D3[] = // and D4 combined -{ // c f - { "", 0, 0 }, // never - { "=", 1, 0 }, // op1 is equal to op2 (word) - { "<", 2, 0 }, // op1 is less than op2 (signed word) - { "<=", 3, 0 }, // op1 is less than or equal to op2 (signed word) - { "<<", 4, 0 }, // op1 is less than op2 (unsigned word) - { "<<=", 5, 0 }, // op1 is less than or equal to op2 (unsigned word) - { "sv", 6, 0 }, // op1 minus op2 overflows (signed word) - { "od", 7, 0 }, // op1 minus op2 is odd - { "tr", 0, 1 }, // always - { "<>", 1, 1 }, // op1 is not equal to op2 (word) - { ">=", 2, 1 }, // op1 is greater than or equal to op2 (signed word) - { ">", 3, 1 }, // op1 is greater than op2 (signed word) - { ">>=", 4, 1 }, // op1 is greater than or equal to op2 (unsigned word) - { ">>", 5, 1 }, // op1 is greater than op2 (unsigned word) - { "nsv", 6, 1 }, // op1 minus op2 does not overflow (signed word) - { "ev", 7, 1 }, // op1 minus op2 is even - { NULL }, -}; - -static const cond_text_t D5[] = // f should be 0! -{ // c f - { "*<<", 0, 0 }, // op1 is less than op2 (unsigned doubleword) - { "*=", 1, 0 }, // op1 is equal to op2 (doubleword) - { "*<", 2, 0 }, // op1 is less than op2 (signed doubleword) - { "*<=", 3, 0 }, // op1 is less than or equal to op2 (signed doubleword) - { "*>>=", 4, 0 }, // op1 is greater than or equal to op2 (unsigned doubleword) - { "*<>", 5, 0 }, // op1 is not equal to op2 (doubleword) - { "*>=", 6, 0 }, // op1 is greater than or equal to op2 (signed doubleword) - { "*>", 7, 0 }, // op1 is greater than op2 (signed doubleword) - { NULL }, -}; - -static const cond_text_t D6[] = // and D7 combined -{ // c f - { "", 0, 0 }, // never - { "=", 1, 0 }, // op1 is equal to negative of op2 (word) - { "<", 2, 0 }, // op1 is less than negative of op2 (signed word) - { "<=", 3, 0 }, // op1 is less than or equal to negative of op2 (signed word) - { "nuv", 4, 0 }, // op1 plus op2 does not overflow (unsigned word) - { "znv", 5, 0 }, // op1 plus op2 is zero or no overflow (unsigned word) - { "sv", 6, 0 }, // op1 plus op2 overflows (signed word) - { "od", 7, 0 }, // op1 plus op2 is odd - { "tr", 0, 1 }, // always - { "<>", 1, 1 }, // op1 is not equal to negative of op2 (word) - { ">=", 2, 1 }, // op1 is greater than or equal to negative of op2 (signed word) - { ">", 3, 1 }, // op1 is greater than negative of op2 (signed word) - { "uv", 4, 1 }, // op1 plus op2 overflows (unsigned word) - { "vnz", 5, 1 }, // op1 plus op2 is nonzero and overflows (unsigned word) - { "nsv", 6, 1 }, // op1 minus op2 does not overflow (signed word) - { "ev", 7, 1 }, // op1 minus op2 is even - { NULL }, -}; - -static const cond_text_t D8[] = // d should be 0! -{ // c f - { "", 0, 0 }, // never - { "=", 1, 0 }, // op1 is equal to negative of op2 (word) - { "<", 2, 0 }, // op1 is less than negative of op2 (signed word) - { "<=", 3, 0 }, // op1 is less than or equal to negative of op2 (signed word) - { "nuv", 4, 0 }, // op1 plus op2 does not overflow (unsigned word) - { "*=", 5, 0 }, // op1 is equal to negative of op2 (doubleword) - { "*<", 6, 0 }, // op1 is less than negative of op2 (signed doubleword) - { "*<=", 7, 0 }, // op1 is less than or equal to negative of op2 (signed doubleword) - { "tr", 0, 1 }, // always - { "<>", 1, 1 }, // op1 is not equal to negative of op2 (word) - { ">=", 2, 1 }, // op1 is greater than or equal to negative of op2 (signed word) - { ">", 3, 1 }, // op1 is greater than negative of op2 (signed word) - { "uv", 4, 1 }, // op1 plus op2 overflows (unsigned word) - { "*<>", 5, 1 }, // op1 is not equal to negative of op2 (doubleword) - { "*>=", 6, 1 }, // op1 is greater than or equal to negative of op2 (signed doubleword) - { "*>", 7, 1 }, // op1 is greater than negative of op2 (signed doubleword) - { NULL }, -}; - -static const cond_text_t D9[] = // and D10 combined -{ // c f - { "", 0, 0 }, // never - { "=", 1, 0 }, // all bits in word are 0 - { "<", 2, 0 }, // leftmost bit in word is 1 - { "<=", 3, 0 }, // leftmost bit in word is 1 or all bits in word are 0 - { "od", 7, 0 }, // rightmost bit is 1 - { "tr", 0, 1 }, // always - { "<>", 1, 1 }, // some bits in word are 1 - { ">=", 2, 1 }, // leftmost bit in word is 0 - { ">", 3, 1 }, // leftmost bit in word is 0 and some bits in word are 1 - { "ev", 7, 1 }, // rightmost bit is 0 -}; - - -static const cond_text_t D11[] = // and D12 combined -{ // c f - { "", 0, 0 }, // never - { "swz", 1, 0 }, // 64! some word zero - { "sbz", 2, 0 }, // some byte zero - { "shz", 3, 0 }, // some halfword zero - { "sdc", 4, 0 }, // some digit carry - { "swc", 5, 0 }, // 64! some word carry - { "sbc", 6, 0 }, // some byte carry - { "shc", 7, 0 }, // some halfword carry - { "tr", 0, 1 }, // always - { "nwz", 1, 1 }, // 64! no word zero - { "nbz", 2, 1 }, // no byte zero - { "nhz", 3, 1 }, // no halfword zero - { "ndc", 4, 1 }, // no digit carry - { "nwc", 5, 1 }, // 64! no word carry - { "nbc", 6, 1 }, // no byte carry - { "nhc", 7, 1 }, // no halfword carry -}; - - -static const cond_text_t D13[] = // and D14 combined (f should be 0) -{ // c f - { "", 0, 0 }, // never - { "=", 1, 0 }, // all bits in word are 0 - { "<", 2, 0 }, // leftmost bit in word is 1 - { "od", 3, 0 }, // rightmost bit is 1 - { "tr", 4, 0 }, // always - { "<>", 5, 0 }, // some bits in word are 1 - { ">=", 6, 0 }, // leftmost bit in word is 0 - { "ev", 7, 0 }, // rightmost bit is 0 -}; - -static const cond_text_t D15[] = // (f should be 0) -{ // c f - { "<", 0, 0 }, // leftmost bit in word is 1 - { ">=", 1, 0 }, // leftmost bit in word is 0 -}; - -static char *append_conds( - const cond_text_t *table, - int c, - int f, - int d, - char *ptr, - char *end) -{ - if ( !d && table == D11 && (c == 1 || c == 5) ) - return NULL; - while ( table->text != NULL ) - { - if ( table->c == c && table->f == f ) - { - if ( table->text[0] != '\0' ) - { - APPCHAR(ptr, end, ','); - if ( d != 0 ) - APPCHAR(ptr, end, '*'); - APPEND(ptr, end, table->text); - } - return ptr; - } - table++; - } - return NULL; -} - -//-------------------------------------------------------------------------- -// short displacement load and store instruction completers -static const char *h1_comp(int a, int m, int im5) -{ - if ( m ) - { - if ( a ) - return ",mb"; // a=1 m=1 - return im5 - ? ",ma" // a=0 m=1 im5 != 0 - : ",o"; // a=0 m=1 im5 == 0 - } - return ""; // m=0 -} - -//-------------------------------------------------------------------------- -// store bytes instruction completers -static const char *h2_comp(int a, int m) -{ - static const char *const suffixes[] = - { - "", // beginning case, don't modify base register - ",b,m", // beginning case, modify base register - ",e", // ending case, don't modify base register - ",e,m" // ending case, modify base register - }; - int idx = (a<<1) | m; - return suffixes[idx & 3]; -} - -//-------------------------------------------------------------------------- -// indexed instruction completers -static const char *h3_comp(int u, int m) -{ - static const char *const suffixes[] = - { - "", // no index shift, don't modify base register - ",m", // no index shift, modify base register - ",s", // shift index by data size, don't modify base register - ",sm" // shift index by data size, modify base register - }; - int idx = (u<<1) | m; - return suffixes[idx & 3]; -} - -//-------------------------------------------------------------------------- -static char *append_cc(char *ptr, const char *end, int cc, bool isload) -{ - static const char *const ld_suffixes[] = { "", NULL, ",sl", NULL }; - static const char *const st_suffixes[] = { "", ",bc", ",sl", NULL }; - const char *comp = (isload ? ld_suffixes : st_suffixes)[cc]; - if ( comp == NULL ) - return NULL; - APPEND(ptr, end, comp); - return ptr; -} - -//-------------------------------------------------------------------------- -static char *ldst_short(const insn_t &insn, uint32 code, char *ptr, const char *end) -{ - int cc = (code>>10) & 3; - int m = (code & BIT26) ? 1 : 0; - int a = (code & BIT18) ? 1 : 0; - const char *comp; - if ( code & BIT19 ) - { - int im5 = (code>>16) & 0x1F; - comp = h1_comp(a, m, im5); - } - else - { - int u = a; - comp = h3_comp(u, m); - } - bool isload; - switch ( insn.itype ) - { - default: - INTERR(10125); //-V796 no break - case HPPA_cldd: - case HPPA_cldw: - case HPPA_ldb: - case HPPA_ldcd: - case HPPA_ldcw: - case HPPA_ldd: - case HPPA_ldda: - case HPPA_ldh: - case HPPA_ldw: - case HPPA_ldwa: - case HPPA_fldd: - case HPPA_fldw: - isload = true; - break; - case HPPA_stby: - case HPPA_stdby: - comp = h2_comp(a, m); - // no break - case HPPA_cstd: - case HPPA_cstw: - case HPPA_stb: - case HPPA_std: - case HPPA_stda: - case HPPA_sth: - case HPPA_stw: - case HPPA_stwa: - case HPPA_fstd: - case HPPA_fstw: - isload = false; - break; - } - APPEND(ptr, end, comp); - ptr = append_cc(ptr, end, cc, isload); - return ptr; -} - -//-------------------------------------------------------------------------- -static const char *const fpp_comp[] = -{ - "false?", // 0 - "false", // 1 - "?", // 2 - "!<=>", // 3 - "=", // 4 - "=T", // 5 - "?=", // 6 - "!<>", // 7 - "!?>=", // 8 - "<", // 9 - "?<", // 10 - "!>=", // 11 - "!?>", // 12 - "<=", // 13 - "?<=", // 14 - "!>", // 15 - "!?<=", // 16 - ">", // 17 - "?>", // 18 - "!<=", // 19 - "!?<", // 20 - ">=", // 21 - "?>=", // 22 - "!<", // 23 - "!?=", // 24 - "<>", // 25 - "!=", // 26 - "!=T", // 27 - "!?", // 28 - "<=>", // 29 - "true?", // 30 - "true", // 31 -}; - -static const char *const fpp_test[] = -{ - "", // 0 - "acc", // 1 - ",rej", // 2 - NULL, // 3 - NULL, // 4 - ",acc8", // 5 - ",rej8", // 6 - NULL, // 7 - NULL, // 8 - ",acc6", // 9 - NULL, // 10 - NULL, // 11 - NULL, // 12 - ",acc4", // 13 - NULL, // 14 - NULL, // 15 - NULL, // 16 - ",acc2", // 17 - NULL, // 18 - NULL, // 19 - NULL, // 20 - NULL, // 21 - NULL, // 22 - NULL, // 23 - NULL, // 24 - NULL, // 25 - NULL, // 26 - NULL, // 27 - NULL, // 28 - NULL, // 29 - NULL, // 30 - NULL, // 31 -}; - -static const char *const fpp_sngop[] = -{ - "", // 0 or sgl - ",dbl", // 1 - NULL, // 2 - ",quad", // 3 -}; - -//-------------------------------------------------------------------------- -inline char *append_fmt(int fmt, char *ptr, const char *end) -{ - if ( fmt == 2 || fmt > 3 ) - return NULL; - APPEND(ptr, end, fpp_sngop[fmt]); - return ptr; -} - -//-------------------------------------------------------------------------- -char *hppa_t::build_insn_completer(const insn_t &insn, uint32 code, char *buf, size_t bufsize) -{ - char *ptr = buf; - char *const end = buf + bufsize; - switch ( insn.itype ) - { - case HPPA_ldo: // format 1 (special case) - case HPPA_ldi: // pseudo-op - case HPPA_nop: // pseudo-op - case HPPA_copy: // pseudo-op (ldo or or) - break; - - case HPPA_ldb: // formats 1-5 - case HPPA_ldcd: - case HPPA_ldcw: - case HPPA_ldd: - case HPPA_ldda: - case HPPA_ldh: - case HPPA_ldw: - case HPPA_ldwa: - case HPPA_stb: - case HPPA_stby: - case HPPA_std: - case HPPA_stda: - case HPPA_stdby: - case HPPA_sth: - case HPPA_stw: - case HPPA_stwa: - case HPPA_fldd: - case HPPA_fldw: - case HPPA_fstd: - case HPPA_fstw: - switch ( opcode(code) ) - { - case 0x10: // format 1 - case 0x11: - case 0x12: - case 0x18: - case 0x19: - case 0x1A: - case 0x17: // format 2 - case 0x1F: - // nothing to do - break; - case 0x13: // ldw (mod) - case 0x1B: // stw (mod) - { - sval_t off = insn.itype == HPPA_ldw ? insn.Op1.addr : insn.Op2.addr; - APPEND(ptr, end, off < 0 ? ",mb" : ",ma"); - } - break; - case 0x14: // format 3 - case 0x1C: - { - int m = (code & BIT28) ? 1 : 0; - int a = (code & BIT29) ? 1 : 0; - int im10a = ((code >> 3) & 0x7FE) | (code & 1); - APPEND(ptr, end, h1_comp(a, m, im10a)); - } - break; - case 0x16: // format 44 (fldw) - case 0x1E: // format 44 (fstw) - { - int m = 0; - int a = (code & BIT29) ? 1 : 0; - int im11a = ((code >> 2) & 0xFFE) | (code & 1); - APPEND(ptr, end, h1_comp(a, m, im11a)); - } - break; - case 0x03: // formats 4 & 5 - case 0x09: // formats 39 & 41 - case 0x0B: // formats 39 & 41 - ptr = ldst_short(insn, code, ptr, end); - break; - default: - interr(insn, "format1"); - } - break; - - case HPPA_addil: // format 7 - case HPPA_ldil: - break; - - case HPPA_hadd: // format 8 (special case) - case HPPA_hsub: - { - int sat = (code>>6) & 3; - static const char *const suffixes[4] = { ",us", ",ss", NULL, "" }; - if ( sat == 2 ) - return NULL; - APPEND(ptr, end, suffixes[sat]); - } - case HPPA_havg: // format 8 (special case2) - case HPPA_hshladd: - case HPPA_hshradd: - break; - - case HPPA_add: // format 8 - case HPPA_and: - case HPPA_andcm: - case HPPA_cmpclr: - case HPPA_dcor: - case HPPA_ds: - case HPPA_or: - case HPPA_shladd: - case HPPA_sub: - case HPPA_uaddcm: - case HPPA_uxor: - case HPPA_xor: - { - int c = (code>>13) & aux_cndc; - int f = (code & BIT19) ? 1 : 0; //aux_cndf - int d = (code & BIT26) ? 1 : 0; //aux_cndd - const cond_text_t *table = NULL; - switch ( insn.itype ) - { - case HPPA_cmpclr: - case HPPA_ds: - table = D3; - break; - case HPPA_add: - case HPPA_shladd: - { - int e1 = (code>>10) & 3; - int e2 = (code & BIT23) ? 1 : 0; - if ( !e1 ) - return NULL; - if ( e1 == 2 && e2 ) - return NULL; // not defined - if ( e2 ) - APPEND(ptr, end, d ? ",dc" : ",c"); - static const char *const suffixes[4] = { "", "", ",l", ",tsv" }; - APPEND(ptr, end, suffixes[e1]); - } - table = D6; - break; - case HPPA_sub: - { - int e1 = (code>>10) & 3; - int e2 = (code & BIT23) ? 1 : 0; - int e3 = (code>> 6) & 3; - if ( e1 != 1 && e1 != 3 ) - return NULL; - if ( e3 != 0 && e3 != 3 ) - return NULL; - if ( e2 && e3 ) - return NULL; - if ( e2 ) - APPEND(ptr, end, d ? ",db" : ",b"); - if ( e3 ) - APPEND(ptr, end, ",tc"); - if ( e1 == 3 ) - APPEND(ptr, end, ",tsv"); - } - table = D3; - break; - case HPPA_or: - case HPPA_and: - case HPPA_andcm: - case HPPA_xor: - table = D9; - break; - case HPPA_uaddcm: - { - int e1 = (code>>6) & 3; - if ( e1 != 2 && e1 != 3 ) - return NULL; - if ( e1 == 3 ) - APPEND(ptr, end, ",tc"); - } - table = D11; - break; - case HPPA_dcor: - { - int e1 = (code>>6) & 3; - if ( e1 != 2 && e1 != 3 ) - return NULL; - if ( e1 == 3 ) - APPEND(ptr, end, ",i"); - } - table = D11; - break; - case HPPA_uxor: - table = D11; - if ( c > 3 ) - return NULL; // disable carry conditions - break; - default: - interr(insn, "format8"); - } - ptr = append_conds(table, c, f, d, ptr, end); - } - break; - - case HPPA_addi: // format 9 (special case) - case HPPA_subi: - { - if ( (code & BIT20) != 0 ) - APPEND(ptr, end, ",tsv"); - if ( opcode(code) == 0x2C ) - APPEND(ptr, end, ",tc"); - int c = (code>>13) & 7; - int f = (code & BIT19) ? 1 : 0; - ptr = append_conds(insn.itype == HPPA_subi ? D3 : D6, c, f, 0, ptr, end); - } - break; - - case HPPA_cmpiclr: // format 9 - { - int c = (code>>13) & 7; - int f = (code & BIT19) ? 1 : 0; - int d = (code & BIT20) ? 1 : 0; - ptr = append_conds(D3, c, f, d, ptr, end); - } - break; - - case HPPA_permh: // format 10 - { - int c0 = (code>>13) & 3; - int c1 = (code>>10) & 3; - int c2 = (code>> 8) & 3; - int c3 = (code>> 6) & 3; - ptr += qsnprintf(ptr, end-ptr, ",%d%d%d%d", c0, c1, c2, c3); - } - break; - - case HPPA_mixh: // format 10 - case HPPA_mixw: - { - int ea = (code>>13) & 3; - if ( ea & 1 ) - return NULL; - APPEND(ptr, end, ea ? ",r" : ",l"); - } - break; - - case HPPA_hshr: // format 10 - { - int se = (code>>10) & 3; - if ( se < 2 ) - return NULL; - if ( se == 2 ) - APPEND(ptr, end, ",u"); - } - case HPPA_hshl: // format 10 (special case) - break; - - case HPPA_shrpd: // formats 11 & 14 - case HPPA_shrpw: - ptr = append_conds(D13, (code>>13) & 7, 0, insn.itype == HPPA_shrpd, ptr, end); - break; - - case HPPA_extrd: // formats 12 & 15 - case HPPA_extrw: - case HPPA_shrd: // pseudo-op - case HPPA_shrw: // pseudo-op - if ( (code & BIT21) == 0 ) - APPEND(ptr, end, ",u"); - ptr = append_conds(D13, (code>>13) & 7, 0, insn.itype == HPPA_extrd, ptr, end); - break; - - case HPPA_depd: // formats 13 & 16 - case HPPA_depdi: - case HPPA_depw: - case HPPA_depwi: - case HPPA_shld: // pseudo-op - case HPPA_shlw: // pseudo-op - { - int nz = (code & BIT21) ? 1 : 0; - int c = (code>>13) & 7; - int d = 0; - switch ( insn.itype ) - { - case HPPA_depd: - case HPPA_depdi: - ++d; - case HPPA_depw: - case HPPA_depwi: - break; - default: - interr(insn, "format13"); - } - if ( !nz && insn.itype < HPPA_call ) - APPEND(ptr, end, ",z"); - ptr = append_conds(D13, c, 0, d, ptr, end); - } - break; - - case HPPA_addb: // format 17 - case HPPA_addib: - case HPPA_cmpb: - case HPPA_cmpib: - case HPPA_movb: - case HPPA_movib: - { - int c = (code>>13) & 7; - int f = 0; - const cond_text_t *table = psw_w() ? D8 : D6; - switch ( opcode(code) ) - { - case 0x20: // cmpb - case 0x21: // cmpib - case 0x27: // cmpb - table = D3; - case 0x28: // addb - case 0x29: // addib - break; - case 0x22: // cmpb - case 0x23: // cmpib - case 0x2F: // cmpb - table = D3; - // fallthrough - case 0x2A: // addb - case 0x2B: // addib - ++f; - break; - case 0x32: // movb - case 0x33: // movib - table = D13; - break; - case 0x3B: // cmpib 64 bit - table = D5; - break; - default: - interr(insn, "format17"); - } - ptr = append_conds(table, c, f, 0, ptr, end); - if ( ptr == NULL ) - return NULL; - } - goto NULLIFY; - - case HPPA_bb: // format 18 - { - int c = (code & BIT16) ? 1 : 0; - int d = (code & BIT18) ? 1 : 0; - ptr = append_conds(D15, c, 0, d, ptr, end); - } - goto NULLIFY; - - case HPPA_be: // format 19 - if ( opcode(code) == 0x39 ) - APPEND(ptr, end, ",l"); - goto NULLIFY; - - case HPPA_b: // format 20 - if ( insn.Op2.type != o_void ) - { - int subopcode = (code>>13) & 7; - if ( subopcode >= 6 ) - goto BVE; - static const char *const suffixes[8] = - { - ",l", ",gate", NULL, NULL, - ",push", ",l", NULL, NULL - }; - const char *s = suffixes[subopcode]; - if ( s == NULL ) - return NULL; - APPEND(ptr, end, s); - } - goto NULLIFY; - - case HPPA_blr: // format 21 - case HPPA_bv: - case HPPA_call: // pseudo-op -NULLIFY: - if ( (code & BIT30) != 0 ) - APPEND(ptr, end, ",n"); - break; - - case HPPA_bve: // format 22 - case HPPA_ret: // pseudo-op -BVE: - { - int subopcode = (code>>13) & 7; - if ( subopcode != 6 && subopcode != 7 ) - return NULL; - if ( subopcode == 7 && insn.itype == HPPA_bve ) - APPEND(ptr, end, ",l"); - if ( (code & BIT31) != 0 ) - APPEND(ptr, end, (subopcode == 7) ? ",push" : ",pop"); - } - goto NULLIFY; - - case HPPA_clrbts: // format 23 - case HPPA_popbts: - case HPPA_pushbts: - case HPPA_pushnom: - break; - - case HPPA_pdtlb: // formats 24 & 25 & 26 - case HPPA_pitlb: - if ( (code & BIT21) != 0 ) - APPEND(ptr, end, ",l"); - // no break - case HPPA_fdc: - case HPPA_fdce: - case HPPA_fic: - case HPPA_fice: - case HPPA_lpa: - case HPPA_pdc: - case HPPA_pdtlbe: - case HPPA_pitlbe: - if ( (code & BIT26) != 0 ) - APPEND(ptr, end, ",m"); - case HPPA_lci: // format 24 (special case) - break; - - case HPPA_probe: // format 24 (special case) - case HPPA_probei: - APPEND(ptr, end, (code & BIT25) != 0 ? ",w" : ",r"); - break; - - case HPPA_idtlbt: // format 26 - case HPPA_iitlbt: - break; - - case HPPA_break: // format 27 - break; - - case HPPA_diag: // format 28 - break; - - case HPPA_mfsp: // format 29 - case HPPA_mtsp: - break; - - case HPPA_ldsid: // format 30 - break; - - case HPPA_mtctl: // format 31 - case HPPA_mtsar: // pseudo-op - case HPPA_mtsarcm: - break; - - case HPPA_mfctl: // format 32 - if ( (code & BIT17) != 0 ) - APPEND(ptr, end, ",w"); - case HPPA_mfia: // format 32 (special case) - break; - - case HPPA_rfi: // format 33 - { - int e1 = (code>>5) & 0xF; - if ( e1 != 0 && e1 != 5 ) - return NULL; - if ( e1 == 5 ) - APPEND(ptr, end, ",r"); - } - case HPPA_mtsm: // format 33 - case HPPA_rsm: - case HPPA_ssm: - case HPPA_sync: - case HPPA_syncdma: - break; - - case HPPA_spop0: // format 34 - { - int sfu = (code>> 6) & 7; - int sop1 = (code>>11) & 0x7FFF; - int sop2 = (code>> 0) & 0x1F; - uint32 sop = (sop1 << 5) | sop2; - ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); - ptr += btoa(ptr, end-ptr, sop); - } - goto NULLIFY2; - - case HPPA_spop1: // format 35 - { - int sfu = (code>> 6) & 7; - uint32 sop = (code>>11) & 0x7FFF; - ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); - ptr += btoa(ptr, end-ptr, sop); - } - goto NULLIFY2; - - case HPPA_spop2: // format 36 - { - int sfu = (code>> 6) & 7; - int sop1 = (code>>11) & 0x3FF; - int sop2 = (code>> 0) & 0x1F; - uint32 sop = (sop1 << 5) | sop2; - ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); - ptr += btoa(ptr, end-ptr, sop); - } - goto NULLIFY2; - - case HPPA_spop3: // format 37 - { - int sfu = (code>> 6) & 7; - int sop1 = (code>>11) & 0x1F; - int sop2 = (code>> 0) & 0x1F; - uint32 sop = (sop1 << 5) | sop2; - ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); - ptr += btoa(ptr, end-ptr, sop); - } - goto NULLIFY2; - - case HPPA_copr: // format 38 - { - int uid = (code>> 6) & 7; - uint32 sop = (code & 0x1F) | ((code>>4)&(0x1FFFF<<5)); - ptr += qsnprintf(ptr, end-ptr, ",%d,", uid); - ptr += btoa(ptr, end-ptr, sop); - } - goto NULLIFY2; - - case HPPA_pmdis: // format 55 -NULLIFY2: - { - int n = (code & BIT26) ? 1 : 0; - if ( n != 0 ) - APPEND(ptr, end, ",n"); - } - break; - - case HPPA_cldd: // formats 39 & 41 - case HPPA_cldw: - case HPPA_cstd: // formats 40 & 42 - case HPPA_cstw: - { - int uid = (code>> 6) & 7; - ptr += qsnprintf(ptr, end-ptr, ",%d", uid); - ptr = ldst_short(insn, code, ptr, end); - } - break; - - case HPPA_fabs: // formats 45 & 49 - case HPPA_fcpy: - case HPPA_fneg: - case HPPA_fnegabs: - case HPPA_frem: - case HPPA_frnd: - case HPPA_fsqrt: - case HPPA_fadd: // formats 48 & 52 - case HPPA_fdiv: - case HPPA_fmpy: - case HPPA_fsub: - { - int fmt = 0; - switch ( opcode(code) ) - { - case 0x0E: // formats 49 & 52 - fmt = (code>>11) & 1; - break; - case 0x0C: // formats 45 & 48 - fmt = (code>>11) & 3; - break; - default: - INTERR(10126); - } - ptr = append_fmt(fmt, ptr, end); - } - break; - case HPPA_fid: // format 45 - break; - - case HPPA_fcnv: // formats 46 & 50 - { - int sub = (code>>15) & 7; - int df, sf; - if ( opcode(code) == 0x0E ) // format 50 - { - df = (code>>13) & 1; - sf = (code>>11) & 1; - } - else // format 46 - { - df = (code>>13) & 3; - sf = (code>>11) & 3; - } - if ( sf == 2 || df == 2 ) - return NULL; - if ( (sub & 3) == 3 ) - APPEND(ptr, end, ",t"); // with explicit round to zero - static const char *const cnv_fpp[] = { ",sgl", ",dbl", NULL, ",quad" }; - static const char *const cnv_sfx[] = { ",w", ",dw", NULL, ",qw" }; - static const char *const cnv_ufx[] = { ",uw", ",udw", NULL, ",uqw" }; - const char *const *s1 = NULL; - const char *const *s2 = NULL; - switch ( sub ) - { - case 0: // fpp->fpp - s1 = cnv_fpp; - s2 = cnv_fpp; - break; - case 2: // fpp->fix - case 3: // fpp->fix with explicit round to zero - s1 = cnv_fpp; - s2 = cnv_sfx; - break; - case 6: // fpp->unsigned fix - case 7: // fpp->unsigned fix with explicit round to zero - s1 = cnv_fpp; - s2 = cnv_ufx; - break; - case 4: // undefined - return NULL; - case 1: // fix->fpp - s1 = cnv_sfx; - s2 = cnv_fpp; - break; - case 5: // unsigned fix->fpp - s1 = cnv_ufx; - s2 = cnv_fpp; - break; - } - APPEND(ptr, end, s1[sf]); - APPEND(ptr, end, s2[df]); - } - break; - - case HPPA_fcmp: // formats 47 & 51 - if ( opcode(code) == 0x0C ) - { - int fmt = (code>>11) & 3; - ptr = append_fmt(fmt, ptr, end); - if ( ptr == NULL ) - return NULL; - } - { - int c = code & 0x1F; - APPCHAR(ptr, end, ','); - APPEND(ptr, end, fpp_comp[c]); - } - break; - - case HPPA_ftest: // format 47 - { - int y = (code>>13) & 7; - if ( y == 1 ) // queue test - { - int c = code & 0x1F; - const char *s = fpp_test[c]; - if ( s == NULL ) - return NULL; - APPEND(ptr, end, s); - } - } - break; - - case HPPA_xmpyu: // format 52 - break; - - case HPPA_fmpyadd: // format 53 - case HPPA_fmpysub: - { - int f = (code>>5) & 1; - if ( f == 0 ) - APPEND(ptr, end, ",dbl"); - } - break; - - case HPPA_fmpyfadd: // format 54 - case HPPA_fmpynfadd: - { - int f = (code>>11) & 1; - if ( f != 0 ) - APPEND(ptr, end, ",dbl"); - } - break; - - default: - interr(insn, "build_insn_completer"); - } - if ( ptr == NULL ) - return NULL; - APPZERO(ptr, end); - return buf; -} - -//---------------------------------------------------------------------- -class out_hppa_t : public outctx_t -{ - out_hppa_t(void) = delete; // not used -public: - void out_bad_address(ea_t addr); - void outreg(int r); - void out_ip_rel(int displ); - void out_memref(ea_t ea); - void resolve_possible_memref(const op_t &x); - - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); -}; -CASSERT(sizeof(out_hppa_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_hppa_t) - -//---------------------------------------------------------------------- -void out_hppa_t::out_bad_address(ea_t addr) -{ - out_tagon(COLOR_ERROR); - out_btoa(addr, 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); -} - -//---------------------------------------------------------------------- -void out_hppa_t::outreg(int r) -{ - bool right = false; - out_tagon(COLOR_REG); - if ( r >= F0+32 && r < F0+64 // fpp register half - && insn.itype != HPPA_fmpyadd - && insn.itype != HPPA_fmpysub ) - { - r -= 32; - right = true; - } - out_line(ph.reg_names[r]); - if ( right ) - out_char('r'); - out_tagoff(COLOR_REG); -} - -//---------------------------------------------------------------------- -void out_hppa_t::out_ip_rel(int displ) -{ - out_printf(COLSTR("%s+", SCOLOR_SYMBOL) COLSTR("%d", SCOLOR_NUMBER), - ash.a_curip, displ); -} - -//---------------------------------------------------------------------- -bool out_hppa_t::out_operand(const op_t &x) -{ - switch ( x.type ) - { - case o_void: - return 0; - - case o_imm: - out_value(x, OOF_SIGNED|OOFS_IFSIGN|OOFW_IMM); - break; - - case o_reg: - outreg(x.reg); - break; - - case o_near: - { - ea_t ea = calc_mem(x.addr); - if ( ea == insn.ea+4 ) - out_ip_rel(4); - else if ( !out_name_expr(x, ea, ea) ) - out_bad_address(x.addr); - } - break; - - case o_displ: - out_value(x, OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED|OOFW_32); - // no break - case o_based: -OUT_PHRASE: - out_symbol('('); - if ( insn.auxpref & aux_space ) - { - outreg(x.sid); - out_symbol(','); - } - outreg(x.phrase); - out_symbol(')'); - break; - - case o_phrase: - outreg(x.secreg); - goto OUT_PHRASE; - - default: - interr(insn, "out"); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -void out_hppa_t::out_memref(ea_t ea) -{ - out_char(' '); - out_line(ash.cmnt, COLOR_AUTOCMT); - out_char(' '); - if ( has_any_name(get_flags(ea)) ) - { - qstring nbuf = get_colored_name(ea); - out_line(nbuf.c_str()); - } - else - { - // do not sign extend values that fit 32 bits -#ifdef __EA64__ - if ( int32(ea) == ea ) - ea = uint32(ea); -#endif - out_printf("%0*a", 8, ea); - } -} - -//---------------------------------------------------------------------- -void out_hppa_t::resolve_possible_memref(const op_t &x) -{ - hppa_t &pm = *static_cast<hppa_t *>(procmod); - ea_t ea = pm.calc_possible_memref(insn, x); - if ( ea != BADADDR ) - out_memref(ea); -} - -//---------------------------------------------------------------------- -void out_hppa_t::out_proc_mnem(void) -{ - hppa_t &pm = *static_cast<hppa_t *>(procmod); - char postfix[80]; - uint32 code = get_dword(insn.ea); - char *pfx = pm.build_insn_completer(insn, code, postfix, sizeof(postfix)); - out_mnem(16, pfx); -} - -//---------------------------------------------------------------------- -void out_hppa_t::out_insn(void) -{ - // output instruction mnemonics - out_mnemonic(); - - int i; - bool comma = false; - for ( i=0; i < PROC_MAXOP; i++ ) - { - if ( insn.ops[i].type == o_void ) - continue; - if ( comma ) - { - out_symbol(','); - out_char(' '); - } - comma = out_one_operand(i); - } - - out_immchar_cmts(); - - if ( insn.Op1.type == o_displ ) - resolve_possible_memref(insn.Op1); - if ( insn.Op2.type == o_displ ) - resolve_possible_memref(insn.Op2); - - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -//lint -esym(818, Srange) could be made const -void hppa_t::hppa_segstart(outctx_t &ctx, segment_t *Srange) const -{ - const char *const predefined[] = - { - ".text", // Text section - ".data", // Data sections - ".rdata", - ".comm", - }; - - if ( is_spec_segm(Srange->type) ) - return; - - qstring sname; - qstring sclas; - get_segm_name(&sname, Srange); - get_segm_class(&sclas, Srange); - - if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) ) - ctx.gen_printf(DEFAULT_INDENT, - COLSTR(".section %s", SCOLOR_ASMDIR) "" COLSTR("%s %s", SCOLOR_AUTOCMT), - sname.c_str(), - ash.cmnt, - sclas.c_str()); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -void hppa_t::hppa_assumes(outctx_t &ctx) // function to produce assume directives -{ - ea_t ea = ctx.insn_ea; - if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || got == BADADDR ) - return; - sreg_range_t sra; - if ( !get_sreg_range(&sra, ea, DPSEG) || sra.start_ea != ea ) - return; - - if ( sra.val == BADSEL ) - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s %s is unknown", SCOLOR_ASMDIR), - ash.cmnt, ph.reg_names[DPSEG]); - else - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s %s = %0*a", SCOLOR_ASMDIR), - ash.cmnt, ph.reg_names[DPSEG], 8, got + sra.val); -} - -//-------------------------------------------------------------------------- -void idaapi hppa_segend(outctx_t &, segment_t *) -{ -} - -//-------------------------------------------------------------------------- -void idaapi hppa_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL); -} - -//-------------------------------------------------------------------------- -void hppa_t::hppa_footer(outctx_t &ctx) const -{ - qstring nbuf = get_colored_name(inf_get_start_ea()); - const char *name = nbuf.c_str(); - const char *end = ash.end; - if ( end == NULL ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name); - else - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), - ash.end, ash.cmnt, name); -} diff --git a/idasdk75/module/hppa/reg.cpp b/idasdk75/module/hppa/reg.cpp deleted file mode 100644 index 02aad03..0000000 --- a/idasdk75/module/hppa/reg.cpp +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "hppa.hpp" -#include "hppa_cfh.cpp" -#include <diskio.hpp> -#include <typeinf.hpp> -#include "notify_codes.hpp" - -#include <ieee.h> -int data_id; - -//-------------------------------------------------------------------------- -static const char *const register_names_plain[] = -{ - // general registers (r0 is always 0) - // r31 is for BLE instruction - "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", - "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", - "%r24", "%r25", "%r26", "%dp", "%r28", "%r29", "%sp", "%r31", - // space registers - "%sr0", "%sr1", "%sr2", "%sr3", "%sr4", "%sr5", "%sr6", "%sr7", - // control registers - "%rctr", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7", - "%pidr1","%pidr2", "%ccr", "%sar", "%pidr3", "%pidr4","%iva", "%eiem", - "%itmr", "%pcsq", "pcoq", "%iir", "%isr", "%ior", "%ipsw", "%eirr", - "%tr0", "%tr1", "%tr2", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", - // floating-point registers - "%fpsr", "%fr1", "%fr2", "%fr3", "%fr4", "%fr5", "%fr6", "%fr7", - "%fr8", "%fr9", "%fr10", "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", - "%fr16", "%fr17", "%fr18", "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", - "%fr24", "%fr25", "%fr26", "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", - // register halves - "%fr16l", "%fr17l", "%fr18l", "%fr19l", "%fr20l", "%fr21l", "%fr22l", "%fr23l", - "%fr24l", "%fr25l", "%fr26l", "%fr27l", "%fr28l", "%fr29l", "%fr30l", "%fr31l", - "%fr16r", "%fr17r", "%fr18r", "%fr19r", "%fr20r", "%fr21r", "%fr22r", "%fr23r", - "%fr24r", "%fr25r", "%fr26r", "%fr27r", "%fr28r", "%fr29r", "%fr30r", "%fr31r", - // condition bits - "%ca0", "%ca1", "%ca2", "%ca3", "%ca4", "%ca5", "%ca6", - - "dp", // segment register to represent DP - "cs","ds", // virtual registers for code and data segments -}; - -static const char *const register_names_mnemonic[] = -{ - // general registers (r0 is always 0) - // r31 is for BLE instruction - "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", - "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%arg3", - "%arg2", "%arg1", "%arg0", "%dp", "%ret0", "%r29", "%sp", "%r31", - // space registers - "%sr0", "%sr1", "%sr2", "%sr3", "%sr4", "%sr5", "%sr6", "%sr7", - // control registers - "%rctr", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7", - "%pidr1","%pidr2", "%ccr", "%sar", "%pidr3", "%pidr4","%iva", "%eiem", - "%itmr", "%pcsq", "pcoq", "%iir", "%isr", "%ior", "%ipsw", "%eirr", - "%tr0", "%tr1", "%tr2", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", - // floating-point registers - "%fpsr", "%fr1", "%fr2", "%fr3", "%fr4", "%fr5", "%fr6", "%fr7", - "%fr8", "%fr9", "%fr10", "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", - "%fr16", "%fr17", "%fr18", "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", - "%fr24", "%fr25", "%fr26", "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", - // register halves - "%fr16l", "%fr17l", "%fr18l", "%fr19l", "%fr20l", "%fr21l", "%fr22l", "%fr23l", - "%fr24l", "%fr25l", "%fr26l", "%fr27l", "%fr28l", "%fr29l", "%fr30l", "%fr31l", - "%fr16r", "%fr17r", "%fr18r", "%fr19r", "%fr20r", "%fr21r", "%fr22r", "%fr23r", - "%fr24r", "%fr25r", "%fr26r", "%fr27r", "%fr28r", "%fr29r", "%fr30r", "%fr31r", - // condition bits - "%ca0", "%ca1", "%ca2", "%ca3", "%ca4", "%ca5", "%ca6", - - "dp", // segment register to represent DP - "cs","ds", // virtual registers for code and data segments -}; -CASSERT(qnumber(register_names_plain) == qnumber(register_names_mnemonic)); - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0xE8, 0x40, 0xC0, 0x00 }; // bv %r0(%rp) - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gas = -{ - AS_ASCIIC|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, - 0, - "GNU-like hypothetical assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - "#", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".long", // double words - ".quad", // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - ".", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "mod", // mod - "and", // and - "or", // or - "xor", // xor - "not", // not - "shl", // shl - "shr", // shr - NULL, // sizeof - 0, // flag2 - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt - NULL, // vstruc_fmt - NULL, // rva -}; - -static const asm_t *const asms[] = { &gas, NULL }; - -//-------------------------------------------------------------------------- -void hppa_t::setup_got(void) -{ - got = get_gotea(); - if ( got == BADADDR ) - got = get_name_ea(BADADDR, "_GLOBAL_OFFSET_TABLE_"); - if ( got == BADADDR ) - { - segment_t *s = get_segm_by_name(".got"); - if ( s != NULL ) - got = s->start_ea; - } - msg("DP is assumed to be %08a\n", got); -} - -//-------------------------------------------------------------------------- -void hppa_t::handle_new_flags(void) -{ - if ( mnemonic() ) - ph.reg_names = register_names_mnemonic; - else - ph.reg_names = register_names_plain; -} - -//-------------------------------------------------------------------------- -const char *hppa_t::get_syscall_name(int syscall) -{ - const ioport_t *p = find_ioport(syscalls, syscall); - return p == NULL ? NULL : p->name.c_str(); -} - -//-------------------------------------------------------------------------- -const char *hppa_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - static const char form[] = - "HELP\n" - "HP PA-RISC specific options\n" - "\n" - " Simplify instructions\n" - "\n" - " If this option is on, IDA will simplify instructions and replace\n" - " them by clearer pseudo-instructions\n" - " For example,\n" - "\n" - " or 0, 0, 0\n" - "\n" - " will be replaced by\n" - "\n" - " nop\n" - "\n" - " PSW bit W is on\n" - "\n" - " If this option is on, IDA will disassemble instructions as if\n" - " PSW W bit is on, i.e. addresses are treated as 64bit. In fact,\n" - " IDA still will truncate them to 32 bit, but this option changes\n" - " disassembly of load/store instructions.\n" - "\n" - " Use mnemonic register names\n" - "\n" - " If checked, IDA will use mnemonic names of the registers:\n" - " %r26: %arg0\n" - " %r25: %arg1\n" - " %r24: %arg2\n" - " %r23: %arg3\n" - " %r28: %ret0\n" - "\n" - "\n" - "ENDHELP\n" - "HPPA specific options\n" - "\n" - " <~S~implify instructions:C>\n" - " <PSW bit W is on (for 64-bit):C>\n" - " <Use ~m~nemonic register names:C>>\n" - "\n" - "\n"; - - if ( keyword == NULL ) - { - CASSERT(sizeof(idpflags) == sizeof(ushort)); - ask_form(form, &idpflags); -OK: - if ( idb_loaded ) - save_idpflags(); - handle_new_flags(); - return IDPOPT_OK; - } - else - { - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - if ( strcmp(keyword, "HPPA_SIMPLIFY") == 0 ) - { - setflag(idpflags, IDP_SIMPLIFY, *(int*)value != 0); - goto OK; - } - if ( strcmp(keyword, "HPPA_MNEMONIC") == 0 ) - { - setflag(idpflags, IDP_MNEMONIC, *(int*)value != 0); - goto OK; - } - if ( strcmp(keyword, "HPPA_PSW_W") == 0 ) - { - setflag(idpflags,IDP_PSW_W,*(int*)value != 0); - goto OK; - } - return IDPOPT_BADKEY; - } -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(hppa_t)); - return 0; -} - -ssize_t idaapi hppa_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: -// __emit__(0xCC); // debugger trap - helper.create("$ hppa"); - inf_set_be(true); // always big endian - read_ioports(&syscalls, NULL, "hpux.cfg"); - init_custom_refs(); - break; - - case processor_t::ev_term: - term_custom_refs(); - syscalls.clear(); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: // new file loaded - handle_new_flags(); - setup_got(); - // save flags to idb - save_idpflags(); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: // old file loaded - idpflags = ushort(helper.altval(-1)); - handle_new_flags(); - setup_got(); - break; - - case processor_t::ev_newprc: // new processor type - break; - - case processor_t::ev_newasm: // new assembler type - break; - - case processor_t::ev_creating_segm: // new segment - { - segment_t *sptr = va_arg(va, segment_t *); - sptr->defsr[ rVds-ph.reg_first_sreg] = find_selector(sptr->sel); - sptr->defsr[DPSEG-ph.reg_first_sreg] = 0; - } - break; - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - int nocrefs = va_arg(va, int); - return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1; - } - - case processor_t::ev_may_be_func: - { - const insn_t *insn = va_arg(va, insn_t *); - return may_be_func(*insn); - } - - case processor_t::ev_is_basic_block_end: - { - const insn_t *insn = va_arg(va, insn_t *); - return is_basic_block_end(*insn) ? 1 : -1; - } - -// +++ TYPE CALLBACKS (only 32-bit programs for the moment) - case processor_t::ev_decorate_name: - { - qstring *outbuf = va_arg(va, qstring *); - const char *name = va_arg(va, const char *); - bool mangle = va_argi(va, bool); - cm_t cc = va_argi(va, cm_t); - tinfo_t *type = va_arg(va, tinfo_t *); - return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; - } - - case processor_t::ev_max_ptr_size: - return 4; - - case processor_t::ev_calc_arglocs: - { - func_type_data_t *fti = va_arg(va, func_type_data_t *); - return calc_hppa_arglocs(fti) ? 1 : -1; - } - - case processor_t::ev_use_stkarg_type: - return 0; - - case processor_t::ev_use_regarg_type: - { - int *used = va_arg(va, int *); - ea_t ea = va_arg(va, ea_t); - const funcargvec_t *rargs = va_arg(va, const funcargvec_t *); - *used = use_hppa_regarg_type(ea, *rargs); - return 1; - } - - case processor_t::ev_use_arg_types: - { - ea_t ea = va_arg(va, ea_t); - func_type_data_t *fti = va_arg(va, func_type_data_t *); - funcargvec_t *rargs = va_arg(va, funcargvec_t *); - use_hppa_arg_types(ea, fti, rargs); - return 1; - } - - case processor_t::ev_get_cc_regs: - { - callregs_t *callregs = va_arg(va, callregs_t *); - cm_t cc = va_argi(va, cm_t); - static const int fastcall_regs[] = { R26, R25, R24, R23, -1 }; - if ( cc == CM_CC_FASTCALL ) - callregs->set(ARGREGS_INDEPENDENT, fastcall_regs, NULL); - else if ( cc == CM_CC_THISCALL ) - callregs->reset(); - else - break; - return 1; - } - - case processor_t::ev_calc_cdecl_purged_bytes: - // calculate number of purged bytes after call - { - // ea_t ea = va_arg(va, ea_t); - return 0; - } - - case processor_t::ev_get_stkarg_offset: - // get offset from SP to the first stack argument - // args: none - // returns: the offset+2 - return -0x34; - -// --- TYPE CALLBACKS - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - hppa_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - hppa_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - hppa_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - hppa_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - hppa_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = hppa_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - case hppa_module_t::ev_is_psw_w: - return psw_w() ? 1 : -1; - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -static const char *const shnames[] = { "hppa", NULL }; -static const char *const lnames[] = -{ - "PA-RISC", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_HPPA, // id - // flag - PRN_HEX // hex numbers - | PR_ALIGN // data items should be aligned - | PR_DEFSEG32 // 32-bit segments by default - | PR_SEGS // has segment registers - | PR_SGROTHER // segment register mean something unknown to the kernel - | PR_STACK_UP // stack grows up - | PR_TYPEINFO // type system is supported - | PR_USE_ARG_TYPES // use ph.use_arg_types() - | PR_DELAYED, // has delayed jumps and calls - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names_plain, // Register names - qnumber(register_names_plain), // Number of registers - - DPSEG, // first - rVds, // last - 8, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - HPPA_null, - HPPA_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - HPPA_rfi, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/i51/ana.cpp b/idasdk75/module/i51/ana.cpp deleted file mode 100644 index 35eba5f..0000000 --- a/idasdk75/module/i51/ana.cpp +++ /dev/null @@ -1,1083 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su, ig@datarescue.com - * FIDO: 2:5020/209 - * - */ - -#include "i51.hpp" - -//---------------------------------------------------------------------- -inline uint32 get_next_24bits(insn_t &insn) -{ - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_word(); - return low | (high<<16); -} - -//---------------------------------------------------------------------- -static void operand1(insn_t &insn, int nibble) -{ - switch ( nibble ) - { - case 4: - insn.Op1.type = o_reg; - insn.Op1.reg = rAcc; - break; - case 5: - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - break; - case 6: - insn.Op1.type = o_phrase; - insn.Op1.phrase = fR0; - break; - case 7: - insn.Op1.type = o_phrase; - insn.Op1.phrase = fR1; - break; - default: - insn.Op1.type = o_reg; - insn.Op1.phrase = uint16(rR0 + (nibble-8)); - break; - } -} - -//---------------------------------------------------------------------- -static void operand2(insn_t &insn, ushort nibble) -{ - switch ( nibble ) - { - case 4: - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - case 5: - insn.Op2.type = o_mem; - insn.Op2.addr = insn.get_next_byte(); - break; - case 6: - insn.Op2.type = o_phrase; - insn.Op2.phrase = fR0; - break; - case 7: - insn.Op2.type = o_phrase; - insn.Op2.phrase = fR1; - break; - default: - insn.Op2.type = o_reg; - insn.Op2.phrase = rR0 + (nibble-8); - break; - } -} - -//---------------------------------------------------------------------- -inline void opAcc(op_t &op) -{ - op.type = o_reg; - op.reg = rAcc; -} - -//---------------------------------------------------------------------- -inline void opC(op_t &op) -{ - op.type = o_reg; - op.reg = rC; -} - -//---------------------------------------------------------------------- -// register direct -static int op_rd(op_t &x, uint16 reg, uchar dtyp) -{ - if ( reg >= rDR32 && reg <= rDR52 ) - return 0; - x.type = o_reg; - x.dtype = dtyp; - x.reg = reg; - return 1; -} - -//---------------------------------------------------------------------- -// register indirect (fRi registers) -static int op_ph(op_t &x, int reg, uchar dtyp) -{ - if ( reg >= rDR32 && reg <= rDR52 ) - return 0; - x.type = o_phrase; - x.dtype = dtyp; - x.reg = fRi; - x.indreg = uchar(reg); - return 1; -} - -//---------------------------------------------------------------------- -// register indirect -static int op_ph(op_t &op, i51_phrases phr, uchar dtyp, uval_t disp = 0) -{ - op.type = o_phrase; - op.dtype = dtyp; - op.phrase = phr; - if ( disp > 0 ) - { - op.imm_disp = 1; - op.value = disp; - } - return 1; -} - - -//---------------------------------------------------------------------- -// register indirect with displacement -static int op_ds(op_t &x, uint16 phrase, uval_t disp, uchar dtyp) -{ - if ( phrase >= rDR32 && phrase <= rDR52 ) - return 0; - x.type = o_displ; - x.dtype = dtyp; - x.phrase = phrase; - x.addr = disp; - return 1; -} - -//---------------------------------------------------------------------- -inline void op_mm(op_t &x, uval_t addr, uchar dtyp) -{ - x.type = o_mem; - x.dtype = dtyp; - x.addr = addr; -} - -//---------------------------------------------------------------------- -inline void op_near(op_t &x, uval_t addr) -{ - x.type = o_near; - x.dtype = dt_word; - x.addr = addr; -} - -//---------------------------------------------------------------------- -inline void op_im(op_t &x, uval_t value, uchar dtyp) -{ - x.type = o_imm; - x.dtype = dtyp; - x.value = value; -} - -//---------------------------------------------------------------------- -uint32 i51_t::truncate(uval_t addr) const -{ - if ( ptype == prc_51 ) - return addr & 0xFFFF; - else - return addr & 0xFFFFFF; -} - -//---------------------------------------------------------------------- -static int make_short(insn_t &insn, uint16 itype, uchar b) -{ - insn.itype = itype; - static const uchar bregs[] = { rR0, rWR0, 0, rDR0 }; - static const uchar dtyps[] = { dt_byte, dt_word, dt_dword }; - int idx = (b >> 2) & 3; - if ( !op_rd(insn.Op1, bregs[idx] + (b>>4), dtyps[idx]) ) - return 0; - b &= 3; - if ( b == 3 ) - return 0; - op_im(insn.Op2, uval_t(1)<<b, dt_byte); - return insn.size; -} - -//---------------------------------------------------------------------- -// analyze extended instruction set - -int i51_t::ana_extended(insn_t &insn) -{ - int code = insn.get_next_byte(); - if ( (code & 8) == 0 ) - return 0; - if ( (code & 0xF0) >= 0xE0 ) - return 0; - - static const uchar itypes[] = - { -/* 8 9 A B C D E F */ -/* 0 */ I51_jsle, I51_mov, I51_movz, I51_mov, I51_null, I51_null, I51_sra, I51_null, -/* 1 */ I51_jsg, I51_mov, I51_movs, I51_mov, I51_null, I51_null, I51_srl, I51_null, -/* 2 */ I51_jle, I51_mov, I51_null, I51_null, I51_add, I51_add, I51_add, I51_add, -/* 3 */ I51_jg, I51_mov, I51_null, I51_null, I51_null, I51_null, I51_sll, I51_null, -/* 4 */ I51_jsl, I51_mov, I51_null, I51_null, I51_orl, I51_orl, I51_orl, I51_null, -/* 5 */ I51_jsge, I51_mov, I51_null, I51_null, I51_anl, I51_anl, I51_anl, I51_null, -/* 6 */ I51_je, I51_mov, I51_null, I51_null, I51_xrl, I51_xrl, I51_xrl, I51_null, -/* 7 */ I51_jne, I51_mov, I51_mov, I51_null, I51_mov, I51_mov, I51_mov, I51_mov, -/* 8 */ I51_null, I51_ljmp, I51_ejmp, I51_null, I51_div, I51_div, I51_null, I51_null, -/* 9 */ I51_null, I51_lcall, I51_ecall, I51_null, I51_sub, I51_sub, I51_sub, I51_sub, -/* A */ I51_null, I51_last, I51_eret, I51_null, I51_mul, I51_mul, I51_null, I51_null, -/* B */ I51_null, I51_trap, I51_null, I51_null, I51_cmp, I51_cmp, I51_cmp, I51_cmp, -/* C */ I51_null, I51_null, I51_push, I51_null, I51_null, I51_null, I51_null, I51_null, -/* D */ I51_null, I51_null, I51_pop, I51_null, I51_null, I51_null, I51_null, I51_null, - }; - insn.itype = itypes[ ((code&0xF0)>>1) | (code & 7) ]; - if ( insn.itype == I51_null ) - return 0; - - uchar b1, b2; - int oax = 0; - switch ( code ) - { - case 0x08: // rel - case 0x18: - case 0x28: - case 0x38: - case 0x48: - case 0x58: - case 0x68: - case 0x78: - { - insn.Op1.type = o_near; - insn.Op1.dtype = dt_word; - signed char off = insn.get_next_byte(); - insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition - } - break; - - case 0x09: // mov Rm, @WRj+dis - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rR0 +(b1>>4), dt_byte); - insn.Op2.offb = (uchar)insn.size; - op_ds(insn.Op2, rWR0+(b1&15), insn.get_next_word(), dt_byte); - break; - - case 0x49: // mov WRk, @WRj+dis - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - insn.Op2.offb = (uchar)insn.size; - op_ds(insn.Op2, rWR0+(b1&15), insn.get_next_word(), dt_word); - break; - - case 0x29: // mov Rm, @DRj+dis - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rR0 +(b1>>4), dt_byte); - insn.Op2.offb = (uchar)insn.size; - if ( !op_ds(insn.Op2, rDR0+(b1&15), insn.get_next_word(), dt_byte) ) - return 0; - break; - - case 0x69: // mov WRj, @DRk+dis - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - insn.Op2.offb = (uchar)insn.size; - if ( !op_ds(insn.Op2, rDR0+(b1&15), insn.get_next_word(), dt_word) ) - return 0; - break; - - case 0x19: // mov @WRj+dis, Rm - b1 = insn.get_next_byte(); - insn.Op1.offb = (uchar)insn.size; - op_ds(insn.Op1, rWR0+(b1&15), insn.get_next_word(), dt_byte); - op_rd(insn.Op2, rR0 +(b1>>4), dt_byte); - break; - - case 0x59: // mov @WRj+dis, WRk - b1 = insn.get_next_byte(); - insn.Op1.offb = (uchar)insn.size; - op_ds(insn.Op1, rWR0+(b1&15), insn.get_next_word(), dt_word); - op_rd(insn.Op2, rWR0+(b1>>4), dt_word); - break; - - case 0x39: // mov @DRj+dis, Rm - b1 = insn.get_next_byte(); - insn.Op1.offb = (uchar)insn.size; - if ( !op_ds(insn.Op1, rDR0+(b1&15), insn.get_next_word(), dt_byte) ) - return 0; - op_rd(insn.Op2, rR0 +(b1>>4), dt_byte); - break; - - case 0x79: // mov @DRk+dis, WRj - b1 = insn.get_next_byte(); - insn.Op1.offb = (uchar)insn.size; - if ( !op_ds(insn.Op1, rDR0+(b1&15), insn.get_next_word(), dt_word) ) - return 0; - op_rd(insn.Op2, rWR0+(b1>>4), dt_word); - break; - - case 0x0A: // movz WRj, Rm - case 0x1A: // movs WRj, Rm - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - op_rd(insn.Op2, rR0 +(b1&15), dt_byte); - break; - - case 0x0B: // 1000 mov WRj, @WRj - // 1010 mov WRj, @DRk - { - b1 = insn.get_next_byte(); - int ri; - switch ( b1 & 15 ) - { - case 0x8: ri = rWR0; break; - case 0xA: ri = rDR0; break; - case 0x9: return 0; - case 0xB: return 0; - default: return make_short(insn, I51_inc, b1); - } - b2 = insn.get_next_byte(); - if ( b2 & 15 ) - return 0; - op_rd(insn.Op1, rWR0+(b2>>4), dt_word); - if ( !op_ph(insn.Op2, ri + (b1>>4), dt_word) ) - return 0; - } - break; - - case 0x1B: // 1000 mov @WRj, WRj - // 1010 mov @DRk, WRj - { - b1 = insn.get_next_byte(); - int ri; - switch ( b1 & 15 ) - { - case 0x8: ri = rWR0; break; - case 0xA: ri = rDR0; break; - case 0x9: return 0; - case 0xB: return 0; - default: return make_short(insn, I51_dec, b1); - } - b2 = insn.get_next_byte(); - if ( b2 & 15 ) - return 0; - if ( !op_ph(insn.Op1, ri + (b1>>4), dt_word) ) - return 0; - op_rd(insn.Op2, rWR0+(b2>>4), dt_word); - } - break; - - case 0x7A: - { - b1 = insn.get_next_byte(); - switch ( b1&15 ) - { - case 9: // 1001 mov @WRj, Rm - case 0xB: // 1011 mov @DRk, Rm - b2 = insn.get_next_byte(); - if ( b2 & 15 ) - return 0; - if ( !op_ph(insn.Op1, ((b1&2) ? rDR0 : rWR0) + (b1>>4), dt_byte) ) - return 0; - op_rd(insn.Op2, rR0+(b2>>4), dt_byte); - break; - case 0xC: // movh DRk, #data16 - insn.itype = I51_movh; - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - insn.Op2.offb = (uchar)insn.size; - op_im(insn.Op2, insn.get_next_word(), dt_word); - break; - default: - goto CONT; - } - break; -CONT: - uval_t addr = (b1&2) ? insn.get_next_word() : insn.get_next_byte(); - switch ( b1&15 ) - { - case 0x1: // mov dir8, Rm - case 0x3: // mov dir16, Rm - op_mm(insn.Op1, addr, dt_byte); - op_rd(insn.Op2, rR0+(b1>>4), dt_byte); - break; - case 0x5: // mov dir8, WRj - case 0x7: // mov dir16, WRj - op_mm(insn.Op1, addr, dt_word); - op_rd(insn.Op2, rWR0+(b1>>4), dt_word); - break; - case 0xD: // mov dir8, DRj - case 0xF: // mov dir16, DRj - op_mm(insn.Op1, addr, dt_dword); - if ( !op_rd(insn.Op2, rDR0+(b1>>4), dt_dword) ) - return 0; - break; - default: return 0; - } - } - break; - - case 0x89: // ljmp @WRj or @DRj - case 0x99: // lcall @WRj or @DRj - { - int r; - uchar dt; - b1 = insn.get_next_byte(); - switch ( b1 & 15 ) - { - case 4: - r = rWR0; - dt = dt_word; - break; - case 8: - r = rDR0; - dt = dt_dword; - insn.itype = (insn.itype == I51_ljmp) ? I51_ejmp : I51_ecall; - break; - default: - return 0; - } - if ( !op_ph(insn.Op1, r+(b1>>4), dt) ) - return 0; - } - break; - - case 0x8A: // ejmp addr24 - case 0x9A: // ecall addr24 - op_near(insn.Op1, get_next_24bits(insn)); - break; - - case 0xAA: // eret - case 0xB9: // trap - break; - - case 0xCA: // push - case 0xDA: // pop - b1 = insn.get_next_byte(); - switch ( b1 & 15 ) - { - case 0x1: // mov DRk, PC - if ( code != 0xCA ) - return 0; - insn.itype = I51_mov; - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - op_rd(insn.Op2, rPC, dt_dword); - break; - case 0x2: // #data8 - insn.Op1.offb = (uchar)insn.size; - op_im(insn.Op1, insn.get_next_byte(), dt_byte); - break; - case 0x6: // #data16 - insn.Op1.offb = (uchar)insn.size; - op_im(insn.Op1, insn.get_next_word(), dt_word); - break; - case 0x8: // Rm - op_rd(insn.Op1, rR0+(b1>>4), dt_byte); - break; - case 0x9: // WRj - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - break; - case 0xB: // DRj - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - break; - default: - return 0; - } - break; - - case 0xA9: // bit instructions - { - static const uchar subtypes[] = - { - I51_null, I51_jbc, I51_jb, I51_jnb, - I51_null, I51_null, I51_null, I51_orl, - I51_anl, I51_mov, I51_mov, I51_cpl, - I51_clr, I51_setb, I51_orl, I51_anl - }; - b1 = insn.get_next_byte(); - if ( b1 & 8 ) - return 0; - insn.itype = subtypes[ b1 >> 4]; - if ( insn.itype == I51_null ) - return 0; - insn.Op1.type = o_bit251; - insn.Op1.dtype = dt_byte; - insn.Op1.b251_bit = b1 & 7; - insn.Op1.addr = insn.get_next_byte(); - insn.Op1.b251_bitneg = 0; - switch ( b1 >> 4 ) - { - case 0x1: // jbc bit, rel - case 0x2: // jb bit, rel - case 0x3: // jnb bit, rel - { - signed char rel = insn.get_next_byte(); - op_near(insn.Op2, truncate(insn.ip + insn.size + rel)); - } - break; - case 0xE: // orl cy, /bit - case 0xF: // anl cy, /bit - insn.Op1.b251_bitneg = 1; - /* no break */ - case 0x7: // orl cy, bit - case 0x8: // anl cy, bit - case 0xA: // mov cy, bit - insn.Op2 = insn.Op1; - opC(insn.Op1); - break; - case 0x9: // mov bit, cy - opC(insn.Op2); - break; - case 0xB: // cpl bit - case 0xC: // clr bit - case 0xD: // setb bit - break; - } - } - break; - - case 0x0E: // sra - case 0x1E: // srl - case 0x3E: // sll - b1 = insn.get_next_byte(); - switch ( b1 & 15 ) - { - case 0: - op_rd(insn.Op1, rR0 +(b1>>4), dt_byte); - break; - case 4: - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - break; - default: - return 0; - } - break; - - case 0x2C: // add Rm, Rm - case 0x4C: // orl Rm, Rm - case 0x5C: // anl Rm, Rm - case 0x6C: // xrl Rm, Rm - case 0x7C: // mov Rm, Rm - case 0x8C: // div Rm, Rm - case 0x9C: // sub Rm, Rm - case 0xAC: // mul Rm, Rm - case 0xBC: // cmp Rm, Rm - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rR0+(b1>>4), dt_byte); - op_rd(insn.Op2, rR0+(b1&15), dt_byte); - break; - - case 0x2D: // add WRj, WRj - case 0x4D: // orl WRj, WRj - case 0x5D: // anl WRj, WRj - case 0x6D: // xrl WRj, WRj - case 0x7D: // mov WRj, WRj - case 0x8D: // div WRj, WRj - case 0x9D: // sub WRj, WRj - case 0xAD: // mul WRj, WRj - case 0xBD: // cmp WRj, WRj - b1 = insn.get_next_byte(); - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - op_rd(insn.Op2, rWR0+(b1&15), dt_word); - break; - - case 0x2F: // add DRj, DRj - case 0x7F: // mov DRj, DRj - case 0x9F: // sub DRj, DRj - case 0xBF: // cmp DRj, DRj - b1 = insn.get_next_byte(); - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - if ( !op_rd(insn.Op2, rDR0+(b1&15), dt_dword) ) - return 0; - break; - - case 0x4E: // orl reg, op2 - case 0x5E: // anl reg, op2 - case 0x6E: // xrl reg, op2 - oax = 1; // orl, anl, xrl - /* no break */ - case 0x2E: // add reg, op2 - case 0x7E: // mov reg, op2 - case 0x8E: // div reg, op2 - case 0x9E: // sub reg, op2 - case 0xAE: // mul reg, op2 - case 0xBE: // cmp reg, op2 - b1 = insn.get_next_byte(); - switch ( b1 & 15 ) - { - case 0x0: // Rm, #8 - op_rd(insn.Op1, rR0+(b1>>4), dt_byte); - insn.Op2.offb = (uchar)insn.size; - op_im(insn.Op2, insn.get_next_byte(), dt_byte); - break; - case 0x4: // WRj, #16 - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - insn.Op2.offb = (uchar)insn.size; - op_im(insn.Op2, insn.get_next_word(), dt_word); - break; - case 0x8: // DRk, #16 - if ( oax ) - return 0; - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - insn.Op2.offb = (uchar)insn.size; - op_im(insn.Op2, insn.get_next_word(), dt_word); - break; - case 0xC: // DRk, #(1)16 - if ( oax ) - return 0; - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - insn.Op2.offb = (uchar)insn.size; - op_im(insn.Op2, insn.get_next_word(), dt_word); - insn.auxpref |= aux_1ext; - break; - case 0x1: // Rm, dir8 - op_rd(insn.Op1, rR0+(b1>>4), dt_byte); - op_mm(insn.Op2, insn.get_next_byte(), dt_byte); - break; - case 0x5: // WRj, dir8 - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - op_mm(insn.Op2, insn.get_next_byte(), dt_word); - break; - case 0xD: // DRk, dir8 - if ( oax ) - return 0; - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - op_mm(insn.Op2, insn.get_next_byte(), dt_word); - break; - case 0x3: // Rm, dir16 - op_rd(insn.Op1, rR0+(b1>>4), dt_byte); - op_mm(insn.Op2, insn.get_next_word(), dt_byte); - break; - case 0x7: // WRj, dir16 - op_rd(insn.Op1, rWR0+(b1>>4), dt_word); - op_mm(insn.Op2, insn.get_next_word(), dt_word); - break; - case 0xF: // DRk, dir16 - if ( code != 0x7E ) - return 0; // only mov works - if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) - return 0; - op_mm(insn.Op2, insn.get_next_word(), dt_word); - break; - case 0x9: // Rm, @WRj - b2 = insn.get_next_byte(); - if ( b2 & 15 ) - return 0; - op_rd(insn.Op1, rR0 +(b2>>4), dt_byte); - op_ph(insn.Op2, rWR0+(b1>>4), dt_byte); - break; - case 0xB: // Rm, @DRk - b2 = insn.get_next_byte(); - if ( b2 & 15 ) - return 0; - op_rd(insn.Op1, rR0 +(b2>>4), dt_byte); - if ( !op_ph(insn.Op2, rDR0+(b1>>4), dt_byte) ) - return 0; - break; - default: - return 0; - } - break; - - default: - error("%a: internal ana_extended() error, code=%x", insn.ea, code); - } - - return insn.size; -} - -//---------------------------------------------------------------------- -// analyze an basic instruction -int i51_t::ana_basic(insn_t &insn) -{ - ushort code = insn.get_next_byte(); - bool mx_a5 = false; - if ( code == 0xA5 && ptype == prc_51mx ) - { - code = insn.get_next_byte(); - mx_a5 = true; - } - - ushort nibble0 = (code & 0xF); - ushort nibble1 = (code >> 4); - char off; - if ( mx_a5 ) - { - if ( nibble1 == 0x6 && nibble0 >= 0x8 ) // ADD PRi,#data2 (0 1 1 0 1 i d1 d2) - { - insn.itype = I51_add; - op_rd(insn.Op1, (nibble0 & 4) == 0 ? rPR0 : rPR1, dt_dword); - int val = nibble0 & 3; - op_im(insn.Op2, val == 0 ? 4 : val, dt_byte); - return insn.size; - } - if ( nibble1 == 0x4 && nibble0 >= 0x8 ) // EMOVE A, @PRi+#data2 - { - insn.itype = I51_emov; - opAcc(insn.Op1); - int val = nibble0 & 3; - op_ph(insn.Op2, (nibble0 & 4) == 0 ? fPr0 : fPr1, dt_dword, val == 0 ? 4 : val); - return insn.size; - } - if ( nibble1 == 0x5 && nibble0 >= 0x8 ) // EMOVE @PRi+#data2, A - { - insn.itype = I51_emov; - int val = nibble0 & 3; - op_ph(insn.Op1, (nibble0 & 4) == 0 ? fPr0 : fPr1, dt_dword, val == 0 ? 4 : val); - opAcc(insn.Op2); - return insn.size; - } - } - if ( nibble0 < 4 ) // complex coding, misc instructions - { - switch ( nibble0 ) - { - case 0: - { - static const uchar misc0[16] = - { - I51_nop, I51_jbc, I51_jb, I51_jnb, - I51_jc, I51_jnc, I51_jz, I51_jnz, - I51_sjmp,I51_mov, I51_orl, I51_anl, - I51_push,I51_pop, I51_movx,I51_movx - }; - insn.itype = misc0[nibble1]; - } - switch ( nibble1 ) - { - case 0x1: case 0x2: case 0x3: // jbc, jb, jnb - insn.Op1.type = o_bit; - insn.Op1.reg = insn.get_next_byte(); - insn.Op2.type = o_near; - off = insn.get_next_byte(); - insn.Op2.addr = truncate(insn.ip + insn.size + off); // signed addition - insn.Op2.dtype = dt_word; - break; - case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: // jc, jnc, jz, jnz, sjmp - insn.Op1.type = o_near; - off = insn.get_next_byte(); - insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition - insn.Op1.dtype = dt_word; - break; - case 0x9: // mov - insn.Op1.type = o_reg; - insn.Op1.reg = mx_a5 ? rEptr : rDptr; - insn.Op1.dtype = mx_a5 ? dt_dword : dt_word; - insn.Op2.type = o_imm; - insn.Op2.offb = (uchar)insn.size; - if ( mx_a5 ) - { - insn.Op2.value = (((ea_t)insn.get_next_word()) << 8) + insn.get_next_byte(); - insn.Op2.dtype = dt_dword; - } - else - { - insn.Op2.value = insn.get_next_word(); - insn.Op2.dtype = dt_word; - } - break; - case 0xA: case 0xB: // orl, anl - opC(insn.Op1); - insn.Op2.type = o_bitnot; - insn.Op2.reg = insn.get_next_byte(); - break; - case 0xC: case 0xD: // push, pop - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - break; - case 0xE: // movx - opAcc(insn.Op1); - insn.Op2.type = o_phrase; - insn.Op2.phrase = mx_a5 ? fEptr : fDptr; - break; - case 0xF: // movx - opAcc(insn.Op2); - insn.Op1.type = o_phrase; - insn.Op1.phrase = mx_a5 ? fEptr : fDptr; - break; - } - break; - case 1: // acall, ajmp - { - ushort lowbits = insn.get_next_byte(); - insn.Op1.type = o_near; - insn.Op1.addr = truncate((code&0xE0)<<3) + lowbits + ((insn.ip+insn.size) & ~0x7FF); - insn.Op1.dtype = dt_word; - insn.itype = (nibble1 & 1) ? I51_acall : I51_ajmp; - } - break; - case 2: - { - static const uchar misc2[16] = - { - I51_ljmp,I51_lcall,I51_ret,I51_reti, - I51_orl, I51_anl, I51_xrl, I51_orl, - I51_anl, I51_mov, I51_mov, I51_cpl, - I51_clr, I51_setb,I51_movx,I51_movx - }; - insn.itype = misc2[nibble1]; - } - switch ( nibble1 ) - { - case 0x0: case 0x1: // ljump (ejmp), lcall (ecall) - insn.Op1.type = o_near; - if ( mx_a5 ) // ecall - { - insn.itype = nibble1 == 0 ? I51_ejmp : I51_ecall; - insn.Op1.addr = (((ea_t)insn.get_next_word()) << 8) + insn.get_next_byte(); - if ( insn.Op1.addr >= 0x800000 ) - insn.Op1.addr -= 0x800000; - } - else - { - insn.Op1.addr = insn.get_next_word(); - } - insn.Op1.addr|= (insn.ip+insn.size) & ~0xFFFF; - insn.Op1.dtype = mx_a5 ? dt_dword : dt_word; - break; - case 0x2: // ret (eret); - if ( mx_a5 ) - insn.itype = I51_eret; - break; - case 0x4: case 0x5: case 0x6: // orl, anl, xrl, - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - opAcc(insn.Op2); - break; - case 0x7: case 0x8: case 0xA: // orl, anl, mov - opC(insn.Op1); - insn.Op2.type = o_bit; - insn.Op2.reg = insn.get_next_byte(); - break; - case 0x9: // mov - opC(insn.Op2); - /* no break */ - case 0xB: case 0xC: case 0xD: // cpl, clr, setb - insn.Op1.type = o_bit; - insn.Op1.reg = insn.get_next_byte(); - break; - case 0xE: // movx - opAcc(insn.Op1); - insn.Op2.type = o_phrase; - insn.Op2.phrase = fR0; - break; - case 0xF: // movx - insn.Op1.type = o_phrase; - insn.Op1.phrase = fR0; - opAcc(insn.Op2); - break; - } - break; - case 3: - { - static const uchar misc3[16] = - { - I51_rr, I51_rrc, I51_rl, I51_rlc, - I51_orl, I51_anl, I51_xrl, I51_jmp, - I51_movc,I51_movc,I51_inc, I51_cpl, - I51_clr, I51_setb,I51_movx,I51_movx - }; - insn.itype = misc3[nibble1]; - } - switch ( nibble1 ) - { - case 0x0: case 0x1: case 0x2: case 0x3: // rr, rrc, rl, rlc - opAcc(insn.Op1); - break; - case 0x4: case 0x5: case 0x6: // orl, anl, xrl - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - insn.Op2.offb = (uchar)insn.size; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - case 0x7: // jmp - insn.Op1.type = o_phrase; - insn.Op1.phrase = mx_a5 ? fAeptr : fAdptr; - break; - case 0x8: case 0x9: // movc - opAcc(insn.Op1); - insn.Op2.type = o_phrase; - insn.Op2.phrase = nibble1 == 0x8 ? fApc : (mx_a5 ? fAeptr : fAdptr); - break; - case 0xA: // inc - insn.Op1.type = o_reg; - insn.Op1.reg = mx_a5 ? rEptr : rDptr; - insn.Op1.dtype = mx_a5 ? dt_dword : dt_word; - break; - case 0xB: case 0xC: case 0xD: //cpl, clr, setb - opC(insn.Op1); - break; - case 0xE: // movx - opAcc(insn.Op1); - insn.Op2.type = o_phrase; - insn.Op2.phrase = fR1; - break; - case 0xF: // movx - insn.Op1.type = o_phrase; - insn.Op1.phrase = fR1; - opAcc(insn.Op2); - break; - } - break; - } - } - else - { // i.e. nibble0 >= 4 - static const uchar regulars[16] = - { - I51_inc, I51_dec, I51_add, I51_addc, - I51_orl, I51_anl, I51_xrl, I51_mov, - I51_mov, I51_subb,I51_mov, I51_cjne, - I51_xch, I51_djnz,I51_mov, I51_mov - }; - insn.itype = regulars[nibble1]; - switch ( nibble1 ) - { - case 0x00: case 0x01: // inc, dec - operand1(insn, nibble0); - break; - case 0x0C: // xch - if ( nibble0 == 4 ) - { - insn.itype = I51_swap; - opAcc(insn.Op1); - break; - } - // fallthrough - case 0x02: case 0x03: case 0x04: // add, addc, orl - case 0x05: case 0x06: case 0x09: // anl, xrl, subb - operand2(insn, nibble0); - opAcc(insn.Op1); - break; - case 0x07: // mov - operand1(insn, nibble0); - insn.Op2.offb = (uchar)insn.size; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - break; - case 0x08: // mov - if ( nibble0 == 4 ) - { - insn.itype = I51_div; - insn.Op1.type = o_reg; - insn.Op1.reg = rAB; - break; - } - operand2(insn, nibble0); - insn.Op1.type = o_mem; - insn.Op1.addr = insn.get_next_byte(); - break; - case 0x0A: // mov - if ( nibble0 == 4 ) - { - insn.itype = I51_mul; - insn.Op1.type = o_reg; - insn.Op1.reg = rAB; - break; - } - if ( nibble0 == 5 ) - return 0; // mov to imm - no sense (0xA5) - operand1(insn, nibble0); - insn.Op2.type = o_mem; - insn.Op2.addr = insn.get_next_byte(); - break; - case 0x0B: // cjne - if ( nibble0 == 5 ) - { - opAcc(insn.Op1); - insn.Op2.type = o_mem; - insn.Op2.addr = insn.get_next_byte(); - } - else - { - operand1(insn, nibble0); - insn.Op2.offb = (uchar)insn.size; - insn.Op2.type = o_imm; - insn.Op2.value = insn.get_next_byte(); - } - insn.Op3.type = o_near; - off = insn.get_next_byte(); - insn.Op3.addr = truncate(insn.ip + insn.size + off); // signed addition - insn.Op3.dtype = dt_word; - break; - case 0x0D: // djnz - switch ( nibble0 ) - { - case 4: - insn.itype = I51_da; - opAcc(insn.Op1); - break; - case 6: case 7: - insn.itype = I51_xchd; - opAcc(insn.Op1); - operand2(insn, nibble0); - break; - default: - operand1(insn, nibble0); - off = insn.get_next_byte(); - insn.Op2.type = o_near; - insn.Op2.addr = truncate(insn.ip + insn.size + off); // signed addition - insn.Op2.dtype = dt_word; - break; - } - break; - case 0x0E: // mov - opAcc(insn.Op1); - if ( nibble0 == 4 ) - { - insn.itype = I51_clr; - break; - } - operand2(insn, nibble0); - break; - case 0x0F: // mov - if ( nibble0 == 4 ) - { - insn.itype = I51_cpl; - opAcc(insn.Op1); - break; - } - operand1(insn, nibble0); - insn.Op2.type = o_reg; - insn.Op2.reg = rAcc; - break; - } - } - return insn.size; -} - -//---------------------------------------------------------------------- -// analyze an instruction -int i51_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - insn.Op1.dtype = dt_byte; - insn.Op2.dtype = dt_byte; - insn.Op3.dtype = dt_byte; - - uchar code = get_byte(insn.ea); - switch ( ptype ) - { - case prc_51: - case prc_51mx: - return ana_basic(insn); - - case prc_251_src: - case prc_930_src: - if ( code == 0xA5 ) - { - insn.size++; // skip A5 - code = get_byte(insn.ea+1); - if ( (code & 15) < 6 ) - return 0; - return ana_basic(insn); - } - if ( (code & 15) < 6 ) - return ana_basic(insn); - return ana_extended(insn); - - case prc_251_bin: - case prc_930_bin: - if ( code == 0xA5 ) - { - insn.size++; // skip A5 - return ana_extended(insn); - } - return ana_basic(insn); - } - return 0; //lint !e527 statement is unreachable -} diff --git a/idasdk75/module/i51/i51.cfg b/idasdk75/module/i51/i51.cfg deleted file mode 100644 index 74e68c9..0000000 --- a/idasdk75/module/i51/i51.cfg +++ /dev/null @@ -1,17356 +0,0 @@ -; The format of the input file: -; each device definition begins with a line like this: -; -; .devicename -; -; after it go the port definitions in this format: -; -; portname address -; -; the bit definitions (optional) are represented like this: -; -; portname.bitname bitnumber -; -; lines beginning with a space are ignored. -; comment lines should be started with ';' character. -; -; the default device is specified at the start of the file -; -; .default device_name -; -; all lines non conforming to the format are passed to the callback function -; -; MOTOROLA SPECIFIC LINES -;------------------------ -; -; the processor definition may include the memory configuration. -; the line format is: - -; area CLASS AREA-NAME START:END -; -; where CLASS is anything, but please use one of CODE, DATA, BSS -; START and END are addresses, the end address is not included - -; Interrupt vectors are declared in the following way: - -; interrupt NAME ADDRESS COMMENT - -.default C517 - -.C501 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8006&parent_oid=13727 -; d501.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 interrupt -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 interrupt -entry RI_TI 0x0023 Serial port interrupt -entry TF2_EXF2 0x002B Timer 2 interrupt - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -RESERVED0086 0x0086 RESERVED -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.P17 7 -P1.P16 6 -P1.P15 5 -P1.P14 4 -P1.P13 3 -P1.P12 2 -P1.P11 1 -P1.P10 0 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IE 0x00A8 Interrupt Enable Register -IE.EA 7 -IE.ET2 5 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 -RESERVED00A9 0x00A9 RESERVED -RESERVED00AA 0x00AA RESERVED -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -RESERVED00B1 0x00B1 RESERVED -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IP 0x00B8 Interrupt Priority Register -IP.PT2 5 -IP.PS 4 -IP.PT1 3 -IP.PX1 2 -IP.PT0 1 -IP.PX0 0 -RESERVED00B9 0x00B9 RESERVED -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -RESERVED00C0 0x00C0 RESERVED -RESERVED00C1 0x00C1 RESERVED -RESERVED00C2 0x00C2 RESERVED -RESERVED00C3 0x00C3 RESERVED -RESERVED00C4 0x00C4 RESERVED -RESERVED00C5 0x00C5 RESERVED -RESERVED00C6 0x00C6 RESERVED -RESERVED00C7 0x00C7 RESERVED -T2CON 0x00C8 Timer 2 Control Register -T2CON.TF2 7 -T2CON.EXF2 6 -T2CON.RCLK 5 -T2CON.TCLK 4 -T2CON.EXEN2 3 -T2CON.TR2 2 -T2CON.C_T2 1 -T2CON.CP_RL2 0 -T2MOD 0x00C9 Timer 2 Mode Register -T2MOD.DCEN 0 -RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte -RC2L.RC2L7 7 -RC2L.RC2L6 6 -RC2L.RC2L5 5 -RC2L.RC2L4 4 -RC2L.RC2L3 3 -RC2L.RC2L2 2 -RC2L.RC2L1 1 -RC2L.RC2L0 0 -RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte -RC2H.RC2H7 7 -RC2H.RC2H6 6 -RC2H.RC2H5 5 -RC2H.RC2H4 4 -RC2H.RC2H3 3 -RC2H.RC2H2 2 -RC2H.RC2H1 1 -RC2H.RC2H0 0 -TL2 0x00CC Timer 2 Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2 High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -RESERVED00D8 0x00D8 RESERVED -RESERVED00D9 0x00D9 RESERVED -RESERVED00DA 0x00DA RESERVED -RESERVED00DB 0x00DB RESERVED -RESERVED00DC 0x00DC RESERVED -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -RESERVED00E8 0x00E8 RESERVED -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C504 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=28993&parent_oid=12032 -; SAF-C504-2E40M.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xFF00 -area DATA XRAM 0xFF00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 interrupt -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 interrupt -entry RI_TI 0x0023 Serial port interrupt -entry TF2_EXF2 0x002B Timer 2 interrupt -entry IE2 0x004B External interrupt 2 -entry TRF_BCERR 0x0053 CAPCOM emergency interrupt -entry CT2P 0x005B Compare timer 2 interrupt -entry CC0F_R_CC2F_R 0x0063 Capture/compare match interrupt -entry CT1FP_CT1FC 0x006B Compare timer 1 interrupt -entry PDINT 0x007B Power-down interrupt - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.P17 7 -P1.P16 6 -P1.P15 5 -P1.P14 4 -P1.P13 3 -P1.P12 2 -P1.T2EX 1 -P1.T2 0 -; P1ANA 0x0090 Port 1 Analog Input Selection Register -; P1ANA.EAN3 3 -; P1ANA.EAN2 2 -; P1ANA.EAN1 1 -; P1ANA.EAN0 0 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -ITCON 0x009A Interrupt Trigger Condition Register -ITCON.IT2 7 -ITCON.IE2 6 -ITCON.I2ETF 5 -ITCON.I2ETR 4 -ITCON.I1ETF 3 -ITCON.I1ETR 2 -ITCON.I0ETF 1 -ITCON.I0ETR 0 -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IEN1 0x00A9 Interrupt Enable Register 1 -IEN1.ECT1 5 -IEN1.ECCM 4 -IEN1.ECT2 3 -IEN1.ECEM 2 -IEN1.EX2 1 -IEN1.EADC 0 -RESERVED00AA 0x00AA RESERVED -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -; P3ANA 0x00B0 Port 3 Analog Input Selection Register -; P3ANA.EAN7 5 -; P3ANA.EAN6 4 -; P3ANA.EAN5 3 -; P3ANA.EAN4 2 -SYSCON 0x00B1 System Control Register -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.XMAP 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IP0 0x00B8 Interrupt Priority Register 0 -IP0.PT2 5 -IP0.PS 4 -IP0.PT1 3 -IP0.PX1 2 -IP0.PT0 1 -IP0.PX0 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.PCT1 5 -IP1.PCCM 4 -IP1.PCT2 3 -IP1.PCEM 2 -IP1.PX2 1 -IP1.PADC 0 -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -WDCON 0x00C0 Watchdog Timer Control Register -WDCON.OWDS 3 -WDCON.WDTS 2 -WDCON.WDT 1 -WDCON.SWDT 0 -CT2CON 0x00C1 Compare timer 2 control register -CT2CON.CT2P 7 -CT2CON.ECT2O 6 -CT2CON.STE2 5 -CT2CON.CT2RES 4 -CT2CON.CT2R 3 -CT2CON.CLK2 2 -CT2CON.CLK1 1 -CT2CON.CLK0 0 -CCL0 0x00C2 Capture/compare register 0, low byte -CCL0.CCL07 7 -CCL0.CCL06 6 -CCL0.CCL05 5 -CCL0.CCL04 4 -CCL0.CCL03 3 -CCL0.CCL02 2 -CCL0.CCL01 1 -CCL0.CCL00 0 -CCH0 0x00C3 Capture/compare register 0, high byte -CCH0.CCH07 7 -CCH0.CCH06 6 -CCH0.CCH05 5 -CCH0.CCH04 4 -CCH0.CCH03 3 -CCH0.CCH02 2 -CCH0.CCH01 1 -CCH0.CCH00 0 -CCL1 0x00C4 Capture/compare register 1, low byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C5 Capture/compare register 1, high byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C6 Capture/compare register 2, low byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C7 Capture/compare register 2, high byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.TF2 7 -T2CON.EXF2 6 -T2CON.RCLK 5 -T2CON.TCLK 4 -T2CON.EXEN2 3 -T2CON.TR2 2 -T2CON.C_T2 1 -T2CON.CP_RL2 0 -T2MOD 0x00C9 Timer 2 Mode Register -T2MOD.DCEN 0 -RC2L 0x00CA Timer 2 Reload Capture Register, Low Byte -RC2L.RC2L7 7 -RC2L.RC2L6 6 -RC2L.RC2L5 5 -RC2L.RC2L4 4 -RC2L.RC2L3 3 -RC2L.RC2L2 2 -RC2L.RC2L1 1 -RC2L.RC2L0 0 -RC2H 0x00CB Timer 2 Reload Capture Register, High Byte -RC2H.RC2H7 7 -RC2H.RC2H6 6 -RC2H.RC2H5 5 -RC2H.RC2H4 4 -RC2H.RC2H3 3 -RC2H.RC2H2 2 -RC2H.RC2H1 1 -RC2H.RC2H0 0 -TL2 0x00CC Timer 2 Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2 High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -TRCON 0x00CF Trap enable control register -TRCON.TRPEN 7 -TRCON.TRF 6 -TRCON.TREN5 5 -TRCON.TREN4 4 -TRCON.TREN3 3 -TRCON.TREN2 2 -TRCON.TREN1 1 -TRCON.TREN0 0 -PSW 0x00D0 Program Status Word Register -PSW.CY 7 Carry Flag -PSW.AC 6 Auxiliary Carry Flag -PSW.F0 5 General Purpose Flag 0 -PSW.RS1 4 Register Bank Select Control bit 1 -PSW.RS0 3 Register Bank Select Control bit 2 -PSW.OV 2 Overflow Flag -PSW.F1 1 General Purpose Flag 1 -PSW.P 0 Parity Flag -RESERVED00D1 0x00D1 RESERVED -CP2L 0x00D2 Compare timer 2 period register, low byte -CP2L.CP2L7 7 -CP2L.CP2L6 6 -CP2L.CP2L5 5 -CP2L.CP2L4 4 -CP2L.CP2L3 3 -CP2L.CP2L2 2 -CP2L.CP2L1 1 -CP2L.CP2L0 0 -CP2H 0x00D3 Compare timer 2 period register, high byte -CP2H.CP2H1 1 -CP2H.CP2H0 0 -CMP2L 0x00D4 Compare timer 2 compare register, low byte -CMP2L.CMP2L7 7 -CMP2L.CMP2L6 6 -CMP2L.CMP2L5 5 -CMP2L.CMP2L4 4 -CMP2L.CMP2L3 3 -CMP2L.CMP2L2 2 -CMP2L.CMP2L1 1 -CMP2L.CMP2L0 0 -CMP2H 0x00D5 Compare timer 2 compare register, high byte -CMP2H.CMP2H1 1 -CMP2H.CMP2H0 0 -CCIE 0x00D6 Capture/Compare Interrupt Enable Reg. -CCIE.ECTP 7 -CCIE.ECTC 6 -CCIE.CC2FEN 5 -CCIE.CC2REN 4 -CCIE.CC1FEN 3 -CCIE.CC1REN 2 -CCIE.CC0FEN 1 -CCIE.CC0REN 0 -BCON 0x00D7 Block commutation control register -BCON.BCMPBCEM 7 -BCON.PWM1 6 -BCON.PWM0 5 -BCON.EBCE 4 -BCON.BCERR 3 -BCON.BCEN 2 -BCON.BCM1 1 -BCON.BCM0 0 -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.IADC 5 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register High Byte -ADDATH.ADDATH9 7 -ADDATH.ADDATH8 6 -ADDATH.ADDATH7 5 -ADDATH.ADDATH6 4 -ADDATH.ADDATH5 3 -ADDATH.ADDATH4 2 -ADDATH.ADDATH3 1 -ADDATH.ADDATH2 0 -ADDATL 0x00DA A/D Converter Data Register Low Byte -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -RESERVED00DB 0x00DB RESERVED -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -CCPL 0x00DE Compare timer 1 period register, low byte -CCPL.CCPL7 7 -CCPL.CCPL6 6 -CCPL.CCPL5 5 -CCPL.CCPL4 4 -CCPL.CCPL3 3 -CCPL.CCPL2 2 -CCPL.CCPL1 1 -CCPL.CCPL0 0 -CCPH 0x00DF Compare timer 1 period register, high byte -CCPH.CCPH7 7 -CCPH.CCPH6 6 -CCPH.CCPH5 5 -CCPH.CCPH4 4 -CCPH.CCPH3 3 -CCPH.CCPH2 2 -CCPH.CCPH1 1 -CCPH.CCPH0 0 -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -CT1CON 0x00E1 Compare timer 1 control register -CT1CON.CTM 7 -CT1CON.ETRP 6 -CT1CON.STE1 5 -CT1CON.CT1RES 4 -CT1CON.CT1R 3 -CT1CON.CLK2 2 -CT1CON.CLK1 1 -CT1CON.CLK0 0 -COINI 0x00E2 Compare output initialization register -COINI.COUT3I 7 -COINI.COUTXI 6 -COINI.COUT2I 5 -COINI.CC2I 4 -COINI.COUT1I 3 -COINI.CC1I 2 -COINI.COUT0I 1 -COINI.CC0I 0 -CMSEL0 0x00E3 Capture/compare mode select register 0 -CMSEL0.CMSEL13 7 -CMSEL0.CMSEL12 6 -CMSEL0.CMSEL11 5 -CMSEL0.CMSEL10 4 -CMSEL0.CMSEL03 3 -CMSEL0.CMSEL02 2 -CMSEL0.CMSEL01 1 -CMSEL0.CMSEL00 0 -CMSEL1 0x00E4 Capture/compare mode select register 1 -CMSEL1.CMSEL23 3 -CMSEL1.CMSEL22 2 -CMSEL1.CMSEL21 1 -CMSEL1.CMSEL20 0 -CCIR 0x00E5 Capture/compare interrupt request flag reg. -CCIR.CT1FP 7 -CCIR.CT1FC 6 -CCIR.CC2F 5 -CCIR.CC2R 4 -CCIR.CC1F 3 -CCIR.CC1R 2 -CCIR.CC0F 1 -CCIR.CC0R 0 -CT1OFL 0x00E6 Compare timer 1 offset register, low byte -CT1OFL.CT1OFL7 7 -CT1OFL.CT1OFL6 6 -CT1OFL.CT1OFL5 5 -CT1OFL.CT1OFL4 4 -CT1OFL.CT1OFL3 3 -CT1OFL.CT1OFL2 2 -CT1OFL.CT1OFL1 1 -CT1OFL.CT1OFL0 0 -; alex - this was cause for error message "duplicate address 0xe6 at line 950" -;CT1OFH 0x00E6 Compare timer 1 offset register, high byte -;CT1OFH.CT1OFH7 7 -;CT1OFH.CT1OFH6 6 -;CT1OFH.CT1OFH5 5 -;CT1OFH.CT1OFH4 4 -;CT1OFH.CT1OFH3 3 -;CT1OFH.CT1OFH2 2 -;CT1OFH.CT1OFH1 1 -;CT1OFH.CT1OFH0 0 -RESERVED00E7 0x00E7 RESERVED -RESERVED00E8 0x00E8 RESERVED -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C505 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 -; C505C.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xF700 -area BSS RESERVED 0xF700:0xFF00 -area DATA XRAM 0xFF00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry CAN_SWI 0x004B CAN Controller / Software Interrupt -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry IRTC 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.P14 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -; P1ANA 0x0090 Port 1 Analog Input Selection Register -; P1ANA.EAN7 7 -; P1ANA.EAN6 6 -; P1ANA.EAN5 5 -; P1ANA.EAN4 4 -; P1ANA.EAN3 3 -; P1ANA.EAN2 2 -; P1ANA.EAN1 1 -; P1ANA.EAN0 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register (C505/C505C/C505A only) -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.CMOD 3 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.ECAN 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.SWI 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Reload Register Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Reload Register High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDAT 0x00D9 A/D Converter Data Reg. (C505 / C505C only) -ADDAT.ADDAT7 7 -ADDAT.ADDAT6 6 -ADDAT.ADDAT5 5 -ADDAT.ADDAT4 4 -ADDAT.ADDAT3 3 -ADDAT.ADDAT2 2 -ADDAT.ADDAT1 1 -ADDAT.ADDAT0 0 -ADST 0x00DA A/D Converter Start Reg. (C505 / C505C only) -RESERVED00DB 0x00DB RESERVED -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.RXDC 1 -P4.TXDC 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -VR2.VR27 7 -VR2.VR26 6 -VR2.VR25 5 -VR2.VR24 4 -VR2.VR23 3 -VR2.VR22 2 -VR2.VR21 1 -VR2.VR20 0 -RESERVED00FF 0x00FF RESERVED - - -.C505A -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 -; C505C.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xF700 -area BSS RESERVED 0xF700:0xFC00 -area DATA XRAM 0xFC00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry CAN_SWI 0x004B CAN Controller / Software Interrupt -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry IRTC 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.P14 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -; P1ANA 0x0090 Port 1 Analog Input Selection Register -; P1ANA.EAN7 7 -; P1ANA.EAN6 6 -; P1ANA.EAN5 5 -; P1ANA.EAN4 4 -; P1ANA.EAN3 3 -; P1ANA.EAN2 2 -; P1ANA.EAN1 1 -; P1ANA.EAN0 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register (C505/C505C/C505A only) -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.CMOD 3 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.ECAN 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.SWI 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Reload Register Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Reload Register High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter High Byte Data Register (C505A / C505CA only) -ADDATH.ADDATH7 7 -ADDATH.ADDATH6 6 -ADDATH.ADDATH5 5 -ADDATH.ADDATH4 4 -ADDATH.ADDATH3 3 -ADDATH.ADDATH2 2 -ADDATH.ADDATH1 1 -ADDATH.ADDATH0 0 -ADDATL 0x00DA A/D Converter Low Byte Data Register (C505A / C505CA only) -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -RESERVED00DB 0x00DB RESERVED -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.RXDC 1 -P4.TXDC 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -VR2.VR27 7 -VR2.VR26 6 -VR2.VR25 5 -VR2.VR24 4 -VR2.VR23 3 -VR2.VR22 2 -VR2.VR21 1 -VR2.VR20 0 -RESERVED00FF 0x00FF RESERVED - - -.C505C -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 -; C505C.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xF700 -area DATA CAN 0xF700:0xF800 -area BSS RESERVED 0xF800:0xFF00 -area DATA XRAM 0xFF00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry CAN_SWI 0x004B CAN Controller / Software Interrupt -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry IRTC 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.P14 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -; P1ANA 0x0090 Port 1 Analog Input Selection Register -; P1ANA.EAN7 7 -; P1ANA.EAN6 6 -; P1ANA.EAN5 5 -; P1ANA.EAN4 4 -; P1ANA.EAN3 3 -; P1ANA.EAN2 2 -; P1ANA.EAN1 1 -; P1ANA.EAN0 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register (C505/C505C/C505A only) -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.CMOD 3 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.ECAN 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.SWI 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Reload Register Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Reload Register High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDAT 0x00D9 A/D Converter Data Reg. (C505 / C505C only) -ADDAT.ADDAT7 7 -ADDAT.ADDAT6 6 -ADDAT.ADDAT5 5 -ADDAT.ADDAT4 4 -ADDAT.ADDAT3 3 -ADDAT.ADDAT2 2 -ADDAT.ADDAT1 1 -ADDAT.ADDAT0 0 -ADST 0x00DA A/D Converter Start Reg. (C505 / C505C only) -RESERVED00DB 0x00DB RESERVED -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.RXDC 1 -P4.TXDC 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -VR2.VR27 7 -VR2.VR26 6 -VR2.VR25 5 -VR2.VR24 4 -VR2.VR23 3 -VR2.VR22 2 -VR2.VR21 1 -VR2.VR20 0 -RESERVED00FF 0x00FF RESERVED -; -------------------------------------- CAN -------------------------------- -CR 0xF700 Control Register -CR.TEST 7 -CR.CCE 6 -CR.EIE 3 -CR.SIE 2 -CR.IE 1 -CR.INIT 0 -SR 0xF701 Status Register -SR.BOFF 7 -SR.EWRN 6 -SR.RXOK 4 -SR.TXOK 3 -SR.LEC2 2 -SR.LEC1 1 -SR.LEC0 0 -IR 0xF702 Interrupt Register -IR.INTID7 7 -IR.INTID6 6 -IR.INTID5 5 -IR.INTID4 4 -IR.INTID3 3 -IR.INTID2 2 -IR.INTID1 1 -IR.INTID0 0 -RESERVEDF703 0xF703 RESERVED -BTR0 0xF704 Bit Timing Register Low -BTR0.SJW7 7 -BTR0.SJW6 6 -BTR0.BRP5 5 -BTR0.BRP4 4 -BTR0.BRP3 3 -BTR0.BRP2 2 -BTR0.BRP1 1 -BTR0.BRP0 0 -BTR1 0xF705 Bit Timing Register High -BTR1.TSEG26 6 -BTR1.TSEG25 5 -BTR1.TSEG24 4 -BTR1.TSEG13 3 -BTR1.TSEG12 2 -BTR1.TSEG11 1 -BTR1.TSEG10 0 -GMS0 0xF706 Global Mask Short Register Low -GMS0.ID28 7 -GMS0.ID27 6 -GMS0.ID26 5 -GMS0.ID25 4 -GMS0.ID24 3 -GMS0.ID23 2 -GMS0.ID22 1 -GMS0.ID21 0 -GMS1 0xF707 Global Mask Short Register High -GMS1.ID20 7 -GMS1.ID19 6 -GMS1.ID18 5 -UGML0 0xF708 Upper Global Mask Long Register Low -UGML0.ID28 7 -UGML0.ID27 6 -UGML0.ID26 5 -UGML0.ID25 4 -UGML0.ID24 3 -UGML0.ID23 2 -UGML0.ID22 1 -UGML0.ID21 0 -UGML1 0xF709 Upper Global Mask Long Register High -UGML1.ID20 7 -UGML1.ID19 6 -UGML1.ID18 5 -UGML1.ID17 4 -UGML1.ID16 3 -UGML1.ID15 2 -UGML1.ID14 1 -UGML1.ID13 0 -LGML0 0xF70A Lower Global Mask Long Register Low -LGML0.ID12 7 -LGML0.ID11 6 -LGML0.ID10 5 -LGML0.ID9 4 -LGML0.ID8 3 -LGML0.ID7 2 -LGML0.ID6 1 -LGML0.ID5 0 -LGML1 0xF70B Lower Global Mask Long Register High -LGML1.ID4 7 -LGML1.ID3 6 -LGML1.ID2 5 -LGML1.ID1 4 -LGML1.ID0 3 -UMLM0 0xF70C Upper Mask of Last Message Register Low -UMLM0.ID28 7 -UMLM0.ID27 6 -UMLM0.ID26 5 -UMLM0.ID25 4 -UMLM0.ID24 3 -UMLM0.ID23 2 -UMLM0.ID22 1 -UMLM0.ID21 0 -UMLM1 0xF70D Upper Mask of Last Message Register High -UMLM1.ID20 7 -UMLM1.ID19 6 -UMLM1.ID18 5 -UMLM1.ID17 4 -UMLM1.ID16 3 -UMLM1.ID15 2 -UMLM1.ID14 1 -UMLM1.ID13 0 -LMLM0 0xF70E Lower Mask of Last Message Register Low -LMLM0.ID12 7 -LMLM0.ID11 6 -LMLM0.ID10 5 -LMLM0.ID9 4 -LMLM0.ID8 3 -LMLM0.ID7 2 -LMLM0.ID6 1 -LMLM0.ID5 0 -LMLM1 0xF70F Lower Mask of Last Message Register High -LMLM1.ID4 7 -LMLM1.ID3 6 -LMLM1.ID2 5 -LMLM1.ID1 4 -LMLM1.ID0 3 -; -------------------------------------- CAN_1 -------------------------------- -MCR0_1 0xF710 Message Control Register Low -MCR0_1.MSGVAL1 7 -MCR0_1.MSGVAL0 6 -MCR0_1.TXIE1 5 -MCR0_1.TXIE0 4 -MCR0_1.RXIE1 3 -MCR0_1.RXIE0 2 -MCR0_1.INTPND1 1 -MCR0_1.INTPND0 0 -MCR1_1 0xF711 Message Control Register High -MCR1_1.RMTPND1 7 -MCR1_1.RMTPND0 6 -MCR1_1.TXRQ1 5 -MCR1_1.TXRQ0 4 -MCR1_1.MSGLSTCPUUPD1 3 -MCR1_1.MSGLSTCPUUPD0 2 -MCR1_1.NEWDAT1 1 -MCR1_1.NEWDAT0 0 -UAR0_1 0xF712 Upper Arbitration Register Low -UAR0_1.ID28 7 -UAR0_1.ID27 6 -UAR0_1.ID26 5 -UAR0_1.ID25 4 -UAR0_1.ID24 3 -UAR0_1.ID23 2 -UAR0_1.ID22 1 -UAR0_1.ID21 0 -UAR1_1 0xF713 Upper Arbitration Register High -UAR1_1.ID20 7 -UAR1_1.ID19 6 -UAR1_1.ID18 5 -UAR1_1.ID17 4 -UAR1_1.ID16 3 -UAR1_1.ID15 2 -UAR1_1.ID14 1 -UAR1_1.ID13 0 -LAR0_1 0xF714 Lower Arbitration Register Low -LAR0_1.ID12 7 -LAR0_1.ID11 6 -LAR0_1.ID10 5 -LAR0_1.ID9 4 -LAR0_1.ID8 3 -LAR0_1.ID7 2 -LAR0_1.ID6 1 -LAR0_1.ID5 0 -LAR1_1 0xF715 Lower Arbitration Register High -LAR1_1.ID4 7 -LAR1_1.ID3 6 -LAR1_1.ID2 5 -LAR1_1.ID1 4 -LAR1_1.ID0 3 -MCFG_1 0xF716 Message Configuration Register -MCFG_1.DLC7 7 -MCFG_1.DLC6 6 -MCFG_1.DLC5 5 -MCFG_1.DLC4 4 -MCFG_1.DIR 3 -MCFG_1.XTD 2 -DB0_1 0xF717 Message Data Byte 0 -DB0_1.DB07 7 -DB0_1.DB06 6 -DB0_1.DB05 5 -DB0_1.DB04 4 -DB0_1.DB03 3 -DB0_1.DB02 2 -DB0_1.DB01 1 -DB0_1.DB00 0 -DB1_1 0xF718 Message Data Byte 1 -DB1_1.DB17 7 -DB1_1.DB16 6 -DB1_1.DB15 5 -DB1_1.DB14 4 -DB1_1.DB13 3 -DB1_1.DB12 2 -DB1_1.DB11 1 -DB1_1.DB10 0 -DB2_1 0xF719 Message Data Byte 2 -DB2_1.DB27 7 -DB2_1.DB26 6 -DB2_1.DB25 5 -DB2_1.DB24 4 -DB2_1.DB23 3 -DB2_1.DB22 2 -DB2_1.DB21 1 -DB2_1.DB20 0 -DB3_1 0xF71A Message Data Byte 3 -DB3_1.DB37 7 -DB3_1.DB36 6 -DB3_1.DB35 5 -DB3_1.DB34 4 -DB3_1.DB33 3 -DB3_1.DB32 2 -DB3_1.DB31 1 -DB3_1.DB30 0 -DB4_1 0xF71B Message Data Byte 4 -DB4_1.DB47 7 -DB4_1.DB46 6 -DB4_1.DB45 5 -DB4_1.DB44 4 -DB4_1.DB43 3 -DB4_1.DB42 2 -DB4_1.DB41 1 -DB4_1.DB40 0 -DB5_1 0xF71C Message Data Byte 5 -DB5_1.DB57 7 -DB5_1.DB56 6 -DB5_1.DB55 5 -DB5_1.DB54 4 -DB5_1.DB53 3 -DB5_1.DB52 2 -DB5_1.DB51 1 -DB5_1.DB50 0 -DB6_1 0xF71D Message Data Byte 6 -DB6_1.DB67 7 -DB6_1.DB66 6 -DB6_1.DB65 5 -DB6_1.DB64 4 -DB6_1.DB63 3 -DB6_1.DB62 2 -DB6_1.DB61 1 -DB6_1.DB60 0 -DB7_1 0xF71E Message Data Byte 7 -DB7_1.DB77 7 -DB7_1.DB76 6 -DB7_1.DB75 5 -DB7_1.DB74 4 -DB7_1.DB73 3 -DB7_1.DB72 2 -DB7_1.DB71 1 -DB7_1.DB70 0 -RESERVEDF71F 0xF71F RESERVED -; -------------------------------------- CAN_2 -------------------------------- -MCR0_2 0xF720 Message Control Register Low -MCR0_2.MSGVAL1 7 -MCR0_2.MSGVAL0 6 -MCR0_2.TXIE1 5 -MCR0_2.TXIE0 4 -MCR0_2.RXIE1 3 -MCR0_2.RXIE0 2 -MCR0_2.INTPND1 1 -MCR0_2.INTPND0 0 -MCR1_2 0xF721 Message Control Register High -MCR1_2.RMTPND1 7 -MCR1_2.RMTPND0 6 -MCR1_2.TXRQ1 5 -MCR1_2.TXRQ0 4 -MCR1_2.MSGLSTCPUUPD1 3 -MCR1_2.MSGLSTCPUUPD0 2 -MCR1_2.NEWDAT1 1 -MCR1_2.NEWDAT0 0 -UAR0_2 0xF722 Upper Arbitration Register Low -UAR0_2.ID28 7 -UAR0_2.ID27 6 -UAR0_2.ID26 5 -UAR0_2.ID25 4 -UAR0_2.ID24 3 -UAR0_2.ID23 2 -UAR0_2.ID22 1 -UAR0_2.ID21 0 -UAR1_2 0xF723 Upper Arbitration Register High -UAR1_2.ID20 7 -UAR1_2.ID19 6 -UAR1_2.ID18 5 -UAR1_2.ID17 4 -UAR1_2.ID16 3 -UAR1_2.ID15 2 -UAR1_2.ID14 1 -UAR1_2.ID13 0 -LAR0_2 0xF724 Lower Arbitration Register Low -LAR0_2.ID12 7 -LAR0_2.ID11 6 -LAR0_2.ID10 5 -LAR0_2.ID9 4 -LAR0_2.ID8 3 -LAR0_2.ID7 2 -LAR0_2.ID6 1 -LAR0_2.ID5 0 -LAR1_2 0xF725 Lower Arbitration Register High -LAR1_2.ID4 7 -LAR1_2.ID3 6 -LAR1_2.ID2 5 -LAR1_2.ID1 4 -LAR1_2.ID0 3 -MCFG_2 0xF726 Message Configuration Register -MCFG_2.DLC7 7 -MCFG_2.DLC6 6 -MCFG_2.DLC5 5 -MCFG_2.DLC4 4 -MCFG_2.DIR 3 -MCFG_2.XTD 2 -DB0_2 0xF727 Message Data Byte 0 -DB0_2.DB07 7 -DB0_2.DB06 6 -DB0_2.DB05 5 -DB0_2.DB04 4 -DB0_2.DB03 3 -DB0_2.DB02 2 -DB0_2.DB01 1 -DB0_2.DB00 0 -DB1_2 0xF728 Message Data Byte 1 -DB1_2.DB17 7 -DB1_2.DB16 6 -DB1_2.DB15 5 -DB1_2.DB14 4 -DB1_2.DB13 3 -DB1_2.DB12 2 -DB1_2.DB11 1 -DB1_2.DB10 0 -DB2_2 0xF729 Message Data Byte 2 -DB2_2.DB27 7 -DB2_2.DB26 6 -DB2_2.DB25 5 -DB2_2.DB24 4 -DB2_2.DB23 3 -DB2_2.DB22 2 -DB2_2.DB21 1 -DB2_2.DB20 0 -DB3_2 0xF72A Message Data Byte 3 -DB3_2.DB37 7 -DB3_2.DB36 6 -DB3_2.DB35 5 -DB3_2.DB34 4 -DB3_2.DB33 3 -DB3_2.DB32 2 -DB3_2.DB31 1 -DB3_2.DB30 0 -DB4_2 0xF72B Message Data Byte 4 -DB4_2.DB47 7 -DB4_2.DB46 6 -DB4_2.DB45 5 -DB4_2.DB44 4 -DB4_2.DB43 3 -DB4_2.DB42 2 -DB4_2.DB41 1 -DB4_2.DB40 0 -DB5_2 0xF72C Message Data Byte 5 -DB5_2.DB57 7 -DB5_2.DB56 6 -DB5_2.DB55 5 -DB5_2.DB54 4 -DB5_2.DB53 3 -DB5_2.DB52 2 -DB5_2.DB51 1 -DB5_2.DB50 0 -DB6_2 0xF72D Message Data Byte 6 -DB6_2.DB67 7 -DB6_2.DB66 6 -DB6_2.DB65 5 -DB6_2.DB64 4 -DB6_2.DB63 3 -DB6_2.DB62 2 -DB6_2.DB61 1 -DB6_2.DB60 0 -DB7_2 0xF72E Message Data Byte 7 -DB7_2.DB77 7 -DB7_2.DB76 6 -DB7_2.DB75 5 -DB7_2.DB74 4 -DB7_2.DB73 3 -DB7_2.DB72 2 -DB7_2.DB71 1 -DB7_2.DB70 0 -RESERVEDF72F 0xF72F RESERVED -; -------------------------------------- CAN_3 -------------------------------- -MCR0_3 0xF730 Message Control Register Low -MCR0_3.MSGVAL1 7 -MCR0_3.MSGVAL0 6 -MCR0_3.TXIE1 5 -MCR0_3.TXIE0 4 -MCR0_3.RXIE1 3 -MCR0_3.RXIE0 2 -MCR0_3.INTPND1 1 -MCR0_3.INTPND0 0 -MCR1_3 0xF731 Message Control Register High -MCR1_3.RMTPND1 7 -MCR1_3.RMTPND0 6 -MCR1_3.TXRQ1 5 -MCR1_3.TXRQ0 4 -MCR1_3.MSGLSTCPUUPD1 3 -MCR1_3.MSGLSTCPUUPD0 2 -MCR1_3.NEWDAT1 1 -MCR1_3.NEWDAT0 0 -UAR0_3 0xF732 Upper Arbitration Register Low -UAR0_3.ID28 7 -UAR0_3.ID27 6 -UAR0_3.ID26 5 -UAR0_3.ID25 4 -UAR0_3.ID24 3 -UAR0_3.ID23 2 -UAR0_3.ID22 1 -UAR0_3.ID21 0 -UAR1_3 0xF733 Upper Arbitration Register High -UAR1_3.ID20 7 -UAR1_3.ID19 6 -UAR1_3.ID18 5 -UAR1_3.ID17 4 -UAR1_3.ID16 3 -UAR1_3.ID15 2 -UAR1_3.ID14 1 -UAR1_3.ID13 0 -LAR0_3 0xF734 Lower Arbitration Register Low -LAR0_3.ID12 7 -LAR0_3.ID11 6 -LAR0_3.ID10 5 -LAR0_3.ID9 4 -LAR0_3.ID8 3 -LAR0_3.ID7 2 -LAR0_3.ID6 1 -LAR0_3.ID5 0 -LAR1_3 0xF735 Lower Arbitration Register High -LAR1_3.ID4 7 -LAR1_3.ID3 6 -LAR1_3.ID2 5 -LAR1_3.ID1 4 -LAR1_3.ID0 3 -MCFG_3 0xF736 Message Configuration Register -MCFG_3.DLC7 7 -MCFG_3.DLC6 6 -MCFG_3.DLC5 5 -MCFG_3.DLC4 4 -MCFG_3.DIR 3 -MCFG_3.XTD 2 -DB0_3 0xF737 Message Data Byte 0 -DB0_3.DB07 7 -DB0_3.DB06 6 -DB0_3.DB05 5 -DB0_3.DB04 4 -DB0_3.DB03 3 -DB0_3.DB02 2 -DB0_3.DB01 1 -DB0_3.DB00 0 -DB1_3 0xF738 Message Data Byte 1 -DB1_3.DB17 7 -DB1_3.DB16 6 -DB1_3.DB15 5 -DB1_3.DB14 4 -DB1_3.DB13 3 -DB1_3.DB12 2 -DB1_3.DB11 1 -DB1_3.DB10 0 -DB2_3 0xF739 Message Data Byte 2 -DB2_3.DB27 7 -DB2_3.DB26 6 -DB2_3.DB25 5 -DB2_3.DB24 4 -DB2_3.DB23 3 -DB2_3.DB22 2 -DB2_3.DB21 1 -DB2_3.DB20 0 -DB3_3 0xF73A Message Data Byte 3 -DB3_3.DB37 7 -DB3_3.DB36 6 -DB3_3.DB35 5 -DB3_3.DB34 4 -DB3_3.DB33 3 -DB3_3.DB32 2 -DB3_3.DB31 1 -DB3_3.DB30 0 -DB4_3 0xF73B Message Data Byte 4 -DB4_3.DB47 7 -DB4_3.DB46 6 -DB4_3.DB45 5 -DB4_3.DB44 4 -DB4_3.DB43 3 -DB4_3.DB42 2 -DB4_3.DB41 1 -DB4_3.DB40 0 -DB5_3 0xF73C Message Data Byte 5 -DB5_3.DB57 7 -DB5_3.DB56 6 -DB5_3.DB55 5 -DB5_3.DB54 4 -DB5_3.DB53 3 -DB5_3.DB52 2 -DB5_3.DB51 1 -DB5_3.DB50 0 -DB6_3 0xF73D Message Data Byte 6 -DB6_3.DB67 7 -DB6_3.DB66 6 -DB6_3.DB65 5 -DB6_3.DB64 4 -DB6_3.DB63 3 -DB6_3.DB62 2 -DB6_3.DB61 1 -DB6_3.DB60 0 -DB7_3 0xF73E Message Data Byte 7 -DB7_3.DB77 7 -DB7_3.DB76 6 -DB7_3.DB75 5 -DB7_3.DB74 4 -DB7_3.DB73 3 -DB7_3.DB72 2 -DB7_3.DB71 1 -DB7_3.DB70 0 -RESERVEDF73F 0xF73F RESERVED -; -------------------------------------- CAN_4 -------------------------------- -MCR0_4 0xF740 Message Control Register Low -MCR0_4.MSGVAL1 7 -MCR0_4.MSGVAL0 6 -MCR0_4.TXIE1 5 -MCR0_4.TXIE0 4 -MCR0_4.RXIE1 3 -MCR0_4.RXIE0 2 -MCR0_4.INTPND1 1 -MCR0_4.INTPND0 0 -MCR1_4 0xF741 Message Control Register High -MCR1_4.RMTPND1 7 -MCR1_4.RMTPND0 6 -MCR1_4.TXRQ1 5 -MCR1_4.TXRQ0 4 -MCR1_4.MSGLSTCPUUPD1 3 -MCR1_4.MSGLSTCPUUPD0 2 -MCR1_4.NEWDAT1 1 -MCR1_4.NEWDAT0 0 -UAR0_4 0xF742 Upper Arbitration Register Low -UAR0_4.ID28 7 -UAR0_4.ID27 6 -UAR0_4.ID26 5 -UAR0_4.ID25 4 -UAR0_4.ID24 3 -UAR0_4.ID23 2 -UAR0_4.ID22 1 -UAR0_4.ID21 0 -UAR1_4 0xF743 Upper Arbitration Register High -UAR1_4.ID20 7 -UAR1_4.ID19 6 -UAR1_4.ID18 5 -UAR1_4.ID17 4 -UAR1_4.ID16 3 -UAR1_4.ID15 2 -UAR1_4.ID14 1 -UAR1_4.ID13 0 -LAR0_4 0xF744 Lower Arbitration Register Low -LAR0_4.ID12 7 -LAR0_4.ID11 6 -LAR0_4.ID10 5 -LAR0_4.ID9 4 -LAR0_4.ID8 3 -LAR0_4.ID7 2 -LAR0_4.ID6 1 -LAR0_4.ID5 0 -LAR1_4 0xF745 Lower Arbitration Register High -LAR1_4.ID4 7 -LAR1_4.ID3 6 -LAR1_4.ID2 5 -LAR1_4.ID1 4 -LAR1_4.ID0 3 -MCFG_4 0xF746 Message Configuration Register -MCFG_4.DLC7 7 -MCFG_4.DLC6 6 -MCFG_4.DLC5 5 -MCFG_4.DLC4 4 -MCFG_4.DIR 3 -MCFG_4.XTD 2 -DB0_4 0xF747 Message Data Byte 0 -DB0_4.DB07 7 -DB0_4.DB06 6 -DB0_4.DB05 5 -DB0_4.DB04 4 -DB0_4.DB03 3 -DB0_4.DB02 2 -DB0_4.DB01 1 -DB0_4.DB00 0 -DB1_4 0xF748 Message Data Byte 1 -DB1_4.DB17 7 -DB1_4.DB16 6 -DB1_4.DB15 5 -DB1_4.DB14 4 -DB1_4.DB13 3 -DB1_4.DB12 2 -DB1_4.DB11 1 -DB1_4.DB10 0 -DB2_4 0xF749 Message Data Byte 2 -DB2_4.DB27 7 -DB2_4.DB26 6 -DB2_4.DB25 5 -DB2_4.DB24 4 -DB2_4.DB23 3 -DB2_4.DB22 2 -DB2_4.DB21 1 -DB2_4.DB20 0 -DB3_4 0xF74A Message Data Byte 3 -DB3_4.DB37 7 -DB3_4.DB36 6 -DB3_4.DB35 5 -DB3_4.DB34 4 -DB3_4.DB33 3 -DB3_4.DB32 2 -DB3_4.DB31 1 -DB3_4.DB30 0 -DB4_4 0xF74B Message Data Byte 4 -DB4_4.DB47 7 -DB4_4.DB46 6 -DB4_4.DB45 5 -DB4_4.DB44 4 -DB4_4.DB43 3 -DB4_4.DB42 2 -DB4_4.DB41 1 -DB4_4.DB40 0 -DB5_4 0xF74C Message Data Byte 5 -DB5_4.DB57 7 -DB5_4.DB56 6 -DB5_4.DB55 5 -DB5_4.DB54 4 -DB5_4.DB53 3 -DB5_4.DB52 2 -DB5_4.DB51 1 -DB5_4.DB50 0 -DB6_4 0xF74D Message Data Byte 6 -DB6_4.DB67 7 -DB6_4.DB66 6 -DB6_4.DB65 5 -DB6_4.DB64 4 -DB6_4.DB63 3 -DB6_4.DB62 2 -DB6_4.DB61 1 -DB6_4.DB60 0 -DB7_4 0xF74E Message Data Byte 7 -DB7_4.DB77 7 -DB7_4.DB76 6 -DB7_4.DB75 5 -DB7_4.DB74 4 -DB7_4.DB73 3 -DB7_4.DB72 2 -DB7_4.DB71 1 -DB7_4.DB70 0 -RESERVEDF74F 0xF74F RESERVED -; -------------------------------------- CAN_5 -------------------------------- -MCR0_5 0xF750 Message Control Register Low -MCR0_5.MSGVAL1 7 -MCR0_5.MSGVAL0 6 -MCR0_5.TXIE1 5 -MCR0_5.TXIE0 4 -MCR0_5.RXIE1 3 -MCR0_5.RXIE0 2 -MCR0_5.INTPND1 1 -MCR0_5.INTPND0 0 -MCR1_5 0xF751 Message Control Register High -MCR1_5.RMTPND1 7 -MCR1_5.RMTPND0 6 -MCR1_5.TXRQ1 5 -MCR1_5.TXRQ0 4 -MCR1_5.MSGLSTCPUUPD1 3 -MCR1_5.MSGLSTCPUUPD0 2 -MCR1_5.NEWDAT1 1 -MCR1_5.NEWDAT0 0 -UAR0_5 0xF752 Upper Arbitration Register Low -UAR0_5.ID28 7 -UAR0_5.ID27 6 -UAR0_5.ID26 5 -UAR0_5.ID25 4 -UAR0_5.ID24 3 -UAR0_5.ID23 2 -UAR0_5.ID22 1 -UAR0_5.ID21 0 -UAR1_5 0xF753 Upper Arbitration Register High -UAR1_5.ID20 7 -UAR1_5.ID19 6 -UAR1_5.ID18 5 -UAR1_5.ID17 4 -UAR1_5.ID16 3 -UAR1_5.ID15 2 -UAR1_5.ID14 1 -UAR1_5.ID13 0 -LAR0_5 0xF754 Lower Arbitration Register Low -LAR0_5.ID12 7 -LAR0_5.ID11 6 -LAR0_5.ID10 5 -LAR0_5.ID9 4 -LAR0_5.ID8 3 -LAR0_5.ID7 2 -LAR0_5.ID6 1 -LAR0_5.ID5 0 -LAR1_5 0xF755 Lower Arbitration Register High -LAR1_5.ID4 7 -LAR1_5.ID3 6 -LAR1_5.ID2 5 -LAR1_5.ID1 4 -LAR1_5.ID0 3 -MCFG_5 0xF756 Message Configuration Register -MCFG_5.DLC7 7 -MCFG_5.DLC6 6 -MCFG_5.DLC5 5 -MCFG_5.DLC4 4 -MCFG_5.DIR 3 -MCFG_5.XTD 2 -DB0_5 0xF757 Message Data Byte 0 -DB0_5.DB07 7 -DB0_5.DB06 6 -DB0_5.DB05 5 -DB0_5.DB04 4 -DB0_5.DB03 3 -DB0_5.DB02 2 -DB0_5.DB01 1 -DB0_5.DB00 0 -DB1_5 0xF758 Message Data Byte 1 -DB1_5.DB17 7 -DB1_5.DB16 6 -DB1_5.DB15 5 -DB1_5.DB14 4 -DB1_5.DB13 3 -DB1_5.DB12 2 -DB1_5.DB11 1 -DB1_5.DB10 0 -DB2_5 0xF759 Message Data Byte 2 -DB2_5.DB27 7 -DB2_5.DB26 6 -DB2_5.DB25 5 -DB2_5.DB24 4 -DB2_5.DB23 3 -DB2_5.DB22 2 -DB2_5.DB21 1 -DB2_5.DB20 0 -DB3_5 0xF75A Message Data Byte 3 -DB3_5.DB37 7 -DB3_5.DB36 6 -DB3_5.DB35 5 -DB3_5.DB34 4 -DB3_5.DB33 3 -DB3_5.DB32 2 -DB3_5.DB31 1 -DB3_5.DB30 0 -DB4_5 0xF75B Message Data Byte 4 -DB4_5.DB47 7 -DB4_5.DB46 6 -DB4_5.DB45 5 -DB4_5.DB44 4 -DB4_5.DB43 3 -DB4_5.DB42 2 -DB4_5.DB41 1 -DB4_5.DB40 0 -DB5_5 0xF75C Message Data Byte 5 -DB5_5.DB57 7 -DB5_5.DB56 6 -DB5_5.DB55 5 -DB5_5.DB54 4 -DB5_5.DB53 3 -DB5_5.DB52 2 -DB5_5.DB51 1 -DB5_5.DB50 0 -DB6_5 0xF75D Message Data Byte 6 -DB6_5.DB67 7 -DB6_5.DB66 6 -DB6_5.DB65 5 -DB6_5.DB64 4 -DB6_5.DB63 3 -DB6_5.DB62 2 -DB6_5.DB61 1 -DB6_5.DB60 0 -DB7_5 0xF75E Message Data Byte 7 -DB7_5.DB77 7 -DB7_5.DB76 6 -DB7_5.DB75 5 -DB7_5.DB74 4 -DB7_5.DB73 3 -DB7_5.DB72 2 -DB7_5.DB71 1 -DB7_5.DB70 0 -RESERVEDF75F 0xF75F RESERVED -; -------------------------------------- CAN_6 -------------------------------- -MCR0_6 0xF760 Message Control Register Low -MCR0_6.MSGVAL1 7 -MCR0_6.MSGVAL0 6 -MCR0_6.TXIE1 5 -MCR0_6.TXIE0 4 -MCR0_6.RXIE1 3 -MCR0_6.RXIE0 2 -MCR0_6.INTPND1 1 -MCR0_6.INTPND0 0 -MCR1_6 0xF761 Message Control Register High -MCR1_6.RMTPND1 7 -MCR1_6.RMTPND0 6 -MCR1_6.TXRQ1 5 -MCR1_6.TXRQ0 4 -MCR1_6.MSGLSTCPUUPD1 3 -MCR1_6.MSGLSTCPUUPD0 2 -MCR1_6.NEWDAT1 1 -MCR1_6.NEWDAT0 0 -UAR0_6 0xF762 Upper Arbitration Register Low -UAR0_6.ID28 7 -UAR0_6.ID27 6 -UAR0_6.ID26 5 -UAR0_6.ID25 4 -UAR0_6.ID24 3 -UAR0_6.ID23 2 -UAR0_6.ID22 1 -UAR0_6.ID21 0 -UAR1_6 0xF763 Upper Arbitration Register High -UAR1_6.ID20 7 -UAR1_6.ID19 6 -UAR1_6.ID18 5 -UAR1_6.ID17 4 -UAR1_6.ID16 3 -UAR1_6.ID15 2 -UAR1_6.ID14 1 -UAR1_6.ID13 0 -LAR0_6 0xF764 Lower Arbitration Register Low -LAR0_6.ID12 7 -LAR0_6.ID11 6 -LAR0_6.ID10 5 -LAR0_6.ID9 4 -LAR0_6.ID8 3 -LAR0_6.ID7 2 -LAR0_6.ID6 1 -LAR0_6.ID5 0 -LAR1_6 0xF765 Lower Arbitration Register High -LAR1_6.ID4 7 -LAR1_6.ID3 6 -LAR1_6.ID2 5 -LAR1_6.ID1 4 -LAR1_6.ID0 3 -MCFG_6 0xF766 Message Configuration Register -MCFG_6.DLC7 7 -MCFG_6.DLC6 6 -MCFG_6.DLC5 5 -MCFG_6.DLC4 4 -MCFG_6.DIR 3 -MCFG_6.XTD 2 -DB0_6 0xF767 Message Data Byte 0 -DB0_6.DB07 7 -DB0_6.DB06 6 -DB0_6.DB05 5 -DB0_6.DB04 4 -DB0_6.DB03 3 -DB0_6.DB02 2 -DB0_6.DB01 1 -DB0_6.DB00 0 -DB1_6 0xF768 Message Data Byte 1 -DB1_6.DB17 7 -DB1_6.DB16 6 -DB1_6.DB15 5 -DB1_6.DB14 4 -DB1_6.DB13 3 -DB1_6.DB12 2 -DB1_6.DB11 1 -DB1_6.DB10 0 -DB2_6 0xF769 Message Data Byte 2 -DB2_6.DB27 7 -DB2_6.DB26 6 -DB2_6.DB25 5 -DB2_6.DB24 4 -DB2_6.DB23 3 -DB2_6.DB22 2 -DB2_6.DB21 1 -DB2_6.DB20 0 -DB3_6 0xF76A Message Data Byte 3 -DB3_6.DB37 7 -DB3_6.DB36 6 -DB3_6.DB35 5 -DB3_6.DB34 4 -DB3_6.DB33 3 -DB3_6.DB32 2 -DB3_6.DB31 1 -DB3_6.DB30 0 -DB4_6 0xF76B Message Data Byte 4 -DB4_6.DB47 7 -DB4_6.DB46 6 -DB4_6.DB45 5 -DB4_6.DB44 4 -DB4_6.DB43 3 -DB4_6.DB42 2 -DB4_6.DB41 1 -DB4_6.DB40 0 -DB5_6 0xF76C Message Data Byte 5 -DB5_6.DB57 7 -DB5_6.DB56 6 -DB5_6.DB55 5 -DB5_6.DB54 4 -DB5_6.DB53 3 -DB5_6.DB52 2 -DB5_6.DB51 1 -DB5_6.DB50 0 -DB6_6 0xF76D Message Data Byte 6 -DB6_6.DB67 7 -DB6_6.DB66 6 -DB6_6.DB65 5 -DB6_6.DB64 4 -DB6_6.DB63 3 -DB6_6.DB62 2 -DB6_6.DB61 1 -DB6_6.DB60 0 -DB7_6 0xF76E Message Data Byte 7 -DB7_6.DB77 7 -DB7_6.DB76 6 -DB7_6.DB75 5 -DB7_6.DB74 4 -DB7_6.DB73 3 -DB7_6.DB72 2 -DB7_6.DB71 1 -DB7_6.DB70 0 -RESERVEDF76F 0xF76F RESERVED -; -------------------------------------- CAN_7 -------------------------------- -MCR0_7 0xF770 Message Control Register Low -MCR0_7.MSGVAL1 7 -MCR0_7.MSGVAL0 6 -MCR0_7.TXIE1 5 -MCR0_7.TXIE0 4 -MCR0_7.RXIE1 3 -MCR0_7.RXIE0 2 -MCR0_7.INTPND1 1 -MCR0_7.INTPND0 0 -MCR1_7 0xF771 Message Control Register High -MCR1_7.RMTPND1 7 -MCR1_7.RMTPND0 6 -MCR1_7.TXRQ1 5 -MCR1_7.TXRQ0 4 -MCR1_7.MSGLSTCPUUPD1 3 -MCR1_7.MSGLSTCPUUPD0 2 -MCR1_7.NEWDAT1 1 -MCR1_7.NEWDAT0 0 -UAR0_7 0xF772 Upper Arbitration Register Low -UAR0_7.ID28 7 -UAR0_7.ID27 6 -UAR0_7.ID26 5 -UAR0_7.ID25 4 -UAR0_7.ID24 3 -UAR0_7.ID23 2 -UAR0_7.ID22 1 -UAR0_7.ID21 0 -UAR1_7 0xF773 Upper Arbitration Register High -UAR1_7.ID20 7 -UAR1_7.ID19 6 -UAR1_7.ID18 5 -UAR1_7.ID17 4 -UAR1_7.ID16 3 -UAR1_7.ID15 2 -UAR1_7.ID14 1 -UAR1_7.ID13 0 -LAR0_7 0xF774 Lower Arbitration Register Low -LAR0_7.ID12 7 -LAR0_7.ID11 6 -LAR0_7.ID10 5 -LAR0_7.ID9 4 -LAR0_7.ID8 3 -LAR0_7.ID7 2 -LAR0_7.ID6 1 -LAR0_7.ID5 0 -LAR1_7 0xF775 Lower Arbitration Register High -LAR1_7.ID4 7 -LAR1_7.ID3 6 -LAR1_7.ID2 5 -LAR1_7.ID1 4 -LAR1_7.ID0 3 -MCFG_7 0xF776 Message Configuration Register -MCFG_7.DLC7 7 -MCFG_7.DLC6 6 -MCFG_7.DLC5 5 -MCFG_7.DLC4 4 -MCFG_7.DIR 3 -MCFG_7.XTD 2 -DB0_7 0xF777 Message Data Byte 0 -DB0_7.DB07 7 -DB0_7.DB06 6 -DB0_7.DB05 5 -DB0_7.DB04 4 -DB0_7.DB03 3 -DB0_7.DB02 2 -DB0_7.DB01 1 -DB0_7.DB00 0 -DB1_7 0xF778 Message Data Byte 1 -DB1_7.DB17 7 -DB1_7.DB16 6 -DB1_7.DB15 5 -DB1_7.DB14 4 -DB1_7.DB13 3 -DB1_7.DB12 2 -DB1_7.DB11 1 -DB1_7.DB10 0 -DB2_7 0xF779 Message Data Byte 2 -DB2_7.DB27 7 -DB2_7.DB26 6 -DB2_7.DB25 5 -DB2_7.DB24 4 -DB2_7.DB23 3 -DB2_7.DB22 2 -DB2_7.DB21 1 -DB2_7.DB20 0 -DB3_7 0xF77A Message Data Byte 3 -DB3_7.DB37 7 -DB3_7.DB36 6 -DB3_7.DB35 5 -DB3_7.DB34 4 -DB3_7.DB33 3 -DB3_7.DB32 2 -DB3_7.DB31 1 -DB3_7.DB30 0 -DB4_7 0xF77B Message Data Byte 4 -DB4_7.DB47 7 -DB4_7.DB46 6 -DB4_7.DB45 5 -DB4_7.DB44 4 -DB4_7.DB43 3 -DB4_7.DB42 2 -DB4_7.DB41 1 -DB4_7.DB40 0 -DB5_7 0xF77C Message Data Byte 5 -DB5_7.DB57 7 -DB5_7.DB56 6 -DB5_7.DB55 5 -DB5_7.DB54 4 -DB5_7.DB53 3 -DB5_7.DB52 2 -DB5_7.DB51 1 -DB5_7.DB50 0 -DB6_7 0xF77D Message Data Byte 6 -DB6_7.DB67 7 -DB6_7.DB66 6 -DB6_7.DB65 5 -DB6_7.DB64 4 -DB6_7.DB63 3 -DB6_7.DB62 2 -DB6_7.DB61 1 -DB6_7.DB60 0 -DB7_7 0xF77E Message Data Byte 7 -DB7_7.DB77 7 -DB7_7.DB76 6 -DB7_7.DB75 5 -DB7_7.DB74 4 -DB7_7.DB73 3 -DB7_7.DB72 2 -DB7_7.DB71 1 -DB7_7.DB70 0 -RESERVEDF77F 0xF77F RESERVED -; -------------------------------------- CAN_8 -------------------------------- -MCR0_8 0xF780 Message Control Register Low -MCR0_8.MSGVAL1 7 -MCR0_8.MSGVAL0 6 -MCR0_8.TXIE1 5 -MCR0_8.TXIE0 4 -MCR0_8.RXIE1 3 -MCR0_8.RXIE0 2 -MCR0_8.INTPND1 1 -MCR0_8.INTPND0 0 -MCR1_8 0xF781 Message Control Register High -MCR1_8.RMTPND1 7 -MCR1_8.RMTPND0 6 -MCR1_8.TXRQ1 5 -MCR1_8.TXRQ0 4 -MCR1_8.MSGLSTCPUUPD1 3 -MCR1_8.MSGLSTCPUUPD0 2 -MCR1_8.NEWDAT1 1 -MCR1_8.NEWDAT0 0 -UAR0_8 0xF782 Upper Arbitration Register Low -UAR0_8.ID28 7 -UAR0_8.ID27 6 -UAR0_8.ID26 5 -UAR0_8.ID25 4 -UAR0_8.ID24 3 -UAR0_8.ID23 2 -UAR0_8.ID22 1 -UAR0_8.ID21 0 -UAR1_8 0xF783 Upper Arbitration Register High -UAR1_8.ID20 7 -UAR1_8.ID19 6 -UAR1_8.ID18 5 -UAR1_8.ID17 4 -UAR1_8.ID16 3 -UAR1_8.ID15 2 -UAR1_8.ID14 1 -UAR1_8.ID13 0 -LAR0_8 0xF784 Lower Arbitration Register Low -LAR0_8.ID12 7 -LAR0_8.ID11 6 -LAR0_8.ID10 5 -LAR0_8.ID9 4 -LAR0_8.ID8 3 -LAR0_8.ID7 2 -LAR0_8.ID6 1 -LAR0_8.ID5 0 -LAR1_8 0xF785 Lower Arbitration Register High -LAR1_8.ID4 7 -LAR1_8.ID3 6 -LAR1_8.ID2 5 -LAR1_8.ID1 4 -LAR1_8.ID0 3 -MCFG_8 0xF786 Message Configuration Register -MCFG_8.DLC7 7 -MCFG_8.DLC6 6 -MCFG_8.DLC5 5 -MCFG_8.DLC4 4 -MCFG_8.DIR 3 -MCFG_8.XTD 2 -DB0_8 0xF787 Message Data Byte 0 -DB0_8.DB07 7 -DB0_8.DB06 6 -DB0_8.DB05 5 -DB0_8.DB04 4 -DB0_8.DB03 3 -DB0_8.DB02 2 -DB0_8.DB01 1 -DB0_8.DB00 0 -DB1_8 0xF788 Message Data Byte 1 -DB1_8.DB17 7 -DB1_8.DB16 6 -DB1_8.DB15 5 -DB1_8.DB14 4 -DB1_8.DB13 3 -DB1_8.DB12 2 -DB1_8.DB11 1 -DB1_8.DB10 0 -DB2_8 0xF789 Message Data Byte 2 -DB2_8.DB27 7 -DB2_8.DB26 6 -DB2_8.DB25 5 -DB2_8.DB24 4 -DB2_8.DB23 3 -DB2_8.DB22 2 -DB2_8.DB21 1 -DB2_8.DB20 0 -DB3_8 0xF78A Message Data Byte 3 -DB3_8.DB37 7 -DB3_8.DB36 6 -DB3_8.DB35 5 -DB3_8.DB34 4 -DB3_8.DB33 3 -DB3_8.DB32 2 -DB3_8.DB31 1 -DB3_8.DB30 0 -DB4_8 0xF78B Message Data Byte 4 -DB4_8.DB47 7 -DB4_8.DB46 6 -DB4_8.DB45 5 -DB4_8.DB44 4 -DB4_8.DB43 3 -DB4_8.DB42 2 -DB4_8.DB41 1 -DB4_8.DB40 0 -DB5_8 0xF78C Message Data Byte 5 -DB5_8.DB57 7 -DB5_8.DB56 6 -DB5_8.DB55 5 -DB5_8.DB54 4 -DB5_8.DB53 3 -DB5_8.DB52 2 -DB5_8.DB51 1 -DB5_8.DB50 0 -DB6_8 0xF78D Message Data Byte 6 -DB6_8.DB67 7 -DB6_8.DB66 6 -DB6_8.DB65 5 -DB6_8.DB64 4 -DB6_8.DB63 3 -DB6_8.DB62 2 -DB6_8.DB61 1 -DB6_8.DB60 0 -DB7_8 0xF78E Message Data Byte 7 -DB7_8.DB77 7 -DB7_8.DB76 6 -DB7_8.DB75 5 -DB7_8.DB74 4 -DB7_8.DB73 3 -DB7_8.DB72 2 -DB7_8.DB71 1 -DB7_8.DB70 0 -RESERVEDF78F 0xF78F RESERVED -; -------------------------------------- CAN_9 -------------------------------- -MCR0_9 0xF790 Message Control Register Low -MCR0_9.MSGVAL1 7 -MCR0_9.MSGVAL0 6 -MCR0_9.TXIE1 5 -MCR0_9.TXIE0 4 -MCR0_9.RXIE1 3 -MCR0_9.RXIE0 2 -MCR0_9.INTPND1 1 -MCR0_9.INTPND0 0 -MCR1_9 0xF791 Message Control Register High -MCR1_9.RMTPND1 7 -MCR1_9.RMTPND0 6 -MCR1_9.TXRQ1 5 -MCR1_9.TXRQ0 4 -MCR1_9.MSGLSTCPUUPD1 3 -MCR1_9.MSGLSTCPUUPD0 2 -MCR1_9.NEWDAT1 1 -MCR1_9.NEWDAT0 0 -UAR0_9 0xF792 Upper Arbitration Register Low -UAR0_9.ID28 7 -UAR0_9.ID27 6 -UAR0_9.ID26 5 -UAR0_9.ID25 4 -UAR0_9.ID24 3 -UAR0_9.ID23 2 -UAR0_9.ID22 1 -UAR0_9.ID21 0 -UAR1_9 0xF793 Upper Arbitration Register High -UAR1_9.ID20 7 -UAR1_9.ID19 6 -UAR1_9.ID18 5 -UAR1_9.ID17 4 -UAR1_9.ID16 3 -UAR1_9.ID15 2 -UAR1_9.ID14 1 -UAR1_9.ID13 0 -LAR0_9 0xF794 Lower Arbitration Register Low -LAR0_9.ID12 7 -LAR0_9.ID11 6 -LAR0_9.ID10 5 -LAR0_9.ID9 4 -LAR0_9.ID8 3 -LAR0_9.ID7 2 -LAR0_9.ID6 1 -LAR0_9.ID5 0 -LAR1_9 0xF795 Lower Arbitration Register High -LAR1_9.ID4 7 -LAR1_9.ID3 6 -LAR1_9.ID2 5 -LAR1_9.ID1 4 -LAR1_9.ID0 3 -MCFG_9 0xF796 Message Configuration Register -MCFG_9.DLC7 7 -MCFG_9.DLC6 6 -MCFG_9.DLC5 5 -MCFG_9.DLC4 4 -MCFG_9.DIR 3 -MCFG_9.XTD 2 -DB0_9 0xF797 Message Data Byte 0 -DB0_9.DB07 7 -DB0_9.DB06 6 -DB0_9.DB05 5 -DB0_9.DB04 4 -DB0_9.DB03 3 -DB0_9.DB02 2 -DB0_9.DB01 1 -DB0_9.DB00 0 -DB1_9 0xF798 Message Data Byte 1 -DB1_9.DB17 7 -DB1_9.DB16 6 -DB1_9.DB15 5 -DB1_9.DB14 4 -DB1_9.DB13 3 -DB1_9.DB12 2 -DB1_9.DB11 1 -DB1_9.DB10 0 -DB2_9 0xF799 Message Data Byte 2 -DB2_9.DB27 7 -DB2_9.DB26 6 -DB2_9.DB25 5 -DB2_9.DB24 4 -DB2_9.DB23 3 -DB2_9.DB22 2 -DB2_9.DB21 1 -DB2_9.DB20 0 -DB3_9 0xF79A Message Data Byte 3 -DB3_9.DB37 7 -DB3_9.DB36 6 -DB3_9.DB35 5 -DB3_9.DB34 4 -DB3_9.DB33 3 -DB3_9.DB32 2 -DB3_9.DB31 1 -DB3_9.DB30 0 -DB4_9 0xF79B Message Data Byte 4 -DB4_9.DB47 7 -DB4_9.DB46 6 -DB4_9.DB45 5 -DB4_9.DB44 4 -DB4_9.DB43 3 -DB4_9.DB42 2 -DB4_9.DB41 1 -DB4_9.DB40 0 -DB5_9 0xF79C Message Data Byte 5 -DB5_9.DB57 7 -DB5_9.DB56 6 -DB5_9.DB55 5 -DB5_9.DB54 4 -DB5_9.DB53 3 -DB5_9.DB52 2 -DB5_9.DB51 1 -DB5_9.DB50 0 -DB6_9 0xF79D Message Data Byte 6 -DB6_9.DB67 7 -DB6_9.DB66 6 -DB6_9.DB65 5 -DB6_9.DB64 4 -DB6_9.DB63 3 -DB6_9.DB62 2 -DB6_9.DB61 1 -DB6_9.DB60 0 -DB7_9 0xF79E Message Data Byte 7 -DB7_9.DB77 7 -DB7_9.DB76 6 -DB7_9.DB75 5 -DB7_9.DB74 4 -DB7_9.DB73 3 -DB7_9.DB72 2 -DB7_9.DB71 1 -DB7_9.DB70 0 -RESERVEDF79F 0xF79F RESERVED -; -------------------------------------- CAN_A -------------------------------- -MCR0_A 0xF7A0 Message Control Register Low -MCR0_A.MSGVAL1 7 -MCR0_A.MSGVAL0 6 -MCR0_A.TXIE1 5 -MCR0_A.TXIE0 4 -MCR0_A.RXIE1 3 -MCR0_A.RXIE0 2 -MCR0_A.INTPND1 1 -MCR0_A.INTPND0 0 -MCR1_A 0xF7A1 Message Control Register High -MCR1_A.RMTPND1 7 -MCR1_A.RMTPND0 6 -MCR1_A.TXRQ1 5 -MCR1_A.TXRQ0 4 -MCR1_A.MSGLSTCPUUPD1 3 -MCR1_A.MSGLSTCPUUPD0 2 -MCR1_A.NEWDAT1 1 -MCR1_A.NEWDAT0 0 -UAR0_A 0xF7A2 Upper Arbitration Register Low -UAR0_A.ID28 7 -UAR0_A.ID27 6 -UAR0_A.ID26 5 -UAR0_A.ID25 4 -UAR0_A.ID24 3 -UAR0_A.ID23 2 -UAR0_A.ID22 1 -UAR0_A.ID21 0 -UAR1_A 0xF7A3 Upper Arbitration Register High -UAR1_A.ID20 7 -UAR1_A.ID19 6 -UAR1_A.ID18 5 -UAR1_A.ID17 4 -UAR1_A.ID16 3 -UAR1_A.ID15 2 -UAR1_A.ID14 1 -UAR1_A.ID13 0 -LAR0_A 0xF7A4 Lower Arbitration Register Low -LAR0_A.ID12 7 -LAR0_A.ID11 6 -LAR0_A.ID10 5 -LAR0_A.ID9 4 -LAR0_A.ID8 3 -LAR0_A.ID7 2 -LAR0_A.ID6 1 -LAR0_A.ID5 0 -LAR1_A 0xF7A5 Lower Arbitration Register High -LAR1_A.ID4 7 -LAR1_A.ID3 6 -LAR1_A.ID2 5 -LAR1_A.ID1 4 -LAR1_A.ID0 3 -MCFG_A 0xF7A6 Message Configuration Register -MCFG_A.DLC7 7 -MCFG_A.DLC6 6 -MCFG_A.DLC5 5 -MCFG_A.DLC4 4 -MCFG_A.DIR 3 -MCFG_A.XTD 2 -DB0_A 0xF7A7 Message Data Byte 0 -DB0_A.DB07 7 -DB0_A.DB06 6 -DB0_A.DB05 5 -DB0_A.DB04 4 -DB0_A.DB03 3 -DB0_A.DB02 2 -DB0_A.DB01 1 -DB0_A.DB00 0 -DB1_A 0xF7A8 Message Data Byte 1 -DB1_A.DB17 7 -DB1_A.DB16 6 -DB1_A.DB15 5 -DB1_A.DB14 4 -DB1_A.DB13 3 -DB1_A.DB12 2 -DB1_A.DB11 1 -DB1_A.DB10 0 -DB2_A 0xF7A9 Message Data Byte 2 -DB2_A.DB27 7 -DB2_A.DB26 6 -DB2_A.DB25 5 -DB2_A.DB24 4 -DB2_A.DB23 3 -DB2_A.DB22 2 -DB2_A.DB21 1 -DB2_A.DB20 0 -DB3_A 0xF7AA Message Data Byte 3 -DB3_A.DB37 7 -DB3_A.DB36 6 -DB3_A.DB35 5 -DB3_A.DB34 4 -DB3_A.DB33 3 -DB3_A.DB32 2 -DB3_A.DB31 1 -DB3_A.DB30 0 -DB4_A 0xF7AB Message Data Byte 4 -DB4_A.DB47 7 -DB4_A.DB46 6 -DB4_A.DB45 5 -DB4_A.DB44 4 -DB4_A.DB43 3 -DB4_A.DB42 2 -DB4_A.DB41 1 -DB4_A.DB40 0 -DB5_A 0xF7AC Message Data Byte 5 -DB5_A.DB57 7 -DB5_A.DB56 6 -DB5_A.DB55 5 -DB5_A.DB54 4 -DB5_A.DB53 3 -DB5_A.DB52 2 -DB5_A.DB51 1 -DB5_A.DB50 0 -DB6_A 0xF7AD Message Data Byte 6 -DB6_A.DB67 7 -DB6_A.DB66 6 -DB6_A.DB65 5 -DB6_A.DB64 4 -DB6_A.DB63 3 -DB6_A.DB62 2 -DB6_A.DB61 1 -DB6_A.DB60 0 -DB7_A 0xF7AE Message Data Byte 7 -DB7_A.DB77 7 -DB7_A.DB76 6 -DB7_A.DB75 5 -DB7_A.DB74 4 -DB7_A.DB73 3 -DB7_A.DB72 2 -DB7_A.DB71 1 -DB7_A.DB70 0 -RESERVEDF7AF 0xF7AF RESERVED -; -------------------------------------- CAN_B -------------------------------- -MCR0_B 0xF7B0 Message Control Register Low -MCR0_B.MSGVAL1 7 -MCR0_B.MSGVAL0 6 -MCR0_B.TXIE1 5 -MCR0_B.TXIE0 4 -MCR0_B.RXIE1 3 -MCR0_B.RXIE0 2 -MCR0_B.INTPND1 1 -MCR0_B.INTPND0 0 -MCR1_B 0xF7B1 Message Control Register High -MCR1_B.RMTPND1 7 -MCR1_B.RMTPND0 6 -MCR1_B.TXRQ1 5 -MCR1_B.TXRQ0 4 -MCR1_B.MSGLSTCPUUPD1 3 -MCR1_B.MSGLSTCPUUPD0 2 -MCR1_B.NEWDAT1 1 -MCR1_B.NEWDAT0 0 -UAR0_B 0xF7B2 Upper Arbitration Register Low -UAR0_B.ID28 7 -UAR0_B.ID27 6 -UAR0_B.ID26 5 -UAR0_B.ID25 4 -UAR0_B.ID24 3 -UAR0_B.ID23 2 -UAR0_B.ID22 1 -UAR0_B.ID21 0 -UAR1_B 0xF7B3 Upper Arbitration Register High -UAR1_B.ID20 7 -UAR1_B.ID19 6 -UAR1_B.ID18 5 -UAR1_B.ID17 4 -UAR1_B.ID16 3 -UAR1_B.ID15 2 -UAR1_B.ID14 1 -UAR1_B.ID13 0 -LAR0_B 0xF7B4 Lower Arbitration Register Low -LAR0_B.ID12 7 -LAR0_B.ID11 6 -LAR0_B.ID10 5 -LAR0_B.ID9 4 -LAR0_B.ID8 3 -LAR0_B.ID7 2 -LAR0_B.ID6 1 -LAR0_B.ID5 0 -LAR1_B 0xF7B5 Lower Arbitration Register High -LAR1_B.ID4 7 -LAR1_B.ID3 6 -LAR1_B.ID2 5 -LAR1_B.ID1 4 -LAR1_B.ID0 3 -MCFG_B 0xF7B6 Message Configuration Register -MCFG_B.DLC7 7 -MCFG_B.DLC6 6 -MCFG_B.DLC5 5 -MCFG_B.DLC4 4 -MCFG_B.DIR 3 -MCFG_B.XTD 2 -DB0_B 0xF7B7 Message Data Byte 0 -DB0_B.DB07 7 -DB0_B.DB06 6 -DB0_B.DB05 5 -DB0_B.DB04 4 -DB0_B.DB03 3 -DB0_B.DB02 2 -DB0_B.DB01 1 -DB0_B.DB00 0 -DB1_B 0xF7B8 Message Data Byte 1 -DB1_B.DB17 7 -DB1_B.DB16 6 -DB1_B.DB15 5 -DB1_B.DB14 4 -DB1_B.DB13 3 -DB1_B.DB12 2 -DB1_B.DB11 1 -DB1_B.DB10 0 -DB2_B 0xF7B9 Message Data Byte 2 -DB2_B.DB27 7 -DB2_B.DB26 6 -DB2_B.DB25 5 -DB2_B.DB24 4 -DB2_B.DB23 3 -DB2_B.DB22 2 -DB2_B.DB21 1 -DB2_B.DB20 0 -DB3_B 0xF7BA Message Data Byte 3 -DB3_B.DB37 7 -DB3_B.DB36 6 -DB3_B.DB35 5 -DB3_B.DB34 4 -DB3_B.DB33 3 -DB3_B.DB32 2 -DB3_B.DB31 1 -DB3_B.DB30 0 -DB4_B 0xF7BB Message Data Byte 4 -DB4_B.DB47 7 -DB4_B.DB46 6 -DB4_B.DB45 5 -DB4_B.DB44 4 -DB4_B.DB43 3 -DB4_B.DB42 2 -DB4_B.DB41 1 -DB4_B.DB40 0 -DB5_B 0xF7BC Message Data Byte 5 -DB5_B.DB57 7 -DB5_B.DB56 6 -DB5_B.DB55 5 -DB5_B.DB54 4 -DB5_B.DB53 3 -DB5_B.DB52 2 -DB5_B.DB51 1 -DB5_B.DB50 0 -DB6_B 0xF7BD Message Data Byte 6 -DB6_B.DB67 7 -DB6_B.DB66 6 -DB6_B.DB65 5 -DB6_B.DB64 4 -DB6_B.DB63 3 -DB6_B.DB62 2 -DB6_B.DB61 1 -DB6_B.DB60 0 -DB7_B 0xF7BE Message Data Byte 7 -DB7_B.DB77 7 -DB7_B.DB76 6 -DB7_B.DB75 5 -DB7_B.DB74 4 -DB7_B.DB73 3 -DB7_B.DB72 2 -DB7_B.DB71 1 -DB7_B.DB70 0 -RESERVEDF7BF 0xF7BF RESERVED -; -------------------------------------- CAN_C -------------------------------- -MCR0_C 0xF7C0 Message Control Register Low -MCR0_C.MSGVAL1 7 -MCR0_C.MSGVAL0 6 -MCR0_C.TXIE1 5 -MCR0_C.TXIE0 4 -MCR0_C.RXIE1 3 -MCR0_C.RXIE0 2 -MCR0_C.INTPND1 1 -MCR0_C.INTPND0 0 -MCR1_C 0xF7C1 Message Control Register High -MCR1_C.RMTPND1 7 -MCR1_C.RMTPND0 6 -MCR1_C.TXRQ1 5 -MCR1_C.TXRQ0 4 -MCR1_C.MSGLSTCPUUPD1 3 -MCR1_C.MSGLSTCPUUPD0 2 -MCR1_C.NEWDAT1 1 -MCR1_C.NEWDAT0 0 -UAR0_C 0xF7C2 Upper Arbitration Register Low -UAR0_C.ID28 7 -UAR0_C.ID27 6 -UAR0_C.ID26 5 -UAR0_C.ID25 4 -UAR0_C.ID24 3 -UAR0_C.ID23 2 -UAR0_C.ID22 1 -UAR0_C.ID21 0 -UAR1_C 0xF7C3 Upper Arbitration Register High -UAR1_C.ID20 7 -UAR1_C.ID19 6 -UAR1_C.ID18 5 -UAR1_C.ID17 4 -UAR1_C.ID16 3 -UAR1_C.ID15 2 -UAR1_C.ID14 1 -UAR1_C.ID13 0 -LAR0_C 0xF7C4 Lower Arbitration Register Low -LAR0_C.ID12 7 -LAR0_C.ID11 6 -LAR0_C.ID10 5 -LAR0_C.ID9 4 -LAR0_C.ID8 3 -LAR0_C.ID7 2 -LAR0_C.ID6 1 -LAR0_C.ID5 0 -LAR1_C 0xF7C5 Lower Arbitration Register High -LAR1_C.ID4 7 -LAR1_C.ID3 6 -LAR1_C.ID2 5 -LAR1_C.ID1 4 -LAR1_C.ID0 3 -MCFG_C 0xF7C6 Message Configuration Register -MCFG_C.DLC7 7 -MCFG_C.DLC6 6 -MCFG_C.DLC5 5 -MCFG_C.DLC4 4 -MCFG_C.DIR 3 -MCFG_C.XTD 2 -DB0_C 0xF7C7 Message Data Byte 0 -DB0_C.DB07 7 -DB0_C.DB06 6 -DB0_C.DB05 5 -DB0_C.DB04 4 -DB0_C.DB03 3 -DB0_C.DB02 2 -DB0_C.DB01 1 -DB0_C.DB00 0 -DB1_C 0xF7C8 Message Data Byte 1 -DB1_C.DB17 7 -DB1_C.DB16 6 -DB1_C.DB15 5 -DB1_C.DB14 4 -DB1_C.DB13 3 -DB1_C.DB12 2 -DB1_C.DB11 1 -DB1_C.DB10 0 -DB2_C 0xF7C9 Message Data Byte 2 -DB2_C.DB27 7 -DB2_C.DB26 6 -DB2_C.DB25 5 -DB2_C.DB24 4 -DB2_C.DB23 3 -DB2_C.DB22 2 -DB2_C.DB21 1 -DB2_C.DB20 0 -DB3_C 0xF7CA Message Data Byte 3 -DB3_C.DB37 7 -DB3_C.DB36 6 -DB3_C.DB35 5 -DB3_C.DB34 4 -DB3_C.DB33 3 -DB3_C.DB32 2 -DB3_C.DB31 1 -DB3_C.DB30 0 -DB4_C 0xF7CB Message Data Byte 4 -DB4_C.DB47 7 -DB4_C.DB46 6 -DB4_C.DB45 5 -DB4_C.DB44 4 -DB4_C.DB43 3 -DB4_C.DB42 2 -DB4_C.DB41 1 -DB4_C.DB40 0 -DB5_C 0xF7CC Message Data Byte 5 -DB5_C.DB57 7 -DB5_C.DB56 6 -DB5_C.DB55 5 -DB5_C.DB54 4 -DB5_C.DB53 3 -DB5_C.DB52 2 -DB5_C.DB51 1 -DB5_C.DB50 0 -DB6_C 0xF7CD Message Data Byte 6 -DB6_C.DB67 7 -DB6_C.DB66 6 -DB6_C.DB65 5 -DB6_C.DB64 4 -DB6_C.DB63 3 -DB6_C.DB62 2 -DB6_C.DB61 1 -DB6_C.DB60 0 -DB7_C 0xF7CE Message Data Byte 7 -DB7_C.DB77 7 -DB7_C.DB76 6 -DB7_C.DB75 5 -DB7_C.DB74 4 -DB7_C.DB73 3 -DB7_C.DB72 2 -DB7_C.DB71 1 -DB7_C.DB70 0 -RESERVEDF7CF 0xF7CF RESERVED -; -------------------------------------- CAN_D -------------------------------- -MCR0_D 0xF7D0 Message Control Register Low -MCR0_D.MSGVAL1 7 -MCR0_D.MSGVAL0 6 -MCR0_D.TXIE1 5 -MCR0_D.TXIE0 4 -MCR0_D.RXIE1 3 -MCR0_D.RXIE0 2 -MCR0_D.INTPND1 1 -MCR0_D.INTPND0 0 -MCR1_D 0xF7D1 Message Control Register High -MCR1_D.RMTPND1 7 -MCR1_D.RMTPND0 6 -MCR1_D.TXRQ1 5 -MCR1_D.TXRQ0 4 -MCR1_D.MSGLSTCPUUPD1 3 -MCR1_D.MSGLSTCPUUPD0 2 -MCR1_D.NEWDAT1 1 -MCR1_D.NEWDAT0 0 -UAR0_D 0xF7D2 Upper Arbitration Register Low -UAR0_D.ID28 7 -UAR0_D.ID27 6 -UAR0_D.ID26 5 -UAR0_D.ID25 4 -UAR0_D.ID24 3 -UAR0_D.ID23 2 -UAR0_D.ID22 1 -UAR0_D.ID21 0 -UAR1_D 0xF7D3 Upper Arbitration Register High -UAR1_D.ID20 7 -UAR1_D.ID19 6 -UAR1_D.ID18 5 -UAR1_D.ID17 4 -UAR1_D.ID16 3 -UAR1_D.ID15 2 -UAR1_D.ID14 1 -UAR1_D.ID13 0 -LAR0_D 0xF7D4 Lower Arbitration Register Low -LAR0_D.ID12 7 -LAR0_D.ID11 6 -LAR0_D.ID10 5 -LAR0_D.ID9 4 -LAR0_D.ID8 3 -LAR0_D.ID7 2 -LAR0_D.ID6 1 -LAR0_D.ID5 0 -LAR1_D 0xF7D5 Lower Arbitration Register High -LAR1_D.ID4 7 -LAR1_D.ID3 6 -LAR1_D.ID2 5 -LAR1_D.ID1 4 -LAR1_D.ID0 3 -MCFG_D 0xF7D6 Message Configuration Register -MCFG_D.DLC7 7 -MCFG_D.DLC6 6 -MCFG_D.DLC5 5 -MCFG_D.DLC4 4 -MCFG_D.DIR 3 -MCFG_D.XTD 2 -DB0_D 0xF7D7 Message Data Byte 0 -DB0_D.DB07 7 -DB0_D.DB06 6 -DB0_D.DB05 5 -DB0_D.DB04 4 -DB0_D.DB03 3 -DB0_D.DB02 2 -DB0_D.DB01 1 -DB0_D.DB00 0 -DB1_D 0xF7D8 Message Data Byte 1 -DB1_D.DB17 7 -DB1_D.DB16 6 -DB1_D.DB15 5 -DB1_D.DB14 4 -DB1_D.DB13 3 -DB1_D.DB12 2 -DB1_D.DB11 1 -DB1_D.DB10 0 -DB2_D 0xF7D9 Message Data Byte 2 -DB2_D.DB27 7 -DB2_D.DB26 6 -DB2_D.DB25 5 -DB2_D.DB24 4 -DB2_D.DB23 3 -DB2_D.DB22 2 -DB2_D.DB21 1 -DB2_D.DB20 0 -DB3_D 0xF7DA Message Data Byte 3 -DB3_D.DB37 7 -DB3_D.DB36 6 -DB3_D.DB35 5 -DB3_D.DB34 4 -DB3_D.DB33 3 -DB3_D.DB32 2 -DB3_D.DB31 1 -DB3_D.DB30 0 -DB4_D 0xF7DB Message Data Byte 4 -DB4_D.DB47 7 -DB4_D.DB46 6 -DB4_D.DB45 5 -DB4_D.DB44 4 -DB4_D.DB43 3 -DB4_D.DB42 2 -DB4_D.DB41 1 -DB4_D.DB40 0 -DB5_D 0xF7DC Message Data Byte 5 -DB5_D.DB57 7 -DB5_D.DB56 6 -DB5_D.DB55 5 -DB5_D.DB54 4 -DB5_D.DB53 3 -DB5_D.DB52 2 -DB5_D.DB51 1 -DB5_D.DB50 0 -DB6_D 0xF7DD Message Data Byte 6 -DB6_D.DB67 7 -DB6_D.DB66 6 -DB6_D.DB65 5 -DB6_D.DB64 4 -DB6_D.DB63 3 -DB6_D.DB62 2 -DB6_D.DB61 1 -DB6_D.DB60 0 -DB7_D 0xF7DE Message Data Byte 7 -DB7_D.DB77 7 -DB7_D.DB76 6 -DB7_D.DB75 5 -DB7_D.DB74 4 -DB7_D.DB73 3 -DB7_D.DB72 2 -DB7_D.DB71 1 -DB7_D.DB70 0 -RESERVEDF7DF 0xF7DF RESERVED -; -------------------------------------- CAN_E -------------------------------- -MCR0_E 0xF7E0 Message Control Register Low -MCR0_E.MSGVAL1 7 -MCR0_E.MSGVAL0 6 -MCR0_E.TXIE1 5 -MCR0_E.TXIE0 4 -MCR0_E.RXIE1 3 -MCR0_E.RXIE0 2 -MCR0_E.INTPND1 1 -MCR0_E.INTPND0 0 -MCR1_E 0xF7E1 Message Control Register High -MCR1_E.RMTPND1 7 -MCR1_E.RMTPND0 6 -MCR1_E.TXRQ1 5 -MCR1_E.TXRQ0 4 -MCR1_E.MSGLSTCPUUPD1 3 -MCR1_E.MSGLSTCPUUPD0 2 -MCR1_E.NEWDAT1 1 -MCR1_E.NEWDAT0 0 -UAR0_E 0xF7E2 Upper Arbitration Register Low -UAR0_E.ID28 7 -UAR0_E.ID27 6 -UAR0_E.ID26 5 -UAR0_E.ID25 4 -UAR0_E.ID24 3 -UAR0_E.ID23 2 -UAR0_E.ID22 1 -UAR0_E.ID21 0 -UAR1_E 0xF7E3 Upper Arbitration Register High -UAR1_E.ID20 7 -UAR1_E.ID19 6 -UAR1_E.ID18 5 -UAR1_E.ID17 4 -UAR1_E.ID16 3 -UAR1_E.ID15 2 -UAR1_E.ID14 1 -UAR1_E.ID13 0 -LAR0_E 0xF7E4 Lower Arbitration Register Low -LAR0_E.ID12 7 -LAR0_E.ID11 6 -LAR0_E.ID10 5 -LAR0_E.ID9 4 -LAR0_E.ID8 3 -LAR0_E.ID7 2 -LAR0_E.ID6 1 -LAR0_E.ID5 0 -LAR1_E 0xF7E5 Lower Arbitration Register High -LAR1_E.ID4 7 -LAR1_E.ID3 6 -LAR1_E.ID2 5 -LAR1_E.ID1 4 -LAR1_E.ID0 3 -MCFG_E 0xF7E6 Message Configuration Register -MCFG_E.DLC7 7 -MCFG_E.DLC6 6 -MCFG_E.DLC5 5 -MCFG_E.DLC4 4 -MCFG_E.DIR 3 -MCFG_E.XTD 2 -DB0_E 0xF7E7 Message Data Byte 0 -DB0_E.DB07 7 -DB0_E.DB06 6 -DB0_E.DB05 5 -DB0_E.DB04 4 -DB0_E.DB03 3 -DB0_E.DB02 2 -DB0_E.DB01 1 -DB0_E.DB00 0 -DB1_E 0xF7E8 Message Data Byte 1 -DB1_E.DB17 7 -DB1_E.DB16 6 -DB1_E.DB15 5 -DB1_E.DB14 4 -DB1_E.DB13 3 -DB1_E.DB12 2 -DB1_E.DB11 1 -DB1_E.DB10 0 -DB2_E 0xF7E9 Message Data Byte 2 -DB2_E.DB27 7 -DB2_E.DB26 6 -DB2_E.DB25 5 -DB2_E.DB24 4 -DB2_E.DB23 3 -DB2_E.DB22 2 -DB2_E.DB21 1 -DB2_E.DB20 0 -DB3_E 0xF7EA Message Data Byte 3 -DB3_E.DB37 7 -DB3_E.DB36 6 -DB3_E.DB35 5 -DB3_E.DB34 4 -DB3_E.DB33 3 -DB3_E.DB32 2 -DB3_E.DB31 1 -DB3_E.DB30 0 -DB4_E 0xF7EB Message Data Byte 4 -DB4_E.DB47 7 -DB4_E.DB46 6 -DB4_E.DB45 5 -DB4_E.DB44 4 -DB4_E.DB43 3 -DB4_E.DB42 2 -DB4_E.DB41 1 -DB4_E.DB40 0 -DB5_E 0xF7EC Message Data Byte 5 -DB5_E.DB57 7 -DB5_E.DB56 6 -DB5_E.DB55 5 -DB5_E.DB54 4 -DB5_E.DB53 3 -DB5_E.DB52 2 -DB5_E.DB51 1 -DB5_E.DB50 0 -DB6_E 0xF7ED Message Data Byte 6 -DB6_E.DB67 7 -DB6_E.DB66 6 -DB6_E.DB65 5 -DB6_E.DB64 4 -DB6_E.DB63 3 -DB6_E.DB62 2 -DB6_E.DB61 1 -DB6_E.DB60 0 -DB7_E 0xF7DE Message Data Byte 7 -DB7_E.DB77 7 -DB7_E.DB76 6 -DB7_E.DB75 5 -DB7_E.DB74 4 -DB7_E.DB73 3 -DB7_E.DB72 2 -DB7_E.DB71 1 -DB7_E.DB70 0 -RESERVEDF7EF 0xF7EF RESERVED -; -------------------------------------- CAN_F -------------------------------- -MCR0_F 0xF7F0 Message Control Register Low -MCR0_F.MSGVAL1 7 -MCR0_F.MSGVAL0 6 -MCR0_F.TXIE1 5 -MCR0_F.TXIE0 4 -MCR0_F.RXIE1 3 -MCR0_F.RXIE0 2 -MCR0_F.INTPND1 1 -MCR0_F.INTPND0 0 -MCR1_F 0xF7F1 Message Control Register High -MCR1_F.RMTPND1 7 -MCR1_F.RMTPND0 6 -MCR1_F.TXRQ1 5 -MCR1_F.TXRQ0 4 -MCR1_F.MSGLSTCPUUPD1 3 -MCR1_F.MSGLSTCPUUPD0 2 -MCR1_F.NEWDAT1 1 -MCR1_F.NEWDAT0 0 -UAR0_F 0xF7F2 Upper Arbitration Register Low -UAR0_F.ID28 7 -UAR0_F.ID27 6 -UAR0_F.ID26 5 -UAR0_F.ID25 4 -UAR0_F.ID24 3 -UAR0_F.ID23 2 -UAR0_F.ID22 1 -UAR0_F.ID21 0 -UAR1_F 0xF7F3 Upper Arbitration Register High -UAR1_F.ID20 7 -UAR1_F.ID19 6 -UAR1_F.ID18 5 -UAR1_F.ID17 4 -UAR1_F.ID16 3 -UAR1_F.ID15 2 -UAR1_F.ID14 1 -UAR1_F.ID13 0 -LAR0_F 0xF7F4 Lower Arbitration Register Low -LAR0_F.ID12 7 -LAR0_F.ID11 6 -LAR0_F.ID10 5 -LAR0_F.ID9 4 -LAR0_F.ID8 3 -LAR0_F.ID7 2 -LAR0_F.ID6 1 -LAR0_F.ID5 0 -LAR1_F 0xF7F5 Lower Arbitration Register High -LAR1_F.ID4 7 -LAR1_F.ID3 6 -LAR1_F.ID2 5 -LAR1_F.ID1 4 -LAR1_F.ID0 3 -MCFG_F 0xF7F6 Message Configuration Register -MCFG_F.DLC7 7 -MCFG_F.DLC6 6 -MCFG_F.DLC5 5 -MCFG_F.DLC4 4 -MCFG_F.DIR 3 -MCFG_F.XTD 2 -DB0_F 0xF7F7 Message Data Byte 0 -DB0_F.DB07 7 -DB0_F.DB06 6 -DB0_F.DB05 5 -DB0_F.DB04 4 -DB0_F.DB03 3 -DB0_F.DB02 2 -DB0_F.DB01 1 -DB0_F.DB00 0 -DB1_F 0xF7F8 Message Data Byte 1 -DB1_F.DB17 7 -DB1_F.DB16 6 -DB1_F.DB15 5 -DB1_F.DB14 4 -DB1_F.DB13 3 -DB1_F.DB12 2 -DB1_F.DB11 1 -DB1_F.DB10 0 -DB2_F 0xF7F9 Message Data Byte 2 -DB2_F.DB27 7 -DB2_F.DB26 6 -DB2_F.DB25 5 -DB2_F.DB24 4 -DB2_F.DB23 3 -DB2_F.DB22 2 -DB2_F.DB21 1 -DB2_F.DB20 0 -DB3_F 0xF7FA Message Data Byte 3 -DB3_F.DB37 7 -DB3_F.DB36 6 -DB3_F.DB35 5 -DB3_F.DB34 4 -DB3_F.DB33 3 -DB3_F.DB32 2 -DB3_F.DB31 1 -DB3_F.DB30 0 -DB4_F 0xF7FB Message Data Byte 4 -DB4_F.DB47 7 -DB4_F.DB46 6 -DB4_F.DB45 5 -DB4_F.DB44 4 -DB4_F.DB43 3 -DB4_F.DB42 2 -DB4_F.DB41 1 -DB4_F.DB40 0 -DB5_F 0xF7FC Message Data Byte 5 -DB5_F.DB57 7 -DB5_F.DB56 6 -DB5_F.DB55 5 -DB5_F.DB54 4 -DB5_F.DB53 3 -DB5_F.DB52 2 -DB5_F.DB51 1 -DB5_F.DB50 0 -DB6_F 0xF7FD Message Data Byte 6 -DB6_F.DB67 7 -DB6_F.DB66 6 -DB6_F.DB65 5 -DB6_F.DB64 4 -DB6_F.DB63 3 -DB6_F.DB62 2 -DB6_F.DB61 1 -DB6_F.DB60 0 -DB7_F 0xF7FE Message Data Byte 7 -DB7_F.DB77 7 -DB7_F.DB76 6 -DB7_F.DB75 5 -DB7_F.DB74 4 -DB7_F.DB73 3 -DB7_F.DB72 2 -DB7_F.DB71 1 -DB7_F.DB70 0 -RESERVEDF7FF 0xF7FF RESERVED - - -.C505CA -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 -; C505C.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xF700 -area DATA CAN 0xF700:0xF800 -area BSS RESERVED 0xF800:0xFC00 -area DATA XRAM 0xFC00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry CAN_SWI 0x004B CAN Controller / Software Interrupt -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry IRTC 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.P14 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -; P1ANA 0x0090 Port 1 Analog Input Selection Register -; P1ANA.EAN7 7 -; P1ANA.EAN6 6 -; P1ANA.EAN5 5 -; P1ANA.EAN4 4 -; P1ANA.EAN3 3 -; P1ANA.EAN2 2 -; P1ANA.EAN1 1 -; P1ANA.EAN0 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register (C505CA only) -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.CMOD 3 -SYSCON.CSWO 2 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.ECAN 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.SWI 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Reload Register Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Reload Register High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter High Byte Data Register (C505A / C505CA only) -ADDATH.ADDATH7 7 -ADDATH.ADDATH6 6 -ADDATH.ADDATH5 5 -ADDATH.ADDATH4 4 -ADDATH.ADDATH3 3 -ADDATH.ADDATH2 2 -ADDATH.ADDATH1 1 -ADDATH.ADDATH0 0 -ADDATL 0x00DA A/D Converter Low Byte Data Register (C505A / C505CA only) -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -RESERVED00DB 0x00DB RESERVED -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.RXDC 1 -P4.TXDC 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -VR2.VR27 7 -VR2.VR26 6 -VR2.VR25 5 -VR2.VR24 4 -VR2.VR23 3 -VR2.VR22 2 -VR2.VR21 1 -VR2.VR20 0 -RESERVED00FF 0x00FF RESERVED -; -------------------------------------- CAN -------------------------------- -CR 0xF700 Control Register -CR.TEST 7 -CR.CCE 6 -CR.EIE 3 -CR.SIE 2 -CR.IE 1 -CR.INIT 0 -SR 0xF701 Status Register -SR.BOFF 7 -SR.EWRN 6 -SR.RXOK 4 -SR.TXOK 3 -SR.LEC2 2 -SR.LEC1 1 -SR.LEC0 0 -IR 0xF702 Interrupt Register -IR.INTID7 7 -IR.INTID6 6 -IR.INTID5 5 -IR.INTID4 4 -IR.INTID3 3 -IR.INTID2 2 -IR.INTID1 1 -IR.INTID0 0 -RESERVEDF703 0xF703 RESERVED -BTR0 0xF704 Bit Timing Register Low -BTR0.SJW7 7 -BTR0.SJW6 6 -BTR0.BRP5 5 -BTR0.BRP4 4 -BTR0.BRP3 3 -BTR0.BRP2 2 -BTR0.BRP1 1 -BTR0.BRP0 0 -BTR1 0xF705 Bit Timing Register High -BTR1.TSEG26 6 -BTR1.TSEG25 5 -BTR1.TSEG24 4 -BTR1.TSEG13 3 -BTR1.TSEG12 2 -BTR1.TSEG11 1 -BTR1.TSEG10 0 -GMS0 0xF706 Global Mask Short Register Low -GMS0.ID28 7 -GMS0.ID27 6 -GMS0.ID26 5 -GMS0.ID25 4 -GMS0.ID24 3 -GMS0.ID23 2 -GMS0.ID22 1 -GMS0.ID21 0 -GMS1 0xF707 Global Mask Short Register High -GMS1.ID20 7 -GMS1.ID19 6 -GMS1.ID18 5 -UGML0 0xF708 Upper Global Mask Long Register Low -UGML0.ID28 7 -UGML0.ID27 6 -UGML0.ID26 5 -UGML0.ID25 4 -UGML0.ID24 3 -UGML0.ID23 2 -UGML0.ID22 1 -UGML0.ID21 0 -UGML1 0xF709 Upper Global Mask Long Register High -UGML1.ID20 7 -UGML1.ID19 6 -UGML1.ID18 5 -UGML1.ID17 4 -UGML1.ID16 3 -UGML1.ID15 2 -UGML1.ID14 1 -UGML1.ID13 0 -LGML0 0xF70A Lower Global Mask Long Register Low -LGML0.ID12 7 -LGML0.ID11 6 -LGML0.ID10 5 -LGML0.ID9 4 -LGML0.ID8 3 -LGML0.ID7 2 -LGML0.ID6 1 -LGML0.ID5 0 -LGML1 0xF70B Lower Global Mask Long Register High -LGML1.ID4 7 -LGML1.ID3 6 -LGML1.ID2 5 -LGML1.ID1 4 -LGML1.ID0 3 -UMLM0 0xF70C Upper Mask of Last Message Register Low -UMLM0.ID28 7 -UMLM0.ID27 6 -UMLM0.ID26 5 -UMLM0.ID25 4 -UMLM0.ID24 3 -UMLM0.ID23 2 -UMLM0.ID22 1 -UMLM0.ID21 0 -UMLM1 0xF70D Upper Mask of Last Message Register High -UMLM1.ID20 7 -UMLM1.ID19 6 -UMLM1.ID18 5 -UMLM1.ID17 4 -UMLM1.ID16 3 -UMLM1.ID15 2 -UMLM1.ID14 1 -UMLM1.ID13 0 -LMLM0 0xF70E Lower Mask of Last Message Register Low -LMLM0.ID12 7 -LMLM0.ID11 6 -LMLM0.ID10 5 -LMLM0.ID9 4 -LMLM0.ID8 3 -LMLM0.ID7 2 -LMLM0.ID6 1 -LMLM0.ID5 0 -LMLM1 0xF70F Lower Mask of Last Message Register High -LMLM1.ID4 7 -LMLM1.ID3 6 -LMLM1.ID2 5 -LMLM1.ID1 4 -LMLM1.ID0 3 -; -------------------------------------- CAN_1 -------------------------------- -MCR0_1 0xF710 Message Control Register Low -MCR0_1.MSGVAL1 7 -MCR0_1.MSGVAL0 6 -MCR0_1.TXIE1 5 -MCR0_1.TXIE0 4 -MCR0_1.RXIE1 3 -MCR0_1.RXIE0 2 -MCR0_1.INTPND1 1 -MCR0_1.INTPND0 0 -MCR1_1 0xF711 Message Control Register High -MCR1_1.RMTPND1 7 -MCR1_1.RMTPND0 6 -MCR1_1.TXRQ1 5 -MCR1_1.TXRQ0 4 -MCR1_1.MSGLSTCPUUPD1 3 -MCR1_1.MSGLSTCPUUPD0 2 -MCR1_1.NEWDAT1 1 -MCR1_1.NEWDAT0 0 -UAR0_1 0xF712 Upper Arbitration Register Low -UAR0_1.ID28 7 -UAR0_1.ID27 6 -UAR0_1.ID26 5 -UAR0_1.ID25 4 -UAR0_1.ID24 3 -UAR0_1.ID23 2 -UAR0_1.ID22 1 -UAR0_1.ID21 0 -UAR1_1 0xF713 Upper Arbitration Register High -UAR1_1.ID20 7 -UAR1_1.ID19 6 -UAR1_1.ID18 5 -UAR1_1.ID17 4 -UAR1_1.ID16 3 -UAR1_1.ID15 2 -UAR1_1.ID14 1 -UAR1_1.ID13 0 -LAR0_1 0xF714 Lower Arbitration Register Low -LAR0_1.ID12 7 -LAR0_1.ID11 6 -LAR0_1.ID10 5 -LAR0_1.ID9 4 -LAR0_1.ID8 3 -LAR0_1.ID7 2 -LAR0_1.ID6 1 -LAR0_1.ID5 0 -LAR1_1 0xF715 Lower Arbitration Register High -LAR1_1.ID4 7 -LAR1_1.ID3 6 -LAR1_1.ID2 5 -LAR1_1.ID1 4 -LAR1_1.ID0 3 -MCFG_1 0xF716 Message Configuration Register -MCFG_1.DLC7 7 -MCFG_1.DLC6 6 -MCFG_1.DLC5 5 -MCFG_1.DLC4 4 -MCFG_1.DIR 3 -MCFG_1.XTD 2 -DB0_1 0xF717 Message Data Byte 0 -DB0_1.DB07 7 -DB0_1.DB06 6 -DB0_1.DB05 5 -DB0_1.DB04 4 -DB0_1.DB03 3 -DB0_1.DB02 2 -DB0_1.DB01 1 -DB0_1.DB00 0 -DB1_1 0xF718 Message Data Byte 1 -DB1_1.DB17 7 -DB1_1.DB16 6 -DB1_1.DB15 5 -DB1_1.DB14 4 -DB1_1.DB13 3 -DB1_1.DB12 2 -DB1_1.DB11 1 -DB1_1.DB10 0 -DB2_1 0xF719 Message Data Byte 2 -DB2_1.DB27 7 -DB2_1.DB26 6 -DB2_1.DB25 5 -DB2_1.DB24 4 -DB2_1.DB23 3 -DB2_1.DB22 2 -DB2_1.DB21 1 -DB2_1.DB20 0 -DB3_1 0xF71A Message Data Byte 3 -DB3_1.DB37 7 -DB3_1.DB36 6 -DB3_1.DB35 5 -DB3_1.DB34 4 -DB3_1.DB33 3 -DB3_1.DB32 2 -DB3_1.DB31 1 -DB3_1.DB30 0 -DB4_1 0xF71B Message Data Byte 4 -DB4_1.DB47 7 -DB4_1.DB46 6 -DB4_1.DB45 5 -DB4_1.DB44 4 -DB4_1.DB43 3 -DB4_1.DB42 2 -DB4_1.DB41 1 -DB4_1.DB40 0 -DB5_1 0xF71C Message Data Byte 5 -DB5_1.DB57 7 -DB5_1.DB56 6 -DB5_1.DB55 5 -DB5_1.DB54 4 -DB5_1.DB53 3 -DB5_1.DB52 2 -DB5_1.DB51 1 -DB5_1.DB50 0 -DB6_1 0xF71D Message Data Byte 6 -DB6_1.DB67 7 -DB6_1.DB66 6 -DB6_1.DB65 5 -DB6_1.DB64 4 -DB6_1.DB63 3 -DB6_1.DB62 2 -DB6_1.DB61 1 -DB6_1.DB60 0 -DB7_1 0xF71E Message Data Byte 7 -DB7_1.DB77 7 -DB7_1.DB76 6 -DB7_1.DB75 5 -DB7_1.DB74 4 -DB7_1.DB73 3 -DB7_1.DB72 2 -DB7_1.DB71 1 -DB7_1.DB70 0 -RESERVEDF71F 0xF71F RESERVED -; -------------------------------------- CAN_2 -------------------------------- -MCR0_2 0xF720 Message Control Register Low -MCR0_2.MSGVAL1 7 -MCR0_2.MSGVAL0 6 -MCR0_2.TXIE1 5 -MCR0_2.TXIE0 4 -MCR0_2.RXIE1 3 -MCR0_2.RXIE0 2 -MCR0_2.INTPND1 1 -MCR0_2.INTPND0 0 -MCR1_2 0xF721 Message Control Register High -MCR1_2.RMTPND1 7 -MCR1_2.RMTPND0 6 -MCR1_2.TXRQ1 5 -MCR1_2.TXRQ0 4 -MCR1_2.MSGLSTCPUUPD1 3 -MCR1_2.MSGLSTCPUUPD0 2 -MCR1_2.NEWDAT1 1 -MCR1_2.NEWDAT0 0 -UAR0_2 0xF722 Upper Arbitration Register Low -UAR0_2.ID28 7 -UAR0_2.ID27 6 -UAR0_2.ID26 5 -UAR0_2.ID25 4 -UAR0_2.ID24 3 -UAR0_2.ID23 2 -UAR0_2.ID22 1 -UAR0_2.ID21 0 -UAR1_2 0xF723 Upper Arbitration Register High -UAR1_2.ID20 7 -UAR1_2.ID19 6 -UAR1_2.ID18 5 -UAR1_2.ID17 4 -UAR1_2.ID16 3 -UAR1_2.ID15 2 -UAR1_2.ID14 1 -UAR1_2.ID13 0 -LAR0_2 0xF724 Lower Arbitration Register Low -LAR0_2.ID12 7 -LAR0_2.ID11 6 -LAR0_2.ID10 5 -LAR0_2.ID9 4 -LAR0_2.ID8 3 -LAR0_2.ID7 2 -LAR0_2.ID6 1 -LAR0_2.ID5 0 -LAR1_2 0xF725 Lower Arbitration Register High -LAR1_2.ID4 7 -LAR1_2.ID3 6 -LAR1_2.ID2 5 -LAR1_2.ID1 4 -LAR1_2.ID0 3 -MCFG_2 0xF726 Message Configuration Register -MCFG_2.DLC7 7 -MCFG_2.DLC6 6 -MCFG_2.DLC5 5 -MCFG_2.DLC4 4 -MCFG_2.DIR 3 -MCFG_2.XTD 2 -DB0_2 0xF727 Message Data Byte 0 -DB0_2.DB07 7 -DB0_2.DB06 6 -DB0_2.DB05 5 -DB0_2.DB04 4 -DB0_2.DB03 3 -DB0_2.DB02 2 -DB0_2.DB01 1 -DB0_2.DB00 0 -DB1_2 0xF728 Message Data Byte 1 -DB1_2.DB17 7 -DB1_2.DB16 6 -DB1_2.DB15 5 -DB1_2.DB14 4 -DB1_2.DB13 3 -DB1_2.DB12 2 -DB1_2.DB11 1 -DB1_2.DB10 0 -DB2_2 0xF729 Message Data Byte 2 -DB2_2.DB27 7 -DB2_2.DB26 6 -DB2_2.DB25 5 -DB2_2.DB24 4 -DB2_2.DB23 3 -DB2_2.DB22 2 -DB2_2.DB21 1 -DB2_2.DB20 0 -DB3_2 0xF72A Message Data Byte 3 -DB3_2.DB37 7 -DB3_2.DB36 6 -DB3_2.DB35 5 -DB3_2.DB34 4 -DB3_2.DB33 3 -DB3_2.DB32 2 -DB3_2.DB31 1 -DB3_2.DB30 0 -DB4_2 0xF72B Message Data Byte 4 -DB4_2.DB47 7 -DB4_2.DB46 6 -DB4_2.DB45 5 -DB4_2.DB44 4 -DB4_2.DB43 3 -DB4_2.DB42 2 -DB4_2.DB41 1 -DB4_2.DB40 0 -DB5_2 0xF72C Message Data Byte 5 -DB5_2.DB57 7 -DB5_2.DB56 6 -DB5_2.DB55 5 -DB5_2.DB54 4 -DB5_2.DB53 3 -DB5_2.DB52 2 -DB5_2.DB51 1 -DB5_2.DB50 0 -DB6_2 0xF72D Message Data Byte 6 -DB6_2.DB67 7 -DB6_2.DB66 6 -DB6_2.DB65 5 -DB6_2.DB64 4 -DB6_2.DB63 3 -DB6_2.DB62 2 -DB6_2.DB61 1 -DB6_2.DB60 0 -DB7_2 0xF72E Message Data Byte 7 -DB7_2.DB77 7 -DB7_2.DB76 6 -DB7_2.DB75 5 -DB7_2.DB74 4 -DB7_2.DB73 3 -DB7_2.DB72 2 -DB7_2.DB71 1 -DB7_2.DB70 0 -RESERVEDF72F 0xF72F RESERVED -; -------------------------------------- CAN_3 -------------------------------- -MCR0_3 0xF730 Message Control Register Low -MCR0_3.MSGVAL1 7 -MCR0_3.MSGVAL0 6 -MCR0_3.TXIE1 5 -MCR0_3.TXIE0 4 -MCR0_3.RXIE1 3 -MCR0_3.RXIE0 2 -MCR0_3.INTPND1 1 -MCR0_3.INTPND0 0 -MCR1_3 0xF731 Message Control Register High -MCR1_3.RMTPND1 7 -MCR1_3.RMTPND0 6 -MCR1_3.TXRQ1 5 -MCR1_3.TXRQ0 4 -MCR1_3.MSGLSTCPUUPD1 3 -MCR1_3.MSGLSTCPUUPD0 2 -MCR1_3.NEWDAT1 1 -MCR1_3.NEWDAT0 0 -UAR0_3 0xF732 Upper Arbitration Register Low -UAR0_3.ID28 7 -UAR0_3.ID27 6 -UAR0_3.ID26 5 -UAR0_3.ID25 4 -UAR0_3.ID24 3 -UAR0_3.ID23 2 -UAR0_3.ID22 1 -UAR0_3.ID21 0 -UAR1_3 0xF733 Upper Arbitration Register High -UAR1_3.ID20 7 -UAR1_3.ID19 6 -UAR1_3.ID18 5 -UAR1_3.ID17 4 -UAR1_3.ID16 3 -UAR1_3.ID15 2 -UAR1_3.ID14 1 -UAR1_3.ID13 0 -LAR0_3 0xF734 Lower Arbitration Register Low -LAR0_3.ID12 7 -LAR0_3.ID11 6 -LAR0_3.ID10 5 -LAR0_3.ID9 4 -LAR0_3.ID8 3 -LAR0_3.ID7 2 -LAR0_3.ID6 1 -LAR0_3.ID5 0 -LAR1_3 0xF735 Lower Arbitration Register High -LAR1_3.ID4 7 -LAR1_3.ID3 6 -LAR1_3.ID2 5 -LAR1_3.ID1 4 -LAR1_3.ID0 3 -MCFG_3 0xF736 Message Configuration Register -MCFG_3.DLC7 7 -MCFG_3.DLC6 6 -MCFG_3.DLC5 5 -MCFG_3.DLC4 4 -MCFG_3.DIR 3 -MCFG_3.XTD 2 -DB0_3 0xF737 Message Data Byte 0 -DB0_3.DB07 7 -DB0_3.DB06 6 -DB0_3.DB05 5 -DB0_3.DB04 4 -DB0_3.DB03 3 -DB0_3.DB02 2 -DB0_3.DB01 1 -DB0_3.DB00 0 -DB1_3 0xF738 Message Data Byte 1 -DB1_3.DB17 7 -DB1_3.DB16 6 -DB1_3.DB15 5 -DB1_3.DB14 4 -DB1_3.DB13 3 -DB1_3.DB12 2 -DB1_3.DB11 1 -DB1_3.DB10 0 -DB2_3 0xF739 Message Data Byte 2 -DB2_3.DB27 7 -DB2_3.DB26 6 -DB2_3.DB25 5 -DB2_3.DB24 4 -DB2_3.DB23 3 -DB2_3.DB22 2 -DB2_3.DB21 1 -DB2_3.DB20 0 -DB3_3 0xF73A Message Data Byte 3 -DB3_3.DB37 7 -DB3_3.DB36 6 -DB3_3.DB35 5 -DB3_3.DB34 4 -DB3_3.DB33 3 -DB3_3.DB32 2 -DB3_3.DB31 1 -DB3_3.DB30 0 -DB4_3 0xF73B Message Data Byte 4 -DB4_3.DB47 7 -DB4_3.DB46 6 -DB4_3.DB45 5 -DB4_3.DB44 4 -DB4_3.DB43 3 -DB4_3.DB42 2 -DB4_3.DB41 1 -DB4_3.DB40 0 -DB5_3 0xF73C Message Data Byte 5 -DB5_3.DB57 7 -DB5_3.DB56 6 -DB5_3.DB55 5 -DB5_3.DB54 4 -DB5_3.DB53 3 -DB5_3.DB52 2 -DB5_3.DB51 1 -DB5_3.DB50 0 -DB6_3 0xF73D Message Data Byte 6 -DB6_3.DB67 7 -DB6_3.DB66 6 -DB6_3.DB65 5 -DB6_3.DB64 4 -DB6_3.DB63 3 -DB6_3.DB62 2 -DB6_3.DB61 1 -DB6_3.DB60 0 -DB7_3 0xF73E Message Data Byte 7 -DB7_3.DB77 7 -DB7_3.DB76 6 -DB7_3.DB75 5 -DB7_3.DB74 4 -DB7_3.DB73 3 -DB7_3.DB72 2 -DB7_3.DB71 1 -DB7_3.DB70 0 -RESERVEDF73F 0xF73F RESERVED -; -------------------------------------- CAN_4 -------------------------------- -MCR0_4 0xF740 Message Control Register Low -MCR0_4.MSGVAL1 7 -MCR0_4.MSGVAL0 6 -MCR0_4.TXIE1 5 -MCR0_4.TXIE0 4 -MCR0_4.RXIE1 3 -MCR0_4.RXIE0 2 -MCR0_4.INTPND1 1 -MCR0_4.INTPND0 0 -MCR1_4 0xF741 Message Control Register High -MCR1_4.RMTPND1 7 -MCR1_4.RMTPND0 6 -MCR1_4.TXRQ1 5 -MCR1_4.TXRQ0 4 -MCR1_4.MSGLSTCPUUPD1 3 -MCR1_4.MSGLSTCPUUPD0 2 -MCR1_4.NEWDAT1 1 -MCR1_4.NEWDAT0 0 -UAR0_4 0xF742 Upper Arbitration Register Low -UAR0_4.ID28 7 -UAR0_4.ID27 6 -UAR0_4.ID26 5 -UAR0_4.ID25 4 -UAR0_4.ID24 3 -UAR0_4.ID23 2 -UAR0_4.ID22 1 -UAR0_4.ID21 0 -UAR1_4 0xF743 Upper Arbitration Register High -UAR1_4.ID20 7 -UAR1_4.ID19 6 -UAR1_4.ID18 5 -UAR1_4.ID17 4 -UAR1_4.ID16 3 -UAR1_4.ID15 2 -UAR1_4.ID14 1 -UAR1_4.ID13 0 -LAR0_4 0xF744 Lower Arbitration Register Low -LAR0_4.ID12 7 -LAR0_4.ID11 6 -LAR0_4.ID10 5 -LAR0_4.ID9 4 -LAR0_4.ID8 3 -LAR0_4.ID7 2 -LAR0_4.ID6 1 -LAR0_4.ID5 0 -LAR1_4 0xF745 Lower Arbitration Register High -LAR1_4.ID4 7 -LAR1_4.ID3 6 -LAR1_4.ID2 5 -LAR1_4.ID1 4 -LAR1_4.ID0 3 -MCFG_4 0xF746 Message Configuration Register -MCFG_4.DLC7 7 -MCFG_4.DLC6 6 -MCFG_4.DLC5 5 -MCFG_4.DLC4 4 -MCFG_4.DIR 3 -MCFG_4.XTD 2 -DB0_4 0xF747 Message Data Byte 0 -DB0_4.DB07 7 -DB0_4.DB06 6 -DB0_4.DB05 5 -DB0_4.DB04 4 -DB0_4.DB03 3 -DB0_4.DB02 2 -DB0_4.DB01 1 -DB0_4.DB00 0 -DB1_4 0xF748 Message Data Byte 1 -DB1_4.DB17 7 -DB1_4.DB16 6 -DB1_4.DB15 5 -DB1_4.DB14 4 -DB1_4.DB13 3 -DB1_4.DB12 2 -DB1_4.DB11 1 -DB1_4.DB10 0 -DB2_4 0xF749 Message Data Byte 2 -DB2_4.DB27 7 -DB2_4.DB26 6 -DB2_4.DB25 5 -DB2_4.DB24 4 -DB2_4.DB23 3 -DB2_4.DB22 2 -DB2_4.DB21 1 -DB2_4.DB20 0 -DB3_4 0xF74A Message Data Byte 3 -DB3_4.DB37 7 -DB3_4.DB36 6 -DB3_4.DB35 5 -DB3_4.DB34 4 -DB3_4.DB33 3 -DB3_4.DB32 2 -DB3_4.DB31 1 -DB3_4.DB30 0 -DB4_4 0xF74B Message Data Byte 4 -DB4_4.DB47 7 -DB4_4.DB46 6 -DB4_4.DB45 5 -DB4_4.DB44 4 -DB4_4.DB43 3 -DB4_4.DB42 2 -DB4_4.DB41 1 -DB4_4.DB40 0 -DB5_4 0xF74C Message Data Byte 5 -DB5_4.DB57 7 -DB5_4.DB56 6 -DB5_4.DB55 5 -DB5_4.DB54 4 -DB5_4.DB53 3 -DB5_4.DB52 2 -DB5_4.DB51 1 -DB5_4.DB50 0 -DB6_4 0xF74D Message Data Byte 6 -DB6_4.DB67 7 -DB6_4.DB66 6 -DB6_4.DB65 5 -DB6_4.DB64 4 -DB6_4.DB63 3 -DB6_4.DB62 2 -DB6_4.DB61 1 -DB6_4.DB60 0 -DB7_4 0xF74E Message Data Byte 7 -DB7_4.DB77 7 -DB7_4.DB76 6 -DB7_4.DB75 5 -DB7_4.DB74 4 -DB7_4.DB73 3 -DB7_4.DB72 2 -DB7_4.DB71 1 -DB7_4.DB70 0 -RESERVEDF74F 0xF74F RESERVED -; -------------------------------------- CAN_5 -------------------------------- -MCR0_5 0xF750 Message Control Register Low -MCR0_5.MSGVAL1 7 -MCR0_5.MSGVAL0 6 -MCR0_5.TXIE1 5 -MCR0_5.TXIE0 4 -MCR0_5.RXIE1 3 -MCR0_5.RXIE0 2 -MCR0_5.INTPND1 1 -MCR0_5.INTPND0 0 -MCR1_5 0xF751 Message Control Register High -MCR1_5.RMTPND1 7 -MCR1_5.RMTPND0 6 -MCR1_5.TXRQ1 5 -MCR1_5.TXRQ0 4 -MCR1_5.MSGLSTCPUUPD1 3 -MCR1_5.MSGLSTCPUUPD0 2 -MCR1_5.NEWDAT1 1 -MCR1_5.NEWDAT0 0 -UAR0_5 0xF752 Upper Arbitration Register Low -UAR0_5.ID28 7 -UAR0_5.ID27 6 -UAR0_5.ID26 5 -UAR0_5.ID25 4 -UAR0_5.ID24 3 -UAR0_5.ID23 2 -UAR0_5.ID22 1 -UAR0_5.ID21 0 -UAR1_5 0xF753 Upper Arbitration Register High -UAR1_5.ID20 7 -UAR1_5.ID19 6 -UAR1_5.ID18 5 -UAR1_5.ID17 4 -UAR1_5.ID16 3 -UAR1_5.ID15 2 -UAR1_5.ID14 1 -UAR1_5.ID13 0 -LAR0_5 0xF754 Lower Arbitration Register Low -LAR0_5.ID12 7 -LAR0_5.ID11 6 -LAR0_5.ID10 5 -LAR0_5.ID9 4 -LAR0_5.ID8 3 -LAR0_5.ID7 2 -LAR0_5.ID6 1 -LAR0_5.ID5 0 -LAR1_5 0xF755 Lower Arbitration Register High -LAR1_5.ID4 7 -LAR1_5.ID3 6 -LAR1_5.ID2 5 -LAR1_5.ID1 4 -LAR1_5.ID0 3 -MCFG_5 0xF756 Message Configuration Register -MCFG_5.DLC7 7 -MCFG_5.DLC6 6 -MCFG_5.DLC5 5 -MCFG_5.DLC4 4 -MCFG_5.DIR 3 -MCFG_5.XTD 2 -DB0_5 0xF757 Message Data Byte 0 -DB0_5.DB07 7 -DB0_5.DB06 6 -DB0_5.DB05 5 -DB0_5.DB04 4 -DB0_5.DB03 3 -DB0_5.DB02 2 -DB0_5.DB01 1 -DB0_5.DB00 0 -DB1_5 0xF758 Message Data Byte 1 -DB1_5.DB17 7 -DB1_5.DB16 6 -DB1_5.DB15 5 -DB1_5.DB14 4 -DB1_5.DB13 3 -DB1_5.DB12 2 -DB1_5.DB11 1 -DB1_5.DB10 0 -DB2_5 0xF759 Message Data Byte 2 -DB2_5.DB27 7 -DB2_5.DB26 6 -DB2_5.DB25 5 -DB2_5.DB24 4 -DB2_5.DB23 3 -DB2_5.DB22 2 -DB2_5.DB21 1 -DB2_5.DB20 0 -DB3_5 0xF75A Message Data Byte 3 -DB3_5.DB37 7 -DB3_5.DB36 6 -DB3_5.DB35 5 -DB3_5.DB34 4 -DB3_5.DB33 3 -DB3_5.DB32 2 -DB3_5.DB31 1 -DB3_5.DB30 0 -DB4_5 0xF75B Message Data Byte 4 -DB4_5.DB47 7 -DB4_5.DB46 6 -DB4_5.DB45 5 -DB4_5.DB44 4 -DB4_5.DB43 3 -DB4_5.DB42 2 -DB4_5.DB41 1 -DB4_5.DB40 0 -DB5_5 0xF75C Message Data Byte 5 -DB5_5.DB57 7 -DB5_5.DB56 6 -DB5_5.DB55 5 -DB5_5.DB54 4 -DB5_5.DB53 3 -DB5_5.DB52 2 -DB5_5.DB51 1 -DB5_5.DB50 0 -DB6_5 0xF75D Message Data Byte 6 -DB6_5.DB67 7 -DB6_5.DB66 6 -DB6_5.DB65 5 -DB6_5.DB64 4 -DB6_5.DB63 3 -DB6_5.DB62 2 -DB6_5.DB61 1 -DB6_5.DB60 0 -DB7_5 0xF75E Message Data Byte 7 -DB7_5.DB77 7 -DB7_5.DB76 6 -DB7_5.DB75 5 -DB7_5.DB74 4 -DB7_5.DB73 3 -DB7_5.DB72 2 -DB7_5.DB71 1 -DB7_5.DB70 0 -RESERVEDF75F 0xF75F RESERVED -; -------------------------------------- CAN_6 -------------------------------- -MCR0_6 0xF760 Message Control Register Low -MCR0_6.MSGVAL1 7 -MCR0_6.MSGVAL0 6 -MCR0_6.TXIE1 5 -MCR0_6.TXIE0 4 -MCR0_6.RXIE1 3 -MCR0_6.RXIE0 2 -MCR0_6.INTPND1 1 -MCR0_6.INTPND0 0 -MCR1_6 0xF761 Message Control Register High -MCR1_6.RMTPND1 7 -MCR1_6.RMTPND0 6 -MCR1_6.TXRQ1 5 -MCR1_6.TXRQ0 4 -MCR1_6.MSGLSTCPUUPD1 3 -MCR1_6.MSGLSTCPUUPD0 2 -MCR1_6.NEWDAT1 1 -MCR1_6.NEWDAT0 0 -UAR0_6 0xF762 Upper Arbitration Register Low -UAR0_6.ID28 7 -UAR0_6.ID27 6 -UAR0_6.ID26 5 -UAR0_6.ID25 4 -UAR0_6.ID24 3 -UAR0_6.ID23 2 -UAR0_6.ID22 1 -UAR0_6.ID21 0 -UAR1_6 0xF763 Upper Arbitration Register High -UAR1_6.ID20 7 -UAR1_6.ID19 6 -UAR1_6.ID18 5 -UAR1_6.ID17 4 -UAR1_6.ID16 3 -UAR1_6.ID15 2 -UAR1_6.ID14 1 -UAR1_6.ID13 0 -LAR0_6 0xF764 Lower Arbitration Register Low -LAR0_6.ID12 7 -LAR0_6.ID11 6 -LAR0_6.ID10 5 -LAR0_6.ID9 4 -LAR0_6.ID8 3 -LAR0_6.ID7 2 -LAR0_6.ID6 1 -LAR0_6.ID5 0 -LAR1_6 0xF765 Lower Arbitration Register High -LAR1_6.ID4 7 -LAR1_6.ID3 6 -LAR1_6.ID2 5 -LAR1_6.ID1 4 -LAR1_6.ID0 3 -MCFG_6 0xF766 Message Configuration Register -MCFG_6.DLC7 7 -MCFG_6.DLC6 6 -MCFG_6.DLC5 5 -MCFG_6.DLC4 4 -MCFG_6.DIR 3 -MCFG_6.XTD 2 -DB0_6 0xF767 Message Data Byte 0 -DB0_6.DB07 7 -DB0_6.DB06 6 -DB0_6.DB05 5 -DB0_6.DB04 4 -DB0_6.DB03 3 -DB0_6.DB02 2 -DB0_6.DB01 1 -DB0_6.DB00 0 -DB1_6 0xF768 Message Data Byte 1 -DB1_6.DB17 7 -DB1_6.DB16 6 -DB1_6.DB15 5 -DB1_6.DB14 4 -DB1_6.DB13 3 -DB1_6.DB12 2 -DB1_6.DB11 1 -DB1_6.DB10 0 -DB2_6 0xF769 Message Data Byte 2 -DB2_6.DB27 7 -DB2_6.DB26 6 -DB2_6.DB25 5 -DB2_6.DB24 4 -DB2_6.DB23 3 -DB2_6.DB22 2 -DB2_6.DB21 1 -DB2_6.DB20 0 -DB3_6 0xF76A Message Data Byte 3 -DB3_6.DB37 7 -DB3_6.DB36 6 -DB3_6.DB35 5 -DB3_6.DB34 4 -DB3_6.DB33 3 -DB3_6.DB32 2 -DB3_6.DB31 1 -DB3_6.DB30 0 -DB4_6 0xF76B Message Data Byte 4 -DB4_6.DB47 7 -DB4_6.DB46 6 -DB4_6.DB45 5 -DB4_6.DB44 4 -DB4_6.DB43 3 -DB4_6.DB42 2 -DB4_6.DB41 1 -DB4_6.DB40 0 -DB5_6 0xF76C Message Data Byte 5 -DB5_6.DB57 7 -DB5_6.DB56 6 -DB5_6.DB55 5 -DB5_6.DB54 4 -DB5_6.DB53 3 -DB5_6.DB52 2 -DB5_6.DB51 1 -DB5_6.DB50 0 -DB6_6 0xF76D Message Data Byte 6 -DB6_6.DB67 7 -DB6_6.DB66 6 -DB6_6.DB65 5 -DB6_6.DB64 4 -DB6_6.DB63 3 -DB6_6.DB62 2 -DB6_6.DB61 1 -DB6_6.DB60 0 -DB7_6 0xF76E Message Data Byte 7 -DB7_6.DB77 7 -DB7_6.DB76 6 -DB7_6.DB75 5 -DB7_6.DB74 4 -DB7_6.DB73 3 -DB7_6.DB72 2 -DB7_6.DB71 1 -DB7_6.DB70 0 -RESERVEDF76F 0xF76F RESERVED -; -------------------------------------- CAN_7 -------------------------------- -MCR0_7 0xF770 Message Control Register Low -MCR0_7.MSGVAL1 7 -MCR0_7.MSGVAL0 6 -MCR0_7.TXIE1 5 -MCR0_7.TXIE0 4 -MCR0_7.RXIE1 3 -MCR0_7.RXIE0 2 -MCR0_7.INTPND1 1 -MCR0_7.INTPND0 0 -MCR1_7 0xF771 Message Control Register High -MCR1_7.RMTPND1 7 -MCR1_7.RMTPND0 6 -MCR1_7.TXRQ1 5 -MCR1_7.TXRQ0 4 -MCR1_7.MSGLSTCPUUPD1 3 -MCR1_7.MSGLSTCPUUPD0 2 -MCR1_7.NEWDAT1 1 -MCR1_7.NEWDAT0 0 -UAR0_7 0xF772 Upper Arbitration Register Low -UAR0_7.ID28 7 -UAR0_7.ID27 6 -UAR0_7.ID26 5 -UAR0_7.ID25 4 -UAR0_7.ID24 3 -UAR0_7.ID23 2 -UAR0_7.ID22 1 -UAR0_7.ID21 0 -UAR1_7 0xF773 Upper Arbitration Register High -UAR1_7.ID20 7 -UAR1_7.ID19 6 -UAR1_7.ID18 5 -UAR1_7.ID17 4 -UAR1_7.ID16 3 -UAR1_7.ID15 2 -UAR1_7.ID14 1 -UAR1_7.ID13 0 -LAR0_7 0xF774 Lower Arbitration Register Low -LAR0_7.ID12 7 -LAR0_7.ID11 6 -LAR0_7.ID10 5 -LAR0_7.ID9 4 -LAR0_7.ID8 3 -LAR0_7.ID7 2 -LAR0_7.ID6 1 -LAR0_7.ID5 0 -LAR1_7 0xF775 Lower Arbitration Register High -LAR1_7.ID4 7 -LAR1_7.ID3 6 -LAR1_7.ID2 5 -LAR1_7.ID1 4 -LAR1_7.ID0 3 -MCFG_7 0xF776 Message Configuration Register -MCFG_7.DLC7 7 -MCFG_7.DLC6 6 -MCFG_7.DLC5 5 -MCFG_7.DLC4 4 -MCFG_7.DIR 3 -MCFG_7.XTD 2 -DB0_7 0xF777 Message Data Byte 0 -DB0_7.DB07 7 -DB0_7.DB06 6 -DB0_7.DB05 5 -DB0_7.DB04 4 -DB0_7.DB03 3 -DB0_7.DB02 2 -DB0_7.DB01 1 -DB0_7.DB00 0 -DB1_7 0xF778 Message Data Byte 1 -DB1_7.DB17 7 -DB1_7.DB16 6 -DB1_7.DB15 5 -DB1_7.DB14 4 -DB1_7.DB13 3 -DB1_7.DB12 2 -DB1_7.DB11 1 -DB1_7.DB10 0 -DB2_7 0xF779 Message Data Byte 2 -DB2_7.DB27 7 -DB2_7.DB26 6 -DB2_7.DB25 5 -DB2_7.DB24 4 -DB2_7.DB23 3 -DB2_7.DB22 2 -DB2_7.DB21 1 -DB2_7.DB20 0 -DB3_7 0xF77A Message Data Byte 3 -DB3_7.DB37 7 -DB3_7.DB36 6 -DB3_7.DB35 5 -DB3_7.DB34 4 -DB3_7.DB33 3 -DB3_7.DB32 2 -DB3_7.DB31 1 -DB3_7.DB30 0 -DB4_7 0xF77B Message Data Byte 4 -DB4_7.DB47 7 -DB4_7.DB46 6 -DB4_7.DB45 5 -DB4_7.DB44 4 -DB4_7.DB43 3 -DB4_7.DB42 2 -DB4_7.DB41 1 -DB4_7.DB40 0 -DB5_7 0xF77C Message Data Byte 5 -DB5_7.DB57 7 -DB5_7.DB56 6 -DB5_7.DB55 5 -DB5_7.DB54 4 -DB5_7.DB53 3 -DB5_7.DB52 2 -DB5_7.DB51 1 -DB5_7.DB50 0 -DB6_7 0xF77D Message Data Byte 6 -DB6_7.DB67 7 -DB6_7.DB66 6 -DB6_7.DB65 5 -DB6_7.DB64 4 -DB6_7.DB63 3 -DB6_7.DB62 2 -DB6_7.DB61 1 -DB6_7.DB60 0 -DB7_7 0xF77E Message Data Byte 7 -DB7_7.DB77 7 -DB7_7.DB76 6 -DB7_7.DB75 5 -DB7_7.DB74 4 -DB7_7.DB73 3 -DB7_7.DB72 2 -DB7_7.DB71 1 -DB7_7.DB70 0 -RESERVEDF77F 0xF77F RESERVED -; -------------------------------------- CAN_8 -------------------------------- -MCR0_8 0xF780 Message Control Register Low -MCR0_8.MSGVAL1 7 -MCR0_8.MSGVAL0 6 -MCR0_8.TXIE1 5 -MCR0_8.TXIE0 4 -MCR0_8.RXIE1 3 -MCR0_8.RXIE0 2 -MCR0_8.INTPND1 1 -MCR0_8.INTPND0 0 -MCR1_8 0xF781 Message Control Register High -MCR1_8.RMTPND1 7 -MCR1_8.RMTPND0 6 -MCR1_8.TXRQ1 5 -MCR1_8.TXRQ0 4 -MCR1_8.MSGLSTCPUUPD1 3 -MCR1_8.MSGLSTCPUUPD0 2 -MCR1_8.NEWDAT1 1 -MCR1_8.NEWDAT0 0 -UAR0_8 0xF782 Upper Arbitration Register Low -UAR0_8.ID28 7 -UAR0_8.ID27 6 -UAR0_8.ID26 5 -UAR0_8.ID25 4 -UAR0_8.ID24 3 -UAR0_8.ID23 2 -UAR0_8.ID22 1 -UAR0_8.ID21 0 -UAR1_8 0xF783 Upper Arbitration Register High -UAR1_8.ID20 7 -UAR1_8.ID19 6 -UAR1_8.ID18 5 -UAR1_8.ID17 4 -UAR1_8.ID16 3 -UAR1_8.ID15 2 -UAR1_8.ID14 1 -UAR1_8.ID13 0 -LAR0_8 0xF784 Lower Arbitration Register Low -LAR0_8.ID12 7 -LAR0_8.ID11 6 -LAR0_8.ID10 5 -LAR0_8.ID9 4 -LAR0_8.ID8 3 -LAR0_8.ID7 2 -LAR0_8.ID6 1 -LAR0_8.ID5 0 -LAR1_8 0xF785 Lower Arbitration Register High -LAR1_8.ID4 7 -LAR1_8.ID3 6 -LAR1_8.ID2 5 -LAR1_8.ID1 4 -LAR1_8.ID0 3 -MCFG_8 0xF786 Message Configuration Register -MCFG_8.DLC7 7 -MCFG_8.DLC6 6 -MCFG_8.DLC5 5 -MCFG_8.DLC4 4 -MCFG_8.DIR 3 -MCFG_8.XTD 2 -DB0_8 0xF787 Message Data Byte 0 -DB0_8.DB07 7 -DB0_8.DB06 6 -DB0_8.DB05 5 -DB0_8.DB04 4 -DB0_8.DB03 3 -DB0_8.DB02 2 -DB0_8.DB01 1 -DB0_8.DB00 0 -DB1_8 0xF788 Message Data Byte 1 -DB1_8.DB17 7 -DB1_8.DB16 6 -DB1_8.DB15 5 -DB1_8.DB14 4 -DB1_8.DB13 3 -DB1_8.DB12 2 -DB1_8.DB11 1 -DB1_8.DB10 0 -DB2_8 0xF789 Message Data Byte 2 -DB2_8.DB27 7 -DB2_8.DB26 6 -DB2_8.DB25 5 -DB2_8.DB24 4 -DB2_8.DB23 3 -DB2_8.DB22 2 -DB2_8.DB21 1 -DB2_8.DB20 0 -DB3_8 0xF78A Message Data Byte 3 -DB3_8.DB37 7 -DB3_8.DB36 6 -DB3_8.DB35 5 -DB3_8.DB34 4 -DB3_8.DB33 3 -DB3_8.DB32 2 -DB3_8.DB31 1 -DB3_8.DB30 0 -DB4_8 0xF78B Message Data Byte 4 -DB4_8.DB47 7 -DB4_8.DB46 6 -DB4_8.DB45 5 -DB4_8.DB44 4 -DB4_8.DB43 3 -DB4_8.DB42 2 -DB4_8.DB41 1 -DB4_8.DB40 0 -DB5_8 0xF78C Message Data Byte 5 -DB5_8.DB57 7 -DB5_8.DB56 6 -DB5_8.DB55 5 -DB5_8.DB54 4 -DB5_8.DB53 3 -DB5_8.DB52 2 -DB5_8.DB51 1 -DB5_8.DB50 0 -DB6_8 0xF78D Message Data Byte 6 -DB6_8.DB67 7 -DB6_8.DB66 6 -DB6_8.DB65 5 -DB6_8.DB64 4 -DB6_8.DB63 3 -DB6_8.DB62 2 -DB6_8.DB61 1 -DB6_8.DB60 0 -DB7_8 0xF78E Message Data Byte 7 -DB7_8.DB77 7 -DB7_8.DB76 6 -DB7_8.DB75 5 -DB7_8.DB74 4 -DB7_8.DB73 3 -DB7_8.DB72 2 -DB7_8.DB71 1 -DB7_8.DB70 0 -RESERVEDF78F 0xF78F RESERVED -; -------------------------------------- CAN_9 -------------------------------- -MCR0_9 0xF790 Message Control Register Low -MCR0_9.MSGVAL1 7 -MCR0_9.MSGVAL0 6 -MCR0_9.TXIE1 5 -MCR0_9.TXIE0 4 -MCR0_9.RXIE1 3 -MCR0_9.RXIE0 2 -MCR0_9.INTPND1 1 -MCR0_9.INTPND0 0 -MCR1_9 0xF791 Message Control Register High -MCR1_9.RMTPND1 7 -MCR1_9.RMTPND0 6 -MCR1_9.TXRQ1 5 -MCR1_9.TXRQ0 4 -MCR1_9.MSGLSTCPUUPD1 3 -MCR1_9.MSGLSTCPUUPD0 2 -MCR1_9.NEWDAT1 1 -MCR1_9.NEWDAT0 0 -UAR0_9 0xF792 Upper Arbitration Register Low -UAR0_9.ID28 7 -UAR0_9.ID27 6 -UAR0_9.ID26 5 -UAR0_9.ID25 4 -UAR0_9.ID24 3 -UAR0_9.ID23 2 -UAR0_9.ID22 1 -UAR0_9.ID21 0 -UAR1_9 0xF793 Upper Arbitration Register High -UAR1_9.ID20 7 -UAR1_9.ID19 6 -UAR1_9.ID18 5 -UAR1_9.ID17 4 -UAR1_9.ID16 3 -UAR1_9.ID15 2 -UAR1_9.ID14 1 -UAR1_9.ID13 0 -LAR0_9 0xF794 Lower Arbitration Register Low -LAR0_9.ID12 7 -LAR0_9.ID11 6 -LAR0_9.ID10 5 -LAR0_9.ID9 4 -LAR0_9.ID8 3 -LAR0_9.ID7 2 -LAR0_9.ID6 1 -LAR0_9.ID5 0 -LAR1_9 0xF795 Lower Arbitration Register High -LAR1_9.ID4 7 -LAR1_9.ID3 6 -LAR1_9.ID2 5 -LAR1_9.ID1 4 -LAR1_9.ID0 3 -MCFG_9 0xF796 Message Configuration Register -MCFG_9.DLC7 7 -MCFG_9.DLC6 6 -MCFG_9.DLC5 5 -MCFG_9.DLC4 4 -MCFG_9.DIR 3 -MCFG_9.XTD 2 -DB0_9 0xF797 Message Data Byte 0 -DB0_9.DB07 7 -DB0_9.DB06 6 -DB0_9.DB05 5 -DB0_9.DB04 4 -DB0_9.DB03 3 -DB0_9.DB02 2 -DB0_9.DB01 1 -DB0_9.DB00 0 -DB1_9 0xF798 Message Data Byte 1 -DB1_9.DB17 7 -DB1_9.DB16 6 -DB1_9.DB15 5 -DB1_9.DB14 4 -DB1_9.DB13 3 -DB1_9.DB12 2 -DB1_9.DB11 1 -DB1_9.DB10 0 -DB2_9 0xF799 Message Data Byte 2 -DB2_9.DB27 7 -DB2_9.DB26 6 -DB2_9.DB25 5 -DB2_9.DB24 4 -DB2_9.DB23 3 -DB2_9.DB22 2 -DB2_9.DB21 1 -DB2_9.DB20 0 -DB3_9 0xF79A Message Data Byte 3 -DB3_9.DB37 7 -DB3_9.DB36 6 -DB3_9.DB35 5 -DB3_9.DB34 4 -DB3_9.DB33 3 -DB3_9.DB32 2 -DB3_9.DB31 1 -DB3_9.DB30 0 -DB4_9 0xF79B Message Data Byte 4 -DB4_9.DB47 7 -DB4_9.DB46 6 -DB4_9.DB45 5 -DB4_9.DB44 4 -DB4_9.DB43 3 -DB4_9.DB42 2 -DB4_9.DB41 1 -DB4_9.DB40 0 -DB5_9 0xF79C Message Data Byte 5 -DB5_9.DB57 7 -DB5_9.DB56 6 -DB5_9.DB55 5 -DB5_9.DB54 4 -DB5_9.DB53 3 -DB5_9.DB52 2 -DB5_9.DB51 1 -DB5_9.DB50 0 -DB6_9 0xF79D Message Data Byte 6 -DB6_9.DB67 7 -DB6_9.DB66 6 -DB6_9.DB65 5 -DB6_9.DB64 4 -DB6_9.DB63 3 -DB6_9.DB62 2 -DB6_9.DB61 1 -DB6_9.DB60 0 -DB7_9 0xF79E Message Data Byte 7 -DB7_9.DB77 7 -DB7_9.DB76 6 -DB7_9.DB75 5 -DB7_9.DB74 4 -DB7_9.DB73 3 -DB7_9.DB72 2 -DB7_9.DB71 1 -DB7_9.DB70 0 -RESERVEDF79F 0xF79F RESERVED -; -------------------------------------- CAN_A -------------------------------- -MCR0_A 0xF7A0 Message Control Register Low -MCR0_A.MSGVAL1 7 -MCR0_A.MSGVAL0 6 -MCR0_A.TXIE1 5 -MCR0_A.TXIE0 4 -MCR0_A.RXIE1 3 -MCR0_A.RXIE0 2 -MCR0_A.INTPND1 1 -MCR0_A.INTPND0 0 -MCR1_A 0xF7A1 Message Control Register High -MCR1_A.RMTPND1 7 -MCR1_A.RMTPND0 6 -MCR1_A.TXRQ1 5 -MCR1_A.TXRQ0 4 -MCR1_A.MSGLSTCPUUPD1 3 -MCR1_A.MSGLSTCPUUPD0 2 -MCR1_A.NEWDAT1 1 -MCR1_A.NEWDAT0 0 -UAR0_A 0xF7A2 Upper Arbitration Register Low -UAR0_A.ID28 7 -UAR0_A.ID27 6 -UAR0_A.ID26 5 -UAR0_A.ID25 4 -UAR0_A.ID24 3 -UAR0_A.ID23 2 -UAR0_A.ID22 1 -UAR0_A.ID21 0 -UAR1_A 0xF7A3 Upper Arbitration Register High -UAR1_A.ID20 7 -UAR1_A.ID19 6 -UAR1_A.ID18 5 -UAR1_A.ID17 4 -UAR1_A.ID16 3 -UAR1_A.ID15 2 -UAR1_A.ID14 1 -UAR1_A.ID13 0 -LAR0_A 0xF7A4 Lower Arbitration Register Low -LAR0_A.ID12 7 -LAR0_A.ID11 6 -LAR0_A.ID10 5 -LAR0_A.ID9 4 -LAR0_A.ID8 3 -LAR0_A.ID7 2 -LAR0_A.ID6 1 -LAR0_A.ID5 0 -LAR1_A 0xF7A5 Lower Arbitration Register High -LAR1_A.ID4 7 -LAR1_A.ID3 6 -LAR1_A.ID2 5 -LAR1_A.ID1 4 -LAR1_A.ID0 3 -MCFG_A 0xF7A6 Message Configuration Register -MCFG_A.DLC7 7 -MCFG_A.DLC6 6 -MCFG_A.DLC5 5 -MCFG_A.DLC4 4 -MCFG_A.DIR 3 -MCFG_A.XTD 2 -DB0_A 0xF7A7 Message Data Byte 0 -DB0_A.DB07 7 -DB0_A.DB06 6 -DB0_A.DB05 5 -DB0_A.DB04 4 -DB0_A.DB03 3 -DB0_A.DB02 2 -DB0_A.DB01 1 -DB0_A.DB00 0 -DB1_A 0xF7A8 Message Data Byte 1 -DB1_A.DB17 7 -DB1_A.DB16 6 -DB1_A.DB15 5 -DB1_A.DB14 4 -DB1_A.DB13 3 -DB1_A.DB12 2 -DB1_A.DB11 1 -DB1_A.DB10 0 -DB2_A 0xF7A9 Message Data Byte 2 -DB2_A.DB27 7 -DB2_A.DB26 6 -DB2_A.DB25 5 -DB2_A.DB24 4 -DB2_A.DB23 3 -DB2_A.DB22 2 -DB2_A.DB21 1 -DB2_A.DB20 0 -DB3_A 0xF7AA Message Data Byte 3 -DB3_A.DB37 7 -DB3_A.DB36 6 -DB3_A.DB35 5 -DB3_A.DB34 4 -DB3_A.DB33 3 -DB3_A.DB32 2 -DB3_A.DB31 1 -DB3_A.DB30 0 -DB4_A 0xF7AB Message Data Byte 4 -DB4_A.DB47 7 -DB4_A.DB46 6 -DB4_A.DB45 5 -DB4_A.DB44 4 -DB4_A.DB43 3 -DB4_A.DB42 2 -DB4_A.DB41 1 -DB4_A.DB40 0 -DB5_A 0xF7AC Message Data Byte 5 -DB5_A.DB57 7 -DB5_A.DB56 6 -DB5_A.DB55 5 -DB5_A.DB54 4 -DB5_A.DB53 3 -DB5_A.DB52 2 -DB5_A.DB51 1 -DB5_A.DB50 0 -DB6_A 0xF7AD Message Data Byte 6 -DB6_A.DB67 7 -DB6_A.DB66 6 -DB6_A.DB65 5 -DB6_A.DB64 4 -DB6_A.DB63 3 -DB6_A.DB62 2 -DB6_A.DB61 1 -DB6_A.DB60 0 -DB7_A 0xF7AE Message Data Byte 7 -DB7_A.DB77 7 -DB7_A.DB76 6 -DB7_A.DB75 5 -DB7_A.DB74 4 -DB7_A.DB73 3 -DB7_A.DB72 2 -DB7_A.DB71 1 -DB7_A.DB70 0 -RESERVEDF7AF 0xF7AF RESERVED -; -------------------------------------- CAN_B -------------------------------- -MCR0_B 0xF7B0 Message Control Register Low -MCR0_B.MSGVAL1 7 -MCR0_B.MSGVAL0 6 -MCR0_B.TXIE1 5 -MCR0_B.TXIE0 4 -MCR0_B.RXIE1 3 -MCR0_B.RXIE0 2 -MCR0_B.INTPND1 1 -MCR0_B.INTPND0 0 -MCR1_B 0xF7B1 Message Control Register High -MCR1_B.RMTPND1 7 -MCR1_B.RMTPND0 6 -MCR1_B.TXRQ1 5 -MCR1_B.TXRQ0 4 -MCR1_B.MSGLSTCPUUPD1 3 -MCR1_B.MSGLSTCPUUPD0 2 -MCR1_B.NEWDAT1 1 -MCR1_B.NEWDAT0 0 -UAR0_B 0xF7B2 Upper Arbitration Register Low -UAR0_B.ID28 7 -UAR0_B.ID27 6 -UAR0_B.ID26 5 -UAR0_B.ID25 4 -UAR0_B.ID24 3 -UAR0_B.ID23 2 -UAR0_B.ID22 1 -UAR0_B.ID21 0 -UAR1_B 0xF7B3 Upper Arbitration Register High -UAR1_B.ID20 7 -UAR1_B.ID19 6 -UAR1_B.ID18 5 -UAR1_B.ID17 4 -UAR1_B.ID16 3 -UAR1_B.ID15 2 -UAR1_B.ID14 1 -UAR1_B.ID13 0 -LAR0_B 0xF7B4 Lower Arbitration Register Low -LAR0_B.ID12 7 -LAR0_B.ID11 6 -LAR0_B.ID10 5 -LAR0_B.ID9 4 -LAR0_B.ID8 3 -LAR0_B.ID7 2 -LAR0_B.ID6 1 -LAR0_B.ID5 0 -LAR1_B 0xF7B5 Lower Arbitration Register High -LAR1_B.ID4 7 -LAR1_B.ID3 6 -LAR1_B.ID2 5 -LAR1_B.ID1 4 -LAR1_B.ID0 3 -MCFG_B 0xF7B6 Message Configuration Register -MCFG_B.DLC7 7 -MCFG_B.DLC6 6 -MCFG_B.DLC5 5 -MCFG_B.DLC4 4 -MCFG_B.DIR 3 -MCFG_B.XTD 2 -DB0_B 0xF7B7 Message Data Byte 0 -DB0_B.DB07 7 -DB0_B.DB06 6 -DB0_B.DB05 5 -DB0_B.DB04 4 -DB0_B.DB03 3 -DB0_B.DB02 2 -DB0_B.DB01 1 -DB0_B.DB00 0 -DB1_B 0xF7B8 Message Data Byte 1 -DB1_B.DB17 7 -DB1_B.DB16 6 -DB1_B.DB15 5 -DB1_B.DB14 4 -DB1_B.DB13 3 -DB1_B.DB12 2 -DB1_B.DB11 1 -DB1_B.DB10 0 -DB2_B 0xF7B9 Message Data Byte 2 -DB2_B.DB27 7 -DB2_B.DB26 6 -DB2_B.DB25 5 -DB2_B.DB24 4 -DB2_B.DB23 3 -DB2_B.DB22 2 -DB2_B.DB21 1 -DB2_B.DB20 0 -DB3_B 0xF7BA Message Data Byte 3 -DB3_B.DB37 7 -DB3_B.DB36 6 -DB3_B.DB35 5 -DB3_B.DB34 4 -DB3_B.DB33 3 -DB3_B.DB32 2 -DB3_B.DB31 1 -DB3_B.DB30 0 -DB4_B 0xF7BB Message Data Byte 4 -DB4_B.DB47 7 -DB4_B.DB46 6 -DB4_B.DB45 5 -DB4_B.DB44 4 -DB4_B.DB43 3 -DB4_B.DB42 2 -DB4_B.DB41 1 -DB4_B.DB40 0 -DB5_B 0xF7BC Message Data Byte 5 -DB5_B.DB57 7 -DB5_B.DB56 6 -DB5_B.DB55 5 -DB5_B.DB54 4 -DB5_B.DB53 3 -DB5_B.DB52 2 -DB5_B.DB51 1 -DB5_B.DB50 0 -DB6_B 0xF7BD Message Data Byte 6 -DB6_B.DB67 7 -DB6_B.DB66 6 -DB6_B.DB65 5 -DB6_B.DB64 4 -DB6_B.DB63 3 -DB6_B.DB62 2 -DB6_B.DB61 1 -DB6_B.DB60 0 -DB7_B 0xF7BE Message Data Byte 7 -DB7_B.DB77 7 -DB7_B.DB76 6 -DB7_B.DB75 5 -DB7_B.DB74 4 -DB7_B.DB73 3 -DB7_B.DB72 2 -DB7_B.DB71 1 -DB7_B.DB70 0 -RESERVEDF7BF 0xF7BF RESERVED -; -------------------------------------- CAN_C -------------------------------- -MCR0_C 0xF7C0 Message Control Register Low -MCR0_C.MSGVAL1 7 -MCR0_C.MSGVAL0 6 -MCR0_C.TXIE1 5 -MCR0_C.TXIE0 4 -MCR0_C.RXIE1 3 -MCR0_C.RXIE0 2 -MCR0_C.INTPND1 1 -MCR0_C.INTPND0 0 -MCR1_C 0xF7C1 Message Control Register High -MCR1_C.RMTPND1 7 -MCR1_C.RMTPND0 6 -MCR1_C.TXRQ1 5 -MCR1_C.TXRQ0 4 -MCR1_C.MSGLSTCPUUPD1 3 -MCR1_C.MSGLSTCPUUPD0 2 -MCR1_C.NEWDAT1 1 -MCR1_C.NEWDAT0 0 -UAR0_C 0xF7C2 Upper Arbitration Register Low -UAR0_C.ID28 7 -UAR0_C.ID27 6 -UAR0_C.ID26 5 -UAR0_C.ID25 4 -UAR0_C.ID24 3 -UAR0_C.ID23 2 -UAR0_C.ID22 1 -UAR0_C.ID21 0 -UAR1_C 0xF7C3 Upper Arbitration Register High -UAR1_C.ID20 7 -UAR1_C.ID19 6 -UAR1_C.ID18 5 -UAR1_C.ID17 4 -UAR1_C.ID16 3 -UAR1_C.ID15 2 -UAR1_C.ID14 1 -UAR1_C.ID13 0 -LAR0_C 0xF7C4 Lower Arbitration Register Low -LAR0_C.ID12 7 -LAR0_C.ID11 6 -LAR0_C.ID10 5 -LAR0_C.ID9 4 -LAR0_C.ID8 3 -LAR0_C.ID7 2 -LAR0_C.ID6 1 -LAR0_C.ID5 0 -LAR1_C 0xF7C5 Lower Arbitration Register High -LAR1_C.ID4 7 -LAR1_C.ID3 6 -LAR1_C.ID2 5 -LAR1_C.ID1 4 -LAR1_C.ID0 3 -MCFG_C 0xF7C6 Message Configuration Register -MCFG_C.DLC7 7 -MCFG_C.DLC6 6 -MCFG_C.DLC5 5 -MCFG_C.DLC4 4 -MCFG_C.DIR 3 -MCFG_C.XTD 2 -DB0_C 0xF7C7 Message Data Byte 0 -DB0_C.DB07 7 -DB0_C.DB06 6 -DB0_C.DB05 5 -DB0_C.DB04 4 -DB0_C.DB03 3 -DB0_C.DB02 2 -DB0_C.DB01 1 -DB0_C.DB00 0 -DB1_C 0xF7C8 Message Data Byte 1 -DB1_C.DB17 7 -DB1_C.DB16 6 -DB1_C.DB15 5 -DB1_C.DB14 4 -DB1_C.DB13 3 -DB1_C.DB12 2 -DB1_C.DB11 1 -DB1_C.DB10 0 -DB2_C 0xF7C9 Message Data Byte 2 -DB2_C.DB27 7 -DB2_C.DB26 6 -DB2_C.DB25 5 -DB2_C.DB24 4 -DB2_C.DB23 3 -DB2_C.DB22 2 -DB2_C.DB21 1 -DB2_C.DB20 0 -DB3_C 0xF7CA Message Data Byte 3 -DB3_C.DB37 7 -DB3_C.DB36 6 -DB3_C.DB35 5 -DB3_C.DB34 4 -DB3_C.DB33 3 -DB3_C.DB32 2 -DB3_C.DB31 1 -DB3_C.DB30 0 -DB4_C 0xF7CB Message Data Byte 4 -DB4_C.DB47 7 -DB4_C.DB46 6 -DB4_C.DB45 5 -DB4_C.DB44 4 -DB4_C.DB43 3 -DB4_C.DB42 2 -DB4_C.DB41 1 -DB4_C.DB40 0 -DB5_C 0xF7CC Message Data Byte 5 -DB5_C.DB57 7 -DB5_C.DB56 6 -DB5_C.DB55 5 -DB5_C.DB54 4 -DB5_C.DB53 3 -DB5_C.DB52 2 -DB5_C.DB51 1 -DB5_C.DB50 0 -DB6_C 0xF7CD Message Data Byte 6 -DB6_C.DB67 7 -DB6_C.DB66 6 -DB6_C.DB65 5 -DB6_C.DB64 4 -DB6_C.DB63 3 -DB6_C.DB62 2 -DB6_C.DB61 1 -DB6_C.DB60 0 -DB7_C 0xF7CE Message Data Byte 7 -DB7_C.DB77 7 -DB7_C.DB76 6 -DB7_C.DB75 5 -DB7_C.DB74 4 -DB7_C.DB73 3 -DB7_C.DB72 2 -DB7_C.DB71 1 -DB7_C.DB70 0 -RESERVEDF7CF 0xF7CF RESERVED -; -------------------------------------- CAN_D -------------------------------- -MCR0_D 0xF7D0 Message Control Register Low -MCR0_D.MSGVAL1 7 -MCR0_D.MSGVAL0 6 -MCR0_D.TXIE1 5 -MCR0_D.TXIE0 4 -MCR0_D.RXIE1 3 -MCR0_D.RXIE0 2 -MCR0_D.INTPND1 1 -MCR0_D.INTPND0 0 -MCR1_D 0xF7D1 Message Control Register High -MCR1_D.RMTPND1 7 -MCR1_D.RMTPND0 6 -MCR1_D.TXRQ1 5 -MCR1_D.TXRQ0 4 -MCR1_D.MSGLSTCPUUPD1 3 -MCR1_D.MSGLSTCPUUPD0 2 -MCR1_D.NEWDAT1 1 -MCR1_D.NEWDAT0 0 -UAR0_D 0xF7D2 Upper Arbitration Register Low -UAR0_D.ID28 7 -UAR0_D.ID27 6 -UAR0_D.ID26 5 -UAR0_D.ID25 4 -UAR0_D.ID24 3 -UAR0_D.ID23 2 -UAR0_D.ID22 1 -UAR0_D.ID21 0 -UAR1_D 0xF7D3 Upper Arbitration Register High -UAR1_D.ID20 7 -UAR1_D.ID19 6 -UAR1_D.ID18 5 -UAR1_D.ID17 4 -UAR1_D.ID16 3 -UAR1_D.ID15 2 -UAR1_D.ID14 1 -UAR1_D.ID13 0 -LAR0_D 0xF7D4 Lower Arbitration Register Low -LAR0_D.ID12 7 -LAR0_D.ID11 6 -LAR0_D.ID10 5 -LAR0_D.ID9 4 -LAR0_D.ID8 3 -LAR0_D.ID7 2 -LAR0_D.ID6 1 -LAR0_D.ID5 0 -LAR1_D 0xF7D5 Lower Arbitration Register High -LAR1_D.ID4 7 -LAR1_D.ID3 6 -LAR1_D.ID2 5 -LAR1_D.ID1 4 -LAR1_D.ID0 3 -MCFG_D 0xF7D6 Message Configuration Register -MCFG_D.DLC7 7 -MCFG_D.DLC6 6 -MCFG_D.DLC5 5 -MCFG_D.DLC4 4 -MCFG_D.DIR 3 -MCFG_D.XTD 2 -DB0_D 0xF7D7 Message Data Byte 0 -DB0_D.DB07 7 -DB0_D.DB06 6 -DB0_D.DB05 5 -DB0_D.DB04 4 -DB0_D.DB03 3 -DB0_D.DB02 2 -DB0_D.DB01 1 -DB0_D.DB00 0 -DB1_D 0xF7D8 Message Data Byte 1 -DB1_D.DB17 7 -DB1_D.DB16 6 -DB1_D.DB15 5 -DB1_D.DB14 4 -DB1_D.DB13 3 -DB1_D.DB12 2 -DB1_D.DB11 1 -DB1_D.DB10 0 -DB2_D 0xF7D9 Message Data Byte 2 -DB2_D.DB27 7 -DB2_D.DB26 6 -DB2_D.DB25 5 -DB2_D.DB24 4 -DB2_D.DB23 3 -DB2_D.DB22 2 -DB2_D.DB21 1 -DB2_D.DB20 0 -DB3_D 0xF7DA Message Data Byte 3 -DB3_D.DB37 7 -DB3_D.DB36 6 -DB3_D.DB35 5 -DB3_D.DB34 4 -DB3_D.DB33 3 -DB3_D.DB32 2 -DB3_D.DB31 1 -DB3_D.DB30 0 -DB4_D 0xF7DB Message Data Byte 4 -DB4_D.DB47 7 -DB4_D.DB46 6 -DB4_D.DB45 5 -DB4_D.DB44 4 -DB4_D.DB43 3 -DB4_D.DB42 2 -DB4_D.DB41 1 -DB4_D.DB40 0 -DB5_D 0xF7DC Message Data Byte 5 -DB5_D.DB57 7 -DB5_D.DB56 6 -DB5_D.DB55 5 -DB5_D.DB54 4 -DB5_D.DB53 3 -DB5_D.DB52 2 -DB5_D.DB51 1 -DB5_D.DB50 0 -DB6_D 0xF7DD Message Data Byte 6 -DB6_D.DB67 7 -DB6_D.DB66 6 -DB6_D.DB65 5 -DB6_D.DB64 4 -DB6_D.DB63 3 -DB6_D.DB62 2 -DB6_D.DB61 1 -DB6_D.DB60 0 -DB7_D 0xF7DE Message Data Byte 7 -DB7_D.DB77 7 -DB7_D.DB76 6 -DB7_D.DB75 5 -DB7_D.DB74 4 -DB7_D.DB73 3 -DB7_D.DB72 2 -DB7_D.DB71 1 -DB7_D.DB70 0 -RESERVEDF7DF 0xF7DF RESERVED -; -------------------------------------- CAN_E -------------------------------- -MCR0_E 0xF7E0 Message Control Register Low -MCR0_E.MSGVAL1 7 -MCR0_E.MSGVAL0 6 -MCR0_E.TXIE1 5 -MCR0_E.TXIE0 4 -MCR0_E.RXIE1 3 -MCR0_E.RXIE0 2 -MCR0_E.INTPND1 1 -MCR0_E.INTPND0 0 -MCR1_E 0xF7E1 Message Control Register High -MCR1_E.RMTPND1 7 -MCR1_E.RMTPND0 6 -MCR1_E.TXRQ1 5 -MCR1_E.TXRQ0 4 -MCR1_E.MSGLSTCPUUPD1 3 -MCR1_E.MSGLSTCPUUPD0 2 -MCR1_E.NEWDAT1 1 -MCR1_E.NEWDAT0 0 -UAR0_E 0xF7E2 Upper Arbitration Register Low -UAR0_E.ID28 7 -UAR0_E.ID27 6 -UAR0_E.ID26 5 -UAR0_E.ID25 4 -UAR0_E.ID24 3 -UAR0_E.ID23 2 -UAR0_E.ID22 1 -UAR0_E.ID21 0 -UAR1_E 0xF7E3 Upper Arbitration Register High -UAR1_E.ID20 7 -UAR1_E.ID19 6 -UAR1_E.ID18 5 -UAR1_E.ID17 4 -UAR1_E.ID16 3 -UAR1_E.ID15 2 -UAR1_E.ID14 1 -UAR1_E.ID13 0 -LAR0_E 0xF7E4 Lower Arbitration Register Low -LAR0_E.ID12 7 -LAR0_E.ID11 6 -LAR0_E.ID10 5 -LAR0_E.ID9 4 -LAR0_E.ID8 3 -LAR0_E.ID7 2 -LAR0_E.ID6 1 -LAR0_E.ID5 0 -LAR1_E 0xF7E5 Lower Arbitration Register High -LAR1_E.ID4 7 -LAR1_E.ID3 6 -LAR1_E.ID2 5 -LAR1_E.ID1 4 -LAR1_E.ID0 3 -MCFG_E 0xF7E6 Message Configuration Register -MCFG_E.DLC7 7 -MCFG_E.DLC6 6 -MCFG_E.DLC5 5 -MCFG_E.DLC4 4 -MCFG_E.DIR 3 -MCFG_E.XTD 2 -DB0_E 0xF7E7 Message Data Byte 0 -DB0_E.DB07 7 -DB0_E.DB06 6 -DB0_E.DB05 5 -DB0_E.DB04 4 -DB0_E.DB03 3 -DB0_E.DB02 2 -DB0_E.DB01 1 -DB0_E.DB00 0 -DB1_E 0xF7E8 Message Data Byte 1 -DB1_E.DB17 7 -DB1_E.DB16 6 -DB1_E.DB15 5 -DB1_E.DB14 4 -DB1_E.DB13 3 -DB1_E.DB12 2 -DB1_E.DB11 1 -DB1_E.DB10 0 -DB2_E 0xF7E9 Message Data Byte 2 -DB2_E.DB27 7 -DB2_E.DB26 6 -DB2_E.DB25 5 -DB2_E.DB24 4 -DB2_E.DB23 3 -DB2_E.DB22 2 -DB2_E.DB21 1 -DB2_E.DB20 0 -DB3_E 0xF7EA Message Data Byte 3 -DB3_E.DB37 7 -DB3_E.DB36 6 -DB3_E.DB35 5 -DB3_E.DB34 4 -DB3_E.DB33 3 -DB3_E.DB32 2 -DB3_E.DB31 1 -DB3_E.DB30 0 -DB4_E 0xF7EB Message Data Byte 4 -DB4_E.DB47 7 -DB4_E.DB46 6 -DB4_E.DB45 5 -DB4_E.DB44 4 -DB4_E.DB43 3 -DB4_E.DB42 2 -DB4_E.DB41 1 -DB4_E.DB40 0 -DB5_E 0xF7EC Message Data Byte 5 -DB5_E.DB57 7 -DB5_E.DB56 6 -DB5_E.DB55 5 -DB5_E.DB54 4 -DB5_E.DB53 3 -DB5_E.DB52 2 -DB5_E.DB51 1 -DB5_E.DB50 0 -DB6_E 0xF7ED Message Data Byte 6 -DB6_E.DB67 7 -DB6_E.DB66 6 -DB6_E.DB65 5 -DB6_E.DB64 4 -DB6_E.DB63 3 -DB6_E.DB62 2 -DB6_E.DB61 1 -DB6_E.DB60 0 -DB7_E 0xF7DE Message Data Byte 7 -DB7_E.DB77 7 -DB7_E.DB76 6 -DB7_E.DB75 5 -DB7_E.DB74 4 -DB7_E.DB73 3 -DB7_E.DB72 2 -DB7_E.DB71 1 -DB7_E.DB70 0 -RESERVEDF7EF 0xF7EF RESERVED -; -------------------------------------- CAN_F -------------------------------- -MCR0_F 0xF7F0 Message Control Register Low -MCR0_F.MSGVAL1 7 -MCR0_F.MSGVAL0 6 -MCR0_F.TXIE1 5 -MCR0_F.TXIE0 4 -MCR0_F.RXIE1 3 -MCR0_F.RXIE0 2 -MCR0_F.INTPND1 1 -MCR0_F.INTPND0 0 -MCR1_F 0xF7F1 Message Control Register High -MCR1_F.RMTPND1 7 -MCR1_F.RMTPND0 6 -MCR1_F.TXRQ1 5 -MCR1_F.TXRQ0 4 -MCR1_F.MSGLSTCPUUPD1 3 -MCR1_F.MSGLSTCPUUPD0 2 -MCR1_F.NEWDAT1 1 -MCR1_F.NEWDAT0 0 -UAR0_F 0xF7F2 Upper Arbitration Register Low -UAR0_F.ID28 7 -UAR0_F.ID27 6 -UAR0_F.ID26 5 -UAR0_F.ID25 4 -UAR0_F.ID24 3 -UAR0_F.ID23 2 -UAR0_F.ID22 1 -UAR0_F.ID21 0 -UAR1_F 0xF7F3 Upper Arbitration Register High -UAR1_F.ID20 7 -UAR1_F.ID19 6 -UAR1_F.ID18 5 -UAR1_F.ID17 4 -UAR1_F.ID16 3 -UAR1_F.ID15 2 -UAR1_F.ID14 1 -UAR1_F.ID13 0 -LAR0_F 0xF7F4 Lower Arbitration Register Low -LAR0_F.ID12 7 -LAR0_F.ID11 6 -LAR0_F.ID10 5 -LAR0_F.ID9 4 -LAR0_F.ID8 3 -LAR0_F.ID7 2 -LAR0_F.ID6 1 -LAR0_F.ID5 0 -LAR1_F 0xF7F5 Lower Arbitration Register High -LAR1_F.ID4 7 -LAR1_F.ID3 6 -LAR1_F.ID2 5 -LAR1_F.ID1 4 -LAR1_F.ID0 3 -MCFG_F 0xF7F6 Message Configuration Register -MCFG_F.DLC7 7 -MCFG_F.DLC6 6 -MCFG_F.DLC5 5 -MCFG_F.DLC4 4 -MCFG_F.DIR 3 -MCFG_F.XTD 2 -DB0_F 0xF7F7 Message Data Byte 0 -DB0_F.DB07 7 -DB0_F.DB06 6 -DB0_F.DB05 5 -DB0_F.DB04 4 -DB0_F.DB03 3 -DB0_F.DB02 2 -DB0_F.DB01 1 -DB0_F.DB00 0 -DB1_F 0xF7F8 Message Data Byte 1 -DB1_F.DB17 7 -DB1_F.DB16 6 -DB1_F.DB15 5 -DB1_F.DB14 4 -DB1_F.DB13 3 -DB1_F.DB12 2 -DB1_F.DB11 1 -DB1_F.DB10 0 -DB2_F 0xF7F9 Message Data Byte 2 -DB2_F.DB27 7 -DB2_F.DB26 6 -DB2_F.DB25 5 -DB2_F.DB24 4 -DB2_F.DB23 3 -DB2_F.DB22 2 -DB2_F.DB21 1 -DB2_F.DB20 0 -DB3_F 0xF7FA Message Data Byte 3 -DB3_F.DB37 7 -DB3_F.DB36 6 -DB3_F.DB35 5 -DB3_F.DB34 4 -DB3_F.DB33 3 -DB3_F.DB32 2 -DB3_F.DB31 1 -DB3_F.DB30 0 -DB4_F 0xF7FB Message Data Byte 4 -DB4_F.DB47 7 -DB4_F.DB46 6 -DB4_F.DB45 5 -DB4_F.DB44 4 -DB4_F.DB43 3 -DB4_F.DB42 2 -DB4_F.DB41 1 -DB4_F.DB40 0 -DB5_F 0xF7FC Message Data Byte 5 -DB5_F.DB57 7 -DB5_F.DB56 6 -DB5_F.DB55 5 -DB5_F.DB54 4 -DB5_F.DB53 3 -DB5_F.DB52 2 -DB5_F.DB51 1 -DB5_F.DB50 0 -DB6_F 0xF7FD Message Data Byte 6 -DB6_F.DB67 7 -DB6_F.DB66 6 -DB6_F.DB65 5 -DB6_F.DB64 4 -DB6_F.DB63 3 -DB6_F.DB62 2 -DB6_F.DB61 1 -DB6_F.DB60 0 -DB7_F 0xF7FE Message Data Byte 7 -DB7_F.DB77 7 -DB7_F.DB76 6 -DB7_F.DB75 5 -DB7_F.DB74 4 -DB7_F.DB73 3 -DB7_F.DB72 2 -DB7_F.DB71 1 -DB7_F.DB70 0 -RESERVEDF7FF 0xF7FF RESERVED - - -.C505L -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=29187&parent_oid=29275 -; SAF-C505L-4EM.pdf - - -; up to 64 Kbytes of program memory (32K on-chip OTP memory) -; up to 64 Kbytes of external data memory -; 256 bytes of internal data memory -; 256 bytes of internal XRAM data memory -; 20 bytes of LCD Controller registers -; 16 bytes of Real-Time Clock (RTC) registers -; A 128-byte Special Function Register (SFR) area - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry SWI 0x004B Software Interrupt -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry IRTC 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.P14 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -; P1ANA 0x0090 Port 1 Analog Input Selection Register -; P1ANA.EAN7 7 -; P1ANA.EAN6 6 -; P1ANA.EAN5 5 -; P1ANA.EAN4 4 -; P1ANA.EAN3 3 -; P1ANA.EAN2 2 -; P1ANA.EAN1 1 -; P1ANA.EAN0 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM, LCD Controller and RTC -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register -SYSCON.EALE 5 -SYSCON.RMAP 4 SFR map bit -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.ESWI 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.SWI 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Reload Register Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Reload Register High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 Carry Flag -PSW.AC 6 Auxiliary Carry Flag -PSW.F0 5 General Purpose Flag -PSW.RS1 4 Register Bank select control bit 1 -PSW.RS0 3 Register Bank select control bit 0 -PSW.OV 2 Overflow Flag -PSW.F1 1 General Purpose Flag -PSW.P 0 Parity Flag -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register High Byte -ADDATH.ADDATH9 7 -ADDATH.ADDATH8 6 -ADDATH.ADDATH7 5 -ADDATH.ADDATH6 4 -ADDATH.ADDATH5 3 -ADDATH.ADDATH4 2 -ADDATH.ADDATH3 1 -ADDATH.ADDATH2 0 -ADDATL 0x00DA A/D Converter Data Register Low Byte -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -RESERVED00DB 0x00DB RESERVED -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.P47 7 -P4.P46 6 -P4.P45 5 -P4.P44 4 -P4.P43 3 -P4.P42 2 -P4.P41 1 -P4.P40 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -P5 0x00F8 Port 5 -P5.P55 5 -P5.P54 4 -P5.P53 3 -P5.P52 2 -P5.P51 1 -P5.P50 0 -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -VR2.VR27 7 -VR2.VR26 6 -VR2.VR25 5 -VR2.VR24 4 -VR2.VR23 3 -VR2.VR22 2 -VR2.VR21 1 -VR2.VR20 0 -RESERVED00FF 0x00FF RESERVED -DAC0 0xF3DC D/A Conversion Register -DAC0.S7 7 -DAC0.S6 6 -DAC0.S5 5 -DAC0.S4 4 -DAC0.S3 3 -DAC0.S2 2 -DAC0.S1 1 -DAC0.S0 0 -LCON 0xF3DD LCD Control Register -LCON.DSB1 7 -LCON.DSB0 6 -LCON.CSEL 1 -LCON.LCEN 0 -LCRL 0xF3DE LCD Timer Reload Low Register -LCRL.LCRL7 7 -LCRL.LCRL6 6 -LCRL.LCRL5 5 -LCRL.LCRL4 4 -LCRL.LCRL3 3 -LCRL.LCRL2 2 -LCRL.LCRL1 1 -LCRL.LCRL0 0 -LCRH 0xF3DF LCD Timer Reload High Register -LCRH.SLT 7 -LCRH.LCRH14 6 -LCRH.LCRH13 5 -LCRH.LCRH12 4 -LCRH.LCRH11 3 -LCRH.LCRH10 2 -LCRH.LCRH9 1 -LCRH.LCRH8 0 -DIG0 0xF3E0 LCD Digit Register 0 -DIG0.SEGF 7 -DIG0.SEGA 6 -DIG0.SEGG 5 -DIG0.SEGB 4 -DIG0.SEGE 3 -DIG0.SEGC 2 -DIG0.SEGH 1 -DIG0.SEGD 0 -DIG1 0xF3E1 LCD Digit Register 1 -DIG1.SEGF 7 -DIG1.SEGA 6 -DIG1.SEGG 5 -DIG1.SEGB 4 -DIG1.SEGE 3 -DIG1.SEGC 2 -DIG1.SEGH 1 -DIG1.SEGD 0 -DIG2 0xF3E2 LCD Digit Register 2 -DIG2.SEGF 7 -DIG2.SEGA 6 -DIG2.SEGG 5 -DIG2.SEGB 4 -DIG2.SEGE 3 -DIG2.SEGC 2 -DIG2.SEGH 1 -DIG2.SEGD 0 -DIG3 0xF3E3 LCD Digit Register 3 -DIG3.SEGF 7 -DIG3.SEGA 6 -DIG3.SEGG 5 -DIG3.SEGB 4 -DIG3.SEGE 3 -DIG3.SEGC 2 -DIG3.SEGH 1 -DIG3.SEGD 0 -DIG4 0xF3E4 LCD Digit Register 4 -DIG4.SEGF 7 -DIG4.SEGA 6 -DIG4.SEGG 5 -DIG4.SEGB 4 -DIG4.SEGE 3 -DIG4.SEGC 2 -DIG4.SEGH 1 -DIG4.SEGD 0 -DIG5 0xF3E5 LCD Digit Register 5 -DIG5.SEGF 7 -DIG5.SEGA 6 -DIG5.SEGG 5 -DIG5.SEGB 4 -DIG5.SEGE 3 -DIG5.SEGC 2 -DIG5.SEGH 1 -DIG5.SEGD 0 -DIG6 0xF3E6 LCD Digit Register 6 -DIG6.SEGF 7 -DIG6.SEGA 6 -DIG6.SEGG 5 -DIG6.SEGB 4 -DIG6.SEGE 3 -DIG6.SEGC 2 -DIG6.SEGH 1 -DIG6.SEGD 0 -DIG7 0xF3E7 LCD Digit Register 7 -DIG7.SEGF 7 -DIG7.SEGA 6 -DIG7.SEGG 5 -DIG7.SEGB 4 -DIG7.SEGE 3 -DIG7.SEGC 2 -DIG7.SEGH 1 -DIG7.SEGD 0 -DIG8 0xF3E8 LCD Digit Register 8 -DIG8.SEGF 7 -DIG8.SEGA 6 -DIG8.SEGG 5 -DIG8.SEGB 4 -DIG8.SEGE 3 -DIG8.SEGC 2 -DIG8.SEGH 1 -DIG8.SEGD 0 -DIG9 0xF3E9 LCD Digit Register 9 -DIG9.SEGF 7 -DIG9.SEGA 6 -DIG9.SEGG 5 -DIG9.SEGB 4 -DIG9.SEGE 3 -DIG9.SEGC 2 -DIG9.SEGH 1 -DIG9.SEGD 0 -DIGA 0xF3EA LCD Digit Register A -DIGA.SEGF 7 -DIGA.SEGA 6 -DIGA.SEGG 5 -DIGA.SEGB 4 -DIGA.SEGE 3 -DIGA.SEGC 2 -DIGA.SEGH 1 -DIGA.SEGD 0 -DIGB 0xF3EB LCD Digit Register B -DIGB.SEGF 7 -DIGB.SEGA 6 -DIGB.SEGG 5 -DIGB.SEGB 4 -DIGB.SEGE 3 -DIGB.SEGC 2 -DIGB.SEGH 1 -DIGB.SEGD 0 -DIGC 0xF3EC LCD Digit Register C -DIGC.SEGF 7 -DIGC.SEGA 6 -DIGC.SEGG 5 -DIGC.SEGB 4 -DIGC.SEGE 3 -DIGC.SEGC 2 -DIGC.SEGH 1 -DIGC.SEGD 0 -DIGD 0xF3ED LCD Digit Register D -DIGD.SEGF 7 -DIGD.SEGA 6 -DIGD.SEGG 5 -DIGD.SEGB 4 -DIGD.SEGE 3 -DIGD.SEGC 2 -DIGD.SEGH 1 -DIGD.SEGD 0 -DIGE 0xF3EE LCD Digit Register E -DIGE.SEGF 7 -DIGE.SEGA 6 -DIGE.SEGG 5 -DIGE.SEGB 4 -DIGE.SEGE 3 -DIGE.SEGC 2 -DIGE.SEGH 1 -DIGE.SEGD 0 -DIGF 0xF3EF LCD Digit Register F -DIGF.SEGF 7 -DIGF.SEGA 6 -DIGF.SEGG 5 -DIGF.SEGB 4 -DIGF.SEGE 3 -DIGF.SEGC 2 -DIGF.SEGH 1 -DIGF.SEGD 0 -RTCON 0xF3F0 Real-Time Clock Control Register -RTCON.RTPD 3 -RTCON.IRTC 2 -RTCON.ERTC 1 -RTCON.RTCS 0 -RTCR0 0xF3F1 Real-Time Clock Initialization Register 0 -RTCR0.RTCR07 7 -RTCR0.RTCR06 6 -RTCR0.RTCR05 5 -RTCR0.RTCR04 4 -RTCR0.RTCR03 3 -RTCR0.RTCR02 2 -RTCR0.RTCR01 1 -RTCR0.RTCR00 0 -RTCR1 0xF3F2 Real-Time Clock Initialization Register 1 -RTCR1.RTCR17 7 -RTCR1.RTCR16 6 -RTCR1.RTCR15 5 -RTCR1.RTCR14 4 -RTCR1.RTCR13 3 -RTCR1.RTCR12 2 -RTCR1.RTCR11 1 -RTCR1.RTCR10 0 -RTCR2 0xF3F3 Real-Time Clock Initialization Register 2 -RTCR2.RTCR27 7 -RTCR2.RTCR26 6 -RTCR2.RTCR25 5 -RTCR2.RTCR24 4 -RTCR2.RTCR23 3 -RTCR2.RTCR22 2 -RTCR2.RTCR21 1 -RTCR2.RTCR20 0 -RTCR3 0xF3F4 Real-Time Clock Initialization Register 3 -RTCR3.RTCR37 7 -RTCR3.RTCR36 6 -RTCR3.RTCR35 5 -RTCR3.RTCR34 4 -RTCR3.RTCR33 3 -RTCR3.RTCR32 2 -RTCR3.RTCR31 1 -RTCR3.RTCR30 0 -RTCR4 0xF3F5 Real-Time Clock Initialization Register 4 -RTCR4.RTCR47 7 -RTCR4.RTCR46 6 -RTCR4.RTCR45 5 -RTCR4.RTCR44 4 -RTCR4.RTCR43 3 -RTCR4.RTCR42 2 -RTCR4.RTCR41 1 -RTCR4.RTCR40 0 -CLREG0 0xF3F6 Clock Count Register 0 -CLREG0.CLREG07 7 -CLREG0.CLREG06 6 -CLREG0.CLREG05 5 -CLREG0.CLREG04 4 -CLREG0.CLREG03 3 -CLREG0.CLREG02 2 -CLREG0.CLREG01 1 -CLREG0.CLREG00 0 -CLREG1 0xF3F7 Clock Count Register 1 -CLREG1.CLREG17 7 -CLREG1.CLREG16 6 -CLREG1.CLREG15 5 -CLREG1.CLREG14 4 -CLREG1.CLREG13 3 -CLREG1.CLREG12 2 -CLREG1.CLREG11 1 -CLREG1.CLREG10 0 -CLREG2 0xF3F8 Clock Count Register 2 -CLREG2.CLREG27 7 -CLREG2.CLREG26 6 -CLREG2.CLREG25 5 -CLREG2.CLREG24 4 -CLREG2.CLREG23 3 -CLREG2.CLREG22 2 -CLREG2.CLREG21 1 -CLREG2.CLREG20 0 -CLREG3 0xF3F9 Clock Count Register 3 -CLREG3.CLREG37 7 -CLREG3.CLREG36 6 -CLREG3.CLREG35 5 -CLREG3.CLREG34 4 -CLREG3.CLREG33 3 -CLREG3.CLREG32 2 -CLREG3.CLREG31 1 -CLREG3.CLREG30 0 -CLREG4 0xF3FA Clock Count Register 4 -CLREG4.CLREG47 7 -CLREG4.CLREG46 6 -CLREG4.CLREG45 5 -CLREG4.CLREG44 4 -CLREG4.CLREG43 3 -CLREG4.CLREG42 2 -CLREG4.CLREG41 1 -CLREG4.CLREG40 0 -RTINT0 0xF3FB Real-Time Clock Interrupt Register 0 -RTINT0.RTINT07 7 -RTINT0.RTINT06 6 -RTINT0.RTINT05 5 -RTINT0.RTINT04 4 -RTINT0.RTINT03 3 -RTINT0.RTINT02 2 -RTINT0.RTINT01 1 -RTINT0.RTINT00 0 -RTINT1 0xF3FC Real-Time Clock Interrupt Register 1 -RTINT1.RTINT17 7 -RTINT1.RTINT16 6 -RTINT1.RTINT15 5 -RTINT1.RTINT14 4 -RTINT1.RTINT13 3 -RTINT1.RTINT12 2 -RTINT1.RTINT11 1 -RTINT1.RTINT10 0 -RTINT2 0xF3FD Real-Time Clock Interrupt Register 2 -RTINT2.RTINT27 7 -RTINT2.RTINT26 6 -RTINT2.RTINT25 5 -RTINT2.RTINT24 4 -RTINT2.RTINT23 3 -RTINT2.RTINT22 2 -RTINT2.RTINT21 1 -RTINT2.RTINT20 0 -RTINT3 0xF3FE Real-Time Clock Interrupt Register 3 -RTINT3.RTINT37 7 -RTINT3.RTINT36 6 -RTINT3.RTINT35 5 -RTINT3.RTINT34 4 -RTINT3.RTINT33 3 -RTINT3.RTINT32 2 -RTINT3.RTINT31 1 -RTINT3.RTINT30 0 -RTINT4 0xF3FF Real-Time Clock Interrupt Register 4 -RTINT4.RTINT47 7 -RTINT4.RTINT46 6 -RTINT4.RTINT45 5 -RTINT4.RTINT44 4 -RTINT4.RTINT43 3 -RTINT4.RTINT42 2 -RTINT4.RTINT41 1 -RTINT4.RTINT40 0 - - -.C508 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=19575&parent_oid=12110 -; SAF-C508-4EM.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xFC00 -area DATA RAM2 0xFC00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External Interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External Interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2 0x002B Timer 2 Overflow -entry IADC 0x0043 A/D Converter -entry IEX2 0x004B External Interrupt 2 -entry IEX3 0x0053 External Interrupt 3 -entry IEX4 0x005B External Interrupt 4 -entry IEX5 0x0063 External Interrupt 5 -entry IEX6 0x006B External Interrupt 6 -entry TRF_BCERR 0x0093 CAPCOM Emergency Interrupt -entry CT2P 0x009B Compare Timer 2 Interrupt -entry CCxF_CCxF 0x00A3 Capture/Compare Match Interrupt -entry CT1FP_CT1FC 0x00AB Compare Timer 1 Interrupt -entry IEX7 0x00D3 External Interrupt 7 -entry IEX8 0x00DB External Interrupt 8 -entry IEX9 0x00E3 External Interrupt 9 -entry WAKE_UP 0x00EB Wake-up from power-down - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -WDTL 0x0084 Watchdog Timer Register, low byte -WDTL.WDTL7 7 -WDTL.WDTL6 6 -WDTL.WDTL5 5 -WDTL.WDTL4 4 -WDTL.WDTL3 3 -WDTL.WDTL2 2 -WDTL.WDTL1 1 -WDTL.WDTL0 0 -WDTH 0x0085 Watchdog Timer Register, high byte -WDTH.WDTH7 7 -WDTH.WDTH6 6 -WDTH.WDTH5 5 -WDTH.WDTH4 4 -WDTH.WDTH3 3 -WDTH.WDTH2 2 -WDTH.WDTH1 1 -WDTH.WDTH0 0 -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.P17 7 -P1.P16 6 -P1.P15 5 -P1.P14 4 -P1.P13 3 -P1.P12 2 -P1.P11 1 -P1.P10 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -IEN2 0x009A Interrupt Enable Register 2 -IEN2.ECT1 5 -IEN2.ECCM 4 -IEN2.ECT2 3 -IEN2.ECEM 2 -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EA 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.EX2 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -IEN3 0x00BE Interrupt Enable Register 3 -IEN3.EX9 4 -IEN3.EX8 3 -IEN3.EX7 2 -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.IEX2 1 -IRCON.IADC 0 -CCEN 0x00C1 Compare/Capture Enable Register -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -T2CCL1 0x00C2 Compare/Capture Register 1, Low Byte -T2CCL1.T2CCL17 7 -T2CCL1.T2CCL16 6 -T2CCL1.T2CCL15 5 -T2CCL1.T2CCL14 4 -T2CCL1.T2CCL13 3 -T2CCL1.T2CCL12 2 -T2CCL1.T2CCL11 1 -T2CCL1.T2CCL10 0 -T2CCH1 0x00C3 Compare/Capture Register 1, High Byte -T2CCH1.T2CCH17 7 -T2CCH1.T2CCH16 6 -T2CCH1.T2CCH15 5 -T2CCH1.T2CCH14 4 -T2CCH1.T2CCH13 3 -T2CCH1.T2CCH12 2 -T2CCH1.T2CCH11 1 -T2CCH1.T2CCH10 0 -T2CCL2 0x00C4 Compare/Capture Register 2, Low Byte -T2CCL2.T2CCL27 7 -T2CCL2.T2CCL26 6 -T2CCL2.T2CCL25 5 -T2CCL2.T2CCL24 4 -T2CCL2.T2CCL23 3 -T2CCL2.T2CCL22 2 -T2CCL2.T2CCL21 1 -T2CCL2.T2CCL20 0 -T2CCH2 0x00C5 Compare/Capture Register 2, High Byte -T2CCH2.T2CCH27 7 -T2CCH2.T2CCH26 6 -T2CCH2.T2CCH25 5 -T2CCH2.T2CCH24 4 -T2CCH2.T2CCH23 3 -T2CCH2.T2CCH22 2 -T2CCH2.T2CCH21 1 -T2CCH2.T2CCH20 0 -T2CCL3 0x00C6 Compare/Capture Register 3, Low Byte -T2CCL3.T2CCL37 7 -T2CCL3.T2CCL36 6 -T2CCL3.T2CCL35 5 -T2CCL3.T2CCL34 4 -T2CCL3.T2CCL33 3 -T2CCL3.T2CCL32 2 -T2CCL3.T2CCL31 1 -T2CCL3.T2CCL30 0 -T2CCH3 0x00C7 Compare/Capture Register 3, High Byte -T2CCH3.T2CCH37 7 -T2CCH3.T2CCH36 6 -T2CCH3.T2CCH35 5 -T2CCH3.T2CCH34 4 -T2CCH3.T2CCH33 3 -T2CCH3.T2CCH32 2 -T2CCH3.T2CCH31 1 -T2CCH3.T2CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.I2FR 5 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Comp./Rel./Capt. Register, Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Comp./Rel./Capt. Register, High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 Carry Flag -PSW.AC 6 Auxiliary Carry Flag -PSW.F0 5 General Purpose Flag 0 -PSW.RS1 4 Register Bank select control bit 1 -PSW.RS0 3 Register Bank select control bit 0 -PSW.OV 2 Overflow Flag -PSW.F1 1 General Purpose Flag 1 -PSW.P 0 Parity Flag -RESERVED00D1 0x00D1 RESERVED -CP2L 0x00D2 Compare timer 2 period register, low byte -CP2L.CP2L7 7 -CP2L.CP2L6 6 -CP2L.CP2L5 5 -CP2L.CP2L4 4 -CP2L.CP2L3 3 -CP2L.CP2L2 2 -CP2L.CP2L1 1 -CP2L.CP2L0 0 -CP2H 0x00D3 Compare timer 2 period register, high byte -CP2H.CP2H1 1 -CP2H.CP2H0 0 -CMP2L 0x00D4 Compare timer 2 compare register, low byte -CMP2L.CMP2L7 7 -CMP2L.CMP2L6 6 -CMP2L.CMP2L5 5 -CMP2L.CMP2L4 4 -CMP2L.CMP2L3 3 -CMP2L.CMP2L2 2 -CMP2L.CMP2L1 1 -CMP2L.CMP2L0 0 -CMP2H 0x00D5 Compare timer 2 compare register, high byte -CMP2H.CMP2H1 1 -CMP2H.CMP2H0 0 -CCIE 0x00D6 Capture/compare interrupt enable register -CCIE.ECTP 7 -CCIE.ECTC 6 -CCIE.CC2FEN 5 -CCIE.CC2REN 4 -CCIE.CC1FEN 3 -CCIE.CC1REN 2 -CCIE.CC0FEN 1 -CCIE.CC0REN 0 -BCON 0x00D7 Block commutation control register -BCON.BCMPBCEM 7 -BCON.PWM1 6 -BCON.PWM0 5 -BCON.EBCE 4 -BCON.BCERR 3 -BCON.BCEN 2 -BCON.BCM1 1 -BCON.BCM0 0 -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.BD 6 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register High Byte -ADDATH.ADDATH9 7 -ADDATH.ADDATH8 6 -ADDATH.ADDATH7 5 -ADDATH.ADDATH6 4 -ADDATH.ADDATH5 3 -ADDATH.ADDATH4 2 -ADDATH.ADDATH3 1 -ADDATH.ADDATH2 0 -ADDATL 0x00DA A/D Converter Start Register Low Byte -ADDATL.1 7 -ADDATL.0 6 -P4 0x00DB Port 4, Analog/Digital Input -P4.P47 7 -P4.P46 6 -P4.P45 5 -P4.P44 4 -P4.P43 3 -P4.P42 2 -P4.P41 1 -P4.P40 0 -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -CCPL 0x00DE Compare timer 1 period register, low byte -CCPL.CCPL7 7 -CCPL.CCPL6 6 -CCPL.CCPL5 5 -CCPL.CCPL4 4 -CCPL.CCPL3 3 -CCPL.CCPL2 2 -CCPL.CCPL1 1 -CCPL.CCPL0 0 -CCPH 0x00DF Compare timer 1 period register, high byte -CCPH.CCPH7 7 -CCPH.CCPH6 6 -CCPH.CCPH5 5 -CCPH.CCPH4 4 -CCPH.CCPH3 3 -CCPH.CCPH2 2 -CCPH.CCPH1 1 -CCPH.CCPH0 0 -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -CT1CON 0x00E1 Compare timer 1 control register -CT1CON.CTM 7 -CT1CON.ETRP 6 -CT1CON.STE1 5 -CT1CON.CT1RES 4 -CT1CON.CT1R 3 -CT1CON.CLK2 2 -CT1CON.CLK1 1 -CT1CON.CLK0 0 -COINI 0x00E2 Compare output initialization register -COINI.COUT3I 7 -COINI.COUTXI 6 -COINI.COUT2I 5 -COINI.CC2I 4 -COINI.COUT1I 3 -COINI.CC1I 2 -COINI.COUT0I 1 -COINI.CC0I 0 -CMSEL0 0x00E3 Capture/compare mode select register 0 -CMSEL0.CMSEL13 7 -CMSEL0.CMSEL12 6 -CMSEL0.CMSEL11 5 -CMSEL0.CMSEL10 4 -CMSEL0.CMSEL03 3 -CMSEL0.CMSEL02 2 -CMSEL0.CMSEL01 1 -CMSEL0.CMSEL00 0 -CMSEL1 0x00E4 Capture/compare mode select register 1 -CMSEL1.ESMC 7 -CMSEL1.NMCS 6 -CMSEL1.CMSEL23 3 -CMSEL1.CMSEL22 2 -CMSEL1.CMSEL21 1 -CMSEL1.CMSEL20 0 -CCIR 0x00E5 Capture/compare interrupt request flag reg. -CCIR.CT1FP 7 -CCIR.CT1FC 6 -CCIR.CC2F 5 -CCIR.CC2R 4 -CCIR.CC1F 3 -CCIR.CC1R 2 -CCIR.CC0F 1 -CCIR.CC0R 0 -CT1OFL 0x00E6 Compare timer 1 offset register, low byte -CT1OFL.CT1OFL7 7 -CT1OFL.CT1OFL6 6 -CT1OFL.CT1OFL5 5 -CT1OFL.CT1OFL4 4 -CT1OFL.CT1OFL3 3 -CT1OFL.CT1OFL2 2 -CT1OFL.CT1OFL1 1 -CT1OFL.CT1OFL0 0 -CT1OFH 0x00E7 Compare timer 1 offset register, high byte -CT1OFH.CT1OFH7 7 -CT1OFH.CT1OFH6 6 -CT1OFH.CT1OFH5 5 -CT1OFH.CT1OFH4 4 -CT1OFH.CT1OFH3 3 -CT1OFH.CT1OFH2 2 -CT1OFH.CT1OFH1 1 -CT1OFH.CT1OFH0 0 -RESERVED00E8 0x00E8 RESERVED -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -CT2CON 0x00F1 Compare timer 2 control register -CT2CON.CT2P 7 -CT2CON.ECT2O 6 -CT2CON.STE2 5 -CT2CON.CT2RES 4 -CT2CON.CT2R 3 -CT2CON.CLK2 2 -CT2CON.CLK1 1 -CT2CON.CLK0 0 -CCL0 0x00F2 Capture/compare register 0, low byte -CCL0.CCL07 7 -CCL0.CCL06 6 -CCL0.CCL05 5 -CCL0.CCL04 4 -CCL0.CCL03 3 -CCL0.CCL02 2 -CCL0.CCL01 1 -CCL0.CCL00 0 -CCH0 0x00F3 Capture/compare register 0, high byte -CCH0.CCH07 7 -CCH0.CCH06 6 -CCH0.CCH05 5 -CCH0.CCH04 4 -CCH0.CCH03 3 -CCH0.CCH02 2 -CCH0.CCH01 1 -CCH0.CCH00 0 -CCL1 0x00F4 Capture/compare register 1, low byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00F5 Capture/compare register 1, high byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00F6 Capture/compare register 2, low byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00F7 Capture/compare register 2, high byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -P5 0x00F8 Port 5 -P5.P57 7 -P5.P56 6 -P5.P55 5 -P5.P54 4 -P5.P53 3 -P5.P52 2 -P5.P51 1 -P5.P50 0 -COTRAP 0x00F9 Compare output in trap state register -COTRAP.BCTSEL 7 -COTRAP.PDTEN 6 -COTRAP.COUT2T 5 -COTRAP.CC2T 4 -COTRAP.COUT1T 3 -COTRAP.CC1T 2 -COTRAP.COUT0T 1 -COTRAP.CC0T 0 -RESERVED00EF 0x00FA RESERVED -EINT 0x00FB External Interrupt Control Register -EINT.IEX9 5 -EINT.I9FR 4 -EINT.IEX8 3 -EINT.I8FR 2 -EINT.IEX7 1 -EINT.I7FR 0 -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -TRCON 0x00FF Trap enable control register -TRCON.TRPEN 7 -TRCON.TRF 6 -TRCON.TREN5 5 -TRCON.TREN4 4 -TRCON.TREN3 3 -TRCON.TREN2 2 -TRCON.TREN1 1 -TRCON.TREN0 0 - - -.C509 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8022&parent_oid=8090 -; C509-L.pdf - - -; up to 64 Kbyte of external program memory -; up to 64 Kbyte of external data memory -; 512 byte of internal Boot ROM (program memory) -; 256 bytes of internal data memory -; 3 Kbyte of external XRAM data memory -; a 128 byte special function register area - - -; MEMORY MAP -area CODE code 0x0000:0xF400 -area DATA XRAM 0xF400:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External Interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External Interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI0_TI0 0x0023 Serial Channel 0 -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry IEX2 0x004B External Interrupt 2 -entry IEX3 0x0053 External Interrupt 3 -entry IEX4 0x005B External Interrupt 4 -entry IEX5 0x0063 External Interrupt 5 -entry IEX6 0x006B External Interrupt 6 -entry RI1_TI1 0x0083 Serial Channel 1 -entry ICMP0_ICMP7 0x0093 Compare Match Interupt of Compare Registers assigned to Timer 2 CM0-CM7 -entry CTF 0x009B Compare Timer Overflow -entry ICS 0x00A3 Compare Match Interupt of Compare Register COMSET -entry ICR 0x00AB Compare Match Interupt of Compare Register COMCLR -entry ICC10_ICC17 0x00D3 Compare / Capture Event interrupt -entry CT1F 0x00DB Compare Timer 1 Overflow - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 (PDIR=0) -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -; DIR0 0x0080 Direction Register Port 0 (PDIR=1) -; DIR0.DIR07 7 -; DIR0.DIR06 6 -; DIR0.DIR05 5 -; DIR0.DIR04 4 -; DIR0.DIR03 3 -; DIR0.DIR02 2 -; DIR0.DIR01 1 -; DIR0.DIR00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -WDTL 0x0084 Watchdog Timer Register, Low Byte -WDTL.WDTL7 7 -WDTL.WDTL6 6 -WDTL.WDTL5 5 -WDTL.WDTL4 4 -WDTL.WDTL3 3 -WDTL.WDTL2 2 -WDTL.WDTL1 1 -WDTL.WDTL0 0 -WDTH 0x0085 Watchdog Timer Register, High Byte -WDTH.WDTH7 7 -WDTH.WDTH6 6 -WDTH.WDTH5 5 -WDTH.WDTH4 4 -WDTH.WDTH3 3 -WDTH.WDTH2 2 -WDTH.WDTH1 1 -WDTH.WDTH0 0 -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 (PDIR=0) -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.INT2 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -; DIR1 0x0090 Direction Register Port 1 (PDIR=1) -; DIR1.DIR17 7 -; DIR1.DIR16 6 -; DIR1.DIR15 5 -; DIR1.DIR14 4 -; DIR1.DIR13 3 -; DIR1.DIR12 2 -; DIR1.DIR11 1 -; DIR1.DIR10 0 -XPAGE 0x0091 Page Address Register for XRAM -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -S0CON 0x0098 Serial Channel 0 Control Register -S0CON.SM0 7 -S0CON.SM1 6 -S0CON.SM20 5 -S0CON.REN0 4 -S0CON.TB80 3 -S0CON.RB80 2 -S0CON.TI0 1 -S0CON.RI0 0 -S0BUF 0x0099 Serial Channel 0 Buffer Register -S0BUF.S0BUF7 7 -S0BUF.S0BUF6 6 -S0BUF.S0BUF5 5 -S0BUF.S0BUF4 4 -S0BUF.S0BUF3 3 -S0BUF.S0BUF2 2 -S0BUF.S0BUF1 1 -S0BUF.S0BUF0 0 -IEN2 0x009A Interrupt Enable Register 2 -IEN2.ECR 5 -IEN2.ECS 4 -IEN2.ECT 3 -IEN2.ECMP 2 -IEN2.ES1 0 -S1CON 0x009B Serial Channel 1 Control Register -S1CON.SM 7 -S1CON.S1P 6 -S1CON.SM21 5 -S1CON.REN1 4 -S1CON.TB81 3 -S1CON.RB81 2 -S1CON.TI1 1 -S1CON.RI1 0 -S1BUF 0x009C Serial Channel 1 Buffer Register -S1BUF.S1BUF7 7 -S1BUF.S1BUF6 6 -S1BUF.S1BUF5 5 -S1BUF.S1BUF4 4 -S1BUF.S1BUF3 3 -S1BUF.S1BUF2 2 -S1BUF.S1BUF1 1 -S1BUF.S1BUF0 0 -S1RELL 0x009D Serial Channel 1 Reload Reg., Low Byte -S1RELL.S1RELL7 7 -S1RELL.S1RELL6 6 -S1RELL.S1RELL5 5 -S1RELL.S1RELL4 4 -S1RELL.S1RELL3 3 -S1RELL.S1RELL2 2 -S1RELL.S1RELL1 1 -S1RELL.S1RELL0 0 -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 (PDIR=0) -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -; DIR2 0x00A0 Direction Register Port 2 (PDIR=1) -; DIR2.DIR27 7 -; DIR2.DIR26 6 -; DIR2.DIR25 5 -; DIR2.DIR24 4 -; DIR2.DIR23 3 -; DIR2.DIR22 2 -; DIR2.DIR21 1 -; DIR2.DIR20 0 -COMSETL 0x00A1 Compare Set Register, Low Byte -COMSETL.COMSETL7 7 -COMSETL.COMSETL6 6 -COMSETL.COMSETL5 5 -COMSETL.COMSETL4 4 -COMSETL.COMSETL3 3 -COMSETL.COMSETL2 2 -COMSETL.COMSETL1 1 -COMSETL.COMSETL0 0 -COMSETH 0x00A2 Compare Set Register, High Byte -COMSETH.COMSETH7 7 -COMSETH.COMSETH6 6 -COMSETH.COMSETH5 5 -COMSETH.COMSETH4 4 -COMSETH.COMSETH3 3 -COMSETH.COMSETH2 2 -COMSETH.COMSETH1 1 -COMSETH.COMSETH0 0 -COMCLRL 0x00A3 Compare Clear Register, Low Byte -COMCLRL.COMCLRL7 7 -COMCLRL.COMCLRL6 6 -COMCLRL.COMCLRL5 5 -COMCLRL.COMCLRL4 4 -COMCLRL.COMCLRL3 3 -COMCLRL.COMCLRL2 2 -COMCLRL.COMCLRL1 1 -COMCLRL.COMCLRL0 0 -COMCLRH 0x00A4 Compare Clear Register, High Byte -COMCLRH.COMCLRH7 7 -COMCLRH.COMCLRH6 6 -COMCLRH.COMCLRH5 5 -COMCLRH.COMCLRH4 4 -COMCLRH.COMCLRH3 3 -COMCLRH.COMCLRH2 2 -COMCLRH.COMCLRH1 1 -COMCLRH.COMCLRH0 0 -SETMSK 0x00A5 Compare Set Mask Register -SETMSK.SETMSK7 7 -SETMSK.SETMSK6 6 -SETMSK.SETMSK5 5 -SETMSK.SETMSK4 4 -SETMSK.SETMSK3 3 -SETMSK.SETMSK2 2 -SETMSK.SETMSK1 1 -SETMSK.SETMSK0 0 -CLRMSK 0x00A6 Compare Clear Mask Register -CLRMSK.CLRMSK7 7 -CLRMSK.CLRMSK6 6 -CLRMSK.CLRMSK5 5 -CLRMSK.CLRMSK4 4 -CLRMSK.CLRMSK3 3 -CLRMSK.CLRMSK2 2 -CLRMSK.CLRMSK1 1 -CLRMSK.CLRMSK0 0 -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EAL 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES0 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -S0RELL 0x00AA Serial Channel 0 Reload Reg., Low Byte -S0RELL.S0RELL7 7 -S0RELL.S0RELL6 6 -S0RELL.S0RELL5 5 -S0RELL.S0RELL4 4 -S0RELL.S0RELL3 3 -S0RELL.S0RELL2 2 -S0RELL.S0RELL1 1 -S0RELL.S0RELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 (PDIR=0) -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T1 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD0 1 -P3.RxD0 0 -; DIR3 0x00B0 Direction Register Port 3 (PDIR=1) -; DIR3.DIR37 7 -; DIR3.DIR36 6 -; DIR3.DIR35 5 -; DIR3.DIR34 4 -; DIR3.DIR33 3 -; DIR3.DIR32 2 -; DIR3.DIR31 1 -; DIR3.DIR30 0 -SYSCON 0x00B1 System Control Register -SYSCON.CLKP 7 -SYSCON.PMOD 6 -SYSCON.RMAP 4 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -SYSCON1 0x00B2 System Control Register 1 -SYSCON1.ESWC 7 -SYSCON1.SWC 6 -SYSCON1.EA1 4 -SYSCON1.EA0 3 -SYSCON1.PRGEN1 2 -SYSCON1.PRGEN0 1 -SYSCON1.SWAP 0 -RESERVED00B3 0x00B3 RESERVED -PRSC 0x00B4 Prescaler Control Register -PRSC.WDTP 7 -PRSC.S0P 6 -PRSC.T2P1 5 -PRSC.T2P0 4 -PRSC.T1P1 3 -PRSC.T1P0 2 -PRSC.T0P1 1 -PRSC.T0P0 0 -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.EX2 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.PDIR 7 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -S0RELH 0x00BA Serial Channel 0 Reload Reg., High Byte -S0RELH.S0RELH1 1 -S0RELH.S0RELH0 0 -S1RELH 0x00BB Serial Channel 1 Reload Reg., High Byte -S1RELH.S1RELH1 1 -S1RELH.S1RELH0 0 -CT1CON 0x00BC Compare Timer 1 Control Register -CT1CON.CT1P 6 -CT1CON.CT1F 3 -CT1CON.CLK12 2 -CT1CON.CLK11 1 -CT1CON.CLK10 0 -RESERVED00BD 0x00BD RESERVED -IEN3 0x00BE Interrupt Enable Register 3 -IEN3.ECT1 3 -IEN3.ECC1 2 -IRCON2 0x00BF Interrupt Request Control Register 2 (PDIR=0) -IRCON2.ICC17 7 -IRCON2.ICC16 6 -IRCON2.ICC15 5 -IRCON2.ICC14 4 -IRCON2.ICC13 3 -IRCON2.ICC12 2 -IRCON2.ICC11 1 -IRCON2.ICC10 0 -; EICC1 0x00BF Interrupt Request Enable Register for CT1 (PDIR=1) -; EICC1.EICC17 7 -; EICC1.EICC16 6 -; EICC1.EICC15 5 -; EICC1.EICC14 4 -; EICC1.EICC13 3 -; EICC1.EICC12 2 -; EICC1.EICC11 1 -; EICC1.EICC10 0 -IRCON0 0x00C0 Interrupt Request Control Register 0 -IRCON0.EXF2 7 -IRCON0.TF2 6 -IRCON0.IEX6 5 -IRCON0.IEX5 4 -IRCON0.IEX4 3 -IRCON0.IEX3 2 -IRCON0.IEX2 1 -IRCON0.IADC 0 -CCEN 0x00C1 Compare/Capture Enable Register -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Compare/Capture Register 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Compare/Capture Register 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Compare/Capture Register 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Compare/Capture Register 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Compare/Capture Register 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Compare/Capture Register 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.I2FR 5 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -CC4EN 0x00C9 Compare/Capture 4 Enable Register -CC4EN.COCOEN1 7 -CC4EN.COCON2 6 -CC4EN.COCON1 5 -CC4EN.COCON0 4 -CC4EN.COCOEN0 3 -CC4EN.COCAH4 2 -CC4EN.COCAL4 1 -CC4EN.COM0 0 -CRCL 0x00CA Comp./Rel./Capt. Reg. Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Comp./Rel./Capt. Reg. High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -CCL4 0x00CE Compare/Capture Register 4, Low Byte -CCL4.CCL47 7 -CCL4.CCL46 6 -CCL4.CCL45 5 -CCL4.CCL44 4 -CCL4.CCL43 3 -CCL4.CCL42 2 -CCL4.CCL41 1 -CCL4.CCL40 0 -CCH4 0x00CF Compare/Capture Register 4, High Byte -CCH4.CCH47 7 -CCH4.CCH46 6 -CCH4.CCH45 5 -CCH4.CCH44 4 -CCH4.CCH43 3 -CCH4.CCH42 2 -CCH4.CCH41 1 -CCH4.CCH40 0 -PSW 0x00D0 Program Status Word -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -IRCON1 0x00D1 Interrupt Request Control Register 1 -IRCON1.ICMP7 7 -IRCON1.ICMP6 6 -IRCON1.ICMP5 5 -IRCON1.ICMP4 4 -IRCON1.ICMP3 3 -IRCON1.ICMP2 2 -IRCON1.ICMP1 1 -IRCON1.ICMP0 0 -CML0 0x00D2 Compare Register 0, Low Byte (RMAP=0) -CML0.CML07 7 -CML0.CML06 6 -CML0.CML05 5 -CML0.CML04 4 -CML0.CML03 3 -CML0.CML02 2 -CML0.CML01 1 -CML0.CML00 0 -; CC1L0 0x00D2 Compare/Capture 1 Register 0, Low Byte (RMAP=1) -; CC1L0.CC1L07 7 -; CC1L0.CC1L06 6 -; CC1L0.CC1L05 5 -; CC1L0.CC1L04 4 -; CC1L0.CC1L03 3 -; CC1L0.CC1L02 2 -; CC1L0.CC1L01 1 -; CC1L0.CC1L00 0 -CMH0 0x00D3 Compare Register 0, High Byte (RMAP=0) -CMH0.CMH07 7 -CMH0.CMH06 6 -CMH0.CMH05 5 -CMH0.CMH04 4 -CMH0.CMH03 3 -CMH0.CMH02 2 -CMH0.CMH01 1 -CMH0.CMH00 0 -; CC1H0 0x00D3 Compare/Capture 1 Register 0, High Byte (RMAP=1) -; CC1H0.CC1H07 7 -; CC1H0.CC1H06 6 -; CC1H0.CC1H05 5 -; CC1H0.CC1H04 4 -; CC1H0.CC1H03 3 -; CC1H0.CC1H02 2 -; CC1H0.CC1H01 1 -; CC1H0.CC1H00 0 -CML1 0x00D4 Compare Register 1, Low Byte (RMAP=0) -CML1.CML17 7 -CML1.CML16 6 -CML1.CML15 5 -CML1.CML14 4 -CML1.CML13 3 -CML1.CML12 2 -CML1.CML11 1 -CML1.CML10 0 -; CC1L1 0x00D4 Compare/Capture 1 Register 1, Low Byte (RMAP=1) -; CC1L1.CC1L17 7 -; CC1L1.CC1L16 6 -; CC1L1.CC1L15 5 -; CC1L1.CC1L14 4 -; CC1L1.CC1L13 3 -; CC1L1.CC1L12 2 -; CC1L1.CC1L11 1 -; CC1L1.CC1L10 0 -CMH1 0x00D5 Compare Register 1, High Byte (RMAP=0) -CMH1.CMH17 7 -CMH1.CMH16 6 -CMH1.CMH15 5 -CMH1.CMH14 4 -CMH1.CMH13 3 -CMH1.CMH12 2 -CMH1.CMH11 1 -CMH1.CMH10 0 -; CC1H1 0x00D5 Compare/Capture 1 Register 1, High Byte (RMAP=1) -; CC1H1.CC1H17 7 -; CC1H1.CC1H16 6 -; CC1H1.CC1H15 5 -; CC1H1.CC1H14 4 -; CC1H1.CC1H13 3 -; CC1H1.CC1H12 2 -; CC1H1.CC1H11 1 -; CC1H1.CC1H10 0 -CML2 0x00D6 Compare Register 2, Low Byte (RMAP=0) -CML2.CML27 7 -CML2.CML26 6 -CML2.CML25 5 -CML2.CML24 4 -CML2.CML23 3 -CML2.CML22 2 -CML2.CML21 1 -CML2.CML20 0 -; CC1L2 0x00D6 Compare/Capture 1 Register 2, Low Byte (RMAP=1) -; CC1L2.CC1L27 7 -; CC1L2.CC1L26 6 -; CC1L2.CC1L25 5 -; CC1L2.CC1L24 4 -; CC1L2.CC1L23 3 -; CC1L2.CC1L22 2 -; CC1L2.CC1L21 1 -; CC1L2.CC1L20 0 -CMH2 0x00D7 Compare Register 2, High Byte (RMAP=0) -CMH2.CMH27 7 -CMH2.CMH26 6 -CMH2.CMH25 5 -CMH2.CMH24 4 -CMH2.CMH23 3 -CMH2.CMH22 2 -CMH2.CMH21 1 -CMH2.CMH20 0 -; CC1H2 0x00D7 Compare/Capture 1 Register 2, High Byte (RMAP=1) -; CC1H2.CC1H27 7 -; CC1H2.CC1H26 6 -; CC1H2.CC1H25 5 -; CC1H2.CC1H24 4 -; CC1H2.CC1H23 3 -; CC1H2.CC1H22 2 -; CC1H2.CC1H21 1 -; CC1H2.CC1H20 0 -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.ADEX 5 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register, High Byte -ADDATH.ADDATH7 7 -ADDATH.ADDATH6 6 -ADDATH.ADDATH5 5 -ADDATH.ADDATH4 4 -ADDATH.ADDATH3 3 -ADDATH.ADDATH2 2 -ADDATH.ADDATH1 1 -ADDATH.ADDATH0 0 -ADDATL 0x00DA A/D Converter Data Register, Low Byte -ADDATL.ADDATL7 7 -ADDATL.ADDATL6 6 -P7 0x00DB Port 7, Analog/Digital Input -P7.P77 7 -P7.P76 6 -P7.P75 5 -P7.P74 4 -P7.P73 3 -P7.P72 2 -P7.P71 1 -P7.P70 0 -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL1 7 -ADCON1.ADCL0 6 -ADCON1.ADST1 5 -ADCON1.ADST0 4 -ADCON1.MX3 3 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -P8 0x00DD Port 8, Analog/Digital Input -P8.P86 6 -P8.P85 5 -P8.P84 4 -P8.P83 3 -P8.P82 2 -P8.P81 1 -P8.P80 0 -CTRELL 0x00DE Compare Timer Rel. Reg., Low Byte (RMAP=0) -CTRELL.CTRELL7 7 -CTRELL.CTRELL6 6 -CTRELL.CTRELL5 5 -CTRELL.CTRELL4 4 -CTRELL.CTRELL3 3 -CTRELL.CTRELL2 2 -CTRELL.CTRELL1 1 -CTRELL.CTRELL0 0 -; CT1RELL 0x00DE Compare Timer 1 Rel. Reg., Low Byte (RMAP=1) -; CT1RELL.CT1RELL7 7 -; CT1RELL.CT1RELL6 6 -; CT1RELL.CT1RELL5 5 -; CT1RELL.CT1RELL4 4 -; CT1RELL.CT1RELL3 3 -; CT1RELL.CT1RELL2 2 -; CT1RELL.CT1RELL1 1 -; CT1RELL.CT1RELL0 0 -CTRELH 0x00DF Compare Timer Rel. Reg., High Byte (RMAP=0) -CTRELH.CTRELH7 7 -CTRELH.CTRELH6 6 -CTRELH.CTRELH5 5 -CTRELH.CTRELH4 4 -CTRELH.CTRELH3 3 -CTRELH.CTRELH2 2 -CTRELH.CTRELH1 1 -CTRELH.CTRELH0 0 -; CT1RELH 0x00DF Compare Timer 1 Rel. Reg., High Byte (RMAP=1) -; CT1RELH.CT1RELH7 7 -; CT1RELH.CT1RELH6 6 -; CT1RELH.CT1RELH5 5 -; CT1RELH.CT1RELH4 4 -; CT1RELH.CT1RELH3 3 -; CT1RELH.CT1RELH2 2 -; CT1RELH.CT1RELH1 1 -; CT1RELH.CT1RELH0 0 -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -CTCON 0x00E1 Compare Timer Control Register -CTCON.T2PS1 7 -CTCON.CTP 6 -CTCON.ICR 5 -CTCON.ICS 4 -CTCON.CTF 3 -CTCON.CLK2 2 -CTCON.CLK1 1 -CTCON.CLK0 0 -CML3 0x00E2 Compare Register 3, Low Byte (RMAP=0) -CML3.CML37 7 -CML3.CML36 6 -CML3.CML35 5 -CML3.CML34 4 -CML3.CML33 3 -CML3.CML32 2 -CML3.CML31 1 -CML3.CML30 0 -; CC1L3 0x00E2 Compare/Capture 1 Register 3, Low Byte (RMAP=1) -; CC1L3.CC1L37 7 -; CC1L3.CC1L36 6 -; CC1L3.CC1L35 5 -; CC1L3.CC1L34 4 -; CC1L3.CC1L33 3 -; CC1L3.CC1L32 2 -; CC1L3.CC1L31 1 -; CC1L3.CC1L30 0 -CMH3 0x00E3 Compare Register 3, High Byte (RMAP=0) -CMH3.CMH37 7 -CMH3.CMH36 6 -CMH3.CMH35 5 -CMH3.CMH34 4 -CMH3.CMH33 3 -CMH3.CMH32 2 -CMH3.CMH31 1 -CMH3.CMH30 0 -; CC1H3 0x00E3 Compare/Capture 1 Register 3, High Byte (RMAP=1) -; CC1H3.CC1H37 7 -; CC1H3.CC1H36 6 -; CC1H3.CC1H35 5 -; CC1H3.CC1H34 4 -; CC1H3.CC1H33 3 -; CC1H3.CC1H32 2 -; CC1H3.CC1H31 1 -; CC1H3.CC1H30 0 -CML4 0x00E4 Compare Register 4, Low Byte (RMAP=0) -CML4.CML47 7 -CML4.CML46 6 -CML4.CML45 5 -CML4.CML44 4 -CML4.CML43 3 -CML4.CML42 2 -CML4.CML41 1 -CML4.CML40 0 -; CC1L4 0x00E4 Compare/Capture 1 Register 4, Low Byte (RMAP=1) -; CC1L4.CC1L47 7 -; CC1L4.CC1L46 6 -; CC1L4.CC1L45 5 -; CC1L4.CC1L44 4 -; CC1L4.CC1L43 3 -; CC1L4.CC1L42 2 -; CC1L4.CC1L41 1 -; CC1L4.CC1L40 0 -CMH4 0x00E5 Compare Register 4, High Byte (RMAP=0) -CMH4.CMH47 7 -CMH4.CMH46 6 -CMH4.CMH45 5 -CMH4.CMH44 4 -CMH4.CMH43 3 -CMH4.CMH42 2 -CMH4.CMH41 1 -CMH4.CMH40 0 -; CC1H4 0x00E5 Compare/Capture 1 Register 4, High Byte (RMAP=1) -; CC1H4.CC1H47 7 -; CC1H4.CC1H46 6 -; CC1H4.CC1H45 5 -; CC1H4.CC1H44 4 -; CC1H4.CC1H43 3 -; CC1H4.CC1H42 2 -; CC1H4.CC1H41 1 -; CC1H4.CC1H40 0 -CML5 0x00E6 Compare Register 5, Low Byte (RMAP=0) -CML5.CML57 7 -CML5.CML56 6 -CML5.CML55 5 -CML5.CML54 4 -CML5.CML53 3 -CML5.CML52 2 -CML5.CML51 1 -CML5.CML50 0 -; CC1L5 0x00E6 Compare/Capture 1 Register 5, Low Byte (RMAP=1) -; CC1L5.CC1L57 7 -; CC1L5.CC1L56 6 -; CC1L5.CC1L55 5 -; CC1L5.CC1L54 4 -; CC1L5.CC1L53 3 -; CC1L5.CC1L52 2 -; CC1L5.CC1L51 1 -; CC1L5.CC1L50 0 -CMH5 0x00E7 Compare Register 5, High Byte (RMAP=0) -CMH5.CMH57 7 -CMH5.CMH56 6 -CMH5.CMH55 5 -CMH5.CMH54 4 -CMH5.CMH53 3 -CMH5.CMH52 2 -CMH5.CMH51 1 -CMH5.CMH50 0 -; CC1H5 0x00E7 Compare/Capture 1 Register 5, High Byte (RMAP=1) -; CC1H5.CC1H57 7 -; CC1H5.CC1H56 6 -; CC1H5.CC1H55 5 -; CC1H5.CC1H54 4 -; CC1H5.CC1H53 3 -; CC1H5.CC1H52 2 -; CC1H5.CC1H51 1 -; CC1H5.CC1H50 0 -P4 0x00E8 Port 4 (PDIR=0) -P4.CM7 7 -P4.CM6 6 -P4.CM5 5 -P4.CM4 4 -P4.CM3 3 -P4.CM2 2 -P4.CM1 1 -P4.CM0 0 -; DIR4 0x00E8 Direction Register Port 4 (PDIR=1) -; DIR4.DIR47 7 -; DIR4.DIR46 6 -; DIR4.DIR45 5 -; DIR4.DIR44 4 -; DIR4.DIR43 3 -; DIR4.DIR42 2 -; DIR4.DIR41 1 -; DIR4.DIR40 0 -MD0 0x00E9 Multiplication/Division Register 0 -MD0.MD07 7 -MD0.MD06 6 -MD0.MD05 5 -MD0.MD04 4 -MD0.MD03 3 -MD0.MD02 2 -MD0.MD01 1 -MD0.MD00 0 -MD1 0x00EA Multiplication/Division Register 1 -MD1.MD17 7 -MD1.MD16 6 -MD1.MD15 5 -MD1.MD14 4 -MD1.MD13 3 -MD1.MD12 2 -MD1.MD11 1 -MD1.MD10 0 -MD2 0x00EB Multiplication/Division Register 2 -MD2.MD27 7 -MD2.MD26 6 -MD2.MD25 5 -MD2.MD24 4 -MD2.MD23 3 -MD2.MD22 2 -MD2.MD21 1 -MD2.MD20 0 -MD3 0x00EC Multiplication/Division Register 3 -MD3.MD37 7 -MD3.MD36 6 -MD3.MD35 5 -MD3.MD34 4 -MD3.MD33 3 -MD3.MD32 2 -MD3.MD31 1 -MD3.MD30 0 -MD4 0x00ED Multiplication/Division Register 4 -MD4.MD47 7 -MD4.MD46 6 -MD4.MD45 5 -MD4.MD44 4 -MD4.MD43 3 -MD4.MD42 2 -MD4.MD41 1 -MD4.MD40 0 -MD5 0x00EE Multiplication/Division Register 5 -MD5.MD57 7 -MD5.MD56 6 -MD5.MD55 5 -MD5.MD54 4 -MD5.MD53 3 -MD5.MD52 2 -MD5.MD51 1 -MD5.MD50 0 -ARCON 0x00EF Arithmetic Control Register -ARCON.MDEF 7 -ARCON.MDOV 6 -ARCON.SLR 5 -ARCON.SC4 4 -ARCON.SC3 3 -ARCON.SC2 2 -ARCON.SC1 1 -ARCON.SC0 0 -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -CML6 0x00F2 Compare Register 6, Low Byte (RMAP=0) -CML6.CML67 7 -CML6.CML66 6 -CML6.CML65 5 -CML6.CML64 4 -CML6.CML63 3 -CML6.CML62 2 -CML6.CML61 1 -CML6.CML60 0 -; CC1L6 0x00F2 Compare/Capture 1 Register 6, Low Byte (RMAP=1) -; CC1L6.CC1L67 7 -; CC1L6.CC1L66 6 -; CC1L6.CC1L65 5 -; CC1L6.CC1L64 4 -; CC1L6.CC1L63 3 -; CC1L6.CC1L62 2 -; CC1L6.CC1L61 1 -; CC1L6.CC1L60 0 -CMH6 0x00F3 Compare Register 6, High Byte (RMAP=0) -CMH6.CMH67 7 -CMH6.CMH66 6 -CMH6.CMH65 5 -CMH6.CMH64 4 -CMH6.CMH63 3 -CMH6.CMH62 2 -CMH6.CMH61 1 -CMH6.CMH60 0 -; CC1H6 0x00F3 Compare/Capture 1 Register 6, High Byte (RMAP=1) -; CC1H6.CC1H67 7 -; CC1H6.CC1H66 6 -; CC1H6.CC1H65 5 -; CC1H6.CC1H64 4 -; CC1H6.CC1H63 3 -; CC1H6.CC1H62 2 -; CC1H6.CC1H61 1 -; CC1H6.CC1H60 0 -CML7 0x00F4 Compare Register 7, Low Byte (RMAP=0) -CML7.CML77 7 -CML7.CML76 6 -CML7.CML75 5 -CML7.CML74 4 -CML7.CML73 3 -CML7.CML72 2 -CML7.CML71 1 -CML7.CML70 0 -; CC1L7 0x00F4 Compare/Capture 1 Register 7, Low Byte (RMAP=1) -; CC1L7.CC1L77 7 -; CC1L7.CC1L76 6 -; CC1L7.CC1L75 5 -; CC1L7.CC1L74 4 -; CC1L7.CC1L73 3 -; CC1L7.CC1L72 2 -; CC1L7.CC1L71 1 -; CC1L7.CC1L70 0 -CMH7 0x00F5 Compare Register 7, High Byte (RMAP=0) -CMH7.CMH77 7 -CMH7.CMH76 6 -CMH7.CMH75 5 -CMH7.CMH74 4 -CMH7.CMH73 3 -CMH7.CMH72 2 -CMH7.CMH71 1 -CMH7.CMH70 0 -; CC1H7 0x00F5 Compare/Capture 1 Register 7, High Byte (RMAP=1) -; CC1H7.CC1H77 7 -; CC1H7.CC1H76 6 -; CC1H7.CC1H75 5 -; CC1H7.CC1H74 4 -; CC1H7.CC1H73 3 -; CC1H7.CC1H72 2 -; CC1H7.CC1H71 1 -; CC1H7.CC1H70 0 -CMEN 0x00F6 Compare Enable Register (RMAP=0) -CMEN.CMEN7 7 -CMEN.CMEN6 6 -CMEN.CMEN5 5 -CMEN.CMEN4 4 -CMEN.CMEN3 3 -CMEN.CMEN2 2 -CMEN.CMEN1 1 -CMEN.CMEN0 0 -; CC1EN 0x00F6 Compare/Capture Enable Register (RMAP=1) -; CC1EN.CC1EN7 7 -; CC1EN.CC1EN6 6 -; CC1EN.CC1EN5 5 -; CC1EN.CC1EN4 4 -; CC1EN.CC1EN3 3 -; CC1EN.CC1EN2 2 -; CC1EN.CC1EN1 1 -; CC1EN.CC1EN0 0 -CMSEL 0x00F7 Compare Input Select (RMAP=0) -CMSEL.CMSEL7 7 -CMSEL.CMSEL6 6 -CMSEL.CMSEL5 5 -CMSEL.CMSEL4 4 -CMSEL.CMSEL3 3 -CMSEL.CMSEL2 2 -CMSEL.CMSEL1 1 -CMSEL.CMSEL0 0 -; CAFR 0x00F7 Capture 1, Falling/Rising Edge Register (RMAP=1) -; CAFR.CAFR7 7 -; CAFR.CAFR6 6 -; CAFR.CAFR5 5 -; CAFR.CAFR4 4 -; CAFR.CAFR3 3 -; CAFR.CAFR2 2 -; CAFR.CAFR1 1 -; CAFR.CAFR0 0 -P5 0x00F8 Port 5 (PDIR=0) -P5.CCM7 7 -P5.CCM6 6 -P5.CCM5 5 -P5.CCM4 4 -P5.CCM3 3 -P5.CCM2 2 -P5.CCM1 1 -P5.CCM0 0 -; DIR5 0x00F8 Direction Register Port 5 (PDIR=1) -; DIR5.DIR57 7 -; DIR5.DIR56 6 -; DIR5.DIR55 5 -; DIR5.DIR54 4 -; DIR5.DIR53 3 -; DIR5.DIR52 2 -; DIR5.DIR51 1 -; DIR5.DIR50 0 -P9 0x00F9 Port 9 (PDIR=0) -P9.CC17 7 -P9.CC16 6 -P9.CC15 5 -P9.CC14 4 -P9.CC13 3 -P9.CC12 2 -P9.CC11 1 -P9.CC10 0 -; DIR9 0x00F9 Direction Register Port 9 (PDIR=1) -; DIR9.DIR97 7 -; DIR9.DIR96 6 -; DIR9.DIR95 5 -; DIR9.DIR94 4 -; DIR9.DIR93 3 -; DIR9.DIR92 2 -; DIR9.DIR91 1 -; DIR9.DIR90 0 -P6 0x00FA Port 6 (PDIR=0) -P6.P67 7 -P6.P66 6 -P6.P65 5 -P6.P64 4 -P6.P63 3 -P6.TxD1 2 -P6.RxD1 1 -P6.ADST 0 -; DIR6 0x00FA Direction Register Port 6 (PDIR=1) -; DIR6.DIR67 7 -; DIR6.DIR66 6 -; DIR6.DIR65 5 -; DIR6.DIR64 4 -; DIR6.DIR63 3 -; DIR6.DIR62 2 -; DIR6.DIR61 1 -; DIR6.DIR60 0 -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C513AO -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8025&parent_oid=16713 -; SAF-C513AO-LN.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xFF00 -area DATA XRAM 0xFF00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External Interrupt 0 -entry TF0 0x000B Timer 0 interrupt -entry IE1 0x0013 External Interrupt 1 -entry TF1 0x001B Timer 1 interrupt -entry RI_TI 0x0023 USART serial port interrupt -entry TF2_EXF2 0x002B Timer 2 interrupt -entry WCOL_TC 0x0043 Synchronous Serial Channel interrupt (SSC) -entry WA_PDM 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.SLS 5 -P1.STO 4 -P1.SRI 3 -P1.SCLK 2 -P1.T2EX 1 -P1.T2 0 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IE 0x00A8 Interrupt Enable Register -IE.EA 7 -IE.ESSC 6 -IE.ET2 5 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 -RESERVED00A9 0x00A9 RESERVED -RESERVED00AA 0x00AA RESERVED -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.XMAP 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IP 0x00B8 Interrupt Priority Register -IP.PSSC 6 -IP.PT2 5 -IP.PS 4 -IP.PT1 3 -IP.PX1 2 -IP.PT0 1 -IP.PX0 0 -RESERVED00B9 0x00B9 RESERVED -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -WDCON 0x00C0 Watchdog Timer Control Register -WDCON.OWDS 3 -WDCON.WDTS 2 -WDCON.WDT 1 -WDCON.SWDT 0 -RESERVED00C1 0x00C1 RESERVED -RESERVED00C2 0x00C2 RESERVED -RESERVED00C3 0x00C3 RESERVED -RESERVED00C4 0x00C4 RESERVED -RESERVED00C5 0x00C5 RESERVED -RESERVED00C6 0x00C6 RESERVED -RESERVED00C7 0x00C7 RESERVED -T2CON 0x00C8 Timer 2 Control Register -T2CON.TF2 7 -T2CON.EXF2 6 -T2CON.RCLK 5 -T2CON.TCLK 4 -T2CON.EXEN2 3 -T2CON.TR2 2 -T2CON.C_T2 1 -T2CON.CP_RL2 0 -T2MOD 0x00C9 Timer 2 Mode Register -T2MOD.DCEN 0 -RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte -RC2L.RC2L7 7 -RC2L.RC2L6 6 -RC2L.RC2L5 5 -RC2L.RC2L4 4 -RC2L.RC2L3 3 -RC2L.RC2L2 2 -RC2L.RC2L1 1 -RC2L.RC2L0 0 -RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte -RC2H.RC2H7 7 -RC2H.RC2H6 6 -RC2H.RC2H5 5 -RC2H.RC2H4 4 -RC2H.RC2H3 3 -RC2H.RC2H2 2 -RC2H.RC2H1 1 -RC2H.RC2H0 0 -TL2 0x00CC Timer 2 Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2 High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -RESERVED00D8 0x00D8 RESERVED -RESERVED00D9 0x00D9 RESERVED -RESERVED00DA 0x00DA RESERVED -RESERVED00DB 0x00DB RESERVED -RESERVED00DC 0x00DC RESERVED -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -SSCCON 0x00E8 SSC Control Register -SSCCON.SCEN 7 -SSCCON.TEN 6 -SSCCON.MSTR 5 -SSCCON.CPOL 4 -SSCCON.CPHA 3 -SSCCON.BRS2 2 -SSCCON.BRS1 1 -SSCCON.BRS0 0 -STB 0x00E9 SSC Transmit Register -STB.STB7 7 -STB.STB6 6 -STB.STB5 5 -STB.STB4 4 -STB.STB3 3 -STB.STB2 2 -STB.STB1 1 -STB.STB0 0 -SRB 0x00EA SSC Receive Register -SRB.SRB7 7 -SRB.SRB6 6 -SRB.SRB5 5 -SRB.SRB4 4 -SRB.SRB3 3 -SRB.SRB2 2 -SRB.SRB1 1 -SRB.SRB0 0 -SSCMOD 0x00EB SSC Mode Test Register -SSCMOD.LOOPB 7 -SSCMOD.TRIO 6 -SSCMOD.LSBSM 0 -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -SCF 0x00F8 SSC Flag Register -SCF.WCOL 1 -SCF.TC 0 -SCIEN 0x00F9 SSC Interrupt Enable Register -SCIEN.WCEN 1 -SCIEN.TCEN 0 -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR0.VR07 7 -VR0.VR06 6 -VR0.VR05 5 -VR0.VR04 4 -VR0.VR03 3 -VR0.VR02 2 -VR0.VR01 1 -VR0.VR00 0 -VR1 0x00FD Version Register 1 -VR1.VR17 7 -VR1.VR16 6 -VR1.VR15 5 -VR1.VR14 4 -VR1.VR13 3 -VR1.VR12 2 -VR1.VR11 1 -VR1.VR10 0 -VR2 0x00FE Version Register 2 -VR2.VR27 7 -VR2.VR26 6 -VR2.VR25 5 -VR2.VR24 4 -VR2.VR23 3 -VR2.VR22 2 -VR2.VR21 1 -VR2.VR20 0 -RESERVED00FF 0x00FF RESERVED - - -.C515 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8032&parent_oid=16670 -; SAF-C515-L24N.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI_TI 0x0023 Serial channel -entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload -entry IADC 0x0043 A/D converter -entry IEX2 0x004B External interrupt 2 -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -RESERVED0086 0x0086 RESERVED -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_0 7 -TMOD.C_T_0 6 -TMOD.M1_0 5 -TMOD.M0_0 4 -TMOD.GATE_1 3 -TMOD.C_T_1 2 -TMOD.M1_1 1 -TMOD.M0_1 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.INT2 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EAL 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -RESERVED00AA 0x00AA RESERVED -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register -SYSCON.EALE 5 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.EX2 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.IEX2 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.I2FR 5 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Com./Rel./Capt. Reg. High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON 0x00D8 A/D Converter Control Register -ADCON.BD 7 -ADCON.CLK 6 -ADCON.BSY 4 -ADCON.ADM 3 -ADCON.MX2 2 -ADCON.MX1 1 -ADCON.MX0 0 -ADDAT 0x00D9 A/D Converter Data Register -ADDAT.ADDAT7 7 -ADDAT.ADDAT6 6 -ADDAT.ADDAT5 5 -ADDAT.ADDAT4 4 -ADDAT.ADDAT3 3 -ADDAT.ADDAT2 2 -ADDAT.ADDAT1 1 -ADDAT.ADDAT0 0 -DAPR 0x00DA A/D Converter Program Register -DAPR.DAPR7 7 -DAPR.DAPR6 6 -DAPR.DAPR5 5 -DAPR.DAPR4 4 -DAPR.DAPR3 3 -DAPR.DAPR2 2 -DAPR.DAPR1 1 -DAPR.DAPR0 0 -P6 0x00DB Port 6, Analog/Digital Input -P6.P67 7 -P6.P66 6 -P6.P65 5 -P6.P64 4 -P6.P63 3 -P6.P62 2 -P6.P61 1 -P6.P60 0 -RESERVED00DC 0x00DC RESERVED -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 -P4.P47 7 -P4.P46 6 -P4.P45 5 -P4.P44 4 -P4.P43 3 -P4.P42 2 -P4.P41 1 -P4.P40 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -P5 0x00F8 -P5.P57 7 -P5.P56 6 -P5.P55 5 -P5.P54 4 -P5.P53 3 -P5.P52 2 -P5.P51 1 -P5.P50 0 -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C515A -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8033&parent_oid=12122 -; SAF_C515A-4R24M.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xFC00 -area DATA XRAM 0xFC00:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI_TI 0x0023 Serial channel -entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload -entry IADC 0x0043 A/D converter -entry IEX2 0x004B External interrupt 2 -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry WAKE_UP 0x007B Wake-up from power-down mode - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.INT2 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -XPAGE 0x0091 Page Address Register for Extended On-Chip RAM -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EAL 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, Low Byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System/XRAM Control Register -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.EX2 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, High Byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.IEX2 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.I2FR 5 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Com./Rel./Capt. Reg. High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.ADEX 5 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register, High Byte -ADDATH.ADDATH9 7 -ADDATH.ADDATH8 6 -ADDATH.ADDATH7 5 -ADDATH.ADDATH6 4 -ADDATH.ADDATH5 3 -ADDATH.ADDATH4 2 -ADDATH.ADDATH3 1 -ADDATH.ADDATH2 0 -ADDATL 0x00DA A/D Converter Data Register, low Byte -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -P6 0x00DB Port 6, Analog/Digital Input -P6.P67 7 -P6.P66 6 -P6.P65 5 -P6.P64 4 -P6.P63 3 -P6.P62 2 -P6.P61 1 -P6.P60 0 -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL 7 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.P47 7 -P4.P46 6 -P4.P45 5 -P4.P44 4 -P4.P43 3 -P4.P42 2 -P4.P41 1 -P4.P40 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -P5 0x00F8 Port 5 -P5.P57 7 -P5.P56 6 -P5.P55 5 -P5.P54 4 -P5.P53 3 -P5.P52 2 -P5.P51 1 -P5.P50 0 -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C515C -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=31042&parent_oid=12126 -; SAF_C515C-8EM.pdf - - -; MEMORY MAP -area CODE code 0x0000:0xF700 -area DATA CAN 0xF700:0xF800 -area DATA XRAM 0xF800:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External Interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External Interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial Channel -entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload -entry IADC 0x0043 A/D Converter -entry IEX2 0x004B External Interrupt 2 -entry IEX3 0x0053 External Interrupt 3 -entry IEX4 0x005B External Interrupt 4 -entry IEX5 0x0063 External Interrupt 5 -entry IEX6 0x006B External Interrupt 6 -entry WUPPDM 0x007B Wake-up from power-down mode -entry CANC 0x008B CAN controller -entry IEX7 0x00A3 External Interrupt 7 -entry IEX8 0x00AB External Interrupt 8 -entry SSCI 0x0093 SSC interface - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_0 7 -TMOD.C_T_0 6 -TMOD.M1_0 5 -TMOD.M0_0 4 -TMOD.GATE_1 3 -TMOD.C_T_1 2 -TMOD.M1_1 1 -TMOD.M0_1 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.INT2 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -SSCCON 0x0093 SSC Control Register -SSCCON.SCEN 7 -SSCCON.TEN 6 -SSCCON.MSTR 5 -SSCCON.CPOL 4 -SSCCON.CPHA 3 -SSCCON.BRS2 2 -SSCCON.BRS1 1 -SSCCON.BRS0 0 -STB 0x0094 SSC Transmit Buffer -STB.STB7 7 -STB.STB6 6 -STB.STB5 5 -STB.STB4 4 -STB.STB3 3 -STB.STB2 2 -STB.STB1 1 -STB.STB0 0 -SRB 0x0095 SSC Receive Register -SRB.SRB7 7 -SRB.SRB6 6 -SRB.SRB5 5 -SRB.SRB4 4 -SRB.SRB3 3 -SRB.SRB2 2 -SRB.SRB1 1 -SRB.SRB0 0 -SSCMOD 0x0096 SSC Mode Test Register -SSCMOD.LOOPB 7 -SSCMOD.TRIO 6 -SSCMOD.LSBSM 0 -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -IEN2 0x009A Interrupt Enable Register 2 -IEN2.EX8 5 -IEN2.EX7 4 -IEN2.ESSC 2 -IEN2.ECAN 1 -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EAL 7 -IEN0.WDT 6 -IEN0.ET2 5 -IEN0.ES 4 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -SRELL 0x00AA Serial Channel Reload Register, low byte -SRELL.SRELL7 7 -SRELL.SRELL6 6 -SRELL.SRELL5 5 -SRELL.SRELL4 4 -SRELL.SRELL3 3 -SRELL.SRELL2 2 -SRELL.SRELL1 1 -SRELL.SRELL0 0 -SCF 0x00AB SSC Flag Register -SCF.WCOL 1 -SCF.TC 0 -SCIEN 0x00AC SSC Interrupt Enable Register -SCIEN.WCEN 1 -SCIEN.TCEN 0 -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD 1 -P3.RxD 0 -SYSCON 0x00B1 System Control Register -SYSCON.PMOD 6 -SYSCON.EALE 5 -SYSCON.RMAP 4 -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -; SYSCON 0x00B1 System Control Register (available in the C515C-8E) -; SYSCON.PMOD 6 -; SYSCON.EALE 5 -; SYSCON.RMAP 4 -; SYSCON.CSWO 2 -; SYSCON.XMAP1 1 -; SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.EX2 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.PDIR 7 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -SRELH 0x00BA Serial Channel Reload Register, high byte -SRELH.SRELH1 1 -SRELH.SRELH0 0 -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -IRCON.EXF2 7 -IRCON.TF2 6 -IRCON.IEX6 5 -IRCON.IEX5 4 -IRCON.IEX4 3 -IRCON.IEX3 2 -IRCON.IEX2 1 -IRCON.IADC 0 -CCEN 0x00C1 Comp./Capture Enable Reg. -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.I2FR 5 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Com./Rel./Capt. Reg. High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.ADEX 5 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register High Byte -ADDATH.ADDATH9 7 -ADDATH.ADDATH8 6 -ADDATH.ADDATH7 5 -ADDATH.ADDATH6 4 -ADDATH.ADDATH5 3 -ADDATH.ADDATH4 2 -ADDATH.ADDATH3 1 -ADDATH.ADDATH2 0 -ADDATL 0x00DA A/D Converter Data Register Low Byte -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -P6 0x00DB Port 6, Analog/Digital Input -P6.P67 7 -P6.P66 6 -P6.P65 5 -P6.P64 4 -P6.P63 3 -P6.P62 2 -P6.P61 1 -P6.P60 0 -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL 7 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -P4.RXDC 7 -P4.TXDC 6 -P4.INT8 5 -P4.SLS 4 -P4.STO 3 -P4.SRI 2 -P4.SCLK 1 -P4.ADST 0 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -P5 0x00F8 Port 5 -P5.P57 7 -P5.P56 6 -P5.P55 5 -P5.P54 4 -P5.P53 3 -P5.P52 2 -P5.P51 1 -P5.P50 0 -; DIR5 0x00F8 Port 5 Direction Register -; DIR5.DIR57 7 -; DIR5.DIR56 6 -; DIR5.DIR55 5 -; DIR5.DIR54 4 -; DIR5.DIR53 3 -; DIR5.DIR52 2 -; DIR5.DIR51 1 -; DIR5.DIR50 0 -RESERVED00F9 0x00F9 RESERVED -P7 0x00FA Port 7 -P7.INT7 0 -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC (C515C-8E only) -VR1 0x00FD (C515C-8E only) -VR2 0x00FE (C515C-8E only) -RESERVED00FF 0x00FF RESERVED -CR 0xF700 Control Register -CR.TEST 7 -CR.CCE 6 -CR.EIE 3 -CR.SIE 2 -CR.IE 1 -CR.INIT 0 -SR 0xF701 Status Register -SR.BOFF 7 -SR.EWRN 6 -SR.RXOK 4 -SR.TXOK 3 -SR.LEC2 2 -SR.LEC1 1 -SR.LEC0 0 -IR 0xF702 Interrupt Register -IR.INTID7 7 -IR.INTID6 6 -IR.INTID5 5 -IR.INTID4 4 -IR.INTID3 3 -IR.INTID2 2 -IR.INTID1 1 -IR.INTID0 0 -RESERVEDF703 0xF703 RESERVED -BTR0 0xF704 Bit Timing Register Low -BTR0.SJW7 7 -BTR0.SJW6 6 -BTR0.BRP5 5 -BTR0.BRP4 4 -BTR0.BRP3 3 -BTR0.BRP2 2 -BTR0.BRP1 1 -BTR0.BRP0 0 -BTR1 0xF705 Bit Timing Register High -BTR1.TSEG27 7 -BTR1.TSEG26 6 -BTR1.TSEG25 5 -BTR1.TSEG24 4 -BTR1.TSEG13 3 -BTR1.TSEG12 2 -BTR1.TSEG11 1 -BTR1.TSEG10 0 -GMS0 0xF706 Global Mask Short Register Low -GMS0.ID28 7 -GMS0.ID27 6 -GMS0.ID26 5 -GMS0.ID25 4 -GMS0.ID24 3 -GMS0.ID23 2 -GMS0.ID22 1 -GMS0.ID21 0 -GMS1 0xF707 Global Mask Short Register High -GMS1.ID20 7 -GMS1.ID19 6 -GMS1.ID18 5 -UGML0 0xF708 Upper Global Mask Long Register Low -UGML0.ID28 7 -UGML0.ID27 6 -UGML0.ID26 5 -UGML0.ID25 4 -UGML0.ID24 3 -UGML0.ID23 2 -UGML0.ID22 1 -UGML0.ID21 0 -UGML1 0xF709 Upper Global Mask Long Register High -UGML1.ID20 7 -UGML1.ID19 6 -UGML1.ID18 5 -UGML1.ID17 4 -UGML1.ID16 3 -UGML1.ID15 2 -UGML1.ID14 1 -UGML1.ID13 0 -LGML0 0xF70A Lower Global Mask Long Register Low -LGML0.ID12 7 -LGML0.ID11 6 -LGML0.ID10 5 -LGML0.ID9 4 -LGML0.ID8 3 -LGML0.ID7 2 -LGML0.ID6 1 -LGML0.ID5 0 -LGML1 0xF70B Lower Global Mask Long Register High -LGML1.ID4 7 -LGML1.ID3 6 -LGML1.ID2 5 -LGML1.ID1 4 -LGML1.ID0 3 -UMLM0 0xF70C Upper Mask of Last Message Register Low -UMLM0.ID28 7 -UMLM0.ID27 6 -UMLM0.ID26 5 -UMLM0.ID25 4 -UMLM0.ID24 3 -UMLM0.ID23 2 -UMLM0.ID22 1 -UMLM0.ID21 0 -UMLM1 0xF70D Upper Mask of Last Message Register High -UMLM1.ID20 7 -UMLM1.ID19 6 -UMLM1.ID18 5 -UMLM1.ID17 4 -UMLM1.ID16 3 -UMLM1.ID15 2 -UMLM1.ID14 1 -UMLM1.ID13 0 -LMLM0 0xF70E Lower Mask of Last Message Register Low -LMLM0.ID12 7 -LMLM0.ID11 6 -LMLM0.ID10 5 -LMLM0.ID9 4 -LMLM0.ID8 3 -LMLM0.ID7 2 -LMLM0.ID6 1 -LMLM0.ID5 0 -LMLM1 0xF70F Lower Mask of Last Message Register High -LMLM1.ID4 7 -LMLM1.ID3 6 -LMLM1.ID2 5 -LMLM1.ID1 4 -LMLM1.ID0 3 -; -------------------------------------- CAN_1 -------------------------------- -MCR0_1 0xF710 Message Control Register Low -MCR0_1.MSGVAL1 7 -MCR0_1.MSGVAL0 6 -MCR0_1.TXIE1 5 -MCR0_1.TXIE0 4 -MCR0_1.RXIE1 3 -MCR0_1.RXIE0 2 -MCR0_1.INTPND1 1 -MCR0_1.INTPND0 0 -MCR1_1 0xF711 Message Control Register High -MCR1_1.RMTPND1 7 -MCR1_1.RMTPND0 6 -MCR1_1.TXRQ1 5 -MCR1_1.TXRQ0 4 -MCR1_1.MSGLSTCPUUPD1 3 -MCR1_1.MSGLSTCPUUPD0 2 -MCR1_1.NEWDAT1 1 -MCR1_1.NEWDAT0 0 -UAR0_1 0xF712 Upper Arbitration Register Low -UAR0_1.ID28 7 -UAR0_1.ID27 6 -UAR0_1.ID26 5 -UAR0_1.ID25 4 -UAR0_1.ID24 3 -UAR0_1.ID23 2 -UAR0_1.ID22 1 -UAR0_1.ID21 0 -UAR1_1 0xF713 Upper Arbitration Register High -UAR1_1.ID20 7 -UAR1_1.ID19 6 -UAR1_1.ID18 5 -UAR1_1.ID17 4 -UAR1_1.ID16 3 -UAR1_1.ID15 2 -UAR1_1.ID14 1 -UAR1_1.ID13 0 -LAR0_1 0xF714 Lower Arbitration Register Low -LAR0_1.ID12 7 -LAR0_1.ID11 6 -LAR0_1.ID10 5 -LAR0_1.ID9 4 -LAR0_1.ID8 3 -LAR0_1.ID7 2 -LAR0_1.ID6 1 -LAR0_1.ID5 0 -LAR1_1 0xF715 Lower Arbitration Register High -LAR1_1.ID4 7 -LAR1_1.ID3 6 -LAR1_1.ID2 5 -LAR1_1.ID1 4 -LAR1_1.ID0 3 -MCFG_1 0xF716 Message Configuration Register -MCFG_1.DLC7 7 -MCFG_1.DLC6 6 -MCFG_1.DLC5 5 -MCFG_1.DLC4 4 -MCFG_1.DIR 3 -MCFG_1.XTD 2 -DB0_1 0xF717 Message Data Byte 0 -DB0_1.DB07 7 -DB0_1.DB06 6 -DB0_1.DB05 5 -DB0_1.DB04 4 -DB0_1.DB03 3 -DB0_1.DB02 2 -DB0_1.DB01 1 -DB0_1.DB00 0 -DB1_1 0xF718 Message Data Byte 1 -DB1_1.DB17 7 -DB1_1.DB16 6 -DB1_1.DB15 5 -DB1_1.DB14 4 -DB1_1.DB13 3 -DB1_1.DB12 2 -DB1_1.DB11 1 -DB1_1.DB10 0 -DB2_1 0xF719 Message Data Byte 2 -DB2_1.DB27 7 -DB2_1.DB26 6 -DB2_1.DB25 5 -DB2_1.DB24 4 -DB2_1.DB23 3 -DB2_1.DB22 2 -DB2_1.DB21 1 -DB2_1.DB20 0 -DB3_1 0xF71A Message Data Byte 3 -DB3_1.DB37 7 -DB3_1.DB36 6 -DB3_1.DB35 5 -DB3_1.DB34 4 -DB3_1.DB33 3 -DB3_1.DB32 2 -DB3_1.DB31 1 -DB3_1.DB30 0 -DB4_1 0xF71B Message Data Byte 4 -DB4_1.DB47 7 -DB4_1.DB46 6 -DB4_1.DB45 5 -DB4_1.DB44 4 -DB4_1.DB43 3 -DB4_1.DB42 2 -DB4_1.DB41 1 -DB4_1.DB40 0 -DB5_1 0xF71C Message Data Byte 5 -DB5_1.DB57 7 -DB5_1.DB56 6 -DB5_1.DB55 5 -DB5_1.DB54 4 -DB5_1.DB53 3 -DB5_1.DB52 2 -DB5_1.DB51 1 -DB5_1.DB50 0 -DB6_1 0xF71D Message Data Byte 6 -DB6_1.DB67 7 -DB6_1.DB66 6 -DB6_1.DB65 5 -DB6_1.DB64 4 -DB6_1.DB63 3 -DB6_1.DB62 2 -DB6_1.DB61 1 -DB6_1.DB60 0 -DB7_1 0xF71E Message Data Byte 7 -DB7_1.DB77 7 -DB7_1.DB76 6 -DB7_1.DB75 5 -DB7_1.DB74 4 -DB7_1.DB73 3 -DB7_1.DB72 2 -DB7_1.DB71 1 -DB7_1.DB70 0 -RESERVEDF71F 0xF71F RESERVED -; -------------------------------------- CAN_2 -------------------------------- -MCR0_2 0xF720 Message Control Register Low -MCR0_2.MSGVAL1 7 -MCR0_2.MSGVAL0 6 -MCR0_2.TXIE1 5 -MCR0_2.TXIE0 4 -MCR0_2.RXIE1 3 -MCR0_2.RXIE0 2 -MCR0_2.INTPND1 1 -MCR0_2.INTPND0 0 -MCR1_2 0xF721 Message Control Register High -MCR1_2.RMTPND1 7 -MCR1_2.RMTPND0 6 -MCR1_2.TXRQ1 5 -MCR1_2.TXRQ0 4 -MCR1_2.MSGLSTCPUUPD1 3 -MCR1_2.MSGLSTCPUUPD0 2 -MCR1_2.NEWDAT1 1 -MCR1_2.NEWDAT0 0 -UAR0_2 0xF722 Upper Arbitration Register Low -UAR0_2.ID28 7 -UAR0_2.ID27 6 -UAR0_2.ID26 5 -UAR0_2.ID25 4 -UAR0_2.ID24 3 -UAR0_2.ID23 2 -UAR0_2.ID22 1 -UAR0_2.ID21 0 -UAR1_2 0xF723 Upper Arbitration Register High -UAR1_2.ID20 7 -UAR1_2.ID19 6 -UAR1_2.ID18 5 -UAR1_2.ID17 4 -UAR1_2.ID16 3 -UAR1_2.ID15 2 -UAR1_2.ID14 1 -UAR1_2.ID13 0 -LAR0_2 0xF724 Lower Arbitration Register Low -LAR0_2.ID12 7 -LAR0_2.ID11 6 -LAR0_2.ID10 5 -LAR0_2.ID9 4 -LAR0_2.ID8 3 -LAR0_2.ID7 2 -LAR0_2.ID6 1 -LAR0_2.ID5 0 -LAR1_2 0xF725 Lower Arbitration Register High -LAR1_2.ID4 7 -LAR1_2.ID3 6 -LAR1_2.ID2 5 -LAR1_2.ID1 4 -LAR1_2.ID0 3 -MCFG_2 0xF726 Message Configuration Register -MCFG_2.DLC7 7 -MCFG_2.DLC6 6 -MCFG_2.DLC5 5 -MCFG_2.DLC4 4 -MCFG_2.DIR 3 -MCFG_2.XTD 2 -DB0_2 0xF727 Message Data Byte 0 -DB0_2.DB07 7 -DB0_2.DB06 6 -DB0_2.DB05 5 -DB0_2.DB04 4 -DB0_2.DB03 3 -DB0_2.DB02 2 -DB0_2.DB01 1 -DB0_2.DB00 0 -DB1_2 0xF728 Message Data Byte 1 -DB1_2.DB17 7 -DB1_2.DB16 6 -DB1_2.DB15 5 -DB1_2.DB14 4 -DB1_2.DB13 3 -DB1_2.DB12 2 -DB1_2.DB11 1 -DB1_2.DB10 0 -DB2_2 0xF729 Message Data Byte 2 -DB2_2.DB27 7 -DB2_2.DB26 6 -DB2_2.DB25 5 -DB2_2.DB24 4 -DB2_2.DB23 3 -DB2_2.DB22 2 -DB2_2.DB21 1 -DB2_2.DB20 0 -DB3_2 0xF72A Message Data Byte 3 -DB3_2.DB37 7 -DB3_2.DB36 6 -DB3_2.DB35 5 -DB3_2.DB34 4 -DB3_2.DB33 3 -DB3_2.DB32 2 -DB3_2.DB31 1 -DB3_2.DB30 0 -DB4_2 0xF72B Message Data Byte 4 -DB4_2.DB47 7 -DB4_2.DB46 6 -DB4_2.DB45 5 -DB4_2.DB44 4 -DB4_2.DB43 3 -DB4_2.DB42 2 -DB4_2.DB41 1 -DB4_2.DB40 0 -DB5_2 0xF72C Message Data Byte 5 -DB5_2.DB57 7 -DB5_2.DB56 6 -DB5_2.DB55 5 -DB5_2.DB54 4 -DB5_2.DB53 3 -DB5_2.DB52 2 -DB5_2.DB51 1 -DB5_2.DB50 0 -DB6_2 0xF72D Message Data Byte 6 -DB6_2.DB67 7 -DB6_2.DB66 6 -DB6_2.DB65 5 -DB6_2.DB64 4 -DB6_2.DB63 3 -DB6_2.DB62 2 -DB6_2.DB61 1 -DB6_2.DB60 0 -DB7_2 0xF72E Message Data Byte 7 -DB7_2.DB77 7 -DB7_2.DB76 6 -DB7_2.DB75 5 -DB7_2.DB74 4 -DB7_2.DB73 3 -DB7_2.DB72 2 -DB7_2.DB71 1 -DB7_2.DB70 0 -RESERVEDF72F 0xF72F RESERVED -; -------------------------------------- CAN_3 -------------------------------- -MCR0_3 0xF730 Message Control Register Low -MCR0_3.MSGVAL1 7 -MCR0_3.MSGVAL0 6 -MCR0_3.TXIE1 5 -MCR0_3.TXIE0 4 -MCR0_3.RXIE1 3 -MCR0_3.RXIE0 2 -MCR0_3.INTPND1 1 -MCR0_3.INTPND0 0 -MCR1_3 0xF731 Message Control Register High -MCR1_3.RMTPND1 7 -MCR1_3.RMTPND0 6 -MCR1_3.TXRQ1 5 -MCR1_3.TXRQ0 4 -MCR1_3.MSGLSTCPUUPD1 3 -MCR1_3.MSGLSTCPUUPD0 2 -MCR1_3.NEWDAT1 1 -MCR1_3.NEWDAT0 0 -UAR0_3 0xF732 Upper Arbitration Register Low -UAR0_3.ID28 7 -UAR0_3.ID27 6 -UAR0_3.ID26 5 -UAR0_3.ID25 4 -UAR0_3.ID24 3 -UAR0_3.ID23 2 -UAR0_3.ID22 1 -UAR0_3.ID21 0 -UAR1_3 0xF733 Upper Arbitration Register High -UAR1_3.ID20 7 -UAR1_3.ID19 6 -UAR1_3.ID18 5 -UAR1_3.ID17 4 -UAR1_3.ID16 3 -UAR1_3.ID15 2 -UAR1_3.ID14 1 -UAR1_3.ID13 0 -LAR0_3 0xF734 Lower Arbitration Register Low -LAR0_3.ID12 7 -LAR0_3.ID11 6 -LAR0_3.ID10 5 -LAR0_3.ID9 4 -LAR0_3.ID8 3 -LAR0_3.ID7 2 -LAR0_3.ID6 1 -LAR0_3.ID5 0 -LAR1_3 0xF735 Lower Arbitration Register High -LAR1_3.ID4 7 -LAR1_3.ID3 6 -LAR1_3.ID2 5 -LAR1_3.ID1 4 -LAR1_3.ID0 3 -MCFG_3 0xF736 Message Configuration Register -MCFG_3.DLC7 7 -MCFG_3.DLC6 6 -MCFG_3.DLC5 5 -MCFG_3.DLC4 4 -MCFG_3.DIR 3 -MCFG_3.XTD 2 -DB0_3 0xF737 Message Data Byte 0 -DB0_3.DB07 7 -DB0_3.DB06 6 -DB0_3.DB05 5 -DB0_3.DB04 4 -DB0_3.DB03 3 -DB0_3.DB02 2 -DB0_3.DB01 1 -DB0_3.DB00 0 -DB1_3 0xF738 Message Data Byte 1 -DB1_3.DB17 7 -DB1_3.DB16 6 -DB1_3.DB15 5 -DB1_3.DB14 4 -DB1_3.DB13 3 -DB1_3.DB12 2 -DB1_3.DB11 1 -DB1_3.DB10 0 -DB2_3 0xF739 Message Data Byte 2 -DB2_3.DB27 7 -DB2_3.DB26 6 -DB2_3.DB25 5 -DB2_3.DB24 4 -DB2_3.DB23 3 -DB2_3.DB22 2 -DB2_3.DB21 1 -DB2_3.DB20 0 -DB3_3 0xF73A Message Data Byte 3 -DB3_3.DB37 7 -DB3_3.DB36 6 -DB3_3.DB35 5 -DB3_3.DB34 4 -DB3_3.DB33 3 -DB3_3.DB32 2 -DB3_3.DB31 1 -DB3_3.DB30 0 -DB4_3 0xF73B Message Data Byte 4 -DB4_3.DB47 7 -DB4_3.DB46 6 -DB4_3.DB45 5 -DB4_3.DB44 4 -DB4_3.DB43 3 -DB4_3.DB42 2 -DB4_3.DB41 1 -DB4_3.DB40 0 -DB5_3 0xF73C Message Data Byte 5 -DB5_3.DB57 7 -DB5_3.DB56 6 -DB5_3.DB55 5 -DB5_3.DB54 4 -DB5_3.DB53 3 -DB5_3.DB52 2 -DB5_3.DB51 1 -DB5_3.DB50 0 -DB6_3 0xF73D Message Data Byte 6 -DB6_3.DB67 7 -DB6_3.DB66 6 -DB6_3.DB65 5 -DB6_3.DB64 4 -DB6_3.DB63 3 -DB6_3.DB62 2 -DB6_3.DB61 1 -DB6_3.DB60 0 -DB7_3 0xF73E Message Data Byte 7 -DB7_3.DB77 7 -DB7_3.DB76 6 -DB7_3.DB75 5 -DB7_3.DB74 4 -DB7_3.DB73 3 -DB7_3.DB72 2 -DB7_3.DB71 1 -DB7_3.DB70 0 -RESERVEDF73F 0xF73F RESERVED -; -------------------------------------- CAN_4 -------------------------------- -MCR0_4 0xF740 Message Control Register Low -MCR0_4.MSGVAL1 7 -MCR0_4.MSGVAL0 6 -MCR0_4.TXIE1 5 -MCR0_4.TXIE0 4 -MCR0_4.RXIE1 3 -MCR0_4.RXIE0 2 -MCR0_4.INTPND1 1 -MCR0_4.INTPND0 0 -MCR1_4 0xF741 Message Control Register High -MCR1_4.RMTPND1 7 -MCR1_4.RMTPND0 6 -MCR1_4.TXRQ1 5 -MCR1_4.TXRQ0 4 -MCR1_4.MSGLSTCPUUPD1 3 -MCR1_4.MSGLSTCPUUPD0 2 -MCR1_4.NEWDAT1 1 -MCR1_4.NEWDAT0 0 -UAR0_4 0xF742 Upper Arbitration Register Low -UAR0_4.ID28 7 -UAR0_4.ID27 6 -UAR0_4.ID26 5 -UAR0_4.ID25 4 -UAR0_4.ID24 3 -UAR0_4.ID23 2 -UAR0_4.ID22 1 -UAR0_4.ID21 0 -UAR1_4 0xF743 Upper Arbitration Register High -UAR1_4.ID20 7 -UAR1_4.ID19 6 -UAR1_4.ID18 5 -UAR1_4.ID17 4 -UAR1_4.ID16 3 -UAR1_4.ID15 2 -UAR1_4.ID14 1 -UAR1_4.ID13 0 -LAR0_4 0xF744 Lower Arbitration Register Low -LAR0_4.ID12 7 -LAR0_4.ID11 6 -LAR0_4.ID10 5 -LAR0_4.ID9 4 -LAR0_4.ID8 3 -LAR0_4.ID7 2 -LAR0_4.ID6 1 -LAR0_4.ID5 0 -LAR1_4 0xF745 Lower Arbitration Register High -LAR1_4.ID4 7 -LAR1_4.ID3 6 -LAR1_4.ID2 5 -LAR1_4.ID1 4 -LAR1_4.ID0 3 -MCFG_4 0xF746 Message Configuration Register -MCFG_4.DLC7 7 -MCFG_4.DLC6 6 -MCFG_4.DLC5 5 -MCFG_4.DLC4 4 -MCFG_4.DIR 3 -MCFG_4.XTD 2 -DB0_4 0xF747 Message Data Byte 0 -DB0_4.DB07 7 -DB0_4.DB06 6 -DB0_4.DB05 5 -DB0_4.DB04 4 -DB0_4.DB03 3 -DB0_4.DB02 2 -DB0_4.DB01 1 -DB0_4.DB00 0 -DB1_4 0xF748 Message Data Byte 1 -DB1_4.DB17 7 -DB1_4.DB16 6 -DB1_4.DB15 5 -DB1_4.DB14 4 -DB1_4.DB13 3 -DB1_4.DB12 2 -DB1_4.DB11 1 -DB1_4.DB10 0 -DB2_4 0xF749 Message Data Byte 2 -DB2_4.DB27 7 -DB2_4.DB26 6 -DB2_4.DB25 5 -DB2_4.DB24 4 -DB2_4.DB23 3 -DB2_4.DB22 2 -DB2_4.DB21 1 -DB2_4.DB20 0 -DB3_4 0xF74A Message Data Byte 3 -DB3_4.DB37 7 -DB3_4.DB36 6 -DB3_4.DB35 5 -DB3_4.DB34 4 -DB3_4.DB33 3 -DB3_4.DB32 2 -DB3_4.DB31 1 -DB3_4.DB30 0 -DB4_4 0xF74B Message Data Byte 4 -DB4_4.DB47 7 -DB4_4.DB46 6 -DB4_4.DB45 5 -DB4_4.DB44 4 -DB4_4.DB43 3 -DB4_4.DB42 2 -DB4_4.DB41 1 -DB4_4.DB40 0 -DB5_4 0xF74C Message Data Byte 5 -DB5_4.DB57 7 -DB5_4.DB56 6 -DB5_4.DB55 5 -DB5_4.DB54 4 -DB5_4.DB53 3 -DB5_4.DB52 2 -DB5_4.DB51 1 -DB5_4.DB50 0 -DB6_4 0xF74D Message Data Byte 6 -DB6_4.DB67 7 -DB6_4.DB66 6 -DB6_4.DB65 5 -DB6_4.DB64 4 -DB6_4.DB63 3 -DB6_4.DB62 2 -DB6_4.DB61 1 -DB6_4.DB60 0 -DB7_4 0xF74E Message Data Byte 7 -DB7_4.DB77 7 -DB7_4.DB76 6 -DB7_4.DB75 5 -DB7_4.DB74 4 -DB7_4.DB73 3 -DB7_4.DB72 2 -DB7_4.DB71 1 -DB7_4.DB70 0 -RESERVEDF74F 0xF74F RESERVED -; -------------------------------------- CAN_5 -------------------------------- -MCR0_5 0xF750 Message Control Register Low -MCR0_5.MSGVAL1 7 -MCR0_5.MSGVAL0 6 -MCR0_5.TXIE1 5 -MCR0_5.TXIE0 4 -MCR0_5.RXIE1 3 -MCR0_5.RXIE0 2 -MCR0_5.INTPND1 1 -MCR0_5.INTPND0 0 -MCR1_5 0xF751 Message Control Register High -MCR1_5.RMTPND1 7 -MCR1_5.RMTPND0 6 -MCR1_5.TXRQ1 5 -MCR1_5.TXRQ0 4 -MCR1_5.MSGLSTCPUUPD1 3 -MCR1_5.MSGLSTCPUUPD0 2 -MCR1_5.NEWDAT1 1 -MCR1_5.NEWDAT0 0 -UAR0_5 0xF752 Upper Arbitration Register Low -UAR0_5.ID28 7 -UAR0_5.ID27 6 -UAR0_5.ID26 5 -UAR0_5.ID25 4 -UAR0_5.ID24 3 -UAR0_5.ID23 2 -UAR0_5.ID22 1 -UAR0_5.ID21 0 -UAR1_5 0xF753 Upper Arbitration Register High -UAR1_5.ID20 7 -UAR1_5.ID19 6 -UAR1_5.ID18 5 -UAR1_5.ID17 4 -UAR1_5.ID16 3 -UAR1_5.ID15 2 -UAR1_5.ID14 1 -UAR1_5.ID13 0 -LAR0_5 0xF754 Lower Arbitration Register Low -LAR0_5.ID12 7 -LAR0_5.ID11 6 -LAR0_5.ID10 5 -LAR0_5.ID9 4 -LAR0_5.ID8 3 -LAR0_5.ID7 2 -LAR0_5.ID6 1 -LAR0_5.ID5 0 -LAR1_5 0xF755 Lower Arbitration Register High -LAR1_5.ID4 7 -LAR1_5.ID3 6 -LAR1_5.ID2 5 -LAR1_5.ID1 4 -LAR1_5.ID0 3 -MCFG_5 0xF756 Message Configuration Register -MCFG_5.DLC7 7 -MCFG_5.DLC6 6 -MCFG_5.DLC5 5 -MCFG_5.DLC4 4 -MCFG_5.DIR 3 -MCFG_5.XTD 2 -DB0_5 0xF757 Message Data Byte 0 -DB0_5.DB07 7 -DB0_5.DB06 6 -DB0_5.DB05 5 -DB0_5.DB04 4 -DB0_5.DB03 3 -DB0_5.DB02 2 -DB0_5.DB01 1 -DB0_5.DB00 0 -DB1_5 0xF758 Message Data Byte 1 -DB1_5.DB17 7 -DB1_5.DB16 6 -DB1_5.DB15 5 -DB1_5.DB14 4 -DB1_5.DB13 3 -DB1_5.DB12 2 -DB1_5.DB11 1 -DB1_5.DB10 0 -DB2_5 0xF759 Message Data Byte 2 -DB2_5.DB27 7 -DB2_5.DB26 6 -DB2_5.DB25 5 -DB2_5.DB24 4 -DB2_5.DB23 3 -DB2_5.DB22 2 -DB2_5.DB21 1 -DB2_5.DB20 0 -DB3_5 0xF75A Message Data Byte 3 -DB3_5.DB37 7 -DB3_5.DB36 6 -DB3_5.DB35 5 -DB3_5.DB34 4 -DB3_5.DB33 3 -DB3_5.DB32 2 -DB3_5.DB31 1 -DB3_5.DB30 0 -DB4_5 0xF75B Message Data Byte 4 -DB4_5.DB47 7 -DB4_5.DB46 6 -DB4_5.DB45 5 -DB4_5.DB44 4 -DB4_5.DB43 3 -DB4_5.DB42 2 -DB4_5.DB41 1 -DB4_5.DB40 0 -DB5_5 0xF75C Message Data Byte 5 -DB5_5.DB57 7 -DB5_5.DB56 6 -DB5_5.DB55 5 -DB5_5.DB54 4 -DB5_5.DB53 3 -DB5_5.DB52 2 -DB5_5.DB51 1 -DB5_5.DB50 0 -DB6_5 0xF75D Message Data Byte 6 -DB6_5.DB67 7 -DB6_5.DB66 6 -DB6_5.DB65 5 -DB6_5.DB64 4 -DB6_5.DB63 3 -DB6_5.DB62 2 -DB6_5.DB61 1 -DB6_5.DB60 0 -DB7_5 0xF75E Message Data Byte 7 -DB7_5.DB77 7 -DB7_5.DB76 6 -DB7_5.DB75 5 -DB7_5.DB74 4 -DB7_5.DB73 3 -DB7_5.DB72 2 -DB7_5.DB71 1 -DB7_5.DB70 0 -RESERVEDF75F 0xF75F RESERVED -; -------------------------------------- CAN_6 -------------------------------- -MCR0_6 0xF760 Message Control Register Low -MCR0_6.MSGVAL1 7 -MCR0_6.MSGVAL0 6 -MCR0_6.TXIE1 5 -MCR0_6.TXIE0 4 -MCR0_6.RXIE1 3 -MCR0_6.RXIE0 2 -MCR0_6.INTPND1 1 -MCR0_6.INTPND0 0 -MCR1_6 0xF761 Message Control Register High -MCR1_6.RMTPND1 7 -MCR1_6.RMTPND0 6 -MCR1_6.TXRQ1 5 -MCR1_6.TXRQ0 4 -MCR1_6.MSGLSTCPUUPD1 3 -MCR1_6.MSGLSTCPUUPD0 2 -MCR1_6.NEWDAT1 1 -MCR1_6.NEWDAT0 0 -UAR0_6 0xF762 Upper Arbitration Register Low -UAR0_6.ID28 7 -UAR0_6.ID27 6 -UAR0_6.ID26 5 -UAR0_6.ID25 4 -UAR0_6.ID24 3 -UAR0_6.ID23 2 -UAR0_6.ID22 1 -UAR0_6.ID21 0 -UAR1_6 0xF763 Upper Arbitration Register High -UAR1_6.ID20 7 -UAR1_6.ID19 6 -UAR1_6.ID18 5 -UAR1_6.ID17 4 -UAR1_6.ID16 3 -UAR1_6.ID15 2 -UAR1_6.ID14 1 -UAR1_6.ID13 0 -LAR0_6 0xF764 Lower Arbitration Register Low -LAR0_6.ID12 7 -LAR0_6.ID11 6 -LAR0_6.ID10 5 -LAR0_6.ID9 4 -LAR0_6.ID8 3 -LAR0_6.ID7 2 -LAR0_6.ID6 1 -LAR0_6.ID5 0 -LAR1_6 0xF765 Lower Arbitration Register High -LAR1_6.ID4 7 -LAR1_6.ID3 6 -LAR1_6.ID2 5 -LAR1_6.ID1 4 -LAR1_6.ID0 3 -MCFG_6 0xF766 Message Configuration Register -MCFG_6.DLC7 7 -MCFG_6.DLC6 6 -MCFG_6.DLC5 5 -MCFG_6.DLC4 4 -MCFG_6.DIR 3 -MCFG_6.XTD 2 -DB0_6 0xF767 Message Data Byte 0 -DB0_6.DB07 7 -DB0_6.DB06 6 -DB0_6.DB05 5 -DB0_6.DB04 4 -DB0_6.DB03 3 -DB0_6.DB02 2 -DB0_6.DB01 1 -DB0_6.DB00 0 -DB1_6 0xF768 Message Data Byte 1 -DB1_6.DB17 7 -DB1_6.DB16 6 -DB1_6.DB15 5 -DB1_6.DB14 4 -DB1_6.DB13 3 -DB1_6.DB12 2 -DB1_6.DB11 1 -DB1_6.DB10 0 -DB2_6 0xF769 Message Data Byte 2 -DB2_6.DB27 7 -DB2_6.DB26 6 -DB2_6.DB25 5 -DB2_6.DB24 4 -DB2_6.DB23 3 -DB2_6.DB22 2 -DB2_6.DB21 1 -DB2_6.DB20 0 -DB3_6 0xF76A Message Data Byte 3 -DB3_6.DB37 7 -DB3_6.DB36 6 -DB3_6.DB35 5 -DB3_6.DB34 4 -DB3_6.DB33 3 -DB3_6.DB32 2 -DB3_6.DB31 1 -DB3_6.DB30 0 -DB4_6 0xF76B Message Data Byte 4 -DB4_6.DB47 7 -DB4_6.DB46 6 -DB4_6.DB45 5 -DB4_6.DB44 4 -DB4_6.DB43 3 -DB4_6.DB42 2 -DB4_6.DB41 1 -DB4_6.DB40 0 -DB5_6 0xF76C Message Data Byte 5 -DB5_6.DB57 7 -DB5_6.DB56 6 -DB5_6.DB55 5 -DB5_6.DB54 4 -DB5_6.DB53 3 -DB5_6.DB52 2 -DB5_6.DB51 1 -DB5_6.DB50 0 -DB6_6 0xF76D Message Data Byte 6 -DB6_6.DB67 7 -DB6_6.DB66 6 -DB6_6.DB65 5 -DB6_6.DB64 4 -DB6_6.DB63 3 -DB6_6.DB62 2 -DB6_6.DB61 1 -DB6_6.DB60 0 -DB7_6 0xF76E Message Data Byte 7 -DB7_6.DB77 7 -DB7_6.DB76 6 -DB7_6.DB75 5 -DB7_6.DB74 4 -DB7_6.DB73 3 -DB7_6.DB72 2 -DB7_6.DB71 1 -DB7_6.DB70 0 -RESERVEDF76F 0xF76F RESERVED -; -------------------------------------- CAN_7 -------------------------------- -MCR0_7 0xF770 Message Control Register Low -MCR0_7.MSGVAL1 7 -MCR0_7.MSGVAL0 6 -MCR0_7.TXIE1 5 -MCR0_7.TXIE0 4 -MCR0_7.RXIE1 3 -MCR0_7.RXIE0 2 -MCR0_7.INTPND1 1 -MCR0_7.INTPND0 0 -MCR1_7 0xF771 Message Control Register High -MCR1_7.RMTPND1 7 -MCR1_7.RMTPND0 6 -MCR1_7.TXRQ1 5 -MCR1_7.TXRQ0 4 -MCR1_7.MSGLSTCPUUPD1 3 -MCR1_7.MSGLSTCPUUPD0 2 -MCR1_7.NEWDAT1 1 -MCR1_7.NEWDAT0 0 -UAR0_7 0xF772 Upper Arbitration Register Low -UAR0_7.ID28 7 -UAR0_7.ID27 6 -UAR0_7.ID26 5 -UAR0_7.ID25 4 -UAR0_7.ID24 3 -UAR0_7.ID23 2 -UAR0_7.ID22 1 -UAR0_7.ID21 0 -UAR1_7 0xF773 Upper Arbitration Register High -UAR1_7.ID20 7 -UAR1_7.ID19 6 -UAR1_7.ID18 5 -UAR1_7.ID17 4 -UAR1_7.ID16 3 -UAR1_7.ID15 2 -UAR1_7.ID14 1 -UAR1_7.ID13 0 -LAR0_7 0xF774 Lower Arbitration Register Low -LAR0_7.ID12 7 -LAR0_7.ID11 6 -LAR0_7.ID10 5 -LAR0_7.ID9 4 -LAR0_7.ID8 3 -LAR0_7.ID7 2 -LAR0_7.ID6 1 -LAR0_7.ID5 0 -LAR1_7 0xF775 Lower Arbitration Register High -LAR1_7.ID4 7 -LAR1_7.ID3 6 -LAR1_7.ID2 5 -LAR1_7.ID1 4 -LAR1_7.ID0 3 -MCFG_7 0xF776 Message Configuration Register -MCFG_7.DLC7 7 -MCFG_7.DLC6 6 -MCFG_7.DLC5 5 -MCFG_7.DLC4 4 -MCFG_7.DIR 3 -MCFG_7.XTD 2 -DB0_7 0xF777 Message Data Byte 0 -DB0_7.DB07 7 -DB0_7.DB06 6 -DB0_7.DB05 5 -DB0_7.DB04 4 -DB0_7.DB03 3 -DB0_7.DB02 2 -DB0_7.DB01 1 -DB0_7.DB00 0 -DB1_7 0xF778 Message Data Byte 1 -DB1_7.DB17 7 -DB1_7.DB16 6 -DB1_7.DB15 5 -DB1_7.DB14 4 -DB1_7.DB13 3 -DB1_7.DB12 2 -DB1_7.DB11 1 -DB1_7.DB10 0 -DB2_7 0xF779 Message Data Byte 2 -DB2_7.DB27 7 -DB2_7.DB26 6 -DB2_7.DB25 5 -DB2_7.DB24 4 -DB2_7.DB23 3 -DB2_7.DB22 2 -DB2_7.DB21 1 -DB2_7.DB20 0 -DB3_7 0xF77A Message Data Byte 3 -DB3_7.DB37 7 -DB3_7.DB36 6 -DB3_7.DB35 5 -DB3_7.DB34 4 -DB3_7.DB33 3 -DB3_7.DB32 2 -DB3_7.DB31 1 -DB3_7.DB30 0 -DB4_7 0xF77B Message Data Byte 4 -DB4_7.DB47 7 -DB4_7.DB46 6 -DB4_7.DB45 5 -DB4_7.DB44 4 -DB4_7.DB43 3 -DB4_7.DB42 2 -DB4_7.DB41 1 -DB4_7.DB40 0 -DB5_7 0xF77C Message Data Byte 5 -DB5_7.DB57 7 -DB5_7.DB56 6 -DB5_7.DB55 5 -DB5_7.DB54 4 -DB5_7.DB53 3 -DB5_7.DB52 2 -DB5_7.DB51 1 -DB5_7.DB50 0 -DB6_7 0xF77D Message Data Byte 6 -DB6_7.DB67 7 -DB6_7.DB66 6 -DB6_7.DB65 5 -DB6_7.DB64 4 -DB6_7.DB63 3 -DB6_7.DB62 2 -DB6_7.DB61 1 -DB6_7.DB60 0 -DB7_7 0xF77E Message Data Byte 7 -DB7_7.DB77 7 -DB7_7.DB76 6 -DB7_7.DB75 5 -DB7_7.DB74 4 -DB7_7.DB73 3 -DB7_7.DB72 2 -DB7_7.DB71 1 -DB7_7.DB70 0 -RESERVEDF77F 0xF77F RESERVED -; -------------------------------------- CAN_8 -------------------------------- -MCR0_8 0xF780 Message Control Register Low -MCR0_8.MSGVAL1 7 -MCR0_8.MSGVAL0 6 -MCR0_8.TXIE1 5 -MCR0_8.TXIE0 4 -MCR0_8.RXIE1 3 -MCR0_8.RXIE0 2 -MCR0_8.INTPND1 1 -MCR0_8.INTPND0 0 -MCR1_8 0xF781 Message Control Register High -MCR1_8.RMTPND1 7 -MCR1_8.RMTPND0 6 -MCR1_8.TXRQ1 5 -MCR1_8.TXRQ0 4 -MCR1_8.MSGLSTCPUUPD1 3 -MCR1_8.MSGLSTCPUUPD0 2 -MCR1_8.NEWDAT1 1 -MCR1_8.NEWDAT0 0 -UAR0_8 0xF782 Upper Arbitration Register Low -UAR0_8.ID28 7 -UAR0_8.ID27 6 -UAR0_8.ID26 5 -UAR0_8.ID25 4 -UAR0_8.ID24 3 -UAR0_8.ID23 2 -UAR0_8.ID22 1 -UAR0_8.ID21 0 -UAR1_8 0xF783 Upper Arbitration Register High -UAR1_8.ID20 7 -UAR1_8.ID19 6 -UAR1_8.ID18 5 -UAR1_8.ID17 4 -UAR1_8.ID16 3 -UAR1_8.ID15 2 -UAR1_8.ID14 1 -UAR1_8.ID13 0 -LAR0_8 0xF784 Lower Arbitration Register Low -LAR0_8.ID12 7 -LAR0_8.ID11 6 -LAR0_8.ID10 5 -LAR0_8.ID9 4 -LAR0_8.ID8 3 -LAR0_8.ID7 2 -LAR0_8.ID6 1 -LAR0_8.ID5 0 -LAR1_8 0xF785 Lower Arbitration Register High -LAR1_8.ID4 7 -LAR1_8.ID3 6 -LAR1_8.ID2 5 -LAR1_8.ID1 4 -LAR1_8.ID0 3 -MCFG_8 0xF786 Message Configuration Register -MCFG_8.DLC7 7 -MCFG_8.DLC6 6 -MCFG_8.DLC5 5 -MCFG_8.DLC4 4 -MCFG_8.DIR 3 -MCFG_8.XTD 2 -DB0_8 0xF787 Message Data Byte 0 -DB0_8.DB07 7 -DB0_8.DB06 6 -DB0_8.DB05 5 -DB0_8.DB04 4 -DB0_8.DB03 3 -DB0_8.DB02 2 -DB0_8.DB01 1 -DB0_8.DB00 0 -DB1_8 0xF788 Message Data Byte 1 -DB1_8.DB17 7 -DB1_8.DB16 6 -DB1_8.DB15 5 -DB1_8.DB14 4 -DB1_8.DB13 3 -DB1_8.DB12 2 -DB1_8.DB11 1 -DB1_8.DB10 0 -DB2_8 0xF789 Message Data Byte 2 -DB2_8.DB27 7 -DB2_8.DB26 6 -DB2_8.DB25 5 -DB2_8.DB24 4 -DB2_8.DB23 3 -DB2_8.DB22 2 -DB2_8.DB21 1 -DB2_8.DB20 0 -DB3_8 0xF78A Message Data Byte 3 -DB3_8.DB37 7 -DB3_8.DB36 6 -DB3_8.DB35 5 -DB3_8.DB34 4 -DB3_8.DB33 3 -DB3_8.DB32 2 -DB3_8.DB31 1 -DB3_8.DB30 0 -DB4_8 0xF78B Message Data Byte 4 -DB4_8.DB47 7 -DB4_8.DB46 6 -DB4_8.DB45 5 -DB4_8.DB44 4 -DB4_8.DB43 3 -DB4_8.DB42 2 -DB4_8.DB41 1 -DB4_8.DB40 0 -DB5_8 0xF78C Message Data Byte 5 -DB5_8.DB57 7 -DB5_8.DB56 6 -DB5_8.DB55 5 -DB5_8.DB54 4 -DB5_8.DB53 3 -DB5_8.DB52 2 -DB5_8.DB51 1 -DB5_8.DB50 0 -DB6_8 0xF78D Message Data Byte 6 -DB6_8.DB67 7 -DB6_8.DB66 6 -DB6_8.DB65 5 -DB6_8.DB64 4 -DB6_8.DB63 3 -DB6_8.DB62 2 -DB6_8.DB61 1 -DB6_8.DB60 0 -DB7_8 0xF78E Message Data Byte 7 -DB7_8.DB77 7 -DB7_8.DB76 6 -DB7_8.DB75 5 -DB7_8.DB74 4 -DB7_8.DB73 3 -DB7_8.DB72 2 -DB7_8.DB71 1 -DB7_8.DB70 0 -RESERVEDF78F 0xF78F RESERVED -; -------------------------------------- CAN_9 -------------------------------- -MCR0_9 0xF790 Message Control Register Low -MCR0_9.MSGVAL1 7 -MCR0_9.MSGVAL0 6 -MCR0_9.TXIE1 5 -MCR0_9.TXIE0 4 -MCR0_9.RXIE1 3 -MCR0_9.RXIE0 2 -MCR0_9.INTPND1 1 -MCR0_9.INTPND0 0 -MCR1_9 0xF791 Message Control Register High -MCR1_9.RMTPND1 7 -MCR1_9.RMTPND0 6 -MCR1_9.TXRQ1 5 -MCR1_9.TXRQ0 4 -MCR1_9.MSGLSTCPUUPD1 3 -MCR1_9.MSGLSTCPUUPD0 2 -MCR1_9.NEWDAT1 1 -MCR1_9.NEWDAT0 0 -UAR0_9 0xF792 Upper Arbitration Register Low -UAR0_9.ID28 7 -UAR0_9.ID27 6 -UAR0_9.ID26 5 -UAR0_9.ID25 4 -UAR0_9.ID24 3 -UAR0_9.ID23 2 -UAR0_9.ID22 1 -UAR0_9.ID21 0 -UAR1_9 0xF793 Upper Arbitration Register High -UAR1_9.ID20 7 -UAR1_9.ID19 6 -UAR1_9.ID18 5 -UAR1_9.ID17 4 -UAR1_9.ID16 3 -UAR1_9.ID15 2 -UAR1_9.ID14 1 -UAR1_9.ID13 0 -LAR0_9 0xF794 Lower Arbitration Register Low -LAR0_9.ID12 7 -LAR0_9.ID11 6 -LAR0_9.ID10 5 -LAR0_9.ID9 4 -LAR0_9.ID8 3 -LAR0_9.ID7 2 -LAR0_9.ID6 1 -LAR0_9.ID5 0 -LAR1_9 0xF795 Lower Arbitration Register High -LAR1_9.ID4 7 -LAR1_9.ID3 6 -LAR1_9.ID2 5 -LAR1_9.ID1 4 -LAR1_9.ID0 3 -MCFG_9 0xF796 Message Configuration Register -MCFG_9.DLC7 7 -MCFG_9.DLC6 6 -MCFG_9.DLC5 5 -MCFG_9.DLC4 4 -MCFG_9.DIR 3 -MCFG_9.XTD 2 -DB0_9 0xF797 Message Data Byte 0 -DB0_9.DB07 7 -DB0_9.DB06 6 -DB0_9.DB05 5 -DB0_9.DB04 4 -DB0_9.DB03 3 -DB0_9.DB02 2 -DB0_9.DB01 1 -DB0_9.DB00 0 -DB1_9 0xF798 Message Data Byte 1 -DB1_9.DB17 7 -DB1_9.DB16 6 -DB1_9.DB15 5 -DB1_9.DB14 4 -DB1_9.DB13 3 -DB1_9.DB12 2 -DB1_9.DB11 1 -DB1_9.DB10 0 -DB2_9 0xF799 Message Data Byte 2 -DB2_9.DB27 7 -DB2_9.DB26 6 -DB2_9.DB25 5 -DB2_9.DB24 4 -DB2_9.DB23 3 -DB2_9.DB22 2 -DB2_9.DB21 1 -DB2_9.DB20 0 -DB3_9 0xF79A Message Data Byte 3 -DB3_9.DB37 7 -DB3_9.DB36 6 -DB3_9.DB35 5 -DB3_9.DB34 4 -DB3_9.DB33 3 -DB3_9.DB32 2 -DB3_9.DB31 1 -DB3_9.DB30 0 -DB4_9 0xF79B Message Data Byte 4 -DB4_9.DB47 7 -DB4_9.DB46 6 -DB4_9.DB45 5 -DB4_9.DB44 4 -DB4_9.DB43 3 -DB4_9.DB42 2 -DB4_9.DB41 1 -DB4_9.DB40 0 -DB5_9 0xF79C Message Data Byte 5 -DB5_9.DB57 7 -DB5_9.DB56 6 -DB5_9.DB55 5 -DB5_9.DB54 4 -DB5_9.DB53 3 -DB5_9.DB52 2 -DB5_9.DB51 1 -DB5_9.DB50 0 -DB6_9 0xF79D Message Data Byte 6 -DB6_9.DB67 7 -DB6_9.DB66 6 -DB6_9.DB65 5 -DB6_9.DB64 4 -DB6_9.DB63 3 -DB6_9.DB62 2 -DB6_9.DB61 1 -DB6_9.DB60 0 -DB7_9 0xF79E Message Data Byte 7 -DB7_9.DB77 7 -DB7_9.DB76 6 -DB7_9.DB75 5 -DB7_9.DB74 4 -DB7_9.DB73 3 -DB7_9.DB72 2 -DB7_9.DB71 1 -DB7_9.DB70 0 -RESERVEDF79F 0xF79F RESERVED -; -------------------------------------- CAN_A -------------------------------- -MCR0_A 0xF7A0 Message Control Register Low -MCR0_A.MSGVAL1 7 -MCR0_A.MSGVAL0 6 -MCR0_A.TXIE1 5 -MCR0_A.TXIE0 4 -MCR0_A.RXIE1 3 -MCR0_A.RXIE0 2 -MCR0_A.INTPND1 1 -MCR0_A.INTPND0 0 -MCR1_A 0xF7A1 Message Control Register High -MCR1_A.RMTPND1 7 -MCR1_A.RMTPND0 6 -MCR1_A.TXRQ1 5 -MCR1_A.TXRQ0 4 -MCR1_A.MSGLSTCPUUPD1 3 -MCR1_A.MSGLSTCPUUPD0 2 -MCR1_A.NEWDAT1 1 -MCR1_A.NEWDAT0 0 -UAR0_A 0xF7A2 Upper Arbitration Register Low -UAR0_A.ID28 7 -UAR0_A.ID27 6 -UAR0_A.ID26 5 -UAR0_A.ID25 4 -UAR0_A.ID24 3 -UAR0_A.ID23 2 -UAR0_A.ID22 1 -UAR0_A.ID21 0 -UAR1_A 0xF7A3 Upper Arbitration Register High -UAR1_A.ID20 7 -UAR1_A.ID19 6 -UAR1_A.ID18 5 -UAR1_A.ID17 4 -UAR1_A.ID16 3 -UAR1_A.ID15 2 -UAR1_A.ID14 1 -UAR1_A.ID13 0 -LAR0_A 0xF7A4 Lower Arbitration Register Low -LAR0_A.ID12 7 -LAR0_A.ID11 6 -LAR0_A.ID10 5 -LAR0_A.ID9 4 -LAR0_A.ID8 3 -LAR0_A.ID7 2 -LAR0_A.ID6 1 -LAR0_A.ID5 0 -LAR1_A 0xF7A5 Lower Arbitration Register High -LAR1_A.ID4 7 -LAR1_A.ID3 6 -LAR1_A.ID2 5 -LAR1_A.ID1 4 -LAR1_A.ID0 3 -MCFG_A 0xF7A6 Message Configuration Register -MCFG_A.DLC7 7 -MCFG_A.DLC6 6 -MCFG_A.DLC5 5 -MCFG_A.DLC4 4 -MCFG_A.DIR 3 -MCFG_A.XTD 2 -DB0_A 0xF7A7 Message Data Byte 0 -DB0_A.DB07 7 -DB0_A.DB06 6 -DB0_A.DB05 5 -DB0_A.DB04 4 -DB0_A.DB03 3 -DB0_A.DB02 2 -DB0_A.DB01 1 -DB0_A.DB00 0 -DB1_A 0xF7A8 Message Data Byte 1 -DB1_A.DB17 7 -DB1_A.DB16 6 -DB1_A.DB15 5 -DB1_A.DB14 4 -DB1_A.DB13 3 -DB1_A.DB12 2 -DB1_A.DB11 1 -DB1_A.DB10 0 -DB2_A 0xF7A9 Message Data Byte 2 -DB2_A.DB27 7 -DB2_A.DB26 6 -DB2_A.DB25 5 -DB2_A.DB24 4 -DB2_A.DB23 3 -DB2_A.DB22 2 -DB2_A.DB21 1 -DB2_A.DB20 0 -DB3_A 0xF7AA Message Data Byte 3 -DB3_A.DB37 7 -DB3_A.DB36 6 -DB3_A.DB35 5 -DB3_A.DB34 4 -DB3_A.DB33 3 -DB3_A.DB32 2 -DB3_A.DB31 1 -DB3_A.DB30 0 -DB4_A 0xF7AB Message Data Byte 4 -DB4_A.DB47 7 -DB4_A.DB46 6 -DB4_A.DB45 5 -DB4_A.DB44 4 -DB4_A.DB43 3 -DB4_A.DB42 2 -DB4_A.DB41 1 -DB4_A.DB40 0 -DB5_A 0xF7AC Message Data Byte 5 -DB5_A.DB57 7 -DB5_A.DB56 6 -DB5_A.DB55 5 -DB5_A.DB54 4 -DB5_A.DB53 3 -DB5_A.DB52 2 -DB5_A.DB51 1 -DB5_A.DB50 0 -DB6_A 0xF7AD Message Data Byte 6 -DB6_A.DB67 7 -DB6_A.DB66 6 -DB6_A.DB65 5 -DB6_A.DB64 4 -DB6_A.DB63 3 -DB6_A.DB62 2 -DB6_A.DB61 1 -DB6_A.DB60 0 -DB7_A 0xF7AE Message Data Byte 7 -DB7_A.DB77 7 -DB7_A.DB76 6 -DB7_A.DB75 5 -DB7_A.DB74 4 -DB7_A.DB73 3 -DB7_A.DB72 2 -DB7_A.DB71 1 -DB7_A.DB70 0 -RESERVEDF7AF 0xF7AF RESERVED -; -------------------------------------- CAN_B -------------------------------- -MCR0_B 0xF7B0 Message Control Register Low -MCR0_B.MSGVAL1 7 -MCR0_B.MSGVAL0 6 -MCR0_B.TXIE1 5 -MCR0_B.TXIE0 4 -MCR0_B.RXIE1 3 -MCR0_B.RXIE0 2 -MCR0_B.INTPND1 1 -MCR0_B.INTPND0 0 -MCR1_B 0xF7B1 Message Control Register High -MCR1_B.RMTPND1 7 -MCR1_B.RMTPND0 6 -MCR1_B.TXRQ1 5 -MCR1_B.TXRQ0 4 -MCR1_B.MSGLSTCPUUPD1 3 -MCR1_B.MSGLSTCPUUPD0 2 -MCR1_B.NEWDAT1 1 -MCR1_B.NEWDAT0 0 -UAR0_B 0xF7B2 Upper Arbitration Register Low -UAR0_B.ID28 7 -UAR0_B.ID27 6 -UAR0_B.ID26 5 -UAR0_B.ID25 4 -UAR0_B.ID24 3 -UAR0_B.ID23 2 -UAR0_B.ID22 1 -UAR0_B.ID21 0 -UAR1_B 0xF7B3 Upper Arbitration Register High -UAR1_B.ID20 7 -UAR1_B.ID19 6 -UAR1_B.ID18 5 -UAR1_B.ID17 4 -UAR1_B.ID16 3 -UAR1_B.ID15 2 -UAR1_B.ID14 1 -UAR1_B.ID13 0 -LAR0_B 0xF7B4 Lower Arbitration Register Low -LAR0_B.ID12 7 -LAR0_B.ID11 6 -LAR0_B.ID10 5 -LAR0_B.ID9 4 -LAR0_B.ID8 3 -LAR0_B.ID7 2 -LAR0_B.ID6 1 -LAR0_B.ID5 0 -LAR1_B 0xF7B5 Lower Arbitration Register High -LAR1_B.ID4 7 -LAR1_B.ID3 6 -LAR1_B.ID2 5 -LAR1_B.ID1 4 -LAR1_B.ID0 3 -MCFG_B 0xF7B6 Message Configuration Register -MCFG_B.DLC7 7 -MCFG_B.DLC6 6 -MCFG_B.DLC5 5 -MCFG_B.DLC4 4 -MCFG_B.DIR 3 -MCFG_B.XTD 2 -DB0_B 0xF7B7 Message Data Byte 0 -DB0_B.DB07 7 -DB0_B.DB06 6 -DB0_B.DB05 5 -DB0_B.DB04 4 -DB0_B.DB03 3 -DB0_B.DB02 2 -DB0_B.DB01 1 -DB0_B.DB00 0 -DB1_B 0xF7B8 Message Data Byte 1 -DB1_B.DB17 7 -DB1_B.DB16 6 -DB1_B.DB15 5 -DB1_B.DB14 4 -DB1_B.DB13 3 -DB1_B.DB12 2 -DB1_B.DB11 1 -DB1_B.DB10 0 -DB2_B 0xF7B9 Message Data Byte 2 -DB2_B.DB27 7 -DB2_B.DB26 6 -DB2_B.DB25 5 -DB2_B.DB24 4 -DB2_B.DB23 3 -DB2_B.DB22 2 -DB2_B.DB21 1 -DB2_B.DB20 0 -DB3_B 0xF7BA Message Data Byte 3 -DB3_B.DB37 7 -DB3_B.DB36 6 -DB3_B.DB35 5 -DB3_B.DB34 4 -DB3_B.DB33 3 -DB3_B.DB32 2 -DB3_B.DB31 1 -DB3_B.DB30 0 -DB4_B 0xF7BB Message Data Byte 4 -DB4_B.DB47 7 -DB4_B.DB46 6 -DB4_B.DB45 5 -DB4_B.DB44 4 -DB4_B.DB43 3 -DB4_B.DB42 2 -DB4_B.DB41 1 -DB4_B.DB40 0 -DB5_B 0xF7BC Message Data Byte 5 -DB5_B.DB57 7 -DB5_B.DB56 6 -DB5_B.DB55 5 -DB5_B.DB54 4 -DB5_B.DB53 3 -DB5_B.DB52 2 -DB5_B.DB51 1 -DB5_B.DB50 0 -DB6_B 0xF7BD Message Data Byte 6 -DB6_B.DB67 7 -DB6_B.DB66 6 -DB6_B.DB65 5 -DB6_B.DB64 4 -DB6_B.DB63 3 -DB6_B.DB62 2 -DB6_B.DB61 1 -DB6_B.DB60 0 -DB7_B 0xF7BE Message Data Byte 7 -DB7_B.DB77 7 -DB7_B.DB76 6 -DB7_B.DB75 5 -DB7_B.DB74 4 -DB7_B.DB73 3 -DB7_B.DB72 2 -DB7_B.DB71 1 -DB7_B.DB70 0 -RESERVEDF7BF 0xF7BF RESERVED -; -------------------------------------- CAN_C -------------------------------- -MCR0_C 0xF7C0 Message Control Register Low -MCR0_C.MSGVAL1 7 -MCR0_C.MSGVAL0 6 -MCR0_C.TXIE1 5 -MCR0_C.TXIE0 4 -MCR0_C.RXIE1 3 -MCR0_C.RXIE0 2 -MCR0_C.INTPND1 1 -MCR0_C.INTPND0 0 -MCR1_C 0xF7C1 Message Control Register High -MCR1_C.RMTPND1 7 -MCR1_C.RMTPND0 6 -MCR1_C.TXRQ1 5 -MCR1_C.TXRQ0 4 -MCR1_C.MSGLSTCPUUPD1 3 -MCR1_C.MSGLSTCPUUPD0 2 -MCR1_C.NEWDAT1 1 -MCR1_C.NEWDAT0 0 -UAR0_C 0xF7C2 Upper Arbitration Register Low -UAR0_C.ID28 7 -UAR0_C.ID27 6 -UAR0_C.ID26 5 -UAR0_C.ID25 4 -UAR0_C.ID24 3 -UAR0_C.ID23 2 -UAR0_C.ID22 1 -UAR0_C.ID21 0 -UAR1_C 0xF7C3 Upper Arbitration Register High -UAR1_C.ID20 7 -UAR1_C.ID19 6 -UAR1_C.ID18 5 -UAR1_C.ID17 4 -UAR1_C.ID16 3 -UAR1_C.ID15 2 -UAR1_C.ID14 1 -UAR1_C.ID13 0 -LAR0_C 0xF7C4 Lower Arbitration Register Low -LAR0_C.ID12 7 -LAR0_C.ID11 6 -LAR0_C.ID10 5 -LAR0_C.ID9 4 -LAR0_C.ID8 3 -LAR0_C.ID7 2 -LAR0_C.ID6 1 -LAR0_C.ID5 0 -LAR1_C 0xF7C5 Lower Arbitration Register High -LAR1_C.ID4 7 -LAR1_C.ID3 6 -LAR1_C.ID2 5 -LAR1_C.ID1 4 -LAR1_C.ID0 3 -MCFG_C 0xF7C6 Message Configuration Register -MCFG_C.DLC7 7 -MCFG_C.DLC6 6 -MCFG_C.DLC5 5 -MCFG_C.DLC4 4 -MCFG_C.DIR 3 -MCFG_C.XTD 2 -DB0_C 0xF7C7 Message Data Byte 0 -DB0_C.DB07 7 -DB0_C.DB06 6 -DB0_C.DB05 5 -DB0_C.DB04 4 -DB0_C.DB03 3 -DB0_C.DB02 2 -DB0_C.DB01 1 -DB0_C.DB00 0 -DB1_C 0xF7C8 Message Data Byte 1 -DB1_C.DB17 7 -DB1_C.DB16 6 -DB1_C.DB15 5 -DB1_C.DB14 4 -DB1_C.DB13 3 -DB1_C.DB12 2 -DB1_C.DB11 1 -DB1_C.DB10 0 -DB2_C 0xF7C9 Message Data Byte 2 -DB2_C.DB27 7 -DB2_C.DB26 6 -DB2_C.DB25 5 -DB2_C.DB24 4 -DB2_C.DB23 3 -DB2_C.DB22 2 -DB2_C.DB21 1 -DB2_C.DB20 0 -DB3_C 0xF7CA Message Data Byte 3 -DB3_C.DB37 7 -DB3_C.DB36 6 -DB3_C.DB35 5 -DB3_C.DB34 4 -DB3_C.DB33 3 -DB3_C.DB32 2 -DB3_C.DB31 1 -DB3_C.DB30 0 -DB4_C 0xF7CB Message Data Byte 4 -DB4_C.DB47 7 -DB4_C.DB46 6 -DB4_C.DB45 5 -DB4_C.DB44 4 -DB4_C.DB43 3 -DB4_C.DB42 2 -DB4_C.DB41 1 -DB4_C.DB40 0 -DB5_C 0xF7CC Message Data Byte 5 -DB5_C.DB57 7 -DB5_C.DB56 6 -DB5_C.DB55 5 -DB5_C.DB54 4 -DB5_C.DB53 3 -DB5_C.DB52 2 -DB5_C.DB51 1 -DB5_C.DB50 0 -DB6_C 0xF7CD Message Data Byte 6 -DB6_C.DB67 7 -DB6_C.DB66 6 -DB6_C.DB65 5 -DB6_C.DB64 4 -DB6_C.DB63 3 -DB6_C.DB62 2 -DB6_C.DB61 1 -DB6_C.DB60 0 -DB7_C 0xF7CE Message Data Byte 7 -DB7_C.DB77 7 -DB7_C.DB76 6 -DB7_C.DB75 5 -DB7_C.DB74 4 -DB7_C.DB73 3 -DB7_C.DB72 2 -DB7_C.DB71 1 -DB7_C.DB70 0 -RESERVEDF7CF 0xF7CF RESERVED -; -------------------------------------- CAN_D -------------------------------- -MCR0_D 0xF7D0 Message Control Register Low -MCR0_D.MSGVAL1 7 -MCR0_D.MSGVAL0 6 -MCR0_D.TXIE1 5 -MCR0_D.TXIE0 4 -MCR0_D.RXIE1 3 -MCR0_D.RXIE0 2 -MCR0_D.INTPND1 1 -MCR0_D.INTPND0 0 -MCR1_D 0xF7D1 Message Control Register High -MCR1_D.RMTPND1 7 -MCR1_D.RMTPND0 6 -MCR1_D.TXRQ1 5 -MCR1_D.TXRQ0 4 -MCR1_D.MSGLSTCPUUPD1 3 -MCR1_D.MSGLSTCPUUPD0 2 -MCR1_D.NEWDAT1 1 -MCR1_D.NEWDAT0 0 -UAR0_D 0xF7D2 Upper Arbitration Register Low -UAR0_D.ID28 7 -UAR0_D.ID27 6 -UAR0_D.ID26 5 -UAR0_D.ID25 4 -UAR0_D.ID24 3 -UAR0_D.ID23 2 -UAR0_D.ID22 1 -UAR0_D.ID21 0 -UAR1_D 0xF7D3 Upper Arbitration Register High -UAR1_D.ID20 7 -UAR1_D.ID19 6 -UAR1_D.ID18 5 -UAR1_D.ID17 4 -UAR1_D.ID16 3 -UAR1_D.ID15 2 -UAR1_D.ID14 1 -UAR1_D.ID13 0 -LAR0_D 0xF7D4 Lower Arbitration Register Low -LAR0_D.ID12 7 -LAR0_D.ID11 6 -LAR0_D.ID10 5 -LAR0_D.ID9 4 -LAR0_D.ID8 3 -LAR0_D.ID7 2 -LAR0_D.ID6 1 -LAR0_D.ID5 0 -LAR1_D 0xF7D5 Lower Arbitration Register High -LAR1_D.ID4 7 -LAR1_D.ID3 6 -LAR1_D.ID2 5 -LAR1_D.ID1 4 -LAR1_D.ID0 3 -MCFG_D 0xF7D6 Message Configuration Register -MCFG_D.DLC7 7 -MCFG_D.DLC6 6 -MCFG_D.DLC5 5 -MCFG_D.DLC4 4 -MCFG_D.DIR 3 -MCFG_D.XTD 2 -DB0_D 0xF7D7 Message Data Byte 0 -DB0_D.DB07 7 -DB0_D.DB06 6 -DB0_D.DB05 5 -DB0_D.DB04 4 -DB0_D.DB03 3 -DB0_D.DB02 2 -DB0_D.DB01 1 -DB0_D.DB00 0 -DB1_D 0xF7D8 Message Data Byte 1 -DB1_D.DB17 7 -DB1_D.DB16 6 -DB1_D.DB15 5 -DB1_D.DB14 4 -DB1_D.DB13 3 -DB1_D.DB12 2 -DB1_D.DB11 1 -DB1_D.DB10 0 -DB2_D 0xF7D9 Message Data Byte 2 -DB2_D.DB27 7 -DB2_D.DB26 6 -DB2_D.DB25 5 -DB2_D.DB24 4 -DB2_D.DB23 3 -DB2_D.DB22 2 -DB2_D.DB21 1 -DB2_D.DB20 0 -DB3_D 0xF7DA Message Data Byte 3 -DB3_D.DB37 7 -DB3_D.DB36 6 -DB3_D.DB35 5 -DB3_D.DB34 4 -DB3_D.DB33 3 -DB3_D.DB32 2 -DB3_D.DB31 1 -DB3_D.DB30 0 -DB4_D 0xF7DB Message Data Byte 4 -DB4_D.DB47 7 -DB4_D.DB46 6 -DB4_D.DB45 5 -DB4_D.DB44 4 -DB4_D.DB43 3 -DB4_D.DB42 2 -DB4_D.DB41 1 -DB4_D.DB40 0 -DB5_D 0xF7DC Message Data Byte 5 -DB5_D.DB57 7 -DB5_D.DB56 6 -DB5_D.DB55 5 -DB5_D.DB54 4 -DB5_D.DB53 3 -DB5_D.DB52 2 -DB5_D.DB51 1 -DB5_D.DB50 0 -DB6_D 0xF7DD Message Data Byte 6 -DB6_D.DB67 7 -DB6_D.DB66 6 -DB6_D.DB65 5 -DB6_D.DB64 4 -DB6_D.DB63 3 -DB6_D.DB62 2 -DB6_D.DB61 1 -DB6_D.DB60 0 -DB7_D 0xF7DE Message Data Byte 7 -DB7_D.DB77 7 -DB7_D.DB76 6 -DB7_D.DB75 5 -DB7_D.DB74 4 -DB7_D.DB73 3 -DB7_D.DB72 2 -DB7_D.DB71 1 -DB7_D.DB70 0 -RESERVEDF7DF 0xF7DF RESERVED -; -------------------------------------- CAN_E -------------------------------- -MCR0_E 0xF7E0 Message Control Register Low -MCR0_E.MSGVAL1 7 -MCR0_E.MSGVAL0 6 -MCR0_E.TXIE1 5 -MCR0_E.TXIE0 4 -MCR0_E.RXIE1 3 -MCR0_E.RXIE0 2 -MCR0_E.INTPND1 1 -MCR0_E.INTPND0 0 -MCR1_E 0xF7E1 Message Control Register High -MCR1_E.RMTPND1 7 -MCR1_E.RMTPND0 6 -MCR1_E.TXRQ1 5 -MCR1_E.TXRQ0 4 -MCR1_E.MSGLSTCPUUPD1 3 -MCR1_E.MSGLSTCPUUPD0 2 -MCR1_E.NEWDAT1 1 -MCR1_E.NEWDAT0 0 -UAR0_E 0xF7E2 Upper Arbitration Register Low -UAR0_E.ID28 7 -UAR0_E.ID27 6 -UAR0_E.ID26 5 -UAR0_E.ID25 4 -UAR0_E.ID24 3 -UAR0_E.ID23 2 -UAR0_E.ID22 1 -UAR0_E.ID21 0 -UAR1_E 0xF7E3 Upper Arbitration Register High -UAR1_E.ID20 7 -UAR1_E.ID19 6 -UAR1_E.ID18 5 -UAR1_E.ID17 4 -UAR1_E.ID16 3 -UAR1_E.ID15 2 -UAR1_E.ID14 1 -UAR1_E.ID13 0 -LAR0_E 0xF7E4 Lower Arbitration Register Low -LAR0_E.ID12 7 -LAR0_E.ID11 6 -LAR0_E.ID10 5 -LAR0_E.ID9 4 -LAR0_E.ID8 3 -LAR0_E.ID7 2 -LAR0_E.ID6 1 -LAR0_E.ID5 0 -LAR1_E 0xF7E5 Lower Arbitration Register High -LAR1_E.ID4 7 -LAR1_E.ID3 6 -LAR1_E.ID2 5 -LAR1_E.ID1 4 -LAR1_E.ID0 3 -MCFG_E 0xF7E6 Message Configuration Register -MCFG_E.DLC7 7 -MCFG_E.DLC6 6 -MCFG_E.DLC5 5 -MCFG_E.DLC4 4 -MCFG_E.DIR 3 -MCFG_E.XTD 2 -DB0_E 0xF7E7 Message Data Byte 0 -DB0_E.DB07 7 -DB0_E.DB06 6 -DB0_E.DB05 5 -DB0_E.DB04 4 -DB0_E.DB03 3 -DB0_E.DB02 2 -DB0_E.DB01 1 -DB0_E.DB00 0 -DB1_E 0xF7E8 Message Data Byte 1 -DB1_E.DB17 7 -DB1_E.DB16 6 -DB1_E.DB15 5 -DB1_E.DB14 4 -DB1_E.DB13 3 -DB1_E.DB12 2 -DB1_E.DB11 1 -DB1_E.DB10 0 -DB2_E 0xF7E9 Message Data Byte 2 -DB2_E.DB27 7 -DB2_E.DB26 6 -DB2_E.DB25 5 -DB2_E.DB24 4 -DB2_E.DB23 3 -DB2_E.DB22 2 -DB2_E.DB21 1 -DB2_E.DB20 0 -DB3_E 0xF7EA Message Data Byte 3 -DB3_E.DB37 7 -DB3_E.DB36 6 -DB3_E.DB35 5 -DB3_E.DB34 4 -DB3_E.DB33 3 -DB3_E.DB32 2 -DB3_E.DB31 1 -DB3_E.DB30 0 -DB4_E 0xF7EB Message Data Byte 4 -DB4_E.DB47 7 -DB4_E.DB46 6 -DB4_E.DB45 5 -DB4_E.DB44 4 -DB4_E.DB43 3 -DB4_E.DB42 2 -DB4_E.DB41 1 -DB4_E.DB40 0 -DB5_E 0xF7EC Message Data Byte 5 -DB5_E.DB57 7 -DB5_E.DB56 6 -DB5_E.DB55 5 -DB5_E.DB54 4 -DB5_E.DB53 3 -DB5_E.DB52 2 -DB5_E.DB51 1 -DB5_E.DB50 0 -DB6_E 0xF7ED Message Data Byte 6 -DB6_E.DB67 7 -DB6_E.DB66 6 -DB6_E.DB65 5 -DB6_E.DB64 4 -DB6_E.DB63 3 -DB6_E.DB62 2 -DB6_E.DB61 1 -DB6_E.DB60 0 -DB7_E 0xF7DE Message Data Byte 7 -DB7_E.DB77 7 -DB7_E.DB76 6 -DB7_E.DB75 5 -DB7_E.DB74 4 -DB7_E.DB73 3 -DB7_E.DB72 2 -DB7_E.DB71 1 -DB7_E.DB70 0 -RESERVEDF7EF 0xF7EF RESERVED -; -------------------------------------- CAN_F -------------------------------- -MCR0_F 0xF7F0 Message Control Register Low -MCR0_F.MSGVAL1 7 -MCR0_F.MSGVAL0 6 -MCR0_F.TXIE1 5 -MCR0_F.TXIE0 4 -MCR0_F.RXIE1 3 -MCR0_F.RXIE0 2 -MCR0_F.INTPND1 1 -MCR0_F.INTPND0 0 -MCR1_F 0xF7F1 Message Control Register High -MCR1_F.RMTPND1 7 -MCR1_F.RMTPND0 6 -MCR1_F.TXRQ1 5 -MCR1_F.TXRQ0 4 -MCR1_F.MSGLSTCPUUPD1 3 -MCR1_F.MSGLSTCPUUPD0 2 -MCR1_F.NEWDAT1 1 -MCR1_F.NEWDAT0 0 -UAR0_F 0xF7F2 Upper Arbitration Register Low -UAR0_F.ID28 7 -UAR0_F.ID27 6 -UAR0_F.ID26 5 -UAR0_F.ID25 4 -UAR0_F.ID24 3 -UAR0_F.ID23 2 -UAR0_F.ID22 1 -UAR0_F.ID21 0 -UAR1_F 0xF7F3 Upper Arbitration Register High -UAR1_F.ID20 7 -UAR1_F.ID19 6 -UAR1_F.ID18 5 -UAR1_F.ID17 4 -UAR1_F.ID16 3 -UAR1_F.ID15 2 -UAR1_F.ID14 1 -UAR1_F.ID13 0 -LAR0_F 0xF7F4 Lower Arbitration Register Low -LAR0_F.ID12 7 -LAR0_F.ID11 6 -LAR0_F.ID10 5 -LAR0_F.ID9 4 -LAR0_F.ID8 3 -LAR0_F.ID7 2 -LAR0_F.ID6 1 -LAR0_F.ID5 0 -LAR1_F 0xF7F5 Lower Arbitration Register High -LAR1_F.ID4 7 -LAR1_F.ID3 6 -LAR1_F.ID2 5 -LAR1_F.ID1 4 -LAR1_F.ID0 3 -MCFG_F 0xF7F6 Message Configuration Register -MCFG_F.DLC7 7 -MCFG_F.DLC6 6 -MCFG_F.DLC5 5 -MCFG_F.DLC4 4 -MCFG_F.DIR 3 -MCFG_F.XTD 2 -DB0_F 0xF7F7 Message Data Byte 0 -DB0_F.DB07 7 -DB0_F.DB06 6 -DB0_F.DB05 5 -DB0_F.DB04 4 -DB0_F.DB03 3 -DB0_F.DB02 2 -DB0_F.DB01 1 -DB0_F.DB00 0 -DB1_F 0xF7F8 Message Data Byte 1 -DB1_F.DB17 7 -DB1_F.DB16 6 -DB1_F.DB15 5 -DB1_F.DB14 4 -DB1_F.DB13 3 -DB1_F.DB12 2 -DB1_F.DB11 1 -DB1_F.DB10 0 -DB2_F 0xF7F9 Message Data Byte 2 -DB2_F.DB27 7 -DB2_F.DB26 6 -DB2_F.DB25 5 -DB2_F.DB24 4 -DB2_F.DB23 3 -DB2_F.DB22 2 -DB2_F.DB21 1 -DB2_F.DB20 0 -DB3_F 0xF7FA Message Data Byte 3 -DB3_F.DB37 7 -DB3_F.DB36 6 -DB3_F.DB35 5 -DB3_F.DB34 4 -DB3_F.DB33 3 -DB3_F.DB32 2 -DB3_F.DB31 1 -DB3_F.DB30 0 -DB4_F 0xF7FB Message Data Byte 4 -DB4_F.DB47 7 -DB4_F.DB46 6 -DB4_F.DB45 5 -DB4_F.DB44 4 -DB4_F.DB43 3 -DB4_F.DB42 2 -DB4_F.DB41 1 -DB4_F.DB40 0 -DB5_F 0xF7FC Message Data Byte 5 -DB5_F.DB57 7 -DB5_F.DB56 6 -DB5_F.DB55 5 -DB5_F.DB54 4 -DB5_F.DB53 3 -DB5_F.DB52 2 -DB5_F.DB51 1 -DB5_F.DB50 0 -DB6_F 0xF7FD Message Data Byte 6 -DB6_F.DB67 7 -DB6_F.DB66 6 -DB6_F.DB65 5 -DB6_F.DB64 4 -DB6_F.DB63 3 -DB6_F.DB62 2 -DB6_F.DB61 1 -DB6_F.DB60 0 -DB7_F 0xF7FE Message Data Byte 7 -DB7_F.DB77 7 -DB7_F.DB76 6 -DB7_F.DB75 5 -DB7_F.DB74 4 -DB7_F.DB73 3 -DB7_F.DB72 2 -DB7_F.DB71 1 -DB7_F.DB70 0 -RESERVEDF7FF 0xF7FF RESERVED - - -.C517 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=10484&parent_oid=13739 -; SAB_80C537.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI0_TI0 0x0023 Serial channel 0 -entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload -entry IADC 0x0043 A/D converter -entry IEX2 0x004B External interrupt 2 -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry RI1_TI1 0x0083 Serial channel 1 -entry CTF 0x009B Compare timer overflow - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -SP 0x0081 Stack Pointer -DPL 0x0082 Data Pointer, Low Byte -DPH 0x0083 Data Pointer, High Byte -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Reg. -PCON 0x0087 Power Control Register -TCON 0x0088 Timer Control Register -TMOD 0x0089 Timer Mode Register -TL0 0x008A Timer 0, Low Byte -TL1 0x008B Timer 1, Low Byte -TH0 0x008C Timer 0, High Byte -TH1 0x008D Timer 1, High Byte -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -RESERVED0091 0x0091 RESERVED -DPSEL 0x0092 Data Pointer Select Register -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -S0CON 0x0098 Serial Channel 0 Control Reg. -S0BUF 0x0099 Serial Channel 0 Buffer Reg. -IEN2 0x009A Interrupt Enable Register 2 -S1CON 0x009B Serial Channel 1 Control Reg. -S1BUF 0x009C Serial Channel 1 Buffer Reg., -S1REL 0x009D Serial Channel 1 Reload Reg., low byte -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IP0 0x00A9 Interrupt Priority Register 0 -S0RELL 0x00AA Serial Channel 0, Reload Reg., low byte -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -RESERVED00B1 0x00B1 RESERVED -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IP1 0x00B9 Interrupt Priority Register 1 -S0RELH 0x00BA Serial Channel 0, Reload Reg., high byte -S1RELH 0x00BB Serial Channel 1, Reload Reg.,high byte -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -CCEN 0x00C1 Comp./Capture Enable Reg. -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -T2CON 0x00C8 Timer 2 Control Register -CC4EN 0x00C9 Comp./Capture Enable 4 Reg. -CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte -CRCH 0x00CB Com./Rel./Capt. Reg. High Byte -TL2 0x00CC Timer 2, Low Byte -TH2 0x00CD Timer 2, High Byte -CCL4 0x00CE Comp./Capture Reg. 4, Low Byte -CCH4 0x00CF Comp./Capture Reg. 4, High Byte -PSW 0x00D0 Program Status Word Register -RESERVED00D1 0x00D1 RESERVED -CML0 0x00D2 Compare Register 0, Low Byte -CMH0 0x00D3 Compare Register 0, High Byte -CML1 0x00D4 Compare Register 1, Low Byte -CMH1 0x00D5 Compare Register 1, High Byte -CML2 0x00D6 Compare Register 2, Low Byte -CMH2 0x00D7 Compare Register 2, High Byte -ADCON0 0x00D8 A/D Converter Control Register 0 -ADDAT 0x00D9 A/D Converter Data Register -DAPR 0x00DA D/AConverter Program Register -P7 0x00DB Port 7, Analog/Digital Input -ADCON1 0x00DC A/D Converter Control Register 1 -P8 0x00DD Port 8, Analog/Digital Input, 4-bit 0DD -CTRELL 0x00DE Com. Timer Rel. Reg., Low Byte -CTRELH 0x00DF Com. Timer Rel. Reg., High Byte -ACC 0x00E0 Accumulator -CTCON 0x00E1 Com. Timer Control Register -CML3 0x00E2 Compare Register 3, Low Byte -CMH3 0x00E3 Compare Register 3, High Byte -CML4 0x00E4 Compare Register 4, Low Byte -CMH4 0x00E5 Compare Register 4, High Byte -CML5 0x00E6 Compare Register 5, Low Byte -CMH5 0x00E7 Compare Register 5, High Byte -P4 0x00E8 Port 4 -MD0 0x00E9 Multiplication/Division Register 0 -MD1 0x00EA Multiplication/Division Register 1 -MD2 0x00EB Multiplication/Division Register 2 -MD3 0x00EC Multiplication/Division Register 3 -MD4 0x00ED Multiplication/Division Register 4 -MD5 0x00EE Multiplication/Division Register 5 -ARCON 0x00EF Arithmetic Control Register -B 0x00F0 B-Register -RESERVED00F1 0x00F1 RESERVED -CML6 0x00F2 Compare Register 6, Low Byte -CMH6 0x00F3 Compare Register 6, High Byte -CML7 0x00F4 Compare Register 7, Low Byte -CMH7 0x00F5 Compare Register 7, High Byte -CMEN 0x00F6 Compare Enable Register -CMSEL 0x00F7 Compare Input Select -P5 0x00F8 Port 5 -RESERVED00F9 0x00F9 RESERVED -P6 0x00FA Port 6 -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C517A -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8041&parent_oid=14402 -; SAF-C517A-LN.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI0_TI0 0x0023 Serial channel 0 -entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload -entry IADC 0x0043 A/D converter -entry IEX2 0x004B External interrupt 2 -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry RI1_TI1 0x0083 Serial channel 1 -entry ICMP0_ICMP7 0x0093 Compare Match Interupt of Compare Registers CM0-CM7 assigned to Timer 2 -entry CTF 0x009B Compare timer overflow -entry ICS 0x00A3 Compare Match Interupt of Compare Register COMSET -entry ICR 0x00AB Compare Match Interupt of Compare Register COMCLR - - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -; WDTREL 0x0083 Watchdog Timer Reload Register -; WDTREL.WDTPSEL 7 -; WDTREL.WDTREL6 6 -; WDTREL.WDTREL5 5 -; WDTREL.WDTREL4 4 -; WDTREL.WDTREL3 3 -; WDTREL.WDTREL2 2 -; WDTREL.WDTREL1 1 -; WDTREL.WDTREL0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -RESERVED0086 0x0086 RESERVED -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_0 7 -TMOD.C_T_0 6 -TMOD.M1_0 5 -TMOD.M0_0 4 -TMOD.GATE_1 3 -TMOD.C_T_1 2 -TMOD.M1_1 1 -TMOD.M0_1 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.T2 7 -P1.CLKOUT 6 -P1.T2EX 5 -P1.INT2 4 -P1.INT6 3 -P1.INT5 2 -P1.INT4 1 -P1.INT3 0 -XPAGE 0x0091 Page Address Register for Extended On-Chip RAM -XPAGE.XPAGE7 7 -XPAGE.XPAGE6 6 -XPAGE.XPAGE5 5 -XPAGE.XPAGE4 4 -XPAGE.XPAGE3 3 -XPAGE.XPAGE2 2 -XPAGE.XPAGE1 1 -XPAGE.XPAGE0 0 -DPSEL 0x0092 Data Pointer Select Register -DPSEL.DPSEL2 2 -DPSEL.DPSEL1 1 -DPSEL.DPSEL0 0 -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -S0CON 0x0098 Serial Channel 0 Control Register -S0CON.SM0 7 -S0CON.SM1 6 -S0CON.SM20 5 -S0CON.REN0 4 -S0CON.TB80 3 -S0CON.RB80 2 -S0CON.TI0 1 -S0CON.RI0 0 -S0BUF 0x0099 Serial Channel 0 Buffer Register -S0BUF.S0BUF7 7 -S0BUF.S0BUF6 6 -S0BUF.S0BUF5 5 -S0BUF.S0BUF4 4 -S0BUF.S0BUF3 3 -S0BUF.S0BUF2 2 -S0BUF.S0BUF1 1 -S0BUF.S0BUF0 0 -IEN2 0x009A Interrupt Enable Register 2 -IEN2.ECR 5 -IEN2.ECS 4 -IEN2.ECT 3 -IEN2.ECMP 2 -IEN2.ES1 0 -S1CON 0x009B Serial Channel 1 Control Register -S1CON.SM 7 -S1CON.SM21 5 -S1CON.REN1 4 -S1CON.TB81 3 -S1CON.RB81 2 -S1CON.TI1 1 -S1CON.RI1 0 -S1BUF 0x009C Serial Channel 1 Buffer Register -S1BUF.S1BUF7 7 -S1BUF.S1BUF6 6 -S1BUF.S1BUF5 5 -S1BUF.S1BUF4 4 -S1BUF.S1BUF3 3 -S1BUF.S1BUF2 2 -S1BUF.S1BUF1 1 -S1BUF.S1BUF0 0 -S1RELL 0x009D Serial Channel 1 Reload Reg., Low Byte -S1RELL.S1RELL7 7 -S1RELL.S1RELL6 6 -S1RELL.S1RELL5 5 -S1RELL.S1RELL4 4 -S1RELL.S1RELL3 3 -S1RELL.S1RELL2 2 -S1RELL.S1RELL1 1 -S1RELL.S1RELL0 0 -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -COMSETL 0x00A1 Compare Set Register Low Byte -COMSETL.COMSETL7 7 -COMSETL.COMSETL6 6 -COMSETL.COMSETL5 5 -COMSETL.COMSETL4 4 -COMSETL.COMSETL3 3 -COMSETL.COMSETL2 2 -COMSETL.COMSETL1 1 -COMSETL.COMSETL0 0 -COMSETH 0x00A2 Compare Set Register, High Byte -COMSETH.COMSETH7 7 -COMSETH.COMSETH6 6 -COMSETH.COMSETH5 5 -COMSETH.COMSETH4 4 -COMSETH.COMSETH3 3 -COMSETH.COMSETH2 2 -COMSETH.COMSETH1 1 -COMSETH.COMSETH0 0 -COMCLRL 0x00A3 Compare Clear Register, Low Byte -COMCLRL.COMCLRL7 7 -COMCLRL.COMCLRL6 6 -COMCLRL.COMCLRL5 5 -COMCLRL.COMCLRL4 4 -COMCLRL.COMCLRL3 3 -COMCLRL.COMCLRL2 2 -COMCLRL.COMCLRL1 1 -COMCLRL.COMCLRL0 0 -COMCLRH 0x00A4 Compare Clear Register, High Byte -COMCLRH.COMCLRH7 7 -COMCLRH.COMCLRH6 6 -COMCLRH.COMCLRH5 5 -COMCLRH.COMCLRH4 4 -COMCLRH.COMCLRH3 3 -COMCLRH.COMCLRH2 2 -COMCLRH.COMCLRH1 1 -COMCLRH.COMCLRH0 0 -SETMSK 0x00A5 Compare Set Mask Register -SETMSK.SETMSK7 7 -SETMSK.SETMSK6 6 -SETMSK.SETMSK5 5 -SETMSK.SETMSK4 4 -SETMSK.SETMSK3 3 -SETMSK.SETMSK2 2 -SETMSK.SETMSK1 1 -SETMSK.SETMSK0 0 -CLRMSK 0x00A6 Compare Clear Mask Register -CLRMSK.CLRMSK7 7 -CLRMSK.CLRMSK6 6 -CLRMSK.CLRMSK5 5 -CLRMSK.CLRMSK4 4 -CLRMSK.CLRMSK3 3 -CLRMSK.CLRMSK2 2 -CLRMSK.CLRMSK1 1 -CLRMSK.CLRMSK0 0 -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.EAL7 7 -IEN0.WDT6 6 -IEN0.ET25 5 -IEN0.ES04 4 -IEN0.ET13 3 -IEN0.EX12 2 -IEN0.ET01 1 -IEN0.EX00 0 -IP0 0x00A9 Interrupt Priority Register 0 -IP0.OWDS 7 -IP0.WDTS 6 -IP0.IP05 5 -IP0.IP04 4 -IP0.IP03 3 -IP0.IP02 2 -IP0.IP01 1 -IP0.IP00 0 -S0RELL 0x00AA Serial Channel 0 Reload Reg., Low Byte -S0RELL.S0RELL7 7 -S0RELL.S0RELL6 6 -S0RELL.S0RELL5 5 -S0RELL.S0RELL4 4 -S0RELL.S0RELL3 3 -S0RELL.S0RELL2 2 -S0RELL.S0RELL1 1 -S0RELL.S0RELL0 0 -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD0 1 -P3.RxD0 0 -SYSCON 0x00B1 System/XRAM Control Register -SYSCON.XMAP1 1 -SYSCON.XMAP0 0 -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IEN1.EXEN2 7 -IEN1.SWDT 6 -IEN1.EX6 5 -IEN1.EX5 4 -IEN1.EX4 3 -IEN1.EX3 2 -IEN1.EX2 1 -IEN1.EADC 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.IP15 5 -IP1.IP14 4 -IP1.IP13 3 -IP1.IP12 2 -IP1.IP11 1 -IP1.IP10 0 -S0RELH 0x00BA Serial Channel 0 Reload Reg., High Byte -S0RELH.S0RELH1 1 -S0RELH.S0RELH0 0 -S1RELH 0x00BB Serial Channel 1 Reload Reg., High Byte -S1RELH.S1RELH1 1 -S1RELH.S1RELH0 0 -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON0 0x00C0 Interrupt Request Control Register 0 -IRCON0.EXF2 7 -IRCON0.TF2 6 -IRCON0.IEX6 5 -IRCON0.IEX5 4 -IRCON0.IEX4 3 -IRCON0.IEX3 2 -IRCON0.IEX2 1 -IRCON0.IADC 0 -CCEN 0x00C1 Compare/Capture Enable Register -CCEN.COCAH3 7 -CCEN.COCAL3 6 -CCEN.COCAH2 5 -CCEN.COCAL2 4 -CCEN.COCAH1 3 -CCEN.COCAL1 2 -CCEN.COCAH0 1 -CCEN.COCAL0 0 -CCL1 0x00C2 Compare/Capture Register 1, Low Byte -CCL1.CCL17 7 -CCL1.CCL16 6 -CCL1.CCL15 5 -CCL1.CCL14 4 -CCL1.CCL13 3 -CCL1.CCL12 2 -CCL1.CCL11 1 -CCL1.CCL10 0 -CCH1 0x00C3 Compare/Capture Register 1, High Byte -CCH1.CCH17 7 -CCH1.CCH16 6 -CCH1.CCH15 5 -CCH1.CCH14 4 -CCH1.CCH13 3 -CCH1.CCH12 2 -CCH1.CCH11 1 -CCH1.CCH10 0 -CCL2 0x00C4 Compare/Capture Register 2, Low Byte -CCL2.CCL27 7 -CCL2.CCL26 6 -CCL2.CCL25 5 -CCL2.CCL24 4 -CCL2.CCL23 3 -CCL2.CCL22 2 -CCL2.CCL21 1 -CCL2.CCL20 0 -CCH2 0x00C5 Compare/Capture Register 2, High Byte -CCH2.CCH27 7 -CCH2.CCH26 6 -CCH2.CCH25 5 -CCH2.CCH24 4 -CCH2.CCH23 3 -CCH2.CCH22 2 -CCH2.CCH21 1 -CCH2.CCH20 0 -CCL3 0x00C6 Compare/Capture Register 1, Low Byte -CCL3.CCL37 7 -CCL3.CCL36 6 -CCL3.CCL35 5 -CCL3.CCL34 4 -CCL3.CCL33 3 -CCL3.CCL32 2 -CCL3.CCL31 1 -CCL3.CCL30 0 -CCH3 0x00C7 Compare/Capture Register 3, High Byte -CCH3.CCH37 7 -CCH3.CCH36 6 -CCH3.CCH35 5 -CCH3.CCH34 4 -CCH3.CCH33 3 -CCH3.CCH32 2 -CCH3.CCH31 1 -CCH3.CCH30 0 -T2CON 0x00C8 Timer 2 Control Register -T2CON.T2PS 7 -T2CON.I3FR 6 -T2CON.I2FR 5 -T2CON.T2R1 4 -T2CON.T2R0 3 -T2CON.T2CM 2 -T2CON.T2I1 1 -T2CON.T2I0 0 -CC4EN 0x00C9 Compare/Capture 4 Enable Register -CC4EN.COCOEN1 7 -CC4EN.COCON2 6 -CC4EN.COCON1 5 -CC4EN.COCON0 4 -CC4EN.COCOEN0 3 -CC4EN.COCAH4 2 -CC4EN.COCAL4 1 -CC4EN.COMO 0 -CRCL 0x00CA Comp./Rel./Capt. Register Low Byte -CRCL.CRCL7 7 -CRCL.CRCL6 6 -CRCL.CRCL5 5 -CRCL.CRCL4 4 -CRCL.CRCL3 3 -CRCL.CRCL2 2 -CRCL.CRCL1 1 -CRCL.CRCL0 0 -CRCH 0x00CB Comp./Rel./Capt. Register High Byte -CRCH.CRCH7 7 -CRCH.CRCH6 6 -CRCH.CRCH5 5 -CRCH.CRCH4 4 -CRCH.CRCH3 3 -CRCH.CRCH2 2 -CRCH.CRCH1 1 -CRCH.CRCH0 0 -TL2 0x00CC Timer 2, Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2, High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -CCL4 0x00CE Compare/Capture Register 4, Low Byte -CCL4.CCL47 7 -CCL4.CCL46 6 -CCL4.CCL45 5 -CCL4.CCL44 4 -CCL4.CCL43 3 -CCL4.CCL42 2 -CCL4.CCL41 1 -CCL4.CCL40 0 -CCH4 0x00CF Compare/Capture Register 4, High Byte -CCH4.CCH47 7 -CCH4.CCH46 6 -CCH4.CCH45 5 -CCH4.CCH44 4 -CCH4.CCH43 3 -CCH4.CCH42 2 -CCH4.CCH41 1 -CCH4.CCH40 0 -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -IRCON1 0x00D1 Interrupt Request Control Register 1 -IRCON1.ICMP7 7 -IRCON1.ICMP6 6 -IRCON1.ICMP5 5 -IRCON1.ICMP4 4 -IRCON1.ICMP3 3 -IRCON1.ICMP2 2 -IRCON1.ICMP1 1 -IRCON1.ICMP0 0 -CML0 0x00D2 Compare Register 0, Low Byte -CML0.CML07 7 -CML0.CML06 6 -CML0.CML05 5 -CML0.CML04 4 -CML0.CML03 3 -CML0.CML02 2 -CML0.CML01 1 -CML0.CML00 0 -CMH0 0x00D3 Compare Register 0, High Byte -CMH0.CMH07 7 -CMH0.CMH06 6 -CMH0.CMH05 5 -CMH0.CMH04 4 -CMH0.CMH03 3 -CMH0.CMH02 2 -CMH0.CMH01 1 -CMH0.CMH00 0 -CML1 0x00D4 Compare Register 1, Low Byte -CML1.CML17 7 -CML1.CML16 6 -CML1.CML15 5 -CML1.CML14 4 -CML1.CML13 3 -CML1.CML12 2 -CML1.CML11 1 -CML1.CML10 0 -CMH1 0x00D5 Compare Register 1, High Byte -CMH1.CMH17 7 -CMH1.CMH16 6 -CMH1.CMH15 5 -CMH1.CMH14 4 -CMH1.CMH13 3 -CMH1.CMH12 2 -CMH1.CMH11 1 -CMH1.CMH10 0 -CML2 0x00D6 Compare Register 2, Low Byte -CML2.CML27 7 -CML2.CML26 6 -CML2.CML25 5 -CML2.CML24 4 -CML2.CML23 3 -CML2.CML22 2 -CML2.CML21 1 -CML2.CML20 0 -CMH2 0x00D7 Compare Register 2, High Byte -CMH2.CMH27 7 -CMH2.CMH26 6 -CMH2.CMH25 5 -CMH2.CMH24 4 -CMH2.CMH23 3 -CMH2.CMH22 2 -CMH2.CMH21 1 -CMH2.CMH20 0 -ADCON0 0x00D8 A/D Converter Control Register 0 -ADCON0.BD 7 -ADCON0.CLK 6 -ADCON0.ADEX 5 -ADCON0.BSY 4 -ADCON0.ADM 3 -ADCON0.MX2 2 -ADCON0.MX1 1 -ADCON0.MX0 0 -ADDATH 0x00D9 A/D Converter Data Register, High Byte -ADDATH.ADDATH9 7 -ADDATH.ADDATH8 6 -ADDATH.ADDATH7 5 -ADDATH.ADDATH6 4 -ADDATH.ADDATH5 3 -ADDATH.ADDATH4 2 -ADDATH.ADDATH3 1 -ADDATH.ADDATH2 0 -ADDATL 0x00DA A/D Converter Data Register, Low Byte -ADDATL.ADDATL1 7 -ADDATL.ADDATL0 6 -P7 0x00DB Port 7, Analog/Digital Input -P7.P77 7 -P7.P76 6 -P7.P75 5 -P7.P74 4 -P7.P73 3 -P7.P72 2 -P7.P71 1 -P7.P70 0 -ADCON1 0x00DC A/D Converter Control Register 1 -ADCON1.ADCL 7 -ADCON1.MX3 3 -ADCON1.MX2 2 -ADCON1.MX1 1 -ADCON1.MX0 0 -P8 0x00DD Port 8, Analog/Digital Input -P8.P83 3 -P8.P82 2 -P8.P81 1 -P8.P80 0 -CTRELL 0x00DE Compare Timer Rel. Register, Low Byte -CTRELL.CTRELL7 7 -CTRELL.CTRELL6 6 -CTRELL.CTRELL5 5 -CTRELL.CTRELL4 4 -CTRELL.CTRELL3 3 -CTRELL.CTRELL2 2 -CTRELL.CTRELL1 1 -CTRELL.CTRELL0 0 -CTRELH 0x00DF Compare Timer Rel. Register, High Byte -CTRELH.CTRELH7 7 -CTRELH.CTRELH6 6 -CTRELH.CTRELH5 5 -CTRELH.CTRELH4 4 -CTRELH.CTRELH3 3 -CTRELH.CTRELH2 2 -CTRELH.CTRELH1 1 -CTRELH.CTRELH0 0 -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -CTCON 0x00E1 Compare Timer Control Register -CTCON.T2PS1 7 -CTCON.ICR 5 -CTCON.ICS 4 -CTCON.CTF 3 -CTCON.CLK2 2 -CTCON.CLK1 1 -CTCON.CLK0 0 -CML3 0x00E2 Compare Register 3, Low Byte -CML3.CML37 7 -CML3.CML36 6 -CML3.CML35 5 -CML3.CML34 4 -CML3.CML33 3 -CML3.CML32 2 -CML3.CML31 1 -CML3.CML30 0 -CMH3 0x00E3 Compare Register 3, High Byte -CMH3.CMH37 7 -CMH3.CMH36 6 -CMH3.CMH35 5 -CMH3.CMH34 4 -CMH3.CMH33 3 -CMH3.CMH32 2 -CMH3.CMH31 1 -CMH3.CMH30 0 -CML4 0x00E4 Compare Register 4, Low Byte -CML4.CML47 7 -CML4.CML46 6 -CML4.CML45 5 -CML4.CML44 4 -CML4.CML43 3 -CML4.CML42 2 -CML4.CML41 1 -CML4.CML40 0 -CMH4 0x00E5 Compare Register 4, High Byte -CMH4.CMH47 7 -CMH4.CMH46 6 -CMH4.CMH45 5 -CMH4.CMH44 4 -CMH4.CMH43 3 -CMH4.CMH42 2 -CMH4.CMH41 1 -CMH4.CMH40 0 -CML5 0x00E6 Compare Register 5, Low Byte -CML5.CML57 7 -CML5.CML56 6 -CML5.CML55 5 -CML5.CML54 4 -CML5.CML53 3 -CML5.CML52 2 -CML5.CML51 1 -CML5.CML50 0 -CMH5 0x00E7 Compare Register 5, High Byte -CMH5.CMH57 7 -CMH5.CMH56 6 -CMH5.CMH55 5 -CMH5.CMH54 4 -CMH5.CMH53 3 -CMH5.CMH52 2 -CMH5.CMH51 1 -CMH5.CMH50 0 -P4 0x00E8 Port 4 -P4.CM7 7 -P4.CM6 6 -P4.CM5 5 -P4.CM4 4 -P4.CM3 3 -P4.CM2 2 -P4.CM1 1 -P4.CM0 0 -MD0 0x00E9 Multiplication/Division Register 0 -MD0.MD07 7 -MD0.MD06 6 -MD0.MD05 5 -MD0.MD04 4 -MD0.MD03 3 -MD0.MD02 2 -MD0.MD01 1 -MD0.MD00 0 -MD1 0x00EA Multiplication/Division Register 1 -MD1.MD17 7 -MD1.MD16 6 -MD1.MD15 5 -MD1.MD14 4 -MD1.MD13 3 -MD1.MD12 2 -MD1.MD11 1 -MD1.MD10 0 -MD2 0x00EB Multiplication/Division Register 2 -MD2.MD27 7 -MD2.MD26 6 -MD2.MD25 5 -MD2.MD24 4 -MD2.MD23 3 -MD2.MD22 2 -MD2.MD21 1 -MD2.MD20 0 -MD3 0x00EC Multiplication/Division Register 3 -MD3.MD37 7 -MD3.MD36 6 -MD3.MD35 5 -MD3.MD34 4 -MD3.MD33 3 -MD3.MD32 2 -MD3.MD31 1 -MD3.MD30 0 -MD4 0x00ED Multiplication/Division Register 4 -MD4.MD47 7 -MD4.MD46 6 -MD4.MD45 5 -MD4.MD44 4 -MD4.MD43 3 -MD4.MD42 2 -MD4.MD41 1 -MD4.MD40 0 -MD5 0x00EE Multiplication/Division Register 5 -MD5.MD57 7 -MD5.MD56 6 -MD5.MD55 5 -MD5.MD54 4 -MD5.MD53 3 -MD5.MD52 2 -MD5.MD51 1 -MD5.MD50 0 -ARCON 0x00EF Arithmetic Control Register -ARCON.MDEF 7 -ARCON.MDOV 6 -ARCON.SLR 5 -ARCON.SC4 4 -ARCON.SC3 3 -ARCON.SC2 2 -ARCON.SC1 1 -ARCON.SC0 0 -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -CML6 0x00F2 Compare Register 6, Low Byte -CML6.CML67 7 -CML6.CML66 6 -CML6.CML65 5 -CML6.CML64 4 -CML6.CML63 3 -CML6.CML62 2 -CML6.CML61 1 -CML6.CML60 0 -CMH6 0x00F3 Compare Register 6, High Byte -CMH6.CMH67 7 -CMH6.CMH66 6 -CMH6.CMH65 5 -CMH6.CMH64 4 -CMH6.CMH63 3 -CMH6.CMH62 2 -CMH6.CMH61 1 -CMH6.CMH60 0 -CML7 0x00F4 Compare Register 7, Low Byte -CML7.CML77 7 -CML7.CML76 6 -CML7.CML75 5 -CML7.CML74 4 -CML7.CML73 3 -CML7.CML72 2 -CML7.CML71 1 -CML7.CML70 0 -CMH7 0x00F5 Compare Register 7, High Byte -CMH7.CMH77 7 -CMH7.CMH76 6 -CMH7.CMH75 5 -CMH7.CMH74 4 -CMH7.CMH73 3 -CMH7.CMH72 2 -CMH7.CMH71 1 -CMH7.CMH70 0 -CMEN 0x00F6 Compare Enable Register -CMEN.CMEN7 7 -CMEN.CMEN6 6 -CMEN.CMEN5 5 -CMEN.CMEN4 4 -CMEN.CMEN3 3 -CMEN.CMEN2 2 -CMEN.CMEN1 1 -CMEN.CMEN0 0 -CMSEL 0x00F7 Compare Input Select -CMSEL.CMSEL7 7 -CMSEL.CMSEL6 6 -CMSEL.CMSEL5 5 -CMSEL.CMSEL4 4 -CMSEL.CMSEL3 3 -CMSEL.CMSEL2 2 -CMSEL.CMSEL1 1 -CMSEL.CMSEL0 0 -P5 0x00F8 Port 5 -P5.CCM7 7 -P5.CCM6 6 -P5.CCM5 5 -P5.CCM4 4 -P5.CCM3 3 -P5.CCM2 2 -P5.CCM1 1 -P5.CCM0 0 -RESERVED00F9 0x00F9 RESERVED -P6 0x00FA Port 6 -P6.P67 7 -P6.P66 6 -P6.P65 5 -P6.P64 4 -P6.P63 3 -P6.TxD1 2 -P6.RxD1 1 -P6.ADST 0 -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C535 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=10483&parent_oid=13738 -; SAB_80C535.pdf -; SAB 80C535: ROM-less version, identical to the SAB 80C515 - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI_TI 0x0023 Serial channel -entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload -entry IADC 0x0043 A/D converter -entry IEX2 0x004B External interrupt 2 -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -SP 0x0081 Stack Pointer -DPL 0x0082 Data Pointer, Low Byte -DPH 0x0083 Data Pointer, High Byte -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -RESERVED0086 0x0086 RESERVED -PCON 0x0087 Power Control Register -TCON 0x0088 Timer Control Register -TMOD 0x0089 Timer Mode Register -TL0 0x008A Timer 0, Low Byte -TL1 0x008B Timer 1, Low Byte -TH0 0x008C Timer 0, High Byte -TH1 0x008D Timer 1, High Byte -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Reg. -SBUF 0x0099 Serial Channel Buffer Reg. -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IP0 0x00A9 Interrupt Priority Register 0 -RESERVED00AA 0x00AA RESERVED -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -RESERVED00B1 0x00B1 RESERVED -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IP1 0x00B9 Interrupt Priority Register 1 -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -CCEN 0x00C1 Comp./Capture Enable Reg. -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -T2CON 0x00C8 Timer 2 Control Register -RESERVED00C9 0x00C9 RESERVED -CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte -CRCH 0x00CB Com./Rel./Capt. Reg. High Byte -TL2 0x00CC Timer 2, Low Byte -TH2 0x00CD Timer 2, High Byte -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -ADCON1 0x00D8 A/D Converter Control Register 1 -ADDAT 0x00D9 A/D Converter Data Register -DAPR 0x00DA D/A Converter Program Register -P6 0x00DB Port 6, Analog/Digital Input -RESERVED00DC 0x00DC RESERVED -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -P4 0x00E8 Port 4 -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B-Register -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -P5 0x00F8 Port 5 -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C537 -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=10484&parent_oid=13739 -; SAB_80C537.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI0_TI0 0x0023 Serial channel 0 -entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload -entry IADC 0x0043 A/D converter -entry IEX2 0x004B External interrupt 2 -entry IEX3 0x0053 External interrupt 3 -entry IEX4 0x005B External interrupt 4 -entry IEX5 0x0063 External interrupt 5 -entry IEX6 0x006B External interrupt 6 -entry RI1_TI1 0x0083 Serial channel 1 -entry CTF 0x009B Compare timer overflow - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -SP 0x0081 Stack Pointer -DPL 0x0082 Data Pointer, Low Byte -DPH 0x0083 Data Pointer, High Byte -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Reg. -PCON 0x0087 Power Control Register -TCON 0x0088 Timer Control Register -TMOD 0x0089 Timer Mode Register -TL0 0x008A Timer 0, Low Byte -TL1 0x008B Timer 1, Low Byte -TH0 0x008C Timer 0, High Byte -TH1 0x008D Timer 1, High Byte -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -RESERVED0091 0x0091 RESERVED -DPSEL 0x0092 Data Pointer Select Register -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -S0CON 0x0098 Serial Channel 0 Control Reg. -S0BUF 0x0099 Serial Channel 0 Buffer Reg. -IEN2 0x009A Interrupt Enable Register 2 -S1CON 0x009B Serial Channel 1 Control Reg. -S1BUF 0x009C Serial Channel 1 Buffer Reg., -S1REL 0x009D Serial Channel 1 Reload Reg., low byte -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IP0 0x00A9 Interrupt Priority Register 0 -S0RELL 0x00AA Serial Channel 0, Reload Reg., low byte -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -RESERVED00B1 0x00B1 RESERVED -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IEN1 0x00B8 Interrupt Enable Register 1 -IP1 0x00B9 Interrupt Priority Register 1 -S0RELH 0x00BA Serial Channel 0, Reload Reg., high byte -S1RELH 0x00BB Serial Channel 1, Reload Reg.,high byte -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -IRCON 0x00C0 Interrupt Request Control Register -CCEN 0x00C1 Comp./Capture Enable Reg. -CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte -CCH1 0x00C3 Comp./Capture Reg. 1, High Byte -CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte -CCH2 0x00C5 Comp./Capture Reg. 2, High Byte -CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte -CCH3 0x00C7 Comp./Capture Reg. 3, High Byte -T2CON 0x00C8 Timer 2 Control Register -CC4EN 0x00C9 Comp./Capture Enable 4 Reg. -CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte -CRCH 0x00CB Com./Rel./Capt. Reg. High Byte -TL2 0x00CC Timer 2, Low Byte -TH2 0x00CD Timer 2, High Byte -CCL4 0x00CE Comp./Capture Reg. 4, Low Byte -CCH4 0x00CF Comp./Capture Reg. 4, High Byte -PSW 0x00D0 Program Status Word Register -RESERVED00D1 0x00D1 RESERVED -CML0 0x00D2 Compare Register 0, Low Byte -CMH0 0x00D3 Compare Register 0, High Byte -CML1 0x00D4 Compare Register 1, Low Byte -CMH1 0x00D5 Compare Register 1, High Byte -CML2 0x00D6 Compare Register 2, Low Byte -CMH2 0x00D7 Compare Register 2, High Byte -ADCON0 0x00D8 A/D Converter Control Register 0 -ADDAT 0x00D9 A/D Converter Data Register -DAPR 0x00DA D/AConverter Program Register -P7 0x00DB Port 7, Analog/Digital Input -ADCON1 0x00DC A/D Converter Control Register 1 -P8 0x00DD Port 8, Analog/Digital Input, 4-bit 0DD -CTRELL 0x00DE Com. Timer Rel. Reg., Low Byte -CTRELH 0x00DF Com. Timer Rel. Reg., High Byte -ACC 0x00E0 Accumulator -CTCON 0x00E1 Com. Timer Control Register -CML3 0x00E2 Compare Register 3, Low Byte -CMH3 0x00E3 Compare Register 3, High Byte -CML4 0x00E4 Compare Register 4, Low Byte -CMH4 0x00E5 Compare Register 4, High Byte -CML5 0x00E6 Compare Register 5, Low Byte -CMH5 0x00E7 Compare Register 5, High Byte -P4 0x00E8 Port 4 -MD0 0x00E9 Multiplication/Division Register 0 -MD1 0x00EA Multiplication/Division Register 1 -MD2 0x00EB Multiplication/Division Register 2 -MD3 0x00EC Multiplication/Division Register 3 -MD4 0x00ED Multiplication/Division Register 4 -MD5 0x00EE Multiplication/Division Register 5 -ARCON 0x00EF Arithmetic Control Register -B 0x00F0 B-Register -RESERVED00F1 0x00F1 RESERVED -CML6 0x00F2 Compare Register 6, Low Byte -CMH6 0x00F3 Compare Register 6, High Byte -CML7 0x00F4 Compare Register 7, Low Byte -CMH7 0x00F5 Compare Register 7, High Byte -CMEN 0x00F6 Compare Enable Register -CMSEL 0x00F7 Compare Input Select -P5 0x00F8 Port 5 -RESERVED00F9 0x00F9 RESERVED -P6 0x00FA Port 6 -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FE 0x00FE RESERVED -RESERVED00FF 0x00FF RESERVED - - -.C541U -; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=28987&parent_oid=12071 -; SAB-C541U-1EN.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External Interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External Interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry TC_WCOL 0x0043 SSC Interrupt -entry EPIR0_4 0x004B USB Endpoint Interrupt -entry DIRR 0x0053 USB Device Interrupt -entry WAKE_UP 0x007B Wake-up from power down - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -WDTREL 0x0086 Watchdog Timer Reload Register -WDTREL.WDTPSEL 7 -WDTREL.WDTREL6 6 -WDTREL.WDTREL5 5 -WDTREL.WDTREL4 4 -WDTREL.WDTREL3 3 -WDTREL.WDTREL2 2 -WDTREL.WDTREL1 1 -WDTREL.WDTREL0 0 -PCON 0x0087 Power Control Register -PCON.PDS 6 -PCON.IDLS 5 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -; PCON1 0x0088 Power Control Register 1 -; PCON1.EWPD 7 -; PCON1.WS 4 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.P17 7 -P1.P16 6 -P1.SLS 5 -P1.STO 4 -P1.SRI 3 -P1.SCLK 2 -P1.LED1 1 -P1.LED0 0 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -SSCCON 0x0093 SSC Control Register -SSCCON.SCEN 7 -SSCCON.TEN 6 -SSCCON.MSTR 5 -SSCCON.CPOL 4 -SSCCON.CPHA 3 -SSCCON.BRS2 2 -SSCCON.BRS1 1 -SSCCON.BRS0 0 -STB 0x0094 SSC Transmit Buffer -STB.STB7 7 -STB.STB6 6 -STB.STB5 5 -STB.STB4 4 -STB.STB3 3 -STB.STB2 2 -STB.STB1 1 -STB.STB0 0 -SRB 0x0095 SSC Receive Register -SRB.SRB7 7 -SRB.SRB6 6 -SRB.SRB5 5 -SRB.SRB4 4 -SRB.SRB3 3 -SRB.SRB2 2 -SRB.SRB1 1 -SRB.SRB0 0 -SSCMOD 0x0096 SSC Mode Test Register -SSCMOD.LOOPB 7 -SSCMOD.TRIO 6 -SSCMOD.LSBSM 0 -RESERVED0097 0x0097 RESERVED -RESERVED0098 0x0098 RESERVED -RESERVED0099 0x0099 RESERVED -ITCON 0x009A External Interrupt Trigger Condition Register -ITCON.I1ETF 3 -ITCON.I1ETR 2 -ITCON.I0ETF 1 -ITCON.I0ETR 0 -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IEN0 0x00A8 Interrupt Enable Register 0 -IEN0.ET1 3 -IEN0.EX1 2 -IEN0.ET0 1 -IEN0.EX0 0 -IEN1 0x00A9 Interrupt Enable Register 1 -IEN1.EUDI 2 -IEN1.EUEI 1 -IEN1.ESSC 0 -RESERVED00AA 0x00AA RESERVED -SCF 0x00AB SSC Flag Register -SCF.WCOL 1 -SCF.TC 0 -SCIEN 0x00AC SSC Interrupt Enable Register -SCIEN.WCEN 1 -SCIEN.TCEN 0 -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.DADD 1 -P3.LED2 0 -SYSCON 0x00B1 System Control Register -SYSCON.EALE 5 -SYSCON.RMAP 4 Special function register map bit -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IP0 0x00B8 Interrupt Priority Register 0 -IP0.PT1 3 -IP0.PX1 2 -IP0.PT0 1 -IP0.PX0 0 -IP1 0x00B9 Interrupt Priority Register 1 -IP1.PUDI 2 -IP1.PUEI 1 -IP1.PSSC 0 -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -WDCON 0x00C0 Watchdog Timer Control Register -WDCON.OWDS 3 -WDCON.WDTS 2 -WDCON.WDT 1 -WDCON.SWDT 0 -; FOR EPSEL = 1XXX.XXXX B Device Registers -DCR 0x00C1 USB Device Control Register -DCR.SPEED 7 -DCR.DA 6 -DCR.SWR 5 -DCR.SUSP 4 -DCR.DINIT 3 -DCR.RSM 2 -DCR.UCLK 1 -DCR.PCLK 0 -DPWDR 0x00C2 USB Device Power Down Register -DPWDR.DRVIE 7 -DPWDR.XVREG 6 -DPWDR.TPWD 1 -DPWDR.RPWD 0 -DIER 0x00C3 USB Device Interrupt Control Register -DIER.SE0IE 7 -DIER.DAIE 6 -DIER.DDIE 5 -DIER.SBIE 4 -DIER.SEIE 3 -DIER.STIE 2 -DIER.SUIE 1 -DIER.SOFIE 0 -DIRR 0x00C4 USB Device Interrupt Request Register -DIRR.SE0I 7 -DIRR.DAI 6 -DIRR.DDI 5 -DIRR.SBI 4 -DIRR.SEI 3 -DIRR.STI 2 -DIRR.SUI 1 -DIRR.SOFI 0 -RESERVED00C5 0x00C5 RESERVED -FNRL 0x00C6 USB Frame Number Register, Low Byte -FNRL.FNR7 7 -FNRL.FNR6 6 -FNRL.FNR5 5 -FNRL.FNR4 4 -FNRL.FNR3 3 -FNRL.FNR2 2 -FNRL.FNR1 1 -FNRL.FNR0 0 -FNRH 0x00C7 USB Frame Number Register, High Byte -FNRH.FNR10 2 -FNRH.FNR9 1 -FNRH.FNR8 0 -; FOR EPSEL = 0XXX.X000 B Endpoint 0 Registers -; EPBC0 0x00C1 USB Endpoint 0 Buffer Control Register -; EPBC0.STALL0 7 -; EPBC0.GEPIE0 4 -; EPBC0.SOFDE0 3 -; EPBC0.INCE0 2 -; EPBC0.DBM0 0 -; EPBS0 0x00C2 USB Endpoint 0 Buffer Status Register -; EPBS0.UBF0 7 -; EPBS0.CBF0 6 -; EPBS0.DIR0 5 -; EPBS0.ESP0 4 -; EPBS0.SETRD0 3 -; EPBS0.SETWR0 2 -; EPBS0.CLREP0 1 -; EPBS0.DONE0 0 -; EPIE0 0x00C3 USB Endpoint 0 Interrupt Enable Register -; EPIE0.AIE0 7 -; EPIE0.NAIE0 6 -; EPIE0.RLEIE0 5 -; EPIE0.DNRIE0 3 -; EPIE0.NODIE0 2 -; EPIE0.EODIE0 1 -; EPIE0.SODIE0 0 -; EPIR0 0x00C4 USB Endpoint 0 Interrupt Request Register -; EPIR0.ACK0 7 -; EPIR0.NACK0 6 -; EPIR0.RLE0 5 -; EPIR0.DNR0 3 -; EPIR0.NOD0 2 -; EPIR0.EOD0 1 -; EPIR0.SOD0 0 -; EPBA0 0x00C5 USB Endpoint 0 Base Address Register -; EPBA0.PAGE0 7 -; EPBA0.A06 3 -; EPBA0.A05 2 -; EPBA0.A04 1 -; EPBA0.A03 0 -; EPLEN0 0x00C6 USB Endpoint 0 Buffer Length Register -; EPLEN0.L06 6 -; EPLEN0.L05 5 -; EPLEN0.L04 4 -; EPLEN0.L03 3 -; EPLEN0.L02 2 -; EPLEN0.L01 1 -; EPLEN0.L00 0 -; RESERVED00C7 0x00C7 RESERVED -; FOR EPSEL = 0XXX.X001 B Endpoint 1 Registers -; EPBC1 0x00C1 USB Endpoint 1 Buffer Control Register -; EPBC1.STALL1 7 -; EPBC1.GEPIE1 4 -; EPBC1.SOFDE1 3 -; EPBC1.INCE1 2 -; EPBC1.DBM1 0 -; EPBS1 0x00C2 USB Endpoint 1 Buffer Status Register -; EPBS1.UBF1 7 -; EPBS1.CBF1 6 -; EPBS1.DIR1 5 -; EPBS1.ESP1 4 -; EPBS1.SETRD1 3 -; EPBS1.SETWR1 2 -; EPBS1.CLREP1 1 -; EPBS1.DONE1 0 -; EPIE1 0x00C3 USB Endpoint 1 Interrupt Enable Register -; EPIE1.AIE1 7 -; EPIE1.NAIE1 6 -; EPIE1.RLEIE1 5 -; EPIE1.DNRIE1 3 -; EPIE1.NODIE1 2 -; EPIE1.EODIE1 1 -; EPIE1.SODIE1 0 -; EPIR1 0x00C4 USB Endpoint 1 Interrupt Request Register -; EPIR1.ACK1 7 -; EPIR1.NACK1 6 -; EPIR1.RLE1 5 -; EPIR1.DNR1 3 -; EPIR1.NOD1 2 -; EPIR1.EOD1 1 -; EPIR1.SOD1 0 -; EPBA1 0x00C5 USB Endpoint 1 Base Address Register -; EPBA1.PAGE1 7 -; EPBA1.A16 3 -; EPBA1.A15 2 -; EPBA1.A14 1 -; EPBA1.A13 0 -; EPLEN1 0x00C6 USB Endpoint 1 Buffer Length Register -; EPLEN1.L16 6 -; EPLEN1.L15 5 -; EPLEN1.L14 4 -; EPLEN1.L13 3 -; EPLEN1.L12 2 -; EPLEN1.L11 1 -; EPLEN1.L10 0 -; RESERVED00C7 0x00C7 RESERVED -; FOR EPSEL = 0XXX.X010 B Endpoint 2 Registers -; EPBC2 0x00C1 USB Endpoint 2 Buffer Control Register -; EPBC2.STALL2 7 -; EPBC2.GEPIE2 4 -; EPBC2.SOFDE2 3 -; EPBC2.INCE2 2 -; EPBC2.DBM2 0 -; EPBS2 0x00C2 USB Endpoint 2 Buffer Status Register -; EPBS2.UBF2 7 -; EPBS2.CBF2 6 -; EPBS2.DIR2 5 -; EPBS2.ESP2 4 -; EPBS2.SETRD2 3 -; EPBS2.SETWR2 2 -; EPBS2.CLREP2 1 -; EPBS2.DONE2 0 -; EPIE2 0x00C3 USB Endpoint 2 Interrupt Enable Register -; EPIE2.AIE2 7 -; EPIE2.NAIE2 6 -; EPIE2.RLEIE2 5 -; EPIE2.DNRIE2 3 -; EPIE2.NODIE2 2 -; EPIE2.EODIE2 1 -; EPIE2.SODIE2 0 -; EPIR2 0x00C4 USB Endpoint 2 Interrupt Request Register -; EPIR2.ACK2 7 -; EPIR2.NACK2 6 -; EPIR2.NACK2 5 -; EPIR2.DNR2 3 -; EPIR2.NOD2 2 -; EPIR2.EOD2 1 -; EPIR2.SOD2 0 -; EPBA2 0x00C5 USB Endpoint 2 Base Address Register -; EPBA2.PAGE2 7 -; EPBA2.A62 3 -; EPBA2.A52 2 -; EPBA2.A42 1 -; EPBA2.A32 0 -; EPLEN2 0x00C6 USB Endpoint 2 Buffer Length Register -; EPLEN2.L62 6 -; EPLEN2.L52 5 -; EPLEN2.L42 4 -; EPLEN2.L32 3 -; EPLEN2.L22 2 -; EPLEN2.L12 1 -; EPLEN2.L02 0 -; RESERVED00C7 0x00C7 RESERVED -; FOR EPSEL = 0XXX.X011 B Endpoint 3 Registers -; EPBC3 0x00C1 USB Endpoint 3 Buffer Control Register -; EPBC3.STALL3 7 -; EPBC3.GEPIE3 4 -; EPBC3.SOFDE3 3 -; EPBC3.INCE3 2 -; EPBC3.DBM3 0 -; EPBS3 0x00C2 USB Endpoint 3 Buffer Status Register -; EPBS3.UBF3 7 -; EPBS3.CBF3 6 -; EPBS3.DIR3 5 -; EPBS3.ESP3 4 -; EPBS3.SETRD3 3 -; EPBS3.SETWR3 2 -; EPBS3.CLREP3 1 -; EPBS3.DONE3 0 -; EPIE3 0x00C3 USB Endpoint 3 Interrupt Enable Register -; EPIE3.AIE3 7 -; EPIE3.NAIE3 6 -; EPIE3.RLEIE3 5 -; EPIE3.DNRIE3 3 -; EPIE3.NODIE3 2 -; EPIE3.EODIE3 1 -; EPIE3.SODIE3 0 -; EPIR3 0x00C4 USB Endpoint 3 Interrupt Request Register -; EPIR3.ACK3 7 -; EPIR3.NACK3 6 -; EPIR3.RLE3 5 -; EPIR3.DNR3 3 -; EPIR3.NOD3 2 -; EPIR3.EOD3 1 -; EPIR3.SOD3 0 -; EPBA3 0x00C5 USB Endpoint 3 Base Address Register -; EPBA3.PAGE3 7 -; EPBA3.A63 3 -; EPBA3.A52 2 -; EPBA3.A43 1 -; EPBA3.A33 0 -; EPLEN3 0x00C6 USB Endpoint 3 Buffer Length Register -; EPLEN3.L63 6 -; EPLEN3.L53 5 -; EPLEN3.L43 4 -; EPLEN3.L33 3 -; EPLEN3.L23 2 -; EPLEN3.L13 1 -; EPLEN3.L03 0 -; RESERVED00C7 0x00C7 RESERVED -; FOR EPSEL = 0XXX.X100 B Endpoint 4 Registers -; EPBC4 0x00C1 USB Endpoint 4 Buffer Control Register -; EPBC4.STALL4 7 -; EPBC4.GEPIE4 4 -; EPBC4.SOFDE4 3 -; EPBC4.INCE4 2 -; EPBC4.DBM4 0 -; EPBS4 0x00C2 USB Endpoint 4 Buffer Status Register -; EPBS4.UBF4 7 -; EPBS4.CBF4 6 -; EPBS4.DIR4 5 -; EPBS4.ESP4 4 -; EPBS4.SETRD4 3 -; EPBS4.SETWR4 2 -; EPBS4.CLREP4 1 -; EPBS4.DONE4 0 -; EPIE4 0x00C3 USB Endpoint 4 Interrupt Enable Register -; EPIE4.AIE4 7 -; EPIE4.NAIE4 6 -; EPIE4.RLEIE4 5 -; EPIE4.DNRIE4 3 -; EPIE4.NODIE4 2 -; EPIE4.EODIE4 1 -; EPIE4.SODIE4 0 -; EPIR4 0x00C4 USB Endpoint 4 Interrupt Request Register -; EPIR4.ACK4 7 -; EPIR4.NACK4 6 -; EPIR4.RLE4 5 -; EPIR4.DNR4 3 -; EPIR4.NOD4 2 -; EPIR4.EOD4 1 -; EPIR4.SOD4 0 -; EPBA4 0x00C5 USB Endpoint 4 Base Address Register -; EPBA4.PAGE4 7 -; EPBA4.A64 3 -; EPBA4.A54 2 -; EPBA4.A44 1 -; EPBA4.A34 0 -; EPLEN4 0x00C6 USB Endpoint 4 Buffer Length Register -; EPLEN4.L64 6 -; EPLEN4.L54 5 -; EPLEN4.L44 4 -; EPLEN4.L34 3 -; EPLEN4.L24 2 -; EPLEN4.L14 1 -; EPLEN4.L04 0 -; RESERVED00C7 0x00C7 RESERVED -RESERVED00C8 0x00C8 RESERVED -RESERVED00C9 0x00C9 RESERVED -RESERVED00CA 0x00CA RESERVED -RESERVED00CB 0x00CB RESERVED -RESERVED00CC 0x00CC RESERVED -RESERVED00CD 0x00CD RESERVED -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 Carry Flag -PSW.AC 6 Auxiliary Carry Flag -PSW.F0 5 General Purpose Flag -PSW.RS1 4 Register Bank Select Control Bit 1 -PSW.RS0 3 Register Bank Select Control Bit 0 -PSW.OV 2 Overflow Flag -PSW.F1 1 General Purpose Flag -PSW.P 0 Parity Flag -RESERVED00D1 0x00D1 RESERVED -EPSEL 0x00D2 USB Endpoint Select Register -EPSEL.EPS7 7 -EPSEL.EPS2 2 -EPSEL.EPS1 1 -EPSEL.EPS0 0 -USBVAL 0x00D3 USB Data Register -USBVAL.USBVAL7 7 -USBVAL.USBVAL6 6 -USBVAL.USBVAL5 5 -USBVAL.USBVAL4 4 -USBVAL.USBVAL3 3 -USBVAL.USBVAL2 2 -USBVAL.USBVAL1 1 -USBVAL.USBVAL0 0 -ADROFF 0x00D4 USB Address Offset Register -ADROFF.AO5 5 -ADROFF.AO4 4 -ADROFF.AO3 3 -ADROFF.AO2 2 -ADROFF.AO1 1 -ADROFF.AO0 0 -RESERVED00D5 0x00D5 RESERVED -GEPIR 0x00D6 USB Global Endpoint Interrupt Request Reg. -GEPIR.DRVI 7 -GEPIR.EPI4 4 -GEPIR.EPI3 3 -GEPIR.EPI2 2 -GEPIR.EPI1 1 -GEPIR.EPI0 0 -RESERVED00D7 0x00D7 RESERVED -RESERVED00D8 0x00D8 RESERVED -RESERVED00D9 0x00D9 RESERVED -RESERVED00DA 0x00DA RESERVED -RESERVED00DB 0x00DB RESERVED -RESERVED00DC 0x00DC RESERVED -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -USBPWD 0x00E6 USB Power Down Register -USBPWD.SUSPIE 5 -USBPWD.DADDIE 4 -USBPWD.SUSP 3 -USBPWD.DADD 2 -USBPWD.TPWD 1 -USBPWD.RPWD 0 -USBDCR 0x00E7 USB Control Register -USBDCR.TYPE3 7 -USBDCR.TYPE2 6 -USBDCR.TYPE1 5 -USBDCR.TYPE0 4 -USBDCR.LEN3 3 -USBDCR.LEN2 2 -USBDCR.LEN1 1 -USBDCR.LEN0 0 -USBDR0 0x00E8 USB Data Register 0 -USBDR0.USBDR07 7 -USBDR0.USBDR06 6 -USBDR0.USBDR05 5 -USBDR0.USBDR04 4 -USBDR0.USBDR03 3 -USBDR0.USBDR02 2 -USBDR0.USBDR01 1 -USBDR0.USBDR00 0 -USBDR1 0x00E9 USB Data Register 1 -USBDR1.USBDR17 7 -USBDR1.USBDR16 6 -USBDR1.USBDR15 5 -USBDR1.USBDR14 4 -USBDR1.USBDR13 3 -USBDR1.USBDR12 2 -USBDR1.USBDR11 1 -USBDR1.USBDR10 0 -USBDR2 0x00EA USB Data Register 2 -USBDR2.USBDR27 7 -USBDR2.USBDR26 6 -USBDR2.USBDR25 5 -USBDR2.USBDR24 4 -USBDR2.USBDR23 3 -USBDR2.USBDR22 2 -USBDR2.USBDR21 1 -USBDR2.USBDR20 0 -USBDR3 0x00EB USB Data Register 3 -USBDR3.USBDR37 7 -USBDR3.USBDR36 6 -USBDR3.USBDR35 5 -USBDR3.USBDR34 4 -USBDR3.USBDR33 3 -USBDR3.USBDR32 2 -USBDR3.USBDR31 1 -USBDR3.USBDR30 0 -USBDR4 0x00EC USB Data Register 4 -USBDR4.USBDR47 7 -USBDR4.USBDR46 6 -USBDR4.USBDR45 5 -USBDR4.USBDR44 4 -USBDR4.USBDR43 3 -USBDR4.USBDR42 2 -USBDR4.USBDR41 1 -USBDR4.USBDR40 0 -USBDR5 0x00ED USB Data Register 5 -USBDR5.USBDR57 7 -USBDR5.USBDR56 6 -USBDR5.USBDR55 5 -USBDR5.USBDR54 4 -USBDR5.USBDR53 3 -USBDR5.USBDR52 2 -USBDR5.USBDR51 1 -USBDR5.USBDR50 0 -USBDR6 0x00EE USB Data Register 6 -USBDR6.USBDR67 7 -USBDR6.USBDR66 6 -USBDR6.USBDR65 5 -USBDR6.USBDR64 4 -USBDR6.USBDR63 3 -USBDR6.USBDR62 2 -USBDR6.USBDR61 1 -USBDR6.USBDR60 0 -USBDR7 0x00EF USB Data Register 7 -USBDR7.USBDR77 7 -USBDR7.USBDR76 6 -USBDR7.USBDR75 5 -USBDR7.USBDR74 4 -USBDR7.USBDR73 3 -USBDR7.USBDR72 2 -USBDR7.USBDR71 1 -USBDR7.USBDR70 0 -B 0x00F0 B Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -VR0 0x00FC Version Register 0 -VR1 0x00FD Version Register 1 -VR2 0x00FE Version Register 2 -RESERVED00FF 0x00FF RESERVED - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.AT89S8252 -; http://www.atmel.com/atmel/acrobat/doc0401.pdf -; - -; MEMORY MAP -area CODE code 0x0000:0x2000 -area DATA RAM 0x0000:0x0100 -area DATA FSR 0x0080:0x0100 - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DP0L 0x0082 Data Pointer Low Byte -DP0H 0x0083 Data Pointer High Byte -DP1L 0x0084 Data Pointer 1 Low Byte -DP1H 0x0085 Data Pointer 1 High Byte -SPDR 0x0086 SPI Data Register -PCON 0x0087 Power Control Register -PCON.PDS 6 -PCON.IDLS 5 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Control Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0 Low Byte -TL1 0x008B Timer 1 Low Byte -TH0 0x008c Timer 0 High Byte -TH1 0x008D Timer 1 High Byte - -P1 0x0090 Port 1 -WMCON 0x0096 Watchdog and Memory Control Register -SCON 0x0098 Serial Port Control -SBUF 0x0099 Serial Port Buffer - -P2 0x00A0 Port 2 -IE 0x00A8 Interrupt Enable Register 0 -IE.EA 7 -IE.ET2 5 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 -SPSR 0x00AA SPI Status Register , different to AT89C52 - -P3 0x00B0 Port 3 -IP 0x00B8 Interrupt Priority Register - -T2CON 0x00C8 Timer 2 Control -T2MOD 0x00C9 Timer 2 Mode -RCAP2L 0x00CA Timer 2 Capture Low Byte -RCAP2H 0x00CB Timer 2 Capture High Byte -TL2 0x00CC Timer 2 Low Byte -TH2 0x00CD Timer 2 High Byte - -PSW 0x00D0 Program Status Word -SPCR 0x00D5 SPI Control Register - -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -B 0x00F0 B Register - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -.AT89C2051 -; http://www.atmel.com/atmel/acrobat/doc0368.pdf -; - -; MEMORY MAP -area CODE code 0x0000:0x0800 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 interrupt -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 interrupt -entry RI_TI 0x0023 Serial port interrupt -entry TF2_EXF2 0x002B Timer 2 interrupt - -; INPUT/OUTPUT PORTS - -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 - -DPL 0x0082 Data Pointer Low Byte -DPH 0x0083 Data Pointer High Byte - -PCON 0x0087 Power Control Register -PCON.PDS 6 -PCON.IDLS 5 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 - -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 - -TMOD 0x0089 Timer Mode Control Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 - -TL0 0x008A Timer 0 Low Byte -TL1 0x008B Timer 1 Low Byte -TH0 0x008c Timer 0 High Byte -TH1 0x008D Timer 1 High Byte - -P1 0x0090 Port 1 -P1.P17 7 -P1.P16 6 -P1.P15 5 -P1.P14 4 -P1.P13 3 -P1.P12 2 -P1.P11 1 -P1.P10 0 - -SCON 0x0098 Serial Port Control -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 - -SBUF 0x0099 Serial Port Buffer - -IE 0x00A8 Interrupt Enable Register 0 -IE.EA 7 -IE.ET2 5 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 - -P3 0x00B0 Port 3 -P3.P37 7 -P3.P36 6 -P3.P35 5 -P3.P34 4 -P3.P33 3 -P3.P32 2 -P3.P31 1 -P3.P30 0 - -IP 0x00B8 Interrupt Priority Register -IP.PS 4 -IP.PT1 3 -IP.PX1 2 -IP.PT0 1 -IP.PX0 0 - -PSW 0x00D0 Program Status Word -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.P 0 - -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 - -B 0x00F0 B Register - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -.8032 -; http://www.keil.com/dd/docs/c51/reg52.h - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0100 -area DATA FSR 0x0080:0x0100 - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External Interrupt 0 -entry TF0 0x000B Timer 0 Overflow -entry IE1 0x0013 External Interrupt 1 -entry TF1 0x001B Timer 1 Overflow -entry RI_TI 0x0023 Serial port interrupt -entry TF2_EXF2 0x002B Timer 2 Overflow or TX2 Pin - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -SP.SP7 7 -SP.SP6 6 -SP.SP5 5 -SP.SP4 4 -SP.SP3 3 -SP.SP2 2 -SP.SP1 1 -SP.SP0 0 -DPL 0x0082 Data Pointer, Low Byte -DPL.DPL7 7 -DPL.DPL6 6 -DPL.DPL5 5 -DPL.DPL4 4 -DPL.DPL3 3 -DPL.DPL2 2 -DPL.DPL1 1 -DPL.DPL0 0 -DPH 0x0083 Data Pointer, High Byte -DPH.DPH7 7 -DPH.DPH6 6 -DPH.DPH5 5 -DPH.DPH4 4 -DPH.DPH3 3 -DPH.DPH2 2 -DPH.DPH1 1 -DPH.DPH0 0 -RESERVED0084 0x0084 RESERVED -RESERVED0085 0x0085 RESERVED -RESERVED0086 0x0086 RESERVED -PCON 0x0087 Power Control Register -PCON.PDS 6 -PCON.IDLS 5 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0, Low Byte -TL0.TL07 7 -TL0.TL06 6 -TL0.TL05 5 -TL0.TL04 4 -TL0.TL03 3 -TL0.TL02 2 -TL0.TL01 1 -TL0.TL00 0 -TL1 0x008B Timer 1, Low Byte -TL1.TL17 7 -TL1.TL16 6 -TL1.TL15 5 -TL1.TL14 4 -TL1.TL13 3 -TL1.TL12 2 -TL1.TL11 1 -TL1.TL10 0 -TH0 0x008C Timer 0, High Byte -TH0.TH07 7 -TH0.TH06 6 -TH0.TH05 5 -TH0.TH04 4 -TH0.TH03 3 -TH0.TH02 2 -TH0.TH01 1 -TH0.TH00 0 -TH1 0x008D Timer 1, High Byte -TH1.TH17 7 -TH1.TH16 6 -TH1.TH15 5 -TH1.TH14 4 -TH1.TH13 3 -TH1.TH12 2 -TH1.TH11 1 -TH1.TH10 0 -RESERVED008E 0x008E RESERVED -RESERVED008F 0x008F RESERVED -P1 0x0090 Port 1 -P1.P17 7 -P1.P16 6 -P1.SLS 5 -P1.STO 4 -P1.SRI 3 -P1.SCLK 2 -P1.T2EX 1 -P1.T2 0 -RESERVED0091 0x0091 RESERVED -RESERVED0092 0x0092 RESERVED -RESERVED0093 0x0093 RESERVED -RESERVED0094 0x0094 RESERVED -RESERVED0095 0x0095 RESERVED -RESERVED0096 0x0096 RESERVED -RESERVED0097 0x0097 RESERVED -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM2 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -SBUF.SBUF7 7 -SBUF.SBUF6 6 -SBUF.SBUF5 5 -SBUF.SBUF4 4 -SBUF.SBUF3 3 -SBUF.SBUF2 2 -SBUF.SBUF1 1 -SBUF.SBUF0 0 -RESERVED009A 0x009A RESERVED -RESERVED009B 0x009B RESERVED -RESERVED009C 0x009C RESERVED -RESERVED009D 0x009D RESERVED -RESERVED009E 0x009E RESERVED -RESERVED009F 0x009F RESERVED -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -RESERVED00A1 0x00A1 RESERVED -RESERVED00A2 0x00A2 RESERVED -RESERVED00A3 0x00A3 RESERVED -RESERVED00A4 0x00A4 RESERVED -RESERVED00A5 0x00A5 RESERVED -RESERVED00A6 0x00A6 RESERVED -RESERVED00A7 0x00A7 RESERVED -IE 0x00A8 -IE.EA 7 -IE.ET2 5 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 -RESERVED00A9 0x00A9 RESERVED -RESERVED00AA 0x00AA RESERVED -RESERVED00AB 0x00AB RESERVED -RESERVED00AC 0x00AC RESERVED -RESERVED00AD 0x00AD RESERVED -RESERVED00AE 0x00AE RESERVED -RESERVED00AF 0x00AF RESERVED -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TXD 1 -P3.RXD 0 -RESERVED00B1 0x00B1 RESERVED -RESERVED00B2 0x00B2 RESERVED -RESERVED00B3 0x00B3 RESERVED -RESERVED00B4 0x00B4 RESERVED -RESERVED00B5 0x00B5 RESERVED -RESERVED00B6 0x00B6 RESERVED -RESERVED00B7 0x00B7 RESERVED -IP 0x00B8 Interrupt Priority Register 0 -IP.PT2 5 -IP.PS0 4 -IP.PT1 3 -IP.PX1 2 -IP.PT0 1 -IP.PX0 0 -RESERVED00B9 0x00B9 RESERVED -RESERVED00BA 0x00BA RESERVED -RESERVED00BB 0x00BB RESERVED -RESERVED00BC 0x00BC RESERVED -RESERVED00BD 0x00BD RESERVED -RESERVED00BE 0x00BE RESERVED -RESERVED00BF 0x00BF RESERVED -RESERVED00C0 0x00C0 RESERVED -RESERVED00C1 0x00C1 RESERVED -RESERVED00C2 0x00C2 RESERVED -RESERVED00C3 0x00C3 RESERVED -RESERVED00C4 0x00C4 RESERVED -RESERVED00C5 0x00C5 RESERVED -RESERVED00C6 0x00C6 RESERVED -RESERVED00C7 0x00C7 RESERVED -T2CON 0x00C8 Timer 2 Control Register -T2CON.TF2 7 -T2CON.EXF2 6 -T2CON.RCLK 5 -T2CON.TCLK 4 -T2CON.EXEN2 3 -T2CON.TR2 2 -T2CON.C_T2 1 -T2CON.CP_RL2 0 -RESERVED00C9 0x00C9 RESERVED -RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte -RC2L.RC2L7 7 -RC2L.RC2L6 6 -RC2L.RC2L5 5 -RC2L.RC2L4 4 -RC2L.RC2L3 3 -RC2L.RC2L2 2 -RC2L.RC2L1 1 -RC2L.RC2L0 0 -RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte -RC2H.RC2H7 7 -RC2H.RC2H6 6 -RC2H.RC2H5 5 -RC2H.RC2H4 4 -RC2H.RC2H3 3 -RC2H.RC2H2 2 -RC2H.RC2H1 1 -RC2H.RC2H0 0 -TL2 0x00CC Timer 2 Low Byte -TL2.TL27 7 -TL2.TL26 6 -TL2.TL25 5 -TL2.TL24 4 -TL2.TL23 3 -TL2.TL22 2 -TL2.TL21 1 -TL2.TL20 0 -TH2 0x00CD Timer 2 High Byte -TH2.TH27 7 -TH2.TH26 6 -TH2.TH25 5 -TH2.TH24 4 -TH2.TH23 3 -TH2.TH22 2 -TH2.TH21 1 -TH2.TH20 0 -RESERVED00CE 0x00CE RESERVED -RESERVED00CF 0x00CF RESERVED -PSW 0x00D0 Program Status Word Register -PSW.CY 7 Carry Flag -PSW.AC 6 Auxiliary Carry Flag -PSW.F0 5 General Purpose Flag -PSW.RS1 4 Register Bank Select Control Bit 1 -PSW.RS0 3 Register Bank Select Control Bit 0 -PSW.OV 2 Overflow Flag -PSW.F1 1 General Purpose Flag -PSW.P 0 Parity Flag -RESERVED00D1 0x00D1 RESERVED -RESERVED00D2 0x00D2 RESERVED -RESERVED00D3 0x00D3 RESERVED -RESERVED00D4 0x00D4 RESERVED -RESERVED00D5 0x00D5 RESERVED -RESERVED00D6 0x00D6 RESERVED -RESERVED00D7 0x00D7 RESERVED -RESERVED00D8 0x00D8 RESERVED -RESERVED00D9 0x00D9 RESERVED -RESERVED00DA 0x00DA RESERVED -RESERVED00DB 0x00DB RESERVED -RESERVED00DC 0x00DC RESERVED -RESERVED00DD 0x00DD RESERVED -RESERVED00DE 0x00DE RESERVED -RESERVED00DF 0x00DF RESERVED -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -RESERVED00E1 0x00E1 RESERVED -RESERVED00E2 0x00E2 RESERVED -RESERVED00E3 0x00E3 RESERVED -RESERVED00E4 0x00E4 RESERVED -RESERVED00E5 0x00E5 RESERVED -RESERVED00E6 0x00E6 RESERVED -RESERVED00E7 0x00E7 RESERVED -RESERVED00E8 0x00E8 RESERVED -RESERVED00E9 0x00E9 RESERVED -RESERVED00EA 0x00EA RESERVED -RESERVED00EB 0x00EB RESERVED -RESERVED00EC 0x00EC RESERVED -RESERVED00ED 0x00ED RESERVED -RESERVED00EE 0x00EE RESERVED -RESERVED00EF 0x00EF RESERVED -B 0x00F0 B Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -RESERVED00F1 0x00F1 RESERVED -RESERVED00F2 0x00F2 RESERVED -RESERVED00F3 0x00F3 RESERVED -RESERVED00F4 0x00F4 RESERVED -RESERVED00F5 0x00F5 RESERVED -RESERVED00F6 0x00F6 RESERVED -RESERVED00F7 0x00F7 RESERVED -RESERVED00F8 0x00F8 RESERVED -RESERVED00F9 0x00F9 RESERVED -RESERVED00FA 0x00FA RESERVED -RESERVED00FB 0x00FB RESERVED -RESERVED00FC 0x00FC RESERVED -RESERVED00FD 0x00FD RESERVED -RESERVED00FF 0x00FF RESERVED - -.FX2 -; Cypress EZ-USB FX2 -; http://www.keil.com/dd/docs/datashts/cypress/cy7c68xxx_ds.pdf -; http://www.keil.com/dd/docs/datashts/cypress/fx2_trm.pdf - -; MEMORY MAP -;area CODE code 0x0000:0x10000 -;area DATA RAM 0x0000:0x0080 -;area DATA FSR 0x0080:0x0100 -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0080 -area DATA FSR 0x0080:0x0100 -area DATA FSR 0xe200:0x10000 - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 overflow -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 overflow -entry RI_TI_0 0x0023 USART0 Rx & Tx -entry TF2 0x002B Timer 2 overflow -entry RESUME 0x0033 USB Resume -entry RI_TI_1 0x003B USART1 Rx & Tx -entry USBINT 0x0043 USB -entry I2CINT 0x004B I2C-Compatible Bus -entry IE4 0x0053 GPIF / FIFOs / INT4 Pin -entry IE5 0x005B INT5 Pin -entry IE6 0x0063 INT6 Pin - -; INPUT/OUTPUT PORTS - -IOA 0x0080 Port A -IOA.D7 7 -IOA.D6 6 -IOA.D5 5 -IOA.D4 4 -IOA.D3 3 -IOA.D2 2 -IOA.D1 1 -IOA.D0 0 - -SP 0x0081 Stack Pointer - -DPL0 0x0082 DPTR0 Low Byte -DPH0 0x0083 DPTR0 High Byte -DPL1 0x0084 DPTR1 Low Byte -DPH1 0x0085 DPTR1 High Byte -DPS 0x0086 DPTR Select (bit 0) -PCON 0x0087 Power Control Register -PCON.SMOD0 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Control Register -TMOD.GATE_1 7 -TMOD.C_T_1 6 -TMOD.M1_1 5 -TMOD.M0_1 4 -TMOD.GATE_0 3 -TMOD.C_T_0 2 -TMOD.M1_0 1 -TMOD.M0_0 0 -TL0 0x008A Timer 0 Reload L -TL1 0x008B Timer 1 Reload L -TH0 0x008C Timer 0 Reload H -TH1 0x008D Timer 1 Reload H -CKCON 0x008E Clock Control - -IOB 0x0090 Port B -IOB.D7 7 -IOB.D6 6 -IOB.D5 5 -IOB.D4 4 -IOB.D3 3 -IOB.D2 2 -IOB.D1 1 -IOB.D0 0 - -EXIF 0x0091 External Interrupt Flag(s) -MPAGE 0x0092 Upper Addr Byte of MOVX using @R0/@R1 -SCON0 0x0098 Serial Port 0 Control -SCON0.SM0 7 -SCON0.SM1 6 -SCON0.SM2 5 -SCON0.REN 4 -SCON0.TB8 3 -SCON0.RB8 2 -SCON0.TI 1 -SCON0.RI 0 - -SBUF0 0x0099 Serial Port 0 Data Buffer -AUTOPTRH1 0x009A Autopointer 1 Address HIGH -AUTOPTRL1 0x009B Autopointer 1 Address LOW -AUTOPTRH2 0x009D Autopointer 1 Address HIGH -AUTOPTRL2 0x009E Autopointer 1 Address LOW - -IOC 0x00A0 Port C -IOC.D7 7 -IOC.D6 6 -IOC.D5 5 -IOC.D4 4 -IOC.D3 3 -IOC.D2 2 -IOC.D1 1 -IOC.D0 0 - -INT2CLR 0x00A1 Interrupt 2 clear -INT4CLR 0x00A2 Interrupt 4 clear - -IE 0x00A8 Interrupt Enable -IE.EA 7 -IE.ET2 5 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 - -EP2468STAT 0x00AA Endpoint 2,4,6,8 status flags -EP2468STAT.EP8F 7 -EP2468STAT.EP8E 6 -EP2468STAT.EP6F 5 -EP2468STAT.EP6E 4 -EP2468STAT.EP4F 3 -EP2468STAT.EP4E 2 -EP2468STAT.EP2F 1 -EP2468STAT.EP2E 0 - -EP24FIFOFLGS 0x00AB Endpoint 2,4 slave FIFO status flags -EP24FIFOFLGS.EP4PF 6 -EP24FIFOFLGS.EP4EF 5 -EP24FIFOFLGS.EP4FF 4 -EP24FIFOFLGS.EP2PF 2 -EP24FIFOFLGS.EP2EF 1 -EP24FIFOFLGS.EP2FF 0 - -EP68FIFOFLGS 0x00AC Endpoint 6,8 slave FIFO status flags -EP68FIFOFLGS.EP8PF 6 -EP68FIFOFLGS.EP8EF 5 -EP68FIFOFLGS.EP8FF 4 -EP68FIFOFLGS.EP6PF 2 -EP68FIFOFLGS.EP6EF 1 -EP68FIFOFLGS.EP6FF 0 - -AUTOPTRSETUP 0x00AF Autopointer 1&2 Setup - -IOD 0x00B0 Port D -IOD.D7 7 -IOD.D6 6 -IOD.D5 5 -IOD.D4 4 -IOD.D3 3 -IOD.D2 2 -IOD.D1 1 -IOD.D0 0 - -; port E is not bit-addressable -IOE 0x00B1 Port E - -OEA 0x00B2 Port A Output Enable -OEB 0x00B3 Port B Output Enable -OEC 0x00B4 Port C Output Enable -OED 0x00B5 Port D Output Enable -OEE 0x00B6 Port E Output Enable - -IP 0x00B8 Interrupt Priority Register -IP.PS1 6 -IP.PT2 5 -IP.PS0 4 -IP.PT1 3 -IP.PX1 2 -IP.PT0 1 -IP.PX0 0 - -EP01STAT 0x00ba Endpoint 0 and 1 Status -EP01STAT.EP1INBSY 2 -EP01STAT.EP1OUTBSY 1 -EP01STAT.EP0BSY 0 -GPIFTRIG 0x00bb Endpoint 2, 4, 6, 8 GPIF slave FIFO trigger -GPIFTRIG.DONE 7 -GPIFTRIG.RW 2 -GPIFTRIG.EP1 1 -GPIFTRIG.EP0 0 -GPIFSGLDATH 0x00bd GPIF Data H -GPIFSGLDATL 0x00be GPIF Data L with Trigger -GPIFSGLDATLNOX 0x00bf GPIF Data L with No Trigger - -SCON1 0x00C0 Serial Port 1 Control -SCON1.SM0 7 -SCON1.SM1 6 -SCON1.SM2 5 -SCON1.REN 4 -SCON1.TB8 3 -SCON1.RB8 2 -SCON1.TI 1 -SCON1.RI 0 - -SBUF1 0x00c1 Serial Port 1 Data Buffer -T2CON 0x00c8 Timer/Counter 2 Control -T2CON.TF2 7 -T2CON.EXF2 6 -T2CON.RCLK 5 -T2CON.TCLK 4 -T2CON.EXEN2 3 -T2CON.TR2 2 -T2CON.CT2 1 -T2CON.CPRL2 0 - -RCAP2L 0x00ca Capture for Timer 2, auto-reload, up-counter -RCAP2H 0x00cb Capture for Timer 2, auto-reload, up-counter -TL2 0x00cc Timer 2 reload L -TH2 0x00cd Timer 2 reload H -PSW 0x00d0 Program Status Word -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -EICON 0x00d8 External Interrupt Control -EICON.SMOD1 7 -EICON.ERESI 5 -EICON.RESI 4 -EICON.INT6 3 -ACC 0x00e0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 - -EIE 0x00e8 External Interrupt Enables - -B 0x00F0 B Register -B.D7 7 -B.D6 6 -B.D5 5 -B.D4 4 -B.D3 3 -B.D2 2 -B.D1 1 -B.D0 0 - -EIP 0x00f8 External Interrupt Priority Control - - -.SM5964 -; SyncMOS SM5964 -; http://www.keil.com/dd/chip/3767.htm -; http://www.keil.com/dd/docs/datashts/syncmos/sm5964.pdf - - -; MEMORY MAP -area CODE code 0x0000:0x10000 -area DATA RAM 0x0000:0x0300 -area DATA FSR 0x0080:0x0100 - - -; Interrupt and reset vector assignments -entry RESET 0x0000 RESET -entry IE0 0x0003 External interrupt 0 -entry TF0 0x000B Timer 0 interrupt -entry IE1 0x0013 External interrupt 1 -entry TF1 0x001B Timer 1 interrupt -entry RI_TI 0x0023 Serial port interrupt -entry TF2_EXF2 0x002B Timer 2 interrupt - - -; INPUT/OUTPUT PORTS -P0 0x0080 Port 0 -P0.P07 7 -P0.P06 6 -P0.P05 5 -P0.P04 4 -P0.P03 3 -P0.P02 2 -P0.P01 1 -P0.P00 0 -SP 0x0081 Stack Pointer -DPL 0x0082 Data Pointer, Low Byte -DPH 0x0083 Data Pointer, High Byte -RCON 0x0085 Internal RAM Control Register -RCON.RAMS0 0 -RCON.RAMS1 1 -DBANK 0x0086 Data Bank Control Register -DBANK.BSE 7 -DBANK.BS3 3 -DBANK.BS2 2 -DBANK.BS1 1 -DBANK.BS0 0 -PCON 0x0087 Power Control Register -PCON.SMOD 7 -PCON.PDS 6 -PCON.IDLS 5 -PCON.SD 4 -PCON.GF1 3 -PCON.GF0 2 -PCON.PDE 1 -PCON.IDLE 0 -TCON 0x0088 Timer 0/1 Control Register -TCON.TF1 7 -TCON.TR1 6 -TCON.TF0 5 -TCON.TR0 4 -TCON.IE1 3 -TCON.IT1 2 -TCON.IE0 1 -TCON.IT0 0 -TMOD 0x0089 Timer Mode Register -TMOD.GATE_0 7 -TMOD.C_T_0 6 -TMOD.M1_0 5 -TMOD.M0_0 4 -TMOD.GATE_1 3 -TMOD.C_T_1 2 -TMOD.M1_1 1 -TMOD.M0_1 0 -TL0 0x008A Timer 0, Low Byte -TL1 0x008B Timer 1, Low Byte -TH0 0x008C Timer 0, High Byte -TH1 0x008D Timer 1, High Byte -P1 0x0090 Port 1 -P1.SPWM4 7 -P1.SPWM3 6 -P1.SPWM2 5 -P1.SPWM1 4 -P1.SPWM0 3 -P1.T2EX 1 -P1.T2 0 -SCON 0x0098 Serial Channel Control Register -SCON.SM0 7 -SCON.SM1 6 -SCON.SM3 5 -SCON.REN 4 -SCON.TB8 3 -SCON.RB8 2 -SCON.TI 1 -SCON.RI 0 -SBUF 0x0099 Serial Channel Buffer Register -P1CON 0x009B Port 1 Configuration Register -P1CON.SPWM4E 7 SPWM function for pin SPWM4 -P1CON.SPWM3E 6 SPWM function for pin SPWM3 -P1CON.SPWM2E 5 SPWM function for pin SPWM2 -P1CON.SPWM1E 4 SPWM function for pin SPWM1 -P1CON.SPWM0E 3 SPWM function for pin SPWM0 -WDTC 0x009F Watch Dog Timer Control -WDTC.WDTE 7 Watch Dog Timer enable -WDTC.CLEAR 5 Watch Dog Timer counter clear -WDTC.PS2 2 Watch Dog Timer clock source divider bit 2 -WDTC.PS1 1 Watch Dog Timer clock source divider bit 1 -WDTC.PS0 0 Watch Dog Timer clock source divider bit 0 -P2 0x00A0 Port 2 -P2.P27 7 -P2.P26 6 -P2.P25 5 -P2.P24 4 -P2.P23 3 -P2.P22 2 -P2.P21 1 -P2.P20 0 -SPWMC 0x00A3 -SPWMC.FPDIV1 1 -SPWMC.FPDIV1 0 -SPWMD0 0x00A4 -SPWMD1 0x00A5 -SPWMD2 0x00A6 -SPWMD3 0x00A7 -IE 0x00A8 Interrupt Enable Register -IE.EA 7 -IE.ES 4 -IE.ET1 3 -IE.EX1 2 -IE.ET0 1 -IE.EX0 0 -SPWMD4 0x00AC -P3 0x00B0 Port 3 -P3.RD 7 -P3.WR 6 -P3.T1 5 -P3.T0 4 -P3.INT1 3 -P3.INT0 2 -P3.TxD0 1 -P3.RxD0 0 -IP 0x00B8 Interrupt Priority Register -IP.PS 4 -IP.PT1 3 -IP.PX1 2 -IP.PT0 1 -IP.PX0 0 -SCONF 0x00BF System Control Register -SCONF.WDR 7 Watch Dog Timer Reset. -SCONF.ISPE 2 ISP function enable bit -SCONF.OME 1 768 byte on-chip RAM enable bit -SCONF.ALEI 0 ALE output inhibit bit -T2CON 0x00C8 Timer 2 Control Register -T2CON.TF2 7 -T2CON.EXF2 6 -T2CON.RCLK 5 -T2CON.TCLK 4 -T2CON.EXEN2 3 -T2CON.TR2 2 -T2CON.C_T2 1 -T2CON.CP_RL2 0 -T2MOD 0x00C9 Timer 2 Mode Register -T2MOD.DCEN 0 -T2MOD.T2OE 1 -RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte -RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte -TL2 0x00CC Timer 2 Low Byte -TH2 0x00CD Timer 2 High Byte -PSW 0x00D0 Program Status Word Register -PSW.CY 7 -PSW.AC 6 -PSW.F0 5 -PSW.RS1 4 -PSW.RS0 3 -PSW.OV 2 -PSW.F1 1 -PSW.P 0 -P4 0x00D8 Port 4 -P4.P47 7 -P4.P46 6 -P4.P45 5 -P4.P44 4 -P4.P43 3 -P4.P42 2 -P4.P41 1 -P4.P40 0 -ACC 0x00E0 Accumulator -ACC.ACC7 7 -ACC.ACC6 6 -ACC.ACC5 5 -ACC.ACC4 4 -ACC.ACC3 3 -ACC.ACC2 2 -ACC.ACC1 1 -ACC.ACC0 0 -B 0x00F0 B-Register -B.B7 7 -B.B6 6 -B.B5 5 -B.B4 4 -B.B3 3 -B.B2 2 -B.B1 1 -B.B0 0 -ISPFAH 0x00F4 ISP Flash Address High Register -ISPFAL 0x00F5 ISP Flash Address Low Register -ISPFD 0x00F6 ISP Flash Data Register -ISPC 0x00F7 ISP Flash Control Register -ISPC.START 7 ISP function start bit -ISPC.F1 1 ISP function select bit 1 -ISPC.F0 0 ISP function select bit 0 diff --git a/idasdk75/module/i51/i51.hpp b/idasdk75/module/i51/i51.hpp deleted file mode 100644 index b3100eb..0000000 --- a/idasdk75/module/i51/i51.hpp +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su, ig@datarescue.com - * FIDO: 2:5020/209 - * - */ - -#ifndef _I51_HPP -#define _I51_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -enum processor_subtype_t -{ - // odd types are binary mode - // even types are source modes - prc_51 = 0, // plain 8051 - prc_251_bin, // 80251 in binary mode - prc_251 = prc_251_bin, // the same... (a shortcut) - prc_251_src, // 80251 in source mode - prc_930_bin, // 8x930 in source mode - prc_930 = prc_930_bin, // the same... (a shortcut) - prc_930_src, // 8x930 in source mode - prc_51mx, -}; - -//------------------------------------------------------------------------ -// customization of the 'cmd' structure: - -// 8051 bit references: - -#define o_bit o_idpspec0 -#define o_bitnot o_idpspec1 - -// fRi indirect register number (for o_phrase): -#define indreg specflag1 - -// displacement is an immediate number (print #) (for o_displ): -#define imm_disp specflag1 - -// 80251 bit references (bit address in x.addr): - -#define o_bit251 o_idpspec2 -#define b251_bit specflag1 // bit number -#define b251_bitneg specflag2 // negate? - - -// cmd.auxpref bits: - -#define aux_0ext 0x0001 // high bit 0-extension immediate value -#define aux_1ext 0x0002 // high bit 1-extension immediate value - - -// ash.uflag bit meanings: - -#define UAS_PSAM 0x0001 // PseudoSam: use funny form of - // equ for intmem -#define UAS_SECT 0x0002 // Segments are named .SECTION -#define UAS_NOSEG 0x0004 // No 'segment' directives -#define UAS_NOBIT 0x0008 // No bit.# names, use bit_# -#define UAS_SELSG 0x0010 // Segment should be selected by its name -#define UAS_EQCLN 0x0020 // ':' in EQU directives -#define UAS_AUBIT 0x0040 // Don't use BIT directives - - // assembler generates bit names itself -#define UAS_CDSEG 0x0080 // Only DSEG,CSEG,XSEG -#define UAS_NODS 0x0100 // No .DS directives in Code segment -#define UAS_NOENS 0x0200 // don't specify start addr in the .end directive -#define UAS_PBIT 0x0400 // assembler knows about predefined bits -#define UAS_PBYTNODEF 0x0800 // do not define predefined byte names - -//------------------------------------------------------------------------ -// Registers -enum i51_registers -{ - rAcc, rAB, rB, - rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7, - rR8, rR9, r10, r11, rR12, rR13, rR14, rR15, - rWR0, rWR2, rWR4, rWR6, rWR8, rWR10, rWR12, rWR14, - rWR16, rWR18, rWR20, rWR22, rWR24, rWR26, rWR28, rWR30, - rDR0, rDR4, rDR8, rDR12, rDR16, rDR20, rDR24, rDR28, - rDR32, rDR36, rDR40, rDR44, rDR48, rDR52, rDR56, rDR60, - rDptr, rC, rPC, - rEptr, rPR0, rPR1, // 51mx registers - rVcs, rVds // these 2 registers are required by the IDA kernel -}; - -// Indirect addressing modes without a displacement: -enum i51_phrases -{ - fR0, // @R0 - fR1, // @R1 - fDptr, // @DPTR - fAdptr, // @A+DPTR - fApc, // @A+PC - fRi, // @WRj or @DRj, reg number in indreg - fEptr, // @EPTR - fAeptr, // @A+EPTR - fPr0, // @PR0 - fPr1, // @PR1 -}; - -//------------------------------------------------------------------------ -bool is_sane_insn(const insn_t &insn, int reason); - -//------------------------------------------------------------------ -struct i51_iohandler_t : public iohandler_t -{ - struct i51_t ± - i51_iohandler_t(i51_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual void apply_io_port(ea_t ea, const char *name, const char *cmt) override; - virtual void get_cfg_filename(char *buf, size_t bufsize) override; - virtual bool segment_created(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct i51_t); - -struct i51_t : public procmod_t -{ - netnode helper; - i51_iohandler_t ioh = i51_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - processor_subtype_t ptype = prc_51; - ea_t intmem = 0; // address of the internal memory - ea_t sfrmem = 0; // address of SFR memory - bool flow = false; - bool first_time = true; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - const ioport_bit_t *find_bit(ea_t address, int bit); - bool IsPredefined(const char *name); - ea_t AdditionalSegment(size_t size, size_t offset, const char *name) const; - uint32 truncate(uval_t addr) const; - int ana_extended(insn_t &insn); - void attach_bit_comment(const insn_t &insn, ea_t addr, int bit); - void setup_data_segment_pointers(void); - void i51_header(outctx_t &ctx); - int out_equ(outctx_t &ctx); - void i51_data(outctx_t &ctx, bool analyze_only); - ea_t i51_map_data_ea(const insn_t &insn, ea_t addr, int opnum) const; - void handle_operand(const insn_t &insn, const op_t &x, bool loading); - int emu(const insn_t &insn); - int ana_basic(insn_t &insn); - int ana(insn_t *_insn); - void i51_segstart(outctx_t &ctx, segment_t *Sarea) const; - void i51_footer(outctx_t &ctx) const; - void do_out_equ(outctx_t &ctx, const char *name, const char *equ, uchar off) const; -}; -#endif diff --git a/idasdk75/module/i51/ins.hpp b/idasdk75/module/i51/ins.hpp deleted file mode 100644 index 6aa6700..0000000 --- a/idasdk75/module/i51/ins.hpp +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint8) -{ -I51_null = 0, // Unknown Operation - -I51_acall, // Absolute Call -I51_add, // Add Second Operand to Acc -I51_addc, // Add Second Operand to Acc with carry -I51_ajmp, // Absolute Jump -I51_anl, // Logical AND (op1 &= op2) -I51_cjne, // Compare Operands and JNE -I51_clr, // Clear Operand (0) -I51_cpl, // Complement Operand -I51_da, // Decimal Adjust Accumulator -I51_dec, // Decrement Operand -I51_div, // Divide Acc by B -I51_djnz, // Decrement Operand and JNZ -I51_inc, // Increment Operand -I51_jb, // Jump if Bit is set -I51_jbc, // Jump if Bit is set & clear Bit -I51_jc, // Jump if Carry is set -I51_jmp, // Jump indirect relative to Data Pointer -I51_jnb, // Jump if Bit is clear -I51_jnc, // Jump if Carry is clear -I51_jnz, // Jump if Acc is not zero -I51_jz, // Jump if Acc is zero -I51_lcall, // Long Subroutine Call -I51_ljmp, // Long Jump -I51_mov, // Move (Op1 <- Op2) -I51_movc, // Move code byte relative to second op to Acc -I51_movx, // Move from/to external RAM -I51_mul, // Multiply Acc by B -I51_nop, // No operation -I51_orl, // Logical OR (op1 |= op2) -I51_pop, // Pop from Stack and put in Direct RAM -I51_push, // Push from Direct RAM to Stack -I51_ret, // Return from subroutine -I51_reti, // Return from Interrupt -I51_rl, // Rotate Acc left -I51_rlc, // Rotate Acc left through Carry -I51_rr, // Rotate Acc right -I51_rrc, // Rotate Acc right through Carry -I51_setb, // Set Direct Bit -I51_sjmp, // Short jump -I51_subb, // Subtract Second Operand from Acc with Borrow -I51_swap, // Swap nibbles of Acc -I51_xch, // Exchange Operands -I51_xchd, // Exchange Digit in Acc with Indirect RAM -I51_xrl, // Exclusive OR (op1 ^= op2) - -// 80251 instructions - -I51_jsle, // Jump if less than or equal (signed) -I51_jsg, // Jump if greater than (signed) -I51_jle, // Jump if less than or equal -I51_jg, // Jump if greater than -I51_jsl, // Jump if less than (signed) -I51_jsge, // Jump if greater than or equal (signed) -I51_je, // Jump if equal -I51_jne, // Jump if not equal -I51_trap, // Trap -I51_ejmp, // Extended jump -I51_ecall, // Extended call -I51_eret, // Extended return -I51_movh, // Move immediate 16-bit data to the high word of a dword (double-word) register -I51_movz, // Move 8-bit register to 16-bit register with zero extension -I51_movs, // Move 8-bit register to 16-bit register with sign extension -I51_srl, // Shift logical right by 1 bit -I51_sra, // Shift arithmetic right by 1 bit -I51_sll, // Shift logical left by 1 bit -I51_sub, // Subtract -I51_cmp, // Compare - -// 51mx instructions -I51_emov, // Move (A <- @PRi+disp) or (@PRi+disp <- A) - -I51_last, - - }; - -#endif diff --git a/idasdk75/module/i51/makefile b/idasdk75/module/i51/makefile deleted file mode 100644 index 1b5fb53..0000000 --- a/idasdk75/module/i51/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=i51 -CONFIGS=i51.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp i51.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp emu.cpp i51.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - i51.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - i51.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp i51.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/i51/reg.cpp b/idasdk75/module/i51/reg.cpp deleted file mode 100644 index 9bced0b..0000000 --- a/idasdk75/module/i51/reg.cpp +++ /dev/null @@ -1,891 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su, ig@datarescue.com - * FIDO: 2:50620/209 - * - */ - -#include "i51.hpp" -#include <entry.hpp> -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "A", "AB", "B", - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", - "WR0", "WR2", "WR4", "WR6", "WR8", "WR10", "WR12", "WR14", - "WR16", "WR18", "WR20", "WR22", "WR24", "WR26", "WR28", "WR30", - "DR0", "DR4", "DR8", "DR12", "DR16", "DR20", "DR24", "DR28", - "DR32", "DR36", "DR40", "DR44", "DR48", "DR52", "DPX", "SPX", - "DPTR","C", "PC", - "EPTR", "PR0", "PR1", - "cs","ds" -}; - -//---------------------------------------------------------------------- -static const char cfgname[] = "i51.cfg"; - -void i51_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) -{ - qstrncpy(buf, cfgname, bufsize); -} - -void i51_iohandler_t::apply_io_port(ea_t ea, const char *name, const char *cmt) -{ - if ( ea >= 0x80 && ea < 0x100 ) - { - // specail mapping alg for i51 FSR regs - segment_t *s = get_segm_by_name("FSR"); - if ( s != NULL ) - { - ea_t map = ea + s->start_ea - 0x80; - if ( is_mapped(map) ) - ea = map; - } - } - set_name(ea, name, SN_NODUMMY); - set_cmt(ea, cmt, true); -} - -bool i51_iohandler_t::segment_created(ea_t start, ea_t end, const char *word, const char *) -{ - if ( stristr(word, "FSR") != NULL || stristr(word, "RAM") != NULL ) - { - pm.AdditionalSegment(end-start, start, word); - return true; - } - return false; -} - -//------------------------------------------------------------------ -const char *i51_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT); - return IDPOPT_OK; -} - -//------------------------------------------------------------------ -const ioport_bit_t *i51_t::find_bit(ea_t address, int bit) -{ - return find_ioport_bit(ioh.ports, address, bit); -} - -//---------------------------------------------------------------------- -bool i51_t::IsPredefined(const char *name) -{ - for ( int i=0; i < ioh.ports.size(); i++ ) - { - const ioport_t &p = ioh.ports[i]; - if ( p.name == name ) - return true; - for ( int j=0; j < p.bits.size(); j++ ) - if ( p.bits[j].name == name ) - return true; - } - return false; -} - -//---------------------------------------------------------------------- -struct entry_t -{ - char proc; - char off; - const char *name; //lint !e958 padding is required to align members - const char *cmt; -}; - -static const entry_t entries[] = -{ - { prc_51, 0x03, "extint0", "External interrupt 0 (INT0 / EX0)" }, - { prc_51, 0x0B, "timint0", "Timer interrupt 0 (TIM0)" }, - { prc_51, 0x13, "extint1", "External interrupt 1 (INT1 / EX1)" }, - { prc_51, 0x1B, "timint1", "Timer interrupt 1 (TIM1)" }, - { prc_51, 0x23, "serint", "Serial port interrupt (SERIAL)" }, - { prc_51, 0x2B, "timint2", "Timer interrupt 2 (TIM2) (52 or higher)" }, - { prc_51, 0x33, "pcaint", "PCA (programmable counter array) interrupt\n(only 51f or higher)" }, - { prc_930, 0x43, "usbhub", "USB Hub/SOF (isochronous end point) (only 930)" }, - { prc_930, 0x4B, "usbfun", "USB Function (non-isochronous end point) (only 930)" }, - { prc_930, 0x53, "usbglb", "USB Global Suspend/Resume and USB Reset (only 930)" }, - { prc_251, 0x7B, "trapint", "TRAP (program interrupt) (only 251 or 930)" } -}; - -//---------------------------------------------------------------------- -// Get linear address of a special segment -// sel - selector of the segment -static ea_t specialSeg(segment_t *s) -{ - if ( s->type != SEG_IMEM ) // is the segment type correct? - no - { - s->type = SEG_IMEM; // fix it - s->update(); - } - return s->start_ea; -} - -//---------------------------------------------------------------------- -ea_t i51_t::AdditionalSegment(size_t size, size_t offset, const char *name) const -{ - segment_t s; - s.start_ea = (ptype > prc_51) - ? (inf_get_max_ea() + 0xF) & ~0xF - : free_chunk(0, size, 0xF); - s.end_ea = s.start_ea + size; - s.sel = allocate_selector((s.start_ea-offset) >> 4); - s.type = SEG_IMEM; // internal memory - add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_OR_DIE); - return s.start_ea - offset; -} - -//---------------------------------------------------------------------- -void i51_t::setup_data_segment_pointers(void) -{ - segment_t *s = get_segm_by_name("INTMEM"); - if ( s == NULL ) - s = get_segm_by_name("RAM"); - if ( s != NULL ) - intmem = specialSeg(s); - - s = get_segm_by_name("SFR"); - if ( s == NULL ) - s = get_segm_by_name("FSR"); - if ( s != NULL ) - sfrmem = specialSeg(s) - 0x80; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::segm_moved: // A segment is moved - // Fix processor dependent address sensitive information - { - // ea_t from = va_arg(va, ea_t); - // ea_t to = va_arg(va, ea_t); - // asize_t size = va_arg(va, asize_t); - // bool changed_netmap = va_argi(va, bool); - - // Add commands to adjust your internal variables here - // Most of the time this callback will be empty - // - // If you keep information in a netnode's altval array, you can use - // node.altshift(from, s->start_ea, s->end_ea - s->start_ea); - // - // If you have a variables pointing to somewhere in the disassembled program memory, - // you can adjust it like this: - // - // if ( var >= from && var < from+size ) - // var += to - from; - } - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new i51_t); - return 0; -} - -ssize_t idaapi i51_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ intel 8051"); - inf_set_be(true); // Set a big endian mode of the IDA kernel - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: - { - segment_t *sptr = get_first_seg(); - if ( sptr != NULL ) - { - if ( sptr->start_ea-get_segm_base(sptr) == 0 ) - { - inf_set_start_ea(sptr->start_ea); - inf_set_start_ip(0); - for ( int i=0; i < qnumber(entries); i++ ) - { - if ( entries[i].proc > ptype ) - continue; - ea_t ea = inf_get_start_ea()+entries[i].off; - if ( is_mapped(ea) && get_byte(ea) != 0xFF ) - { - add_entry(ea, ea, entries[i].name, 1); - set_cmt(ea, entries[i].cmt, 1); - } - } - } - } - segment_t *scode = get_first_seg(); - set_segm_class(scode, "CODE"); - - if ( ptype > prc_51 ) - { - AdditionalSegment(0x10000-256-128, 256+128, "RAM"); - if ( scode != NULL ) - { - ea_t align = (scode->end_ea + 0xFFF) & ~0xFFF; - if ( getseg(align-7) == scode ) // the code segment size is - { // multiple of 4K or near it - uchar b0 = get_byte(align-8); - // 251: - // 0 : 1-source, 0-binary mode - // 6,7: must be 1s - // 82930: - // 0 : 1-source, 0-binary mode - // 7 : must be 1s -// uchar b1 = get_byte(align-7); - // 251 - // 0: eprommap 0 - FE2000..FE4000 is mapped into 00E000..100000 - // 1 - .............. is not mapped ............... - // 1: must be 1 - // 3: - // 2: must be 1 - // 4: intr 1 - upon interrupt PC,PSW are pushed into stack - // 0 - upon interrupt only PC is pushed into stack - // 5: must be 1 - // 6: must be 1 - // 7: must be 1 - // 82930: - // 3: must be 1 - // 5: must be 1 - // 6: must be 1 - // 7: must be 1 -// msg("b0=%x b1=%x\n", b0, b1); -// if ( (b0 & 0x80) == 0x80 && (b1 & 0xEA) == 0xEA ) - { // the init bits are correct - char pname[IDAINFO_PROCNAME_SIZE]; - inf_get_procname(pname, sizeof(pname)); - char ntype = (b0 & 1) ? 's' : 'b'; - char *ptr = tail(pname)-1; - if ( ntype != *ptr - && ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "The input file seems to be for the %s mode of the processor.\n" - "Do you want to change the current processor type?", - ntype == 's' ? "source" : "binary") > 0 ) - { - *ptr = ntype; - first_time = true; - set_processor_type(pname, SETPROC_USER); - } - } - } - } - } - - // the default data segment will be INTMEM - { - segment_t *s = getseg(intmem); - if ( s != NULL ) - set_default_dataseg(s->sel); - } - - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - - if ( get_segm_by_name("RAM") == NULL ) - AdditionalSegment(256, 0, "RAM"); - if ( get_segm_by_name("FSR") == NULL ) - AdditionalSegment(128, 128, "FSR"); - setup_data_segment_pointers(); - } - break; - - case processor_t::ev_ending_undo: - // restore ptype - ptype = processor_subtype_t(ph.get_proc_index()); - //fall through - case processor_t::ev_oldfile: - setup_data_segment_pointers(); - break; - - case processor_t::ev_creating_segm: - // make the default DS point to INTMEM - // (8051 specific issue) - { - segment_t *newseg = va_arg(va, segment_t *); - segment_t *intseg = getseg(intmem); - if ( intseg != NULL ) - newseg->defsr[rVds-ph.reg_first_sreg] = intseg->sel; - } - break; - - case processor_t::ev_newprc: - { - processor_subtype_t prcnum = processor_subtype_t(va_arg(va, int)); - // bool keep_cfg = va_argi(va, bool); - if ( !first_time && prcnum != ptype ) - { - warning("Sorry, it is not possible to change" // (this is 8051 specific) - " the processor mode on the fly." - " Please reload the input file" - " if you want to change the processor."); - code = -1; - break; - } - first_time = false; - ptype = prcnum; - } - break; - - case processor_t::ev_newasm: // new assembler type - ioh.restore_device(); - break; - - case processor_t::ev_is_sane_insn: - // is the instruction sane for the current file type? - // arg: int no_crefs - // 1: the instruction has no code refs to it. - // ida just tries to convert unexplored bytes - // to an instruction (but there is no other - // reason to convert them into an instruction) - // -1: the instruction is created because - // of some coderef, user request or another - // weighty reason. - // The instruction is in 'cmd' - // returns: 1-ok, <=0-no, the instruction isn't - // likely to appear in the program - { - const insn_t *insn = va_arg(va, insn_t *); - int reason = va_arg(va, int); - return is_sane_insn(*insn, reason) == 1 ? 1 : -1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - i51_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - i51_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - i51_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - i51_data(*ctx, analyze_only); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// ASMI -//----------------------------------------------------------------------- -static const asm_t asmi = -{ - AS_COLON | ASH_HEXF3 | AS_1TEXT | AS_NCHRE | ASO_OCTF1 | AS_RELSUP, - UAS_PSAM | UAS_NOSEG | UAS_AUBIT | UAS_PBIT | UAS_NOENS, - "ASMI", - 0, - NULL, // no headers - ".equ $, ", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".text", // ascii string directive - ".byte", // byte directive - ".word", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".byte 0xFF;(array %s)", // uninited arrays - ".equ", // equ - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// 8051 Macro Assembler - Version 4.02a -// Copyright (C) 1985 by 2500 A.D. Software, Inc. -//----------------------------------------------------------------------- -static const asm_t adasm = -{ - AS_COLON | ASH_HEXF0, - UAS_PBIT | UAS_SECT, - "8051 Macro Assembler by 2500 A.D. Software", - 0, - NULL, // no headers - "org", - "end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - "long", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "reg", // equ - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof - 0, // flag2 - NULL, // close comment - COLSTR("<", SCOLOR_SYMBOL) "%s", // low8 - COLSTR(">", SCOLOR_SYMBOL) "%s", // high8 - NULL, // low16 - NULL, // high16 -}; - -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const char *const ps_headers[] = -{ - ".code", - NULL -}; - -static const asm_t pseudosam = -{ - AS_COLON | ASH_HEXF1 | AS_N2CHR, - UAS_PBIT | UAS_PSAM | UAS_SELSG, - "PseudoSam by PseudoCode", - 0, - ps_headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".rs %s", // uninited arrays - ".equ", // equ - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// Cross-16 assembler definiton -//----------------------------------------------------------------------- -static const char *const cross16_headers[] = -{ - "cpu \"8051.tbl\"", - NULL -}; - -static const asm_t cross16 = -{ - AS_COLON | ASH_HEXF0 | AS_NHIAS, - UAS_PBIT | UAS_NOSEG | UAS_NOBIT | UAS_EQCLN, - "Cross-16 by Universal Cross-Assemblers", - 0, - cross16_headers, - "org", - "end", - - ";", // comment string - '"', // string delimiter - '\0', // char delimiter (no char consts) - "\\\"'", // special symbols in char and string constants - - "dfb", // ascii string directive - "dfb", // byte directive - "dwm", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// 8051 Cross-Assembler by MetaLink Corporation -//----------------------------------------------------------------------- -static const asm_t mcross = -{ - AS_COLON | ASH_HEXF0 | AS_NHIAS, - UAS_NOSEG | UAS_CDSEG | UAS_AUBIT | UAS_NODS | UAS_NOENS, - "8051 Cross-Assembler by MetaLink Corporation", - 0, - NULL, - "org", - "end", - - ";", // comment string - '\'', // string delimiter - '\0', // char delimiter (no char consts) - "\\\"'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// TASM assembler definiton -//----------------------------------------------------------------------- -static const char *const tasm_headers[] = -{ - ".msfirst", - NULL -}; - -static const asm_t tasm = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_PBIT | UAS_NOENS | UAS_EQCLN | UAS_NOSEG, - "Table Driven Assembler (TASM) by Speech Technology Inc.", - 0, - tasm_headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".text", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".block %s", // uninited arrays - ".equ", - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - "and", // and - "or", // or - NULL, // xor - "not", // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = -{ - &asmi, &adasm, &pseudosam, &cross16, &mcross, &tasm, NULL -}; - -//----------------------------------------------------------------------- -// The short and long names of the supported processors -#define FAMILY "Intel 51 series:" - -static const char *const shnames[] = -{ - "8051", - "80251b", - "80251s", - "80930b", - "80930s", - "8051mx", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Intel 8051", - "Intel 80251 in binary mode", - "Intel 80251 in source mode", - "Intel 80930 in binary mode", - "Intel 80930 in source mode", - "Intel 8051MX", - NULL -}; - -//-------------------------------------------------------------------------- -// Opcodes of "return" instructions. This information will be used in 2 ways: -// - if an instruction has the "return" opcode, its autogenerated label -// will be "locret" rather than "loc". -// - IDA will use the first "return" opcode to create empty subroutines. - -static const uchar retcode_1[] = { 0x22 }; -static const uchar retcode_2[] = { 0x32 }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } // NULL terminated array -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_8051, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_SEGTRANS // segment translation is supported (map_code_ea) - | PR_BINMEM, // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 0, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0,I51_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - I51_ret, // Icode of return instruction. It is ok to give any of possible return instructions - -}; diff --git a/idasdk75/module/i860/emu.cpp b/idasdk75/module/i860/emu.cpp deleted file mode 100644 index 998d916..0000000 --- a/idasdk75/module/i860/emu.cpp +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "i860.hpp" - -//------------------------------------------------------------------------ -static void set_immd_bit(const insn_t &insn) -{ - set_immd(insn.ea); - if ( is_defarg(get_flags(insn.ea), 1) ) - return; - switch ( insn.itype ) - { - case I860_and: - case I860_andh: - case I860_andnot: - case I860_andnoth: - case I860_xor: - case I860_xorh: - op_num(insn.ea, 1); - break; - } -} - -//---------------------------------------------------------------------- -bool i860_t::handle_operand(const insn_t &insn, const op_t &x, bool isload) const -{ - dref_t xreftype; - uchar outf; - switch ( x.type ) - { - case o_phrase: // 2 registers - case o_reg: - break; - case o_imm: - if ( !isload ) - goto badTouch; - xreftype = dr_O; - outf = OOF_SIGNED; - goto makeImm; - case o_displ: - xreftype = isload ? dr_R : dr_W; - outf = OOF_SIGNED|OOF_ADDR; -makeImm: - set_immd_bit(insn); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, xreftype, outf); - break; - case o_mem: - insn.create_op_data(x.addr, x); - insn.add_dref(x.addr, x.offb, isload ? dr_R : dr_W); - break; - case o_near: - { - int iscall = has_insn_feature(insn.itype,CF_CALL); - insn.add_cref(x.addr, x.offb, iscall ? fl_CN : fl_JN); - if ( iscall && !func_does_return(x.addr) ) - return false; - } - break; - default: -badTouch: - warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); - break; - } - return true; -} - -//---------------------------------------------------------------------- -static bool isDual(uint32 code) -{ - return int(code>>26) == 0x12 && (code & Dbit) != 0; -} - -//---------------------------------------------------------------------- -//static int isDelayed(uint32 code) { -// // bc.t bla bnc.t br bri call calli -// int opcode = int(code >> 26); -// switch ( opcode ) { -// case 0x13: -// return ((code & 0x1F) == 2); // calli -// case 0x10: // bri -// case 0x1A: // br -// case 0x1B: // call -// case 0x1D: // bc.t -// case 0x1F: // bnc.t -// case 0x2D: // bla -// return 1; -// } -// return 0; -//} - -//---------------------------------------------------------------------- -static int isDelayedStop(uint32 code) -{ - // br bri - int opcode = int(code >> 26); - switch ( opcode ) - { - case 0x10: // bri - case 0x1A: // br - return 1; - } - return 0; -} - -//---------------------------------------------------------------------- -static bool canFlow(const insn_t &insn) -{ - if ( !is_flow(get_flags(insn.ea)) ) - return 1; // no previous instructions - ea_t ea = insn.ea - 4; - flags_t F = get_flags(ea); - if ( is_flow(F) && is_code(F) ) - { - if ( isDelayedStop(get_dword(ea)) ) // now or later - { - ea -= 4; - if ( !is_code(get_flags(ea)) || !isDual(get_dword(ea)) ) - return 0; - return 1; - } - if ( is_flow(F) ) - { - ea -= 4; - return !is_code(get_flags(ea)) || !isDelayedStop(get_dword(ea)); - } - } - return 1; -} - -//---------------------------------------------------------------------- -int i860_t::i860_emu(const insn_t &insn) const -{ - bool flow = true; - - uint32 Feature = insn.get_canon_feature(ph); - - if ( Feature & CF_USE1 && !handle_operand(insn, insn.Op1, true) ) - flow = false; - if ( Feature & CF_USE2 && !handle_operand(insn, insn.Op2, true) ) - flow = false; - if ( Feature & CF_USE3 && !handle_operand(insn, insn.Op3, true) ) - flow = false; - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( Feature & CF_CHG1 && !handle_operand(insn, insn.Op1, false) ) - flow = false; - if ( Feature & CF_CHG2 && !handle_operand(insn, insn.Op2, false) ) - flow = false; - if ( Feature & CF_CHG3 && !handle_operand(insn, insn.Op3, false) ) - flow = false; - - if ( flow && canFlow(insn) ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - return 1; -} diff --git a/idasdk75/module/i860/ins.hpp b/idasdk75/module/i860/ins.hpp deleted file mode 100644 index 5e364ea..0000000 --- a/idasdk75/module/i860/ins.hpp +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - -I860_null = 0, // Unknown Operation - -// -// Intel 860 XP instructions -// - -I860_adds, -I860_addu, -I860_and, -I860_andh, -I860_andnot, -I860_andnoth, -I860_bc, -I860_bc_t, -I860_bla, -I860_bnc, -I860_bnc_t, -I860_br, -I860_bri, -I860_bte, -I860_btne, -I860_call, -I860_calli, -I860_fadd, -I860_faddp, -I860_faddz, -I860_famov, -I860_fiadd, -I860_fisub, -I860_fix, -I860_fld, -I860_flush, -I860_fmlow_dd, -I860_fmul, -I860_form, -I860_frcp, -I860_frsqr, -I860_fst, -I860_fsub, -I860_ftrunc, -I860_fxfr, -I860_fzchkl, -I860_fzchks, -I860_introvr, -I860_ixfr, -I860_ld_c, -I860_ld, -I860_ldint, -I860_ldio, -I860_lock, -I860_or, -I860_orh, -I860_pfadd, -I860_pfaddp, -I860_pfaddz, -I860_pfamov, -I860_pfeq, -I860_pfgt, -I860_pfiadd, -I860_pfisub, -I860_pfix, -I860_pfld, -I860_pfle, -I860_pfmul, -I860_pfmul3_dd, -I860_pform, -I860_pfsub, -I860_pftrunc, -I860_pfzchkl, -I860_pfzchks, -I860_pst_d, -I860_scyc, -I860_shl, -I860_shr, -I860_shra, -I860_shrd, -I860_st_c, -I860_st, -I860_stio, -I860_subs, -I860_subu, -I860_trap, -I860_unlock, -I860_xor, -I860_xorh, -// -// iNTEL 860 XP Pipelined F-P instructions -// -I860_r2p1, -I860_r2pt, -I860_r2ap1, -I860_r2apt, -I860_i2p1, -I860_i2pt, -I860_i2ap1, -I860_i2apt, -I860_rat1p2, -I860_m12apm, -I860_ra1p2, -I860_m12ttpa, -I860_iat1p2, -I860_m12tpm, -I860_ia1p2, -I860_m12tpa, -I860_r2s1, -I860_r2st, -I860_r2as1, -I860_r2ast, -I860_i2s1, -I860_i2st, -I860_i2as1, -I860_i2ast, -I860_rat1s2, -I860_m12asm, -I860_ra1s2, -I860_m12ttsa, -I860_iat1s2, -I860_m12tsm, -I860_ia1s2, -I860_m12tsa, -I860_mr2p1, -I860_mr2pt, -I860_mr2mp1, -I860_mr2mpt, -I860_mi2p1, -I860_mi2pt, -I860_mi2mp1, -I860_mi2mpt, -I860_mrmt1p2, -I860_mm12mpm, -I860_mrm1p2, -I860_mm12ttpm, -I860_mimt1p2, -I860_mm12tpm, -I860_mim1p2, -I860_mr2s1, -I860_mr2st, -I860_mr2ms1, -I860_mr2mst, -I860_mi2s1, -I860_mi2st, -I860_mi2ms1, -I860_mi2mst, -I860_mrmt1s2, -I860_mm12msm, -I860_mrm1s2, -I860_mm12ttsm, -I860_mimt1s2, -I860_mm12tsm, -I860_mim1s2, - -I860_last, - - }; - -#endif diff --git a/idasdk75/module/i860/makefile b/idasdk75/module/i860/makefile deleted file mode 100644 index a1cc59f..0000000 --- a/idasdk75/module/i860/makefile +++ /dev/null @@ -1,40 +0,0 @@ -PROC=i860 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp i860.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp i860.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - i860.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - i860.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - i860.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/i960/i960.hpp b/idasdk75/module/i960/i960.hpp deleted file mode 100644 index c3d9f07..0000000 --- a/idasdk75/module/i960/i960.hpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _I960_HPP -#define _I960_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -//Absolute offset (<4096) offset exp MEMA o_imm -//Absolute displacement disp exp MEMB o_imm -//Register Indirect abase (reg) o_phrase, index=-1, scale=1 -// with offset abase+offset exp(reg) o_displ, index=-1,scale=1 -// with displacement abase+disp exp(reg) o_displ, index=-1,scale=1 -// with index abase+(index*scale) (reg)[reg*scale] o_phrase, index=index -// with index and displacement abase+(index*scale)+disp exp(reg)[reg*scale] o_displ -//Index with displacement (index*scale) + disp exp[reg*scale] o_displ, reg=index, index=-1 -//IP with displacement IP+disp+8 exp(IP) o_near - -#define index specflag1 // o_displ, o_phrase -#define scale specflag2 // o_displ, o_phrase - -#define aux_t 0x0001 // .t suffix -#define aux_f 0x0002 // .f suffix -#define aux_ip 0x0004 // ip relative addressing - -//------------------------------------------------------------------ -enum regnum_t -{ - LR0, LR1, LR2, LR3, LR4, LR5, LR6, LR7, - LR8, LR9, LR10, LR11, LR12, LR13, LR14, LR15, - GR0, GR1, GR2, GR3, GR4, GR5, GR6, GR7, - GR8, GR9, GR10, GR11, GR12, GR13, GR14, GR15, - SF0, SF31=SF0+31, - PC, AC, IP, TC, - FP0, FP1, FP2, FP3, - ds, cs, - MAXREG = cs, - PFP = LR0, - SP = LR1, - RIP = LR2, - FP = GR15, - IPND = SF0+0, - IMSK = SF0+1, - DMAC = SF0+2, -}; - -//------------------------------------------------------------------ -ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea -//------------------------------------------------------------------ -void idaapi i960_header(outctx_t &ctx); - -void idaapi i960_segend(outctx_t &ctx, segment_t *seg); -void idaapi i960_assumes(outctx_t &ctx); // function to produce assume directives - -int idaapi is_align_insn(ea_t ea); - -//------------------------------------------------------------------ -struct tabent_t -{ - ushort itype; - char opnum; - char dtype; -}; - -//------------------------------------------------------------------ -struct i960_iohandler_t : public iohandler_t -{ - struct i960_t ± - i960_iohandler_t(i960_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct i960_t); - -struct i960_t : public procmod_t -{ - netnode helper; - i960_iohandler_t ioh = i960_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - ushort idpflags; -#define IDP_STRICT 0x0001 // Strictly adhere to instruction encodings - inline bool is_strict(void) { return (idpflags & IDP_STRICT) != 0; } - -#define REG_MIN 0x580 -#define REG_MAX 0x7f4 - struct tabent_t reg_tab_buf[REG_MAX - REG_MIN + 1]; - struct tabent_t *reg_tab = nullptr; - - bool flow; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void load_symbols(void); - const char *find_sym(ea_t address); - void set_device_name(const char *dev); - void choose_device(); - const char *set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - bool ctrl(insn_t &insn, uint32 code); - bool opmemory(insn_t &insn, op_t &x, uint32 code, char dtype); - bool mem(insn_t &insn, uint32 code); - - int i960_ana(insn_t *_insn); - bool reg(insn_t &insn, uint32 code); - - void handle_operand(const insn_t &insn, const op_t &x, bool isload); - int i960_emu(const insn_t &insn); - - void i960_segstart(outctx_t &ctx, segment_t *Sarea) const; - void i960_footer(outctx_t &ctx) const; -}; -#endif // _I960_HPP diff --git a/idasdk75/module/i960/ins.hpp b/idasdk75/module/i960/ins.hpp deleted file mode 100644 index 71a46f1..0000000 --- a/idasdk75/module/i960/ins.hpp +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ -I960_null = 0, // Unknown Operation - -I960_addc, // Add ordinal with carry -I960_addi, // Add integer -I960_addo, // Add ordinal -I960_alterbit, // Alter bit -I960_and, // Src2 AND src1 -I960_andnot, // Src2 AND (NOT src1) -I960_atadd, // Atomic add -I960_atmod, // Atomic modify -I960_b, // Branch -I960_bal, // Branch and Link -I960_balx, // Branch and Link Extended -I960_bbc, // Check bit and branch if clear -I960_bbs, // Check bit and branch if set -I960_bno, // Branch if unordered/false -I960_bg, // Branch if greater -I960_be, // Branch if equal/true -I960_bge, // Branch if greater or equal -I960_bl, // Branch if less -I960_bne, // Branch if not equal -I960_ble, // Branch if less or equal -I960_bo, // Branch if ordered -I960_bx, // Branch Extended -I960_call, // Call -I960_calls, // Call system -I960_callx, // Call extended -I960_chkbit, // Check bit -I960_clrbit, // Clear bit -I960_cmpdeci, // Compare and decrement integer -I960_cmpdeco, // Compare and decrement ordinal -I960_cmpi, // Compare integer -I960_cmpibno, // Compare integer and branch if unordered -I960_cmpibg, // Compare integer and branch if greater -I960_cmpibe, // Compare integer and branch if equal -I960_cmpibge, // Compare integer and branch if greater or equal -I960_cmpibl, // Compare integer and branch if less -I960_cmpibne, // Compare integer and branch if not equal -I960_cmpible, // Compare integer and branch if less or equal -I960_cmpibo, // Compare integer and branch if ordered -I960_cmpinci, // Compare and increment integer -I960_cmpinco, // Compare and increment ordinal -I960_cmpo, // Compare ordinal -I960_cmpobg, // Compare ordinal and branch if greater -I960_cmpobe, // Compare ordinal and branch if equal -I960_cmpobge, // Compare ordinal and branch if greater or equal -I960_cmpobl, // Compare ordinal and branch if less -I960_cmpobne, // Compare ordinal and branch if not equal -I960_cmpoble, // Compare ordinal and branch if less or equal -I960_concmpi, // Conditional compare integer -I960_concmpo, // Conditional compare ordinal -I960_divi, // Divide integer -I960_divo, // Divide ordinal -I960_ediv, // Extended divide -I960_emul, // Extended multiply -I960_eshro, // Extended shift right ordinal -I960_extract, // Extract -I960_faultno, // Fault if unordered -I960_faultg, // Fault if greater -I960_faulte, // Fault if equal -I960_faultge, // Fault if greater or equal -I960_faultl, // Fault if less -I960_faultne, // Fault if not equal -I960_faultle, // Fault if less or equal -I960_faulto, // Fault if ordered -I960_flushreg, // Flush cached local register sets to memory -I960_fmark, // Force mark -I960_ld, // Load word -I960_lda, // Load address -I960_ldib, // Load integer byte -I960_ldis, // Load integer short -I960_ldl, // Load long -I960_ldob, // Load ordinal byte -I960_ldos, // Load ordinal short -I960_ldq, // Load quad -I960_ldt, // Load triple -I960_mark, // Mark -I960_modac, // Modify the AC register -I960_modi, // Modulo integer -I960_modify, // Modify -I960_modpc, // Modify the process controls register -I960_modtc, // Modify trace controls -I960_mov, // Move word -I960_movl, // Move long word -I960_movq, // Move quad word -I960_movt, // Move triple word -I960_muli, // Multiply integer -I960_mulo, // Multiply ordinal -I960_nand, // NOT (src2 AND src1) -I960_nor, // NOT (src2 OR src1) -I960_not, // NOT src1 -I960_notand, // (NOT src2) AND src1 -I960_notbit, // Not bit -I960_notor, // (NOT src2) or src1 -I960_or, // Src2 OR src1 -I960_ornot, // Src2 or (NOT src1) -I960_remi, // Remainder integer -I960_remo, // Remainder ordinal -I960_ret, // Return -I960_rotate, // Rotate left -I960_scanbit, // Scan for bit -I960_scanbyte, // Scan byte equal -I960_setbit, // Set bit -I960_shli, // Shift left integer -I960_shlo, // Shift left ordinal -I960_shrdi, // Shift right dividing integer -I960_shri, // Shift right integer -I960_shro, // Shift right ordinal -I960_spanbit, // Span over bit -I960_st, // Store word -I960_stib, // Store integer byte -I960_stis, // Store integer short -I960_stl, // Store long -I960_stob, // Store ordinal byte -I960_stos, // Store ordinal short -I960_stq, // Store quad -I960_stt, // Store triple -I960_subc, // Subtract ordinal with carry -I960_subi, // Subtract integer -I960_subo, // Subtract ordinal -I960_syncf, // Synchronize faults -I960_testno, // Test for unordered -I960_testg, // Test for greater -I960_teste, // Test for equal -I960_testge, // Test for greater or equal -I960_testl, // Test for less -I960_testne, // Test for not equal -I960_testle, // Test for less or equal -I960_testo, // Test for ordered -I960_xnor, // Src2 XNOR src1 -I960_xor, // Src2 XOR src1 - -// Cx instructions - -I960_sdma, // Set up a DMA controller channel -I960_sysctl, // Perform system control function -I960_udma, // Copy current DMA pointers to internal data RAM - -// Unknown instructions - -I960_dcinva, -I960_cmpob, -I960_cmpib, -I960_cmpos, -I960_cmpis, -I960_bswap, -I960_intdis, -I960_inten, -I960_synmov, -I960_synmovl, -I960_synmovq, -I960_cmpstr, -I960_movqstr, -I960_movstr, -I960_inspacc, -I960_ldphy, -I960_synld, -I960_fill, -I960_daddc, -I960_dsubc, -I960_dmovt, -I960_condrec, -I960_receive, -I960_intctl, -I960_icctl, -I960_dcctl, -I960_halt, -I960_send, -I960_sendserv, -I960_resumprcs, -I960_schedprcs, -I960_saveprcs, -I960_condwait, -I960_wait, -I960_signal, -I960_ldtime, -I960_addono, -I960_addino, -I960_subono, -I960_subino, -I960_selno, -I960_addog, -I960_addig, -I960_subog, -I960_subig, -I960_selg, -I960_addoe, -I960_addie, -I960_suboe, -I960_subie, -I960_sele, -I960_addoge, -I960_addige, -I960_suboge, -I960_subige, -I960_selge, -I960_addol, -I960_addil, -I960_subol, -I960_subil, -I960_sell, -I960_addone, -I960_addine, -I960_subone, -I960_subine, -I960_selne, -I960_addole, -I960_addile, -I960_subole, -I960_subile, -I960_selle, -I960_addoo, -I960_addio, -I960_suboo, -I960_subio, -I960_selo, - -// Floating point instructions - -I960_faddr, I960_fp_first = I960_faddr, -I960_faddrl, -I960_fatanr, -I960_fatanrl, -I960_fclassr, -I960_fclassrl, -I960_fcmpor, -I960_fcmporl, -I960_fcmpr, -I960_fcmprl, -I960_fcosr, -I960_fcosrl, -I960_fcpyrsre, -I960_fcpysre, -I960_fcvtilr, -I960_fcvtir, -I960_fcvtri, -I960_fcvtril, -I960_fcvtzri, -I960_fcvtzril, -I960_fdivr, -I960_fdivrl, -I960_fexpr, -I960_fexprl, -I960_flogbnr, -I960_flogbnrl, -I960_flogepr, -I960_flogeprl, -I960_flogr, -I960_flogrl, -I960_fmovr, -I960_fmovre, -I960_fmovrl, -I960_fmulr, -I960_fmulrl, -I960_fremr, -I960_fremrl, -I960_froundr, -I960_froundrl, -I960_fscaler, -I960_fscalerl, -I960_fsinr, -I960_fsinrl, -I960_fsqrtr, -I960_fsqrtrl, -I960_fsubr, -I960_fsubrl, -I960_ftanr, -I960_ftanrl, I960_fp_last = I960_ftanrl, - -I960_last, - - }; - -#endif diff --git a/idasdk75/module/i960/makefile b/idasdk75/module/i960/makefile deleted file mode 100644 index 586ffa1..0000000 --- a/idasdk75/module/i960/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=i960 -CONFIGS=i960.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp i960.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - emu.cpp i960.hpp ins.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - i960.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - i960.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp i960.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/i960/reg.cpp b/idasdk75/module/i960/reg.cpp deleted file mode 100644 index 65a201f..0000000 --- a/idasdk75/module/i960/reg.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2001 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "i960.hpp" -#include <diskio.hpp> -#include <typeinf.hpp> -#include <ieee.h> -static int data_id; - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", - "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", - "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", - "sf0", "sf1", "sf2", "sf3", "sf4", "sf5", "sf6", "sf7", - "sf8", "sf9", "sf10", "sf11", "sf12", "sf13", "sf14", "sf15", - "sf16", "sf17","sf18", "sf19", "sf20", "sf21", "sf22", "sf23", - "sf24", "sf25","sf26", "sf27", "sf28", "sf29", "sf30", "sf31", - "pc", "ac", "ip", "tc", - "fp0", "fp1", "fp2", "fp3", - "ds", "cs", -}; - -//-------------------------------------------------------------------------- -static const bytes_t retcodes[] = -{ -// { sizeof(retcode0), retcode0 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// GNU assembler -//----------------------------------------------------------------------- -static const asm_t gnuasm = -{ - AS_ASCIIC|AS_ALIGN2|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, - 0, - "GNU assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - "#", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".long", // double words - ".quad", // qwords - ".octa", // oword (16 bytes) - ".float", // float (4 bytes) - ".double", // double (8 bytes) - ".extended", // tbyte (10/12 bytes) - NULL, // packed decimal real - ".fill #d, #s(1,2,4,8), #v", // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - ".", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &gnuasm, NULL }; - -//-------------------------------------------------------------------------- -static const char *const cfgname = "i960.cfg"; - -void i960_t::load_symbols(void) -{ - ioh.ports.clear(); - read_ioports(&ioh.ports, &ioh.device, cfgname); -} - -const char *i960_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port ? port->name.c_str() : NULL; -} - - -//-------------------------------------------------------------------------- -void i960_t::set_device_name(const char *dev) -{ - if ( dev != NULL ) - ioh.device = dev; -} - -//-------------------------------------------------------------------------- -void i960_t::choose_device() -{ - if ( choose_ioport_device(&ioh.device, cfgname) ) - load_symbols(); -} - -//-------------------------------------------------------------------------- -static int idaapi choose_device_cb(int, form_actions_t &fa) -{ - i960_t &pm = *(i960_t *)fa.get_ud(); - pm.choose_device(); - return 0; -} - -//-------------------------------------------------------------------------- -const char *i960_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - static const char form[] = - "HELP\n" - "Intel 960 specific options\n" - "\n" - " Choose device name\n" - " Here you may select a specific Intel 960 device\n" - " IDA will use the definitions in the I960.CFG file for\n" - " the i/o port names\n" - "\n" - " Strictly adhere to instruction encodings\n" - " If this option is on, IDA will check that unused fields\n" - " of instructions are filled by zeroes. If they are not,\n" - " it will refuse to disassemble the instruction.\n" - "\n" - "ENDHELP\n" - "Intel 960 specific options\n" - "%*\n" - " <~C~hoose device name:B:0:::>\n" - "\n" - " <~S~trictly adhere to instruction encodings:C>>\n" - "\n" - "\n"; - - if ( keyword == NULL ) - { - CASSERT(sizeof(idpflags) == sizeof(ushort)); - ask_form(form, this, choose_device_cb, &idpflags); -OK: - if ( idb_loaded ) - helper.altset(-1, idpflags); - return IDPOPT_OK; - } - else - { - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - if ( strcmp(keyword, "I960_STRICT") == 0 ) - { - setflag(idpflags, IDP_STRICT, *(int*)value != 0); - goto OK; - } - } - return IDPOPT_BADKEY; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.supset(0, pm.ioh.device.c_str()); - pm.helper.altset(-1, pm.idpflags); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(i960_t)); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi i960_t::on_event(ssize_t msgid, va_list va) -{ - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ i960"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: // new file loaded - choose_device(); - break; - - case processor_t::ev_ending_undo: - // restore ptype - { - int n = ph.get_proc_index(); - inf_set_be((n > 1)); - } - //fall through - case processor_t::ev_oldfile: // old file loaded - idpflags = helper.altval(-1); - if ( helper.supstr(&ioh.device, 0) > 0 ) - set_device_name(ioh.device.c_str()); - load_symbols(); - break; - - case processor_t::ev_newprc: - { - int n = va_arg(va, int); - bool keep_cfg = va_argi(va, bool); - if ( !keep_cfg ) - inf_set_be((n > 1)); - } - break; - -// +++ TYPE CALLBACKS - case processor_t::ev_decorate_name: - { - qstring *outbuf = va_arg(va, qstring *); - const char *name = va_arg(va, const char *); - bool mangle = va_argi(va, bool); - cm_t cc = va_argi(va, cm_t); - tinfo_t *type = va_arg(va, tinfo_t *); - return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; - } - - case processor_t::ev_max_ptr_size: - return 4; - - case processor_t::ev_calc_arglocs: - return -1; - - case processor_t::ev_use_stkarg_type: - return 0; - - case processor_t::ev_use_regarg_type: - return -1; - - case processor_t::ev_get_cc_regs: - { - callregs_t *callregs = va_arg(va, callregs_t *); - cm_t cc = va_argi(va, cm_t); - if ( cc == CM_CC_FASTCALL || cc == CM_CC_THISCALL ) - { - callregs->reset(); - return 1; - } - } - break; - - case processor_t::ev_calc_cdecl_purged_bytes:// calculate number of purged bytes after call - { - // ea_t ea = va_arg(va, ea_t); - return 0; - } - - case processor_t::ev_get_stkarg_offset: // get offset from SP to the first stack argument - // args: none - // returns: the offset - return 0; - -// --- TYPE CALLBACKS - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - i960_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - i960_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - i960_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - i960_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return i960_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return i960_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return 0; -} - -//----------------------------------------------------------------------- -#define FAMILY "Intel 960:" - -static const char *const shnames[] = -{ - "i960", - "i960l", - "i960b", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Intel 960 little endian (default)", - "Intel 960 little endian", - "Intel 960 big endian", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_I960, // id - // flag - PRN_HEX - | PR_RNAMESOK - | PR_SEGS - | PR_USE32 - | PR_DEFSEG32 - | PR_TYPEINFO, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - ds, // first - cs, // last - 2, // size of a segment register - cs, ds, - - NULL, // No known code start sequences - retcodes, - - I960_null, - I960_last, - Instructions, // instruc - 10, // int tbyte_size (0-doesn't exist) - { 0, 7, 15, 19 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - I960_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/idaidp.hpp b/idasdk75/module/idaidp.hpp deleted file mode 100644 index be03c60..0000000 --- a/idasdk75/module/idaidp.hpp +++ /dev/null @@ -1,68 +0,0 @@ - -// Common include files for IDP modules: - -#include <ida.hpp> -#include <idp.hpp> -#include <ua.hpp> -#include <name.hpp> -#include <auto.hpp> -#include <bytes.hpp> -#include <problems.hpp> -#include <lines.hpp> -#include <loader.hpp> -#include <offset.hpp> -#include <segment.hpp> -#include <kernwin.hpp> - -#define DECLARE_PROC_LISTENER(listener_type, parent_type) \ - DECLARE_LISTENER(listener_type, parent_type, pm) - -// Current processor in the module -// It must be exported -idaman processor_t ida_module_data LPH; - -void idaapi out_insn(outctx_t &ctx); -void idaapi out_mnem(outctx_t &ctx); -bool idaapi out_opnd(outctx_t &ctx, const op_t &x); - -// use this define if the default out_mnem() is good enough -#define DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(CTXNAME) \ - void idaapi out_insn(outctx_t &ctx) \ - { \ - CTXNAME *p = (CTXNAME *)&ctx; \ - p->out_insn(); \ - } \ - bool idaapi out_opnd(outctx_t &ctx, const op_t &x) \ - { \ - CTXNAME *p = (CTXNAME *)&ctx; \ - return p->out_operand(x); \ - } - -// use this define if you want to print insn mnemonics yourself -#define DECLARE_OUT_FUNCS(CTXNAME) \ - DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(CTXNAME) \ - void idaapi out_mnem(outctx_t &ctx) \ - { \ - CTXNAME *p = (CTXNAME *)&ctx; \ - p->out_proc_mnem(); \ - } - -//-------------------------------------------------------------------------- -inline bool print_predefined_segname( - outctx_t &ctx, - qstring *sname, - const char *const predefined[], - size_t n) -{ - for ( size_t i=0; i < n; i++ ) - { - if ( *sname == predefined[i] ) - { - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR), sname->c_str()); - return true; - } - } - validate_name(sname, VNT_IDENT); - return false; -} - diff --git a/idasdk75/module/iocommon.cpp b/idasdk75/module/iocommon.cpp deleted file mode 100644 index 1888a0a..0000000 --- a/idasdk75/module/iocommon.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* - - This file contains functions common to many processor modules - to manage configuration files. The following functions can be called: - - bool apply_config_file(int _respect_info); - Read and parse the config file - - void set_device_name(const char *dname, int respect_info); - Set a new device name and reread the config file - - bool display_infotype_dialog(int *respect_info, const char *cfgname); - Display a form and allow the user to clear some IORESP_ bits - -*/ - -#include <entry.hpp> - -//lint -esym(843,respect_info) could be declared as const -qstring deviceparams; -static int respect_info; - -#define IORESP_PORT 1 // rename port names in memory -#define IORESP_AREA 2 // respect "area" directives -#define IORESP_INT 4 // respect interrupt information - -#define IORESP_ALL (IORESP_PORT|IORESP_AREA|IORESP_INT) -#define IORESP_NONE 0 - -#define NONEPROC "NONE" - -// Option: additional segment class to appear in the device description -// Default: EEPROC -// Change: define CUSTOM1 for the name you want -#ifndef CUSTOM1 -#define CUSTOM1 "EEPROM" -#endif - -// Option: respect configuration information for different file types? -// Default: only binary-like files use IORESP_PORT, AREA, INT -// Change: define CHECK_IORESP as a condition -#ifndef CHECK_IORESP -#define CHECK_IORESP inf_like_binary() -#endif - -// Option: a callback function to parse additional configuration file lines -// Default: "interrupt" and "entry" keywords are recognized -// Change: define callback to point to a local callback function -#ifndef iocallback -#define iocallback standard_callback -#endif - -// Option: the function that will actually apply the IO port info into the IDB. -// Default: will simply set name & comment. -// Change: define APPLY_IO_PORT to be a specific handler. -#ifndef APPLY_IO_PORT -static void standard_apply_io_port(ea_t ea, const char *name, const char *cmt) -{ - set_name(ea, name, SN_NODUMMY); - set_cmt(ea, cmt, true); -} -#define APPLY_IO_PORT standard_apply_io_port -#endif - -// Option: the function that will be called for unknown directives -// (e.g., "area", "mirror", ...) -// Default: standard_handle_unknown_directive -// Change: define HANDLE_UNKNOWN_DIRECTIVE to be a specific handler. -static const char *idaapi parse_area_line(qstring *buf, const char *line); -static const char *standard_handle_unknown_directive(const char *line) -{ - return parse_area_line(&deviceparams, line); -} -#ifndef HANDLE_UNKNOWN_DIRECTIVE -#define HANDLE_UNKNOWN_DIRECTIVE standard_handle_unknown_directive -#endif - -// Option: function to handle entry points -// Default: create an entry point -// Change: define ENTRY_PROCESSING to point to a local function - -// Option: function to handle areas -// Default: create a segment -// Change: define AREA_PROCESSING to point to a local function - -// Option: define function get_cfg_path() -// Default: yes, it returns a file name using the current processor name -// Change: define NO_GET_CFG_PATH and write your own get_cfg_path() - -//------------------------------------------------------------------ -static const char *idaapi parse_area_line(qstring *buf, const char *line) -{ - if ( line[0] != ';' ) - { - char word[MAXSTR]; - char aclass[MAXSTR]; - word[MAXSTR-1] = '\0'; - aclass[MAXSTR-1] = '\0'; - ea_t ea1, ea2; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "area %1023s %1023s %a:%a", aclass, word, &ea1, &ea2) == 4 ) - { - size_t _ram = 0; - size_t _rom = 0; - size_t _eprom = 0; - size_t _eeprom = 0; - static const char *const format = - "RAM=%" FMT_Z " ROM=%" FMT_Z " EPROM=%" FMT_Z " " CUSTOM1 "=%" FMT_Z; - qsscanf(buf->c_str(), format, &_ram, &_rom, &_eprom, &_eeprom); - size_t size = size_t(ea2 - ea1); - if ( stristr(word, "RAM") != NULL ) - _ram += size; - else if ( stristr(word, CUSTOM1) != NULL ) - _eeprom += size; - else if ( stristr(word, "EPROM") != NULL ) - _eprom += size; - else if ( stristr(word, "ROM") != NULL ) - _rom += size; - if ( _ram || _rom || _eprom || _eeprom ) - buf->sprnt(format, _ram, _rom, _eprom, _eeprom); - else - buf->qclear(); - if ( (respect_info & IORESP_AREA) != 0 && get_first_seg() != NULL ) - { -#ifdef AREA_PROCESSING - if ( !AREA_PROCESSING(ea1, ea2, word, aclass) ) -#endif - { -#ifdef I8051 - if ( stristr(word, "FSR") != NULL || stristr(word, "RAM") != NULL ) - { - AdditionalSegment(ea2-ea1, ea1, word); - } - else -#endif - { - segment_t s; - s.sel = setup_selector(0); - s.start_ea = ea1; - s.end_ea = ea2; - s.align = saRelByte; - s.comb = streq(aclass, "STACK") ? scStack : scPub; - s.bitness = PH.get_segm_bitness(); - if ( s.bitness == 0 && s.size() > 0xFFFF ) - s.bitness = 1; - int sfl = ADDSEG_NOSREG; - if ( !is_loaded(s.start_ea) ) - sfl |= ADDSEG_SPARSE; - add_segm_ex(&s, word, aclass, sfl); - } - } - } - return NULL; - } - } - return "syntax error"; -} - -//------------------------------------------------------------------ -const char *idaapi parse_area_line0(qstring *buf, const char *line) -{ - respect_info = 0; - parse_area_line(buf, line); - return NULL; -} - -//------------------------------------------------------------------ -static const char *idaapi standard_callback(const ioports_t &, const char *line) -{ - int len; - ea_t ea1; - char word[MAXSTR]; - word[MAXSTR-1] = '\0'; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "interrupt %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) - { - if ( (respect_info & IORESP_INT) != 0 ) - { - ea_t proc, wrong; - segment_t *s = getseg(ea1); - if ( s != NULL && s->use32() ) - { - create_dword(ea1, 4); - proc = get_dword(ea1); - wrong = 0xFFFFFFFF; - } - else - { - create_word(ea1, 2); - proc = get_word(ea1); - wrong = 0xFFFF; - } - if ( proc != wrong && is_mapped(proc) ) - { - op_plain_offset(ea1, 0, 0); - add_entry(proc, proc, word, true); - } - else - { - set_name(ea1, word, SN_NODUMMY); - } - const char *ptr = &line[len]; - ptr = skip_spaces(ptr); - if ( ptr[0] != '\0' ) - set_cmt(ea1, ptr, true); - } - return NULL; - } - if ( qsscanf(line, "entry %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) - { - if ( (respect_info & IORESP_INT) != 0 ) - { - if ( is_mapped(ea1) ) - { - const char *ptr = &line[len]; - ptr = skip_spaces(ptr); -#ifdef ENTRY_PROCESSING - if ( !ENTRY_PROCESSING(ea1, word, ptr) ) -#endif - { - add_entry(ea1, ea1, word, true); - if ( ptr[0] != '\0' ) - set_cmt(ea1, ptr, true); - } - } - } - return NULL; - } - return HANDLE_UNKNOWN_DIRECTIVE(line); -} - -//------------------------------------------------------------------ -#ifndef NO_GET_CFG_PATH -inline void get_cfg_filename(char *buf, size_t bufsize) -{ - inf_get_procname(buf, bufsize); - qstrlwr(buf); - qstrncat(buf, ".cfg", bufsize); -} -#endif - -//------------------------------------------------------------------ -static bool apply_config_file(int _respect_info) -{ - if ( device == NONEPROC ) // processor not selected - return true; - - char cfgfile[QMAXFILE]; - get_cfg_filename(cfgfile, sizeof(cfgfile)); - deviceparams.qclear(); - if ( !CHECK_IORESP ) - _respect_info = 0; - respect_info = _respect_info; - ports.clear(); - read_ioports(&ports, &device, cfgfile, iocallback); - if ( respect_info & IORESP_PORT ) - { - for ( size_t i=0; i < ports.size(); i++ ) - { - const ioport_t &p = ports[i]; - ea_t ea = p.address; - APPLY_IO_PORT(ea, p.name.c_str(), p.cmt.c_str()); - } - } - return true; -} - -//------------------------------------------------------------------ -void set_device_name(const char *dname, int respinfo) -{ - if ( dname != NULL ) - { - device = dname; - helper.supset(-1, device.c_str()); - apply_config_file(respinfo); - } -} - -//------------------------------------------------------------------ -void restore_device(int respinfo = IORESP_NONE) -{ - if ( helper.supstr(&device, -1) > 0 ) - set_device_name(device.c_str(), respinfo); -} - -//------------------------------------------------------------------ -// Display a dialog form with the information types -// Let the user to clear some checkboxes if he wants so -// Returns: true - the user clicked OK -bool display_infotype_dialog( - int display_info, - int *p_resp_info, - const char *cfg_filename) -{ - if ( display_info == 0 ) - return false; - static const char *const form = - "Loaded information type\n" - "\n" - "Please specify what information should be loaded from\n" - "the configuration file %s to the database.\n" - "\n" - "If the input file does not contain parts corresponding to\n" - "the segmentation defined in the config file, you might want\n" - "to clear the 'memory layout' checkbox or even cancel this\n" - "dialog box.\n"; - char buf[MAXSTR]; - char *ptr = buf + qsnprintf(buf, sizeof(buf), form, cfg_filename); - char *const end = buf + sizeof(buf); - int B = 1; - ushort b = 0; - ushort r = (ushort)*p_resp_info; -#define ADD_FIELD(bit, desc) \ - if ( display_info & bit ) \ - { \ - if ( r & bit ) \ - b |= B; \ - B <<= 1; \ - APPEND(ptr, end, desc); \ - } - ADD_FIELD(IORESP_PORT, "\n<#Rename port and I/O registers#I/O ports:C>") - ADD_FIELD(IORESP_AREA, "\n<#Adjust the program segmentation#Memory layout:C>") - ADD_FIELD(IORESP_INT, "\n<#Create interrupt vectors and/or entry points#Interrupts:C>") -#undef ADD_FIELD - qnotused(B); - APPEND(ptr, end, ">\n\n"); - if ( !ask_form(buf, &b) ) - return false; - B = 1; - if ( display_info & IORESP_PORT ) - { - setflag(r, IORESP_PORT, (B & b) != 0); - B <<= 1; - } - if ( display_info & IORESP_AREA ) - { - setflag(r, IORESP_AREA, (B & b) != 0); - B <<= 1; - } - if ( display_info & IORESP_INT ) - setflag(r, IORESP_INT, (B & b) != 0); - *p_resp_info = r; - return true; -} diff --git a/idasdk75/module/iohandler.hpp b/idasdk75/module/iohandler.hpp deleted file mode 100644 index 4184b28..0000000 --- a/idasdk75/module/iohandler.hpp +++ /dev/null @@ -1,363 +0,0 @@ -/* - - This file contains functions common to many processor modules - to manage configuration files. The following functions can be called: - - bool apply_config_file(int _respect_info); - Read and parse the config file - - void set_device_name(const char *dname, int respect_info); - Set a new device name and reread the config file - - bool display_infotype_dialog(int *respect_info, const char *cfgname); - Display a form and allow the user to clear some IORESP_ bits - -*/ -#pragma once - -#include <pro.h> -#include <ida.hpp> -#include <netnode.hpp> -#include <bytes.hpp> -#include <diskio.hpp> -#include <segment.hpp> -#include <entry.hpp> -#include <name.hpp> -#include <xref.hpp> -#include <offset.hpp> -#include <idp.hpp> - -struct iohandler_t -{ - qstring device; - ioports_t ports; - qstring deviceparams; -#define IORESP_PORT 1 // rename port names in memory -#define IORESP_AREA 2 // respect "area" directives -#define IORESP_INT 4 // respect interrupt information - -#define IORESP_ALL (IORESP_PORT|IORESP_AREA|IORESP_INT) -#define IORESP_NONE 0 - int respect_info = IORESP_NONE; - netnode &helper; - - iohandler_t(netnode &_helper) : helper(_helper) {} - DEFINE_VIRTUAL_DTOR(iohandler_t) - -#define NONEPROC "NONE" - - // Option: additional segment class to appear in the device description - // Default: EEPROM - virtual const char *aux_segm() const { return "EEPROM"; } - - // Option: respect configuration information for different file types? - // Default: only binary-like files use IORESP_PORT, AREA, INT - virtual bool check_ioresp() const { return inf_like_binary(); } - - // Option: a callback function to parse additional configuration file lines - // Default: "interrupt" and "entry" keywords are recognized - virtual const char *iocallback(const ioports_t &iop, const char *line) - { - return standard_callback(iop, line); - } - - // can be used as object handler for read_ioports2() - struct ioports_loader_t : public ioports_fallback_t - { - iohandler_t *_this; - ioports_loader_t(iohandler_t *_t) : _this(_t) {} - - virtual bool handle(qstring *errbuf, const ioports_t &_ports, const char *line) override - { - const char *errmsg = _this->iocallback(_ports, line); - if ( errmsg == nullptr ) - return true; - if ( errmsg == IOPORT_SKIP_DEVICE ) - errmsg = "SKIP device (logic error):"; - *errbuf = errmsg; - return false; - } - }; - - // Option: the function that will actually apply the IO port info into the IDB. - // Default: will simply set name & comment. - virtual void apply_io_port(ea_t ea, const char *name, const char *cmt) - { - set_name(ea, name, SN_NODUMMY); - set_cmt(ea, cmt, true); - } - - // Option: the function that will be called for unknown directives - // (e.g., "area", "mirror", ...) - // Default: standard_handle_unknown_directive - virtual const char *handle_unknown_directive(const char *line) - { - return parse_area_line(&deviceparams, line); - } - - // Option: function to handle entry points - // Default: create an entry point - //-V:entry_processing:669 - virtual bool entry_processing(ea_t &, const char * /*word*/, const char * /*cmt*/) { return false; } - - // Option: function to handle areas - // Default: create a segment - virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) { return false; } - - virtual bool segment_created(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) { return false; } - - // Option: define function get_cfg_path() - // Default: yes, it returns a file name using the current processor name - virtual void get_cfg_filename(char *buf, size_t bufsize) - { - inf_get_procname(buf, bufsize); - qstrlwr(buf); - qstrncat(buf, ".cfg", bufsize); - } - - GCC_DIAG_OFF(format-nonliteral); - //------------------------------------------------------------------ - const char *parse_area_line(qstring *buf, const char *line) - { - if ( line[0] != ';' ) - { - char word[MAXSTR]; - char aclass[MAXSTR]; - word[MAXSTR-1] = '\0'; - aclass[MAXSTR-1] = '\0'; - ea_t ea1, ea2; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "area %1023s %1023s %a:%a", aclass, word, &ea1, &ea2) == 4 ) - { - size_t _ram = 0; - size_t _rom = 0; - size_t _eprom = 0; - size_t _eeprom = 0; - qstring format("RAM=%" FMT_Z " ROM=%" FMT_Z " EPROM=%" FMT_Z " "); - format.append(aux_segm()); - format.append("=%" FMT_Z); - qsscanf(buf->c_str(), format.c_str(), &_ram, &_rom, &_eprom, &_eeprom); - size_t size = size_t(ea2 - ea1); - if ( stristr(word, "RAM") != NULL ) - _ram += size; - else if ( stristr(word, aux_segm()) != NULL ) - _eeprom += size; - else if ( stristr(word, "EPROM") != NULL ) - _eprom += size; - else if ( stristr(word, "ROM") != NULL ) - _rom += size; - if ( _ram || _rom || _eprom || _eeprom ) - buf->sprnt(format.c_str(), _ram, _rom, _eprom, _eeprom); - else - buf->qclear(); - if ( (respect_info & IORESP_AREA) != 0 && get_first_seg() != NULL ) - { - if ( !area_processing(ea1, ea2, word, aclass) ) - { - if ( !segment_created(ea1, ea2, word, aclass) ) - { - segment_t s; - s.sel = setup_selector(0); - s.start_ea = ea1; - s.end_ea = ea2; - s.align = saRelByte; - s.comb = streq(aclass, "STACK") ? scStack : scPub; - s.bitness = PH.get_segm_bitness(); - if ( s.bitness == 0 && s.size() > 0xFFFF ) - s.bitness = 1; - int sfl = ADDSEG_NOSREG; - if ( !is_loaded(s.start_ea) ) - sfl |= ADDSEG_SPARSE; - add_segm_ex(&s, word, aclass, sfl); - } - } - } - return NULL; - } - } - return "syntax error"; - } - GCC_DIAG_ON(format-nonliteral); - - //------------------------------------------------------------------ - struct parse_area_line0_t : public choose_ioport_parser_t - { - iohandler_t &_this; - parse_area_line0_t(iohandler_t &_t) : _this(_t) {} - - virtual bool parse(qstring *param, const char *line) override - { - _this.respect_info = 0; - _this.parse_area_line(param, line); - return true; - } - }; - - //------------------------------------------------------------------ - const char *idaapi standard_callback(const ioports_t &, const char *line) - { - int len; - ea_t ea1; - char word[MAXSTR]; - word[MAXSTR-1] = '\0'; - CASSERT(MAXSTR == 1024); - if ( qsscanf(line, "interrupt %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) - { - if ( (respect_info & IORESP_INT) != 0 ) - { - ea_t proc, wrong; - segment_t *s = getseg(ea1); - if ( s != NULL && s->use32() ) - { - create_dword(ea1, 4); - proc = get_dword(ea1); - wrong = 0xFFFFFFFF; - } - else - { - create_word(ea1, 2); - proc = get_word(ea1); - wrong = 0xFFFF; - } - if ( proc != wrong && is_mapped(proc) ) - { - op_plain_offset(ea1, 0, 0); - add_entry(proc, proc, word, true); - } - else - { - set_name(ea1, word, SN_NODUMMY); - } - const char *ptr = &line[len]; - ptr = skip_spaces(ptr); - if ( ptr[0] != '\0' ) - set_cmt(ea1, ptr, true); - } - return NULL; - } - if ( qsscanf(line, "entry %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) - { - if ( (respect_info & IORESP_INT) != 0 ) - { - if ( is_mapped(ea1) ) - { - const char *ptr = &line[len]; - ptr = skip_spaces(ptr); - if ( !entry_processing(ea1, word, ptr) ) - { - add_entry(ea1, ea1, word, true); - if ( ptr[0] != '\0' ) - set_cmt(ea1, ptr, true); - } - } - } - return NULL; - } - return handle_unknown_directive(line); - } - - //------------------------------------------------------------------ - bool apply_config_file(int _respect_info) - { - if ( device == NONEPROC ) // processor not selected - return true; - - char cfgfile[QMAXFILE]; - get_cfg_filename(cfgfile, sizeof(cfgfile)); - deviceparams.qclear(); - if ( !check_ioresp() ) - _respect_info = 0; - respect_info = _respect_info; - ports.clear(); - ioports_loader_t ldr(this); - read_ioports2(&ports, &device, cfgfile, &ldr); - if ( respect_info & IORESP_PORT ) - { - for ( size_t i=0; i < ports.size(); i++ ) - { - const ioport_t &p = ports[i]; - ea_t ea = p.address; - apply_io_port(ea, p.name.c_str(), p.cmt.c_str()); - } - } - return true; - } - - //------------------------------------------------------------------ - void set_device_name(const char *dname, int respinfo) - { - if ( dname != NULL ) - { - device = dname; - helper.supset(-1, device.c_str()); - apply_config_file(respinfo); - } - } - - //------------------------------------------------------------------ - void restore_device(int respinfo = IORESP_NONE) - { - if ( helper.supstr(&device, -1) > 0 ) - set_device_name(device.c_str(), respinfo); - } - - //------------------------------------------------------------------ - // Display a dialog form with the information types - // Let the user to clear some checkboxes if he wants so - // Returns: true - the user clicked OK - bool display_infotype_dialog( - int display_info, - int *p_resp_info, - const char *cfg_filename) - { - if ( display_info == 0 ) - return false; - static const char *const form = - "Loaded information type\n" - "\n" - "Please specify what information should be loaded from\n" - "the configuration file %s to the database.\n" - "\n" - "If the input file does not contain parts corresponding to\n" - "the segmentation defined in the config file, you might want\n" - "to clear the 'memory layout' checkbox or even cancel this\n" - "dialog box.\n"; - char buf[MAXSTR]; - char *ptr = buf + qsnprintf(buf, sizeof(buf), form, cfg_filename); - char *const end = buf + sizeof(buf); - int B = 1; - ushort b = 0; - ushort r = (ushort)*p_resp_info; - #define ADD_FIELD(bit, desc) \ - if ( display_info & bit ) \ - { \ - if ( r & bit ) \ - b |= B; \ - B <<= 1; \ - APPEND(ptr, end, desc); \ - } - ADD_FIELD(IORESP_PORT, "\n<#Rename port and I/O registers#I/O ports:C>") - ADD_FIELD(IORESP_AREA, "\n<#Adjust the program segmentation#Memory layout:C>") - ADD_FIELD(IORESP_INT, "\n<#Create interrupt vectors and/or entry points#Interrupts:C>") - #undef ADD_FIELD - qnotused(B); - APPEND(ptr, end, ">\n\n"); - if ( !ask_form(buf, &b) ) - return false; - B = 1; - if ( display_info & IORESP_PORT ) - { - setflag(r, IORESP_PORT, (B & b) != 0); - B <<= 1; - } - if ( display_info & IORESP_AREA ) - { - setflag(r, IORESP_AREA, (B & b) != 0); - B <<= 1; - } - if ( display_info & IORESP_INT ) - setflag(r, IORESP_INT, (B & b) != 0); - *p_resp_info = r; - return true; - } -}; diff --git a/idasdk75/module/java/ana.cpp b/idasdk75/module/java/ana.cpp deleted file mode 100644 index 513f8a3..0000000 --- a/idasdk75/module/java/ana.cpp +++ /dev/null @@ -1,577 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "java.hpp" - -//---------------------------------------------------------------------- -int java_t::LoadIndex(insn_t &insn) -{ - ushort top; - - insn.Op1.type = o_mem; -// insn.Op1.ref = 0; - insn.Op1.offb = char(insn.size); - top = insn.wid ? insn.get_next_word() : insn.get_next_byte(); - insn.Op1.addr = top; - if ( ((insn.Op1.dtype == dt_qword || insn.Op1.dtype == dt_double) && !++top) - || top >= curSeg.DataSize ) - { - if ( !debugmode ) - return 0; - ++insn.Op1.ref; - } - return 1; -} - -//---------------------------------------------------------------------- -void copy_const_to_opnd(op_t &x, const const_desc_t &co) -{ - x.addr = co.value2; - x.value = co.value; -#ifdef __EA64__ - // in 64-bit version of IDA the 'value' field is 64bit, so copy the value - // there - x.value = make_ulonglong((uint32)x.value, (uint32)x.addr); -#endif -} - -//---------------------------------------------------------------------- -int java_t::ConstLoad(insn_t &insn, CIC_param ctype) -{ - const_desc_t cntopis; - - insn.Op1.type = o_cpool; -// insn.Op1.ref = 0; - - if ( !insn.Op1.cp_ind ) - goto dmpchk; //NULL Ptr - - if ( !LoadOpis(lm_normal, insn.Op1.cp_ind, 0, &cntopis) ) - goto dmpchk; - - CASSERT(offsetof(const_desc_t,flag) == (offsetof(const_desc_t,type) + sizeof(uchar) ) - && (sizeof(cntopis.type) == sizeof(uchar)) - && (sizeof(cntopis.flag) == sizeof(uchar)) - && (sizeof(insn.Op1.cp_type) >= (2*sizeof(uchar))) - && (sizeof(ushort) == sizeof(insn.Op1.cp_type))); - insn.Op1.cp_type = *((ushort *)&cntopis.type); - - switch ( ctype ) - { - case C_Class: - if ( cntopis.type != CONSTANT_Class ) - break; - //PASS THRU - case C_4byte: // ldc/ldcw - switch ( cntopis.type ) - { - case CONSTANT_Class: - if ( !(cntopis.flag & HAS_CLSNAME) ) - goto wrnret; - insn.Op1.addr = 0x10001ul * (ushort)fmt_fullname; -loadref1: - insn.xtrn_ip = cntopis.ref_ip; - //PASS THRU - case CONSTANT_Integer: - case CONSTANT_Float: - case CONSTANT_String: - insn.Op1.value = cntopis.value; // for string index to Utf8 - return 1; // or TWO index for other - default: - break; - } - break; - - case C_8byte: - if ( cntopis.type == CONSTANT_Long || cntopis.type == CONSTANT_Double ) - goto load2; - break; - - case C_Field: - if ( cntopis.type != CONSTANT_Fieldref ) - break; - if ( (cntopis.flag & NORM_FIELD) != NORM_FIELD ) - goto wrnret; -loadref2: - insn.xtrn_ip = cntopis.ref_ip; -load2: - copy_const_to_opnd(insn.Op1, cntopis); // for string index to Utf8 - return 1; - - case C_Interface: - if ( cntopis.type == CONSTANT_InterfaceMethodref ) - goto methodchk; - break; - case C_Method: - if ( cntopis.type != CONSTANT_Methodref ) - break; -methodchk: - if ( (cntopis.flag & NORM_METOD) == NORM_METOD ) - goto loadref2; //load 3 ind. & xtrn_ref - goto wrnret; - - case C_CallSite: - if ( cntopis.type != CONSTANT_InvokeDynamic ) - break; - goto wrnret; - - case C_Type: - if ( cntopis.type != CONSTANT_Class ) - break; - if ( !(cntopis.flag & HAS_TYPEDSCR) ) - goto wrnret; - insn.Op1.addr = ((uint32)fmt_FieldDescriptor << 16) | (ushort)fmt_ClassName; - goto loadref1; //load 1 ind. - - case C_TypeName: - if ( cntopis.type != CONSTANT_Class ) - break; - if ( !(cntopis.flag & (HAS_TYPEDSCR | HAS_CLSNAME)) ) - goto wrnret; - insn.Op1.addr = ((uint32)fmt_ClassName_or_Array << 16) - | (ushort)((cntopis.flag & HAS_CLSNAME) - ? fmt_fullname - : fmt_ClassName); - goto loadref1; //load 1 ind. - - default: - warning("Illegal CIC call (%x)", ctype); - return 0; - } -dmpchk: - if ( !debugmode ) - return 0; - ++insn.Op1.ref; -wrnret: - ++insn.Op1.ref; - insn.Op1.addr_shorts.low = insn.Op1.cp_ind; // for dmp out - return 1; -} - -//---------------------------------------------------------------------- -int java_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - - CIC_param ctype; - segment_t *s = getMySeg(insn.ea); // also set curSeg - - if ( s->type != SEG_CODE || insn.ip >= curSeg.CodeSize ) - { - warning("Can't decode non-code fragment!"); - return 0; - } - - insn.Op1.dtype = dt_void; - insn.wid = insn.swit = 0; - insn.Op1.ref = 0; - - insn.itype = insn.get_next_byte(); - if ( insn.itype == j_wide ) - { - insn.itype = insn.get_next_byte(); - if ( insn.itype == j_iinc - || (insn.itype >= j_iload && insn.itype <= j_aload) - || (insn.itype >= j_istore && insn.itype <= j_astore) - || insn.itype == j_ret ) - { - insn.wid = 1; //_w - } - else - { - if ( !debugmode ) - return 0; - insn.size = 1; - insn.itype = j_wide; - } - } - - if ( insn.itype >= j_lastnorm ) - { - if ( !debugmode ) - return 0; - if ( insn.itype < j_quick_last ) - { - static const uchar redefcmd[j_quick_last - j_lastnorm] = - { - j_ldc, //j_ldc_quick - j_ldcw, //j_ldcw_quick - j_ldc2w, //j_ldc2w_quick - j_getfield, //j_getfield_quick - j_putfield, //j_putfield_quick - j_getfield, //j_getfield2_quick - j_putfield, //j_putfield2_quick - j_getstatic, //j_getstatic_quick - j_putstatic, //j_putstatic_quick - j_getstatic, //j_getstatic2_quick - j_putstatic, //j_putstatic2_quick - j_invokevirtual, //j_invokevirtual_quick - j_invokespecial, //j_invokenonvirtual_quick - j_a_invokesuper, //j_invokesuper_quick - j_invokestatic, //j_invokestatic_quick - j_invokeinterface, //j_invokeinterface_quick - j_a_invokevirtualobject, //j_invokevirtualobject_quick - j_a_invokeignored, //j_invokeignored_quick - j_new, //j_new_quick - j_anewarray, //j_anewarray_quick - j_multianewarray, //j_multianewarray_quick - j_checkcast, //j_checkcast_quick - j_instanceof, //j_instanceof_quick - j_invokevirtual, //j_invokevirtual_quick_w - j_getfield, //j_getfield_quick_w - j_putfield //j_putfield_quick_w - }; - - insn.wid = 2; //_quick; - switch ( insn.itype ) - { - case j_getstatic2_quick: - case j_putstatic2_quick: - case j_getfield2_quick: - case j_putfield2_quick: - insn.wid = 3; //2_quick - break; - case j_invokevirtual_quick_w: - case j_getfield_quick_w: - case j_putfield_quick_w: - insn.wid = 4; //_quick_w - break; - default: - break; - } - insn.itype = redefcmd[insn.itype - j_lastnorm]; - } - else if ( insn.itype < j_software ) - { - return 0; - } - else - { - insn.itype -= (j_software - j_a_software); - } - } -//--- - switch ( insn.itype ) - { - default: - { - uint refs, ref2f; - - if ( insn.itype >= j_iload_0 && insn.itype <= j_aload_3 ) - { - refs = (insn.itype - j_iload_0) % 4; - ref2f = (insn.itype - j_iload_0) / 4; - ref2f = ref2f == ((j_lload_0 - j_iload_0) / 4) - || ref2f == ((j_dload_0 - j_iload_0) / 4); - goto refer; - } - if ( insn.itype >= j_istore_0 && insn.itype <= j_astore_3 ) - { - refs = (insn.itype - j_istore_0) % 4; - ref2f = (insn.itype - j_istore_0) / 4; - ref2f = ref2f == ((j_lstore_0 - j_istore_0) / 4) - || ref2f == ((j_dstore_0 - j_istore_0) / 4); -refer: - insn.Op1.addr = curSeg.DataBase + (ushort)refs; - insn.Op1.ref = (uchar)(ref2f + 1); - if ( (ushort)(refs + ref2f) >= curSeg.DataSize ) - insn.Op1.ref |= 0x80; - break; - } - } // end refs/refx - if ( insn.itype < j_ifeq || insn.itype > j_jsr ) - break; - case j_ifnull: - case j_ifnonnull: - insn.Op1.addr = (short)insn.get_next_word(); -b_near: - insn.Op1.type = o_near; - insn.Op1.offb = 1; - insn.Op1.addr += insn.ip; - if ( insn.Op1.addr >= curSeg.CodeSize ) - goto set_bad_ref; - break; - - case j_goto_w: - case j_jsr_w: - insn.Op1.addr = insn.get_next_dword(); - goto b_near; - - case j_bipush: - insn.Op1.dtype = dt_byte; - insn.Op1.value = (char)insn.get_next_byte(); - goto setdat; - case j_sipush: - insn.Op1.dtype = dt_word; - insn.Op1.value = (short)insn.get_next_word(); -setdat: - insn.Op1.type = o_imm; - insn.Op1.offb = 1; - break; - - case j_ldc: - insn.Op1.cp_ind = insn.get_next_byte(); - ctype = C_4byte; - goto constchk; - case j_ldcw: - ctype = C_4byte; - goto const2w; - case j_ldc2w: - ctype = C_8byte; -const2w: - insn.Op1.cp_ind = insn.get_next_word(); -constchk: - if ( !ConstLoad(insn, ctype) ) - return 0; - break; - - case j_getstatic: - case j_putstatic: - case j_getfield: - case j_putfield: - if ( insn.wid > 1 ) //_quick form - { - insn.Op1.type = o_imm; - insn.Op1.ref = 2; //#data - insn.Op1.offb = 1; - if ( insn.wid == 4 ) - { - insn.Op1.dtype = dt_word; - insn.Op1.value = insn.get_next_word(); - } - else - { - insn.Op1.dtype = dt_byte; - insn.Op1.value = insn.get_next_byte(); - ++insn.size; // SKIP - } - break; - } - ctype = C_Field; - goto const2w; - - case j_new: - ctype = C_Class; - goto const2w; - - case j_anewarray: -//\\ ?/ - case j_checkcast: - case j_instanceof: - ctype = C_TypeName; - goto const2w; - - case j_a_invokesuper: - case j_a_invokeignored: - goto fictarg; - case j_invokevirtual: - case j_a_invokevirtualobject: - insn.Op2.dtype = dt_void; - if ( insn.wid > 1 ) - { - if ( insn.wid == 4 ) - { -fictarg: - insn.Op1.value = insn.get_next_word(); //??? - insn.Op1.dtype = dt_word; - } - else - { - insn.Op2.type = o_imm; - insn.Op1.ref = 2; //#data - insn.Op1.dtype = insn.Op2.dtype = dt_byte; - insn.Op1.value = insn.get_next_byte(); - insn.Op2.offb = 2; - insn.Op2.value = insn.get_next_byte(); - } - insn.Op1.offb = 1; - insn.Op1.type = o_imm; - insn.Op1.ref = 2; //#data - break; - } - // fallthrough - case j_invokespecial: - case j_invokestatic: - ctype = C_Method; - goto const2w; - case j_invokedynamic: - ctype = C_CallSite; - insn.Op1.cp_ind = insn.get_next_word(); - if ( !ConstLoad(insn, ctype) ) - return 0; - insn.get_next_word(); // eat two mandatory 0's - insn.Op1.ref = 0; - break; - case j_invokeinterface: - ctype = C_Interface; - insn.Op1.cp_ind = insn.get_next_word(); - insn.Op2.type = o_imm; - insn.Op2.ref = 1; //not descriptor - insn.Op2.dtype = dt_byte; - insn.Op2.value = insn.get_next_byte(); - if ( insn.wid > 1 ) - { - insn.Op3.type = o_imm; - insn.Op3.ref = 2; //#data - insn.Op3.value = insn.get_next_byte(); - insn.Op3.offb = 4; - insn.Op3.dtype = dt_byte; - } - else - { - ++insn.size; //reserved - insn.Op3.dtype = dt_void; - } - goto constchk; - - case j_multianewarray: - insn.Op1.cp_ind = insn.get_next_word(); - insn.Op2.type = o_imm; - insn.Op2.ref = 1; // not descriptor - insn.Op2.dtype = dt_byte; - insn.Op2.value = insn.get_next_byte(); - if ( insn.Op2.value == 0 && !debugmode ) - return 0; - ctype = C_Type; - goto constchk; - - case j_iinc: - case j_iload: - case j_istore: - insn.Op1.dtype = dt_dword; - goto memref; - case j_lload: - case j_lstore: - insn.Op1.dtype = dt_qword; - goto memref; - case j_fload: - case j_fstore: - insn.Op1.dtype = dt_float; - goto memref; - case j_dload: - case j_dstore: - insn.Op1.dtype = dt_double; - goto memref; - case j_aload: - case j_astore: - insn.Op1.dtype = dt_string; - goto memref; - case j_ret: - insn.Op1.dtype = dt_code; -memref: - if ( !LoadIndex(insn) ) - return 0; - if ( insn.itype == j_iinc ) - { - insn.Op2.type = o_imm; - insn.Op2.ref = 0; - insn.Op2.offb = (uchar)insn.size; - if ( insn.wid ) - { - insn.Op2.dtype = dt_word; - insn.Op2.value = (short)insn.get_next_word(); - } - else - { - insn.Op2.dtype = dt_byte; - insn.Op2.value = (char)insn.get_next_byte(); - } - } - break; - - case j_tableswitch: - case j_lookupswitch: - { - int32 count; - uint32 top; - - insn.swit = 1; - for ( top = (4 - uint32((insn.ip + insn.size) % 4)) & 3; top; top-- ) - { - if ( insn.get_next_byte() ) - { - if ( !debugmode ) - return 0; - insn.swit |= 0100; - } - } - insn.Op3.type = o_near; - insn.Op3.offb = (uchar)insn.size; - insn.Op3.addr = insn.get_next_dword(); - insn.Op3.addr += insn.ip; - insn.Op3.ref = 0; - - if ( insn.Op3.addr >= curSeg.CodeSize ) - { - if ( !debugmode ) - return 0; - ++insn.Op3.ref; - } - - insn.swit |= 2; // start out arguments - - count = insn.get_next_dword(); - if ( insn.itype == j_tableswitch ) - { - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_dword; - insn.Op1.value = count; // minimal value - insn.Op2.ref = 0; - insn.Op2.type = o_imm; - insn.Op2.dtype = dt_dword; - count = (uint32(insn.Op2.value = insn.get_next_dword()) - count + 1); - } - insn.Op3.value = count; - insn.Op2.addr = insn.ip + insn.size; - top = uint32(curSeg.CodeSize - insn.ip); - while ( count-- ) - { - if ( insn.itype == j_lookupswitch ) - insn.get_next_dword(); // skip pairs; - if ( (insn.ip + insn.get_next_dword()) >= curSeg.CodeSize ) - { - if ( !debugmode ) - return 0; - insn.swit |= 0200; - } - if ( (uint32)insn.size >= top ) - return 0; - } - } - break; - - case j_newarray: - insn.Op1.type = o_array; // type! - insn.Op1.offb = 1; - insn.Op1.cp_type = insn.get_next_byte(); - if ( insn.Op1.cp_type < T_BOOLEAN || (uchar)insn.Op1.cp_type > T_LONG ) - { -set_bad_ref: - if ( !debugmode ) - return 0; - ++insn.Op1.ref; - } - break; - } // switch ( insn.itype ) - - return insn.size; -} - -//---------------------------------------------------------------------- - -bool idaapi can_have_type(const op_t &x) -{ - if ( x.type == o_cpool ) - return (uchar)x.cp_type == CONSTANT_Integer - || (uchar)x.cp_type == CONSTANT_Long; - return x.type == o_imm; -} diff --git a/idasdk75/module/java/classfil.hpp b/idasdk75/module/java/classfil.hpp deleted file mode 100644 index 079eb13..0000000 --- a/idasdk75/module/java/classfil.hpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _CLASSFIL_HPP_ -#define _CLASSFIL_HPP_ -// -// Java File definition -// -#define MAGICNUMBER 0xcafebabeUL // magic number - -// Oracle's Java Virtual Machine implementation in JDK release 1.0.2 -// supports class file format versions 45.0 through 45.3 inclusive. JDK -// releases 1.1.* support class file format versions in the range 45.0 -// through 45.65535 inclusive. For k >= 2, JDK release 1.k supports class -// file format versions in the range 45.0 through 44+k.0 inclusive. - -#define JDK_1_02_MINOR 2 // (45.2) JDK1.0 -#define JDK_1_1_MINOR 3 // (45.3) JDK1.1 -#define JDK_MIN_MAJOR 45 // JDK1.0/JDK1.1 -#define JDK_MAX_MAJOR (44+11)// JDK1.11(JDK11): Java11? -// -// access_flags -// -#define ACC_PUBLIC 0x0001 //Visible to everyone -#define ACC_PRIVATE 0x0002 //Visible only to the defning -#define ACC_PROTECTED 0x0004 //Visible to subclasses -#define ACC_STATIC 0x0008 //Variable or method is static Method -#define ACC_FINAL 0x0010 //No further subclassing, overriding, or - //assignment after initialization -#define ACC_SYNCHRONIZED 0x0020 //Wrap use in monitor lock -#define ACC_SUPER 0x0020 //invoke by the 'invokespecial' (deprecated) -#define ACC_VOLATILE 0x0040 //Can't cache (field) -#define ACC_BRIDGE 0x0040 //Bridge method (java5) (generate by compiler) -#define ACC_TRANSIENT 0x0080 //Not to be written or read by - //a persistent object manager (field) -#define ACC_VARARGS 0x0080 //Method with variable number of arguments - //(java5) -#define ACC_NATIVE 0x0100 //Implemented in a language otherthan Java -#define ACC_INTERFACE 0x0200 //Is an interface -#define ACC_ABSTRACT 0x0400 //No body provided -#define ACC_STRICT 0x0800 //Delcared strictfp (floating-point mode - //is FP-strict) (method) -#define ACC_SYNTHETIC 0x1000 //Generate by compiler (no present in source) - //(java2) -#define ACC_ANNOTATION 0x2000 //only with INTERFACE (annotated) (java5) -#define ACC_ENUM 0x4000 //Class or BaseClass is enum (java5) -/* jdk1.5 -ACC_BRIDGE, ACC_VARARGS, ACC_STRICT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM -*/ -// -#define ACC_ACCESS_MASK (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE) -#define _ACC_ALLTP (ACC_ACCESS_MASK | ACC_STATIC | ACC_FINAL \ - | ACC_SYNTHETIC) - -#define ACC_THIS_MASK (ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE \ - | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION \ - | ACC_ENUM) -#define ACC_NESTED_MASK (_ACC_ALLTP | ACC_INTERFACE | ACC_ABSTRACT \ - | ACC_ANNOTATION | ACC_ENUM) -#define ACC_FIELD_MASK (_ACC_ALLTP | ACC_VOLATILE | ACC_TRANSIENT | ACC_ENUM) -#define ACC_METHOD_MASK (_ACC_ALLTP | ACC_SYNCHRONIZED | ACC_BRIDGE \ - | ACC_VARARGS | ACC_NATIVE | ACC_ABSTRACT \ - | ACC_STRICT) - -//----------------------------------- -// base type -// -#define j_byte 'B' //signed byte -#define j_char 'C' //unicode character -#define j_double 'D' //double precision IEEE float -#define j_float 'F' //single precision IEEE foat -#define j_int 'I' //integer -#define j_long 'J' //long integer -#define j_class 'L' //<fullclassname>; - // ... an object of the given class -#define j_endclass ';' //tag for end of classname -#define j_parm_list_start '(' //start of function parameters -#define j_parm_list_end ')' //end of function parameters -#define j_short 'S' //signed short -#define j_bool 'Z' //boolean true or false -#define j_array '[' //<length><field sig> ... array -#define j_void_ret 'V' // return no value -//----------- make as mnemonic in new version -#define j_field_dlm '.' // use as field delimiter -#define j_clspath_dlm '/' // uase ass classpath delimeter -//#define j_legacy_dlm '$' // mechanically generated & legacy systems -//----------- jdk1.5 -//signatures -#define j_typeref 'T' // TypeVariable signature -#define j_throw '^' // ThrowsSignature start -#define j_wild '*' // wildcard(unknown) <?> -#define j_wild_e '+' // wildcard(extends) <+name> -#define j_wild_s '-' // wildcard(super) <-name> -// type declaration syntax: <name:typesign> -// iface declaration syntax: <name:typesign:ifacesign> -// super declaration syntax: -#define j_sign '<' // formal type parameter start -#define j_endsign '>' // formal type parameter end -#define j_tag ':' // delimeter - -// annotation tags -// possible const types is: B, C, D, F, I, J, S, Z, [ -// additional annotation tag types -#define j_string 's' // constant string -#define j_enumconst 'e' // enum (type + name) -#define j_class_ret 'c' // return type descriptor -#define j_annotation '@' // nested annotation - -//----------------------------------------------------- -// Constant Pool -// -#define CONSTANT_Asciz 1 //jdk1.1 -#define CONSTANT_Utf8 1 //jdk1.x -#define CONSTANT_Unicode 2 //unused if jdk >= 1.0 (45.2) -#define CONSTANT_Integer 3 -#define CONSTANT_Float 4 -#define CONSTANT_Long 5 -#define CONSTANT_Double 6 -#define CONSTANT_Class 7 -#define CONSTANT_String 8 -#define CONSTANT_Fieldref 9 -#define CONSTANT_Methodref 10 -#define CONSTANT_InterfaceMethodref 11 -#define CONSTANT_NameAndType 12 -#define MAX_CONSTANT_TYPE 12 // Check in Loader flag -// JDK1.7 (JSR 292) -- dynamic for multiLanguage (python, ruby, etc) -#define CONSTANT_MethodHandle 15 -#define CONSTANT_MethodType 16 -// JDK 1.8 -#define CONSTANT_InvokeDynamic 18 -#define CONSTANT_LAST CONSTANT_InvokeDynamic - -// JVM_CONSTANT_MethodHandle subtypes -#define JVM_REF_getField 1 -#define JVM_REF_getStatic 2 -#define JVM_REF_putField 3 -#define JVM_REF_putStatic 4 -#define JVM_REF_invokeVirtual 5 -#define JVM_REF_invokeStatic 6 -#define JVM_REF_invokeSpecial 7 -#define JVM_REF_newInvokeSpecial 8 -#define JVM_REF_invokeInterface 9 - -//------------------------------------------------------- -// Array Type (newarray) -// -#define T_BOOLEAN 4 -#define T_CHAR 5 -#define T_FLOAT 6 -#define T_DOUBLE 7 -#define T_BYTE 8 -#define T_SHORT 9 -#define T_INT 10 -#define T_LONG 11 - -//-------------------------------------------------------- -// StackMapTable records -#define JDK_SMF_MAJOR_MIN 50 // minimal version (previous: CLDC) -// offset for record 0 == offset, else previous_offset + offset + 1; -#define SMT_SAME_FRM_S0_min 0 // off_dt=type, loc=prev, stack=empty -#define SMT_SAME_FRM_S0_max 63 -#define SMT_SAME_FRM_S1_min 64 // off_dt=type-min, loc=prev, stack=1 -#define SMT_SAME_FRM_S1_max 127 // [ + verinf[1] ] -#define SMT_reserved_min 128 -#define SMT_reserved_max 246 -#define SMT_SAME_FRM_S1 247 // loc=prev, stack=1 [ + off_d, verinf[1] ] -#define SMT_CHOP_FRM_S0_min 248 // stack=empty, loc=prev-((max+1)-type) -#define SMT_CHOP_FRM_S0_max 250 // [ + off_dt ] -#define SMT_SAME_FRM_S0 251 // stack=empty, loca=prev [ + off_dt ] -#define SMT_APPE_FRM_S0_min 252 // stack=empty, loc+=prev+(type-(min-1)) -#define SMT_APPE_FRM_S0_max 254 // [ + off_dt, { verinf[n] } ] -#define SMT_FULL_FRAME 255 // see below -/* -struct sm_full -{ - u1 type; // for JDK16 or higher - u2 off_dt; // for StackMap - off - u2 nloc; - verinf locs[nlocks]; - u2 nstk; - verinf stks[nstk]; -}; -*/ -// Initial stack map frame: off=0, stack is free, max_locals, max_stack; - -// StackMap types -enum SM_ITEM // u1 -{ - ITEM_Bogus = 0, // unused (unknown type -- can't used directly) - ITEM_Integer, - ITEM_Float, - ITEM_Double, - ITEM_Long, - ITEM_Null, - ITEM_UnitializedThis, - ITEM_Object, // +pool_index - ITEM_Uninitialized, // +offset (u2) - // additional for out - ITEM_BADOBJECT, - ITEM_CURCLASS -}; - -#endif diff --git a/idasdk75/module/java/emu.cpp b/idasdk75/module/java/emu.cpp deleted file mode 100644 index 655d859..0000000 --- a/idasdk75/module/java/emu.cpp +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "java.hpp" - -static const char badlocvar[] = "Invalid local variable number"; - -//---------------------------------------------------------------------- -uval_t java_t::SearchFM(ushort name, ushort dscr, char *naprN) -{ - char buf[(qmax(sizeof(FieldInfo), sizeof(SegInfo))+1+3)&~3]; - sval_t pos = curClass.FieldCnt; - uint32 csz = sizeof(FieldInfo); - sval_t napr = *naprN; - - if ( napr != 1 ) - { - if ( napr != -1 ) - INTERNAL("SearchFM"); - pos = -(uval_t)curClass.MethodCnt; - csz = sizeof(SegInfo); - } - void *p = buf; - for ( ; pos; pos -= napr ) - { - if ( ClassNode.supval(pos, p, sizeof(buf)) != csz ) - DESTROYED("SearchFM"); - if ( ((_FMid_ *)p)->extflg & EFL_NAMETYPE - || CmpString(name, ((_FMid_ *)p)->name) - || CmpString(dscr, ((_FMid_ *)p)->dscr) ) - { - continue; - } - if ( napr >= 0 ) - return curClass.start_ea + ((FieldInfo *)p)->id.Number; - if ( ((SegInfo *)p)->CodeSize ) - *naprN = 0; - return ((SegInfo *)p)->start_ea; - } - return BADADDR; -} - -//------------------------------------------------------------------------ -void java_t::mark_and_comment(ea_t ea, const char *cmt) const -{ - remember_problem(PR_ATTN, ea); - if ( *cmt && (!has_cmt(get_flags(ea)) || ea == curClass.start_ea) ) - append_cmt(ea, cmt, false); -} - -//------------------------------------------------------------------------ -void java_t::TouchArg(const insn_t &insn, const op_t &x, bool isload) -{ - const char *p; - - switch ( x.type ) - { - case o_void: // not operand - break; - - case o_cpool: // ConstantPool reference (index) - if ( x.ref ) - { - p = x.ref == 1 - ? "Invalid string in constant pool" - : "Invalid index in constant pool"; - goto mark; - } - if ( x.cp_ind ) - { - ea_t ea; - char npr = -1; - - switch ( (uchar)x.cp_type ) - { - case CONSTANT_Fieldref: - npr = 1; - // fallthrough - case CONSTANT_InterfaceMethodref: - case CONSTANT_Methodref: - if ( !(x._subnam | x._name | x._class) ) - break; - if ( x._class == curClass.This.Dscr ) - { - ea = SearchFM(x._subnam, x._dscr, &npr); - if ( ea == BADADDR ) - break; - } - else - { - if ( !insn.xtrn_ip ) - break; - ea = insn.xtrn_ip == 0xFFFF - ? curClass.start_ea - : curClass.xtrnEA + insn.xtrn_ip; - if ( npr < 0 ) - npr = 0; - } - if ( npr <= 0 ) - { - insn.add_cref(ea, x.offb, fl_CF); - if ( !npr ) - auto_cancel(ea, ea+1); - } - else - { - dref_t type = insn.itype == j_putstatic || insn.itype == j_putfield - ? dr_W - : dr_R; - insn.add_dref(ea, x.offb, type); - } - break; - - case CONSTANT_Class: - if ( insn.xtrn_ip ) - { - ea_t target = insn.xtrn_ip == 0xFFFF - ? curClass.start_ea - : curClass.xtrnEA + insn.xtrn_ip; - insn.add_dref(target, x.offb, dr_I); - } - break; - default: - break; - } - } - break; - - case o_array: // type! - if ( x.ref ) - { - p = "Invalid array type"; - goto mark; - } - break; - - case o_imm: //const (& #data) - if ( x.ref < 2 ) - set_immd(insn.ea); - break; - - case o_mem: // local data pool - if ( x.ref ) - { - p = badlocvar; -mark: - mark_and_comment(insn.ea, p); - } - else - { - dref_t ref = isload ? dr_R : dr_W; - ea_t adr = curSeg.DataBase + x.addr; - insn.add_dref(adr, x.offb, ref); - if ( (x.dtype == dt_qword || x.dtype == dt_double) - && get_item_size(adr) <= 1 ) - { - insn.add_dref(adr + 1, x.offb, ref); - } - } - break; - - case o_near: - if ( x.ref ) - { - p = "Invalid jump address"; - goto mark; - } - insn.add_cref( - curSeg.start_ea + x.addr, - x.offb, - (Feature & CF_CALL) != 0 ? fl_CN : fl_JN); - break; - - default: - warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, - x.type); - break; - } -} - -//---------------------------------------------------------------------- -int java_t::emu(const insn_t &insn) -{ - Feature = insn.get_canon_feature(ph); - - if ( insn.wid > 1 ) - mark_and_comment(insn.ea, "Limited usage instruction"); - - if ( insn.itype >= j_a_software ) - mark_and_comment(insn.ea, "Undocumented instruction"); - - if ( insn.Op1.type == o_void && insn.Op1.ref ) - { - if ( (char)insn.Op1.ref < 0 ) - { - mark_and_comment(insn.ea, badlocvar); - } - else - { - dref_t ref = (insn.itype >= j_istore_0) ? dr_W : dr_R; - insn.add_dref(insn.Op1.addr, 0, ref); - if ( (insn.Op1.ref & 2) && get_item_size(insn.Op1.addr) <= 1 ) - insn.add_dref(insn.Op1.addr + 1, 0, ref); - } - } - - if ( Feature & CF_USE1 ) - TouchArg(insn, insn.Op1, true); - if ( Feature & CF_USE2 ) - TouchArg(insn, insn.Op2, true); - if ( Feature & CF_USE3 ) - TouchArg(insn, insn.Op3, true); - - if ( Feature & CF_CHG1 ) - TouchArg(insn, insn.Op1, false); - - if ( insn.swit ) // tableswitch OR lookupswitch - { - uval_t count, addr, rnum; - - if ( insn.swit & 0200 ) - mark_and_comment(insn.ea, badlocvar); - if ( insn.swit & 0100 ) - mark_and_comment(insn.ea, "Nonzero filler (warning)"); - - rnum = insn.Op2.value - 1; // for lookupswtitch - for ( addr=insn.Op2.addr, count=insn.Op3.value; count; addr +=4, count-- ) - { - uval_t refa; - - if ( insn.itype != j_lookupswitch ) - { - ++rnum; - } - else - { - rnum = get_dword(curSeg.start_ea + addr); // skip pairs - addr += 4; - } - refa = insn.ip + get_dword(curSeg.start_ea + addr); - - if ( refa < curSeg.CodeSize ) - { - add_cref(insn.ea, (refa += curSeg.start_ea), fl_JN); - if ( !has_cmt(get_flags(refa)) ) - { - char str[32]; - qsnprintf(str, sizeof(str), "case %" FMT_EA "u", rnum); - set_cmt(refa, str, false); - } - } - } - } - - if ( !(Feature&CF_STOP) && (!(Feature&CF_CALL) || func_does_return(insn.ea)) ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - return 1; -} - -//---------------------------------------------------------------------- -size_t java_t::make_locvar_cmt(qstring *buf, const insn_t &insn) -{ - LocVar lv; - - if ( curSeg.varNode ) - { - const char *p = NULL; - uval_t idx = insn.Op1.addr; - - if ( insn.Op1.type == o_mem ) - { - if ( !insn.Op1.ref ) - { - switch ( insn.itype ) - { - case j_ret: - p = "Return"; - break; - case j_iinc: - p = "Add 8-bit signed const to"; - break; - default: - p = "Push"; - if ( insn.get_canon_feature(ph) & CF_CHG1 ) - p = "Pop"; - break; - } - } - } - else if ( insn.Op1.type == o_void - && (char)insn.Op1.ref >= 0 - && (int32)(idx -= curSeg.DataBase) >= 0 ) - { - p = "Push"; - if ( insn.itype >= j_istore_0 ) - p = "Pop"; - } - - if ( p != NULL && netnode(curSeg.varNode).supval(idx,&lv,sizeof(lv)) == sizeof(lv) ) - { - if ( fmtName(lv.var.Name, tmp_name, sizeof(tmp_name), fmt_UnqualifiedName) ) - return buf->sprnt("%s %s", p, tmp_name).length(); - } - } - return 0; -} diff --git a/idasdk75/module/java/ins.cpp b/idasdk75/module/java/ins.cpp deleted file mode 100644 index fa8fc33..0000000 --- a/idasdk75/module/java/ins.cpp +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include <ida.hpp> -#include <idp.hpp> -#include "ins.hpp" - -// ATTENTION: if change mnemonic(s) change version in 'jas_rw.cc' -const instruc_t Instructions[] = -{ - - //{ "", 0 }, // Unknown Operation - { "nop", 0 }, //Do nothing - { "aconst_null", 0 }, //Push null object reference - { "iconst_m1", 0 }, //Push integer constant -1 - { "iconst_0", 0 }, //Push the integer 0 - { "iconst_1", 0 }, //Push the integer 1 - { "iconst_2", 0 }, //Push the integer 2 - { "iconst_3", 0 }, //Push the integer 3 - { "iconst_4", 0 }, //Push the integer 4 - { "iconst_5", 0 }, //Push the integer 5 - { "lconst_0", 0 }, //Push the long integer 0 - { "lconst_1", 0 }, //Push the long integer 1 - { "fconst_0", 0 }, //Push the single-precision foating point 0.0 - { "fconst_1", 0 }, //Push the single-precision foating point 1.0 - { "fconst_2", 0 }, //Push the single-precision foating point 2.0 - { "dconst_0", 0 }, //Push the double-precision foating point 0.0 - { "dconst_1", 0 }, //Push the double-precision foating point 1.0 - { "bipush", CF_USE1 }, //Push one-byte integer - { "sipush", CF_USE1 }, //Push two-byte integer - { "ldc", CF_USE1 }, //Push item from constant pool (i1) - { "ldc_w", CF_USE1 }, //Push item from constant pool (i2) - { "ldc2_w", CF_USE1 }, //Push long or double from constant pool - { "iload", CF_USE1 }, //Push integer value of the local variable - { "lload", CF_USE1 }, //Push long value of the local variable - { "fload", CF_USE1 }, //Push single-float. val. of the local variable - { "dload", CF_USE1 }, //Push double-float. val. of the local variable - { "aload", CF_USE1 }, //Push object reference from the local variable - { "iload_0", 0 }, //Push integer value of the local variable #0 - { "iload_1", 0 }, //Push integer value of the local variable #1 - { "iload_2", 0 }, //Push integer value of the local variable #2 - { "iload_3", 0 }, //Push integer value of the local variable #3 - { "lload_0", 0 }, //Push long value of the local variable #0 - { "lload_1", 0 }, //Push long value of the local variable #1 - { "lload_2", 0 }, //Push long value of the local variable #2 - { "lload_3", 0 }, //Push long value of the local variable #3 - { "fload_0", 0 }, //Push single-flt. val. of the local variable #0 - { "fload_1", 0 }, //Push single-flt. val. of the local variable #1 - { "fload_2", 0 }, //Push single-flt. val. of the local variable #2 - { "fload_3", 0 }, //Push single-flt. val. of the local variable #3 - { "dload_0", 0 }, //Push double-flt. val. of the local variable #0 - { "dload_1", 0 }, //Push double-flt. val. of the local variable #1 - { "dload_2", 0 }, //Push double-flt. val. of the local variable #2 - { "dload_3", 0 }, //Push double-flt. val. of the local variable #3 - { "aload_0", 0 }, //Push object reference from the local var. #0 - { "aload_1", 0 }, //Push object reference from the local var. #1 - { "aload_2", 0 }, //Push object reference from the local var. #2 - { "aload_3", 0 }, //Push object reference from the local var. #3 - { "iaload", 0 }, //Push integer from array - { "laload", 0 }, //Push long from array - { "faload", 0 }, //Push single float from array - { "daload", 0 }, //Push double float from array - { "aaload", 0 }, //Push object reference from array - { "baload", 0 }, //Push signed byte from array - { "caload", 0 }, //Push signed char from array - { "saload", 0 }, //Push short from array - { "istore", CF_CHG1 }, //Pop integer value into local variable - { "lstore", CF_CHG1 }, //Pop long value into local variable - { "fstore", CF_CHG1 }, //Pop single float value into local variable - { "dstore", CF_CHG1 }, //Pop double float value into local variable - { "astore", CF_CHG1 }, //Pop object refernce into local variable - { "istore_0", 0 }, //Pop integer value into local variable #0 - { "istore_1", 0 }, //Pop integer value into local variable #1 - { "istore_2", 0 }, //Pop integer value into local variable #2 - { "istore_3", 0 }, //Pop integer value into local variable #3 - { "lstore_0", 0 }, //Pop long value into local variable #0 - { "lstore_1", 0 }, //Pop long value into local variable #1 - { "lstore_2", 0 }, //Pop long value into local variable #2 - { "lstore_3", 0 }, //Pop long value into local variable #3 - { "fstore_0", 0 }, //Pop single float value into local variable #0 - { "fstore_1", 0 }, //Pop single float value into local variable #1 - { "fstore_2", 0 }, //Pop single float value into local variable #2 - { "fstore_3", 0 }, //Pop single float value into local variable #3 - { "dstore_0", 0 }, //Pop doublefloat value into local variable #0 - { "dstore_1", 0 }, //Pop doublefloat value into local variable #1 - { "dstore_2", 0 }, //Pop doublefloat value into local variable #2 - { "dstore_3", 0 }, //Pop doublefloat value into local variable #3 - { "astore_0", 0 }, //Pop object refernce into local variable #0 - { "astore_1", 0 }, //Pop object refernce into local variable #1 - { "astore_2", 0 }, //Pop object refernce into local variable #2 - { "astore_3", 0 }, //Pop object refernce into local variable #3 - { "iastore", 0 }, //Pop integer from array - { "lastore", 0 }, //Pop long from array - { "fastore", 0 }, //Pop single float from array - { "dastore", 0 }, //Pop double float from array - { "aastore", 0 }, //Pop object reference from array - { "bastore", 0 }, //Pop signed byte from array - { "castore", 0 }, //Pop signed char from array - { "sastore", 0 }, //Pop short from array - { "pop", 0 }, //Pop top stack word - { "pop2", 0 }, //Pop top two stack word - { "dup", 0 }, //Duplicate top stack word - { "dup_x1", 0 }, //Duplicate top stack word and put two down - { "dup_x2", 0 }, //Duplicate top stack word and put three down - { "dup2", 0 }, //Duplicate top two stack word - { "dup2_x1", 0 }, //Duplicate top two stack words and put two down - { "dup2_x2", 0 }, //Duplicate top two stack words and put three down - { "swap", 0 }, //Swap two top stack words - { "iadd", 0 }, //Integer add - { "ladd", 0 }, //Long add - { "fadd", 0 }, //Single float add - { "dadd", 0 }, //Double float add - { "isub", 0 }, //Integer subtract - { "lsub", 0 }, //Long subtract - { "fsub", 0 }, //Single float subtract - { "dsub", 0 }, //Double float subtract - { "imul", 0 }, //Integer multiply - { "lmul", 0 }, //Long multiply - { "fmul", 0 }, //Single float multiply - { "dmul", 0 }, //Double float multiply - { "idiv", 0 }, //Integer divide - { "ldiv", 0 }, //Long divide - { "fdiv", 0 }, //Single float divide - { "ddiv", 0 }, //Double float divide - { "irem", 0 }, //Integer remainder - { "lrem", 0 }, //Long remainder - { "frem", 0 }, //Single float remainder - { "drem", 0 }, //Double float remainder - { "ineg", 0 }, //Integer negate - { "lneg", 0 }, //Long negate - { "fneg", 0 }, //Single float negate - { "dneg", 0 }, //Double float negate - { "ishl", 0 }, //Integer shift left - { "lshl", 0 }, //Long shift left - { "ishr", 0 }, //Integer logical shift right - { "lshr", 0 }, //Long logical shift right - { "iushr", 0 }, //Integer arithmetic shift right - { "lushr", 0 }, //Long arithmeticshift right - { "iand", 0 }, //Integer boolean AND - { "land", 0 }, //Long boolean AND - { "ior", 0 }, //Integer boolean OR - { "lor", 0 }, //Long boolean OR - { "ixor", 0 }, //Integer boolean XOR - { "lxor", 0 }, //Long boolean XOR - { "iinc", CF_CHG1|CF_USE2 }, //Add 8-bit signed const to local variable - { "i2l", 0 }, //Integer to Long conversion - { "i2f", 0 }, //Integer to Single float conversion - { "i2d", 0 }, //Integer to Double float conversion - { "l2i", 0 }, //Long to Integer conversion - { "l2f", 0 }, //Long to Single float conversion - { "l2d", 0 }, //Long to Double float conversion - { "f2i", 0 }, //Single float to Integer conversion - { "f2l", 0 }, //Single float to Long conversion - { "f2d", 0 }, //Single float to Double float conversion - { "d2i", 0 }, //Double float to Integer conversion - { "d2l", 0 }, //Double float to Long conversion - { "d2f", 0 }, //Double float to Single float conversion - { "int2byte", 0 }, //Integer to signed byte conversion - { "int2char", 0 }, //Integer to unsigned short conversion - { "int2short", 0 }, //Integer to signed short conversion - { "lcmp", 0 }, //Long compare - { "fcmpl", 0 }, //Single float compare (-1 on NaN) - { "fcmpg", 0 }, //Single float compare (1 on NaN) - { "dcmpl", 0 }, //Double float compare (-1 on NaN) - { "dcmpg", 0 }, //Double float compare (1 on NaN) - { "ifeq", CF_USE1 }, //Branch if equal to 0 - { "ifne", CF_USE1 }, //Branch if not equal to 0 - { "iflt", CF_USE1 }, //Branch if less then 0 - { "ifge", CF_USE1 }, //Branch if greater than or equal to 0 - { "ifgt", CF_USE1 }, //Branch if greater than 0 - { "ifle", CF_USE1 }, //Branch if less than or equal to 0 - { "if_icmpeq", CF_USE1 }, //Branch if integers equal - { "if_icmpne", CF_USE1 }, //Branch if integers not equal - { "if_icmplt", CF_USE1 }, //Branch if integers less than - { "if_icmpge", CF_USE1 }, //Branch if integers grater than or equal to - { "if_icmpgt", CF_USE1 }, //Branch if integers grater than - { "if_icmple", CF_USE1 }, //Branch if integers less than or equal to - { "if_acmpeq", CF_USE1 }, //Branch if object references are equal - { "if_acmpne", CF_USE1 }, //Branch if object references not equal - { "goto", CF_USE1|CF_STOP }, //Branch always - { "jsr", CF_USE1|CF_CALL }, //Jump subroutine - { "ret", CF_USE1|CF_STOP }, //Return from subroutine - { "tableswitch", CF_USE1|CF_USE2|CF_USE3 }, //Access jump table by index and jump - { "lookupswitch", CF_USE1|CF_USE2 }, //Access jump table by key match and jump - { "ireturn", CF_STOP }, //Return integer from function - { "lreturn", CF_STOP }, //Return long from function - { "freturn", CF_STOP }, //Return single float from function - { "dreturn", CF_STOP }, //Return double float from function - { "areturn", CF_STOP }, //Return object reference from function - { "return", CF_STOP }, //Return (void) from procedure - { "getstatic", CF_USE1 }, //Set static field from class - { "putstatic", CF_USE1 }, //Set static field in class - { "getfield", CF_USE1 }, //Fetch field from object - { "putfield", CF_CHG1 }, //Set field in object - { "invokevirtual", CF_USE1|CF_USE2|CF_CALL }, //invoke instance method - { "invokespecial", CF_USE1|CF_CALL }, //invoke instance method (super/private/init) - { "invokestatic", CF_USE1|CF_CALL }, //invoke a class (static) method - { "invokeinterface", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, //invoke interface method - { "invokedynamic", CF_USE1|CF_USE2|CF_CALL }, // - { "new", CF_USE1 }, //Create new object - { "newarray", CF_USE1 }, //Allocate new array - { "anewarray", CF_USE1 }, //Allocate new array of references to object - { "arraylength", 0 }, //Get length of array - { "athrow", CF_STOP }, //Throw exception or error - { "checkcast", CF_USE1 }, //Make sure object is of given type - { "instanceof", CF_USE1 }, //Determine if an object is of given type - { "monitorenter", 0 }, //Enter monitored region of code - { "monitorexit", 0 }, //Exit monitored region of code - { "wide", 0 }, //WIDE PREFIX of Command - { "multianewarray", CF_USE1|CF_USE2 }, //Allocate new multidimensional array - { "ifnull", CF_USE1 }, //Branch if NULL-ptr - { "ifnonnull", CF_USE1 }, //Branch if not NULL-ptr - { "goto_w", CF_USE1 }, //Branch always (wide index) - { "jsr_w", CF_USE1 }, //Jump subroutine (wide index) - { "breakpoint", 0 }, //Stop and pass control to breakpoint handler - //{ "ret_w", CF_USE1 }, //Return from subroutine (wide index) - //Pseudocode for quick - { "invokesuper", CF_USE1|CF_CALL }, - { "invokevirtualobject", CF_USE1|CF_USE2|CF_CALL }, - { "invokeignored", CF_USE1 }, - //SUN-dependet - { "software", 0 }, - { "hardware", 0 } - -}; - -CASSERT(qnumber(Instructions) == j_last); diff --git a/idasdk75/module/java/ins.hpp b/idasdk75/module/java/ins.hpp deleted file mode 100644 index 20254e0..0000000 --- a/idasdk75/module/java/ins.hpp +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-2020 Hex-Rays - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - - -extern const instruc_t Instructions[]; -enum nameNum ENUM_SIZE(uint16) -{ - //j_null = 0, // Unknown Operation - j_nop = 0, // 0 //Do nothing - j_aconst_null, // 1 //Push null object reference - j_iconst_m1, // 2 //Push integer constant -1 - j_iconst_0, // 3 //Push the integer 0 - j_iconst_1, // 4 //Push the integer 1 - j_iconst_2, // 5 //Push the integer 2 - j_iconst_3, // 6 //Push the integer 3 - j_iconst_4, // 7 //Push the integer 4 - j_iconst_5, // 8 //Push the integer 5 - j_lconst_0, // 9 //Push the long integer 0 - j_lconst_1, // 10 //Push the long integer 1 - j_fconst_0, // 11 //Push the single-precision foating point 0.0 - j_fconst_1, // 12 //Push the single-precision foating point 1.0 - j_fconst_2, // 13 //Push the single-precision foating point 2.0 - j_dconst_0, // 14 //Push the double-precision foating point 2.0 - j_dconst_1, // 15 //Push the double-precision foating point 2.0 - j_bipush, // 16 //Push one byte signed integer - j_sipush, // 17 //Push two-byte signed integer - j_ldc, // 18 //Push item from constant pool (i1) - j_ldcw, // 19 //Push item from constant pool (i2) - j_ldc2w, // 20 //Push long or double from constant pool - j_iload, // 21 //Push integer value of the local variable - j_lload, // 22 //Push long value of the local variable - j_fload, // 23 //Push single float value of the local variable - j_dload, // 24 //Push double float value of the local variable - j_aload, // 25 //Push object reference from the local variable - j_iload_0, // 26 //Push integer value of the local variable #0 - j_iload_1, // 27 //Push integer value of the local variable #1 - j_iload_2, // 28 //Push integer value of the local variable #2 - j_iload_3, // 29 //Push integer value of the local variable #3 - j_lload_0, // 30 //Push long value of the local variable #0 - j_lload_1, // 31 //Push long value of the local variable #1 - j_lload_2, // 32 //Push long value of the local variable #2 - j_lload_3, // 33 //Push long value of the local variable #3 - j_fload_0, // 34 //Push single float value of the local variable #0 - j_fload_1, // 35 //Push single float value of the local variable #1 - j_fload_2, // 36 //Push single float value of the local variable #2 - j_fload_3, // 37 //Push single float value of the local variable #3 - j_dload_0, // 38 //Push double float value of the local variable #0 - j_dload_1, // 39 //Push double float value of the local variable #1 - j_dload_2, // 40 //Push double float value of the local variable #2 - j_dload_3, // 41 //Push double float value of the local variable #3 - j_aload_0, // 42 //Push object reference from the local variable #0 - j_aload_1, // 43 //Push object reference from the local variable #1 - j_aload_2, // 44 //Push object reference from the local variable #2 - j_aload_3, // 45 //Push object reference from the local variable #3 - j_iaload, // 46 //Push integer from array - j_laload, // 47 //Push long from array - j_faload, // 48 //Push single float from array - j_daload, // 49 //Push double float from array - j_aaload, // 50 //Push object refernce from array - j_baload, // 51 //Push signed byte from array - j_caload, // 52 //Push character from array - j_saload, // 53 //Push short from array - j_istore, // 54 //Pop integer value into local variable - j_lstore, // 55 //Pop long value into local variable - j_fstore, // 56 //Pop single float value into local variable - j_dstore, // 57 //Pop double float value into local variable - j_astore, // 58 //Pop object refernce into local variable - j_istore_0, // 59 //Pop integer value into local variable #0 - j_istore_1, // 60 //Pop integer value into local variable #1 - j_istore_2, // 61 //Pop integer value into local variable #2 - j_istore_3, // 62 //Pop integer value into local variable #3 - j_lstore_0, // 63 //Pop long value into local variable #0 - j_lstore_1, // 64 //Pop long value into local variable #1 - j_lstore_2, // 65 //Pop long value into local variable #2 - j_lstore_3, // 66 //Pop long value into local variable #3 - j_fstore_0, // 67 //Pop single float value into local variable #0 - j_fstore_1, // 68 //Pop single float value into local variable #1 - j_fstore_2, // 69 //Pop single float value into local variable #2 - j_fstore_3, // 70 //Pop single float value into local variable #3 - j_dstore_0, // 71 //Pop double float value into local variable - j_dstore_1, // 72 //Pop double float value into local variable #0 - j_dstore_2, // 73 //Pop double float value into local variable #1 - j_dstore_3, // 74 //Pop double float value into local variable #2 - j_astore_0, // 75 //Pop object refernce into local variable #0 - j_astore_1, // 76 //Pop object refernce into local variable #1 - j_astore_2, // 77 //Pop object refernce into local variable #2 - j_astore_3, // 78 //Pop object refernce into local variable #3 - j_iastore, // 79 //Pop integer from array - j_lastore, // 80 //Pop long from array - j_fastore, // 81 //Pop single float from array - j_dastore, // 82 //Pop double float from array - j_aastore, // 83 //Pop object refernce from array - j_bastore, // 84 //Pop signed byte from array - j_castore, // 85 //Pop character from array - j_sastore, // 86 //Pop short from array - j_pop, // 87 //Pop top stack word - j_pop2, // 88 //Pop top two stack word - j_dup, // 89 //Duplicate top stack word - j_dup_x1, // 90 //Duplicate top stack word and put two down - j_dup_x2, // 91 //Duplicate top stack word and put three down - j_dup2, // 92 //Duplicate top two stack word - j_dup2_x1, // 93 //Duplicate top two stack words and put two down - j_dup2_x2, // 94 //Duplicate top two stack words and put three down - j_swap, // 95 //Swap two top stack words - j_iadd, // 96 //Integer add - j_ladd, // 97 //Long add - j_fadd, // 98 //Single float add - j_dadd, // 99 //Double float add - j_isub, //100 //Integer subtract - j_lsub, //101 //Long subtract - j_fsub, //102 //Single float subtract - j_dsub, //103 //Double Float subtract - j_imul, //104 //Integer multiply - j_lmul, //105 //Long multiply - j_fmul, //106 //Single float multiply - j_dmul, //107 //Double Float multiply - j_idiv, //108 //Integer divide - j_ldiv, //109 //Long divide - j_fdiv, //110 //Single float divide - j_ddiv, //111 //Double Float divide - j_irem, //112 //Integer reminder - j_lrem, //113 //Long reminder - j_frem, //114 //Single float reminder - j_drem, //115 //Double Float reminder - j_ineg, //116 //Integer negate - j_lneg, //117 //Long negate - j_fneg, //118 //Single float negate - j_dneg, //119 //Double Float negate - j_ishl, //120 //Integer shift left - j_lshl, //121 //Long shift left - j_ishr, //122 //Integer logical shift right - j_lshr, //123 //Long logical shift right - j_iushr, //124 //Integer arithmetic shift right - j_lushr, //125 //Long arithmeticshift right - j_iand, //126 //Integer boolean AND - j_land, //127 //Long boolean AND - j_ior, //128 //Integer boolean OR - j_lor, //129 //Long boolean OR - j_ixor, //130 //Integer boolean XOR - j_lxor, //131 //Long boolean XOR - j_iinc, //132 //Add 8-bit signed const to local variable - j_i2l, //133 //Integer to Long conversion - j_i2f, //134 //Integer to single float conversion - j_i2d, //135 //Integer to double float conversion - j_l2i, //136 //Long to Integer conversion - j_l2f, //137 //Long to single float conversion - j_l2d, //138 //Long to double float conversion - j_f2i, //139 //Single float to Integer conversion - j_f2l, //140 //Single float to Long conversion - j_f2d, //141 //Single float to double float conversion - j_d2i, //142 //Double float to Integer conversion - j_d2l, //143 //Double float to Long conversion - j_d2f, //144 //Double float to double float conversion - j_i2b, //145 //Integer to signed byte conversion - j_i2c, //146 //Integer to unsigned short conversion - j_i2s, //147 //Integer to signed short conversion - j_lcmp, //148 //Long compare - j_fcmpl, //149 //Single float compare (-1 on NaN) - j_fcmpg, //150 //Single float compare (1 on NaN) - j_dcmpl, //151 //Double float compare (-1 on NaN) - j_dcmpg, //152 //Double float compare (1 on NaN) - j_ifeq, //153 //Branch if equal to 0 - j_ifne, //154 //Branch if not equal to 0 - j_iflt, //155 //Branch if less then 0 - j_ifge, //156 //Branch if greater than or equal to 0 - j_ifgt, //157 //Branch if greater than 0 - j_ifle, //158 //Branch if less than or equal to 0 - j_if_icmpeq, //159 //Branch if integers equal - j_if_icmpne, //160 //Branch if integers not equal - j_if_icmplt, //161 //Branch if integers less than - j_if_icmpge, //162 //Branch if integers grater than or equal to - j_if_icmpgt, //163 //Branch if integers grater than - j_if_icmple, //164 //Branch if integers less than or equal to - j_if_acmpeq, //165 //Branch if object references are equal - j_if_acmpne, //166 //Branch if object references not equal - j_goto, //167 //Branch always - j_jsr, //168 //Jump subroutine - j_ret, //169 //Return from subroutine - j_tableswitch, //170 //Access jump table by index and jump - j_lookupswitch, //171 //Access jump table by key match and jump - j_ireturn, //172 //Return integer from function - j_lreturn, //173 //Return long from function - j_freturn, //174 //Return single floatr from function - j_dreturn, //175 //Return double float from function - j_areturn, //176 //Return object reference from function - j_return, //177 //Return (void) from procedure - j_getstatic, //178 //Set static field from class - j_putstatic, //179 //Set static field in class - j_getfield, //180 //Fetch field from object - j_putfield, //181 //Set field in object - j_invokevirtual, //182 //invoke instance method - j_invokespecial, //183 //invoke instance method (superclass/init/...) - j_invokestatic, //184 //invoke a class (static) method - j_invokeinterface, //185 //invoke interface method - j_invokedynamic, //186 // invoke instance method (select by paraneter) - j_new, //187 //Create new object - j_newarray, //188 //Allocate new array - j_anewarray, //189 //Allocate new array of refernces to object - j_arraylength, //190 //Get length of array - j_athrow, //191 //Throw exception or error - j_checkcast, //192 //Make sure object is of given type - j_instanceof, //193 //Determine if an object is of given type - j_monitorenter, //194 //Enter monitored region of code - j_monitorexit, //195 //Exit monitored region of code - j_wide, //196 //wide (prefix of command) - j_multianewarray, //197 //Allocate new multi-dimensional array - j_ifnull, //198 //Branch if NULL-ptr - j_ifnonnull, //199 //Branch if not NULL-ptr - j_goto_w, //200 //Branch always (wide index) - j_jsr_w, //201 //Jump subroutine (wide index) - j_breakpoint, //202 //Stop and pass control to breakpoint handler - // - j_lastnorm, - j_a_invokesuper = j_lastnorm, - j_a_invokevirtualobject, - j_a_invokeignored, - //bottom of table ! (emu) - j_a_software, - j_a_hardware, - // - j_last -}; - -enum name_quick -{ - j_ldc_quick = j_lastnorm, //203 (18) - j_ldcw_quick, //204 (19) - j_ldc2w_quick, //205 (20) - j_getfield_quick, //206 (180) - j_putfield_quick, //207 (181) - j_getfield2_quick, //208 - j_putfield2_quick, //209 - j_getstatic_quick, //210 (178) - j_putstatic_quick, //211 (179) - j_getstatic2_quick, //212 - j_putstatic2_quick, //213 - j_invokevirtual_quick, //214 (182) - j_invokenonvirtual_quick, //215 (183) - j_invokesuper_quick, //216 - j_invokestatic_quick, //217 (184) - j_invokeinterface_quick, //218 (185) - j_invokevirtualobject_quick, //219 - j_invokeignored_quick, //220 - j_new_quick, //221 (187) - j_anewarray_quick, //222 (189) - j_multianewarray_quick, //223 (197) - j_checkcast_quick, //224 (192) - j_instanceof_quick, //225 (193) - j_invokevirtual_quick_w, //226 - j_getfield_quick_w, //227 - j_putfield_quick_w, //228 - j_quick_last -}; - -#define j_software 254 -#define j_hardware 255 -#endif diff --git a/idasdk75/module/java/java.hpp b/idasdk75/module/java/java.hpp deleted file mode 100644 index c1818b3..0000000 --- a/idasdk75/module/java/java.hpp +++ /dev/null @@ -1,652 +0,0 @@ -//#define __debug__ - -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _JAVA_HPP -#define _JAVA_HPP - -#define VIEW_WITHOUT_TYPE // no show return/filed type in command if !jasmin() - -#include <set> -#include <pro.h> -#include "../idaidp.hpp" -#include <fpro.h> -#include <ieee.h> - -#include "classfil.hpp" -#include "ins.hpp" -struct java_t; - -#pragma pack(1) -//---------------------------------------------------------------------- -// Redefine temporary names -// -#define wid segpref -#define xtrn_ip auxpref - -#define swit Op1.specflag2 -#define ref specflag1 -#define _name value_shorts.low -#define _class value_shorts.high -#define _bmidx value_shorts.high -#define _mhr_kind value_shorts.low // MethodHandle reference_kind -#define _mhr_index value_shorts.high // MethodHandle reference_index -#define _mtd_index value_shorts.low // MethodType descriptor_index -#define _dscr addr_shorts.low -#define _subnam addr_shorts.high -#define cp_ind specval_shorts.low -#define cp_type specval_shorts.high -// nexts for Utf8 (on load) and _Ssize used in MAP only -#define _Ssize addr_shorts.low -#define _Sflags addr_shorts.high -#define _Sopstr value2 - -// command aliases -#define o_cpool o_idpspec0 -#define o_array o_idpspec1 - -//---------------------------------------------------------------------- -struct TXS -{ - const char *str; - uchar size; -}; -#define TXS_DECLARE(p) { p, (uchar)(sizeof(p)-1) } -#define TXS_EMPTY() { NULL, 0 } - -//---------------------------------------------------------------------- -struct const_desc_t -{ - uchar type; // CONSTANT_type - uchar flag; -#define _REF 0x01 // has reference -#define HAS_FLDNAME 0x02 // Utf8 is valid Field/Variable Name -#define HAS_TYPEDSCR 0x04 // Utf8 is valid Descriptor -#define HAS_CALLDSCR 0x08 // Utf8 is valid Descriptor for Method -#define HAS_CLSNAME 0x10 // Utf8 is valid as Class Name (Not FLD!) -#define SUB_FLDNAME 0x20 -#define SUB_TYPEDSCR 0x40 -#define SUB_CALLDSCR 0x80 -#define SUB_SHIFT 4 - CASSERT((HAS_FLDNAME << SUB_SHIFT) == SUB_FLDNAME - && (HAS_TYPEDSCR << SUB_SHIFT) == SUB_TYPEDSCR - && (HAS_CALLDSCR << SUB_SHIFT) == SUB_CALLDSCR); - - bool is_referenced() const { return (flag & _REF) != 0; } - void mark_referenced() { flag |= _REF; } - -#define NORM_FIELD (HAS_CLSNAME | SUB_FLDNAME | SUB_TYPEDSCR) -#define NORM_METOD (HAS_CLSNAME | SUB_FLDNAME | SUB_CALLDSCR) - - ushort ref_ip; // in xtrn-segment... - union - { - uint32 value; // low part of # value - struct - { - ushort low; // BegInd Utf8 (name) - ushort high; // index to _Class - } value_shorts; // unification - }; - union - { - uint32 value2; // hi part of # value - struct - { - ushort low; // TypeName - ushort high; // Descriptor - } addr_shorts; - }; -}; - -union Object -{ // in IDP_JDK12 format was in reverse order! - struct - { - ushort Name; // index to name - ushort Dscr; // index to descriptor - }; - uint32 Ref; // used in out -}; - -struct _FMid_ -{ - ushort name; // index to name - ushort dscr; // index to descriptor - ushort access; // access flag -// Number not needed for search/out - ushort Number; // Number of current Field or Method - uchar extflg; // for ERROR diagnostic and other flags -#define EFL_NAME 1 -#define EFL_TYPE 2 -#define EFL_NAMETYPE (EFL_NAME | EFL_TYPE) -//#define _OLD_EFL_ACCESS 4 -#define EFL__MASK (EFL_NAME | EFL_TYPE | 4) // for check on conversion -// next constant added in JDK15 store-format -// java-2 store format only -#define XFL_DEPRECATED 0x04 -#define XFL_UNICODENAME 0x08 // name contain unicode character -#define XFL_M_LABSTART 0x10 // for METHOD set label at entry -#define XFL_C_SUPEROBJ 0x10 // for THIS - parent(.super) == Object -#define XFL_M_LABEND 0x20 // for METHOD set label at exit -#define XFL_C_DEBEXT 0x20 // for THIS - have stored SourceDebugExtension -#define XFL_M_EMPTYSM 0x40 // for METHOD - have empty StackMap -#define XFL_C_ERRLOAD 0x40 // for THIS - have loadtime problems -#define XFL_C_DONE 0x80 // analisys pass complete -// next fields added in JDK15 store-format - uchar _UNUSED_ALING; // = 0 - ushort utsign; // index to signature attribute -}; - -struct FieldInfo -{ - _FMid_ id; // for search procedure - uval_t valNode; // init value's node -// next fields added in JDK15 store-format - uval_t annNodes[2]; // nodes for Vis/Invis annotation - uval_t genNode; // list of stored generic attributes -}; - -struct SegInfo -{ - _FMid_ id; // for search procedure - uint32 CodeSize; // CODE size - ea_t start_ea; // EA of Code (checker & slb) - ea_t DataBase; // EA of loc variable segment - ushort DataSize; // max locals (DATA size) - ushort stacks; // stack size - uval_t excNode; // Node for exception table - uval_t thrNode; // Node for throws (fmt change!) -// next fields added in JDK15 store-format - uval_t varNode; // LocVar descriptors - uval_t smNode; // StackMap descriptors - // Visible, Invisible, VisibleParam, InvisibleParam, Default - uval_t annNodes[5]; // nodes for all types of annotations - uval_t genNodes[2]; // list of stored generic attributes + code -}; - -struct ClassInfo -{ - ushort maxCPindex; // max valid index in ConstantPool - ushort MinVers; //-> of file - Object This; // class name/descriptor - Object super; // .super class (parent) - ushort AccessFlag; // access flags - ushort FieldCnt; // Field Declaration Counter - uval_t ClassNode; // Field (>0) & Method (<0) (0?) - ushort MethodCnt; // Method's Segment fot this Class - ushort SourceName; // Index of Utf8 Source File Name - uval_t impNode; // Node for Interfaces (fmt change!) - ea_t start_ea; // for SearchFM - uint32 maxSMsize; // optimize memory allocation (StackMap) - // ATT: JDK15 - previous errload - ea_t xtrnEA; // beg header segment - uval_t xtrnNode; // node for xtrn Segment - ushort xtrnCnt; // header size - ushort xtrnLQE; -// next fields added in JDK15 store-format - ushort MajVers; // -> of file - uchar extflg; // XFL_.... consts - uchar JDKsubver; // for speed/size ONLY - uval_t innerNode; // Node for Inner classes - ushort encClass; // EnclosingMethod class - ushort encMethod; // EnclosingMethod NameAndType - uval_t msgNode; // node for store loading messages - ushort utsign; // signature attribute index - ushort maxStrSz; // optimize memory allocation (string) - uval_t annNodes[2]; // nodes for Visible/Invisible - uint32 maxAnnSz; // optimize memory allocation (annotation) - uval_t genNode; // list of stored generic attributes -}; - -#define FOR_EACH_CONSTANT_POOL_INDEX(Binding) for ( ushort Binding = 1; Binding <= curClass.maxCPindex; ++Binding ) - - -struct Exception -{ - ushort start_pc; - ushort end_pc; - ushort handler_pc; - Object filter; -}; - -struct LocVar -{ - ushort ScopeBeg; // scope start - ushort ScopeTop; // scope end - Object var; // name & descriptor - ushort utsign; // signature attribute index -}; - -struct InnerClass -{ - ushort inner; - ushort outer; - ushort name; - ushort access; -}; - -//------------------------------------------------------------------------ -enum sm_node_t -{ - smn_aa_not_finished = -1, - smn_ok = 0, - smn_no_use = 1, -}; -#define CNS_SOURCE -2 -#define CNS_CLASS 0 -//>0 - opis[i] -//>=0x10000 - string blobs -#define CNA_VERSION -1 -#define CNA_KWRDVER -2 -#define CNA_IDPFLAGS -3 // idpflags value -#define CNA_LIMITER -4 // user_limiter state -//>=0x10000 - string info -#define UR_TAG 'r' - -//------------------------------------------------------------------------ -// !DO NOT CHANGE ORDER! -enum fmt_t -{ - fmt_debug = 0, // as fmt_string, but have prompting - fmt_string, // string as text - fmt_string_single_quotes, - fmt_FieldDescriptor, - - // MethodTypeSignature: - // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* - // ^ - fmt_method_FormalTypeParameters, - - // MethodTypeSignature: - // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* - // ^ - fmt_method_ReturnType, - - // MethodTypeSignature: - // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* - // ^ - fmt_method_TypeSignature, - - // MethodTypeSignature: - // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* - // ^ - fmt_method_ThrowsSignature, - - fmt_ClassSignature, // class signature (start width <...:...>) - fmt_FieldDescriptor_nospace, // signature (==dscr, without space) - fmt_ClassName_or_Array, // if have '[' desriptor, else fieldname - fmt_ClassName, // extract class from descriptor - fmt_fullname, // full qualified name - fmt_UnqualifiedName, - fmt__ENDENUM - }; -#define FMT_ENC_RESERVED (uchar)0x80 - -//------------------------------------------------------------------------- -inline bool fmt_expects_call_descriptor(fmt_t fmt) -{ - return fmt >= fmt_method_FormalTypeParameters && fmt <= fmt_ClassSignature; -} - -//------------------------------------------------------------------------- -struct SMinfo // for sm_getinfo -{ - const uchar *pb; - const uchar *pe; - uint fcnt; - ea_t ea; -}; - -enum load_mode_t -{ - lm_lenient = -1, // don't call remember_problem() - lm_no_set_ref = 0, // no set reference - lm_normal = 1, // Normal mode - lm_need_cr = 2, // needed CR -}; -ea_t extract_name_ea( - char buf[MAXSTR], - const char *name, - int pos, - uchar clv); -const TXS *get_base_typename(uchar tag, bool or_void=false); - -#if defined(__debug__) || defined(TEST_FMTSTR) -NORETURN extern void _destroyed(const char *from); -NORETURN extern void _faterr(uchar mode, const char *from); -#define UNCOMPAT(p) _faterr(1, p) -#define INTERNAL(p) _faterr(0, p) -#define DESTROYED(p) _destroyed(p) -#else -NORETURN extern void _destroyed(void); -NORETURN extern void _faterr(uchar mode); -#define UNCOMPAT(p) _faterr(1) -#define INTERNAL(p) _faterr(0) -#define DESTROYED(p) _destroyed() -#endif - -uchar javaIdent(ushort v, uchar *isStart = NULL); - -// information record of StackMap -struct sm_info_t -{ - uint32 noff; // start offset in blob - uint32 eoff; // end offset in blob - uint fcnt; // locals at entry -}; - -//------------------------------------------------------------------------ -#ifdef __debug__ -#define DEB_ASSERT(cond, text) if ( cond ) error(text) -#else -#define DEB_ASSERT(cond, text) -#endif - -//------------------------------------------------------------------------ -enum j_registers { Rvars=0, Roptop, Rframe, rVcs, rVds }; - -//------------------------------------------------------------------------ -void idaapi java_header(outctx_t &ctx); - -void idaapi java_segstart(outctx_t &ctx, segment_t *seg); -void idaapi java_segend(outctx_t &ctx, segment_t *seg); - -int idaapi j_realcvt(void *m, eNE e, ushort swt); - -void idaapi java_data(outctx_t &ctx, bool analyze_only); - -int cmp_operands(op_t &op1, op_t &op2); -bool idaapi can_have_type(const op_t &op); -void copy_const_to_opnd(op_t &x, const const_desc_t &co); - - -//---------------------------------------------------------------------- -#define UAS_JASMIN 0x0001 // is jasmin assembler? - -//------------------------------------------------------------------------ -#define MLD_EXTREF 0x01 -#define MLD_VARREF 0x02 // if present EXTREF must be present -#define MLD_METHREF 0x04 // if present VARREF must be present - -#define MLD_EXTATR 0x08 // store additional attributes to file(s) -#define MLD_LOCVAR 0x10 // Rename local variables -#define MLD_STRIP 0x20 // Semantic error names show -#define MLD_FORCE 0x40 // Ignore 'additional error' on load - -#define MLD__DEFAULT ((MLD_EXTREF|MLD_VARREF) /* | MLD_LOCVAR */) - - -//------------------------------------------------------------------------ -#define IDF_MULTDEB 0x0001 // multiline debug -#define IDF_HIDESM 0x0002 // hide stackmap -#define IDF_AUTOSTR 0x0004 // fmt_string as fmt_debug (next string at \n) -#define IDF_CONVERT 0x0008 // convert (to jasmin) when write asm file -#define IDF_ENCODING 0x0010 // enable unicode-encoding (also see map) -#define IDF_NOPATH 0x0020 // .attribute's filename without path - -// not stored (in base) flags -#define IDM_BADIDXSTR 0x00010000 // show invalid indexes as string's - -// ... and used loader only -#define IDM_REQUNK 0x20000000 // make request of ;unknown attribute' -#define IDM_WARNUNK 0x40000000 // 'unknown attribute' produced warnings -// ... in module, but temporary -#define IDM_OUTASM 0x80000000 // currently write asm file - -#define IDM__REQMASK ((~(IDM_REQUNK | IDM_WARNUNK | IDM_OUTASM)) >> 16) - -// curent modes -#define IDFM__DEFAULT ((IDF_MULTDEB|IDF_CONVERT|IDF_ENCODING) | IDM_WARNUNK) - -#pragma pack() - -//------------------------------------------------------------------ -enum CIC_param -{ - C_4byte = 0, - C_8byte, - C_Field, - C_Method, - C_Interface, - C_Class, - C_Type, - C_TypeName, - C_CallSite, -}; - -enum attr_parent_kind_t -{ - attr_parent_kind_code = 0, - attr_parent_kind_field, - attr_parent_kind_method, - attr_parent_kind_class_file, - attr_parent_kind_CHECK, -}; - -class out_java_t; -typedef size_t _PRMPT_(java_t &pm, out_java_t *oj); -#define MAX_ATTR_NMSZ 128 - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct java_t); - -struct java_t : public procmod_t -{ - idb_listener_t idb_listener = idb_listener_t(*this); - int start_asm_list = 0; - uint32 idpflags = IDFM__DEFAULT; -#ifdef TEST_FMTSTR - inline bool jasmin(void) const { return false; } - inline bool is_multiline_debug(void) const { return true; } // true by default, it seems - inline bool is_fmt_string_as_fmt_debug(void) const { return false; } // false by default, it seems -#else - inline bool jasmin(void) const { return (ash.uflag & UAS_JASMIN) != 0; } - inline bool is_multiline_debug(void) const { return (idpflags & IDF_MULTDEB) != 0; } - inline bool is_fmt_string_as_fmt_debug(void) const { return (idpflags & IDF_AUTOSTR) != 0; } -#endif - bool mode_changed = false; - bool displayed_nl = false; - - bool g_bufinited = false; - uint32 g_bufsize = 0; - uint32 maxpos = 0; - uint32 curpos = 0; - uchar user_limiter = 0; - //nexts only for out - bool no_prim = false; - size_t outcnt = 0; - size_t ref_pos = 0; - uint32 Feature = 0; - // Normally static buffers of MAX_NODENAME_SIZE are forbidden but since - // 'tmp_name' is defined only in the java module, it is acceptable. To avoid - // warnings we define JAVA_BUFSIZE: -#define JAVA_BUFSIZE MAX_NODENAME_SIZE - char tmp_name[JAVA_BUFSIZE]; - - // map.cpp vars - char rfmt[23] = " %5u=> "; - char ind_fmt[8] = "%s=%-5u"; - char lft_fmt[16] = "%08lX %5u%c %s "; - - // npool.cpp vars - int32 savesize = -1; - uchar sde = 0; - - // npooluti.cpp vars - ClassInfo curClass; - SegInfo curSeg; - FieldInfo curField; - FILE *myFile = nullptr; - netnode ClassNode; - netnode XtrnNode; - netnode ConstantNode; - char debugmode = 0; - uchar SMF_mode = 0; - // only for npool - uchar loadMode = 0; - uint32 errload = 0; - ushort *tsPtr = nullptr; - uchar *smBuf = nullptr; - uchar *annBuf = nullptr; - uint32 FileSize = 0; - sm_node_t sm_node = smn_aa_not_finished; - uchar uni_chk = (uchar)-1; // unicode 'renaming' support - uchar name_chk = 0; - char tmpbuf[JAVA_BUFSIZE]; // see comment for TMP_NAME - netnode SMnode; - uint32 SMsize = 0; - uint endcls = 0; - uchar clunic = 0; // for unicode renaming - ea_t start_ea = 0; - ushort cursel = 1; - // jasmin reserved word support - std::set<qstring> ResW; - - java_t() - { - memset(&curClass, 0, sizeof(curClass)); - memset(&curSeg, 0, sizeof(curSeg)); - memset(&curField, 0, sizeof(curField)); - memset(tmp_name, 0, sizeof(tmp_name)); - memset(tmpbuf, 0, sizeof(tmpbuf)); - } - - inline void StoreOpis(uint index, const const_desc_t &opis) - { - ConstantNode.supset(index, &opis, sizeof(opis)); - } - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - void sm_validate(const SegInfo *si); - - uchar loadDialog(bool manual); - int32 gen_map_file(FILE *fp); - char *convert_clsname(char *buf) const; - void database_loaded(const char *file); - void make_new_name(ushort name, ushort subnam, uchar mode, uint ip); - int upgrade_db_format(int ver, netnode constnode); - void coagulate_unused_data(const SegInfo *ps); - - void java_footer(outctx_t &ctx); - - void load_attributes(attr_parent_kind_t apk); - void loader(FILE *fp, bool manual); - ea_t get_ref_addr(ea_t ea, const char *name, size_t pos); - void TouchArg(const insn_t &insn, const op_t &x, bool isload); - uval_t SearchFM(ushort name, ushort dscr, char *naprN); - void mark_and_comment(ea_t ea, const char *cmt) const; - int emu(const insn_t &insn); - - int format_utf16_string( - const ushort *_tp, - uint32 ostsz, - uint32 off_ReturnType, - uint32 off_ThrowsSignature_and_TypeSignature, - ssize_t size, - fmt_t mode, - out_java_t *oj, - _PRMPT_ putproc); - void xtrnSet( - uint cin, - const_desc_t *co, - uint xip, - char *str, - size_t strsize, - bool full, - uchar rmod=3); - void rename_uninames(int32 mode); - void setPoolReference(void); - void SetName(ushort name, ea_t ea, ushort access, uval_t number, uchar rmod=3); - int refput(ushort index); - bool fmtName(ushort index, char *buf, size_t bufsize, fmt_t fmt); - uchar set_parent_object(void); - uchar attribute_type_from_str(ushort index, attr_parent_kind_t apk, char str[MAX_ATTR_NMSZ]); - void CheckPoolReference(bool insns_created); - void set_lv_name(ushort name, ea_t ea, uchar rmod); - int is_locvar_name(const insn_t &insn, const char *name); - void ValidateStoreLocVar(ushort slot, LocVar & lv); - void dump_floating_constants( - const char *problem, - const char *what, - const intvec_t &ks); - ssize_t check_special_label(const char *buf, size_t len) const; - bool LoadOpis(load_mode_t load_mode, ushort index, uchar _op, const_desc_t *p); - void load_msg(const char *format, ...); - bool isSingleClass(ushort val); - const char *mk_diag(attr_parent_kind_t apk, char str[128]) const; - uint load_constants_pool(void); - inline void BadRefFile(const char *to, ushort id); - void BadRef(ea_t ea, const char *to, ushort id, attr_parent_kind_t apk); - void mark_access(ea_t ea, ushort acc) const; - uchar *sm_realloc(uint size); - uchar *annotation_realloc(uint size); - ushort *append_tmp_buffer(uint size); - bool getblob(uval_t ind, void *p, uval_t sz); - bool getstr(qstring *out, ushort index); - ushort read2(void); - uint32 read4(void); - uchar read1(void); - void readData(void *data, uint32 size); - void skipData(uint32 size); - const uchar *get_annotation(uval_t node, uint *plen); - bool sm_getinfo(const insn_t &insn, SMinfo *pinf); - uchar *annot_elm(uchar *ptr, uint32 *psize, uchar is_array=0); - uchar *annotation(uchar *p, uint32 *psize); - segment_t *getMySeg(ea_t ea, segment_t *seg = nullptr); - bool sm_chkargs(uchar **pptr, uint32 *pDopSize, ushort cnt); - int sm_load(ushort declcnt, uint32 *pDopSize); - NORETURN void loader_failure_bad_attr_decl_size(attr_parent_kind_t apk) const; - int CmpString(ushort index1, ushort index2); - int cmpDscrString(ushort index1, uchar met, ushort index2, uchar self); - ushort xtrnDscrSearch(ushort name, uchar met); - void mark_strange_name(ea_t ea) const; - void xtrnRef(ea_t ea, const const_desc_t &opis) const; - void xtrnRef_dscr(ea_t ea, const_desc_t *opis, uchar met=0); - void deltry(uint bg, uint ic, uint ui, const const_desc_t &pco); - segment_t *_add_seg(int caller); - void resizeLocVars(void) const; - const char *CopyAttrToFile(const char *astr, uint32 size, ushort id); - inline int strstrpos(const char *s1, const char *s2) - { - s2 = strstr(s1, s2); - return s2 == NULL ? -1 : s2 - s1; - } - bool is_valid_string_index(ushort index) const; - uchar LoadUtf8(ushort index, const_desc_t *co); - void parse_const_desc(ushort index, const_desc_t *co); - uchar CheckSignature(ushort index, attr_parent_kind_t apk); - - void ResW_init(void); - void ResW_newbase(void); - uchar ResW_oldbase(void); - void ResW_validate(uint32 *Flags, const ushort *pend); - uint32 upgrade_ResW(uint32 opstr); - void ResW_free(void); - - size_t make_locvar_cmt(qstring *buf, const insn_t &insn); - int32 print_loader_messages(char str[MAXSTR], const char *cmt, outctx_t *ctx); - - int LoadIndex(insn_t &insn); - int ConstLoad(insn_t &insn, CIC_param ctype); - int ana(insn_t *_insn); -}; -extern int data_id; -#endif - diff --git a/idasdk75/module/java/makefile b/idasdk75/module/java/makefile deleted file mode 100644 index 7c76a90..0000000 --- a/idasdk75/module/java/makefile +++ /dev/null @@ -1,119 +0,0 @@ -PROC=java -O1=oututil -O2=map -O3=npool -O4=npooluti -O5=resword -O6=upgrade -O7=fmtstr - -include ../module.mak - -test_fmtstr: $(R)test_fmtstr$(B) - -TEST_FMTSTR_OBJS:=$(F)test_fmtstr_main$(O) -$(R)test_fmtstr$(B): $(call dumb_target, unicode pro, $(TEST_FMTSTR_OBJS)) - -$(F)test_fmtstr_main$(O): CFLAGS += -DTEST_FMTSTR=1 - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp \ - classfil.hpp ins.hpp java.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - emu.cpp ins.hpp java.hpp -$(F)fmtstr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - fmtstr.cpp ins.hpp java.hpp oututil.hpp upgrade.hpp -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)map$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - ins.hpp java.hpp map.cpp oututil.hpp -$(F)npool$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - classfil.hpp ins.hpp java.hpp npool.cpp npooluti.hpp \ - oututil.hpp upgrade.hpp -$(F)npooluti$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - classfil.hpp ins.hpp java.hpp npooluti.cpp npooluti.hpp \ - oututil.hpp upgrade.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - ins.hpp java.hpp npooluti.hpp out.cpp oututil.hpp \ - upgrade.hpp -$(F)oututil$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - ins.hpp java.hpp oututil.cpp oututil.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - ins.hpp java.hpp notify_codes.hpp npooluti.hpp reg.cpp \ - upgrade.hpp -$(F)resword$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - ins.hpp jas_rw.cc java.hpp npooluti.hpp resword.cpp \ - upgrade.hpp -$(F)test_fmtstr_main$(O): $(I)kernwin.hpp $(I)llong.hpp $(I)pro.h \ - fmtstr.cpp test_fmtstr_main.cpp -$(F)upgrade$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ - ins.hpp java.hpp oututil.hpp upgrade.cpp upgrade.hpp diff --git a/idasdk75/module/java/notify_codes.hpp b/idasdk75/module/java/notify_codes.hpp deleted file mode 100644 index ced951b..0000000 --- a/idasdk75/module/java/notify_codes.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __JAVA_NOTIFY_CODES_HPP -#define __JAVA_NOTIFY_CODES_HPP - -#include <idp.hpp> - -//---------------------------------------------------------------------- -// The following events are supported by the JAVA module in the ph.notify() function -namespace java_module_t -{ - enum event_codes_t - { - ev_load_file = processor_t::ev_loader, - // load input file (see also function loader()) - // in: linput_t *li - // bool manual - // Returns: 0-ok, otherwise-failed - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline bool load_file(linput_t *li, bool manual) - { - return processor_t::notify(idp_ev(ev_load_file), li, manual) == 0; - } -} - -#endif // __JAVA_NOTIFY_CODES_HPP diff --git a/idasdk75/module/java/npool.cpp b/idasdk75/module/java/npool.cpp deleted file mode 100644 index 20f6768..0000000 --- a/idasdk75/module/java/npool.cpp +++ /dev/null @@ -1,2496 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ -#include "java.hpp" -#include <loader.hpp> -#include <diskio.hpp> -#include <segregs.hpp> -#include "npooluti.hpp" -#include "oututil.hpp" - -#define _CUR_IDP_VER IDP_JDK16 - -static const char constant_pool[] = "$ Constant Pool ~"; - -//------------------------------------------------------------------------- -nodeidx_t bootstrap_methods_get_node(bool assert, bool can_create) -{ - // if ( curClass.bmNode != 0 ) - // return curClass.bmNode; - netnode n("$ BootstrapMethods ~"); - if ( can_create && !netnode_exist(n) ) - n.create("$ BootstrapMethods ~"); - if ( assert ) - QASSERT(10333, netnode_exist(n)); - return n; -} - -//------------------------------------------------------------------------- -nodeidx_t bootstrap_methods_get_count() -{ - return netnode(bootstrap_methods_get_node()).altval(0); -} - -//------------------------------------------------------------------------- -void bootstrap_methods_set_count(nodeidx_t cnt) -{ - netnode(bootstrap_methods_get_node()).altset(0, cnt); -} - -//------------------------------------------------------------------------- -bool bootstrap_methods_get_method( - bootstrap_method_def_t *out, - nodeidx_t idx) -{ - netnode n = bootstrap_methods_get_node(); - bytevec_t blob; - if ( n.getblob(&blob, idx, stag) < 2 ) - return false; - const uchar *p = blob.begin(); - out->method_ref = *(ushort *) p; - p += sizeof(ushort); - const size_t nargs = size_t(blob.end() - p) / sizeof(ushort); - out->args.resize(nargs); - if ( nargs > 0 ) - memcpy(out->args.begin(), p, nargs * sizeof(ushort)); - return true; -} - -//------------------------------------------------------------------------- -static bool bootstrap_methods_set_method( - const bootstrap_method_def_t &bmd, - nodeidx_t idx) -{ - netnode n = bootstrap_methods_get_node(); - bytevec_t blob; - blob.append(&bmd.method_ref, sizeof(bmd.method_ref)); - if ( !bmd.args.empty() ) - blob.append(bmd.args.begin(), bmd.args.size() * sizeof(ushort)); - return n.setblob(blob.begin(), blob.size(), idx, stag); -} - -//----------------------------------------------------------------------- -void java_t::database_loaded(const char *file) -{ - int i, v; - ssize_t size; - - if ( file == NULL ) // load old file - { - if ( ConstantNode.create(constant_pool) ) - goto BADIDB; - - i = sizeof(curClass); - v = (int)ConstantNode.altval(CNA_VERSION); - switch ( v ) - { - default: - error("Very old database format. Cannot convert it"); - - case IDP_JDK15: - error("Intermediate (developer) database format. Cannot convert it."); - - case IDP_JDK12: - i -= sizeof(curClass) - offsetof(ClassInfo, MajVers); - //PASS THRU - case _CUR_IDP_VER: // IDP_JDK16 - break; - } - - if ( i != (int)ConstantNode.supval(CNS_CLASS, NULL, (size_t)-1) ) - goto BADIDB; - size = ConstantNode.supval(CNS_CLASS, &curClass, sizeof(curClass)); - if ( size < (int32)offsetof(ClassInfo, MajVers) || !curClass.ClassNode ) - goto BADIDB; - if ( curClass.xtrnNode ) - { - if ( !curClass.xtrnCnt ) - goto BADIDB; - XtrnNode = curClass.xtrnNode; - } - else if ( curClass.xtrnCnt ) - { - goto BADIDB; - } - ClassNode = curClass.ClassNode; - - if ( v != IDP_JDK12 ) // current JDK format - { - if ( curClass.MajVers < JDK_MIN_MAJOR ) - goto BADIDB; - if ( curClass.MajVers > JDK_MAX_MAJOR ) - goto BADIDB; - if ( curClass.MajVers == JDK_MIN_MAJOR ) // JDK1.0/1.1 - { - if ( curClass.JDKsubver != (curClass.MinVers >= JDK_1_1_MINOR) ) - goto BADIDB; - } - else - { - if ( curClass.MinVers ) - goto BADIDB; - if ( curClass.MajVers - (JDK_MIN_MAJOR-1) != curClass.JDKsubver ) - goto BADIDB; - } - } - - make_NameChars(/*on_load=*/ false); // initialize and set enableExr_NameChar for upgrade - if ( v != _CUR_IDP_VER ) - { - ResW_init(); // prepare RW-find - v = upgrade_db_format(v, ConstantNode); - if ( v == 0 ) - { -BADIDB: - DESTROYED("database_loaded"); - } - QASSERT(10134, v == _CUR_IDP_VER); - ConstantNode.supset(CNS_CLASS, &curClass, sizeof(curClass)); - ConstantNode.altset(CNA_VERSION, _CUR_IDP_VER); - } - else - { - v = curClass.maxStrSz; - if ( v != 0 ) - tsPtr = (ushort*)myAlloc(sizeof(ushort)*(v+1)); - v = curClass.maxSMsize; - if ( v != 0 ) - smBuf = (uchar*)myAlloc(v+1); - v = curClass.maxAnnSz; - if ( v != 0 ) - annBuf = (uchar*)myAlloc(v+1); - idpflags = (ushort)ConstantNode.altval(CNA_IDPFLAGS); - user_limiter = (uchar)ConstantNode.altval(CNA_LIMITER); - - if ( !ResW_oldbase() ) - goto BADIDB; - } - // disableExt_NameChar(); // set standart extension - if ( curClass.extflg & XFL_C_DONE ) - sm_node = smn_ok; - if ( curClass.MajVers >= JDK_SMF_MAJOR_MIN ) - SMF_mode = 1; - } - else - { // new base - if ( !ConstantNode ) - INTERNAL("ConstantNode"); - - char str[MAXSPECSIZE]; - char *ps = str; - i = qstrlen((char *) file); - if ( i >= sizeof(str) ) - { - ps = (char *) file + i - (sizeof(str) - 3); - for ( i = sizeof(str) - 1 - 3; i; i-- ) - if ( *--ps == '/' ) - break; - if ( i == 0 ) - error("notify: illegal file name parameter"); - file = ps; - memcpy(str, "...", 3); - ps = &str[3]; - } - memcpy(ps, file, i); - if ( ps != str ) - i += 3; - ConstantNode.supset(CNS_SOURCE, str, i); - user_limiter = inf_get_limiter(); - ConstantNode.altset(CNA_LIMITER, user_limiter); - } - inf_set_limiter(0); -} - - -//------------------------------------------------------------------------- -void java_t::dump_floating_constants( - const char *problem, - const char *what, - const intvec_t &ks) -{ - const size_t kss = ks.size(); - if ( kss > 0 ) - { - static const char *const emc = "Number of %s CONSTANT_%s: %" FMT_Z "\n"; - load_msg(emc, problem, what, kss); - for ( size_t i = 0; i < kss; ++i ) - { - qstrvec_t lines; - - const_desc_t cd; - ushort cid = ks[i]; - if ( ConstantNode.supval(cid, &cd, sizeof(cd)) == sizeof(cd) ) - { - print_constant(&lines, cd, cid); - if ( lines.empty() ) - lines.push_back("<failed printing constant>"); - } - else - { - cd.type = 0; - lines.push_back("<failed retrieving constant>"); - } - for ( size_t lidx = 0, lcnt = lines.size(); lidx < lcnt; ++lidx ) - { - char sfxbuf[MAXSTR]; - if ( lcnt > 1 ) - qsnprintf(sfxbuf, sizeof(sfxbuf), ".%" FMT_Z, lidx); - else - sfxbuf[0] = '\0'; - load_msg(" #%" FMT_Z "%s, index=%d, type=%s: %s", - i, sfxbuf, cid, constant_type_to_str(cd.type), - lines[lidx].c_str()); - } - } - } -} - -//----------------------------------------------------------------------- -bool java_t::LoadOpis(load_mode_t load_mode, ushort index, uchar _op, const_desc_t *p) -{ - const uchar op = _op; -#define LoadAnyString(lmod, index) LoadOpis(lmod, index, CONSTANT_Utf8, NULL) - const_desc_t tmp; - if ( p == NULL ) - p = &tmp; - - if ( !index - || index > curClass.maxCPindex - || ConstantNode.supval(index, p, sizeof(*p)) != sizeof(*p) ) - { - return false; - } - - if ( load_mode == lm_lenient || load_mode == lm_no_set_ref ) - return true; - - if ( !p->is_referenced() ) - { - p->mark_referenced(); - StoreOpis(index, *p); - } - CASSERT(MAX_CONSTANT_TYPE < 0x20); - if ( op < 0x20 ) - return op == 0 || op == p->type; - -#define LoadNamedClass(lmod, index, p) LoadOpis(lmod, index, uchar(-1), p) - if ( op == uchar(-1) ) - return p->type == CONSTANT_Class && (p->flag & HAS_CLSNAME); - - if ( p->type != CONSTANT_Utf8 ) - return false; - -#define OP_TYPE_MASK 0x1F -#define OP_CHECK_SHIFT 5 - - const uchar _type = op & OP_TYPE_MASK; - const uchar _check = op >> OP_CHECK_SHIFT; - switch ( _type ) - { - default: - INTERNAL("LoadOpis"); - case 0: - case CONSTANT_Utf8: - break; - } - { - static const uchar chk[8] = - { - 0x00, // align - -#define CheckAnyDscr(lmod, index, p) LoadOpis(lmod, index, (1 << OP_CHECK_SHIFT), p) - (HAS_TYPEDSCR | HAS_CALLDSCR), - -#define CheckFieldDscr(lmod, index, p) LoadOpis(lmod, index, (2 << OP_CHECK_SHIFT), p) -#define LoadFieldDscr(lmod, index, p) LoadOpis(lmod, index, (2 << OP_CHECK_SHIFT) | CONSTANT_Utf8, p) - HAS_TYPEDSCR, - -#define CheckFieldName(lmod, index, p) LoadOpis(lmod, index, (3 << OP_CHECK_SHIFT), p) -#define LoadFieldName(lmod, index) LoadOpis(lmod, index, (3 << OP_CHECK_SHIFT) | CONSTANT_Utf8, NULL) - HAS_FLDNAME, - -//#define Check...(lmod, index, p) LoadOpis(lmod, index, (4 << OP_CHECK_SHIFT), p) - 0x00, - -#define CheckClass(lmod, index, p) LoadOpis(lmod, index, (5 << OP_CHECK_SHIFT), p) - (HAS_TYPEDSCR | HAS_CLSNAME), - -#define CheckCallDscr(lmod, index, p) LoadOpis(lmod, index, (6 << OP_CHECK_SHIFT), p) -#define LoadCallDscr(lmod, index) LoadOpis(lmod, index, (6 << OP_CHECK_SHIFT) | CONSTANT_Utf8, NULL) - HAS_CALLDSCR, - -#define CheckClassName(lmod, index, p) LoadOpis(lmod, index, (7 << OP_CHECK_SHIFT), p) - HAS_CLSNAME - }; - - if ( p->flag & chk[_check] ) - return true; - } - - if ( _type != 0 ) - return false; - - if ( load_mode == lm_need_cr ) - msg("\n"); - load_msg("Illegal reference type to Utf8#%u\n", index); - return lm_need_cr >= 2; // true when load_constants_pool, false after -} - -//----------------------------------------------------------------------- -// for annotation -bool java_t::isSingleClass(ushort val) -{ - const_desc_t co; - - return LoadFieldDscr(lm_normal, val, &co) - && (co._Sflags & (_OP_VALPOS | _OP_ONECLS)) == _OP_ONECLS; -} - -//----------------------------------------------------------------------- -uchar java_t::attribute_type_from_str(ushort index, attr_parent_kind_t apk, char str[MAX_ATTR_NMSZ]) -{ - static const char *const name[] = - { -#define attr_LineNumberTable 0 // 0x000001: code - "LineNumberTable", -#define attr_LocalVariableTable 1 // 0x000002: code - "LocalVariableTable", -#define attr_LocalVariableTypeTable 2 // 0x000004: code - "LocalVariableTypeTable", -#define attr_StackMap 3 // 0x000008: code (J2ME CLDC) - "StackMap", -#define attr_StackMapTable 4 // 0x000010: code (>=JDK1.6) - "StackMapTable", -#define attr_CODE_TOP 5 - -#define attr_ConstantValue 5 // 0x000020: fld - "ConstantValue", -#define attr_FLD_TOP 6 - -#define attr_Code 6 // 0x000040: met - "Code", -#define attr_Exceptions 7 // 0x000080: met - "Exceptions", -#define attr_RuntimeVisibleParameterAnnotations 8 // 0x000100: met - "RuntimeVisibleParameterAnnotations", -#define attr_RuntimeInvisibleParameterAnnotations 9 // 0x000200: met - "RuntimeInvisibleParameterAnnotations", -#define attr_AnnotationDefault 10 // 0x000400: met - "AnnotationDefault", -#define attr_MET_TOP 11 - -#define attr_SourceFile 11 // 0x000800: file - "SourceFile", -#define attr_InnerClasses 12 // 0x001000: file - "InnerClasses", -#define attr_EnclosingMethod 13 // 0x002000: file - "EnclosingMethod", -#define attr_SourceDebugExtension 14 // 0x004000: file - "SourceDebugExtension", -#define attr_BootstrapMethods 15 // 0x008000: file - "BootstrapMethods", -#define attr_FILE_TOP 16 - -#define attr_Signature 16 // 0x010000: all !code - "Signature", -#define attr_Synthetic 17 // 0x020000: all !code - "Synthetic", -#define attr_Deprecated 18 // 0x040000: all !code - "Deprecated", -#define attr_RuntimeVisibleAnnotations 19 // 0x080000: all !code - "RuntimeVisibleAnnotations", -#define attr_RuntimeInvisibleAnnotations 20 // 0x100000: all !code - "RuntimeInvisibleAnnotations", -// next field for check pool ONLY (must be in last position) -#define attr_LocalVariables 21 //0x200000: obsolete - "LocalVariables" -#define attr_CHECK_MASK 0x3FFFFF - }; -#define attr_UNKNOWN 32 -#define attr_TRUNCATED 33 -#define attr_NONAME 34 -//#if sizeof("RuntimeInvisibleParameterAnnotations") > MAX_ATTR_NMSZ -//#error -//#endif - - str[0] = '\0'; - if ( !LoadFieldName(lm_normal, index) ) - return attr_NONAME; - if ( !fmtName(index, str, MAX_ATTR_NMSZ, fmt_UnqualifiedName) ) - return attr_TRUNCATED; - - uchar i = 0, top = (uchar)(qnumber(name) - 1); - switch ( apk ) - { - case attr_parent_kind_code: - top = attr_CODE_TOP; - break; - case attr_parent_kind_field: - i = attr_CODE_TOP; - top = attr_FLD_TOP; - break; - case attr_parent_kind_method: - i = attr_FLD_TOP; - top = attr_MET_TOP; - break; - case attr_parent_kind_class_file: - i = attr_MET_TOP; - top = attr_FILE_TOP; - break; - default: -// case ARQ_CHECK: - ++top; - break; - } - -repeat: - do - { - if ( !strcmp(name[i], str) ) - return i; - } while ( ++i < top ); - if ( apk != attr_parent_kind_code && i < (uchar)(qnumber(name)-1) ) - { - i = attr_FILE_TOP; - top = (uchar)(qnumber(name) - 1); - goto repeat; - } - return attr_UNKNOWN; -} - -//------------------------------------------------------------------------- -static NORETURN void badref_loader_failure(ushort i, ushort k) -{ - loader_failure("Bad reference (from %u to %u) in constant pool", i, k); -} - -//----------------------------------------------------------------------- -uint java_t::load_constants_pool(void) -{ - ushort k; - uint ui = 0; - const_desc_t cd; - - // prepare jasmin reserved word checking - ResW_init(); - - msg("\nLoading constant pool..."); - FOR_EACH_CONSTANT_POOL_INDEX(i) - { - memset(&cd, 0, sizeof(cd)); - cd.type = read1(); - switch ( cd.type ) - { - case CONSTANT_Long: - case CONSTANT_Double: - cd.value2 = read4(); - // fallthrough - case CONSTANT_Integer: - case CONSTANT_Float: - cd.value = read4(); - break; - - case CONSTANT_NameAndType: - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - case CONSTANT_InterfaceMethodref: - k = read2(); - if ( k == 0 || k > curClass.maxCPindex ) - { -badindex: - loader_failure("Bad record in constant pool.\n" - "Record %u have reference to %u\n" - "(maxnum %u, file offset after the read is 0x%" FMT_64 "X)", - i, k, curClass.maxCPindex, qftell(myFile)); - } - cd._class = k; // _subnam for name & type - // fallthrough. Yes, we will let 'name_and_type_index' be read by the CONSTANT_String block below... - case CONSTANT_Class: - cd.ref_ip = 0; - // fallthrough - case CONSTANT_String: - k = read2(); - if ( k == 0 || k > curClass.maxCPindex ) - goto badindex; - cd._name = k; // _dscr for name & type - break; - - case CONSTANT_Unicode: - loader_failure("File contains CONSTANT_Unicode, which was removed from " - "the standard in 1996, and is not supported by IDA"); - - case CONSTANT_Utf8: - cd._name = (ushort)i; // for xtrnRef_dscr - if ( LoadUtf8((ushort)i, &cd) ) - parse_const_desc((ushort)i, &cd); - break; - - case CONSTANT_MethodHandle: - cd._mhr_kind = read1(); - cd._mhr_index = read2(); - break; - - case CONSTANT_MethodType: - k = read2(); // descriptor_index - if ( k == 0 || k > curClass.maxCPindex ) - goto badindex; - cd._mtd_index = k; - break; - - case CONSTANT_InvokeDynamic: - { - cd._bmidx = read2(); // bootstrap_method_attr_index - k = read2(); // name_and_type_index - if ( k == 0 || k > curClass.maxCPindex ) - goto badindex; - cd._name = k; - } - break; - - default: - loader_failure("Bad constant type 0x%x (%u)", cd.type, i); - } // end switch - StoreOpis(i, cd); - if ( cd.type == CONSTANT_Long || cd.type == CONSTANT_Double ) - { - if ( curClass.maxCPindex == (ushort)i ) - loader_failure("Premature end of constant pool"); - ++i; - } - } // end for - ResW_free(); // free mem - this set not needed later - - msg("checking..."); - FOR_EACH_CONSTANT_POOL_INDEX(i) - { - const_desc_t cr; - ConstantNode.supval(i, &cd, sizeof(cd)); - switch ( cd.type ) - { - case CONSTANT_String: - if ( !LoadAnyString(lm_need_cr, cd._name) ) - badref_loader_failure(i, cd._name); - continue; - - case CONSTANT_Long: - case CONSTANT_Double: - ++i; - default: - continue; - - case CONSTANT_NameAndType: - if ( !CheckFieldName(lm_need_cr, cd._class, &cr) ) - badref_loader_failure(i, cd._class); - cd.flag |= ((cr.flag & HAS_FLDNAME) << SUB_SHIFT); - if ( !CheckAnyDscr(lm_need_cr, cd._name, &cr) ) - badref_loader_failure(i, cd._name); - cd.flag |= ((cr.flag<<SUB_SHIFT) & (SUB_TYPEDSCR | SUB_CALLDSCR)); - break; - - case CONSTANT_Class: - if ( !CheckClass(lm_need_cr, cd._name, &cr) ) - badref_loader_failure(i, cd._name); - cd.flag |= (cr.flag & (HAS_FLDNAME | HAS_TYPEDSCR | HAS_CLSNAME)); - cd._dscr = cd._subnam = 0; - break; - } // end switch - StoreOpis(i, cd); - if ( (loadMode & MLD_EXTREF) - && cd.type == CONSTANT_Class - && (cd.flag & HAS_CLSNAME) ) - { - ushort j; - - for ( j = 1; j <= curClass.xtrnCnt; j++ ) - { - uint32 rfc = (uint32)XtrnNode.altval(j); - if ( !CmpString(cd._name, (ushort)rfc) ) - { - cd._subnam = (ushort)(rfc >> 16); - goto found; - } - } - XtrnNode.altset(j, (i << 16) | cd._name); - ++curClass.xtrnCnt; - cd._subnam = (ushort)i; -found: - StoreOpis(i, cd); - } - } // end for - if ( loadMode & MLD_EXTREF ) - XtrnNode.altdel(); // delete all - - msg("referencing..."); - FOR_EACH_CONSTANT_POOL_INDEX(i) - { - const_desc_t cr; - uint32 sav; - - ConstantNode.supval(i, &cd, sizeof(cd)); - switch ( cd.type ) - { - case CONSTANT_Long: - case CONSTANT_Double: - ++i; - default: - continue; - - case CONSTANT_Class: - continue; - - case CONSTANT_InterfaceMethodref: - case CONSTANT_Fieldref: - case CONSTANT_Methodref: - if ( !LoadOpis(lm_need_cr, cd._class, CONSTANT_Class, &cr) ) - badref_loader_failure(i, cd._class); -//\\VALID NULL ??? go twos if any... (reorder cur ind to null) - cd.flag |= (cr.flag & HAS_CLSNAME); - k = cd._name; - sav = errload; - cd.ref_ip = cr._subnam; - CheckClassName(lm_need_cr, cd._name = cr._name, NULL); - if ( !LoadOpis(lm_need_cr, k, CONSTANT_NameAndType, &cr) ) - { - badref_loader_failure(i, k); - } - cd._dscr = cr._name; - cd._subnam = cr._class; - cd.flag |=(cr.flag & (SUB_FLDNAME | SUB_TYPEDSCR | SUB_CALLDSCR)); - if ( cd.type != CONSTANT_Fieldref ) - CheckCallDscr(lm_need_cr, cd._dscr, NULL); - else - CheckFieldDscr(lm_need_cr, cd._dscr, NULL); - if ( !LoadFieldName(lm_need_cr, cd._subnam) ) - --sav; - if ( (loadMode & MLD_EXTREF) && errload == sav ) - { - XtrnNode.altset(++ui, i, '0'); - ++curClass.xtrnCnt; - } - else - { - cd.ref_ip = 0; - } - break; - - case CONSTANT_MethodHandle: - if ( !LoadOpis(lm_need_cr, cd._mhr_index, 0, &cr) ) - badref_loader_failure(i, cd._mhr_index); - break; - - case CONSTANT_MethodType: - if ( !LoadOpis(lm_need_cr, cd._mtd_index, CONSTANT_Utf8, &cr) ) - badref_loader_failure(i, cd._mtd_index); - break; - - case CONSTANT_InvokeDynamic: - // We can resolve the name_and_type_index, right away but the - // bootstrap_method_attr_index, will have to wait after the - // BootstrapMethods array has been loaded (in load_attributes()) - if ( !LoadOpis(lm_need_cr, cd._name, CONSTANT_NameAndType, &cr) ) - badref_loader_failure(i, cd._mtd_index); - break; - } // end switch - StoreOpis(i, cd); - } // end for - - msg("complete\n"); - - // { // debug - // intvec_t tmp; - // FOR_EACH_CONSTANT_POOL_INDEX(i) - // tmp.push_back(i); - // dump_floating_constants( - // "NO PROBLEM", - // "NOTHING", - // tmp); - // } - - return ui; -} - -//----------------------------------------------------------------------- -void java_t::setPoolReference(void) -{ - char str[MAXNAMELEN]; - const_desc_t co; - uint ic, ii, ui = 0; - - msg("Sorting external references..."); - for ( uint i = 1; (ushort)i <= curClass.xtrnCnt; i++ ) - { - uint j = (uint)XtrnNode.altval(i, '0'); - if ( j == 0 ) - continue; - show_addr(curClass.xtrnCnt - (ushort)i); - ConstantNode.supval(j, &co, sizeof(co)); - if ( co._class == curClass.This.Dscr ) - { - co.ref_ip = 0; - StoreOpis(j, co); - continue; - } - const_desc_t cr; - ConstantNode.supval(ic = co.ref_ip, &cr, sizeof(cr)); - xtrnSet(ic, &cr, ++ui, str, sizeof(str), true); - xtrnSet(j, &co, ++ui, str, sizeof(str), false); - deltry(ii = i + 1, ic, ui, co); - for ( ; (ushort)ii <= curClass.xtrnCnt; ii++ ) - { - j = (uint)XtrnNode.altval(ii, '0'); - if ( j == 0 ) - continue; - ConstantNode.supval(j, &cr, sizeof(cr)); - if ( cr.ref_ip != (ushort)ic ) - continue; - xtrnSet(j, &cr, ++ui, str, sizeof(str), false); - XtrnNode.altdel(ii, '0'); - deltry(ii + 1, ic, ui, co); - } - } - XtrnNode.altdel_all('0'); - - FOR_EACH_CONSTANT_POOL_INDEX(i) - { - ConstantNode.supval(i, &co, sizeof(co)); - switch ( co.type ) - { - case CONSTANT_Long: - case CONSTANT_Double: - ++i; - default: - break; - case CONSTANT_Class: - if ( co._subnam == (ushort)i - && (ushort)i != curClass.This.Dscr - && !co.ref_ip ) - { - xtrnSet(i, &co, ++ui, str, sizeof(str), true); - } - break; - } - } - - FOR_EACH_CONSTANT_POOL_INDEX(i) - { - ConstantNode.supval(i, &co, sizeof(co)); - switch ( co.type ) - { - case CONSTANT_Long: - case CONSTANT_Double: - ++i; - default: - continue; - case CONSTANT_Class: - break; - } - if ( co._subnam && co._subnam != (ushort)i ) - { - const_desc_t tmp; - ConstantNode.supval(co._subnam, &tmp, sizeof(tmp)); - co.ref_ip = tmp.ref_ip; - StoreOpis(i, co); - } - } - - curClass.xtrnCnt = (ushort)ui; - if ( curClass.xtrnCnt != 0 ) - { - set_segm_end(curClass.xtrnEA, curClass.xtrnEA + curClass.xtrnCnt + 1, SEGMOD_KILL); - create_byte(curClass.xtrnEA, 1); - } - else - { - XtrnNode.kill(); - curClass.xtrnNode = 0; - del_segm(curClass.xtrnEA, SEGMOD_KILL); - curClass.xtrnEA = 0; - } - msg("OK\n"); -} - -//----------------------------------------------------------------------- -void java_t::CheckPoolReference(bool insns_created) -{ - char str[MAX_ATTR_NMSZ]; - const_desc_t co; - intvec_t k1s; - intvec_t k2s; - intvec_t k3s; - uint mask = attr_CHECK_MASK; - - msg("Checking references, %s creating instructions...\n", insns_created ? "after" : "before"); - FOR_EACH_CONSTANT_POOL_INDEX(i) - { - ConstantNode.supval(i, &co, sizeof(co)); - if ( co.type == CONSTANT_Long || co.type == CONSTANT_Double ) - ++i; - if ( co.is_referenced() ) - continue; - switch ( co.type ) - { - case CONSTANT_Utf8: - if ( !insns_created ) - { - uchar j; - - k2s.push_back(i); - CASSERT((1 << (attr_LocalVariables+1)) - 1 == attr_CHECK_MASK); - if ( (co.flag & HAS_FLDNAME) - && mask - && (j = attribute_type_from_str((ushort)i, attr_parent_kind_CHECK, str)) <= attr_LocalVariables - && (mask & (1 << j)) ) - { - mask ^= (1 << j); - } - else if ( co._Ssize ) - { - k3s.push_back(i); // unnotify empty - } - } - break; - - case CONSTANT_NameAndType: - if ( !insns_created ) - k1s.push_back(i); - break; - - case CONSTANT_Class: - if ( insns_created ) - { - k2s.push_back(i); - if ( !(co.flag & HAS_CLSNAME) ) - k3s.push_back(i); - } - break; - - default: - if ( insns_created ) - k1s.push_back(i); - break; - } // switch - } // for - - if ( !k1s.empty() ) - { - dump_floating_constants( - "unused", - insns_created ? "(any except Class/Type/String)" : "NameAndType", - k1s); - } - if ( !k2s.empty() ) - { - if ( !k3s.empty() ) - { - dump_floating_constants( - insns_created ? "unnamed" : "unreferenced", - insns_created ? "Class" : "Utf8", - k3s); - for ( size_t i = 0, n = k3s.size(); i < n; ++i ) - k2s.del(k3s[i]); - } - if ( !k2s.empty() ) - dump_floating_constants("unused", insns_created ? "Class" : "Utf8", k2s); - } -} - -//----------------------------------------------------------------------- -void java_t::ValidateStoreLocVar(ushort slot, LocVar & lv) -{ - netnode temp; - uint32 cnt, id; - bool dble; - LocVar vals[(qmin(MAXSTR, MAXSPECSIZE)/sizeof(LocVar))]; - const char *txt = "Invalid declaration"; - - lv.ScopeTop = (ushort)(id = (uint32)lv.ScopeBeg + lv.ScopeTop); - - if ( slot >= curSeg.DataSize || id > curSeg.CodeSize ) - goto BADDECL; - - dble = false; - if ( curSeg.varNode ) - { - temp = curSeg.varNode; - cnt = (uint32)temp.altval(slot); - if ( cnt != 0 ) - { - if ( (int32)cnt < 0 ) - { - cnt = -(int32)cnt; - dble = true; - } - if ( (cnt % sizeof(LocVar)) - || cnt >= sizeof(vals) - || temp.supval(slot, vals, cnt+1) != cnt ) - { - goto interr; - } - cnt /= sizeof(LocVar); - } - } - else - { - temp.create(); - curSeg.varNode = temp; - cnt = 0; - } - - if ( !lv.utsign ) // base declaration - { - const_desc_t opis; - - CASSERT(offsetof(LocVar, utsign)+sizeof(lv.utsign) == sizeof(LocVar)); - //lint -esym(645, vals) Symbol may not have been initialized - for ( id = 0; id < cnt; id++ ) // skip full duplication - if ( memcmp(&lv, &vals[id], offsetof(LocVar, utsign)) == 0 ) - return; - - if ( !LoadFieldName(lm_normal, lv.var.Name) ) - goto BADDECL; - if ( !LoadFieldDscr(lm_normal, lv.var.Dscr, &opis) ) - goto BADDECL; - - CASSERT(offsetof(const_desc_t, _Sflags) - offsetof(const_desc_t, _Ssize) == 2); - if ( !dble && opis._Sopstr == (1 | (_OP_UTF8_ << 16)) ) - { - uchar tmp[sizeof(ushort)+1]; - if ( ConstantNode.supval((uint32)lv.var.Dscr << 16, tmp, sizeof(tmp), - BLOB_TAG) != sizeof(ushort) ) - goto interr; - switch ( tmp[0] ) - { - case j_double: - case j_long: - dble = true; - if ( slot+1 == curSeg.DataSize ) - goto BADDECL; - default: - break; - } - } - - txt = "Too many variants"; - if ( cnt == qnumber(vals)-1 ) - goto BADDECL; - - if ( !lv.ScopeBeg ) - curSeg.id.extflg |= XFL_M_LABSTART; // special label at entry - if ( lv.ScopeTop == curSeg.CodeSize ) - curSeg.id.extflg |= XFL_M_LABEND; // special label at end - - { - ea_t dea = curSeg.DataBase + slot; - add_dref(dea, curSeg.start_ea + lv.ScopeBeg, dr_I); - add_dref(dea, curSeg.start_ea + lv.ScopeTop, dr_I); - } - xtrnRef_dscr(curSeg.start_ea + lv.ScopeBeg, &opis); - if ( !cnt ) - set_lv_name(lv.var.Name, curSeg.DataBase + slot, - (loadMode & MLD_LOCVAR) ? 3 : 0); // if not rename_on_load ONLY mark - vals[cnt++] = lv; - } - else - { // signature declaration - CASSERT(offsetof(LocVar, var.Dscr)+sizeof(lv.var.Dscr)+sizeof(lv.utsign) == sizeof(LocVar)); - for ( id = 0; id < cnt; id++ ) - if ( memcmp(&lv, &vals[id], offsetof(LocVar, var.Dscr)) == 0 ) - { - if ( !vals[id].utsign ) - { - if ( !CheckSignature(lv.utsign, attr_parent_kind_code) ) - goto BADDECL; - vals[id].utsign = lv.utsign; - goto store; - } - if ( vals[id].utsign == lv.utsign ) - return; - txt = "Different signature"; - goto BADDECL; - } - txt = "Signature without type"; - goto BADDECL; - } -store: - cnt *= sizeof(LocVar); - temp.supset(slot, vals, cnt); - if ( !lv.utsign ) - { - if ( dble ) - cnt = -(int32)cnt; - temp.altset(slot, cnt); - } - return; - -BADDECL: - load_msg("%s LocVar#%u Method#%u (name#%u dsc#%u sgn#%u scope:%u-%u)\n", - txt, slot, curSeg.id.Number, - lv.var.Name, lv.var.Dscr, lv.utsign, lv.ScopeBeg, lv.ScopeTop); - return; - -interr: - INTERNAL("StoreLocVar"); -} - -//----------------------------------------------------------------------- -inline void java_t::BadRefFile(const char *to, ushort id) -{ - BadRef(BADADDR, to, id, attr_parent_kind_class_file); -} - -//----------------------------------------------------------------------- -uchar *java_t::annotation(uchar *p, uint32 *psize) -{ - if ( *psize < 2 ) - { -bad: - return NULL; - } - *psize -= 2; - uint pairs= read2(); - *(ushort *)p = (ushort)pairs; - p += sizeof(ushort); - if ( pairs ) - { - do - { - if ( *psize < 2 ) - goto bad; - *psize -= 2; - ushort id = read2(); - if ( !LoadFieldName(lm_normal, id) ) - goto bad; - *(ushort *)p = id; - p = annot_elm(p+sizeof(ushort), psize); - if ( p == NULL ) - goto bad; - } - while ( --pairs ); - } - return p; -} - -//--------------------------------------------------------------------------- -uchar *java_t::annot_elm(uchar *ptr, uint32 *psize, uchar is_array) -{ - if ( *psize < 1+2 ) - { -bad: - return NULL; - } - *psize -= 1+2; - union - { - uchar *p1; - ushort *p2; - }; - p1 = ptr; - uchar tag = read1(); - ushort val = read2(); - *p1++ = tag; - *p2++ = val; - switch ( tag ) - { - case j_annotation: - if ( isSingleClass(val) - && (p1 = annotation(p1, psize)) != NULL ) - { - goto done; - } - default: - goto bad; - - case j_array: - if ( val && !is_array ) // multidimensional array is not valid (javac ) - { - uchar *ps = p1; - tag = 0; - do - { - p1 = annot_elm(p1, psize, 1); - if ( p1 == NULL ) - goto bad; - if ( !tag ) - { - if ( val == 1 ) - break; - tag = *ps; - ps = p1; - } - else if ( tag != (uchar)-1 ) - { - if ( tag != *ps ) - goto bad; - tag = (uchar)-1; - } - } - while ( --val ); - goto done; - } - goto bad; - - case j_enumconst: - if ( LoadFieldDscr(lm_normal, val, NULL) ) - { - if ( *psize < 2 ) - goto bad; - *psize -= 2; - *p2++ = val = read2(); - if ( LoadFieldName(lm_normal, val) ) - goto done; - } - goto bad; - - case j_class_ret: - if ( isSingleClass(val) ) - goto done; - goto bad; //### in 'classfile.pdf' j_void_ret also remebemered? - - case j_string: - tag = CONSTANT_Utf8; - break; - case j_float: - tag = CONSTANT_Float; - break; - case j_long: - tag = CONSTANT_Long; - break; - case j_double: - tag = CONSTANT_Double; - break; - case j_int: - case j_byte: - case j_char: - case j_short: - case j_bool: - tag = CONSTANT_Integer; - break; - } - if ( !LoadOpis(lm_normal, val, tag, NULL) ) - goto bad; -done: - return p1; -} - -//----------------------------------------------------------------------- -bool java_t::sm_chkargs(uchar **pptr, uint32 *pDopSize, ushort cnt) -{ - union - { - uchar *p1; - ushort *p2; - }; - p1 = *pptr; - uint32 dopsize = *pDopSize; - bool result = false; - - do - { - if ( !dopsize ) - goto declerr_w; - --dopsize; - uchar tag = read1(); - if ( tag > ITEM_Uninitialized ) - goto declerr_w; - *p1++ = tag; - CASSERT(ITEM_Object+1 == ITEM_Uninitialized); - if ( tag >= ITEM_Object ) - { - if ( dopsize < 2 ) - goto declerr_w; - dopsize -= 2; - ushort var = read2(); - if ( tag == ITEM_Object ) - { - const_desc_t opis; - if ( var == curClass.This.Dscr ) - { - var = curClass.This.Name; - p1[-1] = ITEM_CURCLASS; - } - else if ( LoadNamedClass(lm_normal, var, &opis) ) - { - var = opis._name; - } - else - { - p1[-1] = ITEM_BADOBJECT; - } - } - else - { // Uninitialized (offset to new instruction) - if ( !var ) - curSeg.id.extflg |= XFL_M_LABSTART; // PARANOYA - else if ( var >= curSeg.CodeSize ) - goto declerr_w; - } - *p2++ = var; - } - } - while ( --cnt ); - result = true; - *pptr = p1; -declerr_w: - *pDopSize = dopsize; - return result; -} - -//----------------------------------------------------------------------- -int java_t::sm_load(ushort declcnt, uint32 *pDopSize) -{ - union - { - uchar *p1; - ushort *p2; - }; - sm_info_t smr; - uint32 dopsize = *pDopSize; - netnode temp(curSeg.smNode); - int result = 0; - uint prevoff = (uint)-1; - - p1 = sm_realloc(dopsize); - dopsize -= 2; // skip READED counter - *p2++ = declcnt; // counter - smr.noff = (uint32)(p1 - smBuf); - smr.fcnt = 0; - do - { - ea_t refea; - uint nxcnt; - uchar rectype = SMT_FULL_FRAME; - if ( SMF_mode ) // >=JDK6 - { - if ( !dopsize ) - goto declerr_w; - --dopsize; - rectype = read1(); - *p1++ = rectype; - } - { - uint off; - if ( rectype < SMT_SAME_FRM_S1 ) - { - if ( rectype > SMT_SAME_FRM_S1_max ) - goto declerr_w; // reserved - off = rectype; - if ( rectype >= SMT_SAME_FRM_S1_min ) - off -= SMT_SAME_FRM_S1_min; - } - else - { - if ( dopsize < 2 ) - goto declerr_w; - dopsize -= 2; - off = read2(); - *p2++ = (ushort)off; - } - if ( SMF_mode ) - off += (prevoff + 1); // >=JDK6 - if ( (uint32)off >= curSeg.CodeSize ) - goto declerr_w; - prevoff = off; - refea = curSeg.start_ea + off; - } - if ( temp.supval(refea, NULL, 0) != -1 ) // for CLDC only - { - --result; - goto declerr_w; - } - nxcnt = smr.fcnt; - if ( rectype == SMT_FULL_FRAME ) - { - for ( int pass = 0; pass < 2; pass++ ) - { - ushort cnt; - - if ( dopsize < 2 ) - goto declerr_w; - dopsize -= 2; - *p2++ = cnt = read2(); // number of locals / number of stacks - if ( !pass ) - nxcnt = cnt; - if ( cnt && !sm_chkargs(&p1, &dopsize, cnt) ) - goto declerr_w; - } - } - else if ( rectype > SMT_SAME_FRM_S0 ) - { - rectype -= SMT_SAME_FRM_S0; - if ( !sm_chkargs(&p1, &dopsize, rectype) ) - goto declerr_w; - nxcnt += rectype; - } - else if ( rectype >= SMT_SAME_FRM_S1 ) - { - rectype = (uchar)SMT_SAME_FRM_S0 - rectype; - nxcnt -= rectype; - if ( int(nxcnt) < 0 ) - goto declerr_w; - if ( rectype == 4 /*i.e., was: SMT_SAME_FRM_S1 */ ) - { - // same_locals_1_stack_item_frame_extended - // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.4 - if ( !sm_chkargs(&p1, &dopsize, 1) ) - goto declerr_w; - } - } - else if ( rectype >= SMT_SAME_FRM_S1_min ) - { - if ( !sm_chkargs(&p1, &dopsize, 1) ) - goto declerr_w; - } - smr.eoff = (uint32)(p1 - smBuf); - temp.supset(refea, &smr, sizeof(smr)); - smr.noff = smr.eoff; - smr.fcnt = nxcnt; - } - while ( --declcnt ); -// - temp.altset(-1, smr.noff); - temp.setblob(smBuf, smr.noff, 0, BLOB_TAG); - ++result; -declerr_w: - *pDopSize = dopsize; - return result; -} - -//------------------------------------------------------------------------- -NORETURN void java_t::loader_failure_bad_attr_decl_size(attr_parent_kind_t apk) const -{ - char diastr[128]; - loader_failure("Illegal size of declaration%s", mk_diag(apk, diastr)); -} - -//----------------------------------------------------------------------- -void java_t::load_attributes(attr_parent_kind_t apk) -{ - char atrs[MAX_ATTR_NMSZ+2], diastr[128]; - // ushort k; - uint i, j, r; - netnode temp; - uval_t *pann; - uchar eflg, lvtb = 0, lntb = 0, fatal = (loadMode & MLD_FORCE) == 0; - const_desc_t opis; - opis._name = 0; // for vc - - j = read2(); - for ( i = 0; i < j; i++ ) - { - if ( savesize >= 0 && (savesize -= 6) < 0 ) - loader_failure_bad_attr_decl_size(apk); - const ushort attribute_name_index = read2(); - uint attribute_length = read4(); - if ( savesize >= 0 && (savesize -= attribute_length) < 0 ) - loader_failure_bad_attr_decl_size(apk); - - eflg = 0; // flag(additional attributes/locvars/annotation/stackmap) - atrs[0] = ' '; // for additinal attibutes (mark SourceDebugExtension) - switch ( attribute_type_from_str(attribute_name_index, apk, &atrs[1]) ) - { - case attr_SourceDebugExtension: - if ( sde ) - goto duplerr_w; - ++sde; - if ( attribute_length < 0x10000 ) - { - if ( attribute_length == 0 ) - { - deb(IDA_DEBUG_LDR, - "Ignore zero length SourceDebugExtension attribute\n"); - break; - } - qoff64_t pos = qftell(myFile), ssz = FileSize; - if ( LoadUtf8((ushort)-1, (const_desc_t*)(size_t)attribute_length) ) - { - curClass.extflg |= XFL_C_DEBEXT; - break; - } - qfseek(myFile, pos, SEEK_SET); - FileSize = ssz; - } - if ( ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "SourceDebugExtension attribute have a non standard encoding\n" - "or large size and cannot be represented in assembler.\n\n" - "\3Do you want to store it in external file?") > ASKBTN_NO ) - goto attr2file; - goto skipAttr; - - case attr_BootstrapMethods: - { - if ( bootstrap_methods_get_node(/*assert=*/ false) != BADNODE ) - loader_failure("Duplicate 'BootstrapMethods' attribute definition"); - bootstrap_methods_get_node(/*assert=*/ true, /*can_create=*/ true); - if ( attribute_length < 2 ) - goto declerr_w; - const ushort num_bootstrap_methods = read2(); - bootstrap_methods_set_count(num_bootstrap_methods); - attribute_length -= 2; - const qoff64_t end = qftell(myFile) + attribute_length; - for ( ushort bmidx = 0; bmidx < num_bootstrap_methods; ++bmidx ) - { - if ( qftell(myFile) >= end ) - goto declerr_w; - const ushort bootstrap_method_ref = read2(); - - if ( qftell(myFile) >= end ) - goto declerr_w; - const ushort num_bootstrap_arguments = read2(); - - bootstrap_method_def_t mdef; - mdef.method_ref = bootstrap_method_ref; - for ( ushort baidx = 0; baidx < num_bootstrap_arguments; ++baidx ) - { - if ( qftell(myFile) >= end ) - goto declerr_w; - const ushort bootstrap_argument = read2(); - mdef.args.push_back(bootstrap_argument); - } - - bootstrap_methods_set_method(mdef, bmidx); - } - - // Now that all bootstrap methods are loaded, try and resolve - // the constant pool's references to it - FOR_EACH_CONSTANT_POOL_INDEX(cpidx) - { - const_desc_t cd; - cd.type = 0; - ConstantNode.supval(cpidx, &cd, sizeof(cd)); - if ( cd.type == CONSTANT_InvokeDynamic ) - { - bootstrap_method_def_t mdef; - if ( bootstrap_methods_get_method(&mdef, cd._bmidx) ) - LoadOpis(lm_normal, mdef.method_ref, CONSTANT_MethodHandle, NULL); - } - } - } - break; - - case attr_UNKNOWN: - atrs[0] = uchar(apk); - if ( loadMode & MLD_EXTATR ) - { -attr2file: - const char *p = CopyAttrToFile(atrs, attribute_length, attribute_name_index); - if ( p == NULL ) - break; - loader_failure("%s %sattribute '%s'%s", - p, - atrs[0] == ' ' ? "" : "additional ", - &atrs[1], - mk_diag(apk, diastr)); - } - if ( idpflags & IDM_REQUNK ) - { - idpflags &= ~IDM_REQUNK; - if ( ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "File contains unknown attribute(s).\n" - "Do you want store it in external files?\n\n") > ASKBTN_NO ) - { - loadMode |= MLD_EXTATR; - goto attr2file; - } - } - eflg = 1; - goto unkAttr; - case attr_NONAME: - qsnprintf(atrs, sizeof(atrs), "(with index %u)", attribute_name_index); - goto notify; - case attr_TRUNCATED: - qstrncat(atrs, "...", sizeof(atrs)); -unkAttr: - atrs[0] = '"'; - qstrncat(atrs, "\"", sizeof(atrs)); -notify: -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4191) -#endif - if ( eflg && !(idpflags & IDM_WARNUNK) ) - msg( - "Ignore%s %s attribute (size %u)%s\n", - (uchar)atrs[0] == ' ' ? "" : " unknown", - atrs, attribute_length, mk_diag(apk, diastr)); - else - load_msg( - "Ignore%s %s attribute (size %u)%s\n", - (uchar)atrs[0] == ' ' ? "" : " unknown", - atrs, attribute_length, mk_diag(apk, diastr)); -#ifdef _MSC_VER -#pragma warning(pop) -#endif -skipAttr: - if ( attribute_length ) - { -real_skipAttr: - skipData(attribute_length); - } - break; - - case attr_ConstantValue: - { - ushort constantvalue_index; - if ( attribute_length != 2 || !LoadOpis(lm_normal, constantvalue_index = read2(), 0, &opis) ) - { - declerr: - ++fatal; - declerr_w: - load_msg("Illegal declaration of %s%s\n", - &atrs[1], mk_diag(apk, diastr)); - goto skipAttr; - } - - temp = curField.valNode; - if ( !temp ) - { - temp.create(); - curField.valNode = temp; - r = 0; - } - else - { - r = (uint)temp.altval(0); - } - switch ( opis.type ) - { - case CONSTANT_Integer: - case CONSTANT_Long: - case CONSTANT_Float: - case CONSTANT_Double: - case CONSTANT_String: - temp.supset(++r, &opis, sizeof(opis)); - break; - default: - BadRef(curClass.start_ea + curField.id.Number, "value", constantvalue_index, apk); - temp.altset(++r, (((uint32) constantvalue_index) << 16) | 0xFFFF); - break; - } - temp.altset(0, r); - } - break; - - case attr_Code: - if ( curSeg.CodeSize ) - { -//duplerr: - ++fatal; -duplerr_w: - if ( fatal ) - loader_failure("Duplicate %s attribute declaration%s", &atrs[1], mk_diag(apk, diastr)); - else - load_msg("Duplicate %s attribute declaration%s", &atrs[1], mk_diag(apk, diastr)); - goto skipAttr; - } - r = curClass.JDKsubver ? 12 : 8; - if ( attribute_length < r ) - goto declerr; - attribute_length -= r; - r -= 8; - curSeg.stacks = r ? read2() : read1(); - curSeg.DataSize = r ? read2() : read1(); //max_locals - curSeg.CodeSize = r ? read4() : read2(); - if ( curSeg.CodeSize != 0 ) - { - if ( attribute_length < curSeg.CodeSize ) - goto declerr; - attribute_length -= curSeg.CodeSize; - if ( FileSize < curSeg.CodeSize ) - errtrunc(); - FileSize -= curSeg.CodeSize; - { - segment_t *S = _add_seg(-1); // expand size - if ( curSeg.DataSize ) - set_default_sreg_value(S, rVds, _add_seg(2)->sel); // create data segment - } - } - - { - const ushort exception_table_length = read2(); - if ( exception_table_length != 0 ) // except. table - { - if ( !curSeg.CodeSize ) - goto declerr; - - r = ((uint32) exception_table_length) * (2*4); - if ( attribute_length < r ) - goto declerr; - attribute_length -= r; - temp.create(); - curSeg.excNode = temp; - temp.altset(0, exception_table_length); - ea_t ea = curSeg.start_ea + curSeg.CodeSize; - r = 1; - uchar err = 0; - do - { - Exception exc; - - exc.start_pc = read2(); - exc.end_pc = read2(); - exc.handler_pc = read2(); - - exc.filter.Ref &= 0; // for 'finally' - exc.filter.Dscr = read2(); - if ( exc.filter.Dscr != 0 ) - { - if ( !LoadNamedClass(lm_normal, exc.filter.Dscr, &opis) ) - { - BadRef(ea, ".catch", exc.filter.Dscr, apk); - } - else - { - exc.filter.Name = opis._name; - xtrnRef(ea, opis); - } - } - temp.supset(r++, &exc, sizeof(exc)); - err |= set_exception_xref(&curSeg, exc, ea); // as procedure for base converter - } - while ( (ushort)r <= exception_table_length ); - if ( err ) - { - remember_problem(PR_ILLADDR, ea); - load_msg("Invalid address(es) in .catch%s\n", - mk_diag(apk, diastr)); - } - } - }// exception table - - savesize = attribute_length; - load_attributes(attr_parent_kind_code); //Additional attr - savesize = -1; - break; - - case attr_Exceptions: - if ( curSeg.thrNode ) - goto duplerr_w; - if ( attribute_length < (2+2) || (attribute_length % 2) ) - goto declerr_w; - attribute_length -= 2; - if ( (attribute_length / 2) != (uint32)read2() ) - goto declerr_w; - attribute_length /= 2; - temp.create(); - curSeg.thrNode = temp; - r = 0; - do - { - const ushort exception_index = read2(); - if ( exception_index == 0 ) - { - load_msg("Ignore zero exception index%s\n", mk_diag(apk, diastr)); - } - else - { - uint32 refd = (uint32)exception_index << 16; - if ( !LoadNamedClass(lm_normal, exception_index, &opis) ) - { - BadRef(curSeg.start_ea, ".throws", exception_index, apk); - } - else - { - refd |= opis._name; - xtrnRef(curSeg.start_ea, opis); - } - temp.altset(++r, refd); - } - } - while ( --attribute_length ); - temp.altset(0, r); - break; - - case attr_LineNumberTable: - if ( lntb ) - goto duplerr_w; - ++lntb; - r = attribute_length - 2; - if ( attribute_length < 2 || (r % 4) ) - goto declerr_w; - attribute_length -= 2; - if ( (r /= 4) != (uint32)read2() ) - goto declerr_w; - if ( attribute_length == 0 ) - { -//Symantec error (strip) #1 - deb(IDA_DEBUG_LDR, - "Stripped declaration of LineNumber table%s\n", - mk_diag(apk, diastr)); - } - while ( r-- ) - { - const ushort start_pc = read2(); - const ushort line_number = read2(); - if ( uint32(start_pc) < curSeg.CodeSize ) - set_source_linnum(curSeg.start_ea + start_pc, line_number); - else - load_msg("Illegal address (%u) of source line %u%s\n", start_pc, - line_number, mk_diag(apk, diastr)); - } - break; - - case attr_LocalVariableTypeTable: - if ( !(lvtb & 1) ) // ATT: my be can before LocalVariableTable? - { - if ( fatal ) - loader_failure("%s before LocalVariableTable%s", atrs, mk_diag(apk, diastr)); - else - load_msg("%s before LocalVariableTable%s", atrs, mk_diag(apk, diastr)); - goto skipAttr; - } - ++eflg; // 2 <= 1 + 1 - //PASS THRU - case attr_LocalVariableTable: - ++eflg; // 1 - if ( lvtb & eflg ) - goto duplerr_w; - lvtb |= eflg; - --eflg; // unification (0/1) - r = attribute_length - 2; - if ( attribute_length < 2 || (r % 10) ) - goto declerr_w; - attribute_length -= 2; - if ( (r /= 10) != (uint32)read2() ) - goto declerr_w; - while ( r-- ) - { - LocVar lv; - - lv.ScopeBeg = read2(); // start_pc - lv.ScopeTop = read2(); // length - lv.var.Name = read2(); // name_index - CASSERT(offsetof(LocVar,utsign) == offsetof(LocVar,var.Dscr)+sizeof(lv.var.Dscr) - && sizeof(lv.var.Dscr)*2 == sizeof(uint32)); - *(uint32 *)&lv.var.Dscr &= 0; - if ( eflg == 0 ) // LocalVariableTable/LocalVariableTypeTable - lv.var.Dscr = read2(); // descriptor_index - else - lv.utsign = read2(); // descriptor_index - const ushort index = read2(); // index - if ( !eflg ) // normal table - { - if ( index == 0 && !lv.var.Name && !lv.ScopeBeg && lv.ScopeTop <= 1 ) - { -//Symantec error (strip) #2 - deb(IDA_DEBUG_LDR, - "Stripped declaration of local variables%s\n", - mk_diag(apk, diastr)); - continue; - } - if ( (short)lv.ScopeBeg == -1 ) - { -//Microsoft VisualJ++ error (purge?) - LoadAnyString(lm_normal, lv.var.Name); - LoadAnyString(lm_normal, lv.var.Dscr); - deb(IDA_DEBUG_LDR, - "Purged declaration of LocVar#%u%s\n", index, - mk_diag(apk, diastr)); - continue; - } - } - ValidateStoreLocVar(index, lv); - } // while - break; - - case attr_SourceFile: - { - if ( attribute_length != 2 ) - goto declerr_w; - const ushort sourcefile_index = read2(); - if ( LoadAnyString(lm_normal, sourcefile_index) ) - curClass.SourceName = sourcefile_index; - else - BadRef(BADADDR, "source file name", sourcefile_index, apk); - } - break; - - case attr_InnerClasses: - r = attribute_length - 2; - if ( attribute_length < 2 || (r % 8) ) - goto declerr_w; - attribute_length -= 2; - if ( (r /= 8) != (uint32)read2() ) - goto declerr_w; - if ( !r ) - { - deb(IDA_DEBUG_LDR, "Stripped declaration of InnerClasses\n"); - break; - } - attribute_length = r; - { - ushort flags = 0; - while ( attribute_length-- ) - { - InnerClass ic; - - *(uchar *)&flags = 0; - ic.inner = read2(); // inner_class_info_index - if ( ic.inner && !LoadNamedClass(lm_normal, ic.inner, &opis) ) - flags |= 0x101; - else - ic.inner = opis._name; - ic.outer = read2(); // outer_class_info_index - if ( ic.outer && !LoadNamedClass(lm_normal, ic.outer, &opis) ) - flags |= 0x101; - else - ic.outer = opis._name; - ic.name = read2(); // inner_class_name_index - if ( ic.name && !LoadFieldName(lm_normal, ic.name) ) - flags |= 0x101; - ic.access = read2(); // inner_class_access_flags - r = ic.access & ACC_ACCESS_MASK; - if ( r & (r-1) ) - flags |= 0x101; - if ( uchar(flags) == 0 ) - { - temp = curClass.innerNode; - if ( !temp ) - { - temp.create(); - curClass.innerNode = temp; - r = 0; - } - else - { - r = (uint)temp.altval(0); - } - temp.supset(++r, &ic, sizeof(ic)); - temp.altset(0, r); - } - } - if ( flags != 0 ) - load_msg("Error declaration(s) in Inner Classes\n"); - } - break; - - case attr_EnclosingMethod: - if ( curClass.encClass ) - goto duplerr_w; - if ( attribute_length != 4 ) - goto declerr_w; - curClass.encClass = LoadNamedClass(lm_normal, read2(), &opis) - ? opis._name - : 0xFFFF; - { - const ushort method_index = read2(); - if ( curClass.encClass == 0xFFFF ) - { -bad_encl: - msg("Invalid EnclosingMethod description\n"); - } - else if ( method_index != 0 ) - { - if ( !LoadOpis(lm_normal, method_index, CONSTANT_NameAndType, &opis) - || !(opis.flag & SUB_FLDNAME) - || !LoadCallDscr(lm_normal, opis._name) ) - { - goto bad_encl; - } - curClass.encMethod = method_index; - } - } - break; - - case attr_Synthetic: - if ( attribute_length != 0 ) - goto declerr_w; - switch ( apk ) - { - default: // attr_parent_kind_code - goto declerr_w; // paranoya - case attr_parent_kind_field: - curField.id.access |= ACC_SYNTHETIC; - break; - case attr_parent_kind_method: - curSeg.id.access |= ACC_SYNTHETIC; - break; - case attr_parent_kind_class_file: - curClass.AccessFlag |= ACC_SYNTHETIC; - break; - } - break; - - case attr_Deprecated: - if ( attribute_length != 0 ) - goto declerr_w; - switch ( apk ) - { - default: // attr_parent_kind_code - goto declerr_w; // paranoya - case attr_parent_kind_field: - curField.id.extflg |= XFL_DEPRECATED; - break; - case attr_parent_kind_method: - curSeg.id.extflg |= XFL_DEPRECATED; - break; - case attr_parent_kind_class_file: - curClass.extflg |= XFL_DEPRECATED; - break; - } - break; - - case attr_Signature: - if ( attribute_length != 2 || apk == attr_parent_kind_code ) - goto declerr_w; - { - const ushort signature_index = read2(); - if ( CheckSignature(signature_index, apk) ) - { - switch ( apk ) - { - case attr_parent_kind_field: - curField.id.utsign = signature_index; - break; - case attr_parent_kind_method: - curSeg.id.utsign = signature_index; - break; - case attr_parent_kind_class_file: - curClass.utsign = signature_index; - break; - default: break; - } - } - } - break; - - case attr_StackMapTable: - ++eflg; - // fallthrough - case attr_StackMap: - if ( !eflg != (curClass.JDKsubver < 6) ) - { - if ( fatal ) - loader_failure("JDK1.%u incompatible with attribute%s%s", curClass.JDKsubver, atrs, mk_diag(apk, diastr)); - else - load_msg("JDK1.%u incompatible with attribute%s%s", curClass.JDKsubver, atrs, mk_diag(apk, diastr)); - goto skipAttr; - } - if ( curSeg.smNode ) - goto duplerr_w; - if ( attribute_length < 2 ) - goto declerr_w; - { - const ushort number_of_entries = read2(); - if ( number_of_entries == 0 ) - { - attribute_length -= 2; - curSeg.smNode = BADNODE; - deb(IDA_DEBUG_LDR, - "Empty%s attribute%s\n", atrs, mk_diag(apk, diastr)); - curSeg.id.extflg |= XFL_M_EMPTYSM; - } - else - { - temp.create(); - curSeg.smNode = temp; - r = sm_load(number_of_entries, &attribute_length); - if ( int(r) <= 0 ) - { - temp.kill(); - curSeg.smNode = BADNODE; - if ( !r ) - goto declerr_w; - if ( fatal ) - loader_failure("Inconsistent declaration of %s%s", &atrs[1], mk_diag(apk, diastr)); - else - load_msg("Inconsistent declaration of %s%s", &atrs[1], mk_diag(apk, diastr)); - goto skipAttr; //-V779 Unreachable code detected - } - } - } -skip_excess: - if ( attribute_length ) - { - deb(IDA_DEBUG_LDR, - "Excess %u bytes in%s attribute%s\n", attribute_length, atrs, - mk_diag(apk, diastr)); - goto real_skipAttr; - } - break; - - case attr_AnnotationDefault: - pann = &curSeg.annNodes[2]; - eflg = 4; // as flag - goto do_annot1; - case attr_RuntimeInvisibleParameterAnnotations: - ++eflg; - //PASS THRU - case attr_RuntimeVisibleParameterAnnotations: - pann = &curSeg.annNodes[3]; - eflg |= 2; // flag of secondary loop -do_annot1: - if ( apk != attr_parent_kind_method ) - goto declerr_w; // paranoya - goto do_annot; - case attr_RuntimeInvisibleAnnotations: - ++eflg; - //PASS THRU - case attr_RuntimeVisibleAnnotations: - switch ( apk ) - { - default: // attr_parent_kind_code - goto declerr_w; // paranoya - case attr_parent_kind_class_file: - pann = curClass.annNodes; - break; - case attr_parent_kind_field: - pann = curField.annNodes; - break; - case attr_parent_kind_method: - pann = curSeg.annNodes; - break; - } -do_annot: - if ( eflg & 1 ) - ++pann; // invisible - if ( *pann ) - goto duplerr_w; - temp.create(); - *pann = temp; - if ( attribute_length == 0 ) - goto declerr_w; - { - uchar *p = annotation_realloc(attribute_length); - r = 1; // no paramsloop - if ( eflg & 2 ) // Parameters - { - r = read1(); - *p++ = (uchar)r; - --attribute_length; - if ( !r ) - goto annot_err; - } - if ( eflg & 4 ) // defalut - { - p = annot_elm(p, &attribute_length); - if ( p != NULL ) - goto annot_done; -annot_err: - temp.kill(); - *pann = (uval_t)-1; // as flag for duplicates - goto declerr_w; - } - do // loop for Parameters - { - if ( attribute_length < 2 ) - goto annot_err; - uint cnt = read2(); - attribute_length -= 2; - *(ushort *)p = (ushort)cnt; - p += sizeof(ushort); - if ( !cnt ) - { - if ( !(eflg & 2) ) - goto annot_err; // no parameters - continue; - } - eflg |= 8; // flag for parameters - do - { - if ( attribute_length < 2 ) - goto annot_err; - attribute_length -= 2; - ushort id = read2(); - if ( !isSingleClass(id) ) - goto annot_err; - *(ushort*)p = id; - p = annotation(p + sizeof(ushort), &attribute_length); - if ( p == NULL ) - goto annot_err; - } - while ( --cnt ); - } - while ( --r ); // parameters loop - if ( eflg == 2 ) - goto annot_err; // empty Parameters annotation -annot_done: - r = (uint)(p - annBuf); - } // local variable block - temp.setblob(annBuf, r, 0, BLOB_TAG); - temp.altset(0, r); - goto skip_excess; - - default: - INTERNAL("load_attributes"); - } //switch - } // for -} - -//----------------------------------------------------------------------- -uchar java_t::CheckSignature(ushort index, attr_parent_kind_t apk) -{ - char diastr[128]; - const_desc_t opis; - - if ( !LoadOpis(lm_normal, index, CONSTANT_Utf8, &opis) ) - { -bad: - if ( apk != attr_parent_kind_code ) // not debug variable - load_msg("Invalid signature (#%u)%s\n", index, mk_diag(apk, diastr)); - return 0; - } - - CASSERT(HAS_TYPEDSCR < 0x100 && HAS_CALLDSCR < 0x100); //-V590 expression is excessive - if ( !((uchar)opis.flag & ((apk == attr_parent_kind_method ) ? HAS_CALLDSCR : HAS_TYPEDSCR)) ) - { - if ( !opis._Ssize ) - goto bad; // PARANOYA - if ( opis._Sflags & (_OP_EXTSYM_ | _OP_NOSIGN) ) - goto bad; - opis._Sflags &= (_OP_VALPOS | _OP_METSIGN | _OP_CLSSIGN); - switch ( apk ) - { - case attr_parent_kind_method: - if ( (opis._Sflags &= ~_OP_METSIGN) != _OP_VALPOS ) - goto bad; - break; - case attr_parent_kind_class_file: - opis._Sflags &= ~_OP_CLSSIGN; - //PASS THRU - default: // FIELD & .var - if ( opis._Sflags ) - goto bad; - break; - } - } - return 1; -} - -//----------------------------------------------------------------------- -// -// This function should read the input file (it is opened in binary mode) -// analyze it and: -// - loading segment and offset are in inf.BaseAddr & -// - load it into the database using file2base(),mem2base() -// or allocate addresses by enable_flags() and fill them -// with values using putByte(), putWord(), putLong() -// - (if createsegs) create segments using -// add_segm(segment_t *,const char *name,const char *sclass,int flags) -// or -// add_segm(uint short,ea_t,ea_t,char *,char *) -// see segment.hpp for explanations -// - set up inf_get_start_ip(),startCS to the starting address -// - set up inf_get_min_ea(),inf_get_max_ea() -// -// -void java_t::loader(FILE *fp, bool manual) -{ - ushort j; - const_desc_t opis; - - memset(&curClass, 0, sizeof(curClass)); - qfseek(fp, 0, SEEK_SET); //rewind - FileSize = qfsize(fp); - myFile = fp; - enableExt_NameChar(); - - if ( read4() != MAGICNUMBER ) - error("Illegal magic number"); - - curClass.MinVers = read2(); - curClass.MajVers = read2(); - - if ( curClass.MajVers <= JDK_MIN_MAJOR ) - { - if ( curClass.MajVers < JDK_MIN_MAJOR ) - goto BAD_VERSION; - curClass.JDKsubver = (uchar)(curClass.MinVers >= JDK_1_1_MINOR); - } - else if ( curClass.MajVers > JDK_MAX_MAJOR || curClass.MinVers ) - { -BAD_VERSION: - loader_failure("Unsupported file format (version %u.%u)", - curClass.MajVers, curClass.MinVers); - } - else - { - curClass.JDKsubver = (uchar)(curClass.MajVers - (JDK_MIN_MAJOR-1)); - } - - if ( curClass.MajVers >= JDK_SMF_MAJOR_MIN ) - { - SMF_mode = 1; - } - else if ( curClass.JDKsubver <= 1 ) - { - switch ( curClass.MinVers ) - { - default: - ask_for_feedback( - "Class file with version %u.%u (JDK1.%u?) is not tested!", - curClass.MajVers, curClass.MinVers, curClass.JDKsubver); - //PASS THRU - case JDK_1_02_MINOR: - case JDK_1_1_MINOR: - break; - } - } -//-- - curClass.maxCPindex = read2(); - if ( curClass.maxCPindex <= 2 ) - loader_failure("Empty constant pool"); - loadMode = loadDialog(manual); - ConstantNode.create(constant_pool); - --curClass.maxCPindex; // last valid number - XtrnNode.create(); - make_NameChars(/*on_load=*/ true); // initialize and set 'load extension' - const uint nconstants = load_constants_pool(); - if ( !_add_seg(0) ) - { - XtrnNode.kill(); - } - else - { - curClass.xtrnCnt = ushort(nconstants); - curClass.xtrnNode = XtrnNode; - } -//-- - curClass.AccessFlag = read2(); - if ( curClass.AccessFlag & ~ACC_THIS_MASK ) - load_msg("Illegal class access bits (0x%X)\n", curClass.AccessFlag); - curClass.This.Dscr = read2(); - if ( LoadNamedClass(lm_normal, curClass.This.Dscr, &opis) ) - { - curClass.This.Name = opis._name; - } - else - { - BadRefFile("'this' class", curClass.This.Dscr); - CASSERT(offsetof(ClassInfo, This.Ref)+2 == offsetof(ClassInfo, This.Dscr) - && offsetof(ClassInfo, This.Ref) == offsetof(ClassInfo, This.Name)); - curClass.This.Ref >>= 16; -// curClass.This.Name = curClass.This.Dscr; -// curClass.This.Dscr = 0; - } -//-- - if ( curClass.xtrnNode ) - setPoolReference(); - curClass.super.Dscr = read2(); - uint i = read2(); // interface counter - i *= 2; - if ( FileSize < i ) - errtrunc(); - qfseek(fp, i, SEEK_CUR); - curClass.FieldCnt = read2(); - qfseek(fp, -2 - qoff64_t(i), SEEK_CUR); - _add_seg(3); // class segment - enableExt_NameChar(); - if ( curClass.This.Dscr ) - { - curSeg.id.Number = 0; - SetName(curClass.This.Name, curClass.start_ea, curClass.AccessFlag, 0); - hide_name(curClass.start_ea); - } - - if ( curClass.super.Ref ) - { - if ( !LoadNamedClass(lm_normal, curClass.super.Dscr, &opis) ) - { - BadRefFile("parent class", curClass.super.Dscr); - } - else - { - curClass.super.Name = opis._name; - xtrnRef(curClass.start_ea, opis); - } - } -//-- - if ( (i /= 2) != 0 ) //InterfaceCount - { - netnode temp; - uint r = 0; - - do - { - j = read2(); - if ( j == 0 ) - { - load_msg("Ignore zero interface index\n"); - continue; - } - if ( !r ) - temp.create(); - - uint32 refd = (uint32)j << 16; - if ( !LoadNamedClass(lm_normal, j, &opis) ) - { - BadRefFile("interface", j); - } - else - { - xtrnRef(curClass.start_ea, opis); - refd |= opis._name; - } - temp.altset(++r, refd); - } - while ( --i ); - if ( r ) - { - temp.altset(0, r); - curClass.impNode = temp; - } - } -//--- - ClassNode.create(); - curClass.ClassNode = ClassNode; - qfseek(fp, 2, SEEK_CUR); - if ( errload ) - { - int f = (curClass.AccessFlag & ~ACC_THIS_MASK) ? curClass.AccessFlag : 0; - mark_access(curClass.start_ea, f); - } -//--- - for ( i = 1; (ushort)i <= curClass.FieldCnt; i++ ) - { - memset(&curField, 0, sizeof(curField)); - curField.id.Number = (ushort)i; - curField.id.access = read2(); - j = curField.id.access & ACC_ACCESS_MASK; - if ( (curField.id.access & ~ACC_FIELD_MASK) || (j & (j-1)) ) - { - load_msg("Illegal Field#%u Attribute 0x%04x\n", i, curField.id.access); -// curField.id.extflg |= EFL_ACCESS; - mark_access(curClass.start_ea + i, curField.id.access); - } - - curField.id.name = read2(); - if ( !CheckFieldName(lm_normal, curField.id.name, NULL) ) - curField.id.extflg |= EFL_NAME; - - curField.id.dscr = read2(); - if ( !CheckFieldDscr(lm_normal, curField.id.dscr, &opis) ) - curField.id.extflg |= EFL_TYPE; - else - xtrnRef_dscr(curClass.start_ea + curField.id.Number, &opis); - if ( curField.id.extflg & EFL_NAMETYPE ) - load_msg("Illegal NameAndType of field %u\n", i); - load_attributes(attr_parent_kind_field); - for ( int n = 0; n < qnumber(curField.annNodes); n++ ) - if ( curField.annNodes[n] == (uval_t)-1 ) - ++curField.annNodes[n]; - ClassNode.supset(i, &curField, sizeof(curField)); - if ( !(curField.id.extflg & EFL_NAME) ) - SetName(curField.id.name, curClass.start_ea + i, curField.id.access, i); - } -//-- - curClass.MethodCnt = read2(); - for ( i = 1; i <= curClass.MethodCnt; i++ ) - { - memset(&curSeg, 0, sizeof(curSeg)); - curSeg.id.Number = (ushort)i; - curSeg.id.access = read2(); - j = curSeg.id.access & ACC_ACCESS_MASK; - if ( !(j & ~ACC_METHOD_MASK) && !(j & (j-1)) ) - j = 0; - else - load_msg("Illegal Method#%u Attribute 0x%04x\n", i, curSeg.id.access); -// curSeg.id.extflg |= EFL_ACCESS; - - _add_seg(1); // create code segment // this for strnRef_dscr - curSeg.id.name = read2(); - if ( !CheckFieldName(lm_normal, curSeg.id.name, NULL) ) - curSeg.id.extflg |= EFL_NAME; - - curSeg.id.dscr = read2(); - if ( !CheckCallDscr(lm_normal, curSeg.id.dscr, &opis) ) - curSeg.id.extflg |= EFL_TYPE; - else - xtrnRef_dscr(curSeg.start_ea, &opis, 1); - if ( curSeg.id.extflg & EFL_NAMETYPE ) - load_msg("Illegal NameAndType of method %u\n", i); -// if ( curSeg.id.extflg & EFL_ACCESS ) - if ( j ) - mark_access(curSeg.start_ea, curSeg.id.access); - load_attributes(attr_parent_kind_method); - if ( curSeg.smNode == BADNODE ) - curSeg.smNode = 0; // remove 'flagged' value - for ( int n = 0; n < qnumber(curSeg.annNodes); n++ ) - if ( curSeg.annNodes[n] == (uval_t)-1 ) - ++curSeg.annNodes[n]; - if ( curSeg.varNode ) - resizeLocVars(); - if ( curSeg.thrNode ) - { - netnode tnode(curSeg.thrNode); - if ( !tnode.altval(0) ) - { - tnode.kill(); - curSeg.thrNode = 0; - } - } - ClassNode.supset(-(int)i, &curSeg, sizeof(curSeg)); - } -//-- - load_attributes(attr_parent_kind_class_file); // Source File - for ( int n = 0; n < qnumber(curClass.annNodes); n++ ) - if ( curClass.annNodes[n] == (uval_t)-1 ) - ++curClass.annNodes[n]; - myFile = NULL; - if ( curClass.encClass == 0xFFFF ) - ++curClass.encClass; // unification in out - if ( FileSize ) - warning("This file has extra information (pos=0x%" FMT_64 "x)", qftell(fp)); -//--- - CheckPoolReference(0); - endLoad_NameChar(); // set 'standart extension' - if ( !set_parent_object() && (curClass.AccessFlag & ACC_INTERFACE) ) - { - load_msg("This is interface, but superclass is not java.lang.Object!\n"); - mark_and_comment(curClass.start_ea, "Interface have nonstandart parent"); - } - if ( curClass.impNode && !curClass.super.Ref ) - { - load_msg("This have implements without superclass!\n"); - mark_and_comment(curClass.start_ea, "Empty supperclass not for Object"); - } - if ( errload ) - curClass.extflg |= XFL_C_ERRLOAD; - ConstantNode.supset(CNS_CLASS, &curClass, sizeof(curClass)); // load end! -//-- - debugmode = 1; // full pass... - for ( i = 1; i <= curClass.MethodCnt; i++ ) - { - msg("Analysing method %u...\n", i); - ClassNode.supval(-(int)i, &curSeg, sizeof(curSeg)); - ea_t ea = curSeg.start_ea; - show_addr(ea); - ea_t end = ea + curSeg.CodeSize; - segment_t *s = getseg(ea); - if ( s == NULL || end < ea || end > s->end_ea ) - loader_failure("Bad method %u code size 0x%X", i, curSeg.CodeSize); - if ( !curSeg.CodeSize ) - { - create_byte(ea, 0x10); - } - else - { - do - { - int sz = create_insn(ea); - if ( sz == 0 ) - ++sz; - ea += sz; - } - while ( ea < end ); - } - if ( (curSeg.id.extflg & EFL_NAME) == 0 ) - SetName(curSeg.id.name, curSeg.start_ea, curSeg.id.access, - curClass.FieldCnt + i); - add_func(curSeg.start_ea, end + 1); - } - debugmode = 0; // all references setting... - CheckPoolReference(1); - ConstantNode.altset(CNA_VERSION, _CUR_IDP_VER); - ResW_newbase(); - create_filename_cmt(); -} diff --git a/idasdk75/module/java/npooluti.cpp b/idasdk75/module/java/npooluti.cpp deleted file mode 100644 index a2c234b..0000000 --- a/idasdk75/module/java/npooluti.cpp +++ /dev/null @@ -1,2031 +0,0 @@ -#include "java.hpp" -#include <diskio.hpp> -#include <entry.hpp> -#include "npooluti.hpp" -#include "oututil.hpp" - -#ifndef NCPS -#define NCPS 0x110000 -#endif - -//----------------------------------------------------------------------- -NORETURN void errtrunc(void) -{ - loader_failure("Premature end of file"); -} - -//----------------------------------------------------------------------- -GCC_DIAG_OFF(format-nonliteral); -void java_t::load_msg(const char *format, ...) -{ // this procedure prepares saving load-time message to base - char str[MAXSTR]; - va_list va; - - ++errload; - va_start(va, format); - int cnt = qvsnprintf(str, sizeof(str), format, va); - va_end(va); - msg("%s", str); - for ( int i = cnt; i; ) - { - if ( str[--i] <= ' ' ) // remove cr's - continue; - if ( ++i > MAXSPECSIZE ) - { - i = MAXSPECSIZE; - memcpy(&str[MAXSPECSIZE-3], "...", 3); - } - - netnode temp; - uval_t j; - if ( !curClass.msgNode ) - { - temp.create(); - curClass.msgNode = temp; - j = 0; - } - else - { - temp = curClass.msgNode; - j = temp.altval(0); - } - temp.supset(j, str, i); - temp.altset(0, j+1); - break; - } -} -GCC_DIAG_ON(format-nonliteral); - -//----------------------------------------------------------------------- -const char *java_t::mk_diag(attr_parent_kind_t apk, char str[128]) const -{ - static const char *const diag[] = { "Code in method", "Field", "Method" }; - str[0] = '\0'; - if ( apk < attr_parent_kind_class_file ) - qsnprintf(str, - 126, - " for %s#%u", diag[uchar(apk)], - apk == attr_parent_kind_field ? curField.id.Number : curSeg.id.Number); - return str; -} - -//----------------------------------------------------------------------- -void java_t::BadRef(ea_t ea, const char *to, ushort id, attr_parent_kind_t apk) -{ - if ( ea != BADADDR ) - remember_problem(PR_DISASM, ea); - - char diastr[128]; - load_msg("Illegal %s reference (%u)%s\n", to, id, mk_diag(apk, diastr)); -} - -//----------------------------------------------------------------------- -void java_t::mark_access(ea_t ea, ushort acc) const -{ - char str[60]; - - str[0] = 0; // for module - if ( acc ) - qsnprintf(str, sizeof(str), "Illegal access bits (0x%X)", acc); - mark_and_comment(ea, str); -} - -//------------------------------------------------------------------------- -static const char *_constant_strings[CONSTANT_LAST+1] = -{ - // 0 - "<UNKNOWN>", - "Utf8", - "Unicode", - "Integer", - "Float", - // 5 - "Long", - "Double", - "Class", - "String", - "Fieldref", - // 10 - "Methodref", - "InterfaceMethodref", - "NameAndType", - "<UNUSED_13>", - "<UNUSED_14>", - // 15 - "MethodHandle", - "MethodType", - "<UNUSED_17>", - "InvokeDynamic", -}; -const char *constant_type_to_str(uchar ctype) -{ - if ( ctype > CONSTANT_LAST ) - ctype = 0; - return _constant_strings[ctype]; -} - -//------------------------------------------------------------------------- -void print_constant( - qstrvec_t *out, - const const_desc_t &cd, - ushort index, - bool strip_tags) -{ - size_t anchor = out->size(); - - op_t x; - memset(&x, 0, sizeof(x)); - copy_const_to_opnd(x, cd); - x.ref = 0; // as flag - x.cp_type = cd.type; - x.cp_ind = index; - if ( x.cp_type == CONSTANT_Class ) - x.addr_shorts.high = (cd.flag & HAS_CLSNAME) != 0 ? fmt_fullname : fmt_ClassName; - out_java_t *ctx = (out_java_t *) create_outctx(BADADDR); - ctx->init_lines_array(out, 1000); - ctx->init_prompted_output(); - ctx->OutConstant(x, /*include_descriptor=*/ true); - ctx->flush_outbuf(); - - if ( strip_tags ) - { - for ( ; anchor < out->size(); ++anchor ) - tag_remove(&out->at(anchor)); - } - - delete ctx; -} - -//----------------------------------------------------------------------- -void *myAlloc(uint size) -{ - void *p = qalloc(size); - if ( p == NULL ) - nomem("JavaLoader"); - return p; -} - -//----------------------------------------------------------------------- -uchar *java_t::sm_realloc(uint size) -{ - if ( size > curClass.maxSMsize ) - { - curClass.maxSMsize = size; - qfree(smBuf); - smBuf = (uchar*)myAlloc(size+1); - } - return smBuf; -} - -//----------------------------------------------------------------------- -uchar *java_t::annotation_realloc(uint size) -{ - if ( size > curClass.maxAnnSz ) - { - curClass.maxAnnSz = size; - qfree(annBuf); - annBuf = (uchar*)myAlloc(size+1); - } - return annBuf; -} - -//----------------------------------------------------------------------- -// visible for converter only -ushort *java_t::append_tmp_buffer(uint size) -{ - if ( (ushort)size > curClass.maxStrSz ) - { - curClass.maxStrSz = (ushort)size; - qfree(tsPtr); - tsPtr = (ushort*)myAlloc(size*sizeof(ushort)*2+sizeof(ushort)); - } - return tsPtr; -} - -//----------------------------------------------------------------------- -bool java_t::getblob(uval_t ind, void *p, uval_t sz) -{ - if ( (ushort)sz > curClass.maxStrSz ) - return false; - - sz *= 2; - size_t ts = (size_t)sz + 1; - return ConstantNode.getblob(p, &ts, ind, BLOB_TAG) && (uint32)ts == sz; -} - -//------------------------------------------------------------------------- -bool java_t::getstr(qstring *out, ushort index) -{ - bool ok = is_valid_string_index(index); - if ( ok ) - { - // || !getblob(ind2, p2 = p1 + (size_t)siz1, siz2) ) - // uval_t i1 = ConstantNode.altval(ind1); - uint32 raw_idx = (uint32)index << 16; - nodeidx_t sz = ushort(ConstantNode.altval(raw_idx)); - ok = sz > 0; - if ( ok ) - { - qvector<ushort> raw; - raw.resize(sz, 0); - msg("Reading %u bytes\n", uint32(sz)); - ok = getblob(raw_idx, raw.begin(), sz); - if ( ok ) - out->append((const char *) raw.begin(), sz); - } - } - return ok; -} - -//---------------------------------------------------------------------- -NORETURN static void readerr(void) -{ - loader_failure("Input file read error"); -} - -//----------------------------------------------------------------------- -ushort java_t::read2(void) -{ - ushort data; - if ( FileSize < 2 ) - errtrunc(); - FileSize -= 2; - if ( fread2bytes(myFile, &data, 1) != 0 ) - readerr(); - return data; -} - -//----------------------------------------------------------------------- -uint32 java_t::read4(void) -{ - uint32 data; - if ( FileSize < 4 ) - errtrunc(); - FileSize -= 4; - if ( fread4bytes(myFile, &data, 1) != 0 ) - readerr(); - return data; -} - -//----------------------------------------------------------------------- -uchar java_t::read1(void) -{ - uchar data; - if ( !FileSize ) - errtrunc(); - --FileSize; - if ( qfread(myFile, &data, 1) != 1 ) - readerr(); - return data; -} - -//----------------------------------------------------------------------- -void java_t::readData(void *data, uint32 size) -{ - if ( FileSize < size ) - errtrunc(); - FileSize -= size; - if ( qfread(myFile, data, size) != size ) - readerr(); -} - -//----------------------------------------------------------------------- -void java_t::skipData(uint32 size) -{ - if ( FileSize < size ) - errtrunc(); - FileSize -= size; - qfseek(myFile, size, SEEK_CUR); -} - -//----------------------------------------------------------------------- -uchar java_t::set_parent_object(void) -{ - if ( curClass.super.Name ) - { - static const char object[] = "java.lang.Object"; - if ( fmtName(curClass.super.Name, tmpbuf, sizeof(tmpbuf), fmt_fullname) - && memcmp(tmpbuf, object, sizeof(object)) == 0 ) - { - curClass.extflg |= XFL_C_SUPEROBJ; - return 1; - } - } - return 0; -} - -//----------------------------------------------------------------------- -const uchar *java_t::get_annotation(uval_t node, uint *plen) -{ - netnode temp(node); - size_t len = (size_t)temp.altval(0); - if ( len && len <= curClass.maxAnnSz ) - { - *plen = (uint)len; - ++len; - if ( temp.getblob(annBuf, &len, 0, BLOB_TAG) && len == *plen ) - return annBuf; - } - return NULL; -} - -//----------------------------------------------------------------------- -bool java_t::sm_getinfo(const insn_t &insn, SMinfo *pinf) -{ // call ONLY when curSeg.smNode != 0 - sm_info_t smr; - ea_t ea; - - switch ( sm_node ) - { - case smn_aa_not_finished: - goto noinfo; - - case smn_ok: - sm_node = smn_no_use; - SMnode = curSeg.smNode; - { - size_t cnt = (size_t)SMnode.altval(-1); - if ( cnt < 2 || cnt > curClass.maxSMsize ) - goto destroyed; - SMsize = (uint32)cnt; - ++cnt; - if ( !SMnode.getblob(smBuf, &cnt, 0, BLOB_TAG) || cnt != SMsize ) - goto destroyed; - } - default: - break; - } - - ea = pinf->ea; - if ( ea == BADADDR ) - ea = insn.ea - 1; - ea = SMnode.supnext(ea); - if ( ea == BADNODE ) - goto noinfo; - if ( get_item_head(ea) != insn.ea ) - goto noinfo; - if ( SMnode.supval(ea, &smr, sizeof(smr)) != sizeof(smr) ) - goto destroyed; - if ( smr.noff >= 2 && smr.eoff > smr.noff && smr.eoff <= SMsize ) - { - pinf->ea = ea; - pinf->pb = smBuf + smr.noff; - pinf->pe = smBuf + smr.eoff; - pinf->fcnt = smr.fcnt; - return true; - } - -destroyed: - DESTROYED("sm_getinfo"); - -noinfo: - return false; -} - -//----------------------------------------------------------------------- -static const char special_sym[] = -{ - j_field_dlm, // classname (dot) ==> special point - j_clspath_dlm, // classname path (slash) - j_parm_list_start, j_parm_list_end, // function (for methods) - 0 -}; - -//------------------------------------------------------------------------- -void op_NameChars(namechar_op_t op) -{ - switch ( op ) - { - case ncop_disable: - for ( size_t i = 0; i < qnumber(special_sym); ++i ) - set_cp_validity(UCDR_NAME, special_sym[i], BADCP, false); - break; - case ncop_enable: - for ( size_t i = 0; i < qnumber(special_sym); ++i ) - set_cp_validity(UCDR_NAME, special_sym[i]); - break; - case ncop_enable_without_parens: - for ( size_t i = 0; i < 2; ++i ) - set_cp_validity(UCDR_NAME, special_sym[i]); - break; - default: INTERR(10267); - } -} - -//----------------------------------------------------------------------- -void make_NameChars(bool on_load) -{ - static const char special_char[] = - { - '$', '_', // MUST present (historical/special) - j_sign, j_endsign, // special case for <init>, <clinit> :( - }; - - set_cp_validity(UCDR_NAME, 0, NCPS, false); - // in names accepted ONLY english chars (temporary?) - set_cp_validity(UCDR_NAME, 'A', 'Z'+1); - set_cp_validity(UCDR_NAME, 'a', 'z'+1); - set_cp_validity(UCDR_NAME, '0', '9'+1); - for ( size_t i = 0; i < qnumber(special_char); ++i ) - set_cp_validity(UCDR_NAME, special_char[i]); - // fill national character's - set_cp_validity(UCDR_NAME, '\\'); // is valid for unicode escape sequnce only (special work) - // class/method path/call chars - op_NameChars(on_load ? ncop_enable : ncop_enable_without_parens); // for oldbase convertation -} - -//---------------------------------------------------------------------- -segment_t *java_t::getMySeg(ea_t ea, segment_t *seg) -{ - segment_t *s = seg != NULL ? seg : getseg(ea); - - if ( s == NULL ) - goto compat_err; - - if ( curSeg.start_ea != s->start_ea ) - { - if ( sm_node > smn_ok ) - sm_node = smn_ok; - if ( !s->orgbase ) - { - if ( s->type != SEG_IMP && s->type != SEG_XTRN ) - goto compat_err; - curSeg.start_ea = s->start_ea; - } - else - { - if ( ClassNode.supval(s->orgbase, &curSeg, sizeof(curSeg) ) != sizeof(curSeg) ) - DESTROYED("getMySeg"); - if ( -s->orgbase != curSeg.id.Number - || s->start_ea != (s->type == SEG_BSS ? curSeg.DataBase : curSeg.start_ea) ) - { -compat_err: - UNCOMPAT("getMySeg"); - } - } - } - return s; -} - -//----------------------------------------------------------------------- -// visible for converter only -GCC_DIAG_OFF(format-nonliteral); -void out_java_t::trunc_name(uint num, uchar type) -{ - static const char fnam[] = "...(Field_%u)"; - static const char metnam[] = "...(Method_%u)"; - static const char locnam[] = "...(locvar_%u)"; - static const char xtrn[] = "...(extern_%u)"; - static const char clsnam[] = "..."; - static const char *const add_nam[5] = { xtrn, fnam, metnam, locnam, clsnam }; - - enableExt_NameChar(); - size_t s = (sizeof(metnam) - 2 + 5 + 1); - size_t inplen = outbuf.length(); - outbuf.resize(inplen - s); - outbuf.cat_sprnt(add_nam[type], num); -} -GCC_DIAG_ON(format-nonliteral); - -//----------------------------------------------------------------------- -int java_t::CmpString(ushort index1, ushort index2) -{ - DEB_ASSERT((!index1 || !index2), "cs-ind"); - if ( index1 != index2 ) - { - size_t i; - uval_t ind1 = (uint32)index1 << 16; - uval_t ind2 = (uint32)index2 << 16; - - uval_t sz = ConstantNode.altval(ind1); - if ( sz == 0 || (i=(size_t)ConstantNode.altval(ind2)) == 0 ) - { -BADIDB: - DESTROYED("CmpString"); - } - - if ( sz != i ) - { -diff: - return 1; - } - - i = (ushort)i; - if ( i == 0 ) - return -1; - - sz = i; - i *= sizeof(ushort); - uchar *p1 = (uchar *)tsPtr, *p2 = p1 + i; - if ( !getblob(ind1, p1, sz) || !getblob(ind2, p2, sz) ) - goto BADIDB; - if ( memcmp(p1, p2, i) != 0 ) - goto diff; - } - return 0; -} - -//----------------------------------------------------------------------- -int java_t::cmpDscrString(ushort index1, uchar met, ushort index2, uchar self) -{ - uval_t siz1, siz2; - ushort *p1, *p2; - - uval_t ind1 = (uint32)index1 << 16; - uval_t ind2 = (uint32)index2 << 16; - uval_t i1 = ConstantNode.altval(ind1); - uval_t i2 = ConstantNode.altval(ind2); - if ( i1 == 0 - || i2 == 0 - || (siz1 = (ushort)i1) == 0 - || (siz2 = (ushort)i2) == 0 - || !getblob(ind1, p1 = tsPtr, siz1) - || !getblob(ind2, p2 = p1 + (size_t)siz1, siz2) ) - { - goto int_err; - } - - if ( met ) - { -#define _MCR ((_OP_ONECLS | _OP_VALPOS) << 16) - if ( (i1 & _MCR) != _MCR ) - goto diff; -#undef _MCR - i1 = ConstantNode.altval(ind1+1); - if ( !i1 || (int32)(siz1 -= i1) <= 0 ) - goto int_err; // never signature - p1 += (size_t)i1; - } - - if ( self && !(i1 & (_OP_NODSCR << 16)) ) - { - while ( *p1 == j_array ) - { - if ( !--siz1 ) - goto int_err; - ++p1; - } - } - - if ( (i1 ^ i2) & (_OP_NODSCR << 16) ) - { - if ( i2 & (_OP_NODSCR << 16) ) - { - if ( *p1 == j_class && p1[(size_t)siz1-1] == j_endclass ) - { - ++p1; - if ( (int)(siz1 -= 2) <= 0 ) - goto int_err; - } - } - else - { - if ( *p2 == j_class && p2[(size_t)siz2-1] == j_endclass ) - { - ++p2; - if ( (int)(siz2 -= 2) <= 0 ) - goto int_err; - } - } - } - - if ( siz1 != siz2 || memcmp(p1, p2, (size_t)siz1 * sizeof(ushort)) != 0 ) - goto diff; - return 0; -int_err: - INTERNAL("cmpDscrString"); -diff: - return 1; -} - -//----------------------------------------------------------------------- -ushort java_t::xtrnDscrSearch(ushort name, uchar met) -{ - const_desc_t cr; - - if ( curClass.This.Dscr - && !cmpDscrString(name, met, curClass.This.Name, 1) ) - { - return 0xFFFF; - } - - for ( ushort j = curClass.xtrnLQE; j; j = (ushort)(XtrnNode.altval(j) >> 16) ) - { - if ( ConstantNode.supval(j, &cr, sizeof(cr)) != sizeof(cr) - || cr.type != CONSTANT_Class - || (j = cr.ref_ip) == 0 ) - { - INTERNAL("xtrnDscrSearch"); - } - if ( !cmpDscrString(name, met, cr._name, 0) ) - return j; - } - return 0; -} - -//----------------------------------------------------------------------- -void java_t::mark_strange_name(ea_t ea) const -{ - mark_and_comment(ea, "Strange name"); -} - -//----------------------------------------------------------------------- -void java_t::xtrnSet( - uint cin, - const_desc_t *co, - uint xip, - char *str, - size_t strsize, - bool full, - uchar rmod) -{ - ea_t ea = curClass.xtrnEA + xip; - - if ( !(rmod & 4) ) - { - co->ref_ip = (ushort)xip; - StoreOpis(cin, *co); - uval_t rfa = cin; - if ( full ) - { - rfa |= ((uval_t)curClass.xtrnLQE << 16); - curClass.xtrnLQE = (ushort)cin; - } - XtrnNode.altset(xip, rfa); - create_byte(ea, 1); - } - - uint js = MAXNAMELEN - 1; - out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); - name_chk = 0; - if ( full ) // fmt_fullname - { - uni_chk = 0; - if ( pctx->fmtString(*this, co->_name, js, fmt_fullname) ) - { - endcls = MAXNAMELEN; -trnc: - pctx->trunc_name(xip); - pctx->outbuf.resize(MAXNAMELEN-1); - } - else - { - endcls = (uint)strlen(pctx->outbuf.c_str()); - } - clunic = uni_chk; - } - else - { - uni_chk = clunic; - if ( endcls >= MAXNAMELEN - 2 ) - { - pctx->outbuf.resize(MAXNAMELEN-1); - name_chk = 0; // no mark here - goto trnc; - } - pctx->outbuf.resize(pctx->outbuf.length() + (endcls + 1)); - pctx->outbuf[endcls] = '.'; - js -= (endcls + 1); - if ( pctx->fmtString(*this, co->_subnam, js, fmt_UnqualifiedName) ) - goto trnc; - } - qstrncpy(str, pctx->outbuf.c_str(), strsize); - delete pctx; - if ( rmod & 1 ) - { - // enableExt_NameChar(); - force_name(ea, convert_clsname(str)); - hide_name(ea); - // disableExt_NameChar(); - } - if ( (char)uni_chk > 0 && (rmod & 2) ) - ConstantNode.charset(ea, uni_chk, UR_TAG); - uni_chk = (uchar)-1; - if ( name_chk && !(rmod & 4) ) - mark_strange_name(ea); -} - -//----------------------------------------------------------------------- -void java_t::SetName(ushort name, ea_t ea, ushort access_mode, uval_t number, uchar rmod) -{ - uni_chk = name_chk = 0; - fmt_t fmt = number || curSeg.id.Number ? fmt_UnqualifiedName : fmt_fullname; - out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); - if ( pctx->fmtString(*this, name, sizeof(tmpbuf) - 1, fmt) ) - { - if ( !number ) - pctx->trunc_name(curSeg.id.Number, uchar(3 + !curSeg.id.Number)); - else if ( number <= (uval_t)curClass.FieldCnt ) - pctx->trunc_name((uint)number, 1); - else - pctx->trunc_name((uint)number - curClass.FieldCnt, 2); - } - qstrncpy(tmpbuf, pctx->outbuf.c_str(), sizeof(tmpbuf)); - delete pctx; - convert_clsname(tmpbuf); - - if ( rmod & 1 ) - { - switch ( access_mode & ACC_ACCESS_MASK ) - { - case ACC_PUBLIC: - if ( rmod & 4 ) - del_global_name(ea); - add_entry(number, ea, tmpbuf, 0); - break; - case 0: - if ( rmod & 4 ) - del_global_name(ea); - add_entry(ea, ea, tmpbuf, 0); - break; - default: - force_name(ea, tmpbuf); - break; - } - } - // disableExt_NameChar(); - if ( (char)uni_chk > 0 && (rmod & 2) ) - ConstantNode.charset(ea, uni_chk, UR_TAG); - uni_chk = (uchar)-1; - if ( name_chk && !(rmod & 4) ) - mark_strange_name(ea); -} - -//----------------------------------------------------------------------- -// as procedure for rename_unichars -void java_t::set_lv_name(ushort name, ea_t ea, uchar rmod) -{ - uni_chk = name_chk = 0; - if ( fmtName(name, tmpbuf, sizeof(tmpbuf), fmt_UnqualifiedName) ) - { - if ( rmod & 1 ) - force_name(ea, tmpbuf); - hide_name(ea); - if ( (char)uni_chk > 0 && (rmod & 2) ) - ConstantNode.charset(ea, uni_chk, UR_TAG); - if ( name_chk && !(rmod & 4) ) - mark_strange_name(ea); - } - uni_chk = (uchar)-1; -} - -//-------------------------------------------------------------------------- -void java_t::rename_uninames(int32 mode) -{ - nodeidx_t id = ConstantNode.charfirst(UR_TAG); - if ( id != BADNODE ) - { - char str[MAXNAMELEN]; // for imports - - show_wait_box("HIDECANCEL\nRenaming labels with national characters"); - - ushort lcls = 0; // for imports - uchar rmod = 7; // rename+save (+renamemode) - switch ( mode ) - { - case 0: // change table but renaming not needed (recreate records only) - rmod = 2; // save only - break; - case -1: // change processor flag only - rmod = 5; // rename only - //PASS THRU - default: // change table and renaming needed - break; - } - do - { - adiff_t dif; - ea_t ea = id; - uchar type = ConstantNode.charval(ea, UR_TAG); - show_addr(ea); - if ( !type || type > 3 ) - goto BADIDB; - if ( !(type & 2) && mode == -1 ) - continue; - switch ( getMySeg(ea)->type ) - { - default: -BADIDB: - DESTROYED("rename_uninames"); - - case SEG_BSS: - if ( !curSeg.varNode - || (dif = ea - curSeg.DataBase) < 0 - || dif >= curSeg.DataSize - || is_align(get_flags(ea)) ) - { - goto BADIDB; - } - { - netnode tmp(curSeg.varNode); - LocVar lv; - if ( tmp.supval((nodeidx_t)dif, &lv, sizeof(lv)) != sizeof(lv) ) - goto BADIDB; - set_lv_name(lv.var.Name, ea, rmod); - } - break; - - case SEG_CODE: - if ( ea != curSeg.start_ea ) - goto BADIDB; - SetName(curSeg.id.name, ea, curSeg.id.access, - curClass.FieldCnt + curSeg.id.Number, rmod); - break; - - case SEG_IMP: // class/fields - dif = ea - curClass.start_ea; - if ( dif < 0 ) - goto BADIDB; - if ( !dif ) // class - { - ushort sv = curSeg.id.Number; - curSeg.id.Number = 0; - SetName(curClass.This.Name, ea, curClass.AccessFlag, 0, rmod); - curSeg.id.Number = sv; - break; - } - if ( dif > curClass.FieldCnt ) - goto BADIDB; - if ( ClassNode.supval((nodeidx_t)dif, &curField, sizeof(curField) ) != sizeof(curField) ) - goto BADIDB; - SetName(curField.id.name, ea, curField.id.access, (int)dif, rmod); - break; - - case SEG_XTRN: - dif = ea - curClass.xtrnEA; - if ( dif <= 0 || dif > curClass.xtrnCnt ) - goto BADIDB; - { - uchar cmod = rmod; - const_desc_t co; - { - uint j = (uint)XtrnNode.altval((nodeidx_t)dif); - if ( j == 0 ) - goto BADIDB; - if ( !LoadOpis(lm_normal, (ushort)j, 0, &co) ) - goto BADIDB; - } - switch ( co.type ) - { - default: - goto BADIDB; - - case CONSTANT_Fieldref: - case CONSTANT_InterfaceMethodref: - case CONSTANT_Methodref: - if ( co._name != lcls ) - { - cmod = 4; // set internal static variables only -LCLASS: - lcls = co._name; - xtrnSet(-1, &co, (uint)dif, str, sizeof(str), true, cmod); - if ( co.type == CONSTANT_Class ) - break; - } - xtrnSet(-1, &co, (uint)dif, str, sizeof(str), false, rmod); - break; - case CONSTANT_Class: - goto LCLASS; - } - } - break; - } - } - while ( (id = ConstantNode.charnext(id, UR_TAG)) != BADNODE ); - hide_wait_box(); - } -} - -//----------------------------------------------------------------------- -void java_t::xtrnRef(ea_t ea, const const_desc_t &opis) const -{ - if ( (loadMode & MLD_EXTREF) && opis.ref_ip ) - { - ea_t target = opis.ref_ip == 0xFFFF - ? curClass.start_ea - : curClass.xtrnEA + opis.ref_ip; - add_dref(ea, target, dr_I); - } -} - -//----------------------------------------------------------------------- -void java_t::xtrnRef_dscr(ea_t ea, const_desc_t *opis, uchar met) -{ - if ( !met ) - { - if ( !(loadMode & MLD_VARREF) ) - return; - if ( (opis->flag & (HAS_CLSNAME | HAS_TYPEDSCR)) == HAS_CLSNAME ) - return; - } - else if ( !(loadMode & MLD_METHREF) ) - { - return; - } - - const_desc_t cr(*opis); - opis = &cr; - opis->ref_ip = xtrnDscrSearch(opis->_name, met); - xtrnRef(ea, *opis); -} - -//----------------------------------------------------------------------- -void java_t::deltry(uint bg, uint ic, uint ui, const const_desc_t &pco) -{ - for ( uint i = bg; (ushort)i <= curClass.xtrnCnt; i++ ) - { - uint j = (uint)XtrnNode.altval(i, '0'); - if ( j == 0 ) - continue; - const_desc_t co; - ConstantNode.supval(j, &co, sizeof(co)); - if ( co.type != pco.type - || co.flag != pco.flag - || co.ref_ip != (ushort)ic - || CmpString(co._subnam, pco._subnam) - || CmpString(co._dscr, pco._dscr) ) - { - continue; - } - co.ref_ip = (ushort)ui; - StoreOpis(j, co); - XtrnNode.altdel(i, '0'); - } -} - -//----------------------------------------------------------------------- -GCC_DIAG_OFF(format-nonliteral); -segment_t *java_t::_add_seg(int caller) -{ - static const char *const _cls[4] = { "xtrn", "met_", "_var", "head" }; - static const char *const fm[4] = { "import", "met%03u", "var%03u", "_Class" }; - - uval_t size; - uchar type; - - switch ( caller ) - { - default: - INTERNAL("_add_seg"); - - case 1: // method - curSeg.start_ea = start_ea; - // fallthrough - case -1: // code - start_ea = curSeg.start_ea; - type = SEG_CODE; - size = curSeg.CodeSize; - break; - - case 2: // data - curSeg.DataBase = start_ea; - size = curSeg.DataSize; - type = SEG_BSS; - break; - - case 3: // class - curClass.start_ea = start_ea; - size = curClass.FieldCnt + 1; - type = SEG_IMP; - break; - - case 0: // header - curClass.xtrnEA = start_ea = to_ea(inf_get_baseaddr(), 0); - if ( !curClass.xtrnCnt ) - return NULL; - size = curClass.xtrnCnt; - type = SEG_XTRN; - break; - } - ea_t top = start_ea + size; - ea_t end = (top + (0xF + 1)) & ~0xF; - if ( top < start_ea ) - loader_failure("Our of addressing space"); - - segment_t *S; - if ( caller < 0 ) - { - S = getseg(start_ea); - if ( S == NULL || !set_segm_end(curSeg.start_ea, end, SEGMOD_KILL) ) - qexit(1); - qoff64_t pos = qftell(myFile); - linput_t *li = make_linput(myFile); - file2base(li, pos, start_ea, top, FILEREG_PATCHABLE); - unmake_linput(li); - qfseek(myFile, pos + curSeg.CodeSize, SEEK_SET); - } - else - { - sel_t sel; - if ( start_ea > 0x100000 ) - { - sel = cursel++; - set_selector(sel, start_ea>>4); - } - else - { - sel = (ushort)(start_ea >> 4); - } - if ( !add_segm(sel, start_ea, end, NULL, _cls[caller]) ) - qexit(1); - S = getseg(start_ea); - S->orgbase = -(uval_t)curSeg.id.Number; - S->type = type; - if ( caller != 1 ) - S->set_hidden_segtype(true); // no out comment of segment type - char sname[32]; - qsnprintf(sname, sizeof(sname), fm[caller], curSeg.id.Number); - set_segm_name(S, sname); - if ( caller <= 1 ) - goto end_create; // method/header - for ( uval_t i = 0; start_ea < top; start_ea++, i++ ) // data & class - { - create_byte(start_ea, 1); - if ( caller == 2 ) // data - { - char str[MAXNAMELEN]; - qsnprintf(str, sizeof(str), "met%03u_slot%03" FMT_EA "u", curSeg.id.Number, i); - if ( force_name(start_ea, str) ) - make_name_auto(start_ea); - else - hide_name(start_ea); - } - } - } - - create_byte(top, end - top); // !header && !method -end_create: - start_ea = end; - return S; -} -GCC_DIAG_ON(format-nonliteral); - -//----------------------------------------------------------------------- -void java_t::resizeLocVars(void) const -{ - netnode temp(curSeg.varNode); - int slot = curSeg.DataSize; - - for ( int32 cur, prev = 1; --slot >= 0; prev = cur ) - { - cur = (int32)temp.altval(slot); - if ( cur < 0 && !prev ) - { - del_items(curSeg.DataBase + slot+1, DELIT_SIMPLE); - create_word(curSeg.DataBase + slot, 2); - } - } -} - -//----------------------------------------------------------------------- -const char *java_t::CopyAttrToFile(const char *astr, uint32 size, ushort id) -{ - if ( FileSize < size ) - errtrunc(); // here for alloc diagnostic - - char fname[QMAXPATH]; - qstrncpy(fname, get_path(PATH_TYPE_CMD), sizeof(fname)); - char *ptr = (char *)get_file_ext(fname); - if ( ptr == NULL ) - { - ptr = &fname[strlen(fname)]; - *ptr++ = '.'; - } - - uint32 sz = uint32(ptr - fname); - - uval_t *pnode = NULL; - if ( astr[0] == ' ' ) // SourceDebugExtension - { - if ( sz > sizeof(fname)-sizeof("SDE.utf8") ) - { -too_long: - return "PathName too long"; - } - memcpy(ptr, "SDE.utf8", sizeof("SDE.utf8")); - } - else - { - if ( sz > (sizeof(fname)-30) ) - goto too_long; - - switch ( (uchar)astr[0] ) - { - default: // ARQ_FILE: - pnode = &curClass.genNode; - break; - case attr_parent_kind_field: - ptr += qsnprintf(ptr, 30, "fld%03u_", curField.id.Number); - pnode = &curField.genNode; - break; - case attr_parent_kind_code: - case attr_parent_kind_method: - pnode = &curSeg.genNodes[astr[0] == attr_parent_kind_code]; - ptr += qsnprintf(ptr, 30, "%smet%03u.", - astr[0] == attr_parent_kind_code ? "code_" : "", - curSeg.id.Number); - break; - } - - uchar err = 0; - for ( sz = 1; ptr < &fname[sizeof(fname) - sizeof(".attr")]; sz++ ) //lint !e440 - { - uchar c = astr[sz]; - switch ( c ) - { - case 0: - goto full_copy; - default: - if ( c > CHP_MIN && c < CHP_MAX ) - { - *ptr++ = c; - break; - } - //PASS THRU - case '/': - case '\\': - case '>': - case '<': - case '?': - case '*': - case '=': - err = 1; - break; - } - } - ptr[-1] = '!'; // as marker of truncated name -full_copy: - memcpy(ptr, ".attr", sizeof(".attr")); - if ( err ) - msg("Convert unprintable filename for attribute '%s'\n", &astr[1]); - } - ptr = fname; - while ( (ptr=strchr(ptr, '\\')) != NULL ) - *ptr = '/'; - - ptr = (char *)myAlloc(size + 1); // +1 for zero_size extension! - readData(ptr, size); - - FILE *f = qfopen(fname, "wb"); - if ( f == NULL ) - { - qfree(ptr); - return "Can't create file for storing"; - } - - uchar err = 0; - if ( qfwrite(f, ptr, size) != size ) - ++err; - qfree(ptr); - if ( qfclose(f) && !err ) - { - qunlink(fname); - return "Error writing"; - } - if ( pnode ) - { - netnode temp; - uint32 pos = 0; - if ( *pnode ) - { - temp = *pnode; - } - else - { - temp.create(); - *pnode = temp; - pos = (uint32)temp.altval(0); - } - ++pos; - temp.altset(pos, id); - temp.supset(pos, fname, strlen(fname)); - temp.altset(0, pos); - } - return NULL; -} - -//----------------------------------------------------------------------- -bool java_t::fmtName(ushort index, char *buf, size_t bufsize, fmt_t fmt) -{ - out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); - int i = pctx->fmtString(*this, index, bufsize-1, fmt); - qstrncpy(buf, pctx->outbuf.c_str(), bufsize); - delete pctx; - return !i && buf[0]; -} - -//-------------------------------------------------------------------------- -// Procedures for "press Enter on any name" -int java_t::is_locvar_name(const insn_t &insn, const char *name) -{ - LocVar lv; - uint32 idx = (uint32)insn.Op1.addr; - - if ( insn.Op1.type == o_mem ) - { - if ( insn.Op1.ref ) - goto bad; - } - else if ( insn.Op1.type == o_void ) - { - if ( (char)insn.Op1.ref < 0 || (int32)(idx -= (uint32)curSeg.DataBase) < 0 ) - goto bad; - } - - if ( netnode(curSeg.varNode).supval(idx, &lv, sizeof(lv)) == sizeof(lv) - && fmtName(lv.var.Name, tmpbuf, sizeof(tmpbuf), fmt_UnqualifiedName) - && streq(name, tmpbuf) ) - { - return idx; - } -bad: - return -1; -} - -//------------------------------------------------------------------------- -static bool is_get_ref_addr_visible_cp(wchar32_t cp) -{ - return cp == j_field_dlm || cp == j_clspath_dlm || is_visible_cp(cp); -} - -//-------------------------------------------------------------------------- -ea_t java_t::get_ref_addr(ea_t ea, const char *name, size_t pos) -{ - if ( strlen(name) <= pos || getseg(ea) == NULL ) - { -NOT_FOUND: - return BADADDR; - } - - uchar clv = getMySeg(ea)->type; - switch ( clv ) // also set curSeg - { - case SEG_XTRN: - if ( !jasmin() ) - goto NOT_FOUND; // short form. Can't search by text - // no break - default: - break; - case SEG_CODE: - if ( strstrpos(name, ash.cmnt) <= pos ) - clv |= 0x80; // flag for 'modified autocomment' (see make_locvar_cmt) - break; - } - - ssize_t r = pos; - if ( !is_get_ref_addr_visible_cp(uchar(name[r])) ) - goto NOT_FOUND; - - while ( r > 0 && is_get_ref_addr_visible_cp(uchar(name[r-1])) ) - --r; - ssize_t start = r; - for ( r = pos+1; name[r]; r++ ) - if ( !is_get_ref_addr_visible_cp(uchar(name[r])) ) - break; - if ( name[r] == '\\' && !name[r+1] ) - goto NOT_FOUND; //\\+++ not work with prompt? - char buf[MAXSTR*2]; - memcpy(buf, &name[start], r); - buf[r] = '\0'; - switch ( clv & ~0x80 ) - { - case SEG_CODE: - case SEG_BSS: - r = check_special_label(buf, r); - if ( r >= 0 ) - return curSeg.start_ea + r; - //PASS THRU - default: - break; - } - insn_t insn; - decode_insn(&insn, ea); - if ( (clv&0x80) && curSeg.varNode && (start = is_locvar_name(insn, buf)) >= 0 ) - return curSeg.DataBase + start; -// append(new) - ea_t rea = get_name_ea(BADADDR, convert_clsname(buf)); - if ( rea == BADADDR && jasmin() && (clv&~0x80) == SEG_CODE ) // fieldnames - { - char *p = strrchr(buf, j_field_dlm); - if ( p ) - { - *p++ = '\0'; - if ( get_name_ea(BADADDR, buf) == curClass.start_ea ) - rea = get_name_ea(BADADDR, p); - } - } - return rea; -} - -//----------------------------------------------------------------------- -// for IDF_SHOWBADSTR (index my be not string :) -bool java_t::is_valid_string_index(ushort index) const -{ - return index > 0 - && index <= curClass.maxCPindex - && ConstantNode.altval(((uint32)index) << 16); -} - -//----------------------------------------------------------------------- -/* signatures encoding - * - * methodOrFieldSignature ::= type - * classSignature ::= [ typeparams ] supertype { interfacetype } - * - * type ::= ... | classtype | methodtype | typevar - * classtype ::= classsig { '.' classsig } - * classig ::= 'L' name [typeargs] ';' - * methodtype ::= [ typeparams ] '(' { type } ')' type - * typevar ::= 'T' name ';' - * typeargs ::= '<' type { type } '>' - * typeparams ::= '<' typeparam { typeparam } '>' - * typeparam ::= name ':' type -*/ - -//------------------------------------------------------------------------- -int out_java_t::fmtString(java_t &pm, ushort index, ssize_t size, fmt_t mode, _PRMPT_ putproc) -{ - ushort *tp = NULL; - - if ( size < 0 ) -FMTSTR_INTERR: - INTERNAL("fmtString"); - - if ( !index ) -BADIDB: - DESTROYED("fmtString"); - - uint32 strind = ((uint32)index) << 16; - uint32 ostsz = uint32(pm.ConstantNode.altval(strind)); - if ( ostsz == 0 ) - goto BADIDB; - CASSERT(offsetof(_STROP_, size) == 0 && sizeof(((_STROP_ *)0)->size) == sizeof(ushort)); - if ( !(pm.uni_chk & 1) && (ostsz & (_OP_UNICHARS<<16)) ) - ++pm.uni_chk; // rename unicode - if ( ostsz & (_OP_BADFIRST<<16) ) - pm.name_chk = 1; - if ( mode & FMT_ENC_RESERVED ) // support jasmin reserved words - { - CASSERT((fmt_fullname+1) == fmt_UnqualifiedName && (fmt_UnqualifiedName+1 ) == fmt__ENDENUM); - mode = (fmt_t)(mode ^ FMT_ENC_RESERVED); - if ( mode < fmt_fullname ) - goto FMTSTR_INTERR; - if ( (ostsz & (_OP_JSMRES_ << 16)) && (pm.idpflags & IDM_OUTASM) ) - mode = fmt_string_single_quotes; - } - ostsz = (ushort)ostsz; - if ( ostsz != 0 && !pm.getblob(strind, tp = pm.tsPtr, ostsz) ) - goto BADIDB; - - uint32 off_ReturnType = 0; - uint32 off_ThrowsSignature_and_TypeSignature = 0; - if ( fmt_expects_call_descriptor(mode) ) // method part out - { - off_ReturnType = (uint32)pm.ConstantNode.altval(strind+1); // offset to return type - off_ThrowsSignature_and_TypeSignature = (uint32)pm.ConstantNode.altval(strind+2); // lng of <...:...> + throw off - } - - return pm.format_utf16_string(tp, ostsz, off_ReturnType, off_ThrowsSignature_and_TypeSignature, size, mode, this, putproc); -} - -//----------------------------------------------------------------------- -//----------------------------------------------------------------------- -// this function is called only from the loader -uchar java_t::LoadUtf8(ushort index, const_desc_t *co) -{ - _STROP_ _opstr; - uint32 Flags = 0; - uint32 ind = ((uint32)index) << 16; - uchar result = 0, is_sde = 0, unicode = 0; - uint size; - - if ( index == (ushort)-1 ) // SourceDebugExtension - { - CASSERT(offsetof(_STROP_, size) == 0 && sizeof(_opstr.size) == sizeof(ushort)); - *(uint32*)&_opstr = (ushort)(size_t)co; - co = NULL; - is_sde = 1; - } - else - { - _opstr.flags = _OP_UTF8_; - _opstr.size = read2(); - } - size = _opstr.size; - if ( size != 0 ) - { - ushort *po = append_tmp_buffer(size); - union - { - ushort cw; - uchar cs; - }; - uchar c; - do - { - --size; - cw = (uchar)read1(); - if ( cw == 0 || cs >= 0xf0 ) - goto errcoding; - if ( (char)cs < 0 ) - { - if ( !size ) - goto errchar; - --size; - --_opstr.size; - c = cs; - cs &= 0x1F; - cw <<= 6; - { - uchar c2 = read1(); - if ( (c2 & 0xC0) != 0x80 ) - goto errchar; - cs |= (c2 & 0x3F); - } - if ( (c & 0xE0) != 0xC0 ) - { - if ( !size - || (c & 0xF0) != 0xE0 - || ((c = read1()) & 0xC0) != 0x80 ) - { -errchar: - if ( is_sde ) - goto done; - loader_failure("Illegal byte in CONSTANT_Utf8 (%u)", index); - } - --size; - --_opstr.size; - cw <<= 6; - cs |= (c & 0x3F); - if ( cw < 0x800 ) - goto errcoding; - } - else if ( cw < 0x80 && cs ) - { -errcoding: - if ( is_sde ) - goto done; - loader_failure("Illegal symbol encoding in CONSTANT_Utf8 (%u)", index); - } - } // end encoding - *po++ = cw; - if ( !is_sde ) - { - if ( cw >= CHP_MAX ) - { - if ( !javaIdent(cw) ) - goto extchar; - unicode = 1; - } - else if ( cs <= CHP_MIN ) - { -extchar: - Flags |= _OP_EXTSYM_; - unicode = (uchar)-1; - } - } - } - while ( size ); - - if ( !is_sde - && _opstr.size == 1 - && (loadMode & MLD_STRIP) - && (cw >= 0x80 || get_base_typename(cs) == NULL) ) - { -//Symantec error (strip) #3 - char str[16]; - uchar *ps = (uchar *)str; - - _opstr.size = (ushort)qsnprintf(str, sizeof(str), "_?_%04X", cw); - po = append_tmp_buffer(_opstr.size); - do - *po++ = *ps++; - while ( *ps ); - Flags |= _OP_NODSCR | _OP_NOSIGN; - co->flag = HAS_CLSNAME | HAS_FLDNAME; - unicode = 0; // PARANOYA - } - result = !Flags; - ConstantNode.setblob(tsPtr, (uchar *)po - (uchar *)tsPtr, ind, BLOB_TAG); - } - if ( !is_sde ) - { - if ( unicode == 1 ) - Flags |= _OP_UNICHARS; - _opstr.flags |= (ushort)Flags; - co->_Sopstr = *(int32 *)&_opstr; - } - ConstantNode.altset(ind, *(uint32 *)&_opstr); -done: - return result; -} - -//----------------------------------------------------------------------- -void java_t::parse_const_desc(ushort index, const_desc_t *co) -{ -// all nexts used only here (for parsing) -#define _op_PARAM_ 0x00010000 // start paramlist '(' -#define _op_PAREND_ 0x00020000 // last char is end of paramlist ')' -#define _op_RETTYPE_ 0x00040000 // have valid position for call return type -#define _op_FRSPRM_ 0x00080000 // not first descriptor (parameter) -#define _op_CLSBEG_ 0x00100000 // begin 'L...;' detected -#define _op_TYPBEG_ 0x00200000 // begin 'T...;' (signtype) detected -#define _op_NAME_ 0x00400000 // non empty class/typeref-name -#define _op_ARRAY_ 0x00800000 // previous char is '[' -// next needed for 'complex' classnames -#define _op_ISARRAY_ 0x01000000 // have any '[' in name -#define _op_PRIMSIG_ 0x02000000 // <...:...> signature presnt -#define _op_INPRSIG_ 0x04000000 // currently parse <...:...> signature -#define _op_MUSTNAM_ 0x08000000 // part must be name (before ':') - -#define _op_isTAG_ (_op_CLSBEG_ | _op_NAME_ | _op_TYPBEG_) - - uint Flags = 0; - uint size = co->_Ssize; - uint32 off_ReturnType = 0; - uint32 off_ThrowsSignature_and_TypeSignature = 0; - ushort *po = tsPtr; // ATT: call ONLY after LoadUtf8, size!=0 - uchar sgnlev = 0, prim = 0, *pprim = NULL; - uchar cs; // for prev - - if ( *po == j_sign ) // check <...:...> signature and <init>/<clinit> - { - while ( ++off_ReturnType < size ) - { - if ( !javaIdent(po[off_ReturnType]) ) - { - if ( off_ReturnType != 1 ) - { - size -= off_ReturnType+1; // +1 => balance for while, or align for <init> - switch ( po[off_ReturnType] ) - { - case j_tag: - if ( size < 7 ) - break; // Lx;>Lx; or Lx;>( )V => only_string - Flags |= _OP_FULLNM | _OP_NOFNM | _OP_NODSCR - | _op_PRIMSIG_ | _op_INPRSIG_; - po += off_ReturnType; - off_ReturnType &= 0; - ++sgnlev; - goto accept_tag; - - case j_endsign: - if ( !size ) // <init>/<clinit> - { - Flags |= _OP_NODSCR | _OP_NOSIGN; - goto SET_FLAGS; - } - //PASS THRU - default: - break; // only_string - } // switch - } // off_ReturnType != 1 - break; - } // special_char - } - goto only_string; - } // first '<' - - if ( *po == j_parm_list_start ) // check method descriptor/signature - { -to_func: - if ( --size < 2 ) - goto only_string; // )V - ++po; - Flags |= _op_PARAM_; - } - else - { - pprim = &prim; - } - do - { - --size; - cs = 0; // as flag (for wide characters) - CASSERT(CHP_MAX < 0x100); - if ( *po < CHP_MAX ) - cs = (uchar)*po; // for 'L', 'T'... - if ( javaIdent(*po, pprim) ) // letter/digit/$_ - { - if ( pprim ) - { - if ( !prim ) - Flags |= _OP_BADFIRST; - pprim = NULL; - } - goto norm_char; - } - pprim = NULL; // for speed - if ( cs <= CHP_MIN ) - goto only_string; // also >= CHP_MAX - - if ( Flags & _op_MUSTNAM_ ) // only in <...:...> signature (formal name) - { - if ( cs != j_tag ) - goto only_string; - Flags &= ~_op_MUSTNAM_; - if ( size < 7 ) - goto only_string; // Lx;>Lx; or Lx;>()V -accept_tag: - if ( po[1] == j_tag ) - { // iface - --size; - ++po; - } - goto only_tag; - } - switch ( cs ) // validate special chars - { - case j_parm_list_end: // always can be present in in name - if ( sgnlev ) - goto only_string; - if ( (Flags & (_op_PARAM_ | _op_ARRAY_ | _op_isTAG_)) != _op_PARAM_ ) - goto only_string; - Flags ^= (_op_PARAM_ | _op_PAREND_); - continue; - - case j_array: // class name can be full qualified array :( - if ( !sgnlev && !(Flags & (_op_isTAG_ | _OP_NOSIGN)) ) - { - Flags |= _OP_FULLNM; - break; - } - //PASS THRU - default: - goto only_string; - - case j_clspath_dlm: // '/' - case j_field_dlm: // '.' - Flags |= _OP_FULLNM; - continue; - - case j_sign: - if ( size < 3 // *>; - || (Flags & (_op_NAME_ | _OP_NOSIGN)) != _op_NAME_ - || ++sgnlev >= 30 ) - { - goto only_string; - } - CASSERT((int32)(2 << 30) < 0); // "fmtString check method" - Flags |= _OP_FULLNM | _OP_NOFNM | _OP_NODSCR; - Flags &= ~_op_isTAG_; - --size; - switch ( *++po ) - { - case j_wild: - if ( *++po != j_endsign ) - goto only_string; - --size; - goto end_signW; - - case j_wild_s: - case j_wild_e: - goto only_tag; - - default: - goto skipped_only_tag; - } - - case j_endsign: - if ( !size || !sgnlev ) - goto only_string; -end_signW: - //end of <...:...> signature must resolve in endclass - if ( !--sgnlev && (Flags & _op_INPRSIG_) ) - goto only_string; - if ( *++po != j_endclass ) - goto only_string; - --size; - Flags |= _op_NAME_; // restore - //PASS THRU - case j_endclass: - if ( (Flags & (_op_NAME_ | _op_PAREND_ | _op_ARRAY_)) != _op_NAME_ ) - goto only_string; - - if ( !size && (Flags & (_op_CLSBEG_ | _OP_NOSIGN)) == _op_CLSBEG_ ) - Flags |= _OP_ONECLS; - Flags &= ~_op_isTAG_; - - if ( sgnlev == 1 && (Flags & _op_INPRSIG_) ) // parse <...:...> - { - if ( size < 4 ) - goto only_string; // >Lx; or >( )V - switch ( po[1] ) - { - default: - Flags |= _op_MUSTNAM_; // next substitution - continue; - case j_tag: - goto only_string; - case j_endsign: // end of <...:...> - break; - } - ++po; // skip ';' - --size; // balance next '>' - sgnlev = 0; - Flags &= ~_op_INPRSIG_; - if ( po[1] != j_parm_list_start ) - goto only_tag; // superclass{ifaces} - ++po; // skip '>' (go=> before do-while) - off_ThrowsSignature_and_TypeSignature = (uint32)(po - tsPtr); - goto to_func; - } // end resolve end of <...:...> - - if ( sgnlev ) - { - if ( po[1] == j_endsign ) - continue; - if ( size > 2 ) - goto only_tag; // Lx; - goto only_string; - } - Flags |= _OP_FULLNM; - // class name can be full qualified array :( - if ( (Flags&(_op_ISARRAY_|_op_PARAM_|_op_RETTYPE_)) != _op_ISARRAY_ ) - { - if ( Flags & _OP_NOSIGN ) - goto only_string; // speed only - Flags |= _OP_NOFNM; - } - if ( Flags & (_op_RETTYPE_ | _op_PRIMSIG_) ) - { - Flags &= ~_op_FRSPRM_; - if ( Flags & _op_RETTYPE_ ) - goto check_throw; - } - continue; - } // switch ( specchar ) FULLNM -norm_char: - if ( Flags & (_OP_NOSIGN | _op_MUSTNAM_ | _op_NAME_) ) - continue; - - if ( Flags & _op_isTAG_ ) - { - Flags |= _op_NAME_; - continue; - } - if ( sgnlev ) - continue; - - if ( Flags & _op_PAREND_ ) - { - off_ReturnType = (uint32)(po - tsPtr); - Flags &= ~(_op_PAREND_ | _op_FRSPRM_); - Flags |= _op_RETTYPE_; - if ( cs == j_void_ret ) - goto check_throw; - } - -//chkdscr - if ( (Flags & (_op_PARAM_ | _op_FRSPRM_)) == _op_FRSPRM_ ) - goto nodscsg; - - if ( cs == j_array ) - { - Flags |= _op_ARRAY_ | _op_ISARRAY_; - continue; - } - - Flags = (Flags & ~_op_ARRAY_) | _op_FRSPRM_; - switch ( cs ) - { - case j_class: // 'L' - Flags |= _op_CLSBEG_; - continue; - case j_typeref: // 'T' - Flags |= _op_TYPBEG_; - continue; - default: - break; - } - if ( !cs || get_base_typename(cs) == NULL ) - { -nodscsg: - if ( Flags & (_OP_FULLNM | _op_RETTYPE_) ) - goto only_string; - Flags |= _OP_NODSCR | _OP_NOSIGN; - } - else if ( Flags & _op_RETTYPE_ ) - { -check_throw: - if ( !size ) - break; - if ( size < 4 || po[1] != j_throw ) - goto only_string; // ^Lx; - Flags |= _OP_FULLNM | _OP_NOFNM | _OP_NODSCR; - ++po; // skip rettype/previous-';' - --size; - if ( off_ThrowsSignature_and_TypeSignature < 0x10000 ) - off_ThrowsSignature_and_TypeSignature |= ((uint32)(po - tsPtr) << 16); -only_tag: - --size; - ++po; -skipped_only_tag: - switch ( *po ) - { - default: - goto only_string; - case j_class: // never set CLSBEG (no ONECLS) - case j_typeref: - Flags |= _op_TYPBEG_; - break; - } - } - } - while ( ++po, size ); - - if ( (Flags & (_op_PARAM_ | _op_PAREND_ | _op_ARRAY_)) || sgnlev ) - { -only_string: - Flags |= (_OP_NODSCR | _OP_NOSIGN | _OP_NOFNM | _OP_FULLNM); - } - else - { - if ( Flags & (_op_CLSBEG_ | _op_TYPBEG_) ) - { - Flags |= _OP_NODSCR | _OP_NOSIGN; - } - else if ( !(Flags & _OP_NOSIGN) ) - { - if ( off_ReturnType ) - { - Flags |= _OP_VALPOS; - if ( off_ThrowsSignature_and_TypeSignature ) - Flags |= _OP_METSIGN; - } - else if ( off_ThrowsSignature_and_TypeSignature ) - { - Flags |= _OP_CLSSIGN; - } - } - // check for reserved words - if ( !(Flags & _OP_NOWORD) ) - ResW_validate((uint32 *)&Flags, po); - } - if ( (ushort)Flags ) - { -SET_FLAGS: // <init>/<cinit>/V nor reserved :) - uint32 ind = ((uint32)index) << 16; - co->_Sflags |= (ushort)Flags; - ConstantNode.altset(ind, co->_Sopstr); - CASSERT(_OP_VALPOS < 0x10000u); - if ( Flags & _OP_VALPOS ) - { - ConstantNode.altset(ind+1, off_ReturnType); - if ( Flags & _OP_METSIGN ) - ConstantNode.altset(ind+2, off_ThrowsSignature_and_TypeSignature); - if ( !(Flags & _OP_NODSCR) ) - co->flag |= HAS_CALLDSCR; - return; - } - } - - cs = 0; - if ( !(Flags & _OP_NODSCR) ) - cs |= HAS_TYPEDSCR; - if ( !(Flags & _OP_NOFNM) ) - cs |= HAS_CLSNAME; - if ( !(Flags & _OP_FULLNM) ) - cs |= HAS_FLDNAME; - co->flag |= cs; -} - -//-------------------------------------------------------------------------- -//--------------------------------------------------------------------------- -// generated by JDK1.5 (checked with beta of 1.6) -- previously version have -// some 'skipped' letters(?). See 'addonces\jvunigen.cpp' (and move headers) -uchar javaIdent(ushort v, uchar *isStart) -{ - static const uchar cpchtb[256] = - { - 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 3, 22, 23, 24, 25, 0, 0, 0, 26, 27, 28, - 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 31, 32, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 33, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34, - 3, 3, 3, 3, 35, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 37, 38, 3, 39, 40, 41 }; - - static const uchar idxtb[42][32] = - { - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - { 0, 0, 0, 0, 1, 0,192,215, 38, 26, 26, 49, 38, 26, 26, 86, - 0, 0, 0, 0, 2, 3,111, 3, 26, 26,110, 26, 26, 26,110, 26 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }, - { 26, 26, 26, 26, 26, 26,110, 0, 0, 0, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 28, 26, 37, 0, 40, 83, 0, 0 }, - { 192,192,192,192,192,192,192,192,192,192,192,222,192,192, 0, 3, - 83, 4, 26, 26, 65, 26, 26, 26, 26,110, 26, 26, 26, 26, 71, 55 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 155, 5, 26, 26, 26, 26, 26, 26, 26,110, 26, 26, 26, 26, 96, 37 }, - { 26, 26, 0, 0, 0, 0, 38, 26, 26, 26,110, 97, 38, 26, 26, 26, - 26, 0,217,192,193,192,192,194,195, 0, 26, 26, 26, 86, 86, 0 }, - { 0, 0,224, 0, 38, 26, 26, 86, 26,154,192,228,192,156,157, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,158,196,159,160,192,191 }, - { 0, 0,190, 26, 26, 26,192,192,192,163, 0, 0, 0, 0, 0, 0, - 26, 26, 26, 26,164,192,165, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 166, 26, 26, 26, 26, 26, 26,189,192,224,168, 26,169,192, 0, 0, - 170, 63, 6, 26, 26, 32, 7,189,196,197,237, 8,169,192, 55, 0 }, - { 170, 49, 6, 26, 26, 32, 9,171,198,197, 0, 10,216,192,172, 0, - 170, 71, 65, 26, 26, 32, 11,189,199,200,100, 0,169,192, 97, 0 }, - { 170, 63, 6, 26, 26, 32, 11,189,201,197,216, 8,173,192, 97, 0, - 188, 74, 75, 12,108, 74, 71,173,202,203,237, 0,237,192, 0, 97 }, - { 170, 76, 32, 26, 26, 32, 30,173,204,203,219, 0,173,192, 0, 0, - 175, 76, 32, 26, 26, 32, 30,189,204,203,219, 83,173,192, 0, 0 }, - { 175, 76, 32, 26, 26, 32, 26,173,205,203,237, 0,173,192, 0, 0, - 175, 26,110, 5, 26, 26, 65, 90,110,206,207,192, 0, 0,208, 0 }, - { 38, 26, 26, 26, 26, 26,187,177,178,238,192,215, 0, 0, 0, 0, - 13, 14, 98, 38, 15, 47,187,179, 79,224,192,186, 0, 0, 0, 0 }, - { 100, 0, 0,215,192,215,221,209, 26, 38, 26, 26, 26, 86,217,192, - 204, 55,192,217,192,192,192,210,211, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 65,185,202,215,192,215,164,215, 0, 0, 0, 0, - 0, 0, 0, 0, 26, 26, 26, 26, 96, 0, 26, 26, 26, 26, 26,100 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 16, 26, 26, 26, 26, - 26, 26, 26, 26, 86, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 37 }, - { 110, 26, 26, 26, 26, 26, 26, 26,110, 75,110, 75, 26, 26, 26, 26, - 110, 75, 26, 26, 26,110, 75,110, 75,110,110, 26, 26,110, 26, 26 }, - { 26,110, 75,110, 26, 26, 26, 26,110, 26, 26, 86, 0,217,215, 0, - 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 40, 0 }, - { 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 63,110, 0, - 38, 26, 26, 86, 26, 26, 26, 26, 26, 26, 26, 26, 26, 74,100, 0 }, - { 26, 76,182, 0, 26, 26,182, 0, 26, 26,183, 0, 26, 76,184, 0, - 26, 26, 26, 26, 26, 26,181,192,192,192,180,176,192,215, 0, 0 }, - { 0,212,192,215, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, - 26, 26, 26, 26, 26,174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 40,192,241,192,241,216,192, 26, 26, 26, 96, 40, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 55, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 55, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 37 }, - { 26, 26, 96, 96, 26, 26, 26, 26, 96, 96, 26, 17, 26, 26, 26, 96, - 26, 26, 26, 26, 26, 26, 76, 79, 18, 40, 41, 55, 26, 40, 18, 40 }, - { 0, 0, 0, 0, 0, 0, 0,109,100, 0, 1, 0, 0, 0, 97,109, - 0, 0, 0, 0, 26, 26, 37, 0, 0, 0,192,210,213,214, 0, 0 }, - { 78, 5, 90, 19, 20, 21, 65, 22, 33, 37, 0, 0, 26, 26, 26, 26, - 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 33, 0, 0, 0, 38,167, 19, 40, 38, 26, 26, 26, 26, 26, 26, 26, - 26, 26,110,162, 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }, - { 33, 26, 26, 26, 26, 40, 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26,110, 0, 0, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 26, 26 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 26, 26, 26, 26, 26, 96, 26, 26, 26, 26, 26, 26, 26, 86, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 110, 0, 23,161, 26, 32,110, 79, 24, 26, 26, 26, 26, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 37, 0, 0, 0, 23, 26, 26, 26, 26, 26 }, - { 26, 26, 26, 26, 26, 26, 26, 96, 0, 0, 26, 26, 26, 26, 26, 26, - 26, 26, 5, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 26, 40 }, - { 192,192, 0, 0,241, 0,108, 0, 0, 33, 0, 0, 0, 97, 76, 26, - 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 40 }, - { 1, 0,192,215, 38, 26, 26, 49, 38, 26, 26, 86, 33, 26, 26, 26, - 26, 26, 26, 26, 26, 26, 26,110, 5, 5, 5,104, 25, 0, 0, 0 } - }; - - static const uchar bittb[124] = - { - 0x00, 0x10, 0x3C, 0x04, 0xD7, 0xFC, 0xF9, 0xC5, 0xB0, 0x6D, 0x5E, 0xED, - 0xD6, 0x96, 0x25, 0xAE, 0x83, 0xAA, 0xDC, 0x3E, 0x50, 0xBD, 0xE3, 0xF8, - 0xDB, 0x63, 0xFF, 0x7B, 0xC3, 0xFF, 0xEF, 0xFF, 0xFD, 0xE0, 0xE6, 0xE7, - 0xFF, 0x03, 0xFE, 0xFF, 0x1F, 0xCF, 0xEE, 0xD3, 0x1F, 0xC3, 0x03, 0xEC, - 0x38, 0x87, 0xFF, 0x3B, 0x8F, 0xCF, 0x1F, 0x0F, 0x0D, 0xF6, 0x33, 0xFF, - 0xEC, 0xF3, 0xFF, 0x9F, 0xFF, 0xFB, 0xBB, 0x16, 0x9F, 0x39, 0x87, 0xBF, - 0x3B, 0x8F, 0xC7, 0x3D, 0xDF, 0xCF, 0x84, 0x5F, 0x0C, 0xC2, 0x1F, 0x40, - 0x38, 0xE2, 0x07, 0x03, 0xC0, 0xFE, 0x2F, 0x60, 0xC0, 0xA0, 0xE0, 0xE0, - 0x3F, 0x02, 0xF0, 0x03, 0x01, 0x03, 0xE0, 0x03, 0x1C, 0x03, 0x01, 0xE0, - 0x18, 0x80, 0x7F, 0x20, 0x80, 0x0F, 0x03, 0x03, 0x01, 0x06, 0x30, 0x0D, - 0xE8, 0x23, 0xFD, 0x9C - }; - - uint ind = idxtb[cpchtb[v >> 8]][(((uchar)v) >> 3) & 31]; - uchar bit = uchar(1 << (v & 7)); - - if ( !(bittb[ind & 0x7F] & bit) ) - return 0; - if ( isStart ) - *isStart = (!(ind & 0x80) - || (!(ind & 0x40) && (bittb[ind - 68] & bit))); - return 1; -} - diff --git a/idasdk75/module/java/npooluti.hpp b/idasdk75/module/java/npooluti.hpp deleted file mode 100644 index 9757539..0000000 --- a/idasdk75/module/java/npooluti.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef _NPOOLUTI_HPP_ -#define _NPOOLUTI_HPP_ -#include "upgrade.hpp" - -const char *constant_type_to_str(uchar ctype); -void print_constant( - qstrvec_t *out, - const const_desc_t &cd, - ushort index, - bool strip_tags=false); - -void *myAlloc(uint size); - -NORETURN void errtrunc(void); - -//------------------------------------------------------------------------- -struct bootstrap_method_def_t -{ - ushort method_ref; - qvector<ushort> args; - - bootstrap_method_def_t() : method_ref(0) {} -}; - -nodeidx_t bootstrap_methods_get_node(bool assert=true, bool can_create=false); -nodeidx_t bootstrap_methods_get_count(); -void bootstrap_methods_set_count(nodeidx_t cnt); -bool bootstrap_methods_get_method( - bootstrap_method_def_t *out, - nodeidx_t idx); - -//----------------------------------------------------------------------------- -void make_NameChars(bool on_load); - -enum namechar_op_t -{ - ncop_disable, - ncop_enable, - ncop_enable_without_parens, -}; - -//------------------------------------------------------------------------- -void op_NameChars(namechar_op_t op); - -//------------------ -static void inline endLoad_NameChar(void) -{ - op_NameChars(ncop_enable_without_parens); // end load base (remove '()') -} - -//------------------ -static void inline enableExt_NameChar(void) -{ - op_NameChars(ncop_enable); //j_field_dlm; // (for searches) -} - -//------------------ -static void inline disableExt_NameChar(void) -{ - op_NameChars(ncop_disable); -} - -//----------------------------------------------------------------------- -struct _STROP_ -{ - ushort size; - ushort flags; -}; - -// new flags at VER15 -#define _OP_NOSIGN 0x0001 // not signature (always +_OP_NODSCR) -#define _OP_METSIGN 0x0002 // method signature: <:>(...)ret -#define _OP_CLSSIGN 0x0004 // class signature: <:>super{iface} -//#define _OP_ 0x0008 -//#define _OP_ 0x0010 -#define _OP_JSMRES_ 0x0020 // name reserved in jasmin (asm support) -// end of new flags -#define _OP_ONECLS 0x0040 // descriptor has class reference -#define _OP_FULLNM 0x0080 // field have '.', '/' or [ => no FM name -#define _OP_NOFNM 0x0100 // can only descriptor. Not name -#define _OP_VALPOS 0x0200 // has posit for call descriptor -#define _OP_NODSCR 0x0400 // not descriptor -//#define _OP_NULL_ 0x0800 // has simbols 0 -//#define _OP_NAT0_ 0x1000 // has simbols disabled in Xlat-table -//#define _OP_WIDE_ 0x2000 // has simbols >= 0x100 -#define _OP_BADFIRST 0x1000 // first char in string is badStart for ident -#define _OP_UNICHARS 0x2000 // have valid unicode characters -#define _OP_UTF8_ 0x4000 // Utf8 String -#define _OP_EXTSYM_ 0x8000 // contain (!qisprint(english) && !isJavaIdent()) -// ver12 bits -//#define _OP_UNICODE_ 0x8000 // Unicode String (removed? from standard) -//for jasmin reserved words checking -#define _OP_NOWORD uint32(0xFFFF & ~(_OP_NOSIGN|_OP_ONECLS|_OP_NODSCR|_OP_UTF8_)) - -// low bits used as temporary in VER12 - // _OP_NULL_ | _OP_NAT0_ | _OP_WIDE_ - -CASSERT((UPG12_EXTMASK >> 16) == 0x7000 - && (UPG12_CLRMASK >> 16) == 0xF03F - && (UPG12_BADMASK >> 16) == 0x8000 - && (UPG12_EXTSET >> 16) == _OP_EXTSYM_); - -//----------------------------------------------------------------------------- -#endif diff --git a/idasdk75/module/java/out.cpp b/idasdk75/module/java/out.cpp deleted file mode 100644 index c73edf3..0000000 --- a/idasdk75/module/java/out.cpp +++ /dev/null @@ -1,2160 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "java.hpp" -#include "oututil.hpp" -#include "npooluti.hpp" -//lint -esym(666,qnumber) expression with side effects - -// support for jasmin reserved word's -#define QS(f) (fmt_t)(f | FMT_ENC_RESERVED) - -DECLARE_OUT_FUNCS(out_java_t) - -//---------------------------------------------------------------------- -bool out_java_t::out_sm_end(void) -{ - return block_close(4, "stack"); -} - -//---------------------------------------------------------------------- -bool out_java_t::out_deprecated(uchar pos) -{ - return flush_buf(COLSTR(".deprecated", SCOLOR_KEYWORD), pos); -} - -//---------------------------------------------------------------------- -//lint -e719 too many arguments for format -// no idea why lint complains, everything looks corrrect -bool out_java_t::out_sm_start(int same) -{ - char samestr[80]; - - samestr[0] = 0; - if ( same >= 0 ) - { - char tmp[32]; - tmp[0] = '\0'; - if ( same ) - qsnprintf(tmp, sizeof(tmp), COLSTR(" %d", SCOLOR_NUMBER), same); - qsnprintf(samestr, sizeof(samestr), " use%s locals", tmp); - } - - if ( jasmin() ) - return gen_printf(4, COLSTR(".stack%s", SCOLOR_KEYWORD), samestr); - - return gen_printf(4, - COLSTR("%s %s StackMap%s", SCOLOR_AUTOCMT), - COLSTR("{", SCOLOR_SYMBOL), - ash.cmnt, samestr); -} - -//---------------------------------------------------------------------- -bool out_java_t::out_stackmap(const SMinfo *pinf) -{ - static char const *const verif[ITEM_BADOBJECT] = - { - "Top", "Integer", "Float", "Double", "Long", "Null", "UninitializedThis", - "Object ", "Unititialized " - }; - static char const *const kwd[3] = { "locals", "stack", NULL }; - - union - { - const uchar *p1; - const ushort *p2; - }; - - char const *const *stage; - uchar rectype; - uint vcnt; - - p1 = pinf->pb; - rectype = SMT_FULL_FRAME; - if ( pm().SMF_mode ) - rectype = *p1++; // >=JDK6 - if ( rectype >= SMT_SAME_FRM_S1 ) - ++p2; // skip offset - if ( (rectype < SMT_SAME_FRM_S1 && rectype > SMT_SAME_FRM_S1_max) ) - goto BADIDB; - if ( p1 > pinf->pe ) - goto BADIDB; - - { - int hdr = -1; - - if ( rectype != SMT_FULL_FRAME ) - { - ++hdr; // 0 -- without args - if ( rectype >= SMT_CHOP_FRM_S0_min && rectype <= SMT_CHOP_FRM_S0_max ) - { - hdr = SMT_SAME_FRM_S0 - rectype; - if ( (uint)hdr > pinf->fcnt ) - goto BADIDB; - hdr = pinf->fcnt - hdr; - if ( hdr == 0 ) - --hdr; // nocopy - } - } - if ( out_sm_start(hdr) ) - goto STOP_NOW; - } - - if ( pinf->ea != insn.ea ) - if ( gen_printf(6, COLSTR("%s %u", SCOLOR_ERROR), - COLSTR("offset", SCOLOR_KEYWORD), - (uint)(pinf->ea - pm().curSeg.start_ea)) ) - goto STOP_NOW; - - - if ( rectype <= SMT_SAME_FRM_S0_max ) - goto done_block; - stage = &kwd[1]; - vcnt = 1; - if ( rectype > SMT_SAME_FRM_S1 ) - { - if ( rectype <= SMT_SAME_FRM_S0 ) - goto done_block; - --stage; - if ( rectype != SMT_FULL_FRAME ) - { - vcnt = rectype - SMT_SAME_FRM_S0; - } - else - { -repeat_stage: - vcnt = *p2++; - if ( p1 > pinf->pe ) - goto BADIDB; - } - } - if ( vcnt != 0 ) - { - do - { - uchar tag = *p1++; - if ( p1 > pinf->pe || tag > ITEM_CURCLASS ) - goto BADIDB; - pm().curpos = 6; - out_tagon(COLOR_KEYWORD); - size_t inplen = outbuf.length(); - out_printf("%s %s", *stage, - verif[tag < ITEM_BADOBJECT ? tag : ITEM_Object]); - pm().outcnt = outbuf.length() - inplen; - out_tagoff(COLOR_KEYWORD); - CASSERT((ITEM_Object+1) == ITEM_Uninitialized - && (ITEM_Uninitialized+1) == ITEM_BADOBJECT - && (ITEM_BADOBJECT+1) == ITEM_CURCLASS); - if ( tag >= ITEM_Object ) - { - ushort var = *p2++; - if ( p1 > pinf->pe ) - goto BADIDB; - switch ( tag ) - { - case ITEM_BADOBJECT: - if ( putShort(var) ) - goto STOP_NOW; - break; - case ITEM_CURCLASS: - case ITEM_Object: - if ( OutUtf8(var, - QS(fmt_fullname), - tag == ITEM_Object ? COLOR_IMPNAME : COLOR_DNAME) ) - goto STOP_NOW; - break; - case ITEM_Uninitialized: - if ( outOffName(var) ) - goto STOP_NOW; - break; - } - } - if ( change_line() ) - goto STOP_NOW; - } - while ( --vcnt ); - } - if ( rectype == SMT_FULL_FRAME && *++stage ) - goto repeat_stage; -done_block: - if ( p1 == pinf->pe ) - return out_sm_end(); -BADIDB: - DESTROYED("out_stackmap"); -STOP_NOW: - return true; -} - -//---------------------------------------------------------------------- -uchar out_java_t::OutModes(uint32 mode) -#define OA_THIS 0 -#define OA_FIELD 1 -#define OA_METHOD 2 -#define OA_NEST 4 // in this case low BYTE == OA_NEST, hi word == access -{ - static const TXS fn[] = - { - TXS_DECLARE("public "), - TXS_DECLARE("private "), - TXS_DECLARE("protected "), - TXS_DECLARE("static "), - TXS_DECLARE("final "), - TXS_DECLARE("synchronized "), // "super " (file) - TXS_DECLARE("volatile "), // "bridge " (method) - TXS_DECLARE("transient "), // "varargs " (method) - TXS_DECLARE("native "), - TXS_EMPTY(), // "interface " // special output mode - TXS_DECLARE("abstract "), - TXS_DECLARE("fpstrict "), // float-ing-point FP-stricted - TXS_DECLARE("synthetic "), // create by compiler (not present in source) - TXS_DECLARE("annotation "), - TXS_DECLARE("enum ") // class or it superclass is enum - }; - - static const TXS ex[2] = - { - TXS_DECLARE("bridge "), - TXS_DECLARE("varargs ") - }; - - static const TXS kwd[4] = - { - TXS_DECLARE(".class "), - TXS_DECLARE(".field "), - TXS_DECLARE(".method "), - TXS_DECLARE(".interface ") - }; - - ushort access_mode; - uchar off = 2, flg; - int kwdo; - - switch ( mode ) - { - case OA_FIELD: - flg = pm().curField.id.extflg; - access_mode = pm().curField.id.access & ACC_FIELD_MASK; - break; - case OA_METHOD: - flg = pm().curSeg.id.extflg; - access_mode = pm().curSeg.id.access & ACC_METHOD_MASK; - break; - case OA_THIS: - flg = pm().curClass.extflg; - access_mode = pm().curClass.AccessFlag & ACC_THIS_MASK; - off = 0; - break; - default: // OA_NEST - flg = 0; - access_mode = (ushort)(mode >> 16); - break; - } - - kwdo = mode & 3; - if ( kwdo == 0 && (access_mode & ACC_INTERFACE) ) - kwdo += 3; - - if ( !jasmin() && (flg & XFL_DEPRECATED) ) - { - out_commented("@Deprecated", COLOR_AUTOCMT); - if ( change_line() ) - { -BADIDB: - return 1; - } - pm().curpos = off; - } - - if ( mode >= OA_NEST && !jasmin() ) - { - pm().outcnt += out_commented("{Inner}: "); - } - else - { - out_tagon(COLOR_KEYWORD); - uint rc = 0; - if ( jasmin() ) - { - if ( mode >= OA_NEST ) - { - OUT_STR(".inner "); - ++rc; - } - outLine(&kwd[kwdo].str[rc], kwd[kwdo].size-rc); - } - } - for ( uint m, v = access_mode & ((1 << qnumber(fn)) - 1), i = 0; - (m = (1<<i)) <= v; - i++ ) //lint !e440 for clause irregularity - { - if ( (v & m) == 0 ) - continue; - - const TXS *pfn = &fn[i]; - - switch ( m ) - { - case ACC_SUPER: - if ( !(mode & 3) ) - continue; // OA_THIS, OA_NEST: 'super' is deprecated; - default: - break; - case ACC_BRIDGE: - case ACC_VARARGS: - if ( (uchar)mode == OA_METHOD ) - pfn = &ex[m == ACC_VARARGS]; - break; - } - if ( !pfn->size ) - continue; // special case - if ( chkOutLine(pfn->str, pfn->size) ) - goto BADIDB; - } - switch ( mode ) - { - default: // OA_NEST, OA_THIS - if ( !jasmin() - && chkOutLine(&kwd[kwdo].str[1], kwd[kwdo].size-1) ) - { - goto BADIDB; - } - if ( (uchar)mode != OA_THIS && !jasmin() ) - break; - // no break - case OA_FIELD: - case OA_METHOD: - out_tagoff(COLOR_KEYWORD); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -uchar out_java_t::sign_out(ushort utsign, char mode) -{ - fmt_t fmt = fmt_string; - - if ( !jasmin() ) - { - out_tagon(COLOR_AUTOCMT); - pm().outcnt += out_commented("User type: "); - fmt = fmt_FieldDescriptor_nospace; // for field/locvar - if ( mode ) - { - fmt = fmt_method_FormalTypeParameters; - if ( mode > 0 ) - fmt = fmt_ClassSignature; // defer for check ONLY - } - } - else - { - static const TXS sgn = TXS_DECLARE(".signature "); - out_tagon(COLOR_KEYWORD); - if ( chkOutLine(sgn.str + !mode, sgn.size - !mode) ) - goto BADIDB; - } - if ( OutUtf8(utsign, fmt) ) - { -BADIDB: - return 1; - } - if ( fmt == fmt_method_FormalTypeParameters ) - { - if ( OutUtf8(utsign, fmt_method_ReturnType) - || chkOutSpace() - || OutUtf8(utsign, fmt_method_TypeSignature) - || OutUtf8(utsign, fmt_method_ThrowsSignature) ) - { - goto BADIDB; - } - } - out_tagoff(jasmin() ? COLOR_KEYWORD : COLOR_AUTOCMT); - if ( mode || !jasmin() ) - return change_line(); - return chkOutSpace(); -} - -//---------------------------------------------------------------------- -void out_java_t::out_switch(void) -{ - op_t x; - x.n = 0; - x.flags = OF_SHOW; - x.dtype = dt_dword; - x.type = o_imm; - - if ( !jasmin() && block_begin(4) ) - return; - - uchar nwarns = 0; - uval_t count; - ea_t addr; - for ( addr = insn.Op2.addr, count = insn.Op3.value; count; addr += 4, count-- ) - { - pm().curpos = 8; - if ( insn.itype == j_lookupswitch ) - { - x.value = get_dword(pm().curSeg.start_ea + addr); // pairs - addr += 4; - if ( !putVal(x, OOFW_IMM | OOF_NUMBER | OOF_SIGNED | OOFW_32, 0) - || chkOutSpace() - || chkOutSymSpace(':') ) - { - return; - } - if ( !checkLine(1 + 8 - ((pm().outcnt + 1) % 8)) ) - return; - int idx = pm().outcnt & 7; - if ( idx != 0 ) - { - static const char seven_spaces[] = " "; - out_line(&seven_spaces[idx-1]); - } - } - x.value = insn.ip + get_dword(pm().curSeg.start_ea + addr); - if ( x.value >= pm().curSeg.CodeSize ) - { - ++nwarns; - } - else - { - if ( outName(pm().curSeg.start_ea + addr, x.n, pm().curSeg.start_ea, x.value, &nwarns) ) - goto doneswitch; - if ( nwarns ) - return; - } - if ( !putVal(x, OOFW_IMM | OOF_NUMBER | OOFS_NOSIGN | OOFW_32, nwarns) ) - return; -doneswitch: - if ( change_line() ) - return; - } - pm().curpos = 6; - OUT_KEYWORD("default "); - if ( chkOutSymSpace(':') || !out_operand(insn.Op3) || change_line() ) - return; - if ( !jasmin() ) - block_end(4); -} - -//---------------------------------------------------------------------- -void out_java_t::out_proc_mnem(void) -{ - static const char *const addonce[] = { "", "_w", "_quick", "2_quick", "_quick_w" }; - out_mnem(2, addonce[uchar(insn.wid)]); -} - -//---------------------------------------------------------------------- -void out_java_t::out_insn(void) -{ - pm().getMySeg(insn.ea); // set curSeg (for special strings) - set_gen_xrefs(false); - - if ( pm().curSeg.smNode && !(pm().idpflags & IDF_HIDESM) ) - { - SMinfo smi; - smi.ea = BADADDR; - if ( pm().sm_getinfo(insn, &smi) ) - { - init_prompted_output(4); - do - if ( out_stackmap(&smi) ) - goto STOP_NOW; - while ( pm().sm_getinfo(insn, &smi) ); - } - } - - init_prompted_output(4); - out_mnemonic(); - pm().outcnt = tag_strlen(outbuf.c_str()); - - if ( insn.Op1.type != o_void ) - { - if ( !out_one_operand(0) ) - goto STOP_NOW; - } - else - { - if ( (char)insn.Op1.ref > 0 ) - { - qstring nbuf; - if ( get_visible_name(&nbuf, insn.Op1.addr) > 0 ) - pm().outcnt += out_commented(nbuf.begin(), COLOR_REGCMT); - } - } - - if ( insn.Op2.type != o_void ) - { - if ( chkOutSpace() ) - goto STOP_NOW; - if ( insn.itype == j_tableswitch && !jasmin() ) - { - if ( CHK_OUT_KEYWORD("to ") ) - goto STOP_NOW; - } - if ( !out_one_operand(1) ) - goto STOP_NOW; - } - - if ( insn.Op3.type != o_void && !insn.swit ) // ! lookupswitch/tablesswitch - { - if ( chkOutSpace() || !out_one_operand(2) ) - goto STOP_NOW; - } - - set_gen_xrefs(true); - set_gen_cmt(true); - if ( !change_line(true) ) - { - if ( insn.swit & 2 ) - out_switch(); // normal tableswitch/lookupswitch - } -STOP_NOW: - term_prompted_output(); -} - -//-------------------------------------------------------------------------- -bool out_java_t::close_annotation(uint32 pos) -{ - return block_close(pos, "annotation"); -} - -//-------------------------------------------------------------------------- -const ushort *out_java_t::annotation(const ushort *p, uint *plen, uint pos) -{ - if ( *plen < sizeof(ushort) ) - return NULL; - *plen -= sizeof(ushort); - uint pairs = *p++; - if ( pairs != 0 ) - { - do - { - pm().curpos = pos; - if ( *plen < sizeof(ushort) ) - return NULL; - *plen -= sizeof(ushort); - p = annotation_element(p+1, plen, pos, *p); - if ( p == NULL ) - break; - if ( change_line() ) - goto STOP_NOW; - } - while ( --pairs ); - } - return p; - -STOP_NOW: - *plen = (uint)-1; - return NULL; -} - -//-------------------------------------------------------------------------- -const ushort *out_java_t::annotation_element( - const ushort *p, - uint *plen, - uint pos, - ushort name) -{ - uchar tag = 0, type = 0; - ushort val, prev = 0; - int alev = 0; - color_t ecol = COLOR_IMPNAME; - const TXS *pt; - const_desc_t co; - - op_t x; - x.flags = 0; // output flags, will be used by out_value() - x.n = 0; // operand number, will be used by out_value() - do // array-values-loop - { -arentry: - if ( *plen < sizeof(uchar)+sizeof(ushort) ) - goto BADIDB; - *plen -= sizeof(uchar)+sizeof(ushort); - if ( alev > 0 && tag != *(uchar*)p ) - goto BADIDB; - tag = *(uchar *)p; - p = (ushort*)((uchar*)p+1); - val = *p++; - if ( tag == j_array ) - { - if ( !*plen || (alev= val) == 0 || (tag= *(uchar*)p) == j_array ) - goto BADIDB; - alev = -alev; - goto arentry; - } - - if ( alev > 0 ) // not first array element - { - switch ( tag ) - { - case j_enumconst: - case j_annotation: - if ( prev != val ) - goto BADIDB; - default: - break; - } - if ( !jasmin() ) - { - if ( chkOutSymSpace(',') ) - goto STOP_NOW; - } - else if ( tag != j_annotation ) - { - if ( chkOutSpace() ) - goto STOP_NOW; - } - else - { - if ( change_line() ) - goto STOP_NOW; - pm().curpos = pos; - } - goto do_value; - } - - switch ( tag ) - { - default: - goto BADIDB; - - case j_annotation: - case j_enumconst: - if ( val == pm().curClass.This.Dscr ) - ecol = COLOR_DNAME; - prev = val; - //PASS THRU - case j_class_ret: - case j_string: - break; - - case j_float: - type = CONSTANT_Float; - x.dtype = dt_float; - break; - case j_long: - type = CONSTANT_Long; - x.dtype = dt_qword; - break; - case j_double: - type = CONSTANT_Double; - x.dtype = dt_double; - break; - case j_bool: - case j_byte: - case j_char: - x.dtype = dt_byte; - goto do_int; - case j_short: - x.dtype = dt_word; - goto do_int; - case j_int: - x.dtype = dt_dword; -do_int: - type = CONSTANT_Integer; - break; - } - - if ( jasmin() ) - { - if ( name ) - { - if ( OutUtf8(name, fmt_UnqualifiedName, COLOR_DNAME) || chkOutSpace() ) - goto STOP_NOW; - } - out_tagon(COLOR_KEYWORD); - if ( alev ) - { - if ( !checkLine(2) ) - goto STOP_NOW; - out_char(j_array); - } - if ( chkOutChar(tag) ) - goto STOP_NOW; - out_tagoff(COLOR_KEYWORD); - switch ( tag ) - { - case j_enumconst: - case j_annotation: - if ( chkOutSpace() || OutUtf8(val, fmt_FieldDescriptor_nospace, ecol) ) - goto STOP_NOW; - default: - break; - } - } - else - { // jasmin - static const TXS doptype[] = - { - TXS_DECLARE("String"), - TXS_DECLARE("Enum"), - TXS_DECLARE("Class"), - TXS_DECLARE("Annotation") - }; - pt = doptype; - switch ( tag ) - { - case j_annotation: - ++pt; - //PASS THRU - case j_class_ret: - ++pt; - //PASS THRU - case j_enumconst: - ++pt; - //PASS THRU - case j_string: - break; - - default: - pt = get_base_typename(tag); - if ( pt == NULL ) - goto BADIDB; - break; - } - if ( chkOutKeyword(pt->str, pt->size) ) - goto STOP_NOW; - switch ( tag ) - { - case j_enumconst: - case j_annotation: - if ( chkOutSpace() || OutUtf8(val, fmt_FieldDescriptor_nospace, ecol) ) - goto STOP_NOW; - default: - break; - } - if ( alev && CHK_OUT_KEYWORD("[]") ) - goto STOP_NOW; - if ( name != 0 ) - { - if ( chkOutSpace() || OutUtf8(name, fmt_UnqualifiedName, COLOR_DNAME) ) - goto STOP_NOW; - } - } // jasmin - alev = -alev; // 0 = 0 -/* - if ( chkOutSpace(insn) ) - goto STOP_NOW; - if ( (name || jasmin()) && chkOutSymSpace(insn, '=') ) - goto STOP_NOW; -*/ - if ( chkOutSpace() || chkOutSymSpace('=') ) - goto STOP_NOW; -do_value: - switch ( tag ) - { - case j_annotation: - if ( jasmin() ) - { - if ( CHK_OUT_KEYWORD(".annotation") ) - goto STOP_NOW; - } - else - { - if ( chkOutSymbol('{') ) - goto STOP_NOW; - } - if ( change_line() ) - goto STOP_NOW; - p = annotation(p, plen, pos+2); - if ( p == NULL ) - goto done; - pm().curpos = pos; - if ( jasmin() ) - { - out_line(COLSTR(".end annotation", SCOLOR_KEYWORD)); - } - else - { - out_symbol('}'); - ++pm().outcnt; - } - continue; - - case j_class_ret: - if ( !OutUtf8(val, fmt_FieldDescriptor_nospace, // without space - val == pm().curClass.This.Dscr ? COLOR_DNAME : COLOR_IMPNAME) ) - continue; -STOP_NOW: - *plen = (uint)-1; -BADIDB: - return NULL; - - case j_enumconst: - if ( *plen < sizeof(ushort) ) - goto BADIDB; - *plen -= sizeof(ushort); - if ( OutUtf8(*p++, fmt_UnqualifiedName, ecol) ) - goto STOP_NOW; - continue; - - case j_string: - if ( OutUtf8(val, fmt_string, COLOR_STRING) ) - goto STOP_NOW; - continue; - - default: - break; - } - if ( !pm().LoadOpis(lm_normal, val, type, &co) ) - goto BADIDB; - if ( !jasmin() ) - { - switch ( tag ) - { - case j_bool: - { - static const TXS bt[2] = - { - TXS_DECLARE("true"), - TXS_DECLARE("false") - }; - pt = &bt[!co.value]; - if ( chkOutKeyword(pt->str, pt->size) ) - goto STOP_NOW; - } - continue; - - case j_char: - if ( co.value < ' ' || co.value >= 0x80 ) - break; - if ( !checkLine(3) ) - goto STOP_NOW; - out_printf(COLSTR("'%c'", SCOLOR_CHAR), char(co.value)); - pm().outcnt += 3; - continue; - - default: - break; - } - } - copy_const_to_opnd(x, co); - if ( !putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) ) - goto STOP_NOW; - } - while ( alev && --alev ); -done: - return p; -} - -//-------------------------------------------------------------------------- -uchar out_java_t::annotation_loop(const uval_t *pnodes, uint nodecnt) -{ - uchar result = 1; - uint32 pos = pm().curpos; - - if ( gen_empty_line() ) - goto STOP_NOW; - - for ( uint n = 0; n < nodecnt; n++ ) - { - if ( pnodes[n] ) - { - static char const *const jnames[5] = - { - "visible", "invisible", "default", "visibleparam", "invisibleparam" - }; - static char const *const lnames[5] = - { - "RuntimeVisible", "RuntimeInvisible", - "Default", - "RuntimeVisibleParameter", "RuntimeInvisibleParameter" - }; - char hdr[MAXSTR]; - uint hdrpos, hdrlen, len; - const ushort *p = (ushort*)pm().get_annotation(pnodes[n], &len); - if ( p == NULL ) - goto BADIDB; - - if ( jasmin() ) - { - hdrpos = qsnprintf(hdr, sizeof(hdr), - COLSTR(".annotation %s", SCOLOR_KEYWORD), - jnames[n]); - } - else - { - hdrpos = qsnprintf(hdr, sizeof(hdr), - COLSTR("%sAnnotation", SCOLOR_KEYWORD), - lnames[n]); - } - - if ( n == 2 ) // defalut - { - if ( !jasmin() ) - qstrncpy(&hdr[hdrpos], COLSTR(" {", SCOLOR_SYMBOL), sizeof(hdr)-hdrpos); - if ( flush_buf(hdr, pos) ) - goto STOP_NOW; - pm().curpos = pos + 2; - p = annotation_element(p, &len, pos+2, 0); - if ( p == NULL ) - { -checkans: - if ( len == (uint)-1 ) - goto STOP_NOW; - goto BADIDB; - } - if ( len ) - goto BADIDB; - if ( change_line() || close_annotation(pos) ) - goto STOP_NOW; - continue; - } - int nump = 0, ip = 1; - uchar present = 0; - if ( n > 2 ) // parameters - { - --len; - nump = *(uchar*)p; - if ( nump == 0 ) - goto BADIDB; - p = (ushort*)((uchar*)p+1); - if ( !jasmin() ) - hdrpos += qsnprintf(&hdr[hdrpos], sizeof(hdr)-hdrpos, - COLSTR(" for parameter", SCOLOR_KEYWORD)); - } - hdr[hdrpos++] = ' '; - hdr[hdrpos] = '\0'; - do // parameters loop - { - if ( len < sizeof(ushort) ) - goto BADIDB; - len -= sizeof(ushort); - uint cnt = *p++; - if ( !cnt ) - { - if ( !nump ) - goto BADIDB; - continue; - } - if ( nump ) - qsnprintf(&hdr[hdrpos], sizeof(hdr) - hdrpos, COLSTR("%d ", SCOLOR_NUMBER), ip); - present = 1; - hdrlen = (uint32)tag_strlen(hdr); - do // annotations loop - { - if ( len < sizeof(ushort) ) - goto BADIDB; - len -= sizeof(ushort); - pm().curpos = pos; - out_line(hdr); - pm().outcnt = hdrlen; - if ( OutUtf8(*p, jasmin() ? fmt_FieldDescriptor_nospace : fmt_FieldDescriptor) ) - goto STOP_NOW; - if ( !jasmin() ) - out_symbol('{'); - if ( change_line() ) - goto STOP_NOW; - p = annotation(p+1, &len, pos+2); - if ( p == NULL ) - goto checkans; - if ( close_annotation(pos) ) - goto STOP_NOW; - } - while ( --cnt ); - } - while ( ++ip <= nump ); - if ( nump && !present ) - goto BADIDB; - if ( len ) - goto BADIDB; - } - } // loop of annotation types - result = 0; -STOP_NOW: - return result; - -BADIDB: - DESTROYED("annotation"); -} - -//-------------------------------------------------------------------------- -void out_java_t::java_header(void) -{ - char str[MAXSTR*2]; - - if ( !jasmin() ) - flush_buf(COLSTR("/*", SCOLOR_AUTOCMT), 0); - const char *prefix = jasmin() ? ash.cmnt : ""; - -#ifdef __debug__ - gen_printf(0, COLSTR("%sDisassembler mode: %s", SCOLOR_AUTOCMT), - prefix, debugmode ? "DEBUG" : "Normal"); -#endif - gen_printf(0, - COLSTR("%sJava Virtual Machine (JDK 1.%u)", SCOLOR_AUTOCMT), - prefix, pm().curClass.JDKsubver); - { - char sv = inf_get_indent(); - inf_set_indent(0); - if ( !jasmin() ) - { - gen_printf(-1, - COLSTR("%sClassFile version: %u.%u", SCOLOR_AUTOCMT), - prefix, pm().curClass.MajVers, pm().curClass.MinVers); - } - else - { - if ( out_problems(str, prefix) ) - return; - gen_empty_line(); - gen_printf(-1, COLSTR("%s %u.%u", SCOLOR_NUMBER), - COLSTR(".bytecode", SCOLOR_KEYWORD), - pm().curClass.MajVers, pm().curClass.MinVers); - } - inf_set_indent(sv); - } - - if ( pm().curClass.SourceName ) - { - init_prompted_output(); - if ( jasmin() ) - { - OUT_KEYWORD(".source "); - out_tagon(COLOR_STRING); - } - else - { - out_tagon(COLOR_AUTOCMT); - OUT_STR("Source File : "); - } - uchar stp; - { - uint32 save = pm().idpflags; - pm().idpflags = (pm().idpflags & ~IDF_AUTOSTR) | IDF_ENCODING; // PARANOYA - stp = OutUtf8(pm().curClass.SourceName, fmt_string); - pm().idpflags = save; - } - if ( !stp ) - out_tagoff(jasmin() ? COLOR_STRING : COLOR_AUTOCMT); - if ( stp || flush_outbuf(0) ) - return; - } - else - { - gen_empty_line(); - } - - // - { - nodeidx_t bmnidx = bootstrap_methods_get_node(/*assert=*/ false, /*can_create=*/ true); - if ( bmnidx != BADNODE ) - { - const nodeidx_t bmcnt = bootstrap_methods_get_count(); - if ( bmcnt > 0 ) - { - gen_printf(0, COLSTR("%sBootstrapMethods : %u", SCOLOR_AUTOCMT), - prefix, uint(bmcnt)); - for ( nodeidx_t bmidx = 0; bmidx < bmcnt; ++bmidx ) - { - bootstrap_method_def_t bmd; - const char *bmerr = "error retrieving data"; - bool bmok = bootstrap_methods_get_method(&bmd, bmidx); - if ( bmok ) - { - bmok = bmd.method_ref != 0 && bmd.method_ref <= pm().curClass.maxCPindex; - if ( bmok ) - { - const_desc_t tmp; - bmok = pm().ConstantNode.supval(bmd.method_ref, &tmp, sizeof(tmp)) == sizeof(tmp); - if ( bmok ) - { - bmok = tmp.type == CONSTANT_MethodHandle; - if ( bmok ) - { - const_desc_t method_handle; - bmok = pm().ConstantNode.supval(bmd.method_ref, &method_handle, sizeof(method_handle)) == sizeof(method_handle); - if ( bmok ) - { - // qstring buf; - // buf.sprnt("MethodHandle{kind=%u, index=%u}", - // method_handle._mhr_kind, method_handle._mhr_index); - // flush_buf(buf.c_str()); - switch ( method_handle._mhr_kind ) - { - case JVM_REF_getField: - case JVM_REF_getStatic: - case JVM_REF_putField: - case JVM_REF_putStatic: - // points at CONSTANT_Fieldref - // (fallthrough) - case JVM_REF_invokeVirtual: - case JVM_REF_invokeStatic: - case JVM_REF_invokeSpecial: - case JVM_REF_newInvokeSpecial: - // points at CONSTANT_Methodref - { - qstrvec_t lines; - print_constant(&lines, method_handle, bmd.method_ref); - if ( lines.empty() ) - lines.push_back("<failed printing method handle>"); - for ( ssize_t lidx = 0; lidx < lines.size(); ++lidx ) - gen_printf(0, "%s", lines[lidx].c_str()); - flush_outbuf(); - for ( size_t argidx = 0, argcnt = bmd.args.size(); argidx < argcnt; ++argidx ) - { - const_desc_t arg; - const ushort argcid = bmd.args[argidx]; - if ( pm().ConstantNode.supval(argcid, &arg, sizeof(arg)) == sizeof(arg) ) - { - lines.qclear(); - print_constant(&lines, arg, argcid, /*strip_tags=*/ true); - if ( lines.empty() ) - lines.push_back("<failed printing constant>"); - for ( size_t lidx = 0; lidx < lines.size(); ++lidx ) - gen_printf(0, "Argument #%" FMT_Z ": %s", argidx, lines[lidx].c_str()); - } - else - { - gen_printf(0, COLSTR("Error retrieving argument #%" FMT_Z, SCOLOR_ERROR), argidx); - } - flush_outbuf(); - } - } - break; - case JVM_REF_invokeInterface: - // points at CONSTANT_InterfaceMethodref - bmok = false; - break; - } - } - else - { - bmerr = "Couldn't retrieve method handle"; - } - } - else - { - bmerr = "Bad constant type"; - } - } - else - { - bmerr = "Corrupted data"; - } - } - else - { - bmerr = "Bad constant pool index"; - } - } - if ( !bmok ) - gen_printf(0, COLSTR("Error retrieving bootstrap method %u (%s)", SCOLOR_ERROR), - uint(bmcnt), bmerr); - } - } - } - } - - if ( !jasmin() ) - { - if ( out_problems(str, prefix) ) - return; - close_comment(); - } - myBorder(); -} - -//-------------------------------------------------------------------------- -void idaapi java_header(outctx_t &ctx) -{ - out_java_t *pctx = (out_java_t *)&ctx; - pctx->java_header(); -} - -//-------------------------------------------------------------------------- -uchar out_java_t::enclose_out(void) -{ - if ( !jasmin() ) - { - out_tagon(COLOR_AUTOCMT); - size_t inplen = outbuf.length(); - out_printf("%sEnclosing %s: ", ash.cmnt, - pm().curClass.encMethod ? "method" : "class"); - pm().outcnt += outbuf.length() - inplen; - } - else - { - OUT_KEYWORD(".enclosing method "); - } - if ( !pm().curClass.encMethod ) - { - if ( OutUtf8(pm().curClass.encClass, QS(fmt_fullname)) ) - return 1; - } - else - { - const_desc_t op; - - if ( !pm().LoadOpis(lm_normal, pm().curClass.encMethod, CONSTANT_NameAndType, &op) ) - DESTROYED("out::enclose"); - if ( (!jasmin() && OutUtf8(op._name, fmt_method_ReturnType)) - || OutUtf8(pm().curClass.encClass, fmt_fullname) - || chkOutChar(jasmin() ? '/' : '.') - || OutUtf8(op._class, fmt_UnqualifiedName) - || OutUtf8(op._name, jasmin() ? fmt_FieldDescriptor : fmt_method_TypeSignature) ) - { - return 1; - } - } - if ( !jasmin() ) - out_tagoff(COLOR_AUTOCMT); - pm().curpos = 0; - return change_line(); -} - -//-------------------------------------------------------------------------- -// output the method return type -uchar out_java_t::out_seg_type(fmt_t fmt) -{ - return out_index(pm().curSeg.id.dscr, - fmt, - COLOR_KEYWORD, - pm().curSeg.id.extflg & EFL_TYPE); -} - -//-------------------------------------------------------------------------- -// output the field type -uchar out_java_t::out_field_type(void) -{ - return out_index(pm().curField.id.dscr, - fmt_FieldDescriptor, - COLOR_KEYWORD, - pm().curField.id.extflg & EFL_TYPE); -} - -//---------------------------------------------------------------------- -uchar out_java_t::out_includes(uval_t node, uchar pos) -{ - netnode temp(node); - uint32 len, vid, cnt = (uint32)temp.altval(0); - color_t color = jasmin() ? COLOR_KEYWORD : COLOR_AUTOCMT; - char fnm[qmin(QMAXPATH,MAXSPECSIZE)+4]; - - if ( !cnt ) - goto BADIDB; - fnm[0] = '"'; - do - { - pm().curpos = pos; - - len = (uint32)temp.supstr(cnt, &fnm[1], sizeof(fnm)-3); - if ( !len ) - goto BADIDB; - fnm[++len] = '"'; - fnm[++len] = '\0'; - char *pf = fnm; - if ( pm().idpflags & IDF_NOPATH ) - { - pf = strrchr(pf, '/'); - if ( pf != NULL ) - { - ++pf; - } - else - { -#ifndef __UNIX__ - pf = &fnm[1+1]; - if ( *pf != ':' ) - --pf; -#else - pf = &fnm[1]; -#endif - } - *--pf = '"'; - len -= uint32(pf - fnm); - } - vid = (uint32)temp.altval(cnt); - if ( vid == 0 || vid > pm().curClass.maxCPindex ) - goto BADIDB; - out_tagon(color); - if ( jasmin() ) - OUT_STR(".attribute "); - else - pm().outcnt = out_commented("GenericAttribute "); - if ( OutUtf8((ushort)vid, fmt_UnqualifiedName) - || chkOutSpace() - || chkOutLine(pf, len) ) - { - goto STOP_NOW; - } - out_tagoff(color); - if ( change_line() ) - goto STOP_NOW; - } - while ( --cnt ); - return 0; - -BADIDB: - DESTROYED("out_includes"); -STOP_NOW: - return 1; -} - -//---------------------------------------------------------------------- -void out_java_t::java_segstart(segment_t *) -{ - ea_t ea = insn_ea; - - init_prompted_output(2); - - set_gen_cmt(true); - switch ( pm().getMySeg(ea)->type ) // also set curSeg - { - case SEG_CODE: - { - func_t *pfn = get_func(ea); - if ( pfn != NULL ) - { - qstring qbuf; - if ( get_func_cmt(&qbuf, pfn, false) > 0 - || get_func_cmt(&qbuf, pfn, true) > 0 ) - { - if ( gen_block_cmt(qbuf.c_str(), COLOR_REGCMT) ) - break; - } - } - } - pm().no_prim = true; - if ( OutModes(OA_METHOD) ) - break; - if ( !(pm().curSeg.id.extflg & EFL_TYPE) - && !jasmin() - && out_seg_type(fmt_method_ReturnType) ) - { - break; - } - if ( out_index(pm().curSeg.id.name, fmt_UnqualifiedName, COLOR_CNAME, // Method Name - pm().curSeg.id.extflg & EFL_NAME) ) - break; - if ( pm().curSeg.id.extflg & EFL_TYPE ) - { - if ( chkOutSpace() ) - break; - goto do_dscid; - } - if ( jasmin() ) - { -do_dscid: - if ( out_seg_type(fmt_FieldDescriptor) ) - break; - } - else if ( OutUtf8(pm().curSeg.id.dscr, fmt_method_TypeSignature, COLOR_KEYWORD) ) - { - break; - } - if ( pm().curSeg.thrNode ) - { - const char *p = ".throws "; - if ( !jasmin() ) - { - if ( CHK_OUT_KEYWORD(" throws ") ) - break; - p = NULL; - } - if ( !out_nodelist(pm().curSeg.thrNode, 2, p) ) - break; - } - if ( change_line() ) - break; - if ( pm().curSeg.id.utsign ) - { - pm().curpos = 2; - if ( sign_out(pm().curSeg.id.utsign, -1) ) - break; - } - if ( jasmin() && (pm().curSeg.id.extflg & XFL_DEPRECATED) ) - { - if ( out_deprecated(2) ) - break; - } - if ( pm().curSeg.genNodes[0] && out_includes(pm().curSeg.genNodes[0], 2) ) - break; - - if ( pm().curSeg.stacks ) - { - int over = gen_printf(2, - jasmin() ? COLSTR(".limit stack %u", SCOLOR_ASMDIR) : - COLSTR("max_stack %u", SCOLOR_ASMDIR), - pm().curSeg.stacks); - if ( over ) - break; - } - - if ( pm().curSeg.DataSize ) - { - int over = gen_printf(2, - jasmin() ? COLSTR(".limit locals %u", SCOLOR_ASMDIR) : - COLSTR("max_locals %u", SCOLOR_ASMDIR), - pm().curSeg.DataSize); - if ( over ) - break; - } - if ( (pm().curSeg.id.extflg & XFL_M_EMPTYSM) && (out_sm_start(-1) || out_sm_end()) ) - break; - - if ( pm().curSeg.id.extflg & XFL_M_LABSTART ) - out_method_label(0); - if ( !jasmin() ) - block_begin(2); - break; - - case SEG_IMP: - pm().curpos = 0; - if ( OutModes(OA_THIS) ) - break; - if ( out_index(pm().curClass.This.Name, QS(fmt_fullname), COLOR_DNAME, - (uchar)!pm().curClass.This.Dscr) ) - break; - - if ( jasmin() ) - { - if ( !pm().curClass.super.Ref ) - goto nosuper; - if ( change_line(true) ) - break; - OUT_KEYWORD(".super "); - } - else - { - uchar sskip = 0; - if ( !pm().curClass.super.Ref ) - goto check_imps; - if ( (pm().curClass.AccessFlag & ACC_INTERFACE) - && (pm().curClass.extflg & XFL_C_SUPEROBJ) ) - { -check_imps: - if ( !pm().curClass.impNode ) - goto noparents; - sskip = 1; - } - - if ( CHK_OUT_KEYWORD(" extends ") ) - break; - if ( sskip ) - goto nosuper; - } - if ( out_alt_ind(pm().curClass.super.Ref) ) - break; -nosuper: - if ( pm().curClass.impNode ) - { - const char *p = ".implements "; - if ( !jasmin() ) - { - if ( pm().curClass.AccessFlag & ACC_INTERFACE ) - { - if ( pm().curClass.super.Ref - && !(pm().curClass.extflg&XFL_C_SUPEROBJ) - && chkOutSymSpace(',') ) - { - break; - } - } - else if ( CHK_OUT_KEYWORD(" implements ") ) - { - break; - } - p = NULL; - } - if ( !out_nodelist(pm().curClass.impNode, 0, p) ) - break; - } -noparents: - if ( change_line(!jasmin()) ) - break; - if ( pm().curClass.utsign && sign_out(pm().curClass.utsign, 1) ) - break; - if ( pm().curClass.encClass && enclose_out() ) - break; - if ( jasmin() && (pm().curClass.extflg & XFL_DEPRECATED) ) - { - if ( out_deprecated(0) ) - break; - } - if ( pm().curClass.genNode != 0 && out_includes(pm().curClass.genNode, 0) ) - break; - struct ida_local lambda_t - { - static size_t call_debLine(java_t &pm, out_java_t *oj) - { - return oj->debLine(pm); - } - }; - if ( (pm().curClass.extflg & XFL_C_DEBEXT) - && fmtString(pm(), (ushort)-1, putDeb(0), fmt_debug, lambda_t::call_debLine) >= 0 ) - { - out_tagoff(COLOR_STRING); - change_line(); - } - break; - - case SEG_XTRN: - case SEG_BSS: - if ( !jasmin() ) - flush_buf(COLSTR("/*", SCOLOR_AUTOCMT), 0); - default: - break; - } - term_prompted_output(); - pm().no_prim = false; -} - -//---------------------------------------------------------------------- -void idaapi java_segstart(outctx_t &ctx, segment_t *seg) -{ - out_java_t *pctx = (out_java_t *)&ctx; - pctx->java_segstart(seg); -} - -//-------------------------------------------------------------------------- -void out_java_t::java_segend(segment_t *seg) -{ - init_prompted_output(4); - uchar t = pm().getMySeg(BADADDR, seg)->type; // also set curSeg - switch ( t ) - { - case SEG_CODE: - clr_gen_label(); // for empty method's - if ( pm().curSeg.id.extflg & XFL_M_LABEND ) - out_method_label(1); - if ( pm().curSeg.excNode ) - { - netnode enode(pm().curSeg.excNode); - uint j = (uint32)enode.altval(0); - if ( j == 0 ) - DESTROYED("out::segend"); - - if ( !jasmin() ) - flush_buf(COLSTR("/*", SCOLOR_AUTOCMT), 0); /*"*/// makedep BUG!!! - else - gen_empty_line(); - uint i = 0; - do - { - Exception ex; - if ( enode.supval(++i, &ex, sizeof(ex)) != sizeof(ex) ) - DESTROYED("out::except"); - - pm().curpos = 4; // for loop with large lines - if ( !jasmin() ) - { - OUT_KEYWORD("try"); - } - else - { - OUT_KEYWORD(".catch "); - CASSERT(offsetof(Exception, filter.Ref) == offsetof(Exception, filter.Name) - && offsetof(Exception, filter.Dscr) == offsetof(Exception, filter.Name) + 2); - if ( !ex.filter.Ref ) - OUT_KEYWORD("all"); - else if ( out_alt_ind(ex.filter.Ref) ) - goto STOP_NOW; - } - { - static const TXS kw[3] = - { - TXS_DECLARE(" from "), - TXS_DECLARE(" to "), - TXS_DECLARE(" using ") - }; - int n = 0; - do - { - if ( n == 2 && !jasmin() ) - { - if ( ex.filter.Ref ) - { - if ( CHK_OUT_KEYWORD(" catch") - || chkOutSymbol('(') - || out_alt_ind(ex.filter.Ref) - || chkOutSymbol(')') ) - { - goto STOP_NOW; - } - } - else - { - if ( CHK_OUT_KEYWORD(" finally") ) - goto STOP_NOW; - } - if ( CHK_OUT_KEYWORD(" handler ") ) - goto STOP_NOW; - } - else - { - if ( chkOutKeyword(kw[n].str, kw[n].size) ) - goto STOP_NOW; - } - CASSERT(offsetof(Exception,end_pc)-offsetof(Exception,start_pc) == sizeof(ushort) - && offsetof(Exception,handler_pc)-offsetof(Exception,end_pc) == sizeof(ushort)); - ushort off = 0; - switch ( n ) - { - case 0: off = ex.start_pc; break; - case 1: off = ex.end_pc; break; - case 2: off = ex.handler_pc; break; - } - if ( outOffName(off) ) - goto STOP_NOW; - } - while ( ++n < 3 ); - } - if ( change_line() ) - goto STOP_NOW; - } - while ( i < j ); - if ( !jasmin() ) - close_comment(); - else - gen_empty_line(); - } - if ( pm().curSeg.genNodes[1] && out_includes(pm().curSeg.genNodes[1], 2) ) - goto STOP_NOW; - if ( pm().curSeg.DataSize ) - goto STOP_NOW; -close_method: - for ( int i = 0; i < qnumber(pm().curSeg.annNodes); i++ ) - { - if ( pm().curSeg.annNodes[i] ) - { - if ( annotation_loop(pm().curSeg.annNodes, qnumber(pm().curSeg.annNodes)) ) - goto STOP_NOW; - gen_empty_line(); - break; - } - } - block_close(2, "method"); - break; - -// case SEG_IMP: - default: // PARANOYA - break; - - case SEG_XTRN: - case SEG_BSS: - if ( !jasmin() ) - close_comment(); - if ( t == SEG_BSS ) - goto close_method; - break; - } - myBorder(); -STOP_NOW: - term_prompted_output(); -} - -//-------------------------------------------------------------------------- -void idaapi java_segend(outctx_t &ctx, segment_t *seg) -{ - out_java_t *pctx = (out_java_t *)&ctx; - pctx->java_segend(seg); -} - -//---------------------------------------------------------------------- -static void check_float_const(ea_t ea, void *m, char len) -{ - if ( !has_cmt(get_flags(ea)) && j_realcvt(m, NULL, (uchar)len) < 0 ) - { - char cmt[2+5*5+2], *p = cmt; - - *p++ = '0'; - *p++ = 'x'; - do - p += qsnprintf(p, 5, "%04X", ((ushort *)m)[uchar(len)]); - while ( --len >= 0 ); - remember_problem(PR_ATTN, ea); - append_cmt(ea, cmt, false); - } -} - -//-------------------------------------------------------------------------- -void out_java_t::java_data(bool /*analyze_only*/) -{ - char nbuf[MAXSTR]; - qstring name; - op_t x; - uint32 off; - uint32 lvc; - ea_t ea = insn_ea; - - init_prompted_output(); - char stype = pm().getMySeg(ea)->type; // also set curSeg - ea_t ip = ea - pm().curSeg.start_ea; - asize_t sz = get_item_size(ea) - 1; - switch ( stype ) - { - case SEG_CODE: - if ( ip >= pm().curSeg.CodeSize ) - goto STOP_NOW; - if ( get_name(NULL, ea) > 0 ) - flush_buf(" "); //for string delimeter - if ( sz != 0 ) - { -illcall: - out_line(COLSTR("!!!_UNSUPPORTED_OUTPUT_MODE_!!!", SCOLOR_ERROR)); - } - else - { - pm().curpos = 2; - uchar c = get_byte(ea); - out_printf(COLSTR("%3u %s 0x%02X", SCOLOR_ERROR), - c, ash.cmnt, c); - } - default: - break; - - case SEG_BSS: - if ( is_align(F) ) - { - clr_gen_label(); - set_gen_cmt(false); - set_gen_xrefs(false); - goto STOP_NOW; - } - lvc = 0; // unification - off = uint32(ea - pm().curSeg.DataBase); - if ( (uint32)off >= (uint32)pm().curSeg.DataSize ) - { - off = (uint32)-1; - } - else if ( pm().curSeg.varNode - && (lvc = (uint32)netnode(pm().curSeg.varNode).altval(off)) != 0 ) - { - if ( (int32)lvc < 0 ) - { - lvc = -(int32)lvc; - if ( sz ) // can be byte for 'overloaded' variables :( - { - if ( --sz ) - goto BADIDB; // must be word - } - } - if ( (lvc % sizeof(LocVar)) || lvc >= sizeof(nbuf) ) - goto BADIDB; - } - if ( jasmin() ) - out_line(ash.cmnt, COLOR_AUTOCMT); - clr_gen_label(); - if ( off == (uint32)-1 ) - goto STOP_NOW; - if ( sz ) - goto illcall; - if ( get_visible_name(&name, ea) > 0 ) - out_printf(COLSTR("%s", SCOLOR_AUTOCMT), name.begin()); - if ( lvc == 0 ) - break; - set_gen_cmt(true); - set_gen_xrefs(true); - if ( change_line(true) ) - goto STOP_NOW; - if ( netnode(pm().curSeg.varNode).supval(off, nbuf, lvc+1) != lvc ) - goto BADIDB; - lvc /= sizeof(LocVar); - for ( LocVar *plv = (LocVar*)nbuf; ; plv++ ) - { - if ( jasmin() ) - { - pm().curpos = 4; - OUT_KEYWORD(".var "); - out_tagon(COLOR_NUMBER); - size_t inplen = outbuf.length(); - out_printf("%u", off); - pm().outcnt += outbuf.length() - inplen; - out_tagoff(COLOR_NUMBER); - OUT_KEYWORD(" is "); - } - else - { - if ( plv->utsign && sign_out(plv->utsign, 0) ) - break; - if ( OutUtf8(plv->var.Dscr, fmt_FieldDescriptor, COLOR_KEYWORD) ) - break; - if ( chkOutSpace() ) - break; - } - if ( OutUtf8(plv->var.Name, QS(fmt_UnqualifiedName), COLOR_DNAME) ) - break; - if ( chkOutSpace() ) - break; - if ( jasmin() ) - { - if ( OutUtf8(plv->var.Dscr, fmt_FieldDescriptor, COLOR_KEYWORD) ) - break; - if ( plv->utsign && sign_out(plv->utsign, 0) ) - break; - if ( CHK_OUT_KEYWORD("from ") ) - break; - } - else - { - out_tagon(COLOR_AUTOCMT); - if ( !out_commented("Scope: ") ) - break; - } - if ( putScope(plv->ScopeBeg, off) ) - break; - if ( jasmin() ) - { - if ( CHK_OUT_KEYWORD(" to ") ) - break; - } - else - { - if ( CHK_OUT_STR(" / ") ) - break; - } - if ( putScope(plv->ScopeTop, off) ) - break; - if ( !jasmin() ) - out_tagoff(COLOR_AUTOCMT); - if ( change_line(pm().curpos != 0) || !--lvc ) - break; - } - goto STOP_NOW; - - case SEG_XTRN: - if ( ip > (uint32)pm().curClass.xtrnCnt ) - goto STOP_NOW; - if ( sz ) - goto illcall; - if ( !ip ) - { - gen_printf(0, COLSTR("%s Importing prototypes", SCOLOR_AUTOCMT), - jasmin() ? ash.cmnt : ""); - break; // equivalence - gen_empty_line(); with comment - } - - if ( jasmin() ) - { - out_printf(COLSTR("%s", SCOLOR_AUTOCMT), ash.cmnt); - pm().outcnt = strlen(ash.cmnt); - } - clr_gen_label(); - set_gen_cmt(false); - set_gen_xrefs(false); - { - const_desc_t co; - { - uint j = (uint32)pm().XtrnNode.altval(ip); - if ( j == 0 ) - goto BADIDB; - if ( !pm().LoadOpis(lm_normal, (ushort)j, 0, &co) ) - goto BADIDB; - } - copy_const_to_opnd(x, co); // name / class & dscr / subnam - x.ref = 0; // as flag - x.cp_type = co.type; - switch ( x.cp_type ) - { - default: - goto BADIDB; - - case CONSTANT_Class: - if ( !jasmin() ) - { - outbuf.qclear(); - pm().outcnt = 0; - } - { - static const TXS imp = TXS_DECLARE(".import "); - int of = !jasmin(); - OutKeyword(imp.str+of, imp.size-of); - } - - if ( !(co.flag & (HAS_TYPEDSCR | HAS_CLSNAME)) ) - goto do_idx_out; - x.addr_shorts.high = (co.flag & HAS_CLSNAME) != 0 - ? fmt_fullname - : fmt_ClassName; - goto no_space_check; - - case CONSTANT_Fieldref: - if ( (co.flag & NORM_FIELD) != NORM_FIELD ) - goto do_idx; - break; - case CONSTANT_InterfaceMethodref: - case CONSTANT_Methodref: - if ( (co.flag & NORM_METOD) != NORM_METOD ) - { -do_idx: - ++x.ref; - } - break; - } - } - if ( CHK_OUT_STR(" ") ) - goto STOP_NOW; - if ( x.ref ) - { -do_idx_out: - x.n = 2; - if ( !putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16, 1) ) - goto STOP_NOW; - } - else - { -no_space_check: - if ( !OutConstant(x, /*include_descriptor=*/ true) ) - goto STOP_NOW; - } -// if ( x.cp_type == CONSTANT_Class && !jasmin() ) -// out_line(".*", COLOR_SYMBOL); - break; - - case SEG_IMP: - if ( ip > (uint32)pm().curClass.FieldCnt ) - goto STOP_NOW; - if ( sz ) - goto illcall; - clr_gen_label(); - set_gen_cmt(false); - set_gen_xrefs(false); - if ( !ip ) - { - if ( pm().curClass.annNodes[0] | pm().curClass.annNodes[1] ) - { - if ( annotation_loop(pm().curClass.annNodes, qnumber(pm().curClass.annNodes)) ) - goto STOP_NOW; - } - if ( !jasmin() ) - block_begin(0); - else - gen_empty_line(); - - if ( pm().curClass.innerNode ) - { - netnode inode(pm().curClass.innerNode); - uint j = (uint32)inode.altval(0); - if ( j == 0 ) - goto BADIDB; - color_t ci = jasmin() ? COLOR_IMPNAME : COLOR_NONE; - uint i = 0; - do - { - InnerClass ic; - if ( inode.supval(++i, &ic, sizeof(ic)) != sizeof(ic) ) - goto BADIDB; - pm().curpos = 2; - if ( !jasmin() ) - out_tagon(COLOR_AUTOCMT); - if ( OutModes((((uint32)ic.access) << 16) | OA_NEST) ) - break; - if ( ic.name ) - { - if ( OutUtf8(ic.name, fmt_UnqualifiedName, ci) ) - break; - } - else if ( !jasmin() && CHK_OUT_STR("{anonymous}") ) - { - break; - } - if ( ic.inner ) - { - if ( jasmin() ) - { - if ( CHK_OUT_KEYWORD(" inner ") ) - break; - } - else if ( CHK_OUT_STR(" {is}: ") ) - { - break; - } - if ( OutUtf8(ic.inner, fmt_fullname, ci) ) - break; - } - if ( ic.outer ) - { - if ( jasmin() ) - { - if ( CHK_OUT_KEYWORD(" outer ") ) - break; - } - else if ( CHK_OUT_STR(" {from}: ") ) - { - break; - } - color_t co = ci; - if ( co != COLOR_NONE && ic.outer == pm().curClass.This.Name ) - co = COLOR_DNAME; - if ( OutUtf8(ic.outer, fmt_fullname, co) ) - break; - } - if ( !jasmin() ) - out_tagoff(COLOR_AUTOCMT); - if ( change_line() ) - break; - } - while ( i < j ); - if ( pm().curClass.FieldCnt ) - gen_empty_line(); - } - goto STOP_NOW; - } // first entry (zero offset) - - if ( pm().ClassNode.supval(ip, &pm().curField, sizeof(pm().curField)) != sizeof(pm().curField) ) - goto BADIDB; - pm().curpos = 2; - if ( !jasmin() && pm().curField.id.utsign ) - { - if ( sign_out(pm().curField.id.utsign, 0) ) - goto STOP_NOW; - pm().curpos = 2; - } - if ( OutModes(OA_FIELD) ) - goto STOP_NOW; - if ( !jasmin() && out_field_type() ) - goto STOP_NOW; - if ( out_index(pm().curField.id.name, QS(fmt_UnqualifiedName), COLOR_DNAME, pm().curField.id.extflg & EFL_NAME) ) - goto STOP_NOW; - if ( chkOutSpace() ) - goto STOP_NOW; - if ( jasmin() && out_field_type() ) - goto STOP_NOW; - - if ( pm().curField.valNode ) - { - netnode vnode(pm().curField.valNode); - - uint valcnt = (uint32)vnode.altval(0); - if ( valcnt == 0 ) - goto BADIDB; - x.n = 0; - x.flags = OF_SHOW; - x.type = o_imm; - - if ( chkOutSymSpace('=') ) - goto STOP_NOW; - for ( uint i = 1; ; i++ ) - { - uchar flen; - - const_desc_t co; - if ( vnode.supval(i, &co, sizeof(co)) != sizeof(co) ) - { - ip = netnode(pm().curField.valNode).altval(i); - if ( ushort(ip) != 0xFFFF ) - goto BADIDB; - if ( putShort(ushort(ip >> 16)) ) - goto STOP_NOW; - } - else - { - switch ( co.type ) - { - case CONSTANT_Long: - x.dtype = dt_qword; - copy_const_to_opnd(x, co); - flen = 3; - goto chk_flt; - case CONSTANT_Double: - x.dtype = dt_double; - check_float_const(ea, &co.value, 3); - copy_const_to_opnd(x, co); - goto one_w; - case CONSTANT_Float: - x.dtype = dt_float; - x.value = co.value; - flen = 1; -chk_flt: - check_float_const(ea, &x.value, flen); - goto one_w; - case CONSTANT_Integer: - x.dtype = dt_dword; - x.value = co.value; -one_w: - if ( !putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) ) - goto STOP_NOW; - break; - - case CONSTANT_String: - if ( !checkLine(2) ) - goto STOP_NOW; - if ( OutUtf8(co._name, fmt_string, COLOR_STRING) ) - goto STOP_NOW; - break; - - default: - UNCOMPAT("out::data"); - } - } - - if ( i >= valcnt ) - break; - if ( chkOutSymSpace(',') ) - goto STOP_NOW; - } // for(...) (value) - } // if ( valNode ) - set_gen_cmt(true); - set_gen_xrefs(true); - if ( !change_line(pm().curpos != 0) ) - { - uchar addonce = 0; - - if ( jasmin() ) - { - if ( pm().curField.id.utsign ) - { - pm().curpos = 4; - if ( sign_out(pm().curField.id.utsign, -1) ) - goto STOP_NOW; - addonce = 1; - } - if ( pm().curField.id.extflg & XFL_DEPRECATED ) - { - if ( out_deprecated(4) ) - goto STOP_NOW; - addonce = 1; - } - } - - if ( pm().curField.genNode | pm().curField.annNodes[0] | pm().curField.annNodes[1] ) - { - addonce = 1; - if ( !jasmin() ) - block_begin(2); - } - - if ( pm().curField.genNode && out_includes(pm().curField.genNode, 4) ) - goto STOP_NOW; - - if ( pm().curField.annNodes[0] | pm().curField.annNodes[1] ) - { - pm().curpos = 4; // prompted output (prefer to new syntax) - if ( annotation_loop(pm().curField.annNodes, qnumber(pm().curField.annNodes)) ) - goto STOP_NOW; - } - if ( addonce ) - block_close(2, "field"); - } - goto STOP_NOW; - } - - set_gen_cmt(true); - set_gen_xrefs(true); - change_line(pm().curpos != 0); -STOP_NOW: - term_prompted_output(); - return; - -BADIDB: - DESTROYED("out::data"); -} - -//-------------------------------------------------------------------------- -void idaapi java_data(outctx_t &ctx, bool analyze_only) -{ - out_java_t *pctx = (out_java_t *)&ctx; - pctx->java_data(analyze_only); -} diff --git a/idasdk75/module/java/oututil.cpp b/idasdk75/module/java/oututil.cpp deleted file mode 100644 index e656be8..0000000 --- a/idasdk75/module/java/oututil.cpp +++ /dev/null @@ -1,814 +0,0 @@ -#include "java.hpp" -#include "oututil.hpp" - -//-------------------------------------------------------------------------- -// returns number of positions advanced -int out_java_t::out_commented(const char *p, color_t color) -{ - if ( color != COLOR_NONE ) - out_tagon(color); - size_t inplen = outbuf.length(); - out_printf("%s %s", ash.cmnt, p); - int npos = outbuf.length() - inplen; - if ( color != COLOR_NONE ) - out_tagoff(color); - return npos; -} - -//---------------------------------------------------------------------- -bool out_java_t::change_line(bool main) -{ - bool overflow = false; - if ( pm().g_bufinited ) - { - pm().outcnt = 0; - uchar sv = inf_get_indent(); - inf_set_indent((uchar)pm().curpos); - overflow = flush_buf(outbuf.c_str(), main ? -1 : pm().curpos); - inf_set_indent(sv); - // for autocomment with call fmtName - outbuf.qclear(); - outbuf.reserve(pm().g_bufsize); - } - return overflow; -} - -//---------------------------------------------------------------------- -size_t out_java_t::putLine(java_t &pm) -{ - color_t color = COLOR_NONE; - - if ( pm.g_bufinited ) - { - const char *p = strrchr(outbuf.c_str(), COLOR_ON); - if ( p != NULL && p[1] && strchr(p+2, COLOR_OFF) == NULL ) // second - PARANOYA - { - color = (color_t)*(p + 1); - out_tagoff(color); - } - } - out_symbol('\\'); - if ( change_line(pm.curpos != 0 && !pm.no_prim) ) - return 0; - pm.curpos = 0; - if ( color != COLOR_NONE ) - out_tagon(color); - pm.ref_pos = outbuf.length(); - return pm.maxpos; -} - -//---------------------------------------------------------------------- -bool out_java_t::checkLine(size_t size) -{ - if ( !pm().g_bufinited ) - return true; - if ( pm().maxpos - pm().curpos > pm().outcnt + size ) - return true; - return putLine(pm()) != 0; -} - -//---------------------------------------------------------------------- -bool out_java_t::chkOutLine(const char *str, size_t len) -{ - if ( !checkLine(len) ) - return true; - pm().outcnt += len; - out_line(str); - return false; -} - -//---------------------------------------------------------------------- -bool out_java_t::chkOutKeyword(const char *str, uint len) -{ - if ( !checkLine(len) ) - return true; - OutKeyword(str, len); - return false; -} - -//---------------------------------------------------------------------- -bool out_java_t::chkOutSymbol(char c) -{ - if ( !checkLine(1) ) - return true; - ++pm().outcnt; - out_symbol(c); - return false; -} - -//---------------------------------------------------------------------- -bool out_java_t::chkOutChar(char c) -{ - if ( !checkLine(1) ) - return true; - ++pm().outcnt; - out_char(c); - return false; -} - -//---------------------------------------------------------------------- -bool out_java_t::chkOutSymSpace(char c) -{ - if ( !checkLine(2) ) - return true; - out_symbol(c); - out_char(' '); - pm().outcnt += 2; - return false; -} - -//---------------------------------------------------------------------- -uchar out_java_t::putShort(ushort value, uchar wsym) -{ - size_t inplen = outbuf.length(); - - out_tagon(COLOR_ERROR); - if ( wsym ) - out_char(wsym); - out_btoa(value, -#ifdef __debug__ - debugmode ? 16 : -#endif - 10); - out_tagoff(COLOR_ERROR); - - char tmpstr[32]; - size_t curlen = outbuf.length(); - size_t len = curlen - inplen; - qstrncpy(tmpstr, &outbuf[inplen], qmin(len+1, sizeof(tmpstr))); - outbuf.resize(inplen); - return chkOutLine(tmpstr, tag_strlen(tmpstr)); -} - -//---------------------------------------------------------------------- -char out_java_t::outName(ea_t from, int n, ea_t ea, uval_t off, uchar *rbad) -{ - qstring qbuf; - - if ( get_name_expr(&qbuf, from, n, ea + off, off) <= 0 ) - { - remember_problem(PR_NONAME, insn.ea); - return 0; - } - if ( chkOutLine(qbuf.begin(), tag_strlen(qbuf.begin())) ) - { - *rbad = 1; - return 0; - } - return 1; -} - -//--------------------------------------------------------------------------- -uchar out_java_t::putVal(const op_t &x, uchar mode, uchar warn) -{ - size_t inplen = outbuf.length(); - - { - flags_t saved = F; - F = 0; - out_value(x, mode); - F = saved; - } - - char str[MAXSTR]; - size_t curlen = outbuf.length(); - size_t len = curlen - inplen; - qstrncpy(str, &outbuf[inplen], qmin(len+1, sizeof(str))); - outbuf.resize(inplen); - - if ( warn ) - out_tagon(COLOR_ERROR); - - if ( warn ) - { - qstring qstr; - len = tag_remove(&qstr, str); - qstrncpy(str, qstr.c_str(), sizeof(str)); - } - else - { - len = tag_strlen(str); - } - - if ( chkOutLine(str, len) ) - return 0; - - if ( warn ) - out_tagoff(COLOR_ERROR); - return 1; -} - -//---------------------------------------------------------------------- -//static _PRMPT_ outProc = putLine; -CASSERT(MIN_ARG_SIZE >= 2 && MIN_ARG_SIZE < 30); - -uchar out_java_t::OutUtf8(ushort index, fmt_t mode, color_t color) -{ - size_t size = (pm().maxpos - pm().curpos) - pm().outcnt; - - if ( (int)size <= MIN_ARG_SIZE ) - { - DEB_ASSERT(((int)size < 0), "OutUtf8"); - size = putLine(pm()); - if ( size == 0 ) - return 1; - } - - if ( color != COLOR_NONE ) - out_tagon(color); - pm().ref_pos = outbuf.length(); - struct ida_local lambda_t - { - static size_t call_putLine(java_t &pm, out_java_t *oj) - { - return oj->putLine(pm); - } - }; - if ( fmtString(pm(), index, size, mode, lambda_t::call_putLine) < 0 ) - return 1; - pm().outcnt += outbuf.length() - pm().ref_pos; - if ( color != COLOR_NONE ) - out_tagoff(color); - return 0; -} - -//--------------------------------------------------------------------------- -uchar out_java_t::out_index(ushort index, fmt_t mode, color_t color, uchar as_index) -{ - if ( as_index ) - { - if ( !(pm().idpflags & (IDM_BADIDXSTR | IDM_OUTASM)) // no store in file - || !pm().is_valid_string_index(index) ) - { - return putShort(index); - } - color = COLOR_ERROR; - mode = fmt_string; - } - return OutUtf8(index, mode, color); -} - -//-------------------------------------------------------------------------- -uchar out_java_t::out_alt_ind(uint32 val) -{ - if ( (ushort)val ) - return OutUtf8((ushort)val, fmt_fullname, COLOR_IMPNAME); - return putShort((ushort)(val >> 16)); -} - -//-------------------------------------------------------------------------- -// special label format/scan procedures -//-------------------------------------------------------------------------- -void out_java_t::out_method_label(uchar is_end) -{ - set_gen_cmt(true); - set_gen_xrefs(true); - gen_printf(0, COLSTR("met%03u_%s%s", SCOLOR_CODNAME), pm().curSeg.id.Number, - is_end ? "end" : "begin", COLSTR(":", SCOLOR_SYMBOL)); -} - -//--------------------------------------------------------------------------- -char out_java_t::putMethodLabel(ushort off) -{ - char str[32]; - int len = qsnprintf(str, sizeof(str), "met%03u_%s", pm().curSeg.id.Number, - off ? "end" : "begin"); - - if ( !checkLine(len) ) - return 1; - out_tagon(COLOR_CODNAME); - outLine(str, len); - out_tagoff(COLOR_CODNAME); - return 0; -} - -//-------------------------------------------------------------------------- -// procedure for get_ref_addr -ssize_t java_t::check_special_label(const char *buf, size_t len) const -{ - if ( len >= sizeof("met000_end")-1 - && (*(uint32*)buf & 0xFFFFFF) == ('m'|('e'<<8)|('t'<<16)) ) - { - - switch ( *(uint32*)&buf[len -= 4] ) - { - case ('_'|('e'<<8)|('n'<<16)|('d'<<24)): - break; - case ('e'|('g'<<8)|('i'<<16)|('n'<<24)): - if ( len >= sizeof("met000_begin")-1 - 4 - && *(ushort*)&buf[len -= 2] == ('_'|('b'<<8)) ) - { - break; - } - //PASS THRU - default: - len |= -1; // as flag - break; - } - if ( len <= sizeof("met00000")-1 ) - { - size_t off = curSeg.CodeSize; - if ( buf[len+1] == 'b' ) - off = 0; - size_t n = 0; - size_t j = sizeof("met")-1; - while ( true ) - { - if ( !qisdigit((uchar)buf[j]) ) - break; - n = n*10 + (buf[j] - '0'); - if ( ++j == len ) - { - if ( n >= 0x10000 || (ushort)n != curSeg.id.Number ) - break; - return off; - } - } - } - } - return -1; -} - -//-------------------------------------------------------------------------- -// end of special-label procedures -//---------------------------------------------------------------------- -uchar out_java_t::outOffName(ushort off) -{ - if ( !off || off == pm().curSeg.CodeSize ) - return putMethodLabel(off); - if ( off < pm().curSeg.CodeSize ) - { - uchar err = 0; - if ( outName(pm().curSeg.start_ea + pm().curSeg.CodeSize, 0, - pm().curSeg.start_ea, off, &err) ) - return 0; // good - if ( err ) - return 1; // bad - } - return putShort(off, 0); -} - -//---------------------------------------------------------------------- -bool out_java_t::block_begin(uchar off) -{ - return flush_buf(COLSTR("{", SCOLOR_SYMBOL), off); -} - -//---------------------------------------------------------------------- -bool out_java_t::block_end(uint32 off) -{ - return flush_buf(COLSTR("}", SCOLOR_SYMBOL), off); -} - -//---------------------------------------------------------------------- -bool out_java_t::block_close(uint32 off, const char *name) -{ - if ( !jasmin() ) - return block_end(off); - return gen_printf(off, COLSTR(".end %s", SCOLOR_KEYWORD), name); -} - -//---------------------------------------------------------------------- -bool out_java_t::close_comment(void) -{ - return flush_buf(COLSTR("*/", SCOLOR_AUTOCMT), 0); -} - -//--------------------------------------------------------------------------- -uchar out_java_t::out_nodelist(uval_t nodeid, uchar pos, const char *pref) -{ - netnode node(nodeid); - uval_t cnt = node.altval(0); - if ( cnt == 0 ) - DESTROYED("out::nodelist"); - - uval_t off = 0; - if ( pref ) // jasmin - { - if ( change_line() ) - { -bad: - return 0; - } - off = strlen(pref); - } - - uint i = 0; - while ( true ) - { - if ( pref ) // jasmin (single directive per line) - { - pm().curpos = pos; - out_keyword(pref); - pm().outcnt = off; - } - else if ( i && chkOutSymSpace(',') ) - { - goto bad; // prompted list - } - if ( out_alt_ind((uint32)node.altval(++i)) ) - goto bad; - if ( i >= cnt ) - return 1; - if ( pref && change_line() ) - goto bad; // jasmin - } -} - -//---------------------------------------------------------------------- -void out_java_t::init_prompted_output(uchar pos) -{ - pm().maxpos = inf_get_margin(); -// if ( maxpos < 32 ) -// maxpos = 32; -// if ( maxpos > MAXSTR - 4 ) -// maxpos = MAXSTR - 4; - -#ifdef __debug__ - if ( debugmode == -1 - && inf.show_line_pref() && inf_get_margin() == 77 && !inf.bin_prefix_size ) - { - maxpos -= gl_psize; - } -#endif - pm().g_bufsize = (MAXSTR*2) - STR_PRESERVED; - pm().g_bufinited = true; - outbuf.qclear(); - outbuf.reserve(pm().g_bufsize); - pm().curpos = pos; - pm().outcnt = 0; -} - -//---------------------------------------------------------------------- -void out_java_t::term_prompted_output(void) -{ - outbuf.qclear(); - pm().g_bufinited = false; - pm().g_bufsize = 0; - pm().maxpos = 0; - pm().curpos = -1; -} - -//---------------------------------------------------------------------- -uchar out_java_t::OutConstant(const op_t &_x, bool include_descriptor) -{ - op_t x = _x; - fmt_t fmt = fmt_FieldDescriptor; - color_t color; - - insn_t cur_insn; - decode_insn(&cur_insn, insn_ea); - switch ( (uchar)x.cp_type ) - { - default: - warning("OC: bad constant type %u", (uchar)x.cp_type); - break; - - case CONSTANT_Long: - x.dtype = dt_qword; - goto outNum; - case CONSTANT_Double: - x.dtype = dt_double; - goto outNum; - case CONSTANT_Integer: - x.dtype = dt_dword; - goto outNum; - case CONSTANT_Float: - x.dtype = dt_float; -outNum: - if ( putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) ) - break; -badconst: - return 0; - - case CONSTANT_Utf8: - if ( OutUtf8(x.cp_ind, fmt_string, COLOR_STRING) ) - goto badconst; - break; - - case CONSTANT_String: - if ( OutUtf8(x._name, fmt_string, COLOR_STRING) ) - goto badconst; - break; - - case CONSTANT_NameAndType: -nameandtype: - if ( OutUtf8(x._class, fmt_fullname) - || OutUtf8(x._name, fmt_fullname) ) - { - goto badconst; - } - break; - - case CONSTANT_InvokeDynamic: - { - const_desc_t invdyn; - if ( pm().ConstantNode.supval(x.cp_ind, &invdyn, sizeof(invdyn)) != sizeof(invdyn) ) - goto badconst; - // Retrieve NameAndType - const_desc_t nat; - if ( pm().ConstantNode.supval(invdyn._name, &nat, sizeof(nat)) != sizeof(nat) ) - goto badconst; - memset(&x, 0, sizeof(x)); - copy_const_to_opnd(x, nat); - x.ref = 0; - x.cp_type = nat.type; - x.cp_ind = invdyn._name; - goto nameandtype; - } - break; - - case CONSTANT_MethodHandle: - { - const_desc_t tmp; - if ( pm().ConstantNode.supval(x._mhr_index, &tmp, sizeof(tmp)) != sizeof(tmp) ) - goto badconst; - op_t tmpop; - memset(&tmpop, 0, sizeof(tmpop)); - copy_const_to_opnd(tmpop, tmp); - tmpop.ref = 0; // as flag - tmpop.cp_type = tmp.type; - tmpop.cp_ind = x._mhr_index; - OutConstant(tmpop, include_descriptor); - } - break; - - case CONSTANT_MethodType: - if ( OutUtf8(x._mtd_index, fmt_fullname, COLOR_KEYWORD) ) - goto badconst; - break; - - case CONSTANT_Class: - CASSERT((fmt_ClassName_or_Array+1) == fmt_ClassName && (fmt_ClassName+1) == fmt_fullname); - { - fmt_t f2 = (fmt_t )x.addr_shorts.high; - color_t c2 = f2 < fmt_ClassName_or_Array || f2 > fmt_fullname ? COLOR_KEYWORD - : cur_insn.xtrn_ip == 0xFFFF ? COLOR_DNAME : COLOR_IMPNAME; - - if ( OutUtf8(x._name, f2, c2) ) - goto badconst; - } - break; - - case CONSTANT_InterfaceMethodref: - case CONSTANT_Methodref: - fmt = fmt_method_ReturnType; - // fallthrough - case CONSTANT_Fieldref: -#ifdef VIEW_WITHOUT_TYPE - if ( include_descriptor ) -#endif - if ( !jasmin() && OutUtf8(x._dscr, fmt, COLOR_KEYWORD) ) - goto badconst; - color = x._class == pm().curClass.This.Dscr ? COLOR_DNAME : COLOR_IMPNAME; - out_tagon(color); - if ( jasmin() || (color == COLOR_IMPNAME && !include_descriptor) ) // other class - { - if ( OutUtf8(x._name, fmt_ClassName) || chkOutDot() ) - goto badconst; - } - if ( OutUtf8(x._subnam, fmt_UnqualifiedName) ) - goto badconst; // Field - out_tagoff(color); - if ( jasmin() ) - { - if ( fmt == fmt_method_ReturnType ) - fmt = fmt_FieldDescriptor_nospace; // no space at end - else if ( chkOutSpace() ) - goto badconst; - } - else - { - if ( fmt != fmt_method_ReturnType ) - break; - fmt = fmt_method_TypeSignature; - } - if ( OutUtf8(x._dscr, fmt, COLOR_KEYWORD) ) - goto badconst; - break; - } - return 1; -} - -//-------------------------------------------------------------------------- -// FIXME: there should be a better way of suppressing borders in disassembly -void out_java_t::myBorder(void) -{ - gen_empty_line(); - if ( pm().user_limiter ) - { - inf_set_limiter(LMT_THIN); - gen_border_line(false); - } - inf_set_limiter(0); // do not output border between method & vars :( -} - -//-------------------------------------------------------------------------- -uchar out_java_t::out_problems(char str[MAXSTR], const char *prefix) -{ - if ( pm().curClass.extflg & XFL_C_ERRLOAD ) - { - myBorder(); - gen_printf(DEFAULT_INDENT, - COLSTR("%s This class has had loading time problem(s)", SCOLOR_ERROR), - prefix); - if ( pm().curClass.msgNode ) - { - gen_empty_line(); - if ( pm().print_loader_messages(str, prefix, this) == -1 ) - return 1; - } - myBorder(); - } - return 0; -} - -//-------------------------------------------------------------------------- -uchar out_java_t::putScope(ushort scope, uint32 doff) -{ - if ( !scope || scope == pm().curSeg.CodeSize ) - return putMethodLabel(scope); - - if ( scope < pm().curSeg.CodeSize ) - { - uchar err = 0; - if ( outName(pm().curSeg.DataBase + doff, 0, pm().curSeg.start_ea, scope, &err) ) - return 0; - if ( err ) - return 1; - } - - return putShort(scope, 0); -} - -//---------------------------------------------------------------------- -size_t out_java_t::debLine(java_t &) -{ - out_char('"'); - out_tagoff(COLOR_STRING); - if ( change_line() ) - return 0; - return putDeb(1); -} - -//---------------------------------------------------------------------- -void out_java_t::OutKeyword(const char *str, size_t len) -{ - pm().outcnt += len; - out_keyword(str); -} - -//---------------------------------------------------------------------- -void out_java_t::outLine(const char *str, uint len) -{ - pm().outcnt += len; - out_line(str); -} - -//---------------------------------------------------------------------- -uchar out_java_t::chkOutDot(void) -{ - return chkOutChar('.'); -} - -//---------------------------------------------------------------------- -void out_java_t::OutSpace(void) -{ - ++pm().outcnt; - out_char(' '); -} - -//---------------------------------------------------------------------- -uchar out_java_t::chkOutSpace(void) -{ - return chkOutChar(' '); -} - -//-------------------------------------------------------------------------- -size_t out_java_t::putDeb(uchar next) -{ - OUT_KEYWORD(".debug "); - out_tagon(COLOR_STRING); - if ( next ) - out_char('"'); - return pm().maxpos - pm().outcnt; -} - -//---------------------------------------------------------------------- -bool out_java_t::out_operand(const op_t &x) -{ - int outf; - uchar warn = 0; - - switch ( x.type ) - { - case o_near: - if ( x.ref ) - { - ++warn; - } - else - { - if ( outName(insn.ea + x.offb, x.n, pm().curSeg.start_ea, x.addr, &warn) ) - break; - if ( warn ) - goto badop; - } - if ( putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32, warn) ) - break; - //PASS THRU - case o_void: -badop: - return false; - - case o_imm: - if ( x.ref == 2 ) - ++warn; - outf = OOFW_IMM | OOF_NUMBER | (x.ref ? OOFS_NOSIGN : OOF_SIGNED); - if ( putVal(x, outf, warn) ) - break; - goto badop; - - case o_mem: - if ( jasmin() ) - goto putidcv_num; - if ( x.ref ) - { -putAddr: - ++warn; - } - else - { - if ( outName(insn.ea + x.offb, x.n, pm().curSeg.DataBase, x.addr, &warn) ) - break; - if ( warn ) - goto badop; - } -putidcv_num: - if ( putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16, warn) ) - break; - goto badop; - - case o_cpool: - if ( !x.cp_ind ) - { - OUT_KEYWORD("NULL"); - } - else - { - if ( x.ref ) - goto putAddr; - if ( !OutConstant(x) ) - goto badop; - } - break; - - case o_array: - if ( !x.ref ) - { - uchar btype = 0; - switch ( uchar(x.cp_type) ) - { - case T_BOOLEAN: btype = j_bool; break; - case T_CHAR: btype = j_char; break; - case T_FLOAT: btype = j_float; break; - case T_DOUBLE: btype = j_double; break; - case T_BYTE: btype = j_byte; break; - case T_SHORT: btype = j_short; break; - case T_INT: btype = j_int; break; - case T_LONG: btype = j_long; break; - } - const TXS *tname = get_base_typename(btype); - if ( tname == 0 || chkOutKeyword(tname->str, tname->size) ) - goto badop; - } - else - { - static const char tt_bogust[] = "BOGUST_TYPE-"; - - if ( !checkLine(sizeof(tt_bogust) + 2) ) - goto badop; - out_tagon(COLOR_ERROR); - size_t inplen = outbuf.length(); - out_printf("%c%s%u", WARN_SYM, tt_bogust, (uchar)x.cp_type); - pm().outcnt += outbuf.length() - inplen; - out_tagoff(COLOR_ERROR); - } - break; - - default: - warning("out: %a: bad optype %d", insn.ip, x.type); - break; - } - return true; -} - -//-------------------------------------------------------------------------- -void java_t::java_footer(outctx_t &ctx) -{ - if ( !jasmin() ) - { - out_java_t *p = (out_java_t *)&ctx; - p->block_end(0); - } -} diff --git a/idasdk75/module/java/reg.cpp b/idasdk75/module/java/reg.cpp deleted file mode 100644 index b399b45..0000000 --- a/idasdk75/module/java/reg.cpp +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "java.hpp" -#include <diskio.hpp> -#include <ieee.h> -#include "npooluti.hpp" -#include "notify_codes.hpp" -int data_id; - -//----------------------------------------------------------------------- -#ifdef __debug__ -NORETURN void _destroyed(const char *from) -{ - error("Database is corrupted! [at: %s]", from); -} - -//----------------------------------------------------------------------- -NORETURN void _faterr(uchar mode, const char *from) -{ - error("Internal error (%s) [at: %s]", - mode ? "compatibility" : "idp", - from); -} -#else -//----------------------------------------------------------------------- -NORETURN void _destroyed(void) -{ - error("Database is corrupted!"); -} - -//----------------------------------------------------------------------- -NORETURN void _faterr(uchar mode) -{ - error("Internal error (%s)", mode ? "compatibility" : "idp"); -} -#endif - -//----------------------------------------------------------------------- -void java_t::sm_validate(const SegInfo *si) -{ - ea_t segTopEA = si->start_ea + si->CodeSize; - netnode temp(si->smNode); - nodeidx_t nid = temp.supfirst(); - - if ( (ea_t)nid < si->start_ea ) - goto destroyed; - - do - { - if ( (ea_t)nid >= segTopEA ) - goto destroyed; - if ( temp.supval(nid, NULL, 0) != sizeof(sm_info_t) ) - goto destroyed; - if ( !is_head(get_flags((ea_t)nid)) ) - { - remember_problem(PR_HEAD, (ea_t)nid); - if ( !displayed_nl ) - { - displayed_nl = true; - msg("\n"); - } - msg("StackMap refers to nonHead offset %X in Method#%u\n", - (uint32)((ea_t)nid - si->start_ea), si->id.Number); - } - nid = temp.supnext(nid); - } - while ( nid != BADNODE ); - return; - -destroyed: - DESTROYED("sm_validate"); -} - -//---------------------------------------------------------------------- -// visble for upgrade ONLY -void java_t::coagulate_unused_data(const SegInfo *ps) -{ - uint size = 0; - ea_t ea = ps->DataBase; - ea_t top = ea + ps->DataSize; - for ( ; ea < top; ea++ ) - { - if ( is_head(get_flags(ea)) - && get_first_dref_to(ea) == BADADDR ) - { - ConstantNode.chardel(ea, UR_TAG); // unicode renaming support - del_global_name(ea); - del_items(ea, DELIT_SIMPLE); - ++size; - ea_t to; - while ( (to=get_first_dref_from(ea)) != BADADDR ) - del_dref(ea, to); - } - else if ( size ) - { - create_data(ea-size, align_flag(), size, BADNODE); - size = 0; - } - } - if ( size ) - create_data(ea-size, align_flag(), size, BADNODE); -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -static int idaapi out_asm_file( - FILE *fp, - const qstring &line, - bgcolor_t, - bgcolor_t) -{ - qstring qbuf; - tag_remove(&qbuf, line); - size_t len = qbuf.length(); - size_t chk = len; - - if ( qbuf.last() == '\\' ) - --len; - if ( qfwrite(fp, qbuf.c_str(), len) != len ) - return 0; - if ( chk == len && qfputc('\n', fp) == EOF ) - return 0; - return 1; -} - -//---------------------------------------------------------------------- -static void idaapi func_header(outctx_t &ctx, func_t *) { ctx.ctxflags |= CTXF_LABEL_OK; } -static void idaapi func_footer(outctx_t &, func_t *) {} -static bool idaapi java_specseg(outctx_t &ctx, uchar) { java_data(ctx, false); return false; } - -//---------------------------------------------------------------------- -// floating point conversion -int idaapi j_realcvt(void *m, eNE e, ushort swt) -{ - inf_set_be(false); - int i = ieee_realcvt(m, e, swt); - inf_set_be(true); - return i; -} - -//---------------------------------------------------------------------- -// Set IDP options. Either from the configuration file either allow the user -// to specify them in a dialog box. -const char *java_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - static const char form[] = - "HELP\n" - "JAVA specific options\n" - "\n" - " Multiline .debug\n" - "\n" - " If this option is on, IDA forces new .debug directive at every\n" - " LR ('\\n') in the input string\n" - "\n" - " Hide StackMap(s)\n" - "\n" - " If this option is on, IDA hides .stack verification declarations\n" - "\n" - " Auto strings\n" - "\n" - " If this option is on, IDA makes 'prompt-string' after every CR in\n" - " the quoted-string operand\n" - "\n" - " Save to jasmin\n" - "\n" - " If this option is on, IDA creates asm-file in the jasmin-\n" - " compatibe form: concatenates 'prompted' string, reserved names\n" - " will be enclosed in quotes.\n" - " Also when this option is on IDA changes unicode-to-oem encoding to\n" - " unicode-to-ansi encoding because jasmin expects ansi encoding.\n" - "\n" - " Enable encoding\n" - "\n" - " If this option is on, IDA converts unicode characters which\n" - " can't be represented in current locale to ascii characters.\n" - "\n" - " Nopath .attribute\n" - " If this option is on, IDA prints filename in '.attribute'\n" - " directives without the path part.\n" - "\n" - "\n" - " Bad index as string\n" - " If this option is on, IDA will show invalid name/type references\n" - " as a quoted string.\n" - "ENDHELP\n" - "JAVA specific options\n" - "\n" - " <~M~ultilne .debug :C>\n" - " <~H~ide StackMap(s) :C>\n" - " <~A~uto strings :C>\n" - " <~S~ave to jasmin :C>\n" - " <~E~nable encoding :C>\n" - " <~N~opath .attribute :C>>\n" - "\n" - " <~B~ad index as string :C>>\n" - "\n" - "\n"; - - if ( !keyword ) - { - ushort tmp = (idpflags >> 16) & IDM__REQMASK; - ushort flags = idpflags; - if ( ask_form(form, &flags, &tmp) ) - { - int32 old = idpflags; - idpflags = (flags & ~(IDM__REQMASK << 16)) | (tmp << 16); - if ( (idpflags ^ old) & IDF_ENCODING ) - rename_uninames(-1); - } - goto SAVE; - } - - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - - struct keyword_info_t - { - const char *name; - int bit; - }; - static const keyword_info_t keywords[] = - { - { "JAVA_MULTILINE_DEBUG", IDF_MULTDEB }, - { "JAVA_HIDE_STACKMAP", IDF_HIDESM }, - { "JAVA_AUTO_STRING", IDF_AUTOSTR }, - { "JAVA_ASMFILE_CONVERT", IDF_CONVERT }, - { "JAVA_ENABLE_ENCODING", IDF_ENCODING }, - { "JAVA_NOPATH_ATTRIBUTE", IDF_NOPATH }, - { "JAVA_UNKATTR_REQUEST", IDM_REQUNK }, - { "JAVA_UNKATTR_WARNING", IDM_WARNUNK }, - }; - - for ( int i=0; i < qnumber(keywords); i++ ) - { - if ( strcmp(keywords[i].name, keyword) == 0 ) - { - setflag(idpflags, keywords[i].bit, *(int*)value != 0); - goto SAVE; - } - } - - if ( streq(keyword, "JAVA_STARTASM_LIST") ) - { - start_asm_list = *(int*)value; - return IDPOPT_OK; - } - else - { - return IDPOPT_BADKEY; - } -SAVE: - if ( idb_loaded ) - ConstantNode.altset(CNA_IDPFLAGS, (ushort)idpflags); - return IDPOPT_OK; - -} - -//---------------------------------------------------------------------- -static const asm_t jasmin_asm = -{ - AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3, - UAS_JASMIN, - "Jasmin assembler", - 0, // no help screen - NULL, // header - NULL, // origin - NULL, // end of file - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'\\", // special symbols in char and string constants - - "", // ascii string directive - "", // byte directive - NULL, // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float - NULL, // double - NULL, // no tbytes - NULL, // no packreal - NULL, // arrays: - // #h - header(.byte,.word) - // #d - size of array - // #v - value of array elements - NULL, //".reserv %s", // uninited data (reserve space) - " = ", // equ - NULL, // seg prefix - NULL, // a_curip - func_header, // func header - func_footer, // func footer - "", // public (disable ouput) - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - NULL, // a_include_fmt - NULL, // a_vstruc_fmt - NULL, // a_rva -}; - -//---------------------------------------------------------------------- -static const asm_t list_asm = -{ - AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3, - 0, - "User friendly listing", - 0, // no help screen - NULL, // header - NULL, // origin - NULL, // end of file - - "//", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'\\", // special symbols in char and string constants - - "", // ascii string directive - "", // byte directive - NULL, // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float - NULL, // double - NULL, // no tbytes - NULL, // no packreal - NULL, // arrays: - // #h - header(.byte,.word) - // #d - size of array - // #v - value of array elements - NULL, //".reserv %s", // uninited data (reserve space) - " = ", // equ - NULL, // seg prefix - NULL, // a_curip - func_header, // func header - func_footer, // func footer - "", // public (disable ouput) - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - NULL, // a_include_fmt - NULL, // a_vstruc_fmt - NULL, // a_rva -}; - -//----------------------------------------------------------------------- -static const asm_t *const asms[] = { &jasmin_asm, &list_asm, NULL }; - -static const char *const RegNames[] = { "vars", "optop", "frame", "cs", "ds" }; - -#define FAMILY "Java Virtual Machine:" - -static const char *const shnames[] = -{ - "java", -#ifdef __debug__ - "_javaPC", -#endif - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Java", -#ifdef __debug__ - "Java full (IBM PC, debug mode)", -#endif - NULL -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { j_ret }; -static const uchar retcode_1[] = { j_ireturn }; -static const uchar retcode_2[] = { j_lreturn }; -static const uchar retcode_3[] = { j_freturn }; -static const uchar retcode_4[] = { j_dreturn }; -static const uchar retcode_5[] = { j_areturn }; -static const uchar retcode_6[] = { j_return }; -static const uchar retcode_7[] = { j_wide, j_ret }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { sizeof(retcode_4), retcode_4 }, - { sizeof(retcode_5), retcode_5 }, - { sizeof(retcode_6), retcode_6 }, - { sizeof(retcode_7), retcode_7 }, - { 0, NULL } -}; - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - memset(&pm.curClass, 0, sizeof(pm.curClass)); - // no break - case idb_event::savebase: - pm.ConstantNode.altset(CNA_IDPFLAGS, (ushort)pm.idpflags); - break; - - case idb_event::auto_empty: - if ( !(pm.curClass.extflg & XFL_C_DONE) ) // kernel BUGs - { - pm.curClass.extflg |= XFL_C_DONE; - msg("JavaLoader finalization stage..."); - for ( int n = pm.curClass.MethodCnt; n; n-- ) - { - SegInfo si; - if ( pm.ClassNode.supval(-n, &si, sizeof(si)) != sizeof(si) ) - DESTROYED("postprocess"); - if ( si.smNode || si.DataSize ) - { - show_addr(si.start_ea); - if ( si.smNode ) - pm.sm_validate(&si); - if ( si.DataSize ) - pm.coagulate_unused_data(&si); - } - } - pm.ConstantNode.supset(CNS_CLASS, &pm.curClass, sizeof(pm.curClass)); // all chgs - pm.sm_node = smn_ok; - msg("OK\n"); - } - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(java_t)); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi java_t::on_event(ssize_t msgid, va_list va) -{ - int retcode = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - inf_set_be(true); //reverse byte! - break; - - case processor_t::ev_rename: - va_arg(va, ea_t); - for ( char const *pn, *p = va_arg(va, const char *); - (pn = strchr(p, '\\')) != NULL; - p = pn+1 ) - { - if ( *++pn != 'u' ) - { -inv_name: - --retcode; // 0 - warning("Backslash is accepted only as a unicode escape sequence in names"); - break; - } - for ( int i = 0; i < 4; i++ ) - if ( !qisxdigit((uchar)*++pn) ) - goto inv_name; - } - break; - - case processor_t::ev_newfile: - if ( inf_get_filetype() != f_LOADER ) - { - set_database_flag(DBFL_KILL); // clean up the database files - error("The input file does not have a supported Java file format"); - } - database_loaded (va_arg(va, char *)); - inf_set_lowoff(BADADDR); - inf_set_highoff(BADADDR); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - database_loaded(NULL); - break; - - case processor_t::ev_term: - unhook_event_listener(HT_IDB, &idb_listener); - qfree(tsPtr); - qfree(smBuf); - qfree(annBuf); - clr_module_data(data_id); - break; - -#ifdef __debug__ - case processor_t::ev_newprc: - { - int procnum = va_arg(va, int); - bool keep_cfg = va_argi(va, bool); - if ( procnum == 1 ) // debug mode - { - ph.flag &= ~(PR_DEFNUM | PR_NOCHANGE); - ph.flag |= PRN_HEX; - if ( inf_get_margin() == 77 && !inf.bin_prefix_size && !inf.show_line_pref() ) - { - if ( !keep_cfg ) - inf_set_show_line_pref(true); - --debugmode; - } - else - { - ++debugmode; - } - } - else // normal node - { - ph.flag &= ~PR_DEFNUM; - ph.flag |= PRN_DEC; - if ( debugmode == -1 - && inf.show_line_pref() - && !inf.bin_prefix_size - && inf_get_margin() == 77 - && !keep_cfg ) - { - inf.show_line_pref(false); - } - debugmode = 0; - } - } - break; -#endif - - case java_module_t::ev_load_file: - { - linput_t *li = va_arg(va, linput_t *); - FILE *f = qlfile(li); - QASSERT(10082, f != NULL); - bool manual = va_argi(va, bool); - loader(f, manual); - retcode = 0; - } - if ( start_asm_list ) - set_target_assembler(1); - break; - - case processor_t::ev_gen_src_file_lnnum: - if ( jasmin() ) - { - outctx_t *ctx = va_arg(va, outctx_t *); - va_arg(va, const char *); // skip file name - size_t lineno = va_arg(va, size_t); - ctx->gen_printf(2, COLSTR(".line %" FMT_Z, SCOLOR_ASMDIR), lineno); - retcode = 1; - } - break; - - case processor_t::ev_gen_asm_or_lst: - { - if ( va_argi(va, bool) ) // starting (else end of generation ) - { - va_arg(va, FILE *); // output file (skip) - bool isasm = va_argi(va, bool); // assembler-true, listing-false - if ( isasm && (idpflags & IDF_CONVERT) ) - { - va_arg(va, int); // flags of gen_file() (skip) - *va_arg(va, gen_outline_t**) = out_asm_file; - idpflags |= IDM_OUTASM; - } - if ( isasm == jasmin() ) - break; // need change mode? - } - else // end of generation. - { - idpflags &= ~IDM_OUTASM; - if ( !mode_changed ) - break; // mode changed? - } - mode_changed = !mode_changed; - set_target_assembler(!inf_get_asmtype()); - } - break; - - case processor_t::ev_get_autocmt: - { - qstring *buf = va_arg(va, qstring *); - const insn_t *insn = va_arg(va, insn_t *); - if ( make_locvar_cmt(buf, *insn) ) - retcode = 1; - } - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - java_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - java_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - java_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - java_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - java_data(*ctx, analyze_only); - return 1; - } - - case processor_t::ev_can_have_type: - { - const op_t *op = va_arg(va, const op_t *); - return can_have_type(*op) ? 1 : -1; - } - - case processor_t::ev_realcvt: - { - void *m = va_arg(va, void *); - uint16 *e = va_arg(va, uint16 *); - uint16 swt = va_argi(va, uint16); - int code = j_realcvt(m, e, swt); - return code == 0 ? 1 : code; - } - - case processor_t::ev_gen_map_file: - { - int *nlines = va_arg(va, int *); - FILE *fp = va_arg(va, FILE *); - int code = gen_map_file(fp); - if ( code == -1 ) - return -1; - *nlines = code; - return 1; - } - - case processor_t::ev_extract_address: - { - ea_t *out_ea = va_arg(va, ea_t *); - ea_t screen_ea = va_arg(va, ea_t); - const char *str = va_arg(va, const char *); - size_t pos = va_arg(va, size_t); - ea_t ea = get_ref_addr(screen_ea, str, pos); - if ( ea == BADADDR ) - return -1; - if ( ea == (BADADDR-1) ) - return 0; - *out_ea = ea; - return 1; - } - - case processor_t::ev_out_special_item: - { - outctx_t *ctx = va_arg(va, outctx_t *); - uchar seg_type = va_argi(va, uchar); - java_specseg(*ctx, seg_type); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return retcode; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_JAVA, // id - // flag - PRN_DEC - | PR_RNAMESOK - | PR_NO_SEGMOVE, - // flag2 - PR2_REALCVT // the module has 'realcvt' event implementation - | PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 0, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0,j_last, - Instructions, // instruc - 0, // size of tbyte - {0,7,15,0}, // real width - j_ret, // icode_return - NULL, // Micro virtual machine description -}; diff --git a/idasdk75/module/java/upgrade.cpp b/idasdk75/module/java/upgrade.cpp deleted file mode 100644 index a267e9c..0000000 --- a/idasdk75/module/java/upgrade.cpp +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * JVM module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "java.hpp" -#include "upgrade.hpp" -#include "oututil.hpp" - -//---------------------------------------------------------------------- -#define _TO_VERSION IDP_JDK16 - -//---------------------------------------------------------------------- -void java_t::make_new_name(ushort name, ushort subnam, uchar mode, uint ip) -{ - out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); - if ( pctx->fmtString(*this, name, MAXNAMELEN-2, fmt_fullname) ) - { -trunc: - pctx->trunc_name(ip, mode & 4); - } - else if ( (char)mode > 0 ) - { - size_t len = pctx->outbuf.length(); - if ( len >= (MAXNAMELEN-3) ) - goto trunc; - pctx->out_char(' '); - if ( pctx->fmtString(*this, subnam, (MAXNAMELEN-2) - len, fmt_UnqualifiedName) ) - goto trunc; - } - force_name(ip, convert_clsname(pctx->outbuf.begin())); - delete pctx; - hide_name(ip); -} - -//---------------------------------------------------------------------- -int java_t::upgrade_db_format(int ver, netnode constnode) -{ - if ( ask_yn(ASKBTN_YES, - "AUTOHIDE REGISTRY\nHIDECANCEL\n" - "The database has an old java data format.\n" - "Do you want to upgrade it?") <= ASKBTN_NO ) - { - qexit(1); - } - - switch ( ver ) - { - default: - INTERNAL("upgrade::ver"); - case IDP_JDK12: - break; - } - - // change format: jdk-version - if ( curClass.MinVers > 0x8000u ) - { -BADIDB: - return 0; - } - - curClass.MajVers = JDK_MIN_MAJOR; - if ( curClass.MinVers >= 0x8000 ) - { - curClass.MinVers &= ~0; - ++curClass.MajVers; - curClass.JDKsubver = 2; - } - else if ( curClass.MinVers >= JDK_1_1_MINOR ) - { - ++curClass.JDKsubver; - } - -// change format: This - CASSERT(offsetof(ClassInfo, This.Ref) == offsetof(ClassInfo, This.Name) - && offsetof(ClassInfo, This.Dscr) == offsetof(ClassInfo, This.Name) + 2); - - curClass.This.Ref = (curClass.This.Ref << 16) | curClass.This.Dscr; - if ( !curClass.This.Name ) - goto BADIDB; - -// change format: Super - CASSERT(offsetof(ClassInfo, super.Ref) == offsetof(ClassInfo, super.Name) - && offsetof(ClassInfo, super.Dscr) == offsetof(ClassInfo, super.Name) + 2); - switch ( curClass.super.Name ) - { - case 0: // absent - curClass.super.Ref &= 0; - break; - case 0xFFFF: // bad index - ++curClass.super.Name; - break; - default: // reverse order - curClass.super.Ref = (curClass.super.Ref << 16) | curClass.super.Dscr; - break; - } - -// validate: impNode - if ( curClass.impNode && !netnode(curClass.impNode).altval(0) ) - goto BADIDB; - -// change variable 'errload' in previous version - if ( curClass.maxSMsize ) - { - curClass.extflg |= XFL_C_ERRLOAD; - curClass.maxSMsize &= 0; - } - -// set segments type type for special segments - segment_t *S = getseg(curClass.start_ea); - if ( S == NULL ) - goto BADIDB; - S->set_hidden_segtype(true); - S->update(); - if ( curClass.xtrnCnt ) - { - S = getseg(curClass.xtrnEA); - if ( S == NULL ) - goto BADIDB; - S->set_hidden_segtype(true); - S->update(); - } - - curClass.extflg |= XFL_C_DONE; // do not repeat datalabel destroyer :) -// change: method/fields format -#define SGEXPSZ (sizeof(SegInfo) - offsetof(SegInfo, varNode)) -#define FMEXPSZ (sizeof(_FMid_) - offsetof(_FMid_, _UNUSED_ALING)) -#define FLEXPSZ (sizeof(FieldInfo) - offsetof(FieldInfo, annNodes)) - uval_t oldsize = sizeof(SegInfo) - FMEXPSZ - SGEXPSZ; - - for ( int pos=-(int)curClass.MethodCnt; pos <= (int)curClass.FieldCnt; pos++ ) - { - union - { - SegInfo s; - FieldInfo f; - _FMid_ id; - uchar _space[qmax(sizeof(SegInfo), sizeof(FieldInfo)) + 1]; //lint !e754 not referenced - } u; - - if ( !pos ) // class node - { - oldsize += (sizeof(FieldInfo) - FLEXPSZ) - (sizeof(SegInfo) - SGEXPSZ); - continue; - } - - if ( ClassNode.supval(pos, &u, sizeof(u)) != oldsize ) - goto BADIDB; - - memmove((uchar *)&u.id + sizeof(u.id), &u.id._UNUSED_ALING, - (size_t)oldsize - offsetof(_FMid_, _UNUSED_ALING)); - u.id._UNUSED_ALING = 0; - u.id.utsign = 0; - - if ( u.id.extflg & ~EFL__MASK ) - goto BADIDB; - u.id.extflg &= (EFL_NAMETYPE); - - if ( pos > 0 ) // fields - { - memset(u.f.annNodes, 0, sizeof(u.f)-offsetof(FieldInfo, annNodes)); - ClassNode.supset(pos, &u.f, sizeof(u.f)); - continue; - } - - // segments - memset(&u.s.varNode, 0, sizeof(u.s) - offsetof(SegInfo, varNode)); - if ( u.s.thrNode && !netnode(u.s.thrNode).altval(0) ) - { - netnode(u.s.thrNode).kill(); // empty node (old format) - u.s.thrNode = 0; - } - - // have locvars? - if ( u.s.DataSize ) - { - S = getseg(u.s.DataBase); - if ( S == NULL ) - goto BADIDB; - S->type = SEG_BSS; - S->set_hidden_segtype(true); - S->update(); - } - - // change: Exception format - if ( u.s.excNode ) - { - netnode enode(u.s.excNode); - ushort j = (ushort)enode.altval(0); - if ( j == 0 ) - goto BADIDB; - ea_t ea = u.s.start_ea + u.s.CodeSize; - ushort i = 1; - do - { - Exception exc; - - if ( enode.supval(i, &exc, sizeof(exc)) != sizeof(exc) ) - goto BADIDB; - - CASSERT(offsetof(Exception, filter.Ref) == offsetof(Exception, filter.Name) - && offsetof(Exception, filter.Dscr) == offsetof(Exception, filter.Name) + 2); - if ( !exc.filter.Name != !exc.filter.Dscr ) - goto BADIDB; - exc.filter.Ref = (exc.filter.Ref << 16) | exc.filter.Dscr; // was reverse order - if ( exc.filter.Name == 0xFFFF ) - ++exc.filter.Name; - enode.supset(i, &exc, sizeof(exc)); - set_exception_xref(&u.s, exc, ea); - } - while ( ++i <= j ); - } - ClassNode.supset(pos, &u.s, sizeof(u.s)); - //rename local variables (for references) - if ( u.s.DataSize ) - { - int i = u.s.DataSize; - ea_t ea = u.s.DataBase + i; - do - { - char str[MAXNAMELEN]; - qsnprintf(str, sizeof(str), "met%03u_slot%03d", u.s.id.Number, --i); - --ea; - if ( force_name(ea, str) ) - make_name_auto(ea); - else - hide_name(ea); - } - while ( i > 0 ); - coagulate_unused_data(&u.s); - } - } // for - -//change format of string presentation in constant pool - FOR_EACH_CONSTANT_POOL_INDEX(pos) - { - const_desc_t co; - if ( constnode.supval(pos, &co, sizeof(co)) != sizeof(co) ) - goto BADIDB; - switch ( co.type ) - { - default: - continue; - - case CONSTANT_Unicode: - error("Base contain CONSTANT_Unicode, but it is removed from " - "the standard in 1996 year and never normal loaded in IDA"); - - case CONSTANT_Utf8: - break; - } - uint32 v, i = pos << 16; - uint32 n = (uint32)constnode.altval(i); - if ( (n & UPG12_BADMASK) != 0 || (v = n & ~UPG12_CLRMASK) == 0 ) - goto BADIDB; - if ( n & UPG12_EXTMASK ) - v |= UPG12_EXTSET; - n = ushort(v); - if ( n != 0 ) - { - uchar *po = (uchar*)append_tmp_buffer(v); - n *= sizeof(ushort); - uint32 idx = 0; - do - { - uint32 sz = n - idx; - if ( sz > MAXSPECSIZE ) - sz = MAXSPECSIZE; - if ( constnode.supval(++i, &po[idx], sz) != sz ) - goto BADIDB; - constnode.supdel(i); - idx += sz; - } - while ( idx < n ); - constnode.setblob(po, n, i & ~0xFFFF, BLOB_TAG); - if ( !(v & UPG12_EXTSET) ) - { - do - { - CASSERT((sizeof(ushort) % 2) == 0 && (MAXSPECSIZE % 2) == 0); - ushort cw = *(ushort *)&po[idx]; - if ( cw >= CHP_MAX ) - { - if ( !javaIdent(cw) ) - goto extchar; - } - else if ( (uchar)cw <= CHP_MIN ) - { -extchar: - v |= UPG12_EXTSET; - break; - } - } - while ( (idx -= sizeof(ushort)) != 0 ); - } - v = upgrade_ResW(v); - } - constnode.altset(i, v); - co._Sopstr = v; // my be not needed? (next also) - constnode.supset(pos, &co, sizeof(co)); - } - -// rename 'import' variables for refernces - for ( uint ip = 1; (ushort)ip <= curClass.xtrnCnt; ip++ ) - { - const_desc_t co; - { - uint j = (uint)XtrnNode.altval(ip); - if ( j == 0 || !LoadOpis(lm_lenient, (ushort)j, 0, &co) ) - goto BADIDB; - } - switch ( co.type ) - { - default: - goto BADIDB; - - case CONSTANT_Class: - if ( !(co.flag & HAS_CLSNAME) ) - continue; - break; - case CONSTANT_InterfaceMethodref: - case CONSTANT_Methodref: - if ( (co.flag & NORM_METOD) != NORM_METOD ) - continue; - break; - case CONSTANT_Fieldref: - if ( (co.flag & NORM_FIELD) != NORM_FIELD ) - continue; - break; - } - make_new_name(co._name, co._subnam, co.type != CONSTANT_Class, ip); - } - - if ( curClass.This.Dscr ) - make_new_name(curClass.This.Name, 0, (uchar)-1, (uint)curClass.start_ea); - - return _TO_VERSION; -} - -//----------------------------------------------------------------------- -//---------------------------------------------------------------------- -// some utilities (size of npool) -//---------------------------------------------------------------------- -// visible for converter only -char *java_t::convert_clsname(char *buf) const -{ - if ( jasmin() ) - for ( char *p = buf; (p = strchr(p, j_clspath_dlm)) != NULL; p++ ) - *p = j_field_dlm; - - return buf; -} - -//----------------------------------------------------------------------- -// visible for converter only -uchar set_exception_xref(SegInfo *ps, Exception const & exc, ea_t ea) -{ - uchar ans = 0; - - if ( exc.start_pc >= ps->CodeSize ) - { - ans = 1; - } - else - { - if ( !exc.start_pc ) - ps->id.extflg |= XFL_M_LABSTART; // special label at entry - add_dref(ea, ps->start_ea + exc.start_pc, dr_I); - } - if ( exc.end_pc > ps->CodeSize ) - { - ans = 1; - } - else - { - if ( exc.end_pc == ps->CodeSize ) - ps->id.extflg |= XFL_M_LABEND; // special label at end - add_dref(ea, ps->start_ea + exc.end_pc, dr_I); - } - if ( exc.handler_pc >= ps->CodeSize ) - return 1; - add_dref(ea, ps->start_ea + exc.handler_pc, dr_I); - return ans; -} diff --git a/idasdk75/module/kr1878/kr1878.cfg b/idasdk75/module/kr1878/kr1878.cfg deleted file mode 100644 index fd001fe..0000000 --- a/idasdk75/module/kr1878/kr1878.cfg +++ /dev/null @@ -1,20 +0,0 @@ - -; This file describes the standard addresses for Angstrem KR1878 - -.default kr1878 - -.kr1878 - -ST 0x00 -PortA 0x01 -PortB 0x02 -TCtl 0x04 -Twrk 0x05 -PCtlA 0x19 -PCtlB 0x1A -WDCtl 0x1D -EEPCtl 0x38 -EEPLoA 0x39 -EEPHiA 0x3A -EEPData 0x3F - diff --git a/idasdk75/module/kr1878/kr1878.hpp b/idasdk75/module/kr1878/kr1878.hpp deleted file mode 100644 index 984808c..0000000 --- a/idasdk75/module/kr1878/kr1878.hpp +++ /dev/null @@ -1,122 +0,0 @@ - -#ifndef _KR1878_HPP -#define _KR1878_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> - -//------------------------------------------------------------------ - -#define amode specflag2 // addressing mode -#define amode_x 0x10 // X: - -//------------------------------------------------------------------ -#define UAS_GNU 0x0001 // GNU assembler -//------------------------------------------------------------------ -enum RegNo -{ - SR0, - SR1, - SR2, - SR3, - SR4, - SR5, - SR6, - SR7, - DSP, - ISP, - as, - bs, - cs, - ds, - vCS, vDS, // virtual registers for code and data segments - -}; - - -//------------------------------------------------------------------ - -struct addargs_t -{ - ea_t ea; - int nargs; - op_t args[4][2]; -}; - - -//------------------------------------------------------------------ -#define IDP_SIMPLIFY 0x0001 // simplify instructions -#define IDP_PSW_W 0x0002 // W-bit in PSW is set - -extern ushort idpflags; - -inline bool dosimple(void) { return (idpflags & IDP_SIMPLIFY) != 0; } -inline bool psw_w(void) { return (idpflags & IDP_PSW_W) != 0; } - -ea_t calc_mem(const insn_t &insn, const op_t &x); - -//------------------------------------------------------------------ -void interr(const insn_t &insn, const char *module); - -void idaapi kr1878_header(outctx_t &ctx); - -void idaapi kr1878_segend(outctx_t &ctx, segment_t *seg); - -int idaapi is_align_insn(ea_t ea); -int idaapi is_sp_based(const insn_t &insn, const op_t &x); - -int is_jump_func(const func_t *pfn, ea_t *jump_target); -int is_sane_insn(const insn_t &insn, int nocrefs); -int may_be_func(const insn_t &insn); // can a function start here? - -void init_analyzer(void); - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct kr1878_t); - -struct kr1878_t : public procmod_t -{ - ioports_t ports; - qstring device; - netnode helper; - ea_t xmem = BADADDR; - op_t *op = nullptr; // current operand - bool flow = false; - - idb_listener_t idb_listener = idb_listener_t(*this); - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const ioport_t *find_port(ea_t address); - void read_kr1878_cfg(void); - void set_device_name(const char *dev); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - ea_t calc_data_mem(const insn_t &insn, const op_t &x, ushort segreg) const; - void handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload); - void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); - int emu(const insn_t &insn); - - void opreg(uint16 reg); - void make_o_mem(const insn_t &insn); - bool D_ddddd(const insn_t &, int value); - bool S_ddddd(const insn_t &insn, int value); - bool D_SR(const insn_t &, int value); - bool S_SR(const insn_t &insn, int value); - bool D_Imm(const insn_t &, int value); - bool D_pImm(const insn_t &insn, int value); - bool D_EA(const insn_t &insn, int value); - bool use_table(const insn_t &insn, uint32 code, int entry, int start, int end); - int ana(insn_t *_insn); - - void kr1878_assumes(outctx_t &ctx); - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void kr1878_segstart(outctx_t &ctx, segment_t *Srange) const; - void kr1878_footer(outctx_t &ctx) const; -}; -#endif // _KR1878_HPP diff --git a/idasdk75/module/kr1878/makefile b/idasdk75/module/kr1878/makefile deleted file mode 100644 index 1dc750a..0000000 --- a/idasdk75/module/kr1878/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=kr1878 -CONFIGS=kr1878.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ - kr1878.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)frame.hpp \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp ins.hpp kr1878.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ - kr1878.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp kr1878.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp kr1878.hpp reg.cpp diff --git a/idasdk75/module/kr1878/reg.cpp b/idasdk75/module/kr1878/reg.cpp deleted file mode 100644 index 7cab6e2..0000000 --- a/idasdk75/module/kr1878/reg.cpp +++ /dev/null @@ -1,499 +0,0 @@ - -#include <ctype.h> -#include "kr1878.hpp" -#include <diskio.hpp> -#include <entry.hpp> -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - // data arithmetic logic unit - "SR0", "SR1", "SR2", "SR3", - "SR4", "SR5", "SR6", "SR7", - "DSP", "ISP", - "a", "b", "c", "d", - "cs","ds", // virtual registers for code and data segments -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0x0c, 0x00 }; -static const uchar retcode_1[] = { 0x0d, 0x00 }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//-------------------------------------------------------------------------- -struct interrupt_t -{ - int offset; - const char *name; //lint !e958 padding is required to align members -}; - -static const interrupt_t ints[] = -{ - { 0x0000, "HRESET" }, // Hardware RESET - { 0x0001, "WDOG" }, - { 0x0002, "STOVF" }, - { 0x0003, "TIMER" }, - { 0x0006, "PORTA" }, - { 0x0007, "PORTB" }, - { 0x000F, "EEPWr" }, -}; - -//----------------------------------------------------------------------- -// Angstrem KR1878VE1 Assembler -//----------------------------------------------------------------------- -static const asm_t motasm = -{ - ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASB_BINF2 // %01010 - |ASO_OCTF1 // 0123 - |AS_COLON - |AS_N2CHR - |AS_NCMAS - |AS_ONEDUP, - 0, - "Angstrem KR1878VE1 Assembler", - 0, - NULL, // header lines - "org", // org - "end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - "dc", // ascii string directive - "dcb", // byte directive - "dc", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "*", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - "global", // "public" name keyword - NULL, // "weak" name keyword - "xref", // "extrn" name keyword - // .extern directive requires an explicit object size - NULL, // "comm" (communal variable) - NULL, // get_type_name - NULL, // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gas = -{ - AS_ASCIIC - |ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASB_BINF3 // 0b01010 - |ASO_OCTF1 // 0123 - |AS_COLON - |AS_N2CHR - |AS_NCMAS - |AS_ONEDUP, - UAS_GNU, - "GNU-like hypothetical assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".long", // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - ".", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "mod", // mod - "and", // and - "or", // or - "xor", // xor - "not", // not - "shl", // shl - "shr", // shr - NULL, // sizeof - 0, // flag2 - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt -}; - -static const asm_t *const asms[] = { &motasm, &gas, NULL }; - -//---------------------------------------------------------------------- -static ea_t AdditionalSegment(int size, int offset, const char *name) -{ - segment_t s; - s.start_ea = free_chunk(0x100000, size, 0xF); - s.end_ea = s.start_ea + size; - s.sel = allocate_selector((s.start_ea-offset) >> 4); - s.type = SEG_DATA; - add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE); - return s.start_ea - offset; -} - -inline ea_t get_start(const segment_t *s) -{ - return s ? s->start_ea : BADADDR; -} - -//-------------------------------------------------------------------------- -const ioport_t *kr1878_t::find_port(ea_t address) -{ - return find_ioport(ports, address); -} - -void kr1878_t::read_kr1878_cfg(void) -{ - read_ioports(&ports, &device, "kr1878.cfg"); - for ( size_t i=0; i < ports.size(); i++ ) - { - const ioport_t &p = ports[i]; - ea_t ea = xmem + p.address; - const char *name = p.name.c_str(); - ea_t nameea = get_name_ea(BADADDR, name); - if ( nameea != ea ) - { - set_name(nameea, ""); - if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) - set_cmt(ea, name, 0); - } - } -} - -void kr1878_t::set_device_name(const char *dev) -{ - if ( dev ) - { - device = dev; - read_kr1878_cfg(); - } -} - -const char *kr1878_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - if ( choose_ioport_device(&device, "kr1878.cfg") ) - read_kr1878_cfg(); - return IDPOPT_OK; -} - -//----------------------------------------------------------------------- -// We always return "yes" because of the messy problem that -// there are additional operands with wrong operand number (always 1) -static bool idaapi can_have_type(const op_t &) -{ - return true; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::savebase: - case idb_event::closebase: - pm.helper.supset(0, pm.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new kr1878_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi kr1878_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: -// __emit__(0xCC); // debugger trap - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ kr1878"); - init_analyzer(); - inf_set_gen_tryblks(true); - break; - - case processor_t::ev_term: - ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: // new file loaded - { - for ( int i=0; i < qnumber(ints); i++ ) - { - ea_t ea = inf_get_min_ea() + ints[i].offset; - if ( !is_loaded(ea) ) - continue; - add_entry(ea, ea, ints[i].name, true); - } - - segment_t *s0 = get_first_seg(); - if ( s0 != NULL ) - { - segment_t *s1 = get_next_seg(s0->start_ea); - set_segm_name(s0, "CODE"); - for ( int i = as; i <= vDS; i++ ) - { - set_default_sreg_value(s0, i, BADSEL); - set_default_sreg_value(s1, i, BADSEL); - } - } - xmem = AdditionalSegment(0x100, 0, "MEM"); - } - read_kr1878_cfg(); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: // old file loaded - xmem = get_start(get_segm_by_name("MEM")); - if ( helper.supstr(&device, 0) > 0 ) - set_device_name(device.c_str()); - break; - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - int nocrefs = va_arg(va, int); - return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1; - } - - case processor_t::ev_may_be_func: - // can a function start here? - // arg: instruction - // returns: probability 0..100 - { - const insn_t *insn = va_arg(va, insn_t *); - return may_be_func(*insn); - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - kr1878_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - kr1878_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - kr1878_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - kr1878_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - kr1878_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *_op = va_arg(va, const op_t *); - return out_opnd(*ctx, *_op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *_op = va_arg(va, const op_t *); - return can_have_type(*_op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *_op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *_op); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "Angstrem KR1878:" -static const char *const shnames[] = { "kr1878", NULL }; -static const char *const lnames[] = -{ - FAMILY"Angstrem KR1878", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_KR1878, // id - // flag - PRN_HEX // hex numbers - | PR_ALIGN // data items must be aligned - | PR_BINMEM // segmentation is done by the processor mode - | PR_SEGS, // has segment registers - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 16, // 16 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - as, // first - vDS, // last - 1, // size of a segment register - vCS, vDS, - - NULL, // No known code start sequences - retcodes, - - KR1878_null, - KR1878_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - KR1878_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/m32r/emu.cpp b/idasdk75/module/m32r/emu.cpp deleted file mode 100644 index 94431b7..0000000 --- a/idasdk75/module/m32r/emu.cpp +++ /dev/null @@ -1,394 +0,0 @@ - -#include "m32r.hpp" - -// handle immediate values -static void handle_imm(const insn_t &insn) -{ - set_immd(insn.ea); -} - -//---------------------------------------------------------------------- -// handle the custom switch format -// .... -// bl.s next || nop <- insn_ea -// next: -// add lr, R0 -// jmp lr -// si.jumps: -// bra.s case0 || nop -// bra.l case1 -// ... -int m32r_create_switch_xrefs(ea_t insn_ea, const switch_info_t &si) -{ - if ( (si.flags & SWI_CUSTOM) != 0 ) - { - insn_t insn; - decode_insn(&insn, insn_ea); - ea_t ea = si.jumps; - for ( int i = 0; i < si.ncases; i++, ea += insn.size ) - { - add_cref(insn_ea, ea, fl_JN); - decode_insn(&insn, ea); - if ( insn.Op1.type == o_near ) - { - ea_t target = to_ea(insn.cs, insn.Op1.addr); - // xrefs are from "bl" -> branch target. - add_cref(insn_ea, target, fl_JN); - } - } - } - return 1; // ok -} - -//---------------------------------------------------------------------- -int m32r_calc_switch_cases(casevec_t *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si) -{ - if ( (si.flags & SWI_CUSTOM) == 0 ) - return 0; - - insn_t insn; - decode_insn(&insn, insn_ea); - - ea_t ea = si.jumps; - svalvec_t vals; - vals.push_back(0); //add one item - for ( int i=0; i < si.ncases; i++, ea += insn.size ) - { - decode_insn(&insn, ea); - if ( targets != NULL ) - { - if ( insn.itype == m32r_bra && insn.Op1.type == o_near ) - targets->push_back(insn.Op1.addr); - else - targets->push_back(insn.ea); - } - if ( casevec != NULL ) - { - vals[0] = i; - casevec->push_back(vals); - } - } - return 1; // ok -} - -//---------------------------------------------------------------------- -static bool handle_switch(const insn_t &insn) -{ - switch_info_t si; - flags_t F = get_flags(insn.ea); - bool ok = (F & FF_JUMP) != 0 - && get_switch_info(&si, insn.ea) > 0; - - if ( !ok ) - { - // ldi8 R1, #0x21 ; '!' - // cmpu R1, R0 - // bc.l loc_67F8C - // slli R0, #2 - // addi R0, #4 - // bl.s next || nop - // next: - // add lr, R0 - // jmp lr - // bra.s loc_67CDC || nop - // bra.s loc_67D34 || nop - // bra.l loc_67F8C - // ... - if ( insn.itype != m32r_bl ) - return false; - - // bl should be to next address - ea_t tgt = to_ea(insn.cs, insn.Op1.addr); - if ( tgt != insn.ea + insn.size ) - return false; - - insn_t insn2; - // check for add lr, R0; jmp lr - if ( decode_insn(&insn2, tgt) == 0 - || insn2.itype != m32r_add - || !insn2.Op1.is_reg(rLR) - || insn2.Op2.type != o_reg ) - { - BAD_MATCH: - return false; - } - - int switch_reg = insn2.Op2.reg; - - // jmp lr - if ( decode_insn(&insn2, insn2.ea + insn2.size) == 0 - || insn2.itype != m32r_jmp - || !insn2.Op1.is_reg(rLR) ) - { - goto BAD_MATCH; - } - - // addi R0, #4 - if ( decode_prev_insn(&insn2, insn.ea) == BADADDR - || insn2.itype != m32r_addi - || !insn2.Op1.is_reg(switch_reg) - || insn2.Op2.type != o_imm ) - { - goto BAD_MATCH; - } - - ea_t jumps = insn.ea + insn.size + insn2.Op2.value; - - // slli R0, #2 - if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR - || insn2.itype != m32r_slli - || !insn2.Op1.is_reg(switch_reg) - || !insn2.Op2.is_imm(2) ) - { - goto BAD_MATCH; - } - - // bc.l default - if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR - || insn2.itype != m32r_bc ) - { - goto BAD_MATCH; - } - - ea_t defea = to_ea(insn2.cs, insn2.Op1.addr); - - // cmpu R1, R0 - if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR - || insn2.itype != m32r_cmpu - || !insn2.Op2.is_reg(switch_reg) - || insn2.Op1.type != o_reg ) - { - goto BAD_MATCH; - } - - int cmpreg = insn2.Op1.reg; - - // ldi8 R1, #max - if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR - || insn2.itype != m32r_ldi - || !insn2.Op1.is_reg(cmpreg) - || insn2.Op2.type != o_imm ) - { - goto BAD_MATCH; - } - - // looks good - - si.flags |= SWI_CUSTOM | SWI_J32; - si.ncases = insn2.Op2.value + 1; - si.jumps = jumps; - si.lowcase = 0; - si.startea = insn2.ea; - si.set_expr(switch_reg, dt_dword); - si.defjump = defea; - set_switch_info(insn.ea, si); - create_switch_table(insn.ea, si); - ok = true; - } - return ok; -} - -//---------------------------------------------------------------------- -// emulate operand -void m32r_t::handle_operand(const insn_t &insn, const op_t &op, bool loading) -{ - flags_t F = get_flags(insn.ea); - switch ( op.type ) - { - // Address - case o_near: - // branch label - create code reference (call or jump - // according to the instruction) - { - ea_t ea = to_ea(insn.cs, op.addr); - cref_t ftype = fl_JN; - if ( insn.itype == m32r_bl && !handle_switch(insn) ) - { - if ( !func_does_return(ea) ) - flow = false; - ftype = fl_CN; - } - insn.add_cref(ea, op.offb, ftype); - } - break; - - // Immediate - case o_imm: - QASSERT(10135, loading); - handle_imm(insn); - // if the value was converted to an offset, then create a data xref: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, dr_O, OOFW_IMM|OOF_SIGNED); - - // create a comment if this immediate is represented in the .cfg file - { - const ioport_t *port = find_sym(op.value); - if ( port != NULL && !has_cmt(F) ) - set_cmt(insn.ea, port->cmt.c_str(), false); - } - break; - - // Displ - case o_displ: - handle_imm(insn); - // if the value was converted to an offset, then create a data xref: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, loading ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR|OOFW_32); - - // create stack variables if required - if ( may_create_stkvars() && !is_defarg(F, op.n) ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) - { - if ( insn.create_stkvar(op, op.addr, STKVAR_VALID_SIZE) ) - op_stkvar(insn.ea, op.n); - } - } - break; - - case o_phrase: - /* create stack variables if required */ - if ( op.specflag1 == fRI && may_create_stkvars() && !is_defarg(F, op.n) ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL - && (op.reg == rFP || op.reg == rSP) - && (pfn->flags & FUNC_FRAME) != 0 ) - { - if ( insn.create_stkvar(op, 0, STKVAR_VALID_SIZE) ) - op_stkvar(insn.ea, op.n); - } - } - break; - - // Phrase - register - void : do nothing - case o_reg: - case o_void: - break; - - // Others types should never be called - default: - INTERR(10136); - } -} - -//---------------------------------------------------------------------------- -// emulate an instruction -int m32r_t::emu(const insn_t &insn) -{ - uint32 feature = insn.get_canon_feature(ph); - flow = ((feature & CF_STOP) == 0); - - if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, true); - if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, true); - if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, true); - - if ( feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false); - if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false); - if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, false); - - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - return 1; -} - -//---------------------------------------------------------------------------- -bool idaapi create_func_frame(func_t *pfn) -{ - if ( pfn == NULL ) - return 0; - - ea_t ea = pfn->start_ea; - insn_t insn[4]; - int i; - - for ( i = 0; i < 4; i++ ) - { - decode_insn(&insn[i], ea); - ea += insn[i].size; - } - - i = 0; - ushort regsize = 0; // number of saved registers - - // first insn is not either push fp OR st fp, @-sp - if ( (insn[i].itype != m32r_push - || insn[i].Op1.reg != rFP) - && (insn[i].itype != m32r_st - || insn[i].Op1.reg != rFP - || insn[i].Op2.reg != rSP - || insn[i].Op2.specflag1 != fRIAS) ) - { - return 0; - } - - regsize += 4; - i++; - - // next insn is push lr OR st lr, @-sp - if ( (insn[i].itype == m32r_push - && insn[i].Op1.reg == rLR) - || (insn[i].itype == m32r_st - && insn[i].Op1.reg == rFP - && insn[i].Op2.reg == rLR - && insn[i].Op2.specflag1 != fRIAS) ) - { - regsize += 4; - i++; - } - - // next insn is not addi sp, #imm - if ( insn[i].itype != m32r_addi || insn[i].Op1.reg != rSP ) - return 0; - - sval_t offset = - (sval_t) insn[i].Op2.value; - - // toggle to the negative sign of the immediate operand of the addi insn - if ( !is_invsign(insn[i].ea, get_flags(insn[i].ea), 2) ) - toggle_sign(insn[i].ea, 2); - - i++; - - // next insn is not mv fp, sp - if ( insn[i].itype != m32r_mv || insn[i].Op1.reg != rFP || insn[i].Op2.reg != rSP ) - return 0; - - pfn->flags |= (FUNC_FRAME | FUNC_BOTTOMBP); - return add_frame(pfn, offset, regsize, 0); -} - -//---------------------------------------------------------------------------- -// should always returns 0 -int idaapi m32r_get_frame_retsize(const func_t *) -{ - return 0; -} - -//---------------------------------------------------------------------------- -// check is the specified operand is relative to the SP register -int idaapi is_sp_based(const insn_t &/*insn*/, const op_t &op) -{ - return OP_SP_ADD | (op.reg == rSP ? OP_SP_BASED : OP_FP_BASED); -} - -//---------------------------------------------------------------------------- -bool idaapi can_have_type(const op_t &x) -{ - switch ( x.type ) - { - case o_imm: - case o_displ: - return 1; - - case o_phrase: - if ( x.specflag1 == fRI ) - return 1; - break; - } - return 0; -} diff --git a/idasdk75/module/m32r/m32r.hpp b/idasdk75/module/m32r/m32r.hpp deleted file mode 100644 index 8ec31ab..0000000 --- a/idasdk75/module/m32r/m32r.hpp +++ /dev/null @@ -1,188 +0,0 @@ - -#ifndef _M32R_HPP -#define _M32R_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include <frame.hpp> -#include "../iohandler.hpp" - -// Flags for operand specflag1 - -#define NEXT_INSN_PARALLEL_NOP 0x0001 // next insn is a // nop -#define NEXT_INSN_PARALLEL_DSP 0x0002 // next insn is a // dsp -#define NEXT_INSN_PARALLEL_OTHER 0x0004 // next insn is an other // insn - -#define SYNTHETIC_SHORT 0x0010 // insn is synthetic short (ex bc.s) -#define SYNTHETIC_LONG 0x0020 // insn is synthetic long (ex bc.l) - -#define HAS_MSB 0x0100 // insn _has_ its MSB to 1 - -// Flags for idpflags - -#define NETNODE_USE_INSN_SYNTHETIC 0x0001 // use synthetic instructions -#define NETNODE_USE_REG_ALIASES 0x0002 // use register aliases - -// Synthetic instructions list: - -/* - m32r : - - bc.s label bc label [8-bit offset] - bc.l label bc label [24-bit offset] - bl.s label bl label [8-bit offset] - bl.l label bl label [24-bit offset] - bnc.s label bnc label [8-bit offset] - bnc.l label bnc label [24-bit offset] - bra.s label bra label [8-bit offset] - bra.l label bra label [24-bit offset] - ldi8 reg, #const ldi reg, #const [8-bit constant] - ldi16 reg, #const ldi reg, #const [16-bit constant] - push reg st reg, @-sp - pop reg ld reg, @sp+ - - m32rx : - - bcl.s label bcl label [8 bit offset] - bcl.l label bcl label [24 bit offset] - bncl.s label bncl label [8 bit offset] - bncl.l label bncl label [24 bit offset] -*/ - -// Register aliases list: - -/* - m32r : - - r13 fp - r14 lr - r15 sp - - cr0 psw - cr1 cbr - cr2 spi - cr3 spu - cr6 bpc - - m32rx : - - cr8 bbpsw - cr14 bbpc -*/ - -// define some shortcuts -#define rFP rR13 -#define rLR rR14 -#define rSP rR15 -#define rPSW rCR0 -#define rCBR rCR1 -#define rSPI rCR2 -#define rSPU rCR3 -#define rBPC rCR6 -#define rFPSR rCR7 - -// m32rx only -#define rBBPSW rCR8 -#define rBBPC rCR14 - -// m32r registers -enum m32r_registers -{ - // General-purpose registers - rR0, rR1, rR2, rR3, rR4, - rR5, rR6, rR7, rR8, rR9, - rR10, rR11, rR12, rR13, rR14, rR15, - - // Control registers - rCR0, rCR1, rCR2, rCR3, rCR6, - - // Program counter - rPC, - - // m32rx special registers - - rA0, rA1, // Accumulators - rCR4, rCR5, rCR7, rCR8, rCR9, // Add. control registers - rCR10, rCR11, rCR12, rCR13, rCR14, rCR15, - - rVcs, rVds // these 2 registers are required by the IDA kernel -}; - -// m32r indirect addressing mode -enum m32r_phrases -{ - fRI, // @R Register indirect - fRIBA, // @R+ Register indirect update before add - fRIAA, // @+R Register indirect update after add - fRIAS // @-R Register indirect update after sub -}; - -// this module supports 2 processors: m32r and m32rx -enum processor_subtype_t -{ - prc_m32r = 0, - prc_m32rx = 1 -}; - -// exporting our routines -void idaapi m32r_footer(outctx_t &ctx); -void idaapi m32r_segstart(outctx_t &ctx, segment_t *seg); -int idaapi emu(const insn_t &insn); -bool idaapi create_func_frame(func_t *pfn); -int idaapi m32r_get_frame_retsize(const func_t *pfn); -int idaapi is_sp_based(const insn_t &insn, const op_t &op); -bool idaapi can_have_type(const op_t &op); -int m32r_create_switch_xrefs(ea_t insn_ea, const switch_info_t &si); -int m32r_calc_switch_cases(casevec_t *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si); - -//------------------------------------------------------------------ -struct opcode; - -struct m32r_iohandler_t : public iohandler_t -{ - struct m32r_t ± - m32r_iohandler_t(m32r_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual void get_cfg_filename(char *buf, size_t bufsize) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct m32r_t); - -struct m32r_t : public procmod_t -{ - netnode helper; - m32r_iohandler_t ioh = m32r_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - // Current configuration parameters - uint32 idpflags = 0; - // Current processor type (prc_m32r or prc_m32rx) - processor_subtype_t ptype = prc_m32r; - bool flow = false; - - inline bool use_synthetic_insn(void) { return (idpflags & NETNODE_USE_INSN_SYNTHETIC) != 0; } - inline bool use_reg_aliases(void) { return (idpflags & NETNODE_USE_REG_ALIASES) != 0; } - inline void save_idpflags() { helper.altset(-1, idpflags); } - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - uint32 refresh_idpflags(void); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool idb_loaded); - const ioport_t *find_sym(ea_t address); - void patch_regnames(void); - - int ana(insn_t *_insn); - const opcode *get_opcode(int word) const; - bool ana_special(insn_t &insn, int word, int *s) const; - int parse_fp_insn(insn_t &insn, int word); - - void m32r_header(outctx_t &ctx); - inline const char *ptype_str(void) const; - - void handle_operand(const insn_t &insn, const op_t &op, bool loading); - int emu(const insn_t &insn); -}; -#endif /* _M32R_HPP */ diff --git a/idasdk75/module/m32r/makefile b/idasdk75/module/m32r/makefile deleted file mode 100644 index fdbbd97..0000000 --- a/idasdk75/module/m32r/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=m32r -CONFIGS=m32r.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp ins.hpp m32r.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp emu.cpp ins.hpp m32r.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.cpp ins.hpp m32r.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp m32r.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp m32r.hpp reg.cpp diff --git a/idasdk75/module/m32r/reg.cpp b/idasdk75/module/m32r/reg.cpp deleted file mode 100644 index 79790d7..0000000 --- a/idasdk75/module/m32r/reg.cpp +++ /dev/null @@ -1,497 +0,0 @@ - -#include "m32r.hpp" -#include <ieee.h> -static int data_id; - -// m32r register names -static const char *const RegNames[] = -{ - "R0", "R1", "R2", "R3", "R4", - "R5", "R6", "R7", "R8", "R9", - "R10", "R11", "R12", "R13", "R14", "R15", - "CR0", "CR1", "CR2", "CR3", "CR6", - "PC", - "A0", "A1", - "CR4", "CR5", "CR7", "CR8", "CR9", - "CR10", "CR11", "CR12", "CR13", "CR14", "CR15", - "cs", "ds" // required by IDA kernel -}; -static const char *const RegNames_alias[] = -{ - "R0", "R1", "R2", "R3", "R4", - "R5", "R6", "R7", "R8", "R9", - "R10", "R11", "R12", "fp", "lr", "sp", - "psw", "cbr", "spi", "spu", "bpc", - "PC", - "A0", "A1", - "CR4", "CR5", "fpsr", "CR8", "CR9", - "CR10", "CR11", "CR12", "CR13", "CR14", "CR15", - "cs", "ds" // required by IDA kernel -}; - -static char const cfgname[] = "m32r.cfg"; - -void m32r_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) -{ - qstrncpy(buf, cfgname, bufsize); -} - -//---------------------------------------------------------------------------- -static int idaapi choose_device(int, form_actions_t &fa) -{ - m32r_t &pm = *(m32r_t *)fa.get_ud(); - if ( choose_ioport_device(&pm.ioh.device, cfgname) ) - pm.ioh.set_device_name(pm.ioh.device.c_str(), IORESP_NONE); - return 0; -} - -//---------------------------------------------------------------------------- -// create the netnode helper and fetch idpflags value -uint32 m32r_t::refresh_idpflags(void) -{ - idpflags = (uint32)helper.altval(-1); - return idpflags; -} - -//---------------------------------------------------------------------------- -// patch the RegNames[] array according to the use_reg_aliases parameter. -void m32r_t::patch_regnames(void) -{ - if ( use_reg_aliases() ) - ph.reg_names = RegNames_alias; - else - ph.reg_names = RegNames; -} - -//---------------------------------------------------------------------------- -// This function (called when opening the module related configuration in -// the general options) will create a dialog box asking the end-user if he -// wants to use synthetic instructions and register aliases. -const char *m32r_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool idb_loaded) -{ - short opt_subs = 0; - - if ( keyword != NULL ) - return IDPOPT_BADKEY; - - if ( use_synthetic_insn() ) - opt_subs |= 1; - if ( use_reg_aliases() ) - opt_subs |= 2; - - static const char form[] = - "HELP\n" - "Mitsubishi 32-Bit (m32r) related options :\n" - "\n" - " Use synthetic instructions\n" - "\n" - " If this option is on, IDA will simplify instructions and replace\n" - " them by synthetic pseudo-instructions.\n" - "\n" - " For example,\n" - "\n" - " bc label1 ; 8 bits offset \n" - " bc label2 ; 24 bits offset \n" - " ldi r1, #0xF \n" - " ldi r2, #0x123456 \n" - " st r3, @-sp \n" - " ld r4, @sp+ \n" - "\n" - " will be replaced by\n" - "\n" - " bc.s label1 \n" - " bc.l label2 \n" - " ldi8 r1, #0xF \n" - " ldi24 r2, #0x123456 \n" - " push r3 \n" - " pop r4 \n" - "\n" - " Use registers aliases\n" - "\n" - " If checked, IDA will use aliases names for the following registers :\n" - "\n" - " r13 -> fp \n" - " r14 -> lr \n" - " r15 -> sp \n" - " cr0 -> psw \n" - " cr1 -> cbr \n" - " cr2 -> spi \n" - " cr3 -> spu \n" - " cr6 -> bpc \n" - "\n" - "ENDHELP\n" - "m32r related options\n" - "%*\n" - "<##Substitutions" - "#For example, use bc.s instead of 8-Bit bc instructions#Use ~s~ynthetic instructions:C>" - "<#For example, use fp instead or r14#Use registers ~a~liases:C>>\n\n\n\n" - "<~C~hoose device name:B:0::>" - "\n\n\n"; - - ask_form(form, this, &opt_subs, choose_device); - - idpflags = 0; // reset the configuration - if ( opt_subs & 1 ) - idpflags |= NETNODE_USE_INSN_SYNTHETIC; - if ( opt_subs & 2 ) - idpflags |= NETNODE_USE_REG_ALIASES; - - if ( idb_loaded ) - save_idpflags(); - patch_regnames(); - return IDPOPT_OK; -} - -// returns a pointer to a ioport_t object if address was found in the config file. -// otherwise, returns NULL. -const ioport_t *m32r_t::find_sym(ea_t address) -{ - return find_ioport(ioh.ports, address); -} - -// GNU Assembler description -static const asm_t gnu_asm = -{ - AS_COLON - |ASH_HEXF3 // hex 0x123 format - |ASB_BINF3 // bin 0b010 format - // don't display the final 0 in string declarations - |AS_ASCIIZ | AS_ASCIIC | AS_1TEXT, - 0, - "m32r GNU Assembler", - 0, - NULL, // no headers - NULL, - NULL, - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".word", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - - // Although the M32R/X/D has no hardware floating point, - // the '.float' and '.double' directives generate IEEE-format - // floating-point values for compatibility with other development tools. - - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - NULL, // func_header - NULL, // func_footer - ".global", // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - "LOW(%s)", // low16 op - "HIGH(%s)" // high16 op -}; - -// As this time, we only support the GNU assembler. -static const asm_t *const asms[] = { &gnu_asm, NULL }; - -// Short and long names for our module -#define FAMILY "Mitsubishi 32-BIT family:" -static const char *const shnames[] = -{ - "m32r", - "m32rx", - NULL -}; -static const char *const lnames[] = -{ - FAMILY"Mitsubishi 32-BIT family", - "Mitsubishi 32-BIT family (extended)", - NULL -}; - -// Opcodes of "return" instructions. This information will be used in 2 ways: -// - if an instruction has the "return" opcode, its autogenerated label -// will be "locret" rather than "loc". -// - IDA will use the first "return" opcode to create empty subroutines. - -static const uchar retcode_1[] = { 0x1F, 0xCE }; // jmp lr -static const uchar retcode_2[] = { 0x10, 0xD6 }; // rte - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } // NULL terminated array -}; - -//---------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::savebase: - case idb_event::closebase: - // synchronize the database long variable with the current configuration settings - pm.save_idpflags(); - pm.helper.supset(-1, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(m32r_t)); - return 0; -} - -//---------------------------------------------------------------------------- -ssize_t idaapi m32r_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - // this processor is big endian - inf_set_be(true); - helper.create("$ m32r"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: - if ( choose_ioport_device(&ioh.device, cfgname) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - // default configuration - idpflags = NETNODE_USE_INSN_SYNTHETIC - | NETNODE_USE_REG_ALIASES; - // save flags to idb - save_idpflags(); - - // patch register names according to idpflags - patch_regnames(); - break; - - case processor_t::ev_newprc: - ptype = processor_subtype_t(va_arg(va, int)); -// msg("ptype = %s\n", ptype == prc_m32r ? "m32r" : ptype == prc_m32rx ? "m32rx" : "???"); - break; - - case processor_t::ev_ending_undo: - // restore ptype - ptype = processor_subtype_t(ph.get_proc_index()); - //fall through - case processor_t::ev_oldfile: - refresh_idpflags(); - ioh.restore_device(); - // patch register names according to idpflags - patch_regnames(); - break; - - case processor_t::ev_create_switch_xrefs: - { - ea_t insn_ea = va_arg(va, ea_t); - switch_info_t *si = va_arg(va, switch_info_t *); - return m32r_create_switch_xrefs(insn_ea, *si); - } - - case processor_t::ev_calc_switch_cases: - { - casevec_t *casevec = va_arg(va, casevec_t *); - eavec_t *targets = va_arg(va, eavec_t *); - ea_t insn_ea = va_arg(va, ea_t); - switch_info_t *si = va_arg(va, switch_info_t *); - return m32r_calc_switch_cases(casevec, targets, insn_ea, *si); - } - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m32r_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m32r_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - m32r_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *op = va_arg(va, const op_t *); - return can_have_type(*op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = m32r_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_M32R, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_BINMEM // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - | PR_USE32 - | PR_DEFSEG32, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 0, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0,m32r_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - m32r_rte, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/m740/emu.cpp b/idasdk75/module/m740/emu.cpp deleted file mode 100644 index 62e897f..0000000 --- a/idasdk75/module/m740/emu.cpp +++ /dev/null @@ -1,135 +0,0 @@ - -#include "m740.hpp" - -static void handle_imm(const insn_t &insn, const op_t &op, flags_t F) -{ - set_immd(insn.ea); - if ( is_defarg(F, op.n) ) - return; - bool in_hex = false; - switch ( insn.itype ) - { - case m740_and: - case m740_ora: - in_hex = true; - break; - } - if ( in_hex ) - op_hex(insn.ea, op.n); -} - -void m740_t::handle_operand(const insn_t &insn, const op_t &op) -{ - flags_t F = get_flags(insn.ea); - switch ( op.type ) - { - // code address - case o_near: - { - ea_t ea = to_ea(insn.cs, op.addr); - cref_t mode = fl_JN; - if ( insn.itype == m740_jsr ) - { - if ( !func_does_return(ea) ) - flow = false; - mode = fl_CN; - } - insn.add_cref(ea, op.offb, mode); - } - break; - - // data address - case o_mem: - { - enum dref_t mode = dr_U; - - if ( is_addr_ind(op) ) - mode = dr_R; /* NOT dr_O */ - else if ( is_addr_read(op) ) - mode = dr_R; - else if ( is_addr_write(op) ) - mode = dr_W; - - insn.add_dref(to_ea(insn.cs, op.addr), op.offb, mode); - insn.create_op_data(op.addr, op); - } - break; - - // immediate - case o_imm: - handle_imm(insn, op, F); - // if the value was converted to an offset, then create a data xref: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, dr_O, 0); - break; - - // displ - case o_displ: - if ( op_adds_xrefs(F, op.n) ) - { - ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR); - insn.create_op_data(ea, op); - } - break; - - // reg - do nothing - case o_reg: - case o_void: - break; - - default: - INTERR(10022); - } -} - -// emulate an instruction -int m740_t::emu(const insn_t &insn) -{ - uint32 feature = insn.get_canon_feature(ph); - flow = ((feature & CF_STOP) == 0); - - if ( insn.Op1.type != o_void ) handle_operand(insn, insn.Op1); - if ( insn.Op2.type != o_void ) handle_operand(insn, insn.Op2); - if ( insn.Op3.type != o_void ) handle_operand(insn, insn.Op3); - -/* - we can't use this code - - if ( feature & CF_USE1) handle_operand(insn, insn.Op1, 1 ); - if ( feature & CF_USE2) handle_operand(insn, insn.Op2, 1 ); - if ( feature & CF_USE3) handle_operand(insn, insn.Op3, 1 ); -*/ - - // we don't use CF_JUMP - //if ( feature & CF_JUMP ) - switch ( insn.itype ) - { - case m740_jmp: - case m740_jsr: - if ( insn.Op1.type != o_void && is_addr_ind(insn.Op1) ) - remember_problem(PR_JUMP, insn.ea); - break; - } - -/* - if ( feature & CF_CHG1) handle_operand(insn, insn.Op1, 0 ); - if ( feature & CF_CHG2) handle_operand(insn, insn.Op2, 0 ); - if ( feature & CF_CHG3) handle_operand(insn, insn.Op3, 0 ); -*/ - - if ( flow ) - { - // skip the next byte if the current insn is brk - if ( insn.itype == m740_brk ) - { - add_cref(insn.ea, insn.ea + insn.size + 1, fl_JN); - create_byte(insn.ea + insn.size, 1); - } - else - { - add_cref(insn.ea, insn.ea + insn.size, fl_F); - } - } - - return 1; -} diff --git a/idasdk75/module/m740/m740.hpp b/idasdk75/module/m740/m740.hpp deleted file mode 100644 index 843e570..0000000 --- a/idasdk75/module/m740/m740.hpp +++ /dev/null @@ -1,86 +0,0 @@ - -#ifndef __M740_HPP -#define __M740_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include <frame.hpp> -#include "../iohandler.hpp" - -// flags for insn.auxpref -#define INSN_DISPL_INDX 0x00000001 // indirect X -#define INSN_DISPL_INDY 0x00000002 // indirect Y -#define INSN_DISPL_ZPX 0x00000004 // zero page X -#define INSN_DISPL_ZPY 0x00000008 // zero page Y -#define INSN_DISPL_ABSX 0x00000010 // absolute X -#define INSN_DISPL_ABSY 0x00000020 // absolute Y - -inline bool is_displ_indx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_INDX) != 0; } -inline bool is_displ_indy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_INDY) != 0; } -inline bool is_displ_zpx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ZPX) != 0; } -inline bool is_displ_zpy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ZPY) != 0; } -inline bool is_displ_absx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ABSX) != 0; } -inline bool is_displ_absy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ABSY) != 0; } - -// flags for insn.Op[n].specflag1 -#define OP_ADDR_SP 0x00000001 // special page -#define OP_ADDR_IND 0x00000002 // indirect address -#define OP_ADDR_R 0x00000010 // read access -#define OP_ADDR_W 0x00000020 // write access -#define OP_IMM_BIT 0x00000004 // immediate bit index - -inline bool is_addr_sp(const op_t &op) { return (op.specflag1 & OP_ADDR_SP) != 0; } -inline bool is_addr_ind(const op_t &op) { return (op.specflag1 & OP_ADDR_IND) != 0; } -inline bool is_addr_read(const op_t &op) { return (op.specflag1 & OP_ADDR_R) != 0; } -inline bool is_addr_write(const op_t &op) { return (op.specflag1 & OP_ADDR_W) != 0; } - -// flags for ash.uflag -#define UAS_SEGM 0x0001 // segments are named "segment XXX" -#define UAS_RSEG 0x0002 // segments are named "rseg XXX" -#define UAS_INDX_NOSPACE 0x0004 // no spaces between operands in indirect X addressing mode - -// 740 registers -enum m740_registers -{ - rA, // accumulator - rX, // index register X - rY, // index register Y - rS, // stack pointer - rPS, // processor status register - rVcs, rVds // these 2 registers are required by the IDA kernel -}; - -// 740 phrases -enum m740_phrases {}; - -// exporting our routines -void idaapi m740_header(outctx_t &ctx); -int idaapi ana(insn_t *_insn); - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct m740_t); - -struct m740_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - void handle_operand(const insn_t &insn, const op_t &op); - int emu(const insn_t &insn); - - void m740_header(outctx_t &ctx); - void m740_footer(outctx_t &ctx) const; - void m740_segstart(outctx_t &ctx, segment_t *Sarea) const; -}; -#endif /* __M740_HPP */ diff --git a/idasdk75/module/m740/makefile b/idasdk75/module/m740/makefile deleted file mode 100644 index 61915dd..0000000 --- a/idasdk75/module/m740/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=m740 -CONFIGS=m740.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp ins.hpp m740.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp emu.cpp ins.hpp m740.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.cpp ins.hpp m740.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp m740.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp m740.hpp reg.cpp diff --git a/idasdk75/module/m740/reg.cpp b/idasdk75/module/m740/reg.cpp deleted file mode 100644 index 13fb2d7..0000000 --- a/idasdk75/module/m740/reg.cpp +++ /dev/null @@ -1,343 +0,0 @@ - -#include "m740.hpp" - -// 740 registers names -static const char *const RegNames[] = -{ - "A", // accumulator - "X", // index register X - "Y", // index register Y - "S", // stack pointer - "PS", // processor status register - "cs", "ds" // these 2 registers are required by the IDA kernel -}; - -const char *m740_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( !choose_ioport_device(&ioh.device, cfgfile) ) - { - if ( ioh.device == NONEPROC ) - warning("No devices are defined in the configuration file %s", cfgfile); - } - else - { - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - return IDPOPT_OK; -} - -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::savebase: - case idb_event::closebase: - pm.helper.supset(-1, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new m740_t); - return 0; -} - -ssize_t idaapi m740_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ m740"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: - set_idp_options(NULL, 0, NULL, true); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m740_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m740_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - m740_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -static const asm_t as_asm = -{ - AS_COLON - |ASH_HEXF4 // hex $123 format - |ASB_BINF3 // bin 0b010 format - |ASO_OCTF5 // oct 123q format - |AS_1TEXT, // 1 text per line, no bytes - UAS_SEGM|UAS_INDX_NOSPACE, - "Alfred Arnold's Macro Assembler", - 0, - NULL, // no headers - "ORG", // origin directive - "END", // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - "BYT", // ascii string directive - "BYT", // byte directive (alias: DB) - NULL, // word directive (alias: DW) - NULL, // dword (4 bytes, alias: DD) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -static const asm_t iar_asm = -{ - AS_COLON - |ASH_HEXF4 // hex $123 format - |ASB_BINF3 // bin 0b010 format - |ASO_OCTF5 // oct 123q format - |AS_1TEXT, // 1 text per line, no bytes - UAS_RSEG, - "IAR 740 Assembler", - 0, - NULL, // no headers - "ORG", // origin directive - "END", // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - "BYTE", // ascii string directive - "BYTE", // byte directive (alias: DB) - "WORD", // word directive (alias: DW) - "DWORD", // dword (4 bytes, alias: DD) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "BLKB %s", // uninited arrays - "EQU", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - NULL, // func_header - NULL, // func_footer - "PUBLIC", // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - "SIZEOF", // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -// Supported assemblers -static const asm_t *const asms[] = { &as_asm, &iar_asm, NULL }; - -// Short and long name for our module -#define FAMILY "Mitsubishi 8-BIT 740 family:" // MELPS 740, Renesas 740 - -static const char *const shnames[] = -{ - "m740", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY "Mitsubishi 8-BIT 740 family", - NULL -}; - -static const uchar retcode_1[] = { 0x40 }; // rti -static const uchar retcode_2[] = { 0x60 }; // rts - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } // NULL terminated array -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_M740, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_BINMEM, // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 0, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0, m740_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - m740_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/m7700/emu.cpp b/idasdk75/module/m7700/emu.cpp deleted file mode 100644 index 9c64e28..0000000 --- a/idasdk75/module/m7700/emu.cpp +++ /dev/null @@ -1,269 +0,0 @@ - -#include "m7700.hpp" - -static void handle_imm(const insn_t &insn, const op_t &op, flags_t F) -{ - set_immd(insn.ea); - if ( is_defarg(F, op.n) ) - return; - bool in_hex = false; - switch ( insn.itype ) - { - case m7700_and: - case m7700_ora: - in_hex = true; - break; - } - if ( in_hex ) - op_hex(insn.ea, op.n); -} - -// propagate m and x to the jump target -static void propagate_bits_to(const insn_t &insn, ea_t ea) -{ - if ( !is_loaded(ea) ) - return; - split_sreg_range(ea, rfM, get_sreg(insn.ea, rfM), SR_auto); - split_sreg_range(ea, rfX, get_sreg(insn.ea, rfX), SR_auto); -} - -void m7700_t::handle_operand(const insn_t &insn, const op_t &op) -{ - flags_t F = get_flags(insn.ea); - switch ( op.type ) - { - // code address - case o_near: - { - ea_t ea = to_ea(insn.cs, op.addr); - cref_t mode; - if ( insn.itype == m7700_jsr ) - { - mode = is_insn_long_format(insn) ? fl_CF : fl_CN; - if ( !func_does_return(ea) ) - flow = false; - } - else - { - mode = is_insn_long_format(insn) ? fl_JF : fl_JN; - } - insn.add_cref(ea, op.offb, mode); - propagate_bits_to(insn, ea); - } - break; - - // data address - case o_mem: - // create xref for instructions with : - // - direct addressing mode if the value of DR is known - // (and therefore, computed by the analyzer) - // - other addressing modes - if ( !is_addr_dr_rel(op) || get_sreg(insn.ea, rDR) != BADSEL ) - { - enum dref_t mode = dr_U; - if ( is_addr_ind(op) ) - mode = dr_R; /* NOT dr_O */ - else if ( is_addr_read(op) ) - mode = dr_R; - else if ( is_addr_write(op) ) - mode = dr_W; - - insn.add_dref(to_ea(insn.cs, op.addr), op.offb, mode); - insn.create_op_data(op.addr, op); - } - break; - - // immediate - case o_imm: - handle_imm(insn, op, F); - // if the value was converted to an offset, then create a data xref: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, dr_O, 0); - break; - - // bit - case o_bit: - handle_imm(insn, op, F); - // create a comment if this immediate is represented in the .cfg file - if ( op.n == 0 && (insn.Op2.type == o_near || insn.Op2.type == o_mem) ) - { - const ioport_bit_t * port = find_bit(insn.Op2.addr, (size_t)op.value); - - if ( port != NULL && !port->name.empty() && !has_cmt(F) ) - set_cmt(insn.ea, port->cmt.c_str(), false); - } - // if the value was converted to an offset, then create a data xref: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, dr_O, 0); - break; - - // displ - case o_displ: - if ( op_adds_xrefs(F, op.n) ) - { - ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR); - insn.create_op_data(ea, op); - } - break; - - // reg - do nothing - case o_reg: - case o_void: - break; - - default: - INTERR(10028); - } -} - -//------------------------------------------------------------------------- -// emulate an instruction -int m7700_t::emu(const insn_t &insn) -{ - uint32 feature = insn.get_canon_feature(ph); - flow = ((feature & CF_STOP) == 0); - - if ( insn.Op1.type != o_void ) handle_operand(insn, insn.Op1); - if ( insn.Op2.type != o_void ) handle_operand(insn, insn.Op2); - if ( insn.Op3.type != o_void ) handle_operand(insn, insn.Op3); - - // we don't use CF_JUMP - //if ( feature & CF_JUMP ) - switch ( insn.itype ) - { - case m7700_jmp: - case m7700_jsr: - if ( insn.Op1.type != o_void && is_addr_ind(insn.Op1) ) - remember_problem(PR_JUMP, insn.ea); - break; - } - - if ( flow ) - { - // skip the next byte if the current insn is brk - if ( insn.itype == m7700_brk ) - { - add_cref(insn.ea, insn.ea + insn.size + 1, fl_JN); - create_byte(insn.ea + insn.size, 1); - } - else - { - add_cref(insn.ea, insn.ea + insn.size, fl_F); - } - } - - switch ( insn.itype ) - { - // clear m flag - case m7700_clm: - split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); - break; - // set m flag - case m7700_sem: - split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); - break; - - // clear processor status - case m7700_clp: - // clear m flag - if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) - split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); - // clear x flag - if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) - split_sreg_range(insn.ea + insn.size, rfX, 0, SR_auto); - break; - - // set processor status - case m7700_sep: - // set m flag - if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) - split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); - // set x flag - if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) - split_sreg_range(insn.ea + insn.size, rfX, 1, SR_auto); - break; - - // pull processor status from stack - case m7700_plp: - split_sreg_range(insn.ea + insn.size, rfM, BADSEL, SR_auto); - split_sreg_range(insn.ea + insn.size, rfX, BADSEL, SR_auto); - break; - } - return 1; -} - -static bool is_func_far(ea_t ea) -{ - bool func_far = false; - insn_t insn; - while ( true ) - { - if ( decode_insn(&insn, ea) == 0 ) - break; - ea += insn.size; - - // rts = jsr - if ( insn.itype == m7700_rts ) - break; - - // rtl = jsrl - if ( insn.itype == m7700_rtl ) - { - func_far = true; - break; - } - } - return func_far; -} - -bool idaapi create_func_frame(func_t *pfn) -{ - // PC (2 bytes long) is always pushed - int context_size = 2; - - // detect phd - ea_t ea = pfn->start_ea; - - // if far, 1 byte more on the stack (PG register) - if ( is_func_far(ea) ) - { - pfn->flags |= FUNC_FAR; - context_size++; - } - - insn_t insn; - decode_insn(&insn, ea); - ea += insn.size; - if ( insn.itype != m7700_phd ) - return 0; - - // DR (2 bytes long) is pushed - context_size += 2; - - int auto_size = 0; - - while ( true ) - { - decode_insn(&insn, ea); - ea += insn.size; - - // A (2 bytes long) is pushed - if ( insn.itype != m7700_pha ) - break; - - auto_size += 2; - } - - // gen comment - char b[MAXSTR]; - qsnprintf(b, sizeof b, "Auto Size (%d) - Context Size (%d)", auto_size, context_size); - set_func_cmt(pfn, b, false); - - return add_frame(pfn, auto_size, 0, 0); -} - -//lint -e{818} -int idaapi idp_get_frame_retsize(const func_t *pfn) -{ - return is_func_far(pfn->start_ea) ? 2 : 3; -} diff --git a/idasdk75/module/m7700/m7700.hpp b/idasdk75/module/m7700/m7700.hpp deleted file mode 100644 index a2f638f..0000000 --- a/idasdk75/module/m7700/m7700.hpp +++ /dev/null @@ -1,160 +0,0 @@ - -#ifndef __M7700_HPP -#define __M7700_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include <frame.hpp> -#include <segregs.hpp> // for get_sreg() -#include "../iohandler.hpp" - -// flags for insn.op[n].specflag1 -#define OP_IMM_WITHOUT_SHARP 0x0001 // don't display the # for this immediate -#define OP_ADDR_IND 0x0002 // this address should be printed between '(' ')' -#define OP_DISPL_IND 0x0004 // this displacement should be printed between '(' ')' -#define OP_DISPL_IND_P1 0x0008 // only the first parameter of the displacement - // should be printed between '(' ')' -#define OP_ADDR_R 0x0010 // addr operand used in 'read' context -#define OP_ADDR_W 0x0020 // addr operand used in 'write' context -#define OP_ADDR_DR_REL 0x0040 // addr operand is relative to DR (direct page register) - -// specflag1 helpers -inline bool is_imm_without_sharp(const op_t &op) { return (op.specflag1 & OP_IMM_WITHOUT_SHARP) != 0; } -inline bool is_addr_ind(const op_t &op) { return (op.specflag1 & OP_ADDR_IND) != 0; } -inline bool is_addr_read(const op_t &op) { return (op.specflag1 & OP_ADDR_R) != 0; } -inline bool is_addr_write(const op_t &op) { return (op.specflag1 & OP_ADDR_W) != 0; } -inline bool is_displ_ind(const op_t &op) { return (op.specflag1 & OP_DISPL_IND) != 0; } -inline bool is_displ_ind_p1(const op_t &op) { return (op.specflag1 & OP_DISPL_IND_P1) != 0; } -inline bool is_addr_dr_rel(const op_t &op) { return (op.specflag1 & OP_ADDR_DR_REL) != 0; } - -// flags for insn.auxpref -#define INSN_LONG_FORMAT 0x0001 // we need to write an additionnal 'l' - // after the insn mnemonic. -// auxpref helpers -inline bool is_insn_long_format(const insn_t &insn) { return (insn.auxpref & INSN_LONG_FORMAT) != 0; } - -// flags for ash.uflag -#define UAS_SEGM 0x0001 // segments are named "segment XXX" -#define UAS_INDX_NOSPACE 0x0002 // no spaces between operands in indirect X addressing mode -#define UAS_END_WITHOUT_LABEL 0x0004 // do not print the entry point label after end directive -#define UAS_DEVICE_DIR 0x0008 // supports device declaration directives -#define UAS_BITMASK_LIST 0x0010 // supports list instead of bitmask for some special insn - // like clp, psh... - -// 7700 registers -enum m7700_registers -{ - rA, // accumulator A - rB, // accumulator B - rX, // index X - rY, // index Y - rS, // stack pointer - rPC, // program counter - rPG, // program bank register - rDT, // data bank register - rPS, // processor status register - rDR, // direct page register - rfM, // data length flag - rfX, // index register length flag - rVcs, rVds // these 2 registers are required by the IDA kernel -}; - -// this module supports 2 processors: m7700, m7750 -enum processor_subtype_t -{ - prc_m7700 = 0, - prc_m7750 = 1 -}; - -// shortcut for a new operand type -#define o_bit o_idpspec0 - -// exporting our routines -void idaapi m7700_assumes(outctx_t &ctx); -int idaapi ana(insn_t *_insn); -bool idaapi create_func_frame(func_t *pfn); -int idaapi idp_get_frame_retsize(const func_t *pfn); - -//------------------------------------------------------------------ -// 7700 addressing modes : -enum m7700_addr_mode_t -{ - A_IMPL, // implied - A_IMM, // immediate - A_ACC_A, // accumulator A - A_ACC_B, // accumulator B - A_DIR, // direct - A_DIR_BIT, // direct bit - A_DIR_IND_X, // direct indexed X - A_DIR_IND_Y, // direct indexed Y - A_DIR_INDI, // direct indirect - A_DIR_IND_X_INDI, // direct indexed X indirect - A_DIR_INDI_IND_Y, // direct indirect indexed Y - A_DIR_INDI_LONG, // direct indirect long - A_DIR_INDI_LONG_IND_Y, // direct indirect long indexed Y - A_ABS, // absolute - A_ABS_BIT, // absolute bit - A_ABS_IND_X, // absolute indexed X - A_ABS_IND_Y, // absolute indexed Y - A_ABS_LONG, // absolute long - A_ABS_LONG_IND_X, // absolute long indexed X - A_ABS_INDI, // absolute indirect - A_ABS_INDI_LONG, // absolute indirect long - A_ABS_IND_X_INDI, // absolute indexed X indirect - A_STACK, // stack - A_STACK_S, // stack short - A_STACK_L, // stack long - A_REL, // relative - A_REL_LONG, // relative long - A_DIR_BIT_REL, // direct bit relative - A_ABS_BIT_REL, // absolute bit relative - A_STACK_PTR_REL, // stack pointer relative - A_STACK_PTR_REL_IIY, // stack pointer relative indirect indexed Y - A_BT // block transfer -}; - -//------------------------------------------------------------------ -struct opcode; -struct m7700_iohandler_t : public iohandler_t -{ - struct m7700_t ± - m7700_iohandler_t(m7700_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual void get_cfg_filename(char *buf, size_t bufsize) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct m7700_t); - -struct m7700_t : public procmod_t -{ - netnode helper; - m7700_iohandler_t ioh = m7700_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - // Current processor type - processor_subtype_t ptype = prc_m7700; - bool with_acc_b = false; - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - bool choose_device(); - const ioport_bit_t *find_bit(ea_t address, size_t bit); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - const struct opcode *get_opcode(uint16 code); - void fill_insn(insn_t &insn, m7700_addr_mode_t mode); - int ana(insn_t *_insn); - - void handle_operand(const insn_t &insn, const op_t &op); - int emu(const insn_t &insn); - - void m7700_header(outctx_t &ctx); - void m7700_footer(outctx_t &ctx) const; - void m7700_segstart(outctx_t &ctx, segment_t *Srange) const; - void m7700_assumes(outctx_t &ctx) const; -}; -#endif // __M7700_HPP diff --git a/idasdk75/module/m7700/makefile b/idasdk75/module/m7700/makefile deleted file mode 100644 index f042ef8..0000000 --- a/idasdk75/module/m7700/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=m7700 -CONFIGS=m7700.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ana.cpp ins.hpp m7700.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp m7700.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ins.cpp ins.hpp m7700.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ins.hpp m7700.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ins.hpp m7700.hpp reg.cpp diff --git a/idasdk75/module/m7700/out.cpp b/idasdk75/module/m7700/out.cpp deleted file mode 100644 index 525d2e8..0000000 --- a/idasdk75/module/m7700/out.cpp +++ /dev/null @@ -1,358 +0,0 @@ - -#include "m7700.hpp" - -//---------------------------------------------------------------------- -class out_m7700_t : public outctx_t -{ - out_m7700_t(void) = delete; // not used - m7700_t &pm() { return *static_cast<m7700_t *>(procmod); } -public: - void outreg(const int n) { out_register(ph.reg_names[n]); } - void outaddr(const op_t &op, const bool replace_with_label = true); - void outdispl(const op_t &op); - bool bitmask2list(const op_t &op); - - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); -}; -CASSERT(sizeof(out_m7700_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_m7700_t) - -//-------------------------------------------------------------------------- -void out_m7700_t::outaddr(const op_t &op, const bool replace_with_label) -{ - bool ind = is_addr_ind(op); // is operand indirect ? - - if ( ind ) - out_symbol('('); - - // if addressing mode is direct and the value of DR is unknown, - // we have to print DR:x (where x is the "indexed" value) - if ( is_addr_dr_rel(op) && get_sreg(insn.ea, rDR) == BADSEL ) - { - outreg(rDR); - out_symbol(':'); - out_value(op, OOF_ADDR | OOFS_NOSIGN); - } - // otherwise ... - else if ( !replace_with_label - || !out_name_expr(op, to_ea(insn.cs, op.addr), op.addr) ) - { - if ( replace_with_label ) - out_tagon(COLOR_ERROR); - out_value(op, OOF_ADDR | OOFS_NOSIGN /*| OOFW_16*/); - if ( replace_with_label ) - out_tagoff(COLOR_ERROR); - } - - if ( ind ) - out_symbol(')'); -} - -//-------------------------------------------------------------------------- -void out_m7700_t::outdispl(const op_t &op) -{ - if ( is_displ_ind(op) ) - { - out_symbol('('); - outaddr(op, false); - out_symbol(','); - if ( !(ash.uflag & UAS_INDX_NOSPACE) ) - out_char(' '); - outreg(op.reg); - out_symbol(')'); - } - else if ( is_displ_ind_p1(op) ) - { - out_symbol('('); - outaddr(op, false); - out_symbol(')'); - out_symbol(','); - out_char(' '); - outreg(op.reg); - } - else - { - outaddr(op, false); - out_symbol(','); - out_char(' '); - outreg(op.reg); - } -} - -//-------------------------------------------------------------------------- -void m7700_t::m7700_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); - if ( ash.uflag & UAS_DEVICE_DIR ) - { - switch ( ptype ) - { - case prc_m7700: - ctx.gen_printf(DEFAULT_INDENT, ".MCU M37700"); - break; - case prc_m7750: - ctx.gen_printf(DEFAULT_INDENT, ".MCU M37750"); - break; - default: - INTERR(10029); - } - } -} - -//-------------------------------------------------------------------------- -void m7700_t::m7700_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - ctx.out_char(' '); - if ( ash.uflag & UAS_END_WITHOUT_LABEL ) - ctx.out_line("; "); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} - -//-------------------------------------------------------------------------- -bool out_m7700_t::bitmask2list(const op_t &op) -{ - static const char *const flags[] = - { - "N", "V", "m", "x", "D", "I", "Z", "C" - }; - static const int regs[] = - { - rPS, rPG, rDT, rDR, rY, rX, rB, rA - }; - - enum { bitFLAGS, bitREGS } t; - switch ( insn.itype ) - { - case m7700_psh: - case m7700_pul: - t = bitREGS; - break; - - case m7700_sep: - case m7700_clp: - t = bitFLAGS; - break; - - default: - return false; - } - - if ( op.value == 0 ) - return false; - - bool ok = false; - for ( int tmp = (int)op.value, i = 1, j = 0; j < 8; i *= 2, j++ ) - { - if ( ((tmp & i) >> j) != 1 ) - continue; - - if ( ok ) - { - out_symbol(','); - out_char(' '); - } - - switch ( t ) - { - case bitFLAGS: - out_register(flags[7 - j]); - break; - case bitREGS: - outreg(regs[7 - j]); - break; - } - ok = true; - } - return true; -} - -//-------------------------------------------------------------------------- -bool out_m7700_t::out_operand(const op_t &x) -{ - switch ( x.type ) - { - // register - case o_reg: - outreg(x.reg); - break; - - // immediate - case o_imm: - { - bool list_ok = false; - - if ( ash.uflag & UAS_BITMASK_LIST ) - list_ok = bitmask2list(x); - - if ( !list_ok ) - { - if ( !(is_imm_without_sharp(x)) ) - out_symbol('#'); - out_value(x, OOFW_IMM); - } - } - break; - - // bit - case o_bit: - { - const ioport_bit_t * port = NULL; - - if ( x.n == 0 && (insn.Op2.type == o_near || insn.Op2.type == o_mem) ) - port = pm().find_bit(insn.Op2.addr, (size_t)x.value); - - // this immediate is represented in the .cfg file - if ( port != NULL && !port->name.empty() ) - { - // output the port name instead of the numeric value - out_line(port->name.c_str(), COLOR_IMPNAME); - } - // otherwise, simply print the value - else - { - out_symbol('#'); - out_value(x, OOFW_IMM); - } - } - break; - - // data / code memory address - case o_near: - case o_mem: - outaddr(x); - break; - - // displ - case o_displ: - outdispl(x); - break; - - // ignore void operands - case o_void: - break; - - default: - INTERR(10030); - } - return 1; -} - -//-------------------------------------------------------------------------- -void out_m7700_t::out_proc_mnem(void) -{ - const char *pfx = is_insn_long_format(insn) ? "l" : NULL; - out_mnem(8, pfx); -} - -//-------------------------------------------------------------------------- -void out_m7700_t::out_insn(void) -{ - out_mnemonic(); - - // - // print insn operands - // - - out_one_operand(0); // output the first operand - - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - } - - if ( insn.Op3.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(2); - } - - // output a character representation of the immediate values - // embedded in the instruction as comments - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -// generate segment header -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Srange) could be made const -void m7700_t::m7700_segstart(outctx_t &ctx, segment_t *Srange) const -{ - qstring sname; - get_visible_segm_name(&sname, Srange); - - if ( ash.uflag & UAS_SEGM ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), sname.c_str()); - else - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".SECTION %s", SCOLOR_ASMDIR), sname.c_str()); - - ea_t orgbase = ctx.insn_ea - get_segm_para(Srange); - if ( orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -inline bool show_assume_line(const sreg_range_t *sra, ea_t ea, int segreg) -{ - bool show = false; - if ( sra->start_ea == ea ) - { - sreg_range_t prev_sra; - if ( get_prev_sreg_range(&prev_sra, ea, segreg) ) - show = sra->val != prev_sra.val; - } - return show; -} - -//-------------------------------------------------------------------------- -void m7700_t::m7700_assumes(outctx_t &ctx) const -{ - ea_t ea = ctx.insn_ea; - segment_t *seg = getseg(ea); - if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) - return; - bool seg_started = (ea == seg->start_ea); - - sreg_range_t sra; - if ( get_sreg_range(&sra, ea, rDR) ) - { - if ( (seg_started && sra.val != BADSEL) || show_assume_line(&sra, ea, rDR) ) - ctx.gen_printf(-1, COLSTR("%s DPR = %a", SCOLOR_REGCMT), ash.cmnt, sra.val); - } - - if ( get_sreg_range(&sra, ea, rfM) ) - { - if ( seg_started || show_assume_line(&sra, ea, rfM) ) - ctx.gen_printf(-1, COLSTR("%s m = %a", SCOLOR_REGCMT), ash.cmnt, sra.val); - } - - if ( get_sreg_range(&sra, ea, rfX) ) - { - if ( seg_started || show_assume_line(&sra, ea, rfX) ) - ctx.gen_printf(-1, COLSTR("%s x = %a", SCOLOR_REGCMT), ash.cmnt, sra.val); - } -} diff --git a/idasdk75/module/m7700/reg.cpp b/idasdk75/module/m7700/reg.cpp deleted file mode 100644 index f08622a..0000000 --- a/idasdk75/module/m7700/reg.cpp +++ /dev/null @@ -1,498 +0,0 @@ - -#include "m7700.hpp" -#include <segregs.hpp> - -// 740 registers names -static const char *const RegNames[] = -{ - "A", // accumulator A - "B", // accumulator B - "X", // index register X - "Y", // index register Y - "S", // stack pointer - "PC", // program counter - "PG", // program bank register - "DT", // data bank register - "PS", // processor status register - "DPR", // direct page register - "fM", // data length flag - "fX", // index register length flag - "cs", "ds" // these 2 registers are required by the IDA kernel -}; - -static const char cfgname[] = "m7700.cfg"; - -void m7700_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) -{ - qstrncpy(buf, cfgname, bufsize); -} - -//-------------------------------------------------------------------------- -bool m7700_t::choose_device() -{ - bool ok = choose_ioport_device(&ioh.device, cfgname); - if ( !ok ) - ioh.device = NONEPROC; - return ok; -} - -//-------------------------------------------------------------------------- -const ioport_bit_t *m7700_t::find_bit(ea_t address, size_t bit) -{ - return find_ioport_bit(ioh.ports, address, bit); -} - -//-------------------------------------------------------------------------- -const char *m7700_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - - if ( !choose_ioport_device(&ioh.device, cfgname) - && ioh.device == NONEPROC ) - { - warning("No devices are defined in the configuration file %s", cfgname); - } - else - { - if ( helper.supstr(&ioh.device, -1) > 0 ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case idb_event::savebase: - case idb_event::closebase: - pm.helper.supset(-1, pm.ioh.device.c_str()); - break; - - case idb_event::sgr_changed: - { - ea_t ea1 = va_arg(va, ea_t); - ea_t ea2 = va_arg(va, ea_t); - int reg = va_arg(va, int); - sel_t v = va_arg(va, sel_t); - sel_t ov = va_arg(va, sel_t); - if ( (reg == rfM || reg == rfX) && v != ov ) - set_sreg_at_next_code(ea1, ea2, reg, ov); - } - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -static const char *const m7700_help_message = - "AUTOHIDE REGISTRY\n" - "You have loaded a file for the Mitsubishi 7700 family processor.\n\n"\ - "This processor can be used in two different 'length modes' : 8-bit and 16-bit.\n"\ - "IDA allows to specify the encoding mode for every single instruction.\n"\ - "For this, IDA uses two virtual segment registers : \n"\ - " - fM, used to specify the data length;\n"\ - " - fX, used to specify the index register length.\n\n"\ - "Switching their state from 0 to 1 will switch the disassembly from 16-bit to 8-bit.\n"\ - "You can change their value using the 'change segment register value' command\n"\ - "(the canonical hotkey is Alt-G).\n\n"\ - "Note : in the real design, those registers are represented as flags in the\n"\ - "processor status register.\n"; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new m7700_t); - return 0; -} - -ssize_t idaapi m7700_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ m7700"); - break; - - case processor_t::ev_newfile: - if ( choose_device() ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - else - ioh.set_device_name(NONEPROC, IORESP_NONE); - // Set the default segment register values : - // -1 (badsel) for DR - // 0 for fM and fX - for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) - { - set_default_sreg_value(s, rDR, BADSEL); - set_default_sreg_value(s, rfM, 0); - set_default_sreg_value(s, rfX, 0); - } - info(m7700_help_message); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newprc: - ptype = processor_subtype_t(va_arg(va, int)); - break; - - case processor_t::ev_ending_undo: - // restore ptype - ptype = processor_subtype_t(ph.get_proc_index()); - //fall through - case processor_t::ev_oldfile: - ioh.restore_device(IORESP_ALL); - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m7700_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m7700_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - m7700_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m7700_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = idp_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -static const asm_t as_asm = -{ - AS_COLON - |ASH_HEXF4 // hex $123 format - |ASB_BINF3 // bin 0b010 format - |ASO_OCTF5 // oct 123q format - |AS_1TEXT, // 1 text per line, no bytes - UAS_SEGM|UAS_INDX_NOSPACE, - "Alfred Arnold's Macro Assembler", - 0, - NULL, // no headers - "ORG", // origin directive - "END", // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - "DB", // ascii string directive - "DB", // byte directive - "DW", // word directive - "DD", // dword (4 bytes) - "DQ", // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - "DT", // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -// -// Mitsubishi Macro Assembler for 7700 Family -// - -//-------------------------------------------------------------------------- -// gets a function name -//lint -e{818} could be declared const -static bool mits_get_func_name(qstring *name, func_t *pfn) -{ - ea_t ea = pfn->start_ea; - if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 ) - return false; - - tag_addr(name, ea, true); - return true; -} - -//-------------------------------------------------------------------------- -// prints function header -static void idaapi mits_func_header(outctx_t &ctx, func_t *pfn) -{ - ctx.gen_func_header(pfn); - - qstring name; - if ( mits_get_func_name(&name, pfn) ) - { - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".FUNC %s", SCOLOR_ASMDIR), name.begin()); - ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name.begin()); - ctx.ctxflags |= CTXF_LABEL_OK; - } -} - -//-------------------------------------------------------------------------- -// prints function footer -static void idaapi mits_func_footer(outctx_t &ctx, func_t *pfn) -{ - qstring name; - if ( mits_get_func_name(&name, pfn) ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".ENDFUNC %s", SCOLOR_ASMDIR), name.begin()); -} - -static const asm_t mitsubishi_asm = -{ - AS_COLON - |ASH_HEXF0 // hex 123h format - |ASB_BINF0 // bin 10100011b format - |ASO_OCTF0 // oct 123o format - |AS_1TEXT, // 1 text per line, no bytes - UAS_END_WITHOUT_LABEL|UAS_DEVICE_DIR|UAS_BITMASK_LIST, - "Mitsubishi Macro Assembler for 7700 Family", - 0, - NULL, // no headers - ".ORG", // origin directive - ".END", // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".BYTE", // ascii string directive - ".BYTE", // byte directive - ".WORD", // word directive - ".DWORD", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".BLKB %s", // uninited arrays - ".EQU", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - mits_func_header, // func_header - mits_func_footer, // func_footer - ".PUB", // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - "SIZEOF", // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -// Supported assemblers -static const asm_t *const asms[] = { &mitsubishi_asm, &as_asm, NULL }; - -// Short and long name for our module -#define FAMILY "Mitsubishi 16-BIT 7700 family:" - -static const char *const shnames[] = -{ - "m7700", - "m7750", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Mitsubishi 16-BIT 7700 family", - "Mitsubishi 16-BIT 7700 family (7750 series)", - NULL -}; - -static const uchar retcode_1[] = { 0x40 }; // rti -static const uchar retcode_2[] = { 0x60 }; // rts -static const uchar retcode_3[] = { 0x6B }; // rtl - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } // NULL terminated array -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_M7700, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_BINMEM // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - | PR_SEGS // has segment registers? - | PR_SGROTHER, // the segment registers don't contain - // the segment selectors, something else - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rDR, rVds, - 2, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - 0, m7700_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - m7700_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/m7900/7900.hpp b/idasdk75/module/m7900/7900.hpp deleted file mode 100644 index ef4e902..0000000 --- a/idasdk75/module/m7900/7900.hpp +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#ifndef _MITSUBISHI7900_HPP -#define _MITSUBISHI7900_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <segregs.hpp> -#include "../iohandler.hpp" - -#define UAS_NOSPA 0x0001 // no space after comma -#define UAS_SEGM 0x0002 // segments are named "segment XXX" - - -// flags for insn.auxpref -// operand prefix -// 0x1 - .b -// 0x2 - .w -// 0x4 - .d - -#define INSN_PREF_U 0x0000 -#define INSN_PREF_B 0x0001 -#define INSN_PREF_W 0x0002 -#define INSN_PREF_D 0x0004 - -#define RAZOPER insn.auxpref - -//Detect status value -#define getFlag_M get_sreg(insn.ea, rfM) -#define getFlag_X get_sreg(insn.ea, rfX) - -#define getDT get_sreg(insn.ea, rDT) -#define getPG get_sreg(insn.ea, rPG) - -#define getDPReg get_sreg(insn.ea, rDPReg) - -#define getDPR0 get_sreg(insn.ea, rDPR0) -#define getDPR1 get_sreg(insn.ea, rDPR1) -#define getDPR2 get_sreg(insn.ea, rDPR2) -#define getDPR3 get_sreg(insn.ea, rDPR3) - - -//---------------------------------------------------------------------- -// Redefine temporary names -// - -#define xmode specflag1 -#define TypeOper specflag2 - -#define o_sr o_idpspec0 -#define o_ab o_idpspec1 -#define o_stk o_idpspec2 - - -// -// - -enum mitsubishi_bit_PUL { bPS, bb, bDT, bDPR0, bY, bX, bB, bA }; -// ======= mitsubishi_bit_CPU ======================================== -/* - __________________________ -|... |IPL|N|V|m|x|D|I|Z|C| - __________________________ -*/ - -// -// Bit 0: Carry flag (C) -// Bit 1: Zero flag (Z) -// Bit 2: Interrupt disable flag (I) -// Bit 3: Decimal mode flag (D) -// Bit 4: Index register length flag (x) -// Bit 5: Data length flag (m) -// Bit 6: Overflow flag (V) -// Bit 7: Negative flag (N) -// Bits 10 to 8: Processor interrupt priority level (IPL) -// -enum mitsubishi_bit_CPU { bIPL, bN, bV, bm, bx, bD, bI, bZ, bC }; - - -enum mitsubishi_registers { rA, rB, rE, rX, rY, rPC, - rPS, - rfIPL, rfN, rfV, rfD, rfI, rfZ, rfC, - rDT, rPG, rDPReg, rDPR0, rDPR1, rDPR2, rDPR3,rfM, rfX, - Rcs, Rds }; - - - - -/* - 15____________________0 - | Ah | AL | - Accumulator A - _____________________ -15____________________0 -| Bh | BL | - Accumulator B -| ____________________| - -31___________________________________________0 -| Eh | EL | - Accumulator E - _____________________________________________ - -15____________________0 -| Xh | XL | - Index registr X - _____________________ -15____________________0 -| Yh | YL | - Index registr Y - _____________________ - -15____________________0 -| Sh | SL | - Stack pointer S - _____________________ - -8_________0 -| DT | - Data bank registr(DT) - _________ - -23_________15___________________0 -| PG | PCh | PCl | - Program counter(PC) - _______________________________ - |_____________________________________________________ - Program bank registr()PG - -15____________________0 -| DPR0h | DPR0L | - Direct page registr 0(DPR0) - _____________________ -15____________________0 -| DPR1h | DPR1L | - Direct page registr 1(DPR1) - _____________________ -15____________________0 -| DPR2h | DPR2L | - Direct page registr 2(DPR2) - _____________________ -15____________________0 -| DPR3h | DPR3L | - Direct page registr 3(DPR3) - _____________________ -15____________________0 -| PSh | PS L | - Procesor status register(PS) - _____________________ -*/ - - - - - -enum eMode { IMM_8=0, IMM_16, IMM_32, DIR_32, DIR_16, DIR_8 }; - - -// TDIR_DIR - Direct addressing mode DIR -// TDIR_DIR_X - Direct index X addressing DIR,X -// TDIR_DIR_Y - Direct index Y addressing DIR,Y -// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR) -// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X) -// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y) -// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR) -// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y - -enum eTypeDIR { TDIR_DIR=0, TDIR_DIR_X, TDIR_DIR_Y, TDIR_INDIRECT_DIR, - TDIR_INDIRECT_DIR_X, TDIR_INDIRECT_DIR_Y, TDIR_L_INDIRECT_DIR, TDIR_L_INDIRECT_DIR_Y }; - - -// TSP_SP - Stack pointer relative addressing mode(SR) -// TSP_INDEX_SP_Y - Stack pointer relative indexed Y addressing mode((SR),Y) - -enum eTypeSP { TSP_SP=0, TSP_INDEX_SP_Y }; - - -// TAB_ABS - Absolute addressing mode(ABS) -// TAB_ABS_X - Absolute indexed X addressing mode(ABS,X) -// TAB_ABS_Y - Absolute indexed Y addressing mode(ABS,Y) -// TAB_ABL - Absolute long addressing mode(ABL) -// TAB_ABL_X - Absolute long indexed X addressing mode(ABS,X) -// TAB_INDIRECTED_ABS - Absolute indirect addressing mode((ABS)) -// TAB_L_INDIRECTED_ABS - Absolute indirect long addressing mode(L(ABS)) -// TAB_INDIRECTED_ABS_X - Absolute indexed X indirect addressing mode((ABS,X)) - -enum eTypeAB { TAB_ABS=0, TAB_ABS_X, TAB_ABS_Y, TAB_ABL, TAB_ABL_X, - TAB_INDIRECTED_ABS, TAB_L_INDIRECTED_ABS, TAB_INDIRECTED_ABS_X }; - - -//------------------------------------------------------------------------ -struct ioport_bit_t; -//------------------------------------------------------------------------ -int idaapi ana(insn_t *_insn); - -inline void TRACE1(const char *szStr) -{ - msg("%s\n", szStr); -} - - -inline void TRACE1(uint32 Data) -{ - msg("DATA - %X\n", Data); -} - - -inline void TRACE(const char * /*szStr*/) -{ -// msg("%s\n", szStr); -} - - -inline void TRACE(uint32 /*Data*/) -{ -// msg("DATA - %X\n", Data); -} - -inline int GETBIT(uval_t Data, int bit) -{ - uint32 TempByte = (uint32)Data; - return (TempByte>>bit)&0x01; -} - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct m7900_t); - -struct m7900_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - bool choose_device(); - - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - int emu(const insn_t &insn); - - void m7900_header(outctx_t &ctx); - void m7900_segstart(outctx_t &ctx, segment_t *Srange) const; - void m7900_footer(outctx_t &ctx) const; -}; -#endif - diff --git a/idasdk75/module/m7900/ana.cpp b/idasdk75/module/m7900/ana.cpp deleted file mode 100644 index 969efba..0000000 --- a/idasdk75/module/m7900/ana.cpp +++ /dev/null @@ -1,10078 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "7900.hpp" - -#define SetTypeDataM (getFlag_M ? dt_byte : dt_word) -#define SetTypeDataX (getFlag_X ? dt_byte : dt_word) - -//---------------------------------------------------------------------- -// reg - register -// -inline void Operand_Registr(op_t &x, uint16 rReg) -{ - x.type = o_reg; - x.reg = rReg; - //x.dtype = dt_word; // For A and B, for E need dt_dword -} - -//---------------------------------------------------------------------- -static void Operand_Imm_32(insn_t &insn, op_t &x) -{ - uint32 L_L = insn.get_next_byte(); - uint32 L_H = insn.get_next_byte(); - uint32 H_L = insn.get_next_byte(); - uint32 H_H = insn.get_next_byte(); - - uint32 data = ((L_L | (H_H<<24)) | (H_L << 16)) | (L_H<<8); - - x.type = o_imm; - x.value = data; - x.dtype = dt_dword; - x.xmode = IMM_32; - -} - -//---------------------------------------------------------------------- -static void Operand_Imm_16(insn_t &insn, op_t &x) -{ - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - uint32 data = high | (low<<8); - - x.type = o_imm; - x.value = data; - x.dtype = dt_word; - x.xmode = IMM_16; -} - -//---------------------------------------------------------------------- -static void Operand_Imm_8(insn_t &insn, op_t &x) -{ - uint32 high = insn.get_next_byte(); - - x.type = o_imm; - x.value = high; - x.dtype = dt_byte; - x.xmode = IMM_8; -} - -//---------------------------------------------------------------------- -// Raz - instruction bitness (8, 16, 32) -//---------------------------------------------------------------------- -static void Operand_Imm(insn_t &insn, op_t &x, int Raz) -{ - switch ( Raz ) - { - case 8: Operand_Imm_8(insn, x); break; - case 16: Operand_Imm_16(insn, x); break; - case 32: Operand_Imm_32(insn, x); break; - } -} - -//---------------------------------------------------------------------- -static void Operand_Imm_Spesh(op_t &x, uchar dtype, uint32 data) -{ - uchar type = 0; - - x.type = o_imm; - x.value = data; - x.dtype = dtype; - - if ( dtype == dt_byte ) - type= IMM_8; - - if ( dtype == dt_word ) - type= IMM_16; - - x.xmode = type; -} - -sel_t getDPR(const insn_t &insn, int iDPR) -{ - switch ( iDPR ) - { - case 0x0: return getDPR0; - case 0x40: return getDPR1; - case 0x80: return getDPR2; - case 0xC0: return getDPR3; - } - return 0; -} - -//---------------------------------------------------------------------- -// TypeDIR -// TDIR_DIR - Direct addressing mode DIR -// TDIR_DIR_X - Direct index X addressing DIR,X -// TDIR_DIR_Y - Direct index Y addressing DIR,Y -// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR) -// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X) -// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y) -// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR) -// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y -// -//---------------------------------------------------------------------- -inline void DIR(insn_t &insn, op_t &x, uchar TypeDir, char dtype) -{ - uint32 higth = insn.get_next_byte(); - - uint32 Addr; - if ( getDPReg == 1 ) - { - sel_t ValDPR = getDPR(insn, higth & 0xC0); - Addr = uint32(ValDPR + higth); - } - else - { - Addr = uint32(getDPR0 + higth); - } - x.type = o_mem; - x.addr = Addr; - x.dtype = dtype; - x.TypeOper = TypeDir; -} - -static void LDIR(insn_t &insn, op_t &x, uchar TypeDir, char dtype) -{ - uint32 higth = insn.get_next_byte(); - uint32 Addr; - if ( getDPReg == 1 ) - { - sel_t ValDPR = getDPR(insn, higth & 0xC0); - Addr = uint32(ValDPR + higth); - } - else - { - Addr = uint32(getDPR0 + higth); - } - - x.type = o_mem; - x.addr = Addr; - x.dtype = dtype; - x.TypeOper = TypeDir; -} - -//---------------------------------------------------------------------- -// TypeDIR -// TDIR_DIR - Direct addressing mode DIR -// TDIR_DIR_X - Direct index X addressing DIR,X -// TDIR_DIR_Y - Direct index Y addressing DIR,Y -// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR) -// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X) -// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y) -// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR) -// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y -// -// -// dtype - target data type for memory cell -//---------------------------------------------------------------------- -static void Operand_Dir(insn_t &insn, op_t &x, uchar TypeDir, char dtype = dt_word) -{ - switch ( TypeDir ) - { - case TDIR_DIR:// - Direct addressing mode DIR - DIR(insn, x, TypeDir, dtype); - break; - case TDIR_DIR_X:// - Direct index X addressing DIR,X - DIR(insn, x, TypeDir, dtype); - break; - case TDIR_DIR_Y:// - Direct index Y addressing DIR,Y - DIR(insn, x, TypeDir, dtype); - break; - case TDIR_INDIRECT_DIR:// - Direct indirect addressing mode (DIR) - LDIR(insn, x, TypeDir, dtype); - break; - case TDIR_INDIRECT_DIR_X:// - Direct index X indirect addressing mode (DIR,X) - LDIR(insn, x, TypeDir, dtype); - break; - case TDIR_INDIRECT_DIR_Y:// - Direct index Y indirect addressing mode (DIR,Y) - LDIR(insn, x, TypeDir, dtype); - break; - case TDIR_L_INDIRECT_DIR:// - Direct indirect long addressing mode L(DIR) - LDIR(insn, x, TypeDir, dtype); - break; - case TDIR_L_INDIRECT_DIR_Y:// - Direct indirect long indexed Y addressing mode L(DIR),Y - LDIR(insn, x, TypeDir, dtype); - break; - } -} - -//---------------------------------------------------------------------- -static void Operand_SR_16(insn_t &insn, op_t &x, uchar Type) -{ - uint32 data = insn.get_next_byte(); - - x.type = o_sr; - x.value = data; - x.dtype = dt_word; - x.TypeOper = Type; -} - -//---------------------------------------------------------------------- -static void Operand_SR_8(insn_t &insn, op_t &x, uchar Type) -{ - uint32 data = insn.get_next_byte(); - - x.type = o_sr; - x.value = data; - x.dtype = dt_byte; - x.TypeOper = Type; -} - -//---------------------------------------------------------------------- -static void Operand_SR(insn_t &insn, op_t &x, uchar TypeDir, int Raz) -{ - switch ( Raz ) - { - case 8: Operand_SR_8(insn, x, TypeDir); break; - case 16: Operand_SR_16(insn, x, TypeDir); break; - } -} - -//---------------------------------------------------------------------- -static void ABS(insn_t &insn, op_t &x, uchar Type, sel_t gDT, char dtype) -{ - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - uint32 data = high | (low<<8); - - data = uint32(data | (gDT<<16)); - - x.type = o_ab; - x.addr = data; - x.dtype = dtype; - x.TypeOper = Type; -} - -//---------------------------------------------------------------------- -static void ABL(insn_t &insn, op_t &x, uchar Type, char dtype) -{ - uint32 ll = insn.get_next_byte(); - uint32 mm = insn.get_next_byte(); - uint32 hh = insn.get_next_byte(); - - uint32 data = (ll | (hh<<16)) | (mm<<8); - - x.type = o_ab; - x.addr = data; - x.dtype = dtype; - x.TypeOper = Type; -} - -//---------------------------------------------------------------------- -static void Indirect_ABS(insn_t &insn, op_t &x, uchar Type, sel_t /*gPG*/, char dtype) -{ - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - - uint32 addr = high | (low<<8); - - // This looks like a bug, FIXME! - /*uint32 Addr =*/ get_word(addr); - //Addr = uint32(Addr | (gPG<<16)); - - x.type = o_ab; - x.addr = addr; - x.dtype = dtype; - x.TypeOper = Type; -} - -//---------------------------------------------------------------------- -static void Operand_AB(insn_t &insn, op_t &x, uchar TypeDir, int /*Raz*/, char dtype = dt_word) -{ - switch ( TypeDir ) - { - case TAB_ABS: // - Absolute addressing mode(ABS) - ABS(insn, x, TypeDir, getDT, dtype); - break; - - case TAB_ABS_X:// - Absolute indexed X addressing mode(ABS,X) - ABS(insn, x, TypeDir, getDT, dtype); - break; - - case TAB_ABS_Y:// - Absolute indexed Y addressing mode(ABS,Y) - ABS(insn, x, TypeDir, getDT, dtype); - break; - - case TAB_ABL: // - Absolute long addressing mode(ABL) - ABL(insn, x, TypeDir, dtype); - break; - case TAB_ABL_X:// - Absolute long indexed X addressing mode(ABS,X) - ABL(insn, x, TypeDir, dtype); - break; - - case TAB_INDIRECTED_ABS:// - Absolute indirect addressing mode((ABS)) - Indirect_ABS(insn, x, TypeDir, getPG, dtype);//??? - break; - - case TAB_L_INDIRECTED_ABS:// - Absolute indirect long addressing mode(L(ABS)) - Indirect_ABS(insn, x, TypeDir, getPG, dtype);//??? - break; - - case TAB_INDIRECTED_ABS_X:// - Absolute indexed X indirect addressing mode((ABS,X)) - Indirect_ABS(insn, x, TypeDir, getPG, dtype);//??? - break; - } -} - -//---------------------------------------------------------------------- -static void Bral(insn_t &insn, op_t &x, int del) -{ - x.type = o_near; - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - uint32 addr = high | (low<<8); - - x.addr = insn.ip + (signed short)addr + del; -} - -//---------------------------------------------------------------------- -inline void Operand_BSR(const insn_t &insn, op_t &x, uint32 addr, int del) -{ - x.type = o_near; - x.addr = insn.ip + (int32)addr + del; -} - -//---------------------------------------------------------------------- -inline void Operand_BBC(const insn_t &insn, op_t &x, uchar addr, int del) -{ - x.type = o_near; - x.addr = insn.ip + (signed char)addr + del; -} - -//---------------------------------------------------------------------- -inline void Operand_BBS(const insn_t &insn, op_t &x, uchar addr, int del) -{ - Operand_BBC(insn, x, addr, del); -} - -//---------------------------------------------------------------------- -inline void Operand_DEBNE(const insn_t &insn, op_t &x, uchar addr, int del) -{ - x.type = o_near; - x.addr = insn.ip + (signed char)addr + del; -} - -//---------------------------------------------------------------------- -inline void Operand_Near(const insn_t &insn, op_t &x, uchar addr, int del) -{ - x.type = o_near; - x.addr = insn.ip + (signed char)addr + del; -} - -//---------------------------------------------------------------------- -inline void Operand_IMP(op_t & /*x*/) -{ -} - -//---------------------------------------------------------------------- -static void Jsr_24(insn_t &insn, op_t &x) -{ - x.type = o_near; - - uint32 ll = insn.get_next_byte(); - uint32 mm = insn.get_next_byte(); - uint32 hh = insn.get_next_byte(); - - uint32 data = (ll | (hh<<16)) | (mm<<8); - - x.addr = data; - x.dtype = dt_dword; -} - -//---------------------------------------------------------------------- -static void Jsr_16(insn_t &insn, op_t &x, sel_t gPG) -{ - x.type = o_near; - - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - uint32 data = high | (low<<8); - data = uint32(data | (gPG<<16)); - - x.addr = data; - x.dtype = dt_word; -} - -//---------------------------------------------------------------------- -// dt_byte -// dt_word -// dt_dword -//---------------------------------------------------------------------- -static void Operand_STK_16(insn_t &insn, op_t &x, uchar dtype) -{ - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - uint32 data = high | (low<<8); - - x.type = o_stk; - x.value = data; - x.dtype = dtype; - x.xmode = IMM_16; -} - -//---------------------------------------------------------------------- -// dt_byte -// dt_word -// dt_dword -//---------------------------------------------------------------------- -inline void Operand_STK_8(insn_t &insn, op_t &x, uchar dt_type) -{ - uint32 high = insn.get_next_byte(); - - x.type = o_stk; - x.value = high; - x.dtype = dt_type; - x.xmode = IMM_8; -} - -//---------------------------------------------------------------------- -inline void Operand_STK(insn_t &insn, op_t &x, int Razr) -{ - switch ( Razr ) - { - case 8: Operand_STK_8(insn, x, dt_byte); break; - case 16: Operand_STK_16(insn, x, dt_word); break; - } -} - -//---------------------------------------------------------------------- -static void Branch(insn_t &insn, op_t &x, int cd) -{ - static const uchar icode[] = - { - 0, //0 - m7900_bpl, //1 - m7900_bra, //2 - m7900_bmi, //3 - m7900_bgtu, //4 - m7900_bvc, //5 - m7900_bleu, //6 - m7900_bvs, //7 - m7900_bgt, //8 - m7900_bcc, //9 - m7900_ble, //a - m7900_bcs, //b - m7900_bge, //c - m7900_bne, //d - m7900_blt, //e - m7900_beq //F - }; - //0x1://bmi (REL) - //0x2://bra (REL) - //0x3://bmi (REL) - //0x4://bgtu (REL) - //0x5://bvc (REL) - //0x6://bleu (REL) - //0x7://bvs (REL) - //0x8://bcc (REL) - //0x9://bcc (REL) - //0xA://ble (REL) - //0xB://bcs (REL) - //0xC://bge (REL) - //0xD://bne (REL) - //0xE://blt (REL) - //0xF://beq (REL) - - insn.itype = icode[ cd ]; - Operand_Near(insn, x, insn.get_next_byte(), 2); -} - -//---------------------------------------------------------------------- -int Opcode_91(insn_t &insn) -{ - TRACE("Opcode_91"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - //________________________ ADD________________________ - //101 - ADd - //add B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 20 dd] - case 0x20: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //101 - ADd - //add B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 21 dd] - case 0x21: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //101 - ADd - //add B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[91 28 dd] - case 0x28: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 22 dd] - case 0x22: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //101 - ADd - //add B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 29 dd] - case 0x29: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - // Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, 8, SetTypeDataM); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 23 nn] - case 0x23: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //101 - ADd - //add B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 24 nn] - case 0x24: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 26 ll mm] - case 0x26: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[91 2C ll mm hh] - case 0x2C: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //101 - ADd - //add B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[91 2D ll mm hh] - case 0x2D: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //______________________ END ADD _____________________ - //________________________ CMP________________________ - //161 - CoMPare - //cmp B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 40 dd] - case 0x40: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //161 - CoMPare - //cmp B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 41 dd] - case 0x41: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //161 - CoMPare - //cmp B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[91 48 dd] - case 0x48: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 42 dd] - case 0x42: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //161 - CoMPare - //cmp B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 49 dd] - case 0x49: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 43 nn] - case 0x43: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //161 - CoMPare - //cmp B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 44 nn] - case 0x44: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 46 ll mm] - case 0x46: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[91 4C ll mm hh] - case 0x4C: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //161 - CoMPare - //cmp B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[91 4D ll mm hh] - case 0x4D: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END CMP _____________________ - - //________________________ AND________________________ - //111 - logical AND - //and B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 60 dd] - case 0x60: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //111 - logical AND - //and B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 61 dd] - case 0x61: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //111 - logical AND - //and B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[91 68 dd] - case 0x68: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 62 dd] - case 0x62: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //111 - logical AND - //and B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 69 dd] - case 0x69: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 63 nn] - case 0x63: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //111 - logical AND - //and B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 64 nn] - case 0x64: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 66 ll mm] - case 0x66: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[91 6C ll mm hh] - case 0x6C: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //111 - logical AND - //and B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[91 6D ll mm hh] - case 0x6D: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END AND _____________________ - //________________________ EOR________________________ - //180 - Exclusive OR memory with accumulator - //eor B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 70 dd] - case 0x70: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 71 dd] - case 0x71: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[91 78 dd] - case 0x78: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 72 dd] - case 0x72: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 79 dd] - case 0x79: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 73 nn] - case 0x73: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 74 nn] - case 0x74: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 76 ll mm] - case 0x76: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[91 7C ll mm hh] - case 0x7C: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[91 7D ll mm hh] - case 0x7D: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END eor _____________________ - - //___________________ LDA _________________________ - //195 - LoaD Accumulator from memory - //lda B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 10 dd] - case 0x10: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 11 dd] - case 0x11: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 12 dd] - case 0x12: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //195 - LoaD Accumulator from memory - //lda B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 13 nn] - case 0x13: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //195 - LoaD Accumulator from memory - //lda B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 14 nn] - case 0x14: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //195 - LoaD Accumulator from memory - //lda B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 16 ll mm] - case 0x16: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END LDA ____________________ - - //___________________ LDAB _________________________ - //196 - LoaD Accumulator from memory at Byte - //ldab B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 00 dd] - case 0x00: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 01 dd] - case 0x01: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 02 dd] - case 0x02: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 03 nn] - case 0x03: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 04 nn] - case 0x04: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 06 ll mm] - case 0x06: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END LDAB ____________________ - - //___________________ STA _________________________ - //271 - STore Accumulator in memory - //sta B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 D0 dd] - case 0xD0: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 D1 dd] - case 0xD1: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 D2 dd] - case 0xD2: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_byte); - break; - - //271 - STore Accumulator in memory - //sta B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 D3 nn] - case 0xD3: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //271 - STore Accumulator in memory - //sta B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 D4 nn] - case 0xD4: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //271 - STore Accumulator in memory - //sta B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 D6 ll mm] - case 0xD6: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END STA ____________________ - //_____________________ STAB ____________________ - //272 - STore Accumulator in memory at Byte - //stab B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 C0 dd] - case 0xC0: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 C1 dd] - case 0xC1: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 C2 dd] - case 0xC2: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 C3 nn] - case 0xC3: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 C4 nn] - case 0xC4: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 C6 ll mm] - case 0xC6: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END STAB ____________________ - - //________________________ ORA________________________ - //220 - OR memory with Accumulator - //ora B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 50 dd] - case 0x50: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 51 dd] - case 0x51: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[91 58 dd] - case 0x58: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 52 dd] - case 0x52: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //220 - OR memory with Accumulator - //ora B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 59 dd] - case 0x59: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 53 nn] - case 0x53: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //220 - OR memory with Accumulator - //ora B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 54 nn] - case 0x54: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 56 ll mm] - case 0x56: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[91 5C ll mm hh] - case 0x5C: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //ora B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[91 5D ll mm hh] - case 0x5D: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END ora _____________________ - - //________________________ SUB________________________ - //278 - SUBtract - //sub B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[91 30 dd] - case 0x30: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //278 - SUBtract - //sub B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[91 31 dd] - case 0x31: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //278 - SUBtract - //sub B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[91 38 dd] - case 0x38: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 32 dd] - case 0x32: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //278 - SUBtract - //sub B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[91 39 dd] - case 0x39: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[91 33 nn] - case 0x33: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //278 - SUBtract - //sub B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[91 34 nn] - case 0x34: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[91 36 ll mm] - case 0x36: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[91 3C ll mm hh] - case 0x3C: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //278 - SUBtract - //sub B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[91 3D ll mm hh] - case 0x3D: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END SUB _____________________ - - default: - return 0; - - } - return insn.size; -} - -//-------------------------------------------------------------------------------------------- -static int Opcode_21(insn_t &insn) -{ - TRACE("Opcode_21"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - //___________________ ADC _________________________ - //96 - ADd with Carry - //adc A, dd - //Operation data length: 16 bits or 8 bits - //[21 8A dd] - case 0x8A: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 8B dd] - case 0x8B: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //96 - ADd with Carry - //adc A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 80 dd] - case 0x80: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 81 dd] - case 0x81: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 88 dd] - case 0x88: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 82 dd] - case 0x82: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //96 - ADd with Carry - //adc A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 89 dd] - case 0x89: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 83 nn] - case 0x83: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //96 - ADd with Carry - //adc A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 84 nn] - case 0x84: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 8E ll mm] - case 0x8E: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16,SetTypeDataM); - break; - - //96 - ADd with Carry - //adc A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 8F ll mm] - case 0x8F: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //96 - ADd with Carry - //adc A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 86 ll mm] - case 0x86: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 8C ll mm hh] - case 0x8C: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 8D ll mm hh] - case 0x8D: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END ADC _________________________ - - //___________________ LSR _________________________ - //204 - Logical Shift Right - //lsr dd - //Operation data length: 16 bits or 8 bits - //[21 2A dd] - case 0x2A: - insn.itype = m7900_lsr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //204 - Logical Shift Right - //lsr dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 2B dd] - case 0x2B: - insn.itype = m7900_lsr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //204 - Logical Shift Right - //lsr mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 2E ll mm] - case 0x2E: - insn.itype = m7900_lsr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //204 - Logical Shift Right - //lsr mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 2F ll mm] - case 0x2F: - insn.itype = m7900_lsr; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END LSR _________________________ - - //___________________ ROL _________________________ - //254 - ROtate one bit Left - //rol dd - //Operation data length: 16 bits or 8 bits - //[21 1A dd] - case 0x1A: - insn.itype = m7900_rol; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //254 - ROtate one bit Left - //rol dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 1B dd] - case 0x1B: - insn.itype = m7900_rol; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //254 - ROtate one bit Left - //rol mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 1E ll mm] - case 0x1E: - insn.itype = m7900_rol; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //254 - ROtate one bit Left - //rol mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 1F ll mm] - case 0x1F: - insn.itype = m7900_rol; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END ROL _________________________ - //___________________ ROR _________________________ - //255 - ROtate one bit Right - //rol dd - //Operation data length: 16 bits or 8 bits - //[21 3A dd] - case 0x3A: - insn.itype = m7900_ror; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //255 - ROtate one bit Right - //rol dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 3B dd] - case 0x3B: - insn.itype = m7900_ror; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //255 - ROtate one bit Right - //ror mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 3E ll mm] - case 0x3E: - insn.itype = m7900_ror; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //255 - ROtate one bit Right - //ror mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 3F ll mm] - case 0x3F: - insn.itype = m7900_ror; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END ROR _________________________ - - //___________________ ASL _________________________ - - //116 - Arithmetic Shift to Left - //asl dd - //Operation data length: 16 bits or 8 bits - //[21 0A dd] - case 0x0A: - insn.itype = m7900_asl; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //116 - Arithmetic Shift to Left - //asl dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 0B dd] - case 0x0B: - insn.itype = m7900_asl; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //116 - Arithmetic Shift to Left - //asl mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 0E ll mm] - case 0x0E: - insn.itype = m7900_asl; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //116 - Arithmetic Shift to Left - //asl mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 0F ll mm] - case 0x0F: - insn.itype = m7900_asl; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END ASL _________________________ - - //___________________ ASR _________________________ - - //119 - Arithmetic Shift to Right - //asr dd - //Operation data length: 16 bits or 8 bits - //[21 4A dd] - case 0x4A: - insn.itype = m7900_asr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //119 - Arithmetic Shift to Right - //asr dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 4B dd] - case 0x4B: - insn.itype = m7900_asr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //119 - Arithmetic Shift to Right - //asr mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 4E ll mm] - case 0x4E: - insn.itype = m7900_asr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //119 - Arithmetic Shift to Right - //asr mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 4F ll mm] - case 0x4F: - insn.itype = m7900_asr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END ASR _________________________ - - //___________________ ADCD _________________________ - - //99 - ADd with Carry at Double-word - //adcd E, dd - //Operation data length: 32 bits - //[21 9A dd] - case 0x9A: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //99 - ADd with Carry at Double-word - //adcd E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 32 - //[21 9B dd] - case 0x9B: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //99 - ADd with Carry at Double-word - //adcd E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 32 bits - //[21 90 dd] - case 0x90: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //99 - ADd with Carry at Double-word - //adcd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 32 buts - //[21 91 dd] - case 0x91: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //99 - ADd with Carry at Double-word - //adcd E, (dd), Y () - //Operation data length: 32 bits - //[21 98 dd] - case 0x98: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //99 - ADd with Carry at Double-word - //adcd E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[21 92 dd] - case 0x92: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - - // should collect 3 bytes, but collect as 2 bytes - // can use dt_tbyte - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //99 - ADd with Carry at Double-word - //adcd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[21 99 dd] - case 0x99: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - // should collect 3 bytes, but collect as 2 bytes - // can use dt_tbyte - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //99 - ADd with Carry at Double-word - //adcd E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 32 bits - //[21 93 nn] - case 0x93: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //99 - ADd with Carry at Double-word - //adcd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 32 bits - //[21 94 nn] - case 0x94: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //99 - ADd with Carry at Double-word - //adcd E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[21 9E ll mm] - case 0x9E: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //99 - ADd with Carry at Double-word - //adcd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[21 9F ll mm] - case 0x9F: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //99 - ADd with Carry at Double-word - //adcd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 32 bits - //[21 96 ll mm] - case 0x96: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //99 - ADd with Carry at Double-word - //adcd E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 9C ll mm hh] - case 0x9C: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //99 - ADd with Carry at Double-word - //adcd A, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[21 9D ll mm hh] - case 0x9D: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END ADCD _________________________ - - //___________________ DIV _________________________ - //174 - DIVide unsigned - //div A, dd - //Operation data length: 16 bits or 8 bits - //[21 EA dd] - case 0xEA: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //174 - DIVide unsigned - //div A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 EB dd] - case 0xEB: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //174 - DIVide unsigned - //div A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 E0 dd] - case 0xE0: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //174 - DIVide unsigned - //div A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 E1 dd] - case 0xE1: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //174 - DIVide unsigned - //div A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 E8 dd] - case 0xE8: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //174 - DIVide unsigned - //div A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 E2 dd] - case 0xE2: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //174 - DIVide unsigned - //div A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 E9 dd] - case 0xE9: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op2, rY); - break; - - //174 - DIVide unsigned - //div A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 E3 nn] - case 0xE3: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_SP, 8); - Operand_Registr(insn.Op2, rPS); - break; - - //174 - DIVide unsigned - //div A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 E4 nn] - case 0xE4: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op2, rY); - break; - - //174 - DIVide unsigned - //div A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 EE ll mm] - case 0xEE: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //174 - DIVide unsigned - //div A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 EF ll mm] - case 0xEF: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //174 - DIVide unsigned - //div A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 E6 ll mm] - case 0xE6: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //174 - DIVide unsigned - //div A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 EC ll mm hh] - case 0xEC: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); - break; - - //174 - DIVide unsigned - //div A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 ED ll mm hh] - case 0xED: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END DIV _________________________ - //___________________ DIVS _________________________ - //176 - DIVide with Sign - //divs A, dd - //Operation data length: 16 bits or 8 bits - //[21 FA dd] - case 0xFA: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //176 - DIVide with Sign - //divs A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 FB dd] - case 0xFB: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //176 - DIVide with Sign - //divs A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 F0 dd] - case 0xF0: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //176 - DIVide with Sign - //divs A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 F1 dd] - case 0xF1: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //176 - DIVide with Sign - //divs A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 F8 dd] - case 0xF8: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //176 - DIVide with Sign - //divs A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 F2 dd] - case 0xF2: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //176 - DIVide with Sign - //divs A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 F9 dd] - case 0xF9: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op2, rY); - break; - - //176 - DIVide with Sign - //divs A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 F3 nn] - case 0xF3: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_SP, 8); - Operand_Registr(insn.Op2, rPS); - break; - - //176 - DIVide with Sign - //divs A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 F4 nn] - case 0xF4: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op2, rY); - break; - - //176 - DIVide with Sign - //divs A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 FE ll mm] - case 0xFE: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //176 - DIVide with Sign - //divs A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 FF ll mm] - case 0xFF: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //176 - DIVide with Sign - //divs A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 F6 ll mm] - case 0xF6: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //176 - DIVide with Sign - //divs A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 FC ll mm hh] - case 0xFC: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); - break; - - //176 - DIVide with Sign - //divs A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 FD ll mm hh] - case 0xFD: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END DIVS _________________________ - - //___________________ MPY _________________________ - //212 - MultiPlY - //Operation data length: 16 bits or 8 bits - //[21 CA dd] - case 0xCA: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //212 - MultiPlY - //mpy dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 CB dd] - case 0xCB: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //212 - MultiPlY - //mpy (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 C0 dd] - case 0xC0: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //212 - MultiPlY - //mpy (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 C1 dd] - case 0xC1: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //212 - MultiPlY - //mpy (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 C8 dd] - case 0xC8: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //212 - MultiPlY - //mpy L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 C2 dd] - case 0xC2: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //212 - MultiPlY - //mpy L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 C9 dd] - case 0xC9: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op2, rY); - break; - - //212 - MultiPlY - //mpy nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 C3 nn] - case 0xC3: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_SP, 8); - Operand_Registr(insn.Op2, rPS); - break; - - //212 - MultiPlY - //mpy (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 C4 nn] - case 0xC4: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op2, rY); - break; - - //212 - MultiPlY - //mpy mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 CE ll mm] - case 0xCE: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //212 - MultiPlY - //mpy mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 CF ll mm] - case 0xCF: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //212 - MultiPlY - //mpy A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 C6 ll mm] - case 0xC6: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //212 - MultiPlY - //mpy hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 CC ll mm hh] - case 0xCC: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); - break; - - //212 - MultiPlY - //mpy hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 CD ll mm hh] - case 0xCD: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END MPY _________________________ - //___________________ MPYS _________________________ - //213 - MultiPlY with Sign - //Operation data length: 16 bits or 8 bits - //[21 DA dd] - case 0xDA: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //213 - MultiPlY with Sign - //mpys dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 DB dd] - case 0xDB: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //213 - MultiPlY with Sign - //mpys (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 D0 dd] - case 0xD0: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //213 - MultiPlY with Sign - //mpys (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 D1 dd] - case 0xD1: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //213 - MultiPlY with Sign - //mpys (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 D8 dd] - case 0xD8: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //213 - MultiPlY with Sign - //mpys L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 D2 dd] - case 0xD2: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //213 - MultiPlY with Sign - //mpys L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 D9 dd] - case 0xD9: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op2, rY); - break; - - //213 - MultiPlY with Sign - //mpys nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 D3 nn] - case 0xD3: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_SP, 8); - Operand_Registr(insn.Op2, rPS); - break; - - //213 - MultiPlY with Sign - //mpys (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 D4 nn] - case 0xD4: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op2, rY); - break; - - //213 - MultiPlY with Sign - //mpys mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 DE ll mm] - case 0xDE: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //213 - MultiPlY with Sign - //mpys mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 DF ll mm] - case 0xDF: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //213 - MultiPlY with Sign - //mpys A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 D6 ll mm] - case 0xD6: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - - //213 - MultiPlY with Sign - //mpys hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 DC ll mm hh] - case 0xDC: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); - break; - - //213 - MultiPlY with Sign - //mpys hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 DD ll mm hh] - case 0xDD: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //___________________ END MPYS _________________________ - - //___________________ SBC _________________________ - //264 - SuBtract with Carry - //sbc A, dd - //Operation data length: 16 bits or 8 bits - //[21 AA dd] - case 0xAA: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 AB dd] - case 0xAB: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //264 - SuBtract with Carry - //sbc A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 A0 dd] - case 0xA0: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 A1 dd] - case 0xA1: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 A8 dd] - case 0xA8: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 A2 dd] - case 0xA2: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //264 - SuBtract with Carry - //sbc A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 A9 dd] - case 0xA9: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 A3 nn] - case 0xA3: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //264 - SuBtract with Carry - //sbc A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 A4 nn] - case 0xA4: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 AE ll mm] - case 0xAE: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 AF ll mm] - case 0xAF: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //264 - SuBtract with Carry - //sbc A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 A6 ll mm] - case 0xA6: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 AC ll mm hh] - case 0xAC: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 AD ll mm hh] - case 0xAD: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END sbc _________________________ - - //___________________ SBCD _________________________ - //266 - SuBtract with Carry at Double-word - //sbcd E, dd - //Operation data length: 16 bits or 8 bits - //[21 BA dd] - case 0xBA: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 BB dd] - case 0xBB: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 B0 dd] - case 0xB0: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 B1 dd] - case 0xB1: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 B8 dd] - case 0xB8: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 B2 dd] - case 0xB2: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 B9 dd] - case 0xB9: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 B3 nn] - case 0xB3: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 B4 nn] - case 0xB4: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd BE mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 BE ll mm] - case 0xBE: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 BF ll mm] - case 0xBF: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 B6 ll mm] - case 0xB6: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 BC ll mm hh] - case 0xBC: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 BD ll mm hh] - case 0xBD: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END SBCD _________________________ - - default: - return 0; - } - - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_31(insn_t &insn) -{ - TRACE("Opcode_31"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - uchar nib = (code >> 4) & 0xF; - - switch ( code ) - { - - //_____________________ JMPJMPL ____________________ - //192 - JuMP - //jmp (mmll) - //Operation data - - //[31 5C ll mm] - case 0x5C:// jmp (mmll) ((ABS)) - insn.itype = m7900_jmp; - Operand_AB(insn, insn.Op1, TAB_INDIRECTED_ABS, 16, dt_word); - break; - - //192 - JuMP - //jmp L(mmll) - //Operation data - - //[31 5D ll mm] - case 0x5D:// jmp L(mmll) (L(ABS)) - insn.itype = m7900_jmp; - Operand_AB(insn, insn.Op1, TAB_L_INDIRECTED_ABS, 16, dt_tbyte); - break; - //_____________________ END JMP/JMPL ____________________ - - //232 - PusH proGram bank register on stack - //phg - //Operation data length: 8 bits - //[31 60] - case 0x60: - insn.itype = m7900_phg; - RAZOPER = INSN_PREF_U; - break; - - //235 - - //pht - //Operation data length: 8 bits - //[31 40] - case 0x40: - insn.itype = m7900_pht; - RAZOPER = INSN_PREF_U; - break; - - //243 - PuLl daTa bank register from stack - //plt - //Operation data length: 8 bits - //[31 50] - case 0x50: - insn.itype = m7900_plt; - RAZOPER = INSN_PREF_U; - break; - - //96 - ADd with Carry - //adc A, #imm - //Operation data length: 16 bits or 8 bits - //[31 87 imm] - case 0x87: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //274 - - //stp - //Operation data length: - - //[31 30] - case 0x30: - insn.itype = m7900_stp; - break; - - //284 - SUBtract Stack pointer - //subs #imm - //Operation data length: 16 bits - //[31 0B imm] - case 0x0B: - insn.itype = m7900_subs; - RAZOPER = INSN_PREF_W; - Operand_Imm(insn, insn.Op1, 8); - break; - - //288 - Transfer accumulator A to Stack pointer - //tas - //Operation data length: 16 bits - //[31 82] - case 0x82: - insn.itype = m7900_tas; - break; - - //297 - Transfer Direct page register to Stack pointer - //tds - //Operation data length: 16 bits - //[31 73] - case 0x73: - insn.itype = m7900_tds; - break; - - //298- Transfer Stack pointer to accumulator A - //tsa - //Operation data length: 16 bits or 8 bit - //[31 92] - case 0x92: - insn.itype = m7900_tsa; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - //300- Transfer Stack pointer to Direct page register - //tsd - //Operation data length: 16 bits - //[31 70] - case 0x70: - insn.itype = m7900_tsd; - break; - - //301- Transfer Stack pointer to index register X - //tsx - //Operation data length: 16 bits or 8 bits - //[31 F2] - case 0xF2: - insn.itype = m7900_tsx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - //304- Transfer index register X to Stack pointer - //txs - //Operation data length: 16 bits or 8 bits - //[31 E2] - case 0xE2: - insn.itype = m7900_txs; - break; - - //305- Transfer index register X to Y - //txy - //Operation data length: 16 bits or 8 bits - //[31 C2] - case 0xC2: - insn.itype = m7900_txy; - break; - - //308- Transfer index register Y to X - //tyx - //Operation data length: 16 bits or 8 bits - //[31 D2] - case 0xD2: - insn.itype = m7900_tyx; - break; - - //309- WaIT - //wit - //Operation data length: 16 bits or 8 bits - //[31 10] - case 0x10: - insn.itype = m7900_wit; - break; - - //---------------------------BYTE-------------------------------------// - //98 - ADd with Carry at Byte - //adcb A, #imm - //Operation data length: 8 bits - //[31 1A imm] - case 0x1A: - insn.itype = m7900_adcb; - RAZOPER = 8; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //199 - LoaD immediate to DaTa bank register - //ldt A, #imm - //Operation data length: 8 bits - //[31 4A imm] - case 0x4A: - insn.itype = m7900_ldt; - RAZOPER = INSN_PREF_U; - Operand_Imm(insn, insn.Op1, 8); - break; - - //208 - MOVe Memory to memory at Byte - //movmb mmll, #imm - //Operation data length: 8 bits - //[3B imm ll mm] - case 0x3B: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Imm(insn, insn.Op3, 8); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Registr(insn.Op2, rX); - break; - - //208 - MOVe Memory to memory at Byte - //movmb dd, #imm - //Operation data length: 8 bits - //[3A imm dd] - case 0x3A: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op3, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - Operand_Registr(insn.Op2, rX); - break; - - //265 - SuBtract with Carry at Byte - //sbcb A, #imm - //Operation data length: 8 bits - //[31 1B imm] - case 0x1B: - insn.itype = m7900_sbcb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //---------------------------WORD------------------------------------// - - //107 - ADD Stack pointer and immediate - //adds #imm - //Operation data length: 16 bits - //[31 0A imm] - case 0x0A: - insn.itype = m7900_adds; - RAZOPER = INSN_PREF_W; - Operand_Imm(insn, insn.Op1, 8); - break; - - //---------------------------DWORD------------------------------------// - - //95 - ABSolute at Double-word - //absd E - //Operation data length: 32 bits - //[31 90] - case 0x90: - insn.itype = m7900_absd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - break; - - //186 - EXTension Sign at Double-word - //extsd E - //Operation data length: 32 bits - //[31 B0] - case 0xB0://extsd - insn.itype = m7900_extsd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - break; - - //188 - EXTension Zero at Double-word - //extzd E - //Operation data length: 32 bits - //[31 A0] - case 0xA0://extsd - insn.itype = m7900_extzd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - break; - - //99 - ADd with Carry at Double-word - //adcd E, #imm - //Operation data length: 32 bits - //[31 1C imm imm imm imm] - case 0x1C: - insn.itype = m7900_adcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm(insn, insn.Op2, 32); - break; - - //217 - NEGative at Double-word - //negd E - //Operation data length: 32 bits - //[31 80] - case 0x80: - insn.itype = m7900_negd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - break; - - //266 - SuBtract with Carry at Double-word - //sbcd E - //Operation data length: 32 bits - //[31 1D] - case 0x1D: - insn.itype = m7900_sbcd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm(insn, insn.Op2, 32); - break; - - //---------------------------WORD/byte------------------------------------// - - //174 - DIVide unsigned - //div #imm - //Operation data length: 16 bits or 8 bits - //[31 E7 imm] - case 0xE7: - insn.itype = m7900_div; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - break; - - //174 - DIVide with Sign - //divs #imm - //Operation data length: 16 bits or 8 bits - //[31 F7 imm] - case 0xF7: - insn.itype = m7900_divs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - break; - - //207 - MOVe Memory to memory - //movm mmll, X, #imm - //Operation data length: 16 bits or 8 bits - //[31 57 imm] - case 0x57: - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op3, getFlag_M ? 8 : 16); - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //207 - MOVe Memory to memory - //movm #imm dd - //Operation data length: 16 bits or 8 bits - //[31 47 imm] - case 0x47: - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op3, getFlag_M ? 8 : 16); - Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - //_____________________ MPY ____________________ - //212 - MultiPlY - //MPY #imm - //Operation data - 16 bits or 8 bits - //[31 C7 imm] - case 0xC7: - insn.itype = m7900_mpy; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - break; - //_____________________ END MPY ____________________ - - //_____________________ MPYS ____________________ - //213 - MultiPlY - //MPYS #imm - //Operation data - 16 bits or 8 bits - //[31 D7 imm] - case 0xD7: - insn.itype = m7900_mpys; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - break; - //_____________________ END MPY ____________________ - //_____________________ MVN ____________________ - //214 - MoVe Negative - //mvn hh1 hh2 - //Operation data - 16 bits or 8 bits - //[31 2B hh1 hh2] - case 0x2B: - insn.itype = m7900_mvn; - Operand_Dir(insn, insn.Op1, TDIR_DIR); - Operand_Dir(insn, insn.Op2, TDIR_DIR); - break; - //_____________________ END MVN ____________________ - - //_____________________ MVP ____________________ - //215 - MoVe Positive - //mvp hh1 hh2 - //Operation data - 16 bits or 8 bits - //[31 2A hh1 hh2] - case 0x2A: - insn.itype = m7900_mvp; - Operand_Dir(insn, insn.Op1, TDIR_DIR); - Operand_Dir(insn, insn.Op2, TDIR_DIR); - break; - //_____________________ END MVP ____________________ - - case 0x4B://pei - insn.itype = m7900_pei; - RAZOPER = INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR); - break; - - case 0x4C://pea - insn.itype = m7900_pea; - RAZOPER = INSN_PREF_W; - Operand_STK(insn, insn.Op1, 16); - break; - - case 0x4D://per - insn.itype = m7900_per; - RAZOPER = INSN_PREF_W; - Operand_STK(insn, insn.Op1, 16); - break; - - //_____________________ RLA ____________________ - //250 - Rotate Left accumulator A - //RLA #imm - //Operation data - 16 bits or 8 bits - //[31 07 imm] - case 0x07: - insn.itype = m7900_rla; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - break; - //_____________________ END RLA ____________________ - - //_____________________ RMPA ____________________ - //250 - Repeat Multiply and Accumulate - //RMPA #imm - //Operation data - 16 bits or 8 bits - //[31 5A imm] - case 0x5A: - insn.itype = m7900_rmpa; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END RMPA ____________________ - //_____________________ SBC ____________________ - //264 - SuBtract with Carry - //sbc A,#imm - //Operation data - 16 bits or 8 bits - //[31 A7 imm] - case 0xA7: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_____________________ END SBC ____________________ - - default: - { - uchar cm = code & 0x40; - if ( cm == 0x40 ) - { - insn.itype = m7900_tdan; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, (((code-0x40) >> 4) & 0xF)+0x1); - } - else - { - insn.itype = m7900_tadn; - Operand_Imm_Spesh(insn.Op1, dt_byte, nib); - } - } - break; - } - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_41(insn_t &insn) -{ - TRACE("Opcode_41"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - //________________________ BBC________________________ - - //122 -Branch on Bit Clear - //bbc #imm dd rr (DIR) - //Operation data length: 16 bits or 8 bits - //[41 5A dd imm rr] - case 0x5A: - insn.itype = m7900_bbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - Operand_BBC(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); - break; - - //122 -Branch on Bit Clear - //bbc #imm mmll rr (ABS) - //Operation data length: 16 bits or 8 bits - //[41 5E ll mm imm rr] - case 0x5E: - insn.itype = m7900_bbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - Operand_BBC(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 6 : 7); - break; - - //________________________ END BBC________________________ - //________________________ BBS________________________ - - //124 - Branch on Bit Set - //bbs #imm dd rr (DIR) - //Operation data length: 16 bits or 8 bits - //[41 4A dd imm rr] - case 0x4A: - insn.itype = m7900_bbs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - Operand_BBS(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); - break; - - //124 - Branch on Bit Set - //bbs #imm mmll rr (ABS) - //Operation data length: 16 bits or 8 bits - //[41 4E ll mm imm rr] - case 0x4E: - insn.itype = m7900_bbs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); - Operand_BBS(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 6 : 7); - break; - //________________________ END BBS________________________ - - //_____________________ CBEQ ____________________ - - //145 - Compare immediate and Branch on EQual - //cbeq dd, #imm, rr - //Operation data length: 16 bits or 8 bits - //[41 6A dd imm rr] - case 0x6A: - insn.itype = m7900_cbeq; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); - break; - //_____________________ END CBEQ ____________________ - - //_____________________ CBNE ____________________ - - //147 - Compare immediate and Branch on Not Equal - //cbne dd, #imm, rr - //Operation data length: 16 bits or 8 bits - //[7A dd imm rr] - case 0x7A: - insn.itype = m7900_cbne; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); - break; - //_____________________ END CBNE ____________________ - //_____________________ CPX ____________________ - //167 - ComPare memory and index register X - //cpx mmll - //Operation data length: 16 bits or 8 bits - //[41 2E ll mm] - case 0x2E: - insn.itype = m7900_cpx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_X ? 8 : 16, SetTypeDataX); - break; - //_____________________ END CPX ____________________ - //168 - ComPare memory and index register Y - //cpy mmll - //Operation data length: 16 bits or 8 bits - //[41 3E ll mm] - case 0x3E://cpy - insn.itype = m7900_cpy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataX); - break; - - //_____________________ DEC ____________________ - //170 - DECrement by one - //dec dd, X - //Operation data - 16 bits or 8 bits - //[41 9B dd] - case 0x9B: - insn.itype = m7900_dec; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - case 0x9F://dec - insn.itype = m7900_dec; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //_____________________ END DEC ____________________ - - //_____________________ INC ____________________ - //189 - INCrement by one - //inc dd, X - //Operation data - 16 bits or 8 bits - //[41 8B dd] - case 0x8B: - insn.itype = m7900_inc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - - case 0x8F://inc - insn.itype = m7900_inc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rX); - break; - //_____________________ END INC ____________________ - - //_____________________ DEX ____________________ - //171 - DEcrement index register X by one - //dex - //Operation data - 16 bits or 8 bits - //[E3] - case 0xE3: - insn.itype = m7900_dex; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - //_____________________ END DEX ____________________ - //_____________________ DEY ____________________ - //172 - DEcrement index register Y by one - //dex - //Operation data - 16 bits or 8 bits - //[F3] - case 0xF3: - insn.itype = m7900_dey; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - //_____________________ END DEY ____________________ - - - //_____________________ LDX ____________________ - //200 - Load - //ldx dd, Y - //Operation data - 16 bits or 8 bits - //[41 05 dd] - case 0x05: - insn.itype = m7900_ldx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - Operand_Registr(insn.Op2, rY); - break; - - case 0x06: - insn.itype = m7900_ldx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op2, rY); - break; - //_____________________ END LDX ____________________ - - //_____________________ LDY ____________________ - //202 - LoaD index register Y from memory - //ldy dd, X - //Operation data - 16 bits or 8 bits - //[41 1B dd] - case 0x1B: - insn.itype = m7900_ldy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - Operand_Registr(insn.Op2, rX); - break; - - case 0x1F: - insn.itype = m7900_ldy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS_X, 16); - Operand_Registr(insn.Op2, rX); - break; - //_____________________ END INC ____________________ - //_____________________ STX ____________________ - //275 - STore index register X in memory - //stx dd, Y - //Operation data - 16 bits or 8 bits - //[41 E5 dd] - case 0xE5://stx dd,Y (DIR,Y) - insn.itype = m7900_stx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_Y, SetTypeDataX); - Operand_Registr(insn.Op2, rY); - break; - //_____________________ END STX ____________________ - - //_____________________ STY ____________________ - //276 - STore index register Y in memory - //sty dd, X - //Operation data - 16 bits or 8 bits - //[41 FB dd] - case 0xFB://sty dd,X (DIR,X) - insn.itype = m7900_sty; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR_Y, SetTypeDataX); - Operand_Registr(insn.Op2, rX); - break; - //_____________________ END STX ____________________ - - default: - return 0; - } - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_51(insn_t &insn) -{ - TRACE("Opcode_51"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - //---------------------------BYTE-------------------------------------// - //105 - ADD immediate and Memory at Byte - //addmb dd, #imm - //Operation data length: 8 bits - //[51 02 dd imm] - case 0x02: - insn.itype = m7900_addmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //105 - ADD immediate and Memory at Byte - //addmb mmll, #imm - //Operation data length: 8 bits - //[51 06 ll mm imm] - case 0x06: - insn.itype = m7900_addmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //114 - logical AND between immediate value and Memory (Byte) - //andmb dd, #imm - //Operation data length: 8 bits - //[51 62 dd imm] - case 0x62: - insn.itype = m7900_andmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //105 - ADD immediate and Memory at Byte - //addmb mmll, #imm - //Operation data length: 8 bits - //[51 66 ll mm imm] - case 0x66: - insn.itype = m7900_andmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //165 - CoMPare immediate with Memory at Byte - //cmpmb dd, #imm - //Operation data length: 8 bits - //[51 22 dd imm] - case 0x22: - insn.itype = m7900_cmpmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //165 - CoMPare immediate with Memory at Byte - //cmpmb mmll, #imm - //Operation data length: 8 bits - //[51 26 ll mm imm] - case 0x26: - insn.itype = m7900_cmpmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //183 - Exclusive OR immediate with Memory at Byte - //eormb dd, #imm - //Operation data length: 8 bits - //[51 72 dd imm] - case 0x72: - insn.itype = m7900_eormb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //183 - Exclusive OR immediate with Memory at Byte - //eormb mmll, #imm - //Operation data length: 8 bits - //[51 76 ll mm imm] - case 0x76: - insn.itype = m7900_eormb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //223 - OR immediAte with Memory at Byte - //oramb dd, #imm - //Operation data length: 8 bits - //[51 32 dd imm] - case 0x32: - insn.itype = m7900_oramb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //223 - OR immediAte with Memory at Byte - //oramb mmll, #imm - //Operation data length: 8 bits - //[51 36 ll mm imm] - case 0x36: - insn.itype = m7900_oramb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //282 - SUBtract immediate from Memory at Byte SUBMB - //submb dd, #imm - //Operation data length: 8 bits - //[51 12 dd imm] - case 0x12: - insn.itype = m7900_submb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //282 - SUBtract immediate from Memory at Byte SUBMB - //submb mmll, #imm - //Operation data length: 8 bits - //[51 16 ll mm imm] - case 0x16: - insn.itype = m7900_submb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - break; - - //__________________________ ADDM ___________________ - //104 - ADD immediate and Memory - //addm dd, #imm - //Operation data length: 16 bits or 8 bits - //[51 03 dd imm] - case 0x03: - insn.itype = m7900_addm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //104 - ADD immediate and Memory - //addm mmll, #imm - //Operation data length: 16 bits or 8 bits - //[51 07 ll mm imm] - case 0x07: - insn.itype = m7900_addm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_______________________END ADDM ___________________ - - //__________________________ ANDM ___________________ - //113 - logical AND between immediate value and Memory - //andm dd, #imm - //Operation data length: 16 bits or 8 bits - //[51 63 dd imm] - case 0x63: - insn.itype = m7900_andm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //113 - logical AND between immediate value and Memory - //andm mmll, #imm - //Operation data length: 16 bits or 8 bits - //[51 67 ll mm imm] - case 0x67: - insn.itype = m7900_andm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_______________________END ANDM ___________________ - //__________________________ CMPM ___________________ - //164 - CoMPare immediate with Memory - //cmpm dd, #imm - //Operation data length: 16 bits or 8 bits - //[51 23 dd imm] - case 0x23: - insn.itype = m7900_cmpm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //164 - CoMPare immediate with Memory - //cmpm mmll, #imm - //Operation data length: 16 bits or 8 bits - //[51 27 ll mm imm] - case 0x27: - insn.itype = m7900_cmpm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_______________________END CMPM ___________________ - - //__________________________ EORM ___________________ - //182 - Exclusive OR immediate with Memory - //eorm dd, #imm - //Operation data length: 16 bits or 8 bits - //[51 73 dd imm] - case 0x73: - insn.itype = m7900_eorm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //182 - Exclusive OR immediate with Memory - //eorm mmll, #imm - //Operation data length: 16 bits or 8 bits - //[51 77 ll mm imm] - case 0x77: - insn.itype = m7900_eorm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_______________________END EORM ___________________ - - //__________________________ ORAM ___________________ - //222 - OR immediAte with Memory - //oram dd, #imm - //Operation data length: 16 bits or 8 bits - //[51 33 dd imm] - case 0x33: - insn.itype = m7900_oram; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //222 - OR immediAte with Memory - //oram mmll, #imm - //Operation data length: 16 bits or 8 bits - //[51 37 ll mm imm] - case 0x37: - insn.itype = m7900_oram; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_______________________END oraM ___________________ - - //__________________________ subM ___________________ - //281 - SUBtract immediate from Memory - //subm dd, #imm - //Operation data length: 16 bits or 8 bits - //[51 13 dd imm] - case 0x13: - insn.itype = m7900_subm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //281 - SUBtract immediate from Memory - //subm mmll, #imm - //Operation data length: 16 bits or 8 bits - //[51 17 ll mm imm] - case 0x17: - insn.itype = m7900_subm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); - - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_______________________END subM ___________________ - - //__________________________ ADDMD ___________________ - //106 - ADD immediate and Memory at Double-word - //addmd dd, #imm32 - //Operation data length: 32 bits - //[51 83 dd imm imm imm imm] - case 0x83: - insn.itype = m7900_addmd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - - //106 - ADD immediate and Memory at Double-word - //addmd mmll, #imm32 - //Operation data length: 32 bits - //[51 87 ll mm imm imm imm imm] - case 0x87: - insn.itype = m7900_addmd; - RAZOPER = INSN_PREF_D; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - //_______________________END ADDMD ___________________ - - //__________________________ ANDMD ___________________ - //115 - logical AND between immediate value and Memory (Double word) - //andmd dd, #imm32 - //Operation data length: 32 bits - //[51 E3 dd imm imm imm imm] - case 0xE3: - insn.itype = m7900_andmd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - - //115 - logical AND between immediate value and Memory (Double word) - //andmd mmll, #imm32 - //Operation data length: 32 bits - //[51 E7 ll mm imm imm imm imm] - case 0xE7: - insn.itype = m7900_andmd; - RAZOPER = INSN_PREF_D; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - //_______________________END ADDMD ___________________ - - //__________________________ CMPMD ___________________ - //166 - CoMPare immediate with Memory at Double-word - //cmpmd dd, #imm32 - //Operation data length: 32 bits - //[51 A3 dd imm imm imm imm] - case 0xA3: - insn.itype = m7900_cmpmd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - - //166 - CoMPare immediate with Memory at Double-word - //cmpmd mmll, #imm32 - //Operation data length: 32 bits - //[51 A7 ll mm imm imm imm imm] - case 0xA7: - insn.itype = m7900_cmpmd; - RAZOPER = INSN_PREF_D; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - //_______________________END CMPMD ___________________ - - //__________________________ EORMD ___________________ - //184 - Exclusive OR immediate with Memory at Double-word - //eormd dd, #imm32 - //Operation data length: 32 bits - //[51 F3 dd imm imm imm imm] - case 0xF3: - insn.itype = m7900_eormd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - - //184 - Exclusive OR immediate with Memory at Double-word - //eormd mmll, #imm32 - //Operation data length: 32 bits - //[51 F7 ll mm imm imm imm imm] - case 0xF7: - insn.itype = m7900_eormd; - RAZOPER = INSN_PREF_D; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - //_______________________END EORMD ___________________ - - //__________________________ ORAMD ___________________ - //224 -OR immediAte with Memory at Double-word - //oramd dd, #imm32 - //Operation data length: 32 bits - //[51 B3 dd imm imm imm imm] - case 0xB3: - insn.itype = m7900_oramd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - - //224 - OR immediAte with Memory at Double-word - //oramd mmll, #imm32 - //Operation data length: 32 bits - //[51 B7 ll mm imm imm imm imm] - case 0xB7: - insn.itype = m7900_oramd; - RAZOPER = INSN_PREF_D; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - //_______________________END ORAMD ___________________ - - //__________________________ SUBMD ___________________ - //283 - SUBtract immediate from Memory at Double-word - //submd dd, #imm32 - //Operation data length: 32 bits - //[51 93 dd imm imm imm imm] - case 0x93: - insn.itype = m7900_submd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - - //283 - SUBtract immediate from Memory at Double-word - //submd mmll, #imm32 - //Operation data length: 32 bits - //[51 97 ll mm imm imm imm imm] - case 0x97: - insn.itype = m7900_submd; - RAZOPER = INSN_PREF_D; - Operand_Dir(insn, insn.Op1, TAB_ABS, dt_dword); - Operand_Imm(insn, insn.Op2, 32); - break; - //_______________________END ORAMD ___________________ - - default: - return 0; - } - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_81(insn_t &insn) -{ - TRACE("Opcode_81"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - case 0x85://phb - insn.itype = m7900_phb; - break; - //[ 81 A4] - case 0xA4://txb - insn.itype = m7900_txb; - break; - - case 0xB4://tyb - insn.itype = m7900_tyb; - break; - - case 0x95://plb - insn.itype = m7900_plb; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - //116 - Arithmetic Shift to Left - //asl B - //Operation data length: 16 bits or 8 bits - //[81 03] - case 0x03://asl - insn.itype = m7900_asl; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - - //119 - Arithmetic Shift to Right - //asr B - //Operation data length: 16 bits or 8 bits - //[64] - case 0x64://asr - insn.itype = m7900_asr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - - //94 - Absolute value - //abs B - case 0xE1: - insn.itype = m7900_abs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - - //185 - EXTension Sign - //exts B - //Operation data length: 16 bits - //[35] - case 0x35://exts - insn.itype = m7900_exts; - RAZOPER = INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - - //187 - EXTension Zero - //extz B - //Operation data length: 16 bits - //[34] - case 0x34://extz - insn.itype = m7900_extz; - RAZOPER = INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - - //216 - NEGative - //neg B - //Operation data length: 16 bits or 8 bits - //[24] - case 0x24://neg - insn.itype = m7900_neg; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - - //293 - Transfer accumulator B to index register X - //tbx - //Operation data length: 16 bits or 8 bits - //[C4] - case 0xC4: - insn.itype = m7900_tbx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - //294 - Transfer accumulator B to index register Y - //tby - //Operation data length: 16 bits or 8 bits - //[D4] - case 0xD4: - insn.itype = m7900_tby; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - //_____________________ DEC ____________________ - //170 - DECrement by one - //dec B - //Operation data - 16 bits or 8 bits - //[B3] - case 0xB3: - insn.itype = m7900_dec; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - //_____________________ END DEC ____________________ - - //_____________________ INC ____________________ - //189 - INCrement by one - //inc B - //Operation data - 16 bits or 8 bits - //[A3] - case 0xA3: - insn.itype = m7900_inc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - //_____________________ END INC ____________________ - - //_____________________ LSR ____________________ - //204 - Logical Shift Right - //lsr B - //Operation data - 16 bits or 8 bits - //[43] - case 0x43: - insn.itype = m7900_lsr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - //_____________________ END LSR ____________________ - //_____________________ ROL ____________________ - //254 - ROtate one bit Left - //rol B - //Operation data - 16 bits or 8 bits - //[13] - case 0x13: - insn.itype = m7900_rol; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - //_____________________ END ROL ____________________ - //_____________________ ROR ____________________ - //255 - ROtate one bit Right - //ror B - //Operation data - 16 bits or 8 bits - //[53] - case 0x53://ror - insn.itype = m7900_ror; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - //_____________________ END ROR ____________________ - - //---------------------------BYTE/WORD-------------------------------------// - //_____________________ ADD ____________________ - //101 - ADd - //add B, #imm - //Operation data length: 16 bits or 8 bits - //[26 imm] - case 0x26: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //101 - ADd - //add B, dd - //Operation data length: 16 bits or 8 bits - //[2A dd] - case 0x2A: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR,SetTypeDataM); - break; - - //101 - ADd - //add B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[2B dd] - case 0x2B: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //101 - ADd - //add B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[2E ll mm] - case 0x2E: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //101 - ADd - //add B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[2F ll mm] - case 0x2F: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END ADD ____________________ - //_____________________ CMP ____________________ - //161 - CoMPare - //cmp B, #imm - //Operation data length: 16 bits or 8 bits - //[46 imm] - case 0x46: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //161 - CoMPare - //cmp B, dd - //Operation data length: 16 bits or 8 bits - //[4A dd] - case 0x4A: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //161 - CoMPare - //cmp B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[4B dd] - case 0x4B: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //161 - CoMPare - //cmp B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[4E ll mm] - case 0x4E: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //161 - CoMPare - //cmp B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[4F ll mm] - case 0x4F: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END CMP ____________________ - - //_____________________ AND ____________________ - - //111 - logical AND - //and B, #imm - //Operation data length: 16 bits or 8 bits - //[66 imm] - case 0x66: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //111 - logical AND - //and B, #imm - //Operation data length: 16 bits or 8 bits - //[6A dd] - case 0x6A: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //111 - logical AND - //and B, #imm - //Operation data length: 16 bits or 8 bits - //[6B dd] - case 0x6B: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //111 - logical AND - //and B, #imm - //Operation data length: 16 bits or 8 bits - //[6E ll mm] - case 0x6E: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //111 - logical AND - //and B, #imm - //Operation data length: 16 bits or 8 bits - //[6F ll mm] - case 0x6F: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END AND ____________________ - - //_____________________ CBEQ ____________________ - - //145 - Compare immediate and Branch on EQual - //cbeq B, #imm, rr - //Operation data length: 16 bits or 8 bits - //[A6 imm rr] - case 0xA6: - insn.itype = m7900_cbeq; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 4 : 5); - break; - //_____________________ END CBEQ ____________________ - //_____________________ CBNE ____________________ - //147 - Compare immediate and Branch on Not Equal - //cbne B, #imm, rr - //Operation data length: 16 bits or 8 bits - //[B6 imm rr] - case 0xB6: - insn.itype = m7900_cbne; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 4 : 5); - break; - //_____________________ END CBNE ____________________ - - //_____________________ CLr ____________________ - //153 - CLeaR accumulator - //clr B - //Operation data length: 16 bits or 8 bits - //[54] - case 0x54://clr - insn.itype = m7900_clr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - break; - //_____________________ END CLr ____________________ - - //_____________________ EOR ____________________ - //180 - Exclusive OR memory with accumulator - //eor B, #imm - //Operation data length: 16 bits or 8 bits - //[76 imm] - case 0x76: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, dd - //Operation data length: 16 bits or 8 bits - //[7A dd] - case 0x7A: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[7B dd] - case 0x7B: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[7E ll mm] - case 0x7E: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[7F ll mm] - case 0x7F: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END EOR ____________________ - - //_____________________ LDA ____________________ - //195 - LoaD Accumulator from memory - //lda B, #imm - //Operation data length: 16 bits or 8 bits - //[16 imm] - case 0x16: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //195 - LoaD Accumulator from memory - //lda B, dd - //Operation data length: 16 bits or 8 bits - //[1A dd] - case 0x1A: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[1B dd] - case 0x1B: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //195 - LoaD Accumulator from memory - //lda B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[18 dd] - case 0x18: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //195 - LoaD Accumulator from memory - //lda B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[19 dd] - case 0x19: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //195 - LoaD Accumulator from memory - //lda B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[1E ll mm] - case 0x1E: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[1F ll mm] - case 0x1F: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //195 - LoaD Accumulator from memory - //lda B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[1C ll mm hh] - case 0x1C: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda B, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[1D ll mm hh] - case 0x1D: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END LDA ____________________ - - //_____________________ LDAB ____________________ - //196 - LoaD Accumulator from memory at Byte - //ldab B, #imm - //Operation data length: 16 bits - //[28 imm] - case 0x28: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, dd - //Operation data length: 16 bits - //[0A dd] - case 0x0A: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits - //[0B dd] - case 0x0B: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X); - Operand_Registr(insn.Op3, rX); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[08 dd] - case 0x08: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); - Operand_Registr(insn.Op3, rY); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits - //[09 dd] - case 0x09: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[0E ll mm] - case 0x0E: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[0F ll mm] - case 0x0F: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[0C ll mm hh] - case 0x0C: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[0D ll mm hh] - case 0x0D: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END LDAB ____________________ - - //_____________________ ORA ____________________ - //220 - OR memory with Accumulator - //ora B, #imm - //Operation data length: 16 bits or 8 bits - //[56 imm] - case 0x56: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //220 - OR memory with Accumulator - //ora B, dd - //Operation data length: 16 bits or 8 bits - //[5A dd] - case 0x5A: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[5B dd] - case 0x5B: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //220 - OR memory with Accumulator - //ora B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[5E ll mm] - case 0x5E: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[5F ll mm] - case 0x5F: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END ORA ____________________ - //_____________________ STA ____________________ - //271 - STore Accumulator in memory - //sta B, dd - //Operation data length: 16 bits or 8 bits - //[DA dd] - case 0xDA: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[DB dd] - case 0xDB: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //271 - STore Accumulator in memory - //sta B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[D8 dd] - case 0xD8: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //271 - STore Accumulator in memory - //sta B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[D9 dd] - case 0xD9: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //271 - STore Accumulator in memory - //sta B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[DE ll mm] - case 0xDE: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[DF ll mm] - case 0xDF: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //271 - STore Accumulator in memory - //sta B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[DC ll mm hh] - case 0xDC: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[DD ll mm hh] - case 0xDD: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END STA ____________________ - //_____________________ STAB ____________________ - //272 - STore Accumulator in memory at Byte - //stab B, dd - //Operation data length: 16 bits or 8 bits - //[CA dd] - case 0xCA: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[CB dd] - case 0xCB: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[C8 dd] - case 0xC8: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[C9 dd] - case 0xC9: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[CE ll mm] - case 0xCE: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[CF ll mm] - case 0xCF: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[CC ll mm hh] - case 0xCC: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[CD ll mm hh] - case 0xCD: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END STAB ____________________ - - //_____________________ SUB ____________________ - //278 - SUBtract - //sub B, #imm - //Operation data length: 16 bits or 8 bits - //[36 #imm] - case 0x36: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //278 - SUBtract - //sub B, dd - //Operation data length: 16 bits or 8 bits - //[3A dd] - case 0x3A: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //278 - SUBtract - //sub B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[3B dd] - case 0x3B: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //278 - SUBtract - //sub B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[3E ll mm] - case 0x3E: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //278 - SUBtract - //sub B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[3F ll mm] - case 0x3F: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END SUB ____________________ - - //---------------------------BYTE-------------------------------------// - //102 - ADD at Byte - //addb B, #imm - //Operation data length: 8 bits - //[81 29 imm] - case 0x29: - insn.itype = m7900_addb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //112 - logical AND between immediate (Byte) - //andb B, #imm - //Operation data length: 8 bits - //[81 23 imm] - case 0x23: - insn.itype = m7900_andb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //146 - Compare immediate and Branch on EQual at Byte - //cbeqb B, #imm, rr (DIR) - //Operation data length: 8 bits - //[A2 imm rr] - case 0xA2: - insn.itype = m7900_cbeqb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); - break; - - //148 - Compare immediate and Branch on Not Equal at Byte - //cbneb B, #imm, rr () - //Operation data length: 8 bits - //[B2 imm rr] - case 0xB2: - insn.itype = m7900_cbneb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); - break; - - //154 - CLeaR accumulator at Byte - //clrb B - //Operation data length: 8 bits - //[44] - case 0x44://clrb - insn.itype = m7900_clrb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - break; - - //162 - CoMPare at Byte - //cmpb B, #imm - //Operation data length: 8 bits - //[38 imm] - case 0x38: - insn.itype = m7900_cmpb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //181 - Exclusive OR immediate with accumulator at Byte - //eorb B, #imm - //Operation data length: 8 bits - //[33 imm] - case 0x33: - insn.itype = m7900_eorb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //221 - OR immediate with Accumulator at Byte - //orab B, #imm - //Operation data length: 8 bits - //[63 imm] - case 0x63: - insn.itype = m7900_orab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //279 - OR immediate with Accumulator at Byte - //subb B, #imm - //Operation data length: 8 bits - //[81 39 imm] - case 0x39: - insn.itype = m7900_subb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - default: - return 0; - } - - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_A1(insn_t &insn) -{ - TRACE("Opcode_A1"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - //___________________ ADC _________________________ - //96 - ADd with Carry - //adc B, dd - //Operation data length: 16 bits or 8 bits - //[A1 8A dd] - case 0x8A: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[A1 8B dd] - case 0x8B: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[A1 80 dd] - case 0x80: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[A1 81 dd] - case 0x81: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[A1 88 dd] - case 0x88: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[A1 82 dd] - case 0x82: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //96 - ADd with Carry - //adc B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[A1 89 dd] - case 0x89: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[A1 83 nn] - case 0x83: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //96 - ADd with Carry - //adc B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[A1 84 nn] - case 0x84: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[A1 8E ll mm] - case 0x8E: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[A1 8F ll mm] - case 0x8F: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //96 - ADd with Carry - //adc B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[A1 86 ll mm] - case 0x86: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //96 - ADd with Carry - //adc B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[A1 8C ll mm hh] - case 0x8C: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //96 - ADd with Carry - //adc B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[A1 8D ll mm hh] - case 0x8D: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END ADC _________________________ - - //___________________ SBC _________________________ - //264 - SuBtract with Carry - //sbc B, dd - //Operation data length: 16 bits or 8 bits - //[21 AA dd] - case 0xAA: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc B, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[21 AB dd] - case 0xAB: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //264 - SuBtract with Carry - //sbc B, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[21 A0 dd] - case 0xA0: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[21 A1 dd] - case 0xA1: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc B, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[21 A8 dd] - case 0xA8: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc B, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 A2 dd] - case 0xA2: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //264 - SuBtract with Carry - //sbc B, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[21 A9 dd] - case 0xA9: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc B, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[21 A3 nn] - case 0xA3: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //264 - SuBtract with Carry - //sbc B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 A4 nn] - case 0xA4: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc B, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[21 AE ll mm] - case 0xAE: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc B, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 AF ll mm] - case 0xAF: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //264 - SuBtract with Carry - //sbc B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[21 A6 ll mm] - case 0xA6: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //264 - SuBtract with Carry - //sbc B, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 AC ll mm hh] - case 0xAC: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //264 - SuBtract with Carry - //sbc B, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 AD ll mm hh] - case 0xAD: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END sbc _________________________ - - default: - return 0; - } - - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_11(insn_t &insn) -{ - TRACE("Opcode_11"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - switch ( code ) - { - //________________________ ADD________________________ - //101 - ADd - //add A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 20 dd] - case 0x20: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //101 - ADd - //add A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 21 dd] - case 0x21: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //101 - ADd - //add A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[11 28 dd] - case 0x28: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 22 dd] - case 0x22: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_byte); - break; - - //101 - ADd - //add A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 29 dd] - case 0x29: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 23 nn] - case 0x23: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //101 - ADd - //add A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 24 nn] - case 0x24: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 26 ll mm] - case 0x26: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //101 - ADd - //add A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 2C ll mm hh] - case 0x2C: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //101 - ADd - //add A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 2D ll mm hh] - case 0x2D: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //______________________ END ADD _____________________ - //________________________ CMP________________________ - //161 - CoMPare - //cmp A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 40 dd] - case 0x40: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //161 - CoMPare - //cmp A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 41 dd] - case 0x41: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //161 - CoMPare - //cmp A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[11 48 dd] - case 0x48: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 42 dd] - case 0x42: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //161 - CoMPare - //cmp A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 49 dd] - case 0x49: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 43 nn] - case 0x43: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //161 - CoMPare - //cmp A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 44 nn] - case 0x44: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 46 ll mm] - case 0x46: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //161 - CoMPare - //cmp A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 4C ll mm hh] - case 0x4C: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //161 - CoMPare - //cmp A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 4D ll mm hh] - case 0x4D: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END CMP _____________________ - - //________________________ AND________________________ - //111 - logical AND - //and A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 60 dd] - case 0x60: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //111 - logical AND - //and A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 61 dd] - case 0x61: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //111 - logical AND - //and A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[11 68 dd] - case 0x68: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 62 dd] - case 0x62: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //111 - logical AND - //and A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 69 dd] - case 0x69: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 63 nn] - case 0x63: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //111 - logical AND - //and A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 64 nn] - case 0x64: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 66 ll mm] - case 0x66: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //111 - logical AND - //and A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 6C ll mm hh] - case 0x6C: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //111 - logical AND - //and A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[ 6D ll mm hh] - case 0x6D: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END AND _____________________ - //________________________ EOR________________________ - //180 - Exclusive OR memory with accumulator - //eor A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 70 dd] - case 0x70: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 71 dd] - case 0x71: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[11 78 dd] - case 0x78: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 72 dd] - case 0x72: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 79 dd] - case 0x79: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 73 nn] - case 0x73: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 74 nn] - case 0x74: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 76 ll mm] - case 0x76: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[21 7C ll mm hh] - case 0x7C: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[21 7D ll mm hh] - case 0x7D: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END eor _____________________ - - //___________________ LDA _________________________ - //195 - LoaD Accumulator from memory - //lda A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 10 dd] - case 0x10: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 11 dd] - case 0x11: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 12 dd] - case 0x12: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //195 - LoaD Accumulator from memory - //lda A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 13 nn] - case 0x13: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //195 - LoaD Accumulator from memory - //lda A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[11 14 nn] - case 0x14: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //195 - LoaD Accumulator from memory - //lda A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 16 ll mm] - case 0x16: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END LDA ____________________ - - //___________________ LDAB _________________________ - //196 - LoaD Accumulator from memory at Byte - //ldab a, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 00 dd] - case 0x00: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 01 dd] - case 0x01: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 02 dd] - case 0x02: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 03 nn] - case 0x03: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[11 04 nn] - case 0x04: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 06 ll mm] - case 0x06: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END LDAB ____________________ - - //___________________ STA _________________________ - //271 - STore Accumulator in memory - //sta A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[D0 dd] - case 0xD0: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[D1 dd] - case 0xD1: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[D2 dd] - case 0xD2: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //271 - STore Accumulator in memory - //sta A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[D3 nn] - case 0xD3: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //271 - STore Accumulator in memory - //sta A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[D4 nn] - case 0xD4: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //271 - STore Accumulator in memory - //sta A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[D6 ll mm] - case 0xD6: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END STA ____________________ - //_____________________ STAB ____________________ - //272 - STore Accumulator in memory at Byte - //stab A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[C0 dd] - case 0xC0: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[C1 dd] - case 0xC1: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[C2 dd] - case 0xC2: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[C3 nn] - case 0xC3: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[C4 nn] - case 0xC4: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[C6 ll mm] - case 0xC6: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END STAB ____________________ - - //_____________________ STAD ____________________ - //273 - STore Accumulator in memory at Double-word - //stad E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 32 bits - //[E0 dd] - case 0xE0: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 32 bits - //[E1 dd] - case 0xE1: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 E2 dd] - case 0xE2: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 32 bits - //[E3 nn] - case 0xE3: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 32 bits - //[E4 nn] - case 0xE4: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 32 bits - //[E6 ll mm] - case 0xE6: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - //_____________________ END STAD ____________________ - - //________________________ ORA________________________ - //220 - OR memory with Accumulator - //ora A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 50 dd] - case 0x50: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 51 dd] - case 0x51: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[11 58 dd] - case 0x58: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 52 dd] - case 0x52: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //220 - OR memory with Accumulator - //ora A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 59 dd] - case 0x59: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 53 nn] - case 0x53: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //220 - OR memory with Accumulator - //ora A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 54 nn] - case 0x54: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 56 ll mm] - case 0x56: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //220 - OR memory with Accumulator - //ora A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[11 5C ll mm hh] - case 0x5C: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //ora A, hhmmll, X (Absolute long indexed X addressing mode(ABL,X) - //Operation data length: 16 bits or 8 bits - //[11 5D ll mm hh] - case 0x5D: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END ora _____________________ - - //________________________ SUB________________________ - //278 - SUBtract - //sub A, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 16 bits or 8 bits - //[11 30 dd] - case 0x30: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - break; - - //278 - SUBtract - //sub A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 16 bits or 8 bits - //[11 31 dd] - case 0x31: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); - break; - - //278 - SUBtract - //sub A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[11 38 dd] - case 0x38: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub A, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 32 dd] - case 0x32: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //278 - SUBtract - //sub A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[11 39 dd] - case 0x39: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub A, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 16 bits or 8 bits - //[11 33 nn] - case 0x33: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //278 - SUBtract - //sub A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 16 bits or 8 bits - //[21 34 nn] - case 0x34: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 16 bits or 8 bits - //[11 36 ll mm] - case 0x36: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //278 - SUBtract - //sub A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[11 3C ll mm hh] - case 0x3C: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //278 - SUBtract - //sub A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[11 3D ll mm hh] - case 0x3D: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //______________________ END SUB _____________________ - - //___________________ ADDD _________________________ - - //101 - ADd Double-word - //addd E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 32 bits - //[11 90 dd] - case 0x90: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //103 - ADd at Double-word - //addd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 32 buts - //[11 91 dd] - case 0x91: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //103 - ADd at Double-word - //addd E, (dd), Y () - //Operation data length: 32 bits - //[11 98 dd] - case 0x98: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //103 - ADd Double-word - //addd E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 92 dd] - case 0x92: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //103 - ADd at Double-word - //addd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 99 dd] - case 0x99: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //103 - ADd at Double-word - //addd E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 32 bits - //[11 93 nn] - case 0x93: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //103 - ADd at Double-word - //addd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 32 bits - //[11 94 nn] - case 0x94: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //103 - ADd at Double-word - //addd E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[11 9E ll mm] - case 0x9E: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //103 - ADd at Double-word - //addd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[11 9F ll mm] - case 0x9F: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //103 - ADd at Double-word - //addd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 32 bits - //[11 96 ll mm] - case 0x96: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //103 - ADd at Double-word - //addd E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[11 9C ll mm hh] - case 0x9C: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //103 - ADd at Double-word - //addd A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[11 9D ll mm hh] - case 0x9D: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END ADCD _________________________ - //___________________ CMPD _________________________ - - //163 - CoMPare at Double-word - //cmpd E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 32 bits - //[11 B0 dd] - case 0xB0: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //163 - CoMPare at Double-word - //cmpd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 32 buts - //[11 B1 dd] - case 0xB1: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //163 - CoMPare at Double-word - //cmpd E, (dd), Y () - //Operation data length: 32 bits - //[11 B8 dd] - case 0xB8: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //163 - CoMPare at Double-word - //cmpd E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 B2 dd] - case 0xB2: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //163 - CoMPare at Double-word - //cmpd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 B9 dd] - case 0xB9: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //163 - CoMPare at Double-word - //cmpd E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 32 bits - //[11 B3 nn] - case 0xB3: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //163 - CoMPare at Double-word - //cmpd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 32 bits - //[11 B4 nn] - case 0xB4: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //163 - CoMPare at Double-word - //cmpd E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[11 BE ll mm] - case 0xBE: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //163 - CoMPare at Double-word - //cmpd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[11 BF ll mm] - case 0xBF: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //163 - CoMPare at Double-word - //cmpd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 32 bits - //[11 B6 ll mm] - case 0xB6: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //163 - CoMPare at Double-word - //cmpd E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[11 BC ll mm hh] - case 0xBC: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //163 - CoMPare at Double-word - //cmpd A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[11 BD ll mm hh] - case 0xBD: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END CMPD _________________________ - - //___________________ LDAD _________________________ - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 32 bits - //[11 80 dd] - case 0x80: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 32 buts - //[11 81 dd] - case 0x81: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 82 dd] - case 0x82: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 32 bits - //[11 83 nn] - case 0x83: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 32 bits - //[11 84 nn] - case 0x84: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 32 bits - //[11 86 ll mm] - case 0x86: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - //___________________ END LDAD _________________________ - - //___________________ SUBD _________________________ - - //280 - SUBtract Double-word - //subd E, (dd) (Direct indirect addressing mode (DIR)) - //Operation data length: 32 bits - //[11 A0 dd] - case 0xA0: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - break; - - //280 - SUBtract Double-word - //subd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) - //Operation data length: 32 bits - //[11 A1 dd] - case 0xA1: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); - break; - - //280 - SUBtract Double-word - //subd E, (dd), Y () - //Operation data length: 32 bits - //[11 A8 dd] - case 0xA8: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //280 - SUBtract Double-word - //subd E, L(dd)(Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 A2 dd] - case 0xA2: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - break; - - //280 - SUBtract Double-word - //subd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[11 A9 dd] - case 0xA9: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //280 - SUBtract Double-word - //subd E, nn, S (Stack pointer relative addressing mode(SR)) - //Operation data length: 32 bits - //[11 A3 nn] - case 0xA3: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_SP, 8); - Operand_Registr(insn.Op3, rPS); - break; - - //280 - SUBtract Double-word - //subd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) - //Operation data length: 32 bits - //[11 A4 nn] - case 0xA4: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); - Operand_Registr(insn.Op3, rY); - break; - - //280 - SUBtract Double-word - //subd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) - //Operation data length: 32 bits - //[11 A6 ll mm] - case 0xA6: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //280 - SUBtract Double-word - //subd E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[11 AC ll mm hh] - case 0xAC: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //280 - SUBtract Double-word - //subd A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[11 AD ll mm hh] - case 0xAD: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //___________________ END SUBD _________________________ - - default: - return 0; - } - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_B1(insn_t &insn) -{ - TRACE("Opcode_B1"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - uchar nib = (code >> 4) & 0xF; - - switch ( code ) - { - - //292 - Transfer accumulator B to Stack pointer - //tbs - //Operation data length: 8 bits - //[B1 82] - case 0x82: - insn.itype = m7900_tbs; - break; - - //96 - ADc with Carry - //adc B, #imm - //Operation data length: 16 bits or 8 bits - //[B1 87 imm] - case 0x87: - insn.itype = m7900_adc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //98 - ADd with Carry at Byte - //adcb B, #imm - //Operation data length: 8 bits - //[B1 1A imm] - case 0x1A: - insn.itype = m7900_adcb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //265 - SuBtract with Carry at Byte - //sbcb A, #imm - //Operation data length: 8 bits - //[B1 1B imm] - case 0x1B: - insn.itype = m7900_sbcb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, 8); - break; - - //299 - Transfer Stack pointer to accumulator B - //tsb - //Operation data length: 16 bits or 8 bits - //[B1 92] - case 0x92: - insn.itype = m7900_tsb; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - //_____________________ SBC ____________________ - //264 - SuBtract with Carry - //sbc B, #imm - //Operation data - 16 bits or 8 bits - //[B1 A7 imm] - case 0xA7: - insn.itype = m7900_sbc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - //_____________________ END SBC ____________________ - - default: - { - uchar cm = code & 0x40; - if ( cm == 0x40 ) - { - insn.itype = m7900_tdbn; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, (((code-0x40) >> 4) & 0xF)+0x1); - } - else - { - insn.itype = m7900_tbdn; - Operand_Imm_Spesh(insn.Op1, dt_byte, nib); - } - } - break; - } - - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_B8(insn_t &insn) -{ - TRACE("Opcode_B8"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - uchar nib = (code >> 4) & 0xF; - uchar cd = code & 0xF; - uchar Nib; - - if ( nib == 0 && cd == 0 ) - return 0; - - if ( nib == 0 ) - { - insn.itype = m7900_phdn; - RAZOPER = INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - return insn.size; - } - else if ( cd == 0 ) - { - insn.itype = m7900_lddn; - RAZOPER = INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, nib); - Nib = nib; - } - else - { - if ( nib != cd ) - return 0; - insn.itype = m7900_phldn; - RAZOPER = INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - Nib = cd; - } - - for ( int i=0; i < 4; ++i ) - if ( GETBIT(Nib, i) == 1 ) - Operand_STK(insn, insn.ops[1+i], 16); - - return insn.size; -} - -//------------------------------------------------------------------------------------------------------------------ -static int Opcode_77(insn_t &insn) -{ - TRACE("Opcode_77"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - uchar nib = (code >> 4) & 0xF; - uchar cd = code & 0xF; - - switch ( cd ) - { - case 0xC: - insn.itype = m7900_rtld; - Operand_Imm_Spesh(insn.Op1, dt_byte, nib); - break; - - case 0x0: - insn.itype = m7900_pldn; - RAZOPER = INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, nib); - break; - - case 0x8: - insn.itype = m7900_rtsdn; - Operand_Imm_Spesh(insn.Op1, dt_byte, nib); - break; - - default: - return 0; - } - - return insn.size; -} - -//------------------------------------------------------------------------------------------------------------------ -static int Opcode_61(insn_t &insn) -{ - TRACE("Opcode_61"); - - uchar code = insn.get_next_byte(); - TRACE(code); - - uchar nib = (code >> 4) & 0xF; - uchar count = code & 0x0F; - - Operand_Imm_Spesh(insn.Op1, dt_byte, count); - - uchar i; - - switch ( nib ) - { - case 0x0: - insn.itype = m7900_movrb; - // This instruction is unaffected by flag m - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//imm - insn.get_next_byte();//dd - } - break; - - case 0x2: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//imm - insn.get_next_word();//llmm - } - break; - - case 0x4: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//dds1 - insn.get_next_byte();//ddd1 - } - break; - - case 0x6: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//dd - insn.get_next_word();//llmm - } - break; - - case 0x8: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < count; i++ ) - { - insn.get_next_word();//llmm - insn.get_next_byte();//dd - } - break; - - case 0xA: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < count; i++ ) - { - insn.get_next_word();//mmll1 - insn.get_next_word();//mmll2 - } - break; - //______________________________________________ - - case 0x1: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//dd - - if ( getFlag_M == 0 ) - insn.get_next_word();//imm - else - insn.get_next_byte();//imm - } - break; - - case 0x3: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - - for ( i=0; i < count; i++ ) - { - if ( getFlag_M != 0 ) - { - insn.get_next_byte();//imm - insn.get_next_word();//llmm - } - else - { - insn.get_next_word();//imm - insn.get_next_word();//llmm - } - } - break; - - case 0x5: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//dd1 - insn.get_next_byte();//dd2 - } - break; - - case 0x7: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - for ( i=0; i < count; i++ ) - { - insn.get_next_byte();//dd - insn.get_next_word();//llmm - } - break; - - case 0x9: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - - for ( i=0; i < count; i++ ) - { - insn.get_next_word();//llmm - insn.get_next_byte();//dd - } - break; - - case 0xB: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - for ( i=0; i < count; i++ ) - { - insn.get_next_word();//mmll1 - insn.get_next_word();//mmll2 - } - break; - - default: - return 0; - } - return insn.size; -} - -//---------------------------------------------------------------------- -static int Opcode_71(insn_t &insn) -{ - int i; - TRACE("Opcode_71"); - uchar code = insn.get_next_byte(); - TRACE(code); - - uchar nib = (code >> 4) & 0xF; - uchar cd = code & 0x0F; - - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - - //140 - Branch on Single bit Clear - //bsc n, dd, rr - //bsc n, mmll, rr - //Operation data length: 16 bits or 8 bits - //[71 n+E0 ll mm rr] - //[71 n+A0 dd rr] - - switch ( nib ) - { - case 0x0: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - - for ( i=0; i < cd; i++ ) - { - insn.get_next_word();//mmll1 - insn.get_next_byte();//dd - } - break; - - case 0x6: - insn.itype = m7900_movrb; - RAZOPER = INSN_PREF_U; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movr; - - for ( i=0; i < cd; i++ ) - { - insn.get_next_word();//mmll1 - insn.get_next_byte();//dd - } - break; - - case 0x1: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < cd; i++ ) - { - insn.get_next_word();//mmll1 - insn.get_next_byte();//dd - } - break; - - case 0x7: - insn.itype = m7900_movr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - insn.Op2.type = o_mem; - insn.Op2.TypeOper = m7900_movrb; - - for ( i=0; i < cd; i++ ) - { - insn.get_next_byte();//dd - insn.get_next_word();//llmm - } - break; - - case 0xA: - insn.itype = m7900_bsc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); - break; - - case 0xE: - insn.itype = m7900_bsc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); - break; - - case 0x8: - insn.itype = m7900_bss; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); - break; - - case 0xC: - insn.itype = m7900_bss; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, dt_byte, cd); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); - break; - - default: - return 0; - } - return insn.size; -} - -//---------------------------------------------------------------------- -int idaapi ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - - TRACE("ana"); - - RAZOPER = 0; - - uchar code = insn.get_next_byte(); - uchar nib = (code >> 4) & 0xF; - uchar imm, com; - - switch ( code ) - { - //116 - Arithmetic Shift to Left - //asl A - //Operation data length: 16 bits or 8 bits - //[03] - case 0x03://asl - insn.itype = m7900_asl; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - //119 - Arithmetic Shift to Right - //asr A - //Operation data length: 16 bits or 8 bits - //[64] - case 0x64://asr - insn.itype = m7900_asr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - case 0x91: - return Opcode_91(insn); - - case 0x21: - return Opcode_21(insn); - - case 0x31: - return Opcode_31(insn); - - case 0x41: - return Opcode_41(insn); - - case 0x51: - return Opcode_51(insn); - - case 0x81: - return Opcode_81(insn); - - case 0x11: - return Opcode_11(insn); - - case 0xA1: - return Opcode_A1(insn); - - case 0xB1: - return Opcode_B1(insn); - - case 0xB8: - return Opcode_B8(insn); - - //94 - Absolute value - //abs A - case 0xE1: - insn.itype = m7900_abs; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - //-----------------------------------------------------------// - //139 - force BReaK - //brk - //Operation data length: - - //[00 74] - case 0x00://brk (IMP) - if ( get_byte(insn.ea + 1) == 0x74 ) - { - insn.get_next_byte(); - insn.itype = m7900_brk; - Operand_IMP(insn.Op1); - } - else - { - return 0; - } - break; - - case 0x14://clc - insn.itype = m7900_clc; - break; - - case 0x15://cli - insn.itype = m7900_cli; - break; - - case 0x65://clv - insn.itype = m7900_clv; - break; - - //154 - CLeaR accumulator at Byte - //clrb A - //Operation data length: 8 bits - //[44] - case 0x44://clrb - insn.itype = m7900_clrb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - break; - - //153 - CLeaR accumulator - //clr A - //Operation data length: 16 bits or 8 bits - //[54] - case 0x54://clr - insn.itype = m7900_clr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - case 0xA4://txa - insn.itype = m7900_txa; - break; - - case 0xB4://tya - insn.itype = m7900_tya; - break; - - case 0xC4://tax - insn.itype = m7900_tax; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xD4://tay - insn.itype = m7900_tay; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0x55://xab - insn.itype = m7900_xab; - break; - - case 0xE3://dex - insn.itype = m7900_dex; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xF3://dey - insn.itype = m7900_dey; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - //185 - EXTension Sign - //exts A - //Operation data length: 16 bits - //[35] - case 0x35://exts - insn.itype = m7900_exts; - RAZOPER = INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - //187 - EXTension Zero - //extz A - //Operation data length: 16 bits - //[34] - case 0x34://extz - insn.itype = m7900_extz; - RAZOPER = INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - -//********************************************************IN - case 0xC3://inx (IMP) - insn.itype = m7900_inx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xD3://iny (IMP) - insn.itype = m7900_iny; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - -//************************************************ - case 0x24://neg - insn.itype = m7900_neg; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - case 0x74://nop - insn.itype = m7900_nop; - break; - -//*********************************************************PUSH - - case 0x85://pha - insn.itype = m7900_pha; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0x83://phd - insn.itype = m7900_phd; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xA5://php - insn.itype = m7900_php; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xC5://phx - insn.itype = m7900_phx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xE5://phy - insn.itype = m7900_phy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0x95://pla - insn.itype = m7900_pla; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0x93://pld - insn.itype = m7900_pld; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xB5://plp - insn.itype = m7900_plp; - RAZOPER = INSN_PREF_W; - break; - - case 0xD5://plx - insn.itype = m7900_plx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - case 0xF5://ply - insn.itype = m7900_ply; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - -//**************************************************************** - case 0xF1://rti - insn.itype = m7900_rti; - break; - - case 0x94://rtl - insn.itype = m7900_rtl; - break; - - case 0x84://rts - insn.itype = m7900_rts; - break; - - case 0x04://sec - insn.itype = m7900_sec; - break; - - case 0x05://sei - insn.itype = m7900_sei; - break; - - case 0x45://clm - insn.itype = m7900_clm; - break; - - case 0x25://sem - insn.itype = m7900_sem; - break; - - case 0x77:// - return Opcode_77(insn); - - case 0x61: - return Opcode_61(insn); - - case 0x71: - return Opcode_71(insn); - - //102 - ADD at Byte - //addb A, #imm - //Operation data length: 8 bits - //[29 imm] - case 0x29: - insn.itype = m7900_addb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //112 - logical AND between immediate (Byte) - //andb A, #imm - //Operation data length: 8 bits - //[23 imm] - case 0x23: - insn.itype = m7900_andb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //123 -Branch on Bit Clear (Byte) - //bbcb #imm dd rr (DIR) - //Operation data length: 8 bits - //[52 dd imm rr] - case 0x52: - insn.itype = m7900_bbcb; - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - RAZOPER = INSN_PREF_U; - Operand_Imm(insn, insn.Op1, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); - break; - - //123 -Branch on Bit Clear (Byte) - //bbcb #imm dd rr (ABS) - //Operation data length: 8 bits - //[57 dd imm rr] - case 0x57: - insn.itype = m7900_bbcb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op2, TAB_ABS, 8, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); - break; - - //125 - Branch on Bit Set (Byte) - //bbsb #imm dd rr (DIR) - //Operation data length: 8 bits - //[42 dd imm rr] - case 0x42: - insn.itype = m7900_bbsb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); - break; - - //125 - Branch on Bit Set (Byte) - //bbsb #imm dd rr (ABS) - //Operation data length: 8 bits - //[47 dd imm rr] - case 0x47: - insn.itype = m7900_bbsb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op2, TAB_ABS, 8, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); - break; - - //146 - Compare immediate and Branch on EQual at Byte - //cbeqb A, #imm, rr () - //Operation data length: 8 bits - //[A2 imm rr] - case 0xA2: - insn.itype = m7900_cbeqb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); - break; - - //146 - Compare immediate and Branch on EQual at Byte - //cbeqb A,dd, #imm, rr (DIR) - //Operation data length: 8 bits - //[62 dd imm rr] - case 0x62://cbeqb dd,#imm,rr - insn.itype = m7900_cbeqb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - Operand_Near(insn, insn.Op3,insn.get_next_byte(), 4); - break; - - //148 - Compare immediate and Branch on Not Equal at Byte - //cbneb A, #imm, rr (DIR) - //Operation data length: 8 bits - //[B2 imm rr] - case 0xB2: - insn.itype = m7900_cbneb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); - break; - - //148 - Compare immediate and Branch on Not Equal at Byte - //cbneb A,dd, #imm, rr (DIR) - //Operation data length: 8 bits - //[72 dd imm rr] - case 0x72://cbneb dd,#imm,rr - insn.itype = m7900_cbneb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op2, 8); - Operand_Near(insn, insn.Op3,insn.get_next_byte(), 4); - break; - - //156 - CLeaR Memory at Byte - //clrmb dd(DIR) - //Operation data length: 8 bits - //[C2 dd] - case 0xC2: - insn.itype = m7900_clrmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - break; - - //156 - CLeaR Memory at Byte - //clrmb mmll(ABS) - //Operation data length: 8 bits - //[C2 ll mm] - case 0xC7://clrmb - insn.itype = m7900_clrmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - break; - - //162 - CoMPare at Byte - //cmpb A, #imm - //Operation data length: 8 bits - //[38 imm] - case 0x38: - insn.itype = m7900_cmpb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //181 - Exclusive OR immediate with accumulator at Byte - //eorb A, #imm - //Operation data length: 8 bits - //[33 imm] - case 0x33: - insn.itype = m7900_eorb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //__________________________________________________________// - - //208 - MOVe Memory to memory at Byte - //movmb dd, #imm - //Operation data length: 8 bits - //[A9 imm dd] - case 0xA9: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - break; - - //208 - MOVe Memory to memory at Byte - //movmb dd, mmll - //Operation data length: 8 bits - //[4C imm ll mm] - case 0x4C: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - break; - - //208 - MOVe Memory to memory at Byte - //movmb dd, mmll, X - //Operation data length: 8 bits - //[4D imm ll mm] - case 0x4D: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - Operand_Imm(insn, insn.Op1, 8); - Operand_Registr(insn.Op3, rX); - break; - - //208 - MOVe Memory to memory at Byte - //movmb mmll, #imm - //Operation data length: 8 bits - //[B9 imm ll mm] - case 0xB9: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Imm(insn, insn.Op2, 8); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - break; - - //208 - MOVe Memory to memory at Byte - //movmb mmll, dd - //Operation data length: 8 bits - //[68 dd ll mm] - case 0x68: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - break; - - //208 - MOVe Memory to memory at Byte - //movmb mmll, dd - //Operation data length: 8 bits - //[69 dd ll mm] - case 0x69: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //208 - MOVe Memory to memory at Byte - //movmb mmll, mmll - //Operation data length: 8 bits - //[6C ll mm ll mm] - case 0x6C: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); - break; - - //208 - MOVe Memory to memory at Byte - //movmb mmll, mmll - //Operation data length: 8 bits - //[48 dd dd] - case 0x48: - insn.itype = m7900_movmb; - RAZOPER = INSN_PREF_U; - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); - break; - - //221 - OR immediate with Accumulator at Byte - //orab A, #imm - //Operation data length: 8 bits - //[63 imm] - case 0x63: - insn.itype = m7900_orab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //279 - OR immediate with Accumulator at Byte - //subb A, #imm - //Operation data length: 8 bits - //[39 imm] - case 0x39: - insn.itype = m7900_subb; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //_____________________ ADD ____________________ - //101 - ADd - //add A, #imm - //Operation data length: 16 bits or 8 bits - //[26 imm] - case 0x26: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //101 - ADd - //add A, dd - //Operation data length: 16 bits or 8 bits - //[2A dd] - case 0x2A: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //101 - ADd - //add A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[2B dd] - case 0x2B: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //101 - ADd - //add A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[2E ll mm] - case 0x2E: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //101 - ADd - //add A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[2F ll mm] - case 0x2F: - insn.itype = m7900_add; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END ADD ____________________ - //_____________________ CMP ____________________ - //161 - CoMPare - //cmp A, #imm - //Operation data length: 16 bits or 8 bits - //[46 imm] - case 0x46: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //161 - CoMPare - //cmp A, dd - //Operation data length: 16 bits or 8 bits - //[4A dd] - case 0x4A: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //161 - CoMPare - //cmp A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[4B dd] - case 0x4B: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //161 - CoMPare - //cmp A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[4E ll mm] - case 0x4E: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //161 - CoMPare - //cmp A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[4F ll mm] - case 0x4F: - insn.itype = m7900_cmp; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END CMP ____________________ - - //_____________________ EOR ____________________ - //180 - Exclusive OR memory with accumulator - //eor A, #imm - //Operation data length: 16 bits or 8 bits - //[76 imm] - case 0x76: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, dd - //Operation data length: 16 bits or 8 bits - //[7A dd] - case 0x7A: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[7B dd] - case 0x7B: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[7E ll mm] - case 0x7E: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //180 - Exclusive OR memory with accumulator - //eor A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[7F ll mm] - case 0x7F: - insn.itype = m7900_eor; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END EOR ____________________ - - //_____________________ LDA ____________________ - //195 - LoaD Accumulator from memory - //lda A, #imm - //Operation data length: 16 bits or 8 bits - //[16 imm] - case 0x16: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //195 - LoaD Accumulator from memory - //lda A, dd - //Operation data length: 16 bits or 8 bits - //[1A dd] - case 0x1A: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[1B dd] - case 0x1B: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //195 - LoaD Accumulator from memory - //lda A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[18 dd] - case 0x18: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rB); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //195 - LoaD Accumulator from memory - //lda A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[19 dd] - case 0x19: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //195 - LoaD Accumulator from memory - //lda A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[1E ll mm] - case 0x1E: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[1F ll mm] - case 0x1F: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //195 - LoaD Accumulator from memory - //lda A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[1C ll mm hh] - case 0x1C: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //195 - LoaD Accumulator from memory - //lda A, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[1D ll mm hh] - case 0x1D: - insn.itype = m7900_lda; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END LDA ____________________ - - //_____________________ LDAB ____________________ - //196 - LoaD Accumulator from memory at Byte - //ldab A, #imm - //Operation data length: 16 bits - //[28 imm] - case 0x28: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, 8); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, dd - //Operation data length: 16 bits - //[0A dd] - case 0x0A: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits - //[0B dd] - case 0x0B: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X); - Operand_Registr(insn.Op3, rX); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[08 dd] - case 0x08: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); - Operand_Registr(insn.Op3, rY); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits - //[09 dd] - case 0x09: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[0E ll mm] - case 0x0E: - insn.itype = m7900_ldab; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[0F ll mm] - case 0x0F: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[0C ll mm hh] - case 0x0C: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); - break; - - //196 - LoaD Accumulator from memory at Byte - //ldab A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[0D ll mm hh] - case 0x0D: - insn.itype = m7900_ldab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END LDAB ____________________ - - //_____________________ STA ____________________ - - //271 - STore Accumulator in memory - //sta A, dd - //Operation data length: 16 bits or 8 bits - //[DA dd] - case 0xDA: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[DB dd] - case 0xDB: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //271 - STore Accumulator in memory - //sta A, (dd), Y () - //Operation data length: 16 bits or 8 bits - //[D8 dd] - case 0xD8: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rY); - break; - - //271 - STore Accumulator in memory - //sta A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 16 bits or 8 bits - //[D9 dd] - case 0xD9: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //271 - STore Accumulator in memory - //sta A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[DE ll mm] - case 0xDE: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[DF ll mm] - case 0xDF: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //271 - STore Accumulator in memory - //sta A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[DC ll mm hh] - case 0xDC: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); - break; - - //271 - STore Accumulator in memory - //sta A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[DD ll mm hh] - case 0xDD: - insn.itype = m7900_sta; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END STA ____________________ - //_____________________ ORA ____________________ - //220 - OR memory with Accumulator - //ora A, #imm - //Operation data length: 16 bits or 8 bits - //[56 imm] - case 0x56: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //220 - OR memory with Accumulator - //ora A, dd - //Operation data length: 16 bits or 8 bits - //[5A dd] - case 0x5A: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[5B dd] - case 0x5B: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //220 - OR memory with Accumulator - //ora A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[5E ll mm] - case 0x5E: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //220 - OR memory with Accumulator - //ora A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[5F ll mm] - case 0x5F: - insn.itype = m7900_ora; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END ORA ____________________ - //_____________________ ADDD ____________________ - //103 - ADd at Double-word - //addd E, #imm - //Operation data length: 32 bits - //[2D imm imm imm imm] - case 0x2D: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm(insn, insn.Op2, 32); - break; - - //103 - ADd at Double-word - //addd E, dd - //Operation data length: 32 bits - //[9A dd] - case 0x9A: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //103 - ADd at Double-word - //addd E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 32 bits - //[9B dd] - case 0x9B: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //103 - ADd at Double-word - //addD E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[9E ll mm] - case 0x9E: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //103 - ADd at Double-word - //add A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[9F ll mm] - case 0x9F: - insn.itype = m7900_addd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END ADDD ____________________ - - //_____________________ LDAD ____________________ - //197 - LoaD Accumulator from memory at Double-word - //addd E, #imm - //Operation data length: 32 bits - //[2C imm imm imm imm] - case 0x2C: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm(insn, insn.Op2, 32); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, dd - //Operation data length: 32 bits - //[8A dd] - case 0x8A: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 32 bits - //[8B dd] - case 0x8B: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, (dd), Y () - //Operation data length: 32 bits - //[88 dd] - case 0x88: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[89 dd] - case 0x89: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldaD E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[8E ll mm] - case 0x8E: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[8F ll mm] - case 0x8F: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 16 bits or 8 bits - //[8C ll mm hh] - case 0x8C: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //197 - LoaD Accumulator from memory at Double-word - //ldad A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[8D ll mm hh] - case 0x8D: - insn.itype = m7900_ldad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END LDAD ____________________ - - //_____________________ CMPD ____________________ - - //163 - CoMPare at Double-word - //cmpd E, #imm - //Operation data length: 32 bits - //[3C imm imm imm imm] - case 0x3C: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm(insn, insn.Op2, 32); - break; - - //163 - CoMPare at Double-word - //cmpd E, dd - //Operation data length: 32 bits - //[BA dd] - case 0xBA: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //163 - CoMPare at Double-word - //cmpd E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 32 bits - //[BB dd] - case 0xBB: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //163 - CoMPare at Double-word - //cmpd E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[BE ll mm] - case 0xBE: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //163 - CoMPare at Double-word - //cmpd A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[BF ll mm] - case 0xBF: - insn.itype = m7900_cmpd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END CMPD ____________________ - - //108 - ADD index register X and immediate - //addx #imm - //Operation data length: 16 bits - //[01 imm] - - //140 - Branch on Single bit Clear - //bsc n, A, rr - //Operation data length: 16 bits or 8 bits - //[01 n+A0 rr] - - //142 - Branch on Single bit Set - //bss n, A, rr - //Operation data length: 16 bits or 8 bits - //[01 n+80 rr] - - case 0x01: - imm = insn.get_next_byte(); - switch ( imm & 0xE0 ) - { - case 0x0: /*addx*/ - insn.itype = m7900_addx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, imm); - break; - - case 0x20: /*addy*/ - insn.itype = m7900_addy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x1F)); - break; - - case 0x40: /*subx*/ - insn.itype = m7900_subx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x1F)); - break; - - case 0x60: /*suby*/ - insn.itype = m7900_suby; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x1F)); - break; - - case 0x80: /*bss*/ - insn.itype = m7900_bss; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x0F)); - Operand_Registr(insn.Op2, rA); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); - break; - - case 0xA0: /*bcs*/ - insn.itype = m7900_bsc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x0F)); - Operand_Registr(insn.Op2, rA); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); - break; - - case 0xC0: /*dxbne*/ - insn.itype = m7900_dxbne; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm -0xC0)); - Operand_Near(insn, insn.Op2, insn.get_next_byte(), 3); - break; - - case 0xE0: /*dybne*/ - insn.itype = m7900_dybne; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm - 0xE0)); - Operand_Near(insn, insn.Op2, insn.get_next_byte(), 3); - break; - } - break; - - //_____________________ AND ____________________ - - //111 - logical AND - //and A, #imm - //Operation data length: 16 bits or 8 bits - //[66 imm] - case 0x66: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //111 - logical AND - //and A, #imm - //Operation data length: 16 bits or 8 bits - //[6A dd] - case 0x6A: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //111 - logical AND - //and A, #imm - //Operation data length: 16 bits or 8 bits - //[6B dd] - case 0x6B: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //111 - logical AND - //and A, #imm - //Operation data length: 16 bits or 8 bits - //[6E ll mm] - case 0x6E: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //111 - logical AND - //and A, #imm - //Operation data length: 16 bits or 8 bits - //[6F ll mm] - case 0x6F: - insn.itype = m7900_and; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //_____________________ END AND ____________________ - - //117 - Arithmetic Shift to Left by n bits - //asl n A,#imm - //Operation data length: 16 bits or 8 bits - //[C1 imm+40] - - //120 - Arithmetic Shift to Right by n bits - //asr n A,#imm - //Operation data length: 16 bits or 8 bits - //[C1 imm+80] - - //169 - DEcrement memory and Branch on Not Equal - //debne dd #imm rr - //Operation data length: 16 bits or 8 bits - //[D1 imm+A0 dd rr] - - //253 - n bits ROtate Left - //rol n #imm - //Operation data length: 16 bits or 8 bits - //[C1 imm+A0] - - //256 - n bits ROtate Right - //ror n #imm - //Operation data length: 16 bits or 8 bits - //[C1 imm+20] - - case 0xC1: - imm = insn.get_next_byte(); - com = imm & 0xE0; - if ( com == 0x20 ) - { - insn.itype = m7900_rorn; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); - } - else if ( com == 0x40 ) - { - insn.itype = m7900_asln; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x0F)); - } - else if ( com == 0x60 ) - { - insn.itype = m7900_roln; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); - } - else if ( com == 0x80 ) - { - insn.itype = m7900_asrn; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); - } - else if ( com == 0xA0 ) - { - insn.itype = m7900_debne; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_DEBNE(insn, insn.Op3, insn.get_next_byte(), 4); - } - else - { - insn.itype = m7900_lsrn; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm_Spesh(insn.Op2, dt_byte, imm); - } - break; - - //118 - Arithmetic Shift to Left by n bits (Double word) - //asld n E,#imm - //Operation data length: 32 bits - //[D1 imm+40] - - //169 - DEcrement memory and Branch on Not Equal - //debne mmll #imm rr - //Operation data length: 16 bits or 8 bits - //[D1 imm+E0 ll mm rr] - - //206 - Logical n bits Shift Right at Double-word - //lsrd E #imm - //Operation data length: 32 bits - //[D1 imm] - - //254 - n bits ROtate Left at Double-word - //rold E #imm - //Operation data length: 32 bits - //[D1 imm+60] - - //254 - n bits ROtate Right at Double-word - //rord E #imm - //Operation data length: 32 bits - //[D1 imm+20] - - case 0xD1: - imm = insn.get_next_byte(); - com = imm & 0xE0; - if ( com == 0x20 ) - { - insn.itype = m7900_rordn; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); - } - else if ( com == 0x40 ) - { - insn.itype = m7900_asldn; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); - } - else if ( com == 0x60 ) - { - insn.itype = m7900_roldn; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); - } - else if ( com == 0x80 ) - { - insn.itype = m7900_asrdn; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); - } - else if ( com == 0xE0 ) - { - insn.itype = m7900_debne; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm_Spesh(insn.Op2, dt_dword, (imm & 0x1F)); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - Operand_DEBNE(insn, insn.Op3, insn.get_next_byte(), 5); - } - else - { - insn.itype = m7900_lsrdn; - RAZOPER = 32; - Operand_Registr(insn.Op1, rE); - Operand_Imm_Spesh(insn.Op2, dt_dword, imm); - } - break; - - //126 - Branch on Carry Clear - //bcc rr - //Operation data length: - - //[90 rr] - - //138 - BRanch Always - //bra rr - //Operation data length: - - //[20 rr] - - //127 - Branch on Carry Set - //bcs rr - //Operation data length: - - //[B0 rr] - - //128 - Branch on EQual - //beq rr - //Operation data length: - - //[F0 rr] - - //129 - Branch on Greater or Equal - //bge rr - //Operation data length: - - //[C0 rr] - - //130 - - //bgt rr - //Operation data length: - - //[80 rr] - - //131 - Branch on Greater Than with Unsign - //bgtu rr - //Operation data length: - - //[40 rr] - - //132 - Branch on Less or Equal - //ble rr - //Operation data length: - - //[A0 rr] - - //133 - Branch on Less Equal with Unsign - //bleu rr - //Operation data length: - - //[60 rr] - - //134 - Branch on Less Than - //blt rr - //Operation data length: - - //[E0 rr] - - //135 - Branch on result MInus - //bmi rr - //Operation data length: - - //[30 rr] - - //136 - Branch on Not Equal - //bne rr - //Operation data length: - - //[D0 rr] - - //137 - Branch on result PLus - //bpl rr - //Operation data length: - - //[10 rr] - - //143 - Branch on oVerflow Clear - //bvc rr - //Operation data length: - - //[50 rr] - - //144 - Branch on oVerflow Set - //bvs rr - //Operation data length: - - //[70 rr] - - case 0x10: - case 0x20: - case 0x30: - case 0x40: - case 0x50: - case 0x60: - case 0x70: - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - case 0xC0: - case 0xD0: - case 0xE0: - case 0xF0: - RAZOPER = 0; - Branch(insn, insn.Op1, nib); - break; - - case 0xA7: - insn.itype = m7900_bral; - RAZOPER = 0; - Bral(insn, insn.Op1, 3); - break; - - //_____________________ CBEQ ____________________ - - //145 - Compare immediate and Branch on EQual - //cbeq A, #imm, rr - //Operation data length: 16 bits or 8 bits - //[A6 imm rr] - case 0xA6: - insn.itype = m7900_cbeq; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 3 : 4); - break; - //_____________________ END CBEQ ____________________ - //_____________________ CBNE ____________________ - //147 - Compare immediate and Branch on Not Equal - //cbne A, #imm, rr - //Operation data length: 16 bits or 8 bits - //[B6 imm rr] - case 0xB6: - insn.itype = m7900_cbne; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 3 : 4); - break; - //_____________________ END CBNE ____________________ - - //_____________________ CLP ____________________ - //153 - CLear Processor status - //clp #imm - //Operation data - - //[98 imm] - case 0x98://clp - insn.itype = m7900_clp; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END CLP ____________________ - - //_____________________ CLPM ____________________ - //155 - CLeaR Memory - //clpm dd - //Operation data - 16 bits or 8 bits - //[D2 dd] - case 0xD2://clrm - insn.itype = m7900_clrm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - //155 - CLeaR Memory - //clpm mmll - //Operation data - 16 bits or 8 bits - //[D7 ll mm] - case 0xD7://clrm - insn.itype = m7900_clrm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - //_____________________ END CLPM ____________________ - - //_____________________ CLPX ____________________ - //157 - CLeaR index register X - //clpx - //Operation data - 16 bits or 8 bits - //[E4] - case 0xE4: - insn.itype = m7900_clrx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - - //158 - CLeaR index register Y - //clpy - //Operation data - 16 bits or 8 bits - //[F4] - case 0xF4: - insn.itype = m7900_clry; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - break; - //_____________________ END CLPX CLPY ____________________ - - //_____________________ CPX ____________________ - //167 - ComPare memory and index register X - //cpx #imm - //Operation data - 16 bits or 8 bits - //[E6 imm] - case 0xE6://cpx - insn.itype = m7900_cpx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); - break; - - //167 - ComPare memory and index register X - //cpx dd - //Operation data - 16 bits or 8 bits - //[22 dd] - case 0x22://cpx - insn.itype = m7900_cpx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - break; - //_____________________ END CPX ____________________ - - //_____________________ CPY ____________________ - //168 - ComPare memory and index register Y - //cpy #imm - //Operation data - 16 bits or 8 bits - //[F6 imm] - case 0xF6://cpy - insn.itype = m7900_cpy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); - break; - - //168 - ComPare memory and index register Y - //cpy dd - //Operation data - 16 bits or 8 bits - //[32 dd] - case 0x32://cpy - insn.itype = m7900_cpy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - break; - //_____________________ END CPY ____________________ - //_____________________ DEC ____________________ - //170 - DECrement by one - //dec A - //Operation data - 16 bits or 8 bits - //[B3] - case 0xB3: - insn.itype = m7900_dec; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - case 0x92: - insn.itype = m7900_dec; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - case 0x97: - insn.itype = m7900_dec; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - //_____________________ END DEC ____________________ - - //_____________________ INC ____________________ - //189 - INCrement by one - //inc A - //Operation data - 16 bits or 8 bits - //[A3] - case 0xA3: - insn.itype = m7900_inc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - - case 0x82: - insn.itype = m7900_inc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - case 0x87: - insn.itype = m7900_inc; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - //_____________________ END INC ____________________ - - //_____________________ LDX ____________________ - //200 - load - //ldx #imm - //Operation data - 16 bits or 8 bits - //[C6] - case 0xC6: - insn.itype = m7900_ldx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); - break; - - case 0x02: - insn.itype = m7900_ldx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - break; - - case 0x07: - insn.itype = m7900_ldx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataX); - break; - //_____________________ END LDX ____________________ - //_____________________ LDXB ____________________ - - //201 - LoaD index register X from memory at Byte - //ldxb #imm - //Operation data - 16 bits - //[27] - case 0x27: - insn.itype = m7900_ldxb; - RAZOPER = INSN_PREF_W; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END LDXB ____________________ - - //_____________________ LDY ____________________ - //202 - LoaD index register Y from memory - //ldy #imm - //Operation data - 16 bits or 8 bits - //[D6] - case 0xD6: - insn.itype = m7900_ldy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); - break; - - case 0x12: - insn.itype = m7900_ldy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - break; - - case 0x17: - insn.itype = m7900_ldy; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16); - break; - //_____________________ END LDY ____________________ - //_____________________ LDYB ____________________ - //202 - LoaD index register Y from memory at Byte - //ldyb #imm - //Operation data - 16 bits - //[37] - case 0x37: - insn.itype = m7900_ldyb; - RAZOPER = INSN_PREF_U; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END LDX ____________________ - //_____________________ JMP ____________________ - //192 - JUMP - //jmp mmll - //Operation data - - //[9C ll mm] - case 0x9C: - { - insn.itype = m7900_jmp; - insn.Op1.type = o_near; - uint32 high = insn.get_next_byte(); - uint32 low = insn.get_next_byte(); - uint32 addr = high | (low<<8); - addr = uint32(addr | (getPG<<16)); - insn.Op1.addr = addr; - } - break; - - //[AC ll mm hh] - case 0xAC://jmpl hhmmll - { - insn.itype = m7900_jmpl; - insn.Op1.type = o_near; - uint32 ll = insn.get_next_byte(); - uint32 mm = insn.get_next_byte(); - uint32 hh = insn.get_next_byte(); - uint32 addr = (ll | (hh<<16)) | (mm<<8); - insn.Op1.addr = addr; - } - break; - - case 0xBC://jmpl mmll((ABS,X)) - insn.itype = m7900_jmp; - Operand_AB(insn, insn.Op1, TAB_INDIRECTED_ABS_X, 16, dt_word); - break; - //_____________________ END JMP ____________________ - - //_____________________ JSR ____________________ - - case 0x9D://jsr mmll - insn.itype = m7900_jsr; - Jsr_16(insn, insn.Op1, getPG); - break; - - case 0xAD://jsrl hhmmll - insn.itype = m7900_jsrl; - Jsr_24(insn, insn.Op1); - break; - - case 0xBD://jsr mmll((ABS,X)) - insn.itype = m7900_jsr; - Operand_AB(insn, insn.Op1, TAB_INDIRECTED_ABS_X, 16, dt_word); - break; - //_____________________ END JSR ____________________ - - //_____________________ LSR ____________________ - //204 - Logical Shift Right - //lsr A - //Operation data - 16 bits or 8 bits - //[43] - case 0x43: - insn.itype = m7900_lsr; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - //_____________________ END LSR ____________________ - //_____________________ ROL ____________________ - //254 - ROtate one bit Left - //rol A - //Operation data - 16 bits or 8 bits - //[13] - case 0x13: - insn.itype = m7900_rol; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - //_____________________ END ROL ____________________ - - //_____________________ ROR ____________________ - //255 - ROtate one bit Right - //ror A - //Operation data - 16 bits or 8 bits - //[53] - case 0x53://ror - insn.itype = m7900_ror; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - break; - //_____________________ END ROR ____________________ - - //_____________________ MOVM ____________________ - - case 0x86://movm dd,#imm(DIR, IMM) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - case 0x5C://movm dd, mmll(DIR, ABS) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - - case 0x5D://movm dd, mmll(DIR, ABS,X) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - case 0x96://movm dd, mmll(ABS, IMM) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - case 0x78://movm dd, mmll(ABS, DIR) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16,SetTypeDataM); - break; - - case 0x79://movm dd, mmll(ABS, DIR) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataM); - break; - - case 0x7C://movm mmll1,mmll2(ABS, ABS) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); - break; - - case 0x58://movm dd1, dd2(DIR, DIR) - insn.itype = m7900_movm; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); - break; - //_____________________ END MOVM ____________________ - - //_____________________ PSH ____________________ - //246 - PuSH - //psh #imm - //Operation data - 16 bits or 8 bits - //[A8 imm] - case 0xA8: - insn.itype = m7900_psh; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END PSH ____________________ - - //_____________________ PUL ____________________ - //246 - PuLl - //pul #imm - //Operation data - 16 bits or 8 bits - //[67 imm] - case 0x67: - insn.itype = m7900_pul; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END PUL ____________________ - //_____________________ SEP ____________________ - case 0x99: - insn.itype = m7900_sep; - Operand_Imm(insn, insn.Op1, 8); - break; - //_____________________ END SEP ____________________ - - //_____________________ STAB ____________________ - //272 - STore Accumulator in memory at Byte - //stab A, dd - //Operation data length: 8 bits - //[CA dd] - case 0xCA: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 8 bits - //[CB dd] - case 0xCB: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, (dd), Y () - //Operation data length: 8 bits - //[C8 dd] - case 0xC8: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); - Operand_Registr(insn.Op3, rY); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 8 bits - //[C9 dd] - case 0xC9: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 8 bits - //[CE ll mm] - case 0xCE: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 8 bits - //[CF ll mm] - case 0xCF: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 8 bits - //[CC ll mm hh] - case 0xCC: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); - break; - - //272 - STore Accumulator in memory at Byte - //stab A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 8 bits - //[CD ll mm hh] - case 0xCD: - insn.itype = m7900_stab; - RAZOPER = INSN_PREF_U; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END STAB ____________________ - - //_____________________ STAD ____________________ - //273 - STore Accumulator in memory at Double-word - //stad E, dd - //Operation data length: 32 bits - //[EA dd] - case 0xEA: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 32 bits - //[EB dd] - case 0xEB: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, (dd), Y () - //Operation data length: 32 bits - //[E8 dd] - case 0xE8: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); - Operand_Registr(insn.Op3, rY); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, L(dd),Y (Direct indirect long addressing mode L(DIR)) - //Operation data length: 32 bits - //[E9 dd] - case 0xE9: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); - Operand_Registr(insn.Op3, rY); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[EE ll mm] - case 0xEE: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[EF ll mm] - case 0xEF: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, hhmmll, Y (Absolute long addressing mode(ABL)) - //Operation data length: 32 bits - //[EC ll mm hh] - case 0xEC: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); - break; - - //273 - STore Accumulator in memory at Double-word - //stad E, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[ED ll mm hh] - case 0xED: - insn.itype = m7900_stad; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END STAD ____________________ - //_____________________ STX ____________________ - //275 - STore index register X in memory - //stx dd - //Operation data length: 16 bits or 8 bits - //[E2 dd] - case 0xE2://stx (DIR) - insn.itype = m7900_stx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - break; - - //275 - STore index register X in memory - //stx mmll - //Operation data length: 16 bits or 8 bits - //[E7 ll mm] - case 0xE7://stx ABS - insn.itype = m7900_stx; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataX); - break; - //_____________________ END STX ____________________ - //_____________________ STY ____________________ - //276 - STore index register Y in memory - //sty dd - //Operation data length: 16 bits or 8 bits - //[F2 dd] - case 0xF2://sty (DIR) - insn.itype = m7900_sty; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); - break; - - case 0xF7://sty ABS - insn.itype = m7900_sty; - RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; - Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataX); - break; - //_____________________END STY ____________________ - - //_____________________ SUB ____________________ - //278 - SUBtract - //sub A, #imm - //Operation data length: 16 bits or 8 bits - //[36 #imm] - case 0x36: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); - break; - - //278 - SUBtract - //sub A, dd - //Operation data length: 16 bits or 8 bits - //[3A dd] - case 0x3A: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); - break; - - //278 - SUBtract - //sub A, dd, X (Direct index X addressing DIR,X) - //Operation data length: 16 bits or 8 bits - //[3B dd] - case 0x3B: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - - //278 - SUBtract - //sub A, mmll (Absolute addressing mode(ABS)) - //Operation data length: 16 bits or 8 bits - //[3E ll mm] - case 0x3E: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); - break; - - //278 - SUBtract - //sub A, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 16 bits or 8 bits - //[3F ll mm] - case 0x3F: - insn.itype = m7900_sub; - RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; - Operand_Registr(insn.Op1, rA); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END SUB ____________________ - //_____________________ SUBD ____________________ - //280 - SUBtract at Double-word - //subd E, #imm - //Operation data length: 32 bits - //[3D #imm] - case 0x3D: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Imm(insn, insn.Op2, 32); - break; - - //280 - SUBtract at Double-word - //subd E, dd - //Operation data length: 32 bits - //[AA dd] - case 0xAA: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); - break; - - //280 - SUBtract at Double-word - //subd E, dd, X (Direct index X addressing DIR,X) - //Operation data length: 32 bits - //[AB dd] - case 0xAB: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - - //280 - SUBtract at Double-word - //subd E, mmll (Absolute addressing mode(ABS)) - //Operation data length: 32 bits - //[AE ll mm] - case 0xAE: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); - break; - - //280 - SUBtract at Double-word - //subd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) - //Operation data length: 32 bits - //[AF ll mm] - case 0xAF: - insn.itype = m7900_subd; - RAZOPER = INSN_PREF_D; - Operand_Registr(insn.Op1, rE); - Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); - Operand_Registr(insn.Op3, rX); - break; - //_____________________ END SUBD ____________________ - - default: - { - uchar cd = code & 0xF8; - if ( cd == 0xF8 ) - { - //141 - Branch to SubRoutine - //bsr rr - //Operation data length: - - //[11111 B10-b0] - - insn.itype = m7900_bsr; - uint32 low = insn.get_next_byte(); - uint32 addr = low | (code<<8); - addr&=0x000007FF; - if ( addr & 0x400 ) - addr |= 0xfffff800; - Operand_BSR(insn, insn.Op1, addr, 2); - } - else - { - //msg("ana: %a: bad optype %d\n", insn.ip, code); - return 0; - } - } - break; - } - return insn.size; -} diff --git a/idasdk75/module/m7900/emu.cpp b/idasdk75/module/m7900/emu.cpp deleted file mode 100644 index 05eefcd..0000000 --- a/idasdk75/module/m7900/emu.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "7900.hpp" - -//------------------------------------------------------------------------ -// convert to data and add cross-ref -static void DataSet(const insn_t &insn, const op_t &x, ea_t EA, int isload) -{ - insn.create_op_data(EA, x); - insn.add_dref(EA, x.offb, isload ? dr_R : dr_W); -} - -//---------------------------------------------------------------------- -void m7900_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) -{ - flags_t F = get_flags(insn.ea); - switch ( x.type ) - { - case o_phrase: - //remember_problem(PR_JUMP, insn.ea); - case o_void: - case o_reg: - break; - - case o_sr: - case o_displ: - set_immd(insn.ea); - if ( !is_forced ) - { - ushort addr = ushort(x.addr); - if ( x.type == o_displ ) - { - addr += (ushort)insn.ip; - addr += insn.size; - uint32 offb = map_code_ea(insn, addr, x.n); - DataSet(insn, x, offb, isload); - } - else if ( op_adds_xrefs(F, x.n) ) - { - insn.add_off_drefs(x, dr_O, 0); - } - } - break; - - case o_stk: - case o_imm: - set_immd(insn.ea); - if ( op_adds_xrefs(F, x.n) ) - insn.add_off_drefs(x, dr_O, 0); - break; - - case o_ab: - if ( x.TypeOper == TAB_INDIRECTED_ABS_X ) - { - ea_t ea = to_ea(insn.cs, x.addr); - insn.create_op_data(ea, x.offb, dt_word); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - - // get data - uint32 Addr; - Addr = get_word(ea); - Addr = uint32(Addr | (getPG<<16)); - insn.add_cref(Addr, 2, fl_JF); - } - else - { - DataSet(insn, x, map_code_ea(insn, x), isload); - } - break; - - case o_mem: - // convert to data, add cross ref - switch ( x.TypeOper ) - { - case TDIR_DIR_Y: - case TDIR_DIR_X: - case TDIR_DIR: - case TDIR_INDIRECT_DIR: - case TDIR_INDIRECT_DIR_X: - case TDIR_INDIRECT_DIR_Y: - case TDIR_L_INDIRECT_DIR: - case TDIR_L_INDIRECT_DIR_Y: - if ( getDPReg == 1 ) - { - insn_t tmp = insn; - op_t &tmpx = tmp.ops[x.n]; - tmpx.addr &= 0xFF3F; - DataSet(tmp, tmpx, map_code_ea(tmp, tmpx), isload); - } - else - { - DataSet(insn, x, map_code_ea(insn, x), isload); - } - break; - default: - DataSet(insn, x, map_code_ea(insn, x), isload); - break; - } - break; - - case o_near: - { - ea_t ea = to_ea(insn.cs, x.addr); - switch ( insn.itype ) - { - case m7900_jsr: - insn.add_cref(ea, x.offb, fl_CN); - if ( !func_does_return(ea) ) - flow = false; - break; - - case m7900_jsrl: - insn.add_cref(ea, x.offb, fl_CF); - if ( !func_does_return(ea) ) - flow = false; - break; - - case m7900_jmpl: - insn.add_cref(ea, x.offb, fl_JF); - break; - - default: - insn.add_cref(ea, x.offb, fl_JN); - break; - } - } - break; - - default: - // warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); - break; - } -} - -//---------------------------------------------------------------------- -static void LDD(const insn_t &ins) -{ - static const int DPR[] = { rDPR0, rDPR1, rDPR2, rDPR3 }; - - for ( int i=0; i < 4; i++ ) - if ( GETBIT(ins.Op1.value, i) == 1 ) - split_sreg_range(ins.ea+ins.size, DPR[i], ins.ops[1+i].value, SR_auto); -} - -//---------------------------------------------------------------------- -int m7900_t::emu(const insn_t &insn) -{ - //Set PG - split_sreg_range(insn.ea, rPG, ( insn.ea & 0xFF0000 ) >> 16, SR_auto); - - uint32 Feature = insn.get_canon_feature(ph); - flow = (Feature & CF_STOP) == 0; - - bool flag1 = is_forced_operand(insn.ea, 0); - bool flag2 = is_forced_operand(insn.ea, 1); - bool flag3 = is_forced_operand(insn.ea, 2); - bool flag4 = is_forced_operand(insn.ea, 3); - bool flag5 = is_forced_operand(insn.ea, 4); - - - if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true); - if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true); - if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true); - if ( Feature & CF_USE4 ) handle_operand(insn, insn.Op4, flag4, true); - if ( Feature & CF_USE5 ) handle_operand(insn, insn.Op5, flag5, true); - - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false); - if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false); - if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false); - if ( Feature & CF_CHG4 ) handle_operand(insn, insn.Op4, flag4, false); - if ( Feature & CF_CHG5 ) handle_operand(insn, insn.Op5, flag5, false); - - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - switch ( insn.itype ) - { - case m7900_lddn: - //split_sreg_range(insn.ea + insn.size, GetDPR(), insn.Op1.value, SR_auto); - LDD(insn); - break; - - case m7900_ldt: - split_sreg_range(insn.ea + insn.size, rDT, insn.Op1.value, SR_auto); - break; - - // clear m flag - case m7900_clm: - split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); - break; - // set m flag - case m7900_sem: - split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); - break; - - // clear processor status - case m7900_clp: - // clear m flag - if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) - split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); - // clear x flag - if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) - split_sreg_range(insn.ea + insn.size, rfX, 0, SR_auto); - break; - - // set processor status - case m7900_sep: - // set m flag - if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) - split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); - // set x flag - if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) - split_sreg_range(insn.ea + insn.size, rfX, 1, SR_auto); - break; - - // pull processor status from stack - case m7900_plp: - split_sreg_range(insn.ea + insn.size, rfM, BADSEL, SR_auto); - split_sreg_range(insn.ea + insn.size, rfX, BADSEL, SR_auto); - break; - - } - return 1; -} diff --git a/idasdk75/module/m7900/ins.cpp b/idasdk75/module/m7900/ins.cpp deleted file mode 100644 index d032685..0000000 --- a/idasdk75/module/m7900/ins.cpp +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include <ida.hpp> -#include <idp.hpp> -#include "ins.hpp" - - - -const instruc_t Instructions[] = -{ - - { "", 0 }, // Unknown Operation - - { "abs", CF_CHG1 }, // ABSolute - { "absd", CF_CHG1 }, // ABSolute at Double-word - - { "adc", CF_CHG1 | CF_USE2 }, // ADd with Carry - { "adcb", CF_CHG1 | CF_USE2 }, // ADd with Carry at Byte - { "adcd", CF_CHG1 | CF_USE2 }, // ADd with Carry at Double-word - - { "add", CF_CHG1 | CF_USE2 }, // Addition - - { "addb", CF_CHG1 | CF_USE2 }, // ADD at Byte - - { "addd", CF_CHG1 | CF_USE2 }, // ADD at Double-word - { "addm", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory - { "addmb", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory at Byte - { "addmd", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory at Double-word - { "adds", CF_USE1 }, // ADD Stack pointer and immediate - { "addx", CF_USE1 }, // ADD index register X and immediate - { "addy", CF_USE1 }, // ADD index register Y and immediate - - { "and", CF_CHG1 | CF_USE2 }, // Logical AND - { "andb", CF_CHG1 | CF_USE2 }, // logical AND between immediate (Byte) - { "andm", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory - { "andmb", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory (Byte) - { "andmd", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory (Double word) - - - { "asl", CF_CHG1 }, // Arithmetic Shift to Left - { "asl", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Left by n bits - { "asld", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Left by n bits (Double word) - - { "asr", CF_CHG1 }, // Arithmetic Shift to Right - { "asr", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Right by n bits - { "asrd", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Right by n bits (Double word) - - { "bbc", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Clear - { "bbcb", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Clear (Byte) - { "bbs", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Set - { "bbsb", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Set (Byte) - - { "bcc", CF_USE1 }, // Branch on Carry Clear - { "bcs", CF_USE1 }, // Branch on Carry Set - { "beq", CF_USE1 }, // Branch on EQual - { "bge", CF_USE1 }, // Branch on Greater or Equal - { "bgt", CF_USE1 }, // Branch on Greater Than - { "bgtu", CF_USE1 }, // Branch on Greater Than with Unsign - { "ble", CF_USE1 }, // Branch on Less or Equal - { "bleu", CF_USE1 }, // Branch on Less Equal with Unsign - { "blt", CF_USE1 }, // Branch on Less Than - { "bmi", CF_USE1 }, // Branch on result MInus - { "bne", CF_USE1 }, // Branch on Not Equal - { "bpl", CF_USE1 }, // Branch on result PLus - { "bra", CF_USE1 | CF_JUMP | CF_STOP }, // BRanch Always - { "bral", CF_USE1 | CF_JUMP | CF_STOP }, // BRanch Always - - { "brk", 0 }, // run int 0xFFFA - - { "bsc", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Single bit Clear - { "bsr", CF_USE1 | CF_CALL }, // Branch to SubRoutine - { "bss", CF_USE1 | CF_USE2 | CF_USE3 }, //Branch on Single bit Set - - { "bvc", CF_USE1 }, // Branch on oVerflow Clear - { "bvs", CF_USE1 }, // Branch on oVerflow Set - - { "cbeq", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on EQual - { "cbeqb", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on EQual at Byte - { "cbne", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on Not Equal - { "cbneb", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on Not Equal at Byte - - { "clc", 0 }, // CLear Carry flag - { "cli", 0 }, // CLear Interrupt disable status - { "clm", 0 }, // CLear M flag - { "clp", CF_USE1 }, // CLear Processor status - - { "clr", CF_CHG1 }, // CLeaR accumulator - { "clrb", CF_CHG1 }, // CLeaR accumulator at Byte - { "clrm", CF_CHG1 }, // CLeaR Memory - { "clrmb", CF_CHG1 }, // CLeaR Memory at Byte - { "clrx", 0 }, // CLeaR index register X - { "clry", 0 }, // CLeaR index register Y - - { "clv", 0 }, // CLear oVerflow flag - - { "cmp", CF_USE1 | CF_USE2 }, // CoMPare - { "cmpb", CF_USE1 | CF_USE2 }, // CoMPare at Byte - { "cmpd", CF_USE1 | CF_USE2 }, // CoMPare at Double-word - { "cmpm", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory - { "cmpmb", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory at Byte - { "cmpmd", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory at Double-word - - { "cpx", CF_USE1 }, // ComPare memory and index register X - { "cpy", CF_USE1 }, // ComPare memory and index register Y - - { "debne", CF_USE1 | CF_USE2 | CF_USE3 }, //DEcrement memory and Branch on Not Equal - - { "dec", CF_CHG1 }, // DECrement by one - { "dex", 0 }, // DEcrement index register X by one - { "dey", 0 }, // DEcrement index register Y by one - - { "div", CF_USE1 }, // DIVide unsigned - { "divs", CF_USE1 }, // DIVide with Sign - { "dxbne", CF_USE1 | CF_USE2 }, //Decrement index register X and Branch on Not Equal - { "dybne", CF_USE1 | CF_USE2 }, //Decrement index register Y and Branch on Not Equal - - { "eor", CF_CHG1 | CF_USE2 }, // Exclusive OR memory with accumulator - { "eorb", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with accumulator at Byte - { "eorm", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory - { "eormb", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory at Byte - { "eormd", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory at Double-word - - { "exts", CF_CHG1 }, // EXTension Sign - { "extsd", CF_CHG1 }, // EXTension Sign at Double-word - { "extz", CF_CHG1 }, // EXTension Zero - { "extzd", CF_CHG1 }, // EXTension Zero at Double-word - - { "inc", CF_CHG1 }, // INCrement by one - { "inx", 0 }, // INcrement index register X by one - { "iny", 0 }, // INcrement index register y by one - - { "jmp", CF_USE1 | CF_JUMP | CF_STOP }, // JuMP16 - { "jmpl", CF_USE1 | CF_JUMP | CF_STOP }, // Jump24 - - { "jsr", CF_USE1 | CF_CALL }, // Jump to SubRoutine16 - { "jsrl", CF_USE1 | CF_CALL }, // Jump to SubRoutine24 - - - { "lda", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory - { "ldab", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory at Byte - { "ldad", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory at Double-word - { "ldd", CF_USE1 | CF_USE2 | CF_USE3 | CF_USE4 | CF_USE5 }, // LoaD immediate to Direct page register n - - { "ldt", CF_USE1 }, // LoaD immediate to DaTa bank register - { "ldx", CF_USE1 }, // LoaD index register X from memory - { "ldxb", CF_USE1 }, // LoaD index register X from memory at Byte - { "ldy", CF_USE1 }, // LoaD index register Y from memory - { "ldyb", CF_USE1 }, // LoaD index register Y from memory at Byte - - { "lsr", CF_CHG1 }, // Logical Shift Right - { "lsr", CF_USE2 | CF_CHG1 }, // Logical n bits Shift Right - { "lsrd", CF_USE2 | CF_CHG1 }, // Logical n bits Shift Right at Double-word - - { "movm", CF_USE2 | CF_CHG1 }, // MOVe Memory to memory - { "movmb", CF_USE2 | CF_CHG1 }, // MOVe Memory to memory at Byte - { "movr", CF_USE1 | CF_HLL }, // MOVe Repeat memory to memory - { "movrb", CF_USE1 | CF_HLL }, // MOVe Repeat memory to memory at Byte - - { "mpy", CF_USE1 }, // MultiPlY - { "mpys", CF_USE1 }, // MultiPlY with Sign - - { "mvn", CF_USE1 | CF_USE2 }, // MoVe Negative - { "mvp", CF_USE1 | CF_USE2 }, // MoVe Positive - - { "neg", CF_CHG1 }, // NEGative - { "negd", CF_CHG1 }, // NEGative at Double-word - { "nop", 0 }, // No OPeration - - - { "ora", CF_CHG1 | CF_USE2 }, // OR memory with Accumulator - { "orab", CF_CHG1 | CF_USE2 }, // OR immediate with Accumulator at Byte - { "oram", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory - { "oramb", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory at Byte - { "oramd", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory at Double-word - - - { "pea", CF_USE1 }, // Push Effective Address - { "pei", CF_USE1 }, // Push Effective Indirect address - { "per", CF_USE1 }, // Push Effective program counter Relative address - { "pha", 0 }, // PusH accumulator A on stack - { "phb", 0 }, // PusH accumulator B on stack - { "phd", 0 }, // PusH Direct page register on stack - { "phd", CF_USE1 }, // PusH Direct page register n on stack - { "phg", 0 }, // PusH proGram bank register on stack - - { "phld", CF_USE1 | CF_HLL }, // PusH dpr n to stack and Load immediate to Dpr n - - { "php", 0 }, // PusH Processor status on stack - { "pht", 0 }, // PusH daTa bank register on stack - { "phx", 0 }, // PusH index register X on stack - { "phy", 0 }, // PusH index register Y on stack - - { "pla", 0 }, // PuLl accumulator A from stack - { "plb", 0 }, // PuLl accumulator B from stack - { "pld", 0 }, // PuLl Direct page register from stack - { "pld", CF_USE1 }, // PuLl Direct page register n from stack - { "plp", 0 }, // PuLl Processor status from stack - { "plt", 0 }, // PuLl daTa bank register from stack - { "plx", 0 }, // PuLl index register X from stack - { "ply", 0 }, // PuLl index register Y from stack - - { "psh", CF_USE1 }, // PuSH - { "pul", CF_USE1 }, // PuLl - - { "rla", CF_USE1 }, // Rotate Left accumulator A - { "rmpa", CF_USE1 }, // Repeat Multiply and Accumulate - - { "rol", CF_CHG1 }, // ROtate one bit Left - { "rol", CF_USE2 | CF_CHG1 }, // n bits ROtate Left - { "rold", CF_USE2 | CF_CHG1 }, // n bits ROtate Left at Double-word - - { "ror", CF_CHG1 }, // ROtate one bit Right - { "ror", CF_USE2 | CF_CHG1 }, // n bits ROtate Right - { "rord", CF_USE2 | CF_CHG1 }, // n bits ROtate Right at Double-word - - { "rti", CF_STOP }, // Return from Interrupt - { "rtl", CF_STOP }, // ReTurn from subroutine Long - { "rtld", CF_USE1 | CF_STOP }, // ReTurn from subroutine Long and pull Direct page register n - { "rts", CF_STOP }, // ReTurn from Subroutine - { "rtsd", CF_USE1 | CF_STOP }, // ReTurn from Subroutine and pull Direct page register n - - - { "sbc", CF_USE1 | CF_USE2 }, // SuBtract with Carry - { "sbcb", CF_USE1 | CF_USE2 }, // SuBtract with Carry at Byte - { "sbcd", CF_USE1 | CF_USE2 }, // SuBtract with Carry at Double-word - - - { "sec", 0 }, // SEt Carry flag - { "sei", 0 }, // SEt Interrupt disable status - { "sem", 0 }, // SEt M flag - { "sep", CF_USE1 }, // SEt Processor status - - - { "sta", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory - { "stab", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory at Byte - { "stad", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory at Double-word - - { "stp", 0 }, // SToP - - { "stx", CF_CHG1 }, // STore index register X in memory - { "sty", CF_CHG1 }, // STore index register Y in memory - - { "sub", CF_CHG1 | CF_USE2 }, // SUBtract - { "subb", CF_CHG1 | CF_USE2 }, // SUBtract at Byte - { "subd", CF_CHG1 | CF_USE2 }, // SUBtract at Double-word - { "subm", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory - { "submb", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory at Byte - { "submd", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory at Double-word - - { "subs", CF_USE1 }, // SUBtract Stack pointer - { "subx", CF_USE1 }, // SUBtract immediate from index register X - { "suby", CF_USE1 }, // SUBtract immediate from index register Y - - { "tad", CF_USE1 }, // Transfer accumulator A to Direct page register n - - { "tas", 0 }, // Transfer accumulator A to Stack pointer - { "tax", 0 }, // Transfer accumulator A to index register X - { "tay", 0 }, // Transfer accumulator A to index register Y - - { "tbd", CF_USE1 }, // Transfer accumulator B to Direct page register n - - { "tbs", 0 }, // Transfer accumulator B to Stack pointer - { "tbx", 0 }, // Transfer accumulator B to index register X - { "tby", 0 }, // Transfer accumulator B to index register Y - - { "tda", CF_USE1 }, // Transfer Direct page register n to accumulator A - { "tdb", CF_USE1 }, // Transfer Direct page register n to accumulator B - - { "tds", 0 }, // Transfer Direct page register to Stack pointer - { "tsa", 0 }, // Transfer Stack pointer to accumulator A - { "tsb", 0 }, // Transfer Stack pointer to accumulator B - - { "tsd", 0 }, //Transfer Stack pointer to Direct page register - { "tsx", 0 }, // Transfer Stack pointer to index register X - { "txa", 0 }, // Transfer index register X to accumulator A - { "txb", 0 }, // Transfer index register X to accumulator B - { "txs", 0 }, // Transfer index register X to Stack pointer - { "txy", 0 }, // Transfer index register X to Y - { "tya", 0 }, // Transfer index register Y to accumulator A - { "tyb", 0 }, // Transfer index register Y to accumulator B - { "tyx", 0 }, // Transfer index register Y to X - - { "wit", CF_STOP }, // WaIT - - { "xab", 0 }, // eXchange accumulator A and B - -}; - -CASSERT(qnumber(Instructions) == m7900_last); diff --git a/idasdk75/module/m7900/ins.hpp b/idasdk75/module/m7900/ins.hpp deleted file mode 100644 index c99d3dc..0000000 --- a/idasdk75/module/m7900/ins.hpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * MITSUBISHI 7900 Family - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ -m7900_null = 0, // Unknown Operation - - -m7900_abs, // ABSolute -m7900_absd, // ABSolute at Double-word - -m7900_adc, // ADd with Carry -m7900_adcb, // ADd with Carry at Byte -m7900_adcd, // ADd with Carry at Double-word - -m7900_add, // Addition - -m7900_addb, // ADD at Byte -m7900_addd, // ADD at Double-word -m7900_addm, // ADD immediate and Memory -m7900_addmb, // ADD immediate and Memory at Byte -m7900_addmd, // ADD immediate and Memory at Double-word -m7900_adds, // ADD Stack pointer and immediate -m7900_addx, // ADD index register X and immediate -m7900_addy, // ADD index register Y and immediate - -m7900_and, // Logical AND -m7900_andb, // logical AND between immediate (Byte) - -m7900_andm, // logical AND between immediate value and Memory -m7900_andmb, // logical AND between immediate value and Memory (Byte) -m7900_andmd, // logical AND between immediate value and Memory (Double word) - -m7900_asl, // Arithmetic Shift to Left -m7900_asln, // Arithmetic Shift to Left by n bits -m7900_asldn, // Arithmetic Shift to Left by n bits (Double word) - - -m7900_asr, // Arithmeticshift to the right -m7900_asrn, // Arithmetic Shift to Right by n bits -m7900_asrdn, //Arithmetic Shift to Right by n bits (Double word) - -m7900_bbc, // Branch on Bit Clear -m7900_bbcb, // Branch on Bit Clear (Byte) -m7900_bbs, // Branch on Bit Set -m7900_bbsb, // Branch on Bit Set (Byte) - -m7900_bcc, // Branch on Carry Clear -m7900_bcs, // Branch on Carry Set -m7900_beq, // Branch on EQual -m7900_bge, // Branch on Greater or Equal -m7900_bgt, // Branch on Greater Than -m7900_bgtu, // Branch on Greater Than with Unsign -m7900_ble, // Branch on Less or Equal -m7900_bleu, // Branch on Less Equal with Unsign -m7900_blt, // Branch on Less Than -m7900_bmi, // Branch on result MInus -m7900_bne, // Branch on Not Equal -m7900_bpl, // Branch on result PLus -m7900_bra, // BRanch Always -m7900_bral, // BRanch Always - -m7900_brk, // force BReaK - -m7900_bsc, // Branch on Single bit Clear -m7900_bsr, // Branch to SubRoutine -m7900_bss, // Branch on Single bit Set - -m7900_bvc, // Branch on oVerflow Clear -m7900_bvs, // Branch on oVerflow Set - -m7900_cbeq, // Compare immediate and Branch on EQual -m7900_cbeqb, // Compare immediate and Branch on EQual at Byte -m7900_cbne, // Compare immediate and Branch on Not Equal -m7900_cbneb, // Compare immediate and Branch on Not Equal at Byte - -m7900_clc, // CLear Carry flag -m7900_cli, // CLear Interrupt disable status -m7900_clm, // CLear M flag -m7900_clp, // CLear Processor status - -m7900_clr, // CLeaR accumulator -m7900_clrb, // CLeaR accumulator at Byte -m7900_clrm, // CLeaR Memory -m7900_clrmb, // CLeaR Memory at Byte -m7900_clrx, // CLeaR index register X -m7900_clry, // CLeaR index register Y - -m7900_clv, // CLear oVerflow flag - -m7900_cmp, // CoMPare -m7900_cmpb, // CoMPare at Byte -m7900_cmpd, // CoMPare at Double-word -m7900_cmpm, // CoMPare immediate with Memory -m7900_cmpmb, // CoMPare immediate with Memory at Byte -m7900_cmpmd, // CoMPare immediate with Memory at Double-word - -m7900_cpx, // ComPare memory and index register X -m7900_cpy, // ComPare memory and index register Y - -m7900_debne, // DEcrement memory and Branch on Not Equal - -m7900_dec, // DECrement by one -m7900_dex, // DEcrement index register X by one -m7900_dey, // DEcrement index register Y by one - -m7900_div, // DIVide unsigned -m7900_divs, // DIVide with Sign -m7900_dxbne, // Decrement index register X and Branch on Not Equal -m7900_dybne, // Decrement index register Y and Branch on Not Equal - -m7900_eor, // Exclusive OR memory with accumulator -m7900_eorb, // Exclusive OR immediate with accumulator at Byte -m7900_eorm, // Exclusive OR immediate with Memory -m7900_eormb, // Exclusive OR immediate with Memory at Byte -m7900_eormd, // Exclusive OR immediate with Memory at Double-word - -m7900_exts, // EXTension Sign -m7900_extsd, // EXTension Sign at Double-word -m7900_extz, // EXTension Zero -m7900_extzd, // EXTension Zero at Double-word - -m7900_inc, // INCrement by one -m7900_inx, // INcrement index register X by one -m7900_iny, // INcrement index register y by one - -m7900_jmp, // Jump -m7900_jmpl, // Jump - -m7900_jsr, // Jump to SubRoutine -m7900_jsrl, // Jump to SubRoutine - - -m7900_lda, // LoaD Accumulator from memory -m7900_ldab, // LoaD Accumulator from memory at Byte -m7900_ldad, // LoaD Accumulator from memory at Double-word -m7900_lddn, // LoaD immediate to Direct page register n - -m7900_ldt, // LoaD immediate to DaTa bank register -m7900_ldx, // LoaD index register X from memory -m7900_ldxb, // LoaD index register X from memory at Byte -m7900_ldy, // LoaD index register Y from memory -m7900_ldyb, // LoaD index register Y from memory at Byte - -m7900_lsr, // Logical Shift Right -m7900_lsrn, // Logical n bits Shift Right -m7900_lsrdn, // Logical n bits Shift Right at Double-word - -m7900_movm, // MOVe Memory to memory -m7900_movmb, // MOVe Memory to memory at Byte -m7900_movr, // MOVe Repeat memory to memory -m7900_movrb, // MOVe Repeat memory to memory at Byte - -m7900_mpy, // MultiPlY -m7900_mpys, // MultiPlY with Sign - -m7900_mvn, // MoVe Negative -m7900_mvp, // MoVe Positive - -m7900_neg, // NEGative -m7900_negd, // NEGative at Double-word - -m7900_nop, // No OPeration - -m7900_ora, // OR memory with Accumulator -m7900_orab, // OR immediate with Accumulator at Byte -m7900_oram, // OR immediAte with Memory -m7900_oramb, // OR immediAte with Memory at Byte -m7900_oramd, // OR immediAte with Memory at Double-word - -m7900_pea, // Push Effective Address -m7900_pei, // Push Effective Indirect address -m7900_per, // Push Effective program counter Relative address -m7900_pha, // PusH accumulator A on stack -m7900_phb, // PusH accumulator B on stack -m7900_phd, // PusH Direct page register on stack -m7900_phdn, // PusH Direct page register n on stack -m7900_phg, // PusH proGram bank register on stack - -m7900_phldn, // PusH dpr n to stack and Load immediate to Dpr n - -m7900_php, // PusH Processor status on stack -m7900_pht, // PusH daTa bank register on stack -m7900_phx, // PusH index register X on stack -m7900_phy, // PusH index register Y on stack - -m7900_pla, // PuLl accumulator A from stack -m7900_plb, // PuLl accumulator B from stack -m7900_pld, // PuLl Direct page register from stack -m7900_pldn, // PuLl Direct page register n from stack -m7900_plp, // PuLl Processor status from stack -m7900_plt, // PuLl daTa bank register from stack -m7900_plx, // PuLl index register X from stack -m7900_ply, // PuLl index register Y from stack - -m7900_psh, // PuSH -m7900_pul, // PuLl - -m7900_rla, // Rotate Left accumulator A -m7900_rmpa, // Repeat Multiply and Accumulate - -m7900_rol, // ROtate one bit Left -m7900_roln, // n bits ROtate Left - -m7900_roldn, // n bits ROtate Left at Double-word - -m7900_ror, // ROtate one bit Right -m7900_rorn, // n bits ROtate Right -m7900_rordn, // n bits ROtate Right at Double-word - -m7900_rti, // Return from Interrupt -m7900_rtl, // ReTurn from subroutine Long -m7900_rtld, // ReTurn from subroutine Long and pull Direct page register n -m7900_rts, // ReTurn from Subroutine -m7900_rtsdn, // ReTurn from Subroutine and pull Direct page register n - - -m7900_sbc, // SuBtract with Carry -m7900_sbcb, // SuBtract with Carry at Byte -m7900_sbcd, // SuBtract with Carry at Double-word - - -m7900_sec, // SEt Carry flag -m7900_sei, // SEt Interrupt disable status -m7900_sem, // SEt M flag -m7900_sep, // SEt Processor status - - -m7900_sta, // STore Accumulator in memory -m7900_stab, // STore Accumulator in memory at Byte -m7900_stad, // STore Accumulator in memory at Double-word - - -m7900_stp, // SToP -m7900_stx, // STore index register X in memory -m7900_sty, // STore index register Y in memory - -m7900_sub, // SUBtract -m7900_subb, // SUBtract at Byte -m7900_subd, // SUBtract at Double-word -m7900_subm, // SUBtract immediate from Memory -m7900_submb, // SUBtract immediate from Memory at Byte -m7900_submd, // SUBtract immediate from Memory at Double-word -m7900_subs, // SUBtract Stack pointer -m7900_subx, // SUBtract immediate from index register X -m7900_suby, // SUBtract immediate from index register Y - - - -m7900_tadn, // Transfer accumulator A to Direct page register n - - -m7900_tas, // Transfer accumulator A to Stack pointer -m7900_tax, // Transfer accumulator A to index register X -m7900_tay, // Transfer accumulator A to index register Y - -m7900_tbdn, // Transfer accumulator B to Direct page register n - -m7900_tbs, // Transfer accumulator B to Stack pointer -m7900_tbx, // Transfer accumulator B to index register X -m7900_tby, // Transfer accumulator B to index register Y - -m7900_tdan, // Transfer Direct page register n to accumulator A -m7900_tdbn, // Transfer Direct page register n to accumulator B - -m7900_tds, // Transfer Direct page register to Stack pointer - - -m7900_tsa, // Transfer Stack pointer to accumulator A -m7900_tsb, // Transfer Stack pointer to accumulator B -m7900_tsd, // Transfer Stack pointer to Direct page register -m7900_tsx, // Transfer Stack pointer to index register X -m7900_txa, // Transfer index register X to accumulator A -m7900_txb, // Transfer index register X to accumulator B -m7900_txs, // Transfer index register X to Stack pointer -m7900_txy, // Transfer index register X to Y -m7900_tya, // Transfer index register Y to accumulator A -m7900_tyb, // Transfer index register Y to accumulator B -m7900_tyx, // Transfer index register Y to X - -m7900_wit, // WaIT - -m7900_xab, // eXchange accumulator A and B - -m7900_last // - - }; - -#endif diff --git a/idasdk75/module/m7900/makefile b/idasdk75/module/m7900/makefile deleted file mode 100644 index 57ac0e4..0000000 --- a/idasdk75/module/m7900/makefile +++ /dev/null @@ -1,43 +0,0 @@ -PROC=m7900 -CONFIGS=m7900.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp 7900.hpp ana.cpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp 7900.hpp emu.cpp ins.hpp -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp 7900.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp 7900.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/m7900/out.cpp b/idasdk75/module/m7900/out.cpp deleted file mode 100644 index b35a6ee..0000000 --- a/idasdk75/module/m7900/out.cpp +++ /dev/null @@ -1,846 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "7900.hpp" - -static const char *const BitNamesCPU[] = { "IPL", "N", "V", "m", "x", "D", "I", "Z", "C" }; -static const char *const BitNamesPUL[] = { "PS", "0", "DT", "DP0", "Y", "X", "B", "A" }; - -//---------------------------------------------------------------------- -class out_m7900_t : public outctx_t -{ - out_m7900_t(void) = delete; // not used -public: - void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); } - int OutVarName(const op_t &x); - void SetDP0Plus(const op_t &x) { out_value(x, OOFW_IMM | OOFW_16); } - void GetNumPUL(uval_t data); - void GetNumDPRn(uval_t data); - void GetCLPFlags(uval_t data); - ea_t OutDPRReg(ea_t Addr, uval_t gDPReg); - void OutDPR(uint32 Data); - void OutDT(uint32 Data); - void OutIMM(uint32 Data); - void MOVRB(void); - void MOVR(void); - void MOV(const op_t &x); - - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); -}; -CASSERT(sizeof(out_m7900_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_m7900_t) - -//---------------------------------------------------------------------- -void out_m7900_t::GetNumPUL(uval_t data) -{ - int bitOut = 0; - for ( int i=0; i < 8; i++ ) - { - if ( GETBIT(data, i) == 1 ) - { - if ( bitOut != 0 ) - out_symbol(','); - out_register(BitNamesPUL[7-i]); - if ( bitOut == 0 ) - bitOut++; - } - } -} - -//---------------------------------------------------------------------- -void out_m7900_t::GetNumDPRn(uval_t data) -{ - switch ( data ) - { - case 0x1: - out_symbol('0'); - break; - case 0x2: - out_symbol('1'); - break; - case 0x4: - out_symbol('2'); - break; - case 0x8: - out_symbol('3'); - break; - default: - out_symbol('('); - bool add_comma = false; - for ( int i=0; i < 4; ++i ) - { - if ( GETBIT(data, i) == 1 ) - { - if ( add_comma ) - out_symbol(','); - out_long(i, 10); - add_comma = true; - } - } - out_symbol(')'); - break; - } -} - -//---------------------------------------------------------------------- -void out_m7900_t::GetCLPFlags(uval_t data) -{ - int bitOut = 0; - for ( int i=0; i < 8; i++ ) - { - if ( GETBIT(data, i) == 1 ) - { - if ( bitOut != 0 ) - out_symbol(','); - out_register(BitNamesCPU[8-i]); - if ( bitOut == 0 ) - bitOut++; - } - } -} - -//---------------------------------------------------------------------- -int out_m7900_t::OutVarName(const op_t &x) -{ - return out_name_expr(x, to_ea(insn.cs, x.addr), x.addr); -} - -//---------------------------------------------------------------------- -static int getNumDPR(uval_t iDPR ) -{ - switch ( iDPR ) - { - case 0x0: return 0; - case 0x40: return 1; - case 0x80: return 2; - case 0xC0: return 3; - } - return 0; - -} - -//---------------------------------------------------------------------- -ea_t out_m7900_t::OutDPRReg(ea_t Addr, uval_t gDPReg) -{ - if ( gDPReg == 1 ) - { - char szTemp[5]; - uval_t Data = Addr; - Data &= 0xC0; - qsnprintf(szTemp, sizeof(szTemp), "DP%d", getNumDPR(Data)); - out_register(szTemp); - Addr &= 0xFF3F; - } - else - { - out_keyword("DP0"); - } - return Addr; -} - -//---------------------------------------------------------------------- -static sel_t GetValueDP(const insn_t &insn, int DPR ) -{ - if ( getDPReg == 1 ) - { - switch ( DPR ) - { - case 0x0: return getDPR0; - case 0x40: return getDPR1; - case 0x80: return getDPR2; - case 0xC0: return getDPR3; - } - } - return 0; -} - -//---------------------------------------------------------------------- -void out_m7900_t::OutDPR(uint32 Data) -{ - ea_t Val = Data; - Val = OutDPRReg(Val, getDPReg); - out_symbol(':'); - out_printf(COLSTR("%a",SCOLOR_NUMBER), Val+GetValueDP(insn, Data&0xC0)); -} - -//---------------------------------------------------------------------- -void out_m7900_t::OutDT(uint32 Data) -{ - out_register("DT"); - out_symbol('+'); - out_symbol(':'); - out_printf(COLSTR("%X",SCOLOR_NUMBER), Data); -} - -//---------------------------------------------------------------------- -void out_m7900_t::OutIMM(uint32 Data) -{ - out_symbol('#'); - out_printf(COLSTR("%x",SCOLOR_NUMBER), Data); -} - -//---------------------------------------------------------------------- -void out_m7900_t::MOVRB(void) -{ - int i; - uint32 Val1, Val2; - uchar code = get_byte(insn.ea+1); - uchar nib = (code >> 4) & 0xF; - uchar count = code & 0x0F; - - switch ( nib ) - { - case 0x0: - for ( i=0; i < count; i++ ) - { - Val1 = get_byte(insn.ea+2+(i*2));//imm - Val2 = get_byte(insn.ea+2+(i*2)+1);//dd - - //DPRxx - OutDPR(Val2); - out_symbol(','); - //imm - OutIMM(Val1); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x1: - for ( i=0; i < count; i++ ) - { - Val2 = get_word(insn.ea+2+(i*3));//mmll - Val1 = get_byte(insn.ea+2+(i*3)+2);//dd - - //DPRxx - OutDPR(Val1); - out_symbol(','); - //DPR - OutDT(Val2); - out_symbol(','); - OutReg(rX); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x2: - for ( i=0; i < count; i++ ) - { - Val1 = get_byte(insn.ea+2+(i*3));//imm - Val2 = get_word(insn.ea+2+(i*3)+1);//mmll - - //DPRxx - OutDT(Val2); - out_symbol(','); - //IMM - OutIMM(Val1); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x4: - for ( i=0; i < count; i++ ) - { - Val1 = get_byte(insn.ea+2+(i*2));//dd1 - Val2 = get_byte(insn.ea+2+(i*2)+1);//dd2 - - //DPRxx - OutDPR(Val2); - out_symbol(','); - //DPRxx - OutDPR(Val1); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x6: - for ( i=0; i < count; i++ ) - { - Val1 = get_byte(insn.ea+2+(i*3));//imm - Val2 = get_word(insn.ea+2+(i*3)+1);//mmll - - //DPRxx - OutDT(Val2); - out_symbol(','); - //DPR - OutDPR(Val1); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x7: - for ( i=0; i < count; i++ ) - { - Val2 = get_byte(insn.ea+2+(i*3));//mmll - Val1 = get_word(insn.ea+2+(i*3)+1);//dd - - //DPRxx - OutDT(Val1); - out_symbol(','); - //DPR - OutDPR(Val2); - out_symbol(','); - OutReg(rX); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x8: - for ( i=0; i < count; i++ ) - { - Val2 = get_word(insn.ea+2+(i*3));//mmll - Val1 = get_byte(insn.ea+2+(i*3)+2);//dd - - //DPRxx - OutDPR(Val1); - out_symbol(','); - //DT - OutDT(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0xA: - for ( i=0; i < count; i++ ) - { - Val1 = get_word(insn.ea+2+(i*4));//imm - Val2 = get_word(insn.ea+2+(i*4)+2);//mmll - - //DPRxx - OutDT(Val2); - out_symbol(','); - //DT - OutDT(Val1); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - } -} - -//---------------------------------------------------------------------- -void out_m7900_t::MOVR(void) -{ - int i; - uint32 Val1, Val2; - uchar code = get_byte(insn.ea+1); - uchar nib = (code >> 4) & 0xF; - uchar count = code & 0x0F; - - switch ( nib ) - { - case 0x0: - for ( i=0; i < count; i++ ) - { - Val2 = get_word(insn.ea+2+(i*3));//mmll - Val1 = get_byte(insn.ea+2+(i*3)+2);//dd - - //DPRxx - OutDPR(Val1); - out_symbol(','); - //DT - OutDT(Val2); - out_symbol(','); - OutReg(rX); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x1: - for ( i=0; i < count; i++ ) - { - if ( getFlag_M == 0 ) - { - Val2 = get_word(insn.ea+2+(i*3));//imm - Val1 = get_byte(insn.ea+2+(i*3)+2);//dd - } - else - { - Val2 = get_byte(insn.ea+2+(i*2));//imm - Val1 = get_byte(insn.ea+2+(i*2)+1);//dd - } - - //DPRxx - OutDPR(Val1); - out_symbol(','); - //imm - OutIMM(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x3: - for ( i=0; i < count; i++ ) - { - if ( getFlag_M == 0 ) - { - Val2 = get_word(insn.ea+2+(i*4));//imm - Val1 = get_word(insn.ea+2+(i*4)+2);//llmm - } - else - { - Val2 = get_byte(insn.ea+2+(i*3));//imm - Val1 = get_word(insn.ea+2+(i*3)+1);//llmm - } - - //DPRxx - OutDT(Val1); - out_symbol(','); - //IMM - OutIMM(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x5: - for ( i=0; i < count; i++ ) - { - Val2 = get_byte(insn.ea+2+(i*2));//dd - Val1 = get_byte(insn.ea+2+(i*2)+1);//dd - - //DPRxx - OutDPR(Val1); - out_symbol(','); - //DPR - OutDPR(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x6: - for ( i=0; i < count; i++ ) - { - Val1 = get_byte(insn.ea+2+(i*3));//imm - Val2 = get_word(insn.ea+2+(i*3)+1);//mmll - - //DPRxx - OutDT(Val2); - out_symbol(','); - //DPR - OutDPR(Val1); - out_symbol(','); - OutReg(rX); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x7: - for ( i=0; i < count; i++ ) - { - Val2 = get_byte(insn.ea+2+(i*3));//mmll - Val1 = get_word(insn.ea+2+(i*3)+1);//dd - - //DPRxx - OutDT(Val1); - out_symbol(','); - //DPR - OutDPR(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0x9: - for ( i=0; i < count; i++ ) - { - Val2 = get_word(insn.ea+2+(i*3));//mmll - Val1 = get_byte(insn.ea+2+(i*3)+2);//dd - - //DPRxx - OutDPR(Val1); - out_symbol(','); - //DPR - OutDT(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - - case 0xB: - for ( i=0; i < count; i++ ) - { - Val2 = get_word(insn.ea+2+(i*4));//imm - Val1 = get_word(insn.ea+2+(i*4)+2);//llmm - - //DT - OutDT(Val1); - out_symbol(','); - //DT - OutDT(Val2); - - if ( i != (count-1) ) - out_symbol(','); - } - break; - } -} - -//---------------------------------------------------------------------- -void out_m7900_t::MOV(const op_t &x) -{ - switch ( x.TypeOper ) - { - case m7900_movrb: MOVRB(); break; - case m7900_movr: MOVR(); break; - default: - //msg("out: %a: bad prefix %d\n", insn.ip, RAZOPER); - break; - } -} - -//---------------------------------------------------------------------- -bool out_m7900_t::out_operand(const op_t &x) -{ - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - OutReg(x.reg); - break; - - case o_phrase: - out_line(ph.reg_names[x.reg]); - break; - - case o_ab: - switch ( x.TypeOper ) - { - case TAB_L_INDIRECTED_ABS: - out_symbol('L'); - // fallthrough - - case TAB_INDIRECTED_ABS: - out_symbol('('); - if ( !OutVarName(x) ) - out_value(x, OOF_ADDR | OOFS_NOSIGN); - out_symbol(')'); - break; - - case TAB_INDIRECTED_ABS_X: - out_symbol('('); - - if ( !OutVarName(x) ) - out_value(x, OOF_ADDR | OOFS_NOSIGN); - - out_symbol(','); - OutReg(rX); - out_symbol(')'); - break; - - case TAB_ABS_Y: - case TAB_ABS_X: - case TAB_ABS: - out_register("DT"); - out_symbol(':'); - - if ( !OutVarName(x) ) - out_value(x, OOF_ADDR | OOFS_NOSIGN | OOFW_32); - break; - - case TAB_ABL_X: - case TAB_ABL: - out_register("LG"); - out_symbol(':'); - - if ( !OutVarName(x) ) - out_value(x, OOF_ADDR | OOFS_NOSIGN | OOFW_32); - break; - } - break; - - case o_sr: - if ( x.TypeOper == TSP_INDEX_SP_Y ) - out_symbol('('); - - if ( x.xmode == IMM_32 ) - out_value(x, OOFW_IMM | OOFW_32); - else if ( x.xmode == IMM_16 ) - out_value(x, OOFW_IMM | OOFW_16); - else - out_value(x, OOFW_IMM); - - if ( x.TypeOper == TSP_INDEX_SP_Y ) - { - out_symbol(','); - OutReg(rPS); - out_symbol(')'); - } - break; - - case o_stk: - // there are special cases - switch ( insn.itype ) - { - case m7900_pei: SetDP0Plus(x); break; - case m7900_psh: - case m7900_pul: GetNumPUL(x.value); break; - - default: - out_symbol('#'); - out_value(x, OOFW_IMM | OOFS_NOSIGN); - break; - } - break; - - case o_imm: - // there are special cases - switch ( insn.itype ) - { - case m7900_sep://Set Processor status - case m7900_clp://CLear Processor status - GetCLPFlags(x.value); - break; - - case m7900_lddn: - case m7900_tdan: - case m7900_phdn: - case m7900_rtsdn: - case m7900_pldn: - case m7900_rtld: - case m7900_phldn: - GetNumDPRn(x.value); - break; - case m7900_bsc: - case m7900_bss: - out_value(x, OOFW_IMM); - break; - - default: - out_symbol('#'); - out_value(x, OOFW_IMM); - break; - } - break;//case o_imm - - case o_mem: - // output memory variable name (for example 'byte_98') - if ( x.TypeOper == m7900_movr || x.TypeOper == m7900_movrb ) - { - MOV(x); - break; - } - - switch ( x.TypeOper ) - { - case TDIR_DIR_Y: - case TDIR_DIR_X: - case TDIR_DIR: - { - op_t y = x; - y.addr = OutDPRReg(y.addr, getDPReg); - out_symbol(':'); - if ( !OutVarName(y) ) - out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN); - } - break; - - case TDIR_L_INDIRECT_DIR_Y: - case TDIR_L_INDIRECT_DIR: - out_symbol('L'); - // fallthrough - - case TDIR_INDIRECT_DIR_Y: - case TDIR_INDIRECT_DIR: - out_symbol('('); - { - op_t y = x; - y.addr = OutDPRReg(y.addr, getDPReg); - out_symbol(':'); - if ( !OutVarName(y) ) - out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN); - } - out_symbol(')'); - break; - - case TDIR_INDIRECT_DIR_X: - out_symbol('('); - - { - op_t y = x; - y.addr = OutDPRReg(y.addr, getDPReg); - out_symbol(':'); - if ( !OutVarName(y) ) - out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN); - } - - out_symbol(','); - OutReg(rX); - out_symbol(')'); - break; - } - break; - - case o_near: - { - ea_t v = to_ea(insn.cs,x.addr); - if ( !out_name_expr(x, v, x.addr) ) - { - out_value(x, OOF_ADDR | OOFS_NOSIGN); - //remember_problem(PR_NONAME, insn.ea); - } - } - break; - - default: - //warning("out: %a: bad optype %d", insn.ip, x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -static const char *GetPrefics(int Raz) -{ - switch ( Raz ) - { - case INSN_PREF_B: return ".b"; - case INSN_PREF_W: return ""; - case INSN_PREF_D: return ".d"; - case INSN_PREF_U: return ""; - default: - //msg("out: %a: bad prefix %d\n", insn.ip, RAZOPER); - break; - } - return ""; -} - -//---------------------------------------------------------------------- -void out_m7900_t::out_proc_mnem(void) -{ - out_mnem(8, GetPrefics(RAZOPER)); // output instruction mnemonics -} - -//---------------------------------------------------------------------- -void out_m7900_t::out_insn(void) -{ - out_mnemonic(); - - out_one_operand(0); // output the first operand - - if ( insn.Op2.type != o_void ) - { - out_symbol(','); // operand sep - if ( (ash.uflag & UAS_NOSPA) == 0 ) - out_char(' '); - out_one_operand(1); - } - - if ( insn.Op3.type != o_void ) - { - out_symbol(','); - if ( (ash.uflag & UAS_NOSPA) == 0 ) - out_char(' '); - out_one_operand(2); - } - - if ( insn.Op4.type != o_void ) - { - out_symbol(','); - if ( (ash.uflag & UAS_NOSPA) == 0 ) - out_char(' '); - out_one_operand(3); - } - - - if ( insn.Op5.type != o_void ) - { - out_symbol(','); - if ( (ash.uflag & UAS_NOSPA) == 0 ) - out_char(' '); - out_one_operand(4); - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void m7900_t::m7900_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); -} - -//-------------------------------------------------------------------------- -// generate segment header -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Srange) could be made const -void m7900_t::m7900_segstart(outctx_t &ctx, segment_t *Srange) const -{ - qstring sname; - get_visible_segm_name(&sname, Srange); - - if ( ash.uflag & UAS_SEGM ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), sname.c_str()); - else - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".SECTION %s", SCOLOR_ASMDIR), sname.c_str()); - - ea_t orgbase = ctx.insn_ea - get_segm_para(Srange); - if ( orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -void m7900_t::m7900_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - size_t i = strlen(ash.end); - do - ctx.out_char(' '); - while ( ++i < 8 ); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} diff --git a/idasdk75/module/m7900/reg.cpp b/idasdk75/module/m7900/reg.cpp deleted file mode 100644 index 1814a58..0000000 --- a/idasdk75/module/m7900/reg.cpp +++ /dev/null @@ -1,436 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include <ctype.h> -#include "7900.hpp" -#include <diskio.hpp> -#include <entry.hpp> - -//extern int gFlag_M; -//extern int gFlag_X; - -//---------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "A", "B", "E", "X", "Y", "PC", "S", - "fIPL", "fN", "fV", "fD", "fI", "fZ", "fC", - "DT", "PG", "DPReg", "DPR0","DPR1", "DPR2","DPR3","fM", "fX", - "cs", "ds" -}; - - - - -//---------------------------------------------------------------------- -static const asm_t AS79 = -{ - AS_COLON // create colons after data names ? - // ASCII directives: - |AS_1TEXT // 1 text per line, no bytes - |ASH_HEXF0 // format of hex numbers:// 34h - |ASD_DECF0 // format of dec numbers:// 34 - |ASB_BINF0 // format of binary numbers:// 010101b - |AS_ONEDUP, // One array definition per line - - UAS_NOSPA | UAS_SEGM, - "Mitsubishi AS79 V4.10", - 0, - NULL, // header - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".BYTE", // ascii string directive - ".BYTE", // byte directive - ".WORD", // word directive - ".DWORD", // no double words - NULL, // no qwords - NULL, // oword (16 bytes) - NULL, // no float - NULL, // no double - NULL, // no tbytes - NULL, // no packreal - NULL, //".db.#s(b,w) #d,#v", // #h - header(.byte,.word) - // #d - size of array - // #v - value of array elements - // #s - size specifier - ".rs %s", // uninited data (reserve space) - ".equ", - NULL, // seg prefix - "*", // a_curip - NULL, // returns function header line - NULL, // returns function footer line - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; -//---------------------------------------------------------------------- -//---------------------------------------------------------------------- -#define FAMILY "Mitsubishi series:" - -static const char *const shnames[] = -{ - "m7900", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Mitsubishi 7700 Family / 7900 Series", - NULL -}; - - -static const asm_t *const asms[] = -{ - &AS79, - NULL -}; - -//-------------------------------------------------------------------------- -static const uchar retc_0[] = { 0xF1 }; //rti -static const uchar retc_1[] = { 0x94 }; //rtl -static const uchar retc_2[] = { 0x1C, 0x77 }; //rtld 0 -static const uchar retc_3[] = { 0x2C, 0x77 }; //rtld 1 -static const uchar retc_4[] = { 0x4C, 0x77 }; //rtld 2 -static const uchar retc_5[] = { 0x8C, 0x77 }; //rtld 3 -static const uchar retc_6[] = { 0x84 }; //rts -static const uchar retc_7[] = { 0x18, 0x77 }; //rtsd 0 -static const uchar retc_8[] = { 0x28, 0x77 }; //rtsd 1 -static const uchar retc_9[] = { 0x48, 0x77 }; //rtsd 2 -static const uchar retc_10[] = { 0x88, 0x77 }; //rtsd 3 -static const uchar retc_11[] = { 0x00, 0x74 }; //brk - -static const bytes_t retcodes[] = -{ - { sizeof(retc_0), retc_0 }, - { sizeof(retc_1), retc_1 }, - { sizeof(retc_2), retc_2 }, - { sizeof(retc_3), retc_3 }, - { sizeof(retc_4), retc_4 }, - { sizeof(retc_5), retc_5 }, - { sizeof(retc_6), retc_6 }, - { sizeof(retc_6), retc_7 }, - { sizeof(retc_6), retc_8 }, - { sizeof(retc_9), retc_9 }, - { sizeof(retc_10), retc_10 }, - { sizeof(retc_11), retc_11 }, - { 0, NULL } -}; - - -//---------------------------------------------------------------------- -#define ADDRRESET 0xFFFE - -const char *m7900_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( !choose_ioport_device(&ioh.device, cfgfile) - && ioh.device == NONEPROC ) - { - warning("No devices are defined in the configuration file %s", cfgfile); - } - - ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT); - - return IDPOPT_OK; -} - - -//------------------------------------------------------------------ -bool m7900_t::choose_device() -{ - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - bool ok = choose_ioport_device2(&ioh.device, cfgfile, &cb); - if ( !ok ) - { - ioh.device = NONEPROC; - - segment_t *sptr = get_first_seg(); - if ( sptr != NULL ) - { - //inf_set_start_ea(sptr->start_ea); - //inf_set_start_ip(0); - - // No processor selected, so create RESET. - // According to 7900 manual RESET resides at 0xFFFE address - create_word(ADDRRESET, 2); - ea_t proc = get_word(ADDRRESET); - if ( proc != 0xFFFF && is_mapped(proc) ) - { - op_plain_offset(ADDRRESET, 0, 0); - add_entry(proc, proc, "__RESET", true); - set_cmt(ADDRRESET, "RESET", false); - } - } - } - return ok; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t notification_code, va_list va) -{ - switch ( notification_code ) - { - case idb_event::sgr_changed: - // In case of fM or fX segment registers undefine data above current address - { - int reg = va_arg(va, int); - if ( reg == rfM || reg == rfX || reg == rDT || reg == rPG ) - { -// msg("Deleting instructions in range %08a..%08a\n",ea1, ea2); -// for (ea_t x = ea1; x < ea2; x = next_that(x, ea2, is_code)) -// del_items(x, DELIT_SIMPLE); - } - } - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -static const char *const m7900_help_message = - "AUTOHIDE REGISTRY\n" - "You have loaded a file for the Mitsubishi 7900 family processor.\n\n"\ - "This processor can be used in two different 'length modes' : 8-bit and 16-bit.\n"\ - "IDA allows to specify the encoding mode for every single instruction.\n"\ - "For this, IDA uses two virtual segment registers : \n"\ - " - rDPReg(1), - rDPR0(0), rDPR1(0), rDPR2(0), rDPR3(0) \n"\ - " - rDT(0), rPG(0), rPC(0), rPS(0) \n"\ - " - fM, used to specify the data length;(0)\n"\ - " - fX, used to specify the index register length.(0)\n\n"\ - "Switching their state from 0 to 1 will switch the disassembly from 16-bit to 8-bit.\n"\ - "You can change their value using the 'change segment register value' command"\ - "(the canonical hotkey is Alt-G).\n\n"\ - "Note : in the real design, those registers are represented as flags in the\n"\ - "processor status register.\n"; - - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new m7900_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi m7900_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ m7900"); - break; - - case processor_t::ev_newfile: - if ( choose_device() ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - - // Set the default segment register values : - // -1 (badsel) for DR - // 0 for fM and fX - for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) - { - set_default_sreg_value(s, rDPR0, 0x0); - set_default_sreg_value(s, rDPR1, 0x0); - set_default_sreg_value(s, rDPR2, 0x0); - set_default_sreg_value(s, rDPR3, 0x0); - set_default_sreg_value(s, rDT, 0x0); - set_default_sreg_value(s, rPG, 0x0); - set_default_sreg_value(s, rPC, 0xFFFE); - set_default_sreg_value(s, rPS, 0x0FFF); - - set_default_sreg_value(s, rfI, 1); - set_default_sreg_value(s, rfD, 0); - set_default_sreg_value(s, rfX, 0); - set_default_sreg_value(s, rfM, 0); - set_default_sreg_value(s, rfIPL, 0); - - set_default_sreg_value(s, rDPReg, 1); - } - info(m7900_help_message); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: // new segment - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m7900_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - m7900_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - m7900_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_M7900, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_BINMEM // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - | PR_SEGS // has segment registers? - | PR_SGROTHER, // the segment registers don't contain - // the segment selectors, something else - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rDT, - Rds, - 0, // size of a segment register - Rcs,Rds, - - NULL, // No known code start sequences - retcodes, - - 0, - m7900_last, - Instructions, // instruc - 3, // int tbyte_size; -- doesn't exist - - { 0, 0, 0, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - m7900_rts, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/mc68xx/notify_codes.hpp b/idasdk75/module/mc68xx/notify_codes.hpp deleted file mode 100644 index 893939b..0000000 --- a/idasdk75/module/mc68xx/notify_codes.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __MC68XX_NOTIFY_CODES_HPP -#define __MC68XX_NOTIFY_CODES_HPP - -#include <idp.hpp> - -//---------------------------------------------------------------------- -// The following events are supported by the MC68XX module in the ph.notify() function -namespace mc68xx_module_t -{ - enum event_codes_t - { - ev_notify_flex_format = processor_t::ev_loader, - // tell the module that the file has FLEX format - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline void notify_flex_format() - { - processor_t::notify(idp_ev(ev_notify_flex_format)); - } -} - -#endif // __MC68XX_NOTIFY_CODES_HPP diff --git a/idasdk75/module/mn102/ana.cpp b/idasdk75/module/mn102/ana.cpp deleted file mode 100644 index aad69c0..0000000 --- a/idasdk75/module/mn102/ana.cpp +++ /dev/null @@ -1,1128 +0,0 @@ -/* - * Panasonic MN102 (PanaXSeries) processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "pan.hpp" - -//--------------------------------------------------------------------------- -// internal use only -static uint32 LoadData(insn_t &insn, int bytes) -{ - uint32 dt = 0; - // load data - for ( int i=0; i < bytes; i++ ) - { - uint32 nb = insn.get_next_byte(); - dt |= nb << (8*i); - } - return dt; -} - -//--------------------------------------------------------------------------- -// load a label's address -static void SetLabel(insn_t &insn, op_t &op, int bytes) -{ - uint32 off; - op.type = o_near; - // load the data - off = LoadData(insn, bytes); - // sign extend - switch ( bytes ) - { - // 1 byte - case 1: - if ( off&0x000080L ) - off |= ~0x00007FL; - break; - - // 2 bytes - case 2: - if ( off&0x008000L ) - off |= ~0x007FFFL; - break; - - // 3 bytes - case 3: - if ( off&0x800000L ) - off |= ~0x7FFFFFL; - break; - } -// sprintf(cc,"%lx",off); -// msg(cc); - op.addr = op.value = (off+(uint32)insn.size+insn.ea) & 0xFFFFFFL; -// sprintf(cc,"==%lx",op.value); -// msg(cc); -// sprintf(cc,"==%lx",insn.ea); -// msg(cc); -// msg("\n"); -} - -//--------------------------------------------------------------------------- -// set immediate operand, only numbers -static void SetImm(insn_t &insn, op_t &op, int bytes) -{ - op.type = o_imm; // immediate - op.dtype = dt_dword; - op.addr = op.value = LoadData(insn, bytes); // number value -} - -//--------------------------------------------------------------------------- -static void SetImmC(op_t &op, int Val) -{ - op.type = o_imm; // immediate - op.dtype = dt_dword; - op.flags |= OF_NUMBER; // number only - op.addr = op.value = Val; // value -} - -//--------------------------------------------------------------------------- -// registe addressing -static void SetReg(op_t &op,uchar Reg) -{ - op.type = o_reg; - op.reg = Reg; - op.addr = op.value = 0; -} - -//--------------------------------------------------------------------------- -// indirect addressing -static void SetRReg(op_t &op,uchar Reg) -{ - op.type = o_reg; - op.reg = Reg|0x80; // indirect - op.addr = op.value = 0; -} - -//--------------------------------------------------------------------------- -// indirect addressing with a displacement -static void SetDisplI(op_t &op,uchar Reg, uchar RegI) -{ - op.type = o_reg; - op.reg = (Reg&0x0F)|0x90|((RegI&3)<<5); - op.addr = op.value = 0; -} - -//--------------------------------------------------------------------------- -// indirect addressing with a displacement -static void SetDispl(insn_t &insn, op_t &op,uchar Reg, int OffSize) -{ - op.type = o_displ; - op.dtype = dt_dword; - op.reg = Reg; - op.addr = op.value = LoadData(insn, OffSize); -} - -//--------------------------------------------------------------------------- -// memory addressing -static void SetMem(insn_t &insn, op_t &op, int AddrSize, uchar DataSize) -{ - op.type = o_mem; - op.addr = op.value = LoadData(insn, AddrSize); - op.dtype = DataSize; -} - -//--------------------------------------------------------------------------- -// analyzer -int idaapi mn102_ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - uchar R1, R2; - // read first byte - uchar code = insn.get_next_byte(); - // analyze high bits - R1 = code&3; - R2 = (code>>2)&3; - insn.Op1.specflag1 = 0; - insn.Op2.specflag1 = 0; - switch ( code>>4 ) - { - // mov Dm, (An) - case 0x00: - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rD0); - SetRReg(insn.Op2,R2+rA0); - break; - - // movb Dm, (An) - case 0x01: - insn.itype = mn102_movb; - SetReg(insn.Op1,R1+rD0); - SetRReg(insn.Op2,R2+rA0); - break; - - // mov (An), Dm - case 0x02: - insn.itype = mn102_mov; - SetReg(insn.Op2,R1+rD0); - SetRReg(insn.Op1,R2+rA0); - break; - - // movbu (An), Dm - case 0x03: - insn.itype = mn102_movbu; - SetReg(insn.Op2,R1+rD0); - SetRReg(insn.Op1,R2+rA0); - break; - - // mov Dm, (d8,An) - case 0x04: - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rD0); - SetDispl(insn, insn.Op2,R2+rA0,1); - break; - - // mov An, (d8,An); - case 0x05: - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rA0); - SetDispl(insn, insn.Op2,R2+rA0,1); - break; - - // mov (d8,An), Dm - case 0x06: - insn.itype = mn102_mov; - SetReg(insn.Op2,R1+rD0); - SetDispl(insn, insn.Op1,R2+rA0,1); - break; - - // mov (d8,An), Am - case 0x07: - insn.itype = mn102_mov; - SetReg(insn.Op2,R1+rA0); - SetDispl(insn, insn.Op1,R2+rA0,1); - break; - - // mov Dn, Dm or mov imm8,Dn - case 0x08: - insn.itype = mn102_mov; - if ( (code&3) == ((code>>2)&3) ) - { - // mov imm, Dn - SetImm(insn, insn.Op1,1); - SetReg(insn.Op2,R1+rD0); - } - else - { - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - } - break; - - // add Dn, Dm - case 0x09: - insn.itype = mn102_add; - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - break; - - // Sub Dn,Dm - case 0x0A: - insn.itype = mn102_sub; - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - break; - - // Extx* Dn - case 0x0B: - switch ( code&0xC ) - { - // extx - case 0x00: - insn.itype = mn102_extx; - break; - case 0x04: - insn.itype = mn102_extxu; - break; - case 0x08: - insn.itype = mn102_extxb; - break; - case 0x0C: - insn.itype = mn102_extxbu; - break; - } - SetReg(insn.Op1,R1+rD0); - break; - - // mov* Dn, (mem) - case 0x0C: - switch ( code&0xC ) - { - // mov Dn, (abs) - case 0x00: - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rD0); - SetMem(insn, insn.Op2, 2, dt_word); - break; - - // movb Dn, (abs) - case 0x04: - insn.itype = mn102_movb; - SetReg(insn.Op1,R1+rD0); - SetMem(insn, insn.Op2, 2, dt_byte); - break; - - // mov (abs), Dn - case 0x08: - insn.itype = mn102_mov; - SetReg(insn.Op2,R1+rD0); - SetMem(insn, insn.Op1, 2, dt_word); - break; - - // movbu (abs), Dn - case 0x0C: - insn.itype = mn102_movbu; - SetReg(insn.Op2,R1+rD0); - SetMem(insn, insn.Op1, 2, dt_byte); - break; - } - break; - // add/cmp,mov - case 0x0D: - switch ( code&0xC ) - { - // add imm8, An - case 0x00: - SetReg(insn.Op2,R1+rA0); - insn.itype = mn102_add; - SetImm(insn, insn.Op1, 1); - break; - - // add imm8, Dn - case 0x04: - SetReg(insn.Op2,R1+rD0); - insn.itype = mn102_add; - SetImm(insn, insn.Op1, 1); - break; - - // cmp imm8, Dn - case 0x08: - SetReg(insn.Op2,R1+rD0); - insn.itype = mn102_cmp; - SetImm(insn, insn.Op1, 1); - break; - - // mov imm16, An - case 0x0c: - SetReg(insn.Op2,R1+rA0); - insn.itype = mn102_mov; - SetImm(insn, insn.Op1, 2); - insn.Op1.specflag1 = URB_ADDR; - break; - } - break; - - // Jmps - case 0x0E: - { - static const uchar Cmd[16] = - { - mn102_blt,mn102_bgt,mn102_bge,mn102_ble, - mn102_bcs,mn102_bhi,mn102_bcc,mn102_bls, - mn102_beq,mn102_bne,mn102_bra,mn102_rti, - mn102_cmp,mn102_cmp,mn102_cmp,mn102_cmp - }; - insn.itype = Cmd[code&0xF]; - switch ( insn.itype ) - { - // rti - case mn102_rti: - break; - // cmp imm16, An - case mn102_cmp: - SetReg(insn.Op2,R1+rA0); - SetImm(insn, insn.Op1, 2); - break; - // jmps - default: - SetLabel(insn, insn.Op1,1); - break; - } - break; - } - // ExtCodes - case 0x0F: - switch ( code & 0xF ) - { - // F0 set - case 0x00: - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - switch ( code&0xC0 ) - { - // complex set - case 0x00: - switch ( code&0x30 ) - { - // one more set - case 0x00: - if ( code & 2 ) - return 0; - SetRReg(insn.Op1,R2+rA0); - if ( code & 1 ) - insn.itype = mn102_jsr; - else - insn.itype = mn102_jmp; - break; - case 0x10: - return 0; - case 0x20: - insn.itype = mn102_bset; - SetReg(insn.Op1,R1+rD0); - SetRReg(insn.Op2,R2+rA0); - break; - case 0x30: - insn.itype = mn102_bclr; - SetReg(insn.Op1,R1+rD0); - SetRReg(insn.Op2,R2+rA0); - break; - } - break; - - // movb (Di,An), Dm - case 0x40: - insn.itype = mn102_movb; - SetReg(insn.Op2,R1+rD0); - SetDisplI(insn.Op1,R2+rA0,code>>4); - break; - // movbu (Di,An), Dm - case 0x80: - insn.itype = mn102_movbu; - SetReg(insn.Op2,R1+rD0); - SetDisplI(insn.Op1,R2+rA0,code>>4); - break; - // movb Dm, (Di, An) - case 0xC0: - insn.itype = mn102_movb; - SetReg(insn.Op1,R1+rD0); - SetDisplI(insn.Op2,R2+rA0,code>>4); - break; - } - break; - // F1 set - case 0x01: - insn.itype = mn102_mov; - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - switch ( code&0xC0 ) - { - // mov (Di, An), Am - case 0x00: - SetReg(insn.Op2,R1+rA0); - SetDisplI(insn.Op1,R2+rA0, code>>4); - break; - - // mov (Di,An), Dm - case 0x40: - SetReg(insn.Op2,R1+rD0); - SetDisplI(insn.Op1,R2+rA0, code>>4); - break; - - // mov Am, (Di, An) - case 0x80: - SetReg(insn.Op1,R1+rD0); - SetDisplI(insn.Op2,R2+rA0, code>>4); - break; - - // mov Dm, (Di, An); - case 0xC0: - SetReg(insn.Op1,R1+rD0); - SetDisplI(insn.Op2,R2+rA0, code>>4); - break; - } - break; - // F2 set - case 0x02: - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - { - static const uchar Cmd[16] = - { - mn102_add, mn102_sub, mn102_cmp, mn102_mov, - mn102_add, mn102_sub, mn102_cmp, mn102_mov, - mn102_addc, mn102_subc, 0, 0, - mn102_add, mn102_sub, mn102_cmp, mn102_mov - }; - insn.itype = Cmd[code>>4]; - if ( insn.itype == 0 ) - return 0; - switch ( code&0xC0 ) - { - case 0x00: - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rA0); - break; - - case 0x40: - SetReg(insn.Op1,R2+rA0); - SetReg(insn.Op2,R1+rA0); - break; - - case 0x80: - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - break; - - case 0xC0: - SetReg(insn.Op1,R2+rA0); - SetReg(insn.Op2,R1+rD0); - break; - } - } - break; - // F3 set - case 0x03: - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - { - static const uchar Cmd[16] = - { - mn102_and, mn102_or, mn102_xor, mn102_rol, - mn102_mul, mn102_mulu, mn102_divu, 0, - 0, mn102_cmp, 0, 0, - mn102_ext, mn102_mov, mn102_not, 255 - }; - insn.itype = Cmd[code>>4]; - switch ( insn.itype ) - { - // bad opcode - case 0: - return 0; - // shifts - case mn102_rol: - SetReg(insn.Op1,R1+rD0); - insn.Op2.type = o_void; - { - static const uchar Cmd2[4] = - { - mn102_rol,mn102_ror,mn102_asr,mn102_lsr - }; - insn.itype = Cmd2[(code>>2)&3]; - } - break; - case mn102_ext: - if ( code & 2 ) - return 0; - if ( code & 1 ) - { - insn.Op2.type = o_void; - } - else - { - insn.itype = mn102_mov; - SetReg(insn.Op2,rMDR); - } - break; - - case mn102_mov: - if ( R1 != 0 ) - return 0; - SetReg(insn.Op2,rPSW); - break; - - case mn102_not: - switch ( R2 ) - { - case 0: - insn.itype = mn102_mov; - SetReg(insn.Op1,rMDR); - break; - case 1: - insn.Op2.type = o_void; - SetReg(insn.Op1,R1+rD0); - break; - default: - return 0; - } - break; - - case 255: - switch ( R2 ) - { - case 0: - insn.itype = mn102_mov; - SetReg(insn.Op1,rPSW); - break; - case 3: - insn.Op2.type = insn.Op1.type = o_void; - switch ( R1 ) - { - case 0: - insn.itype = mn102_pxst; - break; - // F3, FE - case 2: - { - static const uchar lCmd[4] = - { - mn102_tbz, mn102_tbnz, mn102_bset, mn102_bclr - }; - code = insn.get_next_byte(); - if ( code < 0xC0 || code >= 0xE0 ) - return 0; - insn.itype = lCmd[(code>>3)&3]; - SetImmC(insn.Op1,1<<(code&7)); - SetMem(insn, insn.Op2, 3, dt_byte); - // if jump, use label - if ( (code&0xF0) == 0xC0 ) - SetLabel(insn, insn.Op3, 1); - } - break; - // F3, FF - case 3: - { - static const uchar lCmd[4] = - { - mn102_tbz, mn102_bset, mn102_tbnz, mn102_bclr - }; - code = insn.get_next_byte(); - if ( code < 0x80 || code >= 0xC0 ) - return 0; - insn.itype = lCmd[(code>>4)&3]; - SetImmC(insn.Op1,1<<(code&7)); - SetDispl(insn, insn.Op2,(code&0x8)?rA3:rA2, 1); - insn.Op3.dtype = dt_byte; - // if jump, use label - if ( (code & 0x10) == 0 ) - SetLabel(insn, insn.Op3, 1); - } - break; - default: - return 0; - } - break; - default: - return 0; - } - break; - //the rest does not need processing - default: - break; - } - } - break; - - // F4 set - 5 bytes - case 0x04: - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - - switch ( code&0xF0 ) - { - // mov Dm, (D24,An) - case 0x00: - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rD0); - SetDispl(insn, insn.Op2,R2+rA0,3); - break; - - case 0x10: - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rA0); - SetDispl(insn, insn.Op2,R2+rA0,3); - break; - - case 0x20: - insn.itype = mn102_movb; - SetReg(insn.Op1,R1+rD0); - SetDispl(insn, insn.Op2,R2+rA0,3); - break; - - case 0x30: - insn.itype = mn102_movx; - SetReg(insn.Op1,R1+rD0); - SetDispl(insn, insn.Op2,R2+rA0,3); - break; - - case 0x40: - switch ( R2 ) - { - case 0: - insn.itype = mn102_mov; - SetMem(insn, insn.Op2,3,dt_dword); - SetReg(insn.Op1,R1+rD0); - break; - - case 1: - insn.itype = mn102_movb; - SetMem(insn, insn.Op2,3,dt_byte); - SetReg(insn.Op1,R1+rD0); - break; - - default: - if ( code != 0x4B && code != 0x4F ) - return 0; - insn.itype = code == 0x4B ? mn102_bset : mn102_bclr; - SetMem(insn, insn.Op2,3,dt_byte); - SetImm(insn, insn.Op1,1); - break; - } - break; - - case 0x50: - if ( R2 != 0 ) - return 0; - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rA0); - SetMem(insn, insn.Op1,3,dt_tbyte); - break; - - case 0x60: - SetImm(insn, insn.Op1,3); - SetReg(insn.Op2, R1+((R2&1)?rA0:rD0)); - insn.itype = (R2&2)?mn102_sub:mn102_add; - break; - - case 0x70: - SetImm(insn, insn.Op1,3); - insn.Op1.specflag1 = URB_ADDR; - SetReg(insn.Op2,R1+((R2&1)?rA0:rD0)); - insn.itype = (R2&2)?mn102_cmp:mn102_mov; - break; - - case 0x80: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op1,R2+rA0,3); - SetReg(insn.Op2,R1+rD0); - break; - - case 0x90: - insn.itype = mn102_movbu; - SetDispl(insn, insn.Op1,R2+rA0,3); - SetReg(insn.Op2,R1+rD0); - break; - - case 0xA0: - insn.itype = mn102_movb; - SetDispl(insn, insn.Op1,R2+rA0,3); - SetReg(insn.Op2,R1+rD0); - break; - - case 0xB0: - insn.itype = mn102_movx; - SetDispl(insn, insn.Op1,R2+rA0,3); - SetReg(insn.Op2,R1+rD0); - break; - - case 0xC0: - SetReg(insn.Op2,R1+rD0); - switch ( R2 ) - { - case 0: - insn.itype = mn102_mov; - SetMem(insn, insn.Op1,3,dt_word); - break; - - case 1: - insn.itype = mn102_movb; - SetMem(insn, insn.Op1,3,dt_byte); - break; - - case 2: - insn.itype = mn102_movbu; - SetMem(insn, insn.Op1,3,dt_byte); - break; - - default: - return 0; - } - break; - - case 0xD0: - if ( R2 != 0 ) - return 0; - insn.itype = mn102_mov; - SetMem(insn, insn.Op1,3,dt_tbyte); - SetReg(insn.Op2,R1+rA0); - break; - - case 0xE0: - switch ( code ) - { - case 0xE0: - insn.itype = mn102_jmp; - SetLabel(insn, insn.Op1,3); - break; - - case 0xE1: - insn.itype = mn102_jsr; - SetLabel(insn, insn.Op1,3); - break; - - case 0xE3: - case 0xE7: - insn.itype = (code == 0xE3) ? mn102_bset : mn102_bclr; - SetMem(insn, insn.Op2,2,dt_byte); - SetImmC(insn.Op1,1); - break; - - default: - if ( code < 0xE8 ) - return 0; - insn.itype = (code&0x4)?mn102_bclr:mn102_bset; - SetImmC(insn.Op1,1); - SetDispl(insn, insn.Op2,rA0+(code&3),1); - break; - } - break; - - case 0xF0: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op1,R2+rA0,3); - SetReg(insn.Op2,R1+rA0); - break; - } - break; - // F5 set - case 0x05: - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - switch ( code&0xF0 ) - { - case 0x00: - { - static const uchar Cmd[4] = - { - mn102_and, mn102_btst, mn102_or, mn102_addnf - }; - SetImm(insn, insn.Op1,1); - SetReg(insn.Op2,R1+rD0); - insn.itype = Cmd[R2]; - } - break; - // movb Dm,(d8,An) - case 0x10: - insn.itype = mn102_movb; - SetReg(insn.Op1,R1+rD0); - SetDispl(insn, insn.Op2,R2+rA0,1); - break; - - // movb (d8,An), Dm - case 0x20: - insn.itype = mn102_movb; - SetReg(insn.Op2,R1+rD0); - SetDispl(insn, insn.Op1,R2+rA0,1); - break; - - //movbu (d8,An), Dm - case 0x30: - insn.itype = mn102_movbu; - SetReg(insn.Op2,R1+rD0); - SetDispl(insn, insn.Op1,R2+rA0,1); - break; - - // mulql dn, dm - case 0x40: - code = insn.get_next_byte(); - if ( code > 1 ) - return 0; - insn.itype = (code == 0) ? mn102_mulql : mn102_mulqh; - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - break; - - // movx Dm, (d8,An) - case 0x50: - insn.itype = mn102_movx; - SetReg(insn.Op1,R1+rD0); - SetDispl(insn, insn.Op2,R2+rA0,1); - break; - - // mulq dn, dm - case 0x60: - code = insn.get_next_byte(); - if ( code != 0x10 ) - return 0; - insn.itype = mn102_mulq; - SetReg(insn.Op1,R2+rD0); - SetReg(insn.Op2,R1+rD0); - break; - - // movx (d8,An), Dm - case 0x70: - insn.itype = mn102_movx; - SetDispl(insn, insn.Op1,R2+rA0,1); - SetReg(insn.Op2,R1+rD0); - break; - - case 0x80: - case 0x90: - case 0xA0: - case 0xB0: - { - static const uchar Cmd[4] = - { - mn102_tbz, mn102_bset, mn102_tbnz, mn102_bclr - }; - insn.itype = Cmd[(code>>4)&3]; - SetImmC(insn.Op1,1<<(code&7)); - SetDispl(insn, insn.Op2,(code&0x8)?rA1:rA0,1); - if ( (code & 0x10) == 0 ) - SetLabel(insn, insn.Op3, 1); - } - break; - case 0xC0: - case 0xD0: - { - static const uchar Cmd[4] = - { - mn102_tbz, mn102_tbnz, mn102_bset, mn102_bclr - }; - insn.itype = Cmd[(code>>3)&3]; - SetImmC(insn.Op1,1<<(code&7)); - SetMem(insn, insn.Op2,2,dt_byte); - if ( (code & 0x10) == 0 ) - SetLabel(insn, insn.Op3, 1); - } - break; - - case 0xE0: - { - static const uchar Cmd[16] = - { - mn102_bltx,mn102_bgtx,mn102_bgex,mn102_blex, - mn102_bcsx,mn102_bhix,mn102_bccx,mn102_blsx, - mn102_beqx,mn102_bnex,0,0, - mn102_bvcx,mn102_bvsx,mn102_bncx,mn102_bnsx - }; - insn.itype = Cmd[code&0xF]; - if ( insn.itype == 0 ) - return 0; - SetLabel(insn, insn.Op1,1); - } - break; - case 0xF0: - if ( code < 0xFC && code > 0xF8 ) - return 0; - if ( code >= 0xFC ) - { - static const uchar Cmd[4] = - { - mn102_bvc, mn102_bvs, mn102_bnc, mn102_bns - }; - insn.itype = Cmd[R1]; - SetLabel(insn, insn.Op1, 1); - } - else - { - code = insn.get_next_byte(); - switch ( code ) - { - case 0x4: - insn.itype = mn102_mulql; - SetImm(insn, insn.Op1,1); - SetReg(insn.Op2,R1+rD0); - break; - case 0x5: - insn.itype = mn102_mulqh; - SetImm(insn, insn.Op1,1); - SetReg(insn.Op2,R1+rD0); - break; - case 0x8: - insn.itype = mn102_mulql; - SetImm(insn, insn.Op1,2); - SetReg(insn.Op2,R1+rD0); - break; - case 0x9: - insn.itype = mn102_mulqh; - SetImm(insn, insn.Op1,2); - SetReg(insn.Op2,R1+rD0); - break; - default: - return 0; - } - } - break; - default: - return 0; - } - break; - - // NOP - case 0x06: - insn.itype = mn102_nop; - break; - - //F7 set - case 0x07: - code = insn.get_next_byte(); - R1 = (code&3); - R2 = (code>>2)&3; - switch ( code&0xF0 ) - { - case 0x00: - { - static const uchar Cmd[4] = - { - mn102_and, mn102_btst, mn102_add, mn102_sub - }; - - SetImm(insn, insn.Op1,2); - SetReg(insn.Op2,R1+((R2&2)?rA0:rD0)); - insn.itype = Cmd[R2]; - } - break; - - case 0x10: - switch ( R2 ) - { - case 0: - if ( R1 != 0 ) - return 0; - insn.itype = mn102_and; - SetReg(insn.Op2,rPSW); - break; - - case 1: - if ( R1 != 0 ) - return 0; - insn.itype = mn102_or; - SetReg(insn.Op2,rPSW); - break; - - case 2: - insn.itype = mn102_add; - SetReg(insn.Op2,R1+rD0); - break; - - case 3: - insn.itype = mn102_sub; - SetReg(insn.Op2,R1+rD0); - break; - } - SetImm(insn, insn.Op1,2); - break; - - case 0x20: - if ( R2 != 0 ) - return 0; - insn.itype = mn102_mov; - SetReg(insn.Op1,R1+rA0); - SetMem(insn, insn.Op2,2,dt_tbyte); - break; - - case 0x30: - if ( R2 != 0 ) - return 0; - insn.itype = mn102_mov; - SetReg(insn.Op2,R1+rA0); - SetMem(insn, insn.Op1,2,dt_tbyte); - break; - - case 0x40: - { - static const uchar Cmd[4] = - { - mn102_or, 0, mn102_cmp, mn102_xor - }; - insn.itype = Cmd[R2]; - if ( insn.itype == 0 ) - return 0; - SetImm(insn, insn.Op1,2); - SetReg(insn.Op2,R1+rD0); - } - break; - - case 0x50: - insn.itype = mn102_movbu; - SetDispl(insn, insn.Op1,R2+rA0,2); - SetReg(insn.Op2,R1+rD0); - break; - - case 0x60: - insn.itype = mn102_movx; - SetDispl(insn, insn.Op2,R2+rA0,2); - SetReg(insn.Op1,R1+rD0); - break; - - case 0x70: - insn.itype = mn102_movx; - SetDispl(insn, insn.Op1,R2+rA0,2); - SetReg(insn.Op2,R1+rD0); - break; - - case 0x80: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op2,R2+rA0,2); - SetReg(insn.Op1,R1+rD0); - break; - - case 0x90: - insn.itype = mn102_movb; - SetDispl(insn, insn.Op2,R2+rA0,2); - SetReg(insn.Op1,R1+rD0); - break; - - case 0xA0: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op2,R2+rA0,2); - SetReg(insn.Op1,R1+rA0); - break; - - case 0xB0: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op1,R2+rA0,2); - SetReg(insn.Op2,R1+rA0); - break; - - case 0xC0: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op1,R2+rA0,2); - SetReg(insn.Op2,R1+rD0); - break; - - case 0xD0: - insn.itype = mn102_mov; - SetDispl(insn, insn.Op1,R2+rA0,2); - SetReg(insn.Op2,R1+rD0); - break; - - default: - return 0; - } - break; - - // mov imm16, Dn - case 0x08: - case 0x09: - case 0x0A: - case 0x0B: - SetReg(insn.Op2,R1+rD0); - SetImm(insn, insn.Op1, 2); - insn.itype = mn102_mov; - break; - - // jmp label16 - case 0x0C: - insn.itype = mn102_jmp; - SetLabel(insn, insn.Op1,2); - break; - - // jsr label16 - case 0x0D: - insn.itype = mn102_jsr; - SetLabel(insn, insn.Op1,2); - break; - - // rts - case 0x0E: - insn.itype = mn102_rts; - break; - - // illegal code - case 0x0F: - return 0; - } - break; - } - return insn.size; -} diff --git a/idasdk75/module/mn102/makefile b/idasdk75/module/mn102/makefile deleted file mode 100644 index 39a659e..0000000 --- a/idasdk75/module/mn102/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=mn102l00 -CONFIGS=mn102l00.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp pan.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - emu.cpp ins.hpp pan.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp pan.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp pan.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp pan.hpp reg.cpp diff --git a/idasdk75/module/mn102/out.cpp b/idasdk75/module/mn102/out.cpp deleted file mode 100644 index 8d36b40..0000000 --- a/idasdk75/module/mn102/out.cpp +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Panasonic MN102 (PanaXSeries) processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "pan.hpp" - -//---------------------------------------------------------------------- -class out_mn102_t : public outctx_t -{ - out_mn102_t(void) = delete; // not used -public: - void OutVarName(const op_t &x); - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_mn102_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_mn102_t) - -//---------------------------------------------------------------------- -void out_mn102_t::OutVarName(const op_t &x) -{ - ea_t toea = map_code_ea(insn, x); - if ( !out_name_expr(x, toea, x.addr) ) - { - out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); - remember_problem(PR_NONAME, insn.ea); - } -} - -//---------------------------------------------------------------------- -// print one operand -bool out_mn102_t::out_operand(const op_t & x) -{ - switch ( x.type ) - { - // memory reference with a regsiter - // (disp,Ri) - case o_displ: - out_symbol('('); - out_value(x); - out_symbol(','); - out_register(ph.reg_names[x.reg]); - out_symbol(')'); - break; - - // register - case o_reg: - if ( x.reg&0x80 ) - out_symbol('('); - if ( x.reg&0x10 ) - { - out_register(ph.reg_names[((x.reg>>5)&3)+rD0]); - out_symbol(','); - } - out_register(ph.reg_names[x.reg&0x0F]); - if ( x.reg&0x80 ) - out_symbol(')'); - break; - - // immediate operand - case o_imm: - refinfo_t ri; - // micro bug-fix - if ( get_refinfo(&ri, insn.ea, x.n) ) - { - if ( ri.flags == REF_OFF16 ) - set_refinfo(insn.ea, x.n, REF_OFF32, ri.target, ri.base, ri.tdelta); - } - out_value(x, /*OOFS_NOSIGN | */ OOF_SIGNED | OOFW_IMM); - break; - - // code reference - case o_near: - OutVarName(x); - break; - - // direct memory reference - case o_mem: - out_symbol('('); - OutVarName(x); - out_symbol(')'); - break; - - // nothing for void - case o_void: - return 0; - - // unknown operand - default: - warning("out: %a: bad optype %d",insn.ea,x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -// main instruction printer -void out_mn102_t::out_insn(void) -{ - // print mnemonic - out_mnemonic(); - - // print first operands - if ( insn.Op1.type != o_void ) - out_one_operand(0); - - // second operand - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - // third operand - if ( insn.Op3.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(2); - } - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -// listing header -void mn102_t::mn102_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, ioh.device.c_str(), ioh.deviceparams.c_str()); -} - -//-------------------------------------------------------------------------- -// segment header -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Sarea) could be made const -void mn102_t::mn102_segstart(outctx_t &ctx, segment_t *Sarea) const -{ - ea_t ea = ctx.insn_ea; - const char *SegType = Sarea->type == SEG_CODE ? "CSEG" - : Sarea->type == SEG_DATA ? "DSEG" - : "RSEG"; - // print RSEG <NAME> - qstring sn; - get_visible_segm_name(&sn, Sarea); - ctx.gen_printf(-1, "%s %s ", SegType, sn.c_str()); - // if org is not zero, print it - if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) - { - ea_t org = ea - get_segm_base(Sarea); - if ( org != 0 ) - { - char bufn[MAX_NUMBUF]; - btoa(bufn, sizeof(bufn), org); - ctx.gen_printf(-1, "%s %s", ash.origin, bufn); - } - } -} - -//-------------------------------------------------------------------------- -// end of listing -void mn102_t::mn102_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - size_t i = strlen(ash.end); - do - ctx.out_char(' '); - while ( ++i < 8 ); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} - -//-------------------------------------------------------------------------- -void idaapi mn102_data(outctx_t &ctx, bool analyze_only) -{ - ea_t ea = ctx.insn_ea; - // micro bug-fix - refinfo_t ri; - if ( get_refinfo(&ri, ea, 0) && ri.flags == REF_OFF16 ) - set_refinfo(ea, 0, REF_OFF32, ri.target, ri.base, ri.tdelta); - - //try equ - // if ( out_equ(ea) ) return; - // didn't work - print as data - ctx.out_data(analyze_only); -} diff --git a/idasdk75/module/mn102/pan.hpp b/idasdk75/module/mn102/pan.hpp deleted file mode 100644 index 1ee108a..0000000 --- a/idasdk75/module/mn102/pan.hpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Panasonic MN102 (PanaXSeries) processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#ifndef _PAN_HPP -#define _PAN_HPP - -#include <ida.hpp> -#include <idp.hpp> - -#include "../idaidp.hpp" -#include "ins.hpp" -#include "../iohandler.hpp" - -//----------------------------------------------- -// additional bits (specflag1) -#define URB_ADDR 0x1 // immediate operand is an address - -//------------------------------------------------------------------------ -#ifdef _MSC_VER -#define ENUM8BIT : uint8 -#else -#define ENUM8BIT -#endif -// list of processor registers -enum mn102_registers ENUM8BIT -{ - rNULLReg, - rD0, rD1, rD2, rD3, - rA0, rA1, rA2, rA3, - rMDR,rPSW, rPC, - rVcs, rVds -}; - -//------------------------------------------------------------------------ -int idaapi mn102_ana(insn_t *_insn); - -void idaapi mn102_data(outctx_t &ctx, bool analyze_only); - -//------------------------------------------------------------------------ -struct mn102_t : public procmod_t -{ - netnode helper; - iohandler_t ioh = iohandler_t(helper); - bool flow = false; // code flow continues flag - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - int mn102_emu(const insn_t &insn); - - void mn102_header(outctx_t &ctx); - void mn102_segstart(outctx_t &ctx, segment_t *Sarea) const; - void mn102_footer(outctx_t &ctx) const; -}; - -#endif diff --git a/idasdk75/module/mn102/reg.cpp b/idasdk75/module/mn102/reg.cpp deleted file mode 100644 index 1e306e4..0000000 --- a/idasdk75/module/mn102/reg.cpp +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Panasonic MN102 (PanaXSeries) processor module for IDA. - * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "pan.hpp" -#include <diskio.hpp> -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -// register names -static const char *const RegNames[] = -{ - // empty - "", - "D0","D1","D2","D3", - "A0","A1","A2","SP", // SP is alias of A3 - // special - "MDR","PSW","PC", - // pseudo-segment - "cs","ds" -}; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new mn102_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi mn102_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - inf_set_be(false); - inf_set_gen_lzero(true); - helper.create("$ MN102"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - { - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - mn102_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - mn102_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - mn102_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return mn102_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return mn102_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - mn102_data(*ctx, analyze_only); - return 1; - } - - default: - break; - } - return code; -} -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const asm_t pseudosam = -{ - AS_COLON | AS_UDATA | ASH_HEXF3 | ASD_DECF0, - 0, - "Generic assembler", // assembeler name - 0, // help topic ID - NULL, // header lines - "org", // org - "end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - "db", // ascii string directive - "DB", // byte directive - "DW", // word directive - "DL", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - "DT", // tbyte (10/12 bytes) - NULL, // packed decimal real - "#d dup(#v)", // arrays (#h,#d,#v,#s(...) - "db ?", // uninited arrays - ".equ", // equ - NULL, // seg prefix - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - NULL, // "public" name keyword - NULL, // "weak" name keyword - NULL, // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // const char *(*get_type_name)(int32 flag,uint32 id); - "align", // "align" keyword - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -// list of assemblers -static const asm_t *const asms[] = { &pseudosam, NULL }; -//----------------------------------------------------------------------- -#define FAMILY "Panasonic MN10200:" -static const char *const shnames[] = { "MN102L00", NULL }; -static const char *const lnames[] = { FAMILY"Panasonic MN102L00", NULL }; - -//-------------------------------------------------------------------------- -// codes of subroutine returns -static const uchar retcode_1[] = { 0xFE }; // ret -static const uchar retcode_2[] = { 0xEB }; // reti -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_MN102L00, // id - // flag - PR_USE32 - | PR_BINMEM - | PR_SEGTRANS - | PR_DEFSEG32, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 2, // size of a segment register - rVcs,rVds, - NULL, // typical code starts - retcodes, // returns - 0,mn102_last, // first, last itype - Instructions, // instruction array - 3, // tbyte size: 24 bits - {0,0,0,0}, // floating point type sizes - 0, // Icode for return - NULL, // micro virtual mashine -}; diff --git a/idasdk75/module/nec850/ana.cpp b/idasdk75/module/nec850/ana.cpp deleted file mode 100644 index 591bcb5..0000000 --- a/idasdk75/module/nec850/ana.cpp +++ /dev/null @@ -1,2065 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) Hex-Rays - * ALL RIGHTS RESERVED. - * - * Instruction decoder - * - */ -#include "ins.hpp" - -static const int bcond_map[16] = -{ - NEC850_BV, NEC850_BL, - NEC850_BZ, NEC850_BNH, - NEC850_BN, NEC850_BR, - NEC850_BLT, NEC850_BLE, - NEC850_BNV, NEC850_BNC, - NEC850_BNZ, NEC850_BH, - NEC850_BP, NEC850_BSA, - NEC850_BGE, NEC850_BGT -}; - -//------------------------------------------------------------------------ -// The instruction formats 5 to 10 have bit10 and bit9 on and are a word -// The rest of the instructions are half-word and their format is 1 to 4 -int detect_inst_len(uint16 w) -{ - return ((w & 0x600) == 0x600) ? 4 : 2; -} - -//------------------------------------------------------------------------ -// Fetchs an instruction (uses ua_next_xxx(insn)) of a correct size (ready for decoding) -// Returns the size of the instruction -int fetch_instruction(uint32 *w, insn_t &insn) -{ - uint16 hw = insn.get_next_word(); - int r = detect_inst_len(hw); - if ( r == 4 ) - *w = (insn.get_next_word() << 16) | hw; - else - *w = hw; - return r; -} - -//------------------------------------------------------------------------ -static sval_t fetch_disp32(const uint32 w, insn_t &ins) -{ - //15 0 31 16 47 32 - //xxxxxxxxxxxxxxxx ddddddddddddddd0 DDDDDDDDDDDDDDDD - uint32 d_low = (w >> 16);// ddddddddddddddd0 - if ( ins.size == 2 ) - d_low = ins.get_next_word(); - else if ( ins.size != 4 ) - { - //bad format - ins.size = 0; - ins.itype = 0; - return 1; - } - uint16 d_high = ins.get_next_word(); //DDDDDDDDDDDDDDDD - int32 addr = (d_high<<16) | d_low; - return sval_t(addr); -} - -//------------------------------------------------------------------------ -static bool decode_disp23(const uint32 w, insn_t &ins, int opidx, op_dtype_t dt) -{ - // LD.B disp23 [reg1] , reg3 - // 00000111100RRRRR wwwwwddddddd0101 DDDDDDDDDDDDDDDD - // ddddddd is the lower 7 bits of disp23. - // DDDDDDDDDDDDDDDD is the higher 16 bits of disp23 - // LD.H disp23[reg1], reg3 - // 00000111100RRRRR wwwwwdddddd00111 DDDDDDDDDDDDDDDD - // dddddd is the lower side bits 6 to 1 of disp23. - // DDDDDDDDDDDDDDDD is the higher 16 bits of disp23. - - // we need at least 32 bits of opcode here - if ( ins.size != 4 ) - return false; - - uint16 d_low = ( w >> 20 ) & 0x7F; //ddddddd - if ( dt != dt_byte && ( d_low & 1 ) != 0 ) - return false; - uint16 d_high = ins.get_next_word(); //DDDDDDDDDDDDDDDD - sval_t addr = ( d_high << 7 ) | d_low; - SIGN_EXTEND(sval_t, addr, 23); - - op_t &op = ins.ops[opidx]; - op.type = o_displ; - op.reg = w & 0x1F; - op.addr = addr; - op.dtype = dt; - op.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED | N850F_VAL32; - return true; -} - -//------------------------------------------------------------------------ -static void set_opreg(op_t &op, int reg, op_dtype_t dtyp = dt_dword) -{ - op.type = o_reg; - op.dtype = dtyp; - op.reg = reg; -} - -//---------------------------------------------------------------------- -// Create operand of condition type -inline void set_opcond(op_t &x, uval_t value) -{ - x.type = o_cond; - x.dtype = dt_qword; - x.value = value; -} - - -//------------------------------------------------------------------------ -static void set_opimm(op_t &op, uval_t value, int dtyp = dt_dword) -{ - op.type = o_imm; - op.dtype = dtyp; - op.value = value; -} - -//------------------------------------------------------------------------ -// Decodes an instruction "w" into cmd structure -bool nec850_t::decode_coprocessor(const uint32 w, insn_t &ins) const -{ //11111 1 33222 2 222 22 2111 1 - //54321 098765 43210 10987 6 543 21 0987 6 - //reg2 |opcode|reg1 |reg3 |b|cat|ty|subo|b| - //..... |111111|.....|.....|1|...|..|....|0| - int r1 = w & 0x1F; - int r2 = ( w & 0xF800 ) >> 11; - int r3 = ( w & 0xF8000000 ) >> 27; - int cat = ( w >> 23 ) & 7; - int typ = ( w >> 21 ) & 3; - int subop = ( w >> 17 ) & 0xF; - ins.itype = NEC850_NULL; - // we only support V850E2M and RH850 FP instructions - if ( !is_v850e2m() ) - return false; - if ( typ == 0 && cat == 0 ) - { - //CMOVF.D: cat = 000, type = 00, subop = 1fff, reg3 != 0 - //CMOVF.S : cat = 000, type = 00, subop = 0fff, reg3 != 0 - //TRFSR: cat = 000, type = 00, subop = 0fff, reg1 = 0, reg3 = 0 - if ( r3 != 0 ) - { - //CMOVF.S|D fcbit, reg1, reg2, reg3 - ins.itype = ( subop & 8 ) ? NEC850_CMOVF_D : NEC850_CMOVF_S; - int fcbit = subop & 7; - set_opimm(ins.Op1, fcbit); - set_opreg(ins.Op2, r1); - set_opreg(ins.Op3, r2); - set_opreg(ins.Op4, r3); - } - else if ( subop < 8 ) - { - ins.itype = NEC850_TRFSR; - int fcbit = subop & 7; - set_opimm(ins.Op1, fcbit); - } - } - else if ( typ == 1 && cat == 0 && r3 < 0x10 ) - { - //CMPF.D: cat = 000, type = 01, subop = 1fff, reg3 = 0FFFF - //CMPF.S : cat = 000, type = 01, subop = 0fff, reg3 = 0FFFF - //CMPF.S|D fcond, reg2, reg1, fcbit - ins.itype = ( subop & 8 ) ? NEC850_CMPF_D : NEC850_CMPF_S; - int fcbit = subop & 7; - set_opcond(ins.Op1, r3); - set_opreg(ins.Op2, r2); - set_opreg(ins.Op3, r1); - set_opimm(ins.Op4, fcbit); - } - else if ( typ == 3 ) - { - // reg1, reg2, reg3 - if ( cat == 0 ) - { - switch ( subop & 7 ) - { - case 0: - ins.itype = ( subop & 8 ) ? NEC850_ADDF_D : NEC850_ADDF_S; - break; - case 1: - ins.itype = ( subop & 8 ) ? NEC850_SUBF_D : NEC850_SUBF_S; - break; - case 2: - ins.itype = ( subop & 8 ) ? NEC850_MULF_D : NEC850_MULF_S; - break; - case 4: - ins.itype = ( subop & 8 ) ? NEC850_MAXF_D : NEC850_MAXF_S; - break; - case 5: - ins.itype = ( subop & 8 ) ? NEC850_MINF_D : NEC850_MINF_S; - break; - case 7: - ins.itype = ( subop & 8 ) ? NEC850_DIVF_D : NEC850_DIVF_S; - break; - - } - } - else if ( cat == 1 && subop < 4 ) - { - if ( is_rh850() ) - { - uint16 itypes[] = { NEC850_FMAF_S, NEC850_FMSF_S, NEC850_FNMAF_S, NEC850_FNMSF_S }; - ins.itype = itypes[subop]; - } - } - if ( ins.itype != NEC850_NULL ) - { - bool dbl = ( subop & 8 ) != 0; - op_dtype_t dt = dbl ? dt_double : dt_float; - set_opreg(ins.Op1, r1, dt); - set_opreg(ins.Op2, r2, dt); - set_opreg(ins.Op3, r3, dt); - } - } - else if ( typ == 2 && cat == 0 ) - { - //reg2, reg3 conversions - op_dtype_t dtsrc = dt_float, dtdst = dt_float; - switch ( subop ) - { - case 0: - { - //TRNCF.SW cat = 0 type = 2 subop = 0 reg1 = 1 - //CEILF.SW cat = 0 type = 2 subop = 0 reg1 = 2 - //FLOORF.SW cat = 0 type = 2 subop = 0 reg1 = 3 - //CVTF.SW cat = 0 type = 2 subop = 0 reg1 = 4 - //TRNCF.SUW cat = 0 type = 2 subop = 0 reg1 = 17 - //CEILF.SUW cat = 0 type = 2 subop = 0 reg1 = 18 - //FLOORF.SUW cat = 0 type = 2 subop = 0 reg1 = 19 - //CVTF.SUW cat = 0 type = 2 subop = 0 reg1 = 20 - static const int ops[] = - { - NEC850_NULL, NEC850_TRNCF_SW, NEC850_CEILF_SW, NEC850_FLOORF_SW, //0-3 - NEC850_CVTF_SW, NEC850_NULL, NEC850_NULL, NEC850_NULL, //4-7 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //8-11 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //12-15 - NEC850_NULL, NEC850_TRNCF_SUW, NEC850_CEILF_SUW, NEC850_FLOORF_SUW, //16-19 - NEC850_CVTF_SUW //20 - }; - if ( r1 < qnumber(ops) ) - ins.itype = ops[r1]; - dtsrc = dt_float; - dtdst = dt_dword; - } - break; - case 1: - { - //CVTF.WS cat=0 type=2 subop=1 reg1=0 dw f - //CVTF.LS cat=0 type=2 subop=1 reg1=1 dq f - //CVTF.HS cat=0 type=2 subop=1 reg1=2 h f - //CVTF.SH cat=0 type=2 subop=1 reg1=3 f h - //CVTF.UWS cat=0 type=2 subop=1 reg1=16 dw f - //CVTF.ULS cat=0 type=2 subop=1 reg1=17 dq f - static const int ops[] = - { - NEC850_CVTF_WS, NEC850_CVTF_LS, NEC850_CVTF_HS, NEC850_CVTF_SH, //0-3 - NEC850_CVTF_SW, NEC850_NULL, NEC850_NULL, NEC850_NULL, //4-7 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //8-11 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //12-15 - NEC850_CVTF_UWS, NEC850_CVTF_ULS //16-17 - }; - if ( r1 < qnumber(ops) ) - ins.itype = ops[r1]; - //NB: we use dt_float for half-precision - op_dtype_t srct[] = { dt_dword, dt_qword, dt_float, dt_float }; - dtsrc = srct[r1&3]; - dtdst = dt_float; - } - break; - case 2: - { - //TRNCF.SL cat=0 type=2 subop=2 reg1=1 - //CEILF.SL cat=0 type=2 subop=2 reg1=2 - //FLOORF.SL cat=0 type=2 subop=2 reg1=3 - //CVTF.SL cat=0 type=2 subop=2 reg1=4 - //TRNCF.SUL cat=0 type=2 subop=2 reg1=17 - //CEILF.SUL cat=0 type=2 subop=2 reg1=18 - //FLOORF.SUL cat=0 type=2 subop=2 reg1=19 - //CVTF.SUL cat=0 type=2 subop=2 reg1=20 - static const int ops[] = - { - NEC850_NULL, NEC850_TRNCF_SL, NEC850_CEILF_SL, NEC850_FLOORF_SL, //0-3 - NEC850_CVTF_SL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //4-7 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //8-11 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //12-15 - NEC850_NULL, NEC850_TRNCF_SUL, NEC850_CEILF_SUL, NEC850_FLOORF_SUL, //16-19 - NEC850_CVTF_SUL //20 - }; - if ( r1 < qnumber(ops) ) - ins.itype = ops[r1]; - dtsrc = dt_float; - dtdst = dt_qword; - } - break; - case 4: - case 12: - { - //ABSF.S cat = 0 type = 2 subop = 4 reg1 = 0 - //NEGF.S cat = 0 type = 2 subop = 4 reg1 = 1 - //ABSF.D cat = 0 type = 2 subop = 12 reg1 = 0 - //NEGF.D cat = 0 type = 2 subop = 12 reg1 = 1 - if ( r1 == 0 ) - ins.itype = subop == 4 ? NEC850_ABSF_S : NEC850_ABSF_D; - else if ( r1 == 1 ) - ins.itype = subop == 4 ? NEC850_NEGF_S : NEC850_NEGF_D; - - dtsrc = subop == 4 ? dt_float: dt_double; - dtdst = dtsrc; - } - break; - case 7: - case 15: - { - //SQRTF.S cat=0 type=2 subop=7 reg1=0 - //RECIPF.S cat=0 type=2 subop=7 reg1=1 - //RSQRTF.S cat=0 type=2 subop=7 reg1=2 - //SQRTF.D cat=0 type=2 subop=15 reg1=0 - //RECIPF.D cat=0 type=2 subop=15 reg1=1 - //RSQRTF.D cat=0 type=2 subop=15 reg1=2 - - if ( r1 == 0 ) - ins.itype = subop == 7 ? NEC850_SQRTF_S : NEC850_SQRTF_D; - else if ( r1 == 1 ) - ins.itype = subop == 7 ? NEC850_RECIPF_S : NEC850_RECIPF_D; - else if ( r1 == 2 ) - ins.itype = subop == 7 ? NEC850_RSQRTF_S : NEC850_RSQRTF_D; - - dtsrc = subop == 7 ? dt_float : dt_double; - dtdst = dtsrc; - } - break; - case 8: - { - //TRNCF.DW cat=0 type=2 subop=8 reg1=1 - //CEILF.DW cat=0 type=2 subop=8 reg1=2 - //FLOORF.DW cat=0 type=2 subop=8 reg1=3 - //CVTF.DW cat=0 type=2 subop=8 reg1=4 - //TRNCF.DUW cat=0 type=2 subop=8 reg1=17 - //CEILF.DUW cat=0 type=2 subop=8 reg1=18 - //FLOORF.DUW cat=0 type=2 subop=8 reg1=19 - //CVTF.DUW cat=0 type=2 subop=8 reg1=20 - static const int ops[] = - { - NEC850_NULL, NEC850_TRNCF_DW, NEC850_CEILF_DW, NEC850_FLOORF_DW, //0-3 - NEC850_CVTF_DW, NEC850_NULL, NEC850_NULL, NEC850_NULL, //4-7 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //8-11 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //12-15 - NEC850_NULL, NEC850_TRNCF_DUW, NEC850_CEILF_DUW, NEC850_FLOORF_DUW, //16-19 - NEC850_CVTF_DUW //20 - }; - if ( r1 < qnumber(ops) ) - ins.itype = ops[r1]; - dtsrc = dt_double; - dtdst = dt_dword; - } - break; - case 9: - { - //CVTF.WD cat=0 type=2 subop=9 reg1=0 dw d - //CVTF.LD cat=0 type=2 subop=9 reg1=1 dq d - //CVTF.SD cat=0 type=2 subop=9 reg1=2 f d - //CVTF.DS cat=0 type=2 subop=9 reg1=3 d f - //CVTF.UWD cat=0 type=2 subop=9 reg1=16 dw d - //CVTF.ULD cat=0 type=2 subop=9 reg1=17 dq d - static const int ops[] = - { - NEC850_CVTF_WD, NEC850_CVTF_LD, NEC850_CVTF_SD, NEC850_CVTF_DS, //0-3 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //4-7 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //8-11 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //12-15 - NEC850_CVTF_UWD, NEC850_CVTF_ULD //16-17 - }; - if ( r1 < qnumber(ops) ) - ins.itype = ops[r1]; - op_dtype_t srct[] = { dt_dword, dt_qword, dt_float, dt_double }; - dtsrc = srct[r1 & 3]; - dtdst = r1 == 3 ? dt_float : dt_double; - } - break; - case 10: - { - //TRNCF.DL cat=0 type=2 subop=10 reg1=1 - //CEILF.DL cat=0 type=2 subop=10 reg1=2 - //FLOORF.DL cat=0 type=2 subop=10 reg1=3 - //CVTF.DL cat=0 type=2 subop=10 reg1=4 - //TRNCF.DUL cat=0 type=2 subop=10 reg1=17 - //CEILF.DUL cat=0 type=2 subop=10 reg1=18 - //FLOORF.DUL cat=0 type=2 subop=10 reg1=19 - //CVTF.DUL cat=0 type=2 subop=10 reg1=20 - static const int ops[] = - { - NEC850_NULL, NEC850_TRNCF_DL, NEC850_CEILF_DL, NEC850_FLOORF_DL, //0-3 - NEC850_CVTF_DL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //4-7 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //8-11 - NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, //12-15 - NEC850_NULL, NEC850_TRNCF_DUL, NEC850_CEILF_DUL, NEC850_FLOORF_DUL, //16-19 - NEC850_CVTF_DUL //20 - }; - if ( r1 < qnumber(ops) ) - ins.itype = ops[r1]; - dtsrc = dt_double; - dtdst = dt_qword; - } - break; - } - if ( ins.itype != NEC850_NULL ) - { - set_opreg(ins.Op1, r2, dtsrc); - set_opreg(ins.Op2, r3, dtdst); - } - } - if ( ins.itype == NEC850_NULL && is_v850e2m() && ( cat >> 1 ) == 1 ) - { - //reg1, reg2, reg3, reg4 - //MADDF.S: cat = 01W type = 00, subop = WWWW - //MSUBF.S : cat = 01W type = 01, subop = WWWW - //NMADDF.S : cat = 01W type = 10, subop = WWWW - //NMSUBF.S : cat = 01W type = 11, subop = WWWW - //WWWWW: reg4. (The least significant bit of reg4 is bit 23.) - - int r4 = (subop << 1) | (cat & 1); - static const uint16 itypes[] = { NEC850_MADDF_S, NEC850_MSUBF_S, NEC850_NMADDF_S, NEC850_NMSUBF_S }; - ins.itype = itypes[typ]; - set_opreg(ins.Op1, r1, dt_float); - set_opreg(ins.Op2, r2, dt_float); - set_opreg(ins.Op3, r3, dt_float); - set_opreg(ins.Op4, r4, dt_float); - } - - - if ( ins.itype != NEC850_NULL ) - { - ins.auxpref |= N850F_FP; - return true; - } - return false; -} - - //------------------------------------------------------------------------ -// Decodes an instruction "w" into cmd structure -bool nec850_t::decode_instruction(const uint32 w, insn_t &ins) -{ -#define PARSE_L12 (((w & 1) << 11) | (w >> 21)) -#define PARSE_R1 (w & 0x1F) -#define PARSE_R2 ((w & 0xF800) >> 11) - - typedef struct - { - int itype; - int flags; - } itype_flags_t; - // If an instruction deals with displacement it should - // initialize this pointer to the operand location. - // At the end we will transform the operand to o_mem - // if we know how to resolve its address - op_t *displ_op = NULL; - - do - { - uint32 op; - - // - // Format I - // - op = (w & 0x7E0) >> 5; // Take bit5->bit10 - if ( op <= 0xF ) - { - static const int inst_1[] = - { - /* MOV reg1, reg2 */ NEC850_MOV, /* NOT reg1, reg2 */ NEC850_NOT, - /* DIVH reg1, reg2 */ NEC850_DIVH, /* JMP [reg1] */ NEC850_JMP, - /* SATSUBR reg1, reg2 */ NEC850_SATSUBR, /* SATSUB reg1, reg2 */ NEC850_SATSUB, - /* SATADD reg1, reg2 */ NEC850_SATADD, /* MULH reg1, reg2 */ NEC850_MULH, - /* OR reg1, reg2 */ NEC850_OR, /* XOR reg1, reg2 */ NEC850_XOR, - /* AND reg1, reg2 */ NEC850_AND, /* TST reg1, reg2 */ NEC850_TST, - /* SUBR reg1, reg2 */ NEC850_SUBR, /* SUB reg1, reg2 */ NEC850_SUB, - /* ADD reg1, reg2 */ NEC850_ADD, /* CMP reg1, reg2 */ NEC850_CMP - }; - - // - // NOP, Equivalent to MOV R, r (where R=r=0) - if ( w == 0 ) - { - ins.itype = NEC850_NOP; - ins.Op1.type = o_void; - ins.Op1.dtype = dt_void; - break; - } - - uint16 r1 = PARSE_R1; - uint16 r2 = PARSE_R2; - if ( is_v850e() && op == 2 && r1 == 0 ) - { - switch ( r2 ) - { - case 0: - if ( is_v850e2m() ) - ins.itype = NEC850_RIE; - break; - case 0x1C: - if ( is_rh850() ) - ins.itype = NEC850_DBHVTRAP; - break; - case 0x1D: - if ( is_rh850() ) - ins.itype = NEC850_DBCP; - break; - case 0x1E: - if ( is_v850e2m() ) - ins.itype = NEC850_RMTRAP; - break; - case 0x1F: - ins.itype = NEC850_DBTRAP; - break; - default: - if ( is_v850e2() && r2 < 0x10 ) - { - ins.itype = NEC850_FETRAP; - set_opimm(ins.Op1, r2); - } - break; - } - if ( ins.itype != 0 ) - break; - } - - ins.itype = inst_1[op]; - set_opreg(ins.Op1, r1); - - if ( is_v850e() ) - { - if ( r2 == 0 ) - { - if ( is_v850e2m() && op == 0 ) - { - switch ( r1 ) - { - case 0x1C: - if ( is_rh850() ) - ins.itype = NEC850_SYNCI; - else - ins.itype = NEC850_NULL; - break; - case 0x1D: - ins.itype = NEC850_SYNCE; - break; - case 0x1E: - ins.itype = NEC850_SYNCM; - break; - case 0x1F: - ins.itype = NEC850_SYNCP; - break; - default: - ins.itype = NEC850_NULL; - break; - } - if ( ins.itype != NEC850_NULL ) - { - ins.Op1.type = o_void; - ins.Op2.type = o_void; - break; - } - } - else if ( ins.itype == NEC850_DIVH ) - { - ins.itype = NEC850_SWITCH; - break; - } - else if ( ins.itype == NEC850_SATSUBR ) - { - ins.itype = NEC850_ZXB; - break; - } - else if ( ins.itype == NEC850_SATSUB ) - { - ins.itype = NEC850_SXB; - break; - } - else if ( ins.itype == NEC850_SATADD ) - { - ins.itype = NEC850_ZXH; - break; - } - else if ( ins.itype == NEC850_MULH ) - { - ins.itype = NEC850_SXH; - break; - } - } - // case when r2 != 0 - else - { - // SLD.BU / SLD.HU - if ( ins.itype == NEC850_JMP ) - { - bool sld_hu = (w >> 4) & 1; - uint32 addr = w & 0xF; - - if ( sld_hu ) - { - ins.itype = NEC850_SLD_HU; - ins.Op1.dtype = dt_word; - addr <<= 1; - } - else - { - ins.itype = NEC850_SLD_BU; - ins.Op1.dtype = dt_byte; - } - - ins.Op1.type = o_displ; - displ_op = &ins.Op1; - ins.Op1.reg = rEP; - ins.Op1.addr = addr; - ins.Op1.specflag1 = N850F_USEBRACKETS; - - set_opreg(ins.Op2, r2); - - break; - } - } - } - if ( ins.itype == NEC850_JMP && r2 == 0 ) - { - ins.Op1.specflag1 = N850F_USEBRACKETS; - } - else - { - set_opreg(ins.Op2, r2); - } - break; - } - // Format II - else if ( op <= 0x17 ) - { - if ( PARSE_R2 == 0 && op == 0x17 && is_v850e2m() ) - { - //48-bit Format VI jr/jarl - //JARL disp32, reg1: 00000010111RRRRR ddddddddddddddd0 DDDDDDDDDDDDDDDD - //JR disp32: 0000001011100000 ddddddddddddddd0 DDDDDDDDDDDDDDDD - uint16 reg = PARSE_R1; - sval_t addr = fetch_disp32(w, ins); - if ( (addr & 1) != 0 ) - return false; - ins.Op1.addr = ins.ip + addr; - ins.Op1.type = o_near; - ins.Op1.specflag1 = N850F_VAL32; - if ( reg == 0 ) - { - ins.itype = NEC850_JR; - } - else - { - ins.itype = NEC850_JARL; - set_opreg(ins.Op2, reg); - } - break; - } - // flag used for sign extension - static const itype_flags_t inst_2[] = - { - { NEC850_MOV, 1 }, /* MOV imm5, reg2 */ - { NEC850_SATADD, 1 }, /* SATADD imm5, reg2 */ - { NEC850_ADD, 1 }, /* ADD imm5, reg2 */ - { NEC850_CMP, 1 }, /* CMP imm5, reg2 */ - { NEC850_SHR, 0 }, /* SHR imm5, reg2 */ - { NEC850_SAR, 0 }, /* SAR imm5, reg2 */ - { NEC850_SHL, 0 }, /* SHL imm5, reg2 */ - { NEC850_MULH, 1 }, /* MULH imm5, reg2 */ - }; - op -= 0x10; - - ins.itype = inst_2[op].itype; - uint16 r2 = PARSE_R2; - - if ( is_v850e() ) - { - // - // CALLT - // - if ( r2 == 0 && (ins.itype == NEC850_SATADD || ins.itype == NEC850_MOV) ) - { - ins.itype = NEC850_CALLT; - set_opimm(ins.Op1, w & 0x3F, dt_byte); - if ( g_ctbp_ea != BADADDR ) - { - // resolve callt addr using ctbp - ea_t ctp = g_ctbp_ea + (ins.Op1.value << 1); - ins.Op1.type = o_near; - ins.Op1.addr = g_ctbp_ea + get_word(ctp); - } - break; - } - } - - sval_t v = PARSE_R1; - if ( inst_2[op].flags == 1 ) - { - SIGN_EXTEND(sval_t, v, 5); - ins.Op1.specflag1 |= N850F_OUTSIGNED; - } - - set_opimm(ins.Op1, v, dt_byte); - set_opreg(ins.Op2, r2); - - // ADD imm, reg -> reg = reg + imm - if ( ins.itype == NEC850_ADD && r2 == rSP ) - ins.auxpref |= N850F_SP; - break; - } - // Format VI - else if ( op >= 0x30 && op <= 0x37 ) - { - static const itype_flags_t inst_6[] = - { - { NEC850_ADDI, 1 }, /* ADDI imm16, reg1, reg2 */ - { NEC850_MOVEA, 1 }, /* MOVEA imm16, reg1, reg2 */ - { NEC850_MOVHI, 0 }, /* MOVHI imm16, reg1, reg2 */ - { NEC850_SATSUBI, 1 }, /* SATSUBI imm16, reg1, reg2 */ - { NEC850_ORI, 0 }, /* ORI imm16, reg1, reg2 */ - { NEC850_XORI, 0 }, /* XORI imm16, reg1, reg2 */ - { NEC850_ANDI, 0 }, /* ANDI imm16, reg1, reg2 */ - { NEC850_MULHI, 0 }, /* MULHI imm16, reg1, reg2 */ - }; - op -= 0x30; - ins.itype = inst_6[op].itype; - - uint16 r1 = PARSE_R1; - uint16 r2 = PARSE_R2; - uint32 imm = w >> 16; - - // - // V850E instructions - if ( is_v850e() && r2 == 0 ) - { - if ( ins.itype == NEC850_MULHI ) - { - if ( !is_v850e2() ) - return false; // "Do not specify r0 as the destination register reg2." - if ( ( imm & 1 ) != 0 ) - { - // RH850: LOOP reg1,disp16 - // 00000110111RRRRR ddddddddddddddd1 - if ( !is_rh850() || r1 == 0 ) - return false; // "Do not specify r0 for reg1." - ins.itype = NEC850_LOOP; - set_opreg(ins.Op1, r1); - imm ^= 1; //clear bit 0 - sval_t addr = ins.ip - imm; - ins.Op2.addr = addr; - ins.Op2.type = o_near; - } - else - { - // V850E2: jmp disp32 [reg1] - // 00000110111RRRRR ddddddddddddddd0 DDDDDDDDDDDDDDDD - sval_t addr = fetch_disp32(w, ins); - if ( ( addr & 1 ) != 0 ) - return false; - ins.Op1.addr = addr; - ins.Op1.type = o_displ; - ins.Op1.specflag1 = N850F_OUTSIGNED | N850F_VAL32 | N850F_USEBRACKETS; - ins.Op1.reg = r1; - ins.itype = NEC850_JMP; - } - break; - } - // MOV imm32, R - if ( ins.itype == NEC850_MOVEA ) - { - imm |= ins.get_next_word() << 16; - set_opimm(ins.Op1, imm); - ins.itype = NEC850_MOV; - - set_opreg(ins.Op2, r1); - break; - } - // DISPOSE imm5, list12 (reg1 == 0) - // DISPOSE imm5, list12, [reg1] - else if ( ins.itype == NEC850_SATSUBI || ins.itype == NEC850_MOVHI ) - { - r1 = (w >> 16) & 0x1F; - uint16 L = PARSE_L12; - - ins.auxpref |= N850F_SP; // SP reference - - set_opimm(ins.Op1, (w & 0x3E) >> 1, dt_byte); - - ins.Op2.value = L; - ins.Op2.type = o_reglist; - ins.Op2.dtype = dt_word; - - if ( r1 != 0 ) - { - set_opreg(ins.Op3, r1); - ins.Op3.specflag1 = N850F_USEBRACKETS; - - ins.itype = NEC850_DISPOSE_r; - } - else - { - ins.itype = NEC850_DISPOSE_r0; - } - break; - } - } - bool is_signed = inst_6[op].flags == 1; - set_opimm(ins.Op1, is_signed ? sval_t(int16(imm)) : imm); - ins.Op1.specflag1 |= N850F_OUTSIGNED; - - set_opreg(ins.Op2, r1); - - set_opreg(ins.Op3, r2); - - // (ADDI|MOVEA) imm, sp, sp -> sp = sp + imm - if ( (ins.itype == NEC850_ADDI || ins.itype == NEC850_MOVEA) - && ((r1 == rSP) && (r2 == rSP)) ) - { - ins.auxpref |= N850F_SP; - } - break; - } - // Format VII - LD.x - else if ( op == 0x38 || op == 0x39 ) - { - displ_op = &ins.Op1; - ins.Op1.type = o_displ; - ins.Op1.phrase = PARSE_R1; // R - - set_opreg(ins.Op2, PARSE_R2); - - uint32 addr; - // LD.B - if ( op == 0x38 ) - { - addr = w >> 16; - ins.itype = NEC850_LD_B; - ins.Op1.dtype = dt_byte; - } - else - { - // Bit16 is cleared for LD.H - if ( (w & (1 << 16)) == 0 ) - { - ins.itype = NEC850_LD_H; - ins.Op1.dtype = dt_word; - } - // LD.W - else - { - ins.itype = NEC850_LD_W; - ins.Op1.dtype = dt_dword; - } - addr = ((w & 0xFFFE0000) >> 17) << 1; - } - ins.Op1.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; - ins.Op1.addr = int16(addr); - - break; - } - // Format VII - ST.x - else if ( op == 0x3A || op == 0x3B ) - { - // (1) ST.B reg2, disp16 [reg1] - // (2) ST.H reg2, disp16 [reg1] - // (3) ST.W reg2, disp16 [reg1] - set_opreg(ins.Op1, PARSE_R2); - - ins.Op2.type = o_displ; - displ_op = &ins.Op2; - ins.Op2.reg = PARSE_R1; - ins.Op2.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; - // ST.B - uint32 addr; - if ( op == 0x3A ) - { - addr = w >> 16; - ins.itype = NEC850_ST_B; - ins.Op2.dtype = dt_byte; - } - else - { - // Bit16 is cleared for ST.H - if ( (w & (1 << 16)) == 0 ) - { - ins.itype = NEC850_ST_H; - ins.Op2.dtype = dt_word; - } - else - { - ins.itype = NEC850_ST_W; - ins.Op2.dtype = dt_dword; - } - addr = ((w & 0xFFFE0000) >> 17) << 1; - } - ins.Op2.addr = int16(addr); - break; - } - // Format XIII - PREPARE / LD.BU - else if ( is_v850e() - && ((w >> 16) & 0x1) // this bit is important to differentiate between JARL/JR instructions - && (op == 0x3C || op == 0x3D) ) - { - uint16 r2 = PARSE_R2; - - uint16 subop = (w >> 16) & 0x1F; - // PREPARE - if ( r2 == 0 && (subop == 1 || (subop & 7) == 3) ) - { - ins.auxpref |= N850F_SP; - ins.Op1.value = PARSE_L12; - ins.Op1.type = o_reglist; - ins.Op1.dtype = dt_word; - - set_opimm(ins.Op2, (w & 0x3E) >> 1, dt_byte); - - if ( subop == 1 ) - { - ins.itype = NEC850_PREPARE_i; - } - else - { - ins.itype = NEC850_PREPARE_sp; - uint16 ff = subop >> 3; - switch ( ff ) - { - case 0: - // disassembles as: PREPARE list12, imm5, sp - // meaning: load sp into ep - set_opreg(ins.Op3, rSP); - break; - // the other cases disassemble with imm (the 3rd operand) directly processed: - // f=1->ep=sign_extend(imm16), f=2->ep=imm16 shl 16, f=3->ep=imm32 - case 1: - // c: a8 07 0b 80 prepare {r24}, 20, 0x1 - //10: 01 00 - set_opimm(ins.Op3, sval_t(int16(ins.get_next_word()))); - break; - case 2: - //2: a8 07 13 80 prepare {r24}, 20, 0x10000 - //6: 01 00 - set_opimm(ins.Op3, ins.get_next_word() << 16); - break; - case 3: - //2: a8 07 1b 80 prepare {r24}, 20, 0x1 - //6: 01 00 00 00 - set_opimm(ins.Op3, ins.get_next_dword()); - break; - } - } - } - else if ( r2 == 0 && is_v850e2m() ) - { - //disp23 variants ( Format XIV) - // LD.BU disp23 [reg1] , reg3 - // 00000111101RRRRR wwwwwddddddd0101 DDDDDDDDDDDDDDDD - // LD.HU disp23 [reg1] , reg3 - // 00000111101RRRRR wwwwwdddddd00111 DDDDDDDDDDDDDDDD - // ST.H reg3, disp23 [reg1] - // 00000111101RRRRR wwwwwdddddd01101 DDDDDDDDDDDDDDDD - // ST.H reg3, disp23 [reg1] - // 00000111101RRRRR wwwwwdddddd01101 DDDDDDDDDDDDDDDD - // LD.B disp23 [reg1] , reg3 - // 00000111100RRRRR wwwwwddddddd0101 DDDDDDDDDDDDDDDD - // LD.H disp23 [reg1] , reg3 - // 00000111100RRRRR wwwwwdddddd00111 DDDDDDDDDDDDDDDD - // LD.W disp23 [reg1] , reg3 - // 00000111100RRRRR wwwwwdddddd01001 DDDDDDDDDDDDDDDD - // LD.DW disp23[reg1], reg3 - // 00000111101RRRRR wwwwwdddddd01001 DDDDDDDDDDDDDDDD - // ST.B reg3, disp23 [reg1] - // 00000111100RRRRR wwwwwddddddd1101 DDDDDDDDDDDDDDDD - // ST.W reg3, disp23 [reg1] - // 00000111100RRRRR wwwwwdddddd01111 DDDDDDDDDDDDDDDD - // ST.DW reg3, disp23[reg1] - // 00000111101RRRRR wwwwwdddddd01111 DDDDDDDDDDDDDDDD - // RRRRR = reg1, wwwww = reg3. - // ddddddd is the lower 7 bits of disp23. - // DDDDDDDDDDDDDDDD is the higher 16 bits of disp23. - subop = ( w >> 16 ) & 0xF; - bool sign = ( op & 1 ) == 0; - uint32 r3 = ( w & 0xF8000000 ) >> 27; - switch ( subop ) - { - case 5: - ins.itype = sign ? NEC850_LD_B : NEC850_LD_BU; - if ( !decode_disp23(w, ins, 0, dt_byte) ) - return false; - set_opreg(ins.Op2, r3); - break; - case 7: - ins.itype = sign ? NEC850_LD_H : NEC850_LD_HU; - if ( !decode_disp23(w, ins, 0, dt_word) ) - return false; - set_opreg(ins.Op2, r3); - break; - case 9: - if ( !sign && !is_rh850() ) - return false; - ins.itype = sign ? NEC850_LD_W : NEC850_LD_DW; - if ( !decode_disp23(w, ins, 0, dt_dword) ) - return false; - set_opreg(ins.Op2, r3); - break; - case 13: - ins.itype = sign ? NEC850_ST_B : NEC850_ST_H; - if ( !decode_disp23(w, ins, 1, sign ? dt_byte : dt_word) ) - return false; - set_opreg(ins.Op1, r3); - break; - case 15: - if ( !sign && !is_rh850() ) - return false; - ins.itype = sign ? NEC850_ST_W : NEC850_ST_DW; - if ( !decode_disp23(w, ins, 1, dt_dword) ) - return false; - set_opreg(ins.Op1, r3); - break; - } - } - else - { - // LD.BU disp16 [reg1] , reg2 - // rrrrr11110bRRRRR ddddddddddddddd1 - // ddddddddddddddd is the higher 15 bits of disp16, and b is bit 0 of disp16. - // rrrrr != 00000 ( Do not specify r0 for reg2. ) - if ( r2 == 0 ) - return false; - uint16 r1 = PARSE_R1; - - ins.itype = NEC850_LD_BU; - - ins.Op1.type = o_displ; - displ_op = &ins.Op1; - ins.Op1.reg = r1; - ins.Op1.addr = int16(((w >> 16) & ~1) | ((w & 0x20) >> 5)); - ins.Op1.dtype = dt_byte; - ins.Op1.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; - - set_opreg(ins.Op2, r2); - } - break; - } - // Format VIII - else if ( op == 0x3E ) - { - // parse sub-opcode (b15..b14) - op = ((w & 0xC000) >> 14); - static const int inst_8[] = - { - NEC850_SET1, NEC850_NOT1, - NEC850_CLR1, NEC850_TST1 - }; - ins.itype = inst_8[op]; - set_opimm(ins.Op1, ((w & 0x3800) >> 11), dt_byte); - - - ins.Op2.type = o_displ; - displ_op = &ins.Op2; - ins.Op2.addr = int16(w >> 16); - ins.Op2.offb = 2; - ins.Op2.dtype = dt_byte; - ins.Op2.reg = PARSE_R1; // R - ins.Op2.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; - break; - } - // - // Format IX, X - // - else if ( op == 0x3F ) - { - if ( (w & ( 1 << 16 )) == 0 && ( w & ( 1 << 26 ) ) != 0 ) - //coprocessor insn - return decode_coprocessor(w, ins); - // - // Format X - // - - // Const opcodes - if ( w == 0x16087E0 ) // EI - ins.itype = NEC850_EI; - else if ( w == 0x16007E0 ) // DI - ins.itype = NEC850_DI; - else if ( w == 0x14007E0 ) // RETI - ins.itype = NEC850_RETI; - else if ( w == 0x12007E0 ) // HALT - ins.itype = NEC850_HALT; - else if ( w == 0xffffffff ) - ins.itype = NEC850_BREAKPOINT; - else if ( (w >> 5) == 0x8003F ) //lint !e587 predicate always false // TRAP - { - ins.itype = NEC850_TRAP; - set_opimm(ins.Op1, PARSE_R1, dt_byte); - break; - } - if ( ins.itype != 0 ) - break; - if ( is_v850e1f() && !is_v850e2m() ) - { - //E1F opcodes (ref. U16374EJ1V0UM) - int subop = ( w >> 16 ) & 0x7FF; - int r3 = ( w & 0xF8000000 ) >> 27; - switch ( subop ) - { -// Format F:I reg1, reg2, reg3 - case 0x3E0: - ins.itype = NEC850_DIVF_S; - goto OPS_FI; - case 0x3E4: - ins.itype = NEC850_SUBF_S; - goto OPS_FI; - case 0x3E8: - ins.itype = NEC850_ADDF_S; - goto OPS_FI; - case 0x3EC: - ins.itype = NEC850_MULF_S; - goto OPS_FI; - case 0x3F0: - ins.itype = NEC850_MINF_S; - goto OPS_FI; - case 0x3F4: - ins.itype = NEC850_MAXF_S; -OPS_FI: - set_opreg(ins.Op1, PARSE_R1); - set_opreg(ins.Op2, PARSE_R2); - set_opreg(ins.Op3, r3); - break; -// Format F:II reg2, reg3 - case 0x360: - ins.itype = NEC850_CVT_SW; -OPS_FII: - set_opreg(ins.Op1, PARSE_R2); - set_opreg(ins.Op2, r3); - break; - case 0x368: - ins.itype = NEC850_TRNC_SW; - goto OPS_FII; - case 0x370: - ins.itype = NEC850_CVT_WS; - goto OPS_FII; - case 0x3F8: - ins.itype = NEC850_NEGF_S; - goto OPS_FII; - case 0x3FC: - ins.itype = NEC850_ABSF_S; - goto OPS_FII; - -// Format F:IV reg2 or reg3 - case 0x378: - if ( r3 != 0 ) - { - // STFF EFG,reg2 - ins.itype = NEC850_STFF; - set_opreg(ins.Op1, EFG); - set_opreg(ins.Op2, r3); - } - else - { - ins.itype = NEC850_TRFF; - // no operands - } - break; - case 0x37C: - // STFC ECT,reg2 - ins.itype = NEC850_STFC; - set_opreg(ins.Op1, ECT); - set_opreg(ins.Op2, r3); - break; - - case 0x37A: - if ( r3 == 0 ) - { - // LDFF reg2,EFG - ins.itype = NEC850_LDFF; - set_opreg(ins.Op1, PARSE_R2); - set_opreg(ins.Op2, EFG); - } - break; - - case 0x37E: - if ( r3 == 0 ) - { - // LDFC reg2,ECT - ins.itype = NEC850_LDFC; - set_opreg(ins.Op1, PARSE_R2); - set_opreg(ins.Op2, ECT); - } - break; - - } - if ( ins.itype != 0 ) - break; - } - // Still in format 10 (op = 0x3F) - if ( is_v850e() ) - { - if ( is_v850e2m() ) - { - if ( w == 0x14807E0 ) - ins.itype = NEC850_EIRET; - else if ( w == 0x14a07E0 ) - ins.itype = NEC850_FERET; - else if ( ( w & 0xc7ffffe0 ) == 0x0160d7e0 ) - { - ins.itype = NEC850_SYSCALL; - int v8 = (w & 0x1f) | ((w >> (27 - 5)) & 0xe0); - set_opimm(ins.Op1, v8); - } - else if ( is_rh850() ) - { - int subop = ( w >> 16 ) & 0x7FF; - switch ( subop ) - { - case 0x20: - case 0x40: - { - // LDSR reg2, regID, selID - // rrrrr111111RRRRR sssss00000100000 - // rrrrr: regID, sssss: selID, RRRRR: reg2 - // STSR regID, reg2, selID - // rrrrr111111RRRRR sssss00001000000 - // rrrrr: regID, sssss: selID, RRRRR: reg2 - bool is_ld = subop == 0x20; - ins.itype = is_ld ? NEC850_LDSR : NEC850_STSR; - uint32 selid = ( w & 0xF8000000 ) >> 27; - uint32 regid = PARSE_R1; - uint32 r2 = PARSE_R2; - if ( is_ld ) - { - //In this instruction, general-purpose register reg2 is used as the source register, but, for - //mnemonic description convenience, the general - purpose register reg1 field is used in the - //opcode.The meanings of the register specifications in the mnemonic descriptions and - //opcode therefore differ from those of other instructions. - set_opreg(ins.Op1, regid); - set_opreg(ins.Op2, r2 + rSR0); - } - else - { - set_opreg(ins.Op1, regid + rSR0); - set_opreg(ins.Op2, r2); - } - if ( selid != 0 ) - set_opimm(ins.Op3, selid); - } - break; - - case 0x30: - case 0x50: - { - bool is_ld = subop == 0x30; - if ( is_ld ) - { - ins.itype = NEC850_LDTC_SR; - set_opreg(ins.Op1, PARSE_R1); - set_opimm(ins.Op2, PARSE_R2); - } - else - { - ins.itype = NEC850_STTC_SR; - set_opimm(ins.Op1, PARSE_R1); - set_opreg(ins.Op2, PARSE_R2); - } - uint32 selid = ( w & 0xF8000000 ) >> 27; - set_opimm(ins.Op3, selid); - } - break; - - case 0x32: - case 0x52: - { - bool is_ld = subop == 0x32; - uint32 selid = ( w & 0xF8000000 ) >> 27; - switch ( selid ) - { - case 0: - ins.itype = is_ld ? NEC850_LDTC_GR: NEC850_STTC_GR; - set_opreg(ins.Op2, PARSE_R2); - set_opreg(ins.Op1, PARSE_R1); - break; - case 1: - ins.itype = is_ld ? NEC850_LDTC_VR : NEC850_STTC_VR; - set_opreg(ins.Op1, is_ld ? PARSE_R2 : PARSE_R1); - set_opreg(ins.Op2, is_ld ? PARSE_R1 : PARSE_R2); - break; - case 31: - ins.itype = is_ld ? NEC850_LDTC_PC : NEC850_STTC_PC; - set_opreg(ins.Op1, is_ld ? PARSE_R1 : PARSE_R2); - break; - default: - break; - } - } - break; - - case 0x34: - case 0x54: - { - bool is_ld = subop == 0x34; - if ( is_ld ) - { - ins.itype = NEC850_LDVC_SR; - set_opreg(ins.Op1, PARSE_R1); - set_opimm(ins.Op2, PARSE_R2); - } - else - { - ins.itype = NEC850_STVC_SR; - set_opimm(ins.Op1, PARSE_R1); - set_opreg(ins.Op2, PARSE_R2); - - } - uint32 selid = ( w & 0xF8000000 ) >> 27; - set_opimm(ins.Op3, selid); - } - break; - - case 0xC4: - case 0xC6: - { - // ROTL imm5, reg2, reg3 - // rrrrr111111iiiii wwwww00011000100 - // ROTL reg1, reg2, reg3 - // rrrrr111111RRRRR wwwww00011000110 - ins.itype = NEC850_ROTL; - uint32 r1 = PARSE_R1; - uint32 r2 = PARSE_R2; - uint32 r3 = (w & 0xF8000000 ) >> 27; - if ( subop == 0xC4 ) - { - set_opimm(ins.Op1, r1); - } - else - { - set_opreg(ins.Op1, r1); - } - set_opreg(ins.Op2, r2); - set_opreg(ins.Op3, r3); - } - break; - - case 0x110: - ins.itype = NEC850_HVTRAP; - set_opimm(ins.Op1, PARSE_R1, dt_byte); - break; - - case 0x132: - ins.itype = NEC850_EST; - break; - - case 0x134: - ins.itype = NEC850_DST; - break; - - case 0x378: - { - // LDL.W [reg1], reg3 - // 00000111111RRRRR wwwww01101111000 - ins.itype = NEC850_LDL_W; - uint32 r3 = ( w & 0xF8000000 ) >> 27; - set_opreg(ins.Op1, PARSE_R1); - ins.Op1.specflag1 = N850F_USEBRACKETS; - set_opreg(ins.Op2, r3); - break; - } - - case 0x37A: - { - // STC.W reg3, [reg1] - // 00000111111RRRRR wwwww01101111010 - ins.itype = NEC850_STC_W; - uint32 r3 = ( w & 0xF8000000 ) >> 27; - set_opreg(ins.Op1, r3); - set_opreg(ins.Op2, PARSE_R1); - ins.Op2.specflag1 = N850F_USEBRACKETS; - break; - } - case 0x160: - { - uint32 r1 = PARSE_R1; - uint32 r2 = PARSE_R2; - uint32 r3 = ( w & 0xF8000000 ) >> 27; - int w1 = w >> 16; - switch ( r2 ) - { - case 8: //pushsp - case 0xB: //dbpush - case 0xC: //popsp - { - // PUSHSP rh-rt - // 01000111111RRRRR wwwww00101100000 - // POPSP rh-rt - // 01100111111RRRRR wwwww00101100000 - // RRRRR indicates rh. wwwww indicates rt. - ins.itype = r2 == 8 ? NEC850_PUSHSP - : r2 == 0xB ? NEC850_DBPUSH - : NEC850_POPSP; - ins.Op1.type = o_regrange; - ins.Op1.regrange_high = r1; - ins.Op1.regrange_low = r3; - } - break; - - case 0x10: - switch ( w1 ) - { - case 0x8960: - ins.itype = NEC850_TLBAI; - break; - case 0x8160: - ins.itype = NEC850_TLBVI; - break; - case 0xC160: - ins.itype = NEC850_TLBS; - break; - case 0xE960: - ins.itype = NEC850_TLBR; - break; - case 0xE160: - ins.itype = NEC850_TLBW; - break; - } - break; - - case 0x18: - { - // JARL [reg1], reg3 - // 11000111111RRRRR WWWWW00101100000 - set_opreg(ins.Op1, r1); - ins.Op1.specflag1 = N850F_USEBRACKETS; - set_opreg(ins.Op2, r3); - ins.itype = NEC850_JARL; - } - break; - - case 0x19: - { - ins.itype = NEC850_DBTAG; - int v8 = (w & 0x1f) | ((w1 >> 6) & 0xe0); - set_opimm(ins.Op1, v8); - } - break; - - case 0x1A: - { - ins.itype = NEC850_HVCALL; - int v8 = (w & 0x1f) | ((w1 >> 6) & 0xe0); - set_opimm(ins.Op1, v8); - } - break; - - case 0x1B: - { - // PREF prefop, [reg1] - // 11011111111RRRRR PPPPP00101100000 - // PPPPP indicates prefop - ins.itype = NEC850_PREF; - set_opimm(ins.Op1, r3); - set_opreg(ins.Op2, r1); - } - break; - - case 0x1Cu: - case 0x1Du: - case 0x1Eu: - case 0x1Fu: - { - //CACHE cacheop, [reg1] - //111pp111111RRRRR PPPPP00101100000 - //ppPPPPP indicates cacheop - - int cacheop = ( ( r2 & 3 ) << 5 ) | r3; - if ( r1 == 0x1f && cacheop == 0x7E ) - { - ins.itype = NEC850_CLL; - } - else - { - ins.itype = NEC850_CACHE; - set_opimm(ins.Op1, cacheop); - set_opreg(ins.Op2, r1); - } - } - break; - } - } - break; - - default: - if ( w == 0x1200FE0 ) - ins.itype = NEC850_SNOOZE; - else if ( (w&0x10000) == 0 ) - { - uint o0 = ( w >> 20 ) & 0x7F; - if ( o0 == 9 || o0 == 11 || o0 == 13 ) - { - //BINS reg1, pos, width, reg2 - - //rrrrr111111RRRRR MMMMK 0001001 LLL0 msb >= 16, lsb >= 16 - //rrrrr111111RRRRR MMMMK 0001011 LLL0 msb >= 16, lsb < 16 - //rrrrr111111RRRRR MMMMK 0001101 LLL0 msb < 16, lsb < 16 - //Most significant bit of field to be updated : msb = pos + width - 1 - //Least significant bit of field to be updated : lsb = pos - //MMMM = lower 4 bits of msb, KLLL = lower 4 bits of lsb - uint16 whi = w >> 16; - uint lsb = ( whi >> 1 ) & 7; - lsb |= ( whi >> 8 ) & 8; - uint msb = ( whi >> 12 ) & 0xF; - if ( o0 == 9 || o0 == 11 ) - msb += 16; - if ( o0 == 9 ) - lsb += 16; - uint width = msb - lsb + 1; - - ins.itype = NEC850_BINS; - set_opreg(ins.Op1, PARSE_R1); - set_opimm(ins.Op2, lsb); - set_opimm(ins.Op3, width); - set_opreg(ins.Op4, PARSE_R2); - } - } - break; - - } - if ( ins.itype != 0 ) - break; - } - - if ( ins.itype != 0 ) - break; - } - if ( w == 0x14607E0 ) - { - ins.itype = NEC850_DBRET; - break; - } - else if ( w == 0x14407E0 ) - { - ins.itype = NEC850_CTRET; - break; - } - else if ( (w >> 16) & 0x1 ) - { - int r2 = PARSE_R2; - int r1 = PARSE_R1; - if ( r2 != 0 ) - { - // V850E: LD.HU disp16 [reg1], reg2 - // rrrrr111111RRRRR ddddddddddddddd1 - ins.itype = NEC850_LD_HU; - ins.Op1.type = o_displ; - displ_op = &ins.Op1; - ins.Op1.reg = r1; - ins.Op1.addr = uint32(( w >> 17 ) << 1); - ins.Op1.dtype = dt_word; - ins.Op1.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; - set_opreg(ins.Op2, r2); - } - else if ( is_rh850() ) - { - // RH850: Bcond disp17 - // 00000111111DCCCC ddddddddddddddd1 - sval_t dest = uint32(( w >> 17 ) << 1); - if ( (w & 0x10) != 0 ) - dest += 0x10000; // D - SIGN_EXTEND(sval_t, dest, 17); - ins.itype = bcond_map[w & 0xF]; - ins.Op1.dtype = dt_word; - ins.Op1.type = o_near; - ins.Op1.addr = ea_t(dest + ins.ip); - } - break; - } - // - // XI Group match (reg1, reg2, reg3) - // - uint32 r1 = PARSE_R1; - uint32 r2 = PARSE_R2; - uint32 r3 = ( w & 0xF8000000 ) >> 27; - - op = (w & 0x7FF0000) >> 16; - if ( op == 0x220 ) - ins.itype = NEC850_MUL; - else if ( op == 0x222 ) - ins.itype = NEC850_MULU; - else if ( op == 0x280 ) - ins.itype = NEC850_DIVH_r3; - else if ( op == 0x282 ) - ins.itype = NEC850_DIVHU; - else if ( op == 0x2C0 ) - ins.itype = NEC850_DIV; - else if ( op == 0x2C2 ) - ins.itype = NEC850_DIVU; - else if ( is_v850e2() ) - { - if ( ( op & 1 ) == 0 ) - { - if ( ( op >> 5 ) == 0x1D ) - { - // ADF - int cc = ( op >> 1 ) & 0xF; - if ( cc == CC_SAT ) - { - ins.itype = NEC850_SATADD; - } - else - { - ins.itype = NEC850_ADF; - set_opcond(ins.Op1, cc); - set_opreg(ins.Op2, r1); - set_opreg(ins.Op3, r2); - set_opreg(ins.Op4, r3); - break; - } - } - else if ( ( op >> 5 ) == 0x1C ) - { - // SBF - int cc = ( op >> 1 ) & 0xF; - if ( cc == CC_SAT ) - { - ins.itype = NEC850_SATSUB; - } - else - { - ins.itype = NEC850_SBF; - set_opcond(ins.Op1, cc); - set_opreg(ins.Op2, r1); - set_opreg(ins.Op3, r2); - set_opreg(ins.Op4, r3); - break; - } - } - else if ( ( op >> 6 ) == 0xF ) - { - //MAC rrrrr111111RRRRR wwww0011110mmmm0 - //MACU rrrrr111111RRRRR wwww0011111mmmm0 - ins.itype = ( op & 0x20 ) ? NEC850_MACU : NEC850_MAC; - int r4 = op&0x1F; - set_opreg(ins.Op1, r1); - set_opreg(ins.Op2, r2); - set_opreg(ins.Op3, r3); - set_opreg(ins.Op4, r4); - break; - } - } - switch ( op ) - { - case 0x82: - ins.itype = NEC850_SHR; - break; - case 0xa2: - ins.itype = NEC850_SAR; - break; - case 0xc2: - ins.itype = NEC850_SHL; - break; - case 0xEE: - ins.itype = NEC850_CAXI; - ins.Op1.specflag1 |= N850F_USEBRACKETS; - break; - case 0x2FE: - ins.itype = NEC850_DIVQU; - break; - case 0x2FC: - ins.itype = NEC850_DIVQ; - break; - } - } - // process the match - if ( ins.itype != 0 ) - { - set_opreg(ins.Op1, r1); - set_opreg(ins.Op2, r2); - set_opreg(ins.Op3, r3); - break; - } - - // - // XII/IX Group match (reg2, reg3) - // - if ( op == 0x340 ) - ins.itype = NEC850_BSW; - else if ( op == 0x342 ) - ins.itype = NEC850_BSH; - else if ( op == 0x344 ) - ins.itype = NEC850_HSW; - else if ( is_v850e2() ) - { - switch ( op ) - { - case 0x346: - ins.itype = NEC850_HSH; - break; - case 0x360: - ins.itype = NEC850_SCH0R; - break; - case 0x362: - ins.itype = NEC850_SCH1R; - break; - case 0x364: - ins.itype = NEC850_SCH0L; - break; - case 0x366: - ins.itype = NEC850_SCH1L; - break; - } - } - // process the match - if ( ins.itype != 0 ) - { - set_opreg(ins.Op1, r2); - set_opreg(ins.Op2, r3); - break; - } - - // - // match CMOV - // - op = w >> 16; - op = ((op & 0x7E0) >> 4) | (op & 0x1); - if ( op == 0x30 || op == 0x32 ) - { - uint32 cc = (w & 0x1E0000) >> 17; - ins.itype = NEC850_CMOV; - set_opcond(ins.Op1, cc); - - r1 = PARSE_R1; - r2 = PARSE_R2; - r3 = (w & 0xF8000000) >> 27; - - if ( op == 0x32 ) // CMOV cc, reg1, reg2, reg3 - { - set_opreg(ins.Op2, r1); - } - else - { - // CMOV cc, imm5, reg2, reg3 - sval_t v = r1; - SIGN_EXTEND(sval_t, v, 5); - set_opimm(ins.Op2, v, dt_byte); - ins.Op2.specflag1 |= N850F_OUTSIGNED; - } - set_opreg(ins.Op3, r2); - set_opreg(ins.Op4, r3); - break; - } - // - // match MUL[U]_i9 - // - op = w >> 16; - op = ((op & 0x7C0) >> 4) | (op & 0x3); - if ( op == 0x24 || op == 0x26 ) - { - sval_t imm = (((w & 0x3C0000) >> 18) << 5) | (w & 0x1F); - if ( op == 0x24 ) - { - ins.itype = NEC850_MUL; - SIGN_EXTEND(sval_t, imm, 9); - ins.Op1.specflag1 |= N850F_OUTSIGNED; - } - else - ins.itype = NEC850_MULU; - - set_opimm(ins.Op1, imm); - set_opreg(ins.Op2, PARSE_R2); - set_opreg(ins.Op3, (w & 0xF8000000) >> 27); - break; - } - } - - // - // Format IX - // - op = w >> 16; // take 2nd half-word as the opcode - uint32 reg1 = PARSE_R1; - uint32 reg2 = PARSE_R2; - // SETF - if ( op == 0 ) - { - if ( ( w & 0x10 ) == 0 ) - { - ins.itype = NEC850_SETF; - set_opcond(ins.Op1, w & 0xF); - set_opreg(ins.Op2, reg2); - } - else if ( is_v850e2m() ) - { - ins.itype = NEC850_RIE; - uint imm5 = ( w >> 11 ) & 0x1F; - uint imm4 = w & 0xF; - set_opimm(ins.Op1, imm5); - set_opimm(ins.Op2, imm4); - } - break; - } - - switch ( op ) - { - case 0x20: // LDSR - ins.itype = NEC850_LDSR; - ins.Op2.reg = rSR0; // designate system register - break; - case 0x40: // STSR - ins.itype = NEC850_STSR; - ins.Op1.reg = rSR0; // designate system register - break; - case 0x80: // SHR - ins.itype = NEC850_SHR; - break; - case 0xA0: // SAR - ins.itype = NEC850_SAR; - break; - case 0xC0: // SHL - ins.itype = NEC850_SHL; - break; - } - - if ( ins.itype != 0 ) - { - // Common stuff for the rest of Format 9 instructions - ins.Op1.dtype = ins.Op2.dtype = dt_dword; - ins.Op1.type = ins.Op2.type = o_reg; - ins.Op1.reg += reg1; - ins.Op2.reg += reg2; - break; - } - - // -> ins.itype == 0 - - - // No match? Try V850E - if ( is_v850e() ) - { - // SASF - if ( op == 0x200 ) - { - ins.itype = NEC850_SASF; - set_opcond(ins.Op1, w & 0xF); - set_opreg(ins.Op2, reg2); - break; - } - - switch ( op ) - { - case 0xE0: // NOT1 - ins.itype = NEC850_SET1; - break; - case 0xE2: // NOT1 - ins.itype = NEC850_NOT1; - break; - case 0xE4: // CLR1 - ins.itype = NEC850_CLR1; - break; - case 0xE6: // TST1 - ins.itype = NEC850_TST1; - break; - default: - return 0; // No match! - } - // Common - set_opreg(ins.Op1, reg2, dt_byte); - - ins.Op2.dtype = dt_byte; - displ_op = &ins.Op2; - ins.Op2.type = o_displ; - ins.Op2.addr = 0; - ins.Op2.reg = reg1; - ins.Op2.specflag1 = N850F_USEBRACKETS; - } - - if ( ins.itype == 0 ) - return 0; // unknown instruction - - break; - } - - // - // Format V - // - op = (w & 0x780) >> 6; // Take bit6->bit10 - // JARL and JR - if ( op == 0x1E ) - { - uint32 reg = PARSE_R2; - sval_t addr = uint32((((w & 0x3F) << 15) | ((w & 0xFFFE0000) >> 17)) << 1); - SIGN_EXTEND(sval_t, addr, 22); - - ins.Op1.addr = ins.ip + addr; - ins.Op1.type = o_near; - // per the docs, if reg is zero then JARL turns to JR - if ( reg == 0 ) - { - ins.itype = NEC850_JR; - } - else - { - ins.itype = NEC850_JARL; - set_opreg(ins.Op2, reg); - } - break; - } - - // - // Format III - // - op = (w & 0x780) >> 7; // Take bit7->bit10 - // assert: op in [0, 0xF] - // Bcond disp9 - if ( op == 0xB ) - { - sval_t dest = ( ((w & 0x70) >> 4) | ((w & 0xF800) >> 8) ) << 1; - SIGN_EXTEND(sval_t, dest, 9); - - ins.itype = bcond_map[w & 0xF]; - ins.Op1.dtype = dt_word; - ins.Op1.type = o_near; - ins.Op1.addr = ea_t(dest + ins.ip); - break; - } - // - // Format IV - // - else if ( op >= 6 ) - { - uint32 reg2 = PARSE_R2; - uint32 addr = (w & 0x7F); // zero extended - int idx_d(-1), idx_r(-1); - char dtyp_d(-1); - - // SLD.B - if ( op == 6 ) - { - ins.itype = NEC850_SLD_B; - idx_d = 0; - idx_r = 1; - dtyp_d = dt_byte; - } - // SLD.H - else if ( op == 8 ) - { - ins.itype = NEC850_SLD_H; - idx_d = 0; - idx_r = 1; - dtyp_d = dt_word; - addr <<= 1; - } - // SLD.W - else if ( op == 10 && ((w & 1) == 0) ) - { - ins.itype = NEC850_SLD_W; - idx_d = 0; - idx_r = 1; - dtyp_d = dt_dword; - addr <<= 1; - } - // SST.B - else if ( op == 7 ) - { - ins.itype = NEC850_SST_B; - idx_d = 1; - idx_r = 0; - dtyp_d = dt_byte; - } - // SST.H - else if ( op == 9 ) - { - ins.itype = NEC850_SST_H; - idx_d = 1; - idx_r = 0; - dtyp_d = dt_byte; - // bit0 is already cleared, so the 7bit addr we read - // can be shifted by one to transform it to 8bit - addr <<= 1; - } - // SST.W - else if ( op == 10 && ((w & 1) == 1) ) - { - ins.itype = NEC850_SST_W; - idx_d = 1; - idx_r = 0; - dtyp_d = dt_dword; - // clear lower bit because it is set, and shift by one - // bit 15 0 - // rrrrr1010dddddd1 - addr = (addr & ~1) << 1; - } - if ( idx_d == -1 || idx_r == -1 || dtyp_d == -1 ) - return false; // could not decode - - set_opreg(ins.ops[idx_r], reg2); - - ins.ops[idx_d].type = o_displ; - displ_op = &ins.ops[idx_d]; - ins.ops[idx_d].reg = rEP; - ins.ops[idx_d].addr = addr; - ins.ops[idx_d].dtype = dtyp_d; - ins.ops[idx_d].specflag1 = N850F_USEBRACKETS; - break; - } - // Unknown instructions - ins.itype = NEC850_NULL; - } while ( false ); - - // special cases when we have memory access through displacement - if ( displ_op != NULL ) - { - // A displacement with GP and GP is set? - if ( displ_op->reg == rGP && g_gp_ea != BADADDR ) - { - displ_op->type = o_mem; - if ( ins.itype == NEC850_SLD_BU || ins.itype == NEC850_LD_BU - || ins.itype == NEC850_SLD_HU || ins.itype == NEC850_LD_HU ) - { - displ_op->addr = short(displ_op->addr) + g_gp_ea; - } - else - { - displ_op->addr += g_gp_ea; - } - } - // register zero access? - else if ( displ_op->reg == rZERO ) - { - // since r0 is always 0, we can replace the operand by the complete address - displ_op->type = o_mem; - displ_op->specflag1 &= ~N850F_OUTSIGNED; - if ( ins.itype == NEC850_LD_BU || ins.itype == NEC850_LD_HU ) - displ_op->addr = short(displ_op->addr); - } -#ifdef __EA64__ - if ( displ_op->type == o_mem ) - { - //truncate address to 32 bits if needed - segment_t *s = getseg(displ_op->addr); - if ( s == NULL || !s->use64() ) - displ_op->addr = uint32(displ_op->addr); - } -#endif - } - return ins.itype != 0; -} - -//------------------------------------------------------------------------ -// Analyze one instruction and fill 'insn' structure. -// insn.ea contains address of instruction to analyze. -// Return length of the instruction in bytes, 0 if instruction can't be decoded. -// This function shouldn't change the database, flags or anything else. -// All these actions should be performed only by u_emu() function. -int nec850_t::nec850_ana(insn_t *pinsn) -{ - insn_t &insn = *pinsn; - if ( insn.ea & 0x1 ) - return 0; - - uint32 w; - fetch_instruction(&w, insn); - if ( decode_instruction(w, insn) ) - return insn.size; - else - return 0; -} diff --git a/idasdk75/module/nec850/emu.cpp b/idasdk75/module/nec850/emu.cpp deleted file mode 100644 index eae43b4..0000000 --- a/idasdk75/module/nec850/emu.cpp +++ /dev/null @@ -1,1297 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) Hex-Rays - * ALL RIGHTS RESERVED. - * - * Processor emulator - * - */ -#include <ida.hpp> -#include <auto.hpp> -#include <frame.hpp> -#include <jumptable.hpp> -#include "ins.hpp" -#include "necv850.hpp" - -//---------------------------------------------------------------------- -//#notify.is_sane_insn -// is the instruction sane for the current file type? -// arg: int no_crefs -// 1: the instruction has no code refs to it. -// ida just tries to convert unexplored bytes -// to an instruction (but there is no other -// reason to convert them into an instruction) -// 0: the instruction is created because -// of some coderef, user request or another -// weighty reason. -// The instruction is in 'cmd' -// returns: 1-ok, <=0-no, the instruction isn't likely to appear in the program -int nec850_t::nec850_is_sane_insn(const insn_t &insn, int /*no_crefs*/) const -{ -#define CHECK_R0_WRITE(n) \ - if ( ((Feature & CF_CHG ## n) != 0) \ - && insn.Op ## n.is_reg(rZERO) ) \ - { \ - return 0; \ - } - int Feature = insn.get_canon_feature(ph); - - CHECK_R0_WRITE(1); - CHECK_R0_WRITE(2); - return 1; -} - -//---------------------------------------------------------------------- -int idaapi nec850_is_sp_based(const insn_t &insn, const op_t &x) -{ - int res = OP_SP_ADD; - if ( x.type == o_displ && x.reg == rSP ) - return res | OP_SP_BASED; - - // check for movea 8, sp, r28 - if ( insn.itype == NEC850_MOVEA && insn.Op2.is_reg(rSP) && x.type == o_imm ) - return res | OP_SP_BASED; - - return res | OP_FP_BASED; -} - -//---------------------------------------------------------------------- -bool idaapi nec850_create_func_frame(func_t *pfn) -{ - asize_t frsize; - - insn_t insn; - if ( decode_insn(&insn, pfn->start_ea) != 0 - && (insn.itype == NEC850_PREPARE_i || insn.itype == NEC850_PREPARE_sp) ) - { - frsize = insn.Op2.value * 4; - } - else - { - frsize = 0; - } - return add_frame(pfn, frsize, 0, 0); -} - -//---------------------------------------------------------------------- -int idaapi nec850_get_frame_retsize(const func_t * /*pfn*/) -{ - return 0; -} - -//---------------------------------------------------------------------- -static bool spoils(const insn_t &insn, uint16 reg) -{ - int n; - switch ( insn.itype ) - { - case NEC850_ZXB: - case NEC850_SXB: - case NEC850_ZXH: - case NEC850_SXH: - n = 0; - break; - - case NEC850_XOR: - case NEC850_SUBR: - case NEC850_SUB: - case NEC850_STSR: - case NEC850_SLD_B: - case NEC850_SLD_H: - case NEC850_SLD_W: - case NEC850_SHR: - case NEC850_SHL: - case NEC850_SATSUBR: - case NEC850_SATSUB: - case NEC850_SATADD: - case NEC850_SAR: - case NEC850_OR: - case NEC850_NOT: - case NEC850_MULH: - case NEC850_MOV: - case NEC850_LD_B: - case NEC850_LD_H: - case NEC850_LD_W: - case NEC850_JARL: - case NEC850_AND: - case NEC850_ADD: - case NEC850_DIVH: - case NEC850_BSW: - case NEC850_BSH: - case NEC850_HSW: - case NEC850_SLD_BU: - case NEC850_SLD_HU: - case NEC850_LD_BU: - case NEC850_LD_HU: - n = 1; - break; - - case NEC850_XORI: - case NEC850_SATSUBI: - case NEC850_ORI: - case NEC850_MULHI: - case NEC850_MOVHI: - case NEC850_MOVEA: - case NEC850_ANDI: - case NEC850_ADDI: - case NEC850_SETF: - case NEC850_SASF: - n = 2; - break; - - case NEC850_CMOV: - n = 4; - break; - - case NEC850_MUL: - case NEC850_MULU: - case NEC850_DIVH_r3: - case NEC850_DIVHU: - case NEC850_DIV: - case NEC850_DIVU: - return insn.ops[1].is_reg(reg) || insn.ops[2].is_reg(reg); - - case NEC850_DISPOSE_r0: - case NEC850_DISPOSE_r: - return reg == rSP || reg_in_list12(reg, insn.Op2.value); - - case NEC850_PREPARE_sp: - return reg == rSP; - - case NEC850_PREPARE_i: - return reg == rSP || reg == rEP; - - default: - return false; - } - return insn.ops[n].is_reg(reg); -} - -//---------------------------------------------------------------------- -// does the instruction spoil the flags? -static bool spoils_flags(const insn_t &insn) -{ - switch ( insn.itype ) - { - case NEC850_ADD: - case NEC850_ADDI: - case NEC850_ADF: - case NEC850_AND: - case NEC850_ANDI: - case NEC850_BSH: - case NEC850_BSW: - case NEC850_CAXI: - case NEC850_CLR1: - case NEC850_CMP: - case NEC850_CTRET: - case NEC850_DIV: - case NEC850_DIVH: - case NEC850_DIVHU: - case NEC850_DIVH_r3: - case NEC850_DIVQ: - case NEC850_DIVQU: - case NEC850_DIVU: - case NEC850_EIRET: - case NEC850_FERET: - case NEC850_HSH: - case NEC850_HSW: - case NEC850_NOT: - case NEC850_NOT1: - case NEC850_OR: - case NEC850_ORI: - case NEC850_RETI: - case NEC850_SAR: - case NEC850_SATADD: - case NEC850_SATSUB: - case NEC850_SATSUBI: - case NEC850_SATSUBR: - case NEC850_SBF: - case NEC850_SCH0L: - case NEC850_SCH0R: - case NEC850_SCH1L: - case NEC850_SCH1R: - case NEC850_SET1: - case NEC850_SHL: - case NEC850_SHR: - case NEC850_SUB: - case NEC850_SUBR: - case NEC850_TST: - case NEC850_TST1: - case NEC850_XOR: - case NEC850_XORI: - - case NEC850_BINS: - case NEC850_ROTL: - return true; - - default: - // other insns don't spoil fixed point flags - return false; - } -} - -//---------------------------------------------------------------------- -bool nec850_t::get_gp_based_addr(ea_t *target, const insn_t &_insn, const op_t &op) const -{ - if ( g_gp_ea == BADADDR ) - return false; - if ( op.phrase == rGP ) - { - *target = g_gp_ea; - return true; - } - uint16 op_phrase = op.phrase; - *target = BADADDR; - insn_t tmp = _insn; - while ( true ) - { - flags_t F = get_flags(tmp.ea); - if ( !is_flow(F) || has_xref(F) ) - break; - if ( decode_prev_insn(&tmp, tmp.ea) == BADADDR ) - break; - - if ( tmp.itype == NEC850_MOVEA - && tmp.Op2.reg == rGP - && tmp.Op3.reg == op_phrase ) - { - *target = g_gp_ea + tmp.Op1.value; - break; - } - - if ( spoils(tmp, op_phrase) ) - break; - } - return *target != BADADDR; -} - -//---------------------------------------------------------------------- -void nec850_t::handle_operand(const insn_t &insn, const op_t &op, bool isRead) -{ - ea_t ea; - flags_t F = get_flags(insn.ea); - switch ( op.type ) - { - case o_imm: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, dr_O, 0); - break; - - case o_displ: - set_immd(insn.ea); - if ( !is_defarg(F, op.n) ) - { - if ( may_create_stkvars() && op.reg == rSP ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL && insn.create_stkvar(op, op.addr, STKVAR_VALID_SIZE) ) - op_stkvar(insn.ea, op.n); - } - else if ( get_gp_based_addr(&ea, insn, op) ) - { - refinfo_t ri; - ri.flags = REF_OFF32|REFINFO_PASTEND|REFINFO_NOBASE|REFINFO_SIGNEDOP; - ri.target = BADADDR; - ri.base = ea; - ri.tdelta = 0; - op_offset_ex(insn.ea, op.n, &ri); - F = get_flags(insn.ea); - } - } - - if ( op_adds_xrefs(F, op.n) ) - { // create data xrefs - ea_t base_ea; - if ( get_gp_based_addr(&base_ea, insn, op) ) - { - ea = base_ea + op.addr; - insn.add_dref(ea, op.offb, isRead ? dr_R : dr_W); - } - else - { - int outf = get_displ_outf(insn, op, F); - ea = insn.add_off_drefs(op, isRead ? dr_R : dr_W, outf); - } - if ( ea != BADADDR ) - insn.create_op_data(ea, op); - } - break; - - case o_near: - { - bool iscall = has_insn_feature(insn.itype, CF_CALL); - - ea_t dest = to_ea(insn.cs, op.addr); - if ( dest == insn.ea + insn.size ) - { - // PIC pattern: - // jarl nextaddr, r29 - // nextaddr: - iscall = false; - } - insn.add_cref(dest, op.offb, iscall ? fl_CN : fl_JN); - if ( flow && iscall ) - { - if ( !func_does_return(dest) ) - flow = false; - } - } - break; - - case o_mem: - { - ea = to_ea(insn.cs, op.addr); - insn.create_op_data(ea, op); - insn.add_dref(op.addr, op.offb, isRead ? dr_R : dr_W); - } - break; - } -} - -//---------------------------------------------------------------------- -static void idaapi trace_stack(func_t *pfn, const insn_t &insn) -{ - sval_t delta; - switch ( insn.itype ) - { - case NEC850_PREPARE_i: - case NEC850_PREPARE_sp: - { - delta = -((bitcount(insn.Op1.value) * 4) + (insn.Op2.value << 2)); - - // PATTERN #1 - /* - 00000030 _func3: - 00000030 000 br loc_5E - 00000032 - 00000032 loc_32: -- CODE XREF: _func3+32j - 00000032 000 st.w r6, 4[sp] - 0000005A - 0000005A loc_5A: -- CODE XREF: _func3+10j - 0000005A -- _func3+14j ... - 0000005A 000 dispose 2, {lp}, [lp] - 0000005E -- --------------------------------------------------------------------------- - 0000005E - 0000005E loc_5E: -- CODE XREF: _func3 - 0000005E -0C prepare {lp}, 2 - 00000062 000 br loc_32 - 00000062 -- End of function _func3 - */ - bool farref; - insn_t tmp; - if ( decode_preceding_insn(&tmp, insn.ea, &farref) != BADADDR - && (tmp.itype == NEC850_BR || tmp.itype == NEC850_JR) - && tmp.Op1.addr == insn.ea - && func_contains(pfn, tmp.ea) ) - { - add_auto_stkpnt(pfn, tmp.ea + tmp.size, delta); - } - } - break; - case NEC850_DISPOSE_r: - case NEC850_DISPOSE_r0: - // count registers in LIST12 and use the imm5 for local vars - delta = (bitcount(insn.Op2.value) * 4) + (insn.Op1.value << 2); - break; - case NEC850_ADD: - case NEC850_ADDI: - case NEC850_MOVEA: - delta = insn.Op1.value; - break; - default: - return; - } - add_auto_stkpnt(pfn, insn.ea + insn.size, delta); -} - -//---------------------------------------------------------------------- -// pattern: -// mov #address, lp -// jmp [reg1] -// address: -// flow to the next instruction -static bool indirect_function_call(const insn_t &_insn) -{ - if ( _insn.itype != NEC850_JMP || _insn.Op1.is_reg(rLP) ) - return false; - - insn_t insn = _insn; - ea_t ret_addr = insn.ea + insn.size; // after the jmp - - bool flows = false; - while ( decode_prev_insn(&insn, insn.ea) != BADADDR ) - { - if ( insn.itype == NEC850_MOV - && insn.Op1.type == o_imm - && insn.Op1.dtype == dt_dword - && insn.Op2.is_reg(rLP) ) - { // MOV #address, lp - op_offset(insn.ea, 0, REF_OFF32); - if ( insn.Op1.value == ret_addr ) - { // normal return, after the jmp instruction - flows = true; - } - else - { // add xref to return address - add_cref(_insn.ea, insn.Op1.value, fl_JN); - } - break; - } - - if ( spoils(insn, rLP) ) - break; - - flags_t F = get_flags(insn.ea); - if ( !is_flow(F) || has_xref(F) ) - break; - } - return flows; -} - -//---------------------------------------------------------------------- -int nec850_t::nec850_emu(const insn_t &insn) -{ - int aux = insn.auxpref; - - int Feature = insn.get_canon_feature(ph); - flow = (Feature & CF_STOP) == 0; - - if ( Feature & CF_USE1 ) - handle_operand(insn, insn.Op1, true); - if ( Feature & CF_CHG1 ) - handle_operand(insn, insn.Op1, false); - if ( Feature & CF_USE2 ) - handle_operand(insn, insn.Op2, true); - if ( Feature & CF_CHG2 ) - handle_operand(insn, insn.Op2, false); - if ( Feature & CF_USE3 ) - handle_operand(insn, insn.Op3, true); - if ( Feature & CF_CHG3 ) - handle_operand(insn, insn.Op3, false); - - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - flags_t F = get_flags(insn.ea); - if ( insn.itype == NEC850_MOVEA - && insn.Op1.type == o_imm - && !is_defarg(F, insn.Op1.n) ) - { - if ( insn.Op2.is_reg(rSP) - && may_create_stkvars() - && insn.create_stkvar(insn.Op1, insn.Op1.value, 0) ) - { - op_stkvar(insn.ea, insn.Op1.n); - } - else if ( insn.Op2.is_reg(rGP) - && g_gp_ea != BADADDR ) - { - ea_t ea = g_gp_ea + insn.Op1.value; - - refinfo_t ri; - ri.flags = REF_OFF32|REFINFO_PASTEND|REFINFO_SIGNEDOP|REFINFO_NOBASE; - ri.target = BADADDR; - ri.base = g_gp_ea; - ri.tdelta = 0; - op_offset_ex(insn.ea, insn.Op1.n, &ri); - F = get_flags(insn.ea); - if ( op_adds_xrefs(F, insn.Op1.n) ) - insn.add_dref(ea, insn.Op1.offb, dr_O); - } - } - - // add dref to callt table entry address - if ( insn.itype == NEC850_CALLT - && g_ctbp_ea != BADADDR ) - { - ea_t ea = g_ctbp_ea + (insn.Op1.value << 1); - insn.create_op_data(ea, insn.Op1.offb, dt_word); - insn.add_dref(ea, insn.Op1.offb, dr_R); - } - - if ( indirect_function_call(insn) ) - flow = true; - - if ( (aux & N850F_SP) && may_trace_sp() ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL ) - trace_stack(pfn, insn); - } - - // add flow - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - return 1; -} - -//---------------------------------------------------------------------- -int nec850_may_be_func(const insn_t &insn) -{ - int prop = 0; - if ( insn.itype == NEC850_PREPARE_i || insn.itype == NEC850_PREPARE_sp ) - prop = 100; - return prop; -} - -//---------------------------------------------------------------------- -inline bool is_ret_itype(const insn_t &insn) -{ - return insn.itype == NEC850_RETI - || insn.itype == NEC850_DBRET - || insn.itype == NEC850_CTRET - || insn.itype == NEC850_DISPOSE_r - || insn.itype == NEC850_JMP && insn.Op1.is_reg(rLP); -} - -//---------------------------------------------------------------------- -bool nec850_is_return(const insn_t &insn, bool strict) -{ - if ( is_ret_itype(insn) ) - return true; - if ( insn.itype == NEC850_DISPOSE_r0 ) - return !strict; - return false; -} - -//------------------------------------------------------------------------- -static bool find_set( - ea_t *value, - ea_t *valea, - insn_t insn, // make a copy - int reg) -{ - simple_bfi_t bfi(insn.ea); - while ( true ) - { - cref_t prev_insn_ref = bfi.prev_insn(); - if ( prev_insn_ref == fl_U || decode_insn(&insn, bfi.cur_ea) <= 0 ) - break; - switch ( insn.itype ) - { - case NEC850_MOV: - if ( insn.Op2.is_reg(reg) && insn.Op1.type == o_reg ) - { - reg = insn.Op1.reg; - continue; - } - if ( insn.Op2.is_reg(reg) && insn.Op1.type == o_imm ) - { - *value = insn.Op1.value; - *valea = insn.ea; - return true; - } - break; - case NEC850_ADDI: - case NEC850_MOVEA: - if ( insn.Op3.is_reg(reg) - && insn.Op1.type == o_imm - && insn.Op2.is_reg(rZERO) ) - { - *value = insn.Op1.value; - *valea = insn.ea; - return true; - } - break; - } - if ( spoils(insn, reg) ) - break; - } - return false; -} - -//------------------------------------------------------------------------- -struct nec850_jump_pattern_t : public jump_pattern_t -{ -protected: - enum { rA, rC }; - - nec850_jump_pattern_t(switch_info_t *_si, const char (*_depends)[4]) - : jump_pattern_t(_si, _depends, rC) - { - modifying_r32_spoils_r64 = false; - non_spoiled_reg = rA; - } - -public: - virtual bool handle_mov(tracked_regs_t &_regs) override; - virtual void check_spoiled(tracked_regs_t *_regs) const override; - -protected: - // movea -minv, rA', rA | add -minv, rA - bool jpi_sub_lowcase(); - // cmp followed by the conditional jump - // it calls jpi_condjump() and jpi_cmp_ncases() that can be redefined in - // the derived class. - bool jpi_cmp_ncases_condjump(); - // switch rA - bool jpi_jump(); - - // bh default - virtual bool jpi_condjump() newapi; - // cmp ncases, rA - virtual bool jpi_cmp_ncases() newapi; -}; - -//------------------------------------------------------------------------- -bool nec850_jump_pattern_t::handle_mov(tracked_regs_t &_regs) -{ - if ( insn.itype != NEC850_MOV - && insn.Op1.type != o_reg - && insn.Op2.type != o_reg ) - { - return false; - } - return set_moved(insn.Op2, insn.Op1, _regs); -} - -//------------------------------------------------------------------------- -#define PROC_MAXCHGOP 3 -void nec850_jump_pattern_t::check_spoiled(tracked_regs_t *__regs) const -{ - tracked_regs_t &_regs = *__regs; - for ( uint i = 0; i < _regs.size(); ++i ) - { - const op_t &x = _regs[i]; - if ( x.type == o_reg && spoils(insn, x.reg) - || x.type == o_condjump && spoils_flags(insn) ) - { - set_spoiled(&_regs, x); - } - } - check_spoiled_not_reg(&_regs, PROC_MAXCHGOP); -} - -//---------------------------------------------------------------------- -// movea -minv, rA', rA | add -minv, rA -bool nec850_jump_pattern_t::jpi_sub_lowcase() -{ - if ( insn.itype == NEC850_MOVEA ) - { - if ( insn.Op1.type != o_imm - || insn.Op2.type != o_reg - || !is_equal(insn.Op3, rA) ) - { - return false; - } - trackop(insn.Op2, rA); - } - else if ( insn.itype == NEC850_ADD ) - { - if ( insn.Op1.type != o_imm || !is_equal(insn.Op2, rA) ) - return false; - } - else - { - return false; - } - si->lowcase = uval_t(-uint32(insn.Op1.value)); - return true; -} - -//------------------------------------------------------------------------- -// cmp followed by the conditional jump -bool nec850_jump_pattern_t::jpi_cmp_ncases_condjump(void) -{ - // var should not be spoiled - QASSERT(10317, !is_spoiled(rA)); - - if ( jpi_condjump() // continue matching if found - || is_spoiled(rC) - || !jpi_cmp_ncases() ) - { - return false; - } - - op_t &op = regs[rC]; - // assert: op.type == o_condjump - if ( (op.value & cc_inc_ncases) != 0 ) - ++si->ncases; - si->defjump = op.specval; - si->set_expr(insn.Op1.reg, insn.Op1.dtype); - return true; -} - -//---------------------------------------------------------------------- -// switch rA -bool nec850_jump_pattern_t::jpi_jump() -{ - if ( insn.itype != NEC850_SWITCH - || insn.Op1.type != o_reg - || insn.Op1.reg == rZERO ) - { - return false; - } - - si->jumps = insn.ea + insn.size; - si->set_elbase(si->jumps); - si->flags |= SWI_SIGNED; - si->set_jtable_element_size(2); - si->set_shift(1); - si->set_expr(insn.Op1.reg, dt_dword); - trackop(insn.Op1, rA); - return true; -} - -//---------------------------------------------------------------------- -// bh default -bool nec850_jump_pattern_t::jpi_condjump() -{ - op_t op; - op.type = o_condjump; - op.value = 0; - switch ( insn.itype ) - { - case NEC850_BH: // higher - case NEC850_BNH: // not higher - op.value |= cc_inc_ncases; - break; - case NEC850_BL: // lower - case NEC850_BNC: // no carry (not lower) - break; - default: - return false; - } - ea_t jump = to_ea(insn.cs, insn.Op1.addr); - switch ( insn.itype ) - { - case NEC850_BH: - case NEC850_BNC: - op.specval = jump; - break; - case NEC850_BL: - case NEC850_BNH: - // we have conditional jump to the switch body - // assert: eas[0] != BADADDR - if ( jump > eas[0] ) - return false; - op.specval = insn.ea + insn.size; - - // possibly followed by 'jr default' - { - insn_t deflt; - if ( decode_insn(&deflt, op.specval) > 0 - && deflt.itype == NEC850_JR - && deflt.Op1.type == o_near ) - { - op.specval = deflt.Op1.addr; - } - } - break; - default: - return false; - } - op.addr = insn.ea; - trackop(op, rC); - return true; -} - -//---------------------------------------------------------------------- -// cmp ncases, rA -bool nec850_jump_pattern_t::jpi_cmp_ncases() -{ - if ( insn.itype != NEC850_CMP - || insn.Op1.type != o_imm && insn.Op1.type != o_reg - || !same_value(insn.Op2, rA) ) - { - return false; - } - - const op_t &x = insn.Op1; - uval_t val; - ea_t dummy; - if ( x.type == o_imm ) - val = x.value; - // assert: x.type == o_reg - else if ( !find_set(&val, &dummy, insn, x.reg) ) - return false; - si->ncases = ushort(val); - return true; -} - -//---------------------------------------------------------------------- -// jump pattern #1 -// 2 movea -minv, rA', rA | add -minv, rA (optional) -// 1 cmp ncases, rA | cmp rNcases, rA -// bh default (nearest to "cmp") -// 0 switch rA -// 0 -> 1 -> 2 - -static const char nec850_depends1[][4] = -{ - { 1 }, // 0 - { 2 | JPT_OPT | JPT_NEAR }, // 1 - { 0 }, // 2 optional, near -}; - -//------------------------------------------------------------------------- -class nec850_jump_pattern1_t : public nec850_jump_pattern_t -{ -public: - nec850_jump_pattern1_t(switch_info_t *_si) - : nec850_jump_pattern_t(_si, nec850_depends1) {} - - virtual bool jpi2(void) override { return jpi_sub_lowcase(); } - virtual bool jpi1(void) override { return jpi_cmp_ncases_condjump(); } - virtual bool jpi0(void) override { return jpi_jump(); } -}; - -//---------------------------------------------------------------------- -static int is_jump_pattern1(switch_info_t *si, const insn_t &insn, procmod_t *) -{ - nec850_jump_pattern1_t jp(si); - if ( !jp.match(insn) ) - return JT_NONE; - return JT_SWITCH; -} - -//---------------------------------------------------------------------- -// jump pattern #2 (addi instead of cmp) -// 2 movea -minv, rA', rA | add -minv, rA (optional) -// 1 addi -ncases, rA, r0 -// bl default (nearest to "cmp") -// 0 switch rA -// 0 -> 1 -> 2 - -static const char nec850_depends2[][4] = -{ - { 1 }, // 0 - { 2 | JPT_OPT | JPT_NEAR }, // 1 - { 0 }, // 2 optional, near -}; - -//------------------------------------------------------------------------- -class nec850_jump_pattern2_t : public nec850_jump_pattern_t -{ -public: - nec850_jump_pattern2_t(switch_info_t *_si) - : nec850_jump_pattern_t(_si, nec850_depends2) {} - - bool jpi2(void) override { return jpi_sub_lowcase(); } - bool jpi1(void) override { return jpi_cmp_ncases_condjump(); } - bool jpi0(void) override { return jpi_jump(); } - -protected: - // bl default - bool jpi_condjump() override; - // addi -ncases, rA, r0 - bool jpi_cmp_ncases() override; -}; - -//---------------------------------------------------------------------- -// bl default -bool nec850_jump_pattern2_t::jpi_condjump() -{ - op_t op; - op.type = o_condjump; - op.value = 0; - switch ( insn.itype ) - { - case NEC850_BH: // higher - op.value |= cc_inc_ncases; - break; - case NEC850_BL: // lower - break; - default: - return false; - } - ea_t jump = to_ea(insn.cs, insn.Op1.addr); - switch ( insn.itype ) - { - case NEC850_BL: - op.specval = jump; - break; - case NEC850_BH: - // we have conditional jump to the switch body - // assert: eas[0] != BADADDR - if ( jump > eas[0] ) - return false; - op.specval = insn.ea + insn.size; - break; - default: - return false; - } - op.addr = insn.ea; - trackop(op, rC); - return true; -} - -//---------------------------------------------------------------------- -// addi -ncases, rA, r0 -bool nec850_jump_pattern2_t::jpi_cmp_ncases() -{ - if ( insn.itype != NEC850_ADDI - || insn.Op1.type != o_imm - || !insn.Op3.is_reg(rZERO) - || !same_value(insn.Op2, rA) ) - { - return false; - } - - si->ncases = ushort(-uint32(insn.Op1.value)); - return true; -} - -//---------------------------------------------------------------------- -static int is_jump_pattern2(switch_info_t *si, const insn_t &insn, procmod_t *) -{ - nec850_jump_pattern2_t jp(si); - if ( !jp.match(insn) ) - return JT_NONE; - return JT_SWITCH; -} - -//---------------------------------------------------------------------- -// jump pattern #3 (without 'switch' insn) -// 3 movea -minv, rA', rA | add -minv, rA (optional) -// 2 cmp ncases, rA | cmp rNcases, rA -// bh default (nearest to "cmp") -// 1 shl 2, rA | shl 1, rA -// 0 jmp jumps[rA] -// -// jumps: jr case0 (4 bytes) | (2 bytes) -// jr case1 -// ... -// -// 0 -> 1 -> 2 -> 3 - -static const char nec850_depends3[][4] = -{ - { 1 }, // 0 - { 2 }, // 1 - { 3 | JPT_OPT | JPT_NEAR }, // 2 - { 0 }, // 3 optional, near -}; - -//------------------------------------------------------------------------- -class nec850_jump_pattern3_t : public nec850_jump_pattern_t -{ -public: - nec850_jump_pattern3_t(switch_info_t *_si) - : nec850_jump_pattern_t(_si, nec850_depends3) - { - si->flags |= SWI_JMPINSN; - } - - virtual bool jpi3(void) override { return jpi_sub_lowcase(); } - virtual bool jpi2(void) override { return jpi_cmp_ncases_condjump(); } - virtual bool jpi1(void) override; // shl shift, rA - virtual bool jpi0(void) override; // jmp jumps[rA] -}; - -//---------------------------------------------------------------------- -// shl shift, rA -bool nec850_jump_pattern3_t::jpi1() -{ - if ( insn.itype != NEC850_SHL - || insn.Op1.type != o_imm - || !same_value(insn.Op2, rA) ) - { - return false; - } - int elsize; - if ( insn.Op1.value == 1 ) - elsize = 2; - else if ( insn.Op1.value == 2 ) - elsize = 4; - else - return false; - si->set_jtable_element_size(elsize); - return true; -} - -//---------------------------------------------------------------------- -// jmp jumps[rA] -bool nec850_jump_pattern3_t::jpi0() -{ - if ( insn.itype != NEC850_JMP || insn.Op1.type != o_displ ) - return false; - si->jumps = insn.Op1.addr; - track(insn.Op1.phrase, rA, dt_dword); - return true; -} - -//---------------------------------------------------------------------- -static int is_jump_pattern3(switch_info_t *si, const insn_t &insn, procmod_t *) -{ - nec850_jump_pattern3_t jp(si); - if ( !jp.match(insn) ) - return JT_NONE; - op_offset(jp.eas[0], 0, REFINFO_NOBASE | REF_OFF32); - // rollback data created in handle_operand() - del_items(si->jumps, DELIT_SIMPLE); - return JT_SWITCH; -} - -//---------------------------------------------------------------------- -bool idaapi nec850_is_switch(switch_info_t *si, const insn_t &insn) -{ - if ( insn.itype != NEC850_SWITCH && insn.itype != NEC850_JMP ) - return false; - - static is_pattern_t *const patterns[] = - { - is_jump_pattern1, - is_jump_pattern2, - is_jump_pattern3, - }; - return check_for_table_jump(si, insn, patterns, qnumber(patterns)); -} - -//------------------------------------------------------------------------- -sval_t nec850_t::regval( - const op_t &op, - getreg_t *getreg, - const regval_t *rv) const -{ - if ( op.reg > rSR31 ) - { - warning("Bad register number passed to nec850.get_register_value: %d", op.reg); - return 0; - } - return sval_t(getreg(ph.reg_names[op.reg], rv).ival); -} - -//------------------------------------------------------------------------- -static bool is_bcond(int itype) -{ - return itype == NEC850_BV - || itype == NEC850_BL - || itype == NEC850_BZ - || itype == NEC850_BNH - || itype == NEC850_BN - || itype == NEC850_BR - || itype == NEC850_BLT - || itype == NEC850_BLE - || itype == NEC850_BNV - || itype == NEC850_BNC - || itype == NEC850_BNZ - || itype == NEC850_BH - || itype == NEC850_BP - || itype == NEC850_BSA - || itype == NEC850_BGE - || itype == NEC850_BGT; -} - -//------------------------------------------------------------------------- -ea_t nec850_t::nec850_next_exec_insn( - ea_t ea, - getreg_t *getreg, - const regval_t *regvalues) const -{ - insn_t insn; - if ( decode_insn(&insn, ea) < 1 ) - return BADADDR; - - // First check for Bcond. - if ( is_bcond(insn.itype) ) - { - uint32_t PSW = getreg("PSW", regvalues).ival; - bool Z = (PSW & (1 << 0)) != 0; - bool S = (PSW & (1 << 1)) != 0; - bool OV = (PSW & (1 << 2)) != 0; - bool CY = (PSW & (1 << 3)) != 0; - bool SAT = (PSW & (1 << 4)) != 0; - bool condition = false; - switch ( insn.itype ) - { - case NEC850_BV: condition = OV; break; - case NEC850_BL: condition = CY; break; - case NEC850_BZ: condition = Z; break; - case NEC850_BNH: condition = (CY || Z); break; - case NEC850_BN: condition = S; break; - case NEC850_BR: condition = true; break; - case NEC850_BLT: condition = (S != OV); break; - case NEC850_BLE: condition = ((S != OV) || Z); break; - case NEC850_BNV: condition = !OV; break; - case NEC850_BNC: condition = !CY; break; - case NEC850_BNZ: condition = !Z; break; - case NEC850_BH: condition = !(CY || Z); break; - case NEC850_BP: condition = !S; break; - case NEC850_BSA: condition = SAT; break; - case NEC850_BGE: condition = !(S != OV); break; - case NEC850_BGT: condition = !((S != OV) || Z); break; - } - ea_t target = condition ? insn.Op1.addr : BADADDR; - return target; - } - - // Then check for other instructions. - ea_t target = BADADDR; - switch ( insn.itype ) - { - case NEC850_RETI: - { - uint32_t PSW = getreg("PSW", regvalues).ival; - if ( (PSW & (1 << 6)) != 0 ) // PSW.EP - { - target = getreg("EIPC", regvalues).ival; - } - else - { - if ( (PSW & (1 << 7)) != 0 ) // PSW.NP - target = getreg("FEPC", regvalues).ival; - else - target = getreg("EIPC", regvalues).ival; - } - } - break; - - case NEC850_JR: - target = insn.Op1.addr; - break; - - case NEC850_JMP: - target = regval(insn.Op1, getreg, regvalues) + insn.Op1.addr; - break; - - case NEC850_JARL: - if ( insn.Op1.type == o_reg ) - target = regval(insn.Op1, getreg, regvalues); - else - target = insn.Op1.addr; - break; - - case NEC850_SWITCH: - // TODO - break; - - case NEC850_DISPOSE_r: - target = regval(insn.Op3, getreg, regvalues); - break; - - case NEC850_CALLT: - target = insn.Op1.addr; - break; - - case NEC850_CTRET: - target = getreg("CTPC", regvalues).ival; - break; - - case NEC850_EIRET: - target = getreg("EIPC", regvalues).ival; - break; - - case NEC850_FERET: - target = getreg("FEPC", regvalues).ival; - break; - - case NEC850_LOOP: - if ( regval(insn.Op1, getreg, regvalues) - 1 != 0 ) - target = insn.Op2.addr; - break; - - case NEC850_DBHVTRAP: - case NEC850_DBRET: - case NEC850_DBTRAP: - case NEC850_FETRAP: - case NEC850_HALT: - case NEC850_HVCALL: - case NEC850_HVTRAP: - case NEC850_RIE: - case NEC850_RMTRAP: - case NEC850_SYSCALL: - case NEC850_TRAP: - // TODO - break; - } - - return target; -} - -//------------------------------------------------------------------------- -ea_t nec850_t::nec850_calc_step_over(ea_t ip) const -{ - insn_t insn; - if ( ip == BADADDR || decode_insn(&insn, ip) < 1 ) - return BADADDR; - - bool step_over = is_call_insn(insn) - || insn.itype == NEC850_LOOP; - if ( step_over ) - return insn.ea + insn.size; - - return BADADDR; -} - -//------------------------------------------------------------------------- -bool nec850_t::nec850_get_operand_info( - idd_opinfo_t *opinf, - ea_t ea, - int n, - getreg_t *getreg, - const regval_t *regvalues) -{ - if ( n < 0 || n > 4 ) // check the operand number - return false; - insn_t insn; - if ( decode_insn(&insn, ea) < 1 ) - return false; - - // TODO check for op.type == o_cond? - opinf->modified = has_cf_chg(insn.get_canon_feature(ph), n); - - uint64 v = 0; - const op_t &op = insn.ops[n]; - switch ( op.type ) - { - case o_imm: - v = op.value; - break; - - case o_mem: - case o_near: - opinf->ea = op.addr; - break; - - case o_reg: - v = regval(op, getreg, regvalues); - break; - - case o_displ: - // TODO - break; - - case o_reglist: - case o_regrange: - // TODO how to represent multiple registers? - break; - - default: - return false; - } - opinf->value._set_int(v); - opinf->value_size = get_dtype_size(op.dtype); - return true; -} - -//-------------------------------------------------------------------------- -int nec850_t::nec850_get_reg_index(const char *name) const -{ - if ( name == NULL || name[0] == '\0' ) - return -1; - for ( size_t i = 0; i < ph.regs_num; i++ ) - if ( stricmp(ph.reg_names[i], name) == 0 ) - return i; - return -1; -} - -//-------------------------------------------------------------------------- -bool nec850_t::nec850_get_reg_info( - const char **main_regname, - bitrange_t *bitrange, - const char *regname) -{ - int regnum = nec850_get_reg_index(regname); - if ( regnum == -1 ) - return false; - - if ( bitrange != NULL ) - *bitrange = bitrange_t(0, 32); - - if ( main_regname != NULL ) - *main_regname = ph.reg_names[regnum]; - - return true; -} diff --git a/idasdk75/module/nec850/ins.cpp b/idasdk75/module/nec850/ins.cpp deleted file mode 100644 index e39b8bf..0000000 --- a/idasdk75/module/nec850/ins.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* -* Interactive disassembler (IDA). -* Copyright (c) 1990-2020 Hex-Rays -* ALL RIGHTS RESERVED. -* -*/ - -#include "ins.hpp" - -const instruc_t Instructions[NEC850_LAST_INSTRUCTION] = -{ - { "", 0 }, // Unknown Operation - - { "breakpoint", CF_STOP }, // undefined instruction - { "xori", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive Or Immediate - { "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Exclusive OR - { "tst1", CF_USE1|CF_USE2 }, // Test bit - { "tst", CF_USE1|CF_USE2 }, // Test - { "trap", CF_USE1 }, // Software trap - { "subr", CF_USE1|CF_USE2|CF_CHG2 }, // Substract reverse - { "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Substract - { "stsr", CF_USE1|CF_CHG2 }, // Store Contents of System Register - { "st.b", CF_USE1|CF_USE2|CF_CHG2 }, // Store byte - { "st.h", CF_USE1|CF_USE2|CF_CHG2 }, // Store half-word - { "st.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store word - { "sst.b", CF_USE1|CF_USE2|CF_CHG2 }, // Store byte (use EP) - { "sst.h", CF_USE1|CF_USE2|CF_CHG2 }, // Store half-word (use EP) - { "sst.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store word (use EP) - { "sld.b", CF_USE1|CF_CHG2 }, // Load byte (use EP) - { "sld.h", CF_USE1|CF_CHG2 }, // Load half-word (use EP) - { "sld.w", CF_USE1|CF_CHG2 }, // Load word (use EP) - { "shr", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Logical Right - { "shl", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Logical Left - { "set1", CF_USE1|CF_USE2|CF_CHG2 }, // Set Bit - { "setf", CF_USE1|CF_CHG2 }, // Set register to 1 if condition is satisfied - { "satsubr", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Subtract Reverse - { "satsubi", CF_USE1|CF_USE2|CF_CHG3 }, // Saturated Subtract Immediate - { "satsub", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Subtract - { "satadd", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Add - { "sar", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Arithmetic Right - { "reti", CF_STOP }, // Return from Trap or Interrupt - { "ori", CF_USE1|CF_USE2|CF_CHG2 }, // OR immediate - { "or", CF_USE1|CF_USE2|CF_CHG2 }, // OR - { "not1", CF_USE1|CF_USE2|CF_CHG2 }, // Not Bit - { "not", CF_USE1|CF_USE2|CF_CHG2 }, // Not - { "nop", 0 }, // No Operation - { "mulhi", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Half-Word Immediate - { "mulh", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply Half-Word - { "movhi", CF_USE1|CF_USE2|CF_CHG3 }, // Move High Half-Word - { "movea", CF_USE1|CF_USE2|CF_CHG3 }, // Move Effective Address - { "mov", CF_USE1|CF_CHG2 }, // Move - { "ldsr", CF_USE1|CF_CHG2 }, // Load to system register - { "ld.b", CF_USE1|CF_CHG2 }, // Load byte - { "ld.h", CF_USE1|CF_CHG2 }, // Load half-word - { "ld.w", CF_USE1|CF_CHG2 }, // Load word - { "jr", CF_USE1|CF_STOP }, // Jump Relative - { "jmp", CF_USE1|CF_JUMP|CF_STOP }, // Jump Register - { "jarl", CF_CALL|CF_USE1|CF_CHG2 }, // Jump and Register Link - { "halt", CF_STOP }, // Halt - { "ei", 0 }, // Enable interrupt - { "divh", CF_USE1|CF_USE2|CF_CHG2 }, // Divide Half-Word - { "di", 0 }, // Disable Interrupt - { "cmp", CF_USE1|CF_USE2 }, // Compare - { "clr1", CF_USE1|CF_USE2|CF_CHG2 }, // Clear bit - { "bv", CF_USE1 }, // Branch if overflow - { "bl", CF_USE1 }, // Branch if less - { "bz", CF_USE1 }, // Branch if zero - { "bnh", CF_USE1 }, // Branch if not higher - { "bn", CF_USE1 }, // Branch if negative - { "br", CF_USE1|CF_STOP }, // Branch if always - { "blt", CF_USE1 }, // Branch if less than (signed) - { "ble", CF_USE1 }, // Branch if less than or equal (signed) - { "bnv", CF_USE1 }, // Branch if no overflow - { "bnc", CF_USE1 }, // Branch if no carry - { "bnz", CF_USE1 }, // Branch if not zero - { "bh", CF_USE1 }, // Branch if higher than - { "bp", CF_USE1 }, // Branch if positive - { "bsa", CF_USE1 }, // Branch if saturated - { "bge", CF_USE1 }, // Branch if greater than or equal (signed) - { "bgt", CF_USE1 }, // Branch if greater than (signed) - { "andi", CF_USE1|CF_USE2|CF_CHG3 }, // And immediate - { "and", CF_USE1|CF_USE2|CF_CHG2 }, // And - { "addi", CF_USE1|CF_USE2|CF_CHG3 }, // Add Immediate - { "add", CF_USE1|CF_USE2|CF_CHG2 }, // Add - - // - // V850E/E1/ES - // - { "switch", CF_USE1|CF_STOP|CF_JUMP }, // Jump with table look up - { "zxb", CF_USE1|CF_CHG1 }, // - { "sxb", CF_USE1|CF_CHG1 }, // - { "zxh", CF_USE1|CF_CHG1 }, // - { "sxh", CF_USE1|CF_CHG1 }, // - { "dispose", CF_USE1|CF_USE2 }, // - { "dispose", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, // - { "callt", CF_USE1|CF_CALL }, // - { "dbtrap", CF_STOP }, // - { "dbret", CF_STOP }, // - { "ctret", CF_STOP }, // - - { "sasf", CF_USE1|CF_USE2|CF_CHG2 }, // Shift and set flag condition - - { "prepare", CF_USE1|CF_USE2|CF_USE3 }, // Function prepare - { "prepare", CF_USE1|CF_USE2 }, // Function prepare - - { "mul", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Multiply word - { "mulu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Multiply word unsigned - - { "divh", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide halfword - { "divhu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide halfword unsigned - { "div", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word - { "divu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word unsigned - - { "bsw", CF_USE1|CF_CHG2 }, // Byte swap word - { "bsh", CF_USE1|CF_CHG2 }, // Byte swap halfword - { "hsw", CF_USE1|CF_CHG2 }, // Halfword swap word - - { "cmov", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Conditional move - - { "sld.bu", CF_USE1|CF_CHG2 }, // Short format load byte unsigned - { "sld.hu", CF_USE1|CF_CHG2 }, // Short format load halfword unsigned - - { "ld.bu", CF_USE1|CF_CHG2 }, // load byte unsigned - { "ld.hu", CF_USE1|CF_CHG2 }, // load halfword unsigned - - // - // V850E2 - // - { "adf", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Add on condition flag - { "hsh", CF_USE1|CF_CHG2 }, // Halfword swap halfword - { "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Multiply and add word - { "macu", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Multiply and add word unsigned - - { "sbf", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Subtract on condition flag - - { "sch0l", CF_USE1|CF_CHG2 }, // Search zero from left - { "sch0r", CF_USE1|CF_CHG2 }, // Search zero from right - { "sch1l", CF_USE1|CF_CHG2 }, // Search one from left - { "sch1r", CF_USE1|CF_CHG2 }, // Search one from right - - // - // V850E2M - // - { "caxi", CF_USE1|CF_USE2|CF_USE3 }, // Compare and exchange for interlock - { "divq", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word quickly - { "divqu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word unsigned quickly - { "eiret", CF_STOP }, // Return from EI level exception - { "feret", CF_STOP }, // Return from FE level exception - { "fetrap", CF_USE1 }, // FE-level Trap - { "rmtrap", 0 }, // Runtime monitor trap - { "rie", CF_STOP|CF_USE1|CF_USE2 }, // Reserved instruction exception - { "synce", 0 }, // Synchronize exceptions - { "syncm", 0 }, // Synchronize memory - { "syncp", 0 }, // Synchronize pipeline - { "syscall", CF_USE1 }, // System call - - // floating point (E1F only) - { "cvt.sw", CF_USE1|CF_CHG2 }, // Real to integer conversion - { "trnc.sw", CF_USE1|CF_CHG2 }, // Real to integer conversion - { "cvt.ws", CF_USE1|CF_CHG2 }, // Integer to real conversion - { "ldfc", CF_USE1|CF_CHG2 }, // Load to Floating Controls - { "ldff", CF_USE1|CF_CHG2 }, // Load to Floating Flags - { "stfc", CF_USE1|CF_CHG2 }, // Store Floating Controls - { "stff", CF_USE1|CF_CHG2 }, // Store Floating Flags - { "trff", 0 }, // Transfer Floating Flags - - // floating point (E2M+) - { "absf.d", CF_USE1|CF_CHG2 }, // Floating-point Absolute Value (Double) - { "absf.s", CF_USE1|CF_CHG2 }, // Floating-point Absolute Value (Single) - { "addf.d", CF_USE1|CF_CHG2 }, // Floating-point Add (Double) - { "addf.s", CF_USE1|CF_CHG2 }, // Floating-point Add (Single) - { "divf.d", CF_USE1|CF_CHG2 }, // Floating-point Divide (Double) - { "divf.s", CF_USE1|CF_CHG2 }, // Floating-point Divide (Single) - { "maxf.d", CF_USE1|CF_CHG2 }, // Floating-point Maximum (Double) - { "maxf.s", CF_USE1|CF_CHG2 }, // Floating-point Maximum (Single) - { "minf.d", CF_USE1|CF_CHG2 }, // Floating-point Minimum (Double) - { "minf.s", CF_USE1|CF_CHG2 }, // Floating-point Minimum (Single) - { "mulf.d", CF_USE1|CF_CHG2 }, // Floating-point Multiply (Double) - { "mulf.s", CF_USE1|CF_CHG2 }, // Floating-point Multiply (Single) - { "negf.d", CF_USE1|CF_CHG2 }, // Floating-point Negate (Double) - { "negf.s", CF_USE1|CF_CHG2 }, // Floating-point Negate (Single) - { "recipf.d", CF_USE1|CF_CHG2 }, // Reciprocal of a floating-point value (Double) - { "recipf.s", CF_USE1|CF_CHG2 }, // Reciprocal of a floating-point value (Single - - { "rsqrtf.d", CF_USE1|CF_CHG2 }, // Reciprocal of the square root of a floating-point value (Double) - { "rsqrtf.s", CF_USE1|CF_CHG2 }, // Reciprocal of the square root of a floating-point value (Single) - { "sqrtf.d", CF_USE1|CF_CHG2 }, // Floating-point Square Root (Double) - { "sqrtf.s", CF_USE1|CF_CHG2 }, // Floating-point Square Root (Single) - { "subf.d", CF_USE1|CF_CHG2 }, // Floating-point Subtract (Double) - { "subf.s", CF_USE1|CF_CHG2 }, // Floating-point Subtract (Single) - { "maddf.s", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Floating-point Multiply-Add (Single) - { "msubf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Multiply-Subtract (Single) - { "nmaddf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Negate Multiply-Add (Single) - { "nmsubf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Negate Multiply-Subtract (Single) - - { "ceilf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double) - { "ceilf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double) - { "ceilf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single) - { "ceilf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single) - { "ceilf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double) - { "ceilf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double) - { "ceilf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single) - { "ceilf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single) - { "cvtf.dl", CF_USE1|CF_CHG2 }, // Floating-point Convert to Long Fixed-point Format (Double) - { "cvtf.ds", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double) - { "cvtf.dul", CF_USE1|CF_CHG2 }, // Floating-point Convert Double to Unsigned-Long (Double) - { "cvtf.duw", CF_USE1|CF_CHG2 }, // Floating-point Convert Double to Unsigned-Word (Double) - { "cvtf.dw", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Fixed-point Format (Double) - { "cvtf.ld", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double) - { "cvtf.ls", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Single) - { "cvtf.sd", CF_USE1|CF_CHG2 }, // Floating-point Convert to Double Floating-point Format (Double) - { "cvtf.sl", CF_USE1|CF_CHG2 }, // Floating-point Convert to Long Fixed-point Format (Single) - { "cvtf.sul", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Unsigned-Long (Single) - { "cvtf.suw", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Unsigned-Word (Single) - { "cvtf.sw", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Fixed-point Format (Single) - { "cvtf.uld", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Long to Double (Double) - { "cvtf.uls", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Long to Single (Single) - { "cvtf.uwd", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Word to Double (Double) - { "cvtf.uws", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Word to Single (Single) - { "cvtf.wd", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double) - { "cvtf.ws", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Single) - { "floorf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double) - { "floorf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double) - { "floorf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single) - { "floorf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single) - { "floorf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double) - { "floorf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double) - { "floorf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single) - { "floorf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single) - { "trncf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double) - { "trncf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate Double to Unsigned-Long (Double) - { "trncf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate Double to Unsigned-Word (Double) - { "trncf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double) - { "trncf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single) - { "trncf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate Single to Unsigned-Long (Single) - { "trncf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate Single to Unsigned-Word (Single) - { "trncf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single) - { "cmpf.s", CF_USE1|CF_CHG2 }, // Compares floating-point values (Single) - { "cmpf.d", CF_USE1|CF_CHG2 }, // Compares floating-point values (Double) - { "cmovf.s", CF_USE1|CF_CHG2 }, // Floating-point conditional move (Single) - { "cmovf.d", CF_USE1|CF_CHG2 }, // Floating-point conditional move (Double) - { "trfsr", CF_USE1|CF_CHG2 }, // Transfers specified CC bit to Zero flag in PSW (Single) - - // - // RH850 - // - { "synci", 0 }, // Synchronize instruction pipeline - { "snooze", 0 }, // Snooze - { "bins", CF_USE1|CF_USE2|CF_USE3|CF_USE4|CF_CHG4 }, // Bitfield Insert - { "rotl", CF_USE1|CF_USE2|CF_CHG3 }, // Rotate Left - { "loop", CF_USE1|CF_USE2 }, // Loop - { "ld.dw", CF_USE1|CF_CHG2 }, // Load Double Word - { "st.dw", CF_USE1|CF_USE2|CF_CHG2 }, // Store Double Word - { "ldl.w", CF_USE1|CF_CHG2 }, // Load Linked - { "stc.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store Conditional - { "cll", 0 }, // Clear Load Link - { "cache", CF_USE1|CF_USE2 }, // Cache operation - { "pref", CF_USE1|CF_USE2 }, // Prefetch - { "pushsp", CF_USE1 }, // Push registers to Stack - { "popsp", CF_CHG1 }, // Pop registers from Stack - - // new RH850 FP instructions - { "cvtf.hs", CF_USE1|CF_CHG2 }, // Floating-point Convert Half to Single (Single) - { "cvtf.sh", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Half (Single) - { "fmaf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Multiply-add (Single) - { "fmsf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Multiply-subtract (Single) - { "fnmaf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Negate-Multiply-add (Single) - { "fnmsf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Negate-Multiply-subtract (Single) - - // debug instructions - { "dbpush", CF_USE1 }, // Output registers as software trace data - { "dbcp", 0 }, // Output current PC value as software trace data - { "dbtag", CF_USE1 }, // Output immediate value as software trace data - { "dbhvtrap", 0 }, // Debug hypervisor trap - - { "est", 0 }, // - { "dst", 0 }, // - { "hvtrap", CF_USE1 }, // Hypervisor trap - { "hvcall", CF_USE1 }, // Hypervisor call - { "ldvc.sr", CF_USE1|CF_USE2 }, // - { "stvc.sr", CF_USE1|CF_USE2 }, // - { "ldtc.gr", CF_USE1|CF_USE2 }, // - { "sttc.gr", CF_USE1|CF_USE2 }, // - { "ldtc.pc", CF_USE1|CF_USE2 }, // - { "sttc.pc", CF_USE1|CF_USE2 }, // - { "ldtc.sr", CF_USE1|CF_USE2 }, // - { "sttc.sr", CF_USE1|CF_USE2 }, // - { "ldtc.vr", CF_USE1|CF_USE2 }, // - { "sttc.vr", CF_USE1|CF_USE2 }, // - - // TLB instructions - { "tlbai", 0 }, // - { "tlbr", 0 }, // - { "tlbs", 0 }, // - { "tlbvi", 0 }, // - { "tlbw", 0 }, // -}; - -CASSERT(qnumber(Instructions) == NEC850_LAST_INSTRUCTION); diff --git a/idasdk75/module/nec850/ins.hpp b/idasdk75/module/nec850/ins.hpp deleted file mode 100644 index b16babb..0000000 --- a/idasdk75/module/nec850/ins.hpp +++ /dev/null @@ -1,310 +0,0 @@ -/* -* Interactive disassembler (IDA). -* Copyright (c) 1990-2020 Hex-Rays -* ALL RIGHTS RESERVED. -* -*/ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -#include "necv850.hpp" - -//---------------------------------------------------------------------- - -extern const instruc_t Instructions[]; - -enum NEC850_Instructions -{ - NEC850_NULL = 0, - - NEC850_BREAKPOINT, - NEC850_XORI, - NEC850_XOR, - NEC850_TST1, - NEC850_TST, - NEC850_TRAP, - NEC850_SUBR, - NEC850_SUB, - NEC850_STSR, - NEC850_ST_B, - NEC850_ST_H, - NEC850_ST_W, - NEC850_SST_B, - NEC850_SST_H, - NEC850_SST_W, - NEC850_SLD_B, - NEC850_SLD_H, - NEC850_SLD_W, - NEC850_SHR, - NEC850_SHL, - NEC850_SET1, - NEC850_SETF, - NEC850_SATSUBR, - NEC850_SATSUBI, - NEC850_SATSUB, - NEC850_SATADD, - NEC850_SAR, - NEC850_RETI, - NEC850_ORI, - NEC850_OR, - NEC850_NOT1, - NEC850_NOT, - NEC850_NOP, - NEC850_MULHI, - NEC850_MULH, - NEC850_MOVHI, - NEC850_MOVEA, - NEC850_MOV, - NEC850_LDSR, - NEC850_LD_B, - NEC850_LD_H, - NEC850_LD_W, - NEC850_JR, - NEC850_JMP, - NEC850_JARL, - NEC850_HALT, - NEC850_EI, - NEC850_DIVH, - NEC850_DI, - NEC850_CMP, - NEC850_CLR1, - NEC850_BV, - NEC850_BL, - NEC850_BZ, - NEC850_BNH, - NEC850_BN, - NEC850_BR, - NEC850_BLT, - NEC850_BLE, - NEC850_BNV, - NEC850_BNC, - NEC850_BNZ, - NEC850_BH, - NEC850_BP, - NEC850_BSA, - NEC850_BGE, - NEC850_BGT, - NEC850_ANDI, - NEC850_AND, - NEC850_ADDI, - NEC850_ADD, - - // - // V850E/E1/ES - // - NEC850_SWITCH, - NEC850_ZXB, - NEC850_SXB, - NEC850_ZXH, - NEC850_SXH, - NEC850_DISPOSE_r0, - NEC850_DISPOSE_r, - NEC850_CALLT, - NEC850_DBTRAP, - NEC850_DBRET, - NEC850_CTRET, - - NEC850_SASF, - - NEC850_PREPARE_sp, - NEC850_PREPARE_i, - - NEC850_MUL, - NEC850_MULU, - - NEC850_DIVH_r3, - NEC850_DIVHU, - NEC850_DIV, - NEC850_DIVU, - - NEC850_BSW, - NEC850_BSH, - NEC850_HSW, - - NEC850_CMOV, - - NEC850_SLD_BU, - NEC850_SLD_HU, - NEC850_LD_BU, - NEC850_LD_HU, - - // - // V850E2 - // - NEC850_ADF, // Add on condition flag - - NEC850_HSH, // Halfword swap halfword - NEC850_MAC, // Multiply and add word - NEC850_MACU, // Multiply and add word unsigned - - NEC850_SBF, // Subtract on condition flag - - NEC850_SCH0L, // Search zero from left - NEC850_SCH0R, // Search zero from right - NEC850_SCH1L, // Search one from left - NEC850_SCH1R, // Search one from right - - // - // V850E2M - // - NEC850_CAXI, // Compare and exchange for interlock - NEC850_DIVQ, // Divide word quickly - NEC850_DIVQU, // Divide word unsigned quickly - NEC850_EIRET, // Return from EI level exception - NEC850_FERET, // Return from FE level exception - NEC850_FETRAP, // FE-level Trap - NEC850_RMTRAP, // Runtime monitor trap - NEC850_RIE, // Reserved instruction exception - NEC850_SYNCE, // Synchronize exceptions - NEC850_SYNCM, // Synchronize memory - NEC850_SYNCP, // Synchronize pipeline - NEC850_SYSCALL, // System call - - // floating point (E1F only) - NEC850_CVT_SW, // Real to integer conversion - NEC850_TRNC_SW, // Real to integer conversion - NEC850_CVT_WS, // Integer to real conversion - NEC850_LDFC, // Load to Floating Controls - NEC850_LDFF, // Load to Floating Flags - NEC850_STFC, // Store Floating Controls - NEC850_STFF, // Store Floating Flags - NEC850_TRFF, // Transfer Floating Flags - - // floating point (E2M) - - NEC850_ABSF_D, // Floating-point Absolute Value (Double) - NEC850_ABSF_S, // Floating-point Absolute Value (Single) - NEC850_ADDF_D, // Floating-point Add (Double) - NEC850_ADDF_S, // Floating-point Add (Single) - NEC850_DIVF_D, // Floating-point Divide (Double) - NEC850_DIVF_S, // Floating-point Divide (Single) - NEC850_MAXF_D, // Floating-point Maximum (Double) - NEC850_MAXF_S, // Floating-point Maximum (Single) - NEC850_MINF_D, // Floating-point Minimum (Double) - NEC850_MINF_S, // Floating-point Minimum (Single) - NEC850_MULF_D, // Floating-point Multiply (Double) - NEC850_MULF_S, // Floating-point Multiply (Single) - NEC850_NEGF_D, // Floating-point Negate (Double) - NEC850_NEGF_S, // Floating-point Negate (Single) - NEC850_RECIPF_D, // Reciprocal of a floating-point value (Double) - NEC850_RECIPF_S, // Reciprocal of a floating-point value (Single - - NEC850_RSQRTF_D, // Reciprocal of the square root of a floating-point value (Double) - NEC850_RSQRTF_S, // Reciprocal of the square root of a floating-point value (Single) - NEC850_SQRTF_D, // Floating-point Square Root (Double) - NEC850_SQRTF_S, // Floating-point Square Root (Single) - NEC850_SUBF_D, // Floating-point Subtract (Double) - NEC850_SUBF_S, // Floating-point Subtract (Single) - NEC850_MADDF_S, // Floating-point Multiply-Add (Single) - NEC850_MSUBF_S, // Floating-point Multiply-Subtract (Single) - NEC850_NMADDF_S, // Floating-point Negate Multiply-Add (Single) - NEC850_NMSUBF_S, // Floating-point Negate Multiply-Subtract (Single) - - NEC850_CEILF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double) - NEC850_CEILF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double) - NEC850_CEILF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single) - NEC850_CEILF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single) - NEC850_CEILF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double) - NEC850_CEILF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double) - NEC850_CEILF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single) - NEC850_CEILF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single) - NEC850_CVTF_DL, // Floating-point Convert to Long Fixed-point Format (Double) - NEC850_CVTF_DS, // Floating-point Convert to Single Floating-point Format (Double) - NEC850_CVTF_DUL, // Floating-point Convert Double to Unsigned-Long (Double) - NEC850_CVTF_DUW, // Floating-point Convert Double to Unsigned-Word (Double) - NEC850_CVTF_DW, // Floating-point Convert to Single Fixed-point Format (Double) - NEC850_CVTF_LD, // Floating-point Convert to Single Floating-point Format (Double) - NEC850_CVTF_LS, // Floating-point Convert to Single Floating-point Format (Single) - NEC850_CVTF_SD, // Floating-point Convert to Double Floating-point Format (Double) - NEC850_CVTF_SL, // Floating-point Convert to Long Fixed-point Format (Single) - NEC850_CVTF_SUL, // Floating-point Convert Single to Unsigned-Long (Single) - NEC850_CVTF_SUW, // Floating-point Convert Single to Unsigned-Word (Single) - NEC850_CVTF_SW, // Floating-point Convert to Single Fixed-point Format (Single) - NEC850_CVTF_ULD, // Floating-point Convert Unsigned-Long to Double (Double) - NEC850_CVTF_ULS, // Floating-point Convert Unsigned-Long to Single (Single) - NEC850_CVTF_UWD, // Floating-point Convert Unsigned-Word to Double (Double) - NEC850_CVTF_UWS, // Floating-point Convert Unsigned-Word to Single (Single) - NEC850_CVTF_WD, // Floating-point Convert to Single Floating-point Format (Double) - NEC850_CVTF_WS, // Floating-point Convert to Single Floating-point Format (Single) - NEC850_FLOORF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double) - NEC850_FLOORF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double) - NEC850_FLOORF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single) - NEC850_FLOORF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single) - NEC850_FLOORF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double) - NEC850_FLOORF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double) - NEC850_FLOORF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single) - NEC850_FLOORF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single) - NEC850_TRNCF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double) - NEC850_TRNCF_DUL, // Floating-point Truncate Double to Unsigned-Long (Double) - NEC850_TRNCF_DUW, // Floating-point Truncate Double to Unsigned-Word (Double) - NEC850_TRNCF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double) - NEC850_TRNCF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single) - NEC850_TRNCF_SUL, // Floating-point Truncate Single to Unsigned-Long (Single) - NEC850_TRNCF_SUW, // Floating-point Truncate Single to Unsigned-Word (Single) - NEC850_TRNCF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single) - NEC850_CMPF_S, // Compares floating-point values (Single) - NEC850_CMPF_D, // Compares floating-point values (Double) - NEC850_CMOVF_S, // Floating-point conditional move (Single) - NEC850_CMOVF_D, // Floating-point conditional move (Double) - NEC850_TRFSR, // Transfers specified CC bit to Zero flag in PSW (Single) - - // - // RH850 - // - NEC850_SYNCI, // Synchronize instruction pipeline - NEC850_SNOOZE, // Snooze - NEC850_BINS, // Bitfield Insert - NEC850_ROTL, // Rotate Left - NEC850_LOOP, // Loop - NEC850_LD_DW, // Load Double Word - NEC850_ST_DW, // Store Double Word - NEC850_LDL_W, // Load Linked - NEC850_STC_W, // Store Conditional - NEC850_CLL, // Clear Load Link - NEC850_CACHE, // Cache operation - NEC850_PREF, // Prefetch - NEC850_PUSHSP, // Push registers to Stack - NEC850_POPSP, // Pop registers from Stack - - // new RH850 FP instructions - NEC850_CVTF_HS, // Floating-point Convert Half to Single (Single) - NEC850_CVTF_SH, // Floating-point Convert Single to Half (Single) - NEC850_FMAF_S, // Floating-point Fused-Multiply-add (Single) - NEC850_FMSF_S, // Floating-point Fused-Multiply-subtract (Single) - NEC850_FNMAF_S, // Floating-point Fused-Negate-Multiply-add (Single) - NEC850_FNMSF_S, // Floating-point Fused-Negate-Multiply-subtract (Single) - - // debug instructions - NEC850_DBPUSH, // - NEC850_DBCP, // - NEC850_DBTAG, // - NEC850_DBHVTRAP, // - - // virtualization instructions - NEC850_EST, // - NEC850_DST, // - NEC850_HVTRAP, // - NEC850_HVCALL, // - NEC850_LDVC_SR, // - NEC850_STVC_SR, // - NEC850_LDTC_GR, // - NEC850_STTC_GR, // - NEC850_LDTC_PC, // - NEC850_STTC_PC, // - NEC850_LDTC_SR, // - NEC850_STTC_SR, // - NEC850_LDTC_VR, // - NEC850_STTC_VR, // - - // TLB instructions - NEC850_TLBAI, // - NEC850_TLBR, // - NEC850_TLBS, // - NEC850_TLBVI, // - NEC850_TLBW, // - - NEC850_LAST_INSTRUCTION -}; - -#endif diff --git a/idasdk75/module/nec850/makefile b/idasdk75/module/nec850/makefile deleted file mode 100644 index b5ba92d..0000000 --- a/idasdk75/module/nec850/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=nec850 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ - necv850.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ - $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)jumptable.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \ - necv850.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ - necv850.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp \ - necv850.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp necv850.hpp reg.cpp diff --git a/idasdk75/module/nec850/necv850.hpp b/idasdk75/module/nec850/necv850.hpp deleted file mode 100644 index 944169d..0000000 --- a/idasdk75/module/nec850/necv850.hpp +++ /dev/null @@ -1,202 +0,0 @@ -#ifndef __NECV850_INC__ -#define __NECV850_INC__ - -#include "../idaidp.hpp" -#include <list> -#include <pro.h> -#include <fpro.h> -#include <idd.hpp> -#include <ida.hpp> -#include <algorithm> -#include <name.hpp> -#include <idp.hpp> -#include <ieee.h> - - - #ifndef SIGN_EXTEND - #define SIGN_EXTEND(type, var, nbits) \ - if ( var & (1 << (nbits-1)) ) \ - var |= ~type((1 << nbits)-1) - #endif - - -//---------------------------------------------------------------------- -// Specific flags - -// -// Used in op_t.specflag1 -#define N850F_USEBRACKETS 0x01 // some instructions use [reg] syntax even when there is no actual memory dereference -#define N850F_OUTSIGNED 0x02 // output as signed value -#define N850F_VAL32 0x04 // value/addr is wider than 16-bit - -#define o_reglist o_idpspec1 // Register list (for DISPOSE) - // bitmask of registers is in 'value' field -// -// Used in insn.auxpref -#define N850F_SP 0x00000001 // instruction modifies the stack pointer -#define N850F_FP 0x00000010 // instruction works with floating-point data - -#define o_cond o_idpspec2 // Condition code as operand (for CMOV/CMPF) - // condition stored in 'value' field - -#define o_regrange o_idpspec3 // Register range (rh-rl, for PUSHSP/POPSP) -#define regrange_high specval_shorts.high //high register (rh) -#define regrange_low specval_shorts.low //low register (rl) - -//---------------------------------------------------------------------- -// Registers def -enum NEC850_Registers -{ - rZERO, - rR1, rR2, rSP /* r3 */, rGP /* r4 */, - rR5, rR6, rR7, rR8, - rR9, rR10, rR11, rR12, - rR13, rR14, rR15, rR16, - rR17, rR18, rR19, rR20, - rR21, rR22, rR23, rR24, - rR25, rR26, rR27, rR28, - rR29, rEP, rR31, - rLP = rR31, - - // system registers start here - rSR0, - rEIP=rSR0, rEIPSW, rFEPC, rFEPSW, - rECR, rPSW, rSR6, rSR7, - rSR8, rSR9, rSR10, rSR11, - rSR12, rSR13, rSR14, rSR15, - rSR16, rSR17, rSR18, rSR19, - rSR20, rSR21, rSR22, rSR23, - rSR24, rSR25, rSR26, rSR27, - rSR28, rSR29, rSR30, rSR31, - - //E1F FPU registers - EFG, ECT, - - // segment registers - rVep, // virtual element pointer segment register - rVcs, rVds, - - rLastRegister -}; - -enum NEC850_CCode //for CMOV -{ - CC_V, //0000: Overflow (OV=1) - CC_CL, //0001: Carry (CY=1) - CC_Z, //0010: Zero (Z=1) - CC_NH, //0011: Not higher (Less than or equal) ((CY or Z) = 1) - CC_SN, //0100: Negative) S=1 - CC_T, //0101: Always (true) - CC_LT, //0110: Less than signed (S xor OV) = 1 - CC_LE, //0111: Less than or equal signed (((S xor OV) or Z) = 1) - CC_NV, //1000: no overflow (OV=0) - CC_NCNL,//1001: no carry (CY=0) - CC_NZ, //1010: not zero (Z=0) - CC_H, //0011: Higher (Greater than) ((CY or Z) = 0) - CC_NSP, //0100: Positive (S=0) - CC_SAT, //1101: Saturated (SAT=1) - CC_GE, //1110: Greater than or equal signed (S xor OV) = 0 - CC_GT, //1111: Greater than signed (((S xor OV) or Z) = 0) -}; - -enum proctype_t -{ - V850, // including V850 - V850E, // - V850ES, // including V850E1 - V850E2M,// including V850E2 - RH850, // -}; -//---------------------------------------------------------------------- -// Prototypes - -// prototypes -- out.cpp -void idaapi nec850_header(outctx_t &ctx); -void idaapi nec850_segstart(outctx_t &ctx, segment_t *seg); -void idaapi nec850_segend(outctx_t &ctx, segment_t *seg); - -bool reg_in_list12(uint16 reg, uint32 L); - -// prototypes -- ana.cpp -int detect_inst_len(uint16 w); -int fetch_instruction(uint32 *w); - -// prototypes -- emu.cpp -bool idaapi nec850_is_switch(switch_info_t *si, const insn_t &insn); -bool idaapi nec850_create_func_frame(func_t *pfn); -int idaapi nec850_get_frame_retsize(const func_t *pfn); -int idaapi nec850_is_sp_based(const insn_t &insn, const op_t &x); -int nec850_may_be_func(const insn_t &insn); -bool nec850_is_return(const insn_t &insn, bool strict); -int get_imm_outf(const insn_t &insn, const op_t &x); -int get_displ_outf(const insn_t &insn, const op_t &x, flags_t F); - -extern const char *const RegNames[]; - -typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); - -//------------------------------------------------------------------ -DECLARE_PROC_LISTENER(idb_listener_t, struct nec850_t); - -struct nec850_t : public procmod_t -{ - idb_listener_t idb_listener = idb_listener_t(*this); - // program pointers (gp, tp) - netnode prog_pointers; - ea_t g_gp_ea = BADADDR; // global pointer - ea_t g_ctbp_ea = BADADDR; // CALLT base pointer - int ptype = 0; - bool flow = false; - - bool inline idaapi is_v850e() const { return ptype >= (int)V850E; } - bool inline idaapi is_v850es() const { return ptype >= (int)V850ES; } - bool inline idaapi is_v850e1() const { return is_v850es(); } - bool inline idaapi is_v850e1f() const { return is_v850e1(); } - bool inline idaapi is_v850e2m() const { return ptype >= (int)V850E2M; } - bool inline idaapi is_v850e2() const { return is_v850e2m(); } - bool inline idaapi is_rh850() const { return ptype >= (int)RH850; } - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void save_settings(); - void load_settings(); - const char *idaapi set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - - bool decode_instruction(const uint32 w, insn_t &ins); - bool decode_coprocessor(const uint32 w, insn_t &ins) const; - int nec850_ana(insn_t *pinsn); - - bool get_gp_based_addr(ea_t *target, const insn_t &_insn, const op_t &op) const; - void handle_operand(const insn_t &insn, const op_t &op, bool isRead); - int nec850_emu(const insn_t &insn); - int nec850_is_sane_insn(const insn_t &insn, int no_crefs) const; - sval_t regval( - const op_t &op, - getreg_t *getreg, - const regval_t *rv) const; - - // debugger functions - ea_t nec850_next_exec_insn( - ea_t ea, - getreg_t *getreg, - const regval_t *regvalues) const; - ea_t nec850_calc_step_over(ea_t ip) const; - bool nec850_get_operand_info( - idd_opinfo_t *opinf, - ea_t ea, - int n, - getreg_t *getreg, - const regval_t *regvalues); - bool nec850_get_reg_info( - const char **main_regname, - bitrange_t *bitrange, - const char *regname); - int nec850_get_reg_index(const char *name) const; // static - - void nec850_footer(outctx_t &ctx) const; -}; -#endif diff --git a/idasdk75/module/nec850/out.cpp b/idasdk75/module/nec850/out.cpp deleted file mode 100644 index 8d023c9..0000000 --- a/idasdk75/module/nec850/out.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) Hex-Rays - * ALL RIGHTS RESERVED. - * - * Output - * - */ -#include "necv850.hpp" -#include "ins.hpp" - -//-------------------------------------------------------------------------- -// LIST12 table mapping to corresponding registers -static const int list12_table[] = -{ - rR31, // 0 - rR29, // 1 - rR28, // 2 - rR23, // 3 - rR22, // 4 - rR21, // 5 - rR20, // 6 - rR27, // 7 - rR26, // 8 - rR25, // 9 - rR24, // 10 - rEP // 11 -}; - -// Using the indexes in this table as indexes in list12_table[] -// we can test for bits in List12 in order -static const int list12order_table[] = -{ - 6, // 0 r20 - 5, // 1 r21 - 4, // 2 r22 - 3, // 3 r23 - 10, // 4 r24 - 9, // 5 r25 - 8, // 6 r26 - 7, // 7 r27 - 2, // 8 r28 - 1, // 9 r29 - 11, // 10 r30 - 0, // 11 r31 -}; - -//---------------------------------------------------------------------- -int get_displ_outf(const insn_t &insn, const op_t &x, flags_t F) -{ - qnotused(insn); - qnotused(F); - - int outf = OOF_ADDR; - outf |= ( x.specflag1 & N850F_VAL32 ) ? OOFW_32 : OOFW_16; - if ( ( x.specflag1 & N850F_OUTSIGNED ) != 0 ) - outf |= OOFS_IFSIGN | OOF_SIGNED; - - return outf; -} - -//---------------------------------------------------------------------- -class out_nec850_t : public outctx_t -{ - out_nec850_t(void) = delete; // not used -public: - void OutReg(const op_t &r); - void out_reg_list(uint32 L); - void out_reg_range(const op_t &op); - bool out_operand(const op_t &x); - void out_insn(void); - void out_cond(const op_t &r); - void out_fcond(const op_t &r); -}; -CASSERT(sizeof(out_nec850_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_nec850_t) - -//-------------------------------------------------------------------------- -bool reg_in_list12(uint16 reg, uint32 L) -{ - if ( rR20 <= reg && reg <= rR31 ) - { - uint32 idx = list12order_table[reg - rR20]; //lint !e676 possibly indexing before the beginning of an allocation - return (L & (1 << idx)) != 0; - } - return false; -} - -//-------------------------------------------------------------------------- -void out_nec850_t::out_reg_list(uint32 L) -{ - int last = qnumber(list12_table); - int in_order = 0, c = 0; - const char *last_rn = NULL; - - out_symbol('{'); - for ( int i=0; i < qnumber(list12order_table); i++ ) - { - uint32 idx = list12order_table[i]; - if ( (L & (1 << idx)) == 0 ) - continue; - c++; - const char *rn = RegNames[list12_table[idx]]; - if ( last + 1 == i ) - in_order++; - else - { - if ( in_order > 1 ) - { - out_symbol('-'); - out_register(last_rn); - out_line(", ", COLOR_SYMBOL); - } - else if ( c > 1 ) - { - out_line(", ", COLOR_SYMBOL); - } - out_register(rn); - in_order = 1; - } - last_rn = rn; - last = i; - } - if ( in_order > 1 ) - { - out_symbol('-'); - out_register(last_rn); - } - out_symbol('}'); -} - - -//-------------------------------------------------------------------------- -void out_nec850_t::out_reg_range(const op_t &op) -{ - out_register(RegNames[op.regrange_high]); - out_symbol('-'); - out_register(RegNames[op.regrange_low]); -} -//-------------------------------------------------------------------------- -void idaapi nec850_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_PROC_AND_ASM); -} - -//-------------------------------------------------------------------------- -void nec850_t::nec850_footer(outctx_t &ctx) const -{ - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - ctx.flush_outbuf(DEFAULT_INDENT); - ctx.gen_cmt_line("-------------- end of module --------------"); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, s) could be made const -void idaapi nec850_segstart(outctx_t &ctx, segment_t *s) -{ - qstring sname; - qstring sclass; - - get_visible_segm_name(&sname, s); - get_segm_class(&sclass, s); - - const char *p_class; - if ( (s->perm == (SEGPERM_READ|SEGPERM_WRITE)) && s->type == SEG_BSS ) - p_class = "bss"; - else if ( s->perm == SEGPERM_READ ) - p_class = "const"; - else if ( s->perm == (SEGPERM_READ|SEGPERM_WRITE) ) - p_class = "data"; - else if ( s->perm == (SEGPERM_READ|SEGPERM_EXEC) ) - p_class = "text"; - else if ( s->type == SEG_XTRN ) - p_class = "symtab"; - else - p_class = sclass.c_str(); - - ctx.gen_printf(0, COLSTR(".section \"%s\", %s", SCOLOR_ASMDIR), sname.c_str(), p_class); -} - -//-------------------------------------------------------------------------- -void idaapi nec850_segend(outctx_t &, segment_t *) -{ -} - -//---------------------------------------------------------------------- -void out_nec850_t::OutReg(const op_t &r) -{ - bool brackets = r.specflag1 & N850F_USEBRACKETS; - if ( brackets ) - out_symbol('['); - out_register(ph.reg_names[r.reg]); - if ( brackets ) - out_symbol(']'); -} - -static const char *cond_tbl[16] = -{ - "v", //0000: Overflow (OV=1) - "c/l", //0001: Carry (CY=1) - "z", //0010: Zero (Z=1) - "nh", //0011: Not higher (Less than or equal) ((CY or Z) = 1) - "s/n", //0100: Negative) S=1 - "t", //0101: Always (true) - "lt", //0110: Less than signed (S xor OV) = 1 - "le", //0111: Less than or equal signed (((S xor OV) or Z) = 1) - "nv", //1000: no overflow (OV=0) - "nc/nl",//1001: no carry (CY=0) - "nz", //1010: not zero (Z=0) - "h", //0011: Higher (Greater than) ((CY or Z) = 0) - "ns/p", //0100: Positive (S=0) - "sat", //1101: Saturated (SAT=1) - "ge", //1110: Greater than or equal signed (S xor OV) = 0 - "gt", //1111: Greater than signed (((S xor OV) or Z) = 0) -}; - -static const char *fcond_tbl[16] = -{ - "f/t", - "un/or", - "eq/neq", - "ueq/ogl", - "olt/uge", - "ult/oge", - "ole/ugt", - "ule/ogt", - "sf/st", - "ngle/gle", - "seq/sne", - "ngl/gl", - "lt/nlt", - "nge/ge", - "le/nle", - "ngt/gt" -}; - -//---------------------------------------------------------------------- -void out_nec850_t::out_cond(const op_t &r) -{ - int cc = r.value; - QASSERT(10327, r.type == o_cond && cc < qnumber(cond_tbl)); - out_keyword(cond_tbl[cc]); -} - -//---------------------------------------------------------------------- -void out_nec850_t::out_fcond(const op_t &r) -{ - int cc = r.value; - QASSERT(10323, r.type == o_cond && cc < qnumber(fcond_tbl)); - out_keyword(fcond_tbl[cc]); -} - -//---------------------------------------------------------------------- -void out_nec850_t::out_insn(void) -{ - out_mnemonic(); - - out_one_operand(0); - - for ( int i=1; i < UA_MAXOP; i++ ) - { - if ( insn.ops[i].type == o_void ) - break; - out_symbol(','); - out_char(' '); - out_one_operand(i); - } - flush_outbuf(); -} - -//---------------------------------------------------------------------- -// Generate text representation of an instructon operand. -// This function shouldn't change the database, flags or anything else. -// All these actions should be performed only by u_emu() function. -// The output text is placed in the output buffer initialized with init_output_buffer() -// This function uses out_...() functions from ua.hpp to generate the operand text -// Returns: 1-ok, 0-operand is hidden. -bool out_nec850_t::out_operand(const op_t &x) -{ - switch ( x.type ) - { - case o_void: - return false; - case o_reglist: - out_reg_list(x.value); - break; - case o_regrange: - out_reg_range(x); - break; - case o_reg: - OutReg(x); - break; - case o_imm: - out_value(x, OOFW_IMM | ((x.specflag1 & N850F_OUTSIGNED) ? OOF_SIGNED : 0)); - break; - case o_near: - case o_mem: - if ( !out_name_expr(x, x.addr, BADADDR) ) - { - out_tagon(COLOR_ERROR); - out_value(x, OOF_ADDR | OOFW_IMM | OOFW_32); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - break; - case o_displ: - if ( x.addr != 0 || x.reg == rSP ) - out_value(x, get_displ_outf(insn, x, F)); - OutReg(x); - if ( x.reg != rGP && x.reg != rSP && x.addr == 0 ) - { // add name comment - xrefblk_t xb; - for ( bool ok=xb.first_from(insn.ea, XREF_DATA); ok; ok=xb.next_from() ) - { - if ( has_cmt(F) ) - continue; - if ( xb.type != dr_R && xb.type != dr_W ) - continue; - - qstring qbuf; - if ( get_name_expr(&qbuf, insn.ea, x.n, xb.to, BADADDR) > 0 ) - set_cmt(insn.ea, qbuf.begin(), false); - } - } - break; - case o_cond: - if ( insn.auxpref & N850F_FP ) - out_fcond(x); - else - out_cond(x); - break; - default: - return false; - } - return true; -} diff --git a/idasdk75/module/nec850/reg.cpp b/idasdk75/module/nec850/reg.cpp deleted file mode 100644 index f05a065..0000000 --- a/idasdk75/module/nec850/reg.cpp +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) Hex-Rays - * ALL RIGHTS RESERVED. - * - * Processor description structures - * - */ -#include "necv850.hpp" -#include "ins.hpp" -#include <loader.hpp> -#include <segregs.hpp> - -#define GP_EA_IDX 1 -#define CTBP_EA_IDX 2 - -//------------------------------------------------------------------ -void nec850_t::save_settings() -{ - prog_pointers.altset(GP_EA_IDX, ea2node(g_gp_ea)); - prog_pointers.altset(CTBP_EA_IDX, ea2node(g_ctbp_ea)); -} - -//------------------------------------------------------------------ -void nec850_t::load_settings() -{ - g_gp_ea = node2ea(prog_pointers.altval(GP_EA_IDX)); - g_ctbp_ea = node2ea(prog_pointers.altval(CTBP_EA_IDX)); -} - -//------------------------------------------------------------------ -const char *nec850_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - if ( keyword != NULL ) - { - if ( streq(keyword, "GP_EA") ) - { - if ( value_type != IDPOPT_NUM ) - return IDPOPT_BADTYPE; - g_gp_ea = *((uval_t *)value); - goto SAVE; - } - if ( streq(keyword, "CTBP_EA") ) - { - if ( value_type != IDPOPT_NUM ) - return IDPOPT_BADTYPE; - g_ctbp_ea = *((uval_t *)value); - goto SAVE; - } - return IDPOPT_BADKEY; - } - - static const char form[] = - "NEC V850x analyzer options\n" - "\n" - " <~G~lobal Pointer address:$::18::>\n" - " <CALLT ~B~ase pointer :$::18::>\n" - "\n" - "\n" - "\n"; - CASSERT(sizeof(g_gp_ea) == sizeof(ea_t)); - CASSERT(sizeof(g_ctbp_ea) == sizeof(ea_t)); - if ( ask_form(form, &g_gp_ea, &g_ctbp_ea) == ASKBTN_YES ) - { -SAVE: - if ( idb_loaded ) - save_settings(); - } - - return IDPOPT_OK; -} - -//---------------------------------------------------------------------- -static const asm_t nec850_asm = -{ - ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, // flags - 0, // user flags - "NEC V850 Assembler", // assembler name - 0, // help - NULL, // array of automatically generated header lines - ".org", // org directive - ".end", // end directive - "--", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - ".str", // ascii string directive - ".byte", // byte directive - ".hword", // halfword (16 bits) [IDA: word] - ".word", // word (32 bits) [IDA: dword] - ".dword", // doubleword (64 bits) [IDA: qword] - NULL, // oword (16 bytes) - ".float", // float (4-byte) - ".double", // double (8-byte) - NULL, // no tbytes - NULL, // no packreal - "#d dup(#v)", //".db.#s(b,w) #d,#v" - ".byte (%s) ?", // uninited data (reserve space) ;? - ".set", // 'equ' Used if AS_UNEQU is set - NULL, // seg prefix - "PC", // a_curip - NULL, // returns function header line - NULL, // returns function footer line - ".globl", // public - NULL, // weak - ".extern", // extrn - ".comm", // comm - NULL, // get_type_name - ".align", // align - '(', // lbrace - ')', // rbrace - NULL, // mod - "&", // bit-and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flags2 - NULL, // cmnt2 - NULL, // low8 operation, should contain %s for the operand - NULL, // high8 - NULL, // low16 - NULL, // high16 - ".include %s", // a_include_fmt - NULL, // if a named item is a structure and displayed - NULL // 'rva' keyword for image based offsets -}; - -static const asm_t *const asms[] = { &nec850_asm, NULL }; - -//---------------------------------------------------------------------- -#define FAMILY "NEC/Renesas 850 series:" - -static const char *const shnames[] = -{ - "V850", - "V850E", - "V850E1", - "V850E2M", - "RH850", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"NEC V850", - "NEC V850E", - "NEC/Renesas V850E1/ES", - "NEC/Renesas V850E2/E2M", - "Renesas RH850", - NULL -}; - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - // save database - case idb_event::closebase: - case idb_event::savebase: - pm.save_settings(); - break; - - case idb_event::segm_moved: // A segment is moved - // Fix processor dependent address sensitive information - // { - // ea_t from = va_arg(va, ea_t); - // ea_t to = va_arg(va, ea_t); - // asize_t size = va_arg(va, asize_t); - // bool changed_netmap = va_argi(va, bool); - // // adjust gp_ea - // } - break; - - default: - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new nec850_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi nec850_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - inf_set_be(false); - prog_pointers.create("$ prog pointers"); - break; - - case processor_t::ev_is_sane_insn: - { - const insn_t &insn = *va_arg(va, insn_t *); - int no_crefs = va_arg(va, int); - code = nec850_is_sane_insn(insn, no_crefs) == 1 ? 1 : -1; - break; - } - - case processor_t::ev_newprc: - { - int procnum = va_arg(va, int); - // bool keep_cfg = va_argi(va, bool); - ptype = procnum; - break; - } - case processor_t::ev_term: - unhook_event_listener(HT_IDB, &idb_listener); - break; - case processor_t::ev_ending_undo: - // restore ptype - ptype = ph.get_proc_index(); - //fall through - case processor_t::ev_oldfile: - // old file loaded - load_settings(); - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_may_be_func: - { - const insn_t &insn = *va_arg(va, insn_t *); - code = nec850_may_be_func(insn); - } - break; - - case processor_t::ev_is_ret_insn: - { - const insn_t &insn = *va_arg(va, insn_t *); - bool strict = va_argi(va, bool); - code = nec850_is_return(insn, strict) ? 1 : -1; - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - nec850_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - nec850_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - nec850_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - nec850_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return nec850_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return nec850_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_is_switch: - { - switch_info_t *si = va_arg(va, switch_info_t *); - const insn_t *insn = va_arg(va, const insn_t *); - return nec850_is_switch(si, *insn) ? 1 : 0; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *op = va_arg(va, const op_t *); - *mode = nec850_is_sp_based(*insn, *op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - nec850_create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = nec850_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - // START OF DEBUGGER CALLBACKS - case processor_t::ev_next_exec_insn: - { - ea_t *target = va_arg(va, ea_t *); - ea_t ea = va_arg(va, ea_t); - int tid = va_arg(va, int); - getreg_t *getreg = va_arg(va, getreg_t *); - const regval_t *regvalues = va_arg(va, const regval_t *); - qnotused(tid); - *target = nec850_next_exec_insn(ea, getreg, regvalues); - return 1; - } - - case processor_t::ev_calc_step_over: - { - ea_t *target = va_arg(va, ea_t *); - ea_t ip = va_arg(va, ea_t); - *target = nec850_calc_step_over(ip); - return 1; - } - - case processor_t::ev_get_idd_opinfo: - { - idd_opinfo_t *opinf = va_arg(va, idd_opinfo_t *); - ea_t ea = va_arg(va, ea_t); - int n = va_arg(va, int); - int thread_id = va_arg(va, int); - getreg_t *getreg = va_arg(va, getreg_t *); - const regval_t *regvalues = va_arg(va, const regval_t *); - qnotused(thread_id); - return nec850_get_operand_info(opinf, ea, n, getreg, regvalues) ? 1 : 0; - } - - case processor_t::ev_get_reg_info: - { - const char **main_regname = va_arg(va, const char **); - bitrange_t *bitrange = va_arg(va, bitrange_t *); - const char *regname = va_arg(va, const char *); - return nec850_get_reg_info(main_regname, bitrange, regname) ? 1 : -1; - } - // END OF DEBUGGER CALLBACKS - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// Registers Definition -//----------------------------------------------------------------------- -const char *const RegNames[rLastRegister] = -{ - "r0", - "r1", - "r2", - "sp", - "gp", - "r5", // text pointer - tp - "r6", - "r7", - "r8", - "r9", - "r10", - "r11", - "r12", - "r13", - "r14", - "r15", - "r16", - "r17", - "r18", - "r19", - "r20", - "r21", - "r22", - "r23", - "r24", - "r25", - "r26", - "r27", - "r28", - "r29", - "ep", - "lp", - // system registers start here - "eipc", - "eipsw", - "fepc", - "fepsw", - "ecr", - "psw", - "sr6", - "sr7", - "sr8", - "sr9", - "sr10", - "sr11", - "sr12", - "sr13", - "sr14", - "sr15", - "sr16", - "sr17", - "sr18", - "sr19", - "sr20", - "sr21", - "sr22", - "sr23", - "sr24", - "sr25", - "sr26", - "sr27", - "sr28", - "sr29", - "sr30", - "sr31", - - "EFG", "ECT", - - // - "ep", "cs", "ds" -}; -CASSERT(qnumber(RegNames) == rLastRegister); - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_NEC_V850X, // id - // flag - PR_DEFSEG32 - | PR_USE32 - | PRN_HEX - | PR_RNAMESOK, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // short processor names - lnames, // long processor names - - asms, // assemblers - - notify, - - RegNames, // Regsiter names - rLastRegister, // Number of registers - - rVcs/*rVep*/, // number of first segment register - rVds/*rVcs*/, // number of last segment register - 0 /*4*/, // size of a segment register - rVcs, - rVds, - NULL, // No known code start sequences - NULL, // Array of 'return' instruction opcodes - NEC850_NULL, - NEC850_LAST_INSTRUCTION, - Instructions, // instruc - 0, // size of tbyte - {0,7,15,0}, // real width - 0, // icode_return - NULL, // Micro virtual machine description -}; diff --git a/idasdk75/module/oakdsp/ana.cpp b/idasdk75/module/oakdsp/ana.cpp deleted file mode 100644 index 4706466..0000000 --- a/idasdk75/module/oakdsp/ana.cpp +++ /dev/null @@ -1,783 +0,0 @@ -#include "oakdsp.hpp" - -#define FUNCS_COUNT 5 - -struct funcdesc_t -{ - bool (oakdsp_t:: *func)(insn_t &, int, int); - uint32 mask; - uint32 param; - uint32 shift; -}; - -struct opcode_t -{ - const char *recog; - ushort itype; - funcdesc_t funcs[FUNCS_COUNT]; //lint !e958 padding is required to align members - uchar cycles; //Number of cycles - uint32 mask; //lint !e958 padding is required to align members - uint32 value; -}; - -//---------------------------------------------------------------------- -static uint32 ua_32bits(const insn_t &insn) -{ - return ((get_wide_byte(insn.ea) << 0) & 0x0000FFFF) - | ((get_wide_byte(insn.ea+1) << 16) & 0xFFFF0000); - -} - -//lint -e1762 member function could be made const - -//---------------------------------------------------------------------- -inline void oakdsp_t::opreg(int reg) -{ - op->type = o_reg; - op->reg = uint16(reg); -} - -//---------------------------------------------------------------------- -void oakdsp_t::make_o_mem(const insn_t &insn) -{ - if ( !(op->amode & amode_x) ) - { - switch ( insn.itype ) - { - - case OAK_Dsp_callr: - case OAK_Dsp_call: - case OAK_Dsp_br_u: - case OAK_Dsp_br: - case OAK_Dsp_brr_u: - case OAK_Dsp_brr: - case OAK_Dsp_bkrep: - op->type = o_near; - op->dtype = dt_code; - return; - } - } - op->type = o_mem; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::rrrrr(insn_t &, int value, int param) -{ - uint idx; - if ( param & mix_mode ) - param = (param & 0xff) + value; - idx = param ? param : value; - - if ( idx >= PAGE ) - return false; - opreg(idx); - if ( op->reg == uchar(-1) ) - return false; - - op++; - return true; -} - -//---------------------------------------------------------------------- -//lint -e{1764} 'insn' could be declared const ref -bool oakdsp_t::sdirect(insn_t &insn, int value, int) -{ - op->amode = amode_short; - op->addr = value & 0x00ff; - op->amode |= amode_x; - - make_o_mem(insn); - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::ldirect(insn_t &insn, int value,int) -{ - op->amode = amode_long; - op->addr = value & 0xffff; - insn.size++; - op->amode |= amode_x; - - make_o_mem(insn); - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::A(insn_t &insn, int value,int) -{ - return rrrrr(insn, value & 0x01, A0 + mix_mode); -} - -//---------------------------------------------------------------------- -bool oakdsp_t::B(insn_t &insn, int value,int) -{ - return rrrrr(insn, value & 0x01, B0 + mix_mode); -} - -//---------------------------------------------------------------------- -bool oakdsp_t::mmnnn(insn_t &, int value,int) -{ - if ( (value & 0x07) > 0x05 ) - return false; - - op->type = o_phrase; - op->reg = value & 0x07; - op->phtype = (value & 0x0018) >> 3; - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::nnn(insn_t &insn, int value, int) -{ - return rrrrr(insn, value & 0x07, R0 + mix_mode); -} -//---------------------------------------------------------------------- -bool oakdsp_t::ALU_ALM(insn_t &insn, int value, int param) -{ - if ( param && (value == 0x04 || value == 0x05) ) - return false; - - insn.itype = OAK_Dsp_or + (value & (param ? 0x07 : 0x0f)); - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::ALB(insn_t &insn, int value, int) -{ - insn.itype = OAK_Dsp_set + (value & 0x07); - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::MUL(insn_t &insn, int value, int param) -{ - if ( param && (value > 0x03) ) - return false; - - insn.itype = OAK_Dsp_mpy + ((value & (param ? 0x03 : 0x07)) << (param ? 0x01 : 0x00)); - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::MODA_B(insn_t &insn, int value, int param) -{ - if ( value == 0x07 ) - return false; - - insn.itype = OAK_Dsp_shr + (value & (param ? 0x07 : 0x0f)); - return true; -} - -//---------------------------------------------------------------------- -//lint -e{1764} 'insn' could be declared const ref -bool oakdsp_t::s_Imm(insn_t &insn, int value, int) -{ - op->type = o_imm; - op->value = value; - - switch ( insn.itype ) - { - case OAK_Dsp_mpyi: - op->amode |= amode_signed; - break; - } - - op++; - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::s_ImmS(insn_t &, int value, int param) -{ - uint mask1 = 1 << (param - 1); - uint mask2 = 0; - for ( int i = 0; i < param; i++ ) - mask2 |= (1 << i); - - op->type = o_imm; - op->value = (value & mask2); - op->amode |= amode_signed; - - if ( value & mask1 ) - op->value = - ((value^mask2) + 1); - - op++; - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::l_Imm(insn_t &insn, int value, int) -{ - op->type = o_imm; - op->value = value & 0xffff; - insn.size++; - - switch ( insn.itype ) - { - case OAK_Dsp_maa: - case OAK_Dsp_mac: - case OAK_Dsp_macus: - case OAK_Dsp_mpy: - case OAK_Dsp_msu: - op->amode |= amode_signed; - break; - } - - op++; - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::rb_rel_short(insn_t &, int value, int) -{ - op->type = o_local; - op->phtype = 0; // "rb + #displ" - op->amode |= amode_signed; - - value &= 0x7f; - - if ( value & 0x40 ) - value = - ((value^0x7f) + 1); - - op->addr = value; - op->amode |= amode_x; - - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::rb_rel_long(insn_t &insn, int value, int) -{ - int16 tmp; - - insn.size++; - op->type = o_local; - op->phtype = 0; // "rb + #displ" - op->amode |= amode_signed; - tmp = (value & 0xffff); - op->addr = tmp; - op->amode |= amode_x; - - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::Cond(insn_t &insn, int value, int param) -{ - insn.auxpref |= value & 0x0f; - - if ( (!param) && ((value & 0x0f) > 0x00) ) - insn.auxpref |= aux_comma_cc; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::xe_xt(insn_t &insn, int value, int param) -{ - static const uchar regs[] = { cc_ge, cc_gt, cc_le, cc_lt }; - - insn.auxpref |= regs[(value & 0x01) + (param ? 2 : 0)]; - insn.auxpref |= aux_comma_cc; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::lim_xx(insn_t &, int value, int) -{ - static const uchar regs1[] = { A0, A0, A1, A1 }; - static const uchar regs2[] = { uchar(-1), A1, A0, uchar(-1) }; - - opreg(regs1[value & 0x03]); - - if ( regs2[value & 0x03] != uchar(-1) ) - { - op++; - opreg(regs2[value & 0x03]); - } - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::rJ_rI(insn_t &, int value,int param) -{ - //jjiiwqq - - op->type = o_phrase; - op->reg = param ? (value & 0x03) : ((value & 0x04) >> 2) + 4; - op->phtype = param ? (value & 0x0018) >> 3 : (value & 0x0060) >> 5; - op++; - - op->type = o_phrase; - op->reg = param ? ((value & 0x04) >> 2) + 4 : (value & 0x03); - op->phtype = param ? (value & 0x0060) >> 5 : (value & 0x0018) >> 3; - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::rI(insn_t &, int value,int) -{ - //iiqq - - op->type = o_phrase; - op->reg = (value & 0x03); - op->phtype = (value & 0x0c) >> 2; - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::AB(insn_t &, int value,int) -{ - static const uchar regs[] = { B0, B1, A0, A1 }; - - opreg(regs[value & 0x03]); - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::ABLH(insn_t &, int value,int) -{ - static const uchar regs[] = { B0L, B0H, B1L, B1H, A0L, A0H, A1L, A1H }; - - opreg(regs[value & 0x07]); - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::indir_reg(insn_t &, int value,int param) -{ - op->type = o_phrase; - op->reg = uint16(param + value); - op->phtype = 4; - op++; - - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::laddr_pgm(insn_t &insn, int value,int) -{ - op->amode |= amode_p; - op->addr = value & 0xffff; - insn.size++; - - make_o_mem(insn); - op++; - - return true; -} - -//---------------------------------------------------------------------- -//lint -e{1764} 'insn' could be declared const ref -bool oakdsp_t::addr_rel_pgm(insn_t &insn, int value, int) -{ - value = (value & 0x7f); - op->amode |= amode_p; - - if ( value & 0x40 ) - { - value = (value^0x7f) + 1; - op->addr = insn.ea + 1 - value; - } - else - { - op->addr = insn.ea + 1 + value; - } - - make_o_mem(insn); - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::ext_XX(insn_t &insn, int value, int) -{ - return rrrrr(insn, (value & 0x01) + ((value & 0x04) >> 1), EXT0 + mix_mode); -} - -//---------------------------------------------------------------------- -bool oakdsp_t::context(insn_t &insn, int value,int) -{ - if ( value ) - insn.auxpref |= aux_iret_context; - return true; -} -//---------------------------------------------------------------------- -bool oakdsp_t::swap(insn_t &, int value,int) -{ - op->type = o_textphrase; - op->phrase = value & 0x0f; - op->phtype = text_swap; - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::banke(insn_t &, int value,int) -{ - op->type = o_textphrase; - op->phrase = value & 0x0f; - op->phtype = text_banke; - return true; -} -//---------------------------------------------------------------------- -bool oakdsp_t::cntx(insn_t &, int value,int) -{ - op->type = o_textphrase; - op->phrase = (uint16)value; - op->phtype = text_cntx; - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::dmod(insn_t &, int value,int) -{ - op->type = o_textphrase; - op->phrase = (uint16)value; - op->phtype = text_dmod; - return true; -} - -//---------------------------------------------------------------------- -bool oakdsp_t::eu(insn_t &, int,int) -{ - op->type = o_textphrase; - op->phtype = text_eu; - return true; -} - -//---------------------------------------------------------------------- -// singleton to init table thread-aware -struct table_t -{ - static int count() { return qnumber(table); } - static const opcode_t &get(int opcode) - { - static const table_t instance; //lint !e1788 only by its constructor/destructor - return instance.table[opcode]; //lint !e727 static local symbol 'instance' of type 'const struct table_t' not explicitly initialized - } - -private: - opcode_t table[124] = - { - { "0000000000000000", OAK_Dsp_nop, {{0}}, 1 }, - { "0000000000100000", OAK_Dsp_trap, {{0}}, 1 }, - { "0000000010fmmnnn", OAK_Dsp_modr, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::dmod, 0x0020}}, 1 }, - { "0000000001arrrrr", OAK_Dsp_movp, {{&oakdsp_t::indir_reg, 0x20, A0}, {&oakdsp_t::rrrrr, 0x001f}}, 3 }, - { "000000010abrrrrr", OAK_Dsp_movs, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "000000011abmmnnn", OAK_Dsp_movs, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "00000100vvvvvvvv", OAK_Dsp_lpg, {{&oakdsp_t::s_Imm, 0x00ff}}, 1 }, - { "00001000vvvvvvvv", OAK_Dsp_mpyi, {{&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::s_Imm, 0x00ff}}, 1 }, - { "00000101vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, - { "00001001vvvvvvvv", OAK_Dsp_rets, {{&oakdsp_t::s_Imm, 0x00ff}}, 3 }, - { "00001101---rrrrr", OAK_Dsp_rep, {{&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "00001100vvvvvvvv", OAK_Dsp_rep, {{&oakdsp_t::s_Imm, 0x00ff}}, 1 }, - { "0000011iiqqmmnnn", OAK_Dsp_movp, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::rI, 0x01e0}}, 3 }, - { "0000111adddddddd", OAK_Dsp_divs, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "0000x01vvvvvvvvv", OAK_Dsp_load, {{&oakdsp_t::s_Imm, 0x01ff}, {&oakdsp_t::rrrrr, 0x0800, MODI|mix_mode}}, 1 }, - { "000110rrrrrmmnnn", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x03e0}, {&oakdsp_t::mmnnn, 0x001f}}, 1 }, - { "000111rrrrrmmnnn", OAK_Dsp_mov, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::rrrrr, 0x03e0}}, 1 }, - { "00010ooooooocccc", OAK_Dsp_callr, {{&oakdsp_t::addr_rel_pgm, 0x07f0}, {&oakdsp_t::Cond, 0x000f}}, 2 }, - { "0010nnn0dddddddd", OAK_Dsp_mov, {{&oakdsp_t::nnn, 0x0e00}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, - { "001a0001vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::rrrrr, 0x1000, A0L|mix_mode}}, 1 }, - { "001a0101vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::rrrrr, 0x1000, A0H|mix_mode}}, 1 }, - { "001nnn11vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::nnn, 0x1c00}}, 1 }, - { "001x1x01vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::ext_XX, 0x1400}}, 1 }, - { "0011ABL0dddddddd", OAK_Dsp_mov, {{&oakdsp_t::ABLH, 0x0e00}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, - { "0100001110000000", OAK_Dsp_eint, {{0}}, 1 }, - { "0100001111000000", OAK_Dsp_dint, {{0}}, 1 }, - { "0100000110000000", OAK_Dsp_br_u, {{&oakdsp_t::laddr_pgm, 0xffff0000}}, 2 }, - { "0100010110000000", OAK_Dsp_ret_u, {{0}}, 2 }, - { "01001101100000vv", OAK_Dsp_load, {{&oakdsp_t::s_Imm, 0x0003}, {&oakdsp_t::rrrrr, 0, PS}}, 1 }, - { "01000101110f0000", OAK_Dsp_reti_u, {{&oakdsp_t::context, 0x0010}}, 2 }, - { "010001011000cccc", OAK_Dsp_ret, {{&oakdsp_t::Cond, 0x000f, 1}}, 2 }, - { "010000011000cccc", OAK_Dsp_br, {{&oakdsp_t::laddr_pgm, 0xffff0000}, {&oakdsp_t::Cond, 0x000f}}, 2 }, - { "010000011100cccc", OAK_Dsp_call, {{&oakdsp_t::laddr_pgm, 0xffff0000}, {&oakdsp_t::Cond, 0x000f}}, 2 }, - { "01000111110rrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0, MIXP}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "01000111111rrrrr", OAK_Dsp_mov, {{&oakdsp_t::indir_reg, 0, SP}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "01000101110fcccc", OAK_Dsp_reti, {{&oakdsp_t::Cond, 0x000f, 1}, {&oakdsp_t::context, 0x0010}}, 1 }, - { "0100100110--swap", OAK_Dsp_swap, {{&oakdsp_t::swap, 0x000f}}, 1 }, - { "0100111111-rrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0, ICR}}, 1 }, - { "0100111110-vvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x001f}, {&oakdsp_t::rrrrr, 0, ICR}}, 1 }, - { "0100100111xx----", OAK_Dsp_lim, {{&oakdsp_t::lim_xx, 0x0030}}, 1 }, - { "010010111---bank", OAK_Dsp_banke, {{&oakdsp_t::banke, 0x000f}}, 1 }, - { "0100nnn01abvvvvv", OAK_Dsp_movsi, {{&oakdsp_t::nnn, 0x0e00}, {&oakdsp_t::AB, 0x0060}, {&oakdsp_t::s_ImmS, 0x001f, 5}}, 1 }, - { "0100xxxa0ooooooo", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0e00, 1}, {&oakdsp_t::rb_rel_short, 0x007f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "0101111101000000", OAK_Dsp_push, {{&oakdsp_t::l_Imm, 0xffff0000}}, 2 }, - { "01011110010rrrrr", OAK_Dsp_push, {{&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "01011110011rrrrr", OAK_Dsp_pop, {{&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "01011110100rrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0, MIXP}}, 1 }, - { "0101111011brrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::B, 0x0020}}, 1 }, - { "01011101000rrrrr", OAK_Dsp_bkrep, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::laddr_pgm, 0xffff0000}}, 2 }, - { "0101111-000rrrrr", OAK_Dsp_mov, {{&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::rrrrr, 0x001f}}, 2 }, - { "0101111b001-----", OAK_Dsp_mov, {{&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::B, 0x0100}}, 2 }, - { "010111111jjiiwqq", OAK_Dsp_movd, {{&oakdsp_t::rJ_rI, 0x007f, 1}}, 4 }, - { "01011100vvvvvvvv", OAK_Dsp_bkrep, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::laddr_pgm, 0xffff0000}}, 2 }, - { "010110RRRRRrrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0x03e0}}, 1 }, - { "01010ooooooo0000", OAK_Dsp_brr_u, {{&oakdsp_t::addr_rel_pgm, 0x07f0}}, 2 }, - { "01010ooooooocccc", OAK_Dsp_brr, {{&oakdsp_t::addr_rel_pgm, 0x07f0}, {&oakdsp_t::Cond, 0x000f}}, 2 }, - { "01101101dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, - { "011nnn00dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::nnn, 0x1c00}}, 1 }, - { "011AB001dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::AB, 0x1800}}, 1 }, - { "011ABL10dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::ABLH, 0x1c00}}, 1 }, - { "011A0101dddddddd", OAK_Dsp_mov_eu, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x1000}, {&oakdsp_t::eu, 0x0}}, 1 }, - { "011ab011dddddddd", OAK_Dsp_movs, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::AB, 0x1800}}, 1 }, - { "011b11110fffcccc", OAK_Dsp_proc, {{&oakdsp_t::MODA_B, 0x0070, 1}, {&oakdsp_t::B, 0x1000}, {&oakdsp_t::Cond, 0x000f}}, 1 }, - { "011a0111ffffcccc", OAK_Dsp_proc, {{&oakdsp_t::MODA_B, 0x00f0}, {&oakdsp_t::A, 0x1000}, {&oakdsp_t::Cond, 0x000f}}, 1 }, - { "01111101dddddddd", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0, SV}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, - { "100000fa011mm000", OAK_Dsp_maxd, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::xe_xt, 0x0200, 0}}, 1 }, - { "100001fa011mm000", OAK_Dsp_max, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::xe_xt, 0x0200, 0}}, 1 }, - { "10001-fa011mm000", OAK_Dsp_min, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::xe_xt, 0x0200, 1}}, 1 }, - { "1000xxxa11000000", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0e00, 1}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, - { "1000xxx0111mmnnn", OAK_Dsp_proc, {{&oakdsp_t::ALB, 0x0e00}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::mmnnn, 0x001f}}, 2 }, - { "1000xxx1111rrrrr", OAK_Dsp_proc, {{&oakdsp_t::ALB, 0x0e00}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::rrrrr, 0x001f}}, 2 }, - { "1000-00x001mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::mmnnn, 0x001f}}, 1 }, - { "1000axxx001mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0800}}, 1 }, - { "1000-00x010rrrrr", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "1000axxx010rrrrr", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0800}}, 1 }, - { "1000-00x000mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::l_Imm, 0xffff0000}}, 2 }, - { "1000axxx000mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::A, 0x0800}}, 2 }, - { "100xxxxa100mmnnn", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x1e00}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "100xxxxa101rrrrr", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x1e00}, {&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1001000a110mmnnn", OAK_Dsp_msu, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, - { "1001010a110mmnnn", OAK_Dsp_norm, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}}, 2 }, - { "1001bbbb001mmnnn", OAK_Dsp_tstb, {{&oakdsp_t::s_Imm, 0x0f00}, {&oakdsp_t::mmnnn, 0x001f}}, 1 }, - { "1001bbbb000rrrrr", OAK_Dsp_tstb, {{&oakdsp_t::s_Imm, 0x0f00}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, - { "1001ab1AB1vvvvvv", OAK_Dsp_shfi, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::AB, 0x0180}, {&oakdsp_t::s_ImmS, 0x003f, 6}}, 1 }, - { "1001100a010mmnnn", OAK_Dsp_exp, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1001000a010rrrrr", OAK_Dsp_exp, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1001000a0110000b", OAK_Dsp_exp, {{&oakdsp_t::B, 0x0001}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "10011100010mmnnn", OAK_Dsp_exp, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, - { "10010100010rrrrr", OAK_Dsp_exp, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, - { "100101000110000b", OAK_Dsp_exp, {{&oakdsp_t::B, 0x0001}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, - { "1001100b110mmnnn", OAK_Dsp_mov, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::B, 0x0100}}, 1 }, - { "1001110a110rrrrr", OAK_Dsp_movr, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1001110a111mmnnn", OAK_Dsp_movr, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "101xxxxadddddddd", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x1e00}, {&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1100xxxavvvvvvvv", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0e00, 1}, {&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1101001111000000", OAK_Dsp_break, {{0}}, 1 }, - { "1101011110000000", OAK_Dsp_retd, {{0}}, 1 }, - { "1101011111000000", OAK_Dsp_retid, {{0}}, 1 }, - { "1101010a10000000", OAK_Dsp_calla, {{&oakdsp_t::A, 0x0100}}, 3 }, - { "11010011100f0000", OAK_Dsp_cntx, {{&oakdsp_t::cntx, 0x0010}}, 1 }, - { "110101001ab10000", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,REPC}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "110101001ab10001", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,DVM}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "110101001ab10010", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,ICR}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "110101001ab10011", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,X}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "1101010a101110--", OAK_Dsp_mov, {{&oakdsp_t::ldirect, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, - { "1101010a101111--", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x0100, A0L|mix_mode}, {&oakdsp_t::ldirect, 0xffff0000}}, 2 }, - { "1101010a100110--", OAK_Dsp_mov, {{&oakdsp_t::rb_rel_long,0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, - { "1101010a100111--", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x0100, A0L|mix_mode}, {&oakdsp_t::rb_rel_long,0xffff0000}}, 2 }, - { "1101010a11011xxx", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0007, 1}, {&oakdsp_t::rb_rel_long, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, - { "1101010a11111xxx", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0007, 1}, {&oakdsp_t::ldirect, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, - { "1101AB1011011000", OAK_Dsp_mov, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::rrrrr, 0x0000, X}}, 1 }, - { "1101AB1010011000", OAK_Dsp_mov, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::rrrrr, 0x0000, DVM}}, 1 }, - { "1101ab101AB10000", OAK_Dsp_mov, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::AB, 0x0060}}, 1 }, - { "1101000a1jjiiwqq", OAK_Dsp_msu, {{&oakdsp_t::rJ_rI, 0x007f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1101ab101AB0cccc", OAK_Dsp_shfc, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::AB, 0x0060}, {&oakdsp_t::Cond, 0x000f}}, 1 }, - { "1101100a1ooooooo", OAK_Dsp_mov, {{&oakdsp_t::rb_rel_short, 0x007f}, {&oakdsp_t::A, 0x0100}}, 1 }, - { "1101110a1ooooooo", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x0100, A0L|mix_mode}, {&oakdsp_t::rb_rel_short, 0x007f}}, 1 }, - { "11011x111vvvvvvv", OAK_Dsp_load, {{&oakdsp_t::s_Imm, 0x007f}, {&oakdsp_t::rrrrr, 0x0400, STEPI|mix_mode}}, 1 }, - { "1101-00x0jjiiwqq", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rJ_rI, 0x007f}}, 1 }, - { "1101axxx0jjiiwqq", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rJ_rI, 0x007f}, {&oakdsp_t::A, 0x0800}}, 1 }, - { "1110xxx1dddddddd", OAK_Dsp_proc, {{&oakdsp_t::ALB, 0x0e00}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::sdirect, 0x00ff}}, 2 }, - { "1110-000dddddddd", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0600, 1}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, - { "1110axx0dddddddd", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0600, 1}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x0800}}, 1 }, - { "1111bbbbdddddddd", OAK_Dsp_tstb, {{&oakdsp_t::s_Imm, 0x0f00}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, - }; - - table_t() - { - gen_masks(); - } - ~table_t() = default; - table_t(const table_t&) = delete; - table_t &operator=(const table_t&) = delete; - - void gen_masks() - { - for ( auto &te : table ) - { - int len = strlen(te.recog); - for ( int b = 0; b < len; b++ ) - { - te.value <<= 1; - te.mask <<= 1; - - if ( te.recog[b] == '1' || te.recog[b] == '0' ) - te.mask++; - - if ( te.recog[b] == '1' ) - te.value++; - } - - for ( int j = 0; j < FUNCS_COUNT; j++ ) - { - if ( te.funcs[j].func ) - { - for ( int b = 0; b < 32; b++ ) - { - if ( te.funcs[j].mask & (1 << b) ) - break; - else - te.funcs[j].shift++; - } - } - } - } - } -}; - -//---------------------------------------------------------------------- -bool oakdsp_t::use_table(insn_t &insn, const opcode_t &ptr, uint code, int start, int end) -{ - for ( int j = start; j <= end; j++ ) - { - if ( !ptr.funcs[j].func ) - break; - int value = (code & ptr.funcs[j].mask) >> ptr.funcs[j].shift; - if ( !(this->*ptr.funcs[j].func)(insn, value, ptr.funcs[j].param) ) - return false; - } - return true; -} - -//---------------------------------------------------------------------- -void oakdsp_t::reset_ops(insn_t &insn) -{ - op = &insn.Op1; - for ( int i=0; i < UA_MAXOP; i++ ) - insn.ops[i].type = o_void; -} - -//---------------------------------------------------------------------- -int oakdsp_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - uint code = ua_32bits(insn); - uint prev_inst_code; - op = &insn.Op1; - int move_rb_to_reg = 0; - - int cnt = table_t::count(); - for ( int i = 0; i < cnt; i++ ) - { - const auto &te = table_t::get(i); - if ( (code & te.mask) == te.value ) - { - insn.itype = te.itype; - insn.cmd_cycles = te.cycles; - insn.size = 1; - - if ( !use_table(insn, te, code, 0, FUNCS_COUNT - 1) ) - { - reset_ops(insn); - continue; - } - - - - // mov #imm, pc --> near jump - if ( insn.itype == OAK_Dsp_mov - && insn.Op1.type == o_imm - && insn.Op2.type == o_reg - && insn.Op2.reg == PC ) - { - insn.Op1.type = o_near; - insn.Op1.dtype = dt_code; - insn.Op1.addr = insn.Op1.value; - insn.Op1.amode = amode_p; - } - - - // add(sub) #imm, reg after mov rb, reg instruction - // #imm --> local var - - if ( insn.ea != 0 ) - { - prev_inst_code = get_wide_byte(insn.ea - 1); - - if ( ((prev_inst_code & 0xfc1f) == 0x5806) - || ((prev_inst_code & 0xffdf) == 0x5ec6) ) - { - if ( (prev_inst_code & 0xfc1f) == 0x5806 ) // mov reg, reg - move_rb_to_reg = (prev_inst_code >> 5) & 0x1f; - else if ( (prev_inst_code & 0xffdf) == 0x5ec6 ) // mov reg, bx - move_rb_to_reg = B0 + ((prev_inst_code >> 5) & 0x01); - - if ( insn.Op1.type == o_imm - && (insn.Op2.reg == move_rb_to_reg - || (insn.Op2.reg == A0L && move_rb_to_reg == A0) - || (insn.Op2.reg == A1L && move_rb_to_reg == A1) - || (insn.Op2.reg == B0L && move_rb_to_reg == B0) - || (insn.Op2.reg == B1L && move_rb_to_reg == B1)) ) - { - int16 tmp = insn.Op1.value; - - switch ( insn.itype ) - { - case OAK_Dsp_sub: - case OAK_Dsp_subv: - tmp = - tmp; - //no break - case OAK_Dsp_add: - case OAK_Dsp_addv: - insn.Op1.addr = tmp; - insn.Op1.type = o_local; - insn.Op1.phtype = 1; // "#" - insn.Op1.amode |= amode_signed; - insn.Op1.amode |= amode_x; - break; - } - } - } - } - - - // add(sub) #imm, SP - // #imm --> signed imm - - if ( insn.Op1.type == o_imm && insn.Op2.type == o_reg && insn.Op2.reg == SP ) - { - switch ( insn.itype ) - { - case OAK_Dsp_add: - case OAK_Dsp_addv: - case OAK_Dsp_sub: - case OAK_Dsp_subv: - insn.Op1.amode |= amode_signed; - break; - } - } - return insn.size; - } - } - return 0; -} - -//-------------------------------------------------------------------------- -void interr(const insn_t &insn, const char *module) -{ - const char *name = NULL; - if ( insn.itype < OAK_Dsp_last ) - name = Instructions[insn.itype].name; - warning("%a(%s): internal error in %s", insn.ea, name, module); -} diff --git a/idasdk75/module/oakdsp/emu.cpp b/idasdk75/module/oakdsp/emu.cpp deleted file mode 100644 index 81d09dc..0000000 --- a/idasdk75/module/oakdsp/emu.cpp +++ /dev/null @@ -1,421 +0,0 @@ - -#include "oakdsp.hpp" -#include <segregs.hpp> -#include <frame.hpp> - -//---------------------------------------------------------------------- -ea_t oakdsp_t::calc_mem(const insn_t &insn, const op_t &x) const -{ - uint xaddr; - - if ( x.amode & amode_x ) - { - if ( x.amode & amode_short ) - { - sel_t dpage = get_sreg(insn.ea, PAGE); - if ( dpage == BADSEL ) - return BADSEL; - xaddr = ((dpage & 0xFF) << 8) | uint(x.addr); - } - else - { - xaddr = (uint)x.addr; - } - return xmem == BADADDR ? BADADDR : xmem + xaddr; - } - - return to_ea(insn.cs, x.addr); - -} -//------------------------------------------------------------------------ -void oakdsp_t::init_emu(void) -{ - delayed = false; - cycles = 0; -} - -//------------------------------------------------------------------------ -inline bool is_stkreg(int r) -{ - return r == SP; -} - -//------------------------------------------------------------------------ -int idaapi is_sp_based(const insn_t &, const op_t &x) -{ - return OP_SP_ADD | (x.phrase == SP ? OP_SP_BASED : OP_FP_BASED); -} - -//------------------------------------------------------------------------ -static void process_immediate_number(const insn_t &insn, int n) -{ - set_immd(insn.ea); - if ( is_defarg(get_flags(insn.ea), n) ) - return; - switch ( insn.itype ) - { - case OAK_Dsp_shfi: - case OAK_Dsp_movsi: - - op_dec(insn.ea, n); - break; - - case OAK_Dsp_lpg: - case OAK_Dsp_mpyi: - case OAK_Dsp_mov: - case OAK_Dsp_rets: - case OAK_Dsp_rep: - case OAK_Dsp_load: - case OAK_Dsp_push: - case OAK_Dsp_bkrep: - case OAK_Dsp_msu: - case OAK_Dsp_tstb: - case OAK_Dsp_or: - case OAK_Dsp_and: - case OAK_Dsp_xor: - case OAK_Dsp_add: - case OAK_Dsp_alm_tst0: - case OAK_Dsp_alm_tst1: - case OAK_Dsp_cmp: - case OAK_Dsp_sub: - case OAK_Dsp_alm_msu: - case OAK_Dsp_addh: - case OAK_Dsp_addl: - case OAK_Dsp_subh: - case OAK_Dsp_subl: - case OAK_Dsp_sqr: - case OAK_Dsp_sqra: - case OAK_Dsp_cmpu: - case OAK_Dsp_set: - case OAK_Dsp_rst: - case OAK_Dsp_chng: - case OAK_Dsp_addv: - case OAK_Dsp_alb_tst0: - case OAK_Dsp_alb_tst1: - case OAK_Dsp_cmpv: - case OAK_Dsp_subv: - case OAK_Dsp_mpy: - case OAK_Dsp_mpysu: - case OAK_Dsp_mac: - case OAK_Dsp_macus: - case OAK_Dsp_maa: - case OAK_Dsp_macuu: - case OAK_Dsp_macsu: - case OAK_Dsp_maasu: - - op_num(insn.ea, n); - break; - } -} - -//---------------------------------------------------------------------- -void oakdsp_t::add_near_ref(const insn_t &insn, const op_t &x, ea_t ea) -{ - cref_t ftype = fl_JN; - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - if ( !func_does_return(ea) ) - flow = false; - ftype = fl_CN; - } - insn.add_cref(ea, x.offb, ftype); -} - -//---------------------------------------------------------------------- -void oakdsp_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) -{ - switch ( x.type ) - { - case o_reg: - default: - break; - case o_imm: - process_immediate_number(insn, x.n); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, dr_O, x.amode & amode_signed ? OOF_SIGNED : 0); - break; - - case o_phrase: - if ( !is_forced && op_adds_xrefs(get_flags(insn.ea), x.n) ) - { - ea_t ea = insn.add_off_drefs(x, isload ? dr_R : dr_W, OOF_ADDR); - if ( ea != BADADDR ) - insn.create_op_data(ea, x); - } - break; - case o_mem: - { - ea_t ea = calc_mem(insn, x); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - insn.create_op_data(ea, x); - } - break; - case o_near: - add_near_ref(insn, x, calc_mem(insn, x)); - break; - case o_textphrase: - break; - - case o_local: // local variables - if ( may_create_stkvars() ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL - && (pfn->flags & FUNC_FRAME) != 0 - && insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) ) - { - op_stkvar(insn.ea, x.n); - } - } - break; - - } -} - -//---------------------------------------------------------------------- -static bool add_stkpnt(const insn_t &insn, sval_t delta) -{ - func_t *pfn = get_func(insn.ea); - if ( pfn == NULL ) - return false; - - return add_auto_stkpnt(pfn, insn.ea+insn.size, delta); -} - -//---------------------------------------------------------------------- -static void trace_sp(const insn_t &insn) -{ - - int16 frame; - - // trace SP changes - - switch ( insn.itype ) - { - case OAK_Dsp_reti_u: - case OAK_Dsp_retid: - case OAK_Dsp_reti: - add_stkpnt(insn, 1); - break; - - case OAK_Dsp_ret_u: - case OAK_Dsp_retd: - case OAK_Dsp_ret: - add_stkpnt(insn, 1); - break; - - case OAK_Dsp_rets: - add_stkpnt(insn, 1 + insn.Op1.value); - break; - - case OAK_Dsp_pop: - add_stkpnt(insn, 1); - break; - - case OAK_Dsp_push: - add_stkpnt(insn, -1); - break; - - case OAK_Dsp_addv: - if ( insn.Op1.type == o_imm - && insn.Op2.type == o_reg - && insn.Op2.reg == SP ) - { - frame = (uint16)insn.Op1.value; - add_stkpnt(insn, frame); - } - break; - - case OAK_Dsp_subv: - if ( insn.Op1.type == o_imm - && insn.Op2.type == o_reg - && insn.Op2.reg == SP ) - { - frame = (uint16)insn.Op1.value; - add_stkpnt(insn, -frame); - } - break; - - - } -} - -//---------------------------------------------------------------------- -int oakdsp_t::emu(const insn_t &insn) -{ - if ( segtype(insn.ea) == SEG_XTRN ) - return 1; - - //uint32 Feature = insn.get_canon_feature(ph); - bool flag1 = is_forced_operand(insn.ea, 0); - bool flag2 = is_forced_operand(insn.ea, 1); - bool flag3 = is_forced_operand(insn.ea, 2); - -// Determine if the next instruction should be executed - flow = (has_insn_feature(insn.itype, CF_STOP) != true); - - if ( has_insn_feature(insn.itype,CF_USE1) ) handle_operand(insn, insn.Op1, flag1, true); - if ( has_insn_feature(insn.itype,CF_USE2) ) handle_operand(insn, insn.Op2, flag2, true); - if ( has_insn_feature(insn.itype,CF_USE3) ) handle_operand(insn, insn.Op3, flag3, true); - - if ( has_insn_feature(insn.itype,CF_CHG1) ) handle_operand(insn, insn.Op1, flag1, false); - if ( has_insn_feature(insn.itype,CF_CHG2) ) handle_operand(insn, insn.Op2, flag2, false); - if ( has_insn_feature(insn.itype,CF_CHG3) ) handle_operand(insn, insn.Op3, flag3, false); - - - // check for DP changes - if ( insn.itype == OAK_Dsp_lpg ) - split_sreg_range(get_item_end(insn.ea), PAGE, insn.Op1.value & 0xFF, SR_auto); - if ( insn.itype == OAK_Dsp_mov - && insn.Op1.type == o_imm - && insn.Op2.type == o_reg - && insn.Op2.reg == ST1 ) - { - split_sreg_range(get_item_end(insn.ea), PAGE, insn.Op1.value & 0xFF, SR_auto); - } - - //Delayed Return - - cycles = insn.cmd_cycles; - delayed = false; - - insn_t prev_ins; - if ( decode_prev_insn(&prev_ins, insn.ea) != BADADDR ) - { - if ( prev_ins.itype == OAK_Dsp_retd || prev_ins.itype == OAK_Dsp_retid ) - delayed = true; - else - cycles += prev_ins.cmd_cycles; - - if ( !delayed ) - if ( decode_prev_insn(&prev_ins, prev_ins.ea) != BADADDR ) - if ( prev_ins.itype == OAK_Dsp_retd || prev_ins.itype == OAK_Dsp_retid ) - delayed = true; - } - - if ( delayed && (cycles > 1) ) - flow = false; - - //mov #imm, pc - - if ( insn.itype == OAK_Dsp_mov && insn.Op2.type == o_reg && insn.Op2.reg == PC ) - flow = false; - - if ( flow ) - add_cref(insn.ea, insn.ea+insn.size, fl_F); - - if ( may_trace_sp() ) - { - if ( !flow ) - recalc_spd(insn.ea); // recalculate SP register for the next insn - else - trace_sp(insn); - } - - return 1; -} - -//---------------------------------------------------------------------- -int may_be_func(const insn_t &) // can a function start here? - // arg: none, the instruction is in 'insn' - // returns: probability 0..100 -{ - return 0; -} - -//---------------------------------------------------------------------- -int oakdsp_t::is_sane_insn(const insn_t &insn, int /*nocrefs*/) const -{ - // disallow jumps to nowhere - if ( insn.Op1.type == o_near && !is_mapped(calc_mem(insn, insn.Op1)) ) - return 0; - - // disallow many nops in a now - int i = 0; - for ( ea_t ea=insn.ea; i < 32; i++,ea++ ) - if ( get_byte(ea) != 0 ) - break; - if ( i == 32 ) - return 0; - - return 1; -} - -//---------------------------------------------------------------------- -int idaapi is_align_insn(ea_t ea) -{ - insn_t insn; - if ( decode_insn(&insn, ea) < 1 ) - return 0; - switch ( insn.itype ) - { - case OAK_Dsp_nop: - break; - default: - return 0; - } - return insn.size; -} - -//---------------------------------------------------------------------- -bool idaapi create_func_frame(func_t *pfn) // create frame of newly created function -{ - bool std_vars_func = true; - - if ( pfn != NULL ) - { - if ( pfn->frame == BADNODE ) - { - ea_t ea = pfn->start_ea; - int regsize = 0; - - insn_t insn; - while ( ea < pfn->end_ea ) // check for register pushes - { - decode_insn(&insn, ea); - ea += insn.size; //count pushes - if ( (insn.itype == OAK_Dsp_push) && (insn.Op1.type == o_reg) ) - regsize++; - else - break; - } - - ea = pfn->start_ea; - int16 localsize = 0; - while ( ea < pfn->end_ea ) // check for frame creation - { - decode_insn(&insn, ea); - ea += insn.size; // try to detect ADDV #,SP - if ( (insn.itype == OAK_Dsp_addv) && (insn.Op1.type == o_imm) && (insn.Op2.type == o_reg) && (insn.Op2.reg == SP) ) - { - localsize = (uint16)insn.Op1.value; - break; - } - - // if found mov #, rb --> do not create frame - if ( (insn.itype == OAK_Dsp_mov) && (insn.Op1.type == o_imm) && (insn.Op2.type == o_reg) && (insn.Op2.reg == RB) ) - { - std_vars_func = false; - break; - } - - } - - if ( std_vars_func ) - { - pfn->flags |= FUNC_FRAME; - update_func(pfn); - } - - add_frame(pfn, -localsize, (ushort)regsize, 0); - - } - } - return 0; -} - -//---------------------------------------------------------------------- -int idaapi OAK_get_frame_retsize(const func_t * /*pfn*/) -{ - return 1; // 1 'byte' for the return address -} diff --git a/idasdk75/module/oakdsp/ins.cpp b/idasdk75/module/oakdsp/ins.cpp deleted file mode 100644 index afc399c..0000000 --- a/idasdk75/module/oakdsp/ins.cpp +++ /dev/null @@ -1,123 +0,0 @@ - -#include "oakdsp.hpp" - -const instruc_t Instructions[] = -{ - { "", 0 }, // Unknown Operation - { "", 0 }, // cmd need further process - // ALU-ALM subcodes - { "or", CF_USE1|CF_USE2|CF_CHG2 }, //000 Logical Or - { "and", CF_USE1|CF_USE2|CF_CHG2 }, //001 And - { "xor", CF_USE1|CF_USE2|CF_CHG2 }, //010 Exclusive Or - { "add", CF_USE1|CF_USE2|CF_CHG2 }, //011 Add - { "tst0", CF_USE1|CF_USE2 }, //100 Test Bit-field for Zeros - { "tst1", CF_USE1|CF_USE2 }, //101 Test Bit-field for Ones - { "cmp", CF_USE1|CF_USE2 }, //110 Compare - { "sub", CF_USE1|CF_USE2|CF_CHG2 }, //111 Subtract - // ALM subcodes - { "msu", CF_USE1|CF_USE2|CF_CHG2 }, //1000 Multiply and Subtract Previous Product - { "addh", CF_USE1|CF_USE2|CF_CHG2 }, //1001 Add to High Accumulator - { "addl", CF_USE1|CF_USE2|CF_CHG2 }, //1010 Add to Low Accumulator - { "subh", CF_USE1|CF_USE2|CF_CHG2 }, //1011 Subtract from High Accumulator - { "subl", CF_USE1|CF_USE2|CF_CHG2 }, //1100 Subtract from Low Accumulator - { "sqr", CF_USE1|CF_USE2|CF_CHG2 }, //1101 Square - { "sqra", CF_USE1|CF_USE2|CF_CHG2 }, //1110 Square and Accumulate Previous Product - { "cmpu", CF_USE1|CF_USE2 }, //1111 Compare Unsigned - // MODA-MODB subcodes conditional - { "shr", CF_USE1|CF_CHG1 }, //000 Shift Accumulator Right - { "shr4", CF_USE1|CF_CHG1 }, //001 Shift Accumulator Right by 4 Bits - { "shl", CF_USE1|CF_CHG1 }, //010 Shift Accumulator Left - { "shl4", CF_USE1|CF_CHG1 }, //011 Shift Accumulator Left by 4 Bits - { "ror", CF_USE1|CF_CHG1 }, //100 Rotate Accumulator Right through Carry - { "rol", CF_USE1|CF_CHG1 }, //101 Rotate Accumulator Left through Carry - { "clr", CF_CHG1 }, //110 Clear Accumulator - { "", 0 }, //111 Mod Reserved - // MODA subcodes conditional - { "not", CF_USE1|CF_CHG1 }, //1000 Logical Not - { "neg", CF_USE1|CF_CHG1 }, //1001 2's Complement of aX-accumulator - { "rnd", CF_USE1|CF_CHG1 }, //1010 Round Upper 20 Bits of aX-accumulator - { "pacr", CF_USE1|CF_CHG1 }, //1011 Product Move and Round to aX-accumulator - { "clrr", CF_USE1|CF_CHG1 }, //1100 Clear and Round aX-accumulator - { "inc", CF_USE1|CF_CHG1 }, //1101 Increment Accumulator by One - { "dec", CF_USE1|CF_CHG1 }, //1110 Decrement aX-accumulator by One - { "copy", CF_USE1|CF_CHG1 }, //1111 Copy aX-accumulator - // --- - { "norm", CF_USE1|CF_CHG1|CF_USE2 }, //Normalize - { "divs", CF_USE1|CF_USE2|CF_CHG2 }, //Division Step - // ALB subcodes - { "set", CF_USE1|CF_USE2|CF_CHG2 }, //000 Set Bit-field - { "rst", CF_USE1|CF_USE2|CF_CHG2 }, //001 Reset Bit-field - { "chng", CF_USE1|CF_USE2|CF_CHG2 }, //010 Change Bit-field - { "addv", CF_USE1|CF_USE2|CF_CHG2 }, //011 Add Long Immediate Value or Data Memory Location - { "tst0", CF_USE1|CF_USE2 }, //100 Test Bit-field for Zeros - { "tst1", CF_USE1|CF_USE2 }, //101 Test Bit-field for Ones - { "cmpv", CF_USE1|CF_USE2 }, //110 Compare Long Immediate Value to Register or Data Memory Location - { "subv", CF_USE1|CF_USE2|CF_CHG2 }, //111 Subtract Long Immediate Value from a Register or a Data Memory Location - // --- - { "maxd", CF_USE1|CF_CHG1|CF_USE2 }, //Maximum between Data Memory Location and Accumulator - { "max", CF_USE1|CF_CHG1|CF_USE2 }, //Maximum between Two Accumulators - { "min", CF_USE1|CF_CHG1|CF_USE2 }, //Minimum between Two Accumulators - { "lim", CF_USE1|CF_CHG1|CF_USE2 }, //Limit Accumulator (lim aX[, aX]) - // MUL subcodes - { "mpy", CF_USE1|CF_USE2 }, //000 Multiply - { "mpysu", CF_USE1|CF_USE2 }, //001 Multiply Signed by Unsigned - { "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //010 Multiply and Accumulate Previous Product - { "macus", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //011 Multiply Unsigned by Signed and Accumulate Previous Product - { "maa", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //100 Multiply and Accumulate Aligned Previous Product - { "macuu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //101 Multiply Unsigned by Unsigned and Accumulate Previous Product - { "macsu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //110 Multiply Signed by Unsigned and Accumulate Previous Product - { "maasu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //111 Multiply Signed by Unsigned and Accumulate Aligned Previous Product - //--- - { "mpyi", CF_USE1|CF_USE2 }, //Multiply Signed Short Immediate - { "msu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, //Multiply and Subtract Previous Product - { "tstb", CF_USE1|CF_USE2 }, //Test Specific Bit - { "shfc", CF_USE1|CF_USE2|CF_CHG2 }, //Shift Accumulators according to Shift Value Register - { "shfi", CF_USE1|CF_USE2|CF_CHG2|CF_USE3 }, //Shift Accumulators by an Immediate Shift Value - { "exp", CF_USE1|CF_USE2|CF_CHG2 }, //Evaluate the Exponent Value - //--- - { "mov", CF_USE1|CF_CHG2 }, //Move Data - { "movp", CF_USE1|CF_CHG2 }, //Move from Program Memory into Data Memory - { "movs", CF_USE1|CF_CHG2 }, //Move and Shift According to Shift Value Register - { "movsi", CF_USE1|CF_USE2|CF_CHG2|CF_USE3 }, //Move and Shift According to an Immediate Shift Value - { "movr", CF_USE1|CF_CHG2 }, //Move and Round - { "movd", CF_USE1|CF_CHG2 }, //Move from Data Memory into Program Memory - //--- - { "push", CF_USE1 }, //Push Register or Long Immediate Value onto Stack - { "pop", CF_USE1|CF_CHG1 }, //Pop from Stack into Register - //--- - { "swap", CF_USE1 }, //Swap aX- and bX-accumulators - { "banke", CF_USE1 }, //Bank Exchange - { "rep", CF_USE1 }, //Repeat Next Instruction - { "bkrep", CF_USE1|CF_USE2 }, //Block-Repeat - { "break", 0 }, //Break from Block-repeat - //--- - { "br", CF_USE1|CF_JUMP }, //Conditional Branch - { "brr", CF_USE1|CF_JUMP }, //Relative Conditional Branch - { "br", CF_USE1|CF_STOP|CF_JUMP }, //UnConditional Branch - { "brr", CF_USE1|CF_STOP|CF_JUMP }, //Relative UnConditional Branch - { "call", CF_USE1|CF_CALL }, //Conditional Call Subroutine - { "callr", CF_USE1|CF_CALL }, //Relative Conditional Call Subroutine - { "calla", CF_USE1 }, //Call Subroutine at Location Specified by Accumulator - //--- - { "ret", 0 }, //Return Conditionally - { "ret", CF_STOP }, //Return UnConditionally - { "retd", 0 }, //Delayed Return - { "reti", 0 }, //Return from Interrupt Conditionally - { "reti", CF_STOP }, //Return from Interrupt UnConditionally - { "retid", 0 }, //Delayed Return from Interrupt - { "rets", CF_USE1|CF_STOP }, //Return with Short Immediate Parameter - //--- - { "cntx", CF_USE1 }, //Context Switching Store or Restore - { "nop", 0 }, //No operation - { "modr", CF_USE1|CF_USE2 }, //Modify rN - { "dint", 0 }, //Disable Interrupt - { "eint", 0 }, //Enable Interrupt - //--- - { "trap", CF_STOP }, //Software Interrupt - //--- - { "lpg", CF_USE1 }, //Load the Page Bits - { "load", CF_USE1|CF_CHG2 }, //Load Specific Fields into Registers - { "mov", CF_USE1|CF_CHG2|CF_USE3 }, //Move Data, eu -}; - -CASSERT(qnumber(Instructions) == OAK_Dsp_last); diff --git a/idasdk75/module/oakdsp/ins.hpp b/idasdk75/module/oakdsp/ins.hpp deleted file mode 100644 index f1b8af3..0000000 --- a/idasdk75/module/oakdsp/ins.hpp +++ /dev/null @@ -1,128 +0,0 @@ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ -OAK_Dsp_null = 0, // Unknown Operation -OAK_Dsp_proc, // cmd need further process -// ALU-ALM subcodes -OAK_Dsp_or, //000 Logical Or -OAK_Dsp_and, //001 And -OAK_Dsp_xor, //010 Exclusive Or -OAK_Dsp_add, //011 Add -OAK_Dsp_alm_tst0, //100 Test Bit-field for Zeros -OAK_Dsp_alm_tst1, //101 Test Bit-field for Ones -OAK_Dsp_cmp, //110 Compare -OAK_Dsp_sub, //111 Subtract -// ALM subcodes -OAK_Dsp_alm_msu, //1000 Multiply and Subtract Previous Product -OAK_Dsp_addh, //1001 Add to High Accumulator -OAK_Dsp_addl, //1010 Add to Low Accumulator -OAK_Dsp_subh, //1011 Subtract from High Accumulator -OAK_Dsp_subl, //1100 Subtract from Low Accumulator -OAK_Dsp_sqr, //1101 Square -OAK_Dsp_sqra, //1110 Square and Accumulate Previous Product -OAK_Dsp_cmpu, //1111 Compare Unsigned -// MODA-MODB subcodes conditional -OAK_Dsp_shr, //000 Shift Accumulator Right -OAK_Dsp_shr4, //001 Shift Accumulator Right by 4 Bits -OAK_Dsp_shl, //010 Shift Accumulator Left -OAK_Dsp_shl4, //011 Shift Accumulator Left by 4 Bits -OAK_Dsp_ror, //100 Rotate Accumulator Right through Carry -OAK_Dsp_rol, //101 Rotate Accumulator Left through Carry -OAK_Dsp_clr, //110 Clear Accumulator -OAK_Dsp_mod_reserved, //111 Mod Reserved -// MODA subcodes conditional -OAK_Dsp_not, //1000 Logical Not -OAK_Dsp_neg, //1001 2's Complement of aX-accumulator -OAK_Dsp_rnd, //1010 Round Upper 20 Bits of aX-accumulator -OAK_Dsp_pacr, //1011 Product Move and Round to aX-accumulator -OAK_Dsp_clrr, //1100 Clear and Round aX-accumulator -OAK_Dsp_inc, //1101 Increment Accumulator by One -OAK_Dsp_dec, //1110 Decrement aX-accumulator by One -OAK_Dsp_copy, //1111 Copy aX-accumulator -// --- -OAK_Dsp_norm, //Normalize -OAK_Dsp_divs, //Division Step -// ALB subcodes -OAK_Dsp_set, //000 Set Bit-field -OAK_Dsp_rst, //001 Reset Bit-field -OAK_Dsp_chng, //010 Change Bit-field -OAK_Dsp_addv, //011 Add Long Immediate Value or Data Memory Location -OAK_Dsp_alb_tst0, //100 Test Bit-field for Zeros -OAK_Dsp_alb_tst1, //101 Test Bit-field for Ones -OAK_Dsp_cmpv, //110 Compare Long Immediate Value to Register or Data Memory Location -OAK_Dsp_subv, //111 Subtract Long Immediate Value from a Register or a Data Memory Location -// --- -OAK_Dsp_maxd, //Maximum between Data Memory Location and Accumulator -OAK_Dsp_max, //Maximum between Two Accumulators -OAK_Dsp_min, //Minimum between Two Accumulators -OAK_Dsp_lim, //Limit Accumulator (lim aX[, aX]) -// MUL subcodes -OAK_Dsp_mpy, //000 Multiply -OAK_Dsp_mpysu, //001 Multiply Signed by Unsigned -OAK_Dsp_mac, //010 Multiply and Accumulate Previous Product -OAK_Dsp_macus, //011 Multiply Unsigned by Signed and Accumulate Previous Product -OAK_Dsp_maa, //100 Multiply and Accumulate Aligned Previous Product -OAK_Dsp_macuu, //101 Multiply Unsigned by Unsigned and Accumulate Previous Product -OAK_Dsp_macsu, //110 Multiply Signed by Unsigned and Accumulate Previous Product -OAK_Dsp_maasu, //111 Multiply Signed by Unsigned and Accumulate Aligned Previous Product -//--- -OAK_Dsp_mpyi, //Multiply Signed Short Immediate -OAK_Dsp_msu, //Multiply and Subtract Previous Product -OAK_Dsp_tstb, //Test Specific Bit -OAK_Dsp_shfc, //Shift Accumulators according to Shift Value Register -OAK_Dsp_shfi, //Shift Accumulators by an Immediate Shift Value -OAK_Dsp_exp, //Evaluate the Exponent Value -//--- -OAK_Dsp_mov, //Move Data -OAK_Dsp_movp, //Move from Program Memory into Data Memory -OAK_Dsp_movs, //Move and Shift According to Shift Value Register -OAK_Dsp_movsi, //Move and Shift According to an Immediate Shift Value -OAK_Dsp_movr, //Move and Round -OAK_Dsp_movd, //Move from Data Memory into Program Memory -//--- -OAK_Dsp_push, //Push Register or Long Immediate Value onto Stack -OAK_Dsp_pop, //Pop from Stack into Register -//--- -OAK_Dsp_swap, //Swap aX- and bX-accumulators -OAK_Dsp_banke, //Bank Exchange -OAK_Dsp_rep, //Repeat Next Instruction -OAK_Dsp_bkrep, //Block-Repeat -OAK_Dsp_break, //Break from Block-repeat -//--- -OAK_Dsp_br, //Conditional Branch -OAK_Dsp_brr, //Relative Conditional Branch -OAK_Dsp_br_u, //UnConditional Branch -OAK_Dsp_brr_u, //Relative UnConditional Branch -OAK_Dsp_call, //Conditional Call Subroutine -OAK_Dsp_callr, //Relative Conditional Call Subroutine -OAK_Dsp_calla, //Call Subroutine at Location Specified by Accumulator -//--- -OAK_Dsp_ret, //Return Conditionally -OAK_Dsp_ret_u, //Return UnConditionally -OAK_Dsp_retd, //Delayed Return -OAK_Dsp_reti, //Return from Interrupt Conditionally -OAK_Dsp_reti_u, //Return from Interrupt UnConditionally -OAK_Dsp_retid, //Delayed Return from Interrupt -OAK_Dsp_rets, //Return with Short Immediate Parameter -//--- -OAK_Dsp_cntx, //Context Switching Store or Restore -OAK_Dsp_nop, //No operation -OAK_Dsp_modr, //Modify rN -OAK_Dsp_dint, //Disable Interrupt -OAK_Dsp_eint, //Enable Interrupt -//--- -OAK_Dsp_trap, //Software Interrupt -//--- -OAK_Dsp_lpg, //Load the Page Bits -OAK_Dsp_load, //Load Specific Fields into Registers -OAK_Dsp_mov_eu, //Move Data, eu -OAK_Dsp_last, - -}; - -#endif diff --git a/idasdk75/module/oakdsp/makefile b/idasdk75/module/oakdsp/makefile deleted file mode 100644 index 093bf97..0000000 --- a/idasdk75/module/oakdsp/makefile +++ /dev/null @@ -1,48 +0,0 @@ -PROC=oakdsp -CONFIGS=oakdsp.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp oakdsp.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp \ - oakdsp.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp oakdsp.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp oakdsp.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp oakdsp.hpp reg.cpp diff --git a/idasdk75/module/oakdsp/oakdsp.hpp b/idasdk75/module/oakdsp/oakdsp.hpp deleted file mode 100644 index f97c984..0000000 --- a/idasdk75/module/oakdsp/oakdsp.hpp +++ /dev/null @@ -1,228 +0,0 @@ - -#ifndef _OAKDSP_HPP -#define _OAKDSP_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include "../iohandler.hpp" - -//------------------------------------------------------------------ - -#define aux_cc 0x000F // condition code -#define aux_comma_cc 0x0010 // comma before cond -#define aux_iret_context 0x0020 - -#define cmd_cycles insnpref - -#define phtype specflag1 // o_phrase: phrase type -//0 (Rn) -//1 (Rn)+1 -//2 (Rn)-1 -//3 (Rn)+s -//4 (any_reg) - -#define amode specflag2 // addressing options & other -#define amode_short 0x01 -#define amode_long 0x02 -#define amode_x 0x04 // X: -#define amode_p 0x08 // P: -#define amode_neg 0x10 // - -#define amode_signed 0x10 // - if x<0 - - -#define o_textphrase o_idpspec0 // text type -#define o_local o_idpspec1 - -#define textphtype specflag1 // o_texttype: phrase type - -#define text_swap 0x01 -//(a0, b0) -//(a0, b1) -//(a1, b0) -//(a1, b1) -//(a0, b0), (a1, b1) -//(a0, b1), (a1, b0) -//(a0, b0, a1) -//(a0, b1, a1) -//(a1, b0, a0) -//(a1, b1, a0) -//(b0, a0, b1) -//(b0, a1, b1) -//(b1, a0, b0) -//(b1, a1, b0) - -#define text_banke 0x02 -//[r0], [r1], [r4], [cfgi] - -#define text_cntx 0x03 -//s -//r - -#define text_dmod 0x04 -//dmod - -#define text_eu 0x05 -//eu - -#define mix_mode 0x80000000 //Func rrrrr should use both input value and param - -//------------------------------------------------------------------ -#define UAS_GNU 0x0001 // GNU assembler -//------------------------------------------------------------------ -enum RegNo -{ - R0, R1, R2, R3, R4, R5, //DAAU Registers - RB, //Base Register - Y, //Input Register - ST0, ST1, ST2, //Status Registers - P, //Output Register - PC, //Program Counter - SP, //Software Stack Pointer - CFGI, CFGJ, //DAAU Configuration Registers - B0H, B1H, B0L, B1L, //Accumulator B - EXT0, EXT1, EXT2, EXT3, //External registers - A0, A1, A0L, A1L, A0H, A1H, //Accumulator A - LC, //Loop Counter - SV, //Shift Value Register - X, //Input Register - DVM, //Data Value Match Register - MIXP, //Minimal/Maximal Pointer Register - ICR, //Internal Configuration Register - PS, //Product Shifter Control - REPC, //Internal Repeat Counter - B0, B1, //Accumulator B - MODI,MODJ, //Modulo Modifier - STEPI, STEPJ, //Linear (Step) Modifier - PAGE, //Short Direct Addressing Mode Page - vCS, vDS, //virtual registers for code and data segments -}; - - -//------------------------------------------------------------------ -// condition codes -enum cc_t -{ - cc_true, //Always - cc_eq, //Equal to zero Z = 1 - cc_neq, //Not equal to zero Z = 0 - cc_gt, //Greater than zero M = 0 and Z = 0 - cc_ge, //Greater than or equal to zero M = 0 - cc_lt, //Less than zero M =1 - cc_le, //Less than or equal to zero M = 1 or Z = 1 - cc_nn, //Normalized flag is cleared N = 0 - cc_v, //Overflow flag is set V = 1 - cc_c, //Carry flag is set C = 1 - cc_e, //Extension flag is set E = 1 - cc_l, //Limit flag is set L = 1 - cc_nr, //flag is cleared R = 0 - cc_niu0, //Input user pin 0 is cleared - cc_iu0, //Input user pin 0 is set - cc_iu1, //Input user pin 1 is set -}; - -//------------------------------------------------------------------ -void interr(const insn_t &insn, const char *module); - -int idaapi is_align_insn(ea_t ea); -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_sp_based(const insn_t &insn, const op_t &x); -int idaapi OAK_get_frame_retsize(const func_t *pfn); - -int is_jump_func(const func_t *pfn, ea_t *jump_target); -int may_be_func(const insn_t &insn); // can a function start here? - -//------------------------------------------------------------------ -struct opcode_t; - -struct oakdsp_iohandler_t : public iohandler_t -{ - struct oakdsp_t ± - oakdsp_iohandler_t(oakdsp_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual const char *iocallback(const ioports_t &iop, const char *line) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct oakdsp_t); - -struct oakdsp_t : public procmod_t -{ - netnode helper; - oakdsp_iohandler_t ioh = oakdsp_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - ea_t xmem = BADADDR; - int xmemsize = 0x1000; - int procnum = -1; - - op_t *op = nullptr; // current operand - - bool flow = false; - bool delayed = false; - int cycles = 0; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const ioport_t *find_port(ea_t address); - void create_xmem(void); - void select_device(const char *dname, int lrespect_info); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - ea_t add_data_segm(size_t size, int offset, const char *name) const; - - inline void opreg(int reg); - void make_o_mem(const insn_t &insn); - bool rrrrr(insn_t &, int value, int param); - bool sdirect(insn_t &insn, int value, int); - bool ldirect(insn_t &insn, int value,int); - bool A(insn_t &insn, int value,int); - bool B(insn_t &insn, int value,int); - bool mmnnn(insn_t &, int value,int); - bool nnn(insn_t &insn, int value, int); - bool ALU_ALM(insn_t &insn, int value, int param); - bool ALB(insn_t &insn, int value, int); - bool MUL(insn_t &insn, int value, int param); - bool MODA_B(insn_t &insn, int value, int param); - bool s_Imm(insn_t &insn, int value, int); - bool s_ImmS(insn_t &, int value, int param); - bool l_Imm(insn_t &insn, int value, int); - bool rb_rel_short(insn_t &, int value, int); - bool rb_rel_long(insn_t &insn, int value, int); - bool Cond(insn_t &insn, int value, int param); - bool xe_xt(insn_t &insn, int value, int param); - bool lim_xx(insn_t &, int value, int); - bool rJ_rI(insn_t &, int value,int param); - bool rI(insn_t &, int value,int); - bool AB(insn_t &, int value,int); - bool ABLH(insn_t &, int value,int); - bool indir_reg(insn_t &, int value,int param); - bool laddr_pgm(insn_t &insn, int value,int); - bool addr_rel_pgm(insn_t &insn, int value, int); - bool ext_XX(insn_t &insn, int value, int); - bool context(insn_t &insn, int value,int); - bool swap(insn_t &, int value,int); - bool banke(insn_t &, int value,int); - bool cntx(insn_t &, int value,int); - bool dmod(insn_t &, int value,int); - bool eu(insn_t &, int,int); - bool use_table(insn_t &insn, const opcode_t &ptr, uint code, int start, int end); - void reset_ops(insn_t &insn); - int ana(insn_t *_insn); - - void init_emu(void); - ea_t calc_mem(const insn_t &insn, const op_t &x) const; - int is_sane_insn(const insn_t &insn, int nocrefs) const; - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); - int emu(const insn_t &insn); - - void oakdsp_header(outctx_t &ctx); - void oakdsp_assumes(outctx_t &ctx); - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void oakdsp_segstart(outctx_t &ctx, segment_t *Srange) const; - void oakdsp_segend(outctx_t &ctx, segment_t *Srange) const; - void oakdsp_footer(outctx_t &ctx) const; - void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; -}; -#endif // _OAKDSP_HPP diff --git a/idasdk75/module/oakdsp/out.cpp b/idasdk75/module/oakdsp/out.cpp deleted file mode 100644 index 3013806..0000000 --- a/idasdk75/module/oakdsp/out.cpp +++ /dev/null @@ -1,511 +0,0 @@ - -#include "oakdsp.hpp" -#include <frame.hpp> -#include <segregs.hpp> -#include <struct.hpp> - -//-------------------------------------------------------------------------- -static const char *const cc_text[] = -{ - "", //Always - "eq", //Equal to zero Z = 1 - "neq", //Not equal to zero Z = 0 - "gt", //Greater than zero M = 0 and Z = 0 - "ge", //Greater than or equal to zero M = 0 - "lt", //Less than zero M =1 - "le", //Less than or equal to zero M = 1 or Z = 1 - "nn", //Normalized flag is cleared N = 0 - "v", //Overflow flag is set V = 1 - "c", //Carry flag is set C = 1 - "e", //Extension flag is set E = 1 - "l", //Limit flag is set L = 1 - "nr", //flag is cleared R = 0 - "niu0", //Input user pin 0 is cleared - "iu0", //Input user pin 0 is set - "iu1", //Input user pin 1 is set - -}; - - -static const char *const formats[] = -{ - COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL), - COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")+1", SCOLOR_SYMBOL), - COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")-1", SCOLOR_SYMBOL), - COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")+s", SCOLOR_SYMBOL), - COLSTR("(", SCOLOR_SYMBOL) COLSTR("reg", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL), -}; - -//0 (Rn) -//1 (Rn)+1 -//2 (Rn)-1 -//3 (Rn)+s -//4 (any_reg) - -static const char *const formats2[] = -{ - COLSTR("(", SCOLOR_SYMBOL) COLSTR("rb+#", SCOLOR_REG), - COLSTR("#", SCOLOR_REG), -}; -//0 (rb + #) -//1 # - -static const char *const swap_formats[] = -{ - COLSTR("(a0, b0)", SCOLOR_REG), - COLSTR("(a0, b1)", SCOLOR_REG), - COLSTR("(a1, b0)", SCOLOR_REG), - COLSTR("(a1, b1)", SCOLOR_REG), - COLSTR("(a0, b0), (a1, b1)", SCOLOR_REG), - COLSTR("(a0, b1), (a1, b0)", SCOLOR_REG), - COLSTR("(a0, b0, a1)", SCOLOR_REG), - COLSTR("(a0, b1, a1)", SCOLOR_REG), - COLSTR("(a1, b0, a0)", SCOLOR_REG), - COLSTR("(a1, b1, a0)", SCOLOR_REG), - COLSTR("(b0, a0, b1)", SCOLOR_REG), - COLSTR("(b0, a1, b1)", SCOLOR_REG), - COLSTR("(b1, a0, b0)", SCOLOR_REG), - COLSTR("(b1, a1, b0)", SCOLOR_REG), -}; - -//(a0, b0) -//(a0, b1) -//(a1, b0) -//(a1, b1) -//(a0, b0), (a1, b1) -//(a0, b1), (a1, b0) -//(a0, b0, a1) -//(a0, b1, a1) -//(a1, b0, a0) -//(a1, b1, a0) -//(b0, a0, b1) -//(b0, a1, b1) -//(b1, a0, b0) -//(b1, a1, b0) - -//---------------------------------------------------------------------- -class out_oakdsp_t : public outctx_t -{ - out_oakdsp_t(void) = delete; // not used - oakdsp_t &pm() { return *static_cast<oakdsp_t *>(procmod); } -public: - void outreg(int r) { out_register(ph.reg_names[r]); } - bool out_port_address(ea_t addr); - void out_bad_address(ea_t addr); - void out_address(ea_t ea, const op_t &x); - void out_ip_rel(int displ) - { - out_printf(COLSTR("%s+", SCOLOR_SYMBOL) COLSTR("%d", SCOLOR_NUMBER), - ash.a_curip, displ); - } - bool out_operand(const op_t &x); - void out_insn(void); -}; -CASSERT(sizeof(out_oakdsp_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_oakdsp_t) - -//---------------------------------------------------------------------- -bool out_oakdsp_t::out_port_address(ea_t addr) -{ - const ioport_t *port = pm().find_port(addr); - if ( port != NULL && !port->name.empty() ) - { - out_line(port->name.c_str(), COLOR_IMPNAME); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -void out_oakdsp_t::out_bad_address(ea_t addr) -{ - if ( !out_port_address(addr) ) - { - out_tagon(COLOR_ERROR); - out_btoa(addr, 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } -} - -//---------------------------------------------------------------------- -void out_oakdsp_t::out_address(ea_t ea, const op_t &x) -{ - if ( !out_name_expr(x, ea,/* ea */ BADADDR) ) - { - out_tagon(COLOR_ERROR); - out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16); - out_printf(" (ea = %a)", ea); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - -} - -//---------------------------------------------------------------------- -bool out_oakdsp_t::out_operand(const op_t & x) -{ - ea_t ea; - char buf[MAXSTR]; - - if ( x.type == o_imm ) - out_symbol('#'); - - switch ( x.type ) - { - case o_void: - return 0; - - case o_imm: - if ( x.amode & amode_signed ) - out_value(x, OOF_SIGNED|OOFW_IMM); - else - out_value(x, OOFS_IFSIGN|OOFW_IMM); - break; - - case o_reg: - outreg(x.reg); - break; - - case o_mem: - // no break; - ea = pm().calc_mem(insn, x); - if ( ea != BADADDR ) - out_address(ea, x); - else - { - out_tagon(COLOR_ERROR); - out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16); - out_tagoff(COLOR_ERROR); - } - break; - - case o_near: - { - ea_t lea = pm().calc_mem(insn, x); - // xmem ioports - if ( x.amode & (amode_x) && out_port_address(x.addr) ) - { - const ioport_t *port = pm().find_port(x.addr); - if ( port != NULL && !has_user_name(get_flags(lea)) ) - set_name(lea, port->name.c_str(), SN_NODUMMY); - break; - } - if ( lea == insn.ea+insn.size ) - out_ip_rel(insn.size); - else if ( !out_name_expr(x, lea, x.addr) ) - out_bad_address(x.addr); - } - break; - - case o_phrase: - { - if ( x.phtype < 4 ) - { - nowarn_qsnprintf(buf, sizeof(buf), formats[uchar(x.phtype)], x.phrase); - out_colored_register_line(buf); - } - if ( x.phtype == 4 ) - { - out_symbol('('); - outreg(x.reg); - out_symbol(')'); - } - } - break; - - case o_local: - { - out_colored_register_line(formats2[uchar(x.phtype)]); - out_value(x, OOF_SIGNED|OOF_ADDR); - if ( x.phtype == 0 ) - out_symbol(')'); - break; - } - - case o_textphrase: - { - switch ( x.textphtype ) - { - case text_swap: - out_line(swap_formats[x.phrase], COLOR_REG); - break; - - case text_banke: - - int comma; - char r0[10], r1[10], r4[10], cfgi[10]; - comma = 0; - - - r0[0]=r1[0]=r4[0]=cfgi[0]='\0'; - - if ( x.phrase & 0x01 ) //cfgi - { - qsnprintf(cfgi, sizeof(cfgi), "cfgi"); - comma = 1; - } - - if ( x.phrase & 0x02 ) //r4 - { - qsnprintf(r4, sizeof(r4), "r4%s", (comma?", ":"")); - comma = 1; - } - - if ( x.phrase & 0x04 ) //r1 - { - qsnprintf(r1, sizeof(r1), "r1%s", (comma?", ":"")); - comma = 1; - } - - if ( x.phrase & 0x08 ) //r0 - qsnprintf(r0, sizeof(r0), "r0%s", (comma?", ":"")); - - qsnprintf(buf, sizeof(buf), "%s%s%s%s", r0, r1, r4, cfgi); - out_line(buf, COLOR_REG); - - break; - case text_cntx: - out_symbol(x.phrase ? 'r': 's'); - break; - case text_dmod: - if ( x.phrase ) - qsnprintf(buf, sizeof(buf), " no modulo"); - else - qsnprintf(buf, sizeof(buf), " modulo"); - - out_line(buf, COLOR_REG); - - break; - case text_eu: - qsnprintf(buf, sizeof(buf), " eu"); - out_line(buf, COLOR_REG); - break; - } - - } - break; - - - default: - interr(insn, "out"); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -void out_oakdsp_t::out_insn(void) -{ - out_mnemonic(); - - bool comma = out_one_operand(0); - if ( insn.Op2.type != o_void ) - { - if ( comma ) - out_symbol(','); - out_one_operand(1); - } - if ( insn.Op3.type != o_void ) - { - out_symbol(','); - out_one_operand(2); - } - out_immchar_cmts(); - - switch ( insn.itype ) - { - case OAK_Dsp_callr: - case OAK_Dsp_ret: - case OAK_Dsp_br: - case OAK_Dsp_call: - case OAK_Dsp_reti: - case OAK_Dsp_brr: - case OAK_Dsp_shfc: - case OAK_Dsp_shr: - case OAK_Dsp_shr4: - case OAK_Dsp_shl: - case OAK_Dsp_shl4: - case OAK_Dsp_ror: - case OAK_Dsp_rol: - case OAK_Dsp_clr: - case OAK_Dsp_not: - case OAK_Dsp_neg: - case OAK_Dsp_rnd: - case OAK_Dsp_pacr: - case OAK_Dsp_clrr: - case OAK_Dsp_inc: - case OAK_Dsp_dec: - case OAK_Dsp_copy: - case OAK_Dsp_maxd: - case OAK_Dsp_max: - case OAK_Dsp_min: - char buf[MAXSTR]; - qsnprintf(buf, - sizeof(buf), - "%s%s%s", - (insn.auxpref & aux_comma_cc) ? ", ": "", - cc_text[insn.auxpref & aux_cc], - (insn.auxpref & aux_iret_context) ? ", context": ""); - out_line(buf, COLOR_REG); - break; - } - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Srange) could be made const -void oakdsp_t::oakdsp_segstart(outctx_t &ctx, segment_t *Srange) const -{ - ea_t ea = ctx.insn_ea; - if ( is_spec_segm(Srange->type) ) - return; - - qstring sname; - qstring sclas; - get_segm_name(&sname, Srange); - get_segm_class(&sclas, Srange); - - if ( ash.uflag & UAS_GNU ) - { - const char *const predefined[] = - { - ".text", // Text section - ".data", // Data sections - ".rdata", - ".comm", - }; - - if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) ) - ctx.gen_printf(DEFAULT_INDENT, - COLSTR(".section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), - sname.c_str(), - ash.cmnt, - sclas.c_str()); - } - else - { - validate_name(&sname, VNT_IDENT); - if ( sname == "XMEM" ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), ea-get_segm_base(Srange)); - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s %c:%s", SCOLOR_ASMDIR), - ash.origin, - qtolower(sname[0]), - buf); - } - else - { - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), - sname.c_str(), - ash.cmnt, - sclas.c_str()); - } - } -} - -//-------------------------------------------------------------------------- -void oakdsp_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) -{ - if ( reg == ph.reg_data_sreg ) - return; - if ( value != BADADDR ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), value); - ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); - } - else - { - ctx.gen_cmt_line("drop %s", ph.reg_names[reg]); - } -} - -//-------------------------------------------------------------------------- -// function to produce assume directives -void oakdsp_t::oakdsp_assumes(outctx_t &ctx) -{ - ea_t ea = ctx.insn_ea; - segment_t *seg = getseg(ea); - if ( seg == NULL || (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 ) - return; - bool seg_started = (ea == seg->start_ea); - - for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) - { - if ( i == ph.reg_code_sreg ) - continue; - sreg_range_t sra; - if ( !get_sreg_range(&sra, ea, i) ) - continue; - sel_t now = get_sreg(ea, i); - if ( seg_started || sra.start_ea == ea ) - { - sreg_range_t prev_sra; - bool prev_exists = get_sreg_range(&prev_sra, ea - 1, i); - if ( seg_started || (prev_exists && get_sreg(prev_sra.start_ea, i) != now) ) - print_segment_register(ctx, i, now); - } - } -} - -//-------------------------------------------------------------------------- -void oakdsp_t::oakdsp_segend(outctx_t &ctx, segment_t *Srange) const -{ - if ( !is_spec_segm(Srange->type) && (ash.uflag & UAS_GNU) == 0 ) - { - qstring sname; - get_segm_name(&sname, Srange); - if ( sname != "XMEM" ) - ctx.gen_printf(DEFAULT_INDENT, "endsec"); - } -} - -//-------------------------------------------------------------------------- -void oakdsp_t::oakdsp_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL, NULL, ioh.device.c_str()); -} - -//-------------------------------------------------------------------------- -void oakdsp_t::oakdsp_footer(outctx_t &ctx) const -{ - qstring nbuf = get_colored_name(inf_get_start_ea()); - const char *name = nbuf.c_str(); - const char *end = ash.end; - if ( end == NULL ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name); - else - ctx.gen_printf(DEFAULT_INDENT, - COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), - ash.end, ash.cmnt, name); -} - -//-------------------------------------------------------------------------- -void oakdsp_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const -{ - char sign = ' '; - if ( v < 0 ) - { - sign = '-'; - v = -v; - } - - qstring name = get_member_name(mptr->id); - - char vstr[MAX_NUMBUF]; - btoa(vstr, sizeof(vstr), v); - ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) " " - COLSTR("%c%s",SCOLOR_DNUM) - COLSTR(",",SCOLOR_SYMBOL) " " - COLSTR("%s",SCOLOR_LOCNAME), - ash.a_equ, - sign, - vstr, - name.c_str()); -} diff --git a/idasdk75/module/oakdsp/reg.cpp b/idasdk75/module/oakdsp/reg.cpp deleted file mode 100644 index 4437de7..0000000 --- a/idasdk75/module/oakdsp/reg.cpp +++ /dev/null @@ -1,566 +0,0 @@ - -#include "oakdsp.hpp" -#include <diskio.hpp> -#include <segregs.hpp> - - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "r0", "r1", "r2", "r3", "r4", "r5", //DAAU Registers - "rb", //Base Register - "y", //Input Register - "st0", "st1", "st2", //Status Registers - "p", //Output Register - "pc", //Program Counter - "sp", //Software Stack Pointer - "cfgi", "cfgj", //DAAU Configuration Registers - "b0h", "b1h", "b0l", "b1l", //Accumulator B - "ext0","ext1", "ext2", "ext3", //External registers - "a0", "a1", "a0l", "a1l", "a0h", "a1h", //Accumulator A - "lc", //Loop Counter - "sv", //Shift Value Register - "x", //Input Register - "dvm", //Data Value Match Register - "mixp", //Minimal/Maximal Pointer Register - "icr", //Internal Configuration Register - "ps", //Product Shifter Control - "repc", //Internal Repeat Counter - "b0", "b1", //Accumulator B - "modi", "modj", //Modulo Modifier - "stepi","stepj", //Linear (Step) Modifier - "page", //Short Direct Addressing Mode Page - "cs","ds", //virtual registers for code and data segments -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0x45, 0xc0 }; -static const uchar retcode_1[] = { 0x45, 0xd0 }; -static const uchar retcode_2[] = { 0x45, 0x80 }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Dsp Group OAK DSP Assembler -//----------------------------------------------------------------------- -static const asm_t oakasm = -{ - ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASB_BINF2 // %01010 - |ASO_OCTF1 // 0123 - |AS_COLON - |AS_N2CHR - |AS_NCMAS - |AS_ONEDUP, - 0, - "Dsp Group OAK DSP Assembler", - 0, - NULL, // header lines - "org", // org - "end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - "dc", // ascii string directive - "dcb", // byte directive - "dc", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "*", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - "global", // "public" name keyword - NULL, // "weak" name keyword - "xref", // "extrn" name keyword - // .extern directive requires an explicit object size - NULL, // "comm" (communal variable) - NULL, // const char *(*get_type_name)(int32 flag,uint32 id); - NULL, // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_BYTE1CHAR,// One symbol per processor byte -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gas = -{ - AS_ASCIIC - |ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASB_BINF3 // 0b01010 - |ASO_OCTF1 // 0123 - |AS_COLON - |AS_N2CHR - |AS_NCMAS - |AS_ONEDUP, - UAS_GNU, - "GNU-like hypothetical assembler", - 0, - NULL, // header lines - ".org", // org - NULL, // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".byte", // byte directive - ".short", // word directive - ".long", // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - "=", // equ - NULL, // 'seg' prefix (example: push seg seg001) - ".", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".extern", // "extrn" name keyword - // .extern directive requires an explicit object size - ".comm", // "comm" (communal variable) - NULL, // const char *(*get_type_name)(int32 flag,uint32 id); - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "mod", // mod - "and", // and - "or", // or - "xor", // xor - "not", // not - "shl", // shl - "shr", // shr - NULL, // sizeof - AS2_BYTE1CHAR,// One symbol per processor byte - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt -}; - -static const asm_t *const asms[] = { &oakasm, &gas, NULL }; - -//---------------------------------------------------------------------- -ea_t oakdsp_t::add_data_segm(size_t size, int offset, const char *name) const -{ - segment_t s; - s.start_ea = free_chunk(0x1000000, size, 0xF); - s.end_ea = s.start_ea + size; - s.sel = allocate_selector((s.start_ea-offset) >> 4); - s.type = SEG_DATA; - s.bitness = ph.dnbits > 16; - add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE); - return s.start_ea - offset; -} - -inline ea_t get_start(const segment_t *s) -{ return s ? s->start_ea : BADADDR; } - -//-------------------------------------------------------------------------- -const char *oakdsp_iohandler_t::iocallback(const ioports_t &lports, const char *line) -{ - int size; - if ( qsscanf(line, "XMEMSIZE = %i", &size) == 1 ) - { - pm.xmemsize = size; - pm.ioh.deviceparams.sprnt("XMEM=0x%X", pm.xmemsize); - return NULL; - } - return standard_callback(lports, line); -} - -const ioport_t *oakdsp_t::find_port(ea_t address) -{ - return find_ioport(ioh.ports, address); -} - -//-------------------------------------------------------------------------- -void oakdsp_t::create_xmem(void) -{ - if ( xmem == BADADDR ) - xmem = add_data_segm(xmemsize, 0, "XMEM"); -} - -//-------------------------------------------------------------------------- -void oakdsp_t::select_device(const char *dname, int lrespect_info) -{ - ioh.set_device_name(dname, lrespect_info); - - create_xmem(); - - for ( int i=0; i < ioh.ports.size(); i++ ) - { - const ioport_t &p = ioh.ports[i]; - ea_t ea = xmem + p.address; - const char *name = p.name.c_str(); - ea_t nameea = get_name_ea(BADADDR, name); - if ( nameea != ea ) - { - set_name(nameea, ""); - if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) - set_cmt(ea, name, 0); - } - } -} - -//-------------------------------------------------------------------------- -const char *oakdsp_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( choose_ioport_device(&ioh.device, cfgfile) ) - select_device(ioh.device.c_str(), IORESP_INT); - return IDPOPT_OK; -} - -//----------------------------------------------------------------------- -// We always return "yes" because of the messy problem that -// there are additional operands with a wrong operand number (always 1) -static bool idaapi can_have_type(const op_t &) -{ - return true; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::savebase: - case idb_event::closebase: - pm.helper.supset(0, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new oakdsp_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi oakdsp_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ oakdsp"); - init_emu(); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: // new file loaded - { - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - select_device(ioh.device.c_str(), IORESP_AREA|IORESP_INT); - else - create_xmem(); - - segment_t *s0 = get_first_seg(); - if ( s0 != NULL ) - { - segment_t *s1 = get_next_seg(s0->start_ea); - for ( int i = PAGE; i <= vDS; i++ ) - { - set_default_sreg_value(s0, i, BADSEL); - set_default_sreg_value(s1, i, BADSEL); - } - } - } - break; - - case processor_t::ev_ending_undo: - procnum = ph.get_proc_index(); - //fall through - case processor_t::ev_oldfile: // old file loaded - xmem = get_start(get_segm_by_name("XMEM")); - { - char dev[MAXSTR]; - char *pdev = helper.supstr(0, dev, sizeof(dev)) > 0 ? dev : NULL; - select_device(pdev, IORESP_NONE); - } - break; - - case processor_t::ev_newprc: // new processor type - { - int n = va_arg(va, int); - // bool keep_cfg = va_argi(va, bool); - if ( procnum == -1 ) - { - procnum = n; - } - else if ( procnum != n ) // can't change the processor type - { // after the initial set up - warning("Sorry, processor type cannot be changed after loading"); - code = -1; - break; - } - } - break; - - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - int nocrefs = va_arg(va, int); - return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1; - } - - case processor_t::ev_may_be_func: - // can a function start here? - // arg: instruction - // returns: probability 0..100 - { - const insn_t *insn = va_arg(va, insn_t *); - return may_be_func(*insn); - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - oakdsp_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - oakdsp_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - oakdsp_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - oakdsp_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - oakdsp_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *_op = va_arg(va, const op_t *); - return out_opnd(*ctx, *_op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *_op = va_arg(va, const op_t *); - return can_have_type(*_op) ? 1 : -1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - const insn_t *insn = va_arg(va, const insn_t *); - const op_t *_op = va_arg(va, const op_t *); - *mode = is_sp_based(*insn, *_op); - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = OAK_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_gen_stkvar_def: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const member_t *mptr = va_arg(va, const member_t *); - sval_t v = va_arg(va, sval_t); - gen_stkvar_def(*ctx, mptr, v); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "Atmel OAK DSP:" - -static const char *const shnames[] = -{ - "oakdsp", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Dsp Group OAK DSP", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_OAKDSP, // id - // flag - PRN_HEX - | PR_SEGS // has segment registers - | PR_ALIGN // data items must be aligned - | PR_BINMEM // module knows about memory organization - | PR_ALIGN_INSN, // allow align instructions - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 16, // 16 bits in a byte for code segments - 16, // 16 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - PAGE, // first - vDS, // last - 1, // size of a segment register - vCS, vDS, - - NULL, // No known code start sequences - retcodes, - - OAK_Dsp_null, - OAK_Dsp_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - OAK_Dsp_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/pdp11/ana.cpp b/idasdk75/module/pdp11/ana.cpp deleted file mode 100644 index 9e6c886..0000000 --- a/idasdk75/module/pdp11/ana.cpp +++ /dev/null @@ -1,403 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "pdp.hpp" - -//---------------------------------------------------------------------- -static void loadoper(insn_t &insn, op_t *Op, uint16 nibble) -{ - ushort base; - switch ( nibble ) - { - case 027: - { - flags_t F1 = get_flags(insn.ea); - flags_t F2 = get_flags(insn.ea+insn.size); - Op->type = o_imm; - Op->ill_imm = is_head(F1) ? !is_tail(F2) : is_head(F2); - Op->offb = (uchar)insn.size; - Op->value = insn.get_next_word(); - } - break; - case 037: - case 077: - case 067: - Op->type = o_mem; - Op->offb = (uchar)insn.size; - base = insn.get_next_word(); - if ( (Op->phrase = nibble) != 037 ) - base += (short)(insn.ip + insn.size); - Op->addr16 = base; - break; - default: - if ( (nibble & 070) == 0 ) - { - Op->type = o_reg; - Op->reg = nibble; - } - else - { - Op->phrase = nibble; - if ( nibble < 060 ) - { - Op->type = o_phrase; - } - else - { - Op->type = o_displ; - Op->offb = (uchar)insn.size; - Op->addr16 = insn.get_next_word(); - } - } - break; - } -} - -//---------------------------------------------------------------------- -void pdp11_t::jmpoper(insn_t &insn, op_t *Op, uint16 nibble) -{ - loadoper(insn, Op, nibble); - if ( Op->type == o_mem && Op->phrase != 077 ) - Op->type = o_near; - if ( Op->type == o_near - && Op->addr16 >= ml.ovrcallbeg - && Op->addr16 <= ml.ovrcallend ) - { - uint32 trans = (uint32)ovrtrans.altval(Op->addr16); -// msg("addr=%o, trans=%lo\n", Op->addr16, trans); - if ( trans != 0 ) - { - segment_t *S = getseg(trans); - if ( S != NULL ) - { - Op->type = o_far; - Op->segval = (uint16)S->sel; - Op->addr16 = (ushort)(trans - to_ea(Op->segval,0)); - } - } - } -} - -//---------------------------------------------------------------------- -int pdp11_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - - static const char twoop[5] = { pdp_mov, pdp_cmp, pdp_bit, pdp_bic, pdp_bis }; - static const char onecmd[12] = - { - pdp_clr, pdp_com, pdp_inc, pdp_dec, - pdp_neg, pdp_adc, pdp_sbc, pdp_tst, pdp_ror, pdp_rol, - pdp_asr, pdp_asl - }; - static const char cc2com[8] = - { - pdp_bpl, pdp_bmi, pdp_bhi, pdp_blos, - pdp_bvc, pdp_bvs, pdp_bcc, pdp_bcs - }; - - if ( insn.ip & 1 ) - return 0; - - insn.Op1.dtype = insn.Op2.dtype = dt_word; -// insn.bytecmd = 0; - - uint code = insn.get_next_word(); - - uchar nibble0 = (code & 077); - uchar nibble1 = (code >> 6 ) & 077; - uchar nibble2 = (code >> 12) & 017; - uchar nib1swt = nibble1 >> 3; - - switch ( nibble2 ) - { - case 017: - if ( nibble1 == 0 ) - { - switch ( nibble0 ) - { - case 0: insn.itype = pdp_cfcc; break; - case 1: insn.itype = pdp_setf; break; - case 2: insn.itype = pdp_seti; break; - case 011: insn.itype = pdp_setd; break; - case 012: insn.itype = pdp_setl; break; - default: return 0; - } - break; - } - loadoper(insn, &insn.Op1, nibble0); - if ( nib1swt != 0 ) - { - static const char fpcom2[14] = - { - pdp_muld, pdp_modd, pdp_addd, - pdp_ldd, pdp_subd, pdp_cmpd, pdp_std, pdp_divd, pdp_stexp, - pdp_stcdi, pdp_stcdf, pdp_ldexp, pdp_ldcif, pdp_ldcfd - }; - insn.Op2.type = o_fpreg; - insn.Op2.reg = (nibble1 & 3); - insn.Op2.dtype = dt_double; - int idx = (nibble1 >> 2) - 2; - QASSERT(10084, idx >= 0 && idx < qnumber(fpcom2)); - insn.itype = fpcom2[idx]; - if ( insn.itype != pdp_ldexp && insn.itype != pdp_stexp ) - { - if ( insn.Op1.type == o_reg ) - insn.Op1.type = o_fpreg; - if ( insn.itype != pdp_stcdi && insn.itype != pdp_ldcif ) - insn.Op1.dtype = dt_double; - } - if ( insn.itype == pdp_std - || insn.itype == pdp_stexp - || insn.itype == pdp_stcdi - || insn.itype == pdp_stcdf ) - { - op_t temp; - temp = insn.Op2; - insn.Op2 = insn.Op1; - insn.Op1 = temp; - insn.Op1.n = 0; - insn.Op2.n = 1; - } - } - else - { - static const char fpcom1[7] = - { - pdp_ldfps, pdp_stfps, pdp_stst, pdp_clrd, - pdp_tstd, pdp_absd, pdp_negd - }; - if ( nibble1 >= 4 ) - { - insn.Op1.dtype = insn.Op2.dtype = dt_double; - if ( insn.Op1.type == o_reg ) - insn.Op1.type = o_fpreg; - } - QASSERT(10085, (nibble1-1) >= 0 && nibble1-1 < qnumber(fpcom1)); - insn.itype = fpcom1[nibble1 - 1]; //lint !e676 possibly indexing before the beginning of an allocation - } - break; - - case 7: - switch ( nib1swt ) - { - case 6: // CIS - return 0; - case 5: // FIS - { - static const char ficom[4] = { pdp_fadd, pdp_fsub, pdp_fmul, pdp_fdiv }; - if ( nibble1 != 050 || nibble0 >= 040 ) - return 0; - insn.Op1.type = o_reg; - insn.Op1.reg = nibble0 & 7; - insn.itype = ficom[nibble0 >> 3]; - break; - } - case 7: // SOB - insn.itype = pdp_sob; - insn.Op1.type = o_reg; - insn.Op1.reg = nibble1 & 7; - insn.Op2.type = o_near; - insn.Op2.phrase = 0; - insn.Op2.addr16 = (ushort)(insn.ip + 2 - (2*nibble0)); - break; - default: - { - static const char eiscom[5] = { pdp_mul, pdp_div, pdp_ash, pdp_ashc, pdp_xor }; - insn.Op2.type = o_reg; - insn.Op2.reg = nibble1 & 7; - loadoper(insn, &insn.Op1, nibble0); - insn.itype = eiscom[nib1swt]; - break; - } - } - break; - - case 016: - insn.itype = pdp_sub; - goto twoopcmd; - case 6: - insn.itype = pdp_add; - goto twoopcmd; - default: //Normal 2 op - insn.itype = twoop[(nibble2 & 7) - 1]; - insn.bytecmd = ((nibble2 & 010) != 0); -twoopcmd: - loadoper(insn, &insn.Op1, nibble1); - loadoper(insn, &insn.Op2, nibble0); - break; - - case 010: - if ( nibble1 >= 070 ) - return 0; - if ( nibble1 >= 064 ) - { - static const char mt1cmd[4] = { pdp_mtps, pdp_mfpd, pdp_mtpd, pdp_mfps }; - insn.itype = mt1cmd[nibble1 - 064]; - loadoper(insn, &insn.Op1, nibble0); - break; - } - if ( nibble1 >= 050 ) - { - insn.bytecmd = 1; -oneoper: - loadoper(insn, &insn.Op1, nibble0); - insn.itype = onecmd[nibble1 - 050]; - break; - } - if ( nibble1 >= 040 ) - { - insn.Op1.type = o_number; // EMT/TRAP - insn.Op1.value = code & 0377; - insn.itype = (nibble1 >= 044) ? pdp_trap : pdp_emt; - break; - } - insn.itype = cc2com[nibble1 >> 2]; -condoper: - insn.Op1.type = o_near; - insn.Op1.phrase = 0; - insn.Op1.addr16 = (ushort)(insn.ip + insn.size + (2*(short)((char)code))); - break; - - case 0: - if ( nibble1 >= 070 ) - return 0; - if ( nibble1 > 064 ) - { - static const char mt2cmd[3] = { pdp_mfpi, pdp_mtpi, pdp_sxt }; - insn.itype = mt2cmd[nibble1 - 065]; - loadoper(insn, &insn.Op1, nibble0); - break; - } - if ( nibble1 == 064 ) - { - insn.itype = pdp_mark; - insn.Op1.type = o_number; - insn.Op1.value = nibble0; - break; - } - if ( nibble1 >= 050 ) - goto oneoper; - if ( nibble1 >= 040 ) - { - if ( (nibble1 & 7) == 7 ) - { - insn.itype = pdp_call; - jmpoper(insn, &insn.Op1, nibble0); - } - else - { - insn.itype = pdp_jsr; - insn.Op1.type = o_reg; - insn.Op1.reg = nibble1 & 7; - jmpoper(insn, &insn.Op2, nibble0); - } - break; - } - switch ( nibble1 ) - { - case 3: - insn.itype = pdp_swab; - loadoper(insn, &insn.Op1, nibble0); - break; - case 1: - insn.itype = pdp_jmp; - jmpoper(insn, &insn.Op1, nibble0); - break; - case 2: - if ( nibble0 == 7 ) - { - insn.itype = pdp_return; - break; - } - if ( nibble0 < 7 ) - { - insn.itype = pdp_rts; - insn.Op1.type = o_reg; - insn.Op1.reg = nibble0; - break; - } - if ( nibble0 < 030 ) - return 0; - if ( nibble0 < 040 ) - { - insn.itype = pdp_spl; - insn.Op1.value = nibble0 & 7; - insn.Op1.type = o_number; - break; - } - switch ( nibble0 & 037 ) - { - case 000: insn.itype = pdp_nop; break; - case 001: insn.itype = pdp_clc; break; - case 002: insn.itype = pdp_clv; break; - case 004: insn.itype = pdp_clz; break; - case 010: insn.itype = pdp_cln; break; - case 017: insn.itype = pdp_ccc; break; - case 021: insn.itype = pdp_sec; break; - case 022: insn.itype = pdp_sev; break; - case 024: insn.itype = pdp_sez; break; - case 030: insn.itype = pdp_sen; break; - case 037: insn.itype = pdp_scc; break; - default: - insn.itype = pdp_compcc; - insn.Op1.phrase = nibble0 & 037; - break; - } - break; - case 0: - { - static const char misc0[16] = - { - pdp_halt, pdp_wait, pdp_rti, pdp_bpt, - pdp_iot, pdp_reset, pdp_rtt, pdp_mfpt - }; - if ( nibble0 > 7 ) - return 0; - insn.itype = misc0[nibble0]; - break; - } - default: // >=4 - { - static const char lcc2com[7] = - { - pdp_br, pdp_bne, pdp_beq, pdp_bge, - pdp_blt, pdp_bgt, pdp_ble - }; - insn.itype = lcc2com[(nibble1 >> 2) - 1]; - goto condoper; - } - } - break; - } - - if ( insn.bytecmd ) - { - if ( insn.Op1.type == o_mem && insn.Op1.phrase != 077 - || insn.Op1.type == o_displ && (insn.Op1.phrase & 070) == 060 ) - { - insn.Op1.dtype = dt_byte; - } - if ( insn.Op2.type == o_mem && insn.Op2.phrase != 077 - || insn.Op2.type == o_displ && (insn.Op2.phrase & 070) == 060 ) - { - insn.Op2.dtype = dt_byte; - } - } - - if ( insn.Op1.type == o_imm && insn.Op1.ill_imm ) - insn.size -= 2; - if ( insn.Op2.type == o_imm && insn.Op2.ill_imm ) - insn.size -= 2; - - return int(insn.size); -} diff --git a/idasdk75/module/pdp11/emu.cpp b/idasdk75/module/pdp11/emu.cpp deleted file mode 100644 index 2ccba1d..0000000 --- a/idasdk75/module/pdp11/emu.cpp +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "pdp.hpp" - -//------------------------------------------------------------------------ -void pdp11_t::loadR0data(const insn_t &insn, const op_t *x, int sme) -{ - if ( insn.Op2.type == o_void ) - { - if ( insn.itype != pdp_clr ) - goto undefdat; - if ( sme ) - { - if ( !insn.bytecmd ) - goto undefdat; - emuR0data.b[1] = 0; - return; - } - if ( insn.bytecmd ) - emuR0data.b[0] = 0; - else - emuR0data.w = 0; - return; - } - if ( x != &insn.Op2 ) - return; - if ( insn.Op1.type == o_imm ) - { - if ( insn.itype == pdp_mov ) - { - if ( !insn.bytecmd ) - { - if ( sme ) - goto undefdat; - emuR0data.w = (ushort)insn.Op1.value; - return; - } - if ( !sme ) - emuR0data.b[0] = (uchar)insn.Op1.value; - else - emuR0data.b[1] = (uchar)insn.Op1.value; - return; - } - if ( !insn.bytecmd ) - goto undefdat; -undefbyt: - if ( !sme ) - emuR0data.b[0] = 0xFF; - else - emuR0data.b[1] = 0xFF; - return; - } - if ( insn.bytecmd ) - goto undefbyt; -undefdat: - emuR0data.w = 0xFFFF; -} - -//------------------------------------------------------------------------ -void pdp11_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) -{ - ea_t jmpa; - switch ( x.type ) - { - case o_near: // Jcc/ [jmp/call 37/67] - case o_mem: // 37/67/77 - case o_far: - jmpa = x.type == o_far - ? to_ea(x.segval, x.addr16) - : map_code_ea(insn, x.addr16, x.n); - if ( x.phrase == 0 ) - { - insn.add_cref(jmpa, x.offb, fl_JN); //Jcc - break; - } -extxref: - if ( (x.phrase & 070) == 070 ) - goto xrefset; - if ( insn.itype == pdp_jmp ) - insn.add_cref(jmpa, x.offb, fl_JF); - else if ( insn.itype == pdp_jsr || insn.itype == pdp_call ) - { - insn.add_cref(jmpa, x.offb, fl_CF); - if ( !func_does_return(jmpa) ) - flow = false; - } - else - { -xrefset: - insn.create_op_data(jmpa, x); - insn.add_dref(jmpa, x.offb, isload ? dr_R : dr_W); - } - break; - case o_displ: // 6x/7x (!67/!77) - set_immd(insn.ea); - if ( !isload && x.phrase == (060 + rR0) && x.addr16 <= 1 ) - loadR0data(insn, &x, x.addr16); - if ( !is_forced - && is_off(get_flags(insn.ea), x.n) - && (jmpa = get_offbase(insn.ea, x.n)) != BADADDR ) - { - jmpa += x.addr16; - goto extxref; - } - break; - case o_imm: // 27 - if ( !x.ill_imm ) - { - set_immd(insn.ea); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, dr_O, OOF_SIGNED); - } - break; - case o_number: // EMT/TRAP/MARK/SPL - if ( insn.itype == pdp_emt && get_cmt(NULL, insn.ea, false) <= 0 ) - { - insn_t tmp = insn; - op_t &tmpx = tmp.ops[x.n]; - if ( tmpx.value >= 0374 && tmpx.value <= 0375 ) - { - tmp.Op2.value = (tmpx.value == 0375) ? emuR0data.b[1] : (emuR0 >> 8); - tmp.Op2.type = o_imm; - } - qstring qbuf; - if ( get_predef_insn_cmt(&qbuf, tmp) > 0 ) - set_cmt(tmp.ea, qbuf.c_str(), false); - } - break; - case o_reg: // 0 - if ( x.reg == rR0 ) - { - if ( insn.Op2.type == o_void ) // one operand insn - { - if ( insn.itype != pdp_clr ) - goto undefall; - if ( insn.bytecmd ) - emuR0 &= 0xFF00; - else - emuR0 = 0; - goto undefdata; - } - if ( &x == &insn.Op2 ) - { - if ( insn.itype != pdp_mov ) - { - if ( insn.bytecmd ) - { - emuR0 |= 0xFF; - goto undefdata; - } - goto undefall; - } - if ( insn.bytecmd ) - goto undefall; - if ( insn.Op1.type == o_imm ) - { - if ( (emuR0 = (ushort)insn.Op1.value) & 1 ) - goto undefdata; - emuR0data.w = get_word(to_ea(insn.cs, emuR0)); - } - else - { -undefall: - emuR0 = 0xFFFF; -undefdata: - emuR0data.w = 0xFFFF; - } - } - } - break; - case o_phrase: // 1x/2x/3x/4x/5x (!27/!37) - if ( (x.phrase & 7) == rR0 ) - { - if ( !isload && x.phrase == (010 + rR0) ) - loadR0data(insn, &x, 0); - else if ( insn.Op2.type == o_void || &x == &insn.Op2 ) - goto undefall; - } - case o_fpreg: // FPP - break; - default: - warning("%" FMT_EA "o (%s): bad optype %d", insn.ip, insn.get_canon_mnem(ph), x.type); - break; - } -} - -//---------------------------------------------------------------------- -int pdp11_t::emu(const insn_t &insn) -{ - bool flag1 = is_forced_operand(insn.ea, 0); - bool flag2 = is_forced_operand(insn.ea, 1); - - uint32 Feature = insn.get_canon_feature(ph); - flow = (Feature & CF_STOP) == 0; - - if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true); - if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true); - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false); - if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false); - - ea_t newEA = insn.ea + insn.size; - if ( insn.itype == pdp_emt && insn.Op1.value == 0376 ) - { - create_byte(newEA, 2); - goto prompt2; - } - else if ( flow && !(insn.itype == pdp_emt && insn.Op1.value == 0350) ) - { - if ( insn.Op1.type == o_imm && insn.Op1.ill_imm ) - newEA += 2; - if ( insn.Op2.type == o_imm && insn.Op2.ill_imm ) - { -prompt2: - newEA += 2; - } - add_cref(insn.ea, newEA, fl_F); - } - return 1; -} diff --git a/idasdk75/module/pdp11/float.c b/idasdk75/module/pdp11/float.c deleted file mode 100644 index ec02cec..0000000 --- a/idasdk75/module/pdp11/float.c +++ /dev/null @@ -1,73 +0,0 @@ -#include <ieee.h> -#define E IEEE_E -#define M IEEE_M -#define EXONE IEEE_EXONE - -// one of the many possible NaNs, -// the one produced by the base converter -const eNE ieee_nan { 0, 0, 0, 0, 0xc000, 0xffff }; - -int idaapi realcvt(void *m, eNE e, unsigned short swt) -{ - eNI x; - long exp; - unsigned short r, msk, *p = (unsigned short *)m; - - switch(swt) { - case 1: // in float - case 0: // in trunc. float - case 3: // in double - ecleaz(x); - x[0] = ((r = *p) & 0x8000) ? 0xffff : 0; /* fill in our sign */ - if(!(r &= (0377 << 7))) { - if ( x[0] ) // negative and zero exponent = Undefined -> transformed to NaN - { - memcpy(e, ieee_nan, sizeof(eNE)); - break; - } - // complain on dirty zero - for(msk = 0x7fff, r = swt + 1; r; r--, msk = 0xffff) - if(*p++ & msk) return(-3); // signed zero accepted - } else { - x[E] = (r >> 7) + (EXONE - 0201); /* DEC exponent offset */ - x[M] = (*p++ & 0177) | 0200; /* now do the high order mantissa */ - if(swt) memcpy(&x[M+1], p, swt*sizeof(unsigned short)); - eshift(x, -8); /* shift our mantissa down 8 bits */ - } - if(e) emovo(x, e); // convert to IEEE format - break; - - case 011: // out float - case 010: // out trunc. float - case 013: // out double - emovi(e, x); - r = swt & 3; - if(!x[E]) goto clear; - if ( x[E] == E_SPECIAL_EXP ) - { - // all of NaN, +/-Inf transformed to "Undefined value" - x[0] = 0xffff; - x[E] = 0; - goto clear; - } - exp = (long )x[E] - (EXONE - 0201); - if(!emdnorm(x, 0, 0, exp, 56) || x[E] >= 0377) - return REAL_ERROR_RANGE; // overfloat - if(!x[E]) { -clear: - memset(p, 0, (r + 1)*sizeof(unsigned short)); - if(x[0]) *p = 0x8000; // signed zero accepted - } else { - *p = (x[0] ? 0100000 : 0) | (x[E] << 7); /* sign & exp */ - eshift(x, 8); - *p++ |= (x[M] & 0177); - if(r) memcpy(p, &x[M+1], r*sizeof(unsigned short)); - } - break; - - default: - return REAL_ERROR_FORMAT; - } - - return 0; -} diff --git a/idasdk75/module/pdp11/ins.hpp b/idasdk75/module/pdp11/ins.hpp deleted file mode 100644 index 7f5fa5e..0000000 --- a/idasdk75/module/pdp11/ins.hpp +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-2020 Hex-Rays - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ -pdp_null = 0, // Unknown Operation - -pdp_halt, // Stop CPU -pdp_wait, // Wait interrupt -pdp_rti, // Interrupt return -pdp_bpt, // Trap to Debbuger -pdp_iot, // Trap to 20 (i/o) -pdp_reset, // Reset CPU and device -pdp_rtt, // Interrupt return and ignore dbg-flag -pdp_mfpt, // Load Processor Type (* hi model) -pdp_jmp, // Absolute jmp -pdp_rts, // Return into subroutine -pdp_spl, // Set Prior. -pdp_nop, // Not operation -pdp_clc, // Clear C bit in PSW -pdp_clv, // Clear V bit in PSW -pdp_clz, // Clear Z bit in PSW -pdp_cln, // Clear N bit in PSW -pdp_ccc, // Clear All Condition bits in PSW -pdp_sec, // Set C bit in PSW -pdp_sev, // Set V bit in PSW -pdp_sez, // Set Z bit in PSW -pdp_sen, // Set N bit in PSW -pdp_scc, // Set All Condition bits bit in PSW -pdp_swab, // Exchange byte in word -pdp_br, // Relative jmp -pdp_bne, // Jump if Z=0 -pdp_beq, // Jump if Z=1 -pdp_bge, // Jump if N^V=0 -pdp_blt, // Jump if N^V=1 -pdp_bgt, // Jump if Z|(N^V)=0 -pdp_ble, // Jump if Z|(N^V)=1 -pdp_jsr, // Call procedure -pdp_clr, // Clear operand -pdp_com, // Inverse operand -pdp_inc, // Increment operand -pdp_dec, // Decrement operand -pdp_neg, // op = -op -pdp_adc, // Add with Carry -pdp_sbc, // Substract with Carry -pdp_tst, // Test operand -pdp_ror, // Cyclic shift rignt -pdp_rol, // Cyclic shift left -pdp_asr, // Arifmetic shift rignt -pdp_asl, // Arifmetic shift left -pdp_mark, // Return and empty stack -pdp_mfpi, // Load from previous instruction space (*hi model) -pdp_mtpi, // Store to previous instruction space (*hi model) -pdp_sxt, // N=>op -pdp_mov, // Move operand -pdp_cmp, // Compare operands -pdp_bit, // Check Bit's -pdp_bic, // Clear Bit's -pdp_bis, // Set Bit's -pdp_add, // Add operands -pdp_sub, // Substract operands -pdp_mul, // Multiple Reg (*eis) -pdp_div, // Divide Reg (*eis) -pdp_ash, // Multistep shift (*eis) -pdp_ashc, // Multistep shift 2 reg (*eis) -pdp_xor, // Exclusive or (*eis) -pdp_fadd, // Floating Add (*fis) -pdp_fsub, // Floating Subtract (*fis) -pdp_fmul, // Floating Multiple (*fis) -pdp_fdiv, // Floating Divide (*fis) -pdp_sob, // -pdp_bpl, // Jump if N=0 -pdp_bmi, // Jump if N=1 -pdp_bhi, // Jump if (!C)&(!Z)=0 -pdp_blos, // Jump if C|Z=1 -pdp_bvc, // Jump if V=0 -pdp_bvs, // Jump if V=1 -pdp_bcc, // Jump if C=0 -pdp_bcs, // Jump if C=1 -pdp_emt, // Trap to System -pdp_trap, // Trap to user/compiler -pdp_mtps, // Store PSW (*lsi11 only) -pdp_mfpd, // Load from previous data space (*hi model) -pdp_mtpd, // Store to previous data space (*hi model) -pdp_mfps, // Load PSW (*lsi11 only) - // FPU instruction -pdp_cfcc, // Copy cond.codes into FPS to PSW -pdp_setf, // Set Float -pdp_seti, // Set Integer -pdp_setd, // Set Double -pdp_setl, // Set Long Integer -pdp_ldfps, // Load FPS -pdp_stfps, // Store FPS -pdp_stst, // Load interrupt status -pdp_clrd, // Clear -pdp_tstd, // Test -pdp_absd, // op = mod(op) -pdp_negd, // op = -op -pdp_muld, // Multiple -pdp_modd, // Get int. part -pdp_addd, // Add -pdp_ldd, // Load in Acc -pdp_subd, // Substract -pdp_cmpd, // Compare -pdp_std, // Store into Acc -pdp_divd, // Divide -pdp_stexp, // Store exponent -pdp_stcdi, // Store and convert double/float to integer/long -pdp_stcdf, // Store and convert double/float to float/double -pdp_ldexp, // Load exponent -pdp_ldcif, // Load and convert integer/long to double/float -pdp_ldcfd, // Load and convert float/double to double/float -pdp_call, // Jsr PC, -pdp_return, // RTS PC -pdp_compcc, // Complex Condition Codes - -pdp_last - - }; - -#endif diff --git a/idasdk75/module/pdp11/makefile b/idasdk75/module/pdp11/makefile deleted file mode 100644 index 83aeb17..0000000 --- a/idasdk75/module/pdp11/makefile +++ /dev/null @@ -1,39 +0,0 @@ -PROC=pdp11 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp ins.hpp pdp.hpp pdp_ml.h -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp ins.hpp pdp.hpp pdp_ml.h -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp out.cpp pdp.hpp pdp_ml.h -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp float.c ins.hpp \ - pdp.hpp pdp_ml.h reg.cpp diff --git a/idasdk75/module/pdp11/out.cpp b/idasdk75/module/pdp11/out.cpp deleted file mode 100644 index df63201..0000000 --- a/idasdk75/module/pdp11/out.cpp +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "pdp.hpp" - -//---------------------------------------------------------------------- -class out_pdp_t : public outctx_t -{ - out_pdp_t(void) = delete; // not used - pdp11_t &pm() { return *static_cast<pdp11_t *>(procmod); } -public: - void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); } - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); -}; -CASSERT(sizeof(out_pdp_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_pdp_t) - -//---------------------------------------------------------------------- -bool out_pdp_t::out_operand(const op_t &x) -{ - ea_t segadr; - switch ( x.type ) - { - case o_void: - return 0; - case o_reg: - OutReg(x.reg); - break; - case o_fpreg: - OutReg(x.reg + 8); - break; - case o_imm: // 27 - if ( x.ill_imm ) - { - out_symbol('('); - OutReg(rPC); - out_symbol(')'); - out_symbol('+'); - } - else - { - out_symbol('#'); - if ( x.dtype == dt_float || x.dtype == dt_double ) - { - char str[MAXSTR]; - if ( print_fpval(str, sizeof(str), &x.value, 2) ) - { - char *p = str; - while ( *p == ' ' ) - p++; - out_symbol('^'); - out_symbol('F'); - out_line(p, COLOR_NUMBER); - } - else - { - out_long(x.value, 8); - } - } - else - { - out_value(x, OOF_SIGNED | OOFW_IMM); - } - } - break; - case o_mem: // 37/67/77 - case o_near: // jcc/ [jmp/call 37/67] - case o_far: - if ( x.phrase != 0 ) - { - if ( x.phrase == 077 || x.phrase == 037 ) - out_symbol('@'); - if ( x.phrase == 037 ) - out_symbol('#'); - if ( x.addr16 < pm().ml.asect_top && !is_off(F, x.n) ) - { - out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16); - break; - } - } - segadr = x.type == o_far - ? to_ea(x.segval, x.addr16) - : map_code_ea(insn, x.addr16, x.n); - if ( !out_name_expr(x, segadr, x.addr16) ) - { - if ( x.type == o_far || x.addr16 < 0160000 ) - remember_problem(PR_NONAME, insn.ea); - out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16); - } - break; - case o_number: //EMT/TRAP/MARK/SPL - out_value(x, OOF_NUMBER | OOFS_NOSIGN | OOFW_8); - break; - case o_displ: // 6x/7x (!67/!77) - if ( x.phrase >= 070 ) - out_symbol('@'); - out_value(x, OOF_ADDR | OOF_SIGNED | OOFW_16); - out_symbol('('); - goto endregout; - case o_phrase: // 1x/2x/3x/4x/5x (!27/!37) - switch ( x.phrase >> 3 ) - { - case 1: - out_symbol('@'); - OutReg(x.phrase & 7); - break; - case 3: - out_symbol('@'); - // fallthrough - case 2: - out_symbol('('); - OutReg(x.phrase & 7); - out_symbol(')'); - out_symbol('+'); - break; - case 5: - out_symbol('@'); - // fallthrough - case 4: - out_symbol('-'); - out_symbol('('); -endregout: - OutReg(x.phrase & 7); - out_symbol(')'); - break; - } - break; - default: - warning("out: %" FMT_EA "o: bad optype %d", insn.ip, x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -void out_pdp_t::out_proc_mnem(void) -{ - static const char *const postfix[] = { "", "b" }; - out_mnem(8, postfix[insn.bytecmd]); -} - -//---------------------------------------------------------------------- -void out_pdp_t::out_insn(void) -{ - out_mnemonic(); - if ( insn.itype == pdp_compcc ) - { - uint i = 0, code, first = 0; - static const uint tabcc[8] = - { - pdp_clc, pdp_clv, pdp_clz, pdp_cln, - pdp_sec, pdp_sev, pdp_sez, pdp_sen - }; - code = insn.Op1.phrase; - out_symbol('<'); - if ( code >= 020 ) - { - if ( (code ^= 020) == 0 ) - out_line(COLSTR("nop!^O20", SCOLOR_INSN)); - i = 4; - } - for ( ; code; i++, code >>= 1 ) - { - if ( code & 1 ) - { - if ( first++ ) - out_symbol('!'); - out_line(ph.instruc[tabcc[i]].name, COLOR_INSN); - } - } - out_symbol('>'); - } - - out_one_operand(0); - - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void idaapi pdp_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, seg) could be made const -void pdp11_t::pdp_segstart(outctx_t &ctx, segment_t *seg) -{ - if ( seg->type == SEG_IMEM ) - { - ctx.flush_buf(COLSTR(".ASECT", SCOLOR_ASMDIR), DEFAULT_INDENT); - } - else - { - qstring sname; - get_visible_segm_name(&sname, seg); - ctx.out_printf(COLSTR(".PSECT %s", SCOLOR_ASMDIR), sname.c_str()); - if ( seg->ovrname != 0 ) - { - char bseg[MAX_NUMBUF]; - char breg[MAX_NUMBUF]; - btoa(bseg, sizeof(bseg), seg->ovrname & 0xFFFF, 10); - btoa(breg, sizeof(breg), seg->ovrname >> 16, 10); - ctx.out_printf( - COLSTR(" %s Overlay Segment %s, Region %s", SCOLOR_AUTOCMT), - ash.cmnt, bseg, breg); - } - ctx.flush_outbuf(0); - } - - if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) - { - size_t org = size_t(ctx.insn_ea-get_segm_base(seg)); - if ( org != 0 && org != ml.asect_top && seg->comorg() ) - { - ctx.out_tagon(COLOR_ASMDIR); - ctx.out_line(ash.origin); - ctx.out_line(ash.a_equ); - if ( seg->type != SEG_IMEM ) - { - ctx.out_line(ash.origin); - ctx.out_char('+'); - } - ctx.out_btoa(org); - ctx.out_tagoff(COLOR_ASMDIR); - ctx.flush_outbuf(DEFAULT_INDENT); - } - } -} - -//-------------------------------------------------------------------------- -void pdp11_t::pdp_footer(outctx_t &ctx) const -{ - if ( ash.end != NULL ) - { - ctx.gen_empty_line(); - ctx.out_line(ash.end, COLOR_ASMDIR); - qstring name; - if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) - { - size_t i = strlen(ash.end); - do - ctx.out_char(' '); - while ( ++i < 8 ); - ctx.out_line(name.begin()); - } - ctx.flush_outbuf(DEFAULT_INDENT); - } - else - { - ctx.gen_cmt_line("end of file"); - } -} - -//-------------------------------------------------------------------------- -bool pdp11_t::out_equ(outctx_t &ctx, ea_t ea) const -{ - segment_t *s = getseg(ea); - char buf[MAXSTR]; - if ( s != NULL ) - { - if ( s->type != SEG_IMEM && !is_loaded(ea) ) - { - char num[MAX_NUMBUF]; - btoa(num, sizeof(num), get_item_size(ea)); - nowarn_qsnprintf(buf, sizeof(buf), ash.a_bss, num); - ctx.flush_buf(buf); - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -void pdp11_t::pdp_data(outctx_t &ctx, bool analyze_only) const -{ - char buf[MAXSTR]; - ushort v[5]; - ea_t endea; - ushort i, j; - - ea_t ea = ctx.insn_ea; - if ( out_equ(ctx, ea) ) - return; - - i = 0; - flags_t F = ctx.F; - if ( !is_unknown(F) ) - { - if ( is_word(F) && get_radix(F,0) == 16 ) - i = 2; - else if ( is_dword(F) ) - i = 4; - else if ( is_qword(F) ) - i = 8; - else if ( is_tbyte(F) ) - i = 10; - if ( i == 0 ) - { - ctx.out_data(analyze_only); - return; - } - - int radix = get_radix(F, 0); - endea = get_item_end(ea); - for ( ; ea < endea; ea += i ) - { - memset(v, 0, sizeof(v)); - if ( get_bytes(v, i, ea) != i || r50_to_asc(buf, v, i/2) != 0 ) - { - ctx.out_keyword(".word "); - for ( j = 0; j < i/2; j++ ) - { - if ( j ) - ctx.out_symbol(','); - btoa(buf, sizeof(buf), v[j], radix); - ctx.out_line(buf, COLOR_NUMBER); - } - } - else - { - ctx.out_keyword(".rad50 "); - ctx.out_tagon(COLOR_CHAR); - ctx.out_char('/'); - ctx.out_line(buf); - ctx.out_char('/'); - ctx.out_tagoff(COLOR_CHAR); - } - if ( ctx.flush_outbuf() ) - return; // too many lines - } - return; - } -// unknown - if ( !is_loaded(ea) ) - { - ctx.flush_buf(COLSTR(".blkb", SCOLOR_KEYWORD)); - } - else - { - uchar c = get_byte(ea); - - char cbuf[MAX_NUMBUF]; - btoa(cbuf, sizeof(cbuf), c); - ctx.out_printf(COLSTR(".byte ", SCOLOR_KEYWORD) - COLSTR("%4s ", SCOLOR_DNUM) - COLSTR("%s %c", SCOLOR_AUTOCMT), - cbuf, - ash.cmnt, - c >= ' ' ? c : ' '); - if ( !(ea & 1) && (i = get_word(ea)) != 0 ) - { - ctx.out_tagon(COLOR_AUTOCMT); - ctx.out_char(' '); - b2a32(buf, sizeof(buf), i, 2, 0); - ctx.out_line(buf); - ctx.out_char(' '); - ushort w = i; - r50_to_asc(buf, &w, 1); - ctx.out_line(buf); - ctx.out_tagoff(COLOR_AUTOCMT); - } - ctx.flush_outbuf(); - } // undefined -} diff --git a/idasdk75/module/pdp11/pdp.hpp b/idasdk75/module/pdp11/pdp.hpp deleted file mode 100644 index b168802..0000000 --- a/idasdk75/module/pdp11/pdp.hpp +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#ifndef _PDP_HPP -#define _PDP_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include "pdp_ml.h" -//-V::536 octal - -#define UAS_SECT 0x0001 // Segments are named .SECTION - -//---------------------------------------------------------------------- -// Redefine temporary names -// -#define bytecmd auxpref_u8[0] - -#define segval specval_shorts.low -#define addr16 addr_shorts.low -#define ill_imm specflag1 - -#define o_fpreg o_idpspec0 -#define o_number o_idpspec1 -//------------------------------------------------------------------------ -enum pdp_registers -{ - rR0, rR1, rR2, rR3, rR4, rR5, rSP, rPC, - rAC0, rAC1, rAC2, rAC3, rAC4, rAC5, - rVcs, rVds -}; - -//------------------------------------------------------------------------ -void idaapi pdp_header(outctx_t &ctx); - -//------------------------------------------------------------------------ -struct pdp11_t : public procmod_t -{ - netnode ovrtrans; - pdp_ml_t ml = { uint32(BADADDR), 0, 0, 0 }; - bool flow = false; - ushort emuR0 = 0xFFFF; - //lint -e708 'union initialization' - union - { - ushort w; - uchar b[2]; - } emuR0data = { 0xFFFF }; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void jmpoper(insn_t &insn, op_t *Op, uint16 nibble); - int ana(insn_t *_insn); - - void pdp_segstart(outctx_t &ctx, segment_t *seg); - - void loadR0data(const insn_t &insn, const op_t *x, int sme); - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - int emu(const insn_t &insn); - - void pdp_footer(outctx_t &ctx) const; - bool out_equ(outctx_t &ctx, ea_t ea) const; - void pdp_data(outctx_t &ctx, bool analyze_only) const; -}; -#endif diff --git a/idasdk75/module/pdp11/reg.cpp b/idasdk75/module/pdp11/reg.cpp deleted file mode 100644 index cded80d..0000000 --- a/idasdk75/module/pdp11/reg.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Interactive disassembler (IDA) - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * E-mail: ig@datarescue.com - * PDP11 module. - * Copyright (c) 1995-2006 by Iouri Kharon. - * E-mail: yjh@styx.cabel.net - * - * ALL RIGHTS RESERVED. - * - */ - -#include "pdp.hpp" -//---------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "R0","R1","R2","R3","R4","R5","SP","PC", - "AC0", "AC1", "AC2", "AC3", "AC4", "AC5", - "cs","ds" -}; - -//----------------------------------------------------------------------- - -static const char *const array_macro[] = -{ - "", - ".macro .array of,type,cnt,val", - ".rept cnt", - " type val", - ".endr", - ".endm .array", - NULL -}; - -static const asm_t macro11 = -{ - /*AS_UNEQU |*/ AS_COLON | AS_2CHRE | AS_NCHRE | ASH_HEXF5 | ASO_OCTF2 | ASD_DECF2 | AS_NCMAS | AS_ONEDUP | ASB_BINF1 | AS_RELSUP, - UAS_SECT, - "Macro-11 Assembler", - 0, - array_macro, // header - ".", // org - ".END", - - ";", // comment string - '\\', // string delimiter - '\'', // char delimiter - "\\\200", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".byte", // byte directive - ".word", // word directive - ".long", // double words - NULL, // no qwords - NULL, // oword (16 bytes) - ".flt2", - ".flt4", - NULL, // no tbytes - NULL, // no packreal - ".array of #hs cnt=#d val=#v", // #h - header(.byte,.word) - // #d - size of array - // #v - value of array elements - ".blkb %s", // uninited data (reserve space) - "=", - NULL, // seg prefix - ".", // a_curip - NULL, // func_header - NULL, // func_footer - ".globl", // public - ".weak", // weak - ".globl", // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '<', '>', // lbrace, rbrace - NULL, // mod - "&", // and - "|", // or - "^", // xor - "!", // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//-------------------------------------------------------------------------- -static const char ovrtrans_name[] = "$ pdp-11 overlay translations"; - -//------------------------------------------------------------------ -// floating point conversion -#include "float.c" - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new pdp11_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi pdp11_t::on_event(ssize_t msgid, va_list va) -{ - int retcode = 1; - segment_t *sptr; - - switch ( msgid ) - { - case processor_t::ev_creating_segm: - sptr = va_arg(va, segment_t *); - sptr->defsr[rVds-ph.reg_first_sreg] = find_selector(inf_get_start_cs()); //sptr->sel; - break; - - case processor_t::ev_init: - ovrtrans.create(ovrtrans_name); // it makes no harm to create it again - break; - - case processor_t::ev_newprc: - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ml.asect_top = (ushort)ovrtrans.altval(n_asect); - ml.ovrcallbeg = (ushort)ovrtrans.altval(n_ovrbeg); - ml.ovrcallend = (ushort)ovrtrans.altval(n_ovrend); - ml.ovrtbl_base = (uint32)ovrtrans.altval(n_ovrbas); - break; - - case pdp11_module_t::ev_get_ml_ptr: - { - pdp_ml_t **p_ml = va_arg(va, pdp_ml_t **); - netnode **p_mn = va_arg(va, netnode **); - if ( p_ml != NULL && p_mn != NULL ) - { - *p_ml = &ml; - *p_mn = &ovrtrans; - retcode = 0; - } - } - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - pdp_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - pdp_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - pdp_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - pdp_data(*ctx, analyze_only); - return 1; - } - - case processor_t::ev_realcvt: - { - void *m = va_arg(va, void *); - uint16 *e = va_arg(va, uint16 *); - uint16 swt = va_argi(va, uint16); - int code = realcvt(m, e, swt); - return code == 0 ? 1 : code; - } - - default: - retcode = 0; - break; - } - return retcode; -} - - -//----------------------------------------------------------------------- -static const asm_t *const asms[] = { ¯o11, NULL }; - -#define FAMILY "DEC series:" -static const char *const shnames[] = { "PDP11", NULL }; -static const char *const lnames[] = { FAMILY"DEC PDP-11", NULL }; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0200, 0000 }; -static const uchar retcode_1[] = { 0201, 0000 }; -static const uchar retcode_2[] = { 0202, 0000 }; -static const uchar retcode_3[] = { 0203, 0000 }; -static const uchar retcode_4[] = { 0204, 0000 }; -static const uchar retcode_5[] = { 0205, 0000 }; -static const uchar retcode_6[] = { 0206, 0000 }; -static const uchar retcode_7[] = { 0207, 0000 }; -static const uchar retcode_8[] = { 0002, 0000 }; -static const uchar retcode_9[] = { 0006, 0000 }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { sizeof(retcode_4), retcode_4 }, - { sizeof(retcode_5), retcode_5 }, - { sizeof(retcode_6), retcode_6 }, - { sizeof(retcode_7), retcode_7 }, - { sizeof(retcode_8), retcode_8 }, - { sizeof(retcode_9), retcode_9 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_PDP, // id - // flag - PR_WORD_INS - | PRN_OCT - | PR_SEGTRANS, - // flag2 - PR2_REALCVT // the module has 'realcvt' event implementation - | PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Register names - qnumber(RegNames), // Number of registers - - rVcs,rVds, - 0, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0,pdp_last, - Instructions, // instruc - 0, // size of tbyte - { 4,7,19,0 }, - -// Icode of return instruction. It is ok to give any of possible return -// instructions - pdp_return, -}; diff --git a/idasdk75/module/pic/ana.cpp b/idasdk75/module/pic/ana.cpp deleted file mode 100644 index 4486b85..0000000 --- a/idasdk75/module/pic/ana.cpp +++ /dev/null @@ -1,1061 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Microchip's PIC - * - */ - -#include "pic.hpp" -#include <segregs.hpp> - -#define PIC18_IP_RANGE 0x1FFFFF - -//------------------------------------------------------------------------- -// it can replace one instruction with another without changing its size -void pic_t::simplify(insn_t &insn) const -{ - switch ( insn.itype ) - { - // movfw macro f ; Move Contents of File Reg to W - // movf f,0 - // endm - // tstf macro f ; Test Contents of File Register - // movf f,1 - // endm - case PIC_movf: - insn.itype = (insn.Op2.reg == W) ? PIC_movfw : PIC_tstf; - insn.Op2.type = o_void; - break; - - // b macro k ; Branch to Address - // goto k - // endm - case PIC_goto: - insn.itype = PIC_b; - break; - - // clrc macro ; Clear Carry - // bcf 3,0 - // endm - // clrdc macro ; Clear Digit Carry - // bcf 3,1 - // endm - // clrz macro ; Clear Zero - // bcf 3,2 - // endm - case PIC_bcf: - if ( is_bank(insn) ) switch ( insn.Op2.value ) - { - case 0: insn.itype = PIC_clrc; goto NOOP; - case 1: insn.itype = PIC_clrdc; goto NOOP; - case 2: insn.itype = PIC_clrz; goto NOOP; -NOOP: - insn.Op1.type = o_void; - insn.Op2.type = o_void; - break; - } - break; - - // setc macro ; Set Carry - // bsf 3,0 - // endm - // setdc macro ; Set Digit Carry - // bsf 3,1 - // endm - // setz macro ; Set Zero - // bcf 3,2 - // endm - case PIC_bsf: - if ( is_bank(insn) ) switch ( insn.Op2.value ) - { - case 0: insn.itype = PIC_setc; goto NOOP; - case 1: insn.itype = PIC_setdc; goto NOOP; - case 2: insn.itype = PIC_setz; goto NOOP; - } - break; - - // skpnc macro ; Skip on No Carry - // btfsc 3,0 - // endm - // skpndc macro ; Skip on No Digit Carry - // btfsc 3,1 - // endm - // skpnz macro ; Skip on No Zero - // btfsc 3,2 - // endm - case PIC_btfsc: - if ( is_bank(insn) ) switch ( insn.Op2.value ) - { - case 0: insn.itype = PIC_skpnc; goto NOOP; - case 1: insn.itype = PIC_skpndc; goto NOOP; - case 2: insn.itype = PIC_skpnz; goto NOOP; - } - break; - - // skpc macro ; Skip on Carry - // btfss 3,0 - // endm - // skpdc macro ; Skip on Digit Carry - // btfss 3,1 - // endm - // skpz macro ; Skip on Zero - // btfss 3,2 - // endm - case PIC_btfss: - if ( is_bank(insn) ) switch ( insn.Op2.value ) - { - case 0: insn.itype = PIC_skpc; goto NOOP; - case 1: insn.itype = PIC_skpdc; goto NOOP; - case 2: insn.itype = PIC_skpz; goto NOOP; - } - break; - } -} - -//------------------------------------------------------------------------- -// it returns true if the size of the instruction is changed -// INSN must be simplified -bool pic_t::build_macro(insn_t &insn, bool may_go_forward) -{ - if ( !may_go_forward ) - return false; - switch ( insn.itype ) - { - // negf macro f,d ; Negate File Register Contents - // comf f,1 - // incf f,d - // endm - case PIC_comf: - if ( insn.Op2.reg == F ) - { - insn_t incf; - if ( decode_insn(&incf, insn.ea + insn.size) > 0 - && incf.itype == PIC_incf - && incf.Op1.type == o_mem - && incf.Op1.addr == insn.Op1.addr ) - { - insn.itype = PIC_negf; - insn.Op2.reg = incf.Op2.reg; - insn.size += incf.size; - return true; - } - } - break; - - // bnc macro k ; Branch on No Carry to k - // skpc - // goto k - // endm - // bndc macro k ; Branch on No Digit Carry to k - // skpdc - // goto k - // endm - // bnz macro k ; Branch on No Zero to Address - // skpz - // goto k - // endm - // bc macro k ; Branch on Carry to Address k - // skpnc - // goto k - // endm - // bdc macro k ; Branch on Digit Carry to k - // skpndc - // goto k - // endm - // bz macro k ; Branch on Zero to Address k - // skpnz - // goto k - // endm - // addcf macro f,d ; Add Carry to File Register - // skpnc - // incf f,d - // endm - // adddcf macro f,d ; Add Digit to File Register - // skpndc - // incf f,d - // endm - // subcf macro f,d ; Subtract Carry from File Reg - // skpnc - // decf f,d - // endm - case PIC_skpnc: - case PIC_skpndc: - case PIC_skpnz: - case PIC_skpc: - case PIC_skpdc: - case PIC_skpz: - { - insn_t ins2; - if ( decode_insn(&ins2, insn.ea + insn.size) == 0 ) - break; - if ( ins2.itype == PIC_b ) - { - insn.itype = insn.itype == PIC_skpc ? PIC_bnc - : insn.itype == PIC_skpdc ? PIC_bndc - : insn.itype == PIC_skpz ? PIC_bnz - : insn.itype == PIC_skpnc ? PIC_bc - : insn.itype == PIC_skpndc ? PIC_bdc - : PIC_bz; - insn.Op1 = ins2.Op1; - insn.size += ins2.size; - return true; - } - if ( ins2.itype == PIC_incf || ins2.itype == PIC_decf ) - { - if ( insn.itype == PIC_skpnc && ins2.itype == PIC_incf ) - insn.itype = PIC_addcf; - else if ( insn.itype == PIC_skpndc && ins2.itype == PIC_incf ) - insn.itype = PIC_adddcf; - else if ( insn.itype == PIC_skpnc && ins2.itype == PIC_decf ) - insn.itype = PIC_subcf; - else - break; - insn.Op1 = ins2.Op1; - insn.Op2 = ins2.Op2; - insn.size += ins2.size; - return true; - } - } - break; - } - return false; -} - -//-------------------------------------------------------------------------- -struct pic_mctr_t : public macro_constructor_t -{ - pic_t ± - pic_mctr_t(pic_t &_pm) : pm(_pm) {} - bool idaapi build_macro(insn_t *insn, bool may_go_forward) override - { - return pm.build_macro(*insn, may_go_forward); - } -}; - -//-------------------------------------------------------------------------- -int pic_t::ana(insn_t *_insn) -{ - if ( _insn == NULL ) - return 0; - insn_t &insn = *_insn; - int len = basic_ana(insn); - if ( len == 0 ) - return len; - - if ( dosimple() ) - simplify(insn); - - pic_mctr_t mctr(*this); - mctr.construct_macro(&insn, ph.supports_macros() && inf_macros_enabled()); - - // if the instruction is too long, recreate it: - /*if ( insn.size == 1 && is_tail(get_flags(insn.ea+1)) ) - { - auto_make_code(insn.ea); - auto_make_code(insn.ea+1); - ea_t saved = insn.ea; - del_items(insn.ea, DELIT_SIMPLE); // destroys insn.ea - insn.ea = saved; - }*/ - return insn.size; -} - -//-------------------------------------------------------------------------- -static void opf12(insn_t &insn, int code) -{ - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - sel_t v = get_sreg(insn.ea, BANK); - if ( v == BADSEL ) - v = 0; - insn.Op1.addr = (code & 0x1F) | ((v&1) << 5); -} - -//-------------------------------------------------------------------------- -static void opf14(insn_t &insn, int code) -{ - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - sel_t v = get_sreg(insn.ea, BANK); - if ( v == BADSEL ) - v = 0; - insn.Op1.addr = (code & 0x7F) | ((v&3) << 7); -} - -//-------------------------------------------------------------------------- -static void opfa16(insn_t &insn, int code) -{ - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - if ( code & 0x0100 ) // if a == 1 (BSR) - { - sel_t v = get_sreg(insn.ea, BANK); - if ( v == BADSEL ) - v = 0; - insn.Op1.addr = ((v&0xF) << 8) | (code & 0xFF); - } - else // if a == 0 (access bank) - { - insn.Op1.addr = code & 0xFF; - if ( insn.Op1.addr >= 128 ) - insn.Op1.addr = 3840 + insn.Op1.addr; - } -} - -//-------------------------------------------------------------------------- -static void basic_ana12(insn_t &insn, int code) -{ - int b4; - - switch ( code >> 10 ) - { - case 0: -// 0000 0100 0000 CLRW Clear W -// 0000 0000 0000 NOP No Operation -// 0000 0000 0100 CLRWDT Clear Watchdog Timer -// 0000 0000 0010 OPTION Load OPTION register -// 0000 0000 0011 SLEEP Go into standby mode - if ( code == 0x040 ) - insn.itype = PIC_clrw; - else if ( code == 0x000 ) - insn.itype = PIC_nop; - else if ( code == 0x004 ) - insn.itype = PIC_clrwdt; - else if ( code == 0x002 ) - insn.itype = PIC_option; - else if ( code == 0x003 ) - insn.itype = PIC_sleep; - else if ( ( code & 0xFF8 ) == 0 ) - { -// 0000 0000 0fff TRIS f (4<f<8) Load TRIS Register - insn.itype = PIC_tris; - opf12(insn, code); - } - else if ( ( code & 0xF80 ) == 0 ) -// 0000 001f ffff MOVWF f Move W to f -// 0000 011f ffff CLRF f Clear f - { - static const ushort codes[4] = - { - PIC_null, PIC_movwf, PIC_null, PIC_clrf - }; - insn.itype = codes[(code>>5)&3]; - opf12(insn, code); - } - else - { -// 0000 10df ffff SUBWF f, d Subtract W from f -// 0000 11df ffff DECF f, d Decrement f -// 0001 00df ffff IORWF f, d Inclusive OR W with f -// 0001 01df ffff ANDWF f, d AND W with f -// 0001 10df ffff XORWF f, d Exclusive OR W with f -// 0001 11df ffff ADDWF f, d Add W and f -// 0010 00df ffff MOVF f, d Move f -// 0010 01df ffff COMF f, d Complement f -// 0010 10df ffff INCF f, d Increment f -// 0010 11df ffff DECFSZ f, d Decrement f, Skip if 0 -// 0011 00df ffff RRF f, d Rotate Right f through Carry -// 0011 01df ffff RLF f, d Rotate Left f through Carry -// 0011 10df ffff SWAPF f, d Swap nibbles in f -// 0011 11df ffff INCFSZ f, d Increment f, Skip if 0 - b4 = code >> 6; - static const ushort codes[16] = - { - PIC_null, PIC_null, PIC_subwf, PIC_decf, - PIC_iorwf, PIC_andwf, PIC_xorwf, PIC_addwf, - PIC_movf, PIC_comf, PIC_incf, PIC_decfsz, - PIC_rrf, PIC_rlf, PIC_swapf, PIC_incfsz - }; - insn.itype = codes[b4]; - opf12(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = (code & 0x20) ? F : W; - insn.Op2.dtype = dt_byte; - } - break; - case 1: -// 0100 bbbf ffff BCF f, b Bit Clear f -// 0101 bbbf ffff BSF f, b Bit Set f -// 0110 bbbf ffff BTFSC f, b Bit Test f, Skip if Clear -// 0111 bbbf ffff BTFSS f, b Bit Test f, Skip if Set - { - static const ushort codes[4] = - { - PIC_bcf, PIC_bsf, PIC_btfsc, PIC_btfss - }; - insn.itype = codes[(code>>8)&3]; - opf12(insn, code); - insn.Op2.type = o_imm; - insn.Op2.value = (code >> 5) & 7; - insn.Op2.dtype = dt_byte; - } - break; - case 2: - b4 = (code >> 8) & 0x3; - switch ( b4 ) - { - case 0: -// 1000 kkkk kkkk RETLW k Return with literal in W - insn.itype = PIC_retlw; - insn.Op1.type = o_imm; - insn.Op1.value = code & 0xFF; - insn.Op1.dtype = dt_byte; - break; - case 1: -// 1001 kkkk kkkk CALL k Call subroutine - { - // old databases used status reg (PCLATH) for hight bit of the address - // new code uses BANK for that - // so we get both and try to guess - sel_t status = get_sreg(insn.ea, PCLATH); - sel_t bank = get_sreg(insn.ea, BANK); - if ( (status != BADSEL && status != 0) && (bank == BADSEL || bank == 0) ) - bank = (status >> 5) & 3; - insn.itype = PIC_call; - insn.Op1.type = o_near; - insn.Op1.addr = (bank << 9) | (code & 0xFF); - insn.Op1.dtype = dt_code; - } - break; - default: -// 101k kkkk kkkk GOTO k Go to address - { - sel_t status = get_sreg(insn.ea, PCLATH); - sel_t bank = get_sreg(insn.ea, BANK); - if ( (status != BADSEL && status != 0) && (bank == BADSEL || bank == 0) ) - bank = (status >> 5) & 3; - insn.itype = PIC_goto; - insn.Op1.type = o_near; - insn.Op1.addr = (bank << 9) | (code & 0x1FF); - insn.Op1.dtype = dt_code; - } - break; - } - break; - case 3: -// 1100 kkkk kkkk MOVLW k Move literal to W -// 1101 kkkk kkkk IORLW k Inclusive OR literal with W -// 1110 kkkk kkkk ANDLW k AND literal with W -// 1111 kkkk kkkk XORLW k Exclusive OR literal with W - { - static const ushort codes[4] = - { - PIC_movlw, PIC_iorlw, PIC_andlw, PIC_xorlw - }; - insn.itype = codes[(code>>8)&3]; - insn.Op1.type = o_imm; - insn.Op1.value = (uchar)code; - insn.Op1.dtype = dt_byte; - } - break; - } -} - -//-------------------------------------------------------------------------- -int32 get_signed(int32 byte, uint32 mask) -{ - uint32 bits = mask >> 1; - uint32 sign = bits + 1; - if ( (byte & sign) != 0 ) // byte < 0 - byte = (byte & bits) - sign; - else // byte >= 0 - byte = byte & mask; - return byte; -} - -//-------------------------------------------------------------------------- -static void basic_ana14(insn_t &insn, int code) -{ - int b4 = (code >> 8) & 0xF; - - switch ( code >> 12 ) - { - // 00 xxxx xxxx xxxx - case 0: - if ( b4 == 0 ) // 00 0000 xxxx xxxx - { - // 00 0000 1fff ffff MOVWF f Move W to f - if ( (code & 0x80) != 0 ) - { - insn.itype = PIC_movwf; - opf14(insn, code); - break; - } - - // 00 0000 0001 0nmm MOVIW Move INDFn to W - // 00 0000 0001 1nmm MOVWI Move W to INDFn - if ( (code >> 4) == 1 ) - { - insn.itype = ((code >> 3) & 1) == 0 ? PIC_moviw : PIC_movwi; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code & 0x4) == 0) ? FSR0 : FSR1; - insn.Op1.specflag1 = (code & 3) + 1; - insn.Op1.dtype = dt_byte; - break; - } - - - // 00 0000 001k kkkk MOVLB k Move literal to BSR - if ( (code >> 5) == 1 ) - { - insn.itype = PIC_movlb; - insn.Op1.type = o_imm; - insn.Op1.value = code & 0x1F; - insn.Op1.dtype = dt_byte; - break; - } - - - // 00 0000 0000 0000 NOP No Operation - // 00 0000 0000 0001 RESET Software device Reset - // 00 0000 0000 1000 RETURN Return from Subroutine - // 00 0000 0000 1001 RETFIE Return from interrupt - // 00 0000 0000 1010 CALLW Call Subroutine with W - // 00 0000 0000 1011 BRW Relative Branch with W - // 00 0000 0110 0010 OPTION Load OPTION register - // 00 0000 0110 0011 SLEEP Go into standby mode - // 00 0000 0110 0100 CLRWDT Clear Watchdog Timer - // 00 0000 0110 0fff TRIS f (4<f<8) Load TRIS Register - if ( code == 0x0 ) - { - insn.itype = PIC_nop; - } - else if ( code == 0x0001 ) - { - insn.itype = PIC_reset; - } - else if ( code == 0x0008 ) - { - insn.itype = PIC_return; - } - else if ( code == 0x000A ) - { - insn.itype = PIC_callw; - } - else if ( code == 0x0009 ) - { - insn.itype = PIC_retfie; - } - else if ( code == 0x000B ) - { - insn.itype = PIC_brw; - sel_t w = get_sreg(insn.ea, W); - insn.Op1.type = o_near; - insn.Op1.value = insn.ea + w + 1; //PC + W + 1 - insn.Op1.dtype = dt_code; - } - else if ( code == 0x0062 ) - { - insn.itype = PIC_option; - } - else if ( code == 0x0063 ) - { - insn.itype = PIC_sleep; - } - else if ( code == 0x0064 ) - { - insn.itype = PIC_clrwdt; - } - else if ( code >= 0x0065 && code <= 0x0067 ) - { - insn.itype = PIC_tris; - insn.Op1.type = o_imm; - insn.Op1.dtype = dt_byte; - insn.Op1.value = code & 7; - } - } - else if ( b4 == 1 ) // 00 0001 xxxx xxxx - { - // 00 0001 1fff ffff CLRF f Clear f - if ( code & 0x80 ) - { - insn.itype = PIC_clrf; - opf14(insn, code); - } - // 00 0001 0xxx xxxx CLRW Clear W - else - { - insn.itype = PIC_clrw; - } - } - else - { - // 00 0010 dfff ffff SUBWF f, d Subtract W from f - // 00 0011 dfff ffff DECF f, d Decrement f - // 00 0100 dfff ffff IORWF f, d Inclusive OR W with f - // 00 0101 dfff ffff ANDWF f, d AND W with f - // 00 0110 dfff ffff XORWF f, d Exclusive OR W with f - // 00 0111 dfff ffff ADDWF f, d Add W and f - // 00 1000 dfff ffff MOVF f, d Move f - // 00 1001 dfff ffff COMF f, d Complement f - // 00 1010 dfff ffff INCF f, d Increment f - // 00 1011 dfff ffff DECFSZ f, d Decrement f, Skip if 0 - // 00 1100 dfff ffff RRF f, d Rotate Right f through Carry - // 00 1101 dfff ffff RLF f, d Rotate Left f through Carry - // 00 1110 dfff ffff SWAPF f, d Swap nibbles in f - // 00 1111 dfff ffff INCFSZ f, d Increment f, Skip if 0 - static const ushort codes[16] = - { - PIC_null, PIC_null, PIC_subwf, PIC_decf, - PIC_iorwf, PIC_andwf, PIC_xorwf, PIC_addwf, - PIC_movf, PIC_comf, PIC_incf, PIC_decfsz, - PIC_rrf, PIC_rlf, PIC_swapf, PIC_incfsz - }; - insn.itype = codes[b4]; - opf14(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = (code & 0x80) ? F : W; - insn.Op2.dtype = dt_byte; - } - break; - - // 01 xxxx xxxx xxxx - case 1: - // 01 00bb bfff ffff BCF f, b Bit Clear f - // 01 01bb bfff ffff BSF f, b Bit Set f - // 01 10bb bfff ffff BTFSC f, b Bit Test f, Skip if Clear - // 01 11bb bfff ffff BTFSS f, b Bit Test f, Skip if Set - { - static const ushort codes[4] = - { - PIC_bcf, PIC_bsf, PIC_btfsc, PIC_btfss - }; - insn.itype = codes[(code >> 10) & 3]; - opf14(insn, code); - insn.Op2.type = o_imm; - insn.Op2.value = (code >> 7) & 7; - insn.Op2.dtype = dt_byte; - } - break; - - // 10 xxxx xxxx xxxx - case 2: - // 10 0kkk kkkk kkkk CALL k Call subroutine - // 10 1kkk kkkk kkkk GOTO k Go to address - { - //Get the content of PCLATH segment register. We use a mask to keep only bits 3 et 4. (The upper bits of PC are loaded from PCLATH<4:3>.) - sel_t pclath = get_sreg(insn.ea, PCLATH) & 0x18; // & 00011000b - insn.itype = (code & 0x800) ? PIC_goto : PIC_call; - insn.Op1.type = o_near; - - //We have 000x x000 for pclath and 10 1kkk kkkk kkkk for code - //Operation : 000x x000 0000 0000 | 00 0kkk kkkk kkkk - //Result : 000x xkkk kkkk kkkk - insn.Op1.addr = (pclath << (11 - 3)) | (code & 0x7FF); - insn.Op1.dtype = dt_code; - } - break; - - // 11 xxxx xxxx xxxx - case 3: - // 11 00xx kkkk kkkk MOVLW k Move literal to W - // 11 0001 1kkk kkkk MOVLP k Move literal to PCLATH - // 11 0001 0nkk kkkk ADDFSR n, k Add Literal to FSRn - // 11 001k kkkk kkkk BRA k Relative Branch - // 11 01xx kkkk kkkk RETLW k Return with literal in W - // 11 0111 dfff ffff ASRF f, d Arithmetic Right Shift - // 11 0101 dfff ffff LSLF f, d Logical Left Shift - // 11 0110 dfff ffff LSRF f, d Logical Right Shift - // 11 1000 kkkk kkkk IORLW k Inclusive OR literal with W - // 11 1001 kkkk kkkk ANDLW k AND literal with W - // 11 1010 kkkk kkkk XORLW k Exclusive OR literal with W - // 11 1011 dfff ffff SUBWFB f, d Subtract W from f with Borrow - // 11 1100 kkkk kkkk SUBLW k Subtract W from literal - // 11 1101 dfff ffff ADDWFC f, d Add with Carry W and f - // 11 111x kkkk kkkk ADDLW k Add literal and W - // 11 1111 0nkk kkkk MOVIW ?? Move INDFn to W - // 11 1111 1nkk kkkk MOVWI ?? Move W to INDFn - { - static const ushort codes[16] = - { - PIC_movlw, PIC_movlp, PIC_bra, PIC_bra, - PIC_retlw, PIC_lslf, PIC_lsrf, PIC_asrf, - PIC_iorlw, PIC_andlw, PIC_xorlw, PIC_subwfb, - PIC_sublw, PIC_addwfc, PIC_addlw, PIC_moviw - }; - insn.itype = codes[b4]; - switch ( insn.itype ) - { - case PIC_movlp: - if ( ((code >> 7) & 1) == 0 ) // 11 0001 0nkk kkkk ADDFSR - { - insn.itype = PIC_addfsr; - insn.Op1.type = o_reg; - insn.Op1.reg = ((code & 0x40) == 0) ? FSR0 : FSR1; - insn.Op1.dtype = dt_byte; - - insn.Op2.type = o_imm; - insn.Op2.value = get_signed(code, 0x3F); - insn.Op2.dtype = dt_byte; - } - else // 11 0001 1kkk kkkk MOVLP - { - insn.itype = PIC_movlp; - insn.Op1.type = o_imm; - insn.Op1.value = code & 0x7F; - insn.Op1.dtype = dt_byte; - } - break; - - case PIC_bra: - insn.Op1.type = o_near; - insn.Op1.addr = insn.ea + 1 + get_signed(code, 0x01FF); // PC + 1 + operand value - insn.Op1.dtype = dt_code; - break; - - case PIC_addwfc: - case PIC_asrf: - case PIC_lslf: - case PIC_lsrf: - case PIC_subwfb: - opf14(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = ( (code & 0x80) != 0) ? F : W; - insn.Op2.dtype = dt_byte; - break; - - case PIC_moviw: - if ( ((code >> 7) & 1) == 0 ) // 11 1111 0nkk kkkk MOVIW - insn.itype = PIC_moviw; - else // 11 1111 1nkk kkkk MOVWI - insn.itype = PIC_movwi; - - insn.Op1.type = o_displ; - insn.Op1.phrase = ((code & 0x40) == 0) ? FSR0 : FSR1; - insn.Op1.addr = get_signed(code, 0x3F); - insn.Op1.dtype = dt_byte; - break; - - default: - insn.Op1.type = o_imm; - insn.Op1.value = code & 0xFF; - insn.Op1.dtype = dt_byte; - break; - } - } - break; - } -} - -//-------------------------------------------------------------------------- -static void basic_ana16(insn_t &insn, int code) -{ - if ( ( code >> 12 ) == 0 ) - { - int b3 = code >> 4; - if ( b3 == 0 ) - { -// 0000 0000 0000 0000 NOP No Operation -// 0000 0000 0000 0011 SLEEP Go into standby mode -// 0000 0000 0000 0100 CLRWDT Clear Watchdog Timer -// 0000 0000 0000 0101 PUSH Push top of return stack -// 0000 0000 0000 0110 POP Pop top of return stack -// 0000 0000 0000 0111 DAW Decimal Adjust W -// 0000 0000 0000 1000 TBLRD* Table Read -// 0000 0000 0000 1001 TBLRD*+ Table Read with post-increment -// 0000 0000 0000 1010 TBLRD*- Table Read with post-decrement -// 0000 0000 0000 1011 TBLRD+* Table Read with pre-increment -// 0000 0000 0000 1100 TBLWT* Table Write -// 0000 0000 0000 1101 TBLWT*+ Table Write with post-increment -// 0000 0000 0000 1110 TBLWT*- Table Write with post-decrement -// 0000 0000 0000 1111 TBLWT+* Table Write with pre-increment - static const ushort codes[16] = - { - PIC_nop, PIC_null, PIC_null, PIC_sleep, - PIC_clrwdt, PIC_push0, PIC_pop0, PIC_daw0, - PIC_tblrd0, PIC_tblrd0p, PIC_tblrd0m, PIC_tblrdp0, - PIC_tblwt0, PIC_tblwt0p, PIC_tblwt0m, PIC_tblwtp0 - }; - insn.itype = codes[code & 15]; - } - else if ( b3 < 0x80 ) - { - if ( ( code & 0xFFFC ) == 0x0010 ) - { -// 0000 0000 0001 000s RETFIE s Return from interrupt enable -// 0000 0000 0001 001s RETURN s Return from Subroutine - insn.itype = (code & 0x2) ? PIC_return1 : PIC_retfie1; - if ( code & 1 ) - { - insn.Op1.type = o_reg; - insn.Op1.reg = FAST; - } - else - { - insn.Op1.type = o_imm; - insn.Op1.value = 0; - } - insn.Op1.dtype = dt_byte; - } - else if ( code == 0x00FF ) - { -// 0000 0000 1111 1111 RESET Software device Reset - insn.itype = PIC_reset0; - } - else if ( ( code & 0xFFF0 ) == 0x0100 ) - { -// 0000 0001 0000 kkkk MOVLB k Move literal to BSR - insn.itype = PIC_movlb1; - insn.Op1.type = o_imm; - insn.Op1.value = code & 0xF; - insn.Op1.dtype = dt_byte; - } - else if ( ( code & 0xFE00 ) == 0x0200 ) - { -// 0000 001a ffff ffff MULWF f, a Multiply W with f - insn.itype = PIC_mulwf2; - opfa16(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = (code & 0x100) ? BANKED : ACCESS; - insn.Op2.dtype = dt_byte; - } - else if ( ( code & 0xFC00 ) == 0x0400 ) - { -// 0000 01da ffff ffff DECF f, d, a Decrement f - insn.itype = PIC_decf3; - opfa16(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = (code & 0x200) ? F : W; - insn.Op2.dtype = dt_byte; - insn.Op3.type = o_reg; - insn.Op3.reg = (code & 0x100) ? BANKED : ACCESS; - insn.Op3.dtype = dt_byte; - } - else - { - insn.itype = PIC_null; - } - } - else - { -// 0000 1000 kkkk kkkk SUBLW k Subtract W from literal -// 0000 1001 kkkk kkkk IORLW k Inclusive OR literal with W -// 0000 1010 kkkk kkkk XORLW k Exclusive OR literal with W -// 0000 1011 kkkk kkkk ANDLW k AND literal with W -// 0000 1100 kkkk kkkk RETLW k Return with literal in W -// 0000 1101 kkkk kkkk MULLW k Multiply literal with W -// 0000 1110 kkkk kkkk MOVLW k Move literal to W -// 0000 1111 kkkk kkkk ADDLW k Add literal and W - static const ushort codes[16] = - { - PIC_sublw, PIC_iorlw, PIC_xorlw, PIC_andlw, - PIC_retlw, PIC_mullw1, PIC_movlw, PIC_addlw - }; - insn.itype = codes[(code>>8)&7]; - insn.Op1.type = o_imm; - insn.Op1.value = (char)code; - insn.Op1.dtype = dt_byte; - } - } - else if ( ( code >> 14 ) <= 2 ) - { - int b1 = code >> 12; - if ( b1 <= 5 ) - { -// 0001 00da ffff ffff IORWF f, d, a Inclusive OR W with f -// 0001 01da ffff ffff ANDWF f, d, a AND W with f -// 0001 10da ffff ffff XORWF f, d, a Exclusive OR W with f -// 0001 11da ffff ffff COMF f, d, a Complement f -// 0010 00da ffff ffff ADDWFC f, d, a Add W and Carry to f -// 0010 01da ffff ffff ADDWF f, d, a Add W and f -// 0010 10da ffff ffff INCF f, d, a Increment f -// 0010 11da ffff ffff DECFSZ f, d, a Decrement f, Skip if 0 -// 0011 00da ffff ffff RRCF f, d, a Rotate Right f through Carry -// 0011 01da ffff ffff RLCF f, d, a Rotate Left f through Carry -// 0011 10da ffff ffff SWAPF f, d, a Swap nibbles in f -// 0011 11da ffff ffff INCFSZ f, d, a Increment f, Skip if 0 -// 0100 00da ffff ffff RRNCF f, d, a Rotate Right f -// 0100 01da ffff ffff RLNCF f, d, a Rotate Left f -// 0100 10da ffff ffff INFSNZ f, d, a Increment f, Skip if not 0 -// 0100 11da ffff ffff DCFSNZ f, d, a Decrement f, Skip if not 0 -// 0101 00da ffff ffff MOVF f, d, a Move f -// 0101 01da ffff ffff SUBFWB f, d, a Substract f from W with borrow -// 0101 10da ffff ffff SUBWFB f, d, a Substract W from f with borrow -// 0101 11da ffff ffff SUBWF f, d, a Substract W from f - static const ushort codes[24] = - { - PIC_null, PIC_null, PIC_null, PIC_null, - PIC_iorwf3, PIC_andwf3, PIC_xorwf3, PIC_comf3, - PIC_addwfc3, PIC_addwf3, PIC_incf3, PIC_decfsz3, - PIC_rrcf3, PIC_rlcf3, PIC_swapf3, PIC_incfsz, - PIC_rrncf3, PIC_rlncf3, PIC_infsnz3, PIC_dcfsnz3, - PIC_movf3, PIC_subfwb3, PIC_subwfb3, PIC_subwf3, - }; - QASSERT(10097, (code>>10) < 24); - insn.itype = codes[code>>10]; - opfa16(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = (code & 0x200) ? F : W; - insn.Op2.dtype = dt_byte; - insn.Op3.type = o_reg; - insn.Op3.reg = (code & 0x100) ? BANKED : ACCESS; - insn.Op3.dtype = dt_byte; - } - else if ( b1 == 6 ) - { -// 0110 000a ffff ffff CPFSLT f, a Compare f with W, Skip if < -// 0110 001a ffff ffff CPFSEQ f, a Compare f with W, Skip if == -// 0110 010a ffff ffff CPFSGT f, a Compare f with W, Skip if > -// 0110 011a ffff ffff TSTFSZ f, a Test f, Skip if 0 -// 0110 100a ffff ffff SETF f, a Set f -// 0110 101a ffff ffff CLRF f, a Clear f -// 0110 110a ffff ffff NEGF f, a Negate f -// 0110 111a ffff ffff MOVWF f, a Move W to f - static const ushort codes[8] = - { - PIC_cpfslt2, PIC_cpfseq2, PIC_cpfsgt2, PIC_tstfsz2, - PIC_setf2, PIC_clrf2, PIC_negf2, PIC_movwf2, - }; - insn.itype = codes[(code>>9)&7]; - opfa16(insn, code); - insn.Op2.type = o_reg; - insn.Op2.reg = (code & 0x100) ? BANKED : ACCESS; - insn.Op2.dtype = dt_byte; - } - else - { -// 0111 bbba ffff ffff BTG f, b, a Bit Toggle f -// 1000 bbba ffff ffff BSF f, b, a Bit Set f -// 1001 bbba ffff ffff BCF f, b, a Bit Clear f -// 1010 bbba ffff ffff BTFSS f, b, a Bit Test f, Skip if Set -// 1011 bbba ffff ffff BTFSC f, b, a Bit Test f, Skip if Clear - static const ushort codes[5] = - { - PIC_btg3, PIC_bsf3, PIC_bcf3, PIC_btfss3, PIC_btfsc3 - }; - QASSERT(10098, (b1-7) < 5); - insn.itype = codes[b1-7]; - opfa16(insn, code); - insn.Op2.type = o_imm; - insn.Op2.value = (code >> 9) & 7; - insn.Op2.dtype = dt_byte; - insn.Op3.type = o_reg; - insn.Op3.reg = (code & 0x100) ? BANKED : ACCESS; - insn.Op3.dtype = dt_byte; - } - } - else - { - int b2 = ( code >> 12 ) & 3; - int b3 = ( code >> 8 ) & 0x0F; - switch ( b2 ) - { - case 0: -// 1100 ffff ffff ffff 1111 ffff ffff ffff MOVFF fs, fd Move fs to fd - insn.itype = PIC_movff2; - insn.Op1.type = o_mem; - insn.Op1.dtype = dt_byte; - insn.Op1.addr = code & 0xFFF; - insn.Op2.type = o_mem; - insn.Op2.dtype = dt_byte; - insn.Op2.addr = insn.get_next_word() & 0xFFF; - break; - case 1: -// 1101 0nnn nnnn nnnn BRA n Branch unconditionally -// 1101 1nnn nnnn nnnn RCALL n Relative Call subroutine - insn.itype = (code & 0x800) ? PIC_rcall1 : PIC_bra1; - insn.Op1.type = o_near; - insn.Op1.addr = (insn.ea + 2 + 2 * get_signed(code,0x07FF)) & PIC18_IP_RANGE; - insn.Op1.dtype = dt_code; - break; - case 2: - if ( b3 <= 7 ) - { -// 1110 0000 nnnn nnnn BZ n Branch if Zero -// 1110 0001 nnnn nnnn BNZ n Branch if not Zero -// 1110 0010 nnnn nnnn BC n Branch if Carry -// 1110 0011 nnnn nnnn BNC n Branch if not Carry -// 1110 0100 nnnn nnnn BOV n Branch if Overflow -// 1110 0101 nnnn nnnn BNOV n Branch if not Overflow -// 1110 0110 nnnn nnnn BN n Branch if Negative -// 1110 0111 nnnn nnnn BNN n Branch if not Negative - static const ushort codes[8] = - { - PIC_bz1, PIC_bnz1, PIC_bc1, PIC_bnc1, - PIC_bov1, PIC_bnov1, PIC_bn1, PIC_bnn1 - }; - insn.itype = codes[(code>>8)&7]; - insn.Op1.type = o_near; - insn.Op1.addr = (insn.ea + 2 + 2 * get_signed(code,0x00FF)) & PIC18_IP_RANGE; - insn.Op1.dtype = dt_code; - } - else if ( b3 == 0xC || b3 == 0xD || b3 == 0xF ) - { -// 1110 110s kkkk kkkk 1111 kkkk kkkk kkkk CALL n, s Call subroutine -// 1110 1111 kkkk kkkk 1111 kkkk kkkk kkkk GOTO n Go to address - static const ushort codes[4] = - { - PIC_call2, PIC_call2, PIC_null, PIC_goto - }; - insn.itype = codes[(code>>8)&3]; - insn.Op1.type = o_near; - insn.Op1.addr = ((insn.get_next_word() & 0xFFF) << 9) | ((code & 0x00FF) << 1); - insn.Op1.dtype = dt_code; - if ( insn.itype == PIC_call2 ) - { - if ( code & 0x0100 ) - { - insn.Op2.type = o_reg; - insn.Op2.reg = FAST; - } - else - { - insn.Op2.type = o_imm; - insn.Op2.value = 0; - } - insn.Op2.dtype = dt_byte; - } - } - else if ( ( code & 0xFFC0 ) == 0xEE00 ) - { -// 1110 1110 00ff kkkk 1111 0000 kkkk kkkk LFSR f, k Move literal to FSR - insn.itype = PIC_lfsr2; - insn.Op1.type = o_reg; - insn.Op1.reg = FSR0 + ((code >> 4) & 3); - insn.Op1.dtype = dt_byte; - insn.Op2.type = o_imm; - insn.Op2.value = ((code&0xF) << 8 ) | (insn.get_next_word() & 0xFF); - insn.Op2.dtype = dt_word; - } - else - { - insn.itype = PIC_null; - } - break; - case 3: -// 1111 xxxx xxxx xxxx NOP No Operation - insn.itype = PIC_nop; - break; - } - } -} - -//-------------------------------------------------------------------------- -int pic_t::basic_ana(insn_t &insn) -{ - int code; - - switch ( ptype ) - { - case PIC12: - code = get_wide_byte(insn.ea); insn.size = 1; - basic_ana12(insn, code); - break; - case PIC14: - code = get_wide_byte(insn.ea); insn.size = 1; - basic_ana14(insn, code); - break; - case PIC16: - code = insn.get_next_word(); - basic_ana16(insn, code); - break; - default: - error("interr: ana"); - } - if ( insn.itype == PIC_null ) - return 0; - return insn.size; -} diff --git a/idasdk75/module/pic/emu.cpp b/idasdk75/module/pic/emu.cpp deleted file mode 100644 index 21d1ca0..0000000 --- a/idasdk75/module/pic/emu.cpp +++ /dev/null @@ -1,509 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "pic.hpp" -#include <segregs.hpp> -#include <frame.hpp> - -//------------------------------------------------------------------------ -bool pic_t::is_banked_reg(ea_t addr, int value) const -{ - // on PIC12, bank size is 0x20 - // on PIC14, bank size is 0x80 - if ( ptype == PIC12 ) - return (addr & 0x1F ) == value; - if ( ptype == PIC14 ) - return (addr & 0x7F ) == value; - return false; -} - -//------------------------------------------------------------------------ -// is pcl register? -bool pic_t::is_pcl(const insn_t &insn) const -{ - if ( insn.Op1.type == o_mem ) - { - switch ( ptype ) - { - case PIC12: - case PIC14: return is_banked_reg(insn.Op1.addr, 0x2); - case PIC16: return insn.Op1.addr == PIC16_PCL; - } - } - return false; -} - -//------------------------------------------------------------------------ -// is bank (status or bsr (PIC18Cxx)) register? -bool pic_t::is_bank(const insn_t &insn) const -{ - if ( insn.Op1.type == o_mem ) - { - switch ( ptype ) - { - case PIC12: - case PIC14: return is_banked_reg(insn.Op1.addr, 0x3); - case PIC16: return insn.Op1.addr == PIC16_BANK; - } - } - return false; -} - -//------------------------------------------------------------------------ -// is pclath register? -bool pic_t::is_pclath(const insn_t &insn) const -{ - if ( insn.Op1.type == o_mem ) - { - switch ( ptype ) - { - case PIC12: return false; - case PIC14: return is_banked_reg(insn.Op1.addr, 0xA); - case PIC16: return insn.Op1.addr == PIC16_PCLATH; - } - } - return false; -} - -//------------------------------------------------------------------------ -void pic_t::process_immediate_number(const insn_t &insn, int n) const -{ - set_immd(insn.ea); - if ( is_defarg(get_flags(insn.ea), n) ) - return; - switch ( insn.itype ) - { - case PIC_iorlw: - case PIC_andlw: - case PIC_xorlw: - op_num(insn.ea, n); - break; - case PIC_lfsr2: - // FSRs are used to address the data memory - if ( dataseg != BADADDR ) - op_offset(insn.ea, n, REF_OFF16, BADADDR, dataseg); - break; - } -} - -//---------------------------------------------------------------------- -void pic_t::destroy_if_unnamed_array(ea_t ea) const -{ - flags_t lF = get_flags(ea); - if ( is_tail(lF) && segtype(ea) == SEG_IMEM ) - { - ea_t head = prev_not_tail(ea); - if ( !has_user_name(get_flags(head)) ) - { - del_items(head, DELIT_SIMPLE); - create_byte(head, ea-head); - ea_t end = next_that(ea, inf_get_max_ea(), f_is_head); - if ( end == BADADDR ) - end = getseg(ea)->end_ea; - create_byte(ea+1, end-ea-1); - } - } -} - -//---------------------------------------------------------------------- -// propagate the bank/pclath register value to the destination -void pic_t::propagate_sreg(const insn_t &insn, ea_t ea, int reg) const -{ - if ( is_loaded(ea) ) - { - sel_t v = get_sreg(insn.ea, reg); - split_sreg_range(ea, reg, v, SR_auto); - } -} - -//---------------------------------------------------------------------- -void pic_t::handle_operand(const insn_t &insn, const op_t &x, int, bool isload) -{ - if ( insn.Op2.type == o_reg && insn.Op2.reg == F || insn.itype == PIC_swapf ) - isload = 0; - switch ( x.type ) - { - case o_reg: - return; - case o_imm: - if ( !isload ) - error("interr: emu"); - process_immediate_number(insn, x.n); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, dr_O, calc_outf(x)); - break; - case o_near: - { - cref_t ftype = fl_JN; - ea_t ea = calc_code_mem(insn, x.addr); - if ( has_insn_feature(insn.itype, CF_CALL) ) - { - if ( !func_does_return(ea) ) - flow = false; - ftype = fl_CN; - } - insn.add_cref(ea, x.offb, ftype); - propagate_sreg(insn, ea, BANK); - propagate_sreg(insn, ea, PCLATH); - } - break; - case o_mem: - { - ea_t ea = calc_data_mem(x.addr); - destroy_if_unnamed_array(ea); - insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); - insn.create_op_data(ea, x); - if ( may_create_stkvars() ) - { - if ( x.addr == PIC16_INDF2 ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) - { - insn.create_stkvar(insn.Op1, 0, STKVAR_VALID_SIZE); - } - } - else if ( x.addr == PIC16_PLUSW2 ) - { - insn_t l = insn; - if ( decode_prev_insn(&l, l.ea) != BADADDR - && l.itype == PIC_movlw ) - { - func_t *pfn = get_func(l.ea); - if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) - { - if ( l.create_stkvar(l.Op1, l.Op1.value, STKVAR_VALID_SIZE) ) - op_stkvar(l.ea, l.Op1.n); - } - } - } - } - } - break; - case o_displ: - process_immediate_number(insn, x.n); - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - insn.add_off_drefs(x, dr_O, OOF_ADDR | OOFW_8); - break; - default: - INTERR(10310); - } -} - -//---------------------------------------------------------------------- -// change value of virtual register "BANK" and switch to another bank -void pic_t::split(const insn_t &insn, int reg, sel_t v) -{ - if ( reg == -1 ) - { - flow = 0; - if ( v != BADSEL ) - { - sel_t pclath = get_sreg(insn.ea, PCLATH) & 0x1F; - ea_t ea = calc_code_mem(insn, uchar(v) | (pclath<<8)); - add_cref(insn.ea, ea, fl_JN); - propagate_sreg(insn, ea, BANK); - propagate_sreg(insn, ea, PCLATH); - } - } - else - { - if ( v == BADSEL ) - v = 0; // assume bank0 if bank is unknown - if ( reg == BANK ) - { - // banks 0..15 - v &= 0xF; - } - split_sreg_range(get_item_end(insn.ea), reg, v, SR_auto); - } -} - -//---------------------------------------------------------------------- -// tris PORTn (or movwf TRISn) -bool pic_t::is_load_tris_reg(const insn_t &insn) -{ - ea_t addr; - const char *key; - switch ( insn.itype ) - { - case PIC_tris: - addr = insn.Op1.value; - key = "port"; - break; - case PIC_movwf: - addr = insn.Op1.addr; - key = "tris"; - break; - default: - return false; - } - qstring name; - addr = calc_data_mem(addr); - if ( get_name(&name, addr, GN_NOT_DUMMY) <= 0 ) - return false; - return strnieq(name.begin(), key, 4); -} - -//------------------------------------------------------------------ -inline void pic_t::set_plain_offset(ea_t insn_ea, int n, ea_t base) const -{ - if ( base == BADADDR ) - base = calc_offset_base(insn_ea, n); - if ( base != BADADDR ) - op_plain_offset(insn_ea, n, base); -} - -//---------------------------------------------------------------------- -int pic_t::emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - flow = (Feature & CF_STOP) == 0; - - int bit = CF_USE1; - bool use = true; - while ( true ) - { - for ( int i=0; i < 3; i++,bit<<=1 ) - { - if ( (Feature & bit) == 0 ) - continue; - bool forced = is_forced_operand(insn.ea, i); - handle_operand(insn, insn.ops[i], forced, use); - } - if ( !use ) - break; - use = false; - bit = CF_CHG1; - } - - // Check for: - // - the register bank changes - // - PCLATH changes - // - PCL changes - bool check_regs = false; - switch ( insn.itype ) - { - case PIC_movlp: //Move literal to PCLATH - split(insn, PCLATH, insn.Op1.value); - break; - case PIC_movlb: //Move literal to BSR - split(insn, BANK, insn.Op1.value); - break; - default: - check_regs = true; - break; - } - - for ( int i=0; check_regs && i < 3; i++ ) - { - int reg = 0; - switch ( i ) - { - case 0: - reg = BANK; - if ( !is_bank(insn) ) - continue; - break; - case 1: - reg = PCLATH; - if ( !is_pclath(insn) ) - continue; - break; - case 2: - reg = -1; - if ( !is_pcl(insn) ) - continue; - break; - } - sel_t v = (reg == -1) ? insn.ip : get_sreg(insn.ea, reg); - if ( insn.Op2.type == o_reg && insn.Op2.reg == F ) - { -// split(insn, reg, v); - } - else - { - switch ( insn.itype ) - { - case PIC_bcf: - case PIC_bcf3: - case PIC_bsf: - case PIC_bsf3: - if ( (ptype == PIC12 && insn.Op2.value == 5) // bank selector (PA0) - || (ptype == PIC14 - && ((reg == BANK && (insn.Op2.value == 5 || insn.Op2.value == 6)) // bank selector (RP1:RP0) - || (reg == PCLATH && (insn.Op2.value == 3 || insn.Op2.value == 4)))) - || (ptype == PIC16 && sval_t(insn.Op2.value) >= 0 && insn.Op2.value <= 3) ) - { - if ( v == BADSEL ) - v = 0; - int shift = 0; - if ( (ptype == PIC14 || ptype == PIC12) && reg == BANK ) // we use bank selector bits as the bank value - shift = 5; - if ( insn.itype == PIC_bcf ) - v = v & ~(sel_t(1) << (insn.Op2.value-shift)); - else - v = v | (sel_t(1) << (insn.Op2.value-shift)); - split(insn, reg, v); - } - break; - case PIC_clrf: - case PIC_clrf2: - split(insn, reg, 0); - break; - case PIC_swapf: - case PIC_swapf3: - split(insn, reg, ((v>>4) & 15) | ((v & 15) << 4)); - break; - case PIC_movwf: - case PIC_movwf2: - case PIC_addlw: - case PIC_andlw: - case PIC_iorlw: - case PIC_sublw: - case PIC_xorlw: - { - insn_t l = insn; - if ( decode_prev_insn(&l, l.ea) != BADADDR - && l.itype == PIC_movlw ) - { - switch ( insn.itype ) - { - case PIC_movwf: - case PIC_movwf2: - v = l.Op1.value; - break; - case PIC_addlw: - v += l.Op1.value; - break; - case PIC_andlw: - v &= l.Op1.value; - break; - case PIC_iorlw: - v |= l.Op1.value; - break; - case PIC_sublw: - v -= l.Op1.value; - break; - case PIC_xorlw: - v ^= l.Op1.value; - break; - } - } - else - { - v = BADSEL; - } - } - split(insn, reg, v); - break; - case PIC_movlw: - split(insn, reg, insn.Op2.value); - break; - } - } - } - -// Such as, IDA doesn't seem to convert the following: -// tris 6 -// into -// tris PORTB ( or whatever ) - - flags_t flags = get_flags(insn.ea); - if ( insn.itype == PIC_tris && !is_defarg0(flags) ) - set_plain_offset(insn.ea, 0, dataseg); - -// movlw value -// followed by a -// movwf FSR -// should convert value into an offset , because FSR is used as a pointer to -// the INDF (indirect addressing file) - - if ( insn.itype == PIC_movwf - && insn.Op1.type == o_mem - && is_banked_reg(insn.Op1.addr, 0x4) ) // FSR - { - insn_t l = insn; - if ( decode_prev_insn(&l, l.ea) != BADADDR - && l.itype == PIC_movlw ) - { - set_plain_offset(l.ea, 0, dataseg); - } - } - -// Also - it seems to make sense to me that a -// movlw value -// followed by a -// tris PORTn (or movwf TRISn) -// should convert value into a binary , because the bits indicate whether a -// port is defined for input or output. - - if ( is_load_tris_reg(insn) ) - { - insn_t l; - if ( decode_prev_insn(&l, insn.ea) != BADADDR - && l.itype == PIC_movlw ) - { - op_bin(l.ea, 0); - } - } - -// Move litteral to BSR - - if ( insn.itype == PIC_movlb1 ) - split(insn, BANK, insn.Op1.value); - -// -// Determine if the next instruction should be executed -// - if ( !flow ) - { - flags = get_flags(insn.ea); - flow = conditional_insn(insn, flags); - } - if ( segtype(insn.ea) == SEG_XTRN ) - flow = false; - if ( flow ) - add_cref(insn.ea, insn.ea+insn.size, fl_F); - - return 1; -} - -//---------------------------------------------------------------------- -bool pic_t::create_func_frame(func_t *pfn) const -{ - if ( pfn != NULL ) - { - if ( pfn->frame == BADNODE ) - { - ea_t ea = pfn->start_ea; - if ( ea + 12 < pfn->end_ea ) // minimum 4 + 4 + 2 + 2 bytes needed - { - insn_t insn[4]; - for ( int i=0; i < 4; i++ ) - { - int len = decode_insn(&insn[i], ea); - ea += len > 0 ? len : 0; - } - if ( insn[0].itype == PIC_movff2 // movff FSR2L,POSTINC1 - && insn[0].Op1.addr == PIC16_FSR2L && insn[0].Op2.addr == PIC16_POSTINC1 - && insn[1].itype == PIC_movff2 // movff FSR1L,FSR2L - && insn[1].Op1.addr == PIC16_FSR1L && insn[1].Op2.addr == PIC16_FSR2L - && insn[2].itype == PIC_movlw // movlw <size> - && insn[3].itype == PIC_addwf3 // addwf FSR1L,f - && insn[3].Op1.addr == PIC16_FSR1L && insn[3].Op2.reg == F ) - { - pfn->flags |= FUNC_FRAME; - return add_frame(pfn, insn[2].Op1.value, 0, 0); - } - } - } - } - return 0; -} diff --git a/idasdk75/module/pic/ins.hpp b/idasdk75/module/pic/ins.hpp deleted file mode 100644 index d15834a..0000000 --- a/idasdk75/module/pic/ins.hpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - -PIC_null = 0, // Unknown Operation - -// BYTE-ORIENTED FILE REGISTER OPERATIONS - -PIC_addwf, // Add W and f -PIC_andwf, // AND W with f -PIC_clrf, // Clear f -PIC_clrw, // Clear W -PIC_comf, // Complement f -PIC_decf, // Decrement f -PIC_decfsz, // Decrement f, Skip if 0 -PIC_incf, // Increment f -PIC_incfsz, // Increment f, Skip if 0 -PIC_iorwf, // Inclusive OR W with f -PIC_movf, // Move f -PIC_movwf, // Move W to f -PIC_nop, // No Operation -PIC_rlf, // Rotate Left f through Carry -PIC_rrf, // Rotate Right f through Carry -PIC_subwf, // Subtract W from f -PIC_swapf, // Swap nibbles in f -PIC_xorwf, // Exclusive OR W with f - -// BIT-ORIENTED FILE REGISTER OPERATIONS - -PIC_bcf, // Bit Clear f -PIC_bsf, // Bit Set f -PIC_btfsc, // Bit Test f, Skip if Clear -PIC_btfss, // Bit Test f, Skip if Set - - -// LITERAL AND CONTROL OPERATIONS - -PIC_addlw, // Add literal and W -PIC_andlw, // AND literal with W -PIC_call, // Call subroutine -PIC_clrwdt, // Clear Watchdog Timer -PIC_goto, // Go to address -PIC_iorlw, // Inclusive OR literal with W -PIC_movlw, // Move literal to W -PIC_retfie, // Return from interrupt -PIC_retlw, // Return with literal in W -PIC_return, // Return from Subroutine -PIC_sleep, // Go into standby mode -PIC_sublw, // Subtract W from literal -PIC_xorlw, // Exclusive OR literal with W - -// ADDITIONAL INSTRUCTIONS TO MAINTAIN COMPITIBILITY WITH 12C5xx,16C5x - -PIC_option, // Load OPTION register -PIC_tris, // Load TRIS Register - -// MACROS - -PIC_movfw, // Move Contents of File Reg to W -PIC_tstf, // Test Contents of File Register -PIC_negf, // Negate File Register Contents -PIC_b, // Branch to Address -PIC_clrc, // Clear Carry -PIC_clrdc, // Clear Digit Carry -PIC_clrz, // Clear Zero -PIC_setc, // Set Carry -PIC_setdc, // Set Digit Carry -PIC_setz, // Set Zero -PIC_skpc, // Skip on Carry -PIC_skpdc, // Skip on Digit Carry -PIC_skpnc, // Skip on No Carry -PIC_skpndc, // Skip on No Digit Carry -PIC_skpnz, // Skip on No Zero -PIC_skpz, // Skip on Zero -PIC_bc, // Branch on Carry to Address k -PIC_bdc, // Branch on Digit Carry to k -PIC_bnc, // Branch on No Carry to k -PIC_bndc, // Branch on No Digit Carry to k -PIC_bnz, // Branch on No Zero to Address -PIC_bz, // Branch on Zero to Address k -PIC_addcf, // Add Carry to File Register -PIC_adddcf, // Add Digit to File Register -PIC_subcf, // Subtract Carry from File Reg - -// ADDITIONAL INSTRUCTIONS FOR 18Cxx - -// BYTE-ORIENTED FILE REGISTER OPERATIONS - -PIC_addwf3, // Add W and f -PIC_addwfc3, // Add W and Carry to f -PIC_andwf3, // AND W with f -PIC_clrf2, // Clear f -PIC_comf3, // Complement f -PIC_cpfseq2, // Compare f with W, Skip if == -PIC_cpfsgt2, // Compare f with W, Skip if > -PIC_cpfslt2, // Compare f with W, Skip if < -PIC_decf3, // Decrement f -PIC_decfsz3, // Decrement f, Skip if 0 -PIC_dcfsnz3, // Decrement f, Skip if not 0 -PIC_incf3, // Increment f -PIC_incfsz3, // Increment f, Skip if 0 -PIC_infsnz3, // Increment f, Skip if not 0 -PIC_iorwf3, // Inclusive OR W with f -PIC_movf3, // Move f -PIC_movff2, // Move fs to fd -PIC_movwf2, // Move W to f -PIC_mulwf2, // Multiply W with f -PIC_negf2, // Negate f -PIC_rlcf3, // Rotate Left f through Carry -PIC_rlncf3, // Rotate Left f -PIC_rrcf3, // Rotate Right f through Carry -PIC_rrncf3, // Rotate Right f -PIC_setf2, // Set f -PIC_subfwb3, // Substract f from W with borrow -PIC_subwf3, // Substract W from f -PIC_subwfb3, // Substract W from f with borrow -PIC_swapf3, // Swap nibbles in f -PIC_tstfsz2, // Test f, Skip if 0 -PIC_xorwf3, // Exclusive OR W with f - -// BIT-ORIENTED FILE REGISTER OPERATIONS - -PIC_bcf3, // Bit Clear f -PIC_bsf3, // Bit Set f -PIC_btfsc3, // Bit Test f, Skip if Clear -PIC_btfss3, // Bit Test f, Skip if Set -PIC_btg3, // Bit Toggle f - -// CONTROL OPERATIONS - -PIC_bc1, // Branch if Carry -PIC_bn1, // Branch if Negative -PIC_bnc1, // Branch if not Carry -PIC_bnn1, // Branch if not Negative -PIC_bnov1, // Branch if not Overflow -PIC_bnz1, // Branch if not Zero -PIC_bov1, // Branch if Overflow -PIC_bra1, // Branch unconditionally -PIC_bz1, // Branch if Zero -PIC_call2, // Call subroutine -// PIC_clrwdt -PIC_daw0, // Decimal Adjust W -// PIC_goto -// PIC_nop -// PIC_nop -PIC_pop0, // Pop top of return stack -PIC_push0, // Push top of return stack -PIC_rcall1, // Relative Call subroutine -PIC_reset0, // Software device Reset -PIC_retfie1, // Return from interrupt enable -// PIC_retlw -PIC_return1, // Return from Subroutine -// PIC_sleep - -// LITERAL OPERATIONS - -// PIC_addlw -// PIC_andlw -// PIC_iorlw -PIC_lfsr2, // Move literal to FSR -PIC_movlb1, // Move literal to BSR -// PIC_movlw -PIC_mullw1, // Multiply literal with W -// PIC_retlw -// PIC_sublw -// PIC_xorlw - -// DATA MEMORY <-> PROGRAM MEMORY OPERATIONS - -PIC_tblrd0, // Table Read -PIC_tblrd0p, // Table Read with post-increment -PIC_tblrd0m, // Table Read with post-decrement -PIC_tblrdp0, // Table Read with pre-increment -PIC_tblwt0, // Table Write -PIC_tblwt0p, // Table Write with post-increment -PIC_tblwt0m, // Table Write with post-decrement -PIC_tblwtp0, // Table Write with pre-increment - -// ADDITIONAL INSTRUCTIONS FOR 16F1x and 12F1x - -PIC_addwfc, // Add W and Carry to f -PIC_movlp, // Move literal to PCLATH -PIC_movlb, // Move literal to BSR -PIC_addfsr, // Add Literal to FSRn -PIC_asrf, // Arithmetic Right Shift -PIC_lslf, // Logical Left Shift -PIC_lsrf, // Logical Right Shift -PIC_subwfb, // Subtract with Borrow W from f -PIC_bra, // Relative Branch -PIC_brw, // Relative Branch with W -PIC_callw, // Call Subroutine with W -PIC_reset, // Software device Reset -PIC_moviw, // Move INDFn to W -PIC_movwi, // Move W to INDFn - -PIC_last, - - }; - -#endif diff --git a/idasdk75/module/pic/makefile b/idasdk75/module/pic/makefile deleted file mode 100644 index f5b93ea..0000000 --- a/idasdk75/module/pic/makefile +++ /dev/null @@ -1,47 +0,0 @@ -PROC=pic -CONFIGS=pic12.cfg pic14.cfg pic16.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp ins.hpp pic.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp pic.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp pic.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp pic.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp pic.hpp reg.cpp diff --git a/idasdk75/module/pic/pic.hpp b/idasdk75/module/pic/pic.hpp deleted file mode 100644 index 7c51a07..0000000 --- a/idasdk75/module/pic/pic.hpp +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _PIC_HPP -#define _PIC_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -enum regnum_t ENUM_SIZE(uint16) -{ - W, F, - ACCESS, // register for PIC18Cxx - BANKED, // register for PIC18Cxx - FAST, // register for PIC18Cxx - FSR0, // register for PIC18Cxx - FSR1, // register for PIC18Cxx - FSR2, // register for PIC18Cxx - BANK, - rVcs, rVds, // virtual registers for code and data segments - PCLATH, - PCLATU // register for PIC18Cxx -}; - -#define PIC16_FSR2L 0xFD9 -#define PIC16_PLUSW2 0xFDB -#define PIC16_INDF2 0xFDF -#define PIC16_BANK 0xFE0 -#define PIC16_FSR1L 0xFE1 -#define PIC16_POSTINC1 0xFE6 -#define PIC16_PCL 0xFF9 -#define PIC16_PCLATH 0xFFA - -//------------------------------------------------------------------ -// processor types - -typedef uchar proctype_t; - -const proctype_t PIC12 = 0; -const proctype_t PIC14 = 1; -const proctype_t PIC16 = 2; - -//------------------------------------------------------------------ -inline bool is_bit_insn(const insn_t &insn) -{ - return insn.itype >= PIC_bcf && insn.itype <= PIC_btfss - || insn.itype >= PIC_bcf3 && insn.itype <= PIC_btg3; -} - -ea_t calc_code_mem(const insn_t &insn, ea_t ea); -int calc_outf(const op_t &x); - -//------------------------------------------------------------------ -void interr(const char *module); - -void idaapi pic_segend(outctx_t &ctx, segment_t *seg); - -int idaapi is_align_insn(ea_t ea); - -int idaapi is_jump_func(const func_t *pfn, ea_t *jump_target); -int idaapi is_sane_insn(int nocrefs); -int idaapi may_be_func(void); // can a function start here? - -//------------------------------------------------------------------ -struct pic_iohandler_t : public iohandler_t -{ - struct pic_t ± - pic_iohandler_t(pic_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} - virtual void get_cfg_filename(char *buf, size_t bufsize) override; - virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct pic_t); - -struct pic_t : public procmod_t -{ - pic_iohandler_t ioh = pic_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - netnode helper; - ea_t dataseg = BADADDR; - - inline void save_idpflags() { helper.altset(-1, idpflags); } - inline void save_dataseg() { helper.altset(0, ea2node(dataseg)); } - -#define IDP_SIMPLIFY 0x0001 // simplify instructions - ushort idpflags = IDP_SIMPLIFY; - inline bool dosimple(void) - { // if macros are enabled, we should simplify insns - return inf_macros_enabled() || (idpflags & IDP_SIMPLIFY) != 0; - } - - proctype_t ptype = PIC12; - const char *cfgname = "pic12.cfg"; - bool set = false; - bool flow = false; - - struct portmap_t - { - ea_t from; - ea_t to; - }; - qvector<portmap_t> map; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void create_mappings(void); - void load_symbols_without_infotype(int _respect_info); - void load_symbols(int _respect_info); - const char *find_sym(ea_t address); - const ioport_bits_t *find_bits(ea_t address); - const char *find_bit(ea_t address, int bit); - void apply_symbols(void); - void setup_device(int lrespect_info); - ea_t AdditionalSegment(size_t size, ea_t offset, const char *name) const; - const char *set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - void set_cpu(int n); - void free_mappings(void); - void add_mapping(ea_t from, ea_t to); - ea_t map_port(ea_t from); - void check_pclath(segment_t *s) const; - - bool build_macro(insn_t &insn, bool may_go_forward); - void simplify(insn_t &insn) const; - int basic_ana(insn_t &insn); - int ana(insn_t *_insn); - - bool is_banked_reg(ea_t addr, int value) const; - bool is_pcl(const insn_t &insn) const; - bool is_bank(const insn_t &insn) const; - bool is_pclath(const insn_t &insn) const; - void process_immediate_number(const insn_t &insn, int n) const; - void destroy_if_unnamed_array(ea_t ea) const; - void propagate_sreg(const insn_t &insn, ea_t ea, int reg) const; - void handle_operand(const insn_t &insn, const op_t &x, int, bool isload); - void split(const insn_t &insn, int reg, sel_t v); - bool is_load_tris_reg(const insn_t &insn); - inline void set_plain_offset(ea_t insn_ea, int n, ea_t base) const; - int emu(const insn_t &insn); - bool create_func_frame(func_t *pfn) const; - - void pic_header(outctx_t &ctx); - int out_equ(outctx_t &ctx); - void out_equ(outctx_t &ctx, bool indent, const char *name, uval_t off); - void pic_data(outctx_t &ctx, bool analyze_only); - ea_t calc_data_mem(ea_t ea); - bool conditional_insn(const insn_t &insn, flags_t F) const; // may instruction be skipped? - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void pic_assumes(outctx_t &ctx); // function to produce assume directives - void pic_segstart(outctx_t &ctx, segment_t *Srange) const; - void pic_footer(outctx_t &ctx) const; -}; -extern int data_id; -#endif // _PIC_HPP diff --git a/idasdk75/module/pic/reg.cpp b/idasdk75/module/pic/reg.cpp deleted file mode 100644 index a370efd..0000000 --- a/idasdk75/module/pic/reg.cpp +++ /dev/null @@ -1,749 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include <ctype.h> -#include "pic.hpp" -#include <diskio.hpp> -#include <segregs.hpp> -int data_id; - -//-------------------------------------------------------------------------- -static const char *const register_names_pic12[] = -{ - "w", "f", - "ACCESS", // register for PIC18Cxx - "BANKED", // register for PIC18Cxx - "FAST", // register for PIC18Cxx - "FSR0", // register for PIC18Cxx - "FSR1", // register for PIC18Cxx - "FSR2", // register for PIC18Cxx - "bank", - "cs","ds", // virtual registers for code and data segments - "status", - "pclatu" // register for PIC18Cxx -}; - -static const char *const register_names_pic14[] = -{ - "w", "f", - "ACCESS", // register for PIC18Cxx - "BANKED", // register for PIC18Cxx - "FAST", // register for PIC18Cxx - "FSR0", // register for PIC18Cxx - "FSR1", // register for PIC18Cxx - "FSR2", // register for PIC18Cxx - "bank", - "cs","ds", // virtual registers for code and data segments - "pclath", - "pclatu" // register for PIC18Cxx -}; - -static const char *const register_names_pic16[] = -{ - "w", "f", - "ACCESS", // register for PIC18Cxx - "BANKED", // register for PIC18Cxx - "FAST", // register for PIC18Cxx - "FSR0", // register for PIC18Cxx - "FSR1", // register for PIC18Cxx - "FSR2", // register for PIC18Cxx - "bsr", - "cs","ds", // virtual registers for code and data segments - "pclath", - "pclatu" // register for PIC18Cxx -}; - -//-------------------------------------------------------------------------- -// 11 01xx kkkk kkkk RETLW k Return with literal in W -static const uchar retcode_0[] = { 0x08, 0x00 }; // return -static const uchar retcode_1[] = { 0x09, 0x00 }; // retfie -static const uchar retcode_2[] = { 0x00, 0x34 }; // retlw 0 -static const uchar retcode_3[] = { 0x01, 0x34 }; // retlw 1 - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Microchip's MPALC -//----------------------------------------------------------------------- -static const asm_t mpalc = -{ - ASH_HEXF2|ASD_DECF3|ASB_BINF5|ASO_OCTF5|AS_N2CHR|AS_NCMAS|AS_ONEDUP, - 0, - "Microchip's MPALC", - 0, - NULL, // header lines - "org", // org - "end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - "data", // ascii string directive - "byte", // byte directive - "data", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "res %s", // uninited arrays - "equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - NULL, // "public" name keyword - NULL, // "weak" name keyword - NULL, // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - NULL, // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &mpalc, NULL }; - -//-------------------------------------------------------------------------- -void pic_t::free_mappings(void) -{ - map.clear(); -} - -void pic_t::add_mapping(ea_t from, ea_t to) -{ - if ( from != to ) - { - deb(IDA_DEBUG_IDP, "add_mapping %a -> %a\n", from, to); - portmap_t &p = map.push_back(); - p.from = from; - p.to = to; - } -} - -ea_t pic_t::map_port(ea_t from) -{ - for ( int i=0; i < map.size(); i++ ) - if ( map[i].from == from ) - return map[i].to; - return from; -} - -//-------------------------------------------------------------------------- -void pic_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) -{ - qstrncpy(buf, pm.cfgname, bufsize); -} - -// create the mapping table -void pic_t::create_mappings(void) -{ - free_mappings(); - for ( int i=0; i < ioh.ports.size(); i++ ) - { - const char *name = ioh.ports[i].name.c_str(); - ea_t nameea = get_name_ea(BADADDR, name); - if ( nameea != BADADDR && nameea > dataseg ) - add_mapping(ioh.ports[i].address, nameea-dataseg); - } -} - -//---------------------------------------------------------------------- -static ea_t AddSegment(ea_t start, size_t size, ea_t base, const char *name, uchar type) -{ - segment_t s; - s.start_ea = start; - s.end_ea = start + size; - s.sel = allocate_selector(base >> 4); - s.type = type; - s.align = saRelByte; - s.comb = scPub; - add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_OR_DIE); - return s.start_ea; -} - -//---------------------------------------------------------------------- -// special handling for 16-bit PICs -// for CODE segments use addresses as-is -// for DATA segments, start from dataseg base -bool pic_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass) -{ - if ( pm.ptype != PIC16 ) - return false; - if ( strcmp(aclass, "CODE") == 0 ) - { - AddSegment(start, end-start, 0, name, SEG_CODE); - } - else if ( strcmp(aclass, "DATA") == 0 ) - { - if ( pm.dataseg == BADADDR ) - pm.dataseg = free_chunk(0, 0x1000, -0xF); - uchar type = stristr(name, "FSR") != NULL ? SEG_IMEM : SEG_DATA; - AddSegment(pm.dataseg + start, end-start, pm.dataseg, name, type); - } - else - { - return false; - } - return true; -} - -void pic_t::load_symbols_without_infotype(int _respect_info) -{ - ioh.ports.clear(); - ioh.respect_info = _respect_info; - iohandler_t::ioports_loader_t ldr(&ioh); - read_ioports2(&ioh.ports, &ioh.device, cfgname, &ldr); - create_mappings(); -} - -void pic_t::load_symbols(int _respect_info) -{ - if ( ioh.display_infotype_dialog(IORESP_ALL, &_respect_info, cfgname) ) - load_symbols_without_infotype(_respect_info); -} - -const char *pic_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port ? port->name.c_str() : NULL; -} - -const ioport_bits_t *pic_t::find_bits(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port ? (&port->bits) : NULL; -} - -const char *pic_t::find_bit(ea_t address, int bit) -{ - address = map_port(address); - const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit); - return b ? b->name.c_str() : NULL; -} - -//---------------------------------------------------------------------- -void pic_t::apply_symbols(void) -{ - free_mappings(); - if ( dataseg != BADADDR ) - { - for ( int i=0; i < ioh.ports.size(); i++ ) - { - ea_t ea = calc_data_mem(ioh.ports[i].address); - segment_t *s = getseg(ea); - if ( s == NULL || s->type != SEG_IMEM ) - continue; - create_byte(ea, 1); - const char *name = ioh.ports[i].name.c_str(); - if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) - set_cmt(ea, name, 0); - } - for ( segment_t *d = getseg(dataseg); d != NULL; d = get_next_seg(d->start_ea) ) - { - if ( d->type != SEG_IMEM ) - continue; - ea_t ea = d->start_ea; - ea_t dataend = d->end_ea; - while ( 1 ) - { - ea = next_unknown(ea, dataend); - if ( ea == BADADDR ) - break; - ea_t end = next_that(ea, dataend, f_is_head); - if ( end == BADADDR ) - end = dataend; - create_byte(ea, end-ea); - } - } - create_mappings(); - } -} - -//------------------------------------------------------------------ -void pic_t::setup_device(int lrespect_info) -{ - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) - { - // we don't pass IORESP_PORT because that would rename bytes in the code segment - // we'll handle port renaming ourselves - if ( ioh.display_infotype_dialog(IORESP_ALL, &lrespect_info, cfgname) ) - { - ioh.set_device_name(ioh.device.c_str(), lrespect_info & ~IORESP_PORT); - if ( (lrespect_info & IORESP_PORT) != 0 ) - apply_symbols(); - } - } -} - -//---------------------------------------------------------------------- -ea_t pic_t::AdditionalSegment(size_t size, ea_t offset, const char *name) const -{ - ea_t start = free_chunk(0, size, -0xF); - return AddSegment(start, size, start - offset, name, SEG_IMEM) - offset; -} - -//-------------------------------------------------------------------------- -static const proctype_t ptypes[] = -{ - PIC12, - PIC14, - PIC16 -}; - -//------------------------------------------------------------------------- -static const cfgopt_t options[] = -{ // name varptr type/bit - CFGOPT_B("PIC_SIMPLIFY", pic_t, idpflags, ushort(IDP_SIMPLIFY)), -}; - -//-------------------------------------------------------------------------- -static const cfgopt_t *find_option(const char *name) -{ - for ( int i=0; i < qnumber(options); i++ ) - if ( streq(options[i].name, name) ) - return &options[i]; - return NULL; -} - -//-------------------------------------------------------------------------- -int idaapi optionscb(int field_id, form_actions_t &fa) -{ - // ensure that instruction simplification can't be turned off - // if macros are enabled - if ( field_id == CB_INIT ) - fa.enable_field(1, !inf_macros_enabled()); - return 1; -} - -//-------------------------------------------------------------------------- -static int idaapi choose_device(int, form_actions_t &fa) -{ - pic_t &pm = *(pic_t *)fa.get_ud(); - if ( choose_ioport_device(&pm.ioh.device, pm.cfgname) ) - { - pm.load_symbols(IORESP_ALL); - pm.apply_symbols(); - } - return 0; -} - -const char *pic_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - if ( keyword == NULL ) - { - if ( ptype != PIC16 ) - { - static const char form[] = -"HELP\n" -"PIC specific options\n" -"\n" -" Simplify instructions\n" -"\n" -" If this option is on, IDA will simplify instructions and replace\n" -" them by clearer macro-instructions\n" -" For example,\n" -"\n" -" btfsc 3,0\n" -"\n" -" will be replaced by\n" -"\n" -" skpnc\n" -"\n" -" If macros are enabled, this options should be turned on.\n" -"ENDHELP\n" -"PIC specific options\n" -"%/%*\n" -" <~S~implify instructions:C1>>\n" -"\n" -" <~C~hoose device name:B:0::>\n" -"\n" -"\n"; - if ( inf_macros_enabled() ) - setflag(idpflags, IDP_SIMPLIFY, true); - CASSERT(sizeof(idpflags) == sizeof(ushort)); - if ( ask_form(form, optionscb, this, &idpflags, choose_device) == ASKBTN_YES ) - { -SAVE: - if ( idb_loaded ) - save_idpflags(); - } - } - else - { - static const char form[] = - "PIC specific options\n" - "\n" - " <~C~hoose device name:B:0::>\n" - "\n" - "\n"; - ask_form(form, choose_device); - } - return IDPOPT_OK; - } - else - { - const cfgopt_t *opt = find_option(keyword); - if ( opt == NULL ) - return IDPOPT_BADKEY; - const char *errmsg = opt->apply(value_type, value, this); - if ( errmsg != IDPOPT_OK ) - return errmsg; - // if macros are enabled, we should simplify insns - if ( ph.supports_macros() && inf_macros_enabled() ) - setflag(idpflags, IDP_SIMPLIFY, true); - goto SAVE; - } -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.save_dataseg(); - pm.save_idpflags(); - pm.helper.supset(0, pm.ioh.device.c_str()); - break; - } - return 0; -} - -void pic_t::set_cpu(int n) -{ - if ( ptypes[n] != ptype ) - { - ptype = ptypes[n]; - ph.cnbits = 12 + 2*n; - } - switch ( ptype ) - { - case PIC12: - ph.reg_names = register_names_pic12; - cfgname = "pic12.cfg"; - break; - case PIC14: - ph.reg_names = register_names_pic14; - cfgname = "pic14.cfg"; - break; - case PIC16: - ph.reg_names = register_names_pic16; - cfgname = "pic16.cfg"; - ph.cnbits = 8; - ph.reg_last_sreg = PCLATU; - break; - default: - INTERR(10311); - } - setflag(ph.flag2, PR2_MACRO, ptype != PIC16); -} - -//---------------------------------------------------------------------- -void pic_t::check_pclath(segment_t *s) const -{ - if ( s == NULL ) - return; - if ( s->defsr[PCLATH-ph.reg_first_sreg] == BADSEL ) - s->defsr[PCLATH-ph.reg_first_sreg] = 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(pic_t)); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi pic_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - int sav_respect_info = ioh.respect_info; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ pic"); - helper.supstr(&ioh.device, 0); - break; - - case processor_t::ev_term: - free_mappings(); - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: // new file loaded - { - segment_t *s0 = get_first_seg(); - if ( s0 != NULL ) - { - ea_t firstEA = s0->start_ea; - if ( ptype == PIC12 || ptype == PIC14 ) - { - set_segm_name(s0, "CODE"); - dataseg = AdditionalSegment(0x200, 0, "DATA"); - setup_device(IORESP_INT|IORESP_PORT); - } - else - { - setup_device(IORESP_ALL); - } - s0 = getseg(firstEA); - if ( s0 != NULL ) - { - set_default_sreg_value(s0, BANK, 0); - set_default_sreg_value(s0, PCLATH, 0); - set_default_sreg_value(s0, PCLATU, 0); - } - segment_t *s1 = getseg(dataseg); - if ( s1 != NULL ) - { - set_default_sreg_value(s1, BANK, 0); - set_default_sreg_value(s1, PCLATH, 0); - set_default_sreg_value(s1, PCLATU, 0); - } - } - } - // save info to idb - save_dataseg(); - save_idpflags(); - break; - - case processor_t::ev_ending_undo: - set_cpu(ph.get_proc_index()); - ioh.respect_info = IORESP_NONE; - //fall through - case processor_t::ev_oldfile: // old file loaded - idpflags = (ushort)helper.altval(-1); - dataseg = node2ea(helper.altval(0)); - load_symbols_without_infotype(IORESP_PORT); - ioh.respect_info = sav_respect_info; - //init PCLATH for very old IDBs - check_pclath(get_first_seg()); - check_pclath(getseg(dataseg)); - break; - - case processor_t::ev_newprc: // new processor type - { - int n = va_arg(va, int); - // bool keep_cfg = va_argi(va, bool); - if ( set ) - return 0; - set = true; - set_cpu(n); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - pic_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - pic_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - pic_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - pic_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - pic_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - pic_data(*ctx, analyze_only); - return 1; - } - - case processor_t::ev_is_sp_based: - { - int *mode = va_arg(va, int *); - *mode = OP_SP_ADD | OP_FP_BASED; - return 1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - *frsize = 0; - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "Microchip PIC:" -static const char *const shnames[] = -{ "PIC12Cxx", - "PIC16Cxx", - "PIC18Cxx", - NULL -}; -static const char *const lnames[] = -{ FAMILY "Microchip PIC12Cxx - 12 bit instructions", - "Microchip PIC16Cxx - 14 bit instructions", - "Microchip PIC18Cxx - 16 bit instructions", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_PIC, // id - // flag - PRN_HEX - | PR_SEGS - | PR_SGROTHER - | PR_STACK_UP - | PR_RNAMESOK, - // flag2 - PR2_IDP_OPTS // the module has processor-specific configuration options - | PR2_MACRO, // try to combine several instructions into a macro instruction - 12, // 12/14/16 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names_pic14, // Register names - qnumber(register_names_pic14), // Number of registers - - BANK, // first - PCLATH, // last - 0, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - PIC_null, - PIC_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 0, 0, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - PIC_return, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/ppc/notify_codes.hpp b/idasdk75/module/ppc/notify_codes.hpp deleted file mode 100644 index 2dce6db..0000000 --- a/idasdk75/module/ppc/notify_codes.hpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __PPC_NOTIFY_CODES_HPP -#define __PPC_NOTIFY_CODES_HPP - -#include <idp.hpp> - -struct pushinfo_t; -//---------------------------------------------------------------------- -// The following events are supported by the PPC module in the ph.notify() function -namespace ppc_module_t -{ - enum event_codes_t - { - ev_dummy = processor_t::ev_loader, // was used before - ev_set_toc, - // obsolete, use processor_t::set_code16_mode() - ev_set_vle_mode, - ev_restore_pushinfo, // Restore function prolog info from the database - // in: pushinfo_t *pi - // ea_t func_start - // Returns: 1-ok, otherwise-failed - ev_save_pushinfo, // Save function prolog info to the database - // in: ea_t func_start - // const pushinfo_t *pi - // Returns: 1-ok, otherwise-failed - // obsolete, use processor_t::get_code16_mode() - ev_get_vle_mode, - ev_set_sda_base, - ev_get_sda_base, - ev_get_toc, - ev_is_gnu_mcount_nc, // Is __gnu_mcount_nc function? - // in: ea_t ea - // Returns: 1-yes, -1-no - ev_set_func_toc, // Set TOC for a function. - // in: ea_t func_start_ea - // ea_t toc_ea - ev_get_fix_gnu_vleadreloc_bug, - // Get config var PPC_FIX_GNU_VLEADRELOC_BUG. - // Used by ELF-loader PPC submodule. - // Returns: 1-yes, -1-no - - ev_get_abi, // returns ABI, \ref abi_type_t - - ev_get_func_toc, // Fet TOC for a function. - // out: ea_t *toc_ea - // in: ea_t func_start_ea - - ev_serialize_pushinfo, // Save function prolog info to the buffer - // in: bytevec_t *buf - // ea_t func_start - // const pushinfo_t *pi - // int flags (reserved) - // Returns: 1-ok, otherwise-failed - ev_deserialize_pushinfo, - // Restore function prolog info from the buffer - // in: pushinfo_t *pi - // memory_deserializer_t *buf - // ea_t func_start - // int flags (reserved) - // Returns: 1-ok, otherwise-failed - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - // set TOC / SDA2_BASE (gpr2) - inline void set_toc(ea_t toc_ea, adiff_t displ = 0) - { - QASSERT(10230, PH.id == PLFM_PPC); - processor_t::notify(idp_ev(ev_set_toc), toc_ea, displ); - } - - // get TOC/SDA2_BASE (gpr2) - inline ea_t get_toc() - { - QASSERT(10241, PH.id == PLFM_PPC); - ea_t toc_ea = BADADDR; // just in case - processor_t::notify(idp_ev(ev_get_toc), &toc_ea); - return toc_ea; - } - - inline bool restore_pushinfo(pushinfo_t *pi, ea_t func_start) - { - return processor_t::notify(idp_ev(ev_restore_pushinfo), pi, func_start) == 1; - } - - inline bool save_pushinfo(ea_t func_start, const pushinfo_t &pi) - { - return processor_t::notify(idp_ev(ev_save_pushinfo), func_start, &pi) == 1; - } - - inline bool is_gnu_mcount_nc(ea_t ea) - { - return processor_t::notify(idp_ev(ev_is_gnu_mcount_nc), ea) == 1; - } - - inline bool get_fix_gnu_vleadreloc_bug() - { - return processor_t::notify(idp_ev(ev_get_fix_gnu_vleadreloc_bug)) == 1; - } - - inline int get_abi() - { - return processor_t::notify(idp_ev(ev_get_abi)); - } - - inline void set_sda_base(ea_t sda_base) - { - QASSERT(10239, PH.id == PLFM_PPC); - processor_t::notify(idp_ev(ev_set_sda_base), sda_base); - } - - // get SDA base (gpr13) - inline ea_t get_sda_base() - { - QASSERT(10240, PH.id == PLFM_PPC); - ea_t sda_base = BADADDR; // just in case - processor_t::notify(idp_ev(ev_get_sda_base), &sda_base); - return sda_base; - } - - // set TOC for a function (gpr2) - inline void set_func_toc(ea_t func_ea, ea_t toc_ea) - { - QASSERT(10247, PH.id == PLFM_PPC); - processor_t::notify(idp_ev(ev_set_func_toc), func_ea, toc_ea); - } - - // get TOC for a function (gpr2) - inline ea_t get_func_toc(ea_t func_ea) - { - QASSERT(10265, PH.id == PLFM_PPC); - ea_t toc_ea = BADADDR; // just in case - processor_t::notify(idp_ev(ev_get_func_toc), &toc_ea, func_ea); - return toc_ea; - } - - inline bool serialize_pushinfo( - bytevec_t *buf, - ea_t func_start, - const pushinfo_t &pi, - int flags = 0) - { - return processor_t::notify(idp_ev(ev_serialize_pushinfo), - buf, - func_start, - &pi, - flags) == 1; - } - - inline bool deserialize_pushinfo( - pushinfo_t *pi, - memory_deserializer_t *buf, - ea_t func_start, - int flags = 0) - { - return processor_t::notify(idp_ev(ev_deserialize_pushinfo), - pi, - buf, - func_start, - flags) == 1; - } -} - -#endif // __PPC_NOTIFY_CODES_HPP diff --git a/idasdk75/module/sam8/makefile b/idasdk75/module/sam8/makefile deleted file mode 100644 index f677332..0000000 --- a/idasdk75/module/sam8/makefile +++ /dev/null @@ -1,40 +0,0 @@ -PROC=sam8 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp ins.hpp sam8.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp ins.hpp sam8.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.cpp ins.hpp sam8.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp out.cpp sam8.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ins.hpp reg.cpp sam8.hpp diff --git a/idasdk75/module/script/ebc.py b/idasdk75/module/script/ebc.py deleted file mode 100644 index e769009..0000000 --- a/idasdk75/module/script/ebc.py +++ /dev/null @@ -1,1393 +0,0 @@ - -# ---------------------------------------------------------------------- -# EFI bytecode processor module -# (c) Hex-Rays -# Please send fixes or improvements to support@hex-rays.com - -import sys -import struct - -from ida_bytes import * -from ida_ua import * -from ida_idp import * -from ida_auto import * -from ida_nalt import * -from ida_funcs import * -from ida_lines import * -from ida_problems import * -from ida_segment import * -from ida_name import * -from ida_netnode import * -from ida_xref import * -from ida_idaapi import * -import ida_frame -import ida_offset -import ida_pro -import idc - -if sys.version_info.major < 3: - range = xrange - -# extract bitfield occupying bits high..low from val (inclusive, start from 0) -def BITS(val, low, high): - return (val>>low)&((1<<(high-low+1))-1) -# extract one bit -def BIT(val, bit): - return (val>>bit) & 1 -# sign extend b low bits in x -# from "Bit Twiddling Hacks" -def SIGNEXT(x, b): - m = 1 << (b - 1) - x = x & ((1 << b) - 1) - return (x ^ m) - m - -# check if operand is register reg -def is_reg(op, reg): - return op.type == o_reg and op.reg == reg - -# check if operand is immediate value val -def is_imm(op, val): - return op.type == o_imm and op.value == val - -# are operands equal? -def same_op(op1, op2): - return op1.type == op2.type and \ - op1.reg == op2.reg and \ - op1.value == op2.value and \ - op1.addr == op2.addr and \ - op1.flags == op2.flags and \ - op1.specval == op2.specval and \ - op1.dtype == op2.dtype - -# is sp delta fixed by the user? -def is_fixed_spd(ea): - return (get_aflags(ea) & AFL_FIXEDSPD) != 0 - -# ---------------------------------------------------------------------- -class ebc_processor_t(processor_t): - # IDP id ( Numbers above 0x8000 are reserved for the third-party modules) - id = PLFM_EBC - - # Processor features - flag = PR_SEGS | PR_DEFSEG32 | PR_USE32 | PRN_HEX | PR_RNAMESOK - - # Number of bits in a byte for code segments (usually 8) - # IDA supports values up to 32 bits - cnbits = 8 - - # Number of bits in a byte for non-code segments (usually 8) - # IDA supports values up to 32 bits - dnbits = 8 - - # short processor names - # Each name should be shorter than 9 characters - psnames = ['ebc'] - - # long processor names - # No restriction on name lengthes. - plnames = ['EFI Byte code'] - - # size of a segment register in bytes - segreg_size = 0 - - # Array of typical code start sequences (optional) - # codestart = ['\x60\x00'] # 60 00 xx xx: MOVqw SP, SP-delta - - # Array of 'return' instruction opcodes (optional) - # retcodes = ['\x04\x00'] # 04 00: RET - - # You should define 2 virtual segment registers for CS and DS. - # Let's call them rVcs and rVds. - - # icode of the first instruction - instruc_start = 0 - - # - # Size of long double (tbyte) for this processor - # (meaningful only if ash.a_tbyte != NULL) - # - tbyte_size = 0 - - # only one assembler is supported - assembler = { - # flag - 'flag' : ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, - - # user defined flags (local only for IDP) - # you may define and use your own bits - 'uflag' : 0, - - # Assembler name (displayed in menus) - 'name': "EFI bytecode assembler", - - # org directive - 'origin': "org", - - # end directive - 'end': "end", - - # comment string (see also cmnt2) - 'cmnt': ";", - - # ASCII string delimiter - 'ascsep': "\"", - - # ASCII char constant delimiter - 'accsep': "'", - - # ASCII special chars (they can't appear in character and ascii constants) - 'esccodes': "\"'", - - # - # Data representation (db,dw,...): - # - # ASCII string directive - 'a_ascii': "db", - - # byte directive - 'a_byte': "db", - - # word directive - 'a_word': "dw", - - # remove if not allowed - 'a_dword': "dd", - - # remove if not allowed - 'a_qword': "dq", - - # remove if not allowed - 'a_oword': "xmmword", - - # float; 4bytes; remove if not allowed - 'a_float': "dd", - - # double; 8bytes; NULL if not allowed - 'a_double': "dq", - - # long double; NULL if not allowed - 'a_tbyte': "dt", - - # array keyword. the following - # sequences may appear: - # #h - header - # #d - size - # #v - value - # #s(b,w,l,q,f,d,o) - size specifiers - # for byte,word, - # dword,qword, - # float,double,oword - 'a_dups': "#d dup(#v)", - - # uninitialized data directive (should include '%s' for the size of data) - 'a_bss': "%s dup ?", - - # 'seg ' prefix (example: push seg seg001) - 'a_seg': "seg", - - # current IP (instruction pointer) symbol in assembler - 'a_curip': "$", - - # "public" name keyword. NULL-gen default, ""-do not generate - 'a_public': "public", - - # "weak" name keyword. NULL-gen default, ""-do not generate - 'a_weak': "weak", - - # "extrn" name keyword - 'a_extrn': "extrn", - - # "comm" (communal variable) - 'a_comdef': "", - - # "align" keyword - 'a_align': "align", - - # Left and right braces used in complex expressions - 'lbrace': "(", - 'rbrace': ")", - - # % mod assembler time operation - 'a_mod': "%", - - # & bit and assembler time operation - 'a_band': "&", - - # | bit or assembler time operation - 'a_bor': "|", - - # ^ bit xor assembler time operation - 'a_xor': "^", - - # ~ bit not assembler time operation - 'a_bnot': "~", - - # << shift left assembler time operation - 'a_shl': "<<", - - # >> shift right assembler time operation - 'a_shr': ">>", - - # size of type (format string) - 'a_sizeof_fmt': "size %s", - } # Assembler - - # ---------------------------------------------------------------------- - # Some internal flags used by the decoder, emulator and output - # operand size or move size; can be in both auxpref and OpN.specval - FL_B = 0x0001 # 8 bits - FL_W = 0x0002 # 16 bits - FL_D = 0x0004 # 32 bits - FL_Q = 0x0008 # 64 bits - - # OpN.specval - FLo_INDIRECT = 0x0010 # This is an indirect access (not immediate value) - FLo_SIGNED = 0x0020 # This is a signed operand - - # insn_t.auxpref flags (NB: only 16 bits!) - FLa_OP1 = 0x0010 # check operand 1 - FLa_32 = 0x0020 # Is 32 - FLa_64 = 0x0040 # Is 64 - FLa_EXTERN = 0x0080 # external call (via thunk) - FLa_ABS = 0x0100 # absolute call - FLa_CS = 0x0200 # Condition flag is set - FLa_NCS = 0x0400 # Condition flag is not set - FLa_CMPMASK = 0xF000 # mask of the CMP[I] comparison - FLa_CMPeq = 0x1000 # compare equal - FLa_CMPlte = 0x2000 # compare signed less than or equal - FLa_CMPgte = 0x3000 # compare signed greater than or equal - FLa_CMPulte = 0x4000 # compare unsigned less than or equal - FLa_CMPugte = 0x5000 # compare unsigned greater than or equal - - IMMDATA_16 = 1 - IMMDATA_32 = 2 - IMMDATA_64 = 3 - - # ---------------------------------------------------------------------- - # Utility functions - # - - # ---------------------------------------------------------------------- - # set comparison kind (eq/lte/gte/ulte/ugte) - def set_cmp(self, insn, no): - insn.auxpref &= ~self.FLa_CMPMASK - insn.auxpref |= [self.FLa_CMPeq, self.FLa_CMPlte, - self.FLa_CMPgte, self.FLa_CMPulte, - self.FLa_CMPugte][no] - - # ---------------------------------------------------------------------- - # get comparison kind (eq/lte/gte/ulte/ugte) - def get_cmp(self, insn): - t = insn.auxpref & self.FLa_CMPMASK - if t: - return { self.FLa_CMPeq: "eq", - self.FLa_CMPlte: "lte", - self.FLa_CMPgte: "gte", - self.FLa_CMPulte: "ulte", - self.FLa_CMPugte: "ugte" } [t] - - # ---------------------------------------------------------------------- - def get_data_width_fl(self, sz): - """Returns a flag given the data width number""" - if sz == 0: return self.FL_B - elif sz == self.IMMDATA_16: return self.FL_W - elif sz == self.IMMDATA_32: return self.FL_D - elif sz == self.IMMDATA_64: return self.FL_Q - - # ---------------------------------------------------------------------- - def next_data_value(self, insn, sz): - """Returns a value depending on the data widh number""" - if sz == 0: return insn.get_next_byte() - elif sz == self.IMMDATA_16: return insn.get_next_word() - elif sz == self.IMMDATA_32: return insn.get_next_dword() - elif sz == self.IMMDATA_64: return insn.get_next_qword() - else: raise Exception("Invalid width!") - - # ---------------------------------------------------------------------- - def get_data_dt(self, sz): - """Returns a dt_xxx on the data widh number""" - if sz == 0: return dt_byte - elif sz == self.IMMDATA_16: return dt_word - elif sz == self.IMMDATA_32: return dt_dword - elif sz == self.IMMDATA_64: return dt_qword - else: raise Exception("Invalid width!") - - # ---------------------------------------------------------------------- - def native_dt(self): - return dt_qword if self.PTRSZ==8 else dt_dword - - # ---------------------------------------------------------------------- - def get_sz_to_bits(self, sz): - """Returns size in bits of the data widh number""" - if sz == self.IMMDATA_16: return 16 - elif sz == self.IMMDATA_32: return 32 - elif sz == self.IMMDATA_64: return 64 - else: return 8 - - # ---------------------------------------------------------------------- - def dt_to_bits(self, dt): - """Returns the size in bits given a dt_xxx""" - if dt == dt_byte: return 8 - elif dt == dt_word: return 16 - elif dt == dt_dword: return 32 - elif dt == dt_qword: return 64 - - # ---------------------------------------------------------------------- - def dt_to_width(self, dt): - """Returns OOFW_xxx flag given a dt_xxx""" - if dt == dt_byte: return OOFW_8 - elif dt == dt_word: return OOFW_16 - elif dt == dt_dword: return OOFW_32 - elif dt == dt_qword: return OOFW_64 - - # ---------------------------------------------------------------------- - def fl_to_str(self, fl): - """Given a flag, it returns a string. (used during output)""" - if fl & self.FL_B != 0: return "b" - elif fl & self.FL_W != 0: return "w" - elif fl & self.FL_D != 0: return "d" - elif fl & self.FL_Q != 0: return "q" - - # ---------------------------------------------------------------------- - def set_ptr_size(self): - """ - Functions checks the database / PE header netnode and sees if the input file - is a PE+ or not. If so, then pointer size is set to 8 bytes. - """ - n = netnode("$ PE header") - s = n.valobj() - if not s: - return - # Extract magic field - t = struct.unpack("<H", s[0x18:0x18+2])[0] - if t == 0x20B: - self.PTRSZ = 8 - - # ---------------------------------------------------------------------- - # Decodes an index and returns all its components in a dictionary - # Refer to "Index Encoding" section - def decode_index(self, index, sz): - N = sz - 1 - s = -1 if BIT(index, N) else 1 - w = BITS(index, N-3, N-1) - t = sz // 8 - A = w * t # width of the natural units field - n = BITS(index, 0, A-1) if A >= 1 else 0 # natural units (n) - c = BITS(index, A, N-4) if N-4 >= A else 0 # constant units (c) - o = (c + (n * self.PTRSZ)) # offset w/o sign - so = o * s # signed final offset - return so - - # ---------------------------------------------------------------------- - def op_reg(self, op, reg): - op.type = o_reg - op.reg = reg - - # ---------------------------------------------------------------------- - def op_disp(self, op, reg, d, direct): - op.type = o_displ - op.phrase = reg - op.addr = d if d else 0 - if not direct: - op.specval |= self.FLo_INDIRECT - else: - op.specval &= ~self.FLo_INDIRECT - op.specval |= self.FLo_SIGNED - - # ---------------------------------------------------------------------- - def decode_index_or_data(self, insn, sz, immed): - bs = self.get_sz_to_bits(sz) - d = self.next_data_value(insn, sz) - if not immed: - d = self.decode_index(d, bs) - else: - d = SIGNEXT(d, bs) - return d - - # ---------------------------------------------------------------------- - def fill_op(self, insn, op, reg, direct, has_imm, immsz, dt = None, index_only = False): - if direct and not has_imm: - self.op_reg(op, reg) - else: - d = self.decode_index_or_data(insn, immsz, direct and not index_only) if has_imm else None - self.op_disp(op, reg, d, direct) - if dt: - insn.Op1.dtype = dt - - # ---------------------------------------------------------------------- - def fill_op1(self, insn, opbyte, has_imm, immsz, dt = None, index_only = False): - op1_direct = (opbyte & 0x08) == 0 - r1 = (opbyte & 0x07) - self.fill_op(insn, insn.Op1, r1, op1_direct, has_imm, immsz, dt, index_only) - - # ---------------------------------------------------------------------- - def fill_op2(self, insn, opbyte, has_imm, immsz, dt = None, index_only = False): - op2_direct = (opbyte & 0x80) == 0 - r2 = (opbyte & 0x70) >> 4 - self.fill_op(insn, insn.Op2, r2, op2_direct, has_imm, immsz, dt, index_only) - - # ---------------------------------------------------------------------- - # Instruction decoding - # - - # ---------------------------------------------------------------------- - def decode_RET(self, insn, opbyte): - # No operands - insn.Op1.type = o_void - # Consume the next byte, and it should be zero - insn.get_next_byte() - return True - - # ---------------------------------------------------------------------- - def decode_STORESP(self, insn, opbyte): - # opbyte (byte0) has nothing meaningful (but the opcode itself) - - # get next byte - opbyte = insn.get_next_byte() - - vm_reg = (opbyte & 0x70) >> 4 - gp_reg = (opbyte & 0x07) - - insn.Op1.type = insn.Op2.type = o_reg - insn.Op1.dtype = insn.Op2.dtype = dt_qword - - insn.Op1.reg = gp_reg - insn.Op2.reg = self.ireg_FLAGS + vm_reg - - return True - - # ---------------------------------------------------------------------- - def decode_LOADSP(self, insn, opbyte): - # opbyte (byte0) has nothing meaningful (but the opcode itself) - - # get next byte - opbyte = insn.get_next_byte() - - gp_reg = (opbyte & 0x70) >> 4 - vm_reg = (opbyte & 0x07) - - insn.Op1.type = insn.Op2.type = o_reg - insn.Op1.dtype = insn.Op2.dtype = dt_qword - - insn.Op1.reg = self.ireg_FLAGS + vm_reg - insn.Op2.reg = gp_reg - - return True - - # ---------------------------------------------------------------------- - def decode_BREAK(self, insn, opbyte): - """ - stx=<BREAK [break code]> - txt=<The BREAK instruction is used to perform special processing by the VM.> - """ - insn.Op1.type = o_imm - insn.Op1.dtype = dt_byte - insn.Op1.value = insn.get_next_byte() - return True - - # ---------------------------------------------------------------------- - def cmt_BREAK(self, insn): - s = "Special processing by VM" - if insn.Op1.value == 0: - s += ": runaway program break (null/bad opcode)" - elif insn.Op1.value == 1: - s += ": get virtual machine version in R7" - elif insn.Op1.value == 3: - s += ": debug breakpoint" - elif insn.Op1.value == 4: - s += ": system call (ignored)" - elif insn.Op1.value == 5: - s += ": create thunk (thunk pointer in R7)" - elif insn.Op1.value == 6: - s += ": set compiler version in R7" - else: - s += ": unknown break code" - return s - - # ---------------------------------------------------------------------- - def decode_PUSH(self, insn, opbyte): - """ - PUSH[32|64] {@}R1 {Index16|Immed16} - PUSHn {@}R1 {Index16|Immed16} - """ - have_data = (opbyte & 0x80) != 0 - is_n = (opbyte & ~0xC0) in [0x35, 0x36] # PUSHn, POPn - if is_n: - dt = self.native_dt() - insn.auxpref = 0 - else: - op_32 = (opbyte & 0x40) == 0 - dt = dt_dword if op_32 else dt_qword - insn.auxpref = self.FLa_32 if op_32 else self.FLa_64 - - opbyte = insn.get_next_byte() - self.fill_op1(insn, opbyte, have_data, self.IMMDATA_16, dt) - return True - - # ---------------------------------------------------------------------- - def decode_JMP(self, insn, opbyte): - """ - stx=<JMP32{cs|cc} {@}R1 {Immed32|Index32}> - stx=<JMP64{cs|cc} Immed64> - """ - have_data = (opbyte & 0x80) != 0 - jmp_32 = (opbyte & 0x40) == 0 - - opbyte = insn.get_next_byte() - conditional = (opbyte & 0x80) != 0 - cs = (opbyte & 0x40) != 0 - abs_jmp = (opbyte & 0x10) == 0 - op1_direct = (opbyte & 0x08) == 0 - r1 = (opbyte & 0x07) - - if jmp_32: - # Indirect and no data specified? - if not op1_direct and not have_data: - return False - - self.fill_op1(insn, opbyte, have_data, self.IMMDATA_32, dt_dword) - if insn.Op1.reg == 0: - if op1_direct: - insn.Op1.type = o_near - else: - insn.Op1.type = o_mem - else: - if not have_data: - return False - insn.Op1.type = o_near - insn.Op1.dtype = dt_qword - insn.Op1.addr = insn.get_next_qword() - - if not abs_jmp: - if jmp_32: - val = SIGNEXT(insn.Op1.addr, 32) - else: - val = insn.Op1.addr - insn.Op1.addr = val + insn.ea + insn.size - - fl = self.FLa_32 if jmp_32 else self.FLa_64 - if conditional: - fl |= self.FLa_CS if cs else self.FLa_NCS - insn.auxpref = fl - - return True - - # ---------------------------------------------------------------------- - def cmt_JMP(self, insn): - s = "Jump to address" - if insn.auxpref & self.FLa_CS: - s += " if condition is true" - elif insn.auxpref & self.FLa_NCS: - s += " if condition is false" - else: - s += " unconditionally" - return s - - # ---------------------------------------------------------------------- - def decode_JMP8(self, insn, opbyte): - """ - stx=<JMP8{cs|cc} Immed8> - """ - conditional = (opbyte & 0x80) != 0 - cs = (opbyte & 0x40) != 0 - insn.Op1.type = o_near - insn.Op1.dtype = dt_byte - addr = insn.get_next_byte() - insn.Op1.addr = (SIGNEXT(addr, 8) * 2) + insn.size + insn.ea - - if conditional: - insn.auxpref = self.FLa_CS if cs else self.FLa_NCS - - return True - - # ---------------------------------------------------------------------- - def decode_MOVI(self, insn, opbyte): - """ - MOVI[b|w|d|q][w|d|q] {@}R1 {Index16}, Immed16|32|64 - MOVIn[w|d|q] {@}R1 {Index16}, Index16|32|64 - - First character specifies the width of the move and is taken from opcode - Second character specifies the immediate data size and is taken from the opbyte - """ - imm_sz = (opbyte & 0xC0) >> 6 - opcode = (opbyte & ~0xC0) - is_MOVIn = opcode == 0x38 - - # Reserved and should not be 0 - if imm_sz == 0: - return False - - # take byte 1 - opbyte = insn.get_next_byte() - - # Bit 7 is reserved and should be 0 - if opbyte & 0x80 != 0: - return False - - have_idx = (opbyte & 0x40) != 0 - move_sz = (opbyte & 0x30) >> 4 - direct = (opbyte & 0x08) == 0 - r1 = (opbyte & 0x07) - - # Cannot have an index with a direct register - if have_idx and direct: - return False - - dt = self.native_dt() if is_MOVIn else self.get_data_dt(move_sz) - self.fill_op1(insn, opbyte, have_idx, self.IMMDATA_16, dt) - - insn.Op2.type = o_imm - insn.Op2.dtype = self.get_data_dt(imm_sz) - v = self.decode_index_or_data(insn, imm_sz, not is_MOVIn) - if imm_sz == self.IMMDATA_64: - insn.Op2.value = SIGNEXT(v, 32) - insn.Op2.addr = int(v >> 32) - else: - insn.Op2.value = v - # save imm size and signal that op1 is defined in first operand - insn.auxpref = self.get_data_width_fl(imm_sz) - if not is_MOVIn: - insn.auxpref |= self.FLa_OP1 - insn.Op1.specval |= self.get_data_width_fl(move_sz) - - return True - - # ---------------------------------------------------------------------- - def decode_MOVREL(self, insn, opbyte): - """ - MOVREL[w|d|q] {@}R1 {Index16}, Immed16|32|64 - """ - - imm_sz = (opbyte & 0xC0) >> 6 - - # Reserved and should not be 0 - if imm_sz == 0: - return False - - # take byte 1 - opbyte = insn.get_next_byte() - - # Bits 7 is reserved and should be 0 - # Bits 4 and 5 are supposed to be 0 too, except in real programs they aren't! - if (opbyte & 0x80) != 0: - return False - - have_idx = (opbyte & 0x40) != 0 - direct = (opbyte & 0x08) == 0 - r1 = (opbyte & 0x07) - - # Cannot have an index with a direct register - if have_idx and direct: - return False - - self.fill_op1(insn, opbyte, have_idx, self.IMMDATA_16, self.get_data_dt(imm_sz)) - insn.Op1.specval = self.get_data_width_fl(imm_sz) - insn.Op2.type = o_mem - insn.Op2.dtype = self.get_data_dt(imm_sz) - insn.Op2.addr = self.next_data_value(insn, imm_sz) + insn.size + insn.ea - - # save imm size - insn.auxpref = self.get_data_width_fl(imm_sz) - - return True - - # ---------------------------------------------------------------------- - def decode_MOV(self, insn, opbyte): - """ - MOV[b|w|d|q]{w|d} {@}R1 {Index16|32}, {@}R2 {Index16|32} - MOVn{w|d} {@}R1 {Index16|32}, {@}R2 {Index16|32} - MOVqq {@}R1 {Index64}, {@}R2 {Index64} - """ - have_idx1 = (opbyte & 0x80) != 0 - have_idx2 = (opbyte & 0x40) != 0 - opcode = (opbyte & ~0xC0) - - # opcode: data move size, index size - m = { - 0x1D: (dt_byte, self.IMMDATA_16), #MOVbw - 0x1E: (dt_word, self.IMMDATA_16), #MOVww - 0x1F: (dt_dword, self.IMMDATA_16), #MOVdw - 0x20: (dt_qword, self.IMMDATA_16), #MOVqw - 0x21: (dt_byte, self.IMMDATA_32), #MOVbd - 0x22: (dt_word, self.IMMDATA_32), #MOVwd - 0x23: (dt_dword, self.IMMDATA_32), #MOVdd - 0x24: (dt_qword, self.IMMDATA_32), #MOVqd - 0x28: (dt_qword, self.IMMDATA_64), #MOVqq - 0x32: (self.native_dt(), self.IMMDATA_16), #MOVnw - 0x33: (self.native_dt(), self.IMMDATA_32), #MOVnd - } - - dt, idx_sz = m[opcode] - # get byte1 - opbyte = insn.get_next_byte() - self.fill_op1(insn, opbyte, have_idx1, idx_sz, dt, True) - self.fill_op2(insn, opbyte, have_idx2, idx_sz, dt, True) - - return True - - # ---------------------------------------------------------------------- - def decode_CMP(self, insn, opbyte): - """ - CMP[32|64][eq|lte|gte|ulte|ugte] R1, {@}R2 {Index16|Immed16} - """ - have_data = (opbyte & 0x80) != 0 - cmp_32 = (opbyte & 0x40) == 0 - opcode = (opbyte & ~0xC0) - - opbyte = insn.get_next_byte() - - if opbyte & 0x08: # operand 1 indirect is not supported - return False - - r1 = (opbyte & 0x07) - dt = dt_dword if cmp_32 else dt_qword - insn.Op1.type = o_reg - insn.Op1.reg = r1 - insn.Op1.dtype = dt - - self.fill_op2(insn, opbyte, have_data, self.IMMDATA_16, dt) - - insn.auxpref = self.FLa_32 if cmp_32 else self.FLa_64 - self.set_cmp(insn, opcode - 0x05) - return True - - # ---------------------------------------------------------------------- - def cmt_CMP(self, insn): - s = "Compare if " - t = insn.auxpref & self.FLa_CMPMASK - s += { self.FLa_CMPeq: "equal", - self.FLa_CMPlte: "less than or equal (signed)", - self.FLa_CMPgte: "greater than or equal (signed)", - self.FLa_CMPulte: "less than or equal (unsigned)", - self.FLa_CMPugte: "greater than or equal (unsigned)" } [t] - return s - - # ---------------------------------------------------------------------- - def decode_CMPI(self, insn, opbyte): - """ - CMPI[32|64]{w|d}[eq|lte|gte|ulte|ugte] {@}R1 {Index16}, Immed16|Immed32 - """ - imm_sz = self.IMMDATA_16 if (opbyte & 0x80) == 0 else self.IMMDATA_32 - cmp_32 = (opbyte & 0x40) == 0 - opcode = (opbyte & ~0xC0) - - opbyte = insn.get_next_byte() - have_idx = (opbyte & 0x10) != 0 - dt = dt_dword if cmp_32 else dt_qword - self.fill_op1(insn, opbyte, have_idx, self.IMMDATA_16, dt) - insn.Op2.type = o_imm - insn.Op2.value = self.next_data_value(insn, imm_sz) - insn.Op2.dtype = dt - - insn.auxpref = (self.FLa_32 if cmp_32 else self.FLa_64) | self.get_data_width_fl(imm_sz) - self.set_cmp(insn, opcode - 0x2D) - return True - - # ---------------------------------------------------------------------- - def decode_CALL(self, insn, opbyte): - """ - stx=<CALL32{EX}{a} {@}R1 {Immed32|Index32}> - stx=<CALL64{EX}{a} Immed64> - """ - have_data = (opbyte & 0x80) != 0 - call_32 = (opbyte & 0x40) == 0 - - opbyte = insn.get_next_byte() - - # Call to EBC or Native code - ebc_call = (opbyte & 0x20) == 0 - # Absolute or Relative address - abs_addr = (opbyte & 0x10) == 0 - # Op1 direct? - op1_direct = (opbyte & 0x08) == 0 - r1 = (opbyte & 0x07) - - if call_32: - self.fill_op1(insn, opbyte, have_data, self.IMMDATA_32, dt_dword) - if have_data and insn.Op1.reg == 0: - insn.Op1.type = o_near - if not abs_addr: - val = SIGNEXT(insn.Op1.addr & 0xFFFFFFFF, 32) - insn.Op1.addr = val + insn.ea + insn.size - # 64-bit - else: - insn.Op1.type = o_near - insn.Op1.dtype = dt_qword - insn.Op1.addr = self.next_data_value(insn, self.IMMDATA_64) # Get 64-bit value - if not abs_addr: - insn.Op1.addr += insn.ea + insn.size - - fl = self.FLa_EXTERN if not ebc_call else 0 - fl |= self.FLa_32 if call_32 else self.FLa_64 - if abs_addr: - fl |= self.FLa_ABS - insn.auxpref = fl - - return True - - # ---------------------------------------------------------------------- - def cmt_CALL(self, insn): - if insn.auxpref & self.FLa_EXTERN: - s = "Call an external subroutine (via thunk)" - else: - s = "Call a subroutine" - if insn.auxpref & self.FLa_ABS: - s += " [absolute addressing]" - return s - - # ---------------------------------------------------------------------- - def decode_BINOP_FORM1(self, insn, opbyte): - """ - op[32|64] {@}R1, {@}R2 {Index16|Immed16} - """ - have_data = (opbyte & 0x80) != 0 - op_32 = (opbyte & 0x40) == 0 - opcode = (opbyte & ~0xC0) - - opbyte = insn.get_next_byte() - - op2_direct = (opbyte & 0x80) == 0 - op1_direct = (opbyte & 0x08) == 0 - r1 = (opbyte & 0x07) - r2 = (opbyte & 0x70) >> 4 - dt = dt_dword if op_32 else dt_qword - - self.fill_op1(insn, opbyte, False, 0, dt) - self.fill_op2(insn, opbyte, have_data, self.IMMDATA_16, dt) - insn.auxpref = self.FLa_32 if op_32 else self.FLa_64 - - return True - - # ---------------------------------------------------------------------- - def decode_MOVSN(self, insn, opbyte): - """ - MOVsn{w} {@}R1 {Index16}, {@}R2 {Index16|Immed16} - MOVsn{d} {@}R1 {Index32}, {@}R2 {Index32|Immed32} - """ - have_idx1 = (opbyte & 0x80) != 0 - have_idx2 = (opbyte & 0x40) != 0 - opcode = (opbyte & ~0xC0) - - if opcode == 0x25: - idx_sz = self.IMMDATA_16 - elif opcode == 0x26: - idx_sz = self.IMMDATA_32 - else: - return False - - opbyte = insn.get_next_byte() - self.fill_op1(insn, opbyte, have_idx1, idx_sz, self.native_dt()) - self.fill_op2(insn, opbyte, have_idx2, idx_sz, self.native_dt()) - - return True - - # ---------------------------------------------------------------------- - # Processor module callbacks - # - # ---------------------------------------------------------------------- - def ev_get_frame_retsize(self, frsize, pfn): - ida_pro.int_pointer.frompointer(frsize).assign(16) - return 1 - - # ---------------------------------------------------------------------- - def ev_get_autocmt(self, insn): - if 'cmt' in self.instruc[insn.itype]: - return self.instruc[insn.itype]['cmt'](insn) - - # ---------------------------------------------------------------------- - def ev_can_have_type(self, op): - return 1 if op.type in [o_imm, o_displ, o_mem] else 0 - - # ---------------------------------------------------------------------- - def ev_is_align_insn(self, ea): - return 2 if get_word(ea) == 0 else 0 - - # ---------------------------------------------------------------------- - def ev_newfile(self, filename): - self.set_ptr_size() - return 0 - - # ---------------------------------------------------------------------- - def ev_oldfile(self, filename): - self.set_ptr_size() - return 0 - - # ---------------------------------------------------------------------- - def ev_out_header(self, ctx): - ctx.out_line("; natural unit size: %d bits" % (self.PTRSZ*8)) - ctx.flush_outbuf(0) - return 1 - - # ---------------------------------------------------------------------- - def ev_may_be_func(self, insn, state): - if is_reg(insn.Op1, self.ireg_SP) and insn.Op2.type == o_displ and\ - insn.Op2.phrase == self.ireg_SP and (insn.Op2.specval & self.FLo_INDIRECT) == 0: - # mov SP, SP+delta - if SIGNEXT(insn.Op2.addr, self.PTRSZ*8) < 0: - return 100 - else: - return 0 - return 10 - - # ---------------------------------------------------------------------- - def check_thunk(self, addr): - """ - Check for EBC thunk at addr - dd fnaddr - (addr+4), 0, 0, 0 - """ - delta = get_dword(addr) - fnaddr = (delta + addr + 4) & 0xFFFFFFFF - if is_off(get_flags(addr), 0): - # already an offset - if ida_offset.get_offbase(addr, 0) == addr + 4: - return fnaddr - else: - return None - # should be followed by three zeroes - if delta == 0 or get_dword(addr+4) != 0 or\ - get_dword(addr+8) != 0 or get_dword(addr+12) != 0: - return None - if segtype(fnaddr) == SEG_CODE: - # looks good, create the offset - idc.create_dword(addr) - if ida_offset.op_offset(addr, 0, REF_OFF32|REFINFO_NOBASE, BADADDR, addr + 4): - return fnaddr - else: - return None - - # ---------------------------------------------------------------------- - def handle_operand(self, insn, op, isRead): - F = get_flags(insn.ea) - is_offs = is_off(F, op.n) - dref_flag = dr_R if isRead else dr_W - def_arg = is_defarg(F, op.n) - optype = op.type - - # create code xrefs - if optype == o_imm: - if is_offs: - insn.add_off_drefs(op, dr_O, 0) - # create data xrefs - elif optype == o_displ: - # reg + delta - if is_offs: - insn.add_off_drefs(op, dref_flag, OOF_ADDR) - elif may_create_stkvars() and not def_arg and op.reg == self.ireg_SP: - # ignore prolog/epilog - # MOVqw SP, SP+delta - if is_reg(insn.Op1, self.ireg_SP): - pass - else: - pfn = get_func(insn.ea) - # [SP+var_x] (indirect) - # SP+var_x (direct) - flag = STKVAR_VALID_SIZE if (op.specval & self.FLo_INDIRECT) else 0 - if pfn and insn.create_stkvar(op, op.addr, flag): - op_stkvar(insn.ea, op.n) - elif optype == o_mem: - if insn.itype == self.itype_MOVREL: - dref_flag = dr_O - self.check_thunk(op.addr) - else: - insn.create_op_data(op.addr, op) - insn.add_dref(op.addr, op.offb, dref_flag) - elif optype == o_near: - itype = insn.itype - if itype == self.itype_CALL: - fl = fl_CN - else: - fl = fl_JN - insn.add_cref(op.addr, op.offb, fl) - - # ---------------------------------------------------------------------- - def add_stkpnt(self, insn, pfn, v): - if pfn: - end = insn.ea + insn.size - if not is_fixed_spd(end): - ida_frame.add_auto_stkpnt(pfn, end, v) - - # ---------------------------------------------------------------------- - def trace_sp(self, insn): - """ - Trace the value of the SP and create an SP change point if the current - instruction modifies the SP. - """ - pfn = get_func(insn.ea) - if not pfn: - return - if is_reg(insn.Op1, self.ireg_SP) and insn.itype in [self.itype_MOVbw, self.itype_MOVww, - self.itype_MOVdw, self.itype_MOVqw, self.itype_MOVbd, - self.itype_MOVwd, self.itype_MOVdd, self.itype_MOVqd, - self.itype_MOVsnw, self.itype_MOVsnd, self.itype_MOVqq]: - # MOVqw SP, SP-0x30 - # MOVqw SP, SP+0x30 - if insn.Op2.type == o_displ and insn.Op2.phrase == self.ireg_SP and (insn.Op2.specval & self.FLo_INDIRECT) == 0: - spofs = SIGNEXT(insn.Op2.addr, self.PTRSZ*8) - self.add_stkpnt(insn, pfn, spofs) - elif insn.itype in [self.itype_PUSH, self.itype_PUSHn]: - spofs = self.dt_to_bits(insn.Op1.dtype) // 8 - self.add_stkpnt(insn, pfn, -spofs) - elif insn.itype in [self.itype_POP, self.itype_POPn]: - spofs = self.dt_to_bits(insn.Op1.dtype) // 8 - self.add_stkpnt(insn, pfn, spofs) - - - # ---------------------------------------------------------------------- - def ev_emu_insn(self, insn): - aux = self.get_auxpref(insn) - Feature = insn.get_canon_feature() - - if Feature & CF_USE1: - self.handle_operand(insn, insn.Op1, 1) - if Feature & CF_CHG1: - self.handle_operand(insn, insn.Op1, 0) - if Feature & CF_USE2: - self.handle_operand(insn, insn.Op2, 1) - if Feature & CF_CHG2: - self.handle_operand(insn, insn.Op2, 0) - if Feature & CF_JUMP: - remember_problem(PR_JUMP, insn.ea) - - # is it an unconditional jump? - uncond_jmp = insn.itype in [self.itype_JMP8, self.itype_JMP] and (aux & (self.FLa_NCS|self.FLa_CS)) == 0 - - # add flow - flow = (Feature & CF_STOP == 0) and not uncond_jmp - if flow: - add_cref(insn.ea, insn.ea + insn.size, fl_F) - - # trace the stack pointer if: - # - it is the second analysis pass - # - the stack pointer tracing is allowed - if may_trace_sp(): - if flow: - self.trace_sp(insn) # trace modification of SP register - else: - idc.recalc_spd(insn.ea) # recalculate SP register for the next insn - - return True - - # ---------------------------------------------------------------------- - def ev_out_operand(self, ctx, op): - """ - Generate text representation of an instructon operand. - This function shouldn't change the database, flags or anything else. - All these actions should be performed only by u_emu() function. - The output text is placed in the output buffer initialized with init_output_buffer() - This function uses out_...() functions from ua.hpp to generate the operand text - Returns: 1-ok, 0-operand is hidden. - """ - optype = op.type - fl = op.specval - signed = OOF_SIGNED if fl & self.FLo_SIGNED != 0 else 0 - def_arg = is_defarg(get_flags(ctx.insn.ea), op.n) - - if optype == o_reg: - ctx.out_register(self.reg_names[op.reg]) - - elif optype == o_imm: - # for immediate loads, use the transfer width (type of first operand) - if op.n == 1: - width = self.dt_to_width(ctx.insn.Op1.dtype) - else: - width = OOFW_32 if self.PTRSZ == 4 else OOFW_64 - ctx.out_value(op, OOFW_IMM | signed | width) - - elif optype in [o_near, o_mem]: - r = ctx.out_name_expr(op, op.addr, BADADDR) - if not r: - ctx.out_tagon(COLOR_ERROR) - ctx.out_btoa(op.addr, 16) - ctx.out_tagoff(COLOR_ERROR) - remember_problem(PR_NONAME, ctx.insn.ea) - - elif optype == o_displ: - indirect = fl & self.FLo_INDIRECT != 0 - if indirect: - ctx.out_symbol('[') - - ctx.out_register(self.reg_names[op.reg]) - - if op.addr != 0 or def_arg: - ctx.out_value(op, OOF_ADDR | (OOFW_32 if self.PTRSZ == 4 else OOFW_64) | signed | OOFS_NEEDSIGN) - - if indirect: - ctx.out_symbol(']') - else: - return False - - return True - - # ---------------------------------------------------------------------- - # Generate the instruction mnemonics - def ev_out_mnem(self, ctx): - # Init output buffer - - postfix = "" - - # First display size of first operand if it exists - if ctx.insn.auxpref & self.FLa_OP1 != 0: - postfix += self.fl_to_str(ctx.insn.Op1.specval) - - # Display opertion size - if ctx.insn.auxpref & self.FLa_32: - postfix += "32" - elif ctx.insn.auxpref & self.FLa_64: - postfix += "64" - - # Display if local or extern CALL - if ctx.insn.auxpref & self.FLa_EXTERN: - postfix += "EX" - - # Display if absolute call - if ctx.insn.auxpref & self.FLa_ABS: - postfix += "a" - - # Display size of instruction - if ctx.insn.auxpref & (self.FL_B | self.FL_W | self.FL_D | self.FL_Q) != 0: - postfix += self.fl_to_str(ctx.insn.auxpref) - - # Display JMP condition - if ctx.insn.auxpref & self.FLa_CS: - postfix += "cs" - elif ctx.insn.auxpref & self.FLa_NCS: - postfix += "cc" - - # Display CMP condition - if ctx.insn.auxpref & self.FLa_CMPMASK: - postfix += self.get_cmp(ctx.insn) - - ctx.out_mnem(12, postfix) - return 1 - - # ---------------------------------------------------------------------- - # Generate text representation of an instruction in 'ctx.insn' structure. - # This function shouldn't change the database, flags or anything else. - # All these actions should be performed only by u_emu() function. - def ev_out_insn(self, ctx): - - ctx.out_mnemonic() - - ctx.out_one_operand(0) - - for i in range(1, 3): - op = ctx.insn[i] - - if op.type == o_void: - break - - ctx.out_symbol(',') - ctx.out_char(' ') - ctx.out_one_operand(i) - - if ctx.insn.itype == self.itype_MOVREL: - fnaddr = self.check_thunk(ctx.insn.Op2.addr) - if fnaddr != None: - nm = get_ea_name(fnaddr, GN_VISIBLE) - if nm: - ctx.out_line("; Thunk to " + nm, COLOR_AUTOCMT) - - ctx.set_gen_cmt() - ctx.flush_outbuf() - return True - - # ---------------------------------------------------------------------- - def ev_ana_insn(self, insn): - """ - Decodes an instruction into insn - """ - # take opcode byte - b = insn.get_next_byte() - - # the 6bit opcode - opcode = b & 0x3F - - # opcode supported? - try: - ins = self.itable[opcode] - # set default itype - insn.itype = getattr(self, 'itype_' + ins.name) - except: - return 0 - # call the decoder - return True if ins.d(insn, b) else False - - # ---------------------------------------------------------------------- - def init_instructions(self): - class idef: - """ - Internal class that describes an instruction by: - - instruction name - - instruction decoding routine - - canonical flags used by IDA - """ - def __init__(self, name, cf, d, cmt = None): - self.name = name - self.cf = cf - self.d = d - self.cmt = cmt - - # - # Instructions table (w/ pointer to decoder) - # - self.itable = { - 0x00: idef(name='BREAK', d=self.decode_BREAK, cf = CF_USE1, cmt = self.cmt_BREAK), - - 0x01: idef(name='JMP', d=self.decode_JMP, cf = CF_USE1 | CF_JUMP, cmt = self.cmt_JMP), - 0x02: idef(name='JMP8', d=self.decode_JMP8, cf = CF_USE1 | CF_JUMP, cmt = self.cmt_JMP), - - 0x03: idef(name='CALL', d=self.decode_CALL, cf = CF_USE1 | CF_CALL, cmt = self.cmt_CALL), - 0x04: idef(name='RET', d=self.decode_RET, cf = CF_STOP, cmt = lambda insn: "Return from subroutine" ), - 0x05: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x06: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x07: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x08: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x09: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - - 0x0A: idef(name='NOT', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 = ~Op2" ), - 0x0B: idef(name='NEG', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 = -Op2" ), - 0x0C: idef(name='ADD', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 += Op2" ), - 0x0D: idef(name='SUB', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 -= Op2" ), - 0x0E: idef(name='MUL', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 *= Op2 (signed multiply)" ), - 0x0F: idef(name='MULU', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 *= Op2 (unsigned multiply)" ), - 0x10: idef(name='DIV', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 /= Op2 (signed division)" ), - 0x11: idef(name='DIVU', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 /= Op2 (unsigned division)" ), - 0x12: idef(name='MOD', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 %= Op2 (signed modulo)" ), - 0x13: idef(name='MODU', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 %= Op2 (unsigned modulo)" ), - 0x14: idef(name='AND', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 &= Op2" ), - 0x15: idef(name='OR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 |= Op2" ), - 0x16: idef(name='XOR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 ^= Op2" ), - 0x17: idef(name='SHL', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1 | CF_SHFT, cmt = lambda insn: "Op1 <<= Op2" ), - 0x18: idef(name='SHR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1 | CF_SHFT, cmt = lambda insn: "Op1 >>= Op2 (unsigned shift)" ), - 0x19: idef(name='ASHR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1 | CF_SHFT, cmt = lambda insn: "Op1 >>= Op2 (signed shift)" ), - - 0x1A: idef(name='EXTNDB', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Sign-extend a byte value" ), - 0x1B: idef(name='EXTNDW', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Sign-extend a word value" ), - 0x1C: idef(name='EXTNDD', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Sign-extend a dword value" ), - - 0x1D: idef(name='MOVbw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move byte" ), - 0x1E: idef(name='MOVww', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move word" ), - 0x1F: idef(name='MOVdw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move dword" ), - 0x20: idef(name='MOVqw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move qword" ), - 0x21: idef(name='MOVbd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move byte" ), - 0x22: idef(name='MOVwd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move word" ), - 0x23: idef(name='MOVdd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move dword" ), - 0x24: idef(name='MOVqd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move qword" ), - - 0x25: idef(name='MOVsnw', d=self.decode_MOVSN, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move signed natural value"), - 0x26: idef(name='MOVsnd', d=self.decode_MOVSN, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move signed natural value"), - - # 0x27: reserved - - 0x28: idef(name='MOVqq', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move qword" ), - - 0x29: idef(name='LOADSP', d=self.decode_LOADSP, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Load a VM dedicated register from a general-purpose register"), - 0x2A: idef(name='STORESP', d=self.decode_STORESP, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Store a VM dedicated register into a general-purpose register"), - - # PUSH/POP - 0x2B: idef(name='PUSH', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Push value on the stack" ), - 0x2C: idef(name='POP', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Pop value from the stack" ), - - # CMPI - 0x2D: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x2E: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x2F: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x30: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - 0x31: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), - - 0x32: idef(name='MOVnw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move unsigned natural value"), - 0x33: idef(name='MOVnd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move unsigned natural value"), - - # 0x34: reserved - - # PUSHn/POPn - 0x35: idef(name='PUSHn', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Push natural value on the stack" ), - 0x36: idef(name='POPn', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Pop natural value from the stack" ), - - 0x37: idef(name='MOVI', d=self.decode_MOVI, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move immediate value"), - 0x38: idef(name='MOVIn', d=self.decode_MOVI, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move immediate value"), - - 0x39: idef(name='MOVREL', d=self.decode_MOVREL, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Load IP-relative address") - # 0x3A: reserved - # 0x3B: reserved - # 0x3C: reserved - # 0x3D: reserved - # 0x3E: reserved - # 0x3F: reserved - } - - # Now create an instruction table compatible with IDA processor module requirements - Instructions = [] - i = 0 - for x in self.itable.values(): - d = dict(name=x.name, feature=x.cf) - if x.cmt != None: - d['cmt'] = x.cmt - Instructions.append(d) - setattr(self, 'itype_' + x.name, i) - i += 1 - - # icode of the last instruction + 1 - self.instruc_end = len(Instructions) - - # Array of instructions - self.instruc = Instructions - - # Icode of return instruction. It is ok to give any of possible return - # instructions - self.icode_return = self.itype_RET - - # ---------------------------------------------------------------------- - def init_registers(self): - """This function parses the register table and creates corresponding ireg_XXX constants""" - - # Registers definition - self.reg_names = [ - # General purpose registers - "SP", # aka R0 - "R1", - "R2", - "R3", - "R4", - "R5", - "R6", - "R7", - # VM registers - "FLAGS", # 0 - "IP", # 1 - "VM2", - "VM3", - "VM4", - "VM5", - "VM6", - "VM7", - # Fake segment registers - "CS", - "DS" - ] - - # Create the ireg_XXXX constants - for i in range(len(self.reg_names)): - setattr(self, 'ireg_' + self.reg_names[i], i) - - # Segment register information (use virtual CS and DS registers if your - # processor doesn't have segment registers): - self.reg_first_sreg = self.ireg_CS - self.reg_last_sreg = self.ireg_DS - - # number of CS register - self.reg_code_sreg = self.ireg_CS - - # number of DS register - self.reg_data_sreg = self.ireg_DS - - # ---------------------------------------------------------------------- - def __init__(self): - processor_t.__init__(self) - self.PTRSZ = 4 # Assume PTRSZ = 4 by default - self.init_instructions() - self.init_registers() - -# ---------------------------------------------------------------------- -def PROCESSOR_ENTRY(): - return ebc_processor_t() diff --git a/idasdk75/module/script/makefile b/idasdk75/module/script/makefile deleted file mode 100644 index 60be364..0000000 --- a/idasdk75/module/script/makefile +++ /dev/null @@ -1,10 +0,0 @@ -include ../../allmake.mak - -SCRIPTS += ebc.py -SCRIPTS += msp430.py - -BIN_PATH = $(R)procs/ -all: $(addprefix $(BIN_PATH),$(SCRIPTS)) - -$(BIN_PATH)%: % - $(CP) $? $@ diff --git a/idasdk75/module/script/msp430.py b/idasdk75/module/script/msp430.py deleted file mode 100644 index 56a6fcf..0000000 --- a/idasdk75/module/script/msp430.py +++ /dev/null @@ -1,1408 +0,0 @@ -# ---------------------------------------------------------------------- -# Texas Instruments MSP430 processor module -# Copyright (c) 2010-2020 Hex-Rays -# -# This module demonstrates: -# - instruction decoding and printing -# - simplification of decoded instructions -# - creation of code and data cross-references -# - auto-creation of data items from cross-references -# - tracing of the stack pointer changes -# - creation of the stack variables -# - handling of switch constructs -# -# Please send fixes or improvements to support@hex-rays.com - -import sys -import copy - -from ida_bytes import * -from ida_ua import * -from ida_idp import * -from ida_auto import * -from ida_nalt import * -from ida_funcs import * -from ida_lines import * -from ida_problems import * -from ida_offset import * -from ida_segment import * -from ida_name import * -from ida_netnode import * -from ida_xref import * -from ida_idaapi import * -import ida_frame -import idc - -if sys.version_info.major < 3: - range = xrange - -# extract bitfield occupying bits high..low from val (inclusive, start from 0) -def BITS(val, high, low): - return (val>>low)&((1<<(high-low+1))-1) - -# extract one bit -def BIT(val, bit): - return (val>>bit) & 1 - -# sign extend b low bits in x -# from "Bit Twiddling Hacks" -def SIGNEXT(x, b): - m = 1 << (b - 1) - x = x & ((1 << b) - 1) - return (x ^ m) - m - -# values for specval field for o_phrase operands -FL_INDIRECT = 1 # indirect: @Rn -FL_AUTOINC = 2 # auto-increment: @Rn+ - -# values for specval field for o_mem operands -FL_ABSOLUTE = 1 # absolute: &addr -FL_SYMBOLIC = 2 # symbolic: addr - -# values for insn_t.auxpref -AUX_SIZEMASK = 0x0F -AUX_NOSUF = 0x00 # no suffix (e.g. SWPB) -AUX_WORD = 0x01 # word transfer, .W suffix -AUX_BYTE = 0x02 # byte transfer, .B suffix -AUX_A = 0x03 # 20-bit transfer, .A suffix -AUX_AX = 0x04 # 20-bit immediate/address, no suffix -AUX_REPIMM = 0x10 # immediate repeat count present (in insn_t.segpref) -AUX_REPREG = 0x20 # register repeat count (reg no in in insn_t.segpref) -AUX_ZC = 0x40 # zero carry flag is set - -# addressing mode field in the opcode -AM_REGISTER = 0 # Rn -AM_INDEXED = 1 # X(Rn), also includes symbolic and absolute -AM_INDIRECT = 2 # @Rn -AM_AUTOINC = 3 # @Rn+, also includes immediate (#N = @PC+) -# extra formats -AM_IMM20 = 100 # Rn is imm19:16, imm15:0 follows -AM_ABS20 = 101 # Rn is &abs19:16, &abs15:0 follows -AM_SYM20 = 102 # as IMM20, plus PC value - -# operand data length value -# A/L B/W -DLEN_WORD = 0 # 1 0 16-bit word -DLEN_BYTE = 1 # 1 1 8-bit byte -DLEN_AWORD = 2 # 0 1 20-bit address-word -DLEN_LONG = 3 # 0 0 Reserved - -# check if operand is immediate value val -def is_imm_op(op, val): - if op.type == o_imm: - # workaround for difference between Python and native numbers - op2 = op_t() - op2.value = val - return op.value == op2.value - return False - -# are operands equal? -def same_op(op1, op2): - return op1.type == op2.type and \ - op1.reg == op2.reg and \ - op1.value == op2.value and \ - op1.addr == op2.addr and \ - op1.flags == op2.flags and \ - op1.specval == op2.specval and \ - op1.dtype == op2.dtype - -# is operand auto-increment register reg? -def is_autoinc(op, reg): - return op.type == o_phrase and op.reg == reg and op.specval == FL_AUTOINC - -# is sp delta fixed by the user? -def is_fixed_spd(ea): - return (get_aflags(ea) & AFL_FIXEDSPD) != 0 - -# ---------------------------------------------------------------------- -class msp430_processor_t(processor_t): - """ - Processor module classes must derive from processor_t - """ - - # IDP id ( Numbers above 0x8000 are reserved for the third-party modules) - id = PLFM_MSP430 - - # Processor features - flag = PR_SEGS | PRN_HEX | PR_RNAMESOK | PR_WORD_INS \ - | PR_USE32 | PR_DEFSEG32 - - # Number of bits in a byte for code segments (usually 8) - # IDA supports values up to 32 bits - cnbits = 8 - - # Number of bits in a byte for non-code segments (usually 8) - # IDA supports values up to 32 bits - dnbits = 8 - - # short processor names - # Each name should be shorter than 9 characters - psnames = ['msp430'] - - # long processor names - # No restriction on name lengthes. - plnames = ['Texas Instruments MSP430'] - - # size of a segment register in bytes - segreg_size = 0 - - # Array of typical code start sequences (optional) - codestart = ['\x0B\x12'] # 120B: push R11 - - # Array of 'return' instruction opcodes (optional) - # retcodes = ['\x30\x41'] # 4130: ret (mov.w @SP+, PC) - - # Array of instructions - instruc = [ - {'name': '', 'feature': 0}, # placeholder for "not an instruction" - - # two-operand instructions - {'name': 'mov', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Move source to destination"}, - {'name': 'add', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source to destination"}, - {'name': 'addc', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source and carry to destination"}, - {'name': 'subc', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source with carry from destination"}, - {'name': 'sub', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source from destination"}, - {'name': 'cmp', 'feature': CF_USE1 | CF_USE2, 'cmt': "Compare source and destination"}, - {'name': 'dadd', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source decimally to destination"}, - {'name': 'bit', 'feature': CF_USE1 | CF_USE2, 'cmt': "Test bits set in source in destination"}, - {'name': 'bic', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Clear bits set in source in destination"}, - {'name': 'bis', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Set bits set in source in destination"}, - {'name': 'xor', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Exclusive OR source with destination"}, - {'name': 'and', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Binary AND source and destination"}, - - # MSP430X instructions - {'name': 'movx', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Move source to destination"}, - {'name': 'addx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source to destination"}, - {'name': 'addcx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source and carry to destination"}, - {'name': 'subcx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source with carry from destination"}, - {'name': 'subx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source from destination"}, - {'name': 'cmpx', 'feature': CF_USE1 | CF_USE2, 'cmt': "Compare source and destination"}, - {'name': 'daddx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source decimally to destination"}, - {'name': 'bitx', 'feature': CF_USE1 | CF_USE2, 'cmt': "Test bits set in source in destination"}, - {'name': 'bicx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Clear bits set in source in destination"}, - {'name': 'bisx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Set bits set in source in destination"}, - {'name': 'xorx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Exclusive OR source with destination"}, - {'name': 'andx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Binary AND source and destination"}, - {'name': 'rrcm', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate right through C"}, - {'name': 'rram', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate right arithmetically"}, - {'name': 'rlam', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate left arithmetically"}, - {'name': 'rrum', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate right unsigned"}, - {'name': 'pushm', 'feature': CF_USE1 | CF_USE2, 'cmt': "Push registers onto stack"}, - {'name': 'popm', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Pop registers from the stack"}, - - # MSP430X address instructions - {'name': 'mova', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Move source to destination"}, - {'name': 'cmpa', 'feature': CF_USE1 | CF_USE2, 'cmt': "Compare source and destination"}, - {'name': 'adda', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source to destination"}, - {'name': 'suba', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source from destination"}, - - # one-operand instructions - {'name': 'rrc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right through C"}, - {'name': 'swpb', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Swap bytes"}, - {'name': 'rra', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right arithmetically"}, - {'name': 'sxt', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Extend sign (8 bits to 16)"}, - {'name': 'push', 'feature': CF_USE1 , 'cmt': "Push onto stack"}, - {'name': 'call', 'feature': CF_USE1 | CF_CALL, 'cmt': "Call subroutine"}, - {'name': 'reti', 'feature': CF_STOP , 'cmt': "Return from interrupt"}, - - # MSP430X instructions - {'name': 'rrcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right through carry"}, - {'name': 'swpbx','feature': CF_USE1 | CF_CHG1, 'cmt': "Exchange low byte with high byte"}, - {'name': 'rrax', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right arithmetically"}, - {'name': 'sxtx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Extend sign of lower byte"}, - {'name': 'pushx','feature': CF_USE1 , 'cmt': "Push onto stack"}, - {'name': 'calla','feature': CF_USE1 , 'cmt': "Call subroutine (20-bit)"}, - {'name': 'rrux', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right unsigned"}, - - # jumps - {'name': 'jnz', 'feature': CF_USE1 , 'cmt': "Jump if not zero/not equal"}, - {'name': 'jz', 'feature': CF_USE1 , 'cmt': "Jump if zero/equal"}, - {'name': 'jnc', 'feature': CF_USE1 , 'cmt': "Jump if no carry/lower (unsigned)"}, - {'name': 'jc', 'feature': CF_USE1 , 'cmt': "Jump if carry/higher or same (unsigned)"}, - {'name': 'jn', 'feature': CF_USE1 , 'cmt': "Jump if negative"}, - {'name': 'jge', 'feature': CF_USE1 , 'cmt': "Jump if greater or equal (signed)"}, - {'name': 'jl', 'feature': CF_USE1 , 'cmt': "Jump if less (signed)"}, - {'name': 'jmp', 'feature': CF_USE1 | CF_STOP, 'cmt': "Jump unconditionally"}, - - # emulated instructions - {'name': 'adc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry to destination"}, - {'name': 'br', 'feature': CF_USE1 | CF_STOP, 'cmt': "Branch to destination"}, - {'name': 'clr', 'feature': CF_CHG1 , 'cmt': "Clear destination"}, - {'name': 'clrc', 'feature': 0 , 'cmt': "Clear carry bit"}, - {'name': 'clrn', 'feature': 0 , 'cmt': "Clear negative bit"}, - {'name': 'clrz', 'feature': 0 , 'cmt': "Clear zero bit"}, - {'name': 'dadc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry decimally to destination"}, - {'name': 'dec', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Decrement destination"}, - {'name': 'decd', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Double-decrement destination"}, - {'name': 'dint', 'feature': 0 , 'cmt': "Disable general interrupts"}, - {'name': 'eint', 'feature': 0 , 'cmt': "Enable general interrupts"}, - {'name': 'inc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Increment destination"}, - {'name': 'incd', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Double-increment destination"}, - {'name': 'inv', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Invert destination"}, - {'name': 'nop', 'feature': 0 , 'cmt': "No operation"}, - {'name': 'pop', 'feature': CF_CHG1 , 'cmt': "Pop from the stack"}, - {'name': 'ret', 'feature': CF_STOP , 'cmt': "Return from subroutine"}, - {'name': 'rla', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left arithmetically"}, - {'name': 'rlc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left through carry"}, - {'name': 'sbc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Substract borrow (=NOT carry) from destination"}, - {'name': 'setc', 'feature': 0 , 'cmt': "Set carry bit"}, - {'name': 'setn', 'feature': 0 , 'cmt': "Set negative bit"}, - {'name': 'setz', 'feature': 0 , 'cmt': "Set zero bit"}, - {'name': 'tst', 'feature': CF_USE1 , 'cmt': "Test destination"}, - # MSP430X instructions - {'name': 'adcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry to destination"}, - {'name': 'bra', 'feature': CF_USE1 | CF_STOP, 'cmt': "Branch indirect to destination"}, - {'name': 'reta', 'feature': CF_STOP , 'cmt': "Return from subroutine"}, - {'name': 'popa', 'feature': CF_CHG1 , 'cmt': "Pop from the stack"}, - {'name': 'clra', 'feature': CF_CHG1 , 'cmt': "Clear destination"}, - {'name': 'clrx', 'feature': CF_CHG1 , 'cmt': "Clear destination"}, - {'name': 'dadcx','feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry decimally to destination"}, - {'name': 'decx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Decrement destination"}, - {'name': 'decda','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-decrement destination"}, - {'name': 'decdx','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-decrement destination"}, - {'name': 'incx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Increment destination"}, - {'name': 'incda','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-increment destination"}, - {'name': 'incdx','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-increment destination"}, - {'name': 'invx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Invert destination"}, - {'name': 'rlax', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left arithmetically"}, - {'name': 'rlcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left through carry"}, - {'name': 'sbcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Substract borrow (=NOT carry) from destination"}, - {'name': 'tsta', 'feature': CF_USE1 , 'cmt': "Test destination"}, - {'name': 'tstx', 'feature': CF_USE1 , 'cmt': "Test destination"}, - {'name': 'popx', 'feature': CF_CHG1 , 'cmt': "Pop from the stack"}, - ] - - # icode of the first instruction - instruc_start = 0 - - # icode of the last instruction + 1 - instruc_end = len(instruc) + 1 - - # Size of long double (tbyte) for this processor (meaningful only if ash.a_tbyte != NULL) (optional) - # tbyte_size = 0 - - # - # Number of digits in floating numbers after the decimal point. - # If an element of this array equals 0, then the corresponding - # floating point data is not used for the processor. - # This array is used to align numbers in the output. - # real_width[0] - number of digits for short floats (only PDP-11 has them) - # real_width[1] - number of digits for "float" - # real_width[2] - number of digits for "double" - # real_width[3] - number of digits for "long double" - # Example: IBM PC module has { 0,7,15,19 } - # - # (optional) - real_width = (0, 7, 15, 19) - - - # only one assembler is supported - assembler = { - # flag - 'flag' : ASH_HEXF0 | ASD_DECF0 | ASO_OCTF5 | ASB_BINF0 | AS_N2CHR, - - # user defined flags (local only for IDP) (optional) - 'uflag' : 0, - - # Assembler name (displayed in menus) - 'name': "Generic MSP430 assembler", - - # array of automatically generated header lines they appear at the start of disassembled text (optional) - 'header': [".msp430"], - - # org directive - 'origin': ".org", - - # end directive - 'end': ".end", - - # comment string (see also cmnt2) - 'cmnt': ";", - - # ASCII string delimiter - 'ascsep': "\"", - - # ASCII char constant delimiter - 'accsep': "'", - - # ASCII special chars (they can't appear in character and ascii constants) - 'esccodes': "\"'", - - # - # Data representation (db,dw,...): - # - # ASCII string directive - 'a_ascii': ".char", - - # byte directive - 'a_byte': ".byte", - - # word directive - 'a_word': ".short", - - # dword (32 bits) - 'a_dword': ".long", - - # qword (64 bits) - 'a_qword': ".quad", - - # float; 4bytes; remove if not allowed - 'a_float': ".float", - - # double ; 8bytes; remove if not allowed - 'a_double': ".double", - - # uninitialized data directive (should include '%s' for the size of data) - 'a_bss': ".space %s", - - # 'equ' Used if AS_UNEQU is set (optional) - 'a_equ': ".equ", - - # 'seg ' prefix (example: push seg seg001) - 'a_seg': "seg", - - # current IP (instruction pointer) symbol in assembler - 'a_curip': "$", - - # "public" name keyword. NULL-gen default, ""-do not generate - 'a_public': ".def", - - # "weak" name keyword. NULL-gen default, ""-do not generate - 'a_weak': "", - - # "extrn" name keyword - 'a_extrn': ".ref", - - # "comm" (communal variable) - 'a_comdef': "", - - # "align" keyword - 'a_align': ".align", - - # Left and right braces used in complex expressions - 'lbrace': "(", - 'rbrace': ")", - - # % mod assembler time operation - 'a_mod': "%", - - # & bit and assembler time operation - 'a_band': "&", - - # | bit or assembler time operation - 'a_bor': "|", - - # ^ bit xor assembler time operation - 'a_xor': "^", - - # ~ bit not assembler time operation - 'a_bnot': "~", - - # << shift left assembler time operation - 'a_shl': "<<", - - # >> shift right assembler time operation - 'a_shr': ">>", - - # size of type (format string) (optional) - 'a_sizeof_fmt': "size %s", - - 'flag2': 0, - - # the include directive (format string) (optional) - 'a_include_fmt': '.include "%s"', - } # Assembler - - def ev_get_frame_retsize(self, frsize, pfn): - ida_pro.int_pointer.frompointer(frsize).assign(2) - return 1 - - def ev_get_autocmt(self, insn): - if 'cmt' in self.instruc[insn.itype]: - return self.instruc[insn.itype]['cmt'] - - # ---------------------------------------------------------------------- - def ev_is_sane_insn(self, insn, no_crefs): - w = get_wide_word(insn.ea) - if w == 0 or w == 0xFFFF: - return -1 - return 1 - - # ---------------------------------------------------------------------- - def is_movpc(self, insn): - # mov xxx, PC - return insn.itype == self.itype_mov and insn.Op2.is_reg(self.ireg_PC) and insn.auxpref == AUX_WORD - - # ---------------------------------------------------------------------- - def changes_pc(self, insn): - Feature = insn.get_canon_feature() - if (Feature & CF_CHG2) and insn.Op2.is_reg(self.ireg_PC): - return True - if (Feature & CF_CHG1) and insn.Op1.is_reg(self.ireg_PC): - return True - return False - - # ---------------------------------------------------------------------- - def handle_operand(self, insn, op, isRead): - flags = get_flags(insn.ea) - is_offs = is_off(flags, op.n) - dref_flag = dr_R if isRead else dr_W - def_arg = is_defarg(flags, op.n) - optype = op.type - - itype = insn.itype - # create code xrefs - if optype == o_imm: - makeoff = False - if itype in [self.itype_call, self.itype_calla]: - # call #func - insn.add_cref(op.value, op.offb, fl_CN) - makeoff = True - elif self.is_movpc(insn) or insn.itype in [self.itype_br, self.itype_bra]: - # mov #addr, PC - insn.add_cref(op.value, op.offb, fl_JN) - makeoff = True - if makeoff and not def_arg: - op_plain_offset(insn.ea, op.n, insn.cs) - is_offs = True - if is_offs: - insn.add_off_drefs(op, dr_O, 0) - # create data xrefs - elif optype == o_displ: - # delta(reg) - if is_offs: - insn.add_off_drefs(op, dref_flag, OOF_ADDR) - elif may_create_stkvars() and not def_arg and op.reg == self.ireg_SP: - # var_x(SP) - pfn = get_func(insn.ea) - if pfn and insn.create_stkvar(op, op.addr, STKVAR_VALID_SIZE): - op_stkvar(insn.ea, op.n) - elif optype == o_mem: - insn.create_op_data(op.addr, op) - insn.add_dref(op.addr, op.offb, dref_flag) - elif optype == o_near: - insn.add_cref(op.addr, op.offb, fl_JN) - - # ---------------------------------------------------------------------- - def add_stkpnt(self, pfn, insn, v): - if pfn: - end = insn.ea + insn.size - if not is_fixed_spd(end): - ida_frame.add_auto_stkpnt(pfn, end, v) - - # ---------------------------------------------------------------------- - def trace_sp(self, insn): - """ - Trace the value of the SP and create an SP change point if the current - instruction modifies the SP. - """ - pfn = get_func(insn.ea) - if not pfn: - return - spofs = 0 - if insn.itype in [self.itype_add, self.itype_addx, self.itype_adda, self.itype_addc, self.itype_addcx, - self.itype_sub, self.itype_subx, self.itype_suba, self.itype_subc, self.itype_subcx] and \ - insn.Op2.is_reg(self.ireg_SP) and insn.auxpref in [AUX_WORD, AUX_A, AUX_AX] and \ - insn.Op1.type == o_imm: - # add.w #xxx, SP - # subc.w #xxx, SP - if insn.auxpref == AUX_WORD: - spofs = SIGNEXT(insn.Op1.value, 16) - else: - spofs = SIGNEXT(insn.Op1.value, 20) - if insn.itype in [self.itype_sub, self.itype_suba, self.itype_subc, self.itype_subx, self.itype_subcx]: - spofs = -spofs - elif insn.itype in [self.itype_incd, self.itype_decd, self.itype_incdx, - self.itype_decdx, self.itype_incda, self.itype_decda] and \ - insn.Op1.is_reg(self.ireg_SP) and insn.auxpref in [AUX_WORD, AUX_A, AUX_AX]: - spofs = 2 if insn.itype in [self.itype_incd, self.itype_incdx, self.itype_incda] else -2 - self.add_stkpnt(pfn, insn, spofs) - elif insn.itype == self.itype_push: - spofs = -2 - elif insn.itype in [self.itype_popm, self.itype_pushm, self.itype_popx, self.itype_pushx]: - # popm.a #n, reg -> +n*4 - # popm.w #n, reg -> +n*2 - # popx.a reg -> +4 - # popx.w reg -> +2 - if insn.itype in [self.itype_popm, self.itype_pushm]: - count = insn.Op1.value - else: - count = 1 - spofs = 1 if insn.itype == self.itype_popm else -1 - if insn.auxpref == AUX_A: - spofs *= count * 4 - else: - spofs *= count * 2 - elif insn.itype == self.itype_pop or is_autoinc(insn.Op1, self.ireg_SP): - # pop R7 or mov.w @SP+, R7 - if insn.auxpref in [AUX_A, AUX_AX]: - spofs = 4 - else: - spofs = 2 - - if spofs != 0: - self.add_stkpnt(pfn, insn, spofs) - - # ---------------------------------------------------------------------- - def check_switch(self, insn): - # detect switches and set switch info - # - # cmp.w #nn, Rx - # jc default - # [mov.w Rx, Ry] - # rla.w Ry, Ry - # br jtbl(Ry) - # jtbl .short case0, .short case1 - if get_switch_info(insn.ea): - return - ok = False - si = switch_info_t() - - # mov.w jtbl(Ry), PC - if (self.is_movpc(insn) or insn.itype in [self.itype_br, self.itype_bra]) and insn.Op1.type == o_displ: - si.jumps = insn.Op1.addr # jump table address - Ry = insn.Op1.reg - ok = True - # add.w Ry, Ry | rla.w Ry - prev = insn_t() - if decode_prev_insn(prev, insn.ea) != BADADDR and prev.auxpref == AUX_WORD: - ok = prev.itype == self.itype_add and prev.Op1.is_reg(Ry) and prev.Op2.is_reg(Ry) or \ - prev.itype == self.itype_rla and prev.Op1.is_reg(Ry) - else: - ok = False - if ok and decode_prev_insn(prev, prev.ea) != BADADDR: - # mov.w Rx, Ry - if prev.itype == self.itype_mov and \ - prev.Op2.is_reg(Ry) and \ - prev.Op1.type == o_reg and \ - prev.auxpref == AUX_WORD: - Rx = prev.Op1.reg - ok = decode_prev_insn(prev, prev.ea) != BADADDR - else: - Rx = Ry - else: - ok = False - - # jc default - if ok and prev.itype == self.itype_jc: - si.defjump = prev.Op1.addr - else: - ok = False - - # cmp.w #nn, Rx - if ok and decode_prev_insn(prev, prev.ea) == BADADDR or \ - prev.itype != self.itype_cmp or \ - prev.Op1.type != o_imm or \ - not prev.Op2.is_reg(Rx) or \ - prev.auxpref != AUX_WORD: - ok = False - else: - si.ncases = prev.Op1.value - si.lowcase = 0 - si.startea = prev.ea - si.set_expr(Rx, dt_word) - - if ok: - # make offset to the jump table - op_plain_offset(insn.ea, 0, insn.cs) - set_switch_info(insn.ea, si) - create_switch_table(insn.ea, si) - - # ---------------------------------------------------------------------- - # The following callbacks are mandatory - # - def ev_emu_insn(self, insn): - aux = self.get_auxpref(insn) - Feature = insn.get_canon_feature() - - if Feature & CF_USE1: - self.handle_operand(insn, insn.Op1, 1) - if Feature & CF_CHG1: - self.handle_operand(insn, insn.Op1, 0) - if Feature & CF_USE2: - self.handle_operand(insn, insn.Op2, 1) - if Feature & CF_CHG2: - self.handle_operand(insn, insn.Op2, 0) - if Feature & CF_JUMP: - remember_problem(PR_JUMP, insn.ea) - - # is it an unconditional jump? - uncond_jmp = insn.itype in [self.itype_jmp, self.itype_br, self.itype_bra] or self.changes_pc(insn) - - # add flow - flow = (Feature & CF_STOP == 0) and not uncond_jmp - if flow: - add_cref(insn.ea, insn.ea + insn.size, fl_F) - else: - self.check_switch(insn) - - # trace the stack pointer if: - # - it is the second analysis pass - # - the stack pointer tracing is allowed - if may_trace_sp(): - if flow: - self.trace_sp(insn) # trace modification of SP register - else: - idc.recalc_spd(insn.ea) # recalculate SP register for the next insn - - return True - - # ---------------------------------------------------------------------- - def ev_out_operand(self, ctx, op): - optype = op.type - fl = op.specval - signed = 0 - sz = ctx.insn.auxpref & AUX_SIZEMASK - - if optype == o_reg: - ctx.out_register(self.reg_names[op.reg]) - elif optype == o_imm: - ctx.out_symbol('#') - op2 = copy.copy(op) - if sz == AUX_BYTE: - op2.value &= 0xFF - elif sz == AUX_WORD: - op2.value &= 0xFFFF - else: - op2.value &= 0xFFFFF - ctx.out_value(op2, OOFW_IMM | signed ) - elif optype in [o_near, o_mem]: - if optype == o_mem and fl == FL_ABSOLUTE: - ctx.out_symbol('&') - r = ctx.out_name_expr(op, op.addr, BADADDR) - if not r: - ctx.out_tagon(COLOR_ERROR) - ctx.out_btoa(op.addr, 16) - ctx.out_tagoff(COLOR_ERROR) - remember_problem(PR_NONAME, ctx.insn.ea) - elif optype == o_displ: - # 16-bit index is signed - width = OOFW_16 - sign = OOF_SIGNED - if sz in [AUX_A, AUX_AX] or op.dtype == dt_dword: - # 20-bit index is not signed - width = OOFW_24 - sign = 0 - ctx.out_value(op, OOF_ADDR | signed | width ) - ctx.out_symbol('(') - ctx.out_register(self.reg_names[op.reg]) - ctx.out_symbol(')') - elif optype == o_phrase: - ctx.out_symbol('@') - ctx.out_register(self.reg_names[op.reg]) - if fl == FL_AUTOINC: - ctx.out_symbol('+') - else: - return False - - return True - - # ---------------------------------------------------------------------- - def ev_out_mnem(self, ctx): - - postfix = "" - - # add postfix if necessary - sz = ctx.insn.auxpref & AUX_SIZEMASK - if sz == AUX_BYTE: - postfix = ".b" - elif sz == AUX_WORD: - postfix = ".w" - elif sz == AUX_A: - postfix = ".a" - - # first argument (8) is the width of the mnemonic field - ctx.out_mnem(8, postfix) - return 1 - - # ---------------------------------------------------------------------- - def ev_out_insn(self, ctx): - """ - Generate text representation of an instruction in 'ctx.insn' structure. - This function shouldn't change the database, flags or anything else. - All these actions should be performed only by emu() function. - Returns: nothing - """ - # do we need to print a modifier line first? - if ctx.insn.auxpref & (AUX_REPREG | AUX_REPIMM | AUX_ZC): - segpref = ctx.insn.segpref - if sys.version_info.major < 3: - segpref = ord(segpref) - if ctx.insn.auxpref & AUX_ZC: - ctx.out_line(".zc", COLOR_INSN) - ctx.flush_outbuf() - if ctx.insn.auxpref & AUX_REPREG: - ctx.out_line(".rpt", COLOR_INSN) - ctx.out_char(' ') - ctx.out_register(self.reg_names[segpref]) - ctx.flush_outbuf() - if ctx.insn.auxpref & AUX_REPIMM: - ctx.out_line(".rpt", COLOR_INSN) - ctx.out_char(' ') - ctx.out_symbol('#') - ctx.out_long(segpref, 10) - ctx.flush_outbuf() - #ident next line - ctx.out_char(' ') - - ctx.out_mnemonic() - - # output first operand - # kernel will call out_operand() - if ctx.insn.Op1.type != o_void: - ctx.out_one_operand(0) - - # output the rest of operands separated by commas - for i in range(1, 3): - if ctx.insn[i].type == o_void: - break - ctx.out_symbol(',') - ctx.out_char(' ') - ctx.out_one_operand(i) - - ctx.set_gen_cmt() # generate comment at the next call to MakeLine() - ctx.flush_outbuf() - return True - - # ---------------------------------------------------------------------- - # fill operand fields from decoded instruction parts - # op: operand to be filled in - # reg: register number - # A: adressing mode - # BW: value of the B/W (byte/word) field - # can be DLEN_AWORD for 20-bit instructions - # is_source: True if filling source operand - # is_cg: can use constant generator - # extw: 20-bit extension word - def fill_op(self, insn, op, reg, A, BW, is_source, is_cg = False, extw = None): - op.reg = reg - topaddr = 0 # top 4 bits of an address value - if extw: - AL = BIT(extw, 6) - if AL == 0 and BW == 1: - BW = DLEN_AWORD - if is_source: - topaddr = BITS(extw, 10, 7) - else: - topaddr = BITS(extw, 3, 0) - if BW == DLEN_WORD: - op.dtype = dt_word - elif BW == DLEN_BYTE: - op.dtype = dt_byte - else: - # 20-bit - op.dtype = dt_dword - if is_cg: - # check for constant generators - if reg == self.ireg_SR and A >= 2 and A <= 3: - op.type = o_imm - op.value = [4, 8] [A-2] - return - elif reg == self.ireg_R3: - op.type = o_imm - op.value = [0, 1, 2, -1] [A] - return - if A == AM_REGISTER: - # register mode - op.type = o_reg - op.dtype = dt_word - elif A == AM_INDEXED: - # indexed mode - if reg == self.ireg_SR: - # absolute address mode - op.type = o_mem - op.specval = FL_ABSOLUTE - op.offb = insn.size - op.addr = insn.get_next_word() | (topaddr << 16) - else: - # map it to IDA's displacement - op.type = o_displ - op.offb = insn.size - pcval = insn.ip + insn.size - op.addr = insn.get_next_word() | (topaddr << 16) - if reg == self.ireg_PC: - # symbolic addressing mode: address = PC + simm16 - # 1) if PC is below 64K, the result is wrapped to be below 64K - # 2) if PC is above 64K, the result is used as-is (can be below or above 64K) - # 3) for MSP430X instructions delta is simm20, result not wrapped - # apparently the PC value is the address of the index word, not next instruction! - if extw: - op.addr = SIGNEXT(op.addr, 20) + pcval - else: - op.addr = SIGNEXT(op.addr, 16) + pcval - if pcval < 0x10000: - op.addr &= 0xFFFF - op.type = o_mem - op.specval = FL_SYMBOLIC - # slau208p.pdf: All addresses, indexes, and immediate numbers have - # 20-bit values when preceded by the extension word. - if extw: - op.dtype = dt_dword - elif A == AM_INDIRECT: - # Indirect register mode - # map it to o_phrase - op.type = o_phrase - op.specval = FL_INDIRECT - elif A == AM_AUTOINC: - # Indirect autoincrement - # map it to o_phrase - if reg == self.ireg_PC: - #this is actually immediate mode - op.dtype = dt_dword if extw else dt_word - op.type = o_imm - op.offb = insn.size - op.value = insn.get_next_word() | (topaddr << 16) - else: - op.type = o_phrase - op.specval = FL_AUTOINC - elif A in [AM_IMM20, AM_ABS20, AM_SYM20]: - # reg is the high 4 bits, low 16 bits follow - val = (reg << 16) | insn.get_next_word() - if A == AM_IMM20: - op.dtype = dt_dword - op.value = val - op.type = o_imm - else: - # &abs20 - op.addr = val - op.type = o_mem - if A == AM_SYM20: - # symbolic addressing mode: address = PC + imm20 - # no sign-extension or wrapping is done - pcval = insn.ip + insn.size - op.addr += pcval - op.specval = FL_SYMBOLIC - else: - op.specval = FL_ABSOLUTE - else: - warning("bad A(%d) in fill_op" % A) - - # ---------------------------------------------------------------------- - def handle_reg_extw(self, insn, extw): - # Register Mode Extension Word - # 15 ... 12 11 10 9 8 7 6 5 4 3 0 - # +---------+--------+----+---+-----+---+---+------+ - # | 0001 | 1 | 00 | ZC | # | A/L | 0 | 0 | R/n-1| - # +---------+--------+----+---+-----+---+---+------+ - ZC = BIT(extw, 8) - repreg = BIT(extw, 7) - rep = BITS(extw, 3, 0) - if rep: - if repreg: - insn.auxpref |= AUX_REPREG - insn.segpref = rep - else: - insn.auxpref |= AUX_REPIMM - insn.segpref = rep + 1 - if ZC: - if insn.itype == self.itype_rrcx: - insn.itype = self.itype_rrux - else: - insn.auxpref |= AUX_ZC - - # ---------------------------------------------------------------------- - def decode_format_I(self, insn, w, extw): - # Double-Operand (Format I) Instructions - # - # 15 ... 12 11 ... 8 7 6 5 4 3 0 - # +---------+--------+----+-----+----+------+ - # | Op-code | Rsrc | Ad | B/W | As | Rdst | - # +---------+--------+----+-----+----+------+ - # | Source or destination 15:0 | - # +-----------------------------------------+ - # | Destination 15:0 | - # +-----------------------------------------+ - opc = BITS(w, 15, 12) - As = BITS(w, 5, 4) - Ad = BIT(w, 7) - Rsrc = BITS(w, 11, 8) - Rdst = BITS(w, 3, 0) - BW = BIT(w, 6) - if opc < 4: - # something went wrong - insn.size = 0 - else: - if extw: - AL = BIT(extw, 6) - if AL == 0 and BW == 1: - BW = DLEN_AWORD - insn.itype = self.itype_movx + (opc-4) - else: - insn.itype = self.itype_mov + (opc-4) - self.fill_op(insn, insn.Op1, Rsrc, As, BW, True, True, extw) - self.fill_op(insn, insn.Op2, Rdst, Ad, BW, False, False, extw) - insn.auxpref = BW + AUX_WORD - if extw and As == AM_REGISTER and Ad == AM_REGISTER: - self.handle_reg_extw(insn, extw) - - # ---------------------------------------------------------------------- - def decode_format_II(self, insn, w, extw): - # Single-Operand (Format II) Instructions - # - # 15 10 9 7 6 5 4 3 0 - # +-------------+---------+-----+----+------+ - # | 0 0 0 1 0 0 | Op-code | B/W | Ad | Rdst | - # +-------------+---------+-----+----+------+ - # | Destination 15:0 | - # +-----------------------------------------+ - opc = BITS(w, 9, 7) - Ad = BITS(w, 5, 4) - Rdst = BITS(w, 3, 0) - BW = BIT(w, 6) - if opc in [6, 7]: - if extw: - return 0 - return self.decode_430x_calla(insn, w) - if extw: - AL = BIT(extw, 6) - if AL == 0 and BW == 1: - BW = DLEN_AWORD - insn.itype = self.itype_rrcx + opc - else: - insn.itype = self.itype_rrc + opc - self.fill_op(insn, insn.Op1, Rdst, Ad, BW, False, True, extw) - insn.auxpref = BW + AUX_WORD - if insn.itype in [self.itype_swpb, self.itype_sxt, self.itype_call, self.itype_reti]: - # these commands have no suffix and should have BW set to 0 - if BW == 0: - insn.auxpref = AUX_NOSUF - if insn.itype == self.itype_reti: - # Ad and Rdst should be 0 - if Ad == 0 and Rdst == 0: - insn.Op1.type = o_void - else: - # bad instruction - insn.itype = self.itype_null - else: - # bad instruction - insn.itype = self.itype_null - if extw and Ad == AM_REGISTER: - self.handle_reg_extw(insn, extw) - - # ---------------------------------------------------------------------- - def decode_jump(self, insn, w): - # Jump Instructions - # - # 15 13 12 10 9 0 - # +---------+-------+----------------------+ - # | 0 0 1 | C | 10-bit PC offset | - # +---------+-------+----------------------+ - C = BITS(w, 12, 10) - offs = BITS(w, 9, 0) - offs = SIGNEXT(offs, 10) - insn.Op1.type = o_near - insn.Op1.addr = insn.ea + 2 + offs*2 - insn.itype = self.itype_jnz + C - - # ---------------------------------------------------------------------- - def decode_430x_mova(self, insn, w): - # MSP430X Address Instructions - # 15 12 11 8 7 4 3 0 - # 0 0 0 0 src 0 0 0 0 dst MOVA @Rsrc,Rdst - # 0 0 0 0 src 0 0 0 1 dst MOVA @Rsrc+,Rdst - # 0 0 0 0 abs 0 0 1 0 dst MOVA &abs20,Rdst - # 0 0 0 0 src 0 0 1 1 dst MOVA x(Rsrc),Rdst - - # 0 0 0 0 n-1 00 0 1 0 0 dst RRCM.A #n,Rdst - # 0 0 0 0 n-1 01 0 1 0 0 dst RRAM.A #n,Rdst - # 0 0 0 0 n-1 10 0 1 0 0 dst RLAM.A #n,Rdst - # 0 0 0 0 n-1 11 0 1 0 0 dst RRUM.A #n,Rdst - - # 0 0 0 0 n-1 00 0 1 0 1 dst RRCM.W #n,Rdst - # 0 0 0 0 n-1 01 0 1 0 1 dst RRAM.W #n,Rdst - # 0 0 0 0 n-1 10 0 1 0 1 dst RLAM.W #n,Rdst - # 0 0 0 0 n-1 11 0 1 0 1 dst RRUM.W #n,Rdst - - # 0 0 0 0 src 0 1 1 0 abs MOVA Rsrc,&abs20 - # 0 0 0 0 src 0 1 1 1 dst MOVA Rsrc,X(Rdst) - - # 0 0 0 0 imm 1 0 0 0 dst MOVA #imm20,Rdst - # 0 0 0 0 imm 1 0 0 1 dst CMPA #imm20,Rdst - # 0 0 0 0 imm 1 0 1 0 dst ADDA #imm20,Rdst - # 0 0 0 0 imm 1 0 1 1 dst SUBA #imm20,Rdst - # 0 0 0 0 src 1 1 0 0 dst MOVA Rsrc,Rdst - # 0 0 0 0 src 1 1 0 1 dst CMPA Rsrc,Rdst - # 0 0 0 0 src 1 1 1 0 dst ADDA Rsrc,Rdst - # 0 0 0 0 src 1 1 1 1 dst SUBA Rsrc,Rdst - - opc = BITS(w, 7, 4) - Rsrc = BITS(w, 11, 8) - Rdst = BITS(w, 3, 0) - tbl = [ - # itype, operands addressing modes - # indexed by opcode[7:4] - [self.itype_mova, AM_INDIRECT, AM_REGISTER], # 0000 MOVA @Rsrc,Rdst - [self.itype_mova, AM_AUTOINC, AM_REGISTER], # 0001 MOVA @Rsrc+,Rdst - [self.itype_mova, AM_ABS20, AM_REGISTER], # 0010 MOVA &abs20,Rdst - [self.itype_mova, AM_INDEXED, AM_REGISTER], # 0011 MOVA X(Rsrc),Rdst - [-1, -1, -1 ], # 0100 Rxxx.A #n, Rdst - [-1, -1, -1 ], # 0101 Rxxx.W #n, Rdst - [self.itype_mova, AM_REGISTER, AM_ABS20 ], # 0110 MOVA Rsrc, &abs20 - [self.itype_mova, AM_REGISTER, AM_INDEXED ], # 0111 MOVA Rsrc, X(Rdst) - [self.itype_mova, AM_IMM20, AM_REGISTER], # 1000 MOVA #imm20, Rdst - [self.itype_cmpa, AM_IMM20, AM_REGISTER], # 1001 CMPA #imm20, Rdst - [self.itype_adda, AM_IMM20, AM_REGISTER], # 1010 ADDA #imm20, Rdst - [self.itype_suba, AM_IMM20, AM_REGISTER], # 1011 SUBA #imm20, Rdst - [self.itype_mova, AM_REGISTER, AM_REGISTER], # 1100 MOVA Rsrc, Rdst - [self.itype_cmpa, AM_REGISTER, AM_REGISTER], # 1101 CMPA Rsrc, Rdst - [self.itype_adda, AM_REGISTER, AM_REGISTER], # 1110 ADDA Rsrc, Rdst - [self.itype_suba, AM_REGISTER, AM_REGISTER], # 1111 SUBA Rsrc, Rdst - ] - row = tbl[opc] - if row[0] != -1: - insn.itype = row[0] - self.fill_op(insn, insn.Op1, Rsrc, row[1], 2, True, Rdst != 0) - self.fill_op(insn, insn.Op2, Rdst, row[2], 2, False, False) - insn.auxpref = AUX_AX - else: - # src[3:2] == n-1 - # src[1:0] == insn id - insn.itype = self.itype_rrcm + (Rsrc & 0b11) - insn.Op1.type = o_imm - insn.Op1.dtype = dt_byte - insn.Op1.value = (Rsrc>>2) + 1 - # opc[0]: 0=.A, 1=.W - BW = 0 if (opc & 1) else 2 - self.fill_op(insn, insn.Op2, Rdst, AM_REGISTER, BW, False, False) - if opc & 1: - insn.auxpref = AUX_A - else: - insn.auxpref = AUX_WORD - - # ---------------------------------------------------------------------- - def decode_430x_calla(self, insn, w): - # MSP430X CALLA Instruction - opc = BITS(w, 7, 4) - Rdst = BITS(w, 3, 0) - tbl = [ - # itype, dest addressing mode - # indexed by opcode[7:4] - [self.itype_reti, -1 ], # 0000 RETI - [self.itype_null, -1 ], # 0001 ---- - [self.itype_null, -1 ], # 0010 ---- - [self.itype_null, -1 ], # 0011 ---- - [self.itype_calla, AM_REGISTER], # 0100 CALLA Rdst - [self.itype_calla, AM_INDEXED ], # 0101 CALLA X(Rdst) - [self.itype_calla, AM_INDIRECT], # 0110 CALLA @Rdst - [self.itype_calla, AM_AUTOINC ], # 0111 CALLA @Rdst+ - [self.itype_calla, AM_ABS20 ], # 1000 CALLA &abs20 - [self.itype_calla, AM_SYM20 ], # 1001 CALLA sym20 (imm20+PC) - [self.itype_null, -1 ], # 1010 ---- - [self.itype_calla, AM_IMM20 ], # 1011 CALLA #imm20 - [self.itype_null, -1 ], # 1100 ---- - [self.itype_null, -1 ], # 1101 ---- - [self.itype_null, -1 ], # 1110 ---- - [self.itype_null, -1 ], # 1111 ---- - ] - row = tbl[opc] - insn.itype = row[0] - if row[1] != -1: - self.fill_op(insn, insn.Op1, Rdst, row[1], DLEN_AWORD, True, False) - insn.auxpref = AUX_AX - - # ---------------------------------------------------------------------- - def decode_430x_pushm(self, insn, w): - # MSP430X PUSHM/POPM Instructions - # 15 10 98 7 4 3 0 - # 000101 00 n-1 dst PUSHM.A #n,Rdst - # 000101 01 n-1 dst PUSHM.W #n,Rdst - # 000101 10 n-1 dst-n+1 POPM.A #n, Rdst - # 000101 11 n-1 dst-n+1 POPM.W #n, Rdst - opc = BITS(w, 7, 4) - Rdst = BITS(w, 3, 0) - - ispop = BIT(w, 9) - insn.itype = [self.itype_pushm, self.itype_popm] [ispop] - n = BITS(w, 7, 4) + 1 - Rdst = BITS(w, 3, 0) - if ispop: - Rdst += n - 1 - insn.Op1.type = o_imm - insn.Op1.dtype = dt_byte - insn.Op1.value = n - isw = BIT(w, 8) - BW = 0 if isw else 2 - self.fill_op(insn, insn.Op2, Rdst, AM_REGISTER, BW, False, False) - insn.auxpref = [AUX_A, AUX_WORD] [isw] - - # ---------------------------------------------------------------------- - # does operand match tuple m? (type, value) - def match_op(self, op, m): - if m == None: - return True - if op.type != m[0]: - return False - if op.type == o_imm: - return op.value == m[1] - elif op.type in [o_reg, o_phrase]: - return op.reg == m[1] - else: - return false - - # ---------------------------------------------------------------------- - # replace some instructions by simplified mnemonics ("emulated" in TI terms) - def simplify(self, insn): - # source mnemonic mapped to a list of matches: - # match function, new mnemonic, new operand - maptbl = { - self.itype_addc: [ - # addc #0, dst -> adc dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_adc, 2 ], - # addc dst, dst -> rlc dst - [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rlc, 1 ], - ], - self.itype_addcx: [ - # addcx #0, dst -> adcx dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_adcx, 2 ], - # addcx dst, dst -> rlcx dst - [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rlcx, 1 ], - ], - self.itype_mov: [ - # mov #0, R3 -> nop - [ lambda: is_imm_op(insn.Op1, 0) and insn.Op2.is_reg(self.ireg_R3), self.itype_nop, 0 ], - # mov #0, dst -> clr dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_clr, 2 ], - # mov @SP+, PC -> ret - [ lambda: is_autoinc(insn.Op1, self.ireg_SP) and insn.Op2.is_reg(self.ireg_PC), self.itype_ret, 0 ], - # mov @SP+, dst -> pop dst - [ lambda: is_autoinc(insn.Op1, self.ireg_SP), self.itype_pop, 2 ], - # mov dst, PC -> br dst - [ lambda: self.is_movpc(insn), self.itype_br, 1 ], - ], - self.itype_movx: [ - # movx #0, dst -> clrx dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_clrx, 2 ], - # movx @SP+, dst -> popx dst - [ lambda: is_autoinc(insn.Op1, self.ireg_SP), self.itype_popx, 2 ], - ], - self.itype_mova: [ - # mova #0, dst -> clra dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_clra, 2 ], - # mova @SP+, PC -> reta - [ lambda: is_autoinc(insn.Op1, self.ireg_SP) and insn.Op2.is_reg(self.ireg_PC), self.itype_reta, 0 ], - # mova @SP+, dst -> popa dst - [ lambda: is_autoinc(insn.Op1, self.ireg_SP), self.itype_popa, 2 ], - # mova dst, PC -> bra dst - [ lambda: insn.Op2.is_reg(self.ireg_PC), self.itype_bra, 1 ], - ], - self.itype_bic: [ - # bic #1, SR -> clrc - [ lambda: is_imm_op(insn.Op1, 1) and insn.Op2.is_reg(self.ireg_SR), self.itype_clrc, 0 ], - # bic #2, SR -> clrz - [ lambda: is_imm_op(insn.Op1, 2) and insn.Op2.is_reg(self.ireg_SR), self.itype_clrz, 0 ], - # bic #4, SR -> clrn - [ lambda: is_imm_op(insn.Op1, 4) and insn.Op2.is_reg(self.ireg_SR), self.itype_clrn, 0 ], - # bic #8, SR -> dint - [ lambda: is_imm_op(insn.Op1, 8) and insn.Op2.is_reg(self.ireg_SR), self.itype_dint, 0 ], - ], - self.itype_bis: [ - # bis #1, SR -> setc - [ lambda: is_imm_op(insn.Op1, 1) and insn.Op2.is_reg(self.ireg_SR), self.itype_setc, 0 ], - # bis #2, SR -> setz - [ lambda: is_imm_op(insn.Op1, 2) and insn.Op2.is_reg(self.ireg_SR), self.itype_setz, 0 ], - # bis #4, SR -> setn - [ lambda: is_imm_op(insn.Op1, 4) and insn.Op2.is_reg(self.ireg_SR), self.itype_setn, 0 ], - # bis #8, SR -> eint - [ lambda: is_imm_op(insn.Op1, 8) and insn.Op2.is_reg(self.ireg_SR), self.itype_eint, 0 ], - ], - self.itype_dadd: [ - # dadd #0, dst -> dadc dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_dadc, 2 ], - ], - self.itype_daddx: [ - # daddx #0, dst -> dadcx dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_dadcx, 2 ], - ], - self.itype_sub: [ - # sub #1, dst -> dec dst - [ lambda: is_imm_op(insn.Op1, 1), self.itype_dec, 2 ], - # sub #2, dst -> decd dst - [ lambda: is_imm_op(insn.Op1, 2), self.itype_decd, 2 ], - ], - self.itype_subx: [ - # subx #1, dst -> decx dst - [ lambda: is_imm_op(insn.Op1, 1), self.itype_decx, 2 ], - # subx #2, dst -> decdx dst - [ lambda: is_imm_op(insn.Op1, 2), self.itype_decdx, 2 ], - ], - self.itype_suba: [ - # suba #2, dst -> decda dst - [ lambda: is_imm_op(insn.Op1, 2), self.itype_decda, 2 ], - ], - self.itype_subc: [ - # subc #0, dst -> sbc dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_sbc, 2 ], - ], - self.itype_subcx: [ - # subcx #0, dst -> sbcx dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_sbcx, 2 ], - ], - self.itype_add: [ - # add #1, dst -> inc dst - [ lambda: is_imm_op(insn.Op1, 1), self.itype_inc, 2 ], - # add #2, dst -> incd dst - [ lambda: is_imm_op(insn.Op1, 2), self.itype_incd, 2 ], - # add dst, dst -> rla dst - [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rla, 1 ], - ], - self.itype_adda: [ - # adda #2, dst -> incda dst - [ lambda: is_imm_op(insn.Op1, 2), self.itype_incda, 2 ], - ], - self.itype_addx: [ - # addx #1, dst -> incx dst - [ lambda: is_imm_op(insn.Op1, 1), self.itype_incx, 2 ], - # addx #2, dst -> incdx dst - [ lambda: is_imm_op(insn.Op1, 2), self.itype_incdx, 2 ], - # addx dst, dst -> rlax dst - [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rlax, 1 ], - ], - self.itype_xor: [ - # xor #-1, dst -> inv dst - [ lambda: is_imm_op(insn.Op1, -1), self.itype_inv, 2 ], - ], - self.itype_xorx: [ - # xorx #-1, dst -> invx dst - [ lambda: is_imm_op(insn.Op1, -1), self.itype_invx, 2 ], - ], - self.itype_cmp: [ - # cmp #0, dst -> tst dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_tst, 2 ], - ], - self.itype_cmpx: [ - # cmpx #0, dst -> tstx dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_tstx, 2 ], - ], - self.itype_cmpa: [ - # cmpa #0, dst -> tsta dst - [ lambda: is_imm_op(insn.Op1, 0), self.itype_tsta, 2 ], - ], - } - - # instructions which should have no suffix - nosuff = [self.itype_ret, self.itype_reta, self.itype_br, self.itype_bra, - self.itype_clrc, self.itype_clrn, self.itype_clrz, self.itype_dint, - self.itype_eint, self.itype_clrc, self.itype_nop, self.itype_pop, - self.itype_popa, self.itype_setc, self.itype_setn, self.itype_setz, ] - - if insn.itype in maptbl: - for m in maptbl[insn.itype]: - if m[0](): - # matched instruction; replace the itype - insn.itype = m[1] - if m[2] == 0: - # remove the operands - insn.Op1.type = o_void - elif m[2] == 2: - # replace first operand with the second - insn.Op1.assign(insn.Op2) - # remove the second operand, if any - insn.Op2.type = o_void - # remove suffix if necessary - if insn.itype in nosuff and insn.auxpref == AUX_WORD: - insn.auxpref = 0 - break - - # ---------------------------------------------------------------------- - def ev_ana_insn(self, insn): - """ - Decodes an instruction into 'insn'. - Returns: insn.size (=the size of the decoded instruction) or zero - """ - if (insn.ea & 1) != 0: - return 0 - w = insn.get_next_word() - extw = None - if BITS(w, 15, 11) == 0b00011: - # operand extension word - extw = w - w = insn.get_next_word() - if BITS(w, 15, 10) == 0b000100: - self.decode_format_II(insn, w, extw) - elif BITS(w, 15, 10) == 0b000101: - if extw: return 0 - self.decode_430x_pushm(insn, w) - elif BITS(w, 15, 13) == 1: # 001 - if extw: return 0 - self.decode_jump(insn, w) - elif BITS(w, 15, 12) == 0: - if extw: return 0 - self.decode_430x_mova(insn, w) - else: - self.decode_format_I(insn, w, extw) - - self.simplify(insn) - return insn.itype != self.itype_null - - # ---------------------------------------------------------------------- - def init_instructions(self): - Instructions = [] - i = 0 - for x in self.instruc: - if x['name'] != '': - setattr(self, 'itype_' + x['name'], i) - else: - setattr(self, 'itype_null', i) - i += 1 - - # icode of the last instruction + 1 - self.instruc_end = len(self.instruc) - - # Icode of return instruction. It is ok to give any of possible return - # instructions - self.icode_return = self.itype_reti - - # ---------------------------------------------------------------------- - def init_registers(self): - """This function parses the register table and creates corresponding ireg_XXX constants""" - - # Registers definition - self.reg_names = [ - # General purpose registers - "PC", # R0 - "SP", # R1 - "SR", # R2, CG1 - "R3", # CG2 - "R4", - "R5", - "R6", - "R7", - "R8", - "R9", - "R10", - "R11", - "R12", - "R13", - "R14", - "R15", - # Fake segment registers - "CS", - "DS" - ] - - # Create the ireg_XXXX constants - for i in range(len(self.reg_names)): - setattr(self, 'ireg_' + self.reg_names[i], i) - - # Segment register information (use virtual CS and DS registers if your - # processor doesn't have segment registers): - self.reg_first_sreg = self.ireg_CS - self.reg_last_sreg = self.ireg_DS - - # number of CS register - self.reg_code_sreg = self.ireg_CS - - # number of DS register - self.reg_data_sreg = self.ireg_DS - - # ---------------------------------------------------------------------- - def __init__(self): - processor_t.__init__(self) - self.init_instructions() - self.init_registers() - -# ---------------------------------------------------------------------- -# Every processor module script must provide this function. -# It should return a new instance of a class derived from processor_t -def PROCESSOR_ENTRY(): - return msp430_processor_t() diff --git a/idasdk75/module/script/proctemplate.py b/idasdk75/module/script/proctemplate.py deleted file mode 100644 index 29dc5c6..0000000 --- a/idasdk75/module/script/proctemplate.py +++ /dev/null @@ -1,1063 +0,0 @@ -# ---------------------------------------------------------------------- -# Processor module template script -# (c) Hex-Rays -import sys -import idaapi -from idaapi import * -import ida_pro - -if sys.version_info.major < 3: - range = xrange - -retcode_0 = 0xC3 -retcode_1 = 0xC2 -g_retcodes = [retcode_0, retcode_1] - -# ---------------------------------------------------------------------- -class sample_processor_t(idaapi.processor_t): - """ - Processor module classes must derive from idaapi.processor_t - - A processor_t instance is, conceptually, both an IDP_Hooks and - an IDB_Hooks. This means any callback from those two classes - can be implemented. Below, you'll find a handful of those - as an example (e.g., ev_out_header(), ev_newfile(), ...) - Also note that some IDP_Hooks callbacks must be implemented - """ - - # IDP id ( Numbers above 0x8000 are reserved for the third-party modules) - id = 0x8000 + 1 - - # Processor features - flag = PR_ASSEMBLE | PR_SEGS | PR_DEFSEG32 | PR_USE32 | PRN_HEX | PR_RNAMESOK - - # Number of bits in a byte for code segments (usually 8) - # IDA supports values up to 32 bits - cnbits = 8 - - # Number of bits in a byte for non-code segments (usually 8) - # IDA supports values up to 32 bits - dnbits = 8 - - # short processor names - # Each name should be shorter than 9 characters - psnames = ['myproc'] - - # long processor names - # No restriction on name lengthes. - plnames = ['My processor module'] - - # register names - reg_names = [ - # General purpose registers - "SP", # aka R0 - "R1", - "R2", - "R3", - "R4", - "R5", - "R6", - "R7", - # VM registers - "FLAGS", # 0 - "IP", # 1 - "VM2", - "VM3", - "VM4", - "VM5", - "VM6", - "VM7", - # Fake segment registers - "CS", - "DS" - ] - - # number of registers (optional: deduced from the len(reg_names)) - regs_num = len(reg_names) - - # Segment register information (use virtual CS and DS registers if your - # processor doesn't have segment registers): - reg_first_sreg = 16 # index of CS - reg_last_sreg = 17 # index of DS - - # size of a segment register in bytes - segreg_size = 0 - - # You should define 2 virtual segment registers for CS and DS. - - # number of CS/DS registers - reg_code_sreg = 16 - reg_data_sreg = 17 - - # Array of typical code start sequences (optional) - codestart = ['\x55\x8B', '\x50\x51'] - - # Array of 'return' instruction opcodes (optional) - retcodes = g_retcodes - - # Array of instructions. Since this is only a template, - # this list will be extremely limited. - instruc = [ - {'name': 'ADD', 'feature': CF_USE1 | CF_CHG1 | CF_USE2}, # ADD <reg>, <#imm> -- opcodes [0x00 -> 0x7F] - {'name': 'MOV', 'feature': CF_USE1 | CF_CHG1 | CF_USE2}, # MOV <reg>, <reg> -- opcodes [0x80 -> 0xEF] (but retcodes) - {'name': 'RET', 'feature': 0}, # RET -- opcodes 0xC2, 0xC3 - {'name': 'JMP', 'feature': CF_USE1 | CF_JUMP}, # JMP -- opcodes [0xF0 -> 0xFF] - ] - - # icode of the first instruction - instruc_start = 0 - - # icode of the last instruction + 1 - instruc_end = len(instruc) - - # Size of long double (tbyte) for this processor (meaningful only if ash.a_tbyte != NULL) (optional) - tbyte_size = 0 - - # - # Number of digits in floating numbers after the decimal point. - # If an element of this array equals 0, then the corresponding - # floating point data is not used for the processor. - # This array is used to align numbers in the output. - # real_width[0] - number of digits for short floats (only PDP-11 has them) - # real_width[1] - number of digits for "float" - # real_width[2] - number of digits for "double" - # real_width[3] - number of digits for "long double" - # Example: IBM PC module has { 0,7,15,19 } - # - # (optional) - real_width = (0, 7, 15, 0) - - # icode (or instruction number) of return instruction. It is ok to give any of possible return - # instructions - icode_return = 5 - - # only one assembler is supported - assembler = { - # flag - 'flag' : ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, - - # user defined flags (local only for IDP) (optional) - 'uflag' : 0, - - # Assembler name (displayed in menus) - 'name': "My processor module bytecode assembler", - - # array of automatically generated header lines they appear at the start of disassembled text (optional) - 'header': ["Line1", "Line2"], - - # org directive - 'origin': "org", - - # end directive - 'end': "end", - - # comment string (see also cmnt2) - 'cmnt': ";", - - # ASCII string delimiter - 'ascsep': "\"", - - # ASCII char constant delimiter - 'accsep': "'", - - # ASCII special chars (they can't appear in character and ascii constants) - 'esccodes': "\"'", - - # - # Data representation (db,dw,...): - # - # ASCII string directive - 'a_ascii': "db", - - # byte directive - 'a_byte': "db", - - # word directive - 'a_word': "dw", - - # remove if not allowed - 'a_dword': "dd", - - # remove if not allowed - 'a_qword': "dq", - - # remove if not allowed - 'a_oword': "xmmword", - - # remove if not allowed - 'a_yword': "ymmword", - - # float; 4bytes; remove if not allowed - 'a_float': "dd", - - # double; 8bytes; NULL if not allowed - 'a_double': "dq", - - # long double; NULL if not allowed - 'a_tbyte': "dt", - - # packed decimal real; remove if not allowed (optional) - 'a_packreal': "", - - # array keyword. the following - # sequences may appear: - # #h - header - # #d - size - # #v - value - # #s(b,w,l,q,f,d,o) - size specifiers - # for byte,word, - # dword,qword, - # float,double,oword - 'a_dups': "#d dup(#v)", - - # uninitialized data directive (should include '%s' for the size of data) - 'a_bss': "%s dup ?", - - # 'equ' Used if AS_UNEQU is set (optional) - 'a_equ': ".equ", - - # 'seg ' prefix (example: push seg seg001) - 'a_seg': "seg", - - # current IP (instruction pointer) symbol in assembler - 'a_curip': "$", - - # "public" name keyword. NULL-gen default, ""-do not generate - 'a_public': "public", - - # "weak" name keyword. NULL-gen default, ""-do not generate - 'a_weak': "weak", - - # "extrn" name keyword - 'a_extrn': "extrn", - - # "comm" (communal variable) - 'a_comdef': "", - - # "align" keyword - 'a_align': "align", - - # Left and right braces used in complex expressions - 'lbrace': "(", - 'rbrace': ")", - - # % mod assembler time operation - 'a_mod': "%", - - # & bit and assembler time operation - 'a_band': "&", - - # | bit or assembler time operation - 'a_bor': "|", - - # ^ bit xor assembler time operation - 'a_xor': "^", - - # ~ bit not assembler time operation - 'a_bnot': "~", - - # << shift left assembler time operation - 'a_shl': "<<", - - # >> shift right assembler time operation - 'a_shr': ">>", - - # size of type (format string) (optional) - 'a_sizeof_fmt': "size %s", - - 'flag2': 0, - - # comment close string (optional) - # this is used to denote a string which closes comments, for example, if the comments are represented with (* ... *) - # then cmnt = "(*" and cmnt2 = "*)" - 'cmnt2': "", - - # low8 operation, should contain %s for the operand (optional fields) - 'low8': "", - 'high8': "", - 'low16': "", - 'high16': "", - - # the include directive (format string) (optional) - 'a_include_fmt': "include %s", - - # if a named item is a structure and displayed in the verbose (multiline) form then display the name - # as printf(a_strucname_fmt, typename) - # (for asms with type checking, e.g. tasm ideal) - # (optional) - 'a_vstruc_fmt': "", - - # 'rva' keyword for image based offsets (optional) - # (see nalt.hpp, REFINFO_RVA) - 'a_rva': "rva" - } # Assembler - - def regname2index(self, regname): - for idx in range(len(self.reg_names)): - if regname == self.reg_names[idx]: - return idx - return -1 - - - OPTION_KEY_OPERAND_SEPARATOR = "PROCTEMPLATE_OPERAND_SEPARATOR" - OPTION_KEY_OPERAND_SPACES = "PROCTEMPLATE_OPERAND_SPACES" - - - # ---------------------------------------------------------------------- - def __init__(self): - idaapi.processor_t.__init__(self) - self.operand_separator = ',' - self.operand_spaces = 1 - - def asm_out_func_header(self, ctx, func_ea): - """generate function header lines""" - pass - - def asm_out_func_footer(self, ctx, func_ea): - """generate function footer lines""" - pass - - def asm_get_type_name(self, flag, ea_or_id): - """ - Get name of type of item at ea or id. - (i.e. one of: byte,word,dword,near,far,etc...) - """ - if is_code(flag): - pfn = get_func(ea_or_id) - # return get func name - elif is_word(flag): - return "word" - return "" - - # - # IDP_Hooks callbacks (the first 4 are mandatory) - # - - def ev_emu_insn(self, insn): - """ - Emulate instruction, create cross-references, plan to analyze - subsequent instructions, modify flags etc. Upon entrance to this function - all information about the instruction is in 'insn' structure. - If zero is returned, the kernel will delete the instruction. - """ - if insn.itype == 4: # JMP - add_cref(insn.ea, insn.Op1.addr, fl_JN) - elif insn.itype != 2: # 2 == RET, 4 == JMP - add_cref(insn.ea, insn.ea + insn.size, fl_F) - return True - - def ev_out_operand(self, ctx, op): - """ - Generate text representation of an instructon operand. - This function shouldn't change the database, flags or anything else. - All these actions should be performed only by u_emu() function. - The output text is placed in the output buffer initialized with init_output_buffer() - This function uses out_...() functions from ua.hpp to generate the operand text - Returns: success - """ - if op.type == o_reg: - ctx.out_register(self.reg_names[op.reg]) - elif op.type == o_imm: - ctx.out_value(op, OOFW_IMM) - elif op.type == o_near: - ctx.out_name_expr(op, op.addr, BADADDR) - else: - return False - return True - - def ev_out_insn(self, ctx): - """ - Generate text representation of an instruction in 'ctx.insn' structure. - This function shouldn't change the database, flags or anything else. - All these actions should be performed only by u_emu() function. - Returns: nothing - """ - ctx.out_mnemonic() - - for i in range(0, 2): - op = ctx.insn[i] - if op.type == o_void: - break; - if i > 0: - ctx.out_symbol(self.operand_separator) - for _ in range(self.operand_spaces): - ctx.out_char(' ') - ctx.out_one_operand(i) - - ctx.set_gen_cmt() - ctx.flush_outbuf() - return True - - def ev_ana_insn(self, insn): - """ - Decodes an instruction into insn - Returns: insn.size (=the size of the decoded instruction) or zero - """ - b = insn.get_next_byte() - if b < 0x80: # ADD - insn.itype = 0 - insn.Op1.type = o_reg - insn.Op1.reg = b & 0xF - insn.Op2.type = o_imm - insn.Op2.dtype = dt_byte - insn.Op2.value = (b >> 4) & 0xF - elif b in g_retcodes: # RET - insn.itype = 2 - elif b < 0xF0: # MOV - insn.itype = 1 - insn.Op1.type = o_reg - insn.Op1.reg = b & 0xF - insn.Op2.type = o_reg - insn.Op2.value = (b >> 4) & 0xF - else: - insn.itype = 3 - insn.Op1.type = o_near - insn.Op1.dtype = dt_dword - insn.Op1.addr = insn.ea + (b & 0xF) - - return True - - # The following callbacks are optional. - # *** Please remove the callbacks that you don't plan to implement *** - - def ev_out_header(self, ctx): - """function to produce start of disassembled text""" - return 0 - - def ev_out_footer(self, ctx): - """function to produce end of disassembled text""" - return 0 - - def ev_out_segstart(self, ctx, segment): - """function to produce start of segment""" - return 0 - - def ev_out_segend(self, ctx, segment): - """function to produce end of segment""" - return 0 - - def ev_out_assumes(self, ctx): - """function to produce assume directives""" - return 0 - - def ev_term(self): - """called when the processor module is unloading""" - return 0 - - def ev_setup_til(self): - """Setup default type libraries (called after loading a new file into the database) - The processor module may load tils, setup memory model and perform other actions required to set up the type system - """ - return 0 - - def ev_newprc(self, nproc, keep_cfg): - """ - Before changing proccesor type - nproc - processor number in the array of processor names - return >=0-ok,<0-prohibit - """ - return 0 - - def ev_newfile(self, filename): - """A new file is loaded (already)""" - return 0 - - def ev_oldfile(self, filename): - """An old file is loaded (already)""" - return 0 - - def ev_newbinary(self, filename, fileoff, basepara, binoff, nbytes): - """ - Before loading a binary file - args: - filename - binary file name - fileoff - offset in the file - basepara - base loading paragraph - binoff - loader offset - nbytes - number of bytes to load - """ - return 0 - - def ev_undefine(self, ea): - """ - An item in the database (insn or data) is being deleted - @param args: ea - @return: >=0-ok, <0 - the kernel should stop - if the return value is not negative: - bit0 - ignored - bit1 - do not delete srareas at the item end - """ - return 0 - - def ev_endbinary(self, ok): - """ - After loading a binary file - args: - ok - file loaded successfully? - """ - return 0 - - def ev_assemble(self, ea, cs, ip, use32, line): - """ - Assemble an instruction - (make sure that PR_ASSEMBLE flag is set in the processor flags) - (display a warning if an error occurs) - args: - ea - linear address of instruction - cs - cs of instruction - ip - ip of instruction - use32 - is 32bit segment? - line - line to assemble - returns the opcode string, or None - """ - return 0 - - def ev_out_data(self, ctx, analyze_only): - """ - Generate text represenation of data items - This function MAY change the database and create cross-references, etc. - """ - ctx.out_data(analyze_only) - return 1 - - def ev_cmp_operands(self, op1, op2): - """ - Compare instruction operands. - Returns 1-equal, -1-not equal, 0-not implemented - """ - return 0 - - def ev_can_have_type(self, op): - """ - Can the operand have a type as offset, segment, decimal, etc. - (for example, a register AX can't have a type, meaning that the user can't - change its representation. see bytes.hpp for information about types and flags) - Returns: 0-unknown, <0-no, 1-yes - """ - return 0 - - def ev_set_idp_options(self, keyword, value_type, value, idb_loaded): - """ - Set IDP-specific option - args: - keyword - the option name - or empty string (check value_type when 0 below) - value_type - one of - IDPOPT_STR string constant - IDPOPT_NUM number - IDPOPT_BIT zero/one - IDPOPT_I64 64bit number - 0 -> You should display a dialog to configure the processor module - value - the actual value - idb_loaded - true if the ev_oldfile/ev_newfile events have been generated - Returns: - 1 ok - 0 not implemented - -1 error - """ - if keyword == self.OPTION_KEY_OPERAND_SEPARATOR and value_type == ida_idp.IDPOPT_STR: - self.operand_separator = value - return 1 - if keyword == self.OPTION_KEY_OPERAND_SPACES and value_type == ida_idp.IDPOPT_NUM: - self.operand_spaces = value - return 1 - else: - return -1 - - def ev_gen_map_file(self, nlines, qfile): - """ - Generate map file. If this function is absent then the kernel will create the map file. - This function returns number of lines in output file. - 0 - not implemented, 1 - ok, -1 - write error - """ - import ida_fpro - qfile = ida_fpro.qfile_t_from_fp(fp) - lines = ["Line 1\n", "Line 2\n!"] - ida_pro.int_pointer.frompointer(nlines).assign(len(lines)) - for l in lines: - qfile.write(l) - return 1 - - def ev_create_func_frame(self, pfn): - """ - Create a function frame for a newly created function. - Set up frame size, its attributes etc. - """ - return 0 - - def ev_is_far_jump(self, icode): - """ - Is indirect far jump or call instruction? - meaningful only if the processor has 'near' and 'far' reference types - """ - return 0 - - def ev_is_align_insn(self, ea): - """ - Is the instruction created only for alignment purposes? - Returns: number of bytes in the instruction - """ - return 0 - - def ev_out_special_item(self, ctx, segtype): - """ - Generate text representation of an item in a special segment - i.e. absolute symbols, externs, communal definitions etc. - Returns: 1-ok, 0-not implemented - """ - return 0 - - def ev_get_frame_retsize(self, frsize, pfn): - """ - Get size of function return address in bytes - If this function is absent, the kernel will assume - 4 bytes for 32-bit function - 2 bytes otherwise - """ - ida_pro.int_pointer.frompointer(frsize).assign(2) - return 1 - - def ev_is_switch(self, swi, insn): - """ - Find 'switch' idiom at instruction 'insn'. - Fills 'swi' structure with information - """ - return 0 - - def ev_is_sp_based(self, mode, insn, op): - """ - Check whether the operand is relative to stack pointer or frame pointer. - This function is used to determine how to output a stack variable - This function may be absent. If it is absent, then all operands - are sp based by default. - Define this function only if some stack references use frame pointer - instead of stack pointer. - returns flags: - OP_FP_BASED operand is FP based - OP_SP_BASED operand is SP based - OP_SP_ADD operand value is added to the pointer - OP_SP_SUB operand value is substracted from the pointer - """ - ida_pro.int_pointer.frompointer(mode).assign(idaapi.OP_FP_BASED) - return 1 - - def ev_get_autocmt(self, insn): - """ - Get instruction comment. 'insn' describes the instruction in question - @return: None or the comment string - """ - return "comment for %d" % insn.itype - - def ev_create_switch_xrefs(self, jumpea, swi): - """Create xrefs for a custom jump table - @param jumpea: address of the jump insn - @param swi: switch information - """ - return 0 - - def ev_calc_step_over(self, target, ip): - ida_pro.ea_pointer.frompointer(target).assign(idaapi.BADADDR) - return 1 - - def ev_may_be_func(self, insn, state): - """ - can a function start here? - the instruction is in 'insn' - arg: state -- autoanalysis phase - state == 0: creating functions - == 1: creating chunks - returns: probability 0..100 - """ - return 0 - - def ev_str2reg(self, regname): - """ - Convert a register name to a register number - args: regname - Returns: register number or -1 if not avail - The register number is the register index in the reg_names array - Most processor modules do not need to implement this callback - It is useful only if ph.reg_names[reg] does not provide - the correct register names - """ - r = self.regname2index(regname) - if r < 0: - return 0 - else: - return r + 1 - - def ev_is_sane_insn(self, insn, no_crefs): - """ - is the instruction sane for the current file type? - args: no_crefs - 1: the instruction has no code refs to it. - ida just tries to convert unexplored bytes - to an instruction (but there is no other - reason to convert them into an instruction) - 0: the instruction is created because - of some coderef, user request or another - weighty reason. - The instruction is in 'insn' - returns: >=0-ok, <0-no, the instruction isn't - likely to appear in the program - """ - return -1 - - def ev_func_bounds(self, code, func_ea, max_func_end_ea): - ida_pro.int_pointer.frompointer(code).assign(FIND_FUNC_OK) - return 1 - - def ev_init(self, idp_file): - return 0 - - def ev_out_label(self, ctx, label): - """ - The kernel is going to generate an instruction label line - or a function header. - args: - ctx - output context - label - label to output - If returns value <0, then the kernel should not generate the label - """ - return 0 - - def ev_rename(self, ea, new_name): - """ - The kernel is going to rename a byte - args: - ea - - new_name - - If returns value <0, then the kernel should not rename it - """ - return 0 - - def ev_may_show_sreg(self, ea): - """ - The kernel wants to display the segment registers - in the messages window. - args: - ea - if this function returns <0 - then the kernel will not show - the segment registers. - (assuming that the module have done it) - """ - return 0 - - def ev_coagulate(self, start_ea): - """ - Try to define some unexplored bytes - This notification will be called if the - kernel tried all possibilities and could - not find anything more useful than to - convert to array of bytes. - The module can help the kernel and convert - the bytes into something more useful. - args: - start_ea - - returns: number of converted bytes - """ - return 0 - - def ev_is_call_insn(self, insn): - """ - Is the instruction a "call"? - args - insn - instruction - returns: 0-unknown, <0-no, 1-yes - """ - return 0 - - def ev_is_ret_insn(self, insn, strict): - """ - Is the instruction a "return"? - insn - instruction - strict - 1: report only ret instructions - 0: include instructions like "leave" - which begins the function epilog - returns: 0-unknown, <0-no, 1-yes - """ - return 0 - - def ev_is_alloca_probe(self, ea): - """ - Does the function at 'ea' behave as __alloca_probe? - args: - ea - returns: 1-yes, 0-false - """ - return 0 - - def ev_gen_src_file_lnnum(self, ctx, filename, lnnum): - """ - Callback: generate analog of - #line "file.c" 123 - directive. - args: - ctx - output context - file - source file (may be NULL) - lnnum - line number - returns: 1-directive has been generated - """ - return 0 - - def ev_is_insn_table_jump(self, insn): - """ - Callback: determine if instruction is a table jump or call - If CF_JUMP bit cannot describe all kinds of table - jumps, please define this callback. - It will be called for insns with CF_JUMP bit set. - input: insn structure contains the current instruction - returns: 0-yes, <0-no - """ - return -1 - - def ev_is_indirect_jump(self, insn): - """ - Callback: determine if instruction is an indrect jump - If CF_JUMP bit cannot describe all jump types - jumps, please define this callback. - input: insn structure contains the current instruction - returns: 0-use CF_JUMP, 1-no, 2-yes - """ - return 0 - - def ev_validate_flirt_func(self, ea, funcname): - """ - flirt has recognized a library function - this callback can be used by a plugin or proc module - to intercept it and validate such a function - args: - start_ea - funcname - returns: -1-do not create a function, - 0-function is validated - """ - return 0 - - def ev_set_proc_options(self, options, confidence): - """ - called if the user specified an option string in the command line: - -p<processor name>:<options> - can be used for e.g. setting a processor subtype - also called if option string is passed to set_processor_type() - and IDC's set_processor_type() - args: - options - confidence - 0: loader's suggestion, - 1: user's decision - returns: <0 - bad option string - """ - return 0 - - def ev_creating_segm(self, s): - return 0 - - def ev_auto_queue_empty(self, atype): - return 0 - - def ev_gen_regvar_def(self, ctx, v): - return 0 - - def ev_is_basic_block_end(self, insn, call_insn_stops_block): - """ - Is the current instruction end of a basic block? - This function should be defined for processors - with delayed jump slots. The current instruction - is stored in 'insn' - args: - call_insn_stops_block - returns: 0-unknown, -1-no, 1-yes - """ - return 0 - - def ev_moving_segm(self, segment, to, flags): - """ - May the kernel move the segment? - returns: 0-yes, <0-the kernel should stop - """ - return 0 - - def ev_segm_moved(self, from_ea, to_ea, size, changed_netdelta): - """ - A segment is moved - """ - return 0 - - def ev_verify_noreturn(self, pfn): - """ - The kernel wants to set 'noreturn' flags for a function - Returns: 0-ok, <0-do not set 'noreturn' flag - """ - return 0 - - def ev_treat_hindering_item(self, hindering_item_ea, new_item_flags, new_item_ea, new_item_length): - """ - An item hinders creation of another item - args: - hindering_item_ea - new_item_flags - new_item_ea - new_item_length - Returns: 0-no reaction, <0-the kernel may delete the hindering item - """ - return 0 - - def ev_coagulate_dref(self, from_ea, to_ea, may_define, code_ea): - """ - data reference is being analyzed - args: - from_ea, to_ea, may_define, code_ea - plugin may correct code_ea (e.g. for thumb mode refs, we clear the last bit) - Returns: new code_ea or -1 - cancel dref analysis - """ - if False: # some condition - ida_pro.ea_pointer.frompointer(code_ea).assign(0x1337) - return 0 - - # - # IDB_Hooks callbacks - # - - def savebase(self): - """The database is being saved. Processor module should save its local data""" - return 0 - - def closebase(self): - """ - The database will be closed now - """ - return 0 - - def idasgn_loaded(self, short_sig_name): - """ - FLIRT signature have been loaded for normal processing - (not for recognition of startup sequences) - args: - short_sig_name - """ - return 0 - - def auto_empty(self): - """ - Info: all analysis queues are empty. - This callback is called once when the - initial analysis is finished. If the queue is - not empty upon the return from this callback, - it will be called later again - """ - return 0 - - def kernel_config_loaded(self): - """ - This callback is called when ida.cfg is parsed - """ - return 0 - - def auto_empty_finally(self): - """ - Info: all analysis queues are empty definitively - """ - return 0 - - def determined_main(self, main_ea): - """ - The main() function has been determined - """ - return 0 - - def sgr_changed(self, start_ea, end_ea, regnum, value, old_value, tag): - return 0 - - def compiler_changed(self): - return 0 - - def make_code(self, insn): - """ - An instruction is being created - args: - insn - returns: 0-ok, <0-the kernel should stop - """ - return 0 - - def make_data(self, ea, flags, tid, size): - """ - A data item is being created - args: - ea - flags - tid - size - returns: 0-ok, <0-the kernel should stop - """ - return 0 - - def notify_verify_sp(self, pfn): - """ - All function instructions have been analyzed - Now the processor module can analyze the stack pointer - for the whole function - Returns: 0-ok, <0-bad stack pointer - """ - return 0 - - def renamed(self, ea, new_name, is_local_name): - """ - The kernel has renamed a byte - args: - ea - new_name - is_local_name - Returns: nothing. See also the 'rename' event - """ - return 0 - - def set_func_start(self, pfn, new_ea): - """ - Function chunk start address will be changed - args: - pfn - new_ea - Returns: 0-ok,<0-do not change - """ - return 0 - - def set_func_end(self, pfn, new_end_ea): - """ - Function chunk end address will be changed - args: - pfn - new_end_ea - Returns: 0-ok,<0-do not change - """ - return 0 - - def func_added(self, pfn): - """ - The kernel has added a function. - @param pfn: function - """ - return 0 - - def deleting_func(self, pfn): - """ - The kernel is about to delete a function - @param func: function - """ - return 0 - - def translate(self, base, offset): - """ - Translation function for offsets - Currently used in the offset display functions - to calculate the referenced address - Returns: ea_t - """ - return BADADDR - -# ---------------------------------------------------------------------- -# Every processor module script must provide this function. -# It should return a new instance of a class derived from idaapi.processor_t -def PROCESSOR_ENTRY(): - return sample_processor_t() diff --git a/idasdk75/module/sparc/notify_codes.hpp b/idasdk75/module/sparc/notify_codes.hpp deleted file mode 100644 index 85b2dbe..0000000 --- a/idasdk75/module/sparc/notify_codes.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __SPARC_NOTIFY_CODES_HPP -#define __SPARC_NOTIFY_CODES_HPP - -#include <idp.hpp> - -//---------------------------------------------------------------------- -// The following events are supported by the SPARC module in the ph.notify() function -namespace sparc_module_t -{ - enum event_codes_t - { - ev_load_symbols = processor_t::ev_loader, - ev_set_v8, - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline void load_symbols(const char *fname) - { - processor_t::notify(idp_ev(ev_load_symbols), fname); - } - - inline void set_v8(bool is_v8) - { - processor_t::notify(idp_ev(ev_set_v8), is_v8); - } -} - -#endif // __SPARC_NOTIFY_CODES_HPP diff --git a/idasdk75/module/st20/ins.hpp b/idasdk75/module/st20/ins.hpp deleted file mode 100644 index c7dfb79..0000000 --- a/idasdk75/module/st20/ins.hpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ -ST20_null = 0, // Unknown Operation - -// C1 instructions - -ST20_adc, // add constant -ST20_add, // add -ST20_addc, // add with carry -ST20_ajw, // adjust work space -ST20_and, // and -ST20_arot, // anti-rotate stack -ST20_ashr, // arithmetic shift right -ST20_biquad, // biquad IIR filter step -ST20_bitld, // load bit -ST20_bitmask, // create bit mask -ST20_bitst, // store bit -ST20_breakpoint, // breakpoint -ST20_cj, // conditional jump -ST20_dequeue, // dequeue a process -ST20_divstep, // divide step -ST20_dup, // duplicate -ST20_ecall, // exception call -ST20_enqueue, // enqueue a process -ST20_eqc, // equals constant -ST20_eret, // exception return -ST20_fcall, // function call -ST20_gajw, // general adjust workspace -ST20_gt, // greater than -ST20_gtu, // greater than unsigned -ST20_io, // input/output -ST20_j, // jump -ST20_jab, // jump absolute -ST20_lbinc, // load byte and increment -ST20_ldc, // load constant -ST20_ldl, // load local -ST20_ldlp, // load local pointer -ST20_ldnl, // load non-local -ST20_ldnlp, // load non-local pointer -ST20_ldpi, // load pointer to instruction -ST20_ldprodid, // load product identity -ST20_ldtdesc, // load task descriptor -ST20_lsinc, // load sixteen and increment -ST20_lsxinc, // load sixteen sign extended and increment -ST20_lwinc, // load word and increment -ST20_mac, // multiply accumulate -ST20_mul, // multiply -ST20_nfix, // negative prefix -ST20_nop, // no operation -ST20_not, // bitwise not -ST20_opr, // operate -ST20_or, // or -ST20_order, // order -ST20_orderu, // unsigned order -ST20_pfix, // prefix -ST20_rev, // reverse -ST20_rmw, // read modify write -ST20_rot, // rotate stack -ST20_run, // run process -ST20_saturate, // saturate -ST20_sbinc, // store byte and increment -ST20_shl, // shift left -ST20_shr, // shift right -ST20_signal, // signal -ST20_smacinit, // initialize short multiply accumulate loop -ST20_smacloop, // short multiply accumulate loop -ST20_smul, // short multiply -ST20_ssinc, // store sixteen and increment -ST20_statusclr, // clear bits in status register -ST20_statusset, // set bits in status register -ST20_statustst, // test status register -ST20_stl, // store local -ST20_stnl, // store non-local -ST20_stop, // stop process -ST20_sub, // subtract -ST20_subc, // subtract with carry -ST20_swap32, // byte swap 32 -ST20_swinc, // store word and increment -ST20_timeslice, // timeslice -ST20_umac, // unsigned multiply accumulate -ST20_unsign, // unsign argument -ST20_wait, // wait -ST20_wsub, // word subscript -ST20_xbword, // sign extend byte to word -ST20_xor, // exclusive or -ST20_xsword, // sign extend sixteen to word - -// C2-C4 instructions - -ST20_alt, // alt start -ST20_altend, // alt end -ST20_altwt, // alt wait -ST20_bcnt, // byte count -ST20_bitcnt, // count bits set in word -ST20_bitrevnbits, // reverse bottom n bits in word -ST20_bitrevword, // reverse bits in word -ST20_bsub, // byte subscript -ST20_call, // call -ST20_causeerror, // cause error -ST20_cb, // check byte -ST20_cbu, // check byte unsigned -ST20_ccnt1, // check count from 1 -ST20_cflerr, // check floating point error -ST20_cir, // check in range -ST20_ciru, // check in range unsigned -ST20_clockdis, // clock disable -ST20_clockenb, // clock enable -ST20_clrhalterr, // clear halt-on error flag -ST20_crcbyte, // calculate CRC on byte -ST20_crcword, // calculate CRC on word -ST20_cs, // check sixteen -ST20_csngl, // check single -ST20_csu, // check sixteen unsigned -ST20_csub0, // check subscript from 0 -ST20_cword, // check word -ST20_devlb, // device load byte -ST20_devls, // device load sixteen -ST20_devlw, // device load word -ST20_devmove, // device move -ST20_devsb, // device store byte -ST20_devss, // device store sixteen -ST20_devsw, // device store word -ST20_diff, // difference -ST20_disc, // disable channel -ST20_diss, // disable skip -ST20_dist, // disable timer -ST20_div, // divide -ST20_enbc, // enable channel -ST20_enbs, // enable skip -ST20_enbt, // enable timer -ST20_endp, // end process -ST20_fmul, // fractional multiply -ST20_fptesterr, // test for FPU error -ST20_gcall, // general call -ST20_gintdis, // general interrupt disable -ST20_gintenb, // general interrupt enable -ST20_in, // input message -ST20_insertqueue, // insert at front of scheduler queue -ST20_intdis, // (localised) interrupt disable -ST20_intenb, // (localised) interrupt enable -ST20_iret, // interrupt return -ST20_ladd, // long add -ST20_lb, // load byte -ST20_lbx, // load byte and sign extend -ST20_ldclock, // load clock -ST20_lddevid, // load device identity -ST20_ldiff, // long diff -ST20_ldinf, // load infinity -ST20_ldiv, // long divide -ST20_ldmemstartval, // load value of MemStart address -ST20_ldpri, // load current priority -ST20_ldshadow, // load shadow registers -ST20_ldtimer, // load timer -ST20_ldtraph, // load trap handler -ST20_ldtrapped, // load trapped process status -ST20_lend, // loop end -ST20_lmul, // long multiply -ST20_ls, // load sixteen -ST20_lshl, // long shift left -ST20_lshr, // long shift right -ST20_lsub, // long subtract -ST20_lsum, // long sum -ST20_lsx, // load sixteen and sign extend -ST20_mint, // minimum integer -ST20_move, // move message -ST20_move2dall, // 2D block copy -ST20_move2dinit, // initialize data for 2D block move -ST20_move2dnonzero, // 2D block copy non-zero bytes -ST20_move2dzero, // 2D block copy zero bytes -ST20_norm, // normalize -ST20_out, // output message -ST20_outbyte, // output byte -ST20_outword, // output word -ST20_pop, // pop processor stack -ST20_postnormsn, // post-normalize correction of single length fp number -ST20_prod, // product -ST20_reboot, // reboot -ST20_rem, // remainder -ST20_resetch, // reset channel -ST20_restart, // restart -ST20_ret, // return -ST20_roundsn, // round single length floating point number -ST20_runp, // run process -ST20_satadd, // saturating add -ST20_satmul, // saturating multiply -ST20_satsub, // saturating subtract -ST20_saveh, // save high priority queue registers -ST20_savel, // save low priority queue registers -ST20_sb, // store byte -ST20_seterr, // set error flags -ST20_sethalterr, // set halt-on error flag -ST20_settimeslice, // set timeslicing status -ST20_slmul, // signed long multiply -ST20_ss, // store sixteen -ST20_ssub, // sixteen subscript -ST20_startp, // start process -ST20_stclock, // store clock register -ST20_sthb, // store high priority back pointer -ST20_sthf, // store high priority front pointer -ST20_stlb, // store low priority back pointer -ST20_stlf, // store low priority front pointer -ST20_stoperr, // stop on error -ST20_stopp, // stop process -ST20_stshadow, // store shadow registers -ST20_sttimer, // store timer -ST20_sttraph, // store trap handler -ST20_sttrapped, // store trapped process -ST20_sulmul, // signed timer unsigned long multiply -ST20_sum, // sum -ST20_swapqueue, // swap scheduler queue -ST20_swaptimer, // swap timer queue -ST20_talt, // timer alt start -ST20_taltwt, // timer alt wait -ST20_testerr, // test error flag -ST20_testhalterr, // test halt-on error flag -ST20_testpranal, // test processor analysing -ST20_tin, // timer input -ST20_trapdis, // trap disable -ST20_trapenb, // trap enable -ST20_tret, // trap return -ST20_unpacksn, // unpack single length fp number -ST20_wcnt, // word count -ST20_wsubdb, // form double word subscript -ST20_xdble, // extend to double -ST20_xword, // extend word - -ST20_last, - - }; - -#endif diff --git a/idasdk75/module/st20/makefile b/idasdk75/module/st20/makefile deleted file mode 100644 index bb2bd03..0000000 --- a/idasdk75/module/st20/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=st20 -CONFIGS=st20.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp st20.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - emu.cpp ins.hpp st20.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp st20.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp st20.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp reg.cpp st20.hpp diff --git a/idasdk75/module/st20/reg.cpp b/idasdk75/module/st20/reg.cpp deleted file mode 100644 index 9bea3ce..0000000 --- a/idasdk75/module/st20/reg.cpp +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2000 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "st20.hpp" -#include <diskio.hpp> - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "Areg", // Evaluation stack register A - "Breg", // Evaluation stack register B - "Creg", // Evaluation stack register C - "Iptr", // Instruction pointer register, pointing to the next instruction to be executed - "Status", // Status register - "Wptr", // Work space pointer, pointing to the stack of the currently executing process - "Tdesc", // Task descriptor - "IOreg", // Input and output register - "cs", "ds", -}; - -//-------------------------------------------------------------------------- -static const uchar ret0[] = { 0x23, 0x22 }; // eret -static const uchar ret1[] = { 0x24, 0xF5 }; // altend -static const uchar ret2[] = { 0x20, 0xF3 }; // endp -static const uchar ret3[] = { 0x61, 0xFF }; // iret -static const uchar ret4[] = { 0x68, 0xFD }; // reboot -static const uchar ret5[] = { 0x62, 0xFE }; // restart -static const uchar ret6[] = { 0x22, 0xF0 }; // ret -static const uchar ret7[] = { 0x60, 0xFB }; // tret - -static const bytes_t retcodes1[] = -{ - { qnumber(ret0), ret0, }, - { 0, NULL } -}; - -static const bytes_t retcodes4[] = -{ - { qnumber(ret1), ret1, }, - { qnumber(ret2), ret2, }, - { qnumber(ret3), ret3, }, - { qnumber(ret4), ret4, }, - { qnumber(ret5), ret5, }, - { qnumber(ret6), ret6, }, - { qnumber(ret7), ret7, }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Hypthetical assembler -//----------------------------------------------------------------------- -static const asm_t hypasm = -{ - ASH_HEXF0 // 1234h - |ASD_DECF0 // 1234 - |ASB_BINF0 // 1010b - |ASO_OCTF0 // 1234o - |AS_COLON // create colons after data names - |AS_ONEDUP, // one array definition per line - 0, - "Hypthetical assembler", - 0, - NULL, // header lines - "org", // org - "end", // end - - ";", // comment string - '\"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - "dd", // double words - "dq", // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - "public", // "public" name keyword - NULL, // "weak" name keyword - "extrn", // "extrn" name keyword - // .extern directive requires an explicit object size - NULL, // "comm" (communal variable) - NULL, // get_type_name - NULL, // "align" keyword - '(', ')', // lbrace, rbrace - "mod", // mod - "&", // and - "|", // or - "^", // xor - "not", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &hypasm, NULL }; - -//-------------------------------------------------------------------------- -static const char cfgname[] = "st20.cfg"; - -//-------------------------------------------------------------------------- -const char *st20_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - choose_ioport_device(&ioh.device, cfgname); - return IDPOPT_OK; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new st20_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list /*va*/) -{ - switch ( code ) - { - case idb_event::savebase: - case idb_event::closebase: - pm.helper.supset(0, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi st20_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ st20"); - break; - - case processor_t::ev_term: - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_ending_undo: - procnum = ph.get_proc_index(); - if ( isc4() ) - ph.retcodes = retcodes4; - //fall through - case processor_t::ev_oldfile: - helper.supstr(&ioh.device, 0); - break; - - case processor_t::ev_newprc: // new processor type - procnum = va_arg(va, int); - // bool keep_cfg = va_argi(va, bool); - if ( isc4() ) - ph.retcodes = retcodes4; - break; - - case processor_t::ev_is_jump_func: - { - const func_t *pfn = va_arg(va, const func_t *); - ea_t *jump_target = va_arg(va, ea_t *); - return is_jump_func(pfn, jump_target); - } - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - int no_crefs = va_arg(va, int); - return is_sane_insn(*insn, no_crefs) == 1 ? 1 : -1; - } - - case processor_t::ev_may_be_func: - { - const insn_t *insn = va_arg(va, insn_t *); - return may_be_func(*insn); - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st20_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st20_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - st20_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - st20_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return st20_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return st20_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "SGS-Thomson ST20:" -static const char *const shnames[] = { "st20", "st20c4", NULL }; -static const char *const lnames[] = -{ - FAMILY"SGS-Thomson ST20/C1", - "SGS-Thomson ST20/C2-C4", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_ST20, // id - // flag - PRN_HEX - | PR_RNAMESOK, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - cs, // first - ds, // last - 2, // size of a segment register - cs, ds, - - NULL, // No known code start sequences - retcodes1, - - ST20_null, - ST20_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - ST20_eret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/st20/st20.hpp b/idasdk75/module/st20/st20.hpp deleted file mode 100644 index c344e3e..0000000 --- a/idasdk75/module/st20/st20.hpp +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2000 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _ST20_HPP -#define _ST20_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -enum regnum_t -{ - Areg, // Evaluation stack register A - Breg, // Evaluation stack register B - Creg, // Evaluation stack register C - Iptr, // Instruction pointer register, pointing to the next instruction to be executed - Status, // Status register - Wptr, // Work space pointer, pointing to the stack of the currently executing process - Tdesc, // Task descriptor - IOreg, // Input and output register - cs, - ds, - -}; - -//------------------------------------------------------------------ -#define PROC_C1 0 -#define PROC_C4 1 - -//------------------------------------------------------------------ -struct st20_iohandler_t : public iohandler_t -{ - st20_iohandler_t(netnode &nn) : iohandler_t(nn) {} -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct st20_t); - -struct st20_t : public procmod_t -{ - netnode helper; - st20_iohandler_t ioh = st20_iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - int procnum; - bool flow; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *idaapi set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - int st20_ana(insn_t *insn); - - int st20_emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &x, bool isload); - - bool isc4(void) { return procnum == PROC_C4; } - - void st20_footer(outctx_t &ctx) const; -}; - -ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea -//------------------------------------------------------------------ -void idaapi st20_header(outctx_t &ctx); - -void idaapi st20_segstart(outctx_t &ctx, segment_t *seg); -void idaapi st20_segend(outctx_t &ctx, segment_t *seg); -void idaapi st20_assumes(outctx_t &ctx); // function to produce assume directives - -int idaapi is_align_insn(ea_t ea); - -int is_jump_func(const func_t *pfn, ea_t *jump_target); -int is_sane_insn(const insn_t &insn, int nocrefs); -int may_be_func(const insn_t &insn); // can a function start here? - -#endif // _ST20_HPP diff --git a/idasdk75/module/st7/ins.hpp b/idasdk75/module/st7/ins.hpp deleted file mode 100644 index 1a872be..0000000 --- a/idasdk75/module/st7/ins.hpp +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ -ST7_null = 0, // Unknown Operation - -ST7_adc, // Add with Carry -ST7_add, // Addition -ST7_and, // Logical And -ST7_bcp, // Bit compare -ST7_bres, // Bit Reset -ST7_bset, // Bit Set -ST7_btjf, // Jump if bit is false -ST7_btjt, // Jump if bit is true -ST7_call, // Call subroutine -ST7_callr, // Call subroutine relative -ST7_clr, // Clear -ST7_cp, // Arithmetic Compare -ST7_cpl, // One Complement -ST7_dec, // Decrement -ST7_halt, // Halt -ST7_iret, // Interrupt routine return -ST7_inc, // Increment -ST7_jp, // Absolute Jump -ST7_jra, // Jump relative always -ST7_jrt, // Jump relative -ST7_jrf, // Never jump -ST7_jrih, // Jump if Port INT pin = 1 -ST7_jril, // Jump if Port INT pin = 0 -ST7_jrh, // Jump if H = 1 -ST7_jrnh, // Jump if H = 0 -ST7_jrm, // Jump if I = 1 -ST7_jrnm, // Jump if I = 0 -ST7_jrmi, // Jump if N = 1 (minus) -ST7_jrpl, // Jump if N = 0 (plus) -ST7_jreq, // Jump if Z = 1 (equal) -ST7_jrne, // Jump if Z = 0 (not equal) -ST7_jrc, // Jump if C = 1 -ST7_jrnc, // Jump if C = 0 -ST7_jrult, // Jump if C = 1 -ST7_jruge, // Jump if C = 0 -ST7_jrugt, // Jump if (C + Z = 0) -ST7_jrule, // Jump if (C + Z = 1) -ST7_ld, // Load -ST7_mul, // Multiply -ST7_neg, // Negate -ST7_nop, // No Operation -ST7_or, // OR Operation -ST7_pop, // Pop from the Stack -ST7_push, // Push onto the Stack -ST7_rcf, // Reset carry flag -ST7_ret, // Subroutine Return -ST7_rim, // Enable Interrupts -ST7_rlc, // Rotate left true -ST7_rrc, // Rotate right true -ST7_rsp, // Reset Stack Pointer -ST7_sbc, // Subtract with Carry -ST7_scf, // Set carry flag -ST7_sim, // Disable Interrupts -ST7_sla, // Shift left Arithmetic -ST7_sll, // Shift left Logic -ST7_srl, // Shift right Logic -ST7_sra, // Shift right Arithmetic -ST7_sub, // Substraction -ST7_swap, // SWAP nibbles -ST7_tnz, // Test for Neg & Zero -ST7_trap, // S/W trap -ST7_wfi, // Wait for Interrupt -ST7_xor, // Exclusive OR - -ST7_last, - - }; - -#endif diff --git a/idasdk75/module/st7/makefile b/idasdk75/module/st7/makefile deleted file mode 100644 index ecd916a..0000000 --- a/idasdk75/module/st7/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=st7 -CONFIGS=st7.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp st7.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - emu.cpp ins.hpp st7.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp st7.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp st7.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp reg.cpp st7.hpp diff --git a/idasdk75/module/st7/reg.cpp b/idasdk75/module/st7/reg.cpp deleted file mode 100644 index 42434bc..0000000 --- a/idasdk75/module/st7/reg.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2000 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "st7.hpp" -#include <diskio.hpp> - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "a", "x", "y", "cc", "s", - "ds", "cs", -}; - -//-------------------------------------------------------------------------- -static const uchar retcode0[] = { 0x80 }; // iret 80 -static const uchar retcode1[] = { 0x81 }; // ret 81 -static const bytes_t retcodes[] = -{ - { sizeof(retcode0), retcode0 }, - { sizeof(retcode1), retcode1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// STMicroelectronics - Assembler - rel. 4.10 -// We support Motorola format -//----------------------------------------------------------------------- -static const char *const st7_headers[] = -{ - "st7/", - "", - NULL -}; - -static const asm_t stasm = -{ - ASH_HEXF4 // $1234 - |ASD_DECF0 // 1234 - |ASB_BINF2 // %1010 - |ASO_OCTF6 // ~1234 - |AS_NOXRF // Disable xrefs during the output file generation - |AS_ONEDUP, // one array definition per line - 0, - "STMicroelectronics - Assembler", - 0, - st7_headers, // header lines - "org", // org - "end", // end - - ";", // comment string - '\"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - "dc.b", // ascii string directive - "dc.b", // byte directive - "dc.w", // word directive - "dc.l", // double words - NULL, // qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "skip#s( )#d, #v", // arrays (#h,#d,#v,#s(...) ONLY BYTE ARRAYS!!! - "ds.b %s", // uninited arrays - "equ", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "*", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - "public", // "public" name keyword - NULL, // "weak" name keyword - "extern", // "extrn" name keyword - // .extern directive requires an explicit object size - NULL, // "comm" (communal variable) - NULL, // get_type_name - NULL, // "align" keyword - '{', '}', // lbrace, rbrace - NULL, // mod - "and", // and - "or", // or - "xor", // xor - NULL, // not - "shl", // shl - "shr", // shr - NULL, // sizeof - AS2_BRACE, -}; - -static const asm_t *const asms[] = { &stasm, NULL }; - -//-------------------------------------------------------------------------- -//static const char cfgname[] = "st7.cfg"; - -//---------------------------------------------------------------------- -const ioport_t *st7_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port; -} - -//---------------------------------------------------------------------- -void st7_t::create_words(void) -{ - for ( int i=0; i < ioh.ports.size(); i++ ) - { - ea_t ea = ioh.ports[i].address; - if ( is_tail(get_flags(ea)) ) - del_items(ea, DELIT_SIMPLE); - create_word(ea, 2); - } -} - -//-------------------------------------------------------------------------- -const char *st7_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( choose_ioport_device(&ioh.device, cfgfile) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT); - return IDPOPT_OK; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new st7_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi st7_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - helper.create("$ st7"); - inf_set_be(true); - break; - - case processor_t::ev_newfile: // new file loaded - { - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( choose_ioport_device(&ioh.device, cfgfile) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - create_words(); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: // old file loaded - ioh.restore_device(); - break; - - case processor_t::ev_is_jump_func: - { - const func_t *pfn = va_arg(va, const func_t *); - ea_t *jump_target = va_arg(va, ea_t *); - return is_jump_func(pfn, jump_target); - } - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, insn_t *); - int no_crefs = va_arg(va, int); - return is_sane_insn(*insn, no_crefs) == 1 ? 1 : -1; - } - - case processor_t::ev_may_be_func: - { - const insn_t *insn = va_arg(va, insn_t *); - return may_be_func(*insn); - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st7_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st7_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - st7_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - st7_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return st7_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return st7_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "SGS-Thomson ST7:" -static const char *const shnames[] = { "st7", NULL }; -static const char *const lnames[] = -{ - FAMILY"SGS-Thomson ST7", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_ST7, // id - // flag - PRN_HEX - | PR_RNAMESOK, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - ds, // first - cs, // last - 2, // size of a segment register - cs, ds, - - NULL, // No known code start sequences - retcodes, - - ST7_null, - ST7_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - ST7_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/st7/st7.hpp b/idasdk75/module/st7/st7.hpp deleted file mode 100644 index 4e9b682..0000000 --- a/idasdk75/module/st7/st7.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2000 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _ST7_HPP -#define _ST7_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -// o_void Inherent nop -// o_imm Immediate ld A,#$55 -// o_mem Direct ld A,$55 -// o_displ Indexed ld A,($55,X) -// o_mem Indirect ld A,([$55],X) -// o_near Relative jrne loop -// o_mem Bit operation bset byte,#5 - -// type Mode Syntax Destination Ptradr PtrSz Len -// ------- --------------------------- ------------------------ ---------- ------ ---- --- -// o_void Inherent nop + 0 -// o_imm Immediate ld A,#$55 + 1 -// o_mem Short Direct ld A,$10 00..FF + 1 -// o_mem Long Direct ld A,$1000 0000..FFFF + 2 -// o_phras No Offset Direct Indexed ld A,(X) 00..FF + 0 -// o_displ Short Direct Indexed ld A,($10,X) 00..1FE + 1 -// o_displ Long Direct Indexed ld A,($1000,X) 0000..FFFF + 2 -// o_mem Short Indirect ld A,[$10] 00..FF 00..FF byte + 2 -// o_mem Long Indirect ld A,[$10.w] 0000..FFFF 00..FF word + 2 -// o_mem Short Indirect Indexed ld A,([$10],X) 00..1FE 00..FF byte + 2 -// o_mem Long Indirect Indexed ld A,([$10.w],X) 0000..FFFF 00..FF word + 2 -// o_near Relative Direct jrne loop PC+/-127 + 1 -// o_mem Relative Indirect jrne [$10] PC+/-127 00..FF byte + 2 -// o_mem Bit Direct bset $10,#7 00..FF + 1 -// o_mem Bit Indirect bset [$10],#7 00..FF 00..FF byte + 2 -// o_mem Bit Direct Relative btjt $10,#7,skip 00..FF + 2 -// o_mem Bit Indirect Relative btjt [$10],#7,skip 00..FF 00..FF byte + 3 - -#define aux_long 0x0001 // long addressing mode -#define aux_indir 0x0002 // o_mem: indirect addressing mode -#define aux_index 0x0004 // o_mem: indexed addressing mode -#define aux_16 0x0008 // 16bit displacement - -//------------------------------------------------------------------ -#ifdef _MSC_VER -#define ENUM8BIT : uint8 -#else -#define ENUM8BIT -#endif -enum regnum_t ENUM8BIT -{ - A, X, Y, CC, S, - ds, cs, -}; - -//------------------------------------------------------------------ -struct st7_iohandler_t : public iohandler_t -{ - st7_iohandler_t(netnode &nn) : iohandler_t(nn) {} -}; - -struct st7_t : public procmod_t -{ - netnode helper; - st7_iohandler_t ioh = st7_iohandler_t(helper); - - bool flow; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const ioport_t *find_sym(ea_t address); - void create_words(void); - const char *idaapi set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - int st7_emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &x, bool isload); - - void st7_footer(outctx_t &ctx) const; -}; - -//------------------------------------------------------------------ -ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea - -//------------------------------------------------------------------ -void idaapi st7_header(outctx_t &ctx); - -void idaapi st7_segstart(outctx_t &ctx, segment_t *seg); -void idaapi st7_segend(outctx_t &ctx, segment_t *seg); -void idaapi st7_assumes(outctx_t &ctx); // function to produce assume directives - -int idaapi st7_ana(insn_t *insn); - -int idaapi is_align_insn(ea_t ea); - -int is_jump_func(const func_t *pfn, ea_t *jump_target); -int is_sane_insn(const insn_t &insn, int nocrefs); -int may_be_func(const insn_t &insn); // can a function start here? - -#endif // _ST7_HPP diff --git a/idasdk75/module/st9/ana.cpp b/idasdk75/module/st9/ana.cpp deleted file mode 100644 index cdec190..0000000 --- a/idasdk75/module/st9/ana.cpp +++ /dev/null @@ -1,1796 +0,0 @@ - -#include "st9.hpp" - -enum st9_addressing_modes ENUM_SIZE(uint16) -{ - A_IMPL, // implied - A_wrd_wrs, // rd,rs - A_wrd_wrsi, // rd,(rs) - A_wrdi_wrs, // (rd),rs - A_wrdi_grs, // (rd),Rs - A_grd_wrsi, // Rd,(rs) - A_grd_grs, // Rd,Rs - A_grs_grd, // Rs,Rd - A_grd_8q, // Rd,#N - A_grpd_grps, // RRd,RRs - A_grpd_16q_0, // RRd,#NN with first byte mask xxxxxxx0 - A_grpd_16q_1, // RRd,#NN with first byte mask xxxxxxx1 - A_grp_8q, // RR,#N - A_grs, // Rs - A_grsi, // (Rs) - A_grd, // Rd - A_grdi, // (Rd) - A_grp_0, // RR with first byte mask xxxxxxx0 - A_grp_1, // RR with first byte mask xxxxxxx1 - A_grpi, // (RR) - A_8q, // N - A_16q, // NN - A_grps, // RRs - A_grpd_0, // RRd with first byte mask xxxxxxx0 - A_grpd_1, // RRd with first byte mask xxxxxxx1 - A_grpdi, // (RRd) - A_wrpd_wrps, // rrd,rrs - A_wrpdi_wrps, // (rrd),rrs - A_wrpd_wrpsi, // rrd,(rrs) - A_wrpdi_wrpsi, // (rrd),(rrs) - - A_wrpdip_wrpsip_00, // (rrd)+,(rrs)+ with first byte mask xxx0xxx0 - A_wrpdip_wrpsip_10, // (rrd)+,(rrs)+ with first byte mask xxx1xxx0 - A_wrpdip_wrpsip_01, // (rrd)+,(rrs)+ with first byte mask xxx0xxx1 - A_wrpdip_wrpsip_11, // (rrd)+,(rrs)+ with first byte mask xxx1xxx1 - - A_wrpd_wrs, // rrd,rs - A_8qxwrp_16q, // Nd(rr),#NNs - A_16qxwrp_16q, // NNd(rr),#NNs - A_8qxwrp_gr, // N(rr),R - A_16qxwrp_gr, // NN(rr),R - A_16q_8q, // NNd,#Ns - A_16q_16q, // NNd,#NNs - A_wr_wrpxwrp, // rd,rrs(rrx) - A_wrpxwrp_wr, // rrd(rrx),rs - A_wrp_wrpxwrp, // rrd,rrs(rrx) - A_wrpxwrp_wrp, // rrd(rrx),rrs - - A_gr_wrpi, // Rd,(rrs) - A_wrip_gr, // (rrd),Rs - A_grpi_wrip, // (RRd),(rrs) - A_gri_wrip_01, // (R),(rr) with first byte mask 0100xxxx - A_gri_wrip_11, // (R),(rr) with first byte mask 1100xxxx - A_gr_8qxwrp, // Rd,N(rrx) - A_gr_16qxwrp, // Rd,NN(rrx) - A_grp_wrpi, // RRd,(rrs) - - A_8qxwrp_grp, // N(rrx),RRs - A_grp_8qxwrp, // RRs,N(rrx) - A_16qxwrp_grp, // NN(rrx),RRs - A_grp_16qxwrp, // RRs,NN(rrx) - - A_8qxgrpi, // N(RRx) - A_16qxgrpi, // NN(RRx) - - A_wrd_wrpsi_8q_0, // rd,(rrs),N with first byte mask xxx0xxxx - A_wrd_wrpsi_8q_1, // rd,(rrs),N with first byte mask xxx1xxxx - - A_grpd_wrsi, // RRd,(rs) - - A_8qxwr_wrs, // N(rx),rs - A_wrs_8qxwr, // rs,N(rx) - A_grd_wrpip, // Rd,(rrs)+ - A_wrpip_grd, // (rrs)+,Rd - A_wrd_wrpi, // rd,(rrs) - A_wrpi_wrd, // (rrs),rd - - A_wrpi_grp, // (rr),RR - A_wrpi_16q, // (rr),#NN - - A_grd_wrpim, // Rd,-(rrs) - A_wrpim_grd, // -(rrs),Rd - A_grpd_wrpim, // RRd,-(rrs) - A_wrpim_grpd, // -(rrs),RRd - A_16q_wrs, // NN,rs - A_wrd_16q, // rd,NN - - A_grpd_wrpip, // RRd,(rrs)+ - A_wrpip_grpd, // (rrd)+,RRs - - A_wrip_wrpip, // (rd)+,(rrs)+ - A_wrpip_wrip, // (rrs)+,(rd)+ - - A_8qxwrip_wrp, // N(rx),rrs - A_wrp_8qxwrip, // rrd,N(rx) - - A_wrp_16q, // rrd,NN - A_16q_wrp, // NN,rrs - - A_wrp_wrp_grp, // rrh,rrl,RRs - A_wrdi_grp, // (rd),RRs - A_wrpi_8q, // (rrd),#N - - A_wrb_wrb_10, // rd.b,rs.b with first word mask xxx1xxxx xxx0xxxx - A_wrb_wrb_11, // rd.b,rs.b with first word mask xxx1xxxx xxx1xxxx - A_wrb_nwrb_10, // rd.b,!rs.b with first word mask xxx1xxxx xxx0xxxx - A_wrb_nwrb_11, // rd.b,!rs.b with first word mask xxx1xxxx xxx1xxxx - A_wrb, // rd.b - A_wrbi, // (rr).bd - A_bwr_8q_0, // b.rd,N with first byte mask xxx0xxxx - A_bwr_8q_1, // b.rd,N with first byte mask xxx1xxxx - - A_seg_16q_01, // nnnnnn,NN with first byte mask 01xxxxxx - A_seg_16q_11, // nnnnnn,NN with first byte mask 11xxxxxx - - A_rwn_000, // wwwww with first byte mask xxxxx000 - A_rwn_100, // wwwww with first byte mask xxxxx100 - A_rwn_101, // wwwww with first byte mask xxxxx101 - A_rpn, // pppppp -}; - -struct opcode -{ - uint16 code; // opcode - uint16 insn; // insn mnemonic - uint16 addr; // addressing mode -}; - -static const opcode opcodes[] = -{ - { 0x00, st9_ei, A_IMPL }, - { 0x01, st9_scf, A_IMPL }, - { 0x02, st9_or, A_wrd_wrs }, - { 0x03, st9_or, A_wrd_wrsi }, - { 0x04, st9_or, A_grd_grs }, - { 0x05, st9_or, A_grd_8q }, - { 0x06, st9_aldw, A_8qxwrp_16q }, - { 0x06, st9_aldw, A_16qxwrp_16q }, - { 0x07, st9_orw, A_grpd_grps }, - { 0x07, st9_orw, A_grpd_16q_1 }, - { 0x08, st9_ld, A_grs }, - { 0x09, st9_ld, A_grd }, - { 0x0A, st9_djnz, A_8q }, - { 0x0B, st9_jrcc, A_8q }, - { 0x0C, st9_ld, A_8q }, - { 0x0D, st9_jpcc, A_16q }, - { 0x0E, st9_orw, A_wrpd_wrps }, - { 0x0E, st9_orw, A_wrpdi_wrps }, - { 0x0E, st9_orw, A_wrpd_wrpsi }, - { 0x0E, st9_orw, A_wrpdi_wrpsi }, - { 0x0F, st9_bor, A_wrb_wrb_10 }, - { 0x0F, st9_bor, A_wrb_nwrb_11 }, - { 0x0F, st9_bset, A_wrb }, - { 0x10, st9_di, A_IMPL }, - { 0x11, st9_rcf, A_IMPL }, - { 0x12, st9_and, A_wrd_wrs }, - { 0x13, st9_and, A_wrd_wrsi }, - { 0x14, st9_and, A_grd_grs }, - { 0x15, st9_and, A_grd_8q }, - { 0x16, st9_xch, A_grs_grd }, - { 0x17, st9_andw, A_grpd_grps }, - { 0x17, st9_andw, A_grpd_16q_1 }, - { 0x18, st9_ld, A_grs }, - { 0x19, st9_ld, A_grd }, - { 0x1A, st9_djnz, A_8q }, - { 0x1B, st9_jrcc, A_8q }, - { 0x1C, st9_ld, A_8q }, - { 0x1D, st9_jpcc, A_16q }, - { 0x1E, st9_andw, A_wrpd_wrps }, - { 0x1E, st9_andw, A_wrpdi_wrps }, - { 0x1E, st9_andw, A_wrpd_wrpsi }, - { 0x1E, st9_andw, A_wrpdi_wrpsi }, - { 0x1F, st9_band, A_wrb_wrb_11 }, - { 0x1F, st9_band, A_wrb_nwrb_10 }, - { 0x1F, st9_bres, A_wrb }, - { 0x20, st9_popu, A_grd }, - { 0x21, st9_popu, A_grdi }, - { 0x22, st9_sbc, A_wrd_wrs }, - { 0x23, st9_sbc, A_wrd_wrsi }, - { 0x24, st9_sbc, A_grd_grs }, - { 0x25, st9_sbc, A_grd_8q }, - { 0x26, st9_ald, A_8qxwrp_gr }, - { 0x26, st9_ald, A_16qxwrp_gr }, - { 0x27, st9_sbcw, A_grpd_grps }, - { 0x27, st9_sbcw, A_grpd_16q_1 }, - { 0x28, st9_ld, A_grs }, - { 0x29, st9_ld, A_grd }, - { 0x2A, st9_djnz, A_8q }, - { 0x2B, st9_jrcc, A_8q }, - { 0x2C, st9_ld, A_8q }, - { 0x2D, st9_jpcc, A_16q }, - { 0x2E, st9_sbcw, A_wrpd_wrps }, - { 0x2E, st9_sbcw, A_wrpdi_wrps }, - { 0x2E, st9_sbcw, A_wrpd_wrpsi }, - { 0x2E, st9_sbcw, A_wrpdi_wrpsi }, - { 0x2F, st9_sraw, A_grp_0 }, - { 0x2F, st9_ald, A_16q_8q }, - { 0x30, st9_pushu, A_grd }, - { 0x31, st9_pushu, A_grdi }, - { 0x32, st9_adc, A_wrd_wrs }, - { 0x33, st9_adc, A_wrd_wrsi }, - { 0x34, st9_adc, A_grd_grs }, - { 0x35, st9_adc, A_grd_8q }, - { 0x36, st9_rrcw, A_grp_0 }, - { 0x36, st9_aldw, A_16q_16q }, - { 0x37, st9_adcw, A_grpd_grps }, - { 0x37, st9_adcw, A_grpd_16q_1 }, - { 0x38, st9_ld, A_grs }, - { 0x39, st9_ld, A_grd }, - { 0x3A, st9_djnz, A_8q }, - { 0x3B, st9_jrcc, A_8q }, - { 0x3C, st9_ld, A_8q }, - { 0x3D, st9_jpcc, A_16q }, - { 0x3E, st9_adcw, A_wrpd_wrps }, - { 0x3E, st9_adcw, A_wrpdi_wrps }, - { 0x3E, st9_adcw, A_wrpd_wrpsi }, - { 0x3E, st9_adcw, A_wrpdi_wrpsi }, - { 0x3F, st9_calls, A_seg_16q_01 }, - { 0x3F, st9_jps, A_seg_16q_11 }, - { 0x40, st9_dec, A_grd }, - { 0x41, st9_dec, A_grdi }, - { 0x42, st9_add, A_wrd_wrs }, - { 0x43, st9_add, A_wrd_wrsi }, - { 0x44, st9_add, A_grd_grs }, - { 0x45, st9_add, A_grd_8q }, - { 0x46, st9_ret, A_IMPL }, - { 0x47, st9_addw, A_grpd_grps }, - { 0x47, st9_addw, A_grpd_16q_1 }, - { 0x48, st9_ld, A_grs }, - { 0x49, st9_ld, A_grd }, - { 0x4A, st9_djnz, A_8q }, - { 0x4B, st9_jrcc, A_8q }, - { 0x4C, st9_ld, A_8q }, - { 0x4D, st9_jpcc, A_16q }, - { 0x4E, st9_addw, A_wrpd_wrps }, - { 0x4E, st9_addw, A_wrpdi_wrps }, - { 0x4E, st9_addw, A_wrpd_wrpsi }, - { 0x4E, st9_addw, A_wrpdi_wrpsi }, - { 0x4F, st9_mul, A_wrpd_wrs }, - { 0x50, st9_inc, A_grd }, - { 0x51, st9_inc, A_grdi }, - { 0x52, st9_sub, A_wrd_wrs }, - { 0x53, st9_sub, A_wrd_wrsi }, - { 0x54, st9_sub, A_grd_grs }, - { 0x55, st9_sub, A_grd_8q }, - { 0x56, st9_divws, A_wrp_wrp_grp }, - { 0x57, st9_subw, A_grpd_grps }, - { 0x57, st9_subw, A_grpd_16q_1 }, - { 0x58, st9_ld, A_grs }, - { 0x59, st9_ld, A_grd }, - { 0x5A, st9_djnz, A_8q }, - { 0x5B, st9_jrcc, A_8q }, - { 0x5C, st9_ld, A_8q }, - { 0x5D, st9_jpcc, A_16q }, - { 0x5E, st9_subw, A_wrpd_wrps }, - { 0x5E, st9_subw, A_wrpdi_wrps }, - { 0x5E, st9_subw, A_wrpd_wrpsi }, - { 0x5E, st9_subw, A_wrpdi_wrpsi }, - { 0x5F, st9_div, A_wrpd_wrs }, - { 0x60, st9_ald, A_wr_wrpxwrp }, - { 0x60, st9_ald, A_wrpxwrp_wr }, - { 0x60, st9_aldw, A_wrp_wrpxwrp }, - { 0x60, st9_aldw, A_wrpxwrp_wrp }, - { 0x61, st9_ccf, A_IMPL }, - { 0x62, st9_xor, A_wrd_wrs }, - { 0x63, st9_xor, A_wrd_wrsi }, - { 0x64, st9_xor, A_grd_grs }, - { 0x65, st9_xor, A_grd_8q }, - { 0x66, st9_push, A_grd }, - { 0x67, st9_xorw, A_grpd_grps }, - { 0x67, st9_xorw, A_grpd_16q_1 }, - { 0x68, st9_ld, A_grs }, - { 0x69, st9_ld, A_grd }, - { 0x6A, st9_djnz, A_8q }, - { 0x6B, st9_jrcc, A_8q }, - { 0x6C, st9_ld, A_8q }, - { 0x6D, st9_jpcc, A_16q }, - { 0x6E, st9_xorw, A_wrpd_wrps }, - { 0x6E, st9_xorw, A_wrpdi_wrps }, - { 0x6E, st9_xorw, A_wrpd_wrpsi }, - { 0x6E, st9_xorw, A_wrpdi_wrpsi }, - { 0x6F, st9_bxor, A_wrb_wrb_10 }, - { 0x6F, st9_bxor, A_wrb_nwrb_11 }, - { 0x6F, st9_bcpl, A_wrb }, - { 0x70, st9_da, A_grd }, - { 0x71, st9_da, A_grdi }, - { 0x72, st9_ald, A_gr_wrpi }, - { 0x72, st9_ald, A_wrip_gr }, - { 0x73, st9_calls, A_gri_wrip_01 }, - { 0x73, st9_jps, A_gri_wrip_11 }, - { 0x73, st9_ald, A_grpi_wrip }, - { 0x74, st9_call, A_grpdi }, - { 0x74, st9_pushw, A_grps }, - { 0x75, st9_popw, A_grpd_0 }, - { 0x75, st9_unlink, A_grpd_1 }, - { 0x76, st9_pop, A_grd }, - { 0x77, st9_pop, A_grdi }, - { 0x78, st9_ld, A_grs }, - { 0x79, st9_ld, A_grd }, - { 0x7A, st9_djnz, A_8q }, - { 0x7B, st9_jrcc, A_8q }, - { 0x7C, st9_ld, A_8q }, - { 0x7D, st9_jpcc, A_16q }, - { 0x7E, st9_aldw, A_grp_wrpi }, - { 0x7F, st9_ald, A_gr_8qxwrp }, - { 0x7F, st9_ald, A_gr_16qxwrp }, - { 0x80, st9_cpl, A_grd }, - { 0x81, st9_cpl, A_grdi }, - { 0x82, st9_cp, A_wrd_wrs }, - { 0x83, st9_cp, A_wrd_wrsi }, - { 0x84, st9_cp, A_grd_grs }, - { 0x85, st9_cp, A_grd_8q }, - { 0x86, st9_aldw, A_8qxwrp_grp }, - { 0x86, st9_aldw, A_grp_8qxwrp }, - { 0x86, st9_aldw, A_16qxwrp_grp }, - { 0x86, st9_aldw, A_grp_16qxwrp }, - { 0x87, st9_cpw, A_grpd_grps }, - { 0x87, st9_cpw, A_grpd_16q_1 }, - { 0x88, st9_ld, A_grs }, - { 0x89, st9_ld, A_grd }, - { 0x8A, st9_djnz, A_8q }, - { 0x8B, st9_jrcc, A_8q }, - { 0x8C, st9_ld, A_8q }, - { 0x8D, st9_jpcc, A_16q }, - { 0x8E, st9_cpw, A_wrpd_wrps }, - { 0x8E, st9_cpw, A_wrpdi_wrps }, - { 0x8E, st9_cpw, A_wrpd_wrpsi }, - { 0x8E, st9_cpw, A_wrpdi_wrpsi }, - { 0x8FF1, st9_push, A_8q }, - { 0x8FF3, st9_pushu, A_8q }, - { 0x8FC1, st9_pushw, A_16q }, - { 0x8FC3, st9_pushuw, A_16q }, - { 0x8F01, st9_pea, A_8qxgrpi }, - { 0x8F01, st9_pea, A_16qxgrpi }, - { 0x8F03, st9_peau, A_8qxgrpi }, - { 0x8F03, st9_peau, A_16qxgrpi }, - { 0x8F, st9_rlcw, A_grpd_0 }, - { 0x90, st9_clr, A_grd }, - { 0x91, st9_clr, A_grdi }, - { 0x92, st9_cp, A_wrd_wrs }, - { 0x93, st9_cp, A_wrd_wrsi }, - { 0x94, st9_cp, A_grd_grs }, - { 0x95, st9_cp, A_grd_8q }, - { 0x96, st9_aldw, A_wrdi_grp }, - { 0x97, st9_cpw, A_grpd_grps }, - { 0x97, st9_cpw, A_grpd_16q_1 }, - { 0x98, st9_ld, A_grs }, - { 0x99, st9_ld, A_grd }, - { 0x9A, st9_djnz, A_8q }, - { 0x9B, st9_jrcc, A_8q }, - { 0x9C, st9_ld, A_8q }, - { 0x9D, st9_jpcc, A_16q }, - { 0x9E, st9_cpw, A_wrpd_wrps }, - { 0x9E, st9_cpw, A_wrpdi_wrps }, - { 0x9E, st9_cpw, A_wrpd_wrpsi }, - { 0x9E, st9_cpw, A_wrpdi_wrpsi }, - { 0x9F, st9_cpjfi, A_wrd_wrpsi_8q_0 }, - { 0x9F, st9_cpjti, A_wrd_wrpsi_8q_1 }, - { 0xA0, st9_rol, A_grd }, - { 0xA1, st9_rol, A_grdi }, - { 0xA2, st9_tm, A_wrd_wrs }, - { 0xA3, st9_tm, A_wrd_wrsi }, - { 0xA4, st9_tm, A_grd_grs }, - { 0xA5, st9_tm, A_grd_8q }, - { 0xA6, st9_aldw, A_grpd_wrsi }, - { 0xA7, st9_tmw, A_grpd_grps }, - { 0xA7, st9_tmw, A_grpd_16q_1 }, - { 0xA8, st9_ld, A_grs }, - { 0xA9, st9_ld, A_grd }, - { 0xAA, st9_djnz, A_8q }, - { 0xAB, st9_jrcc, A_8q }, - { 0xAC, st9_ld, A_8q }, - { 0xAD, st9_jpcc, A_16q }, - { 0xAE, st9_tmw, A_wrpd_wrps }, - { 0xAE, st9_tmw, A_wrpdi_wrps }, - { 0xAE, st9_tmw, A_wrpd_wrpsi }, - { 0xAE, st9_tmw, A_wrpdi_wrpsi }, - { 0xAF, st9_btjt, A_bwr_8q_0 }, - { 0xAF, st9_btjf, A_bwr_8q_1 }, - { 0xB0, st9_rlc, A_grd }, - { 0xB1, st9_rlc, A_grdi }, - { 0xB2, st9_ld, A_8qxwr_wrs }, - { 0xB3, st9_ld, A_wrs_8qxwr }, - { 0xB4, st9_ald, A_grd_wrpip }, - { 0xB4, st9_ald, A_wrpip_grd }, - { 0xB5, st9_ld, A_wrd_wrpi }, - { 0xB5, st9_ld, A_wrpi_wrd }, - { 0xB6, st9_pushuw, A_grp_0 }, - { 0xB6, st9_linku, A_grp_8q }, - { 0xB7, st9_popuw, A_grp_0 }, - { 0xB7, st9_unlinku, A_grp_1 }, - { 0xB8, st9_ld, A_grs }, - { 0xB9, st9_ld, A_grd }, - { 0xBA, st9_djnz, A_8q }, - { 0xBB, st9_jrcc, A_8q }, - { 0xBC, st9_ld, A_8q }, - { 0xBD, st9_jpcc, A_16q }, - { 0xBE, st9_aldw, A_wrpi_grp }, - { 0xBE, st9_aldw, A_wrpi_16q }, - { 0xBF01, st9_halt, A_IMPL }, - { 0xBF, st9_ldw, A_grpd_16q_0 }, - { 0xC0, st9_ror, A_grd }, - { 0xC1, st9_ror, A_grdi }, - { 0xC2, st9_ald, A_grd_wrpim }, - { 0xC2, st9_ald, A_wrpim_grd }, - { 0xC3, st9_aldw, A_grpd_wrpim }, - { 0xC3, st9_aldw, A_wrpim_grpd }, - { 0xC4, st9_ald, A_wrd_16q }, - { 0xC5, st9_ald, A_16q_wrs }, - { 0xC6, st9_ext, A_grp_1 }, - { 0xC6, st9_dwjnz, A_grp_8q }, - { 0xC7, st9_srp, A_rwn_000 }, - { 0xC7, st9_srp0, A_rwn_100 }, - { 0xC7, st9_srp1, A_rwn_101 }, - { 0xC7, st9_spp, A_rpn }, - { 0xC8, st9_ld, A_grs }, - { 0xC9, st9_ld, A_grd }, - { 0xCA, st9_djnz, A_8q }, - { 0xCB, st9_jrcc, A_8q }, - { 0xCC, st9_ld, A_8q }, - { 0xCD, st9_jpcc, A_16q }, - { 0xCE, st9_etrap, A_IMPL }, - { 0xCF, st9_decw, A_grpd_0 }, - { 0xD0, st9_rrc, A_grd }, - { 0xD1, st9_rrc, A_grdi }, - { 0xD2, st9_call, A_16q }, - { 0xD3, st9_iret, A_IMPL }, - { 0xD4, st9_jp, A_grpi }, - { 0xD4, st9_link, A_grp_8q }, - { 0xD5, st9_aldw, A_grpd_wrpip }, - { 0xD5, st9_aldw, A_wrpip_grpd }, - { 0xD6, st9_ldpp, A_wrpdip_wrpsip_00 }, - { 0xD6, st9_lddp, A_wrpdip_wrpsip_10 }, - { 0xD6, st9_ldpd, A_wrpdip_wrpsip_01 }, - { 0xD6, st9_lddd, A_wrpdip_wrpsip_11 }, - { 0xD7, st9_ld, A_wrip_wrpip }, - { 0xD7, st9_ld, A_wrpip_wrip }, - { 0xD8, st9_ld, A_grs }, - { 0xD9, st9_ld, A_grd }, - { 0xDA, st9_djnz, A_8q }, - { 0xDB, st9_jrcc, A_8q }, - { 0xDC, st9_ld, A_8q }, - { 0xDD, st9_jpcc, A_16q }, - { 0xDE, st9_ldw, A_8qxwrip_wrp }, - { 0xDE, st9_ldw, A_wrp_8qxwrip }, - { 0xDF, st9_incw, A_grpd_0 }, - { 0xE0, st9_sra, A_grd }, - { 0xE1, st9_sra, A_grdi }, - { 0xE2, st9_aldw, A_wrp_16q }, - { 0xE2, st9_aldw, A_16q_wrp }, - { 0xE3, st9_ldw, A_wrpd_wrps }, - { 0xE3, st9_ldw, A_wrpdi_wrps }, - { 0xE3, st9_ldw, A_wrpd_wrpsi }, - { 0xE3, st9_ldw, A_wrpdi_wrpsi }, - { 0xE4, st9_ld, A_wrd_wrsi }, - { 0xE5, st9_ld, A_wrdi_wrs }, - { 0xE6, st9_ald, A_wrdi_grs }, - { 0xE7, st9_ald, A_grd_wrsi }, - { 0xE8, st9_ld, A_grs }, - { 0xE9, st9_ld, A_grd }, - { 0xEA, st9_djnz, A_8q }, - { 0xEB, st9_jrcc, A_8q }, - { 0xEC, st9_ld, A_8q }, - { 0xED, st9_jpcc, A_16q }, - { 0xEE, st9_spm, A_IMPL }, - { 0xEF01, st9_wfi, A_IMPL }, - { 0xEF31, st9_eret, A_IMPL }, - { 0xEF, st9_ldw, A_grpd_grps }, - { 0xF0, st9_swap, A_grd }, - { 0xF1, st9_swap, A_grdi }, - { 0xF2, st9_bld, A_wrb_wrb_10 }, - { 0xF2, st9_bld, A_wrb_nwrb_11 }, - { 0xF2, st9_btset, A_wrb }, - { 0xF3, st9_ald, A_wrpi_8q }, - { 0xF4, st9_ld, A_grd_grs }, - { 0xF5, st9_ld, A_grd_8q }, - { 0xF601, st9_rets, A_IMPL }, - { 0xF6, st9_btset, A_wrbi }, - { 0xF7, st9_push, A_grsi }, - { 0xF8, st9_ld, A_grs }, - { 0xF9, st9_ld, A_grd }, - { 0xFA, st9_djnz, A_8q }, - { 0xFB, st9_jrcc, A_8q }, - { 0xFC, st9_ld, A_8q }, - { 0xFD, st9_jpcc, A_16q }, - { 0xFE, st9_sdm, A_IMPL }, - { 0xFF, st9_nop, A_IMPL } -}; - -//---------------------------------------------------------------------- -static const opcode *find_opcode(insn_t &insn, int _code) -{ - for ( int i = 0; i < qnumber(opcodes); i++ ) - { - // is the opcode coded in a word ? - bool need_another_byte = ((opcodes[i].code & 0xFF00) >> 8) != 0; - - int code = need_another_byte - ? (_code << 8) | get_byte(insn.ea + insn.size) - : _code; - - // opcode is wrong - if ( opcodes[i].code != code ) - continue; - - int next_byte = get_byte(insn.ea + insn.size + (need_another_byte ? 1 : 0)); - int mask = 0; - int value = 0; - - switch ( opcodes[i].addr ) - { - // 0000000X (X == 0) - case A_grpd_grps: - case A_16qxwrp_16q: - case A_16qxwrp_gr: - case A_wrip_gr: - case A_gr_16qxwrp: - case A_grpd_0: - case A_grps: - case A_wrpip_grd: - case A_wrd_wrpi: - case A_grp_0: - case A_wrpi_16q: - case A_grpd_16q_0: - case A_wrpim_grd: - case A_wrpim_grpd: - case A_grpi: - case A_wrpip_grpd: - case A_wrpip_wrip: - case A_wrp_16q: - mask = 0x01; - value = 0x00; - break; - - case A_wrb: - mask = 0x10; - value = 0x00; - break; - - // 0000000X (X == 1) - case A_grpd_16q_1: - case A_8qxwrp_16q: - case A_8qxwrp_gr: - case A_gr_wrpi: - case A_gr_8qxwrp: - case A_grpd_1: - case A_grpdi: - case A_grd_wrpip: - case A_wrpi_wrd: - case A_grp_1: - case A_wrpi_grp: - case A_grd_wrpim: - case A_grpd_wrpim: - case A_grpd_wrpip: - case A_wrip_wrpip: - case A_16q_wrp: - mask = 0x01; - value = 0x01; - break; - - // 00000XXX (XXX = 000) - case A_rwn_000: - mask = 0x07; - value = 0x00; - break; - - // 00000XXX (XXX = 100) - case A_rwn_100: - mask = 0x07; - value = 0x04; - break; - - // 00000XXX (XXX = 101) - case A_rwn_101: - mask = 0x07; - value = 0x05; - break; - - // XY000000 (XY == 01) - case A_seg_16q_01: - mask = 0xC0; - value = 0x40; - break; - - // XY000000 (XY == 11) - case A_seg_16q_11: - mask = 0xC0; - value = 0xC0; - break; - - // 000000XY (XY = 10) - case A_rpn: - mask = 0x03; - value = 0x02; - break; - - // 000X0000 (X == 0) - case A_wrd_wrpsi_8q_0: - case A_wrp_8qxwrip: - case A_bwr_8q_0: - mask = 0x10; - value = 0x00; - break; - - // 000X0000 (X == 1) - case A_wrd_wrpsi_8q_1: - case A_8qxwrip_wrp: - case A_bwr_8q_1: - mask = 0x10; - value = 0x10; - break; - - // XXXX0000 (XXXX = 0100) - case A_gri_wrip_01: - mask = 0xF0; - value = 0x40; - break; - - // XXXX0000 (XXXX = 1100) - case A_gri_wrip_11: - mask = 0xF0; - value = 0xC0; - break; - - // 000X000Y (X == 0 && Y == 0) - case A_wrpd_wrps: - case A_wrpdip_wrpsip_00: - case A_wrp_wrpxwrp: - case A_wrbi: - mask = 0x11; - value = 0x00; - break; - - // 000X000Y (X == 1 && Y == 0) - case A_wrpdi_wrps: - case A_wrpdip_wrpsip_10: - case A_wr_wrpxwrp: - mask = 0x11; - value = 0x10; - break; - - // 000X000Y (X == 0 && Y == 1) - case A_wrpd_wrpsi: - case A_wrpdip_wrpsip_01: - case A_wrpxwrp_wrp: - mask = 0x11; - value = 0x01; - break; - - // 000X000Y (X == 1 && Y == 1) - case A_wrpdi_wrpsi: - case A_wrpdip_wrpsip_11: - case A_wrpxwrp_wr: - mask = 0x11; - value = 0x11; - break; - - // 0000X (X = 0001) - case A_16q_8q: - case A_16q_16q: - mask = 0x0F; - value = 0x01; - break; - - // 0000000X (X == 1) && 3th byte MSB == 1 - case A_8qxwrp_grp: - if ( (get_byte(insn.ea + insn.size + 2) & 0x01) == 1 ) - { - mask = 0x01; - value = 0x01; - } - else - mask = -1; - break; - - // 0000000X (X == 1) && 3th byte MSB == 0 - case A_grp_8qxwrp: - if ( (get_byte(insn.ea + insn.size + 2) & 0x01) == 0 ) - { - mask = 0x01; - value = 0x01; - } - else - mask = -1; - break; - - // 0000000X (X == 1) && 4th byte MSB == 1 - case A_16qxwrp_grp: - if ( (get_byte(insn.ea + insn.size + 3) & 0x01) == 1 ) - { - mask = 0x01; - value = 0x00; - } - else - mask = -1; - break; - - // 0000000X (X == 1) && 4th byte MSB == 0 - case A_grp_16qxwrp: - if ( (get_byte(insn.ea + insn.size + 3) & 0x01) == 0 ) - { - mask = 0x01; - value = 0x00; - } - else - mask = -1; - break; - - // 2nd byte MSB == 0 - case A_8qxgrpi: - if ( (get_byte(insn.ea + insn.size + 1) & 0x01) != 0 ) - mask = -1; - break; - - // 2nd byte MSB == 1 - case A_16qxgrpi: - if ( (get_byte(insn.ea + insn.size + 1) & 0x01) != 1 ) - mask = -1; - break; - - // NOTE: it seems that there is an error in the manual : - // rd.b,rs.b and rd.b,rs.!b opcodes are inversed ! - - // 000X0000 (X == 1) + 0x000Y0000 (Y == 0) - case A_wrb_wrb_10: - case A_wrb_nwrb_10: - if ( (get_byte(insn.ea + insn.size + 1) & 0x10) == 0 ) - { - mask = 0x10; - value = 0x10; - } - else - mask = -1; - break; - - // 000X0000 (X == 1) + 0x000Y0000 (Y == 1) - case A_wrb_wrb_11: - case A_wrb_nwrb_11: - if ( (get_byte(insn.ea + insn.size + 1) & 0x10) == 0x10 ) - { - mask = 0x10; - value = 0x10; - } - else - mask = -1; - break; - - } - - // addr mode is wrong - if ( mask != 0 && (mask == -1 || (next_byte & mask) != value) ) - continue; - - // Yahoo ! - if ( need_another_byte ) - insn.size++; - - return &opcodes[i]; - } - return NULL; -} - -//---------------------------------------------------------------------- -static int get_condition_code(int code) -{ - switch ( code ) - { - case 0x0B: // JR F,N - case 0x0D: // JP F,NN - return cF; - - case 0x1B: // JR LT,N - case 0x1D: // JP LT,NN - return cLT; - - case 0x2B: // JR LE,N - case 0x2D: // JP LE,NN - return cLE; - - case 0x3B: // JR ULE,N - case 0x3D: // JP ULE,NN - return cULE; - - case 0x4B: // JR OV,N - case 0x4D: // JP OV,NN - return cOV; - - case 0x5B: // JR MI,N - case 0x5D: // JP MI,NN - return cMI; - - case 0x6B: // JR EQ,N - case 0x6D: // JP EQ,NN - return cEQ; - - // XXX - // According to the manual, 0x7X is related - // to the UL condition code. - // JRUL/JPUL cannot be assembled (unknown instruction). - // objdump9 disassemble 0x7X with the C condition code, - // therefore we use it instead of UL. - case 0x7B: // JR C,N - case 0x7D: // JP C,NN - return cC; - - case 0x8B: // JR T,N - case 0x8D: // JP T,NN - return cT; - - case 0x9B: // JR GE,N - case 0x9D: // JP GE,NN - return cGE; - - case 0xAB: // JR GT,N - case 0xAD: // JP GT,NN - return cGT; - - case 0xBB: // JR UGT,N - case 0xBD: // JP UGT,NN - return cUGT; - - case 0xCB: // JR NOV,N - case 0xCD: // JP NOV,NN - return cNOV; - - case 0xDB: // JR PL,N - case 0xDD: // JP PL,NN - return cPL; - - case 0xEB: // JR NE,N - case 0xED: // JP NE,NN - return cNE; - - case 0xFB: // JR NC,N - case 0xFD: // JP NC,NN - return cNC; - } - return cUNKNOWN; -} - -//---------------------------------------------------------------------- -static uint16 get_working_register(int code) -{ - uchar reg_id = (code & 0xF0) >> 4; - return rr0 + reg_id; -} - -//---------------------------------------------------------------------- -// general register: if the 4 Most Significant Bits (MSB) are Dh then the 4 Least Significant -// Bits (LSB) specify a working register -static uint16 get_general_register(int code, bool pair = false) -{ - uchar reg_grp = (code & 0xF0) >> 4; - //group D (R208-R223) refers to working registers - - if ( reg_grp == 0xD ) - return (pair ? rrr0 : rr0) + (code & 0x0F); - else - return (pair ? rRR0 : rR0) + code; -} - -//---------------------------------------------------------------------- -static uint16 get_alu_insn(const insn_t &insn, int code) -{ - int insn_id = (code & 0xF0) >> 4; - - QASSERT(10031, insn.itype == st9_ald || insn.itype == st9_aldw); - - bool long_insn = insn.itype == st9_aldw; - - if ( !long_insn ) - { - switch ( insn_id ) - { - case 0x0: return st9_or; - case 0x1: return st9_and; - case 0x2: return st9_sbc; - case 0x3: return st9_adc; - case 0x4: return st9_add; - case 0x5: return st9_sub; - case 0x6: return st9_xor; - case 0x8: return st9_cp; - case 0x9: return st9_cp; - case 0xA: return st9_tm; - case 0xF: return st9_ld; - } - } - else - { - switch ( insn_id ) - { - case 0x0: return st9_orw; - case 0x1: return st9_andw; - case 0x2: return st9_sbcw; - case 0x3: return st9_adcw; - case 0x4: return st9_addw; - case 0x5: return st9_subw; - case 0x6: return st9_xorw; - case 0x8: return st9_cpw; - case 0x9: return st9_cpw; - case 0xA: return st9_tmw; - case 0xF: return st9_ldw; - } - } - return st9_null; -} - -//---------------------------------------------------------------------- -// fill instruction flag -static void set_flag(insn_t &insn, int flag) -{ - insn.auxpref |= flag; -} - -//---------------------------------------------------------------------- -// fill operand flag -static void set_flag(op_t &x, int flag) -{ - x.specflag1 |= flag; -} - -//---------------------------------------------------------------------- -// fill an operand as a register -static void set_reg(op_t &op, uint16 reg, int flag = 0) -{ - op.type = o_reg; - op.reg = reg; - op.dtype = dt_byte; - if ( flag ) - set_flag(op, flag); -} - -//---------------------------------------------------------------------- -// fill an operand as an immediate value -static void set_imm(op_t &op, int val, char d_typ, int flag = 0) -{ - op.type = o_imm; - op.value = val; - op.dtype = d_typ; - if ( flag ) - set_flag(op, flag); -} - -//---------------------------------------------------------------------- -// fill an operand as a displacement -static void set_displ(op_t &op, optype_t a1_t, uint16 a1, optype_t a2_t, uint16 a2, char dtyp = dt_byte) -{ - op.type = o_displ; - op.reg = 0; - switch ( a1_t ) - { - case o_reg: - op.reg = a1; - break; - - case o_mem: - op.addr = a1; - break; - - default: - INTERR(10032); - } - switch ( a2_t ) - { - case o_reg: - if ( op.reg == 0 ) - op.reg = a2; - else - INTERR(10033); - break; - - default: - INTERR(10034); - } - op.dtype = dtyp; -} - -//---------------------------------------------------------------------- -// fill an operand as a phrase -static void set_phrase(op_t &op, st9_phrases phrase, uint16 reg1, int reg2 = -1, char dtyp = dt_byte) -{ - op.type = o_phrase; - op.reg = reg1; - op.specflag2 = phrase; - op.dtype = dtyp; - if ( reg2 != -1 ) - { - op.specflag2 = (reg2 & 0xFF00) >> 8; - op.specflag3 = (reg2 & 0x00FF); - } -} - -//---------------------------------------------------------------------- -// add a bit number to a register operand -static void set_bit(op_t &op, int bit, int flag = 0) -{ - op.value = bit; - if ( flag ) - set_flag(op, flag); -} - -//---------------------------------------------------------------------- -// fill an operand as an address (data or code) -static void set_addr(op_t &op, optype_t type, ea_t addr, char dtyp = dt_byte) -{ - QASSERT(10035, type == o_mem || type == o_near || type == o_far); // bad optype_t in set_addr() - op.type = type; - op.addr = addr; - op.dtype = dtyp; -} - -//---------------------------------------------------------------------- -static uint16 my_next_word(insn_t &insn) -{ - uchar b1 = insn.get_next_byte(); - uchar b2 = insn.get_next_byte(); - return b1 | (b2 << 8); -} - -//---------------------------------------------------------------------- -static void fill_cmd(insn_t &insn, int byte, const opcode *op) -{ - QASSERT(10036, op != NULL); - insn.itype = op->insn; - - switch ( op->addr ) - { - // Implied - case A_IMPL: - // Nothing to do ! - break; - - // rd,rs - case A_wrd_wrs: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); - set_reg(insn.Op2, rr0 + (byte & 0x0F)); - break; - - // rd,(rs) - case A_wrd_wrsi: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); - set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND); - break; - - // (rd),rs - case A_wrdi_wrs: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4), OP_IS_IND); - set_reg(insn.Op2, rr0 + (byte & 0x0F)); - break; - - // (rd),Rs - case A_wrdi_grs: - QASSERT(10037, insn.itype == st9_ald); - set_reg(insn.Op2, get_general_register(insn.get_next_byte())); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_IS_IND); - break; - - // Rd,(rs) - case A_grd_wrsi: - QASSERT(10038, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // Rs,Rd - case A_grs_grd: - // Rd,Rs - case A_grd_grs: - set_reg(insn.Op2, get_general_register(insn.get_next_byte())); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // Rd,#N - case A_grd_8q: - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - set_imm(insn.Op2, insn.get_next_byte(), dt_byte); - break; - - // RRd,RRs - case A_grpd_grps: - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // RRd,#NN - case A_grpd_16q_0: - case A_grpd_16q_1: - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - set_imm(insn.Op2, insn.get_next_word(), dt_word); - break; - - // RR,N - case A_grp_8q: - { - byte = insn.get_next_byte(); - uint16 reg = get_general_register(byte & 0xFE, true); - if ( insn.itype == st9_dwjnz ) - { - set_addr(insn.Op2, o_near, insn.get_next_byte()); - insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; - } - else - { // link or linku - set_imm(insn.Op2, 0xFF - insn.get_next_byte(), dt_byte); - } - set_reg(insn.Op1, reg); - } - break; - - // Rs - case A_grs: - if ( insn.itype == st9_ld ) - { - set_reg(insn.Op1, get_working_register(byte)); - set_reg(insn.Op2, get_general_register(insn.get_next_byte())); - } - else - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // Rd - case A_grd: - if ( insn.itype == st9_ld ) - { - set_reg(insn.Op2, get_working_register(byte)); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - } - else - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // (R) - case A_grdi: - case A_grsi: - set_reg(insn.Op1, get_general_register(insn.get_next_byte()), OP_IS_IND); - break; - - // RR - case A_grp_0: - case A_grp_1: - case A_grps: - case A_grpd_0: - case A_grpd_1: - { - byte = insn.get_next_byte(); - uint16 reg = get_general_register((byte & 0xFE), true); - set_reg(insn.Op1, reg); - } - break; - - // (RR) - case A_grpi: - case A_grpdi: - set_reg(insn.Op1, get_general_register((insn.get_next_byte() & 0xFE), true), OP_IS_IND); - break; - - // N - case A_8q: - if ( is_jmp_cc(insn.itype) ) - { - set_flag(insn, get_condition_code(byte)); - set_addr(insn.Op1, o_near, insn.get_next_byte()); - insn.Op1.addr = (signed char) insn.Op1.addr + insn.ip + insn.size; - } - else if ( insn.itype == st9_djnz ) - { - set_reg(insn.Op1, get_working_register(byte)); - set_addr(insn.Op2, o_near, insn.get_next_byte()); - insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; - } - else if ( insn.itype == st9_ld ) - { - set_reg(insn.Op1, get_working_register(byte)); - set_imm(insn.Op2, insn.get_next_byte(), dt_byte); - insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; - } - else if ( insn.itype == st9_push - || insn.itype == st9_pushu - || insn.itype == st9_pushw ) - { - set_imm(insn.Op1, insn.get_next_byte(), dt_byte); - } - else - { - set_addr(insn.Op1, o_mem, insn.get_next_byte()); - insn.Op1.addr = (signed char) insn.Op1.addr + insn.ip + insn.size; - } - break; - - // NN - case A_16q: - if ( is_jmp_cc(insn.itype) || insn.itype == st9_call ) - { - if ( is_jmp_cc(insn.itype) ) - set_flag(insn, get_condition_code(byte)); - set_addr(insn.Op1, o_near, insn.get_next_word()); - } - else if ( insn.itype == st9_push - || insn.itype == st9_pushu - || insn.itype == st9_pushw - || insn.itype == st9_pushuw ) - { - set_imm(insn.Op1, insn.get_next_word(), dt_word); - } - else - { - set_addr(insn.Op1, o_mem, insn.get_next_word()); - } - break; - - // rrd,rrs - case A_wrpd_wrps: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); - set_reg(insn.Op2, rrr0 + (byte & 0x0E)); - break; - - // (rrd),rrs - case A_wrpdi_wrps: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND); - set_reg(insn.Op2, rrr0 + (byte & 0x0E)); - break; - - // rrd,(rrs) - case A_wrpd_wrpsi: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); - set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); - break; - - // (rrd),(rrs) - case A_wrpdi_wrpsi: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND); - set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); - break; - - // rrd,rs - case A_wrpd_wrs: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); - set_reg(insn.Op2, rr0 + (byte & 0x0F)); - break; - - // rd,(rrs) - case A_wrd_wrpi: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); - set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); - break; - - // (rrs),rd - case A_wrpi_wrd: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); - set_reg(insn.Op2, rr0 + ((byte & 0xF0) >> 4)); - break; - - // Nd(rr),#NNs - case A_8qxwrp_16q: - QASSERT(10039, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word); - set_imm(insn.Op2, insn.get_next_word(), dt_word); - break; - - // NNd(rr),#NNs - case A_16qxwrp_16q: - QASSERT(10040, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word); - set_imm(insn.Op2, insn.get_next_word(), dt_word); - break; - - // N(rr),R - case A_8qxwrp_gr: - QASSERT(10041, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E)); - set_reg(insn.Op2, get_general_register(insn.get_next_byte())); - break; - - // NN(rr),R - case A_16qxwrp_gr: - QASSERT(10042, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E)); - set_reg(insn.Op2, get_general_register(insn.get_next_byte())); - break; - - // NNd,#Ns - case A_16q_8q: - QASSERT(10043, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_imm(insn.Op2, insn.get_next_byte(), dt_byte); - set_addr(insn.Op1, o_mem, insn.get_next_word()); - break; - - // NNd,#NNs - case A_16q_16q: - QASSERT(10044, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_imm(insn.Op2, insn.get_next_word(), dt_word); - set_addr(insn.Op1, o_mem, insn.get_next_word(), dt_word); - break; - - // rd,rrs(rrx) - case A_wr_wrpxwrp: - QASSERT(10045, insn.itype == st9_ald); - byte = insn.get_next_byte(); - set_phrase(insn.Op2, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E)); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rr0 + (byte & 0x0F)); - break; - - // rrd(rrx),rs - case A_wrpxwrp_wr: - QASSERT(10046, insn.itype == st9_ald); - byte = insn.get_next_byte(); - set_phrase(insn.Op1, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E)); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rr0 + (byte & 0x0F)); - break; - - // rrd,rrs(rrx) - case A_wrp_wrpxwrp: - QASSERT(10047, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - set_phrase(insn.Op2, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E), dt_word); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rrr0 + (byte & 0x0E)); - break; - - // rrd(rrx),rrs - case A_wrpxwrp_wrp: - QASSERT(10048, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - set_phrase(insn.Op1, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E), dt_word); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rrr0 + (byte & 0x0E)); - break; - - // Rd,(rrs) - case A_gr_wrpi: - QASSERT(10049, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // (rrd),Rs - case A_wrip_gr: - QASSERT(10050, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); - set_reg(insn.Op2, get_general_register(insn.get_next_byte())); - break; - - // (RRd),(rrs) - case A_grpi_wrip: - QASSERT(10051, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true), OP_IS_IND); - break; - - // (R),(rr) - case A_gri_wrip_01: - case A_gri_wrip_11: - set_reg(insn.Op2, rrr0 + (insn.get_next_byte() & 0x0E), OP_IS_IND); - set_reg(insn.Op1, get_general_register(insn.get_next_byte()), OP_IS_IND); - break; - - // Rd,N(rrx) - case A_gr_8qxwrp: - QASSERT(10052, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E)); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // Rd,NN(rrx) - case A_gr_16qxwrp: - QASSERT(10053, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op2, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E)); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // RRd,(rrs) - case A_grp_wrpi: - QASSERT(10054, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // N(rrx),RRs - case A_8qxwrp_grp: - QASSERT(10055, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word); - set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // RRd,N(rrx) - case A_grp_8qxwrp: - QASSERT(10056, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word); - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // NN(rrx),RRs - case A_16qxwrp_grp: - QASSERT(10057, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word); - set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // RRd,NN(rrx) - case A_grp_16qxwrp: - QASSERT(10058, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_displ(insn.Op2, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word); - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // N(RRx) - case A_8qxgrpi: - byte = insn.get_next_byte(); - set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, get_general_register(byte & 0xFE, true)); - break; - - // NN(RRx) - case A_16qxgrpi: - byte = insn.get_next_byte(); - // this word is coded with little endian - set_displ(insn.Op1, o_mem, short(my_next_word(insn)), o_reg, get_general_register(byte & 0xFE, true)); - break; - - // rd,(rrs),N - case A_wrd_wrpsi_8q_0: - case A_wrd_wrpsi_8q_1: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + (byte & 0x0F)); - set_reg(insn.Op2, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND); - set_imm(insn.Op3, insn.get_next_byte(), dt_byte); - break; - - // RRd,(rs) - case A_grpd_wrsi: - QASSERT(10059, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND); - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // N(rx),rs - case A_8qxwr_wrs: - byte = insn.get_next_byte(); - set_reg(insn.Op2, rr0 + ((byte & 0xF0) >> 4)); - set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); - break; - - // rs,N(rx) - case A_wrs_8qxwr: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); - set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); - break; - - // Rd,(rrs)+ - case A_grd_wrpip: - QASSERT(10060, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E)); - set_reg(insn.Op1, get_general_register(insn.get_next_byte())); - break; - - // (rrs)+,Rd - case A_wrpip_grd: - QASSERT(10061, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E)); - set_reg(insn.Op2, rR0 + insn.get_next_byte()); - break; - - // (rr),RR - case A_wrpi_grp: - QASSERT(10062, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); - set_reg(insn.Op2, rRR0 + (insn.get_next_byte() & 0x0E)); - break; - - // (rr),#NN - case A_wrpi_16q: - QASSERT(10063, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); - set_imm(insn.Op2, insn.get_next_word(), dt_word); - break; - - // Rd,-(rrs) - case A_grd_wrpim: - QASSERT(10064, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op2, fPD, rrr0 + (byte & 0x0E)); - set_reg(insn.Op1, rR0 + insn.get_next_byte()); - break; - - // -(rrs),Rd - case A_wrpim_grd: - QASSERT(10065, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op1, fPD, rrr0 + (byte & 0x0E)); - set_reg(insn.Op2, rR0 + insn.get_next_byte()); - break; - - // RRd,-(rrs) - case A_grpd_wrpim: - QASSERT(10066, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op2, fPD, rrr0 + (byte & 0x0E), -1, dt_word); - set_reg(insn.Op1, rRR0 + insn.get_next_byte()); - break; - - // -(rrs),RRd - case A_wrpim_grpd: - QASSERT(10067, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op1, fPD, rrr0 + (byte & 0x0E), -1, dt_word); - set_reg(insn.Op2, rRR0 + insn.get_next_byte()); - break; - - // NN,rs - case A_16q_wrs: - QASSERT(10068, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rr0 + (byte & 0x0F)); - set_addr(insn.Op1, o_mem, insn.get_next_word()); - break; - - // rd,NN - case A_wrd_16q: - QASSERT(10069, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rr0 + (byte & 0x0F)); - set_addr(insn.Op2, o_mem, insn.get_next_word()); - break; - - // (rd)+,(rrs)+ - case A_wrip_wrpip: - byte = insn.get_next_byte(); - set_phrase(insn.Op1, fPI, rr0 + ((byte & 0xE0) >> 4)); - set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E)); - break; - - // (rrs)+,(rd)+ - case A_wrpip_wrip: - byte = insn.get_next_byte(); - set_phrase(insn.Op2, fPI, rr0 + ((byte & 0xE0) >> 4)); - set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E)); - break; - - // (rrd)+,(rrs)+ - case A_wrpdip_wrpsip_00: - case A_wrpdip_wrpsip_10: - case A_wrpdip_wrpsip_01: - case A_wrpdip_wrpsip_11: - byte = insn.get_next_byte(); - set_phrase(insn.Op1, fPI, rrr0 + ((byte & 0xE0) >> 4)); - set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E)); - break; - - // RRd,(rrs)+ - case A_grpd_wrpip: - QASSERT(10070, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E), -1, dt_word); - set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // (rrd)+,RRs - case A_wrpip_grpd: - QASSERT(10071, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E), -1, dt_word); - set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); - break; - - // N(rx),rrs - case A_8qxwrip_wrp: - byte = insn.get_next_byte(); - set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); - set_reg(insn.Op2, rrr0 + ((byte & 0xE0) >> 4)); - break; - - // rrd,N(rx) - case A_wrp_8qxwrip: - byte = insn.get_next_byte(); - set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); - break; - - // rrd,NN - case A_wrp_16q: - QASSERT(10072, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rrr0 + (byte & 0x0E)); - set_addr(insn.Op2, o_mem, insn.get_next_word(), dt_word); - break; - - // NN,rrs - case A_16q_wrp: - QASSERT(10073, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op2, rrr0 + (byte & 0x0E)); - set_addr(insn.Op1, o_mem, insn.get_next_word(), dt_word); - break; - - // rrh,rrl,RRs - case A_wrp_wrp_grp: - set_reg(insn.Op3, rRR0 + (insn.get_next_byte() & 0x0E)); - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); - set_reg(insn.Op2, rrr0 + (byte & 0x0E)); - break; - - // (rd),RRs - case A_wrdi_grp: - QASSERT(10074, insn.itype == st9_aldw); - byte = insn.get_next_byte(); - set_reg(insn.Op2, rRR0 + (byte & 0x0E)); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_IS_IND); - break; - - // (rrd),#N - case A_wrpi_8q: - QASSERT(10075, insn.itype == st9_ald); - byte = insn.get_next_byte(); - insn.itype = get_alu_insn(insn, byte); - set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); - set_imm(insn.Op2, insn.get_next_byte(), dt_byte); - break; - -#define BIT_OP_1 (insn.itype != st9_bld ? insn.Op1 : insn.Op2) -#define BIT_OP_2 (insn.itype != st9_bld ? insn.Op2 : insn.Op1) - - // rd.b,rs.b - case A_wrb_wrb_10: - case A_wrb_wrb_11: - byte = insn.get_next_byte(); - set_reg(BIT_OP_1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); - set_bit(BIT_OP_1, (byte & 0xE0) >> 5); - byte = insn.get_next_byte(); - set_reg(BIT_OP_2, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); - set_bit(BIT_OP_2, (byte & 0xE0) >> 5); - break; - - // rd.b,rs.!b - case A_wrb_nwrb_10: - case A_wrb_nwrb_11: - byte = insn.get_next_byte(); - set_reg(BIT_OP_1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); - set_bit(BIT_OP_1, (byte & 0xE0) >> 5, insn.itype == st9_bld ? OP_BIT_COMPL : 0); - byte = insn.get_next_byte(); - set_reg(BIT_OP_2, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); - set_bit(BIT_OP_2, (byte & 0xE0) >> 5, insn.itype != st9_bld ? OP_BIT_COMPL : 0); - break; - - // rd.b - case A_wrb: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); - set_bit(insn.Op1, (byte & 0xE0) >> 5); - break; - - // (rr).bd - case A_wrbi: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rrr0 + (byte & 0x0F), OP_REG_WITH_BIT | OP_IS_IND); - set_bit(insn.Op1, (byte & 0xE0) >> 5); - break; - - // b.rd,N - case A_bwr_8q_0: - case A_bwr_8q_1: - byte = insn.get_next_byte(); - set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); - set_bit(insn.Op1, (byte & 0xE0) >> 5); - set_addr(insn.Op2, o_near, insn.get_next_byte()); - insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; - break; - - // nnnnnn,NN (calls, jps) - case A_seg_16q_01: - case A_seg_16q_11: - { - uint8 seg = insn.get_next_byte() & 0x3F; - uint16 dst = insn.get_next_word(); - ea_t fardest = (seg<<16) |dst; - if ( is_mapped(fardest) ) - { - set_addr(insn.Op1, o_far, fardest); - } - else - { - set_imm(insn.Op1, seg, dt_byte, OP_IMM_NO_SHIFT); - set_addr(insn.Op2, o_near, dst); - } - - } - break; - - // wwwww - case A_rwn_000: - case A_rwn_100: - case A_rwn_101: - set_imm(insn.Op1, (insn.get_next_byte() & 0xF8) >> 3, dt_byte); - break; - - // pppppp - case A_rpn: - set_imm(insn.Op1, (insn.get_next_byte() & 0xFC) >> 2, dt_byte); - break; - } -} - -//---------------------------------------------------------------------- -// analyze an instruction -int idaapi st9_ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - int byte = insn.get_next_byte(); - - const opcode *op = find_opcode(insn, byte); - if ( op == NULL ) - return 0; - - fill_cmd(insn, byte, op); - - return insn.size; -} diff --git a/idasdk75/module/st9/emu.cpp b/idasdk75/module/st9/emu.cpp deleted file mode 100644 index 64b0b38..0000000 --- a/idasdk75/module/st9/emu.cpp +++ /dev/null @@ -1,490 +0,0 @@ - -#include "st9.hpp" - -//---------------------------------------------------------------------- -static sel_t calc_page(ea_t insn_ea, ushort addr) -{ - return get_sreg(insn_ea, rDPR0+(addr>>14)); -} - -//---------------------------------------------------------------------- -static ea_t calc_data_mem_without_mapping(ea_t insn_ea, ea_t addr) -{ - sel_t page = calc_page(insn_ea, (ushort)addr); - if ( page == BADSEL ) - return BADADDR; - ea_t ea = use_mapping((page<<14) + (addr & 0x3FFF)); - return ea; -} - -//---------------------------------------------------------------------- -ea_t get_dest_addr(const insn_t &insn, const op_t &x) -{ - if ( x.type == o_far ) - return x.addr; - else if ( x.type == o_mem ) - return calc_data_mem_without_mapping(insn.ea, x.addr); - else if ( x.type == o_near ) - return to_ea(insn.cs, x.addr); - else - return BADADDR; -} - -//---------------------------------------------------------------------- -// Emulate an operand. -void st9_t::handle_operand(const insn_t &insn, const op_t &op, bool lwrite) -{ - switch ( op.type ) - { - // Code address - case o_near: - case o_far: - { - cref_t mode; - ea_t ea = get_dest_addr(insn, op); - - // call or jump ? - if ( is_call_insn(insn) ) - { - if ( !func_does_return(ea) ) - flow = false; - mode = op.type == o_near ? fl_CN: fl_CF; - } - else - { - mode = op.type == o_near ? fl_JN: fl_JF; - } - insn.add_cref(ea, op.offb, mode); - } - break; - - // Memory address - case o_mem: - { - ea_t ea = get_dest_addr(insn, op); - insn.add_dref(ea, op.offb, lwrite ? dr_W : dr_R); - insn.create_op_data(ea, op); - } - break; - - // Immediate value - case o_imm: - { - set_immd(insn.ea); - flags_t F = get_flags(insn.ea); - // create a comment if this immediate is represented in the .cfg file - { - const ioport_t * port = find_sym(op.value); - if ( port != NULL && !has_cmt(F) ) - set_cmt(insn.ea, port->cmt.c_str(), false); - } - // if the value was converted to an offset, then create a data xref: - if ( op_adds_xrefs(F, op.n) ) - insn.add_off_drefs(op, dr_O, 0); - } - break; - - // Displacement - case o_displ: - { - set_immd(insn.ea); - flags_t F = get_flags(insn.ea); - if ( op_adds_xrefs(F, op.n) ) - { - ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR); - insn.create_op_data(ea, op); - } - - // create stack variables if required - if ( may_create_stkvars() && !is_defarg(F, op.n) && op.reg == rrr14 ) - { - func_t *pfn = get_func(insn.ea); - if ( pfn != NULL && pfn->flags & FUNC_FRAME ) - { - adiff_t displ = (int16)op.addr; - if ( insn.create_stkvar(op, displ, STKVAR_VALID_SIZE) ) - { - op_stkvar(insn.ea, op.n); - if ( insn.Op2.type == o_reg ) - { - regvar_t *r = find_regvar(pfn, insn.ea, ph.reg_names[insn.Op2.reg]); - if ( r != NULL ) - { - struc_t *s = get_frame(pfn); - member_t *m = get_stkvar(NULL, insn, op, displ); - if ( s != NULL && m != NULL ) - { - char b[20]; - qsnprintf(b, sizeof b, "%scopy", r->user); - set_member_name(s, m->soff, b); - } - } - } - } - } - } - } - break; - - // Register - Phrase - Void: do nothing - case o_reg: - case o_phrase: - case o_void: - break; - - default: - INTERR(10076); - } -} - -//---------------------------------------------------------------------- -// Emulate an instruction. -int st9_t::st9_emu(const insn_t &insn) -{ - uint32 feature = insn.get_canon_feature(ph); - flow = ((feature & CF_STOP) == 0); - // is it "jump always"? - if ( is_jmp_cc(insn.itype) && insn.auxpref == cT ) - flow = false; - - if ( insn.Op1.type != o_void) handle_operand(insn, insn.Op1, (feature & CF_CHG1) != 0); - if ( insn.Op2.type != o_void) handle_operand(insn, insn.Op2, (feature & CF_CHG2) != 0); - if ( insn.Op3.type != o_void) handle_operand(insn, insn.Op3, (feature & CF_CHG3) != 0); - - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - - // Following code will update the current value of the two virtual - // segment registers: RW (register window) and RP (register page). - - bool rw_has_changed = false; - bool rp_has_changed = false; - - switch ( insn.itype ) - { - case st9_srp: - { - sel_t val = insn.Op1.value; - if ( val % 2 ) - val--; // even reduced - split_sreg_range(insn.ea+insn.size, rRW, val | (val << 8), SR_auto); - } - rw_has_changed = true; - break; - - case st9_srp0: - { - sel_t RW = get_sreg(insn.ea, rRW); - split_sreg_range(insn.ea+insn.size, rRW, insn.Op1.value | (RW & 0xFF00), SR_auto); - } - rw_has_changed = true; - break; - - case st9_srp1: - { - sel_t RW = get_sreg(insn.ea, rRW); - split_sreg_range(insn.ea+insn.size, rRW, (insn.Op1.value << 8) | (RW & 0x00FF), SR_auto); - } - rw_has_changed = true; - break; - - case st9_spp: - split_sreg_range(insn.ea+insn.size, rRP, insn.Op1.value, SR_auto); - rp_has_changed = true; - break; - } - - // If RW / RP registers have changed, print a comment which explains the new mapping of - // the general registers. - - flags_t F = get_flags(insn.ea); - if ( rw_has_changed && !has_cmt(F) ) - { - char buf[MAXSTR]; - sel_t RW = get_sreg(insn.ea+insn.size, rRW); - int low = RW & 0x00FF; - int high = (RW & 0xFF00) >> 8; - - low *= 8; - high *= 8; - - const char *const fmt = - "r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n" - "r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d"; - - qsnprintf(buf, sizeof buf, fmt, - 0 + low, - 1 + low, - 2 + low, - 3 + low, - 4 + low, - 5 + low, - 6 + low, - 7 + low, - 8 + high, - 9 + high, - 10 + high, - 11 + high, - 12 + high, - 13 + high, - 14 + high, - 15 + high); - - set_cmt(insn.ea, buf, false); - } - - if ( rp_has_changed && !has_cmt(F) ) - { - char buf[MAXSTR]; - int rpval = get_sreg(insn.ea+insn.size, rRP); - qsnprintf(buf, sizeof buf, "Registers R240-R255 will now be referred to the page %d of paged registers", - rpval); - set_cmt(insn.ea, buf, false); - } - - // reanalyze switch info - if ( insn.itype == st9_jp - && get_auto_state() == AU_USED ) - { - switch_info_t si; - if ( get_switch_info(&si, insn.ea) > 0 ) - { - delete_switch_table(insn.ea, si); - if ( st9_is_switch(&si, insn) ) - { - set_switch_info(insn.ea, si); - create_switch_table(insn.ea, si); - } - else - { - del_switch_info(insn.ea); - } - } - } - - return 1; -} - -//---------------------------------------------------------------------- -// Analyze an instruction -static ea_t next_insn(insn_t *insn, ea_t ea) -{ - if ( decode_insn(insn, ea) == 0 ) - return 0; - ea += insn->size; - return ea; -} - -//------------------------------------------------------------------------ -// does a far return instruction precede 'ea'? -static bool is_far_return(ea_t ea) -{ - insn_t insn; - if ( decode_prev_insn(&insn, ea) != BADADDR ) - return insn.itype == st9_rets; - return false; -} - -//---------------------------------------------------------------------- -// if a function ends with a far return, mark it as such -// NB: we only handle regular (non-chunked) functions -static void setup_far_func(func_t *pfn) -{ - if ( (pfn->flags & FUNC_FAR) == 0 ) - { - if ( is_far_return(pfn->end_ea) ) - { - pfn->flags |= FUNC_FAR; - update_func(pfn); - } - } -} - - -//---------------------------------------------------------------------- -// Create a function frame -bool st9_t::create_func_frame(func_t *pfn) const -{ - setup_far_func(pfn); - - ea_t ea = pfn->start_ea; - - insn_t insn; - ea = next_insn(&insn, ea); - if ( !ea ) - return 0; - - /* - * Get the total frame size - * - * LINK rr14, #size - */ - - if ( insn.itype != st9_link ) - return 0; - - int link_register = insn.Op1.reg; - size_t total_size = (size_t)insn.Op2.value; - - /* - * Get arguments size - * - * LDW 0x??(rr14), RR??? a word - * LD '' a byte - */ - - int args_size = 0; - - for ( int i = 0; true; i++ ) - { - insn_t ldi; - ea = next_insn(&ldi, ea); - if ( !ea ) - return 0; - - if ( ldi.Op1.type != o_displ || ldi.Op2.type != o_reg ) - break; - - if ( ldi.Op1.reg != link_register ) - break; - - if ( ldi.itype == st9_ld ) // byte - args_size++; - else if ( ldi.itype == st9_ldw ) // word - args_size += 2; - else - break; - - char regvar[10]; - qsnprintf(regvar, sizeof regvar, "arg_%d", i); - int err = add_regvar(pfn, ldi.ea, ldi.ea + ldi.size, - ph.reg_names[ldi.Op2.reg], regvar, NULL); - if ( err ) - msg("add_regvar() failed : error %d\n", err); - } - - //msg("LOCAL: %d\nARGS: %d\n", total_size - args_size, args_size); - - pfn->flags |= FUNC_FRAME; - return add_frame(pfn, total_size - args_size, 0, args_size); -} - -//------------------------------------------------------------------------ -/* -GCC?-produced switch: - - ldw ridx, rin [optional] - cpw rin, #n - jpugt default | jrugt default - addw ridx, ridx - spm - ldw rjmp, jtbl(ridx) - sdm - jp (rjmp) -jtbl: .word case0, case1, ... -*/ - -static ea_t check_prev_insn(int itype, insn_t &insn) -{ - ea_t ea = decode_prev_insn(&insn, insn.ea); - if ( ea == BADADDR || insn.itype != itype ) - return BADADDR; - return ea; -} - -//-------------------------------------------------------------------------- -static bool is_gcc_switch(switch_info_t *_si, insn_t &insn) -{ - switch_info_t &si = *_si; - int rjmp, ridx; - //si.flags |= SWI_J32; - ea_t ea, jtbl_insn; - // - // Check jump insn and get register number - // jp (rjmp) - if ( insn.itype != st9_jp - || insn.Op1.type != o_reg - || !is_ind(insn.Op1) ) - { - return false; - } - rjmp = insn.Op1.reg; - // sdm - ea = check_prev_insn(st9_sdm, insn); - if ( ea == BADADDR ) - return false; - //ldw rjmp, jtbl(ridx) - ea = check_prev_insn(st9_ldw, insn); - if ( ea == BADADDR - || !insn.Op1.is_reg(rjmp) - || insn.Op2.type != o_displ ) - return false; - ridx = insn.Op2.reg; - jtbl_insn = ea; - // this addr is offset in current code segment because of spm - si.jumps = to_ea(insn.cs, insn.Op2.addr); - // spm - ea = check_prev_insn(st9_spm, insn); - if ( ea == BADADDR ) - return false; - - // addw ridx, ridx - ea = check_prev_insn(st9_addw, insn); - if ( ea == BADADDR - || !insn.Op1.is_reg(ridx) - || !insn.Op2.is_reg(ridx) ) - return false; - - // jpugt default | jrugt default - ea = decode_prev_insn(&insn, ea); - if ( ea != BADADDR - && is_jmp_cc(insn.itype) - && insn.auxpref == cUGT ) - { - si.defjump = get_dest_addr(insn, insn.Op1); - // cpw rin, #n - ea = check_prev_insn(st9_cpw, insn); - if ( ea == BADADDR - || insn.Op2.type != o_imm ) - return false; - int rin = insn.Op1.reg; - si.ncases = ushort(insn.Op2.value+1); - // is rin the same as ridx? - bool ok = insn.Op1.is_reg(ridx); - if ( !ok ) - { - // check for preceding ldw ridx, rin - ea_t ea2 = decode_prev_insn(&insn, ea); - if ( ea2 != BADADDR - && insn.itype == st9_ldw - && insn.Op1.is_reg(ridx) - && insn.Op2.is_reg(rin) ) - ok = true; - } - if ( !ok ) - return false; - si.set_expr(rin, insn.Op1.dtype); - } - // - // Everything ok. - // - msg("SWITCH %a: gcc_switch\n", insn.ea); - si.startea = ea; - si.set_jtable_element_size(2); - si.set_shift(0); - op_num(ea, 1); // cpw rin, #n - op_plain_offset(jtbl_insn, 1, to_ea(insn.cs, 0)); //ldw rjmp, jtbl(ridx) - return true; -} - -bool st9_is_switch(switch_info_t *si, const insn_t &insn) -{ - if ( insn.itype == st9_jp ) - { - insn_t copy = insn; - return is_gcc_switch(si, copy); - } - return false; -} - - diff --git a/idasdk75/module/st9/makefile b/idasdk75/module/st9/makefile deleted file mode 100644 index 874dc88..0000000 --- a/idasdk75/module/st9/makefile +++ /dev/null @@ -1,51 +0,0 @@ -PROC=st9 -CONFIGS=st9.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp st9.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - emu.cpp ins.hpp st9.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp st9.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp st9.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp reg.cpp st9.hpp diff --git a/idasdk75/module/st9/reg.cpp b/idasdk75/module/st9/reg.cpp deleted file mode 100644 index 50ec094..0000000 --- a/idasdk75/module/st9/reg.cpp +++ /dev/null @@ -1,1269 +0,0 @@ - -#include "st9.hpp" - -#include <segregs.hpp> - -const char *const ConditionCodes[] = -{ - "UNKNOWN", - "f", // always false - "t", // always true - "c", // carry - "nc", // not carry - "z", // zero - "nz", // not zero - "pl", // plus - "mi", // minus - "ov", // overflow - "nov", // no overflow - "eq", // equal - "ne", // not equal - "ge", // greater than or equal - "lt", // less than - "gt", // greater than - "le", // less than or equal - "uge", // unsigned greated than or equal - "ul", // unsigned less than - "ugt", // unsigned greater than - "ule" // unsigned less than or equal -}; - -// ST9 registers names -static const char *const src_RegNames[] = -{ - "R0", - "R1", - "R2", - "R3", - "R4", - "R5", - "R6", - "R7", - "R8", - "R9", - "R10", - "R11", - "R12", - "R13", - "R14", - "R15", - "R16", - "R17", - "R18", - "R19", - "R20", - "R21", - "R22", - "R23", - "R24", - "R25", - "R26", - "R27", - "R28", - "R29", - "R30", - "R31", - "R32", - "R33", - "R34", - "R35", - "R36", - "R37", - "R38", - "R39", - "R40", - "R41", - "R42", - "R43", - "R44", - "R45", - "R46", - "R47", - "R48", - "R49", - "R50", - "R51", - "R52", - "R53", - "R54", - "R55", - "R56", - "R57", - "R58", - "R59", - "R60", - "R61", - "R62", - "R63", - "R64", - "R65", - "R66", - "R67", - "R68", - "R69", - "R70", - "R71", - "R72", - "R73", - "R74", - "R75", - "R76", - "R77", - "R78", - "R79", - "R80", - "R81", - "R82", - "R83", - "R84", - "R85", - "R86", - "R87", - "R88", - "R89", - "R90", - "R91", - "R92", - "R93", - "R94", - "R95", - "R96", - "R97", - "R98", - "R99", - "R100", - "R101", - "R102", - "R103", - "R104", - "R105", - "R106", - "R107", - "R108", - "R109", - "R110", - "R111", - "R112", - "R113", - "R114", - "R115", - "R116", - "R117", - "R118", - "R119", - "R120", - "R121", - "R122", - "R123", - "R124", - "R125", - "R126", - "R127", - "R128", - "R129", - "R130", - "R131", - "R132", - "R133", - "R134", - "R135", - "R136", - "R137", - "R138", - "R139", - "R140", - "R141", - "R142", - "R143", - "R144", - "R145", - "R146", - "R147", - "R148", - "R149", - "R150", - "R151", - "R152", - "R153", - "R154", - "R155", - "R156", - "R157", - "R158", - "R159", - "R160", - "R161", - "R162", - "R163", - "R164", - "R165", - "R166", - "R167", - "R168", - "R169", - "R170", - "R171", - "R172", - "R173", - "R174", - "R175", - "R176", - "R177", - "R178", - "R179", - "R180", - "R181", - "R182", - "R183", - "R184", - "R185", - "R186", - "R187", - "R188", - "R189", - "R190", - "R191", - "R192", - "R193", - "R194", - "R195", - "R196", - "R197", - "R198", - "R199", - "R200", - "R201", - "R202", - "R203", - "R204", - "R205", - "R206", - "R207", - "R208", - "R209", - "R210", - "R211", - "R212", - "R213", - "R214", - "R215", - "R216", - "R217", - "R218", - "R219", - "R220", - "R221", - "R222", - "R223", - "R224", - "R225", - "R226", - "R227", - "R228", - "R229", - "R230", - "R231", - "R232", - "R233", - "R234", - "R235", - "R236", - "R237", - "R238", - "R239", - "R240", - "R241", - "R242", - "R243", - "R244", - "R245", - "R246", - "R247", - "R248", - "R249", - "R250", - "R251", - "R252", - "R253", - "R254", - "R255", - "RR0", - "RR1", - "RR2", - "RR3", - "RR4", - "RR5", - "RR6", - "RR7", - "RR8", - "RR9", - "RR10", - "RR11", - "RR12", - "RR13", - "RR14", - "RR15", - "RR16", - "RR17", - "RR18", - "RR19", - "RR20", - "RR21", - "RR22", - "RR23", - "RR24", - "RR25", - "RR26", - "RR27", - "RR28", - "RR29", - "RR30", - "RR31", - "RR32", - "RR33", - "RR34", - "RR35", - "RR36", - "RR37", - "RR38", - "RR39", - "RR40", - "RR41", - "RR42", - "RR43", - "RR44", - "RR45", - "RR46", - "RR47", - "RR48", - "RR49", - "RR50", - "RR51", - "RR52", - "RR53", - "RR54", - "RR55", - "RR56", - "RR57", - "RR58", - "RR59", - "RR60", - "RR61", - "RR62", - "RR63", - "RR64", - "RR65", - "RR66", - "RR67", - "RR68", - "RR69", - "RR70", - "RR71", - "RR72", - "RR73", - "RR74", - "RR75", - "RR76", - "RR77", - "RR78", - "RR79", - "RR80", - "RR81", - "RR82", - "RR83", - "RR84", - "RR85", - "RR86", - "RR87", - "RR88", - "RR89", - "RR90", - "RR91", - "RR92", - "RR93", - "RR94", - "RR95", - "RR96", - "RR97", - "RR98", - "RR99", - "RR100", - "RR101", - "RR102", - "RR103", - "RR104", - "RR105", - "RR106", - "RR107", - "RR108", - "RR109", - "RR110", - "RR111", - "RR112", - "RR113", - "RR114", - "RR115", - "RR116", - "RR117", - "RR118", - "RR119", - "RR120", - "RR121", - "RR122", - "RR123", - "RR124", - "RR125", - "RR126", - "RR127", - "RR128", - "RR129", - "RR130", - "RR131", - "RR132", - "RR133", - "RR134", - "RR135", - "RR136", - "RR137", - "RR138", - "RR139", - "RR140", - "RR141", - "RR142", - "RR143", - "RR144", - "RR145", - "RR146", - "RR147", - "RR148", - "RR149", - "RR150", - "RR151", - "RR152", - "RR153", - "RR154", - "RR155", - "RR156", - "RR157", - "RR158", - "RR159", - "RR160", - "RR161", - "RR162", - "RR163", - "RR164", - "RR165", - "RR166", - "RR167", - "RR168", - "RR169", - "RR170", - "RR171", - "RR172", - "RR173", - "RR174", - "RR175", - "RR176", - "RR177", - "RR178", - "RR179", - "RR180", - "RR181", - "RR182", - "RR183", - "RR184", - "RR185", - "RR186", - "RR187", - "RR188", - "RR189", - "RR190", - "RR191", - "RR192", - "RR193", - "RR194", - "RR195", - "RR196", - "RR197", - "RR198", - "RR199", - "RR200", - "RR201", - "RR202", - "RR203", - "RR204", - "RR205", - "RR206", - "RR207", - "RR208", - "RR209", - "RR210", - "RR211", - "RR212", - "RR213", - "RR214", - "RR215", - "RR216", - "RR217", - "RR218", - "RR219", - "RR220", - "RR221", - "RR222", - "RR223", - "RR224", - "RR225", - "RR226", - "RR227", - "RR228", - "RR229", - "RR230", - "RR231", - "RR232", - "RR233", - "RR234", - "RR235", - "RR236", - "RR237", - "RR238", - "RR239", - "RR240", - "RR241", - "RR242", - "RR243", - "RR244", - "RR245", - "RR246", - "RR247", - "RR248", - "RR249", - "RR250", - "RR251", - "RR252", - "RR253", - "RR254", - "RR255", - "r0", - "r1", - "r2", - "r3", - "r4", - "r5", - "r6", - "r7", - "r8", - "r9", - "r10", - "r11", - "r12", - "r13", - "r14", - "r15", - "rr0", - "rr1", - "rr2", - "rr3", - "rr4", - "rr5", - "rr6", - "rr7", - "rr8", - "rr9", - "rr10", - "rr11", - "rr12", - "rr13", - "rr14", - "rr15", - "RW", - "RP", - "csr", - "dpr0", "dpr1", "dpr2", "dpr3", -}; - -//---------------------------------------------------------------------- -// returns a pointer to a ioport_t object if address was found in the config file. -// otherwise, returns NULL. -const ioport_t *st9_t::find_sym(ea_t address) -{ - return find_ioport(ioh.ports, address); -} - -//---------------------------------------------------------------------- -void st9_t::patch_general_registers() -{ - char b[15]; - b[0] = '\0'; - - ushort style = idpflags & CONF_GR_DEC ? 0 - : idpflags & CONF_GR_HEX ? 1 - : idpflags & CONF_GR_BIN ? 2 - : 3; - - QASSERT(10079, style != 3); - - msg("General register print style: %s\n", - style == 0 ? "decimal" - : style == 1 ? "hexadecimal" - : "binary"); - - CASSERT(sizeof(RegNames) == sizeof(src_RegNames)); - memcpy(RegNames, src_RegNames, sizeof(src_RegNames)); - dynamic_rgnames.resize(rR255 - rR1 + 1); - for ( int i = rR1; i <= rR255; i++ ) - { - switch ( style ) - { - // decimal - case 0: - qsnprintf(b, sizeof b, "R%d", i); - break; - - // hexadecimal - case 1: - qsnprintf(b, sizeof b, "R0x%X", i); - break; - - // binary - case 2: - { - static const int bits[] = { 128, 64, 32, 16, 8, 4, 2, 1 }; - b[0] = 'R'; - for ( int k = 0; k < 8; k++ ) - b[k + 1] = (i & bits[k]) ? '1' : '0'; - b[9] = 'b'; - b[10] = '\0'; - } - break; - } - dynamic_rgnames[i-rR1] = b; - RegNames[i] = dynamic_rgnames[i-rR1].begin(); - } - ph.reg_names = RegNames; -} - -//---------------------------------------------------------------------- -uint32 st9_t::refresh_idpflags(void) -{ - idpflags = (uint32)helper.altval(-1); - return idpflags; -} - -//---------------------------------------------------------------------- -const char *st9_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool idb_loaded) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - - static const char form[] = - "HELP\n" - "ST9 Related options :\n" - "\n" - " General registers print style\n" - "\n" - " Select the format which will be used by IDA to\n" - " to print general registers.\n" - "\n" - " For example,\n" - "\n" - " R10 (decimal) \n" - " R0x0A (hexadecimal) \n" - " R00001010b (binary) \n" - "\n" - "ENDHELP\n" - "ST9 related options\n" - "<##General registers print style##~D~ecimal (default):R>\n" - "<~H~exadecimal:R>\n" - "<~B~inary:R>>\n"; - - CASSERT(sizeof(print_style) == sizeof(ushort)); - if ( ask_form(form, &print_style) ) - { - idpflags = 0; - switch ( print_style ) - { - case 0: idpflags |= CONF_GR_DEC; break; - case 1: idpflags |= CONF_GR_HEX; break; - case 2: idpflags |= CONF_GR_BIN; break; - } - if ( idpflags ) - patch_general_registers(); - } - if ( idb_loaded ) - helper.altset(-1, idpflags); - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list /*va*/) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(-1, pm.idpflags); - pm.helper.supset(-1, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -// get reference data from ri, -// check compliance of opval and the full value -static bool idaapi dpr_calc_reference_data( - ea_t *target, - ea_t *base, - ea_t from, - const refinfo_t &ri, - adiff_t opval) -{ - if ( ri.base == BADADDR || ri.is_subtract() ) - return false; - - int dpr_reg = rDPR0 + ((opval >> 14) & 3); - sel_t page = get_sreg(from, dpr_reg); - if ( page == BADSEL ) - return false; - - ea_t addr = (page << 14) + (opval & 0x3FFF); - ea_t op_target = ri.base - ri.tdelta + addr; - if ( ri.target != BADADDR && ri.target != op_target ) - return false; - - *target = op_target; - *base = ri.base; - return true; -} - -// complex format with DPR prefix -//lint -e{818} ... parameter 'opval' could be declared as pointing to const -static int idaapi dpr_gen_expr( - qstring * /*buf*/, - qstring *format, - ea_t /*ea*/, - int /*numop*/, - const refinfo_t &/*ri*/, - ea_t /*from*/, - adiff_t *opval, - ea_t * /*target*/, - ea_t * /*fullvalue*/, - int /*getn_flags*/) -{ - int dpr_reg_num = (*opval >> 14) & 3; - format->sprnt(COLSTR("DPR%d:pof", SCOLOR_KEYWORD) "(%%s)", dpr_reg_num); - return 4; // continue standard processing -} - -static const custom_refinfo_handler_t ref_dpr = -{ - sizeof(custom_refinfo_handler_t), - "DPR", - "16-bit offset using DPRx register", - RHF_TGTOPT, // properties: the target can be BADADDR - dpr_gen_expr, // gen_expr - dpr_calc_reference_data, // calc_reference_data - NULL, // get_format -}; - - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new st9_t); - return 0; -} - -//---------------------------------------------------------------------- -// The kernel event notifications -// Here you may take desired actions upon some kernel events -ssize_t idaapi st9_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - // this processor is big endian - inf_set_be(true); - helper.create("$ st9"); - ref_dpr_id = register_custom_refinfo(&ref_dpr); - break; - - case processor_t::ev_term: - unregister_custom_refinfo(ref_dpr_id); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: - // default configuration (decimal reg numbers) - idpflags = CONF_GR_DEC; - if ( inf_like_binary() - && ask_yn(ASKBTN_YES, - "Do you want to split the loaded file contents into 64K banks?") == ASKBTN_YES ) - { - segment_t *s = get_first_seg(); - if ( s != NULL ) - { - ssize_t total = (ssize_t)s->size(); - ea_t ea = s->start_ea; - // align the segment start at the memory bank start - if ( (ea & 0xFFFF) != 0 ) - { - ea_t start = ea & ~0xFFFF; - set_segm_start(ea, start, 0); - ea = start; - } - // each memory bank gets its own segment - while ( 1 ) - { - set_segm_end(ea, ea+0x10000, 0); - total -= 0x10000; - ea += 0x10000; - if ( total <= 0 ) - break; - add_segm(ea>>4, ea, ea+total, NULL, "CODE"); - s = getseg(ea); - if ( s->use32() ) - { - s->bitness = 0; // use 16-bit segments - s->update(); - } - } - } - // check that a segment at 0...10000 exists - // if not, create it - s = get_first_seg(); - if ( s == NULL || s->start_ea > 0x10000 ) - add_segm(0, 0, 0x10000, NULL, "DATA"); - } - //select_device(inf_like_binary() ? IORESP_ALL : (IORESP_ALL & ~IORESP_AREA)); - //file_loaded = true; - patch_general_registers(); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - refresh_idpflags(); - // patch general register names - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // set RW/RP segment registers initial values - s->defsr[rRW-ph.reg_first_sreg] = 0; - s->defsr[rRP-ph.reg_first_sreg] = BADSEL; - } - break; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st9_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st9_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - st9_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - st9_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return st9_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return st9_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_switch: - { - switch_info_t *si = va_arg(va, switch_info_t *); - const insn_t *insn = va_arg(va, const insn_t *); - return st9_is_switch(si, *insn) ? 1 : 0; - } - - case processor_t::ev_is_insn_table_jump: - // Callback: determine if instruction is a table jump or call - // If CF_JUMP bit cannot describe all kinds of table - // jumps, please define this callback. - // It will be called for insns with CF_JUMP bit set. - // input: insn structure contains the current instruction - // returns: 0-yes, <0-no - { - const insn_t *insn = va_arg(va, insn_t *); - // this is an indirect jump or call instruction - // only allow indirect registers - if ( insn->Op1.type != o_reg || !is_ind(insn->Op1) ) - return -1; - } - break; - - case processor_t::ev_is_cond_insn: - ///< Is conditional instruction? - ///< \param insn (const ::insn_t) instruction address - ///< \retval 1 yes - ///< \retval 0 not implemented - ///< \retval -1 no - { - const insn_t *insn = va_arg(va, insn_t *); - return is_jmp_cc(insn->itype) ? 1 : -1; - } - - case processor_t::ev_is_indirect_jump: - { - //jp, call, calls can have indirect register operands (rr), (RR) - const insn_t *insn = va_arg(va, insn_t *); - if ( insn->Op1.type != o_reg || !is_ind(insn->Op1) ) - return 1; // no - if ( insn->itype == st9_jp || insn->itype == st9_call || insn->itype == st9_calls ) - return 2; // yes - else - return 1; // no - } - - - default: - break; - } - return code; -} - -//---------------------------------------------------------------------- -// -// GNU ST9+ Assembler description -// - -// gets a function name -static bool gnu_get_func_name(qstring *name, const func_t *pfn) -{ - ea_t ea = pfn->start_ea; - if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 ) - return false; - - tag_addr(name, ea, true); - return true; -} - -//---------------------------------------------------------------------- -// prints function header -static void idaapi gnu_func_header(outctx_t &ctx, func_t *pfn) -{ - ctx.gen_func_header(pfn); - - qstring name; - if ( gnu_get_func_name(&name, pfn) ) - { - int saved_flags = ctx.forbid_annotations(); - ctx.gen_printf(DEFAULT_INDENT, - COLSTR(".desc %s, %s", SCOLOR_ASMDIR), - name.begin(), - pfn->is_far() ? "far" : "near"); - ctx.restore_ctxflags(saved_flags); - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".proc %s", SCOLOR_ASMDIR), name.begin()); - ctx.ctxflags |= CTXF_LABEL_OK; - } - ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name.begin()); -} - -//---------------------------------------------------------------------- -// prints function footer -//lint -esym(818,pfn) -static void idaapi gnu_func_footer(outctx_t &ctx, func_t *pfn) -{ - qstring name; - if ( gnu_get_func_name(&name, pfn) ) - { - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".endproc", SCOLOR_ASMDIR) COLSTR("%s %s", SCOLOR_ASMDIR), ASH.cmnt, name.begin()); - } -} - -//---------------------------------------------------------------------- -static const asm_t gnu_asm = -{ - AS_COLON - |ASH_HEXF3 // hex 0x123 format - |ASB_BINF0 // bin 0110b format - |ASO_OCTF1 // oct 012345 format - |AS_ASCIIZ // don't display the final 0 in string declarations - |AS_ASCIIC // allow C-style escape sequences - |AS_1TEXT, // 1 text per line, no bytes - 0, - "ST9 GNU Assembler", - 0, - NULL, // no headers - ".org", // origin directive - NULL, // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".byte", // byte directive - ".word", // word directive - ".long", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - -// XXX -// -// .float and .double directives are supposed to be supported by the -// assembler, but when we try to assemble a file including those directives, -// we get this error message : -// -// /vob/st9plus/toolset/src/binutils/gas/config/tc-st9.c(4167): !!! STOP !!! -// -> !(Floating point convertion) - - ".float", // float (4 bytes) - ".double", // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - gnu_func_header, // func_header - gnu_func_footer, // func_footer - ".global", // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -//---------------------------------------------------------------------- -// -// Alfred Arnold's Macro Assembler definition -// - -static const asm_t asw_asm = -{ - AS_COLON - |ASH_HEXF0 // hex 123h format - |ASB_BINF3 // bin 0b010 format - |ASO_OCTF5 // oct 123q format - |AS_1TEXT, // 1 text per line, no bytes - UAS_ASW, - "Alfred Arnold's Macro Assembler", - 0, - NULL, // no headers - "ORG", // origin directive - "END", // end directive - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - "DB", // ascii string directive - "DB", // byte directive (alias: DB) - "DW", // word directive (alias: DW) - "DD", // dword (4 bytes, alias: DD) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - "equ", // Equ - NULL, // seg prefix - "$", // current IP (instruction pointer) symbol in assembler - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - 0, // flag2 ??? - NULL, // comment close string - NULL, // low8 op - NULL, // high8 op - NULL, // low16 op - NULL // high16 op -}; - -static const asm_t *const asms[] = { &gnu_asm, &asw_asm, NULL }; - -// -// Short and long name for our module -// -#define FAMILY "ST9 Family:" - -static const char *const shnames[] = -{ - "st9", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"SGS-Thomson ST9", - NULL -}; - -static const uchar retcode_1[] = { 0x46 }; // ret -static const uchar retcode_2[] = { 0xD3 }; // iret -static const uchar retcode_3[] = { 0xF6, 01 }; // rets -static const uchar retcode_4[] = { 0xEF, 31 }; // eret - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { sizeof(retcode_4), retcode_4 }, - { 0, NULL } // NULL terminated array -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_ST9, // id - // flag - PR_RNAMESOK // can use register names for byte names - | PR_BINMEM // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - | PR_SEGS // has segment registers? - | PR_SGROTHER, // the segment registers don't contain - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // array of short processor names - // the short names are used to specify the processor - // with the -p command line switch) - lnames, // array of long processor names - // the long names are used to build the processor type - // selection menu - - asms, // array of target assemblers - - notify, // the kernel event notification callback - - src_RegNames, // Regsiter names - qnumber(src_RegNames),// Number of registers - - rRW, rDPR3, - 0, // size of a segment register - rCSR, rDPR0, - - NULL, // No known code start sequences - retcodes, - - 0, st9_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 7, 15, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - st9_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/st9/st9.hpp b/idasdk75/module/st9/st9.hpp deleted file mode 100644 index b5c8e4d..0000000 --- a/idasdk75/module/st9/st9.hpp +++ /dev/null @@ -1,699 +0,0 @@ - -#ifndef __ST9_HPP -#define __ST9_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include <frame.hpp> -#include <segregs.hpp> -#include <struct.hpp> -#include "../iohandler.hpp" - -// Operand flags -#define OP_IS_IND 0x00000001 // Operand is indirect, and should be - // printed between (). -#define OP_IMM_NO_SHIFT 0x00000002 // Operand is immediate, and should not - // be prefixed by the '#' character. -#define OP_REG_WITH_BIT 0x00000004 // Operand is register, and a bit number can be - // found in the "value" field. -#define OP_BIT_COMPL 0x00000008 // Bit number is a complement, and should be - // prefixed by the '!' character. -#define OP_DISPL_FUNC_ARG 0x00000010 // Operand is a displacement, and should be considered - // as a function argument variable. -// Flags for ash.uFlag -#define UAS_ASW 0x00000001 // current assembler is ASW. - -inline bool is_ind(const op_t &op) -{ - return (op.specflag1 & OP_IS_IND) != 0; -} - -inline bool is_imm_no_shift(const op_t &op) -{ - return op.type == o_imm && (op.specflag1 & OP_IMM_NO_SHIFT) != 0; -} - -inline bool is_reg_with_bit(const op_t &op) -{ - return op.type == o_reg && (op.specflag1 & OP_REG_WITH_BIT) != 0; -} - -inline bool is_bit_compl(const op_t &op) -{ - return (op.specflag1 & OP_BIT_COMPL) != 0; -} - -// Database configuration flags -#define CONF_GR_DEC 0x00000001 // general registers should be printed in decimal format. -#define CONF_GR_HEX 0x00000002 // general registers should be printed in hexadecimal format. -#define CONF_GR_BIN 0x00000004 // general registers should be printed in binary format. - -// ST9+ registers : -enum st9_registers -{ - rR0, - rR1, - rR2, - rR3, - rR4, - rR5, - rR6, - rR7, - rR8, - rR9, - rR10, - rR11, - rR12, - rR13, - rR14, - rR15, - rR16, - rR17, - rR18, - rR19, - rR20, - rR21, - rR22, - rR23, - rR24, - rR25, - rR26, - rR27, - rR28, - rR29, - rR30, - rR31, - rR32, - rR33, - rR34, - rR35, - rR36, - rR37, - rR38, - rR39, - rR40, - rR41, - rR42, - rR43, - rR44, - rR45, - rR46, - rR47, - rR48, - rR49, - rR50, - rR51, - rR52, - rR53, - rR54, - rR55, - rR56, - rR57, - rR58, - rR59, - rR60, - rR61, - rR62, - rR63, - rR64, - rR65, - rR66, - rR67, - rR68, - rR69, - rR70, - rR71, - rR72, - rR73, - rR74, - rR75, - rR76, - rR77, - rR78, - rR79, - rR80, - rR81, - rR82, - rR83, - rR84, - rR85, - rR86, - rR87, - rR88, - rR89, - rR90, - rR91, - rR92, - rR93, - rR94, - rR95, - rR96, - rR97, - rR98, - rR99, - rR100, - rR101, - rR102, - rR103, - rR104, - rR105, - rR106, - rR107, - rR108, - rR109, - rR110, - rR111, - rR112, - rR113, - rR114, - rR115, - rR116, - rR117, - rR118, - rR119, - rR120, - rR121, - rR122, - rR123, - rR124, - rR125, - rR126, - rR127, - rR128, - rR129, - rR130, - rR131, - rR132, - rR133, - rR134, - rR135, - rR136, - rR137, - rR138, - rR139, - rR140, - rR141, - rR142, - rR143, - rR144, - rR145, - rR146, - rR147, - rR148, - rR149, - rR150, - rR151, - rR152, - rR153, - rR154, - rR155, - rR156, - rR157, - rR158, - rR159, - rR160, - rR161, - rR162, - rR163, - rR164, - rR165, - rR166, - rR167, - rR168, - rR169, - rR170, - rR171, - rR172, - rR173, - rR174, - rR175, - rR176, - rR177, - rR178, - rR179, - rR180, - rR181, - rR182, - rR183, - rR184, - rR185, - rR186, - rR187, - rR188, - rR189, - rR190, - rR191, - rR192, - rR193, - rR194, - rR195, - rR196, - rR197, - rR198, - rR199, - rR200, - rR201, - rR202, - rR203, - rR204, - rR205, - rR206, - rR207, - rR208, - rR209, - rR210, - rR211, - rR212, - rR213, - rR214, - rR215, - rR216, - rR217, - rR218, - rR219, - rR220, - rR221, - rR222, - rR223, - rR224, - rR225, - rR226, - rR227, - rR228, - rR229, - rR230, - rR231, - rR232, - rR233, - rR234, - rR235, - rR236, - rR237, - rR238, - rR239, - rR240, - rR241, - rR242, - rR243, - rR244, - rR245, - rR246, - rR247, - rR248, - rR249, - rR250, - rR251, - rR252, - rR253, - rR254, - rR255, - rRR0, - rRR1, - rRR2, - rRR3, - rRR4, - rRR5, - rRR6, - rRR7, - rRR8, - rRR9, - rRR10, - rRR11, - rRR12, - rRR13, - rRR14, - rRR15, - rRR16, - rRR17, - rRR18, - rRR19, - rRR20, - rRR21, - rRR22, - rRR23, - rRR24, - rRR25, - rRR26, - rRR27, - rRR28, - rRR29, - rRR30, - rRR31, - rRR32, - rRR33, - rRR34, - rRR35, - rRR36, - rRR37, - rRR38, - rRR39, - rRR40, - rRR41, - rRR42, - rRR43, - rRR44, - rRR45, - rRR46, - rRR47, - rRR48, - rRR49, - rRR50, - rRR51, - rRR52, - rRR53, - rRR54, - rRR55, - rRR56, - rRR57, - rRR58, - rRR59, - rRR60, - rRR61, - rRR62, - rRR63, - rRR64, - rRR65, - rRR66, - rRR67, - rRR68, - rRR69, - rRR70, - rRR71, - rRR72, - rRR73, - rRR74, - rRR75, - rRR76, - rRR77, - rRR78, - rRR79, - rRR80, - rRR81, - rRR82, - rRR83, - rRR84, - rRR85, - rRR86, - rRR87, - rRR88, - rRR89, - rRR90, - rRR91, - rRR92, - rRR93, - rRR94, - rRR95, - rRR96, - rRR97, - rRR98, - rRR99, - rRR100, - rRR101, - rRR102, - rRR103, - rRR104, - rRR105, - rRR106, - rRR107, - rRR108, - rRR109, - rRR110, - rRR111, - rRR112, - rRR113, - rRR114, - rRR115, - rRR116, - rRR117, - rRR118, - rRR119, - rRR120, - rRR121, - rRR122, - rRR123, - rRR124, - rRR125, - rRR126, - rRR127, - rRR128, - rRR129, - rRR130, - rRR131, - rRR132, - rRR133, - rRR134, - rRR135, - rRR136, - rRR137, - rRR138, - rRR139, - rRR140, - rRR141, - rRR142, - rRR143, - rRR144, - rRR145, - rRR146, - rRR147, - rRR148, - rRR149, - rRR150, - rRR151, - rRR152, - rRR153, - rRR154, - rRR155, - rRR156, - rRR157, - rRR158, - rRR159, - rRR160, - rRR161, - rRR162, - rRR163, - rRR164, - rRR165, - rRR166, - rRR167, - rRR168, - rRR169, - rRR170, - rRR171, - rRR172, - rRR173, - rRR174, - rRR175, - rRR176, - rRR177, - rRR178, - rRR179, - rRR180, - rRR181, - rRR182, - rRR183, - rRR184, - rRR185, - rRR186, - rRR187, - rRR188, - rRR189, - rRR190, - rRR191, - rRR192, - rRR193, - rRR194, - rRR195, - rRR196, - rRR197, - rRR198, - rRR199, - rRR200, - rRR201, - rRR202, - rRR203, - rRR204, - rRR205, - rRR206, - rRR207, - rRR208, - rRR209, - rRR210, - rRR211, - rRR212, - rRR213, - rRR214, - rRR215, - rRR216, - rRR217, - rRR218, - rRR219, - rRR220, - rRR221, - rRR222, - rRR223, - rRR224, - rRR225, - rRR226, - rRR227, - rRR228, - rRR229, - rRR230, - rRR231, - rRR232, - rRR233, - rRR234, - rRR235, - rRR236, - rRR237, - rRR238, - rRR239, - rRR240, - rRR241, - rRR242, - rRR243, - rRR244, - rRR245, - rRR246, - rRR247, - rRR248, - rRR249, - rRR250, - rRR251, - rRR252, - rRR253, - rRR254, - rRR255, - rr0, - rr1, - rr2, - rr3, - rr4, - rr5, - rr6, - rr7, - rr8, - rr9, - rr10, - rr11, - rr12, - rr13, - rr14, - rr15, - rrr0, - rrr1, - rrr2, - rrr3, - rrr4, - rrr5, - rrr6, - rrr7, - rrr8, - rrr9, - rrr10, - rrr11, - rrr12, - rrr13, - rrr14, - rrr15, - rRW, // register window number - rRP, // register page - rCSR, // code segment register - rDPR0, rDPR1, rDPR2, rDPR3, // Data page registers - st9_lastreg = rDPR3, -}; - -// ST9 condition codes -enum st9_cond_codes -{ - cUNKNOWN, - cF, // always false - cT, // always true - cC, // carry - cNC, // not carry - cZ, // zero - cNZ, // not zero - cPL, // plus - cMI, // minus - cOV, // overflow - cNOV, // no overflow - cEQ, // equal - cNE, // not equal - cGE, // greater than or equal - cLT, // less than - cGT, // greater than - cLE, // less than or equal - cUGE, // unsigned greated than or equal - cUL, // unsigned less than - cUGT, // unsigned greater than - cULE // unsigned less than or equal -}; - -enum st9_phrases ENUM_SIZE(uint8) -{ - fPI, // post incrementation (rr)+ - fPD, // pre decrementation -(rr) - fDISP // displacement rrx(rry) -}; - -inline bool is_jmp_cc(int insn) -{ - return insn == st9_jpcc || insn == st9_jrcc; -} - -//------------------------------------------------------------------ -struct st9_iohandler_t : public iohandler_t -{ - struct st9_t ± - st9_iohandler_t(st9_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct st9_t); - -struct st9_t : public procmod_t -{ - // The netnode helper. - // Using this node we will save current configuration information in the - // IDA database. - netnode helper; - st9_iohandler_t ioh = st9_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - const char *RegNames[st9_lastreg + 1]; - qstrvec_t dynamic_rgnames; // dynamically generated names for rR1..rR255 - - const char *gr_cmt = nullptr; - int ref_dpr_id; // id of refinfo handler - uint32 idpflags; // Current configuration parameters - ushort print_style = 3; - bool flow; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const ioport_t *find_sym(ea_t address); - void patch_general_registers(); - uint32 refresh_idpflags(void); - const char *set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool idb_loaded); - - int st9_emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &op, bool lwrite); - bool create_func_frame(func_t *pfn) const; - - void st9_assumes(outctx_t &ctx); - void st9_footer(outctx_t &ctx) const; - void st9_segstart(outctx_t &ctx, segment_t *Sarea) const; -}; - -// exporting our routines -void idaapi st9_header(outctx_t &ctx); -int idaapi st9_ana(insn_t *insn); -ea_t get_dest_addr(const insn_t &insn, const op_t &x); -bool st9_is_switch(switch_info_t *si, const insn_t &insn); - -extern const char *const ConditionCodes[]; - -#endif /* __ST9_HPP */ diff --git a/idasdk75/module/tlcs900/ana.cpp b/idasdk75/module/tlcs900/ana.cpp deleted file mode 100644 index 594cb56..0000000 --- a/idasdk75/module/tlcs900/ana.cpp +++ /dev/null @@ -1,1111 +0,0 @@ -/* - * TLCS900 processor module for IDA. - * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "tosh.hpp" - -// (number of bytes -1) -> dtype -static const uchar bt_type[4]= { dt_byte, dt_word, dt_tbyte, dt_dword }; - -// power of 2 -> dtype -static const uchar btp_type[4]= { dt_byte, dt_word, dt_dword, uchar(-1) }; - -// memory reference (o_mem/o_displ) -struct MemRefDef -{ - uint32 disp; // offset - ushort off_pos; // place of offset in insn (if any) - optype_t type; // dtype: o_mem/o_displ - uchar flags; // flags - uchar base_reg; // base reg - uchar add_reg; // additional reg (DAfull number) - uchar inc_size; // increment size (+/-4) - uchar dtype; -}; - -//----------------------------------------------------------------------------- -// short reg to full reg -static uchar Reg7ToFull(uchar reg7, uchar size) -{ - reg7&=7; // fix reg number - // byte reg - if ( size == 0 ) - return 0xE0+(1-(reg7&1))+(reg7&6)*2; - // word or double wor dreg - return 0xE0+reg7*4; -} - -//----------------------------------------------------------------------------- -// set number of the reg into operand -// reg_code - byte reg num -// size - 0,1,2 (2^x bytes) -static void SetRegistr(op_t &op, uchar reg_code, uchar size) -{ - op.type=o_reg; - op.addr=op.value=reg_code; - op.dtype = btp_type[size&3]; -} - -//----------------------------------------------------------------------------- -// set register -// regcode - reg number (3 bits) -// size - 0,1,2 (2^x bytes) -static void SetRegistr7(op_t &op, uchar regcode, uchar size) -{ - SetRegistr(op, Reg7ToFull(regcode, size), size); -} - -//----------------------------------------------------------------------------- -// load N ibytes and return result -static uint32 LoadDataValue(insn_t &insn, int bytes) -{ - uint32 val=0; - for ( int i=0; i < bytes; i++ ) - val |= ((uint32)insn.get_next_byte())<<(8*i); - return val; -} - -//----------------------------------------------------------------------------- -// currnet bytes are the memory address -// len - number of bytes -static void SetDirectMemRef(insn_t &insn, op_t &op, int len) -{ - op.type = o_mem; - // elem offset - op.offb = (uchar)insn.size; - // size of offset - op.dtype = bt_type[(len-1)&3]; - // elem value - op.addr = op.value = LoadDataValue(insn, len); -} - -//----------------------------------------------------------------------------- -// code ref -static void SetJmp(insn_t &insn, op_t &op, int len) -{ - op.type = o_near; - op.offb = (uchar)insn.size; - op.dtype = dt_dword; - if ( len > 0 ) - { - // absolute - op.addr=op.value=LoadDataValue(insn, len); - } - else - { - // relative - len=-len; - op.addr=LoadDataValue(insn, len); - // sig - if ( op.addr&(uval_t(1)<<(8*len-1)) ) - { - op.addr|=BADADDR<<(8*len); - } - // target offset - op.addr+=insn.ip+insn.size; - op.value=op.addr; - } -} - -//----------------------------------------------------------------------------- -// MemRef to Operand -static void MemRefToOp(op_t &op, const MemRefDef &mr) -{ - op.value = mr.disp; - op.addr = mr.disp; - op.dtype = mr.dtype; - op.reg = mr.base_reg; - op.specflag2 = mr.inc_size; - op.offb = (uchar)mr.off_pos; - op.specval_shorts.low = mr.add_reg; - op.specflag1 = mr.flags; - op.type = mr.type; -} - -//----------------------------------------------------------------------------- -// load memory ref -// first_code - firt insn byte -static int LoadMemRef(insn_t &insn, MemRefDef &mr, uchar first_code) -{ - memset(&mr, 0, sizeof(mr)); - mr.dtype = btp_type[(first_code>>4)&3]; - if ( (first_code&0x40) == 0 ) - { - // ref is reg (with offset or not) - mr.type = o_displ; - // reg name - mr.base_reg = Reg7ToFull(first_code, 2); - if ( first_code&0x8 ) - { - // offset - mr.off_pos = insn.size; - mr.disp = insn.get_next_byte(); - } - } - else - { - switch ( first_code & 7 ) - { - // direct, byte - case 0: - mr.off_pos = insn.size; - mr.disp = LoadDataValue(insn, 1); - mr.type = o_mem; - break; - // direct, word - case 1: - mr.off_pos = insn.size; - mr.disp = LoadDataValue(insn, 2); - mr.type = o_mem; - break; - // direct, 24 bit - case 2: - mr.off_pos=insn.size; - mr.disp=LoadDataValue(insn, 3); - mr.type=o_mem; - break; - // two regs - case 3: - { - uchar mem_val; - mr.type = o_displ; - mem_val = insn.get_next_byte(); - if ( (mem_val&2) == 0 ) - { - // with reg - mr.base_reg = mem_val & 0xFC; - // and ofsset? - if ( mem_val&1 ) - { - mr.off_pos = insn.size; - mr.disp = LoadDataValue(insn, 2); - } - } - else - { // two regs - if ( (mem_val&1) == 0 ) - return 0; // wrong - if ( (mem_val>>2) > 1 ) - { - // LDAR! - // check for F3/13 - //msg("Ldar Op"); - if ( first_code == 0xF3 && mem_val == 0x13 ) - { - // yes! - insn.itype=T900_ldar; - // elem offset - insn.Op2.offb=(uchar)insn.size; - uint32 target=LoadDataValue(insn, 2); - target+=uint32(insn.ea+4); - insn.Op2.type=o_mem; - // size of offset - insn.Op2.dtype = dt_word; - // elem value - insn.Op2.addr = insn.Op2.value = target; - // get reg - mem_val=insn.get_next_byte(); - // available? - if ( (mem_val&0xE8) != 0x20 ) - return 0; - SetRegistr7(insn.Op1, mem_val, ((mem_val>>4)-1)&3); - //msg("ldar ok"); - return 1; - } - return 0; - } - mr.base_reg = insn.get_next_byte(); // 1st reg - mr.add_reg = insn.get_next_byte(); // 2nd reg - if ( mem_val & 0x4 ) - mr.flags|=URB_WORD;// 2nd reg - word - } - } - break; - // inc/dec - case 4: - case 5: - { - uchar regg = insn.get_next_byte(); - if ( (regg&3) == 3 ) - return 0; - mr.type = o_displ; - mr.base_reg = regg&0xFC; - mr.inc_size = 1<<(regg&3); - // negative inc - if ( (first_code&1) == 0 ) - mr.inc_size|=URB_DECR; - } - break; - } - } - return 1; -} - -//----------------------------------------------------------------------------- -static void SetImmData(insn_t &insn, op_t &op, int bytes) -{ - op.type = o_imm; - op.offb = (uchar)insn.size; - op.dtype = bt_type[(bytes-1)&3]; - op.addr = op.value = LoadDataValue(insn, bytes); -} - -//----------------------------------------------------------------------------- -static void SetImm8Op(op_t &op, uchar code) -{ - op.type = o_imm; - op.dtype = dt_byte; // actually, it is not a byte - op.flags |= OF_NUMBER; - op.addr = op.value = code; -} - -//----------------------------------------------------------------------------- -// set imm3 for inc/dec -static void SetImm3Op(op_t &op, uchar code) -{ - code &= 7; - SetImm8Op(op, code ? code : 8); -} - -//----------------------------------------------------------------------------- -// condition phrase -static void SetCondOp(op_t &op, int cond) -{ - static const uchar cond_p[16] = - { - fCF, fCLT, fCLE, fCULE, fCPE, fCMI, fCZ, fCC, - fCT, fCGE, fCGT, fCUGT, fCPO, fCPL, fCNZ, fCNC - }; - op.type = o_phrase; - op.phrase = cond_p[cond&0xf]; -} - -//----------------------------------------------------------------------------- -// arith insns -static const uchar Add_List[8] = -{ - T900_add, T900_adc, T900_sub, T900_sbc, - T900_and, T900_xor, T900_or, T900_cp -}; - -// shift insns (not simple) -static const uchar Shift_List[8] = -{ - T900_rlc, T900_rrc, T900_rl, T900_rr, - T900_sla, T900_sra, T900_sll, T900_srl -}; - -// shift for memory cells -static const uchar Shift_List1[8] = -{ - T900_rlc_mem, T900_rrc_mem, T900_rl_mem, T900_rr_mem, - T900_sla_mem, T900_sra_mem, T900_sll_mem, T900_srl_mem -}; - -// flag C -static const uchar COp_List[5] = -{ - T900_andcf, T900_orcf, T900_xorcf, T900_ldcf, T900_stcf -}; - -// other flag C -static const uchar COp2_List[5] = -{ - T900_res, T900_set, T900_chg, T900_bit, T900_tset -}; - -//----------------------------------------------------------------------------- -// parse regs -static int RegAnalyser(insn_t &insn, uchar code) -{ - static const uchar reg_codes[32] = - { - 255, 255, 255, 255, - T900_andcf, T900_andcf, T900_res, T900_minc1, - T900_mul, T900_muls, T900_div, T900_divs, - T900_inc, T900_dec, T900_scc, T900_scc, - T900_add, T900_ld, T900_adc, T900_ld, - T900_sub, T900_ld, T900_sbc, T900_ex, - T900_and, 254, T900_xor, 253, - T900_or, T900_rlc, T900_cp, T900_rlc - }; - uchar reg_size = (code>>4) & 3; // 0 - byte, 1 - word, 2 - long - uchar reg_num; // byte reg number - if ( code & 8 ) - { - reg_num = Reg7ToFull(code, reg_size); - } - else - { // aux byte - reg_num = insn.get_next_byte(); - } - uchar reg_op = 0; // Op1 is reg by default - uchar reg_byte = insn.get_next_byte(); - insn.itype = reg_codes[(reg_byte>>3)&0x1F]; - switch ( insn.itype ) - { - case T900_ex: - case T900_add: - case T900_adc: - case T900_sub: - case T900_sbc: - case T900_and: - case T900_xor: - case T900_or: - case T900_cp: - SetRegistr7(insn.Op1, reg_byte, reg_size); - reg_op=1; - break; - - case 255: - { - static const uchar LCodes[] = - { - 0, 0, 0, T900_ld, - T900_push, T900_pop, T900_cpl, T900_neg, - T900_mul, T900_muls, T900_div, T900_divs, - T900_link, T900_unlk, T900_bs1f, T900_bs1b, - T900_daa, 0, T900_extz, T900_exts, - T900_paa, 0, T900_mirr, 0, - 0, T900_mula, 0, 0, - T900_djnz, 0, 0, 0 - }; - - if ( reg_byte >= qnumber(LCodes) ) - return 0; - - insn.itype = LCodes[reg_byte]; - switch ( insn.itype ) - { - // illegal - case 0: - return 0; - - // LD r, # - case T900_ld: - SetImmData(insn, insn.Op2, 1<<reg_size); - break; - - // MUL rr, # - // DIV rr, # - case T900_div: - case T900_divs: - case T900_mul: - case T900_muls: - SetImmData(insn, insn.Op2, 1<<reg_size); - // hig reg used - reg_size++; - if ( reg_size == 3 ) - return 0; - break; - - // LINK r, dd - case T900_link: - SetImmData(insn, insn.Op2, 2); - break; - - // BS1F A,r - case T900_bs1f: - case T900_bs1b: - SetRegistr7(insn.Op1, 1, 0); - reg_op=1; - break; - // MULA r - case T900_mula: - // high reg used - reg_size++; - if ( reg_size == 3 ) - return 0; - break; - // DJNZ r, d - case T900_djnz: - //if ( reg_num == 0 ){ - // // exception for reg=0 - // SetJmp(insn, insn.Op1,-1); - // return(insn.size); - //} - SetJmp(insn, insn.Op2, -1); - break; - } - } - break; - - // ANDCF-STCF XXX #, r - case T900_andcf: - if ( reg_byte > 0x2C ) - { - switch ( reg_byte ) - { - case 0x2D: - return 0; - // compilcated insn LDC - skip it for now - case 0x2E: - SetImmData(insn, insn.Op1, 1); - reg_op=1; - break; - case 0x2F: - SetImmData(insn, insn.Op2, 1); - break; - } - insn.itype=T900_ldc; - } - else if ( (reg_byte&7) < 5 ) // not an LDC - { - reg_op = 1; - insn.itype = COp_List[reg_byte&7]; - if ( reg_byte & 8 ) - SetRegistr7(insn.Op1, 1, 0); - else - SetImmData(insn, insn.Op1, 1); - } - else - { - return 0; - } - break; - - // RES-TSET - case T900_res: - if ( (reg_byte&7) > 4 ) - return 0; - insn.itype = COp2_List[reg_byte&7]; - SetImmData(insn, insn.Op1, 1); - reg_op = 1; - break; - - // MINC/MDEC - case T900_minc1: - { - static const uchar dinc[8] = - { - T900_minc1, T900_minc2, T900_minc4, 0, - T900_mdec1, T900_mdec2, T900_mdec4, 0 - }; - if ( (insn.itype=dinc[reg_byte&7]) == 0 ) - return 0; - SetImmData(insn, insn.Op1, 2); - // fix op - insn.Op1.value += uval_t(1)<<(reg_byte&3); - insn.Op1.addr = insn.Op1.value; - reg_op = 1; - } - break; - // mul/div XXX R, r - case T900_mul: - case T900_muls: - case T900_div: - case T900_divs: - SetRegistr7(insn.Op1, reg_size == 0 ? (reg_byte&7)/2 : reg_byte, reg_size+1); - reg_op=1; - break; - - // INC/DEC #3, r - case T900_inc: - case T900_dec: - SetImm3Op(insn.Op1, reg_byte); - reg_op=1; - break; - - // set SCC, r - case T900_scc: - SetCondOp(insn.Op1, reg_byte&0xF); - reg_op=1; - break; - // LD - case T900_ld: - if ( reg_byte < 0x90 ) - reg_op = 1; - if ( reg_byte < 0xA0 ) - SetRegistr7(insn.ops[1-reg_op], reg_byte, reg_size); - else - SetImm8Op(insn.Op2, reg_byte&7); - break; - - // another arithmetics XXX r, #) - case 254: - insn.itype=Add_List[reg_byte&7]; - SetImmData(insn, insn.Op2, 1<<reg_size); - break; - // CP r, #3 - case 253: - insn.itype=T900_cp; - SetImm8Op(insn.Op2, reg_byte&7); - break; - // shifts - case T900_rlc: - insn.itype=Shift_List[reg_byte&7]; - if ( reg_byte >= 0xF8 ) - { - SetRegistr7(insn.Op1, 1, 0); - } - else - { - uchar ShL = insn.get_next_byte(); - SetImm8Op(insn.Op1, ShL == 0 ? 16 : ShL); - } - reg_op = 1; - break; - default: - return 0; - } - // set reg - SetRegistr(insn.ops[reg_op], reg_num, reg_size); - return insn.size; -} - -//----------------------------------------------------------------------------- -// parse 2nd byte DST -static int DSTAnalyser(insn_t &insn, uchar code) -{ - // memory op number - char memrefop = 1; - MemRefDef mr; // memory ref - // main opcodes - static const uchar dst_codes[32] = - { - 255, 0, 255, 0, - T900_lda, 255, T900_lda, 0, - T900_ld, 0, T900_ldw, 0, - T900_ld, 0, 0, 0, - T900_andcf, T900_orcf, T900_xorcf, T900_ldcf, - T900_stcf, T900_tset, T900_res, T900_set, - T900_chg, T900_bit, T900_jp_cond, T900_jp_cond, - T900_call, T900_call, T900_ret_cond, T900_ret_cond - }; - // get mem ref - if ( LoadMemRef(insn, mr, code) == 0 ) - return 0; - // check for LDAR - if ( insn.itype == T900_ldar ) - return insn.size; - // opcode - uchar dst_byte = insn.get_next_byte(); - // need to check for mr.dtyp - byte by default - mr.dtype = dt_byte; - - insn.itype=dst_codes[(dst_byte>>3)&0x1F]; - switch ( insn.itype ) - { - case 0: - return 0; - - // go further - case 255: - if ( dst_byte < 0x2D && dst_byte >= 0x28 ) - { - // bit insn - insn.itype = COp_List[dst_byte-0x28]; - // reg A - SetRegistr7(insn.Op1, 1, 0); - // mem ref - break; - } - - switch ( dst_byte ) - { - // ld byte - case 0x00: - insn.itype=T900_ld; - SetImmData(insn, insn.Op2, 1); - memrefop=0; - break; - - // ld word - case 0x02: - insn.itype = T900_ldw; - SetImmData(insn, insn.Op2, 2); - mr.dtype = dt_word; - memrefop = 0; - break; - - // pop byte - case 0x04: - insn.itype=T900_pop; - memrefop=0; - break; - - // pop word - case 0x06: - insn.itype = T900_popw; - mr.dtype = dt_word; - memrefop = 0; - break; - - // ld byte xx - case 0x14: - insn.itype = T900_ld; - SetDirectMemRef(insn, insn.Op2, 2); - memrefop = 0; - break; - - // ld word - case 0x16: - insn.itype = T900_ldw; - SetDirectMemRef(insn, insn.Op2, 2); - mr.dtype = dt_word; - memrefop = 0; - break; - - - default: - return 0; - } - break; - // load 40, 50, 60 - case T900_ldw: - case T900_ld: - SetRegistr7(insn.Op2, dst_byte, (dst_byte>>4)&0x3); - mr.dtype = btp_type[(dst_byte>>4)&3]; - memrefop = 0; - break; - // load 20, 30 - case T900_lda: - { - uchar size = ((dst_byte>>4)&0x3)-1; - SetRegistr7(insn.Op1, dst_byte, size); - mr.dtype = btp_type[size]; - mr.flags |= URB_LDA|URB_LDA2;// address, not data! - } - break; - // branches - case T900_jp_cond: - if ( (dst_byte&0xF) == 0x8 ) - insn.itype=T900_jp; - // fallthrough - case T900_call: // set cond code - SetCondOp(insn.Op1, dst_byte&0xF); - mr.flags |= URB_LDA; // address, not data! - break; - // return - case T900_ret_cond: // 1st byte == 0xb0 - if ( code != 0xB0 ) - return 0; - if ( (dst_byte&0xF) == 0x8 ) - insn.itype=T900_ret; - SetCondOp(insn.Op1, dst_byte&0xF); - return insn.size; - - // ANDCF, .... - default: - SetImm8Op(insn.Op1, dst_byte&7); - break; - } - MemRefToOp(insn.ops[uchar(memrefop)], mr); - return insn.size; -} - -//----------------------------------------------------------------------------- -static int SRCAnalyser(insn_t &insn, uchar code) -{ - uchar memrefop=1; // number of operand with mem ref - MemRefDef mr; - static const uchar aa[] = - { - 255, 0, 255, 255, - T900_ld, 0, T900_ex, 254, - T900_mul, T900_muls, T900_div, T900_divs, - T900_inc, T900_dec, 0, 253, - T900_add, T900_add, T900_adc, T900_adc, - T900_sub, T900_sub, T900_sbc, T900_sbc, - T900_and, T900_and, T900_xor, T900_xor, - T900_or, T900_or, T900_cp, T900_cp - }; - - if ( LoadMemRef(insn, mr, code) == 0 ) - return 0; - uchar src_byte = insn.get_next_byte(); - insn.itype=aa[(src_byte>>3)&0x1F]; - uchar reg_size = (code>>4)&3; // 0, 1, 2 - switch ( insn.itype ) - { - case 0: - return 0; - - case 255: - switch ( src_byte ) - { - default: - return 0; - // push - case 4: - insn.itype=T900_push; - memrefop=0; - break; - // rld - case 6: - insn.itype=T900_rld; - SetRegistr7(insn.Op1, 1, 0); - break; - // rrd - case 7: - insn.itype=T900_rrd; - SetRegistr7(insn.Op1, 1, 0); - break; - // ldi - case 0x10: - insn.itype=T900_ldi; - mr.inc_size|=URB_UINC; - mr.base_reg--; - MemRefToOp(insn.Op1, mr); - mr.base_reg++; - if ( reg_size ) - insn.itype++; - break; - // ldir - case 0x11: - insn.itype=T900_ldir; - mr.inc_size|=URB_UINC; - mr.base_reg--; - MemRefToOp(insn.Op1, mr); - mr.base_reg++; - if ( reg_size ) - insn.itype++; - break; - // ldd - case 0x12: - insn.itype=T900_ldd; - mr.inc_size|=URB_UDEC; - mr.base_reg--; - MemRefToOp(insn.Op1, mr); - mr.base_reg++; - if ( reg_size ) - insn.itype++; - break; - // lddr - case 0x13: - insn.itype=T900_lddr; - mr.inc_size|=URB_UDEC; - mr.base_reg--; - MemRefToOp(insn.Op1, mr); - mr.base_reg++; - if ( reg_size ) - insn.itype++; - break; - // cpi - case 0x14: - insn.itype=T900_cpi; - mr.inc_size|=URB_UINC; - if ( reg_size ) - SetRegistr7(insn.Op1, 0, 1); - else - SetRegistr7(insn.Op1, 1, 0); - break; - // cpir - case 0x15: - insn.itype=T900_cpir; - mr.inc_size|=URB_UINC; - if ( reg_size ) - SetRegistr7(insn.Op1, 0, 1); - else - SetRegistr7(insn.Op1, 1, 0); - break; - // cpd - case 0x16: - insn.itype=T900_cpd; - mr.inc_size|=URB_UDEC; - if ( reg_size ) - SetRegistr7(insn.Op1, 0, 1); - else - SetRegistr7(insn.Op1, 1, 0); - break; - // cpdr - case 0x17: - insn.itype=T900_cpdr; - mr.inc_size|=URB_UDEC; - if ( reg_size ) - SetRegistr7(insn.Op1, 0, 1); - else - SetRegistr7(insn.Op1, 1, 0); - break; - // ld - case 0x19: - if ( code&0x10 ) - insn.itype=T900_ldw; - else - insn.itype=T900_ld; - SetDirectMemRef(insn, insn.Op1, 2); - break; - } - break; - // add and others - case 254: - insn.itype=Add_List[src_byte&7]; - SetImmData(insn, insn.Op2, 1<<((code>>4)&3)); - // word size - if ( reg_size != 0 ) - insn.itype++; - memrefop=0; - break; - // shifts xxxx (mem) - case 253: - insn.itype=Shift_List1[src_byte&7]; - // word size - if ( reg_size != 0 ) - insn.itype++; - memrefop=0; - break; - // inc - case T900_inc: - case T900_dec: - SetImm3Op(insn.Op1, src_byte); - // wor size - if ( reg_size != 0 ) - insn.itype++; - break; - - case T900_ld: - SetRegistr7(insn.Op1, src_byte, reg_size); - break; - // mul/div - case T900_mul: - case T900_div: - case T900_muls: - case T900_divs: - SetRegistr7(insn.Op1, reg_size == 0 ? (src_byte&7)/2 : src_byte, reg_size+1); - break; - // ex - case T900_ex: - SetRegistr7(insn.Op2, src_byte, reg_size); - memrefop=0; - break; - // add and others - case T900_add: - case T900_adc: - case T900_sub: - case T900_sbc: - case T900_and: - case T900_xor: - case T900_or: - case T900_cp: - if ( src_byte&0x8 ) - memrefop=0; - SetRegistr7(insn.ops[1-memrefop], src_byte, reg_size); - break; - } - MemRefToOp(insn.ops[memrefop], mr); - return insn.size; -} - -//----------------------------------------------------------------------------- -static void ClearOperand(op_t &op) -{ - op.dtype = dt_byte; - op.type = o_void; - op.specflag1 = 0; - op.specflag2 = 0; - op.offb = 0; - op.offo = 0; - op.reg = 0; - op.value = 0; - op.addr = 0; - op.specval = 0; -} - -//----------------------------------------------------------------------------- -int idaapi T900_ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - - ClearOperand(insn.Op1); - ClearOperand(insn.Op2); - ClearOperand(insn.Op3); - - uchar code = insn.get_next_byte(); - // split u pto two parts - if ( code&0x80 ) - { - // check for illegal - if ( (code&0xF8) == 0xF8 ) - { - // SWI (F8-FF) - insn.itype=T900_swi; - // trap number - SetImm8Op(insn.Op1, code&7); - // trap addres - is not working for now - insn.Op1.addr = 0xFFFF00+(code&7)*4; - insn.Op1.value = insn.Op1.addr; - return insn.size; - } - if ( code == 0xF7 ) - { - // LDX - insn.itype=T900_ldx; - // skip zero byte - if ( insn.get_next_byte() != 0 ) - return 0; - // address is in regs - SetDirectMemRef(insn, insn.Op1, 1); - // skip zero byte - if ( insn.get_next_byte() != 0 ) - return 0; - // data - SetImmData(insn, insn.Op2, 1); - // length is 6 bytes - insn.size = 6; - return insn.size; - } - // unknow codes (C6, D6, E6, F6) - if ( (code & 0xCF) == 0xC6 ) - return 0; - // large general reg (C8, D8, E8) - if ( (code & 0x48) == 0x48 ) - return RegAnalyser(insn, code); - // is smart reg ? (C7, D7, E7, F7) - if ( (code & 0xCF) == 0xC7 ) - return RegAnalyser(insn, code); - // memref - // segments dst (B0, B8, F0) - if ( (code & 0xB0) == 0xB0 ) - return DSTAnalyser(insn, code); - // src - return SRCAnalyser(insn, code); - } - // low part - else if ( code < 0x20 ) - { - static const uchar FirstOp[] = - { - T900_nop, T900_normal, T900_push, T900_pop, - T900_max, T900_halt, T900_ei, T900_reti, - T900_ld, T900_push, T900_ldw, T900_pushw, - T900_incf, T900_decf, T900_ret, T900_retd, - T900_rcf, T900_scf, T900_ccf, T900_zcf, - T900_push, T900_pop, T900_ex, T900_ldf, - T900_push, T900_pop, T900_jp, T900_jp, - T900_call, T900_call, T900_calr, 0 - }; - insn.itype = FirstOp[code]; - switch ( insn.itype ) - { - case 0x00: - return 0; - - case T900_push: - case T900_pop: - switch ( code&0x18 ) - { - case 0x00: - insn.Op1.type=o_phrase; - insn.Op1.phrase=fSR; - break; - // push only - case 0x08: - SetImmData(insn, insn.Op1, 1); - break; - // xxx A - case 0x10: - SetRegistr7(insn.Op1, 1, 0); - break; - // xxx F - case 0x18: - insn.Op1.type=o_phrase; - insn.Op1.phrase=fSF; - break; - } - break; - // ei - case T900_ei: // next byte is imm - SetImmData(insn, insn.Op1, 1); - if ( insn.Op1.value == 7 ) - { - insn.itype=T900_di; - insn.Op1.type=o_void; - } - break; - // ld (n), n - case T900_ld: - SetDirectMemRef(insn, insn.Op1, 1); - SetImmData(insn, insn.Op2, 1); - break; - - // ldw - case T900_ldw: - SetDirectMemRef(insn, insn.Op1, 1); - SetImmData(insn, insn.Op2, 2); - break; - // pushW - // retd - case T900_pushw: - case T900_retd: - SetImmData(insn, insn.Op1, 2); - break; - // ex F, F' - case T900_ex: - insn.Op1.type = o_phrase; - insn.Op1.phrase = fSF; - insn.Op2.type = o_phrase; - insn.Op2.phrase = fSF1; - break; - // ldf - case T900_ldf: - SetImmData(insn, insn.Op1, 1); - break; - - case T900_jp: - case T900_call: - SetJmp(insn, insn.Op1, 2+(code&1)); - insn.Op1.specflag1 |= URB_LDA; - break; - - // callr 16 - case T900_calr: - SetJmp(insn, insn.Op1, -2); - insn.Op1.specflag1 |= URB_LDA; - break; - } - } - else - { - switch ( code & 0x78 ) - { - // ld - case 0x20: - case 0x30: - case 0x40: - insn.itype=T900_ld; - SetRegistr7(insn.Op1, code, (code>>4)-2); - SetImmData(insn, insn.Op2, 1<<((code>>4)-2)); - break; - // push - case 0x28: - case 0x38: - insn.itype=T900_push; - SetRegistr7(insn.Op1, code, (code>>4)-1); - break; - // pop - case 0x48: - case 0x58: - insn.itype=T900_pop; - SetRegistr7(insn.Op1, code, (code>>4)-3); - break; - // reserved - case 0x50: - return 0; - // JR - case 0x60: - case 0x68: - if ( (code&0xF) == 0x8 ) - insn.itype = T900_jr; - else - insn.itype = T900_jr_cond; - SetCondOp(insn.Op1, code&0xF); - SetJmp(insn, insn.Op2, -1); - insn.Op2.specflag1|=URB_LDA; - break; - // JRL - case 0x70: - case 0x78: - if ( (code&0xF) == 0x8 ) - insn.itype=T900_jrl; - else - insn.itype=T900_jrl_cond; - SetCondOp(insn.Op1, code&0xF); - SetJmp(insn, insn.Op2, -2); - insn.Op2.specflag1 |= URB_LDA; - break; - } - } - return insn.size; -} diff --git a/idasdk75/module/tlcs900/makefile b/idasdk75/module/tlcs900/makefile deleted file mode 100644 index cef2471..0000000 --- a/idasdk75/module/tlcs900/makefile +++ /dev/null @@ -1,46 +0,0 @@ -PROC=tlcs900 -CONFIGS=tlcs900.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp tosh.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - emu.cpp ins.hpp tosh.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp tosh.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp tosh.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp reg.cpp tosh.hpp diff --git a/idasdk75/module/tlcs900/reg.cpp b/idasdk75/module/tlcs900/reg.cpp deleted file mode 100644 index d5dff06..0000000 --- a/idasdk75/module/tlcs900/reg.cpp +++ /dev/null @@ -1,248 +0,0 @@ -/* - * TLCS900 processor module for IDA. - * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#include "tosh.hpp" -#include <diskio.hpp> -#include <segregs.hpp> - -//-------------------------------------------------------------------------- -// registers -static const char *const RegNames[] = -{ - // zero reg - "", - // byte regs - "W", "A", "B", "C", "D", "E", "H", "L", - // word regs - "WA", "BC", "DE", "HL", "IX", "IY", "IZ", "SP", - // Double word regs - "XWA", "XBC", "XDE", "XHL", "XIX", "XIY", "XIZ", "XSP", - // strange regs - "IXL", "IXH", "IYL", "IYH", "IZL", "IZH", "SPL", "SPH", - // pesudo-seg regs - "cs", "ds" -}; - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new tlcs900_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi tlcs900_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - inf_set_be(false); - inf_set_gen_lzero(true); - helper.create("$ TLCS900"); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - { - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_creating_segm: - { - segment_t *s = va_arg(va, segment_t *); - // Set default value of DS register for all segments - set_default_dataseg(s->sel); - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - T900_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - T900_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - T900_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return T900_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return T900_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - T900_data(*ctx, analyze_only); - return 1; - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// PseudoSam -//----------------------------------------------------------------------- -static const asm_t pseudosam = -{ - AS_COLON | AS_UDATA | ASH_HEXF3, - 0, - "Generic IAR-style assembler", - 0, - NULL, - "org", - "end", - - ";", - '"', - '\'', - "\\\"'", - - "db", // ascii string directive - "DB", // byte directive - "DW", // word directive - "DL", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "#d dup(#v)", // arrays (#h,#d,#v,#s(...) - "db ?", // uninited arrays - ".equ", // equ - NULL, // seg prefix - "$", - NULL, - NULL, - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, - "align", - '(', // lbrace - ')', // rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &pseudosam, NULL }; -//----------------------------------------------------------------------- -#define FAMILY "Toshiba TLCS-900 series:" -static const char *const shnames[] = { "TLCS900", NULL }; -static const char *const lnames[] = { FAMILY"Toshiba TLCS900", NULL }; - -//-------------------------------------------------------------------------- -static const uchar retcode_1[] = { 0x0E }; // ret -static const uchar retcode_2[] = { 0x0F }; // ret d -static const uchar retcode_3[] = { 0x07 }; // reti -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_TLCS900, // id - // flag - PR_USE32 - | PR_BINMEM - | PR_SEGTRANS - | PR_DEFSEG32, - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Regsiter names - qnumber(RegNames), // Number of registers - - rVcs, rVds, - 2, // size of a segment register - rVcs, rVds, - NULL, - retcodes, - T900_null, T900_last, - Instructions, // instruc - 3, // tbyte - 24 bit - {0,0,0,0}, - 0, - NULL, -}; diff --git a/idasdk75/module/tlcs900/tosh.hpp b/idasdk75/module/tlcs900/tosh.hpp deleted file mode 100644 index f5d23f2..0000000 --- a/idasdk75/module/tlcs900/tosh.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * TLCS900 processor module for IDA. - * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> - * Freeware. - */ - -#ifndef _TOSH_HPP -#define _TOSH_HPP - -#include <ida.hpp> -#include <idp.hpp> - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include "../iohandler.hpp" - -//----------------------------------------------- -// Increment/decrement -#define URB_DECR (0x80) // decrement -#define URB_DCMASK (0x07) // mask or decrement -#define URB_UDEC (0x40) // singleton decrement -#define URB_UINC (0x20) // signleto increment - -// specflag1 bits -#define URB_WORD (1) // second index register is word -#define URB_LDA (2) // insn uses address not the content -#define URB_LDA2 (4) // same, but may constant! - -//------------------------------------------------------------------------ -enum T900_registers -{ - rNULLReg, - rW, rA, rB, rC, rD, rE, rH, rL, - rWA, rBC, rDE, rHL, rIX, rIY, rIZ, rSP, - rXWA, rXBC, rXDE, rXHL, rXIX, rXIY, rXIZ, rXSP, - rIXL, rIXH, rIYL, rIYH, rIZL, rIZH, rSPL, rSPH, - rVcs, rVds -}; - -// phrases -enum T900_phrases -{ - rNULLPh, - fCF,fCLT,fCLE,fCULE,fCPE,fCMI,fCZ,fCC, - fCT,fCGE,fCGT,fCUGT,fCPO,fCPL,fCNZ,fCNC, - fSF,fSF1, - fSR, fPC -}; - -//------------------------------------------------------------------ -struct tlcs900_iohandler_t : public iohandler_t -{ - tlcs900_iohandler_t(netnode &nn) : iohandler_t(nn) {} -}; - -struct tlcs900_t : public procmod_t -{ - netnode helper; - tlcs900_iohandler_t ioh = tlcs900_iohandler_t(helper); - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); - - int T900_emu(const insn_t &insn); - void T900_header(outctx_t &ctx); - void T900_segstart(outctx_t &ctx, segment_t *Sarea) const; - void T900_footer(outctx_t &ctx) const; -}; - -//------------------------------------------------------------------------ -int idaapi T900_ana(insn_t *_insn); - -void idaapi T900_data(outctx_t &ctx, bool analyze_only); - -#endif diff --git a/idasdk75/module/tms320c1/makefile b/idasdk75/module/tms320c1/makefile deleted file mode 100644 index 6342979..0000000 --- a/idasdk75/module/tms320c1/makefile +++ /dev/null @@ -1,51 +0,0 @@ -PROC=tms320c1 -O1=idp -O2=asms - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp ins.hpp reg.hpp tms320c1.hpp -$(F)asms$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - asms.cpp asms.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp emu.cpp ins.hpp reg.hpp tms320c1.hpp -$(F)idp$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.hpp asms.hpp idp.cpp ins.hpp out.hpp reg.hpp \ - tms320c1.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ins.hpp out.cpp out.hpp reg.hpp -$(F)reg$(O) : reg.cpp reg.hpp diff --git a/idasdk75/module/tms320c1/tms320c1.hpp b/idasdk75/module/tms320c1/tms320c1.hpp deleted file mode 100644 index c30bef6..0000000 --- a/idasdk75/module/tms320c1/tms320c1.hpp +++ /dev/null @@ -1,210 +0,0 @@ -// $Id: tms320c1.hpp,v 1.8 2000/11/06 22:11:17 jeremy Exp $ -// -// Copyright (c) 2000 Jeremy Cooper. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// 3. All advertising materials mentioning features or use of this software -// must display the following acknowledgement: -// This product includes software developed by Jeremy Cooper. -// 4. The name of the author may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR -// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES -// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. -// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT -// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF -// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// -// IDA TMS320C1X processor module. -// TMS320C1X constants, etc. -// -#ifndef _IDP_TMS320C1X_H -#define _IDP_TMS320C1X_H - -////////////////////////////////////////////////////////////////////////////// -// TMS320C1X Instruction Opcodes -// -// To ease decoding requirements, we have classified each TMS320C1X -// instruction by the number of significant bits that need to be scanned in -// the instruction opcode in order to uniquely identify it. -// - -// -// Bit scanning masks -// -#define ISN_3_BIT_MASK 0xe000 // 111x xxxx xxxx xxxx -#define ISN_4_BIT_MASK 0xf000 // 1111 xxxx xxxx xxxx -#define ISN_5_BIT_MASK 0xf800 // 1111 1xxx xxxx xxxx -#define ISN_7_BIT_MASK 0xfe00 // 1111 111x xxxx xxxx -#define ISN_8_BIT_MASK 0xff00 // 1111 1111 xxxx xxxx -#define ISN_15_BIT_MASK 0xfffe // 1111 1111 1111 111x -#define ISN_16_BIT_MASK 0xffff // 1111 1111 1111 1111 - -// -// 3 bit Opcodes -// -enum isn_3bit -{ - ISN3_MPYK = 0x8000, // 100... -}; -// -// 4 bit Opcodes -// -enum isn_4bit -{ - ISN4_ADD = 0x0000, // 0000... - ISN4_LAC = 0x2000, // 0100... - ISN4_SUB = 0x1000, // 0001... -}; -// -// 5 bit Opcodes -// -enum isn_5bit -{ - ISN5_SACH = 0x5800, // 0101 1... - ISN5_IN = 0x4000, // 0100 0... - ISN5_OUT = 0x4800, // 0100 1... -}; -// -// 7 bit Opcodes -// -enum isn_7bit -{ - ISN7_LAR = 0x3800, // 0011 100... - ISN7_LARK = 0x7000, // 0111 000... - ISN7_SAR = 0x3000, // 0011 000... -}; -// -// 8 bit Opcodes -// -enum isn_8bit -{ - ISN8_ADDH = 0x6000, // 0110 0000 ... - ISN8_ADDS = 0x6100, // 0110 0001 ... - ISN8_AND = 0x7900, // 0111 1001 ... - ISN8_LACK = 0x7e00, // 0111 1110 ... - ISN8_OR = 0x7a00, // 0111 1010 ... - ISN8_SACL = 0x5000, // 0101 0000 ... - ISN8_SUBC = 0x6400, // 0110 0100 ... - ISN8_SUBH = 0x6200, // 0110 0010 ... - ISN8_SUBS = 0x6300, // 0110 0011 ... - ISN8_XOR = 0x7800, // 0111 1000 ... - ISN8_ZALH = 0x6500, // 0110 0101 ... - ISN8_ZALS = 0x6600, // 0110 0110 ... - ISN8_LDP = 0x6f00, // 0110 1111 ... - ISN8_MAR = 0x6800, // 0110 1000 ... - ISN8_LT = 0x6a00, // 0110 1010 ... - ISN8_LTA = 0x6c00, // 0110 1100 ... - ISN8_LTD = 0x6b00, // 0110 1011 ... - ISN8_MPY = 0x6d00, // 0110 1101 ... - ISN8_LST = 0x7b00, // 0111 1101 ... - ISN8_SST = 0x7c00, // 0111 1100 ... - ISN8_DMOV = 0x6900, // 0110 1001 ... - ISN8_TBLR = 0x6700, // 0110 0111 ... - ISN8_TBLW = 0x7d00, // 0111 1101 ... -}; -// -// 15 bit Opcodes -// -enum isn_15bit -{ -// LARP is a synonym for a special case of MAR -//ISN15_LARP = 0x6880, // 0110 1000 1000 000. - ISN15_LDPK = 0x6e00, // 0110 1110 0000 000. -}; -// -// 16 bit Opcodes -// -enum isn_16bit -{ - ISN16_ABS = 0x7f88, // 0111 1111 1000 1000 - ISN16_ZAC = 0x7f89, // 0111 1111 1000 0101 - ISN16_APAC = 0x7f8f, // 0111 1111 1000 1111 - ISN16_PAC = 0x7f8e, // 0111 1111 1000 1110 - ISN16_SPAC = 0x7f90, // 0111 1111 1001 0000 - ISN16_B = 0xf900, // 1111 1001 0000 0000 - ISN16_BANZ = 0xf400, // 1111 0100 0000 0000 - ISN16_BGEZ = 0xfd00, // 1111 1101 0000 0000 - ISN16_BGZ = 0xfc00, // 1111 1100 0000 0000 - ISN16_BIOZ = 0xf600, // 1111 0110 0000 0000 - ISN16_BLEZ = 0xfb00, // 1111 1011 0000 0000 - ISN16_BLZ = 0xfa00, // 1111 1010 0000 0000 - ISN16_BNZ = 0xfe00, // 1111 1110 0000 0000 - ISN16_BV = 0xf500, // 1111 0101 0000 0000 - ISN16_BZ = 0xff00, // 1111 1111 0000 0000 - ISN16_CALA = 0x7f8c, // 0111 1111 1000 1100 - ISN16_CALL = 0xf800, // 1111 1000 0000 0000 - ISN16_RET = 0x7f8d, // 0111 1111 1000 1101 - ISN16_DINT = 0x7f81, // 0111 1111 1000 0001 - ISN16_EINT = 0x7f82, // 0111 1111 1000 0010 - ISN16_NOP = 0x7f80, // 0111 1111 1000 0000 - ISN16_POP = 0x7f9d, // 0111 1111 1001 1101 - ISN16_PUSH = 0x7f9c, // 0111 1111 1001 1100 - ISN16_ROVM = 0x7f8a, // 0111 1111 1000 1010 - ISN16_SOVM = 0x7f8b, // 0111 1111 1000 1011 -}; - -// -// Instruction property macros. -// These macros deduce certain facts about the instruction. -// -#define ISN_IMM1(op) ((op) & 0x0001) // Immediate 1 bit value -#define ISN_IMM8(op) ((op) & 0x00ff) // Immediate 8 bit value -#define ISN_IMM13(op) ((op) & 0x1fff) // Immediate 13 bit value -#define ISN_DIRECT(op) (!((op) & 0x0080)) // Direct/Indirect reference flag -#define ISN_DIR_ADDR(op) ((op) & 0x007f) // Direct memory location -#define ISN_INDIR_INCR(op) ((op) & 0x0020) // Aux reg. post-increment flag -#define ISN_INDIR_DECR(op) ((op) & 0x0010) // Aux reg. post-decrement flag -#define ISN_INDIR_NARP(op) ((op) & 0x0008) // Aux reg. change flag -#define ISN_INDIR_ARP(op) ((op) & 0x0001) // New aux reg. pointer value -#define ISN_AUX_AR(op) ((op) & 0x0100) // Aux register index -#define ISN_SHIFT(o) (((o)&0x0f00)>>8) // Data bit shift amount -#define ISN_PORT(o) (((o)&0x0700)>>8) // I/O port number - -// -// TMS320C1X environment facts. -// These macros define the size of the TMS320C1X's addressable -// data RAM. -// -#define TMS320C1X_DATA_RAM_SIZE 256 // 256 bytes - -// -// Reference type. Used between emu() and handle_operand() to -// flag whether an operand is written to or read from. -// -enum opRefType -{ - hop_READ, - hop_WRITE, -}; - -struct tms320c1_t : public procmod_t -{ - sel_t tms320c1x_dpage0; // Data page 0 selector - sel_t tms320c1x_dpage1; // Data page 1 selector - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - // Kernel message handlers. - void tms320c1x_Init() const; - void tms320c1x_NewFile(); - - int emu(const insn_t &insn) const; - bool handle_operand(const insn_t &insn, const op_t &op, opRefType ref_type) const; -}; - -#endif // IDP_TMS320C1X_H diff --git a/idasdk75/module/tms320c3/ana.cpp b/idasdk75/module/tms320c3/ana.cpp deleted file mode 100644 index 6c4902a..0000000 --- a/idasdk75/module/tms320c3/ana.cpp +++ /dev/null @@ -1,932 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Texas Instruments's TMS5320C3X - * - */ - -#include "tms320c3x.hpp" - -#define FUNCS_COUNT 3 - -struct ctx_t -{ - insn_t &insn; - op_t *op; - ctx_t(insn_t *i) : insn(*i) { op = &i->Op1; } -}; - -struct funcdesc_t -{ - bool (*func)(ctx_t &ctx, int); - uint32 mask; - uint32 shift; -}; - -struct opcode_t -{ - uint16 itype; - unsigned int insnidx; //lint !e958 padding is required to align members - funcdesc_t funcs[FUNCS_COUNT]; - uchar itype2; - funcdesc_t funcs2[FUNCS_COUNT]; //lint !e958 padding is required to align members - bool ispar; -}; - -//---------------------------------------------------------------------- -//lint -esym(1764, ctx) could be declared const -inline void opreg(ctx_t &ctx, uint16 reg) -{ - ctx.op->type = o_reg; - ctx.op->dtype = dt_byte; - ctx.op->reg = reg; -} - -//---------------------------------------------------------------------- -static void make_o_mem(ctx_t &ctx) -{ - switch ( ctx.insn.itype ) - { - case TMS320C3X_BR: - case TMS320C3X_BRD: - case TMS320C3X_CALL: - case TMS320C3X_RPTB: - case TMS320C3X_Bcond: - case TMS320C3X_DBcond: - case TMS320C3X_CALLcond: - ctx.op->type = o_near; - ctx.op->dtype = dt_code; - return; - } - ctx.op->type = o_mem; - ctx.op->dtype = dt_byte; -} - -//---------------------------------------------------------------------- -static bool D_adr24(ctx_t &ctx, int value) -{ - ctx.op->addr = value & 0xffffff; - make_o_mem(ctx); - return true; -} - -//---------------------------------------------------------------------- -static bool D_PC_Displ(ctx_t &ctx, int value) -{ - int16 disp = value & 0xffff; - - if ( value & 0x200000 ) - D_adr24(ctx, ctx.insn.ea + disp + 3); // delayed branch - else - D_adr24(ctx, ctx.insn.ea + disp + 1); - - return true; -} - -//---------------------------------------------------------------------- -static bool imm8(ctx_t &ctx, int value) -{ - ctx.op->type = o_imm; - ctx.op->dtype = dt_byte; - ctx.op->value = value & 0xff; - return true; -} - -//---------------------------------------------------------------------- -static bool D_regs(ctx_t &ctx, int value) // interpret register numbers -{ - if ( (value & 0x1f) > 0x1b ) - return false; - - if ( (value & 0x1f) == 0x10 ) - value = 0x1b; //remap DP reg - else if ( (value & 0x1f) > 0x10 ) - value = (value & 0x1f) - 1; - opreg(ctx, value & 0x1f); - return true; -} - -//---------------------------------------------------------------------- -static bool S_regs(ctx_t &ctx, int value) -{ - if ( D_regs(ctx, value) ) - { - ctx.op++; - return true; - } - return false; -} -//---------------------------------------------------------------------- -static bool D_R(ctx_t &ctx, int value) // interpret Rx register numbers -{ - if ( D_regs(ctx, value & 0x07) ) - return true; - else - return false; -} - -//---------------------------------------------------------------------- -static bool S_R(ctx_t &ctx, int value) -{ - if ( D_R(ctx, value) ) - { - ctx.op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -static bool D_R2(ctx_t &ctx, int value) -{ - return D_regs(ctx, r2 + (value & 0x07)); -} - -//---------------------------------------------------------------------- -static bool D_ar(ctx_t &ctx, int value) -{ - return D_regs(ctx, ar0 + (value & 0x07)); -} - -//---------------------------------------------------------------------- -static bool S_ar(ctx_t &ctx, int value) // interpret ARx register numbers -{ - if ( D_ar(ctx, value) ) - { - ctx.op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -static bool D_indir(ctx_t &ctx, int value) // indirect addressing -{ - ctx.op->type = o_phrase; - ctx.op->dtype = dt_byte; - ctx.op->phrase = ( value & 0xf800 ) >> 11; - ctx.op->phtype = ar0 + ((value >> 8) & 0x07); - ctx.op->addr = value & 0xff; - return true; -} - -//---------------------------------------------------------------------- -static bool S_indir(ctx_t &ctx, int value) -{ - if ( D_indir(ctx, value) ) - { - ctx.op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -static bool D_indir3(ctx_t &ctx, int value) // indirect addressing for 3-operand and parallel instructions -{ - ctx.op->type = o_phrase; - ctx.op->dtype = dt_byte; - ctx.op->phrase = ( value & 0xf8 ) >> 3; // indirect addressing type - ctx.op->phtype = ar0 + (value & 0x07); // register no - ctx.op->addr = 1; // offset (if present) - return true; - -} -//---------------------------------------------------------------------- -static bool S_indir3(ctx_t &ctx, int value) -{ - if ( D_indir3(ctx, value) ) - { - ctx.op++; - return true; - } - return false; -} - -//---------------------------------------------------------------------- -static bool SSD_src3(ctx_t &ctx, int value) // 3-operand instructions parsing -{ - switch ( (value >> 16) & 0x60 ) - { - case 0x00: - S_regs(ctx, value & 0xff); - S_regs(ctx, (value >> 8) & 0xff); - D_regs(ctx, (value >> 16) & 0x1f); - break; - - case 0x20: - S_regs(ctx, value & 0xff); - S_indir3(ctx, (value >> 8) & 0xff); - D_regs(ctx, (value >> 16) & 0x1f); - break; - - case 0x40: - S_indir3(ctx, value & 0xff); - S_regs(ctx, (value >> 8) & 0xff); - D_regs(ctx, (value >> 16) & 0x1f); - break; - - case 0x60: - S_indir3(ctx, value & 0xff); - S_indir3(ctx, (value >> 8) & 0xff); - D_regs(ctx, (value >> 16) & 0x1f); - break; - - default: - return false; - } - return true; -} - -//---------------------------------------------------------------------- -static bool SD_src3_2op(ctx_t &ctx, int value) // parsing of 3-operand instructions which use only two -{ - switch ( (value >> 16) & 0x60 ) - { - case 0x00: - S_regs(ctx, value & 0xff); - D_regs(ctx, (value >> 8) & 0xff); - break; - case 0x20: - S_regs(ctx, value & 0xff); - D_indir3(ctx, (value >> 8) & 0xff); - break; - case 0x40: - S_indir3(ctx, value & 0xff); - D_regs(ctx, (value >> 8) & 0xff); - break; - case 0x60: - S_indir3(ctx, value & 0xff); - D_indir3(ctx, (value >> 8) & 0xff); - break; - default: - return false; - } - return true; -} - -//---------------------------------------------------------------------- -static bool DBranch(ctx_t &ctx, int /*value*/) // set delayed branch flag -{ - ctx.insn.auxpref |= DBrFlag; - return true; -} - -//---------------------------------------------------------------------- -static bool ImmFlt(ctx_t &ctx, int /*value*/) // set floating-point constand flag -{ - ctx.insn.auxpref |= ImmFltFlag; - return true; -} - -//---------------------------------------------------------------------- -static bool cond(ctx_t &ctx, int value) // parse condition codes -{ - if ( ((value & 0x1f) > 0x14 ) || ((value & 0x1f) == 0x0b ) ) - return false; - - ctx.insn.auxpref |= value & 0x1f; - - if ( (ctx.insn.auxpref & 0x1f) == 0 ) // Upgrade retscond to retsu - { - switch ( ctx.insn.itype ) - { - case TMS320C3X_RETIcond: - ctx.insn.itype = TMS320C3X_RETIU; - break; - - case TMS320C3X_RETScond: - ctx.insn.itype = TMS320C3X_RETSU; - break; - } - } - if ( value & 0x20 ) - DBranch(ctx, 0); //delayed branch - return true; -} -//---------------------------------------------------------------------- -static bool SD_adres(ctx_t &ctx, int value) // main addressing -{ - switch ( (value >> 16) & 0x60 ) - { - case 0x00: - S_regs(ctx, value & 0xff); - D_regs(ctx, (value >> 16) & 0x1f); - break; - - case 0x20: - ctx.op->addr = value & 0xffff; - make_o_mem(ctx); - ctx.op++; - D_regs(ctx, (value >> 16) & 0x1f); - break; - - case 0x40: - S_indir(ctx, value & 0xffff); - D_regs(ctx, (value >> 16) & 0x1f); - break; - - case 0x60: - ctx.op->type = o_imm; - ctx.op->dtype = dt_byte; - ctx.op->value = value & 0xffff; - ctx.op++; - D_regs(ctx, (value >> 16) & 0x1f); - break; - - default: - return false; - } - return true; -} - -//---------------------------------------------------------------------- -static bool SD_adresRev(ctx_t &ctx, int value) // main addressing with reversed operands -{ - switch ( (value >> 16) & 0x60 ) - { - case 0x00: - S_regs(ctx, (value >> 16) & 0x1f); - D_regs(ctx, value & 0xff); - break; - - case 0x20: - S_regs(ctx, (value >> 16) & 0x1f); - ctx.op->addr = value & 0xffff; - make_o_mem(ctx); - break; - - case 0x40: - S_regs(ctx, (value >> 16) & 0x1f); - D_indir(ctx, value & 0xffff); - break; - - case 0x60: - S_regs(ctx, (value >> 16) & 0x1f); - ctx.op->type = o_imm; - ctx.op->dtype = dt_byte; - ctx.op->value = value & 0xffff; - break; - - default: - return false; - } - return true; -} -//---------------------------------------------------------------------- -static bool D_adres_1Op(ctx_t &ctx, int value) // main addressing using only one operand -{ - switch ( (value >> 16) & 0x60 ) - { - case 0x00: - D_regs(ctx, value & 0xffff); - break; - case 0x20: - ctx.op->addr = value & 0xffff; - make_o_mem(ctx); - break; - case 0x40: - D_indir(ctx, value & 0xffff); - break; - case 0x60: - ctx.op->type = o_imm; - ctx.op->dtype = dt_byte; - ctx.op->value = value & 0xffff; - break; - default: - return false; - } - return true; -} - -//---------------------------------------------------------------------- -static bool idle_1_2(ctx_t &ctx, int value) -{ - if ( value & 0x01 ) - ctx.insn.itype = TMS320C3X_IDLE2; - else - ctx.insn.itype = TMS320C3X_IDLE; - return true; -} - -//---------------------------------------------------------------------- -static bool speedctrl(ctx_t &ctx, int value) -{ - if ( value & 0x01 ) - ctx.insn.itype = TMS320C3X_LOPOWER; - else - ctx.insn.itype = TMS320C3X_MAXSPEED; - return true; -} - -//---------------------------------------------------------------------- -static bool nopcases(ctx_t &ctx, int value) -{ - if ( ((value>>16) & 0x60) == 0x40 ) - D_adres_1Op(ctx, value); - return true; -} -//---------------------------------------------------------------------- -static const opcode_t table_pattern[] = -{ - { TMS320C3X_ABSF, 0x000, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_ABSI, 0x001, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_ADDC, 0x002, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_ADDF, 0x003, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_ADDI, 0x004, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_AND, 0x005, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_ANDN, 0x006, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_ASH, 0x007, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_CMPF, 0x008, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_CMPI, 0x009, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_FIX, 0x00a, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_FLOAT, 0x00b, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_NONE, 0x00c, {{ idle_1_2, 0xffffffff } }},//multiple case, mask should be checked further - { TMS320C3X_LDE, 0x00d, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_LDF, 0x00e, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_LDFI, 0x00f, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_LDI, 0x010, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_LDII, 0x011, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_LDM, 0x012, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_LSH, 0x013, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_MPYF, 0x014, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_MPYI, 0x015, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_NEGB, 0x016, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_NEGF, 0x017, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_NEGI, 0x018, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_NOP, 0x019, {{ nopcases, 0x007fffff } }},// possible update registers case - { TMS320C3X_NORM, 0x01a, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_NOT, 0x01b, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_POP, 0x01c, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_POPF, 0x01d, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_PUSH, 0x01e, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_PUSHF, 0x01f, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_OR, 0x020, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_NONE, 0x021, {{ speedctrl, 0xffffffff } }},//multiple case, mask should be checked further - { TMS320C3X_RND, 0x022, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_ROL, 0x023, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_ROLC, 0x024, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_ROR, 0x025, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_RORC, 0x026, {{ D_regs, 0x001f0000 } }}, - { TMS320C3X_RPTS, 0x027, {{ D_adres_1Op, 0x007fffff } }}, - { TMS320C3X_STF, 0x028, {{ SD_adresRev, 0x007fffff } }}, - { TMS320C3X_STFI, 0x029, {{ SD_adresRev, 0x007fffff } }}, - { TMS320C3X_STI, 0x02a, {{ SD_adresRev, 0x007fffff } }}, - { TMS320C3X_STII, 0x02b, {{ SD_adresRev, 0x007fffff } }}, - { TMS320C3X_SIGI, 0x02c }, - { TMS320C3X_SUBB, 0x02d, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_SUBC, 0x02e, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_SUBF, 0x02f, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_SUBI, 0x030, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_SUBRB, 0x031, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_SUBRF, 0x032, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, - { TMS320C3X_SUBRI, 0x033, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_TSTB, 0x034, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_XOR, 0x035, {{ SD_adres, 0x007fffff } }}, - { TMS320C3X_IACK, 0x036 }, - { TMS320C3X_null, 0x037 },{ TMS320C3X_null, 0x038 }, { TMS320C3X_null, 0x039 }, { TMS320C3X_null, 0x03a },// invalid - { TMS320C3X_null, 0x03b },{ TMS320C3X_null, 0x03c }, { TMS320C3X_null, 0x03d }, { TMS320C3X_null, 0x03e },// invalid - { TMS320C3X_null, 0x03f },// invalid -// 3 operand insns - { TMS320C3X_ADDC3, 0x040, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_ADDF3, 0x041, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_ADDI3, 0x042, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_AND3, 0x043, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_ANDN3, 0x044, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_ASH3, 0x045, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_CMPF3, 0x046, {{ SD_src3_2op, 0x007fffff } }}, - { TMS320C3X_CMPI3, 0x047, {{ SD_src3_2op, 0x007fffff } }}, - { TMS320C3X_LSH3, 0x048, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_MPYF3, 0x049, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_MPYI3, 0x04a, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_OR3, 0x04b, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_SUBB3, 0x04c, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_SUBF3, 0x04d, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_SUBI3, 0x04e, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_TSTB3, 0x04f, {{ SD_src3_2op, 0x007fffff } }}, - { TMS320C3X_XOR3, 0x050, {{ SSD_src3, 0x007fffff } }}, - { TMS320C3X_null, 0x051 },{ TMS320C3X_null, 0x052 },{ TMS320C3X_null, 0x053 },{ TMS320C3X_null, 0x054 },// invalid - { TMS320C3X_null, 0x055 },{ TMS320C3X_null, 0x056 },{ TMS320C3X_null, 0x057 },{ TMS320C3X_null, 0x058 },// invalid - { TMS320C3X_null, 0x059 },{ TMS320C3X_null, 0x05a },{ TMS320C3X_null, 0x05b },{ TMS320C3X_null, 0x05c },// invalid - { TMS320C3X_null, 0x05d },{ TMS320C3X_null, 0x05e },{ TMS320C3X_null, 0x05f },{ TMS320C3X_null, 0x060 },// invalid - { TMS320C3X_null, 0x061 },{ TMS320C3X_null, 0x062 },{ TMS320C3X_null, 0x063 },{ TMS320C3X_null, 0x064 },// invalid - { TMS320C3X_null, 0x065 },{ TMS320C3X_null, 0x066 },{ TMS320C3X_null, 0x067 },{ TMS320C3X_null, 0x068 },// invalid - { TMS320C3X_null, 0x069 },{ TMS320C3X_null, 0x06a },{ TMS320C3X_null, 0x06b },{ TMS320C3X_null, 0x06c },// invalid - { TMS320C3X_null, 0x06d },{ TMS320C3X_null, 0x06e },{ TMS320C3X_null, 0x06f },{ TMS320C3X_null, 0x070 },// invalid - { TMS320C3X_null, 0x071 },{ TMS320C3X_null, 0x072 },{ TMS320C3X_null, 0x073 },{ TMS320C3X_null, 0x074 },// invalid - { TMS320C3X_null, 0x075 },{ TMS320C3X_null, 0x076 },{ TMS320C3X_null, 0x077 },{ TMS320C3X_null, 0x078 },// invalid - { TMS320C3X_null, 0x079 },{ TMS320C3X_null, 0x07a },{ TMS320C3X_null, 0x07b },{ TMS320C3X_null, 0x07c },// invalid - { TMS320C3X_null, 0x07d },{ TMS320C3X_null, 0x07e },{ TMS320C3X_null, 0x07f },// invalid -//0x80 - 0x8f LDFcond - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, -//0x90 - 0x9f LDFcond - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f }, - { TMS320C3X_LDFcond, 0x09f, {{ cond, 0x0f800000 }, { SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, -//0xa0 - 0xaf LDIcond - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, -//0xb0 - 0xbf LDIcond - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, - { TMS320C3X_LDIcond, 0x0bf, {{ cond, 0x0f800000 }, { SD_adres, 0x007fffff } }}, -//0xc0 - 0xc1 BR - { TMS320C3X_MV_IDX, 0x0c1 }, - { TMS320C3X_BR, 0x0c1, {{ D_adr24, 0x00ffffff } }}, -//0xc2 - 0xc3 BR - { TMS320C3X_MV_IDX, 0x0c3 }, - { TMS320C3X_BRD, 0x0c3, {{ DBranch, 0x00000000 }, { D_adr24, 0x00ffffff } }}, -//0xc4 - 0xc5 CALL - { TMS320C3X_MV_IDX, 0x0c5 }, - { TMS320C3X_CALL, 0x0c5, {{ D_adr24, 0x00ffffff } }}, - { TMS320C3X_null, 0x0c6 },// invalid - { TMS320C3X_null, 0x0c7 },// invalid -//0xc8 - 0xc9 RPTB - { TMS320C3X_MV_IDX, 0x0c9 }, - { TMS320C3X_RPTB, 0x0c9, {{ D_adr24, 0x00ffffff } }}, - { TMS320C3X_null, 0x0ca },// invalid - { TMS320C3X_null, 0x0cb },// invalid - { TMS320C3X_SWI, 0x0cc }, - { TMS320C3X_null, 0x0cd },// invalid - { TMS320C3X_null, 0x0ce },// invalid - { TMS320C3X_null, 0x0cf },// invalid - { TMS320C3X_Bcond, 0x0d0, {{ cond, 0x003f0000 }, { D_regs, 0x0000ffff } }}, - { TMS320C3X_null, 0x0d1 },// invalid - { TMS320C3X_null, 0x0d2 },// invalid - { TMS320C3X_null, 0x0d3 },// invalid - { TMS320C3X_Bcond, 0x0d4, {{ cond, 0x003f0000 }, { D_PC_Displ, 0x0020ffff } }}, - { TMS320C3X_null, 0x0d5 },// invalid - { TMS320C3X_null, 0x0d6 },// invalid - { TMS320C3X_null, 0x0d7 },// invalid -//0xd8 - 0xdb DBcond - { TMS320C3X_MV_IDX, 0x0db }, - { TMS320C3X_MV_IDX, 0x0db }, - { TMS320C3X_MV_IDX, 0x0db }, - { TMS320C3X_DBcond, 0x0db, {{ cond, 0x003f0000 }, { S_ar, 0x01c00000 }, { D_regs, 0x0000ffff } }}, -//0xdc - 0xdf DBcond - { TMS320C3X_MV_IDX, 0x0df }, - { TMS320C3X_MV_IDX, 0x0df }, - { TMS320C3X_MV_IDX, 0x0df }, - { TMS320C3X_DBcond, 0x0df, {{ cond, 0x003f0000 }, { S_ar, 0x01c00000 }, { D_PC_Displ, 0x0020ffff } }}, - { TMS320C3X_CALLcond, 0x0e0, {{ cond, 0x001f0000 }, { D_regs, 0x0000ffff } }}, - { TMS320C3X_null, 0x0e1 },// invalid - { TMS320C3X_null, 0x0e2 },// invalid - { TMS320C3X_null, 0x0e3 },// invalid - { TMS320C3X_CALLcond, 0x0e4, {{ cond, 0x001f0000 }, { D_PC_Displ, 0x0000ffff } }}, - { TMS320C3X_null, 0x0e5 },// invalid - { TMS320C3X_null, 0x0e6 },// invalid - { TMS320C3X_null, 0x0e7 },// invalid - { TMS320C3X_TRAPcond, 0x0e8, {{ cond, 0x001f0000 }, { imm8, 0x0000001f } }}, - { TMS320C3X_null, 0x0e9 },// invalid - { TMS320C3X_null, 0x0ea },// invalid - { TMS320C3X_null, 0x0eb },// invalid - { TMS320C3X_null, 0x0ec },// invalid - { TMS320C3X_null, 0x0ed },// invalid - { TMS320C3X_null, 0x0ee },// invalid - { TMS320C3X_null, 0x0ef },// invalid - { TMS320C3X_RETIcond, 0x0f0, {{ cond, 0x001f0000 } }}, - { TMS320C3X_RETScond, 0x0f1, {{ cond, 0x001f0000 } }}, - { TMS320C3X_null, 0x0f2 }, { TMS320C3X_null, 0x0f3 }, { TMS320C3X_null, 0x0f4 }, { TMS320C3X_null, 0x0f5 },// invalid - { TMS320C3X_null, 0x0f6 }, { TMS320C3X_null, 0x0f7 }, { TMS320C3X_null, 0x0f8 }, { TMS320C3X_null, 0x0f9 },// invalid - { TMS320C3X_null, 0x0fa }, { TMS320C3X_null, 0x0fb }, { TMS320C3X_null, 0x0fc }, { TMS320C3X_null, 0x0fd },// invalid - { TMS320C3X_null, 0x0fe }, { TMS320C3X_null, 0x0ff },// invalid - { TMS320C3X_MV_IDX, 0x101 }, - { TMS320C3X_MPYF3, 0x101, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, - TMS320C3X_ADDF3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x103 }, - { TMS320C3X_MPYF3, 0x103, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_ADDF3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x105 }, - { TMS320C3X_MPYF3, 0x105, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, - TMS320C3X_ADDF3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x107 }, - { TMS320C3X_MPYF3, 0x107, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_ADDF3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x109 }, - { TMS320C3X_MPYF3, 0x109, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, - TMS320C3X_SUBF3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x10b }, - { TMS320C3X_MPYF3, 0x10b, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_SUBF3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x10d }, - { TMS320C3X_MPYF3, 0x10d, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, - TMS320C3X_SUBF3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x10f }, - { TMS320C3X_MPYF3, 0x10f, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_SUBF3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x111 }, - { TMS320C3X_MPYI3, 0x111, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, - TMS320C3X_ADDI3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x113 }, - { TMS320C3X_MPYI3, 0x113, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_ADDI3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x115 }, - { TMS320C3X_MPYI3, 0x115, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, - TMS320C3X_ADDI3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x117 }, - { TMS320C3X_MPYI3, 0x117, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_ADDI3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x119 }, - { TMS320C3X_MPYI3, 0x119, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, - TMS320C3X_SUBI3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x11b }, - { TMS320C3X_MPYI3, 0x11b, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_SUBI3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x11d }, - { TMS320C3X_MPYI3, 0x11d, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, - TMS320C3X_SUBI3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - { TMS320C3X_MV_IDX, 0x11f }, - { TMS320C3X_MPYI3, 0x11f, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, - TMS320C3X_SUBI3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, - - { TMS320C3X_null, 0x120 }, { TMS320C3X_null, 0x121 }, { TMS320C3X_null, 0x122 }, { TMS320C3X_null, 0x123 },// invalid - { TMS320C3X_null, 0x124 }, { TMS320C3X_null, 0x125 }, { TMS320C3X_null, 0x126 }, { TMS320C3X_null, 0x127 },// invalid - { TMS320C3X_null, 0x128 }, { TMS320C3X_null, 0x129 }, { TMS320C3X_null, 0x12a }, { TMS320C3X_null, 0x12b },// invalid - { TMS320C3X_null, 0x12c }, { TMS320C3X_null, 0x12d }, { TMS320C3X_null, 0x12e }, { TMS320C3X_null, 0x12f },// invalid - { TMS320C3X_null, 0x130 }, { TMS320C3X_null, 0x131 }, { TMS320C3X_null, 0x132 }, { TMS320C3X_null, 0x133 },// invalid - { TMS320C3X_null, 0x134 }, { TMS320C3X_null, 0x135 }, { TMS320C3X_null, 0x136 }, { TMS320C3X_null, 0x137 },// invalid - { TMS320C3X_null, 0x138 }, { TMS320C3X_null, 0x139 }, { TMS320C3X_null, 0x13a }, { TMS320C3X_null, 0x13b },// invalid - { TMS320C3X_null, 0x13c }, { TMS320C3X_null, 0x13d }, { TMS320C3X_null, 0x13e }, { TMS320C3X_null, 0x13f },// invalid - { TMS320C3X_null, 0x140 }, { TMS320C3X_null, 0x141 }, { TMS320C3X_null, 0x142 }, { TMS320C3X_null, 0x143 },// invalid - { TMS320C3X_null, 0x144 }, { TMS320C3X_null, 0x145 }, { TMS320C3X_null, 0x146 }, { TMS320C3X_null, 0x147 },// invalid - { TMS320C3X_null, 0x148 }, { TMS320C3X_null, 0x149 }, { TMS320C3X_null, 0x14a }, { TMS320C3X_null, 0x14b },// invalid - { TMS320C3X_null, 0x14c }, { TMS320C3X_null, 0x14d }, { TMS320C3X_null, 0x14e }, { TMS320C3X_null, 0x14f },// invalid - { TMS320C3X_null, 0x150 }, { TMS320C3X_null, 0x151 }, { TMS320C3X_null, 0x152 }, { TMS320C3X_null, 0x153 },// invalid - { TMS320C3X_null, 0x154 }, { TMS320C3X_null, 0x155 }, { TMS320C3X_null, 0x156 }, { TMS320C3X_null, 0x157 },// invalid - { TMS320C3X_null, 0x158 }, { TMS320C3X_null, 0x159 }, { TMS320C3X_null, 0x15a }, { TMS320C3X_null, 0x15b },// invalid - { TMS320C3X_null, 0x15c }, { TMS320C3X_null, 0x15d }, { TMS320C3X_null, 0x15e }, { TMS320C3X_null, 0x15f },// invalid - { TMS320C3X_null, 0x160 }, { TMS320C3X_null, 0x161 }, { TMS320C3X_null, 0x162 }, { TMS320C3X_null, 0x163 },// invalid - { TMS320C3X_null, 0x164 }, { TMS320C3X_null, 0x165 }, { TMS320C3X_null, 0x166 }, { TMS320C3X_null, 0x167 },// invalid - { TMS320C3X_null, 0x168 }, { TMS320C3X_null, 0x169 }, { TMS320C3X_null, 0x16a }, { TMS320C3X_null, 0x16b },// invalid - { TMS320C3X_null, 0x16c }, { TMS320C3X_null, 0x16d }, { TMS320C3X_null, 0x16e }, { TMS320C3X_null, 0x16f },// invalid - { TMS320C3X_null, 0x170 }, { TMS320C3X_null, 0x171 }, { TMS320C3X_null, 0x172 }, { TMS320C3X_null, 0x123 },// invalid - { TMS320C3X_null, 0x174 }, { TMS320C3X_null, 0x175 }, { TMS320C3X_null, 0x176 }, { TMS320C3X_null, 0x127 },// invalid - { TMS320C3X_null, 0x178 }, { TMS320C3X_null, 0x179 }, { TMS320C3X_null, 0x17a }, { TMS320C3X_null, 0x12b },// invalid - { TMS320C3X_null, 0x17c }, { TMS320C3X_null, 0x17d }, { TMS320C3X_null, 0x17e }, { TMS320C3X_null, 0x12f },// invalid - - { TMS320C3X_MV_IDX, 0x183 }, - { TMS320C3X_MV_IDX, 0x183 }, - { TMS320C3X_MV_IDX, 0x183 }, - { TMS320C3X_STF, 0x183, {{ S_R, 0x01c00000 }, { D_indir3, 0x000000ff }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x187 }, - { TMS320C3X_MV_IDX, 0x187 }, - { TMS320C3X_MV_IDX, 0x187 }, - { TMS320C3X_STI, 0x187, {{ S_R, 0x01c00000 }, { D_indir3, 0x000000ff }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x18b }, - { TMS320C3X_MV_IDX, 0x18b }, - { TMS320C3X_MV_IDX, 0x18b }, - { TMS320C3X_LDF, 0x18b, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_LDF, {{ S_indir3, 0x0000ff00 }, { D_R, 0x00380000 }}}, - { TMS320C3X_MV_IDX, 0x18f }, - { TMS320C3X_MV_IDX, 0x18f }, - { TMS320C3X_MV_IDX, 0x18f }, - { TMS320C3X_LDI, 0x18f, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_LDI, {{ S_indir3, 0x0000ff00 }, { D_R, 0x00380000 }}}, - { TMS320C3X_MV_IDX, 0x193 }, - { TMS320C3X_MV_IDX, 0x193 }, - { TMS320C3X_MV_IDX, 0x193 }, - { TMS320C3X_ABSF, 0x193, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x197 }, - { TMS320C3X_MV_IDX, 0x197 }, - { TMS320C3X_MV_IDX, 0x197 }, - { TMS320C3X_ABSI, 0x197, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x19b }, - { TMS320C3X_MV_IDX, 0x19b }, - { TMS320C3X_MV_IDX, 0x19b }, - { TMS320C3X_ADDF3, 0x19b, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x19f }, - { TMS320C3X_MV_IDX, 0x19f }, - { TMS320C3X_MV_IDX, 0x19f }, - { TMS320C3X_ADDI3, 0x19f, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1a3 }, - { TMS320C3X_MV_IDX, 0x1a3 }, - { TMS320C3X_MV_IDX, 0x1a3 }, - { TMS320C3X_AND3, 0x1a3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1a7 }, - { TMS320C3X_MV_IDX, 0x1a7 }, - { TMS320C3X_MV_IDX, 0x1a7 }, - { TMS320C3X_ASH3, 0x1a7, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1ab }, - { TMS320C3X_MV_IDX, 0x1ab }, - { TMS320C3X_MV_IDX, 0x1ab }, - { TMS320C3X_FIX, 0x1ab, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1af }, - { TMS320C3X_MV_IDX, 0x1af }, - { TMS320C3X_MV_IDX, 0x1af }, - { TMS320C3X_FLOAT, 0x1af, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1b3 }, - { TMS320C3X_MV_IDX, 0x1b3 }, - { TMS320C3X_MV_IDX, 0x1b3 }, - { TMS320C3X_LDF, 0x1b3, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1b7 }, - { TMS320C3X_MV_IDX, 0x1b7 }, - { TMS320C3X_MV_IDX, 0x1b7 }, - { TMS320C3X_LDI, 0x1b7, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1bb }, - { TMS320C3X_MV_IDX, 0x1bb }, - { TMS320C3X_MV_IDX, 0x1bb }, - { TMS320C3X_LSH3, 0x1bb, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1bf }, - { TMS320C3X_MV_IDX, 0x1bf }, - { TMS320C3X_MV_IDX, 0x1bf }, - { TMS320C3X_MPYF3, 0x1bf, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1c3 }, - { TMS320C3X_MV_IDX, 0x1c3 }, - { TMS320C3X_MV_IDX, 0x1c3 }, - { TMS320C3X_MPYI3, 0x1c3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1c7 }, - { TMS320C3X_MV_IDX, 0x1c7 }, - { TMS320C3X_MV_IDX, 0x1c7 }, - { TMS320C3X_NEGF, 0x1c7, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1cb }, - { TMS320C3X_MV_IDX, 0x1cb }, - { TMS320C3X_MV_IDX, 0x1cb }, - { TMS320C3X_NEGI, 0x1cb, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1cf }, - { TMS320C3X_MV_IDX, 0x1cf }, - { TMS320C3X_MV_IDX, 0x1cf }, - { TMS320C3X_NOT, 0x1cf, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1d3 }, - { TMS320C3X_MV_IDX, 0x1d3 }, - { TMS320C3X_MV_IDX, 0x1d3 }, - { TMS320C3X_OR3, 0x1d3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1d7 }, - { TMS320C3X_MV_IDX, 0x1d7 }, - { TMS320C3X_MV_IDX, 0x1d7 }, - { TMS320C3X_SUBF3, 0x1d7, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1db }, - { TMS320C3X_MV_IDX, 0x1db }, - { TMS320C3X_MV_IDX, 0x1db }, - { TMS320C3X_SUBI3, 0x1db, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, - { TMS320C3X_MV_IDX, 0x1df }, - { TMS320C3X_MV_IDX, 0x1df }, - { TMS320C3X_MV_IDX, 0x1df }, - { TMS320C3X_XOR3, 0x1df, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, - TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, -}; - -//-------------------------------------------------------------------------- -int tms320c3x_t::run_functions(ctx_t &ctx, int value, int entry, int start, int end) -{ - const opcode_t &opcode = table[entry]; - for ( int j = start; j <= end; j++ ) - { - const funcdesc_t &fd = opcode.funcs[j]; - if ( fd.func == NULL ) - break; - if ( !fd.func(ctx, (value & fd.mask) >> fd.shift) ) - return false; - } - return true; -} - -//-------------------------------------------------------------------------- -int tms320c3x_t::run_functions2(ctx_t &ctx, int value, int entry, int start, int end) -{ - const opcode_t &opcode = table[entry]; - for ( int j = start; j <= end; j++ ) - { - const funcdesc_t &fd = opcode.funcs2[j]; - if ( fd.func == NULL ) - break; - if ( !fd.func(ctx, (value & fd.mask) >> fd.shift) ) - return false; - } - return true; -} - -//-------------------------------------------------------------------------- -int tms320c3x_t::ana(insn_t *insn) -{ - ctx_t ctx(insn); - - int value = get_wide_byte(insn->ea); - insn->size++; - - int idx = (value >> 23) & 0x1ff; - - // check for known opcode - insn->itype = idx >= table.size ? TMS320C3X_null : table[idx].itype; - - if ( insn->itype == TMS320C3X_MV_IDX ) // for this opcode use the next table line - insn->itype = table[ idx = table[idx].insnidx ].itype; - - if ( insn->itype != TMS320C3X_null ) - { - if ( !run_functions(ctx, value, idx, 0, FUNCS_COUNT - 1) ) - return 0; - - if ( table[idx].ispar ) - { - ctx.op++; - insn->itype2 = table[ idx = table[idx].insnidx ].itype2; // second (parallel) insn opcode - insn->i2op = ctx.op->n; // location for operand of the second insn - - if ( !run_functions2(ctx, value, idx, 0, FUNCS_COUNT - 1) ) - return 0; - } - return insn->size; // length is always 1 - } - else - { - return 0; - } -} - -//-------------------------------------------------------------------------- -void tms320c3x_t::gen_masks(void) -{ - for ( int i = 0; i < table.size; i++ ) - { - table[i].ispar = (table[i].insnidx & 0x100) != 0; - for ( int j = 0; j < FUNCS_COUNT; j++ ) - { - if ( table[i].funcs[j].func != NULL ) - { - for ( int b = 0; b < 32; b++ ) - { - if ( table[i].funcs[j].mask & (1 << b) ) - break; - else - table[i].funcs[j].shift++; - } - } - } - - if ( table[i].insnidx & 0x100 ) - for ( int j = 0; j < FUNCS_COUNT; j++ ) - { - if ( table[i].funcs2[j].func != NULL ) - { - for ( int b = 0; b < 32; b++ ) - { - if ( table[i].funcs2[j].mask & (1 << b) ) - break; - else - table[i].funcs2[j].shift++; - } - } - } - } -} - -//---------------------------------------------------------------------- -void tms320c3x_t::init_analyzer(void) -{ - table.create(table_pattern, qnumber(table_pattern)); - gen_masks(); -} - -//---------------------------------------------------------------------- -void tms320c3_table_t::create(const opcode_t src_table[], int src_table_size) -{ - size = src_table_size; - entries = qalloc_array<opcode_t>(size); - memcpy(entries, src_table, sizeof(opcode_t) * size); -} - -//---------------------------------------------------------------------- -tms320c3_table_t::~tms320c3_table_t() -{ - qfree(entries); - entries = nullptr; -} - -//---------------------------------------------------------------------- -opcode_t &tms320c3_table_t::operator[](size_t i) -{ - return entries[i]; -} diff --git a/idasdk75/module/tms320c3/ins.hpp b/idasdk75/module/tms320c3/ins.hpp deleted file mode 100644 index 3efc18e..0000000 --- a/idasdk75/module/tms320c3/ins.hpp +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum -{ -TMS320C3X_null = 0, // Unknown Operation - -TMS320C3X_ABSF, // Absolute value of a floating-point number -TMS320C3X_ABSI, // Absolute value of an integer -TMS320C3X_ADDC, // Add integers with carry -TMS320C3X_ADDF, // Add Floating-Point Values -TMS320C3X_ADDI, // Add Integer -TMS320C3X_AND, // Bitwise-Logical AND -TMS320C3X_ANDN, // Bitwise-Logical AND With Complement -TMS320C3X_ASH, // Arithmetic Shift -TMS320C3X_CMPF, // Compare Floating-Point Value -TMS320C3X_CMPI, // Compare Integer -TMS320C3X_FIX, // Floating-Point-to-Integer Conversion -TMS320C3X_FLOAT, // Integer-to-Floating-Point Conversion -TMS320C3X_IDLE, // Idle Until Interrupt -TMS320C3X_IDLE2, // Low-Power Idle -TMS320C3X_LDE, // Load Floating-Point Exponent -TMS320C3X_LDF, // Load Floating-Point Value -TMS320C3X_LDFI, // Load Floating-Point Value, Interlocked -TMS320C3X_LDI, // Load Integer -TMS320C3X_LDII, // Load Integer, Interlocked -TMS320C3X_LDM, // Load Floating-Point Mantissa -TMS320C3X_LSH, // Logical Shift -TMS320C3X_MPYF, // Multiply Floating-Point Value -TMS320C3X_MPYI, // Multiply Integer -TMS320C3X_NEGB, // Negative Integer With Borrow -TMS320C3X_NEGF, // Negate Floating-Point Value -TMS320C3X_NEGI, // Negate Integer -TMS320C3X_NOP, // No Operation -TMS320C3X_NORM, // Normalize -TMS320C3X_NOT, // Bitwise-Logical Complement -TMS320C3X_POP, // Pop Integer -TMS320C3X_POPF, // Pop Floating-Point Value -TMS320C3X_PUSH, // PUSH Integer -TMS320C3X_PUSHF, // PUSH Floating-Point Value -TMS320C3X_OR, // Bitwise-Logical OR -TMS320C3X_LOPOWER, // Divide Clock by 16 -TMS320C3X_MAXSPEED, // Restore Clock to Regular Speed -TMS320C3X_RND, // Round Floating-Point Value -TMS320C3X_ROL, // Rotate Left -TMS320C3X_ROLC, // Rotate Left Through Carry -TMS320C3X_ROR, // Rotate Right -TMS320C3X_RORC, // Rotate Right Through Carry -TMS320C3X_RPTS, // Repeat Single Instruction -TMS320C3X_STF, // Store Floating-Point Value -TMS320C3X_STFI, // Store Floating-Point Value, Interlocked -TMS320C3X_STI, // Store Integer -TMS320C3X_STII, // Store Integer, Interlocked -TMS320C3X_SIGI, // Signal, Interlocked -TMS320C3X_SUBB, // Subtract Integer With Borrow -TMS320C3X_SUBC, // Subtract Integer Conditionally -TMS320C3X_SUBF, // Subtract Floating-Point Value -TMS320C3X_SUBI, // Subtract Integer -TMS320C3X_SUBRB, // Subtract Reverse Integer With Borrow -TMS320C3X_SUBRF, // Subtract Reverse Floating-Point Value -TMS320C3X_SUBRI, // Subtract Reverse Integer -TMS320C3X_TSTB, // Test Bit Fields -TMS320C3X_XOR, // Bitwise-Exclusive OR -TMS320C3X_IACK, // Interrupt acknowledge - -TMS320C3X_ADDC3, // Add integers with carry (3-operand) -TMS320C3X_ADDF3, // Add floating-point values (3-operand) -TMS320C3X_ADDI3, // Add integers (3 operand) -TMS320C3X_AND3, // Bitwise-logical AND (3-operand) -TMS320C3X_ANDN3, // Bitwise-logical ANDN (3-operand) -TMS320C3X_ASH3, // Arithmetic shift (3-operand) -TMS320C3X_CMPF3, // Compare floating-point values (3-operand) -TMS320C3X_CMPI3, // Compare integers (3-operand) -TMS320C3X_LSH3, // Logical shift (3-operand) -TMS320C3X_MPYF3, // Multiply floating-point value (3-operand) -TMS320C3X_MPYI3, // Multiply integers (3-operand) -TMS320C3X_OR3, // Bitwise-logical OR (3-operand) -TMS320C3X_SUBB3, // Subtract integers with borrow (3-operand) -TMS320C3X_SUBF3, // Subtract floating-point values (3-operand) -TMS320C3X_SUBI3, // Subtract integers (3-operand) -TMS320C3X_TSTB3, // Test Bit Fields, 3-Operand -TMS320C3X_XOR3, // Bitwise-Exclusive OR, 3-Operand - -TMS320C3X_LDFcond, // Load floating-point value conditionally -TMS320C3X_LDIcond, // Load integer conditionally -TMS320C3X_BR, // Branch unconditionally (standard) -TMS320C3X_BRD, // Branch unconditionally (delayed) -TMS320C3X_CALL, // Call subroutine -TMS320C3X_RPTB, // Repeat block of instructions -TMS320C3X_SWI, // Software Interrupt -TMS320C3X_Bcond, // Branch conditionally -TMS320C3X_DBcond, // Decrement and branch conditionally -TMS320C3X_CALLcond, // Call subroutine conditionally -TMS320C3X_TRAPcond, // Trap Conditionally -TMS320C3X_RETIcond, // Return from interrupt conditionally -TMS320C3X_RETScond, // Return from subroutine conditionally -TMS320C3X_RETIU, // Return from interrupt unconditionally -TMS320C3X_RETSU, // Return from subroutine unconditionally - -TMS320C3X_NONE, // Pseudo insn (more accurate definition need) -TMS320C3X_MV_IDX, // Pseudo insn (move to next index need) -TMS320C3X_last, // last ID - -}; - - -#endif diff --git a/idasdk75/module/tms320c3/makefile b/idasdk75/module/tms320c3/makefile deleted file mode 100644 index 3a9474e..0000000 --- a/idasdk75/module/tms320c3/makefile +++ /dev/null @@ -1,49 +0,0 @@ -PROC=tms320c3 -CONFIGS=tms320c3.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp ins.hpp tms320c3x.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp \ - tms320c3x.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp tms320c3x.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp tms320c3x.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ins.hpp reg.cpp \ - tms320c3x.hpp diff --git a/idasdk75/module/tms320c3/out.cpp b/idasdk75/module/tms320c3/out.cpp deleted file mode 100644 index 141bbe3..0000000 --- a/idasdk75/module/tms320c3/out.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "tms320c3x.hpp" -#include <frame.hpp> -#include <segregs.hpp> -#include <struct.hpp> - -// simple wrapper class for syntactic sugar of member functions -// this class may have only simple member functions. -// virtual functions and data fields are forbidden, otherwise the class -// layout may change -class out_tms320c3_t : public outctx_t -{ - out_tms320c3_t(void) = delete; // not used -public: - bool out_operand(const op_t &x); - void out_insn(void); - void out_proc_mnem(void); - void out_address(ea_t ea, const op_t &x, bool at); -}; -CASSERT(sizeof(out_tms320c3_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS(out_tms320c3_t) - -//---------------------------------------------------------------------- -#define SYM(x) COLSTR(x, SCOLOR_SYMBOL) -#define REG(x) COLSTR(x, SCOLOR_REG) -#define REGP(x) SYM("(") REG(x) SYM(")") - -// o_phrase output format strings, indexed by phtype -static const char *const formats[0x1a] = -{ - SYM("*+") REG("%s"), //0 "*+arn(NN)" - SYM("*-") REG("%s"), //1 "*-arn(NN)" - SYM("*++") REG("%s"), //2 "*++arn(NN)" - SYM("*--") REG("%s"), //3 "*--arn(NN)" - SYM("*") REG("%s") SYM("++"), //4 "*arn++(NN)" - SYM("*") REG("%s") SYM("--"), //5 "*arn--(NN)" - SYM("*") REG("%s") SYM("++"), //6 "*arn++(NN)%" - SYM("*") REG("%s") SYM("--"), //7 "*arn--(NN)%" - SYM("*+") REG("%s") REGP("ir0"), //8 "*+arn(ir0)" - SYM("*-") REG("%s") REGP("ir0"), //9 "*-arn(ir0)" - SYM("*++") REG("%s") REGP("ir0"), //a "*++arn(ir0)" - SYM("*--") REG("%s") REGP("ir0"), //b "*--arn(ir0)" - SYM("*") REG("%s") SYM("++") REGP("ir0"), //c "*arn++(ir0)" - SYM("*") REG("%s") SYM("--") REGP("ir0"), //d "*arn--(ir0)" - SYM("*") REG("%s") SYM("++") REGP("ir0") SYM("%%"), //e "*arn++(ir0)%" - SYM("*") REG("%s") SYM("--") REGP("ir0") SYM("%%"), //f "*arn--(ir0)%" - SYM("*+") REG("%s") REGP("ir1"), //10 "*+arn(ir1)" - SYM("*-") REG("%s") REGP("ir1"), //11 "*-arn(ir1)" - SYM("*++") REG("%s") REGP("ir1"), //12 "*++arn(ir1)" - SYM("*--") REG("%s") REGP("ir1"), //13 "*--arn(ir1)" - SYM("*") REG("%s") SYM("++") REGP("ir1"), //14 "*arn++(ir1)" - SYM("*") REG("%s") SYM("--") REGP("ir1"), //15 "*arn--(ir1)" - SYM("*") REG("%s") SYM("++") REGP("ir1") SYM("%%"), //16 "*arn++(ir1)%" - SYM("*") REG("%s") SYM("--") REGP("ir1") SYM("%%"), //17 "*arn--(ir1)%" - SYM("*") REG("%s"), //18 "*arn" - SYM("*") REG("%s") SYM("++") REGP("ir0") SYM("B"), //19 "*arn++(ir0)B" -}; - -//-------------------------------------------------------------------------- -static const char *const cc_text[] = -{ - //Unconditional compares - "u", //Unconditional - - //Unsigned compares - "lo", //Lower than - "ls", //Lower than or same as - "hi", //Higher than - "hs", //Higher than or same as - "e", //Equal to - "ne", //Not equal to - - //Signed compares - "lt", //Less than - "le", //Less than or equal to - "gt", //Greater than - "ge", //Greater than or equal to - - //Unknown - "?", //Unknown - - //Compare to condition flags - "nv", //No overflow - "v", //Overflow - "nuf", //No underflow - "uf", //Underflow - "nlv", //No latched overflow - "lv", //Latched overflow - "nluf", //No latched floating-point underflow - "luf", //Latched floating-point underflow - "zuf" //Zero or floating-point underflow -}; - -//---------------------------------------------------------------------- -void out_tms320c3_t::out_address(ea_t ea, const op_t &x, bool at) -{ - qstring qbuf; - if ( get_name_expr(&qbuf, insn.ea+x.offb, x.n, ea, ea) > 0 ) - { - if ( at ) - out_symbol('@'); - out_line(qbuf.begin()); - } - else - { - if ( at ) - out_symbol('@'); - out_tagon(COLOR_ERROR); - out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16); - out_printf(" (ea = %a)", ea); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - -} - -//---------------------------------------------------------------------- -bool out_tms320c3_t::out_operand(const op_t &x) -{ - ea_t ea; - char buf[MAXSTR]; - - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - out_register(ph.reg_names[x.reg]); - break; - - case o_near: - out_address(calc_code_mem(insn, x), x, false); - break; - - case o_imm: - if ( insn.itype != TMS320C3X_TRAPcond ) - out_symbol('#'); - - if ( insn.auxpref & ImmFltFlag ) - { - int16 v = int16(x.value); - print_fpval(buf, sizeof(buf), &v, 2); - out_line(buf[0] == ' ' ? &buf[1] : buf, COLOR_NUMBER); - } - else - { - out_value(x, OOFW_IMM); - } - break; - - case o_mem: - ea = calc_data_mem(insn, x); - if ( ea != BADADDR ) - { - out_address(ea, x, true); - } - else - { - out_tagon(COLOR_ERROR); - out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16); - out_tagoff(COLOR_ERROR); - } - break; - - case o_phrase: // Indirect addressing mode - { - if ( x.phrase < qnumber(formats) ) - { - op_t y = x; - bool outdisp = x.phrase < 8; - bool printmod = x.phrase >= 6; - if ( x.phrase == 0x18 ) - { - // this is *arn phrase - // check if we need to print the displacement - int n = x.n; - if ( is_off(F, n) || is_stkvar(F, n) || is_enum(F, n) || is_stroff(F, n) ) - { - outdisp = true; - y.addr = 0; - printmod = false; - y.phrase = 0; // use '*+arn(NN)' syntax - } - } - - // print the base part - const char *reg = ph.reg_names[uchar(y.phtype)]; - nowarn_qsnprintf(buf, sizeof(buf), formats[uchar(y.phrase)], reg); - out_colored_register_line(buf); - - // print the displacement - if ( outdisp ) - { - out_symbol('('); - out_value(y, OOFS_IFSIGN|OOF_ADDR|OOFW_32); - out_symbol(')'); - if ( printmod ) - out_symbol('%'); // %: circular modify - } - } - else - { - out_line("<bad indirect>", COLOR_ERROR); - } - break; - } - - default: - INTERR(10261); - } - return 1; -} - -//---------------------------------------------------------------------- -void out_tms320c3_t::out_proc_mnem(void) -{ - char postfix[8]; - postfix[0] = '\0'; - switch ( insn.itype ) - { - case TMS320C3X_LDFcond: - case TMS320C3X_LDIcond: - case TMS320C3X_Bcond: - case TMS320C3X_DBcond: - case TMS320C3X_CALLcond: - case TMS320C3X_TRAPcond: - case TMS320C3X_RETIcond: - case TMS320C3X_RETScond: - qstrncpy(postfix, cc_text[insn.auxpref & 0x1f ], sizeof(postfix)); - if ( insn.auxpref & DBrFlag ) // delayed branch? - qstrncat(postfix, "d", sizeof(postfix)); - break; - } - - out_mnem(8, postfix); -} - -//---------------------------------------------------------------------- -void out_tms320c3_t::out_insn(void) -{ - out_mnemonic(); - - // following operand combinations exist: - // 0, 1, 2, 3 for non-parallel - // 2+2, 3+2, 3+3 for parallel - - out_one_operand(0); // two operands can be printed always - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_one_operand(1); - } - if ( insn.itype2 ) // Parallel - { - if ( insn.i2op > 2 ) // 3rd operand is for first instruction half - { - out_symbol(','); - out_one_operand(2); - } - flush_outbuf(); - - char insn2[MAXSTR]; - qsnprintf(insn2, sizeof(insn2), "||%s", ph.instruc[uchar(insn.itype2)].name); - ::add_spaces(insn2, sizeof(insn2), 8); - out_line(insn2, COLOR_INSN); - - if ( insn.i2op == 2 ) // 3rd operand is for second instruction half - { - out_one_operand(2); - out_symbol(','); - } - - if ( insn.Op4.type != o_void ) - out_one_operand(3); - - if ( insn.Op5.type != o_void ) - { - out_symbol(','); - out_one_operand(4); - } - - if ( insn.Op6.type != o_void ) - { - out_symbol(','); - out_one_operand(5); - } - } - else if ( insn.Op3.type != o_void ) - { - out_symbol(','); - out_one_operand(2); - } - - out_immchar_cmts(); - - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void tms320c3x_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) -{ - if ( reg == ph.reg_data_sreg ) - return; - if ( value != BADADDR ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), value); - ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); - } - else - { - ctx.gen_cmt_line("drop %s", ph.reg_names[reg]); - } -} - -//-------------------------------------------------------------------------- -// function to produce assume directives -//lint -e{1764} ctx could be const -void tms320c3x_t::assumes(outctx_t &ctx) -{ - ea_t ea = ctx.insn_ea; - segment_t *seg = getseg(ea); - if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) - return; - bool seg_started = (ea == seg->start_ea); - - for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) - { - if ( i == ph.reg_code_sreg ) - continue; - sreg_range_t sra; - if ( !get_sreg_range(&sra, ea, i) ) - continue; - if ( seg_started || sra.start_ea == ea ) - { - sel_t now = get_sreg(ea, i); - sreg_range_t prev; - bool prev_exists = get_sreg_range(&prev, ea-1, i); - if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) ) - print_segment_register(ctx, i, now); - } - } -} - -//-------------------------------------------------------------------------- -//lint -e{818} seg could be const -void tms320c3x_t::segstart(outctx_t &ctx, segment_t *seg) const -{ - if ( is_spec_segm(seg->type) ) - return; - - qstring sclas; - get_segm_class(&sclas, seg); - - if ( sclas == "CODE" ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR)); - else if ( sclas == "DATA" ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR)); - - if ( seg->orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), seg->orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -void idaapi segend(outctx_t &, segment_t *) -{ -} - -//-------------------------------------------------------------------------- -void tms320c3x_t::header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL | GH_BYTESEX_HAS_HIGHBYTE, NULL, ioh.device.c_str()); - ctx.gen_empty_line(); -} - -//-------------------------------------------------------------------------- -void tms320c3x_t::footer(outctx_t &ctx) const -{ - ctx.gen_printf(DEFAULT_INDENT,COLSTR("%s",SCOLOR_ASMDIR),ash.end); -} - -//-------------------------------------------------------------------------- -void tms320c3x_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const -{ - char sign = ' '; - if ( v < 0 ) - { - sign = '-'; - v = -v; - } - - qstring name = get_member_name(mptr->id); - - char vstr[MAX_NUMBUF]; - btoa(vstr, sizeof(vstr), v); - ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) - COLSTR("%c%s",SCOLOR_DNUM) - COLSTR(",",SCOLOR_SYMBOL) " " - COLSTR("%s",SCOLOR_LOCNAME), - ash.a_equ, - sign, - vstr, - name.c_str()); -} diff --git a/idasdk75/module/tms320c3/reg.cpp b/idasdk75/module/tms320c3/reg.cpp deleted file mode 100644 index e034bfe..0000000 --- a/idasdk75/module/tms320c3/reg.cpp +++ /dev/null @@ -1,621 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include <math.h> -#include "tms320c3x.hpp" -#include <diskio.hpp> -#include <segregs.hpp> -#include <ieee.h> - -static const char *const register_names[] = -{ - // Extended-precision registers - "r0", - "r1", - "r2", - "r3", - "r4", - "r5", - "r6", - "r7", - // Auxiliary registers - "ar0", - "ar1", - "ar2", - "ar3", - "ar4", - "ar5", - "ar6", - "ar7", - - // Index register n - "ir0", - "ir1", - - "bk", // Block-size register - "sp", // System-stack pointer - "st", // Status register - "ie", // CPU/DMA interrupt-enable register - "if", // CPU interrupt flag - "iof", // I/O flag - "rs", // Repeat start-address - "re", // Repeat end-address - "rc", // Repeat counter - - // segment registers - "dp", // Data-page pointer - "cs","ds", // virtual registers for code and data segments - -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0x78, 0x80, 0x00, 0x00 }; // 0x78800000 //retsu -static const uchar retcode_1[] = { 0x78, 0x00, 0x00, 0x00 }; // 0x78000000 //retiu - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// TMS320C3X ASM -//----------------------------------------------------------------------- -static const asm_t fasm = -{ - AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON, - 0, - "ASM500", - 0, - NULL, // header lines - NULL, // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".pstring", // ascii string directive - ".word", // byte directive - ".long", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".space 32*%s",// uninited arrays - ".asg", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".ref", // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_BYTE1CHAR,// one character per byte -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gnuasm = -{ - AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON|AS_ASCIIC, - 0, - "GNU assembler", - 0, - NULL, // header lines - NULL, // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".pstring", // ascii string directive - ".word", // byte directive - ".long", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".zero 2*%s", // uninited arrays - ".asg", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - ".weak", // "weak" name keyword - ".extern", // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_BYTE1CHAR,// one character per byte - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt -}; - -static const asm_t *const asms[] = { &fasm, &gnuasm, NULL }; - -//-------------------------------------------------------------------------- -bool tms320c3x_iohandler_t::entry_processing(ea_t &ea, const char *name, const char *cmt) -{ - set_name(ea, name, SN_NODUMMY); - set_cmt(ea, cmt, 0); - return true; -} - -//---------------------------------------------------------------------- -bool tms320c3x_t::select_device(int lrespect_info) -{ - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( !choose_ioport_device(&ioh.device, cfgfile) ) - { - ioh.device = NONEPROC; - return false; - } - - if ( !ioh.display_infotype_dialog(IORESP_ALL, &lrespect_info, cfgfile) ) - return false; - - ioh.set_device_name(ioh.device.c_str(), lrespect_info); - return true; -} - -//---------------------------------------------------------------------- -static float conv32(int32 A) // convertion of 32 bit TMS float -> double -{ - int32 mask, f, i, s; - float mant; - int8 e; - - // exponent, signed 8 bit - e = A >> 24; - - // sign, boolean 1 bit - s = (A & 0x00800000) >> 23; - - // fraction, unsigned 23 bit - f = A & 0x007FFFFF; - - // NaN, Inf - if ( (e & 0xFF) == 0xFF ) - { - uint32 i32 = (s << 31) | (0xFF << 23) | f; - - return *reinterpret_cast<float*>(&i32); - } - - if ( s ) - { - f ^= 0x007FFFFF; - f++; - } - - mant = 1; // mantissa (1<M<2) - mask = 0x00800000; // bit mask of the current bit, - // started from the sign position - - for ( i = 0; i <= 23; i++ ) - { - if ( f & mask ) - mant += (float)pow(double(2), -i); - mask >>= 1; - } - - if ( e == -128 && f == 0 && s == 0 ) - mant = 0; - - return float(pow(double(-1), s) * mant * pow(double(2), e)); -} - -//---------------------------------------------------------------------- -// A short floating-point format for immediate floating-point operands, consisting -// of a 4-bit exponent, a sign bit, and an 11-bit fraction -// x = 01.f * 2^e if s = 0 -// x = 10.f * 2^e if s = 1 -// x = 0 if e = -8 -static float conv16(int16 A) // Convertion of 16 bit TMS float to double -{ - int16 mask, f, i, s; - float mant; - int8 e; - - // exponent, signed 4 bit - e = A >> 12; - - // sign, boolean 1 bit - s = (A & 0x0800) >> 11; - - // fraction, unsigned 11 bit - f = A & 0x07FF; - - // Apparently the 16-bit format does not include - // NaN of Inf at all (the exponent is too small anyway); - // though this is a guess by omission (the documentation - // mention appropriate conversions for 32-bits but not for 16-bits). - // I think the 16-bit format is intended for short immediate values - // rather than FPU operations, so it makes some sense. - // - // Therefore, no account for NaN of Inf is done in the 16-bit format. - - if ( s ) - { - f ^= 0x07FF; - f++; - } - - mant = 1; // mantissa (1<M<2) - mask = 0x0800; // bit mask for the current bit - - for ( i = 0; i <= 11; i++ ) - { - if ( f & mask ) - mant += (float)pow(double(2), -i); - mask >>= 1; - } - - if ( e == -8 && f == 0 && s == 0 ) - mant = 0; - - return float(pow(double(-1), s) * mant * pow(double(2), e)); -} - -//-------------------------------------------------------------------------- -//lint -esym(818,m) -int idaapi tms_realcvt(void *m, ushort *e, ushort swt) -{ - int ret; - int32 A; - int16 B; - - union - { - float pfl; - int32 pint; - }; - - switch ( swt ) - { - case 0: // TmsFloat 16bit to e - memcpy(&B, m, 2); - pfl = conv16(B); - pint = swap32(pint); - ret = ieee_realcvt(&pint, e, 1); - break; - - case 1: // TmsFloat 32bit to e - memcpy(&A, m, 4); - pfl = conv32(A); - pint = swap32(pint); - ret = ieee_realcvt(&pint, e, 1); - break; - - default: - msg("real_cvt_error swt = %d \n", swt); - return -1; - } - return ret; -} - -//-------------------------------------------------------------------------- -const char *tms320c3x_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - select_device(IORESP_PORT|IORESP_INT); - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list /*va*/) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(-1, pm.idpflags); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new tms320c3x_t); - return 0; -} - -//---------------------------------------------------------------------- -ssize_t idaapi tms320c3x_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ tms320c3x"); - inf_set_be(true); // MSB first - inf_set_wide_high_byte_first(true); - init_analyzer(); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_newfile: // new file loaded - inf_set_wide_high_byte_first(false); - if ( inf_like_binary() ) - { - segment_t *s0 = get_first_seg(); - if ( s0 != NULL ) - { - set_segm_name(s0, "CODE"); - segment_t *s1 = get_next_seg(s0->start_ea); - for ( int i = dp; i <= rVds; i++ ) - { - set_default_sreg_value(s0, i, BADSEL); - set_default_sreg_value(s1, i, BADSEL); - } - } - select_device(IORESP_ALL); - } - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_oldfile: // old file loaded - inf_set_wide_high_byte_first(false); - idpflags = (ushort)helper.altval(-1); - ioh.restore_device(); - break; - - case processor_t::ev_is_basic_block_end: - { - const insn_t &insn = *va_arg(va, const insn_t *); - return is_basic_block_end(insn) ? 1 : 0; - } - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *op = va_arg(va, const op_t *); - return can_have_type(*op) ? 1 : -1; - } - - case processor_t::ev_realcvt: - { - void *m = va_arg(va, void *); - uint16 *e = va_arg(va, uint16 *); - uint16 swt = va_argi(va, uint16); - int code1 = tms_realcvt(m, e, swt); - return code1 == 0 ? 1 : code1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_gen_stkvar_def: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const member_t *mptr = va_arg(va, const member_t *); - sval_t v = va_arg(va, sval_t); - gen_stkvar_def(*ctx, mptr, v); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "TMS320C3x Series:" -static const char *const shnames[] = -{ - "TMS320C3", - NULL -}; -static const char *const lnames[] = -{ - FAMILY"Texas Instruments TMS320C3X", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_TMS320C3, // id - // flag - PRN_HEX - | PR_SEGS - | PR_SGROTHER - | PR_ALIGN - | PR_USE32 - | PR_DEFSEG32 - | PR_DELAYED, - // flag2 - PR2_REALCVT // the module has 'realcvt' event implementation - | PR2_IDP_OPTS, // the module has processor-specific configuration options - 32, // 32 bits in a byte for code segments - 32, // 32 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - dp, // first - rVds, // last - 1, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - TMS320C3X_null, - TMS320C3X_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 4,7,15,19 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - TMS320C3X_RETSU, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/tms320c3/tms320c3x.hpp b/idasdk75/module/tms320c3/tms320c3x.hpp deleted file mode 100644 index 61e50ba..0000000 --- a/idasdk75/module/tms320c3/tms320c3x.hpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _TMS320C3X_HPP -#define _TMS320C3X_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" - - -enum regnum_t -{ - // Extended-precision registers - r0 = 0, - r1, - r2, - r3, - r4, - r5, - r6, - r7, - // Auxiliary registers - ar0, - ar1, - ar2, - ar3, - ar4, - ar5, - ar6, - ar7, - - // Index register n - ir0, - ir1, - bk, // Block-size register - sp, // System-stack pointer - st, // Status register - ie, // CPU/DMA interrupt-enable register - if_reg, // CPU interrupt flag - iof, // I/O flag - rs, // Repeat start-address - re, // Repeat end-address - rc, // Repeat counter - // segment registers - dp, // DP register - rVcs, rVds // virtual registers for code and data segments -}; - - -//------------------------------------------------------------------ -// specific processor records - -#define phtype specflag1 // o_phrase: phrase type -//0 "*+arn(NN)" -//1 "*-arn(NN)" -//2 "*++arn(NN)" -//3 "*--arn(NN)" -//4 "*arn++(NN)" -//5 "*arn--(NN)" -//6 "*arn++(NN)%%" -//7 "*arn--(NN)%%" -//8 "*+arn(ir0)" -//9 "*-arn(ir0)" -//a "*++arn(ir0)" -//b "*--arn(ir0)" -//c "*arn++(ir0)" -//d "*arn--(ir0)" -//e "*arn++(ir0)%%" -//f "*arn--(ir0)%%" -//10 "*+arn(ir1)" -//11 "*-arn(ir1)" -//12 "*++arn(ir1)" -//13 "*--arn(ir1)" -//14 "*arn++(ir1)" -//15 "*arn--(ir1)" -//16 "*arn++(ir1)%%" -//17 "*arn--(ir1)%%" -//18 "*arn" -//19 "*arn++(ir0)B" - -#define itype2 segpref // 2-nd command type (within parallel instruction) -#define i2op insnpref // number of first operand that belong to 2-nd insn of parallel instruction -// auxpref flags: -#define DBrFlag 0x80 // Delayed branch flag -#define ImmFltFlag 0x40 // Imm float Value - -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -struct tms320c3x_iohandler_t : public iohandler_t -{ - tms320c3x_iohandler_t(netnode &nn) : iohandler_t(nn) {} - virtual bool entry_processing(ea_t &ea, const char *name, const char *cmt) override; -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct tms320c3x_t); - -struct ctx_t; -struct opcode_t; -struct tms320c3_table_t -{ - opcode_t *entries; - int size; - opcode_t &operator[](size_t i); - void create(const opcode_t src_table[], int src_table_size); - ~tms320c3_table_t(); -}; - -struct tms320c3x_t : public procmod_t -{ - netnode helper; - tms320c3x_iohandler_t ioh = tms320c3x_iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - tms320c3_table_t table; - ushort idpflags; // not used? - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - bool select_device(int lrespect_info); - const char *idaapi set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - int ana(insn_t *insn); - void init_analyzer(void); - void gen_masks(void); - int run_functions(ctx_t &ctx, int value, int entry, int start, int end); - int run_functions2(ctx_t &ctx, int value, int entry, int start, int end); - - int emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use); - - void header(outctx_t &ctx); - void assumes(outctx_t &ctx); - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void segstart(outctx_t &ctx, segment_t *seg) const; - void footer(outctx_t &ctx) const; - void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; -}; - -//------------------------------------------------------------------ -ea_t calc_code_mem(const insn_t &insn, const op_t &x); -ea_t calc_data_mem(const insn_t &insn, const op_t &x); - -regnum_t get_mapped_register(ea_t ea); -const char *get_cond8(char value); -int get_signed(int byte,int mask); - -//------------------------------------------------------------------ -void idaapi segend(outctx_t &, segment_t *seg); - -void idaapi data(outctx_t &ctx); - -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_align_insn(ea_t ea); -bool is_basic_block_end(const insn_t &insn); -bool idaapi can_have_type(const op_t &op); - -#endif // _TMS320C3X_HPP diff --git a/idasdk75/module/tms320c5/ana.cpp b/idasdk75/module/tms320c5/ana.cpp deleted file mode 100644 index 90ff955..0000000 --- a/idasdk75/module/tms320c5/ana.cpp +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 3.05 - * Copyright (c) 1990-95 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "tms.hpp" - -//---------------------------------------------------------------------- -inline ushort get_next_byte(insn_t &insn) -{ - return (ushort)get_wide_byte(insn.ea + insn.size++); -} - -//---------------------------------------------------------------------- -inline void op_daddr(insn_t &insn, op_t &o) // 16-bit address data -{ - o.type = o_mem; - o.addr = get_next_byte(insn); - o.sib = 1; -} - -//---------------------------------------------------------------------- -inline void op_paddr(insn_t &insn, op_t &o) // 16-bit address prog -{ - o.type = o_near; - o.addr = get_next_byte(insn); -} - -//---------------------------------------------------------------------- -inline void op_ioaddr(insn_t &insn, op_t &o) // 16-bit port address -{ - o.dtype = dt_word; - o.type = o_imm; - o.value = get_next_byte(insn); - o.sib = 1; -} - -//---------------------------------------------------------------------- -int tms320c5_t::op_iaa(const insn_t &insn, op_t &o) const // direct or indirect address -{ - if ( code & 0x80 ) - { - o.type = o_phrase; - o.phrase = (code & 0x7F); - if ( (o.phrase & 0x70) == 0x30 ) - return 0; - } - else - { - o.type = o_mem; - o.addr = (get_sreg(insn.ea, rDP)<<7) + (code & 0x7F); - o.sib = 0; - } - return 1; -} - -//---------------------------------------------------------------------- -int tms320c5_t::op_indir(op_t &o) // direct or indirect address -{ // optional - o.type = o_phrase; - o.phrase = (code & 0x7F); - if ( (o.phrase & 0x70) == 0x30 ) - return 0; - if ( (o.phrase & 0x70) == 0 ) - o.clr_shown(); - return 1; -} - -//---------------------------------------------------------------------- -int tms320c5_t::op_maa(const insn_t &insn, op_t &o) const // memory-mapped register from code -{ - if ( !op_iaa(insn, o) ) - return 0; - if ( o.type == o_mem ) - o.addr = (code & 0x7F); - return 1; -} - -//---------------------------------------------------------------------- -inline void op_ar(op_t &o, uint16 ar) // aux register -{ - o.type = o_reg; - o.reg = rAr0 + ar; -} - -//---------------------------------------------------------------------- -inline void op_imm(insn_t &insn, op_t &o) // 16-bit immediate -{ - o.dtype = dt_word; - o.type = o_imm; - o.value = get_next_byte(insn); - o.sib = 0; -} - -//---------------------------------------------------------------------- -inline void op_shift(op_t &o, int shift) // shift -{ - o.type = o_imm; - o.value = shift; - o.sib = 2; - if ( o.value == 0 ) - o.clr_shown(); -} - -//---------------------------------------------------------------------- -void tms320c5_t::op_short(op_t &o) const // short immediate -{ - o.dtype = dt_byte; - o.type = o_imm; - o.value = code & 0xFF; - o.sib = 0; -} - -//---------------------------------------------------------------------- -inline void op_cbit(op_t &o, int bit) -{ - o.type = o_bit; - o.value = bit; -} - -//---------------------------------------------------------------------- -int tms320c5_t::op_cond(op_t &o) const -{ - o.type = o_cond; - o.Cond = uint16(o.value = (code & 0x3FF)); - int mask = int(o.value>>0) & 0xF; - int cond = int(o.value>>4) & 0xF; - if ( ((mask>>2) & 3) == 3 ) // Z L - { - switch ( (cond>>2)&3 ) - { - case 0: - case 1: - return 0; - } - } - return 1; -} - -//---------------------------------------------------------------------- -void tms320c5_t::op_bit(op_t &o) const -{ - o.type = o_imm; -// strange? documentation say this way: o.value = 15 - ((code >> 8) & 0xF); -// assembler works this way: - o.value = (code >> 8) & 0xF; - o.sib = 3; -} - -//---------------------------------------------------------------------- -int tms320c5_t::ana_c2(insn_t &insn) -{ - uchar subcode = (code >> 8) & 0xF; - switch ( code >> 12 ) - { -// 0000 SSSS MDDD DDDD TMS2_add -// 0001 SSSS MDDD DDDD TMS2_sub -// 0010 SSSS MDDD DDDD TMS2_lac - case 0: - insn.itype = TMS2_add; - goto iaa_shift; - case 1: - insn.itype = TMS2_sub; - goto iaa_shift; - case 2: - insn.itype = TMS2_lac; -iaa_shift: - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_shift(insn.Op2, subcode); - break; - -// 0011 0RRR MDDD DDDD TMS2_lar -// 0011 1000 MDDD DDDD TMS2_mpy -// 0011 1001 MDDD DDDD TMS2_sqra -// 0011 1010 MDDD DDDD TMS2_mpya -// 0011 1011 MDDD DDDD TMS2_mpys -// 0011 1100 MDDD DDDD TMS2_lt -// 0011 1101 MDDD DDDD TMS2_lta -// 0011 1110 MDDD DDDD TMS2_ltp -// 0011 1111 MDDD DDDD TMS2_ltd - case 3: - if ( subcode < 8 ) - { - insn.itype = TMS2_lar; - op_ar(insn.Op1, subcode); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - } - else - { - static const uchar codes[8] = - { - TMS2_mpy, TMS2_sqra, TMS2_mpya, TMS2_mpys, - TMS2_lt, TMS2_lta, TMS2_ltp, TMS2_ltd - }; - insn.itype = codes[subcode-8]; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - } - break; - -// 0100 0000 MDDD DDDD TMS2_zalh -// 0100 0001 MDDD DDDD TMS2_zals -// 0100 0010 MDDD DDDD TMS2_lact -// 0100 0011 MDDD DDDD TMS2_addc -// 0100 0100 MDDD DDDD TMS2_subh -// 0100 0101 MDDD DDDD TMS2_subs -// 0100 0110 MDDD DDDD TMS2_subt -// 0100 0111 MDDD DDDD TMS2_subc -// 0100 1000 MDDD DDDD TMS2_addh -// 0100 1001 MDDD DDDD TMS2_adds -// 0100 1010 MDDD DDDD TMS2_addt -// 0100 1011 MDDD DDDD TMS2_rpt -// 0100 1100 MDDD DDDD TMS2_xor -// 0100 1101 MDDD DDDD TMS2_or -// 0100 1110 MDDD DDDD TMS2_and -// 0100 1111 MDDD DDDD TMS2_subb - case 4: - { - static const ushort codes[16] = - { - TMS2_zalh, TMS2_zals, TMS2_lact, TMS2_addc, - TMS2_subh, TMS2_subs, TMS2_subt, TMS2_subc, - TMS2_addh, TMS2_adds, TMS2_addt, TMS2_rpt, - TMS2_xor, TMS2_or, TMS2_and, TMS2_subb - }; - insn.itype = codes[subcode]; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - } - break; - -// 0101 0000 MDDD DDDD TMS2_lst -// 0101 0001 MDDD DDDD TMS2_lst1 -// 0101 0010 MDDD DDDD TMS2_ldp -// 0101 0011 MDDD DDDD TMS2_lph -// 0101 0100 MDDD DDDD TMS2_pshd -// 0101 0101 0000 0000 TMS2_nop -// 0101 0101 1000 1RRR TMS2_larp -// 0101 0101 MDDD DDDD TMS2_mar -// 0101 0110 MDDD DDDD TMS2_dmov -// 0101 0111 MDDD DDDD TMS2_bitt -// 0101 1000 MDDD DDDD TMS2_tblr -// 0101 1001 MDDD DDDD TMS2_tblw -// 0101 1010 MDDD DDDD TMS2_sqrs -// 0101 1011 MDDD DDDD TMS2_lts -// 0101 1100 MDDD DDDD +1 TMS2_macd -// 0101 1101 MDDD DDDD +1 TMS2_mac -// 0101 1110 1DDD DDDD +1 TMS2_bc -// 0101 1111 1DDD DDDD +1 TMS2_bnc - case 5: - { - static const ushort codes[16] = - { - TMS2_lst, TMS2_lst1, TMS2_ldp, TMS2_lph, - TMS2_pshd, TMS2_mar, TMS2_dmov, TMS2_bitt, - TMS2_tblr, TMS2_tblw, TMS2_sqrs, TMS2_lts, - TMS2_macd, TMS2_mac, TMS2_bc, TMS2_bnc - }; - insn.itype = codes[subcode]; - if ( subcode >= 12 ) - { - op_paddr(insn, insn.Op1); - if ( subcode >= 14 ) - { - if ( !op_indir(insn.Op2) ) - return 0; - } - else - { - if ( !op_iaa(insn, insn.Op2) ) - return 0; - } - } - else - { - if ( subcode == 5 ) - { - if ( (code & 0x80) == 0 ) - { - insn.itype = TMS2_nop; - insn.Op1.type = o_void; - break; - } - else if ( (code & 0xF8) == 0x88 ) - { - insn.itype = TMS2_larp; - insn.Op1.type = o_reg; - insn.Op1.reg = rAr0 + (code & 7); - break; - } - } - if ( !op_iaa(insn, insn.Op1) ) - return 0; - } - } - break; - -// 0110 0XXX MDDD DDDD TMS2_sacl -// 0110 1XXX MDDD DDDD TMS2_sach - case 6: - insn.itype = (subcode & 8) ? TMS2_sach : TMS2_sacl; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_shift(insn.Op2, subcode & 7); - break; - -// 0111 0RRR MDDD DDDD TMS2_sar -// 0111 1000 MDDD DDDD TMS2_sst -// 0111 1001 MDDD DDDD TMS2_sst1 -// 0111 1010 MDDD DDDD TMS2_popd -// 0111 1011 MDDD DDDD TMS2_zalr -// 0111 1100 MDDD DDDD TMS2_spl -// 0111 1101 MDDD DDDD TMS2_sph -// 0111 1110 KKKK KKKK TMS2_adrk -// 0111 1111 KKKK KKKK TMS2_sbrk - case 7: - if ( subcode < 8 ) - { - insn.itype = TMS2_sar; - op_ar(insn.Op1, subcode); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - } - else - { - static const ushort codes[8] = - { - TMS2_sst, TMS2_sst1, TMS2_popd, TMS2_zalr, - TMS2_spl, TMS2_sph, TMS2_adrk, TMS2_sbrk - }; - insn.itype = codes[subcode-8]; - if ( subcode >= 14 ) - op_short(insn.Op1); - else if ( !op_iaa(insn, insn.Op1) ) - return 0; - } - break; - -// 1000 AAAA MDDD DDDD TMS2_in - case 8: - insn.itype = TMS2_in; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - insn.Op2.value = subcode; - insn.Op2.type = o_imm; - insn.Op2.sib = 1; - break; - -// 1001 BBBB MDDD DDDD TMS2_bit - case 9: - insn.itype = TMS2_bit; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - insn.Op2.value = subcode; - insn.Op2.type = o_imm; - insn.Op2.sib = 0; - break; - -// 101K KKKK KKKK KKKK TMS2_mpyk - case 0xA: - case 0xB: - insn.itype = TMS2_mpyk; - insn.Op1.value = code & 0x1FFF; - if ( (insn.Op1.value & 0x1000) != 0 ) - insn.Op1.value |= ~0x1FFF; // extend sign - insn.Op1.type = o_imm; - insn.Op1.sib = 0; - break; - -// 1100 0RRR KKKK KKKK TMS2_lark -// 1100 100K KKKK KKKK TMS2_ldpk -// 1100 1010 0000 0000 TMS2_zac -// 1100 1010 KKKK KKKK TMS2_lack -// 1100 1011 KKKK KKKK TMS2_rptk -// 1100 1100 KKKK KKKK TMS2_addk -// 1100 1101 KKKK KKKK TMS2_subk -// 1100 1110 0000 0000 TMS2_eint -// 1100 1110 0000 0001 TMS2_dint -// 1100 1110 0000 0010 TMS2_rovm -// 1100 1110 0000 0011 TMS2_sovm -// 1100 1110 0000 0100 TMS2_cnfd -// 1100 1110 0000 0101 TMS2_cnfp -// 1100 1110 0000 0110 TMS2_rsxm -// 1100 1110 0000 0111 TMS2_ssxm -// 1100 1110 0000 10KK TMS2_spm -// 1100 1110 0000 1100 TMS2_rxf -// 1100 1110 0000 1101 TMS2_sxf -// 1100 1110 0000 111K TMS2_fort -// 1100 1110 0001 0100 TMS2_pac -// 1100 1110 0001 0101 TMS2_apac -// 1100 1110 0001 0110 TMS2_spac -// 1100 1110 0001 1000 TMS2_sfl -// 1100 1110 0001 1001 TMS2_sfr -// 1100 1110 0001 1011 TMS2_abs -// 1100 1110 0001 1100 TMS2_push -// 1100 1110 0001 1101 TMS2_pop -// 1100 1110 0001 1110 TMS2_trap -// 1100 1110 0001 1111 TMS2_idle -// 1100 1110 0010 0000 TMS2_rtxm -// 1100 1110 0010 0001 TMS2_stxm -// 1100 1110 0010 0011 TMS2_neg -// 1100 1110 0010 0100 TMS2_cala -// 1100 1110 0010 0101 TMS2_bacc -// 1100 1110 0010 0110 TMS2_ret -// 1100 1110 0010 0111 TMS2_cmpl -// 1100 1110 0011 0000 TMS2_rc -// 1100 1110 0011 0001 TMS2_sc -// 1100 1110 0011 0010 TMS2_rtc -// 1100 1110 0011 0011 TMS2_stc -// 1100 1110 0011 0100 TMS2_rol -// 1100 1110 0011 0101 TMS2_ror -// 1100 1110 0011 0110 TMS2_rfsm -// 1100 1110 0011 0111 TMS2_sfsm -// 1100 1110 0011 1000 TMS2_rhm -// 1100 1110 0011 1001 TMS2_shm -// 1100 1110 0011 11KK TMS2_conf -// 1100 1110 0101 00KK TMS2_cmpr -// 1100 1110 1AAA 0010 TMS2_norm -// 1100 1111 MDDD DDDD TMS2_mpyu - case 0xC: - switch ( subcode ) - { - default: // 1100 0RRR KKKK KKKK TMS2_lark - insn.itype = TMS2_lark; - op_ar(insn.Op1, subcode); - op_short(insn.Op2); - break; - case 8: - case 9: // 1100 100K KKKK KKKK TMS2_ldpk - insn.itype = TMS2_ldpk; - insn.Op1.dtype = dt_word; - insn.Op1.value = code & 0x1FF; - insn.Op1.type = o_imm; - insn.Op1.sib = 0; - break; - case 0xA: - if ( code == 0xCA00 ) - { - insn.itype = TMS2_zac; - break; - } - insn.itype = TMS2_lack; - goto LOAD_SHORT; - case 0xB: - insn.itype = TMS2_rptk; - op_short(insn.Op1); - insn.Op1.sib = 1; - break; - case 0xC: - insn.itype = TMS2_addk; - goto LOAD_SHORT; - case 0xD: - insn.itype = TMS2_subk; -LOAD_SHORT: - op_short(insn.Op1); - break; - case 0xE: - switch ( (code>>4) & 0xF ) - { - // 0000 0000 TMS2_eint - // 0000 0001 TMS2_dint - // 0000 0010 TMS2_rovm - // 0000 0011 TMS2_sovm - // 0000 0100 TMS2_cnfd - // 0000 0101 TMS2_cnfp - // 0000 0110 TMS2_rsxm - // 0000 0111 TMS2_ssxm - // 0000 10KK TMS2_spm - // 0000 1100 TMS2_rxf - // 0000 1101 TMS2_sxf - // 0000 111K TMS2_fort - case 0: - { - static const ushort codes[] = - { - TMS2_eint, TMS2_dint, TMS2_rovm, TMS2_sovm, - TMS2_cnfd, TMS2_cnfp, TMS2_rsxm, TMS2_ssxm, - TMS2_spm, TMS2_spm, TMS2_spm, TMS2_spm, - TMS2_rxf, TMS2_sxf, TMS2_fort, TMS2_fort - }; - insn.itype = codes[code & 0xF]; - if ( insn.itype == TMS2_spm ) - { - insn.Op1.value = code & 3; - insn.Op1.type = o_imm; - insn.Op1.sib = 0; - } - else if ( insn.itype == TMS2_fort ) - { - insn.Op1.value = code & 1; - insn.Op1.type = o_imm; - insn.Op1.sib = 0; - } - } - break; - - // 0001 0100 TMS2_pac - // 0001 0101 TMS2_apac - // 0001 0110 TMS2_spac - // 0001 1000 TMS2_sfl - // 0001 1001 TMS2_sfr - // 0001 1011 TMS2_abs - // 0001 1100 TMS2_push - // 0001 1101 TMS2_pop - // 0001 1110 TMS2_trap - // 0001 1111 TMS2_idle - case 1: - { - static const ushort codes[] = - { - TMS_null, TMS_null, TMS_null, TMS_null, - TMS2_pac, TMS2_apac, TMS2_spac, TMS_null, - TMS2_sfl, TMS2_sfr, TMS_null, TMS2_abs, - TMS2_push, TMS2_pop, TMS2_trap, TMS2_idle - }; - insn.itype = codes[code & 0xF]; - } - break; - - // 0010 0000 TMS2_rtxm - // 0010 0001 TMS2_stxm - // 0010 0011 TMS2_neg - // 0010 0100 TMS2_cala - // 0010 0101 TMS2_bacc - // 0010 0110 TMS2_ret - // 0010 0111 TMS2_cmpl - case 2: - if ( (code & 0xF) < 8 ) - { - static const ushort codes[] = - { - TMS2_rtxm, TMS2_stxm, TMS_null, TMS2_neg, - TMS2_cala, TMS2_bacc, TMS2_ret, TMS2_cmpl - }; - insn.itype = codes[code & 0xF]; - } - break; - - // 0011 0000 TMS2_rc - // 0011 0001 TMS2_sc - // 0011 0010 TMS2_rtc - // 0011 0011 TMS2_stc - // 0011 0100 TMS2_rol - // 0011 0101 TMS2_ror - // 0011 0110 TMS2_rfsm - // 0011 0111 TMS2_sfsm - // 0011 1000 TMS2_rhm - // 0011 1001 TMS2_shm - // 0011 11KK TMS2_conf - case 3: - if ( (code & 0xF) >= 0xC ) - { - insn.itype = TMS2_conf; - insn.Op1.value = code & 3; - insn.Op1.type = o_imm; - insn.Op1.sib = 0; - } - else - { - static const ushort codes[] = - { - TMS2_rc, TMS2_sc, TMS2_rtc, TMS2_stc, - TMS2_rol, TMS2_ror, TMS2_rfsm, TMS2_sfsm, - TMS2_rhm, TMS2_shm, TMS_null, TMS_null, - }; - insn.itype = codes[code & 0xF]; - } - break; - - // 0101 00KK TMS2_cmpr - case 5: - if ( (code & 0xC) == 0 ) - { - insn.itype = TMS2_cmpr; - insn.Op1.value = code & 3; - insn.Op1.type = o_imm; - insn.Op1.sib = 0; - } - break; - - // 1AAA 0010 TMS2_norm - case 0x8: - case 0x9: - case 0xA: - case 0xB: - case 0xC: - case 0xD: - case 0xE: - case 0xF: - insn.itype = TMS2_norm; - op_indir(insn.Op1); - break; - - default: - return 0; - } - break; - case 0xF: // 1100 1111 MDDD DDDD TMS2_mpyu - insn.itype = TMS2_mpyu; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - break; - } - break; - -// 1101 0RRR 0000 0000 +1 TMS2_lrlk -// 1101 SSSS 0000 0001 +1 TMS2_lalk -// 1101 SSSS 0000 0010 +1 TMS2_adlk -// 1101 SSSS 0000 0011 +1 TMS2_sblk -// 1101 SSSS 0000 0100 +1 TMS2_andk -// 1101 SSSS 0000 0101 +1 TMS2_ork -// 1101 SSSS 0000 0110 +1 TMS2_xork - case 0xD: - { - uint opcode = code & 0xFF; - if ( opcode == 0 ) - { - if ( subcode >= 8 ) - return 0; - insn.itype = TMS2_lrlk; - op_ar(insn.Op1, subcode); - op_imm(insn, insn.Op2); - } - else if ( opcode < 7 ) - { - static const ushort codes[] = - { - 0, TMS2_lalk, TMS2_adlk, TMS2_sblk, - TMS2_andk, TMS2_ork, TMS2_xork, - }; - insn.itype = codes[opcode]; - op_imm(insn, insn.Op1); - op_shift(insn.Op2, subcode); - } - else - { - return 0; - } - } - break; - -// 1110 AAAA MDDD DDDD TMS2_out - case 0xE: - insn.itype = TMS2_out; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - insn.Op2.value = subcode; - insn.Op2.type = o_imm; - insn.Op2.sib = 1; - break; - - // 1111 0000 1DDD DDDD +1 TMS2_bv - // 1111 0001 1DDD DDDD +1 TMS2_bgz - // 1111 0010 1DDD DDDD +1 TMS2_blez - // 1111 0011 1DDD DDDD +1 TMS2_blz - // 1111 0100 1DDD DDDD +1 TMS2_bgez - // 1111 0101 1DDD DDDD +1 TMS2_bnz - // 1111 0110 1DDD DDDD +1 TMS2_bz - // 1111 0111 1DDD DDDD +1 TMS2_bnv - // 1111 1000 1DDD DDDD +1 TMS2_bbz - // 1111 1001 1DDD DDDD +1 TMS2_bbnz - // 1111 1010 1DDD DDDD +1 TMS2_bioz - // 1111 1011 1DDD DDDD +1 TMS2_banz - // 1111 1100 MDDD DDDD +1 TMS2_blkp - // 1111 1101 MDDD DDDD +1 TMS2_blkd - // 1111 1110 1DDD DDDD +1 TMS2_call - // 1111 1111 1DDD DDDD +1 TMS2_b - case 0xF: - { - static const ushort codes[16] = - { - TMS2_bv, TMS2_bgz, TMS2_blez, TMS2_blz, - TMS2_bgez, TMS2_bnz, TMS2_bz, TMS2_bnv, - TMS2_bbz, TMS2_bbnz, TMS2_bioz, TMS2_banz, - TMS2_blkp, TMS2_blkd, TMS2_call, TMS2_b - }; - insn.itype = codes[subcode]; - op_paddr(insn, insn.Op1); - switch ( insn.itype ) - { - case TMS2_blkd: - insn.Op1.type = o_mem; - insn.Op1.sib = 1; - // fallthrough - case TMS2_blkp: - if ( !op_iaa(insn, insn.Op2) ) - return 0; - break; - default: - if ( !op_indir(insn.Op2) ) - return 0; - break; - } - } - break; - } - return 1; -} - -//---------------------------------------------------------------------- -//---------------------------------------------------------------------- -int tms320c5_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - code = get_next_byte(insn); - uchar subcode = (code >> 8) & 0xF; - uint nibble; - - if ( isC2() ) - { - if ( !ana_c2(insn) ) - return 0; - } - else - { - switch ( code >> 12 ) - { - case 0: - if ( subcode < 8 ) - { - insn.itype = TMS_lar; - op_ar(insn.Op1, subcode); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - } - else - { - { - static const uchar codes[8] = - { - TMS_lamm, TMS_smmr, TMS_subc, TMS_rpt, - TMS_out, TMS_ldp, TMS_lst, TMS_lst - }; - insn.itype = codes[subcode-8]; - } - if ( subcode == 0xC ) - op_ioaddr(insn, insn.Op2); - case08_common: - { - int ok = (subcode == 0x8 || subcode == 0x9) - ? op_maa(insn, insn.Op1) - : op_iaa(insn, insn.Op1); - if ( !ok ) - return 0; - } - if ( subcode == 0x9 ) - op_daddr(insn, insn.Op2); - if ( subcode >= 0xE ) - { - if ( insn.itype == TMS_sst ) - op_maa(insn, insn.Op1); - insn.Op2 = insn.Op1; - insn.Op2.n = 1; - insn.Op1.type = o_imm; - insn.Op1.value = subcode & 1; - insn.Op1.sib = 0; - } - } - break; - case 8: - if ( subcode < 8 ) - { - insn.itype = TMS_sar; - op_ar(insn.Op1, subcode); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - } - else - { - static const uchar codes[8] = - { - TMS_samm, TMS_lmmr, TMS_popd, TMS_mar, - TMS_spl, TMS_sph, TMS_sst, TMS_sst - }; - insn.itype = codes[subcode-8]; - if ( subcode == 0xB && (code & 0xFF) == 0 ) - { - insn.itype = TMS_nop; - insn.Op1.type = o_void; - break; - } - goto case08_common; - } - break; - case 1: - insn.itype = TMS_lacc; - goto iaa_shift; - case 2: - insn.itype = TMS_add; - goto iaa_shift; - case 3: - insn.itype = TMS_sub; - iaa_shift: - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_shift(insn.Op2, subcode); - break; - case 4: - insn.itype = TMS_bit; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_bit(insn.Op2); - break; - case 5: - { - static const uchar codes[16] = - { - TMS_mpya, TMS_mpys, TMS_sqra, TMS_sqrs, - TMS_mpy, TMS_mpyu, TMS_null, TMS_bldp, - TMS_xpl, TMS_opl, TMS_apl, TMS_cpl, - TMS_xpl2, TMS_opl2, TMS_apl2, TMS_cpl2 - }; - insn.itype = codes[subcode]; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_t *o; - if ( subcode >= 0xC ) - { - op_imm(insn, insn.Op1); - o = &insn.Op2; - } - else - { - o = &insn.Op1; - } - if ( !op_iaa(insn, *o) ) - return 0; - } - break; - case 6: - { - static const uchar codes[16] = - { - TMS_addc, TMS_add, TMS_adds, TMS_addt, - TMS_subb, TMS_sub, TMS_subs, TMS_subt, - TMS_zalr, TMS_lacl, TMS_lacc, TMS_lact, - TMS_xor, TMS_or, TMS_and, TMS_bitt - }; - insn.itype = codes[subcode]; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - if ( insn.itype == TMS_lacc - || insn.itype == TMS_add - || insn.itype == TMS_sub ) - { - op_shift(insn.Op2, 16); - } - } - break; - case 7: - { - static const uchar codes[16] = - { - TMS_lta, TMS_ltp, TMS_ltd, TMS_lt, - TMS_lts, TMS_lph, TMS_pshd, TMS_dmov, - TMS_adrk, TMS_b, TMS_call, TMS_banz, - TMS_sbrk, TMS_bd, TMS_calld, TMS_banzd - }; - insn.itype = codes[subcode]; - if ( subcode < 8 ) - { - if ( !op_iaa(insn, insn.Op1) ) - return 0; - } - else - { - if ( subcode != 8 && subcode != 0xC ) - { - op_paddr(insn, insn.Op1); - if ( !op_iaa(insn, insn.Op2) || insn.Op2.type != o_phrase ) - insn.itype = TMS_null; - } - else - { - op_short(insn.Op1); - } - } - } - break; - case 9: - insn.itype = (subcode & 8) ? TMS_sach : TMS_sacl; - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_shift(insn.Op2, subcode&7); - break; - case 0xA: - { - static const uchar codes[16] = - { - TMS_norm, TMS_null, TMS_mac, TMS_macd, - TMS_blpd, TMS_blpd, TMS_tblr, TMS_tblw, - TMS_bldd, TMS_bldd, TMS_mads, TMS_madd, - TMS_bldd, TMS_bldd, TMS_splk, TMS_in - }; - insn.itype = codes[subcode]; - switch ( subcode ) - { - case 0: - if ( !op_iaa(insn, insn.Op1) ) - return 0; - if ( (code & 0x80) == 0 ) - insn.itype = TMS_null; - break; - case 4: // blpd bmar, ? - case 0xC: // bldd bmar, ? - insn.Op1.type = o_reg; - insn.Op1.reg = rBMAR; - if ( !op_iaa(insn, insn.Op2) ) - return 0; - break; - case 0xD: // bldd ?, bmar - if ( !op_iaa(insn, insn.Op1) ) - return 0; - insn.Op2.type = o_reg; - insn.Op2.reg = rBMAR; - break; - case 2: // mac - case 3: // macd - case 5: // blpd - op_paddr(insn, insn.Op1); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - break; - case 8: - op_daddr(insn, insn.Op1); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - break; - case 9: - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_daddr(insn, insn.Op2); - break; - case 0xE: - op_imm(insn, insn.Op1); - if ( !op_iaa(insn, insn.Op2) ) - return 0; - break; - case 0xF: - if ( !op_iaa(insn, insn.Op1) ) - return 0; - op_ioaddr(insn, insn.Op2); - break; - default: - if ( !op_iaa(insn, insn.Op1) ) - return 0; - break; - } - } - break; - - case 0xB: - switch ( subcode ) - { - case 0: case 1: case 2: case 3: - case 4: case 5: case 6: case 7: - insn.itype = TMS_lar; - op_ar(insn.Op1, subcode); - op_short(insn.Op2); - break; - case 8: case 9: case 0xA: case 0xB: - case 0xC: - { - static const uchar codes[] = - { - TMS_add, TMS_lacl, TMS_sub, TMS_rpt, TMS_ldp - }; - insn.itype = codes[subcode-8]; - op_short(insn.Op1); - } - break; - case 0xD: - insn.itype = TMS_ldp; - op_short(insn.Op1); - insn.Op1.value |= 0x100; - break; - case 0xE: - nibble = (code & 0xF); - switch ( (code >> 4) & 0xF ) - { - case 0: case 1: case 2: case 3: - { - static const uchar codes[] = - { - TMS_abs, TMS_cmpl, TMS_neg, TMS_pac, - TMS_apac, TMS_spac, TMS_null, TMS_null, - TMS_null, TMS_sfl, TMS_sfr, TMS_null, - TMS_rol, TMS_ror, TMS_null, TMS_null, - - TMS_addb, TMS_adcb, TMS_andb, TMS_orb, - TMS_rolb, TMS_rorb, TMS_sflb, TMS_sfrb, - TMS_sbb, TMS_sbbb, TMS_xorb, TMS_crgt, - TMS_crlt, TMS_exar, TMS_sacb, TMS_lacb, - - TMS_bacc, TMS_baccd, TMS_idle, TMS_idle2, - TMS_null, TMS_null, TMS_null, TMS_null, - TMS_null, TMS_null, TMS_null, TMS_null, - TMS_null, TMS_null, TMS_null, TMS_null, - - TMS_cala, TMS_null, TMS_pop, TMS_null, - TMS_null, TMS_null, TMS_null, TMS_null, - TMS_reti, TMS_null, TMS_rete, TMS_null, - TMS_push, TMS_calad, TMS_null, TMS_null - }; - insn.itype = codes[code & 0x3F]; - } - break; - case 4: - insn.itype = (code & 1) ? TMS_setc : TMS_clrc; - op_cbit(insn.Op1, (code>>1)&7); - break; - case 5: - { - static const uchar codes[] = - { - TMS_null, TMS_trap, TMS_nmi, TMS_null, - TMS_null, TMS_null, TMS_null, TMS_null, - TMS_zpr, TMS_zap, TMS_sath, TMS_satl, - TMS_null, TMS_null, TMS_null, TMS_null - }; - insn.itype = codes[nibble]; - } - break; - case 6: - case 7: - insn.itype = TMS_intr; - insn.Op1.type = o_imm; - insn.Op1.value = (code & 0x1F); - insn.Op1.sib = 1; - break; - case 8: - if ( nibble < 4 ) - { - static const uchar codes[] = - { - TMS_mpy, TMS_and, TMS_or, TMS_xor - }; - insn.itype = codes[nibble]; - op_imm(insn, insn.Op1); - if ( nibble != 0 ) - op_shift(insn.Op2, 16); - } - break; - case 9: - if ( nibble == 0 ) - insn.itype = TMS_estop; - break; - case 0xC: - switch ( nibble ) - { - case 4: - insn.itype = TMS_rpt; - op_imm(insn, insn.Op1); - break; - case 5: - insn.itype = TMS_rptz; - op_imm(insn, insn.Op1); - break; - case 6: - insn.itype = TMS_rptb; - op_paddr(insn, insn.Op1); - break; - } - break; - } - break; - case 0xF: - nibble = (code & 0xF); - switch ( (code>>4) & 0xF ) - { - case 0: - if ( code & 8 ) - { - insn.itype = TMS_lar; - op_ar(insn.Op1, code & 7); - op_imm(insn, insn.Op2); - } - else - { - insn.itype = TMS_spm; - op_short(insn.Op1); - insn.Op1.sib = 1; - } - break; - case 4: - if ( (nibble & 0xC) == 4 ) - { - insn.itype = TMS_cmpr; - insn.Op1.type = o_imm; - insn.Op1.value = nibble & 3; - insn.Op1.sib = 1; - } - break; - case 0xE: - insn.itype = TMS_bsar; - op_shift(insn.Op1, nibble+1); - break; - case 8: - case 9: - case 0xA: - case 0xB: - case 0xC: - case 0xD: - { - static const uchar codes[] = - { - TMS_lacc, TMS_add, TMS_sub, TMS_and, TMS_or, TMS_xor - }; - insn.itype = codes[(code>>4) & 0x7]; - op_imm(insn, insn.Op1); - op_shift(insn.Op2, nibble); - } - break; - } - break; - } - break; - case 0xC: - case 0xD: - insn.itype = TMS_mpy; - insn.Op1.dtype = dt_word; - insn.Op1.type = o_imm; - insn.Op1.value = (code & 0x1FFF); - if ( (insn.Op1.value & 0x1000) != 0 ) - insn.Op1.value |= ~0x1FFF; // extend sign - insn.Op1.sib = 0; - break; - case 0xE: - case 0xF: - switch ( subcode>>2 ) - { - case 0: - insn.itype = (code & 0x1000) ? TMS_bcndd : TMS_bcnd; - op_paddr(insn, insn.Op1); - if ( !op_cond(insn.Op2) ) - return 0; - break; - case 1: - insn.itype = TMS_xc; - insn.Op1.type = o_imm; - insn.Op1.value = (code & 0x1000) ? 2 : 1; - insn.Op1.sib = 1; - if ( !op_cond(insn.Op2) ) - return 0; - break; - case 2: - insn.itype = (code & 0x1000) ? TMS_ccd : TMS_cc; - op_paddr(insn, insn.Op1); - if ( !op_cond(insn.Op2) ) - return 0; - break; - case 3: - if ( (code & 0xEFFF) == 0xEF00 ) - insn.itype = (code & 0x1000) ? TMS_retd : TMS_ret; - else - { - insn.itype = (code & 0x1000) ? TMS_retcd : TMS_retc; - if ( !op_cond(insn.Op1) ) - return 0; - } - break; - } - break; - } - } - if ( insn.itype == TMS_null ) - return 0; - return insn.size; -} diff --git a/idasdk75/module/tms320c5/ins.hpp b/idasdk75/module/tms320c5/ins.hpp deleted file mode 100644 index d52aa76..0000000 --- a/idasdk75/module/tms320c5/ins.hpp +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ -TMS_null = 0, // Unknown Operation -TMS_abs, // Absolute value of Acc -TMS_adcb, // Add ACCB to Acc With Carry -TMS_add, // Add to Acc -TMS_addb, // Add ACCB to Acc -TMS_addc, // Add to Acc With Carry -TMS_adds, // Add to Acc With Sign-Extension Suppressed -TMS_addt, // Add to Acc With Shift Specified by TREG1 -TMS_adrk, // Add to Aux Register With Short Immediate -TMS_and, // AND With Acc -TMS_andb, // AND ACCD With Acc -TMS_apac, // Add P Register to Acc -TMS_apl, // AND Data Memory Value With DBMR -TMS_apl2, // AND Data Memory Value With Long Constant -TMS_b, // Branch Unconditionally -TMS_bacc, // Branch to Location (Acc) -TMS_baccd, // Branch to Location (Acc) Delayed -TMS_banz, // Branch on Aux Register Not Zero -TMS_banzd, // Branch on Aux Register Not Zero Delayed -TMS_bcnd, // Branch Conditionally -TMS_bcndd, // Branch Conditionally Delayed -TMS_bd, // Branch Unconditionally Delayed -TMS_bit, // Test Bit -TMS_bitt, // Test Bit Specified by TREG2 -TMS_bldd, // Block Move From Data Memory to Data Memory -TMS_bldp, // Block Move From Data Memory to Program Memory -TMS_blpd, // Block Move From Program Memory to Data Memory -TMS_bsar, // Barrel Shift -TMS_cala, // Call Subroutine at (Acc) -TMS_calad, // Call Subroutine at (Acc) Delayed -TMS_call, // Call Unconditionally -TMS_calld, // Call Unconditionally Delayed -TMS_cc, // Call Conditionally -TMS_ccd, // Call Conditionally Delayed -TMS_clrc, // Clear Control Bit -TMS_cmpl, // Complement Acc -TMS_cmpr, // Compare Aux Register With ARCR -TMS_cpl, // Compare DBMR With Data Value -TMS_cpl2, // Compare Long Immediate With Data Value -TMS_crgt, // Test for Acc Greater Than ACCB -TMS_crlt, // Test for Acc Smaller Than ACCB -TMS_dmov, // Data Move in Data Memory -TMS_estop, // Emulator Stop -TMS_exar, // Exchange ACCB With Acc -TMS_idle, // Idle Until Interrupt -TMS_idle2, // Idle Until Interrupt - Low Power Mode -TMS_in, // Input Data From Port -TMS_intr, // Soft Interrupt -TMS_lacb, // Load Acc With ACCB -TMS_lacc, // Load Acc With Shift -TMS_lacl, // Load Low Acc and Clear High Acc -TMS_lact, // Load Acc With Shift Specified by TREG1 -TMS_lamm, // Load Acc With Memory-Mapped Register -TMS_lar, // Load Aux Register -TMS_ldp, // Load Data Memory Pointer -TMS_lmmr, // Load Memory-Mapped Register -TMS_lph, // Load Product High Register -TMS_lst, // Load Status Register -TMS_lt, // Load TREG0 -TMS_lta, // Load TREG0 and Accumulate Previous Product -TMS_ltd, // Load TREG0,Accumulate Previous Product and Move Data -TMS_ltp, // Load TREG0 and Store P -> Acc -TMS_lts, // Load TREG0 and Subtract Previous Product -TMS_mac, // Multiply and Accumulate -TMS_macd, // Multiply and Accumulate With Data Move -TMS_madd, // Multiply and Accumulate With Data Move and Dynamic Addressing -TMS_mads, // Multiply and Accumulate With Dynamic Addressing -TMS_mar, // Modify Aux Register -TMS_mpy, // Multiply -TMS_mpya, // Multiply and Accumulate Previous Product -TMS_mpys, // Multiply and Subtract Previous Product -TMS_mpyu, // Multiply Unsigned -TMS_neg, // Negate Acc -TMS_nmi, // Nonmaskable Interrupt -TMS_nop, // No Operation -TMS_norm, // Normalize Contents of Acc -TMS_opl, // OR With DBMS -TMS_opl2, // OR With Long Immediate -TMS_or, // OR With Acc -TMS_orb, // OR ACCB With Accumulator -TMS_out, // Out Data to Port -TMS_pac, // Load Acc <- P -TMS_pop, // Pop Top of Stack to Low Acc -TMS_popd, // Pop Top of Stack to Data Memory -TMS_pshd, // Push Data Memory Value Onto Stack -TMS_push, // Push Low Acc Onto Stack -TMS_ret, // Return From Subroutine -TMS_retc, // Return Conditionally -TMS_retcd, // Return Conditionally Delayed -TMS_retd, // Return From Subroutine Delayed -TMS_rete, // Enable Interrupts and Return From Interrupt -TMS_reti, // Return From Interrupt -TMS_rol, // Rotate Acc Left -TMS_rolb, // Rotate ACCB and Acc Left -TMS_ror, // Rotate Acc Right -TMS_rorb, // Rotate ACCB and Acc Right -TMS_rpt, // Repeat Next Instruction -TMS_rptb, // Repeat Block -TMS_rptz, // Repeat Preceded by Clearing Acc and P -TMS_sacb, // Store Acc in ACCB -TMS_sach, // Store High Acc With Shift -TMS_sacl, // Store Low Acc With Shift -TMS_samm, // Store Acc in Memory-Mapped Register -TMS_sar, // Store Aux Register -TMS_sath, // Barrel Shift Acc as Specified by TREG1(4) -TMS_satl, // Barrel Shift Acc as Specified by TREG1(3-0) -TMS_sbb, // Subtract ACCB From Acc -TMS_sbbb, // Subtract ACCB From Acc With Borrow -TMS_sbrk, // Subtract From Aux Register Short Immediate -TMS_setc, // Set Control Bit -TMS_sfl, // Shift Acc Left -TMS_sflb, // Shift ACCB and Acc Left -TMS_sfr, // Shift Acc Right -TMS_sfrb, // Shift ACCB and Acc Right -TMS_smmr, // Store Memory-Mapped Register -TMS_spac, // Subtract P From Acc -TMS_sph, // Store High P Register -TMS_spl, // Store Low P Register -TMS_splk, // Store Parallel Long Immediate -TMS_spm, // Store ACCB and Acc Right -TMS_sqra, // Square and Accumulate Previous Product -TMS_sqrs, // Square and Subtract Previous Product -TMS_sst, // Store Status Register -TMS_sub, // Subtract From Acc -TMS_subb, // Subtract From Acc With Borrow -TMS_subc, // Conditional Subtract -TMS_subs, // Subtract From Acc With Sign-Extension Suppressed -TMS_subt, // Subtract From Acc With Shift Specified by TREG1 -TMS_tblr, // Table Read -TMS_tblw, // Table Write -TMS_trap, // Software Interrupt -TMS_xc, // Execute Conditionally -TMS_xor, // Exclusive-OR With Acc -TMS_xorb, // Exclusive-OR of ACCB With Acc -TMS_xpl, // Exclusive-OR Data Memory Value -TMS_xpl2, // Exclusive-OR Data Memory Value -TMS_zalr, // Zero Low Acc Load High Acc With Rounding -TMS_zap, // Zero Acc and P -TMS_zpr, // Zero P Register - -// -// TMS320C2x instructions -// - -TMS2_abs, // Absolute value of accumulator -TMS2_add, // Add to accumulator with shift -TMS2_addc, // Add to accumulator with carry -TMS2_addh, // Add to high accumulator -TMS2_addk, // Add to accumulator short immediate -TMS2_adds, // Add to low accumulator with sign extension suppressed -TMS2_addt, // Add to accumulator with shift specified by T register -TMS2_adlk, // Add to accumulator long immediate with shift -TMS2_adrk, // Add to auxiliary register short immediate -TMS2_and, // And with accumulator -TMS2_andk, // And immediate with accumulator with shift -TMS2_apac, // App P register to accumulator -TMS2_b, // Branch unconditionally -TMS2_bacc, // Branch to address specified by accumulator -TMS2_banz, // Bnrach on auxiliary register not zero -TMS2_bbnz, // Branch if tc bit != 0 -TMS2_bbz, // Branch if tc bit = 0 -TMS2_bc, // Branch on carry -TMS2_bgez, // Branch if accumulator >= 0 -TMS2_bgz, // Branch if accumulator > 0 -TMS2_bioz, // Branch on i/o status = 0 -TMS2_bit, // Test bit -TMS2_bitt, // Test bit specifed by T register -TMS2_blez, // Branch if accumulator <= 0 -TMS2_blkd, // Block move from data memory to data memory -TMS2_blkp, // Block move from program memory to data memory -TMS2_blz, // Branch if accumulator < 0 -TMS2_bnc, // Branch on no carry -TMS2_bnv, // Branch if no overflow -TMS2_bnz, // Branch if accumulator != 0 -TMS2_bv, // Branch on overflow -TMS2_bz, // Branch if accumulator = 0 -TMS2_cala, // Call subroutine indirect -TMS2_call, // Call subroutine -TMS2_cmpl, // Complement accumulator -TMS2_cmpr, // Compare auxiliary register with auxiliary register ar0 -TMS2_cnfd, // Configure block as data memory -TMS2_cnfp, // Configure block as program memory -TMS2_conf, // Configure block as data/program memory -TMS2_dint, // Disable interrupt -TMS2_dmov, // Data move in data memory -TMS2_eint, // Enable interrupt -TMS2_fort, // Format serial port registers -TMS2_idle, // Idle until interrupt -TMS2_in, // Input data from port -TMS2_lac, // Load accumulator with shift -TMS2_lack, // Load accumulator short immediate -TMS2_lact, // Load accumulator with shift specified by T register -TMS2_lalk, // Load accumulator long immediate with shift -TMS2_lar, // Load auxiliary register -TMS2_lark, // Load auxiliary register short immediate -TMS2_larp, // Load auxiliary register pointer -TMS2_ldp, // Load data memory page pointer -TMS2_ldpk, // Load data memory page pointer immediate -TMS2_lph, // Load high P register -TMS2_lrlk, // Load auxiliary register long immediate -TMS2_lst, // Load status register ST0 -TMS2_lst1, // Load status register ST1 -TMS2_lt, // Load T register -TMS2_lta, // Load T register and accumulate previous product -TMS2_ltd, // Load T register, accumulate previous product and move data -TMS2_ltp, // Load T register and store P register in accumulator -TMS2_lts, // Load T register and subtract previous product -TMS2_mac, // Multiply and accumulate -TMS2_macd, // Multiply and accumulate with data move -TMS2_mar, // Modify auxiliary register -TMS2_mpy, // Multiply (with T register, store product in P register) -TMS2_mpya, // Multiply and accumulate previous product -TMS2_mpyk, // Multiply immediate -TMS2_mpys, // Multiply and subtract previous product -TMS2_mpyu, // Multiply unsigned -TMS2_neg, // Negate accumulator -TMS2_nop, // No operation -TMS2_norm, // Normalize contents of accumulator -TMS2_or, // Or with accumulator -TMS2_ork, // Or immediate with accumulator with shift -TMS2_out, // Output data to port -TMS2_pac, // Load accumulator with P register -TMS2_pop, // Pop top of stack to low accumulator -TMS2_popd, // Pop top of stack to data memory -TMS2_pshd, // Push data memory value onto stack -TMS2_push, // Push low accumulator onto stack -TMS2_rc, // Reset carry bit -TMS2_ret, // Return from subroutine -TMS2_rfsm, // Reset serial port frame synchronization mode -TMS2_rhm, // Reset hold mode -TMS2_rol, // Rotate accumulator left -TMS2_ror, // Rotate acuumulator right -TMS2_rovm, // Reset overflow mode -TMS2_rpt, // Repeat instruction as specified by data memory value -TMS2_rptk, // Repeat instruction as specified by immediate value -TMS2_rsxm, // Reset sign extension mode -TMS2_rtc, // Reset test/control flag -TMS2_rtxm, // Reset serial port transmit mode -TMS2_rxf, // Reset external flag -TMS2_sach, // Store high accumulator with shift -TMS2_sacl, // Store low accumulator with shift -TMS2_sar, // Store auxiliary register -TMS2_sblk, // Subtract from accumulator long immediate with shift -TMS2_sbrk, // Subtract from auxiliary register short immediate -TMS2_sc, // Set carry bit -TMS2_sfl, // Shift accumulator left -TMS2_sfr, // Shift accumulator right -TMS2_sfsm, // Set serial port frame synchronization mode -TMS2_shm, // Set hold mode -TMS2_sovm, // Set overflow mode -TMS2_spac, // Subtract P register from accumulator -TMS2_sph, // Store high P register -TMS2_spl, // Store low P register -TMS2_spm, // Set P register output shift mode -TMS2_sqra, // Square and accumulate -TMS2_sqrs, // Square and subtract previous product -TMS2_sst, // Store status register ST0 -TMS2_sst1, // Store status register ST1 -TMS2_ssxm, // Set sign extension mode -TMS2_stc, // Set test/control flag -TMS2_stxm, // Set serial port transmit mode -TMS2_sub, // Subtract from accumulator with shift -TMS2_subb, // Subtract from accumulator with borrow -TMS2_subc, // Conditional subtract -TMS2_subh, // Subtract from high accumulator -TMS2_subk, // Subtract from accumulator shoft immediate -TMS2_subs, // Subtract from low accumulator with sign extension suppressed -TMS2_subt, // Subtract from accumulator with shift specified by T register -TMS2_sxf, // Set external flag -TMS2_tblr, // Table read -TMS2_tblw, // Table write -TMS2_trap, // Software interrupt -TMS2_xor, // Exclusive or with accumulator -TMS2_xork, // Exclusive or immediate with accumulator with shift -TMS2_zac, // Zero accumulator -TMS2_zalh, // Zero low accumulator and load high accumulator -TMS2_zalr, // Zero low accumulator and load high accumulator with rounding -TMS2_zals, // Zero low accumulator and load high accumulator with sign extension suppressed - -TMS_last, - - }; - -#endif diff --git a/idasdk75/module/tms320c5/makefile b/idasdk75/module/tms320c5/makefile deleted file mode 100644 index b1caac5..0000000 --- a/idasdk75/module/tms320c5/makefile +++ /dev/null @@ -1,38 +0,0 @@ -PROC=tms320c5 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ana.cpp ins.hpp tms.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp emu.cpp ins.hpp tms.hpp -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ins.hpp out.cpp tms.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ins.hpp reg.cpp tms.hpp diff --git a/idasdk75/module/tms320c54/ins.cpp b/idasdk75/module/tms320c54/ins.cpp deleted file mode 100644 index c743e3e..0000000 --- a/idasdk75/module/tms320c54/ins.cpp +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "tms320c54.hpp" - -const instruc_t Instructions[] = -{ - - { "", 0 }, // Unknown Operation - - // ARITHMETIC OPERATIONS - - // ADD INSTRUCTIONS - - { "add", CF_CHG1 }, // Add to Accumulator - { "add", CF_USE1|CF_CHG2 }, // Add to Accumulator - { "add", CF_USE1|CF_USE2|CF_CHG3 }, // Add to Accumulator - { "addc", CF_USE1|CF_CHG2 }, // Add to Accumulator With Carry - { "addm", CF_USE1|CF_CHG2 }, // Add Long-Immediate Value to Memory - { "adds", CF_USE1|CF_CHG2 }, // Add to Accumulator With Sign-Extension Suppressed - - // SUBTRACT INSTRUCTIONS - - { "sub", CF_CHG1 }, // Sub From Accumulator - { "sub", CF_USE1|CF_CHG2 }, // Sub From Accumulator - { "sub", CF_USE1|CF_USE2|CF_CHG3 }, // Sub From Accumulator - { "subb", CF_USE1|CF_CHG2 }, // Sub From Accumulator With Borrow - { "subc", CF_USE1|CF_CHG2 }, // Subtract Conditionally - { "subs", CF_USE1|CF_CHG2 }, // Subtract From Accumulator With Sign Extension Suppressed - - // MULTIPLY INSTRUCTIONS - - { "mpy", CF_USE1|CF_CHG2 }, // Multiply Without Rounding - { "mpy", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Without Rounding - { "mpyr", CF_USE1|CF_CHG2 }, // Multiply With Rounding - { "mpya", CF_CHG1 }, // Multiply by Accumulator A - { "mpyu", CF_USE1|CF_CHG2 }, // Multiply Unsigned - { "squr", CF_USE1|CF_CHG2 }, // Square - - // MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS - - { "mac", CF_USE1|CF_CHG2 }, // Multiply Accumulate Without Rounding - { "mac", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Accumulate Without Rounding - { "macr", CF_USE1|CF_CHG2 }, // Multiply Accumulate With Rounding - { "macr", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Accumulate With Rounding - { "maca", CF_CHG1 }, // Multiply by Accumulator A and Accumulate Without Rounding - { "maca", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Accumulate Without Rounding - { "maca", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Accumulate Without Rounding - { "macar", CF_CHG1 }, // Multiply by Accumulator A and Accumulate With Rounding - { "macar", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Accumulate With Rounding - { "macar", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Accumulate With Rounding - { "macd", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Program Memory and Accumulate With Delay - { "macp", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Program Memory and Accumulate - { "macsu", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed by Unsigned and Accumulate - { "mas", CF_USE1|CF_CHG2 }, // Multiply and Subtract Without Rounding - { "mas", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply and Subtract Without Rounding - { "masr", CF_USE1|CF_CHG2 }, // Multiply and Subtract With Rounding - { "masr", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply and Subtract With Rounding - //TMS320C54_mas, - { "masa", CF_CHG1 }, // Multiply by Accumulator A and Subtract Without Rounding - { "masa", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Subtract Without Rounding - { "masa", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Subtract Without Rounding - { "masar", CF_CHG1 }, // Multiply by Accumulator A and Subtract With Rounding - { "masar", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Subtract With Rounding - { "masar", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Subtract With Rounding - { "squra", CF_USE1|CF_CHG2 }, // Square and Accumulate - { "squrs", CF_USE1|CF_CHG2 }, // Square and Subtract - - // DOUBLE INSTRUCTIONS - - { "dadd", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Add to Accumulator - { "dadd", CF_USE1|CF_USE2|CF_CHG3 }, // Double-Precision/Dual 16-Bit Add to Accumulator - { "dadst", CF_USE1|CF_CHG2 }, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract - { "drsub", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Subtract From Long Word - { "dsadt", CF_USE1|CF_CHG2 }, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add - { "dsub", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Subtract From Accumulator - { "dsubt", CF_USE1|CF_CHG2 }, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract - - // APPLICATION-SPECIFIC INSTRUCTIONS - - { "abdst", CF_USE1|CF_USE2 }, // Absolute distance - { "abs", CF_CHG1 }, // Absolute Value of Accumulator - { "abs", CF_USE1|CF_CHG2 }, // Absolute Value of Accumulator - { "cmpl", CF_CHG1 }, // Complement Accumulator - { "cmpl", CF_USE1|CF_CHG2 }, // Complement Accumulator - { "delay", CF_USE1 }, // Memory Delay - { "exp", CF_USE1 }, // Accumulator Exponent - { "firs", CF_USE1|CF_USE2 }, // Symmetrical Finite Impulse Response Filter - { "lms", CF_USE1|CF_USE2 }, // Least Mean Square - { "max", CF_CHG1 }, // Accumulator Maximum - { "min", CF_CHG1 }, // Accumulator Minimum - { "neg", CF_CHG1 }, // Negate Accumulator - { "neg", CF_USE1|CF_CHG2 }, // Negate Accumulator - { "norm", CF_CHG1 }, // Normalization - { "norm", CF_USE1|CF_CHG2 }, // Normalization - { "poly", CF_USE1 }, // Polynominal Evaluation - { "rnd", CF_CHG1 }, // Round Accumulator - { "rnd", CF_USE1|CF_CHG2 }, // Round Accumulator - { "sat", CF_CHG1 }, // Saturate Accumulator - { "sqdst", CF_USE1|CF_USE2 }, // Square Distance - - // LOGICAL OPERATIONS - - // AND INSTRUCTIONS - { "and", CF_CHG1 }, // AND With Accumulator - { "and", CF_USE1|CF_CHG2 }, // AND With Accumulator - { "and", CF_USE1|CF_USE2|CF_CHG3 }, // AND With Accumulator - { "andm", CF_USE1|CF_CHG2 }, // AND Memory With Long Immediate - - // OR INSTRUCTIONS - - { "or", CF_CHG1 }, // OR With Accumulator - { "or", CF_USE1|CF_CHG2 }, // OR With Accumulator - { "or", CF_USE1|CF_USE2|CF_CHG3 }, // OR With Accumulator - { "orm", CF_USE1|CF_CHG2 }, // OR Memory With Constant - - // XOR INSTRUCTIONS - - { "xor", CF_CHG1 }, // Exclusive OR With Accumulator - { "xor", CF_USE1|CF_CHG2 }, // Exclusive OR With Accumulator - { "xor", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive OR With Accumulator - { "xorm", CF_USE1|CF_CHG2 }, // Exclusive OR Memory With Constant - - // SHIFT INSTRUCTIONS - - { "rol", CF_CHG1 }, // Rotate Accumulator - { "roltc", CF_CHG1 }, // Rotate Accumulator Left Using TC - { "ror", CF_CHG1 }, // Rotate Accumulator Right - { "sfta", CF_CHG1|CF_USE2 }, // Shift Accumulator Arithmetically - { "sfta", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Accumulator Arithmetically - { "sftc", CF_CHG1 }, // Shift Accumulator Conditionally - { "sftl", CF_CHG1|CF_USE2 }, // Shift Accumulator Logically - { "sftl", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Accumulator Logically - - // TEST INSTRUCTIONS - - { "bit", CF_USE1|CF_USE2 }, // Test Bit - { "bitf", CF_USE1|CF_USE2 }, // Test Bit Field Specified by Immediate Value - { "bitt", CF_USE1 }, // Test Bit Specified by T - { "cmpm", CF_USE1|CF_USE2 }, // Compare Memory With Long Immediate - { "cmpr", CF_USE1|CF_USE2 }, // Compare Auxiliary Register with AR0 - - // PROGRAM CONTROL OPERATIONS - - // BRANCH INSTRUCTIONS - - { "b", CF_USE1|CF_STOP }, // Branch Unconditionally - { "bd", CF_USE1 }, // Branch Unconditionally - { "bacc", CF_USE1|CF_STOP }, // Branch to Location Specified by Accumulator - { "baccd", CF_USE1 }, // Branch to Location Specified by Accumulator - { "banz", CF_USE1|CF_USE2 }, // Branch on Auxiliary Register Not Zero - { "banzd", CF_USE1|CF_USE2 }, // Branch on Auxiliary Register Not Zero - { "bc", CF_USE1|CF_USE2 }, // Branch Conditionally - { "bc", CF_USE1|CF_USE2|CF_USE3 }, // Branch Conditionally - { "bcd", CF_USE1|CF_USE2 }, // Branch Conditionally - { "bcd", CF_USE1|CF_USE2|CF_USE3 }, // Branch Conditionally - { "fb", CF_USE1|CF_STOP }, // Far Branch Unconditionally - { "fbd", CF_USE1 }, // Far Branch Unconditionally - { "fbacc", CF_USE1 }, // Far Branch to Location Specified by Accumulator - { "fbaccd", CF_USE1 }, // Far Branch to Location Specified by Accumulator - - // CALL INSTRUCTIONS - - { "cala", CF_USE1|CF_CALL }, // Call Subroutine at Location Specified by Accumulator - { "calad", CF_USE1|CF_CALL }, // Call Subroutine at Location Specified by Accumulator - { "call", CF_USE1|CF_CALL }, // Call Unconditionally - { "calld", CF_USE1|CF_CALL }, // Call Unconditionally - { "cc", CF_USE1|CF_USE2|CF_CALL }, // Call Conditionally - { "cc", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Call Conditionally - { "ccd", CF_USE1|CF_USE2|CF_CALL }, // Call Conditionally - { "ccd", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Call Conditionally - { "fcala", CF_USE1|CF_CALL }, // Far Call Subroutine at Location Specified by Accumulator - { "fcalad", CF_USE1|CF_CALL }, // Far Call Subroutine at Location Specified by Accumulator - { "fcall", CF_USE1|CF_CALL }, // Far Call Unconditionally - { "fcalld", CF_USE1|CF_CALL }, // Far Call Unconditionally - - // INTERRUPT INSTRUCTIONS - - { "intr", CF_USE1|CF_CALL }, // Software Interrupt - { "trap", CF_USE1|CF_CALL }, // Software Interrupt - - // RETURN INSTRUCTIONS - - { "fret", CF_STOP }, // Far Return - { "fretd", 0 }, // Far Return - { "frete", CF_STOP }, // Enable Interrupts and Far Return From Interrupt - { "freted", 0 }, // Enable Interrupts and Far Return From Interrupt - { "rc", CF_USE1 }, // Return Conditionally - { "rc", CF_USE1|CF_USE2 }, // Return Conditionally - { "rc", CF_USE1|CF_USE2|CF_USE3 }, // Return Conditionally - { "rcd", CF_USE1 }, // Return Conditionally - { "rcd", CF_USE1|CF_USE2 }, // Return Conditionally - { "rcd", CF_USE1|CF_USE2|CF_USE3 }, // Return Conditionally - { "ret", CF_STOP }, // Return - { "retd", 0 }, // Return - { "rete", CF_STOP }, // Enable Interrupts and Far Return From Interrupt - { "reted", 0 }, // Enable Interrupts and Far Return From Interrupt - { "retf", CF_STOP }, // Enable Interrupts and Fast Return From Interrupt - { "retfd", 0 }, // Enable Interrupts and Fast Return From Interrupt - - // REPEAT INSTRUCTIONS - - { "rpt", CF_USE1 }, // Repeat Next Instruction - { "rptb", CF_USE1 }, // Block Repeat - { "rptbd", CF_USE1 }, // Block Repeat - { "rptz", CF_CHG1|CF_USE2 }, // Repeat Next Instruction And Clear Accumulator - - // STACK MANIPULATING INSTRUCTIONS - - { "frame", CF_USE1 }, // Stack Pointer Immediate Offset - { "popd", CF_CHG1 }, // Pop Top of Stack to Data Memory - { "popm", CF_CHG1 }, // Pop Top of Stack to Memory-Mapped Register - { "pshd", CF_USE1 }, // Push Data-Memory Value Onto Stack - { "pshm", CF_USE1 }, // Push Memory-Mapped Register Onto Stack - - // MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS - - { "idle", CF_USE1 }, // Idle Until Interrupt - { "mar", CF_USE1 }, // Modify Auxiliary Register - { "nop", 0 }, // No Operation - { "reset", 0 }, // Software Reset - { "rsbx", CF_CHG1 }, // Reset Status Register Bit - { "rsbx", CF_USE1|CF_USE2 }, // Reset Status Register Bit - { "ssbx", CF_CHG1 }, // Set Status Register Bit - { "ssbx", CF_USE1|CF_USE2 }, // Set Status Register Bit - { "xc", CF_USE1|CF_USE2 }, // Execute Conditionally - { "xc", CF_USE1|CF_USE2|CF_USE3 }, // Execute Conditionally - - // LOAD AND STORE OPERATIONS - - // LOAD INSTRUCTIONS - - { "dld", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator - { "ld", CF_CHG1 }, // Load Accumulator With Shift - { "ld", CF_USE1|CF_CHG2 }, // Load Accumulator With Shift - { "ld", CF_USE1|CF_USE2|CF_CHG3 }, // Load Accumulator With Shift - { "ldm", CF_USE1|CF_CHG2 }, // Load Memory-Mapped Register - { "ldr", CF_USE1|CF_CHG2 }, // Load Memory Value in Accumulator High With Rounding - { "ldu", CF_USE1|CF_CHG2 }, // Load Unsigned Memory Value - { "ltd", CF_USE1 }, // Load T and insert Delay - - // STORE INSTRUCTIONS - - { "dst", CF_USE1|CF_CHG2 }, // Store Accumulator in Long Word - { "st", CF_USE1|CF_CHG2 }, // Store T, TRN, or Immediate Value into Memory - { "sth", CF_USE1|CF_CHG2 }, // Store Accumulator High Into Memory - { "sth", CF_USE1|CF_USE2|CF_CHG3 }, // Store Accumulator High Into Memory - { "stl", CF_USE1|CF_CHG2 }, // Store Accumulator Low Into Memory - { "stl", CF_USE1|CF_USE2|CF_CHG3 }, // Store Accumulator Low Into Memory - { "stlm", CF_USE1|CF_CHG2 }, // Store Accumulator Low Into Memory-Mapped Register - { "stm", CF_USE1|CF_CHG2 }, // Store Immediate Value Into Memory-Mapped Register - - // CONDITIONAL STORE INSTRUCTIONS - - { "cmps", CF_USE1|CF_CHG2 }, // Compare, Select and Store Maximum - { "saccd", CF_USE1|CF_CHG2|CF_USE3 }, // Store Accumulator Conditionally - { "srccd", CF_CHG1|CF_USE2 }, // Store Block Repeat Counter Conditionally - { "strcd", CF_CHG1|CF_USE2 }, // Store T Conditionally - - // PARALLEL LOAD AND STORE INSTRUCTIONS - - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Load // TMS320C54_st_ld - - // PARALLEL LOAD AND MULTIPLY INSTRUCTIONS - - { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Accumulate Without Rounding // TMS320C54_ld_mac - { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Accumulate With Rounding // TMS320C54_ld_macr - { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Subtract Without Rounding // TMS320C54_ld_mas - { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Subtract With Rounding // TMS320C54_ld_masr - - // PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS - - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Add // TMS320C54_st_add - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Subtract // TMS320C54_st_sub - - // PARALLEL STORE AND MULTIPLY INSTRUCTIONS - - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Accumulate Without Rounding // TMS320C54_st_mac - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Accumulate With Rounding // TMS320C54_st_macr - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Subtract Without Rounding // TMS320C54_st_mas - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Subtract With Rounding // TMS320C54_st_masr - { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply // TMS320C54_st_mpy - - // MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS - - { "mvdd", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With X,Y Addressing - { "mvdk", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With Destination Addressing - { "mvdm", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Memory-Mapped Register - { "mvdp", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Program Memory - { "mvkd", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With Source Addressing - { "mvmd", CF_USE1|CF_CHG2 }, // Move Data From Memory-Mapped Register to Data Memory - { "mvmm", CF_USE1|CF_CHG2 }, // Move Data From Memory-Mapped Register to Memory-Mapped Register - { "mvpd", CF_USE1|CF_CHG2 }, // Move Data From Program Memory to Data Memory - { "portr", CF_USE1|CF_USE2 }, // Read Data From Port - { "portw", CF_USE1|CF_USE2 }, // Write Data to Port - { "reada", CF_CHG1 }, // Read Program Memory Addressed by Accumulator A and Store in Data Memory - { "writa", CF_USE1 }, // Write Data to Program Memory Addressed by Accumulator A - -}; - -CASSERT(qnumber(Instructions) == TMS320C54_last); diff --git a/idasdk75/module/tms320c54/ins.hpp b/idasdk75/module/tms320c54/ins.hpp deleted file mode 100644 index 74c5225..0000000 --- a/idasdk75/module/tms320c54/ins.hpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - -TMS320C54_null = 0, // Unknown Operation - -// ARITHMETIC OPERATIONS - -// ADD INSTRUCTIONS - -TMS320C54_add1, // Add to Accumulator -TMS320C54_add2, // Add to Accumulator -TMS320C54_add3, // Add to Accumulator -TMS320C54_addc, // Add to Accumulator With Carry -TMS320C54_addm, // Add Long-Immediate Value to Memory -TMS320C54_adds, // Add to Accumulator With Sign-Extension Suppressed - -// SUBTRACT INSTRUCTIONS - -TMS320C54_sub1, // Sub From Accumulator -TMS320C54_sub2, // Sub From Accumulator -TMS320C54_sub3, // Sub From Accumulator -TMS320C54_subb, // Sub From Accumulator With Borrow -TMS320C54_subc, // Subtract Conditionally -TMS320C54_subs, // Subtract From Accumulator With Sign Extension Suppressed - -// MULTIPLY INSTRUCTIONS - -TMS320C54_mpy2, // Multiply Without Rounding -TMS320C54_mpy3, // Multiply Without Rounding -TMS320C54_mpyr2, // Multiply With Rounding -TMS320C54_mpya, // Multiply by Accumulator A -TMS320C54_mpyu, // Multiply Unsigned -TMS320C54_squr, // Square - -// MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS - -TMS320C54_mac2, // Multiply Accumulate Without Rounding -TMS320C54_mac3, // Multiply Accumulate Without Rounding -TMS320C54_macr2, // Multiply Accumulate With Rounding -TMS320C54_macr3, // Multiply Accumulate With Rounding -TMS320C54_maca1, // Multiply by Accumulator A and Accumulate Without Rounding -TMS320C54_maca2, // Multiply by Accumulator A and Accumulate Without Rounding -TMS320C54_maca3, // Multiply by Accumulator A and Accumulate Without Rounding -TMS320C54_macar1, // Multiply by Accumulator A and Accumulate With Rounding -TMS320C54_macar2, // Multiply by Accumulator A and Accumulate With Rounding -TMS320C54_macar3, // Multiply by Accumulator A and Accumulate With Rounding -TMS320C54_macd, // Multiply by Program Memory and Accumulate With Delay -TMS320C54_macp, // Multiply by Program Memory and Accumulate -TMS320C54_macsu, // Multiply Signed by Unsigned and Accumulate -TMS320C54_mas2, // Multiply and Subtract Without Rounding -TMS320C54_mas3, // Multiply and Subtract Without Rounding -TMS320C54_masr2, // Multiply and Subtract With Rounding -TMS320C54_masr3, // Multiply and Subtract With Rounding -//TMS320C54_mas, -TMS320C54_masa1, // Multiply by Accumulator A and Subtract Without Rounding -TMS320C54_masa2, // Multiply by Accumulator A and Subtract Without Rounding -TMS320C54_masa3, // Multiply by Accumulator A and Subtract Without Rounding -TMS320C54_masar1, // Multiply by Accumulator A and Subtract With Rounding -TMS320C54_masar2, // Multiply by Accumulator A and Subtract With Rounding -TMS320C54_masar3, // Multiply by Accumulator A and Subtract With Rounding -TMS320C54_squra, // Square and Accumulate -TMS320C54_squrs, // Square and Subtract - -// DOUBLE INSTRUCTIONS - -TMS320C54_dadd2, // Double-Precision/Dual 16-Bit Add to Accumulator -TMS320C54_dadd3, // Double-Precision/Dual 16-Bit Add to Accumulator -TMS320C54_dadst, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract -TMS320C54_drsub, // Double-Precision/Dual 16-Bit Subtract From Long Word -TMS320C54_dsadt, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add -TMS320C54_dsub, // Double-Precision/Dual 16-Bit Subtract From Accumulator -TMS320C54_dsubt, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract - -// APPLICATION-SPECIFIC INSTRUCTIONS - -TMS320C54_abdst, // Absolute distance -TMS320C54_abs1, // Absolute Value of Accumulator -TMS320C54_abs2, // Absolute Value of Accumulator -TMS320C54_cmpl1, // Complement Accumulator -TMS320C54_cmpl2, // Complement Accumulator -TMS320C54_delay, // Memory Delay -TMS320C54_exp, // Accumulator Exponent -TMS320C54_firs, // Symmetrical Finite Impulse Response Filter -TMS320C54_lms, // Least Mean Square -TMS320C54_max, // Accumulator Maximum -TMS320C54_min, // Accumulator Minimum -TMS320C54_neg1, // Negate Accumulator -TMS320C54_neg2, // Negate Accumulator -TMS320C54_norm1, // Normalization -TMS320C54_norm2, // Normalization -TMS320C54_poly, // Polynominal Evaluation -TMS320C54_rnd1, // Round Accumulator -TMS320C54_rnd2, // Round Accumulator -TMS320C54_sat, // Saturate Accumulator -TMS320C54_sqdst, // Square Distance - -// LOGICAL OPERATIONS - -// AND INSTRUCTIONS - -TMS320C54_and1, // AND With Accumulator -TMS320C54_and2, // AND With Accumulator -TMS320C54_and3, // AND With Accumulator -TMS320C54_andm, // AND Memory With Long Immediate - -// OR INSTRUCTIONS - -TMS320C54_or1, // OR With Accumulator -TMS320C54_or2, // OR With Accumulator -TMS320C54_or3, // OR With Accumulator -TMS320C54_orm, // OR Memory With Constant - -// XOR INSTRUCTIONS - -TMS320C54_xor1, // Exclusive OR With Accumulator -TMS320C54_xor2, // Exclusive OR With Accumulator -TMS320C54_xor3, // Exclusive OR With Accumulator -TMS320C54_xorm, // Exclusive OR Memory With Constant - -// SHIFT INSTRUCTIONS - -TMS320C54_rol, // Rotate Accumulator -TMS320C54_roltc, // Rotate Accumulator Left Using TC -TMS320C54_ror, // Rotate Accumulator Right -TMS320C54_sfta2, // Shift Accumulator Arithmetically -TMS320C54_sfta3, // Shift Accumulator Arithmetically -TMS320C54_sftc, // Shift Accumulator Conditionally -TMS320C54_sftl2, // Shift Accumulator Logically -TMS320C54_sftl3, // Shift Accumulator Logically - -// TEST INSTRUCTIONS - -TMS320C54_bit, // Test Bit -TMS320C54_bitf, // Test Bit Field Specified by Immediate Value -TMS320C54_bitt, // Test Bit Specified by T -TMS320C54_cmpm, // Compare Memory With Long Immediate -TMS320C54_cmpr, // Compare Auxiliary Register with AR0 - -// PROGRAM CONTROL OPERATIONS - -// BRANCH INSTRUCTIONS - -TMS320C54_b, // Branch Unconditionally -TMS320C54_bd, // Branch Unconditionally -TMS320C54_bacc, // Branch to Location Specified by Accumulator -TMS320C54_baccd, // Branch to Location Specified by Accumulator -TMS320C54_banz, // Branch on Auxiliary Register Not Zero -TMS320C54_banzd, // Branch on Auxiliary Register Not Zero -TMS320C54_bc2, // Branch Conditionally -TMS320C54_bc3, // Branch Conditionally -TMS320C54_bcd2, // Branch Conditionally -TMS320C54_bcd3, // Branch Conditionally -TMS320C54_fb, // Far Branch Unconditionally -TMS320C54_fbd, // Far Branch Unconditionally -TMS320C54_fbacc, // Far Branch to Location Specified by Accumulator -TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator - -// CALL INSTRUCTIONS - -TMS320C54_cala, // Call Subroutine at Location Specified by Accumulator -TMS320C54_calad, // Call Subroutine at Location Specified by Accumulator -TMS320C54_call, // Call Unconditionally -TMS320C54_calld, // Call Unconditionally -TMS320C54_cc2, // Call Conditionally -TMS320C54_cc3, // Call Conditionally -TMS320C54_ccd2, // Call Conditionally -TMS320C54_ccd3, // Call Conditionally -TMS320C54_fcala, // Far Call Subroutine at Location Specified by Accumulator -TMS320C54_fcalad, // Far Call Subroutine at Location Specified by Accumulator -TMS320C54_fcall, // Far Call Unconditionally -TMS320C54_fcalld, // Far Call Unconditionally - -// INTERRUPT INSTRUCTIONS - -TMS320C54_intr, // Software Interrupt -TMS320C54_trap, // Software Interrupt - -// RETURN INSTRUCTIONS - -TMS320C54_fret, // Far Return -TMS320C54_fretd, // Far Return -TMS320C54_frete, // Enable Interrupts and Far Return From Interrupt -TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt -TMS320C54_rc1, // Return Conditionally -TMS320C54_rc2, // Return Conditionally -TMS320C54_rc3, // Return Conditionally -TMS320C54_rcd1, // Return Conditionally -TMS320C54_rcd2, // Return Conditionally -TMS320C54_rcd3, // Return Conditionally -TMS320C54_ret, // Return -TMS320C54_retd, // Return -TMS320C54_rete, // Enable Interrupts and Return From Interrupt -TMS320C54_reted, // Enable Interrupts and Return From Interrupt -TMS320C54_retf, // Enable Interrupts and Fast Return From Interrupt -TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt - -// REPEAT INSTRUCTIONS - -TMS320C54_rpt, // Repeat Next Instruction -TMS320C54_rptb, // Block Repeat -TMS320C54_rptbd, // Block Repeat -TMS320C54_rptz, // Repeat Next Instruction And Clear Accumulator - -// STACK MANIPULATING INSTRUCTIONS - -TMS320C54_frame, // Stack Pointer Immediate Offset -TMS320C54_popd, // Pop Top of Stack to Data Memory -TMS320C54_popm, // Pop Top of Stack to Memory-Mapped Register -TMS320C54_pshd, // Push Data-Memory Value Onto Stack -TMS320C54_pshm, // Push Memory-Mapped Register Onto Stack - -// MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS - -TMS320C54_idle, // Idle Until Interrupt -TMS320C54_mar, // Modify Auxiliary Register -TMS320C54_nop, // No Operation -TMS320C54_reset, // Software Reset -TMS320C54_rsbx1, // Reset Status Register Bit -TMS320C54_rsbx2, // Reset Status Register Bit -TMS320C54_ssbx1, // Set Status Register Bit -TMS320C54_ssbx2, // Set Status Register Bit -TMS320C54_xc2, // Execute Conditionally -TMS320C54_xc3, // Execute Conditionally - -// LOAD AND STORE OPERATIONS - -// LOAD INSTRUCTIONS - -TMS320C54_dld, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator -TMS320C54_ld1, // Load Accumulator With Shift -TMS320C54_ld2, // Load Accumulator With Shift -TMS320C54_ld3, // Load Accumulator With Shift -TMS320C54_ldm, // Load Memory-Mapped Register -TMS320C54_ldr, // Load Memory Value in Accumulator High With Rounding -TMS320C54_ldu, // Load Unsigned Memory Value -TMS320C54_ltd, // Load T and insert Delay - -// STORE INSTRUCTIONS - -TMS320C54_dst, // Store Accumulator in Long Word -TMS320C54_st, // Store T, TRN, or Immediate Value into Memory -TMS320C54_sth2, // Store Accumulator High Into Memory -TMS320C54_sth3, // Store Accumulator High Into Memory -TMS320C54_stl2, // Store Accumulator Low Into Memory -TMS320C54_stl3, // Store Accumulator Low Into Memory -TMS320C54_stlm, // Store Accumulator Low Into Memory-Mapped Register -TMS320C54_stm, // Store Immediate Value Into Memory-Mapped Register - -// CONDITIONAL STORE INSTRUCTIONS - -TMS320C54_cmps, // Compare, Select and Store Maximum -TMS320C54_saccd, // Store Accumulator Conditionally -TMS320C54_srccd, // Store Block Repeat Counter Conditionally -TMS320C54_strcd, // Store T Conditionally - -// PARALLEL LOAD AND STORE INSTRUCTIONS - -TMS320C54_st_ld, // Store Accumulator With Parallel Load - -// PARALLEL LOAD AND MULTIPLY INSTRUCTIONS - -TMS320C54_ld_mac, // Load Accumulator With Parallel Multiply Accumulate Without Rounding -TMS320C54_ld_macr, // Load Accumulator With Parallel Multiply Accumulate With Rounding -TMS320C54_ld_mas, // Load Accumulator With Parallel Multiply Subtract Without Rounding -TMS320C54_ld_masr, // Load Accumulator With Parallel Multiply Subtract With Rounding - -// PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS - -TMS320C54_st_add, // Store Accumulator With Parallel Add -TMS320C54_st_sub, // Store Accumulator With Parallel Subtract - -// PARALLEL STORE AND MULTIPLY INSTRUCTIONS - -TMS320C54_st_mac, // Store Accumulator With Parallel Multiply Accumulate Without Rounding -TMS320C54_st_macr, // Store Accumulator With Parallel Multiply Accumulate With Rounding -TMS320C54_st_mas, // Store Accumulator With Parallel Multiply Subtract Without Rounding -TMS320C54_st_masr, // Store Accumulator With Parallel Multiply Subtract With Rounding -TMS320C54_st_mpy, // Store Accumulator With Parallel Multiply - -// MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS - -TMS320C54_mvdd, // Move Data From Data Memory to Data Memory With X,Y Addressing -TMS320C54_mvdk, // Move Data From Data Memory to Data Memory With Destination Addressing -TMS320C54_mvdm, // Move Data From Data Memory to Memory-Mapped Register -TMS320C54_mvdp, // Move Data From Data Memory to Program Memory -TMS320C54_mvkd, // Move Data From Data Memory to Data Memory With Source Addressing -TMS320C54_mvmd, // Move Data From Memory-Mapped Register to Data Memory -TMS320C54_mvmm, // Move Data From Memory-Mapped Register to Memory-Mapped Register -TMS320C54_mvpd, // Move Data From Program Memory to Data Memory -TMS320C54_portr, // Read Data From Port -TMS320C54_portw, // Write Data to Port -TMS320C54_reada, // Read Program Memory Addressed by Accumulator A and Store in Data Memory -TMS320C54_writa, // Write Data to Program Memory Addressed by Accumulator A - -TMS320C54_last - -}; - -#endif diff --git a/idasdk75/module/tms320c54/makefile b/idasdk75/module/tms320c54/makefile deleted file mode 100644 index 87da605..0000000 --- a/idasdk75/module/tms320c54/makefile +++ /dev/null @@ -1,49 +0,0 @@ -PROC=tms32054 -CONFIGS=tms320c54.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp ins.hpp tms320c54.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp \ - tms320c54.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp tms320c54.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp tms320c54.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ins.hpp notify_codes.hpp \ - reg.cpp tms320c54.hpp diff --git a/idasdk75/module/tms320c54/notify_codes.hpp b/idasdk75/module/tms320c54/notify_codes.hpp deleted file mode 100644 index 99b0bf1..0000000 --- a/idasdk75/module/tms320c54/notify_codes.hpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __TMS320C54_NOTIFY_CODES_HPP -#define __TMS320C54_NOTIFY_CODES_HPP - -#include <idp.hpp> - -//---------------------------------------------------------------------- -// The following events are supported by the TMS320C54 module in the ph.notify() function -namespace tms320c54_module_t -{ - enum event_codes_t - { - ev_set_dataseg = processor_t::ev_loader + 2, - }; - - inline processor_t::event_t idp_ev(event_codes_t ev) - { - return processor_t::event_t(ev); - } - - inline void set_dataseg(ea_t ea) - { - processor_t::notify(idp_ev(ev_set_dataseg), ea); - } -} - -#endif // __TMS320C54_NOTIFY_CODES_HPP diff --git a/idasdk75/module/tms320c54/out.cpp b/idasdk75/module/tms320c54/out.cpp deleted file mode 100644 index beffe9c..0000000 --- a/idasdk75/module/tms320c54/out.cpp +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "tms320c54.hpp" -#include <frame.hpp> -#include <segregs.hpp> -#include <struct.hpp> - -// simple wrapper class for syntactic sugar of member functions -// this class may have only simple member functions. -// virtual functions and data fields are forbidden, otherwise the class -// layout may change -class out_tms320c54_t : public outctx_t -{ - out_tms320c54_t(void) = delete; // not used - - tms320c54_t &pm() { return *static_cast<tms320c54_t *>(procmod); } -public: - bool out_operand(const op_t &x); - void out_insn(void); - void out_address(ea_t ea, const op_t &x, bool mapping, bool at); - void out_cond8(char value); -}; -CASSERT(sizeof(out_tms320c54_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c54_t) - -//---------------------------------------------------------------------- -void out_tms320c54_t::out_address(ea_t ea, const op_t &x, bool mapping, bool at) -{ - regnum_t reg = pm().get_mapped_register(ea); - if ( mapping && reg != rnone ) - { - out_register(ph.reg_names[reg]); - } - else - { -#ifndef TMS320C54_NO_NAME_NO_REF - qstring qbuf; - // since tms320c54 uses memory mapping, we turn off verification - // of name expression values (4th arg of get_name_expr is BADADDR) - if ( get_name_expr(&qbuf, insn.ea+x.offb, x.n, ea, BADADDR) > 0 ) - { - if ( at ) - out_symbol('@'); - out_line(qbuf.begin()); - } - else -#endif - { - out_tagon(COLOR_ERROR); - out_value(x, OOFW_IMM|OOF_ADDR); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - } -} - -//---------------------------------------------------------------------- -const char *get_cond8(char value) -{ - switch ( value ) - { - case COND8_UNC: return "unc"; - case COND8_NBIO: return "nbio"; - case COND8_BIO: return "bio"; - case COND8_NC: return "nc"; - case COND8_C: return "c"; - case COND8_NTC: return "ntc"; - case COND8_TC: return "tc"; - case COND8_AGEQ: return "ageq"; - case COND8_ALT: return "alt"; - case COND8_ANEQ: return "aneq"; - case COND8_AEQ: return "aeq"; - case COND8_AGT: return "agt"; - case COND8_ALEQ: return "aleq"; - case COND8_ANOV: return "anov"; - case COND8_AOV: return "aov"; - case COND8_BGEQ: return "bgeq"; - case COND8_BLT: return "blt"; - case COND8_BNEQ: return "bneq"; - case COND8_BEQ: return "beq"; - case COND8_BGT: return "bgt"; - case COND8_BLEQ: return "bleq"; - case COND8_BNOV: return "bnov"; - case COND8_BOV: return "bov"; - default: return NULL; - } -} - -//---------------------------------------------------------------------- -void out_tms320c54_t::out_cond8(char value) -{ - const char *cond = get_cond8(value); - QASSERT(256, cond != NULL); - out_line(cond, COLOR_REG); -} - -//---------------------------------------------------------------------- -bool out_tms320c54_t::out_operand(const op_t &x) -{ - ea_t ea; - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - out_register(ph.reg_names[x.reg]); - break; - - case o_near: - case o_far: - ea = calc_code_mem(insn, x.addr, x.type == o_near); - out_address(ea, x, false, false); - break; - - case o_imm: - { - const char *name = NULL; - if ( pm().idpflags & TMS320C54_IO && x.IOimm ) - name = pm().find_sym(x.value); - if ( !x.NoCardinal ) - out_symbol('#'); - if ( name != NULL && name[0] != '\0' ) - { - out_line(name, COLOR_IMPNAME); - } - else - { - if ( !x.Signed ) - out_value(x, OOFW_IMM); - else - out_value(x, OOFS_IFSIGN|OOF_SIGNED|OOF_NUMBER|OOFW_IMM); - } - break; - } - - case o_local: - out_value(x, OOFW_IMM|OOF_ADDR); - break; - - case o_mmr: - case o_mem: - case o_farmem: - if ( x.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING ) - { - out_symbol('*'); - out_symbol('('); - } - ea = pm().calc_data_mem(insn, x.addr, x.type == o_mem); - if ( ea != BADADDR ) - { - // no '@' if absolute "indirect" adressing - bool at = x.IndirectAddressingMOD != ABSOLUTE_INDIRECT_ADRESSING; - out_address(ea, x, true, at); - } - else - { - out_value(x, OOFW_IMM|OOF_ADDR); - } - if ( x.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING ) - out_symbol(')'); - break; - - case o_displ: // Indirect addressing mode - { - char buf[8]; - const char *reg = ph.reg_names[x.reg]; - switch ( x.IndirectAddressingMOD ) - { - case 0: - qsnprintf(buf, sizeof(buf), "*%s",reg); - out_register(buf); - break; - case 1: - qsnprintf(buf, sizeof(buf), "*%s-",reg); - out_register(buf); - break; - case 2: - qsnprintf(buf, sizeof(buf), "*%s+",reg); - out_register(buf); - break; - case 3: - qsnprintf(buf, sizeof(buf), "*+%s",reg); - out_register(buf); - break; - case 4: - qsnprintf(buf, sizeof(buf), "*%s-0B",reg); - out_register(buf); - break; - case 5: - qsnprintf(buf, sizeof(buf), "*%s-0",reg); - out_register(buf); - break; - case 6: - qsnprintf(buf, sizeof(buf), "*%s+0",reg); - out_register(buf); - break; - case 7: - qsnprintf(buf, sizeof(buf), "*%s+0B",reg); - out_register(buf); - break; - case 8: - qsnprintf(buf, sizeof(buf), "*%s-%%",reg); - out_register(buf); - break; - case 9: - qsnprintf(buf, sizeof(buf), "*%s-0%%",reg); - out_register(buf); - break; - case 0xA: - qsnprintf(buf, sizeof(buf), "*%s+%%",reg); - out_register(buf); - break; - case 0xB: - qsnprintf(buf, sizeof(buf), "*%s+0%%",reg); - out_register(buf); - break; - case 0xC: - qsnprintf(buf, sizeof(buf), "*%s(",reg); - out_register(buf); - out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); - out_symbol(')'); - break; - case 0xD: - qsnprintf(buf, sizeof(buf), "*+%s(",reg); - out_register(buf); - out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); - out_symbol(')'); - break; - case 0xE: - qsnprintf(buf, sizeof(buf), "*+%s(",reg); - out_register(buf); - out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); - out_symbol(')'); - out_symbol('%'); - break; - // this special adressing mode is now defined as o_farmem ! - // case ABSOLUTE_INDIRECT_ADRESSING: - // out_symbol('*'); - // out_symbol('('); - // out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); - // out_symbol(')'); - // break; - default: - error("interr: out: o_displ"); - } - break; - } - - case o_bit: - { - if ( !x.NoCardinal ) - out_symbol('#'); - char buf[20]; - qsnprintf(buf, sizeof(buf), "%d", int(x.value)); - out_line(buf, COLOR_REG); - break; - } - - case o_cond8: - out_cond8((uchar)x.value); - break; - - case o_cond2: - { - const char *cond = ""; - switch ( x.value ) - { - case 0: cond = "eq"; break; - case 1: cond = "lt"; break; - case 2: cond = "gt"; break; - case 3: cond = "neq"; break; - default: warning("interr: out 2-bit condition"); - } - out_line(cond, COLOR_REG); - break; - } - - default: - error("interr: out"); - } - return 1; -} - -//---------------------------------------------------------------------- -void out_tms320c54_t::out_insn(void) -{ - out_mnemonic(); - out_one_operand(0); - if ( insn.Op2.type != o_void ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - if ( insn.IsParallel ) - { // new line for Parallel instructions - flush_outbuf(); - out_line("|| ", COLOR_INSN); - const char *insn2 = NULL; - switch ( insn.itype ) - { - case TMS320C54_ld_mac: insn2 = "mac "; break; - case TMS320C54_ld_macr: insn2 = "macr "; break; - case TMS320C54_ld_mas: insn2 = "mas "; break; - case TMS320C54_ld_masr: insn2 = "masr "; break; - case TMS320C54_st_add: insn2 = "add "; break; - case TMS320C54_st_sub: insn2 = "sub "; break; - case TMS320C54_st_ld: insn2 = "ld "; break; - case TMS320C54_st_mpy: insn2 = "mpy "; break; - case TMS320C54_st_mac: insn2 = "mac "; break; - case TMS320C54_st_macr: insn2 = "macr "; break; - case TMS320C54_st_mas: insn2 = "mas "; break; - case TMS320C54_st_masr: insn2 = "masr "; break; - default: warning("interr: out parallel instruction"); - } - out_line(insn2, COLOR_INSN); - } - if ( insn.Op3.type != o_void ) - { - if ( !insn.IsParallel ) - { - out_symbol(','); - out_char(' '); - } - out_one_operand(2); - if ( insn.Op4_type != 0 ) - { - out_symbol(','); - out_char(' '); - switch ( insn.Op4_type ) - { - case o_reg: - out_register(ph.reg_names[insn.Op4_value]); - break; - case o_cond8: - out_cond8(insn.Op4_value); - break; - default: - break; - } - } - } - } - - out_immchar_cmts(); - flush_outbuf(); -} - -//-------------------------------------------------------------------------- -void tms320c54_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) -{ - if ( reg == ph.reg_data_sreg ) - return; - if ( value != BADADDR ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), value); - ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); - } - else - { - ctx.gen_cmt_line("drop %s", ph.reg_names[reg]); - } -} - -//-------------------------------------------------------------------------- -// function to produce assume directives -//lint -e{1764} ctx could be const -void tms320c54_t::assumes(outctx_t &ctx) -{ - ea_t ea = ctx.insn_ea; - segment_t *seg = getseg(ea); - if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) - return; - bool seg_started = (ea == seg->start_ea); - - for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) - { - if ( i == ph.reg_code_sreg ) - continue; - sreg_range_t sra; - if ( !get_sreg_range(&sra, ea, i) ) - continue; - if ( seg_started || sra.start_ea == ea ) - { - sel_t now = get_sreg(ea, i); - sreg_range_t prev; - bool prev_exists = get_sreg_range(&prev, ea-1, i); - if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) ) - print_segment_register(ctx, i, now); - } - } -} - -//-------------------------------------------------------------------------- -//lint -e{818} seg could be const -void tms320c54_t::segstart(outctx_t &ctx, segment_t *seg) const -{ - if ( is_spec_segm(seg->type) ) - return; - - qstring sclas; - get_segm_class(&sclas, seg); - - if ( sclas == "CODE" ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR)); - else if ( sclas == "DATA" ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR)); - - if ( seg->orgbase != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), seg->orgbase); - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -void idaapi segend(outctx_t &, segment_t *) -{ -} - -//-------------------------------------------------------------------------- -void idaapi header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL | GH_BYTESEX_HAS_HIGHBYTE); - ctx.gen_empty_line(); -} - -//-------------------------------------------------------------------------- -void tms320c54_t::footer(outctx_t &ctx) const -{ - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s",SCOLOR_ASMDIR), ash.end); -} - -//-------------------------------------------------------------------------- -void tms320c54_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const -{ - char sign = ' '; - if ( v < 0 ) - { - sign = '-'; - v = -v; - } - - qstring name = get_member_name(mptr->id); - - char vstr[MAX_NUMBUF]; - btoa(vstr, sizeof(vstr), v); - ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) " " - COLSTR("%c%s",SCOLOR_DNUM) - COLSTR(",",SCOLOR_SYMBOL) " " - COLSTR("%s",SCOLOR_LOCNAME), - ash.a_equ, - sign, - vstr, - name.c_str()); -} - diff --git a/idasdk75/module/tms320c54/reg.cpp b/idasdk75/module/tms320c54/reg.cpp deleted file mode 100644 index a210c70..0000000 --- a/idasdk75/module/tms320c54/reg.cpp +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include "tms320c54.hpp" -#include "notify_codes.hpp" -#include <diskio.hpp> -#include <segregs.hpp> -#include <ieee.h> -static int data_id; - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "PC", // program counter - "A", // accumulator - "B", // accumulator - - // flags - "ASM", // 5-bit accumulator shift mode field in ST1 - "ARP", // auxiliary register pointer - "TS", // shift value (bits 5-0 of T) - "OVB", - "OVA", - "C", - "TC", - "CMPT", - "FRCT", - "C16", - "SXM", - "OVM", - "INTM", - "HM", - "XF", - "BRAF", - - // CPU memory mapped registers - "IMR", - "IFR", - "ST0", - "ST1", - "AL", - "AH", - "AG", - "BL", - "BH", - "BG", - "T", // temporary register - "TRN", // transition register - "AR0", - "AR1", - "AR2", - "AR3", - "AR4", - "AR5", - "AR6", - "AR7", - "SP", // stack pointer - "BK", - "BRC", - "RSA", - "REA", - "PMST", - - // segment registers - "XPC", // program counter extension register - "CPL", // compiler mode - "DP", // data page pointer - "cs","ds", // virtual registers for code and data segments -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0xF4, 0xE4 }; // fret -static const uchar retcode_1[] = { 0xF6, 0xE4 }; // fretd -static const uchar retcode_2[] = { 0xF4, 0xE5 }; // frete -static const uchar retcode_3[] = { 0xF6, 0xE5 }; // freted -static const uchar retcode_4[] = { 0xFC }; // rc -static const uchar retcode_5[] = { 0xFE }; // rcd -static const uchar retcode_6[] = { 0xFC, 0x00 }; // ret -static const uchar retcode_7[] = { 0xFE, 0x00 }; // retd -static const uchar retcode_8[] = { 0xF4, 0xEA }; // rete -static const uchar retcode_9[] = { 0xF6, 0xEA }; // reted -static const uchar retcode_10[] = { 0xF4, 0x9A }; // retf -static const uchar retcode_11[] = { 0xF6, 0x9A }; // retfd - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { sizeof(retcode_4), retcode_4 }, - { sizeof(retcode_5), retcode_5 }, - { sizeof(retcode_6), retcode_6 }, - { sizeof(retcode_7), retcode_7 }, - { sizeof(retcode_8), retcode_8 }, - { sizeof(retcode_9), retcode_9 }, - { sizeof(retcode_10), retcode_10 }, - { sizeof(retcode_11), retcode_11 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// TMS320C54 ASM -//----------------------------------------------------------------------- -static const asm_t fasm = -{ - AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON, - 0, - "ASM500", - 0, - NULL, // header lines - NULL, // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".pstring", // ascii string directive - ".word", // byte directive - ".long", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".space 16*%s",// uninited arrays - ".asg", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".ref", // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_STRINV // invert string byte order -}; - -//----------------------------------------------------------------------- -// GNU ASM -//----------------------------------------------------------------------- -static const asm_t gnuasm = -{ - AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON|AS_ASCIIC, - 0, - "GNU assembler", - 0, - NULL, // header lines - NULL, // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".pstring", // ascii string directive - ".word", // byte directive - ".long", // word directive - NULL, // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".zero 2*%s", // uninited arrays - ".asg", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - ".weak", // "weak" name keyword - ".extern", // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_STRINV, // invert string byte order - NULL, // cmnt2 - NULL, // low8 - NULL, // high8 - NULL, // low16 - NULL, // high16 - "#include \"%s\"", // a_include_fmt -}; - -static const asm_t *const asms[] = { &fasm, &gnuasm, NULL }; - -//-------------------------------------------------------------------------- -static const char *const cfgname = "tms320c54.cfg"; - -void tms320c54_t::load_symbols(void) -{ - ioh.ports.clear(); - read_ioports(&ioh.ports, &ioh.device, cfgname); -} - -const char *tms320c54_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port ? port->name.c_str() : NULL; -} - -//---------------------------------------------------------------------- -void tms320c54_t::apply_symbols(void) -{ - insn_t dummy; - for ( int i=0; i < ioh.ports.size(); i++ ) - { - ea_t ea = calc_data_mem(dummy, ioh.ports[i].address, false); - segment_t *s = getseg(ea); - if ( s == NULL || s->type != SEG_IMEM ) - continue; - create_byte(ea, 1); - const char *name = ioh.ports[i].name.c_str(); - if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) - set_cmt(ea, name, 0); - } -} - -//-------------------------------------------------------------------------- -void tms320c54_t::set_device_name(const char *dev) -{ - if ( dev != NULL ) - ioh.device = dev; -} - -//-------------------------------------------------------------------------- -inline void swap(unsigned char &c1, unsigned char &c2) -{ - unsigned char tmp = c1; - c1 = c2; - c2 = tmp; -} - -int idaapi tms_realcvt(void *m, ushort *e, ushort swt) -{ - int ret; - switch ( swt ) - { - case 1: // float to e - { - unsigned char p[4]; - memcpy(p, m, 4); - swap(p[0], p[1]); - swap(p[2], p[3]); - ret = ieee_realcvt(p, e, swt); - break; - } - case 011: // float output //-V536 octal - { - ret = ieee_realcvt(m, e, swt); - unsigned char *p = (unsigned char*)m; - swap(p[0], p[1]); - swap(p[2], p[3]); - break; - } - default: - ret = ieee_realcvt(m, e, swt); - } - return ret; -} - -//-------------------------------------------------------------------------- -static int idaapi choose_device(int, form_actions_t &fa) -{ - tms320c54_t &pm = *(tms320c54_t *)fa.get_ud(); - if ( choose_ioport_device(&pm.ioh.device, cfgname) ) - { - pm.load_symbols(); - pm.apply_symbols(); - } - return 0; -} - -//-------------------------------------------------------------------------- -const char *tms320c54_t::set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded) -{ - if ( keyword == NULL ) - { - static const char form[] = - "HELP\n" - "TMS320C54 specific options\n" - "\n" - " Use I/O definitions\n" - "\n" - " If this option is on, IDA will use I/O definitions\n" - " from the configuration file into a macro instruction.\n" - "\n" - " Detect memory mapped registers\n" - "\n" - " If this option is on, IDA will replace addresses\n" - " by an equivalent memory mapped register.\n" - "\n" - " Device name\n" - "\n" - " Choose the exact device name for the processor.\n" - " If you don't see the name you want, you can add\n" - " a section about it to the tms320c54.cfg file\n" - "\n" - " Data segment address\n" - "\n" - " The data segment linear address.\n" - "\n" - "ENDHELP\n" - "TMS320C54 specific options\n" - "%*\n" - " <Use ~I~/O definitions:C>\n" - " <Detect memory mapped ~r~egisters:C>>\n" - "\n" - " <~C~hoose device name:B:0:::>\n" - "\n" - " <~D~ata segment address:N::18::>\n" - "\n"; - CASSERT(sizeof(idpflags) == sizeof(ushort)); - CASSERT(sizeof(dataseg) == sizeof(ea_t)); - ask_form(form, this, &idpflags, choose_device, &dataseg); - } - else - { - if ( strcmp(keyword, "TMS320C54_DSEG") == 0 ) - { - if ( value_type != IDPOPT_NUM ) - return IDPOPT_BADTYPE; - dataseg = *(uval_t *)value; - } - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - if ( strcmp(keyword, "TMS320C54_IO") == 0 ) - { - setflag(idpflags, TMS320C54_IO, *(int*)value != 0); - } - else if ( strcmp(keyword, "TMS320C54_MMR") == 0 ) - { - setflag(idpflags, TMS320C54_MMR, *(int*)value != 0); - } - else - { - return IDPOPT_BADKEY; - } - } - if ( idb_loaded ) - { - helper.altset(0, dataseg); - helper.altset(-1, idpflags); - } - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -static const proctype_t ptypes[] = -{ - TMS320C54 -}; - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list /*va*/) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(0, pm.dataseg); - pm.helper.altset(-1, pm.idpflags); - pm.helper.supset(0, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(tms320c54_t)); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi tms320c54_t::on_event(ssize_t msgid, va_list va) -{ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4063) -#endif - int code = 0; - switch ( msgid ) // Cast to avoid lint complaining. - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ tms320c54"); - if ( helper.supstr(&ioh.device, 0) > 0 ) - set_device_name(ioh.device.c_str()); - inf_set_be(true); // MSB first - inf_set_wide_high_byte_first(true); - dataseg = helper.altval(0); - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: // new file loaded - inf_set_wide_high_byte_first(false); - { - segment_t *s = get_first_seg(); - if ( s != NULL ) - apply_symbols(); - while ( s != NULL ) - { - qstring sclas; - get_segm_class(&sclas, s); - for ( int i = XPC; i <= rVds; i++ ) - set_default_sreg_value(s, i, BADSEL); - if ( sclas == "CODE" ) - set_default_sreg_value(s, XPC, s->start_ea >> 16); - s = get_next_seg(s->start_ea); - } - } - break; - - case tms320c54_module_t::ev_set_dataseg: - dataseg = va_arg(va, ea_t); - break; - - case processor_t::ev_ending_undo: - ptype = ptypes[ph.get_proc_index()]; - //fall through - case processor_t::ev_oldfile: // old file loaded - inf_set_wide_high_byte_first(false); - idpflags = (ushort)helper.altval(-1); - break; - - case processor_t::ev_newbinary: - inf_set_wide_high_byte_first(true); - break; - case processor_t::ev_endbinary: - inf_set_wide_high_byte_first(false); - break; - - case processor_t::ev_newprc: // new processor type - { - ptype = ptypes[va_arg(va, int)]; - // bool keep_cfg = va_argi(va, bool); - switch ( ptype ) - { - case TMS320C54: - break; - default: - error("interr: setprc"); - } - ioh.device.qclear(); - load_symbols(); - } - break; - - case processor_t::ev_newasm: // new assembler type - break; - - case processor_t::ev_creating_segm: // new segment - break; - - case processor_t::ev_is_basic_block_end: - { - const insn_t *insn = va_arg(va, const insn_t *); - return is_basic_block_end(*insn) ? 1 : -1; - } - - case processor_t::ev_is_sane_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - int no_crefs = va_arg(va, int); - // add 0, a is not a sane instruction without crefs to it - code = no_crefs && get_wide_byte(insn->ea) == 0 ? -1 : 1; - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_realcvt: - { - void *m = va_arg(va, void *); - uint16 *e = va_arg(va, uint16 *); - uint16 swt = va_argi(va, uint16); - int code1 = tms_realcvt(m, e, swt); - return code1 == 0 ? 1 : code1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_get_frame_retsize: - { - int *frsize = va_arg(va, int *); - const func_t *pfn = va_arg(va, const func_t *); - *frsize = tms_get_frame_retsize(pfn); - return 1; - } - - case processor_t::ev_gen_stkvar_def: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const member_t *mptr = va_arg(va, const member_t *); - sval_t v = va_arg(va, sval_t); - gen_stkvar_def(*ctx, mptr, v); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } -#ifdef _MSC_VER -#pragma warning(pop) -#endif - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "TMS320C54x Series:" -static const char *const shnames[] = -{ - "TMS32054", - NULL -}; -static const char *const lnames[] = -{ - FAMILY"Texas Instruments TMS320C54", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_TMS320C54, // id - // flag - PRN_HEX - | PR_SEGS - | PR_SGROTHER - | PR_ALIGN, - // flag2 - PR2_MAPPINGS // use memory mapping - | PR2_REALCVT // the module has 'realcvt' event implementation - | PR2_IDP_OPTS, // the module has processor-specific configuration options - 16, // 16 bits in a byte for code segments - 16, // 16 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - XPC, // first - rVds, // last - 1, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - TMS320C54_null, - TMS320C54_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0,7,15,19 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - TMS320C54_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/tms320c54/tms320c54.hpp b/idasdk75/module/tms320c54/tms320c54.hpp deleted file mode 100644 index 764be8c..0000000 --- a/idasdk75/module/tms320c54/tms320c54.hpp +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _TMS320C54_HPP -#define _TMS320C54_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -// #define TMS320C54_NO_NAME_NO_REF - -//------------------------------------------------------------------ -#ifdef _MSC_VER -#define ENUM8BIT : uint8 -#else -#define ENUM8BIT -#endif -enum regnum_t ENUM8BIT -{ - PC, // program counter - A, // accumulator - B, // accumulator - - // flags - ASM, // 5-bit accumulator shift mode field in ST1 - ARP, // auxiliary register pointer - TS, // shift value (bits 5-0 of T) - OVB, - OVA, - C, - TC, - CMPT, - FRCT, - C16, - SXM, - OVM, - INTM, - HM, - XF, - BRAF, - - // CPU memory mapped registers - IMR, - IFR, - ST0, - ST1, - AL, - AH, - AG, - BL, - BH, - BG, - T, // temporary register - TRN, // transition register - AR0, - AR1, - AR2, - AR3, - AR4, - AR5, - AR6, - AR7, - SP, // stack pointer - BK, - BRC, - RSA, - REA, - PMST, - - // segment registers - XPC, // program counter extension register - CPL, // compiler mode - DP, // data page pointer - rVcs, rVds, // virtual registers for code and data segments - rnone = 0xFF, // no register -}; - -//------------------------------------------------------------------ -// specific condition codes -#define COND_A 0x0 -#define COND_B 0x8 - -#define COND_GEQ 0x2 -#define COND_LT 0x3 -#define COND_NEQ 0x4 -#define COND_EQ 0x5 -#define COND_GT 0x6 -#define COND_LEQ 0x7 - - -#define COND4_AGEQ (COND_A | COND_GEQ) -#define COND4_ALT (COND_A | COND_LT) -#define COND4_ANEQ (COND_A | COND_NEQ) -#define COND4_AEQ (COND_A | COND_EQ) -#define COND4_AGT (COND_A | COND_GT) -#define COND4_ALEQ (COND_A | COND_LEQ) - -#define COND4_BGEQ (COND_B | COND_GEQ) -#define COND4_BLT (COND_B | COND_LT) -#define COND4_BNEQ (COND_B | COND_NEQ) -#define COND4_BEQ (COND_B | COND_EQ) -#define COND4_BGT (COND_B | COND_GT) -#define COND4_BLEQ (COND_B | COND_LEQ) - - -#define COND8_FROM_COND4 0x40 - -#define COND8_UNC 0x00 -#define COND8_NBIO 0x02 -#define COND8_BIO 0x03 -#define COND8_NC 0x08 -#define COND8_C 0x0C -#define COND8_NTC 0x20 -#define COND8_TC 0x30 -#define COND8_AGEQ (COND8_FROM_COND4 | COND4_AGEQ) -#define COND8_ALT (COND8_FROM_COND4 | COND4_ALT) -#define COND8_ANEQ (COND8_FROM_COND4 | COND4_ANEQ) -#define COND8_AEQ (COND8_FROM_COND4 | COND4_AEQ) -#define COND8_AGT (COND8_FROM_COND4 | COND4_AGT) -#define COND8_ALEQ (COND8_FROM_COND4 | COND4_ALEQ) -#define COND8_ANOV 0x60 -#define COND8_AOV 0x70 -#define COND8_BGEQ (COND8_FROM_COND4 | COND4_BGEQ) -#define COND8_BLT (COND8_FROM_COND4 | COND4_BLT) -#define COND8_BNEQ (COND8_FROM_COND4 | COND4_BNEQ) -#define COND8_BEQ (COND8_FROM_COND4 | COND4_BEQ) -#define COND8_BGT (COND8_FROM_COND4 | COND4_BGT) -#define COND8_BLEQ (COND8_FROM_COND4 | COND4_BLEQ) -#define COND8_BNOV (COND_B | COND8_ANOV) -#define COND8_BOV (COND_B | COND8_AOV) - -//------------------------------------------------------------------ -// specific processor records - -#define o_bit o_idpspec0 -#define o_cond8 o_idpspec1 -#define o_cond2 o_idpspec2 -#define o_local o_idpspec3 -#define o_mmr o_idpspec4 -#define o_farmem o_idpspec5 - -#define Op4_type auxpref_u8[0] -#define Op4_value auxpref_u8[1] -#define IsParallel segpref - -// != 0 => MOD = IndirectAddressingMOD-1 -#define IndirectAddressingMOD specflag1 -#define ABSOLUTE_INDIRECT_ADRESSING 0xF // special "indirect" adressing - // (in fact absolute adressing) -#define Signed specflag1 -#define NoCardinal specflag2 -#define IOimm specflag3 - -//------------------------------------------------------------------ -// processor types - -typedef uchar proctype_t; - -const proctype_t TMS320C54 = 0; - -#define TMS320C54_IO 0x0001 // use I/O definitions -#define TMS320C54_MMR 0x0002 // use memory mapped registers - -//------------------------------------------------------------------ - -struct tms320c54_iohandler_t : public iohandler_t -{ - tms320c54_iohandler_t(netnode &nn) : iohandler_t(nn) {} -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct tms320c54_t); - -struct tms320c54_t : public procmod_t -{ - netnode helper; - tms320c54_iohandler_t ioh = tms320c54_iohandler_t(helper); - idb_listener_t idb_listener = idb_listener_t(*this); - - ea_t dataseg; - ushort idpflags = TMS320C54_IO|TMS320C54_MMR; - proctype_t ptype = TMS320C54; - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - void load_symbols(void); - const char *find_sym(ea_t address); - void apply_symbols(void); - void set_device_name(const char *dev); - const char *idaapi set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - - int ana(insn_t *insn); - - int emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use); - ea_t calc_data_mem(const insn_t &insn, ea_t ea, bool is_mem) const; - bool create_func_frame(func_t *pfn) const; - regnum_t get_mapped_register(ea_t ea) const; - - void assumes(outctx_t &ctx); - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void segstart(outctx_t &ctx, segment_t *seg) const; - void footer(outctx_t &ctx) const; - void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; -}; - -ea_t calc_code_mem(const insn_t &insn, ea_t ea, bool is_near = true); - -const char *get_cond8(char value); - -//------------------------------------------------------------------ -void idaapi header(outctx_t &ctx); - -void idaapi segend(outctx_t &ctx, segment_t *seg); - -void idaapi data(ea_t ea); - -int idaapi tms_get_frame_retsize(const func_t *pfn); -int idaapi is_align_insn(ea_t ea); -bool is_basic_block_end(const insn_t &insn); // 0-no, 2-yes - -#endif // _TMS320C54_HPP diff --git a/idasdk75/module/tms320c55/ana.cpp b/idasdk75/module/tms320c55/ana.cpp deleted file mode 100644 index 5901b24..0000000 --- a/idasdk75/module/tms320c55/ana.cpp +++ /dev/null @@ -1,1897 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * Texas Instruments's TMS5320C55 - * - */ - -//lint -e704 shift right of signed quantity -//lint -e1764 could be declared const - -#include "tms320c55.hpp" -#include <segregs.hpp> - -#define MAX_BYTE_USER_PARALLELIZED 0x5F -#define BYTE_MMAP 0x98 -#define BYTE_PORT1 0x99 -#define BYTE_PORT2 0x9A -#define BYTE_LR 0x9C -#define BYTE_CR 0x9D - -//-------------------------------------------------------------------------- -// class to store a bytes cache -#define BYTES_SIZE 32 // maximum cache size (maximum number of bytes) -class bytes_c -{ -public: - bytes_c(insn_t &_insn) : insn(_insn), size(0), i(0) - { - memset(bytes, 0, sizeof(bytes)); - } -private: - insn_t &insn; - int bytes[BYTES_SIZE]; - int size; - int i; -public: - void reset(void) { i = 0; } - int get_next(void); - int get(int j) const { return bytes[j]; } - void set_cache(bytevec_t &bytes); -}; - -//-------------------------------------------------------------------------- -// get the next byte -int bytes_c::get_next(void) -{ - if ( i == size ) - { - // if ( size >= CACHE_SIZE ) return NULL; - // load a new byte into the cache - bytes[size] = get_byte(insn.ea+size); - size++; - } - return bytes[i++]; -} - -//-------------------------------------------------------------------------- -// set cache contents -void bytes_c::set_cache(bytevec_t &_bytes) -{ - int n = _bytes.size(); - n = qmin(n, qnumber(bytes)); //lint !e666 expression with side effects - for ( size_t j=0; j < n; j++ ) - bytes[j] = _bytes[j]; - size = n; - reset(); -} - -#define OP_MASK_N 15 // maximum nomber of op_mask_t for an instruction - -struct mask_t; - -// function to generate an operand -typedef void (*func_op_mask_t)(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &optional_op); - -typedef struct -{ - func_op_mask_t func; // function to set operand - int64 mask; // mask of operand -} op_mask_t; - -struct mask_t -{ - int64 code; // full opcode of instruction - int64 mask; // full mask of instruction - char size; // number of bytes for instruction - ushort itype; //lint !e958 padding is required to align members - op_mask_t op_mask[OP_MASK_N]; //lint !e958 padding is required to align members - // function and mask to set operands -}; - -//-------------------------------------------------------------------------- -// verify if a given byte match a byte (0 <= n <= mask_t.size-1) from a code and mask -static bool byte_match_code_mask(const mask_t *mask, int64 byte, char n, char lbytesize = 8) -{ - // compute nshift and nmask - int nshift = (mask->size - 1 - n) * lbytesize; - int64 nmask = 0; - for ( int i = 0; i < lbytesize; i++ ) - nmask = (nmask << 1) | 1; - - // shift code and mask to get current byte - int64 mask_code = (mask->code >> nshift) & nmask; - int64 mask_mask = (mask->mask >> nshift) & nmask; - byte &= nmask; - - return (mask_code & mask_mask) == (byte & mask_mask); -} - -//-------------------------------------------------------------------------- -#define OP_BITS 30 // bits effectively reserved for masks (other bits are reserved for special operators) -#define OP_MASK (~(int64(0xFFFFFFFF) << OP_BITS)) // effective mask -#define OP_MASK_5 (~(make_ulonglong(0x3FFFFFF, 0) << (OP_BITS+8))) // effective mask -#define OP_MASK_6 (~(make_ulonglong(0x3FFFF, 0) << (OP_BITS+16))) // effective mask -#define OP_OP_NULL 0 -#define OP_OP_IMM 1 -#define OP_IMM(imm) ((OP_OP_IMM << OP_BITS)|(imm)) // return offset = imm -#define OP_TRUE OP_IMM(1) // return offset = 1 -#define OP_OP_NOT 2 -#define OP_NOT(mask) ((OP_OP_NOT << OP_BITS)|(mask)) // return (~offset) & 1 -// return a masked operand or the result of a special operation -#define OP_IMM_5(imm) (make_longlong(0x00000000, 0x40)|(imm)) // return offset = imm -#define OP_IMM_6(imm) (make_longlong(0x00000000, 0x4000)|(imm)) // return offset = imm -#define OP_TRUE_5 OP_IMM_5(1) // return offset = 1 -#define OP_TRUE_6 OP_IMM_6(1) // return offset = 1 - -static int64 get_masked_operand(int64 code, int64 mask) -{ - if ( mask == 0 ) - return 0; - bool no = false; - // special operations - switch ( mask >> OP_BITS ) - { - case OP_OP_NULL: - break; - case OP_OP_IMM: - return mask & OP_MASK; - case OP_OP_NOT: - no = true; - break; - default: - //error("interr: ana: get_masked_operand()"); - break; - } - code &= (mask & OP_MASK); - while ( (mask & 1) == 0 ) - { - code = code >> 1; - mask = mask >> 1; - } - if ( no ) - code = (~code) & 1; - return code; -} - - -//-------------------------------------------------------------------------- -static int get_signed(int byte, int mask) -{ - int bits = mask >> 1; - int sign = bits + 1; - if ( byte & sign ) // offset < 0 - byte = ( byte & bits ) - sign; - else // offset >= 0 - byte = byte & mask; - return byte; -} - -//-------------------------------------------------------------------------- -inline int get_signed64(int64 byte, int mask) -{ - return get_signed((int)byte, mask); -} - -//-------------------------------------------------------------------------- -inline int get_unsigned(int byte, int mask) -{ - byte = byte & mask; - return byte; -} - -//-------------------------------------------------------------------------- -static int64 get_masked_operand_5(int64 code, int64 mask) -{ - if ( mask == 0 ) - return 0; - bool no = false; - // special operations - int Switch=mask >> (OP_BITS+8); - switch ( Switch ) - { - case OP_OP_NULL: break; - case OP_OP_IMM: - return mask & OP_MASK_5; - case OP_OP_NOT: - no = true; - break; - default: - INTERR(10262); - } - code &= (mask & OP_MASK_5); - while ( (mask & 1) == 0 ) - { - code = code >> 1; - mask = mask >> 1; - } - if ( no ) - code = (~code) & 1; - return code; -} - -//-------------------------------------------------------------------------- -static int64 get_masked_operand_6(int64 code, int64 mask, bool /*bTest*/) -{ - if ( mask == 0 ) - return 0; - bool no = false; - // special operations - int Switch = mask >> (OP_BITS+16); - switch ( Switch ) - { - case OP_OP_NULL: break; - case OP_OP_IMM: - return mask & OP_MASK_6; - case OP_OP_NOT: - no = true; - break; - default: - INTERR(10263); - } - code &= mask & OP_MASK_6; - while ( (mask & 1) == 0 ) - { - code = code >> 1; - mask = mask >> 1; - } - if ( no ) - code = (~code) & 1; - return code; -} - -//-------------------------------------------------------------------------- -// process mask->op_mask[op_mask_n] on insn.ops[op_n] (if op.n not modified) and eventually modify op_n -bool tms320c55_t::process_masks_operand( - insn_t &insn, - const mask_t *mask, - int64 code, - int64 op_mask_n, - unsigned *p_opnum, - bool bTest) -{ - // initialize an operand to work on - op_t work; - unsigned opnum = *p_opnum; - if ( opnum < UA_MAXOP ) - work = insn.ops[opnum]; - else - work = insn.ops[UA_MAXOP-1]; - - const op_mask_t *op_mask = &mask->op_mask[int(op_mask_n)]; - if ( op_mask->func == NULL ) - return false; - - int64 opv = mask->size == 5 ? get_masked_operand_5(code, op_mask->mask) - : mask->size == 6 ? get_masked_operand_6(code, op_mask->mask, bTest) - : get_masked_operand(code, op_mask->mask); - op_mask->func(mask, opv, &work, insn, optional_op); - - if ( work.type != o_void ) // if the operand was modified - { - if ( work.n == opnum ) // the function worked on the current operand - { - if ( opnum >= UA_MAXOP ) - return false; // error if not enough operands in insn - insn.ops[opnum] = work; // save the new operand - *p_opnum = ++opnum; // go to the next operand - } - else // the function modified the previous operand - { - if ( work.n >= UA_MAXOP ) - return false; - insn.ops[work.n] = work; // save the new precedent operand (modified) - } - } - return true; -} - -//-------------------------------------------------------------------------- -// get number of bytes for a given instruction opcode (left-aligned in dword) -static int get_insn_size(const mask_t *masks, uint32 opcode) -{ - const mask_t *p = masks; - while ( p->mask != 0 ) - { - if ( p->size <= 4 && (p->mask & (opcode>>(8*(4-p->size)))) == p->code ) - return p->size; - p++; - } - return 0; -} - -//-------------------------------------------------------------------------- -// analyze code by processing all necessary masks -void tms320c55_t::process_masks( - insn_t &insn, - const mask_t *masks, - ushort itype_null, - bytes_c &bytes, - char lbytesize) -{ - insn.itype = itype_null; - insn.size = 1; - - const mask_t *p = masks; - while ( p->mask != 0 ) - { - bytes.reset(); - ushort nbytes = 0; - while ( nbytes < p->size - && byte_match_code_mask(p, bytes.get_next(), (uchar &)nbytes, lbytesize) ) - { - nbytes++; - } - if ( nbytes == p->size ) // if bytes matches all bytes from code and mask - { - int i; - insn.itype = p->itype; - insn.size = nbytes; - // compute full code - int64 code = 0; - for ( i = 0; i < nbytes; i++ ) - code = (code << lbytesize) | bytes.get(i); - // process operands - unsigned opnum = 0; - for ( i = 0; i < OP_MASK_N; i++ ) - { - bool bTest = p->size == 6 && i == 2; - if ( !process_masks_operand(insn, p, code, i, &opnum, bTest) ) - break; - } - return; - } - p++; - } -} - -//-------------------------------------------------------------------------- -// permit a mask_func_n to work on the last operand -static bool get_last_op(op_t *op, const insn_t &insn) -{ - int n; - for ( n = 0; n < 6; n++ ) // find the first o_void operand - if ( insn.ops[n].type == o_void ) - break; - - if ( n == 0 ) - return false; // no precedent operand - *op = insn.ops[n-1]; // copy the precedent operand to the current position - return true; -} - -//-------------------------------------------------------------------------- -// format instruction name -static void get_name_chars( - char *buf, - size_t bufsize, - bool incl_chars, - const char *name, - const char *chars) -{ - char *bufend = qstpncpy(buf, name, bufsize); - if ( incl_chars ) - qstrncpy(bufend, chars, bufsize - (bufend-buf)); -} - -//-------------------------------------------------------------------------- -// instructions - -// find instruction insn+"chars" with same operands: -// parallel indicate an instructions on 2 lines -// name1_chars indicate if we must have "chars" added to the first line -// name2_chars indicate if we must have "chars" added to the second line -// instructions in instruc_t Instructions[] must be sorted as follow: -// insn1 - insn2 - ... - insn"chars"1 - insn"chars"2 - ... -static bool find_insn_suffix( - insn_t &insn, - const char *chars, - ushort itype_last, - bool parallel, - bool name1_chars, - bool name2_chars) -{ - const char *insn_name1 = Instructions[insn.itype].name; - char insn_name1_chars[MAXSTR]; - get_name_chars(insn_name1_chars, sizeof(insn_name1_chars), name1_chars, insn_name1, chars); - - const char *insn_name2 = NULL; - char insn_name2_chars[MAXSTR]; - insn_name2_chars[0] = '\0'; - if ( parallel ) - { - insn_name2 = strchr(insn_name1, 0)+1; - get_name_chars(insn_name2_chars, sizeof(insn_name2_chars), name2_chars, insn_name2, chars); - } - - ushort i = insn.itype + 1; - // jump over same instruction names (but eventually different number of params) - while ( streq(Instructions[i].name, insn_name1) - && (!parallel || streq(strchr(Instructions[i].name, 0)+1, insn_name2)) ) //-V575 potential null pointer - { - if ( ++i == itype_last ) - return false; - } - - // loop until current instruction names are the same as what we are searching for (name or name+chars) - while ( !streq(Instructions[i].name, insn_name1_chars) - || (parallel && !streq(strchr(Instructions[i].name, 0)+1, insn_name2_chars)) ) - { - if ( ++i == itype_last ) - return false; - } - - // loop until current instruction has same params - uint32 insn_feature = Instructions[insn.itype].feature; - while ( Instructions[i].feature != insn_feature ) - { - if ( ++i == itype_last ) - return false; - } - - insn.itype = i; - return true; -} - -#define insn_chars(NAME, CHARS, PARALLEL, NAME1_CHARS, NAME2_CHARS) \ - static void NAME(const mask_t *, int64 offset, op_t *, insn_t &insn, char &) \ - { \ - if ( (offset & 1) != 0 ) \ - { \ - bool ok = find_insn_suffix(insn, CHARS, TMS320C55_last, PARALLEL,\ - NAME1_CHARS, NAME2_CHARS); \ - if ( !ok ) \ - error("interr: ana: adjust_insn_suffix"); \ - } \ - } - -insn_chars(insn_1_R_2_R, "r", true, true, true) // insn_1_R_2_R % -insn_chars(insn_1_40_2_40, "40", true, true, true) // insn_1_40_2_40 g -insn_chars(insn_1_2_R, "r", true, false, true) // insn_1_2_R % -insn_chars(insn_1_2_40, "40", true, false, true) // insn_1_2_40 g -insn_chars(insn_1_R, "r", false, true, false) // insn_1_R % -insn_chars(insn_1_40, "40", false, true, false) // insn_1_40 g -insn_chars(insn_1_R_2, "r", true, true, false) // insn_1_R_2 % -insn_chars(insn_1_U, "u", false, true, false) // insn_1_U u -insn_chars(insn_1_P, "p", false, true, false) // insn_1_P swap() -insn_chars(insn_1_4, "4", false, true, false) // insn_1_4 swap() - -// set user parellel -static void insn_UP(const mask_t *, int64, op_t *, insn_t &insn, char &) -{ - insn.SpecialModes |= TMS_MODE_USER_PARALLEL; -} - -// built-in parallelism -static void blt_prll(const mask_t *, int64, op_t *, insn_t &insn, char &) -{ // count the number of actual operands - insn.Parallel = 0; - for ( int i = 0; i < UA_MAXOP; i++ ) - { - if ( insn.ops[i].type == o_void ) - break; - insn.Parallel++; - } -} - -// simulated user parallelism -//static void usr_prll(const mask_t *mask, int64 offset, op_t *op) -//{ -// if ( offset & 1 ) -// { -// blt_prll(mask, offset, op); -// insn.SpecialModes |= TMS_MODE_SIMULATE_USER_PARALLEL; -// } -//} -//? actually not used, but will probably be used for non-documented opcodes -// need also to add new instructions "ins1\nins2" in ins.hpp & ins.cpp - -// immediates - -#define op_imm(NAME, DTYP) \ - static void op_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &, char &) \ - { \ - op->type = o_imm; \ - op->value = (uval_t)offset; \ - op->dtype = dt_##DTYP; \ - } - -op_imm(k8, byte) // op_k8 -op_imm(k16, word) // op_k16 -#define op_k4 op_k8 -#define op_k5 op_k8 -#define op_k7 op_k8 -#define op_k9 op_k16 -#define op_k12 op_k16 - -//-------------------------------------------------------------------------- -static void op_min_k4(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_imm; - op->value = (uval_t)-offset; - op->dtype = dt_byte; - op->tms_signed = true; -} - -//-------------------------------------------------------------------------- -static void op_K8(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_imm; - op->value = get_signed64(offset, 0xFF); - op->dtype = dt_byte; - op->tms_signed = true; -} - -//-------------------------------------------------------------------------- -static void op_K16(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_imm; - op->value = get_signed64(offset, 0xFFFF); - op->dtype = dt_word; - op->tms_signed = true; -} - -//-------------------------------------------------------------------------- -/* -static void op_K23(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_imm; - op->value = get_unsigned(offset, 0x7FFFFF); - op->dtype = dt_3byte; -} -*/ - -//-------------------------------------------------------------------------- -static void op_1(const mask_t *, int64, op_t *op, insn_t &, char &) -{ - op->type = o_imm; - op->value = 1; - op->dtype = dt_byte; -} - -//-------------------------------------------------------------------------- -static void op_min_1(const mask_t *, int64, op_t *op, insn_t &, char &) -{ - op->type = o_imm; - op->value = uval_t(-1); - op->dtype = dt_byte; - op->tms_signed = true; -} - -//-------------------------------------------------------------------------- -// registers - -static void op_src(const mask_t *, int64 offset, op_t *op, insn_t &, char &optional_op) // FSSS, FDDD -{ - op->type = o_reg; - op->dtype = dt_word; - op->reg = AC0 + uint16(offset); - optional_op = op->n; -} - -#define op_dst op_src -#define op_ACw op_src -#define op_ACx op_src -#define op_ACy op_src -#define op_ACz op_src -#define op_TAx op_src // ARx or Tx -#define op_TAy op_src // ARy or Ty - -// optional operand -static void opt_src(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // FSSS, FDDD -{ - if ( optional_op != -1 - && insn.ops[uchar(optional_op)].type == o_reg - && insn.ops[uchar(optional_op)].reg == AC0 + offset ) - { - return; // no operand if same than the source - } - // add the operand - op_src(mask, offset, op, insn, optional_op); - optional_op = -1; - insn.itype++; -} - -#define opt_dst opt_src -#define opt_ACy opt_src - - -#define op_reg(NAME, REG) \ - static void op_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &, char &)\ - { \ - op->type = o_reg; \ - op->dtype = dt_word; \ - op->reg = REG + uint16(offset); \ - } - -op_reg(Tx, T0) // op_Tx -op_reg(TCx, TC1) // op_TCx -op_reg(TRNx, TRN0) // op_TRNx -#define op_TCy op_TCx -op_reg(ARx, AR0) // op_ARx -op_reg(DPH, DPH) // op_DPH -op_reg(PDP, PDP) // op_PDP -op_reg(BK03, BK03) // op_BK03 -op_reg(BK47, BK47) // op_BK47 -op_reg(BKC, BKC) // op_BKC -op_reg(CSR, CSR) // op_CSR -op_reg(BRC0, BRC0) // op_BRC0 -op_reg(BRC1, BRC1) // op_BRC1 -op_reg(SP, SP) // op_SP -op_reg(SSP, SSP) // op_SSP -op_reg(CDP, CDP) // op_CDP -op_reg(RPTC, RPTC) // op_RPTC -op_reg(STx_55, ST0_55) // op_STx_55 -op_reg(DP, DP) // op_DP -op_reg(BSA01, BSA01) // op_BSA01 -op_reg(BSA23, BSA23) // op_BSA23 -op_reg(BSA45, BSA45) // op_BSA45 -op_reg(BSA67, BSA67) // op_BSA67 -op_reg(BSAC, BSAC) // op_BSAC -op_reg(TRN0, TRN0) // op_TRN0 -op_reg(TRN1, TRN1) // op_TRN1 -op_reg(TC1, TC1) // op_TC1 -op_reg(TC2, TC2) // op_TC2 -op_reg(CARRY, CARRY) // op_CARRY -op_reg(BORROW, BORROW) // op_BORROW -op_reg(RETA, RETA) // op_RETA -op_reg(MDP05, MDP05) // op_MDP05 -op_reg(MDP67, MDP67) // op_MDP67 - -//-------------------------------------------------------------------------- -static void op_xsrc(const mask_t *, int64 offset, op_t *op, insn_t &, char &) // XSSS, XDDD -{ // AC0 AC1 AC2 AC3 XSP XSSP XDP XCDP XAR0 -> XAR7 - static const ushort regs[] = - { - AC0, AC1, AC2, AC3, XSP, XSSP, XDP, XCDP, - XAR0, XAR1, XAR2, XAR3, XAR4, XAR5, XAR6, XAR7 - }; - op->type = o_reg; - op->dtype = dt_dword; - op->reg = regs[int(offset)]; -} -#define op_xdst op_xsrc - -//-------------------------------------------------------------------------- -static void op_Xmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // XXXMMM, YYYMMM -{ - op_ARx(mask, offset >> 3, op, insn, optional_op); - op->tms_modifier = TMS_MODIFIER_REG + (offset & 0x7); -} -#define op_Ymem op_Xmem - -//-------------------------------------------------------------------------- -static void op_Cmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // mm -{ - op_CDP(mask, 0, op, insn, optional_op); - op->tms_modifier = TMS_MODIFIER_REG + (offset & 0x3); -} - -//-------------------------------------------------------------------------- -static void op_mem( - const mask_t *mask, - int64 offset, - op_t *op, - op_dtype_t dtype, - insn_t &insn, - char optional_op, - bool ARn_mod = false) // AAAAAAAI -{ - insn.OpMem = 1 + op->n; - if ( !(offset & 1) ) // @dma - { // direct memory address - sel_t cpl = get_sreg(insn.ea, CPL); - if ( cpl == BADSEL ) - cpl = 0; - if ( !cpl ) - { // use DP - op->type = o_mem; - op->tms_regH = DPH; - op->tms_regP = DP; - op->addr = ea_t(offset >> 1); - op->tms_modifier = TMS_MODIFIER_DMA; - } - else - { // use SP - op->type = o_reg; - op->reg = SP; - op->value = ea_t(offset >> 1); - op->tms_modifier = TMS_MODIFIER_REG_OFFSET; - } - } - else - { // indirect memory access - if ( (offset & 0x1F) == 0x11 ) // xxx1 0001 - { - int bits = int(offset >> 5); - switch ( bits ) - { - case 0: // *ABS16(#k16) - op->type = o_mem; - op->tms_regH = DPH; - op->addr = (get_byte(insn.ea+insn.size) << 8) - | get_byte(insn.ea+insn.size+1); - op->tms_modifier = TMS_MODIFIER_ABS16; - insn.size += 2; - break; - case 1: // *(#k23) - op->type = o_mem; - op->addr = (get_byte(insn.ea+insn.size) << 16) - | (get_byte(insn.ea+insn.size+1) << 8) - | get_byte(insn.ea+insn.size+2); - op->tms_modifier = TMS_MODIFIER_PTR; - insn.size += 3; - break; - case 2: // port(#k16) - op->type = o_io; - op->addr = (get_byte(insn.ea+insn.size) << 8) - | get_byte(insn.ea+insn.size+1); - op->tms_modifier = TMS_MODIFIER_PORT; - insn.size += 2; - break; - case 3: // *CDP - case 4: // *CDP+ - case 5: // *CDP- - op_CDP(mask, 0, op, insn, optional_op); - op->tms_modifier= TMS_MODIFIER_REG + uchar(bits)-3; - break; - case 6: // *CDP(#K16) - case 7: // *+CDP(#K16) - op_CDP(mask, 0, op, insn, optional_op); - op->value = get_signed((get_byte(insn.ea+insn.size) << 8) - | get_byte(insn.ea+insn.size+1), 0xFFFF); - op->tms_modifier = TMS_MODIFIER_REG_OFFSET + uchar(bits)-6; - insn.size += 2; - break; - } - } - else - { - op_ARx(mask, offset >> 5, op, insn, optional_op); - int bits = (offset >> 1) & 0xF; - if ( (offset & 0x11) == 0x01 ) // xxx0 xxx1 - { - switch ( bits ) - { - case 0: // *ARn - case 1: // *ARn+ - case 2: // *ARn- - op->tms_modifier= TMS_MODIFIER_REG + uchar(bits); - break; - case 3: // *(ARn+T0) - op->tms_modifier= TMS_MODIFIER_REG_P_T0; - break; - case 4: // *(ARn-T0) - op->tms_modifier= TMS_MODIFIER_REG_M_T0; - break; - case 5: // *ARn(T0) - op->tms_modifier= TMS_MODIFIER_REG_T0; - break; - case 6: // *ARn(#K16) - case 7: // *+ARn(#K16) - op->value = get_signed((get_byte(insn.ea+insn.size) << 8) - | get_byte(insn.ea+insn.size+1), 0xFFFF); - op->tms_modifier = TMS_MODIFIER_REG_OFFSET + uchar(bits)-6; - insn.size += 2; - break; - } - } - else // xxx1 xxx1 - { - int lbits = (offset >> 1) & 0x7; - sel_t arms = get_sreg(insn.ea, ARMS); - if ( arms == BADSEL ) - arms = 0; - if ( ARn_mod || !arms ) - { - switch ( lbits ) - { - case 1: // *(ARn+T1) - op->tms_modifier= TMS_MODIFIER_REG_P_T1; - break; - case 2: // *(ARn-T1) - op->tms_modifier= TMS_MODIFIER_REG_M_T1; - break; - case 3: // *ARn(T1) - case 4: // *+ARn - case 5: // *-ARn - case 6: // *(ARn+T0B) - case 7: // *(ARn-T0B) - op->tms_modifier= TMS_MODIFIER_REG_T1 + uchar(lbits)-3; - break; - } - } - else - { // *ARn(short(#value)) - op->value = lbits; - op->tms_modifier = TMS_MODIFIER_REG_SHORT_OFFSET; - } - } - } - } - op->dtype = dtype; -} - -//-------------------------------------------------------------------------- -static void op_Smem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference -{ - op_mem(mask, offset, op, dt_word, insn, optional_op); -} - -//-------------------------------------------------------------------------- -static void op_Lmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference -{ - op_mem(mask, offset, op, dt_dword, insn, optional_op); -} - -//-------------------------------------------------------------------------- -static void op_ARn_mod(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference -{ - op_mem(mask, offset, op, dt_word, insn, optional_op, true); -} - -//-------------------------------------------------------------------------- -// @dma = bit number -static void op_Baddr(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference -{ - if ( !(offset & 1) ) // @dma - { - op->type = o_imm; - op->value = ea_t(offset >> 1); - op->dtype = dt_byte; - op->tms_prefix = '@'; - op->tms_signed = false; - } - else - { - op_mem(mask, offset, op, dt_byte, insn, optional_op); - } -} - -//lint -emacro(572,fn_operator) excessive shift value -#define fn_operator(NAME, OPERATOR) \ - static void fn_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) \ - { \ - if ( offset & 1 ) \ - { \ - get_last_op(op, insn); \ - op->tms_operator1 |= TMS_OPERATOR_##OPERATOR & 0xFF; \ - /*lint -e572 Excessive shift value*/ \ - op->tms_operator2 |= (TMS_OPERATOR_##OPERATOR >> 8); \ - } \ - } - -fn_operator(not, NOT) // fn_not -fn_operator(T3, T3) // fn_T3 U -fn_operator(uns, UNS) // fn_uns u -fn_operator(rnd, RND) // fn_rnd % -fn_operator(hb, HB) // fn_hb -fn_operator(lb, LB) // fn_lb -fn_operator(hi, HI) // fn_hi -fn_operator(lo, LO) // fn_lo -fn_operator(sat, SAT) // fn_sat = fn_uns -fn_operator(dbl, DBL) // fn_dbl -fn_operator(pair, PAIR) // fn_pair -fn_operator(dual, DUAL) // fn_dual - -//-------------------------------------------------------------------------- -static void op_BitIn(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_reg; - op->dtype = dt_byte; - op->reg = (offset & 1) ? TC2 : CARRY; -} -#define op_BitOut op_BitIn - -//-------------------------------------------------------------------------- -static void op_swap(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) -{ - insn.Op1.type = o_reg; - insn.Op1.dtype = dt_word; - insn.Op2.type = o_reg; - insn.Op2.dtype = dt_word; - switch ( offset ) - { - case 0x00: insn.Op1.reg = AC0; insn.Op2.reg = AC2; break; - case 0x01: insn.Op1.reg = AC1; insn.Op2.reg = AC3; break; - case 0x04: insn.Op1.reg = T0; insn.Op2.reg = T2; break; - case 0x05: insn.Op1.reg = T1; insn.Op2.reg = T3; break; - case 0x08: insn.Op1.reg = AR0; insn.Op2.reg = AR2; break; - case 0x09: insn.Op1.reg = AR1; insn.Op2.reg = AR3; break; - case 0x0C: insn.Op1.reg = AR4; insn.Op2.reg = T0; break; - case 0x0D: insn.Op1.reg = AR5; insn.Op2.reg = T1; break; - case 0x0E: insn.Op1.reg = AR6; insn.Op2.reg = T2; break; - case 0x0F: insn.Op1.reg = AR7; insn.Op2.reg = T3; break; - case 0x10: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AC0; insn.Op2.reg = AC2; break; - case 0x14: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = T0; insn.Op2.reg = T2; break; - case 0x18: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR0; insn.Op2.reg = AR2; break; - case 0x1C: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR4; insn.Op2.reg = T0; break; - case 0x1E: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR6; insn.Op2.reg = T2; break; - case 0x2C: insn_1_4(mask, 1, op, insn, optional_op); insn.Op1.reg = AR4; insn.Op2.reg = T0; break; - case 0x38: insn.Op1.reg = AR0; insn.Op2.reg = AR1; break; - default: insn.itype = TMS320C55_null; - } -} - -//-------------------------------------------------------------------------- -// get address for the branch offset base -// in case of parallel execution, this is the end of the second, parallel instruction -static ea_t get_next_ip(insn_t &insn) -{ - ea_t next = insn.ip + insn.size; - if ( insn.size <= 3 ) - { - uchar nextbyte = get_byte(insn.ea + insn.size); - if ( nextbyte <= MAX_BYTE_USER_PARALLELIZED && (nextbyte & 1) ) - { - // next instruction is executed in parallel, so take it into account - insn_t tmp; - next += decode_insn(&tmp, insn.ea + insn.size); - } - } - return next; -} - -//-------------------------------------------------------------------------- -// code addresses - -static void op_l4(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // llll -{ - op->type = o_near; - op->addr = (get_next_ip(insn) + offset) & 0xFFFFFF; - op->dtype = dt_code; -} - -static void op_L7(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLL -{ - op->type = o_near; - op->addr = (get_next_ip(insn) + get_signed64(offset, 0x7F)) & 0xFFFFFF; - op->dtype = dt_code; -} - -static void op_L8(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLLL -{ - op->type = o_near; - op->addr = (get_next_ip(insn) + get_signed64(offset, 0xFF)) & 0xFFFFFF; - op->dtype = dt_code; -} - -static void op_L16(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLLL LLLLLLLL -{ - op->type = o_near; - op->addr = (get_next_ip(insn) + get_signed64(offset, 0xFFFF)) & 0xFFFFFF; - op->dtype = dt_code; -} - -static void op_pmad(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) -{ - op->type = o_near; - op->addr = (get_next_ip(insn) + offset) & 0xFFFFFF; - op->dtype = dt_code; -} - -static void op_P24(const mask_t *, int64, op_t *op, insn_t &insn, char &) // get_byte included -{ - op->type = o_near; - op->addr = (get_byte(insn.ea+insn.size+0) << 16) - | (get_byte(insn.ea+insn.size+1) << 8) - | get_byte(insn.ea+insn.size+2); - op->dtype = dt_code; - insn.size += 3; -} - -// data addresses - -static void op_D16(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_mem; - op->addr = ea_t(offset); - op->dtype = dt_word; -} - -// various - -static void op_SHIFTW(const mask_t *, int64 offset, op_t *op, insn_t &, char &) -{ - op->type = o_shift; - op->value = (signed short)get_signed64(offset, 0x3F); -} - -//-------------------------------------------------------------------------- -// shift left -static void shl_SHIFTW(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_SHIFTL_IMM; - op->tms_shift_value = (signed short)get_signed64(offset, 0x3F); - if ( short(op->tms_shift_value) < 0 ) - { - op->tms_shift = TMS_OP_SHIFTR_IMM; - op->tms_shift_value = -op->tms_shift_value; //lint !e2501 negation of value of unsigned type - } -} - -//-------------------------------------------------------------------------- -// shift left out of brackets -static void slo_SHIFTW(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) -{ - shl_SHIFTW(mask, offset, op, insn, optional_op); - op->tms_shift |= TMS_OP_SHIFT_OUT; -} - -//-------------------------------------------------------------------------- -// shift right -static void shl_SHFT(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_SHIFTL_IMM; - op->tms_shift_value = (uint16)offset; -} - -//-------------------------------------------------------------------------- -static void shl_Tx(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_SHIFTL_REG; - op->tms_shift_value = T0 + uint16(offset); -} - -//-------------------------------------------------------------------------- -static void shl_T2(const mask_t *, int64, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_SHIFTL_REG; - op->tms_shift_value = T2; -} - -//-------------------------------------------------------------------------- -static void shl_16(const mask_t *, int64, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_SHIFTL_IMM; - op->tms_shift_value = 16; -} - -//-------------------------------------------------------------------------- -static void shr(const mask_t *, int64 imm, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_SHIFTR_IMM; - op->tms_shift_value = uint16(imm); -} - -//-------------------------------------------------------------------------- -static void eq_K16(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_EQ; - op->tms_shift_value = (uint16)get_signed64(offset, 0xFFFF); -} - -//-------------------------------------------------------------------------- -static void neq_0(const mask_t *, int64, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_shift = TMS_OP_NEQ; - op->tms_shift_value = 0; -} - -//-------------------------------------------------------------------------- -static void RELOP(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // cc -{ - get_last_op(op, insn); - op->type = o_relop; - op->tms_relop = offset & 0x3; -} - -//-------------------------------------------------------------------------- -static void RELOP_dst(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) -{ - get_last_op(op, insn); - op->tms_relop_type = TMS_RELOP_REG; - ushort sav = op->reg; - op_src(mask, offset, op, insn, optional_op); - op->type = o_relop; - op->value = op->reg; - op->reg = sav; -} - -//-------------------------------------------------------------------------- -static void RELOP_K8(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) -{ - get_last_op(op, insn); - op->tms_relop_type = TMS_RELOP_IMM; - op->value = (signed short)get_signed64(offset, 0xFF); -} - -//-------------------------------------------------------------------------- -static void op_cond(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // CCC CCCC -{ - op->reg = 0; - if ( (offset>>4) <= 0x5 ) // <= 101 xxxx - { // src <comparison operator> 0 - op_src(mask, offset & 0xF, op, insn, optional_op); - op->type = o_cond; - op->value = offset & 0x70; - } - else if ( (offset>>2) == 0x18 ) // == 110 00xx - { // overflow(ACx) - op_src(mask, offset & 0x3, op, insn, optional_op); - op->type = o_cond; - op->value = offset & 0x7C; - } - else if ( (offset>>2) == 0x19 ) // == 110 01xx - { // TC1, TC2, CARRY, reserved - if ( offset == 0x67 ) // 110 0111 - insn.itype = TMS320C55_null; // reserved - else - { - op->type = o_cond; - op->value = (uval_t)offset; - } - } - else if ( (offset>>2) == 0x1A ) // == 110 10xx - { // TC1 & TC2, TC1 & !TC2, !TC1 & TC2, !TC1 & !TC2 - op->type = o_cond; - op->value = (uval_t)offset; - } - else if ( (offset>>2) == 0x1B ) // == 110 11xx - { - insn.itype = TMS320C55_null; // reserved - } - else if ( (offset>>2) == 0x1C ) // == 111 00xx - { // !overflow(ACx) - op_src(mask, offset & 0x3, op, insn, optional_op); - op->type = o_cond; - op->value = offset & 0x7C; - } - else - { - if ( offset == 0x77 ) // 111 0111 - insn.itype = TMS320C55_null; // reserved - else - { - op->type = o_cond; - op->value = (uval_t)offset; - } - } -} - -//-------------------------------------------------------------------------- -//lint -e648 overflow in computing constant for operator '<<': signed shift result (0x80000000) sets the sign bit of the shift expression's type ('int') and becomes negative expanded from macro 'OP_NOT' -static const mask_t masks[] = -{ - // 0000000E XDDDX000 error manual - { 0x000000, 0xFE0000, 3, TMS320C55_rptcc, {{ op_k8, 0x0000FF }, { op_cond, 0x007F00 }}}, - { 0x020000, 0xFE0000, 3, TMS320C55_retcc, {{ op_cond, 0x007F00 }}}, - { 0x040000, 0xFE0000, 3, TMS320C55_bcc, {{ op_L8, 0x0000FF }, { op_cond, 0x007F00 }}}, - { 0x060000, 0xFE0000, 3, TMS320C55_b, {{ op_L16, 0x00FFFF }}}, - { 0x080000, 0xFE0000, 3, TMS320C55_call, {{ op_L16, 0x00FFFF }}}, - // 0000101E GGGGGGGG Glllllll error manual - { 0x0C0000, 0xFE0000, 3, TMS320C55_rpt, {{ op_k16, 0x00FFFF }}}, - { 0x0E0000, 0xFE0000, 3, TMS320C55_rptb, {{ op_pmad, 0x00FFFF }}}, - { 0x100000, 0xFE0F00, 3, TMS320C55_and1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, - { 0x100100, 0xFE0F00, 3, TMS320C55_or1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, - { 0x100200, 0xFE0F00, 3, TMS320C55_xor1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, - { 0x100300, 0xFE0F00, 3, TMS320C55_add2, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { op_ACy, 0x00C000 }}}, - { 0x100400, 0xFE0F00, 3, TMS320C55_sub2, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { op_ACy, 0x00C000 }}}, - { 0x100500, 0xFE0F00, 3, TMS320C55_sfts2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, - { 0x100600, 0xFE0F00, 3, TMS320C55_sftsc2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, // SFTA - { 0x100700, 0xFE0F00, 3, TMS320C55_sftl2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, - { 0x100800, 0xFE0F00, 3, TMS320C55_exp, {{ op_ACx, 0x003000 }, { op_Tx, 0x000030 }}}, - { 0x100900, 0xFE0F00, 3, TMS320C55_mant_nexp, {{ op_ACx, 0x003000 }, { op_ACy, 0x00C000 }, { blt_prll, 0 }, { op_ACx, 0x003000 }, { op_Tx, 0x000030 }}}, - { 0x100A00, 0xFE0F00, 3, TMS320C55_bcnt, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_TCx, 0x000001 }, { op_Tx, 0x000030 }}}, - { 0x100C00, 0xFE0F00, 3, TMS320C55_maxdiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }}}, - { 0x100D00, 0xFE0F00, 3, TMS320C55_dmaxdiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }, { op_TRNx, 0x000001 }}}, - { 0x100E00, 0xFE0F00, 3, TMS320C55_mindiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }}}, - { 0x100F00, 0xFE0F00, 3, TMS320C55_dmindiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }, { op_TRNx, 0x000001 }}}, - { 0x120000, 0xFE0300, 3, TMS320C55_cmp, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCx, 0x000001 }}}, - { 0x120100, 0xFE0308, 3, TMS320C55_cmpand, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { op_TCx, 0x000001 }}}, - { 0x120108, 0xFE0308, 3, TMS320C55_cmpand, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { fn_not, OP_TRUE }, { op_TCx, 0x000001 }}}, - { 0x120200, 0xFE0308, 3, TMS320C55_cmpor, {{ insn_1_U, OP_NOT(0x000004) }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { op_TCx, 0x000001 }}}, - { 0x120208, 0xFE0308, 3, TMS320C55_cmpor, {{ insn_1_U, OP_NOT(0x000004) }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { fn_not, OP_TRUE }, { op_TCx, 0x000001 }}}, - { 0x120300, 0xFE0308, 3, TMS320C55_rol, {{ op_BitOut, 0x000001 }, { op_src, 0x00F000 }, { op_BitIn, 0x000002 }, { op_dst, 0x0000F0 }}}, - { 0x120308, 0xFE0308, 3, TMS320C55_ror, {{ op_BitIn, 0x000002 }, { op_src, 0x00F000 }, { op_BitOut, 0x000001 }, { op_dst, 0x0000F0 }}}, - { 0x140000, 0xFE000F, 3, TMS320C55_aadd, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, - { 0x140001, 0xFE000F, 3, TMS320C55_amov, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, - { 0x140002, 0xFE000F, 3, TMS320C55_asub, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, - { 0x140004, 0xFE000F, 3, TMS320C55_aadd, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, - { 0x140005, 0xFE000F, 3, TMS320C55_amov, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, - { 0x140006, 0xFE000F, 3, TMS320C55_asub, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, - { 0x140008, 0xFE000F, 3, TMS320C55_aadd, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, - { 0x140009, 0xFE000F, 3, TMS320C55_amov, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, - { 0x14000A, 0xFE000F, 3, TMS320C55_asub, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, - { 0x14000C, 0xFE000F, 3, TMS320C55_aadd, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, - { 0x14000D, 0xFE000F, 3, TMS320C55_amov, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, - { 0x14000E, 0xFE000F, 3, TMS320C55_asub, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, - { 0x160000, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_DPH, 0 }}}, - { 0x160001, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_MDP05, 0 }}}, - { 0x160002, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_MDP67, 0 }}}, - { 0x160003, 0xFE000F, 3, TMS320C55_mov2, {{ op_k9, 0x001FF0 }, { op_PDP, 0 }}}, - { 0x160004, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BK03, 0 }}}, - { 0x160005, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BK47, 0 }}}, - { 0x160006, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BKC, 0 }}}, - { 0x160008, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_CSR, 0 }}}, - { 0x160009, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BRC0, 0 }}}, - { 0x16000A, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BRC1, 0 }}}, - // 0001011E xxxxxxxk kkkk11xx error manual - { 0x180000, 0xFE0000, 3, TMS320C55_and3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, - { 0x1A0000, 0xFE0000, 3, TMS320C55_or3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, - { 0x1C0000, 0xFE0000, 3, TMS320C55_xor3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, - { 0x1E0000, 0xFE0002, 3, TMS320C55_mpyk2, {{ insn_1_R, 0x000001 }, { op_K8, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0x1E0002, 0xFE0002, 3, TMS320C55_mack3, {{ insn_1_R, 0x000001 }, { op_Tx, 0x00000C }, { op_K8, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0x20, 0xFE, 1, TMS320C55_nop }, - { 0x2200, 0xFE00, 2, TMS320C55_mov2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x2400, 0xFE00, 2, TMS320C55_add1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, - { 0x2600, 0xFE00, 2, TMS320C55_sub1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, - { 0x2800, 0xFE00, 2, TMS320C55_and2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x2A00, 0xFE00, 2, TMS320C55_or2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x2C00, 0xFE00, 2, TMS320C55_xor2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x2E00, 0xFE00, 2, TMS320C55_max1, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x3000, 0xFE00, 2, TMS320C55_min1, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x3200, 0xFE00, 2, TMS320C55_abs1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, - { 0x3400, 0xFE00, 2, TMS320C55_neg1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, - { 0x3600, 0xFE00, 2, TMS320C55_not1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, - { 0x3800, 0xFE00, 2, TMS320C55_psh2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x3A00, 0xFE00, 2, TMS320C55_pop2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x3C00, 0xFE00, 2, TMS320C55_mov2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x3E00, 0xFE00, 2, TMS320C55_mov2, {{ op_min_k4, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x4000, 0xFE00, 2, TMS320C55_add2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x4200, 0xFE00, 2, TMS320C55_sub2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}}, - { 0x4400, 0xFEC0, 2, TMS320C55_mov2, {{ op_ACx, 0x0030 }, { fn_hi, OP_TRUE }, { op_TAx, 0x000F }}}, - { 0x4440, 0xFED0, 2, TMS320C55_sfts2, {{ op_dst, 0x000F }, { op_min_1, 0 }}}, - { 0x4450, 0xFED0, 2, TMS320C55_sfts2, {{ op_dst, 0x000F }, { op_1, 0 }}}, - { 0x4480, 0xFEF0, 2, TMS320C55_mov2, {{ op_SP, 0 }, { op_TAx, 0x000F }}}, - { 0x4490, 0xFEF0, 2, TMS320C55_mov2, {{ op_SSP, 0 }, { op_TAx, 0x000F }}}, - { 0x44A0, 0xFEF0, 2, TMS320C55_mov2, {{ op_CDP, 0 }, { op_TAx, 0x000F }}}, - { 0x44C0, 0xFEF0, 2, TMS320C55_mov2, {{ op_BRC0, 0 }, { op_TAx, 0x000F }}}, - { 0x44D0, 0xFEF0, 2, TMS320C55_mov2, {{ op_BRC1, 0 }, { op_TAx, 0x000F }}}, - { 0x44E0, 0xFEF0, 2, TMS320C55_mov2, {{ op_RPTC, 0 }, { op_TAx, 0x000F }}}, - { 0x4600, 0xFE09, 2, TMS320C55_bclr2, {{ op_k4, 0x00F0 }, { op_STx_55, 0x0006 }}}, - { 0x4601, 0xFE09, 2, TMS320C55_bset2, {{ op_k4, 0x00F0 }, { op_STx_55, 0x0006 }}}, - // 0100011E xxxx1000 error manual - // 0100011E xxxx1001 error manual - // 0100011E xxxx1010 error manual - // 0100011E xxxx1100 error manual - { 0x4800, 0xFE07, 2, TMS320C55_rpt, {{ op_CSR, 0 }}}, - { 0x4801, 0xFE07, 2, TMS320C55_rptadd, {{ op_CSR, 0 }, { op_TAx, 0x00F0 }}}, - { 0x4802, 0xFE07, 2, TMS320C55_rptadd, {{ op_CSR, 0 }, { op_k4, 0x00F0 }}}, - { 0x4803, 0xFE07, 2, TMS320C55_rptsub, {{ op_CSR, 0 }, { op_k4, 0x00F0 }}}, - { 0x4804, 0xFE07, 2, TMS320C55_ret }, - { 0x4805, 0xFE07, 2, TMS320C55_reti }, - { 0x4A00, 0xFE80, 2, TMS320C55_b, {{ op_L7, 0x007F }}}, - { 0x4A80, 0xFE80, 2, TMS320C55_rptblocal, {{ op_pmad, 0x007F }}}, - { 0x4C00, 0xFE00, 2, TMS320C55_rpt, {{ op_k8, 0x00FF }}}, - { 0x4E00, 0xFE00, 2, TMS320C55_aadd, {{ op_K8, 0x00FF }, { op_SP, 0 }}}, - { 0x5000, 0xFE07, 2, TMS320C55_sftl2, {{ op_dst, 0x00F0 }, { op_1, 0 }}}, - { 0x5001, 0xFE07, 2, TMS320C55_sftl2, {{ op_dst, 0x00F0 }, { op_min_1, 0 }}}, - { 0x5002, 0xFE07, 2, TMS320C55_pop1, {{ op_dst, 0x00F0 }}}, - { 0x5003, 0xFE07, 2, TMS320C55_pop1, {{ op_ACx, 0x0030 }, { fn_dbl, OP_TRUE }}}, - { 0x5004, 0xFE07, 2, TMS320C55_popboth, {{ op_xsrc, 0x00F0 }}}, // not in documentation - { 0x5005, 0xFE07, 2, TMS320C55_pshboth, {{ op_xsrc, 0x00F0 }}}, // not in documentation - { 0x5006, 0xFE07, 2, TMS320C55_psh1, {{ op_dst, 0x00F0 }}}, - { 0x5007, 0xFE07, 2, TMS320C55_psh1, {{ op_ACx, 0x0030 }, { fn_dbl, OP_TRUE }}}, - { 0x5200, 0xFE0C, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_ACx, 0x0003 }, { fn_hi, OP_TRUE }}}, - { 0x5208, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_SP, 0 }}}, - { 0x5209, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_SSP, 0 }}}, - { 0x520A, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_CDP, 0 }}}, - { 0x520C, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_CSR, 0 }}}, - { 0x520D, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_BRC1, 0 }}}, - { 0x520E, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_BRC0, 0 }}}, - { 0x5400, 0xFE0F, 2, TMS320C55_addv1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5401, 0xFE0F, 2, TMS320C55_addrv1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5402, 0xFE0E, 2, TMS320C55_sqa1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5404, 0xFE0E, 2, TMS320C55_sqs1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5406, 0xFE0E, 2, TMS320C55_mpy1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5408, 0xFE0E, 2, TMS320C55_sqr1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x540A, 0xFE0E, 2, TMS320C55_round1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, // error manual: unused bits - { 0x540C, 0xFE0E, 2, TMS320C55_sat1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5600, 0xFE02, 2, TMS320C55_mac3, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }, { op_ACy, 0x00C0 }}}, - { 0x5602, 0xFE02, 2, TMS320C55_mas2, {{ insn_1_R, 0x0001 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5800, 0xFE02, 2, TMS320C55_mpy2, {{ insn_1_R, 0x0001 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, - { 0x5802, 0xFE02, 2, TMS320C55_mac4, {{ insn_1_R, 0x0001 }, { op_ACy, 0x00C0 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { op_ACy, 0x00C0 }}}, - { 0x5A00, 0xFE03, 2, TMS320C55_add2, {{ op_ACx, 0x0030 }, { shl_Tx, 0x000C }, { op_ACy, 0x00C0 }}}, - { 0x5A01, 0xFE03, 2, TMS320C55_sub2, {{ op_ACx, 0x0030 }, { shl_Tx, 0x000C }, { op_ACy, 0x00C0 }}}, - { 0x5A02, 0xFE02, 2, TMS320C55_sftcc, {{ op_ACx, 0x00C0 }, { op_TCx, 0x0001 }}}, - { 0x5C00, 0xFE03, 2, TMS320C55_sftl2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}}, - { 0x5C01, 0xFE03, 2, TMS320C55_sfts2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}}, - { 0x5C02, 0xFE03, 2, TMS320C55_sftsc2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}}, - { 0x5E00, 0xFEC0, 2, TMS320C55_swap, {{ op_swap, 0x003F }}}, - { 0x5E80, 0xFEC0, 2, TMS320C55_nop_16 }, - { 0x6000, 0xF800, 2, TMS320C55_bcc, {{ op_l4, 0x0780 }, { op_cond, 0x007F }}}, - { 0x6800, 0xFF00, 2, TMS320C55_bcc, {{ op_P24, 0 }, { op_cond, 0x007F }}}, // compiler bug - { 0x6900, 0xFF00, 2, TMS320C55_callcc, {{ op_P24, 0 }, { op_cond, 0x007F }}}, - { 0x6A, 0xFF, 1, TMS320C55_b, {{ op_P24, 0 }}}, - { 0x6C, 0xFF, 1, TMS320C55_call, {{ op_P24, 0 }}}, - { 0x6D000000, 0xFF000000, 4, TMS320C55_bcc, {{ op_L16, 0x0000FFFF }, { op_cond, 0x007F0000 }}}, - { 0x6E000000, 0xFF000000, 4, TMS320C55_callcc, {{ op_L16, 0x0000FFFF }, { op_cond, 0x007F0000 }}}, - { 0x6F000000, 0xFF000000, 4, TMS320C55_bcc, {{ insn_1_U, 0x00010000 }, { op_L8, 0x000000FF }, { op_src, 0x00F00000 }, { RELOP, 0x000C0000 }, { RELOP_K8, 0x0000FF00 }}}, - { 0x70000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x71000000, 0xFF000000, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x72000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x73000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x74000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x75000000, 0xFF000000, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x00000030 }}}, - { 0x76000000, 0xFF00000C, 4, TMS320C55_bfxtr, {{ op_k16, 0x00FFFF00 }, { op_ACx, 0x00000003 }, { op_dst, 0x000000F0 }}}, - { 0x76000004, 0xFF00000C, 4, TMS320C55_bfxpa, {{ op_k16, 0x00FFFF00 }, { op_ACx, 0x00000003 }, { op_dst, 0x000000F0 }}}, - { 0x76000008, 0xFF00000C, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { op_dst, 0x000000F0 }}}, - { 0x77000000, 0xFF000000, 4, TMS320C55_amov, {{ op_D16, 0x00FFFF00 }, { op_TAx, 0x000000F0 }}}, - { 0x78000000, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_DP, 0 }}}, - { 0x78000002, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_SSP, 0 }}}, - { 0x78000004, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_CDP, 0 }}}, - { 0x78000006, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA01, 0 }}}, - { 0x78000008, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA23, 0 }}}, - { 0x7800000A, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA45, 0 }}}, - { 0x7800000C, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA67, 0 }}}, - { 0x7800000E, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSAC, 0 }}}, - { 0x78000010, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_SP, 0 }}}, - { 0x79000000, 0xFF000002, 4, TMS320C55_mpyk2, {{ insn_1_R, 0x00000001 }, { op_K16, 0x00FFFF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x79000002, 0xFF000002, 4, TMS320C55_mack3, {{ insn_1_R, 0x00000001 }, { op_Tx, 0x0000000C }, { op_K16, 0x00FFFF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x7A000000, 0xFF00000E, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x7A000002, 0xFF00000E, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x7A000004, 0xFF00000E, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x7A000006, 0xFF00000E, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x7A000008, 0xFF00000E, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0x7A00000A, 0xFF00000E, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x00000030 }}}, - { 0x7A00000C, 0xFF00000E, 4, TMS320C55_idle }, - { 0x7B000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { op_src, 0x0000000F }, { opt_dst, 0x000000F0 }}}, - { 0x7C000000, 0xFF000000, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { op_src, 0x0000000F }, { opt_dst, 0x000000F0 }}}, - { 0x7D000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}}, - { 0x7E000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}}, - { 0x7F000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}}, - { 0x800000, 0xFF000C, 3, TMS320C55_mov2, {{ op_Xmem, 0x00FC00 }, { fn_dbl, OP_TRUE, }, { op_Ymem, 0x0003F0 }, { fn_dbl, OP_TRUE }}}, - { 0x800004, 0xFF000C, 3, TMS320C55_mov2, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0 }}}, - { 0x800008, 0xFF000C, 3, TMS320C55_mov3, {{ op_ACx, 0x000003 }, { op_Xmem, 0x00FC00, }, { op_Ymem, 0x0003F0 }}}, - { 0x810000, 0xFF000C, 3, TMS320C55_add3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}}, - { 0x810004, 0xFF000C, 3, TMS320C55_sub3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}}, - { 0x810008, 0xFF000C, 3, TMS320C55_mov3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}}, - { 0x82000000, 0xFF000C00, 4, TMS320C55_mpy_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x82000400, 0xFF000C00, 4, TMS320C55_mac_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x82000800, 0xFF000C00, 4, TMS320C55_mas_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x82000C00, 0xFF000C00, 4, TMS320C55_amar_mpy, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}}, - { 0x83000000, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x83000400, 0xFF000C00, 4, TMS320C55_mas_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x83000800, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { shr, OP_IMM(16) }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x83000C00, 0xFF000C00, 4, TMS320C55_amar_mac, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}}, - { 0x84000000, 0xFF000C00, 4, TMS320C55_mas_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}}, - { 0x84000400, 0xFF000C00, 4, TMS320C55_amar_mac, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }, { shr, OP_IMM(16) }}}, - { 0x84000800, 0xFF000C00, 4, TMS320C55_mpy_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}}, - { 0x84000C00, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { shr, OP_IMM(16) }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}}, - { 0x85000000, 0xFF000C00, 4, TMS320C55_amar_mas, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}}, - { 0x85000400, 0xFF000C00, 4, TMS320C55_mas_mas, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, - { 0x85000800, 0xFF000C00, 4, TMS320C55_amar3, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }}}, - { 0x85000C00, 0xFF000C10, 4, TMS320C55_firsadd, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }, { op_ACx, 0x000000C0 }, { op_ACy, 0x0000000C }}}, // error manual: unused bits: DDx0DDU% p552 - { 0x85000C10, 0xFF000C10, 4, TMS320C55_firssub, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }, { op_ACx, 0x000000C0 }, { op_ACy, 0x0000000C }}}, // error manual: unused bits: DDx0DDU% p552 - { 0x86000000, 0xFF0000E0, 4, TMS320C55_mpym3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000300 }}}, - { 0x86000020, 0xFF0000E0, 4, TMS320C55_macm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { opt_ACy, 0x00000300 }}}, - { 0x86000040, 0xFF0000E0, 4, TMS320C55_macm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { shr, OP_IMM(16) }, { opt_ACy, 0x00000300 }}}, - { 0x86000060, 0xFF0000E0, 4, TMS320C55_masm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { opt_ACy, 0x00000300 }}}, - { 0x86000080, 0xFF0000E0, 4, TMS320C55_masm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACx, 0x00000C00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { shl_16, 0 }, { op_ACy, 0x00000300 }}}, - { 0x860000A0, 0xFF0000E0, 4, TMS320C55_macm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACx, 0x00000C00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { shl_16, 0 }, { op_ACy, 0x00000300 }}}, - { 0x860000C0, 0xFF0000E0, 4, TMS320C55_lms, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}}, - { 0x860000E0, 0xFF0000F0, 4, TMS320C55_sqdst, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}}, - { 0x860000F0, 0xFF0000F0, 4, TMS320C55_abdst, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}}, - { 0x87000000, 0xFF0000E0, 4, TMS320C55_mpym_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, - { 0x87000020, 0xFF0000E0, 4, TMS320C55_macm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, - { 0x87000040, 0xFF0000E0, 4, TMS320C55_masm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, - { 0x87000080, 0xFF0000E0, 4, TMS320C55_add_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACy, 0x00000300 }, { fn_hi, OP_TRUE, }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, - { 0x870000A0, 0xFF0000E0, 4, TMS320C55_sub_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACy, 0x00000300 }, { fn_hi, OP_TRUE, }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, - { 0x870000C0, 0xFF0000E0, 4, TMS320C55_mov_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0, }, { op_Ymem, 0x0003F000 }}}, - { 0x8A0000A0, 0xFF0000F0, 4, TMS320C55_mov_mov, {{ op_Xmem, 0x00FC0000 }, { op_dst, 0x00000F00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { op_dst, 0x0000000F }}}, - { make_longlong(0x00001000, 0x008A), make_longlong(0x0000F700, 0x00FF), 5, TMS320C55_mov_aadd, {{ op_Smem, 0xFF000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_src, 0x00000000F0 }, { op_dst, 0x0000F00000 }}}, - { make_longlong(0x0000D600, 0x008A), make_longlong(0x0000FF00, 0x00FF), 5, TMS320C55_mov_add, {{ op_Xmem, 0xFC000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_Ymem, 0x0003F00000 }, { op_dst, 0x00000000F0 }, { op_src, 0x000000000F }}}, - { make_longlong(0x0000E708, 0x008A), make_longlong(0x0000FF0C, 0x00FF), 5, TMS320C55_mov_mov, {{ op_Xmem, 0xFC000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_ACx, 0x00000000C0 }, { shl_Tx, 0x0000000030 }, { fn_hi, OP_TRUE_5 }, { fn_rnd, 0x0000000001 }, { op_Ymem, 0x0003F00000 }}}, - { 0x8B0004B4, 0xFF000FFF, 4, TMS320C55_amar_amar, {{ op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }}}, - { make_longlong(0x00001400, 0x008C), make_longlong(0x0000F700, 0x00FF), 5, TMS320C55_mov_aadd, {{ op_src, 0x000F0000 }, { op_Smem, 0xFF000000 }, { blt_prll, 0 }, { op_k8, 0x00000000FF }, { op_dst, 0x0000F00000 }}}, - { make_longlong(0x000CB000, 0x008D), make_longlong(0x000FFC03, 0x00FF), 5, TMS320C55_btst_mov, {{ op_k4, 0x000000F0 }, { op_Xmem, 0xFC000000 }, { op_TCx, 0x00000001 }, { blt_prll, 0 }, { op_Ymem, 0x0003F00000 }, { shl_16, 0 }, { op_ACx, 0x00000300 }}}, - { make_longlong(0x061A0000, 0x8D00), make_longlong(0x0FF70000, 0xFF00), 6, TMS320C55_add_asub, {{ op_Smem, make_longlong(0x00000000, 0x00FF) }, { op_dst, make_longlong(0x0000F000, 0x0000) }, { op_src, 0x000000000F00 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0B100500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0B160500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_asub, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0D100800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { op_ACx, 0x000000003000 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0B140500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0B140800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_ACx, make_longlong(0x00003000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0B100800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_ACx, make_longlong(0x00003000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x06140000, 0x8E00), make_longlong(0x0FF70000, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_k8, make_longlong(0x0000FF00, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, - { make_longlong(0x0DEB080D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_mov_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dbl, OP_TRUE_6 }, { op_ACx, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1) }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dual, OP_TRUE_6 }}}, - { make_longlong(0x0EEB040D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_sub_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1 ) }, { op_Ymem, make_longlong(0xF0000000, 0x03) }, { fn_dual, OP_TRUE_6 }}}, - { make_longlong(0x0EEB000D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_add_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1 ) }, { op_Ymem, make_longlong(0xF0000000, 0x03) }, { fn_dual, OP_TRUE_6 }}}, - { make_longlong(0x0EEB0408, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_sub_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dbl, OP_TRUE_6 }}}, - { make_longlong(0x0EEB0008, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_add_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dbl, OP_TRUE_6 }}}, - - // 10001xxx error manual - { 0x9000, 0xFF00, 2, TMS320C55_mov2, {{op_xsrc, 0x00F0 }, {op_xdst, 0x000F}}}, - { 0x9100, 0xFF00, 2, TMS320C55_b, {{ op_ACx, 0x0003 }}}, - { 0x9200, 0xFF00, 2, TMS320C55_call, {{ op_ACx, 0x0003 }}}, - { 0x9400, 0xFF00, 2, TMS320C55_reset }, - { 0x9500, 0xFF80, 2, TMS320C55_intr, {{ op_k5, 0x001F }}}, - { 0x9580, 0xFF80, 2, TMS320C55_trap, {{ op_k5, 0x001F }}}, - { 0x9600, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }}}, - { 0x9680, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}}, - // 10010111 error manual - // mmap() - // port() - // <instruction>.LR - // <instruction>.CR - { 0x9E00, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }, { insn_UP, 0 }}}, - { 0x9E80, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}}, - { 0x9F00, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }}}, - { 0x9F80, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}}, - { 0xA000, 0xF000, 2, TMS320C55_mov2, {{ op_Smem, 0x00FF }, { op_dst, 0x0F00 }}}, - { 0xB000, 0xFC00, 2, TMS320C55_mov2, {{ op_Smem, 0x00FF }, { shl_16, 0 }, { op_ACx, 0x0300 }}}, - { 0xB400, 0xFF00, 2, TMS320C55_amar1, {{ op_Smem, 0x00FF }}}, - { 0xB500, 0xFF00, 2, TMS320C55_psh1, {{ op_Smem, 0x00FF }}}, - { 0xB600, 0xFF00, 2, TMS320C55_delay, {{ op_Smem, 0x00FF }}}, - { 0xB700, 0xFF00, 2, TMS320C55_psh1, {{ op_Lmem, 0x00FF }, { fn_dbl, OP_TRUE }}}, - { 0xB800, 0xFF00, 2, TMS320C55_pop1, {{ op_Lmem, 0x00FF }, { fn_dbl, OP_TRUE }}}, - { 0xBB00, 0xFF00, 2, TMS320C55_pop1, {{ op_Smem, 0x00FF }}}, - { 0xBC00, 0xFC00, 2, TMS320C55_mov2, {{ op_ACx, 0x0300 }, { fn_hi, OP_TRUE }, { op_Smem, 0x00FF }}}, - { 0xC000, 0xF000, 2, TMS320C55_mov2, {{ op_src, 0x0F00 }, { op_Smem, 0x00FF }}}, - { 0xD00000, 0xFF0040, 3, TMS320C55_macmz, {{ op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, - { 0xD00040, 0xFF0040, 3, TMS320C55_macmrz, {{ op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, - { 0xD10000, 0xFF000C, 3, TMS320C55_mpym3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, - { 0xD10004, 0xFF000C, 3, TMS320C55_macm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, - { 0xD10008, 0xFF000C, 3, TMS320C55_masm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, - { 0xD20000, 0xFF000C, 3, TMS320C55_macm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD20004, 0xFF000C, 3, TMS320C55_masm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD20008, 0xFF000C, 3, TMS320C55_sqam2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD2000C, 0xFF000C, 3, TMS320C55_sqsm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD30000, 0xFF000C, 3, TMS320C55_mpym2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD30008, 0xFF000C, 3, TMS320C55_sqrm, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000030 }}}, - { 0xD30004, 0xFF0004, 3, TMS320C55_mpym3, {{ insn_1_R, 0x000040 }, { insn_1_U, 0x000008 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x000003 }, { op_ACx, 0x000030 }}}, - { 0xD40000, 0xFF0000, 3, TMS320C55_macm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x00000C }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD50000, 0xFF0000, 3, TMS320C55_masm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x00000C }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, - { 0xD60000, 0xFF0000, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { opt_dst, 0x0000F0 }}}, - { 0xD70000, 0xFF0000, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { opt_dst, 0x0000F0 }}}, - { 0xD80000, 0xFF0000, 3, TMS320C55_sub3, {{ op_src, 0x00000F }, { op_Smem, 0x00FF00 }, { op_dst, 0x0000F0 }}}, - { 0xD90000, 0xFF0000, 3, TMS320C55_and3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, - { 0xDA0000, 0xFF0000, 3, TMS320C55_or3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, - { 0xDB0000, 0xFF0000, 3, TMS320C55_xor3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, - { 0xDC0000, 0xFF0002, 3, TMS320C55_btst, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TCx, 0x000001 }}}, - { 0xDC0002, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_DP, 0 }}}, - { 0xDC0012, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_CDP, 0 }}}, - { 0xDC0022, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA01, 0 }}}, - { 0xDC0032, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA23, 0 }}}, - { 0xDC0042, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA45, 0 }}}, - { 0xDC0052, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA67, 0 }}}, - { 0xDC0062, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSAC, 0 }}}, - { 0xDC0072, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_SP, 0 }}}, - { 0xDC0082, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_SSP, 0 }}}, - { 0xDC0092, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BK03, 0 }}}, - { 0xDC00A2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BK47, 0 }}}, - { 0xDC00B2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BKC, 0 }}}, - { 0xDC00C2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_DPH, 0 }}}, - { 0xDC00D2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_MDP05, 0 }}}, - { 0xDC00E2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_MDP67, 0 }}}, - { 0xDC00F2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_PDP, 0 }}}, - { 0xDC0003, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_CSR, 0 }}}, - { 0xDC0013, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BRC0, 0 }}}, - { 0xDC0023, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BRC1, 0 }}}, - { 0xDC0033, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_TRN0, 0 }}}, - { 0xDC0043, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_TRN1, 0 }}}, - { 0xDD0000, 0xFF0003, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDD0001, 0xFF0003, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDD0002, 0xFF0003, 3, TMS320C55_addsub2cc, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_Tx, 0x00000C }, { op_TC1, 0, }, { op_TC2, 0, }, { op_ACy, 0x000030 }}}, - { 0xDD0003, 0xFF0003, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { fn_rnd, 0x000040 }, { op_ACx, 0x000030 }}}, - { 0xDE0000, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC1, 0 }, { op_ACy, 0x000030 }}}, - { 0xDE0001, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC2, 0 }, { op_ACy, 0x000030 }}}, - { 0xDE0002, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC1, 0 }, { op_TC2, 0, }, { op_ACy, 0x000030 }}}, - { 0xDE0003, 0xFF000F, 3, TMS320C55_subc2, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDE0004, 0xFF000F, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDE0005, 0xFF000F, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDE0006, 0xFF000F, 3, TMS320C55_sub3, {{ op_ACx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACy, 0x000030 }}}, - { 0xDE0008, 0xFF000F, 3, TMS320C55_addsub, {{ op_Tx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { op_ACx, 0x000030 }}}, - { 0xDE0009, 0xFF000F, 3, TMS320C55_subadd, {{ op_Tx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { op_ACx, 0x000030 }}}, - { 0xDF0000, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }, { fn_uns, OP_NOT(0x000001) }, { op_dst, 0x0000F0 }}}, - { 0xDF0002, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }, { fn_uns, OP_NOT(0x000001) }, { op_dst, 0x0000F0 }}}, - { 0xDF0004, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x000030 }}}, - { 0xDF0008, 0xFF000E, 3, TMS320C55_add3, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_CARRY, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDF000A, 0xFF000E, 3, TMS320C55_sub3, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_BORROW, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDF000C, 0xFF000E, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xDF000E, 0xFF000E, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xE00000, 0xFF0000, 3, TMS320C55_btst, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TCx, 0x000001 }}}, - { 0xE10000, 0xFF0000, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }, { slo_SHIFTW, 0x00003F }, { op_ACx, 0x0000C0 }}}, - { 0xE20000, 0xFF0000, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }, { slo_SHIFTW, 0x00003F }, { op_ACx, 0x0000C0 }}}, - { 0xE30000, 0xFF000E, 3, TMS320C55_btstset, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}}, - { 0xE30002, 0xFF000E, 3, TMS320C55_btstset, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}}, - { 0xE30004, 0xFF000E, 3, TMS320C55_btstclr, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}}, - { 0xE30006, 0xFF000E, 3, TMS320C55_btstclr, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}}, - { 0xE30008, 0xFF000E, 3, TMS320C55_btstnot, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}}, - { 0xE3000A, 0xFF000E, 3, TMS320C55_btstnot, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}}, - { 0xE3000C, 0xFF000F, 3, TMS320C55_bset2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, - { 0xE3000D, 0xFF000F, 3, TMS320C55_bclr2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, - { 0xE3000E, 0xFF000E, 3, TMS320C55_bnot, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, - { 0xE40000, 0xFF0004, 3, TMS320C55_psh2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, - { 0xE40004, 0xFF0004, 3, TMS320C55_pop2, {{ op_dst, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50004, 0xFF000D, 3, TMS320C55_mov2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }}}, - { 0xE50005, 0xFF000D, 3, TMS320C55_mov2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }}}, - { 0xE50008, 0xFF00FC, 3, TMS320C55_mov2, {{ op_DP, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50018, 0xFF00FC, 3, TMS320C55_mov2, {{ op_CDP, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50028, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA01, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50038, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA23, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50048, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA45, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50058, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA67, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50068, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSAC, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50078, 0xFF00FC, 3, TMS320C55_mov2, {{ op_SP, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50088, 0xFF00FC, 3, TMS320C55_mov2, {{ op_SSP, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE50098, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BK03, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE500A8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BK47, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE500B8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BKC, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE500C8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_DPH, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE500D8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_MDP05, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE500E8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_MDP67, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE500F8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_PDP, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE5000C, 0xFF007C, 3, TMS320C55_mov2, {{ op_CSR, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE5001C, 0xFF007C, 3, TMS320C55_mov2, {{ op_BRC0, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE5002C, 0xFF007C, 3, TMS320C55_mov2, {{ op_BRC1, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE5003C, 0xFF007C, 3, TMS320C55_mov2, {{ op_TRN0, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE5004C, 0xFF007C, 3, TMS320C55_mov2, {{ op_TRN1, 0 }, { op_Smem, 0x00FF00 }}}, - { 0xE60000, 0xFF0000, 3, TMS320C55_mov2, {{ op_K8, 0x0000FF }, { op_Smem, 0x00FF00 }}}, - { 0xE70000, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { op_Smem, 0x00FF00 }}}, - { 0xE70008, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { fn_hi, OP_TRUE, }, { fn_rnd, 0x000001 }, { op_Smem, 0x00FF00 }}}, - { 0xE7000C, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { fn_sat, OP_TRUE, }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { fn_uns, 0x000002 }, { op_Smem, 0x00FF00 }}}, - { 0xE80000, 0xFF0004, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { op_Smem, 0x00FF00 }}}, - { 0xE80004, 0xFF0004, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { fn_sat, OP_TRUE }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { fn_uns, 0x000002 }, { op_Smem, 0x00FF00 }}}, - { 0xE90000, 0xFF0000, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_SHIFTW, 0x00003F }, { op_Smem, 0x00FF00 }}}, - { 0xEA0000, 0xFF0000, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_SHIFTW, 0x00003F }, { fn_hi, OP_TRUE }, { op_Smem, 0x00FF00 }}}, - { 0xEB0004, 0xFF000D, 3, TMS320C55_mov2, {{ op_RETA, 0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEB0005, 0xFF000D, 3, TMS320C55_mov2, {{ op_xsrc, 0x0000F0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, // not in documentation - { 0xEB0008, 0xFF000D, 3, TMS320C55_mov2, {{ op_ACx, 0x000030 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEB0009, 0xFF000D, 3, TMS320C55_mov2, {{ op_ACx, 0x000030 }, { fn_sat, OP_TRUE }, { fn_uns, 0x000002 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEB000C, 0xFF000F, 3, TMS320C55_mov2, {{ op_TAx, 0x0000F0 }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEB000D, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { shr, OP_IMM(1) }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }}}, - { 0xEB000E, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { fn_hi, OP_TRUE }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEB000F, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { fn_lo, OP_TRUE }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEC0000, 0xFF000E, 3, TMS320C55_bset2, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, - { 0xEC0002, 0xFF000E, 3, TMS320C55_bclr2, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, - { 0xEC0004, 0xFF000E, 3, TMS320C55_btstp, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, - { 0xEC0006, 0xFF000E, 3, TMS320C55_bnot, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, - { 0xEC0008, 0xFF000E, 3, TMS320C55_btst, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }, { op_TCx, 0x000001 }}}, - { 0xEC000E, 0xFF000F, 3, TMS320C55_amar2, {{ op_Smem, 0x00FF00 }, { op_xdst, 0x0000F0 }}}, - { 0xED0000, 0xFF000E, 3, TMS320C55_add2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xED0002, 0xFF000E, 3, TMS320C55_sub2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xED0004, 0xFF000E, 3, TMS320C55_sub3, {{ op_ACx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACy, 0x000030 }}}, - { 0xED0006, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_RETA, 0 }}}, - { 0xED0008, 0xFF000E, 3, TMS320C55_mov2, {{ insn_1_40, 0x000001 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }}}, - { 0xED000A, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }, { fn_hi, OP_TRUE, }, { fn_pair, OP_TRUE }}}, - { 0xED000C, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }, { fn_lo, OP_TRUE, }, { fn_pair, OP_TRUE }}}, - { 0xED000E, 0xFF000F, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_TAx, 0x0000F0 }, { fn_pair, OP_TRUE }}}, - { 0xED000F, 0xFF000F, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_xdst, 0x0000F0 }}}, - { 0xEE0000, 0xFF000E, 3, TMS320C55_add2, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xEE0002, 0xFF000E, 3, TMS320C55_sub2, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, - { 0xEE0004, 0xFF000E, 3, TMS320C55_sub3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { op_ACy, 0x000030 }}}, - { 0xEE0006, 0xFF000E, 3, TMS320C55_sub3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_Tx, 0x0000C0 }, { op_ACx, 0x000030 }}}, - { 0xEE0008, 0xFF000E, 3, TMS320C55_add3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_Tx, 0x0000C0 }, { op_ACx, 0x000030 }}}, - { 0xEE000A, 0xFF000E, 3, TMS320C55_sub3, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}}, - { 0xEE000C, 0xFF000E, 3, TMS320C55_addsub, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}}, - { 0xEE000E, 0xFF000E, 3, TMS320C55_subadd, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}}, - { 0xEF0000, 0xFF000C, 3, TMS320C55_mov2, {{ op_Cmem, 0x000003 }, { op_Smem, 0x00FF00 }}}, - { 0xEF0004, 0xFF000C, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_Cmem, 0x000003 }}}, - { 0xEF0008, 0xFF000C, 3, TMS320C55_mov2, {{ op_Cmem, 0x000003 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, - { 0xEF000C, 0xFF000C, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_Cmem, 0x000003 }}}, - { 0xF0000000, 0xFF000000, 4, TMS320C55_cmp, {{ op_Smem, 0x00FF0000 }, { eq_K16, 0x0000FFFF }, { op_TC1, 0 }}}, - { 0xF1000000, 0xFF000000, 4, TMS320C55_cmp, {{ op_Smem, 0x00FF0000 }, { eq_K16, 0x0000FFFF }, { op_TC2, 0 }}}, - { 0xF2000000, 0xFF000000, 4, TMS320C55_band, {{ op_Smem, 0x00FF0000 }, { op_k16, 0x0000FFFF }, { op_TC1, 0 }}}, - { 0xF3000000, 0xFF000000, 4, TMS320C55_band, {{ op_Smem, 0x00FF0000 }, { op_k16, 0x0000FFFF }, { op_TC2, 0 }}}, - { 0xF4000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, - { 0xF5000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, - { 0xF6000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, - { 0xF7000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, - { 0xF8000000, 0xFF000004, 4, TMS320C55_mpymk, {{ insn_1_R, 0x00000001 }, { op_Smem, 0x00FF0000 }, { fn_T3, 0x00000002 }, { op_K8, 0x0000FF00 }, { op_ACx, 0x00000030 }}}, - { 0xF8000004, 0xFF000004, 4, TMS320C55_macmk3, {{ insn_1_R, 0x00000001 }, { op_Smem, 0x00FF0000 }, { fn_T3, 0x00000002 }, { op_K8, 0x0000FF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0xF9000000, 0xFF00000C, 4, TMS320C55_add2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0xF9000004, 0xFF00000C, 4, TMS320C55_sub2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, - { 0xF9000008, 0xFF00000C, 4, TMS320C55_mov2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x00000030 }}}, - { 0xFA000000, 0xFF000004, 4, TMS320C55_mov2, {{ op_ACx, 0x000000C0 }, { shl_SHIFTW, 0x00003F00 }, { fn_hi, OP_TRUE }, { fn_rnd, 0x00000001 }, { op_Smem, 0x00FF0000 }}}, - { 0xFA000004, 0xFF000004, 4, TMS320C55_mov2, {{ op_ACx, 0x000000C0 }, { shl_SHIFTW, 0x00003F00 }, { fn_sat, OP_TRUE }, { fn_hi, OP_TRUE }, { fn_rnd, 0x00000001 }, { fn_uns, 0x00008000 }, { op_Smem, 0x00FF0000 }}}, - { 0xFB000000, 0xFF000000, 4, TMS320C55_mov2, {{ op_K16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, - { 0xFC000000, 0xFF000000, 4, TMS320C55_bcc, {{ op_L16, 0x0000FFFF }, { op_ARn_mod, 0x00FF0000 }, { neq_0, OP_TRUE }}}, - { 0, 0, 0, TMS320C55_null } -}; - -//-------------------------------------------------------------------------- -// unpack an "sdual" instruction operand ( 6->8 bits ) -static uchar unpack_opsdual(uchar packed) -{ - static const uchar lowpart[8] = { 0, 1, 2, 3, 9, 4, 10, 5 }; - return ((lowpart[packed&7] | ((packed<<1) & 0x70)) << 1) | 1; -} - -//-------------------------------------------------------------------------- -// unpack an "sdual" instruction -// these are probably instructions from C55x+ processor -static bool unpack_sdual(ea_t ea, bytevec_t *insn1, bytevec_t *insn2) -{ - // sdual instruction packs two parallel instructions - uint32 word = 0; - for ( int i=0; i < 4; i++ ) - word = (word << 8) | get_byte(ea + i); - uchar opc1 = ((word >> 20) & 0xF0) | ((word >> 8) & 0x0F); - uchar opc2 = (word & 0xFF); - if ( opc2 & 0x80 ) - { - // 3 | 2 | 1 | - // 1098 7654|321098 76|5432 1098|76543210 - // | | | - // 1000 1011|100010 10|1001 1100|11000001 - // o1h | opd1 opd2 o1l| opc2 - // - // opcode1 = o1h:o1l - // opcode2 = opc2 - // opd1 and opd2 are packed operand parts - - uchar ops1 = (word >> 18) & 0x3F; - uchar ops2 = (word >> 12) & 0x3F; - int insn1_len = get_insn_size(masks, opc1<<24); - if ( insn1_len < 2 ) - return false; - int insn2_len = get_insn_size(masks, opc2<<24); - if ( insn2_len < 2 ) - { - // try to add extra bytes (skip operand byte) - uint32 w2 = (opc2<<24) | (get_byte(ea + insn1_len+2) << 8); - insn2_len = get_insn_size(masks, w2); - if ( insn2_len < 2 ) - { - w2 |= get_byte(ea + insn1_len+3); - insn2_len = get_insn_size(masks, w2); - } - } - if ( insn2_len < 2 ) - return false; - if ( insn1 ) - { - insn1->clear(); - // add real opcode and operands - insn1->push_back(opc1); - insn1->push_back(unpack_opsdual(ops1)); - // add extra bytes - for ( int i=4; i < insn1_len+2; i++ ) - insn1->push_back(get_byte(ea + i)); - } - if ( insn2 ) - { - insn2->clear(); - insn2->push_back(opc2); - insn2->push_back(unpack_opsdual(ops2)); - for ( int i=insn1_len+2; i < (insn1_len+insn2_len); i++ ) - insn2->push_back(get_byte(ea + i)); - } - } - else - { - // unpacked insn1 can be 2, 3, or 4 bytes - // insn2 is always 3 bytes - // - // source bytes: ab cd ef gh ij kl mn op - // case 2+3: - // insn1 = bf cd - // insn2 = g4 ij eh - // case 3+3: - // insn1 = bf cd ij - // insn2 = g4 kl eh - // case 4+3: - // insn1 = bf cd ij kl - // insn2 = g4 mn eh - uint32 w1 = (opc1<<24) | (word & 0x00FF0000); // bfcd0000 - uint32 w2 = (((word&0xF0)|4)<<24) | (word&0xF000) | ((word&0x0F)<<8); // g400eh00 - int insn1_len = get_insn_size(masks, w1); - if ( insn1_len == 0 ) - { - // try to add one byte - w1 |= (get_byte(ea + 4) << 8); - insn1_len = get_insn_size(masks, w1); - if ( insn1_len == 0 || insn1_len < 3 ) - { - w1 |= get_byte(ea + 5); - insn1_len = get_insn_size(masks, w1); - if ( insn1_len != 4 ) - return false; - } - } - int insn2_len = get_insn_size(masks, w2); - if ( insn1_len < 2 || insn2_len != 3 ) - return false; - if ( insn1 ) - { - insn1->clear(); - insn1->push_back((w1>>24)&0xFF); - insn1->push_back((w1>>16)&0xFF); - // add extra bytes - for ( int i=4; i < insn1_len + 2; i++ ) - insn1->push_back(get_byte(ea + i)); - } - if ( insn2 ) - { - insn2->clear(); - insn2->push_back((w2>>24)&0xFF); - insn2->push_back(get_byte(ea + insn1_len + 2)); - insn2->push_back((w2>>8)&0xFF); - } - } - return true; -} - -//-------------------------------------------------------------------------- -void ana_status_bits(insn_t &insn) -{ - if ( (insn.itype == TMS320C55_bclr2 || insn.itype == TMS320C55_bset2) - && insn.Op2.type == o_reg - && insn.Op1.type == o_imm ) - { - int reg = -1; - switch ( insn.Op2.reg ) - { - case ST0_55: - { - static const int regs[] = - { - -1, -1, -1, -1, -1, -1, -1, -1, - -1, ACOV1, ACOV0, CARRY, TC2, TC1, ACOV3, ACOV2 - }; - reg = regs[int(insn.Op1.value)]; - break; - } - case ST1_55: - { - static const int regs[] = - { - -1, -1, -1, -1, -1, C54CM, FRCT, C16, - SXMD, SATD, M40, INTM, HM, XF, CPL, BRAF - }; - reg = regs[int(insn.Op1.value)]; - break; - } - case ST2_55: - { - static const int regs[] = - { - AR0LC, AR1LC, AR2LC, AR3LC, AR4LC, AR5LC, AR6LC, AR7LC, - CDPLC, -1, RDM, EALLOW, DBGM, -1, -1, ARMS - }; - reg = regs[int(insn.Op1.value)]; - break; - } - case ST3_55: - { - static const int regs[] = - { - SST, SMUL, CLKOFF, -1, -1, SATA, MPNMC, CBERR, - -1, -1, -1, -1, HINT, CACLR, CAEN, CAFRZ - }; - reg = regs[int(insn.Op1.value)]; - break; - } - } - if ( reg != -1 ) - { - insn.itype = (insn.itype == TMS320C55_bclr2) ? TMS320C55_bclr1 : TMS320C55_bset1; - insn.Op1.type = o_reg; - insn.Op1.reg = uint16(reg); - insn.Op2.type = o_void; - } - } -} - -//-------------------------------------------------------------------------- -int tms320c55_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - optional_op = -1; - bytes_c bytes(insn); - uchar firstbyte = bytes.get_next(); - - int sdual_len = helper.altval_ea(insn.ea, TAG_SDUAL); - if ( sdual_len != 0 ) - { - // this is a second part of sdual instruction - bytevec_t insn_bytes; - if ( !unpack_sdual(insn.ea - sdual_len, NULL, &insn_bytes) ) - return 0; - bytes.set_cache(insn_bytes); - process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode - if ( insn.itype == TMS320C55_null || insn.size != insn_bytes.size() ) - return 0; - ana_status_bits(insn); - insn.SpecialModes |= TMS_MODE_USER_PARALLEL; - return insn.size; - } - else - { - // a normal instruction ? - process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode - if ( insn.size != 0 && insn.itype != TMS320C55_null ) - { - helper.altdel_ea(insn.ea + insn.size, TAG_SDUAL); - } - else if ( (firstbyte & 0xF8) == 0x88 ) - { - // "sdual" instruction; unpack it - bytevec_t insn_bytes; - if ( !unpack_sdual(insn.ea, &insn_bytes, NULL) ) - return 0; - bytes.set_cache(insn_bytes); - process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode - if ( insn.itype != TMS320C55_null && insn.size == insn_bytes.size() ) - { - ana_status_bits(insn); - // remember that next address is the second part - helper.altset_ea(insn.ea + insn.size, insn.size, TAG_SDUAL); - return insn.size; - } - } - } - - // analyze special bits access - ana_status_bits(insn); - - // analyze user-parallelized instructions - if ( firstbyte <= MAX_BYTE_USER_PARALLELIZED && (firstbyte & 1) ) // instruction has E bit set - insn.SpecialModes |= TMS_MODE_USER_PARALLEL; - - // analyze postfixes - uchar nextbyte = get_byte(insn.ea+insn.size); // is_mapped() not necessary here - switch ( nextbyte ) - { - case BYTE_MMAP: // mmap() - if ( insn.OpMem != 0 ) - { - int n = insn.OpMem - 1; - if ( insn.ops[n].type == o_mem - && insn.ops[n].tms_regH == DPH - && insn.ops[n].tms_regP == DP - && insn.ops[n].tms_modifier == TMS_MODIFIER_DMA ) - { // @dma using DP - insn.ops[n].tms_regH = 0; - insn.ops[n].tms_regP = 0; - insn.ops[n].tms_modifier = TMS_MODIFIER_MMAP; - insn.size++; - } - else if ( insn.ops[n].type == o_reg - && insn.ops[n].reg == SP - && insn.ops[n].tms_modifier == TMS_MODIFIER_REG_OFFSET ) - { // @dma using SP - insn.ops[n].addr = insn.ops[n].value; - insn.ops[n].type = o_mem; - insn.ops[n].tms_regH = 0; - insn.ops[n].tms_regP = 0; - insn.ops[n].tms_modifier = TMS_MODIFIER_MMAP; - insn.size++; - } - } - break; - case BYTE_PORT1: - case BYTE_PORT2: // port() - if ( insn.OpMem != 0 ) - { - int n = insn.OpMem - 1; - switch ( insn.ops[n].type ) - { - case o_mem: - insn.ops[n].type = o_io; - insn.ops[n].tms_regH = 0; - insn.ops[n].tms_regP = PDP; - insn.ops[n].addr = insn.ops[n].addr >> 1; - insn.ops[n].tms_modifier = TMS_MODIFIER_PORT_AT; - insn.size++; - break; - case o_reg: - insn.ops[n].tms_operator1 |= TMS_OPERATOR_PORT & 0xFF; - insn.ops[n].tms_operator2 |= (TMS_OPERATOR_PORT >> 8); - insn.size++; - break; - } - } - break; - case BYTE_LR: - case BYTE_CR: // .lr & .cr - insn.SpecialModes |= nextbyte == BYTE_LR ? TMS_MODE_LR : TMS_MODE_CR; - insn.size++; - break; - } - if ( insn.itype == TMS320C55_null ) - return 0; - return insn.size; -} diff --git a/idasdk75/module/tms320c55/ins.hpp b/idasdk75/module/tms320c55/ins.hpp deleted file mode 100644 index a7fd810..0000000 --- a/idasdk75/module/tms320c55/ins.hpp +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ - -TMS320C55_null = 0, // Unknown Operation - -// ARITHMETICAL OPERATIONS - -TMS320C55_abdst, // Absolute Distance -TMS320C55_abs1, // Absolute Value -TMS320C55_abs2, // Absolute Value - -TMS320C55_add1, // Addition -TMS320C55_add2, // Addition -TMS320C55_add3, // Addition -TMS320C55_add4, // Addition -TMS320C55_addv1, // Addition -TMS320C55_addv2, // Addition -TMS320C55_addrv1, // Addition and Round -TMS320C55_addrv2, // Addition and Round - -TMS320C55_maxdiff, // Compare and Select Maximum -TMS320C55_dmaxdiff, // Compare and Select 40-bit Maximum -TMS320C55_mindiff, // Compare and Select Minimum -TMS320C55_dmindiff, // Compare and Select 40-bit Minimum - -TMS320C55_addsubcc4, // Conditional Add or Subtract -TMS320C55_addsubcc5, // Conditional Add or Subtract -TMS320C55_addsub2cc, // Conditional Add or Subtract - -TMS320C55_sftcc, // Conditional Shift - -TMS320C55_subc2, // Conditional Subtract -TMS320C55_subc3, // Conditional Subtract - -TMS320C55_addsub, // Paralleled Add - Subtract -TMS320C55_subadd, // Parallel Subtract - Add - -TMS320C55_mpy_mpy, // Two Parallel Multiply -TMS320C55_mpy_mpyr, // Two Parallel Multiply, and Round -TMS320C55_mpy_mpy40, // Two Parallel Multiply, on 40 bits -TMS320C55_mpy_mpyr40, // Two Parallel Multiply, and Round on 40 bits -TMS320C55_mac_mpy, // Parallel Multiply - Accumulate -TMS320C55_macr_mpyr, // Parallel Multiply - Accumulate, and Round -TMS320C55_mac40_mpy40, // Parallel Multiply - Accumulate, on 40 bits -TMS320C55_macr40_mpyr40, // Parallel Multiply - Accumulate, and Round on 40 bits -TMS320C55_mas_mpy, // Parallel Multiply - Subtract -TMS320C55_masr_mpyr, // Parallel Multiply - Subtract, and Round -TMS320C55_mas40_mpy40, // Parallel Multiply - Subtract, on 40 bits -TMS320C55_masr40_mpyr40, // Parallel Multiply - Subtract, and Round on 40 bits -TMS320C55_amar_mpy, // Parallel Modify Auxiliary Register - Multiply -TMS320C55_amar_mpyr, // Parallel Modify Auxiliary Register - Multiply, and Round -TMS320C55_amar_mpy40, // Parallel Modify Auxiliary Register - Multiply, on 40 bits -TMS320C55_amar_mpyr40, // Parallel Modify Auxiliary Register - Multiply, and Round on 40 bits -TMS320C55_mac_mac, // Two Parallel Multiply and Accumulate -TMS320C55_macr_macr, // Two Parallel Multiply and Accumulate, and Round -TMS320C55_mac40_mac40, // Two Parallel Multiply and Accumulate, on 40 bits -TMS320C55_macr40_macr40, // Two Parallel Multiply and Accumulate, and Round on 40 bits -TMS320C55_mas_mac, // Parallel Multiply and Subtract - Multiply and Accumulate -TMS320C55_masr_macr, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round -TMS320C55_mas40_mac40, // Parallel Multiply and Subtract - Multiply and Accumulate, on 40 bits -TMS320C55_masr40_macr40, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round on 40 bits -TMS320C55_amar_mac, // Parallel Modify Auxiliary Register - Multiply and Accumulate -TMS320C55_amar_macr, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round -TMS320C55_amar_mac40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, on 40 bits -TMS320C55_amar_macr40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round on 40 bits -TMS320C55_mas_mas, // Two Parallel Multiply and Subtract -TMS320C55_masr_masr, // Two Parallel Multiply and Subtract, and Round -TMS320C55_mas40_mas40, // Two Parallel Multiply and Subtract, on 40 bits -TMS320C55_masr40_masr40, // Two Parallel Multiply and Subtract, and Round on 40 bits -TMS320C55_amar_mas, // Parallel Modify Auxiliary Register - Multiply and Subtract -TMS320C55_amar_masr, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round -TMS320C55_amar_mas40, // Parallel Modify Auxiliary Register - Multiply and Subtract, on 40 bits -TMS320C55_amar_masr40, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round on 40 bits -TMS320C55_mpy_mac, // Parallel Multiply - Multiply and Accumulate -TMS320C55_mpyr_macr, // Parallel Multiply - Multiply and Accumulate, and Round -TMS320C55_mpy40_mac40, // Parallel Multiply - Multiply and Accumulate, on 40 bits -TMS320C55_mpyr40_macr40, // Parallel Multiply - Multiply and Accumulate, and Round on 40 bits -TMS320C55_amar3, // Three Parallel Modify Auxiliary Registers - -TMS320C55_firsadd, // Parallel Multiply and Accumulate - Add -TMS320C55_firssub, // Parallel Multiply and Accumulate - Subtract - -TMS320C55_mpym_mov, // Parallel Multiply - Store -TMS320C55_mpymr_mov, // Parallel Multiply - Store, and Round -TMS320C55_macm_mov, // Parallel Multiply and Accumulate - Store -TMS320C55_macmr_mov, // Parallel Multiply and Accumulate - Store, and Round -TMS320C55_masm_mov, // Parallel Multiply and Subtract - Store -TMS320C55_masmr_mov, // Parallel Multiply and Subtract - Store, and Round -TMS320C55_add_mov, // Parallel Add - Store -TMS320C55_sub_mov, // Parallel Subtract - Store -TMS320C55_mov_mov, // Parallel Load - Store -TMS320C55_mov_aadd, // Parallel Store - aadd -TMS320C55_mov_add, // Parallel Store - Add -TMS320C55_amar_amar, // Parallel Modify Auxiliary Register - Modify Auxiliary Register -TMS320C55_add_asub, // Parallel Add - asub -TMS320C55_btst_mov, // Parallel Bit Test - Store -TMS320C55_mov_asub, // Parallel Store - asub - -TMS320C55_lms, // Least Mean Square - -TMS320C55_max1, // Maximum Comparison -TMS320C55_max2, // Maximum Comparison -TMS320C55_min1, // Minimum Comparison -TMS320C55_min2, // Minimum Comparison - -TMS320C55_cmp, // Memory Comparison -TMS320C55_cmpu, // Unsigned memory Comparison - -TMS320C55_aadd, // Add Two Registers -TMS320C55_asub, // Subtract Two Registers -TMS320C55_amov, // Move From Register to Register -TMS320C55_amar1, // Auxiliary Register Modification - -TMS320C55_sqr1, // Square -TMS320C55_sqr2, // Square -TMS320C55_sqrr1, // Square and Round -TMS320C55_sqrr2, // Square and Round -TMS320C55_mpy1, // Multiply -TMS320C55_mpy2, // Multiply -TMS320C55_mpy3, // Multiply -TMS320C55_mpyr1, // Multiply and Round -TMS320C55_mpyr2, // Multiply and Round -TMS320C55_mpyr3, // Multiply and Round -TMS320C55_mpyk2, // Multiply by Constant -TMS320C55_mpyk3, // Multiply by Constant -TMS320C55_mpykr2, // Multiply by Constant and Round -TMS320C55_mpykr3, // Multiply by Constant and Round -TMS320C55_mpym2, // Multiply Memory Value -TMS320C55_mpym3, // Multiply Memory Values -TMS320C55_mpymr2, // Multiply Memory Value and Round -TMS320C55_mpymr3, // Multiply Memory Values and Round -TMS320C55_mpym403, // Multiply Memory Values on 40 bits -TMS320C55_mpymr403, // Multiply Memory Values and Round on 40 bits -TMS320C55_mpymu3, // Unsigned multiply Memory Values -TMS320C55_mpymru3, // Unsigned multiply Memory Values and Round -TMS320C55_sqrm, // Square Memory Value -TMS320C55_sqrmr, // Square Memory Value, and Round -TMS320C55_mpymk, // Multiply Memory Value by Constant -TMS320C55_mpymkr, // Multiply Memory Value by Constant and Round - -TMS320C55_sqa1, // Square and Accumulate -TMS320C55_sqa2, // Square and Accumulate -TMS320C55_sqar1, // Square, Accumulate and Round -TMS320C55_sqar2, // Square, Accumulate and Round -TMS320C55_mac3, // Multiply and Accumulate -TMS320C55_mac4, // Multiply and Accumulate -TMS320C55_macr3, // Multiply, Accumulate and Round -TMS320C55_macr4, // Multiply, Accumulate and Round -TMS320C55_mack3, // Multiply by Constant and Accumulate -TMS320C55_mack4, // Multiply by Constant and Accumulate -TMS320C55_mackr3, // Multiply by Constant, Round and Accumulate -TMS320C55_mackr4, // Multiply by Constant, Round and Accumulate -TMS320C55_macm2, // Multiply and Accumulate Memory Values -TMS320C55_macm3, // Multiply and Accumulate Memory Values -TMS320C55_macm4, // Multiply and Accumulate Memory Values -TMS320C55_macmr2, // Multiply and Accumulate Memory Values, and Round -TMS320C55_macmr3, // Multiply and Accumulate Memory Values, and Round -TMS320C55_macmr4, // Multiply and Accumulate Memory Values, and Round -TMS320C55_macm403, // Multiply and Accumulate Memory Values, on 40 bits -TMS320C55_macm404, // Multiply and Accumulate Memory Values, on 40 bits -TMS320C55_macmr403, // Multiply and Accumulate Memory Values, and Round on 40 bits -TMS320C55_macmr404, // Multiply and Accumulate Memory Values, and Round on 40 bits -TMS320C55_macmz, // Multiply and Accumulate Memory Values -TMS320C55_macmrz, // Multiply and Accumulate Memory Values, and Round -TMS320C55_sqam2, // Square and Accumulate Memory Value -TMS320C55_sqam3, // Square and Accumulate Memory Values -TMS320C55_sqamr2, // Square and Accumulate Memory Value, and Round -TMS320C55_sqamr3, // Square and Accumulate Memory Values, and Round -TMS320C55_macmk3, // Multiply Memory Value by Constant and Accumulate -TMS320C55_macmk4, // Multiply Memory Value by Constant and Accumulate -TMS320C55_macmkr3, // Multiply Memory Value by Constant - Accumulate, and Round -TMS320C55_macmkr4, // Multiply Memory Value by Constant - Accumulate, and Round - -TMS320C55_sqs1, // Square and Subtract -TMS320C55_sqs2, // Square and Subtract -TMS320C55_sqsr1, // Square, Subtract and Round -TMS320C55_sqsr2, // Square, Subtract and Round - -TMS320C55_mas2, // Multiply and Subtract -TMS320C55_mas3, // Multiply and Subtract -TMS320C55_masr2, // Multiply, Subtract and Round -TMS320C55_masr3, // Multiply, Subtract and Round -TMS320C55_masm2, // Multiply and Subtract Memory Value -TMS320C55_masm3, // Multiply and Subtract Memory Values -TMS320C55_masm4, // Multiply and Subtract Memory Values -TMS320C55_masmr2, // Multiply and Subtract Memory Values, and Round -TMS320C55_masmr3, // Multiply and Subtract Memory Values, and Round -TMS320C55_masmr4, // Multiply and Subtract Memory Values, and Round -TMS320C55_masm403, // Multiply and Subtract Memory Values, on 40 bits -TMS320C55_masm404, // Multiply and Subtract Memory Values, on 40 bits -TMS320C55_masmr403, // Multiply and Subtract Memory Values, and Round on 40 bits -TMS320C55_masmr404, // Multiply and Subtract Memory Values, and Round on 40 bits -TMS320C55_sqsm2, // Square and Subtract Memory Values -TMS320C55_sqsm3, // Square and Subtract Memory Values -TMS320C55_sqsmr2, // Square and Subtract Memory Values, and Round -TMS320C55_sqsmr3, // Square and Subtract Memory Values, and Round - -TMS320C55_neg1, // Negation -TMS320C55_neg2, // Negation - -TMS320C55_mant_nexp, // Exponent and Mantissa -TMS320C55_exp, // Exponent - -TMS320C55_cmpand, // Compare and AND -TMS320C55_cmpandu, // Unsigned compare and AND -TMS320C55_cmpor, // Compare and OR -TMS320C55_cmporu, // Unsigned compare and OR - -TMS320C55_round1, // Round -TMS320C55_round2, // Round - -TMS320C55_sat1, // Saturate -TMS320C55_sat2, // Saturate -TMS320C55_satr1, // Saturate and Round -TMS320C55_satr2, // Saturate and Round - -TMS320C55_sfts2, // Signed Shift -TMS320C55_sfts3, // Signed Shift -TMS320C55_sftsc2, // Signed Shift with Carry -TMS320C55_sftsc3, // Signed Shift with Carry - -TMS320C55_sqdst, // Square distance - -TMS320C55_sub1, // Subtract -TMS320C55_sub2, // Subtract -TMS320C55_sub3, // Subtract -TMS320C55_sub4, // Subtract - -TMS320C55_band, // Bit Field Comparison - -TMS320C55_bfxpa, // Bit Field Expand - -TMS320C55_bfxtr, // Bit Field Extract - -TMS320C55_btst, // Bit Test -TMS320C55_bnot, // Bit NOT -TMS320C55_bclr2, // Bit Clear -TMS320C55_bset2, // Bit Set -TMS320C55_btstset, // Bit Test and Set -TMS320C55_btstclr, // Bit Test and Clear -TMS320C55_btstnot, // Bit Test and NOT -TMS320C55_btstp, // Bit Pair Test -TMS320C55_bclr1, // Bit Clear -TMS320C55_bset1, // Bit Set - -TMS320C55_amar2, // Load Effective Address to Extended Auxiliary Register -TMS320C55_popboth, // Pop Extended Auxiliary Register from Stack Pointers -TMS320C55_pshboth, // Push Extended Auxiliary Register to Stack Pointers - -// LOGICAL OPERATIONS - -TMS320C55_bcnt, // Count Bit Field - -TMS320C55_not1, // NOT -TMS320C55_not2, // NOT - -TMS320C55_and1, // AND -TMS320C55_and2, // AND -TMS320C55_and3, // AND - -TMS320C55_or1, // OR -TMS320C55_or2, // OR -TMS320C55_or3, // OR - -TMS320C55_xor1, // XOR -TMS320C55_xor2, // XOR -TMS320C55_xor3, // XOR - -TMS320C55_sftl2, // Logical Shift -TMS320C55_sftl3, // Logical Shift - -TMS320C55_rol, // Rotate Left - -TMS320C55_ror, // Rotate Right - -// MISCELLANEOUS OPERATIONS - -// MOVE OPERATIONS - -TMS320C55_swap, // Swap Registers -TMS320C55_swapp, // Swap Pair Registers -TMS320C55_swap4, // Swap 4 Registers - -TMS320C55_mov2, // Move Data -TMS320C55_mov3, // Move 2 Data -TMS320C55_mov402, // Move Data on 40 bits - -TMS320C55_delay, // Memory Delay - -TMS320C55_pop1, // Pop Top of Stack1 -TMS320C55_pop2, // Pop Top of Stack2 - -TMS320C55_psh1, // Pop Top of Stack3 -TMS320C55_psh2, // Pop Top of Stack4 - -// PROGRAM CONTROL OPERATIONS - -TMS320C55_bcc, // Branch Conditionally -TMS320C55_bccu, // Branch Conditionally - -TMS320C55_b, // Branch Unconditionally - -TMS320C55_callcc, // Call Conditionally - -TMS320C55_call, // Call Unconditionally - -TMS320C55_xcc, // Execute Conditionally -TMS320C55_xccpart, // Execute Conditionally - -TMS320C55_idle, // Idle - -TMS320C55_nop, // No Operation -TMS320C55_nop_16, // No Operation - -TMS320C55_rptblocal, // Repeat Block of Instructions Unconditionally -TMS320C55_rptb, // Repeat Block of Instructions Unconditionally - -TMS320C55_rptcc, // Repeat Single Instruction Conditionally - -TMS320C55_rpt, // Repeat Single Instruction Unconditionally -TMS320C55_rptadd, // Repeat Single Instruction Unconditionally and Add to Register -TMS320C55_rptsub, // Repeat Single Instruction Unconditionally and Subtract to Register - -TMS320C55_retcc, // Return Conditionally -TMS320C55_ret, // Return Unconditionally -TMS320C55_reti, // Return from Interrupt - -TMS320C55_intr, // Software Interrupt - -TMS320C55_reset, // Software Reset - -TMS320C55_trap, // Software Trap - -TMS320C55_last - -}; - -#endif diff --git a/idasdk75/module/tms320c55/makefile b/idasdk75/module/tms320c55/makefile deleted file mode 100644 index 5e3e960..0000000 --- a/idasdk75/module/tms320c55/makefile +++ /dev/null @@ -1,49 +0,0 @@ -PROC=tms32055 -CONFIGS=tms320c55.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp ins.hpp tms320c55.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp \ - tms320c55.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.cpp ins.hpp tms320c55.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)struct.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ins.hpp out.cpp tms320c55.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ - ../idaidp.hpp ../iohandler.hpp ins.hpp reg.cpp \ - tms320c55.hpp diff --git a/idasdk75/module/tms320c55/reg.cpp b/idasdk75/module/tms320c55/reg.cpp deleted file mode 100644 index 5ee6435..0000000 --- a/idasdk75/module/tms320c55/reg.cpp +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#include <ctype.h> -#include "tms320c55.hpp" -#include <diskio.hpp> -#include <segregs.hpp> -#include <ieee.h> -static int data_id; - -//-------------------------------------------------------------------------- -static const char *const register_names[] = -{ - "AC0", // Accumulator - "AC1", // Accumulator - "AC2", // Accumulator - "AC3", // Accumulator - "T0", // Temporary register - "T1", // Temporary register - "T2", // Temporary register - "T3", // Temporary register - "AR0", // Auxiliary register - "AR1", // Auxiliary register - "AR2", // Auxiliary register - "AR3", // Auxiliary register - "AR4", // Auxiliary register - "AR5", // Auxiliary register - "AR6", // Auxiliary register - "AR7", // Auxiliary register - - "AC0L", // Accumulator - "AC0H", // Accumulator - "AC0G", // Accumulator - "AC1L", // Accumulator - "AC1H", // Accumulator - "AC1G", // Accumulator - "AC2L", // Accumulator - "AC2H", // Accumulator - "AC2G", // Accumulator - "AC3L", // Accumulator - "AC3H", // Accumulator - "AC3G", // Accumulator - "BK03", // Circular buffer size register - "BK47", // Circular buffer size register - "BKC", // Circular buffer size register - "BRC0", // Block-repeat counter - "BRC1", // Block-repeat counter - "BRS1", // BRC1 save register - "BSA01", // Circulat buffer start address register - "BSA23", // Circulat buffer start address register - "BSA45", // Circulat buffer start address register - "BSA67", // Circulat buffer start address register - "BSAC", // Circulat buffer start address register - "CDP", // Coefficient data pointer (low part of XCDP) - "CDPH", // High part of XCDP - "CFCT", // Control-flow contect register - "CSR", // Computed single-repeat register - "DBIER0", // Debug interrupt enable register - "DBIER1", // Debug interrupt enable register - // DP Data page register (low part of XDP) - // DPH High part of XDP - "IER0", // Interrupt enable register - "IER1", // Interrupt enable register - "IFR0", // Interrupt flag register - "IFR1", // Interrupt flag register - "IVPD", - "IVPH", - "PC", // Program counter - // PDP Peripheral data page register - "PMST", - "REA0", // Block-repeat end address register - "REA0L", // Block-repeat end address register - "REA0H", // Block-repeat end address register - "REA1", // Block-repeat end address register - "REA1L", // Block-repeat end address register - "REA1H", // Block-repeat end address register - "RETA", // Return address register - "RPTC", // Single-repeat counter - "RSA0", // Block-repeat start address register - "RSA0L", // Block-repeat start address register - "RSA0H", // Block-repeat start address register - "RSA1", // Block-repeat start address register - "RSA1L", // Block-repeat start address register - "RSA1H", // Block-repeat start address register - "SP", // Data stack pointer - "SPH", // High part of XSP and XSSP - "SSP", // System stack pointer - "ST0", // Status register - "ST1", // Status register - "ST0_55", // Status register - "ST1_55", // Status register - "ST2_55", // Status register - "ST3_55", // Status register - "TRN0", // Transition register - "TRN1", // Transition register - - "XAR0", // Extended auxiliary register - "XAR1", // Extended auxiliary register - "XAR2", // Extended auxiliary register - "XAR3", // Extended auxiliary register - "XAR4", // Extended auxiliary register - "XAR5", // Extended auxiliary register - "XAR6", // Extended auxiliary register - "XAR7", // Extended auxiliary register - - "XCDP", // Extended coefficient data pointer - "XDP", // Extended data page register - "XPC", // Extended program counter - "XSP", // Extended data stack pointer - "XSSP", // Extended system stack pointer - - "MDP", // Main Data page pointer (direct memory access / indirect from CDP) - "MDP05", // Main Data page pointer (indirect AR[0-5]) - "MDP67", // Main Data page pointer (indirect AR[6-7]) - - // flags - "ACOV2", - "ACOV3", - "TC1", - "TC2", - "CARRY", - "ACOV0", - "ACOV1", - "BRAF", - "XF", - "HM", - "INTM", - "M40", - "SATD", - "SXMD", - "C16", - "FRCT", - "C54CM", - "DBGM", - "EALLOW", - "RDM", - "CDPLC", - "AR7LC", - "AR6LC", - "AR5LC", - "AR4LC", - "AR3LC", - "AR2LC", - "AR1LC", - "AR0LC", - "CAFRZ", - "CAEN", - "CACLR", - "HINT", - "CBERR", - "MPNMC", - "SATA", - "CLKOFF", - "SMUL", - "SST", - - "BORROW", - - // segment registers - "ARMS", // AR indirect operands available - "CPL", // Compiler mode - "DP", // Data page pointer - "DPH", // Data page - "PDP", // Peripheral data page register - "cs","ds" // virtual registers for code and data segments -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_0[] = { 0x48, 0x04 }; // ret -static const uchar retcode_1[] = { 0x48, 0x05 }; // reti - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_0), retcode_0 }, - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// TMS320C55 ASM -//----------------------------------------------------------------------- -static const asm_t masm55 = -{ - AS_COLON|AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP, - 0, - "MASM55", - 0, - NULL, // header lines - NULL, // org - ".end", // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".pstring", // ascii string directive - "MY_BYTE", // byte directive - ".word", // word directive - ".long", // double words - NULL, // qwords - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".space 8*%s",// uninited arrays - ".asg", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".global", // "public" name keyword - NULL, // "weak" name keyword - ".ref", // "extrn" name keyword - NULL, // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof - AS2_STRINV // invert string byte order -}; - -static const asm_t *const asms[] = { &masm55, NULL }; - -//-------------------------------------------------------------------------- -static const char *const cfgname = "tms320c55.cfg"; - -void tms320c55_t::load_symbols(void) -{ - ioh.ports.clear(); - read_ioports(&ioh.ports, &ioh.device, cfgname); -} - -const char *tms320c55_t::find_sym(ea_t address) -{ - const ioport_t *port = find_ioport(ioh.ports, address); - return port ? port->name.c_str() : NULL; -} - -//-------------------------------------------------------------------------- -void tms320c55_t::set_device_name(const char *dev) -{ - if ( dev != NULL ) - ioh.device = dev; -} - -//-------------------------------------------------------------------------- -static int idaapi choose_device(int, form_actions_t &fa) -{ - tms320c55_t &pm = *(tms320c55_t *)fa.get_ud(); - if ( choose_ioport_device(&pm.ioh.device, cfgname) ) - pm.load_symbols(); - return 0; -} - -//-------------------------------------------------------------------------- -const char *tms320c55_t::set_idp_options( - const char *keyword, - int value_type, - const void *value, - bool idb_loaded) -{ - if ( keyword == NULL ) - { - static const char form[] = - "HELP\n" - "TMS320C55 specific options\n" - "\n" - " Use I/O definitions \n" - "\n" - " If this option is on, IDA will use I/O definitions\n" - " from the configuration file into a macro instruction.\n" - "\n" - " Detect memory mapped registers \n" - "\n" - " If this option is on, IDA will replace addresses\n" - " by an equivalent memory mapped register.\n" - "\n" - "ENDHELP\n" - "TMS320C54 specific options\n" - "%*\n" - " <Use ~I~/O definitions:C>\n" - " <Detect memory mapped ~r~egisters:C>>\n" - "\n" - " <~C~hoose device name:B:0::>\n" - "\n" - "\n"; - CASSERT(sizeof(idpflags) == sizeof(ushort)); - ask_form(form, this, &idpflags, choose_device); - } - else - { - if ( value_type != IDPOPT_BIT ) - return IDPOPT_BADTYPE; - if ( strcmp(keyword, "TMS320C55_IO") == 0 ) - { - setflag(idpflags, TMS320C55_IO, *(int*)value != 0); - } - else if ( strcmp(keyword, "TMS320C55_MMR") == 0 ) - { - setflag(idpflags, TMS320C55_MMR, *(int*)value != 0); - } - else - { - return IDPOPT_BADKEY; - } - } - if ( idb_loaded ) - helper.altset(-1, idpflags); - return IDPOPT_OK; -} - -//-------------------------------------------------------------------------- -static const proctype_t ptypes[] = -{ - TMS320C55 -}; - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list /*va*/) -{ - switch ( code ) - { - case idb_event::closebase: - case idb_event::savebase: - pm.helper.altset(-1, pm.idpflags); - pm.helper.supset(0, pm.ioh.device.c_str()); - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(SET_MODULE_DATA(tms320c55_t)); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi tms320c55_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - helper.create("$ tms320c54"); - if ( helper.supstr(&ioh.device, 0) > 0 ) - set_device_name(ioh.device.c_str()); - inf_set_be(true); // MSB first - break; - - case processor_t::ev_term: - ioh.ports.clear(); - unhook_event_listener(HT_IDB, &idb_listener); - clr_module_data(data_id); - break; - - case processor_t::ev_newfile: // new file loaded - { - { - set_default_sreg_value(NULL, ARMS, 0); - set_default_sreg_value(NULL, CPL, 1); - for ( int i = DP; i <= rVds; i++ ) - set_default_sreg_value(NULL, i, 0); - } - static const char *const informations = - "AUTOHIDE REGISTRY\n" - "Default values of flags and registers:\n" - "\n" - "ARMS bit = 0 (DSP mode operands).\n" - "CPL bit = 1 (SP direct addressing mode).\n" - "DP register = 0 (Data Page register)\n" - "DPH register = 0 (High part of EXTENDED Data Page Register)\n" - "PDP register = 0 (Peripheral Data Page register)\n" - "\n" - "You can change the register values by pressing Alt-G\n" - "(Edit, Segments, Change segment register value)\n"; - info(informations); - break; - } - - case processor_t::ev_ending_undo: - ptype = ptypes[ph.get_proc_index()]; - //fall through - case processor_t::ev_oldfile: // old file loaded - idpflags = (ushort)helper.altval(-1); - break; - - case processor_t::ev_newprc: // new processor type - { - ptype = ptypes[va_arg(va, int)]; - // bool keep_cfg = va_argi(va, bool); - switch ( ptype ) - { - case TMS320C55: - break; - default: - error("interr: setprc"); - } - ioh.device.qclear(); - load_symbols(); - } - break; - - case processor_t::ev_newasm: // new assembler type - break; - - case processor_t::ev_creating_segm: // new segment - break; - - case processor_t::ev_get_stkvar_scale_factor: - return 2; - - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_mnem(*ctx); - return 1; - } - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *op = va_arg(va, const op_t *); - return can_have_type(*op) ? 1 : -1; - } - - case processor_t::ev_create_func_frame: - { - func_t *pfn = va_arg(va, func_t *); - create_func_frame(pfn); - return 1; - } - - case processor_t::ev_gen_stkvar_def: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const member_t *mptr = va_arg(va, const member_t *); - sval_t v = va_arg(va, sval_t); - gen_stkvar_def(*ctx, mptr, v); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -#define FAMILY "TMS320C55x Series:" -static const char *const shnames[] = -{ "TMS32055", - NULL -}; -static const char *const lnames[] = -{ - FAMILY"Texas Instruments TMS320C55", - NULL -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_TMS320C55, // id - // flag - PRN_HEX - | PR_SEGS - | PR_SGROTHER - | PR_SCALE_STKVARS, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - register_names, // Register names - qnumber(register_names), // Number of registers - - ARMS, // first - rVds, // last - 1, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - TMS320C55_null, - TMS320C55_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0,7,15,19 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - TMS320C55_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/tms320c55/tms320c55.hpp b/idasdk75/module/tms320c55/tms320c55.hpp deleted file mode 100644 index d98e402..0000000 --- a/idasdk75/module/tms320c55/tms320c55.hpp +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-99 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@datarescue.com - * - * - */ - -#ifndef _TMS320C55_HPP -#define _TMS320C55_HPP - -#include "../idaidp.hpp" -#include <diskio.hpp> -#include "ins.hpp" -#include "../iohandler.hpp" - -// #define TMS320C55_NO_NAME_NO_REF - -//------------------------------------------------------------------ -enum regnum_t ENUM_SIZE(uint16) -{ - AC0, // Accumulator - AC1, // Accumulator - AC2, // Accumulator - AC3, // Accumulator - T0, // Temporary register - T1, // Temporary register - T2, // Temporary register - T3, // Temporary register - AR0, // Auxiliary register - AR1, // Auxiliary register - AR2, // Auxiliary register - AR3, // Auxiliary register - AR4, // Auxiliary register - AR5, // Auxiliary register - AR6, // Auxiliary register - AR7, // Auxiliary register - - AC0L, // Accumulator - AC0H, // Accumulator - AC0G, // Accumulator - AC1L, // Accumulator - AC1H, // Accumulator - AC1G, // Accumulator - AC2L, // Accumulator - AC2H, // Accumulator - AC2G, // Accumulator - AC3L, // Accumulator - AC3H, // Accumulator - AC3G, // Accumulator - BK03, // Circular buffer size register - BK47, // Circular buffer size register - BKC, // Circular buffer size register - BRC0, // Block-repeat counter - BRC1, // Block-repeat counter - BRS1, // BRC1 save register - BSA01, // Circulat buffer start address register - BSA23, // Circulat buffer start address register - BSA45, // Circulat buffer start address register - BSA67, // Circulat buffer start address register - BSAC, // Circulat buffer start address register - CDP, // Coefficient data pointer (low part of XCDP) - CDPH, // High part of XCDP - CFCT, // Control-flow contect register - CSR, // Computed single-repeat register - DBIER0, // Debug interrupt enable register - DBIER1, // Debug interrupt enable register - // DP Data page register (low part of XDP) - // DPH High part of XDP - IER0, // Interrupt enable register - IER1, // Interrupt enable register - IFR0, // Interrupt flag register - IFR1, // Interrupt flag register - IVPD, - IVPH, - PC, // Program counter - // PDP Peripheral data page register - PMST, - REA0, // Block-repeat end address register - REA0L, // Block-repeat end address register - REA0H, // Block-repeat end address register - REA1, // Block-repeat end address register - REA1L, // Block-repeat end address register - REA1H, // Block-repeat end address register - RETA, // Return address register - RPTC, // Single-repeat counter - RSA0, // Block-repeat start address register - RSA0L, // Block-repeat start address register - RSA0H, // Block-repeat start address register - RSA1, // Block-repeat start address register - RSA1L, // Block-repeat start address register - RSA1H, // Block-repeat start address register - SP, // Data stack pointer - SPH, // High part of XSP and XSSP - SSP, // System stack pointer - ST0, // Status register - ST1, // Status register - ST0_55, // Status register - ST1_55, // Status register - ST2_55, // Status register - ST3_55, // Status register - TRN0, // Transition register - TRN1, // Transition register - - XAR0, // Extended auxiliary register - XAR1, // Extended auxiliary register - XAR2, // Extended auxiliary register - XAR3, // Extended auxiliary register - XAR4, // Extended auxiliary register - XAR5, // Extended auxiliary register - XAR6, // Extended auxiliary register - XAR7, // Extended auxiliary register - - XCDP, // Extended coefficient data pointer - XDP, // Extended data page register - XPC, // Extended program counter - XSP, // Extended data stack pointer - XSSP, // Extended system stack pointer - - // these seem to be an old way of what is now DPH/CDPH/AR0H..AR7H - // i.e. supply bits 22:16 of the address for specific situations) - MDP, // Main Data page pointer (direct memory access / indirect from CDP) - MDP05, // Main Data page pointer (indirect AR[0-5]) - MDP67, // Main Data page pointer (indirect AR[6-7]) - - // flags - ACOV2, - ACOV3, - TC1, - TC2, - CARRY, - ACOV0, - ACOV1, - BRAF, - XF, - HM, - INTM, - M40, - SATD, - SXMD, - C16, - FRCT, - C54CM, - DBGM, - EALLOW, - RDM, - CDPLC, - AR7LC, - AR6LC, - AR5LC, - AR4LC, - AR3LC, - AR2LC, - AR1LC, - AR0LC, - CAFRZ, - CAEN, - CACLR, - HINT, - CBERR, - MPNMC, - SATA, - CLKOFF, - SMUL, - SST, - - BORROW, - - // segment registers - ARMS, // AR indirect operands available - CPL, // Compiler mode - DP, // Data page pointer - DPH, // Data page - PDP, // Peripheral data page register - rVcs, rVds, // virtual registers for code and data segments -}; - -//------------------------------------------------------------------ -// specific condition codes -#define COND_A 0x0 -#define COND_B 0x8 - -#define COND_GEQ 0x2 -#define COND_LT 0x3 -#define COND_NEQ 0x4 -#define COND_EQ 0x5 -#define COND_GT 0x6 -#define COND_LEQ 0x7 - - -#define COND4_AGEQ (COND_A | COND_GEQ) -#define COND4_ALT (COND_A | COND_LT) -#define COND4_ANEQ (COND_A | COND_NEQ) -#define COND4_AEQ (COND_A | COND_EQ) -#define COND4_AGT (COND_A | COND_GT) -#define COND4_ALEQ (COND_A | COND_LEQ) - -#define COND4_BGEQ (COND_B | COND_GEQ) -#define COND4_BLT (COND_B | COND_LT) -#define COND4_BNEQ (COND_B | COND_NEQ) -#define COND4_BEQ (COND_B | COND_EQ) -#define COND4_BGT (COND_B | COND_GT) -#define COND4_BLEQ (COND_B | COND_LEQ) - - -#define COND8_FROM_COND4 0x40 - -#define COND8_UNC 0x00 -#define COND8_NBIO 0x02 -#define COND8_BIO 0x03 -#define COND8_NC 0x08 -#define COND8_C 0x0C -#define COND8_NTC 0x20 -#define COND8_TC 0x30 -#define COND8_AGEQ (COND8_FROM_COND4 | COND4_AGEQ) -#define COND8_ALT (COND8_FROM_COND4 | COND4_ALT) -#define COND8_ANEQ (COND8_FROM_COND4 | COND4_ANEQ) -#define COND8_AEQ (COND8_FROM_COND4 | COND4_AEQ) -#define COND8_AGT (COND8_FROM_COND4 | COND4_AGT) -#define COND8_ALEQ (COND8_FROM_COND4 | COND4_ALEQ) -#define COND8_ANOV 0x60 -#define COND8_AOV 0x70 -#define COND8_BGEQ (COND8_FROM_COND4 | COND4_BGEQ) -#define COND8_BLT (COND8_FROM_COND4 | COND4_BLT) -#define COND8_BNEQ (COND8_FROM_COND4 | COND4_BNEQ) -#define COND8_BEQ (COND8_FROM_COND4 | COND4_BEQ) -#define COND8_BGT (COND8_FROM_COND4 | COND4_BGT) -#define COND8_BLEQ (COND8_FROM_COND4 | COND4_BLEQ) -#define COND8_BNOV (COND_B | COND8_ANOV) -#define COND8_BOV (COND_B | COND8_AOV) - -//------------------------------------------------------------------ -#define Parallel segpref // number of operands for the first line of a parallel instruction - #define TMS_PARALLEL_BIT -1 -#define SpecialModes auxpref_u8[0] - #define TMS_MODE_USER_PARALLEL 0x1 // user parallel bit (E) is set - #define TMS_MODE_LR 0x2 // LR postfix - #define TMS_MODE_CR 0x4 // CR postfix - #define TMS_MODE_SIMULATE_USER_PARALLEL 0x8 // the instruction simulate two instructions linked by a user parallelism -#define OpMem auxpref_u8[1] - -// complex operands - -// for o_reg, o_imm, o_mem -#define tms_shift specval_shorts.low // operand << value - #define TMS_OP_SHIFT_NULL 0 // no shift - #define TMS_OP_SHIFT_TYPE 0x7FFF - #define TMS_OP_SHIFTL_IMM 1 // operand << #... - #define TMS_OP_SHIFTL_REG 2 // operand << reg - #define TMS_OP_SHIFTR_IMM 3 // operand >> #... - #define TMS_OP_EQ 4 // operand == #... - #define TMS_OP_NEQ 5 // operand != #... - #define TMS_OP_SHIFT_OUT 0x8000 // functions(...) << ... (default = functions(... << ...)) - -#define tms_shift_value specval_shorts.high - -// for o_reg, o_mem -#define tms_modifier specflag2 - #define TMS_MODIFIER_NULL 0 - // o_reg - #define TMS_MODIFIER_REG 1 // *reg - #define TMS_MODIFIER_REG_P 2 // *reg+ - #define TMS_MODIFIER_REG_M 3 // *reg- - #define TMS_MODIFIER_REG_P_T0 4 // *(reg+T0) - #define TMS_MODIFIER_REG_P_T1 5 // *(reg+T1) - #define TMS_MODIFIER_REG_M_T0 6 // *(reg-T0) - #define TMS_MODIFIER_REG_M_T1 7 // *(reg-T1) - #define TMS_MODIFIER_REG_T0 8 // *reg(T0) - #define TMS_MODIFIER_REG_OFFSET 9 // *reg(#value) - #define TMS_MODIFIER_P_REG_OFFSET 10 // *+reg(#value) - #define TMS_MODIFIER_REG_SHORT_OFFSET 11 // *reg(short(#value)) - #define TMS_MODIFIER_REG_T1 12 // *reg(T1) - #define TMS_MODIFIER_P_REG 13 // *+reg - #define TMS_MODIFIER_M_REG 14 // *-reg - #define TMS_MODIFIER_REG_P_T0B 15 // *(reg+T0B) - #define TMS_MODIFIER_REG_M_T0B 16 // *(reg-T0B) - // o_mem, o_io - #define TMS_MODIFIER_DMA 1 // @addr - #define TMS_MODIFIER_ABS16 2 // *abs16(#addr) - #define TMS_MODIFIER_PTR 3 // *(#addr) - #define TMS_MODIFIER_MMAP 4 // mmap() - #define TMS_MODIFIER_PORT 5 // port(#addr) - #define TMS_MODIFIER_PORT_AT 6 // port(@addr) - -// for o_reg, o_mem, o_io -#define tms_operator1 specflag3 // operators sorted by priority order -#define tms_operator2 specflag4 - #define TMS_OPERATORS_SIZE 13 - #define TMS_OPERATOR_NULL 0x0000 - #define TMS_OPERATOR_T3 0x0001 // T3=xxx - #define TMS_OPERATOR_NOT 0x0002 // !xxx - #define TMS_OPERATOR_UNS 0x0004 // uns(xxx) - #define TMS_OPERATOR_DBL 0x0008 // dbl(xxx) - #define TMS_OPERATOR_RND 0x0010 // rnd(xxx) - #define TMS_OPERATOR_PAIR 0x0020 // pair(xxx) - #define TMS_OPERATOR_LO 0x0040 // lo(xxx) - #define TMS_OPERATOR_HI 0x0080 // hi(xxx) - #define TMS_OPERATOR_LB 0x0100 // low_byte(xxx) - #define TMS_OPERATOR_HB 0x0200 // high_byte(xxx) - #define TMS_OPERATOR_SAT 0x0400 // saturate(xxx) - #define TMS_OPERATOR_DUAL 0x0800 // dual(xxx) - #define TMS_OPERATOR_PORT 0x1000 // port(xxx) - -// for o_imm -#define tms_signed specflag1 -#define tms_prefix specflag2 - -// for o_mem (real address = tms_reg_h : tms_reg_p + addr) -#define tms_regH value_shorts.low -#define tms_regP value_shorts.high - -#define o_cond o_idpspec0 -#define o_shift o_idpspec1 -#define o_relop o_idpspec2 - #define tms_relop specflag1 // relational operator - #define tms_relop_type specflag2 // o_reg, o_imm - #define TMS_RELOP_REG 1 // operand << #... - #define TMS_RELOP_IMM 2 // operand << reg - // value will contain register or immediate -#define o_io o_idpspec3 - -//------------------------------------------------------------------ -// processor types - -typedef uchar proctype_t; - -const proctype_t TMS320C55 = 0; - -//------------------------------------------------------------------ -#define TAG_SDUAL '2' // helper.altval(ea, '2') == length of the first part of sdual instruction - -#define TMS320C55_IO 0x0001 // use I/O definitions -#define TMS320C55_MMR 0x0002 // use memory mapped registers - -//------------------------------------------------------------------ -struct tms320c55_iohandler_t : public iohandler_t -{ - struct tms320c55_t ± - qstring errbuf; - - tms320c55_iohandler_t(tms320c55_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} -}; - -DECLARE_PROC_LISTENER(idb_listener_t, struct tms320c55_t); - -struct mask_t; -class bytes_c; -struct tms320c55_t : public procmod_t -{ - netnode helper; - tms320c55_iohandler_t ioh = tms320c55_iohandler_t(*this, helper); - idb_listener_t idb_listener = idb_listener_t(*this); - ea_t dataseg; - ushort idpflags = TMS320C55_IO|TMS320C55_MMR; - proctype_t ptype = TMS320C55; // contains processor type - bool flow = false; - char optional_op = -1; // ana: index of an optional operand - - ssize_t idaapi on_event(ssize_t msgid, va_list va); - void load_symbols(void); - const char *find_sym(ea_t address); - void set_device_name(const char *dev); - const char *idaapi set_idp_options( - const char *keyword, - int value_type, - const void * value, - bool idb_loaded); - - int ana(insn_t *insn); - void process_masks( - insn_t &insn, - const mask_t *masks, - ushort itype_null, - bytes_c &bytes, - char lbytesize = 8); - bool process_masks_operand( - insn_t &insn, - const mask_t *mask, - int64 code, - int64 op_mask_n, - unsigned *p_opnum, - bool bTest); - - int emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &op, flags_t F, bool use); - int get_mapped_register(ea_t ea) const; - - void assumes(outctx_t &ctx); - void print_segment_register(outctx_t &ctx, int reg, sel_t value); - void segstart(outctx_t &ctx, segment_t *seg) const; - void footer(outctx_t &ctx) const; - void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; -}; - - -const char *find_sym(ea_t address); -//------------------------------------------------------------------ -void idaapi header(outctx_t &ctx); - -void idaapi segend(outctx_t &ctx, segment_t *seg); - -void idaapi data(outctx_t &ctx); - -bool idaapi create_func_frame(func_t *pfn); -int idaapi is_align_insn(ea_t ea); -bool idaapi can_have_type(const op_t &op); - -ea_t calc_io_mem(const insn_t &insn, const op_t &op); -ea_t calc_data_mem(const insn_t &insn, const op_t &op); -inline ea_t calc_code_mem(const insn_t &insn, ea_t ea) -{ - return to_ea(insn.cs, ea); -} - -#endif // _TMS320C55_HPP diff --git a/idasdk75/module/tms320c6/emu.cpp b/idasdk75/module/tms320c6/emu.cpp deleted file mode 100644 index f29e90c..0000000 --- a/idasdk75/module/tms320c6/emu.cpp +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - * - * TMS320C6xx - VLIW (very long instruction word) architecture - * - */ - -#include "tms6.hpp" - -//------------------------------------------------------------------------ -static void set_immd_bit(const insn_t &insn, int n, flags_t F) -{ - set_immd(insn.ea); - if ( is_defarg(F, n) ) - return; - switch ( insn.itype ) - { - case TMS6_mvk: - if ( is_mvk_scst16_form(insn.ea) ) - { - op_hex(insn.ea, n); - break; - } - // fallthrough for scst5 form - case TMS6_addk: - case TMS6_and: // Rd = Op1 & Op2 - case TMS6_xor: // Rd = Op1 ^ Op2 - case TMS6_or: // Rd = Op2 | Op1 - case TMS6_cmpeq: - case TMS6_cmpgt: - case TMS6_cmplt: - case TMS6_mpy: - case TMS6_mpyi: - case TMS6_mpyid: - case TMS6_mpysu: - case TMS6_sadd: - case TMS6_ssub: - case TMS6_sub: - case TMS6_set: // Rd = Op1 & ~Op2 - case TMS6_clr: // Rd = Op1 & ~Op2 - case TMS6_ext: // Rd = Op1 & ~Op2 - case TMS6_extu: // Rd = Op1 & ~Op2 - op_dec(insn.ea, n); - break; - } -} - -//---------------------------------------------------------------------- -static void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool isload) -{ - switch ( x.type ) - { - case o_regpair: - case o_reg: - case o_phrase: - case o_spmask: - case o_stgcyc: - break; - case o_imm: - if ( !isload ) - goto badTouch; - /* no break */ - case o_displ: - set_immd_bit(insn, x.n, F); - if ( op_adds_xrefs(F, x.n) ) - { - int outf = x.type != o_imm ? OOF_ADDR : 0; - if ( x.dtype == dt_word ) - outf |= OOF_SIGNED; - insn.add_off_drefs(x, dr_O, outf); - } - break; - case o_near: - { - ea_t ea = to_ea(insn.cs, x.addr); - ea_t ref = find_first_insn_in_packet(ea); - insn.add_cref(ref, x.offb, fl_JN); - } - break; - default: -badTouch: - INTERR(10380); - } -} - -//---------------------------------------------------------------------- -ea_t find_first_insn_in_packet(ea_t ea) -{ - if ( !is_spec_ea(ea) ) - { - while ( (ea & 0x1F) != 0 ) - { - ea_t ea2 = prev_not_tail(ea); - if ( ea2 == BADADDR - || !is_code(get_flags(ea2)) - || (get_dword(ea2) & BIT0) == 0 ) - { - break; - } - ea = ea2; - } - } - return ea; -} - -//---------------------------------------------------------------------- -inline bool is_tms6_nop(uint32 code) -{ - return (code & 0x21FFEL) == 0; -} - -//---------------------------------------------------------------------- -inline bool is_tms6_bnop(uint32 code) -{ - return (code & 0x00001FFC) == 0x00000120 // Branch Using a Displacement With NOP - || (code & 0x0F830FFE) == 0x00800362; // Branch Using a Register With NOP -} - -//---------------------------------------------------------------------- -static int get_delay(uint32 code) -{ - if ( is_tms6_nop(code) ) // NOP - return int((code >> 13) & 0xF) + 1; - if ( is_tms6_bnop(code) ) // BNOP - return int((code >> 13) & 0x7); - return 1; -} - -//---------------------------------------------------------------------- -struct call_info_t -{ - ea_t mvk; - ea_t mvkh; - uint32 next; - int reg; - call_info_t(ea_t n) : mvk(BADADDR), mvkh(BADADDR), next(n), reg(rB3) {} - bool call_is_present(void) const { return mvk != BADADDR && mvkh != BADADDR; } - void test(ea_t ea, uint32 code); -}; - -//---------------------------------------------------------------------- -inline ushort get_mvk_op(uint32 code) { return ushort(code >> 7); } - -void call_info_t::test(ea_t ea, uint32 code) -{ - if ( (code & 0xF000007CL) == 0x28 && mvk == BADADDR ) - { // unconditional MVK.S - int mvk_reg = int(code >> 23) & 0x1F; - if ( code & BIT1 ) - mvk_reg += rB0; - if ( (reg == -1 || reg == mvk_reg) && ushort(next) == get_mvk_op(code) ) - { - reg = mvk_reg; - mvk = ea; - } - } - else if ( (code & 0xF000007CL) == 0x68 && mvkh == BADADDR ) - { // unconditional MVKH.S - int mvk_reg = int(code >> 23) & 0x1F; - if ( code & BIT1 ) - mvk_reg += rB0; - if ( (reg == -1 || reg == mvk_reg) && ushort(next>>16) == get_mvk_op(code) ) - { - reg = mvk_reg; - mvkh = ea; - } - } -} - -//---------------------------------------------------------------------- -static int calc_packet_delay(ea_t ea, call_info_t *ci) -{ - int delay = 1; - while ( true ) - { - uint32 code = get_dword(ea); - int d2 = get_delay(code); - if ( d2 > delay ) - delay = d2; - ci->test(ea, code); - if ( (code & BIT0) == 0 ) - break; - ea += 4; - if ( !is_code(get_flags(ea)) ) - break; - } - return delay; -} - -//---------------------------------------------------------------------- -static ea_t find_prev_packet(ea_t ea) -{ - ea_t res = BADADDR; - while ( 1 ) - { - ea_t ea2 = prev_not_tail(res != BADADDR ? res : ea); - if ( ea2 == BADADDR ) - break; - if ( !is_code(get_flags(ea2)) ) - break; - res = ea2; - if ( (get_dword(ea2) & BIT0) == 0 ) - break; - } - return res; -} - -//---------------------------------------------------------------------- -static ea_t get_branch_ea(ea_t ea) -{ - while ( 1 ) - { - uint32 code = get_dword(ea); - if ( (code >> 28) == cAL ) - { - switch ( (code >> 2) & 0x1F ) - { - case 0x04: // bcond() - return ea; - case 0x08: // S unit - case 0x18: - { - int opcode = int(code >> 6) & 0x3F; - switch ( opcode ) - { - case 0: // bdec/bpos - case 3: // b irp - case 4: // bnop - case 13: // b - return ea; - } - } - break; - } - } - if ( (code & BIT0) == 0 ) - break; - ea += 4; - if ( !is_code(get_flags(ea)) ) - break; - } - return BADADDR; -} - -//---------------------------------------------------------------------- -int tms6_t::emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - flow = ((Feature & CF_STOP) == 0); - - if ( segtype(insn.ea) == SEG_XTRN ) - { - flow = false; - } - else if ( (insn.cflags & aux_para) == 0 ) // the last instruction of packet - { - // From spru732j.pdf: - // Although branch instructions take one execute phase, there are five - // delay slots between the execution of the branch and execution of the - // target code. - - // We look backwards for five delay slots to check for an unconditionnal - // branch instruction. - - ea_t ea = find_first_insn_in_packet(insn.ea); - int delay = 0; - call_info_t ci(insn.ea+insn.size); - while ( 1 ) - { - // If there are any crefs to this address, we cannot guarantee that - // the branch instruction really got executed. - if ( has_xref(get_flags(ea)) ) - break; - - // Increment delay count for this packet. - delay += calc_packet_delay(ea, &ci); - if ( delay > 5 ) - break; - - // Unless we have a bnop instruction, seek to the previous packet. - bool is_bnop = is_tms6_bnop(get_dword(ea)); - if ( !is_bnop ) - { - ea = find_prev_packet(ea); - if ( ea == BADADDR ) - break; - ea = find_first_insn_in_packet(ea); - } - - ea_t brea; - if ( delay == 5 && (brea=get_branch_ea(ea)) != BADADDR ) - { - // We seeked to the previous packet and it was a bnop. The check - // for delay == 5 is no longer correct, since we did not take into - // account the delays of the bnop instruction itself. - if ( is_tms6_bnop(get_dword(ea)) && !is_bnop ) - break; - - insn_t brins; - calc_packet_delay(ea, &ci); // just to test for MVK/MVKH - bool iscall = ci.call_is_present(); - decode_insn(&brins, brea); - nodeidx_t ndx2; - if ( brins.Op1.type == o_near ) - { - ea_t target = to_ea(brins.cs, brins.Op1.addr); - if ( iscall ) - { - target = find_first_insn_in_packet(target); - brins.add_cref(target, brins.Op1.offb, fl_CN); - if ( !func_does_return(target) ) - flow = false; - } - else - { - flow = false; - target++; - } - ndx2 = ea2node(target); - } - else - { - ndx2 = iscall ? 2 : 1; - if ( !iscall ) - flow = false; - } - tnode.altset_ea(insn.ea, ndx2); - if ( iscall ) - { - if ( !is_off0(get_flags(ci.mvk)) ) - op_offset(ci.mvk, 0, REF_LOW16, ci.next, brins.cs, 0); - if ( !is_off0(get_flags(ci.mvkh)) ) - op_offset(ci.mvkh, 0, REF_HIGH16, ci.next, brins.cs, 0); - } - break; - } - - // We don't check past one bnop instruction. - if ( is_bnop ) - break; - } - } - - flags_t F = get_flags(insn.ea); - if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, F, true); - if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, F, true); - if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, F, true); - - if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, F, false); - if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, F, false); - if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, F, false); - - if ( flow ) - add_cref(insn.ea, insn.ea + insn.size, fl_F); - return 1; -} - -//---------------------------------------------------------------------- -int idaapi is_align_insn(ea_t ea) -{ - insn_t insn; - decode_insn(&insn, ea); - switch ( insn.itype ) - { - case TMS6_mv: - if ( insn.Op1.reg == insn.Op2.reg ) - break; - default: - return 0; - case TMS6_nop: - break; - } - return insn.size; -} diff --git a/idasdk75/module/tms320c6/ins.hpp b/idasdk75/module/tms320c6/ins.hpp deleted file mode 100644 index de1e0a4..0000000 --- a/idasdk75/module/tms320c6/ins.hpp +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - * TMS320C6xx - VLIW (very long instruction word) architecture - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ -// Original TMS320C62x instructions - -TMS6_null = 0, // Unknown Operation -TMS6_abs, // Absolute value -TMS6_add, // Integer addition without saturation (signed) -TMS6_addu, // Integer addition without saturation (unsigned) -TMS6_addab, // Integer addition using addressing mode (byte) -TMS6_addah, // Integer addition using addressing mode (halfword) -TMS6_addaw, // Integer addition using addressing mode (word) -TMS6_addk, // Integer addition 16bit signed constant -TMS6_add2, // Two 16bit Integer adds on register halves -TMS6_and, // Logical AND -TMS6_b, // Branch -TMS6_clr, // Clear a bit field -TMS6_cmpeq, // Compare for equality -TMS6_cmpgt, // Compare for greater than (signed) -TMS6_cmpgtu, // Compare for greater than (unsigned) -TMS6_cmplt, // Compare for less than (signed) -TMS6_cmpltu, // Compare for less than (unsigned) -TMS6_ext, // Extract and sign-extend a bit filed -TMS6_extu, // Extract an unsigned bit field -TMS6_idle, // Multicycle NOP with no termination until interrupt -TMS6_ldb, // Load from memory (signed 8bit) -TMS6_ldbu, // Load from memory (unsigned 8bit) -TMS6_ldh, // Load from memory (signed 16bit) -TMS6_ldhu, // Load from memory (unsigned 16bit) -TMS6_ldw, // Load from memory (32bit) -TMS6_lmbd, // Leftmost bit detection -TMS6_mpy, // Signed Integer Multiply (LSB16 x LSB16) -TMS6_mpyu, // Unsigned Integer Multiply (LSB16 x LSB16) -TMS6_mpyus, // Integer Multiply Signed*Unsigned (LSB16 x LSB16) -TMS6_mpysu, // Integer Multiply Unsigned*Signed (LSB16 x LSB16) -TMS6_mpyh, // Signed Integer Multiply (MSB16 x MSB16) -TMS6_mpyhu, // Unsigned Integer Multiply (MSB16 x MSB16) -TMS6_mpyhus, // Integer Multiply Unsigned*Signed (MSB16 x MSB16) -TMS6_mpyhsu, // Integer Multiply Signed*Unsigned (MSB16 x MSB16) -TMS6_mpyhl, // Signed Integer Multiply (MSB16 x LSB16) -TMS6_mpyhlu, // Unsigned Integer Multiply (MSB16 x LSB16) -TMS6_mpyhuls, // Integer Multiply Signed*Unsigned (MSB16 x LSB16) -TMS6_mpyhslu, // Integer Multiply Unsigned*Signed (MSB16 x LSB16) -TMS6_mpylh, // Signed Integer Multiply (LSB16 x MB16) -TMS6_mpylhu, // Unsigned Integer Multiply (LSB16 x MSB16) -TMS6_mpyluhs, // Integer Multiply Signed*Unsigned (LSB16 x MSB16) -TMS6_mpylshu, // Integer Multiply Unsigned*Signed (LSB16 x MSB16) -TMS6_mv, // Move from register to register -TMS6_mvc, // Move between the control file & register file -TMS6_mvk, // Move a 16bit signed constant into register -TMS6_mvkh, // Move a 16bit constant into the upper bits of a register -TMS6_mvklh, // Move a 16bit constant into the upper bits of a register -TMS6_neg, // Negate -TMS6_nop, // No operation -TMS6_norm, // Normalize -TMS6_not, // Bitwise NOT -TMS6_or, // Logical or -TMS6_sadd, // Integer addition with saturation -TMS6_sat, // Saturate 40bit value to 32bits -TMS6_set, // Set a bit field -TMS6_shl, // Arithmetic shift left -TMS6_shr, // Arithmetic shift right -TMS6_shru, // Logical shift left -TMS6_smpy, // Integer multiply with left shift & saturation (LSB16*LSB16) -TMS6_smpyhl, // Integer multiply with left shift & saturation (MSB16*LSB16) -TMS6_smpylh, // Integer multiply with left shift & saturation (LSB16*MSB16) -TMS6_smpyh, // Integer multiply with left shift & saturation (MSB16*MSB16) -TMS6_sshl, // Shift left with saturation -TMS6_ssub, // Integer substraction with saturation -TMS6_stb, // Store to memory (signed 8bit) -TMS6_stbu, // Store to memory (unsigned 8bit) -TMS6_sth, // Store to memory (signed 16bit) -TMS6_sthu, // Store to memory (unsigned 16bit) -TMS6_stw, // Store to memory (32bit) -TMS6_sub, // Integer substaraction without saturation (signed) -TMS6_subu, // Integer substaraction without saturation (unsigned) -TMS6_subab, // Integer subtraction using addressing mode (byte) -TMS6_subah, // Integer subtraction using addressing mode (halfword) -TMS6_subaw, // Integer subtraction using addressing mode (word) -TMS6_subc, // Conditional subtract & shift (for division) -TMS6_sub2, // Two 16bit integer subtractions on register halves -TMS6_xor, // Exclusive OR -TMS6_zero, // Zero a register - -// New TMS320C674x instructions - -TMS6_abs2, // Absolute Value With Saturation, Signed, Packed 16-bit -TMS6_absdp, // Absolute Value, Double-Precision Floating-Point -TMS6_abssp, // Absolute Value, Single-Precision Floating-Point -TMS6_add4, // Add Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_addad, // Add Using Doubleword Addressing Mode -TMS6_adddp, // Add Two Double-Precision Floating-Point Values -TMS6_addkpc, // Add Signed 7-bit Constant to Program Counter -TMS6_addsp, // Add Two Single-Precision Floating-Point Values -TMS6_addsub, // Parallel ADD and SUB Operations On Common Inputs -TMS6_addsub2, // Parallel ADD2 and SUB2 Operations On Common Inputs -TMS6_andn, // Bitwise AND Invert -TMS6_avg2, // Average, Signed, Packed 16-bit -TMS6_avgu4, // Average, Unsigned, Packed 16-bit -TMS6_bdec, // Branch and Decrement -TMS6_bitc4, // Bit Count, Packed 8-bit -TMS6_bitr, // Bit Reverse -TMS6_bnop, // Branch With NOP -TMS6_bpos, // Branch Positive -TMS6_callp, // Call Using a Displacement -TMS6_cmpeq2, // Compare for Equality, Packed 16-bit -TMS6_cmpeq4, // Compare for Equality, Packed 8-bit -TMS6_cmpeqdp, // Compare for Equality, Double-Precision Floating-Point Values -TMS6_cmpeqsp, // Compare for Equality, Single-Precision Floating-Point Values -TMS6_cmpgt2, // Compare for Greater Than, Packed 16-bit -TMS6_cmpgtdp, // Compare for Greater Than, Double-Precision Floating-Point Values -TMS6_cmpgtsp, // Compare for Greater Than, Single-Precision Floating-Point Values -TMS6_cmpgtu4, // Compare for Greater Than, Unsigned, Packed 8-bit -TMS6_cmplt2, // Compare for Less Than, Packed 16-bit -TMS6_cmpltdp, // Compare for Less Than, Double-Precision Floating-Point Values -TMS6_cmpltsp, // Compare for Less Than, Single-Precision Floating-Point Values -TMS6_cmpltu4, // Compare for Less Than, Unsigned, Packed 8-bit -TMS6_cmpy, // Complex Multiply Two Pairs, Signed, Packed 16-bit -TMS6_cmpyr, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding -TMS6_cmpyr1, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding -TMS6_ddotp4, // Double Dot Product, Signed, Packed 16-Bit and Signed, Packed 8-Bit -TMS6_ddotph2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit -TMS6_ddotph2r, // Double Dot Product With Rounding, Two Pairs, Signed, Packed 16-Bit -TMS6_ddotpl2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit -TMS6_ddotpl2r, // Double Dot Product With Rounding, Two Pairs, Signed Packed 16-Bit -TMS6_deal, // Deinterleave and Pack -TMS6_dint, // Disable Interrupts and Save Previous Enable State -TMS6_dmv, // Move Two Independent Registers to Register Pair -TMS6_dotp2, // Dot Product, Signed, Packed 16-Bit -TMS6_dotpn2, // Dot Product With Negate, Signed, Packed 16-Bit -TMS6_dotpnrsu2, // Dot Product With Negate, Shift and Round, Signed by Unsigned, Packed 16-Bit -TMS6_dotpnrus2, // Dot Product With Negate, Shift and Round, Unsigned by Signed, Packed 16-Bit -TMS6_dotprsu2, // Dot Product With Shift and Round, Signed by Unsigned, Packed 16-Bit -TMS6_dotprus2, // Dot Product With Shift and Round, Unsigned by Signed, Packed 16-Bit -TMS6_dotpsu4, // Dot Product, Signed by Unsigned, Packed 8-Bit -TMS6_dotpu4, // Dot Product, Unsigned, Packed 8-Bit -TMS6_dotpus4, // Dot Product, Unsigned by Signed, Packed 8-Bit -TMS6_dpack2, // Parallel PACK2 and PACKH2 Operations -TMS6_dpackx2, // Parallel PACKLH2 Operations -TMS6_dpint, // Convert Double-Precision Floating-Point Value to Integer -TMS6_dpsp, // Convert Double-Precision Floating-Point Value to Single-Precision Floating-Point Value -TMS6_dptrunc, // Convert Double-Precision Floating-Point Value to Integer With Truncation -TMS6_gmpy, // Galois Field Multiply -TMS6_gmpy4, // Galois Field Multiply, Packed 8-Bit -TMS6_intdp, // Convert Signed Integer to Double-Precision Floating-Point Value -TMS6_intdpu, // Convert Unsigned Integer to Double-Precision Floating-Point Value -TMS6_intsp, // Convert Signed Integer to Single-Precision Floating-Point Value -TMS6_intspu, // Convert Unsigned Integer to Single-Precision Floating-Point Value -TMS6_lddw, // Load Doubleword From Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_ldndw, // Load Nonaligned Doubleword From Memory With Constant or Register Offset -TMS6_ldnw, // Load Nonaligned Word From Memory With Constant or Register Offset -TMS6_max2, // Maximum, Signed, Packed 16-Bit -TMS6_maxu4, // Maximum, Unsigned, Packed 8-Bit -TMS6_min2, // Minimum, Signed, Packed 16-Bit -TMS6_minu4, // Minimum, Unsigned, Packed 8-Bit -TMS6_mpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB -TMS6_mpy2ir, // Multiply Two 16-Bit x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 32-Bit Result -TMS6_mpy32su, // Multiply Signed 32-Bit x Unsigned 32-Bit Into Signed 64-Bit Result -TMS6_mpy32u, // Multiply Unsigned 32-Bit x Unsigned 32-Bit Into Unsigned 64-Bit Result -TMS6_mpy32us, // Multiply Unsigned 32-Bit x Signed 32-Bit Into Signed 64-Bit Result -TMS6_mpydp, // Multiply Two Double-Precision Floating-Point Values -TMS6_mpyhi, // Multiply 16 MSB x 32-Bit Into 64-Bit Result -TMS6_mpyhir, // Multiply 16 MSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpyi, // Multiply 32-Bit x 32-Bit Into 32-Bit Result -TMS6_mpyid, // Multiply 32-Bit x 32-Bit Into 64-Bit Result -TMS6_mpyih, // Multiply 32-Bit x 16-MSB Into 64-Bit Result -TMS6_mpyihr, // Multiply 32-Bit x 16 MSB, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpyil, // Multiply 32-Bit x 16 LSB Into 64-Bit Result -TMS6_mpyilr, // Multiply 32-Bit x 16 LSB, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpyli, // Multiply 16 LSB x 32-Bit Into 64-Bit Result -TMS6_mpylir, // Multiply 16 LSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result -TMS6_mpysp, // Multiply Two Single-Precision Floating-Point Values -TMS6_mpysp2dp, // Multiply Two Single-Precision Floating-Point Values for Double-Precision Result -TMS6_mpyspdp, // Multiply Single-Precision Floating-Point Value x Double-Precision Floating-Point Value -TMS6_mpysu4, // Multiply Signed x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_mpyu4, // Multiply Unsigned x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_mpyus4, // Multiply Unsigned x Signed, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_mvd, // Move From Register to Register, Delayed -TMS6_mvkl, // Move Signed Constant Into Register and Sign Extend -TMS6_pack2, // Pack Two 16 LSBs Into Upper and Lower Register Halves -TMS6_packh2, // Pack Two 16 MSBs Into Upper and Lower Register Halves -TMS6_packh4, // Pack Four High Bytes Into Four 8-Bit Halfwords -TMS6_packhl2, // Pack 16 MSB Into Upper and 16 LSB Into Lower Register Halves -TMS6_packl4, // Pack Four Low Bytes Into Four 8-Bit Halfwords -TMS6_packlh2, // Pack 16 LSB Into Upper and 16 MSB Into Lower Register Halves -TMS6_rcpdp, // Double-Precision Floating-Point Reciprocal Approximation -TMS6_rcpsp, // Single-Precision Floating-Point Reciprocal Approximation -TMS6_rint, // Restore Previous Enable State -TMS6_rotl, // Rotate Left -TMS6_rpack2, // Shift With Saturation and Pack Two 16 MSBs Into Upper and Lower Register Halves -TMS6_rsqrdp, // Double-Precision Floating-Point Square-Root Reciprocal Approximation -TMS6_rsqrsp, // Single-Precision Floating-Point Square-Root Reciprocal Approximation -TMS6_sadd2, // Add Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation -TMS6_saddsu2, // Add Two Signed and Unsigned 16-Bit Integers on Register Halves With Saturation -TMS6_saddsub, // Parallel SADD and SSUB Operations On Common Inputs -TMS6_saddsub2, // Parallel SADD2 and SSUB2 Operations On Common Inputs -TMS6_saddu4, // Add With Saturation, Four Unsigned 8-Bit Pairs for Four 8-Bit Results -TMS6_saddus2, // Add Two Unsigned and Signed 16-Bit Integers on Register Halves With Saturation -TMS6_shfl, // Shuffle -TMS6_shfl3, // 3-Way Bit Interleave On Three 16-Bit Values Into a 48-Bit Result -TMS6_shlmb, // Shift Left and Merge Byte -TMS6_shr2, // Arithmetic Shift Right, Signed, Packed 16-Bit -TMS6_shrmb, // Shift Right and Merge Byte -TMS6_shru2, // Arithmetic Shift Right, Unsigned, Packed 16-Bit -TMS6_smpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB With Left Shift and Saturation -TMS6_smpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 64-Bit Result With Left Shift and Saturation -TMS6_spack2, // Saturate and Pack Two 16 LSBs Into Upper and Lower Register Halves -TMS6_spacku4, // Saturate and Pack Four Signed 16-Bit Integers Into Four Unsigned 8-Bit Halfwords -TMS6_spdp, // Convert Single-Precision Floating-Point Value to Double-Precision Floating-Point Value -TMS6_spint, // Convert Single-Precision Floating-Point Value to Integer -TMS6_spkernel, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary -TMS6_spkernelr, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary -TMS6_sploop, // Software Pipelined Loop (SPLOOP) Buffer Operation -TMS6_sploopd, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing -TMS6_sploopw, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing and No Epilog -TMS6_spmask, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control -TMS6_spmaskr, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control -TMS6_sptrunc, // Convert Single-Precision Floating-Point Value to Integer With Truncation -TMS6_sshvl, // Variable Shift Left -TMS6_sshvr, // Variable Shift Right -TMS6_ssub2, // Subtract Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation -TMS6_stdw, // Store Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_stndw, // Store Nonaligned Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_stnw, // Store Nonaligned Word to Memory With a 5-Bit Unsigned Constant Offset or Register Offset -TMS6_sub4, // Subtract Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_subabs4, // Subtract With Absolute Value, Four 8-Bit Pairs for Four 8-Bit Results -TMS6_subdp, // Subtract Two Double-Precision Floating-Point Values -TMS6_subsp, // Subtract Two Single-Precision Floating-Point Values -TMS6_swap2, // Swap Bytes in Upper and Lower Register Halves -TMS6_swap4, // Swap Byte Pairs in Upper and Lower Register Halves -TMS6_swe, // Software Exception -TMS6_swenr, // Software Exception, no Return -TMS6_unpkhu4, // Unpack 16 MSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves -TMS6_unpklu4, // Unpack 16 LSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves -TMS6_xormpy, // Galois Field Multiply With Zero Polynomial -TMS6_xpnd2, // Expand Bits to Packed 16-Bit Masks -TMS6_xpnd4, // Expand Bits to Packed 8-Bit Masks - -TMS6_last, - - }; - -#endif diff --git a/idasdk75/module/tms320c6/makefile b/idasdk75/module/tms320c6/makefile deleted file mode 100644 index 3d47ee8..0000000 --- a/idasdk75/module/tms320c6/makefile +++ /dev/null @@ -1,40 +0,0 @@ -PROC=tms320c6 - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp ins.hpp tms6.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp ins.hpp tms6.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.cpp ins.hpp tms6.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp out.cpp tms6.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp reg.cpp tms6.hpp diff --git a/idasdk75/module/tms320c6/out.cpp b/idasdk75/module/tms320c6/out.cpp deleted file mode 100644 index 6507c9a..0000000 --- a/idasdk75/module/tms320c6/out.cpp +++ /dev/null @@ -1,512 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - * - * TMS320C6xx - VLIW (very long instruction word) architecture - * - */ - -#include "tms6.hpp" - -// simple wrapper class for syntactic sugar of member functions -// this class may have only simple member functions. -// virtual functions and data fields are forbidden, otherwise the class -// layout may change -class out_tms320c6_t : public outctx_t -{ - out_tms320c6_t(void) = delete; // not used -public: - bool out_operand(const op_t &x); - void out_insn(void); - void outreg(int r) { out_register(ph.reg_names[r]); } - void out_pre_mode(int mode); - void out_post_mode(int mode); - void print_stg_cyc(ea_t ea, int stgcyc); - bool tms6_out_name_expr(const op_t &x, uval_t opval); -}; -CASSERT(sizeof(out_tms320c6_t) == sizeof(outctx_t)); - -DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c6_t) - -//---------------------------------------------------------------------- -static bool is_first_insn_in_exec_packet(ea_t ea) -{ -// if ( (ea & 0x1F) == 0 ) -// return 1; - ea = prev_not_tail(ea); - return ea == BADADDR - || !is_code(get_flags(ea)) - || (get_dword(ea) & BIT0) == 0; -} - -//---------------------------------------------------------------------- -static bool prev_complex(const insn_t &insn) -{ - ea_t ea = prev_not_tail(insn.ea); - if ( ea == BADADDR || !is_code(get_flags(ea)) ) - return 0; - return !is_first_insn_in_exec_packet(ea); -} - -//---------------------------------------------------------------------- -void out_tms320c6_t::out_pre_mode(int mode) -{ - out_symbol('*'); - switch ( mode ) - { - case 0x08: // 1000 *--R[cst] - case 0x0C: // 1100 *--Rb[Ro] - out_symbol('-'); - // fallthrough - case 0x00: // 0000 *-R[cst] - case 0x04: // 0100 *-Rb[Ro] - out_symbol('-'); - break; - case 0x09: // 1001 *++R[cst] - case 0x0D: // 1101 *++Rb[Ro] - out_symbol('+'); - out_symbol('+'); - break; - case 0x01: // 0001 *+R[cst] - case 0x05: // 0101 *+Rb[Ro] -// out_symbol('+'); - break; - case 0x0A: // 1010 *R--[cst] - case 0x0B: // 1011 *R++[cst] - case 0x0E: // 1110 *Rb--[Ro] - case 0x0F: // 1111 *Rb++[Ro] - break; - } -} - -//---------------------------------------------------------------------- -void out_tms320c6_t::out_post_mode(int mode) -{ - switch ( mode ) - { - case 0x08: // 1000 *--R[cst] - case 0x0C: // 1100 *--Rb[Ro] - case 0x00: // 0000 *-R[cst] - case 0x04: // 0100 *-Rb[Ro] - case 0x09: // 1001 *++R[cst] - case 0x0D: // 1101 *++Rb[Ro] - case 0x01: // 0001 *+R[cst] - case 0x05: // 0101 *+Rb[Ro] - break; - case 0x0A: // 1010 *R--[cst] - case 0x0E: // 1110 *Rb--[Ro] - out_symbol('-'); - out_symbol('-'); - break; - case 0x0B: // 1011 *R++[cst] - case 0x0F: // 1111 *Rb++[Ro] - out_symbol('+'); - out_symbol('+'); - break; - } -} - -//---------------------------------------------------------------------- -struct ii_info_t -{ - char ii; - char cyc; -}; - -static const ii_info_t ii_info[] = -{ - { 1, 0 }, - { 2, 1 }, - { 4, 2 }, - { 8, 3 }, - { 14, 4 }, -}; - -void out_tms320c6_t::print_stg_cyc(ea_t ea, int stgcyc) -{ - int ii = 1; - insn_t prev; - for ( int i=0; i < 14 && decode_prev_insn(&prev, ea) != BADADDR; i++ ) - { - if ( prev.itype == TMS6_sploop - || prev.itype == TMS6_sploopd - || prev.itype == TMS6_sploopw ) - { - ii = prev.Op1.value; - break; - } - ea = prev.ea; - } - for ( int i=0; i < qnumber(ii_info); i++ ) - { - if ( ii_info[i].ii >= ii ) - { - int cyc = ii_info[i].cyc; - int stg = 0; - int stgbits = 6 - cyc; - int bit = 1 << cyc; - for ( int j=0; j < stgbits; j++, bit<<=1 ) - { - stg <<= 1; - if ( stgcyc & bit ) - stg |= 1; - } - cyc = stgcyc & ((1<<cyc)-1); - out_long(stg, 10); - out_symbol(','); - out_long(cyc, 10); - break; - } - } -} - -//---------------------------------------------------------------------- -bool out_tms320c6_t::tms6_out_name_expr(const op_t &x, uval_t opval) -{ - ea_t ea = to_ea(insn.cs, opval); - ea_t safe = find_first_insn_in_packet(ea); - adiff_t delta = ea - safe; - if ( !out_name_expr(x, safe, opval - delta) ) - return false; - if ( delta > 0 ) - { - out_symbol('+'); - out_long(delta, 16); - } - return true; -} - -//---------------------------------------------------------------------- -bool out_tms320c6_t::out_operand(const op_t &x) -{ - switch ( x.type ) - { - case o_void: - return 0; - - case o_reg: - outreg(x.reg); - break; - - case o_regpair: - outreg(x.reg + 1); - out_symbol(':'); - outreg(x.reg); - break; - - case o_imm: - { - uchar sign = insn.itype == TMS6_mvkh - || insn.itype == TMS6_mvklh - || (insn.itype == TMS6_mvk && is_mvk_scst16_form(insn.ea)) - ? 0 - : OOF_SIGNED; - out_value(x, OOFS_IFSIGN|OOFW_IMM|sign); - break; - } - - case o_stgcyc: - print_stg_cyc(insn.ea, x.value); - break; - - case o_near: - if ( !tms6_out_name_expr(x, x.addr) ) - { - out_tagon(COLOR_ERROR); - out_btoa(x.addr, 16); - out_tagoff(COLOR_ERROR); - remember_problem(PR_NONAME, insn.ea); - } - break; - - case o_phrase: - out_pre_mode(x.mode); - outreg(x.reg); - out_post_mode(x.mode); - out_symbol('['); - outreg(x.secreg); - out_symbol(']'); - break; - - case o_displ: - out_pre_mode(x.mode); - outreg(x.reg); - out_post_mode(x.mode); - { - if ( x.addr != 0 || is_off(F, x.n) ) - { - if ( is_off(F, x.n) ) - { - out_symbol('('); - out_value(x, OOF_ADDR|OOFS_IFSIGN|OOFW_IMM|OOF_SIGNED|OOFW_32); - out_symbol(')'); - } - else - { - out_symbol('['); - out_value(x, OOF_ADDR|OOFS_IFSIGN|OOFW_IMM|OOF_SIGNED|OOFW_32); - out_symbol(']'); - } - } - } - break; - - case o_spmask: - { - static const char units[] = "LLSSDDMM"; - uchar mask = x.reg; - bool need_comma = false; - for ( int i=0; i < 8; i++, mask>>=1 ) - { - if ( mask & 1 ) - { - if ( need_comma ) - out_symbol(','); - out_tagon(COLOR_KEYWORD); - out_char(units[i]); - out_char('1'+(i&1)); - out_tagoff(COLOR_KEYWORD); - need_comma = true; - } - } - } - break; - - default: - warning("out: %a: bad optype %d", insn.ea, x.type); - break; - } - return 1; -} - -//---------------------------------------------------------------------- -void out_tms320c6_t::out_insn(void) -{ -// -// Parallel instructions -// - ea_t ea = insn.ea; - if ( !is_first_insn_in_exec_packet(ea) ) - { - out_symbol('|'); - out_symbol('|'); - } - else - { - if ( !has_any_name(F) - && (prev_complex(insn) || insn.cflags & aux_para) ) - { - gen_empty_line(); - } - out_char(' '); - out_char(' '); - } - -// -// Condition code -// - static const char *const conds[] = - { - " ", " ", "[B0] ", "[!B0]", - "[B1] ", "[!B1]", "[B2] ", "[!B2]", - "[A1] ", "[!A1]", "[A2] ", "[!A2]", - "[A0] ", "[!A0]", " ", " " - }; - out_keyword(conds[insn.cond]); - out_char(' '); - -// -// Instruction name -// - out_mnemonic(); -// -// Functional unit -// - static const char *const units[] = - { - NULL, - ".L1", ".L2", - ".S1", ".S2", - ".M1", ".M2", - ".D1", ".D2", - }; - if ( insn.funit != FU_NONE ) - out_keyword(units[uchar(insn.funit)]); - else - out_line(" "); - if ( insn.cflags & aux_xp ) - out_keyword("X"); - else - out_char(' '); - out_line(" "); - -// -// Operands -// - if ( (insn.cflags & aux_src2) != 0 ) - { - outreg(insn.Op1.src2); - out_symbol(','); - out_char(' '); - } - - if ( insn.Op1.shown() ) - out_one_operand(0); - - if ( insn.Op2.type != o_void && insn.Op2.shown() ) - { - out_symbol(','); - out_char(' '); - out_one_operand(1); - } - - - if ( insn.Op3.type != o_void && insn.Op3.shown() ) - { - out_symbol(','); - out_char(' '); - out_one_operand(2); - } - - out_immchar_cmts(); - - int indent = inf_get_indent() - 8; // reserve space for conditions - if ( indent <= 1 ) // too little space? - indent = 2; // pass -2, which means one space - // (-1 would mean 'use DEFAULT_INDENT') - flush_outbuf(-indent); // negative value means 'print opcodes here' - - if ( (insn.cflags & aux_para) == 0 ) - { - tms6_t &pm = *static_cast<tms6_t *>(procmod); - nodeidx_t ndx = pm.tnode.altval_ea(ea); - switch ( ndx ) - { - case 1: - gen_printf(DEFAULT_INDENT, COLSTR("; BRANCH OCCURS", SCOLOR_AUTOCMT)); - break; - case 2: - gen_printf(DEFAULT_INDENT, COLSTR("; CALL OCCURS", SCOLOR_AUTOCMT)); - break; - default: - if ( ndx != 0 ) - { - ea_t target = node2ea(ndx); - qstring nbuf = get_colored_name(target & ~1); - gen_printf(DEFAULT_INDENT, - COLSTR("; %s %s OCCURS", SCOLOR_AUTOCMT), - (target & 1) ? "BRANCH" : "CALL", - nbuf.c_str()); - } - break; - } - } -} - -//-------------------------------------------------------------------------- -//lint -e{818} seg could be const -void idaapi segstart(outctx_t &ctx, segment_t *seg) -{ - if ( is_spec_segm(seg->type) ) - return; - - qstring sname; - get_segm_name(&sname, seg); - - if ( sname == ".bss" ) - return; - if ( sname == ".text" || sname == ".data" ) - { - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR), sname.c_str()); - } - else - { - validate_name(&sname, VNT_IDENT); - ctx.gen_printf(DEFAULT_INDENT, COLSTR(".sect \"%s\"", SCOLOR_ASMDIR), sname.c_str()); - } -} - -//-------------------------------------------------------------------------- -void idaapi segend(outctx_t &, segment_t *) -{ -} - -//-------------------------------------------------------------------------- -void idaapi header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_ALL); -} - -//-------------------------------------------------------------------------- -void tms6_t::footer(outctx_t &ctx) const -{ - qstring nbuf = get_colored_name(inf_get_start_ea()); - const char *name = nbuf.c_str(); - const char *end = ash.end; - if ( end == NULL ) - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s", SCOLOR_AUTOCMT), ash.cmnt, name); - else - ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR) - " " - COLSTR("%s %s", SCOLOR_AUTOCMT), ash.end, ash.cmnt, name); -} - -//-------------------------------------------------------------------------- -void idaapi data(outctx_t &ctx, bool analyze_only) -{ - ea_t ea = ctx.insn_ea; - segment_t *s = getseg(ea); - if ( s != NULL ) - { - qstring sname; - if ( get_segm_name(&sname, s) > 0 && sname == ".bss" ) - { - qstring name; - if ( get_colored_name(&name, ea) <= 0 ) - name.sprnt(COLSTR("bss_dummy_name_%a", SCOLOR_UNKNAME), ea); - char num[MAX_NUMBUF]; - btoa(num, sizeof(num), get_item_size(ea), get_radix(ctx.F, 0)); - ctx.ctxflags |= CTXF_LABEL_OK; - ctx.gen_printf(-1, - COLSTR(".bss", SCOLOR_KEYWORD) - " %s, " - COLSTR("%s", SCOLOR_DNUM), - name.begin(), - num); - return; - } - } - ctx.out_data(analyze_only); -} - -//-------------------------------------------------------------------------- -//lint -e{1764} ctx could be const -bool tms6_t::outspec(outctx_t &ctx, uchar stype) const -{ - ea_t ea = ctx.insn_ea; - qstring nbuf; - if ( get_colored_name(&nbuf, ea) <= 0 ) - return false; - const char *name = nbuf.begin(); - char buf[MAX_NUMBUF]; - switch ( stype ) - { - case SEG_XTRN: - return ctx.gen_printf(-1, COLSTR("%s %s", SCOLOR_ASMDIR), ash.a_extrn,name); - case SEG_ABSSYM: - // i don't know how to declare absolute symbols. - // perhaps, like this? - btoa(buf, sizeof(buf), get_dword(ea)); - return ctx.gen_printf(-1, COLSTR("%s = %s", SCOLOR_ASMDIR), name, buf); - case SEG_COMM: - btoa(buf, sizeof(buf), get_dword(ea)); - ctx.gen_printf(-1, - COLSTR("%s \"%s\", %s", SCOLOR_ASMDIR), - ash.a_comdef, name, buf); - } - return false; -} diff --git a/idasdk75/module/tms320c6/reg.cpp b/idasdk75/module/tms320c6/reg.cpp deleted file mode 100644 index 4a55f7b..0000000 --- a/idasdk75/module/tms320c6/reg.cpp +++ /dev/null @@ -1,324 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - * - * TMS320C6xx - VLIW (very long instruction word) architecture - * - */ - -#include "tms6.hpp" - -//-------------------------------------------------------------------------- -// B14 - data page pointer -// B15 - stack pointer -static const char *const RegNames[] = -{ - "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", - "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", - "A16", "A17", "A18", "A19", "A20", "A21", "A22", "A23", - "A24", "A25", "A26", "A27", "A28", "A29", "A30", "A31", - "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", - "B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15", - "B16", "B17", "B18", "B19", "B20", "B21", "B22", "B23", - "B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31", - "AMR", - "CSR", - "IFR", - "ISR", - "ICR", - "IER", - "ISTP", - "IRP", - "NRP", - "ACR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com> - "ADR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com> - "PCE1", - "FADCR", - "FAUCR", - "FMCR", - "TSCL", - "TSCH", - "ILC", - "RILC", - "REP", - "DNUM", - "SSR", - "GPLYA", - "GPLYB", - "GFPGFR", - "TSR", - "ITSR", - "NTSR", - "ECR", - "EFR", - "IERR", - "CS", "DS" -}; - -//-------------------------------------------------------------------------- -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case idb_event::segm_moved: // A segment is moved - // Fix processor dependent address sensitive information - { - ea_t from = va_arg(va, ea_t); - ea_t to = va_arg(va, ea_t); - asize_t size = va_arg(va, asize_t); - bool changed_netmap = va_argi(va, bool); - if ( !changed_netmap ) - { - struct aaj_visitor_t : public altadjust_visitor_t - { - tms6_t ± - aaj_visitor_t(tms6_t &_pm): pm(_pm) {} - virtual bool should_skip(nodeidx_t n) override - { - nodeidx_t ndx = pm.tnode.altval(n); - return ndx == 1 || ndx == 2; - } - }; - nodeidx_t ndx1 = ea2node(from); - nodeidx_t ndx2 = ea2node(to); - pm.tnode.altshift(ndx1, ndx2, size); - aaj_visitor_t aaj(pm); - pm.tnode.altadjust2(ndx1, ndx2, size, aaj); - } - } - break; - } - return 0; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new tms6_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi tms6_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - hook_event_listener(HT_IDB, &idb_listener, &LPH); - break; - - case processor_t::ev_term: - unhook_event_listener(HT_IDB, &idb_listener); - break; - - case processor_t::ev_ending_undo: - case processor_t::ev_newfile: - case processor_t::ev_oldfile: - tnode.create("$ tms node"); - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - segend(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - data(*ctx, analyze_only); - return 1; - } - - case processor_t::ev_out_special_item: - { - outctx_t *ctx = va_arg(va, outctx_t *); - uchar seg_type = va_argi(va, uchar); - outspec(*ctx, seg_type); - return 1; - } - - case processor_t::ev_is_align_insn: - { - ea_t ea = va_arg(va, ea_t); - return is_align_insn(ea); - } - - default: - break; - } - return code; -} - -//----------------------------------------------------------------------- -// TMS320C6x COFF Assembler -//----------------------------------------------------------------------- -static const asm_t dspasm = -{ - AS_COLON | ASH_HEXF0 | ASD_DECF0 | ASB_BINF0 | ASO_OCTF5, - 0, - "TMS320C6x COFF Assembler", - 0, - NULL, // header lines - NULL, // org - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".string", // ascii string directive - ".char", // byte directive - ".short", // word directive - ".long", // double words - NULL, // no qwords - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".space %s", // uninited arrays - ".set", // equ - NULL, // 'seg' prefix (example: push seg seg001) - "$", // current IP (instruction pointer) - NULL, // func_header - NULL, // func_footer - ".def", // "public" name keyword - NULL, // "weak" name keyword - ".ref", // "extrn" name keyword - ".usect", // "comm" (communal variable) - NULL, // get_type_name - ".align", // "align" keyword - '(', ')', // lbrace, rbrace - NULL, // mod - "&", // and - "|", // or - "^", // xor - "!", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - - -static const asm_t *const asms[] = { &dspasm, NULL }; -//----------------------------------------------------------------------- -#define FAMILY "TMS320C6 series:" -static const char *const shnames[] = { "TMS320C6", NULL }; -static const char *const lnames[] = -{ - FAMILY"Texas Instruments TMS320C6xxx", - NULL -}; - -//-------------------------------------------------------------------------- -static const uchar retcode_1[] = { 0x62, 0x63, 0x0C, 0x00 }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_TMSC6, // id - // flag - PR_USE32 - | PR_DEFSEG32 - | PR_DELAYED - | PR_ALIGN_INSN, // allow align instructions - // flag2 - 0, - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - asms, - - notify, - - RegNames, // Register names - qnumber(RegNames), // Number of registers - - rVcs, // first - rVds, // last - 0, // size of a segment register - rVcs, rVds, - - NULL, // No known code start sequences - retcodes, - - TMS6_null, - TMS6_last, - Instructions, // instruc - 0, // int tbyte_size; - { 2, 4, 8, 12 }, // char real_width[4]; - TMS6_null, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/tms320c6/tms6.hpp b/idasdk75/module/tms320c6/tms6.hpp deleted file mode 100644 index de3d947..0000000 --- a/idasdk75/module/tms320c6/tms6.hpp +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-98 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * E-mail: ig@estar.msk.su - * FIDO: 2:5020/209 - * - * - * TMS320C6xx - VLIW (very long instruction word) architecture - * - */ - -#ifndef _TMS6_HPP -#define _TMS6_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" - -DECLARE_PROC_LISTENER(idb_listener_t, struct tms6_t); - -struct tms6_t : public procmod_t -{ - netnode tnode; - idb_listener_t idb_listener = idb_listener_t(*this); - bool flow = false; - - ssize_t idaapi on_event(ssize_t msgid, va_list va); - int emu(const insn_t &insn); - void footer(outctx_t &ctx) const; - bool outspec(outctx_t &ctx, uchar stype) const; -}; - -//--------------------------------- -// Functional units: - -#ifdef _MSC_VER -#define ENUM8BIT : uint8 -#else -#define ENUM8BIT -#endif -enum funit_t ENUM8BIT -{ - FU_NONE, // No unit (NOP, IDLE) - FU_L1, FU_L2, // 32/40-bit arithmetic and compare operations - // Leftmost 1 or 0 bit counting for 32 bits - // Normalization count for 32 and 40 bits - // 32-bit logical operations - - FU_S1, FU_S2, // 32-bit arithmetic operations - // 32/40-bit shifts and 32-bit bit-field operations - // 32-bit logical operations - // Branches - // Constant generation - // Register transfers to/from the control register file (.S2 only) - - FU_M1, FU_M2, // 16 x 16 bit multiply operations - - FU_D1, FU_D2, // 32-bit add, subtract, linear and circular address calculation - // Loads and stores with a 5-bit constant offset - // Loads and stores with 15-bit constant offset (.D2 only) -}; - -//--------------------------------- -// Operand types: -#define o_regpair o_idpspec0 // Register pair (A1:A0..B15:B14) - // Register pair is denoted by its - // even register in op.reg - // (Odd register keeps MSB) - -#define o_spmask o_idpspec1 // unit mask (reg) -#define o_stgcyc o_idpspec2 // fstg/fcyc (value) - - -// o_phrase: the second register is held in secreg (specflag1) -#define secreg specflag1 -// o_phrase, o_displ: mode -#define mode specflag2 - -#define src2 specflag2 // for field instructions - -//------------------------------------------------------------------ -#define funit segpref // Functional unit for insn -#define cond auxpref_u8[0] // The condition code of instruction -#define cflags auxpref_u8[1] // Various bit definitions: -# define aux_para 0x0001 // parallel execution with the next insn -# define aux_src2 0x0002 // src2 register for immediate form of - // field instructions is present at "Op1.src2" -# define aux_xp 0x0004 // X path is used -# define aux_pseudo 0x0008 // Pseudo instruction - -//------------------------------------------------------------------ -// condition codes: -#define cAL 0x0 // unconditional -#define cB0 0x2 // B0 -#define cnB0 0x3 // !B0 -#define cB1 0x4 // B1 -#define cnB1 0x5 // !B1 -#define cB2 0x6 // B2 -#define cnB2 0x7 // !B2 -#define cA1 0x8 // A1 -#define cnA1 0x9 // !A1 -#define cA2 0xA // A2 -#define cnA2 0xB // !A2 - -//------------------------------------------------------------------ -// Bit definitions. Just for convenience: -#define BIT0 0x00000001L -#define BIT1 0x00000002L -#define BIT2 0x00000004L -#define BIT3 0x00000008L -#define BIT4 0x00000010L -#define BIT5 0x00000020L -#define BIT6 0x00000040L -#define BIT7 0x00000080L -#define BIT8 0x00000100L -#define BIT9 0x00000200L -#define BIT10 0x00000400L -#define BIT11 0x00000800L -#define BIT12 0x00001000L -#define BIT13 0x00002000L -#define BIT14 0x00004000L -#define BIT15 0x00008000L -#define BIT16 0x00010000L -#define BIT17 0x00020000L -#define BIT18 0x00040000L -#define BIT19 0x00080000L -#define BIT20 0x00100000L -#define BIT21 0x00200000L -#define BIT22 0x00400000L -#define BIT23 0x00800000L -#define BIT24 0x01000000L -#define BIT25 0x02000000L -#define BIT26 0x04000000L -#define BIT27 0x08000000L -#define BIT28 0x10000000L -#define BIT29 0x20000000L -#define BIT30 0x40000000L -#define BIT31 0x80000000L - -//------------------------------------------------------------------ -enum RegNo ENUM8BIT -{ - rA0, rA1, rA2, rA3, rA4, rA5, rA6, rA7, - rA8, rA9, rA10, rA11, rA12, rA13, rA14, rA15, - rA16, rA17, rA18, rA19, rA20, rA21, rA22, rA23, - rA24, rA25, rA26, rA27, rA28, rA29, rA30, rA31, - rB0, rB1, rB2, rB3, rB4, rB5, rB6, rB7, - rB8, rB9, rB10, rB11, rB12, rB13, rB14, rB15, - rB16, rB17, rB18, rB19, rB20, rB21, rB22, rB23, - rB24, rB25, rB26, rB27, rB28, rB29, rB30, rB31, - rAMR, - rCSR, - rIFR, - rISR, - rICR, - rIER, - rISTP, - rIRP, - rNRP, - rACR, - rADR, - rPCE1, - rFADCR, - rFAUCR, - rFMCR, - rTSCL, - rTSCH, - rILC, - rRILC, - rREP, - rDNUM, - rSSR, - rGPLYA, - rGPLYB, - rGFPGFR, - rTSR, - rITSR, - rNTSR, - rECR, - rEFR, - rIERR, - rVcs, rVds, // virtual registers for code and data segments -}; - -//------------------------------------------------------------------ -// XXX this assumes the non-compact encoding -inline bool is_mvk_scst16_form(ea_t ea) -{ - return ((get_dword(ea) >> 2) & 0x1F) == 0xA; -} - -//------------------------------------------------------------------ -void idaapi header(outctx_t &ctx); - -void idaapi segstart(outctx_t &ctx, segment_t *seg); -void idaapi segend(outctx_t &ctx, segment_t *seg); - -void idaapi data(outctx_t &ctx, bool analyze_only); - -int idaapi ana(insn_t *insn); - -int idaapi is_align_insn(ea_t ea); - -ea_t find_first_insn_in_packet(ea_t ea); - -#endif // _TMS6_HPP diff --git a/idasdk75/module/xa/ana.cpp b/idasdk75/module/xa/ana.cpp deleted file mode 100644 index 6e6d3e7..0000000 --- a/idasdk75/module/xa/ana.cpp +++ /dev/null @@ -1,942 +0,0 @@ -/* - This module has been created by Petr Novak - */ - -#include "xa.hpp" - -static int ana_basic(insn_t &insn); - -//---------------------------------------------------------------------- -inline int ua_next_word_be(insn_t &insn) -{ - int32 result; - result = ((uchar)insn.get_next_byte()) << 8; - result += (uchar)insn.get_next_byte(); - return (int)result; -} - -//---------------------------------------------------------------------- -inline void opC(op_t &op) -{ - op.type = o_reg; - op.reg = rC; -} - -//---------------------------------------------------------------------- -// register direct -static int op_rd(op_t &x, int reg, int dtype) -{ - x.type = o_reg; - x.dtype = uchar(dtype); - x.reg = uint16((dtype == dt_byte ? rR0L : rR0) + reg); - return 1; -} - -//---------------------------------------------------------------------- -// register indirect -static int op_ph(op_t &x, uint16 phrase, int reg, int dtype) -{ - x.type = o_phrase; - x.dtype = uchar(dtype); - x.phrase = phrase; // union with x.reg - x.indreg = (uchar)reg; - if ( (phrase != fRlistL) && (phrase != fRlistH) ) - x.indreg += rR0; - return 1; -} - -//---------------------------------------------------------------------- -// register indirect with displacement -static int op_ds(op_t &x, uint16 phrase, int ireg, sval_t disp, int dtype) -{ - if ( disp > 0xFD00L ) - { - disp = disp - 0x10000L; // heuristics: treat large values from -300h as negative - } - x.type = o_displ; - x.dtype = uchar(dtype); - x.phrase = phrase; - x.indreg = rR0 + (uchar)ireg; - x.addr = disp; - return 1; -} - -//---------------------------------------------------------------------- -inline void op_mm(op_t &x, uval_t addr, int dtype) -{ - x.type = o_mem; - x.dtype = uchar(dtype); - x.addr = addr; -} - -//---------------------------------------------------------------------- -inline void op_rel(const insn_t &insn, op_t &x, sval_t addr) -{ - if ( addr > 32767 ) - addr -= 0x10000L; - x.type = o_near; - x.dtype = dt_code; - x.addr = (insn.ip + insn.size + 2*addr) & (~1L); -} - -//---------------------------------------------------------------------- -inline void op_near(op_t &x, uval_t addr) -{ - x.type = o_near; - x.dtype = dt_word; - x.addr = addr; -} - -//---------------------------------------------------------------------- -inline void op_im(op_t &x, uval_t value, int dtype) -{ - x.type = o_imm; - x.dtype = uchar(dtype); - x.value = value; -} - -//---------------------------------------------------------------------- -inline void op_bit(op_t &x, int type, uval_t addr) -{ - x.type = optype_t(type); - x.dtype = dt_word; - x.addr = addr; -} - -//---------------------------------------------------------------------- -// analyze an basic instruction -static int ana_basic(insn_t &insn) -{ - - static const nameNum xa_basic[16] = - { - XA_add, XA_addc, XA_sub, XA_subb, XA_cmp, XA_and, XA_or, XA_xor, - XA_mov, XA_null, XA_null, XA_null, XA_null, XA_null, XA_null, XA_null, - }; - - static const nameNum xa_branches[16] = - { - XA_bcc, XA_bcs, XA_bne, XA_beq, XA_bnv, XA_bov, XA_bpl, XA_bmi, - XA_bg, XA_bl, XA_bge, XA_blt, XA_bgt, XA_ble, XA_br, XA_bkpt, - }; - - static const nameNum xa_pushpop[] = - { - XA_push, XA_pushu, XA_pop, XA_popu, - }; - - static const nameNum xa_bitops[] = - { - XA_clr, XA_setb, XA_mov, XA_mov, XA_anl, XA_anl, XA_orl, XA_orl, - }; - - static const nameNum xa_Jxx[] = - { - XA_jb, XA_jnb, XA_jbc, XA_null, - }; - - static const nameNum xa_misc[] = - { - XA_da, XA_sext, XA_cpl, XA_neg, - }; - - static const nameNum xa_shifts[] = - { - XA_lsr, XA_asl, XA_asr, XA_norm, - }; - - ushort code = insn.get_next_byte(); - - ushort nibble0 = (code & 0xF); - ushort nibble1 = (code >> 4); - signed char off; - int size = 0; - ushort b1; - - if ( nibble1 <= 0xB ) - { - switch ( nibble0 & 0x7 ) - { - case 0: // Specials - case 7: // dtto - switch ( code ) - { - case 0x00: // 00 - NOP - insn.itype = XA_nop; - break; - - case 0x07: // PUSH.B Rlist - case 0x0F: // PUSH.W Rlist - case 0x17: // PUSHU.B Rlist - case 0x1F: // PUSHU.W Rlist - case 0x27: // POP.B Rlist - case 0x2F: // POP.W Rlist - case 0x37: // POPU.B Rlist - case 0x3F: // POPU.W Rlist - case 0x47: // PUSH.B Rlist - case 0x4F: // PUSH.W Rlist - case 0x57: // PUSHU.B Rlist - case 0x5F: // PUSHU.W Rlist - case 0x67: // POP.B Rlist - case 0x6F: // POP.W Rlist - case 0x77: // POPU.B Rlist - case 0x7F: // POPU.W Rlist - size = (nibble0 < 8) ? dt_byte : dt_word; - b1 = insn.get_next_byte(); // Rlist - insn.itype = xa_pushpop[nibble1 & 3]; - if ( nibble1 & 4 ) // High - op_ph(insn.Op1, fRlistH, b1, size); - else - op_ph(insn.Op1, fRlistL, b1, size); - break; - - case 0x08: // 08 - misc - b1 = insn.get_next_byte(); - switch ( b1 & 0xfc ) - { - case 0x00: // CLR - case 0x10: // SETB - insn.itype = xa_bitops[(b1>>4) & 7]; - op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); - break; - case 0x20: // MOV C,bit - insn.itype = xa_bitops[(b1>>4) & 7]; - opC(insn.Op1); - op_bit(insn.Op2, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); - break; - case 0x30: // MOV bit,C - insn.itype = xa_bitops[(b1>>4) & 7]; - op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); - opC(insn.Op2); - break; - case 0x40: // ANL C, bit - case 0x50: // ANL C, /bit - case 0x60: // ORL C, bit - case 0x70: // ORL C, /bit - insn.itype = xa_bitops[(b1>>4) & 7]; - opC(insn.Op1); - op_bit(insn.Op2, - (b1&0x10)?o_bitnot:o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); - break; - default: // undefined - return 0; - } - break; - - case 0x40: // LEA - case 0x48: // LEA - insn.itype = XA_lea; - b1 = insn.get_next_byte(); - if ( b1 & 0x88 ) - return 0; - op_rd(insn.Op1, b1>>4, dt_word); - if ( code & 0x8 ) // 16bit offset - op_ds(insn.Op2, fRid16, b1&0x07, (int32)ua_next_word_be(insn), dt_word); - else - op_ds(insn.Op2, fRid8, b1&0x07, (signed char)insn.get_next_byte(), dt_word); - break; - - case 0x50: // XCH.B Rd,[Rs] - case 0x58: // XCH.W Rd,[Rs] - case 0x60: // XCH.B Rd,Rs - case 0x68: // XCH.W Rd,Rs - insn.itype = XA_xch; - size = (nibble0 < 8) ? dt_byte : dt_word; - b1 = insn.get_next_byte(); - op_rd(insn.Op1, b1>>4, size); - switch ( nibble1 ) - { - case 0x5: // Rd,[Rs] - if ( b1 & 8 ) - return 0; - op_ds(insn.Op2, fRi, b1&7, 0, size); - break; - case 0x6: // Rd,Rs - op_rd(insn.Op2, b1&0xf, size); - break; - } - break; - - case 0x80: // MOVC - case 0x88: // MOVC - b1 = insn.get_next_byte(); - size = (nibble0 < 8) ? dt_byte : dt_word; - if ( b1 & 8 ) - return 0; - insn.itype = XA_movc; - op_rd(insn.Op1, b1>>4, size); - op_ph(insn.Op2, fRip, b1&7, size); - break; - - case 0x87: // DJNZ Rd, rel8 - case 0x8F: // POP, POPU, PUSH, PUSHU direct - b1 = insn.get_next_byte(); - size = (nibble0 < 8) ? dt_byte : dt_word; - if ( b1 & 8 ) // DJNZ - { - if ( b1 & 7 ) - return 0; - insn.itype = XA_djnz; - op_rd(insn.Op1, b1>>4, size); - op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); - } - else - { //POP, POPU, PUSH, PUSHU - if ( b1 & 0xc0 ) - return 0; - insn.itype = xa_pushpop[3-((b1>>4)&3)]; - op_mm(insn.Op1, ((b1 & 7) << 8) + insn.get_next_byte(), size); - } - break; - - case 0x90: // CPL, DA, SEXT - case 0x98: // CPL & MOV [Rd+], [Rs+] & MOV direct, [Rs] - b1 = insn.get_next_byte(); - size = (nibble0 < 8) ? dt_byte : dt_word; - switch ( b1 & 0x0f ) - { - case 0x0: // MOV [Rd+], [Rs+] - case 0x1: - case 0x2: - case 0x3: - case 0x4: - case 0x5: - case 0x6: - case 0x7: // MOV [Rd+], [Rs+] - if ( b1 & 0x80 ) - return 0; - insn.itype = XA_mov; - op_ph(insn.Op1, fRip, (b1>>4)&7, size); - op_ph(insn.Op2, fRip, (b1&7), size); - break; - - case 0x8: // DA - case 0x9: // SEXT - case 0xA: // CPL - case 0xB: // NEG - insn.itype = xa_misc[b1&3]; - op_rd(insn.Op1, b1>>4, size); - if ( (nibble0&8) != 0 && insn.itype == XA_da ) - return 0; - break; - - case 0xC: // MOVC A,[A+PC] 904C - if ( (nibble0 != 0) & ((b1&0xf0) != 0xc0) ) - return 0; - insn.itype = XA_movc; - op_rd(insn.Op1, rA, dt_byte); - op_ph(insn.Op2, fApc, 0, dt_byte); - break; - - case 0xE: // MOVC A,[A+DPTR] 904E - if ( (nibble0 != 0) & ((b1&0xf0) != 0xc0) ) - return 0; - insn.itype = XA_movc; - op_rd(insn.Op1, rA, dt_byte); - op_ph(insn.Op2, fAdptr, 0, dt_byte); - break; - - case 0xF: // MOV Rd,USP & MOV USP, Rs - insn.itype = XA_mov; - if ( nibble0&8 ) // USP,Rs - { - op_rd(insn.Op1, rUSP-rR0, dt_word); - op_rd(insn.Op2, b1>>4, dt_word); - } - else - { - op_rd(insn.Op1, b1>>4, dt_word); - op_rd(insn.Op2, rUSP-rR0, dt_word); - } - break; - - default: - return 0; - } - break; - - case 0x97: // {JB,JBC,JNB} bit, rel8 & MOV direct, direct - case 0x9F: // {JB,JBC,JNB} bit, rel8 & MOV direct, direct - b1 = insn.get_next_byte(); - if ( (b1 & 0x88) == 0x00 ) // MOV direct, direct - { - insn.itype = XA_mov; - size = (nibble0 < 8) ? dt_byte : dt_word; - op_mm(insn.Op1, ((b1 & 0x70) << 4) + (uchar)insn.get_next_byte(), size); - op_mm(insn.Op2, ((b1 & 0x7) << 8) + (uchar)insn.get_next_byte(), size); - } - else - { - if ( nibble0 & 8 ) - return 0; - switch ( b1 & 0xfc ) - { - case 0x80: // JB - case 0xA0: // JNB - case 0xC0: // JBC - insn.itype = xa_Jxx[(b1>>5)&3]; - op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); - op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); - break; - default: - return 0; - } - } - break; - - case 0xA0: // MOV.B direct, [Rs] & [Rd], direct & XCH - case 0xA8: // MOV.W direct, [Rs] & [Rd], direct & XCH - b1 = insn.get_next_byte(); - size = (nibble0 < 8) ? dt_byte : dt_word; - if ( b1 & 8 ) // XCH - { - insn.itype = XA_xch; - op_rd(insn.Op1, b1>>4, size); - op_mm(insn.Op2, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); - } - else - { // MOV - insn.itype = XA_mov; - if ( b1 & 0x80 ) // direct, [Rs] - { - op_mm(insn.Op1, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); - op_ds(insn.Op2, fRi, (b1>>4)&7, 0, size); - } - else - { - op_ds(insn.Op1, fRi, (b1>>4)&7, 0, size); - op_mm(insn.Op2, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); - } - } - break; - - case 0xA7: // MOVX - case 0xAF: // MOVX - insn.itype = XA_movx; - size = (nibble0 < 8) ? dt_byte : dt_word; - b1 = insn.get_next_byte(); - if ( b1 & 8 ) // [Rd],Rs - { - op_ds(insn.Op1, fRi, b1&0x7, 0, size); - op_rd(insn.Op2, b1>>4, size); - } - else - { // Rd,[Rs] - op_rd(insn.Op1, b1>>4, size); - op_ds(insn.Op2, fRi, b1&0x7, 0, size); - } - break; - - case 0xB0: // RR - case 0xB7: // RRC - case 0xB8: // RR - case 0xBF: // RRC - insn.itype = (nibble0 & 7) ? XA_rrc : XA_rr; - size = (nibble0 < 8) ? dt_byte : dt_word; - b1 = insn.get_next_byte(); - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, b1&0xf, size); - break; - - default: - return 0; - } - break; - - default: - switch ( nibble1 ) - { - case 0: // ADD - case 1: // ADDC - case 2: // SUB - case 3: // SUBB - case 4: // CMP - case 5: // AND - case 6: // OR - case 7: // XOR - case 8: // MOV - insn.itype = xa_basic[nibble1]; - size = (nibble0 < 8) ? dt_byte : dt_word; - b1 = insn.get_next_byte(); - switch ( nibble0 & 0x7 ) - { - case 0x1: // OP Rd,Rs - op_rd(insn.Op1, b1>>4, size); - op_rd(insn.Op2, b1&0xF, size); - break; - - case 0x2: // OP Rd,[Rs] - if ( b1 & 8 ) // [Rd], Rs - { - op_ds(insn.Op1, fRi, b1&7, 0, size); - op_rd(insn.Op2, b1>>4, size); - } - else - { - op_rd(insn.Op1, b1>>4, size); - op_ds(insn.Op2, fRi, b1&7, 0, size); - } - break; - - case 0x3: // OP Rd,[Rs+] - if ( b1 & 8 ) // [Rd], Rs - { - op_ph(insn.Op1, fRip, (b1&7), size); - op_rd(insn.Op2, b1>>4, size); - } - else - { - op_rd(insn.Op1, b1>>4, size); - op_ph(insn.Op2, fRip, (b1&7), size); - } - break; - - case 0x4: // OP Rd,[Rs+o8] - if ( b1 & 8 ) // [Rd], Rs - { - op_ds(insn.Op1, fRid8, (b1&7), (signed char)insn.get_next_byte(), size); - op_rd(insn.Op2, b1>>4, size); - } - else - { - op_rd(insn.Op1, b1>>4, size); - op_ds(insn.Op2, fRid8, (b1&7), (signed char)insn.get_next_byte(), size); - } - break; - - case 0x5: // OP Rd,[Rs+o16] - if ( b1 & 8 ) // [Rd], Rs - { - op_ds(insn.Op1, fRid16, (b1&7), (int)ua_next_word_be(insn), size); - op_rd(insn.Op2, b1>>4, size); - } - else - { - op_rd(insn.Op1, b1>>4, size); - op_ds(insn.Op2, fRid16, (b1&7), (int)ua_next_word_be(insn), size); - } - break; - - case 0x6: // OP Rd,direct - if ( b1 & 8 ) // direct, Rs - { - op_mm(insn.Op1, ((b1 & 7) << 8) + insn.get_next_byte(), size); - op_rd(insn.Op2, b1>>4, size); - } - else - { - op_rd(insn.Op1, b1>>4, size); - op_mm(insn.Op2, ((b1 & 7) << 8) + insn.get_next_byte(), size); - } - break; - } - break; - - case 9: // Immediate operations - b1 = insn.get_next_byte(); - insn.itype = xa_basic[b1 & 0x0f]; - size = (nibble0 < 8) ? dt_byte : dt_word; - switch ( nibble0 & 0x7 ) - { - case 0x1: - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); - break; - - case 0x2: - op_ds(insn.Op1, fRi, (b1>>4) & 0x7, 0, size); - op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); - break; - - case 0x3: - op_ph(insn.Op1, fRip, (b1>>4) & 0x7, size); - op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); - break; - - case 0x4: - op_ds(insn.Op1, fRid8, (b1>>4) & 0x7, (signed char)insn.get_next_byte(), size); - op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); - break; - - case 0x5: - op_ds(insn.Op1, fRid16, (b1>>4) & 0x7, (int)ua_next_word_be(insn), size); - op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); - break; - - case 0x6: - op_mm(insn.Op1, (((b1>>4) & 0x7) << 8) + insn.get_next_byte(), size); - op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); - break; - } - break; - - case 0xA: // ADDS - case 0xB: // MOVS - b1 = insn.get_next_byte(); - insn.itype = (nibble1 == 0x0A) ? XA_adds : XA_movs; - size = (nibble0 < 8) ? dt_byte : dt_word; - off = b1 & 0xf; - if ( off > 7 ) - off -= 16; - op_im(insn.Op2, (int32)off, size); - switch ( nibble0 & 0x7 ) - { - case 0x1: - op_rd(insn.Op1, b1>>4, size); - break; - - case 0x2: - op_ds(insn.Op1, fRi, (b1>>4) & 0x7, 0, size); - break; - - case 0x3: - op_ph(insn.Op1, fRip, (b1>>4) & 0x7, size); - break; - - case 0x4: - op_ds(insn.Op1, fRid8, (b1>>4) & 0x7, (signed char)insn.get_next_byte(), size); - break; - - case 0x5: - op_ds(insn.Op1, fRid16, (b1>>4) & 0x7, (int)ua_next_word_be(insn), size); - break; - - case 0x6: - op_mm(insn.Op1, (((b1>>4) & 0x7) << 8) + (uchar)insn.get_next_byte(), size); - break; - } - break; - } - } - } - else - { // nibble1 > B - switch ( nibble1 ) - { - case 0xC: // Shifts, CALL, FCALL - switch ( nibble0 & 0xc ) - { - case 0x0: - size = dt_byte; - break; - case 0x8: - size = dt_word; - break; - case 0xC: - size = dt_dword; - break; - case 0x4: // Special instructions - switch ( nibble0 ) - { - case 4: // FCALL addr24 - insn.itype = XA_fcall; - insn.Op1.type = o_far; - insn.Op1.dtype = dt_code; - insn.Op1.addr = (ushort)ua_next_word_be(insn); - insn.Op1.specval = (uchar)insn.get_next_byte(); - break; - case 5: // CALL rel16 - insn.itype = XA_call; - op_rel(insn, insn.Op1, (int)ua_next_word_be(insn)); - break; - case 6: // CALL [Rs] - b1 = insn.get_next_byte(); - if ( b1 & 0xf8 ) - return 0; - insn.itype = XA_call; - op_ds(insn.Op1, fRi, b1&7, 0, dt_word); - break; - default: - return 0; - } - break; - } - if ( insn.itype == XA_null ) - { - insn.itype = xa_shifts[nibble0 & 3]; - b1 = insn.get_next_byte(); - op_rd(insn.Op1, b1>>4, size); - op_rd(insn.Op2, b1&0xf, size); - } - break; - - case 0xD: // JMP, FJMP, rotations & shifts with #d4/#d5 - switch ( nibble0 & 0xC ) - { - case 0x4: // Special instructions - switch ( nibble0 ) - { - case 7: // rotate - break; - case 4: // FJMP addr24 - insn.itype = XA_fjmp; - insn.Op1.type = o_far; - insn.Op1.dtype = dt_code; - insn.Op1.addr = (ushort)ua_next_word_be(insn); - insn.Op1.specval = (uchar)insn.get_next_byte(); - break; - case 5: // JMP rel16 - insn.itype = XA_jmp; - op_rel(insn, insn.Op1, (int)ua_next_word_be(insn)); - break; - case 6: // specials - insn.itype = XA_jmp; - b1 = insn.get_next_byte(); - switch ( b1 & 0xf8 ) - { - case 0x10: // RESET - if ( b1 & 7 ) - return 0; - insn.itype = XA_reset; - break; - case 0x30: // TRAP - case 0x38: // TRAP - insn.itype = XA_trap; - op_im(insn.Op1, b1 & 0xf, dt_byte); - break; - case 0x40: // JMP [A+DPTR] - if ( (b1&7) != 6 ) - return 0; - op_ph(insn.Op1, fAdptr, 0, dt_word); - break; - case 0x60: // JMP [[Rs+]] - op_ph(insn.Op1, fRipi, b1&7, dt_word); - break; - case 0x70: // JMP [Rs] - op_ph(insn.Op1, fRi, b1&7, dt_word); - break; - case 0x80: // RET - if ( b1 & 7 ) - return 0; - insn.itype = XA_ret; - break; - case 0x90: // RETI - if ( b1 & 7 ) - return 0; - insn.itype = XA_reti; - break; - default: - return 0; - } - break; - default: - return 0; - } - break; - - case 0x0: - size = dt_byte; - break; - - case 0x8: - size = dt_word; - break; - - case 0xC: - size = dt_dword; - break; - } - if ( insn.itype == XA_null ) - { - insn.itype = xa_shifts[nibble0 & 3]; - if ( insn.itype == XA_norm ) - { // rotations - size = (nibble0 < 8) ? dt_byte : dt_word; - insn.itype = (nibble0 & 4) ? XA_rlc : XA_rl; - b1 = insn.get_next_byte(); - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, b1&0xf, size); - } - else - { // shifts - b1 = insn.get_next_byte(); - if ( size == dt_dword ) - { - op_rd(insn.Op1, (b1>>4)&0x0e, size); // Only even registers allowed - op_im(insn.Op2, b1&0x1f, size); - } - else - { - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, b1&0xf, size); - } - } - } - break; - - case 0xE: // DIV & MUL & cjne & jz/jnz - b1 = insn.get_next_byte(); - switch ( nibble0 ) - { - case 0x0: // MULU.B Rd,Rs - insn.itype = XA_mulu; - op_rd(insn.Op1, b1>>4, dt_byte); - op_rd(insn.Op2, b1&0xf, dt_byte); - break; - case 0x1: // DIVU.B Rd,Rs - insn.itype = XA_divu; - op_rd(insn.Op1, b1>>4, dt_byte); - op_rd(insn.Op2, b1&0xf, dt_byte); - break; - case 0x4: // MULU.W Rd,Rs - insn.itype = XA_mulu; - op_rd(insn.Op1, b1>>4, dt_word); - op_rd(insn.Op2, b1&0xf, dt_word); - break; - case 0x5: // DIVU.W Rd,Rs - insn.itype = XA_divu; - op_rd(insn.Op1, b1>>4, dt_word); - op_rd(insn.Op2, b1&0xf, dt_word); - break; - case 0x6: // MUL.W Rd,Rs - insn.itype = XA_mul; - op_rd(insn.Op1, b1>>4, dt_word); - op_rd(insn.Op2, b1&0xf, dt_word); - break; - case 0x7: // DIV.W Rd, Rs - insn.itype = XA_div; - op_rd(insn.Op1, b1>>4, dt_word); - op_rd(insn.Op2, b1&0xf, dt_word); - break; - case 0x8: // MUL & DIV Rd,#8 - switch ( b1 & 0xf ) - { - case 0x0: // MULU.B Rd,#d8 - insn.itype = XA_mulu; - size = dt_byte; - break; - case 0x1: // DIVU.B Rd,#d8 - insn.itype = XA_divu; - size = dt_byte; - break; - case 0x3: // DIVU.W Rd,#d8 - insn.itype = XA_divu; - size = dt_word; - break; - case 0xB: // DIV.W Rd,#d8 - insn.itype = XA_div; - size = dt_word; - break; - default: - return 0; - } - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, insn.get_next_byte(), dt_word); - break; - case 0x9: // MUL & DIV Rd,#16 - switch ( b1 & 0xf ) - { - case 0x0: // MULU.W Rd,#d16 - insn.itype = XA_mulu; - size = dt_word; - break; - case 0x1: // DIVU.D Rd,#d16 - if ( b1&0x10 ) - return 0; - insn.itype = XA_divu; - size = dt_dword; - break; - case 0x8: // MUL.W Rd,#d16 - insn.itype = XA_mul; - size = dt_word; - break; - case 0x9: // DIV.D Rd,#d16 - if ( b1&0x10 ) - return 0; - insn.itype = XA_div; - size = dt_dword; - break; - default: - return 0; - } - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, ua_next_word_be(insn), dt_byte); - break; - case 0xD: // DIVU.D Rd,Rs - if ( b1&0x10 ) - return 0; - insn.itype = XA_divu; - op_rd(insn.Op1, b1>>4, dt_dword); - op_rd(insn.Op2, b1&0xf, dt_dword); - break; - case 0xF: // DIV.D Rd, Rs - if ( b1&0x10 ) - return 0; - insn.itype = XA_div; - op_rd(insn.Op1, b1>>4, dt_dword); - op_rd(insn.Op2, b1&0xf, dt_dword); - break; - case 0x2: // cjne direct & [Rd] & DJNZ direct - case 0xA: // cjne direct & [Rd] & DJNZ direct - size = (nibble0 < 8) ? dt_byte : dt_word; - if ( b1 & 8 ) - { // DJNZ direct, rel8 - insn.itype = XA_djnz; - op_mm(insn.Op1, ((b1&7)<<8)+(uchar)insn.get_next_byte(), size); - op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); - } - else - { // CJNE.s Rd, direct, rel8 - insn.itype = XA_cjne; - op_rd(insn.Op1, b1>>4, size); - op_mm(insn.Op2, ((b1&7)<<8)+(uchar)insn.get_next_byte(), size); - op_rel(insn, insn.Op3, (signed char)insn.get_next_byte()); - } - break; - case 0x3: // cjne #,rel - case 0xB: // cjne #,rel - if ( b1 & 7 ) - return 0; - insn.itype = XA_cjne; - size = (nibble0 < 8) ? dt_byte : dt_word; - off = insn.get_next_byte(); - if ( b1 & 0x8 ) - op_ds(insn.Op1, fRi, b1>>4, 0, size); - else - op_rd(insn.Op1, b1>>4, size); - op_im(insn.Op2, size == dt_byte ? insn.get_next_byte() : ua_next_word_be(insn), size); - op_rel(insn, insn.Op3, off); - break; - case 0xC: // JZ rel8 - insn.itype = XA_jz; - op_rel(insn, insn.Op1, (signed char)b1); - break; - case 0xE: // JNZ rel8 - insn.itype = XA_jnz; - op_rel(insn, insn.Op1, (signed char)b1); - break; - default: - return 0; - } - break; - - case 0xF: // Bxx - insn.itype = xa_branches[nibble0]; - if ( nibble0 != 0xF ) - { - op_rel(insn, insn.Op1, (signed char)insn.get_next_byte()); - } - break; - } - } - return insn.size; -} - -//---------------------------------------------------------------------- -// analyze an instruction -int xa_t::ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - - insn.itype = XA_null; - insn.Op1.dtype = dt_byte; - insn.Op2.dtype = dt_byte; - insn.Op3.dtype = dt_byte; - - switch ( ptype ) //-V785 Constant expression in switch statement - { - case prc_xaG3: - return ana_basic(insn); - } - return 0; //lint !e527 statement is unreachable -} diff --git a/idasdk75/module/xa/makefile b/idasdk75/module/xa/makefile deleted file mode 100644 index fe7b431..0000000 --- a/idasdk75/module/xa/makefile +++ /dev/null @@ -1,43 +0,0 @@ -PROC=xa - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ana.cpp ins.hpp xa.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - emu.cpp ins.hpp xa.hpp -$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.cpp ins.hpp xa.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \ - xa.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ins.hpp reg.cpp xa.hpp diff --git a/idasdk75/module/z8/emu.cpp b/idasdk75/module/z8/emu.cpp deleted file mode 100644 index c63da53..0000000 --- a/idasdk75/module/z8/emu.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Zilog Z8 module - * - */ - -#include "z8.hpp" - -//---------------------------------------------------------------------- -// Calculate the target data address -ea_t z8_t::map_addr(const insn_t &insn, asize_t off, int opnum, bool isdata) const -{ - if ( isdata ) - { - if ( is_off(get_flags(insn.ea), opnum) ) - return get_offbase(insn.ea, opnum) >> 4; - return intmem + off; - } - return map_code_ea(insn, off, opnum); -} - -//---------------------------------------------------------------------- -void z8_t::handle_operand(const insn_t &insn, const op_t &x, bool isload) -{ - switch ( x.type ) - { - case o_displ: - case o_imm: - if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) - { - int outf = x.type != o_imm ? OOF_ADDR : 0; - insn.add_off_drefs(x, dr_O, outf|OOF_SIGNED); - } - break; - - case o_mem: - case o_ind_mem: - case o_reg: - case o_ind_reg: - { - ea_t dea; - if ( x.type == o_mem || x.type == o_ind_mem ) - { - dea = map_addr(insn, x.addr, x.n, true); - } - else - { - if ( x.reg >= rRR0 ) - dea = map_addr(insn, x.reg - rRR0, x.n, true); - else - dea = map_addr(insn, x.reg - rR0, x.n, true); - } - insn.create_op_data(dea, x); - insn.add_dref(dea, x.offb, isload ? dr_R : dr_W); - if ( !has_user_name(get_flags(dea)) && dea > intmem ) - { - char buf[10]; - int num = dea - intmem; - if ( num < 0x100 ) - { - qsnprintf(buf, sizeof(buf), "R%d", num); - } - else if ( num < 0x1000 ) - { - qsnprintf(buf, sizeof(buf), "ERF_%X_%d", num >> 8, num & 0xFF); - } - else - { - int reg_no = ((num >> 4) & 0xF0) + (num & 0xF); - int subbank_no = ((num >> 4) & 0xF) + 1; - qsnprintf(buf, sizeof(buf), "R%d_%X", reg_no, subbank_no); - } - set_name(dea, buf, SN_NOCHECK|SN_NOWARN|SN_NODUMMY); - } - } - break; - - case o_near: - { - ea_t ea = map_code_ea(insn, x); - int iscall = has_insn_feature(insn.itype, CF_CALL); - insn.add_cref(ea, x.offb, iscall ? fl_CN : fl_JN); - if ( flow && iscall ) - flow = func_does_return(ea); - } - break; - - } -} - -//---------------------------------------------------------------------- -int z8_t::z8_emu(const insn_t &insn) -{ - uint32 Feature = insn.get_canon_feature(ph); - - flow = (Feature & CF_STOP) == 0; - - if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, true); - if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, true); - if ( Feature & CF_JUMP ) - remember_problem(PR_JUMP, insn.ea); - - if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false); - if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false); - - if ( flow ) - add_cref(insn.ea, insn.ea+insn.size, fl_F); - - if ( insn.itype == Z8_srp // Set register pointer - || (insn.itype == Z8_pop && insn.Op1.type == o_mem && insn.Op1.addr == 0xFD) ) // popping RP - { - // set the RP value - sel_t val = insn.itype == Z8_srp ? (insn.Op1.value & 0xFF) : BADSEL; - split_sreg_range(insn.ea + insn.size, rRp, val, SR_auto, true); - } - return 1; -} diff --git a/idasdk75/module/z8/makefile b/idasdk75/module/z8/makefile deleted file mode 100644 index 5fed7a1..0000000 --- a/idasdk75/module/z8/makefile +++ /dev/null @@ -1,43 +0,0 @@ -PROC=z8 -CONFIGS=z8.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ana.cpp ins.hpp z8.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp emu.cpp ins.hpp z8.hpp -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp out.cpp z8.hpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp ins.hpp reg.cpp z8.hpp diff --git a/idasdk75/module/z8/out.cpp b/idasdk75/module/z8/out.cpp deleted file mode 100644 index e0f5e0c..0000000 --- a/idasdk75/module/z8/out.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Zilog Z8 module - * - */ - -#include "z8.hpp" - -static const char *const phrases[] = -{ - "F", "LT", "LE", "ULE", "OV", "MI", "Z", "C", - "T", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC" -}; - -//---------------------------------------------------------------------- -inline void z8_t::out_reg(outctx_t &ctx, int rgnum) -{ - ctx.out_register(ph.reg_names[rgnum]); -} - -//-------------------------------------------------------------------------- -void z8_t::z8_header(outctx_t &ctx) -{ - ctx.gen_header(GH_PRINT_PROC_ASM_AND_BYTESEX); -} - -//-------------------------------------------------------------------------- -void z8_t::z8_footer(outctx_t &ctx) -{ - ctx.gen_empty_line(); - - ctx.out_line(ash.end, COLOR_ASMDIR); - ctx.flush_outbuf(DEFAULT_INDENT); - - ctx.gen_cmt_line("end of file"); -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -//lint -esym(818, Srange) could be made const -void z8_t::z8_segstart(outctx_t &ctx, segment_t *Srange) -{ - qstring sname; - get_visible_segm_name(&sname, Srange); - - ctx.gen_cmt_line(COLSTR("segment %s", SCOLOR_AUTOCMT), sname.c_str()); - - ea_t org = ctx.insn_ea - get_segm_base(Srange); - if ( org != 0 ) - { - char buf[MAX_NUMBUF]; - btoa(buf, sizeof(buf), org); - ctx.gen_cmt_line("%s %s", ash.origin, buf); - } -} - -//-------------------------------------------------------------------------- -//lint -esym(818, seg) could be made const -void z8_t::z8_segend(outctx_t &ctx, segment_t *seg) -{ - qstring sname; - get_visible_segm_name(&sname, seg); - ctx.gen_cmt_line("end of '%s'", sname.c_str()); -} - -//---------------------------------------------------------------------- -void idaapi out_insn(outctx_t &ctx) -{ - ctx.out_mnemonic(); - - ctx.out_one_operand(0); - - if ( ctx.insn.Op2.type != o_void ) - { - ctx.out_symbol(','); - ctx.out_char(' '); - ctx.out_one_operand(1); - } - - ctx.out_immchar_cmts(); - ctx.flush_outbuf(); -} - -//---------------------------------------------------------------------- -bool z8_t::out_opnd(outctx_t &ctx, const op_t &x) -{ - uval_t v; - - z8_t &pm = *static_cast<z8_t *>(ctx.procmod); - switch ( x.type ) - { - case o_imm: - ctx.out_symbol('#'); - ctx.out_value(x, OOFW_IMM); - break; - - case o_ind_reg: - ctx.out_symbol('@'); - // fallthrough - - case o_reg: - out_reg(ctx, x.reg); - break; - - case o_phrase: - ctx.out_keyword(phrases[x.phrase]); - break; - - case o_displ: - ctx.out_value(x, OOF_ADDR | OOFW_IMM); // x.addr - ctx.out_symbol('('); - out_reg(ctx, x.reg); - ctx.out_symbol(')'); - break; - - case o_ind_mem: - ctx.out_symbol('@'); - // fallthrough - - case o_mem: - case o_near: - v = pm.map_addr(ctx.insn, x.addr, x.n, x.type != o_near); - if ( !ctx.out_name_expr(x, v, x.addr) ) - { - const char *name = pm.find_ioport(v); - if ( name != NULL ) - { - ctx.out_line(name, COLOR_IMPNAME); - } - else - { - ctx.out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16); - remember_problem(PR_NONAME, ctx.insn.ea); - } - } - break; - - case o_void: - return 0; - - default: - warning("out: %a: bad optype %d", ctx.insn.ea, x.type); - } - - return 1; -} - -//-------------------------------------------------------------------------- -static void out_equ(outctx_t &ctx, const char *name, const char *equ, uchar off) -{ - ctx.out_line(name, COLOR_DNAME); - ctx.out_char(' '); - ctx.out_line(equ, COLOR_KEYWORD); - ctx.out_char(' '); - ctx.out_tagon(COLOR_NUMBER); - ctx.out_btoa(off); - ctx.out_tagoff(COLOR_NUMBER); - ctx.ctxflags |= CTXF_LABEL_OK; - ctx.flush_outbuf(0x80000000); -} - -//-------------------------------------------------------------------------- -void z8_t::z8_data(outctx_t &ctx, bool analyze_only) -{ - ea_t ea = ctx.insn_ea; - segment_t *s = getseg(ea); - if ( s != NULL && s->type == SEG_IMEM ) - { - qstring name; - if ( get_visible_name(&name, ea) > 0 ) - out_equ(ctx, name.begin(), ash.a_equ, uint16(ea - get_segm_base(s))); - } - else - { - ctx.out_data(analyze_only); - } -} - -//-------------------------------------------------------------------------- -//lint -esym(1764, ctx) could be made const -void z8_t::z8_assumes(outctx_t &ctx) -{ - ea_t ea = ctx.insn_ea; - segment_t *seg = getseg(ea); - if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) - return; - // always show at the start of code segments - bool seg_started = (ea == seg->start_ea) && (seg->type == SEG_CODE); - - sreg_range_t sra; - if ( !get_sreg_range(&sra, ea, rRp) ) - return; - bool show = sra.start_ea == ea; - if ( show ) - { - sreg_range_t prev_sra; - if ( get_prev_sreg_range(&prev_sra, ea, rRp) ) - show = sra.val != prev_sra.val; - } - if ( seg_started || show ) - { - sel_t rp = sra.val; - if ( rp == BADSEL ) - rp = 0; - char num[MAX_NUMBUF]; - btoa(num, sizeof(num), rp); - char nbuf[MAXSTR]; - qsnprintf(nbuf, sizeof(nbuf), COLSTR(".rp %s", SCOLOR_ASMDIR), num); - ctx.flush_buf(nbuf, DEFAULT_INDENT); - } -} diff --git a/idasdk75/module/z8/reg.cpp b/idasdk75/module/z8/reg.cpp deleted file mode 100644 index b4e1c82..0000000 --- a/idasdk75/module/z8/reg.cpp +++ /dev/null @@ -1,451 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Zilog Z8 module - * - */ - -#include "z8.hpp" -#include <diskio.hpp> - -//-------------------------------------------------------------------------- -static const char *const RegNames[] = -{ - "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", - "RR0", "RR1", "RR2", "RR3", "RR4", "RR5", "RR6", "RR7", - "RR8", "RR9", "RR10", "RR11", "RR12", "RR13", "RR14", "RR15", - "cs", "ds", "rp", -}; - -//---------------------------------------------------------------------- -typedef struct -{ - int off; - const char *name; //lint !e958 padding is required to align members - const char *cmt; -} entry_t; - -static const entry_t entries[] = -{ - { 0, "irq0", "DAV0, IRQ0, Comparator" }, - { 2, "irq1", "DAV1, IRQ1" }, - { 4, "irq2", "DAV2, IRQ2, TIN, Comparator" }, - { 6, "irq3", "IRQ3, Serial in" }, - { 8, "irq4", "T0, Serial out" }, - { 10, "irq5", "T1" }, -}; - -//---------------------------------------------------------------------- -static ea_t AdditionalSegment(size_t size, size_t offset, const char *name, const char *sclass, uchar stype) -{ - segment_t s; - s.start_ea = free_chunk(0, size, -0xF); - s.end_ea = s.start_ea + size; - s.sel = allocate_selector((s.start_ea-offset) >> 4); - s.type = stype; - add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_OR_DIE); - return s.start_ea - offset; -} - -//---------------------------------------------------------------------- -// special handling for areas -bool z8_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass) -{ - if ( start >= end ) - { - warning("Error in definition of segment %s %s", aclass, name); - return false; - } - if ( strcmp(aclass, "CODE") == 0 ) - { - AdditionalSegment(end-start, start, name, aclass, SEG_CODE); - } - else if ( strcmp(aclass, "DATA") == 0 ) - { - uchar type = stristr(name, "FSR") != NULL ? SEG_IMEM : SEG_DATA; - AdditionalSegment(end-start, start, name, aclass, type); - } - else - { - return false; - } - return true; -} - -//------------------------------------------------------------------ -const char *z8_t::find_ioport(uval_t port) -{ - const ioport_t *p = ::find_ioport(ioh.ports, port); - return p ? p->name.c_str() : NULL; -} - -//---------------------------------------------------------------------- -static ea_t specialSeg(sel_t sel, bool make_imem = true) -{ - segment_t *s = get_segm_by_sel(sel); - - if ( s != NULL ) - { - if ( make_imem && s->type != SEG_IMEM ) - { - s->type = SEG_IMEM; - s->update(); - } - return s->start_ea; - } - return BADADDR; -} - -//---------------------------------------------------------------------- -void z8_t::setup_data_segment_pointers(void) -{ - sel_t sel; - if ( atos(&sel, "INTMEM") || atos(&sel, "RAM") ) - intmem = specialSeg(sel); - else - intmem = BADADDR; -} - -//---------------------------------------------------------------------- -bool z8_t::select_device(int resp_info) -{ - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - if ( !choose_ioport_device(&ioh.device, cfgfile) ) - { - ioh.device = NONEPROC; - return false; - } - - if ( !ioh.display_infotype_dialog(IORESP_ALL, &resp_info, cfgfile) ) - return false; - - ioh.set_device_name(ioh.device.c_str(), resp_info & ~IORESP_PORT); - setup_data_segment_pointers(); - - if ( (resp_info & IORESP_PORT) != 0 ) - { - if ( intmem == BADADDR ) - { - AdditionalSegment(0x1000, 0, "INTMEM", NULL, SEG_IMEM); - setup_data_segment_pointers(); - } - for ( int i=0; i < ioh.ports.size(); i++ ) - { - const ioport_t &p = ioh.ports[i]; - ea_t ea = p.address + intmem; - ea_t oldea = get_name_ea(BADADDR, p.name.c_str()); - if ( oldea != ea ) - { - if ( oldea != BADADDR ) - set_name(oldea, NULL); - del_items(ea, DELIT_EXPAND); - set_name(ea, p.name.c_str(), SN_NODUMMY); - } - if ( !p.cmt.empty() ) - set_cmt(ea, p.cmt.c_str(), true); - } - } - return true; -} - -//-------------------------------------------------------------------------- -const char *z8_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - select_device(IORESP_PORT|IORESP_INT); - return IDPOPT_OK; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new z8_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi z8_t::on_event(ssize_t msgid, va_list va) -{ - int code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - helper.create("$ Zilog Z8"); - inf_set_be(true); // MSB first - break; - - case processor_t::ev_term: - ioh.ports.clear(); - break; - - case processor_t::ev_newfile: - { - segment_t *sptr = get_first_seg(); - if ( sptr != NULL ) - { - if ( sptr->start_ea - get_segm_base(sptr) == 0 ) - { - inf_set_start_ea(sptr->start_ea + 0xC); - inf_set_start_ip(0xC); - if ( !inf_like_binary() ) - { - // set default entries - for ( int i = 0; i < qnumber(entries); i++ ) - { - ea_t ea = sptr->start_ea + entries[i].off; - if ( is_mapped(ea) ) - { - create_word(ea, 2); - op_plain_offset(ea, 0, sptr->start_ea); - ea_t ea1 = sptr->start_ea + get_word(ea); - auto_make_proc(ea1); - set_name(ea, entries[i].name, SN_NODUMMY); - set_cmt(sptr->start_ea+get_word(ea), entries[i].cmt, 1); - } - } - } - } - set_segm_class(sptr, "CODE"); - } - - select_device(IORESP_ALL); - - if ( intmem == BADADDR ) - { - AdditionalSegment(0x1000, 0, "INTMEM", NULL, SEG_IMEM); - setup_data_segment_pointers(); - } - } - break; - - case processor_t::ev_oldfile: - ioh.restore_device(); - setup_data_segment_pointers(); - break; - - case processor_t::ev_creating_segm: - { // default DS is equal to CS - segment_t *sptr = va_arg(va, segment_t *); - sptr->defsr[rVds-ph.reg_first_sreg] = sptr->sel; - } - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - z8_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - z8_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - z8_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_out_segend: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - z8_segend(*ctx, seg); - return 1; - } - - case processor_t::ev_out_assumes: - { - outctx_t *ctx = va_arg(va, outctx_t *); - z8_assumes(*ctx); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return z8_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return z8_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_out_data: - { - outctx_t *ctx = va_arg(va, outctx_t *); - bool analyze_only = va_argi(va, bool); - z8_data(*ctx, analyze_only); - return 1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - default: - break; - } - return code; -} - -//-------------------------------------------------------------------------- -static const asm_t Z8asm = -{ - AS_COLON, - 0, - "Zilog Z8 assembler", - 0, - NULL, - ".org", - ".end", - - ";", // comment string - '\'', // string delimiter - '\0', // char delimiter (no char consts) - "\\\"'", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".byte", // byte directive - ".word", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".block %s", // uninited arrays - ".equ", // Equ - NULL, // seg prefix - "$", - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - '(', ')', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -static const asm_t *const asms[] = { &Z8asm, NULL }; - -//-------------------------------------------------------------------------- - -#define FAMILY "Zilog Z8 series:" -static const char *const shnames[] = { "Z8", NULL }; -static const char *const lnames[] = { FAMILY"Zilog Z8 MCU", NULL }; - -//-------------------------------------------------------------------------- - -static const uchar retcode[] = { 0xAF }; // ret -static const uchar iretcode[] = { 0xBF }; // iret - -static const bytes_t retcodes[] = -{ - { sizeof(retcode), retcode }, - { sizeof(iretcode), iretcode }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Processor Definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_Z8, // id - // flag - PRN_HEX - | PR_RNAMESOK // can use register names for byte names - | PR_SEGTRANS // segment translation is supported (map_code_ea) - | PR_BINMEM // The module creates RAM/ROM segments for binary files - // (the kernel shouldn't ask the user about their sizes and addresses) - | PR_SEGS // has segment registers? - | PR_SGROTHER, // the segment registers don't contain - // the segment selectors, something else - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, // short processor names (null term) - lnames, // long processor names (null term) - - asms, // array of enabled assemblers - - notify, // Various messages: - - RegNames, // Register names - qnumber(RegNames), // Number of registers - - rVcs,rRp, - 1, // size of a segment register - rVcs,rVds, - - NULL, // No known code start sequences - retcodes, - - 0, Z8_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 0, 0, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - Z8_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/z8/z8.hpp b/idasdk75/module/z8/z8.hpp deleted file mode 100644 index e92e57a..0000000 --- a/idasdk75/module/z8/z8.hpp +++ /dev/null @@ -1,118 +0,0 @@ -/* -* .org -* .word - .equ -* .end -* .ascii -* .byte -* .block - -*+ IM o_imm 12h -* Ir o_ind_reg @R1 -* r o_reg R1 -* Irr o_ind_reg @RR1 -* RR o_reg RR1 -* cond o_phrase -*+ IRR o_ind_mem @INTMEM_12 -*+ IR o_ind_mem @INTMEM_12 -*+ DA/RA o_near loc_1234 -*+ R o_mem INTMEM_12 -*+ X o_displ INTMEM_12(R1) - - * - * Interactive disassembler (IDA). - * Zilog Z8 module - * - */ - -#ifndef _Z8_HPP -#define _Z8_HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <segregs.hpp> -#include <diskio.hpp> -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -struct z8_iohandler_t : public iohandler_t -{ - z8_iohandler_t(netnode &nn) : iohandler_t(nn) {} - virtual bool area_processing(ea_t start, ea_t end, const char *name, const char *aclass) override; -}; - -struct z8_t : public procmod_t -{ - netnode helper; - z8_iohandler_t ioh = z8_iohandler_t(helper); - ea_t intmem = BADADDR; // linear EA of the internal memory/registers segment - bool flow = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *find_ioport(uval_t port); - void setup_data_segment_pointers(void); - bool select_device(int resp_info); - const char *idaapi set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/); - - // ana.cpp - int z8_ana(insn_t *insn); - - // emu.cpp - int z8_emu(const insn_t &insn); - void handle_operand(const insn_t &insn, const op_t &x, bool isload); - ea_t map_addr(const insn_t &insn, asize_t off, int opnum, bool isdata) const; - - // out.cpp - void out_reg(outctx_t &ctx, int rgnum); - bool out_opnd(outctx_t &ctx, const op_t &x); - void z8_header(outctx_t &ctx); - void z8_footer(outctx_t &ctx); - void z8_segstart(outctx_t &ctx, segment_t *seg); - void z8_segend(outctx_t &ctx, segment_t *seg); - void z8_data(outctx_t &ctx, bool analyze_only); - void z8_assumes(outctx_t &ctx); -}; - -//------------------------------------------------------------------------ -// customization of insn_t structure: - -#define o_ind_mem o_idpspec0 // @intmem -#define o_ind_reg o_idpspec1 // @Rx - -//------------------------------------------------------------------------ - -enum z8_registers -{ - rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7, - rR8, rR9, rR10, rR11, rR12, rR13, rR14, rR15, - rRR0, rRR1, rRR2, rRR3, rRR4, rRR5, rRR6, rRR7, - rRR8, rRR9, rRR10, rRR11, rRR12, rRR13, rRR14, rRR15, - rVcs, rVds, rRp, -}; - -enum z8_phrases -{ - fF, fLT, fLE, fULE, fOV, fMI, fZ, fC, - fTrue, fGE, fGT, fUGT, fNOV, fPL, fNZ, fNC -}; - -struct predefined_t -{ - uchar addr; - const char *name; - const char *cmt; -}; - -//------------------------------------------------------------------------ -inline uint16 get_rp(ea_t ea) -{ - sel_t t = get_sreg(ea, rRp); - return t != BADSEL ? t : 0; -} - -#endif diff --git a/idasdk75/module/z80/ana.cpp b/idasdk75/module/z80/ana.cpp deleted file mode 100644 index 7a78026..0000000 --- a/idasdk75/module/z80/ana.cpp +++ /dev/null @@ -1,2631 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-96 by Ilfak Guilfanov. - * ALL RIGHTS RESERVED. - * FIDO: 2:5020/209 - * E-mail: ig@estar.msk.su - * - */ - -#include "i5.hpp" - -//---------------------------------------------------------------------- -inline void GetImm(insn_t &insn, op_t &x) -{ - x.type = o_imm; - x.value = insn.get_next_byte(); -} - -//------------------------------------------------------------------------ -inline void op_c(op_t &x) -{ - x.type = o_phrase; - x.phrase = R_c; -} - -//------------------------------------------------------------------------ -static void op_ad(insn_t &insn, op_t &x) -{ - x.type = o_near; - x.addr = insn.get_next_word(); -} - -static void op_a(op_t &x); -static void op_e(insn_t &insn, op_t &x); -static void op_nn(insn_t &insn, op_t &x); -static void op_ad(insn_t &insn, op_t &x); -static void op_n(insn_t &insn, op_t &x); -static void op_mm(insn_t &insn, op_t &x); - -static const uint16 W [] = { I5_add,I5_adc,I5_sub,I5_sbb,I5_ana,I5_xra,I5_ora,I5_cmp }; -static const uint16 Wi [] = { I5_adi,I5_aci,I5_sui,I5_sbi,I5_ani,I5_xri,I5_ori,I5_cpi }; -static const uint16 calls[] = { I5_cnz,I5_cz, I5_cnc,I5_cc, I5_cpo,I5_cpe,I5_cp, I5_cm }; -static const uint16 jumps[] = { I5_jnz,I5_jz, I5_jnc,I5_jc, I5_jpo,I5_jpe,I5_jp, I5_jm }; -static const uint16 rets [] = { I5_rnz,I5_rz, I5_rnc,I5_rc, I5_rpo,I5_rpe,I5_rp, I5_rm }; -static const uint16 rols [] = { I5_rlc,I5_rrc,I5_ral,I5_rar,I5_daa,I5_cma,I5_stc,I5_cmc }; -static const uint16 CBrols[]= { Z80_rlc,Z80_rrc,Z80_rl,Z80_rr,Z80_sla,Z80_sra,Z80_srr,Z80_srl }; -static const uint16 Zrols[] = { Z80_rlca,Z80_rrca,Z80_rla,Z80_rra,I5_daa,Z80_cpl,Z80_scf,Z80_ccf }; - -//---------------------------------------------------------------------- -static void ConvertToFunny(insn_t &insn) -{ - switch ( insn.itype ) - { - case I5_mov: - insn.Op1.set_shown(); - insn.Op2.set_shown(); - if ( insn.Op1.type == o_reg && insn.Op2.type == o_mem ) - { - switch ( insn.Op1.reg ) - { - case R_bc: - insn.itype = A80_lbcd; - insn.Op1.clr_shown(); - break; - case R_de: - insn.itype = A80_lded; - insn.Op1.clr_shown(); - break; - case R_sp: - insn.itype = A80_lspd; - insn.Op1.clr_shown(); - break; - case R_ix: - insn.itype = A80_lixd; - insn.Op1.clr_shown(); - break; - case R_iy: - insn.itype = A80_liyd; - insn.Op1.clr_shown(); - break; - } - } - if ( insn.Op1.type == o_mem && insn.Op2.type == o_reg ) - { - switch ( insn.Op2.reg ) - { - case R_bc: - insn.itype = A80_sbcd; - insn.Op2.clr_shown(); - break; - case R_de: - insn.itype = A80_sded; - insn.Op2.clr_shown(); - break; - case R_sp: - insn.itype = A80_sspd; - insn.Op2.clr_shown(); - break; - case R_ix: - insn.itype = A80_sixd; - insn.Op2.clr_shown(); - break; - case R_iy: - insn.itype = A80_siyd; - insn.Op2.clr_shown(); - break; - } - } - if ( insn.Op1.type == o_reg && insn.Op2.type == o_reg ) - { - switch ( insn.Op1.reg ) - { - case R_sp: - if ( insn.Op2.reg == R_ix ) - { - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - insn.itype = A80_spix; - } - if ( insn.Op2.reg == R_iy ) - { - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - insn.itype = A80_spiy; - } - break; - case R_r: - insn.itype = A80_mvra; - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - break; - case R_i: - insn.itype = A80_mvia; - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - break; - case R_a: - if ( insn.Op2.reg == R_r ) - { - insn.itype = A80_mvar; - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - } - if ( insn.Op2.reg == R_i ) - { - insn.itype = A80_mvai; - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - } - break; - } - } - break; /* mov */ - case Z80_jp: - if ( insn.Op2.type == o_phrase && insn.Op2.phrase == R_ix ) - { - insn.itype = A80_pcix; - insn.Op2.clr_shown(); - break; - } - if ( insn.Op2.type == o_phrase && insn.Op2.phrase == R_iy ) - { - insn.itype = A80_pciy; - insn.Op2.clr_shown(); - break; - } - break; /* jp */ - case Z80_ex: - insn.Op1.clr_shown(); - insn.Op2.clr_shown(); - if ( insn.Op2.reg == R_ix ) - insn.itype = A80_xtix; - if ( insn.Op2.reg == R_iy ) - insn.itype = A80_xtiy; - break; /* ex */ - case I5_in: - if ( insn.Op2.type == o_phrase && insn.Op2.reg == R_c ) - { - insn.itype = Z80_inp; - insn.Op2.clr_shown(); - } - break; - case I5_out: - if ( insn.Op1.type == o_phrase && insn.Op1.reg == R_c ) - { - insn.itype = Z80_outp; - insn.Op1.clr_shown(); - } - break; - case Z80_cpl: - insn.itype = I5_cma; - break; - case Z80_scf: - insn.itype = I5_stc; - break; - case Z80_ccf: - insn.itype = I5_cmc; - break; - case I5_add: - if ( insn.Op1.type == o_reg && insn.Op1.reg == R_ix ) - { - insn.itype = A80_addix; - insn.Op1.clr_shown(); - if ( insn.Op2.type == o_reg && insn.Op2.reg == R_ix ) - insn.Op2.reg = R_hl; - break; - } - if ( insn.Op1.type == o_reg && insn.Op1.reg == R_iy ) - { - insn.itype = A80_addiy; - insn.Op1.clr_shown(); - if ( insn.Op2.type == o_reg && insn.Op2.reg == R_iy ) - insn.Op2.reg = R_hl; - break; - } - break; - case I5_adc: - if ( insn.Op1.dtype == dt_word && insn.Op1.type == o_reg ) - { - insn.itype = A80_addc; - insn.Op1.clr_shown(); - if ( insn.Op1.reg == R_ix ) - insn.itype = A80_addcix; - if ( insn.Op1.reg == R_iy ) - insn.itype = A80_addciy; - if ( insn.Op2.type == o_reg && insn.Op1.reg == insn.Op2.reg ) - insn.Op2.reg = R_hl; - } - break; - case Z80_sbc: - if ( insn.Op1.dtype == dt_word && insn.Op1.type == o_reg ) - { - insn.itype = A80_subc; - insn.Op1.clr_shown(); - if ( insn.Op1.reg == R_ix ) - insn.itype = A80_subcix; - if ( insn.Op1.reg == R_iy ) - insn.itype = A80_subciy; - if ( insn.Op2.type == o_reg && insn.Op1.reg == insn.Op2.reg ) - insn.Op2.reg = R_hl; - } - break; - case Z80_jr: - insn.Op1.clr_shown(); - switch ( insn.Op1.Cond ) - { - case oc_c: insn.itype = A80_jrc; break; - case oc_nc: insn.itype = A80_jrnc; break; - case oc_z: insn.itype = A80_jrz; break; - case oc_nz: insn.itype = A80_jrnz; break; - } - break; - case Z80_rrca: insn.itype = I5_rrc; break; - case Z80_rlca: insn.itype = I5_rlc; break; - case Z80_rla: insn.itype = I5_ral; break; - case Z80_rl: insn.itype = I5_ral; break; - case Z80_rra: insn.itype = I5_rar; break; - case Z80_rr: insn.itype = I5_rar; break; - case Z80_cpi: insn.itype = A80_cmpi; break; - case Z80_cpd: insn.itype = A80_cmpd; break; - case Z80_outi: insn.itype = A80_oti; break; - case Z80_outd: insn.itype = A80_otd; break; - case Z80_inc: insn.itype = I5_inr; break; - case Z80_dec: insn.itype = I5_dcr; break; - case Z80_im: - if ( insn.Op1.value == 0 ) - insn.itype = A80_im0; - else if ( insn.Op1.value == 1 ) - insn.itype = A80_im1; - else - insn.itype = A80_im2; - insn.Op1.clr_shown(); - break; - } -} - -//---------------------------------------------------------------------- -void z80_t::ConvertToZ80(insn_t &insn) -{ - uint16 cc; - if ( insn.itype < Z80_and ) - { - insn.Op1.set_shown(); - insn.Op2.set_shown(); - } - switch ( insn.itype ) - { - case I5_aci: - insn.itype = I5_adc; - break; - case I5_adi: - case I5_dad: - insn.itype = I5_add; - break; - case I5_cmp: - case I5_cpi: - insn.itype = Z80_cp; - if ( !isZ380() ) - insn.Op1.clr_shown(); - break; - case I5_ana: - case I5_ani: - insn.itype = Z80_and; - if ( !isZ380() ) - insn.Op1.clr_shown(); - break; - case I5_ora: - case I5_ori: - insn.itype = Z80_or; - if ( !isZ380() ) - insn.Op1.clr_shown(); - break; - case I5_xra: - case I5_xri: - insn.itype = Z80_xor; - if ( !isZ380() ) - insn.Op1.clr_shown(); - break; - case I5_sbi: - case I5_sbb: - insn.itype = Z80_sbc; - break; - case I5_sui: - case I5_sub: - insn.itype = I5_sub; - if ( !isZ380() ) - insn.Op1.clr_shown(); - break; - case I5_dcr: - case I5_dcx: - insn.itype = Z80_dec; - break; - case I5_inr: - case I5_inx: - insn.itype = Z80_inc; - break; - case I5_halt: - insn.itype = Z80_halt; - break; - case I5_sphl: - case I5_mov: - case I5_mvi: - case I5_ldax: - case I5_lxi: - case I5_lhld: - case I5_shld: - case I5_sta: - case I5_stax: - case I5_lda: - insn.itype = Z80_ld; - break; - case I5_xchg: - case I5_xthl: - insn.itype = Z80_ex; - break; - case I5_pchl: - insn.Op1.type = o_phrase; - insn.Op1.reg = R_hl; - cc = oc_not; - goto zjump; - - case I5_call: cc = oc_not;goto zcall; - case I5_cnz: cc = oc_nz; goto zcall; - case I5_cz: cc = oc_z; goto zcall; - case I5_cnc: cc = oc_nc; goto zcall; - case I5_cc: cc = oc_c; goto zcall; - case I5_cpo: cc = oc_po; goto zcall; - case I5_cpe: cc = oc_pe; goto zcall; - case I5_cp: cc = oc_p; goto zcall; - case I5_cm: cc = oc_m; goto zcall; - case I5_jmp: cc = oc_not;goto zjump; - case I5_jnz: cc = oc_nz; goto zjump; - case I5_jz: cc = oc_z; goto zjump; - case I5_jnc: cc = oc_nc; goto zjump; - case I5_jc: cc = oc_c; goto zjump; - case I5_jpo: cc = oc_po; goto zjump; - case I5_jpe: cc = oc_pe; goto zjump; - case I5_jp: cc = oc_p; goto zjump; - case I5_jm: cc = oc_m; goto zjump; - case I5_ret: cc = oc_not;goto zret; - case I5_rnz: cc = oc_nz; goto zret; - case I5_rz: cc = oc_z; goto zret; - case I5_rnc: cc = oc_nc; goto zret; - case I5_rc: cc = oc_c; goto zret; - case I5_rpo: cc = oc_po; goto zret; - case I5_rpe: cc = oc_pe; goto zret; - case I5_rp: cc = oc_p; goto zret; - case I5_rm: cc = oc_m; goto zret; - -zret: - insn.itype = Z80_ret; - goto zcc; -zjump: - insn.itype = Z80_jp; - goto zcc; -zcall: - insn.itype = Z80_call; - goto zcc; -zcc: - insn.Op2 = insn.Op1; - insn.Op2.n = 1; - insn.Op1.type = o_cond; - insn.Op1.Cond = cc; - break; - - } -} - -//---------------------------------------------------------------------- -static bool is_gameboy_insn(const insn_t &insn) -{ - switch ( insn.itype ) - { - case Z80_adc: - case Z80_add: - case Z80_and: - case Z80_bit: - case Z80_call: - case Z80_ccf: - case Z80_cp: - case Z80_cpl: - case I5_daa: - case Z80_dec: - case Z80_di: - case Z80_ei: - case Z80_halt: - case Z80_inc: - case Z80_jp: - case Z80_jr: - case Z80_ld: - case Z80_ldd: - case GB_ldh: - case Z80_ldi: - case I5_nop: - case Z80_or: - case Z80_pop: - case Z80_push: - case Z80_res: - case Z80_ret: - case Z80_reti: - case Z80_rl: - case Z80_rla: - case Z80_rlc: - case Z80_rlca: - case Z80_rr: - case Z80_rra: - case Z80_rrc: - case Z80_rrca: - case I5_rst: - case Z80_sbc: - case Z80_scf: - case Z80_set: - case Z80_sla: - case Z80_sra: - case Z80_srl: - case GB_stop: - case Z80_sub: - case Z80_swap: - case Z80_xor: - break; - default: - return false; - } - return true; -} - -//---------------------------------------------------------------------- -static void swap_operands(insn_t &insn) -{ - op_t op = insn.Op1; - insn.Op1 = insn.Op2; - insn.Op2 = op; -} - -//---------------------------------------------------------------------- -int z80_t::i5_ana(insn_t *_insn) -{ - insn_t &insn = *_insn; - - insn.Op1.dtype = dt_byte; - insn.Op2.dtype = dt_byte; - insn.itype = I5_null; - - code = insn.get_next_byte(); - - switch ( code & 0xC0 ) - { - case 0x00: - switch ( code & 0xF ) - { - case 0: - case 8: - { - int sub = ( code >> 3 ) & 7; - switch ( sub ) - { - case 0: - insn.itype = I5_nop; - break; - case 1: // 08 - if ( isGB() ) // 08 bb aa LD ($aabb),SP - { - insn.itype = Z80_ld; - op_mm(insn, insn.Op1); - insn.Op1.dtype = dt_word; - insn.Op2.type = o_reg; - insn.Op2.reg = R_sp; - } - else if ( isZ80() ) - { - insn.itype = Z80_ex; - insn.Op1.type = o_reg; - insn.Op1.reg = R_af; - insn.Op2.type = o_reg; - insn.Op2.reg = R_af2; - } - else - { - insn.itype = I5_dsub; // undoc - } - break; - case 2: // 10 - if ( isGB() ) // 10 00 STOP - { - if ( insn.get_next_byte() ) - return 0; - insn.itype = GB_stop; - } - else if ( isZ80() ) - { - insn.itype = Z80_djnz; - op_e(insn, insn.Op1); - } - else - { - insn.itype = I5_arhl; // undoc - } - break; - case 3: // 18 - if ( isZ80() ) - { -Z80_COMMON: - static const uint16 conds[] = { 0,1,2,oc_not,oc_nz,oc_z,oc_nc,oc_c }; - insn.Op1.Cond = conds[sub]; - insn.itype = Z80_jr; - insn.Op1.type = o_cond; - op_e(insn, insn.Op2); - break; - } - insn.itype = I5_rdel; // undoc - break; - case 4: // 20 - if ( isZ80() ) - goto Z80_COMMON; - insn.itype = I5_rim; - break; - case 5: // 28 - if ( isZ80() ) - goto Z80_COMMON; - insn.itype = I5_ldhi; // undoc - GetImm(insn, insn.Op1); - break; - case 6: // 30 - if ( isZ80() ) - goto Z80_COMMON; - insn.itype = I5_sim; - break; - case 7: // 38 - if ( isZ80() ) - goto Z80_COMMON; - insn.itype = I5_ldsi; - GetImm(insn, insn.Op1); - break; - } - } - break; - case 1: - insn.itype = I5_lxi; - op_ss(insn.Op1); - op_nn(insn, insn.Op2); - break; - - case 9: - insn.itype = I5_dad; - insn.Op1.reg = R_hl; - insn.Op1.dtype = dt_word; - insn.Op1.type = o_reg; - insn.Op1.clr_shown(); - op_ss(insn.Op2); - break; - case 0xA: - if ( (code & 0x20) == 0 ) - { - insn.itype = I5_ldax; - insn.Op2.type = o_phrase; - insn.Op2.phrase = R_bc + ((code >> 4) & 1); - op_a(insn.Op1); - } - else - { - if ( isGB() ) - { - insn.itype = (code & 0x10) ? Z80_ldd : Z80_ldi; - insn.Op1.type = o_reg; - insn.Op1.reg = R_a; - insn.Op2.type = o_phrase; - insn.Op2.phrase = R_hl; - break; - } - insn.Op1.type = o_reg; - if ( (code & 0x10) == 0 ) - { - insn.itype = I5_lhld; - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - insn.Op1.reg = R_hl; - } - else - { - insn.itype = I5_lda; - insn.Op1.reg = R_a; - } - op_mm(insn, insn.Op2); - } - insn.Op1.clr_shown(); - break; - case 2: - if ( (code & 0x20) == 0 ) - { - insn.itype = I5_stax; - insn.Op1.type = o_phrase; - insn.Op1.phrase = R_bc + ((code >> 4) & 1); - op_a(insn.Op2); - } - else - { - if ( isGB() ) - { - insn.itype = (code & 0x10) ? Z80_ldd : Z80_ldi; - insn.Op1.type = o_phrase; - insn.Op1.phrase = R_hl; - insn.Op2.type = o_reg; - insn.Op2.reg = R_a; - break; - } - insn.Op2.type = o_reg; - if ( (code & 0x10) == 0 ) - { - insn.itype = I5_shld; - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - insn.Op2.reg = R_hl; - } - else - { - insn.itype = I5_sta; - insn.Op2.reg = R_a; - } - op_mm(insn, insn.Op1); - } - insn.Op2.clr_shown(); - break; - case 3: - insn.itype = I5_inx; - op_ss(insn.Op1); - break; - case 0xB: - insn.itype = I5_dcx; - op_ss(insn.Op1); - break; - case 4: - case 0xC: - insn.itype = I5_inr; - op_r1(insn.Op1); - break; - case 5: - case 0xD: - insn.itype = I5_dcr; - op_r1(insn.Op1); - break; - case 6: - case 0xE: - insn.itype = I5_mvi; - op_r1(insn.Op1); - op_n (insn, insn.Op2); - break; - case 7: - case 0xF: - insn.itype = (isZ80() ? Zrols : rols)[ (code >> 3) & 7 ]; - break; - } - break; - case 0x40: - insn.itype = I5_halt; - if ( code != 0x76 ) - { - insn.itype = I5_mov; - op_r1(insn.Op1); - op_r2(insn.Op2); - } - break; - case 0x80: - op_r2(insn.Op2); -common: - insn.Op1.type = o_reg; - insn.Op1.reg = R_a; - insn.itype = (insn.Op2.type == o_imm ? Wi : W)[ (code >> 3) & 7 ]; - insn.Op1.clr_shown(); - break; - case 0xC0: /* 11?????? */ - switch ( code & 0xF ) - { - case 0x0: - case 0x8: /* 11???000 */ - if ( isGB() ) - { - switch ( code ) - { - case 0xE0: - case 0xF0: - insn.itype = Z80_ld; - insn.Op1.type = o_mem; - insn.Op1.addr = 0xFF00 + insn.get_next_byte(); - insn.Op2.type = o_reg; - insn.Op2.reg = R_a; - if ( code & 0x10 ) - swap_operands(insn); - break; - case 0xE8: - insn.itype = Z80_add; - insn.Op1.type = o_reg; - insn.Op1.reg = R_sp; - GetImm(insn, insn.Op2); - break; - case 0xF8: // docs say this is "ld hl, sp" - // Daniel Filner <danf@codefrog.cx> says - // this is "ld hl, sp+immbyte" - insn.itype = Z80_ld; - insn.Op1.type = o_reg; - insn.Op1.reg = R_hl; - insn.Op2.type = o_displ; - insn.Op2.phrase = R_sp; - insn.Op2.addr = insn.get_next_byte(); - break; - default: - goto RETS; - } - break; - } -RETS: - insn.itype = rets[ (code >> 3) & 7 ]; - break; - case 0x2: - case 0xA: /* 11???010 */ - if ( isGB() ) - { - switch ( code ) - { - case 0xE2: - case 0xF2: - insn.itype = Z80_ld; - insn.auxpref |= aux_off16; - op_c(insn.Op1); - insn.Op2.type = o_reg; - insn.Op2.reg = R_a; - if ( code & 0x10 ) - swap_operands(insn); - break; - case 0xEA: - case 0xFA: - insn.itype = Z80_ld; - op_mm(insn, insn.Op1); - insn.Op2.type = o_reg; - insn.Op2.reg = R_a; - if ( code & 0x10 ) - swap_operands(insn); - break; - default: - goto JUMPS; - } - break; - } -JUMPS: - insn.itype = jumps[ (code >> 3) & 7 ]; - op_ad(insn, insn.Op1); - break; - case 0x3: - case 0xB: /* 11???011 */ - switch ( ( code >> 3 ) & 7 ) - { - case 0: /* 11000011=C3 */ - insn.itype = I5_jmp; - op_ad(insn, insn.Op1); - break; - case 1: // 11001011=CB - Z80 extensions - if ( isZ80() ) - { - code = insn.get_next_byte(); - int fn = (code>>6); - if ( fn == 0 ) - { - op_r2(insn.Op1); - insn.itype = CBrols[ (code>>3) & 7 ]; - if ( insn.itype == Z80_srr ) - { - if ( isZ380() ) - { - insn.itype = Z80_ex; - op_r2(insn.Op2); - insn.Op2.reg += R_b2; - } - else if ( isGB() ) - { - insn.itype = Z80_swap; - } - } - } - else - { - static const uint16 brs[] = { 0, Z80_bit,Z80_res,Z80_set }; - insn.itype = brs[fn]; - insn.Op1.type = o_imm; - insn.Op1.value = (code>>3) & 7; - op_r2(insn.Op2); - } - } - else - { - insn.itype = I5_rstv; // undoc - } - break; - case 2: /* 11010011=D3 */ - insn.itype = I5_out; - op_a(insn.Op2); - op_n(insn, insn.Op1); - break; - case 3: // DB - insn.itype = I5_in; - op_a(insn.Op1); - op_n(insn, insn.Op2); - break; - case 4: // E3 - insn.itype = I5_xthl; - insn.Op1.type = o_phrase; - insn.Op1.reg = R_sp; - insn.Op1.clr_shown(); - insn.Op2.type = o_reg; - insn.Op2.reg = R_hl; - insn.Op2.clr_shown(); - break; - case 5: // EB - insn.itype = I5_xchg; - insn.Op1.type = o_reg; - insn.Op1.reg = R_de; - insn.Op1.clr_shown(); - insn.Op2.type = o_reg; - insn.Op2.reg = R_hl; - insn.Op2.clr_shown(); - break; - case 6: // F3 - insn.itype = I5_di; - break; - case 7: // FB - insn.itype = I5_ei; - break; - } - break; - case 0x4: - case 0xC: /* 11???100 */ - insn.itype = calls[ (code >> 3) & 7 ]; - op_ad(insn, insn.Op1); - break; - case 0x1: - case 0x5: // 11????01 - insn.itype = (code & 4) ? I5_push : I5_pop; - op_dd(insn.Op1); - break; - case 0x6: - case 0xE: // 11???110 - op_n(insn, insn.Op2); - goto common; - case 0x7: - case 0xF: // 11???111 - insn.itype = I5_rst; - insn.Op1.type = o_imm; - insn.Op1.value = (code >> 3) & 7; - if ( isZ80() ) - { // workaround for bcb6 bug: - uval_t x = insn.Op1.value; - x <<= 3; - insn.Op1.value = x; - } - break; - case 0x9: - switch ( (code >> 4) & 3 ) - { - case 0: - insn.itype = I5_ret; // 11001001 = C9 - break; - case 1: // 11011001 = D9 - if ( isGB() ) - insn.itype = Z80_reti; - else if ( isZ80() ) - insn.itype = Z80_exx; - else - insn.itype = I5_shlx; // undoc - break; - case 2: - insn.itype = I5_pchl; - break; - case 3: - insn.itype = I5_sphl; - insn.Op1.type = o_reg; - insn.Op1.reg = R_sp; - insn.Op1.clr_shown(); - insn.Op2.type = o_reg; - insn.Op2.reg = R_hl; - insn.Op2.clr_shown(); - break; - } - break; - case 0xD: /* 11??1101 */ - switch ( (code >> 4) & 3 ) - { - case 0: - insn.itype = I5_call; - op_ad(insn, insn.Op1); - break; - case 1: // 11011101 = DD - Z80 extensions - if ( is8085() ) - { - insn.itype = I5_jnx5; // undoc - op_ad(insn, insn.Op1); - } - else - { - z80_ixcommands(insn, true); - } - break; - case 2: // 11101101 = ED - Z80 extensions - if ( isGB() ) - return 0; - else if ( isZ380() ) - z380_ED(insn); - else if ( is8085() ) - insn.itype = I5_lhlx; // undoc - else - z80_misc(insn); - break; - case 3: // 11111101 = FD - Z80 extensions - if ( is8085() ) - { - insn.itype = I5_jx5; // undoc - op_ad(insn, insn.Op1); - } - else - { - z80_ixcommands(insn, false); - } - break; - } - break; - } - break; - } - - if ( insn.itype == I5_null ) - return 0; - - if ( isZ80() ) - { - if ( ash.uflag & UAS_FUNNY ) - ConvertToFunny(insn); - else - ConvertToZ80(insn); - if ( isGB() && !is_gameboy_insn(insn) ) - return 0; - } - - return insn.size; - -} - -//------------------------------------------------------------------------ -void z80_t::op_r1(op_t &x) const -{ - uint16 mode = (code >> 3) & 7; - if ( mode == 6 ) - { - x.type = o_phrase; - x.phrase = R_hl; - } - else - { - x.type = o_reg; - x.reg = mode; - } -} - -//------------------------------------------------------------------------ -void z80_t::op_r2(op_t &x) const -{ - uint16 mode = code & 7; - if ( mode == 6 ) - { - x.type = o_phrase; - x.phrase = R_hl; - } - else - { - x.type = o_reg; - x.reg = mode; - } -} - -//------------------------------------------------------------------------ -void z80_t::op_ss(op_t &x) const -{ - uint16 ss = (code >> 4) & 3; - x.type = o_reg; - x.dtype = dt_word; - x.reg = ss + R_bc; - if ( ss == 3 ) - x.reg = R_sp; -} - -//------------------------------------------------------------------------ -void z80_t::op_dd(op_t &x) const -{ - uint16 ss = (code >> 4) & 3; - x.type = o_reg; - x.dtype = dt_word; - x.reg = ss + R_bc; -} - -//------------------------------------------------------------------------ -static void op_nn(insn_t &insn, op_t &x) -{ - x.type = o_imm; - x.dtype = dt_word; - x.value = insn.get_next_word(); -} - -//------------------------------------------------------------------------ -static void op_n(insn_t &insn, op_t &x) -{ - x.type = o_imm; - x.value = insn.get_next_byte(); -} - -//------------------------------------------------------------------------ -static void op_e(insn_t &insn, op_t &x) -{ - x.type = o_near; - sval_t rel = char(insn.get_next_byte()); - x.addr = ushort(insn.ip + insn.size + rel); -} - -//------------------------------------------------------------------------ -static void op_a(op_t &x) -{ - x.type = o_reg; - x.reg = R_a; - x.clr_shown(); -} - -//------------------------------------------------------------------------ -static void op_mm(insn_t &insn, op_t &x) -{ - x.type = o_mem; - x.addr = insn.get_next_word(); -} - -//------------------------------------------------------------------------ -static void op_f(op_t &x) -{ - x.type = o_reg; - x.dtype = dt_byte; - x.reg = R_f; -} - -//------------------------------------------------------------------------ -void z80_t::op_xdispl(insn_t &insn, op_t &x) const -{ - x.type = o_displ; - x.phrase = isx ? R_ix : R_iy; - x.addr = insn.get_next_byte(); -} - -//------------------------------------------------------------------------ -void z80_t::op_ix(op_t &x) const -{ - x.type = o_reg; - x.reg = isx ? R_ix : R_iy; - x.dtype = dt_word; -} - -//------------------------------------------------------------------------ -void z80_t::op_ibyte(op_t &x,int low) const -{ - x.type = o_reg; - x.reg = isx - ? (low ? R_xl : R_xh) - : (low ? R_yl : R_yh); -} - -//------------------------------------------------------------------------ -int z80_t::op_xbytereg(op_t &x,uint16 mode) const -{ - if ( mode == 6 ) - { - x.type = o_phrase; - x.phrase = R_hl; - return 1; - } - else - { - if ( mode == R_h ) - { - op_ibyte(x,0); - } - else if ( mode == R_l ) - { - op_ibyte(x,1); - } - else - { - x.type = o_reg; - x.reg = mode; - } - return 0; - } -} - -//------------------------------------------------------------------------ -int z80_t::op_xr1(op_t &x) const -{ - return op_xbytereg(x,(code >> 3) & 7); -} - -//------------------------------------------------------------------------ -int z80_t::op_xr2(op_t &x) const -{ - return op_xbytereg(x,code & 7); -} - -//------------------------------------------------------------------------ -struct insndesc_t -{ - uchar code; - ushort itype; //lint !e958 padding is required to align members - uchar op1; - uchar op2; -}; - -#define rA (R_a+1) -#define rB (R_b+1) -#define rC (R_c+1) -#define rD (R_d+1) -#define rE (R_e+1) -#define rH (R_h+1) -#define rL (R_l+1) -#define rI (R_i+1) -#define rW (R_w+1) -#define rR (R_r+1) -#define rBC (R_bc+1) -#define rDE (R_de+1) -#define rHL (R_hl+1) -#define rIX (R_ix+1) -#define rIY (R_iy+1) -#define rSP (R_sp+1) -#define rLW (R_lw+1) -#define rIXL (R_ixl+1) -#define rIXU (R_ixu+1) -#define rDSR (R_dsr+1) -#define rXSR (R_xsr+1) -#define rIYL (R_iyl+1) -#define rIYU (R_iyu+1) -#define rYSR (R_ysr+1) -#define rSR (R_sr+1) -#define rIB (R_ib+1) -#define rIW (R_iw+1) -#define rXM (R_xm+1) -#define rLCK (R_lck+1) -#define rBC2 (R_bc2+1) -#define rDE2 (R_de2+1) -#define rHL2 (R_hl2+1) -#define rIX2 (R_ix2+1) -#define rIY2 (R_iy2+1) - -#define atBC 0x30 -#define atDE 0x31 -#define atHL 0x32 -#define atSP 0x33 -#define atIX 0x34 -#define atIY 0x35 -#define atC 0x36 -#define rip8 0x37 // ip relative displ 8bits -#define rip16 0x38 // ip relative displ 16bits -#define rip24 0x39 // ip relative displ 24bits -#define imm8 0x3A // 8bit immval -#define imm16 0x3B // 16bit immval -#define mem16 0x3C // (1234h) - -#define ix8 0x40 // (IX+12) -#define iy8 0x41 // (IY+12) -#define ixs 0x42 // (IX+saved_value) -#define iys 0x43 // (IY+saved_value) -#define sps 0x44 // (SP+saved_value) - -// condition codes -#define ccNZ 0x50 -#define ccZ 0x51 -#define ccNC 0x52 -#define ccC 0x53 -#define ccPO 0x54 -#define ccPE 0x55 -#define ccP 0x56 -#define ccM 0x57 - -#define c0 0x60 -#define c1 0x61 -#define c2 0x62 -#define c3 0x63 -#define c4 0x64 -#define c5 0x65 -#define c6 0x66 -#define c7 0x67 - -static const insndesc_t cmdsDD[] = -{ - { 0x01, Z80_ld, atBC, rIX }, - { 0x02, Z80_ld, rBC, rDE }, - { 0x03, Z80_ld, rIX, atBC }, - { 0x07, Z80_ld, rIX, rBC }, - { 0x09, Z80_add, rIX, rBC }, - { 0x0B, Z80_ld, rBC, rIX }, - { 0x0C, Z80_ld, rBC, atBC }, - { 0x0D, Z80_ld, rBC, atDE }, - { 0x0F, Z80_ld, rBC, atHL }, - { 0x10, Z80_djnz, rip16 }, - { 0x11, Z80_ld, atDE, rIX }, - { 0x12, Z80_ld, rDE, rDE }, - { 0x13, Z80_ld, rIX, atDE }, - { 0x17, Z80_ld, rIX, rDE }, - { 0x18, Z80_jr, rip16 }, - { 0x19, Z80_add, rIX, rDE }, - { 0x1B, Z80_ld, rDE, rIX }, - { 0x1C, Z80_ld, rDE, atBC }, - { 0x1D, Z80_ld, rDE, atDE }, - { 0x1F, Z80_ld, rDE, atHL }, - { 0x20, Z80_jr, ccNZ, rip16 }, - { 0x21, Z80_ld, rIX, imm16 }, - { 0x22, Z80_ld, mem16, rIX }, - { 0x23, Z80_inc, rIX }, - { 0x24, Z80_inc, rIXU }, - { 0x25, Z80_dec, rIXU }, - { 0x26, Z80_ld, rIXU, imm8 }, - { 0x27, Z80_ld, rIX, rIY }, - { 0x28, Z80_jr, ccZ, rip16 }, - { 0x29, Z80_add, rIX, rIX }, - { 0x2A, Z80_ld, rIX, mem16 }, - { 0x2B, Z80_dec, rIX }, - { 0x2C, Z80_inc, rIXL }, - { 0x2D, Z80_dec, rIXL }, - { 0x2E, Z80_ld, rIXL, imm8 }, - { 0x2F, Z80_cplw, rHL }, - { 0x30, Z80_jr, ccNC, rip16 }, - { 0x31, Z80_ld, atHL, rIX }, - { 0x32, Z80_ld, rHL, rDE }, - { 0x33, Z80_ld, rIX, atHL }, - { 0x34, Z80_inc, ix8 }, - { 0x35, Z80_dec, ix8 }, - { 0x36, Z80_ld, ix8, imm8 }, - { 0x37, Z80_ld, rIX, rHL }, - { 0x38, Z80_jr, ccC, rip16 }, - { 0x39, Z80_add, rIX, rSP }, - { 0x3B, Z80_ld, rHL, rIX }, - { 0x3C, Z80_ld, rHL, atBC }, - { 0x3D, Z80_ld, rHL, atDE }, - { 0x3E, Z80_swap, rIX }, - { 0x3F, Z80_ld, rHL, atHL }, - { 0x40, Z80_inw, rBC, atC }, - { 0x41, Z80_outw, atC, rBC }, - { 0x44, Z80_ld, rB, rIXU }, - { 0x45, Z80_ld, rB, rIXL }, - { 0x46, Z80_ld, rB, ix8 }, - { 0x47, Z80_ldw, rI, rHL }, - { 0x4C, Z80_ld, rC, rIXU }, - { 0x4D, Z80_ld, rC, rIXL }, - { 0x4E, Z80_ld, rC, ix8 }, - { 0x50, Z80_inw, rDE, atC }, - { 0x51, Z80_outw, atC, rDE }, - { 0x54, Z80_ld, rD, rIXU }, - { 0x55, Z80_ld, rD, rIXL }, - { 0x56, Z80_ld, rD, ix8 }, - { 0x57, Z80_ldw, rHL, rI }, - { 0x5D, Z80_ld, rE, rIXL }, - { 0x5E, Z80_ld, rE, ix8 }, - { 0x60, Z80_ld, rIXU, rB }, - { 0x61, Z80_ld, rIXU, rC }, - { 0x62, Z80_ld, rIXU, rD }, - { 0x63, Z80_ld, rIXU, rE }, - { 0x64, Z80_ld, rIXU, rIXU }, - { 0x65, Z80_ld, rIXU, rIXL }, - { 0x66, Z80_ld, rH, ix8 }, - { 0x67, Z80_ld, rIXU, rA }, - { 0x68, Z80_ld, rIXL, rB }, - { 0x69, Z80_ld, rIXL, rC }, - { 0x6A, Z80_ld, rIXL, rD }, - { 0x6B, Z80_ld, rIXL, rE }, - { 0x6C, Z80_ld, rIXL, rIXU }, - { 0x6D, Z80_ld, rIXL, rIXL }, - { 0x6E, Z80_ld, rL, ix8 }, - { 0x6F, Z80_ld, rIXL, rA }, - { 0x70, Z80_ld, ix8, rB }, - { 0x71, Z80_ld, ix8, rC }, - { 0x72, Z80_ld, ix8, rD }, - { 0x73, Z80_ld, ix8, rE }, - { 0x74, Z80_ld, ix8, rH }, - { 0x75, Z80_ld, ix8, rL }, - { 0x77, Z80_ld, ix8, rA }, - { 0x78, Z80_inw, rHL, atC }, - { 0x79, Z80_outw, atC, rHL }, - { 0x7C, Z80_ld, rA, rIXU }, - { 0x7D, Z80_ld, rA, rIXL }, - { 0x7E, Z80_ld, rA, ix8 }, - { 0x84, Z80_add, rA, rIXU }, - { 0x85, Z80_add, rA, rIXL }, - { 0x86, Z80_add, rA, ix8 }, - { 0x87, Z80_addw, rHL, rIX }, - { 0x8C, Z80_adc, rA, rIXU }, - { 0x8D, Z80_adc, rA, rIXL }, - { 0x8E, Z80_adc, rA, ix8 }, - { 0x8F, Z80_adcw, rHL, rIX }, - { 0x94, Z80_sub, rA, rIXU }, - { 0x95, Z80_sub, rA, rIXL }, - { 0x96, Z80_sub, rA, ix8 }, - { 0x97, Z80_subw, rHL, rIX }, - { 0x9C, Z80_sbc, rA, rIXU }, - { 0x9D, Z80_sbc, rA, rIXL }, - { 0x9E, Z80_sbc, rA, ix8 }, - { 0x9F, Z80_sbcw, rHL, rIX }, - { 0xA4, Z80_and, rA, rIXU }, - { 0xA5, Z80_and, rA, rIXL }, - { 0xA6, Z80_and, rA, ix8 }, - { 0xA7, Z80_andw, rHL, rIX }, - { 0xAC, Z80_xor, rA, rIXU }, - { 0xAD, Z80_xor, rA, rIXL }, - { 0xAE, Z80_xor, rA, ix8 }, - { 0xAF, Z80_xorw, rHL, rIX }, - { 0xB4, Z80_or, rA, rIXU }, - { 0xB5, Z80_or, rA, rIXL }, - { 0xB6, Z80_or, rA, ix8 }, - { 0xB7, Z80_orw, rHL, rIX }, - { 0xBC, Z80_cp, rA, rIXU }, - { 0xBD, Z80_cp, rA, rIXL }, - { 0xBE, Z80_cp, rA, ix8 }, - { 0xBF, Z80_cpw, rHL, rIX }, - { 0xC0, Z80_ddir, rW }, - { 0xC1, Z80_ddir, rIB, rW }, - { 0xC2, Z80_ddir, rIW, rW }, - { 0xC3, Z80_ddir, rIB }, - { 0xC4, Z80_calr, ccNZ, rip16 }, - { 0xC6, Z80_addw, rHL, ix8 }, - { 0xC8, Z80_ldctl, rSR, rA }, - { 0xCA, Z80_ldctl, rSR, imm8 }, - { 0xCC, Z80_calr, ccZ, rip16 }, - { 0xCD, Z80_calr, rip16 }, - { 0xCE, Z80_adcw, rHL, ix8 }, - { 0xCF, Z80_mtest, }, - { 0xD0, Z80_ldctl, rA, rXSR }, - { 0xD4, Z80_calr, ccNC, rip16 }, - { 0xD6, Z80_subw, rHL, ix8 }, - { 0xD8, Z80_ldctl, rXSR, rA }, - { 0xD9, Z80_exxx, }, - { 0xDA, Z80_ldctl, rXSR, imm8 }, - { 0xDC, Z80_calr, ccC, rip16 }, - { 0xDE, Z80_sbcw, rHL, ix8 }, - { 0xE1, Z80_pop, rIX }, - { 0xE3, Z80_ex, atSP, rIX }, - { 0xE4, Z80_calr, ccPO, rip16 }, - { 0xE5, Z80_push, rIX }, - { 0xE6, Z80_andw, rHL, ix8 }, - { 0xE9, Z80_jp, atIX }, - { 0xEC, Z80_calr, ccPE, rip16 }, - { 0xEE, Z80_xorw, rHL, ix8 }, - { 0xF3, Z80_di, imm8 }, - { 0xF4, Z80_calr, ccP, rip16 }, - { 0xF6, Z80_orw, rHL, ix8 }, - { 0xF7, Z80_setc, rLW }, - { 0xF9, Z80_ld, rSP, rIX }, - { 0xFB, Z80_ei, imm8 }, - { 0xFC, Z80_calr, ccM, rip16 }, - { 0xFE, Z80_cpw, rHL, ix8 }, - { 0xFF, Z80_resc, rLW }, - { 0x00, 0 }, -}; - -//the next byte after DDBC is in saved_value -static const insndesc_t cmdsDDCB[] = -{ - { 0x01, Z80_ld, rBC, sps }, - { 0x02, Z80_rlcw, ixs }, - { 0x03, Z80_ld, rBC, ixs }, - { 0x06, Z80_rlc, ixs }, - { 0x09, Z80_ld, sps, rBC }, - { 0x0A, Z80_rrcw, ixs }, - { 0x0B, Z80_ld, ixs, rBC }, - { 0x0E, Z80_rrc, ixs }, - { 0x11, Z80_ld, rDE, sps }, - { 0x12, Z80_rlw, ixs }, - { 0x13, Z80_ld, rDE, ixs }, - { 0x16, Z80_rl, ixs }, - { 0x19, Z80_ld, sps, rDE }, - { 0x1A, Z80_rrw, ixs }, - { 0x1B, Z80_ld, ixs, rDE }, - { 0x1E, Z80_rr, ixs }, - { 0x21, Z80_ld, rIX, sps }, - { 0x22, Z80_slaw, ixs }, - { 0x23, Z80_ld, rIY, ixs }, - { 0x26, Z80_sla, ixs }, - { 0x29, Z80_ld, sps, rIX }, - { 0x2A, Z80_sraw, ixs }, - { 0x2B, Z80_ld, ixs, rIY }, - { 0x2E, Z80_sra, ixs }, - { 0x31, Z80_ld, rHL, sps }, - { 0x33, Z80_ld, rHL, ixs }, - { 0x39, Z80_ld, sps, rHL }, - { 0x3A, Z80_srlw, ixs }, - { 0x3B, Z80_ld, ixs, rHL }, - { 0x3E, Z80_srl, ixs }, - { 0x46, Z80_bit, c0, ixs }, - { 0x4E, Z80_bit, c1, ixs }, - { 0x56, Z80_bit, c2, ixs }, - { 0x5E, Z80_bit, c3, ixs }, - { 0x66, Z80_bit, c4, ixs }, - { 0x6E, Z80_bit, c5, ixs }, - { 0x76, Z80_bit, c6, ixs }, - { 0x7E, Z80_bit, c7, ixs }, - { 0x86, Z80_res, c0, ixs }, - { 0x8E, Z80_res, c1, ixs }, - { 0x92, Z80_multw, ixs }, - { 0x92, Z80_multw, rHL, ixs }, - { 0x96, Z80_res, c2, ixs }, - { 0x9A, Z80_multuw, ixs }, - { 0x9A, Z80_multuw, rHL, ixs }, - { 0x9E, Z80_res, c3, ixs }, - { 0xA6, Z80_res, c4, ixs }, - { 0xAE, Z80_res, c5, ixs }, - { 0xB6, Z80_res, c6, ixs }, - { 0xBA, Z80_divuw, ixs }, - { 0xBA, Z80_divuw, rHL, ixs }, - { 0xBE, Z80_res, c7, ixs }, - { 0xC6, Z80_set, c0, ixs }, - { 0xCE, Z80_set, c1, ixs }, - { 0xD6, Z80_set, c2, ixs }, - { 0xDE, Z80_set, c3, ixs }, - { 0xE6, Z80_set, c4, ixs }, - { 0xEE, Z80_set, c5, ixs }, - { 0xF6, Z80_set, c6, ixs }, - { 0xFE, Z80_set, c7, ixs }, - { 0x00, 0 }, -}; - - -static const insndesc_t cmdsFD[] = -{ - { 0x01, Z80_ld, atBC, rIY }, - { 0x02, Z80_ld, rBC, rHL }, - { 0x03, Z80_ld, rIY, atBC }, - { 0x07, Z80_ld, rIY, rBC }, - { 0x09, Z80_add, rIY, rBC }, - { 0x0B, Z80_ld, rBC, rIY }, - { 0x0C, Z80_ld, atBC, rBC }, - { 0x0D, Z80_ld, atDE, rBC }, - { 0x0F, Z80_ld, atHL, rBC }, - { 0x10, Z80_djnz, rip24 }, - { 0x11, Z80_ld, atDE, rIY }, - { 0x12, Z80_ld, rDE, rHL }, - { 0x13, Z80_ld, rIY, atDE }, - { 0x17, Z80_ld, rIY, rDE }, - { 0x18, Z80_jr, rip24 }, - { 0x19, Z80_add, rIY, rDE }, - { 0x1B, Z80_ld, rDE, rIY }, - { 0x1C, Z80_ld, atBC, rDE }, - { 0x1D, Z80_ld, atDE, rDE }, - { 0x1F, Z80_ld, atHL, rDE }, - { 0x20, Z80_jr, ccNZ, rip24 }, - { 0x21, Z80_ld, rIY, imm16 }, - { 0x22, Z80_ld, mem16, rIY }, - { 0x23, Z80_inc, rIY }, - { 0x24, Z80_inc, rIYU }, - { 0x25, Z80_dec, rIYU }, - { 0x26, Z80_ld, rIYU, imm8 }, - { 0x27, Z80_ld, rIY, rIX }, - { 0x28, Z80_jr, ccZ, rip24 }, - { 0x29, Z80_add, rIY, rIY }, - { 0x2A, Z80_ld, rIY, mem16 }, - { 0x2B, Z80_dec, rIY }, - { 0x2C, Z80_inc, rIYL }, - { 0x2D, Z80_dec, rIYL }, - { 0x2E, Z80_ld, rIYL, imm8 }, - { 0x30, Z80_jr, ccNC, rip24 }, - { 0x31, Z80_ld, atHL, rIY }, - { 0x32, Z80_ld, rHL, rHL }, - { 0x33, Z80_ld, rIY, atHL }, - { 0x34, Z80_inc, iy8 }, - { 0x35, Z80_dec, iy8 }, - { 0x36, Z80_ld, iy8, imm8 }, - { 0x26, Z80_ld, rIYU, imm8 }, - { 0x37, Z80_ld, rIY, rHL }, - { 0x38, Z80_jr, ccC, rip24 }, - { 0x39, Z80_add, rIY, rSP }, - { 0x3B, Z80_ld, rHL, rIY }, - { 0x3C, Z80_ld, atBC, rHL }, - { 0x3D, Z80_ld, atDE, rHL }, - { 0x3E, Z80_swap, rIY }, - { 0x3F, Z80_ld, atHL, rHL }, - { 0x44, Z80_ld, rB, rIYU }, - { 0x45, Z80_ld, rB, rIYL }, - { 0x46, Z80_ld, rB, iy8 }, - { 0x4C, Z80_ld, rC, rIYU }, - { 0x4D, Z80_ld, rC, rIYL }, - { 0x4E, Z80_ld, rC, iy8 }, - { 0x54, Z80_ld, rD, rIYU }, - { 0x55, Z80_ld, rD, rIYL }, - { 0x56, Z80_ld, rD, iy8 }, - { 0x5C, Z80_ld, rE, rIYU }, - { 0x5D, Z80_ld, rE, rIYL }, - { 0x5E, Z80_ld, rE, iy8 }, - { 0x60, Z80_ld, rIYU, rB }, - { 0x61, Z80_ld, rIYU, rC }, - { 0x62, Z80_ld, rIYU, rD }, - { 0x63, Z80_ld, rIYU, rE }, - { 0x64, Z80_ld, rIYU, rIYU }, - { 0x65, Z80_ld, rIYU, rIYL }, - { 0x66, Z80_ld, rH, iy8 }, - { 0x67, Z80_ld, rIYU, rA }, - { 0x68, Z80_ld, rIYL, rB }, - { 0x69, Z80_ld, rIYL, rC }, - { 0x6A, Z80_ld, rIYL, rD }, - { 0x6B, Z80_ld, rIYL, rE }, - { 0x6C, Z80_ld, rIYL, rIYU }, - { 0x6D, Z80_ld, rIYL, rIYL }, - { 0x6E, Z80_ld, rL, iy8 }, - { 0x6F, Z80_ld, rIYL, rA }, - { 0x70, Z80_ld, iy8, rB }, - { 0x71, Z80_ld, iy8, rC }, - { 0x72, Z80_ld, iy8, rD }, - { 0x73, Z80_ld, iy8, rE }, - { 0x74, Z80_ld, iy8, rH }, - { 0x75, Z80_ld, iy8, rL }, - { 0x77, Z80_ld, iy8, rA }, - { 0x79, Z80_outw, atC, imm16 }, - { 0x7C, Z80_ld, rA, rIYU }, - { 0x7D, Z80_ld, rA, rIYL }, - { 0x7E, Z80_ld, rA, iy8 }, - { 0x84, Z80_add, rA, rIYU }, - { 0x85, Z80_add, rA, rIYL }, - { 0x86, Z80_add, rA, iy8 }, - { 0x87, Z80_addw, rHL, rIY }, - { 0x8C, Z80_adc, rA, rIYU }, - { 0x8D, Z80_adc, rA, rIYL }, - { 0x8E, Z80_adc, rA, iy8 }, - { 0x8F, Z80_adcw, rHL, rIY }, - { 0x8F, Z80_adcw, rIY }, - { 0x94, Z80_sub, rA, rIYU }, - { 0x95, Z80_sub, rA, rIYL }, - { 0x96, Z80_sub, rA, iy8 }, - { 0x97, Z80_subw, rHL, rIY }, - { 0x9C, Z80_sbc, rA, rIYU }, - { 0x9D, Z80_sbc, rA, rIYL }, - { 0x9E, Z80_sbc, rA, iy8 }, - { 0x9F, Z80_sbcw, rHL, rIY }, - { 0xA4, Z80_and, rA, rIYU }, - { 0xA5, Z80_and, rA, rIYL }, - { 0xA6, Z80_and, rA, iy8 }, - { 0xA7, Z80_andw, rHL, rIY }, - { 0xAC, Z80_xor, rA, rIYU }, - { 0xAD, Z80_xor, rA, rIYL }, - { 0xAE, Z80_xor, rA, iy8 }, - { 0xAF, Z80_xorw, rHL, rIY }, - { 0xB4, Z80_or, rA, rIYU }, - { 0xB5, Z80_or, rA, rIYL }, - { 0xB6, Z80_or, rA, iy8 }, - { 0xB7, Z80_orw, rHL, rIY }, - { 0xBC, Z80_cp, rA, rIYU }, - { 0xBD, Z80_cp, rA, rIYL }, - { 0xBE, Z80_cp, rA, iy8 }, - { 0xBF, Z80_cpw, rHL, rIY }, - { 0xC0, Z80_ddir, rLW }, - { 0xC1, Z80_ddir, rIB, rLW }, - { 0xC2, Z80_ddir, rIW, rLW }, - { 0xC3, Z80_ddir, rIW }, - { 0xC4, Z80_calr, ccNZ, rip24 }, - { 0xC6, Z80_addw, iy8 }, - { 0xC6, Z80_addw, rHL, iy8 }, - { 0xCC, Z80_calr, ccZ, rip24 }, - { 0xCD, Z80_calr, rip24 }, - { 0xCE, Z80_adcw, rHL, iy8 }, - { 0xD0, Z80_ldctl, rA, rYSR }, - { 0xD3, Z80_outaw, imm16, rHL }, - { 0xD4, Z80_calr, ccNC, rip24 }, - { 0xD6, Z80_subw, rHL, iy8 }, - { 0xD8, Z80_ldctl, rYSR, rA }, - { 0xD9, Z80_exxy, }, - { 0xDA, Z80_ldctl, rYSR, imm8 }, - { 0xDB, Z80_inaw, rHL, imm16 }, - { 0xDC, Z80_calr, ccC, rip24 }, - { 0xDE, Z80_sbcw, rHL, iy8 }, - { 0xE1, Z80_pop, rIY }, - { 0xE3, Z80_ex, atSP, rIY }, - { 0xE4, Z80_calr, ccPO, rip24 }, - { 0xE5, Z80_push, rIY }, - { 0xE6, Z80_andw, rHL, iy8 }, - { 0xE9, Z80_jp, atIY }, - { 0xEC, Z80_calr, ccPE, rip24 }, - { 0xEE, Z80_xorw, rHL, iy8 }, - { 0xF4, Z80_calr, ccP, rip24 }, - { 0xF5, Z80_push, imm16 }, - { 0xF6, Z80_orw, rHL, iy8 }, - { 0xF7, Z80_setc, rXM }, - { 0xF9, Z80_ld, rSP, rIY }, - { 0xFC, Z80_calr, ccM, rip24 }, - { 0xFE, Z80_cpw, rHL, iy8 }, - { 0x00, 0 }, -}; - -//the next byte after FDBC is in saved_value -static const insndesc_t cmdsFDCB[] = -{ - { 0x02, Z80_rlcw, iys }, - { 0x03, Z80_ld, rBC, iys }, - { 0x06, Z80_rlc, iys }, - { 0x0A, Z80_rrcw, iys }, - { 0x0B, Z80_ld, iys, rBC }, - { 0x0E, Z80_rrc, iys }, - { 0x12, Z80_rlw, iys }, - { 0x13, Z80_ld, rDE, iys }, - { 0x16, Z80_rl, iys }, - { 0x1A, Z80_rrw, iys }, - { 0x1B, Z80_ld, iys, rDE }, - { 0x1E, Z80_rr, iys }, - { 0x21, Z80_ld, rIY, sps }, - { 0x22, Z80_slaw, iys }, - { 0x23, Z80_ld, rIX, iys }, - { 0x26, Z80_sla, iys }, - { 0x29, Z80_ld, sps, rIY }, - { 0x2A, Z80_sraw, iys }, - { 0x2B, Z80_ld, iys, rIX }, - { 0x2E, Z80_sra, iys }, - { 0x33, Z80_ld, rHL, iys }, - { 0x3A, Z80_srlw, iys }, - { 0x3B, Z80_ld, iys, rHL }, - { 0x3E, Z80_srl, iys }, - { 0x46, Z80_bit, c0, iys }, - { 0x4E, Z80_bit, c1, iys }, - { 0x56, Z80_bit, c2, iys }, - { 0x5E, Z80_bit, c3, iys }, - { 0x66, Z80_bit, c4, iys }, - { 0x6E, Z80_bit, c5, iys }, - { 0x76, Z80_bit, c6, iys }, - { 0x7E, Z80_bit, c7, iys }, - { 0x86, Z80_res, c0, iys }, - { 0x8E, Z80_res, c1, iys }, - { 0x92, Z80_multw, iys }, - { 0x92, Z80_multw, rHL, iys }, - { 0x96, Z80_res, c2, iys }, - { 0x9A, Z80_multuw, iys }, - { 0x9A, Z80_multuw, rHL, iys }, - { 0x9E, Z80_res, c3, iys }, - { 0xA6, Z80_res, c4, iys }, - { 0xAE, Z80_res, c5, iys }, - { 0xB6, Z80_res, c6, iys }, - { 0xBA, Z80_divuw, iys }, - { 0xBA, Z80_divuw, rHL, iys }, - { 0xBE, Z80_res, c7, iys }, - { 0xC6, Z80_set, c0, iys }, - { 0xCE, Z80_set, c1, iys }, - { 0xD6, Z80_set, c2, iys }, - { 0xDE, Z80_set, c3, iys }, - { 0xE6, Z80_set, c4, iys }, - { 0xEE, Z80_set, c5, iys }, - { 0xF6, Z80_set, c6, iys }, - { 0xFE, Z80_set, c7, iys }, - { 0x00, 0 }, -}; - -static const insndesc_t cmdsED[] = -{ - { 0x00, Z80_in0, rB, imm8 }, - { 0x01, Z80_out0, imm8, rB }, - { 0x02, Z80_ld, rBC, rBC }, - { 0x03, Z80_ex, rBC, rIX }, - { 0x04, Z80_tst, rB }, - { 0x05, Z80_ex, rBC, rDE }, - { 0x06, Z80_ldw, atBC, imm16 }, - { 0x07, Z80_ex, rA, rB }, - { 0x08, Z80_in0, rC, imm8 }, - { 0x09, Z80_out0, imm8, rC }, - { 0x0B, Z80_ex, rBC, rIY }, - { 0x0C, Z80_tst, rC }, - { 0x0D, Z80_ex, rBC, rHL }, - { 0x0E, Z80_swap, rBC }, - { 0x0F, Z80_ex, rA, rC }, - { 0x10, Z80_in0, rD, imm8 }, - { 0x11, Z80_out0, imm8, rD }, - { 0x12, Z80_ld, rDE, rBC }, - { 0x13, Z80_ex, rDE, rIX }, - { 0x14, Z80_tst, rD }, - { 0x16, Z80_ldw, atDE, imm16 }, - { 0x17, Z80_ex, rA, rD }, - { 0x18, Z80_in0, rE, imm8 }, - { 0x19, Z80_out0, imm8, rE }, - { 0x1B, Z80_ex, rDE, rIY }, - { 0x1C, Z80_tst, rE }, - { 0x1E, Z80_swap, rDE }, - { 0x1F, Z80_ex, rA, rE }, - { 0x20, Z80_in0, rH, imm8 }, - { 0x21, Z80_out0, imm8, rH }, - { 0x24, Z80_tst, rH }, - { 0x27, Z80_ex, rA, rH }, - { 0x28, Z80_in0, rL, imm8 }, - { 0x29, Z80_out0, imm8, rL }, - { 0x2B, Z80_ex, rIX, rIY }, - { 0x2C, Z80_tst, rL }, - { 0x2F, Z80_ex, rA, rL }, - { 0x30, Z80_in0, imm8 }, - { 0x32, Z80_ld, rHL, rBC }, - { 0x33, Z80_ex, rHL, rIX }, - { 0x34, Z80_tst, atHL }, - { 0x36, Z80_ldw, atHL, imm16 }, - { 0x37, Z80_ex, rA, atHL }, - { 0x38, Z80_in0, rA, imm8 }, - { 0x39, Z80_out0, imm8, rA }, - { 0x3B, Z80_ex, rHL, rIY }, - { 0x3C, Z80_tst, rA }, - { 0x3E, Z80_swap, rHL }, - { 0x3F, Z80_ex, rA, rA }, - { 0x40, Z80_in, rB, atC }, - { 0x41, Z80_out, atC, rB }, - { 0x42, Z80_sbc, rHL, rBC }, - { 0x43, Z80_ld, mem16, rBC }, - { 0x44, Z80_neg, rA }, - { 0x45, Z80_retn, }, - { 0x46, Z80_im, c0 }, - { 0x47, Z80_ld, rI, rA }, - { 0x48, Z80_in, rC, atC }, - { 0x49, Z80_out, atC, rC }, - { 0x4A, Z80_adc, rHL, rBC }, - { 0x4B, Z80_ld, rBC, mem16 }, - { 0x4C, Z80_mlt, rBC }, - { 0x4D, Z80_reti, }, - { 0x4E, Z80_im, c3 }, - { 0x4F, Z80_ld, rR, rA }, - { 0x50, Z80_in, rD, atC }, - { 0x51, Z80_out, atC, rD }, - { 0x52, Z80_sbc, rHL, rDE }, - { 0x53, Z80_ld, mem16, rDE }, - { 0x54, Z80_negw, rHL }, - { 0x56, Z80_im, c1 }, - { 0x57, Z80_ld, rA, rI }, - { 0x58, Z80_in, rE, atC }, - { 0x59, Z80_out, atC, rE }, - { 0x5A, Z80_adc, rHL, rDE }, - { 0x5B, Z80_ld, rDE, mem16 }, - { 0x5C, Z80_mlt, rDE }, - { 0x5E, Z80_im, c2 }, - { 0x5F, Z80_ld, rA, rR }, - { 0x60, Z80_in, rH, atC }, - { 0x61, Z80_out, atC, rH }, - { 0x62, Z80_sbc, rHL, rHL }, - { 0x64, Z80_tst, imm8 }, - { 0x65, Z80_exts, rA }, - { 0x67, Z80_rrd, }, - { 0x68, Z80_in, rL, atC }, - { 0x69, Z80_out, atC, rL }, - { 0x6A, Z80_adc, rHL, rHL }, - { 0x6C, Z80_mlt, rHL }, - { 0x6F, Z80_rld, }, - { 0x71, Z80_out, atC, imm8 }, - { 0x72, Z80_sbc, rHL, rSP }, - { 0x73, Z80_ld, mem16, rSP }, - { 0x74, Z80_tstio, imm8 }, - { 0x75, Z80_extsw, rHL }, - { 0x76, Z80_slp, }, - { 0x78, Z80_in, rA, atC }, - { 0x79, Z80_out, atC, rA }, - { 0x7A, Z80_adc, rHL, rSP }, - { 0x7B, Z80_ld, rSP, mem16 }, - { 0x7C, Z80_mlt, rSP }, - { 0x82, Z80_add, rSP, imm16 }, - { 0x83, Z80_otim, }, - { 0x84, Z80_addw, rHL, rBC }, - { 0x85, Z80_addw, rHL, rDE }, - { 0x86, Z80_addw, rHL, imm16 }, - { 0x87, Z80_addw, rHL, rHL }, - { 0x8B, Z80_otdm, }, - { 0x8C, Z80_adcw, rHL, rBC }, - { 0x8D, Z80_adcw, rHL, rDE }, - { 0x8E, Z80_adcw, rHL, imm16 }, - { 0x8F, Z80_adcw, rHL, rHL }, - { 0x92, Z80_sub, rSP, imm16 }, - { 0x93, Z80_otimr, }, - { 0x94, Z80_subw, rHL, rBC }, - { 0x95, Z80_subw, rHL, rDE }, - { 0x96, Z80_subw, rHL, imm16 }, - { 0x97, Z80_subw, rHL, rHL }, - { 0x9B, Z80_otdmr, }, - { 0x9C, Z80_sbcw, rHL, rBC }, - { 0x9D, Z80_sbcw, rHL, rDE }, - { 0x9E, Z80_sbcw, rHL, imm16 }, - { 0x9F, Z80_sbcw, rHL, rHL }, - { 0xA0, Z80_ldi, }, - { 0xA1, Z80_cpi, }, - { 0xA2, Z80_ini, }, - { 0xA3, Z80_outi, }, - { 0xA4, Z80_andw, rHL, rBC }, - { 0xA5, Z80_andw, rHL, rDE }, - { 0xA6, Z80_andw, rHL, imm16 }, - { 0xA7, Z80_andw, rHL, rHL }, - { 0xA8, Z80_ldd, }, - { 0xA9, Z80_cpd, }, - { 0xAA, Z80_ind, }, - { 0xAB, Z80_outd, }, - { 0xAC, Z80_xorw, rHL, rBC }, - { 0xAD, Z80_xorw, rHL, rDE }, - { 0xAE, Z80_xorw, rHL, imm16 }, - { 0xAF, Z80_xorw, rHL, rHL }, - { 0xB0, Z80_ldir, }, - { 0xB1, Z80_cpir, }, - { 0xB2, Z80_inir, }, - { 0xB3, Z80_otir, }, - { 0xB4, Z80_orw, rHL, rBC }, - { 0xB5, Z80_orw, rHL, rDE }, - { 0xB6, Z80_orw, rHL, imm16 }, - { 0xB7, Z80_orw, rHL, rHL }, - { 0xB8, Z80_lddr, }, - { 0xB9, Z80_cpdr, }, - { 0xBA, Z80_indr, }, - { 0xBB, Z80_otdr, }, - { 0xBC, Z80_cpw, rHL, rBC }, - { 0xBD, Z80_cpw, rHL, rDE }, - { 0xBE, Z80_cpw, rHL, imm16 }, - { 0xBF, Z80_cpw, rHL, rHL }, - { 0xC0, Z80_ldctl, rHL, rSR }, - { 0xC1, Z80_pop, rSR }, - { 0xC4, Z80_calr, ccNZ, rip8 }, - { 0xC5, Z80_push, rSR }, - { 0xC6, Z80_add, rHL, mem16 }, - { 0xC8, Z80_ldctl, rSR, rHL }, - { 0xCC, Z80_calr, ccZ, rip8 }, - { 0xCD, Z80_calr, rip8 }, - { 0xCF, Z80_btest, }, - { 0xD0, Z80_ldctl, rA, rDSR }, - { 0xD3, Z80_outa, mem16, rA }, - { 0xD4, Z80_calr, ccNC, rip8 }, - { 0xD6, Z80_sub, rHL, mem16 }, - { 0xD8, Z80_ldctl, rDSR, rA }, - { 0xD9, Z80_exall, }, - { 0xDA, Z80_ldctl, rDSR, imm8 }, - { 0xDB, Z80_ina, rA, mem16 }, - { 0xDC, Z80_calr, ccC, rip8 }, - { 0xE0, Z80_ldiw, }, - { 0xE2, Z80_iniw, }, - { 0xE3, Z80_outiw, }, - { 0xE4, Z80_calr, ccPO, rip8 }, - { 0xE8, Z80_lddw, }, - { 0xEA, Z80_indw, }, - { 0xEB, Z80_outdw, }, - { 0xEC, Z80_calr, ccPE, rip8 }, - { 0xF0, Z80_ldirw, }, - { 0xF2, Z80_inirw, }, - { 0xF3, Z80_otirw, }, - { 0xF4, Z80_calr, ccP, rip8 }, - { 0xF7, Z80_setc, rLCK }, - { 0xF8, Z80_lddrw, }, - { 0xFA, Z80_indrw, }, - { 0xFB, Z80_otdrw, }, - { 0xFC, Z80_calr, ccM, rip8 }, - { 0xFF, Z80_resc, rLCK }, -}; - -static const insndesc_t cmdsEDCB[] = -{ - { 0x00, Z80_rlcw, rBC }, - { 0x01, Z80_rlcw, rDE }, - { 0x02, Z80_rlcw, atHL }, - { 0x03, Z80_rlcw, rHL }, - { 0x04, Z80_rlcw, rIX }, - { 0x05, Z80_rlcw, rIY }, - { 0x08, Z80_rrcw, rBC }, - { 0x09, Z80_rrcw, rDE }, - { 0x0A, Z80_rrcw, atHL }, - { 0x0B, Z80_rrcw, rHL }, - { 0x0C, Z80_rrcw, rIX }, - { 0x0D, Z80_rrcw, rIY }, - { 0x10, Z80_rlw, rBC }, - { 0x11, Z80_rlw, rDE }, - { 0x12, Z80_rlw, atHL }, - { 0x13, Z80_rlw, rHL }, - { 0x14, Z80_rlw, rIX }, - { 0x15, Z80_rlw, rIY }, - { 0x18, Z80_rrw, rBC }, - { 0x19, Z80_rrw, rDE }, - { 0x1A, Z80_rrw, atHL }, - { 0x1B, Z80_rrw, rHL }, - { 0x1C, Z80_rrw, rIX }, - { 0x1D, Z80_rrw, rIY }, - { 0x20, Z80_slaw, rBC }, - { 0x21, Z80_slaw, rDE }, - { 0x22, Z80_slaw, atHL }, - { 0x23, Z80_slaw, rHL }, - { 0x24, Z80_slaw, rIX }, - { 0x25, Z80_slaw, rIY }, - { 0x28, Z80_sraw, rBC }, - { 0x29, Z80_sraw, rDE }, - { 0x2A, Z80_sraw, atHL }, - { 0x2B, Z80_sraw, rHL }, - { 0x2C, Z80_sraw, rIX }, - { 0x2D, Z80_sraw, rIY }, - { 0x30, Z80_ex, rBC, rBC2 }, - { 0x31, Z80_ex, rDE, rDE2 }, - { 0x33, Z80_ex, rHL, rHL2 }, - { 0x34, Z80_ex, rIX, rIX2 }, - { 0x35, Z80_ex, rIY, rIY2 }, - { 0x38, Z80_srlw, rBC }, - { 0x39, Z80_srlw, rDE }, - { 0x3A, Z80_srlw, atHL }, - { 0x3B, Z80_srlw, rHL }, - { 0x3C, Z80_srlw, rIX }, - { 0x3D, Z80_srlw, rIY }, - { 0x90, Z80_multw, rHL, rBC }, - { 0x91, Z80_multw, rHL, rDE }, - { 0x93, Z80_multw, rHL, rHL }, - { 0x94, Z80_multw, rHL, rIX }, - { 0x95, Z80_multw, rHL, rIY }, - { 0x97, Z80_multw, rHL, imm16 }, - { 0x98, Z80_multuw, rHL, rBC }, - { 0x99, Z80_multuw, rHL, rDE }, - { 0x9B, Z80_multuw, rHL, rHL }, - { 0x9C, Z80_multuw, rHL, rIX }, - { 0x9D, Z80_multuw, rHL, rIY }, - { 0x9F, Z80_multuw, rHL, imm16 }, - { 0xB8, Z80_divuw, rHL, rBC }, - { 0xB9, Z80_divuw, rHL, rDE }, - { 0xBB, Z80_divuw, rHL, rHL }, - { 0xBC, Z80_divuw, rHL, rIX }, - { 0xBD, Z80_divuw, rHL, rIY }, - { 0xBF, Z80_divuw, rHL, imm16 }, -}; - -//------------------------------------------------------------------------ -void z80_t::load_z80_operand(insn_t &insn, op_t &x, uchar op) -{ - if ( op == 0 ) - return; - switch ( op ) - { - case rBC: - case rDE: - case rHL: - case rIX: - case rIY: - case rBC2: - case rDE2: - case rHL2: - case rIX2: - case rIY2: - case rSP: - case rLW: - case rIXL: - case rIXU: - case rDSR: - case rXSR: - case rIYL: - case rIYU: - case rYSR: - case rSR: - case rIB: - case rIW: - case rXM: - case rLCK: - x.dtype = dt_word; - // fallthrough - case rA: - case rB: - case rC: - case rD: - case rE: - case rH: - case rL: - case rI: - case rW: - case rR: - x.type = o_reg; - x.reg = op - 1; - break; - - case atBC: - x.type = o_phrase; - x.phrase = R_bc; - break; - case atDE: - x.type = o_phrase; - x.phrase = R_de; - break; - case atHL: - x.type = o_phrase; - x.phrase = R_hl; - break; - case atSP: - x.type = o_phrase; - x.phrase = R_sp; - break; - case atIX: - x.type = o_phrase; - x.phrase = R_ix; - break; - case atIY: - x.type = o_phrase; - x.phrase = R_iy; - break; - case atC: - x.type = o_phrase; - x.phrase = R_c; - break; - - case rip8: - { - sval_t disp = char(insn.get_next_byte()); - x.type = o_near; - x.addr = insn.ip + insn.size + disp; - } - break; - case rip16: - { - sval_t disp = short(insn.get_next_word()); - x.type = o_near; - x.addr = insn.ip + insn.size + disp; - } - break; - case rip24: - { - sval_t disp = insn.get_next_word(); - disp |= (sval_t((char)(insn.get_next_byte())) << 16); - x.type = o_near; - x.addr = insn.ip + insn.size + disp; - } - break; - - case imm8: - x.type = o_imm; - x.value = insn.get_next_byte(); - break; - - case imm16: - x.type = o_imm; - x.dtype = dt_word; - x.value = insn.get_next_word(); - break; - - case mem16: - x.type = o_mem; - x.addr = insn.get_next_word(); - break; - - case ix8: - x.type = o_displ; - x.phrase = R_ix; - x.addr = insn.get_next_byte(); - break; - case iy8: - x.type = o_displ; - x.phrase = R_iy; - x.addr = insn.get_next_byte(); - break; - case ixs: - x.type = o_displ; - x.phrase = R_ix; - x.addr = saved_value; - break; - case iys: - x.type = o_displ; - x.phrase = R_iy; - x.addr = saved_value; - break; - case sps: - x.type = o_displ; - x.phrase = R_sp; - x.addr = saved_value; - break; - - case ccNZ: - case ccZ: - case ccNC: - case ccC: - case ccPO: - case ccPE: - case ccP: - case ccM: - x.type = o_cond; - x.Cond = op - ccNZ; - break; - - case c0: - case c1: - case c2: - case c3: - case c4: - case c5: - case c6: - case c7: - x.type = o_imm; - x.value = op - c0; - break; - - default: - warning("%a: interr in z380, code=%x", insn.ea, code); - } -} - -//------------------------------------------------------------------------ -bool z80_t::search_map(insn_t &insn, const insndesc_t *map, uchar _code) -{ - for ( int i=0; map[i].itype; i++ ) - { - if ( map[i].code > _code ) - break; - if ( map[i].code == _code ) - { - insn.itype = map[i].itype; - load_z80_operand(insn, insn.Op1, map[i].op1); - load_z80_operand(insn, insn.Op2, map[i].op2); - return true; - } - } - return false; -} - -//------------------------------------------------------------------------ -bool z80_t::z380_insns(insn_t &insn, const insndesc_t *map, const insndesc_t *cb) -{ - code = insn.get_next_byte(); - if ( code == 0xCB ) - { - map = cb; - saved_value = insn.get_next_byte(); - code = insn.get_next_byte(); - } - return search_map(insn, map, (uchar)code); -} - -//------------------------------------------------------------------------ -bool z80_t::z380_ED(insn_t &insn) -{ - const insndesc_t *map = cmdsED; - code = insn.get_next_byte(); - if ( code == 0xCB ) - { - map = cmdsEDCB; - code = insn.get_next_byte(); - } - return search_map(insn, map, (uchar)code); -} - -//------------------------------------------------------------------------ -void z80_t::z80_ixcommands(insn_t &insn, bool _isx) -{ - if ( isGB() ) - return; - if ( isZ380() ) - { - if ( _isx ) - z380_insns(insn, cmdsDD, cmdsDDCB); - else - z380_insns(insn, cmdsFD, cmdsFDCB); - return; - } - - isx = _isx; - code = insn.get_next_byte(); - switch ( (code>>4) & 0xF ) - { - case 0: /* 0000???? */ - case 1: /* 0001???? */ - if ( (code & 0xF) == 9 ) - { - insn.itype = I5_add; - op_ix(insn.Op1); - op_ss(insn.Op2); - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - } - break; - case 2: /* 0010???? */ - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - (code & 4) ? op_ibyte(insn.Op1,code & 8) : op_ix(insn.Op1); - switch ( code & 0xF ) - { - case 1: - insn.itype = I5_lxi; - op_nn(insn, insn.Op2); - break; - case 2: - insn.itype = I5_mov; - op_mm(insn, insn.Op1); - op_ix(insn.Op2); - break; - case 3: - insn.itype = I5_inx; - break; - case 4: - case 0xC: - insn.itype = I5_inr; - break; - case 5: - case 0xD: - insn.itype = I5_dcr; - break; - case 6: - case 0xE: - insn.itype = I5_mvi; - op_n(insn, insn.Op2); - break; - case 9: - insn.itype = I5_add; - op_ix(insn.Op2); - break; - case 0xA: - insn.itype = I5_mov; - op_mm(insn, insn.Op2); - break; - case 0xB: - insn.itype = I5_dcx; - break; - } - break; - case 3: - switch ( code & 0xF ) - { - case 4: - insn.itype = I5_inr; - op_xdispl(insn, insn.Op1); - break; - case 5: - insn.itype = I5_dcr; - op_xdispl(insn, insn.Op1); - break; - case 6: - insn.itype = I5_mvi; - op_xdispl(insn, insn.Op1); - op_n(insn, insn.Op2); - break; - case 9: - insn.itype = I5_add; - op_ix(insn.Op1); - op_ss(insn.Op2); - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - break; - } - break; - case 4: - case 5: - if ( (code & 6) == 4 ) - { - insn.itype = I5_mov; - op_xr1(insn.Op1); - op_ibyte(insn.Op2,code & 1); - break; - } - /* no break */ - case 6: - if ( (code & 6) == 4 ) - break; - if ( (code & 7) == 6 ) - { - if ( op_xr1(insn.Op1) ) - break; // mem,mem not allowed - if ( code == 0x66 ) - insn.Op1.reg = R_h; - if ( code == 0x6E ) - insn.Op1.reg = R_l; - op_xdispl(insn, insn.Op2); - insn.itype = I5_mov; - break; - } - if ( (code & 0xF0) == 0x60 ) - { - op_ibyte(insn.Op1,code & 8); - op_xr2(insn.Op2); - insn.itype = I5_mov; - } - break; - case 7: - switch ( code & 0xF ) - { - case 0: case 1: case 2: case 3: case 4: case 5: case 7: - op_xdispl(insn, insn.Op1); - if ( !op_xr2(insn.Op2) ) - insn.itype = I5_mov; - if ( code == 0x74 ) - insn.Op2.reg = R_h; - if ( code == 0x75 ) - insn.Op2.reg = R_l; - break; - case 0xE: - op_xdispl(insn, insn.Op2); - op_a(insn.Op1); - insn.itype = I5_mov; // to show all regs - break; - case 0xC: - case 0xD: - op_ibyte(insn.Op2,code & 1); - op_a(insn.Op1); - insn.itype = I5_mov; // to show all regs - break; - } - break; - case 8: - case 9: - case 0xA: - case 0xB: - if ( (code & 4) == 4 && (code & 7) != 7 ) - { - int type = (code >> 3) & 7; - insn.itype = W[type]; - op_a(insn.Op1); - ((code & 7) == 6) ? op_xdispl(insn, insn.Op2) - : op_ibyte(insn.Op2,code & 1); -// if ( type == 0 || type == 1 || type == 3 ) insn.Op1.clr_show(); - } - break; - case 0xC: - if ( code == 0xCB ) - { - op_xdispl(insn, insn.Op2); - code = insn.get_next_byte(); - if ( (code & 7) == 6 ) - { - int type = (code>>6) & 3; - if ( type == 0 ) - { - insn.itype = CBrols[ (code >> 3) & 7 ]; - op_a(insn.Op1); - } - else - { - static const uint16 brs[] = { I5_null, Z80_bit, Z80_res, Z80_set }; - insn.itype = brs[type]; - insn.Op1.type = o_imm; - insn.Op1.value = (code >> 3) & 7; - } - } - } - break; - case 0xE: - switch ( code & 0xF ) - { - case 1: - insn.itype = I5_pop; - op_ix(insn.Op1); - break; - case 3: - insn.itype = Z80_ex; - insn.Op1.type = o_phrase; - insn.Op1.phrase = R_sp; - insn.Op1.dtype = dt_word; - op_ix(insn.Op2); - break; - case 5: - insn.itype = I5_push; - op_ix(insn.Op1); - break; - case 9: - insn.itype = Z80_jp; - insn.Op1.type = o_cond; - insn.Op1.Cond = oc_not; - insn.Op2.type = o_phrase; - insn.Op2.phrase = isx ? R_ix : R_iy; - insn.Op2.dtype = dt_code; - break; - case 0xD: - code = insn.get_next_byte(); - switch ( code ) - { - case 0x42: - case 0x4A: - case 0x52: - case 0x5A: - case 0x62: - case 0x6A: - case 0x72: - case 0x7A: - insn.itype = (code & 8) ? I5_adc : Z80_sbc; - op_ix(insn.Op1); - op_ss(insn.Op2); - if ( insn.Op2.reg == R_hl ) - op_ix(insn.Op2); - break; - case 0x60: - case 0x68: - insn.itype = I5_in; - op_ibyte(insn.Op1,code & 8); - op_c(insn.Op2); - break; - case 0x61: - case 0x69: - insn.itype = I5_out; - op_c(insn.Op1); - op_ibyte(insn.Op2,code & 8); - break; - } - break; - } - // fallthrough - case 0xF: - if ( code == 0xF9 ) - { - insn.itype = I5_mov; - insn.Op1.type = o_reg; - insn.Op1.phrase = R_sp; - insn.Op1.dtype = dt_word; - op_ix(insn.Op2); - } - break; - } -} - - -//------------------------------------------------------------------------ -void z80_t::z80_misc(insn_t &insn) -{ - code = insn.get_next_byte(); - switch ( code ) - { - case 0x40: - case 0x48: - case 0x50: - case 0x58: - case 0x60: - case 0x68: - case 0x78: - insn.itype = I5_in; - op_r1(insn.Op1); - op_c(insn.Op2); - break; - case 0x41: - case 0x49: - case 0x51: - case 0x59: - case 0x61: - case 0x69: - case 0x79: - insn.itype = I5_out; - op_c(insn.Op1); - op_r1(insn.Op2); - break; - case 0x42: - case 0x4A: - case 0x52: - case 0x5A: - case 0x62: - case 0x6A: - case 0x72: - case 0x7A: - insn.itype = (code & 8) ? I5_adc : Z80_sbc; - insn.Op1.type = o_reg; - insn.Op1.reg = R_hl; - insn.Op1.dtype = dt_word; - op_ss(insn.Op2); - break; - case 0x43: - case 0x53: - case 0x73: - insn.itype = I5_mov; - op_mm(insn, insn.Op1); - op_ss(insn.Op2); - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - break; - case 0x44: insn.itype = Z80_neg; break; - case 0x45: insn.itype = Z80_retn; break; - case 0x46: - insn.itype = Z80_im; - insn.Op1.type = o_imm; - insn.Op1.value = 0; - break; - case 0x47: - insn.itype = I5_mov; // to show all regs - insn.Op1.type = o_reg; - insn.Op1.reg = R_i; - op_a(insn.Op2); - break; - case 0x4B: - case 0x5B: - case 0x7B: - insn.itype = I5_mov; - op_ss(insn.Op1); - op_mm(insn, insn.Op2); - insn.Op1.dtype = dt_word; - insn.Op2.dtype = dt_word; - break; - case 0x4D: - insn.itype = Z80_reti; - break; - case 0x4F: - insn.itype = I5_mov; // to show all regs - insn.Op1.type = o_reg; - insn.Op1.reg = R_r; - op_a(insn.Op2); - break; - case 0x56: - insn.itype = Z80_im; - insn.Op1.type = o_imm; - insn.Op1.value = 1; - break; - case 0x5E: - insn.itype = Z80_im; - insn.Op1.type = o_imm; - insn.Op1.value = 2; - break; - case 0x57: - insn.itype = I5_mov; // to show all regs - op_a(insn.Op1); - insn.Op2.type = o_reg; - insn.Op2.reg = R_i; - break; - case 0x5F: - insn.itype = I5_mov; // to show all regs - op_a(insn.Op1); - insn.Op2.type = o_reg; - insn.Op2.reg = R_r; - break; - case 0x67: insn.itype = Z80_rrd; break; - case 0x6F: insn.itype = Z80_rld; break; - - case 0xA0: insn.itype = Z80_ldi; break; - case 0xA1: insn.itype = Z80_cpi; break; - case 0xA2: insn.itype = Z80_ini; break; - case 0xA3: insn.itype = Z80_outi; break; - case 0xA8: insn.itype = Z80_ldd; break; - case 0xA9: insn.itype = Z80_cpd; break; - case 0xAA: insn.itype = Z80_ind; break; - case 0xAB: insn.itype = Z80_outd; break; - case 0xB0: insn.itype = Z80_ldir; break; - case 0xB1: insn.itype = Z80_cpir; break; - case 0xB2: insn.itype = Z80_inir; break; - case 0xB3: insn.itype = Z80_otir; break; - case 0xB8: insn.itype = Z80_lddr; break; - case 0xB9: insn.itype = Z80_cpdr; break; - case 0xBA: insn.itype = Z80_indr; break; - case 0xBB: insn.itype = Z80_otdr; break; -// -// HD64180 extensions -// - case 0x76: if ( is64180() ) insn.itype = HD_slp; break; - case 0x83: if ( is64180() ) insn.itype = HD_otim; break; - case 0x93: if ( is64180() ) insn.itype = HD_otimr; break; - case 0x8B: if ( is64180() ) insn.itype = HD_otdm; break; - case 0x9B: if ( is64180() ) insn.itype = HD_otdmr; break; - case 0x64: - if ( is64180() ) - { - insn.itype = HD_tst; - op_n(insn, insn.Op1); - } - break; - case 0x74: - if ( is64180() ) - { - insn.itype = HD_tstio; - op_n(insn, insn.Op1); - } - break; - default: -// I did not find an assembler that understands this... -// if ( (code & 0xC0) == 0x40 && (code & 6) == 0 ) // undocumented -// { -// insn.itype = (code & 1) ? I5_out : I5_in; -// op_r1(insn.Op1); -// break; -// } -//-------- - if ( is64180() ) - { - switch ( code & 0xC0 ) - { - case 0: - switch ( code & 7 ) - { - case 0: - insn.itype = HD_in0; - op_r1(insn.Op1); - op_n(insn, insn.Op2); - if ( insn.Op1.type == o_phrase ) - op_f(insn.Op1); - break; - case 1: - insn.itype = HD_out0; - op_n(insn, insn.Op1); - op_r1(insn.Op2); - break; - case 4: - insn.itype = HD_tst; - op_r1(insn.Op1); - break; - } - break; - case 0x40: - if ( code == 0x70 ) - { - insn.itype = I5_in; - op_f(insn.Op1); - op_c(insn.Op2); - break; - } - if ( (code & 0xF) == 0xC ) - { - insn.itype = HD_mlt; - op_ss(insn.Op1); - } - break; - } - } - break; - } -} diff --git a/idasdk75/module/z80/i5.hpp b/idasdk75/module/z80/i5.hpp deleted file mode 100644 index 1c9abd6..0000000 --- a/idasdk75/module/z80/i5.hpp +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 2.06 - * Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet) - * ALL RIGHTS RESERVED. - * - */ - -#ifndef I5HPP -#define I5HPP - -#include "../idaidp.hpp" -#include "ins.hpp" -#include <diskio.hpp> -#include "../iohandler.hpp" - -//------------------------------------------------------------------ -// debugger functions -typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); - -//------------------------------------------------------------------ -// customization of insn_t structure: -#define o_cond o_idpspec0 - -#define Cond reg - - -//------------------------------------------------------------------ -enum opcond_t // condition code types -{ - oc_nz, - oc_z, - oc_nc, - oc_c, - oc_po, - oc_pe, - oc_p, - oc_m, - oc_not -}; - -//------------------------------------------------------------------ -#define _PT_64180 0x01 // HD64180 -#define _PT_Z80 0x02 // Z80 -#define _PT_8085 0x04 // Intel 8085 -#define _PT_Z180 0x08 // Z180 -#define _PT_Z380 0x10 // Z380 -#define _PT_GB 0x20 // GameBoy - -#define PT_GB _PT_GB -#define PT_Z380 _PT_Z380 -#define PT_Z180 ( PT_Z380 | _PT_Z180) -#define PT_64180 ( PT_Z180 | _PT_64180) -#define PT_Z80 ( PT_64180| _PT_Z80 | _PT_GB) -#define PT_8085 ( PT_Z80 | _PT_8085 ) - -extern int pflag; - -enum RegNo ENUM_SIZE(uint16) -{ - R_b = 0, - R_c = 1, - R_d = 2, - R_e = 3, - R_h = 4, - R_l = 5, - R_a = 7, - R_bc = 8, - R_de = 9, - R_hl = 10, - R_af = 11, - R_sp = 12, - R_ix = 13, - R_iy = 14, - R_af2 = 15, - R_r = 16, - R_i = 17, - R_f = 18, - R_xl = 19, - R_xh = 20, - R_yl = 21, - R_yh = 22, - - R_w, - R_lw, - R_ixl, - R_ixu, - R_dsr, - R_xsr, - R_iyl, - R_iyu, - R_ysr, - R_sr, - R_ib, - R_iw, - R_xm, - R_lck, - R_bc2, - R_de2, - R_hl2, - R_ix2, - R_iy2, - R_b2, - R_c2, - R_d2, - R_e2, - R_h2, - R_l2, - R_m2, - R_a2, - - R_vcs, // virtual code segment register - R_vds // virtual data segment register -}; - - -//------------------------------------------------------------------ -#define UAS_NOENS 0x0001 // I5: don't specify start addr in the .end directive -#define UAS_NPAIR 0x0002 // I5: pairs are denoted by 1 char ('b') -#define UAS_UNDOC 0x0004 // I5: does assembler support undoc-d instrs? -#define UAS_MKIMM 0x0008 // I5: place # in front of imm operand -#define UAS_MKOFF 0x0010 // I5: offset(ix) form -#define UAS_CNDUP 0x0020 // I5: conditions UPPERCASE -#define UAS_FUNNY 0x0040 // I5: special for A80 -#define UAS_CSEGS 0x0080 // I5: generate 'cseg' directives -#define UAS_TOFF 0x0100 // I5: (ix+-10) -#define UAS_ZMASM 0x0200 // ZMASM -#define UAS_GBASM 0x0400 // RGBASM - - -#define aux_off16 0x0001 // o_displ: off16 - -//------------------------------------------------------------------ -struct z80_iohandler_t : public iohandler_t -{ - z80_iohandler_t(netnode &nn) : iohandler_t(nn) {} -}; - -struct insndesc_t; -struct z80_t : public procmod_t -{ - netnode helper; - z80_iohandler_t ioh = z80_iohandler_t(helper); - - int pflag = 0; - int code; - - uchar saved_value = 0; - bool flow = false; - bool isx = false; - - virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; - - const char *find_ioport(uval_t port); - const char *find_ioport_bit(int port, int bit); - void choose_device(int respinfo); - - void set_cpu(int np); - - const char *set_idp_options(const char *keyword, int /*value_type*/, const void * /*value*/, bool /*idb_loaded*/); - - // out.cpp - inline bool isFunny(void) { return (ash.uflag & UAS_FUNNY) != 0; } - void i5_header(outctx_t &ctx); - void i5_footer(outctx_t &ctx); - void i5_segstart(outctx_t &ctx, segment_t *); - - // ana.cpp - int i5_ana(insn_t *_insn); - void load_z80_operand(insn_t &insn, op_t &x, uchar op); - bool search_map(insn_t &insn, const insndesc_t *map, uchar _code); - bool z380_insns(insn_t &insn, const insndesc_t *map, const insndesc_t *cb); - bool z380_ED(insn_t &insn); - void z80_ixcommands(insn_t &insn, bool _isx); - void z80_misc(insn_t &insn); - void ConvertToZ80(insn_t &insn); - void op_r1(op_t &x) const; - void op_r2(op_t &x) const; - void op_ss(op_t &x) const; - void op_dd(op_t &x) const; - void op_xdispl(insn_t &insn, op_t &x) const; - void op_ix(op_t &x) const; - void op_ibyte(op_t &x,int low) const; - int op_xbytereg(op_t &x,uint16 mode) const; - int op_xr1(op_t &x) const; - int op_xr2(op_t &x) const; - inline bool isGB(void); - inline bool isZ380(void); - inline bool isZ180(void); - inline bool isZ80(void); - inline bool is64180(void); - inline bool is8085(void); - - // emu.cpp - int i5_emu(const insn_t &insn); - void load_operand(const insn_t &insn, const op_t &x); - sval_t named_regval(const char *regname, getreg_t *getreg, const regval_t *rv); - sval_t regval(const op_t &op, getreg_t *getreg, const regval_t *rv); - bool check_cond(uint16_t cc, getreg_t *getreg, const regval_t *regvalues); - ea_t next_exec_insn( - ea_t ea, - getreg_t *getreg, - const regval_t *regvalues); - ea_t calc_step_over(ea_t ip) const; - bool get_operand_info( - idd_opinfo_t *opinf, - ea_t ea, - int n, - getreg_t *getreg, - const regval_t *regvalues); - bool get_reg_info( - const char **main_regname, - bitrange_t *bitrange, - const char *regname); -}; - -inline bool z80_t::isGB(void) { return (pflag & PT_GB) != 0; } -inline bool z80_t::isZ380(void) { return (pflag & PT_Z380) != 0; } -inline bool z80_t::isZ180(void) { return (pflag & PT_Z180) != 0; } -inline bool z80_t::isZ80(void) { return (pflag & PT_Z80) != 0; } -inline bool z80_t::is64180(void) { return (pflag & PT_64180) != 0; } -inline bool z80_t::is8085(void) { return !isZ80(); } - -#endif // I5HPP diff --git a/idasdk75/module/z80/ins.hpp b/idasdk75/module/z80/ins.hpp deleted file mode 100644 index 70ff057..0000000 --- a/idasdk75/module/z80/ins.hpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Copyright (c) 1990-2020 Hex-Rays - * ALL RIGHTS RESERVED. - * - */ - -#ifndef __INSTRS_HPP -#define __INSTRS_HPP - -extern const instruc_t Instructions[]; - -enum nameNum ENUM_SIZE(uint16) -{ -I5_null = 0, // Unknown Operation - -// -// Intel 8080-8085 instructions -// - -I5_aci, -I5_adc, Z80_adc = I5_adc, -I5_add, Z80_add = I5_add, -I5_adi, -I5_ana, -I5_ani, -I5_call, -I5_cnz, -I5_cz, -I5_cnc, -I5_cc, -I5_cpo, -I5_cpe, -I5_cp, -I5_cm, -I5_cmc, -I5_cmp, -I5_cpi, -I5_cma, -I5_daa, -I5_dad, -I5_dcr, -I5_dcx, -I5_di, Z80_di = I5_di, -I5_ei, Z80_ei = I5_ei, -I5_halt, -I5_in, Z80_in = I5_in, -I5_inr, -I5_inx, -I5_jmp, -I5_jnz, -I5_jz, -I5_jnc, -I5_jc, -I5_jpo, -I5_jpe, -I5_jp, -I5_jm, -I5_lda, -I5_ldax, -I5_lhld, -I5_lxi, -I5_mov, -I5_mvi, -I5_nop, -I5_ora, -I5_ori, -I5_out, Z80_out = I5_out, -I5_pchl, -I5_pop, Z80_pop = I5_pop, -I5_push, Z80_push = I5_push, -I5_ret, -I5_rnz, -I5_rz, -I5_rnc, -I5_rc, -I5_rpo, -I5_rpe, -I5_rp, -I5_rm, -I5_ral, -I5_rlc, -I5_rar, -I5_rrc, -I5_rst, -I5_sbb, -I5_sbi, -I5_stc, -I5_sphl, -I5_sta, -I5_stax, -I5_shld, -I5_sui, -I5_sub, Z80_sub = I5_sub, -I5_xra, -I5_xri, -I5_xchg, -I5_xthl, - -I5_rim, -I5_sim, - -// -// Z80 extensions -// - -Z80_and, -Z80_bit, -Z80_call, -Z80_ccf, -Z80_cp, -Z80_cpd, -Z80_cpdr, -Z80_cpi, -Z80_cpir, -Z80_cpl, -Z80_dec, -Z80_djnz, -Z80_ex, -Z80_exx, -Z80_halt, -Z80_im, -Z80_inc, -Z80_ind, -Z80_indr, -Z80_ini, -Z80_inir, -Z80_jp, -Z80_jr, -Z80_ld, -Z80_ldd, -Z80_lddr, -Z80_ldi, -Z80_ldir, -Z80_neg, -Z80_or, -Z80_otdr, -Z80_otir, -Z80_outd, -Z80_outi, -Z80_res, -Z80_ret, -Z80_reti, -Z80_retn, -Z80_rl, -Z80_rla, -Z80_rlc, -Z80_rlca, -Z80_rld, -Z80_rr, -Z80_rra, -Z80_rrc, -Z80_rrca, -Z80_rrd, -Z80_scf, -Z80_sbc, -Z80_set, -Z80_sla, -Z80_sra, -Z80_srl, -Z80_xor, -Z80_inp, // undocumented -Z80_outp, // undocumented -Z80_srr, // undocumented - -// -// HD64180 extensions -// - -HD_in0, Z80_in0 = HD_in0, -HD_mlt, Z80_mlt = HD_mlt, -HD_otim, Z80_otim = HD_otim, -HD_otimr, Z80_otimr = HD_otimr, -HD_otdm, Z80_otdm = HD_otdm, -HD_otdmr, Z80_otdmr = HD_otdmr, -HD_out0, Z80_out0 = HD_out0, -HD_slp, Z80_slp = HD_slp, -HD_tst, Z80_tst = HD_tst, -HD_tstio, Z80_tstio = HD_tstio, - -// -// A80 special instructions -// - -A80_lbcd, -A80_lded, -A80_lspd, -A80_lixd, -A80_liyd, -A80_sbcd, -A80_sded, -A80_sspd, -A80_sixd, -A80_siyd, -A80_xtix, -A80_xtiy, -A80_spix, -A80_spiy, -A80_pcix, -A80_pciy, -A80_mvra, -A80_mvia, -A80_mvar, -A80_mvai, -A80_addix, -A80_addiy, -A80_addc, -A80_addcix, -A80_addciy, -A80_subc, -A80_subcix, -A80_subciy, -A80_jrc, -A80_jrnc, -A80_jrz, -A80_jrnz, -A80_cmpi, -A80_cmpd, -A80_im0, -A80_im1, -A80_im2, -A80_otd, -A80_oti, - -// Intel 8085 undocumented instructions -// (info from http://oak.oakland.edu/pub/cpm/maclib/i8085.lib) - -I5_dsub, // (HL) <- (HL)-(BC), affects all flags -I5_arhl, // SHIFT HL RIGHT ONE BIT, (H7 IS DUPLICATED, L0 IS SHIFTED INTO CY) -I5_rdel, // ROTATE DE LEFT ONE BIT THRU CY, (E0 RECEIVES CY, CY RECEIVES D7) -I5_ldhi, // (DE) <- (HL)+arg -I5_ldsi, // (DE) <- (SP)+arg -I5_shlx, // ((DE)) <- (HL) -I5_lhlx, // (HL) <- ((DE)) -I5_rstv, // RESTART 40H ON V (OVERFLOW) -I5_jx5, // JUMP IF X5 SET -I5_jnx5, // JUMP IF NOT X5 SET - -// Z380 instructions - -Z80_cplw, // Complement HL register -Z80_swap, // Swap upper register word with lower register word -Z80_inw, // Input word -Z80_outw, // Output word -Z80_ldw, // Load word -Z80_addw, // Add word -Z80_subw, // Subtract word -Z80_adcw, // Add with carry word -Z80_sbcw, // Subtract with borrow word -Z80_andw, // AND logical word -Z80_xorw, // XOR logical word -Z80_orw, // OR logical word -Z80_cpw, // Compare word -Z80_ddir, // Decoder directive -Z80_calr, // Call relative -Z80_ldctl, // Load control register -Z80_mtest, // Mode test -Z80_exxx, // Exchange Index Register with Alternate Bank -Z80_exxy, // Exchange Index Register with Alternate Bank -Z80_exall, // Exchange all registers with Alternate Bank -Z80_setc, // Set control bit -Z80_resc, // Reset control bit -Z80_rlcw, // Rotate Left Circular Word -Z80_rrcw, // Rotate Right Circular Word -Z80_rlw, // Rotate Left Word -Z80_rrw, // Rotate Right Word -Z80_slaw, // Shift Left Arithmetic Word -Z80_sraw, // Shift Right Arithmetic Word -Z80_srlw, // Shift Right Logical Word -Z80_multw, // Multiply Word -Z80_multuw, // Multiply Word Unsigned -Z80_divuw, // Divide unsigned -Z80_outaw, // Output word direct to port address -Z80_inaw, // Input word direct from port address -Z80_outa, // Output byte direct to port address -Z80_ina, // Input byte direct from port address -Z80_negw, // Negate word -Z80_exts, // Extend byte sign -Z80_extsw, // Extend word sign -Z80_btest, // Bank test -Z80_ldiw, // Load and increment (word) -Z80_ldirw, // Load and increment, repeat (word) -Z80_lddw, // Load and decrement (word) -Z80_lddrw, // Load and decrement, repeat (word) -Z80_iniw, // Input and increment (word) -Z80_inirw, // Input and increment, repeat (word) -Z80_indw, // Input and decrement (word) -Z80_indrw, // Input and decrement, repeat (word) -Z80_outiw, // Output and increment (word) -Z80_otirw, // Output and increment, repeat (word) -Z80_outdw, // Output and decrement (word) -Z80_otdrw, // Output and decrement, repeat (word) - -// Gameboy instructions - -GB_ldh, -GB_stop, - -I5_last, - - }; - -#endif diff --git a/idasdk75/module/z80/makefile b/idasdk75/module/z80/makefile deleted file mode 100644 index e6876be..0000000 --- a/idasdk75/module/z80/makefile +++ /dev/null @@ -1,43 +0,0 @@ -PROC=z80 -CONFIGS=z180.cfg - -include ../module.mak - -# MAKEDEP dependency list ------------------ -$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - ana.cpp i5.hpp ins.hpp -$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)problems.hpp $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ - ../iohandler.hpp emu.cpp i5.hpp ins.hpp -$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ - $(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ - $(I)xref.hpp ins.cpp ins.hpp -$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - i5.hpp ins.hpp out.cpp -$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ - $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ - i5.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/z80/reg.cpp b/idasdk75/module/z80/reg.cpp deleted file mode 100644 index 6833302..0000000 --- a/idasdk75/module/z80/reg.cpp +++ /dev/null @@ -1,1072 +0,0 @@ -/* - * Interactive disassembler (IDA). - * Version 2.06 - * Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet) - * ALL RIGHTS RESERVED. - * - */ - -#include "i5.hpp" -#include <diskio.hpp> - -static const char *const RegNames[] = -{ - "b", "c", "d", "e", "h", "l", "m", "a", // 0..7 - "bc", "de", "hl","psw","sp","ix","iy","af'", // 8..15 - "r", "i", "f", "xl", "xh","yl","yh", // 16..22 - - "w", "lw", "ixl", "ixu", "dsr", "xsr", "iyl", - "iyu", "ysr", "sr", "ib", "iw", "xm", "lck", - "bc'", "de'", "hl'","ix'","iy'", - "b'", "c'", "d'", "e'", "h'", "l'", "m'", "a'", - - "cs","ds" -}; - -//----------------------------------------------------------------------- -// PseudoSam assembler definiton -//----------------------------------------------------------------------- -static const char *const ps_headers[] = -{ - ".code", - NULL -}; - -static const asm_t pseudosam = -{ - AS_COLON | ASH_HEXF1 | AS_N2CHR, - 0, - "PseudoSam by PseudoCode", - 0, - ps_headers, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".db", // ascii string directive - ".db", // byte directive - ".drw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".rs %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// TASM assembler definiton for 8085 -//----------------------------------------------------------------------- -static const char tasmname[] = "Table Driven Assembler (TASM) by Speech Technology Inc."; -static const asm_t tasm = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_NPAIR | UAS_NOENS, - tasmname, - 0, - NULL, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".text", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".block %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// TASM assembler definiton for Z80 -//----------------------------------------------------------------------- -static const asm_t tasmz80 = -{ - AS_COLON | AS_N2CHR | AS_1TEXT, - UAS_NOENS | UAS_TOFF, - "Table Driven Assembler (TASM) by Speech Technology Inc.", - 0, - NULL, - ".org", - ".end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\\\"'", // special symbols in char and string constants - - ".text", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".block %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// Cross-16 assembler definiton (8085) -//----------------------------------------------------------------------- -static const char *const cross16_headers[] = -{ - "cpu \"8085.tbl\"", - NULL -}; - -static const asm_t cross16 = -{ - AS_COLON | AS_NHIAS, - UAS_NPAIR, - "Cross-16 by Universal Cross-Assemblers", - 0, - cross16_headers, - "org", - "end", - - ";", // comment string - '"', // string delimiter - '\0', // char delimiter (no char consts) - "\\\"'", // special symbols in char and string constants - - "dfb", // ascii string directive - "dfb", // byte directive - "dwl", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// Cross-16 assembler definiton (z80) -//----------------------------------------------------------------------- -static const char *const cross16z80_headers[] = -{ - "cpu \"z80.tbl\"", - NULL -}; - -static const asm_t cross16z80 = -{ - AS_COLON | AS_NHIAS, - UAS_MKIMM, - "Cross-16 by Universal Cross-Assemblers", - 0, - cross16z80_headers, - "org", - "end", - - ";", // comment string - '"', // string delimiter - '\0', // char delimiter (no char consts) - "\\\"'", // special symbols in char and string constants - - "dfb", // ascii string directive - "dfb", // byte directive - "dwl", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "dfs %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// A80 assembler definiton -//----------------------------------------------------------------------- -static const asm_t a80 = -{ - AS_COLON | ASD_DECF1 | ASH_HEXF2 | AS_UNEQU, - UAS_NPAIR, - "A80 by ANTA electronics", - 0, - NULL, - "org", - NULL, - - ";", // comment string - '\'', // string delimiter - '\0', // char delimiter (no char consts) - "'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - NULL, // uninited arrays - "equ", - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// A80 assembler definiton (Z80) -//----------------------------------------------------------------------- -static const asm_t a80z = -{ - AS_COLON | ASD_DECF1 | ASH_HEXF2 | AS_UNEQU, - UAS_NPAIR | UAS_UNDOC | UAS_FUNNY, - "A80 by ANTA electronics", - 0, - NULL, - "adr", - NULL, - - ";", // comment string - '\'', // string delimiter - '\0', // char delimiter (no char consts) - "'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - NULL, // uninited arrays - "equ", - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// Avocet Macro Preprocessor v1.0 by Avocet Systems, Inc. -//----------------------------------------------------------------------- -static const char *const avocet_headers[] = -{ - "; $chip(HD64180) ; please uncomment and place as first line for HD64180", - " defseg allseg, absolute ; make avocet think that we have", - " seg allseg ; one big absolute segment", - NULL -}; - -static const asm_t avocet = -{ - AS_NHIAS, - 0, - "Avocet Macro Preprocessor v1.0 by Avocet Systems, Inc.", - 0, - avocet_headers, - "org", - "end", - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "\"'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//----------------------------------------------------------------------- -// ASxxxx by Alan R. Baldwin -//----------------------------------------------------------------------- -static const char *const asxxxx_headers[] = -{ - " .area idaseg (ABS)", - " .hd64 ; this is needed only for HD64180", - NULL -}; - -static const asm_t asxxxx = -{ - AS_NHIAS | AS_COLON | AS_NCHRE | AS_N2CHR | AS_1TEXT | ASH_HEXF3, - UAS_MKIMM | UAS_MKOFF | UAS_CNDUP, - "ASxxxx by Alan R. Baldwin v1.5", - 0, - asxxxx_headers, - ".org", - NULL, - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "'", // special symbols in char and string constants - - ".ascii", // ascii string directive - ".db", // byte directive - ".dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - ".ds %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//----------------------------------------------------------------------- -// X-M-80 by Leo Sandy, (8080) -//----------------------------------------------------------------------- -static const char *const xm80_headers[] = -{ - ".8080", - NULL -}; - -static const asm_t xm80 = -{ - AS_COLON | AS_NHIAS, - UAS_CSEGS, - "X-M-80 by Leo Sandy", - 0, - xm80_headers, - "org", - "end", - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// X-M-80 by Leo Sandy, (Z80) -//----------------------------------------------------------------------- -static const char *const xm80z_headers[] = -{ - ".Z80", - NULL -}; - -static const asm_t xm80z = -{ - AS_COLON | AS_NHIAS, - UAS_CSEGS, - "X-M-80 by Leo Sandy", - 0, - xm80z_headers, - "org", - "end", - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "'", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - NULL, // equ - NULL, // seg prefix - NULL, // curip - NULL, // func_header - NULL, // func_footer - NULL, // public - NULL, // weak - NULL, // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - NULL, // mod - NULL, // and - NULL, // or - NULL, // xor - NULL, // not - NULL, // shl - NULL, // shr - NULL, // sizeof -}; - - -//----------------------------------------------------------------------- -// Zilog Macro Assembler (ZMASM) -//----------------------------------------------------------------------- -static const asm_t zmasm = -{ - ASH_HEXF0 // 34h - |ASD_DECF0 // 34 - |ASO_OCTF0 // 123o - |ASB_BINF0 // 010101b - |AS_N2CHR // can't have 2 byte char consts - |AS_COLON // ':' after all labels - |AS_ASCIIC // ascii directive accepts C-like strings - |AS_ONEDUP, // one dup directive per line - UAS_ZMASM, - "Zilog Macro Assembler", - 0, - NULL, // headers - "org", - "end", - - ";", // comment string - '\'', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - ".ascii", // ascii string directive - "db", // byte directive - "dw", // word directive - "dl", // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - ".float", // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - "#h [ #d ], #v", // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // equ - NULL, // seg prefix - "$", // curip - NULL, // func_header - NULL, // func_footer - "public", // public - NULL, // weak - "extern", // extrn - NULL, // comm - NULL, // get_type_name - "align", // align - ' ', ' ', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -//----------------------------------------------------------------------- -// RGBAsm v1.11 (part of ASMotor 1.10) -//----------------------------------------------------------------------- -static const asm_t rgbasm = -{ - ASH_HEXF4 // $34 - |ASD_DECF0 // 34 - |ASO_OCTF3 // @123 (in fact this should be &123) - |ASB_BINF2 // %010101 - |AS_N2CHR // can't have 2 byte char consts - |AS_COLON, // ':' after all labels - UAS_GBASM, - "RGBAsm (part of ASMotor)", - 0, - NULL, // headers - "org", - NULL, // end - - ";", // comment string - '"', // string delimiter - '\'', // char delimiter - "'\"", // special symbols in char and string constants - - "db", // ascii string directive - "db", // byte directive - "dw", // word directive - NULL, // dword (4 bytes) - NULL, // qword (8 bytes) - NULL, // oword (16 bytes) - NULL, // float (4 bytes) - NULL, // double (8 bytes) - NULL, // tbyte (10/12 bytes) - NULL, // packed decimal real - NULL, // arrays (#h,#d,#v,#s(...) - "ds %s", // uninited arrays - "equ", // equ - NULL, // seg prefix - "@", // curip - NULL, // func_header - NULL, // func_footer - "export", // public - NULL, // weak - "import", // extrn - NULL, // comm - NULL, // get_type_name - NULL, // align - ' ', ' ', // lbrace, rbrace - "%", // mod - "&", // and - "|", // or - "^", // xor - "~", // not - "<<", // shl - ">>", // shr - NULL, // sizeof -}; - -static const asm_t *const i8085asms[] = { &tasm, &xm80, &pseudosam, &cross16, &a80, NULL }; -static const asm_t *const Z80asms[] = { &zmasm, &tasmz80, &xm80z, &pseudosam, &cross16z80, &a80z, &avocet, &asxxxx, NULL }; -static const asm_t *const HD64180asms[] = { &zmasm, &tasmz80, &avocet, &asxxxx, NULL }; -static const asm_t *const GBasms[] = { &rgbasm, NULL }; - -//------------------------------------------------------------------ -const char *z80_t::find_ioport(uval_t port) -{ - const ioport_t *p = ::find_ioport(ioh.ports, port); - return p ? p->name.c_str() : NULL; -} - -//------------------------------------------------------------------ -const char *z80_t::find_ioport_bit(int port, int bit) -{ - const ioport_bit_t *p = ::find_ioport_bit(ioh.ports, port, bit); - return p ? p->name.c_str() : NULL; -} - -//------------------------------------------------------------------ -void z80_t::choose_device(int respinfo) -{ - char cfgfile[QMAXFILE]; - ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); - iohandler_t::parse_area_line0_t cb(ioh); - if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) - ioh.set_device_name(ioh.device.c_str(), respinfo); -} - -//------------------------------------------------------------------ -const char *z80_t::set_idp_options( - const char *keyword, - int /*value_type*/, - const void * /*value*/, - bool /*idb_loaded*/) -{ - if ( keyword != NULL ) - return IDPOPT_BADKEY; - choose_device(IORESP_NONE); - return IDPOPT_OK; -} - -//----------------------------------------------------------------------- -static bool idaapi can_have_type(const op_t &x) // returns 1 - operand can have -{ - switch ( x.type ) - { - case o_void: // No Operand - case o_reg: // General Register - case o_phrase: // Base Reg + Index Reg - case o_cond: // FPP register - return 0; - } - return 1; -} - - -//---------------------------------------------------------------------- -static char const features[] = { _PT_8085, _PT_Z80, _PT_64180, _PT_Z180, _PT_Z380, _PT_GB }; - -//---------------------------------------------------------------------- -void z80_t::set_cpu(int np) -{ - pflag = features[np]; - ph.assemblers = i8085asms; - if ( isZ80() ) - ph.assemblers = Z80asms; - if ( is64180() ) - ph.assemblers = HD64180asms; - if ( isGB() ) - ph.assemblers = GBasms; -} - -//---------------------------------------------------------------------- -// This old-style callback only returns the processor module object. -static ssize_t idaapi notify(void *, int msgid, va_list) -{ - if ( msgid == processor_t::ev_get_procmod ) - return size_t(new z80_t); - return 0; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi z80_t::on_event(ssize_t msgid, va_list va) -{ - int _code = 0; - switch ( msgid ) - { - case processor_t::ev_init: - helper.create("$ z80"); - break; - - case processor_t::ev_newprc: - { - int np = va_arg(va, int); - // bool keep_cfg = va_argi(va, bool); - set_cpu(np); - } - break; - - case processor_t::ev_ending_undo: - set_cpu(ph.get_proc_index()); - //fall through - case processor_t::ev_oldfile: - ioh.restore_device(); - break; - - case processor_t::ev_newfile: - if ( inf_get_procname() == "z180" ) - choose_device(IORESP_AREA); - break; - - case processor_t::ev_out_header: - { - outctx_t *ctx = va_arg(va, outctx_t *); - i5_header(*ctx); - return 1; - } - - case processor_t::ev_out_footer: - { - outctx_t *ctx = va_arg(va, outctx_t *); - i5_footer(*ctx); - return 1; - } - - case processor_t::ev_out_segstart: - { - outctx_t *ctx = va_arg(va, outctx_t *); - segment_t *seg = va_arg(va, segment_t *); - i5_segstart(*ctx, seg); - return 1; - } - - case processor_t::ev_ana_insn: - { - insn_t *out = va_arg(va, insn_t *); - return i5_ana(out); - } - - case processor_t::ev_emu_insn: - { - const insn_t *insn = va_arg(va, const insn_t *); - return i5_emu(*insn) ? 1 : -1; - } - - case processor_t::ev_out_insn: - { - outctx_t *ctx = va_arg(va, outctx_t *); - out_insn(*ctx); - return 1; - } - - case processor_t::ev_out_operand: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const op_t *op = va_arg(va, const op_t *); - return out_opnd(*ctx, *op) ? 1 : -1; - } - - case processor_t::ev_can_have_type: - { - const op_t *op = va_arg(va, const op_t *); - return can_have_type(*op) ? 1 : -1; - } - - case processor_t::ev_set_idp_options: - { - const char *keyword = va_arg(va, const char *); - int value_type = va_arg(va, int); - const char *value = va_arg(va, const char *); - const char **errmsg = va_arg(va, const char **); - bool idb_loaded = va_argi(va, bool); - const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); - if ( ret == IDPOPT_OK ) - return 1; - if ( errmsg != NULL ) - *errmsg = ret; - return -1; - } - - // START OF DEBUGGER CALLBACKS - case processor_t::ev_next_exec_insn: - { - ea_t *target = va_arg(va, ea_t *); - ea_t ea = va_arg(va, ea_t); - int tid = va_arg(va, int); - getreg_t *getreg = va_arg(va, getreg_t *); - const regval_t *regvalues = va_arg(va, const regval_t *); - qnotused(tid); - *target = next_exec_insn(ea, getreg, regvalues); - return 1; - } - - case processor_t::ev_calc_step_over: - { - ea_t *target = va_arg(va, ea_t *); - ea_t ip = va_arg(va, ea_t); - *target = calc_step_over(ip); - return 1; - } - - case processor_t::ev_get_idd_opinfo: - { - idd_opinfo_t *opinf = va_arg(va, idd_opinfo_t *); - ea_t ea = va_arg(va, ea_t); - int n = va_arg(va, int); - int thread_id = va_arg(va, int); - getreg_t *getreg = va_arg(va, getreg_t *); - const regval_t *regvalues = va_arg(va, const regval_t *); - qnotused(thread_id); - return get_operand_info(opinf, ea, n, getreg, regvalues) ? 1 : 0; - } - - case processor_t::ev_get_reg_info: - { - const char **main_regname = va_arg(va, const char **); - bitrange_t *bitrange = va_arg(va, bitrange_t *); - const char *regname = va_arg(va, const char *); - return get_reg_info(main_regname, bitrange, regname) ? 1 : -1; - } - // END OF DEBUGGER CALLBACKS - - default: - break; - } - return _code; -} - -//----------------------------------------------------------------------- -#define FAMILY "Z80 processors:" - -static const char *const shnames[] = -{ - "8085", - "z80", - "64180", - "z180", - "z380", - "gb", - NULL -}; - -static const char *const lnames[] = -{ - FAMILY"Intel 8085", - "Zilog 80", - "Hitachi HD64180", - "Zilog Z180", - "Zilog Z380", - "GameBoy", - NULL -}; - -//----------------------------------------------------------------------- -static const uchar retcode_1[] = { 0xC9 }; -static const uchar retcode_2[] = { 0xED, 0x45 }; -static const uchar retcode_3[] = { 0xED, 0x4D }; - -static const bytes_t retcodes[] = -{ - { sizeof(retcode_1), retcode_1 }, - { sizeof(retcode_2), retcode_2 }, - { sizeof(retcode_3), retcode_3 }, - { 0, NULL } -}; - -//----------------------------------------------------------------------- -// Intel 8080/8085 processor definition -//----------------------------------------------------------------------- -processor_t LPH = -{ - IDP_INTERFACE_VERSION, // version - PLFM_Z80, // id - // flag - PRN_HEX - | PR_SEGTRANS, - // flag2 - PR2_IDP_OPTS, // the module has processor-specific configuration options - 8, // 8 bits in a byte for code segments - 8, // 8 bits in a byte for other segments - - shnames, - lnames, - - i8085asms, - - notify, - - RegNames, - R_vds+1, // number of registers - - R_vcs,R_vds, // first, last - 0, // size of a segment register - R_vcs,R_vds, // CS,DS - - NULL, // No known code start sequences - retcodes, // 'Return' instruction codes - - 0,I5_last, - Instructions, // instruc - 0, // int tbyte_size; -- doesn't exist - { 0, 0, 0, 0 }, // char real_width[4]; - // number of symbols after decimal point - // 2byte float (0-does not exist) - // normal float - // normal double - // long double - I5_ret, // Icode of return instruction. It is ok to give any of possible return instructions -}; diff --git a/idasdk75/module/z80/z180.cfg b/idasdk75/module/z80/z180.cfg deleted file mode 100644 index ca3a3a2..0000000 --- a/idasdk75/module/z80/z180.cfg +++ /dev/null @@ -1,239 +0,0 @@ -.Z80180 -; Enhanced Z80 Megacell -; http://www.zilog.com/products/partdetails.asp?id=Z80180 - - -; INPUT/ OUTPUT PORTS - -CNTLA0 0x0000 ASCI Channel Control Register A 0 -CNTLA0.MPE 7 Multi-Processor Mode Enable -CNTLA0.RE 6 Receiver Enable -CNTLA0.TE 5 Transmitter Enable -CNTLA0._RTS0 4 Request to Send Channel 0 -CNTLA0.MPBR_EFR 3 Multiprocessor Bit Receive/Error Flag Reset -CNTLA0.MOD2 2 ASCI Data Format Mode 2 -CNTLA0.MOD1 1 ASCI Data Format Mode 1 -CNTLA0.MOD0 0 ASCI Data Format Mode 0 - -CNTLA1 0x0001 ASCI Channel Control Register A 0 -CNTLA1.MPE 7 Multi-Processor Mode Enable -CNTLA1.RE 6 Receiver Enable -CNTLA1.TE 5 Transmitter Enable -CNTLA1._RTS0 4 Request to Send Channel 0 -CNTLA1.MPBR_EFR 3 Multiprocessor Bit Receive/Error Flag Reset -CNTLA1.MOD2 2 ASCI Data Format Mode 2 -CNTLA1.MOD1 1 ASCI Data Format Mode 1 -CNTLA1.MOD0 0 ASCI Data Format Mode 0 - -CNTLB0 0x0002 ASCI Channel Control Register B 0 -CNTLB0.MPBT 7 Multiprocessor Bit Transmit -CNTLB0.MP 6 Multiprocessor Mode -CNTLB0.__CTS_PS 5 Clear to Send/Prescale -CNTLB0.PEO 4 Parity Even Odd -CNTLB0.DR 3 Divide Ratio -CNTLB0.SS2 2 Source/Speed Select 2 -CNTLB0.SS1 1 Source/Speed Select 1 -CNTLB0.SS0 0 Source/Speed Select 0 - -CNTLB1 0x0003 ASCI Channel Control Register B 1 -CNTLB1.MPBT 7 Multiprocessor Bit Transmit -CNTLB1.MP 6 Multiprocessor Mode -CNTLB1.__CTS_PS 5 Clear to Send/Prescale -CNTLB1.PEO 4 Parity Even Odd -CNTLB1.DR 3 Divide Ratio -CNTLB1.SS2 2 Source/Speed Select 2 -CNTLB1.SS1 1 Source/Speed Select 1 -CNTLB1.SS0 0 Source/Speed Select 0 - -STAT0 0x0004 ASCI Status Register 0 -STAT0.RDRF 7 Receive Data Register Full -STAT0.OVRN 6 Overrun Error -STAT0.PE 5 Parity Error -STAT0.FE 4 Framing Error -STAT0.REI 3 Receive Interrupt Enable -STAT0._DCD0 2 Data Carrier Detect -STAT0.TDRE 1 Transmit Data Register Empty -STAT0.TIE 0 Transmit Interrupt Enable - -STAT1 0x0005 ASCI Status Register 1 -STAT1.RDRF 7 Receive Data Register Full -STAT1.OVRN 6 Overrun Error -STAT1.PE 5 Parity Error -STAT1.FE 4 Framing Error -STAT1.REI 3 Receive Interrupt Enable -STAT1.TDRE 1 Transmit Data Register Empty -STAT1.TIE 0 Transmit Interrupt Enable - -TDR0 0x0006 -TDR1 0x0007 -RDR0 0x0008 -RDR1 0x0009 - -CNTR 0x000A CSIO Control/Status Register -CNTR.EF 7 End Flag -CNTR.EIE 6 End Interrupt Enable -CNTR.RE 5 Receive Enable -CNTR.TE 4 Transmit Enable -CNTR.SS2 2 Speed Select 2 -CNTR.SS1 1 Speed Select 1 -CNTR.SS0 0 Speed Select 0 - -TRDR 0x000B CSIO Transmit/Receive Data Register -TMDR0L 0x000C Timer Data Register Channel 0L -TMDR0H 0x000D Timer Data Register Channel 0H -RLDR0L 0x000E Timer Reload Register 0L -RLDR0H 0x000F Timer Reload Register 0H - -TCR 0x0010 Timer Control Register -TCR.TIF1 7 Timer Interrupt Flag 1 -TCR.TIF0 6 Timer Interrupt Flag 0 -TCR.TIE1 5 Timer Interrupt Enable 1 -TCR.TIE0 4 Timer Interrupt Enable 0 -TCR.TOC1 3 Timer Output Control -TCR.TOC0 2 Timer Output Control -TCR.TDE1 1 -TCR.TDE0 0 - -TMDR1L 0x0014 Timer Data Register Channel 1L -TMDR1H 0x0015 Timer Data Register Channel 1H -RLDR1L 0x0016 Timer Reload Register 1L -RLDR1H 0x0017 Timer Reload Register 1H -FRC 0x0018 Free Running Counter -SAR0L 0x0020 DMA Source Address Register Channel 0L -SAR0H 0x0021 DMA Source Address Register Channel 0H -SAR0B 0x0022 DMA Source Address Register Channel 0B -DAR0L 0x0023 DMA Destination Address Register Channel 0L -DAR0H 0x0024 DMA Destination Address Register Channel 0H -DAR0B 0x0025 DMA Destination Address Register Channel 0B -BCR0L 0x0026 DMA Byte Count Register Channel 0L -BCR0H 0x0027 DMA Byte Count Register Channel 0H -MAR1L 0x0028 DMA Memory Address Register, Channel 1L -MAR1H 0x0029 DMA Memory Address Register, Channel 1H -MAR1B 0x002A DMA Memory Address Register, Channel 1B -IAR1L 0x002B DMA I/O Address Register Channel 1L -IAR1H 0x002C DMA I/O Address Register Channel 1H -BCR1L 0x002E DMA Byte Count Register Channel 1L -BCR1H 0x002F DMA Byte Count Register Channel 1H - -DSTAT 0x0030 DMA Status Register -DSTAT.DE1 7 DE1: DMA Enable Channel 1 -DSTAT.DE0 6 DE0: DMA Enable Channel 0 -DSTAT.DWE1 5 DE1 Bit WRITE Enable -DSTAT.DWE0 4 DE0 Bit WRITE Enable -DSTAT.DIE1 3 DMA Interrupt Enable Channel -DSTAT.DIE0 2 DMA Interrupt Enable Channel -DSTAT.DME 0 DMA Main Enable - -DMODE 0x0031 DMA Mode Register -DMODE.DM1 5 Destination Mode Channel 0 -DMODE.DM0 4 Destination Mode Channel 0 -DMODE.SM1 3 Source Mode Channel 0 -DMODE.SM0 2 Source Mode Channel 0 -DMODE.MMOD 1 Memory Mode Channel 0 - -DCNTL 0x0032 DMA/WAIT Control Register -DCNTL.MWI1 7 Memory Wait Insertion -DCNTL.MWI0 6 Memory Wait Insertion -DCNTL.IWI1 5 I/O Wait Insertion -DCNTL.IWI0 4 I/O Wait Insertion -DCNTL.DMS1 3 DMA Request Sense -DCNTL.DMS0 2 DMA Request Sense -DCNTL.DIM1 1 DMA Channel 1 I/O and Memory Mode -DCNTL.DIM0 0 DMA Channel 1 I/O and Memory Mode - -IL 0x0033 Interrupt Vector Low Register -IL.IL7 7 -IL.IL6 6 -IL.IL5 5 - -ITC 0x0034 Int/TRAP Control Register -ITC.TRAP 7 -ITC.UFO 6 Undefined Fetch Object -ITC.ITE2 2 Interrupt Enable 2 -ITC.ITE1 1 Interrupt Enable 1 -ITC.ITE0 0 Interrupt Enable 0 - -RCR 0x0036 Refresh Control Register -RCR.REFE 7 Refresh Enable -RCR.REFW 6 Refresh Wait -RCR.CYC1 1 Cycle Interval -RCR.CYC0 0 Cycle Interval - -CBR 0x0038 MMU Common Base Register (CBR) -CBR.CB7 7 -CBR.CB6 6 -CBR.CB5 5 -CBR.CB4 4 -CBR.CB3 3 -CBR.CB2 2 -CBR.CB1 1 -CBR.CB0 0 - -BBR 0x0039 MMU Bank Base Register (BBR) -BBR.BB7 7 -BBR.BB6 6 -BBR.BB5 5 -BBR.BB4 4 -BBR.BB3 3 -BBR.BB2 2 -BBR.BB1 1 -BBR.BB0 0 - -CBAR 0x003A MMU Common/Bank Area Register (CBAR) -CBAR.CA3 7 -CBAR.CA2 6 -CBAR.CA1 5 -CBAR.CA0 4 -CBAR.BA3 3 -CBAR.BA2 2 -CBAR.BA1 1 -CBAR.BA0 0 - -OMCR 0x003E Operation Mode Control Register -OMCR.MIE 7 -OMCR._MITE 6 -OMCR._IOC 5 - -ICR 0x003F I/O Control Register (ICR) -ICR.IOA7 7 -ICR.IOA6 6 -ICR.IOSTP 5 - - - -.Z80181 -; Smart Access Controller - -.Z80182 -; ZiLOG Intelligent Peripheral (ZIPT) - -.Z80189 - -.Z8S180 -; + Parallel I/O - -.Z80195 -; Smart Peripheral Controller (ROMless) - -.Z80L183 -; Mixed-Signal Z183 Internet Processor - -.Z80S183 -. Mixed-Signal Z183 Internet Processor - -.Z8L180 -; Enhanced Z80 Megacell - -.Z8L180 -; Low-Voltage Version (3.3 V) - -.Z8L182 -; ZiLOG Intelligent Peripheral (ZIPT) - Low Voltage Version - -.Z8S180 -; Enhanced Z80 Megacell - -.Z8L180 -; Low-Voltage Version (3.3 V) - - diff --git a/idasdk75/plugins/callee/makefile b/idasdk75/plugins/callee/makefile deleted file mode 100644 index a97397e..0000000 --- a/idasdk75/plugins/callee/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=callee - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)callee$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ - $(I)xref.hpp callee.cpp diff --git a/idasdk75/plugins/callgraph/callgraph.cpp b/idasdk75/plugins/callgraph/callgraph.cpp deleted file mode 100644 index 7b52726..0000000 --- a/idasdk75/plugins/callgraph/callgraph.cpp +++ /dev/null @@ -1,1560 +0,0 @@ -#include "callgraph.h" - -static bool get_graph_title(ea_t ea, qstring *out); -//------------------------------------------------------------------------- -// The main action to invoke the plugin -struct show_callgraph_ah_t : public action_handler_t -{ - plugin_ctx_t &ctx; - show_callgraph_ah_t(plugin_ctx_t &_ctx) : ctx(_ctx) {} - virtual int idaapi activate(action_activation_ctx_t *) override; - virtual action_state_t idaapi update(action_update_ctx_t *) override - { - return AST_ENABLE_ALWAYS; - } -}; - -#define ACTION_NAME "callgraph:ShowCallgraph" -#define ACTION_LABEL "Function call graph" - -//------------------------------------------------------------------------- -// Base class for additional actions in the graph view -struct cg_ah_t : public action_handler_t -{ - plugin_ctx_t &plg; - cg_ah_t(plugin_ctx_t &p) : plg(p) {} - virtual int act(graph_info_t *gi) = 0; - - virtual int idaapi activate(action_activation_ctx_t *ctx) override - { - graph_info_t *gi = graph_info_t::find(plg, (graph_viewer_t *) ctx->widget); - return gi != nullptr ? act(gi) : 0; - } - - virtual action_state_t idaapi update(action_update_ctx_t *ctx) override - { - return graph_info_t::find(plg, (graph_viewer_t *) ctx->widget) != nullptr - ? AST_ENABLE_FOR_WIDGET - : AST_DISABLE_FOR_WIDGET; - } -}; - -//------------------------------------------------------------------------- -#define DECLARE_ACTION_HANDLER(Method) \ -struct Method##_ah_t : public cg_ah_t \ -{ \ - Method##_ah_t(plugin_ctx_t &p) : cg_ah_t(p) {} \ - virtual int act(graph_info_t *gi) override \ - { \ - return int(gi->fg.Method(gi)); \ - } \ -} -DECLARE_ACTION_HANDLER(options); -DECLARE_ACTION_HANDLER(refresh); -DECLARE_ACTION_HANDLER(jumpxref); -DECLARE_ACTION_HANDLER(jumpaddr); -DECLARE_ACTION_HANDLER(jump); -DECLARE_ACTION_HANDLER(back); -DECLARE_ACTION_HANDLER(forward); -DECLARE_ACTION_HANDLER(center); -DECLARE_ACTION_HANDLER(select); -DECLARE_ACTION_HANDLER(home); -DECLARE_ACTION_HANDLER(searchfirst); -DECLARE_ACTION_HANDLER(searchnext); -DECLARE_ACTION_HANDLER(hidenode); -DECLARE_ACTION_HANDLER(showhidden); -DECLARE_ACTION_HANDLER(showall); -#undef DECLARE_ACTION_HANDLER - -//-------------------------------------------------------------------------- -struct plugin_ctx_t : public plugmod_t, public event_listener_t -{ - show_callgraph_ah_t show_callgraph_ah = show_callgraph_ah_t(*this); - const action_desc_t main_action = ACTION_DESC_LITERAL_PLUGMOD( - ACTION_NAME, - ACTION_LABEL, - &show_callgraph_ah, - this, - "Ctrl+Shift+B", - nullptr, -1); -#define DEFINE_ACTION_HANDLER(Method) Method##_ah_t Method##_ah = Method##_ah_t(*this) //lint !e773 macro not parenthized - DEFINE_ACTION_HANDLER(options); - DEFINE_ACTION_HANDLER(refresh); - DEFINE_ACTION_HANDLER(jumpxref); - DEFINE_ACTION_HANDLER(jumpaddr); - DEFINE_ACTION_HANDLER(jump); - DEFINE_ACTION_HANDLER(back); - DEFINE_ACTION_HANDLER(forward); - DEFINE_ACTION_HANDLER(center); - DEFINE_ACTION_HANDLER(select); - DEFINE_ACTION_HANDLER(home); - DEFINE_ACTION_HANDLER(searchfirst); - DEFINE_ACTION_HANDLER(searchnext); - DEFINE_ACTION_HANDLER(hidenode); - DEFINE_ACTION_HANDLER(showhidden); - DEFINE_ACTION_HANDLER(showall); -#undef DEFINE_ACTION_HANDLER - const action_desc_t actions[15] = - { -#define ROW(Method, Label, Shortcut) \ - ACTION_DESC_LITERAL_PLUGMOD("callgraph:" #Method, Label, &Method##_ah, this, Shortcut, nullptr, -1) - ROW(options, "Options", "O"), // 1 - ROW(refresh, "Refresh", "R"), // 2 - ROW(jumpxref, "Jump to xref", "X"), // 3 - ROW(jumpaddr, "Jump to address", "G"), // 4 - ROW(jump, "Jump to function", "SPACE"), // 5 - ROW(back, "Jump to previous node", "ESC"), // 6 - ROW(forward, "Jump to next node", "Ctrl+Enter"), // 7 - ROW(center, "Center node", "Enter"), // 8 - ROW(select, "Select node", "Ctrl+L"), // 9 - ROW(home, "Goto to first node", "H"), // 0 - ROW(searchfirst, "Search first", "S"), // 1 - ROW(searchnext, "Search next", "N"), // 2 - ROW(hidenode, "Hide selected node", nullptr), // 3 - ROW(showhidden, "Show hidden node", nullptr), // 4 - ROW(showall, "Show all nodes", nullptr), // 5 -#undef ROW - }; - - graphinfo_list_t instances; - funcs_walk_options_t fg_opts = - { - FWO_VERSION, // version - FWO_CALLEE_RECURSE_UNLIM, // flags - 2, // max callees recursion - 1, // max callers recursion - 255 // max nodes per level - }; - - bool actions_registered = false; - - qstring last_text; //lint !e958 padding // see findfirst_node() - - virtual ssize_t idaapi on_event(ssize_t event_id, va_list) override; - virtual bool idaapi run(size_t arg) override; - plugin_ctx_t() - { - hook_event_listener(HT_VIEW, this); - } - bool register_main_action() - { - return register_action(main_action) - && attach_action_to_menu("View/Open subviews/Function calls", ACTION_NAME, SETMENU_APP); - } - bool load_options(); - qstring gen_graph_title(ea_t ea); - bool show_options(); - void ensure_actions_registered(); -}; - -//-------------------------------------------------------------------------- -int idaapi show_callgraph_ah_t::activate(action_activation_ctx_t *) -{ - ctx.run(0); - return 0; -} - -//-------------------------------------------------------------------------- -// Checks if a function is visited already -// If it is visited then true is returned and nid contains the node ID -bool callgraph_t::visited(ea_t func_ea, int *nid) -{ - ea_int_map_t::const_iterator it = ea2node.find(func_ea); - if ( it != ea2node.end() ) - { - if ( nid != nullptr ) - *nid = it->second; - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -void callgraph_t::add_fathers( - func_t * /*func*/, - ea_t func_start, - int id, - funcs_walk_options_t *opt, - int level) -{ - if ( level >= (opt->callers_recurse_limit+2) ) - { - return; - } - - //msg("Level %d, node 0x%08x\n", level, func_start); - xrefblk_t xb_to; - - for ( bool xb_to_ok = xb_to.first_to(func_start, XREF_FAR); - xb_to_ok && xb_to.iscode; - xb_to_ok = xb_to.next_to() ) - { - func_t *f_from = get_func(xb_to.from); - if ( f_from == nullptr ) - continue; - - int idto = add(f_from->start_ea); - //msg("Adding XREF to 1st node %d\n", idto); - create_edge(idto, id); - - add_fathers(f_from, f_from->start_ea, idto, opt, level+1); - } -} - -//-------------------------------------------------------------------------- -int callgraph_t::walk_func( - eavec_t *hide_nodes, - func_t *func, - funcs_walk_options_t *opt, - int level) -{ - // add a node for this function - ea_t func_start = func->start_ea; - - int id = add(func_start); - - // Add the callers of the 1st function - if ( level == 2 ) - { - add_fathers(func, func_start, id, opt, 2); - } - - int total = 0; - func_item_iterator_t fii; - - for ( bool fi_ok=fii.set(func); fi_ok; fi_ok=fii.next_code() ) - { - xrefblk_t xb; - for ( bool xb_ok = xb.first_from(fii.current(), XREF_FAR); - xb_ok && xb.iscode; - xb_ok = xb.next_from() ) - { - bool is_func_lib; - ea_t ea; - - func_t *f = get_func(xb.to); - if ( f == nullptr ) - { - ea = xb.to; - is_func_lib = true; - - if ( (opt->flags & FWO_SKIPLIB) != 0 ) - continue; - } - else - { - ea = f->start_ea; - is_func_lib = false; - } - - eavec_t::iterator hide_nodes_it; - - // Any node to hide? - if ( !hide_nodes->empty() ) - { - hide_nodes_it = std::find(hide_nodes->begin(), hide_nodes->end(), ea); - if ( *hide_nodes_it == ea ) - { - //msg("Hiding node 0x%08x\n", *hide_nodes_it); - continue; - } - } - - int id2 = -1; - if ( !visited(ea, &id2) ) - { - if ( func_contains(func, xb.to) ) - continue; - - bool skip = false; - - if ( opt != nullptr ) - { - skip = is_func_lib && (opt->flags & FWO_SKIPLIB) != 0 // skip lib funcs? - || ((opt->flags & FWO_CALLEE_RECURSE_UNLIM) == 0 // max recursion is off, and limit is reached? - && level > opt->callees_recurse_limit); - } - - // More nodes in this level than the maximum specified? - if ( total++ >= ctx.fg_opts.max_nodes ) - { - id2 = add((ea_t)VERTEX_HIDDEN_NODES); - create_edge(id, id2); - break; - } - - if ( skip ) - id2 = add(ea); - else if ( !is_func_lib ) - id2 = walk_func(hide_nodes, f, opt, level+1); - else if ( (opt->flags & FWO_SKIPLIB) == 0 ) - id2 = add(ea); - - if ( id2 != -1 ) - create_edge(id, id2); - } - //msg("Adding edge between %d and %d\n", id, id2); - } - } - return id; -} - -//-------------------------------------------------------------------------- -int callgraph_t::find_first(const char *text) -{ - if ( text == nullptr || text[0] == '\0' ) - return -1; - - qstrncpy(cur_text, text, sizeof(cur_text)); - cur_node = 0; - return find_next(); -} - -//-------------------------------------------------------------------------- -int callgraph_t::find_next() -{ - for ( int i = cur_node; i < node_count; i++ ) - { - const char *s = get_name(i); - if ( stristr(s, cur_text) != nullptr ) - { - cur_node = i + 1; - return i; - } - } - // reset search - cur_node = 0; - // nothing is found - return -1; -} - -//-------------------------------------------------------------------------- -void callgraph_t::create_edge(int id1, int id2) -{ - edges.push_back(edge_t(id1, id2)); -} - -//-------------------------------------------------------------------------- -void callgraph_t::reset() -{ - node_count = 0; - cur_node = 0; - cur_text[0] = '\0'; - ea2node.clear(); - node2ea.clear(); - cached_funcs.clear(); - edges.clear(); -} - -//-------------------------------------------------------------------------- -ea_t callgraph_t::get_addr(int nid) const -{ - int_ea_map_t::const_iterator it = node2ea.find(nid); - return it == node2ea.end() ? BADADDR : it->second; -} - -//-------------------------------------------------------------------------- -// Given an address, this function first returns ASCII string if found -// otherwise it returns a UNICODE string -// FIXME: not comprehensive, better follow the settings in strings options -size_t get_string(ea_t ea, qstring *out) -{ - const char *encodings[2] = - { - encoding_from_strtype(STRTYPE_C), - inf_is_be() ? ENC_UTF16BE : ENC_UTF16LE - }; - for ( int i = 0; i < qnumber(encodings); i++ ) - { - int enc_idx = add_encoding(encodings[i]); - uint32 strtype = STRTYPE_C | (enc_idx << 24); - size_t len = get_max_strlit_length(ea, strtype); - if ( len > 4 && get_strlit_contents(out, ea, len, strtype) > 0 ) - break; - out->qclear(); - } - return out->size(); -} - -//-------------------------------------------------------------------------- -bool get_strings(ea_t ea, qstring *out) -{ - qstring tmp; - - func_t *func = get_func(ea); - func_item_iterator_t fii; - for ( bool fi_ok=fii.set(func); fi_ok; fi_ok=fii.next_code() ) - { - xrefblk_t xb; - for ( bool xb_ok = xb.first_from(fii.current(), XREF_DATA); - xb_ok; - xb_ok = xb.next_from() ) - { - if ( get_string(xb.to, &tmp) > 0 ) - *out += tmp + "\n"; - } - } - - if ( out->size() > 1 ) - out->insert("\n\nStrings:\n"); - - return !out->empty(); -} - -//-------------------------------------------------------------------------- -callgraph_t::funcinfo_t *callgraph_t::get_info(int nid) -{ - funcinfo_t *ret = nullptr; - - do - { - // returned cached name - int_funcinfo_map_t::iterator it = cached_funcs.find(nid); - - if ( it != cached_funcs.end() ) - { - ret = &it->second; - break; - } - - // node does not exist? - int_ea_map_t::const_iterator it_ea = node2ea.find(nid); - if ( it_ea == node2ea.end() ) - break; - - funcinfo_t fi; - - qstring buf; - if ( ::get_name(&buf, it_ea->second) <= 0 ) - { - /* - ** NOTE: With patched databases it may fail for a reason unknown (ATM). - ** To test it, open an Objective-C app and patch it with the following - ** script: https://github.com/zynamics/objc-helper-plugin-ida - */ - if ( (int32)it_ea->second == VERTEX_HIDDEN_NODES ) - { - fi.name = "More nodes hidden..."; - } - else - { - msg("%a: Invalid address\n", it_ea->second); - fi.name = "?"; - } - } - else - { - qstring outbuf = buf; - qstring demangled; - if ( demangle_name(&demangled, buf.begin(), MNG_SHORT_FORM) > 0 ) - { - outbuf.append("\n"); - outbuf.append(demangled); - } - - // Assign the name - fi.name = outbuf; - - // Add the strings reference if set - qstring strings; - if ( (ctx.fg_opts.flags & FWO_SHOWSTRING) != 0 && get_strings(it_ea->second, &strings) ) - fi.strings = strings; - } - - // XXX: FIXME: UGLY HACK - // Use a special color for the selected node - if ( nid == 0 ) - { - fi.color = 0x44FF55; - } - else - { - // Is it an imported function? - segment_t *seg = getseg(it_ea->second); - if ( seg != nullptr && seg->type == SEG_XTRN ) - { - fi.color = 0xf000f0; - } - else - { - // XXX: FIXME Horrible... - func_t *f = get_func(it_ea->second); - if ( f != nullptr - && ((f->flags & FUNC_LIB) != 0 || buf[0] == '.') ) - { - fi.color = 0xfff000; - } - else - { - fi.color = calc_bg_color(it_ea->second); - } - } - } - - fi.ea = it_ea->second; - - it = cached_funcs.insert(cached_funcs.end(), std::make_pair(nid, fi)); //-V783 Dereferencing of the invalid iterator - ret = &it->second; - } while ( false ); - - return ret; -} - -//-------------------------------------------------------------------------- -const char *callgraph_t::get_name(int nid) -{ - funcinfo_t *fi = get_info(nid); - if ( fi == nullptr ) - return "?"; - else - return fi->name.c_str(); -} - -//-------------------------------------------------------------------------- -int callgraph_t::add(ea_t func_ea) -{ - ea_int_map_t::const_iterator it = ea2node.find(func_ea); - if ( it != ea2node.end() ) - return it->second; - - ea2node[func_ea] = node_count; - node2ea[node_count] = func_ea; - return node_count++; -} - -//-------------------------------------------------------------------------- -callgraph_t::callgraph_t(plugin_ctx_t &_ctx) : ctx(_ctx) -{ - cur_text[0] = '\0'; -} - -//-------------------------------------------------------------------------- -void callgraph_t::clear_edges() -{ - edges.clear(); -} - -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -//-------------------------------------------------------------------------- -bool graph_info_t::find(plugin_ctx_t &ctx, ea_t ea, iterator *out) -{ - iterator end = ctx.instances.end(); - for ( iterator it = ctx.instances.begin(); it != end; ++it ) - { - if ( (*it)->func_ea == ea ) - { - if ( out != nullptr ) - *out = it; - return true; - } - } - return false; -} - -//-------------------------------------------------------------------------- -graph_info_t *graph_info_t::find(plugin_ctx_t &ctx, ea_t ea) -{ - iterator it; - return find(ctx, ea, &it) ? *it : nullptr; -} - -//-------------------------------------------------------------------------- -graph_info_t *graph_info_t::find(plugin_ctx_t &ctx, const char *_title) -{ - for ( auto &gi : ctx.instances ) - if ( gi->title == _title ) - return gi; - return nullptr; -} - -//------------------------------------------------------------------------- -graph_info_t *graph_info_t::find(plugin_ctx_t &ctx, const graph_viewer_t *v) -{ - for ( auto &gi : ctx.instances ) - if ( gi->gv == v ) - return gi; - return nullptr; -} - -//-------------------------------------------------------------------------- -graph_info_t *graph_info_t::create(plugin_ctx_t &ctx, ea_t ea) -{ - graph_info_t *r = find(ctx, ea); - - // not there? create it - if ( r == nullptr ) - { - // we need a function! - func_t *pfn = get_func(ea); - if ( pfn == nullptr ) - return nullptr; - - r = new graph_info_t(ctx); - get_graph_title(ea, &r->title); - r->func_ea = pfn->start_ea; - ctx.instances.push_back(r); - - r->install_hooks(); - } - return r; -} - -//-------------------------------------------------------------------------- -// Check if the user changed any of the functions in the current graph -static void check_func_changed(ea_t ea, graph_info_t *gi) -{ - ea_int_map_t::const_iterator it = gi->fg.ea2node.find(ea); - if ( it != gi->fg.ea2node.end() ) - { - // The center node has been changed, destroy the current callgraph - if ( it->second == 0 ) - close_widget(gi->widget, WCLS_SAVE); - else - // A function shown in the callgraph has been changed, refresh - // the callgraph - gi->refresh(); - } -} - -//-------------------------------------------------------------------------- -// We hook to IDP event to receive processor module notifications -ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case idb_event::func_added: - case idb_event::func_updated: - case idb_event::deleting_func: - case idb_event::set_func_start: - case idb_event::set_func_end: - { - func_t *pfn = va_arg(va, func_t *); - check_func_changed(pfn->start_ea, gi); - break; - } - } - - return 0; -} - -//-------------------------------------------------------------------------- -// We hook to IDP event to receive processor module notifications -ssize_t idaapi idp_listener_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case processor_t::ev_create_switch_xrefs: - case processor_t::ev_add_cref: - case processor_t::ev_del_cref: - { - ea_t ea = va_arg(va, ea_t); - check_func_changed(ea, gi); - } - break; - } - - return 0; -} - -//-------------------------------------------------------------------------- -void graph_info_t::install_hooks() -{ - hook_event_listener(HT_IDP, &idp_listener, &ctx); - hook_event_listener(HT_IDB, &idb_listener, &ctx); -} - -//-------------------------------------------------------------------------- -void graph_info_t::remove_hooks() -{ - unhook_event_listener(HT_IDP, &idp_listener); - unhook_event_listener(HT_IDB, &idb_listener); -} - -//-------------------------------------------------------------------------- -void graph_info_t::destroy_graph(plugin_ctx_t &ctx, graph_info_t *gi) -{ - iterator it; - if ( find(ctx, gi->func_ea, &it) ) - { - ctx.instances.erase(it); - gi->remove_hooks(); - delete gi; - } -} - -//-------------------------------------------------------------------------- -// Get a new title for the form to be opened -qstring plugin_ctx_t::gen_graph_title(ea_t ea) -{ - // We should succeed in getting the name - qstring func_name; - if ( get_func_name(&func_name, ea) > 0 ) - { - qstring tmp; - for ( int i=1; i < 255; i++ ) - { - tmp.sprnt("Call graph: %s (%d)", func_name.begin(), i); - if ( find_widget(tmp.c_str()) == nullptr ) - return tmp; - } - } - return qstring(); -} - -//-------------------------------------------------------------------------- -static bool get_graph_title(ea_t ea, qstring *out) -{ - // we should succeed in getting the name - qstring func_name; - if ( get_func_name(&func_name, ea) <= 0 ) - return false; - - out->sprnt("Call graph: %s", func_name.begin()); - return true; -} - -//-------------------------------------------------------------------------- -void graph_info_t::mark_for_refresh() -{ - refresh_needed = true; -} - -//-------------------------------------------------------------------------- -void graph_info_t::mark_as_refreshed() -{ - refresh_needed = false; -} - -//-------------------------------------------------------------------------- -void graph_info_t::refresh() -{ - mark_for_refresh(); - refresh_viewer(gv); -} - -//-------------------------------------------------------------------------- -// -//-------------------------------------------------------------------------- -void idaapi callgraph_t::user_refresh( - void *ud, - int code, - va_list va, - int current_node) -{ - graph_info_t *gi = (graph_info_t *) ud; - callgraph_t *fg = &gi->fg; - qnotused(code); - qnotused(current_node); - if ( !gi->is_refresh_needed() ) - return; - - gi->mark_as_refreshed(); - fg->reset(); - - func_t *f = get_func(gi->func_ea); - if ( f == nullptr ) - { - msg("%a: Invalid function\n", gi->func_ea); - return; - } - - fg->walk_func(&gi->hide_nodes, f, &fg->ctx.fg_opts, 2); - - mutable_graph_t *mg = va_arg(va, mutable_graph_t *); - - // we have to resize - mg->reset(); - mg->resize(fg->count()); - - callgraph_t::edge_iterator it; - callgraph_t::edge_iterator end = fg->end_edges(); - - for ( it=fg->begin_edges(); it != end; ++it ) - mg->add_edge(it->id1, it->id2, nullptr); - - fg->clear_edges(); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi callgraph_t::gr_callback(void *ud, int code, va_list va) -{ - bool result = false; - graph_info_t *gi = (graph_info_t *) ud; - callgraph_t *fg = &gi->fg; - switch ( code ) - { - // a graph node has been double clicked - // in: graph_viewer_t *gv - // selection_item_t *current_item - // out: 0-ok, 1-ignore click - case grcode_dblclicked: - result = fg->center(gi); - break; - // refresh user-defined graph nodes and edges - // in: mutable_graph_t *g - // out: success - case grcode_user_refresh: - user_refresh(ud, code, va, -1); - result = true; - break; - - // retrieve text for user-defined graph node - // in: mutable_graph_t *g - // int node - // const char **result - // bgcolor_t *bg_color (maybe nullptr) - // out: must return 0, result must be filled - case grcode_user_text: - { - va_arg(va, mutable_graph_t *); - int node = va_arg(va, int); - const char **text = va_arg(va, const char **); - bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); - - callgraph_t::funcinfo_t *fi = fg->get_info(node); - result = fi != nullptr; - if ( result ) - { - qstring hint; - - hint = fi->name + fi->strings; - *text = hint.extract(); - //*text = fi->name.c_str(); - if ( bgcolor != nullptr ) - *bgcolor = fi->color; - } - break; - } - - // retrieve hint for the user-defined graph - // in: mutable_graph_t *g - // int mousenode - // int mouseedge_src - // int mouseedge_dst - // char **hint - // 'hint' must be allocated by qalloc() or qstrdup() - // out: 0-use default hint, 1-use proposed hint - case grcode_user_hint: - { - va_arg(va, mutable_graph_t *); - - int mousenode = va_argi(va, int); - int to = va_argi(va, int); - int from = va_argi(va, int); - char **hint = va_arg(va, char **); - - result = true; - - ea_t addr; - if ( mousenode != -1 && (addr = fg->get_addr(mousenode)) != BADADDR ) - { - qstrvec_t lines; - qstring all_lines; - - for ( int j=0; j < 16; j++ ) - { - int nl = generate_disassembly(&lines, nullptr, addr, 1024, false); - - for ( int i = 0; i < nl; i++ ) - { - all_lines.append(lines[i]); - all_lines.append('\n'); - } - addr = get_item_end(addr); - } - - *hint = all_lines.extract(); - } - else if ( mousenode == -1 ) - { - qstring line; - - if ( from != -1 && to != -1 ) - { - funcinfo_t *fifrom = fg->get_info(from); - funcinfo_t *fito = fg->get_info(to); - - // XXX: FIXME: Hack. It should be fixed hooking to del_func, etc... - if ( fifrom == nullptr || fito == nullptr ) - { - msg("Invalid function\n"); - result = false; - } - else - { - line.insert(fifrom->name.c_str()); - line.insert(" -> "); - line.insert(fito->name.c_str()); - - *hint = line.extract(); - } - } - } - break; - } - } - return (int)result; -} - -//-------------------------------------------------------------------------- -static const char *const NODE_NAME = "$ proximity browser"; - -bool plugin_ctx_t::load_options() -{ - funcs_walk_options_t opt; - netnode n(NODE_NAME); - if ( !exist(n) ) - return false; - - n.supval(1, &opt, sizeof(opt)); - - if ( opt.version != FWO_VERSION ) - return false; - - fg_opts = opt; - return true; -} - -//-------------------------------------------------------------------------- -static int idaapi options_cb(int fid, form_actions_t &fa) -{ - ushort opt = 0; - - if ( fid == FIELD_ID_CHILDS || fid == CB_INIT ) - { - if ( !fa.get_checkbox_value(FIELD_ID_CHILDS, &opt) ) - INTERR(562); - - // Disable recursion level textbox - fa.enable_field(FIELD_ID_CHILDS_LEVEL, !opt);//(opt & FWO_CALLEE_RECURSE_UNLIM) == 0); - } - - if ( fid == FIELD_ID_FATHERS ) - { - if ( !fa.get_checkbox_value(FIELD_ID_FATHERS, &opt) ) - INTERR(563); - - if ( opt > MAX_CALLERS_LEVEL ) - { - info("Sorry, value is too big: %d", opt); - opt = MAX_CALLERS_LEVEL; - fa.set_checkbox_value(FIELD_ID_FATHERS, &opt); - } - } - - return 1; -} - -//-------------------------------------------------------------------------- -bool plugin_ctx_t::show_options() -{ - static const char opt_form[] = - "Call graph configuration\n" - "%/" - "<##Show ~s~tring references:C1>\n" - "<##Options##Hide ~l~ibrary functions:C2>\n" - "<##Max ~p~arents recursion level:D3:5:5::>\n" - "<##Unlimited children recursion:C4>5>\n" - "<##Max ~c~hildren recursion level:D6:5:5::>\n" - "<##~L~imit of nodes per level:D7:5:5::>\n" - ; - - ushort opt = fg_opts.flags; - - // When analyzing big functions, fg_opts.recurse_limit is too big - sval_t callers_limit = fg_opts.callers_recurse_limit; - sval_t callees_limit = fg_opts.callees_recurse_limit; - sval_t max_nodes = fg_opts.max_nodes; - - if ( !ask_form(opt_form, - options_cb, - &callers_limit, - &opt, - &callees_limit, - &max_nodes) ) - { - return false; - } - - if ( callees_limit <= 0 ) - { - callers_limit = 0; - opt |= FWO_CALLEE_RECURSE_UNLIM; - } - - fg_opts.flags = opt; - fg_opts.callees_recurse_limit = callees_limit; - fg_opts.callers_recurse_limit = callers_limit; - fg_opts.max_nodes = max_nodes; - - // save options - netnode n; - n.create(NODE_NAME); - n.supset(1, &fg_opts, sizeof(fg_opts)); - return true; -} - -//-------------------------------------------------------------------------- -static void jump_to_node(const graph_info_t *gi, const int nid) -{ - viewer_center_on(gi->gv, nid); - int x, y; - - // will return a place only when a node was previously selected - place_t *old_pl = get_custom_viewer_place(gi->gv, false, &x, &y); - if ( old_pl != nullptr ) - { - user_graph_place_t *new_pl = (user_graph_place_t *) old_pl->clone(); - new_pl->node = nid; - jumpto(gi->gv, new_pl, x, y); - ::qfree(new_pl); - } -} - -//-------------------------------------------------------------------------- -static int findfirst_node(callgraph_t *fg) -{ - static const char form[] = - "Enter search substring\n" - "\n" - " <#Search is not case sensitive#Function name:q:1000:50::>\n\n"; - - CASSERT(IS_QSTRING(fg->ctx.last_text)); - if ( !ask_form(form, &fg->ctx.last_text) ) - return -2; - - return fg->find_first(fg->ctx.last_text.c_str()); -} - -//-------------------------------------------------------------------------- -static void display_node_search_result(graph_info_t *gi, int nid) -{ - // search was cancelled - if ( nid == -2 ) - return; - - const char *txt = gi->fg.get_findtext(); - if ( nid == -1 ) - { - msg("No match for '%s'\n", txt); - } - else - { - msg("%a: matched '%s'\n", gi->fg.get_addr(nid), txt); - jump_to_node(gi, nid); - } -} - -//-------------------------------------------------------------------------- -bool callgraph_t::options(graph_info_t *gi) const -{ - if ( ctx.show_options() ) - gi->refresh(); - - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::refresh(graph_info_t *gi) const -{ - gi->refresh(); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::jumpxref(graph_info_t *gi) const -{ - int node; - ea_t addr; - - node = viewer_get_curnode(gi->gv); - if ( node != -1 ) - { - addr = gi->fg.get_addr(node); - ea_t xref = choose_xref(addr); - - if ( xref != 0 && xref != BADADDR ) - navigate(gi, xref); - - } - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::jumpaddr(graph_info_t *gi) const -{ - ea_t addr; - - if ( ask_addr(&addr, "Jump address") ) - { - func_t *pfn = get_func(addr); - if ( pfn == nullptr ) - { - warning("You have entered an invalid address"); - return false; - } - navigate(gi, addr); - } - - return true; -} - - -//-------------------------------------------------------------------------- -bool callgraph_t::jump(const graph_info_t *gi) const -{ - int node; - ea_t addr; - - node = viewer_get_curnode(gi->gv); - if ( node != -1 ) - { - addr = gi->fg.get_addr(node); - jumpto(addr); - } - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::back(graph_info_t *gi) const -{ - if ( gi->queue.empty() ) - close_widget(gi->widget, WCLS_SAVE); - else - go_back(gi); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::forward(graph_info_t *gi) const -{ - if ( !gi->forward_queue.empty() ) - go_forward(gi); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::center(graph_info_t *gi) const -{ - int node; - ea_t addr; - - node = viewer_get_curnode(gi->gv); - if ( node != -1 ) - { - addr = gi->fg.get_addr(node); - return navigate(gi, addr); - } - else - return false; - -} - -//------------------------------------------------------------------------- -// node chooser's helper -struct node_chooser_t : public chooser_t -{ -protected: - static const int widths_[]; - static const char *const header_[]; - -public: - // this chooser is modal - node_chooser_t(const char * title); -}; - -const int node_chooser_t::widths_[] = -{ - CHCOL_HEX | 32, // Function - 10, // Address -}; -const char *const node_chooser_t::header_[] = -{ - "Function", // 0 - "Address", // 1 -}; - -inline node_chooser_t::node_chooser_t(const char *title_) - : chooser_t(CH_MODAL | CH_KEEP, - qnumber(widths_), widths_, header_, - title_) -{ - CASSERT(qnumber(widths_) == qnumber(header_)); -} - - -//------------------------------------------------------------------------- -// modal call node chooser -struct call_node_chooser_t : public node_chooser_t -{ - const callgraph_t &fg; - - // this chooser is modal - call_node_chooser_t(const callgraph_t &fg_) - : node_chooser_t("Select function"), fg(fg_) {} - - virtual size_t idaapi get_count() const override { return fg.count(); } - virtual void idaapi get_row( - qstrvec_t *cols, - int *icon_, - chooser_item_attrs_t *attrs, - size_t n) const override; -}; - -void idaapi call_node_chooser_t::get_row( - qstrvec_t *cols_, - int *, - chooser_item_attrs_t *, - size_t n) const -{ - ea_t ea = fg.get_addr(n); - - qstrvec_t &cols = *cols_; - if ( get_name(&cols[0], ea) > 0 ) - cols[1].sprnt("%a", ea); - CASSERT(qnumber(header_) == 2); -} - -//-------------------------------------------------------------------------- -bool callgraph_t::select(const graph_info_t *gi) const -{ - call_node_chooser_t ch(gi->fg); - ssize_t n = ch.choose(chooser_base_t::NO_SELECTION); // why? - if ( n >= 0 ) - jump_to_node(gi, n); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::home(const graph_info_t *gi) const -{ - if ( count() > 1 ) - jump_to_node(gi, 0); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::searchfirst(graph_info_t *gi) -{ - display_node_search_result(gi, findfirst_node(this)); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::searchnext(graph_info_t *gi) -{ - display_node_search_result(gi, find_next()); - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::hidenode(graph_info_t *gi) const -{ - int node; - ea_t addr; - - node = viewer_get_curnode(gi->gv); - if ( node != -1 ) - { - addr = gi->fg.get_addr(node); - //msg("Should hide 0x%08x\n", addr); - gi->hide_nodes.push_back(addr); - gi->refresh(); - } - - return true; -} - -//------------------------------------------------------------------------- -// modal hidden node chooser -struct hidden_node_chooser_t : public node_chooser_t -{ - const eavec_t &hn; - - // this chooser is modal - hidden_node_chooser_t(const eavec_t &hn_) - : node_chooser_t("Show function"), hn(hn_) {} - - virtual size_t idaapi get_count() const override { return hn.size(); } - virtual void idaapi get_row( - qstrvec_t *cols, - int *icon_, - chooser_item_attrs_t *attrs, - size_t n) const override; -}; - -void idaapi hidden_node_chooser_t::get_row( - qstrvec_t *cols_, - int *, - chooser_item_attrs_t *, - size_t n) const -{ - ea_t ea = hn[n]; - - qstrvec_t &cols = *cols_; - if ( get_name(&cols[0], ea) > 0 ) - cols[1].sprnt("%a", ea); - CASSERT(qnumber(header_) == 2); -} - -//-------------------------------------------------------------------------- -bool callgraph_t::showhidden(graph_info_t *gi) const -{ - if ( gi->hide_nodes.empty() ) - { - info("No functions hidden\n"); - return true; - } - - hidden_node_chooser_t ch(gi->hide_nodes); - ssize_t n = ch.choose(chooser_base_t::NO_SELECTION); // why? - if ( n >= 0 ) - { - eavec_t::iterator it = gi->hide_nodes.begin() + n; - gi->hide_nodes.erase(it); - gi->refresh(); - } - - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::showall(graph_info_t *gi) const -{ - gi->hide_nodes.clear(); - gi->refresh(); - - return true; -} - -//-------------------------------------------------------------------------- -bool callgraph_t::navigate(graph_info_t *gi, ea_t addr) const -{ - ea_t func_ea; - - func_ea = gi->fg.get_addr(0); - - // Is it a function? - func_t *pfn = get_func(addr); - if ( pfn != nullptr ) - { - // Is it the same function? - if ( gi->func_ea != addr ) - { - // Clear the forward queue - gi->forward_queue.clear(); - - // Enqueue the current center node - gi->queue.push_front(func_ea); - - gi->func_ea = addr; - gi->refresh(); - - jump_to_node(gi, 0); - return true; - } - } - else - { - return true; - } - - return false; -} - -//-------------------------------------------------------------------------- -void callgraph_t::go_back(graph_info_t *gi) const -{ - gi->forward_queue.push_front(gi->func_ea); - gi->func_ea = gi->queue.front(); - gi->queue.pop_front(); - gi->refresh(); - - jump_to_node(gi, 0); -} - -//-------------------------------------------------------------------------- -void callgraph_t::go_forward(graph_info_t *gi) const -{ - ea_t ea; - - ea = gi->forward_queue.front(); - gi->forward_queue.pop_front(); - gi->queue.push_front(gi->func_ea); - gi->func_ea = ea; - gi->refresh(); - - jump_to_node(gi, 0); -} - -//------------------------------------------------------------------------- -void plugin_ctx_t::ensure_actions_registered() -{ - if ( !actions_registered ) - { - for ( int i = 0, n = qnumber(actions); i < n; ++i ) - register_action(actions[i]); - - actions_registered = true; - } -} - -//-------------------------------------------------------------------------- -bool idaapi plugin_ctx_t::run(size_t arg) -{ - if ( ssize_t(arg) == -1 ) - { - load_options(); - show_options(); - return true; - } - - func_t *pfn = get_func(get_screen_ea()); - if ( pfn == nullptr ) - { - warning("Please position the cursor in a function first!"); - return true; - } - - load_options(); - qstring title = gen_graph_title(pfn->start_ea); - TWidget *form = find_widget(title.c_str()); - if ( form == nullptr ) - { - // no current window, but instance is in the list? - graph_info_t *gi = graph_info_t::find(*this, title.c_str()); - if ( gi != nullptr ) - { - // In that case let us "recycle" the instance - gi->func_ea = pfn->start_ea; - } - else - { - // we create a new instance - gi = graph_info_t::create(*this, pfn->start_ea); - } - - if ( gi != nullptr ) - { - // get a unique graph id - netnode id; - id.create("$ callgraph sample"); - - gi->hide_nodes.begin(); - - gi->mark_for_refresh(); - // gi->form = form; - gi->gv = create_graph_viewer(title.c_str(), id, callgraph_t::gr_callback, gi, 0); - if ( gi->gv != nullptr ) - { - display_widget(/*form*/ gi->gv, WOPN_DP_TAB); - - ensure_actions_registered(); - - viewer_fit_window(gi->gv); -#define ADD_POPUP(Method) viewer_attach_menu_item(gi->gv, "callgraph:" #Method) -#define ADD_SEPARATOR() viewer_attach_menu_item(gi->gv, nullptr) - ADD_POPUP(options); - ADD_POPUP(refresh); - ADD_SEPARATOR(); - ADD_POPUP(jumpxref); - ADD_POPUP(jumpaddr); - ADD_POPUP(jump); - ADD_POPUP(back); - ADD_POPUP(forward); - ADD_SEPARATOR(); - ADD_POPUP(center); - ADD_POPUP(select); - ADD_POPUP(home); - ADD_POPUP(searchfirst); - ADD_POPUP(searchnext); - ADD_POPUP(hidenode); - ADD_POPUP(showhidden); - ADD_POPUP(showall); -#undef ADD_SEPARATOR -#undef ADD_POPUP - } - else - { - graph_info_t::destroy_graph(*this, gi); - gi = nullptr; - } - } - - // Failed to create a graph view? - if ( gi == nullptr ) - { - warning("Failed to create call graph window!"); - return true; - } - } - else - { - graph_info_t *gi = graph_info_t::find(*this, title.c_str()); - if ( gi != nullptr ) - { - gi->refresh(); - display_widget(gi->gv, WOPN_DP_TAB); - } - } - return true; -} - -//------------------------------------------------------------------------- -ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) -{ - if ( code == view_close ) - { - TWidget *cc = va_arg(va, TWidget *); - graph_info_t *gi = graph_info_t::find(*this, (graph_viewer_t *) cc); - if ( gi != nullptr ) - graph_info_t::destroy_graph(*this, gi); - } - return 0; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - plugin_ctx_t *ctx = nullptr; - if ( is_idaq() ) // GUI version? - { - ctx = new plugin_ctx_t; - if ( !ctx->register_main_action() ) - { - msg("Failed to register menu item for <" ACTION_LABEL "> plugin!\n"); - delete ctx; - ctx = nullptr; - } - } - return ctx; -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_HIDE|PLUGIN_MULTI, // plugin flags - init, // initialize - - nullptr, // terminate. this pointer may be nullptr. - nullptr, // invoke plugin - - // long comment about the plugin - "Proximity browser plugin.", - // it could appear in the status line - // or as a hint - - // multiline help about the plugin - "Proximity browser using the graph SDK\n" - "\n" - "Position the cursor in a function and run the plugin.", - - ACTION_LABEL, // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/callgraph/callgraph.h b/idasdk75/plugins/callgraph/callgraph.h deleted file mode 100644 index 0c2b834..0000000 --- a/idasdk75/plugins/callgraph/callgraph.h +++ /dev/null @@ -1,199 +0,0 @@ -#ifndef __CALLGRAPH__06192009__ -#define __CALLGRAPH__06192009__ - -#include <deque> -#include <algorithm> -#include <ida.hpp> -#include <idp.hpp> -#include <name.hpp> -#include <bytes.hpp> -#include <graph.hpp> -#include <loader.hpp> -#include <kernwin.hpp> -#include <demangle.hpp> - -#define MAX_CALLERS_LEVEL 10 - -#define FIELD_ID_STRINGS 1 -#define FIELD_ID_LIBS 2 -#define FIELD_ID_FATHERS 3 -#define FIELD_ID_CHILDS 4 -#define FIELD_ID_CHILDS_LEVEL 6 - -#define VERTEX_HIDDEN_NODES -1 - -struct plugin_ctx_t; -typedef std::deque<int> int_queue_t; -typedef std::map<ea_t, int> ea_int_map_t; - -//-------------------------------------------------------------------------- -struct funcs_walk_options_t -{ - int32 version; -#define FWO_VERSION 1 // current version of options block - int32 flags; -#define FWO_SHOWSTRING 0x0001 // show string references -#define FWO_SKIPLIB 0x0002 // skip library functions -#define FWO_CALLEE_RECURSE_UNLIM 0x0004 // unlimited callees recursion - int32 callees_recurse_limit; // how deep to recurse callees (0 = unlimited) - int32 callers_recurse_limit; // how deep to recurse callers (0 = unlimited) - int32 max_nodes; // maximum number of nodes per level -}; - -class graph_info_t; - -//-------------------------------------------------------------------------- -// function call graph creator class -class callgraph_t -{ -public: - plugin_ctx_t &ctx; - -private: - int node_count = 0; - - // node id to func addr and reverse lookup - typedef std::map<int, ea_t> int_ea_map_t; - int_ea_map_t node2ea; - - // current node search ptr - int cur_node = 0; - char cur_text[MAXSTR]; - - bool visited(ea_t func_ea, int *nid); - int add(ea_t func_ea); - -public: - - ea_int_map_t ea2node; - // edge structure - struct edge_t - { - int id1; - int id2; - edge_t(int i1, int i2): id1(i1), id2(i2) {} - edge_t(): id1(0), id2(0) {} - }; - typedef qlist<edge_t> edges_t; - - // edge manipulation - typedef edges_t::iterator edge_iterator; - void create_edge(int id1, int id2); - edge_iterator begin_edges() { return edges.begin(); } - edge_iterator end_edges() { return edges.end(); } - void clear_edges(); - - // find nodes by text - int find_first(const char *text); - int find_next(); - const char *get_findtext() { return cur_text; } - callgraph_t(plugin_ctx_t &ctx); - int count() const { return node_count; } - void reset(); - - // node / func info - struct funcinfo_t - { - qstring name; - bgcolor_t color; - ea_t ea; - qstring strings; - }; - typedef std::map<int, funcinfo_t> int_funcinfo_map_t; - int_funcinfo_map_t cached_funcs; - funcinfo_t *get_info(int nid); - - // function name manipulation - ea_t get_addr(int nid) const; - const char *get_name(int nid); - - int walk_func(eavec_t *hide_nodes, func_t *func, funcs_walk_options_t *o=NULL, int level=1); - void add_fathers(func_t *func, ea_t func_start, int id, funcs_walk_options_t *opt, int level); - - bool navigate(graph_info_t *gi, ea_t addr) const; - - void go_back(graph_info_t *gi) const; - void go_forward(graph_info_t *gi) const; - - bool options(graph_info_t *gi) const; - bool refresh(graph_info_t *gi) const; - - bool jumpxref(graph_info_t *gi) const; - bool jumpaddr(graph_info_t *gi) const; - bool jump(const graph_info_t *gi) const; - bool back(graph_info_t *gi) const; - bool forward(graph_info_t *gi) const; - - bool center(graph_info_t *gi) const; - bool select(const graph_info_t *gi) const; - bool home(const graph_info_t *gi) const; - bool searchfirst(graph_info_t *gi); - bool searchnext(graph_info_t *gi); - bool hidenode(graph_info_t *gi) const; - bool showhidden(graph_info_t *gi) const; - bool showall(graph_info_t *gi) const; - - static ssize_t idaapi gr_callback(void *ud, int code, va_list va); - static void idaapi user_refresh(void *ud, int code, va_list va, int current_node); -private: - edges_t edges; -}; - -//-------------------------------------------------------------------------- -struct idp_listener_t : public event_listener_t -{ - graph_info_t *gi; - idp_listener_t(graph_info_t *g) : gi(g) {} - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; -}; - -struct idb_listener_t : public event_listener_t -{ - graph_info_t *gi; - idb_listener_t(graph_info_t *g) : gi(g) {} - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; -}; - -//-------------------------------------------------------------------------- -// Per function call graph context -typedef qlist<class graph_info_t *> graphinfo_list_t; -class graph_info_t -{ - plugin_ctx_t &ctx; - idp_listener_t idp_listener = idp_listener_t(this); - idb_listener_t idb_listener = idb_listener_t(this); - -public: - typedef graphinfo_list_t::iterator iterator; - - callgraph_t fg; // associated call graph maker - graph_viewer_t *gv = nullptr; // associated graph_view - TWidget *widget = nullptr; // associated widget - ea_t func_ea = BADADDR; // function ea in question - qstring title; // the title - - int_queue_t queue; - int_queue_t forward_queue; - - eavec_t hide_nodes; - -private: - bool refresh_needed = true; // schedule a refresh - - graph_info_t(plugin_ctx_t &_ctx) : ctx(_ctx), fg(_ctx) {} - static bool find(plugin_ctx_t &ctx, ea_t func_ea, iterator *out); -public: - static graph_info_t *find(plugin_ctx_t &ctx, ea_t func_ea); - static graph_info_t *find(plugin_ctx_t &ctx, const char *title); - static graph_info_t *find(plugin_ctx_t &ctx, const graph_viewer_t *v); - static graph_info_t *create(plugin_ctx_t &ctx, ea_t func_ea); - static void destroy_graph(plugin_ctx_t &ctx, graph_info_t *gi); - void install_hooks(); - void remove_hooks(); - void mark_for_refresh(void); - void mark_as_refreshed(void); - void refresh(void); - bool is_refresh_needed(void) const { return refresh_needed; } -}; - -#endif diff --git a/idasdk75/plugins/callgraph/makefile b/idasdk75/plugins/callgraph/makefile deleted file mode 100644 index 9c4bb3c..0000000 --- a/idasdk75/plugins/callgraph/makefile +++ /dev/null @@ -1,12 +0,0 @@ -PROC=callgraph - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)callgraph$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)demangle.hpp $(I)fpro.h $(I)funcs.hpp $(I)gdl.hpp \ - $(I)graph.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)pro.h $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp callgraph.cpp \ - callgraph.h diff --git a/idasdk75/plugins/choose/makefile b/idasdk75/plugins/choose/makefile deleted file mode 100644 index 8e0f961..0000000 --- a/idasdk75/plugins/choose/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=choose - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)choose$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp choose.cpp diff --git a/idasdk75/plugins/custdata/custdata.cpp b/idasdk75/plugins/custdata/custdata.cpp deleted file mode 100644 index 4f2ca59..0000000 --- a/idasdk75/plugins/custdata/custdata.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* Custom data type sample plugin. - * Copyright (c) 2010-2020 Hex-Rays, support@hex-rays.com - * Feel free to do whatever you want with this code. - * - * This sample plugin demonstates how to install a custom data type - * and a custom data format in IDA v5.7 - * - * Custom data types can be used to create your own data types. - * A custom data type basically defines the data size. It can be fixed - * or variable. This plugin defines a variable size data type: a pascal - * string. Pascal strings start with a count byte: - * db len, '....' - * - * Custom data formats are used to render data values on the screen. - * Multiple data formats can be registered for a custom data type. - * The data formats with non-NULL menu_names will be listed in the 'Operand type' - * menu and the user will be able to select them. - * - */ - -#include <ida.hpp> -#include <idp.hpp> -#include <struct.hpp> -#include <loader.hpp> -#include <kernwin.hpp> - -struct plugin_ctx_t : public plugmod_t -{ - int psid = 0; // id of the 'pascal string' data type - int psfid = 0; // id of the 'pascal string' data format - - plugin_ctx_t(); - ~plugin_ctx_t(); - virtual bool idaapi run(size_t) override { return false; } -}; - -//--------------------------------------------------------------------------- -// We define a variable size data type. For fixed size types this function -// must be omitted. -static asize_t idaapi calc_pascal_string_length(void *, ea_t ea, asize_t maxsize) -{ - if ( is_member_id(ea) ) - { // Custom data types may be used in structure definitions. If this case - // ea is a member id. Check for this situation and return 1 - return 1; - } - ushort n = get_byte(ea); - if ( n+1 > maxsize ) - return 0; // string would be too big - return n+1; // ok, we accept any pascal string -} - -//--------------------------------------------------------------------------- -// Definition of the data type -static const data_type_t pascal_string_type = -{ - sizeof(data_type_t), // size of this structure - NULL, // user defined data - 0, // properties - "pascal_string", // internal name of the data type - // must be unique for the current database - "Pascal string", // Menu name. If NULL, the type won't be visible in the Edit menu. - NULL, // Hotkey - "pstr", // Keyword to use in the assembly listing - 2, // value size. For varsize types, specify the - // minimal size of the value - NULL, // may_create_at? NULL means the type can be created anywhere - calc_pascal_string_length, // for varsize types: calculate the exact size of an item -}; - -//--------------------------------------------------------------------------- -// Print contents of a pascal string -static bool idaapi print_pascal_string( - void *, // user defined data, not used here - qstring *out, // output buffer. may be NULL - const void *value, // value to print. may not be NULL - asize_t size, // value size in bytes - ea_t, // current ea - int, // operand number - int) // data type id -{ - const char *vptr = (const char *)value; - int n = *vptr++; - if ( n+1 > size ) - return false; - - if ( out != NULL ) - { - *out = "\""; - for ( int i=0; i < n; i++ ) - { - if ( qisprint(*vptr) ) - out->append(*vptr++); - else - out->cat_sprnt("\\x%02X", uchar(*vptr++)); - } - out->append('"'); - } - return true; -} - -//--------------------------------------------------------------------------- -// Definition of the data format -static const data_format_t pascal_string_format = -{ - sizeof(data_format_t), // size of this structure - NULL, // user defined data - 0, // properties - "pascal_string", // internal name of the data format - NULL, // Menu name of the format. NULL means 'do not create menu item' - NULL, // Hotkey - 0, // value size. 0 means that this format accepts any value size - 0, // Text width of the value. Unknown, specify 0 - print_pascal_string, // callback to render colored text for the data - NULL, // scan - NULL, // analyze -}; - - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - processor_t &ph = PH; - if ( ph.id != PLFM_386 ) - return nullptr; - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -plugin_ctx_t::plugin_ctx_t() -{ - // Register custom data type - psid = register_custom_data_type(&pascal_string_type); - // Register custom data format for it - psfid = register_custom_data_format(&pascal_string_format); - attach_custom_data_format(psid, psfid); -} - -//-------------------------------------------------------------------------- -plugin_ctx_t::~plugin_ctx_t() -{ - // unregister data type - if ( psid > 0 ) - { - // IDA would detach the data format automatically. - unregister_custom_data_type(psid); - } - // unregister data format - if ( psfid > 0 ) - unregister_custom_data_format(psfid); -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_PROC // plugin flags - // we want the plugin to load as soon as possible - // immediately after the processor module - |PLUGIN_HIDE // we want to hide the plugin because it there will - // be a menu item in the Edit submenu - |PLUGIN_MULTI, // this plugin can work with multiple idbs in parallel - init, // initialize - nullptr, - nullptr, - "", // long comment about the plugin - // it could appear in the status line - // or as a hint - "", // multiline help about the plugin - - "Sample custdata", // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/custdata/makefile b/idasdk75/plugins/custdata/makefile deleted file mode 100644 index 600d26d..0000000 --- a/idasdk75/plugins/custdata/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=custdata - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)custdata$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp custdata.cpp diff --git a/idasdk75/plugins/custview/custview.cpp b/idasdk75/plugins/custview/custview.cpp deleted file mode 100644 index 6ec18b9..0000000 --- a/idasdk75/plugins/custview/custview.cpp +++ /dev/null @@ -1,283 +0,0 @@ -/* Custom viewer sample plugin. - * Copyright (c) 2007 by Ilfak Guilfanov, ig@hexblog.com - * Feel free to do whatever you want with this code. - * - * This sample plugin demonstates how to create and manipulate a simple - * custom viewer in IDA v5.1 - * - * Custom viewers allow you to create a view which displays colored lines. - * These colored lines are dynamically created by callback functions. - * - * Custom viewers are used in IDA itself to display - * the disassembly listng, structure, and enumeration windows. - * - * This sample plugin just displays several sample lines on the screen. - * It displays a hint with the current line number. - * The right-click menu contains one sample command. - * It reacts to one hotkey. - * - * This plugin uses the simpleline_place_t class for the locations. - * Custom viewers can use any decendant of the place_t class. - * The place_t is responsible for supplying data to the viewer. - */ - -//--------------------------------------------------------------------------- -#include <ida.hpp> -#include <idp.hpp> -#include <loader.hpp> -#include <kernwin.hpp> - -#define ACTION_NAME "custview:SampleMenuItem" - -struct plugin_ctx_t; -struct sample_action_t : public action_handler_t -{ - plugin_ctx_t &plg; - sample_action_t(plugin_ctx_t &p) : plg(p) {} - virtual int idaapi activate(action_activation_ctx_t *) override; - virtual action_state_t idaapi update(action_update_ctx_t *) override - { - return AST_ENABLE_ALWAYS; - } -}; - -//------------------------------------------------------------------------- -static struct -{ - const char *text; - bgcolor_t color; -} const sample_text[] = -{ - { "This is a sample text", 0xFFFFFF }, - { "It will be displayed in the custom view", 0xFFC0C0 }, - { COLSTR("This line will be colored as erroneous", SCOLOR_ERROR), 0xC0FFC0 }, - { COLSTR("Every", SCOLOR_AUTOCMT) " " - COLSTR("word", SCOLOR_DNAME) " " - COLSTR("can", SCOLOR_IMPNAME) " " - COLSTR("be", SCOLOR_NUMBER) " " - COLSTR("colored!", SCOLOR_EXTRA), 0xC0C0FF }, - { " No limit on the number of lines.", 0xC0FFFF }, -}; - -// Structure to keep all information about the our sample view -struct sample_info_t -{ - TWidget *cv; - strvec_t sv; - sample_info_t() : cv(NULL) {} -}; - -struct plugin_ctx_t : public plugmod_t, public event_listener_t -{ - sample_info_t *si = NULL; - const sample_info_t *last_si = NULL; - - sample_action_t sample_ah = sample_action_t(*this); - const action_desc_t sample_action = ACTION_DESC_LITERAL_PLUGMOD( - ACTION_NAME, - "Sample menu item", - &sample_ah, - this, - "N", - NULL, - -1); - - virtual bool idaapi run(size_t) override; - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; -}; - -//--------------------------------------------------------------------------- -// get the word under the (keyboard or mouse) cursor -static bool get_current_word(TWidget *v, bool mouse, qstring &word) -{ - // query the cursor position - int x, y; - if ( get_custom_viewer_place(v, mouse, &x, &y) == NULL ) - return false; - - // query the line at the cursor - qstring buf; - tag_remove(&buf, get_custom_viewer_curline(v, mouse)); - if ( x >= buf.length() ) - return false; - - // find the beginning of the word - char *ptr = buf.begin() + x; - while ( ptr > buf.begin() && !qisspace(ptr[-1]) ) - ptr--; - - // find the end of the word - char *begin = ptr; - ptr = buf.begin() + x; - while ( !qisspace(*ptr) && *ptr != '\0' ) - ptr++; - - word = qstring(begin, ptr-begin); - return true; -} - -//--------------------------------------------------------------------------- -int idaapi sample_action_t::activate(action_activation_ctx_t *) -{ - qstring word; - if ( !get_current_word(plg.last_si->cv, false, word) ) - return 0; - - info("The current word is: %s", word.c_str()); - return 1; -} - -//--------------------------------------------------------------------------- -// Keyboard callback -static bool idaapi ct_keyboard(TWidget * /*v*/, int key, int shift, void *ud) -{ - if ( shift == 0 ) - { - sample_info_t *si = (sample_info_t *)ud; - switch ( key ) - { - case 'N': - warning("The hotkey 'N' has been pressed"); - return true; - case IK_ESCAPE: - close_widget(si->cv, WCLS_SAVE | WCLS_CLOSE_LATER); - return true; - } - } - return false; -} - -//--------------------------------------------------------------------------- -// This callback will be called each time the keyboard cursor position -// is changed -static void idaapi ct_curpos(TWidget *v, void *) -{ - qstring word; - if ( get_current_word(v, false, word) ) - msg("Current word is: %s\n", word.c_str()); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - // how to implement a simple hint callback - case ui_get_custom_viewer_hint: - { - qstring &hint = *va_arg(va, qstring *); - TWidget *viewer = va_arg(va, TWidget *); - place_t *place = va_arg(va, place_t *); - int *important_lines = va_arg(va, int *); - if ( si->cv == viewer ) // our viewer - { - if ( place == NULL ) - return 0; - simpleline_place_t *spl = (simpleline_place_t *)place; - hint.sprnt("Hint for line %u", spl->n); - *important_lines = 1; - return 1; - } - break; - } - case ui_widget_invisible: - { - TWidget *f = va_arg(va, TWidget *); - if ( f == si->cv ) - { - delete si; - si = nullptr; - unhook_event_listener(HT_UI, this); - } - } - break; - case ui_populating_widget_popup: - { - TWidget *f = va_arg(va, TWidget *); - if ( f == si->cv ) - { - TPopupMenu *p = va_arg(va, TPopupMenu *); - // Create right-click menu on the fly - attach_action_to_popup(f, p, ACTION_NAME); - } - } - break; - } - return 0; -} - -//------------------------------------------------------------------------- -static const custom_viewer_handlers_t handlers( - ct_keyboard, - NULL, // popup - NULL, // mouse_moved - NULL, // click - NULL, // dblclick - ct_curpos, - NULL, // close - NULL, // help - NULL);// adjust_place - -//--------------------------------------------------------------------------- -// Create a custom view window -bool idaapi plugin_ctx_t::run(size_t) -{ - TWidget *widget = find_widget("Sample custom view"); - if ( widget != NULL ) - { - activate_widget(widget, true); - return true; - } - - // allocate block to hold info about our sample view - si = new sample_info_t(); - last_si = si; - // prepare the data to display. we could prepare it on the fly too. - // but for that we have to use our own custom place_t class decendant. - for ( int i=0; i < qnumber(sample_text); i++ ) - { - si->sv.push_back(simpleline_t("")); // add empty line - si->sv.push_back(simpleline_t(sample_text[i].text)); - si->sv.back().bgcolor = sample_text[i].color; - } - // create two place_t objects: for the minimal and maximal locations - simpleline_place_t s1; - simpleline_place_t s2(si->sv.size()-1); - // create a custom viewer - si->cv = create_custom_viewer("Sample custom view", &s1, &s2, &s1, NULL, &si->sv, &handlers, si); - // also set the ui event callback - hook_event_listener(HT_UI, this); - // finally display the form on the screen - display_widget(si->cv, WOPN_DP_TAB|WOPN_RESTORE); - - // Register the action. This one will be attached - // live, to the popup menu. - register_action(sample_action); - return true; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI, // plugin flags - init, // initialize - - nullptr, - nullptr, - - "", // long comment about the plugin - "", // multiline help about the plugin - "Sample custview", // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/custview/makefile b/idasdk75/plugins/custview/makefile deleted file mode 100644 index bdbd7bd..0000000 --- a/idasdk75/plugins/custview/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=custview - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)custview$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp custview.cpp diff --git a/idasdk75/plugins/ex_debidc/ex_debidc.cpp b/idasdk75/plugins/ex_debidc/ex_debidc.cpp deleted file mode 100644 index 3fce25a..0000000 --- a/idasdk75/plugins/ex_debidc/ex_debidc.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// Debugger IDC Helper -// Executes IDC script when the process is launched -// In fact, this approach can be used to hook IDC scripts to various debugger -// events. - -#include <ida.hpp> -#include <idp.hpp> -#include <dbg.hpp> -#include <expr.hpp> -#include <loader.hpp> - -//-------------------------------------------------------------------------- -struct plugin_ctx_t : public plugmod_t, public event_listener_t -{ - plugin_ctx_t() - { - hook_event_listener(HT_DBG, this); - } - ~plugin_ctx_t() - { - // listeners are uninstalled automatically - // when the owner module is unloaded - } - - virtual bool idaapi run(size_t) override; - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; -}; - -//-------------------------------------------------------------------------- -// The plugin stores the IDC file name in the database -// It will create a node for this purpose -static const char node_name[] = "$ debugger idc file"; - -//-------------------------------------------------------------------------- -// Get the IDC file name from the database -static bool get_idc_name(char *buf, size_t bufsize) -{ - // access the node - netnode mynode(node_name); - // retrieve the value - return mynode.valstr(buf, bufsize) > 0; -} - -//-------------------------------------------------------------------------- -// Store the IDC file name in the database -static void set_idc_name(const char *idc) -{ - // access the node - netnode mynode; - // if it doesn't exist yet, create it - // otherwise get its id - mynode.create(node_name); - // store the value - mynode.set(idc, strlen(idc)+1); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list /*va*/) -{ - switch ( code ) - { - case dbg_process_start: - case dbg_process_attach: - // it is time to run the script - char idc[QMAXPATH]; - if ( get_idc_name(idc, sizeof(idc)) ) - { - qstring errbuf; - if ( !exec_idc_script(NULL, idc, "main", NULL, 0, &errbuf) ) - warning("%s", errbuf.c_str()); - } - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -bool idaapi plugin_ctx_t::run(size_t) -{ - // retrieve the old IDC name from the database - char idc[QMAXPATH]; - if ( !get_idc_name(idc, sizeof(idc)) ) - qstrncpy(idc, "*.idc", sizeof(idc)); - - char *newidc = ask_file(false, idc, "Specify the script to run upon debugger launch"); - if ( newidc != NULL ) - { - // store it back in the database - set_idc_name(newidc); - msg("Script %s will be run when the debugger is launched\n", newidc); - } - return true; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - // Our plugin works only for x86 PE executables - processor_t &ph = PH; - if ( ph.id != PLFM_386 || inf_get_filetype() != f_PE ) - return nullptr; - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -static const char wanted_name[] = "Specify Debugger IDC Script"; -static const char wanted_hotkey[] = ""; - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel - init, // initialize - nullptr, - nullptr, - wanted_name, // long comment about the plugin - wanted_name, // multiline help about the plugin - wanted_name, // the preferred short name of the plugin - wanted_hotkey // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/ex_debidc/makefile b/idasdk75/plugins/ex_debidc/makefile deleted file mode 100644 index cf15513..0000000 --- a/idasdk75/plugins/ex_debidc/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ex_debidc - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ex_debidc$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ex_debidc.cpp diff --git a/idasdk75/plugins/ex_events1/makefile b/idasdk75/plugins/ex_events1/makefile deleted file mode 100644 index 74c7811..0000000 --- a/idasdk75/plugins/ex_events1/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ex_events1 - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ex_events1$(O): $(I)allins.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ex_events1.cpp diff --git a/idasdk75/plugins/extlang/makefile b/idasdk75/plugins/extlang/makefile deleted file mode 100644 index d68e0e4..0000000 --- a/idasdk75/plugins/extlang/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=extlang - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)extlang$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - extlang.cpp diff --git a/idasdk75/plugins/findcrypt2/makefile b/idasdk75/plugins/findcrypt2/makefile deleted file mode 100644 index 884fda3..0000000 --- a/idasdk75/plugins/findcrypt2/makefile +++ /dev/null @@ -1,15 +0,0 @@ -PROC=findcrypt -O1=consts -O2=sparse - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)consts$(O) : $(I)llong.hpp $(I)pro.h consts.cpp findcrypt.hpp -$(F)findcrypt$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)moves.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp findcrypt.cpp findcrypt.hpp -$(F)sparse$(O) : $(I)llong.hpp $(I)pro.h findcrypt.hpp sparse.cpp diff --git a/idasdk75/plugins/formchooser/makefile b/idasdk75/plugins/formchooser/makefile deleted file mode 100644 index eb5e586..0000000 --- a/idasdk75/plugins/formchooser/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=formchooser - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)formchooser$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - formchooser.cpp diff --git a/idasdk75/plugins/formsample/makefile b/idasdk75/plugins/formsample/makefile deleted file mode 100644 index f3da4ed..0000000 --- a/idasdk75/plugins/formsample/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=formsample - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)formsample$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - formsample.cpp diff --git a/idasdk75/plugins/funclist/makefile b/idasdk75/plugins/funclist/makefile deleted file mode 100644 index 64e7e8e..0000000 --- a/idasdk75/plugins/funclist/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=funclist - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)funclist$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp funclist.cpp diff --git a/idasdk75/plugins/getlines/makefile b/idasdk75/plugins/getlines/makefile deleted file mode 100644 index 440fe7b..0000000 --- a/idasdk75/plugins/getlines/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=getlines - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)getlines$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp getlines.cpp diff --git a/idasdk75/plugins/hello/makefile b/idasdk75/plugins/hello/makefile deleted file mode 100644 index 1f45d81..0000000 --- a/idasdk75/plugins/hello/makefile +++ /dev/null @@ -1,25 +0,0 @@ -PROC=hello - -include ../plugin.mak - -all: scripts - -SCRIPTS := $(addprefix $(BIN_PATH),idchello.idc pyhello.py) - -.PHONY: scripts -scripts: $(SCRIPTS) - -$(BIN_PATH)%.idc: %.idc - $(CP) $? $@ -$(BIN_PATH)%.py: %.py - $(CP) $? $@ - -uninstall:: - rm -rf $(SCRIPTS) - -# MAKEDEP dependency list ------------------ -$(F)hello$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp hello.cpp diff --git a/idasdk75/plugins/hexview/makefile b/idasdk75/plugins/hexview/makefile deleted file mode 100644 index 11eb1c8..0000000 --- a/idasdk75/plugins/hexview/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=hexview - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)hexview$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp hexplace.cpp hexview.cpp diff --git a/idasdk75/plugins/highlighter/highlighter.cpp b/idasdk75/plugins/highlighter/highlighter.cpp deleted file mode 100644 index 518963a..0000000 --- a/idasdk75/plugins/highlighter/highlighter.cpp +++ /dev/null @@ -1,194 +0,0 @@ -// Highlighter plugin v1.0 -// Highlights executed instructions - -// This plugin will display a colored box at the executed instructions. -// It will take into account only the instructions where the application -// has been suspended. - -// http://www.hexblog.com/2005/11/the_highlighter.html - -// Copyright 2005 Ilfak Guilfanov, <ig@hexblog.com> - -#include <ida.hpp> -#include <idp.hpp> -#include <dbg.hpp> -#include <loader.hpp> -#include <kernwin.hpp> -#include <set> - -//-------------------------------------------------------------------------- -struct plugin_ctx_t; -struct idd_post_events_t : public post_event_visitor_t -{ - plugin_ctx_t &ctx; - idd_post_events_t(plugin_ctx_t &_ctx) : ctx(_ctx) {} - virtual ssize_t idaapi handle_post_event( - ssize_t code, - int notification_code, - va_list va) override; -}; - -//-------------------------------------------------------------------------- -struct exec_prefix_t : public user_defined_prefix_t -{ - static const int prefix_width = 1; - - plugin_ctx_t &ctx; - exec_prefix_t(plugin_ctx_t &_ctx) - : user_defined_prefix_t(prefix_width, &_ctx), ctx(_ctx) {} - - virtual void idaapi get_user_defined_prefix( - qstring *out, - ea_t ea, - const insn_t &insn, - int lnnum, - int indent, - const char *line) override; -}; - -//-------------------------------------------------------------------------- -typedef std::set<ea_t> easet_t; -struct plugin_ctx_t : public plugmod_t, public event_listener_t -{ - idd_post_events_t idd_post_events = idd_post_events_t(*this); - - exec_prefix_t *exec_prefix = nullptr; - - // List of executed addresses - easet_t execset; - - ea_t old_ea = BADADDR; - int old_lnnum = 0; - - plugin_ctx_t() - { - hook_event_listener(HT_DBG, this); - } - ~plugin_ctx_t() - { - // listeners are uninstalled automatically - // when the owner module is unloaded - exec_prefix = nullptr; // make lint happy - } - - virtual bool idaapi run(size_t) override; - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; -}; - -//-------------------------------------------------------------------------- -// A sample how to generate user-defined line prefixes -static const char highlight_prefix[] = { COLOR_INV, ' ', COLOR_INV, 0 }; -void idaapi exec_prefix_t::get_user_defined_prefix( - qstring *buf, - ea_t ea, - const insn_t &, - int lnnum, - int indent, - const char *line) -{ - buf->qclear(); // empty prefix by default - - // We want to display the prefix only the lines which - // contain the instruction itself - - if ( indent != -1 ) - return; // a directive - if ( line[0] == '\0' ) - return; // empty line - if ( tag_advance(line,1)[-1] == ASH.cmnt[0] ) - return; // comment line... - - // We don't want the prefix to be printed again for other lines of the - // same instruction/data. For that we remember the line number - // and compare it before generating the prefix - - if ( ctx.old_ea == ea && ctx.old_lnnum == lnnum ) - return; - - if ( ctx.execset.find(ea) != ctx.execset.end() ) - *buf = highlight_prefix; - - // Remember the address and line number we produced the line prefix for: - ctx.old_ea = ea; - ctx.old_lnnum = lnnum; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi idd_post_events_t::handle_post_event( - ssize_t retcode, - int notification_code, - va_list va) -{ - switch ( notification_code ) - { - case debugger_t::ev_get_debug_event: - { - gdecode_t *code = va_arg(va, gdecode_t *); - debug_event_t *event = va_arg(va, debug_event_t *); - if ( *code == GDE_ONE_EVENT ) // got an event? - ctx.execset.insert(event->ea); - } - break; - } - return retcode; -} - -//-------------------------------------------------------------------------- -bool idaapi plugin_ctx_t::run(size_t) -{ - info("AUTOHIDE NONE\n" - "This is the highlighter plugin.\n" - "It highlights executed instructions if a debug event occurs at them.\n" - "The plugins is fully automatic and has no parameters.\n"); - return true; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list /*va*/) -{ - // We set our debug event handler at the beginning and remove it at the end - // of a debug session - switch ( code ) - { - case dbg_process_start: - case dbg_process_attach: - exec_prefix = new exec_prefix_t(*this); - register_post_event_visitor(HT_IDD, &idd_post_events, this); - break; - case dbg_process_exit: - unregister_post_event_visitor(HT_IDD, &idd_post_events); - delete exec_prefix; - exec_prefix = nullptr; - execset.clear(); - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -static const char wanted_name[] = "Highlighter"; -static const char wanted_hotkey[] = ""; - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel - init, // initialize - nullptr, - nullptr, - wanted_name, // long comment about the plugin - wanted_name, // multiline help about the plugin - wanted_name, // the preferred short name of the plugin - wanted_hotkey, // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/highlighter/makefile b/idasdk75/plugins/highlighter/makefile deleted file mode 100644 index 1a3b26b..0000000 --- a/idasdk75/plugins/highlighter/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=highlighter - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)highlighter$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp highlighter.cpp diff --git a/idasdk75/plugins/ht_output/makefile b/idasdk75/plugins/ht_output/makefile deleted file mode 100644 index ddda4ed..0000000 --- a/idasdk75/plugins/ht_output/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ht_output - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ht_output$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ht_output.cpp diff --git a/idasdk75/plugins/ht_view/makefile b/idasdk75/plugins/ht_view/makefile deleted file mode 100644 index beece7e..0000000 --- a/idasdk75/plugins/ht_view/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ht_view - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ht_view$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ht_view.cpp diff --git a/idasdk75/plugins/makefile b/idasdk75/plugins/makefile deleted file mode 100644 index 6b59010..0000000 --- a/idasdk75/plugins/makefile +++ /dev/null @@ -1,70 +0,0 @@ -include ../allmake.mak - -GOALS += plugins -GOALS += samples -ifndef IDAHOME - GOALS += examples -endif -.PHONY: $(GOALS) -all: $(GOALS) - -#---------------------------------------------------------------------- -PLUGINS += callee -PLUGINS += callgraph -PLUGINS += choose -PLUGINS += findcrypt2 -PLUGINS += ht_output -PLUGINS += ht_view -PLUGINS += pdb -PLUGINS += tracing_api -PLUGINS += uiswitch -PLUGINS-$(__NT__) += uunp -PLUGINS += $(PLUGINS-1) -plugins: $(PLUGINS) - -#---------------------------------------------------------------------- -SAMPLES += custdata -SAMPLES += custview -SAMPLES += formchooser -SAMPLES += formsample -SAMPLES += funclist -SAMPLES += getlines -SAMPLES += hexview -SAMPLES += mtsample -SAMPLES += openform -SAMPLES += procext -SAMPLES += ugraph -SAMPLES += ugraph3 -SAMPLES += vcsample -samples: $(SAMPLES) - -#---------------------------------------------------------------------- -# Note: examples are not installed in the plugins/ directory by default. -# to install them there, run 'make' from the plugin subdirectory. -# to uninstall the plugin afterwards, run 'make uninstall' from -# the plugin subdirectory or 'make examples_uninstall' from the -# 'plugins' directory. -HAS_QT := $(call ls,$(QTDIR)) -EXAMPLES += ex_debidc -EXAMPLES += ex_events1 -EXAMPLES += script_plg -EXAMPLES-$(HAS_QT) += qproject -EXAMPLES-$(HAS_QT) += qwindow -# do not include ugraph2 in the samples because it is buggy: -# in some cases it combines blocks in such a way that switching to -# graph view becomes impossible -EXAMPLES += ugraph2 -# the z80dbg plugin will conflict with functionality already submitted -# to the z80 processor module, so we don't install it -EXAMPLES += z80dbg -EXAMPLES += $(EXAMPLES-1) -examples: $(EXAMPLES) - -#---------------------------------------------------------------------- -.PHONY: $(PLUGINS) $(SAMPLES) $(EXAMPLES) -$(PLUGINS) $(SAMPLES) $(EXAMPLES): - $(Q)$(MAKE) -C $@ - -#---------------------------------------------------------------------- -clean:: - $(foreach dir,$(PLUGINS) $(SAMPLES) $(EXAMPLES),$(MAKE) -C $(dir) clean;) diff --git a/idasdk75/plugins/mtsample/makefile b/idasdk75/plugins/mtsample/makefile deleted file mode 100644 index c09103a..0000000 --- a/idasdk75/plugins/mtsample/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=mtsample - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)mtsample$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp mtsample.cpp diff --git a/idasdk75/plugins/navcolor/makefile b/idasdk75/plugins/navcolor/makefile deleted file mode 100644 index 7338719..0000000 --- a/idasdk75/plugins/navcolor/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=navcolor - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)navcolor$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp navcolor.cpp diff --git a/idasdk75/plugins/openform/makefile b/idasdk75/plugins/openform/makefile deleted file mode 100644 index 303a2d8..0000000 --- a/idasdk75/plugins/openform/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=openform - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)openform$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp openform.cpp diff --git a/idasdk75/plugins/pdb/common.cpp b/idasdk75/plugins/pdb/common.cpp deleted file mode 100644 index eb3967f..0000000 --- a/idasdk75/plugins/pdb/common.cpp +++ /dev/null @@ -1,2546 +0,0 @@ - -#include "pdbaccess.hpp" - -//---------------------------------------------------------------------------- -static const char g_spath_prefix[] = "srv*"; -static const char g_spath_suffix[] = "*http://msdl.microsoft.com/download/symbols"; - -//---------------------------------------------------------------------------- -HRESULT pdb_access_t::iterate_subtags( - pdb_sym_t &sym, - enum SymTagEnum type, - children_visitor_t &visitor) -{ - struct subtag_helper_t : children_visitor_t - { - pdb_access_t *tb; - enum SymTagEnum type; - children_visitor_t &visitor; - virtual HRESULT visit_child(pdb_sym_t &_sym) override - { - return tb->iterate_children(_sym, type, visitor); - } - subtag_helper_t(pdb_access_t *_tb, enum SymTagEnum t, children_visitor_t &_visitor) - : tb(_tb), - type(t), - visitor(_visitor) {} - }; - subtag_helper_t helper(this, type, visitor); - return iterate_children(sym, SymTagCompiland, helper); -} - -//---------------------------------------------------------------------------- -HRESULT pdb_access_t::iterate_children( - pdb_sym_t &sym, - enum SymTagEnum type, - children_visitor_t &visitor) -{ - visitor.parent = &sym; - return do_iterate_children(sym, type, visitor); -} - -//---------------------------------------------------------------------- -void print_pdb_register(qstring *out, int machine, int reg) -{ - // Register subset shared by all processor types, - switch ( reg ) - { - case CV_ALLREG_ERR: *out = "[*err*]"; return; - case CV_ALLREG_TEB: *out = "[*teb*]"; return; - case CV_ALLREG_TIMER: *out = "[*timer*]"; return; - case CV_ALLREG_EFAD1: *out = "[*efad1*]"; return; - case CV_ALLREG_EFAD2: *out = "[*efad2*]"; return; - case CV_ALLREG_EFAD3: *out = "[*efad3*]"; return; - case CV_ALLREG_VFRAME: *out = "[*vframe*]"; return; - case CV_ALLREG_HANDLE: *out = "[*handle*]"; return; - case CV_ALLREG_PARAMS: *out = "[*params*]"; return; - case CV_ALLREG_LOCALS: *out = "[*locals*]"; return; - case CV_ALLREG_TID: *out = "[*tid*]"; return; - case CV_ALLREG_ENV: *out = "[*env*]"; return; - case CV_ALLREG_CMDLN: *out = "[*cmdln*]"; return; - } - - // Processor specific subsets - switch ( machine ) - { - case CV_CFL_8080: - case CV_CFL_8086: - case CV_CFL_80286: - case CV_CFL_80386: - case CV_CFL_80486: - case CV_CFL_PENTIUM: - case CV_CFL_PENTIUMII: - case CV_CFL_PENTIUMIII: - // Register set for the Intel 80x86 and ix86 processor series - // (plus PCODE registers) - switch ( reg ) - { - case CV_REG_NONE: *out = "none"; return; - case CV_REG_AL: *out = "al"; return; - case CV_REG_CL: *out = "cl"; return; - case CV_REG_DL: *out = "dl"; return; - case CV_REG_BL: *out = "bl"; return; - case CV_REG_AH: *out = "ah"; return; - case CV_REG_CH: *out = "ch"; return; - case CV_REG_DH: *out = "dh"; return; - case CV_REG_BH: *out = "bh"; return; - case CV_REG_AX: *out = "ax"; return; - case CV_REG_CX: *out = "cx"; return; - case CV_REG_DX: *out = "dx"; return; - case CV_REG_BX: *out = "bx"; return; - case CV_REG_SP: *out = "sp"; return; - case CV_REG_BP: *out = "bp"; return; - case CV_REG_SI: *out = "si"; return; - case CV_REG_DI: *out = "di"; return; - case CV_REG_EAX: *out = "eax"; return; - case CV_REG_ECX: *out = "ecx"; return; - case CV_REG_EDX: *out = "edx"; return; - case CV_REG_EBX: *out = "ebx"; return; - case CV_REG_ESP: *out = "esp"; return; - case CV_REG_EBP: *out = "ebp"; return; - case CV_REG_ESI: *out = "esi"; return; - case CV_REG_EDI: *out = "edi"; return; - case CV_REG_ES: *out = "es"; return; - case CV_REG_CS: *out = "cs"; return; - case CV_REG_SS: *out = "ss"; return; - case CV_REG_DS: *out = "ds"; return; - case CV_REG_FS: *out = "fs"; return; - case CV_REG_GS: *out = "gs"; return; - case CV_REG_IP: *out = "ip"; return; - case CV_REG_FLAGS: *out = "flags"; return; - case CV_REG_EIP: *out = "eip"; return; - case CV_REG_EFLAGS: *out = "eflags"; return; - case CV_REG_TEMP: *out = "temp"; return; // PCODE Temp return; - case CV_REG_TEMPH: *out = "temph"; return; // PCODE TempH return; - case CV_REG_QUOTE: *out = "quote"; return; // PCODE Quote return; - case CV_REG_PCDR3: *out = "pcdr3"; return; // PCODE reserved return; - case CV_REG_PCDR4: *out = "pcdr4"; return; // PCODE reserved return; - case CV_REG_PCDR5: *out = "pcdr5"; return; // PCODE reserved return; - case CV_REG_PCDR6: *out = "pcdr6"; return; // PCODE reserved return; - case CV_REG_PCDR7: *out = "pcdr7"; return; // PCODE reserved return; - case CV_REG_CR0: *out = "cr0"; return; // CR0 -- control registers return; - case CV_REG_CR1: *out = "cr1"; return; - case CV_REG_CR2: *out = "cr2"; return; - case CV_REG_CR3: *out = "cr3"; return; - case CV_REG_CR4: *out = "cr4"; return; // Pentium return; - case CV_REG_DR0: *out = "dr0"; return; // Debug register return; - case CV_REG_DR1: *out = "dr1"; return; - case CV_REG_DR2: *out = "dr2"; return; - case CV_REG_DR3: *out = "dr3"; return; - case CV_REG_DR4: *out = "dr4"; return; - case CV_REG_DR5: *out = "dr5"; return; - case CV_REG_DR6: *out = "dr6"; return; - case CV_REG_DR7: *out = "dr7"; return; - case CV_REG_GDTR: *out = "gdtr"; return; - case CV_REG_GDTL: *out = "gdtl"; return; - case CV_REG_IDTR: *out = "idtr"; return; - case CV_REG_IDTL: *out = "idtl"; return; - case CV_REG_LDTR: *out = "ldtr"; return; - case CV_REG_TR: *out = "tr"; return; - - case CV_REG_PSEUDO1: *out = "pseudo1"; return; - case CV_REG_PSEUDO2: *out = "pseudo2"; return; - case CV_REG_PSEUDO3: *out = "pseudo3"; return; - case CV_REG_PSEUDO4: *out = "pseudo4"; return; - case CV_REG_PSEUDO5: *out = "pseudo5"; return; - case CV_REG_PSEUDO6: *out = "pseudo6"; return; - case CV_REG_PSEUDO7: *out = "pseudo7"; return; - case CV_REG_PSEUDO8: *out = "pseudo8"; return; - case CV_REG_PSEUDO9: *out = "pseudo9"; return; - - case CV_REG_ST0: *out = "st0"; return; - case CV_REG_ST1: *out = "st1"; return; - case CV_REG_ST2: *out = "st2"; return; - case CV_REG_ST3: *out = "st3"; return; - case CV_REG_ST4: *out = "st4"; return; - case CV_REG_ST5: *out = "st5"; return; - case CV_REG_ST6: *out = "st6"; return; - case CV_REG_ST7: *out = "st7"; return; - case CV_REG_CTRL: *out = "ctrl"; return; - case CV_REG_STAT: *out = "stat"; return; - case CV_REG_TAG: *out = "tag"; return; - case CV_REG_FPIP: *out = "fpip"; return; - case CV_REG_FPCS: *out = "fpcs"; return; - case CV_REG_FPDO: *out = "fpdo"; return; - case CV_REG_FPDS: *out = "fpds"; return; - case CV_REG_ISEM: *out = "isem"; return; - case CV_REG_FPEIP: *out = "fpeip"; return; - case CV_REG_FPEDO: *out = "fpedo"; return; - - case CV_REG_MM0: *out = "mm0"; return; - case CV_REG_MM1: *out = "mm1"; return; - case CV_REG_MM2: *out = "mm2"; return; - case CV_REG_MM3: *out = "mm3"; return; - case CV_REG_MM4: *out = "mm4"; return; - case CV_REG_MM5: *out = "mm5"; return; - case CV_REG_MM6: *out = "mm6"; return; - case CV_REG_MM7: *out = "mm7"; return; - - case CV_REG_XMM0: *out = "xmm0"; return; // KATMAI registers return; - case CV_REG_XMM1: *out = "xmm1"; return; - case CV_REG_XMM2: *out = "xmm2"; return; - case CV_REG_XMM3: *out = "xmm3"; return; - case CV_REG_XMM4: *out = "xmm4"; return; - case CV_REG_XMM5: *out = "xmm5"; return; - case CV_REG_XMM6: *out = "xmm6"; return; - case CV_REG_XMM7: *out = "xmm7"; return; - - case CV_REG_XMM00: *out = "xmm00"; return; // KATMAI sub-registers return; - case CV_REG_XMM01: *out = "xmm01"; return; - case CV_REG_XMM02: *out = "xmm02"; return; - case CV_REG_XMM03: *out = "xmm03"; return; - case CV_REG_XMM10: *out = "xmm10"; return; - case CV_REG_XMM11: *out = "xmm11"; return; - case CV_REG_XMM12: *out = "xmm12"; return; - case CV_REG_XMM13: *out = "xmm13"; return; - case CV_REG_XMM20: *out = "xmm20"; return; - case CV_REG_XMM21: *out = "xmm21"; return; - case CV_REG_XMM22: *out = "xmm22"; return; - case CV_REG_XMM23: *out = "xmm23"; return; - case CV_REG_XMM30: *out = "xmm30"; return; - case CV_REG_XMM31: *out = "xmm31"; return; - case CV_REG_XMM32: *out = "xmm32"; return; - case CV_REG_XMM33: *out = "xmm33"; return; - case CV_REG_XMM40: *out = "xmm40"; return; - case CV_REG_XMM41: *out = "xmm41"; return; - case CV_REG_XMM42: *out = "xmm42"; return; - case CV_REG_XMM43: *out = "xmm43"; return; - case CV_REG_XMM50: *out = "xmm50"; return; - case CV_REG_XMM51: *out = "xmm51"; return; - case CV_REG_XMM52: *out = "xmm52"; return; - case CV_REG_XMM53: *out = "xmm53"; return; - case CV_REG_XMM60: *out = "xmm60"; return; - case CV_REG_XMM61: *out = "xmm61"; return; - case CV_REG_XMM62: *out = "xmm62"; return; - case CV_REG_XMM63: *out = "xmm63"; return; - case CV_REG_XMM70: *out = "xmm70"; return; - case CV_REG_XMM71: *out = "xmm71"; return; - case CV_REG_XMM72: *out = "xmm72"; return; - case CV_REG_XMM73: *out = "xmm73"; return; - - case CV_REG_XMM0L: *out = "xmm0l"; return; - case CV_REG_XMM1L: *out = "xmm1l"; return; - case CV_REG_XMM2L: *out = "xmm2l"; return; - case CV_REG_XMM3L: *out = "xmm3l"; return; - case CV_REG_XMM4L: *out = "xmm4l"; return; - case CV_REG_XMM5L: *out = "xmm5l"; return; - case CV_REG_XMM6L: *out = "xmm6l"; return; - case CV_REG_XMM7L: *out = "xmm7l"; return; - - case CV_REG_XMM0H: *out = "xmm0h"; return; - case CV_REG_XMM1H: *out = "xmm1h"; return; - case CV_REG_XMM2H: *out = "xmm2h"; return; - case CV_REG_XMM3H: *out = "xmm3h"; return; - case CV_REG_XMM4H: *out = "xmm4h"; return; - case CV_REG_XMM5H: *out = "xmm5h"; return; - case CV_REG_XMM6H: *out = "xmm6h"; return; - case CV_REG_XMM7H: *out = "xmm7h"; return; - - case CV_REG_MXCSR: *out = "mxcsr"; return; // XMM status register - - case CV_REG_EDXEAX: *out = "edxeax"; return; // EDX";EAX pair - - case CV_REG_EMM0L: *out = "emm0l"; return; // XMM sub-registers (WNI integer) - case CV_REG_EMM1L: *out = "emm1l"; return; - case CV_REG_EMM2L: *out = "emm2l"; return; - case CV_REG_EMM3L: *out = "emm3l"; return; - case CV_REG_EMM4L: *out = "emm4l"; return; - case CV_REG_EMM5L: *out = "emm5l"; return; - case CV_REG_EMM6L: *out = "emm6l"; return; - case CV_REG_EMM7L: *out = "emm7l"; return; - - case CV_REG_EMM0H: *out = "emm0h"; return; - case CV_REG_EMM1H: *out = "emm1h"; return; - case CV_REG_EMM2H: *out = "emm2h"; return; - case CV_REG_EMM3H: *out = "emm3h"; return; - case CV_REG_EMM4H: *out = "emm4h"; return; - case CV_REG_EMM5H: *out = "emm5h"; return; - case CV_REG_EMM6H: *out = "emm6h"; return; - case CV_REG_EMM7H: *out = "emm7h"; return; - - - case CV_REG_MM00: *out = "mm00"; return; // do not change the order of these regs, first one must be even too - case CV_REG_MM01: *out = "mm01"; return; - case CV_REG_MM10: *out = "mm10"; return; - case CV_REG_MM11: *out = "mm11"; return; - case CV_REG_MM20: *out = "mm20"; return; - case CV_REG_MM21: *out = "mm21"; return; - case CV_REG_MM30: *out = "mm30"; return; - case CV_REG_MM31: *out = "mm31"; return; - case CV_REG_MM40: *out = "mm40"; return; - case CV_REG_MM41: *out = "mm41"; return; - case CV_REG_MM50: *out = "mm50"; return; - case CV_REG_MM51: *out = "mm51"; return; - case CV_REG_MM60: *out = "mm60"; return; - case CV_REG_MM61: *out = "mm61"; return; - case CV_REG_MM70: *out = "mm70"; return; - case CV_REG_MM71: *out = "mm71"; return; - } - break; - - // registers for the 68K processors - case CV_CFL_M68000: - case CV_CFL_M68010: - case CV_CFL_M68020: - case CV_CFL_M68030: - case CV_CFL_M68040: - switch ( reg ) - { - case CV_R68_D0: *out = "D0"; return; - case CV_R68_D1: *out = "D1"; return; - case CV_R68_D2: *out = "D2"; return; - case CV_R68_D3: *out = "D3"; return; - case CV_R68_D4: *out = "D4"; return; - case CV_R68_D5: *out = "D5"; return; - case CV_R68_D6: *out = "D6"; return; - case CV_R68_D7: *out = "D7"; return; - case CV_R68_A0: *out = "A0"; return; - case CV_R68_A1: *out = "A1"; return; - case CV_R68_A2: *out = "A2"; return; - case CV_R68_A3: *out = "A3"; return; - case CV_R68_A4: *out = "A4"; return; - case CV_R68_A5: *out = "A5"; return; - case CV_R68_A6: *out = "A6"; return; - case CV_R68_A7: *out = "A7"; return; - case CV_R68_CCR: *out = "CCR"; return; - case CV_R68_SR: *out = "SR"; return; - case CV_R68_USP: *out = "USP"; return; - case CV_R68_MSP: *out = "MSP"; return; - case CV_R68_SFC: *out = "SFC"; return; - case CV_R68_DFC: *out = "DFC"; return; - case CV_R68_CACR: *out = "CACR"; return; - case CV_R68_VBR: *out = "VBR"; return; - case CV_R68_CAAR: *out = "CAAR"; return; - case CV_R68_ISP: *out = "ISP"; return; - case CV_R68_PC: *out = "PC"; return; - //reserved 27 - case CV_R68_FPCR: *out = "FPCR"; return; - case CV_R68_FPSR: *out = "FPSR"; return; - case CV_R68_FPIAR: *out = "FPIAR"; return; - //reserved 31 - case CV_R68_FP0: *out = "FP0"; return; - case CV_R68_FP1: *out = "FP1"; return; - case CV_R68_FP2: *out = "FP2"; return; - case CV_R68_FP3: *out = "FP3"; return; - case CV_R68_FP4: *out = "FP4"; return; - case CV_R68_FP5: *out = "FP5"; return; - case CV_R68_FP6: *out = "FP6"; return; - case CV_R68_FP7: *out = "FP7"; return; - //reserved 40 - case CV_R68_MMUSR030:*out = "MMUSR030"; return; - case CV_R68_MMUSR: *out = "MMUSR"; return; - case CV_R68_URP: *out = "URP"; return; - case CV_R68_DTT0: *out = "DTT0"; return; - case CV_R68_DTT1: *out = "DTT1"; return; - case CV_R68_ITT0: *out = "ITT0"; return; - case CV_R68_ITT1: *out = "ITT1"; return; - //reserved 50 - case CV_R68_PSR: *out = "PSR"; return; - case CV_R68_PCSR: *out = "PCSR"; return; - case CV_R68_VAL: *out = "VAL"; return; - case CV_R68_CRP: *out = "CRP"; return; - case CV_R68_SRP: *out = "SRP"; return; - case CV_R68_DRP: *out = "DRP"; return; - case CV_R68_TC: *out = "TC"; return; - case CV_R68_AC: *out = "AC"; return; - case CV_R68_SCC: *out = "SCC"; return; - case CV_R68_CAL: *out = "CAL"; return; - case CV_R68_TT0: *out = "TT0"; return; - case CV_R68_TT1: *out = "TT1"; return; - //reserved 63 - case CV_R68_BAD0: *out = "BAD0"; return; - case CV_R68_BAD1: *out = "BAD1"; return; - case CV_R68_BAD2: *out = "BAD2"; return; - case CV_R68_BAD3: *out = "BAD3"; return; - case CV_R68_BAD4: *out = "BAD4"; return; - case CV_R68_BAD5: *out = "BAD5"; return; - case CV_R68_BAD6: *out = "BAD6"; return; - case CV_R68_BAD7: *out = "BAD7"; return; - case CV_R68_BAC0: *out = "BAC0"; return; - case CV_R68_BAC1: *out = "BAC1"; return; - case CV_R68_BAC2: *out = "BAC2"; return; - case CV_R68_BAC3: *out = "BAC3"; return; - case CV_R68_BAC4: *out = "BAC4"; return; - case CV_R68_BAC5: *out = "BAC5"; return; - case CV_R68_BAC6: *out = "BAC6"; return; - case CV_R68_BAC7: *out = "BAC7"; return; - } - break; - - case CV_CFL_MIPS: - case CV_CFL_MIPS16: - case CV_CFL_MIPS32: - case CV_CFL_MIPS64: - case CV_CFL_MIPSI: - case CV_CFL_MIPSII: - case CV_CFL_MIPSIII: - case CV_CFL_MIPSIV: - case CV_CFL_MIPSV: - switch ( reg ) - { - // Register set for the MIPS 4000 - case CV_M4_NOREG: *out = "NOREG"; return; - case CV_M4_IntZERO: *out = "IntZERO"; return; /* CPU REGISTER */ - case CV_M4_IntAT: *out = "IntAT"; return; - case CV_M4_IntV0: *out = "IntV0"; return; - case CV_M4_IntV1: *out = "IntV1"; return; - case CV_M4_IntA0: *out = "IntA0"; return; - case CV_M4_IntA1: *out = "IntA1"; return; - case CV_M4_IntA2: *out = "IntA2"; return; - case CV_M4_IntA3: *out = "IntA3"; return; - case CV_M4_IntT0: *out = "IntT0"; return; - case CV_M4_IntT1: *out = "IntT1"; return; - case CV_M4_IntT2: *out = "IntT2"; return; - case CV_M4_IntT3: *out = "IntT3"; return; - case CV_M4_IntT4: *out = "IntT4"; return; - case CV_M4_IntT5: *out = "IntT5"; return; - case CV_M4_IntT6: *out = "IntT6"; return; - case CV_M4_IntT7: *out = "IntT7"; return; - case CV_M4_IntS0: *out = "IntS0"; return; - case CV_M4_IntS1: *out = "IntS1"; return; - case CV_M4_IntS2: *out = "IntS2"; return; - case CV_M4_IntS3: *out = "IntS3"; return; - case CV_M4_IntS4: *out = "IntS4"; return; - case CV_M4_IntS5: *out = "IntS5"; return; - case CV_M4_IntS6: *out = "IntS6"; return; - case CV_M4_IntS7: *out = "IntS7"; return; - case CV_M4_IntT8: *out = "IntT8"; return; - case CV_M4_IntT9: *out = "IntT9"; return; - case CV_M4_IntKT0: *out = "IntKT0"; return; - case CV_M4_IntKT1: *out = "IntKT1"; return; - case CV_M4_IntGP: *out = "IntGP"; return; - case CV_M4_IntSP: *out = "IntSP"; return; - case CV_M4_IntS8: *out = "IntS8"; return; - case CV_M4_IntRA: *out = "IntRA"; return; - case CV_M4_IntLO: *out = "IntLO"; return; - case CV_M4_IntHI: *out = "IntHI"; return; - - case CV_M4_Fir: - case CV_M4_Psr: - - case CV_M4_FltF0: *out = "FltF0"; return; /* Floating point registers */ - case CV_M4_FltF1: *out = "FltF1"; return; - case CV_M4_FltF2: *out = "FltF2"; return; - case CV_M4_FltF3: *out = "FltF3"; return; - case CV_M4_FltF4: *out = "FltF4"; return; - case CV_M4_FltF5: *out = "FltF5"; return; - case CV_M4_FltF6: *out = "FltF6"; return; - case CV_M4_FltF7: *out = "FltF7"; return; - case CV_M4_FltF8: *out = "FltF8"; return; - case CV_M4_FltF9: *out = "FltF9"; return; - case CV_M4_FltF10: *out = "FltF10"; return; - case CV_M4_FltF11: *out = "FltF11"; return; - case CV_M4_FltF12: *out = "FltF12"; return; - case CV_M4_FltF13: *out = "FltF13"; return; - case CV_M4_FltF14: *out = "FltF14"; return; - case CV_M4_FltF15: *out = "FltF15"; return; - case CV_M4_FltF16: *out = "FltF16"; return; - case CV_M4_FltF17: *out = "FltF17"; return; - case CV_M4_FltF18: *out = "FltF18"; return; - case CV_M4_FltF19: *out = "FltF19"; return; - case CV_M4_FltF20: *out = "FltF20"; return; - case CV_M4_FltF21: *out = "FltF21"; return; - case CV_M4_FltF22: *out = "FltF22"; return; - case CV_M4_FltF23: *out = "FltF23"; return; - case CV_M4_FltF24: *out = "FltF24"; return; - case CV_M4_FltF25: *out = "FltF25"; return; - case CV_M4_FltF26: *out = "FltF26"; return; - case CV_M4_FltF27: *out = "FltF27"; return; - case CV_M4_FltF28: *out = "FltF28"; return; - case CV_M4_FltF29: *out = "FltF29"; return; - case CV_M4_FltF30: *out = "FltF30"; return; - case CV_M4_FltF31: *out = "FltF31"; return; - case CV_M4_FltFsr: *out = "FltFsr"; return; - } - break; - - case CV_CFL_ALPHA: -// case CV_CFL_ALPHA_21064: - case CV_CFL_ALPHA_21164: - case CV_CFL_ALPHA_21164A: - case CV_CFL_ALPHA_21264: - case CV_CFL_ALPHA_21364: - // Register set for the ALPHA AXP - switch ( reg ) - { - case CV_ALPHA_NOREG: *out = "NOREG"; return; - case CV_ALPHA_FltF0: *out = "FltF0"; return; // Floating point registers - case CV_ALPHA_FltF1: *out = "FltF1"; return; - case CV_ALPHA_FltF2: *out = "FltF2"; return; - case CV_ALPHA_FltF3: *out = "FltF3"; return; - case CV_ALPHA_FltF4: *out = "FltF4"; return; - case CV_ALPHA_FltF5: *out = "FltF5"; return; - case CV_ALPHA_FltF6: *out = "FltF6"; return; - case CV_ALPHA_FltF7: *out = "FltF7"; return; - case CV_ALPHA_FltF8: *out = "FltF8"; return; - case CV_ALPHA_FltF9: *out = "FltF9"; return; - case CV_ALPHA_FltF10:*out = "FltF10"; return; - case CV_ALPHA_FltF11:*out = "FltF11"; return; - case CV_ALPHA_FltF12:*out = "FltF12"; return; - case CV_ALPHA_FltF13:*out = "FltF13"; return; - case CV_ALPHA_FltF14:*out = "FltF14"; return; - case CV_ALPHA_FltF15:*out = "FltF15"; return; - case CV_ALPHA_FltF16:*out = "FltF16"; return; - case CV_ALPHA_FltF17:*out = "FltF17"; return; - case CV_ALPHA_FltF18:*out = "FltF18"; return; - case CV_ALPHA_FltF19:*out = "FltF19"; return; - case CV_ALPHA_FltF20:*out = "FltF20"; return; - case CV_ALPHA_FltF21:*out = "FltF21"; return; - case CV_ALPHA_FltF22:*out = "FltF22"; return; - case CV_ALPHA_FltF23:*out = "FltF23"; return; - case CV_ALPHA_FltF24:*out = "FltF24"; return; - case CV_ALPHA_FltF25:*out = "FltF25"; return; - case CV_ALPHA_FltF26:*out = "FltF26"; return; - case CV_ALPHA_FltF27:*out = "FltF27"; return; - case CV_ALPHA_FltF28:*out = "FltF28"; return; - case CV_ALPHA_FltF29:*out = "FltF29"; return; - case CV_ALPHA_FltF30:*out = "FltF30"; return; - case CV_ALPHA_FltF31:*out = "FltF31"; return; - - case CV_ALPHA_IntV0: *out = "IntV0"; return; // Integer registers - case CV_ALPHA_IntT0: *out = "IntT0"; return; - case CV_ALPHA_IntT1: *out = "IntT1"; return; - case CV_ALPHA_IntT2: *out = "IntT2"; return; - case CV_ALPHA_IntT3: *out = "IntT3"; return; - case CV_ALPHA_IntT4: *out = "IntT4"; return; - case CV_ALPHA_IntT5: *out = "IntT5"; return; - case CV_ALPHA_IntT6: *out = "IntT6"; return; - case CV_ALPHA_IntT7: *out = "IntT7"; return; - case CV_ALPHA_IntS0: *out = "IntS0"; return; - case CV_ALPHA_IntS1: *out = "IntS1"; return; - case CV_ALPHA_IntS2: *out = "IntS2"; return; - case CV_ALPHA_IntS3: *out = "IntS3"; return; - case CV_ALPHA_IntS4: *out = "IntS4"; return; - case CV_ALPHA_IntS5: *out = "IntS5"; return; - case CV_ALPHA_IntFP: *out = "IntFP"; return; - case CV_ALPHA_IntA0: *out = "IntA0"; return; - case CV_ALPHA_IntA1: *out = "IntA1"; return; - case CV_ALPHA_IntA2: *out = "IntA2"; return; - case CV_ALPHA_IntA3: *out = "IntA3"; return; - case CV_ALPHA_IntA4: *out = "IntA4"; return; - case CV_ALPHA_IntA5: *out = "IntA5"; return; - case CV_ALPHA_IntT8: *out = "IntT8"; return; - case CV_ALPHA_IntT9: *out = "IntT9"; return; - case CV_ALPHA_IntT10:*out = "IntT10"; return; - case CV_ALPHA_IntT11:*out = "IntT11"; return; - case CV_ALPHA_IntRA: *out = "IntRA"; return; - case CV_ALPHA_IntT12:*out = "IntT12"; return; - case CV_ALPHA_IntAT: *out = "IntAT"; return; - case CV_ALPHA_IntGP: *out = "IntGP"; return; - case CV_ALPHA_IntSP: *out = "IntSP"; return; - case CV_ALPHA_IntZERO:*out = "IntZERO"; return; - - case CV_ALPHA_Fpcr: *out = "Fpcr"; return; // Control registers - case CV_ALPHA_Fir: *out = "Fir"; return; - case CV_ALPHA_Psr: *out = "Psr"; return; - case CV_ALPHA_FltFsr:*out = "FltFsr"; return; - case CV_ALPHA_SoftFpcr:*out = "SoftFpcr"; return; - } - break; - - case CV_CFL_PPC601: - case CV_CFL_PPC603: - case CV_CFL_PPC604: - case CV_CFL_PPC620: - case CV_CFL_PPCFP: - case CV_CFL_PPCBE: - // Register Set for Motorola/IBM PowerPC - switch ( reg ) - { - /* - ** PowerPC General Registers ( User Level ) - */ - case CV_PPC_GPR0: *out = "gpr0"; return; - case CV_PPC_GPR1: *out = "gpr1"; return; - case CV_PPC_GPR2: *out = "gpr2"; return; - case CV_PPC_GPR3: *out = "gpr3"; return; - case CV_PPC_GPR4: *out = "gpr4"; return; - case CV_PPC_GPR5: *out = "gpr5"; return; - case CV_PPC_GPR6: *out = "gpr6"; return; - case CV_PPC_GPR7: *out = "gpr7"; return; - case CV_PPC_GPR8: *out = "gpr8"; return; - case CV_PPC_GPR9: *out = "gpr9"; return; - case CV_PPC_GPR10: *out = "gpr10"; return; - case CV_PPC_GPR11: *out = "gpr11"; return; - case CV_PPC_GPR12: *out = "gpr12"; return; - case CV_PPC_GPR13: *out = "gpr13"; return; - case CV_PPC_GPR14: *out = "gpr14"; return; - case CV_PPC_GPR15: *out = "gpr15"; return; - case CV_PPC_GPR16: *out = "gpr16"; return; - case CV_PPC_GPR17: *out = "gpr17"; return; - case CV_PPC_GPR18: *out = "gpr18"; return; - case CV_PPC_GPR19: *out = "gpr19"; return; - case CV_PPC_GPR20: *out = "gpr20"; return; - case CV_PPC_GPR21: *out = "gpr21"; return; - case CV_PPC_GPR22: *out = "gpr22"; return; - case CV_PPC_GPR23: *out = "gpr23"; return; - case CV_PPC_GPR24: *out = "gpr24"; return; - case CV_PPC_GPR25: *out = "gpr25"; return; - case CV_PPC_GPR26: *out = "gpr26"; return; - case CV_PPC_GPR27: *out = "gpr27"; return; - case CV_PPC_GPR28: *out = "gpr28"; return; - case CV_PPC_GPR29: *out = "gpr29"; return; - case CV_PPC_GPR30: *out = "gpr30"; return; - case CV_PPC_GPR31: *out = "gpr31"; return; - - /* - ** PowerPC Condition Register ( user level ) - */ - case CV_PPC_CR: *out = "cr"; return; - case CV_PPC_CR0: *out = "cr0"; return; - case CV_PPC_CR1: *out = "cr1"; return; - case CV_PPC_CR2: *out = "cr2"; return; - case CV_PPC_CR3: *out = "cr3"; return; - case CV_PPC_CR4: *out = "cr4"; return; - case CV_PPC_CR5: *out = "cr5"; return; - case CV_PPC_CR6: *out = "cr6"; return; - case CV_PPC_CR7: *out = "cr7"; return; - - /* - ** PowerPC Floating Point Registers ( user Level ) - */ - case CV_PPC_FPR0: *out = "fpr0"; return; - case CV_PPC_FPR1: *out = "fpr1"; return; - case CV_PPC_FPR2: *out = "fpr2"; return; - case CV_PPC_FPR3: *out = "fpr3"; return; - case CV_PPC_FPR4: *out = "fpr4"; return; - case CV_PPC_FPR5: *out = "fpr5"; return; - case CV_PPC_FPR6: *out = "fpr6"; return; - case CV_PPC_FPR7: *out = "fpr7"; return; - case CV_PPC_FPR8: *out = "fpr8"; return; - case CV_PPC_FPR9: *out = "fpr9"; return; - case CV_PPC_FPR10: *out = "fpr10"; return; - case CV_PPC_FPR11: *out = "fpr11"; return; - case CV_PPC_FPR12: *out = "fpr12"; return; - case CV_PPC_FPR13: *out = "fpr13"; return; - case CV_PPC_FPR14: *out = "fpr14"; return; - case CV_PPC_FPR15: *out = "fpr15"; return; - case CV_PPC_FPR16: *out = "fpr16"; return; - case CV_PPC_FPR17: *out = "fpr17"; return; - case CV_PPC_FPR18: *out = "fpr18"; return; - case CV_PPC_FPR19: *out = "fpr19"; return; - case CV_PPC_FPR20: *out = "fpr20"; return; - case CV_PPC_FPR21: *out = "fpr21"; return; - case CV_PPC_FPR22: *out = "fpr22"; return; - case CV_PPC_FPR23: *out = "fpr23"; return; - case CV_PPC_FPR24: *out = "fpr24"; return; - case CV_PPC_FPR25: *out = "fpr25"; return; - case CV_PPC_FPR26: *out = "fpr26"; return; - case CV_PPC_FPR27: *out = "fpr27"; return; - case CV_PPC_FPR28: *out = "fpr28"; return; - case CV_PPC_FPR29: *out = "fpr29"; return; - case CV_PPC_FPR30: *out = "fpr30"; return; - case CV_PPC_FPR31: *out = "fpr31"; return; - - /* - ** PowerPC Floating Point Status and Control Register ( User Level ) - */ - case CV_PPC_FPSCR: *out = "FPSCR"; return; - - /* - ** PowerPC Machine State Register ( Supervisor Level ) - */ - case CV_PPC_MSR: *out = "msr"; return; - - /* - ** PowerPC Segment Registers ( Supervisor Level ) - */ - case CV_PPC_SR0: *out = "sr0"; return; - case CV_PPC_SR1: *out = "sr1"; return; - case CV_PPC_SR2: *out = "sr2"; return; - case CV_PPC_SR3: *out = "sr3"; return; - case CV_PPC_SR4: *out = "sr4"; return; - case CV_PPC_SR5: *out = "sr5"; return; - case CV_PPC_SR6: *out = "sr6"; return; - case CV_PPC_SR7: *out = "sr7"; return; - case CV_PPC_SR8: *out = "sr8"; return; - case CV_PPC_SR9: *out = "sr9"; return; - case CV_PPC_SR10: *out = "sr10"; return; - case CV_PPC_SR11: *out = "sr11"; return; - case CV_PPC_SR12: *out = "sr12"; return; - case CV_PPC_SR13: *out = "sr13"; return; - case CV_PPC_SR14: *out = "sr14"; return; - case CV_PPC_SR15: *out = "sr15"; return; - - /* - ** For all of the special purpose registers add 100 to the SPR# that the - ** Motorola/IBM documentation gives with the exception of any imaginary - ** registers. - */ - - /* - ** PowerPC Special Purpose Registers ( User Level ) - */ - case CV_PPC_PC: *out = "pc"; return; // PC (imaginary register) - - case CV_PPC_MQ: *out = "mq"; return; // MPC601 - case CV_PPC_XER: *out = "xer"; return; - case CV_PPC_RTCU: *out = "rtcu"; return; // MPC601 - case CV_PPC_RTCL: *out = "rtcl"; return; // MPC601 - case CV_PPC_LR: *out = "lr"; return; - case CV_PPC_CTR: *out = "ctr"; return; - - case CV_PPC_COMPARE: *out = "compare"; return;// part of XER (internal to the debugger only) - case CV_PPC_COUNT: *out = "count"; return;// part of XER (internal to the debugger only) - - /* - ** PowerPC Special Purpose Registers ( supervisor Level ) - */ - case CV_PPC_DSISR: *out = "dsisr"; return; - case CV_PPC_DAR: *out = "dar"; return; - case CV_PPC_DEC: *out = "dec"; return; - case CV_PPC_SDR1: *out = "sdr1"; return; - case CV_PPC_SRR0: *out = "srr0"; return; - case CV_PPC_SRR1: *out = "srr1"; return; - case CV_PPC_SPRG0: *out = "sprg0"; return; - case CV_PPC_SPRG1: *out = "sprg1"; return; - case CV_PPC_SPRG2: *out = "sprg2"; return; - case CV_PPC_SPRG3: *out = "sprg3"; return; - case CV_PPC_ASR: *out = "asr"; return;// 64-bit implementations only - case CV_PPC_EAR: *out = "ear"; return; - case CV_PPC_PVR: *out = "pvr"; return; - case CV_PPC_BAT0U: *out = "bat0u"; return; - case CV_PPC_BAT0L: *out = "bat0l"; return; - case CV_PPC_BAT1U: *out = "bat1u"; return; - case CV_PPC_BAT1L: *out = "bat1l"; return; - case CV_PPC_BAT2U: *out = "bat2u"; return; - case CV_PPC_BAT2L: *out = "bat2l"; return; - case CV_PPC_BAT3U: *out = "bat3u"; return; - case CV_PPC_BAT3L: *out = "bat3l"; return; - case CV_PPC_DBAT0U: *out = "dbat0u"; return; - case CV_PPC_DBAT0L: *out = "dbat0l"; return; - case CV_PPC_DBAT1U: *out = "dbat1u"; return; - case CV_PPC_DBAT1L: *out = "dbat1l"; return; - case CV_PPC_DBAT2U: *out = "dbat2u"; return; - case CV_PPC_DBAT2L: *out = "dbat2l"; return; - case CV_PPC_DBAT3U: *out = "dbat3u"; return; - case CV_PPC_DBAT3L: *out = "dbat3l"; return; - - /* - ** PowerPC Special Purpose Registers implementation Dependent ( Supervisor Level ) - */ - - /* - ** Doesn't appear that IBM/Motorola has finished defining these. - */ - - case CV_PPC_PMR0: *out = "pmr0"; return;// MPC620, - case CV_PPC_PMR1: *out = "pmr1"; return;// MPC620, - case CV_PPC_PMR2: *out = "pmr2"; return;// MPC620, - case CV_PPC_PMR3: *out = "pmr3"; return;// MPC620, - case CV_PPC_PMR4: *out = "pmr4"; return;// MPC620, - case CV_PPC_PMR5: *out = "pmr5"; return;// MPC620, - case CV_PPC_PMR6: *out = "pmr6"; return;// MPC620, - case CV_PPC_PMR7: *out = "pmr7"; return;// MPC620, - case CV_PPC_PMR8: *out = "pmr8"; return;// MPC620, - case CV_PPC_PMR9: *out = "pmr9"; return;// MPC620, - case CV_PPC_PMR10: *out = "pmr10"; return;// MPC620, - case CV_PPC_PMR11: *out = "pmr11"; return;// MPC620, - case CV_PPC_PMR12: *out = "pmr12"; return;// MPC620, - case CV_PPC_PMR13: *out = "pmr13"; return;// MPC620, - case CV_PPC_PMR14: *out = "pmr14"; return;// MPC620, - case CV_PPC_PMR15: *out = "pmr15"; return;// MPC620, - - case CV_PPC_DMISS: *out = "dmiss"; return;// MPC603 - case CV_PPC_DCMP: *out = "dcmp"; return;// MPC603 - case CV_PPC_HASH1: *out = "hash1"; return;// MPC603 - case CV_PPC_HASH2: *out = "hash2"; return;// MPC603 - case CV_PPC_IMISS: *out = "imiss"; return;// MPC603 - case CV_PPC_ICMP: *out = "icmp"; return;// MPC603 - case CV_PPC_RPA: *out = "rpa"; return;// MPC603 - - case CV_PPC_HID0: *out = "hid0"; return;// MPC601, MPC603, MPC620 - case CV_PPC_HID1: *out = "hid1"; return;// MPC601 - case CV_PPC_HID2: *out = "hid2"; return;// MPC601, MPC603, MPC620 ( IABR ) - case CV_PPC_HID3: *out = "hid3"; return;// Not Defined - case CV_PPC_HID4: *out = "hid4"; return;// Not Defined - case CV_PPC_HID5: *out = "hid5"; return;// MPC601, MPC604, MPC620 ( DABR ) - case CV_PPC_HID6: *out = "hid6"; return;// Not Defined - case CV_PPC_HID7: *out = "hid7"; return;// Not Defined - case CV_PPC_HID8: *out = "hid8"; return;// MPC620 ( BUSCSR ) - case CV_PPC_HID9: *out = "hid9"; return;// MPC620 ( L2CSR ) - case CV_PPC_HID10: *out = "hid10"; return;// Not Defined - case CV_PPC_HID11: *out = "hid11"; return;// Not Defined - case CV_PPC_HID12: *out = "hid12"; return;// Not Defined - case CV_PPC_HID13: *out = "hid13"; return;// MPC604 ( HCR ) - case CV_PPC_HID14: *out = "hid14"; return;// Not Defined - case CV_PPC_HID15: *out = "hid15"; return;// MPC601, MPC604, MPC620 ( PIR ) - } - break; - - // - // JAVA VM registers - // - - // case CV_JAVA_PC: *out = "PC"; return; - - case CV_CFL_SH3: - case CV_CFL_SH3E: - case CV_CFL_SH3DSP: - case CV_CFL_SH4: - // - // Register set for the Hitachi SH3 - // - switch ( reg ) - { - case CV_SH3_NOREG: *out = "NOREG"; return; - - case CV_SH3_IntR0: *out = "IntR0"; return;// CPU REGISTER - case CV_SH3_IntR1: *out = "IntR1"; return; - case CV_SH3_IntR2: *out = "IntR2"; return; - case CV_SH3_IntR3: *out = "IntR3"; return; - case CV_SH3_IntR4: *out = "IntR4"; return; - case CV_SH3_IntR5: *out = "IntR5"; return; - case CV_SH3_IntR6: *out = "IntR6"; return; - case CV_SH3_IntR7: *out = "IntR7"; return; - case CV_SH3_IntR8: *out = "IntR8"; return; - case CV_SH3_IntR9: *out = "IntR9"; return; - case CV_SH3_IntR10: *out = "IntR10"; return; - case CV_SH3_IntR11: *out = "IntR11"; return; - case CV_SH3_IntR12: *out = "IntR12"; return; - case CV_SH3_IntR13: *out = "IntR13"; return; - case CV_SH3_IntFp: *out = "IntFp"; return; - case CV_SH3_IntSp: *out = "IntSp"; return; - case CV_SH3_Gbr: *out = "Gbr"; return; - case CV_SH3_Pr: *out = "Pr"; return; - case CV_SH3_Mach: *out = "Mach"; return; - case CV_SH3_Macl: *out = "Macl"; return; - - case CV_SH3_Pc: *out = "Pc"; return; - case CV_SH3_Sr: *out = "Sr"; return; - - case CV_SH3_BarA: *out = "BarA"; return; - case CV_SH3_BasrA: *out = "BasrA"; return; - case CV_SH3_BamrA: *out = "BamrA"; return; - case CV_SH3_BbrA: *out = "BbrA"; return; - case CV_SH3_BarB: *out = "BarB"; return; - case CV_SH3_BasrB: *out = "BasrB"; return; - case CV_SH3_BamrB: *out = "BamrB"; return; - case CV_SH3_BbrB: *out = "BbrB"; return; - case CV_SH3_BdrB: *out = "BdrB"; return; - case CV_SH3_BdmrB: *out = "BdmrB"; return; - case CV_SH3_Brcr: *out = "Brcr"; return; - - // - // Additional registers for Hitachi SH processors - // - - case CV_SH_Fpscr: *out = "Fpscr"; return;// floating point status/control register - case CV_SH_Fpul: *out = "Fpul"; return;// floating point communication register - - case CV_SH_FpR0: *out = "FpR0"; return;// Floating point registers - case CV_SH_FpR1: *out = "FpR1"; return; - case CV_SH_FpR2: *out = "FpR2"; return; - case CV_SH_FpR3: *out = "FpR3"; return; - case CV_SH_FpR4: *out = "FpR4"; return; - case CV_SH_FpR5: *out = "FpR5"; return; - case CV_SH_FpR6: *out = "FpR6"; return; - case CV_SH_FpR7: *out = "FpR7"; return; - case CV_SH_FpR8: *out = "FpR8"; return; - case CV_SH_FpR9: *out = "FpR9"; return; - case CV_SH_FpR10: *out = "FpR10"; return; - case CV_SH_FpR11: *out = "FpR11"; return; - case CV_SH_FpR12: *out = "FpR12"; return; - case CV_SH_FpR13: *out = "FpR13"; return; - case CV_SH_FpR14: *out = "FpR14"; return; - case CV_SH_FpR15: *out = "FpR15"; return; - - case CV_SH_XFpR0: *out = "XFpR0"; return; - case CV_SH_XFpR1: *out = "XFpR1"; return; - case CV_SH_XFpR2: *out = "XFpR2"; return; - case CV_SH_XFpR3: *out = "XFpR3"; return; - case CV_SH_XFpR4: *out = "XFpR4"; return; - case CV_SH_XFpR5: *out = "XFpR5"; return; - case CV_SH_XFpR6: *out = "XFpR6"; return; - case CV_SH_XFpR7: *out = "XFpR7"; return; - case CV_SH_XFpR8: *out = "XFpR8"; return; - case CV_SH_XFpR9: *out = "XFpR9"; return; - case CV_SH_XFpR10: *out = "XFpR10"; return; - case CV_SH_XFpR11: *out = "XFpR11"; return; - case CV_SH_XFpR12: *out = "XFpR12"; return; - case CV_SH_XFpR13: *out = "XFpR13"; return; - case CV_SH_XFpR14: *out = "XFpR14"; return; - case CV_SH_XFpR15: *out = "XFpR15"; return; - } - break; - - case CV_CFL_ARM3: - case CV_CFL_ARM4: - case CV_CFL_ARM4T: - case CV_CFL_ARM5: - case CV_CFL_ARM5T: - case CV_CFL_ARM6: - case CV_CFL_ARM_XMAC: - case CV_CFL_ARM_WMMX: - case CV_CFL_THUMB: - // - // Register set for the ARM processor. - // - switch ( reg ) - { - case CV_ARM_NOREG: *out = "noreg"; return; - case CV_ARM_R0: *out = "r0"; return; - case CV_ARM_R1: *out = "r1"; return; - case CV_ARM_R2: *out = "r2"; return; - case CV_ARM_R3: *out = "r3"; return; - case CV_ARM_R4: *out = "r4"; return; - case CV_ARM_R5: *out = "r5"; return; - case CV_ARM_R6: *out = "r6"; return; - case CV_ARM_R7: *out = "r7"; return; - case CV_ARM_R8: *out = "r8"; return; - case CV_ARM_R9: *out = "r9"; return; - case CV_ARM_R10: *out = "r10"; return; - case CV_ARM_R11: *out = "r11"; return;// Frame pointer, if allocated - case CV_ARM_R12: *out = "r12"; return; - case CV_ARM_SP: *out = "sp"; return;// Stack pointer - case CV_ARM_LR: *out = "lr"; return;// Link Register - case CV_ARM_PC: *out = "pc"; return;// Program counter - case CV_ARM_CPSR: *out = "cpsr"; return;// Current program status register - } - break; - - case CV_CFL_IA64: -// case CV_CFL_IA64_1: - case CV_CFL_IA64_2: - // - // Register set for Intel IA64 - // - switch ( reg ) - { - case CV_IA64_NOREG: *out = "noreg"; return; - - // Branch Registers - - case CV_IA64_Br0: *out = "br0"; return; - case CV_IA64_Br1: *out = "br1"; return; - case CV_IA64_Br2: *out = "br2"; return; - case CV_IA64_Br3: *out = "br3"; return; - case CV_IA64_Br4: *out = "br4"; return; - case CV_IA64_Br5: *out = "br5"; return; - case CV_IA64_Br6: *out = "br6"; return; - case CV_IA64_Br7: *out = "br7"; return; - - // Predicate Registers - - case CV_IA64_P0: *out = "p0"; return; - case CV_IA64_P1: *out = "p1"; return; - case CV_IA64_P2: *out = "p2"; return; - case CV_IA64_P3: *out = "p3"; return; - case CV_IA64_P4: *out = "p4"; return; - case CV_IA64_P5: *out = "p5"; return; - case CV_IA64_P6: *out = "p6"; return; - case CV_IA64_P7: *out = "p7"; return; - case CV_IA64_P8: *out = "p8"; return; - case CV_IA64_P9: *out = "p9"; return; - case CV_IA64_P10: *out = "p10"; return; - case CV_IA64_P11: *out = "p11"; return; - case CV_IA64_P12: *out = "p12"; return; - case CV_IA64_P13: *out = "p13"; return; - case CV_IA64_P14: *out = "p14"; return; - case CV_IA64_P15: *out = "p15"; return; - case CV_IA64_P16: *out = "p16"; return; - case CV_IA64_P17: *out = "p17"; return; - case CV_IA64_P18: *out = "p18"; return; - case CV_IA64_P19: *out = "p19"; return; - case CV_IA64_P20: *out = "p20"; return; - case CV_IA64_P21: *out = "p21"; return; - case CV_IA64_P22: *out = "p22"; return; - case CV_IA64_P23: *out = "p23"; return; - case CV_IA64_P24: *out = "p24"; return; - case CV_IA64_P25: *out = "p25"; return; - case CV_IA64_P26: *out = "p26"; return; - case CV_IA64_P27: *out = "p27"; return; - case CV_IA64_P28: *out = "p28"; return; - case CV_IA64_P29: *out = "p29"; return; - case CV_IA64_P30: *out = "p30"; return; - case CV_IA64_P31: *out = "p31"; return; - case CV_IA64_P32: *out = "p32"; return; - case CV_IA64_P33: *out = "p33"; return; - case CV_IA64_P34: *out = "p34"; return; - case CV_IA64_P35: *out = "p35"; return; - case CV_IA64_P36: *out = "p36"; return; - case CV_IA64_P37: *out = "p37"; return; - case CV_IA64_P38: *out = "p38"; return; - case CV_IA64_P39: *out = "p39"; return; - case CV_IA64_P40: *out = "p40"; return; - case CV_IA64_P41: *out = "p41"; return; - case CV_IA64_P42: *out = "p42"; return; - case CV_IA64_P43: *out = "p43"; return; - case CV_IA64_P44: *out = "p44"; return; - case CV_IA64_P45: *out = "p45"; return; - case CV_IA64_P46: *out = "p46"; return; - case CV_IA64_P47: *out = "p47"; return; - case CV_IA64_P48: *out = "p48"; return; - case CV_IA64_P49: *out = "p49"; return; - case CV_IA64_P50: *out = "p50"; return; - case CV_IA64_P51: *out = "p51"; return; - case CV_IA64_P52: *out = "p52"; return; - case CV_IA64_P53: *out = "p53"; return; - case CV_IA64_P54: *out = "p54"; return; - case CV_IA64_P55: *out = "p55"; return; - case CV_IA64_P56: *out = "p56"; return; - case CV_IA64_P57: *out = "p57"; return; - case CV_IA64_P58: *out = "p58"; return; - case CV_IA64_P59: *out = "p59"; return; - case CV_IA64_P60: *out = "p60"; return; - case CV_IA64_P61: *out = "p61"; return; - case CV_IA64_P62: *out = "p62"; return; - case CV_IA64_P63: *out = "p63"; return; - - case CV_IA64_Preds: *out = "Preds"; return; - - // Banked General Registers - - case CV_IA64_IntH0: *out = "IntH0"; return; - case CV_IA64_IntH1: *out = "IntH1"; return; - case CV_IA64_IntH2: *out = "IntH2"; return; - case CV_IA64_IntH3: *out = "IntH3"; return; - case CV_IA64_IntH4: *out = "IntH4"; return; - case CV_IA64_IntH5: *out = "IntH5"; return; - case CV_IA64_IntH6: *out = "IntH6"; return; - case CV_IA64_IntH7: *out = "IntH7"; return; - case CV_IA64_IntH8: *out = "IntH8"; return; - case CV_IA64_IntH9: *out = "IntH9"; return; - case CV_IA64_IntH10: *out = "IntH10"; return; - case CV_IA64_IntH11: *out = "IntH11"; return; - case CV_IA64_IntH12: *out = "IntH12"; return; - case CV_IA64_IntH13: *out = "IntH13"; return; - case CV_IA64_IntH14: *out = "IntH14"; return; - case CV_IA64_IntH15: *out = "IntH15"; return; - - // Special Registers - - case CV_IA64_Ip: *out = "Ip"; return; - case CV_IA64_Umask: *out = "Umask"; return; - case CV_IA64_Cfm: *out = "Cfm"; return; - case CV_IA64_Psr: *out = "Psr"; return; - - // Banked General Registers - - case CV_IA64_Nats: *out = "Nats"; return; - case CV_IA64_Nats2: *out = "Nats2"; return; - case CV_IA64_Nats3: *out = "Nats3"; return; - - // General-Purpose Registers - - // Integer registers - case CV_IA64_IntR0: *out = "IntR0"; return; - case CV_IA64_IntR1: *out = "IntR1"; return; - case CV_IA64_IntR2: *out = "IntR2"; return; - case CV_IA64_IntR3: *out = "IntR3"; return; - case CV_IA64_IntR4: *out = "IntR4"; return; - case CV_IA64_IntR5: *out = "IntR5"; return; - case CV_IA64_IntR6: *out = "IntR6"; return; - case CV_IA64_IntR7: *out = "IntR7"; return; - case CV_IA64_IntR8: *out = "IntR8"; return; - case CV_IA64_IntR9: *out = "IntR9"; return; - case CV_IA64_IntR10: *out = "IntR10"; return; - case CV_IA64_IntR11: *out = "IntR11"; return; - case CV_IA64_IntR12: *out = "IntR12"; return; - case CV_IA64_IntR13: *out = "IntR13"; return; - case CV_IA64_IntR14: *out = "IntR14"; return; - case CV_IA64_IntR15: *out = "IntR15"; return; - case CV_IA64_IntR16: *out = "IntR16"; return; - case CV_IA64_IntR17: *out = "IntR17"; return; - case CV_IA64_IntR18: *out = "IntR18"; return; - case CV_IA64_IntR19: *out = "IntR19"; return; - case CV_IA64_IntR20: *out = "IntR20"; return; - case CV_IA64_IntR21: *out = "IntR21"; return; - case CV_IA64_IntR22: *out = "IntR22"; return; - case CV_IA64_IntR23: *out = "IntR23"; return; - case CV_IA64_IntR24: *out = "IntR24"; return; - case CV_IA64_IntR25: *out = "IntR25"; return; - case CV_IA64_IntR26: *out = "IntR26"; return; - case CV_IA64_IntR27: *out = "IntR27"; return; - case CV_IA64_IntR28: *out = "IntR28"; return; - case CV_IA64_IntR29: *out = "IntR29"; return; - case CV_IA64_IntR30: *out = "IntR30"; return; - case CV_IA64_IntR31: *out = "IntR31"; return; - - // Register Stack - case CV_IA64_IntR32: *out = "IntR32"; return; - case CV_IA64_IntR33: *out = "IntR33"; return; - case CV_IA64_IntR34: *out = "IntR34"; return; - case CV_IA64_IntR35: *out = "IntR35"; return; - case CV_IA64_IntR36: *out = "IntR36"; return; - case CV_IA64_IntR37: *out = "IntR37"; return; - case CV_IA64_IntR38: *out = "IntR38"; return; - case CV_IA64_IntR39: *out = "IntR39"; return; - case CV_IA64_IntR40: *out = "IntR40"; return; - case CV_IA64_IntR41: *out = "IntR41"; return; - case CV_IA64_IntR42: *out = "IntR42"; return; - case CV_IA64_IntR43: *out = "IntR43"; return; - case CV_IA64_IntR44: *out = "IntR44"; return; - case CV_IA64_IntR45: *out = "IntR45"; return; - case CV_IA64_IntR46: *out = "IntR46"; return; - case CV_IA64_IntR47: *out = "IntR47"; return; - case CV_IA64_IntR48: *out = "IntR48"; return; - case CV_IA64_IntR49: *out = "IntR49"; return; - case CV_IA64_IntR50: *out = "IntR50"; return; - case CV_IA64_IntR51: *out = "IntR51"; return; - case CV_IA64_IntR52: *out = "IntR52"; return; - case CV_IA64_IntR53: *out = "IntR53"; return; - case CV_IA64_IntR54: *out = "IntR54"; return; - case CV_IA64_IntR55: *out = "IntR55"; return; - case CV_IA64_IntR56: *out = "IntR56"; return; - case CV_IA64_IntR57: *out = "IntR57"; return; - case CV_IA64_IntR58: *out = "IntR58"; return; - case CV_IA64_IntR59: *out = "IntR59"; return; - case CV_IA64_IntR60: *out = "IntR60"; return; - case CV_IA64_IntR61: *out = "IntR61"; return; - case CV_IA64_IntR62: *out = "IntR62"; return; - case CV_IA64_IntR63: *out = "IntR63"; return; - case CV_IA64_IntR64: *out = "IntR64"; return; - case CV_IA64_IntR65: *out = "IntR65"; return; - case CV_IA64_IntR66: *out = "IntR66"; return; - case CV_IA64_IntR67: *out = "IntR67"; return; - case CV_IA64_IntR68: *out = "IntR68"; return; - case CV_IA64_IntR69: *out = "IntR69"; return; - case CV_IA64_IntR70: *out = "IntR70"; return; - case CV_IA64_IntR71: *out = "IntR71"; return; - case CV_IA64_IntR72: *out = "IntR72"; return; - case CV_IA64_IntR73: *out = "IntR73"; return; - case CV_IA64_IntR74: *out = "IntR74"; return; - case CV_IA64_IntR75: *out = "IntR75"; return; - case CV_IA64_IntR76: *out = "IntR76"; return; - case CV_IA64_IntR77: *out = "IntR77"; return; - case CV_IA64_IntR78: *out = "IntR78"; return; - case CV_IA64_IntR79: *out = "IntR79"; return; - case CV_IA64_IntR80: *out = "IntR80"; return; - case CV_IA64_IntR81: *out = "IntR81"; return; - case CV_IA64_IntR82: *out = "IntR82"; return; - case CV_IA64_IntR83: *out = "IntR83"; return; - case CV_IA64_IntR84: *out = "IntR84"; return; - case CV_IA64_IntR85: *out = "IntR85"; return; - case CV_IA64_IntR86: *out = "IntR86"; return; - case CV_IA64_IntR87: *out = "IntR87"; return; - case CV_IA64_IntR88: *out = "IntR88"; return; - case CV_IA64_IntR89: *out = "IntR89"; return; - case CV_IA64_IntR90: *out = "IntR90"; return; - case CV_IA64_IntR91: *out = "IntR91"; return; - case CV_IA64_IntR92: *out = "IntR92"; return; - case CV_IA64_IntR93: *out = "IntR93"; return; - case CV_IA64_IntR94: *out = "IntR94"; return; - case CV_IA64_IntR95: *out = "IntR95"; return; - case CV_IA64_IntR96: *out = "IntR96"; return; - case CV_IA64_IntR97: *out = "IntR97"; return; - case CV_IA64_IntR98: *out = "IntR98"; return; - case CV_IA64_IntR99: *out = "IntR99"; return; - case CV_IA64_IntR100:*out = "IntR100"; return; - case CV_IA64_IntR101:*out = "IntR101"; return; - case CV_IA64_IntR102:*out = "IntR102"; return; - case CV_IA64_IntR103:*out = "IntR103"; return; - case CV_IA64_IntR104:*out = "IntR104"; return; - case CV_IA64_IntR105:*out = "IntR105"; return; - case CV_IA64_IntR106:*out = "IntR106"; return; - case CV_IA64_IntR107:*out = "IntR107"; return; - case CV_IA64_IntR108:*out = "IntR108"; return; - case CV_IA64_IntR109:*out = "IntR109"; return; - case CV_IA64_IntR110:*out = "IntR110"; return; - case CV_IA64_IntR111:*out = "IntR111"; return; - case CV_IA64_IntR112:*out = "IntR112"; return; - case CV_IA64_IntR113:*out = "IntR113"; return; - case CV_IA64_IntR114:*out = "IntR114"; return; - case CV_IA64_IntR115:*out = "IntR115"; return; - case CV_IA64_IntR116:*out = "IntR116"; return; - case CV_IA64_IntR117:*out = "IntR117"; return; - case CV_IA64_IntR118:*out = "IntR118"; return; - case CV_IA64_IntR119:*out = "IntR119"; return; - case CV_IA64_IntR120:*out = "IntR120"; return; - case CV_IA64_IntR121:*out = "IntR121"; return; - case CV_IA64_IntR122:*out = "IntR122"; return; - case CV_IA64_IntR123:*out = "IntR123"; return; - case CV_IA64_IntR124:*out = "IntR124"; return; - case CV_IA64_IntR125:*out = "IntR125"; return; - case CV_IA64_IntR126:*out = "IntR126"; return; - case CV_IA64_IntR127:*out = "IntR127"; return; - - // Floating-Point Registers - - // Low Floating Point Registers - case CV_IA64_FltF0: *out = "FltF0"; return; - case CV_IA64_FltF1: *out = "FltF1"; return; - case CV_IA64_FltF2: *out = "FltF2"; return; - case CV_IA64_FltF3: *out = "FltF3"; return; - case CV_IA64_FltF4: *out = "FltF4"; return; - case CV_IA64_FltF5: *out = "FltF5"; return; - case CV_IA64_FltF6: *out = "FltF6"; return; - case CV_IA64_FltF7: *out = "FltF7"; return; - case CV_IA64_FltF8: *out = "FltF8"; return; - case CV_IA64_FltF9: *out = "FltF9"; return; - case CV_IA64_FltF10: *out = "FltF10"; return; - case CV_IA64_FltF11: *out = "FltF11"; return; - case CV_IA64_FltF12: *out = "FltF12"; return; - case CV_IA64_FltF13: *out = "FltF13"; return; - case CV_IA64_FltF14: *out = "FltF14"; return; - case CV_IA64_FltF15: *out = "FltF15"; return; - case CV_IA64_FltF16: *out = "FltF16"; return; - case CV_IA64_FltF17: *out = "FltF17"; return; - case CV_IA64_FltF18: *out = "FltF18"; return; - case CV_IA64_FltF19: *out = "FltF19"; return; - case CV_IA64_FltF20: *out = "FltF20"; return; - case CV_IA64_FltF21: *out = "FltF21"; return; - case CV_IA64_FltF22: *out = "FltF22"; return; - case CV_IA64_FltF23: *out = "FltF23"; return; - case CV_IA64_FltF24: *out = "FltF24"; return; - case CV_IA64_FltF25: *out = "FltF25"; return; - case CV_IA64_FltF26: *out = "FltF26"; return; - case CV_IA64_FltF27: *out = "FltF27"; return; - case CV_IA64_FltF28: *out = "FltF28"; return; - case CV_IA64_FltF29: *out = "FltF29"; return; - case CV_IA64_FltF30: *out = "FltF30"; return; - case CV_IA64_FltF31: *out = "FltF31"; return; - - // High Floating Point Registers - case CV_IA64_FltF32: *out = "FltF32"; return; - case CV_IA64_FltF33: *out = "FltF33"; return; - case CV_IA64_FltF34: *out = "FltF34"; return; - case CV_IA64_FltF35: *out = "FltF35"; return; - case CV_IA64_FltF36: *out = "FltF36"; return; - case CV_IA64_FltF37: *out = "FltF37"; return; - case CV_IA64_FltF38: *out = "FltF38"; return; - case CV_IA64_FltF39: *out = "FltF39"; return; - case CV_IA64_FltF40: *out = "FltF40"; return; - case CV_IA64_FltF41: *out = "FltF41"; return; - case CV_IA64_FltF42: *out = "FltF42"; return; - case CV_IA64_FltF43: *out = "FltF43"; return; - case CV_IA64_FltF44: *out = "FltF44"; return; - case CV_IA64_FltF45: *out = "FltF45"; return; - case CV_IA64_FltF46: *out = "FltF46"; return; - case CV_IA64_FltF47: *out = "FltF47"; return; - case CV_IA64_FltF48: *out = "FltF48"; return; - case CV_IA64_FltF49: *out = "FltF49"; return; - case CV_IA64_FltF50: *out = "FltF50"; return; - case CV_IA64_FltF51: *out = "FltF51"; return; - case CV_IA64_FltF52: *out = "FltF52"; return; - case CV_IA64_FltF53: *out = "FltF53"; return; - case CV_IA64_FltF54: *out = "FltF54"; return; - case CV_IA64_FltF55: *out = "FltF55"; return; - case CV_IA64_FltF56: *out = "FltF56"; return; - case CV_IA64_FltF57: *out = "FltF57"; return; - case CV_IA64_FltF58: *out = "FltF58"; return; - case CV_IA64_FltF59: *out = "FltF59"; return; - case CV_IA64_FltF60: *out = "FltF60"; return; - case CV_IA64_FltF61: *out = "FltF61"; return; - case CV_IA64_FltF62: *out = "FltF62"; return; - case CV_IA64_FltF63: *out = "FltF63"; return; - case CV_IA64_FltF64: *out = "FltF64"; return; - case CV_IA64_FltF65: *out = "FltF65"; return; - case CV_IA64_FltF66: *out = "FltF66"; return; - case CV_IA64_FltF67: *out = "FltF67"; return; - case CV_IA64_FltF68: *out = "FltF68"; return; - case CV_IA64_FltF69: *out = "FltF69"; return; - case CV_IA64_FltF70: *out = "FltF70"; return; - case CV_IA64_FltF71: *out = "FltF71"; return; - case CV_IA64_FltF72: *out = "FltF72"; return; - case CV_IA64_FltF73: *out = "FltF73"; return; - case CV_IA64_FltF74: *out = "FltF74"; return; - case CV_IA64_FltF75: *out = "FltF75"; return; - case CV_IA64_FltF76: *out = "FltF76"; return; - case CV_IA64_FltF77: *out = "FltF77"; return; - case CV_IA64_FltF78: *out = "FltF78"; return; - case CV_IA64_FltF79: *out = "FltF79"; return; - case CV_IA64_FltF80: *out = "FltF80"; return; - case CV_IA64_FltF81: *out = "FltF81"; return; - case CV_IA64_FltF82: *out = "FltF82"; return; - case CV_IA64_FltF83: *out = "FltF83"; return; - case CV_IA64_FltF84: *out = "FltF84"; return; - case CV_IA64_FltF85: *out = "FltF85"; return; - case CV_IA64_FltF86: *out = "FltF86"; return; - case CV_IA64_FltF87: *out = "FltF87"; return; - case CV_IA64_FltF88: *out = "FltF88"; return; - case CV_IA64_FltF89: *out = "FltF89"; return; - case CV_IA64_FltF90: *out = "FltF90"; return; - case CV_IA64_FltF91: *out = "FltF91"; return; - case CV_IA64_FltF92: *out = "FltF92"; return; - case CV_IA64_FltF93: *out = "FltF93"; return; - case CV_IA64_FltF94: *out = "FltF94"; return; - case CV_IA64_FltF95: *out = "FltF95"; return; - case CV_IA64_FltF96: *out = "FltF96"; return; - case CV_IA64_FltF97: *out = "FltF97"; return; - case CV_IA64_FltF98: *out = "FltF98"; return; - case CV_IA64_FltF99: *out = "FltF99"; return; - case CV_IA64_FltF100:*out = "FltF100"; return; - case CV_IA64_FltF101:*out = "FltF101"; return; - case CV_IA64_FltF102:*out = "FltF102"; return; - case CV_IA64_FltF103:*out = "FltF103"; return; - case CV_IA64_FltF104:*out = "FltF104"; return; - case CV_IA64_FltF105:*out = "FltF105"; return; - case CV_IA64_FltF106:*out = "FltF106"; return; - case CV_IA64_FltF107:*out = "FltF107"; return; - case CV_IA64_FltF108:*out = "FltF108"; return; - case CV_IA64_FltF109:*out = "FltF109"; return; - case CV_IA64_FltF110:*out = "FltF110"; return; - case CV_IA64_FltF111:*out = "FltF111"; return; - case CV_IA64_FltF112:*out = "FltF112"; return; - case CV_IA64_FltF113:*out = "FltF113"; return; - case CV_IA64_FltF114:*out = "FltF114"; return; - case CV_IA64_FltF115:*out = "FltF115"; return; - case CV_IA64_FltF116:*out = "FltF116"; return; - case CV_IA64_FltF117:*out = "FltF117"; return; - case CV_IA64_FltF118:*out = "FltF118"; return; - case CV_IA64_FltF119:*out = "FltF119"; return; - case CV_IA64_FltF120:*out = "FltF120"; return; - case CV_IA64_FltF121:*out = "FltF121"; return; - case CV_IA64_FltF122:*out = "FltF122"; return; - case CV_IA64_FltF123:*out = "FltF123"; return; - case CV_IA64_FltF124:*out = "FltF124"; return; - case CV_IA64_FltF125:*out = "FltF125"; return; - case CV_IA64_FltF126:*out = "FltF126"; return; - case CV_IA64_FltF127:*out = "FltF127"; return; - - // Application Registers - - case CV_IA64_ApKR0: *out = "ApKR0"; return; - case CV_IA64_ApKR1: *out = "ApKR1"; return; - case CV_IA64_ApKR2: *out = "ApKR2"; return; - case CV_IA64_ApKR3: *out = "ApKR3"; return; - case CV_IA64_ApKR4: *out = "ApKR4"; return; - case CV_IA64_ApKR5: *out = "ApKR5"; return; - case CV_IA64_ApKR6: *out = "ApKR6"; return; - case CV_IA64_ApKR7: *out = "ApKR7"; return; - case CV_IA64_AR8: *out = "AR8"; return; - case CV_IA64_AR9: *out = "AR9"; return; - case CV_IA64_AR10: *out = "AR10"; return; - case CV_IA64_AR11: *out = "AR11"; return; - case CV_IA64_AR12: *out = "AR12"; return; - case CV_IA64_AR13: *out = "AR13"; return; - case CV_IA64_AR14: *out = "AR14"; return; - case CV_IA64_AR15: *out = "AR15"; return; - case CV_IA64_RsRSC: *out = "RsRSC"; return; - case CV_IA64_RsBSP: *out = "RsBSP"; return; - case CV_IA64_RsBSPSTORE:*out = "RsBSPSTORE"; return; - case CV_IA64_RsRNAT: *out = "rsrnat"; return; - case CV_IA64_AR20: *out = "ar20"; return; - case CV_IA64_StFCR: *out = "stfcr"; return; - case CV_IA64_AR22: *out = "ar22"; return; - case CV_IA64_AR23: *out = "ar23"; return; - case CV_IA64_EFLAG: *out = "eflag"; return; - case CV_IA64_CSD: *out = "csd"; return; - case CV_IA64_SSD: *out = "ssd"; return; - case CV_IA64_CFLG: *out = "cflg"; return; - case CV_IA64_StFSR: *out = "stfsr"; return; - case CV_IA64_StFIR: *out = "stfir"; return; - case CV_IA64_StFDR: *out = "stfdr"; return; - case CV_IA64_AR31: *out = "ar31"; return; - case CV_IA64_ApCCV: *out = "apccv"; return; - case CV_IA64_AR33: *out = "ar33"; return; - case CV_IA64_AR34: *out = "ar34"; return; - case CV_IA64_AR35: *out = "ar35"; return; - case CV_IA64_ApUNAT: *out = "apunat"; return; - case CV_IA64_AR37: *out = "ar37"; return; - case CV_IA64_AR38: *out = "ar38"; return; - case CV_IA64_AR39: *out = "ar39"; return; - case CV_IA64_StFPSR: *out = "stfpsr"; return; - case CV_IA64_AR41: *out = "ar41"; return; - case CV_IA64_AR42: *out = "ar42"; return; - case CV_IA64_AR43: *out = "ar43"; return; - case CV_IA64_ApITC: *out = "apitc"; return; - case CV_IA64_AR45: *out = "ar45"; return; - case CV_IA64_AR46: *out = "ar46"; return; - case CV_IA64_AR47: *out = "ar47"; return; - case CV_IA64_AR48: *out = "ar48"; return; - case CV_IA64_AR49: *out = "ar49"; return; - case CV_IA64_AR50: *out = "ar50"; return; - case CV_IA64_AR51: *out = "ar51"; return; - case CV_IA64_AR52: *out = "ar52"; return; - case CV_IA64_AR53: *out = "ar53"; return; - case CV_IA64_AR54: *out = "ar54"; return; - case CV_IA64_AR55: *out = "ar55"; return; - case CV_IA64_AR56: *out = "ar56"; return; - case CV_IA64_AR57: *out = "ar57"; return; - case CV_IA64_AR58: *out = "ar58"; return; - case CV_IA64_AR59: *out = "ar59"; return; - case CV_IA64_AR60: *out = "ar60"; return; - case CV_IA64_AR61: *out = "ar61"; return; - case CV_IA64_AR62: *out = "ar62"; return; - case CV_IA64_AR63: *out = "ar63"; return; - case CV_IA64_RsPFS: *out = "rspfs"; return; - case CV_IA64_ApLC: *out = "aplc"; return; - case CV_IA64_ApEC: *out = "apec"; return; - case CV_IA64_AR67: *out = "ar67"; return; - case CV_IA64_AR68: *out = "ar68"; return; - case CV_IA64_AR69: *out = "ar69"; return; - case CV_IA64_AR70: *out = "ar70"; return; - case CV_IA64_AR71: *out = "ar71"; return; - case CV_IA64_AR72: *out = "ar72"; return; - case CV_IA64_AR73: *out = "ar73"; return; - case CV_IA64_AR74: *out = "ar74"; return; - case CV_IA64_AR75: *out = "ar75"; return; - case CV_IA64_AR76: *out = "ar76"; return; - case CV_IA64_AR77: *out = "ar77"; return; - case CV_IA64_AR78: *out = "ar78"; return; - case CV_IA64_AR79: *out = "ar79"; return; - case CV_IA64_AR80: *out = "ar80"; return; - case CV_IA64_AR81: *out = "ar81"; return; - case CV_IA64_AR82: *out = "ar82"; return; - case CV_IA64_AR83: *out = "ar83"; return; - case CV_IA64_AR84: *out = "ar84"; return; - case CV_IA64_AR85: *out = "ar85"; return; - case CV_IA64_AR86: *out = "ar86"; return; - case CV_IA64_AR87: *out = "ar87"; return; - case CV_IA64_AR88: *out = "ar88"; return; - case CV_IA64_AR89: *out = "ar89"; return; - case CV_IA64_AR90: *out = "ar90"; return; - case CV_IA64_AR91: *out = "ar91"; return; - case CV_IA64_AR92: *out = "ar92"; return; - case CV_IA64_AR93: *out = "ar93"; return; - case CV_IA64_AR94: *out = "ar94"; return; - case CV_IA64_AR95: *out = "ar95"; return; - case CV_IA64_AR96: *out = "ar96"; return; - case CV_IA64_AR97: *out = "ar97"; return; - case CV_IA64_AR98: *out = "ar98"; return; - case CV_IA64_AR99: *out = "ar99"; return; - case CV_IA64_AR100: *out = "ar100"; return; - case CV_IA64_AR101: *out = "ar101"; return; - case CV_IA64_AR102: *out = "ar102"; return; - case CV_IA64_AR103: *out = "ar103"; return; - case CV_IA64_AR104: *out = "ar104"; return; - case CV_IA64_AR105: *out = "ar105"; return; - case CV_IA64_AR106: *out = "ar106"; return; - case CV_IA64_AR107: *out = "ar107"; return; - case CV_IA64_AR108: *out = "ar108"; return; - case CV_IA64_AR109: *out = "ar109"; return; - case CV_IA64_AR110: *out = "ar110"; return; - case CV_IA64_AR111: *out = "ar111"; return; - case CV_IA64_AR112: *out = "ar112"; return; - case CV_IA64_AR113: *out = "ar113"; return; - case CV_IA64_AR114: *out = "ar114"; return; - case CV_IA64_AR115: *out = "ar115"; return; - case CV_IA64_AR116: *out = "ar116"; return; - case CV_IA64_AR117: *out = "ar117"; return; - case CV_IA64_AR118: *out = "ar118"; return; - case CV_IA64_AR119: *out = "ar119"; return; - case CV_IA64_AR120: *out = "ar120"; return; - case CV_IA64_AR121: *out = "ar121"; return; - case CV_IA64_AR122: *out = "ar122"; return; - case CV_IA64_AR123: *out = "ar123"; return; - case CV_IA64_AR124: *out = "ar124"; return; - case CV_IA64_AR125: *out = "ar125"; return; - case CV_IA64_AR126: *out = "ar126"; return; - case CV_IA64_AR127: *out = "ar127"; return; - - // CPUID Registers - - case CV_IA64_CPUID0: *out = "cpuid0"; return; - case CV_IA64_CPUID1: *out = "cpuid1"; return; - case CV_IA64_CPUID2: *out = "cpuid2"; return; - case CV_IA64_CPUID3: *out = "cpuid3"; return; - case CV_IA64_CPUID4: *out = "cpuid4"; return; - - // Control Registers - - case CV_IA64_ApDCR: *out = "apdcr"; return; - case CV_IA64_ApITM: *out = "apitm"; return; - case CV_IA64_ApIVA: *out = "apiva"; return; - case CV_IA64_CR3: *out = "cr3"; return; - case CV_IA64_CR4: *out = "cr4"; return; - case CV_IA64_CR5: *out = "cr5"; return; - case CV_IA64_CR6: *out = "cr6"; return; - case CV_IA64_CR7: *out = "cr7"; return; - case CV_IA64_ApPTA: *out = "appta"; return; - case CV_IA64_ApGPTA: *out = "apgpta"; return; - case CV_IA64_CR10: *out = "cr10"; return; - case CV_IA64_CR11: *out = "cr11"; return; - case CV_IA64_CR12: *out = "cr12"; return; - case CV_IA64_CR13: *out = "cr13"; return; - case CV_IA64_CR14: *out = "cr14"; return; - case CV_IA64_CR15: *out = "cr15"; return; - case CV_IA64_StIPSR: *out = "stipsr"; return; - case CV_IA64_StISR: *out = "stisr"; return; - case CV_IA64_CR18: *out = "cr18"; return; - case CV_IA64_StIIP: *out = "stiip"; return; - case CV_IA64_StIFA: *out = "stifa"; return; - case CV_IA64_StITIR: *out = "stitir"; return; - case CV_IA64_StIIPA: *out = "stiipa"; return; - case CV_IA64_StIFS: *out = "stifs"; return; - case CV_IA64_StIIM: *out = "stiim"; return; - case CV_IA64_StIHA: *out = "stiha"; return; - case CV_IA64_CR26: *out = "cr26"; return; - case CV_IA64_CR27: *out = "cr27"; return; - case CV_IA64_CR28: *out = "cr28"; return; - case CV_IA64_CR29: *out = "cr29"; return; - case CV_IA64_CR30: *out = "cr30"; return; - case CV_IA64_CR31: *out = "cr31"; return; - case CV_IA64_CR32: *out = "cr32"; return; - case CV_IA64_CR33: *out = "cr33"; return; - case CV_IA64_CR34: *out = "cr34"; return; - case CV_IA64_CR35: *out = "cr35"; return; - case CV_IA64_CR36: *out = "cr36"; return; - case CV_IA64_CR37: *out = "cr37"; return; - case CV_IA64_CR38: *out = "cr38"; return; - case CV_IA64_CR39: *out = "cr39"; return; - case CV_IA64_CR40: *out = "cr40"; return; - case CV_IA64_CR41: *out = "cr41"; return; - case CV_IA64_CR42: *out = "cr42"; return; - case CV_IA64_CR43: *out = "cr43"; return; - case CV_IA64_CR44: *out = "cr44"; return; - case CV_IA64_CR45: *out = "cr45"; return; - case CV_IA64_CR46: *out = "cr46"; return; - case CV_IA64_CR47: *out = "cr47"; return; - case CV_IA64_CR48: *out = "cr48"; return; - case CV_IA64_CR49: *out = "cr49"; return; - case CV_IA64_CR50: *out = "cr50"; return; - case CV_IA64_CR51: *out = "cr51"; return; - case CV_IA64_CR52: *out = "cr52"; return; - case CV_IA64_CR53: *out = "cr53"; return; - case CV_IA64_CR54: *out = "cr54"; return; - case CV_IA64_CR55: *out = "cr55"; return; - case CV_IA64_CR56: *out = "cr56"; return; - case CV_IA64_CR57: *out = "cr57"; return; - case CV_IA64_CR58: *out = "cr58"; return; - case CV_IA64_CR59: *out = "cr59"; return; - case CV_IA64_CR60: *out = "cr60"; return; - case CV_IA64_CR61: *out = "cr61"; return; - case CV_IA64_CR62: *out = "cr62"; return; - case CV_IA64_CR63: *out = "cr63"; return; - case CV_IA64_SaLID: *out = "salid"; return; - case CV_IA64_SaIVR: *out = "saivr"; return; - case CV_IA64_SaTPR: *out = "satpr"; return; - case CV_IA64_SaEOI: *out = "saeoi"; return; - case CV_IA64_SaIRR0: *out = "sairr0"; return; - case CV_IA64_SaIRR1: *out = "sairr1"; return; - case CV_IA64_SaIRR2: *out = "sairr2"; return; - case CV_IA64_SaIRR3: *out = "sairr3"; return; - case CV_IA64_SaITV: *out = "saitv"; return; - case CV_IA64_SaPMV: *out = "sapmv"; return; - case CV_IA64_SaCMCV: *out = "sacmcv"; return; - case CV_IA64_CR75: *out = "cr75"; return; - case CV_IA64_CR76: *out = "cr76"; return; - case CV_IA64_CR77: *out = "cr77"; return; - case CV_IA64_CR78: *out = "cr78"; return; - case CV_IA64_CR79: *out = "cr79"; return; - case CV_IA64_SaLRR0: *out = "salrr0"; return; - case CV_IA64_SaLRR1: *out = "salrr1"; return; - case CV_IA64_CR82: *out = "cr82"; return; - case CV_IA64_CR83: *out = "cr83"; return; - case CV_IA64_CR84: *out = "cr84"; return; - case CV_IA64_CR85: *out = "cr85"; return; - case CV_IA64_CR86: *out = "cr86"; return; - case CV_IA64_CR87: *out = "cr87"; return; - case CV_IA64_CR88: *out = "cr88"; return; - case CV_IA64_CR89: *out = "cr89"; return; - case CV_IA64_CR90: *out = "cr90"; return; - case CV_IA64_CR91: *out = "cr91"; return; - case CV_IA64_CR92: *out = "cr92"; return; - case CV_IA64_CR93: *out = "cr93"; return; - case CV_IA64_CR94: *out = "cr94"; return; - case CV_IA64_CR95: *out = "cr95"; return; - case CV_IA64_CR96: *out = "cr96"; return; - case CV_IA64_CR97: *out = "cr97"; return; - case CV_IA64_CR98: *out = "cr98"; return; - case CV_IA64_CR99: *out = "cr99"; return; - case CV_IA64_CR100: *out = "cr100"; return; - case CV_IA64_CR101: *out = "cr101"; return; - case CV_IA64_CR102: *out = "cr102"; return; - case CV_IA64_CR103: *out = "cr103"; return; - case CV_IA64_CR104: *out = "cr104"; return; - case CV_IA64_CR105: *out = "cr105"; return; - case CV_IA64_CR106: *out = "cr106"; return; - case CV_IA64_CR107: *out = "cr107"; return; - case CV_IA64_CR108: *out = "cr108"; return; - case CV_IA64_CR109: *out = "cr109"; return; - case CV_IA64_CR110: *out = "cr110"; return; - case CV_IA64_CR111: *out = "cr111"; return; - case CV_IA64_CR112: *out = "cr112"; return; - case CV_IA64_CR113: *out = "cr113"; return; - case CV_IA64_CR114: *out = "cr114"; return; - case CV_IA64_CR115: *out = "cr115"; return; - case CV_IA64_CR116: *out = "cr116"; return; - case CV_IA64_CR117: *out = "cr117"; return; - case CV_IA64_CR118: *out = "cr118"; return; - case CV_IA64_CR119: *out = "cr119"; return; - case CV_IA64_CR120: *out = "cr120"; return; - case CV_IA64_CR121: *out = "cr121"; return; - case CV_IA64_CR122: *out = "cr122"; return; - case CV_IA64_CR123: *out = "cr123"; return; - case CV_IA64_CR124: *out = "cr124"; return; - case CV_IA64_CR125: *out = "cr125"; return; - case CV_IA64_CR126: *out = "cr126"; return; - case CV_IA64_CR127: *out = "cr127"; return; - - // Protection Key Registers - - case CV_IA64_Pkr0: *out = "pkr0"; return; - case CV_IA64_Pkr1: *out = "pkr1"; return; - case CV_IA64_Pkr2: *out = "pkr2"; return; - case CV_IA64_Pkr3: *out = "pkr3"; return; - case CV_IA64_Pkr4: *out = "pkr4"; return; - case CV_IA64_Pkr5: *out = "pkr5"; return; - case CV_IA64_Pkr6: *out = "pkr6"; return; - case CV_IA64_Pkr7: *out = "pkr7"; return; - case CV_IA64_Pkr8: *out = "pkr8"; return; - case CV_IA64_Pkr9: *out = "pkr9"; return; - case CV_IA64_Pkr10: *out = "pkr10"; return; - case CV_IA64_Pkr11: *out = "pkr11"; return; - case CV_IA64_Pkr12: *out = "pkr12"; return; - case CV_IA64_Pkr13: *out = "pkr13"; return; - case CV_IA64_Pkr14: *out = "pkr14"; return; - case CV_IA64_Pkr15: *out = "pkr15"; return; - - // Region Registers - - case CV_IA64_Rr0: *out = "rr0"; return; - case CV_IA64_Rr1: *out = "rr1"; return; - case CV_IA64_Rr2: *out = "rr2"; return; - case CV_IA64_Rr3: *out = "rr3"; return; - case CV_IA64_Rr4: *out = "rr4"; return; - case CV_IA64_Rr5: *out = "rr5"; return; - case CV_IA64_Rr6: *out = "rr6"; return; - case CV_IA64_Rr7: *out = "rr7"; return; - - // Performance Monitor Data Registers - - case CV_IA64_PFD0: *out = "pfd0"; return; - case CV_IA64_PFD1: *out = "pfd1"; return; - case CV_IA64_PFD2: *out = "pfd2"; return; - case CV_IA64_PFD3: *out = "pfd3"; return; - case CV_IA64_PFD4: *out = "pfd4"; return; - case CV_IA64_PFD5: *out = "pfd5"; return; - case CV_IA64_PFD6: *out = "pfd6"; return; - case CV_IA64_PFD7: *out = "pfd7"; return; - case CV_IA64_PFD8: *out = "pfd8"; return; - case CV_IA64_PFD9: *out = "pfd9"; return; - case CV_IA64_PFD10: *out = "pfd10"; return; - case CV_IA64_PFD11: *out = "pfd11"; return; - case CV_IA64_PFD12: *out = "pfd12"; return; - case CV_IA64_PFD13: *out = "pfd13"; return; - case CV_IA64_PFD14: *out = "pfd14"; return; - case CV_IA64_PFD15: *out = "pfd15"; return; - case CV_IA64_PFD16: *out = "pfd16"; return; - case CV_IA64_PFD17: *out = "pfd17"; return; - - // Performance Monitor Config Registers - - case CV_IA64_PFC0: *out = "pfc0"; return; - case CV_IA64_PFC1: *out = "pfc1"; return; - case CV_IA64_PFC2: *out = "pfc2"; return; - case CV_IA64_PFC3: *out = "pfc3"; return; - case CV_IA64_PFC4: *out = "pfc4"; return; - case CV_IA64_PFC5: *out = "pfc5"; return; - case CV_IA64_PFC6: *out = "pfc6"; return; - case CV_IA64_PFC7: *out = "pfc7"; return; - case CV_IA64_PFC8: *out = "pfc8"; return; - case CV_IA64_PFC9: *out = "pfc9"; return; - case CV_IA64_PFC10: *out = "pfc10"; return; - case CV_IA64_PFC11: *out = "pfc11"; return; - case CV_IA64_PFC12: *out = "pfc12"; return; - case CV_IA64_PFC13: *out = "pfc13"; return; - case CV_IA64_PFC14: *out = "pfc14"; return; - case CV_IA64_PFC15: *out = "pfc15"; return; - - // Instruction Translation Registers - - case CV_IA64_TrI0: *out = "tri0"; return; - case CV_IA64_TrI1: *out = "tri1"; return; - case CV_IA64_TrI2: *out = "tri2"; return; - case CV_IA64_TrI3: *out = "tri3"; return; - case CV_IA64_TrI4: *out = "tri4"; return; - case CV_IA64_TrI5: *out = "tri5"; return; - case CV_IA64_TrI6: *out = "tri6"; return; - case CV_IA64_TrI7: *out = "tri7"; return; - - // Data Translation Registers - - case CV_IA64_TrD0: *out = "trd0"; return; - case CV_IA64_TrD1: *out = "trd1"; return; - case CV_IA64_TrD2: *out = "trd2"; return; - case CV_IA64_TrD3: *out = "trd3"; return; - case CV_IA64_TrD4: *out = "trd4"; return; - case CV_IA64_TrD5: *out = "trd5"; return; - case CV_IA64_TrD6: *out = "trd6"; return; - case CV_IA64_TrD7: *out = "trd7"; return; - - // Instruction Breakpoint Registers - - case CV_IA64_DbI0: *out = "dbi0"; return; - case CV_IA64_DbI1: *out = "dbi1"; return; - case CV_IA64_DbI2: *out = "dbi2"; return; - case CV_IA64_DbI3: *out = "dbi3"; return; - case CV_IA64_DbI4: *out = "dbi4"; return; - case CV_IA64_DbI5: *out = "dbi5"; return; - case CV_IA64_DbI6: *out = "dbi6"; return; - case CV_IA64_DbI7: *out = "dbi7"; return; - - // Data Breakpoint Registers - - case CV_IA64_DbD0: *out = "dbd0"; return; - case CV_IA64_DbD1: *out = "dbd1"; return; - case CV_IA64_DbD2: *out = "dbd2"; return; - case CV_IA64_DbD3: *out = "dbd3"; return; - case CV_IA64_DbD4: *out = "dbd4"; return; - case CV_IA64_DbD5: *out = "dbd5"; return; - case CV_IA64_DbD6: *out = "dbd6"; return; - case CV_IA64_DbD7: *out = "dbd7"; return; - } - break; - - - case CV_CFL_TRICORE: - // - // Register set for the TriCore processor. - // - switch ( reg ) - { - case CV_TRI_NOREG: *out = "noreg"; return; - - // General Purpose Data Registers - - case CV_TRI_D0: *out = "d0"; return; - case CV_TRI_D1: *out = "d1"; return; - case CV_TRI_D2: *out = "d2"; return; - case CV_TRI_D3: *out = "d3"; return; - case CV_TRI_D4: *out = "d4"; return; - case CV_TRI_D5: *out = "d5"; return; - case CV_TRI_D6: *out = "d6"; return; - case CV_TRI_D7: *out = "d7"; return; - case CV_TRI_D8: *out = "d8"; return; - case CV_TRI_D9: *out = "d9"; return; - case CV_TRI_D10: *out = "d10"; return; - case CV_TRI_D11: *out = "d11"; return; - case CV_TRI_D12: *out = "d12"; return; - case CV_TRI_D13: *out = "d13"; return; - case CV_TRI_D14: *out = "d14"; return; - case CV_TRI_D15: *out = "d15"; return; - - // General Purpose Address Registers - - case CV_TRI_A0: *out = "a0"; return; - case CV_TRI_A1: *out = "a1"; return; - case CV_TRI_A2: *out = "a2"; return; - case CV_TRI_A3: *out = "a3"; return; - case CV_TRI_A4: *out = "a4"; return; - case CV_TRI_A5: *out = "a5"; return; - case CV_TRI_A6: *out = "a6"; return; - case CV_TRI_A7: *out = "a7"; return; - case CV_TRI_A8: *out = "a8"; return; - case CV_TRI_A9: *out = "a9"; return; - case CV_TRI_A10: *out = "a10"; return; - case CV_TRI_A11: *out = "a11"; return; - case CV_TRI_A12: *out = "a12"; return; - case CV_TRI_A13: *out = "a13"; return; - case CV_TRI_A14: *out = "a14"; return; - case CV_TRI_A15: *out = "a15"; return; - - // Extended (64-bit) data registers - - case CV_TRI_E0: *out = "e0"; return; - case CV_TRI_E2: *out = "e2"; return; - case CV_TRI_E4: *out = "e4"; return; - case CV_TRI_E6: *out = "e6"; return; - case CV_TRI_E8: *out = "e8"; return; - case CV_TRI_E10: *out = "e10"; return; - case CV_TRI_E12: *out = "e12"; return; - case CV_TRI_E14: *out = "e14"; return; - - // Extended (64-bit) address registers - - case CV_TRI_EA0: *out = "ea0"; return; - case CV_TRI_EA2: *out = "ea2"; return; - case CV_TRI_EA4: *out = "ea4"; return; - case CV_TRI_EA6: *out = "ea6"; return; - case CV_TRI_EA8: *out = "ea8"; return; - case CV_TRI_EA10: *out = "ea10"; return; - case CV_TRI_EA12: *out = "ea12"; return; - case CV_TRI_EA14: *out = "ea14"; return; - - case CV_TRI_PSW: *out = "psw"; return; - case CV_TRI_PCXI: *out = "pcxi"; return; - case CV_TRI_PC: *out = "pc"; return; - case CV_TRI_FCX: *out = "fcx"; return; - case CV_TRI_LCX: *out = "lcx"; return; - case CV_TRI_ISP: *out = "isp"; return; - case CV_TRI_ICR: *out = "icr"; return; - case CV_TRI_BIV: *out = "biv"; return; - case CV_TRI_BTV: *out = "btv"; return; - case CV_TRI_SYSCON: *out = "syscon"; return; - case CV_TRI_DPRx_0: *out = "dprx_0"; return; - case CV_TRI_DPRx_1: *out = "dprx_1"; return; - case CV_TRI_DPRx_2: *out = "dprx_2"; return; - case CV_TRI_DPRx_3: *out = "dprx_3"; return; -// case CV_TRI_CPRx_0: *out = "cprx_0"; return; -// case CV_TRI_CPRx_1: *out = "cprx_1"; return; -// case CV_TRI_CPRx_2: *out = "cprx_2"; return; -// case CV_TRI_CPRx_3: *out = "cprx_3"; return; -// case CV_TRI_DPMx_0: *out = "dpmx_0"; return; -// case CV_TRI_DPMx_1: *out = "dpmx_1"; return; -// case CV_TRI_DPMx_2: *out = "dpmx_2"; return; -// case CV_TRI_DPMx_3: *out = "dpmx_3"; return; -// case CV_TRI_CPMx_0: *out = "cpmx_0"; return; -// case CV_TRI_CPMx_1: *out = "cpmx_1"; return; -// case CV_TRI_CPMx_2: *out = "cpmx_2"; return; -// case CV_TRI_CPMx_3: *out = "cpmx_3"; return; - case CV_TRI_DBGSSR: *out = "dbgssr"; return; - case CV_TRI_EXEVT: *out = "exevt"; return; - case CV_TRI_SWEVT: *out = "swevt"; return; - case CV_TRI_CREVT: *out = "crevt"; return; - case CV_TRI_TRnEVT: *out = "trnevt"; return; - case CV_TRI_MMUCON: *out = "mmucon"; return; - case CV_TRI_ASI: *out = "asi"; return; - case CV_TRI_TVA: *out = "tva"; return; - case CV_TRI_TPA: *out = "tpa"; return; - case CV_TRI_TPX: *out = "tpx"; return; - case CV_TRI_TFA: *out = "tfa"; return; - } - break; - - case CV_CFL_AM33: - // - // Register set for the AM33 and related processors. - // - switch ( reg ) - { - case CV_AM33_NOREG: *out = "noreg"; return; - - // "Extended" (general purpose integer) registers - case CV_AM33_E0: *out = "e0"; return; - case CV_AM33_E1: *out = "e1"; return; - case CV_AM33_E2: *out = "e2"; return; - case CV_AM33_E3: *out = "e3"; return; - case CV_AM33_E4: *out = "e4"; return; - case CV_AM33_E5: *out = "e5"; return; - case CV_AM33_E6: *out = "e6"; return; - case CV_AM33_E7: *out = "e7"; return; - - // Address registers - case CV_AM33_A0: *out = "a0"; return; - case CV_AM33_A1: *out = "a1"; return; - case CV_AM33_A2: *out = "a2"; return; - case CV_AM33_A3: *out = "a3"; return; - - // Integer data registers - case CV_AM33_D0: *out = "d0"; return; - case CV_AM33_D1: *out = "d1"; return; - case CV_AM33_D2: *out = "d2"; return; - case CV_AM33_D3: *out = "d3"; return; - - // (Single-precision) floating-point registers - case CV_AM33_FS0: *out = "fs0"; return; - case CV_AM33_FS1: *out = "fs1"; return; - case CV_AM33_FS2: *out = "fs2"; return; - case CV_AM33_FS3: *out = "fs3"; return; - case CV_AM33_FS4: *out = "fs4"; return; - case CV_AM33_FS5: *out = "fs5"; return; - case CV_AM33_FS6: *out = "fs6"; return; - case CV_AM33_FS7: *out = "fs7"; return; - case CV_AM33_FS8: *out = "fs8"; return; - case CV_AM33_FS9: *out = "fs9"; return; - case CV_AM33_FS10: *out = "fs10"; return; - case CV_AM33_FS11: *out = "fs11"; return; - case CV_AM33_FS12: *out = "fs12"; return; - case CV_AM33_FS13: *out = "fs13"; return; - case CV_AM33_FS14: *out = "fs14"; return; - case CV_AM33_FS15: *out = "fs15"; return; - case CV_AM33_FS16: *out = "fs16"; return; - case CV_AM33_FS17: *out = "fs17"; return; - case CV_AM33_FS18: *out = "fs18"; return; - case CV_AM33_FS19: *out = "fs19"; return; - case CV_AM33_FS20: *out = "fs20"; return; - case CV_AM33_FS21: *out = "fs21"; return; - case CV_AM33_FS22: *out = "fs22"; return; - case CV_AM33_FS23: *out = "fs23"; return; - case CV_AM33_FS24: *out = "fs24"; return; - case CV_AM33_FS25: *out = "fs25"; return; - case CV_AM33_FS26: *out = "fs26"; return; - case CV_AM33_FS27: *out = "fs27"; return; - case CV_AM33_FS28: *out = "fs28"; return; - case CV_AM33_FS29: *out = "fs29"; return; - case CV_AM33_FS30: *out = "fs30"; return; - case CV_AM33_FS31: *out = "fs31"; return; - - // Special purpose registers - - // Stack pointer - case CV_AM33_SP: *out = "sp"; return; - - // Program counter - case CV_AM33_PC: *out = "pc"; return; - - // Multiply-divide/accumulate registers - case CV_AM33_MDR: *out = "mdr"; return; - case CV_AM33_MDRQ: *out = "mdrq"; return; - case CV_AM33_MCRH: *out = "mcrh"; return; - case CV_AM33_MCRL: *out = "mcrl"; return; - case CV_AM33_MCVF: *out = "mcvf"; return; - - // CPU status words - case CV_AM33_EPSW: *out = "epsw"; return; - case CV_AM33_FPCR: *out = "fpcr"; return; - - // Loop buffer registers - case CV_AM33_LIR: *out = "lir"; return; - case CV_AM33_LAR: *out = "lar"; return; - } - break; - - case CV_CFL_M32R: - // - // Register set for the Mitsubishi M32R - // - switch ( reg ) - { - case CV_M32R_NOREG: *out = "noreg"; return; - case CV_M32R_R0: *out = "r0"; return; - case CV_M32R_R1: *out = "r1"; return; - case CV_M32R_R2: *out = "r2"; return; - case CV_M32R_R3: *out = "r3"; return; - case CV_M32R_R4: *out = "r4"; return; - case CV_M32R_R5: *out = "r5"; return; - case CV_M32R_R6: *out = "r6"; return; - case CV_M32R_R7: *out = "r7"; return; - case CV_M32R_R8: *out = "r8"; return; - case CV_M32R_R9: *out = "r9"; return; - case CV_M32R_R10: *out = "r10"; return; - case CV_M32R_R11: *out = "r11"; return; - case CV_M32R_R12: *out = "r12"; return;// Gloabal Pointer, if used - case CV_M32R_R13: *out = "r13"; return;// Frame Pointer, if allocated - case CV_M32R_R14: *out = "r14"; return;// Link Register - case CV_M32R_R15: *out = "r15"; return;// Stack Pointer - case CV_M32R_PSW: *out = "psw"; return;// Preocessor Status Register - case CV_M32R_CBR: *out = "cbr"; return;// Condition Bit Register - case CV_M32R_SPI: *out = "spi"; return;// Interrupt Stack Pointer - case CV_M32R_SPU: *out = "spu"; return;// User Stack Pointer - case CV_M32R_SPO: *out = "spo"; return;// OS Stack Pointer - case CV_M32R_BPC: *out = "bpc"; return;// Backup Program Counter - case CV_M32R_ACHI: *out = "achi"; return;// Accumulator High - case CV_M32R_ACLO: *out = "aclo"; return;// Accumulator Low - case CV_M32R_PC: *out = "pc"; return;// Program Counter - } - break; - - // - // Register set for the SuperH SHMedia processor including compact - // mode - // - case CV_CFL_SHMEDIA: - switch ( reg ) - { - // Integer - 64 bit general registers - case CV_SHMEDIA_NOREG:*out = "noreg"; return; - case CV_SHMEDIA_R0: *out = "r0"; return; - case CV_SHMEDIA_R1: *out = "r1"; return; - case CV_SHMEDIA_R2: *out = "r2"; return; - case CV_SHMEDIA_R3: *out = "r3"; return; - case CV_SHMEDIA_R4: *out = "r4"; return; - case CV_SHMEDIA_R5: *out = "r5"; return; - case CV_SHMEDIA_R6: *out = "r6"; return; - case CV_SHMEDIA_R7: *out = "r7"; return; - case CV_SHMEDIA_R8: *out = "r8"; return; - case CV_SHMEDIA_R9: *out = "r9"; return; - case CV_SHMEDIA_R10: *out = "r10"; return; - case CV_SHMEDIA_R11: *out = "r11"; return; - case CV_SHMEDIA_R12: *out = "r12"; return; - case CV_SHMEDIA_R13: *out = "r13"; return; - case CV_SHMEDIA_R14: *out = "r14"; return; - case CV_SHMEDIA_R15: *out = "r15"; return; - case CV_SHMEDIA_R16: *out = "r16"; return; - case CV_SHMEDIA_R17: *out = "r17"; return; - case CV_SHMEDIA_R18: *out = "r18"; return; - case CV_SHMEDIA_R19: *out = "r19"; return; - case CV_SHMEDIA_R20: *out = "r20"; return; - case CV_SHMEDIA_R21: *out = "r21"; return; - case CV_SHMEDIA_R22: *out = "r22"; return; - case CV_SHMEDIA_R23: *out = "r23"; return; - case CV_SHMEDIA_R24: *out = "r24"; return; - case CV_SHMEDIA_R25: *out = "r25"; return; - case CV_SHMEDIA_R26: *out = "r26"; return; - case CV_SHMEDIA_R27: *out = "r27"; return; - case CV_SHMEDIA_R28: *out = "r28"; return; - case CV_SHMEDIA_R29: *out = "r29"; return; - case CV_SHMEDIA_R30: *out = "r30"; return; - case CV_SHMEDIA_R31: *out = "r31"; return; - case CV_SHMEDIA_R32: *out = "r32"; return; - case CV_SHMEDIA_R33: *out = "r33"; return; - case CV_SHMEDIA_R34: *out = "r34"; return; - case CV_SHMEDIA_R35: *out = "r35"; return; - case CV_SHMEDIA_R36: *out = "r36"; return; - case CV_SHMEDIA_R37: *out = "r37"; return; - case CV_SHMEDIA_R38: *out = "r38"; return; - case CV_SHMEDIA_R39: *out = "r39"; return; - case CV_SHMEDIA_R40: *out = "r40"; return; - case CV_SHMEDIA_R41: *out = "r41"; return; - case CV_SHMEDIA_R42: *out = "r42"; return; - case CV_SHMEDIA_R43: *out = "r43"; return; - case CV_SHMEDIA_R44: *out = "r44"; return; - case CV_SHMEDIA_R45: *out = "r45"; return; - case CV_SHMEDIA_R46: *out = "r46"; return; - case CV_SHMEDIA_R47: *out = "r47"; return; - case CV_SHMEDIA_R48: *out = "r48"; return; - case CV_SHMEDIA_R49: *out = "r49"; return; - case CV_SHMEDIA_R50: *out = "r50"; return; - case CV_SHMEDIA_R51: *out = "r51"; return; - case CV_SHMEDIA_R52: *out = "r52"; return; - case CV_SHMEDIA_R53: *out = "r53"; return; - case CV_SHMEDIA_R54: *out = "r54"; return; - case CV_SHMEDIA_R55: *out = "r55"; return; - case CV_SHMEDIA_R56: *out = "r56"; return; - case CV_SHMEDIA_R57: *out = "r57"; return; - case CV_SHMEDIA_R58: *out = "r58"; return; - case CV_SHMEDIA_R59: *out = "r59"; return; - case CV_SHMEDIA_R60: *out = "r60"; return; - case CV_SHMEDIA_R61: *out = "r61"; return; - case CV_SHMEDIA_R62: *out = "r62"; return; - case CV_SHMEDIA_R63: *out = "r63"; return; - - // Target Registers - 32 bit - case CV_SHMEDIA_TR0: *out = "tr0"; return; - case CV_SHMEDIA_TR1: *out = "tr1"; return; - case CV_SHMEDIA_TR2: *out = "tr2"; return; - case CV_SHMEDIA_TR3: *out = "tr3"; return; - case CV_SHMEDIA_TR4: *out = "tr4"; return; - case CV_SHMEDIA_TR5: *out = "tr5"; return; - case CV_SHMEDIA_TR6: *out = "tr6"; return; - case CV_SHMEDIA_TR7: *out = "tr7"; return; - case CV_SHMEDIA_TR8: *out = "tr8"; return; // future-proof - case CV_SHMEDIA_TR9: *out = "tr9"; return; // future-proof - case CV_SHMEDIA_TR10:*out = "tr10"; return; // future-proof - case CV_SHMEDIA_TR11:*out = "tr11"; return; // future-proof - case CV_SHMEDIA_TR12:*out = "tr12"; return; // future-proof - case CV_SHMEDIA_TR13:*out = "tr13"; return; // future-proof - case CV_SHMEDIA_TR14:*out = "tr14"; return; // future-proof - case CV_SHMEDIA_TR15:*out = "tr15"; return; // future-proof - - // Single - 32 bit fp registers - case CV_SHMEDIA_FR0: *out = "fr0"; return; - case CV_SHMEDIA_FR1: *out = "fr1"; return; - case CV_SHMEDIA_FR2: *out = "fr2"; return; - case CV_SHMEDIA_FR3: *out = "fr3"; return; - case CV_SHMEDIA_FR4: *out = "fr4"; return; - case CV_SHMEDIA_FR5: *out = "fr5"; return; - case CV_SHMEDIA_FR6: *out = "fr6"; return; - case CV_SHMEDIA_FR7: *out = "fr7"; return; - case CV_SHMEDIA_FR8: *out = "fr8"; return; - case CV_SHMEDIA_FR9: *out = "fr9"; return; - case CV_SHMEDIA_FR10:*out = "fr10"; return; - case CV_SHMEDIA_FR11:*out = "fr11"; return; - case CV_SHMEDIA_FR12:*out = "fr12"; return; - case CV_SHMEDIA_FR13:*out = "fr13"; return; - case CV_SHMEDIA_FR14:*out = "fr14"; return; - case CV_SHMEDIA_FR15:*out = "fr15"; return; - case CV_SHMEDIA_FR16:*out = "fr16"; return; - case CV_SHMEDIA_FR17:*out = "fr17"; return; - case CV_SHMEDIA_FR18:*out = "fr18"; return; - case CV_SHMEDIA_FR19:*out = "fr19"; return; - case CV_SHMEDIA_FR20:*out = "fr20"; return; - case CV_SHMEDIA_FR21:*out = "fr21"; return; - case CV_SHMEDIA_FR22:*out = "fr22"; return; - case CV_SHMEDIA_FR23:*out = "fr23"; return; - case CV_SHMEDIA_FR24:*out = "fr24"; return; - case CV_SHMEDIA_FR25:*out = "fr25"; return; - case CV_SHMEDIA_FR26:*out = "fr26"; return; - case CV_SHMEDIA_FR27:*out = "fr27"; return; - case CV_SHMEDIA_FR28:*out = "fr28"; return; - case CV_SHMEDIA_FR29:*out = "fr29"; return; - case CV_SHMEDIA_FR30:*out = "fr30"; return; - case CV_SHMEDIA_FR31:*out = "fr31"; return; - case CV_SHMEDIA_FR32:*out = "fr32"; return; - case CV_SHMEDIA_FR33:*out = "fr33"; return; - case CV_SHMEDIA_FR34:*out = "fr34"; return; - case CV_SHMEDIA_FR35:*out = "fr35"; return; - case CV_SHMEDIA_FR36:*out = "fr36"; return; - case CV_SHMEDIA_FR37:*out = "fr37"; return; - case CV_SHMEDIA_FR38:*out = "fr38"; return; - case CV_SHMEDIA_FR39:*out = "fr39"; return; - case CV_SHMEDIA_FR40:*out = "fr40"; return; - case CV_SHMEDIA_FR41:*out = "fr41"; return; - case CV_SHMEDIA_FR42:*out = "fr42"; return; - case CV_SHMEDIA_FR43:*out = "fr43"; return; - case CV_SHMEDIA_FR44:*out = "fr44"; return; - case CV_SHMEDIA_FR45:*out = "fr45"; return; - case CV_SHMEDIA_FR46:*out = "fr46"; return; - case CV_SHMEDIA_FR47:*out = "fr47"; return; - case CV_SHMEDIA_FR48:*out = "fr48"; return; - case CV_SHMEDIA_FR49:*out = "fr49"; return; - case CV_SHMEDIA_FR50:*out = "fr50"; return; - case CV_SHMEDIA_FR51:*out = "fr51"; return; - case CV_SHMEDIA_FR52:*out = "fr52"; return; - case CV_SHMEDIA_FR53:*out = "fr53"; return; - case CV_SHMEDIA_FR54:*out = "fr54"; return; - case CV_SHMEDIA_FR55:*out = "fr55"; return; - case CV_SHMEDIA_FR56:*out = "fr56"; return; - case CV_SHMEDIA_FR57:*out = "fr57"; return; - case CV_SHMEDIA_FR58:*out = "fr58"; return; - case CV_SHMEDIA_FR59:*out = "fr59"; return; - case CV_SHMEDIA_FR60:*out = "fr60"; return; - case CV_SHMEDIA_FR61:*out = "fr61"; return; - case CV_SHMEDIA_FR62:*out = "fr62"; return; - case CV_SHMEDIA_FR63:*out = "fr63"; return; - - // Double - 64 bit synonyms for 32bit fp register pairs - // subtract 128 to find first base single register - case CV_SHMEDIA_DR0: *out = "dr0"; return; - case CV_SHMEDIA_DR2: *out = "dr2"; return; - case CV_SHMEDIA_DR4: *out = "dr4"; return; - case CV_SHMEDIA_DR6: *out = "dr6"; return; - case CV_SHMEDIA_DR8: *out = "dr8"; return; - case CV_SHMEDIA_DR10:*out = "dr10"; return; - case CV_SHMEDIA_DR12:*out = "dr12"; return; - case CV_SHMEDIA_DR14:*out = "dr14"; return; - case CV_SHMEDIA_DR16:*out = "dr16"; return; - case CV_SHMEDIA_DR18:*out = "dr18"; return; - case CV_SHMEDIA_DR20:*out = "dr20"; return; - case CV_SHMEDIA_DR22:*out = "dr22"; return; - case CV_SHMEDIA_DR24:*out = "dr24"; return; - case CV_SHMEDIA_DR26:*out = "dr26"; return; - case CV_SHMEDIA_DR28:*out = "dr28"; return; - case CV_SHMEDIA_DR30:*out = "dr30"; return; - case CV_SHMEDIA_DR32:*out = "dr32"; return; - case CV_SHMEDIA_DR34:*out = "dr34"; return; - case CV_SHMEDIA_DR36:*out = "dr36"; return; - case CV_SHMEDIA_DR38:*out = "dr38"; return; - case CV_SHMEDIA_DR40:*out = "dr40"; return; - case CV_SHMEDIA_DR42:*out = "dr42"; return; - case CV_SHMEDIA_DR44:*out = "dr44"; return; - case CV_SHMEDIA_DR46:*out = "dr46"; return; - case CV_SHMEDIA_DR48:*out = "dr48"; return; - case CV_SHMEDIA_DR50:*out = "dr50"; return; - case CV_SHMEDIA_DR52:*out = "dr52"; return; - case CV_SHMEDIA_DR54:*out = "dr54"; return; - case CV_SHMEDIA_DR56:*out = "dr56"; return; - case CV_SHMEDIA_DR58:*out = "dr58"; return; - case CV_SHMEDIA_DR60:*out = "dr60"; return; - case CV_SHMEDIA_DR62:*out = "dr62"; return; - - // Vector - 128 bit synonyms for 32bit fp register quads - // subtract 384 to find first base single register - case CV_SHMEDIA_FV0: *out = "fv0"; return; - case CV_SHMEDIA_FV4: *out = "fv4"; return; - case CV_SHMEDIA_FV8: *out = "fv8"; return; - case CV_SHMEDIA_FV12:*out = "fv12"; return; - case CV_SHMEDIA_FV16:*out = "fv16"; return; - case CV_SHMEDIA_FV20:*out = "fv20"; return; - case CV_SHMEDIA_FV24:*out = "fv24"; return; - case CV_SHMEDIA_FV28:*out = "fv28"; return; - case CV_SHMEDIA_FV32:*out = "fv32"; return; - case CV_SHMEDIA_FV36:*out = "fv36"; return; - case CV_SHMEDIA_FV40:*out = "fv40"; return; - case CV_SHMEDIA_FV44:*out = "fv44"; return; - case CV_SHMEDIA_FV48:*out = "fv48"; return; - case CV_SHMEDIA_FV52:*out = "fv52"; return; - case CV_SHMEDIA_FV56:*out = "fv56"; return; - case CV_SHMEDIA_FV60:*out = "fv60"; return; - - // Matrix - 512 bit synonyms for 16 adjacent 32bit fp registers - // subtract 896 to find first base single register - case CV_SHMEDIA_MTRX0: *out = "mtrx0"; return; - case CV_SHMEDIA_MTRX16:*out = "mtrx16"; return; - case CV_SHMEDIA_MTRX32:*out = "mtrx32"; return; - case CV_SHMEDIA_MTRX48:*out = "mtrx48"; return; - - // Control - Implementation defined 64bit control registers - case CV_SHMEDIA_CR0: *out = "cr0"; return; - case CV_SHMEDIA_CR1: *out = "cr1"; return; - case CV_SHMEDIA_CR2: *out = "cr2"; return; - case CV_SHMEDIA_CR3: *out = "cr3"; return; - case CV_SHMEDIA_CR4: *out = "cr4"; return; - case CV_SHMEDIA_CR5: *out = "cr5"; return; - case CV_SHMEDIA_CR6: *out = "cr6"; return; - case CV_SHMEDIA_CR7: *out = "cr7"; return; - case CV_SHMEDIA_CR8: *out = "cr8"; return; - case CV_SHMEDIA_CR9: *out = "cr9"; return; - case CV_SHMEDIA_CR10:*out = "cr10"; return; - case CV_SHMEDIA_CR11:*out = "cr11"; return; - case CV_SHMEDIA_CR12:*out = "cr12"; return; - case CV_SHMEDIA_CR13:*out = "cr13"; return; - case CV_SHMEDIA_CR14:*out = "cr14"; return; - case CV_SHMEDIA_CR15:*out = "cr15"; return; - case CV_SHMEDIA_CR16:*out = "cr16"; return; - case CV_SHMEDIA_CR17:*out = "cr17"; return; - case CV_SHMEDIA_CR18:*out = "cr18"; return; - case CV_SHMEDIA_CR19:*out = "cr19"; return; - case CV_SHMEDIA_CR20:*out = "cr20"; return; - case CV_SHMEDIA_CR21:*out = "cr21"; return; - case CV_SHMEDIA_CR22:*out = "cr22"; return; - case CV_SHMEDIA_CR23:*out = "cr23"; return; - case CV_SHMEDIA_CR24:*out = "cr24"; return; - case CV_SHMEDIA_CR25:*out = "cr25"; return; - case CV_SHMEDIA_CR26:*out = "cr26"; return; - case CV_SHMEDIA_CR27:*out = "cr27"; return; - case CV_SHMEDIA_CR28:*out = "cr28"; return; - case CV_SHMEDIA_CR29:*out = "cr29"; return; - case CV_SHMEDIA_CR30:*out = "cr30"; return; - case CV_SHMEDIA_CR31:*out = "cr31"; return; - case CV_SHMEDIA_CR32:*out = "cr32"; return; - case CV_SHMEDIA_CR33:*out = "cr33"; return; - case CV_SHMEDIA_CR34:*out = "cr34"; return; - case CV_SHMEDIA_CR35:*out = "cr35"; return; - case CV_SHMEDIA_CR36:*out = "cr36"; return; - case CV_SHMEDIA_CR37:*out = "cr37"; return; - case CV_SHMEDIA_CR38:*out = "cr38"; return; - case CV_SHMEDIA_CR39:*out = "cr39"; return; - case CV_SHMEDIA_CR40:*out = "cr40"; return; - case CV_SHMEDIA_CR41:*out = "cr41"; return; - case CV_SHMEDIA_CR42:*out = "cr42"; return; - case CV_SHMEDIA_CR43:*out = "cr43"; return; - case CV_SHMEDIA_CR44:*out = "cr44"; return; - case CV_SHMEDIA_CR45:*out = "cr45"; return; - case CV_SHMEDIA_CR46:*out = "cr46"; return; - case CV_SHMEDIA_CR47:*out = "cr47"; return; - case CV_SHMEDIA_CR48:*out = "cr48"; return; - case CV_SHMEDIA_CR49:*out = "cr49"; return; - case CV_SHMEDIA_CR50:*out = "cr50"; return; - case CV_SHMEDIA_CR51:*out = "cr51"; return; - case CV_SHMEDIA_CR52:*out = "cr52"; return; - case CV_SHMEDIA_CR53:*out = "cr53"; return; - case CV_SHMEDIA_CR54:*out = "cr54"; return; - case CV_SHMEDIA_CR55:*out = "cr55"; return; - case CV_SHMEDIA_CR56:*out = "cr56"; return; - case CV_SHMEDIA_CR57:*out = "cr57"; return; - case CV_SHMEDIA_CR58:*out = "cr58"; return; - case CV_SHMEDIA_CR59:*out = "cr59"; return; - case CV_SHMEDIA_CR60:*out = "cr60"; return; - case CV_SHMEDIA_CR61:*out = "cr61"; return; - case CV_SHMEDIA_CR62:*out = "cr62"; return; - case CV_SHMEDIA_CR63:*out = "cr63"; return; - - case CV_SHMEDIA_FPSCR: *out = "fpscr"; return; - - // Compact mode synonyms -// case CV_SHMEDIA_GBR: *out = "gbr"; return; - case CV_SHMEDIA_MACL: *out = "macl"; return;// synonym for lower 32bits of media R17 - case CV_SHMEDIA_MACH: *out = "mach"; return;// synonym for upper 32bits of media R17 -// case CV_SHMEDIA_PR: *out = "pr"; return; - case CV_SHMEDIA_T: *out = "t"; return;// synonym for lowest bit of media R19 -// case CV_SHMEDIA_FPUL: *out = "fpul"; return; - case CV_SHMEDIA_PC: *out = "pc"; return; -// case CV_SHMEDIA_SR: *out = "sr"; return; - } - break; - - case CV_CFL_AMD64: - // - // AMD64 registers - // - switch ( reg ) - { - case CV_AMD64_AL: *out = "al"; return; - case CV_AMD64_CL: *out = "cl"; return; - case CV_AMD64_DL: *out = "dl"; return; - case CV_AMD64_BL: *out = "bl"; return; - case CV_AMD64_AH: *out = "ah"; return; - case CV_AMD64_CH: *out = "ch"; return; - case CV_AMD64_DH: *out = "dh"; return; - case CV_AMD64_BH: *out = "bh"; return; - case CV_AMD64_AX: *out = "ax"; return; - case CV_AMD64_CX: *out = "cx"; return; - case CV_AMD64_DX: *out = "dx"; return; - case CV_AMD64_BX: *out = "bx"; return; - case CV_AMD64_SP: *out = "sp"; return; - case CV_AMD64_BP: *out = "bp"; return; - case CV_AMD64_SI: *out = "si"; return; - case CV_AMD64_DI: *out = "di"; return; - case CV_AMD64_EAX: *out = "eax"; return; - case CV_AMD64_ECX: *out = "ecx"; return; - case CV_AMD64_EDX: *out = "edx"; return; - case CV_AMD64_EBX: *out = "ebx"; return; - case CV_AMD64_ESP: *out = "esp"; return; - case CV_AMD64_EBP: *out = "ebp"; return; - case CV_AMD64_ESI: *out = "esi"; return; - case CV_AMD64_EDI: *out = "edi"; return; - case CV_AMD64_ES: *out = "es"; return; - case CV_AMD64_CS: *out = "cs"; return; - case CV_AMD64_SS: *out = "ss"; return; - case CV_AMD64_DS: *out = "ds"; return; - case CV_AMD64_FS: *out = "fs"; return; - case CV_AMD64_GS: *out = "gs"; return; - case CV_AMD64_FLAGS: *out = "flags"; return; - case CV_AMD64_RIP: *out = "rip"; return; - case CV_AMD64_EFLAGS: *out = "eflags"; return; - - // Control registers - case CV_AMD64_CR0: *out = "cr0"; return; - case CV_AMD64_CR1: *out = "cr1"; return; - case CV_AMD64_CR2: *out = "cr2"; return; - case CV_AMD64_CR3: *out = "cr3"; return; - case CV_AMD64_CR4: *out = "cr4"; return; - case CV_AMD64_CR8: *out = "cr8"; return; - - // Debug registers - case CV_AMD64_DR0: *out = "dr0"; return; - case CV_AMD64_DR1: *out = "dr1"; return; - case CV_AMD64_DR2: *out = "dr2"; return; - case CV_AMD64_DR3: *out = "dr3"; return; - case CV_AMD64_DR4: *out = "dr4"; return; - case CV_AMD64_DR5: *out = "dr5"; return; - case CV_AMD64_DR6: *out = "dr6"; return; - case CV_AMD64_DR7: *out = "dr7"; return; - case CV_AMD64_DR8: *out = "dr8"; return; - case CV_AMD64_DR9: *out = "dr9"; return; - case CV_AMD64_DR10: *out = "dr10"; return; - case CV_AMD64_DR11: *out = "dr11"; return; - case CV_AMD64_DR12: *out = "dr12"; return; - case CV_AMD64_DR13: *out = "dr13"; return; - case CV_AMD64_DR14: *out = "dr14"; return; - case CV_AMD64_DR15: *out = "dr15"; return; - - case CV_AMD64_GDTR: *out = "gdtr"; return; - case CV_AMD64_GDTL: *out = "gdtl"; return; - case CV_AMD64_IDTR: *out = "idtr"; return; - case CV_AMD64_IDTL: *out = "idtl"; return; - case CV_AMD64_LDTR: *out = "ldtr"; return; - case CV_AMD64_TR: *out = "tr"; return; - - case CV_AMD64_ST0: *out = "st0"; return; - case CV_AMD64_ST1: *out = "st1"; return; - case CV_AMD64_ST2: *out = "st2"; return; - case CV_AMD64_ST3: *out = "st3"; return; - case CV_AMD64_ST4: *out = "st4"; return; - case CV_AMD64_ST5: *out = "st5"; return; - case CV_AMD64_ST6: *out = "st6"; return; - case CV_AMD64_ST7: *out = "st7"; return; - case CV_AMD64_CTRL: *out = "ctrl"; return; - case CV_AMD64_STAT: *out = "stat"; return; - case CV_AMD64_TAG: *out = "tag"; return; - case CV_AMD64_FPIP: *out = "fpip"; return; - case CV_AMD64_FPCS: *out = "fpcs"; return; - case CV_AMD64_FPDO: *out = "fpdo"; return; - case CV_AMD64_FPDS: *out = "fpds"; return; - case CV_AMD64_ISEM: *out = "isem"; return; - case CV_AMD64_FPEIP: *out = "fpeip"; return; - case CV_AMD64_FPEDO: *out = "fpedo"; return; - - case CV_AMD64_MM0: *out = "mm0"; return; - case CV_AMD64_MM1: *out = "mm1"; return; - case CV_AMD64_MM2: *out = "mm2"; return; - case CV_AMD64_MM3: *out = "mm3"; return; - case CV_AMD64_MM4: *out = "mm4"; return; - case CV_AMD64_MM5: *out = "mm5"; return; - case CV_AMD64_MM6: *out = "mm6"; return; - case CV_AMD64_MM7: *out = "mm7"; return; - - case CV_AMD64_XMM0: *out = "xmm0"; return;// KATMAI registers - case CV_AMD64_XMM1: *out = "xmm1"; return; - case CV_AMD64_XMM2: *out = "xmm2"; return; - case CV_AMD64_XMM3: *out = "xmm3"; return; - case CV_AMD64_XMM4: *out = "xmm4"; return; - case CV_AMD64_XMM5: *out = "xmm5"; return; - case CV_AMD64_XMM6: *out = "xmm6"; return; - case CV_AMD64_XMM7: *out = "xmm7"; return; - - case CV_AMD64_XMM0_0: *out = "xmm0_0"; return; // KATMAI sub-registers - case CV_AMD64_XMM0_1: *out = "xmm0_1"; return; - case CV_AMD64_XMM0_2: *out = "xmm0_2"; return; - case CV_AMD64_XMM0_3: *out = "xmm0_3"; return; - case CV_AMD64_XMM1_0: *out = "xmm1_0"; return; - case CV_AMD64_XMM1_1: *out = "xmm1_1"; return; - case CV_AMD64_XMM1_2: *out = "xmm1_2"; return; - case CV_AMD64_XMM1_3: *out = "xmm1_3"; return; - case CV_AMD64_XMM2_0: *out = "xmm2_0"; return; - case CV_AMD64_XMM2_1: *out = "xmm2_1"; return; - case CV_AMD64_XMM2_2: *out = "xmm2_2"; return; - case CV_AMD64_XMM2_3: *out = "xmm2_3"; return; - case CV_AMD64_XMM3_0: *out = "xmm3_0"; return; - case CV_AMD64_XMM3_1: *out = "xmm3_1"; return; - case CV_AMD64_XMM3_2: *out = "xmm3_2"; return; - case CV_AMD64_XMM3_3: *out = "xmm3_3"; return; - case CV_AMD64_XMM4_0: *out = "xmm4_0"; return; - case CV_AMD64_XMM4_1: *out = "xmm4_1"; return; - case CV_AMD64_XMM4_2: *out = "xmm4_2"; return; - case CV_AMD64_XMM4_3: *out = "xmm4_3"; return; - case CV_AMD64_XMM5_0: *out = "xmm5_0"; return; - case CV_AMD64_XMM5_1: *out = "xmm5_1"; return; - case CV_AMD64_XMM5_2: *out = "xmm5_2"; return; - case CV_AMD64_XMM5_3: *out = "xmm5_3"; return; - case CV_AMD64_XMM6_0: *out = "xmm6_0"; return; - case CV_AMD64_XMM6_1: *out = "xmm6_1"; return; - case CV_AMD64_XMM6_2: *out = "xmm6_2"; return; - case CV_AMD64_XMM6_3: *out = "xmm6_3"; return; - case CV_AMD64_XMM7_0: *out = "xmm7_0"; return; - case CV_AMD64_XMM7_1: *out = "xmm7_1"; return; - case CV_AMD64_XMM7_2: *out = "xmm7_2"; return; - case CV_AMD64_XMM7_3: *out = "xmm7_3"; return; - - case CV_AMD64_XMM0L: *out = "xmm0l"; return; - case CV_AMD64_XMM1L: *out = "xmm1l"; return; - case CV_AMD64_XMM2L: *out = "xmm2l"; return; - case CV_AMD64_XMM3L: *out = "xmm3l"; return; - case CV_AMD64_XMM4L: *out = "xmm4l"; return; - case CV_AMD64_XMM5L: *out = "xmm5l"; return; - case CV_AMD64_XMM6L: *out = "xmm6l"; return; - case CV_AMD64_XMM7L: *out = "xmm7l"; return; - - case CV_AMD64_XMM0H: *out = "xmm0h"; return; - case CV_AMD64_XMM1H: *out = "xmm1h"; return; - case CV_AMD64_XMM2H: *out = "xmm2h"; return; - case CV_AMD64_XMM3H: *out = "xmm3h"; return; - case CV_AMD64_XMM4H: *out = "xmm4h"; return; - case CV_AMD64_XMM5H: *out = "xmm5h"; return; - case CV_AMD64_XMM6H: *out = "xmm6h"; return; - case CV_AMD64_XMM7H: *out = "xmm7h"; return; - - case CV_AMD64_MXCSR: *out = "mxcsr"; return; // XMM status register - - case CV_AMD64_EMM0L: *out = "emm0l"; return; // XMM sub-registers (WNI integer) - case CV_AMD64_EMM1L: *out = "emm1l"; return; - case CV_AMD64_EMM2L: *out = "emm2l"; return; - case CV_AMD64_EMM3L: *out = "emm3l"; return; - case CV_AMD64_EMM4L: *out = "emm4l"; return; - case CV_AMD64_EMM5L: *out = "emm5l"; return; - case CV_AMD64_EMM6L: *out = "emm6l"; return; - case CV_AMD64_EMM7L: *out = "emm7l"; return; - - case CV_AMD64_EMM0H: *out = "emm0h"; return; - case CV_AMD64_EMM1H: *out = "emm1h"; return; - case CV_AMD64_EMM2H: *out = "emm2h"; return; - case CV_AMD64_EMM3H: *out = "emm3h"; return; - case CV_AMD64_EMM4H: *out = "emm4h"; return; - case CV_AMD64_EMM5H: *out = "emm5h"; return; - case CV_AMD64_EMM6H: *out = "emm6h"; return; - case CV_AMD64_EMM7H: *out = "emm7h"; return; - - // do not change the order of these regs, first one must be even too - case CV_AMD64_MM00: *out = "mm00"; return; - case CV_AMD64_MM01: *out = "mm01"; return; - case CV_AMD64_MM10: *out = "mm10"; return; - case CV_AMD64_MM11: *out = "mm11"; return; - case CV_AMD64_MM20: *out = "mm20"; return; - case CV_AMD64_MM21: *out = "mm21"; return; - case CV_AMD64_MM30: *out = "mm30"; return; - case CV_AMD64_MM31: *out = "mm31"; return; - case CV_AMD64_MM40: *out = "mm40"; return; - case CV_AMD64_MM41: *out = "mm41"; return; - case CV_AMD64_MM50: *out = "mm50"; return; - case CV_AMD64_MM51: *out = "mm51"; return; - case CV_AMD64_MM60: *out = "mm60"; return; - case CV_AMD64_MM61: *out = "mm61"; return; - case CV_AMD64_MM70: *out = "mm70"; return; - case CV_AMD64_MM71: *out = "mm71"; return; - - // Extended KATMAI registers - case CV_AMD64_XMM8: *out = "xmm8"; return;// KATMAI registers - case CV_AMD64_XMM9: *out = "xmm9"; return; - case CV_AMD64_XMM10: *out = "xmm10"; return; - case CV_AMD64_XMM11: *out = "xmm11"; return; - case CV_AMD64_XMM12: *out = "xmm12"; return; - case CV_AMD64_XMM13: *out = "xmm13"; return; - case CV_AMD64_XMM14: *out = "xmm14"; return; - case CV_AMD64_XMM15: *out = "xmm15"; return; - - case CV_AMD64_XMM8_0: *out = "xmm8_0"; return; // KATMAI sub-registers - case CV_AMD64_XMM8_1: *out = "xmm8_1"; return; - case CV_AMD64_XMM8_2: *out = "xmm8_2"; return; - case CV_AMD64_XMM8_3: *out = "xmm8_3"; return; - case CV_AMD64_XMM9_0: *out = "xmm9_0"; return; - case CV_AMD64_XMM9_1: *out = "xmm9_1"; return; - case CV_AMD64_XMM9_2: *out = "xmm9_2"; return; - case CV_AMD64_XMM9_3: *out = "xmm9_3"; return; - case CV_AMD64_XMM10_0:*out = "xmm10_0"; return; - case CV_AMD64_XMM10_1:*out = "xmm10_1"; return; - case CV_AMD64_XMM10_2:*out = "xmm10_2"; return; - case CV_AMD64_XMM10_3:*out = "xmm10_3"; return; - case CV_AMD64_XMM11_0:*out = "xmm11_0"; return; - case CV_AMD64_XMM11_1:*out = "xmm11_1"; return; - case CV_AMD64_XMM11_2:*out = "xmm11_2"; return; - case CV_AMD64_XMM11_3:*out = "xmm11_3"; return; - case CV_AMD64_XMM12_0:*out = "xmm12_0"; return; - case CV_AMD64_XMM12_1:*out = "xmm12_1"; return; - case CV_AMD64_XMM12_2:*out = "xmm12_2"; return; - case CV_AMD64_XMM12_3:*out = "xmm12_3"; return; - case CV_AMD64_XMM13_0:*out = "xmm13_0"; return; - case CV_AMD64_XMM13_1:*out = "xmm13_1"; return; - case CV_AMD64_XMM13_2:*out = "xmm13_2"; return; - case CV_AMD64_XMM13_3:*out = "xmm13_3"; return; - case CV_AMD64_XMM14_0:*out = "xmm14_0"; return; - case CV_AMD64_XMM14_1:*out = "xmm14_1"; return; - case CV_AMD64_XMM14_2:*out = "xmm14_2"; return; - case CV_AMD64_XMM14_3:*out = "xmm14_3"; return; - case CV_AMD64_XMM15_0:*out = "xmm15_0"; return; - case CV_AMD64_XMM15_1:*out = "xmm15_1"; return; - case CV_AMD64_XMM15_2:*out = "xmm15_2"; return; - case CV_AMD64_XMM15_3:*out = "xmm15_3"; return; - - case CV_AMD64_XMM8L: *out = "xmm8l"; return; - case CV_AMD64_XMM9L: *out = "xmm9l"; return; - case CV_AMD64_XMM10L: *out = "xmm10l"; return; - case CV_AMD64_XMM11L: *out = "xmm11l"; return; - case CV_AMD64_XMM12L: *out = "xmm12l"; return; - case CV_AMD64_XMM13L: *out = "xmm13l"; return; - case CV_AMD64_XMM14L: *out = "xmm14l"; return; - case CV_AMD64_XMM15L: *out = "xmm15l"; return; - - case CV_AMD64_XMM8H: *out = "xmm8h"; return; - case CV_AMD64_XMM9H: *out = "xmm9h"; return; - case CV_AMD64_XMM10H: *out = "xmm10h"; return; - case CV_AMD64_XMM11H: *out = "xmm11h"; return; - case CV_AMD64_XMM12H: *out = "xmm12h"; return; - case CV_AMD64_XMM13H: *out = "xmm13h"; return; - case CV_AMD64_XMM14H: *out = "xmm14h"; return; - case CV_AMD64_XMM15H: *out = "xmm15h"; return; - - case CV_AMD64_EMM8L: *out = "emm8l"; return; // XMM sub-registers (WNI integer) - case CV_AMD64_EMM9L: *out = "emm9l"; return; - case CV_AMD64_EMM10L: *out = "emm10l"; return; - case CV_AMD64_EMM11L: *out = "emm11l"; return; - case CV_AMD64_EMM12L: *out = "emm12l"; return; - case CV_AMD64_EMM13L: *out = "emm13l"; return; - case CV_AMD64_EMM14L: *out = "emm14l"; return; - case CV_AMD64_EMM15L: *out = "emm15l"; return; - - case CV_AMD64_EMM8H: *out = "emm8h"; return; - case CV_AMD64_EMM9H: *out = "emm9h"; return; - case CV_AMD64_EMM10H: *out = "emm10h"; return; - case CV_AMD64_EMM11H: *out = "emm11h"; return; - case CV_AMD64_EMM12H: *out = "emm12h"; return; - case CV_AMD64_EMM13H: *out = "emm13h"; return; - case CV_AMD64_EMM14H: *out = "emm14h"; return; - case CV_AMD64_EMM15H: *out = "emm15h"; return; - - // Low byte forms of some standard registers - case CV_AMD64_SIL: *out = "sil"; return; - case CV_AMD64_DIL: *out = "dil"; return; - case CV_AMD64_BPL: *out = "bpl"; return; - case CV_AMD64_SPL: *out = "spl"; return; - - // 64-bit regular registers - case CV_AMD64_RAX: *out = "rax"; return; - case CV_AMD64_RBX: *out = "rbx"; return; - case CV_AMD64_RCX: *out = "rcx"; return; - case CV_AMD64_RDX: *out = "rdx"; return; - case CV_AMD64_RSI: *out = "rsi"; return; - case CV_AMD64_RDI: *out = "rdi"; return; - case CV_AMD64_RBP: *out = "rbp"; return; - case CV_AMD64_RSP: *out = "rsp"; return; - - // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D) - case CV_AMD64_R8: *out = "r8"; return; - case CV_AMD64_R9: *out = "r9"; return; - case CV_AMD64_R10: *out = "r10"; return; - case CV_AMD64_R11: *out = "r11"; return; - case CV_AMD64_R12: *out = "r12"; return; - case CV_AMD64_R13: *out = "r13"; return; - case CV_AMD64_R14: *out = "r14"; return; - case CV_AMD64_R15: *out = "r15"; return; - - case CV_AMD64_R8B: *out = "r8b"; return; - case CV_AMD64_R9B: *out = "r9b"; return; - case CV_AMD64_R10B: *out = "r10b"; return; - case CV_AMD64_R11B: *out = "r11b"; return; - case CV_AMD64_R12B: *out = "r12b"; return; - case CV_AMD64_R13B: *out = "r13b"; return; - case CV_AMD64_R14B: *out = "r14b"; return; - case CV_AMD64_R15B: *out = "r15b"; return; - - case CV_AMD64_R8W: *out = "r8w"; return; - case CV_AMD64_R9W: *out = "r9w"; return; - case CV_AMD64_R10W: *out = "r10w"; return; - case CV_AMD64_R11W: *out = "r11w"; return; - case CV_AMD64_R12W: *out = "r12w"; return; - case CV_AMD64_R13W: *out = "r13w"; return; - case CV_AMD64_R14W: *out = "r14w"; return; - case CV_AMD64_R15W: *out = "r15w"; return; - - case CV_AMD64_R8D: *out = "r8d"; return; - case CV_AMD64_R9D: *out = "r9d"; return; - case CV_AMD64_R10D: *out = "r10d"; return; - case CV_AMD64_R11D: *out = "r11d"; return; - case CV_AMD64_R12D: *out = "r12d"; return; - case CV_AMD64_R13D: *out = "r13d"; return; - case CV_AMD64_R14D: *out = "r14d"; return; - case CV_AMD64_R15D: *out = "r15d"; return; - } - - default: - break; - } - out->sprnt("reg %d", reg); -} diff --git a/idasdk75/plugins/pdb/makefile b/idasdk75/plugins/pdb/makefile deleted file mode 100644 index 8e67a55..0000000 --- a/idasdk75/plugins/pdb/makefile +++ /dev/null @@ -1,31 +0,0 @@ -PROC=pdb -CONFIGS=pdb.cfg - -ifdef __NT__ - O1=old - STDLIBS += ole32.lib - STDLIBS += oleaut32.lib -else - LIBS += $(L)network$(A) -endif - -include ../plugin.mak - -$(F)pdb$(O): CC_WNO-$(call gte,$(GCC_VERSION),6.1) += -Wno-null-dereference - -# MAKEDEP dependency list ------------------ -$(F)pdb$(O) : $(I)allins.hpp $(I)auto.hpp $(I)bitrange.hpp \ - $(I)bytes.hpp $(I)config.hpp $(I)dbg.hpp \ - $(I)demangle.hpp $(I)diskio.hpp $(I)err.h $(I)fpro.h \ - $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ - $(I)idp.hpp $(I)intel.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)md5.h $(I)nalt.hpp \ - $(I)name.hpp $(I)netnode.hpp $(I)network.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)struct.hpp \ - $(I)typeinf.hpp $(I)ua.hpp $(I)workarounds.hpp \ - $(I)xref.hpp ../../dbg/win32/win32_rpc.h \ - ../../ldr/pe/cor.h ../../ldr/pe/corhdr.h \ - ../../ldr/pe/mycor.h ../../ldr/pe/pe.h common.cpp \ - cvconst.h dia2.h misc.cpp oldpdb.h pdb.cpp pdb.hpp \ - pdbaccess.hpp pdbremote.cpp pdbremote.hpp sip.cpp \ - sip.hpp tilbuild.cpp tilbuild.hpp varser.hpp diff --git a/idasdk75/plugins/pdb/msdia.cpp b/idasdk75/plugins/pdb/msdia.cpp deleted file mode 100644 index 504a8d6..0000000 --- a/idasdk75/plugins/pdb/msdia.cpp +++ /dev/null @@ -1,1150 +0,0 @@ - -// This file is included from 4 places: -// - efd/pdb.cpp efd: to dump pdb contents -// - base/pdb2til.cpp tilib: to convert pdb to til -// - plugins/pdb/pdb.cpp ida: read pdb info and populate idb -// - dbg/win32_server/tilfuncs.cpp win32_server: read pdb info and send it to ida -// -// The following symbols may be defined: -// PDB_PLUGIN pdb -// PDB_WIN32_SERVER win32_server - -#include <diskio.hpp> - -#include "msdia.hpp" - -#include "../../ldr/pe/pe.h" -#include "pdblocal.cpp" - -//lint -esym(843, g_diadlls, g_pdb_errors, PathIsUNC) could be declared as const - -int pdb_session_t::session_count = 0; -bool pdb_session_t::co_initialized = false; - -typedef BOOL (__stdcall *PathIsUNC_t)(LPCTSTR pszPath); -static PathIsUNC_t PathIsUNC = NULL; - -static bool check_for_odd_paths(const char *fname); - -//--------------------------------------------------------------------------- -class msdia_reader_t -{ -public: - DEFINE_VIRTUAL_DTOR(msdia_reader_t); - virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) = 0; - virtual bool setup(void) { return true; } -}; - -//--------------------------------------------------------------------------- -class local_exe_msdia_reader_t : public msdia_reader_t -{ - LPCWSTR FileName; - HANDLE hFile; - -public: - local_exe_msdia_reader_t(LPCWSTR _FileName) - { - FileName = _FileName; - hFile = INVALID_HANDLE_VALUE; - } - - ~local_exe_msdia_reader_t(void) - { - if ( hFile != INVALID_HANDLE_VALUE ) - CloseHandle(hFile); - } - - virtual bool setup(void) override - { - hFile = CreateFileW( - FileName, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - 0, - NULL); - return hFile != INVALID_HANDLE_VALUE; - } - - virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) override - { - if ( hFile == INVALID_HANDLE_VALUE ) - return false; - - LARGE_INTEGER pos; - pos.QuadPart = (LONGLONG) offset; - if ( SetFilePointerEx(hFile, pos, NULL, FILE_BEGIN) == 0 ) - return false; - - if ( ReadFile(hFile, buf, count, (DWORD *) nread, NULL) == 0 ) - return false; - - return true; - } -}; - -#ifdef PDB_PLUGIN -//--------------------------------------------------------------------------- -class local_mem_msdia_reader_t : public msdia_reader_t -{ -public: - virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) override - { - if ( get_bytes(buf, count, offset) != count ) - return false; - *nread = count; - return true; - } -}; - -#elif defined(PDB_WIN32_SERVER) -//--------------------------------------------------------------------------- -class win32_msdia_reader_t : public msdia_reader_t -{ - pdb_remote_session_t *pdb_rsess; - pdb_rr_kind_t kind; -public: - win32_msdia_reader_t(void *_pdb_rsess, pdb_rr_kind_t _kind) - { - pdb_rsess = (pdb_remote_session_t *) _pdb_rsess; - kind = _kind; - } - - virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) override - { - return pdb_rsess->client_read_request.request_read(kind, offset, count, buf, nread); - } -}; - -#endif - -//---------------------------------------------------------------------- -// Common code for PDB handling -//---------------------------------------------------------------------- -class CCallback : public IDiaLoadCallback2, - public IDiaReadExeAtRVACallback, - public IDiaReadExeAtOffsetCallback -{ - unsigned int m_nRefCount; - ea_t m_load_address; - msdia_reader_t *msdia_reader; - pdb_session_t *pdb_session; - DWORDLONG last_cv_off; - ea_t last_cv_rva; -public: - CCallback(pdb_session_t *_pdb_session, - msdia_reader_t *_msdia_reader, - ea_t _load_address) - : msdia_reader(_msdia_reader), - m_load_address(_load_address), - // Note: we initialize the reference count to 1 since the only - // instance of this object is created in the stack, and - // the destructor will take care of the cleanup. - m_nRefCount(1), - pdb_session(_pdb_session), - last_cv_off(0), - last_cv_rva(BADADDR) - { - } - - // IUnknown - ULONG STDMETHODCALLTYPE AddRef() - { - return InterlockedIncrement(&m_nRefCount); - } - - ULONG STDMETHODCALLTYPE Release() - { - // Note: we don't check the reference count and delete the object - // (see comment for the m_nRefCount field). - return InterlockedDecrement(&m_nRefCount); - } - - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID rid, void **ppUnk) - { - if ( ppUnk == NULL ) - return E_INVALIDARG; - - *ppUnk = NULL; - if ( rid == __uuidof(IDiaLoadCallback2) || rid == __uuidof(IDiaLoadCallback) ) - { - *ppUnk = (IDiaLoadCallback2 *)this; - } - else if ( rid == __uuidof(IDiaReadExeAtRVACallback) ) - { - // we may use only one of IDiaReadExeAtRVACallback and IDiaReadExeAtOffsetCallback - // claiming that both are supported will lead to crashes in MSDIA - if ( m_load_address != BADADDR ) - *ppUnk = (IDiaReadExeAtRVACallback *)this; - } - else if ( rid == __uuidof(IDiaReadExeAtOffsetCallback) ) - { - // see the comment above about IDiaReadExeAtRVACallback - if ( m_load_address == BADADDR ) - *ppUnk = (IDiaReadExeAtOffsetCallback *)this; - } - else if ( rid == __uuidof(IUnknown) ) - { - *ppUnk = (IUnknown *)(IDiaLoadCallback *)this; - } - if ( *ppUnk == NULL ) - return E_NOINTERFACE; - AddRef(); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE NotifyDebugDir( - BOOL fExecutable, - DWORD cbData, - BYTE data[]) - { - // msdia90.dll can crash on bogus CV data - // so we remember the offset here and check it in ReadFileAt - if ( fExecutable && cbData >= sizeof(debug_entry_t) ) - { - debug_entry_t &de = *(debug_entry_t *)data; - if ( de.type == DBG_CV ) - { - last_cv_off = de.seek; - last_cv_rva = de.rva; - } - } - return S_OK; - } - HRESULT STDMETHODCALLTYPE NotifyOpenDBG( - LPCOLESTR dbgPath, - HRESULT resultCode) - { - if ( resultCode == S_OK ) - deb(IDA_DEBUG_DEBUGGER, "MSDIA: dbg file \"%S\" matched\n", dbgPath); - else - deb(IDA_DEBUG_DEBUGGER, "MSDIA: \"%S\": %s\n", dbgPath, pdberr(resultCode)); - - return S_OK; - } - - HRESULT STDMETHODCALLTYPE NotifyOpenPDB( - LPCOLESTR pdbPath, - HRESULT resultCode) - { - if ( resultCode == S_OK ) - deb(IDA_DEBUG_DEBUGGER, "MSDIA: pdb file \"%S\" matched\n", pdbPath); - else - deb(IDA_DEBUG_DEBUGGER, "MSDIA: \"%S\": %s\n", pdbPath, pdberr(resultCode)); -#ifdef _DEBUG - qstring spath; - utf16_utf8(&spath, pdbPath); - pdb_session->_pdb_path = spath; -#endif - return S_OK; - } - HRESULT STDMETHODCALLTYPE RestrictRegistryAccess() - { - // return hr != S_OK to prevent querying the registry for symbol search paths - return S_OK; - } - HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess() - { - // return hr != S_OK to prevent accessing a symbol server - return S_OK; - } - HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess() - { - // return hr != S_OK to prevent querying the registry for symbol search paths - return S_OK; - } - HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess() - { - // return hr != S_OK to prevent accessing a symbol server - return S_OK; - } - HRESULT STDMETHODCALLTYPE RestrictDBGAccess() - { - return S_OK; - } - HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess() - { - return S_OK; - } - - bool check_codeview_data(BYTE pbData[], DWORD cbData) - { - bool ok = true; - if ( cbData > 4 ) - { - // check that the data has a valid NB or RSDS signature and PDB path doesn't look suspicious - ok = false; - if ( pbData[0] == 'N' && pbData[1] == 'B' && cbData >= sizeof(cv_info_pdb20_t) ) - { - char *pdbname = (char*)pbData + sizeof(cv_info_pdb20_t); - pbData[cbData-1] = '\0'; - ok = check_for_odd_paths(pdbname); - } - else if ( memcmp(pbData, "RSDS", 4) == 0 && cbData >= sizeof(rsds_t) ) - { - char *pdbname = (char*)pbData + sizeof(rsds_t); - pbData[cbData-1] = '\0'; - ok = check_for_odd_paths(pdbname); - } - } - return ok; - } - - // IDiaReadExeAtRVACallback - HRESULT STDMETHODCALLTYPE ReadExecutableAtRVA( - DWORD relativeVirtualAddress, - DWORD cbData, - DWORD *pcbData, - BYTE data[]) - { - ea_t ea = m_load_address + relativeVirtualAddress; - if ( !msdia_reader->read(ea, data, cbData, (uint32 *) pcbData) ) - return E_FAIL; - // are we reading the CV debug directory entry? - if ( relativeVirtualAddress == last_cv_rva ) - return check_codeview_data(data, cbData) ? S_OK : E_FAIL; - return S_OK; - } - - // IDiaReadExeAtOffsetCallback - HRESULT STDMETHODCALLTYPE ReadExecutableAt( - DWORDLONG fileOffset, - DWORD cbData, - DWORD *pcbData, - BYTE data[]) - { - if ( !msdia_reader->read(fileOffset, data, cbData, (uint32 *) pcbData) ) - return E_FAIL; - // are we reading the CV debug directory entry? - if ( fileOffset != 0 && last_cv_off == fileOffset ) - return check_codeview_data(data, cbData) ? S_OK : E_FAIL; - return S_OK; - } -}; - -//--------------------------------------------------------------------------- -template<class T> void print_generic(T t) -{ - IDiaPropertyStorage *pPropertyStorage; - HRESULT hr = t->QueryInterface(__uuidof(IDiaPropertyStorage), (void **)&pPropertyStorage); - if ( hr == S_OK ) - { - print_property_storage(pPropertyStorage); - pPropertyStorage->Release(); - } -} - -//--------------------------------------------------------------------------- -static const char *const g_pdb_errors[] = -{ - "Operation successful (E_PDB_OK)", - "(E_PDB_USAGE)", - "Out of memory (E_PDB_OUT_OF_MEMORY)", - "(E_PDB_FILE_SYSTEM)", - "Failed to open the file, or the file has an invalid format (E_PDB_NOT_FOUND)", - "Signature does not match (E_PDB_INVALID_SIG)", - "Age does not match (E_PDB_INVALID_AGE)", - "(E_PDB_PRECOMP_REQUIRED)", - "(E_PDB_OUT_OF_TI)", - "(E_PDB_NOT_IMPLEMENTED)", - "(E_PDB_V1_PDB)", - "Attempted to access a file with an obsolete format (E_PDB_FORMAT)", - "(E_PDB_LIMIT)", - "(E_PDB_CORRUPT)", - "(E_PDB_TI16)", - "(E_PDB_ACCESS_DENIED)", - "(E_PDB_ILLEGAL_TYPE_EDIT)", - "(E_PDB_INVALID_EXECUTABLE)", - "(E_PDB_DBG_NOT_FOUND)", - "(E_PDB_NO_DEBUG_INFO)", - "(E_PDB_INVALID_EXE_TIMESTAMP)", - "(E_PDB_RESERVED)", - "(E_PDB_DEBUG_INFO_NOT_IN_PDB)", - "(E_PDB_SYMSRV_BAD_CACHE_PATH)", - "(E_PDB_SYMSRV_CACHE_FULL)", -}; - -//--------------------------------------------------------------------------- -inline void pdberr_suggest_vs_runtime(HRESULT hr) -{ - if ( hr == E_NOINTERFACE ) - { - msg("<< It appears that MS DIA SDK is not installed.\n"); -#ifdef __X86__ - msg("Please try installing \"Microsoft Visual C++ 2008 Redistributable Package / x86\" >>\n"); -#else - msg("Please try installing \"Microsoft Visual C++ 2008 Redistributable Package / x64\" >>\n"); -#endif - } -} - -//--------------------------------------------------------------------------- -const char *pdberr(int code) -{ - switch ( code ) - { // tab in first pos is flag for replace warning to msg - case E_INVALIDARG: return "Invalid parameter."; - case E_UNEXPECTED: return "Data source has already been prepared."; - default: - if ( code >= E_PDB_OK && (code - E_PDB_OK) < qnumber(g_pdb_errors) ) - return g_pdb_errors[code - E_PDB_OK]; - } - return winerr(code); -} - -//---------------------------------------------------------------------- -class DECLSPEC_UUID("4C41678E-887B-4365-A09E-925D28DB33C2") DiaSource90; -class DECLSPEC_UUID("1fbd5ec4-b8e4-4d94-9efe-7ccaf9132c98") DiaSource80; -class DECLSPEC_UUID("31495af6-0897-4f1e-8dac-1447f10174a1") DiaSource71; -static const GUID *const g_d90 = &__uuidof(DiaSource90); // msdia90.dll -static const GUID *const g_d80 = &__uuidof(DiaSource80); // msdia80.dll -static const GUID *const g_d71 = &__uuidof(DiaSource71); // msdia71.dll -static const GUID *const g_msdiav[] = { g_d90, g_d80, g_d71 }; -static const int g_diaver[] = { 900, 800, 710 }; -static const char *const g_diadlls[] = { "msdia90.dll", "msdia80.dll", "msdia71.dll" }; - -//---------------------------------------------------------------------- -HRESULT __stdcall CoCreateInstanceNoReg( - LPCTSTR szDllName, - IN REFCLSID rclsid, - IUnknown *pUnkOuter, - IN REFIID riid, - OUT LPVOID FAR *ppv, - OUT HMODULE *phMod) -{ - // http://lallousx86.wordpress.com/2007/01/29/emulating-cocreateinstance/ - HRESULT hr = REGDB_E_CLASSNOTREG; - HMODULE hDll; - do - { - hDll = LoadLibrary(szDllName); - if ( hDll == NULL ) - break; - - HRESULT (__stdcall *GetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); - *(FARPROC*)&GetClassObject = GetProcAddress(hDll, "DllGetClassObject"); - if ( GetClassObject == NULL ) - break; - - IClassFactory *pIFactory; - hr = GetClassObject(rclsid, IID_IClassFactory, (LPVOID *)&pIFactory); - if ( FAILED(hr) ) - break; - - hr = pIFactory->CreateInstance(pUnkOuter, riid, ppv); - pIFactory->Release(); - } - while ( false ); - - if ( FAILED(hr) && hDll != NULL ) - FreeLibrary(hDll); - else - *phMod = hDll; - - return hr; -} - -//---------------------------------------------------------------------------- -// Note: This will return the machine type, as it is known -// by the IDB, which might not be what you think. For example, -// if you need to tell x86 and x64 apart, you're out of luck. -// You may want to consider looking at pdbaccess_t's -// get_machine_type(). -static DWORD get_machine_type(DWORD dwMachType) -{ - DWORD machine; - switch ( dwMachType ) - { - default: - machine = CV_CFL_80386; - break; - case IMAGE_FILE_MACHINE_IA64: - machine = CV_CFL_IA64; - break; - case IMAGE_FILE_MACHINE_AMD64: - machine = CV_CFL_AMD64; - break; - case IMAGE_FILE_MACHINE_THUMB: - case IMAGE_FILE_MACHINE_ARM: - machine = CV_CFL_ARM6; - break; - case PECPU_ARMV7: - machine = CV_CFL_ARM7; - break; - case PECPU_PPC: - machine = CV_CFL_PPC620; - break; - case PECPU_PPCFP: - machine = CV_CFL_PPCFP; - break; - case PECPU_PPCBE: - machine = CV_CFL_PPCBE; - break; - } - return machine; -} - -//---------------------------------------------------------------------- -pdb_session_t::~pdb_session_t() -{ - if ( --session_count == 0 && co_initialized ) - { - CoUninitialize(); - co_initialized = false; - } -} - -//---------------------------------------------------------------------- -void pdb_session_t::close() -{ - if ( pdb_access != NULL ) - { - delete pdb_access; - pdb_access = NULL; - } - - if ( dia_hmod != NULL ) - { - FreeLibrary(dia_hmod); - dia_hmod = NULL; - } - -#ifdef _DEBUG - if ( !_pdb_path.empty() && qfileexist(_pdb_path.begin() ) ) - { - HANDLE hFile = CreateFileA(_pdb_path.begin(), GENERIC_READ, /*FILE_SHARE_READ*/ 0, 0, OPEN_EXISTING, 0, 0); - if ( hFile == INVALID_HANDLE_VALUE ) - warning("Couldn't acquire probing lock to \"%s\"; file might be still locked by IDA", _pdb_path.begin()); - else - CloseHandle(hFile); - } -#endif -} - -//---------------------------------------------------------------------- -typedef BOOL (CALLBACK *SymbolServerSetOptions_t)(UINT_PTR options, ULONG64 data); -typedef BOOL (CALLBACK *SymbolServerGetOptionData_t)(UINT_PTR option, PULONG64 pData); - -#include "dbghelp.h" -// copied from dbghelp.h -#ifndef SSRVOPT_CALLBACK -#define SSRVOPT_CALLBACK 0x000001 -#endif -#ifndef SSRVOPT_SETCONTEXT -#define SSRVOPT_SETCONTEXT 0x000800 -#endif -#ifndef SSRVOPT_TRACE -#define SSRVOPT_TRACE 0x000400 -#endif -#ifndef SSRVACTION_TRACE -#define SSRVACTION_TRACE 1 -#define SSRVACTION_QUERYCANCEL 2 -#define SSRVACTION_EVENT 3 -#define SSRVACTION_EVENTW 4 -#endif -#ifndef SSRVACTION_SIZE -#define SSRVACTION_SIZE 5 -#endif - -//---------------------------------------------------------------------- -static void symsrv_dprint(const char *str) -{ - qstring qbuf(str); - qbuf.replace("\b", ""); // remove backspaces - if ( qbuf.empty() ) - return; - // strings usually already start with "SYMSRV: " - if ( strncmp(qbuf.c_str(), "SYMSRV: ", 9) != 0 ) - qbuf.insert(0, "SYMSRV: "); - // strings usually already end with '\n' - if ( qbuf.last() != '\n' ) - qbuf.append('\n'); - deb(IDA_DEBUG_DEBUGGER, "%s", qbuf.c_str()); -} - -//---------------------------------------------------------------------- -static BOOL CALLBACK SymbolServerCallback( - UINT_PTR action, - ULONG64 data, - ULONG64 context) -{ - switch ( action ) - { - case SSRVACTION_SIZE: - { - bool *wait_box_shown = (bool *) context; - if ( !*wait_box_shown ) - show_wait_box("Downloading pdb..."); - *wait_box_shown = true; - } - break; - case SSRVACTION_QUERYCANCEL: - { - BOOL *do_cancel = (BOOL *) data; - if ( user_cancelled() ) - *do_cancel = TRUE; - } - break; - case SSRVACTION_TRACE: - symsrv_dprint((const char *)data); - break; - case SSRVACTION_EVENT: - IMAGEHLP_CBA_EVENT *pev = (IMAGEHLP_CBA_EVENT*)data; - // Event information is usually all zero. - if ( pev->severity != 0 || pev->code != 0 || pev->object != NULL ) - deb(IDA_DEBUG_DEBUGGER, "SYMSRV: event severity: %d code: %d object: %p\n", pev->severity, pev->code, pev->object); - symsrv_dprint(pev->desc); - break; - } - return TRUE; -} - -//---------------------------------------------------------------------------- -class symsrv_cb_t -{ - HMODULE symsrv_hmod; - bool wait_box_shown; - SymbolServerGetOptionData_t get_option_data; // "DbgHelp.dll 10.0 or later" - SymbolServerSetOptions_t set_options; - ULONG64 was_context; - ULONG64 was_callback; - -public: - symsrv_cb_t(void) - { - symsrv_hmod = LoadLibrary("symsrv.dll"); - wait_box_shown = false; - get_option_data = NULL; - set_options = NULL; - was_context = 0; - was_callback = 0; - } - - void init(void) - { - if ( symsrv_hmod != NULL ) - { - get_option_data = (SymbolServerGetOptionData_t)(void *)GetProcAddress(symsrv_hmod, "SymbolServerGetOptionData"); - if ( get_option_data != NULL ) - { - was_context = get_option_data(SSRVOPT_SETCONTEXT, &was_context); - was_callback = get_option_data(SSRVOPT_CALLBACK, &was_callback); - } - - set_options = (SymbolServerSetOptions_t)(void *)GetProcAddress(symsrv_hmod, "SymbolServerSetOptions"); - if ( set_options != NULL ) - { - set_options(SSRVOPT_SETCONTEXT, (ULONG64) (intptr_t) &wait_box_shown); - set_options(SSRVOPT_CALLBACK, (ULONG64) SymbolServerCallback); - if ( (debug & IDA_DEBUG_DEBUGGER) != 0 ) - { - set_options(SSRVOPT_TRACE, (ULONG64) TRUE); - } - } - } - } - - void term(void) - { - if ( symsrv_hmod != NULL ) - { - if ( set_options != NULL ) - { - set_options(SSRVOPT_SETCONTEXT, was_context); - set_options(SSRVOPT_CALLBACK, was_callback); - } - FreeLibrary(symsrv_hmod); - symsrv_hmod = NULL; - if ( wait_box_shown ) - hide_wait_box(); - } - } -}; - -//---------------------------------------------------------------------------- -static qstring print_guid(GUID *guid) -{ - qstring guid_str; - if ( guid != NULL ) - { - OLECHAR *guid_wstr = NULL; - StringFromCLSID(*guid, &guid_wstr); - if ( guid_wstr != NULL ) - { - utf16_utf8(&guid_str, guid_wstr); - CoTaskMemFree(guid_wstr); - } - } - if ( guid_str.empty() ) - guid_str = "{00000000-0000-0000-0000-000000000000}"; - return guid_str; -} - -//---------------------------------------------------------------------------- -static HRESULT check_and_load_pdb( - IDiaDataSource *pSource, - LPCOLESTR pdb_path, - const pdb_signature_t &pdb_sign, - bool load_anyway) -{ - HRESULT hr = E_FAIL; - if ( !load_anyway ) - { - uint32 sig = pdb_sign.sig; - uint32 age = pdb_sign.age; - GUID *pcsig70 = NULL; - for ( int i=0; i < qnumber(pdb_sign.guid); i++ ) - { - if ( pdb_sign.guid[i] != 0 ) - { - pcsig70 = (GUID *)&pdb_sign.guid; - break; - } - } - if ( sig == 0 && age == 0 && pcsig70 == NULL ) - return E_FAIL; - qstring guid_str = print_guid(pcsig70); - deb(IDA_DEBUG_DEBUGGER, "PDB: Trying to load PDB \"%S\" (guid %s, sig 0x%08X, age 0x%08X)\n", pdb_path, guid_str.c_str(), sig, age); - hr = pSource->loadAndValidateDataFromPdb(pdb_path, pcsig70, sig, age); - deb(IDA_DEBUG_DEBUGGER, "PDB: loadAndValidateDataFromPdb(\"%S\"): %s\n", pdb_path, pdberr(hr)); - if ( hr == E_PDB_INVALID_SIG || hr == E_PDB_INVALID_AGE ) - { - load_anyway = ask_yn(ASKBTN_NO, - "HIDECANCEL\nICON WARNING\nAUTOHIDE NONE\n" - "PDB signature and/or age does not match the input file.\n" - "Do you want to load it anyway?") == ASKBTN_YES; - } - } - if ( load_anyway ) - { - hr = pSource->loadDataFromPdb(pdb_path); - deb(IDA_DEBUG_DEBUGGER, "PDB: loadDataFromPdb(\"%S\"): %s\n", pdb_path, pdberr(hr)); - } - return hr; -} - -//---------------------------------------------------------------------------- -// warn the user about eventual UNC or other problematic paths -static bool check_for_odd_paths(const char *fname) -{ - if ( PathIsUNC == NULL ) - { - HMODULE h = GetModuleHandle("shlwapi.dll"); - if ( h != NULL ) - PathIsUNC = (PathIsUNC_t)(void*)GetProcAddress(h, "PathIsUNCA"); - } - if ( fname[0] == '\\' - || fname[0] == '/' - || PathIsUNC != NULL && PathIsUNC(fname) ) - { - if ( ask_yn(ASKBTN_NO, - "AUTOHIDE NONE\nHIDECANCEL\n" - "Please be careful, the debug path looks odd!\n" - "\"%s\"\n" - "Do you really want IDA to access this path (possibly a remote server)?", - fname) != ASKBTN_YES ) - { - return false; - } - } - return true; -} - -//--------------------------------------------------------------------------- -HRESULT pdb_session_t::load_data_for_exe( - const pdbargs_t &pdbargs, - load_data_type_t type) -{ - // First check for load address. - ea_t load_address = BADADDR; - if ( type == MEM_LOCAL || type == MEM_WIN32 ) - { - load_address = pdbargs.loaded_base; - if ( load_address == BADADDR ) - return E_FAIL; - } - - msdia_reader_t *msdia_reader = NULL; - HRESULT hr = E_FAIL; - switch ( type ) - { - case EXE_LOCAL: - msdia_reader = new local_exe_msdia_reader_t(winput.c_str()); - break; -#ifdef PDB_PLUGIN - case MEM_LOCAL: - msdia_reader = new local_mem_msdia_reader_t; - break; -#elif defined(PDB_WIN32_SERVER) - case EXE_WIN32: - msdia_reader = new win32_msdia_reader_t(pdbargs.user_data, READ_INPUT_FILE); - break; - case MEM_WIN32: - msdia_reader = new win32_msdia_reader_t(pdbargs.user_data, READ_MEMORY); - break; -#endif - default: - break; - } - if ( msdia_reader->setup() ) - { - qstring buf; - if ( load_address != BADADDR ) - buf.sprnt(" with load address %a", load_address); - deb(IDA_DEBUG_DEBUGGER, "PDB: Trying loadDataForExe(\"%S\", \"%S\")%s\n", winput.c_str(), wspath.c_str(), buf.c_str()); - - CCallback callback(this, msdia_reader, load_address); - hr = pSource->loadDataForExe(winput.c_str(), wspath.c_str(), (IDiaLoadCallback *)&callback); - - deb(IDA_DEBUG_DEBUGGER, "PDB: %s\n", pdberr(hr)); - } - delete msdia_reader; - - return hr; -} - -//---------------------------------------------------------------------------- -HRESULT pdb_session_t::load_input_path( - const pdbargs_t &pdbargs, - const char *input_path) -{ - utf8_utf16(&wspath, pdbargs.spath.c_str()); - utf8_utf16(&winput, input_path); - - qvector<load_data_type_t> methods; -#ifdef PDB_PLUGIN - // Is the debugger active? - if ( get_process_state() != DSTATE_NOTASK ) - { - // First try using program data from debugger memory. - methods.push_back(MEM_LOCAL); - // Then try reading the executable (unless we're remote debugging). - if ( !dbg->is_remote() ) - methods.push_back(EXE_LOCAL); - } - else // debugger not active - { - // First try reading the executable. - methods.push_back(EXE_LOCAL); - // Then try using program data from the IDB. - methods.push_back(MEM_LOCAL); - } -#elif defined(PDB_WIN32_SERVER) - // First try reading the executable. - if ( pdbargs.is_dbg_module() ) - { - // If the module has been loaded by the debugger itself, we can - // read the file locally on the server side. - // TODO isn't this a security issue? the user can specify - // any input_path to be read on the server. - methods.push_back(EXE_LOCAL); - } - else - { - // Otherwise we want to read the input file from the remote stub. - methods.push_back(EXE_WIN32); - } - // Then try reading memory locally on the server side (the process - // being debugged). - methods.push_back(MEM_WIN32); -#else - // For efd and tilib, only try loading the executable locally. - methods.push_back(EXE_LOCAL); -#endif - - HRESULT hr = E_FAIL; - for ( size_t i = 0; i < methods.size(); i++ ) - { - hr = load_data_for_exe(pdbargs, methods[i]); - if ( hr == S_OK ) - break; - if ( hr == E_PDB_NOT_FOUND ) - break; // another address won't help - } - - return hr; -} - -//---------------------------------------------------------------------------- -HRESULT pdb_session_t::open_session(const pdbargs_t &pdbargs) -{ - // Already open? - if ( pdb_access != NULL ) - return S_OK; - - // Not initialized yet? - if ( !co_initialized ) - { - // Initialize COM - CoInitialize(NULL); - co_initialized = true; - } - - int dia_version; - HRESULT hr; - IDiaSession *pSession = NULL; - IDiaSymbol *pGlobal = NULL; - bool pdb_loaded = false; - - // No interface was created? - hr = create_dia_source(&dia_version); - if ( FAILED(hr) ) - goto fail; - - // First try to open PDB file if it was specified. - const qstring &pdb_path = pdbargs.pdb_path; - if ( !pdb_path.empty() - && check_for_odd_paths(pdb_path.c_str()) - && qfileexist(pdb_path.c_str()) ) - { - qwstring wpdb_path; - utf8_utf16(&wpdb_path, pdb_path.c_str()); - bool force_load = (pdbargs.flags & (PDBFLG_ONLY_TYPES|PDBFLG_EFD)) != 0; - hr = check_and_load_pdb(pSource, wpdb_path.c_str(), pdbargs.pdb_sign, force_load); - if ( hr == E_PDB_INVALID_SIG || hr == E_PDB_INVALID_AGE ) // Mismatching PDB - goto fail; - pdb_loaded = (hr == S_OK); - used_fname = pdb_path; // TODO is this needed? - } - - // Failed? Try to load input_path as EXE if it was specified. - const qstring &input_path = pdbargs.input_path; - if ( !pdb_loaded && !input_path.empty() ) - { - qstring path = input_path; - if ( !qfileexist(path.c_str()) ) - { - // If the input path came from a remote system, it is unlikely to be - // correct on our system. DIA does not care about the exact file name - // but uses the directory path to locate the PDB file. It combines - // the name of the pdb file from the debug directory and the directory - // from the input path. - // Since we cannot rely on remote paths, we simply use the current dir - char buf[QMAXPATH]; - qgetcwd(buf, sizeof(buf)); - path.sprnt("%s\\%s", buf, qbasename(input_path.c_str())); - msg("PDB: \"%s\": not found, trying \"%s\"\n", path.c_str(), buf); - } - if ( !check_for_odd_paths(path.c_str()) ) - return E_PDB_NOT_FOUND; - - used_fname = path; - - // Setup symsrv callback to show wait box for pdb downloading - symsrv_cb_t symsrv_cb; - symsrv_cb.init(); - - // Try searching for PDB information from the debug directory in a - // PE file. Either the input file is read directly or the contents - // of a loaded module are read from memory. - hr = load_input_path(pdbargs, path.c_str()); - pdb_loaded = (hr == S_OK); - - // Hide wait box for pdb downloading if needed - symsrv_cb.term(); - } - - // Failed? Then nothing else to try, quit - if ( !pdb_loaded ) - { - // make sure we do return an error - if ( hr == S_OK ) - hr = E_FAIL; - goto fail; - } - - // Open a session for querying symbols - hr = pSource->openSession(&pSession); - deb(IDA_DEBUG_DEBUGGER, "PDB: openSession(): %s\n", pdberr(hr)); - if ( FAILED(hr) ) - goto fail; - - // Set load address - // TODO check if load_address should be set when loading PDB works directly. - ea_t load_address = pdbargs.loaded_base; - if ( load_address != BADADDR ) - { - msg("PDB: using load address %a\n", load_address); - pSession->put_loadAddress(load_address); - } - - // Retrieve a reference to the global scope - hr = pSession->get_globalScope(&pGlobal); //-V595 The 'pSession' pointer was utilized before it was verified against nullptr - if ( hr != S_OK ) - goto fail; - - pdb_access = new local_pdb_access_t(pdbargs, pSource, pSession, pGlobal); - - DWORD pdb_machType, machType; - if ( pGlobal->get_machineType(&pdb_machType) != S_OK ) //-V595 The 'pGlobal' pointer was utilized before it was verified against nullptr - pdb_machType = IMAGE_FILE_MACHINE_I386; - machType = get_machine_type(pdb_machType); - - pdb_access->set_machine_type(machType); - pdb_access->set_dia_version(dia_version); - - hr = pdb_access->init(); - if ( hr == S_OK ) - return hr; - - // TODO clear pdb_access since above test failed - -fail: - // In the event of an error, this will be reached. - if ( pdb_access == NULL ) - { - if ( pGlobal != NULL ) - pGlobal->Release(); - if ( pSession != NULL ) - pSession->Release(); - if ( pSource != NULL ) - pSource->Release(); - } - return hr; -} - -//---------------------------------------------------------------------- -HRESULT pdb_session_t::create_dia_source(int *dia_version) -{ - HRESULT hr; - // VC80/90 CRT installs msdiaNN.dll in this folder: - // "C:\Program Files (x86)\Common Files\microsoft shared\VC" - char common_files[QMAXPATH]; - qstring vc_shared; - if ( get_special_folder(common_files, sizeof(common_files), CSIDL_PROGRAM_FILES_COMMON) ) - { - vc_shared = common_files; - vc_shared.append("\\Microsoft Shared\\VC"); - } - - for ( size_t i=0; i < qnumber(g_msdiav); i++ ) - { - // Try to create using CoCreateInstance() - hr = CoCreateInstance(*g_msdiav[i], - NULL, - CLSCTX_INPROC_SERVER, - __uuidof(IDiaDataSource), - (void**)&pSource); - - // Try to create with CoCreateInstanceNoReg() - if ( FAILED(hr) ) - { - // Search for this interface in DIA dlls - char path[QMAXPATH]; - if ( !search_path(path, sizeof(path), g_diadlls[i], false) - && (vc_shared.empty() - || SearchPathA(vc_shared.c_str(), g_diadlls[i], NULL, - qnumber(path), path, NULL) == 0) ) - { - continue; - } - - for ( size_t j=0; j < qnumber(g_msdiav); j++ ) - { - hr = CoCreateInstanceNoReg(path, - *g_msdiav[j], - NULL, - __uuidof(IDiaDataSource), - (void**)&pSource, - &dia_hmod); - - if ( hr == S_OK ) - { - static bool displayed = false; - if ( !displayed ) - { - displayed = true; - msg("PDB: using DIA dll \"%s\"\n", path); - } - i = j; - break; - } - } - } - - if ( hr == S_OK ) - { - *dia_version = g_diaver[i]; - static bool displayed = false; - if ( !displayed ) - { - displayed = true; - msg("PDB: DIA interface version %d.%d\n", (*dia_version)/100, (*dia_version)%100); - } - return hr; - } - else - { - *dia_version = 0; - } - } - return E_NOINTERFACE; -} - -//---------------------------------------------------------------------- -pdb_session_ref_t::pdb_session_ref_t(const pdb_session_ref_t &r) - : session(r.session) -{ - if ( session != NULL ) - session->refcount++; -} - -//---------------------------------------------------------------------- -pdb_session_ref_t &pdb_session_ref_t::operator=(const pdb_session_ref_t &r) -{ - if ( &r != this ) - { - this->~pdb_session_ref_t(); - new (this) pdb_session_ref_t(r); - } - return *this; -} - -//---------------------------------------------------------------------------- -pdb_session_ref_t::~pdb_session_ref_t() -{ - close(); - if ( session != NULL ) - { - delete session; - session = NULL; - } -} - -//---------------------------------------------------------------------- -void pdb_session_ref_t::create_session(void) -{ - QASSERT(30462, session == NULL); - session = new pdb_session_t(); -} - -//---------------------------------------------------------------------- -void pdb_session_ref_t::close() -{ - if ( session != NULL ) - { - // shared instance? then detach - if ( session->refcount > 1 ) - { // unlink - session->refcount--; - session = NULL; - } - else - { - session->close(); - } - } -} - -//---------------------------------------------------------------------- -HRESULT pdb_session_ref_t::open_session(const pdbargs_t &pdbargs) -{ - if ( opened() ) - return S_OK; - - if ( empty() ) - create_session(); - - return session->open_session(pdbargs); -} diff --git a/idasdk75/plugins/pdb/pdb.cfg b/idasdk75/plugins/pdb/pdb.cfg deleted file mode 100644 index 8908239..0000000 --- a/idasdk75/plugins/pdb/pdb.cfg +++ /dev/null @@ -1,40 +0,0 @@ -// PDB plugin - -// PDB information provider -#define PDB_PROVIDER_MSDIA 1 // use MSDIA local/remote provider -#define PDB_PROVIDER_PDBIDA 2 // use PDBIDA provider -//PDB_PROVIDER = PDB_PROVIDER_PDBIDA - -// it is possible to specify the desired provider in the command line: -// ida -Opdb:off input_file -// ida -Opdb:msdia input_file -// ida -Opdb:pdbida input_file - -// Symbol search path -// The _NT_SYMBOL_PATH environment variable overrides this setting. -// If none of these variables is set then the default value will be used: -// "SRV*CACHEDIR*http://msdl.microsoft.com/download/symbols" -// where -// CACHEDIR=%TEMP%\ida for Windows -// CACHEDIR=$TMPDIR/ida or $TMP/ida or /tmp/ida for non-Windows OSes -// -//_NT_SYMBOL_PATH = "SRV*c:\\symbols*http://symbols.mozilla.org/firefox;SRV*c:\\symbols*http://msdl.microsoft.com/download/symbols"; - -// PDBIDA is able to load MSF 7.0 PDB files only. -// MSDIA can load all PDB files, including old MSF 2.0 files. -// If you set the following option to YES, IDA will automatically switch -// to MSDIA for old files. -// Please note that under Linux/macOS the MSDIA provider requires you to configure -// the win32_remote.exe server because it can run only on Windows. -// It is possible to specify the desired behavior in the command line: -// ida -Opdb:fallback input_file -// ida -Opdb:nofallback input_file -PDB_MSDIA_FALLBACK = NO - -// remote server where win32_remote.exe is running -// used when loading PDB symbols on non-Windows platforms -// NB: it will be used only if there is not already an existing debugging session started -PDB_REMOTE_SERVER = "localhost"; -PDB_REMOTE_PORT = 23946 -// password for the remote server -PDB_REMOTE_PASSWD = ""; diff --git a/idasdk75/plugins/pdb/pdb.cpp b/idasdk75/plugins/pdb/pdb.cpp deleted file mode 100644 index 70f4835..0000000 --- a/idasdk75/plugins/pdb/pdb.cpp +++ /dev/null @@ -1,1397 +0,0 @@ - -// IDA plugin to load function name information from PDB files -// 26-02-2008 Complete rewrite to use DIA API - -#ifdef __NT__ -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -# include <objidl.h> -# define PDB_PLUGIN -#else -# define ENABLE_REMOTEPDB -#endif - -#include <memory> -#include <set> -#include <map> - -#include <ida.hpp> -#include <idp.hpp> -#include <err.h> -#include <md5.h> -#include <dbg.hpp> -#include <auto.hpp> -#include <name.hpp> -#include <frame.hpp> -#include <loader.hpp> -#include <diskio.hpp> -#include <struct.hpp> -#include <typeinf.hpp> -#include <demangle.hpp> -#include <intel.hpp> -#include <network.hpp> -#include <workarounds.hpp> -int data_id; - -#include "pdb.hpp" -#include "common.cpp" -#ifdef ENABLE_REMOTEPDB -// We only enable remote PDB fetching in case -// we are building the plugin, for the moment. -// While this is an annoying limitation, it's mostly -// because the pdbremote code requires that -// the 'win32' (stub) debugger be loadable, in order -// to work: Ideally, we should only use an rpc_client -// instance, but currently we channel PDB requests -// through the remote debugger connection. -// (Neither efd.exe, nor tilib.exe can use of a -// running win32_remote.exe debugger instance for the -// moment) -# include "pdbremote.cpp" -#else -# include "oldpdb.h" -# include "msdia.cpp" -#endif -#include "tilbuild.cpp" - - -#include "sip.cpp" - -//---------------------------------------------------------------------- -static bool looks_like_function_name(const char *name) -{ - // this is not quite correct: the presence of an opening brace - // in the demangled name indicates a function - // we can have a pointer to a function and there will be a brace - // but this logic is not applied to data segments - if ( strchr(name, '(') != NULL ) - return true; - - // check various function keywords - static const char *const keywords[] = - { - "__cdecl ", - "public: ", - "virtual ", - "operator ", - "__pascal ", - "__stdcall ", - "__thiscall ", - }; - for ( int i=0; i < qnumber(keywords); i++ ) - if ( strstr(name, keywords[i]) != NULL ) - return true; - return false; -} - -//---------------------------------------------------------------------- -bool pdb_ctx_t::check_for_ids(ea_t ea, const char *name, bool has_typeinfo) -{ - // Seems to be a GUID? - const char *ptr = name; - while ( *ptr == '_' ) - ptr++; - - static const char *const guids[] = { "IID", "DIID", "GUID", "CLSID", "LIBID", NULL }; - static const char *const sids[] = { "SID", NULL }; - - struct id_info_t - { - const char *const *names; - const char *type; - }; - static const id_info_t ids[] = - { - { guids, "GUID x;" }, - { sids, "SID x;" }, - }; - if ( !checked_types ) - { - if ( get_named_type(NULL, "GUID", NTF_TYPE) == 0 ) - { - static const char decl[] = "typedef struct _GUID { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[8];} GUID;"; - h2ti(NULL, NULL, decl, HTI_DCL, NULL, NULL, msg); - } - // SID type is pretty complex, so we won't add it manually but just check if it exists - has_sid = get_named_type(NULL, "SID", NTF_TYPE) != 0; - checked_types = true; - } - for ( int k=0; k < qnumber(ids); k++ ) - { - if ( k == 1 && !has_sid ) - continue; - for ( const char *const *p2=ids[k].names; *p2; p2++ ) - { - const char *guid = *p2; - size_t len = strlen(guid); - if ( strncmp(ptr, guid, len) == 0 - && (ptr[len] == '_' || ptr[len] == ' ') ) // space can be in demangled names - { - if ( has_typeinfo ) - apply_cdecl(NULL, ea, ids[k].type); - return true; - } - } - } - if ( strncmp(name, "_guid", 5) == 0 ) - { - if ( has_typeinfo ) - apply_cdecl(NULL, ea, ids[0].type); - return true; - } - return false; -} - -//---------------------------------------------------------------------- -static bool is_data_prefix(ea_t ea, const char *name) -{ - static const char *const data_prefixes[] = - { - "__IMPORT_DESCRIPTOR", - //"__imp_", //imported function pointer - }; - for ( int i=0; i < qnumber(data_prefixes); i++ ) - if ( strncmp(name, data_prefixes[i], strlen(data_prefixes[i])) == 0 ) - return true; - - // __real@xxxxxxxx - floating point number, 4 bytes - // __real@xxxxxxxxxxxxxxxx - floating point number, 8 bytes - if ( strncmp(name, "__real@", 7) == 0 ) - { - const char *ptr = name + 7; - const char *hex = ptr; - while ( qisxdigit(*ptr) ) - ptr++; - size_t len = ptr - hex; - if ( len == 8 ) - { - create_float(ea, 4); - return true; - } - if ( len == 16 ) - { - create_double(ea, 8); - return true; - } - if ( len == 20 ) - { // i haven't seen this, but probably it exists too - create_tbyte(ea, 10); - return true; - } - } - return false; -} - -//------------------------------------------------------------------------- -// Names that we prefer to ignore -static bool ignore_name(const char *name) -{ - struct ida_local sfxlen_t - { - const char *const sfx; - size_t len; // strlen(sfx) - }; - - static const sfxlen_t unwanted_suffixes[] = - { - { "_epilog1_start", 14 }, - }; - - size_t len = qstrlen(name); - - for ( auto &sfx : unwanted_suffixes ) - { - if ( len > sfx.len && streq(&name[len-sfx.len], sfx.sfx) ) - return true; - } - - // MSVS debug symbols may contain the temporary labels "Temp.00000001" - if ( strneq(name, "Temp.", 5) ) - { - const char *p = &name[5]; - if ( *p != '\0' ) - { - for ( ; *p != '\0' && isdigit(*p); ++p ) - ; - if ( *p == '\0' ) - return true; - } - } - - // _lc002_004933_ - if ( strneq(name, "_lc", 3) ) - { - const char *p = &name[3]; - if ( isdigit(p[0]) - && isdigit(p[1]) - && isdigit(p[2]) - && p[3] == '_' - && isdigit(p[4]) - && isdigit(p[5]) - && isdigit(p[6]) - && isdigit(p[7]) - && isdigit(p[8]) - && isdigit(p[9]) - && p[10] == '_' ) - { - return true; - } - } - - return false; -} - -//------------------------------------------------------------------------- -int pdb_ctx_t::get_utf16_encoding_idx() -{ - if ( utf16_encidx < 0 ) - utf16_encidx = add_encoding(inf_is_be() ? "UTF-16BE" : "UTF-16LE"); - return utf16_encidx; -} - -//---------------------------------------------------------------------- -// maybe_func: -1:no, 0-maybe, 1-yes, 2:no,but iscode -bool pdb_ctx_t::apply_name_in_idb(ea_t ea, const qstring &name, int maybe_func, uint32 the_machine_type) -{ - show_addr(ea); // so the user doesn't get bored - - if ( ignore_name(name.c_str()) ) - return true; - - // check for meaningless 'string' names - if ( strncmp(name.c_str(), "??_C@_", 6) == 0 ) - { - // ansi: ??_C@_0<len>@xxx - // unicode: ??_C@_1<len>@xxx - // TODO: parse length? - uint32 strtype = STRTYPE_C; - if ( name[6] == '1' ) - strtype = STRTYPE_C_16 | (get_utf16_encoding_idx() << 24); - create_strlit(ea, 0, strtype); - return true; - } - - qstring demangled; - if ( maybe_func <= 0 && demangle_name(&demangled, name.c_str(), MNG_SHORT_FORM) > 0 ) - { - if ( demangled == "`string'" ) - { - uint32 utf16_strtype = STRTYPE_C_16 | (get_utf16_encoding_idx() << 24); - size_t s1 = get_max_strlit_length(ea, STRTYPE_C); - size_t s2 = get_max_strlit_length(ea, utf16_strtype); - create_strlit(ea, 0, s1 >= s2 ? STRTYPE_C : utf16_strtype); - return true; - } - } - - // Renaming things immediately right here can lead to bad things. - // For example, if the name is a well known function name, then - // ida will immediately try to create a function. This is a bad idea - // because IDA does not know exact function boundaries and will try - // to guess them. Since the database has little information yet, there - // is a big chance that the function will end up to be way too long. - // That's why we collect names here and will rename them later. - namelist[ea] = name; - - bool has_typeinfo = ph.ti(); - if ( check_for_ids(ea, name.c_str(), has_typeinfo) - || check_for_ids(ea, demangled.c_str(), has_typeinfo) - || is_data_prefix(ea, name.c_str()) - || maybe_func < 0 ) - { - set_notcode(ea); // should not be code - return true; - } - if ( maybe_func == 0 && get_mangled_name_type(name.c_str()) == MANGLED_DATA ) - { - // NB: don't call set_notcode() here - // since demangler may give false positives - return true; - } - - // do not automatically create functions in debugger segments - segment_t *s = getseg(ea); - if ( s == NULL || !s->is_loader_segm() ) - return true; - - // ARMv7 PDBs don't use bit 0 for Thumb mode - if ( ph.has_code16_bit() && the_machine_type != CV_CFL_ARM7 ) - { - // low bit is Thumb/MIPS16 mode - bool func16 = (ea & 1) != 0; - ea &= ~1; - if ( func16 ) - { - // move the entry in namelist - namelist.erase(ea|1); - namelist[ea] = name; - } - } - - if ( maybe_func == 0 ) - { - do - { - // check for function telltales - if ( segtype(ea) != SEG_DATA - && demangle_name(&demangled, name.c_str(), MNG_LONG_FORM) > 0 - && looks_like_function_name(demangled.c_str()) ) - { - maybe_func = 1; - break; - } - - int stype = segtype(ea); - if ( stype != SEG_NORM && stype != SEG_CODE ) // only for code or normal segments - break; - - insn_t insn; - if ( decode_insn(&insn, ea) == 0 ) - break; - - if ( processor_t::is_sane_insn(insn, 1) < 0 ) - break; - maybe_func = 1; - } while ( false ); - } - if ( maybe_func == 1 ) - auto_make_proc(ea); // fixme: when we will implement lvars, we have to process these request - // before handling lvars - return true; -} - -//---------------------------------------------------------------------------- -// These two funcs for old.cpp only -bool apply_name(ea_t ea, const qstring &name, int maybe_func) -{ - pdb_ctx_t &pv = *GET_MODULE_DATA(pdb_ctx_t); - return pv.apply_name_in_idb(ea, name, maybe_func, pv.g_machine_type); -} - -void load_vc_til(void) -{ - pdb_ctx_t &pv = *GET_MODULE_DATA(pdb_ctx_t); - pv.load_vc_til(); -} - -//---------------------------------------------------------------------- -void pdb_ctx_t::load_vc_til(void) const -{ - // We managed to load the PDB file. - // It is very probably that the file comes from VC - // Load the corresponding type library immediately - if ( ph.id == PLFM_386 && pe.signature == PEEXE_ID ) - { - if ( pe.is_userland() ) - add_til(pe.is_pe_plus() ? "mssdk64_win7" : "mssdk_win7", ADDTIL_INCOMP); - else - add_til(pe.is_pe_plus() ? "ntddk64_win7" : "ntddk_win7", ADDTIL_INCOMP); - } -} - -//---------------------------------------------------------------------------- -class pdb_til_builder_t : public til_builder_t -{ - int npass; -public: - pdb_til_builder_t(pdb_ctx_t &_pv, til_t *_ti, pdb_access_t *_pa) - : til_builder_t(_pv, _ti, _pa), npass(0) {} - - virtual HRESULT before_iterating(pdb_sym_t &global_sym) override; - virtual bool iterate_symbols_once_more(pdb_sym_t & /*global_sym*/) override - { - handled.clear(); - return ++npass == 1; - } - virtual void type_created(ea_t ea, int id, const char *name, const tinfo_t &tif) const override; - virtual bool handle_symbol_at_ea(pdb_sym_t &sym, DWORD tag, ea_t ea, qstring &name) override; - virtual void handle_function_type(pdb_sym_t &fun_sym, ea_t ea) override; - virtual HRESULT handle_function_child( - pdb_sym_t &fun_sym, - ea_t ea, - pdb_sym_t &child_sym, - DWORD child_tag, - DWORD child_loc_type) override; -}; - -//---------------------------------------------------------------------------- -HRESULT pdb_til_builder_t::before_iterating(pdb_sym_t &) -{ - pv.load_vc_til(); - if ( default_compiler() == COMP_UNK ) - set_compiler_id(COMP_MS); - return S_OK; -} - -//---------------------------------------------------------------------------- -void pdb_til_builder_t::type_created(ea_t ea, int id, const char *name, const tinfo_t &tif) const -{ - pv.check_tinfo(ea, id, name, tif); -} - -//---------------------------------------------------------------------------- -// add the annotation strings to 'ea' -// following types are commonly used in windows drivers -// 1) assertion: -// #define NT_ASSERT(_exp) -// ((!(_exp)) ? -// (__annotation(L"Debug", L"AssertFail", L#_exp), -// DbgRaiseAssertionFailure(), FALSE) : -// TRUE) -// 2) trace message -// -// TMF: -// 2158e7d3-9867-cde3-18b5-9713c628abdf TEEDriver // SRC=Queue.c MJ= MN= -// #typev Queue_c2319 207 "%0PowerDown = %10!x!" // LEVEL=TRACE_LEVEL_VERBOSE FLAGS=TRACE_QUEUE -// { -// devExt->powerDown, ItemLong -- 10 -// }, Constant -// -// 3) trace message control -// WPP_DEFINE_CONTROL_GUID(Name,Guid,Bits) __annotation(L"TMC:", WPP_GUID_WTEXT Guid, _WPPW(WPP_STRINGIZE(Name)) Bits WPP_TMC_ANNOT_SUFIX); -// expands into: -// -// TMC: -// 0b67e6f7-ae91-470c-b4b6-dcd6a9034e18 -// TEEDriverTraceGuid -// MYDRIVER_ALL_INFO -// TRACE_DRIVER -// TRACE_DEVICE -// [..] -// TRACE_BUS_DRIVER_LAYER -// -// In all other cases we just use plain __annotation(a,b,c,...) -// TODO: use anterior lines for big annotations (over 1KB) -static void apply_annotation(ea_t ea, const qstrvec_t ¶ms) -{ - if ( params.empty() ) - return; - - qstring full_cmt; - if ( params.size() >= 3 && params[0] == "Debug" && params[1] == "AssertFail" ) - { - full_cmt.sprnt("NT_ASSERT(\"%s\"", params[2].c_str()); - for ( size_t i = 3; i < params.size(); i++ ) - full_cmt.cat_sprnt(",\n \"%s\"", params[i].c_str()); - full_cmt.append(")"); - } - else if ( params[0] == "TMF:" ) - { - full_cmt = "__annotation(\"TMF:\""; - bool add_newline = true; - for ( size_t i = 1; i < params.size(); i++ ) - { - full_cmt.cat_sprnt(",%s\"%s\"", add_newline ? "\n " : " ", params[i].c_str()); - // print args betwen { } on one line - if ( params[i] == "{" ) - add_newline = false; - else if ( params[i] == "}" ) - add_newline = true; - } - full_cmt.append(")"); - } - else - { - full_cmt.sprnt("__annotation(\"%s\"", params[0].c_str()); - for ( size_t i = 1; i < params.size(); i++ ) - full_cmt.cat_sprnt(", \"%s\"", params[i].c_str()); - full_cmt.append(")"); - } - set_cmt(ea, full_cmt.c_str(), false); -} - -//---------------------------------------------------------------------------- -bool pdb_til_builder_t::handle_symbol_at_ea( - pdb_sym_t &sym, - DWORD tag, - ea_t ea, - qstring &name) -{ - int maybe_func = 0; - switch ( tag ) - { - case SymTagFunction: - case SymTagThunk: - maybe_func = 1; - break; - case SymTagBlock: - case SymTagLabel: - case SymTagFuncDebugStart: - case SymTagFuncDebugEnd: - maybe_func = 2; - break; - case SymTagData: - case SymTagVTable: - maybe_func = -1; - break; - case SymTagPublicSymbol: - { - BOOL b; - if ( sym.get_function(&b) == S_OK && b ) - maybe_func = 1; - } - break; - case SymTagAnnotation: - { - struct annotation_value_collector_t : public pdb_access_t::children_visitor_t - { - const til_builder_t *tb; - qstrvec_t ann_params; - HRESULT visit_child(pdb_sym_t &child) override - { - qstring v; - if ( tb->get_variant_string_value(&v, child) ) - //set_cmt(ea, v.c_str(), false); - ann_params.push_back(v); - return S_OK; - } - annotation_value_collector_t(const til_builder_t *_tb) - : tb(_tb) {} - }; - annotation_value_collector_t avc(this); - pdb_access->iterate_children(sym, SymTagNull, avc); - apply_annotation(ea, avc.ann_params); - maybe_func = segtype(ea) == SEG_CODE ? 2 /*no func, but code*/ : 0 /*unclear*/; - } - break; - default: - break; - } - - // symbols starting with __imp__ cannot be functions - if ( strncmp(name.c_str(), "__imp__", 7) == 0 ) - { - create_dword(ea, 4); - maybe_func = -1; - } - - BOOL iscode; - if ( sym.get_code(&iscode) == S_OK ) - { - if ( iscode ) - { - if ( is_notcode(ea) ) - { - // clear wrong notcode mark - // (was seen happening with bogus SymTagData symbol for _guard_dispatch_icall_nop) - clr_notcode(ea); - create_insn(ea); - } - } - else - { - // not a function - maybe_func = -1; - } - } - - tpinfo_t tpi; - if ( get_symbol_type(&tpi, sym, NULL) ) - { - // Apparently _NAME_ is a wrong symbol generated for file names - // It has wrong type information, so correct it - if ( tag == SymTagData && name == "_NAME_" && tpi.type.get_decltype() == BTF_CHAR ) - tpi.type = tinfo_t::get_stock(STI_ACHAR); // char [] - if ( tag == SymTagFunction ) - { - // convert the type again, this time passing function symbol - // this allows us to get parameter names and handle static class methods - pdb_sym_t *func_sym = pdb_access->create_sym(); - pdb_sym_janitor_t janitor_pType(func_sym); - if ( sym.get_type(func_sym) == S_OK ) - { - tpinfo_t tpi2; - if ( really_convert_type(&tpi2, *func_sym, &sym, SymTagFunctionType) == cvt_ok ) - tpi.type.swap(tpi2.type); // successfully retrieved - } - } - if ( tpi.type.is_func() || tag == SymTagFunction ) - { - maybe_func = 1; - handle_function_type(sym, ea); - } - else - { - maybe_func = -1; - } - if ( npass != 0 ) - { - bool use_ti = true; - func_type_data_t fti; - if ( tpi.type.get_func_details(&fti) - && fti.empty() - && fti.rettype.is_decl_void() ) - { // sometimes there are functions with linked FunctionType but no parameter or return type info in it - // we get better results by not forcing type info on them - use_ti = false; - } - if ( use_ti ) - { - type_created(ea, 0, NULL, tpi.type); - apply_tinfo(ea, tpi.type, TINFO_STRICT); - } - } - } - else if ( maybe_func == 1 ) - { - auto_make_proc(ea); // certainly a func - } - pv.apply_name_in_idb(ea, name, maybe_func, pdb_access->get_machine_type()); - return true; -} - -//--------------------------------------------------------------------------- -HRESULT pdb_til_builder_t::handle_function_child( - pdb_sym_t &fun_sym, - ea_t ea, - pdb_sym_t &child_sym, - DWORD child_tag, - DWORD child_loc_type) -{ - LONG offset; - DWORD reg_id; - switch ( child_loc_type ) - { - case LocIsEnregistered: - if ( child_sym.get_registerId(®_id) == S_OK ) - { - if ( enregistered_bug && reg_id > 0 ) - reg_id--; - func_t *pfn = get_func(ea); - qstring name; - child_sym.get_name(&name); - qstring canon; - print_pdb_register(&canon, pdb_access->get_machine_type(), reg_id); - if ( pfn != NULL ) - add_regvar(pfn, pfn->start_ea, pfn->end_ea, canon.c_str(), name.c_str(), NULL); - } - break; - - case LocIsRegRel: - if ( child_sym.get_registerId(®_id) == S_OK - && child_sym.get_offset(&offset) == S_OK - && reg_id == CV_REG_EBP ) // we can handle only ebp for the moment - { - func_t *pfn = get_func(ea); - if ( pfn != NULL ) - { - qstring name; - child_sym.get_name(&name); - tpinfo_t tpi; - if ( get_symbol_type(&tpi, child_sym, NULL) ) - { - opinfo_t mt; - size_t size; - flags_t flags; - if ( get_idainfo_by_type(&size, &flags, &mt, tpi.type) ) - { - // DIA's offset is bp-based, not frame-based like in IDA - offset -= pfn->fpd; - // make sure the new variable is not overwriting the return address - // for some reason some PDBs have bogus offsets for some params/locals... - if ( !is_intel386(pdb_access->get_machine_type()) - || offset > 0 - || size <= -offset ) - { - if ( define_stkvar(pfn, name.c_str(), offset, flags, &mt, size) ) - { - insn_t insn; - insn.ea = pfn->start_ea; - member_t *mptr = get_stkvar(NULL, insn, *(op_t*)NULL, offset); //lint !e413 deref null ptr - if ( mptr != NULL ) - { - struc_t *sptr = get_frame(pfn); - set_member_tinfo(sptr, mptr, 0, tpi.type, 0); - set_userti(mptr->id); - } - } - } - } - } - else // no type info... - { - msg("%a: stkvar '%s' with no type info\n", ea, name.c_str()); - } - } - } - break; - default: - return til_builder_t::handle_function_child(fun_sym, ea, child_sym, - child_tag, child_loc_type); - } - return S_OK; -} - -//--------------------------------------------------------------------------- -void pdb_til_builder_t::handle_function_type(pdb_sym_t &sym, ea_t ea) -{ - if ( npass == 0 ) - { - if ( !create_insn(ea) ) - return; - - // add the address to the queue - this will help to determine better function boundaries - auto_make_proc(ea); - } - else - { - ea_t end = BADADDR; - DWORD64 ulLen; - if ( sym.get_length(&ulLen) == S_OK ) - end = ea + asize_t(ulLen); - ea_t next_planned = peek_auto_queue(ea+1, AU_PROC); - - // before adding a function, try to create all its instructions. - // without this the frame analysis may fail. - func_t fn(ea); - find_func_bounds(&fn, FIND_FUNC_DEFINE); - - bool created = false; - bool acceptable_end = end <= next_planned; // end is wrong for fragmented functions - if ( acceptable_end ) - created = add_func(ea, end); - if ( !created ) - add_func(ea); - - til_builder_t::handle_function_type(sym, ea); - } -} - -//--------------------------------------------------------------------------- -static HRESULT common_handler(pdb_ctx_t &pv, pdb_access_t &pdb_access) -{ - try - { - pdb_til_builder_t builder(pv, CONST_CAST(til_t *)(get_idati()), &pdb_access); - pdb_sym_t *global = pdb_access.create_sym(pdb_access.get_global_symbol_id()); - pdb_sym_janitor_t janitor_global(global); - return builder.build(*global); - } - catch ( const pdb_exception_t &e ) - { - msg("Couldn't parse PDB data: %s\n", e.what.c_str()); - return E_FAIL; - } -} - -//--------------------------------------------------------------------------- -#ifdef ENABLE_REMOTEPDB -// On Unix computers use remote_pdb_access -static HRESULT remote_handler(pdb_ctx_t &pv, const pdbargs_t &args) -{ - int chosen_remote_port = pv.pdb_remote_port; - if ( pv.pdb_remote_port_64 != -1 && inf_is_64bit() ) - chosen_remote_port = pv.pdb_remote_port_64; - remote_pdb_access_t remote_pdb_access(args, - pv.pdb_remote_server.c_str(), - chosen_remote_port, - pv.pdb_remote_passwd.c_str()); - HRESULT hr = remote_pdb_access.open_connection(); - if ( hr == S_OK ) - hr = common_handler(pv, remote_pdb_access); - return hr; -} -#endif - - -/*==================================================================== - IDA PRO INTERFACE START HERE -====================================================================*/ - -//------------------------------------------------------------------------- -static const cfgopt_t g_opts[] = -{ - CFGOPT_R ("PDB_REMOTE_PORT", pdb_ctx_t, pdb_remote_port, 0, 65535), - CFGOPT_R ("PDB_REMOTE_PORT_64", pdb_ctx_t, pdb_remote_port_64, 0, 65535), - CFGOPT_QS("_NT_SYMBOL_PATH", pdb_ctx_t, full_sympath, true), - CFGOPT_QS("PDB_REMOTE_SERVER", pdb_ctx_t, pdb_remote_server, true), - CFGOPT_QS("PDB_REMOTE_PASSWD", pdb_ctx_t, pdb_remote_passwd, true), -}; - -//---------------------------------------------------------------------- -#ifndef ENABLE_REMOTEPDB -static uint32 get_machine_from_idb(const processor_t &ph) -{ - uint32 mt; - switch ( ph.id ) - { - case PLFM_ARM: - mt = CV_CFL_ARM6; - break; - case PLFM_MIPS: - mt = CV_CFL_MIPSR4000; - break; - case PLFM_PPC: - mt = inf_is_be() ? CV_CFL_PPCBE : CV_CFL_PPCFP; - break; - case PLFM_SH: - mt = CV_CFL_SH4; - break; - case PLFM_IA64: - mt = CV_CFL_IA64; - break; - case PLFM_386: - default: - mt = CV_CFL_80386; - break; - } - return mt; -} -#endif - -//---------------------------------------------------------------------- -void pdb_ctx_t::init_sympaths() -{ - // user specified symbol path? - full_sympath.qclear(); - read_config_file2("pdb", g_opts, qnumber(g_opts), nullptr, nullptr, 0, this); - - qstring env_sympath; - if ( qgetenv("_NT_SYMBOL_PATH", &env_sympath) ) - full_sympath.swap(env_sympath); - - // default symbol search path - if ( full_sympath.empty() ) - { - char cache_path[QMAXPATH]; - - #ifdef __NT__ - if ( !GetTempPath(sizeof(cache_path), cache_path) ) - cache_path[0] = '\0'; - else - qstrncat(cache_path, "ida", sizeof(cache_path)); - #else - qstring tmpdir; - if ( !qgetenv("TMPDIR", &tmpdir) && !qgetenv("TMP", &tmpdir) ) - tmpdir = "/tmp"; - qmakepath(cache_path, sizeof(cache_path), tmpdir.c_str(), "ida", NULL); - if ( !qisdir(cache_path) && qmkdir(cache_path, 0777) != 0 ) - cache_path[0] = '\0'; - #endif - - full_sympath.sprnt("%s%s%s", g_spath_prefix, cache_path, g_spath_suffix); - } - deb(IDA_DEBUG_DBGINFO, "PDB: _NT_SYMBOL_PATH=%s\n", full_sympath.c_str()); - - if ( opt_provider != 0 ) - pdb_provider = opt_provider; -} - -//---------------------------------------------------------------------- -#define MAX_DISP_PATH 80 -// If path name is too long then replace some directories with "...." -static qstring truncate_path(const qstring &path) -{ - qstring str = path; - int len = str.length(); - if ( len > MAX_DISP_PATH ) - { - char slash = '\\'; - size_t start = str.find(slash); - if ( start == qstring::npos ) - { - slash = '/'; - start = str.find(slash); - } - if ( start != qstring::npos ) - { - size_t end = str.rfind(slash); - size_t prev_start; - do - { - prev_start = start; - start = str.find(slash, start + 1); - } while ( len - (end - start) < MAX_DISP_PATH ); - start = prev_start + 1; - if ( end > start ) - { - str.remove(start, end - start); - str.insert(start, "...."); - } - } - } - return str; -} - -//---------------------------------------------------------------------------- -static bool read_pdb_signature(pdb_signature_t *pdb_sign) -{ - netnode penode(PE_NODE); - rsds_t rsds; - size_t size = sizeof(rsds_t); - if ( penode.getblob(&rsds, &size, 0, RSDS_TAG) != NULL && size == sizeof(rsds_t) ) // RSDS - { - pdb_sign->age = rsds.age; - pdb_sign->sig = 0; - memcpy(pdb_sign->guid, &rsds.guid, sizeof(pdb_sign->guid)); - CASSERT(sizeof(pdb_sign->guid) == sizeof(rsds.guid)); - } - else - { - cv_info_pdb20_t nb10; - size = sizeof(nb10); - if ( penode.getblob(&nb10, &size, 0, NB10_TAG) != NULL && size == sizeof(nb10) ) // NB10 - { - pdb_sign->age = nb10.age; - pdb_sign->sig = nb10.signature; - } - else - { - return false; - } - } - return true; -} - -//---------------------------------------------------------------------------- -// moved into a separate function to diminish the stack consumption -static qstring get_input_path() -{ - char input_path[QMAXPATH]; - if ( get_input_file_path(input_path, sizeof(input_path)) <= 0 ) - input_path[0] = '\0'; - return input_path; -} - -//-------------------------------------------------------------------------- -static int idaapi details_modcb(int fid, form_actions_t &fa) -{ - switch ( fid ) - { - // "Types only" - case 20: - { - ushort c; - if ( fa.get_checkbox_value(20, &c) ) - fa.enable_field(10, c == 0); // enable/disable address field - } - break; - } - - return 1; -} - -//------------------------------------------------------------------------- -static void set_file_by_ext(pdbargs_t *args, const char *buf) -{ - const char *ext = get_file_ext(buf); - if ( ext != NULL && strieq(ext, "pdb") ) - { - args->pdb_path = buf; - args->input_path.clear(); - } - else - { - args->input_path = buf; - args->pdb_path.clear(); - } -} - -//---------------------------------------------------------------------------- -static bool ask_pdb_details(pdbargs_t *args) -{ - netnode penode(PE_NODE); - args->loaded_base = penode.altval(PE_ALT_IMAGEBASE); - - static const char form[] = - "Load PDB file\n" - "%/" - "<#Specify the path to the file to load symbols for#~I~nput file:f:0:64::>\n" - "<#Specify the loading address of the exe/dll file#~A~ddress :N10::64::>\n" - "<#Load only types, do not rename program locations#~T~ypes only:C20>>\n" - "Note: you can specify either a .pdb, or an .exe/.dll file name.\n" - "In the latter case, IDA will try to find and load\n" - "the PDB specified in its debug directory.\n" - "\n"; - - char buf[QMAXPATH]; - const char *src = NULL; - if ( !args->pdb_path.empty() ) - src = args->pdb_path.begin(); - else if ( !args->input_path.empty() ) - src = args->input_path.begin(); - if ( src == NULL ) - src = "*.pdb"; - - qstrncpy(buf, src, sizeof(buf)); - - CASSERT(sizeof(args->loaded_base) == sizeof(ea_t)); - sval_t typesonly = (args->flags & PDBFLG_ONLY_TYPES) != 0; - if ( !ask_form(form, details_modcb, buf, &args->loaded_base, &typesonly) ) - return false; - - set_file_by_ext(args, buf); - - setflag(args->flags, PDBFLG_ONLY_TYPES, typesonly != 0); - - return true; -} - -//------------------------------------------------------------------------- -static bool get_details_from_netnode(pdbargs_t *args) -{ - netnode pdbnode; - pdbnode.create(PDB_NODE_NAME); - - args->loaded_base = pdbnode.altval(PDB_DLLBASE_NODE_IDX); - if ( args->loaded_base == 0 ) - { - msg("PDB: PDB_CC_USER_WITH_DATA called without an imagebase, cannot proceed\n"); -fail: - // set failure result - pdbnode.altset(PDB_DLLBASE_NODE_IDX, 0); - return false; - } - - // TODO dllname shouldn't be needed when we're reading from debugger memory - qstring tmp; - pdbnode.supstr(&tmp, PDB_DLLNAME_NODE_IDX); - if ( tmp.empty() ) - { - msg("PDB: PDB_CC_USER_WITH_DATA called without a filename, cannot proceed\n"); - goto fail; - } - - set_file_by_ext(args, tmp.c_str()); - - bool typesonly = pdbnode.altval(PDB_TYPESONLY_NODE_IDX) != 0; - setflag(args->flags, PDBFLG_ONLY_TYPES, typesonly); - - return true; -} - -//------------------------------------------------------------------------- -static bool get_details_from_pe(pdbargs_t *args) -{ - netnode penode(PE_NODE); - args->loaded_base = penode.altval(PE_ALT_IMAGEBASE); - penode.supstr(&args->pdb_path, PE_SUPSTR_PDBNM); - - args->input_path = get_input_path(); - - if ( args->pdb_path.empty() ) - return false; // do not ask to load pdb with empty name - - return ask_yn(ASKBTN_YES, - "AUTOHIDE REGISTRY\nHIDECANCEL\n" - "The input file was linked with debug information\n" - " and the symbol filename is:\n" - "\"%s\"\n" - "Do you want to look for this file at the specified path\n" - "and the Microsoft Symbol Server?\n", - args->pdb_path.c_str()) == ASKBTN_YES; -} - -//------------------------------------------------------------------------- -static bool ask_for_pdb_file(pdbargs_t *pdbargs, const char *err_str) -{ - qstring disp_path = truncate_path(pdbargs->input_path); - if ( ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "AUTOHIDE REGISTRY\n" - "%s: failed to load pdb info.\n%s\n" - "Do you want to browse for the pdb file on disk?", - disp_path.c_str(), - err_str == NULL ? "" : err_str) == ASKBTN_YES ) - { - char *pdb_file = ask_file(false, "*.pdb", "Choose PDB file"); - if ( pdb_file != NULL ) - { - pdbargs->pdb_path = pdb_file; - return true; - } - } - return false; -} - -//------------------------------------------------------------------------- -bool pdb_ctx_t::apply_debug_info(pdbargs_t &pdbargs) -{ - // we may run out of memory on huge pdb files. prefer to keep the partial - // idb file in this case. - bool restore_kill_flag = is_database_flag(DBFL_KILL); - clr_database_flag(DBFL_KILL); - - netnode pdbnode; - if ( pdbargs.is_pdbfile() ) - pdbnode.create(PDB_NODE_NAME); - - init_sympaths(); - pdbargs.spath = full_sympath; - - bool ok = true; - HRESULT hr = E_FAIL; - - { - msg("PDB: using MSDIA provider\n"); -#ifdef ENABLE_REMOTEPDB - hr = remote_handler(*this, pdbargs); -#else - bool was_load_error = false; -LOAD_PDB: - try - { - pdb_session_ref_t ref; - hr = ref.open_session(pdbargs); - if ( hr == S_OK ) - hr = common_handler(*this, *ref.session->pdb_access); - } - catch ( const std::bad_alloc & ) - { - warning("It appears IDA has run out of memory while loading the PDB file.\n" - "This can happen when using the DIA SDK dll with big and/or corrupt PDBs.\n" - "While you will now be able to continue your work, IDA cannot proceed with PDB parsing, sorry.\n\n" - "It is also HIGHLY recommended that you save the database as soon as possible,\n" - "quit, and restart IDA with that database."); - hr = E_PDB_OUT_OF_MEMORY; - was_load_error = true; - } -#endif - - if ( pdbargs.input_path.empty() ) - pdbargs.input_path = pdbargs.pdb_path; - - if ( FAILED(hr) ) - { - ok = false; -#ifndef ENABLE_REMOTEPDB - const char *err_str = pdberr(hr); - msg("PDB: could not process file \"%s\" with DIA: %s\n", pdbargs.input_path.c_str(), err_str); - pdberr_suggest_vs_runtime(hr); - - // DIA interface failed, try the old methods - if ( hr != E_PDB_INVALID_SIG - && hr != E_PDB_INVALID_AGE - && hr != E_PDB_NOT_FOUND - && hr != E_PDB_INVALID_EXECUTABLE - && !inf_test_mode() ) - { - g_machine_type = get_machine_from_idb(ph); // See 'g_machine_type' comment above - ok = old_pdb_plugin(pdbargs.loaded_base, pdbargs.input_path.c_str(), pdbargs.spath.c_str()); - if ( ok ) - msg("Old method of loading PDB files (dbghelp) was successful\n"); - } - if ( !was_load_error && !ok ) - { - was_load_error = true; - if ( ask_for_pdb_file(&pdbargs, err_str) ) - { - ok = true; // reset to default - goto LOAD_PDB; - } - } -#else - if ( !pdbargs.is_dbg_module() ) // called as main plugin routine - warning("IDA could not open \"%s\". Please check that the file " - "exists on the remote computer.", pdbargs.fname()); - else - msg("No PDB information found for \"%s\"\n", pdbargs.fname()); -#endif - } - } - - if ( ok && (pdbargs.flags & PDBFLG_ONLY_TYPES) == 0 ) - { - // Now all information is loaded into the database (except names) - // We are ready to use names. - int counter = 0; - for ( namelist_t::iterator p=namelist.begin(); p != namelist.end(); ++p ) - { - ea_t ea = p->first; - // do not override name for COFF file - if ( pdbargs.is_pdbfile() || !has_name(get_flags(ea)) ) - { - if ( pdbargs.is_dbg_module() ) - counter += set_debug_name(ea, p->second.c_str()); - else - counter += force_name(ea, p->second.c_str()); - } - // Every now & then, make sure the UI has had a chance to refresh. - if ( (counter % 10) == 0 ) - user_cancelled(); - } - namelist.clear(); - msg("PDB: total %d symbol%s loaded for \"%s\"\n", - counter, - counter != 1 ? "s" : "", - pdbargs.input_path.c_str()); - } - - pdbnode.altset(PDB_DLLBASE_NODE_IDX, ok); - check_added_types(); - - // we have to restore the kill flag; otherwise the logic of the other parts - // of ida may change. for example, in the absence of DBFL_KILL we remember - // the idb path in the idb history (displayed in the File menu) - if ( restore_kill_flag ) - set_database_flag(DBFL_KILL); - - return ok; -} - -//---------------------------------------------------------------------------- -bool idaapi pdb_ctx_t::run(size_t _call_code) -{ - - - // PDB - pdbargs_t pdbargs; - if ( inf_get_filetype() != f_PE && !is_miniidb() ) - pdbargs.flags |= PDBFLG_ONLY_TYPES; - - netnode penode(PE_NODE); - penode.valobj(&pe, sizeof(pe)); - - bool ok = false; - switch ( (pdb_callcode_t)_call_code ) - { - case PDB_CC_USER: - // user explicitly invoked the plugin - ok = ask_pdb_details(&pdbargs); - // pdb_path, input_path: only one is set (depending on the file - // extension), the other is cleared - // loaded_base: specified by user (default obtained from PE) - break; - case PDB_CC_USER_WITH_DATA: - // user invoked the plugin programmatically - ok = get_details_from_netnode(&pdbargs); - // pdb_path, input_path: only one is set (depending on the file - // extension), the other is cleared - // loaded_base: specified by user - break; - case PDB_CC_IDA: - // IDA decided to call the plugin - ok = get_details_from_pe(&pdbargs); - // pdb_path: obtained from PE - // input_path: IDA's input file name - // loaded_base: obtained from PE - break; - default: - break; - } - - if ( ok ) - { - // read pdb signature from the database, if any - if ( !read_pdb_signature(&pdbargs.pdb_sign) ) - { - // make it invalid but not empty - // so that check_and_load_pdb() does not fail silently - pdbargs.pdb_sign.age = 0xFFFFFFFF; - } - - apply_debug_info(pdbargs); - } - - return true; -} - -//-------------------------------------------------------------------------- -void pdb_ctx_t::parse_options(bool *opt_skip) -{ - *opt_skip = false; - qstring opts(get_plugin_options("pdb")); - if ( opts.empty() ) - return; - char *opt = opts.begin(); - opt_provider = 0; - opt_fallback = -1; - do - { - char *end = qstrchr(opt, ':'); - if ( end != NULL ) - *end++ = '\0'; - - if ( streq(opt, "off") ) - { - *opt_skip = true; - } - else if ( streq(opt, "msdia") ) - { - opt_provider = PDB_PROVIDER_MSDIA; - } - else - { - error("AUTOHIDE NONE\n" - "Wrong option for the PDB plugin.\n" - "\n" - "The valid options are:\n" - "off do not load plugin\n" - "msdia use MSDIA provider\n"); - } - - if ( end == NULL ) - break; - opt = end; - } while ( true ); -} - -//-------------------------------------------------------------------------- -// initialize plugin -static plugmod_t *idaapi init() -{ - auto pv = std::unique_ptr<pdb_ctx_t>(new pdb_ctx_t); - bool opt_skip; - pv->parse_options(&opt_skip); - if ( opt_skip ) - return nullptr; - register_srcinfo_provider(pv->pdb_srcinfo_provider); - - auto plugmod = pv.release(); - set_module_data(&data_id, plugmod); - return plugmod; -} - -//-------------------------------------------------------------------------- -pdb_ctx_t::pdb_ctx_t() : ph(PH) -{ - memset(&pe, 0, sizeof(pe)); - alloc_pdb_srcinfo_provider(); - g_machine_type = CV_CFL_80386; -} - -//-------------------------------------------------------------------------- -// terminate -pdb_ctx_t::~pdb_ctx_t() -{ - namelist.clear(); - unregister_srcinfo_provider(pdb_srcinfo_provider); - free_pdb_srcinfo_provider(); - clr_module_data(data_id); - data_id = 0; -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MOD | PLUGIN_HIDE | PLUGIN_MULTI, // plugin flags: - init, // initialize - nullptr, // terminate. this pointer may be NULL. - nullptr, // invoke plugin - - // long comment about the plugin - // it could appear in the status line - // or as a hint - "Load debug information from a PDB file", - - // multiline help about the plugin - "PDB file loader\n" - "\n" - "This module allows you to load debug information about function names\n" - "from a PDB file.\n" - "\n" - "The PDB file should be in the same directory as the input file\n", - - // the preferred short name of the plugin - "Load PDB file (dbghelp 4.1+)", - // the preferred hotkey to run the plugin - "" -}; - - -//lint -esym(766, md5.h, diskio.hpp) Unused header files. diff --git a/idasdk75/plugins/pdb/pdb.hpp b/idasdk75/plugins/pdb/pdb.hpp deleted file mode 100644 index bbe62b2..0000000 --- a/idasdk75/plugins/pdb/pdb.hpp +++ /dev/null @@ -1,202 +0,0 @@ -// -// Copyright (c) 2005-2020 Hex-Rays SA <support@hex-rays.com> -// ALL RIGHTS RESERVED. -// -#pragma once -#include <idp.hpp> -#include <idd.hpp> -#include <typeinf.hpp> -#include "../../ldr/pe/pe.h" - -#define PDB_NODE_NAME "$ pdb" -#define PDB_DLLBASE_NODE_IDX 0 -#define PDB_DLLNAME_NODE_IDX 0 -#define PDB_LOADING_WIN32_DBG 1 -#define PDB_TYPESONLY_NODE_IDX 2 - -enum pdb_callcode_t -{ - // user invoked 'load pdb' command, load pdb for the input file. - // after invocation, result (boolean) is stored in: netnode(PDB_NODE_NAME).altval(PDB_DLLBASE_NODE_IDX) - PDB_CC_USER = 0, - // ida decided to call the plugin itself - PDB_CC_IDA = 1, - // load additional pdb. This is semantically the same as - // PDB_CC_USER (i.e., "File > Load file > PDB file..."), except - // it won't ask the user for the data; rather it expects it in - // netnode(PDB_NODE_NAME): - // load_addr: netnode(PDB_NODE_NAME).altval(PDB_DLLBASE_NODE_IDX) - // dll_name: netnode(PDB_NODE_NAME).supstr(PDB_DLLNAME_NODE_IDX) - PDB_CC_USER_WITH_DATA = 3, - // load debug info from the COFF file - // ida decided to call the plugin itself - // dbginfo_params_t: netnode(DBGINFO_PARAM_NODE_NAME).supval(DBGINFO_PARAMS_KEY) - PDB_CC_IDA_COFF = 4, -}; - -//---------------------------------------------------------------------- -struct pdb_signature_t -{ - uint32 guid[4]; // if all zeroes, then consider as non-existing - uint32 sig; - uint32 age; - pdb_signature_t(void) { memset(this, 0, sizeof(*this)); } -}; - -//---------------------------------------------------------------------------- -struct pdbargs_t -{ - qstring pdb_path; // Path to PDB file. - qstring input_path; // Path to PE file with associated PDB. - pdb_signature_t pdb_sign; - qstring spath; - ea_t loaded_base; - void *user_data; - uint32 flags; -#define PDBFLG_DBG_MODULE 0x01 -#define PDBFLG_ONLY_TYPES 0x02 -#define PDBFLG_EFD 0x04 -#define PDBFLG_COFF_FILE 0x08 - - pdbargs_t(void) - : loaded_base(BADADDR), - user_data(NULL), - flags(0) - {} - - // If true, we are in a debugging session and the file specified by - // input_path is an additional module that has been loaded by the - // debugger itself. - bool is_dbg_module(void) const - { - return (flags & PDBFLG_DBG_MODULE) != 0; - } - // PDB? - bool is_pdbfile(void) const { return (flags & PDBFLG_COFF_FILE) == 0; } - - const char *fname(void) const - { - return !pdb_path.empty() ? pdb_path.begin() : input_path.c_str(); - } -}; - -//---------------------------------------------------------------------------- -struct pdb_ctx_t : public plugmod_t -{ - processor_t &ph; - - // PDB search path (in _NT_SYMBOL_PATH format) - qstring full_sympath; - - peheader_t pe; - - // config options - int pdb_remote_port = DEBUGGER_PORT_NUMBER; - int pdb_remote_port_64 = -1; - qstring pdb_remote_server; - qstring pdb_remote_passwd; -#define PDB_PROVIDER_MSDIA 1 - uint pdb_provider = PDB_PROVIDER_MSDIA; - - // Plugin options - uint opt_provider = 0; - // -1 don't specified - // 0 set PDB_FALLBACK to false - // 1 set PDB_FALLBACK to true - int opt_fallback = -1; - - using namelist_t = std::map<ea_t, qstring>; - namelist_t namelist; - - // srcinfo provider - class pdb_provider_t *pdb_srcinfo_provider = nullptr; - - pdb_ctx_t(); - virtual ~pdb_ctx_t(); - virtual bool idaapi run(size_t arg) override; - - void parse_options(bool *opt_skip); - - void init_sympaths(); - void load_vc_til(void) const; - - // maybe_func: -1:no, 0-maybe, 1-yes, 2:no,but iscode - bool apply_name_in_idb(ea_t ea, const qstring &name, int maybe_func, uint32 the_machine_type); - bool apply_debug_info(pdbargs_t &pdbargs); - - // printable register name - bool get_pdb_register_info(int *p_reg, uint64 *p_mask, int machine, int reg); - - // Because we need to be able to call the 'old' pdb plugin - // code, which knows nothing about the til_builder_t (and - // thus its 'machine_type' field, and also because, at the - // very time we call the old pdb code, our til_builder_t - // instance will have been long forgotten and destroyed, - // we must keep this machine type information somewhere. - uint32 g_machine_type = 0; // will be set to CV_CFL_80386 in ctor - -private: - //------------------------------------------------------------------------- - int utf16_encidx = -1; - int get_utf16_encoding_idx(); - - bool checked_types = false; - bool has_sid = false; - bool check_for_ids(ea_t ea, const char *name, bool has_typeinfo); - - void alloc_pdb_srcinfo_provider(); - void free_pdb_srcinfo_provider(); - -public: - //------------------------------------------------------------------------- - //#define CHECK_CREATED_TYPES -#ifdef CHECK_CREATED_TYPES - struct type_to_check_t - { - // one of the following 3 will be valid: - ea_t ea; - int id; - qstring name; - - // the type itself - tinfo_t type; - }; - - qvector<type_to_check_t> types_to_check; - int check_n = 0; - - void check_tinfo(ea_t ea, int id, const char *name, const tinfo_t &tif) - { - type_to_check_t &tc = types_to_check.push_back(); - tc.ea = ea; - tc.id = id; - tc.name = name; - tc.type = tif; - } - - void check_added_types(void) - { - for ( const auto &tc : types_to_check ) - { - if ( !tc.type.is_correct() ) - { - msg("%d: INCORRECT TYPE ", check_n); - if ( !tc.name.empty() ) - msg("%s", tc.name.begin()); - else if ( tc.ea != BADADDR ) - msg("%a", tc.ea); - else - msg("#%d", tc.id); - qstring res; - tc.type.print(&res); - msg(": %s\n", res.c_str()); - check_n++; - } - } - } -#else - inline void check_tinfo(ea_t,int,const char*,const tinfo_t &) {} - inline void check_added_types(void) {} -#endif -}; -extern int data_id; diff --git a/idasdk75/plugins/pdb/pdbaccess.hpp b/idasdk75/plugins/pdb/pdbaccess.hpp deleted file mode 100644 index d0e8db8..0000000 --- a/idasdk75/plugins/pdb/pdbaccess.hpp +++ /dev/null @@ -1,664 +0,0 @@ - - -#ifndef PDBACCESS__H -#define PDBACCESS__H - -#include <set> -#include <map> - -#include <pro.h> -#include "cvconst.h" - -#ifdef __NT__ -#include <windows.h> -#include <oaidl.h> -#include "dia2.h" -#else -// FIXME: It'd be good if those windows declarations for non-windows -// systems were somewhere else than in the PE loader. -#include "../../ldr/pe/mycor.h" -#endif -#include "pdb.hpp" - -//---------------------------------------------------------------------------- -class pdb_access_t; -class local_pdb_access_t; -class remote_pdb_access_t; - -struct pdb_exception_t -{ - pdb_exception_t(const qstring &_what) : what(_what) {} - qstring what; -}; - -//---------------------------------------------------------------------------- -#ifdef __NT__ -enum sym_token_t : uint64 -#else -enum sym_token_t -#endif -{ - t_start = 1 << 0, - // bool - t_bool_start = t_start, - t_constType = t_bool_start, - t_isStatic = 1 << 1, - t_virtual = 1 << 2, - t_volatileType = 1 << 3, - t_code = 1 << 4, - t_hasAssignmentOperator = 1 << 5, - t_hasCastOperator = 1 << 6, - t_function = 1 << 7, // FIXME! - t_constructor = 1 << 8, - t_isVirtualBaseClass = 1 << 9, - t_bool_end = t_isVirtualBaseClass, - - // dword - t_dword_start = 1 << 10, - t_backEndMajor = t_dword_start, - t_baseType = 1 << 11, - t_bitPosition = 1 << 12, - t_callingConvention = 1 << 13, - t_count = 1 << 14, - t_dataKind = 1 << 15, - t_locationType = 1 << 16, - t_registerId = 1 << 17, - t_relativeVirtualAddress = 1 << 18, - t_symIndexId = 1 << 19, - t_symTag = 1 << 20, - t_udtKind = 1 << 21, - t_virtualBaseOffset = 1 << 22, - t_machineType = 1 << 23, - t_classParentId = 1 << 24, - t_typeId = 1 << 25, - t_lexicalParentId = 1 << 26, - t_dword_end = t_lexicalParentId, - - // dword64 - t_dword64_start = 1 << 27, - t_length = t_dword64_start, - t_dword64_end = t_length, - - // string - t_string_start = 1 << 28, - t_name = t_string_start, - t_string_end = t_name, - - // long - t_long_start = 1 << 29, - t_offset = t_long_start, - t_long_end = t_offset, - - // ulonglong - t_ulonglong_start = 1 << 30, - t_virtualAddress = t_ulonglong_start, - t_ulonglong_end = t_virtualAddress, - - // variant - t_variant_start = 1ULL << 31, - t_value = t_variant_start, - t_variant_end = t_value, - - t_end = 1ULL << 32, -}; -CASSERT(sizeof(sym_token_t) == 8); - -inline bool is_sym_token_bool(sym_token_t t) { return t >= t_bool_start && t <= t_bool_end; } -inline bool is_sym_token_dword(sym_token_t t) { return t >= t_dword_start && t <= t_dword_end; } -inline bool is_sym_token_dword64(sym_token_t t) { return t >= t_dword64_start && t <= t_dword64_end; } -// inline bool is_sym_token_pdb_sym(sym_token_t t) { return t >= t_pdb_sym_start && t <= t_pdb_sym_end; } -inline bool is_sym_token_string(sym_token_t t) { return t >= t_string_start && t <= t_string_end; } -inline bool is_sym_token_long(sym_token_t t) { return t >= t_long_start && t <= t_long_end; } -inline bool is_sym_token_ulonglong(sym_token_t t) { return t >= t_ulonglong_start && t <= t_ulonglong_end; } -inline bool is_sym_token_variant(sym_token_t t) { return t >= t_variant_start && t <= t_variant_end; } //-V560 is always true - - -typedef uint64 token_mask_t; -#define TOKEN_MASK_FULL token_mask_t(-1) - -//---------------------------------------------------------------------------- -// engine PDB symbol implementation identity -enum pdb_sym_id_t -{ - DIA_PDB_SYM, - REMOTE_PDB_SYM, - OWN_PDB_SYM, -}; - -//---------------------------------------------------------------------------- -struct pdb_sym_t -{ - virtual HRESULT get_backEndMajor(DWORD *out) = 0; - virtual HRESULT get_baseType(DWORD *out) = 0; - virtual HRESULT get_bitPosition(DWORD *out) = 0; - virtual HRESULT get_callingConvention(DWORD *out) = 0; - virtual HRESULT get_code(BOOL *out) = 0; - virtual HRESULT get_constructor(BOOL *out) = 0; - virtual HRESULT get_isVirtualBaseClass(BOOL *out) = 0; - virtual HRESULT get_constType(BOOL *out) = 0; - virtual HRESULT get_count(DWORD *out) = 0; - virtual HRESULT get_dataKind(DWORD *out) = 0; - virtual HRESULT get_function(BOOL *out) = 0; - virtual HRESULT get_hasAssignmentOperator(BOOL *out) = 0; - virtual HRESULT get_hasCastOperator(BOOL *out) = 0; - virtual HRESULT get_isStatic(BOOL *out) = 0; - virtual HRESULT get_length(DWORD64 *out) = 0; - virtual HRESULT get_lexicalParent(pdb_sym_t *out) = 0; - virtual HRESULT get_locationType(DWORD *out) = 0; - virtual HRESULT get_machineType(DWORD *out) = 0; - virtual HRESULT get_name(qstring *out) = 0; - virtual HRESULT get_offset(LONG *out) = 0; - virtual HRESULT get_registerId(DWORD *out) = 0; - virtual HRESULT get_relativeVirtualAddress(DWORD *out) = 0; - virtual HRESULT get_symIndexId(DWORD *out) = 0; - virtual HRESULT get_symTag(DWORD *out) = 0; - virtual HRESULT get_udtKind(DWORD *out) = 0; - virtual HRESULT get_value(VARIANT *out) = 0; - virtual HRESULT get_virtual(BOOL *out) = 0; - virtual HRESULT get_virtualAddress(ULONGLONG *out) = 0; - virtual HRESULT get_virtualBaseOffset(DWORD *out) = 0; - virtual HRESULT get_volatileType(BOOL *out) = 0; - // Be very, very careful to _not_ use classParent if you can avoid it: - // In case the symbol was *not* resolved through get_type(), the link - // to the parent might be lost, and a bug in the DIA SDK will - // return S_FALSE. - virtual HRESULT get_classParent(pdb_sym_t *out) = 0; - virtual HRESULT get_type(pdb_sym_t *out) = 0; - //------------------------------------------------------------ - virtual HRESULT get_ordinal(DWORD *pRetVal) = 0; - - // careful with this! - virtual void steal_data(pdb_sym_t &other) = 0; - - virtual pdb_sym_id_t whoami(void) = 0; - virtual bool empty(void) = 0; - - DEFINE_VIRTUAL_DTOR(pdb_sym_t) - - // Declare, but ***don't*** define: we don't want - // that to happen, and thus we'll have a linker - // error if that would happen in the code. - DECLARE_UNCOPYABLE(pdb_sym_t); - -protected: - pdb_sym_t() {} -}; -DECLARE_TYPE_AS_MOVABLE(pdb_sym_t); - -typedef janitor_t<pdb_sym_t*> pdb_sym_janitor_t; -template <> inline pdb_sym_janitor_t::~janitor_t() -{ - delete resource; - resource = NULL; -} - -//---------------------------------------------------------------------------- -enum packing_info_t -{ - SYMDAT_PACKED = 1, - SYMDAT_UNPACKED -}; - -//---------------------------------------------------------------------------- -struct sym_data_t -{ - sym_data_t(token_mask_t _tokens, const uchar *buf, size_t bufsize, packing_info_t _packing, bool *_warned); - ~sym_data_t(); - - DWORD get_id() const - { - DWORD id; - if ( get_dword(t_symIndexId, &id) != S_OK ) - INTERR(30211); - return id; - } - HRESULT get_bool(sym_token_t token, BOOL *out) const; - HRESULT get_dword(sym_token_t token, DWORD *out) const; - HRESULT get_dword64(sym_token_t token, DWORD64 *out) const; - HRESULT get_pdb_sym(sym_token_t token, pdb_sym_t *out) const; - HRESULT get_string(sym_token_t token, qstring *out) const; - HRESULT get_dword(sym_token_t token, LONG *out) const; - HRESULT get_ulonglong(sym_token_t token, ULONGLONG *out) const; - HRESULT get_variant(sym_token_t token, VARIANT *out) const; - -private: - sym_data_t(); - - bool token_present(sym_token_t token) const - { - return (present & token) == token; - } - - void assert_token(sym_token_t token) const - { - if ( !token_present(token) ) - INTERR(30210); - } - - const BOOL *bool_ptr(sym_token_t token) const - { - return (const BOOL *)any_ptr(token, t_bool_start, t_bool_end); - } - - const DWORD *dword_ptr(sym_token_t token) const - { - return (const DWORD *)any_ptr(token, t_dword_start, t_dword_end); - } - - const DWORD64 *dword64_ptr(sym_token_t token) const - { - return (const DWORD64 *)any_ptr(token, t_dword64_start, t_dword64_end); - } - - const LONG *long_ptr(sym_token_t token) const - { - return (const LONG *)any_ptr(token, t_long_start, t_long_end); - } - - const ULONGLONG *uint64_ptr(sym_token_t token) const - { - return (const ULONGLONG *)any_ptr(token, t_ulonglong_start, t_ulonglong_end); - } - - const char **string_ptr(sym_token_t token) const - { - return (const char **)any_ptr(token, t_string_start, t_string_end); - } - - const VARIANT *variant_ptr(sym_token_t token) const - { - return (const VARIANT *)any_ptr(token, t_variant_start, t_variant_end); - } - - enum type_t - { - t_bool = 0, - t_dword, - t_dword64, - t_string, - t_long, - t_ulonglong, - t_variant, - t_max - }; - - static const uint32 sizes[]; - - const void *any_ptr(sym_token_t token, sym_token_t start, sym_token_t end) const; - - token_mask_t present; // The tokens that are present in this instance. - bytevec_t data; - uint8 counters[t_max]; - - struct children_t - { - DWORD *ids; - uint32 cnt; - }; - children_t children_infos[SymTagMax]; - friend class remote_pdb_access_t; // accesses children_infos directly - bool *warned; -}; - - -//---------------------------------------------------------------------------- -#ifdef __NT__ -struct dia_pdb_sym_t : public pdb_sym_t -{ - dia_pdb_sym_t(pdb_access_t *_pdb_access, IDiaSymbol *_data, bool _own_sym) - : pdb_access(_pdb_access), - data(_data), - own_sym(_own_sym) - {} - - ~dia_pdb_sym_t() - { - if ( data != NULL && own_sym ) - { - data->Release(); - data = NULL; - } - pdb_access = NULL; - } - - pdb_access_t *pdb_access; - IDiaSymbol *data; - bool own_sym; - - pdb_sym_id_t whoami(void) { return DIA_PDB_SYM; } - void set_symbol_data(IDiaSymbol *s, bool own) - { - data = s; - own_sym = own; - } - bool empty(void) { return data == NULL; } - - HRESULT get_backEndMajor(DWORD *out) { return data->get_backEndMajor(out); } - HRESULT get_baseType(DWORD *out) { return data->get_baseType(out); } - HRESULT get_bitPosition(DWORD *out) { return data->get_bitPosition(out); } - HRESULT get_callingConvention(DWORD *out) { return data->get_callingConvention(out); } - HRESULT get_code(BOOL *out) { return data->get_code(out); } - HRESULT get_constType(BOOL *out) { return data->get_constType(out); } - HRESULT get_count(DWORD *out) { return data->get_count(out); } - HRESULT get_constructor(BOOL *out) { return data->get_constructor(out); } - HRESULT get_isVirtualBaseClass(BOOL *out) { return data->get_virtualBaseClass(out); } - HRESULT get_dataKind(DWORD *out) { return data->get_dataKind(out); } - HRESULT get_function(BOOL *out) { return data->get_function(out); } - HRESULT get_hasAssignmentOperator(BOOL *out) { return data->get_hasAssignmentOperator(out); } - HRESULT get_hasCastOperator(BOOL *out) { return data->get_hasCastOperator(out); } - HRESULT get_isStatic(BOOL *out) { return data->get_isStatic(out); } - HRESULT get_length(DWORD64 *out) { return data->get_length(out); } - HRESULT get_lexicalParent(pdb_sym_t *out) - { - IDiaSymbol *t; - HRESULT res = data->get_lexicalParent(&t); - return handle_related_symbol(res, t, out); - } - HRESULT get_locationType(DWORD *out) { return data->get_locationType(out); } - HRESULT get_machineType(DWORD *out) { return data->get_machineType(out); } - HRESULT get_name(qstring *out) - { - BSTR name; - HRESULT hr = data->get_name(&name); - return maybe_convert_bstr(out, hr, &name); - } - HRESULT get_offset(LONG *out) { return data->get_offset(out); } - HRESULT get_registerId(DWORD *out) { return data->get_registerId(out); } - HRESULT get_relativeVirtualAddress(DWORD *out) { return data->get_relativeVirtualAddress(out); } - HRESULT get_symIndexId(DWORD *out) { return data->get_symIndexId(out); } - HRESULT get_symTag(DWORD *out) { return data->get_symTag(out); } - HRESULT get_udtKind(DWORD *out) { return data->get_udtKind(out); } - HRESULT get_value(VARIANT *out) { return data->get_value(out); } - HRESULT get_virtual(BOOL *out) { return data->get_virtual(out); } - HRESULT get_virtualAddress(ULONGLONG *out) { return data->get_virtualAddress(out); } - HRESULT get_virtualBaseOffset(DWORD *out) { return data->get_virtualBaseOffset(out); } - HRESULT get_volatileType(BOOL *out) { return data->get_volatileType(out); } - HRESULT get_classParent(pdb_sym_t *out) - { - IDiaSymbol *t; - HRESULT res = data->get_classParent(&t); - return handle_related_symbol(res, t, out); - } - - HRESULT get_type(pdb_sym_t *out) - { - IDiaSymbol *t; - HRESULT res = data->get_type(&t); - return handle_related_symbol(res, t, out); - } - - //------------------------------------------------------------ - virtual HRESULT get_ordinal(DWORD *) override { return S_FALSE; } - - HRESULT handle_related_symbol(HRESULT fetch_success, IDiaSymbol *t, pdb_sym_t *out) - { - if ( out == NULL ) - return S_FALSE; - QASSERT(30545, out->whoami() == DIA_PDB_SYM); - dia_pdb_sym_t *sym = (dia_pdb_sym_t *)out; - sym->set_symbol_data(fetch_success == S_OK ? t : NULL, true); - return fetch_success; - } - - // careful with this! - void steal_data(pdb_sym_t &other) - { - QASSERT(30541, whoami() == other.whoami()); - dia_pdb_sym_t &other_dia = (dia_pdb_sym_t &)other; - QASSERT(30503, other_dia.own_sym && other_dia.data != NULL && data == NULL); - data = other_dia.data; - own_sym = true; - other_dia.own_sym = false; - other_dia.data = NULL; - } - -private: - dia_pdb_sym_t(); - - HRESULT maybe_convert_bstr(qstring *out, HRESULT hr, BSTR *s) - { - if ( hr == S_OK ) - { - utf16_utf8(out, *s); - SysFreeString(*s); - } - return hr; - } -}; -DECLARE_TYPE_AS_MOVABLE(dia_pdb_sym_t); - -//---------------------------------------------------------------------------- -#else // __NT__ -struct remote_pdb_sym_t : public pdb_sym_t -{ - remote_pdb_sym_t(pdb_access_t *_pdb_access, sym_data_t *_data) - : pdb_access(_pdb_access), - data(_data) - {} - - ~remote_pdb_sym_t() - { - data = NULL; - pdb_access = NULL; - } - - void set_symbol_data(sym_data_t *s) { data = s; } - - HRESULT get_backEndMajor(DWORD *out) override { return data->get_dword(t_backEndMajor, out); } - HRESULT get_baseType(DWORD *out) override { return data->get_dword(t_baseType, out); } - HRESULT get_bitPosition(DWORD *out) override { return data->get_dword(t_bitPosition, out); } - HRESULT get_callingConvention(DWORD *out) override { return data->get_dword(t_callingConvention, out); } - HRESULT get_code(BOOL *out) override { return data->get_bool(t_code, out); } - HRESULT get_constructor(BOOL *out) override { return data->get_bool(t_constructor, out); } - HRESULT get_isVirtualBaseClass(BOOL *out) override { return data->get_bool(t_isVirtualBaseClass, out); } - HRESULT get_constType(BOOL *out) override { return data->get_bool(t_constType, out); } - HRESULT get_count(DWORD *out) override { return data->get_dword(t_count, out); } - HRESULT get_dataKind(DWORD *out) override { return data->get_dword(t_dataKind, out); } - HRESULT get_function(BOOL *out) override { return data->get_bool(t_function, out); } - HRESULT get_hasAssignmentOperator(BOOL *out) override { return data->get_bool(t_hasAssignmentOperator, out); } - HRESULT get_hasCastOperator(BOOL *out) override { return data->get_bool(t_hasCastOperator, out); } - HRESULT get_isStatic(BOOL *out) override { return data->get_bool(t_isStatic, out); } - HRESULT get_length(DWORD64 *out) override { return data->get_dword64(t_length, out); } - HRESULT get_lexicalParent(pdb_sym_t *out) override; - HRESULT get_locationType(DWORD *out) override { return data->get_dword(t_locationType, out); } - HRESULT get_machineType(DWORD *out) override { return data->get_dword(t_machineType, out); } - HRESULT get_name(qstring *out) override { return data->get_string(t_name, out); } - HRESULT get_offset(LONG *out) override { return data->get_dword(t_offset, out); } - HRESULT get_registerId(DWORD *out) override { return data->get_dword(t_registerId, out); } - HRESULT get_relativeVirtualAddress(DWORD *out) override { return data->get_dword(t_relativeVirtualAddress, out); } - HRESULT get_symIndexId(DWORD *out) override { return data->get_dword(t_symIndexId, out); } - HRESULT get_symTag(DWORD *out) override { return data->get_dword(t_symTag, out); } - HRESULT get_udtKind(DWORD *out) override { return data->get_dword(t_udtKind, out); } - HRESULT get_value(VARIANT *out) override { return data->get_variant(t_value, out); } - HRESULT get_virtual(BOOL *out) override { return data->get_bool(t_virtual, out); } - HRESULT get_virtualAddress(ULONGLONG *out) override { return data->get_ulonglong(t_virtualAddress, out); } - HRESULT get_virtualBaseOffset(DWORD *out) override { return data->get_dword(t_virtualBaseOffset, out); } - HRESULT get_volatileType(BOOL *out) override { return data->get_bool(t_volatileType, out); } - HRESULT get_classParent(pdb_sym_t *out) override; - HRESULT get_type(pdb_sym_t *out) override; - //------------------------------------------------------------ - virtual HRESULT get_ordinal(DWORD *) override { return S_FALSE; } - - // careful with this! - void steal_data(pdb_sym_t &other) override - { - QASSERT(30542, whoami() == other.whoami()); - remote_pdb_sym_t &other_rem = (remote_pdb_sym_t &)other; - QASSERT(30492, other_rem.data != NULL && data == NULL); - data = other_rem.data; - // we don't want to set 'other.data = NULL', because in remote access, - // the pdb_sym_t doesn't actually own the data anyway: it's part of - // the cache. - } - - pdb_sym_id_t whoami(void) override { return REMOTE_PDB_SYM; } - bool empty(void) override { return data == NULL; } - - pdb_access_t *pdb_access; - sym_data_t *data; - -private: - remote_pdb_sym_t(); -}; -DECLARE_TYPE_AS_MOVABLE(remote_pdb_sym_t); -#endif // !__NT__ - -//---------------------------------------------------------------------------- -#define BAD_MACHINE_TYPE ((uint32) -1) - -#define BADSYM ((uint32) -1) - -//------------------------------------------------------------------------- -struct pdb_lnnum_t -{ - pdb_lnnum_t() - : va(BADADDR), length(0), - columnNumber(0), columnNumberEnd(0), - lineNumber(0), lineNumberEnd(0), - file_id(DWORD(-1)), statement(0) {} - ULONGLONG va; - DWORD length; - DWORD columnNumber; - DWORD columnNumberEnd; - DWORD lineNumber; - DWORD lineNumberEnd; - DWORD file_id; - BOOL statement; -}; - -//-------------------------------------------------------------------------- -typedef qvector<pdb_lnnum_t> pdb_lnnum_vec_t; -typedef std::map<int, pdb_lnnum_vec_t> lnmap_t; - -//------------------------------------------------------------------------- -struct pdb_lnnums_t : pdb_lnnum_vec_t -{ - pdb_lnnums_t() : inited(false) {} - - bool get_item_bounds(rangeset_t *set) const; - int get_lnnum() const; - int get_colnum() const; - int get_end_lnnum() const; - int get_end_colnum() const; - - bool inited; -}; - -//---------------------------------------------------------------------------- -class pdb_access_t -{ -public: - pdb_access_t(const pdbargs_t &args) - : pdbargs(args), - machine_type((uint32) -1), - dia_version(0), - base_address(BADADDR), - global_sym_id(BADSYM) - { - } - DEFINE_VIRTUAL_DTOR(pdb_access_t); - - //---------------------------------------------------------------------- - struct children_visitor_t - { - children_visitor_t() - : parent(NULL) {} - - virtual HRESULT visit_child(pdb_sym_t &child) = 0; - virtual ~children_visitor_t() {} - - pdb_sym_t *parent; - }; - - //------------------------------------------------------------------------- - struct dummy_visitor_t : public children_visitor_t - { - virtual HRESULT visit_child(pdb_sym_t &) override { return S_OK; } - }; - - //---------------------------------------------------------------------------- - HRESULT iterate_children( - pdb_sym_t &sym, - enum SymTagEnum type, - children_visitor_t &visitor); - - //---------------------------------------------------------------------------- - virtual HRESULT do_iterate_children( - pdb_sym_t &sym, - enum SymTagEnum type, - children_visitor_t &visitor) = 0; - virtual HRESULT iterate_subtags( - pdb_sym_t &sym, - enum SymTagEnum type, - children_visitor_t &visitor); - virtual HRESULT load(pdb_sym_t &sym, DWORD id) = 0; - - // source-level debugging-specific - virtual HRESULT sip_retrieve_lines_by_va( - pdb_lnnums_t *out, - ULONGLONG va, - ULONGLONG length) = 0; - virtual HRESULT sip_retrieve_lines_by_coords( - pdb_lnnums_t *out, - DWORD file_id, - int lnnum, - int colnum) = 0; - virtual HRESULT sip_iterate_symbols_at_ea( - ULONGLONG va, - ULONGLONG size, - enum SymTagEnum tag, - children_visitor_t &visitor) = 0; - virtual HRESULT sip_iterate_file_compilands( - DWORD file_id, - children_visitor_t &visitor) = 0; - virtual HRESULT sip_retrieve_file_path( - qstring *out, - qstring *errbuf, - DWORD file_id) = 0; - virtual HRESULT sip_retrieve_symbol_files( - qvector<DWORD> *out, - pdb_sym_t &sym) = 0; - virtual HRESULT sip_find_files( - qvector<DWORD> *out, - const char *filename) = 0; // case insensitive search - // /source-level debugging-specific - - //---------------------------------------------------------------------------- - virtual DWORD get_global_symbol_id() const { return global_sym_id; } - virtual ea_t get_base_address() const { return base_address; } - virtual uint32 get_machine_type() const { return machine_type; } - virtual int get_dia_version() const { return dia_version; } - - void set_global_symbol_id(DWORD _global_sym_id) { global_sym_id = _global_sym_id; } - void set_machine_type(uint32 _machine_type) { machine_type = _machine_type; } - void set_base_address(ea_t _base_address) { base_address = _base_address; } - void set_dia_version(int _dia_version) { dia_version = _dia_version; } - - //---------------------------------------------------------------------------- - virtual pdb_sym_t *create_sym(void *data=NULL, bool own=false) = 0; - pdb_sym_t *create_sym(DWORD sym_id) - { - pdb_sym_t *sym = create_sym(); - if ( load(*sym, sym_id) != S_OK ) - { - qstring err; - err.sprnt("Failed loading symbol data for ID %u", sym_id); - delete sym; - throw pdb_exception_t(err.c_str()); - } - return sym; - } - - //---------------------------------------------------------------------------- - const pdbargs_t &pdbargs; - -private: - uint32 machine_type; - int dia_version; - ea_t base_address; - DWORD global_sym_id; - DECLARE_UNCOPYABLE(pdb_access_t) -}; - - -#endif // PDBACCESS__H diff --git a/idasdk75/plugins/pdb/pdbremote.hpp b/idasdk75/plugins/pdb/pdbremote.hpp deleted file mode 100644 index f401c4b..0000000 --- a/idasdk75/plugins/pdb/pdbremote.hpp +++ /dev/null @@ -1,164 +0,0 @@ - -#ifndef PDBREMOTE_HPP -#define PDBREMOTE_HPP - -#include <map> -#include <network.hpp> -#include "../../dbg/win32/win32_rpc.h" -#include "pdbaccess.hpp" - -// The PDB related code that works on Unix -// It connects to a Windows computer and asks to retrieve PDB info - -//---------------------------------------------------------------------------- -bool is_win32_remote_debugger_loaded(); - -//---------------------------------------------------------------------------- -//-V:remote_pdb_access_t:730 not all members of a class are initialized inside the constructor -class remote_pdb_access_t : public pdb_access_t -{ -public: - remote_pdb_access_t( - const pdbargs_t &args, - const char *_host, - int _port, - const char *_pwd) - : pdb_access_t(args), - host(_host), - port(_port), - pwd(_pwd), - remote_session_id(-1) - { - set_base_address(args.loaded_base); - } - - virtual ~remote_pdb_access_t(); - - // Open connection, create PDB session. - HRESULT open_connection(); - // Close PDB session, close connection. - void close_connection(); - - virtual HRESULT do_iterate_children( - pdb_sym_t &sym, - enum SymTagEnum type, - children_visitor_t &visitor) override; - virtual HRESULT load(pdb_sym_t &sym, DWORD id) override; - - virtual HRESULT sip_retrieve_lines_by_va( - pdb_lnnums_t *out, - ULONGLONG va, - ULONGLONG length) override; - virtual HRESULT sip_retrieve_lines_by_coords( - pdb_lnnums_t *out, - DWORD file_id, - int lnnum, - int colnum) override; - virtual HRESULT sip_iterate_symbols_at_ea( - ULONGLONG va, - ULONGLONG size, - enum SymTagEnum tag, - children_visitor_t &visitor) override; - virtual HRESULT sip_iterate_file_compilands( - DWORD file_id, - children_visitor_t &visitor) override; - virtual HRESULT sip_retrieve_file_path( - qstring *out, - qstring *errbuf, - DWORD file_id) override; - virtual HRESULT sip_retrieve_symbol_files( - qvector<DWORD> *out, - pdb_sym_t &sym) override; - virtual HRESULT sip_find_files( - qvector<DWORD> *out, - const char *name) override; - - virtual pdb_sym_t *create_sym(void *data, bool) override - { - sym_data_t *sym = (sym_data_t *)data; - return new remote_pdb_sym_t(this, sym); - } - pdb_sym_t *create_sym(DWORD sym_id) { return pdb_access_t::create_sym(sym_id); } - - // Possibly remote operation. - // If NULL is returned, it means the symbol is not available, nor - // could it be fetched remotely. - ioctl_pdb_code_t get_sym_data(pdb_sym_t &sym, sym_data_t **); - ioctl_pdb_code_t get_sym_data(DWORD sym_id, sym_data_t **); - - -private: - HRESULT _do_iterate_symbols_ids( - const DWORD *ids, - size_t count, - enum SymTagEnum type, - children_visitor_t &visitor); - -#define SAFE_GET(type) \ - sym_data_t *sym_data; \ - ioctl_pdb_code_t result = get_sym_data(sym, &sym_data); \ - if ( result == pdb_ok ) \ - return sym_data->get_##type(token, out); \ - else \ - return E_FAIL - - // Build sym_data_t instance, and register it into the 'cache'. - DWORD build_and_register_sym_data(const uchar **raw, const uchar *end); - - // Whenever fetch_children_infos() or get_sym_data() performs - // a remote operation, this is used to handle the response - // and add the fetched symbol data to the cache. - void handle_fetch_response( - const uchar **ptr, - const uchar *end, - qvector<DWORD> *ids_storage); - - // Remote operation. - ioctl_pdb_code_t fetch_children_infos( - pdb_sym_t &sym, - enum SymTagEnum type, - qvector<DWORD> *children_ids); - - HRESULT handle_fetch_lnnums( - pdb_lnnums_t *out, - const bytevec_t &resp) const; - - HRESULT handle_fetch_file_ids( - qvector<DWORD> *out, - const bytevec_t &resp) const; - - sym_data_t *get_sym_data_from_cache(DWORD id); - - // Low-level interface used by open_connection(), fetch_children_infos(), and get_sym_data(). - // 'fetch_type' is one of - // WIN32_IOCTL_PDB_OPEN, - // WIN32_IOCTL_PDB_FETCH_SYMBOL, - // WIN32_IOCTL_PDB_FETCH_CHILDREN - ioctl_pdb_code_t perform_op(int op_type, const bytevec_t &oper, void *data); - - ioctl_pdb_code_t send_ioctl( - int fn, - const void *buf, - size_t size, - void **poutbuf, - ssize_t *poutsize); - - std::map<DWORD, sym_data_t*> cache; - const char *user_spath; - char errbuf[MAXSTR]; - - // For the moment, we'll channel all IOCTL requests - // through the debugger. Ideally, we should be able to just - // use a RPC client. - bool load_win32_debugger(void); - - const char *host; - int port; - const char *pwd; - bool was_connected; - bool is_dbg_module; - int remote_session_id; - bool warned = false; -}; - -#endif // PDBREMOTE_HPP diff --git a/idasdk75/plugins/pdb/tilbuild.cpp b/idasdk75/plugins/pdb/tilbuild.cpp deleted file mode 100644 index 9c2449a..0000000 --- a/idasdk75/plugins/pdb/tilbuild.cpp +++ /dev/null @@ -1,2378 +0,0 @@ - -#include <algorithm> - -#include "tilbuild.hpp" -#include "misc.cpp" - -//#define PDEB -//#define PDEBSYM -#ifdef PDEB -#define ddeb(x) _ddeb x -AS_PRINTF(1, 2) inline void _ddeb(const char *format, ...) -{ - va_list va; - va_start(va, format); - vmsg(format, va); - va_end(va); -} -#else -#define ddeb(x) (void)0 -#endif -#ifndef TESTABLE_BUILD -#undef PDEB -#undef PDEBSYM -#endif - -static const char fake_vtable_type[] = "$vt"; - -//---------------------------------------------------------------------------- -void til_builder_t::remove_anonymous_namespaces(qstring &buf) -{ - char *p = buf.begin(); - while ( true ) - { // 1234567890 - p = strstr(p, "`anonymous"); - if ( p == NULL ) - break; - const char *q = p + 10; - if ( *q != '-' && *q != ' ' ) - break; - if ( strncmp(q+1, "namespace'::", 12) != 0 ) - break; // 123456789012 - size_t idx = p - buf.begin(); - buf.remove(idx, 10+1+12); - p = buf.begin() + idx; - } -} - -//------------------------------------------------------------------------- -static inline bool ident_char(char c) -{ - return c == '_' || qisalnum(c); -} - -//---------------------------------------------------------------------------- -bool til_builder_t::get_symbol_name(pdb_sym_t &sym, qstring &buf) -{ - bool is_unnamed = false; - sym.get_name(&buf); - if ( buf.empty() ) - { - is_unnamed = true; - } - else - { - // - remove_anonymous_namespaces(buf); - - // <unnamed-tag> => <unnamed_tag> - // <unnamed-type-xxx> => <unnamed_type_xxx> - char *p = buf.begin(); - while ( true ) - { - // 012345678 - p = strstr(p, "<unnamed"); - if ( p == NULL ) - break; - if ( p == buf.begin() ) - is_unnamed = true; - p += 8; - while ( *p != '\0' ) - { - if ( *p == '>' ) - { - p++; - break; - } - else if ( *p == '-' ) - { - *p = '_'; - } - p++; - } - } - if ( !is_unnamed ) - { - const char *marker = strstr(buf.begin(), "__unnamed"); - if ( marker != NULL - // Is prev char not a valid identifier char? - && (marker == buf.begin() || !ident_char(marker[-1])) - // Is next char not a valid identifier char? - && !ident_char(marker[9]) ) - { - is_unnamed = true; - } - } - } - return is_unnamed; -} - -//---------------------------------------------------------------------------- -bool til_builder_t::get_symbol_type(tpinfo_t *out, pdb_sym_t &sym, int *p_id) -{ -#ifdef PDEBSYM - static int zz=0; ++zz; - int zzz = zz; - qstring sym_name; - sym.get_name(&sym_name); - DWORD sym_id = 0; - sym.get_symIndexId(&sym_id); - msg("PDEB: %d: get_symbol_type sym_id=%d '%s'\n", zzz, sym_id, sym_name.c_str()); -#endif - pdb_sym_t *pType = pdb_access->create_sym(); - pdb_sym_janitor_t janitor_pType(pType); - if ( p_id != NULL ) - *p_id = -1; - if ( sym.get_type(pType) != S_OK ) - return false; - bool ok = retrieve_type(out, *pType, NULL, p_id); -#ifdef PDEBSYM - DWORD typsym_id = 0; - pType->get_symIndexId(&typsym_id); - msg("PDEB: %d: get_symbol_type typsym_id=%d tif='%s' ok=%d\n", zzz, typsym_id, out->type.dstr(), ok); -#endif - return ok; -} - -//---------------------------------------------------------------------------- -size_t til_builder_t::get_symbol_type_length(pdb_sym_t &sym) const -{ - DWORD64 size = 0; - DWORD tag = 0; - - sym.get_symTag(&tag); - if ( tag == SymTagData ) - { - pdb_sym_t *pType = pdb_access->create_sym(); - pdb_sym_janitor_t janitor_pType(pType); - if ( sym.get_type(pType) == S_OK ) - pType->get_length(&size); - } - else - { - sym.get_length(&size); - } - return size_t(size); -} - -//---------------------------------------------------------------------- -cvt_code_t til_builder_t::convert_basetype( - tpinfo_t *out, - DWORD baseType, - int size) const -{ - type_t bt = BTF_TYPEDEF; - const char *name = NULL; - switch ( baseType ) - { - case btNoType: - out->is_notype = true; - // Fallthrough. - default: - case 0x12c304: // "impdir_entry" (guessed) - case btBCD: - case btBit: - return cvt_failed; - case btVoid: - bt = BTF_VOID; - break; - case btChar: - bt = BT_INT8|BTMT_CHAR; - break; - case btBool: - bt = BT_BOOL; - if ( size != inf_get_cc_size_b() ) - { - switch ( size ) - { - case 1: - bt |= BTMT_BOOL1; - break; - case 2: - if ( inf_is_64bit() ) - goto MAKE_INT; // 64bit apps do not have BOOL2 - bt |= BTMT_BOOL2; - break; - case 4: - bt |= BTMT_BOOL4; - break; - case 8: - if ( !inf_is_64bit() ) - goto MAKE_INT; // 32bit apps do not have BOOL8 - bt |= BTMT_BOOL8; - break; - default: - // can't make this bool size; make an int - goto MAKE_INT; - } - } - break; -MAKE_INT: - case btInt: - case btLong: - bt = get_scalar_bt(size); - break; - case btUInt: - case btULong: - if ( size == 1 ) - bt = BTF_UCHAR; // get_scalar_bt returns 'char', or'ing it with BTMT_USIGNED - else // does not help - bt = get_scalar_bt(size)|BTMT_USIGNED; - break; - case btFloat: - if ( size == pv.ph.sizeof_ldbl() ) - { - bt = BTMT_LNGDBL; - } - else - { - switch ( size ) - { - case 4: bt = BTMT_FLOAT; break; - default: - case 8: bt = BTMT_DOUBLE; break; - case 10: bt = BTMT_SPECFLT; break; - } - } - bt |= BT_FLOAT; - break; - case btWChar: name = "wchar_t"; break; - case btBSTR: name = "BSTR"; break; - case btHresult: name = "HRESULT"; break; - case btCurrency: name = "CURRENCY"; break; - case btVariant: name = "VARIANT"; break; - case btComplex: name = "complex"; break; - case btDate: name = "DATE"; break; - } - if ( name != NULL ) - { - out->type.create_typedef(ti, name); - return cvt_typedef; - } - else - { - out->type = tinfo_t(bt); - return cvt_ok; - } -} - -//---------------------------------------------------------------------- -bool til_builder_t::retrieve_arguments( - pdb_sym_t &_sym, - func_type_data_t &fi, - pdb_sym_t *funcSym) -{ - struct type_name_collector_t : public pdb_access_t::children_visitor_t - { - func_type_data_t &fi; - til_builder_t *tb; - til_t *ti; - HRESULT visit_child(pdb_sym_t &sym) override - { - // check that it's a parameter - DWORD dwDataKind; - if ( sym.get_dataKind(&dwDataKind) == S_OK - && dwDataKind != DataIsParam - && dwDataKind != DataIsObjectPtr ) - { - return S_OK; - } - tpinfo_t tpi; - bool cvt_succeeded = tb->retrieve_type(&tpi, sym, parent, NULL); - if ( cvt_succeeded || tpi.is_notype ) - { - funcarg_t &arg = fi.push_back(); - arg.type = tpi.type; - sym.get_name(&arg.name); - } - return S_OK; - } - type_name_collector_t(til_t *_ti, til_builder_t *_tb, func_type_data_t &_fi) - : fi(_fi), tb(_tb), ti(_ti) {} - }; - fi.clear(); - type_name_collector_t pp(ti, this, fi); - HRESULT hr = pdb_access->iterate_children(_sym, SymTagNull, pp); - if ( hr == S_OK && funcSym != NULL ) - { - // get parameter names from the function symbol - func_type_data_t args; - args.flags = 0; - enum_function_args(*funcSym, args); -// QASSERT(497, args.empty() || args.size() == fi.size() ); - bool custom_cc = false; - for ( int i = 0; i < fi.size(); i++ ) - { - if ( i < args.size() ) - { - if ( fi[i].name.empty() ) - fi[i].name = args[i].name; - argloc_t &cur_argloc = args[i].argloc; - fi[i].argloc = cur_argloc; - if ( !custom_cc && cur_argloc.is_reg1() ) - { - if ( is_intel386(pdb_access->get_machine_type()) ) - { - if ( fi.cc == CM_CC_FASTCALL - && cur_argloc.regoff() == 0 - && (cur_argloc.reg1() == R_cx && i == 0 - || cur_argloc.reg1() == R_dx && i == 1) ) - { - // ignore ecx and edx for fastcall - } - else if ( fi.cc == CM_CC_THISCALL - && cur_argloc.regoff() == 0 - && cur_argloc.reg1() == R_cx && i == 0 ) - { - // ignore ecx for thiscall - } - else - { - custom_cc = true; - } - } - } - //ask_for_feedback("pdb: register arguments are not supported for machine type %d", machine_type); - } - } - if ( custom_cc ) - { - // we have some register params; need to convert function to custom cc - fi.cc = (is_purging_cc(fi.cc) || fi.cc == CM_CC_THISCALL || fi.cc == CM_CC_FASTCALL) - ? CM_CC_SPECIALP - : CM_CC_SPECIAL; - } - return true; - } - return false; -} - -//---------------------------------------------------------------------- -cm_t til_builder_t::convert_cc(DWORD cc0) const -{ - switch ( cc0 ) - { - case CV_CALL_GENERIC : - case CV_CALL_NEAR_C : - case CV_CALL_FAR_C : - return inf_is_64bit() ? CM_CC_FASTCALL : CM_CC_CDECL; - case CV_CALL_NEAR_PASCAL: - case CV_CALL_FAR_PASCAL : return CM_CC_PASCAL; - case CV_CALL_NEAR_FAST : - case CV_CALL_FAR_FAST : return CM_CC_FASTCALL; -// case CV_CALL_SKIPPED : - case CV_CALL_NEAR_STD : - case CV_CALL_FAR_STD : - case CV_CALL_ARMCALL : return CM_CC_STDCALL; - case CV_CALL_THISCALL : return CM_CC_THISCALL; -// case CV_CALL_NEAR_SYS : -// case CV_CALL_FAR_SYS : -// case CV_CALL_MIPSCALL : -// case CV_CALL_ALPHACALL : -// case CV_CALL_PPCCALL : -// case CV_CALL_SHCALL : -// case CV_CALL_ARMCALL : -// case CV_CALL_AM33CALL : -// case CV_CALL_TRICALL : -// case CV_CALL_SH5CALL : -// case CV_CALL_M32RCALL : - } - return CM_CC_UNKNOWN; -} - -//---------------------------------------------------------------------- -bool til_builder_t::get_variant_string_value(qstring *out, pdb_sym_t &sym) const -{ - bool ok = false; - VARIANT value; - VariantInit(&value); - if ( sym.get_value(&value) == S_OK ) - { - if ( value.vt == VT_BSTR ) - { - utf16_utf8(out, (wchar16_t*) value.bstrVal); - ok = true; - } - else if ( value.vt == VT_LPSTR ) - { - qstring str((const char *)value.byref); - out->swap(str); - ok = true; - } - } - VariantClear(&value); - return ok; -} - -//---------------------------------------------------------------------- -uint32 til_builder_t::get_variant_long_value(pdb_sym_t &sym) const -{ - uint32 v = 0; - VARIANT value; - VariantInit(&value); - if ( sym.get_value(&value) == S_OK ) - { - switch ( value.vt ) - { - case VT_I1: v = value.cVal; break; - case VT_I2: v = value.iVal; break; - case VT_I4: v = value.lVal; break; - case VT_I8: v = value.llVal; break; - case VT_INT: v = value.intVal; break; - case VT_UI1: v = value.bVal; break; - case VT_UI2: v = value.uiVal; break; - case VT_UI4: v = value.ulVal; break; - case VT_UI8: v = value.ullVal; break; - case VT_UINT: v = value.uintVal; break; - default: - ask_for_feedback("pdb: unsupported VARIANT type %d", value.vt); - break; - } - } - VariantClear(&value); - return v; -} - -//---------------------------------------------------------------------- -// funcSym is Function, typeSym is FunctionType -bool til_builder_t::is_member_func(tinfo_t *class_type, pdb_sym_t &typeSym, pdb_sym_t *funcSym) -{ - // make sure we retrieve class type first - pdb_sym_t *pParent = pdb_access->create_sym(); - pdb_sym_janitor_t janitor_pParent(pParent); - if ( typeSym.get_classParent(pParent) != S_OK || pParent->empty() ) - return false; - - tpinfo_t tpi; - if ( !retrieve_type(&tpi, *pParent, NULL, NULL) ) - return false; // failed to retrieve the parent's type - - class_type->swap(tpi.type); - - // then check if it's static - if ( funcSym != NULL - && pdb_access->get_dia_version() >= 800 ) - { - BOOL bIsStatic = false; - HRESULT hr = funcSym->get_isStatic(&bIsStatic); - if ( hr == S_OK ) - return !bIsStatic; - } - return true; -} - -//---------------------------------------------------------------------------- -bool til_builder_t::is_intel386(DWORD machine_type) const -{ - return machine_type == CV_CFL_80386 - || machine_type == CV_CFL_80486 - || machine_type == CV_CFL_PENTIUM - || machine_type == CV_CFL_PENTIUMII - || machine_type == CV_CFL_PENTIUMIII; -} - -//---------------------------------------------------------------------------- -bool til_builder_t::is_arm(DWORD machine_type) const -{ - return machine_type == CV_CFL_ARM3 - || machine_type == CV_CFL_ARM4 - || machine_type == CV_CFL_ARM4T - || machine_type == CV_CFL_ARM5 - || machine_type == CV_CFL_ARM5T - || machine_type == CV_CFL_ARM6 - || machine_type == CV_CFL_ARM7 - || machine_type == CV_CFL_ARMNT - || machine_type == CV_CFL_ARM_XMAC - || machine_type == CV_CFL_ARM_WMMX - || machine_type == CV_CFL_THUMB; -} - -//---------------------------------------------------------------------- -bool til_builder_t::is_frame_reg(int reg) const -{ - if ( is_intel386(pdb_access->get_machine_type()) ) - return reg == CV_REG_EBP; - else if ( is_arm(pdb_access->get_machine_type()) ) - return reg == CV_ARM_R11 || reg == CV_ARM_SP; - return false; -} - -//---------------------------------------------------------------------------- -int til_builder_t::get_symbol_funcarg_info( - funcarg_t *out, - pdb_sym_t &sym, - DWORD /*dwDataKind*/, - DWORD locType, - int stack_off) -{ - sym.get_name(&out->name); - tpinfo_t tpi; - get_symbol_type(&tpi, sym, NULL); - out->type = tpi.type; - if ( locType == LocIsEnregistered ) - { - DWORD dwReg; - if ( sym.get_registerId(&dwReg) == S_OK ) - { - if ( enregistered_bug && dwReg > 0 ) - dwReg--; - qstring regname; - print_pdb_register(®name, pdb_access->get_machine_type(), dwReg); - out->argloc._set_reg1(str2reg(regname.c_str())); - } - } - else if ( locType == LocIsRegRel ) - { - DWORD dwReg; - LONG lOffset; - if ( sym.get_registerId(&dwReg) == S_OK - && sym.get_offset(&lOffset) == S_OK - && is_frame_reg(dwReg) ) - { - uint32 align; - out->argloc._set_stkoff(stack_off); - size_t argsz = out->type.get_size(&align); - if ( align > argsz ) - argsz = align; - stack_off += argsz; - } - } - else - { - ask_for_feedback("pdb: unsupported location type %d", locType); - } - return stack_off; -} - -//---------------------------------------------------------------------- -void til_builder_t::enum_function_args(pdb_sym_t &_sym, func_type_data_t &args) -{ - // enumerate all function parameters and gather their names - struct param_enumerator_t : public pdb_access_t::children_visitor_t - { - func_type_data_t &args; - til_builder_t *tb; - int stack_off; - virtual HRESULT visit_child(pdb_sym_t &sym) override - { - DWORD tag = 0; - HRESULT hr = sym.get_symTag(&tag); - if ( FAILED(hr) ) - return hr; - - switch ( tag ) - { - case SymTagBlock: // nested blocks - return tb->pdb_access->iterate_children(sym, SymTagNull, *this); - case SymTagFuncDebugStart: - case SymTagFuncDebugEnd: - return S_OK; // ignore these for the moment - } - - DWORD dwDataKind, locType; - if ( sym.get_dataKind(&dwDataKind) == S_OK - && dwDataKind == DataIsParam - && sym.get_locationType(&locType) == S_OK ) - { - funcarg_t &fa = args.push_back(); - stack_off = tb->get_symbol_funcarg_info(&fa, sym, dwDataKind, locType, stack_off); - } - return S_OK; // continue enumeration - } - param_enumerator_t(func_type_data_t &_args, til_builder_t *_tb) - : args(_args), tb(_tb), stack_off(0) {} - }; - param_enumerator_t pen(args, this); - pdb_access->iterate_children(_sym, SymTagData, pen); -} - -//---------------------------------------------------------------------- -// verify unions that would be created out of [p1, p2) members. -// The [p1, p2) members are spoiled by the function. -// Create substructures if necessary. Returns the result in out (can be the same -// vector as [p1, p2) -cvt_code_t til_builder_t::verify_union( - pdb_udt_type_data_t *out, - pdb_udt_type_data_t::iterator p1, - pdb_udt_type_data_t::const_iterator p2) const -{ - if ( p1 == p2 ) - return cvt_ok; - - QASSERT(498, p2 > p1); - uint64 off = p1->offset; - typedef qvector<pdb_udt_type_data_t> stems_t; - stems_t stems; // each stem is a member of the future union - for ( pdb_udt_type_data_t::iterator q=p1; q != p2; ++q ) - { - pdb_udt_type_data_t *best = NULL; - q->offset -= off; - if ( q->offset != 0 ) - { // find best suited stem: the one with end() closest to our offset - uint64 bestend = 0; - for ( stems_t::iterator s=stems.begin(); s != stems.end(); ++s ) - { - pdb_udt_type_data_t &sm = *s; - pdb_udt_member_t &lastmem = sm.back(); - uint64 smend = lastmem.end(); - if ( (lastmem.is_bitfield() == q->is_bitfield() || q->bit_offset == 0) - && smend <= q->begin() - && (best == NULL || bestend < smend) ) - { - best = &sm; - bestend = smend; - } - } - } - if ( best == NULL ) - best = &stems.push_back(); - uint64 qend; - if ( q->is_bitfield() ) - { - bitfield_type_data_t bi; - q->type.get_bitfield_details(&bi); - size_t size = bi.nbytes * 8; - QASSERT(30385, size == 8 || size == 16 || size == 32 || size == 64); - qend = q->offset - q->bit_offset + size; - } - else - { - qend = q->offset + q->size + 7; - } - qend /= 8; - if ( best->total_size < qend ) - best->total_size = qend; - qswap(best->push_back(), *q); - } - - // all non-trivial stems must be converted to structures - for ( stems_t::iterator s=stems.begin(); s != stems.end(); ++s ) - { - if ( s->size() == 1 && s->begin()->offset == 0 && !s->begin()->is_bitfield() ) - continue; -#ifdef PDEB - msg("CREATE STEM\n"); - for ( pdb_udt_type_data_t::iterator p=s->begin(); p != s->end(); ++p ) - msg(" %" FMT_64 "x %s %s\n", p->offset, p->type.dstr(), p->name.c_str()); -#endif - tinfo_t tif; - int total_size = s->total_size; - cvt_code_t code = create_udt_ref(&tif, s, UdtStruct); - if ( code != cvt_ok ) - return code; - s->resize(1); - pdb_udt_member_t &sm = s->front(); - sm.offset = 0; - sm.size = uint64(total_size) * 8; - sm.name.sprnt("__s%u", uint(s-stems.begin())); - sm.type = tif; - } - - // collect the results - out->resize(stems.size()); - for ( int i=0; i < stems.size(); i++ ) - { - QASSERT(499, stems[i].size() == 1); - qswap(out->at(i), *stems[i].begin()); - } - return cvt_ok; -} - -//---------------------------------------------------------------------- -// create a union out of [p1, p2) members. they are spoiled by the function. -// returns type of the new union and its fields -// this function also creates substructures if necessary -cvt_code_t til_builder_t::create_union( - tinfo_t *out, - size_t *p_total_size, - pdb_udt_type_data_t::iterator p1, - pdb_udt_type_data_t::const_iterator p2) const -{ -#ifdef PDEB - msg("CREATE UNION\n"); - for ( pdb_udt_type_data_t::iterator p=p1; p != p2; ++p ) - msg(" %" FMT_64 "x %s %s\n", p->offset, p->type.dstr(), p->name.c_str()); -#endif - pdb_udt_type_data_t unimems; - cvt_code_t code = verify_union(&unimems, p1, p2); - if ( code != cvt_ok ) - return code; - // calculate the total size - for ( int i=0; i < unimems.size(); i++ ) - { - pdb_udt_member_t &udm = unimems[i]; - size_t nbytes = (udm.end() + 7) / 8; - if ( nbytes > unimems.total_size ) - unimems.total_size = nbytes; - } - if ( p_total_size != NULL ) - *p_total_size = unimems.total_size; - return create_udt_ref(out, &unimems, UdtUnion); -} - -//---------------------------------------------------------------------- -inline void ida_vft_name(qstring *vftn, const char *ns, uint32_t offset=0) -{ - qstring new_vft_name(ns); - if ( offset != 0 ) - new_vft_name.cat_sprnt("_%04X", offset); - new_vft_name.append(VTBL_SUFFIX); - vftn->swap(new_vft_name); -} - -//---------------------------------------------------------------------- -#define MS_VTBL_SUFFIX "Vtbl" -inline void ms_vft_name(qstring *vftn, const char *ns) -{ - qstring new_vft_name(ns); - new_vft_name.append(MS_VTBL_SUFFIX); - vftn->swap(new_vft_name); -} - -//---------------------------------------------------------------------- -inline bool is_ms_vft_name(const qstring &udt_name) -{ - size_t len = udt_name.length(); - return len > sizeof(MS_VTBL_SUFFIX) - && streq(udt_name.begin() + (len - sizeof(MS_VTBL_SUFFIX) + 1), MS_VTBL_SUFFIX); -} - -//---------------------------------------------------------------------- -inline void ida_vft_name_from_ms(qstring *ivftnm, const qstring &msvftnm) -{ - qstring tmp(msvftnm); - if ( is_ms_vft_name(msvftnm) ) - tmp.remove(tmp.length()-4, 4); - ida_vft_name(ivftnm, tmp.c_str()); -} - -//---------------------------------------------------------------------- -bool til_builder_t::get_vft_name(qstring *vftn, uint32 *ord, const char *ns, uint32_t offset) -{ - bool vft_creating = false; - qstring new_vft_name; - // check for MS vftable - ms_vft_name(&new_vft_name, ns); - uint32 id = get_type_ordinal(ti, new_vft_name.c_str()); - if ( id == 0 ) - { - // maybe creating? - vft_creating = creating.find(new_vft_name.c_str()) != creating.end(); - if ( !vft_creating ) - { - ida_vft_name(&new_vft_name, ns, offset); - if ( ord != nullptr ) - id = get_type_ordinal(ti, new_vft_name.c_str()); - } - } - vftn->swap(new_vft_name); - if ( ord != nullptr ) - *ord = id; - return vft_creating; -} - -//---------------------------------------------------------------------- -void pdb_udt_type_data_t::convert_to_tinfo_udt(udt_type_data_t *out) -{ - out->total_size = total_size; - out->taudt_bits = taudt_bits; - out->is_union = is_union; - out->reserve(size()); - for ( size_t i = 0; i < size(); i++ ) - { - udt_member_t &udm = at(i); - out->push_back().swap(udm); - } -} - -//---------------------------------------------------------------------- -// insert si into the destination type -inline void merge_vft_udm(int *j, udt_type_data_t *dst_udt, const udt_member_t &si, bool replace) -{ - bool insert_src = true; - for ( ; *j < dst_udt->size(); (*j)++ ) - { - udt_member_t &dj = (*dst_udt)[*j]; - if ( dj.offset + dj.size <= si.offset ) - continue; - if ( dj.offset >= si.offset + si.size ) - break; // should insert before dj - // Looks like an overlap, - // fields may differ in type and name only. - // Ignore "__vecDelDtor", - // this often happens when virtual class::~class - // is later redefined as __vecDelDtor() - if ( replace && si.name != "__vecDelDtor" - || dj.name == "__vecDelDtor" ) - { - dj.type = si.type; - dj.name = si.name; - } - insert_src = false; - break; - } - if ( insert_src ) - dst_udt->insert(dst_udt->begin()+*j, si); -} - -//---------------------------------------------------------------------- -// merge two vftables into one -// dst_udt gets all fields of srctype in addition to its own fields. -// dst_udt preserves or overrides the coinciding field. -static void merge_vftables(udt_type_data_t *dst_udt, const tinfo_t &srcvft, bool replace) -{ - udt_type_data_t src_udt; - if ( !srcvft.get_udt_details(&src_udt) ) - { - deb(IDA_DEBUG_DBGINFO, "PDB: failed to merge type '%s' to vftable\n", srcvft.dstr()); -#ifdef TESTABLE_BUILD - INTERR(30585); -#else - return; -#endif - } - - int j(0); - for ( const auto &si : src_udt ) - merge_vft_udm(&j, dst_udt, si, replace); - dst_udt->total_size = (dst_udt->back().end() + 7) / 8; -} - -//---------------------------------------------------------------------- -static void add_vftable_member( - udt_type_data_t *dst_udt, - const tinfo_t &member, - const char *name, - DWORD vfptr_offset) -{ - tinfo_t ptr_member; - ptr_member.create_ptr(member); // the field is a pointer to function - asize_t size = ptr_member.get_size(); - - udt_member_t udm; - udm.offset = uint64(vfptr_offset) * 8; - udm.size = uint64(size) * 8; - udm.type = ptr_member; - udm.effalign = size; - udm.name = name; - - int j(0); - merge_vft_udm(&j, dst_udt, udm, true); - dst_udt->total_size = (dst_udt->back().end() + 7) / 8; -} - -//---------------------------------------------------------------------- -inline bool get_vfptr_offset(DWORD *vfptr_offset, pdb_sym_t &sym) -{ - BOOL is_virtual; - return sym.get_virtual(&is_virtual) == S_OK - && is_virtual - && sym.get_virtualBaseOffset(vfptr_offset) == S_OK; -} - -//---------------------------------------------------------------------- -// enumerate virtual functions of class sym and create a vtable structure -// with function pointers -cvt_code_t til_builder_t::make_vtable_struct(tinfo_t *out, pdb_sym_t &_sym) -{ - struct virtual_func_visitor_t : public pdb_access_t::children_visitor_t - { - til_builder_t *tb; - vft_info_t *vftinfo; // vftable info - virtual HRESULT visit_child(pdb_sym_t &sym) override - { - qstring name; - sym.get_name(&name); - - // is introducing virtual? - DWORD vfptr_offset = -1; - bool is_intro_virtual = get_vfptr_offset(&vfptr_offset, sym); - - tpinfo_t tpi; - if ( is_intro_virtual && tb->retrieve_type(&tpi, sym, parent, NULL) ) - { - ddeb(("PDEB: make_vtable_struct add '%s' vptr offset %u\n", tpi.type.dstr(), vfptr_offset)); - add_vftable_member(&vftinfo->udt, tpi.type, name.c_str(), vfptr_offset); - } - return S_OK; - } - virtual_func_visitor_t(til_builder_t *_tb, vft_info_t *_vftinfo) - : tb(_tb), - vftinfo(_vftinfo) - {} - }; - - qstring udt_name; - _sym.get_name(&udt_name); - // FIXME: should we remove classprefix (name + "::") ? - #ifdef PDEB - static int zzlevel = 0; - msg("PDEB: %d{ make_vtable_struct '%s'\n", ++zzlevel, udt_name.c_str()); - #endif - vft_info_t vftinfo; - virtual_func_visitor_t pp(this, &vftinfo); - pdb_access->iterate_children(_sym, SymTagFunction, pp); - - bool ok = false; - if ( !vftinfo.udt.empty() ) - { - out->create_udt(vftinfo.udt, BTF_STRUCT); - ddeb(("PDEB: %d make_vtable_struct collected vftable '%s'\n", zzlevel, out->dstr())); - ok = out->calc_udt_aligns(); - } - #ifdef PDEB - if ( !ok ) - msg("PDEB: make_vtable_struct failed to create vftable\n"); - msg("PDEB: %d} make_vtable_struct '%s'\n", zzlevel--, udt_name.c_str()); - #endif - return ok ? cvt_ok : cvt_failed; -} - -//---------------------------------------------------------------------- -inline bool is_fake_vftable(tinfo_t vft_tif) -{ - qstring tname; - return vft_tif.get_final_type_name(&tname) && tname == fake_vtable_type; -} - -//---------------------------------------------------------------------- -cvt_code_t til_builder_t::convert_udt( - tinfo_t *out, - pdb_sym_t &_sym, - DWORD64 size) -{ - DWORD udtKind; - if ( _sym.get_udtKind(&udtKind) != S_OK ) - return cvt_failed; - - // retrieve member names, types, offsets - struct type_name_collector_t : public pdb_access_t::children_visitor_t - { - til_builder_t *tb; - pdb_udt_type_data_t &udt; - const char *vftname; // vftable name - vft_info_t *vftinfo; // vftable info, maybe nullptr if we don't want - // to collect vftable - bool mark_lpVtbl; // mark "lpVtbl" as pointer to vftable - bool has_virtbases; - HRESULT visit_child(pdb_sym_t &sym) override - { - qstring name; - sym.get_name(&name); - - // is introducing virtual? - DWORD vfptr_offset = -1; - bool is_intro_virtual = get_vfptr_offset(&vfptr_offset, sym); - - LONG offset = 0; - if ( !is_intro_virtual && sym.get_offset(&offset) != S_OK ) - return S_OK; - // assert: intro virtual or data member - - tpinfo_t tpi; - if ( !tb->retrieve_type(&tpi, sym, parent, NULL) ) - return S_OK; - - if ( is_intro_virtual ) - { - if ( vftinfo != nullptr ) - { - ddeb(("PDEB: convert_udt vtable %s add '%s' of '%s' vptr offset %u\n", vftname, name.c_str(), tpi.type.dstr(), vfptr_offset)); - add_vftable_member(&vftinfo->udt, tpi.type, name.c_str(), vfptr_offset); - } - return S_OK; - } - - ddeb(("PDEB: convert_udt adding member '%s' of type '%s'\n", name.c_str(), tpi.type.dstr())); - asize_t memsize = tb->get_symbol_type_length(sym); - - pdb_udt_member_t &udm = udt.push_back(); - - DWORD tag = SymTagNull; - sym.get_symTag(&tag); - if ( tag == SymTagBaseClass ) - { - udm.set_baseclass(); - // determine if the base is virtual - BOOL is_virtbase = false; - sym.get_isVirtualBaseClass(&is_virtbase); - if ( is_virtbase ) - { - udm.set_virtbase(); - has_virtbases = true; - } - - // we are interested only in baseclass at offset 0 - if ( offset == 0 && vftinfo != nullptr ) - { - // get baseclass vftable - qstring bcvft_name; - uint32 bcvft_ord; - tb->get_vft_name(&bcvft_name, &bcvft_ord, name.c_str()); - if ( bcvft_ord != 0 ) - { - tinfo_t bcvft_tif; - bcvft_tif.get_numbered_type(tb->ti, bcvft_ord); - if ( !is_fake_vftable(bcvft_tif) ) - { - ddeb(("PDEB: convert_udt vtable %s add baseclass %s vtable '%s'\n", vftname, bcvft_name.c_str(), bcvft_tif.dstr())); - merge_vftables(&vftinfo->udt, bcvft_tif, false); - } - else - { - ddeb(("PDEB: convert_udt vtable %s baseclass %s vtable is fake\n", vftname, bcvft_name.c_str())); - } - } - else - { - ddeb(("PDEB: convert_udt vtable %s baseclass %s vtable not found\n", vftname, bcvft_name.c_str())); - vftinfo->base0.swap(bcvft_name); - } - } - name.clear(); // no name for baseclass member - } - else if ( tag == SymTagVTable ) - { - ddeb(("PDEB: convert_udt our vtable '%s'\n", tpi.type.dstr())); - if ( is_fake_vftable(tpi.type) ) - { - tpi.type = tinfo_t::get_stock(STI_PVOID); - } - else - { - if ( vftinfo != nullptr ) - merge_vftables(&vftinfo->udt, tpi.type, true); - // type is a structure, while the field is a pointer to it - tpi.type.create_ptr(tpi.type); - } - name = VTBL_MEMNAME; // we need only this name - memsize = tpi.type.get_size(); - udm.set_vftable(); - } - // mark MS vftable pointer - if ( mark_lpVtbl && tpi.type.is_ptr() && name == "lpVtbl" ) - { // no need to rename it - udm.set_vftable(); - } - mark_lpVtbl = false; // pointer to vftable maybe the first field only - - DWORD64 ulLen = DWORD64(memsize) * 8; - DWORD dwBitPos = 0; - DWORD dwLocType = LocIsNull; - sym.get_locationType(&dwLocType); // may fail, just ignore - if ( dwLocType == LocIsBitField ) - { - sym.get_bitPosition(&dwBitPos); - sym.get_length(&ulLen); - bool is_unsigned = tpi.type.is_unsigned(); - udm.type.create_bitfield(memsize, ulLen, is_unsigned); - } - else - { - udm.type = tpi.type; - } - udm.size = ulLen; - udm.offset = uint64(offset) * 8 + dwBitPos; - udm.bit_offset = dwBitPos; - udm.name.swap(name); - return S_OK; - } - type_name_collector_t( - til_builder_t *_tb, - pdb_udt_type_data_t &m, - const char *_vftname, - vft_info_t *_vftinfo) - : tb(_tb), - udt(m), - vftname(_vftname), - vftinfo(_vftinfo), - mark_lpVtbl(true), - has_virtbases(false) - {} - }; - - qstring udt_name; - _sym.get_name(&udt_name); - - bool is_vtbl_udt = is_ms_vft_name(udt_name); - qstring udt_vft_name; - uint32 udt_vft_ord(0); - bool vft_creating = false; - if ( !is_vtbl_udt ) - vft_creating = get_vft_name(&udt_vft_name, &udt_vft_ord, udt_name.c_str()); - bool collect_vft = !vft_creating && !is_vtbl_udt && udt_vft_ord == 0; - - #ifdef PDEB - static int zzlevel = 0; - msg("PDEB: %d{ convert_udt '%s' assuming vftable '%s'\n", ++zzlevel, udt_name.c_str(), udt_vft_name.c_str()); - #endif - pdb_udt_type_data_t udt; - if ( is_vtbl_udt ) - udt.taudt_bits |= TAUDT_VFTABLE; - vft_info_t vtinfo; - type_name_collector_t pp( - this, - udt, - udt_vft_name.c_str(), - collect_vft ? &vtinfo : nullptr); - pdb_access->iterate_children(_sym, SymTagNull, pp); - - bool is_cppobj = false; - if ( collect_vft && !vtinfo.udt.empty() ) - { - if ( vtinfo.base0.empty() ) - { - tinfo_t vft_tif; - if ( vft_tif.create_udt(vtinfo.udt, BTF_STRUCT) - && vft_tif.calc_udt_aligns() ) - { - ddeb(("PDEB: convert_udt %d collected vftable '%s' '%s'\n", zzlevel, udt_vft_name.c_str(), vft_tif.dstr())); - uint32 id = get_type_ordinal(ti, udt_vft_name.c_str()); - if ( id == 0 ) - vft_tif.set_named_type(ti, udt_vft_name.c_str(), NTF_NOBASE); - else - ddeb(("PDEB: convert_udt '%s' exists\n", udt_vft_name.c_str())); - is_cppobj = true; // there is a vftable, so it is a C++ object - } - else - { // ignore failure, continue w/o vftable - ddeb(("PDEB: convert_udt failed to create vftable\n")); - } - } - else - { - vftmap.emplace(std::make_pair(udt_vft_name.c_str(), vtinfo)); - } - } - #ifdef PDEB - msg("PDEB: %d} convert_udt '%s'\n", zzlevel--, udt_name.c_str()); - #endif - - // if we will use MS Vtbl then create IDA synonym - if ( is_vtbl_udt ) - { - tinfo_t tif; - tif.create_typedef(ti, udt_name.c_str()); - qstring ivftnm; - ida_vft_name_from_ms(&ivftnm, udt_name.c_str()); - tif.set_named_type(ti, ivftnm.c_str(), NTF_NOBASE); - } - - // if we inherit from c++ object, we are too a c++ object - if ( size > 0 ) - { - if ( udt.empty() ) - is_cppobj = true; - if ( udt.size() == 1 - && udt[0].is_baseclass() - && udt[0].type.is_empty_udt() ) - { - is_cppobj = true; - } - } - if ( is_cppobj ) - { - udt.taudt_bits |= TAUDT_CPPOBJ; - } - else if ( udt.empty() ) - { // create forward ref - qstring name; - get_symbol_name(_sym, name); - type_t bt = udtKind == UdtUnion ? BTF_UNION : BTF_STRUCT; - out->create_typedef(ti, name.c_str(), bt); - return cvt_typedef; - } - udt.total_size = size; - std::stable_sort(udt.begin(), udt.end()); - BOOL cppobj; - if ( _sym.get_constructor(&cppobj) == S_OK && cppobj > 0 ) - udt.taudt_bits |= TAUDT_CPPOBJ; - return create_udt(out, &udt, udtKind); -} - -//---------------------------------------------------------------------- -inline void get_empty_vft_tif(tinfo_t *vtif) -{ - udt_type_data_t empty_udt; - empty_udt.taudt_bits |= TAUDT_VFTABLE; - vtif->create_udt(empty_udt, BTF_STRUCT); -} - -//---------------------------------------------------------------------- -// fill the empty start slots of vftable, -// the holes will be filled latter, see SUDT_GAPS -static void fill_vft_empty_splots(udt_type_data_t *udt) -{ - if ( udt->empty() ) - return; - - uint64 offset = udt->begin()->offset; - if ( offset == 0 ) - return; - uint32 nbytes = offset / 8; - - udt_member_t gap; - gap.type.create_array(tinfo_t(BTF_BYTE), nbytes); - gap.offset = 0; - gap.size = offset; - gap.effalign = 1; - gap.name = "gap0"; - udt->insert(udt->begin(), gap); - // assert: no need to fix udt->total_size -} - -//---------------------------------------------------------------------- -void til_builder_t::create_vftables() -{ - while ( !vftmap.empty() ) - { - bool changed = false; - for ( auto p=vftmap.begin(); p != vftmap.end(); ) - { - auto &name = p->first; - auto &info = p->second; - ddeb(("PDB: create_vftables checking %s base0 %s\n", name.c_str(), info.base0.c_str())); - const char *b0name = info.base0.c_str(); - uint32 id = get_type_ordinal(ti, b0name); - if ( id != 0 ) - { // merge the known base class vftable - ddeb(("PDB: merge %s to %s\n", b0name, name.c_str())); - tinfo_t btif; - btif.get_numbered_type(ti, id); - merge_vftables(&info.udt, btif, false); - info.base0.clear(); - changed = true; - } - else - { - auto r = vftmap.find(b0name); - if ( r == vftmap.end() || r->second.empty() ) - { // ordinary class - ddeb(("PDB: ignore %s for %s\n", b0name, name.c_str())); - info.base0.clear(); - changed = true; - } - else - { - ddeb(("PDB: skip %s for %s\n", b0name, name.c_str())); - } - } - if ( info.base0.empty() ) - { // all base classes references are resolved, create vftable - ddeb(("PDB: create_vftables creating %s\n", name.c_str())); - tinfo_t vtif; - if ( !vtif.create_udt(info.udt, BTF_STRUCT) - || !vtif.calc_udt_aligns() ) - { // something wrong with vftable udt, - // create an empty vftable - ddeb(("PDEB: create_vftables failed to create vftable %s\n", name.c_str())); - get_empty_vft_tif(&vtif); - } - ddeb(("PDB: create_vftables created %s '%s'\n", name.c_str(), vtif.dstr())); - vtif.set_named_type(ti, name.c_str(), NTF_NOBASE); - p = vftmap.erase(p); - changed = true; - } - else - { - ++p; - } - } - if ( !changed ) - break; - } - - if ( !vftmap.empty() ) - { // Something wrong or not: - // base class w/o virtual functions - // cyclic references, - // missed types - // Create the vftables ASIS - for ( auto p : vftmap ) - { - auto &name = p.first; - auto &info = p.second; - ddeb(("PDEB: create_vftables create vftable %s ASIS, base0 %s\n", name.c_str(), info.base0.c_str())); - fill_vft_empty_splots(&info.udt); - tinfo_t vtif; - vtif.create_udt(info.udt, BTF_STRUCT); - vtif.calc_udt_aligns(); - ddeb(("PDB: create_vftables created %s '%s'\n", name.c_str(), vtif.dstr())); - vtif.set_named_type(ti, name.c_str(), NTF_NOBASE); - } - vftmap.clear(); - } -} - -//---------------------------------------------------------------------- -static bool set_array_type(pdb_udt_member_t *udm, int nbytes) -{ - bool ok = udm->type.create_array(tinfo_t(BT_UNK_BYTE), nbytes); - if ( ok ) - udm->size = nbytes * 8; - return ok; -} - -//---------------------------------------------------------------------- -cvt_code_t til_builder_t::create_udt(tinfo_t *out, pdb_udt_type_data_t *udt, int udtKind) const -{ - cvt_code_t code; - if ( udtKind == UdtUnion ) - { - udt->is_union = true; - code = verify_union(udt, udt->begin(), udt->end()); - } - else - { - // find overlapping members and convert into subunions (anonymous union would be great) - udt->is_union = false; - code = handle_overlapping_members(udt); - } - if ( code != cvt_ok ) - return code; - - // validate the type sizes, for the following reasons: - // - pdb information may be misleading (see pc_pdb_redefined_type.pe) - // - the same type name can be used for different types - // - invalid arrays happen (pc_pdb_wow.pe) - for ( int i=0; i < udt->size(); i++ ) - { - pdb_udt_member_t &udm = udt->at(i); - if ( udm.is_bitfield() ) - continue; - int gts_code = GTS_NESTED | (udm.is_baseclass() ? GTS_BASECLASS : 0); - size_t nbytes = udm.type.get_size(NULL, gts_code); - if ( nbytes == BADSIZE ) - continue; // cannot verify, the type is not ready yet - if ( uint64(nbytes)*8 != udm.size ) - { - if ( nbytes != 0 ) - { - if ( !set_array_type(&udm, udm.size/8) ) - return cvt_failed; - } - else if ( udm.is_baseclass() || udm.type.is_array() ) - { // nbytes==0 - udm.size = 0; // correct the base class size - } - } - } - - if ( udt->total_size == 0 && !udt->empty() ) - { // msdia did not provide the udt size. use the end of the last element - pdb_udt_member_t &udm = udt->back(); - udt->total_size = (udm.end() + 7) / 8; - } - - // the kernel cannot handle virtual base classes yet, so we remove them - // also check for overlapping members and members that go past the udt end - uint64 last = 0; - uint64 total_bits = uint64(udt->total_size) * 8; - for ( int i=0; i < udt->size(); i++ ) - { - pdb_udt_member_t &udm = udt->at(i); - if ( udm.offset < last || udm.end() > total_bits ) - { - if ( udm.end() > total_bits ) - udm.size = total_bits - udm.offset; - int nbytes = (udm.end() + 7 - last) / 8; - if ( nbytes > 0 ) - { // replace with byte array - if ( !set_array_type(&udm, nbytes) ) - return cvt_failed; - if ( udm.name.empty() ) - udm.name.sprnt("_bytes_%" FMT_64 "x", last/8); - udm.offset = last; - udm.clr_baseclass(); - udm.clr_virtbase(); - } - else - { // we do not need this member - udt->erase(udt->begin()+i); - --i; - continue; - } - } - if ( udtKind != UdtUnion ) - last = udm.end(); - } - - type_t bt = udt->is_union ? BTF_UNION : BTF_STRUCT; - udt_type_data_t tinfo_udt; - udt->convert_to_tinfo_udt(&tinfo_udt); - out->create_udt(tinfo_udt, bt); - if ( !out->calc_udt_aligns(SUDT_GAPS|SUDT_UNEX) ) - { -#ifdef TESTABLE_BUILD - QASSERT(30380, !inf_test_mode() && out->get_size() == BADSIZE); -#endif - ask_for_feedback("Failed to calculate struct member alignments"); - } - return cvt_ok; -} - -//---------------------------------------------------------------------- -// is the return type complex? -// if so, a pointer to return value will be passed as a hidden parameter -bool til_builder_t::is_complex_return(pdb_sym_t &sym) const -{ - pdb_sym_t *pType = pdb_access->create_sym(); - pdb_sym_janitor_t janitor_pType(pType); - bool complex = false; - if ( sym.get_type(pType) == S_OK ) - { - DWORD tag = 0; - complex = pType->get_symTag(&tag) == S_OK && tag == SymTagUDT; - if ( complex ) - { - ULONGLONG size; - complex = pType->get_length(&size) == S_OK && size > 8; - } - if ( !complex && tag == SymTagUDT ) - { - // we've got a small UDT which possibly fits into a register (or two) - // but it has to be a POD for that, i.e. should have no constructor or assignment operators - BOOL b; - if ( (pType->get_constructor (&b) == S_OK) && b - || (pType->get_hasAssignmentOperator(&b) == S_OK) && b - || (pType->get_hasCastOperator (&b) == S_OK) && b ) - complex = true; - } - } - return complex; -} - - -//---------------------------------------------------------------------------- -bool til_builder_t::is_unnamed_tag_typedef(const tinfo_t &tif) const -{ - uint32 id = tif.get_ordinal(); - if ( id == 0 ) - return false; - - return unnamed_types.find(id) != unnamed_types.end(); -} - - -//---------------------------------------------------------------------- -// borland does not like this structure to be defined inside a function. -// this is the only reason why it is in the file scope. -struct this_seeker_t : public pdb_access_t::children_visitor_t -{ - funcarg_t thisarg; - til_builder_t *tb; - bool found; - virtual HRESULT visit_child(pdb_sym_t &sym) override - { - DWORD dwDataKind, locType; - if ( sym.get_dataKind(&dwDataKind) == S_OK - && dwDataKind == DataIsObjectPtr - && sym.get_locationType(&locType) == S_OK ) - { - tb->get_symbol_funcarg_info(&thisarg, sym, dwDataKind, locType, 0); - found = true; - return S_FALSE; // Stop enum. - } - return S_OK; - } - this_seeker_t(til_builder_t *_tb) : thisarg(), tb(_tb), found(false) {} -}; - -//---------------------------------------------------------------------------- -inline type_t get_sym_modifiers(pdb_sym_t &sym) -{ - type_t type_mod = 0; - BOOL sym_mod; - if ( sym.get_constType(&sym_mod) == S_OK && sym_mod ) - type_mod |= BTM_CONST; - if ( sym.get_volatileType(&sym_mod) == S_OK && sym_mod ) - type_mod |= BTM_VOLATILE; - return type_mod; -} - -//---------------------------------------------------------------------- -cvt_code_t til_builder_t::really_convert_type( - tpinfo_t *out, - pdb_sym_t &sym, - pdb_sym_t *parent, - DWORD tag) -{ - // retrieve type modifiers - type_t mods = get_sym_modifiers(sym); - - DWORD64 size = 0; - sym.get_length(&size); - DWORD bt, count; - cvt_code_t code = cvt_ok; - switch ( tag ) - { - default: - case SymTagNull: - deb(IDA_DEBUG_DBGINFO, "PDB: unsupported tag %s\n", symtag_to_string(tag)); - code = cvt_failed; - break; - - case SymTagBaseType: - if ( sym.get_baseType(&bt) != S_OK ) - code = cvt_failed; - else - code = convert_basetype(out, bt, int(size)); - break; - - case SymTagPointerType: - { - tpinfo_t obj; - if ( !get_symbol_type(&obj, sym, NULL) ) - { - code = cvt_failed; - break; - } - tinfo_t tif; - tif.create_ptr(obj.type); - int s2 = tif.get_size(); - if ( size != s2 ) - { - if ( size == 4 || size == 8 ) - { // use __ptr32 or __ptr64 - ptr_type_data_t pi; - pi.obj_type = obj.type; - pi.taptr_bits = size == 4 ? TAPTR_PTR32 : TAPTR_PTR64; - tif.create_ptr(pi); - } - else - { // revert to int - type_t inttype = get_scalar_bt(size); - if ( inttype == BT_UNK ) - { - code = cvt_failed; - break; - } - tif = tinfo_t(inttype); - } - } - out->type.swap(tif); - } - break; - - case SymTagArrayType: - { - tpinfo_t el; - if ( !get_symbol_type(&el, sym, NULL) ) - { -FAILED_ARRAY: - code = cvt_failed; - break; - } - if ( sym.get_count(&count) != S_OK ) - goto FAILED_ARRAY; - mods |= el.type.get_modifiers(); // propagate element type to array - if ( !out->type.create_array(el.type, count) ) - goto FAILED_ARRAY; - } - break; - - case SymTagFunctionType: - { - tpinfo_t itp2; - if ( !get_symbol_type(&itp2, sym, NULL) ) // return type - { - code = cvt_failed; - break; - } - func_type_data_t fi; - fi.rettype = itp2.type; - if ( fi.rettype.is_array() ) - { - code = cvt_failed; // arrays cannot be returned - break; - } - DWORD cc0; - fi.cc = CM_CC_UNKNOWN; - if ( sym.get_callingConvention(&cc0) == S_OK ) - fi.cc = convert_cc(cc0); - - if ( get_cc(fi.cc) != CM_CC_VOIDARG ) - { - retrieve_arguments(sym, fi, parent); - // if arg has unknown/invalid argument => convert to ellipsis - for ( func_type_data_t::iterator i = fi.begin(); i != fi.end(); i++ ) - { - if ( i->type.empty() ) - { - // If the CC is cdecl, empty arguments represent an ellipsis. - // Otherwise, it's likely to be a C-type function - // with unknown number of arguments, such as 'foo()' - // (as opposed to 'foo(void)'), and which might not have a cdecl - // calling convention. E.g., pc_win32_appcall.pe's 'FARPROC': - // "int (FAR WINAPI * FARPROC) ()", which is a stdcall. - cm_t cc = get_cc(fi.cc); - if ( cc == CM_CC_CDECL || inf_is_64bit() && cc == CM_CC_FASTCALL ) - fi.cc = CM_CC_ELLIPSIS; - // remove the ellipsis and any trailing arguments - fi.erase(i, fi.end()); - break; - } - } - // is there an implicit "result" pointer passed? - if ( is_complex_return(sym) ) - { - // complex return type: what's returned is actually a pointer - fi.rettype.create_ptr(fi.rettype); - funcarg_t retarg; - retarg.type = fi.rettype; - retarg.name = "result"; - fi.insert(fi.begin(), retarg); - } - // is there an implicit "this" passed? - // N.B.: 'this' is passed before the implicit result, if both are present - tinfo_t class_type; - if ( is_member_func(&class_type, sym, parent) ) - { - class_type.create_ptr(class_type); - funcarg_t thisarg; - thisarg.type = class_type; - thisarg.name = "this"; - // due to MSDIA error sometimes it is failed to answer correctly - // for the get_isStatic() request (S_FALSE). - // So we need to check does 'this' pointer present in the function parameters. - bool add_this = true; - if ( parent != NULL ) - { - this_seeker_t ts(this); - pdb_access->iterate_children(*parent, SymTagData, ts); - thisarg.argloc = ts.thisarg.argloc; - if ( thisarg.argloc.is_stkoff() ) - { // shift the remaining stkargs - int delta = thisarg.type.get_size(); - for ( int i=0; i < fi.size(); i++ ) - { - funcarg_t &fa = fi[i]; - if ( fa.argloc.is_stkoff() ) - fa.argloc.set_stkoff(fa.argloc.stkoff()+delta); - } - } - add_this = ts.found; - } - if ( add_this ) - fi.insert(fi.begin(), thisarg); - } - if ( is_user_cc(fi.cc) ) - { - // specify argloc for the return value - size_t retsize = fi.rettype.get_size(); - if ( retsize <= 1 ) - fi.retloc._set_reg1(R_al); - else if ( retsize <= 4 ) - fi.retloc._set_reg1(R_ax); - else - fi.retloc._set_reg2(R_ax, R_dx); - - // __usercall must have all its arguments location - // specified. - // It happens that some PDB information, - // generated at compile-time, does _not_ hold info - // about all the parameters. For example, - // a function declared as: - // void BlockOpVPSDec(char *p, uint32 dwLength, char btXorKey, char /*foo*/) - // will end up having only its first three arguments - // properly defined in the PDB (because the fourth is - // not used, its location is not defined.) - // Still, in order for 'build_func_type2()' to work, - // it requires all valid argloc_t instances. Thus, - // we remove invalid ones completely. - for ( int i = fi.size() - 1; i >= 0; --i ) - if ( fi[i].argloc.is_badloc() ) - fi.erase(fi.begin() + i); - } - out->type.create_func(fi); - } - } - break; - - case SymTagUDT: - case SymTagBaseClass: - code = convert_udt(&out->type, sym, size); - break; - case SymTagEnum: - { - struct name_value_collector_t : public pdb_access_t::children_visitor_t - { - const til_builder_t *tb; - enum_type_data_t ei; - const type_t *idatype; - HRESULT visit_child(pdb_sym_t &child) override - { - enum_member_t &em = ei.push_back(); - child.get_name(&em.name); - em.value = tb->get_variant_long_value(child); - if ( get_named_type(tb->ti, em.name.c_str(), NTF_SYMM, &idatype) == 1 ) - return E_FAIL; - return S_OK; - } - name_value_collector_t(const til_builder_t *_tb) - : tb(_tb), idatype(NULL) {} - }; - name_value_collector_t nvc(this); - if ( size != 0 && size <= 64 ) - { - int bte_size = log2ceil(size) + 1; - nvc.ei.bte |= bte_size & BTE_SIZE_MASK; - } - HRESULT hr = pdb_access->iterate_children(sym, SymTagNull, nvc); - if ( FAILED(hr) ) // symbol already exists? - { // just reuse the existing enum - if ( !out->type.deserialize(ti, &nvc.idatype) ) // this is not quite correct - INTERR(30407); - qstring n1; - if ( out->type.get_type_name(&n1) ) - { - qstring nm; - get_symbol_name(sym, nm); - if ( nm == n1 ) - code = cvt_typedef; // avoid circular dependencies - } - } - else - { - out->type.create_enum(nvc.ei); - } - } - break; - - case SymTagTypedef: - case SymTagFunctionArgType: - case SymTagFunction: - case SymTagData: - if ( !get_symbol_type(out, sym, NULL) ) - code = cvt_failed; - else if ( out->type.is_decl_typedef() ) - code = cvt_typedef; // signal that this is a typedef - break; - - case SymTagVTable: - if ( parent == NULL || make_vtable_struct(&out->type, *parent) != cvt_ok ) - out->type.create_typedef(ti, fake_vtable_type); - break; - } - if ( code != cvt_failed && mods != 0 ) - out->type.set_modifiers(mods); - // todo: check that the type has the expected size - return code; -} - -//---------------------------------------------------------------------- -cvt_code_t til_builder_t::convert_type( - tpinfo_t *out, - pdb_sym_t &sym, - pdb_sym_t *parent, - DWORD type, - DWORD tag) -{ - if ( level == 500 ) - { - deb(IDA_DEBUG_DBGINFO, "PDB: the maximum recursion level was reached\n"); - return cvt_failed; - } - level++; - typemap_t::iterator p = typemap.find(type); - if ( p == typemap.end() ) - { - tpinfo_t tpi; - tpi.cvt_code = really_convert_type(&tpi, sym, parent, tag); - p = typemap.insert(std::make_pair(type, tpi)).first; - } - tpinfo_t &tpi = p->second; - *out = tpi; - level--; - return tpi.cvt_code; -} - -//---------------------------------------------------------------------- -bool til_builder_t::begin_creation(DWORD tag, const qstring &name, uint32 *p_id) -{ - if ( tag != SymTagFunction ) - { - uint32 id = *p_id; - creating_t::iterator c = creating.find(name); - if ( c != creating.end() ) // recursive call - { - if ( !c->second ) // allocated? - { - if ( id == 0 ) - id = alloc_type_ordinal(ti); // have to create the type id immediately - c->second = id; - QASSERT(490, id != 0); -// msg("%d %s: prematurely mapped to %d\n", type, name.c_str(), c->second); - } - *p_id = c->second; - return false; - } - creating.insert(std::make_pair(name, id)); // add to the 'creating' list - } - return true; -} - -//---------------------------------------------------------------------------- -uint32 til_builder_t::end_creation(const qstring &name) -{ - uint32 id = 0; - creating_t::iterator c = creating.find(name); - if ( c != creating.end() ) - { - id = c->second; - creating.erase(c); - } - if ( id == 0 ) - { - id = alloc_type_ordinal(ti); // have to create the type id immediately - QASSERT(491, id != 0); -// msg("%d %s: mapped to %d\n", type, name.c_str(), id); - } - return id; -} - - -//---------------------------------------------------------------------------- -cvt_code_t til_builder_t::handle_overlapping_members(pdb_udt_type_data_t *udt) const -{ - qstack<qstring> union_names; - pdb_udt_type_data_t::iterator end = udt->end(); - pdb_udt_type_data_t::iterator first = end; // !=end => collecting union members - pdb_udt_type_data_t::iterator last = end; // member with highest ending offset so far - for ( pdb_udt_type_data_t::iterator p=udt->begin(); ; ++p ) - { - if ( p != udt->end() ) - { - if ( is_unnamed_tag_typedef(p->type) ) - handle_unnamed_overlapping_member(udt, &union_names, &p->name); - if ( last == end ) - { - last = p; - continue; - } - if ( last->end() > p->begin() ) - { // found an overlap. however, we ignore base classes, in order - // not to convert them into unions - if ( first == end && !last->is_baseclass() ) - first = last; - goto NEXT; - } - } - if ( first != end ) - { - int fidx = first - udt->begin(); - uval_t off = first->offset; - // if we have a bitfield, include the adjacent bitfields in the new type - int bf_typesize = 0; - for ( pdb_udt_type_data_t::iterator q=first; q != p; ++q ) - { - if ( q->is_bitfield() ) - { - bf_typesize = q->type.get_size(); - break; - } - } - if ( bf_typesize != 0 ) - { - while ( fidx > 0 - && (first-1)->is_bitfield() - && (first-1)->type.get_size() == bf_typesize ) - { - --fidx; - --first; - off = first->offset; - } - while ( p != end - && p->is_bitfield() - && p->type.get_size() == bf_typesize ) - { - ++p; - } - } - // range [first, p) is overlapping, create a new type for it - tinfo_t unitif; - size_t union_size; - cvt_code_t code = create_union(&unitif, &union_size, first, p); - if ( code != cvt_ok ) - return code; - udt->erase(first+1, p); - end = udt->end(); - first = end; - last = end; - p = udt->begin() + fidx; - p->offset = off & ~7; - p->size = uint64(union_size) * 8; - if ( union_names.empty() ) - p->name.sprnt("___u%d", fidx); - else - p->name = union_names.pop(); - p->type = unitif; - } - if ( p == end ) - break; -NEXT: - if ( last->end() < p->end() ) - last = p; - } - return cvt_ok; -} - - -//---------------------------------------------------------------------------- -void til_builder_t::handle_function_type(pdb_sym_t &fun_sym, ea_t ea) -{ - struct local_data_creator_t : public pdb_access_t::children_visitor_t - { - virtual HRESULT visit_child(pdb_sym_t &sym) override - { - DWORD tag = 0; - HRESULT hr = sym.get_symTag(&tag); - if ( FAILED(hr) ) - return hr; - - switch ( tag ) - { - case SymTagBlock: // nested blocks - return tb->pdb_access->iterate_children(sym, SymTagNull, *this); - case SymTagFuncDebugStart: - case SymTagFuncDebugEnd: - return S_OK; // ignore these for the moment - } - - DWORD loc_type; - if ( sym.get_locationType(&loc_type) != S_OK ) - return S_OK; // optimized away? - - return tb->handle_function_child(fun_sym, ea, sym, tag, loc_type); - } - local_data_creator_t(til_builder_t *_tb, pdb_sym_t &_fun_sym, ea_t _ea) : - tb(_tb), fun_sym(_fun_sym), ea(_ea) {} - til_builder_t *tb; - pdb_sym_t &fun_sym; - ea_t ea; - }; - local_data_creator_t ldc(this, fun_sym, ea); - pdb_access->iterate_children(fun_sym, SymTagNull, ldc); -} - - -//---------------------------------------------------------------------------- -void til_builder_t::type_created( - ea_t /*ea*/, - int /*id*/, - const char * /*name*/, - const tinfo_t & /*ptr*/) const -{ -} - - -//---------------------------------------------------------------------------- -HRESULT til_builder_t::handle_function_child( - pdb_sym_t & /*fun_sym*/, - ea_t ea, - pdb_sym_t &child_sym, - DWORD child_tag, - DWORD child_loc_type) -{ - switch ( child_loc_type ) - { - case LocIsConstant: - break; // we ignore function level constants - - case LocIsStatic: - case LocIsTLS: // not tested - handle_symbol(child_sym); - break; - - case LocIsEnregistered: - case LocIsRegRel: - break; - - default: - ask_for_feedback("pdb: unsupported location type %d, tag %d at %a", child_loc_type, child_tag, ea); - break; - } - return S_OK; -} - - -//---------------------------------------------------------------------------- -cvt_code_t til_builder_t::create_udt_ref(tinfo_t *out, pdb_udt_type_data_t *udt, int udt_kind) const -{ - tinfo_t tif; - cvt_code_t code = create_udt(&tif, udt, udt_kind); - if ( code != cvt_ok ) - return code; - - qtype type, fields; - tif.serialize(&type, &fields); - - qstring name; - build_anon_type_name(&name, type.begin(), fields.begin()); - uint32 id = get_type_ordinal(ti, name.c_str()); - if ( id == 0 ) - { - id = alloc_type_ordinal(ti); - if ( set_numbered_type(ti, id, NTF_NOBASE|NTF_FIXNAME, name.c_str(), type.begin(), fields.begin()) != TERR_OK ) - return cvt_failed; - type_created(BADADDR, id, NULL, tif); - } - - out->create_typedef(ti, id); - return cvt_ok; -} - -//---------------------------------------------------------------------------- -bool til_builder_t::retrieve_type( - tpinfo_t *out, - pdb_sym_t &sym, - pdb_sym_t *parent, - int *p_id) -{ - if ( p_id != NULL ) - *p_id = -1; - - // id -> unknown typedef? - DWORD sym_id = 0; - sym.get_symIndexId(&sym_id); - tpdefs_t::iterator q = tpdefs.find(sym_id); - if ( q != tpdefs.end() ) - { - out->type = q->second; - return true; - } - - DWORD tag = 0; - HRESULT hr = sym.get_symTag(&tag); - if ( FAILED(hr) ) - return false; - - qstring ns; - bool is_unnamed = get_symbol_name(sym, ns); - //msg("ID: %d -> %s\n", sym_id, ns.begin()); - uint32 id(0); - bool id_set = false; - if ( tag == SymTagVTable && ns.empty() ) - { - if ( parent != NULL ) - get_symbol_name(*parent, ns); - LONG offset = 0; - sym.get_offset(&offset); - get_vft_name(&ns, &id, ns.c_str(), offset); - - is_unnamed = false; - id_set = true; - } - - // udt fields and simple types are converted without allocating - // an ordinal number - if ( tag == SymTagData || ns.empty() ) - return convert_type(out, sym, parent, sym_id, tag) != cvt_failed; - - // give a unique name to unnamed types so they can be told apart - // this is a temporary name, it will be replaced by $hex.. - if ( is_unnamed ) - ns.sprnt("unnamed-%d", unnamed_idx++); - else - validate_name(&ns, VNT_TYPE); - - // some types can be defined multiple times. check if the name is already defined - bool defined_correctly = false; - bool defined_wrongly = false; - type_t tif_mod = 0; - if ( !id_set ) - id = get_type_ordinal(ti, ns.c_str()); - if ( id != 0 ) - { - tinfo_t tif; - tif.create_typedef(ti, id); - tif_mod = get_sym_modifiers(sym); - if ( tif.get_realtype() == BT_UNK ) - defined_wrongly = true; - else - defined_correctly = true; - } - if ( !defined_correctly ) - { - if ( begin_creation(tag, ns, &id) ) - { - // now convert the type information, recursive types won't bomb - tpinfo_t tpi2; - cvt_code_t cc = convert_type(&tpi2, sym, parent, sym_id, tag); - if ( cc != cvt_ok ) // failed or typedef - { - creating.erase(ns); - if ( cc == cvt_failed ) - return false; - // cvt_typedef - { - tinfo_t tif; - tif.create_typedef(ti, ns.c_str()); - tif.set_modifiers(tpi2.type.get_modifiers()); - tpdefs[sym_id] = tif; // reference to unknown typedef - } -RETT2: - out->type = tpi2.type; - return true; - } - - qtype type, fields; - if ( !tpi2.type.serialize(&type, &fields) ) - INTERR(30408); - - // Function types are saved as symbols - if ( tag == SymTagFunction ) - { - // the following may fail because of c++ overloaded functions - // do not check the error code - we cannot help it - tpi2.type.set_symbol_type(ti, ns.c_str(), NTF_SYMM); - type_created(BADADDR, 0, ns.c_str(), tpi2.type); - goto RETT2; - } - - bool reuse_anon_type = false; - if ( is_unnamed ) // this type will be referenced, so create a name for it - { - build_anon_type_name(&ns, type.begin(), fields.begin()); - id = get_type_ordinal(ti, ns.c_str()); - if ( id != 0 ) // this type already exists, just reuse it - { - creating.erase(ns); - reuse_anon_type = true; - } - tif_mod = get_sym_modifiers(sym); - } - if ( !reuse_anon_type ) - { - id = end_creation(ns); - int ntf_flags = NTF_NOBASE|NTF_FIXNAME; - if ( defined_wrongly ) - ntf_flags |= NTF_REPLACE; - if ( set_numbered_type(ti, id, ntf_flags, - ns.empty() ? NULL : ns.c_str(), - type.begin(), - fields.begin()) != TERR_OK ) - { - return 0; - } - tif_mod = tpi2.type.get_modifiers(); - } - if ( is_unnamed ) - unnamed_types.insert(id); - // msg("%d: %s\n name: %s\n", id, tpi2.dstr(), ns.c_str()); - type_created(BADADDR, id, NULL, tpi2.type); - } - else - { // in case of recursive call we need to preserve modifiers - tif_mod = get_sym_modifiers(sym); - } - } - if ( p_id != NULL ) - *p_id = id; - out->type.create_typedef(ti, id); - if ( tif_mod != 0 ) - out->type.set_modifiers(tif_mod); - return true; -} - - -//---------------------------------------------------------------------------- -bool til_builder_t::handle_symbol_at_ea(pdb_sym_t &/*sym*/, DWORD /*tag*/, ea_t /*ea*/, qstring & /*name*/) -{ - return true; -} - - -//---------------------------------------------------------------------------- -HRESULT til_builder_t::handle_symbol(pdb_sym_t &sym) -{ - DWORD id; - HRESULT hr = sym.get_symIndexId(&id); - if ( FAILED(hr) ) - return hr; - - if ( handled.find(id) != handled.end() ) - return S_OK; - handled.insert(id); - - DWORD tag = 0; - hr = sym.get_symTag(&tag); - if ( FAILED(hr) ) - return hr; - - switch ( tag ) - { - case SymTagNull: - case SymTagExe: - case SymTagCompiland: - case SymTagCompilandEnv: - case SymTagCustom: - case SymTagCustomType: - case SymTagManagedType: - case SymTagUDT: - case SymTagEnum: - case SymTagFunctionType: - case SymTagPointerType: - case SymTagArrayType: - case SymTagBaseType: - case SymTagTypedef: - case SymTagBaseClass: - case SymTagFunctionArgType: - case SymTagUsingNamespace: - case SymTagVTableShape: - case SymTagDimension: - return S_OK; - case SymTagCompilandDetails: - { - DWORD backEndVer; - if ( is_intel386(pdb_access->get_machine_type()) && sym.get_backEndMajor(&backEndVer) == S_OK ) - enregistered_bug = backEndVer <= 13; - } - return S_OK; - // new tags for msdia140 - case SymTagCoffGroup: - return S_OK; - default: - break; - } - - DWORD off = 0; - hr = sym.get_relativeVirtualAddress(&off); - if ( hr == S_OK ) - { - ea_t ea = get_load_address() + off; - qstring name; - sym.get_name(&name); - handle_symbol_at_ea(sym, tag, ea, name); - } - return S_OK; -} - - -//---------------------------------------------------------------------- -// Each time we encounter a toplevel type/func/whatever, we want to make -// sure the UI has had a chance to refresh itself. -struct toplevel_children_visitor_t : public pdb_access_t::children_visitor_t -{ - virtual HRESULT visit_child(pdb_sym_t &sym) override - { - user_cancelled(); - return do_visit_child(sym); - } - - virtual HRESULT do_visit_child(pdb_sym_t &sym) = 0; -}; - -//------------------------------------------------------------------------- -struct symbol_handler_t : public toplevel_children_visitor_t -{ - virtual HRESULT do_visit_child(pdb_sym_t &sym) override - { - return tb->handle_symbol(sym); - } - symbol_handler_t(til_builder_t *_tb) : tb(_tb) {} - til_builder_t *tb; -}; - -//------------------------------------------------------------------------- -HRESULT til_builder_t::handle_symbols(pdb_sym_t &global_sym) -{ - symbol_handler_t cp(this); - HRESULT hr; - while ( true ) - { - hr = pdb_access->iterate_subtags(global_sym, SymTagNull, cp); - if ( FAILED(hr) ) - break; - if ( !iterate_symbols_once_more(global_sym) ) - break; - } - return hr; -} - -//------------------------------------------------------------------------- -HRESULT til_builder_t::handle_publics(pdb_sym_t &global_sym) -{ - symbol_handler_t cp(this); - return pdb_access->iterate_children(global_sym, SymTagPublicSymbol, cp); -} - -//------------------------------------------------------------------------- -HRESULT til_builder_t::handle_globals(pdb_sym_t &global_sym) -{ - symbol_handler_t cp(this); - return pdb_access->iterate_children(global_sym, SymTagData, cp); -} - - -//---------------------------------------------------------------------- -HRESULT til_builder_t::handle_types(pdb_sym_t &global_sym) -{ - struct type_importer_t : public toplevel_children_visitor_t - { - til_builder_t *tb; - int counter; - virtual HRESULT do_visit_child(pdb_sym_t &sym) override - { - tpinfo_t tpi; - if ( tb->retrieve_type(&tpi, sym, parent, NULL) ) - counter++; - return S_OK; - } - type_importer_t(til_builder_t *_tb) : tb(_tb), counter(0) {} - }; - type_importer_t timp(this); - HRESULT hr = pdb_access->iterate_children(global_sym, SymTagEnum, timp); - if ( hr == S_OK ) - hr = pdb_access->iterate_children(global_sym, SymTagUDT, timp); - if ( hr == S_OK ) - hr = pdb_access->iterate_children(global_sym, SymTagTypedef, timp); - msg("PDB: loaded %d type%s\n", timp.counter, timp.counter != 1 ? "s" : ""); - return hr; -} - - -//---------------------------------------------------------------------------- -HRESULT til_builder_t::before_iterating(pdb_sym_t &) -{ - return S_OK; -} - - -//---------------------------------------------------------------------------- -HRESULT til_builder_t::after_iterating(pdb_sym_t &) -{ - return S_OK; -} - -//---------------------------------------------------------------------------- -HRESULT til_builder_t::build(pdb_sym_t &global_sym) -{ - HRESULT hr = before_iterating(global_sym); - if ( hr == S_OK ) - hr = handle_types(global_sym); - if ( (pdb_access->pdbargs.flags & PDBFLG_ONLY_TYPES) == 0 ) - { - if ( hr == S_OK ) - hr = handle_symbols(global_sym); - if ( hr == S_OK ) - hr = handle_globals(global_sym); - // handle_globals() will set the type and undecorated name for globals, - // and handle_publics() will set the decorated name for public symbols. - // We want both the type (from handle_globals()) and the decorated symbol - // name (from handle_publics()), since that gives the user more information - // about the variable and enables FLIRT to match rulefuncs based on the - // symbol name. - // For example, @__security_check_cookie@4 is used as a rulefunc by FLIRT, - // and that won't match with the undecorated name __security_check_cookie. - // Therefore, handle_publics() must be called *after* handle_globals(). - if ( hr == S_OK ) - hr = handle_publics(global_sym); - } - if ( hr == S_OK ) - { - create_vftables(); - hr = after_iterating(global_sym); - } - return hr; -} diff --git a/idasdk75/plugins/pdb/tilbuild.hpp b/idasdk75/plugins/pdb/tilbuild.hpp deleted file mode 100644 index 81e2a9c..0000000 --- a/idasdk75/plugins/pdb/tilbuild.hpp +++ /dev/null @@ -1,215 +0,0 @@ -#pragma once - -//---------------------------------------------------------------------------- -enum cvt_code_t -{ - cvt_failed, - cvt_ok, - cvt_typedef // conversion resulted in a typedef to a named type -}; - -//---------------------------------------------------------------------------- -// PBD provides the offset of a bitfield inside a bitfield group. -// We subclass udt_member_t in order to keep that information separate from -// the 'offset' field. -struct pdb_udt_member_t : public udt_member_t -{ - uint32 bit_offset; ///< member offset in bits from start of bitfield group -}; -DECLARE_TYPE_AS_MOVABLE(pdb_udt_member_t); -typedef qvector<pdb_udt_member_t> pdbudtmembervec_t; ///< vector of pdb udt member objects - -//---------------------------------------------------------------------------- -// stripped-down version of udt_type_data_t with only the fields used by pdb. -struct pdb_udt_type_data_t : public pdbudtmembervec_t -{ - size_t total_size; ///< total structure size in bytes - uint32 taudt_bits; ///< TA... and TAUDT... bits - bool is_union; ///< is union or struct? - - pdb_udt_type_data_t(void) - : total_size(0), - taudt_bits(0), - is_union(false) - { - } - - void convert_to_tinfo_udt(udt_type_data_t *out); -}; -DECLARE_TYPE_AS_MOVABLE(pdb_udt_type_data_t); - -//---------------------------------------------------------------------------- -class til_builder_t -{ -protected: - pdb_ctx_t &pv; -public: - - //---------------------------------------------------------------------------- - struct tpinfo_t - { - cvt_code_t cvt_code; - bool is_notype; - tinfo_t type; - til_t *ti; // FIXME: do we need this? - tpinfo_t(void) : cvt_code(cvt_ok), is_notype(false), ti(NULL) {} - tpinfo_t(til_t *_ti, const tinfo_t &t) : cvt_code(cvt_ok), is_notype(false), type(t), ti(_ti) {} - const char *dstr(void) const - { - if ( cvt_code == cvt_failed ) - return "#cvt_failed"; - - static qstring res; - if ( !type.print(&res) ) - res = "#print_failed"; - return res.c_str(); - } - }; - - //---------------------------------------------------------------------------- - til_builder_t(pdb_ctx_t &_pv, til_t *_ti, pdb_access_t *_pa) - : pv(_pv), - unnamed_idx(0), - level(0), - ti(_ti), - pdb_access(NULL), - enregistered_bug(false) - { - set_pdb_access(_pa); - } - - virtual ~til_builder_t() - { - typemap.clear(); - tpdefs.clear(); - handled.clear(); - creating.clear(); - unnamed_types.clear(); - } - - void set_pdb_access(pdb_access_t *_pdb_access) - { - pdb_access = _pdb_access; - } - - typedef std::map<DWORD, tpinfo_t> typemap_t; - typedef std::map<DWORD, tinfo_t> tpdefs_t; - typedef std::set<DWORD> idset_t; - typedef std::map<qstring, int> creating_t; - typedef std::set<uint32> unnamed_t; - - struct vft_info_t - { - udt_type_data_t udt; // collected vft members - qstring base0; // base vftable at offset 0 - - vft_info_t() { udt.taudt_bits |= TAUDT_VFTABLE; } - bool empty() const { return udt.empty() && base0.empty(); } - }; - typedef std::map<qstring, vft_info_t> vftmap_t; - - // remove `anonymous-namespace':: - // also remove `anonymous namespace':: - void remove_anonymous_namespaces(qstring &storage); - - bool get_symbol_type(tpinfo_t *out, pdb_sym_t &sym, int *p_id); - bool retrieve_type(tpinfo_t *out, pdb_sym_t &sym, pdb_sym_t *parent, int *p_id); - bool retrieve_arguments( - pdb_sym_t &sym, - func_type_data_t &fi, - pdb_sym_t *funcSym); - cm_t convert_cc(DWORD cc0) const; - bool get_variant_string_value(qstring *out, pdb_sym_t &sym) const; - uint32 get_variant_long_value(pdb_sym_t &sym) const; - bool begin_creation(DWORD tag, const qstring &name, uint32 *p_id); - uint32 end_creation(const qstring &name); - bool is_member_func(tinfo_t *class_type, pdb_sym_t &typeSym, pdb_sym_t *funcSym); - bool is_frame_reg(int regnum) const; - bool is_complex_return(pdb_sym_t &sym) const; - bool is_unnamed_tag_typedef(const tinfo_t &tif) const; - bool is_intel386(DWORD machine_type) const; - bool is_arm(DWORD machine_type) const; - int get_symbol_funcarg_info( - funcarg_t *out, - pdb_sym_t &sym, - DWORD /*dwDataKind*/, - DWORD locType, - int stack_off); - void enum_function_args(pdb_sym_t &sym, func_type_data_t &args); - cvt_code_t verify_union( - pdb_udt_type_data_t *out, - pdb_udt_type_data_t::iterator p1, - pdb_udt_type_data_t::const_iterator p2) const; - cvt_code_t create_union( - tinfo_t *out, - size_t *p_total_size, - pdb_udt_type_data_t::iterator p1, - pdb_udt_type_data_t::const_iterator p2) const; - cvt_code_t convert_basetype(tpinfo_t *out, DWORD baseType, int size) const; - cvt_code_t make_vtable_struct(tinfo_t *out, pdb_sym_t &sym); - cvt_code_t convert_udt(tinfo_t *out, pdb_sym_t &sym, DWORD64 size); - cvt_code_t create_udt(tinfo_t *out, pdb_udt_type_data_t *udt, int udtKind) const; - cvt_code_t create_udt_ref(tinfo_t *out, pdb_udt_type_data_t *udt, int udt_kind) const; - cvt_code_t really_convert_type(tpinfo_t *out, pdb_sym_t &sym, pdb_sym_t *parent, DWORD tag); - cvt_code_t convert_type( - tpinfo_t *out, - pdb_sym_t &sym, - pdb_sym_t *parent, - DWORD type, - DWORD tag); - cvt_code_t handle_overlapping_members(pdb_udt_type_data_t *udt) const; - // Will iterate on children, and call handle_function_child() - HRESULT handle_symbols(pdb_sym_t &pGlobal); - HRESULT handle_globals(pdb_sym_t &pGlobal); - HRESULT handle_publics(pdb_sym_t &pGlobal); - HRESULT handle_types(pdb_sym_t &pGlobal); - HRESULT build(pdb_sym_t &pGlobal); - ea_t get_load_address() const { return pdb_access->get_base_address(); } - HRESULT handle_symbol(pdb_sym_t &sym); - size_t get_symbol_type_length(pdb_sym_t &sym) const; - void create_vftables(); - // check for MS or IDA vftable name, - // get type ordinal of vftable - // returns the type is creating - bool get_vft_name(qstring *vft_name, uint32 *ord, const char *udt_name, uint32_t offset=0); - - virtual HRESULT before_iterating(pdb_sym_t &global_sym); - virtual HRESULT after_iterating(pdb_sym_t &global_sym); - virtual bool iterate_symbols_once_more(pdb_sym_t & /*global_sym*/) { return false; } - virtual bool get_symbol_name(pdb_sym_t &sym, qstring &storage); - virtual bool handle_symbol_at_ea( - pdb_sym_t &sym, - DWORD tag, - ea_t ea, - qstring &name); - virtual void type_created(ea_t /*ea*/, int /*id*/, const char * /*name*/, const tinfo_t & /*ptr*/) const; - virtual void handle_function_type(pdb_sym_t &fun_sym, ea_t ea); - virtual HRESULT handle_function_child( - pdb_sym_t &fun_sym, - ea_t ea, - pdb_sym_t &child_sym, - DWORD child_tag, - DWORD child_loc_type); - virtual cvt_code_t handle_unnamed_overlapping_member( - pdb_udt_type_data_t * /*udt*/, - qstack<qstring> * /*union_names*/, - qstring * /*name*/) const - { - return cvt_ok; - } - -protected: - typemap_t typemap; // id -> type info - tpdefs_t tpdefs; // id -> enum type defined in base til - idset_t handled; // set of handled symbols - creating_t creating; - unnamed_t unnamed_types; - vftmap_t vftmap; // vftable name -> vft info - int unnamed_idx; - int level; - -public: - til_t *ti; - pdb_access_t *pdb_access; - bool enregistered_bug; -}; diff --git a/idasdk75/plugins/plugin.mak b/idasdk75/plugins/plugin.mak deleted file mode 100644 index 20ec9d2..0000000 --- a/idasdk75/plugins/plugin.mak +++ /dev/null @@ -1,21 +0,0 @@ - -#__FUZZ_PLUGINS__=1 - -SRC_PATH = $(IDA)plugins/ -ifdef EXAMPLE - BIN_PATH = $(R)plugins-examples/ -else - BIN_PATH = $(R)plugins/ -endif - -ifndef NO_DEFAULT_TARGETS - BASE_OBJS += $(F)$(PROC)$(O) -endif - -include ../../module.mak - -ifdef __NT__ - ifndef NDEBUG - $(MODULES): PDBFLAGS = /PDB:$(@:$(DLLEXT)=.pdb) - endif -endif diff --git a/idasdk75/plugins/procext/makefile b/idasdk75/plugins/procext/makefile deleted file mode 100644 index 4f743cb..0000000 --- a/idasdk75/plugins/procext/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=nec - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)nec$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp nec.cpp diff --git a/idasdk75/plugins/procext/nec.cpp b/idasdk75/plugins/procext/nec.cpp deleted file mode 100644 index d27bb6f..0000000 --- a/idasdk75/plugins/procext/nec.cpp +++ /dev/null @@ -1,311 +0,0 @@ -/* - * This is a sample plugin module - * It extends the IBM PC processor module to disassemble some NEC V20 instructions - * This is a sample file, it supports just two instructions! - * - */ - -#include <ida.hpp> -#include <idp.hpp> -#include <bytes.hpp> -#include <loader.hpp> -#include <kernwin.hpp> - -//-------------------------------------------------------------------------- -// Context data for the plugin. This object is created by the init() -// function and hold all local data. -struct plugin_ctx_t : public plugmod_t, public event_listener_t -{ - ea_t ea = 0; // current address within the instruction - - netnode nec_node; - bool hooked = false; - - plugin_ctx_t(); - ~plugin_ctx_t(); - - // This function is called when the user invokes the plugin. - virtual bool idaapi run(size_t) override; - // This function is called upon some events. - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; - - size_t ana(insn_t &insn); - void process_rm(insn_t &insn, op_t &x, uchar postbyte); -}; - -static const char node_name[] = "$ sample NEC processor extender parameters"; - -// Some definitions from IBM PC: - -#define segrg specval_shorts.high // IBM PC expects the segment address - // to be here -#define aux_short 0x0020 // short (byte) displacement used -#define aux_basess 0x0200 // SS based instruction - -#define R_ss 18 -#define R_ds 19 -//-------------------------------------------------------------------------- -// This plugin supports just 2 instructions: -// Feel free to add more... - -// 0FH 20H ADD4S ; Addition for packed BCD strings -// 0FH 12H Postbyte CLEAR1 reg/mem8,CL ; Clear one bit - -enum nec_insn_type_t -{ - NEC_add4s = CUSTOM_INSN_ITYPE, - NEC_clear1, -}; - -//---------------------------------------------------------------------- -static int get_dataseg(insn_t &insn, int defseg) -{ - if ( defseg == R_ss ) - insn.auxpref |= aux_basess; - return defseg; -} - -//-------------------------------------------------------------------------- -// -// process r/m byte of the instruction -// -void plugin_ctx_t::process_rm(insn_t &insn, op_t &x, uchar postbyte) -{ - int Mod = (postbyte >> 6) & 3; - x.reg = postbyte & 7; - if ( Mod == 3 ) // register - { - if ( x.dtype == dt_byte ) - x.reg += 8; - x.type = o_reg; - } - else // memory - { - if ( Mod == 0 && x.reg == 6 ) - { - x.type = o_mem; - x.offb = uchar(ea-insn.ea); - x.addr = get_word(ea); ea+=2; - x.segrg = (uint16)get_dataseg(insn, R_ds); - } - else - { - x.type = o_phrase; // x.phrase contains the base register - x.addr = 0; - int reg = (x.phrase == 2 || x.phrase == 3 || x.phrase == 6) ? R_ss : R_ds; - x.segrg = (uint16)get_dataseg(insn, reg); - // [bp+si],[bp+di],[bp] by SS - if ( Mod != 0 ) - { - x.type = o_displ; // i.e. phrase + offset - x.offb = uchar(ea-insn.ea); - if ( Mod == 1 ) - { - x.addr = char(get_byte(ea++)); - insn.auxpref |= aux_short; - } - else - { - x.addr = get_word(ea); ea+=2; - } - } - } - } -} - -//-------------------------------------------------------------------------- -// Analyze an instruction and fill the 'insn' structure -size_t plugin_ctx_t::ana(insn_t &insn) -{ - int code = get_byte(ea++); - if ( code != 0x0F ) - return 0; - code = get_byte(ea++); - switch ( code ) - { - case 0x20: - insn.itype = NEC_add4s; - return 2; - case 0x12: - insn.itype = NEC_clear1; - { - uchar postbyte = get_byte(ea++); - process_rm(insn, insn.Op1, postbyte); - insn.Op2.type = o_reg; - insn.Op2.reg = 9; // 9 is CL for IBM PC - return size_t(ea - insn.ea); - } - default: - return 0; - } -} - -//-------------------------------------------------------------------------- -// Return the instruction mnemonics -const char *get_insn_mnem(const insn_t &insn) -{ - if ( insn.itype == NEC_add4s ) - return "add4s"; - return "clear1"; -} - -//-------------------------------------------------------------------------- -// This function can be hooked to various kernel events. -// In this particular plugin we hook to the HT_IDP group. -// As soon the kernel needs to decode and print an instruction, it will -// generate some events that we intercept and provide our own response. -// -// We extend the processor module to disassemble opcode 0x0F -// (This is a hypothetical example) -// There are 2 different possible approaches for the processor extensions: -// A. Quick & dirty -// Implement reaction to ev_ana_insn and ev_out_insn. -// The first checks if the instruction is valid. -// The second generates its text. -// B. Thourough and clean -// Implement all relevant callbacks. -// ev_ana_insn fills the 'insn' structure. -// ev_emu_insn creates all xrefs using ua_add_[cd]ref functions. -// ev_out_insn generates the textual representation of the instruction. -// It is required only if the instruction requires special processing -// or the processor module cannot handle the custom instruction for -// any reason. -// ev_out_operand generates the operand representation (only if the -// operand requires special processing). -// ev_out_mnem generates the instruction mnemonics. -// The main difference between these 2 approaches is in the creation of -// cross-references and the amount of special processing required by the -// new instructions. - -// The quick & dirty approach. -// We just produce the instruction mnemonics along with its operands. -// No cross-references are created. No special processing. -ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case processor_t::ev_ana_insn: - { - insn_t *insn = va_arg(va, insn_t *); - ea = insn->ea; - size_t length = ana(*insn); - if ( length ) - { - insn->size = (uint16)length; - return insn->size; // event processed - } - } - break; - case processor_t::ev_out_mnem: - { - outctx_t *ctx = va_arg(va, outctx_t *); - const insn_t &insn = ctx->insn; - if ( insn.itype >= CUSTOM_INSN_ITYPE ) - { - ctx->out_line(get_insn_mnem(insn), COLOR_INSN); - return 1; - } - } - break; - } - return 0; // event is not processed -} - -//-------------------------------------------------------------------------- -// Initialize the plugin. -// IDA will call this function only once. -// If this function returns nullptr, IDA will unload the plugin. -// Otherwise the plugin returns a pointer to a newly created context structure. -// -// In this example we check the processor type and make the decision. -// You may or may not check any other conditions to decide what you do: -// whether your plugin wants to work with the database or not. - -static plugmod_t *idaapi init() -{ - processor_t &ph = PH; - if ( ph.id != PLFM_386 ) - return nullptr; - return new plugin_ctx_t; -} - -//------------------------------------------------------------------------- -plugin_ctx_t::plugin_ctx_t() -{ - nec_node.create(node_name); - hooked = nec_node.altval(0) != 0; - if ( hooked ) - { - hook_event_listener(HT_IDP, this); - msg("NEC V20 processor extender is enabled\n"); - } -} - -//-------------------------------------------------------------------------- -// Terminate the plugin. -// This destructor will be called before unloading the plugin. -plugin_ctx_t::~plugin_ctx_t() -{ - // listeners are uninstalled automatically - // when the owner module is unloaded -} - -//-------------------------------------------------------------------------- -// The plugin method -// This is the main function of plugin. -// It will be called when the user selects the plugin from the menu. -// The input argument is usually zero. Non-zero values can be specified -// by using load_and_run_plugin() or through plugins.cfg file (discouraged). -bool idaapi plugin_ctx_t::run(size_t) -{ - if ( hooked ) - unhook_event_listener(HT_IDP, this); - else - hook_event_listener(HT_IDP, this); - hooked = !hooked; - nec_node.create(node_name); - nec_node.altset(0, hooked); - info("AUTOHIDE NONE\n" - "NEC V20 processor extender now is %s", hooked ? "enabled" : "disabled"); - return true; -} - -//-------------------------------------------------------------------------- -static const char comment[] = "NEC V20 processor extender"; -static const char help[] = - "A sample plugin module\n" - "\n" - "This module shows you how to create plugin modules.\n" - "\n" - "It supports some NEC V20 instructions\n" - "and shows the current address.\n"; - -//-------------------------------------------------------------------------- -// This is the preferred name of the plugin module in the menu system -// The preferred name may be overridden in plugins.cfg file - -static const char desired_name[] = "NEC V20 processor extender"; - -// This is the preferred hotkey for the plugin module -// The preferred hotkey may be overridden in plugins.cfg file - -static const char desired_hotkey[] = ""; - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_PROC // this is a processor extension plugin -| PLUGIN_MULTI, // this plugin can work with multiple idbs in parallel - init, // initialize - nullptr, - nullptr, - comment, // long comment about the plugin. not used. - help, // multiline help about the plugin. not used. - desired_name, // the preferred short name of the plugin - desired_hotkey // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/pyplg.mak b/idasdk75/plugins/pyplg.mak deleted file mode 100644 index 419aec1..0000000 --- a/idasdk75/plugins/pyplg.mak +++ /dev/null @@ -1,13 +0,0 @@ - -# definitions for idapython (& other plugins dynamically linked to Python) -ifdef __NT__ - PYTHON_CFLAGS := -I"$(PYTHON_ROOT)/include" - ifeq ($(PYTHON_VERSION_MAJOR),3) - PYTHON_LDFLAGS := "$(PYTHON_ROOT)/libs/python$(PYTHON_VERSION_MAJOR).lib" - else - PYTHON_LDFLAGS := "$(PYTHON_ROOT)/libs/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib" - endif -else - PYTHON_CFLAGS := $(shell $(PYTHON)-config --includes) - PYTHON_LDFLAGS := $(shell $(PYTHON)-config --ldflags) -endif diff --git a/idasdk75/plugins/qwindow/makefile b/idasdk75/plugins/qwindow/makefile deleted file mode 100644 index 32be02e..0000000 --- a/idasdk75/plugins/qwindow/makefile +++ /dev/null @@ -1,12 +0,0 @@ -PROC=qwindow -O1=moc_myactions - -include ../qtplugin.mak - -# MAKEDEP dependency list ------------------ -$(F)moc_myactions$(O): $(F)moc_myactions.cpp myactions.h -$(F)qwindow$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp myactions.h qwindow.cpp diff --git a/idasdk75/plugins/readme.txt b/idasdk75/plugins/readme.txt deleted file mode 100644 index a76e8ad..0000000 --- a/idasdk75/plugins/readme.txt +++ /dev/null @@ -1,34 +0,0 @@ - - - This directory contains sample plugin modules for IDA. - - Plugin modules are accessible by the user in two ways: - - - they appear as menu items in menu Edit|Plugins - - they can be invoked by hotkeys - - A plugin has full access to the database and can interact with - the user. - - IDA looks for plugins in PLUGINS subdirectory. - In this directory there is also a configuration file. - It is not necessary for a plugin to appear in the configuration file. - Even if a plugin is not there IDA will load it. - The configuration file allows the user to reassign the hotkeys, - to change the plugin name as it appears in the menu or to change - the argument passed to the plugin. - - A plugin has one exported entry (it should has the "PLUGIN" name). - The entry is a plugin descriptor (plugin_t). - It contains pointers to the following functions: - - - init: is called when the plugin is loaded - - run: is called when the user calls the plugin - - term: is called before the plugin is unloaded - - run() function is the function which will do the real work. - It has full access to the database (see include files for the - description of IDA API). Also it can interact with the user - (most of these functions are in kernwin.hpp file). - - diff --git a/idasdk75/plugins/snapshots/makefile b/idasdk75/plugins/snapshots/makefile deleted file mode 100644 index d1d0a75..0000000 --- a/idasdk75/plugins/snapshots/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=snapshots - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)snapshots$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - snapshots.cpp diff --git a/idasdk75/plugins/snapshots/snapshots.cpp b/idasdk75/plugins/snapshots/snapshots.cpp deleted file mode 100644 index 16c1956..0000000 --- a/idasdk75/plugins/snapshots/snapshots.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* -* This is a sample plugin to demonstrate the snapshot management API -*/ - -#include <ida.hpp> -#include <idp.hpp> -#include <loader.hpp> -#include <kernwin.hpp> -#include <algorithm> - -//-------------------------------------------------------------------------- -class snapman_t : public chooser_t -{ - struct snapdesc_t - { - snapshot_t *ss; - qstring title; - qstring date; - }; - typedef qvector<snapdesc_t> sdlist_t; - snapshot_t root; - sdlist_t sdlist; - - static const int widths_[2]; - static const char *const header_[2]; - - static void idaapi done_restore(const char *err_msg, void *) - { - if ( err_msg != NULL ) - warning("ICON ERROR\nError restoring: %s", err_msg); - else - warning("Restored successfully!"); - } - - void build_tree_list(snapshot_t *n, int level = 0) - { - if ( n != &root ) - { - // Insert new description record - snapdesc_t &sd = sdlist.push_back(); - - // Compute title - for ( int i=0; i < level; i++ ) - sd.title += " "; - if ( n->id == root.id ) - sd.title += "->"; - sd.title += n->desc; - - // Compute date - char ss_date[MAXSTR]; - qstrftime64(ss_date, sizeof(ss_date), "%Y-%m-%d %H:%M:%S", n->id); - sd.date = ss_date; - // Store ss - sd.ss = n; - } - for ( snapshots_t::iterator it=n->children.begin(); it != n->children.end(); ++it ) - build_tree_list(*it, level+1); - } - - snapdesc_t *get_item(uint32 n) - { - return n >= sdlist.size() ? NULL : &sdlist[n]; - } - const snapdesc_t *get_item(uint32 n) const - { - return n >= sdlist.size() ? NULL : &sdlist[n]; - } - -public: - bool init() override - { - sdlist.clear(); - root.clear(); - if ( !build_snapshot_tree(&root) ) - { - warning("Snapshot tree cannot be built.\nNo snapshots exist?"); - return false; - } - - // Convert the tree to a list - build_tree_list(&root); - if ( sdlist.empty() ) - { - warning("Snapshot tree empty!"); - return false; - } - return true; - } - - snapman_t() - : chooser_t(CH_MODAL | CH_KEEP | CH_CAN_INS | CH_CAN_DEL | CH_CAN_EDIT, - qnumber(widths_), widths_, header_, - "Simple snapshot manager"), - root(), - sdlist() {} - - virtual size_t idaapi get_count() const override - { - return sdlist.size(); - } - - virtual void idaapi get_row( - qstrvec_t *cols_, - int *, - chooser_item_attrs_t *, - size_t n) const override - { - const snapdesc_t *sd = get_item(n); - QASSERT(561, sd != NULL); - - qstrvec_t &cols = *cols_; - cols[0] = sd->date; - cols[1] = sd->title; - } - - virtual cbret_t idaapi ins(ssize_t n) override - { - qstring desc = "snapshot description"; - if ( !ask_str(&desc, HIST_CMT, "Enter snapshot description") ) - return cbret_t(); // nothing changed - - qstring err_msg; - snapshot_t new_attr; - qstrncpy(new_attr.desc, desc.c_str(), sizeof(new_attr.desc)); - if ( !take_database_snapshot(&new_attr, &err_msg) ) - { - warning("Failed to create a snapshot, error: %s", err_msg.c_str()); - return cbret_t(); // nothing changed - } - msg("Created new snapshot: %s\n", new_attr.filename); - init(); - // we preserve the selection - // FIXME use get_item_index() - return n; - } - - virtual cbret_t idaapi del(size_t n) override - { - const snapdesc_t *sd = get_item(n); - if ( sd == NULL ) - return cbret_t(); - - // Simply delete the file - qunlink(sd->ss->filename); - - // Rebuild the list - init(); - - return adjust_last_item(n); // take in account deleting of the last item - } - - virtual cbret_t idaapi edit(size_t n) override - { - snapdesc_t *sd = get_item(n); - if ( sd == NULL ) - return cbret_t(); - - qstring desc = sd->ss->desc; - if ( !ask_str(&desc, HIST_CMT, "Enter new snapshot description") ) - return cbret_t(); - - // Update the description - qstrncpy(sd->ss->desc, desc.c_str(), sizeof(sd->ss->desc)); - update_snapshot_attributes(sd->ss->filename, &root, sd->ss, SSUF_DESC); - return n; - } - - // calculate the location of the default item only, - // `item_data` is a pointer to a snapshot ID - virtual ssize_t idaapi get_item_index(const void *item_data) const override - { - qtime64_t item_id = *(const qtime64_t *)item_data; - for ( size_t i = 0; i < sdlist.size(); ++i ) - { - if ( sdlist[i].ss->id == item_id ) - return i; - } - return NO_SELECTION; - } - - void show() - { - // now open the window - ssize_t n = ::choose(this, &root.id); - if ( n >= 0 ) - { - snapdesc_t *sd = get_item(n); - if ( sd != NULL && sd->ss != NULL ) - restore_database_snapshot(sd->ss, done_restore, NULL); - } - } -}; -DECLARE_TYPE_AS_MOVABLE(snapman_t::snapdesc_t); - -// column widths -const int snapman_t::widths_[2] = -{ - 12, // Date - 70, // Description -}; - -// column headers -const char *const snapman_t::header_[2] = -{ - "Date", // 0 - "Description", // 1 -}; - - -//-------------------------------------------------------------------------- -struct plugin_ctx_t : public plugmod_t -{ - virtual bool idaapi run(size_t) override; -}; - -//-------------------------------------------------------------------------- -bool idaapi plugin_ctx_t::run(size_t) -{ - snapman_t sm; - if ( !sm.init() ) - return false; - - sm.show(); - return true; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - // Display help - msg( - "Simple snapshot manager loaded!\n" - "Press Shift+F8 to toggle the plugin\n" - "Inside the snapshots window, press:\n" - " - Insert: to take a snapshot\n" - " - Delete: to delete\n" - " - Edit: to edit the snapshot description\n" - "\n" - "Click on:\n" - " - Ok: to restore the selected snapshot\n" - " - Cancel: close without doing anything\n"); - - // The plugin flags must include PLUGIN_FIX as well - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - // plugin flags - PLUGIN_FIX // Load plugin when IDA starts and keep it in the - // memory until IDA stops - | PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel - init, // initialize - nullptr, - nullptr, - "This is a sample plugin. It displays the list of snapshots", - // long comment about the plugin - "A snapshot manager sample plugin\n" - "\n" - "This plugin allows you to list and restore snapshots.\n", - // multiline help about the plugin - "Simple snapshot manager", // the preferred short name of the plugin - "Shift-F8", // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/tracer/makefile b/idasdk75/plugins/tracer/makefile deleted file mode 100644 index b85e88f..0000000 --- a/idasdk75/plugins/tracer/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=tracer - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)tracer$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp tracer.cpp diff --git a/idasdk75/plugins/tracing_api/makefile b/idasdk75/plugins/tracing_api/makefile deleted file mode 100644 index cfe128b..0000000 --- a/idasdk75/plugins/tracing_api/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=tracing_api - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)tracing_api$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp tracing_api.cpp diff --git a/idasdk75/plugins/tracing_api/tracing_api.cpp b/idasdk75/plugins/tracing_api/tracing_api.cpp deleted file mode 100644 index 569dc1c..0000000 --- a/idasdk75/plugins/tracing_api/tracing_api.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* Tracing API sample plugin. - * - * Copyright (c) 2012-2020 Hex-Rays, support@hex-rays.com - * - * This sample plugin demonstrates how to use the tracing events API - * in IDA v6.3 - * - * The tracing events API allow you to record, save and load traces, - * find register values as well as memory pointed by registers. - * - * This sample plugin looks for an ASCII string in the recorded - * trace's memory - * - */ - -//--------------------------------------------------------------------------- -#include <idp.hpp> -#include <dbg.hpp> -#include <loader.hpp> - -//-------------------------------------------------------------------------- -struct plugin_ctx_t : public plugmod_t -{ - bytevec_t last_found; // last found buffer - - virtual bool idaapi run(size_t) override; - bool find_memory_tev(int i, const char *mem); -}; - -//-------------------------------------------------------------------------- -inline bool __memmem( - const unsigned char *where, - size_t size1, - const char *what, - size_t size2) -{ - if ( size2 > size1 ) - return false; - else if ( size2 == size1 ) - return memcmp(where, what, size1) == 0; - - int i = size1 - size2; - do - { - if ( where[i] == what[0] ) - { - if ( memcmp(where+i, what, size2) == 0 ) - return true; - } - } - while ( --i >= 0 ); - - return false; -} - -//-------------------------------------------------------------------------- -static void dump_memreg(const unsigned char *buf, size_t size) -{ - msg("Memory found: "); - for ( int i = 0; i < size; i++ ) - { - if ( isprint(buf[i]) ) - msg("%c", buf[i]); - else - msg("."); - } - msg("\n"); -} - -//-------------------------------------------------------------------------- -bool plugin_ctx_t::find_memory_tev(int i, const char *mem) -{ - // retrieve the memory map - memreg_infos_t memmap; - if ( get_insn_tev_reg_mem(i, &memmap) ) - { - // iterate over all elements in the map - memreg_infos_t::iterator p; - for ( p = memmap.begin(); p != memmap.end(); ++p ) - { - memreg_info_t reg = *p; - // compare the memory of this memreg_info_t object with the given - // string mem - if ( last_found != reg.bytes && __memmem(reg.bytes.begin(), reg.bytes.size(), mem, strlen(mem)) ) - { - last_found = reg.bytes; - // if found, print it to the output window - dump_memreg(reg.bytes.begin(), reg.bytes.size()); - return true; - } - } - } - return false; -} - -//-------------------------------------------------------------------------- -bool idaapi plugin_ctx_t::run(size_t) -{ - // clear the last found buffer - last_found.clear(); - - // get the number of recorded events - size_t total = get_tev_qty(); - if ( total == 0 ) - { - msg("No recorded events."); - return true; - } - - qstring mem_search; - if ( !ask_str(&mem_search, - HIST_SRCH, - "Enter the string to search in the recorded trace:") - || mem_search.empty() ) - { - return true; - } - - // iterate over all the recorded events - for ( int i = total; i != 0; i-- ) - { - // if the recorded event is an instruction trace event - // search the string mem_search in the recorded memory - tev_info_t tev; - if ( get_tev_info(i, &tev) && tev.type == tev_insn ) - { - // if the string is found in this instruction trace event's memory - // print the tev object address, thread and number if the output - // window - const char *str = mem_search.begin(); - if ( find_memory_tev(i, str) ) - msg("%a: tid %d: string '%s' found in tev %d.\n", tev.ea, tev.tid, str, i); - } - } - return true; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel - init, // initialize - nullptr, - nullptr, - "Search for a string in the recorded trace memory", // long comment about the plugin - "", // multiline help about the plugin - "Trace search", // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/ugraph/makefile b/idasdk75/plugins/ugraph/makefile deleted file mode 100644 index a2cbff3..0000000 --- a/idasdk75/plugins/ugraph/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ugraph - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ugraph$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ugraph.cpp diff --git a/idasdk75/plugins/ugraph/ugraph.cpp b/idasdk75/plugins/ugraph/ugraph.cpp deleted file mode 100644 index cf8512e..0000000 --- a/idasdk75/plugins/ugraph/ugraph.cpp +++ /dev/null @@ -1,439 +0,0 @@ -/* - * This is a sample plugin module. - * It demonstrates how to create a graph viewer with an aribtrary graph. - * - * It can be compiled by the following compilers: - * - * - Borland C++, CBuilder, free C++ - * - */ - -#include <ida.hpp> -#include <idp.hpp> -#include <graph.hpp> -#include <loader.hpp> -#include <kernwin.hpp> - -//------------------------------------------------------------------------- -struct plugin_ctx_t; -struct change_layout_ah_t : public action_handler_t -{ - plugin_ctx_t &plg; - change_layout_ah_t(plugin_ctx_t &_plg) : plg(_plg) {} - virtual int idaapi activate(action_activation_ctx_t *ctx) override; - virtual action_state_t idaapi update(action_update_ctx_t *ctx) override; -}; - -//-------------------------------------------------------------------------- -struct plugin_ctx_t : public plugmod_t, public event_listener_t -{ - change_layout_ah_t change_layout_ah = change_layout_ah_t(*this); - const action_desc_t change_layout_desc = ACTION_DESC_LITERAL_PLUGMOD( - "ugraph:ChangeLayout", - "User function", - &change_layout_ah, - this, - NULL, - NULL, - -1); - - qstrvec_t graph_text; - graph_viewer_t *gv = nullptr; - - plugin_ctx_t() - { - hook_event_listener(HT_VIEW, this); - } - ~plugin_ctx_t() - { - // listeners are uninstalled automatically - // when the owner module is unloaded - } - - virtual bool idaapi run(size_t) override; - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; - static ssize_t idaapi gr_callback(void *ud, int code, va_list va); -}; - -//------------------------------------------------------------------------- -int idaapi change_layout_ah_t::activate(action_activation_ctx_t *ctx) -{ - plg.gv = (graph_viewer_t *)ctx->widget; - mutable_graph_t *g = get_viewer_graph(plg.gv); - int code = ask_buttons("Circle", "Tree", "Digraph", 1, "Please select layout type"); - node_info_t ni; - ni.bg_color = 0x44FF55; - ni.text = "Hello from plugin!"; - set_node_info(g->gid, 7, ni, NIF_BG_COLOR | NIF_TEXT); - g->current_layout = code + 2; - g->circle_center = point_t(200, 200); - g->circle_radius = 200; - g->redo_layout(); - refresh_viewer(plg.gv); - return 1; -} - -//------------------------------------------------------------------------- -action_state_t idaapi change_layout_ah_t::update(action_update_ctx_t *ctx) -{ - if ( ctx->widget == (TWidget *)plg.gv ) - return AST_ENABLE_FOR_WIDGET; - else - return AST_DISABLE_FOR_WIDGET; -} - -//-------------------------------------------------------------------------- -static const char *get_node_name(int n) -{ - switch ( n ) - { - case 0: return COLSTR("This", SCOLOR_MACRO); - case 1: return COLSTR("is", SCOLOR_CNAME); - case 2: return "a"; - case 3: return COLSTR("sample", SCOLOR_DNAME); - case 4: return COLSTR("graph", SCOLOR_IMPNAME); - case 5: return COLSTR("viewer", SCOLOR_ERROR); - case 6: return COLSTR("window!", SCOLOR_DNUM) "\n(with colorful names)"; - } - return "?"; -} - -//-------------------------------------------------------------------------- -ssize_t idaapi plugin_ctx_t::gr_callback(void *ud, int code, va_list va) -{ - plugin_ctx_t &ctx = *(plugin_ctx_t *)ud; - ssize_t result = 0; - switch ( code ) - { - case grcode_calculating_layout: - // calculating user-defined graph layout - // in: mutable_graph_t *g - // out: 0-not implemented - // 1-graph layout calculated by the plugin - msg("calculating graph layout...\n"); - break; - - case grcode_clicked: // a graph has been clicked - // in: graph_viewer_t *gv - // selection_item_t *current_item - // out: 0-ok, 1-ignore click - { - graph_viewer_t *v = va_arg(va, graph_viewer_t *); qnotused(v); - selection_item_t *it = va_arg(va, selection_item_t *); qnotused(it); - graph_item_t *m = va_arg(va, graph_item_t *); - msg("clicked on "); - switch ( m->type ) - { - case git_none: - msg("background\n"); - break; - case git_edge: - msg("edge (%d, %d)\n", m->e.src, m->e.dst); - break; - case git_node: - msg("node %d\n", m->n); - break; - case git_tool: - msg("toolbutton %d\n", m->b); - break; - case git_text: - msg("text (x,y)=(%d,%d)\n", m->p.x, m->p.y); - break; - case git_elp: - msg("edge layout point (%d, %d) #%d\n", m->elp.e.src, m->elp.e.dst, m->elp.pidx); - break; - } - } - break; - - case grcode_dblclicked: // a graph node has been double clicked - // in: graph_viewer_t *gv - // selection_item_t *current_item - // out: 0-ok, 1-ignore click - { - graph_viewer_t *v = va_arg(va, graph_viewer_t *); - selection_item_t *s = va_arg(va, selection_item_t *); - msg("%p: dblclicked on ", v); - if ( s == NULL ) - msg("background\n"); - else if ( s->is_node ) - msg("node %d\n", s->node); - else - msg("edge (%d, %d) layout point #%d\n", s->elp.e.src, s->elp.e.dst, s->elp.pidx); - } - break; - - case grcode_creating_group: - // a group is being created - // in: mutable_graph_t *g - // intvec_t *nodes - // out: 0-ok, 1-forbid group creation - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - intvec_t &nodes = *va_arg(va, intvec_t *); - msg("%p: creating group", g); - for ( intvec_t::iterator p=nodes.begin(); p != nodes.end(); ++p ) - msg(" %d", *p); - msg("...\n"); - } - break; - - case grcode_deleting_group: - // a group is being deleted - // in: mutable_graph_t *g - // int old_group - // out: 0-ok, 1-forbid group deletion - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - int group = va_argi(va, int); - msg("%p: deleting group %d\n", g, group); - } - break; - - case grcode_group_visibility: - // a group is being collapsed/uncollapsed - // in: mutable_graph_t *g - // int group - // bool expand - // out: 0-ok, 1-forbid group modification - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - int group = va_argi(va, int); - bool expand = va_argi(va, bool); - msg("%p: %scollapsing group %d\n", g, expand ? "un" : "", group); - } - break; - - case grcode_gotfocus: // a graph viewer got focus - // in: graph_viewer_t *gv - // out: must return 0 - { - graph_viewer_t *g = va_arg(va, graph_viewer_t *); - msg("%p: got focus\n", g); - } - break; - - case grcode_lostfocus: // a graph viewer lost focus - // in: graph_viewer_t *gv - // out: must return 0 - { - graph_viewer_t *g = va_arg(va, graph_viewer_t *); - msg("%p: lost focus\n", g); - } - break; - - case grcode_user_refresh: // refresh user-defined graph nodes and edges - // in: mutable_graph_t *g - // out: success - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - msg("%p: refresh\n", g); - // our graph is like this: - // 0 -> 1 -> 2 - // \-> 3 -> 4 -> 5 -> 6 - // ^ / - // \-------/ - if ( g->empty() ) - g->resize(7); - g->add_edge(0, 1, NULL); - g->add_edge(1, 2, NULL); - g->add_edge(1, 3, NULL); - g->add_edge(3, 4, NULL); - g->add_edge(4, 5, NULL); - g->add_edge(5, 3, NULL); - g->add_edge(5, 6, NULL); - result = true; - } - break; - - case grcode_user_gentext: // generate text for user-defined graph nodes - // in: mutable_graph_t *g - // out: must return 0 - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - msg("%p: generate text for graph nodes\n", g); - ctx.graph_text.resize(g->size()); - for ( node_iterator p=g->begin(); p != g->end(); ++p ) - { - int n = *p; - ctx.graph_text[n] = get_node_name(n); - } - result = true; - } - break; - - case grcode_user_text: // retrieve text for user-defined graph node - // in: mutable_graph_t *g - // int node - // const char **result - // bgcolor_t *bg_color (maybe NULL) - // out: must return 0, result must be filled - // NB: do not use anything calling GDI! - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - int node = va_arg(va, int); - const char **text = va_arg(va, const char **); - bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); - *text = ctx.graph_text[node].c_str(); - if ( bgcolor != NULL ) - *bgcolor = DEFCOLOR; - result = true; - qnotused(g); - } - break; - - - case grcode_user_size: // calculate node size for user-defined graph - // in: mutable_graph_t *g - // int node - // int *cx - // int *cy - // out: 0-did not calculate, ida will use node text size - // 1-calculated. ida will add node title to the size - msg("calc node size - not implemented\n"); - // ida will calculate the node size based on the node text - break; - - case grcode_user_title: // render node title of a user-defined graph - // in: mutable_graph_t *g - // int node - // rect_t *title_rect - // int title_bg_color - // HDC dc - // out: 0-did not render, ida will fill it with title_bg_color - // 1-rendered node title - // ida will draw the node title itself - break; - - case grcode_user_draw: // render node of a user-defined graph - // in: mutable_graph_t *g - // int node - // rect_t *node_rect - // HDC dc - // out: 0-not rendered, 1-rendered - // NB: draw only on the specified DC and nowhere else! - // ida will draw the node text itself - break; - - case grcode_user_hint: // retrieve hint for the user-defined graph - // in: mutable_graph_t *g - // int mousenode - // int mouseedge_src - // int mouseedge_dst - // char **hint - // 'hint' must be allocated by qalloc() or qstrdup() - // out: 0-use default hint, 1-use proposed hint - { - mutable_graph_t *g = va_arg(va, mutable_graph_t *); - int mousenode = va_argi(va, int); - int mouseedge_src = va_argi(va, int); - int mouseedge_dst = va_argi(va, int); - char **hint = va_arg(va, char **); - char buf[MAXSTR]; - buf[0] = '\0'; - if ( mousenode != -1 ) - qsnprintf(buf, sizeof(buf), "My fancy hint for node %d", mousenode); - else if ( mouseedge_src != -1 ) - qsnprintf(buf, sizeof(buf), "Hovering on (%d,%d)", mouseedge_src, mouseedge_dst); - if ( buf[0] != '\0' ) - *hint = qstrdup(buf); - result = true; // use our hint - qnotused(g); - } - break; - } - return result; -} - -//------------------------------------------------------------------------- -ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) -{ - if ( code == view_close ) - { - TWidget *view = va_arg(va, TWidget *); - if ( view == (TWidget *)gv ) - gv = nullptr; - } - return 0; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - if ( !is_idaq() ) - return nullptr; - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -static const char wanted_title[] = "Sample graph"; -bool idaapi plugin_ctx_t::run(size_t) -{ - TWidget *widget = find_widget(wanted_title); - if ( widget == nullptr ) - { - // get a unique graph id - netnode id; - id.create("$ ugraph sample"); - gv = create_graph_viewer(wanted_title, id, gr_callback, this, 0); - if ( gv != nullptr ) - { - display_widget(gv, WOPN_DP_TAB); - viewer_fit_window(gv); - register_action(change_layout_desc); - viewer_attach_menu_item(gv, change_layout_desc.name); - } - } - else - { - close_widget(widget, 0); - } - - return true; -} - -//-------------------------------------------------------------------------- -static const char comment[] = "This is a sample graph plugin."; - -static const char help[] = - "A sample graph plugin module\n" - "\n" - "This module shows you how to create a graph viewer."; - -//-------------------------------------------------------------------------- -// This is the preferred name of the plugin module in the menu system -// The preferred name may be overridden in plugins.cfg file - -static const char wanted_name[] = "Create sample graph view"; - - -// This is the preferred hotkey for the plugin module -// The preferred hotkey may be overridden in plugins.cfg file - -static const char wanted_hotkey[] = ""; - - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel - init, // initialize - - nullptr, - - nullptr, // invoke plugin - - comment, // long comment about the plugin - // it could appear in the status line - // or as a hint - - help, // multiline help about the plugin - - wanted_name, // the preferred short name of the plugin - wanted_hotkey // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/ugraph2/makefile b/idasdk75/plugins/ugraph2/makefile deleted file mode 100644 index 3fba6f2..0000000 --- a/idasdk75/plugins/ugraph2/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ugraph2 - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ugraph2$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ugraph2.cpp diff --git a/idasdk75/plugins/ugraph3/makefile b/idasdk75/plugins/ugraph3/makefile deleted file mode 100644 index 1561be0..0000000 --- a/idasdk75/plugins/ugraph3/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ugraph3 - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ugraph3$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - ugraph3.cpp diff --git a/idasdk75/plugins/ui_requests/makefile b/idasdk75/plugins/ui_requests/makefile deleted file mode 100644 index a62f3db..0000000 --- a/idasdk75/plugins/ui_requests/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=ui_requests - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)ui_requests$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)fpro.h $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp \ - $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp ui_requests.cpp diff --git a/idasdk75/plugins/uiswitch/makefile b/idasdk75/plugins/uiswitch/makefile deleted file mode 100644 index f79421c..0000000 --- a/idasdk75/plugins/uiswitch/makefile +++ /dev/null @@ -1,10 +0,0 @@ -PROC=uiswitch - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)uiswitch$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp uiswitch.cpp diff --git a/idasdk75/plugins/uiswitch/uiswitch.cpp b/idasdk75/plugins/uiswitch/uiswitch.cpp deleted file mode 100644 index 9019a6a..0000000 --- a/idasdk75/plugins/uiswitch/uiswitch.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* - - Plugin that allows the user to specify the exact - address and shape of a jump table (switch idiom). - - It displays a dialog box with the most important - attributes of the switch idiom. If the idiom is - complex and has more attributes, then more - dialog boxes are displayed. - - All collected information is validated and then - stored in the database in the switch_info_t structure. - The last step is to reanalyze the switch idiom. - - Please note that this plugin supports the most - common switch idiom but some idiom types are not - handled, for example, custom switches are not. - -*/ - -#include <ida.hpp> -#include <idp.hpp> -#include <loader.hpp> - -//------------------------------------------------------------------------- -struct plugin_ctx_t; -#define ACTION_NAME "uiswitch:SpecSwitchIdiom" -struct uiswitch_ah_t : public action_handler_t -{ - plugin_ctx_t &plg; - uiswitch_ah_t(plugin_ctx_t &_plg) : plg(_plg) {} - virtual int idaapi activate(action_activation_ctx_t *) override; - virtual action_state_t idaapi update(action_update_ctx_t *ctx) override - { - return ctx->widget_type == BWN_DISASM - ? AST_ENABLE_FOR_WIDGET - : AST_DISABLE_FOR_WIDGET; - } -}; - -//-------------------------------------------------------------------------- -struct plugin_ctx_t : public plugmod_t, public ignore_micro_t -{ - uiswitch_ah_t uiswitch_ah = uiswitch_ah_t(*this); - plugin_ctx_t(); - virtual bool idaapi run(size_t) override; - bool callback(); -}; - -//------------------------------------------------------------------------- -int idaapi uiswitch_ah_t::activate(action_activation_ctx_t *) -{ - return plg.callback(); -} - -//--------------------------------------------------------------------------- -// The main form -// hotkeys: abdefginpstu -static const char main_form[] = - "HELP\n" - "Please specify the jump table address, the number of its\n" - "elements and their widths(1,2,4,8). The element shift amount and base value\n" - "should be specified only if the table elements are not\n" - "plain target addresses but must be converted using the following\n" - "formula:\n" - "\n" - " target = base +/- (table_element << shift)\n" - "\n" - "(only this formula is supported by the kernel; other cases must be\n" - "handled by plugins and 'custom' switch idioms).\n" - "\n" - "If you specify BADADDR as the element base then the base of the\n" - "switch segment will be used\n" - "\n" - "The start of the switch idiom is the address of the first instruction\n" - "in the switch idiom.\n" - "\n" - "Subtraction is used instead of addition if \"Subtract table elements\"\n" - "is selected.\n" - "\n" - "When table element is an instruction then you should select\n" - "\"Table element is insn\".\n" - "\n" - "If you specify that a separate value table is present, an additional\n" - "dialog box with its attributes will be displayed.\n" - "ENDHELP\n" - // ansebtifdpgul - "Manual switch declaration - Main features\n" - "\n" - "<~A~ddress of jump table :N::18::>\n" - "<~N~umber of elements :D::18::>\n" - "<~S~ize of table element :D::18::>\n" - "<~E~lement shift amount :D::18::>\n" - "<Element ~b~ase value :N::18::>\n" - "\n" - "<S~t~art of the switch idiom:N::18::>\n" - "<~I~nput register of switch :q:511:18::>\n" - "<~F~irst(lowest) input value:D::18::>(if value table is absent)\n" - "<~D~efault jump address :N::18::>\n" - "\n" - "<Se~p~arate value table is present:C>\n" - "<Si~g~ned jump table elements :C>\n" - "<S~u~btract table elements :C>\n" - "<Tab~l~e element is insn :C>>\n" - "\n" - "\n"; - -// this form displayed if the value table is present -// shortcuts: afinus -static const char value_form[] = - "HELP\n" - "Direct value table holds values of the switch 'case's.\n" - "Each value maps to the corresponding target of the jump table\n" - "Indirect value table holds indexes into jump table.\n" - "\n" - "Inversed value table maps the first element of the value table\n" - "to the last element of the jump table.\n" - "\n" - "For direct table the size of the value table is equal\n" - "to the size of the jump table.\n" - "\n" - "Example of switch idiom with indirect value table:\n" - "\n" - " cmp ecx, 0Fh\n" - " ja short defjump\n" - " movzx ecx, ds:indirect_value_table[ecx]\n" - " jmp ds:jump_table[ecx*4]\n" - "\n" - " jump_table dd offset target_1\n" - " dd offset target_2\n" - " indirect_value_table db 0, 0, 1, 0\n" - " db 1, 1, 1, 0\n" - " db 1, 1, 1, 1\n" - " db 1, 1, 1, 0\n" - "\n" - "ENDHELP\n" - "Manual switch declaration - Value table\n" - "\n" - "<~I~ndirect value table:C>\n" - "<I~n~versed value table:C>>\n" - "<~A~ddress of value table:N::18::>\n" - "<N~u~mber of elements :D::18::> (only for indirect table)\n" - "<~S~ize of table element :D::18::>\n" - "<~F~irst(lowest) input value:D::18::> (only for indirect table)\n" - "\n" - "\n"; - -//--------------------------------------------------------------------------- -// Validate table attributes -static bool check_table(ea_t table, uval_t elsize, uval_t tsize) -{ - flags_t F; - if ( getseg(table) == NULL || is_code((F=get_flags(table))) || is_tail(F) ) - { - warning("AUTOHIDE NONE\nIncorrect table address %a", table); - return false; - } - if ( elsize != 1 && elsize != 2 && elsize != 4 && elsize != 8 ) - { - warning("AUTOHIDE NONE\nIncorrect table element size %" FMT_EA "u", elsize); - return false; - } - flags_t DF = get_flags_by_size((size_t)elsize); - if ( !can_define_item(table, elsize*tsize, DF) ) - { - warning("AUTOHIDE NONE\nCannot create table at %a size %" FMT_EA "u", table, tsize); - return false; - } - return true; -} - -//--------------------------------------------------------------------------- -// The main function - called when the user selects the menu item -bool plugin_ctx_t::callback() -{ - // Calculate the default values to display in the form - ea_t screen_ea = get_screen_ea(); - segment_t *s = getseg(screen_ea); - if ( s == NULL || !is_code(get_flags(screen_ea)) ) - { - warning("AUTOHIDE NONE\nThe cursor must be on the table jump instruction"); - return false; - } - ea_t startea = screen_ea; - while ( true ) - { - ea_t prev = prev_not_tail(startea); - if ( !is_switch_insn(prev) ) - break; - startea = prev; - } - ea_t jumps = get_first_dref_from(screen_ea); - uval_t jelsize = s->abytes(); - uval_t jtsize = 0; - if ( jumps != BADADDR ) - { - insn_t insn; - decode_insn(&insn, screen_ea); - jtsize = guess_table_size(insn, jumps); - } - uval_t shift = 0; - uval_t elbase = BADADDR; - qstring input; - ea_t defea = BADADDR; - uval_t lowcase = 0; - ushort jflags = 0; - ushort vflags = 0; - ea_t vtable = BADADDR; - ea_t vtsize = 0; - ea_t velsize = s->abytes(); - ea_t vlowcase = 0; - reg_info_t ri; - ri.size = 0; - // TODO allow to change these fields - ea_t expr_ea = BADADDR; - eavec_t marks; - // If switch information is present in the database, use it for defaults - switch_info_t si; - if ( get_switch_info(&si, screen_ea) > 0 ) - { - jumps = si.jumps; - jtsize = si.ncases; - startea = si.startea; - elbase = si.elbase; - jelsize = si.get_jtable_element_size(); - shift = si.get_shift(); - defea = si.defjump; - if ( si.regnum != -1 ) - get_reg_name(&input, si.regnum, get_dtype_size(si.regdtype)); - if ( si.flags & SWI_SIGNED ) - jflags |= 2; - if ( si.flags & SWI_SUBTRACT ) - jflags |= 4; - if ( si.flags & SWI_JMPINSN ) - jflags |= 8; - if ( si.flags & SWI_SPARSE ) - { - jflags |= 1; - vtable = si.values; - vtsize = jtsize; - velsize = si.get_vtable_element_size(); - if ( si.flags & SWI_INDIRECT ) - { - vlowcase = si.get_lowcase(); - vflags |= 1; - jtsize = si.jcases; - } - if ( si.flags & SWI_JMP_INV ) - vflags |= 2; - } - else - { - lowcase = si.lowcase; - } - expr_ea = si.expr_ea; - marks = si.marks; - } - // Now display the form and let the user edit the attributes - while ( ask_form(main_form, &jumps, &jtsize, &jelsize, &shift, &elbase, - &startea, &input, &lowcase, &defea, &jflags) ) - { - if ( !check_table(jumps, jelsize, jtsize) ) - continue; - if ( shift > 3 ) - { - warning("AUTOHIDE NONE\nInvalid shift value (allowed values are 0..3)"); - continue; - } - if ( !is_code(get_flags(startea)) ) - { - warning("AUTOHIDE NONE\nInvalid switch idiom start %a (must be an instruction", startea); - continue; - } - ri.reg = -1; - if ( !input.empty() && !parse_reg_name(&ri, input.c_str()) ) - { - warning("AUTOHIDE NONE\nUnknown input register: %s", input.c_str()); - continue; - } - if ( defea != BADADDR && !is_code(get_flags(defea)) ) - { - warning("AUTOHIDE NONE\nInvalid default jump %a (must be an instruction", defea); - continue; - } - if ( jflags & 1 ) // value table is present - { - bool vok = false; - while ( ask_form(value_form, &vflags, &vtable, &vtsize, &velsize, &vlowcase) ) - { - if ( (vflags & 1) == 0 ) - vtsize = jtsize; - if ( check_table(vtable, velsize, vtsize) ) - { - vok = true; - break; - } - } - if ( !vok ) - break; - } - // ok, got and validated all params -- fill the structure - si.clear(); - if ( jflags & 2 ) - si.flags |= SWI_SIGNED; - if ( jflags & 4 ) - si.flags |= SWI_SUBTRACT; - if ( jflags & 8 ) - si.flags |= SWI_JMPINSN; - si.jumps = jumps; - si.ncases = ushort(jtsize); - si.startea = startea; - if ( elbase != BADADDR ) - si.set_elbase(elbase); - si.set_jtable_element_size((int)jelsize); - si.set_shift((int)shift); - si.defjump = defea; - if ( ri.reg != -1 ) - si.set_expr(ri.reg, get_dtype_by_size(ri.size)); - if ( jflags & 1 ) // value table is present - { - si.flags |= SWI_SPARSE; - si.values = vtable; - si.set_vtable_element_size((int)velsize); - if ( (vflags & 1) != 0 ) - { - si.flags |= SWI_INDIRECT; - si.jcases = (int)jtsize; - si.ncases = (ushort)vtsize; - si.ind_lowcase = vlowcase; - } - if ( (vflags & 2) != 0 ) - si.flags |= SWI_JMP_INV; - } - else - { - si.lowcase = lowcase; - } - si.expr_ea = expr_ea; - si.marks = marks; - // ready, store it - set_switch_info(screen_ea, si); - create_switch_table(screen_ea, si); - create_insn(screen_ea); - info("AUTOHIDE REGISTRY\nSwitch information has been stored"); - break; - } - return true; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - return new plugin_ctx_t; -} - -//-------------------------------------------------------------------------- -plugin_ctx_t::plugin_ctx_t() -{ - register_and_attach_to_menu( - "Edit/Other/Create", ACTION_NAME, "Specify switch idiom...", - NULL, SETMENU_INS, - &uiswitch_ah, - this, - ADF_OT_PLUGMOD); - init_ignore_micro(); -} - -//-------------------------------------------------------------------------- -bool idaapi plugin_ctx_t::run(size_t) -{ - callback(); - return true; -} - -//-------------------------------------------------------------------------- -static const char help[] = ""; -static const char comment[] = ""; -static const char wanted_name[] = "Specify switch idiom"; -static const char wanted_hotkey[] = ""; - -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI // The plugin can work with multiple idbs in parallel - | PLUGIN_HIDE, // Plugin should not appear in the Edit, Plugins menu - init, // initialize - nullptr, - nullptr, - comment, // long comment about the plugin - help, // multiline help about the plugin - wanted_name, // the preferred short name of the plugin - wanted_hotkey // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/uunp/makefile b/idasdk75/plugins/uunp/makefile deleted file mode 100644 index 6ac74ba..0000000 --- a/idasdk75/plugins/uunp/makefile +++ /dev/null @@ -1,26 +0,0 @@ -PROC=uunp -O1=resext -O2=win9x - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)resext$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)kernwin.hpp \ - $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)prodir.h $(I)range.hpp \ - $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp resext.cpp \ - uunp.hpp -$(F)uunp$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)dbg.hpp $(I)entry.hpp $(I)fpro.h \ - $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ - $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ - $(I)offset.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp uunp.cpp uunp.hpp -$(F)win9x$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp uunp.hpp win9x.cpp diff --git a/idasdk75/plugins/uunp/uunp.cpp b/idasdk75/plugins/uunp/uunp.cpp deleted file mode 100644 index d73f2eb..0000000 --- a/idasdk75/plugins/uunp/uunp.cpp +++ /dev/null @@ -1,811 +0,0 @@ -// Universal Unpacker based on IDA debugger 1.2 -// Unpacks PE files - -// The algorithm of this plugin is: - -// 1. start the process until the entry point of the packed program -// 2. add a breakpoint at kernel32.GetProcAddress -// 3. resume the execution and wait until the packer calls GetProcAddress -// if the function name passed to GetProcAddress is not in the ignore-list, -// then switch to the trace mode -// A call to GetProcAddress() most likely means that the program has been -// unpacked in the memory and now it setting up its import table -// 4. trace the program in the single step mode until we jump to -// the range with the original entry point. -// 5. as soon as the current ip belongs OEP range, suspend the execution and -// inform the user -// -// So, in short, we allow the unpacker to do its job full speed until -// it starts to setup the import table. At this moment we switch to the single -// step mode and try to find the original entry point. -// -// While this algorithm works with UPX, aspack, and several other packers, -// it might fail and execution of the packed program might go out of control. -// So please use this plugin with precaution. -// -// Ilfak Guilfanov, Yury Haron - -#include <windows.h> - -#ifdef _MSC_VER -# pragma warning(disable: 4996) // GetVersion was declared deprecated -#endif - -#include <ida.hpp> -#include <idp.hpp> -#include <dbg.hpp> -#include <loader.hpp> -#include <kernwin.hpp> -#include <bytes.hpp> -#include <offset.hpp> -#include <auto.hpp> -#include <entry.hpp> -#include <name.hpp> -#include "uunp.hpp" - -//-------------------------------------------------------------------------- -#define REGNAME_EAX (inf_is_64bit() ? "rax" : "eax") -#define REGNAME_ECX (inf_is_64bit() ? "rcx" : "ecx") -#define REGVALUE_MASK (inf_is_64bit() ? ea_t(-1) : ea_t(0xffffffffu)) - -//-------------------------------------------------------------------------- -static size_t get_ptrsize(void) -{ -#ifndef __EA64__ - return sizeof(ea_t); -#else - static size_t ptr_sz = 0; - if ( ptr_sz == 0 ) - ptr_sz = inf_is_64bit() ? 8 : 4; - return ptr_sz; -#endif -} - -//-------------------------------------------------------------------------- -bool doPtr(ea_t ea) -{ - bool ok = get_ptrsize() == 4 ? create_dword(ea, 4) : create_qword(ea, 8); - return ok && op_plain_offset(ea, 0, 0); -} - -//-------------------------------------------------------------------------- -ea_t getPtr(ea_t ea) -{ - return get_ptrsize() == 4 ? get_dword(ea) : get_qword(ea); -} - -//-------------------------------------------------------------------------- -inline bool my_add_bpt(uunp_ctx_t &ctx, ea_t ea) -{ - ctx.bpt_ea = ea; - return add_bpt(ea); -} - -//-------------------------------------------------------------------------- -inline bool my_del_bpt(uunp_ctx_t &ctx, ea_t ea) -{ - ctx.bpt_ea = BADADDR; - return del_bpt(ea); -} - -//--------------------------------------------------------------------------- -inline void uunp_ctx_t::_hide_wait_box() -{ - if ( wait_box_visible ) - { - wait_box_visible = false; - hide_wait_box(); - } -} - -//-------------------------------------------------------------------------- -inline void uunp_ctx_t::set_wait_box(const char *mesg) -{ - if ( wait_box_visible ) - { - replace_wait_box("HIDECANCEL\n%s", mesg); - } - else - { - wait_box_visible = true; - show_wait_box("HIDECANCEL\n%s", mesg); - } -} - -//-------------------------------------------------------------------------- -static void move_entry(uunp_ctx_t &ctx, ea_t rstart) -{ - // remove old start - set_name(inf_get_start_ea(), ""); - - // patch inf struct - inf_set_start_ea(rstart); - inf_set_start_ip(rstart); - - // add new entry point - add_entry(rstart, rstart, "start", true); - ctx.success = true; - - segment_t *ps = getseg(rstart); - if ( ps != NULL ) - { - ps->set_loader_segm(true); - ps->update(); - } -} - -//-------------------------------------------------------------------------- -// Unpacker might use some Win32 functions to perform their function -// This function verifies whether we must switch to the trace mode -// or continue to wait for GetProcAddress() of some other interesting function -static bool ignore_win32_api(const char *name) -{ - static const char *const ignore_names[] = { "VirtualAlloc", "VirtualFree" }; - for ( size_t i=0; i < qnumber(ignore_names); i++ ) - { - if ( strcmp(name, ignore_names[i]) == 0 ) - return true; - } - return false; -} - -//-------------------------------------------------------------------------- -inline bool is_library_entry(const uunp_ctx_t &ctx, ea_t ea) -{ - return !ctx.curmod.contains(ea); -} - -//-------------------------------------------------------------------------- -static bool find_module(ea_t ea, modinfo_t *mi) -{ - bool ok; - for ( ok=get_first_module(mi); ok; ok=get_next_module(mi) ) - { - if ( range_t(mi->base, mi->base+mi->size).contains(ea) ) - break; - } - return ok; -} - -//-------------------------------------------------------------------------- -static bool create_idata_segm(const range_t &impdir) -{ - segment_t ns; - segment_t *s = getseg(impdir.start_ea); - if ( s != NULL ) - ns = *s; - else - ns.sel = setup_selector(0); - - ns.start_ea = impdir.start_ea; - ns.end_ea = impdir.end_ea; - ns.type = SEG_XTRN; - ns.set_loader_segm(true); - bool ok = add_segm_ex(&ns, ".idata", "XTRN", ADDSEG_NOSREG) != 0; - if ( !ok ) - ok = ask_yn(ASKBTN_NO, - "HIDECANCEL\n" - "Cannot create the import segment. Continue anyway?") > ASKBTN_NO; - - return ok; -} - -//-------------------------------------------------------------------------- -static bool find_impdir(uunp_ctx_t &ctx, range_t *impdir) -{ - impdir->start_ea = impdir->end_ea = 0; - - uint32 ea32 = uint32(ctx.an_imported_func); - for ( ea_t pos = ctx.curmod.start_ea; - pos <= ctx.curmod.end_ea; - pos += sizeof(DWORD) ) - { - pos = bin_search2(pos, ctx.curmod.end_ea, (uchar *)&ea32, NULL, 4, - BIN_SEARCH_NOBREAK|BIN_SEARCH_CASE|BIN_SEARCH_FORWARD); - if ( pos == BADADDR ) - break; - - // skip unaligned matches - if ( (pos & 3) != 0 ) - continue; - - // cool, we found a pointer to an imported function - // now try to determine the impdir bounds - ea_t bounds[2] = { pos, pos }; - - for ( int k=0; k < 2; k++ ) - { - ea_t ea = pos; - while ( true ) - { - if ( k == 1 ) - ea += get_ptrsize(); - else - ea -= get_ptrsize(); - - ea_t func = ctx.is_9x ? ctx.win9x_find_thunk(ea) : getPtr(ea); - if ( func == 0 ) - continue; - - if ( !is_mapped(func) ) - break; - - if ( ctx.curmod.contains(func) ) - break; - - modinfo_t mi; - if ( !find_module(func, &mi) ) - break; - - bounds[k] = ea; - } - } - - bounds[1] += get_ptrsize(); - - asize_t bsize = bounds[1] - bounds[0]; - if ( bsize > impdir->size() ) - *impdir = range_t(bounds[0], bounds[1]); - } - return impdir->start_ea != 0; -} - -//-------------------------------------------------------------------------- -static bool create_impdir(uunp_ctx_t &ctx, const range_t &impdir) -{ - // now rename all entries in impdir - del_items(impdir.start_ea, DELIT_EXPAND, impdir.size()); - if ( !create_idata_segm(impdir) ) - return false; - - char dll[MAXSTR]; - qstring buf; - dll[0] = '\0'; - modinfo_t mi; - mi.base = BADADDR; - mi.size = 0; - size_t len = 0; - for ( ea_t ea=impdir.start_ea; ea < impdir.end_ea; ea += get_ptrsize() ) - { - doPtr(ea); - ea_t func = ctx.is_9x ? ctx.win9x_find_thunk(ea) : getPtr(ea); - if ( get_name(&buf, func) <= 0 ) - continue; - - if ( !range_t(mi.base, mi.base+mi.size).contains(func) ) - { - find_module(func, &mi); - qstrncpy(dll, qbasename(mi.name.c_str()), sizeof(dll)); - char *ptr = strrchr(dll, '.'); - if ( ptr != NULL ) - *ptr = '\0'; - if ( streq(dll, "ntdll32") ) // ntdll32 -> ntdll - dll[5] = '\0'; - len = strlen(dll); - } - const char *name = buf.begin(); - if ( strnicmp(dll, name, len) == 0 && name[len] == '_' ) - name += len + 1; - if ( !force_name(ea, name, SN_IDBENC) ) - msg("%a: cannot rename to imported name '%s'\n", ea, name); - } - - return true; -} - -//-------------------------------------------------------------------------- -static void create_impdir(uunp_ctx_t &ctx) -{ - // refresh dll entry point names - dbg->suspended(true); - - // refresh memory configuration - invalidate_dbgmem_config(); - - // found impdir? - range_t impdir; - if ( !find_impdir(ctx, &impdir) ) - return; - - msg("Uunp: Import directory bounds %a..%a\n", impdir.start_ea, impdir.end_ea); - create_impdir(ctx, impdir); -} - -//-------------------------------------------------------------------------- -static void tell_about_failure(void) -{ - warning("The plugin failed to unpack the program, sorry.\n" - "If you want to improve it, the source code is in the SDK!"); -} - -//-------------------------------------------------------------------------- -ssize_t idaapi uunp_ctx_t::on_event(ssize_t code, va_list va) -{ - switch ( code ) - { - case dbg_process_start: - case dbg_process_attach: - get_input_file_path(needed_file, sizeof(needed_file)); - // no break - case dbg_library_load: - if ( stage == 0 ) - { - const debug_event_t *pev = va_arg(va, const debug_event_t *); - const char *modname = pev->modinfo().name.c_str(); - const char *myname = needed_file; - if ( !inf_is_dll() ) - { // ignore the full path for exe names (to handle subst drives) - modname = qbasename(modname); - myname = qbasename(myname); - } - if ( !strieq(modname, myname) ) - break; - if ( code == dbg_library_load ) - is_dll = true; - // remember the current module bounds - if ( pev->modinfo().rebase_to != BADADDR ) - curmod.start_ea = pev->modinfo().rebase_to; - else - curmod.start_ea = pev->modinfo().base; - curmod.end_ea = curmod.start_ea + pev->modinfo().size; - deb(IDA_DEBUG_DBGINFO, "UUNP: module space %a-%a\n", curmod.start_ea, curmod.end_ea); - ++stage; - } - break; - - case dbg_library_unload: - if ( stage != 0 && is_dll ) - { - const debug_event_t *pev = va_arg(va, const debug_event_t *); - if ( curmod.start_ea == pev->modinfo().base - || curmod.start_ea == pev->modinfo().rebase_to ) - { - deb(IDA_DEBUG_DBGINFO, "UUNP: unload unpacked module\n"); - if ( stage > 2 ) - enable_step_trace(false); - stage = 0; - curmod.start_ea = 0; - curmod.end_ea = 0; - _hide_wait_box(); - } - } - break; - - case dbg_run_to: // Parameters: const debug_event_t *event - dbg->suspended(true); - bp_gpa = get_name_ea(BADADDR, "kernel32_GetProcAddress"); - if ( (LONG)GetVersion() < 0 ) // win9x mode -- use thunk's - { - is_9x = true; - win9x_resolve_gpa_thunk(); - } - if ( bp_gpa == BADADDR ) - { - bring_debugger_to_front(); - warning("Sorry, could not find kernel32.GetProcAddress"); -FORCE_STOP: - stage = 4; // last stage - clear_requests_queue(); - request_exit_process(); - run_requests(); - break; - } - else if ( !my_add_bpt(*this, bp_gpa) ) - { - bring_debugger_to_front(); - warning("Sorry, cannot set bpt to kernel32.GetProcAddress"); - goto FORCE_STOP; - } - else - { - ++stage; - set_wait_box("Waiting for a call to GetProcAddress()"); - } - continue_process(); - break; - - case dbg_bpt: // A user defined breakpoint was reached. - // Parameters: thid_t tid - // ea_t breakpoint_ea - // int *warn = -1 - // Return (in *warn): - // -1 - to display a breakpoint warning dialog - // if the process is suspended. - // 0 - to never display a breakpoint warning dialog. - // 1 - to always display a breakpoint warning dialog. - { - thid_t tid = va_arg(va, thid_t); qnotused(tid); - ea_t ea = va_arg(va, ea_t); - ea &= REGVALUE_MASK; - //int *warn = va_arg(va, int*); - if ( stage == 2 ) - { - if ( ea == bp_gpa ) - { - ea_t esp; - if ( get_sp_val(&esp) ) - { - invalidate_dbgmem_contents(esp, 1024); - ea_t gpa_caller = getPtr(esp); - if ( !is_library_entry(*this, gpa_caller) ) - { - ea_t nameaddr; - if ( get_ptrsize() == 4 ) - { - nameaddr = get_dword(esp+8); - } - else - { - regval_t rv; - get_reg_val(REGNAME_ECX, &rv); - nameaddr = ea_t(rv.ival) & REGVALUE_MASK; - } - invalidate_dbgmem_contents(nameaddr, 1024); - qstring name; - size_t len = get_max_strlit_length(nameaddr, STRTYPE_C, ALOPT_IGNHEADS); - get_strlit_contents(&name, nameaddr, len, STRTYPE_C); - if ( !ignore_win32_api(name.c_str()) ) - { - deb(IDA_DEBUG_DBGINFO, "%a: found a call to GetProcAddress(%s)\n", gpa_caller, name.c_str()); - if ( !my_del_bpt(*this, bp_gpa) || !my_add_bpt(*this, gpa_caller) ) - error("Cannot modify breakpoint"); - } - } - } - } - else if ( ea == bpt_ea ) - { - my_del_bpt(*this, ea); - if ( !is_library_entry(*this, ea) ) - { - msg("Uunp: reached unpacker code at %a, switching to trace mode\n", ea); - enable_step_trace(true); - ++stage; - uint64 eax = 0; - if ( get_reg_val(REGNAME_EAX, &eax) ) - an_imported_func = ea_t(eax) & REGVALUE_MASK; - set_wait_box("Waiting for the unpacker to finish"); - } - else - { - warning("%a: bpt in library code", ea); // how can it be? - my_add_bpt(*this, bp_gpa); - } - } - // not our bpt? skip it - else - { - // hide the wait box to allow others plugins to properly stop - _hide_wait_box(); - break; - } - } - } - // while continue_process() would work here too, request+run is more universal - // because they do not ignore the request queue - request_continue_process(); - run_requests(); - break; - - case dbg_trace: // A step occurred (one instruction was executed). This event - // notification is only generated if step tracing is enabled. - // Parameter: none - if ( stage == 3 ) - { - thid_t tid = va_arg(va, thid_t); qnotused(tid); - ea_t ip = va_arg(va, ea_t); - ip &= REGVALUE_MASK; - - // ip reached the OEP range? - if ( oep_range.contains(ip) ) - { - // stop the trace mode - enable_step_trace(false); - msg("Uunp: reached OEP %a\n", ip); - set_wait_box("Reanalyzing the unpacked code"); - - // reanalyze the unpacked code - del_items(oep_range.start_ea, DELIT_EXPAND, oep_range.size()); - auto_make_code(ip); // plan to make code - plan_range(oep_range.start_ea, oep_range.end_ea); // plan to reanalyze - auto_mark_range(oep_range.start_ea, oep_range.end_ea, AU_FINAL); // plan to analyze - move_entry(*this, ip); // mark the program's entry point - - _hide_wait_box(); - - // inform the user - bring_debugger_to_front(); - if ( ask_yn(ASKBTN_YES, - "HIDECANCEL\n" - "The universal unpacker has finished its work.\n" - "Do you want to take a memory snapshot and stop now?\n" - "(you can do it yourself if you want)\n") > ASKBTN_NO ) - { - set_wait_box("Recreating the import table"); - invalidate_dbgmem_config(); - - if ( is_9x ) - find_thunked_imports(); - - create_impdir(*this); - - set_wait_box("Extracting resources"); - if ( !resfile.empty() ) - extract_resource(resfile.c_str()); - - _hide_wait_box(); - if ( take_memory_snapshot(true) ) - goto FORCE_STOP; - } - suspend_process(); - unhook_event_listener(HT_DBG, this); - } - } - break; - - case dbg_process_exit: - { - stage = 0; - // stop the tracing - _hide_wait_box(); - unhook_event_listener(HT_DBG, this); - if ( success ) - jumpto(inf_get_start_ea(), -1); - else - tell_about_failure(); - } - break; - - case dbg_exception:// Parameters: const debug_event_t *event - // int *warn = -1 - // Return (in *warn): - // -1 - to display an exception warning dialog - // if the process is suspended. - // 0 - to never display an exception warning dialog. - // 1 - to always display an exception warning dialog. - - { -// const debug_event_t *event = va_arg(va, const debug_event_t *); -// int *warn = va_arg(va, int *); - // FIXME: handle code which uses SEH to unpack itself - if ( ask_yn(ASKBTN_YES, - "AUTOHIDE DATABASE\n" - "HIDECANCEL\n" - "An exception occurred in the program.\n" - "UUNP does not support exceptions yet.\n" - "The execution has been suspended.\n" - "Do you want to continue the unpacking?") <= ASKBTN_NO ) - { - _hide_wait_box(); - stage = 0; - enable_step_trace(false); // stop the trace mode - suspend_process(); - } - else - { - continue_process(); - } - } - break; - - case dbg_request_error: - // An error occurred during the processing of a request. - // Parameters: ui_notification_t failed_command - // dbg_notification_t failed_dbg_notification - { - ui_notification_t failed_cmd = va_arg(va, ui_notification_t); - dbg_notification_t failed_dbg_notification = va_arg(va, dbg_notification_t); - _hide_wait_box(); - stage = 0; - warning("dbg request error: command: %d notification: %d", - failed_cmd, failed_dbg_notification); - } - break; - } - return 0; -} - -//-------------------------------------------------------------------------- -// 0 - run uunp interactively -// 1 - run without questions -// 2 - run manual reconstruction -bool idaapi uunp_ctx_t::run(size_t arg) -{ - if ( arg == 2 ) - { - range_t impdir = range_t(0, 0); - ea_t oep; - - netnode n; - - // Settings never stored before? - if ( n.create("$ uunp") ) - { - // Populate default values - oep = get_screen_ea(); - segment_t *s = getseg(oep); - if ( s != NULL ) - { - oep_range.start_ea = s->start_ea; - oep_range.end_ea = s->end_ea; - } - } - else - { - // Restore previous settings - oep = n.altval(0); - oep_range.start_ea = n.altval(1); - oep_range.end_ea = n.altval(2); - impdir.start_ea = n.altval(3); - impdir.end_ea = n.altval(4); - } - CASSERT(sizeof(oep_range.start_ea) == sizeof(ea_t)); - CASSERT(sizeof(oep_range.end_ea) == sizeof(ea_t)); - if ( !ask_form("Reconstruction parameters\n" - "\n" - " <~O~riginal entrypoint:N::32::>\n" - " <Code ~s~tart address:N::32::>\n" - " <Code ~e~nd address :N::32::>\n" - "\n" - " <IAT s~t~art address:N::32::>\n" - " <IAT e~n~d address:N::32::>\n" - "\n", - &oep, - &oep_range.start_ea, &oep_range.end_ea, - &impdir.start_ea, &impdir.end_ea) ) - { - // Cancelled? - return true; - } - - // Invalid settings? - if ( impdir.start_ea == 0 || impdir.end_ea == 0 ) - { - msg("Invalid import address table boundaries"); - return true; - } - - // Store settings - n.altset(0, oep); - n.altset(1, oep_range.start_ea); - n.altset(2, oep_range.end_ea); - n.altset(3, impdir.start_ea); - n.altset(4, impdir.end_ea); - - if ( !create_impdir(*this, impdir) ) - return false; - - // reanalyze the unpacked code - del_items(oep_range.start_ea, DELIT_EXPAND, oep_range.size()); - auto_make_code(oep); - plan_range(oep_range.start_ea, oep_range.end_ea); - auto_mark_range(oep_range.start_ea, oep_range.end_ea, AU_FINAL); - - // mark the program's entry point - move_entry(*this, oep); - - take_memory_snapshot(true); - return true; - } - - // Determine the original entry point range - for ( segment_t *s = get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) - { - if ( s->type != SEG_GRP ) - { - oep_range = *s; - break; - } - } - - if ( arg == 0 - && ask_yn(ASKBTN_NO, - "HIDECANCEL\n" - "AUTOHIDE REGISTRY\n" - "Universal PE unpacker\n" - "\n" - "IMPORTANT INFORMATION, PLEASE READ CAREFULLY!\n" - "\n" - "This plugin will start the program execution and try to suspend it\n" - "as soon as the packer finishes its work. Since there might be many\n" - "variations in packers and packing methods, the execution might go out\n" - "of control. There are many ways how things can go wrong, but since you\n" - "have the source code of this plugin, you can modify it as you wish.\n" - "\n" - "Do you really want to launch the program?\n") <= 0 ) - { - return true; - } - - success = false; - - char resfile_[QMAXPATH]; - set_file_ext(resfile_, sizeof(resfile_), get_path(PATH_TYPE_IDB), "res"); - if ( arg == 0 - && !ask_form("Uunp parameters\n" - "IDA will suspend the program when the execution reaches\n" - "the original entry point range. The default values are in\n" - "this dialog box. Please verify them and correct if you wish.\n" - "\n" - "ORIGINAL ENTRY POINT AREA\n" - " <~S~tart address:N::32::>\n" - " <~E~nd address :N::32::>\n" - "\n" - "OUTPUT RESOURCE FILE NAME\n" - " <~R~esource file:f:1:32::>\n" - "\n", - &oep_range.start_ea, - &oep_range.end_ea, - resfile_) ) - { - return true; - } - resfile = resfile_; - - if ( !hook_event_listener(HT_DBG, this) ) - { - warning("Could not hook to notification point"); - return true; - } - - if ( dbg == NULL ) - load_debugger("win32", false); - - // Let's start the debugger - if ( !run_to(inf_get_start_ea()) ) - { - warning("Sorry, could not start the process"); - unhook_event_listener(HT_DBG, this); - } - return true; -} - -//-------------------------------------------------------------------------- -static plugmod_t *idaapi init() -{ - // Our plugin works only for x86 PE executables - processor_t &ph = PH; - if ( ph.id != PLFM_386 || inf_get_filetype() != f_PE ) - return nullptr; - - return new uunp_ctx_t; -} - -//-------------------------------------------------------------------------- -uunp_ctx_t::~uunp_ctx_t() -{ - // listeners are uninstalled automatically - // when the owner module is unloaded - - // just to be safe - _hide_wait_box(); - fr = nullptr; -} - -//-------------------------------------------------------------------------- -static const char wanted_name[] = "Universal PE unpacker"; - -//-------------------------------------------------------------------------- -// -// PLUGIN DESCRIPTION BLOCK -// -//-------------------------------------------------------------------------- -plugin_t PLUGIN = -{ - IDP_INTERFACE_VERSION, - PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel - init, // initialize - - nullptr, - - nullptr, - - wanted_name, // long comment about the plugin - // it could appear in the status line - // or as a hint - - wanted_name, // multiline help about the plugin - - wanted_name, // the preferred short name of the plugin - "" // the preferred hotkey to run the plugin -}; diff --git a/idasdk75/plugins/uunp/uunp.hpp b/idasdk75/plugins/uunp/uunp.hpp deleted file mode 100644 index 4177335..0000000 --- a/idasdk75/plugins/uunp/uunp.hpp +++ /dev/null @@ -1,79 +0,0 @@ -#include <loader.hpp> - -//---------------------------------------------------------------------- -struct uunp_ctx_t : public plugmod_t, public event_listener_t -{ - ea_t bp_gpa = BADADDR; // address of GetProcAddress() - range_t curmod; // current module range - bool wait_box_visible = false; - range_t oep_range; // original entry point range - qstring resfile; // resource file name - ea_t an_imported_func = BADADDR; // an imported function - bool success = false; - bool is_9x = false; - ea_t bpt_ea = BADADDR; // our bpt address - - // win9x.cpp - typedef std::map<ea_t, ea_t> thunks_t; - thunks_t thunks; - - // resext.cpp - FILE *fr = NULL; - ea_t ResBase = 0; - uint32 ResTop = 0; - asize_t ImgSize = 0; - struct - { - union - { - wchar_t *name = nullptr; - uint16 Id; - }; - uint32 len = 0; - } Names[3]; - -#pragma pack(push, 1) - struct rhdr_end_t - { - uint32 DataVersion; - uint16 MemoryFlags; - uint16 LanguageId; - uint32 Version; - uint32 Characteristrics; - }; - union rhdr_name_t - { - struct - { - uint16 prefix; // = 0xFFFF if number entry - uint16 Id; // for number entry - }; - wchar_t Name[1]; // zero terminated - }; -#pragma pack() - rhdr_end_t re = { 0 }; - rhdr_name_t zname = { { 0xFFFF } }; - - // on_event() - int stage = 0; - bool is_dll = false; - char needed_file[QMAXPATH] = ""; - - uunp_ctx_t() {} - ~uunp_ctx_t(); - virtual bool idaapi run(size_t) override; - virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; - - inline void set_wait_box(const char *mesg); - inline void _hide_wait_box(); - - // Windows9x specific functions - void win9x_resolve_gpa_thunk(); - ea_t win9x_find_thunk(ea_t ea); - void find_thunked_imports(); - - // Resource extractor function - void extract_resource(const char *fname); - void store(const void *Data, uint32 size); -}; - diff --git a/idasdk75/plugins/uunp/win9x.cpp b/idasdk75/plugins/uunp/win9x.cpp deleted file mode 100644 index 664a12a..0000000 --- a/idasdk75/plugins/uunp/win9x.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/* - This file contains Win9x (95, 98) specific stuff. - - It can be safely ignored if you are only interested in XP systems. - -*/ - -#include <windows.h> -#include <map> - -#include <ida.hpp> -#include <idp.hpp> -#include <dbg.hpp> - -#include "uunp.hpp" - -#pragma pack(push, 1) -//lint --e{958} Padding required -struct push_insn_t -{ - BYTE push; // must be 0x68 - DWORD ea; -}; - -//lint -estring(958,member) padding is required to align members -struct push_jump_insns_t -{ - BYTE push; // must be 0x68 - DWORD ea; - BYTE jmp; // must be 0xE9 - DWORD reloff; //lint !e754 not referenced -}; -#pragma pack(pop) - -//-------------------------------------------------------------------------- -// find the address of the thunk for GetProcessAddress() under Windows 9x -void uunp_ctx_t::win9x_resolve_gpa_thunk() -{ - DWORD off; - - ea_t ea = curmod.start_ea + offsetof(IMAGE_DOS_HEADER, e_lfanew); - if ( read_dbg_memory(ea, &off, sizeof(off)) != sizeof(off) ) - return; - -#define _OI offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory[ \ - IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) - if ( read_dbg_memory((DWORD)curmod.start_ea + off + _OI, &off, sizeof(off)) != sizeof(off) ) - return; -#undef _OI - - IMAGE_IMPORT_DESCRIPTOR imp; - DWORD hK32 = DWORD(size_t(GetModuleHandle("kernel32"))); - - bool found = false; - for ( off += (DWORD)curmod.start_ea; - read_dbg_memory(off, &imp, sizeof(imp)) == sizeof(imp) && imp.Name; - off += sizeof(imp) ) - { - if ( imp.ForwarderChain == hK32 ) - { - found = true; - break; - } - } - if ( found ) - { - DWORD tmp; - for ( off = imp.FirstThunk + (DWORD)curmod.start_ea; - read_dbg_memory(off, &tmp, sizeof(tmp)) == sizeof(tmp) && tmp != 0; - off += sizeof(DWORD) ) - { - if ( tmp >= hK32 ) - continue; // for TH_xxx entries - - push_insn_t thunk; - if ( read_dbg_memory(tmp, &thunk, sizeof(thunk)) != sizeof(thunk) - || thunk.push != 0x68 ) - { - break; - } - - if ( thunk.ea == bp_gpa ) - { - bp_gpa = tmp; - break; - } - } - } -} - -//-------------------------------------------------------------------------- -// find all dwords equal to 'ea' and remember their translations -// search in the current module -static bool calc_thunk_target(uunp_ctx_t &ctx, uint32 ea32, uint32 imp32) -{ - bool matched = false; - - for ( ea_t pos = ctx.curmod.start_ea; - pos <= ctx.curmod.end_ea; - pos += sizeof(DWORD) ) - { - pos = bin_search2(pos, ctx.curmod.end_ea, (uchar *)&ea32, NULL, - 4, BIN_SEARCH_NOBREAK|BIN_SEARCH_CASE|BIN_SEARCH_FORWARD); - if ( pos == BADADDR ) - break; - if ( pos & 3 ) - continue; - - flags_t F = get_flags(pos); - if ( is_tail(F) ) - continue; - - matched = true; - ctx.thunks[pos] = imp32; - } - return matched; -} - -//-------------------------------------------------------------------------- -// find Windows 9x import thunk -static bool resolve_thunk(uunp_ctx_t &ctx, ea_t ea) -{ - push_jump_insns_t thunk; - - if ( get_bytes(&thunk, sizeof(thunk), ea) != sizeof(thunk) - || thunk.push != 0x68 || thunk.jmp != 0xE9 - || thunk.ea < 0x80000000 || thunk.ea >= 0xC0000000 ) - { - return false; - } - - if ( !calc_thunk_target(ctx, uint32(ea), thunk.ea) ) - msg("%a: Thunked import (%08a) without references\n", ea, ea_t(thunk.ea)); - return true; -} - -//-------------------------------------------------------------------------- -// Windows 9x: find thunked imports and their targets -void uunp_ctx_t::find_thunked_imports() -{ - if ( (DWORD)bp_gpa & 0xF ) - { - warning("Non-standard thunk address"); - return; - } - - // find the thunk area for our module - invalidate_dbgmem_contents(curmod.start_ea, curmod.end_ea); // for bin-search - invalidate_dbgmem_contents(0x80000000, 0xC0000000); - - for ( ea_t ea = bp_gpa; ea > 0x80000000; ea -= 0x10 ) - { - if ( !resolve_thunk(*this, ea) ) - break; - } - - for ( ea_t ea = bp_gpa + 0x10; ea < 0xC0000000; ea += 0x10 ) - { - if ( !resolve_thunk(*this, ea) ) - break; - } - - if ( thunks.empty() ) - warning("Could not find thunk area"); -} - -//-------------------------------------------------------------------------- -ea_t uunp_ctx_t::win9x_find_thunk(ea_t ea) -{ - thunks_t::iterator p = thunks.find(ea); - ea_t func = p != thunks.end() ? p->second : get_dword(ea); - return func; -} diff --git a/idasdk75/plugins/vcsample/makefile b/idasdk75/plugins/vcsample/makefile deleted file mode 100644 index 6428d30..0000000 --- a/idasdk75/plugins/vcsample/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=strings - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)strings$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ - $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ - $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ - $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ - strings.cpp diff --git a/idasdk75/plugins/z80dbg/makefile b/idasdk75/plugins/z80dbg/makefile deleted file mode 100644 index a4a74f5..0000000 --- a/idasdk75/plugins/z80dbg/makefile +++ /dev/null @@ -1,11 +0,0 @@ -PROC=z80dbg - -include ../plugin.mak - -# MAKEDEP dependency list ------------------ -$(F)z80dbg$(O) : $(I)allins.hpp $(I)bitrange.hpp $(I)bytes.hpp \ - $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ - $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ - $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ - $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ - $(I)ua.hpp $(I)xref.hpp z80dbg.cpp diff --git a/idasdk76/allmake.mak b/idasdk76/allmake.mak new file mode 100644 index 0000000..fd8b592 --- /dev/null +++ b/idasdk76/allmake.mak @@ -0,0 +1,855 @@ +# +# Common part of make files for IDA. +# + +# find directory of allmake.mak: +IDA:=$(dir $(lastword $(MAKEFILE_LIST))) + +# define the version number we are building +IDAVER_MAJOR:=7 +IDAVER_MINOR:=6 +# 760 +IDAVERDECIMAL:=$(IDAVER_MAJOR)$(IDAVER_MINOR)0 +# 7.6 +IDAVERDOTTED:=$(IDAVER_MAJOR).$(IDAVER_MINOR) + +# only 32-bit cygwin make is support on Windows +ifeq ($(OS),Windows_NT) + ifneq ($(MAKE_HOST),i686-pc-cygwin) + $(error Only 32-bit cygwin make is supported on Windows. Make sure you are not using 64-bit cygwin, msys, msys2, or any other version of win32 make) + endif +endif + +# if no targets are defined, default to host OS +ifeq ($(or $(__ANDROID__),$(__ANDROID_X86__),$(__ARMLINUX__),$(__LINUX__),$(__MAC__),$(__NT__)),) + ifeq ($(OS),Windows_NT) + __NT__=1 + else + UNAME_S := $(shell uname -s) + ifeq ($(UNAME_S),Linux) + __LINUX__=1 + endif + ifeq ($(UNAME_S),Darwin) + __MAC__=1 + endif + endif +endif + +# only one build target may be defined +ifneq ($(__ANDROID__)$(__ANDROID_X86__)$(__ARMLINUX__)$(__LINUX__)$(__MAC__)$(__NT__),1) + $(error Only one build target may be defined (__ANDROID__, __ANDROID_X86__, __ARMLINUX__, __LINUX__, __MAC__, or __NT__)) +endif + +# detect build configuration +# Note: will set one of M, MM, MMH, M32, MO, MMO, MMHO, MO32, MSO, MMSO, or MSO32 +BUILD_CONFIG-1 := M +BUILD_CONFIG-$(__EA64__) += M +BUILD_CONFIG-$(USE_STATIC_RUNTIME) += S +BUILD_CONFIG-$(IDAHOME) += H +BUILD_CONFIG-$(NDEBUG) += O +BUILD_CONFIG-$(__X86__) += 32 +empty := +space := $(empty) $(empty) +comma := , +BUILD_CONFIG := $(subst $(space),,$(BUILD_CONFIG-1)) +$(BUILD_CONFIG) := 1 + +# definition of a single \n character (empty lines are important!) +define newline + + +endef + + +# support arm64 macOS11 builds +ifeq ($(and $(__MAC__),$(__ARM__)),1) + ifdef __X86__ + $(error 32-bit ARM builds are not supported on mac.) + endif + # create a shortcut for convenience + __APPLE_SILICON__=1 +endif + + +ifdef __ARM__ + PROCDEF = __ARM__ + TARGET_PROCESSOR_NAME-1=arm + TARGET_PROCESSOR_NAME-$(__MAC__)=arm64 + TARGET_PROCESSOR_NAME=$(TARGET_PROCESSOR_NAME-1) +else ifndef __X86__ + ARCH_FLAGS = -m64 + TARGET_PROCESSOR_NAME=x64 +else + ARCH_FLAGS = -m32 + TARGET_PROCESSOR_NAME=x86 +endif + +# define some variables to simplify build system +ifndef __X86__ + __X64__ = 1 + ifndef __EA64__ + __X32__ = 1 + endif +endif +ifndef __NT__ + __UNIX__ = 1 +endif + +ifndef IDAHOME + IDAADV = 1 +endif + +# define SYSNAME +SYSNAME-$(__LINUX__) = linux +SYSNAME-$(__MAC__) = mac +SYSNAME-$(__NT__) = win +SYSNAME = $(SYSNAME-1) + +# path functions (depending on host OS) +ifeq ($(OS),Windows_NT) + # define: convert unix path to dos path by replacing slashes by backslashes + dospath=$(subst /,\\,$(1)) +else + # define: dospath does not do anything in unix + dospath=$(1) +endif +# define: return 1 if path exists, 0 otherwise +ls=$(if $(wildcard $(1)),1,0) + +# define: logical negation +not = $(if $(1),,1) + +# define: greater or equal +gte = $(if $(filter-out $(1),$(word 2,$(sort $(1) $(2)))),,1) + +include $(IDA)defaults.mk + +############################################################################# +ifdef __NT__ + COMPILER_NAME=vc + + # Visual C++ Toolchain and Windows SDK paths + # Note: see comments in defaults.mk for more information about these + # variables. + + # This function searches for a specified path, converts it to a 8.3 + # path with forward slashes as separator, and exports it as an + # environment variable. This way, subcalls to make do not need to + # call $(shell) again. + define require_path + $$(if $(strip $$($(1))),,$$(eval $(1):=$$(subst \,/,$$(shell cygpath -d $(2) 2>/dev/null)))) + $$(if $(strip $$($(1))),,$$(error Could not find $(3) in $(2)$$(newline)*** See defaults.mk and "Visual C++ Toolchain and Windows SDK paths" in allmake.mak)) + $$(eval export $(1)) + endef + + # This function fixes variables imported from defaults.mk/vcvars.bat + # by ensuring that they are surrounded by quotes and by removing the + # trailing backslash. + fix_var=$(1):='$$(patsubst %\,%,$$(patsubst '%,%,$$(patsubst %',%,$$(patsubst "%,%,$$(patsubst %",%,$$($(1)))))))' + + # Note: these cfg files are created in makeenv_vc.mak + ifdef __XPCOMPAT__ + -include $(IDA)vs17paths_xp.cfg + else + -include $(IDA)vs17paths.cfg + endif + + # Visual C++ 2017 Install Directory + ifndef MSVC_ROOT + ifneq (,$(findstring Microsoft$(space)Visual$(space)Studio$(space),$(VCINSTALLDIR))) + ifeq (,$(findstring 2017,$(VCINSTALLDIR))) + $(error Please check your system environment variable VCInstallDir [$(VCINSTALLDIR)].$(newline)It seems to be pointing to an old version of Visual Studio (and not version 2017).$(newline)You may override it in defaults.mk.) + endif + endif + $(eval $(call fix_var,VCINSTALLDIR)) + $(eval $(call require_path,MSVC_ROOT,$(VCINSTALLDIR),Visual C++ 2017 Install Directory)) + export MSVC_ROOT + endif + + # Visual C++ 2017 Tools Version + ifndef MSVC_TOOLSVER + ifndef VCToolsVersion + # Try to obtain version from Microsoft.VCToolsVersion.default.txt + MSVC_TOOLSVER_PATH = $(MSVC_ROOT)/Auxiliary/Build/Microsoft.VCToolsVersion.default.txt + VCToolsVersion := $(shell cat $(MSVC_TOOLSVER_PATH) 2> /dev/null) + ifeq (,$(VCToolsVersion)) + # If that failed, try to detect latest version from the directory names + VCToolsVersion := $(notdir $(lastword $(sort $(wildcard $(MSVC_ROOT)/Tools/MSVC/14.*)))) + endif + ifeq (,$(VCToolsVersion)) + $(error Could not find Visual C++ 2017 Tools Version in $(MSVC_TOOLSVER_PATH)) + endif + endif + $(eval $(call fix_var,VCToolsVersion)) + MSVC_TOOLSVER := $(VCToolsVersion) + export MSVC_TOOLSVER + endif + + # Final Visual C++ 2017 Tools path + $(eval $(call require_path,MSVC_PATH,$(MSVC_ROOT)/Tools/MSVC/$(MSVC_TOOLSVER),Visual C++ 2017 Tools)) + + MSVC_BIN-X86 ?= $(MSVC_PATH)/bin/HostX86/x86 + MSVC_BIN-X64 ?= $(MSVC_PATH)/bin/HostX64/x64 + ifdef __X86__ + MSVC_BIN ?= $(MSVC_BIN-X86) + else + MSVC_BIN ?= $(MSVC_BIN-X64) + endif + MSVC_INCLUDE ?= $(MSVC_PATH)/Include + + # Windows SDK Install Directory + ifndef WSDK_PATH + $(eval $(call fix_var,WindowsSdkDir)) + $(eval $(call require_path,WSDK_PATH,$(WindowsSdkDir),Windows SDK Install Directory)) + export WSDK_PATH + endif + + # Windows SDK Version + ifndef WSDK_VER + ifndef WindowsSDKVersion + # Detect the latest version of the Windows SDK + WSDK_VER_PATH = $(WSDK_PATH)/Include/10.* + WindowsSDKVersion := $(notdir $(lastword $(sort $(wildcard $(WSDK_VER_PATH))))) + ifeq (,$(WindowsSDKVersion)) + $(error Could not find Windows SDK Version in $(WSDK_VER_PATH)) + endif + endif + $(eval $(call fix_var,WindowsSDKVersion)) + WSDK_VER := $(WindowsSDKVersion) + export WSDK_VER + endif + + # Windows SDK Include/Lib paths + INCLUDE_UCRT_PATH ?= $(WSDK_PATH)/Include/$(WSDK_VER)/ucrt + LIB_UCRT_PATH ?= $(WSDK_PATH)/Lib/$(WSDK_VER)/ucrt + $(eval $(call require_path,INCLUDE_UCRT,$(INCLUDE_UCRT_PATH),Windows SDK Include/ucrt)) + $(eval $(call require_path,LIB_UCRT,$(LIB_UCRT_PATH),Windows SDK Lib/ucrt)) + + ifdef __XPCOMPAT__ + $(eval $(call require_path,INCLUDE_MSSDK71,$(MSSDK71_PATH)/Include,Microsoft SDK Include)) + $(eval $(call require_path,LIB_MSSDK71,$(MSSDK71_PATH)/Lib,Microsoft SDK Lib)) + $(eval $(call require_path,SDK_BIN,$(MSSDK71_PATH)/Bin,Microsoft SDK Bin)) + else + INCLUDE_SHARED_PATH ?= $(WSDK_PATH)/Include/$(WSDK_VER)/shared + INCLUDE_UM_PATH ?= $(WSDK_PATH)/Include/$(WSDK_VER)/um + LIB_UM_PATH ?= $(WSDK_PATH)/Lib/$(WSDK_VER)/um + SDK_BIN_PATH ?= $(WSDK_PATH)/Bin/$(WSDK_VER)/ + + $(eval $(call require_path,INCLUDE_SHARED,$(INCLUDE_SHARED_PATH),Windows SDK Include/shared)) + $(eval $(call require_path,INCLUDE_UM,$(INCLUDE_UM_PATH),Windows SDK Include/um)) + $(eval $(call require_path,LIB_UM,$(LIB_UM_PATH),Windows SDK Lib/um)) + $(eval $(call require_path,SDK_BIN,$(SDK_BIN_PATH),Windows SDK Bin)) + endif + + # Export INCLUDE as an environment variable so it may be used by cl. + ifndef INCLUDE + ifdef __XPCOMPAT__ + INCLUDE = $(MSVC_INCLUDE);$(INCLUDE_UCRT);$(INCLUDE_MSSDK71) + else + INCLUDE = $(MSVC_INCLUDE);$(INCLUDE_UCRT);$(INCLUDE_UM);$(INCLUDE_SHARED) + endif + export INCLUDE + endif + + # Export LIB as an environment variable so it may be used by cl/link. + ifndef LIB + ifdef __XPCOMPAT__ + ifdef __X86__ + LIB = $(MSVC_PATH)/lib/x86;$(LIB_UCRT)/x86;$(LIB_MSSDK71) + else + LIB = $(MSVC_PATH)/lib/x64;$(LIB_UCRT)/x64;$(LIB_MSSDK71)/x64 + endif + else + ifdef __X86__ + LIB = $(MSVC_PATH)/lib/x86;$(LIB_UCRT)/x86;$(LIB_UM)/x86 + else + LIB = $(MSVC_PATH)/lib/x64;$(LIB_UCRT)/x64;$(LIB_UM)/x64 + endif + endif + export LIB + endif + + # If a Visual Studio Command Prompt is used, make sure the target + # architecture is correct. + ifdef VSCMD_ARG_TGT_ARCH + ifneq ($(VSCMD_ARG_TGT_ARCH),$(TARGET_PROCESSOR_NAME)) + ifdef __X86__ + EXPECTED_ARCH = x86 + else + EXPECTED_ARCH = x64 + endif + LOWERCASE_BUILD_CONFIG := $(subst M,m,$(subst S,s,$(subst O,o,$(BUILD_CONFIG)))) + $(error Please use the correct Visual Studio Command Prompt for the target architecture$(newline)*** The target architecture for '$(LOWERCASE_BUILD_CONFIG)' is $(EXPECTED_ARCH), and the architecture for the current Visual Studio Command Prompt is $(VSCMD_ARG_TGT_ARCH))) + endif + endif +############################################################################# +else ifdef __LINUX__ + COMPILER_NAME=gcc + PTHR_SWITCH=-pthread + STDLIBS += -lrt -lpthread -lc +############################################################################# +else ifdef __MAC__ + COMPILER_NAME=clang + STDLIBS += -lpthread -liconv + ARCH_FLAGS-$(__X64__) = -arch x86_64 + ARCH_FLAGS-$(__X86__) = -arch i386 + ARCH_FLAGS-$(__ARM__) = -arch arm64 + ARCH_FLAGS += $(ARCH_FLAGS-1) + # The following value is defined in defaults.mk. + ARCH_FLAGS += -mmacosx-version-min=$(MACOSX_DEPLOYMENT_TARGET) + ifndef MACSDK + MACSDK := $(shell /usr/bin/xcrun --sdk macosx --show-sdk-path) + ifeq ($(MACSDK),) + $(error Could not find MacOSX SDK) + endif + export MACSDK + endif + ARCH_FLAGS += -isysroot $(MACSDK) +endif + +############################################################################# +# toolchain-specific variables + +ifneq (,$(filter $(COMPILER_NAME),gcc clang)) + # file extensions + A = .a + B = $(SUFF64) + O = .o + II = .i + # toolchain output switches + OBJSW = -o # with space + OUTAR = + OUTII = -o # with space + OUTSW = -o # with space + ifdef __MAC__ + OUTMAP = -Wl,-map, + else + OUTMAP = -Wl,-Map, + endif + # misc switches + AROPT = rc + CPPONLY = -E + FORCEC = -xc + NORTTI = -fno-rtti + ifdef __MAC__ + OUTDLL = -dynamiclib + else + OUTDLL = --shared + endif + # utilities + CCACHE-$(USE_CCACHE) = ccache + ifeq ($(COMPILER_NAME),clang) + _CC = clang + _CXX = clang++ + else + _CC = gcc + _CXX = g++ + ifdef USE_GOLD + GOLD = -fuse-ld=gold + endif + endif + AR = $(CROSS_PREFIX)ar$(HOST_EXE) $(AROPT) + CC = $(CCACHE-1) $(CROSS_PREFIX)$(_CC)$(HOST_EXE) $(ARCH_FLAGS) + CCL = $(CROSS_PREFIX)$(_CXX)$(HOST_EXE) $(ARCH_FLAGS) $(GOLD) + CXX = $(CCACHE-1) $(CROSS_PREFIX)$(_CXX)$(HOST_EXE) $(ARCH_FLAGS) +else ifeq ($(COMPILER_NAME),vc) + # file extensions + A = .lib + B = $(SUFF64).exe + O = .obj + II = .i + # toolchain output switches + OBJSW = /Fo + OUTAR = /OUT: + OUTII = /Fi + OUTSW = /OUT: + OUTMAP = /map: + # misc switches + CPPONLY = /P + FORCEC = /TC + NOLOGO = /nologo + NORTTI = /GR- + OUTDLL = /DLL + # utilities + AR = $(MSVC_BIN)/lib.exe $(NOLOGO) + CC = $(MSVC_BIN)/cl.exe $(NOLOGO) + CCL = $(MSVC_BIN)/link.exe $(NOLOGO) + CXX = $(CC) +endif + +############################################################################## +# target-specific cflags/ldflags +ifneq (,$(filter $(COMPILER_NAME),gcc clang)) + + # system cflags + CC_DEFS += $(PROCDEF) + ifdef __MAC__ + CC_DEFS += __MAC__ + else + CC_DEFS += __LINUX__ + endif + + ifdef __APPLE_SILICON__ + CC_DEFS += __APPLE_SILICON__ + endif + + # pic-related flags + # Note: this variable may be overridden in other parts of the build + PIC = -fPIC + + ifdef __MAC__ + LDPIE = $(PIC) -Wl,-pie + else + LDPIE = $(PIC) -pie + endif + + # common cflags + CC_DEFS += $(DEF64) + CC_DEFS += $(DEFX86) + + CC_F += $(PIC) + CC_F += -fdiagnostics-show-option + CC_F += -fno-strict-aliasing + CC_F += -fvisibility=hidden + CC_F += -fwrapv + ifneq ($(COMPILER_NAME),clang) + CC_F += -fno-delete-null-pointer-checks + endif + + CC_INCP += $(I) + + CC_W += -Wall + CC_W += -Wextra + CC_W += -Wformat=2 + CC_W += -Werror=format-security + CC_W += -Werror=format-nonliteral + CC_W += -Wshadow + CC_W += -Wunused + + CC_WNO += -Wno-format-y2k + CC_WNO += -Wno-missing-field-initializers + CC_WNO += -Wno-sign-compare + + CC_X += -g + CC_X += -pipe + + # enable c++11 + CXXSTD = -std=c++11 + + CXX_F += -fvisibility-inlines-hidden + CXX_WNO += -Wno-invalid-offsetof + + # system-specific cflags + ifeq ($(COMPILER_NAME),clang) # mac/android + # 'cc -dumpversion' always reports 4.2.1 for clang + # https://stackoverflow.com/questions/12893731/why-does-clang-dumpversion-report-4-2-1 + + # clang is extra picky - need to add some warning supressions + # must eventually get rid of most of these + CC_WNO += -Wno-char-subscripts + CC_WNO += -Wno-dynamic-class-memaccess + CC_WNO += -Wno-int-to-pointer-cast + CC_WNO += -Wno-invalid-source-encoding + CC_WNO += -Wno-logical-not-parentheses + CC_WNO += -Wno-logical-op-parentheses + CC_WNO += -Wno-null-conversion + CC_WNO += -Wno-nullability-completeness + CC_WNO += -Wno-parentheses-equality + CC_WNO += -Wno-self-assign + CC_WNO += -Wno-unused-const-variable + CC_WNO += -Wno-unused-function + CC_WNO += -Wno-unused-private-field + CC_WNO += -Wno-unused-variable + CC_WNO += -Wno-varargs + + CC_F += -fno-caret-diagnostics + else # (arm)linux + + # get gcc version + ifndef _GCC_VERSION + _GCC_VERSION:=$(wordlist 1,2,$(subst ., ,$(shell $(CC) -dumpversion))) + export _GCC_VERSION + endif + GCC_VERSION=$(firstword $(_GCC_VERSION)).$(lastword $(_GCC_VERSION)) + + CC_WNO += -Wno-unused-local-typedefs + CC_F += -fno-diagnostics-show-caret + + CC_DEFS-$(call gte,$(GCC_VERSION),5.0) += _GLIBCXX_USE_CXX11_ABI=0 + CC_W-$(call gte,$(GCC_VERSION),7.0) += -Wimplicit-fallthrough=0 + CXX_WNO-$(call gte,$(GCC_VERSION),8.0) += -Wno-class-memaccess + + # suppress warning about ABI change in GCC 4.4 + CC_WNO-$(__ARMLINUX__) += -Wno-psabi + endif + + # optimization cflags + ifdef NDEBUG + CC_F += -fdata-sections + CC_F += -ffunction-sections + ifndef __ASAN__ + CC_F += -fomit-frame-pointer + endif + # stack protector + ifdef __TARGET_MAC_HOST_LINUX__ + # disable stack protector for our osxcross toolchain (we check + # against __TARGET_MAC_HOST_LINUX__ since it is hard to check + # for version number in clang). + else ifeq ($(call gte,$(GCC_VERSION),4.9),1) + CC_F += -fstack-protector-strong + else + CC_F += -fstack-protector + endif + CC_DEFS += NDEBUG + CC_DEFS += _FORTIFY_SOURCE=2 + else + CC_DEFS += _DEBUG + endif + + # system-specific ldflags + ifdef __LINUX__ + LDFLAGS += -Wl,--build-id + LDFLAGS += -Wl,--gc-sections + LDFLAGS += -Wl,--warn-shared-textrel + + NO_UNDEFS = -Wl,--no-undefined + DLL_W += $(NO_UNDEFS) + else ifdef __MAC__ + LDFLAGS += -Wl,-dead_strip + + ifndef __TARGET_MAC_HOST_LINUX__ + DLL_X += -compatibility_version 1.0 + DLL_X += -current_version 1.0 + DLL_X += -single_module + endif + endif + + # common linker/compiler flags + ifdef NDEBUG + CCOPT += -O2 + ifdef __LINUX__ + LDOPT += -Wl,-O1 + endif + endif + + # AddressSanitizer flags + ifdef __ASAN__ + CC_DEFS += __ASAN__ + CC_F += -fno-omit-frame-pointer + CC_F += -fsanitize=address + LDFLAGS += -fsanitize=address + export LSAN_OPTIONS=suppressions=$(IDA)etc/bin/known_leaks.txt:detect_leaks=0 + endif + + # final compiler flags + CC_F += $(CC_F-1) + CC_W += $(CC_W-1) + CC_WNO += $(CC_WNO-1) + CXX_WNO += $(CXX_WNO-1) + CC_DEFS += $(CC_DEFS-1) + CC_INCP += $(CC_INCP-1) + CC_D += $(addprefix -D,$(CC_DEFS)) + CC_I += $(addprefix -I,$(CC_INCP)) + + # the -Wno-* flags must come after the -W enabling flags + WARNS = $(sort $(CC_W)) $(sort $(CC_WNO)) + + CFLAGS += $(sort $(CC_X)) + CFLAGS += $(CCOPT) + CFLAGS += $(sort $(CC_I)) + CFLAGS += $(sort $(CC_D)) + CFLAGS += $(sort $(CC_F)) + CFLAGS += $(WARNS) + CFLAGS += $(PTHR_SWITCH) + + # for warning suppression, override the WARNS variable with NOWARNS: + # $(TARGET): WARNS = $(NOWARNS) + NOWARNS = -w + + # dll linker flags + DLLFLAGS += $(DLL_W) $(DLL_X) + +else ifeq ($(COMPILER_NAME),vc) + # for warning suppression, override the WARNS variable with NOWARNS: + # $(TARGET): WARNS = $(NOWARNS) + NOWARNS = -w -wd4702 -wd4738 + + # optimization ldflags + LDOPT += /DEBUG + ifdef NDEBUG + LDOPT += /INCREMENTAL:NO /OPT:ICF /OPT:REF + endif + + # set c runtime to use + ifdef NDEBUG + ifdef USE_STATIC_RUNTIME + RUNTIME_LIBSW = /MT + else + RUNTIME_LIBSW = /MD + endif + else + ifdef USE_STATIC_RUNTIME + RUNTIME_LIBSW = /MTd + else + RUNTIME_LIBSW = /MDd + endif + endif + + # PDB options + PDBFLAGS = /PDB:$(PDBDIR)/ + ifdef NDEBUG + PDBFLAGS += /PDBALTPATH:%_PDB% + endif + # Generate debug info (old style) + PDBFORMAT = /Z7 + + # final compiler flags + CC_DEFS += $(DEF64) + CC_DEFS += $(DEFX86) + CC_DEFS += $(CC_DEFS-1) + CC_INCP += $(CC_INCP-1) + CC_D += $(addprefix -D,$(CC_DEFS)) + CC_I += $(addprefix -I,$(CC_INCP)) + + CFGFILE = @$(IDA)$(SYSDIR).cfg + CFLAGS += $(CFGFILE) + CFLAGS += $(RUNTIME_LIBSW) + CFLAGS += $(PDBFORMAT) + CFLAGS += /Brepro + CFLAGS += $(sort $(CC_I)) + CFLAGS += $(sort $(CC_D)) + CFLAGS += $(sort $(CC_F)) + CFLAGS += $(WARNS) + + # final linker flags + LDFLAGS += /Brepro + LDFLAGS += $(PDBFLAGS) + LDFLAGS += /ERRORREPORT:QUEUE + ifdef __X86__ + LDFLAGS += /LARGEADDRESSAWARE + endif + + ifdef __XPCOMPAT__ + XPSUBSYS-$(__X64__) = /SUBSYSTEM:CONSOLE,5.02 + XPSUBSYS-$(__X86__) = /SUBSYSTEM:CONSOLE,5.01 + LDFLAGS += $(XPSUBSYS-1) + endif + +endif + +# to enable obsolete functions, disable the NO_OBSOLETE_FUNCS variable: +# $(TARGET): NO_OBSOLETE_FUNCS = +NO_OBSOLETE_FUNCS = NO_OBSOLETE_FUNCS +CC_DEFS += $(NO_OBSOLETE_FUNCS) + +CXXFLAGS += $(CXXSTD) +CXXFLAGS += $(CFLAGS) +CXXFLAGS += $(sort $(CXX_F)) +CXXFLAGS += $(sort $(CXX_WNO)) +CXXFLAGS += $(UFLAGS) + +LDFLAGS += $(LDOPT) + +############################################################################# +ifdef __X86__ + DEFX86 = __X86__ +endif + +ifdef __EA64__ + SUFF64=64 + ADRSIZE=64 + DEF64 = __EA64__ +else + ADRSIZE=32 +endif + +ifdef NDEBUG + OPTSUF=_opt +endif + +ifdef IDAHOME + EXTRASUF1:=_home + IDAHOME_PROCESSORS=pc arm ppc mips mc68k +else ifdef DEMO_OR_FREE + ifdef DEMO + EXTRASUF1:=_demo + else + EXTRASUF1:=_free + endif + IDADEMO_PROCESSOR=pc + IDADEMO_LOADERS=pe elf mach-o +else + ifdef USE_STATIC_RUNTIME + EXTRASUF1:=_s + endif + ifdef __ASAN__ + EXTRASUF2:=_asan + endif + ifdef __FUZZER__ + EXTRASUF3:=_afl + endif +endif +EXTRASUF=$(EXTRASUF1)$(EXTRASUF2)$(EXTRASUF3) + +############################################################################# +SYSDIR=$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(OPTSUF)$(EXTRASUF) +# libraries directory +LIBDIR=$(IDA)lib/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(EXTRASUF) +# object files directory (using ?= to allow overriding) +OBJDIR?=obj/$(SYSDIR) +# PDB files directory +PDBDIR=$(IDA)pdb/$(TARGET_PROCESSOR_NAME)_$(SYSNAME)_$(COMPILER_NAME)_$(ADRSIZE)$(EXTRASUF) +# output directory for target platform +R=$(IDA)bin/ +# input directory with existing build utilities +RS=$(IDA)bin/ +# _ida.hlp placed in main tool directory +HI=$(RS) +# help source +HS=.hls +# help headers +HH=.hhp +# include,help and other directories are common for all platforms and compilers: +I =$(IDA)include/ +C =$(R)cfg/ +RI=$(R)idc/ +F=$(OBJDIR)/ +L=$(LIBDIR)/ + +DUMB=$(L)dumb$(O) +HELP=$(L)help$(O) +HLIB=$(HI)_ida.hlp + +# to be used like this: +# $(L)va$(A): $(call lib, $(VA_OBJS)) +lib=$(1); $(strip $(QARf)$(AR) $(OUTAR)$$@ $$^) + +# to be used like this: $(call _link_exe, target, objs, libs) +_link_exe=$(strip $(QCCL)$(CCL) $(OUTSW)$(1) $(2) $(3) $(LDFLAGS) $(STDLIBS)) + +# to be used like this: $(call link_exe, objs, libs) +link_exe=$(call _link_exe,$@,$(1),$(2)) + +# to be used like this: $(call _link_dll, target, objs, libs) +_link_dll=$(strip $(QCCL)$(CCL) $(OUTDLL) $(DLLFLAGS) $(OUTSW)$(1) $(2) $(3) $(LDFLAGS) $(STDLIBS)) + +# to be used like this: $(call link_dll, objs, libs) +link_dll=$(call _link_dll,$@,$(1),$(2)) + +# to be used like this: $(call link_dumb, target, libs, objs) +link_dumb=$(3) $(patsubst %,$(L)%$(A),$(2)); $(strip $(QCCLf)$(CCL) $(OUTSW)$(1) $(LDFLAGS) $(3) $(patsubst %,$(L)%$(A),$(2)) $(STDLIBS)) + +# to be used like this: +# target: $(call dumb_target, libs, objs) extra_ldflags +dumb_target=$(call link_dumb,$$@,$(1),$(2) $(DUMB)) + +# to be used like this: +# $(R)%$(B): $(F)%$(O) $(call dumb_pattern, libs, objs) extra_ldflags +dumb_pattern=$(call link_dumb,$$@ $$<,$(1),$(2) $(DUMB)) + +# to be used like this: +# OBJS += $(call objs,obj1 obj2 obj3 ...) +objs=$(addprefix $(F),$(addsuffix $(O),$(1))) + +# output name for module dll +module_dll=$(BIN_PATH)$(1)$(SUFF64)$(DLLEXT) + +# output name for server executable +server_exe=$(R)dbgsrv/$(1) + +ifeq ($(or $(M),$(MM),$(MMH),$(MO),$(MMO),$(MMHO)),1) + BUILD_IDA = 1 +endif +ifeq ($(or $(M32),$(MM),$(MO32),$(MMO)),1) + BUILD_DBGSRV = 1 +endif + +# target-os specific variables +ifdef __NT__ + DLLEXT=.dll +else ifdef __MAC__ + DLLEXT=.dylib +else + DLLEXT=.so +endif + +# build system commands +ifeq ($(OS),Windows_NT) + CP=cp -f --preserve=all + MKDIR=-@mkdir + AWK=gawk +else + CP=cp -f + MKDIR=-@mkdir 2>/dev/null + AWK=awk +endif +RM=rm -f +MV=mv + +# used to silence some makefile commands +# run 'make Q=' to prevent commands from being silenced +Q?=@ + +# some makefiles rebuild targets when the makefile itself changes. +# this makes debugging makefiles a pain. +# run 'make MAKEFILE_DEP=' to disable this behaviour. +MAKEFILE_DEP?=makefile + +# libida-related +# Note: $(IDALIB) should be used in the dependency list +# $(LINKIDA) should be used in the link command +ifdef __NT__ + # Note: on Windows, ida.lib does not have a "64" suffix for ea64 + IDALIB = $(L)ida$(A) + LINKIDA = $(IDALIB) +else + IDALIB = $(L)libida$(SUFF64)$(DLLEXT) + LINKIDA = -L$(L) -lida$(SUFF64) +endif + +# simplify command echo +ifdef IDAMAKE_SIMPLIFY + ifeq ($(Q),@) + DO_IDAMAKE_SIMPLIFY=1 + endif +endif + +ifdef DO_IDAMAKE_SIMPLIFY + ifdef IDAMAKE_SIMPLIFY_NO_COLOR + qcolor=$(1) + else + ifeq ($(OS),Windows_NT) + qcolor=-e # + endif + qcolor+="\033[1;34m$(1)\033[0m" + endif + QCXX = @echo $(call qcolor,compile) $< && # + QCC = @echo $(call qcolor,compile) $< && # + QASM = @echo $(call qcolor,asm) $< && # + QARf = @echo $(call qcolor,lib) $$@ && # + QCCL = @echo $(call qcolor,link) $@ && # + QCCLf = @echo $(call qcolor,link) $$@ && # +endif + +# simple build rules +CONLY?=-c + +$(F)%$(O): %.cpp + $(strip $(QCXX)$(CXX) $(CXXFLAGS) $(NORTTI) $(CONLY) $(OBJSW)$@ $<) + +$(F)%$(O): %.c + $(strip $(QCC)$(CC) $(CFLAGS) $(CONLY) $(OBJSW)$@ $(FORCEC) $<) + +$(C)%.cfg: %.cfg + $(CP) $? $@ + +# http://www.cmcrossroads.com/article/printing-value-makefile-variable +print-%: + @echo $* = "$($*)" + @echo $*\'s origin is $(origin $*) + +############################################################################# +.PHONY: all test cfg includes + +# Force make to delete the target if the rule to build it fails +.DELETE_ON_ERROR: diff --git a/idasdk76/dbg/arm_debmod.cpp b/idasdk76/dbg/arm_debmod.cpp new file mode 100644 index 0000000..593e871 --- /dev/null +++ b/idasdk76/dbg/arm_debmod.cpp @@ -0,0 +1,363 @@ +#include <pro.h> +#include <nalt.hpp> +#include "arm_debmod.h" + +#ifdef ENABLE_LOWCNDS +inline bool has_armv5(void) { return true; } +static arm_debmod_t *ssmod; // pointer to the current debugger module +#endif + + +//-------------------------------------------------------------------------- +arm_debmod_t::arm_debmod_t(void) +{ + static const uchar bpt[] = ARM_BPT_CODE; + bpt_code.append(bpt, sizeof(bpt)); + sp_idx = R_SP; + pc_idx = R_PC; + lr_idx = R_LR; + sr_idx = R_PSR; + nregs = qnumber(arm_registers); + + set_platform("linux"); + + reset_hwbpts(); +} + +//-------------------------------------------------------------------------- +int arm_debmod_t::getn_hwbpts_supported(void) +{ + if ( hwbpt_count < 0 ) + { + // unknown, ask the subclass how many hwbpts are supported + hwbpt_count = _getn_hwbpts_supported(); + if ( hwbpt_count < 0 ) + hwbpt_count = 0; + else + hwbpt_count = qmin(hwbpt_count, ARM_MAX_HWBPTS); + } + return hwbpt_count; +} + +//-------------------------------------------------------------------------- +int arm_debmod_t::getn_watchpoints_supported(void) +{ + if ( watch_count < 0 ) + { + // unknown, ask the subclass how many watchpoints are supported + watch_count = _getn_watchpoints_supported(); + if ( watch_count < 0 ) + watch_count = 0; + else + watch_count = qmin(watch_count, ARM_MAX_WATCHPOINTS); + } + return watch_count; +} + +//-------------------------------------------------------------------------- +int arm_debmod_t::find_hwbpt_slot(int *out, ea_t ea) +{ + int slot = -1; + for ( int i = 0, n = getn_hwbpts_supported(); i < n; i++ ) + { + if ( hwbpt_slots[i].addr == ea ) + return BPT_BAD_ADDR; // duplicate + + if ( hwbpt_slots[i].addr == BADADDR && slot < 0 ) + slot = i; + } + + if ( slot < 0 ) + return BPT_TOO_MANY; + + if ( out != nullptr ) + *out = slot; + + return BPT_OK; +} + +//-------------------------------------------------------------------------- +int arm_debmod_t::find_watchpoint_slot(int *out, ea_t ea) +{ + int slot = -1; + for ( int i = 0, n = getn_watchpoints_supported(); i < n; i++ ) + { + if ( watch_slots[i].addr == ea ) + return BPT_BAD_ADDR; // duplicate + + if ( watch_slots[i].addr == BADADDR && slot < 0 ) + slot = i; + } + + if ( slot < 0 ) + return BPT_TOO_MANY; + + if ( out != nullptr ) + *out = slot; + + return BPT_OK; +} + +//-------------------------------------------------------------------------- +int idaapi arm_debmod_t::dbg_is_ok_bpt(bpttype_t type, ea_t ea, int /*len*/) +{ + switch ( type ) + { + case BPT_SOFT: + break; + + case BPT_EXEC: + { + if ( getn_hwbpts_supported() <= 0 ) + return BPT_BAD_TYPE; + + int code = find_hwbpt_slot(nullptr, ea); + if ( code != BPT_OK ) + return code; + } + break; + + default: + { + if ( getn_watchpoints_supported() <= 0 ) + return BPT_BAD_TYPE; + + int code = find_watchpoint_slot(nullptr, ea); + if ( code != BPT_OK ) + return code; + } + break; + } + + return BPT_OK; +} + +//-------------------------------------------------------------------------- +bool arm_debmod_t::add_hwbpt(bpttype_t type, ea_t ea, int len) +{ + int slot; + bool ok = false; + switch ( type ) + { + case BPT_EXEC: + if ( find_hwbpt_slot(&slot, ea) == BPT_OK ) + { + hwbpt_slots[slot].type = type; + hwbpt_slots[slot].addr = ea; + hwbpt_slots[slot].ctrl = get_hwbpt_ctrl_bits(type, ea, len); + ok = true; + } + break; + default: + if ( find_watchpoint_slot(&slot, ea) == BPT_OK ) + { + watch_slots[slot].type = type; + watch_slots[slot].addr = ea; + watch_slots[slot].ctrl = get_watchpoint_ctrl_bits(type, ea, len); + ok = true; + } + break; + } + return ok && refresh_hwbpts(); +} + +//-------------------------------------------------------------------------- +bool arm_debmod_t::del_hwbpt(ea_t ea, bpttype_t type) +{ + bool ok = false; + switch ( type ) + { + case BPT_EXEC: + for ( int i = 0, n = getn_hwbpts_supported(); i < n; i++ ) + { + if ( hwbpt_slots[i].addr == ea ) + { + hwbpt_slots[i].clear(); + ok = true; + break; + } + } + break; + default: + for ( int i = 0, n = getn_watchpoints_supported(); i < n; i++ ) + { + if ( watch_slots[i].addr == ea ) + { + watch_slots[i].clear(); + ok = true; + break; + } + } + break; + } + return ok && refresh_hwbpts(); +} + +//-------------------------------------------------------------------------- +void arm_debmod_t::reset_hwbpts(void) +{ + hwbpt_count = -1; + watch_count = -1; + + for ( size_t i = 0; i < ARM_MAX_HWBPTS; i++ ) + hwbpt_slots[i].clear(); + + for ( size_t i = 0; i < ARM_MAX_WATCHPOINTS; i++ ) + watch_slots[i].clear(); +} + +//-------------------------------------------------------------------------- +void arm_debmod_t::cleanup_hwbpts(void) +{ + reset_hwbpts(); + refresh_hwbpts(); +} + +//-------------------------------------------------------------------------- +int arm_debmod_t::finalize_appcall_stack( + call_context_t &ctx, + regval_map_t ®s, + bytevec_t &/*stk*/) +{ + regs[lr_idx].ival = ctx.ctrl_ea; + // return addrsize as the adjustment factor to add to sp + // we do not need the return address, that's why we ignore the first 4 + // bytes of the prepared stack image + return debapp_attrs.addrsize; +} + +//-------------------------------------------------------------------------- +int arm_debmod_t::get_regidx(const char *regname, int *clsmask) +{ + return arm_get_regidx(clsmask, regname); +} + +#ifdef ENABLE_LOWCNDS +//-------------------------------------------------------------------------- +static const regval_t &idaapi arm_getreg(const char *name, const regval_t *regvals) +{ + int idx = ssmod->get_regidx(name, NULL); + QASSERT(30182, idx >= 0 && idx < ssmod->nregs); + return regvals[idx]; +} + +//-------------------------------------------------------------------------- +static uint32 idaapi arm_get_long(ea_t ea) +{ + uint32 v = -1; + ssmod->dbg_read_memory(ea, &v, sizeof(v), NULL); + return v; +} + +//-------------------------------------------------------------------------- +static uint16 idaapi arm_get_word(ea_t ea) +{ + uint16 v = -1; + ssmod->dbg_read_memory(ea, &v, sizeof(v), NULL); + return v; +} + +//-------------------------------------------------------------------------- +static uint8 idaapi arm_get_byte(ea_t ea) +{ + uint8 v = -1; + ssmod->dbg_read_memory(ea, &v, sizeof(v), NULL); + return v; +} + +//---------------------------------------------------------------------- +// stripped down version of get_dtype_size() +static size_t idaapi arm_get_dtype_size(op_dtype_t dtype) +{ + switch ( dtype ) + { + case dt_byte: return 1; // 8 bit + case dt_word: + case dt_half: return 2; // 16 bit + case dt_dword: + case dt_float: return 4; // 4 byte + case dt_qword: + case dt_double: return 8; // 8 byte + default: return 0; + } +} + +//-------------------------------------------------------------------------- +// since arm does not have a single step facility, we have to emulate it +// with a temporary breakpoint. +drc_t arm_debmod_t::dbg_perform_single_step(debug_event_t *dev, const insn_t &insn) +{ + // read register values + regvals_t values; + values.resize(nregs); + drc_t drc = dbg_read_registers(dev->tid, ARM_RC_GENERAL, values.begin(), NULL); + if ( drc <= DRC_NONE ) + return drc; + + static const opinfo_helpers_t oh = + { + arm_getreg, + arm_get_byte, + arm_get_word, + arm_get_long, + arm_get_dtype_size, + NULL, // has_insn_cf_chg not needed + }; + + // calculate the address of the next executed instruction + lock_begin(); + ssmod = this; + ea_t next = calc_next_exec_insn(insn, values.begin(), oh, false); // TODO pass is_mprofile parameter + ssmod = NULL; + lock_end(); + + // BADADDR means that the execution flow is linear + if ( next == BADADDR ) + { + next = insn.ea + insn.size; + if ( (values[sr_idx].ival & BIT5) != 0 ) // thumb? + next |= 1; + } + + // safety check: self jumping instruction cannot be single stepped + if ( (next & ~1) == insn.ea ) + return DRC_FAILED; + + // add a breakpoint there + update_bpt_info_t ubi; + ubi.ea = next; + ubi.type = BPT_SOFT; + ubi.code = 0; + int nbpts; + drc = dbg_update_bpts(&nbpts, &ubi, 1, 0, NULL); + if ( drc != DRC_OK || nbpts == 0 ) + return drc != DRC_OK ? drc : DRC_FAILED; + + drc = resume_app_and_get_event(dev); + + // clean up: delete the temporary breakpoint + ubi.ea &= ~1; // del_bpt requires an even address + drc_t drc2 = dbg_update_bpts(&nbpts, &ubi, 0, 1, NULL); + if ( drc2 != DRC_OK || nbpts == 0 ) + { + msg("%a: failed to remove single step bpt?!\n", ubi.ea); + drc = drc2 != DRC_OK ? drc2 : DRC_FAILED; + } + // the caller expects to see STEP after us: + if ( drc == DRC_OK ) + dev->set_eid(STEP); + return drc; +} + +#endif // ENABLE_LOWCNDS + +//-------------------------------------------------------------------------- +void arm_debmod_t::adjust_swbpt(ea_t *p_ea, int *p_len) +{ + ea_t &ea = *p_ea; + if ( (ea & 1) != 0 ) // T bit is set, use a thumb breakpoint + { + ea--; + *p_len = 2; + } +} diff --git a/idasdk76/dbg/arm_debmod.h b/idasdk76/dbg/arm_debmod.h new file mode 100644 index 0000000..50905be --- /dev/null +++ b/idasdk76/dbg/arm_debmod.h @@ -0,0 +1,77 @@ +#ifndef __ARM_DEBMOD__ +#define __ARM_DEBMOD__ + +#include "arm_regs.hpp" +#include "deb_arm.hpp" +#include "debmod.h" + +//-------------------------------------------------------------------------- +struct arm_hwbpt_info_t +{ + bpttype_t type; // BPT_... + ea_t addr; // target address + ea_t ctrl; // control value + + arm_hwbpt_info_t(void) { clear(); } + + void clear(void) + { + type = BPT_DEFAULT; + addr = BADADDR; + ctrl = 0; + } +}; + +//-------------------------------------------------------------------------- +class arm_debmod_t : public debmod_t +{ + typedef debmod_t inherited; + +protected: + int hwbpt_count; + int watch_count; + + arm_hwbpt_info_t hwbpt_slots[ARM_MAX_HWBPTS]; + arm_hwbpt_info_t watch_slots[ARM_MAX_WATCHPOINTS]; + + int lr_idx; + int sr_idx; + +public: + arm_debmod_t(void); + + void reset_hwbpts(void); + void cleanup_hwbpts(void); + + int getn_hwbpts_supported(void); + int getn_watchpoints_supported(void); + + int find_hwbpt_slot(int *slot, ea_t ea); + int find_watchpoint_slot(int *slot, ea_t ea); + + bool add_hwbpt(bpttype_t type, ea_t ea, int len); + bool del_hwbpt(ea_t ea, bpttype_t type); + + // subclasses must implement these functions to properly support hardware breakpoints/watchpoints + virtual int _getn_hwbpts_supported(void) newapi { return -1; } + virtual int _getn_watchpoints_supported(void) newapi { return -1; } + virtual ea_t get_hwbpt_ctrl_bits(bpttype_t, ea_t, int) newapi { return 0; } + virtual ea_t get_watchpoint_ctrl_bits(bpttype_t, ea_t, int) newapi { return 0; } + virtual bool refresh_hwbpts(void) newapi { return false; } + + // overridden base class functions + virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) override; + virtual int finalize_appcall_stack(call_context_t &ctx, regval_map_t ®s, bytevec_t &stk) override; + + virtual int get_regidx(const char *regname, int *clsmask) override; + virtual void adjust_swbpt(ea_t *p_ea, int *p_len) override; + +protected: +#ifdef ENABLE_LOWCNDS + virtual drc_t dbg_perform_single_step(debug_event_t *dev, const insn_t &insn) override; +#endif +}; + +bool is_32bit_thumb_insn(uint16 code); + +#endif diff --git a/idasdk76/dbg/arm_local_impl.cpp b/idasdk76/dbg/arm_local_impl.cpp new file mode 100644 index 0000000..e24a90c --- /dev/null +++ b/idasdk76/dbg/arm_local_impl.cpp @@ -0,0 +1,101 @@ +#include <idp.hpp> +#include <dbg.hpp> +#include <loader.hpp> +#include <segregs.hpp> +#include <segment.hpp> + +#include "deb_arm.hpp" + +#include "arm_regs.cpp" + +//-------------------------------------------------------------------------- +int is_arm_valid_bpt(bpttype_t type, ea_t ea, int len) +{ + switch ( type ) + { + case BPT_SOFT: + if ( (ea & 1) != 0 ) + return BPT_BAD_ADDR; + break; + + case BPT_EXEC: + if ( (ea & 3) != 0 ) + return BPT_BAD_ALIGN; + break; + + default: + if ( (ea & 7) != 0 ) + return BPT_BAD_ALIGN; + if ( len < 1 || len > 8 ) + return BPT_BAD_LEN; + break; + } + + return BPT_OK; +} + +//-------------------------------------------------------------------------- +// if bit0 is set, ensure that thumb mode +// if bit0 is clear, ensure that arm mode +static void handle_arm_thumb_modes(ea_t ea) +{ + bool should_be_thumb = (ea & 1) != 0; + bool is_thumb = processor_t::get_code16_mode(ea); + if ( should_be_thumb != is_thumb ) + processor_t::set_code16_mode(ea, should_be_thumb); +} + +//-------------------------------------------------------------------------- +static easet_t pending_addresses; + +static ssize_t idaapi dbg_callback(void *, int code, va_list) +{ + // we apply thumb/arm switches when the process is suspended. + // it is quite late (normally we should do it as soon as the corresponding + // segment is created) but i did not manage to make it work. + // in the segm_added event the addresses are not enabled yet, + // so switching modes fails. + if ( code == dbg_suspend_process && !pending_addresses.empty() ) + { + for ( easet_t::iterator p=pending_addresses.begin(); + p != pending_addresses.end(); + ++p ) + { + handle_arm_thumb_modes(*p); + } + pending_addresses.clear(); + } + return 0; +} + +//-------------------------------------------------------------------------- +// For ARM processors the low bit means 1-thumb, 0-arm mode. +// The following function goes over the address list and sets the mode +// in IDA database according to bit0. It also resets bit0 for all addresses. +void set_arm_thumb_modes(ea_t *addrs, int qty) +{ + for ( int i=0; i < qty; i++ ) + { + ea_t ea = addrs[i]; + segment_t *s = getseg(ea); + if ( s == NULL ) + pending_addresses.insert(ea); + else + handle_arm_thumb_modes(ea); + + addrs[i] = ea & ~1; + } +} + +//-------------------------------------------------------------------------- +void processor_specific_init(void) +{ + hook_to_notification_point(HT_DBG, dbg_callback); +} + +//-------------------------------------------------------------------------- +void processor_specific_term(void) +{ + unhook_from_notification_point(HT_DBG, dbg_callback); + pending_addresses.clear(); +} diff --git a/idasdk76/dbg/arm_regs.cpp b/idasdk76/dbg/arm_regs.cpp new file mode 100644 index 0000000..48f9227 --- /dev/null +++ b/idasdk76/dbg/arm_regs.cpp @@ -0,0 +1,259 @@ + +#include "arm_regs.hpp" + +//------------------------------------------------------------------------- +// NOTE: keep in sync with register_class_arm_t +const char *arm_register_classes[] = +{ + "General registers", + "VFP registers", + "NEON registers", + NULL +}; + +#ifndef __EA64__ +//------------------------------------------------------------------------- +static const char *const psr[] = +{ + "MODE", // 0 + "MODE", // 1 + "MODE", // 2 + "MODE", // 3 + "MODE", // 4 + "T", // 5 + "F", // 6 + "I", // 7 + "A", // 8 + "E", // 9 + "IT", // 10 + "IT", // 11 + "IT", // 12 + "IT", // 13 + "IT", // 14 + "IT", // 15 + "GE", // 16 + "GE", // 17 + "GE", // 18 + "GE", // 19 + NULL, // 20 + NULL, // 21 + NULL, // 22 + NULL, // 23 + "J", // 24 + "IT2", // 25 additional bits of IT + "IT2", // 26 additional bits of IT + "Q", // 27 + "V", // 28 + "C", // 29 + "Z", // 30 + "N", // 31 +}; + +//------------------------------------------------------------------------- +static const char *const vfp_format[] = +{ + "VFP_1_double", +}; +#else +//------------------------------------------------------------------------- +static const char *const psr[] = +{ + "M", // 0 AArch32 mode that an exception was taken from + "M", // 1 + "M", // 2 + "M", // 3 + "M", // 4 Execution state that the exception was taken from + "T", // 5 T32 Instruction set state bit + "F", // 6 FIQ mask bit + "I", // 7 IRQ mask bit + "A", // 8 Asynchronous data abort mask bit + "E", // 9 Endianness Execution State bit + "IT", // 10 If-Then + "IT", // 11 + "IT", // 12 + "IT", // 13 + "IT", // 14 + "IT", // 15 + "GE", // 16 Greater than or Equal flags + "GE", // 17 + "GE", // 18 + "GE", // 19 + "IL", // 20 Illegal Execution State bit + NULL, // 21 + NULL, // 22 + NULL, // 23 + NULL, // 24 + "IT2", // 25 If-Then + "IT2", // 26 + "Q", // 27 Cumulative saturation bit + "V", // 28 oVerflow condition flag + "C", // 29 Carry condition flag + "Z", // 30 Zero condition flag + "N", // 31 Negative condition flag +}; + +//------------------------------------------------------------------------- +static const char *const neon_formats[] = +{ + "NEON_16_bytes", + "NEON_8_words", + "NEON_4_dwords", + "NEON_2_qwords", + "NEON_4_floats", + "NEON_2_doubles", +}; +#endif + +//------------------------------------------------------------------------- +// NOTE: keep in sync with register_arm_t +register_info_t arm_registers[] = +{ +#ifndef __EA64__ + // General registers + { "R0", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R1", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R2", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R3", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R4", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R5", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R6", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R7", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R8", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R9", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R10", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R11", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "R12", REGISTER_ADDRESS|REGISTER_FP, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "SP", REGISTER_ADDRESS|REGISTER_SP, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "LR", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "PC", REGISTER_ADDRESS|REGISTER_IP, ARM_RC_GENERAL, dt_dword, NULL, 0 }, + { "PSR", 0, ARM_RC_GENERAL, dt_dword, psr, 0xF800007F }, + // VFP registers + { "D0", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D1", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D2", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D3", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D4", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D5", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D6", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D7", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D8", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D9", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D10", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D11", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D12", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D13", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D14", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D15", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D16", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D17", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D18", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D19", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D20", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D21", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D22", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D23", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D24", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D25", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D26", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D27", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D28", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D29", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D30", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "D31", REGISTER_CUSTFMT, ARM_RC_VFP, dt_qword, vfp_format, 0 }, + { "FPSCR", 0, ARM_RC_VFP, dt_dword, NULL, 0 }, +#else + // General registers + { "X0", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X1", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X2", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X3", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X4", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X5", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X6", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X7", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X8", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X9", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X10", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X11", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X12", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X13", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X14", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X15", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X16", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X17", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X18", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X19", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X20", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X21", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X22", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X23", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X24", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X25", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X26", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X27", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X28", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X29", REGISTER_ADDRESS|REGISTER_FP, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "X30", REGISTER_ADDRESS, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "SP", REGISTER_ADDRESS|REGISTER_SP, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "PC", REGISTER_ADDRESS|REGISTER_IP, ARM_RC_GENERAL, dt_qword, NULL, 0 }, + { "PSR", 0, ARM_RC_GENERAL, dt_dword, psr, 0xF8000000 }, + { "V0", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V1", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V2", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V3", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V4", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V5", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V6", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V7", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V8", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V9", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V10", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V11", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V12", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V13", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V14", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V15", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V16", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V17", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V18", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V19", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V20", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V21", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V22", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V23", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V24", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V25", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V26", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V27", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V28", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V29", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V30", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "V31", REGISTER_CUSTFMT, ARM_RC_NEON, dt_byte16, neon_formats, 0 }, + { "FPSR", 0, ARM_RC_NEON, dt_dword, NULL, 0 }, + { "FPCR", 0, ARM_RC_NEON, dt_dword, NULL, 0 }, +#endif +}; +CASSERT(qnumber(arm_registers) == ARM_NREGS); + +//------------------------------------------------------------------------- +int arm_get_regidx(int *clsmask, const char *regname) +{ + for ( size_t i = 0; i < qnumber(arm_registers); i++ ) + { + if ( strieq(regname, arm_registers[i].name) ) + { + if ( clsmask != NULL ) + *clsmask = arm_registers[i].register_class; + return i; + } + } + return -1; +} + +//------------------------------------------------------------------------- +int arm_get_regclass(int idx) +{ + if ( idx >= 0 && idx < qnumber(arm_registers) ) + return arm_registers[idx].register_class; + return 0; +} diff --git a/idasdk76/dbg/arm_regs.hpp b/idasdk76/dbg/arm_regs.hpp new file mode 100644 index 0000000..378a6d1 --- /dev/null +++ b/idasdk76/dbg/arm_regs.hpp @@ -0,0 +1,182 @@ + +#pragma once + +#include <pro.h> +#include <idd.hpp> + +//------------------------------------------------------------------------- +#if defined(__LINUX__) && defined(__ARM__) && !defined(__EA64__) +# define __HAVE_ARM_VFP__ +#endif + +//------------------------------------------------------------------------- +#if defined(__MAC__) && defined(__ARM__) +# define __HAVE_ARM_NEON__ +#endif + +//------------------------------------------------------------------------- +// NOTE: keep in sync with arm_register_classes +enum register_class_arm_t +{ + ARM_RC_GENERAL = 0x01, // General registers + ARM_RC_VFP = 0x02, // VFP registers + ARM_RC_NEON = 0x04, // NEON registers + ARM_RC_ALL = ARM_RC_GENERAL +#ifdef __HAVE_ARM_VFP__ + | ARM_RC_VFP +#endif +#ifdef __HAVE_ARM_NEON__ + | ARM_RC_NEON +#endif +}; + +//------------------------------------------------------------------------- + +//------------------------------------------------------------------------- +// NOTE: keep in sync with arm_registers +enum register_arm_t +{ +#ifndef __EA64__ + // General registers + R_R0, + R_R1, + R_R2, + R_R3, + R_R4, + R_R5, + R_R6, + R_R7, + R_R8, + R_R9, + R_R10, + R_R11, + R_R12, + R_SP, + R_LR, + R_PC, + R_PSR, + // VFP registers + R_D0, + R_D1, + R_D2, + R_D3, + R_D4, + R_D5, + R_D6, + R_D7, + R_D8, + R_D9, + R_D10, + R_D11, + R_D12, + R_D13, + R_D14, + R_D15, + R_D16, + R_D17, + R_D18, + R_D19, + R_D20, + R_D21, + R_D22, + R_D23, + R_D24, + R_D25, + R_D26, + R_D27, + R_D28, + R_D29, + R_D30, + R_D31, + R_FPSCR, +#else + // General registers + R_R0, + R_R1, + R_R2, + R_R3, + R_R4, + R_R5, + R_R6, + R_R7, + R_R8, + R_R9, + R_R10, + R_R11, + R_R12, + R_R13, + R_R14, + R_R15, + R_R16, + R_R17, + R_R18, + R_R19, + R_R20, + R_R21, + R_R22, + R_R23, + R_R24, + R_R25, + R_R26, + R_R27, + R_R28, + R_R29, + R_LR, + R_SP, + R_PC, + R_PSR, + // NEON registers + R_V0, + R_V1, + R_V2, + R_V3, + R_V4, + R_V5, + R_V6, + R_V7, + R_V8, + R_V9, + R_V10, + R_V11, + R_V12, + R_V13, + R_V14, + R_V15, + R_V16, + R_V17, + R_V18, + R_V19, + R_V20, + R_V21, + R_V22, + R_V23, + R_V24, + R_V25, + R_V26, + R_V27, + R_V28, + R_V29, + R_V30, + R_V31, + R_FPSR, + R_FPCR, +#endif +}; + +// Number of registers in arm and aarch64 +#define ARM64_NREGS 68 +#define ARM32_NREGS 50 + +#ifdef __EA64__ + #define ARM_NREGS ARM64_NREGS +#else + #define ARM_NREGS ARM32_NREGS +#endif + +//------------------------------------------------------------------------- +extern const char *arm_register_classes[]; +extern register_info_t arm_registers[ARM_NREGS]; + +//------------------------------------------------------------------------- +int arm_get_regidx(int *clsmask, const char *regname); +int arm_get_regclass(int idx); diff --git a/idasdk76/dbg/bin_search.cpp b/idasdk76/dbg/bin_search.cpp new file mode 100644 index 0000000..90681f4 --- /dev/null +++ b/idasdk76/dbg/bin_search.cpp @@ -0,0 +1,906 @@ +#include <pro.h> +#include "debmod.h" + +//#define TEST +#ifdef TEST +static uchar memory[256]; +static const int PAGESZ = 4; +static ssize_t read_page(ea_t ea, void *buf, size_t size, qstring *) +{ + QASSERT(1517, (size % PAGESZ) == 0); + if ( ea >= sizeof(memory) ) + return -1; + memcpy(buf, &memory[ea], size); + return size; +} +#else +static const int PAGESZ = 4096; +#define read_page(ea, buf, size, errbuf) mod->dbg_read_memory(ea, buf, size, errbuf) +#endif +static const int PAGE_HB = 1000; // page heartbeat counter +static const int TIME_HB = (RECV_TIMEOUT_PERIOD/1000) / 2; + // time period between heartbeats + +//-------------------------------------------------------------------------- +// memrchr is unavailable under Windows and MAC +#if defined(_WIN32) || defined(__MAC__) +// fixme: we need more optimized version +static void *local_memrchr(const void *s, int c, size_t n) +{ + const unsigned char *start = (const unsigned char *)s; + const unsigned char *end = start + n - 1; + while ( end >= start ) + { + if ( *end == c ) + return (void *)end; + end--; + } + return NULL; +} +#else +#define local_memrchr memrchr +#endif + +//-------------------------------------------------------------------------- +class matcher_t +{ +protected: + struct partmatch_t + { + ea_t match_ea; // starting address of the match + size_t ptn_idx; // index of the pattern + size_t ptn_off; // offset inside the pattern + }; + typedef qlist<partmatch_t> partmatches_t; + + // constructor arguments + ea_t *found_ea; + debmod_t *mod; + const compiled_binpat_vec_t &ptns; + int srch_flags; + qstring *errbuf; //lint !e958 + + uchar page[PAGESZ]; + ea_t page_ea; + partmatches_t pmatches; + ea_t failed_ea; + + // cache + intvec_t simple_ptns; // indexes of patterns w/o a mask and the search is case sensitive + intvec_t complex_ptns; // other patterns + + // heartbeat + uint32 last_hb; // time in secs of the last heartbeat + + matcher_t( + ea_t *_found_ea, + debmod_t *_mod, + const compiled_binpat_vec_t &_ptns, + int _srch_flags, + qstring *_errbuf) + : found_ea(_found_ea), + mod(_mod), + ptns(_ptns), + srch_flags(_srch_flags), + errbuf(_errbuf), + page_ea(BADADDR), + failed_ea(BADADDR) + { + for ( int i=0; i < ptns.size(); ++i ) + { + const compiled_binpat_t &ptn = ptns[i]; + if ( ptn.bytes.empty() ) + continue; + if ( sense_case() && ptn.all_bytes_defined() ) // TODO: && !inf_is_wide_high_byte_first() - for servers + simple_ptns.push_back(i); + else + complex_ptns.push_back(i); + } + memset(page, 0, sizeof(page)); + last_hb = get_secs(qtime64()); + } + + bool sense_case(void) const { return (srch_flags & BIN_SEARCH_CASE) != 0; } + bool check_break(void) const { return (srch_flags & BIN_SEARCH_NOBREAK) == 0; } + + bool test_cancelled(void) const + { + struct ida_local tester_t : public exec_request_t + { + virtual ~tester_t() {} + virtual int idaapi execute(void) + { + return user_cancelled(); + } + }; + tester_t tester; + return static_cast<bool>(execute_sync(tester, MFF_FAST)); + } + + void send_heartbeat(size_t *page_counter) + { + *page_counter += 1; + if ( *page_counter >= PAGE_HB ) + { + *page_counter = 0; + uint32 now = get_secs(qtime64()); + if ( now - last_hb >= TIME_HB ) + { + mod->dmsg(""); // heartbeat + last_hb = now; + } + } + } + +public: + virtual ~matcher_t() + { + found_ea = NULL; + mod = NULL; + errbuf = NULL; + } + + virtual drc_t walk_memory_ranges(const ea_t srch_start_ea, const ea_t srch_end_ea) = 0; + + drc_t search_memory_range(ea_t range_start_ea, ea_t range_end_ea) + { + if ( range_is_unreadable(range_start_ea) ) + { + #ifndef TEST + mod->debdeb("dbg_bin_search memory range %a..%a is unreadable, skip it\n", range_start_ea, range_end_ea); + #endif + return DRC_FAILED; + } + + return find(range_start_ea, range_end_ea); + } + + virtual drc_t find(ea_t start_ea, ea_t end_ea) = 0; + + bool match_pattern( + const uchar *page_ptr, + const compiled_binpat_t &ptn, + size_t ptn_off, + size_t nbytes) const + { + const uchar *image = ptn.bytes.begin() + ptn_off; + const uchar *mask = ptn.all_bytes_defined() ? NULL : ptn.mask.begin() + ptn_off; + for ( int i=0; i < nbytes; ++i, ++page_ptr, ++image ) + { + uchar c = *page_ptr; + if ( mask != NULL ) + { + if ( mask == SKIP_FF_MASK ) + { + if ( *image == 0xFF ) + continue; + } + else + { + if ( mask[i] == 0 ) + continue; + } + } + uchar c2 = *image; + if ( sense_case() ? (c != c2) : (qtoupper(c) != qtoupper(c2)) ) + return false; + } + return true; + } + + ea_t get_failed_address(void) const { return failed_ea; } + +private: + bool range_is_unreadable(ea_t range_start_ea) + { + uchar dummy; + return mod->dbg_read_memory(range_start_ea, &dummy, sizeof(dummy), NULL) != sizeof(dummy); + } +}; + +typedef janitor_t<matcher_t *> matcher_janitor_t; +template <> inline matcher_janitor_t::~janitor_t() +{ + delete resource; + resource = NULL; +} + +//-------------------------------------------------------------------------- +class forward_matcher_t : public matcher_t +{ + size_t last_off; + +public: + forward_matcher_t( + ea_t *_found_ea, + debmod_t *_mod, + const compiled_binpat_vec_t &_ptns, + int _srch_flags, + qstring *_errbuf) + : matcher_t(_found_ea, _mod, _ptns, _srch_flags, _errbuf), + last_off(PAGESZ) + {} + + //-------------------------------------------------------------------------- + virtual drc_t walk_memory_ranges(const ea_t srch_start_ea, const ea_t srch_end_ea) override + { + meminfo_vec_t::const_iterator p=mod->old_ranges.begin(); + ea_t range_start_ea = BADADDR; + for ( ; p < mod->old_ranges.end(); ++p ) + { + if ( p->contains(srch_start_ea) ) + { + range_start_ea = srch_start_ea; + break; + } + if ( p->start_ea > srch_start_ea ) + break; + } + if ( range_start_ea == BADADDR ) + { + if ( p == mod->old_ranges.end() || p->start_ea >= srch_end_ea ) + return DRC_FAILED; // not found + range_start_ea = p->start_ea; + } + ea_t range_end_ea = srch_end_ea < p->end_ea ? srch_end_ea : p->end_ea; + drc_t drc = search_memory_range(range_start_ea, range_end_ea); + if ( drc != DRC_FAILED ) // not found + return drc; + + for ( ++p; p < mod->old_ranges.end() && srch_end_ea >= p->end_ea; ++p ) + { + range_start_ea = p->start_ea; + range_end_ea = srch_end_ea < p->end_ea ? srch_end_ea : p->end_ea; + drc = search_memory_range(range_start_ea, range_end_ea); + if ( drc != DRC_FAILED ) // not found + return drc; + } + + return DRC_FAILED; // not found + } + + //-------------------------------------------------------------------------- + // find patterns in [start_ea, end_ea) + virtual drc_t find(ea_t start_ea, ea_t end_ea) override + { + page_ea = align_down(start_ea, PAGESZ); + ea_t page_off = start_ea - page_ea; + size_t page_counter = 0; + while ( page_ea < end_ea ) + { + if ( check_break() && test_cancelled() ) + return DRC_ERROR; + if ( read_page(page_ea, page, sizeof(page), errbuf) != sizeof(page) ) + { + failed_ea = page_ea; + return DRC_ERROR; + } + last_off = end_ea - page_ea; + if ( last_off > PAGESZ ) + last_off = PAGESZ; + // handle partial matches first + for ( partmatches_t::iterator p=pmatches.begin(); p != pmatches.end(); ) + { + switch ( finalize_partial_match(*p) ) + { + case DRC_OK: // found a match + return DRC_OK; + default: + case DRC_FAILED: // definitely failed + p = pmatches.erase(p); + break; + case DRC_NONE: // need to continue matching + ++p; + break; + } + } + // try to find new matches + if ( match_simple_patterns(page_off) ) + return DRC_OK; + if ( !complex_ptns.empty() ) + { + while ( page_off < last_off ) + { + if ( match_at(page_off) ) + return DRC_OK; + page_off++; + } + } + page_ea += PAGESZ; // advance to the next page + page_off = 0; + send_heartbeat(&page_counter); + } + return DRC_FAILED; + } + +private: + //-------------------------------------------------------------------------- + // try to match complex patterns at PAGE_OFF + // too long patterns that do not fit the page will be matched partially + // if the partial match is ok, we will remember them + bool match_at(ea_t page_off) + { + const uchar *page_ptr = page + page_off; + size_t rest = last_off - page_off; + for ( intvec_t::const_iterator p=complex_ptns.begin(); + p != complex_ptns.end(); + ++p ) + { + const int &i = *p; + const compiled_binpat_t &ptn = ptns[i]; + size_t vecsize = ptn.bytes.size(); + size_t nbytes = qmin(rest, vecsize); + if ( !match_pattern(page_ptr, ptn, 0, nbytes) ) + continue; + if ( vecsize <= rest ) + { + *found_ea = page_ea + page_off; + return true; // fits the page, a simple comparison is enough + } + // remember partial match + partmatch_t pm; + pm.match_ea = page_ea + page_off; + pm.ptn_idx = i; + pm.ptn_off = nbytes; + pmatches.push_back(pm); + } + return false; + } + + //-------------------------------------------------------------------------- + // try to match simple patterns inside the page + // the partial match is processed as described above + bool match_simple_patterns(ea_t page_off) + { + for ( intvec_t::const_iterator p=simple_ptns.begin(); + p != simple_ptns.end(); + ++p ) + { + const int &i = *p; + const uchar *page_ptr = page + page_off; + size_t rest = last_off - page_off; + const bytevec_t &ptn_bytes = ptns[i].bytes; + size_t ptn_sz = ptn_bytes.size(); + uchar ptn_ch = ptn_bytes[0]; + + const uchar *pold = page_ptr; + while ( rest > 0 ) + { + const uchar *pnew = (uchar *)memchr(pold, ptn_ch, rest); + if ( pnew == NULL ) + break; + rest -= (pnew - pold); + size_t nbytes = qmin(rest, ptn_sz); + if ( memcmp(pnew, ptn_bytes.begin(), nbytes) == 0 ) + { + ea_t matched_ea = page_ea + (pnew - page); + if ( ptn_sz <= rest ) + { + *found_ea = matched_ea; + return true; + } + // remember partial match + partmatch_t pm; + pm.match_ea = matched_ea; + pm.ptn_idx = i; + pm.ptn_off = nbytes; + pmatches.push_back(pm); + } + pold = pnew + 1; + rest -= 1; + } + } + return false; + } + + //-------------------------------------------------------------------------- + // try to finalize a partial match by matching the next part of the + // long pattern against the start of the PAGE. patterns that are still + // too long for matching may produce new partial matches. + drc_t finalize_partial_match(partmatch_t &pm) + { + const compiled_binpat_t &ptn = ptns[pm.ptn_idx]; + size_t vecsize = ptn.bytes.size(); + size_t ptn_rest = vecsize - pm.ptn_off; + size_t nbytes = qmin(ptn_rest, last_off); + if ( !match_pattern(page, ptn, pm.ptn_off, nbytes) ) + return DRC_FAILED; + if ( ptn_rest <= last_off ) + { + *found_ea = pm.match_ea; + return DRC_OK; // finalized the match + } + if ( last_off != PAGESZ ) + return DRC_FAILED; + // remember a new partial match + pm.ptn_off += PAGESZ; + return DRC_NONE; + } +}; + +//-------------------------------------------------------------------------- +class backward_matcher_t : public matcher_t +{ + ea_t page_off; + +public: + backward_matcher_t( + ea_t *_found_ea, + debmod_t *_mod, + const compiled_binpat_vec_t &_ptns, + int _srch_flags, + qstring *_errbuf) + : matcher_t(_found_ea, _mod, _ptns, _srch_flags, _errbuf), + page_off(0) + {} + + //-------------------------------------------------------------------------- + virtual drc_t walk_memory_ranges(const ea_t srch_start_ea, const ea_t srch_end_ea) override + { + meminfo_vec_t::const_iterator p=mod->old_ranges.end() - 1; + ea_t range_end_ea = BADADDR; + for ( ; p >= mod->old_ranges.begin(); --p ) + { + if ( p->start_ea < srch_end_ea ) + { + range_end_ea = srch_end_ea < p->end_ea ? srch_end_ea : p->end_ea; + break; + } + } + if ( range_end_ea == BADADDR ) + return DRC_FAILED; // not found + ea_t range_start_ea = p->contains(srch_start_ea) ? srch_start_ea : p->start_ea; + drc_t drc = search_memory_range(range_start_ea, range_end_ea); + if ( drc != DRC_FAILED ) // not found + return drc; + + for ( --p; p >= mod->old_ranges.begin() && srch_start_ea < p->end_ea; --p ) + { + range_end_ea = p->end_ea; + range_start_ea = p->contains(srch_start_ea) ? srch_start_ea : p->start_ea; + drc = search_memory_range(range_start_ea, range_end_ea); + if ( drc != DRC_FAILED ) // not found + return drc; + } + + return DRC_FAILED; // not found + } + + //-------------------------------------------------------------------------- + // find patterns in [start_ea, end_ea) + virtual drc_t find(ea_t start_ea, ea_t end_ea) override + { + page_ea = align_down(end_ea - 1, PAGESZ); + ea_t last_off = end_ea - page_ea; + size_t page_counter = 0; + while ( start_ea < page_ea + PAGESZ ) + { + if ( check_break() && test_cancelled() ) + return DRC_ERROR; + if ( read_page(page_ea, page, sizeof(page), errbuf) != sizeof(page) ) + { + failed_ea = page_ea; + return DRC_ERROR; + } + page_off = page_ea < start_ea ? start_ea - page_ea : 0; + // handle partial matches first + for ( partmatches_t::iterator p=pmatches.begin(); p != pmatches.end(); ) + { + switch ( finalize_partial_match(*p) ) + { + case DRC_OK: // found a match + return DRC_OK; + default: + case DRC_FAILED: // definitely failed + p = pmatches.erase(p); + break; + case DRC_NONE: // need to continue matching + ++p; + break; + } + } + // try to find new matches + if ( match_simple_patterns(last_off) ) + return DRC_OK; + if ( !complex_ptns.empty() ) + { + while ( page_off < last_off ) + { + if ( match_before(last_off) ) + return DRC_OK; + last_off--; + } + } + page_ea -= PAGESZ; // advance to the next page + last_off = PAGESZ; + send_heartbeat(&page_counter); + } + return DRC_FAILED; + } + +private: + //-------------------------------------------------------------------------- + // try to match all patterns before LAST_OFF + // too long patterns that do not fit the page will be matched partially + // if the partial match is ok, we will remember them + bool match_before(ea_t last_off) + { + size_t rest = last_off - page_off; + for ( intvec_t::const_iterator p=complex_ptns.begin(); + p != complex_ptns.end(); + ++p ) + { + const int &i = *p; + const compiled_binpat_t &ptn = ptns[i]; + size_t vecsize = ptn.bytes.size(); + size_t nbytes = qmin(rest, vecsize); + if ( !match_pattern(page+last_off-nbytes, ptn, vecsize-nbytes, nbytes) ) + continue; + if ( vecsize <= rest ) + { + *found_ea = page_ea + last_off - nbytes; + return true; // fits the page, a simple comparison is enough + } + // remember partial match + partmatch_t pm; + pm.match_ea = page_ea + last_off - vecsize; + pm.ptn_idx = i; + pm.ptn_off = nbytes; + pmatches.push_back(pm); + } + return false; + } + + //-------------------------------------------------------------------------- + // try to match simple patterns inside the page + // the partial match is processed as described above + bool match_simple_patterns(ea_t last_off) + { + const uchar *page_ptr = page + page_off; + + for ( intvec_t::const_iterator q=simple_ptns.begin(); + q != simple_ptns.end(); + ++q ) + { + const int &i = *q; + size_t rest = last_off - page_off; + const bytevec_t &ptn_bytes = ptns[i].bytes; + size_t ptn_sz = ptn_bytes.size(); + uchar ptn_ch = ptn_bytes[ptn_sz-1]; + + while ( rest > 0 ) + { + const uchar *p = (uchar *)local_memrchr(page_ptr, ptn_ch, rest); + if ( p == NULL ) + break; + rest = p + 1 - page_ptr; + size_t nbytes = qmin(rest, ptn_sz); + if ( memcmp(p + 1 - nbytes, &ptn_bytes[ptn_sz - nbytes], nbytes) == 0 ) + { + ea_t matched_ea = page_ea + (p + 1 - page) - ptn_sz; + if ( ptn_sz <= rest ) + { + *found_ea = matched_ea; + return true; + } + // remember partial match + partmatch_t pm; + pm.match_ea = matched_ea; + pm.ptn_idx = i; + pm.ptn_off = nbytes; + pmatches.push_back(pm); + } + rest -= 1; + } + } + return false; + } + + //-------------------------------------------------------------------------- + // try to finalize a partial match by matching the previous part of the + // long pattern against the end of the PAGE. patterns that are still + // too long for matching may produce new partial matches. + drc_t finalize_partial_match(partmatch_t &pm) + { + const compiled_binpat_t &ptn = ptns[pm.ptn_idx]; + size_t vecsize = ptn.bytes.size(); + size_t ptn_rest = vecsize - pm.ptn_off; + size_t nbytes = qmin(ptn_rest, PAGESZ - page_off); + if ( !match_pattern(page + PAGESZ - nbytes, ptn, ptn_rest - nbytes, nbytes) ) + return DRC_FAILED; + if ( ptn_rest <= PAGESZ - page_off ) + { + *found_ea = pm.match_ea; + return DRC_OK; // finalized the match + } + if ( page_off != 0 ) + return DRC_FAILED; + // remember a new partial match + pm.ptn_off += PAGESZ; + return DRC_NONE; + } + +}; + +#ifndef TEST +//-------------------------------------------------------------------------- +// Note: +// The input search range can include the unreadable memory regions. +// For example, "[vvar]" on Linux. +// read_memory() returns 0 when trying to read from such region. +// These regions must be skipped. +drc_t idaapi debmod_t::dbg_bin_search( + ea_t *found_ea, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &ptns, + int srch_flags, + qstring *errbuf) +{ + static int forbidden = -1; + if ( forbidden == -1 ) + forbidden = qgetenv("IDA_IDB_BIN_SEARCH", NULL); + if ( forbidden ) + return DRC_NONE; + + debdeb("dbg_bin_search %a..%a\n", start_ea, end_ea); + + if ( start_ea >= end_ea || ptns.empty() || old_ranges.empty() ) + return DRC_NONE; + + //lint -esym(429,matcher) has not been freed + matcher_t *matcher = NULL; + matcher_janitor_t matcher_janitor(matcher); + + bool search_backward = (srch_flags & BIN_SEARCH_BACKWARD) != 0; + if ( search_backward ) + matcher = new backward_matcher_t(found_ea, this, ptns, srch_flags, errbuf); + else + matcher = new forward_matcher_t(found_ea, this, ptns, srch_flags, errbuf); + + drc_t drc = matcher->walk_memory_ranges(start_ea, end_ea); + if ( drc != DRC_ERROR ) + return drc; //-V773 without releasing the 'matcher' pointer + + ea_t failed_ea = matcher->get_failed_address(); + if ( failed_ea != BADADDR ) + { + debdeb("dbg_bin_search failed to read memory at %a\n", failed_ea); + if ( errbuf != NULL && errbuf->empty() ) + errbuf->sprnt("Failed to read memory at %a\n", failed_ea); + } + + return DRC_ERROR; +} + +#else // TEST +//-------------------------------------------------------------------------- +drc_t binary_search( + ea_t *found_ea, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &ptns, + int srch_flags, + qstring *errbuf) +{ + matcher_t *matcher; + if ( (srch_flags & BIN_SEARCH_BACKWARD) != 0 ) + matcher = new backward_matcher_t(found_ea, NULL, ptns, srch_flags, errbuf); + else + matcher = new forward_matcher_t(found_ea, NULL, ptns, srch_flags, errbuf); + drc_t drc = matcher->find(start_ea, end_ea); + delete matcher; + return drc; +} + +//--------------------------------------------------------------------------- +inline bool cmpbytes( + const uchar *ptr, + uchar b, + const uchar *pptr, + size_t ptnsize, + bool sense_case) +{ + if ( sense_case ) + return *ptr == b && memcmp(ptr+1, pptr, ptnsize) == 0; //lint !e670 + if ( qtoupper(b) != qtoupper(*ptr) ) + return false; + ++ptr; + for ( int i=0; i < ptnsize; ++i, ++ptr, ++pptr ) + { + if ( qtoupper(*ptr) != qtoupper(*pptr) ) + return false; + } + return true; +} + +//--------------------------------------------------------------------------- +void *memmem( + const void *buf, + size_t bufsize, + const void *ptn, + size_t ptnsize, + bool sense_case) +{ + if ( int(ptnsize) <= 0 || int(bufsize) < 0 || ptnsize > bufsize ) + return NULL; + const uchar *ptr = (const uchar *)buf; + const uchar *const end = ptr + bufsize - ptnsize + 1; + const uchar *pptr = (const uchar *)ptn; + uchar b = *pptr++; + ptnsize--; + while ( ptr < end ) + { + if ( cmpbytes(ptr, b, pptr, ptnsize, sense_case) ) + return (void *)ptr; + ++ptr; + } + return NULL; +} + +//--------------------------------------------------------------------------- +void *memmemr( + const void *buf, + size_t bufsize, + const void *ptn, + size_t ptnsize, + bool sense_case) +{ + if ( int(ptnsize) <= 0 || int(bufsize) < 0 || ptnsize > bufsize ) + return NULL; + const uchar *ptr = (const uchar *)buf + bufsize - ptnsize; + const uchar *const start = (const uchar *)buf; + const uchar *pptr = (const uchar *)ptn; + uchar b = *pptr++; + ptnsize--; + while ( start <= ptr ) + { + if ( cmpbytes(ptr, b, pptr, ptnsize, sense_case) ) + return (void *)ptr; + --ptr; + } + return NULL; +} + +//-------------------------------------------------------------------------- +drc_t simple_binary_search( + eavec_t *found_eas, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &ptns, + int srch_flags, + qstring * /*errbuf*/) +{ + if ( start_ea >= end_ea || start_ea > sizeof(memory) ) + return DRC_FAILED; + bool sense_case = (srch_flags & BIN_SEARCH_CASE) != 0; + found_eas->clear(); + bool backward = (srch_flags & BIN_SEARCH_BACKWARD) != 0; + for ( compiled_binpat_vec_t::const_iterator p=ptns.begin(); + p != ptns.end(); + ++p ) + { + const bytevec_t &vec = p->bytes; + uchar *start = memory + start_ea; + asize_t nbytes = qmin(sizeof(memory)-start_ea, end_ea-start_ea); + uchar *f = (uchar *)(backward + ? memmemr(start, nbytes, vec.begin(), vec.size(), sense_case) + : memmem(start, nbytes, vec.begin(), vec.size(), sense_case)); + if ( f == NULL ) + continue; + ea_t idx = f - memory; + if ( idx >= end_ea ) + continue; + found_eas->push_back(idx); + } + return found_eas->empty() ? DRC_FAILED : DRC_OK; +} + +//-------------------------------------------------------------------------- +static bool check(qstring *found1_s, const eavec_t &found1, ea_t found2) +{ + bool ok = found1.empty() && found2 == BADADDR; + for ( int k=0; k < found1.size(); ++k ) + { + if ( found1[k] == found2 ) + ok = true; + if ( k > 0 ) + found1_s->append(','); + found1_s->cat_sprnt("%a", found1[k]); + } + if ( found1_s->empty() ) + found1_s->sprnt("%a", BADADDR); + return ok; +} + +//-------------------------------------------------------------------------- +int main(int argc, char *argv[]) +{ + bool sense_case = false; + int max_ptns = 3; + for ( int i=1; i < argc; ++i ) + { + char argch = argv[i][0]; + if ( argch == 'C' ) + { + sense_case = true; + } + else if ( '0' < argch && argch <= '9' ) + { + max_ptns = argch - '0'; + } + } + msg("Test bin_search with %d pattern[s] and %s\n", + max_ptns, + sense_case ? "case sensitive" : "case ignored"); + + for ( int i=0; i < sizeof(memory); i++ ) + memory[i] = i;//rand(); + + for ( int i=0; i < 1000000; i++ ) + { + // prepare a pattern for searching + compiled_binpat_vec_t ptns; + int ptns_cnt = max_ptns == 1 ? 1 : (rand() % max_ptns) + 1; + ptns.resize(ptns_cnt); + qstring out; + for ( int c=0; c < ptns.size(); c++ ) + { + size_t off = rand() % sizeof(memory); + size_t len = (rand() % sizeof(memory)/20) + 1; + if ( (rand() % 50) == 0 ) + len += 8; + compiled_binpat_t &pat = ptns[c]; + pat.bytes.resize(len, 0xFF); + size_t copyable = qmin(sizeof(memory)-off, len); + memcpy(pat.bytes.begin(), &memory[off], copyable); + if ( c > 0 ) + out.append(","); + out.cat_sprnt("%X:%X", int(off), int(len)); + // if some rare cases make the pattern possibly insearchable + if ( (rand() % 50) == 0 ) + { + pat.bytes[0] = 0xAA; + out.append("-"); + } + } + ea_t start_ea = rand() % sizeof(memory); + ea_t end_ea = start_ea + (rand() % sizeof(memory)); + if ( end_ea > sizeof(memory) ) + end_ea = sizeof(memory); // no need to test out of memory + int flags = sense_case ? BIN_SEARCH_CASE : BIN_SEARCH_NOCASE; + + eavec_t found1; + simple_binary_search(&found1, start_ea, end_ea, ptns, flags|BIN_SEARCH_FORWARD, NULL); + + ea_t found2 = BADADDR; + binary_search(&found2, start_ea, end_ea, ptns, flags|BIN_SEARCH_FORWARD, NULL); + + qstring found1_s; + bool ok = check(&found1_s, found1, found2); + msg("%3d find (%s) in (%a..%a) => %s %a\n", i, out.c_str(), start_ea, end_ea, found1_s.c_str(), found2); + if ( !ok ) + { + msg("FAILED!\n"); + return 1; + } + + found1.clear(); + simple_binary_search(&found1, start_ea, end_ea, ptns, flags|BIN_SEARCH_BACKWARD, NULL); + + found2 = BADADDR; + binary_search(&found2, start_ea, end_ea, ptns, flags|BIN_SEARCH_BACKWARD, NULL); + + found1_s.qclear(); + ok = check(&found1_s, found1, found2); + msg("%3d findr(%s) in (%a..%a) => %s %a\n", i, out.c_str(), start_ea, end_ea, found1_s.c_str(), found2); + if ( !ok ) + { + msg("FAILED!\n"); + return 1; + } + } + msg("OK\n"); + return 0; +} +#endif // TEST diff --git a/idasdk76/dbg/bochs/bochsext.h b/idasdk76/dbg/bochs/bochsext.h new file mode 100644 index 0000000..32d6af0 --- /dev/null +++ b/idasdk76/dbg/bochs/bochsext.h @@ -0,0 +1,34 @@ +/* + * Interactive disassembler (IDA). + * ALL RIGHTS RESERVED. + * Copyright (c) 1990-2021 Hex-Rays + * + * + * This file defines the Bochs Debugger module extension functions. + * Use debugger_t->get_debmod_extensions() to retrieve this structure. + * + */ + +#ifndef __BOCHSEXT__ +#define __BOCHSEXT__ + +#pragma pack(push, 1) + +#define BOCHSEXT_VER 1 + +struct bochsext_t +{ + // the structure version + uint32 version; + + // Sends an arbitrary command to Bochs internal debugger + // cmd - command to send + // out - pointer to qstring that will hold the output of the command + // Returns: true if ok; false if failed to send command to bochs or receive + // a reply + bool (idaapi *send_command)(const char *cmd, qstring *out); +}; + +#pragma pack(pop) + +#endif diff --git a/idasdk76/dbg/bochs/ctrl/bochsys.h b/idasdk76/dbg/bochs/ctrl/bochsys.h new file mode 100644 index 0000000..ef37156 --- /dev/null +++ b/idasdk76/dbg/bochs/ctrl/bochsys.h @@ -0,0 +1,62 @@ +/* + * Interactive disassembler (IDA). + * ALL RIGHTS RESERVED. + * Copyright (c) 1990-2021 Hex-Rays + * + * + * This file defines the functions prototypes that are exported by bochsys.dll + * + * + */ + +#ifndef __BOCHSYS_DLL__ +#define __BOCHSYS_DLL__ + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define BX_CALLCONV WINAPI + +typedef wchar_t wchar16_t; +//CASSERT(sizeof(wchar16_t) == 2); + +//-------------------------------------------------------------------------- +// These functions are similar to MS Windows functions. Please refer +// to the SDK documentation for more information on how to use them. +extern FARPROC WINAPI BxGetProcAddress(HMODULE hMod, LPCSTR ProcName); +extern HMODULE WINAPI BxGetModuleHandleA(LPCSTR ModuleFileName); +extern DWORD WINAPI BxGetModuleFileNameA(HINSTANCE hModule, LPCSTR lpFilename, DWORD nSize); +extern DWORD WINAPI BxGetModuleFileNameW(HINSTANCE hModule, LPWSTR lpFilename, DWORD nSize); +extern HMODULE WINAPI BxLoadLibraryA(LPCTSTR lpFileName); +extern LPVOID WINAPI BxVirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); +extern BOOL WINAPI BxVirtualFree(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); +extern DWORD WINAPI BxExitProcess(DWORD); +extern DWORD WINAPI BxGetTickCount(VOID); +extern BOOL WINAPI BxVirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect); +extern DWORD WINAPI BxWin32SetLastError(DWORD ErrorCode); +extern DWORD WINAPI BxWin32GetLastError(VOID); +extern LPCSTR WINAPI BxWin32GetCommandLineA(VOID); +extern LPWSTR WINAPI BxWin32GetCommandLineW(VOID); +extern LPCSTR WINAPI BxWin32GetEnvironmentStringsA(VOID); +extern LPWSTR WINAPI BxWin32GetEnvironmentStringsW(VOID); +extern LPVOID WINAPI BxWin32TlsGetValue(DWORD dwTlsIndex); +extern BOOL WINAPI BxWin32TlsSetValue(DWORD dwTlsIndex,LPVOID lpTlsValue); +extern BOOL WINAPI BxWin32TlsFree(DWORD dwTlsIndex); +extern DWORD WINAPI BxWin32TlsAlloc(VOID); +extern DWORD WINAPI BxWin32FlsAlloc(VOID); +extern char * WINAPI BxStrCpyA(char *Dst, char *Src); +extern wchar16_t * WINAPI BxStrCpyW(wchar16_t *Dst, wchar16_t *Src); +extern char * WINAPI BxStrCatA(char *Dst, char *Src); +extern wchar16_t * WINAPI BxStrCatW(wchar16_t *Dst, wchar16_t *Src); + +//-------------------------------------------------------------------------- +// Installs an exception handler. Only one exception handler +// can be installed at one time. You need to uninstall one +// before reinstalling another. +// These two functions will return non-zero on success. +typedef DWORD (*PEXCEPTION_HANDLER)(PEXCEPTION_RECORD, struct _EXCEPTION_REGISTRATION_RECORD *, PCONTEXT,struct _EXCEPTION_REGISTRATION_RECORD **); + +extern DWORD WINAPI BxInstallSEH(PEXCEPTION_HANDLER Handler); +extern DWORD WINAPI BxUninstallSEH(); + +#endif diff --git a/idasdk75/dbg/bochs/ctrl/startup.idc b/idasdk76/dbg/bochs/ctrl/startup.idc similarity index 100% rename from idasdk75/dbg/bochs/ctrl/startup.idc rename to idasdk76/dbg/bochs/ctrl/startup.idc diff --git a/idasdk75/dbg/bochs/sdk/api_user32.idc b/idasdk76/dbg/bochs/sdk/api_user32.idc similarity index 100% rename from idasdk75/dbg/bochs/sdk/api_user32.idc rename to idasdk76/dbg/bochs/sdk/api_user32.idc diff --git a/idasdk75/dbg/bochs/sdk/bxtest.c b/idasdk76/dbg/bochs/sdk/bxtest.c similarity index 100% rename from idasdk75/dbg/bochs/sdk/bxtest.c rename to idasdk76/dbg/bochs/sdk/bxtest.c diff --git a/idasdk75/dbg/bochs/sdk/bxtest.def b/idasdk76/dbg/bochs/sdk/bxtest.def similarity index 100% rename from idasdk75/dbg/bochs/sdk/bxtest.def rename to idasdk76/dbg/bochs/sdk/bxtest.def diff --git a/idasdk75/dbg/bochs/sdk/bxtest.dll b/idasdk76/dbg/bochs/sdk/bxtest.dll similarity index 100% rename from idasdk75/dbg/bochs/sdk/bxtest.dll rename to idasdk76/dbg/bochs/sdk/bxtest.dll diff --git a/idasdk75/dbg/bochs/sdk/compile.bat b/idasdk76/dbg/bochs/sdk/compile.bat similarity index 100% rename from idasdk75/dbg/bochs/sdk/compile.bat rename to idasdk76/dbg/bochs/sdk/compile.bat diff --git a/idasdk75/dbg/bochs/sdk/readme.txt b/idasdk76/dbg/bochs/sdk/readme.txt similarity index 100% rename from idasdk75/dbg/bochs/sdk/readme.txt rename to idasdk76/dbg/bochs/sdk/readme.txt diff --git a/idasdk75/dbg/bochs/sdk/test.asm b/idasdk76/dbg/bochs/sdk/test.asm similarity index 100% rename from idasdk75/dbg/bochs/sdk/test.asm rename to idasdk76/dbg/bochs/sdk/test.asm diff --git a/idasdk75/dbg/bochs/sdk/test.pe b/idasdk76/dbg/bochs/sdk/test.pe similarity index 100% rename from idasdk75/dbg/bochs/sdk/test.pe rename to idasdk76/dbg/bochs/sdk/test.pe diff --git a/idasdk76/dbg/common_local_impl.cpp b/idasdk76/dbg/common_local_impl.cpp new file mode 100644 index 0000000..6709bec --- /dev/null +++ b/idasdk76/dbg/common_local_impl.cpp @@ -0,0 +1,857 @@ +// +// This file is included from other files, do not directly compile it. +// It contains the debugger_t structure definition and a few other helper functions +// + +#include <loader.hpp> +#include <segregs.hpp> +#include <network.hpp> + +bool plugin_inited; +bool debugger_inited; + +#define IS_GDB_DEBUGGER (DEBUGGER_ID == DEBUGGER_ID_GDB_USER || DEBUGGER_ID == DEBUGGER_ID_ARM_IPHONE_USER || DEBUGGER_ID == DEBUGGER_ID_XNU_USER) + +#if TARGET_PROCESSOR == PLFM_386 + #define REGISTERS x86_registers + #define REGISTERS_SIZE qnumber(x86_registers) + #define REGISTER_CLASSES x86_register_classes + #define REGISTER_CLASSES_DEFAULT X86_RC_GENERAL + #define READ_REGISTERS x86_read_registers + #define WRITE_REGISTER x86_write_register + #if !IS_GDB_DEBUGGER + #define is_valid_bpt is_x86_valid_bpt + #endif + #define BPT_CODE X86_BPT_CODE + #define BPT_CODE_SIZE X86_BPT_SIZE +#elif TARGET_PROCESSOR == PLFM_ARM + #define REGISTERS arm_registers + #define REGISTERS_SIZE qnumber(arm_registers) + #define REGISTER_CLASSES arm_register_classes + #define REGISTER_CLASSES_DEFAULT ARM_RC_GENERAL + #define READ_REGISTERS s_read_registers + #define WRITE_REGISTER s_write_register + #if !IS_GDB_DEBUGGER + #define is_valid_bpt is_arm_valid_bpt + #else + #define is_valid_bpt gdb_valid_bpt + #endif + #define BPT_CODE ARM_BPT_CODE + #define BPT_CODE_SIZE ARM_BPT_SIZE +#elif TARGET_PROCESSOR == PLFM_DALVIK + #define BPT_CODE { 0 } + #define BPT_CODE_SIZE 0 + #define READ_REGISTERS s_read_registers + #define WRITE_REGISTER s_write_register + #define is_valid_bpt is_dalvik_valid_bpt +#elif IS_GDB_DEBUGGER + #define REGISTERS NULL + #define REGISTERS_SIZE 0 + #define REGISTER_CLASSES NULL + #define REGISTER_CLASSES_DEFAULT 0 + #define READ_REGISTERS simple_read_registers + #define WRITE_REGISTER simple_write_register + #define is_valid_bpt gdb_valid_bpt + #define BPT_CODE { 0 } + #define BPT_CODE_SIZE 0 +#else + #error This processor is not supported yet +#endif + +static const uchar bpt_code[] = BPT_CODE; + +//-------------------------------------------------------------------------- +int idaapi is_ok_bpt(bpttype_t type, ea_t ea, int len) +{ + int ret = is_valid_bpt(type, ea, len); + if ( ret != BPT_OK ) + return ret; + else + return g_dbgmod.dbg_is_ok_bpt(type, ea, len); +} + +//-------------------------------------------------------------------------- +// For ARM, we have to set the low bit of the address to 1 for thumb mode +#if DEBUGGER_ID == DEBUGGER_ID_ARM_LINUX_USER +static drc_t idaapi arm_update_bpts( + int *nbpts, + update_bpt_info_t *bpts, + int nadd, + int ndel, + qstring *errbuf) +{ + // This function is called from debthread, but to use get_sreg() we must + // switch to the mainthread + struct ida_local arm_bptea_fixer_t : public exec_request_t + { + update_bpt_info_t *bpts; + update_bpt_info_t *e; + qvector<ea_t *> thumb_mode; + virtual int idaapi execute(void) override + { + for ( update_bpt_info_t *b=bpts; b != e; b++ ) + { + if ( b->type == BPT_SOFT && get_sreg(b->ea, ARM_T) == 1 ) + { + b->ea++; // odd address means that thumb bpt must be set + thumb_mode.push_back(&b->ea); + } + } + return 0; + } + arm_bptea_fixer_t(update_bpt_info_t *p1, update_bpt_info_t *p2) + : bpts(p1), e(p2) {} + }; + arm_bptea_fixer_t abf(bpts, bpts+nadd); + execute_sync(abf, MFF_READ); + + drc_t drc = s_update_bpts(nbpts, bpts, nadd, ndel, errbuf); + + // reset the odd bit because the addresses are required by the caller + for ( int i=0; i < abf.thumb_mode.size(); i++ ) + (*abf.thumb_mode[i])--; + + return drc; +} +#define s_update_bpts arm_update_bpts +#endif + +//-------------------------------------------------------------------------- +static drc_t idaapi update_bpts( + int *nbpts, + update_bpt_info_t *bpts, + int nadd, + int ndel, + qstring *errbuf) +{ + bool valid_bpt_exists = false; + update_bpt_info_t *e = bpts + nadd; + for ( update_bpt_info_t *b=bpts; b != e; b++ ) + { + if ( b->code == BPT_SKIP ) + continue; + + b->code = is_valid_bpt(b->type, b->ea, b->size); + if ( b->code == BPT_OK ) + valid_bpt_exists = true; + } + + if ( !valid_bpt_exists && ndel == 0 ) + { + if ( nbpts != NULL ) + *nbpts = 0; + return DRC_OK; // none of bpts is writable + } + + drc_t drc = s_update_bpts(nbpts, bpts, nadd, ndel, errbuf); + return drc; +} + +//-------------------------------------------------------------------------- +#ifndef REMOTE_DEBUGGER +// another copy of this function (for remote debugging) is defined in dbg_rpc_handler.cpp +int send_ioctl( + void *, + int fn, + const void *buf, + size_t size, + void **poutbuf, + ssize_t *poutsize) +{ + return g_dbgmod.handle_ioctl(fn, buf, size, poutbuf, poutsize); +} +#endif + +//-------------------------------------------------------------------------- +THREAD_SAFE int debmod_t::send_debug_names_to_ida( + ea_t *addrs, + const char *const *names, + int qty) +{ + return ::send_debug_names_to_ida(addrs, names, qty); +} + +//--------------------------------------------------------------------------- +THREAD_SAFE int send_debug_names_to_ida( + ea_t *addrs, + const char *const *names, + int qty) +{ + struct debug_name_handler_t : public exec_request_t + { + ea_t *addrs; + const char *const *names; + int qty; + debug_name_handler_t(ea_t *_addrs, const char *const *_names, int _qty) + : addrs(_addrs), names(_names), qty(_qty) {} + int idaapi execute(void) override + { + set_arm_thumb_modes(addrs, qty); + return set_debug_names(addrs, names, qty); + } + }; + debug_name_handler_t dnh(addrs, names, qty); + return execute_sync(dnh, MFF_WRITE); +} + +//-------------------------------------------------------------------------- +THREAD_SAFE int debmod_t::send_debug_event_to_ida( + const debug_event_t *ev, + int rqflags) +{ + return ::send_debug_event_to_ida(ev, rqflags); +} + +//--------------------------------------------------------------------------- +THREAD_SAFE int send_debug_event_to_ida( + const debug_event_t *ev, + int rqflags) +{ + return handle_debug_event(ev, rqflags); +} + +//-------------------------------------------------------------------------- +THREAD_SAFE int import_dll(const import_request_t &req) +{ + struct dll_importer_t : public exec_request_t + { + const import_request_t &req; + dll_importer_t(const import_request_t &_req) : req(_req) {} + int idaapi execute(void) override + { + return g_dbgmod.import_dll(req) ? 0 : 1; + } + }; + dll_importer_t di(req); + return execute_sync(di, MFF_WRITE); +} + +//-------------------------------------------------------------------------- +#if TARGET_PROCESSOR != PLFM_ARM +void set_arm_thumb_modes(ea_t * /*addrs*/, int /*qty*/) +{ +} +#endif + +//-------------------------------------------------------------------------- +// installs or uninstalls debugger specific idc functions +bool add_idc_funcs(const ext_idcfunc_t efuncs[], size_t nfuncs, bool reg) +{ + if ( reg ) + { + for ( int i=0; i < nfuncs; i++ ) + if ( !add_idc_func(efuncs[i]) ) + return false; + } + else + { + for ( int i=0; i < nfuncs; i++ ) + if ( !del_idc_func(efuncs[i].name) ) + return false; + } + return true; +} + +//-------------------------------------------------------------------------- +static drc_t init_debugger( + const char *hostname, + int port_num, + const char *password, + qstring *errbuf) +{ + g_dbgmod.dbg_set_debugging((debug & IDA_DEBUG_DEBUGGER) != 0); + + if ( !s_open_remote(hostname, port_num, password, errbuf) ) + return DRC_FAILED; + + uint32_t flags2 = 0; + drc_t drc = s_init(&flags2, errbuf); + if ( drc != DRC_OK ) + { + s_close_remote(); + return drc; + } + + debugger.flags2 |= flags2; +#if defined(REMOTE_DEBUGGER) && !defined(NO_OPEN_FILE) + setflag(debugger.flags2, DBG_HAS_OPEN_FILE, true); +#endif +#ifdef HAVE_UPDATE_CALL_STACK + setflag(debugger.flags2, DBG_HAS_UPDATE_CALL_STACK, true); +#endif +#ifdef HAVE_APPCALL + setflag(debugger.flags2, DBG_HAS_APPCALL, true); +#endif +#ifdef HAVE_MAP_ADDRESS + setflag(debugger.flags2, DBG_HAS_MAP_ADDRESS, true); +#endif + debugger_inited = true; + processor_specific_init(); + register_idc_funcs(true); + init_dbg_idcfuncs(true); +#if DEBUGGER_ID == DEBUGGER_ID_X86_IA32_WIN32_USER || DEBUGGER_ID == DEBUGGER_ID_X86_IA32_BOCHS + install_x86seh_menu(); +#endif + return DRC_OK; +} + +//-------------------------------------------------------------------------- +static drc_t term_debugger(void) +{ + if ( debugger_inited ) + { + debugger_inited = false; +#if DEBUGGER_ID == DEBUGGER_ID_X86_IA32_WIN32_USER || DEBUGGER_ID == DEBUGGER_ID_X86_IA32_BOCHS + remove_x86seh_menu(); +#endif + init_dbg_idcfuncs(false); + register_idc_funcs(false); + processor_specific_term(); + g_dbgmod.dbg_term(); + return s_close_remote(); + } + return DRC_FAILED; +} + +//-------------------------------------------------------------------------- +static ssize_t idaapi idd_notify(void *, int msgid, va_list va) +{ + int retcode = DRC_NONE; + qstring *errbuf; + + switch ( msgid ) + { + case debugger_t::ev_init_debugger: + { + const char *hostname = va_arg(va, const char *); + int portnum = va_arg(va, int); + const char *password = va_arg(va, const char *); + errbuf = va_arg(va, qstring *); + QASSERT(1522, errbuf != NULL); + retcode = init_debugger(hostname, portnum, password, errbuf); + } + break; + + case debugger_t::ev_term_debugger: + retcode = term_debugger(); + break; + + case debugger_t::ev_get_processes: + { + procinfo_vec_t *procs = va_arg(va, procinfo_vec_t *); + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_get_processes(procs, errbuf); + } + break; + + case debugger_t::ev_start_process: + { + const char *path = va_arg(va, const char *); + const char *args = va_arg(va, const char *); + const char *startdir = va_arg(va, const char *); + uint32 dbg_proc_flags = va_arg(va, uint32); + const char *input_path = va_arg(va, const char *); + uint32 input_file_crc32 = va_arg(va, uint32); + errbuf = va_arg(va, qstring *); + retcode = s_start_process(path, + args, + startdir, + dbg_proc_flags, + input_path, + input_file_crc32, + errbuf); + } + break; + + case debugger_t::ev_attach_process: + { + pid_t pid = va_argi(va, pid_t); + int event_id = va_arg(va, int); + uint32 dbg_proc_flags = va_arg(va, uint32); + errbuf = va_arg(va, qstring *); + retcode = s_attach_process(pid, event_id, dbg_proc_flags, errbuf); + } + break; + + case debugger_t::ev_detach_process: + retcode = g_dbgmod.dbg_detach_process(); + break; + + case debugger_t::ev_get_debapp_attrs: + { + debapp_attrs_t *out_pattrs = va_arg(va, debapp_attrs_t *); + g_dbgmod.dbg_get_debapp_attrs(out_pattrs); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_rebase_if_required_to: + { + ea_t new_base = va_arg(va, ea_t); + rebase_if_required_to(new_base); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_request_pause: + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_prepare_to_pause_process(errbuf); + break; + + case debugger_t::ev_exit_process: + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_exit_process(errbuf); + break; + + case debugger_t::ev_get_debug_event: + { + gdecode_t *code = va_arg(va, gdecode_t *); + debug_event_t *event = va_arg(va, debug_event_t *); + int timeout_ms = va_arg(va, int); + *code = g_dbgmod.dbg_get_debug_event(event, timeout_ms); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_resume: + { + debug_event_t *event = va_arg(va, debug_event_t *); + retcode = g_dbgmod.dbg_continue_after_event(event); + } + break; + + case debugger_t::ev_set_exception_info: + { + exception_info_t *info = va_arg(va, exception_info_t *); + int qty = va_arg(va, int); + g_dbgmod.dbg_set_exception_info(info, qty); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_suspended: + { + bool dlls_added = va_argi(va, bool); + thread_name_vec_t *thr_names = va_arg(va, thread_name_vec_t *); + s_stopped_at_debug_event(thr_names, dlls_added); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_thread_suspend: + { + thid_t tid = va_argi(va, thid_t); + retcode = g_dbgmod.dbg_thread_suspend(tid); + } + break; + + case debugger_t::ev_thread_continue: + { + thid_t tid = va_argi(va, thid_t); + retcode = g_dbgmod.dbg_thread_continue(tid); + } + break; + + case debugger_t::ev_set_resume_mode: + { + thid_t tid = va_argi(va, thid_t); + resume_mode_t resmod = va_argi(va, resume_mode_t); + retcode = g_dbgmod.dbg_set_resume_mode(tid, resmod); + } + break; + + case debugger_t::ev_read_registers: + { + thid_t tid = va_argi(va, thid_t); + int clsmask = va_arg(va, int); + regval_t *values = va_arg(va, regval_t *); + errbuf = va_arg(va, qstring *); + retcode = READ_REGISTERS(tid, clsmask, values, errbuf); + } + break; + + case debugger_t::ev_write_register: + { + thid_t tid = va_argi(va, thid_t); + int regidx = va_arg(va, int); + const regval_t *value = va_arg(va, const regval_t *); + errbuf = va_arg(va, qstring *); + retcode = WRITE_REGISTER(tid, regidx, value, errbuf); + } + break; + + case debugger_t::ev_thread_get_sreg_base: + { + ea_t *answer = va_arg(va, ea_t *); + thid_t tid = va_argi(va, thid_t); + int sreg_value = va_arg(va, int); + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_thread_get_sreg_base(answer, tid, sreg_value, errbuf); + } + break; + + case debugger_t::ev_get_memory_info: + { + meminfo_vec_t *ranges = va_arg(va, meminfo_vec_t *); + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_get_memory_info(*ranges, errbuf); + } + break; + + case debugger_t::ev_read_memory: + { + size_t *nbytes = va_arg(va, size_t *); + ea_t ea = va_arg(va, ea_t); + void *buffer = va_arg(va, void *); + size_t size = va_arg(va, size_t); + errbuf = va_arg(va, qstring *); + ssize_t code = g_dbgmod.dbg_read_memory(ea, buffer, size, errbuf); + *nbytes = code >= 0 ? code : 0; + retcode = code >= 0 ? DRC_OK : DRC_NOPROC; + } + break; + + case debugger_t::ev_write_memory: + { + size_t *nbytes = va_arg(va, size_t *); + ea_t ea = va_arg(va, ea_t); + const void *buffer = va_arg(va, void *); + size_t size = va_arg(va, size_t); + errbuf = va_arg(va, qstring *); + ssize_t code = g_dbgmod.dbg_write_memory(ea, buffer, size, errbuf); + *nbytes = code >= 0 ? code : 0; + retcode = code >= 0 ? DRC_OK : DRC_NOPROC; + } + break; + + case debugger_t::ev_check_bpt: + { + int *bptvc = va_arg(va, int *); + bpttype_t type = va_argi(va, bpttype_t); + ea_t ea = va_arg(va, ea_t); + int len = va_arg(va, int); + *bptvc = is_ok_bpt(type, ea, len); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_update_bpts: + { + int *nbpts = va_arg(va, int *); + update_bpt_info_t *bpts = va_arg(va, update_bpt_info_t *); + int nadd = va_arg(va, int); + int ndel = va_arg(va, int); + errbuf = va_arg(va, qstring *); + retcode = update_bpts(nbpts, bpts, nadd, ndel, errbuf); + } + break; + + case debugger_t::ev_update_lowcnds: + { + int *nupdated = va_arg(va, int *); + const lowcnd_t *lowcnds = va_arg(va, const lowcnd_t *); + int nlowcnds = va_arg(va, int); + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_update_lowcnds(nupdated, lowcnds, nlowcnds, errbuf); + } + break; + + case debugger_t::ev_open_file: + { + const char *file = va_arg(va, const char *); + uint64 *fsize = va_arg(va, uint64 *); + bool readonly = va_argi(va, bool); + retcode = g_dbgmod.dbg_open_file(file, fsize, readonly); + } + break; + + case debugger_t::ev_close_file: + { + int fn = va_arg(va, int); + g_dbgmod.dbg_close_file(fn); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_read_file: + { + int fn = va_arg(va, int); + qoff64_t off = va_arg(va, qoff64_t); + void *buf = va_arg(va, void *); + size_t size = va_arg(va, size_t); + retcode = g_dbgmod.dbg_read_file(fn, off, buf, size); + } + break; + + case debugger_t::ev_write_file: + { + int fn = va_arg(va, int); + qoff64_t off = va_arg(va, qoff64_t); + const void *buf = va_arg(va, const void *); + size_t size = va_arg(va, size_t); + retcode = g_dbgmod.dbg_write_file(fn, off, buf, size); + } + break; + + case debugger_t::ev_map_address: + { + ea_t *mapped = va_arg(va, ea_t *); + ea_t ea = va_arg(va, ea_t); + const regval_t *regs = va_arg(va, const regval_t *); + int regnum = va_arg(va, int); + *mapped = g_dbgmod.map_address(ea, regs, regnum); + return DRC_OK; + } + break; + + #ifdef GET_DEBMOD_EXTS + case debugger_t::ev_get_debmod_extensions: + { + const void **ext = va_arg(va, const void **); + *ext = GET_DEBMOD_EXTS(); + retcode = DRC_OK; + } + break; + #endif + + #ifdef HAVE_UPDATE_CALL_STACK + case debugger_t::ev_update_call_stack: + { + thid_t tid = va_argi(va, thid_t); + call_stack_t *trace = va_arg(va, call_stack_t *); + retcode = g_dbgmod.dbg_update_call_stack(tid, trace); + } + break; + #endif + + #ifdef HAVE_APPCALL + case debugger_t::ev_appcall: + { + ea_t *blob_ea = va_arg(va, ea_t *); + ea_t func_ea = va_arg(va, ea_t); + thid_t tid = va_arg(va, thid_t); + const func_type_data_t *fti = va_arg(va, const func_type_data_t *); + int nargs = va_arg(va, int); + const regobjs_t *regargs = va_arg(va, const regobjs_t *); + relobj_t *stkargs = va_arg(va, relobj_t *); + regobjs_t *retregs = va_arg(va, regobjs_t *); + errbuf = va_arg(va, qstring *); + debug_event_t *event = va_arg(va, debug_event_t *); + int opts = va_arg(va, int); + qnotused(nargs); + *blob_ea = g_dbgmod.dbg_appcall(func_ea, tid, fti->stkargs, regargs, stkargs, retregs, errbuf, event, opts); + retcode = DRC_OK; + } + break; + + case debugger_t::ev_cleanup_appcall: + { + thid_t tid = va_argi(va, thid_t); + retcode = g_dbgmod.dbg_cleanup_appcall(tid); + } + break; + #endif + + case debugger_t::ev_eval_lowcnd: + { + thid_t tid = va_argi(va, thid_t); + ea_t ea = va_arg(va, ea_t); + errbuf = va_arg(va, qstring *); + retcode = g_dbgmod.dbg_eval_lowcnd(tid, ea, errbuf); + } + break; + + case debugger_t::ev_send_ioctl: + { + int fn = va_arg(va, int); + const void *buf = va_arg(va, const void *); + size_t size = va_arg(va, size_t); + void **poutbuf = va_arg(va, void **); + ssize_t *poutsize = va_arg(va, ssize_t *); + retcode = g_dbgmod.handle_ioctl(fn, buf, size, poutbuf, poutsize); + } + break; + + case debugger_t::ev_dbg_enable_trace: + { + thid_t tid = va_arg(va, thid_t); + bool enable = va_argi(va, bool); + int trace_flags = va_arg(va, int); + retcode = g_dbgmod.dbg_enable_trace(tid, enable, trace_flags) ? DRC_OK : DRC_NONE; + } + break; + + case debugger_t::ev_is_tracing_enabled: + { + thid_t tid = va_arg(va, thid_t); + int tracebit = va_arg(va, int); + retcode = g_dbgmod.dbg_is_tracing_enabled(tid, tracebit) ? DRC_OK : DRC_NONE; + } + break; + + case debugger_t::ev_rexec: + { + const char *cmdline = va_arg(va, const char *); + retcode = g_dbgmod.dbg_rexec(cmdline); + } + break; + + #ifdef HAVE_GET_SRCINFO_PATH + case debugger_t::ev_get_srcinfo_path: + { + qstring *path = va_arg(va, qstring *); + ea_t base = va_arg(va, ea_t); + bool ok = g_dbgmod.dbg_get_srcinfo_path(path, base); + retcode = ok ? DRC_OK : DRC_NONE; + } + break; + #endif + + case debugger_t::ev_bin_search: + { + ea_t *ea = va_arg(va, ea_t *); + ea_t start_ea = va_arg(va, ea_t); + ea_t end_ea = va_arg(va, ea_t); + const compiled_binpat_vec_t *ptns = va_arg(va, const compiled_binpat_vec_t *); + int srch_flags = va_arg(va, int); + errbuf = va_arg(va, qstring *); + if ( ptns != NULL ) + retcode = g_dbgmod.dbg_bin_search(ea, start_ea, end_ea, *ptns, srch_flags, errbuf); + } + break; + } + + return retcode; +} + +//-------------------------------------------------------------------------- +// Initialize debugger plugin +static plugmod_t *idaapi init(void) +{ + // copy of the definitions from loader.hpp + // we will delete them after improving the debuggers to use PLUGIN_MULTI. +#define PLUGIN_SKIP nullptr +#define PLUGIN_KEEP ((plugmod_t *)2) + + if ( init_plugin() ) + { + update_idd_registers(); + dbg = &debugger; + plugin_inited = true; + return PLUGIN_KEEP; + } + return PLUGIN_SKIP; +} + +//-------------------------------------------------------------------------- +// Terminate debugger plugin +static void idaapi term(void) +{ + if ( plugin_inited ) + { + term_plugin(); + plugin_inited = false; + } + // we're being unloaded, clear the 'dbg' pointer if it's ours + if ( dbg == &debugger ) + dbg = NULL; +} + +//-------------------------------------------------------------------------- +// The plugin method - usually is not used for debugger plugins +static bool idaapi run(size_t arg) +{ +#ifdef HAVE_PLUGIN_RUN + plugin_run(int(arg)); +#else + qnotused(arg); +#endif + return true; +} + +//-------------------------------------------------------------------------- +// +// DEBUGGER DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- + +#ifdef SET_DBG_OPTIONS +# define S_SET_DBG_OPTIONS s_set_dbg_options +#else +# define S_SET_DBG_OPTIONS NULL +# define SET_DBG_OPTIONS NULL +#endif + +#ifndef S_FILETYPE +# define S_FILETYPE 0 +#endif + +// DBG_HAS_SET_RESUME_MODE must be set before init_debugger. +// typically arm has no single step mechanism, arm64 macOS11 is an exception. +#if TARGET_PROCESSOR == PLFM_ARM && DEBUGGER_ID != DEBUGGER_ID_ARM_MACOS_USER +# define S_DBG_HAS_SET_RESUME_MODE 0 +#else +# define S_DBG_HAS_SET_RESUME_MODE DBG_HAS_SET_RESUME_MODE +#endif + +#ifndef DEBUGGER_RESMOD +# define DEBUGGER_RESMOD 0 +#endif + +debugger_t debugger = +{ + IDD_INTERFACE_VERSION, + DEBUGGER_NAME, + DEBUGGER_ID, + PROCESSOR_NAME, + DEBUGGER_FLAGS, // flags + DBG_HAS_ATTACH_PROCESS +| DBG_HAS_REQUEST_PAUSE +| DBG_HAS_SET_EXCEPTION_INFO +| DBG_HAS_THREAD_SUSPEND +| DBG_HAS_THREAD_CONTINUE +| S_DBG_HAS_SET_RESUME_MODE +| DBG_HAS_THREAD_GET_SREG_BASE +| DBG_HAS_CHECK_BPT +| DBG_HAS_REXEC, // flags2 + + REGISTER_CLASSES, + REGISTER_CLASSES_DEFAULT, + REGISTERS, + REGISTERS_SIZE, + + MEMORY_PAGE_SIZE, + + bpt_code, + sizeof(bpt_code), + S_FILETYPE, + DEBUGGER_RESMOD, + + S_SET_DBG_OPTIONS, + idd_notify, +}; + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_HIDE|PLUGIN_DBG, // plugin flags + init, // initialize + + term, // terminate. this pointer may be NULL. + + run, // invoke plugin + + comment, // long comment about the plugin + // it could appear in the status line + // or as a hint + + comment, // multiline help about the plugin + + wanted_name, // the preferred short name of the plugin + "" // the preferred hotkey to run the plugin +}; diff --git a/idasdk75/dbg/common_stub_impl.cpp b/idasdk76/dbg/common_stub_impl.cpp similarity index 100% rename from idasdk75/dbg/common_stub_impl.cpp rename to idasdk76/dbg/common_stub_impl.cpp diff --git a/idasdk75/dbg/dbg_pe_hlp.cpp b/idasdk76/dbg/dbg_pe_hlp.cpp similarity index 100% rename from idasdk75/dbg/dbg_pe_hlp.cpp rename to idasdk76/dbg/dbg_pe_hlp.cpp diff --git a/idasdk76/dbg/dbg_rpc_client.cpp b/idasdk76/dbg/dbg_rpc_client.cpp new file mode 100644 index 0000000..d78790b --- /dev/null +++ b/idasdk76/dbg/dbg_rpc_client.cpp @@ -0,0 +1,246 @@ + +// This file is included in the debugger stub that runs on the computer with IDA + +#include <pro.h> +#include <name.hpp> +#include <diskio.hpp> + +#include "dbg_rpc_client.h" +#include "dbg_rpc_hlp.h" +#include "debmod.h" + +//-------------------------------------------------------------------------- +// check and send to the remote server the specified stub +// do it only if its crc does not match the specified crc +// this function runs on the local machine with ida interface +static uchar *sync_stub(const char *fname, uint32 crc, size_t *psize) +{ + bool complain = true; + uchar *retval = NULL; + char path[QMAXPATH]; + if ( getsysfile(path, sizeof(path), fname, NULL) != NULL ) + { + linput_t *li = open_linput(path, false); + if ( li != NULL ) + { + int64 size = qlsize(li); + if ( size > 0 ) + { + bytevec_t buf; + buf.resize(size); + if ( qlread(li, buf.begin(), size) == size ) + { + complain = false; + if ( calc_crc32(0, buf.begin(), size) != crc ) + { + *psize = size; + retval = buf.extract(); + } + else + { + msg("Kernel debugger stub is up to date...\n"); + *psize = 1; // signal ok + } + } + } + close_linput(li); + } + } + if ( complain ) + warning("AUTOHIDE NONE\nCould not find/read debugger stub %s", fname); + return retval; +} + +//-------------------------------------------------------------------------- +dbg_rpc_client_t::dbg_rpc_client_t(idarpc_stream_t *_irs) + : dbg_rpc_engine_t(/*is_client=*/ true), + client_irs(_irs) +{ + pending_event.clear_all(); + verbose = false; + recv_timeout = RECV_TIMEOUT_PERIOD; +} + +//------------------------------------------------------------------------- +void dbg_rpc_client_t::my_update_wait_dialog( + const char *message, + const rpc_packet_t *rp) +{ + if ( send_request_data.wait_dialog_displayed ) + { + if ( rp->code != send_request_data.code ) + replace_wait_box("%s", message); + } + else + { + show_wait_box("%s", message); + send_request_data.wait_dialog_displayed = true; + } + send_request_data.code = rp->code; +} + +//-------------------------------------------------------------------------- +// requests received from the server. +// here the client handles certain server -> client requests +bytevec_t dbg_rpc_client_t::on_send_request_interrupt(const rpc_packet_t *rp) +{ + memory_deserializer_t mmdsr(rp+1, rp->length); + bytevec_t req = prepare_rpc_packet(RPC_OK); + + switch ( rp->code ) + { + // send_debug_names_to_ida() is thread safe + case RPC_SET_DEBUG_NAMES: + { + my_update_wait_dialog("Downloading Symbols", rp); + int qty = mmdsr.unpack_dd(); + ea_t *addrs = OPERATOR_NEW(ea_t, qty); + char **names = OPERATOR_NEW(char *, qty); + qstring name; + ea_t old = 0; + for ( int i=0; i < qty; i++ ) + { + adiff_t o2 = mmdsr.unpack_ea64(); + if ( mmdsr.unpack_dd() ) + o2 = -o2; + old += o2; + addrs[i] = old; + int oldlen = mmdsr.unpack_dd(); + QASSERT(1203, oldlen >= 0 && oldlen <= name.length()); + // keep the prefix + name.resize(oldlen); + if ( !mmdsr.unpack_str(&name) ) + INTERR(1294); + names[i] = qstrdup(name.c_str()); + } + int result = send_debug_names_to_ida(addrs, names, qty); + verb(("set_debug_name(qty=%d) => %d\n", qty, result)); + req.pack_dd(result); + for ( int i=0; i < qty; i++ ) + qfree(names[i]); + delete [] addrs; + delete [] names; + } + break; + + // import_dll() is thread safe + case RPC_IMPORT_DLL: + { + my_update_wait_dialog("Importing DLLs", rp); + ea_t base = mmdsr.unpack_ea64(); + const char *path = mmdsr.unpack_str(); + int n = mmdsr.unpack_dd(); + const void *bytes = mmdsr.unpack_obj_inplace(n); + bytevec_t uuid(bytes, n); + int result = import_dll(import_request_t(base, path, uuid)); + verb(("import_dll(base=%a, path=%s) => %d\n", base, path, result)); + req.pack_dd(result); + } + break; + + // send_debug_event_to_ida() is thread safe + case RPC_HANDLE_DEBUG_EVENT: + { + debug_event_t ev; + extract_debug_event(&ev, mmdsr); + int rqflags = mmdsr.unpack_dd(); + int code = send_debug_event_to_ida(&ev, rqflags); + req.pack_dd(code); + } + break; + + // sync_stub() is thread safe + case RPC_SYNC_STUB: + { + const char *fname = mmdsr.unpack_str(); + uint32 crc = mmdsr.unpack_dd(); + + // security problem: the debugger server should not be able to + // read an arbitrary file on the local computer. therefore we completely + // ignore the file name and use a hardcoded name. + qnotused(fname); + fname = "ida_kdstub.dll"; + + size_t size = 0; + uchar *contents = sync_stub(fname, crc, &size); + req.pack_dd((uint32)size); + if ( contents != NULL ) + { + req.append(contents, size); + qfree(contents); + } + } + break; + + // msg/error/warning are thread safe + case RPC_ERROR: + case RPC_MSG: + case RPC_WARNING: + { + const char *str = mmdsr.unpack_str(); + if ( *str != '\0' ) + { + if ( rp->code == RPC_MSG ) + msg("%s", str); + else if ( rp->code == RPC_ERROR ) + error("%s", str); + else + warning("%s", str); + } + } + break; + + // no external functions are called + case RPC_EVENT: + { + extract_debug_event(&pending_event, mmdsr); + has_pending_event = true; + req = prepare_rpc_packet(RPC_EVOK); + verbev(("got event, storing it and sending RPC_EVOK\n")); + } + break; + + // i doubt that this code is used on the client side + // ioctl_handler is NULL + case RPC_IOCTL: + { + int code = handle_ioctl_packet(req, mmdsr.ptr, mmdsr.end); + if ( code != RPC_OK ) + return prepare_rpc_packet((uchar)code); + } + break; + + // report_idc_error() is thread safe + case RPC_REPORT_IDC_ERROR: + { + ea_t ea = mmdsr.unpack_ea64(); + error_t code = mmdsr.unpack_dd(); + const char *errprm; + ssize_t errval; + if ( mmdsr.unpack_db() ) + { + errprm = mmdsr.unpack_str(); + errval = (ssize_t)errprm; + } + else + { + errprm = NULL; + errval = mmdsr.unpack_ea64(); + } + report_idc_error(NULL, ea, code, errval, errprm); + } + break; + + default: + return prepare_rpc_packet(RPC_UNK); + } + return req; +} + +//------------------------------------------------------------------------- +void dbg_rpc_client_t::on_send_request_end(const rpc_packet_t *) +{ + if ( send_request_data.wait_dialog_displayed ) + hide_wait_box(); + send_request_data.reset(); +} diff --git a/idasdk75/dbg/dbg_rpc_client.h b/idasdk76/dbg/dbg_rpc_client.h similarity index 100% rename from idasdk75/dbg/dbg_rpc_client.h rename to idasdk76/dbg/dbg_rpc_client.h diff --git a/idasdk76/dbg/dbg_rpc_engine.cpp b/idasdk76/dbg/dbg_rpc_engine.cpp new file mode 100644 index 0000000..a6a1591 --- /dev/null +++ b/idasdk76/dbg/dbg_rpc_engine.cpp @@ -0,0 +1,166 @@ + +#include <network.hpp> + +#include "dbg_rpc_engine.h" + +//------------------------------------------------------------------------- +#ifdef TESTABLE_BUILD +static const rpc_packet_type_desc_t dbg_rpc_packet_t_descs[] = +{ + { RPC_OK, "RPC_OK", nullptr }, + { RPC_UNK, "RPC_UNK", nullptr }, + { RPC_MEM, "RPC_MEM", nullptr }, + + { RPC_OPEN, "RPC_OPEN", nullptr }, + { RPC_EVENT, "RPC_EVENT", nullptr }, + { RPC_EVOK, "RPC_EVOK", nullptr }, + { RPC_CANCELLED, "RPC_CANCELLED", nullptr }, + + { RPC_INIT, "RPC_INIT", nullptr }, + { RPC_TERM, "RPC_TERM", nullptr }, + { RPC_GET_PROCESSES, "RPC_GET_PROCESSES", nullptr }, + { RPC_START_PROCESS, "RPC_START_PROCESS", nullptr }, + { RPC_EXIT_PROCESS, "RPC_EXIT_PROCESS", nullptr }, + { RPC_ATTACH_PROCESS, "RPC_ATTACH_PROCESS", nullptr }, + { RPC_DETACH_PROCESS, "RPC_DETACH_PROCESS", nullptr }, + { RPC_GET_DEBUG_EVENT, "RPC_GET_DEBUG_EVENT", nullptr }, + { RPC_PREPARE_TO_PAUSE_PROCESS, "RPC_PREPARE_TO_PAUSE_PROCESS", nullptr }, + { RPC_STOPPED_AT_DEBUG_EVENT, "RPC_STOPPED_AT_DEBUG_EVENT", nullptr }, + { RPC_CONTINUE_AFTER_EVENT, "RPC_CONTINUE_AFTER_EVENT", nullptr }, + { RPC_TH_SUSPEND, "RPC_TH_SUSPEND", nullptr }, + { RPC_TH_CONTINUE, "RPC_TH_CONTINUE", nullptr }, + { RPC_SET_RESUME_MODE, "RPC_SET_RESUME_MODE", nullptr }, + { RPC_GET_MEMORY_INFO, "RPC_GET_MEMORY_INFO", nullptr }, + { RPC_READ_MEMORY, "RPC_READ_MEMORY", nullptr }, + { RPC_WRITE_MEMORY, "RPC_WRITE_MEMORY", nullptr }, + { RPC_UPDATE_BPTS, "RPC_UPDATE_BPTS", nullptr }, + { RPC_UPDATE_LOWCNDS, "RPC_UPDATE_LOWCNDS", nullptr }, + { RPC_EVAL_LOWCND, "RPC_EVAL_LOWCND", nullptr }, + { RPC_ISOK_BPT, "RPC_ISOK_BPT", nullptr }, + { RPC_READ_REGS, "RPC_READ_REGS", nullptr }, + { RPC_WRITE_REG, "RPC_WRITE_REG", nullptr }, + { RPC_GET_SREG_BASE, "RPC_GET_SREG_BASE", nullptr }, + { RPC_SET_EXCEPTION_INFO, "RPC_SET_EXCEPTION_INFO", nullptr }, + + { RPC_OPEN_FILE, "RPC_OPEN_FILE", nullptr }, + { RPC_CLOSE_FILE, "RPC_CLOSE_FILE", nullptr }, + { RPC_READ_FILE, "RPC_READ_FILE", nullptr }, + { RPC_WRITE_FILE, "RPC_WRITE_FILE", nullptr }, + { RPC_IOCTL, "RPC_IOCTL", nullptr }, + { RPC_UPDATE_CALL_STACK, "RPC_UPDATE_CALL_STACK", nullptr }, + { RPC_APPCALL, "RPC_APPCALL", nullptr }, + { RPC_CLEANUP_APPCALL, "RPC_CLEANUP_APPCALL", nullptr }, + { RPC_REXEC, "RPC_REXEC", nullptr }, + { RPC_GET_SCATTERED_IMAGE, "RPC_GET_SCATTERED_IMAGE", nullptr }, + { RPC_GET_IMAGE_UUID, "RPC_GET_IMAGE_UUID", nullptr }, + { RPC_GET_SEGM_START, "RPC_GET_SEGM_START", nullptr }, + { RPC_BIN_SEARCH, "RPC_BIN_SEARCH", nullptr }, + + { RPC_SET_DEBUG_NAMES, "RPC_SET_DEBUG_NAMES", nullptr }, + { RPC_SYNC_STUB, "RPC_SYNC_STUB", nullptr }, + { RPC_ERROR, "RPC_ERROR", nullptr }, + { RPC_MSG, "RPC_MSG", nullptr }, + { RPC_WARNING, "RPC_WARNING", nullptr }, + { RPC_HANDLE_DEBUG_EVENT, "RPC_HANDLE_DEBUG_EVENT", nullptr }, + { RPC_REPORT_IDC_ERROR, "RPC_REPORT_IDC_ERROR", nullptr }, + { RPC_IMPORT_DLL, "RPC_IMPORT_DLL", nullptr }, +}; +#endif + +//------------------------------------------------------------------------- +dbg_rpc_engine_t::dbg_rpc_engine_t(bool _is_client) + : rpc_engine_t(_is_client), + has_pending_event(false), + poll_debug_events(false) +{ +#ifdef TESTABLE_BUILD + register_packet_type_descs( + dbg_rpc_packet_t_descs, + qnumber(dbg_rpc_packet_t_descs)); +#endif +} + +//-------------------------------------------------------------------------- +// sends a request and waits for a reply +// may occasionally send another request based on the reply +rpc_packet_t *dbg_rpc_engine_t::send_request_and_receive_reply(bytevec_t &req, int flags) +{ + bool displayed = false; + rpc_packet_t *result = NULL; + + while ( true ) + { + if ( displayed && user_cancelled() ) + req = prepare_rpc_packet(RPC_CANCELLED); + + if ( !req.empty() ) + { + int code = send_data(req); + if ( code != 0 || (flags & PREQ_GET_EVENT) != 0 ) + break; + + rpc_packet_t *reqp = (rpc_packet_t *)req.begin(); + if ( reqp->code == RPC_ERROR ) + qexit(1); // sent error packet, may die now + } + + rpc_packet_t *rp = recv_packet(); + if ( rp == NULL ) + break; + + switch ( rp->code ) + { + case RPC_UNK: + dwarning("rpc: remote did not understand our request"); + goto FAILURE; + case RPC_MEM: + dwarning("rpc: no remote memory"); + goto FAILURE; + case RPC_CANCELLED: + msg("rpc: user cancelled the operation\n"); + goto FAILURE; + case RPC_OK: + result = rp; + goto END; + default: + // other replies are passed to the handler + break; + } + + if ( !logged_in ) + { + lprintf("Exploit packet has been detected and ignored\n"); +FAILURE: + qfree(rp); + break; + } + // handle actual command in the request + // FIXME: use a better function name + req = on_send_request_interrupt(rp); + qfree(rp); + } + +END: + on_send_request_end(result); + + return result; +} + +//------------------------------------------------------------------------- +int dbg_rpc_engine_t::_send_request_get_int_result( + bytevec_t &req, + int failure_code, + qstring *errbuf) +{ + rpc_packet_t *rp = send_request_and_receive_reply(req); + if ( rp == NULL ) + return failure_code; + + memory_deserializer_t mmdsr(rp+1, rp->length); + int rc = mmdsr.unpack_dd(); + if ( rc < 0 && errbuf != NULL ) + *errbuf = mmdsr.unpack_str(); + + qfree(rp); + return rc; +} diff --git a/idasdk75/dbg/dbg_rpc_engine.h b/idasdk76/dbg/dbg_rpc_engine.h similarity index 100% rename from idasdk75/dbg/dbg_rpc_engine.h rename to idasdk76/dbg/dbg_rpc_engine.h diff --git a/idasdk76/dbg/dbg_rpc_handler.cpp b/idasdk76/dbg/dbg_rpc_handler.cpp new file mode 100644 index 0000000..e6bd284 --- /dev/null +++ b/idasdk76/dbg/dbg_rpc_handler.cpp @@ -0,0 +1,1423 @@ +#include <limits.h> + +#include <pro.h> +#include <typeinf.hpp> +#include <diskio.hpp> +#include <network.hpp> // otherwise cannot compile win32_remote.bpr +#include <err.h> + +#include "server.h" + +//-------------------------------------------------------------------------- +// another copy of this function (for local debugging) is defined in common_local_impl.cpp +int send_ioctl( + rpc_engine_t *srv, + int fn, + const void *buf, + size_t size, + void **poutbuf, + ssize_t *poutsize) +{ + return srv->send_ioctl(fn, buf, size, poutbuf, poutsize); +} + +//-------------------------------------------------------------------------- +AS_PRINTF(3, 0) ssize_t dvmsg(int code, rpc_engine_t *rpc, const char *format, va_list va) +{ + if ( code == 0 ) + code = RPC_MSG; + else if ( code > 0 ) + code = RPC_WARNING; + else + code = RPC_ERROR; + + bytevec_t req = prepare_rpc_packet((uchar)code); + + char buf[MAXSTR]; + qvsnprintf(buf, sizeof(buf), format, va); + req.pack_str(buf); + + qfree(rpc->send_request_and_receive_reply(req)); + if ( code == RPC_ERROR ) + exit(1); + return strlen(buf); +} + +//-------------------------------------------------------------------------- +void report_idc_error(rpc_engine_t *rpc, ea_t ea, error_t code, ssize_t errval, const char *errprm) +{ + if ( code == eOS ) + { + dbg_rpc_handler_t *h = (dbg_rpc_handler_t *)rpc; + errval = h->get_debugger_instance()->get_system_specific_errno(); + } + + bytevec_t req = prepare_rpc_packet(RPC_REPORT_IDC_ERROR); + req.pack_ea64(ea); + req.pack_dd(code); + if ( (const char *)errval == errprm ) + { + req.pack_db(1); + req.pack_str(errprm); + } + else + { + req.pack_db(0); + req.pack_ea64(errval); + } + qfree(rpc->send_request_and_receive_reply(req)); +} + +//-------------------------------------------------------------------------- +debmod_t *dbg_rpc_handler_t::get_debugger_instance() +{ + return dbg_mod; //lint !e1535 !e1536 exposes lower access member +} + +//-------------------------------------------------------------------------- +void dbg_rpc_handler_t::prepare_broken_connection(void) +{ + if ( debmod_t::reuse_broken_connections ) + { + if ( !dbg_mod->dbg_prepare_broken_connection() ) + dmsg("Error preparing debugger server to handle a broken connection\n"); + } +} + +//-------------------------------------------------------------------------- +// dbg_rpc_handler_t +//-------------------------------------------------------------------------- +dbg_rpc_handler_t::dbg_rpc_handler_t( + idarpc_stream_t *_irs, + dbgsrv_dispatcher_t *_dispatcher) + : client_handler_t(_irs, /*_verbose=*/ false), + dbg_rpc_engine_t(/*is_client=*/ false), + dbg_mod(NULL), + dispatcher(_dispatcher) +{ + clear_channels(); //lint -esym(1566,dbg_rpc_handler_t::channels) not inited + struct ida_local lambda_t + { + static int ioctl(rpc_engine_t *rpc, int fn, const void *buf, size_t size, void **out, ssize_t *outsz) + { + dbg_rpc_handler_t *serv = (dbg_rpc_handler_t *) rpc; + memory_deserializer_t mmdsr(buf, size); + if ( fn >= MIN_SERVER_IOCTL ) + return serv->handle_server_ioctl(fn, out, outsz, mmdsr); + else + return serv->get_debugger_instance()->handle_ioctl(fn, buf, size, out, outsz); + } + + static progress_loop_ctrl_t recv_data_iter(bool, size_t, size_t, void *ud) + { + dbg_rpc_handler_t *eng = (dbg_rpc_handler_t *) ud; + bool performed = false; + int code = eng->on_recv_packet_progress(&performed); + if ( performed ) + return code == 0 ? plc_skip_iter : plc_cancel; + else + return plc_proceed; + } + }; + + set_ioctl_handler(lambda_t::ioctl); + irs_set_progress_cb(irs, 100, lambda_t::recv_data_iter, this); +} + +//-------------------------------------------------------------------------- +dbg_rpc_handler_t::~dbg_rpc_handler_t() +{ + //lint -e(1506) Call to virtual function 'dbg_rpc_handler_t::get_broken_connection(void)' within a constructor or destructor + if ( !get_broken_connection() ) + delete dbg_mod; // the connection is not broken, delete the debugger instance + + //lint -esym(1579,dbg_rpc_handler_t::dbg_mod) pointer member might have been freed by a separate function + clear_channels(); + + dispatcher = NULL; +} + +//------------------------------------------------------------------------ +// Function safe against time slicing attack, comparing time depends only on str length +static bool password_matches(const char *str, const char *pass) +{ + if ( str == NULL ) + return false; + int str_length = strlen(str); + int pass_length = strlen(pass); + int res = str_length ^ pass_length; + if ( pass_length != 0 ) + { + for ( int i = 0; i < str_length; i++ ) + res |= (pass[i % pass_length] ^ str[i]); + } + return res == 0; +} + +//------------------------------------------------------------------------- +bool dbg_rpc_handler_t::handle() +{ + bytevec_t req = prepare_rpc_packet(RPC_OPEN); + req.pack_dd(IDD_INTERFACE_VERSION); + req.pack_dd(DEBUGGER_ID); + req.pack_dd(sizeof(ea_t)); + + bool send_response = false; + rpc_packet_t *rp = send_request_and_receive_reply(req, PREQ_MUST_LOGIN); + bool ok = rp != NULL; + if ( ok ) + { + send_response = true; + + // Answer is after rpc_packet_t + memory_deserializer_t mmdsr(rp+1, rp->length); + ok = mmdsr.unpack_dd() != 0; + if ( !ok ) + { + lprintf("[%d] Incompatible IDA version\n", session_id); + send_response = false; + } + else if ( !dispatcher->server_password.empty() ) + { + const char *pass = mmdsr.unpack_str(); + if ( !password_matches(pass, dispatcher->server_password.c_str()) ) + { + lprintf("[%d] Bad password\n", session_id); + ok = false; + } + } + logged_in = ok; + + qfree(rp); + } + else + { + lprintf("[%d] Could not establish the connection\n", session_id); + } + + if ( send_response ) + { + req = prepare_rpc_packet(RPC_OK); + req.pack_dd(ok); + send_data(req); + + // remove reception timeout on the server side + recv_timeout = -1; + logged_in = true; + + if ( ok ) + { + // the main loop: handle client requests until it drops the connection + // or sends us RPC_OK (see rpc_debmod_t::close_remote) + bytevec_t empty; + rpc_packet_t *packet = send_request_and_receive_reply(empty); + if ( packet != NULL ) + qfree(packet); + } + } + network_error = false; + + bool preserve_server = false; + if ( get_broken_connection() ) + { + if ( dispatcher->on_broken_conn == BCH_KEEP_DEBMOD ) + { + term_irs(); + lprintf("[%d] Debugged session entered into sleeping mode\n", session_id); + prepare_broken_connection(); + preserve_server = true; + } + else + { + if ( dispatcher->on_broken_conn == BCH_KILL_PROCESS ) + { + int pid = get_debugger_instance()->pid; + if ( pid > 0 ) + { + lprintf("[%d] Killing debugged process %d\n", + session_id, get_debugger_instance()->pid); + int code = kill_process(); + if ( code != 0 ) + lprintf("[%d] Failed to kill process after %d seconds. Giving up\n", + session_id, code); + } + } + goto TERM_DEBMOD; + } + } + else + { +TERM_DEBMOD: + get_debugger_instance()->dbg_term(); + term_irs(); + } + + return !preserve_server; +} + +//-------------------------------------------------------------------------- +void dbg_rpc_handler_t::set_debugger_instance(debmod_t *instance) +{ + dbg_mod = instance; + dbg_mod->rpc = this; +} + +//-------------------------------------------------------------------------- +#ifdef VERBOSE_ENABLED +static const char *bptcode2str(uint code) +{ + static const char *const strs[] = + { + "BPT_OK", + "BPT_INTERNAL_ERR", + "BPT_BAD_TYPE", + "BPT_BAD_ALIGN", + "BPT_BAD_ADDR", + "BPT_BAD_LEN", + "BPT_TOO_MANY", + "BPT_READ_ERROR", + "BPT_WRITE_ERROR", + "BPT_SKIP", + "BPT_PAGE_OK", + }; + if ( code >= qnumber(strs) ) + return "?"; + return strs[code]; +} +#endif + +//-------------------------------------------------------------------------- +int dbg_rpc_handler_t::rpc_update_bpts(bytevec_t &req, memory_deserializer_t &mmdsr) +{ + update_bpt_vec_t bpts; + int nadd = mmdsr.unpack_dd(); + int ndel = mmdsr.unpack_dd(); + + if ( nadd < 0 || ndel < 0 || INT_MAX - ndel < nadd ) + { + req.pack_dd(0); + verb(("update_bpts(nadd=%d, ndel=%d) => 0 (incorrect values)\n", nadd, ndel)); + return 0; + } + + bpts.resize(nadd+ndel); + ea_t ea = 0; + update_bpt_vec_t::iterator b; + update_bpt_vec_t::iterator bend = bpts.begin() + nadd; + for ( b=bpts.begin(); b != bend; ++b ) + { + b->code = BPT_OK; + b->ea = ea + mmdsr.unpack_ea64(); ea = b->ea; + b->size = mmdsr.unpack_dd(); + b->type = mmdsr.unpack_dd(); + b->pid = mmdsr.unpack_dd(); + b->tid = mmdsr.unpack_dd(); + } + + ea = 0; + bend += ndel; + for ( ; b != bend; ++b ) + { + b->ea = ea + mmdsr.unpack_ea64(); ea = b->ea; + uchar len = mmdsr.unpack_db(); + if ( len > 0 ) + { + b->orgbytes.resize(len); + mmdsr.unpack_obj(b->orgbytes.begin(), len); + } + b->type = mmdsr.unpack_dd(); + b->pid = mmdsr.unpack_dd(); + b->tid = mmdsr.unpack_dd(); + } + +#ifdef VERBOSE_ENABLED + for ( b=bpts.begin()+nadd; b != bend; ++b ) + verb(("del_bpt(ea=%a, type=%d orgbytes.size=%" FMT_Z " size=%d)\n", + b->ea, b->type, b->orgbytes.size(), b->type != BPT_SOFT ? b->size : 0)); +#endif + + int nbpts; + qstring errbuf; + drc_t drc = dbg_mod->dbg_update_bpts(&nbpts, bpts.begin(), nadd, ndel, &errbuf); + + bend = bpts.begin() + nadd; +#ifdef VERBOSE_ENABLED + for ( b=bpts.begin(); b != bend; ++b ) + verb(("add_bpt(ea=%a type=%d len=%d) => %s\n", b->ea, b->type, b->size, bptcode2str(b->code))); +#endif + + req.pack_dd(drc); + req.pack_dd(nbpts); + for ( b=bpts.begin(); b != bend; ++b ) + { + req.pack_db(b->code); + if ( b->code == BPT_OK && b->type == BPT_SOFT ) + { + req.pack_db(b->orgbytes.size()); + req.append(b->orgbytes.begin(), b->orgbytes.size()); + } + } + + bend += ndel; + for ( ; b != bend; ++b ) + { + req.pack_db(b->code); + verb(("del_bpt(ea=%a) => %s\n", b->ea, bptcode2str(b->code))); + } + + if ( drc != DRC_OK ) + req.pack_str(errbuf); + return drc; +} + +//-------------------------------------------------------------------------- +void dbg_rpc_handler_t::rpc_update_lowcnds( + bytevec_t &req, + memory_deserializer_t &mmdsr) +{ + ea_t ea = 0; + lowcnd_vec_t lowcnds; + int nlowcnds = mmdsr.unpack_dd(); + lowcnds.resize(nlowcnds); + lowcnd_t *lc = lowcnds.begin(); + for ( int i=0; i < nlowcnds; i++, lc++ ) + { + lc->compiled = false; + lc->ea = ea + mmdsr.unpack_ea64(); ea = lc->ea; + lc->cndbody = mmdsr.unpack_str(); + if ( !lc->cndbody.empty() ) + { + lc->size = 0; + lc->type = mmdsr.unpack_dd(); + if ( lc->type != BPT_SOFT ) + lc->size = mmdsr.unpack_dd(); + int norg = mmdsr.unpack_db(); + if ( norg > 0 ) + { + lc->orgbytes.resize(norg); + mmdsr.unpack_obj(lc->orgbytes.begin(), norg); + } + lc->cmd.ea = mmdsr.unpack_ea64(); + if ( lc->cmd.ea != BADADDR ) + mmdsr.unpack_obj(&lc->cmd, sizeof(lc->cmd)); + } + verb(("update_lowcnd(ea=%a cnd=%s)\n", ea, lc->cndbody.c_str())); + } + int nupdated; + qstring errbuf; + drc_t drc = dbg_mod->dbg_update_lowcnds(&nupdated, lowcnds.begin(), nlowcnds, &errbuf); + verb((" update_lowcnds => %d\n", drc)); + + req.pack_dd(drc); + req.pack_dd(nupdated); + if ( drc != DRC_OK ) + req.pack_str(errbuf); +} + +//-------------------------------------------------------------------------- +bool dbg_rpc_handler_t::check_broken_connection(pid_t pid) +{ + bool result = false; + dispatcher->clients_list->lock(); + client_handlers_list_t::storage_t::iterator p; + for ( p = dispatcher->clients_list->storage.begin(); + p != dispatcher->clients_list->storage.end(); + ++p ) + { + dbg_rpc_handler_t *h = (dbg_rpc_handler_t *) p->first; + if ( h == this ) + continue; + + debmod_t *d = h->get_debugger_instance(); + if ( d->broken_connection && d->pid == pid && d->dbg_continue_broken_connection(pid) ) + { + dbg_mod->dbg_term(); + delete dbg_mod; + dbg_mod = d; + result = true; + verb(("reusing previously broken debugging session\n")); + +#ifndef __SINGLE_THREADED_SERVER__ + qthread_t thr = p->second; + + // free thread + if ( thr != NULL ) + qthread_free(thr); +#endif + + h->term_irs(); + dispatcher->clients_list->storage.erase(p); + delete h; + + d->broken_connection = false; + break; + } + } + dispatcher->clients_list->unlock(); + return result; +} + +//------------------------------------------------------------------------- +int dbg_rpc_handler_t::handle_server_ioctl( + int fn, + void **out, + ssize_t *outsz, + memory_deserializer_t &mmdsr) +{ + int code = -1; + verb(("handle_server_ioctl(fn=%d, bufsize=%" FMT_Z ").\n", fn, mmdsr.size())); + return code; +} + +//------------------------------------------------------------------------- +int dbg_rpc_handler_t::on_recv_packet_progress(bool *performed) +{ + *performed = poll_debug_events; + return poll_debug_events ? poll_events(TIMEOUT) : 0; +} + +//-------------------------------------------------------------------------- +drc_t dbg_rpc_handler_t::rpc_attach_process( + qstring *errbuf, + memory_deserializer_t &mmdsr) +{ + pid_t pid = mmdsr.unpack_dd(); + int event_id = mmdsr.unpack_dd(); + int flags = mmdsr.unpack_dd(); + drc_t drc = check_broken_connection(pid) + ? DRC_OK + : dbg_mod->dbg_attach_process(pid, event_id, flags, errbuf); + verb(("attach_process(pid=%d, evid=%d) => %d\n", pid, event_id, drc)); + return drc; +} + +//------------------------------------------------------------------------- +void dbg_rpc_handler_t::append_start_or_attach(bytevec_t &req, drc_t drc, const qstring &errbuf) const +{ + req.pack_dd(drc); + if ( drc > DRC_NONE ) + { + debapp_attrs_t attrs; + dbg_mod->dbg_get_debapp_attrs(&attrs); + append_debapp_attrs(req, attrs); + append_dynamic_register_set(req, dbg_mod->idaregs); + } + else + { + req.pack_str(errbuf); + } +} + +//------------------------------------------------------------------------- +void dbg_rpc_handler_t::shutdown_gracefully(int /*signum*/) +{ + debmod_t *d = get_debugger_instance(); + if ( d != NULL ) + d->dbg_exit_process(NULL); // kill the process instead of letting it run in wild +} + +//-------------------------------------------------------------------------- +// performs requests on behalf of a remote client +// client -> server +#ifdef __UNIX__ +# define PERM_0755 (S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) +# define IS_SUBPATH strneq +#else +# define PERM_0755 0755 +# define IS_SUBPATH strnieq +#endif +bytevec_t dbg_rpc_handler_t::on_send_request_interrupt(const rpc_packet_t *rp) +{ + // While the server is performing a request, it should not poll + // for debugger events + bool saved_poll_mode = poll_debug_events; + poll_debug_events = false; + + memory_deserializer_t mmdsr(rp+1, rp->length); + bytevec_t req = prepare_rpc_packet(RPC_OK); +#if defined(__EXCEPTIONS) || defined(__NT__) + try +#endif + { + switch ( rp->code ) + { + case RPC_INIT: + { + dbg_mod->debugger_flags = mmdsr.unpack_dd(); + bool debug_debugger = mmdsr.unpack_dd() != 0; + if ( debug_debugger ) + verbose = true; + + dbg_mod->dbg_set_debugging(debug_debugger); + qstring errbuf; + uint32_t flags2 = 0; + drc_t drc = dbg_mod->dbg_init(&flags2, &errbuf); + verb(("init(debug_debugger=%d) => %d (flags2=%d)\n", debug_debugger, drc, flags2)); + req.pack_dd(drc); + req.pack_dd(flags2); + if ( drc != DRC_OK ) + req.pack_str(errbuf); + } + break; + + case RPC_TERM: + // Do not dbg_term() here, as it will be called + // at the end of server.cpp's handle_single_session(), + // right after this. + // dbg_mod->dbg_term(); + // verb(("term()\n")); + break; + + case RPC_GET_PROCESSES: + { + procinfo_vec_t procs; + qstring errbuf; + drc_t drc = dbg_mod->dbg_get_processes(&procs, &errbuf); + req.pack_dd(drc); + if ( drc == DRC_OK ) + append_process_info_vec(req, &procs); + else + req.pack_str(errbuf); + verb(("get_processes() => %d\n", drc)); + } + break; + + case RPC_DETACH_PROCESS: + { + drc_t drc = dbg_mod->dbg_detach_process(); + req.pack_dd(drc); + verb(("detach_process() => %d\n", drc)); + } + break; + + case RPC_START_PROCESS: + { + const char *path = mmdsr.unpack_str(); + const char *args = mmdsr.unpack_str(); + const char *sdir = mmdsr.unpack_str(); + int flags = mmdsr.unpack_dd(); + const char *input = mmdsr.unpack_str(); + uint32 crc32 = mmdsr.unpack_dd(); + qstring errbuf; + drc_t drc = DRC_NOFILE; + if ( path != NULL && sdir != NULL && input != NULL ) // protect against malicious ida + { + drc = dbg_mod->dbg_start_process(path, args, sdir, flags, input, crc32, &errbuf); + verb(("start_process(path=%s args=%s flags=%s%s%s\n" + " sdir=%s\n" + " input=%s crc32=%x) => %d\n", + path, args, + flags & DBG_PROC_IS_DLL ? " is_dll" : "", + flags & DBG_PROC_IS_GUI ? " under_gui" : "", + flags & DBG_HIDE_WINDOW ? " hide_window" : "", + sdir, + input, crc32, + drc)); + } + append_start_or_attach(req, drc, errbuf); + } + break; + + case RPC_GET_DEBUG_EVENT: + { + int timeout_ms = mmdsr.unpack_dd(); + gdecode_t result = GDE_NO_EVENT; + if ( !has_pending_event ) + result = dbg_mod->dbg_get_debug_event(&ev, timeout_ms); + req.pack_dd(result); + if ( result >= GDE_ONE_EVENT ) + { + append_debug_event(req, &ev); + verb(("got event: %s\n", debug_event_str(&ev))); + } + else if ( !has_pending_event ) + { + saved_poll_mode = true; + } + verbev(("get_debug_event(timeout=%d) => %d (has_pending=%d, willpoll=%d)\n", timeout_ms, result, has_pending_event, saved_poll_mode)); + } + break; + + case RPC_ATTACH_PROCESS: + { + qstring errbuf; + append_start_or_attach(req, rpc_attach_process(&errbuf, mmdsr), errbuf); + } + break; + + case RPC_PREPARE_TO_PAUSE_PROCESS: + { + qstring errbuf; + drc_t drc = dbg_mod->dbg_prepare_to_pause_process(&errbuf); + verb(("prepare_to_pause_process() => %d\n", drc)); + req.pack_dd(drc); + if ( drc < DRC_NONE ) + req.pack_str(errbuf); + } + break; + + case RPC_EXIT_PROCESS: + { + qstring errbuf; + drc_t drc = dbg_mod->dbg_exit_process(&errbuf); + verb(("exit_process() => %d\n", drc)); + req.pack_dd(drc); + if ( drc < DRC_NONE ) + req.pack_str(errbuf); + } + break; + + case RPC_CONTINUE_AFTER_EVENT: + { + extract_debug_event(&ev, mmdsr); + drc_t drc = dbg_mod->dbg_continue_after_event(&ev); + verb(("continue_after_event(...) => %d\n", drc)); + req.pack_dd(drc); + } + break; + + case RPC_STOPPED_AT_DEBUG_EVENT: + { + bool dlls_added = mmdsr.unpack_db() != 0; + bool ask_thr_names = mmdsr.unpack_db() != 0; + import_infos_t infos; + thread_name_vec_t thr_names; + dbg_mod->dbg_stopped_at_debug_event(&infos, dlls_added, ask_thr_names ? &thr_names : NULL); + process_import_requests(infos); + name_info_t *ni = dbg_mod->get_debug_names(); + int err = RPC_OK; + if ( ni != NULL ) + { + err = send_debug_names_to_ida(ni->addrs.begin(), ni->names.begin(), (int)ni->addrs.size()); + dbg_mod->clear_debug_names(); + } + if ( ask_thr_names ) + { + uint32 n = thr_names.size(); + req.pack_dd(n); + for ( int i=0; i < n; ++i ) + { + thread_name_t &tn = thr_names[i]; + req.pack_dd(tn.tid); + req.pack_str(tn.name); + } + } + } + break; + + case RPC_TH_SUSPEND: + { + thid_t tid = mmdsr.unpack_dd(); + drc_t drc = dbg_mod->dbg_thread_suspend(tid); + verb(("thread_suspend(tid=%d) => %d\n", tid, drc)); + req.pack_dd(drc); + } + break; + + case RPC_TH_CONTINUE: + { + thid_t tid = mmdsr.unpack_dd(); + drc_t drc = dbg_mod->dbg_thread_continue(tid); + verb(("thread_continue(tid=%d) => %d\n", tid, drc)); + req.pack_dd(drc); + } + break; + + case RPC_SET_RESUME_MODE: + { + thid_t tid = mmdsr.unpack_dd(); + resume_mode_t resmod = resume_mode_t(mmdsr.unpack_dd()); + drc_t drc = dbg_mod->dbg_set_resume_mode(tid, resmod); + verb(("set_resume_mode(tid=%d, resmod=%d) => %d\n", tid, resmod, drc)); + req.pack_dd(drc); + } + break; + + case RPC_READ_REGS: + { + drc_t drc = DRC_NONE; + qstring errbuf; + bytevec_t regmap; + regvals_t values; + thid_t tid = mmdsr.unpack_dd(); + int clsmask = mmdsr.unpack_dd(); + int nregs = mmdsr.unpack_dd(); + if ( nregs <= 0 || nregs > dbg_mod->nregs ) + { + errbuf.sprnt("read_regs(tid=%d, mask=%x, nregs=%d) => 0 " + "(incorrect nregs, should be in range 0..%d)\n", + tid, clsmask, nregs, dbg_mod->nregs); + } + else + { + regmap.resize((nregs+7)/8); + mmdsr.unpack_obj(regmap.begin(), regmap.size()); + values.resize(dbg_mod->nregs); + drc = dbg_mod->dbg_read_registers(tid, clsmask, values.begin(), &errbuf); + verb(("read_regs(tid=%d, mask=%x) => %d\n", tid, clsmask, drc)); + } + req.pack_dd(drc); + if ( drc == DRC_OK ) + append_regvals(req, values.begin(), nregs, regmap.begin()); + else + req.pack_str(errbuf); + } + break; + + case RPC_WRITE_REG: + { + thid_t tid = mmdsr.unpack_dd(); + int reg_idx = mmdsr.unpack_dd(); + regval_t value; + unpack_regvals(&value, 1, NULL, mmdsr); + qstring errbuf; + drc_t drc = dbg_mod->dbg_write_register(tid, reg_idx, &value, &errbuf); + verb(("write_reg(tid=%d) => %d\n", tid, drc)); + req.pack_dd(drc); + if ( drc < DRC_NONE ) + req.pack_str(errbuf); + } + break; + + case RPC_GET_SREG_BASE: + { + thid_t tid = mmdsr.unpack_dd(); + int sreg_value = mmdsr.unpack_dd(); + ea_t ea; + qstring errbuf; + drc_t drc = dbg_mod->dbg_thread_get_sreg_base(&ea, tid, sreg_value, &errbuf); + verb(("get_thread_sreg_base(tid=%d, %d) => %a\n", tid, sreg_value, drc == DRC_OK ? ea : BADADDR)); + req.pack_dd(drc); + if ( drc == DRC_OK ) + req.pack_ea64(ea); + else + req.pack_str(errbuf); + } + break; + + case RPC_SET_EXCEPTION_INFO: + { + int qty = mmdsr.unpack_dd(); + exception_info_t *extable = extract_exception_info(qty, mmdsr); + dbg_mod->dbg_set_exception_info(extable, qty); + delete [] extable; + verb(("set_exception_info(qty=%d)\n", qty)); + } + break; + + case RPC_GET_MEMORY_INFO: + { + meminfo_vec_t areas; + qstring errbuf; + drc_t drc = dbg_mod->dbg_get_memory_info(areas, &errbuf); + int qty = areas.size(); + verb(("get_memory_info() => %d (qty=%d)\n", drc, qty)); + req.pack_dd(drc + (-DRC_IDBSEG)); + if ( drc == DRC_OK ) + { + req.pack_dd(qty); + for ( int i=0; i < qty; i++ ) + append_memory_info(req, &areas[i]); + } + else + { + req.pack_str(errbuf); + } + } + break; + + case RPC_GET_SCATTERED_IMAGE: + { + ea_t base = mmdsr.unpack_ea64(); + scattered_image_t si; + int result = dbg_mod->dbg_get_scattered_image(si, base); + int qty = si.size(); + verb(("get_scattered_image(base=%a) => %d (qty=%d)\n", base, result, qty)); + req.pack_dd(result+2); + if ( result > 0 ) + { + req.pack_dd(qty); + for ( int i=0; i < qty; i++ ) + append_scattered_segm(req, &si[i]); + } + } + break; + + case RPC_GET_IMAGE_UUID: + { + ea_t base = mmdsr.unpack_ea64(); + bytevec_t uuid; + bool result = dbg_mod->dbg_get_image_uuid(&uuid, base); + int size = uuid.size(); + verb(("get_image_uuid(base=%a) => %d (size=%d)\n", base, result, size)); + req.pack_dd(result); + if ( result ) + req.pack_buf(uuid.begin(), size); + } + break; + + case RPC_GET_SEGM_START: + { + ea_t base = mmdsr.unpack_ea64(); + const char *segname = mmdsr.unpack_str(); + ea_t result = dbg_mod->dbg_get_segm_start(base, segname); + verb(("get_segm_start(base=%a, segname=%s) => %a\n", base, segname, result)); + req.pack_ea64(result); + } + break; + + case RPC_READ_MEMORY: + { + ea_t ea = mmdsr.unpack_ea64(); + size_t size = mmdsr.unpack_dd(); + uchar *buf = new uchar[size]; + qstring errbuf; + ssize_t result = dbg_mod->dbg_read_memory(ea, buf, size, &errbuf); + verb(("read_memory(ea=%a size=%" FMT_Z ") => %" FMT_ZS, ea, size, result)); + if ( result > 0 && size == 1 ) + verb((" (0x%02X)\n", *buf)); + else + verb(("\n")); + req.pack_dd(uint32(result)); + if ( result > 0 ) + req.append(buf, result); + else + req.pack_str(errbuf); + delete[] buf; + } + break; + + case RPC_WRITE_MEMORY: + { + ea_t ea = mmdsr.unpack_ea64(); + size_t size = mmdsr.unpack_dd(); + uchar *buf = new uchar[size]; + mmdsr.unpack_obj(buf, size); + qstring errbuf; + ssize_t result = dbg_mod->dbg_write_memory(ea, buf, size, &errbuf); + verb(("write_memory(ea=%a size=%" FMT_Z ") => %" FMT_ZS, ea, size, result)); + if ( result && size == 1 ) + verb((" (0x%02X)\n", *buf)); + else + verb(("\n")); + req.pack_dd(uint32(result)); + if ( result <= 0 ) + req.pack_str(errbuf); + delete[] buf; + } + break; + + case RPC_ISOK_BPT: + { + bpttype_t type = mmdsr.unpack_dd(); + ea_t ea = mmdsr.unpack_ea64(); + int len = mmdsr.unpack_dd() - 1; + int result = dbg_mod->dbg_is_ok_bpt(type, ea, len); + verb(("isok_bpt(type=%d ea=%a len=%d) => %d\n", type, ea, len, result)); + req.pack_dd(result); + } + break; + + case RPC_UPDATE_BPTS: + { + int ret = rpc_update_bpts(req, mmdsr); + if ( ret == 0 ) + verb(("rpc_update_bpts failed!\n")); + } + break; + + case RPC_UPDATE_LOWCNDS: + rpc_update_lowcnds(req, mmdsr); + break; + + case RPC_EVAL_LOWCND: + { + thid_t tid = mmdsr.unpack_dd(); + ea_t ea = mmdsr.unpack_ea64(); + qstring errbuf; + drc_t drc = dbg_mod->dbg_eval_lowcnd(tid, ea, &errbuf); + req.pack_dd(drc); + if ( drc != DRC_OK ) + req.pack_str(errbuf); + verb(("eval_lowcnd(tid=%d, ea=%a) => %d\n", tid, ea, drc)); + } + break; + + case RPC_OPEN_FILE: + { + const char *path = mmdsr.unpack_str(); + bool readonly = mmdsr.unpack_dd() != 0; + int64 fsize = 0; + int fn = find_free_channel(); + if ( fn != -1 ) + { + if ( readonly ) + { + channels[fn] = fopenRB(path); + } + else + { + char dir[QMAXPATH]; + if ( qdirname(dir, sizeof(dir), path) && !qisdir(dir) ) + { + char absdir[QMAXPATH]; + qmake_full_path(absdir, sizeof(absdir), dir); + char cwd[QMAXPATH]; + qgetcwd(cwd, sizeof(cwd)); + if ( IS_SUBPATH(absdir, cwd, qstrlen(cwd)) ) + { + qstrvec_t subpaths; + while ( !qisdir(absdir) ) + { + subpaths.insert(subpaths.begin(), absdir); + if ( !qdirname(absdir, sizeof(absdir), absdir) ) + break; + } + for ( size_t i = 0, n = subpaths.size(); i < n; ++i ) + { + const char *subdir = subpaths[i].c_str(); + verb(("open_file() creating directory %s\n", subdir)); + if ( qmkdir(subdir, PERM_0755) != 0 ) + break; + } + } + } + channels[fn] = fopenWB(path); + } + if ( channels[fn] == NULL ) + fn = -1; + else if ( readonly ) + fsize = qfsize(channels[fn]); + } + verb(("open_file('%s', %d) => %d %" FMT_64 "d\n", path, readonly, fn, fsize)); + req.pack_dd(fn); + if ( fn != -1 ) + req.pack_dq(fsize); + else + req.pack_dd(qerrcode()); + } + break; + + case RPC_CLOSE_FILE: + { + int fn = mmdsr.unpack_dd(); + if ( fn >= 0 && fn < qnumber(channels) ) + { + FILE *fp = channels[fn]; + if ( fp != NULL ) + { +#ifdef __UNIX__ + fchmod(fileno(fp), PERM_0755); // set mode 0755 for unix applications +#endif + qfclose(fp); + channels[fn] = NULL; + } + } + verb(("close_file(%d)\n", fn)); + } + break; + + case RPC_READ_FILE: + { + char *buf = NULL; + int fn = mmdsr.unpack_dd(); + int64 off = mmdsr.unpack_dq(); + int32 size = mmdsr.unpack_dd(); + int32 s2 = 0; + if ( size > 0 ) + { + buf = new char[size]; + qfseek(channels[fn], off, SEEK_SET); + s2 = qfread(channels[fn], buf, size); + } + req.pack_dd(s2); + if ( size != s2 ) + req.pack_dd(qerrcode()); + else + req.append(buf, s2); + delete[] buf; + verb(("read_file(%d, 0x%" FMT_64 "X, %d) => %d\n", fn, off, size, s2)); + } + break; + + case RPC_WRITE_FILE: + { + char *buf = NULL; + int fn = mmdsr.unpack_dd(); + uint64 off = mmdsr.unpack_dq(); + uint32 size = mmdsr.unpack_dd(); + if ( size > 0 ) + { + buf = new char[size]; + mmdsr.unpack_obj(buf, size); + } + qfseek(channels[fn], off, SEEK_SET); + uint32 s2 = buf == NULL ? 0 : qfwrite(channels[fn], buf, size); + req.pack_dd(size); + if ( size != s2 ) + req.pack_dd(qerrcode()); + delete [] buf; + verb(("write_file(%d, 0x%" FMT_64 "X, %u) => %u\n", fn, off, size, s2)); + } + break; + + case RPC_EVOK: + req.clear(); + verbev(("got evok!\n")); + break; + + case RPC_IOCTL: + { + int code = handle_ioctl_packet(req, mmdsr.ptr, mmdsr.end); + if ( code != RPC_OK ) + req = prepare_rpc_packet((uchar)code); + } + break; + + case RPC_UPDATE_CALL_STACK: + { + call_stack_t trace; + thid_t tid = mmdsr.unpack_dd(); + drc_t drc = dbg_mod->dbg_update_call_stack(tid, &trace); + req.pack_dd(drc); + if ( drc == DRC_OK ) + append_call_stack(req, trace); + } + break; + + case RPC_APPCALL: + { + ea_t func_ea = mmdsr.unpack_ea64(); + thid_t tid = mmdsr.unpack_dd(); + int stkarg_nbytes = mmdsr.unpack_dd(); + int flags = mmdsr.unpack_dd(); + + regobjs_t regargs, retregs; + relobj_t stkargs; + regobjs_t *rr = (flags & APPCALL_MANUAL) == 0 ? &retregs : NULL; + extract_appcall(®args, &stkargs, rr, mmdsr); + + qstring errbuf; + debug_event_t event; + ea_t sp = dbg_mod->dbg_appcall(func_ea, tid, stkarg_nbytes, ®args, &stkargs, + &retregs, &errbuf, &event, flags); + req.pack_ea64(sp); + if ( sp == BADADDR ) + { + if ( (flags & APPCALL_DEBEV) != 0 ) + append_debug_event(req, &event); + req.pack_str(errbuf); + } + else if ( (flags & APPCALL_MANUAL) == 0 ) + { + append_regobjs(req, retregs, true); + } + } + break; + + case RPC_CLEANUP_APPCALL: + { + thid_t tid = mmdsr.unpack_dd(); + drc_t drc = dbg_mod->dbg_cleanup_appcall(tid); + req.pack_dd(drc); + } + break; + + case RPC_REXEC: + { + const char *cmdline = mmdsr.unpack_str(); + int code = dbg_mod->dbg_rexec(cmdline); + req.pack_dd(code); + } + break; + + case RPC_BIN_SEARCH: + { + ea_t start_ea = mmdsr.unpack_ea64(); + ea_t end_ea = mmdsr.unpack_ea64(); + int cnt = mmdsr.unpack_dd(); + compiled_binpat_vec_t ptns; + ptns.resize(cnt); + for ( int i=0; i < cnt; ++i ) + { + compiled_binpat_t &p = ptns[i]; + // bytes + int sz = mmdsr.unpack_dd(); + if ( sz != 0 ) + { + p.bytes.resize(sz); + mmdsr.unpack_obj(p.bytes.begin(), sz); + } + // mask + sz = mmdsr.unpack_dd(); + if ( sz != 0 ) + { + p.mask.resize(sz); + mmdsr.unpack_obj(p.mask.begin(), sz); + } + // strlits + sz = mmdsr.unpack_dd(); + p.strlits.resize(sz); + for ( int j=0; j < sz; ++j ) + { + p.strlits[j].start_ea = mmdsr.unpack_ea64(); + p.strlits[j].end_ea = mmdsr.unpack_ea64(); + } + // encidx + p.encidx = mmdsr.unpack_dd(); + } + int srch_flags = mmdsr.unpack_dd(); + ea_t srch_ea; + qstring errbuf; + drc_t drc = dbg_mod->dbg_bin_search(&srch_ea, start_ea, end_ea, ptns, srch_flags, &errbuf); + req.pack_dd(drc); + if ( drc == DRC_OK ) + req.pack_ea64(srch_ea); + else if ( drc != DRC_FAILED ) // DRC_FAILED means not found + req.pack_str(errbuf); + } + break; + + default: + req = prepare_rpc_packet(RPC_UNK); + break; + } + } +#if defined(__EXCEPTIONS) || defined(__NT__) + catch ( const std::bad_alloc & ) + { + req = prepare_rpc_packet(RPC_MEM); + } +#endif + + if ( saved_poll_mode ) + poll_debug_events = true; + return req; +} + +//-------------------------------------------------------------------------- +// poll for events from the debugger module +int dbg_rpc_handler_t::poll_events(int timeout_ms) +{ + int code = 0; + if ( !has_pending_event ) + { + // immediately set poll_debug_events to false to avoid recursive calls. + poll_debug_events = false; + has_pending_event = dbg_mod->dbg_get_debug_event(&pending_event, timeout_ms) >= GDE_ONE_EVENT; + if ( has_pending_event ) + { + verbev(("got event, sending it, poll will be 0 now\n")); + bytevec_t req = prepare_rpc_packet(RPC_EVENT); + append_debug_event(req, &pending_event); + code = send_data(req); + has_pending_event = false; + } + else + { // no event, continue to poll + poll_debug_events = true; + } + } + return code; +} + +//-------------------------------------------------------------------------- +// this function runs on the server side +// a dbg_rpc_client sends an RPC_SYNC request and the server must give the stub to the client +bool dbg_rpc_handler_t::rpc_sync_stub(const char *server_stub_name, const char *ida_stub_name) +{ + bool ok = false; + int32 crc32 = -1; + linput_t *li = open_linput(server_stub_name, false); + if ( li != NULL ) + { + crc32 = calc_file_crc32(li); + close_linput(li); + } + + bytevec_t stub = prepare_rpc_packet(RPC_SYNC_STUB); + stub.pack_str(ida_stub_name); + stub.pack_dd(crc32); + rpc_packet_t *rp = send_request_and_receive_reply(stub); + + if ( rp == NULL ) + return ok; + + const uchar *answer = (uchar *)(rp+1); + const uchar *end = answer + rp->length; + size_t size = unpack_dd(&answer, end); + if ( size == 1 ) + { + ok = true; + } + else if ( size != 0 ) + { + FILE *fp = fopenWB(server_stub_name); + if ( fp != NULL ) + { + ok = qfwrite(fp, answer, size) == size; + dmsg("Updated kernel debugger stub: %s\n", ok ? "success" : "failed"); + qfclose(fp); + } + else + { + dwarning("Could not update the kernel debugger stub.\n%s", qerrstr()); + } + } + qfree(rp); + + return ok; +} + +//-------------------------------------------------------------------------- +//lint -e{818} 'addrs' could be declared as pointing to const +int dbg_rpc_handler_t::send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty) +{ + if ( qty == 0 ) + return RPC_OK; + + bytevec_t buf; + + // The overall size of debug names may be large. + // This may lead to unwanted network timeouts. + // On the other hand, the small packet size produces a lot of packets, + // which can significantly increase the total response time for the request. + // Example: with 1300 byte packets, attaching to a process using Corellium + // was taking 20 minutes, while with 1MB packets it takes 3 minutes + const size_t SZPACKET = 1024*1024; + + while ( qty > 0 ) + { + buf.qclear(); + + ea_t old = 0; + const char *optr = ""; + + // Start appending names and EAs + int i = 0; + while ( i < qty ) + { + adiff_t diff = *addrs - old; + bool neg = diff < 0; + if ( neg ) + diff = -diff; + + buf.pack_ea64(diff); // send address deltas + buf.pack_dd(neg); + + old = *addrs; + const char *nptr = *names; + int len = 0; + + // do not send repeating prefixes of names + while ( nptr[len] != '\0' && nptr[len] == optr[len] ) //lint !e690 wrong access + len++; + + buf.pack_dd(len); + buf.pack_str(nptr+len); + optr = nptr; + addrs++; + names++; + i++; + + if ( buf.size() > SZPACKET ) + break; + } + qty -= i; + + bytevec_t req = prepare_rpc_packet(RPC_SET_DEBUG_NAMES); + req.pack_dd(i); + req.append(buf.begin(), buf.size()); + + // should return a qty as much as sent...if not probably network error! + if ( i != send_request_get_long_result(req) ) + return RPC_UNK; + } + + return RPC_OK; +} + +//-------------------------------------------------------------------------- +int dbg_rpc_handler_t::send_debug_event_to_ida(const debug_event_t *debev, int rqflags) +{ + bytevec_t req = prepare_rpc_packet(RPC_HANDLE_DEBUG_EVENT); + append_debug_event(req, debev); + req.pack_dd(rqflags); + return send_request_get_long_result(req); +} + +//-------------------------------------------------------------------------- +void dbg_rpc_handler_t::process_import_requests(const import_infos_t &infos) +{ + // in an effort to avoid sending large amounts of symbol data over the network, + // we attempt to import symbols for each dll on the client side. + // if the client does not support such behavior, then we simply parse the symbols + // on the server side and append to the list of debug names to send to IDA, as normal. + for ( import_infos_t::const_iterator i = infos.begin(); i != infos.end(); ++i ) + { + ea_t base = i->base; + const char *path = i->path.c_str(); + const bytevec_t &uuid = i->uuid; + + bytevec_t req = prepare_rpc_packet(RPC_IMPORT_DLL); + req.pack_ea64(base); + req.pack_str(path); + req.pack_buf(uuid.begin(), uuid.size()); + + int code = send_request_get_long_result(req); + if ( code < 0 ) // cancelled or network error + return; + if ( code != 0 ) // request failed, fall back to parsing symbols server-side + dbg_mod->import_dll(*i); + } +} + +//-------------------------------------------------------------------------- +bool dbg_rpc_handler_t::get_broken_connection(void) +{ + return get_debugger_instance()->broken_connection; +} + +//-------------------------------------------------------------------------- +void dbg_rpc_handler_t::set_broken_connection(void) +{ + get_debugger_instance()->broken_connection = true; +} + +//------------------------------------------------------------------------- +int dbg_rpc_handler_t::kill_process(void) +{ + const int NSEC = 5; + dbg_mod->dbg_exit_process(NULL); + + // now, wait up to NSEC seconds until the process is gone + qtime64_t wait_start = qtime64(); + qtime64_t wait_threshold = make_qtime64( + get_secs(wait_start) + NSEC, + get_usecs(wait_start)); + while ( qtime64() < wait_threshold ) + { + gdecode_t result = dbg_mod->dbg_get_debug_event(&ev, 100); + if ( result >= GDE_ONE_EVENT ) + { + dbg_mod->dbg_continue_after_event(&ev); + if ( ev.eid() == PROCESS_EXITED ) + return 0; + } + } + return NSEC; +} + +//-------------------------------------------------------------------------- +int debmod_t::send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty) +{ + dbg_rpc_handler_t *s = (dbg_rpc_handler_t *)rpc; + return s->send_debug_names_to_ida(addrs, names, qty); +} + +//-------------------------------------------------------------------------- +int debmod_t::send_debug_event_to_ida(const debug_event_t *ev, int rqflags) +{ + dbg_rpc_handler_t *s = (dbg_rpc_handler_t *)rpc; + return s->send_debug_event_to_ida(ev, rqflags); +} diff --git a/idasdk75/dbg/dbg_rpc_handler.h b/idasdk76/dbg/dbg_rpc_handler.h similarity index 100% rename from idasdk75/dbg/dbg_rpc_handler.h rename to idasdk76/dbg/dbg_rpc_handler.h diff --git a/idasdk75/dbg/dbg_rpc_handler_ioctls.h b/idasdk76/dbg/dbg_rpc_handler_ioctls.h similarity index 100% rename from idasdk75/dbg/dbg_rpc_handler_ioctls.h rename to idasdk76/dbg/dbg_rpc_handler_ioctls.h diff --git a/idasdk75/dbg/dbg_rpc_hlp.cpp b/idasdk76/dbg/dbg_rpc_hlp.cpp similarity index 100% rename from idasdk75/dbg/dbg_rpc_hlp.cpp rename to idasdk76/dbg/dbg_rpc_hlp.cpp diff --git a/idasdk75/dbg/dbg_rpc_hlp.h b/idasdk76/dbg/dbg_rpc_hlp.h similarity index 100% rename from idasdk75/dbg/dbg_rpc_hlp.h rename to idasdk76/dbg/dbg_rpc_hlp.h diff --git a/idasdk76/dbg/deb_arm.hpp b/idasdk76/dbg/deb_arm.hpp new file mode 100644 index 0000000..6654872 --- /dev/null +++ b/idasdk76/dbg/deb_arm.hpp @@ -0,0 +1,22 @@ +#ifndef __DEB_ARM__ +#define __DEB_ARM__ + +#include <ua.hpp> +#include <idd.hpp> + +#define MEMORY_PAGE_SIZE 0x1000 +#define ARM_BPT_CODE { 0xF0, 0x01, 0xF0, 0xE7 } // und #10 +#define AARCH64_BPT_CODE { 0x00, 0x00, 0x20, 0xD4 } // brk #0 + +#define ARM_BPT_SIZE 4 // size of BPT instruction + +#define ARM_T 20 // number of virtual T segment register in IDA + // it controls thumb/arm mode. + +#define ARM_MAX_HWBPTS 16 +#define ARM_MAX_WATCHPOINTS 16 + +int is_arm_valid_bpt(bpttype_t type, ea_t ea, int len); + +#endif + diff --git a/idasdk75/dbg/deb_pc.hpp b/idasdk76/dbg/deb_pc.hpp similarity index 100% rename from idasdk75/dbg/deb_pc.hpp rename to idasdk76/dbg/deb_pc.hpp diff --git a/idasdk76/dbg/debmod.cpp b/idasdk76/dbg/debmod.cpp new file mode 100644 index 0000000..9480659 --- /dev/null +++ b/idasdk76/dbg/debmod.cpp @@ -0,0 +1,1333 @@ +/* + Base debmod class. +*/ + +#ifdef __NT__ +# include <windows.h> +#else +# include <sys/utsname.h> +#endif + +#include "debmod.h" +#include <err.h> +#include <idp.hpp> +#include <expr.hpp> +#include <diskio.hpp> +#include <typeinf.hpp> +#include <kernwin.hpp> +#include <network.hpp> + +//-------------------------------------------------------------------------- +// Variables to be used by built-in IDC functions +debmod_t *idc_debmod; +thid_t idc_thread; + +//-------------------------------------------------------------------------- +// Initialize static members +bool debmod_t::reuse_broken_connections = false; + +//-------------------------------------------------------------------------- +static const char *get_event_name(event_id_t id) +{ + switch ( id ) + { + case NO_EVENT: return "NO_EVENT"; + case THREAD_STARTED: return "THREAD_STARTED"; + case STEP: return "STEP"; + case PROCESS_DETACHED: return "PROCESS_DETACHED"; + case PROCESS_STARTED: return "PROCESS_STARTED"; + case PROCESS_ATTACHED: return "PROCESS_ATTACHED"; + case PROCESS_SUSPENDED: return "PROCESS_SUSPENDED"; + case LIB_LOADED: return "LIB_LOADED"; + case PROCESS_EXITED: return "PROCESS_EXITED"; + case THREAD_EXITED: return "THREAD_EXITED"; + case BREAKPOINT: return "BREAKPOINT"; + case EXCEPTION: return "EXCEPTION"; + case LIB_UNLOADED: return "LIB_UNLOADED"; + case INFORMATION: return "INFORMATION"; + case TRACE_FULL: return "TRACE_FULL"; + default: return "???"; + } +} + +#if defined(__MAC__) || defined(__LINUX__) || defined(__ANDROID__) +//--------------------------------------------------------------------------- +inline bool is_esxi() +{ +#ifdef __LINUX__ + static int ok = -1; + if ( ok == -1 ) + { + utsname utsinfo; + ok = uname(&utsinfo) == 0 && strieq(utsinfo.sysname, "VMkernel"); + } + return ok > 0; +#else + return false; +#endif +} + +//--------------------------------------------------------------------------- +drc_t idaapi maclnx_launch_process( + debmod_t *debmod, + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + void **child_pid, + qstring * /*errbuf*/) +{ + // prepare full path if the input_path is relative + char full_input[QMAXPATH]; + if ( startdir[0] != '\0' && !qisabspath(input_path) ) + { + qmake_full_path(full_input, sizeof(full_input), input_path); + input_path = full_input; + } + + // input file specified in the database does not exist + if ( (flags & DBG_PROC_IS_DLL) == 0 + && input_path[0] != '\0' + && !qfileexist(input_path) ) + { + debmod->dwarning("AUTOHIDE NONE\nInput file is missing: %s", input_path); + return DRC_NOFILE; + } + + // temporary thing, later we will retrieve the real file name + // based on the process id + debmod->input_file_path = input_path; + debmod->is_dll = (flags & DBG_PROC_IS_DLL) != 0; + + if ( !qfileexist(path) ) + { + debmod->dmsg("%s: %s\n", path, winerr(errno)); + return DRC_NETERR; + } + + drc_t mismatch = DRC_OK; + if ( !debmod->check_input_file_crc32(input_file_crc32) ) + mismatch = DRC_CRC; + + //-V:dbg_srv_64:547 is always true +#ifdef __EA64__ + bool dbg_srv_64 = true; +#else + bool dbg_srv_64 = false; + if ( (flags & DBG_PROC_64BIT) != 0 ) + { + debmod->dwarning("Cannot debug a 64bit process with the 32bit debugger server, sorry\n"); + return DRC_NETERR; + } +#endif + + launch_process_params_t lpi; + lpi.path = path; + lpi.args = args; + lpi.startdir = startdir[0] != '\0' ? startdir : NULL; + lpi.flags = LP_NO_ASLR | LP_DETACH_TTY; + + // Vmware ESXi sends SIGHUP when we try to detact. It could be because of a + // racing condition in but I do not have ESXi handy to check. + if ( is_esxi() ) + lpi.flags &= ~LP_DETACH_TTY; + if ( (flags & DBG_NO_TRACE) == 0 ) + lpi.flags |= LP_TRACE; + if ( (flags & DBG_HIDE_WINDOW) != 0 ) + lpi.flags |= LP_HIDE_WINDOW; + if ( (flags & DBG_SUSPENDED) != 0 ) + lpi.flags |= LP_SUSPENDED; + + if ( (flags & DBG_PROC_64BIT) != 0 ) + { + lpi.flags |= LP_LAUNCH_64_BIT; + } + else if ( (flags & DBG_PROC_32BIT) != 0 ) + { + lpi.flags |= LP_LAUNCH_32_BIT; + } + else + { + lpi.flags |= dbg_srv_64 ? LP_LAUNCH_64_BIT : LP_LAUNCH_32_BIT; + debmod->dmsg("Launching as %sbit process\n", dbg_srv_64 ? "64" : "32"); + } + + qstring errbuf; + *child_pid = launch_process(lpi, &errbuf); + + if ( *child_pid == NULL ) + { + debmod->dmsg("launch_process: %s", errbuf.c_str()); + return DRC_NETERR; + } + return mismatch; +} +#endif + +//-------------------------------------------------------------------------- +debmod_t::debmod_t(void): +// ph(PH), + debugger_flags(0), + rpc(NULL), + debug_debugger(false), + is_dll(false), + sp_idx(-1), + pc_idx(-1), + fp_idx(-1), + nregs(0), + broken_connection(false), + pid(-1) +{ + debapp_attrs.platform = "UNDEFINED"; + proclist.clear(); +} + +//-------------------------------------------------------------------------- +bool debmod_t::same_as_oldmemcfg(const meminfo_vec_t &ranges) const +{ + return old_ranges == ranges; +} + +//-------------------------------------------------------------------------- +void debmod_t::save_oldmemcfg(const meminfo_vec_t &ranges) +{ + old_ranges = ranges; +} + +//-------------------------------------------------------------------------- +bool debmod_t::check_input_file_crc32(uint32 orig_crc) +{ + // take this opportunity to check that the derived class initialized + // register related fields correctly + QASSERT(30016, sp_idx != -1 && pc_idx != -1 && nregs > 0); + + if ( orig_crc == 0 ) + return true; // the database has no crc + + linput_t *li = open_linput(input_file_path.c_str(), false); + if ( li == NULL ) + return false; + + uint32 crc = calc_file_crc32(li); + close_linput(li); + return crc == orig_crc; +} + +//-------------------------------------------------------------------------- +const exception_info_t *debmod_t::find_exception(int code) +{ + for ( const exception_info_t *ei = exceptions.begin(); + ei != exceptions.end(); + ++ei ) + { + if ( ei->code == (uint)code ) + return ei; + } + return NULL; +} + +//-------------------------------------------------------------------------- +bool debmod_t::get_exception_name(int code, char *buf, size_t bufsize) +{ + const exception_info_t *ei = find_exception(code); + if ( ei != NULL ) + { + qstrncpy(buf, ei->name.c_str(), bufsize); + return true; + } + qsnprintf(buf, bufsize, "%08X", code); + return false; +} + +//---------------------------------------------------------------------- +int idaapi debmod_t::get_system_specific_errno(void) const +{ + // this code must be acceptable by winerr() +#ifdef __NT__ + return GetLastError(); +#else + return errno; +#endif +} + +//------------------------------------------------------------------------- +ssize_t debmod_t::dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va) +{ + if ( rpc == NULL || rpc->is_client ) + return dvnotif_client(code, format, va); + else + return dvnotif_rpc(code, rpc, format, va); +} + +//---------------------------------------------------------------------- +// Display a system error message. This function always returns false +bool debmod_t::deberr(const char *format, ...) +{ + if ( !debug_debugger ) + return false; + + int code = get_system_specific_errno(); + va_list va; + va_start(va, format); + dvnotif(0, rpc, format, va); + va_end(va); + dmsg(": %s\n", winerr(code)); + return false; +} + +//-------------------------------------------------------------------------- +// used to debug the debugger +void debmod_t::debdeb(const char *format, ...) +{ + if ( !debug_debugger ) + return; + + va_list va; + va_start(va, format); + dvnotif(0, rpc, format, va); + va_end(va); +} + +//-------------------------------------------------------------------------- +void debmod_t::cleanup(void) +{ + input_file_path.qclear(); + old_ranges.qclear(); + exceptions.qclear(); + clear_debug_names(); + handling_lowcnds.clear(); +#ifdef ENABLE_LOWCNDS + cndmap.clear(); +#endif + page_bpts.clear(); + pid = 0; + is_dll = false; +} + +//-------------------------------------------------------------------------- +void idaapi debmod_t::dbg_set_exception_info(const exception_info_t *table, int qty) +{ + exceptions.qclear(); + exceptions.reserve(qty); + for ( int i=0; i < qty; i++ ) + exceptions.push_back(*table++); +} + +//-------------------------------------------------------------------------- +char *debug_event_str(const debug_event_t *ev) +{ + static char buf[MAXSTR]; + return debug_event_str(ev, buf, sizeof(buf)); +} + +//-------------------------------------------------------------------------- +char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize) +{ + char *ptr = buf; + char *end = buf + bufsize; + ptr += qsnprintf(ptr, end-ptr, "%s ea=%a", + get_event_name(ev->eid()), + ev->ea); + switch ( ev->eid() ) + { + case PROCESS_STARTED: // New process started + case PROCESS_ATTACHED: // Attached to running process + case LIB_LOADED: // New library loaded + ptr += qsnprintf(ptr, end-ptr, " base=%a size=%a rebase=%a name=%s", + ev->modinfo().base, + ev->modinfo().size, + ev->modinfo().rebase_to, + ev->modinfo().name.c_str()); + break; + case PROCESS_EXITED: // Process stopped + case THREAD_EXITED: // Thread stopped + ptr += qsnprintf(ptr, end-ptr, " exit_code=%d", ev->exit_code()); + break; + case BREAKPOINT: // Breakpoint reached + ptr += qsnprintf(ptr, end-ptr, " hea=%a kea=%a", ev->bpt().hea, ev->bpt().kea); + break; + case EXCEPTION: // Exception + ptr += qsnprintf(ptr, end-ptr, " code=%x can_cont=%d ea=%a info=%s", + ev->exc().code, + ev->exc().can_cont, + ev->exc().ea, + ev->exc().info.c_str()); + break; + case THREAD_STARTED: // thread name + case LIB_UNLOADED: // Library unloaded + case INFORMATION: // User-defined information + APPCHAR(ptr, end, ' '); + APPEND(ptr, end, ev->info().c_str()); + break; + default: + break; + } + qsnprintf(ptr, end-ptr, " pid=%d tid=%d handled=%d", + ev->pid, + ev->tid, + ev->handled); + return buf; +} + +//-------------------------------------------------------------------------- +//lint -e{1536} Exposing low access member 'debmod_t::dn_names' +name_info_t *debmod_t::get_debug_names() +{ + return &dn_names; +} + +//-------------------------------------------------------------------------- +int debmod_t::set_debug_names() +{ + name_info_t *ni = get_debug_names(); + if ( ni->addrs.empty() ) + return 1; + int code = send_debug_names_to_ida( + ni->addrs.begin(), + ni->names.begin(), + (int)ni->addrs.size()); + clear_debug_names(); + return code; +} + +//-------------------------------------------------------------------------- +void debmod_t::clear_debug_names() +{ + if ( dn_names.addrs.empty() ) + return; + + typedef qvector<char *> charptr_vec_t; + charptr_vec_t::iterator it_end = dn_names.names.end(); + for ( charptr_vec_t::iterator it=dn_names.names.begin(); it != it_end; ++it ) + qfree(*it); + + dn_names.names.clear(); + dn_names.addrs.clear(); +} + +//-------------------------------------------------------------------------- +void debmod_t::save_debug_name(ea_t ea, const char *name) +{ + dn_names.addrs.push_back(ea); + dn_names.names.push_back(qstrdup(name)); +} + +//-------------------------------------------------------------------------- +ea_t debmod_t::find_debug_name(const char *name) const +{ + for ( size_t i = 0, size = dn_names.names.size(); i < size; i++ ) + { + if ( streq(name, dn_names.names[i]) ) + return dn_names.addrs[i]; + } + return BADADDR; +} + +//-------------------------------------------------------------------------- +bool debmod_t::continue_after_last_event(bool handled) +{ + last_event.handled = handled; + return dbg_continue_after_event(&last_event) == DRC_OK; +} + +//-------------------------------------------------------------------------- +// if there is an active control bpt at the exception address, +// unconditionally suspend the execution at it. continuing won't do any good +// even if the user told us to continue after all exceptions. +bool debmod_t::should_suspend_at_exception( + const debug_event_t *event, + const exception_info_t *ei) +{ + if ( ei == NULL || ei->break_on() ) + return true; + appcalls_t::const_iterator p = appcalls.find(event->tid); + if ( p == appcalls.end() ) + return false; + const call_contexts_t &ctxvec = p->second; + return !ctxvec.empty() && ctxvec.back().ctrl_ea == event->ea; +} + +//-------------------------------------------------------------------------- +bool debmod_t::should_stop_appcall(thid_t, const debug_event_t *event, ea_t ea) +{ + switch ( event->eid() ) + { + case EXCEPTION: + // exception on the stack (non-executable stack?) + if ( event->exc().ea == ea ) + return true; + // no break + case BREAKPOINT: + // reached the control breakpoint? + if ( event->ea == ea ) + return true; + default: + break; + } + return false; +} + +//-------------------------------------------------------------------------- +// return top of the stack range usable by appcall. usually it is equal to the +// current esp, unless the range below the stack pointer is not usable +// (for example, AMD64 ABI required the "red zone" not to be modified) +ea_t debmod_t::calc_appcall_stack(const regvals_t ®vals) +{ + return ea_t(regvals[sp_idx].ival); +} + +//-------------------------------------------------------------------------- +ea_t idaapi debmod_t::dbg_appcall( + ea_t func_ea, + thid_t tid, + int stkarg_nbytes, + const struct regobjs_t *regargs, + struct relobj_t *stkbytes, + struct regobjs_t *retregs, + qstring *errbuf, + debug_event_t *_event, + int options) +{ + enum + { + E_OK, // Success + E_READREGS, // Failed to read registers + E_NOSTACK, // Failed to allocate stack frame + E_REG_USED, // The calling convention refers to reserved registers + E_ARG_ALLOC, // Failed to allocate memory for stack arguments + E_WRITE_ARGS, // Failed to setup stack arguments + E_WRITE_REGS, // Failed to setup register arguments + E_HANDLE_EVENT,// Failed to handle debug event + E_DEBUG_EVENT, // Could not get debug events + E_RESUME, // Failed to resume the application + E_EXCEPTION, // An exception has occurred + E_APPCALL_FROM_EXC, // Cannot issue an AppCall if last event was an exception + E_TIMEOUT, // Timeout + }; + + static const char *const errstrs[] = + { + "success", + "failed to read registers", + "failed to allocate stack frame", + "the calling convention refers to reserved registers", + "failed to allocate memory for stack arguments", + "failed to setup stack arguments", + "failed to setup register arguments", + "failed to handle debug event", + "could not get debug events", + "failed to resume the application", + "an exception has occurred", + "last event was an exception, cannot perform an appcall", + "timeout", + }; + + // Save registers + regval_t rv; + + bool brk = false; + int err = E_OK; + + call_context_t &ctx = appcalls[tid].push_back(); + + regval_map_t call_regs; + ea_t args_sp = BADADDR; + do + { + // In Win32, when WaitForDebugEvent() returns an exception + // it seems that the OS remembers the exception context so that + // the next call to ContinueDebugEvent() will work with the last exception context. + // Now if we carry an AppCall when an exception was just reported: + // - Appcall will change context + // - Appcall's control bpt will generate an exception thus overriding the last exception context saved by the OS + // - After Appcall, IDA kernel cannot really continue from the first exception because it was overwritten + // Currently we will disallow Appcalls if last event is an exception + if ( last_event.eid() == EXCEPTION ) + { + err = E_APPCALL_FROM_EXC; + break; + } + // Save registers + ctx.saved_regs.resize(nregs); + if ( dbg_read_registers(tid, -1, ctx.saved_regs.begin(), NULL) != DRC_OK ) + { + err = E_READREGS; + break; + } + + // Get SP value + ea_t org_sp = calc_appcall_stack(ctx.saved_regs); + if ( org_sp == BADADDR ) + { + err = E_NOSTACK; + break; + } + + // Stack contents + bytevec_t stk; + + // Prepare control address + // We will generate a BP code ptrsz aligned and push unto the stack + // as the first argument. This is where we will set the control bpt. + // Since the bpt is on the stack, two possible scenarios: + // - BPT exception + // - Access violation: trying to execute from NX page + // In both cases we will catch an exception and learn what address was + // involved. + + // - Save the ctrl address + ea_t ctrl_ea = org_sp - debapp_attrs.addrsize; + + // - Compute the pointer where arguments will be allocated on the stack + size_t stkbytes_size = align_up(stkbytes->size(), debapp_attrs.addrsize); + args_sp = ctrl_ea - stkbytes_size; + + // align the stack pointer to 16 byte boundary (gcc compiled programs require it) + args_sp &= ~15; + ctx.ctrl_ea = args_sp + stkbytes_size; + + // Relocate the stack arguments + if ( !stkbytes->relocate(args_sp, false) ) + { + err = E_ARG_ALLOC; + break; + } + + // Prepare the stack. + // The memory layout @SP before transfering to the function: + // R = ret addr + // A = args + + // - Append the return address (its value is the value of the ctrl code address) + stk.append(&ctx.ctrl_ea, debapp_attrs.addrsize); + + // - Append the stack args + stk.append(stkbytes->begin(), stkbytes->size()); + stk.resize(debapp_attrs.addrsize+stkbytes_size); // align up + ctx.sp = args_sp - debapp_attrs.addrsize; + if ( ctx.sp >= org_sp ) + { // underflow? + err = E_NOSTACK; + break; + } + + int delta = finalize_appcall_stack(ctx, call_regs, stk); + ctx.sp += delta; // nbytes inserted at the beginning of stk + + // Write the stack + int nwrite = stk.size() - delta; + if ( nwrite > 0 ) + { + if ( dbg_write_memory(ctx.sp, stk.begin()+delta, nwrite, NULL) != nwrite ) + { + err = E_WRITE_ARGS; + break; + } + //show_hex(stk.begin()+delta, nwrite, "Written stack bytes to %a:\n", ctx.sp); + } + + // ask the debugger to set a breakpoint + dbg_add_bpt(NULL, BPT_SOFT, ctx.ctrl_ea, -1); + + // Copy arg registers to call_regs + for ( size_t i=0; i < regargs->size(); i++ ) + { + const regobj_t &ri = regargs->at(i); + int reg_idx = ri.regidx; + if ( reg_idx == sp_idx || reg_idx == pc_idx ) + { + brk = true; + err = E_REG_USED; + break; + } + + // Copy the register value + if ( ri.size() <= sizeof(rv.fval) ) + { + rv.clear(); + memcpy(&rv.fval, ri.value.begin(), ri.size()); + if ( ri.relocate ) + rv.ival += args_sp; + } + else + { + bytevec_t &b = rv.set_bytes(); + b.resize(ri.size()); + memcpy(b.begin(), ri.value.begin(), ri.size()); + rv.rvtype = 0; // custom data format + } + call_regs[reg_idx] = rv; + } + if ( brk ) + break; + + // Set the stack pointer + rv.clear(); + rv.ival = ctx.sp; + call_regs[sp_idx] = rv; + + // Set the instruction pointer + rv.ival = func_ea; + call_regs[pc_idx] = rv; + + // Change all the registers in question + for ( regval_map_t::iterator it = call_regs.begin(); + it != call_regs.end(); + ++it ) + { + if ( dbg_write_register(tid, it->first, &it->second, NULL) != DRC_OK ) + { + err = E_WRITE_REGS; + brk = true; + break; + } + // Mark that we changed the regs already + ctx.regs_spoiled = true; + } + if ( brk ) + break; + + // For manual appcall, we have done everything, just return now + if ( (options & APPCALL_MANUAL) != 0 ) + break; + + // Resume the application + // Since no* exception last occurred**, we can safely say that the + // debugger actually handled the exception. + // * : We disallow appcalls if an exception last occurred + // **: Actually if an AppCall was issued then last event is an exception + // but we will mask it by calling continue_after_event(handled_by_debugger = true) + if ( !continue_after_last_event(true) ) + { + err = E_RESUME; + break; + } + + // We use this list to accumulate the events + // We will give back the events at the end of the loop + debug_event_t tmp; + debug_event_t *event = _event != NULL ? _event : &tmp; + + // Determine timeout for get_debug_event() + uint64 endtime = 0; + int recalc_timeout = 0; // never recalc timeout + int timeout_ms = TIMEOUT; + if ( (options & APPCALL_TIMEOUT) != 0 ) + { + timeout_ms = GET_APPCALL_TIMEOUT(options); + if ( timeout_ms > 0 ) + { + endtime = get_nsec_stamp(); + endtime += timeout_ms * uint64(1000 * 1000); + } + recalc_timeout = 1; // recalc timeout after the first pass + } + + while ( true ) + { + if ( recalc_timeout ) + { + if ( recalc_timeout != 2 ) + { // we will recalc timeout at the next iteration + recalc_timeout = 2; + } + else + { + if ( timeout_ms > 0 ) + { + // calculate the remaining timeout + uint64 now = get_nsec_stamp(); + timeout_ms = int64(endtime - now) / int64(1000 * 1000); + } + if ( timeout_ms <= 0 ) + { // timeout out waiting for the appcall to finish + err = E_TIMEOUT; + if ( dbg_prepare_to_pause_process(NULL) <= DRC_NONE ) + break; // could not even prepare to pause, nothing we can do :( + } + } + } + // Wait for debug events + gdecode_t r = dbg_get_debug_event(event, timeout_ms); + if ( r == GDE_NO_EVENT ) + continue; + if ( r == GDE_ERROR ) + { // error getting debug event (network error, etc) + err = E_DEBUG_EVENT; + break; + } + + // We may get three possible events related to our control breakpoint: + // - Access violation type: because we try to execute non-executable code + // - Or a BPT exception if the stack page happens to be executable + // - Process exit + if ( event->eid() == PROCESS_EXITED // process is gone + || event->eid() == THREAD_EXITED && event->tid == tid ) // our thread is gone + { + send_debug_event_to_ida(event, RQ_SILENT); + args_sp = BADADDR; + brk = true; + break; + } + if ( err == E_TIMEOUT ) + { + send_debug_event_to_ida(event, RQ_SILENT|RQ_SUSPEND); + event->set_eid(NO_EVENT); + last_event.set_eid(NO_EVENT); + break; + } + if ( should_stop_appcall(tid, event, ctx.ctrl_ea) ) + { + last_event.set_eid(NO_EVENT); + break; + } + // Any other exception? + if ( event->eid() == EXCEPTION ) + { + if ( (options & APPCALL_DEBEV) == 0 ) + *errbuf = event->exc().info; // Copy exception text to the user + err = E_EXCEPTION; + // When an exception happens during the appcall, we want to mask + // the exception, because: + // 1. we reset the EIP to its original location + // 2. there is no exception handler for the appcall so we cannot really pass as unhandled + // FIXME + last_event.set_eid(NO_EVENT); + last_event.handled = true; + brk = true; + break; + } + + if ( send_debug_event_to_ida(event, RQ_SILENT|RQ_SUSPEND) != 0 ) + { + err = E_HANDLE_EVENT; + break; + } + dbg_continue_after_event(event); + event->set_eid(NO_EVENT); + } + + if ( brk || err != E_OK ) + break; + + // write the argument vector back because it could be spoiled by the application + if ( stkarg_nbytes > 0 ) + { + int nbytes = stkarg_nbytes; + if ( nbytes > stkbytes->size() // wrong parameters + || dbg_write_memory(args_sp, stkbytes->begin(), nbytes, NULL) != ssize_t(nbytes) ) + { + err = E_WRITE_ARGS; + break; + } + } + + // Retrieve the return value + if ( retregs != NULL && !retregs->empty() ) + { + regvals_t retr; + retr.resize(nregs); + if ( dbg_read_registers(tid, -1, retr.begin(), NULL) <= DRC_NONE ) + { + err = E_READREGS; + break; + } + for ( size_t i=0; i < retregs->size(); i++ ) + { + regobj_t &r = retregs->at(i); + regval_t &v = retr[r.regidx]; + memcpy(r.value.begin(), v.get_data(), r.value.size()); + r.relocate = false; + } + } + } while ( false ); + + if ( err != E_OK ) + { + if ( err != E_EXCEPTION ) + *errbuf = errstrs[err]; + dbg_cleanup_appcall(tid); + args_sp = BADADDR; + } + + return args_sp; +} + +//-------------------------------------------------------------------------- +// Cleanup after appcall() +// The debugger module must keep the stack blob in the memory until this function +// is called. It will be called by the kernel for each successful call_app_func() +drc_t idaapi debmod_t::dbg_cleanup_appcall(thid_t tid) +{ + appcalls_t::iterator p = appcalls.find(tid); + if ( p == appcalls.end() ) + return DRC_FAILED; + call_contexts_t &calls = p->second; + if ( calls.empty() ) + return DRC_FAILED; + + // remove the return breakpoint + call_context_t &ctx = calls.back(); + if ( !preprocess_appcall_cleanup(tid, ctx) ) + return DRC_FAILED; + + dbg_del_bpt(BPT_SOFT, ctx.ctrl_ea, bpt_code.begin(), bpt_code.size()); + if ( ctx.regs_spoiled ) + { + if ( !write_registers(tid, 0, ctx.saved_regs.size(), ctx.saved_regs.begin()) ) + { + dmsg("Failed to restore %" FMT_Z " registers!\n", ctx.saved_regs.size()); + return DRC_FAILED; + } + } + + calls.pop(); + if ( calls.empty() ) + appcalls.erase(p); + return events.empty() ? DRC_OK : DRC_EVENTS; +} + +//-------------------------------------------------------------------------- +drc_t debmod_t::resume_app_and_get_event(debug_event_t *dev) +{ + thid_t tid = dev->tid; + drc_t drc = dbg_continue_after_event(dev); + if ( drc > DRC_NONE ) + { + while ( true ) + { + gdecode_t gc = dbg_get_debug_event(dev, TIMEOUT_INFINITY); + if ( gc != GDE_NO_EVENT ) + break; + } + // is it in our thread? + if ( tid != dev->tid ) + { // very odd! an event from another thread arrived + if ( dev->eid() != THREAD_STARTED ) + dmsg("unexpected event from thread %d arrived (expected thread %d)\n", dev->tid, tid); + drc = DRC_FAILED; // indicate failure + } + } + return drc; +} + +//-------------------------------------------------------------------------- +drc_t debmod_t::dbg_perform_single_step(debug_event_t *dev, const insn_t &) +{ + // all other threads must be frozen at this moment + drc_t drc = dbg_set_resume_mode(dev->tid, RESMOD_INTO); + if ( drc > DRC_NONE ) + drc = resume_app_and_get_event(dev); + return drc; +} + +//-------------------------------------------------------------------------- +// returns true-lowcnd was false, resumed the application +// nb: recursive calls to this function are not handled in any special way! +bool debmod_t::handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags) +{ + if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 + || lc->type != BPT_SOFT && find_page_bpt(lc->ea, lc->size) != page_bpts.end() ) + { + // difficult case: we have to reset pc, remove the bpt, single step, and resume the app + QASSERT(616, !handling_lowcnds.has(lc->ea)); + handling_lowcnds.push_back(lc->ea); + + if ( (elc_flags & ELC_KEEP_EIP) == 0 ) + { + regval_t rv; + rv._set_int(lc->ea); + drc_t drc = dbg_write_register(event->tid, pc_idx, &rv, NULL); + if ( drc <= DRC_NONE ) + { + handling_lowcnds.del(lc->ea); + return false; + } + } + + int code = dbg_freeze_threads_except(event->tid); + if ( code > 0 ) + { + int bptlen = lc->type == BPT_SOFT ? lc->orgbytes.size() : lc->size; + code = dbg_del_bpt(lc->type, lc->ea, lc->orgbytes.begin(), bptlen); + if ( code > 0 ) + { + drc_t drc = dbg_perform_single_step(event, lc->cmd); + if ( drc <= DRC_NONE ) + { + code = 0; + dmsg("%a: failed to single step\n", event->ea); // may happen + } + + if ( dbg_add_bpt(NULL, lc->type, lc->ea, bptlen) <= 0 ) + { + // if this fails, it may be because the breakpoint is invalid + // at this time so we should notify IDA it isn't available + // any more + code = 0; + dwarning("%a: could not restore deleted bpt\n", lc->ea); // odd + } + } + if ( dbg_thaw_threads_except(event->tid) <= 0 ) + { + dwarning("%d: could not resume suspended threads\n", event->tid); // odd + code = 0; + } + } + handling_lowcnds.del(lc->ea); + if ( code <= 0 || event->eid() != STEP ) + return false; // did not resume + } + if ( (elc_flags & ELC_KEEP_SUSP) != 0 ) + return true; + return dbg_continue_after_event(event) > DRC_NONE; +} + +//-------------------------------------------------------------------------- +// return lowcnd_t if its condition is not satisfied +lowcnd_t *debmod_t::get_failed_lowcnd(thid_t tid, ea_t ea) +{ +#ifndef ENABLE_LOWCNDS + //lint -esym(1762, debmod_t::get_failed_lowcnd) could be made const + qnotused(tid); + qnotused(ea); +#else + lowcnds_t::iterator p = cndmap.find(ea); + if ( p != cndmap.end() ) + { + bool ok = true; + idc_value_t rv; + char name[32]; + ::qsnprintf(name, sizeof(name), "__lc%a", ea); + lowcnd_t &lc = p->second; + lock_begin(); + { + idc_debmod = this; // is required by compiler/interpreter + idc_thread = tid; // is required by interpreter + if ( !lc.compiled ) + { + ok = compile_idc_snippet(name, lc.cndbody.begin(), NULL, NULL, true); + if ( ok ) + lc.compiled = true; + } + if ( ok ) + ok = call_idc_func(&rv, name, NULL, 0); + } + lock_end(); + if ( !ok ) + { + report_idc_error(ea, get_qerrno(), get_error_data(0), get_error_string(0)); + return NULL; + } + + idcv_int64(&rv); + if ( rv.i64 == 0 ) + return &lc; // condition is not satisfied, resume + } +#endif + return NULL; +} + +//-------------------------------------------------------------------------- +bool debmod_t::evaluate_and_handle_lowcnd(debug_event_t *event, int elc_flags) +{ + bool resume = false; + if ( event->eid() == BREAKPOINT ) + { + ea_t ea = event->bpt().kea != BADADDR ? event->bpt().kea + : event->bpt().hea != BADADDR ? event->bpt().hea + : event->ea; + lowcnd_t *lc = get_failed_lowcnd(event->tid, ea); + if ( lc != NULL ) + { // condition is not satisfied, just make a single step and resume + debdeb("%a: bptcnd yielded false\n", ea); + event->handled = true; + QASSERT(617, !handling_lowcnds.has(ea)); + resume = handle_lowcnd(lc, event, elc_flags); + } + } + return resume; +} + +//-------------------------------------------------------------------------- +drc_t idaapi debmod_t::dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring * /*errbuf*/) +{ + return get_failed_lowcnd(tid, ea) == NULL ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +drc_t idaapi debmod_t::dbg_update_lowcnds( + int *nupdated, + const lowcnd_t *lowcnds, + int nlowcnds, + qstring * /*errbuf*/) +{ +#ifndef ENABLE_LOWCNDS + qnotused(lowcnds); + qnotused(nlowcnds); + if ( nupdated != NULL ) + *nupdated = 0; + return DRC_OK; +#else + for ( int i=0; i < nlowcnds; i++, lowcnds++ ) + { + ea_t ea = lowcnds->ea; + if ( lowcnds->cndbody.empty() ) + cndmap.erase(ea); + else + cndmap[ea] = *lowcnds; + } + if ( nupdated != NULL ) + *nupdated = nlowcnds; + return DRC_OK; +#endif +} + +//-------------------------------------------------------------------------- +// determine the future bpt size and read the original instruction from memory. +// if necessary, the bpt address may be adjusted. +// return the number of read bytes. +// this function is overloaded in arm debugger subclasses. +int debmod_t::read_bpt_orgbytes(bytevec_t *buf, ea_t ea, int len) +{ + buf->qclear(); + if ( (debugger_flags & DBG_FLAG_CAN_CONT_BPT) == 0 ) + { // we must save the original bytes before adding the bpt + buf->resize(len); + if ( dbg_read_memory(ea, buf->begin(), len, NULL) <= 0 ) + return -1; + } + else + { // if the debuger can itself continue from bpts, + // orgbytes will not be used by the kernel. however + // we must return something because non-empty orgbytes mean + // that a soft bpt is active. we return zeroes in b->orgbytes. + buf->resize(len, 0); + } + return len; +} + +//-------------------------------------------------------------------------- +drc_t idaapi debmod_t::dbg_update_bpts( + int *nbpts, + update_bpt_info_t *ubpts, + int nadd, + int ndel, + qstring * /*errbuf*/) +{ + if ( events.empty() ) + deleted_bpts.clear(); + + // Write breakpoints to the process + int cnt = 0; + update_bpt_info_t *b; + update_bpt_info_t *end = ubpts + nadd; + for ( b=ubpts; b != end; b++ ) + { + int code = b->code; + if ( code != BPT_OK ) + continue; // should be BPT_SKIP + + int len = b->type == BPT_SOFT ? bpt_code.size() : b->size; + ea_t ea = b->ea; + if ( b->type == BPT_SOFT ) + adjust_swbpt(&ea, &len); + + update_bpt_vec_t::iterator d = deleted_bpts.find(*b); + if ( d != deleted_bpts.end() && d->tid == b->tid ) + deleted_bpts.erase(d); + + code = dbg_add_bpt(&b->orgbytes, b->type, ea, len); + debdeb("dbg_add_bpt(type=%d, ea=%a, len=%d) => %d\n", b->type, ea, len, code); + switch ( code ) + { + case 2: + code = BPT_PAGE_OK; + break; + case 1: + code = BPT_OK; + break; + default: + code = BPT_WRITE_ERROR; + break; + case -2: + code = BPT_READ_ERROR; + break; + } + + b->code = code; + if ( code == BPT_OK || code == BPT_PAGE_OK ) + cnt++; + } + + // Delete breakpoints from the process. + end += ndel; + for ( ; b != end; b++ ) + { + b->code = BPT_OK; + int len = b->type == BPT_SOFT ? b->orgbytes.size() : b->size; + int code = dbg_del_bpt(b->type, b->ea, b->orgbytes.begin(), len); + debdeb("dbg_del_bpt(type=%d, ea=%a) => %d\n", b->type, b->ea, code); + if ( code > 0 ) + { + cnt++; + if ( b->type == BPT_SOFT || b->type == BPT_EXEC ) + deleted_bpts.push_back(*b); + } + else + { + b->code = BPT_WRITE_ERROR; + } + } + + if ( nbpts != NULL ) + *nbpts = cnt; + return DRC_OK; +} + +//-------------------------------------------------------------------------- +// Find a page breakpoint that would cause an exception on the given range +// NB: we do not check the user-specified range but the real page range! +page_bpts_t::iterator debmod_t::find_page_bpt( + ea_t ea, + int size) +{ + page_bpts_t::iterator p = page_bpts.lower_bound(calc_page_base(ea)); + if ( p == page_bpts.end() || p->first >= ea+size ) + { + if ( p == page_bpts.begin() ) + return page_bpts.end(); // not found + --p; + } + ea_t page_ea = p->first; + int page_len = p->second.aligned_len; + if ( !interval::overlap(ea, size, page_ea, page_len) ) + p = page_bpts.end(); + return p; +} + +//-------------------------------------------------------------------------- +bool debmod_t::del_page_bpt(ea_t ea, bpttype_t type) +{ + page_bpts_t::iterator p = find_page_bpt(ea); + if ( p == page_bpts.end() ) + return false; // could not find + if ( p->second.ea != ea || p->second.type != type ) + return false; // not exact match + + dbg_enable_page_bpt(p, false); + page_bpts.erase(p); + return true; +} + +//-------------------------------------------------------------------------- +void debmod_t::enable_page_bpts(bool enable) +{ + for ( page_bpts_t::iterator p = page_bpts.begin(); p != page_bpts.end(); ++p ) + dbg_enable_page_bpt(p, enable); +} + +//-------------------------------------------------------------------------- +void debmod_t::set_platform(const char *platform_name) +{ + debapp_attrs.platform = platform_name; +} + +//-------------------------------------------------------------------------- +void debmod_t::dbg_get_debapp_attrs(debapp_attrs_t *out_pattrs) const +{ + *out_pattrs = debapp_attrs; +} + +//-------------------------------------------------------------------------- +bool debmod_t::restore_broken_breakpoints(void) +{ + debmodbpt_map_t::const_iterator p; + for ( p = bpts.begin(); p != bpts.end(); ++p ) + { + const debmod_bpt_t &bpt = p->second; + if ( !dbg_write_memory(bpt.ea, bpt.saved, bpt.nsaved, NULL) ) + msg("Failed to restore broken breakpoint at 0x%a\n", bpt.ea); + } + bpts.clear(); + return true; +} + + +//-------------------------------------------------------------------------- +void debmod_t::log_exception( + const debug_event_t *ev, + const exception_info_t *ei) +{ + if ( ei == NULL || (ei->flags & EXC_SILENT) == 0 ) + { + if ( ev->exc().ea != BADADDR ) + { + dmsg("%a: %s -> %a (exc.code %x, tid %d)\n", + ev->ea, ev->exc().info.c_str(), ev->exc().ea, ev->exc().code, ev->tid); + } + else + { + dmsg("%a: %s (exc.code %x, tid %d)\n", + ev->ea, ev->exc().info.c_str(), ev->exc().code, ev->tid); + } + } +} + +//-------------------------------------------------------------------------- +int idaapi debmod_t::dbg_rexec(const char *cmdline) +{ + msg("REXEC: %s\n", cmdline); + return call_system(cmdline); +} + +//-------------------------------------------------------------------------- +drc_t idaapi debmod_t::dbg_get_processes(procinfo_vec_t *procs, qstring *errbuf) +{ + proclist.qclear(); + get_process_list(&proclist, errbuf); + + size_t size = proclist.size(); + procs->qclear(); + procs->reserve(size); + for ( size_t i = 0; i < size; i++ ) + { + process_info_t &procinf = procs->push_back(); + proclist[i].copy_to(&procinf); + } + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +int idaapi debmod_t::get_process_list(procvec_t *list, qstring *) +{ + list->clear(); + return -1; +} + +//-------------------------------------------------------------------------- +uint64 debmod_t::probe_file_size(int fn, uint64 step) +{ + uint64 low = 0; + uint64 high = step; + char dummy; + while ( dbg_read_file(fn, high-1, &dummy, 1) == 1 ) + { + low = high; + high += step; + if ( step < 0x7FFFFFFFFFFFFFFFULL ) + step *= 2; + } + while ( low+1 < high ) + { + int middle = (high+low)/2; + if ( dbg_read_file(fn, middle-1, &dummy, 1) == 1 ) + low = middle; + else + high = middle; + } + return low; +} diff --git a/idasdk76/dbg/debmod.h b/idasdk76/dbg/debmod.h new file mode 100644 index 0000000..fcb57e4 --- /dev/null +++ b/idasdk76/dbg/debmod.h @@ -0,0 +1,739 @@ +#ifndef __DEBUGGER_MODULE__ +#define __DEBUGGER_MODULE__ + +// +// +// This is the base debmod_t class definition +// From this class all debugger code must inherite and specialize +// +// Some OS specific functions must be implemented: +// bool init_subsystem(); +// bool term_subsystem(); +// debmod_t *create_debug_session(void *); +// int create_thread(thread_cb_t thread_cb, void *context); +// + +#include <deque> + +#include <pro.h> +#include <idd.hpp> +#include <network.hpp> + +//-------------------------------------------------------------------------- +extern debugger_t debugger; + +//-------------------------------------------------------------------------- +struct name_info_t +{ + eavec_t addrs; + qvector<char *> names; + void clear(void) + { + addrs.clear(); + names.clear(); + } +}; + +//-------------------------------------------------------------------------- +// Extended process info +struct ext_process_info_t : public process_info_t +{ + int addrsize; // process bitness 32bit - 4, 64bit - 8, 0 - unknown + qstring ext_name; // human-readable name (e.g. with command line agrs) + void copy_to(process_info_t *dst) + { + dst->pid = pid; + dst->name = ext_name.empty() ? name : ext_name; + } +}; +typedef qvector<ext_process_info_t> procvec_t; + +//-------------------------------------------------------------------------- +// Very simple class to store pending events +enum queue_pos_t +{ + IN_FRONT, + IN_BACK +}; + +//-------------------------------------------------------------------------- +struct pagebpt_data_t +{ + ea_t ea; // address of the bpt as specified by the user + ea_t page_ea; // real address of the bpt as written to the process + int user_len; // breakpoint length as specified by the user + int aligned_len; // breakpoint length aligned to the page size + int real_len; // real length of the breakpoint as written to the process + uint32 old_prot; // old page protections (before writing the bpt to the process) + // if 0, the bpt has not been written to the process yet. + uint32 new_prot; // new page protections (when the bpt is active) + bpttype_t type; // breakpoint type +}; + +// Information about page breakpoints is stored in this data structure. +// The map is indexed by the page start address (not the address specified +// by the user!) +typedef std::map<ea_t, pagebpt_data_t> page_bpts_t; // page_ea -> bpt info +typedef qvector<page_bpts_t::iterator> pbpt_iterators_t; // list of iterators into page_bpts_t + +//-------------------------------------------------------------------------- +// set of addresses +typedef std::set<ea_t> easet_t; + +//------------------------------------------------------------------------- +class idc_value_t; +class rpc_engine_t; +error_t idaapi idc_get_reg_value(idc_value_t *argv, idc_value_t *r); +error_t idaapi idc_set_reg_value(idc_value_t *argv, idc_value_t *r); +void report_idc_error(rpc_engine_t *rpc, ea_t ea, error_t code, ssize_t errval, const char *errprm); + +// IDC function name that is exported by a debugger module +// to allow scripts to send debugger commands +#define IDC_SENDDBG_CMD "send_dbg_command" +#define IDC_READ_MSR "read_msr" +#define IDC_WRITE_MSR "write_msr" +#define IDC_STEP_BACK "step_back" +#define IDC_SET_TEV "set_current_tev" +#define IDC_GET_TEV "get_current_tev" + +// A macro to convert a pointer to ea_t without sign extension. +#define EA_T(ptr) (ea_t)(size_t)(ptr) + +//-------------------------------------------------------------------------- +//-V:debmod_bpt_t:730 not all members of a class are initialized inside the constructor: saved +struct debmod_bpt_t +{ + ea_t ea; + uchar saved[8]; // size of the biggest supported bpt size (PPC64) + uchar nsaved; + int bid; // (epoc) breakpoint id (from TRK) + debmod_bpt_t() : ea(BADADDR), nsaved(0), bid(0) {} + debmod_bpt_t(ea_t _ea, uchar _nsaved) : ea(_ea), nsaved(_nsaved), bid(0) { QASSERT(1796, nsaved < sizeof(saved)); } +}; +typedef std::map<ea_t, debmod_bpt_t> debmodbpt_map_t; + +//-------------------------------------------------------------------------- +struct eventlist_t : public std::deque<debug_event_t> +{ +public: + // save a pending event + void enqueue(const debug_event_t &ev, queue_pos_t pos) + { + if ( pos != IN_BACK ) + push_front(ev); + else + push_back(ev); + } + + // retrieve a pending event + bool retrieve(debug_event_t *event) + { + if ( empty() ) + return false; + // get the first event and return it + *event = front(); + pop_front(); + return true; + } +}; + +//-------------------------------------------------------------------------- +int send_ioctl(rpc_engine_t *rpc, int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize); +int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty); +int send_debug_event_to_ida(const debug_event_t *ev, int rqflags); +void set_arm_thumb_modes(ea_t *addrs, int qty); +char *debug_event_str(const debug_event_t *ev, char *buf, size_t bufsize); +char *debug_event_str(const debug_event_t *ev); // returns static buf + +//-------------------------------------------------------------------------- +// describes a dll to be imported +struct import_request_t +{ + ea_t base; + qstring path; + bytevec_t uuid; + import_request_t(ea_t _base, const qstring &_path, const bytevec_t &_uuid) + : base(_base), path(_path), uuid(_uuid) {} +}; +DECLARE_TYPE_AS_MOVABLE(import_request_t); +typedef qvector<import_request_t> import_infos_t; +int import_dll(const import_request_t &req); + +//-------------------------------------------------------------------------- +struct regctx_t; + +//-------------------------------------------------------------------------- +struct regctx_entry_t +{ + enum type_t + { + IVAL = 0, + FVAL = 1, + DATA = 2, + FUNC = 3, + } type; + int reg_class; + int reg_idx; + union + { + struct + { + size_t offset_in_ctx; + size_t size_in_ctx; + size_t reg_size; + }; + struct + { + void (*read_func)(const regctx_t *, regval_t *, void *); + void (*write_func)(regctx_t *, const regval_t *, void *); + void *user_data; + }; + }; + + uint64_t truncate_ival(uint64_t ival) const + { + switch ( reg_size ) + { + case 1: ival = uint8_t(ival); break; + case 2: ival = uint16_t(ival); break; + case 4: ival = uint32_t(ival); break; + } + return ival; + } + + void read(regval_t *value, const uint8_t *ptr) const + { + if ( type == regctx_entry_t::FUNC ) + { + read_func((regctx_t *) ptr, value, user_data); + } + else + { + const uint8_t *p = ptr + offset_in_ctx; + switch ( type ) + { + case regctx_entry_t::IVAL: + { + uint64_t ival = 0; + switch ( size_in_ctx ) + { + case 1: ival = *(uint8_t *)p; break; + case 2: ival = *(uint16_t *)p; break; + case 4: ival = *(uint32_t *)p; break; + case 8: ival = *(uint64_t *)p; break; + } + ival = truncate_ival(ival); + value->ival = ival; + } + break; + case regctx_entry_t::FVAL: + // TODO: for x86, the value is converted to IEEE format in + // x86_read_registers(). clean this up somehow. + memcpy(&value->fval, p, size_in_ctx); + value->rvtype = RVT_FLOAT; + break; + case regctx_entry_t::DATA: + value->set_bytes(p, size_in_ctx); + break; + case regctx_entry_t::FUNC: + // never happens; makes compiler happy. + break; + } + } + } + + bool patch(uint8_t *ptr, const regval_t *value) const + { + if ( type == regctx_entry_t::FUNC ) + { + write_func((regctx_t *) ptr, value, user_data); + } + else + { + uint8_t *p = ptr + offset_in_ctx; + switch ( type ) + { + case regctx_entry_t::IVAL: + { + uint64_t ival = value->ival; + ival = truncate_ival(ival); + switch ( size_in_ctx ) + { + case 1: *(uint8_t *)p = ival; break; + case 2: *(uint16_t *)p = ival; break; + case 4: *(uint32_t *)p = ival; break; + case 8: *(uint64_t *)p = ival; break; + } + } + break; + case regctx_entry_t::FVAL: + // TODO: for x86, the value is converted from IEEE format in + // x86_write_register(). clean this up somehow. + memcpy(p, &value->fval, size_in_ctx); + break; + case regctx_entry_t::DATA: + if ( value->get_data_size() != size_in_ctx ) + return false; + memcpy(p, value->get_data(), value->get_data_size()); + break; + case regctx_entry_t::FUNC: + // never happens; makes compiler happy. + break; + } + } + return true; + } +}; +DECLARE_TYPE_AS_MOVABLE(regctx_entry_t); +typedef qvector<regctx_entry_t> reg_ctx_entries_t; + +//-------------------------------------------------------------------------- +struct regctx_base_t +{ + dynamic_register_set_t &idaregs; // linked to debmod_t's variable of the same name + thid_t tid; + int clsmask; + + reg_ctx_entries_t entries; + + void setup(thid_t _tid, int _clsmask=0) + { + tid = _tid; + clsmask = _clsmask; + } + + void setup_reg(int dyn_reg_idx) + { + clsmask |= entries[dyn_reg_idx].reg_class; + } + + regctx_base_t(dynamic_register_set_t &_idaregs) + : idaregs(_idaregs) + { + setup(0, 0); + } + + void add_idareg(register_info_t &ri) + { + idaregs.add_register(ri.name, + ri.flags, + ri.dtype, + ri.register_class, + ri.bit_strings, + ri.default_bit_strings_mask); + } + + size_t add_entry( + regctx_entry_t::type_t type, + register_info_t &ri, + size_t offset_in_ctx, + size_t size_in_ctx, + size_t reg_size) + { + size_t dyn_reg_idx = entries.size(); + regctx_entry_t &entry = entries.push_back(); + entry.type = type; + entry.reg_class = ri.register_class; + entry.reg_idx = dyn_reg_idx; + entry.offset_in_ctx = offset_in_ctx; + entry.size_in_ctx = size_in_ctx; + entry.reg_size = reg_size; + add_idareg(ri); + return dyn_reg_idx; + } + + size_t add_ival(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx) + { + QASSERT(1797, size_in_ctx <= sizeof(regval_t::ival)); + size_t reg_size = ri.dtype == dt_word ? 2 + : ri.dtype == dt_dword ? 4 + : ri.dtype == dt_qword ? 8 + : 0; + QASSERT(1798, reg_size != 0); + return add_entry(regctx_entry_t::IVAL, ri, offset_in_ctx, size_in_ctx, reg_size); + } + + size_t add_fval(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx) + { + QASSERT(1799, size_in_ctx <= sizeof(regval_t::fval)); + return add_entry(regctx_entry_t::FVAL, ri, offset_in_ctx, size_in_ctx, size_in_ctx); + } + + size_t add_data(register_info_t &ri, size_t offset_in_ctx, size_t size_in_ctx) + { + return add_entry(regctx_entry_t::DATA, ri, offset_in_ctx, size_in_ctx, size_in_ctx); + } + + size_t add_func( + register_info_t &ri, + void (*read_func)(const regctx_t *, regval_t *, void *), + void (*write_func)(regctx_t *, const regval_t *, void *), + void *user_data=nullptr) + { + size_t dyn_reg_idx = entries.size(); + regctx_entry_t &entry = entries.push_back(); + entry.type = regctx_entry_t::FUNC; + entry.reg_class = ri.register_class; + entry.reg_idx = dyn_reg_idx; + entry.read_func = read_func; + entry.write_func = write_func; + entry.user_data = user_data; + add_idareg(ri); + return dyn_reg_idx; + } + + void read_all(regval_t *values) + { + for ( const regctx_entry_t &entry: entries ) + if ( (clsmask & entry.reg_class) != 0 ) + entry.read(&values[entry.reg_idx], (const uint8_t *) this); + } + + bool patch(int dyn_reg_idx, const regval_t *value) + { + return entries[dyn_reg_idx].patch((uint8_t *) this, value); + } +}; + +//-------------------------------------------------------------------------- +// Main class to represent a debugger module +class debmod_t +{ +protected: +// processor_t &ph; + typedef std::map<int, regval_t> regval_map_t; + qvector<exception_info_t> exceptions; + name_info_t dn_names; + // Pending events. currently used only to store + // exceptions that happen while attaching + eventlist_t events; + // The last event received via a successful get_debug_event() + debug_event_t last_event; + + // debugged process attributes (may be changed after process start/attach) + debapp_attrs_t debapp_attrs; + + procvec_t proclist; + + // appcall contexts + struct call_context_t + { + regvals_t saved_regs; + ea_t sp; + ea_t ctrl_ea; + bool regs_spoiled; + call_context_t() : sp(BADADDR), ctrl_ea(BADADDR), regs_spoiled(false) {} + }; + typedef qstack<call_context_t> call_contexts_t; + typedef std::map<thid_t, call_contexts_t> appcalls_t; + appcalls_t appcalls; + + int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) + { + return ::send_ioctl(rpc, fn, buf, size, poutbuf, poutsize); + } + // If an IDC error occurs: we cannot prepare an error message on the server + // side because we do not have access to error strings (they are in ida.hlp). + // We pass the error code to IDA (with eventual arguments) so it can prepare + // a nice error message for the user + void report_idc_error(ea_t ea, error_t code, ssize_t errval, const char *errprm) + { + return ::report_idc_error(rpc, ea, code, errval, errprm); + } + + typedef std::map<ea_t, lowcnd_t> lowcnds_t; + lowcnds_t cndmap; + eavec_t handling_lowcnds; + bool evaluate_and_handle_lowcnd(debug_event_t *event, int elc_flags=0); + bool handle_lowcnd(lowcnd_t *lc, debug_event_t *event, int elc_flags); +#define ELC_KEEP_EIP 0x0001 // do not reset eip before stepping +#define ELC_KEEP_SUSP 0x0002 // keep suspended state, do not resume after stepping + + // helper functions for programmatical single stepping + virtual drc_t dbg_perform_single_step(debug_event_t *event, const insn_t &ins); + virtual int dbg_freeze_threads_except(thid_t) { return 0; } + virtual int dbg_thaw_threads_except(thid_t) { return 0; } + drc_t resume_app_and_get_event(debug_event_t *dev); + void set_platform(const char *platform_name); + + // return number of processes, -1 - not implemented + virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf); + +public: + // initialized by dbg_init() + int debugger_flags; + meminfo_vec_t old_ranges; + rpc_engine_t *rpc; + bool debug_debugger; + // Is dynamic library? + bool is_dll; + + // indexes of sp and program counter registers. + // Must be initialized by derived classes. + int sp_idx; + int pc_idx; + + // index of frame pointer register + int fp_idx; + + // Total number of registers. + // Must be initialized by derived classes. + int nregs; + + // Breakpoint code. + // Must be initialized by derived classes. + bytevec_t bpt_code; + + qstring input_file_path; + + page_bpts_t page_bpts; + + // will either send as msg/warning/error through callui, + // or through 'rpc' if it is present. + DEFINE_ALL_NOTIFICATION_FUNCTIONS(rpc); + AS_PRINTF(3,0) static ssize_t dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va); + + bool broken_connection; + pid_t pid; + + debmodbpt_map_t bpts; + update_bpt_vec_t deleted_bpts; // deleted bpts in the last update_bpts() call + // if bpt EA was deleted then bpt raised in the same place for the + // same thread does not belong to IDA + bool is_ida_bpt(ea_t ea, thid_t tid) + { + if ( bpts.find(ea) != bpts.end() ) + return true; + update_bpt_info_t b; + b.ea = ea; + return deleted_bpts.find(b) != deleted_bpts.end() + && (last_event.eid() != BREAKPOINT + || last_event.ea != ea + || last_event.tid != tid); + } + + static bool reuse_broken_connections; + + //------------------------------------ + // Dynamic register set for debugger_t + //------------------------------------ + dynamic_register_set_t idaregs; + + //------------------------------------ + // Constructors and destructors + //------------------------------------ + debmod_t(); + virtual ~debmod_t() { cleanup(); } + + //------------------------------------ + // Debug names methods + //------------------------------------ + void clear_debug_names(); + name_info_t *get_debug_names(); + void save_debug_name(ea_t ea, const char *name); + int set_debug_names(); + int send_debug_names_to_ida(ea_t *addrs, const char *const *names, int qty); + int send_debug_event_to_ida(const debug_event_t *ev, int rqflags); + ea_t find_debug_name(const char *name) const; + //------------------------------------ + // Utility methods + //------------------------------------ + void cleanup(void); + AS_PRINTF(2, 3) void debdeb(const char *format, ...); + AS_PRINTF(2, 3) bool deberr(const char *format, ...); + bool same_as_oldmemcfg(const meminfo_vec_t &ranges) const; + void save_oldmemcfg(const meminfo_vec_t &ranges); + bool continue_after_last_event(bool handled = true); + lowcnd_t *get_failed_lowcnd(thid_t tid, ea_t ea); + page_bpts_t::iterator find_page_bpt(ea_t ea, int size=1); + bool del_page_bpt(ea_t ea, bpttype_t type); + void enable_page_bpts(bool enable); + ea_t calc_page_base(ea_t ea) { return align_down(ea, dbg_memory_page_size()); } + void log_exception(const debug_event_t *ev, const exception_info_t *ei); + uint64 probe_file_size(int fn, uint64 step); + void set_input_path(const char *input_path); + int read_bpt_orgbytes(bytevec_t *buf, ea_t ea, int len); + + //------------------------------------ + // Shared methods + //------------------------------------ + virtual bool check_input_file_crc32(uint32 orig_crc); + virtual const exception_info_t *find_exception(int code); + virtual bool get_exception_name(int code, char *buf, size_t bufsize); + virtual drc_t idaapi dbg_get_processes(procinfo_vec_t *info, qstring *errbuf); + + //------------------------------------ + // Methods to be implemented + //------------------------------------ + virtual void idaapi dbg_set_debugging(bool _debug_debugger) = 0; + virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) = 0; + virtual void idaapi dbg_term(void) = 0; + virtual drc_t idaapi dbg_detach_process(void) = 0; + virtual drc_t idaapi dbg_start_process( + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf) = 0; + virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_msecs) = 0; + virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) = 0; + virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) = 0; + virtual drc_t idaapi dbg_exit_process(qstring *errbuf) = 0; + virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) = 0; + virtual void idaapi dbg_set_exception_info(const exception_info_t *info, int qty); + virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) = 0; + virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) = 0; + virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) = 0; + virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) = 0; + virtual drc_t idaapi dbg_read_registers( + thid_t thread_id, + int clsmask, + regval_t *values, + qstring *errbuf) = 0; + virtual drc_t idaapi dbg_write_register( + thid_t thread_id, + int reg_idx, + const regval_t *value, + qstring *errbuf) = 0; + virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) = 0; + virtual ea_t idaapi map_address(ea_t ea, const regval_t *, int /* regnum */) { return ea; } + virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) = 0; + virtual int idaapi dbg_get_scattered_image(scattered_image_t & /*si*/, ea_t /*base*/) { return -1; } + virtual bool idaapi dbg_get_image_uuid(bytevec_t * /*uuid*/, ea_t /*base*/) { return false; } + virtual ea_t idaapi dbg_get_segm_start(ea_t /*base*/, const qstring & /*segname*/) { return BADADDR; } + virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) = 0; + virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) = 0; + virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) = 0; + // for swbpts, len may be -1 (unknown size, for example arm/thumb mode) or bpt opcode length + // dbg_add_bpt returns 2 if it adds a page bpt + virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) = 0; + virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) = 0; + virtual drc_t idaapi dbg_update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf); + virtual int idaapi dbg_add_page_bpt(bpttype_t /*type*/, ea_t /*ea*/, int /*size*/) { return 0; } + virtual bool idaapi dbg_enable_page_bpt(page_bpts_t::iterator /*p*/, bool /*enable*/) { return false; } + virtual drc_t idaapi dbg_update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf); + virtual drc_t idaapi dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf); + virtual int idaapi dbg_open_file(const char * /*file*/, uint64 * /*fsize*/, bool /*readonly*/) { return -1; } + virtual void idaapi dbg_close_file(int /*fn*/) {} + virtual ssize_t idaapi dbg_read_file(int /*fn*/, qoff64_t /*off*/, void * /*buf*/, size_t /*size*/) { return 0; } + virtual ssize_t idaapi dbg_write_file(int /*fn*/, qoff64_t /*off*/, const void * /*buf*/, size_t /*size*/) { return 0; } + virtual int idaapi handle_ioctl( + int /*fn*/, + const void * /*buf*/, + size_t /*size*/, + void ** /*outbuf*/, + ssize_t * /*outsize*/) + { + return 0; + } + virtual int idaapi get_system_specific_errno(void) const; // this code must be acceptable by winerr() + virtual drc_t idaapi dbg_update_call_stack(thid_t, call_stack_t *) { return DRC_NONE; } + virtual ea_t idaapi dbg_appcall( + ea_t /*func_ea*/, + thid_t /*tid*/, + int /*stkarg_nbytes*/, + const struct regobjs_t * /*regargs*/, + struct relobj_t * /*stkargs*/, + struct regobjs_t * /*retregs*/, + qstring *errbuf, + debug_event_t * /*event*/, + int /*flags*/); + virtual drc_t idaapi dbg_cleanup_appcall(thid_t /*tid*/); + virtual bool idaapi write_registers( + thid_t /*tid*/, + int /*start*/, + int /*count*/, + const regval_t * /*values*/) + { + return false; + } + // finalize appcall stack image + // input: stack image contains the return address at the beginning + virtual int finalize_appcall_stack(call_context_t &, regval_map_t &, bytevec_t &) { return 0; } + virtual ea_t calc_appcall_stack(const regvals_t ®vals); + virtual bool should_stop_appcall(thid_t tid, const debug_event_t *event, ea_t ea); + virtual bool should_suspend_at_exception(const debug_event_t *event, const exception_info_t *ei); + virtual bool preprocess_appcall_cleanup(thid_t, call_context_t &) { return true; } + virtual int get_regidx(const char *regname, int *clsmask) = 0; + virtual uint32 dbg_memory_page_size(void) { return 0x1000; } + virtual bool idaapi dbg_prepare_broken_connection(void) { return false; } + virtual bool idaapi dbg_continue_broken_connection(pid_t) { old_ranges.clear(); return true; } + virtual bool idaapi dbg_enable_trace(thid_t, bool, int) { return false; } + virtual bool idaapi dbg_is_tracing_enabled(thid_t, int) { return false; } + virtual int idaapi dbg_rexec(const char *cmdline); + virtual void adjust_swbpt(ea_t *, int *) {} + virtual void dbg_get_debapp_attrs(debapp_attrs_t *out_pattrs) const; + virtual bool idaapi dbg_get_srcinfo_path(qstring * /*path*/, ea_t /*base*/) const { return false; } + virtual bool import_dll(const import_request_t & /*req*/) { return false; } + virtual drc_t idaapi dbg_bin_search( + ea_t *ea, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &ptns, + int srch_flags, + qstring *errbuf); + + bool restore_broken_breakpoints(void); + void set_addr_size(int size) { debapp_attrs.addrsize = size; } + void set_endianness(bool is_be) { debapp_attrs.is_be = is_be; } +}; + +//--------------------------------------------------------------------------- + +// +// Some functions, per OS implemented +// +bool init_subsystem(); +bool term_subsystem(); +debmod_t *create_debug_session(void *params); + +// +// Processor specific init/term +// +void processor_specific_init(void); +void processor_specific_term(void); + +// Perform an action on all existing debugger modules +struct debmod_visitor_t +{ + virtual int visit(debmod_t *debmod) = 0; +}; +int for_all_debuggers(debmod_visitor_t &v); + + +// +// Utility functions +// + +// Common method between MacOS and Linux to launch a process +drc_t idaapi maclnx_launch_process( + debmod_t *debmod, + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + void **child_pid, + qstring *errbuf); + +bool add_idc_funcs(const struct ext_idcfunc_t funcs[], size_t nfuncs, bool reg); + +// +// Externs +// +extern debmod_t *idc_debmod; +extern thid_t idc_thread; +extern bool ignore_sigint; + +//--------------------------------------------------------------------------- +// server.cpp +bool lock_begin(); +bool lock_end(); + +// bool srv_lock_begin(void); +// bool srv_lock_end(void); + +#endif diff --git a/idasdk75/dbg/exceptions.cfg b/idasdk76/dbg/exceptions.cfg similarity index 100% rename from idasdk75/dbg/exceptions.cfg rename to idasdk76/dbg/exceptions.cfg diff --git a/idasdk75/dbg/linux/android.cpp b/idasdk76/dbg/linux/android.cpp similarity index 100% rename from idasdk75/dbg/linux/android.cpp rename to idasdk76/dbg/linux/android.cpp diff --git a/idasdk75/dbg/linux/android.hpp b/idasdk76/dbg/linux/android.hpp similarity index 100% rename from idasdk75/dbg/linux/android.hpp rename to idasdk76/dbg/linux/android.hpp diff --git a/idasdk75/dbg/linux/armlinux_stub.cpp b/idasdk76/dbg/linux/armlinux_stub.cpp similarity index 100% rename from idasdk75/dbg/linux/armlinux_stub.cpp rename to idasdk76/dbg/linux/armlinux_stub.cpp diff --git a/idasdk76/dbg/linux/linux_debmod.cpp b/idasdk76/dbg/linux/linux_debmod.cpp new file mode 100644 index 0000000..67425c5 --- /dev/null +++ b/idasdk76/dbg/linux/linux_debmod.cpp @@ -0,0 +1,3693 @@ +/* +* This is a userland linux debugger module +* +* Functions unique for Linux +* +* It can be compiled by gcc +* +*/ + +//#define LDEB // enable debug print in this module + +#include <sys/syscall.h> +#include <pthread.h> +#include <dirent.h> + +#include <pro.h> +#include <prodir.h> +#include <fpro.h> +#include <err.h> +#include <ida.hpp> +#include <idp.hpp> +#include <idd.hpp> +#include <name.hpp> +#include <bytes.hpp> +#include <loader.hpp> +#include <diskio.hpp> +#include <network.hpp> + +#include "symelf.hpp" +#include "linux_debmod.h" + +#ifdef __ANDROID__ +# include <linux/elf.h> +# include "android.hpp" +# include "android.cpp" +#else +# include <link.h> +#endif + +//-------------------------------------------------------------------------- +// Load IDA register sets. +#ifdef __ARM__ +# include "arm_regs.hpp" +# define arch_registers arm_registers +#else +# include "pc_regs.hpp" +# define arch_registers x86_registers +#endif + +//-------------------------------------------------------------------------- +// Define some ptrace() requests if they're not available. +#ifndef PTRACE_GETREGSET +# define PTRACE_GETREGSET __ptrace_request(0x4204) +# define PTRACE_SETREGSET __ptrace_request(0x4205) +#endif + +#ifdef __HAVE_ARM_VFP__ +# ifndef PTRACE_GETVFPREGS +# define PTRACE_GETVFPREGS __ptrace_request(27) +# define PTRACE_SETVFPREGS __ptrace_request(28) +# endif +#endif + +#if !defined(__ARM__) && !defined(__X86__) && !defined(PTRACE_ARCH_PRCTL) +# define PTRACE_ARCH_PRCTL __ptrace_request(30) +#endif + +//-------------------------------------------------------------------------- +// ARM breakpoint codes. +#ifdef __ARM__ +static const uchar thumb16_bpt[] = { 0x10, 0xDE }; // UND #10 +// we must use 32-bit breakpoints for 32bit instructions inside IT blocks (thumb mode) +// if we use a 16-bit breakpoint and the processor decides to skip it +// because the condition codes are not satisfied, we will end up skipping +// only half of the original 32-bit instruction +static const uchar thumb32_bpt[] = { 0xF0, 0xF7, 0x00, 0xA0 }; +// This bit is combined with the software bpt size to indicate +// that 32bit bpt code should be used. +#define USE_THUMB32_BPT 0x80 +static const uchar aarch64_bpt[] = AARCH64_BPT_CODE; +#endif + +//-------------------------------------------------------------------------- +#if defined(__HAVE_ARM_VFP__) && !defined(__ANDROID__) +struct user_vfp +{ + int64 fpregs[32]; + int32 fpscr; +}; +#endif + +//-------------------------------------------------------------------------- +#ifdef __ARM__ +# if defined(__X86__) +# define user_regs_struct user_regs +# define PCREG uregs[15] +# else // arm64 +# define user_regs_struct user_pt_regs +# define LRREG_IDX 30 +# endif +#else // __ARM__ +# if defined(__X86__) +# define SPREG esp +# define PCREG eip +# define XMM_STRUCT x387 +# define TAGS_REG twd +# define INTEL_REG(reg) e##reg +# define INTEL_SREG(reg) x##reg +# else // x64 +# define SPREG rsp +# define PCREG rip +# define XMM_STRUCT i387 +# define TAGS_REG ftw +# define INTEL_REG(reg) r##reg +# define INTEL_SREG(reg) reg +# endif +#endif + +//-------------------------------------------------------------------------- +#ifdef TESTABLE_BUILD +typedef const char *per_pid_elf_dbgdir_resolver_t(int pid); +static per_pid_elf_dbgdir_resolver_t *per_pid_elf_dbgdir_resolver = nullptr; +#endif + +//-------------------------------------------------------------------------- +// ptrace() uses long as part of its API and we want to use that, so we +// tell lint to ignore it. +//lint -esym(970,long) use of modifier or type 'long' outside of a typedef + +//-------------------------------------------------------------------------- +linux_debmod_t::linux_debmod_t(void) : + ta(nullptr), + complained_shlib_bpt(false), + process_handle(INVALID_HANDLE_VALUE), + thread_handle(INVALID_HANDLE_VALUE), + exited(false), + mapfp(nullptr), + npending_signals(0), + may_run(false), + requested_to_suspend(false), + in_event(false), + nptl_base(BADADDR), + reg_ctx(nullptr) +{ + prochandle.pid = NO_PROCESS; + set_platform("linux"); +} + +#pragma GCC diagnostic ignored "-Wswitch" // case values do not belong to... + +#ifdef LDEB +//-------------------------------------------------------------------------- +const char *get_ptrace_name(__ptrace_request request) +{ + switch ( request ) + { + case PTRACE_TRACEME: return "PTRACE_TRACEME"; /* Indicate that the process making this request should be traced. + All signals received by this process can be intercepted by its + parent, and its parent can use the other `ptrace' requests. */ + case PTRACE_PEEKTEXT: return "PTRACE_PEEKTEXT"; /* Return the word in the process's text space at address ADDR. */ + case PTRACE_PEEKDATA: return "PTRACE_PEEKDATA"; /* Return the word in the process's data space at address ADDR. */ + case PTRACE_PEEKUSER: return "PTRACE_PEEKUSER"; /* Return the word in the process's user area at offset ADDR. */ + case PTRACE_POKETEXT: return "PTRACE_POKETEXT"; /* Write the word DATA into the process's text space at address ADDR. */ + case PTRACE_POKEDATA: return "PTRACE_POKEDATA"; /* Write the word DATA into the process's data space at address ADDR. */ + case PTRACE_POKEUSER: return "PTRACE_POKEUSER"; /* Write the word DATA into the process's user area at offset ADDR. */ + case PTRACE_CONT: return "PTRACE_CONT"; /* Continue the process. */ + case PTRACE_KILL: return "PTRACE_KILL"; /* Kill the process. */ + case PTRACE_SINGLESTEP: return "PTRACE_SINGLESTEP"; /* Single step the process. This is not supported on all machines. */ +#if !defined(__ARM__) || defined(__X86__) + case PTRACE_GETREGS: return "PTRACE_GETREGS"; /* Get all general purpose registers used by a processes. This is not supported on all machines. */ + case PTRACE_SETREGS: return "PTRACE_SETREGS"; /* Set all general purpose registers used by a processes. This is not supported on all machines. */ + case PTRACE_GETFPREGS: return "PTRACE_GETFPREGS"; /* Get all floating point registers used by a processes. This is not supported on all machines. */ + case PTRACE_SETFPREGS: return "PTRACE_SETFPREGS"; /* Set all floating point registers used by a processes. This is not supported on all machines. */ +#endif + case PTRACE_ATTACH: return "PTRACE_ATTACH"; /* Attach to a process that is already running. */ + case PTRACE_DETACH: return "PTRACE_DETACH"; /* Detach from a process attached to with PTRACE_ATTACH. */ +#if !defined(__ARM__) + case PTRACE_GETFPXREGS: return "PTRACE_GETFPXREGS"; /* Get all extended floating point registers used by a processes. This is not supported on all machines. */ + case PTRACE_SETFPXREGS: return "PTRACE_SETFPXREGS"; /* Set all extended floating point registers used by a processes. This is not supported on all machines. */ +#endif + case PTRACE_SYSCALL: return "PTRACE_SYSCALL"; /* Continue and stop at the next (return from) syscall. */ +#if defined(__ARM__) && defined(__X86__) + case PTRACE_GETVFPREGS: return "PTRACE_GETVFPREGS"; /* Get all vfp registers used by a processes. This is not supported on all machines. */ + case PTRACE_SETVFPREGS: return "PTRACE_SETVFPREGS"; /* Set all vfp registers used by a processes. This is not supported on all machines. */ +#endif + case PTRACE_SETOPTIONS: return "PTRACE_SETOPTIONS"; /* Set ptrace filter options. */ + case PTRACE_GETEVENTMSG: return "PTRACE_GETEVENTMSG"; /* Get last ptrace message. */ + case PTRACE_GETSIGINFO: return "PTRACE_GETSIGINFO"; /* Get siginfo for process. */ + case PTRACE_SETSIGINFO: return "PTRACE_SETSIGINFO"; /* Set new siginfo for process. */ + case PTRACE_GETREGSET: return "PTRACE_GETREGSET"; /* Get register content. */ + case PTRACE_SETREGSET: return "PTRACE_SETREGSET"; /* Set register content. */ +#ifdef PTRACE_SEIZE + case PTRACE_SEIZE: return "PTRACE_SEIZE"; /* Like PTRACE_ATTACH, but do not force tracee to trap and do not affect signal or group stop state. */ + case PTRACE_INTERRUPT: return "PTRACE_INTERRUPT"; /* Trap seized tracee. */ + case PTRACE_LISTEN: return "PTRACE_LISTEN"; /* Wait for next group event. */ + case PTRACE_PEEKSIGINFO: return "PTRACE_PEEKSIGINFO"; /* Wait for next group event. */ + case PTRACE_GETSIGMASK: return "PTRACE_GETSIGMASK"; /* Wait for next group event. */ + case PTRACE_SETSIGMASK: return "PTRACE_SETSIGMASK"; /* Wait for next group event. */ +#endif +#if !defined(__ARM__) && !defined(__X86__) + case PTRACE_ARCH_PRCTL: return "PTRACE_ARCH_PRCTL"; //lint !e2444 case value is not in enumeration +#endif + default: + static char buf[MAXSTR]; + qsnprintf(buf, sizeof(buf), "%d", request); + return buf; + } +} +#endif + +//-------------------------------------------------------------------------- +// fixme: can we use peeksize_t instead? +static long qptrace(__ptrace_request request, pid_t pid, void *addr, void *data) +{ + long code = ptrace(request, pid, addr, data); +#ifdef LDEB + if ( request != PTRACE_PEEKTEXT + && request != PTRACE_PEEKUSER + && (request != PTRACE_POKETEXT + && request != PTRACE_POKEDATA +#if !defined(__ARM__) || defined(__X86__) + && request != PTRACE_GETREGS + && request != PTRACE_SETREGS + && request != PTRACE_GETFPREGS + && request != PTRACE_SETFPREGS +#endif +#if defined(__ARM__) && defined(__X86__) + && request != PTRACE_GETVFPREGS + && request != PTRACE_SETVFPREGS +#endif +#if !defined(__ARM__) + && request != PTRACE_SETFPXREGS + && request != PTRACE_GETFPXREGS +#endif + || code != 0) ) + { +// int saved_errno = errno; +// msg("%s(%u, 0x%X, 0x%X) => 0x%X\n", get_ptrace_name(request), pid, addr, data, code); +// errno = saved_errno; + } +#endif + return code; +} + +//-------------------------------------------------------------------------- +#ifdef LDEB +GCC_DIAG_OFF(format-nonliteral); +void linux_debmod_t::log(thid_t tid, const char *format, ...) +{ + if ( tid != -1 ) + { + thread_info_t *thif = get_thread(tid); + if ( thif == NULL ) + { + msg(" %d: ** missing **\n", tid); + } + else + { + const char *name = "?"; + switch ( thif->state ) + { + case RUNNING: name = "RUN "; break; + case STOPPED: name = "STOP"; break; + case DYING: name = "DYIN"; break; + case DEAD: name = "DEAD"; break; + } + msg(" %d: %s %c%c S=%d U=%d ", + thif->tid, + name, + thif->waiting_sigstop ? 'W' : ' ', + thif->got_pending_status ? 'P' : ' ', + thif->suspend_count, + thif->user_suspend); + } + } + va_list va; + va_start(va, format); + vmsg(format, va); + va_end(va); +} + +static const char *strevent(int status) +{ + int event = status >> 16; + if ( WIFSTOPPED(status) + && WSTOPSIG(status) == SIGTRAP + && event != 0 ) + { + switch ( event ) + { + case PTRACE_EVENT_FORK: + return " event=PTRACE_EVENT_FORK"; + case PTRACE_EVENT_VFORK: + return " event=PTRACE_EVENT_VFORK"; + case PTRACE_EVENT_CLONE: + return " event=PTRACE_EVENT_CLONE"; + case PTRACE_EVENT_EXEC: + return " event=PTRACE_EVENT_EXEC"; + case PTRACE_EVENT_VFORK_DONE: + return " event=PTRACE_EVENT_VFORK_DONE"; + case PTRACE_EVENT_EXIT: + return " event=PTRACE_EVENT_EXIT"; + default: + return " UNKNOWN event"; + } + } + return ""; +} + +static char *status_dstr(int status) +{ + static char buf[80]; + if ( WIFSTOPPED(status) ) + { + int sig = WSTOPSIG(status); + ::qsnprintf(buf, sizeof(buf), "stopped(%s)%s", strsignal(sig), strevent(status)); + } + else if ( WIFSIGNALED(status) ) + { + int sig = WTERMSIG(status); + ::qsnprintf(buf, sizeof(buf), "terminated(%s)", strsignal(sig)); + } + else if ( WIFEXITED(status) ) + { + int code = WEXITSTATUS(status); + ::qsnprintf(buf, sizeof(buf), "exited(%d)", code); + } + else + { + ::qsnprintf(buf, sizeof(buf), "status=%x\n", status); + } + return buf; +} + +static void ldeb(const char *format, ...) +{ + va_list va; + va_start(va, format); + vmsg(format, va); + va_end(va); +} +GCC_DIAG_OFF(format-nonliteral); + +#else +//lint -estring(750,status_dstr, strevent) not referenced +#define log(tid, format, args...) +#define ldeb(format, args...) do {} while ( 0 ) +#define status_dstr(status) "?" +#define strevent(status) "" +#endif + +//-------------------------------------------------------------------------- +static int qkill(int pid, int signo) +{ + ldeb("%d: sending signal %s\n", pid, signo == SIGSTOP ? "SIGSTOP" + : signo == SIGKILL ? "SIGKILL" : ""); + int ret; + errno = 0; + static bool tkill_failed = false; + if ( !tkill_failed ) + { + ret = syscall(__NR_tkill, pid, signo); + if ( ret != 0 && errno == ENOSYS ) + { + errno = 0; + tkill_failed = true; + } + } + if ( tkill_failed ) + ret = kill(pid, signo); + if ( ret != 0 ) + ldeb(" %s\n", strerror(errno)); + return ret; +} + +//-------------------------------------------------------------------------- +inline thread_info_t *linux_debmod_t::get_thread(thid_t tid) +{ + threads_t::iterator p = threads.find(tid); + if ( p == threads.end() ) + return NULL; + return &p->second; +} + +#define X86_XSTATE_SSE_SIZE 576 +// #define X86_XSTATE_AVX_SIZE 832 +// #define X86_XSTATE_BNDREGS_SIZE 1024 +// #define X86_XSTATE_BNDCFG_SIZE 1088 +// #define X86_XSTATE_AVX512_SIZE 2688 +// #define X86_XSTATE_PKRU_SIZE 2696 +#define X86_XSTATE_MAX_SIZE 2696 + +//------------------------------------------------------------------------- +static int _has_ptrace_getregset = -1; +static bool has_ptrace_getregset(thid_t tid) +{ + if ( _has_ptrace_getregset < 0 ) + { +#if defined(__ARM__) + uint8_t xstateregs[sizeof(struct user_regs_struct)]; +# define _TEST_PTRACE_OP NT_PRSTATUS +#else + uint8_t xstateregs[X86_XSTATE_SSE_SIZE]; +# define _TEST_PTRACE_OP NT_X86_XSTATE +#endif + struct iovec iov; + iov.iov_base = xstateregs; + iov.iov_len = sizeof(xstateregs); + _has_ptrace_getregset = qptrace(PTRACE_GETREGSET, tid, (void *) _TEST_PTRACE_OP, &iov) == 0; +#undef _TEST_PTRACE_OP + } + return _has_ptrace_getregset > 0; +} + +//------------------------------------------------------------------------- +inline bool qptrace_get_regset(struct iovec *out, size_t what, thid_t tid) +{ + if ( !has_ptrace_getregset(tid) ) + return false; + return qptrace(PTRACE_GETREGSET, tid, (void *) what, out) == 0; +} + +//------------------------------------------------------------------------- +inline bool qptrace_get_regset(void *out, size_t outsz, size_t what, thid_t tid) +{ + struct iovec iov = { out, outsz }; + return qptrace_get_regset(&iov, what, tid); +} + +//------------------------------------------------------------------------- +inline bool qptrace_set_regset(size_t what, thid_t tid, struct iovec &iov) +{ + // we'll assume that if a platform exposes 'PTRACE_GETREGSET' + // it also exposes 'PTRACE_SETREGSET'. + if ( !has_ptrace_getregset(tid) ) + return false; + return qptrace(PTRACE_SETREGSET, tid, (void *) what, &iov) == 0; +} + +//------------------------------------------------------------------------- +inline bool qptrace_set_regset(size_t what, thid_t tid, void *in, size_t insz) +{ + struct iovec iov = { in, insz }; + return qptrace_set_regset(what, tid, iov); +} + +//-------------------------------------------------------------------------- +#if defined(__ARM__) && !defined(__X86__) +inline bool qptrace_get_prstatus(struct user_regs_struct *regset, thid_t tid) +{ + return qptrace_get_regset(regset, sizeof(struct user_regs_struct), NT_PRSTATUS, tid); +} +#endif + +//-------------------------------------------------------------------------- +static ea_t get_ip(thid_t tid) +{ + ea_t ea; +#if defined(__ARM__) && !defined(__X86__) + struct user_regs_struct regset; + ea = qptrace_get_prstatus(®set, tid) ? regset.pc : BADADDR; +#else + const size_t pcreg_off = qoffsetof(user, regs) + qoffsetof(user_regs_struct, PCREG); + // In case 64bit IDA (__EA64__=1) is debugging a 32bit process: + // - size of ea_t is 64 bit + // - qptrace() returns a 32bit long value + // Here we cast the return value to unsigned long to prevent + // extending of the sign bit when convert 32bit long value to 64bit ea_t + ea = (unsigned long)qptrace(PTRACE_PEEKUSER, tid, (void *)pcreg_off, 0); +#endif + return ea; +} + +#include "linux_threads.cpp" + +//-------------------------------------------------------------------------- +#ifndef __ARM__ +static unsigned long get_dr(thid_t tid, int idx) +{ + uchar *offset = (uchar *)qoffsetof(user, u_debugreg) + idx*sizeof(unsigned long int); + unsigned long value = qptrace(PTRACE_PEEKUSER, tid, (void *)offset, 0); + // msg("dr%d => %a\n", idx, value); + return value; +} + +//-------------------------------------------------------------------------- +static bool set_dr(thid_t tid, int idx, ea_t ea) +{ + uchar *offset = (uchar *)qoffsetof(user, u_debugreg) + idx*sizeof(unsigned long int); + + if ( ea == BADADDR ) + ea = 0; // linux does not accept too high values + unsigned long value = ea; + // msg("dr%d <= %a\n", idx, value); + return qptrace(PTRACE_POKEUSER, tid, offset, (void *)value) == 0; +} +#endif + +//-------------------------------------------------------------------------- +bool linux_debmod_t::del_pending_event(event_id_t id, const char *module_name) +{ + for ( eventlist_t::iterator p=events.begin(); p != events.end(); ++p ) + { + if ( p->eid() == id && p->modinfo().name == module_name ) + { + events.erase(p); + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::enqueue_event(const debug_event_t &ev, queue_pos_t pos) +{ + if ( ev.eid() != NO_EVENT ) + { + events.enqueue(ev, pos); + may_run = false; + ldeb("enqueued event, may not run!\n"); + } +} + +//-------------------------------------------------------------------------- +static inline void resume_dying_thread(int tid, int) +{ + qptrace(PTRACE_CONT, tid, 0, (void *)0); +} + +//-------------------------------------------------------------------------- +// we got a signal that does not belong to our thread. find the target thread +// and store the signal there +void linux_debmod_t::store_pending_signal(int _pid, int status) +{ + struct ida_local linux_signal_storer_t : public debmod_visitor_t + { + int pid; + int status; + linux_signal_storer_t(int p, int s) : pid(p), status(s) {} + virtual int visit(debmod_t *debmod) override + { + linux_debmod_t *ld = (linux_debmod_t *)debmod; + threads_t::iterator p = ld->threads.find(pid); + if ( p != ld->threads.end() ) + { + thread_info_t &ti = p->second; + // normally we should not receive a new signal unless the process or the thread + // exited. the exit signals may occur even if there is a pending signal. + QASSERT(30185, !ti.got_pending_status || ld->exited || WIFEXITED(status)); + if ( ti.waiting_sigstop && WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP ) + { + ti.waiting_sigstop = false; + ld->set_thread_state(ti, STOPPED); + } + else + { + ti.got_pending_status = true; + ti.pending_status = status; + ld->npending_signals++; + } + return 1; // stop + } + else + { + // we are handling an event from a thread we recently removed, ignore this + if ( ld->deleted_threads.has(pid) ) + { + // do not store the signal but resume the thread and let it finish + resume_dying_thread(pid, status); + return 1; + } + } + + return 0; // continue + } + }; + linux_signal_storer_t lss(_pid, status); + if ( !for_all_debuggers(lss) ) // uses lock_begin(), lock_end() to protect common data + { + if ( WIFSTOPPED(status) ) + { + // we can get SIGSTOP for the new-born lwp before the parent get it + // store pid to mark that we should not wait for SIGSTOP anymore + seen_threads.push_back(_pid); + } + else if ( !WIFSIGNALED(status) ) + { + // maybe it comes from a zombie? + // if we terminate the process, there might be some zombie threads remaining(?) + msg(" %d: failed to store pending status %x, killing unknown thread\n", _pid, status); + qptrace(PTRACE_KILL, _pid, 0, 0); + } + } +} + +//-------------------------------------------------------------------------- +inline bool is_bpt_status(int status) +{ + if ( !WIFSTOPPED(status) ) + return false; + int sig = WSTOPSIG(status); +#ifdef __ARM__ + return sig == SIGTRAP || sig == SIGILL; +#else + return sig == SIGTRAP; +#endif +} + +//-------------------------------------------------------------------------- +// check if there are any pending signals for our process +bool linux_debmod_t::retrieve_pending_signal(pid_t *p_pid, int *status) +{ + if ( npending_signals == 0 ) + return false; + + lock_begin(); + + // try to stick to the same thread as before + threads_t::iterator p = threads.find(last_event.tid); + if ( p != threads.end() ) + { + thread_info_t &ti = p->second; + if ( !ti.got_pending_status || ti.user_suspend > 0 || ti.suspend_count > 0 ) + p = threads.end(); + } + + // find a thread with a signal. + if ( p == threads.end() ) + { + for ( int i=0; i < 3; i++ ) + { + for ( p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + if ( ti.user_suspend > 0 || ti.suspend_count > 0 ) + continue; + if ( ti.got_pending_status ) + { + // signal priorities: STEP, SIGTRAP, others + if ( i == 0 ) + { + if ( !ti.single_step ) + continue; + } + else if ( i == 1 ) + { + if ( !is_bpt_status(ti.pending_status) ) + continue; + } + break; + } + } + } + } + + bool got_pending_signal = false; + if ( p != threads.end() ) + { + *p_pid = p->first; + *status = p->second.pending_status; + p->second.got_pending_status = false; + got_pending_signal = true; + npending_signals--; + QASSERT(30186, npending_signals >= 0); + ldeb("-------------------------------\n"); + log(p->first, "qwait (pending signal): %s (may_run=%d)\n", status_dstr(*status), may_run); + } + lock_end(); + return got_pending_signal; +} + +//-------------------------------------------------------------------------- +// read a zero terminated string. try to avoid reading unreadable memory +bool linux_debmod_t::read_asciiz(tid_t tid, ea_t ea, char *buf, size_t bufsize, bool suspend) +{ + while ( bufsize > 0 ) + { + int pagerest = 4096 - (ea % 4096); // number of bytes remaining on the page + int nread = qmin(pagerest, bufsize); + if ( !suspend && nread > 128 ) + nread = 128; // most paths are short, try to read only 128 bytes + nread = _read_memory(tid, ea, buf, nread, suspend); + if ( nread < 0 ) + return false; // failed + + // did we read a zero byte? + for ( int i=0; i < nread; i++ ) + if ( buf[i] == '\0' ) + return true; + + ea += nread; + buf += nread; + bufsize -= nread; + } + return true; // odd, we did not find any zero byte. should we report success? +} + +//-------------------------------------------------------------------------- +// may add/del threads! +bool linux_debmod_t::gen_library_events(int /*tid*/) +{ + int s = events.size(); + meminfo_vec_t miv; + if ( get_memory_info(miv, false) == 1 ) + handle_dll_movements(miv); + return events.size() != s; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::handle_hwbpt(debug_event_t *event) +{ +#ifdef __ARM__ + qnotused(event); +#else + + uint32 dr6_value = get_dr(event->tid, 6); + for ( int i=0; i < MAX_BPT; i++ ) + { + if ( dr6_value & (1<<i) ) // Hardware breakpoint 'i' + { + if ( hwbpt_ea[i] == get_dr(event->tid, i) ) + { + bptaddr_t &addr = event->set_bpt(); + addr.hea = hwbpt_ea[i]; + addr.kea = BADADDR; + set_dr(event->tid, 6, 0); // Clear the status bits + return true; + } + } + } +#endif + return false; +} + +//-------------------------------------------------------------------------- +inline ea_t calc_bpt_event_ea(const debug_event_t *event) +{ +#ifdef __ARM__ + if ( event->exc().code == SIGTRAP || event->exc().code == SIGILL ) + return event->ea; +#else + if ( event->exc().code == SIGTRAP ) +// || event->exc().code == SIGSEGV ) // NB: there was a bug in linux 2.6.10 when int3 was reported as SIGSEGV instead of SIGTRAP + { + return event->ea - 1; // x86 reports the address after the bpt + } +#endif + return BADADDR; +} + +//-------------------------------------------------------------------------- +inline void linux_debmod_t::set_thread_state(thread_info_t &ti, thstate_t state) const +{ + ti.state = state; +} + +//-------------------------------------------------------------------------- +static __inline void clear_tbit(thid_t tid) +{ +#ifdef __ARM__ + qnotused(tid); + return; +#else + + struct user_regs_struct regs; + if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) + { + msg("clear_tbit: error reading registers for thread %d\n", tid); + return; + } + + if ( (regs.eflags & 0x100) != 0 ) + { + regs.eflags &= ~0x100; + if ( qptrace(PTRACE_SETREGS, tid, 0, ®s) != 0 ) + msg("clear_tbit: error writting registers for thread %d\n", tid); + } + +#endif +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::check_for_new_events(chk_signal_info_t *csi, bool *event_prepared) +{ + if ( event_prepared != NULL ) + *event_prepared = false; + + while ( true ) + { + // even if we have pending events, check for new events first. + // this improves multithreaded debugging experience because + // we stick to the same thread (hopefully a new event arrives fast enough + // if we are single stepping). if we first check pending events, + // the user will be constantly switched from one thread to another. + csi->pid = check_for_signal(&csi->status, -1, 0); + if ( csi->pid <= 0 ) + { // no new events, do we have any pending events? + if ( retrieve_pending_signal(&csi->pid, &csi->status) ) + { + // check for extended event, + // if any the debugger event can be prepared + handle_extended_wait(event_prepared, *csi); + break; + } + // if the timeout was zero, nothing else to do + if ( csi->timeout_ms == 0 ) + return false; + // ok, we will wait for new events for a while + csi->pid = check_for_signal(&csi->status, -1, csi->timeout_ms); + if ( csi->pid <= 0 ) + return false; + } + ldeb("-------------------------------\n"); + log(csi->pid, " => qwait: %s\n", status_dstr(csi->status)); + + // check for extended event, + // if any the debugger event can be prepared + handle_extended_wait(event_prepared, *csi); + + if ( threads.find(csi->pid) != threads.end() ) + break; + + // when an application creates many short living threads we may receive events + // from a thread we already removed so, do not store this pending signal, just + // ignore it + if ( !deleted_threads.has(csi->pid) ) + { + // we are not interested in this pid + log(csi->pid, "storing status %d\n", csi->status); + store_pending_signal(csi->pid, csi->status); + } + else + { + // do not store the signal but resume the thread and let it finish + resume_dying_thread(csi->pid, csi->status); + } + csi->timeout_ms = 0; + } + return true; +} + +//-------------------------------------------------------------------------- +// timeout in microseconds +// 0 - no timeout, return immediately +// -1 - wait forever +// returns: 1-ok, 0-failed +int linux_debmod_t::get_debug_event(debug_event_t *event, int timeout_ms) +{ + chk_signal_info_t csi(timeout_ms); + + // even if we have pending events, check for new events first. + bool event_ready = false; + if ( !check_for_new_events(&csi, &event_ready) ) + return false; + + pid_t tid = csi.pid; + int status = csi.status; + + thread_info_t *thif = get_thread(tid); + if ( thif == NULL ) + { + // not our thread?! + debdeb("EVENT FOR UNKNOWN THREAD %d, IGNORED...\n", tid); + size_t sig = WIFSTOPPED(status) ? WSTOPSIG(status) : 0; + qptrace(PTRACE_CONT, tid, 0, (void*)(sig)); + return false; + } + QASSERT(30057, thif->state != STOPPED || exited || WIFEXITED(status) || WIFSIGNALED(status)); + + event->tid = NO_EVENT; // start with empty event + + // if there was a pending event, it means that previously we did not resume + // any threads, all of them are suspended + set_thread_state(*thif, STOPPED); + + dbg_freeze_threads(NO_THREAD); + may_run = false; + + // debugger event could be prepared during the check_for_new_events + if ( event_ready ) + goto EVENT_READY; // report empty event to get called back immediately + + // dbg_freeze_threads may delete some threads and render our 'thif' pointer invalid + thif = get_thread(tid); + if ( thif == NULL ) + { + debdeb("thread %d disappeared after freezing?!...\n", tid); + goto EVENT_READY; // report empty event to get called back immediately + } + + event->pid = process_handle; + event->tid = tid; + if ( exited ) + { + event->ea = BADADDR; + } + else if ( WIFSIGNALED(status) ) + { + siginfo_t info; + qptrace(PTRACE_GETSIGINFO, tid, NULL, &info); + event->ea = (ea_t)(size_t)info.si_addr; + } + else + { + event->ea = get_ip(event->tid); + } + event->handled = false; + if ( WIFSTOPPED(status) ) + { + ea_t proc_ip; + bool suspend; + const exception_info_t *ei; + int code = WSTOPSIG(status); + excinfo_t &exc = event->set_exception(); + exc.code = code; + exc.can_cont = true; + exc.ea = BADADDR; + if ( code == SIGSTOP ) + { + if ( thif->waiting_sigstop ) + { + log(tid, "got pending SIGSTOP!\n"); + thif->waiting_sigstop = false; + goto RESUME; // silently resume the application + } + // convert SIGSTOP into simple PROCESS_SUSPENDED, this will avoid + // a dialog box about the signal. I'm not sure that this is a good thing + // (probably better to report exceptions in the output windows rather than + // in dialog boxes), so I'll comment it out for the moment. + //event->eid = PROCESS_SUSPENDED; + } + + ei = find_exception(code); + if ( ei != NULL ) + { + exc.info.sprnt("got %s signal (%s)", ei->name.c_str(), ei->desc.c_str()); + suspend = should_suspend_at_exception(event, ei); + if ( !suspend && ei->handle() ) + code = 0; // mask the signal + } + else + { + exc.info.sprnt("got unknown signal #%d", code); + suspend = true; + } + proc_ip = calc_bpt_event_ea(event); // if bpt, calc its address from event->ea + if ( proc_ip != BADADDR ) + { // this looks like a bpt-related exception. it occurred either because + // of our bpt either it was generated by the app. + // by default, reset the code so we don't send any SIGTRAP signal to the debugged + // process *except* in the case where the program generated the signal by + // itself + code = 0; + if ( proc_ip == shlib_bpt.bpt_addr && shlib_bpt.bpt_addr != 0 ) + { + log(tid, "got shlib bpt %a\n", proc_ip); + // emulate return from function + if ( !emulate_retn(tid) ) + { + msg("%a: could not return from the shlib breakpoint!\n", proc_ip); + return true; + } + if ( !gen_library_events(tid) ) // something has changed in shared libraries? + { // no, nothing has changed + log(tid, "nothing has changed in dlls\n"); +RESUME: + if ( !requested_to_suspend && !in_event ) + { + ldeb("autoresuming\n"); +// QASSERT(30177, thif->state == STOPPED); + resume_app(NO_THREAD); + return false; + } + log(tid, "app may not run, keeping it suspended (%s)\n", + requested_to_suspend ? "requested_to_suspend" : + in_event ? "in_event" : "has_pending_events"); + event->set_eid(PROCESS_SUSPENDED); + return true; + } + log(tid, "gen_library_events ok\n"); + event->set_eid(NO_EVENT); + } + else if ( (proc_ip == birth_bpt.bpt_addr && birth_bpt.bpt_addr != 0) + || (proc_ip == death_bpt.bpt_addr && death_bpt.bpt_addr != 0) ) + { + log(tid, "got thread bpt %a (%s)\n", proc_ip, proc_ip == birth_bpt.bpt_addr ? "birth" : "death"); + size_t s = events.size(); + thread_handle = tid; // for ps_pdread + // NB! if we don't do this, some running threads can interfere with thread_db + tdb_handle_messages(tid); + // emulate return from function + if ( !emulate_retn(tid) ) + { + msg("%a: could not return from the thread breakpoint!\n", proc_ip); + return true; + } + if ( s == events.size() ) + { + log(tid, "resuming after thread_bpt\n"); + goto RESUME; + } + event->set_eid(NO_EVENT); + } + else + { + // according to the requirement of commdbg a LIB_LOADED event + // should not be reported with the same thread/IP immediately after + // a BPT-related event (see idd.hpp) + // Here we put to the queue all already loaded (but not reported) + // libraries to be sent _before_ BPT (do it only if ELF interpreter + // is not yet loaded, otherwise LIB_LOADED events will be generated + // by shlib_bpt and thus they cannot conflict with regular BPTs + if ( interp.empty() ) + { + gen_library_events(tid); + thif = get_thread(tid); + } + if ( !handle_hwbpt(event) ) + { + if ( bpts.find(proc_ip) != bpts.end() + && !handling_lowcnds.has(proc_ip) ) + { + bptaddr_t &bpta = event->set_bpt(); + bpta.hea = BADADDR; + bpta.kea = BADADDR; + event->ea = proc_ip; + } + else if ( thif != NULL && thif->single_step ) + { + event->set_eid(STEP); + } + else + { + // in case of unknown breakpoints (icebp, int3, etc...) we must remember the signal + // unless it should be masked + if ( ei == NULL || !ei->handle() ) + code = event->exc().code; + } + } + } + } + thif = get_thread(tid); + if ( thif == NULL ) + goto EVENT_READY; // report empty event to get called back immediately + thif->child_signum = code; + if ( !requested_to_suspend && evaluate_and_handle_lowcnd(event) ) + return false; + if ( !suspend && event->eid() == EXCEPTION ) + { + log_exception(event, ei); + log(tid, "resuming after exception %d\n", code); + goto RESUME; + } + } + else + { + int exit_code; + if ( WIFSIGNALED(status) ) + { + int sig = WTERMSIG(status); + debdeb("SIGNALED pid=%d tid=%d signal='%s'(%d) pc=%a\n", event->pid, event->tid, strsignal(sig), sig, event->ea); + exit_code = sig; + } + else + { + exit_code = WEXITSTATUS(status); + } + if ( threads.size() <= 1 || thif->tid == process_handle ) + { + event->set_exit_code(PROCESS_EXITED, exit_code); + exited = true; + } + else + { + log(tid, "got a thread exit\n"); + event->clear(); + dead_thread(event->tid, DEAD); + } + } +EVENT_READY: + log(tid, "low got event: %s, signum=%d\n", debug_event_str(event), thif->child_signum); + thif = get_thread(event->tid); + if ( thif != NULL ) + thif->single_step = false; + last_event = *event; + return true; +} + +//-------------------------------------------------------------------------- +gdecode_t idaapi linux_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) +{ + QASSERT(30059, !in_event || exited); + while ( true ) + { + // are there any pending events? + if ( !events.empty() ) + { + // get the first event and return it + *event = events.front(); + events.pop_front(); + if ( event->eid() == NO_EVENT ) + continue; + log(-1, "GDE1(handling_lowcnds.size()=%" FMT_Z "): %s\n", handling_lowcnds.size(), debug_event_str(event)); + in_event = true; + if ( handling_lowcnds.empty() ) + { + ldeb("requested_to_suspend := 0\n"); + requested_to_suspend = false; + } + return events.empty() ? GDE_ONE_EVENT : GDE_MANY_EVENTS; + } + + debug_event_t ev; + if ( !get_debug_event(&ev, timeout_ms) ) + break; + enqueue_event(ev, IN_BACK); + } + return GDE_NO_EVENT; +} + +//-------------------------------------------------------------------------- +// R is running +// S is sleeping in an interruptible wait +// D is waiting in uninterruptible disk sleep +// Z is zombie +// T is traced or stopped (on a signal) +// W is paging +static char getstate(int tid) +{ + char buf[QMAXPATH]; + qsnprintf(buf, sizeof(buf), "/proc/%u/status", tid); + FILE *fp = fopenRT(buf); + qstring line; + if ( fp == NULL //-V501 identical sub-expressions + || qgetline(&line, fp) < 0 + || qgetline(&line, fp) < 0 ) + { + // no file or file read error (e.g. was deleted after successful fopenRT()) + return ' '; + } + char st; + if ( qsscanf(line.c_str(), "State: %c", &st) != 1 ) + INTERR(30060); + qfclose(fp); + return st; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::has_pending_events(void) +{ + if ( !events.empty() ) + return true; + + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + if ( ti.got_pending_status && ti.user_suspend == 0 && ti.suspend_count == 0 ) + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +int linux_debmod_t::dbg_freeze_threads(thid_t tid, bool exclude) +{ + ldeb(" freeze_threads(%s %d) handling_lowcnds.size()=%" FMT_Z "\n", exclude ? "exclude" : "only", tid, handling_lowcnds.size()); + // first send all threads the SIGSTOP signal, as fast as possible + typedef qvector<thread_info_t *> queue_t; + queue_t queue; + qvector<thid_t> deadtids; + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + if ( (p->first == tid) == exclude ) + continue; + thread_info_t &ti = p->second; + if ( ti.is_running() ) + { + if ( qkill(ti.tid, SIGSTOP) != 0 ) + { + // In some cases the thread may already be dead but we are not aware + // of it (for example, if many threads died at once, the events + // will be queued and not processed yet. + if ( errno == ESRCH ) + deadtids.push_back(ti.tid); + else + dmsg("failed to send SIGSTOP to thread %d: %s\n", ti.tid, strerror(errno)); + continue; + } + queue.push_back(&ti); + ti.waiting_sigstop = true; + } + ti.suspend_count++; + } + // then wait for the SIGSTOP signals to arrive + while ( !queue.empty() ) + { + int status = 0; + int stid = check_for_signal(&status, -1, exited ? -1 : 0); + if ( stid > 0 ) + { + // if more signals are to arrive, enable the waiter + for ( queue_t::iterator p=queue.begin(); p != queue.end(); ++p ) + { + thread_info_t &ti = **p; + if ( ti.tid == stid ) + { + if ( WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP ) + { + // suspended successfully + ti.waiting_sigstop = false; + set_thread_state(ti, STOPPED); + } + else + { // got another signal, SIGSTOP will arrive later + store_pending_signal(stid, status); + } + stid = -1; + queue.erase(p); + break; + } + } + } + if ( stid > 0 ) // got a signal for some other thread + store_pending_signal(stid, status); + } + + // clean up dead threads + for ( int i=0; i < deadtids.size(); i++ ) + dead_thread(deadtids[i], DEAD); + +#ifdef LDEB + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + if ( (p->first == tid) != exclude ) + { + thid_t tid2 = p->first; + log(tid2, "suspendd (ip=%08a)\n", get_ip(tid2)); + } + } +#endif + return 1; +} + +//-------------------------------------------------------------------------- +int linux_debmod_t::dbg_thaw_threads(thid_t tid, bool exclude) +{ + int ok = 1; + ldeb(" thaw_threads(%s %d), may_run=%d handlng_lowcnd.size()=%" FMT_Z " npending_signals=%d\n", exclude ? "exclude" : "only", tid, may_run, handling_lowcnds.size(), npending_signals); + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + if ( (p->first == tid) == exclude ) + continue; + + thread_info_t &ti = p->second; + log(ti.tid, "(ip=%08a) ", get_ip(ti.tid)); + + if ( ti.is_running() ) + { + QASSERT(30188, ti.suspend_count == 0); + ldeb("already running\n"); + continue; + } + + if ( ti.suspend_count > 0 && --ti.suspend_count > 0 ) + { + ldeb("suspended\n"); + continue; + } + if ( ti.user_suspend > 0 ) + { + ldeb("user suspended\n"); + continue; + } + + if ( ti.got_pending_status ) + { + ldeb("have pending signal\n"); + continue; + } + + if ( (!may_run && ti.state != DYING) || exited ) + { + ldeb("!may_run\n"); + continue; + } + + if ( ti.state == STOPPED || ti.state == DYING ) + { + __ptrace_request request = ti.single_step ? PTRACE_SINGLESTEP : PTRACE_CONT; +#ifdef LDEB + char ostate = getstate(ti.tid); +#endif + ldeb("really resuming\n"); + if ( qptrace(request, ti.tid, 0, (void *)(size_t)(ti.child_signum)) != 0 && ti.state != DYING ) //lint !e571 cast results in sign extension + { + ldeb(" !! failed to resume thread (error %d)\n", errno); + if ( getstate(ti.tid) != 'Z' ) + { + ok = 0; + continue; + } + // we have a zombie thread + // report its death + dead_thread(ti.tid, DYING); + } + if ( ti.state == DYING ) + { + set_thread_state(ti, DEAD); + } + else + { + QASSERT(30178, ti.state == STOPPED); //-V547 is always true + set_thread_state(ti, RUNNING); + } + ldeb("PTRACE_%s, signum=%d, old_state: '%c', new_state: '%c'\n", request == PTRACE_SINGLESTEP ? "SINGLESTEP" : "CONT", ti.child_signum, ostate, getstate(ti.tid)); + } + else + { + ldeb("ti.state is not stopped or dying\n"); + } + } + return ok; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::suspend_all_threads(void) +{ + return dbg_freeze_threads(NO_THREAD); +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::resume_all_threads(void) +{ + return dbg_thaw_threads(NO_THREAD); +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_continue_after_event(const debug_event_t *event) +{ + if ( event == NULL ) + return DRC_FAILED; + + int tid = event->tid; + thread_info_t *t = get_thread(tid); + if ( t == NULL && event->eid() != THREAD_EXITED && !exited ) + { + dwarning("could not find thread %d!\n", tid); + return DRC_FAILED; + } + + ldeb("continue after event %s%s\n", debug_event_str(event), has_pending_events() ? " (there are pending events)" : ""); + + if ( t != NULL ) + { + if ( event->eid() != THREAD_STARTED + && event->eid() != THREAD_EXITED + && event->eid() != LIB_LOADED + && event->eid() != LIB_UNLOADED + && (event->eid() != EXCEPTION || event->handled) ) + { + t->child_signum = 0; + } + + if ( t->state == DYING ) + { + // this thread is about to exit; resume it so it can do so + t->suspend_count = 0; + t->user_suspend = 0; + dbg_thaw_threads(t->tid, false); + } + else if ( t->state == DEAD ) + { + // remove from internal list + del_thread(event->tid); + } + + // ensure TF bit is not set (if we aren't single stepping) after a SIGTRAP + // because TF bit may still be set + if ( event->eid() == EXCEPTION && !t->single_step + && event->exc().code == SIGTRAP && event->handled ) + clear_tbit(event->tid); + } + + in_event = false; + return resume_app(NO_THREAD) ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +// if tid is specified, resume only it. +bool linux_debmod_t::resume_app(thid_t tid) +{ + may_run = !handling_lowcnds.empty() || !has_pending_events(); + if ( !removed_bpts.empty() && npending_signals == 0 && handling_lowcnds.empty() ) + { + for ( easet_t::iterator p=removed_bpts.begin(); p != removed_bpts.end(); ++p ) + bpts.erase(*p); + removed_bpts.clear(); + } + + return tid == NO_THREAD + ? resume_all_threads() + : dbg_thaw_threads(tid, false); +} + +//-------------------------------------------------------------------------- +// PTRACE_PEEKTEXT / PTRACE_POKETEXT operate on unsigned long values! (i.e. 4 bytes on x86 and 8 bytes on x64) +typedef unsigned long peeksize_t; +#define PEEKSIZE sizeof(peeksize_t) + +//-------------------------------------------------------------------------- +int linux_debmod_t::_read_memory(int tid, ea_t ea, void *buffer, int size, bool suspend) +{ + if ( exited || process_handle == INVALID_HANDLE_VALUE ) + return 0; + + // stop all threads before accessing the process memory + if ( suspend ) + suspend_all_threads(); + + if ( tid == -1 ) + tid = process_handle; + + int read_size = 0; + bool tried_mem = false; + bool tried_peek = false; + // don't use memory for short reads + if ( size > 3 * PEEKSIZE ) + { +TRY_MEMFILE: +#ifndef __ANDROID__ + char filename[64]; + qsnprintf (filename, sizeof(filename), "/proc/%d/mem", tid); + int fd = open(filename, O_RDONLY | O_LARGEFILE); + if ( fd != -1 ) + { + read_size = pread64(fd, buffer, size, ea); + close(fd); + } + // msg("%d: pread64 %d:%a:%d => %d\n", tid, fd, ea, size, read_size); + +#ifdef LDEB + if ( read_size < size ) + perror("read_memory: pread64 failed"); +#endif +#endif + tried_mem = true; + } + + if ( read_size != size && !tried_peek ) + { + uchar *ptr = (uchar *)buffer; + read_size = 0; + tried_peek = true; + while ( read_size < size ) + { + const int shift = ea & (PEEKSIZE-1); + int nbytes = shift == 0 ? PEEKSIZE : PEEKSIZE - shift; + if ( nbytes > (size - read_size) ) + nbytes = size - read_size; + errno = 0; + unsigned long v = qptrace(PTRACE_PEEKTEXT, tid, (void *)(size_t)(ea-shift), 0); + if ( errno != 0 ) + { + ldeb("PEEKTEXT %d:%a => %s\n", tid, ea-shift, strerror(errno)); + break; + } + else + { + //msg("PEEKTEXT %d:%a => OK\n", tid, ea-shift); + } + if ( nbytes == PEEKSIZE ) + { + *(unsigned long*)ptr = v; //lint !e433 !e415 allocated area not large enough for pointer + } + else + { + v >>= (shift*8); + for ( int i=0; i < nbytes; i++ ) + { + ptr[i] = uchar(v); + v >>= 8; + } + } + ptr += nbytes; + ea += nbytes; + read_size += nbytes; + } + } + + // sometimes PEEKTEXT fails but memfile succeeds... so try both + if ( read_size < size && !tried_mem ) + goto TRY_MEMFILE; + + if ( suspend ) + resume_all_threads(); + // msg("READ MEMORY (%d): %d\n", tid, read_size); + return read_size > 0 ? read_size : 0; +} + +//-------------------------------------------------------------------------- +int linux_debmod_t::_write_memory(int tid, ea_t ea, const void *buffer, int size, bool suspend) +{ + if ( exited || process_handle == INVALID_HANDLE_VALUE ) + return 0; + +#ifndef LDEB + if ( debug_debugger ) +#endif + { + show_hex(buffer, size, "WRITE MEMORY %a %d bytes:\n", ea, size); + } + + // stop all threads before accessing the process memory + if ( suspend ) + suspend_all_threads(); + + + if ( tid == -1 ) + tid = process_handle; + + int ok = size; + const uchar *ptr = (const uchar *)buffer; + errno = 0; + + while ( size > 0 ) + { + const int shift = ea & (PEEKSIZE-1); + int nbytes = shift == 0 ? PEEKSIZE : PEEKSIZE - shift; + if ( nbytes > size ) + nbytes = size; + unsigned long word; + memcpy(&word, ptr, qmin(sizeof(word), nbytes)); // use memcpy() to read unaligned bytes + if ( nbytes != PEEKSIZE ) + { + unsigned long old = qptrace(PTRACE_PEEKTEXT, tid, (void *)(size_t)(ea-shift), 0); + if ( errno != 0 ) + { + ok = 0; + break; + } + unsigned long mask = ~0; + mask >>= ((PEEKSIZE - nbytes)*8); + mask <<= (shift*8); + word <<= (shift*8); + word &= mask; + word |= old & ~mask; + } + errno = 0; + qptrace(PTRACE_POKETEXT, process_handle, (void *)(size_t)(ea-shift), (void *)word); + if ( errno ) + { + errno = 0; + qptrace(PTRACE_POKEDATA, process_handle, (void *)(size_t)(ea-shift), (void *)word); + } + if ( errno ) + { + ok = 0; + break; + } + ptr += nbytes; + ea += nbytes; + size -= nbytes; + } + + if ( suspend ) + resume_all_threads(); + + return ok; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi linux_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring * /*errbuf*/) +{ + return _write_memory(-1, ea, buffer, size, true); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi linux_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring * /*errbuf*/) +{ + return _read_memory(-1, ea, buffer, size, true); +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::add_dll(ea_t base, asize_t size, const char *modname, const char *soname) +{ + debdeb("%a: new dll %s (soname=%s)\n", base, modname, soname); + debug_event_t ev; + modinfo_t &mi_ll = ev.set_modinfo(LIB_LOADED); + ev.pid = process_handle; + ev.tid = process_handle; + ev.ea = base; + ev.handled = true; + mi_ll.name = modname; + mi_ll.base = base; + mi_ll.size = size; + mi_ll.rebase_to = BADADDR; + if ( is_dll && input_file_path == modname ) + mi_ll.rebase_to = base; + enqueue_event(ev, IN_FRONT); + + image_info_t ii(base, ev.modinfo().size, modname, soname); + dlls.insert(make_pair(ii.base, ii)); + dlls_to_import.insert(ii.base); +} + +#define LOOK_FOR_DEBUG_FILE_DEBUG_FLAG IDA_DEBUG_DEBUGGER +#include "../../plugins/dwarf/look_for_debug_file.cpp" + +//-------------------------------------------------------------------------- +void linux_debmod_t::_import_symbols_from_file(name_info_t *out, image_info_t &ii) +{ + struct dll_symbol_importer_t : public symbol_visitor_t + { + linux_debmod_t *ld; + image_info_t ⅈ + name_info_t *out; + dll_symbol_importer_t(linux_debmod_t *_ld, name_info_t *_out, image_info_t &_ii) + : symbol_visitor_t(VISIT_SYMBOLS|VISIT_BUILDID|VISIT_DBGLINK), + ld(_ld), + ii(_ii), + out(_out) + {} + virtual int visit_symbol(ea_t ea, const char *name) override + { + ea += ii.base; + out->addrs.push_back(ea); + out->names.push_back(qstrdup(name)); + ii.names[ea] = name; + // every 10000th name send a message to ida - we are alive! + if ( (out->addrs.size() % 10000) == 0 ) + ld->dmsg(""); + return 0; + } + virtual int visit_buildid(const char *buildid) override + { + ii.buildid = buildid; + ld->debdeb("Build ID '%s' of '%s'\n", buildid, ii.fname.c_str()); + return 0; + } + virtual int visit_debuglink(const char *debuglink, uint32 crc) override + { + ii.debuglink = debuglink; + ii.dl_crc = crc; + ld->debdeb("debuglink '%s' of '%s'\n", debuglink, ii.fname.c_str()); + return 0; + } + }; + if ( ii.base == BADADDR ) + { + debdeb("Can't import symbols from %s: no imagebase\n", ii.fname.c_str()); + return; + } + dll_symbol_importer_t dsi(this, out, ii); + load_elf_symbols(ii.fname.c_str(), dsi); +} + +//------------------------------------------------------------------------- +void linux_debmod_t::_import_dll(image_info_t &ii) +{ + bool is_libpthread = stristr(ii.soname.c_str(), "libpthread") != NULL; + // keep nptl names in a separate list to be able to resolve them any time + name_info_t *storage = is_libpthread ? &nptl_names : &pending_names; + if ( is_libpthread ) + nptl_base = ii.base; + + _import_symbols_from_file(storage, ii); + // Try to locate file with the separate debug info. + // FIXME: should we check that libpthread lacks symbols for libthread_db? + // Library.so usually contains debuglink which points to itself, + // so we need to avoid to load library.so another time. + const char *elf_dbgdir = get_elf_debug_file_directory(); +#ifdef TESTABLE_BUILD + if ( per_pid_elf_dbgdir_resolver != NULL ) + { + const char *supp = per_pid_elf_dbgdir_resolver(pid); + if ( supp != NULL ) + elf_dbgdir = supp; + } +#endif + debug_info_file_visitor_t dif( + elf_dbgdir, + /*from envvar=*/ true, + ii.fname.c_str(), + ii.debuglink.c_str(), + ii.dl_crc, + ii.buildid.c_str()); + if ( dif.accept() != 0 && ii.fname != dif.fullpath ) + { + debdeb("load separate debug info '%s'\n", dif.fullpath); + image_info_t ii_deb(ii.base, 0, dif.fullpath, ""); + _import_symbols_from_file(storage, ii_deb); + } + + if ( is_libpthread ) + { + pending_names.addrs.insert(pending_names.addrs.end(), nptl_names.addrs.begin(), nptl_names.addrs.end()); + pending_names.names.insert(pending_names.names.end(), nptl_names.names.begin(), nptl_names.names.end()); + for ( int i=0; i < nptl_names.names.size(); i++ ) + nptl_names.names[i] = qstrdup(nptl_names.names[i]); + } +} + +//-------------------------------------------------------------------------- +// enumerate names from the specified shared object and save the results +// we'll need to send it to IDA later +// if libname == NULL, enum all modules +void linux_debmod_t::enum_names(const char *libname) +{ + if ( dlls_to_import.empty() ) + return; + + for ( easet_t::iterator p=dlls_to_import.begin(); p != dlls_to_import.end(); ) + { + images_t::iterator q = dlls.find(*p); + if ( q != dlls.end() ) + { + image_info_t &ii = q->second; + if ( libname != NULL && ii.soname != libname ) + { + ++p; + continue; + } + _import_dll(ii); + } + p = dlls_to_import.erase(p); + } +} + +//-------------------------------------------------------------------------- +ea_t linux_debmod_t::find_pending_name(const char *name) +{ + if ( name == NULL ) + return BADADDR; + // enumerate pending names in reverse order. we need this to find the latest + // resolved address for a name (on android, pthread_..() functions exist twice) + for ( int i=pending_names.addrs.size()-1; i >= 0; --i ) + if ( streq(pending_names.names[i], name) ) + return pending_names.addrs[i]; + for ( int i=0; i < nptl_names.addrs.size(); ++i ) + if ( streq(nptl_names.names[i], name) ) + return nptl_names.addrs[i]; + return BADADDR; +} + +//-------------------------------------------------------------------------- +void idaapi linux_debmod_t::dbg_stopped_at_debug_event(import_infos_t *, bool dlls_added, thread_name_vec_t *thr_names) +{ + if ( dlls_added ) + { + // we will take advantage of this event to import information + // about the exported functions from the loaded dlls + enum_names(); + + name_info_t &ni = *get_debug_names(); + ni = pending_names; // NB: ownership of name pointers is transferred + pending_names.clear(); + } + if ( thr_names != NULL ) + update_thread_names(thr_names); +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::cleanup(void) +{ + // if the process is still running, kill it, otherwise it runs uncontrolled + // normally the process is dead at this time but may survive if we arrive + // here after an interr. + if ( process_handle != INVALID_HANDLE_VALUE ) + dbg_exit_process(NULL); + process_handle = INVALID_HANDLE_VALUE; + thread_handle = INVALID_HANDLE_VALUE; + threads_collected = false; + is_dll = false; + requested_to_suspend = false; + in_event = false; + + threads.clear(); + dlls.clear(); + dlls_to_import.clear(); + events.clear(); + if ( mapfp != NULL ) + { + qfclose(mapfp); + mapfp = NULL; + } + + complained_shlib_bpt = false; + bpts.clear(); + + tdb_delete(); + erase_internal_bp(birth_bpt); + erase_internal_bp(death_bpt); + erase_internal_bp(shlib_bpt); + npending_signals = 0; + interp.clear(); + exe_path.qclear(); + exited = false; + + for ( int i=0; i < nptl_names.names.size(); i++ ) + qfree(nptl_names.names[i]); + nptl_names.clear(); + + inherited::cleanup(); +} + +//-------------------------------------------------------------------------- +// +// DEBUGGER INTERFACE FUNCTIONS +// +//-------------------------------------------------------------------------- +inline const char *skipword(const char *ptr) +{ + while ( !qisspace(*ptr) && *ptr != '\0' ) + ptr++; + return ptr; +} + +//-------------------------------------------------------------------------- +// find a first mapping of shared lib in the memory information array +static const memory_info_t *find_first_mapping(const meminfo_vec_t &miv, const char *name) +{ + for ( int i=0; i < miv.size(); i++ ) + if ( miv[i].name == name ) + return &miv[i]; + return NULL; +} + +//-------------------------------------------------------------------------- +static memory_info_t *find_first_mapping(meminfo_vec_t &miv, const char *name) //lint !e1764 could be reference to const +{ + return CONST_CAST(memory_info_t *)(find_first_mapping(CONST_CAST(const meminfo_vec_t &)(miv), name)); +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::add_shlib_bpt(const meminfo_vec_t &miv, bool attaching) +{ + if ( shlib_bpt.bpt_addr != 0 ) + return true; + + qstring interp_soname; + if ( interp.empty() ) + { + // find out the loader name + struct interp_finder_t : public symbol_visitor_t + { + qstring interp; + interp_finder_t(void) : symbol_visitor_t(VISIT_INTERP) {} + virtual int visit_symbol(ea_t, const char *) override { return 0; } // unused + virtual int visit_interp(const char *name) override + { + interp = name; + return 2; + } + }; + interp_finder_t itf; + const char *exename = exe_path.c_str(); + int code = load_elf_symbols(exename, itf); + if ( code == 0 ) + { // no interpreter + if ( !complained_shlib_bpt ) + { + complained_shlib_bpt = true; + dwarning("AUTOHIDE DATABASE\n%s:\n" + "Could not find the elf interpreter name,\n" + "shared object events will not be reported", exename); + } + return false; + } + if ( code != 2 ) + { + dwarning("%s: could not read symbols on remote computer", exename); + return false; + } + char path[QMAXPATH]; + qmake_full_path(path, sizeof(path), itf.interp.c_str()); + interp_soname.swap(itf.interp); + interp = path; + } + else + { + interp_soname = qbasename(interp.c_str()); + } + + // check if it is present in the memory map (normally it is) + debdeb("INTERP: %s, SONAME: %s\n", interp.c_str(), interp_soname.c_str()); + const memory_info_t *mi = find_first_mapping(miv, interp.c_str()); + if ( mi == NULL ) + { + dwarning("%s: could not find in process memory", interp.c_str()); + return false; + } + + asize_t size = calc_module_size(miv, mi); + add_dll(mi->start_ea, size, interp.c_str(), interp_soname.c_str()); + + // set bpt at r_brk + enum_names(interp_soname.c_str()); // update the name list + const char *bpt_name = "_r_debug"; + ea_t ea = find_pending_name(bpt_name); + if ( ea != BADADDR ) + { + struct r_debug rd; + if ( _read_memory(-1, ea, &rd, sizeof(rd), false) == sizeof(rd) ) + { + if ( rd.r_brk != 0 ) + { + if ( !add_internal_bp(shlib_bpt, rd.r_brk) ) + { + ea_t ea1 = rd.r_brk; + debdeb("%a: could not set shlib bpt\n", ea1); + } + } + } + } + if ( shlib_bpt.bpt_addr == 0 ) + { + static const char *const shlib_bpt_names[] = + { + "r_debug_state", + "_r_debug_state", + "_dl_debug_state", + "rtld_db_dlactivity", + "_rtld_debug_state", + NULL + }; + + for ( int i=0; i < qnumber(shlib_bpt_names); i++ ) + { + bpt_name = shlib_bpt_names[i]; + ea = find_pending_name(bpt_name); + if ( ea != BADADDR && ea != 0 ) + { + if ( add_internal_bp(shlib_bpt, ea) ) + break; + debdeb("%a: could not set shlib bpt (name=%s)\n", ea, bpt_name); + } + } + if ( shlib_bpt.bpt_addr == 0 ) + { +#if defined(__ANDROID__) && defined(__X86__) + // Last attempt for old Android, + // the modern Android doesn't need the special handling + return add_android_shlib_bpt(miv, attaching); +#else + qnotused(attaching); + return false; +#endif + } + } + debdeb("%a: added shlib bpt (%s)\n", shlib_bpt.bpt_addr, bpt_name); + return true; +} + +//-------------------------------------------------------------------------- +thread_info_t &linux_debmod_t::add_thread(int tid) +{ + std::pair<threads_t::iterator, bool> ret = + threads.insert(std::make_pair(tid, thread_info_t(tid))); + thread_info_t &ti = ret.first->second; + get_thread_name(&ti.name, tid); + return ti; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::del_thread(int tid) +{ + threads_t::iterator p = threads.find(tid); + QASSERT(30064, p != threads.end()); + if ( p->second.got_pending_status ) + npending_signals--; + threads.erase(p); + + if ( deleted_threads.size() >= 10 ) + deleted_threads.erase(deleted_threads.begin()); + + deleted_threads.push_back(tid); +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::handle_process_start(pid_t _pid, attach_mode_t attaching) +{ + pid = _pid; + deleted_threads.clear(); + process_handle = pid; + threads_collected = false; + add_thread(pid); + int status; + int options = 0; + if ( attaching == AMT_ATTACH_BROKEN ) + options = WNOHANG; + qwait(&status, pid, options); // (should succeed) consume SIGSTOP + debdeb("process pid/tid: %d\n", pid); + may_run = false; + + char fname[QMAXPATH]; + debug_event_t ev; + modinfo_t &mi_ps = ev.set_modinfo(PROCESS_STARTED); + ev.pid = pid; + ev.tid = pid; + ev.ea = get_ip(pid); + ev.handled = true; + get_exec_fname(pid, fname, sizeof(fname)); + mi_ps.name = fname; + mi_ps.base = BADADDR; + mi_ps.size = 0; + mi_ps.rebase_to = BADADDR; + + qsnprintf(fname, sizeof(fname), "/proc/%u/maps", pid); + mapfp = fopenRT(fname); + if ( mapfp == NULL ) + { + dmsg("%s: %s\n", fname, winerr(errno)); + return false; // if fails, the process did not start + } + + exe_path = mi_ps.name.c_str(); + if ( !is_dll ) + input_file_path = exe_path; + + // find the executable base + meminfo_vec_t miv; + // init debapp_attrs.addrsize: 32bit application by default + // get_memory_info() may correct it if meets a 64-bit address + debapp_attrs.addrsize = 4; + if ( get_memory_info(miv, false) <= 0 ) + INTERR(30065); + + term_reg_ctx(); + init_reg_ctx(); + + const memory_info_t *mi = find_first_mapping(miv, mi_ps.name.c_str()); + if ( mi != NULL ) + { + mi_ps.base = mi->start_ea; + mi_ps.size = calc_module_size(miv, mi); + if ( !is_dll ) // exe files: rebase idb to the loaded address + mi_ps.rebase_to = mi->start_ea; + } + else + { + if ( !is_dll ) + dmsg("%s: nowhere in the process memory?!\n", mi_ps.name.c_str()); + } + + if ( !add_shlib_bpt(miv, attaching) ) + dmsg("Could not set the shlib bpt, shared object events will not be handled\n"); + + enqueue_event(ev, IN_BACK); + if ( attaching != AMT_NO_ATTACH ) + { + modinfo_t &mi_pa = ev.set_modinfo(PROCESS_ATTACHED); + enqueue_event(ev, IN_BACK); + if ( !qgetenv("IDA_SKIP_SYMS", NULL) ) + { + // collect exported names from the main module + qstring soname; + get_soname(mi_pa.name.c_str(), &soname); + image_info_t ii(mi_pa.base, mi_pa.size, mi_pa.name.c_str(), soname); + _import_dll(ii); + } + } + + return true; +} + +//-------------------------------------------------------------------------- +static void idaapi kill_all_processes(void) +{ + struct ida_local process_killer_t : public debmod_visitor_t + { + virtual int visit(debmod_t *debmod) override + { + linux_debmod_t *ld = (linux_debmod_t *)debmod; + if ( ld->process_handle != INVALID_HANDLE_VALUE ) + qkill(ld->process_handle, SIGKILL); + return 0; + } + }; + process_killer_t pk; + for_all_debuggers(pk); +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_start_process( + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf) +{ + void *child_pid; + drc_t drc = maclnx_launch_process(this, path, args, startdir, flags, + input_path, input_file_crc32, &child_pid, + errbuf); + + if ( drc > 0 + && child_pid != NULL + && !handle_process_start(size_t(child_pid), AMT_NO_ATTACH) ) + { + dbg_exit_process(NULL); + drc = DRC_NETERR; + } + + return drc; +} + +//-------------------------------------------------------------------------- +// 1-ok, 0-failed +drc_t idaapi linux_debmod_t::dbg_attach_process(pid_t _pid, int /*event_id*/, int flags, qstring * /*errbuf*/) +{ + is_dll = (flags & DBG_PROC_IS_DLL) != 0; + if ( qptrace(PTRACE_ATTACH, _pid, NULL, NULL) == 0 + && handle_process_start(_pid, AMT_ATTACH_NORMAL) ) + { + gen_library_events(_pid); // detect all loaded libraries + return DRC_OK; + } + qptrace(PTRACE_DETACH, _pid, NULL, NULL); + return DRC_FAILED; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::cleanup_signals(void) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + // cannot leave pending sigstop, try to recieve and handle it + if ( p->second.waiting_sigstop ) + { + thread_info_t &ti = p->second; + ldeb("cleanup_signals:\n"); + log(ti.tid, "must be STOPPED\n"); + QASSERT(30181, ti.state == STOPPED); + qptrace(PTRACE_CONT, ti.tid, 0, 0); + int status; + int tid = check_for_signal(&status, ti.tid, -1); + if ( tid != ti.tid ) + msg("%d: failed to clean up pending SIGSTOP\n", tid); + } + } +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::cleanup_breakpoints(void) +{ + erase_internal_bp(birth_bpt); + erase_internal_bp(death_bpt); + erase_internal_bp(shlib_bpt); +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_detach_process(void) +{ + // restore only internal breakpoints and signals + cleanup_breakpoints(); + cleanup_signals(); + + bool had_pid = false; + bool ok = true; + log(-1, "detach all threads.\n"); + for ( threads_t::iterator p=threads.begin(); ok && p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + if ( ti.tid == process_handle ) + had_pid = true; + + ok = qptrace(PTRACE_DETACH, ti.tid, NULL, NULL) == 0; + log(-1, "detach tid %d: ok=%d\n", ti.tid, ok); + } + + if ( ok && !had_pid ) + { + // if pid was not in the thread list, detach it separately + ok = qptrace(PTRACE_DETACH, process_handle, NULL, NULL) == 0; + log(-1, "detach pid %d: ok=%d\n", process_handle, ok); + } + if ( ok ) + { + debug_event_t ev; + ev.set_eid(PROCESS_DETACHED); + ev.pid = process_handle; + ev.tid = process_handle; + ev.ea = BADADDR; + ev.handled = true; + enqueue_event(ev, IN_BACK); + in_event = false; + exited = true; + threads.clear(); + process_handle = INVALID_HANDLE_VALUE; + threads_collected = false; + return DRC_OK; + } + return DRC_FAILED; +} + +//-------------------------------------------------------------------------- +// if we have to do something as soon as we noticed the connection +// broke, this is the correct place +bool idaapi linux_debmod_t::dbg_prepare_broken_connection(void) +{ + broken_connection = true; + return true; +} + +//-------------------------------------------------------------------------- +// 1-ok, 0-failed +drc_t idaapi linux_debmod_t::dbg_prepare_to_pause_process(qstring * /*errbuf*/) +{ + if ( events.empty() ) + { + qkill(process_handle, SIGSTOP); + thread_info_t &ti = threads.begin()->second; + ti.waiting_sigstop = true; + } + may_run = false; + requested_to_suspend = true; + ldeb("requested_to_suspend := 1\n"); + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_exit_process(qstring * /*errbuf*/) +{ + ldeb("------- exit process\n"); + bool ok = true; + // suspend all threads to avoid problems (for example, killing a + // thread may resume another thread and it can throw an exception because + // of that) + suspend_all_threads(); + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + if ( ti.state == STOPPED ) + { + if ( qptrace(PTRACE_KILL, ti.tid, 0, (void*)SIGKILL) != 0 && errno != ESRCH ) + { + dmsg("PTRACE_KILL %d: %s\n", ti.tid, strerror(errno)); + ok = false; + } + } + else + { + if ( ti.tid != INVALID_HANDLE_VALUE && qkill(ti.tid, SIGKILL) != 0 && errno != ESRCH ) + { + dmsg("SIGKILL %d: %s\n", ti.tid, strerror(errno)); + ok = false; + } + } + if ( ok ) + { + set_thread_state(ti, RUNNING); + ti.suspend_count = 0; + } + } + if ( ok ) + { + process_handle = INVALID_HANDLE_VALUE; + threads_collected = false; + } + may_run = true; + exited = true; + return ok ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +// Set hardware breakpoints for one thread +bool linux_debmod_t::set_hwbpts(HANDLE hThread) const +{ +#ifdef __ARM__ + qnotused(hThread); + return false; +#else + bool ok = set_dr(hThread, 0, hwbpt_ea[0]) + && set_dr(hThread, 1, hwbpt_ea[1]) + && set_dr(hThread, 2, hwbpt_ea[2]) + && set_dr(hThread, 3, hwbpt_ea[3]) + && set_dr(hThread, 6, 0) + && set_dr(hThread, 7, dr7); + // msg("set_hwbpts: DR0=%a DR1=%a DR2=%a DR3=%a DR7=%a => %d\n", + // hwbpt_ea[0], + // hwbpt_ea[1], + // hwbpt_ea[2], + // hwbpt_ea[3], + // dr7, + // ok); + return ok; +#endif +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::refresh_hwbpts(void) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + if ( !set_hwbpts(p->second.tid) ) + return false; + return true; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::erase_internal_bp(internal_bpt &bp) +{ + bool ok = bp.bpt_addr == 0 || dbg_del_bpt(BPT_SOFT, bp.bpt_addr, bp.saved, bp.nsaved); + bp.bpt_addr = 0; + bp.nsaved = 0; + return ok; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::add_internal_bp(internal_bpt &bp, ea_t addr) +{ + int len = -1; + int nread = sizeof(bp.saved); +#ifdef __ARM__ + if ( (addr & 1) != 0 ) + { + len = 2; + addr--; + } + else + { + len = 4; + } + CASSERT(sizeof(bp.saved) >= 4); + nread = len; +#endif + if ( _read_memory(-1, addr, bp.saved, nread) == nread ) + { + if ( dbg_add_bpt(NULL, BPT_SOFT, addr, len) ) + { + bp.bpt_addr = addr; + bp.nsaved = nread; + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------- +// 1-ok, 0-failed, -2-read failed +int idaapi linux_debmod_t::dbg_add_bpt( + bytevec_t *orig_bytes, + bpttype_t type, + ea_t ea, + int len) +{ +#if defined(__ARM__) && defined(__X86__) + bool is_thumb32_bpt = false; + if ( len == (2 | USE_THUMB32_BPT) ) + { + is_thumb32_bpt = true; + len = 4; + } +#endif + ldeb("%a: add bpt (size=%d)\n", ea, len); + if ( type == BPT_SOFT ) + { + if ( orig_bytes != NULL && read_bpt_orgbytes(orig_bytes, ea, len) < 0 ) + return -2; + const uchar *bptcode = bpt_code.begin(); +#ifdef __ARM__ +# ifndef __X86__ + if ( len < 0 ) + len = bpt_code.size(); + bptcode = aarch64_bpt; +# else + if ( len < 0 ) + { // unknown mode. we have to decide between thumb and arm bpts + // ideally we would decode the instruction and try to determine its mode + // unfortunately we do not have instruction decoder in arm server. + // besides, it cannot really help. + // just check for some known opcodes. this is bad but i do not know + // how to do better. + + len = 4; // default to arm mode + uchar opcodes[2]; + if ( dbg_read_memory(ea, opcodes, sizeof(opcodes), NULL) == sizeof(opcodes) ) + { + static const uchar ins1[] = { 0x70, 0x47 }; // BX LR + static const uchar ins3[] = { 0x00, 0xB5 }; // PUSH {LR} + static const uchar ins2[] = { 0x00, 0xBD }; // POP {PC} + static const uchar *const ins[] = { ins1, ins2, ins3 }; + for ( int i=0; i < qnumber(ins); i++ ) + { + const uchar *p = ins[i]; + if ( opcodes[0] == p[0] && opcodes[1] == p[1] ) + { + len = 2; + break; + } + } + } + } + if ( len == 2 ) + bptcode = thumb16_bpt; + else if ( len == 4 && is_thumb32_bpt ) + bptcode = thumb32_bpt; +# endif +#else + if ( len < 0 ) + len = bpt_code.size(); +#endif + QASSERT(30066, len > 0 && len <= bpt_code.size()); + debmod_bpt_t dbpt(ea, len); + if ( dbg_read_memory(ea, dbpt.saved, len, NULL) + && dbg_write_memory(ea, bptcode, len, NULL) == len ) + { + bpts[ea] = dbpt; + removed_bpts.erase(ea); + return 1; + } + } + +#ifndef __ARM__ + if ( add_hwbpt(type, ea, len) ) + return 1; +#endif + + return 0; +} + +//-------------------------------------------------------------------------- +#ifdef __ARM__ +void linux_debmod_t::adjust_swbpt(ea_t *p_ea, int *p_len) +{ + inherited::adjust_swbpt(p_ea, p_len); + // for thumb mode we have to decide between 16-bit and 32-bit bpt + if ( *p_len == 2 ) + { + uint16 opcode; + if ( dbg_read_memory(*p_ea, &opcode, sizeof(opcode), NULL) <= 0 ) + return; + if ( is_32bit_thumb_insn(opcode) ) + *p_len |= USE_THUMB32_BPT; // ask for thumb32 bpt + } +} +#endif + +//-------------------------------------------------------------------------- +// 1-ok, 0-failed +int idaapi linux_debmod_t::dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) +{ +#if defined(__ARM__) && defined(__X86__) + if ( len == (2 | USE_THUMB32_BPT) ) + len = 4; +#endif + ldeb("%a: del bpt (size=%d) exited=%d\n", ea, len, exited); + if ( orig_bytes != NULL ) + { + if ( dbg_write_memory(ea, orig_bytes, len, NULL) == len ) + { + removed_bpts.insert(ea); + return true; + } + } + +#ifdef __ARM__ + qnotused(type); + return false; +#else + return del_hwbpt(ea, type); +#endif +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_thread_get_sreg_base(ea_t *pea, thid_t tid, int sreg_value, qstring * /*errbuf*/) +{ +#ifdef __ARM__ + qnotused(tid); + qnotused(sreg_value); + qnotused(pea); + return DRC_FAILED; +#else + *pea = 0; // all other selectors (cs, ds) usually have base of 0... + // since we do not receive the segment register id we need to retrieve, we + // rely on the register value, which is not great. for example, + // on x64 fs==gs==0, and when IDA passes sreg_value==0, we return the + // base of fs. + if ( sreg_value != 0 ) + { + // find out which selector we're asked to retrieve + struct user_regs_struct regs; + memset(®s, -1, sizeof(regs)); + if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) + return DRC_FAILED; + if ( sreg_value == regs.INTEL_SREG(fs) ) + return thread_get_fs_base(tid, fs_idx, pea) ? DRC_OK : DRC_FAILED; + else if ( sreg_value == regs.INTEL_SREG(gs) ) + return thread_get_fs_base(tid, gs_idx, pea) ? DRC_OK : DRC_FAILED; + } + return DRC_OK; +#endif +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_thread_suspend(thid_t tid) +{ + thread_info_t *ti = get_thread(tid); + if ( ti == NULL ) + return DRC_FAILED; + if ( !dbg_freeze_threads(tid, false) ) + return DRC_FAILED; + ti->user_suspend++; + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_thread_continue(thid_t tid) +{ + thread_info_t *ti = get_thread(tid); + if ( ti == NULL ) + return DRC_FAILED; + if ( ti->user_suspend > 0 ) + { + if ( --ti->user_suspend > 0 ) + return DRC_OK; + } + return dbg_thaw_threads(tid, false) ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_set_resume_mode(thid_t tid, resume_mode_t resmod) +{ + if ( resmod != RESMOD_INTO ) + return DRC_FAILED; // not supported + + thread_info_t *t = get_thread(tid); + if ( t == NULL ) + return DRC_FAILED; + t->single_step = true; + return DRC_OK; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::emulate_retn(int tid) +{ +#ifdef __ARM__ +# ifndef __X86__ + struct user_regs_struct regs; + if ( !qptrace_get_prstatus(®s, tid) ) + return false; + + // emulate BX LR + regs.pc = regs.regs[LRREG_IDX]; // PC <- LR + + return qptrace_set_regset(NT_PRSTATUS, tid, ®s, sizeof(regs)); +# else + struct user_regs_struct regs; + qptrace(PTRACE_GETREGS, tid, 0, ®s); + // emulate BX LR + int tbit = regs.uregs[14] & 1; + regs.PCREG = regs.uregs[14] & ~1; // PC <- LR + setflag(regs.uregs[16], 1<<5, tbit); // Set/clear T bit in PSR + return qptrace(PTRACE_SETREGS, tid, 0, ®s) == 0; +# endif +#else + struct user_regs_struct regs; + qptrace(PTRACE_GETREGS, tid, 0, ®s); + size_t sizeof_pcreg = debapp_attrs.addrsize; + if ( _read_memory(tid, regs.SPREG, ®s.PCREG, sizeof_pcreg, false) != sizeof_pcreg ) + { + log(-1, "%d: reading return address from %a failed\n", tid, ea_t(regs.SPREG)); + if ( tid == process_handle ) + return false; + if ( _read_memory(process_handle, regs.SPREG, ®s.PCREG, sizeof_pcreg, false) != sizeof_pcreg ) + { + log(-1, "%d: reading return address from %a failed (2)\n", process_handle, ea_t(regs.SPREG)); + return false; + } + } + regs.SPREG += sizeof_pcreg; + log(-1, "%d: retn to %a\n", tid, ea_t(regs.PCREG)); + return qptrace(PTRACE_SETREGS, tid, 0, ®s) == 0; +#endif +} + +//-------------------------------------------------------------------------- +#define qoffsetof2(s, f) (qoffsetof(regctx_t, s) + qoffsetof(decltype(regctx_t::s), f)) +#define offset_size(s, f) qoffsetof2(s, f), sizeof(decltype(regctx_t::s)::f) + +#ifdef __ARM__ +# ifndef __X86__ +//-------------------------------------------------------------------------- +// AArch64 +//-------------------------------------------------------------------------- +struct regctx_t : public regctx_base_t +{ + struct user_regs_struct regs; + + // clsmask helpers + bool clsmask_regs; + + regctx_t(dynamic_register_set_t &_idaregs); + bool init(void); + bool load(void); + bool store(void); +}; + +//-------------------------------------------------------------------------- +regctx_t::regctx_t(dynamic_register_set_t &_idaregs) + : regctx_base_t(_idaregs) +{ + memset(®s, 0, sizeof(regs)); + + clsmask_regs = 0; + + idaregs.set_regclasses(arm_register_classes); +} + +//-------------------------------------------------------------------------- +bool regctx_t::init(void) +{ + if ( (clsmask & ARM_RC_ALL) == 0 ) + return false; + // setup clsmask helpers + clsmask_regs = (clsmask & ARM_RC_GENERAL) != 0; + return true; +} + +//-------------------------------------------------------------------------- +bool regctx_t::load(void) +{ + if ( !init() ) + return false; + if ( clsmask_regs ) + if ( !qptrace_get_prstatus(®s, tid) ) + return false; + return true; +} + +//-------------------------------------------------------------------------- +bool regctx_t::store(void) +{ + if ( clsmask_regs ) + if ( !qptrace_set_regset(NT_PRSTATUS, tid, ®s, sizeof(regs)) ) + return false; + return true; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::init_reg_ctx(void) +{ + reg_ctx = new regctx_t(idaregs); + + // Populate register context + reg_ctx->add_ival(arch_registers[R_R0], offset_size(regs, regs[0])); + reg_ctx->add_ival(arch_registers[R_R1], offset_size(regs, regs[1])); + reg_ctx->add_ival(arch_registers[R_R2], offset_size(regs, regs[2])); + reg_ctx->add_ival(arch_registers[R_R3], offset_size(regs, regs[3])); + reg_ctx->add_ival(arch_registers[R_R4], offset_size(regs, regs[4])); + reg_ctx->add_ival(arch_registers[R_R5], offset_size(regs, regs[5])); + reg_ctx->add_ival(arch_registers[R_R6], offset_size(regs, regs[6])); + reg_ctx->add_ival(arch_registers[R_R7], offset_size(regs, regs[7])); + reg_ctx->add_ival(arch_registers[R_R8], offset_size(regs, regs[8])); + reg_ctx->add_ival(arch_registers[R_R9], offset_size(regs, regs[9])); + reg_ctx->add_ival(arch_registers[R_R10], offset_size(regs, regs[10])); + reg_ctx->add_ival(arch_registers[R_R11], offset_size(regs, regs[11])); + reg_ctx->add_ival(arch_registers[R_R12], offset_size(regs, regs[12])); + reg_ctx->add_ival(arch_registers[R_R13], offset_size(regs, regs[13])); + reg_ctx->add_ival(arch_registers[R_R14], offset_size(regs, regs[14])); + reg_ctx->add_ival(arch_registers[R_R15], offset_size(regs, regs[15])); + reg_ctx->add_ival(arch_registers[R_R16], offset_size(regs, regs[16])); + reg_ctx->add_ival(arch_registers[R_R17], offset_size(regs, regs[17])); + reg_ctx->add_ival(arch_registers[R_R18], offset_size(regs, regs[18])); + reg_ctx->add_ival(arch_registers[R_R19], offset_size(regs, regs[19])); + reg_ctx->add_ival(arch_registers[R_R20], offset_size(regs, regs[20])); + reg_ctx->add_ival(arch_registers[R_R21], offset_size(regs, regs[21])); + reg_ctx->add_ival(arch_registers[R_R22], offset_size(regs, regs[22])); + reg_ctx->add_ival(arch_registers[R_R23], offset_size(regs, regs[23])); + reg_ctx->add_ival(arch_registers[R_R24], offset_size(regs, regs[24])); + reg_ctx->add_ival(arch_registers[R_R25], offset_size(regs, regs[25])); + reg_ctx->add_ival(arch_registers[R_R26], offset_size(regs, regs[26])); + reg_ctx->add_ival(arch_registers[R_R27], offset_size(regs, regs[27])); + reg_ctx->add_ival(arch_registers[R_R28], offset_size(regs, regs[28])); + reg_ctx->add_ival(arch_registers[R_R29], offset_size(regs, regs[29])); + lr_idx = reg_ctx->add_ival(arch_registers[R_LR], offset_size(regs, regs[30])); + sp_idx = reg_ctx->add_ival(arch_registers[R_SP], offset_size(regs, sp)); + pc_idx = reg_ctx->add_ival(arch_registers[R_PC], offset_size(regs, pc)); + sr_idx = reg_ctx->add_ival(arch_registers[R_PSR], offset_size(regs, pstate)); // 32-bit +} + +# else // __ARM__ && __X86__ + +//-------------------------------------------------------------------------- +// ARM (32-bit) +//-------------------------------------------------------------------------- +struct regctx_t : public regctx_base_t +{ + struct user_regs_struct regs; +#ifdef __HAVE_ARM_VFP__ + struct user_vfp vfp_regs; +#endif + + // clsmask helpers + bool clsmask_regs; +#ifdef __HAVE_ARM_VFP__ + bool clsmask_vfp; +#endif + + regctx_t(dynamic_register_set_t &_idaregs); + bool init(void); + bool load(void); + bool store(void); +}; + +//-------------------------------------------------------------------------- +regctx_t::regctx_t(dynamic_register_set_t &_idaregs) + : regctx_base_t(_idaregs) +{ + memset(®s, 0, sizeof(regs)); +#ifdef __HAVE_ARM_VFP__ + memset(&vfp_regs, 0, sizeof(vfp_regs)); +#endif + + clsmask_regs = 0; +#ifdef __HAVE_ARM_VFP__ + clsmask_vfp = 0; +#endif + + idaregs.set_regclasses(arm_register_classes); +} + +//-------------------------------------------------------------------------- +bool regctx_t::init(void) +{ + if ( (clsmask & ARM_RC_ALL) == 0 ) + return false; + // setup clsmask helpers + clsmask_regs = (clsmask & ARM_RC_GENERAL) != 0; +#ifdef __HAVE_ARM_VFP__ + clsmask_vfp = (clsmask & ARM_RC_VFP) != 0; +#endif + return true; +} + +//-------------------------------------------------------------------------- +bool regctx_t::load(void) +{ + if ( !init() ) + return false; + if ( clsmask_regs ) + if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) + return false; +#ifdef __HAVE_ARM_VFP__ + if ( clsmask_vfp ) + if ( qptrace(PTRACE_GETVFPREGS, tid, 0, &vfp_regs) != 0 ) + return false; +#endif + return true; +} + +//-------------------------------------------------------------------------- +bool regctx_t::store(void) +{ + if ( clsmask_regs ) + if ( qptrace(PTRACE_SETREGS, tid, 0, ®s) != 0 ) + return false; +#ifdef __HAVE_ARM_VFP__ + if ( clsmask_vfp ) + if ( qptrace(PTRACE_SETVFPREGS, tid, 0, &vfp_regs) != 0 ) + return false; +#endif + return true; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::init_reg_ctx(void) +{ + reg_ctx = new regctx_t(idaregs); + + // Populate register context + reg_ctx->add_ival(arch_registers[R_R0], offset_size(regs, uregs[0])); + reg_ctx->add_ival(arch_registers[R_R1], offset_size(regs, uregs[1])); + reg_ctx->add_ival(arch_registers[R_R2], offset_size(regs, uregs[2])); + reg_ctx->add_ival(arch_registers[R_R3], offset_size(regs, uregs[3])); + reg_ctx->add_ival(arch_registers[R_R4], offset_size(regs, uregs[4])); + reg_ctx->add_ival(arch_registers[R_R5], offset_size(regs, uregs[5])); + reg_ctx->add_ival(arch_registers[R_R6], offset_size(regs, uregs[6])); + reg_ctx->add_ival(arch_registers[R_R7], offset_size(regs, uregs[7])); + reg_ctx->add_ival(arch_registers[R_R8], offset_size(regs, uregs[8])); + reg_ctx->add_ival(arch_registers[R_R9], offset_size(regs, uregs[9])); + reg_ctx->add_ival(arch_registers[R_R10], offset_size(regs, uregs[10])); + reg_ctx->add_ival(arch_registers[R_R11], offset_size(regs, uregs[11])); + reg_ctx->add_ival(arch_registers[R_R12], offset_size(regs, uregs[12])); + sp_idx = reg_ctx->add_ival(arch_registers[R_SP], offset_size(regs, uregs[13])); + lr_idx = reg_ctx->add_ival(arch_registers[R_LR], offset_size(regs, uregs[14])); + pc_idx = reg_ctx->add_ival(arch_registers[R_PC], offset_size(regs, uregs[15])); + sr_idx = reg_ctx->add_ival(arch_registers[R_PSR], offset_size(regs, uregs[16])); + +#ifdef __HAVE_ARM_VFP__ + size_t offset = qoffsetof2(vfp_regs, fpregs); + for ( size_t i = R_D0; i <= R_D31; i++, offset += sizeof(int64) ) + reg_ctx->add_data(arch_registers[i], offset, sizeof(int64)); + reg_ctx->add_ival(arch_registers[R_FPSCR], offset_size(vfp_regs, fpscr)); +#endif +} + +# endif +#else // !__ARM__ + +//-------------------------------------------------------------------------- +// X86/X64 +//------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +//lint -esym(749,TAG_*) local enumeration constant '' not referenced +enum +{ + TAG_VALID = 0, + TAG_ZERO = 1, + TAG_SPECIAL = 2, + TAG_EMPTY = 3, +}; + +//------------------------------------------------------------------------- +// Intel® 64 and IA-32 Architectures Software Developer's Manual +// Volume 1: Basic Architecture +// 253665-070US May 2019 + +// 13.1 XSAVE-SUPPORTED FEATURES AND STATE-COMPONENT BITMAPS +// Bit 1 corresponds to the state component used for registers used by the +// streaming SIMD extensions (SSE state). +#define X86_XSTATE_SSE (1ULL << 1) +// Bit 2 corresponds to the state component used for the additional register +// state used by the Intel® Advanced Vector Extensions (AVX state). +#define X86_XSTATE_AVX (1ULL << 2) + +// 13.4 XSAVE AREA +// The legacy region of an XSAVE area comprises the 512 bytes starting at the +// area's base address. [...] The XSAVE feature set uses the legacy area for +// x87 state (state component 0) and SSE state (state component 1). +#define XSAVE_LEGACY_REGION_OFFSET 0 +// The XSAVE header of an XSAVE area comprises the 64 bytes starting at +// offset 512 from the area’s base address: +#define XSAVE_HEADER_OFFSET 512 +// The extended region of an XSAVE area starts at an offset of 576 bytes from +// the area's base address. +#define XSAVE_EXTENDED_REGION_OFFSET 576 + +// 13.4.2 XSAVE Header +// Bytes 7:0 of the XSAVE header is a state-component bitmap (see Section +// 13.1) called XSTATE_BV. +#define XSAVE_XSTATE_BV XSAVE_HEADER_OFFSET + +// 13.5.2 SSE State +// Bytes 287:160 are used for the registers XMM0–XMM7. +// Bytes 415:288 are used for the registers XMM8–XMM15. +#define XSAVE_XMM_OFFSET_BASE (XSAVE_LEGACY_REGION_OFFSET + 160) + +// 13.5.3 AVX State +// Bytes 127:0 of the AVX-state section are used for YMM0_H–YMM7_H. +// Bytes 255:128 are used for YMM8_H–YMM15_H. +#define XSAVE_YMMH_OFFSET_BASE XSAVE_EXTENDED_REGION_OFFSET + +//-------------------------------------------------------------------------- +struct regctx_t : public regctx_base_t +{ + struct user_regs_struct regs; + struct user_fpregs_struct i387; +#ifdef __X86__ + struct user_fpxregs_struct x387; +#endif + uint8_t xstate[X86_XSTATE_MAX_SIZE]; + struct iovec ymm_iov; + + // clsmask helpers + bool clsmask_regs; + bool clsmask_fpregs; +#ifdef __X86__ + bool clsmask_fpxregs; +#endif + bool clsmask_ymm; + + regctx_t(dynamic_register_set_t &_idaregs); + bool init(void); + bool load(void); + bool store(void); +}; + +//-------------------------------------------------------------------------- +regctx_t::regctx_t(dynamic_register_set_t &_idaregs) + : regctx_base_t(_idaregs) +{ + memset(®s, 0, sizeof(regs)); + memset(&i387, 0, sizeof(i387)); +#ifdef __X86__ + memset(&x387, 0, sizeof(x387)); +#endif + memset(xstate, 0, sizeof(xstate)); + + clsmask_regs = 0; + clsmask_fpregs = 0; +#ifdef __X86__ + clsmask_fpxregs = 0; +#endif + clsmask_ymm = 0; + + ymm_iov.iov_base = xstate; + ymm_iov.iov_len = sizeof(xstate); + + idaregs.set_regclasses(x86_register_classes); +} + +//-------------------------------------------------------------------------- +bool regctx_t::init(void) +{ + if ( (clsmask & X86_RC_ALL) == 0 ) + return false; + // setup clsmask helpers + clsmask_regs = (clsmask & (X86_RC_GENERAL|X86_RC_SEGMENTS)) != 0; +#ifdef __X86__ + // 32-bit version uses two different structures to return xmm & fpu + clsmask_fpregs = (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0; + clsmask_fpxregs = (clsmask & X86_RC_XMM) != 0; +#else + // 64-bit version uses one struct to return xmm & fpu + clsmask_fpregs = (clsmask & (X86_RC_FPU|X86_RC_MMX|X86_RC_XMM)) != 0; +#endif + clsmask_ymm = (clsmask & X86_RC_YMM) != 0; + return true; +} + +//-------------------------------------------------------------------------- +bool regctx_t::load(void) +{ + if ( !init() ) + return false; + if ( clsmask_regs ) + if ( qptrace(PTRACE_GETREGS, tid, 0, ®s) != 0 ) + return false; + // Note: On linux kernels older than 4.8, the ptrace call to fetch + // registers from xstate did not sanitize the state before + // copying data to user-space. If only the YMM register class + // was requested (and not fp or fpx), this could lead to IDA + // having stale data on the lower half of the YMM registers. + // The ptrace calls to fetch fp or fpx registers do sanitize + // the state. This is the only reason we may also get the fp + // registers when the YMM register class is requested, but + // the fp and fpx registers were not requested. The order is + // important in this case (first fp or fpx, then xstate). +#ifdef __X86__ + bool xstate_sanitized = clsmask_fpregs || clsmask_fpxregs; +#else + bool xstate_sanitized = clsmask_fpregs; +#endif + if ( clsmask_fpregs || (clsmask_ymm && !xstate_sanitized) ) + if ( qptrace(PTRACE_GETFPREGS, tid, 0, &i387) != 0 ) + return false; +#ifdef __X86__ + if ( clsmask_fpxregs ) + if ( qptrace(PTRACE_GETFPXREGS, tid, 0, &x387) != 0 ) + return false; +#endif + if ( clsmask_ymm ) + if ( !qptrace_get_regset(&ymm_iov, NT_X86_XSTATE, tid) ) + return false; + return true; +} + +//-------------------------------------------------------------------------- +bool regctx_t::store(void) +{ + if ( clsmask_regs ) + if ( qptrace(PTRACE_SETREGS, tid, 0, ®s) != 0 ) + return false; + // The order of the following calls is VERY IMPORTANT so as + // PTRACE_SETFPXREGS can spoil FPU registers. + // The subsequent call to PTRACE_SETFPREGS will correct them. + // Could it be better to get rid of PTRACE_SETFPREGS and use + // PTRACE_SETFPXREGS for both FPU and XMM registers instead? + if ( clsmask_ymm ) + if ( !qptrace_set_regset(NT_X86_XSTATE, tid, ymm_iov) ) + return false; +#ifdef __X86__ + if ( clsmask_fpxregs ) + if ( qptrace(PTRACE_SETFPXREGS, tid, 0, &x387) != 0 ) + return false; +#endif + if ( clsmask_fpregs ) + if ( qptrace(PTRACE_SETFPREGS, tid, 0, &i387) != 0 ) + return false; + return true; +} + +//-------------------------------------------------------------------------- +static void ftag_read(const regctx_t *ctx, regval_t *value, void * /*user_data*/) +{ + uint32_t ival = ctx->i387.TAGS_REG; +#ifndef __X86__ + // fix 'ftag': + // --- + // Byte 4 is used for an abridged version of the x87 FPU Tag + // Word (FTW). The following items describe its usage: + // — For each j, 0 <= j <= 7, FXSAVE saves a 0 into bit j of + // byte 4 if x87 FPU data register STj has a empty tag; + // otherwise, FXSAVE saves a 1 into bit j of byte 4. + // (...) + // --- + // See also the opposite conversion when writing registers + // (look for 'abridged'.) + uint8_t abridged = ival; + int top = (ctx->i387.swd >> 11) & 0x7; + uint16_t ftag = 0; + for ( int st_idx = 7; st_idx >= 0; --st_idx ) + { + uint16_t tag = TAG_EMPTY; + if ( (abridged & (1 << st_idx)) != 0 ) + { + int actual_st = (st_idx + 8 - top) % 8; + const uint8_t *p = ((const uint8_t *) ctx->i387.st_space) + actual_st * (sizeof(ctx->i387.st_space)/8); //-V706 Suspicious division + bool integer = (p[7] & 0x80) != 0; + uint32 exp = ((p[9] & 0x7f) << 8) | p[8]; //-V557 Array overrun is possible + uint32 frac0 = ((p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); + uint32 frac1 = (((p[7] & 0x7f) << 24) | (p[6] << 16) | (p[5] << 8) | p[4]); + if ( exp == 0x7fff ) + tag = TAG_SPECIAL; + else if ( exp == 0 ) + tag = (frac0 == 0 && frac1 == 0 && !integer) ? TAG_ZERO : TAG_SPECIAL; + else + tag = integer ? TAG_VALID : TAG_SPECIAL; + } + ftag |= tag << (2 * st_idx); + } + ival = ftag; +#endif + value->ival = ival; +} + +//-------------------------------------------------------------------------- +static void ftag_write(regctx_t *ctx, const regval_t *value, void * /*user_data*/) +{ +#ifndef __X86__ + // => abridged + // See also the opposite conversion when reading registers + // (look for 'abridged'.) + // + // NOTE: This assumes that i387.swd _IS UP-TO-DATE_. + // If it has to be overwritten later in the same batch of + // updates, its new value won't be used here. + uint16_t expanded = value->ival; + uint8_t tags = 0; + int top = (ctx->i387.swd >> 11) & 0x7; + for ( int st_idx = 7; st_idx >= 0; --st_idx ) + if ( ((expanded >> (2 * st_idx)) & 3) != TAG_EMPTY ) + tags |= uint8_t(1 << ((st_idx + 8 - top) % 8)); + ctx->i387.TAGS_REG = tags; +#else + ctx->i387.TAGS_REG = value->ival; +#endif +} + +//-------------------------------------------------------------------------- +static void ymm_read(const regctx_t *ctx, regval_t *value, void *user_data) +{ + size_t ymm_reg_idx = size_t(user_data); + const uint128 *ptrl = (uint128 *) &ctx->xstate[XSAVE_XMM_OFFSET_BASE]; + const uint128 *ptrh = (uint128 *) &ctx->xstate[XSAVE_YMMH_OFFSET_BASE]; + uint8_t ymm[32]; + *(uint128 *) &ymm[ 0] = ptrl[ymm_reg_idx]; + *(uint128 *) &ymm[16] = ptrh[ymm_reg_idx]; + value->set_bytes(ymm, sizeof(ymm)); +} + +//-------------------------------------------------------------------------- +static void ymm_write(regctx_t *ctx, const regval_t *value, void *user_data) +{ + size_t ymm_reg_idx = size_t(user_data); + const uint8_t *ymm = (const uint8_t *) value->get_data(); + uint128 *ptrl = (uint128 *) &ctx->xstate[XSAVE_XMM_OFFSET_BASE]; + uint128 *ptrh = (uint128 *) &ctx->xstate[XSAVE_YMMH_OFFSET_BASE]; + ptrl[ymm_reg_idx] = *(uint128 *) &ymm[ 0]; + ptrh[ymm_reg_idx] = *(uint128 *) &ymm[16]; + ctx->xstate[XSAVE_XSTATE_BV] |= X86_XSTATE_SSE | X86_XSTATE_AVX; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::init_reg_ctx(void) +{ + reg_ctx = new regctx_t(idaregs); + + // Populate register context + size_t offset = 0; + +#ifdef __EA64__ + bool is_64 = debapp_attrs.addrsize > 4; + if ( is_64 ) + { + reg_ctx->add_ival(r_rax, offset_size(regs, INTEL_REG(ax))); + reg_ctx->add_ival(r_rbx, offset_size(regs, INTEL_REG(bx))); + reg_ctx->add_ival(r_rcx, offset_size(regs, INTEL_REG(cx))); + reg_ctx->add_ival(r_rdx, offset_size(regs, INTEL_REG(dx))); + reg_ctx->add_ival(r_rsi, offset_size(regs, INTEL_REG(si))); + reg_ctx->add_ival(r_rdi, offset_size(regs, INTEL_REG(di))); + reg_ctx->add_ival(r_rbp, offset_size(regs, INTEL_REG(bp))); + sp_idx = reg_ctx->add_ival(r_rsp, offset_size(regs, INTEL_REG(sp))); + pc_idx = reg_ctx->add_ival(r_rip, offset_size(regs, INTEL_REG(ip))); + reg_ctx->add_ival(r_r8, offset_size(regs, r8)); + reg_ctx->add_ival(r_r9, offset_size(regs, r9)); + reg_ctx->add_ival(r_r10, offset_size(regs, r10)); + reg_ctx->add_ival(r_r11, offset_size(regs, r11)); + reg_ctx->add_ival(r_r12, offset_size(regs, r12)); + reg_ctx->add_ival(r_r13, offset_size(regs, r13)); + reg_ctx->add_ival(r_r14, offset_size(regs, r14)); + reg_ctx->add_ival(r_r15, offset_size(regs, r15)); + } + else +#endif + { + reg_ctx->add_ival(r_eax, offset_size(regs, INTEL_REG(ax))); + reg_ctx->add_ival(r_ebx, offset_size(regs, INTEL_REG(bx))); + reg_ctx->add_ival(r_ecx, offset_size(regs, INTEL_REG(cx))); + reg_ctx->add_ival(r_edx, offset_size(regs, INTEL_REG(dx))); + reg_ctx->add_ival(r_esi, offset_size(regs, INTEL_REG(si))); + reg_ctx->add_ival(r_edi, offset_size(regs, INTEL_REG(di))); + reg_ctx->add_ival(r_ebp, offset_size(regs, INTEL_REG(bp))); + sp_idx = reg_ctx->add_ival(r_esp, offset_size(regs, INTEL_REG(sp))); + pc_idx = reg_ctx->add_ival(r_eip, offset_size(regs, INTEL_REG(ip))); + } + sr_idx = reg_ctx->add_ival(arch_registers[R_EFLAGS], offset_size(regs, eflags)); + + cs_idx = reg_ctx->add_ival(arch_registers[R_CS], offset_size(regs, INTEL_SREG(cs))); + ds_idx = reg_ctx->add_ival(arch_registers[R_DS], offset_size(regs, INTEL_SREG(ds))); + es_idx = reg_ctx->add_ival(arch_registers[R_ES], offset_size(regs, INTEL_SREG(es))); + fs_idx = reg_ctx->add_ival(arch_registers[R_FS], offset_size(regs, INTEL_SREG(fs))); + gs_idx = reg_ctx->add_ival(arch_registers[R_GS], offset_size(regs, INTEL_SREG(gs))); + ss_idx = reg_ctx->add_ival(arch_registers[R_SS], offset_size(regs, INTEL_SREG(ss))); + + offset = qoffsetof2(i387, st_space); + for ( size_t i = R_ST0; i <= R_ST7; i++, offset += sizeof(regctx_t::i387.st_space)/8 ) //-V706 Suspicious division + reg_ctx->add_fval(arch_registers[i], offset, 10); + reg_ctx->add_ival(arch_registers[R_CTRL], offset_size(i387, cwd)); + reg_ctx->add_ival(arch_registers[R_STAT], offset_size(i387, swd)); + reg_ctx->add_func(arch_registers[R_TAGS], ftag_read, ftag_write); + + offset = qoffsetof2(i387, st_space); + for ( size_t i = R_MMX0; i <= R_MMX7; i++, offset += sizeof(regctx_t::i387.st_space)/8 ) //-V706 Suspicious division + reg_ctx->add_data(arch_registers[i], offset, 8); + + offset = qoffsetof2(XMM_STRUCT, xmm_space); + for ( size_t i = R_XMM0; i <= R_LAST_XMM; i++, offset += 16 ) + { +#ifdef __EA64__ + if ( !is_64 && i >= R_XMM8 ) + break; +#endif + reg_ctx->add_data(arch_registers[i], offset, 16); + } + reg_ctx->add_ival(arch_registers[R_MXCSR], offset_size(XMM_STRUCT, mxcsr)); + + for ( size_t i = R_YMM0; i <= R_LAST_YMM; i++ ) + { +#ifdef __EA64__ + if ( !is_64 && i >= R_YMM8 ) + break; +#endif + reg_ctx->add_func(arch_registers[i], ymm_read, ymm_write, (void *) (i - R_YMM0)); + } +} +#endif // !__ARM__ + +//-------------------------------------------------------------------------- +void linux_debmod_t::term_reg_ctx(void) +{ + if ( reg_ctx != nullptr ) + { + delete reg_ctx; + idaregs.clear(); + } + reg_ctx = nullptr; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_read_registers( + thid_t tid, + int clsmask, + regval_t *values, + qstring * /*errbuf*/) +{ + if ( values == nullptr ) + return DRC_FAILED; + + reg_ctx->setup(tid, clsmask); + if ( !reg_ctx->load() ) + return DRC_FAILED; + + reg_ctx->read_all(values); + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_write_register( + thid_t tid, + int reg_idx, + const regval_t *value, + qstring * /*errbuf*/) +{ + if ( value == nullptr ) + return DRC_FAILED; + + reg_ctx->setup(tid); + reg_ctx->setup_reg(reg_idx); + if ( !reg_ctx->load() ) + return DRC_FAILED; + + if ( reg_idx == pc_idx ) + ldeb("NEW EIP: %08" FMT_64 "X\n", value->ival); + + if ( !reg_ctx->patch(reg_idx, value) ) + return DRC_FAILED; + + if ( !reg_ctx->store() ) + return DRC_FAILED; + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +bool idaapi linux_debmod_t::write_registers( + thid_t tid, + int start, + int count, + const regval_t *values) +{ + if ( values == nullptr ) + return false; + + reg_ctx->setup(tid); + for ( size_t i = 0; i < count; i++ ) + reg_ctx->setup_reg(start + i); + if ( !reg_ctx->load() ) + return false; + + for ( size_t i = 0; i < count; i++, values++ ) + if ( !reg_ctx->patch(start + i, values) ) + return false; + + if ( !reg_ctx->store() ) + return false; + + return true; +} + +//-------------------------------------------------------------------------- +// find DT_SONAME of a elf image directly from the memory +bool linux_debmod_t::get_soname(const char *fname, qstring *soname) const +{ + struct dll_soname_finder_t : public symbol_visitor_t + { + qstring *soname; + dll_soname_finder_t(qstring *res) : symbol_visitor_t(VISIT_DYNINFO), soname(res) {} + virtual int visit_dyninfo(uint64 tag, const char *name, uint64 /*value*/) override + { + if ( tag == DT_SONAME ) + { + *soname = name; + return 1; + } + return 0; + } + }; + + dll_soname_finder_t dsf(soname); + return load_elf_symbols(fname, dsf) == 1; +} + +//-------------------------------------------------------------------------- +asize_t linux_debmod_t::calc_module_size(const meminfo_vec_t &miv, const memory_info_t *mi) const +{ + QASSERT(30067, miv.begin() <= mi && mi < miv.end()); + ea_t start = mi->start_ea; + ea_t end = mi->end_ea; + if ( end == 0 ) + return 0; // unknown size + const qstring &name = mi->name; + while ( ++mi != miv.end() ) + { + if ( name != mi->name ) + break; + end = mi->end_ea; + } + QASSERT(30068, end > start); + return end - start; +} + +//-------------------------------------------------------------------------- +// may add/del threads! +void linux_debmod_t::handle_dll_movements(const meminfo_vec_t &_miv) +{ + ldeb("handle_dll_movements\n"); + + // first, merge memory ranges by module + meminfo_vec_t miv; + for ( size_t i = 0, n = _miv.size(); i < n; ++i ) + { + const memory_info_t &src = _miv[i]; + + // See if we already registered a module with that name. + memory_info_t *target = find_first_mapping(miv, src.name.c_str()); + if ( target != NULL ) + { + // Found one. Let's make sure it contains our addresses. + target->extend(src.start_ea); + target->extend(src.end_ea); + } + else + { + miv.push_back(src); + } + } + + // unload missing dlls + images_t::iterator p; + for ( p=dlls.begin(); p != dlls.end(); ) + { + image_info_t &ii = p->second; + const char *fname = ii.fname.c_str(); + if ( find_first_mapping(miv, fname) == NULL ) + { + if ( !del_pending_event(LIB_LOADED, fname) ) + { + debug_event_t ev; + ev.set_info(LIB_UNLOADED) = fname; + ev.pid = process_handle; + ev.tid = process_handle; + ev.ea = BADADDR; + ev.handled = true; + enqueue_event(ev, IN_FRONT); + } + p = dlls.erase(p); + } + else + { + ++p; + } + } + + // load new dlls + int n = miv.size(); + for ( int i=0; i < n; i++ ) + { + // ignore unnamed dlls + if ( miv[i].name.empty() ) + continue; + + // ignore the input file + if ( !is_dll && miv[i].name == input_file_path ) + continue; + + // ignore if dll already exists + ea_t base = miv[i].start_ea; + p = dlls.find(base); + if ( p != dlls.end() ) + continue; + + // ignore memory chunks which do not correspond to an ELF header + char magic[4]; + if ( _read_memory(-1, base, magic, 4, false) != 4 ) + continue; + + if ( memcmp(magic, "\x7F\x45\x4C\x46", 4) != 0 ) + continue; + + qstring soname; + const char *modname = miv[i].name.c_str(); + get_soname(modname, &soname); + asize_t size = calc_module_size(miv, &miv[i]); + add_dll(base, size, modname, soname.c_str()); + } + if ( !dlls_to_import.empty() ) + activate_multithreading(); +} + +//-------------------------------------------------------------------------- +// this function has a side effect: it sets debapp_attrs.addrsize to 8 +// if founds a 64-bit address in the mapfile +bool linux_debmod_t::read_mapping(mapfp_entry_t *me) +{ + qstring line; + if ( qgetline(&line, mapfp) <= 0 ) + return false; + + me->ea1 = BADADDR; + me->bitness = 0; + int len = 0; + me->perm[7] = '\0'; + me->device[7] = '\0'; + CASSERT(sizeof(me->perm) == 8); + CASSERT(sizeof(me->device) == 8); + int code = qsscanf(line.begin(), "%a-%a %7s %a %7s %" FMT_64 "x%n", + &me->ea1, &me->ea2, me->perm, + &me->offset, me->device, &me->inode, &len); + if ( code == 6 ) + { + me->bitness = 1; + size_t pos = line.find('-'); + if ( pos != qstring::npos && pos > 8 ) + { + me->bitness = 2; + debapp_attrs.addrsize = 8; + } + char *ptr = line.begin() + len; + ptr = skip_spaces(ptr); + // remove trailing spaces and eventual (deleted) suffix + static const char delsuff[] = " (deleted)"; + const int suflen = sizeof(delsuff) - 1; + char *end = tail(ptr); + while ( end > ptr && qisspace(end[-1]) ) + *--end = '\0'; + if ( end-ptr > suflen && strncmp(end-suflen, delsuff, suflen) == 0 ) + end[-suflen] = '\0'; + me->fname = ptr; + } + return me->ea1 != BADADDR; +} + +//-------------------------------------------------------------------------- +drc_t linux_debmod_t::get_memory_info(meminfo_vec_t &miv, bool suspend) +{ + ldeb("get_memory_info(suspend=%d)\n", suspend); + if ( exited || mapfp == NULL ) + return DRC_NOPROC; + if ( suspend ) + suspend_all_threads(); + + rewind(mapfp); + mapfp_entry_t me; + qstrvec_t possible_interp; + int bitness = 1; + while ( read_mapping(&me) ) + { + // skip empty ranges + if ( me.empty() ) + continue; + + if ( interp.empty() && !me.fname.empty() && !possible_interp.has(me.fname) ) + { + // check for [.../]ld-XXX.so" + size_t pos = me.fname.find("ld-"); + if ( pos != qstring::npos && (pos == 0 || me.fname[pos-1] == '/') ) + possible_interp.push_back(me.fname); + } + + // for some reason linux lists some ranges twice + // ignore them + int i; + for ( i=0; i < miv.size(); i++ ) + if ( miv[i].start_ea == me.ea1 ) + break; + if ( i != miv.size() ) + continue; + + memory_info_t &mi = miv.push_back(); + mi.start_ea = me.ea1; + mi.end_ea = me.ea2; + mi.name.swap(me.fname); +#ifdef __ANDROID__ + // android reports simple library names without path. try to find it. + make_android_abspath(&mi.name); +#endif + mi.bitness = me.bitness; + //msg("%s: %a..%a. Bitness: %d\n", mi.name.c_str(), mi.start_ea, mi.end_ea, mi.bitness); + + if ( bitness < mi.bitness ) + bitness = mi.bitness; + + if ( strchr(me.perm, 'r') != NULL ) + mi.perm |= SEGPERM_READ; + if ( strchr(me.perm, 'w') != NULL ) + mi.perm |= SEGPERM_WRITE; + if ( strchr(me.perm, 'x') != NULL ) + mi.perm |= SEGPERM_EXEC; + } + + if ( !possible_interp.empty() ) + { + bool ok = false; + + for ( size_t i = 0; i < possible_interp.size(); ++i ) + { + interp = possible_interp[i]; + debdeb("trying potential interpreter %s\n", interp.c_str()); + if ( add_shlib_bpt(miv, true) ) + { + ok = true; + dmsg("Found a valid interpeter in %s, will report shared library events!\n", interp.c_str()); + handle_dll_movements(miv); + } + } + + if ( !ok ) + interp.qclear(); + } + + // During the parsing of each memory segment we had just guessed the bitness. + // So fix now bitness of all memory segments + for ( int i = 0; i < miv.size(); i++ ) + miv[i].bitness = bitness; + + if ( suspend ) + resume_all_threads(); + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_get_memory_info(meminfo_vec_t &ranges, qstring * /*errbuf*/) +{ + drc_t drc = get_memory_info(ranges, false); + if ( drc == DRC_OK ) + { + if ( same_as_oldmemcfg(ranges) ) + drc = DRC_NOCHG; + else + save_oldmemcfg(ranges); + } + return drc; +} + +//-------------------------------------------------------------------------- +linux_debmod_t::~linux_debmod_t() +{ + term_reg_ctx(); + mapfp = NULL; + ta = NULL; +} + +//-------------------------------------------------------------------------- +void idaapi linux_debmod_t::dbg_set_debugging(bool _debug_debugger) +{ + debug_debugger = _debug_debugger; +} + +//-------------------------------------------------------------------------- +drc_t idaapi linux_debmod_t::dbg_init(uint32_t *flags2, qstring * /*errbuf*/) +{ + dbg_term(); // initialize various variables + if ( flags2 != nullptr ) + *flags2 = DBG_HAS_GET_PROCESSES | DBG_HAS_DETACH_PROCESS; + return DRC_OK; +} + +//-------------------------------------------------------------------------- +void idaapi linux_debmod_t::dbg_term(void) +{ + cleanup(); + cleanup_hwbpts(); +} + +//-------------------------------------------------------------------------- +//lint -save -esym(818,pea) could be pointer to const +bool idaapi linux_debmod_t::thread_get_fs_base(thid_t tid, int reg_idx, ea_t *pea) const +{ +#if !defined(__ARM__) && !defined(__X86__) + + /* The following definitions come from prctl.h, but may be absent + for certain configurations. */ + #ifndef ARCH_GET_FS + #define ARCH_SET_GS 0x1001 + #define ARCH_SET_FS 0x1002 + #define ARCH_GET_FS 0x1003 + #define ARCH_GET_GS 0x1004 + #endif + + if ( reg_idx == fs_idx ) + { + if ( qptrace(PTRACE_ARCH_PRCTL, tid, pea, (void *) ARCH_GET_FS) == 0 ) + return true; + } + else if ( reg_idx == gs_idx ) + { + if ( qptrace(PTRACE_ARCH_PRCTL, tid, pea, (void *) ARCH_GET_GS) == 0 ) + return true; + } + else if ( reg_idx == cs_idx + || reg_idx == ds_idx + || reg_idx == es_idx + || reg_idx == ss_idx ) + { + *pea = 0; + return true; + } + return false; +#else + qnotused(tid); + qnotused(reg_idx); + qnotused(pea); + return false; +#endif +} //lint -restore + +//-------------------------------------------------------------------------- +int idaapi linux_debmod_t::handle_ioctl(int fn, const void *in, size_t, void **, ssize_t *) +{ + if ( fn == 0 ) // chmod +x + { + // this call is not used anymore + char *fname = (char *)in; + qstatbuf st; + qstat(fname, &st); + int mode = st.qst_mode | S_IXUSR|S_IXGRP|S_IXOTH; + chmod(fname, mode); + } + return 0; +} + +//-------------------------------------------------------------------------- +// recovering from a broken session consists in the following steps: +// +// 1 - Cleanup dlls previously recorded. +// 2 - Do like if we were attaching (calling handle_process_start(attaching=>AMT_ATTACH_BROKEN)) +// 3 - Generate library events. +// 4 - Restore RIP/EIP if we stopped in a breakpoint. +// +bool idaapi linux_debmod_t::dbg_continue_broken_connection(pid_t _pid) +{ + debmod_t::dbg_continue_broken_connection(_pid); + bool ret = in_event = false; + + // cleanup previously recorded information + dlls.clear(); + + // restore broken breakpoints and continue like a normal attach + if ( restore_broken_breakpoints() && handle_process_start(_pid, AMT_ATTACH_BROKEN) ) + { + // generate all library events + gen_library_events(_pid); + + // fix instruction pointer in case we're at a breakpoint + if ( !fix_instruction_pointer() ) + dmsg("Debugger failed to correctly restore the instruction pointer after recovering from a broken connection.\n"); + + // and finally pause the process + ret = true; + } + return ret; +} + +//-------------------------------------------------------------------------- +// if the process was stopped at a breakpoint and then the connections goes +// down, when re-attaching the process we may be at EIP+1 (Intel procs) so +// we need to change EIP to EIP-1 +bool linux_debmod_t::fix_instruction_pointer(void) const +{ + bool ret = true; +#if !defined(__ARM__) + if ( last_event.eid() == BREAKPOINT ) + { + ret = false; + struct user_regs_struct regs; + if ( qptrace(PTRACE_GETREGS, last_event.tid, 0, ®s) == 0 ) + { + if ( last_event.ea == regs.PCREG-1 ) + regs.PCREG--; + + ret = qptrace(PTRACE_SETREGS, last_event.tid, 0, ®s) == 0; + } + } +#endif + return ret; +} + +//-------------------------------------------------------------------------- +bool init_subsystem() +{ + init_multithreading(); + qatexit(kill_all_processes); + linux_debmod_t::reuse_broken_connections = true; + return true; +} + +//-------------------------------------------------------------------------- +bool term_subsystem() +{ + del_qatexit(kill_all_processes); + term_multithreading(); + return true; +} + +//-------------------------------------------------------------------------- +debmod_t *create_debug_session(void *params) +{ +#ifdef TESTABLE_BUILD + // new_client_handler(), and thus create_debug_session() is called from + // the main thread, so we don't risk a race for setting up the resolver. + if ( per_pid_elf_dbgdir_resolver == NULL ) + per_pid_elf_dbgdir_resolver = (per_pid_elf_dbgdir_resolver_t *) params; //lint !e611 cast between pointer to function type '' and pointer to object type 'void *' +#else + qnotused(params); +#endif + return new linux_debmod_t(); +} diff --git a/idasdk76/dbg/linux/linux_debmod.h b/idasdk76/dbg/linux/linux_debmod.h new file mode 100644 index 0000000..28b41b5 --- /dev/null +++ b/idasdk76/dbg/linux/linux_debmod.h @@ -0,0 +1,352 @@ +#ifndef __LINUX_DEBUGGER_MODULE__ +#define __LINUX_DEBUGGER_MODULE__ + +#include <signal.h> +#include <sys/ptrace.h> +#include <sys/wait.h> +#include <sys/user.h> + +#include "linuxbase_debmod.h" + +extern "C" +{ +#include <thread_db.h> +} + +#include <deque> + +typedef int HANDLE; +typedef uint32 DWORD; +#define INVALID_HANDLE_VALUE (-1) + +using std::pair; +using std::make_pair; + +//-------------------------------------------------------------------------- +typedef std::map<ea_t, qstring> ea2name_t; +typedef std::map<qstring, ea_t> name2ea_t; + +#ifndef WCONTINUED +#define WCONTINUED 8 +#endif + +#ifndef __WALL +#define __WALL 0x40000000 +#endif + +//-------------------------------------------------------------------------- +// image information +struct image_info_t +{ + image_info_t() : base(BADADDR), size(0), dl_crc(0) {} + image_info_t( + ea_t _base, + asize_t _size, + const qstring &_fname, + const qstring &_soname) + : base(_base), size(_size), fname(_fname), soname(_soname), dl_crc(0) {} + ea_t base; + asize_t size; // image size, currently 0 + qstring fname; + qstring soname; + ea2name_t names; + qstring buildid; + qstring debuglink; + uint32 dl_crc; +}; +typedef std::map<ea_t, image_info_t> images_t; // key: image base address + +//-------------------------------------------------------------------------- +enum thstate_t +{ + RUNNING, // running + STOPPED, // waiting to be resumed after qwait + DYING, // we got a notification that the thread is about to die + DEAD, // dead thread; ignore any signals from it +}; + +//-------------------------------------------------------------------------- +// thread information +struct thread_info_t +{ + thread_info_t(int t) + : tid(t), suspend_count(0), user_suspend(0), child_signum(0), single_step(false), + state(STOPPED), waiting_sigstop(false), got_pending_status(false), pending_status(0) {} + int tid; + int suspend_count; + int user_suspend; + int child_signum; + bool single_step; + thstate_t state; + bool waiting_sigstop; + bool got_pending_status; + int pending_status; + qstring name; // thread name + bool is_running(void) const + { + return state == RUNNING && !waiting_sigstop && !got_pending_status; + } +}; + +//-------------------------------------------------------------------------- +typedef std::map<HANDLE, thread_info_t> threads_t; // (tid -> info) + +//-------------------------------------------------------------------------- +enum ps_err_e +{ + PS_OK, /* Success. */ + PS_ERR, /* Generic error. */ + PS_BADPID, /* Bad process handle. */ + PS_BADLID, /* Bad LWP id. */ + PS_BADADDR, /* Bad address. */ + PS_NOSYM, /* Symbol not found. */ + PS_NOFREGS /* FPU register set not available. */ +}; +struct ps_prochandle +{ + pid_t pid; +}; + +#ifndef UINT32_C +# define UINT32_C uint32 +#endif + +//-------------------------------------------------------------------------- +struct internal_bpt +{ + ea_t bpt_addr; + uchar saved[BPT_CODE_SIZE]; + uchar nsaved; + internal_bpt(): bpt_addr(0), nsaved(0) {} //-V730 Not all members of a class are initialized +}; + +//-------------------------------------------------------------------------- +struct mapfp_entry_t +{ + ea_t ea1; + ea_t ea2; + ea_t offset; + uint64 inode; + char perm[8]; + char device[8]; + uint8 bitness; // Number of bits in segment addresses (0-16bit, 1-32bit, 2-64bit) + qstring fname; + bool empty(void) const { return ea1 >= ea2; } +}; + +//-------------------------------------------------------------------------- +struct chk_signal_info_t +{ + pid_t pid; + int status; + int timeout_ms; + + chk_signal_info_t(int _timeout_ms) + { + timeout_ms = _timeout_ms; + pid = 0; + status = 0; + } +}; + +//-------------------------------------------------------------------------- +enum attach_mode_t +{ + AMT_NO_ATTACH, + AMT_ATTACH_NORMAL, + AMT_ATTACH_BROKEN +}; + +//-------------------------------------------------------------------------- +class linux_debmod_t: public linuxbase_debmod_t +{ + typedef linuxbase_debmod_t inherited; + + // thread_db related data and functions: + struct ps_prochandle prochandle; + td_thragent_t *ta; + + internal_bpt birth_bpt; // thread created + internal_bpt death_bpt; // thread exited + internal_bpt shlib_bpt; // shared lib list changed + bool complained_shlib_bpt; + + void make_android_abspath(qstring *in_out_path); + bool add_android_shlib_bpt(const meminfo_vec_t &miv, bool attaching); + + bool add_internal_bp(internal_bpt &bp, ea_t addr); + bool erase_internal_bp(internal_bpt &bp); + + bool tdb_enable_event(td_event_e event, internal_bpt *bp); + void tdb_update_threads(void); + bool tdb_new(void); + void tdb_delete(void); + void tdb_handle_messages(int pid); + void dead_thread(int tid, thstate_t state); + void store_pending_signal(int pid, int status); + + bool activate_multithreading(); + + // procfs + void procfs_collect_threads(void); + bool attach_collected_thread(unsigned long lwp); + bool get_thread_name(qstring *thr_name, thid_t tid); + void update_thread_names(thread_name_vec_t *thr_names); + + // list of debug names not yet sent to IDA + name_info_t pending_names; + name_info_t nptl_names; + + pid_t check_for_signal(int *status, int pid, int timeout_ms) const; + + int find_largest_addrsize(const meminfo_vec_t &miv); + void _import_dll(image_info_t &ii); + void _import_symbols_from_file(name_info_t *out, image_info_t &ii); + +public: + easet_t dlls_to_import; // list of dlls to import information from + images_t dlls; // list of loaded DLLs + threads_t threads; + qvector<thid_t> deleted_threads; + qvector<thid_t> seen_threads; // thread was born and appeared too early + + // debugged process information + HANDLE process_handle; + HANDLE thread_handle; + bool threads_collected = false; + + bool exited; // Did the process exit? + + easet_t removed_bpts; // removed breakpoints + + FILE *mapfp; // map file handle + + int npending_signals; // number of pending signals + bool may_run; + bool requested_to_suspend; + bool in_event; // IDA kernel is handling a debugger event + + qstring interp; + + qstring exe_path; // name of the executable file + + ea_t nptl_base; // base of 'libpthread.so' + + regctx_t *reg_ctx; + + linux_debmod_t(); + ~linux_debmod_t(); + + void init_reg_ctx(void); + void term_reg_ctx(void); + + thread_info_t &add_thread(int tid); + void del_thread(int tid); + thread_info_t *get_thread(thid_t tid); + bool retrieve_pending_signal(pid_t *pid, int *status); + int get_debug_event(debug_event_t *event, int timeout_ms); + bool del_pending_event(event_id_t id, const char *module_name); + void enqueue_event(const debug_event_t &ev, queue_pos_t pos); + bool suspend_all_threads(void); + bool resume_all_threads(void); + int dbg_freeze_threads(thid_t tid, bool exclude=true); + int dbg_thaw_threads(thid_t tid, bool exclude=true); + void set_thread_state(thread_info_t &ti, thstate_t state) const; + bool resume_app(thid_t tid); + bool has_pending_events(void); + bool read_asciiz(tid_t tid, ea_t ea, char *buf, size_t bufsize, bool suspend=false); + int _read_memory(int tid, ea_t ea, void *buffer, int size, bool suspend=false); + int _write_memory(int tid, ea_t ea, const void *buffer, int size, bool suspend=false); + void add_dll(ea_t base, asize_t size, const char *modname, const char *soname); + asize_t calc_module_size(const meminfo_vec_t &miv, const memory_info_t *mi) const; + void enum_names(const char *libpath=NULL); + bool add_shlib_bpt(const meminfo_vec_t &miv, bool attaching); + bool gen_library_events(int tid); + bool emulate_retn(int tid); + void cleanup(void); + bool handle_process_start(pid_t pid, attach_mode_t attaching); + drc_t get_memory_info(meminfo_vec_t &areas, bool suspend); + bool set_hwbpts(HANDLE hThread) const; + virtual bool refresh_hwbpts() override; + void handle_dll_movements(const meminfo_vec_t &miv); + bool idaapi thread_get_fs_base(thid_t tid, int reg_idx, ea_t *pea) const; + bool read_mapping(mapfp_entry_t *me); + bool get_soname(const char *fname, qstring *soname) const; + ea_t find_pending_name(const char *name); + bool handle_hwbpt(debug_event_t *event); + bool thread_is_known(const td_thrinfo_t &info) const; + bool listen_thread_events(const td_thrinfo_t &info, const td_thrhandle_t *th_p); + void attach_to_thread(const td_thrinfo_t &info); + bool attach_to_thread(int tid, ea_t ea); + void handle_extended_wait(bool *handled, const chk_signal_info_t &csi); + bool finish_attaching(int tid, ea_t ea, bool use_ip); + bool check_for_new_events(chk_signal_info_t *csi, bool *event_prepared); + + // + virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; + virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; + virtual void idaapi dbg_term(void) override; + virtual drc_t idaapi dbg_detach_process(void) override; + virtual drc_t idaapi dbg_start_process( + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf) override; + virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; + virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) override; + virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; + virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; + virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; + virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) override; + virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; + virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; + virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; + virtual drc_t idaapi dbg_read_registers( + thid_t thread_id, + int clsmask, + regval_t *values, + qstring *errbuf) override; + virtual drc_t idaapi dbg_write_register( + thid_t thread_id, + int reg_idx, + const regval_t *value, + qstring *errbuf) override; + virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) override; + virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &areas, qstring *errbuf) override; + virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; + virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; + virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; + virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; + virtual int idaapi handle_ioctl(int fn, const void *buf, size_t size, void **outbuf, ssize_t *outsize) override; + virtual bool idaapi write_registers( + thid_t tid, + int start, + int count, + const regval_t *values) override; + virtual int dbg_freeze_threads_except(thid_t tid) override { return dbg_freeze_threads(tid); } + virtual int dbg_thaw_threads_except(thid_t tid) override { return dbg_thaw_threads(tid); } + + virtual bool idaapi dbg_continue_broken_connection(pid_t pid) override; + virtual bool idaapi dbg_prepare_broken_connection(void) override; + + // thread_db + void display_thrinfo(thid_t tid); + void display_all_threads(); + + void cleanup_breakpoints(void); + void cleanup_signals(void); + + bool fix_instruction_pointer(void) const; +#ifdef __ARM__ + virtual void adjust_swbpt(ea_t *p_ea, int *p_len) override; +#endif + +#ifdef LDEB + void log(thid_t tid, const char *format, ...); +#endif +}; + +#endif diff --git a/idasdk75/dbg/linux/linux_debmod.script b/idasdk76/dbg/linux/linux_debmod.script similarity index 100% rename from idasdk75/dbg/linux/linux_debmod.script rename to idasdk76/dbg/linux/linux_debmod.script diff --git a/idasdk75/dbg/linux/linux_local_impl.cpp b/idasdk76/dbg/linux/linux_local_impl.cpp similarity index 100% rename from idasdk75/dbg/linux/linux_local_impl.cpp rename to idasdk76/dbg/linux/linux_local_impl.cpp diff --git a/idasdk75/dbg/linux/linux_stub.cpp b/idasdk76/dbg/linux/linux_stub.cpp similarity index 100% rename from idasdk75/dbg/linux/linux_stub.cpp rename to idasdk76/dbg/linux/linux_stub.cpp diff --git a/idasdk76/dbg/linux/linux_threads.cpp b/idasdk76/dbg/linux/linux_threads.cpp new file mode 100644 index 0000000..169e759 --- /dev/null +++ b/idasdk76/dbg/linux/linux_threads.cpp @@ -0,0 +1,1355 @@ +/* +* Thread support for IDA debugger under Linux. +* +* There are two approaches to handle threads: +* 1. PTRACE_O_TRACECLONE (since Linux 2.5.46) +* 2. libthread_db.so (the oldest one) +* +* At first we are testing the PTRACE_O_TRACECLONE ability. +* In case of success the approach 1. will be used. +* Otherwise we will try the approach 2. +* +* User is able to set IDA_USE_LIBTHREAD_DB environment variable to skip +* the 1. approach. +* +*/ + +// debugging multi-threaded program +enum mt_state_t +{ + MT_NONE, // disabled + MT_CLONE, // PTRACE_O_TRACECLONE + MT_LIB, // libthread_db.so +}; +static uint32 mt_state = MT_NONE; + +//------------------------------------------------------------------- +//#define TDEB // debug threads +#ifdef TDEB +#define ddeb(x) _ddeb x +AS_PRINTF(1, 2) inline void _ddeb(const char *format, ...) +{ + va_list va; + va_start(va, format); + vmsg(format, va); + va_end(va); +} +#else +#define ddeb(x) (void)0 +#endif + +//========================================================================== +// thread_db +//========================================================================== + +//------------------------------------------------------------------- +//#define MANUALLY_LOAD_THREAD_DB +#ifdef MANUALLY_LOAD_THREAD_DB +// On some systems libthread_db cannot be linked statically because only .so files exists. +// Also, linking it statically is probably a bad idea because it is closely +// tied to the thread implementation. +// Therefore we manually load libthread_db.so. + +// Prototypes of functions we use from libthread_db.so: +typedef td_err_e td_init_t(void); +typedef td_err_e td_ta_delete_t(td_thragent_t *__ta); +typedef td_err_e td_ta_event_addr_t(const td_thragent_t *__ta, td_event_e __event, td_notify_t *__ptr); +typedef td_err_e td_ta_event_getmsg_t(const td_thragent_t *__ta, td_event_msg_t *__msg); +typedef td_err_e td_ta_map_lwp2thr_t(const td_thragent_t *__ta, lwpid_t __lwpid, td_thrhandle_t *__th); +typedef td_err_e td_ta_new_t(struct ps_prochandle *__ps, td_thragent_t **__ta); +typedef td_err_e td_ta_set_event_t(const td_thragent_t *__ta, td_thr_events_t *__event); +typedef td_err_e td_ta_thr_iter_t(const td_thragent_t *__ta, td_thr_iter_f *__callback, void *__cbdata_p, td_thr_state_e __state, int __ti_pri, sigset_t *__ti_sigmask_p, unsigned int __ti_user_flags); +typedef td_err_e td_thr_event_enable_t(const td_thrhandle_t *__th, int __event); +typedef td_err_e td_thr_get_info_t(const td_thrhandle_t *__th, td_thrinfo_t *__infop); +typedef td_err_e td_thr_setsigpending_t(const td_thrhandle_t *__th, unsigned char __n, const sigset_t *__ss); +typedef td_err_e td_thr_set_event_t(const td_thrhandle_t *__th, td_thr_events_t *__event); + +// Pointers to imported functions: +static td_init_t *p_td_init = NULL; +static td_ta_delete_t *p_td_ta_delete = NULL; +static td_ta_event_addr_t *p_td_ta_event_addr = NULL; +static td_ta_event_getmsg_t *p_td_ta_event_getmsg = NULL; +static td_ta_map_lwp2thr_t *p_td_ta_map_lwp2thr = NULL; +static td_ta_new_t *p_td_ta_new = NULL; +static td_ta_set_event_t *p_td_ta_set_event = NULL; +static td_ta_thr_iter_t *p_td_ta_thr_iter = NULL; +static td_thr_event_enable_t *p_td_thr_event_enable = NULL; +static td_thr_get_info_t *p_td_thr_get_info = NULL; +static td_thr_setsigpending_t *p_td_thr_setsigpending = NULL; +static td_thr_set_event_t *p_td_thr_set_event = NULL; + +struct symbol_resolve_info_t +{ + const char *name; + void **ptr; +}; +static symbol_resolve_info_t tdsyms[] = +{ + { "td_init", (void**)&p_td_init }, + { "td_ta_delete", (void**)&p_td_ta_delete }, + { "td_ta_event_addr", (void**)&p_td_ta_event_addr }, + { "td_ta_event_getmsg", (void**)&p_td_ta_event_getmsg }, + { "td_ta_map_lwp2thr", (void**)&p_td_ta_map_lwp2thr }, + { "td_ta_new", (void**)&p_td_ta_new }, + { "td_ta_set_event", (void**)&p_td_ta_set_event }, + { "td_ta_thr_iter", (void**)&p_td_ta_thr_iter }, + { "td_thr_event_enable", (void**)&p_td_thr_event_enable }, + { "td_thr_get_info", (void**)&p_td_thr_get_info }, + { "td_thr_setsigpending", (void**)&p_td_thr_setsigpending }, + { "td_thr_set_event", (void**)&p_td_thr_set_event }, +}; + +// These definitions make our source code the same: +#define td_init p_td_init +#define td_ta_delete p_td_ta_delete +#define td_ta_event_addr p_td_ta_event_addr +#define td_ta_event_getmsg p_td_ta_event_getmsg +#define td_ta_map_lwp2thr p_td_ta_map_lwp2thr +#define td_ta_new p_td_ta_new +#define td_ta_set_event p_td_ta_set_event +#define td_ta_thr_iter p_td_ta_thr_iter +#define td_thr_event_enable p_td_thr_event_enable +#define td_thr_get_info p_td_thr_get_info +#define td_thr_setsigpending p_td_thr_setsigpending +#define td_thr_set_event p_td_thr_set_event + +//-------------------------------------------------------------------------- +static bool load_libthread_db_so(void) +{ + if ( p_td_init == NULL ) + { + const char *file = "libthread_db.so"; + void *lib = dlopen(file, RTLD_NOW); + if ( lib == NULL ) + { + msg("dlopen(%s): %s\n", file, dlerror()); + return false; + } + for ( int i=0; i < qnumber(tdsyms); i++ ) + { + *tdsyms[i].ptr = dlsym(lib, tdsyms[i].name); + const char *err = dlerror(); + if ( err != NULL ) + { + msg("dlsym(%s.%s): %s\n", file, tdsyms[i].name, err); + dlclose(lib); + return false; + } + } + } + return true; +} +#else // Automatic loading of libthread_db.so +inline bool load_libthread_db_so(void) { return true; } +#endif // MANUALLY_LOAD_THREAD_DB + +typedef std::map<qstring, ea_t> psnames_t; +static psnames_t psname_cache; + +static bool tdb_inited = false; + +//-------------------------------------------------------------------------- +#define COMPLAIN_IF_FAILED(func, err) \ + do \ + { \ + if ( err != TD_OK ) \ + msg("%s: %s\n", func, tdb_strerr(err)); \ + } \ + while ( 0 ) + +#define DIE_IF_FAILED(func, err) \ + do \ + { \ + if ( err != TD_OK ) \ + error("%s: %s\n", func, tdb_strerr(err));\ + } \ + while ( 0 ) + +static const char *tdb_strerr(td_err_e err) +{ + static char buf[64]; + switch ( err ) + { + case TD_OK: return "ok"; + case TD_ERR: return "generic error"; + case TD_NOTHR: return "no thread to satisfy query"; + case TD_NOSV: return "no sync handle to satisfy query"; + case TD_NOLWP: return "no LWP to satisfy query"; + case TD_BADPH: return "invalid process handle"; + case TD_BADTH: return "invalid thread handle"; + case TD_BADSH: return "invalid synchronization handle"; + case TD_BADTA: return "invalid thread agent"; + case TD_BADKEY: return "invalid key"; + case TD_NOMSG: return "no event message for getmsg"; + case TD_NOFPREGS: return "FPU register set not available"; + case TD_NOLIBTHREAD: return "application not linked with libpthread"; + case TD_NOEVENT: return "requested event is not supported"; + case TD_NOCAPAB: return "capability not available"; + case TD_DBERR: return "debugger service failed"; + case TD_NOAPLIC: return "operation not applicable to"; + case TD_NOTSD: return "no thread-specific data for this thread"; + case TD_MALLOC: return "malloc failed"; + case TD_PARTIALREG: return "only part of register set was written/read"; + case TD_NOXREGS: return "X register set not available for this thread"; +#ifdef TD_TLSDEFER + case TD_TLSDEFER: return "thread has not yet allocated TLS for given module"; +#endif +#ifdef TD_VERSION + case TD_VERSION: return "versions of libpthread and libthread_db do not match"; +#endif +#ifdef TD_NOTLS + case TD_NOTLS: return "there is no TLS segment in the given module"; +#endif + default: + qsnprintf(buf, sizeof(buf), "tdb error %d", err); + return buf; + } +} + +//-------------------------------------------------------------------------- +// Debug print functions +//{{{ +#ifdef TDEB +static const char *tdb_event_name(int ev) +{ + static const char *const names[] = + { + "READY", // 1 + "SLEEP", // 2 + "SWITCHTO", // 3 + "SWITCHFROM", // 4 + "LOCK_TRY", // 5 + "CATCHSIG", // 6 + "IDLE", // 7 + "CREATE", // 8 + "DEATH", // 9 + "PREEMPT", // 10 + "PRI_INHERIT", // 11 + "REAP", // 12 + "CONCURRENCY", // 13 + "TIMEOUT", // 14 + }; + if ( ev > 0 && ev <= qnumber(names) ) + return names[ev-1]; + + static char buf[16]; + qsnprintf(buf, sizeof(buf), "%u", ev); + return buf; +} + +//-------------------------------------------------------------------------- +static char *get_thr_events_str(const td_thr_events_t &set) +{ + static char buf[MAXSTR]; + char *ptr = buf; + char *end = buf + sizeof(buf); + for ( int i=TD_MIN_EVENT_NUM; i <= TD_MAX_EVENT_NUM; i++ ) + { + if ( td_eventismember(&set, i) ) + { + if ( ptr != buf ) + APPCHAR(ptr, end, ' '); + APPEND(ptr, end, tdb_event_name(i)); + } + } + return buf; +} + +//-------------------------------------------------------------------------- +static const char *get_sigset_str(const sigset_t &set) +{ + static char buf[MAXSTR]; + char *ptr = buf; + char *end = buf + sizeof(buf); + for ( int i=0; i <= 32; i++ ) + { + if ( sigismember(CONST_CAST(sigset_t*)(&set), i) ) + { + if ( ptr != buf ) + APPCHAR(ptr, end, ' '); + ptr += qsnprintf(ptr, end-ptr, "%d", i); + } + } + return buf; +} + +//-------------------------------------------------------------------------- +static const char *get_thread_state_name(td_thr_state_e state) +{ + static const char *const names[] = + { + "ANY_STATE", // 0 + "UNKNOWN", // 1 + "STOPPED", // 2 + "RUN", // 3 + "ACTIVE", // 4 + "ZOMBIE", // 5 + "SLEEP", // 6 + "STOPPED_ASLEEP" // 7 + }; + if ( state >= 0 && state < qnumber(names) ) + return names[state]; + + static char buf[16]; + qsnprintf(buf, sizeof(buf), "%u", state); + return buf; +} + +//-------------------------------------------------------------------------- +static const char *get_thread_type_name(td_thr_type_e type) +{ + static const char *const names[] = + { + "ANY_STATE", // 0 + "USER", // 1 + "SYSTEM", // 2 + }; + if ( type >= 0 && type < qnumber(names) ) + return names[type]; + + static char buf[16]; + qsnprintf(buf, sizeof(buf), "%u", type); + return buf; +} + +//-------------------------------------------------------------------------- +static void display_thrinfo(const td_thrinfo_t &thi) +{ +#ifdef __ANDROID__ + msg(" tid : %lx\n", thi.ti_tid); + msg(" kernel pid : %d\n", thi.ti_lid); // lwpid_t + msg(" state : %s\n", get_thread_state_name(thi.ti_state)); +#else + size_t sigmask = *(size_t*)&thi.ti_sigmask; + msg(" tid : %lx\n", thi.ti_tid); + msg(" tls : %lx\n", (size_t)thi.ti_tls); + msg(" entry : %lx\n", (size_t)thi.ti_startfunc); + msg(" stackbase : %lx\n", (size_t)thi.ti_stkbase); + msg(" stacksize : %lx\n", thi.ti_stksize); + msg(" state : %s\n", get_thread_state_name(thi.ti_state)); + msg(" suspended : %d\n", thi.ti_db_suspended); + msg(" type : %s\n", get_thread_type_name(thi.ti_type)); + msg(" priority : %d\n", thi.ti_pri); + msg(" kernel pid : %d\n", thi.ti_lid); // lwpid_t + msg(" signal mask : %lx\n", sigmask); + msg(" traceme : %d\n", thi.ti_traceme); + msg(" pending sg : %s\n", get_sigset_str(thi.ti_pending)); + msg(" enabled ev : %s\n", get_thr_events_str(thi.ti_events)); +#endif +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::display_thrinfo(thid_t tid) +{ + msg("tid=%d\n", tid); + td_thrhandle_t th; + td_err_e err = td_ta_map_lwp2thr(ta, tid, &th); + COMPLAIN_IF_FAILED("td_ta_map_lwp2thr2", err); + + if ( err == 0 ) + { + td_thrinfo_t thi; + memset(&thi, 0, sizeof(thi)); + err = td_thr_get_info(&th, &thi); + COMPLAIN_IF_FAILED("td_thr_get_info2", err); + + if ( err == 0 ) + ::display_thrinfo(thi); + } +} + +//-------------------------------------------------------------------------- +static int display_thread_cb(const td_thrhandle_t *th_p, void * /*data*/) +{ + td_thrinfo_t ti; + td_err_e err = td_thr_get_info(th_p, &ti); + DIE_IF_FAILED("td_thr_get_info", err); + + if ( ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE ) + return 0; + + display_thrinfo(ti); + return 0; +} + +void linux_debmod_t::display_all_threads() +{ + if ( ta != NULL ) + { + td_err_e err = td_ta_thr_iter(ta, display_thread_cb, NULL, + TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); + COMPLAIN_IF_FAILED("td_ta_thr_iter", err); + } +} + +#endif // end of debug print functions +//}}} + +//-------------------------------------------------------------------------- +// Helper functions for thread_db +// (it requires ps_... functions to be defined in the debugger) +//-------------------------------------------------------------------------- +static linux_debmod_t *find_debugger(ps_prochandle *hproc) +{ +#ifdef __ANDROID__ // android passes NULL as hproc, do not use it + qnotused(hproc); + linux_debmod_t *d = (linux_debmod_t *)g_global_server->get_debugger_instance(); + return d; +#else + struct ida_local find_debugger_t : public debmod_visitor_t + { + int pid; + linux_debmod_t *found; + find_debugger_t(int p) : pid(p), found(NULL) {} + virtual int visit(debmod_t *debmod) override + { + linux_debmod_t *ld = (linux_debmod_t *)debmod; + if ( ld->process_handle == pid ) + { + found = ld; + return 1; // stop + } + return 0; // continue + } + }; + find_debugger_t fd(hproc->pid); + for_all_debuggers(fd); +// msg("prochandle: %x, looking for the debugger, found: %x\n", hproc, fd.found); + return fd.found; +#endif +} + +//-------------------------------------------------------------------------- +inline ea_t get_symbol_as_envvar(const char *name) +{ + qstring buf; + return qgetenv(name, &buf) ? strtoull(buf.begin(), NULL, 16) : BADADDR; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_pglobal_lookup( + ps_prochandle *hproc, + const char *obj, + const char *name, + psaddr_t *sym_addr) +{ + ea_t ea; + // cache names for repeated requests. android, for example, requests the + // same name again and again. without the cache, the name would be gone + // from the pending name list and become unresolvable. + psnames_t::iterator p = psname_cache.find(name); + if ( p != psname_cache.end() ) + { + ea = p->second; + } + else + { + linux_debmod_t *ld = find_debugger(hproc); + if ( ld == NULL ) + return PS_BADPID; + + ld->enum_names(obj); // update the name list + + ea = ld->find_pending_name(name); + if ( ea == BADADDR ) + { + if ( ld->nptl_base != BADADDR ) + ea = get_symbol_as_envvar(name); + if ( ea == BADADDR ) + { + if ( ld->nptl_base != BADADDR ) + msg("*WARNING* Failed to resolve name '%s' in libpthread shared object.\n" + " Support for multithread applications will be turned off.\n" + " We recommend you to analyze libpthread and provide the\n" + " missing symbol info as an environment variable:\n" + "\n" + " export %s=####\n" + "\n" + " where #### is the hexadecimal address of the symbol.\n" + " The full list of symbols is in syms_as_envvars.py\n", + name, name); + return PS_NOSYM; + } + ea += ld->nptl_base; + } +#ifdef TDEB + if ( streq(name, "nptl_version") ) + { + char buf[8 + 1]; + buf[0] = '\0'; + ld->_read_memory(-1, ea, buf, 8, false); + buf[8] = '\0'; + msg("nptl_version='%s'\n", buf); + } +#endif + psname_cache[name] = ea; + } + *sym_addr = psaddr_t(size_t(ea)); + ddeb(("ps_pglobal_lookup('%s') => %a\n", name, ea)); + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman pid_t ps_getpid(ps_prochandle *hproc) +{ + return hproc->pid; +} + +#ifdef __ANDROID__ +# ifndef __X86__ +//-------------------------------------------------------------------------- +idaman ps_err_e ps_get_thread_area(const struct ps_prochandle *, lwpid_t lwpid, int idx, void **base) +{ + struct iovec iovec; + uint64_t reg; + + iovec.iov_base = ® + iovec.iov_len = sizeof (reg); + + if ( ptrace(PTRACE_GETREGSET, lwpid, NT_ARM_TLS, &iovec) != 0 ) + return PS_ERR; + + /* IDX is the bias from the thread pointer to the beginning of the + thread descriptor. It has to be subtracted due to implementation + quirks in libthread_db. */ + *base = (void *) (reg - idx); + + return PS_OK; +} +# endif + +#else // !__ANDROID__ +//-------------------------------------------------------------------------- +idaman ps_err_e ps_pdread( + ps_prochandle *hproc, + psaddr_t addr, + void *buf, + size_t size) +{ + ddeb(("ps_pdread(%" FMT_Z ", %ld)\n", size_t(addr), size)); + linux_debmod_t *ld = find_debugger(hproc); + if ( ld == NULL ) + { + ddeb(("\t=> bad pid\n")); + return PS_BADPID; + } + if ( ld->thread_handle == INVALID_HANDLE_VALUE + || ld->_read_memory(ld->thread_handle, size_t(addr), buf, size, false) <= 0 ) + { + ddeb(("\t=> read error (1)\n")); + if ( ld->_read_memory(hproc->pid, size_t(addr), buf, size, false) <= 0 ) + { + ddeb(("\t=> read error (2)\n")); + return PS_ERR; + } + } + ddeb(("\t=> read OK\n")); + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_pdwrite( + ps_prochandle *hproc, + psaddr_t addr, + void *buf, + size_t size) +{ + linux_debmod_t *ld = find_debugger(hproc); + if ( ld == NULL ) + return PS_BADPID; + if ( ld->_write_memory(hproc->pid, size_t(addr), buf, size, false) <= 0 ) + return PS_ERR; + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_lgetregs(ps_prochandle *, lwpid_t lwpid, prgregset_t gregset) +{ + if ( qptrace(PTRACE_GETREGS, lwpid, 0, gregset) != 0 ) + return PS_ERR; + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_lsetregs(ps_prochandle *, lwpid_t lwpid, const prgregset_t gregset) +{ + if ( qptrace(PTRACE_SETREGS, lwpid, 0, (void*)gregset) != 0 ) + return PS_ERR; + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_lgetfpregs(ps_prochandle *, lwpid_t lwpid, prfpregset_t *fpregset) +{ + if ( qptrace(PTRACE_GETFPREGS, lwpid, 0, fpregset) != 0 ) + return PS_ERR; + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_lsetfpregs(ps_prochandle *, lwpid_t lwpid, const prfpregset_t *fpregset) +{ + if ( qptrace(PTRACE_SETFPREGS, lwpid, 0, (void*)fpregset) != 0 ) + return PS_ERR; + return PS_OK; +} + +//-------------------------------------------------------------------------- +idaman ps_err_e ps_get_thread_area(const struct ps_prochandle *, lwpid_t lwpid, int idx, void **base) +{ + #ifndef PTRACE_GET_THREAD_AREA + #ifdef __ARM__ + #define PTRACE_GET_THREAD_AREA __ptrace_request(22) + #else + #define PTRACE_GET_THREAD_AREA __ptrace_request(25) + #endif + #endif + unsigned int desc[4]; + if ( qptrace(PTRACE_GET_THREAD_AREA, lwpid, (void *)size_t(idx), &desc) < 0 ) + { +#ifndef __X86__ + // from <sys/reg.h> + #define LINUX_FS 25 + #define LINUX_GS 26 + + /* The following definitions come from prctl.h, but may be absent + for certain configurations. */ + #ifndef ARCH_GET_FS + #define ARCH_SET_GS 0x1001 + #define ARCH_SET_FS 0x1002 + #define ARCH_GET_FS 0x1003 + #define ARCH_GET_GS 0x1004 + #endif + + switch ( idx ) + { + case LINUX_FS: + if ( ptrace(PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_FS) != 0 ) + return PS_ERR; + break; + case LINUX_GS: + if ( ptrace(PTRACE_ARCH_PRCTL, lwpid, base, ARCH_GET_GS) != 0 ) + return PS_ERR; + break; + default: + return PS_BADADDR; + } +#endif + return PS_ERR; + } + + *(int *)base = desc[1]; + + return PS_OK; +} +#endif + +//-------------------------------------------------------------------------- +// High level interface for the rest of the debugger module +//-------------------------------------------------------------------------- +void tdb_init(void) +{ + if ( !tdb_inited ) + { + if ( !load_libthread_db_so() ) + { + msg("DBG: thread support is not available\n"); + } + else + { + td_err_e code = td_init(); + if ( code == TD_OK ) + tdb_inited = true; + else + msg("DBG: td_init error code %d\n", code); + } + } +} + +//-------------------------------------------------------------------------- +void tdb_term(void) +{ + // no way to uninitialize thread_db +} + +//-------------------------------------------------------------------------- +typedef qvector<td_thrinfo_t> td_thrinfovec_t; + +//-------------------------------------------------------------------------- +// check if there are pending messages from thread DB +void linux_debmod_t::tdb_handle_messages(int /*tid*/) +{ + if ( ta == NULL ) + return; + + td_event_msg_t tmsg; + td_thrinfo_t ti; + td_err_e err; +#ifndef __ANDROID__ + while ( true ) +#endif + { + err = td_ta_event_getmsg(ta, &tmsg); + if ( err != TD_OK ) + { + if ( err == TD_NOMSG ) + return; + msg("Cannot get thread event message: %s\n", tdb_strerr(err)); + return; + } + + err = td_thr_get_info(tmsg.th_p, &ti); + COMPLAIN_IF_FAILED("td_thr_get_info", err); + switch ( tmsg.event ) + { + case TD_CREATE: + if ( !thread_is_known(ti) ) + { + if ( listen_thread_events(ti, tmsg.th_p) ) + attach_to_thread(ti); + } + break; + + case TD_DEATH: + dead_thread(ti.ti_lid, DYING); + break; + + default: + msg("Spurious thread event %d.", tmsg.event); + } + } +} + +//---------------------------------------------------------------------------- +struct cbdata_t +{ + linux_debmod_t *debmod; + td_thrinfovec_t *threads_list; +}; + +//---------------------------------------------------------------------------- +static int update_threads_cb(const td_thrhandle_t *th_p, void *data) +{ + cbdata_t *cbdata = (cbdata_t *) data; + + td_thrinfo_t ti; + td_err_e err = td_thr_get_info(th_p, &ti); + DIE_IF_FAILED("td_thr_get_info", err); + + if ( ti.ti_state != TD_THR_UNKNOWN && ti.ti_state != TD_THR_ZOMBIE ) + { + if ( !cbdata->debmod->thread_is_known(ti) ) + { + cbdata->debmod->listen_thread_events(ti, th_p); + cbdata->threads_list->push_back(ti); + } + } + return 0; +} + +//---------------------------------------------------------------------------- +bool linux_debmod_t::thread_is_known(const td_thrinfo_t &info) const +{ + return threads.find(info.ti_lid) != threads.end(); +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::listen_thread_events(const td_thrinfo_t &info, const td_thrhandle_t *th_p) +{ +#ifdef TDEB + msg("thread %d is new\n", info.ti_lid); + ::display_thrinfo(info); +#else + qnotused(info); +#endif + td_err_e err; + td_thr_events_t thr_events; + td_event_emptyset(&thr_events); + td_event_addset(&thr_events, TD_CREATE); + td_event_addset(&thr_events, TD_DEATH); +#ifndef __ANDROID__ + td_event_addset(&thr_events, TD_CATCHSIG); +#endif + err = td_thr_set_event(th_p, &thr_events); + DIE_IF_FAILED("td_thr_set_event", err); + + err = td_thr_event_enable(th_p, 1); + COMPLAIN_IF_FAILED("td_thr_event_enable", err); + if ( err != TD_OK ) + { + ddeb(("%d: thread dead already? not adding to list.\n", info.ti_lid)); + return false; + } + + return true; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::attach_to_thread(const td_thrinfo_t &info) +{ +#ifndef __ANDROID__ + ea_t ea = (ea_t) (size_t) info.ti_startfunc; +#else + ea_t ea = BADADDR; +#endif + + attach_to_thread(info.ti_lid, ea); +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::tdb_update_threads(void) +{ + if ( ta != NULL ) + { + td_thrinfovec_t newlist; + cbdata_t cb_payload = { this, &newlist }; + + td_err_e err = td_ta_thr_iter(ta, update_threads_cb, &cb_payload, + TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, + TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); + COMPLAIN_IF_FAILED("td_ta_thr_iter", err); + if ( err != TD_OK ) + return; + + // generate THREAD_STARTED events + for ( int i=0; i < newlist.size(); i++ ) + { + const td_thrinfo_t &info = newlist[i]; + // Main thread is already suspended; others not. + if ( i != 0 ) + dbg_freeze_threads(info.ti_lid, false); + attach_to_thread(newlist[i]); + } + } +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::tdb_enable_event(td_event_e event, internal_bpt *bp) +{ + td_notify_t notify; + td_err_e err = td_ta_event_addr(ta, event, ¬ify); + COMPLAIN_IF_FAILED("td_ta_event_addr", err); + if ( err != TD_OK ) + return false; + bool ok = add_internal_bp(*bp, size_t(notify.u.bptaddr)); + if ( !ok ) + { + // Having the following cast inline in the 'dmsg' call causes + // the __X86__=1 build on linux to report: + // linux_threads.cpp:851:86: warning: format '%a' expects argument of + // type 'double', but argument 3 has type 'size_t {aka unsigned int}' + // ...which AFAICT is a bug in gcc. + // Putting it on a separate line works fine, though. + ea_t bptaddr = ea_t(size_t(notify.u.bptaddr)); + dmsg("%a: failed to add thread_db breakpoint\n", bptaddr); + return false; + } + debdeb("%a: added BP for thread event %s\n", bp->bpt_addr, event == TD_CREATE ? "TD_CREATE" : "TD_DEATH"); + return true; +} + +//-------------------------------------------------------------------------- +// returns true: multithreaded application has been detected +bool linux_debmod_t::tdb_new(void) +{ + if ( ta == NULL ) + { + if ( !tdb_inited ) + return false; // no libthread_db + +#ifdef __ANDROID__ + // wait until libc gets loaded. on android v4.2.2 there are 2 sets of pthread_...() + // functions: in /system/bin/linker and in /system/lib/libc.so. The ones + // from /system/bin/linker get resolved first but we have to use the ones + // from /system/lib/libc.so + bool libc_loaded = false; + qstring custom_libc_path; + qgetenv("IDA_LIBC_PATH", &custom_libc_path); + for ( images_t::const_iterator p=dlls.begin(); p != dlls.end(); ++p ) + { + const qstring &path = p->second.fname; + if ( path == "/system/lib/libc.so" + || path == "/system/lib64/libc.so" + || !custom_libc_path.empty() && path == custom_libc_path ) + { + libc_loaded = true; + break; + } + } + if ( !libc_loaded ) + { + debdeb("DBG: /system/lib/libc.so is not loaded yet, use IDA_LIBC_PATH if necessary\n"); + return false; + } +#endif + + debdeb("DBG: checking pid %d with thread_db\n", process_handle); + prochandle.pid = process_handle; + td_err_e err = td_ta_new(&prochandle, &ta); + // the call might fail the first time if libc is not loaded yet + // so don't show misleading message to the user +#ifdef TDEB + COMPLAIN_IF_FAILED("td_ta_new", err); +#endif + if ( err != TD_OK ) + { + debdeb("DBG: td_ta_new: %s\n", tdb_strerr(err)); + ta = NULL; + return false; + } + + td_thrhandle_t th; + err = td_ta_map_lwp2thr(ta, process_handle, &th); + COMPLAIN_IF_FAILED("td_ta_map_lwp2thr", err); + if ( err != TD_OK ) + return false; + + err = td_thr_event_enable(&th, TD_CREATE); + DIE_IF_FAILED("td_thr_event_enable(TD_CREATE)", err); +#ifndef __ANDROID__ + err = td_thr_event_enable(&th, TD_DEATH); + DIE_IF_FAILED("td_thr_event_enable(TD_DEATH)", err); +#endif + + // set breakpoints for thread birth/death + td_thr_events_t thr_events; + td_event_emptyset(&thr_events); + td_event_addset(&thr_events, TD_CREATE); + td_event_addset(&thr_events, TD_DEATH); + err = td_ta_set_event(ta, &thr_events); + DIE_IF_FAILED("td_ta_set_event", err); + + tdb_enable_event(TD_CREATE, &birth_bpt); +#ifndef __ANDROID__ + tdb_enable_event(TD_DEATH, &death_bpt); +#endif + debdeb("DBG: thread support has been enabled, birth_bpt=%a death_bpt=%a\n", birth_bpt.bpt_addr, death_bpt.bpt_addr); + + tdb_update_threads(); + } + return true; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::tdb_delete(void) +{ + if ( ta != NULL ) + { + td_ta_delete(ta); + ta = NULL; + psname_cache.clear(); + } +} + +//========================================================================== +// PTRACE_O_TRACECLONE +//========================================================================== + +//-------------------------------------------------------------------------- +// This variable is a tri-state flag: +// -1 for unknown, +// 0 if PTRACE_O_TRACEFORK cannot be used, +// 1 if it can. +static int linux_supports_tracefork_flag = -1; + +//-------------------------------------------------------------------------- +static int linux_tracefork_grandchild(void *) +{ + _exit(0); +} + +static int linux_tracefork_child(void) +{ + errno = 0; + if ( qptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0 ) + { + msg("PTRACE_O_TRACEFORK test: Cannot trace created process: %s\n", winerr(errno)); + _exit(127); + } + kill(getpid(), SIGSTOP); + + if ( fork() == 0 ) + linux_tracefork_grandchild(NULL); + + _exit(0); +} + +// Determine if PTRACE_O_TRACEFORK can be used to follow fork events. Make +// sure that we can enable the option, and that it had the desired effect. +static void linux_test_for_tracefork(void) +{ + linux_supports_tracefork_flag = 0; + + int child_pid = fork(); + if ( child_pid == 0 ) + linux_tracefork_child(); + + if ( child_pid == -1 ) + { + msg("clone: %s\n", winerr(errno)); + return; + } + + int status; + int ret = qwait(&status, child_pid, 0); + if ( ret == -1 ) + { + msg("waitpid: %s\n", winerr(errno)); + return; + } + else if ( ret != child_pid ) + { + msg("linux_test_for_tracefork: waitpid: unexpected result %d\n", ret); + return; + } + if ( !WIFSTOPPED(status) ) + { + msg("linux_test_for_tracefork: waitpid: unexpected status %d\b", status); + return; + } + + ret = qptrace(PTRACE_SETOPTIONS, child_pid, NULL, (void *)PTRACE_O_TRACEFORK); + if ( ret != 0 ) + { + ret = qptrace(PTRACE_KILL, child_pid, NULL, NULL); + if ( ret != 0 ) + { + msg("linux_test_for_tracefork: failed to kill child"); + return; + } + + ret = qwait(&status, child_pid, 0); + if ( ret != child_pid ) + msg("linux_test_for_tracefork: failed to wait for killed child"); + else if ( !WIFSIGNALED(status) ) + msg("linux_test_for_tracefork: unexpected wait status 0x%x from " + "killed child", status); + return; + } + + ret = qptrace(PTRACE_CONT, child_pid, NULL, NULL); + if ( ret != 0 ) + msg("linux_test_for_tracefork: failed to resume child"); + + ret = qwait(&status, child_pid, 0); + if ( ret == child_pid + && WIFSTOPPED(status) + && status >> 16 == PTRACE_EVENT_FORK ) + { + long second_pid = 0; + ret = qptrace(PTRACE_GETEVENTMSG, child_pid, NULL, &second_pid); + if ( ret == 0 && second_pid != 0 ) + { + int second_status; + + linux_supports_tracefork_flag = 1; + qwait(&second_status, second_pid, 0); + ret = qptrace(PTRACE_KILL, second_pid, NULL, NULL); + if ( ret != 0 ) + msg("linux_test_for_tracefork: failed to kill second child"); + qwait(&status, second_pid, 0); + } + } + else + { + msg("linux_test_for_tracefork: unexpected result from waitpid " + "(%d, status 0x%x)", ret, status); + } + + do + { + ret = qptrace(PTRACE_KILL, child_pid, NULL, NULL); + if ( ret != 0 ) + msg("linux_test_for_tracefork: failed to kill child"); + qwait(&status, child_pid, 0); + } + while ( WIFSTOPPED(status) ); +} + +//-------------------------------------------------------------------------- +// Return non-zero iff we have tracefork functionality available. +// This function also sets linux_supports_tracefork_flag. +static int linux_supports_tracefork(void) +{ + if ( linux_supports_tracefork_flag == -1 ) + linux_test_for_tracefork(); + return linux_supports_tracefork_flag; +} + +//-------------------------------------------------------------------------- +static void linux_enable_event_reporting(int pid) +{ + if ( linux_supports_tracefork() == 0 ) + return; + + qptrace(PTRACE_SETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACECLONE); +} + +//-------------------------------------------------------------------------- +// ported from GDB sources: linux_proc_attach_tgid_threads() +void linux_debmod_t::procfs_collect_threads(void) +{ + // TODO: if (linux_proc_get_tgid (pid) != pid) return; + + qstring pathname; + pathname.sprnt("/proc/%d/task", process_handle); + DIR *dir = opendir(pathname.c_str()); + if ( dir == NULL ) + { + msg("Could not open /proc/%d/task", process_handle); + return; + } + + /* Scan the task list for existing threads. While we go through the + threads, new threads may be spawned. Cycle through the list of + threads until we have done two iterations without finding new + threads. */ + for ( int iterations=0; iterations < 2; ++iterations ) + { + bool new_threads_found = false; + + struct dirent *dp; + while ( (dp = readdir(dir)) != NULL ) + { + /* Fetch one lwp. */ + unsigned long lwp = strtoul(dp->d_name, NULL, 10); + if ( lwp != 0 ) + { + debdeb("DBG: %d found %s thread\n", iterations, dp->d_name); + if ( attach_collected_thread(lwp) ) + { + new_threads_found = true; + debdeb("DBG: %d collected %s thread\n", iterations, dp->d_name); + } + } + } + + if ( new_threads_found ) + { /* Start over. */ + iterations = -1; + } + rewinddir(dir); + } + + closedir(dir); +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::attach_collected_thread(unsigned long lwp) +{ + thread_info_t *thif = get_thread(lwp); + if ( thif != NULL ) + return false; + + // Main thread is already suspended; others not. + if ( lwp != process_handle ) + dbg_freeze_threads(lwp, false); + // generate THREAD_STARTED event + return attach_to_thread(lwp, BADADDR); +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::handle_extended_wait(bool *handled, const chk_signal_info_t &csi) +{ + if ( handled != NULL ) + *handled = false; + + // extended event guard + int event = csi.status >> 16; + if ( !WIFSTOPPED(csi.status) + || WSTOPSIG(csi.status) != SIGTRAP + || event == 0 ) + { + return; + } + + if ( event == PTRACE_EVENT_CLONE ) + { + unsigned long new_pid; + qptrace(PTRACE_GETEVENTMSG, csi.pid, NULL, &new_pid); + ddeb(("handle_extended_wait: PTRACE_EVENT_CLONE(signal_pid=%d, new_pid=%ld)\n", csi.pid, new_pid)); + + linux_enable_event_reporting(new_pid); + finish_attaching(new_pid, BADADDR, true); + if ( handled != NULL ) + *handled = true; + } +} + +//========================================================================== +// Common part +//========================================================================== + +//-------------------------------------------------------------------------- +void init_multithreading() +{ + bool skip_clone = qgetenv("IDA_USE_LIBTHREAD_DB", nullptr); + if ( !skip_clone ) + { + if ( linux_supports_tracefork() == 1 ) + { + mt_state = MT_CLONE; + return; + } + } + tdb_init(); + if ( tdb_inited ) + mt_state = MT_LIB; + else + mt_state = MT_NONE; +} + +//-------------------------------------------------------------------------- +void term_multithreading() +{ + if ( mt_state == MT_LIB ) + tdb_term(); +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::activate_multithreading() +{ + if ( mt_state == MT_NONE ) + { + debdeb("DBG: debugging of multi-threaded program is not available\n"); + return false; + } + + bool ok; + if ( mt_state == MT_CLONE ) + { + debdeb("DBG: PTRACE_O_TRACECLONE ability detected, will be used in debugging multi-threaded program\n"); + linux_enable_event_reporting(process_handle); + birth_bpt.bpt_addr = 0; + death_bpt.bpt_addr = 0; + + if ( !threads_collected ) + { + debdeb("DBG: collect threads\n"); + procfs_collect_threads(); + threads_collected = true; + } + ok = true; + } + else + { // MT_LIB + ok = tdb_new(); + debdeb("DBG: tdb_new returns %d\n", ok); + if ( ok && ta != nullptr ) + debdeb("DBG: libthread_db.so will be used in debugging multi-threaded program\n"); + } + + return ok; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::attach_to_thread(int tid, ea_t ea) +{ + // attach to the thread and make it ready for debugging + if ( qptrace(PTRACE_ATTACH, tid, 0, 0) != 0 ) + { + dmsg("Attaching to %d thread: %s\n", tid, winerr(errno)); + if ( errno == EPERM || errno == ESRCH ) + return false; // thread died prematurely + INTERR(30197); + } + + return finish_attaching(tid, ea, false); +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::dead_thread(int tid, thstate_t state) +{ + threads_t::iterator p = threads.find(tid); + if ( p != threads.end() ) + { + ddeb(("thread %d died\n", tid)); + set_thread_state(p->second, state); + debug_event_t ev; + ev.set_exit_code(THREAD_EXITED, 0); // ??? + ev.pid = process_handle; + ev.tid = tid; + ev.ea = BADADDR; + ev.handled = true; + enqueue_event(ev, IN_BACK); + if ( state == DEAD ) + del_thread(tid); + } + else + { + msg("unknown thread %d died\n", tid); + } +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::finish_attaching(int tid, ea_t ea, bool use_ip) +{ + thread_info_t &ti = add_thread(tid); + + // If we haven't already seen the new PID stop, wait for it now + if ( !seen_threads.del(tid) ) + { + // The new child has a pending SIGSTOP. We can't affect it until it + // hits the SIGSTOP, but we're already attached + int status; + int tid2 = check_for_signal(&status, tid, -1); + ddeb(("finish_attaching: tid2=%d status=%s\n", tid2, status_dstr(status))); + if ( tid2 == -1 ) + { + dmsg("Finish attaching to %d thread: %s\n", tid, winerr(errno)); + return false; // looks alike a "zombie" + } + if ( tid2 != tid || !WIFSTOPPED(status) || WSTOPSIG(status) != SIGSTOP ) + { + get_thread(tid)->waiting_sigstop = true; + if ( tid2 > 0 ) + store_pending_signal(tid2, status); + } + } + + debug_event_t ev; + ev.set_info(THREAD_STARTED) = ti.name; + ev.pid = process_handle; + ev.tid = tid; + ev.ea = use_ip ? get_ip(ev.tid) : ea; + ev.handled = true; + enqueue_event(ev, IN_FRONT); + return true; +} + +//-------------------------------------------------------------------------- +bool linux_debmod_t::get_thread_name(qstring *thr_name, thid_t tid) +{ + qstring comm_file; + comm_file.sprnt("/proc/%d/task/%d/comm", process_handle, tid); + FILE *fp = fopenRT(comm_file.c_str()); + if ( fp == NULL ) + { + dmsg("%s: %s\n", comm_file.c_str(), winerr(errno)); + return false; + } + qgetline(thr_name, fp); // return code is ignored, assumed empty thread name + qfclose(fp); + return true; +} + +//-------------------------------------------------------------------------- +void linux_debmod_t::update_thread_names(thread_name_vec_t *thr_names) +{ + // assert: thr_names != NULL + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + qstring new_thr_name; + if ( get_thread_name(&new_thr_name, ti.tid) + && new_thr_name != ti.name ) + { + ddeb(("Thread %d renamed from '%s' to '%s'\n", ti.tid, ti.name.c_str(), new_thr_name.c_str())); + ti.name.swap(new_thr_name); + thread_name_t &tn = thr_names->push_back(); + tn.tid = ti.tid; + tn.name = ti.name; + } + } +} diff --git a/idasdk75/dbg/linux/linux_user.cpp b/idasdk76/dbg/linux/linux_user.cpp similarity index 100% rename from idasdk75/dbg/linux/linux_user.cpp rename to idasdk76/dbg/linux/linux_user.cpp diff --git a/idasdk75/dbg/linux/linux_wait.cpp b/idasdk76/dbg/linux/linux_wait.cpp similarity index 100% rename from idasdk75/dbg/linux/linux_wait.cpp rename to idasdk76/dbg/linux/linux_wait.cpp diff --git a/idasdk76/dbg/linux/linuxbase_debmod.cpp b/idasdk76/dbg/linux/linuxbase_debmod.cpp new file mode 100644 index 0000000..ec4db0e --- /dev/null +++ b/idasdk76/dbg/linux/linuxbase_debmod.cpp @@ -0,0 +1,146 @@ +#include <fpro.h> +#include <prodir.h> +#include <diskio.hpp> +#include "linuxbase_debmod.h" + +//-------------------------------------------------------------------------- +static inline const char *str_bitness(int bitness) +{ + switch ( bitness ) + { + case 8: + return "[64]"; + case 4: + return "[32]"; + default: + return "[x]"; + } +} + +//-------------------------------------------------------------------------- +static void build_process_ext_name(ext_process_info_t *pinfo) +{ + pinfo->ext_name = str_bitness(pinfo->addrsize); + + char buf[QMAXPATH]; + qsnprintf(buf, sizeof(buf), "/proc/%u/cmdline", pinfo->pid); + + FILE *cmdfp = qfopen(buf, "r"); + if ( cmdfp == nullptr ) + return; + + int size = qfread(cmdfp, buf, sizeof(buf)); + buf[size] = '\0'; + qfclose(cmdfp); + +#ifdef __ANDROID__ + while ( size >= 0 && buf[size] == '\0' ) + size--; + size++; +#endif + + // arguments are separated by '\0' + for ( int i=0; i < size; ) + { + const char *in = &buf[i]; + qstring arg = in; + quote_cmdline_arg(&arg); + pinfo->ext_name.append(" "); + pinfo->ext_name.append(arg); + + i += strlen(in) + 1; + } +} + +//-------------------------------------------------------------------------- +// Returns the file name assciated with pid +bool idaapi linuxbase_debmod_t::get_exec_fname( + int _pid, + char *buf, + size_t bufsize) +{ + char path[QMAXPATH]; + qsnprintf(path, sizeof(path), "/proc/%u/exe", _pid); + int len = readlink(path, buf, bufsize-1); + if ( len > 0 ) + { + buf[len] = '\0'; + return true; + } + else + { + // ESXi keeps the real file name inside /proc/PID/exe (which is not a link) + FILE *fp = qfopen(path, "r"); + if ( fp != NULL ) + { + len = qfread(fp, buf, bufsize); + qfclose(fp); + if ( len > 1 && len < bufsize && buf[0] == '/' ) // sanity check + { + buf[len] = '\0'; + return true; + } + } + buf[0] = '\0'; + return false; + } +} + +//-------------------------------------------------------------------------- +// Get process bitness: 32bit - 4, 64bit - 8, 0 - unknown +int idaapi linuxbase_debmod_t::get_process_bitness(int _pid) +{ + char fname[QMAXPATH]; + qsnprintf(fname, sizeof(fname), "/proc/%u/maps", _pid); + FILE *mapfp = fopenRT(fname); + if ( mapfp == NULL ) + return 0; + + int bitness = 4; + qstring line; + while ( qgetline(&line, mapfp) >= 0 ) + { + if ( line.empty() ) + continue; + ea_t ea1; + ea_t ea2; + if ( qsscanf(line.begin(), "%a-%a ", &ea1, &ea2) == 2 ) + { + size_t pos = line.find('-'); + if ( pos != qstring::npos && pos > 8 ) + { + bitness = 8; + break; + } + } + } + qfclose(mapfp); + return bitness; +} + +//-------------------------------------------------------------------------- +int idaapi linuxbase_debmod_t::get_process_list(procvec_t *list, qstring *) +{ + int mypid = getpid(); + list->clear(); + qffblk64_t fb; + for ( int code = qfindfirst("/proc/*", &fb, FA_DIREC); + code == 0; + code = qfindnext(&fb) ) + { + if ( !qisdigit(fb.ff_name[0]) ) + continue; + ext_process_info_t pinfo; + pinfo.pid = atoi(fb.ff_name); + if ( pinfo.pid == mypid ) + continue; + char buf[MAXSTR]; + if ( !get_exec_fname(pinfo.pid, buf, sizeof(buf)) ) + continue; // we skip the process because we cannot debug it anyway + pinfo.name = buf; + pinfo.addrsize = get_process_bitness(pinfo.pid); + build_process_ext_name(&pinfo); + list->push_back(pinfo); + } + return list->size(); +} diff --git a/idasdk75/dbg/linux/linuxbase_debmod.h b/idasdk76/dbg/linux/linuxbase_debmod.h similarity index 100% rename from idasdk75/dbg/linux/linuxbase_debmod.h rename to idasdk76/dbg/linux/linuxbase_debmod.h diff --git a/idasdk76/dbg/linux/makefile b/idasdk76/dbg/linux/makefile new file mode 100644 index 0000000..bba338d --- /dev/null +++ b/idasdk76/dbg/linux/makefile @@ -0,0 +1,164 @@ +include ../../allmake.mak + +GOALS-$(BUILD_IDA) += modules # target in $(IDA)module.mak +GOALS-$(BUILD_DBGSRV) += server # target in $(IDA)dbg/server.mak +.PHONY: $(GOALS-1) +all: $(GOALS-1) + +#---------------------------------------------------------------------- +ifdef __LINUX__ + SERVER = linux_server$(SUFF64) +endif +ifdef SERVER + SERVERS += $(call server_exe,$(SERVER)) +endif + +#---------------------------------------------------------------------- +USER = $(call module_dll,linux_user) +ifeq ($(and $(BUILD_IDA),$(__LINUX__)),1) + MODULES += $(USER) +endif + +#---------------------------------------------------------------------- +# we explicitly added our module targets +NO_DEFAULT_TARGETS = 1 + +# NOTE: all MODULES must be defined before including plugin.mak. +include ../plugin.mak +# NOTE: target-specific rules and dependencies that use variable +# expansion to name the target (such as "$(MODULE): [...]") must +# come after including plugin.mak + +#---------------------------------------------------------------------- +# select OBJS common to user plugin and debugger server +ifeq ($(or $(__LINUX__),$(__ANDROID__),$(__ANDROID_X86__),$(__ARMLINUX__)),1) + BUILD_LINUX:=1 +endif + +BASE_OBJS-$(BUILD_LINUX) += $(F)linuxbase_debmod$(O) +BASE_OBJS-$(BUILD_LINUX) += $(F)linux_debmod$(O) +BASE_OBJS-$(BUILD_LINUX) += $(F)linux_wait$(O) + +BASE_OBJS += $(BASE_OBJS-1) $(F)symelf$(O) + +#---------------------------------------------------------------------- +ifdef __LINUX__ + SERVER_LDFLAGS += -Wl,--version-script=linux_debmod.script + SERVER_LDFLAGS += $(OUTMAP)$(F)$(@F).map + SERVER_STDLIBS += -lthread_db -lrt -lc -lpthread -ldl +endif +SERVER_OBJS += $(BASE_OBJS) + +# suppress warnings for libthread_db.c +$(F)libthread_db$(O): WARNS = $(NOWARNS) + +include ../server.mak + +#---------------------------------------------------------------------- +STUB_OBJS += $(F)linux_stub$(O) +$(STUB): MODULE_OBJS += $(STUB_OBJS) +$(STUB): $(STUB_OBJS) + +#---------------------------------------------------------------------- +USER_OBJS += $(F)linux_user$(O) +USER_OBJS += $(BASE_OBJS) +$(USER): MODULE_OBJS += $(USER_OBJS) +$(USER): $(USER_OBJS) +$(USER): DEFFILE = linux_debmod.script +$(USER): STDLIBS += -ldl +$(USER): STDLIBS += -lthread_db + +ifeq ($(COMPILER_NAME),gcc) + $(USER): LDFLAGS += -Wl,--export-dynamic +endif + +#---------------------------------------------------------------------- +include $(IDA)objdir.mak + +# MAKEDEP dependency list ------------------ +$(F)armlinux_stub$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../arm_local_impl.cpp ../arm_regs.cpp ../arm_regs.hpp \ + ../common_local_impl.cpp ../common_stub_impl.cpp \ + ../dbg_rpc_client.h ../dbg_rpc_engine.h ../deb_arm.hpp \ + ../debmod.h ../rpc_debmod.h armlinux_stub.cpp \ + linux_local_impl.cpp +$(F)libthread_db$(O): libthread_db.c +$(F)linux_debmod$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)diskio.hpp $(I)err.h $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)network.hpp $(I)pro.h \ + $(I)prodir.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ + $(I)xref.hpp ../../plugins/dwarf/look_for_debug_file.cpp \ + ../arm_debmod.h ../arm_regs.hpp ../dbg_rpc_engine.h \ + ../dbg_rpc_handler.h ../dbg_rpc_handler_ioctls.h \ + ../deb_arm.hpp ../deb_pc.hpp ../debmod.h ../pc_debmod.h \ + ../pc_regs.hpp android.cpp android.hpp linux_debmod.cpp \ + linux_debmod.h linux_threads.cpp linuxbase_debmod.h \ + symelf.hpp +$(F)linux_stub$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../common_local_impl.cpp ../common_stub_impl.cpp \ + ../dbg_rpc_client.h ../dbg_rpc_engine.h ../deb_pc.hpp \ + ../debmod.h ../pc_local_impl.cpp ../pc_regs.hpp \ + ../rpc_debmod.h linux_local_impl.cpp linux_stub.cpp +$(F)linux_user$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../arm_debmod.h ../common_local_impl.cpp \ + ../common_stub_impl.cpp ../deb_arm.hpp ../deb_pc.hpp \ + ../debmod.h ../pc_debmod.h ../pc_local_impl.cpp \ + ../pc_regs.hpp linux_debmod.h linux_local_impl.cpp \ + linux_user.cpp linuxbase_debmod.h +$(F)linux_wait$(O): $(I)bytes.hpp $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)ua.hpp \ + $(I)xref.hpp ../arm_debmod.h ../deb_arm.hpp \ + ../deb_pc.hpp ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ + linux_debmod.h linux_wait.cpp linuxbase_debmod.h +$(F)linuxbase_debmod$(O): $(I)bytes.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)prodir.h $(I)range.hpp \ + $(I)ua.hpp $(I)xref.hpp ../arm_debmod.h ../deb_arm.hpp \ + ../deb_pc.hpp ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ + linuxbase_debmod.cpp linuxbase_debmod.h +$(F)symelf$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)network.hpp \ + $(I)offset.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/elf/../idaldr.h ../../ldr/elf/common.cpp \ + ../../ldr/elf/elf.h ../../ldr/elf/elfbase.h \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + ../../ldr/elf/reader.cpp \ + ../debmod.h symelf.cpp symelf.hpp diff --git a/idasdk75/dbg/linux/symelf.cpp b/idasdk76/dbg/linux/symelf.cpp similarity index 100% rename from idasdk75/dbg/linux/symelf.cpp rename to idasdk76/dbg/linux/symelf.cpp diff --git a/idasdk75/dbg/linux/symelf.hpp b/idasdk76/dbg/linux/symelf.hpp similarity index 100% rename from idasdk75/dbg/linux/symelf.hpp rename to idasdk76/dbg/linux/symelf.hpp diff --git a/idasdk75/dbg/makefile b/idasdk76/dbg/makefile similarity index 100% rename from idasdk75/dbg/makefile rename to idasdk76/dbg/makefile diff --git a/idasdk76/dbg/pc_debmod.cpp b/idasdk76/dbg/pc_debmod.cpp new file mode 100644 index 0000000..e684b5b --- /dev/null +++ b/idasdk76/dbg/pc_debmod.cpp @@ -0,0 +1,304 @@ +#ifdef __NT__ +#include <windows.h> +#endif +#include <pro.h> +#include <ua.hpp> +#include "pc_debmod.h" + +//-------------------------------------------------------------------------- +//lint -esym(1566,pc_debmod_t::hwbpt_ea,pc_debmod_t::hwbpt_type) +//lint -esym(1566,pc_debmod_t::dr6,pc_debmod_t::dr7) +pc_debmod_t::pc_debmod_t() +{ + static const uchar bpt[] = X86_BPT_CODE; + bpt_code.append(bpt, sizeof(bpt)); + sp_idx = R_ESP; + pc_idx = R_EIP; + sr_idx = R_EFLAGS; + fs_idx = R_FS; + gs_idx = R_GS; + cs_idx = R_CS; + ds_idx = R_DS; + es_idx = R_ES; + ss_idx = R_SS; + nregs = X86_NREGS; + + cleanup_hwbpts(); + set_platform(get_local_platform()); +} + +//-------------------------------------------------------------------------- +int pc_debmod_t::get_regidx(const char *regname, int *clsmask) +{ + return x86_get_regidx(clsmask, regname); +} + +//-------------------------------------------------------------------------- +int idaapi pc_debmod_t::dbg_is_ok_bpt(bpttype_t type, ea_t ea, int /* len */) +{ + if ( type == BPT_SOFT ) + return BPT_OK; + + return find_hwbpt_slot(ea, type) == -1 ? BPT_TOO_MANY : BPT_OK; +} + +//-------------------------------------------------------------------------- +// returns -1 if something is wrong +int pc_debmod_t::find_hwbpt_slot(ea_t ea, bpttype_t type) const +{ + for ( int i=0; i < MAX_BPT; i++ ) + { + if ( hwbpt_ea[i] == ea && hwbpt_type[i] == type ) // another breakpoint is here + return -1; + if ( hwbpt_ea[i] == BADADDR ) // empty slot found + return i; + } + return -1; +} + +//-------------------------------------------------------------------------- +bool pc_debmod_t::add_hwbpt(bpttype_t type, ea_t ea, int len) +{ + int i = find_hwbpt_slot(ea, type); // get slot number + if ( i != -1 ) + { + hwbpt_ea[i] = ea; + hwbpt_type[i] = type; + if ( type == BPT_EXEC ) + type = 0; // exec bpts are encoded with 0 on x86 + + // length code used by the processor + int lenc = (len == 2) ? 1 + : (len == 4) ? 3 + : (len == 8) ? 2 + : 0; + + dr7 |= (1 << (i*2)); // enable local breakpoint + dr7 |= (type << (16+(i*4))); // set breakpoint type + dr7 |= (lenc << (18+(i*4))); // set breakpoint length + + return refresh_hwbpts(); + } + return false; +} + +//-------------------------------------------------------------------------- +bool pc_debmod_t::del_hwbpt(ea_t ea, bpttype_t type) +{ + for ( int i=0; i < MAX_BPT; i++ ) + { + if ( hwbpt_ea[i] == ea && hwbpt_type[i] == type ) + { + hwbpt_ea[i] = BADADDR; // clean the address + dr7 &= ~(3 << (i*2)); // clean the enable bits + dr7 &= ~(0xF << (i*4+16)); // clean the length and type + return refresh_hwbpts(); + } + } + return false; +} + + +#ifdef __NT__ +//-------------------------------------------------------------------------- +// Set hardware breakpoint for one thread +bool pc_debmod_t::set_hwbpts(HANDLE hThread) +{ + // sure_suspend_thread(ti); + CONTEXT Context; + Context.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; + + BOOL ok = GetThreadContext(hThread, &Context); + if ( !ok ) + { + deberr("GetThreadContext"); + return false; + } + Context.Dr0 = hwbpt_ea[0]; + Context.Dr1 = hwbpt_ea[1]; + Context.Dr2 = hwbpt_ea[2]; + Context.Dr3 = hwbpt_ea[3]; + Context.Dr6 = 0; + Context.Dr7 = dr7; + + ok = SetThreadContext(hThread, &Context); + if ( !ok ) + { + deberr("SetThreadContext"); + } + // sure_resume_thread(ti); + return ok != FALSE; +} + +//-------------------------------------------------------------------------- +ea_t pc_debmod_t::is_hwbpt_triggered(thid_t id, bool is_stepping) +{ + CONTEXT Context; + Context.ContextFlags = CONTEXT_DEBUG_REGISTERS | CONTEXT_CONTROL; + HANDLE h = get_thread_handle(id); + if ( GetThreadContext(h, &Context) ) + { + for ( int i=0; i < MAX_BPT; i++ ) + { + if ( (Context.Dr7 & uint32(1 << (i*2))) + && (Context.Dr6 & uint32(1 << i)) ) // Local hardware breakpoint 'i' + { + ULONG_PTR *dr = NULL; + switch ( i ) + { + case 0: dr = &Context.Dr0; break; + case 1: dr = &Context.Dr1; break; + case 2: dr = &Context.Dr2; break; + case 3: dr = &Context.Dr3; break; + } + if ( dr == NULL ) + break; + if ( hwbpt_ea[i] == *dr ) + { + set_hwbpts(h); // Clear the status bits + // do not report exec breakpoint if it occurs while we are stepping + if ( is_stepping && hwbpt_type[i] == BPT_EXEC ) + break; + return hwbpt_ea[i]; + } + //? TRACING else + // debdeb("System hardware breakpoint at %08X ???\n", *dr); //? + // what to do ?: + // reset it, and continue as if no event were received ? + // send it to IDA, and let the user setup a "stop on non-debugger hardware breakpoint" option ? + } + } + } + return BADADDR; +} +#endif // ifdef __NT__ + +//-------------------------------------------------------------------------- +void pc_debmod_t::cleanup_hwbpts() +{ + for ( int i=0; i < MAX_BPT; i++ ) + { + hwbpt_ea[i] = BADADDR; + hwbpt_type[i] = bpttype_t(0); + } + dr6 = 0; + dr7 = 0x100; // exact local breakpoints +} + +//-------------------------------------------------------------------------- +ea_t pc_debmod_t::calc_appcall_stack(const regvals_t ®vals) +{ + ea_t ea = inherited::calc_appcall_stack(regvals); +#ifndef __X86__ + // do not touch the red zone (used by gcc) + ea = ea > 128 ? ea - 128 : BADADDR; +#endif + return ea; +} + +//-------------------------------------------------------------------------- +int pc_debmod_t::finalize_appcall_stack( + call_context_t &, + regval_map_t &, + bytevec_t &stk) +{ + // pc-specific: add endless loop, so user does not execute unwanted code + // after manual appcall. we do not really need to write bpt, + // but it is easy to include it here than skip it. + // previously we reserved 'addrsize' bytes on the stack for this purpose, + // and we use 3 of them. + static const uchar bpt_and_loop[] = { 0xCC, 0xEB, 0xFE }; + stk.append(bpt_and_loop, sizeof(bpt_and_loop)); + return 0; +} + +//-------------------------------------------------------------------------- +bool pc_debmod_t::should_stop_appcall( + thid_t tid, + const debug_event_t *event, + ea_t ea) +{ + if ( inherited::should_stop_appcall(tid, event, ea) ) + return true; + + // Check if the current instruction is a "RET" and then dereferences + // the contents of SP to find the return address. IF it matches, it is + // time to stop + regvals_t regs; + regs.resize(X86_NREGS); + do + { + // Start by reading registers + if ( dbg_read_registers(tid, X86_RC_GENERAL, regs.begin(), NULL) != DRC_OK ) + break; + + // Get the opcodes + uchar opcode; + if ( dbg_read_memory((ea_t)regs[pc_idx].ival, &opcode, 1, NULL) != 1 ) + break; + // Check for "RET" and "RET n" + if ( opcode != 0xC3 && opcode != 0xC2 ) + break; + + // Dereference value at ESP + ea_t at_sp = BADADDR; + if ( dbg_read_memory((ea_t)regs[sp_idx].ival, &at_sp, sizeof(at_sp), NULL) != sizeof(at_sp) ) + break; + return ea == at_sp; // time to stop! + } while ( false ); + return false; +} + +//-------------------------------------------------------------------------- +bool pc_debmod_t::preprocess_appcall_cleanup(thid_t, call_context_t &ctx) +{ + // Linux 2.6.24-19 has a bug(?): + // it doesn't clear trace flag after single-stepping + // so if we single-step and then make an appcall, we would restore eflags with TF set + // but next time we resume the program, kernel thinks that TF was set by the user + // and doesn't clear it, and so our appcall stops immediately + // to prevent that, we'll always clear trace flag before restoring eflags + if ( ctx.saved_regs.size() > sr_idx ) + ctx.saved_regs[sr_idx].ival &= ~0x100; + return true; // success +} + +//-------------------------------------------------------------------------- +void pc_debmod_t::read_fpu_registers( + regval_t *values, + int clsmask, + const void *fptr, + size_t step) +{ + const uchar *vptr = (const uchar *)fptr; + for ( int i=0; i < 8; i++,vptr+=step ) + { + if ( (clsmask & X86_RC_FPU) != 0 ) + { + regval_t *v = &values[R_ST0+i]; + memcpy(&v->fval, vptr, 10); //-V512 v->fval underflow + v->rvtype = RVT_FLOAT; + } + if ( (clsmask & X86_RC_MMX) != 0 ) + values[R_MMX0+i].set_bytes(vptr, 8); + } +} + +//-------------------------------------------------------------------------- +const char *pc_debmod_t::get_local_platform() +{ +#ifdef __NT__ +# define LOCAL_PLATFORM "win32" +#else +# ifdef __MAC__ +# define LOCAL_PLATFORM "macosx" +# else +# ifdef __LINUX__ +# define LOCAL_PLATFORM "linux" +# else +# define LOCAL_PLATFORM "PC_UNDEFINED" +# endif +# endif +#endif + return LOCAL_PLATFORM; +} diff --git a/idasdk75/dbg/pc_debmod.h b/idasdk76/dbg/pc_debmod.h similarity index 100% rename from idasdk75/dbg/pc_debmod.h rename to idasdk76/dbg/pc_debmod.h diff --git a/idasdk76/dbg/pc_local_impl.cpp b/idasdk76/dbg/pc_local_impl.cpp new file mode 100644 index 0000000..95b6474 --- /dev/null +++ b/idasdk76/dbg/pc_local_impl.cpp @@ -0,0 +1,113 @@ +// x86-specific code (compiled only on IDA side, never on the server side) + +#include <dbg.hpp> +#include "pc_regs.hpp" +#include "deb_pc.hpp" + +//-------------------------------------------------------------------------- +// +// DEBUGGER REGISTER AND INSTRUCTION INFORMATIONS +// +//-------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +#if 0 +static void DEBUG_REGVALS(regval_t *values) +{ + for ( int i = 0; i < qnumber(registers); i++ ) + { + msg("%s = ", registers[i].name); + switch ( registers[i].dtyp ) + { + case dt_qword: msg("%016LX\n", values[i].ival); break; + case dt_dword: msg("%08X\n", values[i].ival); break; + case dt_word: msg("%04X\n", values[i].ival); break; + case dt_tbyte: + for ( int j = 0; j < sizeof(regval_t); j++ ) + { + if ( j == 10 ) + msg(" - "); // higher bytes are not used by x86 floats + msg("%02X ", ((unsigned char*)&values[i])[j]); + } + // msg("%02X ", (unsigned short)values[i].fval[j]); + msg("\n"); + break; + } + } + msg("\n"); +} +#endif + +//-------------------------------------------------------------------------- +drc_t idaapi x86_read_registers( + thid_t thread_id, + int clsmask, + regval_t *values, + qstring *errbuf) +{ + drc_t drc = s_read_registers(thread_id, clsmask, values, errbuf); + if ( drc == DRC_OK ) + { + // FPU related registers + if ( (clsmask & X86_RC_FPU) != 0 ) + { + for ( size_t i = 0; i < debugger.nregs; i++ ) + { + const register_info_t &ri = debugger.regs(i); + if ( ri.register_class == X86_RC_FPU && ri.dtype == dt_tbyte ) + { + int rc = processor_t::realcvt(&values[i].fval, &values[i].fval, 004); // load long double + if ( rc == 0 ) + break; // realcvt not implemented + else if ( rc < 0 ) // error + values[i].fval.clear(); + } + } + } + } + return drc; +} + +//-------------------------------------------------------------------------- +drc_t idaapi x86_write_register( + thid_t thread_id, + int reg_idx, + const regval_t *value, + qstring *errbuf) +{ + regval_t rv = *value; + // FPU related registers + const register_info_t &ri = debugger.regs(reg_idx); + if ( ri.register_class == X86_RC_FPU && ri.dtype == dt_tbyte ) + { + uchar fn[10]; + int code = processor_t::realcvt(fn, &rv.fval, 014); // store long double //-V536 octal + if ( code == REAL_ERROR_FPOVER ) + memcpy(&rv.fval, fn, 10); //-V512 rv.fval underflow + } + return s_write_register(thread_id, reg_idx, &rv, errbuf); +} + +//-------------------------------------------------------------------------- +int is_x86_valid_bpt(bpttype_t type, ea_t ea, int len) +{ + if ( type != BPT_SOFT ) + { + if ( (debugger.flags & DBG_FLAG_ANYSIZE_HWBPT) == 0 ) + return check_x86_hwbpt(type, ea, len); + + if ( type == 0 ) + return BPT_BAD_TYPE; + } + return BPT_OK; +} + +//-------------------------------------------------------------------------- +void processor_specific_init(void) +{ +} + +//-------------------------------------------------------------------------- +void processor_specific_term(void) +{ +} diff --git a/idasdk75/dbg/pc_regs.cpp b/idasdk76/dbg/pc_regs.cpp similarity index 100% rename from idasdk75/dbg/pc_regs.cpp rename to idasdk76/dbg/pc_regs.cpp diff --git a/idasdk75/dbg/pc_regs.hpp b/idasdk76/dbg/pc_regs.hpp similarity index 100% rename from idasdk75/dbg/pc_regs.hpp rename to idasdk76/dbg/pc_regs.hpp diff --git a/idasdk75/dbg/plugin.mak b/idasdk76/dbg/plugin.mak similarity index 100% rename from idasdk75/dbg/plugin.mak rename to idasdk76/dbg/plugin.mak diff --git a/idasdk75/dbg/rpc_debmod.cpp b/idasdk76/dbg/rpc_debmod.cpp similarity index 100% rename from idasdk75/dbg/rpc_debmod.cpp rename to idasdk76/dbg/rpc_debmod.cpp diff --git a/idasdk76/dbg/rpc_debmod.h b/idasdk76/dbg/rpc_debmod.h new file mode 100644 index 0000000..bd88e25 --- /dev/null +++ b/idasdk76/dbg/rpc_debmod.h @@ -0,0 +1,121 @@ +#ifndef __RPC_DEBUGGER_MODULE__ +#define __RPC_DEBUGGER_MODULE__ + +#define pack_ea DONT_USE_pack_ea_USE_pack_ea64_INSTEAD +#define unpack_ea DONT_USE_unpack_ea_USE_unpack_ea64_INSTEAD + +#include "debmod.h" +#include "dbg_rpc_client.h" + +//--------------------------------------------------------------------------- +class rpc_debmod_t + : public debmod_t, + public dbg_rpc_client_t +{ + drc_t process_start_or_attach(bytevec_t &req, qstring *errbuf); + +public: + rpc_debmod_t(const char *default_platform = NULL); + virtual bool idaapi open_remote(const char *hostname, int port_number, const char *password, qstring *errbuf) newapi; + drc_t close_remote(); + + int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) + { + return rpc_engine_t::send_ioctl(fn, buf, size, poutbuf, poutsize); + } + + //-------------------------------------------------------------------------- + inline int getint(ushort code) + { + bytevec_t req = prepare_rpc_packet((uchar)code); + return send_request_get_long_result(req); + } + drc_t get_drc_int(uchar code, int x) + { + bytevec_t req = prepare_rpc_packet(code); + req.pack_dd(x); + return send_request_get_drc_result(req, NULL); + } + inline drc_t get_drc(ushort code, qstring *errbuf=NULL) + { + bytevec_t req = prepare_rpc_packet((uchar)code); + return send_request_get_drc_result(req, errbuf); + } + + // + virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; + virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; + virtual void idaapi dbg_term(void) override; + virtual drc_t idaapi dbg_get_processes(procinfo_vec_t *procs, qstring *errbuf) override; + virtual drc_t idaapi dbg_detach_process(void) override; + virtual drc_t idaapi dbg_start_process( + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf) override; + virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; + virtual drc_t idaapi dbg_attach_process(pid_t process_id, int event_id, int flags, qstring *errbuf) override; + virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; + virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; + virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; + virtual void idaapi dbg_set_exception_info(const exception_info_t *info, int qty) override; + virtual void idaapi dbg_stopped_at_debug_event(import_infos_t *infos, bool dlls_added, thread_name_vec_t *thr_names) override; + virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; + virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; + virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; + virtual drc_t idaapi dbg_read_registers( + thid_t thread_id, + int clsmask, + regval_t *values, + qstring *errbuf) override; + virtual drc_t idaapi dbg_write_register( + thid_t thread_id, + int reg_idx, + const regval_t *value, + qstring *errbuf) override; + virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) override; + virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &areas, qstring *errbuf) override; + virtual int idaapi dbg_get_scattered_image(scattered_image_t &si, ea_t base) override; + virtual bool idaapi dbg_get_image_uuid(bytevec_t *uuid, ea_t base) override; + virtual ea_t idaapi dbg_get_segm_start(ea_t base, const qstring &segname) override; + virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; + virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; + virtual int idaapi dbg_is_ok_bpt(bpttype_t type, ea_t ea, int len) override; + virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; + virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; + virtual drc_t idaapi dbg_update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf) override; + virtual drc_t idaapi dbg_update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf) override; + virtual drc_t idaapi dbg_eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf) override; + virtual int idaapi dbg_open_file(const char *file, uint64 *fsize, bool readonly) override; + virtual void idaapi dbg_close_file(int fn) override; + virtual ssize_t idaapi dbg_read_file(int fn, qoff64_t off, void *buf, size_t size) override; + virtual ssize_t idaapi dbg_write_file(int fn, qoff64_t off, const void *buf, size_t size) override; + virtual int idaapi handle_ioctl(int fn, const void *buf, size_t size, void **outbuf, ssize_t *outsize) override; + virtual int idaapi get_system_specific_errno(void) const override; + virtual drc_t idaapi dbg_update_call_stack(thid_t, call_stack_t *) override; + virtual ea_t idaapi dbg_appcall( + ea_t func_ea, + thid_t tid, + int stkarg_nbytes, + const struct regobjs_t *regargs, + struct relobj_t *stkargs, + struct regobjs_t *retregs, + qstring *errbuf, + debug_event_t *event, + int flags) override; + virtual drc_t idaapi dbg_cleanup_appcall(thid_t tid) override; + virtual int get_regidx(const char *, int *) override { INTERR(30116); } + virtual int idaapi dbg_rexec(const char *cmdline) override; + virtual drc_t idaapi dbg_bin_search( + ea_t *ea, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &ptns, + int srch_flags, + qstring *errbuf) override; +}; + +#endif diff --git a/idasdk76/dbg/server.cpp b/idasdk76/dbg/server.cpp new file mode 100644 index 0000000..07a88bd --- /dev/null +++ b/idasdk76/dbg/server.cpp @@ -0,0 +1,224 @@ +/* + IDA remote debugger server +*/ + +#ifdef _WIN32 +// We use the deprecated inet_ntoa() function for Windows XP compatibility. +//lint -e750 local macro '' not referenced +#define _WINSOCK_DEPRECATED_NO_WARNINGS +#endif + +#include <pro.h> +#include <expr.hpp> +#include "server.h" + +// Provide dummy versions for tinfo copy/clear. Debugger servers do not use them +#if !defined(__NT__) +void ida_export copy_tinfo_t(tinfo_t *, const tinfo_t &) {} +void ida_export clear_tinfo_t(tinfo_t *) {} +#endif + +// We don't have a kernel. Provide envvar-based debug file directory retrieval. +#if defined(__LINUX__) +static bool _elf_debug_file_directory_resolved = false; +static qstring _elf_debug_file_directory; +idaman const char *ida_export get_elf_debug_file_directory() +{ + if ( !_elf_debug_file_directory_resolved ) + { + if ( !qgetenv("DEBUG_FILE_DIRECTORY", &_elf_debug_file_directory) ) + qgetenv("ELF_DEBUG_FILE_DIRECTORY", &_elf_debug_file_directory); + if ( _elf_debug_file_directory.empty() ) + _elf_debug_file_directory = "/usr/lib/debug"; + _elf_debug_file_directory_resolved = true; + } + return _elf_debug_file_directory.c_str(); +} + +//------------------------------------------------------------------------- +#ifdef TESTABLE_BUILD +static std::map<int,qstring> _pid_elf_debug_file_directories; +void set_elf_debug_file_directory_for_pid(int pid, const char *path) +{ + _pid_elf_debug_file_directories[pid] = path; +} + +//------------------------------------------------------------------------- +const char *get_elf_debug_file_directory_for_pid(int pid) +{ + const char *found = NULL; + std::map<int,qstring>::const_iterator it = _pid_elf_debug_file_directories.find(pid); + if ( it != _pid_elf_debug_file_directories.end() ) + found = it->second.begin(); + else + found = get_elf_debug_file_directory(); + return found; +} +#endif +#endif + +//lint -esym(714, dump_udt) not referenced +void dump_udt(const char *, const struct udt_type_data_t &) {} + + +//-------------------------------------------------------------------------- +// SERVER GLOBAL VARIABLES +#ifdef __SINGLE_THREADED_SERVER__ +dbgsrv_dispatcher_t dispatcher(false); + +static bool init_lock(void) { return true; } +bool lock_begin(void) { return true; } +bool lock_end(void) { return true; } +#else +dbgsrv_dispatcher_t dispatcher(true); + +static qmutex_t g_mutex = NULL; +static bool init_lock(void) { g_mutex = qmutex_create(); return g_mutex != NULL; } +bool lock_begin(void) { return qmutex_lock(g_mutex); } +bool lock_end(void) { return qmutex_unlock(g_mutex); } +#endif + +//-------------------------------------------------------------------------- +dbg_rpc_handler_t *g_global_server = NULL; + +//-------------------------------------------------------------------------- +// perform an action (func) on all debuggers +int for_all_debuggers(debmod_visitor_t &v) +{ + int code = 0; + dispatcher.clients_list->lock(); + { + client_handlers_list_t::storage_t::iterator it; + for ( it = dispatcher.clients_list->storage.begin(); + it != dispatcher.clients_list->storage.end(); + ++it ) + { + dbg_rpc_handler_t *h = (dbg_rpc_handler_t *) it->first; + code = v.visit(h->get_debugger_instance()); + if ( code != 0 ) + break; + } + } + dispatcher.clients_list->unlock(); + return code; +} + +//------------------------------------------------------------------------- +dbgsrv_dispatcher_t::dbgsrv_dispatcher_t(bool multi_threaded) + : base_dispatcher_t(multi_threaded), + broken_conns_supported(false), + on_broken_conn(BCH_DEFAULT) +{ + port_number = DEBUGGER_PORT_NUMBER; +} + +//------------------------------------------------------------------------- +void dbgsrv_dispatcher_t::collect_cliopts(cliopts_t *out) +{ + struct ida_local ns_t + { + static void _set_dpassword(const char *value, void *ud) + { + ((dbgsrv_dispatcher_t *) ud)->server_password = value; + } + static void _set_broken_connections_keep_debmod(const char *, void *ud) + { + ((dbgsrv_dispatcher_t *) ud)->on_broken_conn = BCH_KEEP_DEBMOD; + } + static void _set_closing_session_kill_debuggee(const char *, void *ud) + { + ((dbgsrv_dispatcher_t *) ud)->on_broken_conn = BCH_KILL_PROCESS; + } + }; + + static const cliopt_t cliopts[] = + { + { 'P', "password", "Password", ns_t::_set_dpassword, 1 }, + }; + // the following options are valid only if broken connections are supported + static const cliopt_t bc_cliopts[] = + { + { + 'k', + "on-broken-connection-keep-session", + "Keep debugger session alive when connection breaks", + ns_t::_set_broken_connections_keep_debmod, + 0, + }, + { + 'K', + "on-stop-kill-process", + "Kill debuggee when closing session", + ns_t::_set_closing_session_kill_debuggee, + 0, + }, + }; + + base_dispatcher_t::collect_cliopts(out); + for ( size_t i = 0; i < qnumber(cliopts); ++i ) + out->push_back(cliopts[i]); + + if ( broken_conns_supported ) + for ( size_t i = 0; i < qnumber(bc_cliopts); ++i ) + out->push_back(bc_cliopts[i]); +} + +//------------------------------------------------------------------------- +client_handler_t *dbgsrv_dispatcher_t::new_client_handler(idarpc_stream_t *_irs) +{ + dbg_rpc_handler_t *h = new dbg_rpc_handler_t(_irs, this); + h->verbose = verbose; + void *params = NULL; +#if defined(__LINUX__) && defined(TESTABLE_BUILD) + params = (void *) get_elf_debug_file_directory_for_pid; //lint !e611 cast between pointer to function type '' and pointer to object type 'void *' +#endif + h->set_debugger_instance(create_debug_session(params)); + g_global_server = h; + return h; +} + +//------------------------------------------------------------------------- +void dbgsrv_dispatcher_t::shutdown_gracefully(int signum) +{ + base_dispatcher_t::shutdown_gracefully(signum); + term_subsystem(); +} + + +//-------------------------------------------------------------------------- +// debugger remote server - TCP/IP mode +int NT_CDECL main(int argc, const char *argv[]) +{ +#ifdef ENABLE_LOWCNDS + init_idc(); +#endif + + // call the debugger module to initialize its subsystem once + if ( !init_lock() || !init_subsystem() ) + { + lprintf("Could not initialize subsystem!"); + return -1; + } + + qstring password; + if ( qgetenv("IDA_DBGSRV_PASSWD", &password) ) + dispatcher.server_password = password; + + int ida_major = IDA_SDK_VERSION / 100; +#if (IDA_SDK_VERSION % 10) == 0 + int ida_minor = (IDA_SDK_VERSION % 100)/10; // 740 -> 4 +#else + int ida_minor = IDA_SDK_VERSION % 100; // 741 -> 41 +#endif + + lprintf("IDA " SYSTEM SYSBITS " remote debug server(" __SERVER_TYPE__ ") " + "v%d.%d.%d. Hex-Rays (c) 2004-2021\n", + ida_major, ida_minor, IDD_INTERFACE_VERSION); + + dispatcher.broken_conns_supported = debmod_t::reuse_broken_connections; + cliopts_t cliopts(lprintf); + dispatcher.collect_cliopts(&cliopts); + cliopts.apply(argc, argv, &dispatcher); + dispatcher.install_signal_handlers(); + dispatcher.dispatch(); +} diff --git a/idasdk76/dbg/server.h b/idasdk76/dbg/server.h new file mode 100644 index 0000000..d0573a6 --- /dev/null +++ b/idasdk76/dbg/server.h @@ -0,0 +1,62 @@ +#ifndef SERVER_H +#define SERVER_H + +#include <network.hpp> + +#ifdef __NT__ +//# ifndef SIGHUP +//# define SIGHUP 1 +//# endif +# define DEBUGGER_ID DEBUGGER_ID_X86_IA32_WIN32_USER +#else // not NT, i.e. UNIX +# if defined(__LINUX__) +# if defined(__ARM__) +# define DEBUGGER_ID DEBUGGER_ID_ARM_LINUX_USER +# else +# define DEBUGGER_ID DEBUGGER_ID_X86_IA32_LINUX_USER +# endif +# elif defined(__MAC__) +# if defined(__ARM__) +# define DEBUGGER_ID DEBUGGER_ID_ARM_MACOS_USER +# else +# define DEBUGGER_ID DEBUGGER_ID_X86_IA32_MACOSX_USER +# endif +# endif +# include <sys/socket.h> +# include <netinet/in.h> +#endif // !__NT__ + +enum broken_conn_hndl_t +{ + BCH_DEFAULT, + BCH_KEEP_DEBMOD, + BCH_KILL_PROCESS, +}; + +struct dbgsrv_dispatcher_t : public base_dispatcher_t +{ + qstring server_password; + bool broken_conns_supported; + broken_conn_hndl_t on_broken_conn; + + dbgsrv_dispatcher_t(bool multi_threaded); + + virtual void collect_cliopts(cliopts_t *out) override; + virtual client_handler_t *new_client_handler(idarpc_stream_t *irs) override; + + virtual void shutdown_gracefully(int signum) override; +}; + +#include "debmod.h" +#include "dbg_rpc_hlp.h" +#include "dbg_rpc_handler.h" + +// // sizeof(ea_t)==8 and sizeof(size_t)==4 servers cannot be used to debug 64-bit +// // applications. but to debug 32-bit applications, simple 32-bit servers +// // are enough and can work with both 32-bit and 64-bit versions of ida. +// // so, there is no need to build sizeof(ea_t)==8 and sizeof(size_t)==4 servers +// #if defined(__EA64__) == defined(__X86__) +// #error "Mixed mode servers do not make sense, they should not be compiled" +// #endif + +#endif diff --git a/idasdk75/dbg/server.mak b/idasdk76/dbg/server.mak similarity index 100% rename from idasdk75/dbg/server.mak rename to idasdk76/dbg/server.mak diff --git a/idasdk76/dbg/win32/makefile b/idasdk76/dbg/win32/makefile new file mode 100644 index 0000000..8c9a5ef --- /dev/null +++ b/idasdk76/dbg/win32/makefile @@ -0,0 +1,176 @@ +include ../../allmake.mak + +GOALS-$(BUILD_IDA) += modules # target in $(IDA)module.mak +GOALS-$(BUILD_DBGSRV) += server # target in $(IDA)dbg/server.mak +.PHONY: $(GOALS-1) +all: $(GOALS-1) + +#---------------------------------------------------------------------- +ifdef __NT__ + ifndef __X86__ + SERVER = win64_remote$(B) + else + SERVER = win32_remote$(B) + endif +endif +ifdef SERVER + SERVERS += $(call server_exe,$(SERVER)) +endif + +#---------------------------------------------------------------------- +STUB = $(call module_dll,win32_stub) +ifdef BUILD_IDA + ifeq ($(or $(IDAHOME),$(DEMO_OR_FREE)),) + MODULES += $(STUB) + endif +endif + +#---------------------------------------------------------------------- +USER = $(call module_dll,win32_user) +ifeq ($(and $(BUILD_IDA),$(__NT__)),1) + MODULES += $(USER) +endif + +#---------------------------------------------------------------------- +# we explicitly added our module targets +NO_DEFAULT_TARGETS = 1 + +# NOTE: all MODULES must be defined before including plugin.mak. +include ../plugin.mak +# NOTE: target-specific rules and dependencies that use variable +# expansion to name the target (such as "$(MODULE): [...]") must +# come after including plugin.mak + +#---------------------------------------------------------------------- +# select OBJS common to user plugin and debugger server +BASE_OBJS-$(__NT__) += $(F)win32_debmod$(O) +BASE_OBJS-$(__NT__) += $(F)win32_util$(O) +BASE_OBJS-$(__NT__) += $(F)winbase_debmod$(O) +BASE_OBJS += $(BASE_OBJS-1) + +#---------------------------------------------------------------------- +SERVER_OBJS += $(F)win32_server$(O) +SERVER_OBJS += $(F)tilfuncs$(O) +SERVER_OBJS += $(BASE_OBJS) + +SERVER_STDLIBS += ole32.lib +SERVER_STDLIBS += oleaut32.lib + +include ../server.mak + +#---------------------------------------------------------------------- +STUB_OBJS += $(F)win32_stub$(O) +STUB_OBJS += $(F)w32sehch$(O) +$(STUB): MODULE_OBJS += $(STUB_OBJS) +$(STUB): $(STUB_OBJS) + +#---------------------------------------------------------------------- +USER_OBJS += $(F)win32_user$(O) +USER_OBJS += $(F)w32sehch$(O) +USER_OBJS += $(BASE_OBJS) +$(USER): MODULE_OBJS += $(USER_OBJS) +$(USER): $(USER_OBJS) +$(USER): STDLIBS += user32.lib + +#---------------------------------------------------------------------- +include $(IDA)objdir.mak + +# MAKEDEP dependency list ------------------ +$(F)tilfuncs$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)diskio.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)ins/pc.hpp $(I)intel.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)network.hpp $(I)pro.h $(I)range.hpp \ + $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/pe/cor.h ../../ldr/pe/corerror.h \ + ../../ldr/pe/corhdr.h ../../ldr/pe/mycor.h \ + ../../ldr/pe/pe.h ../../plugins/pdb/common.cpp \ + ../../plugins/pdb/cvconst.h ../../plugins/pdb/dbghelp.h \ + ../../plugins/pdb/dia2.h ../../plugins/pdb/idaaccess.hpp \ + ../../plugins/pdb/msdia.cpp ../../plugins/pdb/msdia.hpp \ + ../../plugins/pdb/pdb.hpp \ + ../../plugins/pdb/pdbaccess.hpp \ + ../../plugins/pdb/pdbida.hpp \ + ../../plugins/pdb/pdblocal.cpp \ + ../../plugins/pdb/pdblocal.hpp \ + ../../plugins/pdb/varser.hpp ../debmod.h tilfuncs.cpp \ + tilfuncs.hpp +$(F)w32sehch$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp w32sehch.cpp w32sehch.h +$(F)win32_debmod$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)dbg.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)err.h $(I)exehdr.h $(I)fixup.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ + $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)offset.hpp $(I)pro.h $(I)prodir.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../../ldr/pe/../idaldr.h \ + ../../ldr/pe/common.cpp ../../ldr/pe/common.h \ + ../../ldr/pe/pe.h ../dbg_pe_hlp.cpp ../deb_pc.hpp \ + ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ + win32_debmod.cpp win32_debmod.h win32_debmod_impl.cpp \ + win32_rpc.h win32_undoc.h win32_util.hpp \ + winbase_debmod.h +$(F)win32_server$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ + $(I)idp.hpp $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/pe/cor.h ../../ldr/pe/corerror.h \ + ../../ldr/pe/corhdr.h ../../ldr/pe/mycor.h \ + ../../ldr/pe/pe.h ../../plugins/pdb/cvconst.h \ + ../../plugins/pdb/dia2.h ../../plugins/pdb/idaaccess.hpp \ + ../../plugins/pdb/msdia.hpp ../../plugins/pdb/pdb.hpp \ + ../../plugins/pdb/pdbaccess.hpp \ + ../../plugins/pdb/pdbida.hpp \ + ../../plugins/pdb/pdblocal.hpp ../dbg_rpc_hlp.h \ + ../deb_pc.hpp ../debmod.h ../pc_debmod.h ../pc_regs.hpp \ + tilfuncs.hpp win32_debmod.h win32_rpc.h win32_server.cpp \ + win32_util.hpp winbase_debmod.h +$(F)win32_stub$(O): $(I)../ldr/pe/pe.h $(I)../plugins/pdb/pdb.hpp \ + $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/pe/pe.h ../common_local_impl.cpp \ + ../common_stub_impl.cpp ../dbg_rpc_client.h \ + ../dbg_rpc_engine.h ../dbg_rpc_hlp.h ../deb_pc.hpp \ + ../debmod.h ../pc_local_impl.cpp ../pc_regs.hpp \ + ../rpc_debmod.h w32sehch.h win32_local_impl.cpp \ + win32_rpc.h win32_stub.cpp +$(F)win32_user$(O): $(I)../ldr/pe/pe.h $(I)../plugins/pdb/pdb.hpp \ + $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/pe/pe.h ../common_local_impl.cpp \ + ../common_stub_impl.cpp ../dbg_rpc_hlp.h ../deb_pc.hpp \ + ../debmod.h ../pc_debmod.h ../pc_local_impl.cpp \ + ../pc_regs.hpp w32sehch.h win32_debmod.h \ + win32_local_impl.cpp win32_rpc.h win32_server_stub.cpp \ + win32_user.cpp win32_util.hpp winbase_debmod.h +$(F)win32_util$(O): $(I)bytes.hpp $(I)ida.hpp $(I)idd.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp $(I)netnode.hpp \ + $(I)network.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../deb_pc.hpp ../debmod.h \ + ../pc_debmod.h ../pc_regs.hpp win32_util.cpp \ + win32_util.hpp winbase_debmod.h +$(F)winbase_debmod$(O): $(I)bytes.hpp $(I)ida.hpp $(I)idd.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)network.hpp $(I)pro.h $(I)range.hpp \ + $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ../deb_pc.hpp \ + ../debmod.h ../pc_debmod.h ../pc_regs.hpp win32_util.hpp \ + winbase_debmod.cpp winbase_debmod.h diff --git a/idasdk76/dbg/win32/w32sehch.cpp b/idasdk76/dbg/win32/w32sehch.cpp new file mode 100644 index 0000000..d021019 --- /dev/null +++ b/idasdk76/dbg/win32/w32sehch.cpp @@ -0,0 +1,338 @@ +#include <pro.h> +#include <name.hpp> +#include <kernwin.hpp> +#include <dbg.hpp> +#include <loader.hpp> +#include "w32sehch.h" + +static int req_id = -1; + +//------------------------------------------------------------------------- +// represents data to store on x86seh_chooser_t +struct x86seh_entry_t +{ + uint32 handler = 0; // address of SEH handler + uint32 stack = 0; // address of SEH chain on the stack + x86seh_entry_t(uint32 _handler, uint32 _stack) + : handler(_handler), stack(_stack) {} + + bool operator ==(const x86seh_entry_t &e) const { return handler == e.handler && stack == e.handler; } +}; +DECLARE_TYPE_AS_MOVABLE(x86seh_entry_t); + +//------------------------------------------------------------------------- +// non-modal exception handler chooser +struct x86seh_chooser_t : public chooser_t +{ +protected: + qvector<x86seh_entry_t> list; + qstring title_; + thid_t tid; + + static const int widths_[]; + static const char *const header_[]; + enum { ICON = 144 }; + +public: + // this object must be allocated using `new` + x86seh_chooser_t(thid_t tid); + virtual ~x86seh_chooser_t() + { + unhook_from_notification_point( + HT_DBG, + dbg_handler, const_cast<char *>(title)); + } + ssize_t choose(uint32 addr = uint32(-1)) //lint !e1511 member hides non-virtual member + { + return ::choose(this, &addr); + } + + virtual const void *get_obj_id(size_t *len) const override + { + *len = sizeof(tid); + return &tid; + } + + virtual size_t idaapi get_count() const override { return list.size(); } + virtual void idaapi get_row( + qstrvec_t *cols, + int *icon_, + chooser_item_attrs_t *attrs, + size_t n) const override; + virtual cbret_t idaapi enter(size_t n) override; + + // calculate the location of the item, + virtual ssize_t idaapi get_item_index(const void *item_data) const override; + virtual bool idaapi init() override; + virtual cbret_t idaapi refresh(ssize_t n) override; + + ea_t get_stack_addr(int n) const; + +protected: + static ssize_t idaapi dbg_handler(void *ud, int notif_code, va_list va); +}; + +//------------------------------------------------------------------------- +const int x86seh_chooser_t::widths_[] = +{ + CHCOL_HEX | 10, // Address + 30, // Name + 10, // Stack +}; +const char *const x86seh_chooser_t::header_[] = +{ + "Address", // 0 + "Name", // 1 + "Stack", // 2 +}; + +static const char seh_widget_title[] = "Structured exception handlers"; +//------------------------------------------------------------------------- +inline x86seh_chooser_t::x86seh_chooser_t(thid_t tid_) + : chooser_t(CH_NOBTNS | CH_FORCE_DEFAULT | CH_CAN_REFRESH, + qnumber(widths_), widths_, header_), + tid(tid_) +{ + title_.sprnt("[%04X] - %s", tid, seh_widget_title); + title = title_.c_str(); + CASSERT(qnumber(widths_) == qnumber(header_)); + icon = ICON; + + hook_to_notification_point( + HT_DBG, + dbg_handler, const_cast<char *>(title)); +} + +//------------------------------------------------------------------------- +void idaapi x86seh_chooser_t::get_row( + qstrvec_t *cols_, + int *, + chooser_item_attrs_t *, + size_t n) const +{ + // assert: n < list.size() + uint32 addr = list[n].handler; + + qstrvec_t &cols = *cols_; + cols[0].sprnt("%08X", addr); + get_nice_colored_name(&cols[1], addr, GNCN_NOCOLOR | GNCN_NOLABEL); + // set Stack column data + cols[2].sprnt("%08X", list[n].stack); + CASSERT(qnumber(header_) == 3); +} + +//------------------------------------------------------------------------- +chooser_t::cbret_t idaapi x86seh_chooser_t::enter(size_t n) +{ + // assert: n < list.size() + ea_t ea = ea_t(list[n].handler); + if ( !is_code(get_flags(ea)) ) + create_insn(ea); + jumpto(ea); + return cbret_t(); // nothing changed +} + +//------------------------------------------------------------------------ +ssize_t idaapi x86seh_chooser_t::get_item_index(const void *item_data) const +{ + if ( list.empty() ) + return NO_SELECTION; + + const x86seh_entry_t item = *(const x86seh_entry_t *)item_data; + if ( item.handler == uint32(-1) ) + return 0; // first item by default + + // find `item_script` in the list + const x86seh_entry_t *p = list.find(item); + if ( p != list.end() ) + return p - list.begin(); + return 0; // first item by default +} + +//-------------------------------------------------------------------------- +bool idaapi x86seh_chooser_t::init() +{ + // rebuild the handlers list + uint64 fs_sel; + ea_t fs_base; + uint32 excr_ea; + list.clear(); + if ( !get_reg_val("fs", &fs_sel) + || internal_get_sreg_base(&fs_base, tid, int(fs_sel)) <= DRC_NONE + || read_dbg_memory(fs_base, &excr_ea, sizeof(excr_ea)) != sizeof(excr_ea) ) + { + warning("Failed to build the SEH list for thread %08X", tid); + return false; // do not show the empty chooser + } + + struct EXC_REG_RECORD + { + uint32 prev; + uint32 handler; + }; + EXC_REG_RECORD rec; + std::set<uint32> seen; + while ( excr_ea != 0xffffffff ) + { + if ( read_dbg_memory(excr_ea, &rec, sizeof(rec)) != sizeof(rec) ) + break; + + if ( !seen.insert(excr_ea).second ) + { + msg("Circular SEH record has been detected\n"); + break; + } + + list.push_back(x86seh_entry_t(rec.handler, excr_ea)); + excr_ea = rec.prev; + } + return true; +} + +//------------------------------------------------------------------------ +chooser_t::cbret_t idaapi x86seh_chooser_t::refresh(ssize_t n) +{ + uint32 item_addr = uint32(-1); + if ( n >= 0 && n < list.size() ) + item_addr = list[n].handler; // remember the currently selected handler + + init(); + + if ( n < 0 ) + return NO_SELECTION; + ssize_t idx = get_item_index(&item_addr); + // no need to adjust `idx` as get_item_index() returns first item by + // default + return idx; +} + +//------------------------------------------------------------------------- +ea_t x86seh_chooser_t::get_stack_addr(int n) const +{ + if ( n < list.size() ) + return ea_t(list[n].stack); + + return BADADDR; +} + +//------------------------------------------------------------------------- +ssize_t idaapi x86seh_chooser_t::dbg_handler(void *ud, int code, va_list) +{ + if ( code == dbg_suspend_process ) + { + const char *ttl = static_cast<const char *>(ud); + refresh_chooser(ttl); + } + return 0; +} + +//------------------------------------------------------------------------- +struct stkview_ah_t : public action_handler_t +{ + virtual int idaapi activate(action_activation_ctx_t *ctx) override + { + if ( !ctx->chooser_selection.empty() ) // should always be the case + { + size_t idx = ctx->chooser_selection[0]; + const x86seh_chooser_t *c = (x86seh_chooser_t *) ctx->source.chooser; + if ( c == nullptr ) + return 0; + + ea_t ea = c->get_stack_addr(idx); + if ( ea != BADADDR ) + { + TWidget *w = find_widget("Stack view"); + if ( w != nullptr ) + { + activate_widget(w, true); + jumpto(ea); + } + } + } + return 1; + } + + virtual action_state_t idaapi update(action_update_ctx_t *ctx) override + { + return ::qstrstr(ctx->widget_title.c_str(), seh_widget_title) != nullptr + ? AST_ENABLE_FOR_WIDGET + : AST_DISABLE_FOR_WIDGET; + } +}; +static stkview_ah_t stkview_ah; + +//------------------------------------------------------------------------- +struct show_window_ah_t : public action_handler_t +{ + virtual int idaapi activate(action_activation_ctx_t *) override + { + thid_t tid = get_current_thread(); + x86seh_chooser_t *ch = new x86seh_chooser_t(tid); + bool ok = ch->choose() == 0; + if ( ok ) + { + TWidget *w = find_widget(ch->title); + if ( w != nullptr ) + { +#define ACTION_NAME "x86seh:Stack" + const action_desc_t stkview_ah_action = ACTION_DESC_LITERAL_OWNER( + ACTION_NAME, + "Follow in stack view", + &stkview_ah, + &PLUGIN, + nullptr, + nullptr, + -1, + ADF_OT_PLUGIN); + register_action(stkview_ah_action); + attach_action_to_popup( + w, + nullptr, // make permanent + ACTION_NAME); + } + } + return ok; //-V773 The function was exited without releasing the 'ch' pointer. + } //lint !e429 Custodial pointer 'ch' has not been freed or returned + + virtual action_state_t idaapi update(action_update_ctx_t *) override + { + return AST_ENABLE; + } +}; +static show_window_ah_t show_window_ah; + + +//--------------------------------------------------------------------------- +void remove_x86seh_menu() +{ + if ( req_id != -1 ) + { + cancel_exec_request(req_id); + req_id = -1; + } +} + +//--------------------------------------------------------------------------- +void install_x86seh_menu() +{ + // HACK: We queue this request because commdbg apparently enables the debug menus + // just after calling init_debugger(). + struct uireq_install_menu_t: public ui_request_t + { + virtual bool idaapi run() override + { + if ( !inf_is_64bit() ) + { + register_and_attach_to_menu( + "Debugger/Debugger windows/Stack trace", + "dbg:sehList", "SEH list", NULL, SETMENU_APP, + &show_window_ah, + &PLUGIN, + ADF_OT_PLUGIN); + } + req_id = -1; + return false; + } + }; + req_id = execute_ui_requests(new uireq_install_menu_t, NULL); +} diff --git a/idasdk75/dbg/win32/w32sehch.h b/idasdk76/dbg/win32/w32sehch.h similarity index 100% rename from idasdk75/dbg/win32/w32sehch.h rename to idasdk76/dbg/win32/w32sehch.h diff --git a/idasdk76/dbg/win32/win32_debmod.cpp b/idasdk76/dbg/win32/win32_debmod.cpp new file mode 100644 index 0000000..afe41d1 --- /dev/null +++ b/idasdk76/dbg/win32/win32_debmod.cpp @@ -0,0 +1,3519 @@ +#include <windows.h> +#include <fpro.h> +#include <err.h> +#include <ida.hpp> +#include <dbg.hpp> +#include <prodir.h> +#include <exehdr.h> +#include <kernwin.hpp> +#include <segment.hpp> +#include "win32_debmod.h" + +//------------------------------------------------------------------------- +struct machine_thread_state_t +{ + ea_t __eax; + ea_t __ebx; + ea_t __ecx; + ea_t __edx; + ea_t __edi; + ea_t __esi; + ea_t __ebp; + ea_t __esp; + ea_t __eip; +#ifndef __X86__ + ea_t __r8; + ea_t __r9; + ea_t __r10; + ea_t __r11; + ea_t __r12; + ea_t __r13; + ea_t __r14; + ea_t __r15; +#endif + ea_t __eflags; + ea_t __ss; + ea_t __cs; + ea_t __ds; + ea_t __es; + ea_t __fs; + ea_t __gs; +}; + +//------------------------------------------------------------------------- +#define MMX_FPU_REG_DATA_SIZE 10 +//lint -e754 local struct member '' not referenced +struct mmx_fpu_reg_t +{ + char __data[MMX_FPU_REG_DATA_SIZE]; + char __rsv[6]; +}; +CASSERT(sizeof(mmx_fpu_reg_t) == 16); + +//------------------------------------------------------------------------- +struct xmm_reg_t +{ + char __data[16]; +}; +CASSERT(sizeof(xmm_reg_t) == 16); +//lint +e754 + +//------------------------------------------------------------------------- +struct machine_float_state_t +{ + mmx_fpu_reg_t __fpu_stmm[8]; + xmm_reg_t __fpu_xmm[16]; + xmm_reg_t __fpu_ymmh[16]; + + uint32 __fpu_mxcsr; + uint32 __fpu_fcw; + uint32 __fpu_fsw; + uint32 __fpu_ftw; +}; + +//-------------------------------------------------------------------------- +struct regctx_t : public regctx_base_t +{ + win32_debmod_t &debmod; + + machine_thread_state_t cpu; + machine_float_state_t fpu; + + regctx_t(dynamic_register_set_t &_idaregs, win32_debmod_t &_debmod); + + bool init(void); + bool load(context_holder_t *out); + bool store(const context_holder_t &ctxh); +}; + +//-------------------------------------------------------------------------- +regctx_t::regctx_t(dynamic_register_set_t &_idaregs, win32_debmod_t &_debmod) + : regctx_base_t(_idaregs), debmod(_debmod) +{ + memset(&cpu, 0, sizeof(cpu)); + memset(&fpu, 0, sizeof(fpu)); + + idaregs.set_regclasses(x86_register_classes); +} + +//-------------------------------------------------------------------------- +//lint -esym(1762,regctx_t::init) could be made const +bool regctx_t::init(void) +{ + return (clsmask & X86_RC_ALL) != 0; +} + +//-------------------------------------------------------------------------- +bool regctx_t::load(context_holder_t *out) +{ + return init() && debmod.get_thread_state(out, &cpu, &fpu, tid, clsmask); +} + +//-------------------------------------------------------------------------- +bool regctx_t::store(const context_holder_t &ctxh) +{ + return debmod.set_thread_state(cpu, fpu, ctxh, tid, clsmask); +} + +//-------------------------------------------------------------------------- + +#ifndef TH32CS_SNAPNOHEAPS + #define TH32CS_SNAPNOHEAPS 0x0 +#endif +#include "win32_debmod_impl.cpp" + +typedef HANDLE WINAPI OpenThread_t(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwThreadId); +static OpenThread_t *_OpenThread = NULL; +typedef HRESULT WINAPI GetThreadDescription_t(HANDLE hThread, PWSTR *threadDescription); +static GetThreadDescription_t *_GetThreadDescription = NULL; + +#ifndef __X86__ +typedef BOOL WINAPI Wow64GetThreadContext_t(HANDLE hThread, PWOW64_CONTEXT lpContext); +typedef BOOL WINAPI Wow64SetThreadContext_t(HANDLE hThread, const WOW64_CONTEXT *lpContext); +typedef BOOL WINAPI Wow64GetThreadSelectorEntry_t(HANDLE hThread, DWORD dwSelector, PWOW64_LDT_ENTRY lpSelectorEntry); +static Wow64GetThreadContext_t *_Wow64GetThreadContext = NULL; +static Wow64SetThreadContext_t *_Wow64SetThreadContext = NULL; +static Wow64GetThreadSelectorEntry_t *_Wow64GetThreadSelectorEntry = NULL; +#endif + +// Older SDKs (such as the one used for the ..._opt_s debug servers) +// requires these defines +#ifndef XSTATE_MASK_AVX +# define XSTATE_MASK_AVX (XSTATE_MASK_GSSE) +#endif // XSTATE_MASK_AVX +#ifndef XSTATE_AVX +# define XSTATE_AVX (XSTATE_GSSE) +#endif // XSTATE_AVX + +#define CONTEXT_XSTATE_BIT 0x40 + +// https://docs.microsoft.com/en-us/windows/desktop/debug/working-with-xstate-context +// The definition of CONTEXT_XSTATE changed across SDKs. On older SDKs, where it would +// have another value, it wasn't usable anyway, so it's safe to undefine & re-define it. +#ifdef CONTEXT_XSTATE +# if ((CONTEXT_XSTATE & CONTEXT_XSTATE_BIT) == 0) +# undef CONTEXT_XSTATE +# if defined(_M_X64) +# define CONTEXT_XSTATE (0x00100040) +# else +# define CONTEXT_XSTATE (0x00010040) +# endif +# endif +#endif + + +//-------------------------------------------------------------------------- +static int calc_ctxflags(int clsmask) +{ + int ctxflags = CONTEXT_CONTROL|CONTEXT_INTEGER; + if ( (clsmask & X86_RC_SEGMENTS) != 0 ) + ctxflags |= CONTEXT_SEGMENTS; + if ( (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0 ) + ctxflags |= CONTEXT_FLOATING_POINT; + if ( (clsmask & X86_RC_XMM) != 0 ) +#ifndef __X86__ + ctxflags |= CONTEXT_FLOATING_POINT; +#else + ctxflags |= CONTEXT_EXTENDED_REGISTERS; +#endif + if ( (clsmask & X86_RC_YMM) != 0 ) +#ifndef __X86__ + ctxflags |= CONTEXT_XSTATE|CONTEXT_FLOATING_POINT; +#else + ctxflags |= CONTEXT_XSTATE|CONTEXT_EXTENDED_REGISTERS; +#endif + return ctxflags; +} + +//-------------------------------------------------------------------------- +// assertions that ensure that the conversion between CONTEXT and WOW64_CONTEXT +// is correct +#ifdef __X86__ +CASSERT(sizeof(FLOATING_SAVE_AREA) == 112); +CASSERT(CONTEXT_CONTROL == 0x10001); +CASSERT(CONTEXT_INTEGER == 0x10002); +CASSERT(CONTEXT_SEGMENTS == 0x10004); +CASSERT(CONTEXT_FLOATING_POINT == 0x10008); +CASSERT(CONTEXT_DEBUG_REGISTERS == 0x10010); +CASSERT(CONTEXT_EXTENDED_REGISTERS == 0x10020); +#else +CASSERT(sizeof(WOW64_FLOATING_SAVE_AREA) == 112); +CASSERT(sizeof(XSAVE_FORMAT) == WOW64_MAXIMUM_SUPPORTED_EXTENSION); +CASSERT(WOW64_CONTEXT_CONTROL == 0x10001); +CASSERT(WOW64_CONTEXT_INTEGER == 0x10002); +CASSERT(WOW64_CONTEXT_SEGMENTS == 0x10004); +CASSERT(WOW64_CONTEXT_FLOATING_POINT == 0x10008); +CASSERT(WOW64_CONTEXT_DEBUG_REGISTERS == 0x10010); +CASSERT(WOW64_CONTEXT_EXTENDED_REGISTERS == 0x10020); +#endif + +#ifndef __X86__ +//-------------------------------------------------------------------------- +inline int ctxflags_to_wow64(int ctxflags) +{ + if ( (ctxflags & CONTEXT_FLOATING_POINT) != 0 ) + ctxflags |= WOW64_CONTEXT_EXTENDED_REGISTERS; + // XSTATE in WOW64 is handled in a separate context + bool requires_xstate = (ctxflags & CONTEXT_XSTATE) == CONTEXT_XSTATE; + if ( requires_xstate ) + ctxflags |= WOW64_CONTEXT_FLOATING_POINT; + ctxflags &= ~CONTEXT_XSTATE_BIT; + ctxflags &= ~CONTEXT_AMD64; + ctxflags |= WOW64_CONTEXT_i386; + return ctxflags; // see CASSERTs anout CONTEXT_... bits above +} + +//------------------------------------------------------------------------- +static void WOW64_CONTEXT_to_CONTEXT( + CONTEXT *out, + const WOW64_CONTEXT &wow64ctx, + int clsmask, + PCONTEXT xstate_ctx, + const context_helper_t &helper) +{ + out->ContextFlags = calc_ctxflags(clsmask); + + if ( xstate_ctx != NULL && helper.xstate_helpers_loaded() ) + helper.pfnCopyContext(out, CONTEXT_XSTATE, xstate_ctx); + + out->Dr0 = wow64ctx.Dr0; + out->Dr1 = wow64ctx.Dr1; + out->Dr2 = wow64ctx.Dr2; + out->Dr3 = wow64ctx.Dr3; + out->Dr6 = wow64ctx.Dr6; + out->Dr7 = wow64ctx.Dr7; + + out->SegGs = wow64ctx.SegGs; + out->SegFs = wow64ctx.SegFs; + out->SegEs = wow64ctx.SegEs; + out->SegDs = wow64ctx.SegDs; + + out->Rdi = wow64ctx.Edi; + out->Rsi = wow64ctx.Esi; + out->Rbx = wow64ctx.Ebx; + out->Rdx = wow64ctx.Edx; + out->Rcx = wow64ctx.Ecx; + out->Rax = wow64ctx.Eax; + + out->Rbp = wow64ctx.Ebp; + out->SegCs = wow64ctx.SegCs; + out->EFlags = wow64ctx.EFlags; + out->SegSs = wow64ctx.SegSs; + out->Rip = wow64ctx.Eip; + out->Rsp = wow64ctx.Esp; + + if ( (wow64ctx.ContextFlags & WOW64_CONTEXT_EXTENDED_REGISTERS) != 0 ) + { + memcpy(&out->FltSave, wow64ctx.ExtendedRegisters, sizeof(out->FltSave)); + } + else if ( (wow64ctx.ContextFlags & WOW64_CONTEXT_FLOATING_POINT) != 0 ) + { + out->FltSave.ControlWord = wow64ctx.FloatSave.ControlWord; + out->FltSave.StatusWord = wow64ctx.FloatSave.StatusWord; + out->FltSave.TagWord = wow64ctx.FloatSave.TagWord; + out->FltSave.ErrorOffset = wow64ctx.FloatSave.ErrorOffset; + out->FltSave.ErrorSelector = wow64ctx.FloatSave.ErrorSelector; + out->FltSave.DataOffset = wow64ctx.FloatSave.DataOffset; + out->FltSave.DataSelector = wow64ctx.FloatSave.DataSelector; + memset(out->FltSave.FloatRegisters, 0, sizeof(out->FltSave.FloatRegisters)); + for ( int i=0; i < 8; i++ ) + memcpy(&out->FltSave.FloatRegisters[i], &wow64ctx.FloatSave.RegisterArea[i*10], 10); + } +} + +//-------------------------------------------------------------------------- +static void CONTEXT_to_WOW64_CONTEXT( + WOW64_CONTEXT *out, + CONTEXT &ctx, + PCONTEXT xstate_ctx, + int clsmask, + const context_helper_t &helper) +{ + int cflags = calc_ctxflags(clsmask); + int wflags = ctxflags_to_wow64(cflags); + out->ContextFlags = wflags; + + if ( xstate_ctx != NULL && helper.xstate_helpers_loaded() ) + helper.pfnCopyContext(xstate_ctx, CONTEXT_XSTATE, &ctx); + + out->Dr0 = ctx.Dr0; + out->Dr1 = ctx.Dr1; + out->Dr2 = ctx.Dr2; + out->Dr3 = ctx.Dr3; + out->Dr6 = ctx.Dr6; + out->Dr7 = ctx.Dr7; + + out->SegGs = ctx.SegGs; + out->SegFs = ctx.SegFs; + out->SegEs = ctx.SegEs; + out->SegDs = ctx.SegDs; + + out->Edi = ctx.Rdi; + out->Esi = ctx.Rsi; + out->Ebx = ctx.Rbx; + out->Edx = ctx.Rdx; + out->Ecx = ctx.Rcx; + out->Eax = ctx.Rax; + + out->Ebp = ctx.Rbp; + out->SegCs = ctx.SegCs; + out->EFlags = ctx.EFlags; + out->SegSs = ctx.SegSs; + out->Eip = ctx.Rip; + out->Esp = ctx.Rsp; + + if ( (wflags & WOW64_CONTEXT_FLOATING_POINT) != 0 ) + { + out->FloatSave.ControlWord = ctx.FltSave.ControlWord; + out->FloatSave.StatusWord = ctx.FltSave.StatusWord; + out->FloatSave.TagWord = ctx.FltSave.TagWord; + out->FloatSave.ErrorOffset = ctx.FltSave.ErrorOffset; + out->FloatSave.ErrorSelector = ctx.FltSave.ErrorSelector; + out->FloatSave.DataOffset = ctx.FltSave.DataOffset; + out->FloatSave.DataSelector = ctx.FltSave.DataSelector; + for ( int i=0; i < 8; i++ ) + memcpy(&out->FloatSave.RegisterArea[i*10], &ctx.FltSave.FloatRegisters[i], 10); + } + if ( (wflags & WOW64_CONTEXT_EXTENDED_REGISTERS) != 0 ) + memcpy(out->ExtendedRegisters, &ctx.FltSave, sizeof(ctx.FltSave)); +} + +#define Eip Rip +#endif + +//------------------------------------------------------------------------- +// https://docs.microsoft.com/en-us/windows/desktop/debug/working-with-xstate-context +bool context_helper_t::create_context(context_holder_t *out, int *_ctxflags) +{ + out->buffer.qclear(); + out->buffer.clear(); + int ctxsz = sizeof(CONTEXT); +#define CONTEXT_REQUIRES_XSTATE() ((*_ctxflags & CONTEXT_XSTATE_BIT) == CONTEXT_XSTATE_BIT) + if ( CONTEXT_REQUIRES_XSTATE() && !get_xstate_context_size(&ctxsz) ) + *_ctxflags &= ~CONTEXT_XSTATE_BIT; + out->buffer.resize(ctxsz); + if ( CONTEXT_REQUIRES_XSTATE() ) + { + if ( pfnInitializeContext( + out->buffer.begin(), + *_ctxflags, + &out->ptr, + (DWORD *) &ctxsz) == FALSE ) + { + return false; + } + + if ( pfnSetXStateFeaturesMask(out->ptr, XSTATE_MASK_AVX) == FALSE ) + return false; + } + else + { + out->ptr = (PCONTEXT) out->buffer.begin(); + out->ptr->ContextFlags = *_ctxflags; + } + return true; +} + +//------------------------------------------------------------------------- +bool context_helper_t::get_xstate_context_size(int *out_ctxsz) +{ + if ( xstate_context_size < 0 ) + { + xstate_context_size = 0; + const char *error = NULL; + + HINSTANCE h = GetModuleHandle(kernel32_dll); + *(FARPROC*) &pfnGetEnabledXStateFeatures = GetProcAddress(h, "GetEnabledXStateFeatures"); + *(FARPROC*) &pfnInitializeContext = GetProcAddress(h, "InitializeContext"); + *(FARPROC*) &pfnGetXStateFeaturesMask = GetProcAddress(h, "GetXStateFeaturesMask"); + *(FARPROC*) &pfnLocateXStateFeature = GetProcAddress(h, "LocateXStateFeature"); + *(FARPROC*) &pfnSetXStateFeaturesMask = GetProcAddress(h, "SetXStateFeaturesMask"); + *(FARPROC*) &pfnCopyContext = GetProcAddress(h, "CopyContext"); + + if ( pfnGetEnabledXStateFeatures != NULL + && pfnInitializeContext != NULL + && pfnGetXStateFeaturesMask != NULL + && pfnLocateXStateFeature != NULL + && pfnSetXStateFeaturesMask != NULL + && pfnCopyContext != NULL ) + { + DWORD64 feature_mask; + feature_mask = pfnGetEnabledXStateFeatures(); + if ( (feature_mask & XSTATE_MASK_AVX) != 0 ) + { + DWORD context_size = 0; + BOOL success = pfnInitializeContext( + NULL, + CONTEXT_ALL | CONTEXT_XSTATE, + NULL, + &context_size); + + if ( (success != FALSE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER) ) + error = "InitializeContext failed"; + else + xstate_context_size = context_size; + } + else + { + error = "AVX feature not enabled"; + } + } + else + { + error = "Couldn't retrieve AVX functions"; + } + + if ( error != NULL ) + msg("%s\n", error); + } + int ctxsz = xstate_context_size; + bool ok = ctxsz > 0; + if ( ok ) + *out_ctxsz = ctxsz; + return ok; +} + +//------------------------------------------------------------------------- +void context_helper_t::clear() +{ + memset(this, 0, sizeof(*this)); + xstate_context_size = -1; +} + +//-------------------------------------------------------------------------- +// Macro to test the DBG_FLAG_DONT_DISTURB flag +#if 0 +#define NODISTURB_ASSERT(x) QASSERT(x) +#else +#define NODISTURB_ASSERT(x) +#endif + +static int g_code = 0; + +//-------------------------------------------------------------------------- +void win32_debmod_t::check_thread(bool must_be_main_thread) const +{ + // remote debugger uses only one thread + if ( rpc != NULL ) + return; + + // someone turned off debthread? + if ( (debugger_flags & DBG_FLAG_DEBTHREAD) == 0 ) + return; + + // local debugger uses 2 threads and we must be in the correct one + QASSERT(30191, is_main_thread() == must_be_main_thread); +} + +//-------------------------------------------------------------------------- +static int utf16_to_utf8(char *buf, size_t bufsize, LPCWSTR unicode) +{ + qstring res; + utf16_utf8(&res, unicode); + qstrncpy(buf, res.c_str(), bufsize); + size_t n = res.length(); + if ( n > bufsize ) + n = bufsize; + return (int)n; +} + +//-------------------------------------------------------------------------- +// try to locate full path of a dll name without full path +// for example, toolhelp.dll -> c:\windows\toolhelp.dll +static bool find_full_path(char *fname, size_t fnamesize, const char *process_path) +{ + if ( fname[0] != '\0' && !qisabspath(fname) ) + { + char path[QMAXPATH]; + char dir[QMAXPATH]; + // check system directory + GetSystemDirectory(dir, sizeof(dir)); + qmakepath(path, sizeof(path), dir, fname, NULL); + if ( qfileexist(path) ) + { +FOUND: + qstrncpy(fname, path, fnamesize); + return true; + } + // check current process directory + if ( process_path[0] != '\0' && !qisabspath(process_path) ) + { + qdirname(dir, sizeof(dir), process_path); + qmakepath(path, sizeof(path), dir, fname, NULL); + if ( qfileexist(path) ) + goto FOUND; + } + // check current directory + if ( GetCurrentDirectory(sizeof(dir), dir) != 0 ) + { + qmakepath(path, sizeof(path), dir, fname, NULL); + if ( qfileexist(path) ) + goto FOUND; + } + return false; + } + return true; +} + +//-------------------------------------------------------------------------- +ssize_t win32_debmod_t::access_memory(eanat_t ea, void *buffer, ssize_t size, bool do_write, bool suspend) +{ + if ( process_handle == INVALID_HANDLE_VALUE ) + return -1; + + NODISTURB_ASSERT(in_event != NULL || exiting); + + // stop all threads before accessing its memory + if ( suspend ) + suspend_all_threads(); + + ea = s0tops(ea); + void *addr = (void *)ea; + + DWORD_PTR size_access = 0; + const DWORD BADPROT = DWORD(-1); + DWORD oldprotect = BADPROT; + bool ok; + + while ( true ) + { + // try to access the memory + + ok = do_write + ? WriteProcessMemory( + process_handle, // handle of the process whose memory is accessed + addr, // address to start access + buffer, // address of buffer + (DWORD)size, // number of bytes to access + (PDWORD_PTR)&size_access) != 0// address of number of bytes accessed + : ReadProcessMemory( + process_handle, // handle of the process whose memory is accessed + addr, // address to start access + buffer, // address of buffer + (DWORD)size, // number of bytes to access + (PDWORD_PTR)&size_access) != 0;// address of number of bytes accessed + + // if we have changed the page protection, revert it + if ( oldprotect != BADPROT ) + { + if ( !VirtualProtectEx( + process_handle, // handle of the process whose memory is accessed + addr, // address to start access + (DWORD)size, // number of bytes to access + oldprotect, + &oldprotect) ) + { + deberr("VirtualProtectEx2(%p)", addr); + } + break; // do not attempt more than once + } + + // bail out after a successful read/write + if ( ok ) + break; + + // bail out if it is not about "not enough access rights" + // *or* ERROR_PARTIAL_COPY as, sometimes we may read/write + // *only* parts of memory because of page breakpoints + int code = GetLastError(); + if ( code != ERROR_NOACCESS && code != ERROR_PARTIAL_COPY ) + { + deberr("%sProcessMemory(%p)", do_write ? "Write" : "Read", ea); + break; + } + + if ( code != ERROR_PARTIAL_COPY ) + size_access = 0; // size_access may be spoiled after failed ReadProcessMemory + + // check if the address is valid + MEMORY_BASIC_INFORMATION meminfo; + if ( !VirtualQueryEx(process_handle, // handle of process + addr, // address of region + &meminfo, // address of information buffer + sizeof(meminfo)) ) // size of buffer + { + size_access = 0; + break; + } + + // allow the desired access on the page + if ( !VirtualProtectEx( + process_handle, // handle of the process whose memory is accessed + addr, // address to start access + (DWORD)size, // number of bytes to access + do_write ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ, + &oldprotect) ) + { + deberr("VirtualProtectEx1(%08p, size=%d for %s)", ea, int(size), do_write ? "write" : "read"); + break; + } + } + + if ( do_write && ok ) + FlushInstructionCache( + process_handle, // handle to process with cache to flush + addr, // pointer to region to flush + (DWORD)size); // length of region to flush + + if ( suspend ) + resume_all_threads(); + return size_access; +} + +//-------------------------------------------------------------------------- +ssize_t win32_debmod_t::_read_memory(eanat_t ea, void *buffer, size_t size, bool suspend) +{ + return access_memory(ea, buffer, size, false, suspend); +} + +ssize_t idaapi win32_debmod_t::dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring * /*errbuf*/) +{ + check_thread(false); + return _read_memory(ea, buffer, size, true); +} + +//-------------------------------------------------------------------------- +// Make sure that the thread is suspended +// by calling SuspendThread twice +// If raw=true then SuspendThread() API will be called and we return directly +// without doing any further logic +static void _sure_suspend_thread(thread_info_t &ti, bool raw = false) +{ + HANDLE h = ti.hThread; + + int count = SuspendThread(h); + if ( raw ) + return; + + if ( count != -1 ) + ti.suspend_count++; + + count = SuspendThread(h); + if ( count != -1 ) + ti.suspend_count++; +} + +//-------------------------------------------------------------------------- +// Resume thread by calling ResumeThread as many times as required +// Note: this function just reverts the actions of sure_suspend_thread +// If the thread was already suspended before calling sure_suspend_thread +// then it will stay in the suspended state +// If raw=true then ResumeThread() will be called and we return directly +// without doing any further logic +static void _sure_resume_thread(thread_info_t &ti, bool raw = false) +{ + HANDLE h = ti.hThread; + if ( raw ) + { + ResumeThread(h); + return; + } + + while ( ti.suspend_count > 0 ) + { + ResumeThread(h); + ti.suspend_count--; + } +} + +//-------------------------------------------------------------------------- +inline void win32_debmod_t::suspend_all_threads(bool raw) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + _sure_suspend_thread(p->second, raw); +} + +//-------------------------------------------------------------------------- +inline void win32_debmod_t::resume_all_threads(bool raw) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + _sure_resume_thread(p->second, raw); +} + +//-------------------------------------------------------------------------- +static int get_thread_suspend_count(HANDLE hThread) +{ + DWORD dwSuspendCount = SuspendThread(hThread); + ResumeThread(hThread); + return dwSuspendCount; +} + +//-------------------------------------------------------------------------- +inline void win32_debmod_t::suspend_running_threads(threadvec_t &suspended) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t t = p->second; + t.suspend_count = get_thread_suspend_count(t.hThread); + if ( t.suspend_count == 0 ) + { + _sure_suspend_thread(t); + suspended.push_back(t); + } + } +} + +//-------------------------------------------------------------------------- +inline void win32_debmod_t::resume_suspended_threads(threadvec_t suspended) const +{ + threadvec_t::iterator p; + for ( p = suspended.begin(); p != suspended.end(); ++p ) + _sure_resume_thread(*p); +} + +//-------------------------------------------------------------------------- +size_t win32_debmod_t::add_dll(image_info_t &ii) +{ + dlls.insert(std::make_pair(ii.base, ii)); + dlls_to_import.insert(ii.base); + return (size_t)ii.imagesize; +} + +//-------------------------------------------------------------------------- +// is modname already present in the loaded module list? +bool win32_debmod_t::module_present(const char *modname) +{ + // host process is not added to dlls, so check it first + if ( process_path == modname ) + return true; + + // check DLLs which we already know about + for ( const auto &p : dlls ) + { + const image_info_t &ii = p.second; + if ( ii.name == modname ) + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +// iterate all modules of the specified process +// until the callback returns != 0 +int win32_debmod_t::for_each_module(DWORD _pid, module_cb_t module_cb, void *ud) +{ + int code = 0; + + module_snapshot_t msnap(get_tool_help()); + MODULEENTRY32 me; + for ( bool ok = msnap.first(TH32CS_SNAPNOHEAPS, _pid, &me); ok; ok = msnap.next(&me) ) + { + code = module_cb(this, &me, ud); + if ( code != 0 ) + break; + } + return code; +} + +//-------------------------------------------------------------------------- +// callback: get info about the main module of the debugger process +//lint -e{818} +int win32_debmod_t::get_dmi_cb(debmod_t *sess, MODULEENTRY32 *me32, void *ud) +{ + win32_debmod_t *_this = (win32_debmod_t *)sess; + // if the module name doesn't correspond to the process name, + // we continue to iterate + char buf[QMAXPATH]; + tchar_utf8(buf, me32->szModule, sizeof(buf)); + if ( !_this->process_path.empty() && stricmp(buf, qbasename(_this->process_path.c_str())) != 0 ) + return 0; + + // ok, this module corresponds to our debugged process + modinfo_t &dmi = *(modinfo_t *)ud; + dmi.name = _this->process_path; + dmi.base = EA_T(me32->modBaseAddr); + dmi.size = (asize_t)me32->modBaseSize; + return 1; // we stop to iterate +} + +//-------------------------------------------------------------------------- +// Return module information on the currently debugged process +void win32_debmod_t::get_debugged_module_info(modinfo_t *dmi) +{ + dmi->name[0] = '\0'; + dmi->base = BADADDR; + dmi->size = 0; + dmi->rebase_to = BADADDR; + for_each_module(pid, get_dmi_cb, dmi); +} + +//-------------------------------------------------------------------------- +void idaapi win32_debmod_t::dbg_stopped_at_debug_event( + import_infos_t *, + bool dlls_added, + thread_name_vec_t *thr_names) +{ + if ( dlls_added ) + { + check_thread(true); + // we will take advantage of this event to import information + // about the exported functions from the loaded dlls and the + // binary itself + name_info_t &ni = *get_debug_names(); + if ( !binary_to_import.name.empty() ) + { + const char *bin_path = binary_to_import.name.c_str(); + linput_t *li = open_linput(bin_path, false); + if ( li != NULL ) + { + get_pe_exports_from_path(bin_path, li, binary_to_import.base, ni); + close_linput(li); + } + binary_to_import.name.clear(); + } + + for ( easet_t::iterator p = dlls_to_import.begin(); p != dlls_to_import.end(); ) + { + get_dll_exports(dlls, *p, ni); + p = dlls_to_import.erase(p); + } + } + + if ( thr_names != NULL ) + update_thread_names(thr_names); +} + +//-------------------------------------------------------------------------- +static void update_thread_description(thread_info_t &ti) +{ + if ( _GetThreadDescription == NULL ) + return; + + PWSTR data; + HRESULT hr = _GetThreadDescription(ti.hThread, &data); + if ( SUCCEEDED(hr) ) + { + int data_sz = wcslen(data) * 2; // size in bytes + qstring newname; + if ( convert_encoding( + (bytevec_t*)&newname, + ENC_UTF16LE, ENC_UTF8, + (const uchar *)data, + data_sz) > 0 ) + { + if ( newname != ti.name ) + { + ti.name = newname.c_str(); // newname over allocated + ti.set_new_name(); + } + } + LocalFree(data); + } +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::update_thread_names(thread_name_vec_t *thr_names) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + update_thread_description(ti); + if ( ti.is_new_name() ) + { + thread_name_t &tn = thr_names->push_back(); + tn.tid = ti.tid; + tn.name = ti.name; + ti.clr_new_name(); + } + } +} + +//-------------------------------------------------------------------------- +// return the address of an exported name +ea_t win32_debmod_t::get_dll_export( + const images_t &_dlls, + ea_t imagebase, + const char *exported_name) +{ + ea_t ret = BADADDR; + + name_info_t ni; + if ( get_dll_exports(_dlls, imagebase, ni, exported_name) && !ni.addrs.empty() ) + ret = ni.addrs[0]; + return ret; +} + +//-------------------------------------------------------------------------- +win32_debmod_t::win32_debmod_t() + : expecting_debug_break(0), stop_at_ntdll_bpts(false) +{ + fake_suspend_event = false; + + pid = -1; + + // Reset handles + process_handle = INVALID_HANDLE_VALUE; + thread_handle = INVALID_HANDLE_VALUE; + redirin_handle = INVALID_HANDLE_VALUE; + redirout_handle = INVALID_HANDLE_VALUE; + + attach_evid = INVALID_HANDLE_VALUE; + attach_status = as_none; + + memset(&cpdi, 0, sizeof(cpdi)); + cpdi.hFile = INVALID_HANDLE_VALUE; // hFile + cpdi.hProcess = INVALID_HANDLE_VALUE; // hProcess + cpdi.hThread = INVALID_HANDLE_VALUE; // hThread + + winxp_step_thread = 0; + memset(&in_event, 0, sizeof(in_event)); + exiting = false; + pause_requested = false; + + broken_event_handle = NULL; + // we don't set platform name here because it will be inherited + // from winbase_debmod_t + + binary_to_import.base = BADADDR; + binary_to_import.size = 0; + binary_to_import.rebase_to = BADADDR; + + reg_ctx = nullptr; +} + +//-------------------------------------------------------------------------- +#define qoffsetof2(s, f) (qoffsetof(regctx_t, s) + qoffsetof(decltype(regctx_t::s), f)) +#define offset_size(s, f) qoffsetof2(s, f), sizeof(decltype(regctx_t::s)::f) + +//-------------------------------------------------------------------------- +static void clear_ival(const regctx_t * /*ctx*/, regval_t *value, void * /*user_data*/) +{ + value->ival = 0; +} + +//-------------------------------------------------------------------------- +static void nop_write(regctx_t * /*ctx*/, const regval_t * /*value*/, void * /*user_data*/) +{ +} + +//-------------------------------------------------------------------------- +static void ymm_read(const regctx_t *ctx, regval_t *value, void *user_data) +{ + size_t ymm_reg_idx = size_t(user_data); + const uint128 *ptrl = (uint128 *) &ctx->fpu.__fpu_xmm[0]; + const uint128 *ptrh = (uint128 *) &ctx->fpu.__fpu_ymmh[0]; + uint8_t ymm[32]; + *(uint128 *) &ymm[ 0] = ptrl[ymm_reg_idx]; + *(uint128 *) &ymm[16] = ptrh[ymm_reg_idx]; + value->set_bytes(ymm, sizeof(ymm)); +} + +//-------------------------------------------------------------------------- +static void ymm_write(regctx_t *ctx, const regval_t *value, void *user_data) +{ + size_t ymm_reg_idx = size_t(user_data); + const uint8_t *ymm = (const uint8_t *) value->get_data(); + uint128 *ptrl = (uint128 *) &ctx->fpu.__fpu_xmm[0]; + uint128 *ptrh = (uint128 *) &ctx->fpu.__fpu_ymmh[0]; + ptrl[ymm_reg_idx] = *(uint128 *) &ymm[ 0]; + ptrh[ymm_reg_idx] = *(uint128 *) &ymm[16]; +} + +//------------------------------------------------------------------------- +void win32_debmod_t::init_reg_ctx(void) +{ + reg_ctx = new regctx_t(idaregs, *this); + +#ifdef __EA64__ + if ( is64 ) + { + reg_ctx->add_ival(r_rax, offset_size(cpu, __eax)); + reg_ctx->add_ival(r_rbx, offset_size(cpu, __ebx)); + reg_ctx->add_ival(r_rcx, offset_size(cpu, __ecx)); + reg_ctx->add_ival(r_rdx, offset_size(cpu, __edx)); + reg_ctx->add_ival(r_rsi, offset_size(cpu, __esi)); + reg_ctx->add_ival(r_rdi, offset_size(cpu, __edi)); + reg_ctx->add_ival(r_rbp, offset_size(cpu, __ebp)); + sp_idx = reg_ctx->add_ival(r_rsp, offset_size(cpu, __esp)); + pc_idx = reg_ctx->add_ival(r_rip, offset_size(cpu, __eip)); + reg_ctx->add_ival(r_r8, offset_size(cpu, __r8)); + reg_ctx->add_ival(r_r9, offset_size(cpu, __r9)); + reg_ctx->add_ival(r_r10, offset_size(cpu, __r10)); + reg_ctx->add_ival(r_r11, offset_size(cpu, __r11)); + reg_ctx->add_ival(r_r12, offset_size(cpu, __r12)); + reg_ctx->add_ival(r_r13, offset_size(cpu, __r13)); + reg_ctx->add_ival(r_r14, offset_size(cpu, __r14)); + reg_ctx->add_ival(r_r15, offset_size(cpu, __r15)); + } + else +#endif + { + reg_ctx->add_ival(r_eax, offset_size(cpu, __eax)); + reg_ctx->add_ival(r_ebx, offset_size(cpu, __ebx)); + reg_ctx->add_ival(r_ecx, offset_size(cpu, __ecx)); + reg_ctx->add_ival(r_edx, offset_size(cpu, __edx)); + reg_ctx->add_ival(r_esi, offset_size(cpu, __esi)); + reg_ctx->add_ival(r_edi, offset_size(cpu, __edi)); + reg_ctx->add_ival(r_ebp, offset_size(cpu, __ebp)); + sp_idx = reg_ctx->add_ival(r_esp, offset_size(cpu, __esp)); + pc_idx = reg_ctx->add_ival(r_eip, offset_size(cpu, __eip)); + } + sr_idx = reg_ctx->add_ival(x86_registers[R_EFLAGS], offset_size(cpu, __eflags)); + + cs_idx = reg_ctx->add_ival(x86_registers[R_CS], offset_size(cpu, __cs)); + fs_idx = reg_ctx->add_ival(x86_registers[R_FS], offset_size(cpu, __fs)); + gs_idx = reg_ctx->add_ival(x86_registers[R_GS], offset_size(cpu, __gs)); + if ( is64 ) + { + ds_idx = reg_ctx->add_func(x86_registers[R_DS], clear_ival, nop_write); + es_idx = reg_ctx->add_func(x86_registers[R_ES], clear_ival, nop_write); + ss_idx = reg_ctx->add_func(x86_registers[R_SS], clear_ival, nop_write); + } + else + { + ds_idx = reg_ctx->add_ival(x86_registers[R_DS], offset_size(cpu, __ds)); + es_idx = reg_ctx->add_ival(x86_registers[R_ES], offset_size(cpu, __es)); + ss_idx = reg_ctx->add_ival(x86_registers[R_SS], offset_size(cpu, __ss)); + } + + // ST* + size_t offset = qoffsetof2(fpu, __fpu_stmm); + for ( size_t i = R_ST0; i <= R_ST7; i++, offset += 16 ) + reg_ctx->add_fval(x86_registers[i], offset, 10); + + // FPU control + reg_ctx->add_ival(x86_registers[R_CTRL], offset_size(fpu, __fpu_fcw)); + reg_ctx->add_ival(x86_registers[R_STAT], offset_size(fpu, __fpu_fsw)); + reg_ctx->add_ival(x86_registers[R_TAGS], offset_size(fpu, __fpu_ftw)); + + // MMX* + offset = qoffsetof2(fpu, __fpu_stmm); + for ( size_t i = R_MMX0; i <= R_MMX7; i++, offset += 16 ) + reg_ctx->add_data(x86_registers[i], offset, 8); + + // XMM* + offset = qoffsetof2(fpu, __fpu_xmm); + for ( size_t i = R_XMM0; i <= R_LAST_XMM; i++, offset += 16 ) + { +#ifdef __EA64__ + if ( !is64 && i >= R_XMM8 ) + break; +#endif + reg_ctx->add_data(x86_registers[i], offset, 16); + } + reg_ctx->add_ival(x86_registers[R_MXCSR], offset_size(fpu, __fpu_mxcsr)); + + // YMM* + for ( size_t i = R_YMM0; i <= R_LAST_YMM; i++ ) + { +#ifdef __EA64__ + if ( !is64 && i >= R_YMM8 ) + break; +#endif + reg_ctx->add_func(x86_registers[i], ymm_read, ymm_write, (void *) (i - R_YMM0)); + } +} + +//------------------------------------------------------------------------- +void win32_debmod_t::term_reg_ctx(void) +{ + _term_reg_ctx(); +} + +//-------------------------------------------------------------------------- +#ifndef __X86__ +# define FloatSave FltSave // FIXME: use XMM save area! +# define RegisterArea FloatRegisters +# define FPUREG_ENTRY_SIZE 16 +# define XMMREG_PTR ((uchar *)&ctx.Xmm0) +# define XMMREG_MXCSR (ctx.FltSave.MxCsr) +#else +# define FltSave FloatSave +# define XMMREG_PTR ((uchar *)&ctx.ExtendedRegisters[0xA0]) +# define XMMREG_MXCSR (*(uint32 *)&ctx.ExtendedRegisters[0x18]) +# define FPUREG_ENTRY_SIZE 10 +#endif + +#define FPUREG_PTR ((uchar *)ctx.FloatSave.RegisterArea) + +//------------------------------------------------------------------------- +bool win32_debmod_t::get_thread_state( + context_holder_t *out_ctxh, + machine_thread_state_t *out_regs, + machine_float_state_t *out_floats, + thid_t tid, + int clsmask) +{ + thread_info_t *ti = threads.get(tid); + if ( ti == nullptr || !ti->read_context(out_ctxh, clsmask) ) + return false; + CONTEXT &ctx = *out_ctxh->ptr; + memset(out_regs, 0, sizeof(*out_regs)); + memset(out_floats, 0, sizeof(*out_floats)); + + // if ( (clsmask & (X86_RC_GENERAL|X86_RC_SEGMENTS)) != 0 ) + { +#ifdef __X86__ + out_regs->__eax = ctx.Eax; + out_regs->__ebx = ctx.Ebx; + out_regs->__ecx = ctx.Ecx; + out_regs->__edx = ctx.Edx; + out_regs->__edi = ctx.Edi; + out_regs->__esi = ctx.Esi; + out_regs->__ebp = ctx.Ebp; + out_regs->__esp = ctx.Esp; + out_regs->__eip = ctx.Eip; + out_regs->__eflags = ctx.EFlags; + out_regs->__cs = ctx.SegCs; + out_regs->__fs = ctx.SegFs; + out_regs->__gs = ctx.SegGs; + out_regs->__ss = ctx.SegSs; + out_regs->__ds = ctx.SegDs; + out_regs->__es = ctx.SegEs; +#else + out_regs->__eax = ctx.Rax; + out_regs->__ebx = ctx.Rbx; + out_regs->__ecx = ctx.Rcx; + out_regs->__edx = ctx.Rdx; + out_regs->__edi = ctx.Rdi; + out_regs->__esi = ctx.Rsi; + out_regs->__ebp = ctx.Rbp; + out_regs->__esp = ctx.Rsp; + out_regs->__eip = ctx.Rip; + out_regs->__r8 = ctx.R8; + out_regs->__r9 = ctx.R9; + out_regs->__r10 = ctx.R10; + out_regs->__r11 = ctx.R11; + out_regs->__r12 = ctx.R12; + out_regs->__r13 = ctx.R13; + out_regs->__r14 = ctx.R14; + out_regs->__r15 = ctx.R15; + out_regs->__eflags = ctx.EFlags; + out_regs->__cs = ctx.SegCs; + out_regs->__fs = ctx.SegFs; + out_regs->__gs = ctx.SegGs; + out_regs->__ss = ctx.SegSs; + out_regs->__ds = ctx.SegDs; + out_regs->__es = ctx.SegEs; +#endif + } + + if ( (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0 ) + { + if ( (clsmask & X86_RC_FPU) != 0 ) + { + out_floats->__fpu_fcw = ctx.FltSave.ControlWord; + out_floats->__fpu_fsw = ctx.FltSave.StatusWord; + out_floats->__fpu_ftw = ctx.FltSave.TagWord; + } + + const uchar *vptr = (const uchar *) FPUREG_PTR; + for ( int i = 0; i < 8; ++i, vptr += FPUREG_ENTRY_SIZE ) + memcpy(&out_floats->__fpu_stmm[i], vptr, MMX_FPU_REG_DATA_SIZE); + } + + if ( (clsmask & (X86_RC_XMM|X86_RC_YMM)) != 0 ) + { + const uchar *xptr = XMMREG_PTR; + memcpy(&out_floats->__fpu_xmm[0], xptr, (R_MXCSR - R_XMM0) * sizeof(xmm_reg_t)); + out_floats->__fpu_mxcsr = XMMREG_MXCSR; + } + + if ( (clsmask & X86_RC_YMM) != 0 + && context_helper.xstate_helpers_loaded() + && context_helper.pfnSetXStateFeaturesMask(&ctx, XSTATE_MASK_AVX) != FALSE ) + { + DWORD xmm_blob_length = 0; + PM128A Xmm = (PM128A) context_helper.pfnLocateXStateFeature( + &ctx, + XSTATE_LEGACY_SSE, + &xmm_blob_length); + PM128A Ymm = (PM128A) context_helper.pfnLocateXStateFeature( + &ctx, + XSTATE_AVX, + NULL); + CASSERT(sizeof(Ymm[0]) == sizeof(xmm_reg_t)); + const int nxmm_regs = xmm_blob_length / sizeof(Xmm[0]); + const int nymm_regs = qmin(nxmm_regs, 16); + memcpy(&out_floats->__fpu_ymmh[0], Ymm, nymm_regs * sizeof(xmm_reg_t)); + } + + return true; +} + +//------------------------------------------------------------------------- +bool win32_debmod_t::set_thread_state( + const machine_thread_state_t &state, + const machine_float_state_t &floats, + const context_holder_t &ctxh, + thid_t tid, + int clsmask) +{ + thread_info_t *ti = threads.get(tid); + if ( ti == nullptr ) + return false; + + CONTEXT &ctx = *ctxh.ptr; + + // if ( (clsmask & (X86_RC_GENERAL|X86_RC_SEGMENTS)) != 0 ) + { +#ifdef __X86__ + ctx.Eax = state.__eax; + ctx.Ebx = state.__ebx; + ctx.Ecx = state.__ecx; + ctx.Edx = state.__edx; + ctx.Edi = state.__edi; + ctx.Esi = state.__esi; + ctx.Ebp = state.__ebp; + ctx.Esp = state.__esp; + ctx.Eip = state.__eip; + ctx.EFlags = state.__eflags; + ctx.SegCs = state.__cs; + ctx.SegFs = state.__fs; + ctx.SegGs = state.__gs; + ctx.SegSs = state.__ss; + ctx.SegDs = state.__ds; + ctx.SegEs = state.__es; +#else + ctx.Rax = state.__eax; + ctx.Rbx = state.__ebx; + ctx.Rcx = state.__ecx; + ctx.Rdx = state.__edx; + ctx.Rdi = state.__edi; + ctx.Rsi = state.__esi; + ctx.Rbp = state.__ebp; + ctx.Rsp = state.__esp; + ctx.Rip = state.__eip; + ctx.R8 = state.__r8; + ctx.R9 = state.__r9; + ctx.R10 = state.__r10; + ctx.R11 = state.__r11; + ctx.R12 = state.__r12; + ctx.R13 = state.__r13; + ctx.R14 = state.__r14; + ctx.R15 = state.__r15; + ctx.EFlags = state.__eflags; + ctx.SegCs = state.__cs; + ctx.SegFs = state.__fs; + ctx.SegGs = state.__gs; + ctx.SegSs = state.__ss; + ctx.SegDs = state.__ds; + ctx.SegEs = state.__es; +#endif + } + + if ( (clsmask & (X86_RC_FPU|X86_RC_MMX)) != 0 ) + { + if ( (clsmask & X86_RC_FPU) != 0 ) + { + ctx.FloatSave.ControlWord = floats.__fpu_fcw; + ctx.FloatSave.StatusWord = floats.__fpu_fsw; + ctx.FloatSave.TagWord = floats.__fpu_ftw; + } + + uchar *vptr = (uchar *) FPUREG_PTR; + for ( int i = 0; i < 8; ++i, vptr += FPUREG_ENTRY_SIZE ) + memcpy(vptr, &floats.__fpu_stmm[i], MMX_FPU_REG_DATA_SIZE); + } + + if ( (clsmask & (X86_RC_XMM|X86_RC_YMM)) != 0 ) + { + uchar *xptr = XMMREG_PTR; + memcpy(xptr, &floats.__fpu_xmm[0], (R_MXCSR - R_XMM0) * sizeof(xmm_reg_t)); + XMMREG_MXCSR = floats.__fpu_mxcsr; + } + + if ( (clsmask & X86_RC_YMM) != 0 + && context_helper.xstate_helpers_loaded() + && context_helper.pfnSetXStateFeaturesMask(&ctx, XSTATE_MASK_AVX) != FALSE ) + { + DWORD xmm_blob_length = 0; + PM128A Xmm = (PM128A) context_helper.pfnLocateXStateFeature( + &ctx, + XSTATE_LEGACY_SSE, + &xmm_blob_length); + PM128A Ymm = (PM128A) context_helper.pfnLocateXStateFeature( + &ctx, + XSTATE_AVX, + NULL); + CASSERT(sizeof(Ymm[0]) == sizeof(xmm_reg_t)); + const int nxmm_regs = xmm_blob_length / sizeof(Xmm[0]); + const int nymm_regs = qmin(nxmm_regs, 16); + memcpy(Ymm, &floats.__fpu_ymmh[0], nymm_regs * sizeof(xmm_reg_t)); + } + + return ti->write_context(clsmask, ctx); +} + +//---------------------------------------------------------------------- +// return the handle associated with a thread id from the threads list +HANDLE win32_debmod_t::get_thread_handle(thid_t tid) +{ + thread_info_t *tinfo = threads.get(tid); + return tinfo == NULL ? INVALID_HANDLE_VALUE : tinfo->hThread; +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::refresh_hwbpts(void) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + set_hwbpts(p->second.hThread); + return true; +} + +//-------------------------------------------------------------------------- +// 1-ok, 0-failed +int idaapi win32_debmod_t::dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) +{ + check_thread(false); + if ( orig_bytes != NULL ) + { + bool ok = false; + bpts.erase(ea); + suspend_all_threads(); + // write the old value only if our bpt is still present + if ( !has_bpt_at(ea) ) + { + if ( !exiting ) + dmsg("%a: breakpoint vanished from memory\n", ea); + ok = true; + } + else + { + ok = _write_memory(ea, orig_bytes, len) == len; + } + resume_all_threads(); + return ok; + } + + // try to delete a page bpt first + if ( del_page_bpt(ea, type) ) + return true; + return del_hwbpt(ea, type); +} + +//-------------------------------------------------------------------------- +ssize_t win32_debmod_t::_write_memory(eanat_t ea, const void *buffer, size_t size, bool suspend) +{ + if ( !may_write(ea) ) + return -1; + return access_memory(ea, (void *)buffer, size, true, suspend); +} + +//-------------------------------------------------------------------------- +void idaapi win32_debmod_t::dbg_term(void) +{ + check_thread(true); + cleanup_hwbpts(); + cleanup(); + for ( size_t i = 0; i < pdb_remote_sessions.size(); ++i ) + close_pdb_remote_session(pdb_remote_sessions[i]); + inherited::dbg_term(); +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::has_bpt_at(ea_t ea) +{ + uchar bytes[8]; + int size = bpt_code.size(); + return _read_memory(ea, bytes, size) == size + && memcmp(bytes, bpt_code.begin(), size) == 0; +} + +//-------------------------------------------------------------------------- +// 2-ok(pagebpt), 1-ok, 0-failed, -2-read failed +int idaapi win32_debmod_t::dbg_add_bpt( + bytevec_t *orig_bytes, + bpttype_t type, + ea_t ea, + int len) +{ + check_thread(false); + if ( type == BPT_SOFT ) + { + if ( len <= 0 ) + len = bpt_code.size(); + if ( orig_bytes != NULL && read_bpt_orgbytes(orig_bytes, ea, len) < 0 ) + return -2; + debmod_bpt_t dbpt(ea, len); + if ( !dbg_read_memory(ea, dbpt.saved, len, NULL) ) + return -2; + int size = bpt_code.size(); + if ( dbg_write_memory(ea, bpt_code.begin(), size, NULL) != size ) + return 0; + bpts[ea] = dbpt; + return 1; + } + + // try, first, to add a real hw breakpoint + // if it fails, add a memory range type bpt + // reason: the user may try to insert a 5th + // correct hw bpt, however, it isn't possible + // so, instead, we add a page breakpoint + int ret = 0; + if ( check_x86_hwbpt(type, ea, len) == BPT_OK ) + ret = add_hwbpt(type, ea, len); + + if ( !ret ) + ret = dbg_add_page_bpt(type, ea, len); + return ret; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_get_memory_info(meminfo_vec_t &ranges, qstring * /*errbuf*/) +{ + check_thread(false); + NODISTURB_ASSERT(in_event != NULL); + + images.clear(); + thread_ranges.clear(); + class_ranges.clear(); + for ( threads_t::iterator t=threads.begin(); t != threads.end(); ++t ) + add_thread_ranges(t->first, thread_ranges, class_ranges); + + if ( process_handle != INVALID_HANDLE_VALUE ) + { + for ( ea_t ea=0; ea != BADADDR; ) + { + memory_info_t meminf; + ea = get_region_info(ea, &meminf); + if ( ea != BADADDR && meminf.start_ea != BADADDR ) + ranges.push_back(meminf); + } + enable_page_bpts(true); + } + + if ( same_as_oldmemcfg(ranges) ) + return DRC_NOCHG; + + save_oldmemcfg(ranges); + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_thread_suspend(thid_t tid) +{ + check_thread(false); + NODISTURB_ASSERT(in_event != NULL); + int count = SuspendThread(get_thread_handle(tid)); + if ( count == -1 ) + deberr("SuspendThread(%08X)", tid); + + if ( debug_debugger ) + debdeb("SuspendThread(%08X) -> %d\n", tid, count); + + return count != -1 ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_thread_continue(thid_t tid) +{ + check_thread(false); + NODISTURB_ASSERT(in_event != NULL); + int count = ResumeThread(get_thread_handle(tid)); + if ( count == -1 ) + deberr("ResumeThread(%08X)", tid); + + if ( debug_debugger ) + debdeb("ResumeThread(%08X) -> %d\n", tid, count); + + return count != -1 ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +bool thread_info_t::read_context( + context_holder_t *out, + int clsmask) +{ + // if ( (flags & clsmask) == clsmask ) + // return true; + + int ctxflags = calc_ctxflags(clsmask); + if ( !debmod->context_helper.create_context(out, &ctxflags) ) + return false; + + PCONTEXT ctx = out->ptr; +#ifndef __X86__ + if ( is_wow64() && _Wow64GetThreadContext != NULL ) + { + WOW64_CONTEXT wow64ctx; + wow64ctx.ContextFlags = ctxflags_to_wow64(ctxflags); + if ( !_Wow64GetThreadContext(hThread, &wow64ctx) ) + return false; + context_holder_t xstate_ctx; + if ( (clsmask & X86_RC_YMM) != 0 ) + { + int xstate_ctxflags = CONTEXT_XSTATE; + if ( !debmod->context_helper.create_context(&xstate_ctx, &xstate_ctxflags) ) + return false; + if ( !GetThreadContext(hThread, xstate_ctx.ptr) ) + return false; + } + WOW64_CONTEXT_to_CONTEXT( + ctx, + wow64ctx, + clsmask, + xstate_ctx.ptr, + debmod->context_helper); + } + else +#endif + { + ctx->ContextFlags = ctxflags; + if ( !GetThreadContext(hThread, ctx) ) + return false; + } + return true; +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be const ref +bool thread_info_t::write_context(int clsmask, CONTEXT &ctx) +{ +#ifndef __X86__ + if ( is_wow64() && _Wow64SetThreadContext != NULL ) + { + context_holder_t xstate_ctx; + if ( (clsmask & X86_RC_YMM) != 0 ) + { + int xstate_ctxflags = CONTEXT_XSTATE; + if ( !debmod->context_helper.create_context(&xstate_ctx, &xstate_ctxflags) ) + return false; + } + WOW64_CONTEXT wow64ctx; + CONTEXT_to_WOW64_CONTEXT( + &wow64ctx, + ctx, + xstate_ctx.ptr, + clsmask, + debmod->context_helper); + if ( xstate_ctx.ptr != NULL ) + { + if ( SetThreadContext(hThread, xstate_ctx.ptr) == 0 ) + return false; + } + if ( _Wow64SetThreadContext(hThread, &wow64ctx) == 0 ) + return false; + return true; + } +#else + qnotused(clsmask); +#endif + return SetThreadContext(hThread, &ctx) != 0; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_prepare_to_pause_process(qstring * /*errbuf*/) +{ + check_thread(false); + bool ok = true; + win_tool_help_t *wth = get_tool_help(); + if ( wth->use_debug_break_process() ) // only possible on XP/2K3 or higher + { + ok = wth->debug_break_process(process_handle); + if ( !stop_at_ntdll_bpts ) + expecting_debug_break = ok; + } + else if ( threads.empty() ) + { + ok = false; + } + else + { + suspend_all_threads(); + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + thread_info_t &ti = p->second; + context_holder_t ctxh; + if ( !ti.read_context(&ctxh, X86_RC_GENERAL) ) + { + ok = false; + continue; + } + // we have a problem: it is possible that eip points past a temporary breakpoint + // that will be removed and replaced by the original instruction opcode. + // if we set a new breakpoint now, it will be at the second byte of the + // instruction and will lead to a crash. + eanat_t ip = ctxh.ptr->Eip; + if ( bpts.find(ip-bpt_code.size()) != bpts.end() ) + continue; // yes, there is a breakpoint just before us. it was just hit + // but hopefully not processed yet + if ( !set_thread_bpt(ti, ip) ) + ok = false; + } + // send WM_NULL to the main thread, hopefully it will wake up the application + thread_info_t &ti = threads.begin()->second; + PostThreadMessageA(ti.tid, WM_NULL, 0, 0); + resume_all_threads(); + } + pause_requested = true; + return ok ? DRC_OK : DRC_FAILED; +} + +//---------------------------------------------------------------------- +// return the name associated with an existing image in 'images' list +// containing a particular range +static const char *get_range_name(const images_t &images, const range_t *range) +{ + for ( images_t::const_iterator p=images.begin(); p != images.end(); ++p ) + { + const image_info_t &img = p->second; + ea_t ea1 = (ea_t)img.base; + ea_t ea2 = ea1 + img.imagesize; + range_t b = range_t(ea1, ea2); + b.intersect(*range); + if ( !b.empty() ) + return img.name.c_str(); + } + return NULL; +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::restore_original_bytes(ea_t ea, bool really_restore) +{ + bpt_info_t::iterator p = thread_bpts.find(ea); + QASSERT(1488, p != thread_bpts.end()); + if ( --p->second.count == 0 ) + { + uchar *obytes = p->second.orig_bytes; + if ( really_restore ) + { + int size = bpt_code.size(); + if ( _write_memory(ea, obytes, size) != size ) + INTERR(1489); + } + thread_bpts.erase(p); + } +} + +//-------------------------------------------------------------------------- +// returns: 0-error,1-ok,2-already had bpt, just increased the counter +int win32_debmod_t::save_original_bytes(ea_t ea) +{ + bpt_info_t::iterator p = thread_bpts.find(ea); + if ( p == thread_bpts.end() ) + { + internal_bpt_info_t ibi; + ibi.count = 1; + int size = bpt_code.size(); + if ( _read_memory(ea, ibi.orig_bytes, size) != size ) + return 0; + thread_bpts.insert(std::make_pair(ea, ibi)); + return 1; + } + else + { + p->second.count++; + return 2; + } +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::del_thread_bpt(thread_info_t &ti, ea_t ea) +{ + if ( ti.bpt_ea == BADADDR ) + return false; + + if ( ti.bpt_ea == ea ) + { + context_holder_t ctxh; + if ( !ti.read_context(&ctxh, X86_RC_GENERAL) ) + return false; + ctxh.ptr->Eip = ti.bpt_ea; // reset EIP + ctxh.ptr->ContextFlags = CONTEXT_CONTROL; + if ( !ti.write_context(X86_RC_GENERAL, *ctxh.ptr) ) + deberr("del_thread_bpt: SetThreadContext"); + } + + // restore old insn if necessary + restore_original_bytes(ti.bpt_ea); + ti.bpt_ea = BADADDR; + return true; +} + +//-------------------------------------------------------------------------- +// delete all thread breakpoints +// returns true if a breakpoint at which we stopped was removed +bool win32_debmod_t::del_thread_bpts(ea_t ea) +{ + bool found = false; + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + found |= del_thread_bpt(p->second, ea); + return found; +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::set_thread_bpt(thread_info_t &ti, ea_t ea) +{ + // delete old thread bpt if any existed before + del_thread_bpt(ti, BADADDR); + + ti.bpt_ea = ea; + int code = save_original_bytes(ti.bpt_ea); + if ( code ) + { + if ( code == 2 ) // already have a bpt? + return true; // yes, then everything ok + int size = bpt_code.size(); + code = _write_memory(ti.bpt_ea, bpt_code.begin(), size); + if ( code > 0 ) + { + if ( code == size ) + return true; + // failed to write, forget the original byte + restore_original_bytes(ti.bpt_ea, false); + } + } + debdeb("%a: set_thread_bpt() failed to pause thread %d\n", ti.bpt_ea, ti.tid); + ti.bpt_ea = BADADDR; + return false; +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::add_thread(const CREATE_THREAD_DEBUG_INFO &thr_info, thid_t tid) +{ + wow64_state_t w = check_wow64_process(); + thread_info_t ti(this, thr_info, tid, w); + threads.insert(std::make_pair(tid, ti)); +} + +//-------------------------------------------------------------------------- +gdecode_t win32_debmod_t::get_debug_event(debug_event_t *event, int timeout_ms) +{ + check_thread(false); + if ( events.retrieve(event) ) + return events.empty() ? GDE_ONE_EVENT : GDE_MANY_EVENTS; + + DEBUG_EVENT DebugEvent; + // we have to wait infinitely if we just try to attach to a running process + if ( attach_status == as_attaching ) + timeout_ms = INFINITE; + if ( !WaitForDebugEvent(&DebugEvent, timeout_ms) ) + { + // no event occurred + if ( attach_status == as_detaching ) // if we were requested to detach, + { // we generate a fake detach event + event->set_eid(PROCESS_DETACHED); + return GDE_ONE_EVENT; + } + // else, we don't return an event + return GDE_NO_EVENT; + } + + if ( attach_status == as_attaching ) + { + if ( DebugEvent.dwDebugEventCode != CREATE_PROCESS_DEBUG_EVENT ) + return GDE_ERROR; + // fill in starting information for the just attached process (we couldn't do it from CreateProcess() return values !) + process_path = ""; + pid = DebugEvent.dwProcessId; + attach_status = as_breakpoint; + } + + if ( debug_debugger ) + show_debug_event(DebugEvent); + + // ignore events coming from other child processes + if ( DebugEvent.dwProcessId != pid ) + { + debdeb("ignore: pid %x != %x\n", DebugEvent.dwProcessId, pid); + bool handled = DebugEvent.dwDebugEventCode == EXCEPTION_DEBUG_EVENT + && (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT + || DebugEvent.u.Exception.ExceptionRecord.ExceptionCode == STATUS_WX86_BREAKPOINT); + + if ( !ContinueDebugEvent(DebugEvent.dwProcessId, + DebugEvent.dwThreadId, + handled ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED) ) + { + deberr("ContinueDebugEvent"); + } + return GDE_NO_EVENT; + } + + event->pid = DebugEvent.dwProcessId; + event->tid = DebugEvent.dwThreadId; + event->handled = true; + + gdecode_t gdecode = GDE_ONE_EVENT; + switch ( DebugEvent.dwDebugEventCode ) + { + case EXCEPTION_DEBUG_EVENT: + { + EXCEPTION_RECORD &er = DebugEvent.u.Exception.ExceptionRecord; + // remove temporary breakpoints if any + bool was_thread_bpt = del_thread_bpts(EA_T(er.ExceptionAddress)); + bool firsttime = DebugEvent.u.Exception.dwFirstChance != 0; + gdecode = handle_exception(event, er, was_thread_bpt, firsttime); + } + break; + + case CREATE_THREAD_DEBUG_EVENT: + { + // add this thread to our list + add_thread(DebugEvent.u.CreateThread, event->tid); + event->set_info(THREAD_STARTED); + event->ea = EA_T(DebugEvent.u.CreateThread.lpStartAddress); + // set hardware breakpoints if any + set_hwbpts(DebugEvent.u.CreateThread.hThread); + } + break; + + case CREATE_PROCESS_DEBUG_EVENT: + { + // save information for later + cpdi = DebugEvent.u.CreateProcessInfo; + cpdi.lpBaseOfImage = correct_exe_image_base(cpdi.lpBaseOfImage); + if ( process_handle != INVALID_HANDLE_VALUE && process_handle != cpdi.hProcess ) + myCloseHandle(process_handle); // already have an open handle + process_handle = cpdi.hProcess; + + create_start_event(event); + curproc.insert(std::make_pair(event->modinfo().base, image_info_t(this, event->modinfo()))); + + // add record about the main thread into the list + CREATE_THREAD_DEBUG_INFO ctdi; + ctdi.hThread = cpdi.hThread; + ctdi.lpThreadLocalBase = cpdi.lpThreadLocalBase; + ctdi.lpStartAddress = cpdi.lpStartAddress; + add_thread(ctdi, DebugEvent.dwThreadId); + + // set hardware breakpoints if any + set_hwbpts(cpdi.hThread); + + // test hardware breakpoints: + // add_hwbpt(HWBPT_WRITE, 0x0012FF68, 4); + if ( highdlls.empty() && winver.is_DW32() ) // dw32 specific + { + HINSTANCE h = GetModuleHandle(kernel32_dll); + eanat_t addr = eanat_t(h); + uint32 size = calc_imagesize(addr); + highdlls.add(addr, size); + } + break; + } + + case EXIT_THREAD_DEBUG_EVENT: + { + threads.erase(event->tid); + event->set_exit_code(THREAD_EXITED, DebugEvent.u.ExitThread.dwExitCode); + // invalidate corresponding handles + HANDLE h = get_thread_handle(event->tid); + if ( h == thread_handle ) + thread_handle = INVALID_HANDLE_VALUE; + if ( h == cpdi.hThread ) + cpdi.hThread = INVALID_HANDLE_VALUE; + break; + } + + case EXIT_PROCESS_DEBUG_EVENT: + event->set_exit_code(PROCESS_EXITED, DebugEvent.u.ExitProcess.dwExitCode); + exiting = true; + break; + + case LOAD_DLL_DEBUG_EVENT: + { + const LOAD_DLL_DEBUG_INFO &dil = DebugEvent.u.LoadDll; + eanat_t addr = eanat_t(dil.lpBaseOfDll); + modinfo_t &mi_ll = event->set_modinfo(LIB_LOADED); + event->ea = addr; + mi_ll.base = event->ea; + mi_ll.rebase_to = BADADDR; // this must be determined locally - see common_local.cpp + + char full_name[MAXSTR]; + full_name[0] = '\0'; + bool ok = get_filename_for(full_name, + sizeof(full_name), + eanat_t(dil.lpImageName), + dil.fUnicode != 0, + addr); + // Win 7 may send a bogus DLL load event for the main module + // ignore event if this module has already been mapped + if ( !ok || module_present(full_name) ) + { + debdeb("%p: bogus DLL load event, skippping\n", addr); + goto SILENTLY_RESUME; + } + mi_ll.name = full_name; + uint32 size = calc_imagesize(addr); + mi_ll.size = size; + + // does the address fit into ea_t? + HANDLE ntdll_handle = dil.hFile; + if ( highdlls.add_high_module(addr, size, ntdll_handle) ) + { + debdeb("%p: 64bit DLL loaded into high addresses has been detected\n", + addr); + goto SILENTLY_RESUME; + } + + // we defer the import of the dll until the moment when ida stops + // at a debug event. we do so to avoid unnecessary imports because + // the dll might get unloaded before ida stops. + image_info_t di(this, DebugEvent.u.LoadDll, size, full_name); + add_dll(di); + // determine the attach breakpoint if needed + size_t max_ntdlls = check_wow64_process() == WOW64_YES ? 2 : 1; + if ( highdlls.count_ntdlls() < max_ntdlls ) + { + if ( is_ntdll_name(full_name) ) + highdlls.add_ntdll(addr, size); + if ( attach_status == as_none && !stop_at_ntdll_bpts ) + expecting_debug_break = highdlls.count_ntdlls(); + } + break; + } + +SILENTLY_RESUME: + // do not report this event to ida + event->handled = true; + dbg_continue_after_event(event); + return GDE_NO_EVENT; + + case UNLOAD_DLL_DEBUG_EVENT: + event->set_info(LIB_UNLOADED); + { + eanat_t addr = eanat_t(DebugEvent.u.UnloadDll.lpBaseOfDll); + range_t range(addr, addr+MEMORY_PAGE_SIZE); // we assume DLL image is at least a PAGE size + const char *name = get_range_name(dlls, &range); + if ( name != NULL ) + event->info() = name; + else + event->info().clear(); + + // remove ntdll from the list + HANDLE ntdll_handle; + if ( highdlls.del_high_module(&ntdll_handle, addr) ) + { + myCloseHandle(ntdll_handle); + goto SILENTLY_RESUME; + } + + // close the associated DLL handle + images_t::iterator p = dlls.find(addr); + if ( p != dlls.end() ) + { + myCloseHandle(p->second.dll_info.hFile); + // Remove it from the list of dlls to import + // (in the case it was never imported) + dlls_to_import.erase(p->first); + dlls.erase(p); + } + else + { + debdeb("Could not find dll to unload (base=%a)\n", EA_T(DebugEvent.u.UnloadDll.lpBaseOfDll)); + } + } + break; + + case OUTPUT_DEBUG_STRING_EVENT: + { + char buf[MAXSTR]; + get_debug_string(DebugEvent, buf, sizeof(buf)); + event->set_info(INFORMATION) = buf; + } + break; + + case RIP_EVENT: + debdeb("RIP_EVENT (system debugging error)"); + break; + + default: + debdeb("UNKNOWN_EVENT %d", DebugEvent.dwDebugEventCode); + event->handled = false; // don't handle it + break; + } + + if ( gdecode > GDE_NO_EVENT && attach_status == as_breakpoint && event->eid() == EXCEPTION ) + { // exception while attaching. apparently things went wrong + // pretend that we attached successfully + events.enqueue(*event, IN_BACK); + create_attach_event(event, true); + attach_status = as_none; + } + return gdecode; +} + +//-------------------------------------------------------------------------- +gdecode_t idaapi win32_debmod_t::dbg_get_debug_event(debug_event_t *event, int timeout_ms) +{ + check_thread(false); + gdecode_t gdecode = get_debug_event(event, timeout_ms); + if ( gdecode >= GDE_ONE_EVENT ) + { + last_event = *event; + in_event = &last_event; + pause_requested = false; + } + return gdecode; +} + + +//-------------------------------------------------------------------------- +bool win32_debmod_t::get_debug_string(const DEBUG_EVENT &ev, char *buf, size_t bufsize) +{ + buf[0] = '\0'; + size_t nullsize = ev.u.DebugString.fUnicode ? sizeof(wchar_t) : 1; + size_t msize = qmin(ev.u.DebugString.nDebugStringLength, bufsize-nullsize); + ea_t ea = EA_T(ev.u.DebugString.lpDebugStringData); + ssize_t rsize = _read_memory(ea, buf, msize); + if ( rsize == msize ) + { + buf[rsize] = '\0'; + if ( ev.u.DebugString.fUnicode ) + { + *(wchar_t*)(buf + rsize) = 0; + utf16_to_utf8(buf, bufsize, (LPCWSTR)buf); + } + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::cleanup() +{ + myCloseHandle(redirin_handle); + myCloseHandle(redirout_handle); + myCloseHandle(thread_handle); + myCloseHandle(process_handle); + myCloseHandle(cpdi.hFile); + + // Close handles of remaining DLLs + for ( images_t::iterator p=dlls.begin(); p != dlls.end(); ++p ) + myCloseHandle(p->second.dll_info.hFile); + + pid = -1; + highdlls.clear(); + stop_at_ntdll_bpts = qgetenv("IDA_SYSTEMBREAKPOINT"); + expecting_debug_break = 0; + in_event = NULL; + memset(&cpdi, 0, sizeof(cpdi)); + cpdi.hFile = INVALID_HANDLE_VALUE; + cpdi.hProcess = INVALID_HANDLE_VALUE; + cpdi.hThread = INVALID_HANDLE_VALUE; + attach_status = as_none; + attach_evid = INVALID_HANDLE_VALUE; + + old_ranges.clear(); + threads.clear(); + thread_bpts.clear(); + bpts.clear(); + curproc.clear(); + dlls.clear(); + dlls_to_import.clear(); + images.clear(); + thread_ranges.clear(); + class_ranges.clear(); + context_helper.clear(); + inherited::cleanup(); +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::_term_reg_ctx(void) +{ + if ( reg_ctx != nullptr ) + { + delete reg_ctx; + idaregs.clear(); + } + reg_ctx = nullptr; +} + +#define DRVBUFSIZE 512 + +//-------------------------------------------------------------------------- +// Translate path with device name to drive letters. +// e.g. \Device\HarddiskVolume4\Windows\System32\ntdll.dll -> C:\Windows\System32\ntdll.dll +static void translate_nt_path(qstring *out, LPCWSTR pszFilename) +{ + WCHAR szTemp[DRVBUFSIZE]; + + // get a list of all drive letters + if ( GetLogicalDriveStringsW(qnumber(szTemp) - 1, szTemp) ) + { + WCHAR szName[MAX_PATH]; + WCHAR szDrive[3] = L" :"; + BOOL bFound = FALSE; + WCHAR *p = szTemp; + + do + { + // Copy the drive letter to the template string + *szDrive = *p; + + // Look up device name for this drive + DWORD uNameLen = QueryDosDeviceW(szDrive, szName, qnumber(szName) - 1); + if ( uNameLen != 0 ) + { + // for some reason return value is 2 chars longer, so get the actual length + uNameLen = wcslen(szName); + // do we have a match at the start of filename? + bFound = _wcsnicmp(pszFilename, szName, uNameLen) == 0 + && pszFilename[uNameLen] == L'\\'; + + if ( bFound ) + { + // Reconstruct filename + // by replacing device path with DOS path (drive) + qstring path; + utf16_utf8(out, szDrive); + utf16_utf8(&path, pszFilename + uNameLen); + out->append(path); + return; + } + } + + // Go to the next NULL character. + while ( *p++ ) + ; + } + while ( !bFound && *p ); // end of string + } +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::get_filename_for( + char *buf, + size_t bufsize, + eanat_t image_name_ea, + bool use_unicode, + eanat_t image_base) +{ + buf[0] = '\0'; + // if we have address of file name in the process image from the debug API, try to use it + // remark: depending on the OS, NTDLL.DLL can return an empty string or only the DLL name! + if ( image_name_ea != 0 ) + { + if ( get_filename_from_process(image_name_ea, use_unicode, buf, bufsize) ) + return true; + } + + // various fallbacks + // first try GetMappedFileName + if ( _GetMappedFileName != NULL ) + { + wchar16_t tbuf[MAXSTR]; + HMODULE hmod = (HMODULE)(size_t)image_base; + if ( _GetMappedFileName(process_handle, hmod, tbuf, qnumber(tbuf)) ) + { + qstring tmp; + translate_nt_path(&tmp, tbuf); + qstrncpy(buf, tmp.c_str(), bufsize); + return true; + } + } + + // then try GetModuleFileNameEx + if ( _GetModuleFileNameEx != NULL ) + { + wchar16_t tbuf[MAXSTR]; + HMODULE hmod = (HMODULE)(size_t)image_base; + if ( _GetModuleFileNameEx(process_handle, hmod, tbuf, qnumber(tbuf)) ) + { + qstring tmp; + utf16_utf8(&tmp, tbuf); + qstrncpy(buf, tmp.c_str(), bufsize); + return true; + } + } + + // last: we try to get DLL name by looking at the export name from + // the export directory in PE image in debugged process. + // this is the least reliable way since this string may not match the actual dll filename + get_pe_export_name_from_process(image_base, buf, bufsize); + + // for dlls without path, try to find it + find_full_path(buf, bufsize, process_path.c_str()); + + // convert possible short path to long path + qffblk64_t fb; + if ( qfindfirst(buf, &fb, 0) == 0 ) + { + char *fptr = qbasename(buf); + qstrncpy(fptr, fb.ff_name, bufsize-(fptr-buf)); + } + return buf[0] != '\0'; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_detach_process() +{ + check_thread(false); + if ( in_event != NULL ) + dbg_continue_after_event(in_event); + BOOL ret = get_tool_help()->debug_detach_process(pid); + if ( ret ) + { + attach_status = as_detaching; + exiting = true; + } + return ret ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +void idaapi win32_debmod_t::dbg_set_debugging(bool _debug_debugger) +{ + debug_debugger = _debug_debugger; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_init(uint32_t *flags2, qstring * /*errbuf*/) +{ + check_thread(true); + + cleanup(); + cleanup_hwbpts(); + + if ( flags2 != nullptr ) + *flags2 = g_code; + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +image_info_t::image_info_t(win32_debmod_t *ses) + : sess(ses), base(BADADDR), imagesize(0) +{ + memset(&dll_info, 0, sizeof(dll_info)); +} + +image_info_t::image_info_t( + win32_debmod_t *ses, + ea_t _base, + uint32 _imagesize, + const qstring &_name) + : sess(ses), base(_base), imagesize(_imagesize), name(_name) +{ + memset(&dll_info, 0, sizeof(dll_info)); +} + +image_info_t::image_info_t( + win32_debmod_t *ses, + const LOAD_DLL_DEBUG_INFO &i, + uint32 _imagesize, + const char *_name) + : sess(ses), name(_name), dll_info(i) +{ + base = EA_T(i.lpBaseOfDll); + imagesize = _imagesize; +} + +image_info_t::image_info_t(win32_debmod_t *ses, const modinfo_t &m) + : sess(ses), base(m.base), imagesize(m.size), name(m.name) +{ + memset(&dll_info, 0, sizeof(dll_info)); +} + +//-------------------------------------------------------------------------- +// get (path+)name from debugged process +// lpFileName - pointer to pointer to the file name +// use_unicode - true if the filename is in unicode +bool win32_debmod_t::get_filename_from_process( + eanat_t name_ea, + bool use_unicode, + char *buf, + size_t bufsize) +{ + buf[0] = '\0'; + if ( name_ea == 0 ) + return false; + eanat_t dll_addr; + if ( _read_memory(name_ea, &dll_addr, sizeof(dll_addr)) != sizeof(dll_addr) ) + return false; + if ( dll_addr == NULL ) + return false; + name_ea = dll_addr; + if ( _read_memory(name_ea, buf, bufsize) != bufsize ) + return false; + if ( use_unicode ) + utf16_to_utf8(buf, bufsize, (LPCWSTR)buf); + return true; +} + +//-------------------------------------------------------------------------- +ea_t win32_debmod_t::get_region_info(ea_t ea, memory_info_t *mi) +{ + // okay to keep static, they won't change between clients + static DWORD_PTR totalVirtual = 0; + static DWORD granularity = 0; + + if ( totalVirtual == 0 ) + { + SYSTEM_INFO si; + GetSystemInfo(&si); + granularity = si.dwAllocationGranularity; + totalVirtual = (DWORD_PTR)si.lpMaximumApplicationAddress; + } + + void *addr = (void *)(size_t)ea; + MEMORY_BASIC_INFORMATION meminfo; + while ( !VirtualQueryEx(process_handle, // handle of process + addr, // address of region + &meminfo, // address of information buffer + sizeof(meminfo)) ) // size of buffer + { + // On Windows CE VirtualQueryEx can fail when called with addr == 0, + // so try to call it again with the next page (and end loop after 2d + // iteration to prevent scanning of huge number of pages) + // It's possible VirtualQueryEx fails on Windows CE not only for zero + // address: perhaps we shouldn't limit the number of iterations and return + // to using of a separate variable 'first' (as in win32_debmod.cpp#34) + if ( ea != 0 || ea >= totalVirtual ) + return BADADDR; + // try to find next valid page + ea += granularity; + addr = (void *)(size_t)ea; + } + + eanat_t startea = (eanat_t)meminfo.BaseAddress; + eanat_t endea = startea + meminfo.RegionSize; + if ( endea <= startea // overflow/empty? +#if !defined(__X86__) && !defined(__EA64__) + || endea >= BADADDR // crossed 4GB boundary +#endif + ) + { + if ( endea == startea ) + { + // ignore empty sections ... + mi->start_ea = BADADDR; + mi->end_ea = BADADDR; + return endea + 1; + } + // signal end of enumeration + endea = BADADDR; + } + +// debdeb("VirtualQueryEx(%a): base = %a, end = %a, protect=0x%x, allocprotect=0x%x, state=0x%x\n", ea, startea, endea, meminfo.Protect, meminfo.AllocationProtect, meminfo.State); + + // hide the page bpts in this memory region from ida + uint32 prot = meminfo.Protect; + if ( mask_page_bpts(startea, endea, &prot) ) + { + debdeb(" masked protect=0x%x\n", prot); + meminfo.Protect = prot; + } + + if ( (meminfo.State & (MEM_FREE|MEM_RESERVE)) == MEM_FREE // if the range isn't interesting for/accessible by IDA + || (meminfo.Protect & PAGE_NOACCESS) != 0 ) + { // we simply return an invalid range, and a pointer to the next (eventual) range + mi->start_ea = BADADDR; + mi->end_ea = BADADDR; + return endea; + } + + mi->start_ea = startea; + mi->end_ea = endea; +#ifdef __EA64__ + // we may be running a 32bit process in wow64 with ida64 + mi->bitness = check_wow64_process() > 0 ? 1 : 2; +#else + mi->bitness = 1; // 32bit +#endif + + // convert Windows protection modes to IDA protection modes + mi->perm = win_prot_to_ida_perm(meminfo.Protect); + + // try to associate a segment name to the memory range + const char *ptr; + if ( (ptr=get_range_name(curproc, mi)) != NULL // first try with the current process + || (ptr=get_range_name(dlls, mi)) != NULL // then try in DLLs + || (ptr=get_range_name(images, mi)) != NULL // then try in previous images ranges + || (ptr=get_range_name(thread_ranges, mi)) != NULL ) // and finally in thread ranges + { + // return the filename without the file path + mi->name = qbasename(ptr); + } + else + { + char buf[MAXSTR]; + buf[0] = '\0'; + // check for a mapped filename + get_filename_for(buf, sizeof(buf), 0, false, mi->start_ea); + if ( buf[0] != '\0' ) + { + mi->name = qbasename(buf); + } + // if we found nothing, check if the segment is a PE file header, + // and we try to locate a name in it + else if ( get_pe_export_name_from_process(mi->start_ea, buf, sizeof(buf)) ) + { // we insert it in the image ranges list + uint32 size = calc_imagesize(mi->start_ea); + image_info_t ii(this, mi->start_ea, size, buf); + images.insert(std::make_pair(ii.base, ii)); + mi->name = buf; + } + } + + // try to associate a segment class name to the memory range + mi->sclass = get_range_name(class_ranges, mi); + return endea; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_attach_process(pid_t _pid, int event_id, int /*flags*/, qstring * /*errbuf*/) +{ + check_thread(false); +#ifndef __EA64__ + int addrsize = get_process_addrsize(_pid); + if ( addrsize > 4 ) + { + dwarning("AUTOHIDE NONE\nPlease use ida64 to debug 64-bit applications"); + SetLastError(ERROR_NOT_SUPPORTED); + return DRC_FAILED; + } +#endif + if ( !DebugActiveProcess(_pid) ) + { + deberr("DebugActiveProcess %08lX", _pid); + return DRC_FAILED; + } + + if ( !handle_process_start(_pid) ) + return DRC_FAILED; + + attach_status = as_attaching; + attach_evid = (HANDLE)(INT_PTR)(event_id); + exiting = false; + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_start_process( + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + qstring * /*errbuf*/) +{ + check_thread(false); + // input file specified in the database does not exist + if ( input_path[0] != '\0' && !qfileexist(input_path) ) + { + dwarning("AUTOHIDE NONE\nInput file is missing: %s", input_path); + return DRC_NOFILE; + } + + input_file_path = input_path; + is_dll = (flags & DBG_PROC_IS_DLL) != 0; + + char fullpath[QMAXPATH]; + if ( !qfileexist(path) ) + { + if ( qisabspath(path) || !search_path(fullpath, sizeof(fullpath), path, false) ) + { + dwarning("AUTOHIDE NONE\nCannot find application file '%s'", path); + return DRC_NETERR; + } + path = fullpath; + } + + drc_t drc = DRC_OK; + if ( !check_input_file_crc32(input_file_crc32) ) + drc = DRC_CRC; + + exiting = false; + + // Build a full command line + qstring args_buffer; // this vector must survive until create_process() + if ( args != NULL && args[0] != '\0' ) + { + args_buffer += '"'; + args_buffer += path; + args_buffer += '"'; + args_buffer += ' '; + args_buffer += args; + args = args_buffer.c_str(); + } + + PROCESS_INFORMATION ProcessInformation; + bool is_gui = (flags & DBG_PROC_IS_GUI) != 0; + bool hide_window = (flags & DBG_HIDE_WINDOW) != 0; + if ( !create_process(path, args, startdir, is_gui, hide_window, &ProcessInformation) ) + return DRC_FAILED; + + pid = ProcessInformation.dwProcessId; + process_handle = ProcessInformation.hProcess; + thread_handle = ProcessInformation.hThread; + process_path = path; + + if ( !handle_process_start(pid) ) + return DRC_NETERR; + + return drc; +} + +//-------------------------------------------------------------------------- +//lint -esym(1762,win32_debmod_t::myCloseHandle) could be made const +bool win32_debmod_t::myCloseHandle(HANDLE &h) +{ + bool ok = true; + if ( h != INVALID_HANDLE_VALUE && h != NULL ) + { + DWORD code; + __try + { + ok = CloseHandle(h) != 0; + if ( !ok ) + deberr("CloseHandle(%08X)", h); + } + __except ( code=GetExceptionCode() ) + { + debdeb("CloseHandle(%08X) exception code %08X\n", h, code); + ok = false; + } + h = INVALID_HANDLE_VALUE; + } + return ok; +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::install_callgate_workaround(thread_info_t *ti, const debug_event_t *event) +{ + // add a breakpoint after the call statement + ea_t bpt = event->ea + 7; + ti->callgate_ea = bpt; + if ( !set_thread_bpt(*ti, bpt) ) + INTERR(637); // how can it be? +} + +//-------------------------------------------------------------------------- +// we do not use 'firsttime' argument anymore. we could use it to distinguish +// the first chance and the second chance but it is more logical to +// behave consistently. +gdecode_t win32_debmod_t::handle_exception( + debug_event_t *event, + const EXCEPTION_RECORD &er, + bool was_thread_bpt, + bool /*firsttime*/) +{ + int code = er.ExceptionCode; + const exception_info_t *ei = find_exception(code); + + eanat_t addr = eanat_t(er.ExceptionAddress); + excinfo_t &exc = event->set_exception(); + event->ea = addr; + exc.code = code; + exc.can_cont = (er.ExceptionFlags == 0); + exc.ea = BADADDR; + event->handled = false; + + if ( exiting && ei == NULL ) + { + event->set_exit_code(PROCESS_EXITED, -1); + return GDE_ONE_EVENT; + } + + bool suspend = true; + + // we don't expect callgate breakpoints anymore + ea_t was_callgate_ea = BADADDR; + thread_info_t *ti = threads.get(event->tid); + if ( ti != NULL ) + { + was_callgate_ea = ti->callgate_ea; + ti->callgate_ea = BADADDR; + } + + if ( ei != NULL ) + { + event->handled = ei->handle(); + // if the user asked to suspend the process, do not resume + if ( !was_thread_bpt ) + suspend = ei->break_on() || pause_requested; + } + if ( !suspend ) + suspend = should_suspend_at_exception(event, ei); + exc.info.qclear(); + int elc_flags = 0; + switch ( uint32(code) ) + { + case EXCEPTION_BREAKPOINT: + case STATUS_WX86_BREAKPOINT: + if ( was_thread_bpt ) + { + QASSERT(638, ti != NULL); + + // is installed the workaround for the 'freely running after syscall' problem? + if ( was_callgate_ea == event->ea ) + event->set_eid(STEP); + else + event->set_eid(PROCESS_SUSPENDED); + break; + } + if ( attach_status == as_breakpoint ) // the process was successfully suspended after an attachement + { + create_attach_event(event, true); + break; + } + if ( expecting_debug_break > 0 + && highdlls.has(addr) + && get_kernel_bpt_ea(event->ea, event->tid) == BADADDR ) // not user-defined bpt + { + --expecting_debug_break; + debdeb("%a: resuming after DbgBreakPoint(), expecting bpts: %d\n", event->ea, expecting_debug_break); + event->handled = true; + dbg_continue_after_event(event); + return GDE_NO_EVENT; + } + // is this a breakpoint set by ida? + { + ea_t kea = get_kernel_bpt_ea(event->ea, event->tid); + if ( kea != BADADDR ) + { + bptaddr_t &bpta = event->set_bpt(); + bpta.hea = BADADDR; // no referenced address (only for hardware breakpoint) + bpta.kea = kea == event->ea ? BADADDR : kea; + event->handled = true; + } + } + break; + case EXCEPTION_SINGLE_STEP: + case STATUS_WX86_SINGLE_STEP: + { + bool is_stepping = ti != NULL && ti->is_tracing(); + // if this happened because of a hardware breakpoint + // find out which one caused it + if ( !check_for_hwbpt(event, is_stepping) ) + { + // if we have not asked for single step, do not convert it to STEP + if ( is_stepping ) + { + event->set_eid(STEP); // Single-step breakpoint + event->handled = true; + ti->clr_tracing(); + break; + } + } + } + break; + case EXCEPTION_ACCESS_VIOLATION: + { + ea_t exc_ea = EA_T(er.ExceptionInformation[1]); // virtual address of the inaccessible data. + exc.ea = exc_ea; + // is this a page bpt? + page_bpts_t::iterator p = find_page_bpt(exc_ea); + if ( p == page_bpts.end() ) + { + exc_ea = event->ea; + p = find_page_bpt(exc_ea); + } + if ( p != page_bpts.end() ) + { + // since on access violation the system does not update anything + // there is no need to reset eip when handling lowcnd below. + elc_flags |= ELC_KEEP_EIP; + ea_t exc_eip = EA_T(er.ExceptionAddress); + if ( !should_fire_page_bpt(p, exc_ea, er.ExceptionInformation[0], + exc_eip, dep_policy) ) + { // Silently step over the page breakpoint + if ( ti != NULL && ti->is_tracing() ) + elc_flags |= ELC_KEEP_SUSP; + lowcnd_t lc; + const pagebpt_data_t &bpt = p->second; + lc.ea = bpt.ea; + lc.type = bpt.type; + lc.size = bpt.user_len; + if ( !handling_lowcnds.has(bpt.ea) + && handle_lowcnd(&lc, event, elc_flags) ) + { + if ( (elc_flags & ELC_KEEP_SUSP) != 0 ) + { // if we were tracing, report a STEP event + event->set_eid(STEP); + event->handled = true; + ti->clr_tracing(); + return GDE_ONE_EVENT; + } + return GDE_NO_EVENT; + } + // failed to step over, return the exception + } + else + { + bptaddr_t &bpta = event->set_bpt(); + bpta.hea = p->second.ea; + bpta.kea = BADADDR; + event->handled = true; + break; + } + } + if ( ei != NULL && event->eid() == EXCEPTION ) + { + int einfo = er.ExceptionInformation[0]; + const char *verb = einfo == EXCEPTION_EXECUTE_FAULT ? "executed" + : einfo == EXCEPTION_WRITE_FAULT ? "written" + : "read"; + exc.info.sprnt(ei->desc.c_str(), event->ea, exc.ea, verb); + } + } + break; +#define EXCEPTION_BCC_FATAL 0xEEFFACE +#define EXCEPTION_BCC_NORMAL 0xEEDFAE6 + case EXCEPTION_BCC_FATAL: + case EXCEPTION_BCC_NORMAL: + if ( er.NumberParameters == 5 + && er.ExceptionInformation[0] == 2 // these numbers are highly hypothetic + && er.ExceptionInformation[1] == 3 ) + { + EXCEPTION_RECORD r2; + if ( dbg_read_memory(er.ExceptionInformation[3], &r2, sizeof(r2), NULL) == sizeof(r2) ) + return handle_exception(event, r2, false, false); + } + break; +#define MS_VC_EXCEPTION 0x406D1388L + case MS_VC_EXCEPTION: + // SetThreadName + // https://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx + if ( er.ExceptionInformation[0] == 0x1000 + && er.ExceptionInformation[3] == 0x00 ) + { + qstring name; + name.resize(MAXSTR); + ea_t nameaddr = er.ExceptionInformation[1]; + if ( dbg_read_memory(nameaddr, name.begin(), name.length(), NULL) > 0 ) + { + thid_t tid = er.ExceptionInformation[2]; + msg("Thread %d is named '%s'\n", tid, name.c_str()); + thread_info_t *tin = threads.get(tid); + if ( tin != NULL ) + { + tin->name = name.c_str(); + tin->set_new_name(); + } + event->handled = true; + } + } + break; + } + if ( !pause_requested && evaluate_and_handle_lowcnd(event, elc_flags) ) + return GDE_NO_EVENT; + + if ( event->eid() == EXCEPTION ) + { + if ( ei == NULL ) + { + exc.info.sprnt("unknown exception code %X", code); + } + else if ( exc.info.empty() ) + { + exc.info.sprnt(ei->desc.c_str(), event->ea, + ea_t(er.ExceptionInformation[0]), + ea_t(er.ExceptionInformation[1])); + } + if ( !suspend ) + { + log_exception(event, ei); + // if a single step was scheduled by the user + if ( ti != NULL && ti->is_tracing() ) + { + clear_tbit(*ti); + if ( event->handled ) + { + // since we mask the exception, we generate a STEP event + event->set_eid(STEP); + return GDE_ONE_EVENT; // got an event + } + } + dbg_continue_after_event(event); + return GDE_NO_EVENT; + } + } + return GDE_ONE_EVENT; +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::check_for_hwbpt(debug_event_t *event, bool is_stepping) +{ + ea_t ea = is_hwbpt_triggered(event->tid, is_stepping); + if ( ea != BADADDR ) + { + bptaddr_t &addr = event->set_bpt(); + addr.hea = ea; + addr.kea = BADADDR; + event->handled = true; + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::create_attach_event(debug_event_t *event, bool attached) +{ + event->set_modinfo(PROCESS_ATTACHED); + event->handled = true; + if ( attached ) + attach_status = as_attached; + else + attach_status = as_attaching; + if ( attach_evid != INVALID_HANDLE_VALUE ) + { + SetEvent(attach_evid); + attach_evid = INVALID_HANDLE_VALUE; + } + modinfo_t &mi_ps = event->modinfo(); + get_debugged_module_info(&mi_ps); + + binary_to_import = mi_ps; +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::create_start_event(debug_event_t *event) +{ + modinfo_t &mi_ps = event->set_modinfo(PROCESS_STARTED); + ea_t base = EA_T(cpdi.lpBaseOfImage); + + process_snapshot_t psnap(get_tool_help()); + PROCESSENTRY32 pe32; + for ( bool ok = psnap.first(TH32CS_SNAPNOHEAPS, &pe32); ok; ok = psnap.next(&pe32) ) + { + if ( pe32.th32ProcessID == event->pid ) + { + char exefile[QMAXPATH]; + tchar_utf8(exefile, pe32.szExeFile, sizeof(exefile)); + if ( !qisabspath(exefile) ) + { + char abspath[QMAXPATH]; + get_filename_for(abspath, + sizeof(abspath), + /*image_name_ea=*/ 0, + /*use_unicode=*/ false, // irrelevant + base); + if ( abspath[0] != '\0' ) + qstrncpy(exefile, abspath, sizeof(exefile)); + } + if ( process_path.empty() || qisabspath(exefile) ) + process_path = exefile; + break; + } + } + mi_ps.name = process_path; + mi_ps.base = base; + mi_ps.size = calc_imagesize(base); + mi_ps.rebase_to = BADADDR; // this must be determined locally - see common_local.cpp + + binary_to_import = mi_ps; +} + +//-------------------------------------------------------------------------- +ea_t win32_debmod_t::get_kernel_bpt_ea(ea_t ea, thid_t tid) +{ + if ( is_ida_bpt(ea, tid) ) + return ea; + return BADADDR; +} + + +ssize_t idaapi win32_debmod_t::dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring * /*errbuf*/) +{ + check_thread(false); + return _write_memory(ea, buffer, size, true); +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_thread_get_sreg_base( + ea_t *pea, + thid_t tid, + int sreg_value, + qstring * /*errbuf*/) +{ + check_thread(false); + NODISTURB_ASSERT(in_event != NULL); + HANDLE h = get_thread_handle(tid); + if ( h == INVALID_HANDLE_VALUE ) + return DRC_FAILED; + +#ifndef __X86__ + + thread_info_t *ti = threads.get(tid); + context_holder_t ctxh; + if ( ti != NULL && ti->read_context(&ctxh, X86_RC_SEGMENTS) ) + { + // is this a TLS base register? (FS for wow64 and GS for x64) + if ( sreg_value == ctxh.ptr->SegGs && !ti->is_wow64() + || sreg_value == ctxh.ptr->SegFs && ti->is_wow64() ) + { + // lpThreadLocalBase is the native (X64) TEB, or GS base + if ( sreg_value == ctxh.ptr->SegGs ) + *pea = EA_T(ti->lpThreadLocalBase); + else + { + // fs base is the WoW64 TEB + // pointer to it is the first field in the native TEB + LPVOID tib32; + if ( _read_memory(EA_T(ti->lpThreadLocalBase), &tib32, sizeof(tib32)) != sizeof(tib32) ) + return DRC_FAILED; + *pea = EA_T(tib32); + } + return DRC_OK; + } + else if ( ti->is_wow64() ) + { + WOW64_LDT_ENTRY se; + if ( !_Wow64GetThreadSelectorEntry(h, sreg_value, &se) ) + { + if ( GetLastError() == ERROR_NOT_SUPPORTED ) + { + // in x64 all selectors except fs/gs are 0-based + *pea = 0; + return DRC_OK; + } + deberr("GetThreadSelectorEntry"); + return DRC_FAILED; + } + *pea = (se.HighWord.Bytes.BaseHi << 24) + | (se.HighWord.Bytes.BaseMid << 16) + | se.BaseLow; + return DRC_OK; + } + } +#endif // __X64__ + // the below code works for non-x64 + LDT_ENTRY se; + if ( !GetThreadSelectorEntry(h, sreg_value, &se) ) + { + if ( GetLastError() == ERROR_NOT_SUPPORTED ) + { + *pea = 0; + return DRC_OK; + } + deberr("GetThreadSelectorEntry"); + return DRC_FAILED; + } + + *pea = (se.HighWord.Bytes.BaseHi << 24) + | (se.HighWord.Bytes.BaseMid << 16) + | se.BaseLow; + return DRC_OK; +} + +//------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_write_register( + thid_t tid, + int reg_idx, + const regval_t *value, + qstring * /*errbuf*/) +{ + check_thread(false); + if ( value == NULL ) + return DRC_FAILED; + + NODISTURB_ASSERT(in_event != NULL); + + reg_ctx->setup(tid); + reg_ctx->setup_reg(reg_idx); + context_holder_t ctxh; + if ( !reg_ctx->load(&ctxh) ) + return DRC_FAILED; + + if ( !reg_ctx->patch(reg_idx, value) ) + return DRC_FAILED; + + if ( !reg_ctx->store(ctxh) ) + return DRC_FAILED; + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +bool idaapi win32_debmod_t::write_registers( + thid_t tid, + int start, + int count, + const regval_t *values) +{ + if ( values == nullptr ) + return false; + + reg_ctx->setup(tid); + for ( size_t i = 0; i < count; i++ ) + reg_ctx->setup_reg(start + i); + context_holder_t ctxh; + if ( !reg_ctx->load(&ctxh) ) + return false; + + for ( size_t i = 0; i < count; i++, values++ ) + if ( !reg_ctx->patch(start + i, values) ) + return false; + + if ( !reg_ctx->store(ctxh) ) + return false; + + return true; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_read_registers( + thid_t tid, + int clsmask, + regval_t *values, + qstring * /*errbuf*/) +{ + check_thread(false); + if ( values == nullptr ) + return DRC_FAILED; + + reg_ctx->setup(tid, clsmask); + context_holder_t ctxh; + if ( !reg_ctx->load(&ctxh) ) + return DRC_FAILED; + + reg_ctx->read_all(values); + + return DRC_OK; +} + +//-------------------------------------------------------------------------- +bool thread_info_t::toggle_tbit(bool set_tbit) +{ + context_holder_t ctxh; + if ( !read_context(&ctxh, X86_RC_GENERAL) ) + return false; + + bool ok = true; + CASSERT(EFLAGS_TRAP_FLAG == 0x100); // so we can shift set_tbit << 8 + if ( (ctxh.ptr->EFlags & EFLAGS_TRAP_FLAG) != (set_tbit << 8) ) //lint !e647 possible truncation before conversion from 'int' to 'unsigned long' + { + QASSERT(30117, (ctxh.ptr->ContextFlags & CONTEXT_CONTROL) != 0); + ctxh.ptr->EFlags |= EFLAGS_TRAP_FLAG; + ctxh.ptr->ContextFlags = CONTEXT_CONTROL; + ok = write_context(X86_RC_GENERAL, *ctxh.ptr); + if ( ok ) + setflag(flags, THR_TRACING, set_tbit); + else + debmod->deberr("%d: SetThreadContext failed", tid); + } + return ok; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_set_resume_mode(thid_t tid, resume_mode_t resmod) +{ + if ( resmod != RESMOD_INTO ) + return DRC_FAILED; // not supported + + check_thread(false); + NODISTURB_ASSERT(in_event != NULL); + thread_info_t *ti = threads.get(tid); + if ( ti == NULL ) + return DRC_FAILED; + + bool ok = ti->toggle_tbit(true); + if ( !ok ) + deberr("%d: (set_step) SetThreadContext failed", tid); + return ok ? DRC_OK : DRC_FAILED; +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::clear_tbit(thread_info_t &ti) +{ + NODISTURB_ASSERT(in_event != NULL); + bool ok = ti.toggle_tbit(false); + if ( !ok ) + deberr("%d: (clr_step) SetThreadContext failed", ti.tid); + return ok; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_continue_after_event(const debug_event_t *event) +{ + check_thread(false); + NODISTURB_ASSERT(in_event != NULL || exiting); + + if ( event == NULL ) + return DRC_FAILED; + + if ( events.empty() ) + { + bool done = false; + if ( !done ) //-V547 '!done' is always true + { + // check if we need to install the workaround for single stepping over callgates + thread_info_t *ti = threads.get(event->tid); + if ( ti != NULL && ti->is_tracing() ) + { + if ( check_for_call_large(event, process_handle) ) + install_callgate_workaround(ti, event); + } + + int flag = event->handled ? DBG_CONTINUE : DBG_EXCEPTION_NOT_HANDLED; + if ( !ContinueDebugEvent(event->pid, event->tid, flag) ) + { + deberr("ContinueDebugEvent"); + return DRC_FAILED; + } + debdeb("ContinueDebugEvent: handled=%s\n", event->handled ? "yes" : "no"); + if ( event->eid() == PROCESS_EXITED ) + { + // from WaitForDebugEvent help page: + // If the system previously reported an EXIT_PROCESS_DEBUG_EVENT debugging event, + // the system closes the handles to the process and thread when the debugger calls the ContinueDebugEvent function. + // => we don't close these handles to avoid error messages + cpdi.hProcess = INVALID_HANDLE_VALUE; + cpdi.hThread = INVALID_HANDLE_VALUE; + process_handle= INVALID_HANDLE_VALUE; + thread_handle = INVALID_HANDLE_VALUE; + cleanup(); + } + } + } + in_event = NULL; + return DRC_OK; +} + +//-------------------------------------------------------------------------- +drc_t idaapi win32_debmod_t::dbg_exit_process(qstring * /*errbuf*/) +{ + check_thread(false); + // WindowsCE sometimes reports failure but terminates the application. + // We ignore the return value. + bool check_termination_code = prepare_to_stop_process(in_event, threads); + bool terminated = TerminateProcess(process_handle, -1) != 0; + if ( !terminated && check_termination_code ) + { + deberr("TerminateProcess"); + return DRC_FAILED; + } + exiting = true; + + if ( in_event != NULL && dbg_continue_after_event(in_event) != DRC_OK ) + { + deberr("continue_after_event"); + return DRC_FAILED; + } + return DRC_OK; +} + + +//-------------------------------------------------------------------------- +void win32_debmod_t::show_exception_record(const EXCEPTION_RECORD &er, int level) +{ + char name[MAXSTR]; + get_exception_name(er.ExceptionCode, name, sizeof(name)); + if ( level > 0 ) + dmsg("%*c", level, ' '); + dmsg("%s: fl=%X adr=%a #prm=%d\n", + name, + er.ExceptionFlags, + EA_T(er.ExceptionAddress), + er.NumberParameters); + if ( er.NumberParameters > 0 ) + { + dmsg("%*c", level+2, ' '); + int n = qmin(er.NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS); + for ( int i=0; i < n; i++ ) + dmsg("%s0x%a", i == 0 ? "" : " ", ea_t(er.ExceptionInformation[i])); + dmsg("\n"); + } + if ( er.ExceptionRecord != NULL ) + show_exception_record(*er.ExceptionRecord, level+2); +} + +//-------------------------------------------------------------------------- +void win32_debmod_t::show_debug_event(const DEBUG_EVENT &ev) +{ + if ( !debug_debugger ) + return; + dmsg("[%u %d] ", ev.dwProcessId, ev.dwThreadId); + switch ( ev.dwDebugEventCode ) + { + case EXCEPTION_DEBUG_EVENT: + { + const EXCEPTION_RECORD &er = ev.u.Exception.ExceptionRecord; + dmsg("EXCEPTION: ea=%p first: %d", // no \n intentionally + er.ExceptionAddress, ev.u.Exception.dwFirstChance); + show_exception_record(er); + } + break; + + case CREATE_THREAD_DEBUG_EVENT: + dmsg("CREATE_THREAD: hThread=%X LocalBase=%p Entry=%p\n", + ev.u.CreateThread.hThread, + ev.u.CreateThread.lpThreadLocalBase, + ev.u.CreateThread.lpStartAddress); + break; + + case CREATE_PROCESS_DEBUG_EVENT: + { + const CREATE_PROCESS_DEBUG_INFO &cpinf = ev.u.CreateProcessInfo; + char path[QMAXPATH]; + if ( process_handle == INVALID_HANDLE_VALUE ) + process_handle = cpinf.hProcess; + get_filename_for( + path, + sizeof(path), + eanat_t(cpinf.lpImageName), + cpinf.fUnicode != 0, + eanat_t(cpinf.lpBaseOfImage)); + dmsg("CREATE_PROCESS: hFile=%X hProcess=%X hThread=%X " + "base=%p\n dbgoff=%X dbgsiz=%X tlbase=%p start=%p name=%p '%s' \n", + cpinf.hFile, cpinf.hProcess, cpinf.hThread, cpinf.lpBaseOfImage, + cpinf.dwDebugInfoFileOffset, cpinf.nDebugInfoSize, cpinf.lpThreadLocalBase, + cpinf.lpStartAddress, cpinf.lpImageName, path); + } + break; + + case EXIT_THREAD_DEBUG_EVENT: + dmsg("EXIT_THREAD: code=%d\n", ev.u.ExitThread.dwExitCode); + break; + + case EXIT_PROCESS_DEBUG_EVENT: + dmsg("EXIT_PROCESS: code=%d\n", ev.u.ExitProcess.dwExitCode); + break; + + case LOAD_DLL_DEBUG_EVENT: + { + char path[QMAXPATH]; + const LOAD_DLL_DEBUG_INFO &di = ev.u.LoadDll; + get_filename_for( + path, + sizeof(path), + eanat_t(di.lpImageName), + di.fUnicode != 0, + eanat_t(di.lpBaseOfDll)); + dmsg("LOAD_DLL: h=%X base=%p dbgoff=%X dbgsiz=%X name=%X '%s'\n", + di.hFile, di.lpBaseOfDll, di.dwDebugInfoFileOffset, di.nDebugInfoSize, + di.lpImageName, path); + } + break; + + case UNLOAD_DLL_DEBUG_EVENT: + dmsg("UNLOAD_DLL: base=%p\n", ev.u.UnloadDll.lpBaseOfDll); + break; + + case OUTPUT_DEBUG_STRING_EVENT: + { + char buf[MAXSTR]; + get_debug_string(ev, buf, sizeof(buf)); + dmsg("OUTPUT_DEBUG_STRING: str=\"%s\"\n", buf); + } + break; + + case RIP_EVENT: + dmsg("RIP_EVENT (system debugging error)\n"); + break; + + default: + dmsg("UNKNOWN_DEBUG_EVENT %d\n", ev.dwDebugEventCode); + break; + } +} + +//-------------------------------------------------------------------------- +int win32_debmod_t::dbg_freeze_threads_except(thid_t tid) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + if ( p->first != tid ) + _sure_suspend_thread(p->second, true); + return 1; +} + +//-------------------------------------------------------------------------- +int win32_debmod_t::dbg_thaw_threads_except(thid_t tid) +{ + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + if ( p->first != tid ) + _sure_resume_thread(p->second, true); + return 1; +} + +//-------------------------------------------------------------------------- +// if we have to do something as soon as we noticed the connection +// broke, this is the correct place +bool idaapi win32_debmod_t::dbg_prepare_broken_connection(void) +{ + broken_connection = true; + bool ret = false; + if ( restore_broken_breakpoints() ) + { + // create the required event for synchronization; we use it + // to notify when the process was successfully detached + broken_event_handle = CreateEvent(NULL, false, false, NULL); + + if ( broken_event_handle != NULL ) + { + int code = WAIT_TIMEOUT; + while ( code == WAIT_TIMEOUT ) + code = WaitForSingleObject(broken_event_handle, 100); + + if ( code == WAIT_OBJECT_0 ) + { + suspend_running_threads(_suspended_threads); + if ( dbg_detach_process() == DRC_OK ) + SetEvent(broken_event_handle); + } + } + } + + return ret; +} + +//-------------------------------------------------------------------------- +// Continuing from a broken connection in win32 debugger consist in the +// following step (if we're talking about a single threaded server): +// +// 1 - Notify the other thread that we want to reuse that connection +// 2 - Wait for the previous thread to notify that finished his work +// 3 - Reattach to the process and reopen thread's handles as, for a +// reason, the handles we have are invalid (why?). +// 4 - Resume the threads we suspended before. +// +bool idaapi win32_debmod_t::dbg_continue_broken_connection(pid_t _pid) +{ + debmod_t::dbg_continue_broken_connection(_pid); + + QASSERT(676, broken_event_handle != NULL); + + // notify the broken thread we want to reuse the connection + SetEvent(broken_event_handle); + + // and wait for the notification for a maximum of 15 seconds + // as we don't want to wait forever (INFINITE) because the + // other thread may fail + int code = WaitForSingleObject(broken_event_handle, 15000); + if ( code != WAIT_OBJECT_0 ) + { + msg("Error restoring broken connection"); + return false; + } + + if ( dbg_attach_process(_pid, -1, 0, NULL) == DRC_OK && reopen_threads() ) + { + resume_suspended_threads(_suspended_threads); + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +bool win32_debmod_t::reopen_threads(void) +{ + if ( _OpenThread == NULL ) + return false; + + for ( threads_t::iterator p=threads.begin(); p != threads.end(); ++p ) + { + HANDLE hThread; + hThread = _OpenThread(THREAD_ALL_ACCESS, true, p->second.tid); + if ( hThread != NULL ) + p->second.hThread = hThread; + else + deberr("OpenThread"); + p->second.suspend_count = get_thread_suspend_count(hThread); + } + return true; +} + +//-------------------------------------------------------------------------- +static bool enable_privilege(LPCTSTR privilege, bool enable); +static bool g_subsys_inited = false; +static bool g_got_debpriv = false; + +bool init_subsystem() +{ + if ( g_subsys_inited ) + return true; + + if ( !win32_debmod_t::winver.ok() ) + return false; + + win_tool_help_t *wth = win32_debmod_t::get_tool_help(); + if ( wth->ok() ) + g_code |= DBG_HAS_GET_PROCESSES; + + // DebugActiveProcessStop() is only available on XP/2K3 + if ( wth->use_debug_detach_process() ) + g_code |= DBG_HAS_DETACH_PROCESS; + + g_got_debpriv = enable_privilege(SE_DEBUG_NAME, true); + if ( !g_got_debpriv ) + msg("Cannot set debug privilege: %s.\n" + "Debugging of processes owned by another account won't be possible.\n", + winerr(GetLastError())); + + win32_debmod_t::reuse_broken_connections = true; + init_win32_subsystem(); + + HINSTANCE h = GetModuleHandle(kernel32_dll); + *(FARPROC*)&_OpenThread = GetProcAddress(h, TEXT("OpenThread")); + *(FARPROC*)&_GetThreadDescription = GetProcAddress(h, TEXT("GetThreadDescription")); + +#ifndef __X86__ + *(FARPROC*)&_Wow64GetThreadContext = GetProcAddress(h, TEXT("Wow64GetThreadContext")); + *(FARPROC*)&_Wow64SetThreadContext = GetProcAddress(h, TEXT("Wow64SetThreadContext")); + *(FARPROC*)&_Wow64GetThreadSelectorEntry = GetProcAddress(h, TEXT("Wow64GetThreadSelectorEntry")); +#endif + + g_subsys_inited = g_code != 0; + return g_subsys_inited; +} + +//-------------------------------------------------------------------------- +bool term_subsystem() +{ + if ( !g_subsys_inited ) + return true; + + g_subsys_inited = false; + + if ( g_got_debpriv ) + { + enable_privilege(SE_DEBUG_NAME, false); + g_got_debpriv = false; + } + + term_win32_subsystem(); + return true; +} + +//-------------------------------------------------------------------------- +debmod_t *create_debug_session(void *) +{ + return new win32_debmod_t(); +} + +//-------------------------------------------------------------------------- +// +// DEBUG PRIVILEGE +// +//-------------------------------------------------------------------------- +// dynamic linking information for Advapi functions +static HMODULE hAdvapi32 = NULL; +// function prototypes +typedef BOOL (WINAPI *OpenProcessToken_t)( + HANDLE ProcessHandle, + DWORD DesiredAccess, + PHANDLE TokenHandle); +typedef BOOL (WINAPI *LookupPrivilegeValue_t)( + LPCTSTR lpSystemName, + LPCTSTR lpName, + PLUID lpLuid); +typedef BOOL (WINAPI *AdjustTokenPrivileges_t)( + HANDLE TokenHandle, + BOOL DisableAllPrivileges, + PTOKEN_PRIVILEGES NewState, + DWORD BufferLength, + PTOKEN_PRIVILEGES PreviousState, + PDWORD ReturnLength); + +// Function pointers +static OpenProcessToken_t _OpenProcessToken = NULL; +static LookupPrivilegeValue_t _LookupPrivilegeValue = NULL; +static AdjustTokenPrivileges_t _AdjustTokenPrivileges = NULL; + +//-------------------------------------------------------------------------- +static void term_advapi32(void) +{ + if ( hAdvapi32 != NULL ) + { + DWORD code = GetLastError(); + FreeLibrary(hAdvapi32); + SetLastError(code); + hAdvapi32 = NULL; + } +} + +//-------------------------------------------------------------------------- +static bool init_advapi32(void) +{ + // load the library + hAdvapi32 = LoadLibrary(TEXT("advapi32.dll")); + if ( hAdvapi32 == NULL ) + return false; + + // find the needed functions + *(FARPROC*)&_OpenProcessToken = GetProcAddress(hAdvapi32, TEXT("OpenProcessToken")); + *(FARPROC*)&_LookupPrivilegeValue = GetProcAddress(hAdvapi32, TEXT(LookupPrivilegeValue_Name)); + *(FARPROC*)&_AdjustTokenPrivileges = GetProcAddress(hAdvapi32, TEXT("AdjustTokenPrivileges")); + + bool ok = _OpenProcessToken != NULL + && _LookupPrivilegeValue != NULL + && _AdjustTokenPrivileges != NULL; + if ( !ok ) + term_advapi32(); + return ok; +} + + +//-------------------------------------------------------------------------- +// based on code from: +// http://support.microsoft.com/support/kb/articles/Q131/0/65.asp +static bool enable_privilege(LPCTSTR privilege, bool enable) +{ + if ( !win32_debmod_t::winver.is_NT() ) // no privileges on 9X/ME + return true; + + bool ok = false; + if ( init_advapi32() ) + { + HANDLE hToken; + DWORD tokens = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY; + if ( _OpenProcessToken(GetCurrentProcess(), tokens, &hToken) ) + { + LUID luid; + if ( _LookupPrivilegeValue(NULL, privilege, &luid) ) + { + TOKEN_PRIVILEGES tp; + memset(&tp, 0, sizeof(tp)); + tp.PrivilegeCount = 1; + tp.Privileges[0].Luid = luid; + tp.Privileges[0].Attributes = enable ? SE_PRIVILEGE_ENABLED : 0; + ok = _AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL) != FALSE; + } + CloseHandle(hToken); + } + term_advapi32(); + } + return ok; +} diff --git a/idasdk76/dbg/win32/win32_debmod.h b/idasdk76/dbg/win32/win32_debmod.h new file mode 100644 index 0000000..094f2a6 --- /dev/null +++ b/idasdk76/dbg/win32/win32_debmod.h @@ -0,0 +1,427 @@ +#ifndef __WIN32_DEBUGGER_MODULE__ +#define __WIN32_DEBUGGER_MODULE__ + +#include <windows.h> +#include <Tlhelp32.h> +#include "../../ldr/pe/pe.h" +#include "winbase_debmod.h" + +//-V::720 It is advised to utilize the 'SuspendThread' function only when developing a debugger + +// Type definitions + +class win32_debmod_t; + +//-------------------------------------------------------------------------- +// image information +struct image_info_t +{ + image_info_t() { memset(this, 0, sizeof(*this)); } + image_info_t(win32_debmod_t *); + image_info_t(win32_debmod_t *, ea_t _base, uint32 _imagesize, const qstring &_name); + image_info_t(win32_debmod_t *, const LOAD_DLL_DEBUG_INFO &i, uint32 _imagesize, const char *_name); + image_info_t(win32_debmod_t *, const modinfo_t &m); + + win32_debmod_t *sess; + ea_t base; + uval_t imagesize; + qstring name; + LOAD_DLL_DEBUG_INFO dll_info; +}; + +// key: image base address +typedef std::map<ea_t, image_info_t> images_t; + +//------------------------------------------------------------------------- +struct context_holder_t +{ + bytevec_t buffer; + PCONTEXT ptr; + + context_holder_t() : ptr(NULL) {} +}; + +//------------------------------------------------------------------------- +struct context_helper_t +{ + typedef DWORD64 (WINAPI *PGETENABLEDXSTATEFEATURES)(); + PGETENABLEDXSTATEFEATURES pfnGetEnabledXStateFeatures; + + typedef BOOL (WINAPI *PINITIALIZECONTEXT)(PVOID Buffer, DWORD ContextFlags, PCONTEXT *Context, PDWORD ContextLength); + PINITIALIZECONTEXT pfnInitializeContext; + + typedef BOOL (WINAPI *PGETXSTATEFEATURESMASK)(PCONTEXT Context, PDWORD64 FeatureMask); + PGETXSTATEFEATURESMASK pfnGetXStateFeaturesMask; + + typedef PVOID (WINAPI *LOCATEXSTATEFEATURE)(PCONTEXT Context, DWORD FeatureId, PDWORD Length); + LOCATEXSTATEFEATURE pfnLocateXStateFeature; + + typedef BOOL (WINAPI *SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask); + SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask; + + typedef BOOL (WINAPI *COPYCONTEXT)(PCONTEXT Destination, DWORD ContextFlags, PCONTEXT Source); + COPYCONTEXT pfnCopyContext; + + int xstate_context_size; + bool get_xstate_context_size(int *out_ctxsz); + context_helper_t() { clear(); } + bool create_context(context_holder_t *out, int *ctxflags); + bool xstate_helpers_loaded() const { return xstate_context_size > 0; } + void clear(); +}; + +//-------------------------------------------------------------------------- +// thread information +struct thread_info_t : public CREATE_THREAD_DEBUG_INFO +{ + thread_info_t( + win32_debmod_t *dm, + const CREATE_THREAD_DEBUG_INFO &i, + thid_t t, + wow64_state_t wow64_state); + win32_debmod_t *debmod; + thid_t tid; // thread id + int suspend_count; + ea_t bpt_ea; + int flags; +#define THR_TRACING 0x0001 // expecting a STEP event +#define THR_WOW64 0x0002 // is wow64 process? +#define THR_NEWNAME 0x0004 // thread was renamed + ea_t callgate_ea; + qstring name; + + bool read_context(context_holder_t *out, int clsmask); + bool write_context(int clsmask, CONTEXT &ctx); + bool toggle_tbit(bool set_tbit); + bool is_tracing(void) const { return (flags & THR_TRACING) != 0; } + bool is_wow64(void) const { return (flags & THR_WOW64) != 0; } + void set_tracing(void) { flags |= THR_TRACING; } + void clr_tracing(void) { flags &= ~THR_TRACING; } + bool is_new_name(void) const { return (flags & THR_NEWNAME) != 0; } + void clr_new_name(void) { flags &= ~THR_NEWNAME; } + void set_new_name(void) { flags |= THR_NEWNAME; } +}; + +//-------------------------------------------------------------------------- +inline thread_info_t::thread_info_t( + win32_debmod_t *dm, + const CREATE_THREAD_DEBUG_INFO &i, + thid_t t, + wow64_state_t wow64_state) + : CREATE_THREAD_DEBUG_INFO(i), tid(t), suspend_count(0), bpt_ea(BADADDR), + debmod(dm), + flags(wow64_state > 0 ? THR_WOW64 : 0), + callgate_ea(0) +{ +} + +//-------------------------------------------------------------------------- +// Check if the context structure has valid values at the specified portion +// portion is a conbination of CONTEXT_... bitmasks +inline bool has_portion(const CONTEXT &ctx, int portion) +{ + return (ctx.ContextFlags & portion & 0xFFFF) != 0; +} + +//-------------------------------------------------------------------------- +// (tid -> info) +struct threads_t: public std::map<DWORD, thread_info_t> +{ + thread_info_t *get(DWORD tid) + { + const iterator it = find(tid); + if ( it == end() ) + return NULL; + return &it->second; + } +}; + +//-------------------------------------------------------------------------- +typedef qvector<thread_info_t> threadvec_t; + +//-------------------------------------------------------------------------- +// structure for the internal breakpoint information for threads +struct internal_bpt_info_t +{ + int count; // number of times this breakpoint is 'set' + uchar orig_bytes[BPT_CODE_SIZE]; // original byte values +}; +typedef std::map<ea_t, internal_bpt_info_t> bpt_info_t; + +//-------------------------------------------------------------------------- +typedef int (*process_cb_t)(debmod_t *, PROCESSENTRY32 *pe32, void *ud); +typedef int (*module_cb_t)(debmod_t *, MODULEENTRY32 *me32, void *ud); + +//---------------------------------------------------------------------------- +// A live PDB session, that will be used remotely (typically by non-windows machines). +struct pdb_remote_session_t; +void close_pdb_remote_session(pdb_remote_session_t *); + +// Wow64-specific events +#ifndef STATUS_WX86_BREAKPOINT +# define STATUS_WX86_BREAKPOINT 0x4000001f +#endif +#ifndef STATUS_WX86_SINGLE_STEP +# define STATUS_WX86_SINGLE_STEP 0x4000001e +#endif + +//------------------------------------------------------------------------- +struct machine_thread_state_t; +struct machine_float_state_t; + +//-------------------------------------------------------------------------- +class win32_debmod_t : public winbase_debmod_t +{ + typedef winbase_debmod_t inherited; + + regctx_t *reg_ctx; + + gdecode_t get_debug_event(debug_event_t *event, int timeout_ms); + void check_thread(bool must_be_main_thread) const; + void add_thread(const CREATE_THREAD_DEBUG_INFO &thr_info, thid_t tid); + void install_callgate_workaround(thread_info_t *ti, const debug_event_t *event); + int describe_stack_segment( + thid_t tid, + images_t &thr_ranges, + images_t &cls_ranges, + const _NT_TIB &tib, + const char *pref); + void update_thread_names(thread_name_vec_t *thr_names); + + bool get_pe_exports_from_path( + const char *path, + linput_t *li, + ea_t imagebase, + name_info_t &ni, + const char *exported_name=NULL) const; + void _term_reg_ctx(void); + +public: + // debugged process information + qstring process_path; + HANDLE thread_handle; + HANDLE redirin_handle; + HANDLE redirout_handle; + attach_status_t attach_status; + HANDLE attach_evid; + int8 expecting_debug_break; + bool stop_at_ntdll_bpts; + + images_t curproc; // image of the running process + images_t dlls; // list of loaded DLLs + images_t images; // list of detected PE images + images_t thread_ranges; // list of ranges related to threads + images_t class_ranges; // list of ranges related to class names + + easet_t dlls_to_import; // list of dlls to import information from + modinfo_t binary_to_import; // executable to import information from + + bpt_info_t thread_bpts; + + threads_t threads; + + // ID of a thread for which we must emulate a STEP event on XP (using a breakpoint) + thid_t winxp_step_thread; + + CREATE_PROCESS_DEBUG_INFO cpdi; + + debug_event_t *in_event; // current debug event + bool fake_suspend_event; + bool exiting; + bool pause_requested; + procinfo_vec_t processes; + + // threads suspended by the fiber created for restoring broken connections + threadvec_t _suspended_threads; + // event to wait until the broken connection is completely restored + HANDLE broken_event_handle; + context_helper_t context_helper; + + // Module specific methods, to be implemented + virtual void idaapi dbg_set_debugging(bool _debug_debugger) override; + virtual drc_t idaapi dbg_init(uint32_t *flags2, qstring *errbuf) override; + virtual void idaapi dbg_term(void) override; + virtual drc_t idaapi dbg_detach_process(void) override; + virtual drc_t idaapi dbg_start_process( + const char *path, + const char *args, + const char *startdir, + int flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf) override; + virtual gdecode_t idaapi dbg_get_debug_event(debug_event_t *event, int timeout_ms) override; + virtual drc_t idaapi dbg_attach_process( + pid_t process_id, + int event_id, + int flags, + qstring *errbuf) override; + virtual drc_t idaapi dbg_prepare_to_pause_process(qstring *errbuf) override; + virtual drc_t idaapi dbg_exit_process(qstring *errbuf) override; + virtual drc_t idaapi dbg_continue_after_event(const debug_event_t *event) override; + virtual void idaapi dbg_stopped_at_debug_event( + import_infos_t *infos, + bool dlls_added, + thread_name_vec_t *thr_names) override; + virtual drc_t idaapi dbg_thread_suspend(thid_t thread_id) override; + virtual drc_t idaapi dbg_thread_continue(thid_t thread_id) override; + virtual drc_t idaapi dbg_set_resume_mode(thid_t thread_id, resume_mode_t resmod) override; + virtual drc_t idaapi dbg_read_registers( + thid_t thread_id, + int clsmask, + regval_t *values, + qstring *errbuf) override; + virtual drc_t idaapi dbg_write_register( + thid_t thread_id, + int reg_idx, + const regval_t *value, + qstring *errbuf) override; + + virtual drc_t idaapi dbg_thread_get_sreg_base(ea_t *ea, thid_t thread_id, int sreg_value, qstring *errbuf) override; + virtual drc_t idaapi dbg_get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) override; + virtual ssize_t idaapi dbg_read_memory(ea_t ea, void *buffer, size_t size, qstring *errbuf) override; + virtual ssize_t idaapi dbg_write_memory(ea_t ea, const void *buffer, size_t size, qstring *errbuf) override; + virtual int idaapi dbg_add_bpt(bytevec_t *orig_bytes, bpttype_t type, ea_t ea, int len) override; + virtual int idaapi dbg_del_bpt(bpttype_t type, ea_t ea, const uchar *orig_bytes, int len) override; + virtual int idaapi handle_ioctl(int fn, const void *buf, size_t size, void **outbuf, ssize_t *outsize) override; + // + win32_debmod_t(); + ~win32_debmod_t() { cleanup(); _term_reg_ctx(); } + + virtual void init_reg_ctx(void) override; + virtual void term_reg_ctx(void) override; + + bool get_thread_state( + context_holder_t *out_ctxh, + machine_thread_state_t *out_regs, + machine_float_state_t *out_floats, + thid_t tid, + int clsmask); + bool set_thread_state( + const machine_thread_state_t ®s, + const machine_float_state_t &floats, + const context_holder_t &ctxh, + thid_t tid, + int clsmask); + + void handle_pdb_thread_request(void *data); + uint32 calc_imagesize(eanat_t base); + bool get_filename_for( + char *buf, + size_t bufsize, + eanat_t image_name_ea, + bool use_unicode, + eanat_t image_base); + ea_t get_dll_export( + const images_t &dlls, + ea_t imagebase, + const char *exported_name); + + bool create_process( + const char *path, + const char *args, + const char *startdir, + bool is_gui, + bool hide_window, + PROCESS_INFORMATION *ProcessInformation); + + void show_debug_event(const DEBUG_EVENT &ev); + + ssize_t _read_memory(eanat_t ea, void *buffer, size_t size, bool suspend = false); + ssize_t _write_memory(eanat_t ea, const void *buffer, size_t size, bool suspend = false); + + int rdmsr(int reg, uint64 *value); + int wrmsr(int reg, uint64 value); + int kldbgdrv_access_msr(struct SYSDBG_MSR *msr, bool write); + + // !! OVERWRITTEN METHODS !! + bool refresh_hwbpts(); + + // Utility methods + gdecode_t handle_exception(debug_event_t *event, + const EXCEPTION_RECORD &er, + bool was_thread_bpt, + bool firsttime); + ssize_t access_memory(eanat_t ea, void *buffer, ssize_t size, bool write, bool suspend); + inline void resume_all_threads(bool raw = false); + inline void suspend_all_threads(bool raw = false); + size_t add_dll(image_info_t &ii); + bool module_present(const char *modname); + HANDLE get_thread_handle(thid_t tid); + static int get_dmi_cb(debmod_t *sess, MODULEENTRY32 *me32, void *ud); + void get_debugged_module_info(modinfo_t *dmi); + int for_each_module(DWORD pid, module_cb_t module_cb, void *ud); + bool myCloseHandle(HANDLE &h); + void cleanup(void); + void restore_original_bytes(ea_t ea, bool really_restore = true); + int save_original_bytes(ea_t ea); + bool set_thread_bpt(thread_info_t &ti, ea_t ea); + bool del_thread_bpt(thread_info_t &ti, ea_t ea); + bool del_thread_bpts(ea_t ea); + bool has_bpt_at(ea_t ea); + bool can_access(ea_t addr); + ea_t get_kernel_bpt_ea(ea_t ea, thid_t tid); + void create_attach_event(debug_event_t *event, bool attached); + void create_start_event(debug_event_t *event); + bool check_for_hwbpt(debug_event_t *event, bool is_stepping=false); + ea_t get_region_info(ea_t ea, memory_info_t *info); + bool get_dll_exports( + const images_t &dlls, + ea_t imagebase, + name_info_t &ni, + const char *exported_name = NULL); + bool get_filename_from_process( + eanat_t name_ea, + bool is_unicode, + char *buf, + size_t bufsize); + bool get_debug_string(const DEBUG_EVENT &ev, char *buf, size_t bufsize); + int add_thread_ranges( + thid_t tid, + images_t &thread_ranges, + images_t &class_ranges); + ea_t get_pe_header(eanat_t imagebase, peheader_t *nh); + bool get_pe_export_name_from_process( + eanat_t imagebase, + char *name, + size_t namesize); + + void show_exception_record(const EXCEPTION_RECORD &er, int level=0); + + eanat_t pstos0(eanat_t ea); + eanat_t s0tops(eanat_t ea); + + bool prepare_to_stop_process(debug_event_t *, const threads_t &); + bool disable_hwbpts(); + bool enable_hwbpts(); + bool may_write(ea_t ea); + LPVOID correct_exe_image_base(LPVOID base); + bool clear_tbit(thread_info_t &th); + void enqueue_event(const debug_event_t &ev, queue_pos_t pos); + + void suspend_running_threads(threadvec_t &suspended); + void resume_suspended_threads(threadvec_t suspended) const; + bool reopen_threads(void); + + virtual bool idaapi write_registers( + thid_t thread_id, + int start, + int count, + const regval_t *values) override; + + virtual bool idaapi dbg_prepare_broken_connection(void) override; + virtual bool idaapi dbg_continue_broken_connection(pid_t pid) override; + + qvector<pdb_remote_session_t*> pdb_remote_sessions; + pdb_remote_session_t *get_pdb_session(int id); + void delete_pdb_session(int id); + +protected: + virtual int dbg_freeze_threads_except(thid_t tid) override; + virtual int dbg_thaw_threads_except(thid_t tid) override; +}; + +ea_t s0tops(ea_t ea); + +#endif + diff --git a/idasdk75/dbg/win32/win32_debmod_impl.cpp b/idasdk76/dbg/win32/win32_debmod_impl.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_debmod_impl.cpp rename to idasdk76/dbg/win32/win32_debmod_impl.cpp diff --git a/idasdk75/dbg/win32/win32_local_impl.cpp b/idasdk76/dbg/win32/win32_local_impl.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_local_impl.cpp rename to idasdk76/dbg/win32/win32_local_impl.cpp diff --git a/idasdk75/dbg/win32/win32_rpc.h b/idasdk76/dbg/win32/win32_rpc.h similarity index 100% rename from idasdk75/dbg/win32/win32_rpc.h rename to idasdk76/dbg/win32/win32_rpc.h diff --git a/idasdk75/dbg/win32/win32_server.cpp b/idasdk76/dbg/win32/win32_server.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_server.cpp rename to idasdk76/dbg/win32/win32_server.cpp diff --git a/idasdk75/dbg/win32/win32_server_stub.cpp b/idasdk76/dbg/win32/win32_server_stub.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_server_stub.cpp rename to idasdk76/dbg/win32/win32_server_stub.cpp diff --git a/idasdk75/dbg/win32/win32_stub.cpp b/idasdk76/dbg/win32/win32_stub.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_stub.cpp rename to idasdk76/dbg/win32/win32_stub.cpp diff --git a/idasdk75/dbg/win32/win32_undoc.h b/idasdk76/dbg/win32/win32_undoc.h similarity index 100% rename from idasdk75/dbg/win32/win32_undoc.h rename to idasdk76/dbg/win32/win32_undoc.h diff --git a/idasdk75/dbg/win32/win32_user.cpp b/idasdk76/dbg/win32/win32_user.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_user.cpp rename to idasdk76/dbg/win32/win32_user.cpp diff --git a/idasdk75/dbg/win32/win32_util.cpp b/idasdk76/dbg/win32/win32_util.cpp similarity index 100% rename from idasdk75/dbg/win32/win32_util.cpp rename to idasdk76/dbg/win32/win32_util.cpp diff --git a/idasdk75/dbg/win32/win32_util.hpp b/idasdk76/dbg/win32/win32_util.hpp similarity index 100% rename from idasdk75/dbg/win32/win32_util.hpp rename to idasdk76/dbg/win32/win32_util.hpp diff --git a/idasdk76/dbg/win32/winbase_debmod.cpp b/idasdk76/dbg/win32/winbase_debmod.cpp new file mode 100644 index 0000000..54f432e --- /dev/null +++ b/idasdk76/dbg/win32/winbase_debmod.cpp @@ -0,0 +1,633 @@ +#include <windows.h> +#include <ida.hpp> +#include "winbase_debmod.h" + +#ifndef __X86__ +#define IDA_ADDRESS_SIZE 8 +#else +#define IDA_ADDRESS_SIZE 4 +#endif + +const TCHAR kernel32_dll[] = TEXT("kernel32.dll"); + +typedef BOOL WINAPI GetProcessDEPPolicy_t(HANDLE hProcess, LPDWORD lpFlags, PBOOL lpPermanent); +static GetProcessDEPPolicy_t *_GetProcessDEPPolicy = NULL; + +typedef dep_policy_t WINAPI GetSystemDEPPolicy_t(void); +static GetSystemDEPPolicy_t *_GetSystemDEPPolicy = NULL; + +//-------------------------------------------------------------------------- +winbase_debmod_t::winbase_debmod_t(void) +{ + HMODULE k32 = GetModuleHandle(kernel32_dll); + + if ( _GetProcessDEPPolicy == NULL ) + *(FARPROC*)&_GetProcessDEPPolicy = GetProcAddress(k32, TEXT("GetProcessDEPPolicy")); + + if ( _GetSystemDEPPolicy == NULL ) + *(FARPROC*)&_GetSystemDEPPolicy = GetProcAddress(k32, TEXT("GetSystemDEPPolicy")); + + if ( _GetSystemDEPPolicy != NULL ) + dep_policy = _GetSystemDEPPolicy(); + + win_tool_help = NULL; + set_platform("win32"); +} + +//-------------------------------------------------------------------------- +// Prepare new page protections for a breakpoint of BPTTYPE. +// Use INPUT as starting page protections. +// Return false in the case of failure. +bool winbase_debmod_t::remove_page_protections( + DWORD *p_input, + bpttype_t bpttype, + dep_policy_t dpolicy, + HANDLE proc_handle) +{ + // If PAGE_GUARD is already set, do not change anything, it is already ok + DWORD input = *p_input; + if ( (input & PAGE_GUARD) != 0 ) + return false; + + // Convert between Unix permissions and Win32 page protections using this array: + static const uchar win32_page_protections[] = + { + PAGE_NOACCESS, // 000 + PAGE_READONLY, // 001 + 0xFF, // 010 WRITE_ONLY does not exist on win32 + PAGE_READWRITE, // 011 + PAGE_EXECUTE, // 100 + PAGE_EXECUTE_READ, // 101 + 0xFF, // 110 EXECUTE_WRITE does not exist on win32 + PAGE_EXECUTE_READWRITE, // 111 + }; + uchar unix; + // convert ..COPY page protections into their non-copy counterparts + // this is the best thing we can do with them because they are automatically + // converted by the system upon a write access + if ( (input & PAGE_WRITECOPY) != 0 ) + { + unix = 3; // rw + } + else if ( (input & PAGE_EXECUTE_WRITECOPY) != 0 ) + { + unix = 7; // rwx + } + else + { + for ( unix=0; unix < 8; unix++ ) + { + uchar p = win32_page_protections[unix]; + if ( p != 0xFF && (input & p) != 0 ) + break; + } + } + QASSERT(622, unix < 8); + + // convert bpttype into unix permissions + int del = 0; + if ( (bpttype & BPT_READ) != 0 ) + del |= 1; + if ( (bpttype & BPT_WRITE) != 0 ) + del |= 2; + if ( (bpttype & BPT_EXEC) != 0 ) + { + del |= 4; + // if DEP is disabled for this process then a program can + // happily execute code in a read only area so we need to + // remove *all* privileges, unfortunately + if ( dpolicy != dp_always_on ) + { + // on XP, GetProcessDEPPolicy returns DEP policy for current process (i.e. the debugger) + // so we can't use it + // assume that DEP is disabled by default + DWORD flags = 0; + BOOL permanent = 0; + if ( _GetProcessDEPPolicy == NULL + || winver.is_strictly_xp() + || winver.is_GetProcessDEPPolicy_broken() + || _GetProcessDEPPolicy(proc_handle, &flags, &permanent) ) + { + // flags == 0: DEP is disabled for the specified process. + // + // Remarks: if permanent == 0 and global DEP policy is OptIn + // flags may be equal to 1 *but* having DEP disabled because, + // in case the process called SetProcessDEPPolicy the + // permanent argument would be 1, it seems to be a bug in the + // documentation + if ( (dpolicy == dp_opt_in && permanent == 0) || flags == 0 ) + del |= 1; + } + } + } + + // Remove the access types to trigger on + unix &= ~del; + + // Handle WRITE_ONLY and EXECUTE_WRITE cases because win32 does not have them. + // We use stricter page permissions for them. This means that there will + // be more useless exceptions but we cannot do much about it. + if ( unix == 2 || unix == 6 ) + unix = 0; // use PAGE_NOACCESS instead of WRITE_ONLY or EXECUTE_WRITE + + uchar perm = win32_page_protections[unix]; + *p_input = (input & ~0xFF) | perm; + return true; +} + +//-------------------------------------------------------------------------- +bool idaapi winbase_debmod_t::dbg_enable_page_bpt( + page_bpts_t::iterator p, + bool enable) +{ + pagebpt_data_t &bpt = p->second; + if ( (bpt.old_prot != 0) == enable ) + return false; // already the desired state + + debdeb("dbg_enable_page_bpt(%s): page_ea=%a, old_prot=0x%x, new_prot=0x%x\n", enable ? "true" : "false", bpt.page_ea, bpt.old_prot, bpt.new_prot); + + DWORD old; + DWORD prot = enable ? bpt.new_prot : bpt.old_prot; + if ( !VirtualProtectEx(process_handle, (void*)(size_t)bpt.page_ea, + bpt.real_len, prot, &old) ) + { + deberr("VirtualProtectEx"); + // if the page disappeared while disabling a bpt, do not complain, + // silently return success + if ( enable ) + return false; + old = 0; + } + + debdeb(" success! old=0x%x\n", old); + + bpt.old_prot = enable ? old : 0; + return true; +} + +//-------------------------------------------------------------------------- +// Should we generate a BREAKPOINT event because of page bpt? +//lint -e{1746} could be made const reference +bool should_fire_page_bpt( + page_bpts_t::iterator p, + ea_t ea, + DWORD failed_access_type, + ea_t pc, + dep_policy_t dep_policy) +{ + const pagebpt_data_t &bpt = p->second; + if ( !interval::contains(bpt.ea, bpt.user_len, ea) ) + return false; // not in the user-defined interval + + int bit; + switch ( failed_access_type ) + { + default: + INTERR(623); //-V796 no break + case EXCEPTION_READ_FAULT: // failed READ access + // depending on the DEP policy we mark this access also + // to be triggered in case of EXEC breakpoints + bit = BPT_READ; + if ( dep_policy != dp_always_on && bpt.type == BPT_EXEC && pc == ea ) + bit |= BPT_EXEC; + break; + case EXCEPTION_WRITE_FAULT: // failed WRITE access + bit = BPT_WRITE; + break; + case EXCEPTION_EXECUTE_FAULT: // failed EXECUTE access + bit = BPT_EXEC; + break; + } + return (bpt.type & bit) != 0; +} + +//-------------------------------------------------------------------------- +// returns 0-failure, 2-success +int idaapi winbase_debmod_t::dbg_add_page_bpt( + bpttype_t type, + ea_t ea, + int size) +{ + // only one page breakpoint per page is permitted + page_bpts_t::iterator p = find_page_bpt(ea, size); + if ( p != page_bpts.end() ) + return 0; // another page bpt exists + + // Find out the current page protections + MEMORY_BASIC_INFORMATION meminfo; + ea_t page_ea = calc_page_base(ea); + if ( !VirtualQueryEx(process_handle, (void *)(size_t)page_ea, + &meminfo, sizeof(meminfo)) ) + { + deberr("VirtualQueryEx"); + return 0; + } + + // Make sure the page is loaded + if ( (meminfo.State & MEM_FREE) != 0 ) + { + deberr("%a: the page has not been allocated", page_ea); + return 0; + } + + // According to MSDN documentation for VirtualQueryEx + // (...) + // AllocationProtect + // The memory protection option when the region was initially allocated. This member can be + // one of the memory protection constants or 0 if the caller does not have access. + // + // Unfortunately, there is no more information about why it my happen so, for now, I'm just + // returning an error. + if ( meminfo.Protect == 0 ) + { + deberr("%a: the page cannot be accessed", page_ea); + return 0; + } + + // Calculate new page protections + int aligned_len = align_up((ea-page_ea)+size, MEMORY_PAGE_SIZE); + int real_len = 0; + DWORD prot = meminfo.Protect; + if ( remove_page_protections(&prot, type, dep_policy, process_handle) ) + { // We have to set new protections + real_len = aligned_len; + } + + // Remember the new breakpoint + p = page_bpts.insert(std::make_pair(page_ea, pagebpt_data_t())).first; + pagebpt_data_t &bpt = p->second; + bpt.ea = ea; + bpt.user_len = size; + bpt.page_ea = page_ea; + bpt.aligned_len = aligned_len; + bpt.real_len = real_len; + bpt.old_prot = 0; + bpt.new_prot = prot; + bpt.type = type; + + // for PAGE_GUARD pages, no need to change the permissions, everything is fine already + if ( real_len == 0 ) + { + bpt.old_prot = meminfo.Protect; + return 2; + } + + return dbg_enable_page_bpt(p, true) ? 2 : 0; +} + +//-------------------------------------------------------------------------- +// returns true if changed *protect (in other words, if we have to mask +// the real page protections and return the original one) +bool winbase_debmod_t::mask_page_bpts( + ea_t startea, + ea_t endea, + uint32 *protect) +{ + // if we have page breakpoints, what we return must be changed to show the + // real segment privileges, instead of the new ones we applied for the bpt + int newprot = 0; + page_bpts_t::iterator p = page_bpts.begin(); + while ( p != page_bpts.end() ) + { + pagebpt_data_t &pbd = p->second; + if ( pbd.page_ea + pbd.real_len > startea ) + { + if ( pbd.page_ea >= endea ) + break; + if ( pbd.old_prot != 0 ) + { // bpt has been written to the process memory + if ( *protect == pbd.new_prot ) + { // return the old protection, before setting the page bpt + newprot = pbd.old_prot; + } + else + { + debdeb("mask_page_bpts: app changed our page protection for %a (expected: 0x%x, actual: 0x%x)\n", pbd.page_ea, pbd.new_prot, *protect); + // page protection has been changed by the application + DWORD prot = *protect; + if ( prot == PAGE_WRITECOPY && pbd.new_prot == PAGE_READWRITE + || prot == PAGE_EXECUTE_WRITECOPY && pbd.new_prot == PAGE_EXECUTE_READWRITE ) + { + // in some cases OS may restore WRITECOPY protection; do nothing in such cases since it works the same way for breakpoint purposes + debdeb(" ignoring changes to WRITECOPY protection\n"); + } + else if ( remove_page_protections(&prot, pbd.type, dep_policy, process_handle) ) + { + pbd.new_prot = prot; + pbd.old_prot = 0; // mark our bpt as non-written + debdeb(" will re-set protection to 0x%x\n", pbd.new_prot); + } + } + } + } + ++p; + } + if ( newprot != 0 ) + { + *protect = newprot; + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +// Page breakpoints modify the page protections to induce access violations. +// We must hide the modified page protections from IDA and report the original +// page protections. +// Second, the application may render a page bpt inactive by changing its page protections. +// In this case we must report to IDA the new page protections and also reactivate +// the page breakpoint. +void winbase_debmod_t::verify_page_protections( + meminfo_vec_t *areas, + const win32_prots_t &prots) +{ + QASSERT(624, areas->size() == prots.size()); + if ( page_bpts.empty() ) + return; + + for ( int i = 0; i < areas->size(); i++ ) + { + uint32 prot = prots[i]; + memory_info_t &a = areas->at(i); + if ( mask_page_bpts(a.start_ea, a.end_ea, &prot) ) + a.perm = win_prot_to_ida_perm(prot); + } + + // reactivate all disabled page bpts, if any + enable_page_bpts(true); +} + +//-------------------------------------------------------------------------- +#ifndef __X86__ +wow64_state_t winbase_debmod_t::check_wow64_process() +{ + if ( is_wow64 == WOW64_NONE ) + { + is_wow64 = check_wow64_handle(process_handle); + if ( is_wow64 > 0 ) + dmsg("WOW64 process has been detected (pid=%d)\n", pid); + } + return is_wow64; +} +#endif + +//-------------------------------------------------------------------------- +bool highdll_vec_t::has(eanat_t addr) const +{ + for ( int i = 0; i < size(); ++i ) + if ( (*this)[i].has(addr) ) + return true; + return false; +} + +//-------------------------------------------------------------------------- +bool highdll_vec_t::add(eanat_t addr, size_t sz, HANDLE h) +{ + if ( has(addr) ) + return false; + + // check removed: on new win10 we can have above 4GB: + // ntdll.dll, wow64.dll, wow64win.dll + // QASSERT(1491, size() < 2); + highdll_range_t &r = push_back(); + r.start = addr; + r.end = addr + sz; + r.handle = h; + return true; +} + +//-------------------------------------------------------------------------- +bool highdll_vec_t::add_high_module( + eanat_t addr, + size_t sz, + HANDLE h) +{ + if ( ea_t(addr) == addr ) + return false; + add(addr, sz, h); //-V779 unreachable code + return true; +} + +//-------------------------------------------------------------------------- +bool highdll_vec_t::del_high_module(HANDLE *h, eanat_t addr) +{ + for ( int i = 0; i < size(); ++i ) + { + const highdll_range_t &r = (*this)[i]; + if ( r.start == addr ) + { + if ( h != NULL ) + *h = r.handle; + erase(begin() + i); + return ea_t(addr) != addr; + } + } + return false; +} + +//-------------------------------------------------------------------------- +void idaapi winbase_debmod_t::dbg_term(void) +{ + is_wow64 = WOW64_NONE; + delete win_tool_help; + win_tool_help = NULL; +} + +//------------------------------------------------------------------------- +bool winbase_debmod_t::handle_process_start(pid_t _pid) +{ + debapp_attrs.addrsize = get_process_addrsize(_pid); + is64 = debapp_attrs.addrsize == 8; + + term_reg_ctx(); + init_reg_ctx(); + return true; +} + +//------------------------------------------------------------------------- +void winbase_debmod_t::cleanup(void) +{ + inherited::cleanup(); + is64 = false; +} + +//-------------------------------------------------------------------------- +// Check if we need to install a temporary breakpoint to workaround the +// 'freely running after syscall' problem. Exactly, the problem is the +// following: after single stepping over a "jmp far ptr" instruction in +// wow64cpu.dll for a 32bits process under a 64bits OS (Win7), the trap flag +// is lost. Probably, it's a bug in wow64cpu!CpuReturnFromSimulatedCode. +// +// So, if we find an instruction like "call large dword fs:XX" we add a +// temporary breakpoint at the next instruction and re-enable tracing +// when the breakpoint is reached. +bool winbase_debmod_t::check_for_call_large( + const debug_event_t *event, + HANDLE handle) +{ + if ( check_wow64_handle(handle) <= 0 ) + return false; + uchar buf[3]; + if ( dbg_read_memory(event->ea, buf, 3, NULL) == 3 ) + { + // is it the call large instruction? + if ( memcmp(buf, "\x64\xFF\x15", 3) == 0 ) + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +// Get process bitness: 32bit - 4, 64bit - 8, 0 - unknown +int idaapi winbase_debmod_t::get_process_bitness(int _pid) +{ + if ( _pid != -1 && _pid != GetCurrentProcessId() ) + { + if ( !winver.is_64bitOS() ) + return 4; + switch ( check_wow64_pid(_pid) ) + { + case WOW64_BAD: return 0; // bad process id + case WOW64_YES: return 4; // wow64 process, 32bit + case WOW64_NO: return 8; // regular 64bit process + default: break; + } + } + return IDA_ADDRESS_SIZE; +} + +//-------------------------------------------------------------------------- +static const char *str_bitness(int addrsize) +{ + switch ( addrsize ) + { + case 8: + return "[64]"; + case 4: + return "[32]"; + default: + return "[x]"; + } +} + +//-------------------------------------------------------------------------- +// this function may correct pinfo->addrsize +bool winbase_debmod_t::get_process_path( + ext_process_info_t *pinfo, + char *buf, + size_t bufsize) +{ + module_snapshot_t msnap(get_tool_help()); + MODULEENTRY32 me; + if ( !msnap.first(TH32CS_SNAPMODULE, pinfo->pid, &me) ) + { + if ( msnap.last_err() == ERROR_PARTIAL_COPY && pinfo->addrsize == 0 ) + { + // MSDN: If the specified process is a 64-bit process and the caller is a + // 32-bit process, error code is ERROR_PARTIAL_COPY + pinfo->addrsize = 8; + } + qstrncpy(buf, pinfo->name.c_str(), bufsize); + return false; + } + else + { + tchar_utf8(buf, me.szExePath, bufsize); + return true; + } +} + +//-------------------------------------------------------------------------- +win_tool_help_t *winbase_debmod_t::get_tool_help() +{ + if ( win_tool_help == NULL ) + win_tool_help = new win_tool_help_t; + return win_tool_help; +} + +//------------------------------------------------------------------------- +int winbase_debmod_t::get_process_addrsize(pid_t _pid) +{ + int addrsize = get_process_bitness(_pid); + return addrsize != 0 ? addrsize : IDA_ADDRESS_SIZE; +} + +//-------------------------------------------------------------------------- +//lint -e{1762} could be made const [in fact it cannot be made const in x64 mode] +bool winbase_debmod_t::is_ntdll_name(const char *path) +{ + const char *base_name = qbasename(path); + const char *ntdll_name = winver.is_NT() + ? "ntdll.dll" // NT + : "kernel32.dll"; // 9X/Me and KERNEL32.DLL + if ( strieq(base_name, ntdll_name) ) + return true; +#ifndef __X86__ + if ( winver.is_NT() + && check_wow64_process() == WOW64_YES + && strieq(base_name, "ntdll32.dll") ) + { + return true; + } +#endif + return false; +} + +//-------------------------------------------------------------------------- +//lint -esym(1762,winbase_debmod_t::build_process_ext_name) could be made const +void winbase_debmod_t::build_process_ext_name(ext_process_info_t *pinfo) +{ + char fullname[MAXSTR]; + if ( get_process_path(pinfo, fullname, sizeof(fullname)) + && pinfo->addrsize == 0 ) + { + // the WOW64 is optional on R2 x64 server + pinfo->addrsize = IDA_ADDRESS_SIZE; + } + pinfo->ext_name = str_bitness(pinfo->addrsize); + if ( !pinfo->ext_name.empty() ) + pinfo->ext_name += ' '; + pinfo->ext_name += fullname; +} + +//-------------------------------------------------------------------------- +int idaapi winbase_debmod_t::get_process_list(procvec_t *list, qstring *) +{ + int mypid = GetCurrentProcessId(); + list->clear(); + + process_snapshot_t psnap(get_tool_help()); + PROCESSENTRY32 pe32; + for ( bool ok = psnap.first(TH32CS_SNAPNOHEAPS, &pe32); ok; ok = psnap.next(&pe32) ) + { + if ( pe32.th32ProcessID != mypid ) + { + int addrsize = get_process_bitness(pe32.th32ProcessID); +#ifndef __EA64__ + if ( addrsize > 4 ) + continue; // skip 64bit processes, we cannot debug them because ea_t is 32bit +#endif + ext_process_info_t pinfo; + pinfo.pid = pe32.th32ProcessID; + pinfo.addrsize = addrsize; + tchar_utf8(&pinfo.name, pe32.szExeFile); + build_process_ext_name(&pinfo); + list->push_back(pinfo); + } + } + return list->size(); +} + +//-------------------------------------------------------------------------- +// Returns the file name assciated with pid +bool idaapi winbase_debmod_t::get_exec_fname(int _pid, char *buf, size_t bufsize) +{ + ext_process_info_t pinfo; + pinfo.pid = _pid; + pinfo.name.qclear(); + return get_process_path(&pinfo, buf, bufsize); +} + +//-------------------------------------------------------------------------- +win_tool_help_t *winbase_debmod_t::win_tool_help = NULL; +win_version_t winbase_debmod_t::winver; diff --git a/idasdk76/dbg/win32/winbase_debmod.h b/idasdk76/dbg/win32/winbase_debmod.h new file mode 100644 index 0000000..5b5c051 --- /dev/null +++ b/idasdk76/dbg/win32/winbase_debmod.h @@ -0,0 +1,185 @@ +#ifndef __WINBASE_HPP__ +#define __WINBASE_HPP__ + +// Base class for win32 and windbg modules + +using std::for_each; +using std::pair; +using std::make_pair; + +//-------------------------------------------------------------------------- +#define BASE_DEBUGGER_MODULE pc_debmod_t +#include "deb_pc.hpp" +#include "pc_debmod.h" +#define BPT_CODE_SIZE X86_BPT_SIZE +#include "win32_util.hpp" + +extern const TCHAR kernel32_dll[]; + +//-------------------------------------------------------------------------- +// DEP policies +enum dep_policy_t +{ + dp_always_off, + dp_always_on, + dp_opt_in, + dp_opt_out +}; + +//-------------------------------------------------------------------------- +enum attach_status_t +{ + as_none, // no attach to process requested + as_attaching, // waiting for CREATE_PROCESS_DEBUG_EVENT, indicating the process is attached + as_breakpoint, // waiting for first breakpoint, indicating the process was properly initialized and suspended + as_attached, // process was successfully attached + as_detaching, // waiting for next get_debug_event() request, to return the process as detached + as_attach_kernel, // attaching to kernel +}; + +// vector of win32 page protections +// we need this type because meminfo_t does not contain the original win32 protections +// but we need them to verify page bpts +typedef qvector<uint32> win32_prots_t; + +//-------------------------------------------------------------------------- +// When debugging WOW64 processes with ida32 we have to take into account +// ntdll.dll (and wow64*.dll), which are x64 files +// that can be loaded into high addresses (above 4GB) +// Since ea_t cannot represent such addresses, +// we use our own type to remember the DLL boundaries + +typedef size_t eanat_t; + +struct highdll_range_t +{ + eanat_t start; + eanat_t end; + HANDLE handle; + highdll_range_t() : start(0), end(0), handle(INVALID_HANDLE_VALUE) {} + bool has(eanat_t addr) const { return addr >= start && addr < end; } +}; +DECLARE_TYPE_AS_MOVABLE(highdll_range_t); + +struct highdll_vec_t : protected qvector<highdll_range_t> +{ +private: + size_t num_ntdlls; // count of actual ntdll*.dll modules in the list +public: + typedef qvector<highdll_range_t> inherited; + highdll_vec_t() : num_ntdlls(0) {} + void clear() { inherited::clear(); num_ntdlls = 0; } + size_t size() const { return inherited::size(); } + size_t count_ntdlls() const { return num_ntdlls; } + bool empty() const { return inherited::empty(); } + // return false if there is already a dll with such an address + bool add(eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE); + bool add_ntdll(eanat_t addr, size_t size, HANDLE h = INVALID_HANDLE_VALUE) + { + bool ok = add(addr, size, h); + if ( ok ) + num_ntdlls++; + return ok; + }; + // it returns true if the dll address doesn't fit in `ea_t` + bool add_high_module( + eanat_t addr, + size_t size, + HANDLE h = INVALID_HANDLE_VALUE); + // it returns true if the dll address doesn't fit to `ea_t` + bool del_high_module(HANDLE *h, eanat_t addr); + bool has(eanat_t addr) const; +}; + +//-------------------------------------------------------------------------- +class winbase_debmod_t: public BASE_DEBUGGER_MODULE +{ + typedef BASE_DEBUGGER_MODULE inherited; + wow64_state_t is_wow64 = WOW64_NONE; // use check_wow64_process() + +protected: + HANDLE process_handle = INVALID_HANDLE_VALUE; + dep_policy_t dep_policy = dp_always_off; + highdll_vec_t highdlls; + bool is64 = false; + + // local functions + bool mask_page_bpts(ea_t startea, ea_t endea, uint32 *protect); + void verify_page_protections(meminfo_vec_t *areas, const win32_prots_t &prots); + + winbase_debmod_t(void); + + // overridden virtual functions + bool idaapi dbg_enable_page_bpt(page_bpts_t::iterator p, bool enable); + int idaapi dbg_add_page_bpt(bpttype_t type, ea_t ea, int size); + bool check_for_call_large(const debug_event_t *event, HANDLE process_handle); +#ifndef __X86__ + wow64_state_t check_wow64_process(); +#else + wow64_state_t check_wow64_process() { return WOW64_NO; } +#endif + + int get_process_addrsize(pid_t pid); + + bool is_ntdll_name(const char *path); + + // return number of processes, -1 - not implemented + virtual int idaapi get_process_list(procvec_t *proclist, qstring *errbuf) override; + // return the file name assciated with pid + virtual bool idaapi get_exec_fname(int pid, char *buf, size_t bufsize) newapi; + // get process bitness: 32bit - 4, 64bit - 8, 0 - unknown + virtual int idaapi get_process_bitness(int pid) newapi; + + virtual void init_reg_ctx(void) newapi {} + virtual void term_reg_ctx(void) newapi {} + +public: + virtual void idaapi dbg_term(void) override; + + static win_tool_help_t *get_tool_help(); + static win_version_t winver; + +protected: + bool handle_process_start(pid_t _pid); + void cleanup(void); + +private: + void build_process_ext_name(ext_process_info_t *pinfo); + static bool get_process_path( + ext_process_info_t *pinfo, + char *buf, + size_t bufsize); + static bool remove_page_protections( + DWORD *p_input, + bpttype_t bpttype, + dep_policy_t dpolicy, + HANDLE proc_handle); + + static win_tool_help_t *win_tool_help; +}; + +bool should_fire_page_bpt(page_bpts_t::iterator p, ea_t ea, DWORD failed_access_type, ea_t pc, dep_policy_t dep_policy); + +#ifdef _PE_H_ +bool read_pe_header(peheader_t *pe); +#endif + +//------------------------------------------------------------------------- +inline void tchar_utf8(qstring *buf, TCHAR *tchar) +{ +#ifdef UNICODE + utf16_utf8(buf, tchar); +#else + acp_utf8(buf, tchar); +#endif +} + +//------------------------------------------------------------------------- +inline void tchar_utf8(char *buf, TCHAR *tchar, size_t bufsize) +{ + qstring utf8; + tchar_utf8(&utf8, tchar); + qstrncpy(buf, utf8.c_str(), bufsize); +} + +#endif diff --git a/idasdk76/defaults.mk b/idasdk76/defaults.mk new file mode 100644 index 0000000..f02e6e8 --- /dev/null +++ b/idasdk76/defaults.mk @@ -0,0 +1,131 @@ +############################################################################# +# versions and paths for various external libraries and utils + +ifdef __NT__ + # The following variables may have been set by vcvars.bat. You may + # also set them manually. The default installation directories are + # defined below in case these variables are not set. + # Note: the following paths use backslashes (and may also contain a + # trailing backslash) in order to conform to the variables + # exported by vcvars.bat. + + # Visual C++ 2017 Install Directory + VCINSTALLDIR ?= '$(PROGRAMFILES)\Microsoft Visual Studio\2017\Professional\VC\' + + # Visual C++ 2017 Tools Version + # Note: if this variable is not set, the default version is obtained + # in allmake.mak under "Visual C++ 2017 Tools Version". + # VCToolsVersion ?= '14.11.25503' + + # Windows SDK Install Directory + WindowsSdkDir ?= '$(PROGRAMFILES)\Windows Kits\10\' + + # Windows SDK version + # Note: if this variable is not set, the latest version is detected + # in allmake.mak under "Windows SDK Version". + # WindowsSDKVersion ?= '10.0.17134.0\' + + # Microsoft SDK v7.1A is only used for the win32 debugger server for + # Windows XP compatibility. + MSSDK71_PATH = '$(PROGRAMFILES)/Microsoft SDKs/Windows/v7.1A' +else ifdef __MAC__ + # oldest supported version of MacOSX + ifdef __ARM__ + MACOSX_DEPLOYMENT_TARGET = 11.0 + else + MACOSX_DEPLOYMENT_TARGET = 10.9 + endif +endif + +# Python +PYTHON_VERSION_MAJOR?=3 +PYTHON_VERSION_MINOR?=4 +PYTHON_VERNAME=python$(PYTHON_VERSION_MAJOR).$(PYTHON_VERSION_MINOR) + +# TODO clean this up +ifdef __NT__ + ifneq (,$(wildcard /cygdrive/c/Program\ Files/Python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)/python.exe)) + PYTHON_ROOT ?= C:/Program Files/Python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR) + else + ifeq ($(PYTHON_VERSION_MAJOR),2) + PYTHON_VERSUF=-x64 + endif + PYTHON_ROOT ?= $(SYSTEMDRIVE)/Python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR)$(PYTHON_VERSUF) + endif + PYTHON ?= "$(PYTHON_ROOT)/python.exe" +else + PYTHON ?= $(PYTHON_VERNAME) +endif + +# Qt +QTPROC-1=x64 +QTPROC-$(__ARM__)=arm64 +QTVER?=5.6.3-$(QTPROC-1) + +QTDIR-$(__LINUX__) = /usr/local/Qt/$(QTVER)/ +QTDIR-$(__MAC__) = /Users/Shared/Qt/$(QTVER)/ +QTDIR-$(__NT__) = $(SYSTEMDRIVE)/Qt/$(QTVER)/ +QTDIR ?= $(QTDIR-1) + +ifdef __NT__ + ifdef NDEBUG + QTSUFF=.dll + else + QTSUFF=d.dll + endif + QTLIBDIR=bin +else ifdef __LINUX__ + QTPREF=lib + QTSUFF=.so.5 + QTLIBDIR=lib +endif + +# SWiG +ifeq ($(PYTHON_VERSION_MAJOR),3) + SWIG_VERSION?=4.0.1 + ifdef __NT__ + SWIG_DIR_SUFFIX?=-py3-stable-abi-cygwin + else + SWIG_DIR_SUFFIX?=-py3-stable-abi + endif +else + SWIG_VERSION?=4.0.0 +endif +ifdef __NT__ + ifeq ($(PYTHON_VERSION_MAJOR),3) + SWIG_DISTRIBUTION_HAS_UNIX_LAYOUT:=1 + endif +else + SWIG_DISTRIBUTION_HAS_UNIX_LAYOUT:=1 +endif + +ifeq ($(SWIG_DISTRIBUTION_HAS_UNIX_LAYOUT),1) + ifdef USE_CCACHE + # we set CCACHE_DIR so as to not interfere with the system's ccache + # and we set CCACHE_CPP2 to prevent SWiG from printing a bunch of + # warnings due to re-using of the preprocessed source. + SWIG?=CCACHE_DIR='$${HOME}/.ccache-swig' CCACHE_CPP2=1 $(SWIG_HOME)/bin/ccache-swig $(SWIG_HOME)/bin/swig + else + SWIG?=$(SWIG_HOME)/bin/swig + endif + SWIG_INCLUDES?=-I$(SWIG_HOME)/share/swig/$(SWIG_VERSION)/python -I$(SWIG_HOME)/share/swig/$(SWIG_VERSION) +else + SWIG?=$(SWIG_HOME)/swig.exe + SWIG_INCLUDES?=-I$(SWIG_HOME)/Lib/python -I$(SWIG_HOME)/Lib +endif + +############################################################################# +# keep all paths in unix format, with forward slashes +ifeq ($(OS),Windows_NT) + # define: convert dos path to unix path by replacing backslashes by slashes + unixpath=$(subst \,/,$(1)) + + PYTHON_ROOT :=$(call unixpath,$(PYTHON_ROOT)) + PYTHON :=$(call unixpath,$(PYTHON)) + SWIG :=$(call unixpath,$(SWIG)) + QTDIR :=$(call unixpath,$(QTDIR)) +endif + +############################################################################# +# http://stackoverflow.com/questions/16467718/how-to-print-out-a-variable-in-makefile +.print-% : ; @echo $($*) diff --git a/idasdk76/include/allins.hpp b/idasdk76/include/allins.hpp new file mode 100644 index 0000000..e7973cf --- /dev/null +++ b/idasdk76/include/allins.hpp @@ -0,0 +1,21420 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +NN_null = 0, // Unknown Operation +NN_aaa, // ASCII Adjust after Addition +NN_aad, // ASCII Adjust AX before Division +NN_aam, // ASCII Adjust AX after Multiply +NN_aas, // ASCII Adjust AL after Subtraction +NN_adc, // Add with Carry +NN_add, // Add +NN_and, // Logical AND +NN_arpl, // Adjust RPL Field of Selector +NN_bound, // Check Array Index Against Bounds +NN_bsf, // Bit Scan Forward +NN_bsr, // Bit Scan Reverse +NN_bt, // Bit Test +NN_btc, // Bit Test and Complement +NN_btr, // Bit Test and Reset +NN_bts, // Bit Test and Set +NN_call, // Call Procedure +NN_callfi, // Indirect Call Far Procedure +NN_callni, // Indirect Call Near Procedure +NN_cbw, // AL -> AX (with sign) +NN_cwde, // AX -> EAX (with sign) +NN_cdqe, // EAX -> RAX (with sign) +NN_clc, // Clear Carry Flag +NN_cld, // Clear Direction Flag +NN_cli, // Clear Interrupt Flag +NN_clts, // Clear Task-Switched Flag in CR0 +NN_cmc, // Complement Carry Flag +NN_cmp, // Compare Two Operands +NN_cmps, // Compare Strings +NN_cwd, // AX -> DX:AX (with sign) +NN_cdq, // EAX -> EDX:EAX (with sign) +NN_cqo, // RAX -> RDX:RAX (with sign) +NN_daa, // Decimal Adjust AL after Addition +NN_das, // Decimal Adjust AL after Subtraction +NN_dec, // Decrement by 1 +NN_div, // Unsigned Divide +NN_enterw, // Make Stack Frame for Procedure Parameters +NN_enter, // Make Stack Frame for Procedure Parameters +NN_enterd, // Make Stack Frame for Procedure Parameters +NN_enterq, // Make Stack Frame for Procedure Parameters +NN_hlt, // Halt +NN_idiv, // Signed Divide +NN_imul, // Signed Multiply +NN_in, // Input from Port +NN_inc, // Increment by 1 +NN_ins, // Input Byte(s) from Port to String +NN_int, // Call to Interrupt Procedure +NN_into, // Call to Interrupt Procedure if Overflow Flag = 1 +NN_int3, // Trap to Debugger +NN_iretw, // Interrupt Return +NN_iret, // Interrupt Return +NN_iretd, // Interrupt Return (use32) +NN_iretq, // Interrupt Return (use64) +NN_ja, // Jump if Above (CF=0 & ZF=0) +NN_jae, // Jump if Above or Equal (CF=0) +NN_jb, // Jump if Below (CF=1) +NN_jbe, // Jump if Below or Equal (CF=1 | ZF=1) +NN_jc, // Jump if Carry (CF=1) +NN_jcxz, // Jump if CX is 0 +NN_jecxz, // Jump if ECX is 0 +NN_jrcxz, // Jump if RCX is 0 +NN_je, // Jump if Equal (ZF=1) +NN_jg, // Jump if Greater (ZF=0 & SF=OF) +NN_jge, // Jump if Greater or Equal (SF=OF) +NN_jl, // Jump if Less (SF!=OF) +NN_jle, // Jump if Less or Equal (ZF=1 | SF!=OF) +NN_jna, // Jump if Not Above (CF=1 | ZF=1) +NN_jnae, // Jump if Not Above or Equal (CF=1) +NN_jnb, // Jump if Not Below (CF=0) +NN_jnbe, // Jump if Not Below or Equal (CF=0 & ZF=0) +NN_jnc, // Jump if Not Carry (CF=0) +NN_jne, // Jump if Not Equal (ZF=0) +NN_jng, // Jump if Not Greater (ZF=1 | SF!=OF) +NN_jnge, // Jump if Not Greater or Equal (ZF=1) +NN_jnl, // Jump if Not Less (SF=OF) +NN_jnle, // Jump if Not Less or Equal (ZF=0 & SF=OF) +NN_jno, // Jump if Not Overflow (OF=0) +NN_jnp, // Jump if Not Parity (PF=0) +NN_jns, // Jump if Not Sign (SF=0) +NN_jnz, // Jump if Not Zero (ZF=0) +NN_jo, // Jump if Overflow (OF=1) +NN_jp, // Jump if Parity (PF=1) +NN_jpe, // Jump if Parity Even (PF=1) +NN_jpo, // Jump if Parity Odd (PF=0) +NN_js, // Jump if Sign (SF=1) +NN_jz, // Jump if Zero (ZF=1) +NN_jmp, // Jump +NN_jmpfi, // Indirect Far Jump +NN_jmpni, // Indirect Near Jump +NN_jmpshort, // Jump Short (not used) +NN_lahf, // Load Flags into AH Register +NN_lar, // Load Access Right Byte +NN_lea, // Load Effective Address +NN_leavew, // High Level Procedure Exit +NN_leave, // High Level Procedure Exit +NN_leaved, // High Level Procedure Exit +NN_leaveq, // High Level Procedure Exit +NN_lgdt, // Load Global Descriptor Table Register +NN_lidt, // Load Interrupt Descriptor Table Register +NN_lgs, // Load Full Pointer to GS:xx +NN_lss, // Load Full Pointer to SS:xx +NN_lds, // Load Full Pointer to DS:xx +NN_les, // Load Full Pointer to ES:xx +NN_lfs, // Load Full Pointer to FS:xx +NN_lldt, // Load Local Descriptor Table Register +NN_lmsw, // Load Machine Status Word +NN_lock, // Assert LOCK# Signal Prefix +NN_lods, // Load String +NN_loopw, // Loop while ECX != 0 +NN_loop, // Loop while CX != 0 +NN_loopd, // Loop while ECX != 0 +NN_loopq, // Loop while RCX != 0 +NN_loopwe, // Loop while CX != 0 and ZF=1 +NN_loope, // Loop while rCX != 0 and ZF=1 +NN_loopde, // Loop while ECX != 0 and ZF=1 +NN_loopqe, // Loop while RCX != 0 and ZF=1 +NN_loopwne, // Loop while CX != 0 and ZF=0 +NN_loopne, // Loop while rCX != 0 and ZF=0 +NN_loopdne, // Loop while ECX != 0 and ZF=0 +NN_loopqne, // Loop while RCX != 0 and ZF=0 +NN_lsl, // Load Segment Limit +NN_ltr, // Load Task Register +NN_mov, // Move Data +NN_movsp, // Move to/from Special Registers +NN_movs, // Move Byte(s) from String to String +NN_movsx, // Move with Sign-Extend +NN_movzx, // Move with Zero-Extend +NN_mul, // Unsigned Multiplication of AL or AX +NN_neg, // Two's Complement Negation +NN_nop, // No Operation +NN_not, // One's Complement Negation +NN_or, // Logical Inclusive OR +NN_out, // Output to Port +NN_outs, // Output Byte(s) to Port +NN_pop, // Pop a word from the Stack +NN_popaw, // Pop all General Registers +NN_popa, // Pop all General Registers +NN_popad, // Pop all General Registers (use32) +NN_popaq, // Pop all General Registers (use64) +NN_popfw, // Pop Stack into Flags Register +NN_popf, // Pop Stack into Flags Register +NN_popfd, // Pop Stack into Eflags Register +NN_popfq, // Pop Stack into Rflags Register +NN_push, // Push Operand onto the Stack +NN_pushaw, // Push all General Registers +NN_pusha, // Push all General Registers +NN_pushad, // Push all General Registers (use32) +NN_pushaq, // Push all General Registers (use64) +NN_pushfw, // Push Flags Register onto the Stack +NN_pushf, // Push Flags Register onto the Stack +NN_pushfd, // Push Flags Register onto the Stack (use32) +NN_pushfq, // Push Flags Register onto the Stack (use64) +NN_rcl, // Rotate Through Carry Left +NN_rcr, // Rotate Through Carry Right +NN_rol, // Rotate Left +NN_ror, // Rotate Right +NN_rep, // Repeat String Operation +NN_repe, // Repeat String Operation while ZF=1 +NN_repne, // Repeat String Operation while ZF=0 +NN_retn, // Return Near from Procedure +NN_retf, // Return Far from Procedure +NN_sahf, // Store AH into Flags Register +NN_sal, // Shift Arithmetic Left +NN_sar, // Shift Arithmetic Right +NN_shl, // Shift Logical Left +NN_shr, // Shift Logical Right +NN_sbb, // Integer Subtraction with Borrow +NN_scas, // Compare String +NN_seta, // Set Byte if Above (CF=0 & ZF=0) +NN_setae, // Set Byte if Above or Equal (CF=0) +NN_setb, // Set Byte if Below (CF=1) +NN_setbe, // Set Byte if Below or Equal (CF=1 | ZF=1) +NN_setc, // Set Byte if Carry (CF=1) +NN_sete, // Set Byte if Equal (ZF=1) +NN_setg, // Set Byte if Greater (ZF=0 & SF=OF) +NN_setge, // Set Byte if Greater or Equal (SF=OF) +NN_setl, // Set Byte if Less (SF!=OF) +NN_setle, // Set Byte if Less or Equal (ZF=1 | SF!=OF) +NN_setna, // Set Byte if Not Above (CF=1 | ZF=1) +NN_setnae, // Set Byte if Not Above or Equal (CF=1) +NN_setnb, // Set Byte if Not Below (CF=0) +NN_setnbe, // Set Byte if Not Below or Equal (CF=0 & ZF=0) +NN_setnc, // Set Byte if Not Carry (CF=0) +NN_setne, // Set Byte if Not Equal (ZF=0) +NN_setng, // Set Byte if Not Greater (ZF=1 | SF!=OF) +NN_setnge, // Set Byte if Not Greater or Equal (ZF=1) +NN_setnl, // Set Byte if Not Less (SF=OF) +NN_setnle, // Set Byte if Not Less or Equal (ZF=0 & SF=OF) +NN_setno, // Set Byte if Not Overflow (OF=0) +NN_setnp, // Set Byte if Not Parity (PF=0) +NN_setns, // Set Byte if Not Sign (SF=0) +NN_setnz, // Set Byte if Not Zero (ZF=0) +NN_seto, // Set Byte if Overflow (OF=1) +NN_setp, // Set Byte if Parity (PF=1) +NN_setpe, // Set Byte if Parity Even (PF=1) +NN_setpo, // Set Byte if Parity Odd (PF=0) +NN_sets, // Set Byte if Sign (SF=1) +NN_setz, // Set Byte if Zero (ZF=1) +NN_sgdt, // Store Global Descriptor Table Register +NN_sidt, // Store Interrupt Descriptor Table Register +NN_shld, // Double Precision Shift Left +NN_shrd, // Double Precision Shift Right +NN_sldt, // Store Local Descriptor Table Register +NN_smsw, // Store Machine Status Word +NN_stc, // Set Carry Flag +NN_std, // Set Direction Flag +NN_sti, // Set Interrupt Flag +NN_stos, // Store String +NN_str, // Store Task Register +NN_sub, // Integer Subtraction +NN_test, // Logical Compare +NN_verr, // Verify a Segment for Reading +NN_verw, // Verify a Segment for Writing +NN_wait, // Wait until BUSY# Pin is Inactive (HIGH) +NN_xchg, // Exchange Register/Memory with Register +NN_xlat, // Table Lookup Translation +NN_xor, // Logical Exclusive OR + +// +// 486 instructions +// + +NN_cmpxchg, // Compare and Exchange +NN_bswap, // Swap bits in EAX +NN_xadd, // t<-dest; dest<-src+dest; src<-t +NN_invd, // Invalidate Data Cache +NN_wbinvd, // Invalidate Data Cache (write changes) +NN_invlpg, // Invalidate TLB entry + +// +// Pentium instructions +// + +NN_rdmsr, // Read Machine Status Register +NN_wrmsr, // Write Machine Status Register +NN_cpuid, // Get CPU ID +NN_cmpxchg8b, // Compare and Exchange Eight Bytes +NN_rdtsc, // Read Time Stamp Counter +NN_rsm, // Resume from System Management Mode + +// +// Pentium Pro instructions +// + +NN_cmova, // Move if Above (CF=0 & ZF=0) +NN_cmovb, // Move if Below (CF=1) +NN_cmovbe, // Move if Below or Equal (CF=1 | ZF=1) +NN_cmovg, // Move if Greater (ZF=0 & SF=OF) +NN_cmovge, // Move if Greater or Equal (SF=OF) +NN_cmovl, // Move if Less (SF!=OF) +NN_cmovle, // Move if Less or Equal (ZF=1 | SF!=OF) +NN_cmovnb, // Move if Not Below (CF=0) +NN_cmovno, // Move if Not Overflow (OF=0) +NN_cmovnp, // Move if Not Parity (PF=0) +NN_cmovns, // Move if Not Sign (SF=0) +NN_cmovnz, // Move if Not Zero (ZF=0) +NN_cmovo, // Move if Overflow (OF=1) +NN_cmovp, // Move if Parity (PF=1) +NN_cmovs, // Move if Sign (SF=1) +NN_cmovz, // Move if Zero (ZF=1) +NN_fcmovb, // Floating Move if Below +NN_fcmove, // Floating Move if Equal +NN_fcmovbe, // Floating Move if Below or Equal +NN_fcmovu, // Floating Move if Unordered +NN_fcmovnb, // Floating Move if Not Below +NN_fcmovne, // Floating Move if Not Equal +NN_fcmovnbe, // Floating Move if Not Below or Equal +NN_fcmovnu, // Floating Move if Not Unordered +NN_fcomi, // FP Compare, result in EFLAGS +NN_fucomi, // FP Unordered Compare, result in EFLAGS +NN_fcomip, // FP Compare, result in EFLAGS, pop stack +NN_fucomip, // FP Unordered Compare, result in EFLAGS, pop stack +NN_rdpmc, // Read Performance Monitor Counter + +// +// FPP instructuions +// + +NN_fld, // Load Real +NN_fst, // Store Real +NN_fstp, // Store Real and Pop +NN_fxch, // Exchange Registers +NN_fild, // Load Integer +NN_fist, // Store Integer +NN_fistp, // Store Integer and Pop +NN_fbld, // Load BCD +NN_fbstp, // Store BCD and Pop +NN_fadd, // Add Real +NN_faddp, // Add Real and Pop +NN_fiadd, // Add Integer +NN_fsub, // Subtract Real +NN_fsubp, // Subtract Real and Pop +NN_fisub, // Subtract Integer +NN_fsubr, // Subtract Real Reversed +NN_fsubrp, // Subtract Real Reversed and Pop +NN_fisubr, // Subtract Integer Reversed +NN_fmul, // Multiply Real +NN_fmulp, // Multiply Real and Pop +NN_fimul, // Multiply Integer +NN_fdiv, // Divide Real +NN_fdivp, // Divide Real and Pop +NN_fidiv, // Divide Integer +NN_fdivr, // Divide Real Reversed +NN_fdivrp, // Divide Real Reversed and Pop +NN_fidivr, // Divide Integer Reversed +NN_fsqrt, // Square Root +NN_fscale, // Scale: st(0) <- st(0) * 2^st(1) +NN_fprem, // Partial Remainder +NN_frndint, // Round to Integer +NN_fxtract, // Extract exponent and significand +NN_fabs, // Absolute value +NN_fchs, // Change Sign +NN_fcom, // Compare Real +NN_fcomp, // Compare Real and Pop +NN_fcompp, // Compare Real and Pop Twice +NN_ficom, // Compare Integer +NN_ficomp, // Compare Integer and Pop +NN_ftst, // Test +NN_fxam, // Examine +NN_fptan, // Partial tangent +NN_fpatan, // Partial arctangent +NN_f2xm1, // 2^x - 1 +NN_fyl2x, // Y * lg2(X) +NN_fyl2xp1, // Y * lg2(X+1) +NN_fldz, // Load +0.0 +NN_fld1, // Load +1.0 +NN_fldpi, // Load PI=3.14... +NN_fldl2t, // Load lg2(10) +NN_fldl2e, // Load lg2(e) +NN_fldlg2, // Load lg10(2) +NN_fldln2, // Load ln(2) +NN_finit, // Initialize Processor +NN_fninit, // Initialize Processor (no wait) +NN_fsetpm, // Set Protected Mode +NN_fldcw, // Load Control Word +NN_fstcw, // Store Control Word +NN_fnstcw, // Store Control Word (no wait) +NN_fstsw, // Store Status Word +NN_fnstsw, // Store Status Word (no wait) +NN_fclex, // Clear Exceptions +NN_fnclex, // Clear Exceptions (no wait) +NN_fstenv, // Store Environment +NN_fnstenv, // Store Environment (no wait) +NN_fldenv, // Load Environment +NN_fsave, // Save State +NN_fnsave, // Save State (no wait) +NN_frstor, // Restore State +NN_fincstp, // Increment Stack Pointer +NN_fdecstp, // Decrement Stack Pointer +NN_ffree, // Free Register +NN_fnop, // No Operation +NN_feni, // (8087 only) +NN_fneni, // (no wait) (8087 only) +NN_fdisi, // (8087 only) +NN_fndisi, // (no wait) (8087 only) + +// +// 80387 instructions +// + +NN_fprem1, // Partial Remainder ( < half ) +NN_fsincos, // t<-cos(st); st<-sin(st); push t +NN_fsin, // Sine +NN_fcos, // Cosine +NN_fucom, // Compare Unordered Real +NN_fucomp, // Compare Unordered Real and Pop +NN_fucompp, // Compare Unordered Real and Pop Twice + +// +// Instructions added 28.02.96 +// + +NN_setalc, // Set AL to Carry Flag +NN_svdc, // Save Register and Descriptor +NN_rsdc, // Restore Register and Descriptor +NN_svldt, // Save LDTR and Descriptor +NN_rsldt, // Restore LDTR and Descriptor +NN_svts, // Save TR and Descriptor +NN_rsts, // Restore TR and Descriptor +NN_icebp, // ICE Break Point +NN_loadall, // Load the entire CPU state from ES:EDI + +// +// MMX instructions +// + +NN_emms, // Empty MMX state +NN_movd, // Move 32 bits +NN_movq, // Move 64 bits +NN_packsswb, // Pack with Signed Saturation (Word->Byte) +NN_packssdw, // Pack with Signed Saturation (Dword->Word) +NN_packuswb, // Pack with Unsigned Saturation (Word->Byte) +NN_paddb, // Packed Add Byte +NN_paddw, // Packed Add Word +NN_paddd, // Packed Add Dword +NN_paddsb, // Packed Add with Saturation (Byte) +NN_paddsw, // Packed Add with Saturation (Word) +NN_paddusb, // Packed Add Unsigned with Saturation (Byte) +NN_paddusw, // Packed Add Unsigned with Saturation (Word) +NN_pand, // Bitwise Logical And +NN_pandn, // Bitwise Logical And Not +NN_pcmpeqb, // Packed Compare for Equal (Byte) +NN_pcmpeqw, // Packed Compare for Equal (Word) +NN_pcmpeqd, // Packed Compare for Equal (Dword) +NN_pcmpgtb, // Packed Compare for Greater Than (Byte) +NN_pcmpgtw, // Packed Compare for Greater Than (Word) +NN_pcmpgtd, // Packed Compare for Greater Than (Dword) +NN_pmaddwd, // Packed Multiply and Add +NN_pmulhw, // Packed Multiply High +NN_pmullw, // Packed Multiply Low +NN_por, // Bitwise Logical Or +NN_psllw, // Packed Shift Left Logical (Word) +NN_pslld, // Packed Shift Left Logical (Dword) +NN_psllq, // Packed Shift Left Logical (Qword) +NN_psraw, // Packed Shift Right Arithmetic (Word) +NN_psrad, // Packed Shift Right Arithmetic (Dword) +NN_psrlw, // Packed Shift Right Logical (Word) +NN_psrld, // Packed Shift Right Logical (Dword) +NN_psrlq, // Packed Shift Right Logical (Qword) +NN_psubb, // Packed Subtract Byte +NN_psubw, // Packed Subtract Word +NN_psubd, // Packed Subtract Dword +NN_psubsb, // Packed Subtract with Saturation (Byte) +NN_psubsw, // Packed Subtract with Saturation (Word) +NN_psubusb, // Packed Subtract Unsigned with Saturation (Byte) +NN_psubusw, // Packed Subtract Unsigned with Saturation (Word) +NN_punpckhbw, // Unpack High Packed Data (Byte->Word) +NN_punpckhwd, // Unpack High Packed Data (Word->Dword) +NN_punpckhdq, // Unpack High Packed Data (Dword->Qword) +NN_punpcklbw, // Unpack Low Packed Data (Byte->Word) +NN_punpcklwd, // Unpack Low Packed Data (Word->Dword) +NN_punpckldq, // Unpack Low Packed Data (Dword->Qword) +NN_pxor, // Bitwise Logical Exclusive Or + +// +// Undocumented Deschutes processor instructions +// + +NN_fxsave, // Fast save FP context +NN_fxrstor, // Fast restore FP context + +// Pentium II instructions + +NN_sysenter, // Fast Transition to System Call Entry Point +NN_sysexit, // Fast Transition from System Call Entry Point + +// 3DNow! instructions + +NN_pavgusb, // Packed 8-bit Unsigned Integer Averaging +NN_pfadd, // Packed Floating-Point Addition +NN_pfsub, // Packed Floating-Point Subtraction +NN_pfsubr, // Packed Floating-Point Reverse Subtraction +NN_pfacc, // Packed Floating-Point Accumulate +NN_pfcmpge, // Packed Floating-Point Comparison, Greater or Equal +NN_pfcmpgt, // Packed Floating-Point Comparison, Greater +NN_pfcmpeq, // Packed Floating-Point Comparison, Equal +NN_pfmin, // Packed Floating-Point Minimum +NN_pfmax, // Packed Floating-Point Maximum +NN_pi2fd, // Packed 32-bit Integer to Floating-Point +NN_pf2id, // Packed Floating-Point to 32-bit Integer +NN_pfrcp, // Packed Floating-Point Reciprocal Approximation +NN_pfrsqrt, // Packed Floating-Point Reciprocal Square Root Approximation +NN_pfmul, // Packed Floating-Point Multiplication +NN_pfrcpit1, // Packed Floating-Point Reciprocal First Iteration Step +NN_pfrsqit1, // Packed Floating-Point Reciprocal Square Root First Iteration Step +NN_pfrcpit2, // Packed Floating-Point Reciprocal Second Iteration Step +NN_pmulhrw, // Packed Floating-Point 16-bit Integer Multiply with rounding +NN_femms, // Faster entry/exit of the MMX or floating-point state +NN_prefetch, // Prefetch at least a 32-byte line into L1 data cache +NN_prefetchw, // Prefetch processor cache line into L1 data cache (mark as modified) + + +// Pentium III instructions + +NN_addps, // Packed Single-FP Add +NN_addss, // Scalar Single-FP Add +NN_andnps, // Bitwise Logical And Not for Single-FP +NN_andps, // Bitwise Logical And for Single-FP +NN_cmpps, // Packed Single-FP Compare +NN_cmpss, // Scalar Single-FP Compare +NN_comiss, // Scalar Ordered Single-FP Compare and Set EFLAGS +NN_cvtpi2ps, // Packed signed INT32 to Packed Single-FP conversion +NN_cvtps2pi, // Packed Single-FP to Packed INT32 conversion +NN_cvtsi2ss, // Scalar signed INT32 to Single-FP conversion +NN_cvtss2si, // Scalar Single-FP to signed INT32 conversion +NN_cvttps2pi, // Packed Single-FP to Packed INT32 conversion (truncate) +NN_cvttss2si, // Scalar Single-FP to signed INT32 conversion (truncate) +NN_divps, // Packed Single-FP Divide +NN_divss, // Scalar Single-FP Divide +NN_ldmxcsr, // Load Streaming SIMD Extensions Technology Control/Status Register +NN_maxps, // Packed Single-FP Maximum +NN_maxss, // Scalar Single-FP Maximum +NN_minps, // Packed Single-FP Minimum +NN_minss, // Scalar Single-FP Minimum +NN_movaps, // Move Aligned Four Packed Single-FP +NN_movhlps, // Move High to Low Packed Single-FP +NN_movhps, // Move High Packed Single-FP +NN_movlhps, // Move Low to High Packed Single-FP +NN_movlps, // Move Low Packed Single-FP +NN_movmskps, // Move Mask to Register +NN_movss, // Move Scalar Single-FP +NN_movups, // Move Unaligned Four Packed Single-FP +NN_mulps, // Packed Single-FP Multiply +NN_mulss, // Scalar Single-FP Multiply +NN_orps, // Bitwise Logical OR for Single-FP Data +NN_rcpps, // Packed Single-FP Reciprocal +NN_rcpss, // Scalar Single-FP Reciprocal +NN_rsqrtps, // Packed Single-FP Square Root Reciprocal +NN_rsqrtss, // Scalar Single-FP Square Root Reciprocal +NN_shufps, // Shuffle Single-FP +NN_sqrtps, // Packed Single-FP Square Root +NN_sqrtss, // Scalar Single-FP Square Root +NN_stmxcsr, // Store Streaming SIMD Extensions Technology Control/Status Register +NN_subps, // Packed Single-FP Subtract +NN_subss, // Scalar Single-FP Subtract +NN_ucomiss, // Scalar Unordered Single-FP Compare and Set EFLAGS +NN_unpckhps, // Unpack High Packed Single-FP Data +NN_unpcklps, // Unpack Low Packed Single-FP Data +NN_xorps, // Bitwise Logical XOR for Single-FP Data +NN_pavgb, // Packed Average (Byte) +NN_pavgw, // Packed Average (Word) +NN_pextrw, // Extract Word +NN_pinsrw, // Insert Word +NN_pmaxsw, // Packed Signed Integer Word Maximum +NN_pmaxub, // Packed Unsigned Integer Byte Maximum +NN_pminsw, // Packed Signed Integer Word Minimum +NN_pminub, // Packed Unsigned Integer Byte Minimum +NN_pmovmskb, // Move Byte Mask to Integer +NN_pmulhuw, // Packed Multiply High Unsigned +NN_psadbw, // Packed Sum of Absolute Differences +NN_pshufw, // Packed Shuffle Word +NN_maskmovq, // Byte Mask write +NN_movntps, // Move Aligned Four Packed Single-FP Non Temporal +NN_movntq, // Move 64 Bits Non Temporal +NN_prefetcht0, // Prefetch to all cache levels +NN_prefetcht1, // Prefetch to all cache levels +NN_prefetcht2, // Prefetch to L2 cache +NN_prefetchnta, // Prefetch to L1 cache +NN_sfence, // Store Fence + +// Pentium III Pseudo instructions + +NN_cmpeqps, // Packed Single-FP Compare EQ +NN_cmpltps, // Packed Single-FP Compare LT +NN_cmpleps, // Packed Single-FP Compare LE +NN_cmpunordps, // Packed Single-FP Compare UNORD +NN_cmpneqps, // Packed Single-FP Compare NOT EQ +NN_cmpnltps, // Packed Single-FP Compare NOT LT +NN_cmpnleps, // Packed Single-FP Compare NOT LE +NN_cmpordps, // Packed Single-FP Compare ORDERED +NN_cmpeqss, // Scalar Single-FP Compare EQ +NN_cmpltss, // Scalar Single-FP Compare LT +NN_cmpless, // Scalar Single-FP Compare LE +NN_cmpunordss, // Scalar Single-FP Compare UNORD +NN_cmpneqss, // Scalar Single-FP Compare NOT EQ +NN_cmpnltss, // Scalar Single-FP Compare NOT LT +NN_cmpnless, // Scalar Single-FP Compare NOT LE +NN_cmpordss, // Scalar Single-FP Compare ORDERED + +// AMD K7 instructions + +NN_pf2iw, // Packed Floating-Point to Integer with Sign Extend +NN_pfnacc, // Packed Floating-Point Negative Accumulate +NN_pfpnacc, // Packed Floating-Point Mixed Positive-Negative Accumulate +NN_pi2fw, // Packed 16-bit Integer to Floating-Point +NN_pswapd, // Packed Swap Double Word + +// Undocumented FP instructions (thanks to norbert.juffa@amd.com) + +NN_fstp1, // Alias of Store Real and Pop +NN_fcom2, // Alias of Compare Real +NN_fcomp3, // Alias of Compare Real and Pop +NN_fxch4, // Alias of Exchange Registers +NN_fcomp5, // Alias of Compare Real and Pop +NN_ffreep, // Free Register and Pop +NN_fxch7, // Alias of Exchange Registers +NN_fstp8, // Alias of Store Real and Pop +NN_fstp9, // Alias of Store Real and Pop + +// Pentium 4 instructions + +NN_addpd, // Add Packed Double-Precision Floating-Point Values +NN_addsd, // Add Scalar Double-Precision Floating-Point Values +NN_andnpd, // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values +NN_andpd, // Bitwise Logical AND of Packed Double-Precision Floating-Point Values +NN_clflush, // Flush Cache Line +NN_cmppd, // Compare Packed Double-Precision Floating-Point Values +NN_cmpsd, // Compare Scalar Double-Precision Floating-Point Values +NN_comisd, // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS +NN_cvtdq2pd, // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values +NN_cvtdq2ps, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values +NN_cvtpd2dq, // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers +NN_cvtpd2pi, // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers +NN_cvtpd2ps, // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values +NN_cvtpi2pd, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values +NN_cvtps2dq, // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers +NN_cvtps2pd, // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values +NN_cvtsd2si, // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer +NN_cvtsd2ss, // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value +NN_cvtsi2sd, // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value +NN_cvtss2sd, // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value +NN_cvttpd2dq, // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers +NN_cvttpd2pi, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers +NN_cvttps2dq, // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers +NN_cvttsd2si, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer +NN_divpd, // Divide Packed Double-Precision Floating-Point Values +NN_divsd, // Divide Scalar Double-Precision Floating-Point Values +NN_lfence, // Load Fence +NN_maskmovdqu, // Store Selected Bytes of Double Quadword +NN_maxpd, // Return Maximum Packed Double-Precision Floating-Point Values +NN_maxsd, // Return Maximum Scalar Double-Precision Floating-Point Value +NN_mfence, // Memory Fence +NN_minpd, // Return Minimum Packed Double-Precision Floating-Point Values +NN_minsd, // Return Minimum Scalar Double-Precision Floating-Point Value +NN_movapd, // Move Aligned Packed Double-Precision Floating-Point Values +NN_movdq2q, // Move Quadword from XMM to MMX Register +NN_movdqa, // Move Aligned Double Quadword +NN_movdqu, // Move Unaligned Double Quadword +NN_movhpd, // Move High Packed Double-Precision Floating-Point Values +NN_movlpd, // Move Low Packed Double-Precision Floating-Point Values +NN_movmskpd, // Extract Packed Double-Precision Floating-Point Sign Mask +NN_movntdq, // Store Double Quadword Using Non-Temporal Hint +NN_movnti, // Store Doubleword Using Non-Temporal Hint +NN_movntpd, // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint +NN_movq2dq, // Move Quadword from MMX to XMM Register +NN_movsd, // Move Scalar Double-Precision Floating-Point Values +NN_movupd, // Move Unaligned Packed Double-Precision Floating-Point Values +NN_mulpd, // Multiply Packed Double-Precision Floating-Point Values +NN_mulsd, // Multiply Scalar Double-Precision Floating-Point Values +NN_orpd, // Bitwise Logical OR of Double-Precision Floating-Point Values +NN_paddq, // Add Packed Quadword Integers +NN_pause, // Spin Loop Hint +NN_pmuludq, // Multiply Packed Unsigned Doubleword Integers +NN_pshufd, // Shuffle Packed Doublewords +NN_pshufhw, // Shuffle Packed High Words +NN_pshuflw, // Shuffle Packed Low Words +NN_pslldq, // Shift Double Quadword Left Logical +NN_psrldq, // Shift Double Quadword Right Logical +NN_psubq, // Subtract Packed Quadword Integers +NN_punpckhqdq, // Unpack High Data +NN_punpcklqdq, // Unpack Low Data +NN_shufpd, // Shuffle Packed Double-Precision Floating-Point Values +NN_sqrtpd, // Compute Square Roots of Packed Double-Precision Floating-Point Values +NN_sqrtsd, // Compute Square Rootof Scalar Double-Precision Floating-Point Value +NN_subpd, // Subtract Packed Double-Precision Floating-Point Values +NN_subsd, // Subtract Scalar Double-Precision Floating-Point Values +NN_ucomisd, // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS +NN_unpckhpd, // Unpack and Interleave High Packed Double-Precision Floating-Point Values +NN_unpcklpd, // Unpack and Interleave Low Packed Double-Precision Floating-Point Values +NN_xorpd, // Bitwise Logical OR of Double-Precision Floating-Point Values + +// AMD syscall/sysret instructions + +NN_syscall, // Low latency system call +NN_sysret, // Return from system call + +// AMD64 instructions + +NN_swapgs, // Exchange GS base with KernelGSBase MSR + +// New Pentium instructions (SSE3) + +NN_movddup, // Move One Double-FP and Duplicate +NN_movshdup, // Move Packed Single-FP High and Duplicate +NN_movsldup, // Move Packed Single-FP Low and Duplicate + +// Missing AMD64 instructions + +NN_movsxd, // Move with Sign-Extend Doubleword +NN_cmpxchg16b, // Compare and Exchange 16 Bytes + +// SSE3 instructions + +NN_addsubpd, // Add /Sub packed DP FP numbers +NN_addsubps, // Add /Sub packed SP FP numbers +NN_haddpd, // Add horizontally packed DP FP numbers +NN_haddps, // Add horizontally packed SP FP numbers +NN_hsubpd, // Sub horizontally packed DP FP numbers +NN_hsubps, // Sub horizontally packed SP FP numbers +NN_monitor, // Set up a linear address range to be monitored by hardware +NN_mwait, // Wait until write-back store performed within the range specified by the MONITOR instruction +NN_fisttp, // Store ST in intXX (chop) and pop +NN_lddqu, // Load unaligned integer 128-bit + +// SSSE3 instructions + +NN_psignb, // Packed SIGN Byte +NN_psignw, // Packed SIGN Word +NN_psignd, // Packed SIGN Doubleword +NN_pshufb, // Packed Shuffle Bytes +NN_pmulhrsw, // Packed Multiply High with Round and Scale +NN_pmaddubsw, // Multiply and Add Packed Signed and Unsigned Bytes +NN_phsubsw, // Packed Horizontal Subtract and Saturate +NN_phaddsw, // Packed Horizontal Add and Saturate +NN_phaddw, // Packed Horizontal Add Word +NN_phaddd, // Packed Horizontal Add Doubleword +NN_phsubw, // Packed Horizontal Subtract Word +NN_phsubd, // Packed Horizontal Subtract Doubleword +NN_palignr, // Packed Align Right +NN_pabsb, // Packed Absolute Value Byte +NN_pabsw, // Packed Absolute Value Word +NN_pabsd, // Packed Absolute Value Doubleword + +// VMX instructions + +NN_vmcall, // Call to VM Monitor +NN_vmclear, // Clear Virtual Machine Control Structure +NN_vmlaunch, // Launch Virtual Machine +NN_vmresume, // Resume Virtual Machine +NN_vmptrld, // Load Pointer to Virtual Machine Control Structure +NN_vmptrst, // Store Pointer to Virtual Machine Control Structure +NN_vmread, // Read Field from Virtual Machine Control Structure +NN_vmwrite, // Write Field from Virtual Machine Control Structure +NN_vmxoff, // Leave VMX Operation +NN_vmxon, // Enter VMX Operation + +// Undefined Instruction + +NN_ud2, // Undefined Instruction + +// Added with x86-64 + +NN_rdtscp, // Read Time-Stamp Counter and Processor ID + +// Geode LX 3DNow! extensions + +NN_pfrcpv, // Reciprocal Approximation for a Pair of 32-bit Floats +NN_pfrsqrtv, // Reciprocal Square Root Approximation for a Pair of 32-bit Floats + +// SSE2 pseudoinstructions + +NN_cmpeqpd, // Packed Double-FP Compare EQ +NN_cmpltpd, // Packed Double-FP Compare LT +NN_cmplepd, // Packed Double-FP Compare LE +NN_cmpunordpd, // Packed Double-FP Compare UNORD +NN_cmpneqpd, // Packed Double-FP Compare NOT EQ +NN_cmpnltpd, // Packed Double-FP Compare NOT LT +NN_cmpnlepd, // Packed Double-FP Compare NOT LE +NN_cmpordpd, // Packed Double-FP Compare ORDERED +NN_cmpeqsd, // Scalar Double-FP Compare EQ +NN_cmpltsd, // Scalar Double-FP Compare LT +NN_cmplesd, // Scalar Double-FP Compare LE +NN_cmpunordsd, // Scalar Double-FP Compare UNORD +NN_cmpneqsd, // Scalar Double-FP Compare NOT EQ +NN_cmpnltsd, // Scalar Double-FP Compare NOT LT +NN_cmpnlesd, // Scalar Double-FP Compare NOT LE +NN_cmpordsd, // Scalar Double-FP Compare ORDERED + +// SSSE4.1 instructions + +NN_blendpd, // Blend Packed Double Precision Floating-Point Values +NN_blendps, // Blend Packed Single Precision Floating-Point Values +NN_blendvpd, // Variable Blend Packed Double Precision Floating-Point Values +NN_blendvps, // Variable Blend Packed Single Precision Floating-Point Values +NN_dppd, // Dot Product of Packed Double Precision Floating-Point Values +NN_dpps, // Dot Product of Packed Single Precision Floating-Point Values +NN_extractps, // Extract Packed Single Precision Floating-Point Value +NN_insertps, // Insert Packed Single Precision Floating-Point Value +NN_movntdqa, // Load Double Quadword Non-Temporal Aligned Hint +NN_mpsadbw, // Compute Multiple Packed Sums of Absolute Difference +NN_packusdw, // Pack with Unsigned Saturation +NN_pblendvb, // Variable Blend Packed Bytes +NN_pblendw, // Blend Packed Words +NN_pcmpeqq, // Compare Packed Qword Data for Equal +NN_pextrb, // Extract Byte +NN_pextrd, // Extract Dword +NN_pextrq, // Extract Qword +NN_phminposuw, // Packed Horizontal Word Minimum +NN_pinsrb, // Insert Byte +NN_pinsrd, // Insert Dword +NN_pinsrq, // Insert Qword +NN_pmaxsb, // Maximum of Packed Signed Byte Integers +NN_pmaxsd, // Maximum of Packed Signed Dword Integers +NN_pmaxud, // Maximum of Packed Unsigned Dword Integers +NN_pmaxuw, // Maximum of Packed Word Integers +NN_pminsb, // Minimum of Packed Signed Byte Integers +NN_pminsd, // Minimum of Packed Signed Dword Integers +NN_pminud, // Minimum of Packed Unsigned Dword Integers +NN_pminuw, // Minimum of Packed Word Integers +NN_pmovsxbw, // Packed Move with Sign Extend +NN_pmovsxbd, // Packed Move with Sign Extend +NN_pmovsxbq, // Packed Move with Sign Extend +NN_pmovsxwd, // Packed Move with Sign Extend +NN_pmovsxwq, // Packed Move with Sign Extend +NN_pmovsxdq, // Packed Move with Sign Extend +NN_pmovzxbw, // Packed Move with Zero Extend +NN_pmovzxbd, // Packed Move with Zero Extend +NN_pmovzxbq, // Packed Move with Zero Extend +NN_pmovzxwd, // Packed Move with Zero Extend +NN_pmovzxwq, // Packed Move with Zero Extend +NN_pmovzxdq, // Packed Move with Zero Extend +NN_pmuldq, // Multiply Packed Signed Dword Integers +NN_pmulld, // Multiply Packed Signed Dword Integers and Store Low Result +NN_ptest, // Logical Compare +NN_roundpd, // Round Packed Double Precision Floating-Point Values +NN_roundps, // Round Packed Single Precision Floating-Point Values +NN_roundsd, // Round Scalar Double Precision Floating-Point Values +NN_roundss, // Round Scalar Single Precision Floating-Point Values + +// SSSE4.2 instructions + +NN_crc32, // Accumulate CRC32 Value +NN_pcmpestri, // Packed Compare Explicit Length Strings, Return Index +NN_pcmpestrm, // Packed Compare Explicit Length Strings, Return Mask +NN_pcmpistri, // Packed Compare Implicit Length Strings, Return Index +NN_pcmpistrm, // Packed Compare Implicit Length Strings, Return Mask +NN_pcmpgtq, // Compare Packed Data for Greater Than +NN_popcnt, // Return the Count of Number of Bits Set to 1 + +// AMD SSE4a instructions + +NN_extrq, // Extract Field From Register +NN_insertq, // Insert Field +NN_movntsd, // Move Non-Temporal Scalar Double-Precision Floating-Point +NN_movntss, // Move Non-Temporal Scalar Single-Precision Floating-Point +NN_lzcnt, // Leading Zero Count + +// xsave/xrstor instructions + +NN_xgetbv, // Get Value of Extended Control Register +NN_xrstor, // Restore Processor Extended States +NN_xsave, // Save Processor Extended States +NN_xsetbv, // Set Value of Extended Control Register + +// Intel Safer Mode Extensions (SMX) + +NN_getsec, // Safer Mode Extensions (SMX) Instruction + +// AMD-V Virtualization ISA Extension + +NN_clgi, // Clear Global Interrupt Flag +NN_invlpga, // Invalidate TLB Entry in a Specified ASID +NN_skinit, // Secure Init and Jump with Attestation +NN_stgi, // Set Global Interrupt Flag +NN_vmexit, // Stop Executing Guest, Begin Executing Host +NN_vmload, // Load State from VMCB +NN_vmmcall, // Call VMM +NN_vmrun, // Run Virtual Machine +NN_vmsave, // Save State to VMCB + +// VMX+ instructions + +NN_invept, // Invalidate Translations Derived from EPT +NN_invvpid, // Invalidate Translations Based on VPID + +// Intel Atom instructions + +NN_movbe, // Move Data After Swapping Bytes + +// Intel AES instructions + +NN_aesenc, // Perform One Round of an AES Encryption Flow +NN_aesenclast, // Perform the Last Round of an AES Encryption Flow +NN_aesdec, // Perform One Round of an AES Decryption Flow +NN_aesdeclast, // Perform the Last Round of an AES Decryption Flow +NN_aesimc, // Perform the AES InvMixColumn Transformation +NN_aeskeygenassist, // AES Round Key Generation Assist + +// Carryless multiplication + +NN_pclmulqdq, // Carry-Less Multiplication Quadword + +// Returns modifies by operand size prefixes + +NN_retnw, // Return Near from Procedure (use16) +NN_retnd, // Return Near from Procedure (use32) +NN_retnq, // Return Near from Procedure (use64) +NN_retfw, // Return Far from Procedure (use16) +NN_retfd, // Return Far from Procedure (use32) +NN_retfq, // Return Far from Procedure (use64) + +// RDRAND support + +NN_rdrand, // Read Random Number + +// new GPR instructions + +NN_adcx, // Unsigned Integer Addition of Two Operands with Carry Flag +NN_adox, // Unsigned Integer Addition of Two Operands with Overflow Flag +NN_andn, // Logical AND NOT +NN_bextr, // Bit Field Extract +NN_blsi, // Extract Lowest Set Isolated Bit +NN_blsmsk, // Get Mask Up to Lowest Set Bit +NN_blsr, // Reset Lowest Set Bit +NN_bzhi, // Zero High Bits Starting with Specified Bit Position +NN_clac, // Clear AC Flag in EFLAGS Register +NN_mulx, // Unsigned Multiply Without Affecting Flags +NN_pdep, // Parallel Bits Deposit +NN_pext, // Parallel Bits Extract +NN_rorx, // Rotate Right Logical Without Affecting Flags +NN_sarx, // Shift Arithmetically Right Without Affecting Flags +NN_shlx, // Shift Logically Left Without Affecting Flags +NN_shrx, // Shift Logically Right Without Affecting Flags +NN_stac, // Set AC Flag in EFLAGS Register +NN_tzcnt, // Count the Number of Trailing Zero Bits +NN_xsaveopt, // Save Processor Extended States Optimized +NN_invpcid, // Invalidate Processor Context ID +NN_rdseed, // Read Random Seed +NN_rdfsbase, // Read FS Segment Base +NN_rdgsbase, // Read GS Segment Base +NN_wrfsbase, // Write FS Segment Base +NN_wrgsbase, // Write GS Segment Base + +// new AVX instructions + +NN_vaddpd, // Add Packed Double-Precision Floating-Point Values +NN_vaddps, // Packed Single-FP Add +NN_vaddsd, // Add Scalar Double-Precision Floating-Point Values +NN_vaddss, // Scalar Single-FP Add +NN_vaddsubpd, // Add /Sub packed DP FP numbers +NN_vaddsubps, // Add /Sub packed SP FP numbers +NN_vaesdec, // Perform One Round of an AES Decryption Flow +NN_vaesdeclast, // Perform the Last Round of an AES Decryption Flow +NN_vaesenc, // Perform One Round of an AES Encryption Flow +NN_vaesenclast, // Perform the Last Round of an AES Encryption Flow +NN_vaesimc, // Perform the AES InvMixColumn Transformation +NN_vaeskeygenassist, // AES Round Key Generation Assist +NN_vandnpd, // Bitwise Logical AND NOT of Packed Double-Precision Floating-Point Values +NN_vandnps, // Bitwise Logical And Not for Single-FP +NN_vandpd, // Bitwise Logical AND of Packed Double-Precision Floating-Point Values +NN_vandps, // Bitwise Logical And for Single-FP +NN_vblendpd, // Blend Packed Double Precision Floating-Point Values +NN_vblendps, // Blend Packed Single Precision Floating-Point Values +NN_vblendvpd, // Variable Blend Packed Double Precision Floating-Point Values +NN_vblendvps, // Variable Blend Packed Single Precision Floating-Point Values +NN_vbroadcastf128, // Broadcast 128 Bits of Floating-Point Data +NN_vbroadcasti128, // Broadcast 128 Bits of Integer Data +NN_vbroadcastsd, // Broadcast Double-Precision Floating-Point Element +NN_vbroadcastss, // Broadcast Single-Precision Floating-Point Element +NN_vcmppd, // Compare Packed Double-Precision Floating-Point Values +NN_vcmpps, // Packed Single-FP Compare +NN_vcmpsd, // Compare Scalar Double-Precision Floating-Point Values +NN_vcmpss, // Scalar Single-FP Compare +NN_vcomisd, // Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS +NN_vcomiss, // Scalar Ordered Single-FP Compare and Set EFLAGS +NN_vcvtdq2pd, // Convert Packed Doubleword Integers to Packed Single-Precision Floating-Point Values +NN_vcvtdq2ps, // Convert Packed Doubleword Integers to Packed Double-Precision Floating-Point Values +NN_vcvtpd2dq, // Convert Packed Double-Precision Floating-Point Values to Packed Doubleword Integers +NN_vcvtpd2ps, // Convert Packed Double-Precision Floating-Point Values to Packed Single-Precision Floating-Point Values +NN_vcvtph2ps, // Convert 16-bit FP Values to Single-Precision FP Values +NN_vcvtps2dq, // Convert Packed Single-Precision Floating-Point Values to Packed Doubleword Integers +NN_vcvtps2pd, // Convert Packed Single-Precision Floating-Point Values to Packed Double-Precision Floating-Point Values +NN_vcvtps2ph, // Convert Single-Precision FP value to 16-bit FP value +NN_vcvtsd2si, // Convert Scalar Double-Precision Floating-Point Value to Doubleword Integer +NN_vcvtsd2ss, // Convert Scalar Double-Precision Floating-Point Value to Scalar Single-Precision Floating-Point Value +NN_vcvtsi2sd, // Convert Doubleword Integer to Scalar Double-Precision Floating-Point Value +NN_vcvtsi2ss, // Scalar signed INT32 to Single-FP conversion +NN_vcvtss2sd, // Convert Scalar Single-Precision Floating-Point Value to Scalar Double-Precision Floating-Point Value +NN_vcvtss2si, // Scalar Single-FP to signed INT32 conversion +NN_vcvttpd2dq, // Convert With Truncation Packed Double-Precision Floating-Point Values to Packed Doubleword Integers +NN_vcvttps2dq, // Convert With Truncation Packed Single-Precision Floating-Point Values to Packed Doubleword Integers +NN_vcvttsd2si, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Doubleword Integer +NN_vcvttss2si, // Scalar Single-FP to signed INT32 conversion (truncate) +NN_vdivpd, // Divide Packed Double-Precision Floating-Point Values +NN_vdivps, // Packed Single-FP Divide +NN_vdivsd, // Divide Scalar Double-Precision Floating-Point Values +NN_vdivss, // Scalar Single-FP Divide +NN_vdppd, // Dot Product of Packed Double Precision Floating-Point Values +NN_vdpps, // Dot Product of Packed Single Precision Floating-Point Values +NN_vextractf128, // Extract Packed Floating-Point Values +NN_vextracti128, // Extract Packed Integer Values +NN_vextractps, // Extract Packed Floating-Point Values +NN_vfmadd132pd, // Fused Multiply-Add of Packed Double-Precision Floating-Point Values +NN_vfmadd132ps, // Fused Multiply-Add of Packed Single-Precision Floating-Point Values +NN_vfmadd132sd, // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values +NN_vfmadd132ss, // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values +NN_vfmadd213pd, // Fused Multiply-Add of Packed Double-Precision Floating-Point Values +NN_vfmadd213ps, // Fused Multiply-Add of Packed Single-Precision Floating-Point Values +NN_vfmadd213sd, // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values +NN_vfmadd213ss, // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values +NN_vfmadd231pd, // Fused Multiply-Add of Packed Double-Precision Floating-Point Values +NN_vfmadd231ps, // Fused Multiply-Add of Packed Single-Precision Floating-Point Values +NN_vfmadd231sd, // Fused Multiply-Add of Scalar Double-Precision Floating-Point Values +NN_vfmadd231ss, // Fused Multiply-Add of Scalar Single-Precision Floating-Point Values +NN_vfmaddsub132pd, // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values +NN_vfmaddsub132ps, // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values +NN_vfmaddsub213pd, // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values +NN_vfmaddsub213ps, // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values +NN_vfmaddsub231pd, // Fused Multiply-Alternating Add/Subtract of Packed Double-Precision Floating-Point Values +NN_vfmaddsub231ps, // Fused Multiply-Alternating Add/Subtract of Packed Single-Precision Floating-Point Values +NN_vfmsub132pd, // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values +NN_vfmsub132ps, // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values +NN_vfmsub132sd, // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values +NN_vfmsub132ss, // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values +NN_vfmsub213pd, // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values +NN_vfmsub213ps, // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values +NN_vfmsub213sd, // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values +NN_vfmsub213ss, // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values +NN_vfmsub231pd, // Fused Multiply-Subtract of Packed Double-Precision Floating-Point Values +NN_vfmsub231ps, // Fused Multiply-Subtract of Packed Single-Precision Floating-Point Values +NN_vfmsub231sd, // Fused Multiply-Subtract of Scalar Double-Precision Floating-Point Values +NN_vfmsub231ss, // Fused Multiply-Subtract of Scalar Single-Precision Floating-Point Values +NN_vfmsubadd132pd, // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values +NN_vfmsubadd132ps, // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values +NN_vfmsubadd213pd, // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values +NN_vfmsubadd213ps, // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values +NN_vfmsubadd231pd, // Fused Multiply-Alternating Subtract/Add of Packed Double-Precision Floating-Point Values +NN_vfmsubadd231ps, // Fused Multiply-Alternating Subtract/Add of Packed Single-Precision Floating-Point Values +NN_vfnmadd132pd, // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values +NN_vfnmadd132ps, // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values +NN_vfnmadd132sd, // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values +NN_vfnmadd132ss, // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values +NN_vfnmadd213pd, // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values +NN_vfnmadd213ps, // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values +NN_vfnmadd213sd, // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values +NN_vfnmadd213ss, // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values +NN_vfnmadd231pd, // Fused Negative Multiply-Add of Packed Double-Precision Floating-Point Values +NN_vfnmadd231ps, // Fused Negative Multiply-Add of Packed Single-Precision Floating-Point Values +NN_vfnmadd231sd, // Fused Negative Multiply-Add of Scalar Double-Precision Floating-Point Values +NN_vfnmadd231ss, // Fused Negative Multiply-Add of Scalar Single-Precision Floating-Point Values +NN_vfnmsub132pd, // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values +NN_vfnmsub132ps, // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values +NN_vfnmsub132sd, // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values +NN_vfnmsub132ss, // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values +NN_vfnmsub213pd, // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values +NN_vfnmsub213ps, // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values +NN_vfnmsub213sd, // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values +NN_vfnmsub213ss, // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values +NN_vfnmsub231pd, // Fused Negative Multiply-Subtract of Packed Double-Precision Floating-Point Values +NN_vfnmsub231ps, // Fused Negative Multiply-Subtract of Packed Single-Precision Floating-Point Values +NN_vfnmsub231sd, // Fused Negative Multiply-Subtract of Scalar Double-Precision Floating-Point Values +NN_vfnmsub231ss, // Fused Negative Multiply-Subtract of Scalar Single-Precision Floating-Point Values +NN_vgatherdps, // Gather Packed SP FP Values Using Signed Dword Indices +NN_vgatherdpd, // Gather Packed DP FP Values Using Signed Dword Indices +NN_vgatherqps, // Gather Packed SP FP Values Using Signed Qword Indices +NN_vgatherqpd, // Gather Packed DP FP Values Using Signed Qword Indices +NN_vhaddpd, // Add horizontally packed DP FP numbers +NN_vhaddps, // Add horizontally packed SP FP numbers +NN_vhsubpd, // Sub horizontally packed DP FP numbers +NN_vhsubps, // Sub horizontally packed SP FP numbers +NN_vinsertf128, // Insert Packed Floating-Point Values +NN_vinserti128, // Insert Packed Integer Values +NN_vinsertps, // Insert Packed Single Precision Floating-Point Value +NN_vlddqu, // Load Unaligned Packed Integer Values +NN_vldmxcsr, // Load Streaming SIMD Extensions Technology Control/Status Register +NN_vmaskmovdqu, // Store Selected Bytes of Double Quadword with NT Hint +NN_vmaskmovpd, // Conditionally Load Packed Double-Precision Floating-Point Values +NN_vmaskmovps, // Conditionally Load Packed Single-Precision Floating-Point Values +NN_vmaxpd, // Return Maximum Packed Double-Precision Floating-Point Values +NN_vmaxps, // Packed Single-FP Maximum +NN_vmaxsd, // Return Maximum Scalar Double-Precision Floating-Point Value +NN_vmaxss, // Scalar Single-FP Maximum +NN_vminpd, // Return Minimum Packed Double-Precision Floating-Point Values +NN_vminps, // Packed Single-FP Minimum +NN_vminsd, // Return Minimum Scalar Double-Precision Floating-Point Value +NN_vminss, // Scalar Single-FP Minimum +NN_vmovapd, // Move Aligned Packed Double-Precision Floating-Point Values +NN_vmovaps, // Move Aligned Four Packed Single-FP +NN_vmovd, // Move 32 bits +NN_vmovddup, // Move One Double-FP and Duplicate +NN_vmovdqa, // Move Aligned Double Quadword +NN_vmovdqu, // Move Unaligned Double Quadword +NN_vmovhlps, // Move High to Low Packed Single-FP +NN_vmovhpd, // Move High Packed Double-Precision Floating-Point Values +NN_vmovhps, // Move High Packed Single-FP +NN_vmovlhps, // Move Low to High Packed Single-FP +NN_vmovlpd, // Move Low Packed Double-Precision Floating-Point Values +NN_vmovlps, // Move Low Packed Single-FP +NN_vmovmskpd, // Extract Packed Double-Precision Floating-Point Sign Mask +NN_vmovmskps, // Move Mask to Register +NN_vmovntdq, // Store Double Quadword Using Non-Temporal Hint +NN_vmovntdqa, // Load Double Quadword Non-Temporal Aligned Hint +NN_vmovntpd, // Store Packed Double-Precision Floating-Point Values Using Non-Temporal Hint +NN_vmovntps, // Move Aligned Four Packed Single-FP Non Temporal +NN_vmovq, // Move 64 bits +NN_vmovsd, // Move Scalar Double-Precision Floating-Point Values +NN_vmovshdup, // Move Packed Single-FP High and Duplicate +NN_vmovsldup, // Move Packed Single-FP Low and Duplicate +NN_vmovss, // Move Scalar Single-FP +NN_vmovupd, // Move Unaligned Packed Double-Precision Floating-Point Values +NN_vmovups, // Move Unaligned Four Packed Single-FP +NN_vmpsadbw, // Compute Multiple Packed Sums of Absolute Difference +NN_vmulpd, // Multiply Packed Double-Precision Floating-Point Values +NN_vmulps, // Packed Single-FP Multiply +NN_vmulsd, // Multiply Scalar Double-Precision Floating-Point Values +NN_vmulss, // Scalar Single-FP Multiply +NN_vorpd, // Bitwise Logical OR of Double-Precision Floating-Point Values +NN_vorps, // Bitwise Logical OR for Single-FP Data +NN_vpabsb, // Packed Absolute Value Byte +NN_vpabsd, // Packed Absolute Value Doubleword +NN_vpabsw, // Packed Absolute Value Word +NN_vpackssdw, // Pack with Signed Saturation (Dword->Word) +NN_vpacksswb, // Pack with Signed Saturation (Word->Byte) +NN_vpackusdw, // Pack with Unsigned Saturation +NN_vpackuswb, // Pack with Unsigned Saturation (Word->Byte) +NN_vpaddb, // Packed Add Byte +NN_vpaddd, // Packed Add Dword +NN_vpaddq, // Add Packed Quadword Integers +NN_vpaddsb, // Packed Add with Saturation (Byte) +NN_vpaddsw, // Packed Add with Saturation (Word) +NN_vpaddusb, // Packed Add Unsigned with Saturation (Byte) +NN_vpaddusw, // Packed Add Unsigned with Saturation (Word) +NN_vpaddw, // Packed Add Word +NN_vpalignr, // Packed Align Right +NN_vpand, // Bitwise Logical And +NN_vpandn, // Bitwise Logical And Not +NN_vpavgb, // Packed Average (Byte) +NN_vpavgw, // Packed Average (Word) +NN_vpblendd, // Blend Packed Dwords +NN_vpblendvb, // Variable Blend Packed Bytes +NN_vpblendw, // Blend Packed Words +NN_vpbroadcastb, // Broadcast a Byte Integer +NN_vpbroadcastd, // Broadcast a Dword Integer +NN_vpbroadcastq, // Broadcast a Qword Integer +NN_vpbroadcastw, // Broadcast a Word Integer +NN_vpclmulqdq, // Carry-Less Multiplication Quadword +NN_vpcmpeqb, // Packed Compare for Equal (Byte) +NN_vpcmpeqd, // Packed Compare for Equal (Dword) +NN_vpcmpeqq, // Compare Packed Qword Data for Equal +NN_vpcmpeqw, // Packed Compare for Equal (Word) +NN_vpcmpestri, // Packed Compare Explicit Length Strings, Return Index +NN_vpcmpestrm, // Packed Compare Explicit Length Strings, Return Mask +NN_vpcmpgtb, // Packed Compare for Greater Than (Byte) +NN_vpcmpgtd, // Packed Compare for Greater Than (Dword) +NN_vpcmpgtq, // Compare Packed Data for Greater Than +NN_vpcmpgtw, // Packed Compare for Greater Than (Word) +NN_vpcmpistri, // Packed Compare Implicit Length Strings, Return Index +NN_vpcmpistrm, // Packed Compare Implicit Length Strings, Return Mask +NN_vperm2f128, // Permute Floating-Point Values +NN_vperm2i128, // Permute Integer Values +NN_vpermd, // Full Doublewords Element Permutation +NN_vpermilpd, // Permute Double-Precision Floating-Point Values +NN_vpermilps, // Permute Single-Precision Floating-Point Values +NN_vpermpd, // Permute Double-Precision Floating-Point Elements +NN_vpermps, // Permute Single-Precision Floating-Point Elements +NN_vpermq, // Qwords Element Permutation +NN_vpextrb, // Extract Byte +NN_vpextrd, // Extract Dword +NN_vpextrq, // Extract Qword +NN_vpextrw, // Extract Word +NN_vpgatherdd, // Gather Packed Dword Values Using Signed Dword Indices +NN_vpgatherdq, // Gather Packed Qword Values Using Signed Dword Indices +NN_vpgatherqd, // Gather Packed Dword Values Using Signed Qword Indices +NN_vpgatherqq, // Gather Packed Qword Values Using Signed Qword Indices +NN_vphaddd, // Packed Horizontal Add Doubleword +NN_vphaddsw, // Packed Horizontal Add and Saturate +NN_vphaddw, // Packed Horizontal Add Word +NN_vphminposuw, // Packed Horizontal Word Minimum +NN_vphsubd, // Packed Horizontal Subtract Doubleword +NN_vphsubsw, // Packed Horizontal Subtract and Saturate +NN_vphsubw, // Packed Horizontal Subtract Word +NN_vpinsrb, // Insert Byte +NN_vpinsrd, // Insert Dword +NN_vpinsrq, // Insert Qword +NN_vpinsrw, // Insert Word +NN_vpmaddubsw, // Multiply and Add Packed Signed and Unsigned Bytes +NN_vpmaddwd, // Packed Multiply and Add +NN_vpmaskmovd, // Conditionally Store Dword Values Using Mask +NN_vpmaskmovq, // Conditionally Store Qword Values Using Mask +NN_vpmaxsb, // Maximum of Packed Signed Byte Integers +NN_vpmaxsd, // Maximum of Packed Signed Dword Integers +NN_vpmaxsw, // Packed Signed Integer Word Maximum +NN_vpmaxub, // Packed Unsigned Integer Byte Maximum +NN_vpmaxud, // Maximum of Packed Unsigned Dword Integers +NN_vpmaxuw, // Maximum of Packed Word Integers +NN_vpminsb, // Minimum of Packed Signed Byte Integers +NN_vpminsd, // Minimum of Packed Signed Dword Integers +NN_vpminsw, // Packed Signed Integer Word Minimum +NN_vpminub, // Packed Unsigned Integer Byte Minimum +NN_vpminud, // Minimum of Packed Unsigned Dword Integers +NN_vpminuw, // Minimum of Packed Word Integers +NN_vpmovmskb, // Move Byte Mask to Integer +NN_vpmovsxbd, // Packed Move with Sign Extend +NN_vpmovsxbq, // Packed Move with Sign Extend +NN_vpmovsxbw, // Packed Move with Sign Extend +NN_vpmovsxdq, // Packed Move with Sign Extend +NN_vpmovsxwd, // Packed Move with Sign Extend +NN_vpmovsxwq, // Packed Move with Sign Extend +NN_vpmovzxbd, // Packed Move with Zero Extend +NN_vpmovzxbq, // Packed Move with Zero Extend +NN_vpmovzxbw, // Packed Move with Zero Extend +NN_vpmovzxdq, // Packed Move with Zero Extend +NN_vpmovzxwd, // Packed Move with Zero Extend +NN_vpmovzxwq, // Packed Move with Zero Extend +NN_vpmuldq, // Multiply Packed Signed Dword Integers +NN_vpmulhrsw, // Packed Multiply High with Round and Scale +NN_vpmulhuw, // Packed Multiply High Unsigned +NN_vpmulhw, // Packed Multiply High +NN_vpmulld, // Multiply Packed Signed Dword Integers and Store Low Result +NN_vpmullw, // Packed Multiply Low +NN_vpmuludq, // Multiply Packed Unsigned Doubleword Integers +NN_vpor, // Bitwise Logical Or +NN_vpsadbw, // Packed Sum of Absolute Differences +NN_vpshufb, // Packed Shuffle Bytes +NN_vpshufd, // Shuffle Packed Doublewords +NN_vpshufhw, // Shuffle Packed High Words +NN_vpshuflw, // Shuffle Packed Low Words +NN_vpsignb, // Packed SIGN Byte +NN_vpsignd, // Packed SIGN Doubleword +NN_vpsignw, // Packed SIGN Word +NN_vpslld, // Packed Shift Left Logical (Dword) +NN_vpslldq, // Shift Double Quadword Left Logical +NN_vpsllq, // Packed Shift Left Logical (Qword) +NN_vpsllvd, // Variable Bit Shift Left Logical (Dword) +NN_vpsllvq, // Variable Bit Shift Left Logical (Qword) +NN_vpsllw, // Packed Shift Left Logical (Word) +NN_vpsrad, // Packed Shift Right Arithmetic (Dword) +NN_vpsravd, // Variable Bit Shift Right Arithmetic +NN_vpsraw, // Packed Shift Right Arithmetic (Word) +NN_vpsrld, // Packed Shift Right Logical (Dword) +NN_vpsrldq, // Shift Double Quadword Right Logical (Qword) +NN_vpsrlq, // Packed Shift Right Logical (Qword) +NN_vpsrlvd, // Variable Bit Shift Right Logical (Dword) +NN_vpsrlvq, // Variable Bit Shift Right Logical (Qword) +NN_vpsrlw, // Packed Shift Right Logical (Word) +NN_vpsubb, // Packed Subtract Byte +NN_vpsubd, // Packed Subtract Dword +NN_vpsubq, // Subtract Packed Quadword Integers +NN_vpsubsb, // Packed Subtract with Saturation (Byte) +NN_vpsubsw, // Packed Subtract with Saturation (Word) +NN_vpsubusb, // Packed Subtract Unsigned with Saturation (Byte) +NN_vpsubusw, // Packed Subtract Unsigned with Saturation (Word) +NN_vpsubw, // Packed Subtract Word +NN_vptest, // Logical Compare +NN_vpunpckhbw, // Unpack High Packed Data (Byte->Word) +NN_vpunpckhdq, // Unpack High Packed Data (Dword->Qword) +NN_vpunpckhqdq, // Unpack High Packed Data (Qword->Xmmword) +NN_vpunpckhwd, // Unpack High Packed Data (Word->Dword) +NN_vpunpcklbw, // Unpack Low Packed Data (Byte->Word) +NN_vpunpckldq, // Unpack Low Packed Data (Dword->Qword) +NN_vpunpcklqdq, // Unpack Low Packed Data (Qword->Xmmword) +NN_vpunpcklwd, // Unpack Low Packed Data (Word->Dword) +NN_vpxor, // Bitwise Logical Exclusive Or +NN_vrcpps, // Packed Single-FP Reciprocal +NN_vrcpss, // Scalar Single-FP Reciprocal +NN_vroundpd, // Round Packed Double Precision Floating-Point Values +NN_vroundps, // Round Packed Single Precision Floating-Point Values +NN_vroundsd, // Round Scalar Double Precision Floating-Point Values +NN_vroundss, // Round Scalar Single Precision Floating-Point Values +NN_vrsqrtps, // Packed Single-FP Square Root Reciprocal +NN_vrsqrtss, // Scalar Single-FP Square Root Reciprocal +NN_vshufpd, // Shuffle Packed Double-Precision Floating-Point Values +NN_vshufps, // Shuffle Single-FP +NN_vsqrtpd, // Compute Square Roots of Packed Double-Precision Floating-Point Values +NN_vsqrtps, // Packed Single-FP Square Root +NN_vsqrtsd, // Compute Square Rootof Scalar Double-Precision Floating-Point Value +NN_vsqrtss, // Scalar Single-FP Square Root +NN_vstmxcsr, // Store Streaming SIMD Extensions Technology Control/Status Register +NN_vsubpd, // Subtract Packed Double-Precision Floating-Point Values +NN_vsubps, // Packed Single-FP Subtract +NN_vsubsd, // Subtract Scalar Double-Precision Floating-Point Values +NN_vsubss, // Scalar Single-FP Subtract +NN_vtestpd, // Packed Double-Precision Floating-Point Bit Test +NN_vtestps, // Packed Single-Precision Floating-Point Bit Test +NN_vucomisd, // Unordered Compare Scalar Ordered Double-Precision Floating-Point Values and Set EFLAGS +NN_vucomiss, // Scalar Unordered Single-FP Compare and Set EFLAGS +NN_vunpckhpd, // Unpack and Interleave High Packed Double-Precision Floating-Point Values +NN_vunpckhps, // Unpack High Packed Single-FP Data +NN_vunpcklpd, // Unpack and Interleave Low Packed Double-Precision Floating-Point Values +NN_vunpcklps, // Unpack Low Packed Single-FP Data +NN_vxorpd, // Bitwise Logical OR of Double-Precision Floating-Point Values +NN_vxorps, // Bitwise Logical XOR for Single-FP Data +NN_vzeroall, // Zero All YMM Registers +NN_vzeroupper, // Zero Upper Bits of YMM Registers + +// Transactional Synchronization Extensions + +NN_xabort, // Transaction Abort +NN_xbegin, // Transaction Begin +NN_xend, // Transaction End +NN_xtest, // Test If In Transactional Execution + +// Virtual PC synthetic instructions + +NN_vmgetinfo, // Virtual PC - Get VM Information +NN_vmsetinfo, // Virtual PC - Set VM Information +NN_vmdxdsbl, // Virtual PC - Disable Direct Execution +NN_vmdxenbl, // Virtual PC - Enable Direct Execution +NN_vmcpuid, // Virtual PC - Virtualized CPU Information +NN_vmhlt, // Virtual PC - Halt +NN_vmsplaf, // Virtual PC - Spin Lock Acquisition Failed +NN_vmpushfd, // Virtual PC - Push virtualized flags register +NN_vmpopfd, // Virtual PC - Pop virtualized flags register +NN_vmcli, // Virtual PC - Clear Interrupt Flag +NN_vmsti, // Virtual PC - Set Interrupt Flag +NN_vmiretd, // Virtual PC - Return From Interrupt +NN_vmsgdt, // Virtual PC - Store Global Descriptor Table +NN_vmsidt, // Virtual PC - Store Interrupt Descriptor Table +NN_vmsldt, // Virtual PC - Store Local Descriptor Table +NN_vmstr, // Virtual PC - Store Task Register +NN_vmsdte, // Virtual PC - Store to Descriptor Table Entry +NN_vpcext, // Virtual PC - ISA extension + +// AMD FMA4 + +NN_vfmaddsubps, // Multiply with Alternating Add/Subtract of Packed Single-Precision Floating-Point +NN_vfmaddsubpd, // Multiply with Alternating Add/Subtract of Packed Double-Precision Floating-Point +NN_vfmsubaddps, // Multiply with Alternating Subtract/Add of Packed Single-Precision Floating-Point +NN_vfmsubaddpd, // Multiply with Alternating Subtract/Add of Packed Double-Precision Floating-Point +NN_vfmaddps, // Multiply and Add Packed Single-Precision Floating-Point +NN_vfmaddpd, // Multiply and Add Packed Double-Precision Floating-Point +NN_vfmaddss, // Multiply and Add Scalar Single-Precision Floating-Point +NN_vfmaddsd, // Multiply and Add Scalar Double-Precision Floating-Point +NN_vfmsubps, // Multiply and Subtract Packed Single-Precision Floating-Point +NN_vfmsubpd, // Multiply and Subtract Packed Double-Precision Floating-Point +NN_vfmsubss, // Multiply and Subtract Scalar Single-Precision Floating-Point +NN_vfmsubsd, // Multiply and Subtract Scalar Double-Precision Floating-Point +NN_vfnmaddps, // Negative Multiply and Add Packed Single-Precision Floating-Point +NN_vfnmaddpd, // Negative Multiply and Add Packed Double-Precision Floating-Point +NN_vfnmaddss, // Negative Multiply and Add Scalar Single-Precision Floating-Point +NN_vfnmaddsd, // Negative Multiply and Add Double Single-Precision Floating-Point +NN_vfnmsubps, // Negative Multiply and Subtract Packed Single-Precision Floating-Point +NN_vfnmsubpd, // Negative Multiply and Subtract Packed Double-Precision Floating-Point +NN_vfnmsubss, // Negative Multiply and Subtract Scalar Single-Precision Floating-Point +NN_vfnmsubsd, // Negative Multiply and Subtract Double Single-Precision Floating-Point + +// Intel Memory Protection Extensions (MPX) + +NN_bndmk, // Make Bounds +NN_bndcl, // Check Lower Bound +NN_bndcu, // Check Upper Bound +NN_bndcn, // Check Upper Bound +NN_bndmov, // Move Bounds +NN_bndldx, // Load Extended Bounds Using Address Translation +NN_bndstx, // Store Extended Bounds Using Address Translation + +// New xstate instructions + +NN_xrstors, // Restore Processor Extended States Supervisor +NN_xsavec, // Save Processor Extended States with Compaction +NN_xsaves, // Save Processor Extended States Supervisor + +// PREFETCHWT1 support + +NN_prefetchwt1, // Prefetch Vector Data Into Caches with Intent to Write and T1 Hint + +// Memory instructions + +NN_clflushopt, // Flush a Cache Line Optimized +NN_clwb, // Cache Line Write Back +NN_pcommit, // Persistent Commit (deprecated by Intel) + +// Protection Key Rights for User Pages + +NN_rdpkru, // Read Protection Key Rights for User Pages +NN_wrpkru, // Write Data to User Page Key Register + +// AVX comparison pseudo-ops + +NN_vcmpeqpd, // Compare Packed Double-Precision Floating-Point Values - Equal (ordered, non-signaling) +NN_vcmpltpd, // Compare Packed Double-Precision Floating-Point Values - Less-than (ordered, signaling) +NN_vcmplepd, // Compare Packed Double-Precision Floating-Point Values - Less-than-or-equal (ordered, signaling) +NN_vcmpunordpd, // Compare Packed Double-Precision Floating-Point Values - Unordered (non-signaling) +NN_vcmpneqpd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (unordered, non-signaling) +NN_vcmpnltpd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than (unordered, signaling) +NN_vcmpnlepd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, signaling) +NN_vcmpordpd, // Compare Packed Double-Precision Floating-Point Values - Ordered (non-signaling) +NN_vcmpeq_uqpd, // Compare Packed Double-Precision Floating-Point Values - Equal (unordered, non-signaling) +NN_vcmpngepd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, signaling) +NN_vcmpngtpd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than (unordered, signaling) +NN_vcmpfalsepd, // Compare Packed Double-Precision Floating-Point Values - False (ordered, non-signaling) +NN_vcmpneq_oqpd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (ordered, non-signaling) +NN_vcmpgepd, // Compare Packed Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, signaling) +NN_vcmpgtpd, // Compare Packed Double-Precision Floating-Point Values - Greater-than (ordered, signaling) +NN_vcmptruepd, // Compare Packed Double-Precision Floating-Point Values - True (unordered, non-signaling) +NN_vcmpeq_ospd, // Compare Packed Double-Precision Floating-Point Values - Equal (ordered, signaling) +NN_vcmplt_oqpd, // Compare Packed Double-Precision Floating-Point Values - Less-than (ordered, non-signaling) +NN_vcmple_oqpd, // Compare Packed Double-Precision Floating-Point Values - Less-than-or-equal (ordered, non-signaling) +NN_vcmpunord_spd, // Compare Packed Double-Precision Floating-Point Values - Unordered (signaling) +NN_vcmpneq_uspd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (unordered, signaling) +NN_vcmpnlt_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than (unordered, non-signaling) +NN_vcmpnle_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, non-signaling) +NN_vcmpord_spd, // Compare Packed Double-Precision Floating-Point Values - Ordered (signaling) +NN_vcmpeq_uspd, // Compare Packed Double-Precision Floating-Point Values - Equal (unordered, signaling) +NN_vcmpnge_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, non-signaling) +NN_vcmpngt_uqpd, // Compare Packed Double-Precision Floating-Point Values - Not-greater-than (unordered, non-signaling) +NN_vcmpfalse_ospd, // Compare Packed Double-Precision Floating-Point Values - False (ordered, signaling) +NN_vcmpneq_ospd, // Compare Packed Double-Precision Floating-Point Values - Not-equal (ordered, signaling) +NN_vcmpge_oqpd, // Compare Packed Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, non-signaling) +NN_vcmpgt_oqpd, // Compare Packed Double-Precision Floating-Point Values - Greater-than (ordered, non-signaling) +NN_vcmptrue_uspd, // Compare Packed Double-Precision Floating-Point Values - True (unordered, signaling) + +NN_vcmpeqps, // Packed Single-FP Compare - Equal (ordered, non-signaling) +NN_vcmpltps, // Packed Single-FP Compare - Less-than (ordered, signaling) +NN_vcmpleps, // Packed Single-FP Compare - Less-than-or-equal (ordered, signaling) +NN_vcmpunordps, // Packed Single-FP Compare - Unordered (non-signaling) +NN_vcmpneqps, // Packed Single-FP Compare - Not-equal (unordered, non-signaling) +NN_vcmpnltps, // Packed Single-FP Compare - Not-less-than (unordered, signaling) +NN_vcmpnleps, // Packed Single-FP Compare - Not-less-than-or-equal (unordered, signaling) +NN_vcmpordps, // Packed Single-FP Compare - Ordered (non-signaling) +NN_vcmpeq_uqps, // Packed Single-FP Compare - Equal (unordered, non-signaling) +NN_vcmpngeps, // Packed Single-FP Compare - Not-greater-than-or-equal (unordered, signaling) +NN_vcmpngtps, // Packed Single-FP Compare - Not-greater-than (unordered, signaling) +NN_vcmpfalseps, // Packed Single-FP Compare - False (ordered, non-signaling) +NN_vcmpneq_oqps, // Packed Single-FP Compare - Not-equal (ordered, non-signaling) +NN_vcmpgeps, // Packed Single-FP Compare - Greater-than-or-equal (ordered, signaling) +NN_vcmpgtps, // Packed Single-FP Compare - Greater-than (ordered, signaling) +NN_vcmptrueps, // Packed Single-FP Compare - True (unordered, non-signaling) +NN_vcmpeq_osps, // Packed Single-FP Compare - Equal (ordered, signaling) +NN_vcmplt_oqps, // Packed Single-FP Compare - Less-than (ordered, non-signaling) +NN_vcmple_oqps, // Packed Single-FP Compare - Less-than-or-equal (ordered, non-signaling) +NN_vcmpunord_sps, // Packed Single-FP Compare - Unordered (signaling) +NN_vcmpneq_usps, // Packed Single-FP Compare - Not-equal (unordered, signaling) +NN_vcmpnlt_uqps, // Packed Single-FP Compare - Not-less-than (unordered, non-signaling) +NN_vcmpnle_uqps, // Packed Single-FP Compare - Not-less-than-or-equal (unordered, non-signaling) +NN_vcmpord_sps, // Packed Single-FP Compare - Ordered (signaling) +NN_vcmpeq_usps, // Packed Single-FP Compare - Equal (unordered, signaling) +NN_vcmpnge_uqps, // Packed Single-FP Compare - Not-greater-than-or-equal (unordered, non-signaling) +NN_vcmpngt_uqps, // Packed Single-FP Compare - Not-greater-than (unordered, non-signaling) +NN_vcmpfalse_osps, // Packed Single-FP Compare - False (ordered, signaling) +NN_vcmpneq_osps, // Packed Single-FP Compare - Not-equal (ordered, signaling) +NN_vcmpge_oqps, // Packed Single-FP Compare - Greater-than-or-equal (ordered, non-signaling) +NN_vcmpgt_oqps, // Packed Single-FP Compare - Greater-than (ordered, non-signaling) +NN_vcmptrue_usps, // Packed Single-FP Compare - True (unordered, signaling) + +NN_vcmpeqsd, // Compare Scalar Double-Precision Floating-Point Values - Equal (ordered, non-signaling) +NN_vcmpltsd, // Compare Scalar Double-Precision Floating-Point Values - Less-than (ordered, signaling) +NN_vcmplesd, // Compare Scalar Double-Precision Floating-Point Values - Less-than-or-equal (ordered, signaling) +NN_vcmpunordsd, // Compare Scalar Double-Precision Floating-Point Values - Unordered (non-signaling) +NN_vcmpneqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (unordered, non-signaling) +NN_vcmpnltsd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than (unordered, signaling) +NN_vcmpnlesd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, signaling) +NN_vcmpordsd, // Compare Scalar Double-Precision Floating-Point Values - Ordered (non-signaling) +NN_vcmpeq_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Equal (unordered, non-signaling) +NN_vcmpngesd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, signaling) +NN_vcmpngtsd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than (unordered, signaling) +NN_vcmpfalsesd, // Compare Scalar Double-Precision Floating-Point Values - False (ordered, non-signaling) +NN_vcmpneq_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (ordered, non-signaling) +NN_vcmpgesd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, signaling) +NN_vcmpgtsd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than (ordered, signaling) +NN_vcmptruesd, // Compare Scalar Double-Precision Floating-Point Values - True (unordered, non-signaling) +NN_vcmpeq_ossd, // Compare Scalar Double-Precision Floating-Point Values - Equal (ordered, signaling) +NN_vcmplt_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Less-than (ordered, non-signaling) +NN_vcmple_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Less-than-or-equal (ordered, non-signaling) +NN_vcmpunord_ssd, // Compare Scalar Double-Precision Floating-Point Values - Unordered (signaling) +NN_vcmpneq_ussd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (unordered, signaling) +NN_vcmpnlt_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than (unordered, non-signaling) +NN_vcmpnle_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-less-than-or-equal (unordered, non-signaling) +NN_vcmpord_ssd, // Compare Scalar Double-Precision Floating-Point Values - Ordered (signaling) +NN_vcmpeq_ussd, // Compare Scalar Double-Precision Floating-Point Values - Equal (unordered, signaling) +NN_vcmpnge_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than-or-equal (unordered, non-signaling) +NN_vcmpngt_uqsd, // Compare Scalar Double-Precision Floating-Point Values - Not-greater-than (unordered, non-signaling) +NN_vcmpfalse_ossd, // Compare Scalar Double-Precision Floating-Point Values - False (ordered, signaling) +NN_vcmpneq_ossd, // Compare Scalar Double-Precision Floating-Point Values - Not-equal (ordered, signaling) +NN_vcmpge_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than-or-equal (ordered, non-signaling) +NN_vcmpgt_oqsd, // Compare Scalar Double-Precision Floating-Point Values - Greater-than (ordered, non-signaling) +NN_vcmptrue_ussd, // Compare Scalar Double-Precision Floating-Point Values - True (unordered, signaling) + +NN_vcmpeqss, // Scalar Single-FP Compare - Equal (ordered, non-signaling) +NN_vcmpltss, // Scalar Single-FP Compare - Less-than (ordered, signaling) +NN_vcmpless, // Scalar Single-FP Compare - Less-than-or-equal (ordered, signaling) +NN_vcmpunordss, // Scalar Single-FP Compare - Unordered (non-signaling) +NN_vcmpneqss, // Scalar Single-FP Compare - Not-equal (unordered, non-signaling) +NN_vcmpnltss, // Scalar Single-FP Compare - Not-less-than (unordered, signaling) +NN_vcmpnless, // Scalar Single-FP Compare - Not-less-than-or-equal (unordered, signaling) +NN_vcmpordss, // Scalar Single-FP Compare - Ordered (non-signaling) +NN_vcmpeq_uqss, // Scalar Single-FP Compare - Equal (unordered, non-signaling) +NN_vcmpngess, // Scalar Single-FP Compare - Not-greater-than-or-equal (unordered, signaling) +NN_vcmpngtss, // Scalar Single-FP Compare - Not-greater-than (unordered, signaling) +NN_vcmpfalsess, // Scalar Single-FP Compare - False (ordered, non-signaling) +NN_vcmpneq_oqss, // Scalar Single-FP Compare - Not-equal (ordered, non-signaling) +NN_vcmpgess, // Scalar Single-FP Compare - Greater-than-or-equal (ordered, signaling) +NN_vcmpgtss, // Scalar Single-FP Compare - Greater-than (ordered, signaling) +NN_vcmptruess, // Scalar Single-FP Compare - True (unordered, non-signaling) +NN_vcmpeq_osss, // Scalar Single-FP Compare - Equal (ordered, signaling) +NN_vcmplt_oqss, // Scalar Single-FP Compare - Less-than (ordered, non-signaling) +NN_vcmple_oqss, // Scalar Single-FP Compare - Less-than-or-equal (ordered, non-signaling) +NN_vcmpunord_sss, // Scalar Single-FP Compare - Unordered (signaling) +NN_vcmpneq_usss, // Scalar Single-FP Compare - Not-equal (unordered, signaling) +NN_vcmpnlt_uqss, // Scalar Single-FP Compare - Not-less-than (unordered, non-signaling) +NN_vcmpnle_uqss, // Scalar Single-FP Compare - Not-less-than-or-equal (unordered, non-signaling) +NN_vcmpord_sss, // Scalar Single-FP Compare - Ordered (signaling) +NN_vcmpeq_usss, // Scalar Single-FP Compare - Equal (unordered, signaling) +NN_vcmpnge_uqss, // Scalar Single-FP Compare - Not-greater-than-or-equal (unordered, non-signaling) +NN_vcmpngt_uqss, // Scalar Single-FP Compare - Not-greater-than (unordered, non-signaling) +NN_vcmpfalse_osss, // Scalar Single-FP Compare - False (ordered, signaling) +NN_vcmpneq_osss, // Scalar Single-FP Compare - Not-equal (ordered, signaling) +NN_vcmpge_oqss, // Scalar Single-FP Compare - Greater-than-or-equal (ordered, non-signaling) +NN_vcmpgt_oqss, // Scalar Single-FP Compare - Greater-than (ordered, non-signaling) +NN_vcmptrue_usss, // Scalar Single-FP Compare - True (unordered, signaling) + +// AVX-512 instructions + +NN_valignd, // Align Doubleword Vectors +NN_valignq, // Align Quadword Vectors +NN_vblendmpd, // Blend Float64 Vectors Using an OpMask Control +NN_vblendmps, // Blend Float32 Vectors Using an OpMask Control +NN_vpblendmb, // Blend Byte Vectors Using an Opmask Control +NN_vpblendmw, // Blend Word Vectors Using an Opmask Control +NN_vpblendmd, // Blend Int32 Vectors Using an OpMask Control +NN_vpblendmq, // Blend Int64 Vectors Using an OpMask Control +NN_vbroadcastf32x2, // Load with Broadcast Floating-Point Data +NN_vbroadcastf32x4, // Load with Broadcast Floating-Point Data +NN_vbroadcastf64x2, // Load with Broadcast Floating-Point Data +NN_vbroadcastf32x8, // Load with Broadcast Floating-Point Data +NN_vbroadcastf64x4, // Load with Broadcast Floating-Point Data +NN_vbroadcasti32x2, // Load Integer and Broadcast +NN_vbroadcasti32x4, // Load Integer and Broadcast +NN_vbroadcasti64x2, // Load Integer and Broadcast +NN_vbroadcasti32x8, // Load Integer and Broadcast +NN_vbroadcasti64x4, // Load Integer and Broadcast +NN_vcompresspd, // Store Sparse Packed Double-Precision Floating-Point Values into Dense Memory +NN_vcompressps, // Store Sparse Packed Single-Precision Floating-Point Values into Dense Memory +NN_vcvtpd2qq, // Convert Packed Double-Precision Floating-Point Values to Packed Quadword Integers +NN_vcvtpd2udq, // Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers +NN_vcvtpd2uqq, // Convert Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers +NN_vcvtps2udq, // Convert Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values +NN_vcvtps2qq, // Convert Packed Single Precision Floating-Point Values to Packed Singed Quadword Integer Values +NN_vcvtps2uqq, // Convert Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values +NN_vcvtqq2pd, // Convert Packed Quadword Integers to Packed Double-Precision Floating-Point Values +NN_vcvtqq2ps, // Convert Packed Quadword Integers to Packed Single-Precision Floating-Point Values +NN_vcvtsd2usi, // Convert Scalar Double-Precision Floating-Point Value to Unsigned Doubleword Integer +NN_vcvtss2usi, // Convert Scalar Single-Precision Floating-Point Value to Unsigned Doubleword Integer +NN_vcvttpd2qq, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Quadword Integers +NN_vcvttpd2udq, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Doubleword Integers +NN_vcvttpd2uqq, // Convert with Truncation Packed Double-Precision Floating-Point Values to Packed Unsigned Quadword Integers +NN_vcvttps2udq, // Convert with Truncation Packed Single-Precision Floating-Point Values to Packed Unsigned Doubleword Integer Values +NN_vcvttps2qq, // Convert with Truncation Packed Single Precision Floating-Point Values to Packed Singed Quadword Integer Values +NN_vcvttps2uqq, // Convert with Truncation Packed Single Precision Floating-Point Values to Packed Unsigned Quadword Integer Values +NN_vcvttsd2usi, // Convert with Truncation Scalar Double-Precision Floating-Point Value to Unsigned Integer +NN_vcvttss2usi, // Convert with Truncation Scalar Single-Precision Floating-Point Value to Unsigned Integer +NN_vcvtudq2pd, // Convert Packed Unsigned Doubleword Integers to Packed Double-Precision Floating-Point Values +NN_vcvtudq2ps, // Convert Packed Unsigned Doubleword Integers to Packed Single-Precision Floating-Point Values +NN_vcvtuqq2pd, // Convert Packed Unsigned Quadword Integers to Packed Double-Precision Floating-Point Values +NN_vcvtuqq2ps, // Convert Packed Unsigned Quadword Integers to Packed Single-Precision Floating-Point Values +NN_vcvtusi2sd, // Convert Unsigned Integer to Scalar Double-Precision Floating-Point Value +NN_vcvtusi2ss, // Convert Unsigned Integer to Scalar Single-Precision Floating-Point Value +NN_vdbpsadbw, // Double Block Packed Sum-Absolute-Differences (SAD) on Unsigned Bytes +NN_vexpandpd, // Load Sparse Packed Double-Precision Floating-Point Values from Dense Memory +NN_vexpandps, // Load Sparse Packed Single-Precision Floating-Point Values from Dense Memory +NN_vextractf32x4, // Extract Packed Floating-Point Values +NN_vextractf64x2, // Extract Packed Floating-Point Values +NN_vextractf32x8, // Extract Packed Floating-Point Values +NN_vextractf64x4, // Extract Packed Floating-Point Values +NN_vextracti32x4, // Extract packed Integer Values +NN_vextracti64x2, // Extract packed Integer Values +NN_vextracti32x8, // Extract packed Integer Values +NN_vextracti64x4, // Extract packed Integer Values +NN_vfixupimmpd, // Fix Up Special Packed Float64 Values +NN_vfixupimmps, // Fix Up Special Packed Float32 Values +NN_vfixupimmsd, // Fix Up Special Scalar Float64 Value +NN_vfixupimmss, // Fix Up Special Scalar Float32 Value +NN_vfpclasspd, // Tests Types Of a Packed Float64 Values +NN_vfpclassps, // Tests Types Of a Packed Float32 Values +NN_vfpclasssd, // Tests Types Of a Scalar Float64 Values +NN_vfpclassss, // Tests Types Of a Scalar Float32 Values +NN_vgetexppd, // Convert Exponents of Packed DP FP Values to DP FP Values +NN_vgetexpps, // Convert Exponents of Packed SP FP Values to SP FP Values +NN_vgetexpsd, // Convert Exponents of Scalar DP FP Values to DP FP Value +NN_vgetexpss, // Convert Exponents of Scalar SP FP Values to SP FP Value +NN_vgetmantpd, // Extract Float64 Vector of Normalized Mantissas from Float64 Vector +NN_vgetmantps, // Extract Float32 Vector of Normalized Mantissas from Float32 Vector +NN_vgetmantsd, // Extract Float64 of Normalized Mantissas from Float64 Scalar +NN_vgetmantss, // Extract Float32 Vector of Normalized Mantissa from Float32 Vector +NN_vinsertf32x4, // Insert Packed Floating-Point Values +NN_vinsertf64x2, // Insert Packed Floating-Point Values +NN_vinsertf32x8, // Insert Packed Floating-Point Values +NN_vinsertf64x4, // Insert Packed Floating-Point Values +NN_vinserti32x4, // Insert Packed Integer Values +NN_vinserti64x2, // Insert Packed Integer Values +NN_vinserti32x8, // Insert Packed Integer Values +NN_vinserti64x4, // Insert Packed Integer Values +NN_vmovdqa32, // Move Aligned Packed Integer Values +NN_vmovdqa64, // Move Aligned Packed Integer Values +NN_vmovdqu8, // Move Unaligned Packed Integer Values +NN_vmovdqu16, // Move Unaligned Packed Integer Values +NN_vmovdqu32, // Move Unaligned Packed Integer Values +NN_vmovdqu64, // Move Unaligned Packed Integer Values +NN_vpabsq, // Packed Absolute Value +NN_vpandd, // Logical AND +NN_vpandq, // Logical AND +NN_vpandnd, // Logical AND NOT +NN_vpandnq, // Logical AND NOT +NN_vpbroadcastmb2q, // Broadcast Mask to Vector Register +NN_vpbroadcastmw2d, // Broadcast Mask to Vector Register +NN_vpcmpb, // Compare Packed Byte Values Into Mask +NN_vpcmpub, // Compare Packed Byte Values Into Mask +NN_vpcmpd, // Compare Packed Integer Values into Mask +NN_vpcmpud, // Compare Packed Integer Values into Mask +NN_vpcmpq, // Compare Packed Integer Values into Mask +NN_vpcmpuq, // Compare Packed Integer Values into Mask +NN_vpcmpw, // Compare Packed Word Values Into Mask +NN_vpcmpuw, // Compare Packed Word Values Into Mask +NN_vpcompressd, // Store Sparse Packed Doubleword Integer Values into Dense Memory/Register +NN_vpcompressq, // Store Sparse Packed Quadword Integer Values into Dense Memory/Register +NN_vpconflictd, // Detect Conflicts Within a Vector of Packed Dword Values into Dense Memory/Register +NN_vpconflictq, // Detect Conflicts Within a Vector of Packed Qword Values into Dense Memory/Register +NN_vpermb, // Permute Packed Bytes Elements +NN_vpermw, // Permute Packed Words Elements +NN_vpermi2b, // Full Permute of Bytes From Two Tables Overwriting the Index +NN_vpermi2w, // Full Permute From Two Tables Overwriting the Index +NN_vpermi2d, // Full Permute From Two Tables Overwriting the Index +NN_vpermi2q, // Full Permute From Two Tables Overwriting the Index +NN_vpermi2ps, // Full Permute From Two Tables Overwriting the Index +NN_vpermi2pd, // Full Permute From Two Tables Overwriting the Index +NN_vpermt2b, // Full Permute of Bytes From Two Tables Overwriting a Table +NN_vpermt2w, // Full Permute from Two Tables Overwriting one Table +NN_vpermt2d, // Full Permute from Two Tables Overwriting one Table +NN_vpermt2q, // Full Permute from Two Tables Overwriting one Table +NN_vpermt2ps, // Full Permute from Two Tables Overwriting one Table +NN_vpermt2pd, // Full Permute from Two Tables Overwriting one Table +NN_vpexpandd, // Load Sparse Packed Doubleword Integer Values from Dense Memory/Register +NN_vpexpandq, // Load Sparse Packed Quadword Integer Values from Dense Memory/Register +NN_vplzcntd, // Count the Number of Leading Zero Bits for Packed Dword Values +NN_vplzcntq, // Count the Number of Leading Zero Bits for Packed Qword Values +NN_vpmadd52luq, // Packed Multiply of Unsigned 52-bit Integers and Add the Low 52-bit Products to Qword Accumulators +NN_vpmadd52huq, // Packed Multiply of Unsigned 52-bit Unsigned Integers and Add High 52-bit Products to 64-bit Accumulators +NN_vpmaxsq, // Maximum of Packed Signed Integers +NN_vpmaxuq, // Maximum of Packed Unsigned Integers +NN_vpminsq, // Minimum of Packed Signed Integers +NN_vpminuq, // Minimum of Packed Unsigned Integers +NN_vpmovm2b, // Convert a Mask Register to a Vector Register +NN_vpmovm2w, // Convert a Mask Register to a Vector Register +NN_vpmovm2d, // Convert a Mask Register to a Vector Register +NN_vpmovm2q, // Convert a Mask Register to a Vector Register +NN_vpmovb2m, // Convert a Vector Register to a Mask +NN_vpmovw2m, // Convert a Vector Register to a Mask +NN_vpmovd2m, // Convert a Vector Register to a Mask +NN_vpmovq2m, // Convert a Vector Register to a Mask +NN_vpmovqb, // Down Convert QWord to Byte +NN_vpmovsqb, // Down Convert QWord to Byte +NN_vpmovusqb, // Down Convert QWord to Byte +NN_vpmovqw, // Down Convert QWord to Word +NN_vpmovsqw, // Down Convert QWord to Word +NN_vpmovusqw, // Down Convert QWord to Word +NN_vpmovqd, // Down Convert QWord to DWord +NN_vpmovsqd, // Down Convert QWord to DWord +NN_vpmovusqd, // Down Convert QWord to DWord +NN_vpmovdb, // Down Convert DWord to Byte +NN_vpmovsdb, // Down Convert DWord to Byte +NN_vpmovusdb, // Down Convert DWord to Byte +NN_vpmovdw, // Down Convert DWord to Word +NN_vpmovsdw, // Down Convert DWord to Word +NN_vpmovusdw, // Down Convert DWord to Word +NN_vpmovwb, // Down Convert Word to Byte +NN_vpmovswb, // Down Convert Word to Byte +NN_vpmovuswb, // Down Convert Word to Byte +NN_vpmullq, // Multiply Packed Integers and Store Low Result +NN_vpmultishiftqb, // Select Packed Unaligned Bytes from Quadword Sources +NN_vpord, // Bitwise Logical Or +NN_vporq, // Bitwise Logical Or +NN_vprold, // Bit Rotate Left +NN_vprolvd, // Bit Rotate Left +NN_vprolq, // Bit Rotate Left +NN_vprolvq, // Bit Rotate Left +NN_vprord, // Bit Rotate Right +NN_vprorvd, // Bit Rotate Right +NN_vprorq, // Bit Rotate Right +NN_vprorvq, // Bit Rotate Right +NN_vpscatterdd, // Scatter Packed Dword with Signed Dword +NN_vpscatterdq, // Scatter Packed Qword with Signed Qword Indices +NN_vpscatterqd, // Scatter Packed Dword with Signed Dword +NN_vpscatterqq, // Scatter Packed Qword with Signed Qword Indices +NN_vpsraq, // Bit Shift Arithmetic Right +NN_vpsllvw, // Variable Bit Shift Left Logical +NN_vpsrlvw, // Variable Bit Shift Right Logical +NN_vptestnmb, // Logical NAND and Set +NN_vptestnmw, // Logical NAND and Set +NN_vptestnmd, // Logical NAND and Set +NN_vptestnmq, // Logical NAND and Set +NN_vshuff32x4, // Shuffle Packed Values at 128-bit Granularity +NN_vshuff64x2, // Shuffle Packed Values at 128-bit Granularity +NN_vshufi32x4, // Shuffle Packed Values at 128-bit Granularity +NN_vshufi64x2, // Shuffle Packed Values at 128-bit Granularity +NN_vpternlogd, // Bitwise Ternary Logic +NN_vpternlogq, // Bitwise Ternary Logic +NN_vptestmb, // Logical AND and Set Mask +NN_vptestmw, // Logical AND and Set Mask +NN_vptestmd, // Logical AND and Set Mask +NN_vptestmq, // Logical AND and Set Mask +NN_vpsravw, // Variable Bit Shift Right Arithmetic +NN_vpsravq, // Variable Bit Shift Right Arithmetic +NN_vpxord, // Exclusive Or +NN_vpxorq, // Exclusive Or +NN_vrangepd, // Range Restriction Calculation For Packed Pairs of Float64 Values +NN_vrangeps, // Range Restriction Calculation For Packed Pairs of Float32 Values +NN_vrangesd, // Range Restriction Calculation From a pair of Scalar Float64 Values +NN_vrangess, // Range Restriction Calculation From a Pair of Scalar Float32 Values +NN_vrcp14pd, // Compute Approximate Reciprocals of Packed Float64 Values +NN_vrcp14sd, // Compute Approximate Reciprocal of Scalar Float64 Value +NN_vrcp14ps, // Compute Approximate Reciprocals of Packed Float32 Values +NN_vrcp14ss, // Compute Approximate Reciprocal of Scalar Float32 Value +NN_vreducepd, // Perform Reduction Transformation on Packed Float64 Values +NN_vreducesd, // Perform a Reduction Transformation on a Scalar Float64 Value +NN_vreduceps, // Perform Reduction Transformation on Packed Float32 Values +NN_vreducess, // Perform a Reduction Transformation on a Scalar Float32 Value +NN_vrndscalepd, // Round Packed Float64 Values To Include A Given Number Of Fraction Bits +NN_vrndscalesd, // Round Scalar Float64 Value To Include A Given Number Of Fraction Bits +NN_vrndscaleps, // Round Packed Float32 Values To Include A Given Number Of Fraction Bits +NN_vrndscaless, // Round Scalar Float32 Value To Include A Given Number Of Fraction Bits +NN_vrsqrt14pd, // Compute Approximate Reciprocals of Square Roots of Packed Float64 Values +NN_vrsqrt14sd, // Compute Approximate Reciprocal of Square Root of Scalar Float64 Value +NN_vrsqrt14ps, // Compute Approximate Reciprocals of Square Roots of Packed Float32 Values +NN_vrsqrt14ss, // Compute Approximate Reciprocal of Square Root of Scalar Float32 Value +NN_vscalefpd, // Scale Packed Float64 Values With Float64 Values +NN_vscalefsd, // Scale Scalar Float64 Values With Float64 Values +NN_vscalefps, // Scale Packed Float32 Values With Float32 Values +NN_vscalefss, // Scale Scalar Float32 Value With Float32 Value +NN_vscatterdps, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices +NN_vscatterdpd, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices +NN_vscatterqps, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices +NN_vscatterqpd, // Scatter Packed Single, Packed Double with Signed Dword and Qword Indices + +NN_vexp2pd, // Approximation to the Exponential 2^x of Packed Double-Precision Floating-Point Values with Less Than 2^-23 Relative Error +NN_vexp2ps, // Approximation to the Exponential 2^x of Packed Single-Precision Floating-Point Values with Less Than 2^-23 Relative Error +NN_vrcp28pd, // Approximation to the Reciprocal of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error +NN_vrcp28sd, // Approximation to the Reciprocal of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error +NN_vrcp28ps, // Approximation to the Reciprocal of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error +NN_vrcp28ss, // Approximation to the Reciprocal of Scalar Single-Precision Floating-Point Value with Less Than 2^-28 Relative Error +NN_vrsqrt28pd, // Approximation to the Reciprocal Square Root of Packed Double-Precision Floating-Point Values with Less Than 2^-28 Relative Error +NN_vrsqrt28sd, // Approximation to the Reciprocal Square Root of Scalar Double-Precision Floating-Point Value with Less Than 2^-28 Relative Error +NN_vrsqrt28ps, // Approximation to the Reciprocal Square Root of Packed Single-Precision Floating-Point Values with Less Than 2^-28 Relative Error +NN_vrsqrt28ss, // Approximation to the Reciprocal Square Root of Scalar Single-Precision Floating-Point Value with Less Than 2^-28 Relative Error + +NN_vgatherpf0dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint +NN_vgatherpf0qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint +NN_vgatherpf0dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint +NN_vgatherpf0qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint +NN_vgatherpf1dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint +NN_vgatherpf1qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint +NN_vgatherpf1dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint +NN_vgatherpf1qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint +NN_vscatterpf0dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write +NN_vscatterpf0qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write +NN_vscatterpf0dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write +NN_vscatterpf0qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T0 Hint with Intent to Write +NN_vscatterpf1dps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write +NN_vscatterpf1qps, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write +NN_vscatterpf1dpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write +NN_vscatterpf1qpd, // Sparse Prefetch Packed SP/DP Data Values with Signed Dword, Signed Qword Indices Using T1 Hint with Intent to Write + +// AVX-512 comparison pseudo-ops + +NN_vpcmpltd, // Compare Packed Integer Values into Mask +NN_vpcmpled, // Compare Packed Integer Values into Mask +NN_vpcmpneqd, // Compare Packed Integer Values into Mask +NN_vpcmpnltd, // Compare Packed Integer Values into Mask +NN_vpcmpnled, // Compare Packed Integer Values into Mask + +NN_vpcmpequd, // Compare Packed Integer Values into Mask +NN_vpcmpltud, // Compare Packed Integer Values into Mask +NN_vpcmpleud, // Compare Packed Integer Values into Mask +NN_vpcmpnequd, // Compare Packed Integer Values into Mask +NN_vpcmpnltud, // Compare Packed Integer Values into Mask +NN_vpcmpnleud, // Compare Packed Integer Values into Mask + +NN_vpcmpltq, // Compare Packed Integer Values into Mask +NN_vpcmpleq, // Compare Packed Integer Values into Mask +NN_vpcmpneqq, // Compare Packed Integer Values into Mask +NN_vpcmpnltq, // Compare Packed Integer Values into Mask +NN_vpcmpnleq, // Compare Packed Integer Values into Mask + +NN_vpcmpequq, // Compare Packed Integer Values into Mask +NN_vpcmpltuq, // Compare Packed Integer Values into Mask +NN_vpcmpleuq, // Compare Packed Integer Values into Mask +NN_vpcmpnequq, // Compare Packed Integer Values into Mask +NN_vpcmpnltuq, // Compare Packed Integer Values into Mask +NN_vpcmpnleuq, // Compare Packed Integer Values into Mask + +// Opmask instructions + +NN_kaddw, // ADD Two Masks +NN_kaddb, // ADD Two Masks +NN_kaddq, // ADD Two Masks +NN_kaddd, // ADD Two Masks +NN_kandw, // Bitwise Logical AND Masks +NN_kandb, // Bitwise Logical AND Masks +NN_kandq, // Bitwise Logical AND Masks +NN_kandd, // Bitwise Logical AND Masks +NN_kandnw, // Bitwise Logical AND NOT Masks +NN_kandnb, // Bitwise Logical AND NOT Masks +NN_kandnq, // Bitwise Logical AND NOT Masks +NN_kandnd, // Bitwise Logical AND NOT Masks +NN_kmovw, // Move from and to Mask Registers +NN_kmovb, // Move from and to Mask Registers +NN_kmovq, // Move from and to Mask Registers +NN_kmovd, // Move from and to Mask Registers +NN_kunpckbw, // Unpack for Mask Registers +NN_kunpckwd, // Unpack for Mask Registers +NN_kunpckdq, // Unpack for Mask Registers +NN_knotw, // NOT Mask Register +NN_knotb, // NOT Mask Register +NN_knotq, // NOT Mask Register +NN_knotd, // NOT Mask Register +NN_korw, // Bitwise Logical OR Masks +NN_korb, // Bitwise Logical OR Masks +NN_korq, // Bitwise Logical OR Masks +NN_kord, // Bitwise Logical OR Masks +NN_kortestw, // OR Masks And Set Flags +NN_kortestb, // OR Masks And Set Flags +NN_kortestq, // OR Masks And Set Flags +NN_kortestd, // OR Masks And Set Flags +NN_kshiftlw, // Shift Left Mask Registers +NN_kshiftlb, // Shift Left Mask Registers +NN_kshiftlq, // Shift Left Mask Registers +NN_kshiftld, // Shift Left Mask Registers +NN_kshiftrw, // Shift Right Mask Registers +NN_kshiftrb, // Shift Right Mask Registers +NN_kshiftrq, // Shift Right Mask Registers +NN_kshiftrd, // Shift Right Mask Registers +NN_kxnorw, // Bitwise Logical XNOR Masks +NN_kxnorb, // Bitwise Logical XNOR Masks +NN_kxnorq, // Bitwise Logical XNOR Masks +NN_kxnord, // Bitwise Logical XNOR Masks +NN_ktestw, // Packed Bit Test Masks and Set Flags +NN_ktestb, // Packed Bit Test Masks and Set Flags +NN_ktestq, // Packed Bit Test Masks and Set Flags +NN_ktestd, // Packed Bit Test Masks and Set Flags +NN_kxorw, // Bitwise Logical XOR Masks +NN_kxorb, // Bitwise Logical XOR Masks +NN_kxorq, // Bitwise Logical XOR Masks +NN_kxord, // Bitwise Logical XOR Masks + +// SHA Extensions + +NN_sha1rnds4, // Perform Four Rounds of SHA1 Operation +NN_sha1nexte, // Calculate SHA1 State Variable E after Four Rounds +NN_sha1msg1, // Perform an Intermediate Calculation for the Next Four SHA1 Message Dwords +NN_sha1msg2, // Perform a Final Calculation for the Next Four SHA1 Message Dwords +NN_sha256rnds2, // Perform Two Rounds of SHA256 Operation +NN_sha256msg1, // Perform an Intermediate Calculation for the Next Four SHA256 Message Dwords +NN_sha256msg2, // Perform a Final Calculation for the Next Four SHA256 Message Dwords + +// Intel Software Guard Extensions + +NN_encls, // Execute an Enclave System Function of Specified Leaf Number +NN_enclu, // Execute an Enclave User Function of Specified Leaf Number + +// AMD XOP + +NN_vfrczpd, // Extract Fraction Packed Double-Precision Floating-Point +NN_vfrczps, // Extract Fraction Packed Single-Precision Floating-Point +NN_vfrczsd, // Extract Fraction Scalar Double-Precision Floating-Point +NN_vfrczss, // Extract Fraction Scalar Single-Precision Floating Point +NN_vpcmov, // Vector Conditional Moves +NN_vpcomb, // Compare Vector Signed Bytes +NN_vpcomd, // Compare Vector Signed Doublewords +NN_vpcomq, // Compare Vector Signed Quadwords +NN_vpcomub, // Compare Vector Unsigned Bytes +NN_vpcomud, // Compare Vector Unsigned Doublewords +NN_vpcomuq, // Compare Vector Unsigned Quadwords +NN_vpcomuw, // Compare Vector Unsigned Words +NN_vpcomw, // Compare Vector Signed Words +NN_vpermil2pd, // Permute Two-Source Double-Precision Floating-Point Values +NN_vpermil2ps, // Permute Two-Source Single-Precision Floating-Point Values +NN_vphaddbd, // Packed Horizontal Add Signed Byte to Signed Doubleword +NN_vphaddbq, // Packed Horizontal Add Signed Byte to Signed Quadword +NN_vphaddbw, // Packed Horizontal Add Signed Byte to Signed Word +NN_vphadddq, // Packed Horizontal Add Signed Doubleword to Signed Quadword +NN_vphaddubd, // Packed Horizontal Add Unsigned Byte to Doubleword +NN_vphaddubq, // Packed Horizontal Add Unsigned Byte to Quadword +NN_vphaddubw, // Packed Horizontal Add Unsigned Byte to Word +NN_vphaddudq, // Packed Horizontal Add Unsigned Doubleword to Quadword +NN_vphadduwd, // Packed Horizontal Add Unsigned Word to Doubleword +NN_vphadduwq, // Packed Horizontal Add Unsigned Word to Quadword +NN_vphaddwd, // Packed Horizontal Add Signed Word to Signed Doubleword +NN_vphaddwq, // Packed Horizontal Add Signed Word to Signed Quadword +NN_vphsubbw, // Packed Horizontal Subtract Signed Byte to Signed Word +NN_vphsubdq, // Packed Horizontal Subtract Signed Doubleword to Signed Quadword +NN_vphsubwd, // Packed Horizontal Subtract Signed Word to Signed Doubleword +NN_vpmacsdd, // Packed Multiply Accumulate Signed Doubleword to Signed Doubleword +NN_vpmacsdqh, // Packed Multiply Accumulate Signed High Doubleword to Signed Quadword +NN_vpmacsdql, // Packed Multiply Accumulate Signed Low Doubleword to Signed Quadword +NN_vpmacssdd, // Packed Multiply Accumulate Signed Doubleword to Signed Doubleword with Saturation +NN_vpmacssdqh, // Packed Multiply Accumulate Signed High Doubleword to Signed Quadword with Saturation +NN_vpmacssdql, // Packed Multiply Accumulate Signed Low Doubleword to Signed Quadword with Saturation +NN_vpmacsswd, // Packed Multiply Accumulate Signed Word to Signed Doubleword with Saturation +NN_vpmacssww, // Packed Multiply Accumulate Signed Word to Signed Word with Saturation +NN_vpmacswd, // Packed Multiply Accumulate Signed Word to Signed Doubleword +NN_vpmacsww, // Packed Multiply Accumulate Signed Word to Signed Word +NN_vpmadcsswd, // Packed Multiply, Add and Accumulate Signed Word to Signed Doubleword with Saturation +NN_vpmadcswd, // Packed Multiply Add and Accumulate Signed Word to Signed Doubleword +NN_vpperm, // Packed Permute Bytes +NN_vprotb, // Packed Rotate Bytes +NN_vprotd, // Packed Rotate Doublewords +NN_vprotq, // Packed Rotate Quadwords +NN_vprotw, // Packed Rotate Words +NN_vpshab, // Packed Shift Arithmetic Bytes +NN_vpshad, // Packed Shift Arithmetic Doublewords +NN_vpshaq, // Packed Shift Arithmetic Quadwords +NN_vpshaw, // Packed Shift Arithmetic Words +NN_vpshlb, // Packed Shift Logical Bytes +NN_vpshld, // Packed Shift Logical Doublewords +NN_vpshlq, // Packed Shift Logical Quadwords +NN_vpshlw, // Packed Shift Logical Words + +// AMD XOP comparison pseudo-ops + +NN_vpcomltb, // Compare Vector Signed Bytes +NN_vpcomleb, // Compare Vector Signed Bytes +NN_vpcomgtb, // Compare Vector Signed Bytes +NN_vpcomgeb, // Compare Vector Signed Bytes +NN_vpcomeqb, // Compare Vector Signed Bytes +NN_vpcomneqb, // Compare Vector Signed Bytes +NN_vpcomfalseb, // Compare Vector Signed Bytes +NN_vpcomtrueb, // Compare Vector Signed Bytes + +NN_vpcomltw, // Compare Vector Signed Words +NN_vpcomlew, // Compare Vector Signed Words +NN_vpcomgtw, // Compare Vector Signed Words +NN_vpcomgew, // Compare Vector Signed Words +NN_vpcomeqw, // Compare Vector Signed Words +NN_vpcomneqw, // Compare Vector Signed Words +NN_vpcomfalsew, // Compare Vector Signed Words +NN_vpcomtruew, // Compare Vector Signed Words + +NN_vpcomltd, // Compare Vector Signed Doublewords +NN_vpcomled, // Compare Vector Signed Doublewords +NN_vpcomgtd, // Compare Vector Signed Doublewords +NN_vpcomged, // Compare Vector Signed Doublewords +NN_vpcomeqd, // Compare Vector Signed Doublewords +NN_vpcomneqd, // Compare Vector Signed Doublewords +NN_vpcomfalsed, // Compare Vector Signed Doublewords +NN_vpcomtrued, // Compare Vector Signed Doublewords + +NN_vpcomltq, // Compare Vector Signed Quadwords +NN_vpcomleq, // Compare Vector Signed Quadwords +NN_vpcomgtq, // Compare Vector Signed Quadwords +NN_vpcomgeq, // Compare Vector Signed Quadwords +NN_vpcomeqq, // Compare Vector Signed Quadwords +NN_vpcomneqq, // Compare Vector Signed Quadwords +NN_vpcomfalseq, // Compare Vector Signed Quadwords +NN_vpcomtrueq, // Compare Vector Signed Quadwords + +NN_vpcomltub, // Compare Vector Unsigned Bytes +NN_vpcomleub, // Compare Vector Unsigned Bytes +NN_vpcomgtub, // Compare Vector Unsigned Bytes +NN_vpcomgeub, // Compare Vector Unsigned Bytes +NN_vpcomequb, // Compare Vector Unsigned Bytes +NN_vpcomnequb, // Compare Vector Unsigned Bytes +NN_vpcomfalseub, // Compare Vector Unsigned Bytes +NN_vpcomtrueub, // Compare Vector Unsigned Bytes + +NN_vpcomltuw, // Compare Vector Unsigned Words +NN_vpcomleuw, // Compare Vector Unsigned Words +NN_vpcomgtuw, // Compare Vector Unsigned Words +NN_vpcomgeuw, // Compare Vector Unsigned Words +NN_vpcomequw, // Compare Vector Unsigned Words +NN_vpcomnequw, // Compare Vector Unsigned Words +NN_vpcomfalseuw, // Compare Vector Unsigned Words +NN_vpcomtrueuw, // Compare Vector Unsigned Words + +NN_vpcomltud, // Compare Vector Unsigned Doublewords +NN_vpcomleud, // Compare Vector Unsigned Doublewords +NN_vpcomgtud, // Compare Vector Unsigned Doublewords +NN_vpcomgeud, // Compare Vector Unsigned Doublewords +NN_vpcomequd, // Compare Vector Unsigned Doublewords +NN_vpcomnequd, // Compare Vector Unsigned Doublewords +NN_vpcomfalseud, // Compare Vector Unsigned Doublewords +NN_vpcomtrueud, // Compare Vector Unsigned Doublewords + +NN_vpcomltuq, // Compare Vector Unsigned Quadwords +NN_vpcomleuq, // Compare Vector Unsigned Quadwords +NN_vpcomgtuq, // Compare Vector Unsigned Quadwords +NN_vpcomgeuq, // Compare Vector Unsigned Quadwords +NN_vpcomequq, // Compare Vector Unsigned Quadwords +NN_vpcomnequq, // Compare Vector Unsigned Quadwords +NN_vpcomfalseuq, // Compare Vector Unsigned Quadwords +NN_vpcomtrueuq, // Compare Vector Unsigned Quadwords + +// AMD Excavator + +NN_monitorx, // Setup Monitor Address +NN_mwaitx, // Monitor Wait with Timeout + +// AMD Zen + +NN_clzero, // Zero out 64 byte cache + +// Intel Processor Trace + +NN_ptwrite, // Write Data to a Processor Trace Packet + +// new Intel AVX-512 instructions (December 2016) + +NN_v4fmaddps, // Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations) +NN_v4fnmaddps, // Packed Single-Precision Floating-Point Fused Multiply-Add (4-iterations) +NN_v4fmaddss, // Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations) +NN_v4fnmaddss, // Scalar Single-Precision Floating-Point Fused Multiply-Add (4-iterations) +NN_vp4dpwssd, // Dot Product of Signed Words with Dword Accumulation (4-iterations) +NN_vp4dpwssds, // Dot Product of Signed Words with Dword Accumulation and Saturation (4-iterations) +NN_vpopcntd, // Return the Count of Number of Bits Set to 1 in DWORD +NN_vpopcntq, // Return the Count of Number of Bits Set to 1 in QWORD + +// Read Processor ID + +NN_rdpid, // Read Processor ID + +// Invoke VM function + +NN_vmfunc, // Invoke VM function + +// Control-flow Enforcement + +NN_incsspd, // Increment Shadow Stack Pointer (by 4) +NN_incsspq, // Increment Shadow Stack Pointer (by 8) +NN_rdsspd, // Read (low 32 bits of) Shadow Stack Pointer +NN_rdsspq, // Read Shadow Stack Pointer +NN_saveprevssp, // Save Previous Shadow Stack Pointer +NN_rstorssp, // Restore saved Shadow Stack Pointer +NN_wrssd, // Write (4 bytes) to shadow stack +NN_wrssq, // Write (8 bytes) to shadow stack +NN_wrussd, // Write (4 bytes) to User Shadow Stack +NN_wrussq, // Write (8 bytes) to User Shadow Stack +NN_setssbsy, // Mark Shadow Stack Busy +NN_clrssbsy, // Clear Shadow Stack Busy Flag +NN_endbr64, // Terminate an Indirect Branch in 64-bit Mode +NN_endbr32, // Terminate an Indirect Branch in 32-bit and Compatibility Mode + +// Undefined Instruction + +NN_ud0, // Undefined Instruction +NN_ud1, // Undefined Instruction + +// Enqueue Stores + +NN_enqcmd, // Enqueue Command +NN_enqcmds, // Enqueue Command Supervisor + +// AMD Zen2 + +NN_mcommit, // Commit Stores to Memory +NN_rdpru, // Read Processor Register + +// Intel Tremont instructions + +NN_cldemote, // Cache Line Demote +NN_enclv, // Execute an Enclave VMM Function of Specified Leaf Number + +// Direct Stores + +NN_movdiri, // Move Doubleword as Direct Store +NN_movdir64b, // Move 64 Bytes as Direct Store + +// Intel WAITPKG instructions + +NN_tpause, // Timed PAUSE +NN_umonitor, // User Level Set Up Monitor Address +NN_umwait, // User Level Monitor Wait + +// Intel Sapphire Rapids instructions + +NN_serialize, // Serialize Instruction Execution + +// Intel TSX + +NN_xresldtrk, // Resume Tracking Load Addresses +NN_xsusldtrk, // Suspend Tracking Load Addresses + +// Intel Affine Transformation instructions + +NN_gf2p8mulb, // Galois Field Multiply Bytes +NN_gf2p8affineqb, // Computes Affine Transformation +NN_gf2p8affineinvqb, // Computes Inverse Affine Transformation + +// VEX versions +NN_vgf2p8mulb, // Galois Field Multiply Bytes +NN_vgf2p8affineqb, // Computes Affine Transformation +NN_vgf2p8affineinvqb, // Computes Inverse Affine Transformation + +// Intrinsics for Saving and Restoring the Extended Processor States (64-bits) + +NN_fxsave64, // Fast save FP context (64-bits) +NN_fxrstor64, // Fast restore FP context (64-bits) + +NN_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +I5_null = 0, // Unknown Operation + +// +// Intel 8080-8085 instructions +// + +I5_aci, +I5_adc, Z80_adc = I5_adc, +I5_add, Z80_add = I5_add, +I5_adi, +I5_ana, +I5_ani, +I5_call, +I5_cnz, +I5_cz, +I5_cnc, +I5_cc, +I5_cpo, +I5_cpe, +I5_cp, +I5_cm, +I5_cmc, +I5_cmp, +I5_cpi, +I5_cma, +I5_daa, +I5_dad, +I5_dcr, +I5_dcx, +I5_di, Z80_di = I5_di, +I5_ei, Z80_ei = I5_ei, +I5_halt, +I5_in, Z80_in = I5_in, +I5_inr, +I5_inx, +I5_jmp, +I5_jnz, +I5_jz, +I5_jnc, +I5_jc, +I5_jpo, +I5_jpe, +I5_jp, +I5_jm, +I5_lda, +I5_ldax, +I5_lhld, +I5_lxi, +I5_mov, +I5_mvi, +I5_nop, +I5_ora, +I5_ori, +I5_out, Z80_out = I5_out, +I5_pchl, +I5_pop, Z80_pop = I5_pop, +I5_push, Z80_push = I5_push, +I5_ret, +I5_rnz, +I5_rz, +I5_rnc, +I5_rc, +I5_rpo, +I5_rpe, +I5_rp, +I5_rm, +I5_ral, +I5_rlc, +I5_rar, +I5_rrc, +I5_rst, +I5_sbb, +I5_sbi, +I5_stc, +I5_sphl, +I5_sta, +I5_stax, +I5_shld, +I5_sui, +I5_sub, Z80_sub = I5_sub, +I5_xra, +I5_xri, +I5_xchg, +I5_xthl, + +I5_rim, +I5_sim, + +// +// Z80 extensions +// + +Z80_and, +Z80_bit, +Z80_call, +Z80_ccf, +Z80_cp, +Z80_cpd, +Z80_cpdr, +Z80_cpi, +Z80_cpir, +Z80_cpl, +Z80_dec, +Z80_djnz, +Z80_ex, +Z80_exx, +Z80_halt, +Z80_im, +Z80_inc, +Z80_ind, +Z80_indr, +Z80_ini, +Z80_inir, +Z80_jp, +Z80_jr, +Z80_ld, +Z80_ldd, +Z80_lddr, +Z80_ldi, +Z80_ldir, +Z80_neg, +Z80_or, +Z80_otdr, +Z80_otir, +Z80_outd, +Z80_outi, +Z80_res, +Z80_ret, +Z80_reti, +Z80_retn, +Z80_rl, +Z80_rla, +Z80_rlc, +Z80_rlca, +Z80_rld, +Z80_rr, +Z80_rra, +Z80_rrc, +Z80_rrca, +Z80_rrd, +Z80_scf, +Z80_sbc, +Z80_set, +Z80_sla, +Z80_sra, +Z80_srl, +Z80_xor, +Z80_inp, // undocumented +Z80_outp, // undocumented +Z80_srr, // undocumented + +// +// HD64180 extensions +// + +HD_in0, Z80_in0 = HD_in0, +HD_mlt, Z80_mlt = HD_mlt, +HD_otim, Z80_otim = HD_otim, +HD_otimr, Z80_otimr = HD_otimr, +HD_otdm, Z80_otdm = HD_otdm, +HD_otdmr, Z80_otdmr = HD_otdmr, +HD_out0, Z80_out0 = HD_out0, +HD_slp, Z80_slp = HD_slp, +HD_tst, Z80_tst = HD_tst, +HD_tstio, Z80_tstio = HD_tstio, + +// +// A80 special instructions +// + +A80_lbcd, +A80_lded, +A80_lspd, +A80_lixd, +A80_liyd, +A80_sbcd, +A80_sded, +A80_sspd, +A80_sixd, +A80_siyd, +A80_xtix, +A80_xtiy, +A80_spix, +A80_spiy, +A80_pcix, +A80_pciy, +A80_mvra, +A80_mvia, +A80_mvar, +A80_mvai, +A80_addix, +A80_addiy, +A80_addc, +A80_addcix, +A80_addciy, +A80_subc, +A80_subcix, +A80_subciy, +A80_jrc, +A80_jrnc, +A80_jrz, +A80_jrnz, +A80_cmpi, +A80_cmpd, +A80_im0, +A80_im1, +A80_im2, +A80_otd, +A80_oti, + +// Intel 8085 undocumented instructions +// (info from http://oak.oakland.edu/pub/cpm/maclib/i8085.lib) + +I5_dsub, // (HL) <- (HL)-(BC), affects all flags +I5_arhl, // SHIFT HL RIGHT ONE BIT, (H7 IS DUPLICATED, L0 IS SHIFTED INTO CY) +I5_rdel, // ROTATE DE LEFT ONE BIT THRU CY, (E0 RECEIVES CY, CY RECEIVES D7) +I5_ldhi, // (DE) <- (HL)+arg +I5_ldsi, // (DE) <- (SP)+arg +I5_shlx, // ((DE)) <- (HL) +I5_lhlx, // (HL) <- ((DE)) +I5_rstv, // RESTART 40H ON V (OVERFLOW) +I5_jx5, // JUMP IF X5 SET +I5_jnx5, // JUMP IF NOT X5 SET + +// Z380 instructions + +Z80_cplw, // Complement HL register +Z80_swap, // Swap upper register word with lower register word +Z80_inw, // Input word +Z80_outw, // Output word +Z80_ldw, // Load word +Z80_addw, // Add word +Z80_subw, // Subtract word +Z80_adcw, // Add with carry word +Z80_sbcw, // Subtract with borrow word +Z80_andw, // AND logical word +Z80_xorw, // XOR logical word +Z80_orw, // OR logical word +Z80_cpw, // Compare word +Z80_ddir, // Decoder directive +Z80_calr, // Call relative +Z80_ldctl, // Load control register +Z80_mtest, // Mode test +Z80_exxx, // Exchange Index Register with Alternate Bank +Z80_exxy, // Exchange Index Register with Alternate Bank +Z80_exall, // Exchange all registers with Alternate Bank +Z80_setc, // Set control bit +Z80_resc, // Reset control bit +Z80_rlcw, // Rotate Left Circular Word +Z80_rrcw, // Rotate Right Circular Word +Z80_rlw, // Rotate Left Word +Z80_rrw, // Rotate Right Word +Z80_slaw, // Shift Left Arithmetic Word +Z80_sraw, // Shift Right Arithmetic Word +Z80_srlw, // Shift Right Logical Word +Z80_multw, // Multiply Word +Z80_multuw, // Multiply Word Unsigned +Z80_divuw, // Divide unsigned +Z80_outaw, // Output word direct to port address +Z80_inaw, // Input word direct from port address +Z80_outa, // Output byte direct to port address +Z80_ina, // Input byte direct from port address +Z80_negw, // Negate word +Z80_exts, // Extend byte sign +Z80_extsw, // Extend word sign +Z80_btest, // Bank test +Z80_ldiw, // Load and increment (word) +Z80_ldirw, // Load and increment, repeat (word) +Z80_lddw, // Load and decrement (word) +Z80_lddrw, // Load and decrement, repeat (word) +Z80_iniw, // Input and increment (word) +Z80_inirw, // Input and increment, repeat (word) +Z80_indw, // Input and decrement (word) +Z80_indrw, // Input and decrement, repeat (word) +Z80_outiw, // Output and increment (word) +Z80_otirw, // Output and increment, repeat (word) +Z80_outdw, // Output and decrement (word) +Z80_otdrw, // Output and decrement, repeat (word) + +// Gameboy instructions + +GB_ldh, +GB_stop, + +I5_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +I860_null = 0, // Unknown Operation + +// +// Intel 860 XP instructions +// + +I860_adds, +I860_addu, +I860_and, +I860_andh, +I860_andnot, +I860_andnoth, +I860_bc, +I860_bc_t, +I860_bla, +I860_bnc, +I860_bnc_t, +I860_br, +I860_bri, +I860_bte, +I860_btne, +I860_call, +I860_calli, +I860_fadd, +I860_faddp, +I860_faddz, +I860_famov, +I860_fiadd, +I860_fisub, +I860_fix, +I860_fld, +I860_flush, +I860_fmlow_dd, +I860_fmul, +I860_form, +I860_frcp, +I860_frsqr, +I860_fst, +I860_fsub, +I860_ftrunc, +I860_fxfr, +I860_fzchkl, +I860_fzchks, +I860_introvr, +I860_ixfr, +I860_ld_c, +I860_ld, +I860_ldint, +I860_ldio, +I860_lock, +I860_or, +I860_orh, +I860_pfadd, +I860_pfaddp, +I860_pfaddz, +I860_pfamov, +I860_pfeq, +I860_pfgt, +I860_pfiadd, +I860_pfisub, +I860_pfix, +I860_pfld, +I860_pfle, +I860_pfmul, +I860_pfmul3_dd, +I860_pform, +I860_pfsub, +I860_pftrunc, +I860_pfzchkl, +I860_pfzchks, +I860_pst_d, +I860_scyc, +I860_shl, +I860_shr, +I860_shra, +I860_shrd, +I860_st_c, +I860_st, +I860_stio, +I860_subs, +I860_subu, +I860_trap, +I860_unlock, +I860_xor, +I860_xorh, +// +// iNTEL 860 XP Pipelined F-P instructions +// +I860_r2p1, +I860_r2pt, +I860_r2ap1, +I860_r2apt, +I860_i2p1, +I860_i2pt, +I860_i2ap1, +I860_i2apt, +I860_rat1p2, +I860_m12apm, +I860_ra1p2, +I860_m12ttpa, +I860_iat1p2, +I860_m12tpm, +I860_ia1p2, +I860_m12tpa, +I860_r2s1, +I860_r2st, +I860_r2as1, +I860_r2ast, +I860_i2s1, +I860_i2st, +I860_i2as1, +I860_i2ast, +I860_rat1s2, +I860_m12asm, +I860_ra1s2, +I860_m12ttsa, +I860_iat1s2, +I860_m12tsm, +I860_ia1s2, +I860_m12tsa, +I860_mr2p1, +I860_mr2pt, +I860_mr2mp1, +I860_mr2mpt, +I860_mi2p1, +I860_mi2pt, +I860_mi2mp1, +I860_mi2mpt, +I860_mrmt1p2, +I860_mm12mpm, +I860_mrm1p2, +I860_mm12ttpm, +I860_mimt1p2, +I860_mm12tpm, +I860_mim1p2, +I860_mr2s1, +I860_mr2st, +I860_mr2ms1, +I860_mr2mst, +I860_mi2s1, +I860_mi2st, +I860_mi2ms1, +I860_mi2mst, +I860_mrmt1s2, +I860_mm12msm, +I860_mrm1s2, +I860_mm12ttsm, +I860_mimt1s2, +I860_mm12tsm, +I860_mim1s2, + +I860_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +I51_null = 0, // Unknown Operation + +I51_acall, // Absolute Call +I51_add, // Add Second Operand to Acc +I51_addc, // Add Second Operand to Acc with carry +I51_ajmp, // Absolute Jump +I51_anl, // Logical AND (op1 &= op2) +I51_cjne, // Compare Operands and JNE +I51_clr, // Clear Operand (0) +I51_cpl, // Complement Operand +I51_da, // Decimal Adjust Accumulator +I51_dec, // Decrement Operand +I51_div, // Divide Acc by B +I51_djnz, // Decrement Operand and JNZ +I51_inc, // Increment Operand +I51_jb, // Jump if Bit is set +I51_jbc, // Jump if Bit is set & clear Bit +I51_jc, // Jump if Carry is set +I51_jmp, // Jump indirect relative to Data Pointer +I51_jnb, // Jump if Bit is clear +I51_jnc, // Jump if Carry is clear +I51_jnz, // Jump if Acc is not zero +I51_jz, // Jump if Acc is zero +I51_lcall, // Long Subroutine Call +I51_ljmp, // Long Jump +I51_mov, // Move (Op1 <- Op2) +I51_movc, // Move code byte relative to second op to Acc +I51_movx, // Move from/to external RAM +I51_mul, // Multiply Acc by B +I51_nop, // No operation +I51_orl, // Logical OR (op1 |= op2) +I51_pop, // Pop from Stack and put in Direct RAM +I51_push, // Push from Direct RAM to Stack +I51_ret, // Return from subroutine +I51_reti, // Return from Interrupt +I51_rl, // Rotate Acc left +I51_rlc, // Rotate Acc left through Carry +I51_rr, // Rotate Acc right +I51_rrc, // Rotate Acc right through Carry +I51_setb, // Set Direct Bit +I51_sjmp, // Short jump +I51_subb, // Subtract Second Operand from Acc with Borrow +I51_swap, // Swap nibbles of Acc +I51_xch, // Exchange Operands +I51_xchd, // Exchange Digit in Acc with Indirect RAM +I51_xrl, // Exclusive OR (op1 ^= op2) + +// 80251 instructions + +I51_jsle, // Jump if less than or equal (signed) +I51_jsg, // Jump if greater than (signed) +I51_jle, // Jump if less than or equal +I51_jg, // Jump if greater than +I51_jsl, // Jump if less than (signed) +I51_jsge, // Jump if greater than or equal (signed) +I51_je, // Jump if equal +I51_jne, // Jump if not equal +I51_trap, // Trap +I51_ejmp, // Extended jump +I51_ecall, // Extended call +I51_eret, // Extended return +I51_movh, // Move immediate 16-bit data to the high word of a dword (double-word) register +I51_movz, // Move 8-bit register to 16-bit register with zero extension +I51_movs, // Move 8-bit register to 16-bit register with sign extension +I51_srl, // Shift logical right by 1 bit +I51_sra, // Shift arithmetic right by 1 bit +I51_sll, // Shift logical left by 1 bit +I51_sub, // Subtract +I51_cmp, // Compare + +// 51mx instructions +I51_emov, // Move (A <- @PRi+disp) or (@PRi+disp <- A) + +I51_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +TMS_null = 0, // Unknown Operation +TMS_abs, // Absolute value of Acc +TMS_adcb, // Add ACCB to Acc With Carry +TMS_add, // Add to Acc +TMS_addb, // Add ACCB to Acc +TMS_addc, // Add to Acc With Carry +TMS_adds, // Add to Acc With Sign-Extension Suppressed +TMS_addt, // Add to Acc With Shift Specified by TREG1 +TMS_adrk, // Add to Aux Register With Short Immediate +TMS_and, // AND With Acc +TMS_andb, // AND ACCD With Acc +TMS_apac, // Add P Register to Acc +TMS_apl, // AND Data Memory Value With DBMR +TMS_apl2, // AND Data Memory Value With Long Constant +TMS_b, // Branch Unconditionally +TMS_bacc, // Branch to Location (Acc) +TMS_baccd, // Branch to Location (Acc) Delayed +TMS_banz, // Branch on Aux Register Not Zero +TMS_banzd, // Branch on Aux Register Not Zero Delayed +TMS_bcnd, // Branch Conditionally +TMS_bcndd, // Branch Conditionally Delayed +TMS_bd, // Branch Unconditionally Delayed +TMS_bit, // Test Bit +TMS_bitt, // Test Bit Specified by TREG2 +TMS_bldd, // Block Move From Data Memory to Data Memory +TMS_bldp, // Block Move From Data Memory to Program Memory +TMS_blpd, // Block Move From Program Memory to Data Memory +TMS_bsar, // Barrel Shift +TMS_cala, // Call Subroutine at (Acc) +TMS_calad, // Call Subroutine at (Acc) Delayed +TMS_call, // Call Unconditionally +TMS_calld, // Call Unconditionally Delayed +TMS_cc, // Call Conditionally +TMS_ccd, // Call Conditionally Delayed +TMS_clrc, // Clear Control Bit +TMS_cmpl, // Complement Acc +TMS_cmpr, // Compare Aux Register With ARCR +TMS_cpl, // Compare DBMR With Data Value +TMS_cpl2, // Compare Long Immediate With Data Value +TMS_crgt, // Test for Acc Greater Than ACCB +TMS_crlt, // Test for Acc Smaller Than ACCB +TMS_dmov, // Data Move in Data Memory +TMS_estop, // Emulator Stop +TMS_exar, // Exchange ACCB With Acc +TMS_idle, // Idle Until Interrupt +TMS_idle2, // Idle Until Interrupt - Low Power Mode +TMS_in, // Input Data From Port +TMS_intr, // Soft Interrupt +TMS_lacb, // Load Acc With ACCB +TMS_lacc, // Load Acc With Shift +TMS_lacl, // Load Low Acc and Clear High Acc +TMS_lact, // Load Acc With Shift Specified by TREG1 +TMS_lamm, // Load Acc With Memory-Mapped Register +TMS_lar, // Load Aux Register +TMS_ldp, // Load Data Memory Pointer +TMS_lmmr, // Load Memory-Mapped Register +TMS_lph, // Load Product High Register +TMS_lst, // Load Status Register +TMS_lt, // Load TREG0 +TMS_lta, // Load TREG0 and Accumulate Previous Product +TMS_ltd, // Load TREG0,Accumulate Previous Product and Move Data +TMS_ltp, // Load TREG0 and Store P -> Acc +TMS_lts, // Load TREG0 and Subtract Previous Product +TMS_mac, // Multiply and Accumulate +TMS_macd, // Multiply and Accumulate With Data Move +TMS_madd, // Multiply and Accumulate With Data Move and Dynamic Addressing +TMS_mads, // Multiply and Accumulate With Dynamic Addressing +TMS_mar, // Modify Aux Register +TMS_mpy, // Multiply +TMS_mpya, // Multiply and Accumulate Previous Product +TMS_mpys, // Multiply and Subtract Previous Product +TMS_mpyu, // Multiply Unsigned +TMS_neg, // Negate Acc +TMS_nmi, // Nonmaskable Interrupt +TMS_nop, // No Operation +TMS_norm, // Normalize Contents of Acc +TMS_opl, // OR With DBMS +TMS_opl2, // OR With Long Immediate +TMS_or, // OR With Acc +TMS_orb, // OR ACCB With Accumulator +TMS_out, // Out Data to Port +TMS_pac, // Load Acc <- P +TMS_pop, // Pop Top of Stack to Low Acc +TMS_popd, // Pop Top of Stack to Data Memory +TMS_pshd, // Push Data Memory Value Onto Stack +TMS_push, // Push Low Acc Onto Stack +TMS_ret, // Return From Subroutine +TMS_retc, // Return Conditionally +TMS_retcd, // Return Conditionally Delayed +TMS_retd, // Return From Subroutine Delayed +TMS_rete, // Enable Interrupts and Return From Interrupt +TMS_reti, // Return From Interrupt +TMS_rol, // Rotate Acc Left +TMS_rolb, // Rotate ACCB and Acc Left +TMS_ror, // Rotate Acc Right +TMS_rorb, // Rotate ACCB and Acc Right +TMS_rpt, // Repeat Next Instruction +TMS_rptb, // Repeat Block +TMS_rptz, // Repeat Preceded by Clearing Acc and P +TMS_sacb, // Store Acc in ACCB +TMS_sach, // Store High Acc With Shift +TMS_sacl, // Store Low Acc With Shift +TMS_samm, // Store Acc in Memory-Mapped Register +TMS_sar, // Store Aux Register +TMS_sath, // Barrel Shift Acc as Specified by TREG1(4) +TMS_satl, // Barrel Shift Acc as Specified by TREG1(3-0) +TMS_sbb, // Subtract ACCB From Acc +TMS_sbbb, // Subtract ACCB From Acc With Borrow +TMS_sbrk, // Subtract From Aux Register Short Immediate +TMS_setc, // Set Control Bit +TMS_sfl, // Shift Acc Left +TMS_sflb, // Shift ACCB and Acc Left +TMS_sfr, // Shift Acc Right +TMS_sfrb, // Shift ACCB and Acc Right +TMS_smmr, // Store Memory-Mapped Register +TMS_spac, // Subtract P From Acc +TMS_sph, // Store High P Register +TMS_spl, // Store Low P Register +TMS_splk, // Store Parallel Long Immediate +TMS_spm, // Store ACCB and Acc Right +TMS_sqra, // Square and Accumulate Previous Product +TMS_sqrs, // Square and Subtract Previous Product +TMS_sst, // Store Status Register +TMS_sub, // Subtract From Acc +TMS_subb, // Subtract From Acc With Borrow +TMS_subc, // Conditional Subtract +TMS_subs, // Subtract From Acc With Sign-Extension Suppressed +TMS_subt, // Subtract From Acc With Shift Specified by TREG1 +TMS_tblr, // Table Read +TMS_tblw, // Table Write +TMS_trap, // Software Interrupt +TMS_xc, // Execute Conditionally +TMS_xor, // Exclusive-OR With Acc +TMS_xorb, // Exclusive-OR of ACCB With Acc +TMS_xpl, // Exclusive-OR Data Memory Value +TMS_xpl2, // Exclusive-OR Data Memory Value +TMS_zalr, // Zero Low Acc Load High Acc With Rounding +TMS_zap, // Zero Acc and P +TMS_zpr, // Zero P Register + +// +// TMS320C2x instructions +// + +TMS2_abs, // Absolute value of accumulator +TMS2_add, // Add to accumulator with shift +TMS2_addc, // Add to accumulator with carry +TMS2_addh, // Add to high accumulator +TMS2_addk, // Add to accumulator short immediate +TMS2_adds, // Add to low accumulator with sign extension suppressed +TMS2_addt, // Add to accumulator with shift specified by T register +TMS2_adlk, // Add to accumulator long immediate with shift +TMS2_adrk, // Add to auxiliary register short immediate +TMS2_and, // And with accumulator +TMS2_andk, // And immediate with accumulator with shift +TMS2_apac, // App P register to accumulator +TMS2_b, // Branch unconditionally +TMS2_bacc, // Branch to address specified by accumulator +TMS2_banz, // Bnrach on auxiliary register not zero +TMS2_bbnz, // Branch if tc bit != 0 +TMS2_bbz, // Branch if tc bit = 0 +TMS2_bc, // Branch on carry +TMS2_bgez, // Branch if accumulator >= 0 +TMS2_bgz, // Branch if accumulator > 0 +TMS2_bioz, // Branch on i/o status = 0 +TMS2_bit, // Test bit +TMS2_bitt, // Test bit specifed by T register +TMS2_blez, // Branch if accumulator <= 0 +TMS2_blkd, // Block move from data memory to data memory +TMS2_blkp, // Block move from program memory to data memory +TMS2_blz, // Branch if accumulator < 0 +TMS2_bnc, // Branch on no carry +TMS2_bnv, // Branch if no overflow +TMS2_bnz, // Branch if accumulator != 0 +TMS2_bv, // Branch on overflow +TMS2_bz, // Branch if accumulator = 0 +TMS2_cala, // Call subroutine indirect +TMS2_call, // Call subroutine +TMS2_cmpl, // Complement accumulator +TMS2_cmpr, // Compare auxiliary register with auxiliary register ar0 +TMS2_cnfd, // Configure block as data memory +TMS2_cnfp, // Configure block as program memory +TMS2_conf, // Configure block as data/program memory +TMS2_dint, // Disable interrupt +TMS2_dmov, // Data move in data memory +TMS2_eint, // Enable interrupt +TMS2_fort, // Format serial port registers +TMS2_idle, // Idle until interrupt +TMS2_in, // Input data from port +TMS2_lac, // Load accumulator with shift +TMS2_lack, // Load accumulator short immediate +TMS2_lact, // Load accumulator with shift specified by T register +TMS2_lalk, // Load accumulator long immediate with shift +TMS2_lar, // Load auxiliary register +TMS2_lark, // Load auxiliary register short immediate +TMS2_larp, // Load auxiliary register pointer +TMS2_ldp, // Load data memory page pointer +TMS2_ldpk, // Load data memory page pointer immediate +TMS2_lph, // Load high P register +TMS2_lrlk, // Load auxiliary register long immediate +TMS2_lst, // Load status register ST0 +TMS2_lst1, // Load status register ST1 +TMS2_lt, // Load T register +TMS2_lta, // Load T register and accumulate previous product +TMS2_ltd, // Load T register, accumulate previous product and move data +TMS2_ltp, // Load T register and store P register in accumulator +TMS2_lts, // Load T register and subtract previous product +TMS2_mac, // Multiply and accumulate +TMS2_macd, // Multiply and accumulate with data move +TMS2_mar, // Modify auxiliary register +TMS2_mpy, // Multiply (with T register, store product in P register) +TMS2_mpya, // Multiply and accumulate previous product +TMS2_mpyk, // Multiply immediate +TMS2_mpys, // Multiply and subtract previous product +TMS2_mpyu, // Multiply unsigned +TMS2_neg, // Negate accumulator +TMS2_nop, // No operation +TMS2_norm, // Normalize contents of accumulator +TMS2_or, // Or with accumulator +TMS2_ork, // Or immediate with accumulator with shift +TMS2_out, // Output data to port +TMS2_pac, // Load accumulator with P register +TMS2_pop, // Pop top of stack to low accumulator +TMS2_popd, // Pop top of stack to data memory +TMS2_pshd, // Push data memory value onto stack +TMS2_push, // Push low accumulator onto stack +TMS2_rc, // Reset carry bit +TMS2_ret, // Return from subroutine +TMS2_rfsm, // Reset serial port frame synchronization mode +TMS2_rhm, // Reset hold mode +TMS2_rol, // Rotate accumulator left +TMS2_ror, // Rotate acuumulator right +TMS2_rovm, // Reset overflow mode +TMS2_rpt, // Repeat instruction as specified by data memory value +TMS2_rptk, // Repeat instruction as specified by immediate value +TMS2_rsxm, // Reset sign extension mode +TMS2_rtc, // Reset test/control flag +TMS2_rtxm, // Reset serial port transmit mode +TMS2_rxf, // Reset external flag +TMS2_sach, // Store high accumulator with shift +TMS2_sacl, // Store low accumulator with shift +TMS2_sar, // Store auxiliary register +TMS2_sblk, // Subtract from accumulator long immediate with shift +TMS2_sbrk, // Subtract from auxiliary register short immediate +TMS2_sc, // Set carry bit +TMS2_sfl, // Shift accumulator left +TMS2_sfr, // Shift accumulator right +TMS2_sfsm, // Set serial port frame synchronization mode +TMS2_shm, // Set hold mode +TMS2_sovm, // Set overflow mode +TMS2_spac, // Subtract P register from accumulator +TMS2_sph, // Store high P register +TMS2_spl, // Store low P register +TMS2_spm, // Set P register output shift mode +TMS2_sqra, // Square and accumulate +TMS2_sqrs, // Square and subtract previous product +TMS2_sst, // Store status register ST0 +TMS2_sst1, // Store status register ST1 +TMS2_ssxm, // Set sign extension mode +TMS2_stc, // Set test/control flag +TMS2_stxm, // Set serial port transmit mode +TMS2_sub, // Subtract from accumulator with shift +TMS2_subb, // Subtract from accumulator with borrow +TMS2_subc, // Conditional subtract +TMS2_subh, // Subtract from high accumulator +TMS2_subk, // Subtract from accumulator shoft immediate +TMS2_subs, // Subtract from low accumulator with sign extension suppressed +TMS2_subt, // Subtract from accumulator with shift specified by T register +TMS2_sxf, // Set external flag +TMS2_tblr, // Table read +TMS2_tblw, // Table write +TMS2_trap, // Software interrupt +TMS2_xor, // Exclusive or with accumulator +TMS2_xork, // Exclusive or immediate with accumulator with shift +TMS2_zac, // Zero accumulator +TMS2_zalh, // Zero low accumulator and load high accumulator +TMS2_zalr, // Zero low accumulator and load high accumulator with rounding +TMS2_zals, // Zero low accumulator and load high accumulator with sign extension suppressed + +TMS_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + M65_null = 0, // Unknown Operation + + // NMOS instructions + + M65_adc, // A <- (A) + M + C + M65_anc, // A <- A /\ M, C <- ~A7 + M65_and, // A <- (A) /\ M + M65_ane, // M <-[(A)\/$EE] /\ (X)/\(M) + M65_arr, // A <- [(A /\ M) >> 1] + M65_asl, // C <- A7, A <- (A) << 1 + M65_asr, // A <- [(A /\ M) >> 1] + M65_bcc, // if C=0, PC = PC + offset + M65_bcs, // if C=1, PC = PC + offset + M65_beq, // if Z=1, PC = PC + offset + M65_bit, // Z <- ~(A /\ M) N<-M7 V<-M6 + M65_bmi, // if N=1, PC = PC + offset + M65_bne, // if Z=0, PC = PC + offset + M65_bpl, // if N=0, PC = PC + offset + M65_brk, // Stack <- PC, PC <- ($fffe) + M65_bvc, // if V=0, PC = PC + offset + M65_bvs, // if V=1, PC = PC + offset + M65_clc, // C <- 0 + M65_cld, // D <- 0 + M65_cli, // I <- 0 + M65_clv, // V <- 0 + M65_cmp, // (A - M) -> NZC + M65_cpx, // (X - M) -> NZC + M65_cpy, // (Y - M) -> NZC + M65_dcp, // M <- (M)-1, (A-M) -> NZC + M65_dec, // M <- (M) - 1 + M65_dex, // X <- (X) - 1 + M65_dey, // Y <- (Y) - 1 + M65_eor, // A <- (A) \-/ M + M65_inc, // M <- (M) + 1 + M65_inx, // X <- (X) +1 + M65_iny, // Y <- (Y) + 1 + M65_isb, // M <- (M) - 1,A <- (A)-M-~C + M65_jmp, // PC <- Address + M65_jmpi, // (PC <- Address) + M65_jsr, // Stack <- PC, PC <- Address + M65_lae, // X,S,A <- (S /\ M) + M65_lax, // A <- M, X <- M + M65_lda, // A <- M + M65_ldx, // X <- M + M65_ldy, // Y <- M + M65_lsr, // C <- A0, A <- (A) >> 1 + M65_lxa, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04 + M65_nop, // [no operation] + M65_ora, // A <- (A) V M + M65_pha, // Stack <- (A) + M65_php, // Stack <- (P) + M65_pla, // A <- (Stack) + M65_plp, // A <- (Stack) + M65_rla, // M <- (M << 1) /\ (A) + M65_rol, // C <- A7 & A <- A << 1 + C + M65_ror, // C<-A0 & A<- (A7=C + A>>1) + M65_rra, // M <- (M >> 1) + (A) + C + M65_rti, // P <- (Stack), PC <-(Stack) + M65_rts, // PC <- (Stack) + M65_sax, // M <- (A) /\ (X) + M65_sbc, // A <- (A) - M - ~C + M65_sbx, // X <- (X)/\(A) - M + M65_sec, // C <- 1 + M65_sed, // D <- 1 + M65_sei, // I <- 1 + M65_sha, // M <- (A) /\ (X) /\ (PCH+1) + M65_shs, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1) + M65_shx, // M <- (X) /\ (PCH+1) + M65_shy, // M <- (Y) /\ (PCH+1) + M65_slo, // M <- (M >> 1) + A + C + M65_sre, // M <- (M >> 1) \-/ A + M65_sta, // M <- (A) + M65_stx, // M <- (X) + M65_sty, // M <- (Y) + M65_tax, // X <- (A) + M65_tay, // Y <- (A) + M65_tsx, // X <- (S) + M65_txa, // A <- (X) + M65_txs, // S <- (X) + M65_tya, // A <- (Y) + + // CMOS instructions + + M65_bbr0, // Branch if bit 0 reset + M65_bbr1, // Branch if bit 1 reset + M65_bbr2, // Branch if bit 2 reset + M65_bbr3, // Branch if bit 3 reset + M65_bbr4, // Branch if bit 4 reset + M65_bbr5, // Branch if bit 5 reset + M65_bbr6, // Branch if bit 6 reset + M65_bbr7, // Branch if bit 7 reset + M65_bbs0, // Branch if bit 0 set + M65_bbs1, // Branch if bit 1 set + M65_bbs2, // Branch if bit 2 set + M65_bbs3, // Branch if bit 3 set + M65_bbs4, // Branch if bit 4 set + M65_bbs5, // Branch if bit 5 set + M65_bbs6, // Branch if bit 6 set + M65_bbs7, // Branch if bit 7 set + M65_rmb0, // Reset memory bit 0 + M65_rmb1, // Reset memory bit 1 + M65_rmb2, // Reset memory bit 2 + M65_rmb3, // Reset memory bit 3 + M65_rmb4, // Reset memory bit 4 + M65_rmb5, // Reset memory bit 5 + M65_rmb6, // Reset memory bit 6 + M65_rmb7, // Reset memory bit 7 + M65_smb0, // Set memory bit 0 + M65_smb1, // Set memory bit 1 + M65_smb2, // Set memory bit 2 + M65_smb3, // Set memory bit 3 + M65_smb4, // Set memory bit 4 + M65_smb5, // Set memory bit 5 + M65_smb6, // Set memory bit 6 + M65_smb7, // Set memory bit 7 + M65_stz, // Store zero + M65_tsb, // Test and set bits + M65_trb, // Test and reset bits + M65_phy, // Push Y register + M65_ply, // Pull Y register + M65_phx, // Push X register + M65_plx, // Pull X register + M65_bra, // Branch always + M65_wai, // Wait for interrupt + M65_stp, // Stop processor + + M65_last, +}; + + + + +// The instruction types (``itype''s) +// m65* CPUs implements. + +enum m65_itype_t +{ + // http://www.westerndesigncenter.com/wdc/datasheets/Programmanual.pdf + M65816_null=0, // Unknown Operation + M65816_adc, // Add with carry + M65816_and, // AND A with memory + M65816_asl, // Shift memory or A left + M65816_bcc, // Branch if carry clear + M65816_bcs, // Branch if carry set + M65816_beq, // Branch if equal + M65816_bit, // Test memory bits against A + M65816_bmi, // Branch if minus + M65816_bne, // Branch if not equal + M65816_bpl, // Branch if plus + M65816_bra, // Branch always + M65816_brk, // Software break + M65816_brl, // Branch always long + M65816_bvc, // Branch if overflow clear + M65816_bvs, // Branch if overflow set + M65816_clc, // Clear carry flag + M65816_cld, // Clear decimal mode flag + M65816_cli, // Clear interrupt disable flag + M65816_clv, // Clear overflow flag + M65816_cmp, // Compare A with memory + M65816_cop, // Co-processor enable + M65816_cpx, // Compare X with memory + M65816_cpy, // Compare Y with memory + M65816_dec, // Decrement + M65816_dex, // Decrement X + M65816_dey, // Decrement Y + M65816_eor, // XOR A with M + M65816_inc, // Increment + M65816_inx, // Increment X + M65816_iny, // Increment Y + M65816_jml, // Jump long (inter-bank) + M65816_jmp, // Jump + M65816_jsl, // Jump to subroutine long (inter-bank) + M65816_jsr, // Jump to subroutine + M65816_lda, // Load A from memory + M65816_ldx, // Load X from memory + M65816_ldy, // Load Y from memory + M65816_lsr, // Logical shift memory or A right + M65816_mvn, // Block move next + M65816_mvp, // Block move prev + M65816_nop, // Nop + M65816_ora, // Or A with memory + M65816_pea, // Push effective absolute address + M65816_pei, // Push effective indirect address + M65816_per, // Push effective PC-relative indirect address + M65816_pha, // Push A + M65816_phb, // Push B (data bank register) + M65816_phd, // Push D (direct page register) + M65816_phk, // Push K (program bank register) + M65816_php, // Push processor status + M65816_phx, // Push X + M65816_phy, // Push Y + M65816_pla, // Pull A + M65816_plb, // Pull B + M65816_pld, // Pull D + M65816_plp, // Pull processor status + M65816_plx, // Pull X + M65816_ply, // Pull Y + M65816_rep, // Reset status bits + M65816_rol, // Rotate memory or A left + M65816_ror, // Rotate memory or A right + M65816_rti, // Return from interrupt + M65816_rtl, // Return from subroutine long + M65816_rts, // Return from subroutine + M65816_sbc, // Subtract with borrow from A + M65816_sec, // Set carry flag + M65816_sed, // Set decimal mode flag + M65816_sei, // Set interrupt disable flag + M65816_sep, // Set status bits + M65816_sta, // Store A to memory + M65816_stp, // Stop processor + M65816_stx, // Store X to memory + M65816_sty, // Store Y to memory + M65816_stz, // Store zero to memory + M65816_tax, // Transfer A to X + M65816_tay, // Transfer A to Y + M65816_tcd, // Transfer 16-bit A to D (direct page register) + M65816_tcs, // Transfer A to S + M65816_tdc, // Transfer 16-bit D to A + M65816_trb, // Test and reset memory bits against A + M65816_tsb, // Test and set memory bits against A + M65816_tsc, // Transfer S to A + M65816_tsx, // Transfer S to X + M65816_txa, // Transfer X to A + M65816_txs, // Transfer X to S + M65816_txy, // Transfer X to Y + M65816_tya, // Transfer Y to A + M65816_tyx, // Transfer Y to X + M65816_wai, // Wait for interrupt + M65816_wdm, // Reserved + M65816_xba, // Exchange bytes in A + M65816_xce, // Exchange carry and emulation bits + M65816_last +}; + +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-2021 Hex-Rays + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +pdp_null = 0, // Unknown Operation + +pdp_halt, // Stop CPU +pdp_wait, // Wait interrupt +pdp_rti, // Interrupt return +pdp_bpt, // Trap to Debbuger +pdp_iot, // Trap to 20 (i/o) +pdp_reset, // Reset CPU and device +pdp_rtt, // Interrupt return and ignore dbg-flag +pdp_mfpt, // Load Processor Type (* hi model) +pdp_jmp, // Absolute jmp +pdp_rts, // Return into subroutine +pdp_spl, // Set Prior. +pdp_nop, // Not operation +pdp_clc, // Clear C bit in PSW +pdp_clv, // Clear V bit in PSW +pdp_clz, // Clear Z bit in PSW +pdp_cln, // Clear N bit in PSW +pdp_ccc, // Clear All Condition bits in PSW +pdp_sec, // Set C bit in PSW +pdp_sev, // Set V bit in PSW +pdp_sez, // Set Z bit in PSW +pdp_sen, // Set N bit in PSW +pdp_scc, // Set All Condition bits bit in PSW +pdp_swab, // Exchange byte in word +pdp_br, // Relative jmp +pdp_bne, // Jump if Z=0 +pdp_beq, // Jump if Z=1 +pdp_bge, // Jump if N^V=0 +pdp_blt, // Jump if N^V=1 +pdp_bgt, // Jump if Z|(N^V)=0 +pdp_ble, // Jump if Z|(N^V)=1 +pdp_jsr, // Call procedure +pdp_clr, // Clear operand +pdp_com, // Inverse operand +pdp_inc, // Increment operand +pdp_dec, // Decrement operand +pdp_neg, // op = -op +pdp_adc, // Add with Carry +pdp_sbc, // Substract with Carry +pdp_tst, // Test operand +pdp_ror, // Cyclic shift rignt +pdp_rol, // Cyclic shift left +pdp_asr, // Arifmetic shift rignt +pdp_asl, // Arifmetic shift left +pdp_mark, // Return and empty stack +pdp_mfpi, // Load from previous instruction space (*hi model) +pdp_mtpi, // Store to previous instruction space (*hi model) +pdp_sxt, // N=>op +pdp_mov, // Move operand +pdp_cmp, // Compare operands +pdp_bit, // Check Bit's +pdp_bic, // Clear Bit's +pdp_bis, // Set Bit's +pdp_add, // Add operands +pdp_sub, // Substract operands +pdp_mul, // Multiple Reg (*eis) +pdp_div, // Divide Reg (*eis) +pdp_ash, // Multistep shift (*eis) +pdp_ashc, // Multistep shift 2 reg (*eis) +pdp_xor, // Exclusive or (*eis) +pdp_fadd, // Floating Add (*fis) +pdp_fsub, // Floating Subtract (*fis) +pdp_fmul, // Floating Multiple (*fis) +pdp_fdiv, // Floating Divide (*fis) +pdp_sob, // +pdp_bpl, // Jump if N=0 +pdp_bmi, // Jump if N=1 +pdp_bhi, // Jump if (!C)&(!Z)=0 +pdp_blos, // Jump if C|Z=1 +pdp_bvc, // Jump if V=0 +pdp_bvs, // Jump if V=1 +pdp_bcc, // Jump if C=0 +pdp_bcs, // Jump if C=1 +pdp_emt, // Trap to System +pdp_trap, // Trap to user/compiler +pdp_mtps, // Store PSW (*lsi11 only) +pdp_mfpd, // Load from previous data space (*hi model) +pdp_mtpd, // Store to previous data space (*hi model) +pdp_mfps, // Load PSW (*lsi11 only) + // FPU instruction +pdp_cfcc, // Copy cond.codes into FPS to PSW +pdp_setf, // Set Float +pdp_seti, // Set Integer +pdp_setd, // Set Double +pdp_setl, // Set Long Integer +pdp_ldfps, // Load FPS +pdp_stfps, // Store FPS +pdp_stst, // Load interrupt status +pdp_clrd, // Clear +pdp_tstd, // Test +pdp_absd, // op = mod(op) +pdp_negd, // op = -op +pdp_muld, // Multiple +pdp_modd, // Get int. part +pdp_addd, // Add +pdp_ldd, // Load in Acc +pdp_subd, // Substract +pdp_cmpd, // Compare +pdp_std, // Store into Acc +pdp_divd, // Divide +pdp_stexp, // Store exponent +pdp_stcdi, // Store and convert double/float to integer/long +pdp_stcdf, // Store and convert double/float to float/double +pdp_ldexp, // Load exponent +pdp_ldcif, // Load and convert integer/long to double/float +pdp_ldcfd, // Load and convert float/double to double/float +pdp_call, // Jsr PC, +pdp_return, // RTS PC +pdp_compcc, // Complex Condition Codes + +pdp_last + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + mc_null = 0, // Unknown Operation + + mc_abcd, // summa with BCD correction + mc_add, // summa with Dn + mc_adda, // summa with An + mc_addi, // summa with immediate + mc_addq, // -"- + mc_addx, // summa 2 reg and const + mc_and, // logical and + mc_andi, // logical and with immediate + mc_asl, // shift by count + mc_asr, // -"- + mc_b, // branch if cond code + mc_bchg, // bit chang + mc_bclr, // bit clear + mc_bftst, // bit field test + mc_bfchg, // bit field change + mc_bfclr, // bit field set in 0 + mc_bfset, // bit field set in 1 + mc_bfextu, // bit field extract (unsigned) + mc_bfexts, // bit field extract (signed) + mc_bfffo, // bit field offset + mc_bfins, // bit field include + mc_bgnd, // CPU32- enter backgound mode + mc_bkpt, // disable TRAP at any cycles + mc_bra, // branch + mc_bset, // bit set + mc_bsr, // relative call + mc_btst, // bit test + mc_callm, // call module [descrtiptor] (020) + mc_cas, // compare and swap + mc_cas2, // -"- + mc_chk, // compare and trap + mc_chk2, // -"- + mc_cinv, // invalidate cache + mc_clr, // clear data + mc_cmp, // compare data + mc_cmp2, // -"- + mc_cmpa, // compare address + mc_cmpi, // compare immediate + mc_cmpm, // compare memory + mc_cpush, // invalidate cache + mc_db, // (djnz) if cond code + mc_divs, // sign divide + mc_divsl, // -"- + mc_divu, // unsign didide + mc_divul, // -"- + mc_eor, // logical xor + mc_eori, // logical xor with immediate + mc_exg, // exchange registers + mc_ext, // analog cwd + mc_extb, // analog cwq + mc_fabs, // FP abs + mc_facos, // FP acos + mc_fadd, // FP add + mc_fasin, // FP asin + mc_fatan, // FP atan + mc_fatanh, // FP atanh + mc_fb, // fBcc + mc_fcmp, // FP cmp + mc_fcos, // FP cos + mc_fcosh, // FP cosh + mc_fdabs, // FP abs double rounded + mc_fdadd, // FP add + mc_fdb, // fDBcc + mc_fddiv, // FP div double rounded + mc_fdiv, // FP div + mc_fdmove, // FP mov double rounded + mc_fdmul, // FP mul double rounded + mc_fdneg, // FP neg double rounded + mc_fdsqrt, // FP sqrt double rounded + mc_fdsub, // FP sub double rounded + mc_fetox, // FP e**x + mc_fetoxm1, // FP e**x-1 + mc_fgetexp, // FP extract exponent + mc_fgetman, // FP extract mantissa + mc_fint, // FP get integer part + mc_fintrz, // FP get integer part by round + mc_flog2, // FP log[2] + mc_flog10, // FP log[10] + mc_flogn, // FP log[e] + mc_flognp1, // FP log[e] x+1 + mc_fmod, // FP mod + mc_fmove, // move float + mc_fmovecr, // move floating const + mc_fmovem, // move float register list + mc_fmul, // FM mul + mc_fneg, // FP neg + mc_fnop, // float nop + mc_frem, // FP rem + mc_frestore, // restore status + mc_fs, // fScc + mc_fsabs, // FP abs single rounded + mc_fsadd, // FP add single rounded + mc_fsave, // Fsave status + mc_fscale, // FP *2**x + mc_fsdiv, // FP div single rounded + mc_fsgldiv, // FP single div + mc_fsglmul, // FP single mul + mc_fsin, // FP sin + mc_fsincos, // FP sin & cos + mc_fsinh, // FP sinh + mc_fsmove, // FP mov single rounded + mc_fsmul, // FP mul single rounded + mc_fsneg, // FP neg single rounded + mc_fsqrt, // FP sqrt + mc_fssqrt, // FP sqrt single rounded + mc_fssub, // FP sub single rounded + mc_fsub, // FP sub + mc_ftan, // FP tan + mc_ftanh, // FP tanh + mc_ftentox, // FP 10**x + mc_ftrap, // fTRAPcc + mc_ftst, // FP tst + mc_ftwotox, // FP 2**x + mc_halt, // (coldfire) Halt the processor + mc_illegal, // trap to vector + mc_jmp, // absolute Jmp + mc_jsr, // absolute jsr + mc_lea, // load effective address + mc_link, // change sp context + mc_lpstop, // cpu32 - stop + mc_lsl, // logical shift + mc_lsr, // -"- + mc_mac, // multiple and accumulate + mc_macl, // multiple and accumulate with register load + mc_move, // move memory + mc_move16, // move 16 byte + mc_movea, // move move with address reg + mc_movec, // move from/to control register + mc_movem, // move register list + mc_movep, // move with data register + mc_moveq, // move with immediate + mc_moves, // mtpd/mfpd + mc_msac, // multiple and subtract + mc_msacl, // multiple and subtract with register load + mc_muls, // sign multiplication + mc_mulu, // unsign multiplication + mc_nbcd, // negative with BCD correct + mc_neg, // negative + mc_negx, // negative with immediate + mc_nop, // null operation + mc_not, // logical not + mc_or, // logical or + mc_ori, // logical or with immediate + mc_pack, // UNP(bcd)+adj -> PACK(bcd) + mc_pea, // lea into stack + mc_pb, // 68851 pbcc + mc_pdb, // 68851 pdbcc + mc_pflush, // invalidate cache + mc_pflushr, // 68851 load root entry + mc_ploadr, // 68851 + mc_ploadw, // 68851 + mc_pmove, // move MMU register + mc_prestore, // 68851 + mc_psave, // 68851 + mc_ps, // 68851 pscc + mc_ptestr, // test a logical address + mc_ptestw, // -"- + mc_ptrap, // 68851 ptrapcc + mc_pulse, // (coldfire) generate unique PST value + mc_pvalid, // 68851 move AL bit + mc_rol, // cycl. shift + mc_ror, // -"- + mc_roxl, // two op cycl shift + mc_roxr, // -"- + mc_reset, // reset + mc_rtd, // mark + mc_rte, // return with SR + mc_rtm, // reload save module state + mc_rtr, // return with CCR + mc_rts, // return + mc_sbcd, // substract with BCD correction + mc_s, // 1 if cond code else 0 + mc_stop, // halt + mc_sub, // substract + mc_suba, // substract address + mc_subi, // substract immediate + mc_subq, // -"- + mc_subx, // substract memory + mc_swap, // hi and low word in register + mc_tas, // test byte sign + mc_tbl, // CPU32-tblu/tblun/tbls/tblsn + mc_trap, // analog int(86) (or trap if cond code) + mc_trapv, // if V then trap + mc_tst, // test destination + mc_unlk, // destroy address ? + mc_unpk, // PACK(bcd)+adj -> UNPACK(bcd) + mc_wddata, // (coldfire) load WDDATA port (pins) + mc_wdebug, // (coldfire) load debug register + mc_atrap, // MacOS atrap + + // new ColdFire instructions + mc_bitrev, // bit reverse + mc_byterev, // byte reverse + mc_ff1, // find first one + mc_intouch, // instruction fetch touch + mc_mov3q, // move 3-bit data quick + mc_mvs, // move with sign extend + mc_mvz, // move with zero-fill + mc_sats, // signed saturate + mc_movclr, // move from accumulator and clear + mc_maaac, // Multiply and Add to 1st Accumulator, Add to 2nd Accumulator + mc_masac, // Multiply and Add to 1st Accumulator, Subtract from 2nd Accumulator + mc_msaac, // Multiply and Subtract to 1st Accumulator, Add to 2nd Accumulator + mc_mssac, // Multiply and Subtract to 1st Accumulator, Subtract to 2nd Accumulator + + mc_remsl, // Signed Divide Remainder + mc_remul, // Unsigned Divide Remainder + + mc_last +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +mc8_null = 0, // Unknown Operation + +mc8_aba, // Add b to a (11) +mc8_ab, // Add b to index register +mc8_adc, // Add with carry +mc8_add, // Add without carry +mc8_addd, // Add 16-bit to D (11) +mc8_ais, // Add immediate value to stack pointer (8) +mc8_aix, // Add immediate value to index register (H:X) (8) +mc8_and, // Logical AND +mc8_andcc, // Logical AND immdiate with CCR (9) +mc8_asr, // Ariphmetic shift right +mc8_bcc, // Branch if carry bit clear +mc8_bclr, // Clear bit in memory +mc8_bcs, // Branch if carry bit set +mc8_beq, // Branch if equal +mc8_bge, // Branch if >= (signed) +mc8_bgt, // Branch if > (signed) +mc8_bhcc, // Branch if half carry bit clear (8) +mc8_bhcs, // Branch if half carry bit set (8) +mc8_bhi, // Branch if > (unsigned) +mc8_bhs, // Branch if >= (unsigned) (11) +mc8_bih, // Branch if IRQ pin high (8) +mc8_bil, // Branch if IRQ pin low (8) +mc8_bit, // Bit test (8) +mc8_ble, // Branch if <= (signed) (8) +mc8_blo, // Branch if < (unsigned) (11) +mc8_bls, // Branch if <= (unsigned) (8) +mc8_blt, // Branch if < (signed) (8) +mc8_bmc, // Branch if interrupt mask clear (8) +mc8_bmi, // Branch if minus +mc8_bms, // Branch if interrupt mask set (8) +mc8_bne, // Branch if not equal +mc8_bpl, // Branch if not plus +mc8_bra, // Branch always +mc8_brclr, // Branch if bit (n) in memory clear +mc8_brn, // Branch never +mc8_brset, // Branch if bit (n) in memory set +mc8_bset, // Set bit in memory +mc8_bsr, // Branch to subroutine +mc8_bvc, // Branch if overflow cleared (11) +mc8_bvs, // Branch if overflow set (11) +mc8_cba, // Compare A to B (11) +mc8_cbeq, // Compare and branch if equal (8) +mc8_clc, // Clear carry bit +mc8_cli, // Clear interrupt mask +mc8_clr, // Clear +mc8_clv, // Clear overflow flag (11) +mc8_cmp, // Compare accumulator with memory +mc8_com, // Complement +mc8_cp, // Compare index register 16 bit (11) +mc8_cpd, // Compare D 16 bit (11) +mc8_cphx, // Compare index register with memory (8) +mc8_cpx, // Compare X (index register low) with memory (8) +mc8_cwai, // Clear CC bits & wait for interrupt (9) +mc8_daa, // Decimal adjust accumulator +mc8_dbnz, // Decrement and branch if not equal (8) +mc8_de, // Decrement index register (11) +mc8_dec, // Decrement +mc8_des, // Decrement stack pointer (11) +mc8_div, // Divide (8) +mc8_eor, // Excusive OR memory with accumulator +mc8_exg, // Exchange register (9) +mc8_fdiv, // Fractional divide 16 by 16 (11) +mc8_idiv, // Integer divide 16 by 16 (11) +mc8_in, // Increment index register (11) +mc8_inc, // Increment +mc8_ins, // Increment stack pointer (11) +mc8_jmp, // Jump +mc8_jsr, // Jump to subroutine +mc8_ld, // Load index register (11) +mc8_lda, // Load accumulator from memory +mc8_ldd, // Load double accumulator (11) +mc8_ldhx, // Load index register from memory (8) +mc8_lds, // Load stack pointer (11) +mc8_ldx, // Load X (index register low) from memory (8) +mc8_lea, // Load register from memory (9) +mc8_lsl, // Logical (or Ariphmetic) shift left +mc8_lsld, // Logical (or Ariphmetic) shift left double (11) +mc8_lsr, // Logical shift right +mc8_lsrd, // Logical shift right double (11) +mc8_mov, // Move (8) +mc8_mul, // Unsigned multiply +mc8_neg, // Negate +mc8_nop, // No Operation +mc8_nsa, // Nibble swap accumulator (8) +mc8_ora, // Inclusive OR memory with accumulator +mc8_orcc, // Inclusive OR immediate with CCR (9) +mc8_psh, // Push index register into stack (low first) (11) +mc8_psha, // Push accumulator A into stack +mc8_pshb, // Push accumulator B into stack (11) +mc8_pshh, // Push H (index register high) into stack (8) +mc8_pshx, // Push X (index register low) into stack (8) +mc8_pul, // Pull index register from stack (hi first) (11) +mc8_pula, // Pull accumulator A from stack +mc8_pulb, // Pull accumulator B from stack (11) +mc8_pulh, // Pull H (index register high) from stack (8) +mc8_pulx, // Pull X (index register low) from stack (8) +mc8_rol, // Rotate left trough carry +mc8_ror, // Rotate right trough carry +mc8_rsp, // Reset stack pointer (8) +mc8_rti, // Reset from interrupt +mc8_rts, // Reset from subroutine +mc8_sba, // Subtract B from A (11) +mc8_sbc, // Subtract with carry +mc8_sec, // Set carry bit +mc8_sei, // Set interrupt mask bit +mc8_sev, // Set Overflow Flag (11) +mc8_sex, // Sign extended (9) +mc8_slp, // Sleep (HD63701 extention) (11) +mc8_st, // Store index register in memory (11) +mc8_sta, // Store accumulator in memory +mc8_std, // Store accumulators in memory (11) +mc8_sthx, // Store H:X (index reg) (8) +mc8_stop, // Enable IRQ pin. Stop oscillator +mc8_sts, // Store stack pointer (11) +mc8_stx, // Store X (index register low) in memory (8) +mc8_sub, // Subtract +mc8_subd, // Subtract 16-bit (11) +mc8_swi, // Software interrupt +mc8_sync, // Syncronisation with interrupt (9) +mc8_tab, // Transfer A to B (11) +mc8_tap, // Transfer A to CCR +mc8_tax, // Transfer accumulator to X (index register low) (8) +mc8_tba, // Transfer B to A (11) +mc8_test, // Address Bus Counts (in test mode) (11) +mc8_tfr, // Transfer register to register (9) +mc8_tpa, // Transfer CCR to A +mc8_ts, // Transfer SP to index reg (11) +mc8_tst, // Test for negative or zero +mc8_tsx, // Transfer SP to index reg (8) +mc8_txa, // Transfer X (index reg low) to accumulator (8) +mc8_txs, // Transfer index reg X to SP +mc8_tys, // Transfer index reg Y to SP (11) +mc8_wai, // Wait for interrupt (11) +mc8_wait, // Enable interrupt. Stop processor (8) +mc8_xgd, // Exchange D with index register (11) +mc8_1, // Special testing command (11) +mc8_2, // Special testing command (11) +mc8_os9, // OS9 system call (9) +// these instructions must be continuous (HD63701 extention) +mc8_aim, +mc8_oim, +mc8_eim, +mc8_tim, + +// new S08 instructions +mc8_bgnd, // Background (8) +mc8_call, // Call Subroutine (8) +mc8_rtc, // Return fom Call (8) + +// Pseudoinstructions +mc8_skip1, // Skip one byte +mc8_skip2, // Skip two bytes + +mc8_last + + }; + +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-2021 Hex-Rays + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + j_nop = 0, // 0 Do nothing + j_aconst_null, // 1 Push null object reference + j_iconst_m1, // 2 Push integer constant -1 + j_iconst_0, // 3 Push the integer 0 + j_iconst_1, // 4 Push the integer 1 + j_iconst_2, // 5 Push the integer 2 + j_iconst_3, // 6 Push the integer 3 + j_iconst_4, // 7 Push the integer 4 + j_iconst_5, // 8 Push the integer 5 + j_lconst_0, // 9 Push the long integer 0 + j_lconst_1, // 10 Push the long integer 1 + j_fconst_0, // 11 Push the single-precision foating point 0.0 + j_fconst_1, // 12 Push the single-precision foating point 1.0 + j_fconst_2, // 13 Push the single-precision foating point 2.0 + j_dconst_0, // 14 Push the double-precision foating point 2.0 + j_dconst_1, // 15 Push the double-precision foating point 2.0 + j_bipush, // 16 Push one byte signed integer + j_sipush, // 17 Push two-byte signed integer + j_ldc, // 18 Push item from constant pool (i1) + j_ldcw, // 19 Push item from constant pool (i2) + j_ldc2w, // 20 Push long or double from constant pool + j_iload, // 21 Push integer value of the local variable + j_lload, // 22 Push long value of the local variable + j_fload, // 23 Push single float value of the local variable + j_dload, // 24 Push double float value of the local variable + j_aload, // 25 Push object reference from the local variable + j_iload_0, // 26 Push integer value of the local variable #0 + j_iload_1, // 27 Push integer value of the local variable #1 + j_iload_2, // 28 Push integer value of the local variable #2 + j_iload_3, // 29 Push integer value of the local variable #3 + j_lload_0, // 30 Push long value of the local variable #0 + j_lload_1, // 31 Push long value of the local variable #1 + j_lload_2, // 32 Push long value of the local variable #2 + j_lload_3, // 33 Push long value of the local variable #3 + j_fload_0, // 34 Push single float value of the local variable #0 + j_fload_1, // 35 Push single float value of the local variable #1 + j_fload_2, // 36 Push single float value of the local variable #2 + j_fload_3, // 37 Push single float value of the local variable #3 + j_dload_0, // 38 Push double float value of the local variable #0 + j_dload_1, // 39 Push double float value of the local variable #1 + j_dload_2, // 40 Push double float value of the local variable #2 + j_dload_3, // 41 Push double float value of the local variable #3 + j_aload_0, // 42 Push object reference from the local variable #0 + j_aload_1, // 43 Push object reference from the local variable #1 + j_aload_2, // 44 Push object reference from the local variable #2 + j_aload_3, // 45 Push object reference from the local variable #3 + j_iaload, // 46 Push integer from array + j_laload, // 47 Push long from array + j_faload, // 48 Push single float from array + j_daload, // 49 Push double float from array + j_aaload, // 50 Push object refernce from array + j_baload, // 51 Push signed byte from array + j_caload, // 52 Push character from array + j_saload, // 53 Push short from array + j_istore, // 54 Pop integer value into local variable + j_lstore, // 55 Pop long value into local variable + j_fstore, // 56 Pop single float value into local variable + j_dstore, // 57 Pop double float value into local variable + j_astore, // 58 Pop object refernce into local variable + j_istore_0, // 59 Pop integer value into local variable #0 + j_istore_1, // 60 Pop integer value into local variable #1 + j_istore_2, // 61 Pop integer value into local variable #2 + j_istore_3, // 62 Pop integer value into local variable #3 + j_lstore_0, // 63 Pop long value into local variable #0 + j_lstore_1, // 64 Pop long value into local variable #1 + j_lstore_2, // 65 Pop long value into local variable #2 + j_lstore_3, // 66 Pop long value into local variable #3 + j_fstore_0, // 67 Pop single float value into local variable #0 + j_fstore_1, // 68 Pop single float value into local variable #1 + j_fstore_2, // 69 Pop single float value into local variable #2 + j_fstore_3, // 70 Pop single float value into local variable #3 + j_dstore_0, // 71 Pop double float value into local variable + j_dstore_1, // 72 Pop double float value into local variable #0 + j_dstore_2, // 73 Pop double float value into local variable #1 + j_dstore_3, // 74 Pop double float value into local variable #2 + j_astore_0, // 75 Pop object refernce into local variable #0 + j_astore_1, // 76 Pop object refernce into local variable #1 + j_astore_2, // 77 Pop object refernce into local variable #2 + j_astore_3, // 78 Pop object refernce into local variable #3 + j_iastore, // 79 Pop integer from array + j_lastore, // 80 Pop long from array + j_fastore, // 81 Pop single float from array + j_dastore, // 82 Pop double float from array + j_aastore, // 83 Pop object refernce from array + j_bastore, // 84 Pop signed byte from array + j_castore, // 85 Pop character from array + j_sastore, // 86 Pop short from array + j_pop, // 87 Pop top stack word + j_pop2, // 88 Pop top two stack word + j_dup, // 89 Duplicate top stack word + j_dup_x1, // 90 Duplicate top stack word and put two down + j_dup_x2, // 91 Duplicate top stack word and put three down + j_dup2, // 92 Duplicate top two stack word + j_dup2_x1, // 93 Duplicate top two stack words and put two down + j_dup2_x2, // 94 Duplicate top two stack words and put three down + j_swap, // 95 Swap two top stack words + j_iadd, // 96 Integer add + j_ladd, // 97 Long add + j_fadd, // 98 Single float add + j_dadd, // 99 Double float add + j_isub, // 100 Integer subtract + j_lsub, // 101 Long subtract + j_fsub, // 102 Single float subtract + j_dsub, // 103 Double Float subtract + j_imul, // 104 Integer multiply + j_lmul, // 105 Long multiply + j_fmul, // 106 Single float multiply + j_dmul, // 107 Double Float multiply + j_idiv, // 108 Integer divide + j_ldiv, // 109 Long divide + j_fdiv, // 110 Single float divide + j_ddiv, // 111 Double Float divide + j_irem, // 112 Integer reminder + j_lrem, // 113 Long reminder + j_frem, // 114 Single float reminder + j_drem, // 115 Double Float reminder + j_ineg, // 116 Integer negate + j_lneg, // 117 Long negate + j_fneg, // 118 Single float negate + j_dneg, // 119 Double Float negate + j_ishl, // 120 Integer shift left + j_lshl, // 121 Long shift left + j_ishr, // 122 Integer logical shift right + j_lshr, // 123 Long logical shift right + j_iushr, // 124 Integer arithmetic shift right + j_lushr, // 125 Long arithmeticshift right + j_iand, // 126 Integer boolean AND + j_land, // 127 Long boolean AND + j_ior, // 128 Integer boolean OR + j_lor, // 129 Long boolean OR + j_ixor, // 130 Integer boolean XOR + j_lxor, // 131 Long boolean XOR + j_iinc, // 132 Add 8-bit signed const to local variable + j_i2l, // 133 Integer to Long conversion + j_i2f, // 134 Integer to single float conversion + j_i2d, // 135 Integer to double float conversion + j_l2i, // 136 Long to Integer conversion + j_l2f, // 137 Long to single float conversion + j_l2d, // 138 Long to double float conversion + j_f2i, // 139 Single float to Integer conversion + j_f2l, // 140 Single float to Long conversion + j_f2d, // 141 Single float to double float conversion + j_d2i, // 142 Double float to Integer conversion + j_d2l, // 143 Double float to Long conversion + j_d2f, // 144 Double float to double float conversion + j_i2b, // 145 Integer to signed byte conversion + j_i2c, // 146 Integer to unsigned short conversion + j_i2s, // 147 Integer to signed short conversion + j_lcmp, // 148 Long compare + j_fcmpl, // 149 Single float compare (-1 on NaN) + j_fcmpg, // 150 Single float compare (1 on NaN) + j_dcmpl, // 151 Double float compare (-1 on NaN) + j_dcmpg, // 152 Double float compare (1 on NaN) + j_ifeq, // 153 Branch if equal to 0 + j_ifne, // 154 Branch if not equal to 0 + j_iflt, // 155 Branch if less then 0 + j_ifge, // 156 Branch if greater than or equal to 0 + j_ifgt, // 157 Branch if greater than 0 + j_ifle, // 158 Branch if less than or equal to 0 + j_if_icmpeq, // 159 Branch if integers equal + j_if_icmpne, // 160 Branch if integers not equal + j_if_icmplt, // 161 Branch if integers less than + j_if_icmpge, // 162 Branch if integers grater than or equal to + j_if_icmpgt, // 163 Branch if integers grater than + j_if_icmple, // 164 Branch if integers less than or equal to + j_if_acmpeq, // 165 Branch if object references are equal + j_if_acmpne, // 166 Branch if object references not equal + j_goto, // 167 Branch always + j_jsr, // 168 Jump subroutine + j_ret, // 169 Return from subroutine + j_tableswitch, // 170 Access jump table by index and jump + j_lookupswitch, // 171 Access jump table by key match and jump + j_ireturn, // 172 Return integer from function + j_lreturn, // 173 Return long from function + j_freturn, // 174 Return single floatr from function + j_dreturn, // 175 Return double float from function + j_areturn, // 176 Return object reference from function + j_return, // 177 Return (void) from procedure + j_getstatic, // 178 Set static field from class + j_putstatic, // 179 Set static field in class + j_getfield, // 180 Fetch field from object + j_putfield, // 181 Set field in object + j_invokevirtual, // 182 invoke instance method + j_invokespecial, // 183 invoke instance method (superclass/init/...) + j_invokestatic, // 184 invoke a class (static) method + j_invokeinterface,// 185 invoke interface method + j_invokedynamic, // 186 invoke instance method (select by paraneter) + j_new, // 187 Create new object + j_newarray, // 188 Allocate new array + j_anewarray, // 189 Allocate new array of refernces to object + j_arraylength, // 190 Get length of array + j_athrow, // 191 Throw exception or error + j_checkcast, // 192 Make sure object is of given type + j_instanceof, // 193 Determine if an object is of given type + j_monitorenter, // 194 Enter monitored region of code + j_monitorexit, // 195 Exit monitored region of code + j_wide, // 196 wide (prefix of command) + j_multianewarray, // 197 Allocate new multi-dimensional array + j_ifnull, // 198 Branch if NULL-ptr + j_ifnonnull, // 199 Branch if not NULL-ptr + j_goto_w, // 200 Branch always (wide index) + j_jsr_w, // 201 Jump subroutine (wide index) + j_breakpoint, // 202 Stop and pass control to breakpoint handler + // + j_lastnorm, + j_a_invokesuper = j_lastnorm, + j_a_invokevirtualobject, + j_a_invokeignored, + // bottom of table ! (emu) + j_a_software, + j_a_hardware, + // + j_last +}; + +enum name_quick +{ + j_ldc_quick = j_lastnorm, // 203 (18) + j_ldcw_quick, // 204 (19) + j_ldc2w_quick, // 205 (20) + j_getfield_quick, // 206 (180) + j_putfield_quick, // 207 (181) + j_getfield2_quick, // 208 + j_putfield2_quick, // 209 + j_getstatic_quick, // 210 (178) + j_putstatic_quick, // 211 (179) + j_getstatic2_quick, // 212 + j_putstatic2_quick, // 213 + j_invokevirtual_quick, // 214 (182) + j_invokenonvirtual_quick, // 215 (183) + j_invokesuper_quick, // 216 + j_invokestatic_quick, // 217 (184) + j_invokeinterface_quick, // 218 (185) + j_invokevirtualobject_quick, // 219 + j_invokeignored_quick, // 220 + j_new_quick, // 221 (187) + j_anewarray_quick, // 222 (189) + j_multianewarray_quick, // 223 (197) + j_checkcast_quick, // 224 (192) + j_instanceof_quick, // 225 (193) + j_invokevirtual_quick_w, // 226 + j_getfield_quick_w, // 227 + j_putfield_quick_w, // 228 + j_quick_last +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +ARM_null = 0, // Unknown Operation +ARM_ret, // Return from Subroutine +ARM_nop, // No Operation +ARM_b, // Branch +ARM_bl, // Branch with Link +ARM_asr, // Arithmetic Shift Right +ARM_lsl, // Logical Shift Left +ARM_lsr, // Logical Shift Right +ARM_ror, // Rotate Right +ARM_neg, // Negate +ARM_and, // 0 Rd = Op1 & Op2 +ARM_eor, // 1 Rd = Op1 ^ Op2 +ARM_sub, // 2 Rd = Op1 - Op2 +ARM_rsb, // 3 Rd = Op2 - Op1 +ARM_add, // 4 Rd = Op1 + Op2 +ARM_adc, // 5 Rd = Op1 + Op2 + C +ARM_sbc, // 6 Rd = Op1 - Op2 + C - 1 +ARM_rsc, // 7 Rd = Op2 - Op1 + C - 1 +ARM_tst, // 8 Set cond. codes on Op1 & Op2 +ARM_teq, // 9 Set cond. codes on Op1 ^ Op2 +ARM_cmp, // A Set cond. codes on Op1 - Op2 +ARM_cmn, // B Set cond. codes on Op1 + Op2 +ARM_orr, // C Rd = Op1 | Op2 +ARM_mov, // D Rd = Op2 +ARM_bic, // E Rd = Op1 & ~Op2 +ARM_mvn, // F Rd = ~Op2 +ARM_mrs, // Transfer PSR to Register +ARM_msr, // Transfer Register to PSR +ARM_mul, // Multiply +ARM_mla, // Multiply-Accumulate +ARM_ldr, // Load from Memory +ARM_ldrpc, // Indirect Jump +ARM_str, // Store to Memory +ARM_ldm, // Load Block from Memory +ARM_stm, // Store Block to Memory +ARM_swp, // Single Data Swap +ARM_svc, // Supervisor call + +// Version 4 + +ARM_smull, // Signed Multiply long +ARM_smlal, // Signed Multiply-Accumulate long +ARM_umull, // Unsigned Multiply long +ARM_umlal, // Unsigned Multiply-Accumulate long +ARM_bx, // Branch to/from Thumb mode +ARM_pop, // Pop registers +ARM_push, // Push registers +ARM_adr, // Load address + +// Version 5 + +ARM_bkpt, // Breakpoint +ARM_blx1, // Branch with Link and Exchange (immediate address) +ARM_blx2, // Branch with Link and Exchange (register indirect) +ARM_clz, // Count Leading Zeros + +// Version 5E + +ARM_ldrd, // Load pair of registers +ARM_pld, // Prepare to load data +ARM_qadd, // Saturated addition +ARM_qdadd, // Saturated addition with doubling +ARM_qdsub, // Saturated subtraction with doubling +ARM_qsub, // Saturated subtraction +ARM_smlabb, // Signed multiply-accumulate (bottom*bottom) +ARM_smlatb, // Signed multiply-accumulate (top*bottom) +ARM_smlabt, // Signed multiply-accumulate (bottom*top) +ARM_smlatt, // Signed multiply-accumulate (top*top) +ARM_smlalbb, // Long signed multiply-accumulate (bottom*bottom) +ARM_smlaltb, // Long signed multiply-accumulate (top*bottom) +ARM_smlalbt, // Long signed multiply-accumulate (bottom*top) +ARM_smlaltt, // Long signed multiply-accumulate (top*top) +ARM_smlawb, // Wide signed multiply-accumulate (bottom) +ARM_smulwb, // Wide signed multiply (bottom) +ARM_smlawt, // Wide signed multiply-accumulate (top) +ARM_smulwt, // Wide signed multiply (top) +ARM_smulbb, // Signed multiply (bottom*bottom) +ARM_smultb, // Signed multiply (top*bottom) +ARM_smulbt, // Signed multiply (bottom*top) +ARM_smultt, // Signed multiply (top*top) +ARM_strd, // Store pair of registers + +// Intel xScale coprocessor instructions + +xScale_mia, // Multiply-Internal Accumulate +xScale_miaph, // Multiply-Internal Accumulate Packed HalfWords +xScale_miabb, // Multiply-Internal Accumulate Bottom-Bottom Halves +xScale_miabt, // Multiply-Internal Accumulate Bottom-Top Halves +xScale_miatb, // Multiply-Internal Accumulate Top-Bottom Halves +xScale_miatt, // Multiply-Internal Accumulate Top-Top Halves +xScale_mar, // Move To Internal Accumulator +xScale_mra, // Move From Internal Accumulator + +// Macro instructions + +ARM_movl, // Move immediate to register +ARM_adrl, // Load address +ARM_swbkpt, // WinCE Debugger break + +// Coprocessor instructions + +ARM_cdp, // Coprocessor Data Processing +ARM_cdp2, // Coprocessor Data Processing +ARM_ldc, // Load Coprocessor Register +ARM_ldc2, // Load Coprocessor Register +ARM_stc, // Store Coprocessor Register +ARM_stc2, // Store Coprocessor Register +ARM_mrc, // Move from Coprocessor to ARM Register +ARM_mrc2, // Move from Coprocessor to ARM Register +ARM_mcr, // Move from ARM to Coprocessor Register +ARM_mcr2, // Move from ARM to Coprocessor Register +ARM_mcrr, // Copy pair of registers to coprocessor (5E) +ARM_mrrc, // Copy pair of registers from coprocessor (5E) + +// VFP instructions + +ARM_fabsd, // Floating point Absolute Value, Double precision +ARM_fabss, // Floating point Absolute Value, Single precision +ARM_faddd, // Floating point Addition, Double precision +ARM_fadds, // Floating point Addition, Single precision +ARM_fcmpd, // Floating point Compare, Double precision +ARM_fcmps, // Floating point Compare, Single precision +ARM_fcmped, // Floating point Compare (NaN Exceptions), Double precision +ARM_fcmpes, // Floating point Compare (NaN Exceptions), Single precision +ARM_fcmpezd, // Floating point Compare (NaN Exceptions) with Zero, Double precision +ARM_fcmpezs, // Floating point Compare (NaN Exceptions) with Zero, Single precision +ARM_fcmpzd, // Floating point Compare with Zero, Double precision +ARM_fcmpzs, // Floating point Compare with Zero, Single precision +ARM_fcpyd, // Floating point Copy, Double precision +ARM_fcpys, // Floating point Copy, Single precision +ARM_fcvtsd, // Floating point Convert to Single precision from Double precision +ARM_fcvtds, // Floating point Convert to Double precision from Single precision +ARM_fdivd, // Floating point Divide, Double precision +ARM_fdivs, // Floating point Divide, Single precision +ARM_fldd, // Floating point Load, Double precision +ARM_flds, // Floating point Load, Single precision +ARM_fldmd, // Floating point Load Multiple, Double precision +ARM_fldms, // Floating point Load Multiple, Single precision +ARM_fldmx, // Floating point Load Multiple, Unknown precision +ARM_fmacd, // Floating point Multiply and Accumulate, Double precision +ARM_fmacs, // Floating point Multiply and Accumulate, Single precision +ARM_fmscd, // Floating point Multiply and Subtract, Double precision +ARM_fmscs, // Floating point Multiply and Subtract, Single precision +ARM_fmstat, // Floating point Move Status +ARM_fmuld, // Floating point Multiply, Double precision +ARM_fmuls, // Floating point Multiply, Single precision +ARM_fnegd, // Floating point Negate, Double precision +ARM_fnegs, // Floating point Negate, Single precision +ARM_fnmacd, // Floating point Negated Multiply and Accumulate, Double precision +ARM_fnmacs, // Floating point Negated Multiply and Accumulate, Single precision +ARM_fnmscd, // Floating point Negated Multiply and Subtract, Double precision +ARM_fnmscs, // Floating point Negated Multiply and Subtract, Single precision +ARM_fnmuld, // Floating point Negated Multiply, Double precision +ARM_fnmuls, // Floating point Negated Multiply, Single precision +ARM_fsitod, // Floating point Convert Signed Integer to Double precision +ARM_fsitos, // Floating point Convert Signed Integer to Single precision +ARM_fsqrtd, // Floating point Square Root, Double precision +ARM_fsqrts, // Floating point Square Root, Single precision +ARM_fstd, // Floating point Store, Double precision +ARM_fsts, // Floating point Store, Single precision +ARM_fstmd, // Floating point Store Multiple, Double precision +ARM_fstms, // Floating point Store Multiple, Single precision +ARM_fstmx, // Floating point Store Multiple, Unknown precision +ARM_fsubd, // Floating point Subtract, Double precision +ARM_fsubs, // Floating point Subtract, Single precision +ARM_ftosid, // Floating point Convert to Signed Integer from Double precision +ARM_ftosis, // Floating point Convert to Signed Integer from Single precision +ARM_ftosizd, // Floating point Convert to Signed Integer from Double precision, RZ mode +ARM_ftosizs, // Floating point Convert to Signed Integer from Single precision, RZ mode +ARM_ftouid, // Floating point Convert to Unsigned Integer from Double precision +ARM_ftouis, // Floating point Convert to Unsigned Integer from Single precision +ARM_ftouizd, // Floating point Convert to Unsigned Integer from Double precision, RZ mode +ARM_ftouizs, // Floating point Convert to Unsigned Integer from Single precision, RZ mode +ARM_fuitod, // Floating point Convert Unsigned Integer to Double precision +ARM_fuitos, // Floating point Convert Unsigned Integer to Single precision +ARM_fmdhr, // Floating point Move to Double precision High from Register +ARM_fmrdh, // Floating point Move to Register from Double precision High +ARM_fmdlr, // Floating point Move to Double precision Low from Register +ARM_fmrdl, // Floating point Move to Register from Double precision Low +ARM_fmxr, // Floating point Move to System Register from Register +ARM_fmrx, // Floating point Move to Register from System Register +ARM_fmsr, // Floating point Move to Single precision from Register +ARM_fmrs, // Floating point Move to Register from Single precision + +// VFP ARMv5TE extensions + +ARM_fmdrr, // Floating point Move to Double precision from two Registers +ARM_fmrrd, // Floating point Move to two Registers from Double precision +ARM_fmsrr, // Floating point Move to two Single precision from two Registers +ARM_fmrrs, // Floating point Move to two Registers from two Single precision + +// ARM v5J instructions + +ARM_bxj, // Branch to Jazelle + +// ARM v6 instructions + +ARM_mcrr2, // Move to Coprocessor from two ARM Registers +ARM_mrrc2, // Move to two ARM Registers from Coprocessor +ARM_cps, // Change Processor State +ARM_cpsid, // Disable Interrupts +ARM_cpsie, // Enable Interrupts +ARM_ldrex, // Load Register Exclusive +ARM_pkhbt, // Pack halfword bottom + top +ARM_pkhtb, // Pack halfword top + bottom +ARM_qadd16, // Signed saturating arithmetic hafword-wise addition +ARM_qadd8, // Signed saturating arithmetic byte-wise addition +ARM_qaddsubx, // Signed saturating arithmetic exchange, add, substract +ARM_qsub16, // Signed saturating arithmetic hafword-wise substraction +ARM_qsub8, // Signed saturating arithmetic byte-wise substraction +ARM_qsubaddx, // Signed saturating arithmetic exchange, substract, add +ARM_rev, // Byte Reverse Word +ARM_rev16, // Byte Reverse Packed Halfword +ARM_revsh, // Byte Reverse Signed Halfword +ARM_rfe, // Return from exception +ARM_sadd16, // Signed arithmetic modulo hafword-wise addition +ARM_sadd8, // Signed arithmetic modulo byte-wise addition +ARM_saddsubx, // Signed arithmetic modulo exchange, add, substract +ARM_sel, // Select bytes +ARM_setend, // Set Byte Endianness +ARM_shadd16, // Signed arithmetic hafword-wise addition, halving results +ARM_shadd8, // Signed arithmetic byte-wise addition, halving results +ARM_shaddsubx, // Signed arithmetic exchange, add, substract, halving results +ARM_shsub16, // Signed arithmetic hafword-wise substraction, halving results +ARM_shsub8, // Signed arithmetic byte-wise substraction, halving results +ARM_shsubaddx, // Signed arithmetic exchange, substract, add, halving results +ARM_smlad, // Dual signed multiply, add and accumulate +ARM_smladx, // Dual signed multiply, add and accumulate crossed +ARM_smuad, // Dual signed multiply and add +ARM_smuadx, // Dual signed multiply and add crossed +ARM_smlald, // Dual signed multiply, add and accumulate long +ARM_smlaldx, // Dual signed multiply, add and accumulate long crossed +ARM_smlsd, // Dual signed multiply, substract and accumulate +ARM_smlsdx, // Dual signed multiply, substract and accumulate crossed +ARM_smusd, // Dual signed multiply and substract +ARM_smusdx, // Dual signed multiply and substract crossed +ARM_smlsld, // Dual signed multiply, substract and accumulate long +ARM_smlsldx, // Dual signed multiply, substract and accumulate long crossed +ARM_smmla, // Signed most significant word multiply and accumulate truncated +ARM_smmlar, // Signed most significant word multiply and accumulate rounded +ARM_smmul, // Signed most significant word multiply truncated +ARM_smmulr, // Signed most significant word multiply rounded +ARM_smmls, // Signed most significant word multiply and substract truncated +ARM_smmlsr, // Signed most significant word multiply and substract rounded +ARM_srs, // Store Return State +ARM_ssat, // Signed Saturate +ARM_ssat16, // Signed saturate two halfwords +ARM_ssub16, // Signed arithmetic hafword-wise substraction +ARM_ssub8, // Signed arithmetic byte-wise substraction +ARM_ssubaddx, // Signed arithmetic exchange, substract, add +ARM_strex, // Store Register Exclusive +ARM_sxtab, // Signed extend byte to word, add +ARM_sxtb, // Signed extend byte to word +ARM_sxtab16, // Signed extend two bytes to halfwords, add +ARM_sxtb16, // Signed extend two bytes to halfwords +ARM_sxtah, // Signed extend halfword to word, add +ARM_sxth, // Signed extend halfword to word +ARM_uadd16, // Unsigned arithmetic modulo hafword-wise addition +ARM_uadd8, // Unsigned arithmetic modulo byte-wise addition +ARM_uaddsubx, // Unsigned arithmetic modulo exchange, add, substract +ARM_uhadd16, // Unsigned arithmetic hafword-wise addition, halving results +ARM_uhadd8, // Unsigned arithmetic byte-wise addition, halving results +ARM_uhaddsubx, // Unsigned arithmetic exchange, add, substract, halving results +ARM_uhsub16, // Unsigned arithmetic hafword-wise substraction, halving results +ARM_uhsub8, // Unsigned arithmetic byte-wise substraction, halving results +ARM_uhsubaddx, // Unsigned arithmetic exchange, substract, add, halving results +ARM_umaal, // Multiply unsigned double accumulate long +ARM_uqadd16, // Unsigned saturating arithmetic hafword-wise addition +ARM_uqadd8, // Unsigned saturating arithmetic byte-wise addition +ARM_uqaddsubx, // Unsigned saturating arithmetic exchange, add, substract +ARM_uqsub16, // Unsigned saturating arithmetic hafword-wise substraction +ARM_uqsub8, // Unsigned saturating arithmetic byte-wise substraction +ARM_uqsubaddx, // Unsigned saturating arithmetic exchange, substract, add +ARM_usada8, // Unsigned sum of absolute differences and accumulate +ARM_usad8, // Unsigned sum of absolute differences +ARM_usat, // Unsigned saturate word +ARM_usat16, // Unsigned saturate two halfwords +ARM_usub16, // Unsigned arithmetic hafword-wise substraction +ARM_usub8, // Unsigned arithmetic byte-wise substraction +ARM_usubaddx, // Unsigned arithmetic exchange, substract, add +ARM_uxtab, // Unsigned extend byte to word, add +ARM_uxtb, // Unsigned extend byte to word +ARM_uxtab16, // Unsigned extend two bytes to halfwords, add +ARM_uxtb16, // Unsigned extend two bytes to halfwords +ARM_uxtah, // Unsigned extend halfword to word, add +ARM_uxth, // Unsigned extend halfword to word + +// ARM v6zk instructions + +ARM_clrex, // Clear Exclusive +ARM_ldrexb, // Load Byte Exclusive +ARM_ldrexd, // Load DoubleWord Exclusive +ARM_ldrexh, // Load Halfword Exclusive +ARM_strexb, // Store Byte Exclusive +ARM_strexd, // Store DoubleWord Exclusive +ARM_strexh, // Store Halfword Exclusive +ARM_yield, // Yield (hint) +ARM_sev, // Send Event (hint) +ARM_wfe, // Wait For Event (hint) +ARM_wfi, // Wait For Interrupt (hint) +ARM_smc, // Secure Monitor Call + +// ARM Thumb32 instructions + +ARM_orn, // Rd = Op1 | ~Op2 +ARM_movt, // Move Top +ARM_sbfx, // Signed Bit Field Extract +ARM_ubfx, // Unsigned Bit Field Extract +ARM_bfi, // Bit Field Insert +ARM_bfc, // Bit Field Clear +ARM_tbb, // Table Branch Byte +ARM_tbh, // Table Branch Halfword +ARM_pli, // Prepare to load code +ARM_rbit, // Reverse Bits +ARM_it, // If Then +ARM_mls, // Multiply and Subtract +ARM_sdiv, // Signed Divide +ARM_udiv, // Unsigned Divide +ARM_cbz, // Compare and Branch on Zero +ARM_cbnz, // Compare and Branch on Non-Zero +ARM_dsb, // Data Synchronization Barrier +ARM_dmb, // Data Memory Barrier +ARM_isb, // Instruction Synchronization Barrier +ARM_dbg, // Debug Hint + +ARM_und, // Architecturally undefined instruction + +// missing instructions (not yet decoded) + +ARM_rrx, // Rotate Right with Extend +ARM_enterx, // Enter ThumbEE state +ARM_leavex, // Leave ThumbEE state +ARM_chka, // Check Array +ARM_hb, // Handler Branch +ARM_hbl, // Handler Branch with Link +ARM_hblp, // Handler Branch with Link and Parameter +ARM_hbp, // Handler Branch with Parameter + +// NEON (Advanced SIMD) and extra VFP instructions + +ARM_vaba, // Vector Absolute Difference and Accumulate +ARM_vabal, // Vector Absolute Difference and Accumulate Long +ARM_vabd, // Vector Absolute Difference +ARM_vabdl, // Vector Absolute Difference Long +ARM_vabs, // Vector Absolute +ARM_vacge, // Vector Absolute Compare Greater Than or Equal +ARM_vacgt, // Vector Absolute Compare Greater Than +ARM_vacle, // Vector Absolute Compare Less Than or Equal +ARM_vaclt, // Vector Absolute Compare Less Than +ARM_vadd, // Vector Add +ARM_vaddhn, // Vector Add and Narrow, returning High Half +ARM_vaddl, // Vector Add Long +ARM_vaddw, // Vector Add Wide +ARM_vand, // Vector Bitwise AND +ARM_vbic, // Vector Bitwise Bit Clear +ARM_vbif, // Vector Bitwise Insert if False +ARM_vbit, // Vector Bitwise Insert if True +ARM_vbsl, // Vector Bitwise Select +ARM_vceq, // Vector Compare Equal +ARM_vcge, // Vector Compare Greater Than or Equal +ARM_vcgt, // Vector Compare Greater Than +ARM_vcle, // Vector Compare Less Than or Equal +ARM_vcls, // Vector Count Leading Sign Bits +ARM_vclt, // Vector Compare Less Than +ARM_vclz, // Vector Count Leading Zeros +ARM_vcmp, // Vector Compare +ARM_vcmpe, // Vector Compare (Quiet NaNs trigger Exception) +ARM_vcnt, // Vector Count Number of Bits +ARM_vcvt, // Vector Convert +ARM_vcvtr, // Vector Convert Rounding +ARM_vcvtb, // Vector Convert Half-Precision Bottom +ARM_vcvtt, // Vector Convert Half-Precision Top +ARM_vdiv, // Vector Divide +ARM_vdup, // Vector Duplicate +ARM_veor, // Vector Bitwise Exclusive OR +ARM_vext, // Vector Extract +ARM_vfma, // Vector Fused Multiply Accumulate +ARM_vfms, // Vector Fused Multiply Substract +ARM_vfnma, // Vector Fused Negated Multiply Accumulate +ARM_vfnms, // Vector Fused Negated Multiply Substract +ARM_vhadd, // Vector Halving Add +ARM_vhsub, // Vector Halving Sub +ARM_vld1, // Vector Load Single Element +ARM_vld2, // Vector Load Two-Element Structures +ARM_vld3, // Vector Load Three-Element Structures +ARM_vld4, // Vector Load Four-Element Structures +ARM_vldm, // Vector Load Multiple +ARM_vldr, // Vector Load Register +ARM_vmax, // Vector Maximum +ARM_vmin, // Vector Minimum +ARM_vmla, // Vector Multiply Accumulate +ARM_vmlal, // Vector Multiply Accumulate Long +ARM_vmls, // Vector Multiply Subtract +ARM_vmlsl, // Vector Multiply Subtract Long +ARM_vmov, // Vector Move +ARM_vmovl, // Vector Move Long +ARM_vmovn, // Vector Move and Narrow +ARM_vmrs, // Move FPSCR to ARM Register +ARM_vmsr, // Move to FPSCR from ARM Register +ARM_vmul, // Vector Multiply +ARM_vmull, // Vector Multiply Long +ARM_vmvn, // Vector Bitwise NOT +ARM_vneg, // Vector Negate +ARM_vnmla, // Vector Multiply Add Negated +ARM_vnmls, // Vector Multiply Substract Negated +ARM_vnmul, // Vector Multiply Negated +ARM_vorn, // Vector Bitwise OR NOT +ARM_vorr, // Vector Bitwise OR +ARM_vpadal, // Vector Pairwise Add and Accumulate Long +ARM_vpadd, // Vector Pairwise Add +ARM_vpaddl, // Vector Pairwise Add Long +ARM_vpmax, // Vector Pairwise Maximum +ARM_vpmin, // Vector Pairwise Minimum +ARM_vpop, // Vector Pop +ARM_vpush, // Vector Push +ARM_vqabs, // Vector Saturating Absolute +ARM_vqadd, // Vector Saturating Add +ARM_vqdmlal, // Vector Saturating Doubling Multiply Accumulate Long +ARM_vqdmlsl, // Vector Saturating Doubling Multiply Subtract Long +ARM_vqdmulh, // Vector Saturating Doubling Multiply Returning High Half +ARM_vqdmull, // Vector Saturating Doubling Multiply Long +ARM_vqmovn, // Vector Saturating Move and Narrow +ARM_vqmovun, // Vector Saturating Move and Narrow, Unsigned result +ARM_vqneg, // Vector Saturating Negate +ARM_vqrdmulh, // Vector Saturating Rounding Doubling Multiply Returning High Half +ARM_vqrshl, // Vector Saturating Rounding Shift Left +ARM_vqrshrn, // Vector Saturating Rounding Shift Right, Narrow +ARM_vqrshrun, // Vector Saturating Rounding Shift Right, Narrow, Unsigned result +ARM_vqshl, // Vector Saturating Shift Left +ARM_vqshlu, // Vector Saturating Shift Left, Unsigned result +ARM_vqshrn, // Vector Saturating Shift Right, Narrow +ARM_vqshrun, // Vector Saturating Shift Right, Narrow, Unsigned result +ARM_vqsub, // Vector Saturating Subtract +ARM_vraddhn, // Vector Rounding Add and Narrow, returning High Half +ARM_vrecpe, // Vector Reciprocal Estimate +ARM_vrecps, // Vector Reciprocal Step +ARM_vrev16, // Vector Reverse in halfwords +ARM_vrev32, // Vector Reverse in words +ARM_vrev64, // Vector Reverse in doublewords +ARM_vrhadd, // Vector Rounding Halving Add +ARM_vrshl, // Vector Rounding Shift Left +ARM_vrshr, // Vector Rounding Shift Right +ARM_vrshrn, // Vector Rounding Shift Right and Narrow +ARM_vrsqrte, // Vector Reciprocal Square Root Estimate +ARM_vrsqrts, // Vector Reciprocal Square Root Step +ARM_vrsra, // Vector Rounding Shift Right and Accumulate +ARM_vrsubhn, // Vector Rounding Subtract and Narrow, returning High Half +ARM_vshl, // Vector Shift Left +ARM_vshll, // Vector Shift Left Long +ARM_vshr, // Vector Shift Right +ARM_vshrn, // Vector Shift Right Narrow +ARM_vsli, // Vector Shift Left and Insert +ARM_vsqrt, // Vector Square Root +ARM_vsra, // Vector Shift Right and Accumulate +ARM_vsri, // Vector Shift Right and Insert +ARM_vst1, // Vector Store Single Element +ARM_vst2, // Vector Store Two-Element Structures +ARM_vst3, // Vector Store Three-Element Structures +ARM_vst4, // Vector Store Four-Element Structures +ARM_vstm, // Vector Store Multiple +ARM_vstr, // Vector Store Register +ARM_vsub, // Vector Subtract +ARM_vsubhn, // Vector Subtract and Narrow, returning High Half +ARM_vsubl, // Vector Subtract Long +ARM_vsubw, // Vector Subtract Wide +ARM_vswp, // Vector Swap +ARM_vtbl, // Vector Table Lookup +ARM_vtbx, // Vector Table Extension +ARM_vtrn, // Vector Transpose +ARM_vtst, // Vector Test Bits +ARM_vuzp, // Vector Unzip +ARM_vzip, // Vector Zip + +// ARMv7 Hypervisor extensions + +ARM_eret, // Exception Return +ARM_hvc, // Hypervisor Call + +// new ARMv8 instructions for A32 and T32 mode + +ARM_lda, // Load-Acquire Word/Byte/Halfword +ARM_stl, // Store-Release Word/Byte/Halfword +ARM_ldaex, // Load-Acquire Exclusive Word/Byte/Halfword +ARM_stlex, // Store-Release Exclusive Word/Byte/Halfword +ARM_vsel, // Floating-point Conditional Select + +ARM_vmaxnm, // Vector Maximum Numeric +ARM_vminnm, // Vector Minimum Numeric +ARM_vcvta, // Vector Convert Round to Nearest with Ties to Away +ARM_vcvtn, // Vector Convert Round to Nearest with Ties to Even +ARM_vcvtp, // Vector Convert Round towards +Infinity +ARM_vcvtm, // Vector Convert Round towards -Infinity +ARM_vrintx, // Vector Round to Integral, FPSCR rounding mode and signaling inexactness +ARM_vrintr, // Vector Round to Integral, FPSCR rounding mode +ARM_vrintz, // Vector Round to Integral, Round toward Zero +ARM_vrinta, // Vector Round to Integral, Round to Nearest with Ties to Away +ARM_vrintn, // Vector Round to Integral, Round to Nearest with Ties to Even +ARM_vrintp, // Vector Round to Integral, Round towards +Infinity +ARM_vrintm, // Vector Round to Integral, Round towards -Infinity + +ARM_aesd, // AES single round decryption +ARM_aese, // AES single round encryption +ARM_aesimc, // AES inverse mix columns +ARM_aesmc, // AES mix columns +ARM_sha1c, // SHA1 hash update accelerator, choose +ARM_sha1m, // SHA1 hash update accelerator, majority +ARM_sha1p, // SHA1 hash update accelerator, parity +ARM_sha1h, // SHA1 hash update accelerator, rotate left by 30 +ARM_sha1su0, // SHA1 schedule update accelerator, first part +ARM_sha1su1, // SHA1 schedule update accelerator, second part +ARM_sha256h, // SHA256 hash update accelerator +ARM_sha256h2, // SHA256 hash update accelerator upper part +ARM_sha256su0, // SHA256 schedule update accelerator, first part +ARM_sha256su1, // SHA256 schedule update accelerator, second part + +ARM_dcps1, // Debug Change Processor State to EL1 +ARM_dcps2, // Debug Change Processor State to EL2 +ARM_dcps3, // Debug Change Processor State to EL3 +ARM_hlt, // Halting mode software breakpoint +ARM_sevl, // Send Event Locally + +// ARMv8 AArch64 new instructions + +ARM_tbz, // Test and Branch Zero +ARM_tbnz, // Test and Branch Non-Zero +ARM_br, // Branch To Register +ARM_blr, // Branch and Link Register +ARM_ldur, // Load Single Register (unscaled offset) +ARM_stur, // Store Single Register (unscaled offset) +ARM_ldp, // Load Pair +ARM_stp, // Store Pair +ARM_ldnp, // Load Non-temporal Pair +ARM_stnp, // Store Non-temporal Pair +ARM_ldtr, // Load Unprivileged Register +ARM_sttr, // Store Unprivileged Register +ARM_ldxr, // Load Exclusive Register +ARM_stxr, // Store Exclusive Register +ARM_ldxp, // Load Exclusive Pair +ARM_stxp, // Store Exclusive Pair +ARM_ldar, // Load-Acquire Register +ARM_stlr, // Store-Release Register +ARM_ldaxr, // Load-Acquire Exclusive Register +ARM_stlxr, // Store-Release Exclusive Register +ARM_ldaxp, // Load-Acquire Exclusive Pair +ARM_stlxp, // Store Exclusive Pair +ARM_prfm, // Prefetch Memory +ARM_prfum, // Prefetch Memory (unscaled offset) +ARM_movi, // Move Immediate +ARM_mvni, // Move Inverted Immediate +ARM_movz, // Move with Zero +ARM_movn, // Move with Not +ARM_movk, // Move with Keep +ARM_adrp, // Address of Page +ARM_bfm, // Bitfield Move +ARM_sbfm, // Signed Bitfield Move +ARM_ubfm, // Unsigned Bitfield Move +// ARM_bfi, // Bitfield Insert +ARM_bfxil, // Bitfield Extract and Insert Low +ARM_sbfiz, // Signed Bitfield Insert in Zero +// ARM_sbfx, // Signed Bitfield Extract +ARM_ubfiz, // Signed Bitfield Insert in Zero +// ARM_ubfx, // Unsigned Bitfield Extract +ARM_extr, // Extract +ARM_sxtw, // Signed Extend Word +ARM_uxtw, // Unsigned Extend Word (non-existing insn) +ARM_eon, // Bitwise exclusive OR NOT +ARM_not, // Bitwise NOT +ARM_cls, // Count Leading Sign Bits +ARM_rev32, // Reverse Bytes in Words +ARM_csel, // Conditional Select +ARM_csinc, // Conditional Select Increment +ARM_csinv, // Conditional Select Invert +ARM_csneg, // Conditional Select Negate +ARM_cset, // Conditional Set +ARM_csetm, // Conditional Set Mask +ARM_cinc, // Conditional Increment +ARM_cinv, // Conditional Invert +ARM_cneg, // Conditional Negate +ARM_ngc, // Negate with Carry +ARM_ccmn, // Conditional Compare Negative +ARM_ccmp, // Conditional Compare +ARM_madd, // Multiply-Add +ARM_msub, // Multiply-Subtract +ARM_mneg, // Multiply-Negate +ARM_smaddl, // Signed Multiply-Add Long +ARM_smsubl, // Signed Multiply-Subtract Long +ARM_smnegl, // Signed Multiply-Negate Long +ARM_smulh, // Signed Multiply High +ARM_umaddl, // Unsigned Multiply-Add Long +ARM_umsubl, // Unsigned Multiply-Subtract Long +ARM_umnegl, // Unsigned Multiply-Negate Long +ARM_umulh, // Unsigned Multiply High + +ARM_drps, // Debug Restore Processor State +ARM_sys, // System Maintenance Operation +ARM_sysl, // System Maintenance Operation With Result +ARM_ic, // Instruction Cache Maintenance +ARM_dc, // Data Cache Maintenance +ARM_at, // Address Translation +ARM_tlbi, // TLB Invalidation +ARM_hint, // Hint instruction +ARM_brk, // Monitor debug-mode breakpoint + +// AArch64 Advanced SIMD +ARM_uaba, // Unsigned Integer Absolute Difference and Accumulate +ARM_saba, // Signed Integer Absolute Difference and Accumulate +ARM_uabal, // Unsigned Integer Absolute Difference and Accumulate Long +ARM_uabal2, // Unsigned Integer Absolute Difference and Accumulate Long (Second Part) +ARM_sabal, // Signed Integer Absolute Difference and Accumulate Long +ARM_sabal2, // Signed Integer Absolute Difference and Accumulate Long (Second Part) +ARM_uabd, // Unsigned Integer Absolute Difference +ARM_sabd, // Signed Integer Absolute Difference +ARM_fabd, // Floating-point Absolute Difference +ARM_uabdl, // Unsigned Integer Absolute Difference Long +ARM_uabdl2, // Unsigned Integer Absolute Difference Long (Second Part) +ARM_sabdl, // Signed Integer Absolute Difference Long +ARM_sabdl2, // Signed Integer Absolute Difference Long (Second Part) +ARM_abs, // Integer Absolute Value +ARM_fabs, // Floating-point Absolute Value +ARM_facge, // Floating-point Absolute Compare Greater Than or Equal +ARM_facgt, // Floating-point Absolute Compare Greater Than +ARM_facle, // Floating-point Absolute Compare Less Than or Equal +ARM_faclt, // Floating-point Absolute Compare Less Than +ARM_fadd, // Floating-point Add +ARM_addhn, // Integer Vector Add and Narrow High Half +ARM_addhn2, // Integer Vector Add and Narrow High Half (second part) +ARM_uaddl, // Unsigned Integer Add Long +ARM_uaddl2, // Unsigned Integer Add Long (second part) +ARM_saddl, // Signed Integer Add Long +ARM_saddl2, // Signed Integer Add Long (second part) +ARM_uaddw, // Unsigned Integer Add Wide +ARM_uaddw2, // Unsigned Integer Add Wide (second part) +ARM_saddw, // Signed Integer Add Wide +ARM_saddw2, // Signed Integer Add Wide (second part) +ARM_bif, // Bitwise Vector Insert if False +ARM_bit, // Bitwise Vector Insert if True +ARM_bsl, // Bitwise Vector Select +ARM_cmeq, // Ingeger Vector Compare Equal +ARM_fcmeq, // Floating-point Vector Compare Equal +ARM_cmhs, // Unsigned Compare Greater Than or Equal +ARM_cmge, // Signed Compare Greater Than or Equal +ARM_fcmge, // Floating-point Compare Greater Than or Equal +ARM_cmhi, // Unsigned Compare Greater Than +ARM_cmgt, // Signed Compare Greater Than +ARM_fcmgt, // Floating-point Compare Greater Than +ARM_cmls, // Unsigned Compare Less Than or Equal +ARM_cmle, // Signed Compare Less Than or Equal +ARM_fcmle, // Floating-point Compare Less Than or Equal +ARM_cmlo, // Unsigned Compare Less Than +ARM_cmlt, // Signed Compare Less Than +ARM_fcmlt, // Floating-point Compare Less Than +ARM_fcmp, // Floating-point Compare +ARM_fcmpe, // Floating-point Signaling Compare +ARM_fccmp, // Floating-point Conditional Quiet Compare +ARM_fccmpe, // Floating-point Conditional Signaling Compare +ARM_fcsel, // Floating-point Conditional Select +ARM_cnt, // Vector Count Non-zero Bits +ARM_fcvt, // Floating-point convert precision (scalar) +ARM_fcvtzs, // Convert Floating-point to Signed Integer (Round to Zero) +ARM_fcvtas, // Convert Floating-point to Signed Integer (Round to Nearest, Ties to Away) +ARM_fcvtns, // Convert Floating-point to Signed Integer (Round to Nearest, Ties to Even) +ARM_fcvtps, // Convert Floating-point to Signed Integer (Round towards +Infinity) +ARM_fcvtms, // Convert Floating-point to Signed Integer (Round towards -Infinity) +ARM_fcvtzu, // Convert Floating-point to Unsigned Integer (Round to Zero) +ARM_fcvtau, // Convert Floating-point to Unsigned Integer (Round to Nearest, Ties to Away) +ARM_fcvtnu, // Convert Floating-point to Unsigned Integer (Round to Nearest, Ties to Even) +ARM_fcvtpu, // Convert Floating-point to Unsigned Integer (Round towards +Infinity) +ARM_fcvtmu, // Convert Floating-point to Unsigned Integer (Round towards -Infinity) +ARM_ucvtf, // Convert Unsigned Integer to Floating-point +ARM_scvtf, // Convert Signed Integer to Floating-point +ARM_fcvtn, // Floating-point Convert Precision, Narrow +ARM_fcvtn2, // Floating-point Convert Precision, Narrow (second part) +ARM_fcvtl, // Floating-point Convert Precision, Long +ARM_fcvtl2, // Floating-point Convert Precision, Long (second part) +ARM_fcvtxn, // Floating-point Convert Precision, Narrow (Round to Odd) +ARM_fcvtxn2, // Floating-point Convert Precision, Narrow (Round to Odd) (second part) +ARM_frinta, // Floating-point Round to Integral (Round to Nearest, Ties to Away) +ARM_frinti, // Floating-point Round to Integral (using FPCR rounding mode) +ARM_frintm, // Floating-point Round to Integral (Round towards -Infinity) +ARM_frintn, // Floating-point Round to Integral (Round to Nearest, Ties to Even) +ARM_frintp, // Floating-point Round to Integral (Round towards +Infinity) +ARM_frintx, // Floating-point Round to Integral (using FPCR rounding mode, with exactness test) +ARM_frintz, // Floating-point Round to Integral (Round towards Zero) +ARM_fmadd, // Floating-point scalar fused multiply-add +ARM_fmsub, // Floating-point scalar fused multiply-subtract +ARM_fnmadd, // Floating-point scalar negated fused multiply-add +ARM_fnmsub, // Floating-point scalar negated fused multiply-subtract +ARM_fdiv, // Floating-point Divide +ARM_dup, // Duplicate Single Element to All Elements +ARM_ins, // Insert Single Element in Another Element +ARM_ext, // Bitwise Extract +ARM_uhadd, // Unsigned Integer Halving Add +ARM_shadd, // Signed Integer Halving Add +ARM_uhsub, // Unsigned Integer Halving Subtract +ARM_shsub, // Signed Integer Halving Subtract +ARM_ld1, // Vector Load Single Element +ARM_ld2, // Vector Load Two-Element Structures +ARM_ld3, // Vector Load Three-Element Structures +ARM_ld4, // Vector Load Four-Element Structures +ARM_ld1r, // Vector Load Single Element and Replicate +ARM_ld2r, // Vector Load Two-Element Structures and Replicate +ARM_ld3r, // Vector Load Three-Element Structures and Replicate +ARM_ld4r, // Vector Load Four-Element Structures and Replicate +ARM_umax, // Unsigned Integer Maximum +ARM_smax, // Signed Integer Maximum +ARM_fmax, // Floating-point Maximum +ARM_fmaxnm, // Floating-point maxNum() +ARM_umin, // Unsigned Integer Minimum +ARM_smin, // Signed Integer Minimum +ARM_fmin, // Floating-point Minimum +ARM_fminnm, // Floating-point minNum() +ARM_fmla, // Fused Multiply-Add +ARM_umlal2, // Unsigned Integer Multiply-Add Long (second part) +ARM_smlal2, // Signed Integer Multiply-Add Long (second part) +ARM_fmls, // Fused Multiply-Subtract +ARM_umlsl, // Unsigned Integer Multiply-Subtract Long +ARM_umlsl2, // Unsigned Integer Multiply-Subtract Long (second part) +ARM_smlsl, // Signed Integer Multiply-Subtract Long +ARM_smlsl2, // Signed Integer Multiply-Subtract Long (second part) +ARM_umov, // Unsigned Integer Move +ARM_smov, // Signed Integer Move +ARM_fmov, // Floating-point Move +ARM_uxtl, // Unsigned Integer Vector Lengthen +ARM_uxtl2, // Unsigned Integer Vector Lengthen (second part) +ARM_sxtl, // Signed Integer Vector Lengthen +ARM_sxtl2, // Signed Integer Vector Lengthen (second part) +ARM_xtn, // Integer Vector Narrow +ARM_xtn2, // Integer Vector Narrow (second part) +ARM_fmul, // Floating-point Vector Multiply +ARM_pmul, // Polynomial Vector Multiply +ARM_fmulx, // Floating-point Multiply Extended +ARM_fnmul, // Floating-point Multiply-Negate +ARM_umull2, // Unsigned Integer Vector Multiply Long (second part) +ARM_smull2, // Signed Integer Vector Multiply Long (second part) +ARM_pmull, // Polynomial Vector Multiply Long +ARM_pmull2, // Polynomial Vector Multiply Long (second part) +ARM_fneg, // Floating-point Negate +ARM_uadalp, // Unsigned Integer Vector Add and Accumulate Long Pair +ARM_sadalp, // Signed Integer Vector Add and Accumulate Long Pair +ARM_addp, // Integer Vector Add Pair +ARM_faddp, // Floating-point Vector Add Pair +ARM_uaddlp, // Unsigned Integer Vector Add Long Pair +ARM_saddlp, // Signed Integer Vector Add Long Pair +ARM_umaxp, // Unsigned Integer Maximum Pair +ARM_smaxp, // Signed Integer Maximum Pair +ARM_fmaxp, // Floating-point Maximum Pair +ARM_fmaxnmp, // Floating-point maxNum Pair +ARM_uminp, // Unsigned Integer Minimum Pair +ARM_sminp, // Signed Integer Minimum Pair +ARM_fminp, // Floating-point Minimum Pair +ARM_fminnmp, // Floating-point minNum Pair +ARM_sqabs, // Signed Integer Saturating Absolute +ARM_uqadd, // Unsigned Integer Saturating Add +ARM_sqadd, // Signed Integer Saturating Add +ARM_suqadd, // Signed Integer Saturating Accumulate of Unsigned Values +ARM_usqadd, // Unsigned Integer Saturating Accumulate of Signed Values +ARM_sqdmlal, // Signed Integer Saturating Doubling Multiply Add Long +ARM_sqdmlal2, // Signed Integer Saturating Doubling Multiply Add Long (second part) +ARM_sqdmlsl, // Signed Integer Saturating Doubling Multiply Subtract Long +ARM_sqdmlsl2, // Signed Integer Saturating Doubling Multiply Subtract Long (second part) +ARM_sqdmulh, // Signed Integer Saturating Doubling Multiply Returning High Half +ARM_sqdmull, // Signed Integer Saturating Doubling Multiply Long +ARM_sqdmull2, // Signed Integer Saturating Doubling Multiply Long (second part) +ARM_uqxtn, // Unsigned Integer Saturating Vector Narrow +ARM_uqxtn2, // Unsigned Integer Saturating Vector Narrow (second part) +ARM_sqxtn, // Signed Integer Saturating Vector Narrow +ARM_sqxtn2, // Signed Integer Saturating Vector Narrow (second part) +ARM_sqxtun, // Signed Integer Saturating Vector and Unsigned Narrow +ARM_sqxtun2, // Signed Integer Saturating Vector and Unsigned Narrow (second part) +ARM_sqneg, // Signed Integer Saturating Negate +ARM_sqrdmulh, // Signed Integer Saturating Rounding Doubling Multiply Returning High Half +ARM_uqrshl, // Unsigned Integer Saturating Rounding Shift Left +ARM_sqrshl, // Signed Integer Saturating Rounding Shift Left +ARM_uqrshrn, // Unsigned Integer Saturating Rounding Shift Right, Narrow +ARM_uqrshrn2, // Unsigned Integer Saturating Rounding Shift Right, Narrow (second part) +ARM_sqrshrn, // Signed Integer Saturating Rounding Shift Right, Narrow +ARM_sqrshrn2, // Signed Integer Saturating Rounding Shift Right, Narrow (second part) +ARM_sqrshrun, // Signed Integer Saturating Rounding Shift Right, Narrow, Unsigned result +ARM_sqrshrun2, // Signed Integer Saturating Rounding Shift Right, Narrow, Unsigned result (second part) +ARM_uqshl, // Unsigned Integer Saturating Shift Left +ARM_sqshl, // Signed Integer Saturating Shift Left +ARM_sqshlu, // Signed Integer Saturating Shift Left, Unsigned result +ARM_uqshrn, // Unsigned Integer Saturating Shift Right, Narrow +ARM_uqshrn2, // Unsigned Integer Saturating Shift Right, Narrow (second part) +ARM_sqshrn, // Signed Integer Saturating Shift Right, Narrow +ARM_sqshrn2, // Signed Integer Saturating Shift Right, Narrow (second part) +ARM_sqshrun, // Signed Integer Saturating Shift Right, Narrow, Unsigned result +ARM_sqshrun2, // Signed Integer Saturating Shift Right, Narrow, Unsigned result (second part) +ARM_uqsub, // Unsigned Integer Saturating Subtract +ARM_sqsub, // Signed Integer Saturating Subtract +ARM_raddhn, // Integer Rounding Add and Narrow, returning High Half +ARM_raddhn2, // Integer Rounding Add and Narrow, returning High Half (second part) +ARM_urecpe, // Unsigned Integer Reciprocal Estimate +ARM_frecpe, // Floating-point Reciprocal Estimate +ARM_frecps, // Floating-point Reciprocal Step +ARM_frecpx, // Floating-point Reciprocal Exponent +ARM_rev64, // Reverse doublewords +ARM_urhadd, // Unsigned Integer Rounding Halving Add +ARM_srhadd, // Signed Integer Rounding Halving Add +ARM_urshl, // Unsigned Integer Rounding Shift Left +ARM_srshl, // Signed Integer Rounding Shift Left +ARM_urshr, // Unsigned Integer Rounding Shift Right +ARM_srshr, // Signed Integer Rounding Shift Right +ARM_rshrn, // Integer Rounding Shift Right and Narrow +ARM_rshrn2, // Integer Rounding Shift Right and Narrow (second part) +ARM_ursqrte, // Unsigned Integer Reciprocal Square Root Estimate +ARM_frsqrte, // Floating-point Reciprocal Square Root Estimate +ARM_frsqrts, // Floating-point Reciprocal Square Root Step +ARM_ursra, // Unsigned Integer Rounding Shift Right and Accumulate +ARM_srsra, // Signed Integer Rounding Shift Right and Accumulate +ARM_rsubhn, // Integer Subtract and Narrow, returning High Half +ARM_rsubhn2, // Integer Subtract and Narrow, returning High Half (second part) +ARM_ushl, // Unsigned Integer Shift Left +ARM_sshl, // Signed Integer Shift Left +ARM_ushll, // Unsigned Integer Shift Left Long +ARM_ushll2, // Unsigned Integer Shift Left Long (second part) +ARM_sshll, // Signed Integer Shift Left Long +ARM_sshll2, // Signed Integer Shift Left Long (second part) +ARM_ushr, // Unsigned Integer Shift Right +ARM_sshr, // Signed Integer Shift Right +ARM_shrn, // Integer Shift Right Narrow +ARM_shrn2, // Integer Shift Right Narrow (second part) +ARM_shl, // Shift Left +ARM_shll, // Shift Left Long +ARM_shll2, // Shift Left Long (second part) +ARM_sli, // Integer Vector Shift Left and Insert +ARM_fsqrt, // Floating-point Square Root +ARM_usra, // Unsigned Integer Shift Right and Accumulate +ARM_ssra, // Signed Integer Shift Right and Accumulate +ARM_sri, // Integer Shift Right and Insert +ARM_st1, // Vector Store Single Element +ARM_st2, // Vector Store Two-Element Structures +ARM_st3, // Vector Store Three-Element Structures +ARM_st4, // Vector Store Four-Element Structures +ARM_fsub, // Floating-point Subtract +ARM_subhn, // Integer Subtract and Narrow, returning High Half +ARM_subhn2, // Integer Subtract and Narrow, returning High Half (second part) +ARM_usubl, // Unsigned Integer Subtract Long +ARM_usubl2, // Unsigned Integer Subtract Long (second part) +ARM_ssubl, // Signed Integer Subtract Long +ARM_ssubl2, // Signed Integer Subtract Long (second part) +ARM_usubw, // Unsigned Integer Subtract Wide +ARM_usubw2, // Unsigned Integer Subtract Wide (second part) +ARM_ssubw, // Signed Integer Subtract Wide +ARM_ssubw2, // Signed Integer Subtract Wide (second part) +ARM_tbl, // Vector Table Lookup +ARM_tbx, // Vector Table Extension +ARM_trn1, // Vector Element Transpose (primary) +ARM_trn2, // Vector Element Transpose (secondary) +ARM_cmtst, // Integer Compare Mask Bitwise Test +ARM_uzp1, // Vector Element Unzip (primary) +ARM_uzp2, // Vector Element Unzip (secondary) +ARM_zip1, // Vector Element Zip (primary) +ARM_zip2, // Vector Element Zip (secondary) +ARM_addv, // Integer Sum Elements in Vector +ARM_uaddlv, // Unsigned Integer Sum Elements in Vector Long +ARM_saddlv, // Signed Integer Sum Elements in Vector Long +ARM_umaxv, // Unsigned Integer Max Element in Vector +ARM_smaxv, // Signed Integer Max Element in Vector +ARM_fmaxv, // Floating-point Max Element in Vector +ARM_fmaxnmv, // Floating-point maxNum Element in Vector +ARM_uminv, // Unsigned Integer Min Element in Vector +ARM_sminv, // Signed Integer Min Element in Vector +ARM_fminv, // Floating-point Min Element in Vector +ARM_fminnmv, // Floating-point minNum Element in Vector + +// atomic operations (ARMv8.1/ARMv8.3) +// ARM_swp, // Swap value with memory, No memory ordering +ARM_swpl, // Swap value with memory, Release +ARM_swpa, // Swap value with memory, Acquire +ARM_swpal, // Swap value with memory, Acquire and release + +ARM_ldapr, // Load-Acquire RCpc Register + +ARM_ldadd, // Atomic add on value in memory (return initial value), No memory ordering +ARM_ldaddl, // Atomic add on value in memory (return initial value), Release +ARM_ldadda, // Atomic add on value in memory (return initial value), Acquire +ARM_ldaddal, // Atomic add on value in memory (return initial value), Acquire and release +ARM_stadd, // Atomic add on value in memory (no return), No memory ordering +ARM_staddl, // Atomic add on value in memory (no return), Release + +ARM_ldclr, // Atomic bit clear on value in memory (return initial value), No memory ordering +ARM_ldclrl, // Atomic bit clear on value in memory (return initial value), Release +ARM_ldclra, // Atomic bit clear on value in memory (return initial value), Acquire +ARM_ldclral, // Atomic bit clear on value in memory (return initial value), Acquire and release +ARM_stclr, // Atomic bit clear on value in memory (no return), No memory ordering +ARM_stclrl, // Atomic bit clear on value in memory (no return), Release + +ARM_ldeor, // Atomic exclusive OR on value in memory (return initial value), No memory ordering +ARM_ldeorl, // Atomic exclusive OR on value in memory (return initial value), Release +ARM_ldeora, // Atomic exclusive OR on value in memory (return initial value), Acquire +ARM_ldeoral, // Atomic exclusive OR on value in memory (return initial value), Acquire and release +ARM_steor, // Atomic exclusive OR on value in memory (no return), No memory ordering +ARM_steorl, // Atomic exclusive OR on value in memory (no return), Release + +ARM_ldset, // Atomic bit set on value in memory (return initial value), No memory ordering +ARM_ldsetl, // Atomic bit set on value in memory (return initial value), Release +ARM_ldseta, // Atomic bit set on value in memory (return initial value), Acquire +ARM_ldsetal, // Atomic bit set on value in memory (return initial value), Acquire and release +ARM_stset, // Atomic bit set on value in memory (no return), No memory ordering +ARM_stsetl, // Atomic bit set on value in memory (no return), Release + +ARM_ldsmax, // Atomic signed maximum on value in memory (return initial value), No memory ordering +ARM_ldsmaxl, // Atomic signed maximum on value in memory (return initial value), Release +ARM_ldsmaxa, // Atomic signed maximum on value in memory (return initial value), Acquire +ARM_ldsmaxal, // Atomic signed maximum on value in memory (return initial value), Acquire and release +ARM_stsmax, // Atomic signed maximum on value in memory (no return), No memory ordering +ARM_stsmaxl, // Atomic signed maximum on value in memory (no return), Release + + +ARM_ldsmin, // Atomic signed minimum on value in memory (return initial value), No memory ordering +ARM_ldsminl, // Atomic signed minimum on value in memory (return initial value), Release +ARM_ldsmina, // Atomic signed minimum on value in memory (return initial value), Acquire +ARM_ldsminal, // Atomic signed minimum on value in memory (return initial value), Acquire and release +ARM_stsmin, // Atomic signed minimum on value in memory (no return), No memory ordering +ARM_stsminl, // Atomic signed minimum on value in memory (no return), Release + +ARM_ldumax, // Atomic unsigned maximum on value in memory (return initial value), No memory ordering +ARM_ldumaxl, // Atomic unsigned maximum on value in memory (return initial value), Release +ARM_ldumaxa, // Atomic unsigned maximum on value in memory (return initial value), Acquire +ARM_ldumaxal, // Atomic unsigned maximum on value in memory (return initial value), Acquire and release +ARM_stumax, // Atomic unsigned maximum on value in memory (no return), No memory ordering +ARM_stumaxl, // Atomic unsigned maximum on value in memory (no return), Release + + +ARM_ldumin, // Atomic unsigned minimum on value in memory (return initial value), No memory ordering +ARM_lduminl, // Atomic unsigned minimum on value in memory (return initial value), Release +ARM_ldumina, // Atomic unsigned minimum on value in memory (return initial value), Acquire +ARM_lduminal, // Atomic unsigned minimum on value in memory (return initial value), Acquire and release +ARM_stumin, // Atomic unsigned minimum on value in memory (no return), No memory ordering +ARM_stuminl, // Atomic unsigned minimum on value in memory (no return), Release + +// Compare and Swap (ARMv8.1) + +ARM_cas, // Compare and Swap , No memory ordering +ARM_casl, // Compare and Swap, Release +ARM_casa, // Compare and Swap, Acquire +ARM_casal, // Compare and Swap, Acquire and release + +ARM_casp, // Compare and Swap Pair, No memory ordering +ARM_caspl, // Compare and Swap Pair, Release +ARM_caspa, // Compare and Swap Pair, Acquire +ARM_caspal, // Compare and Swap Pair, Acquire and release + +ARM_ldlar, // Load LOAcquire Register +ARM_stllr, // Store LORelease Register + +ARM_sqrdmlah, // Signed Saturating Rounding Doubling Multiply Accumulate +ARM_sqrdmlsh, // Signed Saturating Rounding Doubling Multiply Subtract + +// Pointer authentication (ARMv8.3) +// only completely new instructions are included; +// authenticated variations of old ones are represented by instruction flags (see arm.hpp) + +ARM_pac, // Pointer Authentication Code for Data/Instruction address/generic +ARM_aut, // Authenticate Data/Instruction address +ARM_xpac, // Strip Pointer Authentication Code + +// ARM insns for the legacy assembler (2 operands) +ARM_ldrd2, // Load pair of registers +ARM_strd2, // Store pair of registers + +// CRC32 (optional in 8.0, mandatory since 8.1) +ARM_crc32, // CRC32 using polynomial 0x04C11DB7 +ARM_crc32c, // CRC32 using polynomial 0x1EDC6F41 + +// Armv8-M Security Extension (TrustZone for Armv8-M) +ARM_tt, // Test Target (query the Security state and access permissions of a memory location) +ARM_tta, // Test Target Alternate Domain (query the Security state and access permissions of a memory location for a Non-secure access) +ARM_sg, // Secure Gateway +ARM_vlldm, // Floating-point Lazy Load Multiple +ARM_vlstm, // Floating-point Lazy Store Multiple + +// MP Extension instructions +ARM_pldw, // Preload Data for write + +// ARMv8.1-RDMA (AArh32) +ARM_vqrdmlah, // Vector Saturating Rounding Doubling Multiply Accumulate Returning High Half. +ARM_vqrdmlsh, // Vector Saturating Rounding Doubling Multiply Subtract Returning High Half + +// ARMv8.2-FP16 (AArch32) + +ARM_vmovx, // Vector Move extraction +ARM_vins, // Vector move Insertion. + +// ARMv8.3-JSConv (AArch32) +ARM_vjcvt, // Javascript Convert to signed fixed-point, rounding toward Zero + +// ARMv8.3-JSConv (A64) +ARM_fjcvtzs, // Javascript Convert to signed fixed-point, rounding toward Zero + + +/* +// ARMv8.3-CompNum, SIMD complex number support +ARM_fcadd, // Floating-point complex add +ARM_fcmla, // Floating-point complex multiply accumulate +*/ + +// ARMv8.4-RCPC + +ARM_ldapur, // Load-Acquire RCpc Register (unscaled offset) +ARM_stlur, // Store-Release Register (unscaled offset) + +// ARMv8.4 + +ARM_cfinv, // Invert Carry Flag +ARM_rmif, // Rotate value and mask into flags +ARM_setf8, // set flags from value (8-bit) +ARM_setf16, // set flags from value (16-bit) +ARM_xaflag, // Convert floating-point condition flags to ARM format +ARM_axflag, // Convert floating-point condition flags from ARM to external format. + +// ARMv8.5 +ARM_addg, // Add with Tag +ARM_subg, // Subtract with Tag +ARM_subp, // Subtract Pointer +ARM_cmpp, // Compare with Tag +ARM_irg, // Insert Random Tag +ARM_gmi, // Tag Mask Insert +ARM_stg, // Store Allocation Tag +ARM_stzg, // Store Allocation Tag, Zeroing +ARM_stzgm, // Store Tag and Zero Multiple +ARM_st2g, // Store Allocation Tags +ARM_stz2g, // Store Allocation Tags, Zeroing +ARM_stgm, // Store Tag Multiple +ARM_stgp, // Store Allocation Tag and Pair of registers +ARM_ldg, // Load Allocation Tag +ARM_ldgm, // Load Tag Multiple +ARM_bti, // Branch Target Identification +ARM_sb, // Speculation Barrier +ARM_ssbb, // Speculative Store Bypass Barrier +ARM_pssbb, // Physical Speculative Store Bypass Barrier + + + + + + + +ARM_last + + }; + + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * TMS320C6xx - VLIW (very long instruction word) architecture + * + */ + + + +enum +{ +// Original TMS320C62x instructions + +TMS6_null = 0, // Unknown Operation +TMS6_abs, // Absolute value +TMS6_add, // Integer addition without saturation (signed) +TMS6_addu, // Integer addition without saturation (unsigned) +TMS6_addab, // Integer addition using addressing mode (byte) +TMS6_addah, // Integer addition using addressing mode (halfword) +TMS6_addaw, // Integer addition using addressing mode (word) +TMS6_addk, // Integer addition 16bit signed constant +TMS6_add2, // Two 16bit Integer adds on register halves +TMS6_and, // Logical AND +TMS6_b, // Branch +TMS6_clr, // Clear a bit field +TMS6_cmpeq, // Compare for equality +TMS6_cmpgt, // Compare for greater than (signed) +TMS6_cmpgtu, // Compare for greater than (unsigned) +TMS6_cmplt, // Compare for less than (signed) +TMS6_cmpltu, // Compare for less than (unsigned) +TMS6_ext, // Extract and sign-extend a bit filed +TMS6_extu, // Extract an unsigned bit field +TMS6_idle, // Multicycle NOP with no termination until interrupt +TMS6_ldb, // Load from memory (signed 8bit) +TMS6_ldbu, // Load from memory (unsigned 8bit) +TMS6_ldh, // Load from memory (signed 16bit) +TMS6_ldhu, // Load from memory (unsigned 16bit) +TMS6_ldw, // Load from memory (32bit) +TMS6_lmbd, // Leftmost bit detection +TMS6_mpy, // Signed Integer Multiply (LSB16 x LSB16) +TMS6_mpyu, // Unsigned Integer Multiply (LSB16 x LSB16) +TMS6_mpyus, // Integer Multiply Signed*Unsigned (LSB16 x LSB16) +TMS6_mpysu, // Integer Multiply Unsigned*Signed (LSB16 x LSB16) +TMS6_mpyh, // Signed Integer Multiply (MSB16 x MSB16) +TMS6_mpyhu, // Unsigned Integer Multiply (MSB16 x MSB16) +TMS6_mpyhus, // Integer Multiply Unsigned*Signed (MSB16 x MSB16) +TMS6_mpyhsu, // Integer Multiply Signed*Unsigned (MSB16 x MSB16) +TMS6_mpyhl, // Signed Integer Multiply (MSB16 x LSB16) +TMS6_mpyhlu, // Unsigned Integer Multiply (MSB16 x LSB16) +TMS6_mpyhuls, // Integer Multiply Signed*Unsigned (MSB16 x LSB16) +TMS6_mpyhslu, // Integer Multiply Unsigned*Signed (MSB16 x LSB16) +TMS6_mpylh, // Signed Integer Multiply (LSB16 x MB16) +TMS6_mpylhu, // Unsigned Integer Multiply (LSB16 x MSB16) +TMS6_mpyluhs, // Integer Multiply Signed*Unsigned (LSB16 x MSB16) +TMS6_mpylshu, // Integer Multiply Unsigned*Signed (LSB16 x MSB16) +TMS6_mv, // Move from register to register +TMS6_mvc, // Move between the control file & register file +TMS6_mvk, // Move a 16bit signed constant into register +TMS6_mvkh, // Move a 16bit constant into the upper bits of a register +TMS6_mvklh, // Move a 16bit constant into the upper bits of a register +TMS6_neg, // Negate +TMS6_nop, // No operation +TMS6_norm, // Normalize +TMS6_not, // Bitwise NOT +TMS6_or, // Logical or +TMS6_sadd, // Integer addition with saturation +TMS6_sat, // Saturate 40bit value to 32bits +TMS6_set, // Set a bit field +TMS6_shl, // Arithmetic shift left +TMS6_shr, // Arithmetic shift right +TMS6_shru, // Logical shift left +TMS6_smpy, // Integer multiply with left shift & saturation (LSB16*LSB16) +TMS6_smpyhl, // Integer multiply with left shift & saturation (MSB16*LSB16) +TMS6_smpylh, // Integer multiply with left shift & saturation (LSB16*MSB16) +TMS6_smpyh, // Integer multiply with left shift & saturation (MSB16*MSB16) +TMS6_sshl, // Shift left with saturation +TMS6_ssub, // Integer substraction with saturation +TMS6_stb, // Store to memory (signed 8bit) +TMS6_stbu, // Store to memory (unsigned 8bit) +TMS6_sth, // Store to memory (signed 16bit) +TMS6_sthu, // Store to memory (unsigned 16bit) +TMS6_stw, // Store to memory (32bit) +TMS6_sub, // Integer substaraction without saturation (signed) +TMS6_subu, // Integer substaraction without saturation (unsigned) +TMS6_subab, // Integer subtraction using addressing mode (byte) +TMS6_subah, // Integer subtraction using addressing mode (halfword) +TMS6_subaw, // Integer subtraction using addressing mode (word) +TMS6_subc, // Conditional subtract & shift (for division) +TMS6_sub2, // Two 16bit integer subtractions on register halves +TMS6_xor, // Exclusive OR +TMS6_zero, // Zero a register + +// New TMS320C674x instructions + +TMS6_abs2, // Absolute Value With Saturation, Signed, Packed 16-bit +TMS6_absdp, // Absolute Value, Double-Precision Floating-Point +TMS6_abssp, // Absolute Value, Single-Precision Floating-Point +TMS6_add4, // Add Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_addad, // Add Using Doubleword Addressing Mode +TMS6_adddp, // Add Two Double-Precision Floating-Point Values +TMS6_addkpc, // Add Signed 7-bit Constant to Program Counter +TMS6_addsp, // Add Two Single-Precision Floating-Point Values +TMS6_addsub, // Parallel ADD and SUB Operations On Common Inputs +TMS6_addsub2, // Parallel ADD2 and SUB2 Operations On Common Inputs +TMS6_andn, // Bitwise AND Invert +TMS6_avg2, // Average, Signed, Packed 16-bit +TMS6_avgu4, // Average, Unsigned, Packed 16-bit +TMS6_bdec, // Branch and Decrement +TMS6_bitc4, // Bit Count, Packed 8-bit +TMS6_bitr, // Bit Reverse +TMS6_bnop, // Branch With NOP +TMS6_bpos, // Branch Positive +TMS6_callp, // Call Using a Displacement +TMS6_cmpeq2, // Compare for Equality, Packed 16-bit +TMS6_cmpeq4, // Compare for Equality, Packed 8-bit +TMS6_cmpeqdp, // Compare for Equality, Double-Precision Floating-Point Values +TMS6_cmpeqsp, // Compare for Equality, Single-Precision Floating-Point Values +TMS6_cmpgt2, // Compare for Greater Than, Packed 16-bit +TMS6_cmpgtdp, // Compare for Greater Than, Double-Precision Floating-Point Values +TMS6_cmpgtsp, // Compare for Greater Than, Single-Precision Floating-Point Values +TMS6_cmpgtu4, // Compare for Greater Than, Unsigned, Packed 8-bit +TMS6_cmplt2, // Compare for Less Than, Packed 16-bit +TMS6_cmpltdp, // Compare for Less Than, Double-Precision Floating-Point Values +TMS6_cmpltsp, // Compare for Less Than, Single-Precision Floating-Point Values +TMS6_cmpltu4, // Compare for Less Than, Unsigned, Packed 8-bit +TMS6_cmpy, // Complex Multiply Two Pairs, Signed, Packed 16-bit +TMS6_cmpyr, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding +TMS6_cmpyr1, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding +TMS6_ddotp4, // Double Dot Product, Signed, Packed 16-Bit and Signed, Packed 8-Bit +TMS6_ddotph2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit +TMS6_ddotph2r, // Double Dot Product With Rounding, Two Pairs, Signed, Packed 16-Bit +TMS6_ddotpl2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit +TMS6_ddotpl2r, // Double Dot Product With Rounding, Two Pairs, Signed Packed 16-Bit +TMS6_deal, // Deinterleave and Pack +TMS6_dint, // Disable Interrupts and Save Previous Enable State +TMS6_dmv, // Move Two Independent Registers to Register Pair +TMS6_dotp2, // Dot Product, Signed, Packed 16-Bit +TMS6_dotpn2, // Dot Product With Negate, Signed, Packed 16-Bit +TMS6_dotpnrsu2, // Dot Product With Negate, Shift and Round, Signed by Unsigned, Packed 16-Bit +TMS6_dotpnrus2, // Dot Product With Negate, Shift and Round, Unsigned by Signed, Packed 16-Bit +TMS6_dotprsu2, // Dot Product With Shift and Round, Signed by Unsigned, Packed 16-Bit +TMS6_dotprus2, // Dot Product With Shift and Round, Unsigned by Signed, Packed 16-Bit +TMS6_dotpsu4, // Dot Product, Signed by Unsigned, Packed 8-Bit +TMS6_dotpu4, // Dot Product, Unsigned, Packed 8-Bit +TMS6_dotpus4, // Dot Product, Unsigned by Signed, Packed 8-Bit +TMS6_dpack2, // Parallel PACK2 and PACKH2 Operations +TMS6_dpackx2, // Parallel PACKLH2 Operations +TMS6_dpint, // Convert Double-Precision Floating-Point Value to Integer +TMS6_dpsp, // Convert Double-Precision Floating-Point Value to Single-Precision Floating-Point Value +TMS6_dptrunc, // Convert Double-Precision Floating-Point Value to Integer With Truncation +TMS6_gmpy, // Galois Field Multiply +TMS6_gmpy4, // Galois Field Multiply, Packed 8-Bit +TMS6_intdp, // Convert Signed Integer to Double-Precision Floating-Point Value +TMS6_intdpu, // Convert Unsigned Integer to Double-Precision Floating-Point Value +TMS6_intsp, // Convert Signed Integer to Single-Precision Floating-Point Value +TMS6_intspu, // Convert Unsigned Integer to Single-Precision Floating-Point Value +TMS6_lddw, // Load Doubleword From Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_ldndw, // Load Nonaligned Doubleword From Memory With Constant or Register Offset +TMS6_ldnw, // Load Nonaligned Word From Memory With Constant or Register Offset +TMS6_max2, // Maximum, Signed, Packed 16-Bit +TMS6_maxu4, // Maximum, Unsigned, Packed 8-Bit +TMS6_min2, // Minimum, Signed, Packed 16-Bit +TMS6_minu4, // Minimum, Unsigned, Packed 8-Bit +TMS6_mpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB +TMS6_mpy2ir, // Multiply Two 16-Bit x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 32-Bit Result +TMS6_mpy32su, // Multiply Signed 32-Bit x Unsigned 32-Bit Into Signed 64-Bit Result +TMS6_mpy32u, // Multiply Unsigned 32-Bit x Unsigned 32-Bit Into Unsigned 64-Bit Result +TMS6_mpy32us, // Multiply Unsigned 32-Bit x Signed 32-Bit Into Signed 64-Bit Result +TMS6_mpydp, // Multiply Two Double-Precision Floating-Point Values +TMS6_mpyhi, // Multiply 16 MSB x 32-Bit Into 64-Bit Result +TMS6_mpyhir, // Multiply 16 MSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpyi, // Multiply 32-Bit x 32-Bit Into 32-Bit Result +TMS6_mpyid, // Multiply 32-Bit x 32-Bit Into 64-Bit Result +TMS6_mpyih, // Multiply 32-Bit x 16-MSB Into 64-Bit Result +TMS6_mpyihr, // Multiply 32-Bit x 16 MSB, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpyil, // Multiply 32-Bit x 16 LSB Into 64-Bit Result +TMS6_mpyilr, // Multiply 32-Bit x 16 LSB, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpyli, // Multiply 16 LSB x 32-Bit Into 64-Bit Result +TMS6_mpylir, // Multiply 16 LSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpysp, // Multiply Two Single-Precision Floating-Point Values +TMS6_mpysp2dp, // Multiply Two Single-Precision Floating-Point Values for Double-Precision Result +TMS6_mpyspdp, // Multiply Single-Precision Floating-Point Value x Double-Precision Floating-Point Value +TMS6_mpysu4, // Multiply Signed x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_mpyu4, // Multiply Unsigned x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_mpyus4, // Multiply Unsigned x Signed, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_mvd, // Move From Register to Register, Delayed +TMS6_mvkl, // Move Signed Constant Into Register and Sign Extend +TMS6_pack2, // Pack Two 16 LSBs Into Upper and Lower Register Halves +TMS6_packh2, // Pack Two 16 MSBs Into Upper and Lower Register Halves +TMS6_packh4, // Pack Four High Bytes Into Four 8-Bit Halfwords +TMS6_packhl2, // Pack 16 MSB Into Upper and 16 LSB Into Lower Register Halves +TMS6_packl4, // Pack Four Low Bytes Into Four 8-Bit Halfwords +TMS6_packlh2, // Pack 16 LSB Into Upper and 16 MSB Into Lower Register Halves +TMS6_rcpdp, // Double-Precision Floating-Point Reciprocal Approximation +TMS6_rcpsp, // Single-Precision Floating-Point Reciprocal Approximation +TMS6_rint, // Restore Previous Enable State +TMS6_rotl, // Rotate Left +TMS6_rpack2, // Shift With Saturation and Pack Two 16 MSBs Into Upper and Lower Register Halves +TMS6_rsqrdp, // Double-Precision Floating-Point Square-Root Reciprocal Approximation +TMS6_rsqrsp, // Single-Precision Floating-Point Square-Root Reciprocal Approximation +TMS6_sadd2, // Add Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation +TMS6_saddsu2, // Add Two Signed and Unsigned 16-Bit Integers on Register Halves With Saturation +TMS6_saddsub, // Parallel SADD and SSUB Operations On Common Inputs +TMS6_saddsub2, // Parallel SADD2 and SSUB2 Operations On Common Inputs +TMS6_saddu4, // Add With Saturation, Four Unsigned 8-Bit Pairs for Four 8-Bit Results +TMS6_saddus2, // Add Two Unsigned and Signed 16-Bit Integers on Register Halves With Saturation +TMS6_shfl, // Shuffle +TMS6_shfl3, // 3-Way Bit Interleave On Three 16-Bit Values Into a 48-Bit Result +TMS6_shlmb, // Shift Left and Merge Byte +TMS6_shr2, // Arithmetic Shift Right, Signed, Packed 16-Bit +TMS6_shrmb, // Shift Right and Merge Byte +TMS6_shru2, // Arithmetic Shift Right, Unsigned, Packed 16-Bit +TMS6_smpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB With Left Shift and Saturation +TMS6_smpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 64-Bit Result With Left Shift and Saturation +TMS6_spack2, // Saturate and Pack Two 16 LSBs Into Upper and Lower Register Halves +TMS6_spacku4, // Saturate and Pack Four Signed 16-Bit Integers Into Four Unsigned 8-Bit Halfwords +TMS6_spdp, // Convert Single-Precision Floating-Point Value to Double-Precision Floating-Point Value +TMS6_spint, // Convert Single-Precision Floating-Point Value to Integer +TMS6_spkernel, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary +TMS6_spkernelr, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary +TMS6_sploop, // Software Pipelined Loop (SPLOOP) Buffer Operation +TMS6_sploopd, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing +TMS6_sploopw, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing and No Epilog +TMS6_spmask, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control +TMS6_spmaskr, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control +TMS6_sptrunc, // Convert Single-Precision Floating-Point Value to Integer With Truncation +TMS6_sshvl, // Variable Shift Left +TMS6_sshvr, // Variable Shift Right +TMS6_ssub2, // Subtract Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation +TMS6_stdw, // Store Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_stndw, // Store Nonaligned Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_stnw, // Store Nonaligned Word to Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_sub4, // Subtract Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_subabs4, // Subtract With Absolute Value, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_subdp, // Subtract Two Double-Precision Floating-Point Values +TMS6_subsp, // Subtract Two Single-Precision Floating-Point Values +TMS6_swap2, // Swap Bytes in Upper and Lower Register Halves +TMS6_swap4, // Swap Byte Pairs in Upper and Lower Register Halves +TMS6_swe, // Software Exception +TMS6_swenr, // Software Exception, no Return +TMS6_unpkhu4, // Unpack 16 MSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves +TMS6_unpklu4, // Unpack 16 LSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves +TMS6_xormpy, // Galois Field Multiply With Zero Polynomial +TMS6_xpnd2, // Expand Bits to Packed 16-Bit Masks +TMS6_xpnd4, // Expand Bits to Packed 8-Bit Masks + +TMS6_last, + + }; + +/* + * Interactive disassembler (IDA). + * Intel 80196 module + * + */ + + + +enum +{ + I196_null = 0, // Unknown Operation + + I196_add2, // Add words (2 operands) + I196_add3, // Add words (3 operands) + I196_addb2, // Add bytes (2 operands) + I196_addb3, // Add bytes (3 operands) + + I196_addc, // Add words with carry + I196_addcb, // Add bytes with carry + + I196_and2, // Logical AND words (2 operands) + I196_and3, // Logical AND words (3 operands) + I196_andb2, // Logical AND bytes (2 operands) + I196_andb3, // Logical AND bytes (3 operands) + + I196_bmov, // Block move + I196_bmovi, // Interruptable block move + + I196_br, // Branch indirect + + I196_clr, // Clear word + I196_clrb, // Clear byte + I196_clrc, // Clear carry flag + I196_clrvt, // Clear overflow-trap flag + + I196_cmp, // Compare words + I196_cmpb, // Compare bytes + I196_cmpl, // Compare long + + I196_dec, // Decrement word + I196_decb, // Decrement byte + + I196_di, // Disable interrupts + + I196_div, // Divide integers + I196_divb, // Divide short-integers + I196_divu, // Divide words, unsigned + I196_divub, // Divide bytes, unsigned + + I196_djnz, // Decrement and jump if not zero + I196_djnzw, // Decrement and jump if not zero word + + I196_dpts, // Disable peripheral transaction server + + I196_ei, // Enable interrupts + + I196_epts, // Enable peripheral transaction server + + I196_ext, // Sign-extend integer into long-integer + I196_extb, // Sign-extend short-integer into integer + + I196_idlpd, // Idle/powerdown + + I196_inc, // Increment word + I196_incb, // Increment byte + + I196_jbc, // Jump if bit is clear + I196_jbs, // Jump if bit is set + I196_jc, // Jump if carry flag is set + I196_je, // Jump if equal + I196_jge, // Jump if signed greater than or equal + I196_jgt, // Jump if signed greater than + I196_jh, // Jump if higher (unsigned) + I196_jle, // Jump if signed less than or equal + I196_jlt, // Jump if signed less than + I196_jnc, // Jump if carry flag is clear + I196_jne, // Jump if not equal + I196_jnh, // Jump if not higher (unsigned) + I196_jnst, // Jump if sticky bit flag is clear + I196_jnv, // Jump if overflow flag is clear + I196_jnvt, // Jump if overflow-trap flag is clear + I196_jst, // Jump if sticky bit flag is set + I196_jv, // Jump if overflow flag is set + I196_jvt, // Jump if overflow-trap flag is set + + I196_lcall, // Long call + + I196_ld, // Load word + I196_ldb, // Load byte + I196_ldbse, // Load byte sign-extended + I196_ldbze, // Load byte zero-extended + + I196_ljmp, // Long jump + + I196_mul2, // Multiply integers (2 operands) + I196_mul3, // Multiply integers (3 operands) + I196_mulb2, // Multiply short-integers (2 operands) + I196_mulb3, // Multiply short-integers (3 operands) + I196_mulu2, // Multiply words, unsigned (2 operands) + I196_mulu3, // Multiply words, unsigned (3 operands) + I196_mulub2, // Multiply bytes, unsigned (2 operands) + I196_mulub3, // Multiply bytes, unsigned (3 operands) + + I196_neg, // Negate integer + I196_negb, // Negate short-integer + + I196_nop, // No operation + + I196_norml, // Normalize long-integer + + I196_not, // Complement word + I196_notb, // Complement byte + + I196_or, // Logical OR words + I196_orb, // Logical OR bytes + + I196_pop, // Pop word + I196_popa, // Pop all + I196_popf, // Pop flags + I196_push, // Push word + I196_pusha, // Push all + I196_pushf, // Push flags + + I196_ret, // Return from subroutine + + I196_rst, // Reset system + + I196_scall, // Short call + + I196_setc, // Set carry flag + + I196_shl, // Shift word left + I196_shlb, // Shift byte left + I196_shll, // Shift double-word left + I196_shr, // Logical right shift word + I196_shra, // Arithmetic right shift word + I196_shrab, // Arithmetic right shift byte + I196_shral, // Arithmetic right shift double-word + I196_shrb, // Logical right shift byte + I196_shrl, // Logical right shift double-word + + I196_sjmp, // Short jump + + I196_skip, // Two byte no-operation + + I196_st, // Store word + I196_stb, // Store byte + + I196_sub2, // Subtract words (2 operands) + I196_sub3, // Subtract words (3 operands) + I196_subb2, // Subtract bytes (2 operands) + I196_subb3, // subtract bytes (3 operands) + + I196_subc, // Subtract words with borrow + I196_subcb, // Subtract bytes with borrow + + I196_tijmp, // Table indirect jump + + I196_trap, // Software trap + + I196_xch, // Exchange word + I196_xchb, // Exchange byte + + I196_xor, // Logical exclusive-or words + I196_xorb, // Logical exclusive-or bytes + +// 8x196NU, NP instructions + + I196_ebmovi, // Extended interruptable block move + I196_ebr, // Extended branch indirect + I196_ecall, // Extended call + I196_ejmp, // Extended jump + I196_eld, // Extended load word + I196_eldb, // Extended load byte + I196_est, // Extended store word + I196_estb, // Extended store byte + + I196_last +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Renesas SuperH - RISC with 16bit instructions + * + */ + + + + +enum +{ +SH3_null = 0, // Unknown Operation + +SH3_add, // Add binary +SH3_addc, // Add with Carry +SH3_addv, // Add with V Flag Overflow Check +SH3_and, // AND Logical +SH3_and_b, // AND Byte Logical +SH3_bf, // Branch if False +SH3_bf_s, // Branch of False with Delay Slot +SH3_bra, // Branch +SH3_braf, // Branch Far +SH3_bsr, // Branch to Subroutine +SH3_bsrf, // Branch to Subroutine Far +SH3_bt, // Branch if True +SH3_bt_s, // Branch if True with Delay Slot +SH3_clrmac, // Clear MAC register +SH3_clrs, // Clear S Bit +SH3_clrt, // Clear T Bit +SH3_cmp_eq, // Compare: Equal +SH3_cmp_ge, // Compare: Signed Greater or Equal +SH3_cmp_gt, // Compare: Signed Greater +SH3_cmp_hi, // Compare: Unsigned Greater +SH3_cmp_hs, // Compare: Unsigned Greater or Equal +SH3_cmp_pl, // Compare: Positive +SH3_cmp_pz, // Compare: Positive or Zero +SH3_cmp_str, // Compare: Equal Bytes +SH3_div0s, // Divide Step 0 as Signed +SH3_div0u, // Divide Step 0 as Unsigned +SH3_div1, // Divide Step 1 +SH3_dmuls_l, // Double-Length Multiply as Signed +SH3_dmulu_l, // Double-Length Multiply as Unsigned +SH3_dt, // Decrement and Test +SH3_exts_b, // Extend as Signed (Byte) +SH3_exts_w, // Extend as Signed (Word) +SH3_extu_b, // Extend as Unsigned (Byte) +SH3_extu_w, // Extend as Unsigned (Word) +SH3_jmp, // Jump +SH3_jsr, // Jump to Subroutine +SH3_ldc, // Load to Control Register +SH3_ldc_l, // Load to Control Register Long +SH3_lds, // Load to System Register +SH3_lds_l, // Load to System Register Long +SH3_ldtlb, // Load PTEH/PTEL/PTEA to TLB +SH3_mac_w, // Multiply and Accumulate Word +SH3_mac_l, // Multiply and Accumulate Long +SH3_mov, // Move Data +SH3_mov_b, // Move Byte Data +SH3_mov_w, // Move Word Data +SH3_mov_l, // Move Long Data +SH3_movi, // Move Immediate Byte Data +SH3_movi_w, // Move Immediate Word Data +SH3_movi_l, // Move Immediate Long Data +SH3_movp_b, // Move Peripherial Byte Data +SH3_movp_w, // Move Peripherial Word Data +SH3_movp_l, // Move Peripherial Long Data +SH3_movs_b, // Move Structure Byte Data +SH3_movs_w, // Move Structure Word Data +SH3_movs_l, // Move Structure Long Data +SH3_mova, // Move Effective Address +SH3_movt, // Move T Bit +SH3_mul, // Multiply Long +SH3_muls, // Multiply as Signed Word +SH3_mulu, // Multiply as Unsigned Word +SH3_neg, // Negate +SH3_negc, // Negate with Carry +SH3_nop, // No Operation +SH3_not, // NOT - Logical Complement +SH3_or, // OR Logical +SH3_or_b, // OR Byte Logical +SH3_pref, // Prefetch Data to the Cache +SH3_rotcl, // Rotate with Carry Left +SH3_rotcr, // Rotate with Carry Right +SH3_rotl, // Rotate Left +SH3_rotr, // Rotate Right +SH3_rte, // Return from Exception +SH3_rts, // Return from Subroutine +SH3_sets, // Set S Bit +SH3_sett, // Set T Bit +SH3_shad, // Shift Arithmetic Dynamically +SH3_shal, // Shift Arithmetic Left +SH3_shar, // Shift Arithmetic Right +SH3_shld, // Shift Logical Dynamically +SH3_shll, // Shift Logical Left +SH3_shll2, // Shift Logical Left 2 +SH3_shll8, // Shift Logical Left 8 +SH3_shll16, // Shift Logical Left 16 +SH3_shlr, // Shift Logical Right +SH3_shlr2, // Shift Logical Right 2 +SH3_shlr8, // Shift Logical Right 8 +SH3_shlr16, // Shift Logical Right 16 +SH3_sleep, // Sleep +SH3_stc, // Store Control Register +SH3_stc_l, // Store Control Register Long +SH3_sts, // Store System Register +SH3_sts_l, // Store System Register Long +SH3_sub, // Subtract Binary +SH3_subc, // Subtract with Carry +SH3_subv, // Subtract with V Flag Underflow Check +SH3_swap_b, // Swap Register Halves (Byte) +SH3_swap_w, // Swap Register Halves (Word) +SH3_tas_b, // Test and Set +SH3_trapa, // Trap Always +SH3_tst, // Test Logical +SH3_tst_b, // Test Byte Logical +SH3_xor, // Exclusive OR Logical +SH3_xor_b, // Exclusive OR Byte Logical +SH3_xtrct, // Extract + +SH4_fabs, // Floating-point absolute value +SH4_fadd, // Floating-point add +SH4_fcmp_eq, // Floating-point compare eqaul +SH4_fcmp_gt, // Floating-point compare greater than +SH4_fcnvds, // Floating-point convert double to single precision +SH4_fcnvsd, // Floating-point convert single to double precision +SH4_fdiv, // Floating-point divide +SH4_fipr, // Floating-point inner product +SH4_fldi0, // Floating-point Load Immediate 0.0 +SH4_fldi1, // Floating-point Load Immediate 1.0 +SH4_flds, // Floating-point Load to system register +SH4_float, // Floating-point convert from integer +SH4_fmac, // Floating-point multiply and accumulate +SH4_fmov, // Floating-point move +SH4_fmov_s, // Floating-point move single precision +SH4_fmovex, // Floating-point move extension +SH4_fmul, // Floating-point multiply +SH4_fneg, // Floating-Point sign inversion +SH4_frchg, // FR-bit change +SH4_fschg, // SZ-bit change +SH4_fsqrt, // Floating-point square root +SH4_fsts, // Floating-point store system register +SH4_fsub, // Floating-point subtract +SH4_ftrc, // Floating-point truncate and convert to integer +SH4_ftrv, // Floating-point transform vector +SH4_ftstn, // Floating point square root reciprocal approximate +SH4_movca_l, // Move with cache block allocation +SH4_ocbi, // Operand Cache Block Invalidate +SH4_ocbp, // Operand Cache Block Purge +SH4_ocbwb, // Operand Cache Block Write Back +SH4_fsca, // Floating point sine and cosine approximate + +// SH-2a new instructions + +SH2a_band_b, // Bit And Byte Data +SH2a_bandnot_b, // Bit And Not Byte Data +SH2a_bclr, // Bit Clear +SH2a_bclr_b, // Bit Clear Byte Data +SH2a_bld, // Bit Load +SH2a_bld_b, // Bit Load Byte Data +SH2a_bldnot_b, // Bit Load Not Byte Data +SH2a_bor_b, // Bit Or Byte Data +SH2a_bornot_b, // Bit Or Not Byte Data +SH2a_bset, // Bit Set +SH2a_bset_b, // Bit Set Byte Data +SH2a_bst, // Bit Store +SH2a_bst_b, // Bit Store Byte Data +SH2a_bxor_b, // Bit Exclusive Or Byte Data +SH2a_clips_b, // Clip as Signed Byte +SH2a_clips_w, // Clip as Signed Word +SH2a_clipu_b, // Clip as Unsigned Byte +SH2a_clipu_w, // Clip as Unsigned Word +SH2a_divs, // Divide as Signed +SH2a_divu, // Divide as Unsigned +SH2a_jsr_n, // Jump to Subroutine with No delay slot +SH2a_ldbank, // Load Register Bank +SH2a_movi20, // 20-bit immediate data transfer +SH2a_movi20s, // 20-bit immediate data transfer, 8-bit left-shift +SH2a_movml_l, // Move Multi-register Lower part +SH2a_movmu_l, // Move Multi-register Upper part +SH2a_movrt, // Move Reverse T bit +SH2a_movu_b, // Move Structure Byte Data as Unsigned +SH2a_movu_w, // Move Structure Word Data as Unsigned +SH2a_mulr, // Multiply to Register +SH2a_nott, // Not T bit +SH2a_resbank, // Restore From Register Bank +SH2a_rts_n, // Return from Subroutine with No delay slot +SH2a_rtv_n, // Return to Value and from Subroutine with No delay slot +SH2a_stbank, // Store Register Bank + +// SH-4a new instructions + +SH4a_movco_l, // Move Conditional +SH4a_movli_l, // Move Linked +SH4a_movua_l, // Move Unaligned +SH4a_icbi, // Instruction Cache Block Invalidate +SH4a_prefi, // Prefetch Instruction Cache Block +SH4a_synco, // Synchronize Data Operation +SH4a_fsrra, // Floating Point Square Reciprocal Approximate +SH4a_fpchg, // PR-bit Change + +SH4_last, + + }; + +/* + * Interactive disassembler (IDA). + * Zilog Z8 module + * + */ + + + +enum +{ + Z8_null = 0, // Unknown Operation + + Z8_adc, // Add with carry + Z8_add, // Add + Z8_and, // Logical AND + Z8_call, // Call procedure + Z8_ccf, // Complement carry flag + Z8_clr, // Clear + Z8_com, // Complement + Z8_cp, // Compare + Z8_da, // Decimal adjust + Z8_dec, // Decrement + Z8_decw, // Decrement word + Z8_di, // Disable interrupts + Z8_djnz, // Decrement and jump if non-zero + Z8_ei, // Enable interrupts + Z8_halt, // Enter HALT mode + Z8_inc, // Increment + Z8_incw, // Increment word + Z8_iret, // Return from interrupt + Z8_jp, // Unconditional jump + Z8_jpcond, // Conditional jump + Z8_jr, // Relative jump + Z8_jrcond, // Conditional relative jump + Z8_ld, // Load data + Z8_ldc, // Load constant + Z8_ldci, // Load constant with auto-increment + Z8_lde, // Load external data + Z8_ldei, // Load external data with auto-increment + Z8_nop, // NOP + Z8_or, // Logical OR + Z8_pop, // Pop + Z8_push, // Push + Z8_rcf, // Reset carry flag + Z8_ret, // Return + Z8_rl, // Rotate left + Z8_rlc, // Rotate left through carry + Z8_rr, // Rotate right + Z8_rrc, // Rotate right through carry + Z8_sbc, // Subtract with carry + Z8_scf, // Set carry flag + Z8_sra, // Shift right arithmetic + Z8_srp, // Set register pointer + Z8_stop, // Enter STOP mode + Z8_sub, // Subtract + Z8_swap, // Swap nibbles + Z8_tm, // Test under mask + Z8_tcm, // Test complement under mask + Z8_xor, // Logical EXCLUSIVE OR + Z8_wdh, // Enable WATCH-DOG in HALT mode + Z8_wdt, // Clear WATCH-DOG timer + + Z8_last +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Atmel AVR - 8-bit RISC processor + * + */ + + + +enum +{ + +AVR_null = 0, // Unknown Operation + +// ARITHMETIC AND LOGIC INSTRUCTIONS +AVR_add, // Add without Carry +AVR_adc, // Add with Carry +AVR_adiw, // Add Immediate to Word +AVR_sub, // Subtract without Carry +AVR_subi, // Subtract Immediate +AVR_sbc, // Subtract with Carry +AVR_sbci, // Subtract Immediate with Carry +AVR_sbiw, // Subtract Immediate from Word +AVR_and, // Logical AND +AVR_andi, // Logical AND with Immediate +AVR_or, // Logical OR +AVR_ori, // Logical OR with Immediate +AVR_eor, // Exclusive OR +AVR_com, // One's Complement +AVR_neg, // Two's Complement +AVR_sbr, // Set Bit(s) in Register +AVR_cbr, // Clear Bit(s) in Register +AVR_inc, // Increment +AVR_dec, // Decrement +AVR_tst, // Test for Zero or Minus +AVR_clr, // Clear Register +AVR_ser, // Set Register +AVR_cp, // Compare +AVR_cpc, // Compare with Carry +AVR_cpi, // Compare with Immediate +AVR_mul, // Multiply + +// BRANCH INSTRUCTIONS +AVR_rjmp, // Relative Jump +AVR_ijmp, // Indirect Jump to (Z) +AVR_jmp, // Jump +AVR_rcall, // Relative Call Subroutine +AVR_icall, // Indirect Call to (Z) +AVR_call, // Call Subroutine +AVR_ret, // Subroutine Return +AVR_reti, // Interrupt Return +AVR_cpse, // Compare, Skip if Equal +AVR_sbrc, // Skip if Bit in Register Cleared +AVR_sbrs, // Skip if Bit in Register Set +AVR_sbic, // Skip if Bit in I/O Register Cleared +AVR_sbis, // Skip if Bit in I/O Register Set +AVR_brbs, // Branch if Status Flag Set +AVR_brbc, // Branch if Status Flag Cleared +AVR_breq, // Branch if Equal +AVR_brne, // Branch if Not Equal +AVR_brcs, // Branch if Carry Set +AVR_brcc, // Branch if Carry Cleared +AVR_brsh, // Branch if Same or Higher +AVR_brlo, // Branch if Lower +AVR_brmi, // Branch if Minus +AVR_brpl, // Branch if Plus +AVR_brge, // Branch if Greater or Equal +AVR_brlt, // Branch if Less Than +AVR_brhs, // Branch if Half Carry Flag Set +AVR_brhc, // Branch if Half Carry Flag Cleared +AVR_brts, // Branch if T Flag Set +AVR_brtc, // Branch if T Flag Cleared +AVR_brvs, // Branch if Overflow Flag is Set +AVR_brvc, // Branch if Overflow Flag is Cleared +AVR_brie, // Branch if Interrupt Enabled +AVR_brid, // Branch if Interrupt Disabled + +// DATA TRANSFER INSTRUCTIONS +AVR_mov, // Copy Register +AVR_ldi, // Load Immediate +AVR_lds, // Load Direct +AVR_ld, // Load Indirect +AVR_ldd, // Load Indirect with Displacement +AVR_sts, // Store Direct to SRAM +AVR_st, // Store Indirect +AVR_std, // Store Indirect with Displacement +AVR_lpm, // Load Program Memory +AVR_in, // In Port +AVR_out, // Out Port +AVR_push, // Push Register on Stack +AVR_pop, // Pop Register from Stack + +// BIT AND BIT-TEST INSTRUCTIONS +AVR_lsl, // Logical Shift Left +AVR_lsr, // Logical Shift Right +AVR_rol, // Rotate Left Through Carry +AVR_ror, // Rotate Right Through Carry +AVR_asr, // Arithmetic Shift Right +AVR_swap, // Swap Nibbles +AVR_bset, // Flag Set +AVR_bclr, // Flag Clear +AVR_sbi, // Set Bit in I/O Register +AVR_cbi, // Clear Bit in I/O Register +AVR_bst, // Bit Store from Register to T +AVR_bld, // Bit load from T to Register +AVR_sec, // Set Carry +AVR_clc, // Clear Carry +AVR_sen, // Set Negative Flag +AVR_cln, // Clear Negative Flag +AVR_sez, // Set Zero Flag +AVR_clz, // Clear Zero Flag +AVR_sei, // Global Interrupt Enable +AVR_cli, // Global Interrupt Disable +AVR_ses, // Set Signed Test Flag +AVR_cls, // Clear Signed Test Flag +AVR_sev, // Set Two's Complement Overflow +AVR_clv, // Clear Two's Complement Overflow +AVR_set, // Set T in SREG +AVR_clt, // Clear T in SREG +AVR_seh, // Set Half Carry Flag in SREG +AVR_clh, // Clear Half Carry Flag in SREG +AVR_nop, // No Operation +AVR_sleep, // Sleep +AVR_wdr, // Watchdog Reset + +// New MegaAVR instructions + +AVR_elpm, // Extended Load Program Memory +AVR_espm, // Extended Store Program Memory +AVR_fmul, // Fractional Multiply Unsigned +AVR_fmuls, // Fractional Multiply Signed +AVR_fmulsu, // Fractional Multiply Signed with Unsigned +AVR_movw, // Copy Register Word +AVR_muls, // Multiply Signed +AVR_mulsu, // Multiply Signed with Unsigned +AVR_spm, // Store Program Memory +AVR_eicall, // Extended Indirect Call to Subroutine +AVR_eijmp, // Extended Indirect Jump + +// New XMega instructions + +AVR_des, // Data Encryption Standard +AVR_lac, // Load And Clear +AVR_las, // Load And Set +AVR_lat, // Load And Toggle +AVR_xch, // Exchange + +AVR_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +MIPS_null = 0, // Unknown Operation + +// The core processor instructions + +MIPS_add, // Add +MIPS_addu, // Add Unsigned +MIPS_and, // AND +MIPS_dadd, // Doubleword Add +MIPS_daddu, // Doubleword Add Unsigned +MIPS_dsub, // Doubleword Subtract +MIPS_dsubu, // Doubleword Subtract Unsigned +MIPS_nor, // NOR +MIPS_or, // OR +MIPS_slt, // Set on Less Than +MIPS_sltu, // Set on Less Than Unsigned +MIPS_sub, // Subtract +MIPS_subu, // Subtract Unsigned +MIPS_xor, // Exclusive OR +MIPS_dsll, // Doubleword Shift Left Logical +MIPS_dsll32, // Doubleword Shift Left Logical + 32 +MIPS_dsra, // Doubleword Shift Right Arithmetic +MIPS_dsra32, // Doubleword Shift Right Arithmetic + 32 +MIPS_dsrl, // Doubleword Shift Right Logical +MIPS_dsrl32, // Doubleword Shift Right Logical + 32 +MIPS_sll, // Shift Left Logical +MIPS_sra, // Shift Right Arithmetic +MIPS_srl, // Shift Right Logical +MIPS_dsllv, // Doubleword Shift Left Logical Variable +MIPS_dsrav, // Doubleword Shift Right Arithmetic Variable +MIPS_dsrlv, // Doubleword Shift Right Logical Variable +MIPS_sllv, // Shift Left Logical Variable +MIPS_srav, // Shift Right Arithmetic Variable +MIPS_srlv, // Shift Right Logical Variable +MIPS_addi, // Add Immediate +MIPS_addiu, // Add Immediate Unsigned +MIPS_daddi, // Doubleword Add Immediate +MIPS_daddiu, // Doubleword Add Immediate Unsigned +MIPS_slti, // Set on Less Than Immediate +MIPS_sltiu, // Set on Less Than Immediate Unsigned +MIPS_andi, // AND Immediate +MIPS_ori, // OR Immediate +MIPS_xori, // Exclusive OR Immediate +MIPS_teq, // Trap if Equal +MIPS_tge, // Trap if Greater Than or Equal +MIPS_tgeu, // Trap if Greater Than or Equal Unsigned +MIPS_tlt, // Trap if Less Than +MIPS_tltu, // Trap if Less Than Unsigned +MIPS_tne, // Trap if Not Equal +MIPS_cfc1, // Move Control From FPU +MIPS_cfc2, // Move Control From Coprocessor 2 +MIPS_ctc1, // Move Control to FPU +MIPS_ctc2, // Move Control to Coprocessor 2 +MIPS_dmfc0, // Doubleword Move From CP0 +MIPS_qmfc2, // Quadword Move From CP2 +MIPS_dmtc0, // Doubleword Move To CP0 +MIPS_qmtc2, // Quadword Move To CP2 +MIPS_mfc0, // Move from CP0 +MIPS_mfc1, // Move from FPU +MIPS_mfc2, // Move from CP2 +MIPS_mtc0, // Move to CP0 +MIPS_mtc1, // Move to FPU +MIPS_mtc2, // Move to CP2 +MIPS_teqi, // Trap if Equal Immediate +MIPS_tgei, // Trap if Greater Than or Equal Immediate +MIPS_tgeiu, // Trap if Greater Than or Equal Immediate Unsigned +MIPS_tlti, // Trap if Less Than Immediate +MIPS_tltiu, // Trap if Less Than Immediate Unsigned +MIPS_tnei, // Trap if Not Equal Immediate +MIPS_ddiv, // Doubleword Divide +MIPS_ddivu, // Doubleword Divide Unsigned +MIPS_div, // Divide +MIPS_divu, // Divide Unsigned +MIPS_dmult, // Doubleword Multiply +MIPS_dmultu, // Doubleword Multiply Unsigned +MIPS_mult, // Multiply +MIPS_multu, // Multiply Unsigned +MIPS_mthi, // Move To HI +MIPS_mtlo, // Move To LO +MIPS_mfhi, // Move From HI +MIPS_mflo, // Move From LO +MIPS_cop0, // Coprocessor 0 Operation +MIPS_cop1, // FPU Operation +MIPS_cop2, // Coprocessor 2 Operation +MIPS_break, // Break +MIPS_syscall, // System Call +MIPS_bc0f, // Branch on Coprocessor 0 False +MIPS_bc1f, // Branch on FPU False +MIPS_bc2f, // Branch on Coprocessor 2 False +MIPS_bc3f, // Branch on Coprocessor 3 False +MIPS_bc0fl, // Branch on Coprocessor 0 False Likely +MIPS_bc1fl, // Branch on FPU False Likely +MIPS_bc2fl, // Branch on Coprocessor 2 False Likely +MIPS_bc3fl, // Branch on Coprocessor 3 False Likely +MIPS_bc0t, // Branch on Coprocessor 0 True +MIPS_bc1t, // Branch on FPU True +MIPS_bc2t, // Branch on Coprocessor 2 True +MIPS_bc3t, // Branch on Coprocessor 3 True +MIPS_bc0tl, // Branch on Coprocessor 0 True Likely +MIPS_bc1tl, // Branch on FPU True Likely +MIPS_bc2tl, // Branch on Coprocessor 2 True Likely +MIPS_bc3tl, // Branch on Coprocessor 3 True Likely +MIPS_bgez, // Branch on Greater Than or Equal to Zero +MIPS_bgezal, // Branch on Greater Than or Equal to Zero And Link +MIPS_bgezall, // Branch on Greater Than or Equal to Zero And Link Likely +MIPS_bgezl, // Branch on Greater Than or Equal to Zero Likely +MIPS_bgtz, // Branch on Greater Than Zero +MIPS_bgtzl, // Branch on Greater Than Zero Likely +MIPS_blez, // Branch on Less Than or Equal to Zero +MIPS_blezl, // Branch on Less Than or Equal to Zero Likely +MIPS_bltz, // Branch on Less Than Zero +MIPS_bltzal, // Branch on Less Than Zero And Link +MIPS_bltzall, // Branch on Less Than Zero And Link Likely +MIPS_bltzl, // Branch on Less Than Zero Likely +MIPS_beq, // Branch on Equal +MIPS_beql, // Branch on Equal Likely +MIPS_bne, // Branch on Not Equal +MIPS_bnel, // Branch on Not Equal Likely +MIPS_jalr, // Jump And Link Register +MIPS_j, // Jump +MIPS_jr, // Jump Register +MIPS_jal, // Jump And Link +MIPS_jalx, // Jump And Link And Exchange +MIPS_cache, // Cache Operation +MIPS_lb, // Load Byte +MIPS_lbu, // Load Byte Unsigned +MIPS_ldl, // Load Doubleword Left +MIPS_ldr, // Load Doubleword Right +MIPS_lwl, // Load Word Left +MIPS_lwr, // Load Word Right +MIPS_ld, // Load Doubleword +MIPS_lld, // Load Linked Doubleword +MIPS_ldc1, // Load Double FPU +MIPS_ldc2, // Load Double Coprocessor 2 +MIPS_ll, // Load Linked +MIPS_lw, // Load Word +MIPS_lwu, // Load Word Unsigned +MIPS_lh, // Load Halfword +MIPS_lhu, // Load Halfword Unsigned +MIPS_lui, // Load Upper Immediate +MIPS_lwc1, // Load Word to FPU +MIPS_lwc2, // Load Word to Coprocessor 2 +MIPS_sb, // Store Byte +MIPS_sdl, // Store Doubleword Left +MIPS_sdr, // Store Doubleword Right +MIPS_swl, // Store Word Left +MIPS_swr, // Store Word Right +MIPS_scd, // Store Conditional Doubleword +MIPS_sd, // Store Doubleword +MIPS_sdc1, // Store Double FPU +MIPS_sdc2, // Store Double Coprocessor 2 +MIPS_sc, // Store Conditional +MIPS_sw, // Store Word +MIPS_sh, // Store Halfword +MIPS_swc1, // Store Word from FPU +MIPS_swc2, // Store Word from Coprocessor 2 +MIPS_sync, // Sync + +// Coprocessor 0 instructions + +MIPS_eret, // Exception Return +MIPS_tlbp, // Probe TLB for Matching Entry +MIPS_tlbr, // Read Indexed TLB Entry +MIPS_tlbwi, // Write Indexed TLB Entry +MIPS_tlbwr, // Write Random TLB Entry + + +// Coprocessor 1 (FPU) instructions + +MIPS_fadd, // Floating-point Add +MIPS_fsub, // Floating-point Subtract +MIPS_fmul, // Floating-point Multiply +MIPS_fdiv, // Floating-point Divide +MIPS_fabs, // Floating-point Absolute Value +MIPS_fcvt_s, // Floating-point Convert to Single Fixed-Point Format +MIPS_fcvt_d, // Floating-point Convert to Double Floating-Point Format +MIPS_fcvt_w, // Floating-point Convert to Fixed-Point Format +MIPS_fcvt_l, // Floating-point Convert to Long Fixed-Point Format +MIPS_fround_l, // Floating-point Round to Long Fixed-Point Format +MIPS_ftrunc_l, // Floating-point Truncate to Long Fixed-Point Format +MIPS_fceil_l, // Floating-point Ceiling to Long Fixed-Point Format +MIPS_ffloor_l, // Floating-point Floor to Long Fixed-Point Format +MIPS_fround_w, // Floating-point Round to Single Fixed-Point Format +MIPS_ftrunc_w, // Floating-point Truncate to Single Fixed-Point Format +MIPS_fceil_w, // Floating-point Ceiling to Single Fixed-Point Format +MIPS_ffloor_w, // Floating-point Floor to Single Fixed-Point Format +MIPS_fmov, // Floating-point Move +MIPS_fneg, // Floating-point Negate +MIPS_fsqrt, // Floating-point Square Root +MIPS_fc_f, // Floating-point Compare +MIPS_fc_un, // Floating-point Compare +MIPS_fc_eq, // Floating-point Compare +MIPS_fc_ueq, // Floating-point Compare +MIPS_fc_olt, // Floating-point Compare +MIPS_fc_ult, // Floating-point Compare +MIPS_fc_ole, // Floating-point Compare +MIPS_fc_ule, // Floating-point Compare +MIPS_fc_sf, // Floating-point Compare +MIPS_fc_ngle, // Floating-point Compare +MIPS_fc_seq, // Floating-point Compare +MIPS_fc_ngl, // Floating-point Compare +MIPS_fc_lt, // Floating-point Compare +MIPS_fc_nge, // Floating-point Compare +MIPS_fc_le, // Floating-point Compare +MIPS_fc_ngt, // Floating-point Compare + +// Pseudo instructions + +MIPS_nop, // No operation +MIPS_mov, // Move register +MIPS_neg, // Negate +MIPS_negu, // Negate Unsigned +MIPS_bnez, // Branch on Not Zero +MIPS_bnezl, // Branch on Not Zero Likely +MIPS_beqz, // Branch on Zero +MIPS_beqzl, // Branch on Zero Likely +MIPS_b, // Branch Always +MIPS_bal, // Branch Always and Link +MIPS_li, // Load Immediate +MIPS_la, // Load Address + +// MIPS IV instructions + +MIPS_pref, // Prefetch +MIPS_ldxc1, // Load Doubleword Indexed to Floating Point +MIPS_lwxc1, // Load Word Indexed to Floating Point +MIPS_sdxc1, // Store Doubleword Indexed from Floating Point +MIPS_swxc1, // Store Word Indexed from Floating Point +MIPS_madd_s, // Floating-Point Multiply Add +MIPS_madd_d, // Floating-Point Multiply Add +MIPS_msub_s, // Floating-Point Multiply Subtract +MIPS_msub_d, // Floating-Point Multiply Subtract +MIPS_movf, // Move Conditional on FP False +MIPS_movt, // Move Conditional on FP True +MIPS_movn, // Move Conditional on Not Zero +MIPS_movz, // Move Conditional on Zero +MIPS_fmovf, // Floating-Point Move Conditional on FP False +MIPS_fmovt, // Floating-Point Move Conditional on FP True +MIPS_fmovn, // Floating-Point Move Conditional on Not Zero +MIPS_fmovz, // Floating-Point Move Conditional on Zero +MIPS_nmadd_s, // Floating-Pont Negative Multiply Add +MIPS_nmadd_d, // Floating-Pont Negative Multiply Add +MIPS_nmsub_s, // Floating-Pont Negative Multiply Subtract +MIPS_nmsub_d, // Floating-Pont Negative Multiply Subtract +MIPS_prefx, // Prefetch Indexed +MIPS_frecip, // Reciprocal Approximation +MIPS_frsqrt, // Reciprocal Suare Root Approximation + +// RSP instructions + +MIPS_lbv, // Load Byte into Vector +MIPS_lsv, // Load Short into Vector +MIPS_llv, // Load Word into Vector +MIPS_ldv, // Load Doubleword into Vector +MIPS_lqv, // Load Quadword into Vector +MIPS_lrv, // Load Rest Vector +MIPS_lpv, // Load Packed Vector +MIPS_luv, // Load Unpack Vector +MIPS_lhv, // Load Half Vector +MIPS_lfv, // Load Fourth Vector +MIPS_lwv, // Load Wrap Vector +MIPS_ltv, // Load Transpose Vector +MIPS_sbv, // Store Byte from Vector +MIPS_ssv, // Store Short from Vector +MIPS_slv, // Store Word from Vector +MIPS_sdv, // Store Doubleword from Vector +MIPS_sqv, // Store Quadword from Vector +MIPS_srv, // Store Rest Vector +MIPS_spv, // Store Packed Vector +MIPS_suv, // Store Unpack Vector +MIPS_shv, // Store Half Vector +MIPS_sfv, // Store Fourth Vector +MIPS_swv, // Store Wrap Vector +MIPS_stv, // Store Transpose Vector +MIPS_vmulf, // Vector (Frac) Multiply +MIPS_vmacf, // Vector (Frac) Multiply Accumulate +MIPS_vmulu, // Vector (Unsigned Frac) Multiply +MIPS_vmacu, // Vector (Unsigned Frac) Multiply Accumulate +MIPS_vrndp, // Vector DCT Round (+) +MIPS_vrndn, // Vector DCT Round (-) +MIPS_vmulq, // Vector (Integer) Multiply +MIPS_vmacq, // Vector (Integer) Multiply Accumulate +MIPS_vmudh, // Vector (High) Multiply +MIPS_vmadh, // Vector (High) Multiply Accumulate +MIPS_vmudm, // Vector (Mid-M) Multiply +MIPS_vmadm, // Vector (Mid-M) Multiply Accumulate +MIPS_vmudn, // Vector (Mid-N) Multiply +MIPS_vmadn, // Vector (Mid-N) Multiply Accumulate +MIPS_vmudl, // Vector (Low) Multiply +MIPS_vmadl, // Vector (Low) Multiply Accumulate +MIPS_vadd, // Vector Add +MIPS_vsub, // Vector Subtract +MIPS_vsut, // Vector SUT (vt - vs) +MIPS_vabs, // Vector Absolute Value +MIPS_vaddc, // Vector ADDC +MIPS_vsubc, // Vector SUBC +MIPS_vaddb, // Vector Add Byte +MIPS_vsubb, // Vector Subtract Byte +MIPS_vaccb, // Vector Add Byte/Add Accumulator +MIPS_vsucb, // Vector Subtract Byte/Add Accumulator +MIPS_vsad, // Vector SAD +MIPS_vsac, // Vector SAC +MIPS_vsum, // Vector SUM +MIPS_vsaw, // Vector SAW +MIPS_vlt, // Vector Less Than +MIPS_veq, // Vector Equal To +MIPS_vne, // Vector Not Equal To +MIPS_vge, // Vector Greater Than or Equal To +MIPS_vcl, // Vector Clip Low +MIPS_vch, // Vector Clip High +MIPS_vcr, // Vector 1's Complement Clip +MIPS_vmrg, // Vector Merge +MIPS_vand, // Vector Logical AND +MIPS_vnand, // Vector Logical NAND +MIPS_vor, // Vector Logical OR +MIPS_vnor, // Vector Logical NOR +MIPS_vxor, // Vector Logical Exclusive OR +MIPS_vnxor, // Vector Logical NOT Exclusive OR +MIPS_vnoop, // Vector No-Operation +MIPS_vmov, // Vector Scalar-Element Move +MIPS_vrcp, // Single Precision, Lookup Source, Write Result +MIPS_vrsq, // Single Precision, Lookup Source, Write Result +MIPS_vrcph, // Set Source, Write Previous Result +MIPS_vrsqh, // Set Source, Write Previous Result +MIPS_vrcpl, // Lookup Source and Previous, Write Result +MIPS_vrsql, // Lookup Source and Previous, Write Result +MIPS_vinst, // Vector Insert Triple (5/5/5/1) +MIPS_vextt, // Vector Extract Triple (5/5/5/1) +MIPS_vinsq, // Vector Insert Quad (4/4/4/4) +MIPS_vextq, // Vector Extract Quad (4/4/4/4) +MIPS_vinsn, // Vector Insert Nibble (4/4/4/4) Sign-Extended +MIPS_vextn, // Vector Insert Nibble (4/4/4/4) Sign-Extended +MIPS_cfc0, // Move Control From Coprocessor 0 +MIPS_ctc0, // Move Control to Coprocessor 0 + +// R5900 (PSX2 or PlayStation2) processor additional commands + +MIPS_mtsa, // Move To Shift Amount Register +MIPS_R5900_first = MIPS_mtsa, +MIPS_mfsa, // Move From Shift Amount Register +MIPS_mtsab, // Move Byte Count To Shift Amount Register +MIPS_mtsah, // Move Halfword Count To Shift Amount Register +MIPS_fadda, // Floating-point add to accumulator +MIPS_fsuba, // Floating-point subtract to accumulator +MIPS_fmula, // Floating-point multiply to accumulator +MIPS_fmadda, // Floating-point multiply and add to accumulator +MIPS_fmsuba, // Floating-point multiply and subtract from accumulator +MIPS_fmadd, // Floating-point multiply and add +MIPS_fmsub, // Floating-point multiply and subtract +MIPS_fmax, // Floating-point maximum +MIPS_fmin, // Floating-point minimum +MIPS_plzcw, // Parallel Leading Zero or One Count Word +MIPS_mthi1, // Move To HI1 Register +MIPS_mtlo1, // Move To LO1 Register +MIPS_pmthl_lw, // Parallel Move From HI/LO Register +MIPS_pmthi, // Parallel Move To HI Register +MIPS_pmtlo, // Parallel Move To LO Register +MIPS_div1, // Divide Pipeline 1 +MIPS_divu1, // Divide Unsigned Pipeline 1 +MIPS_pdivw, // Parallel Divide Word +MIPS_pdivuw, // Parallel Divide Unsigned Word +MIPS_pdivbw, // Parallel Divide Broadcast Word +MIPS_paddw, // Parallel Add Word +MIPS_pmaddw, // Parallel Multiply-Add Word +MIPS_mult1, // Multiply Pipeline 1 +MIPS_multu1, // Multiply Unsigned Pipeline 1 +MIPS_madd1, // Multiply-Add Pipeline 1 +MIPS_maddu1, // Multiply-Add Unsigned Pipeline 1 +MIPS_pmadduw, // Parallel Multiply-Add Unsigned Word +MIPS_psubw, // Parallel Subtract HalfWord +MIPS_pcgtw, // Parallel Compare for Greater Than Word +MIPS_psllvw, // Parallel Shift Left Logical Variable Word +MIPS_pceqw, // Parallel Compare for Equal Word +MIPS_pmaxw, // Parallel Maximize Word +MIPS_psrlvw, // Parallel Shift Right Logical Variable Word +MIPS_pminw, // Parallel Minimize Word +MIPS_psravw, // Parallel Shift Right Arithmetic Variable Word +MIPS_paddh, // Parallel Add Halfword +MIPS_pmsubw, // Parallel Multiply-Subtract Word +MIPS_padsbh, // Parallel Add/Subtract Halfword +MIPS_psubh, // Parallel Subtract Halfword +MIPS_pcgth, // Parallel Compare for Greater Than Halfword +MIPS_pceqh, // Parallel Compare for Equal Halfword +MIPS_pmaxh, // Parallel Maximize Halfword +MIPS_pminh, // Parallel Minimize Halfword +MIPS_paddb, // Parallel Add Byte +MIPS_psubb, // Parallel Subtract Byte +MIPS_pcgtb, // Parallel Compare for Greater Than Byte +MIPS_pinth, // Parallel Interleave Halfword +MIPS_pceqb, // Parallel Compare for Equal Byte +MIPS_pintoh, // Parallel Interleave Odd Halfword +MIPS_pmultw, // Parallel Multiply Word +MIPS_pmultuw, // Parallel Multiply Unsigned Word +MIPS_pcpyld, // Parallel Copy Lower Doubleword +MIPS_pcpyud, // Parallel Copy Upper Doubleword +MIPS_paddsw, // Parallel Add with Signed Saturation Word +MIPS_pmaddh, // Parallel Multiply-Add Halfword +MIPS_padduw, // Parallel Add with Unsigned Saturation Word +MIPS_psubsw, // Parallel Subtract with Signed Saturation Word +MIPS_phmadh, // Parallel Horizontal Multiply-Add Halfword +MIPS_psubuw, // Parallel Subtract with Unsigned Saturation Word +MIPS_pextlw, // Parallel Extend Lower from Word +MIPS_pand, // Parallel AND +MIPS_pextuw, // Parallel Extend Upper from Word +MIPS_por, // Parallel OR +MIPS_ppacw, // Paralle Pack to Word +MIPS_pxor, // Parallel XOR +MIPS_pnor, // Parallel NOR +MIPS_paddsh, // Parallel Add with Signed Saturation Halfword +MIPS_pmsubh, // Parallel Multiply-Subtract Halfword +MIPS_padduh, // Parallel Add with Unsigned Saturation Halfword +MIPS_psubsh, // Parallel Subtract with Signed Saturation Halfword +MIPS_phmsbh, // Parallel Horizontal Multiply-Subtract Halfword +MIPS_psubuh, // Parallel Subtract with Unsigned Saturation Halfword +MIPS_pextlh, // Parallel Extend Lower from Halfword +MIPS_pextuh, // Parallel Extend Upper from Halfword +MIPS_ppach, // Paralle Pack to Halfword +MIPS_paddsb, // Parallel Add with Signed Saturation Byte +MIPS_paddub, // Parallel Add with Unsigned Saturation Byte +MIPS_psubsb, // Parallel Subtract with Signed Saturation Byte +MIPS_psubub, // Parallel Subtract with Unsigned Saturation Byte +MIPS_pextlb, // Parallel Extend Lower from Byte +MIPS_pextub, // Parallel Extend Upper from Byte +MIPS_ppacb, // Paralle Pack to Byte +MIPS_qfsrv, // Quadword Funnel Shift Right Variable +MIPS_pmulth, // Parallel Multiply Halfword +MIPS_pabsw, // Parallel Absolute Word +MIPS_pabsh, // Parallel Absolute Halfword +MIPS_pexoh, // Parallel Exchange Odd Halfword +MIPS_pexch, // Parallel Exchange Center Halfword +MIPS_prevh, // Parallel Reverse Halfword +MIPS_pcpyh, // Parallel Copy Halfword +MIPS_pext5, // Parallel Extend Upper from 5 bits +MIPS_pexow, // Parallel Exchange Odd Word +MIPS_pexcw, // Parallel Exchange Center Word +MIPS_ppac5, // Parallel Pack to 5 bits +MIPS_prot3w, // Parallel Rotate 3 Words +MIPS_psllh, // Parallel Shift Left Logical Halfword +MIPS_psrlh, // Parallel Shift Right Logical Halfword +MIPS_psrah, // Parallel Shift Right Arithmetic Halfword +MIPS_psllw, // Parallel Shift Left Logical Word +MIPS_psrlw, // Parallel Shift Right Logical Word +MIPS_psraw, // Parallel Shift Right Arithmetic Word +MIPS_mfhi1, // Move From HI1 Register +MIPS_mflo1, // Move From LO1 Register +MIPS_pmfhi, // Parallel Move From HI Register +MIPS_pmflo, // Parallel Move From LO Register +MIPS_pmfhl, // Parallel Move From HI/LO Register +MIPS_lq, // Load Quadword +MIPS_sq, // Store Quadword +MIPS_lqc2, // Load Quadword Coprocessor 2 +MIPS_sqc2, // Store Quadword Coprocessor 2 +MIPS_madd_r5900, // Multiply/Add +MIPS_maddu_r5900, // Multiply/Add Unsigned +MIPS_R5900_last = MIPS_maddu_r5900, +MIPS_mult3, // Multiply (3-operand) +MIPS_multu3, // Multiply Unsigned (3-operand) + +// 16-bit instructions +// NOTE: in previous version of IDA, all mips16 instructions +// had separate numbers, even for the instructions with the +// same mnemonics. Now same mnemonics have the same numbers, +// regardless of the encoding. + +MIPS_bteqz=439, // Branch on T Equal to Zero +MIPS_btnez, // Branch on T Not Equal to Zero +MIPS_cmp, // Compare +MIPS_cmpi, // Compare Immediate +MIPS_extend=458, // Extend +MIPS_move=473, // Move +MIPS_not=477, // Not +MIPS_dla=495, // Load 64-bit address + +// Instructions which belong to MIPS32 but which were not decoded by IDA + +MIPS_clo=498, // Count Leading Ones in Word +MIPS_clz, // Count Leading Zeros in Word +MIPS_madd, // Multiply/Add +MIPS_maddu, // Multiply/Add Unsigned +MIPS_msub, // Multiply and Subtract Word to Hi,Lo +MIPS_msubu, // Multiply and Subtract Word to Hi,Lo +MIPS_mul, // Multiply Word to GPR +MIPS_sdbbp, // Software Debug Breakpoint +MIPS_wait, // Enter Standby Mode + +// New instructions for MIPS32 Release 2.0 + +MIPS_alnv_ps, // Floating Point Align Variable +MIPS_deret, // Debug Exception Return +MIPS_di, // Disable interrupts +MIPS_ehb, // Execution Hazard Barrier +MIPS_ei, // Enable interrupts +MIPS_ext, // Extract Bit Field +MIPS_fcvt_ps, // Floating Point Convert Pair to Paired Single +MIPS_fcvt_s_pl, // Floating Point Convert Pair Lower to Single Floating Point +MIPS_fcvt_s_pu, // Floating Point Convert Pair Upper to Single Floating Point +MIPS_ins, // Insert Bit Field +MIPS_jalr_hb, // Jump and Link Register with Hazard Barrier +MIPS_jr_hb, // Jump Register with Hazard Barrier +MIPS_luxc1, // Load Doubleword Indexed Unaligned to Floating Point +MIPS_madd_ps, // Floating Point Multiply Add +MIPS_mfhc1, // Move Word from High Half of Floating Point Register +MIPS_mfhc2, // Move Word from High Half of Coprocessor 2 Register +MIPS_msub_ps, // Floating Point Multiply Subtract +MIPS_mthc1, // Move Word to High Half of Floating Point Register +MIPS_mthc2, // Move Word to High Half of Coprocessor 2 Register +MIPS_nmadd_ps, // Floating Point Negative Multiply Add +MIPS_nmsub_ps, // Floating Point Negative Multiply Subtract +MIPS_pll, // Pair Lower Lower +MIPS_plu, // Pair Lower Upper +MIPS_pul, // Pair Upper Lower +MIPS_puu, // Pair Upper Upper +MIPS_rdhwr, // Read Hardware Register +MIPS_rdpgpr, // Read GPR from Previous Shadow Set +MIPS_rotr, // Rotate Word Right +MIPS_rotrv, // Rotate Word Right Variable +MIPS_seb, // Sign-Extend Byte +MIPS_seh, // Sign-Extend Halfword +MIPS_suxc1, // Store Doubleword Indexed Unaligned from Floating Point +MIPS_synci, // Synchronize Caches to Make Instruction Writes Effective +MIPS_wrpgpr, // Write GPR to Previous Shadow Set +MIPS_wsbh, // Word Swap Bytes Within Halfwords + +// Missing instructions - for some reason they were not supported before + +MIPS_dmfc1, // Doubleword Move From CP1 +MIPS_dmtc1, // Doubleword Move To CP1 + +// additional MIPS16e instructions + +MIPS_save, // Save Registers and Set Up Stack Frame +MIPS_restore, // Restore Registers and Deallocate Stack Frame +MIPS_jalrc, // Jump and Link Register, Compact +MIPS_jrc, // Jump Register, Compact +MIPS_sew, // Sign-Extend Word +MIPS_zeb, // Zero-Extend Byte +MIPS_zeh, // Zero-Extend Halfword +MIPS_zew, // Zero-Extend Word + +// extra pseudoinstructions +MIPS_ssnop, // Superscalar No operation +MIPS_li_s, // Load floating-point immediate +MIPS_li_d, // Load floating-point immediate +MIPS_dneg, // Negate +MIPS_dnegu, // Negate Unsigned +MIPS_pause, // Wait for the LLBit to clear + +// Missing instructions from MIPS64 Release 2 + +MIPS_dclo, // Count Leading Ones in Doubleword +MIPS_dclz, // Count Leading Zeros in Doubleword +MIPS_dext, // Doubleword Extract Bit Field +MIPS_dextm, // Doubleword Extract Bit Field Middle +MIPS_dextu, // Doubleword Extract Bit Field Upper +MIPS_dins, // Doubleword Insert Bit Field +MIPS_dinsm, // Doubleword Insert Bit Field Middle +MIPS_dinsu, // Doubleword Insert Bit Field Upper +MIPS_dmfc2, // Doubleword Move From CP2 +MIPS_dmtc2, // Doubleword Move To CP2 +MIPS_drotr, // Doubleword Rotate Right +MIPS_drotr32, // Doubleword Rotate Right Plus 32 +MIPS_drotrv, // Doubleword Rotate Right Variable +MIPS_dsbh, // Doubleword Swap Bytes Within Halfwords +MIPS_dshd, // Doubleword Swap Halfwords Within Doublewords + +// cnMIPS (Cavium Networks Octeon) instructions + +MIPS_baddu, // Unsigned Byte Add +MIPS_bbit0, // Branch on Bit Clear +MIPS_bbit032, // Branch on Bit Clear Plus 32 +MIPS_bbit1, // Branch on Bit Set +MIPS_bbit132, // Branch on Bit Set Plus 32 +MIPS_cins, // Clear and Insert a Bit Field +MIPS_cins32, // Clear and Insert a Bit Field Plus 32 +MIPS_dmul, // Multiply Doubleword to GPR +MIPS_dpop, // Count Ones in a Doubleword +MIPS_exts, // Extract a Signed Bit Field +MIPS_exts32, // Extract a Signed Bit Field Plus 32 +MIPS_mtm0, // Load Multiplier Register MPL0 +MIPS_mtm1, // Load Multiplier Register MPL1 +MIPS_mtm2, // Load Multiplier Register MPL2 +MIPS_mtp0, // Load Multiplier Register P0 +MIPS_mtp1, // Load Multiplier Register P1 +MIPS_mtp2, // Load Multiplier Register P2 +MIPS_pop, // Count Ones in a Word +MIPS_saa, // Store Atomic Add Word +MIPS_saad, // Store Atomic Add Double Word +MIPS_seq, // Set on Equal +MIPS_seqi, // Set on Equal Immediate +MIPS_sne, // Set on Not Equal +MIPS_snei, // Set on Not Equal Immediate +MIPS_synciobdma, // Synchronize IOBDMAs +MIPS_syncs, // Synchronize Special +MIPS_syncw, // Synchronize Stores +MIPS_syncws, // Synchronize Stores Special +MIPS_uld, // Unaligned Load Doubleword +MIPS_ulw, // Unaligned Load Word +MIPS_usd, // Unaligned Store Doubleword +MIPS_usw, // Unaligned Store Word +MIPS_v3mulu, // 192-bit x 64-bit Unsigned Multiply and Add +MIPS_vmm0, // 64-bit Unsigned Multiply and Add Move +MIPS_vmulu_cn, // 64-bit Unsigned Multiply and Add + +// NEC VR5432 and PSP instructions + +MIPS_dbreak, // Debug Break +MIPS_dret, // Debug Return +MIPS_mfdr, // Move from Debug Register +MIPS_mtdr, // Move to Debug Register + +// Allegrex (Sony PSP) instructions + +PSP_bitrev, // Bit reverse +PSP_max, // Maximum +PSP_min, // Minimum +PSP_mfic, // Move from interrupt controller +PSP_mtic, // Move to interrupt controller +PSP_wsbw, // Word Swap Bytes Within Word +PSP_sleep, // Sleep + +// Allegrex VFPU instructions + +PSP_lv, // Load Vector +PSP_lvl, // Load Vector Left +PSP_lvr, // Load Vector Right +PSP_sv, // Store Vector +PSP_svl, // Store Vector Left +PSP_svr, // Store Vector Right +PSP_mfv, // Move from VFPU +PSP_mtv, // Move to VFPU +PSP_mfvc, // Move Control from VFPU +PSP_mtvc, // Move Control to VFPU +PSP_bvf, // Branch on VFPU False +PSP_bvt, // Branch on VFPU True +PSP_bvfl, // Branch on VFPU False Likely +PSP_bvtl, // Branch on VFPU True Likely +PSP_vnop, // VFPU no-op +PSP_vflush, // VFPU flush +PSP_vsync, // VFPU sync +PSP_vabs, // Vector absolute value +PSP_vadd, // Vector add +PSP_vasin, // Vector arcsine +PSP_vavg, // Vector average +PSP_vbfy1, // IDCT butterfly 1 +PSP_vbfy2, // IDCT butterfly 2 +PSP_vc2i, // Vector convert signed char to integer +PSP_vcmovf, // Vector move if condition field is true +PSP_vcmovt, // Vector move if condition field is false +PSP_vcmp, // Vector compare and set condition fields +PSP_vcos, // Vector cosine +PSP_vcrs, // Vector cross multiplication: vd = [y1*z2, z1*x2, x1*y2] +PSP_vcrsp, // Vector cross product +PSP_vcst, // Set constant +PSP_vdet, // Determinant +PSP_vdiv, // Vector divide +PSP_vdot, // Vector dot product +PSP_vexp2, // Vector exponent of 2 (2^x) +PSP_vf2h, // Vector convert float single to half precision +PSP_vf2id, // Vector convert float to integer, round down +PSP_vf2in, // Vector convert float to integer, round to nearest +PSP_vf2iu, // Vector convert float to integer, round up +PSP_vf2iz, // Vector convert float to integer, round toward zero +PSP_vfad, // Vector funnel add (sum components) +PSP_vfim, // Set floating-point immediate +PSP_vh2f, // Vector convert float half to single precision +PSP_vhdp, // Vector homogenous dot product +PSP_vhtfm2, // Homogenous transform vector by matrix +PSP_vhtfm3, // Homogenous transform vector by matrix +PSP_vhtfm4, // Homogenous transform vector by matrix +PSP_vi2c, // Vector convert integer to signed char +PSP_vi2f, // Vector convert integer to float +PSP_vi2s, // Vector convert integer to signed short +PSP_vi2uc, // Vector convert integer to unsigned char +PSP_vi2us, // Vector convert integer to unsigned short +PSP_vidt, // Set vector to identity +PSP_viim, // Set integer immediate +PSP_vlgb, // +PSP_vlog2, // Vector logarithm base 2 +PSP_vmax, // Vector maximum values +PSP_vmfvc, // Vector move from control register +PSP_vmidt, // Set matrix to identity +PSP_vmin, // Vector minimum values +PSP_vmmov, // Move matrix +PSP_vmmul, // Matrix multiply +PSP_vmone, // Set matrix to ones +PSP_vmov, // Move vector +PSP_vmscl, // Scale matrix by +PSP_vmtvc, // Vector move to control register +PSP_vmul, // Vector multiply +PSP_vmzero, // Set matrix to zeroes +PSP_vneg, // Vector negate +PSP_vnrcp, // Vector negative reciprocal (-1/x) +PSP_vnsin, // Vector negative sine +PSP_vocp, // Vector one complement (1-x) +PSP_vone, // Set vector to ones +PSP_vpfxd, // Set prefix operation for vd +PSP_vpfxs, // Set prefix operation for vs +PSP_vpfxt, // Set prefix operation for vt +PSP_vqmul, // Quaternion multiply +PSP_vrcp, // Vector reciprocal (1/x) +PSP_vrexp2, // Vector reciprocal exponent of 2 (1/(2^x)) +PSP_vrndf1, // Vector generate pseudorandom float (1.0 ~ 2.0) +PSP_vrndf2, // Vector generate pseudorandom float (2.0 ~ 4.0) +PSP_vrndi, // Vector generate pseudorandom integer +PSP_vrnds, // Vector set pseudorandom seed +PSP_vrot, // Rotate vector +PSP_vrsq, // Vector reciprocal square root (1/sqrt(x)) +PSP_vs2i, // Vector convert signed short to integer +PSP_vsat0, // Vector saturate to range 0..1 +PSP_vsat1, // Vector saturate to range -1..1 +PSP_vsbn, // Vector scale by 2^x, round to nearest +PSP_vsbz, // Vector scale by 2^x, round towards zero +PSP_vscl, // Vector scale by +PSP_vscmp, // Vector set signed compare +PSP_vsge, // Vector set results for greater than or equal +PSP_vsgn, // Vector get sign +PSP_vsin, // Vector sine +PSP_vslt, // Vector set results for less +PSP_vsocp, // Vector split and one complement +PSP_vsqrt, // Vector square root +PSP_vsrt1, // Vector sort 1: vd = min(x,y), max(x,y), min(z,w), max(z,w) +PSP_vsrt2, // Vector sort 2: vd = min(x,w), max(y,z), min(y,z), max(x,w) +PSP_vsrt3, // Vector sort 3: vd = max(x,y), min(x,y), max(z,w), min(z,w) +PSP_vsrt4, // Vector sort 4: vd = max(x,w), max(y,z), min(y,z), max(x,w) +PSP_vsub, // Vector subtract +PSP_vt4444, // Transform color RGBA8888 to RGBA4444 +PSP_vt5551, // Transform color RGBA8888 to RGBA5551 +PSP_vt5650, // Transform color RGB888 to RGB565 +PSP_vtfm2, // Transform vector by matrix +PSP_vtfm3, // Transform vector by matrix +PSP_vtfm4, // Transform vector by matrix +PSP_vuc2i, // Vector convert unsigned char to integer +PSP_vus2i, // Vector convert unsigned short to integer +PSP_vwbn, // +PSP_vzero, // VFPU set vector to zeroes + +// PSP Media Engine instructions +PSP_mfvme, // move from VME +PSP_mtvme, // move to VME + +// Toshiba TX19a instructions +MIPS_ac0iu, // Add Coprocessor 0 Immediate Unsigned +MIPS_bs1f, // Bit Search One Forward +MIPS_bfins, // Bit field insert +MIPS_addmiu, // Add Immediate to Memory Word +MIPS_sadd, // Saturated Add +MIPS_ssub, // Saturated Subtract +MIPS_btst, // Bit Test +MIPS_bclr, // Bit Clear +MIPS_bset, // Bit Set +MIPS_bins, // Bit Insert +MIPS_bext, // Bit Extract +MIPS_dive, // Divide, with Overflow Exception +MIPS_diveu, // Divide unsigned, with Overflow Exception +MIPS_min, // Minimum signed +MIPS_max, // Maximum signed + +MIPS_madd3, // Multiply/Add (3-operand) +MIPS_maddu3, // Multiply/Add Unsigned (3-operand) +MIPS_msub3, // Multiply and Subtract Word to Hi,Lo (3-operand) +MIPS_msubu3, // Multiply and Subtract Word to Hi,Lo (3-operand) + +// MIPS-MT +MIPS_dvpe, // Disable Virtual Processor Execution +MIPS_evpe, // Enable Virtual Processor Execution +MIPS_dmt, // Disable Multi-Threaded Execution +MIPS_emt, // Enable Multi-Threaded Execution +MIPS_fork, // Allocate and Schedule a New Thread +MIPS_yield, // Conditionally Deschedule or Deallocate the Current Thread +MIPS_mftr, // Move From Thread Context +MIPS_mftc0, +MIPS_mftlo, +MIPS_mfthi, +MIPS_mftacx, +MIPS_mftdsp, +MIPS_mfthc1, +MIPS_mftc1, +MIPS_cftc1, +MIPS_mfthc2, +MIPS_mftc2, +MIPS_cftc2, +MIPS_mftgpr, +MIPS_mttr, // Move To Thread Context +MIPS_mttc0, +MIPS_mttlo, +MIPS_mtthi, +MIPS_mttacx, +MIPS_mttdsp, +MIPS_mtthc1, +MIPS_mttc1, +MIPS_cttc1, +MIPS_mtthc2, +MIPS_mttc2, +MIPS_cttc2, +MIPS_mttgpr, + +// MIPS-3D +MIPS_faddr, // Floating-point Reduction Addition +MIPS_bc1any2f, // Branch on Any of Two Floating Point Condition Codes False +MIPS_bc1any2t, // Branch on Any of Two Floating Point Condition Codes True +MIPS_bc1any4f, // Branch on Any of Four Floating Point Condition Codes False +MIPS_bc1any4t, // Branch on Any of Four Floating Point Condition Codes True +MIPS_fcabs_f, // Floating-point Absolute Compare +MIPS_fcabs_un, // Floating-point Absolute Compare +MIPS_fcabs_eq, // Floating-point Absolute Compare +MIPS_fcabs_ueq, // Floating-point Absolute Compare +MIPS_fcabs_olt, // Floating-point Absolute Compare +MIPS_fcabs_ult, // Floating-point Absolute Compare +MIPS_fcabs_ole, // Floating-point Absolute Compare +MIPS_fcabs_ule, // Floating-point Absolute Compare +MIPS_fcabs_sf, // Floating-point Absolute Compare +MIPS_fcabs_ngle, // Floating-point Absolute Compare +MIPS_fcabs_seq, // Floating-point Absolute Compare +MIPS_fcabs_ngl, // Floating-point Absolute Compare +MIPS_fcabs_lt, // Floating-point Absolute Compare +MIPS_fcabs_nge, // Floating-point Absolute Compare +MIPS_fcabs_le, // Floating-point Absolute Compare +MIPS_fcabs_ngt, // Floating-point Absolute Compare +MIPS_fcvt_pw_ps, // Floating-point Convert Paired Single to Paired Word +MIPS_fcvt_ps_pw, // Floating-point Convert Paired Word to Paired Single +MIPS_fmulr, // Floating-point Reduction Multiply +MIPS_frecip1, // Floating-point Reduced Precision Reciprocal (Step 1) +MIPS_frecip2, // Floating-point Reduced Precision Reciprocal (Step 2) +MIPS_frsqrt1, // Floating-point Reduced Precision Reciprocal Square Root (Step 1) +MIPS_frsqrt2, // Floating-point Reduced Precision Reciprocal Square Root (Step 2) + +// smartMIPS +MIPS_lwxs, +MIPS_maddp, +MIPS_mflhxu, +MIPS_mtlhx, +MIPS_multp, +MIPS_pperm, + +// microMIPS +MIPS_jals, // Jump and Link, Short Delay Slot +MIPS_lwp, // Load Word Pair +MIPS_ldp, // Load Doubleword Pair +MIPS_lwm, // Load Word Multiple +MIPS_ldm, // Load Doubleword Multiple +MIPS_swp, // Store Word Pair +MIPS_sdp, // Store Doubleword Pair +MIPS_swm, // Store Word Multiple +MIPS_sdm, // Store Doubleword Multiple +MIPS_bnezc, // Branch on Not Equal to Zero, Compact +MIPS_bltzals, // Branch on Less Than Zero and Link, Short Delay-Slot +MIPS_beqzc, // Branch on Equal to Zero, Compact +MIPS_bgezals, // Branch on Greater Than or Equal to Zero and Link, Short Delay-Slot +MIPS_jraddiusp, // Jump Register, Adjust Stack Pointer +MIPS_jalrs, // Jump and Link Register, Short Delay Slot +MIPS_jalrs_hb, // Jump and Link Register with Hazard Barrier, Short Delay-Slot +MIPS_movep, // Move a Pair of Registers + +// had been missed; 64-bit MIPS pseudoinstruction +MIPS_dli, // Doubleword Load Immediate + +// DSP ASE instructions +MIPS_insv, // Insert Bit Field Variable +MIPS_dinsv, // Doubleword Insert Variable Bit Field +MIPS_bposge32, // Branch on Greater Than or Equal To Value 32 in DSPControl Pos Field +MIPS_bposge64, // Branch on Greater Than or Equal To Value 64 in DSPControl Pos Field +MIPS_addu_qb, // Unsigned Add Quad Byte Vectors +MIPS_addu_ph, // Unsigned Add Integer Halfwords +MIPS_addsc, // Add Signed Word and Set Carry Bit +MIPS_subu_qb, // Subtract Unsigned Quad Byte Vector +MIPS_subu_ph, // Subtract Unsigned Integer Halfwords +MIPS_addwc, // Add Word with Carry Bit +MIPS_addq_ph, // Add Fractional Halfword Vectors +MIPS_modsub, // Modular Subtraction on an Index Value +MIPS_subq_ph, // Subtract Fractional Halfword Vector +MIPS_addu_s_qb, // Unsigned Add Quad Byte Vectors +MIPS_addu_s_ph, // Unsigned Add Integer Halfwords +MIPS_raddu_w_qb, // Unsigned Reduction Add Vector Quad Bytes +MIPS_muleq_s_w_phl, // Multiply Vector Fractional Left Halfwords to Expanded Width Products +MIPS_subu_s_qb, // Subtract Unsigned Quad Byte Vector +MIPS_subu_s_ph, // Subtract Unsigned Integer Halfwords +MIPS_muleq_s_w_phr, // Multiply Vector Fractional Right Halfwords to Expanded Width Products +MIPS_muleu_s_ph_qbl, // Multiply Unsigned Vector Left Bytes by Halfwords to Halfword Products +MIPS_addq_s_ph, // Add Fractional Halfword Vectors +MIPS_addq_s_w, // Add Fractional Words +MIPS_mulq_s_ph, // Multiply Vector Fractional Half-Words to Same Size Products +MIPS_muleu_s_ph_qbr, // Multiply Unsigned Vector Right Bytes with halfwords to Half Word Products +MIPS_subq_s_ph, // Subtract Fractional Halfword Vector +MIPS_subq_s_w, // Subtract Fractional Word +MIPS_mulq_rs_ph, // Multiply Vector Fractional Halfwords to Fractional Halfword Products +MIPS_addu_ob, // Unsigned Add Octal Byte Vectors +MIPS_subu_ob, // Subtract Unsigned Octal Byte Vector +MIPS_addq_qh, // Add Fractional Halfword Vectors +MIPS_addq_pw, // Add Fractional Word Vectors +MIPS_subq_qh, // Subtract Fractional Halfword Vector +MIPS_subq_pw, // Subtract Fractional Word Vector +MIPS_addu_s_ob, // Unsigned Add Octal Byte Vectors +MIPS_raddu_l_ob, // Unsigned Reduction Add Vector Octal Bytes +MIPS_muleq_s_pw_qhl, // Multiply Vector Fractional Left Halfwords to Expanded Width Products +MIPS_subu_s_ob, // Subtract Unsigned Octal Byte Vector +MIPS_muleq_s_pw_qhr, // Multiply Vector Fractional Right Halfwords to Expanded Width Products +MIPS_muleu_s_qh_obl, // Multiply Unsigned Vector Left Bytes by Halfwords to Halfword Products +MIPS_addq_s_qh, // Add Fractional Halfword Vectors +MIPS_addq_s_pw, // Add Fractional Word Vectors +MIPS_muleu_s_qh_obr, // Multiply Unsigned Vector Right Bytes by Halfwords to Halfword Products +MIPS_subq_s_qh, // Subtract Fractional Halfword Vector +MIPS_subq_s_pw, // Subtract Fractional Word Vector +MIPS_mulq_rs_qh, // Multiply Vector Fractional Halfwords to Fractional Halfword Products +MIPS_cmpu_eq_qb, // Compare Vectors of Unsigned Byte Values +MIPS_cmp_eq_ph, // Compare Vectors of Signed Integer Halfword Values +MIPS_cmpgdu_eq_qb, // Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl +MIPS_cmpu_lt_qb, // Compare Vectors of Unsigned Byte Values +MIPS_cmp_lt_ph, // Compare Vectors of Signed Integer Halfword Values +MIPS_cmpgdu_lt_qb, // Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl +MIPS_cmpu_le_qb, // Compare Vectors of Unsigned Byte Values +MIPS_cmp_le_ph, // Compare Vectors of Signed Integer Halfword Values +MIPS_cmpgdu_le_qb, // Compare Unsigned Vector of Four Bytes and Write Result to GPR and DSPControl +MIPS_pick_qb, // Pick a Vector of Byte Values Based on Condition Code Bits +MIPS_pick_ph, // Pick a Vector of Halfword Values Based on Condition Code Bits +MIPS_cmpgu_eq_qb, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR +MIPS_precrq_qb_ph, // Precision Reduce Four Fractional Halfwords to Four Bytes +MIPS_precrq_ph_w, // Precision Reduce Fractional Words to Fractional Halfwords +MIPS_cmpgu_lt_qb, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR +MIPS_precr_qb_ph, // Precision Reduce Four Integer Halfwords to Four Bytes +MIPS_precrq_rs_ph_w, // Precision Reduce Fractional Words to Halfwords With Rounding and Saturation +MIPS_cmpgu_le_qb, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR +MIPS_packrl_ph, // Pack a Vector of Halfwords from Vector Halfword Sources +MIPS_precr_sra_ph_w, // Precision Reduce Two Integer Words to Halfwords after a Right Shift +MIPS_precrqu_s_qb_ph, // Precision Reduce Fractional Halfwords to Unsigned Bytes With Saturation +MIPS_precr_sra_r_ph_w, // Precision Reduce Two Integer Words to Halfwords after a Right Shift +MIPS_cmpu_eq_ob, // Compare Vectors of Unsigned Byte Values +MIPS_cmp_eq_qh, // Compare Vectors of Signed Integer Halfword Values +MIPS_cmp_eq_pw, // Compare Vectors of Signed Integer Word Values +MIPS_cmpu_lt_ob, // Compare Vectors of Unsigned Byte Values +MIPS_cmp_lt_qh, // Compare Vectors of Signed Integer Halfword Values +MIPS_cmp_lt_pw, // Compare Vectors of Signed Integer Word Values +MIPS_cmpu_le_ob, // Compare Vectors of Unsigned Byte Values +MIPS_cmp_le_qh, // Compare Vectors of Signed Integer Halfword Values +MIPS_cmp_le_pw, // Compare Vectors of Signed Integer Word Values +MIPS_pick_ob, // Pick a Vector of Byte Values Based on Condition Code Bits +MIPS_pick_qh, // Pick a Vector of Halfword Values Based on Condition Code Bits +MIPS_pick_pw, // Pick a Vector of Word Values Based on Condition Code Bits +MIPS_cmpgu_eq_ob, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR +MIPS_precrq_ob_qh, // Precision Reduce Fractional Halfwords to Fractional Bytes +MIPS_precrq_qh_pw, // Precision Reduce Fractional Words to Fractional Halfwords +MIPS_precrq_pw_l, // Precision Reduce Fractional Doublewords to Fractional Words +MIPS_cmpgu_lt_ob, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR +MIPS_precrq_rs_qh_pw, // Precision Reduce Fractional Words to Halfwords With Rounding and Saturation +MIPS_cmpgu_le_ob, // Compare Vectors of Unsigned Byte Values and Write Results to a GPR +MIPS_packrl_pw, // Pack a Vector of Words from Vector Word Sources +MIPS_precrqu_s_ob_qh, // Precision Reduce Fractional Halfwords to Unsigned Bytes With Saturation +MIPS_absq_s_qb, // Find Absolute Value of Four Fractional Byte Values +MIPS_absq_s_ph, // Find Absolute Value of Two Fractional Halfwords +MIPS_absq_s_w, // Find Absolute Value of Fractional Word +MIPS_repl_qb, // Replicate Immediate Integer into all Vector Element Positions +MIPS_repl_ph, // Replicate Immediate Integer into all Vector Element Positions +MIPS_replv_qb, // Replicate Byte into all Vector Element Positions +MIPS_replv_ph, // Replicate a Halfword into all Vector Element Positions +MIPS_bitrev, // Bit-Reverse Halfword +MIPS_precequ_ph_qbl, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceq_w_phl, // Precision Expand Fractional Halfword to Fractional Word Value +MIPS_preceu_ph_qbl, // Precision Expand Two Unsigned Bytes to Unsigned Halfword Values +MIPS_precequ_ph_qbr, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceq_w_phr, // Precision Expand Fractional Halfword to Fractional Word Value +MIPS_preceu_ph_qbr, // Precision Expand two Unsigned Bytes to Unsigned Halfword Values +MIPS_precequ_ph_qbla, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceu_ph_qbla, // Precision Expand Two Unsigned Bytes to Unsigned Halfword Values +MIPS_precequ_ph_qbra, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceu_ph_qbra, // Precision Expand Two Unsigned Bytes to Unsigned Halfword Values +MIPS_absq_s_qh, // Find Absolute Value of Four Fractional Halfwords +MIPS_absq_s_pw, // Find Absolute Value of Two Fractional Words +MIPS_repl_ob, // Replicate Immediate Integer into all Vector Element Positions +MIPS_repl_qh, // Replicate Immediate Integer into all Vector Element Positions +MIPS_repl_pw, // Replicate Immediate Integer into all Vector Element Positions +MIPS_replv_ob, // Replicate Byte into all Vector Element Positions +MIPS_replv_qh, // Replicate a Halfword into all Vector Element Positions +MIPS_replv_pw, // Replicate Word into all Vector Element Positions +MIPS_precequ_pw_qhl, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceq_pw_qhl, // Precision Expand Two Fractional Halfwords to Fractional Word Values +MIPS_preceq_s_l_pwl, // Precision Expand Fractional Word to Fractional Doubleword Value +MIPS_preceu_qh_obl, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values +MIPS_precequ_pw_qhr, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceq_pw_qhr, // Precision Expand Two Fractional Halfwords to Fractional Word Values +MIPS_preceq_s_l_pwr, // Precision Expand Fractional Word to Fractional Doubleword Value +MIPS_preceu_qh_obr, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values +MIPS_precequ_pw_qhla, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceq_pw_qhla, // Precision Expand Two Fractional Halfwords to Fractional Word Values +MIPS_preceu_qh_obla, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values +MIPS_precequ_pw_qhra, // Precision Expand two Unsigned Bytes to Fractional Halfword Values +MIPS_preceq_pw_qhra, // Precision Expand Two Fractional Halfwords to Fractional Word Values +MIPS_preceu_qh_obra, // Precision Expand Four Unsigned Bytes to Unsigned Halfword Values +MIPS_shll_qb, // Shift Left Logical Vector Quad Bytes +MIPS_shll_ph, // Shift Left Logical Vector Pair Halfwords +MIPS_shrl_qb, // Shift Right Logical Vector Quad Bytes +MIPS_shra_ph, // Shift Right Arithmetic Vector Pair Halfwords +MIPS_shrl_ph, // Shift Right Logical Two Halfwords +MIPS_shllv_qb, // Shift Left Logical Variable Vector Quad Bytes +MIPS_shllv_ph, // Shift Left Logical Variable Vector Pair Halfwords +MIPS_shrlv_qb, // Shift Right Logical Variable Vector Quad Bytes +MIPS_shrav_ph, // Shift Right Arithmetic Variable Vector Pair Halfwords +MIPS_shrlv_ph, // Shift Variable Right Logical Pair of Halfwords +MIPS_shra_qb, // Shift Right Arithmetic Vector of Four Bytes +MIPS_shll_s_ph, // Shift Left Logical Vector Pair Halfwords +MIPS_shll_s_w, // Shift Left Logical Word with Saturation +MIPS_shra_r_qb, // Shift Right Arithmetic Vector of Four Bytes +MIPS_shra_r_ph, // Shift Right Arithmetic Vector Pair Halfwords +MIPS_shra_r_w, // Shift Right Arithmetic Word with Rounding +MIPS_shrav_qb, // Shift Right Arithmetic Variable Vector of Four Bytes +MIPS_shllv_s_ph, // Shift Left Logical Variable Vector Pair Halfwords +MIPS_shllv_s_w, // Shift Left Logical Variable Vector Word +MIPS_shrav_r_qb, // Shift Right Arithmetic Variable Vector of Four Bytes +MIPS_shrav_r_ph, // Shift Right Arithmetic Variable Vector Pair Halfwords +MIPS_shrav_r_w, // Shift Right Arithmetic Variable Word with Rounding +MIPS_shll_ob, // Shift Left Logical Vector Octal Bytes +MIPS_shll_qh, // Shift Left Logical Vector Quad Halfwords +MIPS_shll_pw, // Shift Left Logical Vector Pair Words +MIPS_shrl_ob, // Shift Right Logical Vector Octal Bytes +MIPS_shra_qh, // Shift Right Arithmetic Vector Quad Halfwords +MIPS_shra_pw, // Shift Right Arithmetic Vector Pair Words +MIPS_shllv_ob, // Shift Left Logical Variable Vector Octal Bytes +MIPS_shllv_qh, // Shift Left Logical Variable Vector Quad Halfwords +MIPS_shllv_pw, // Shift Left Logical Variable Vector Pair Words +MIPS_shrlv_ob, // Shift Right Logical Variable Vector Octal Bytes +MIPS_shrav_qh, // Shift Right Arithmetic Variable Vector Quad Halfwords +MIPS_shrav_pw, // Shift Right Arithmetic Variable Vector Pair Words +MIPS_shll_s_qh, // Shift Left Logical Vector Quad Halfwords +MIPS_shll_s_pw, // Shift Left Logical Vector Pair Words +MIPS_shra_r_qh, // Shift Right Arithmetic Vector Quad Halfwords +MIPS_shra_r_pw, // Shift Right Arithmetic Vector Pair Words +MIPS_shllv_s_qh, // Shift Left Logical Variable Vector Quad Halfwords +MIPS_shllv_s_pw, // Shift Left Logical Variable Vector Pair Words +MIPS_shrav_r_qh, // Shift Right Arithmetic Variable Vector Quad Halfwords +MIPS_shrav_r_pw, // Shift Right Arithmetic Variable Vector Pair Words +MIPS_lwx, // Load Word Indexed +MIPS_ldx, // Load Doubleword Indexed +MIPS_lhx, // Load Halfword Indexed +MIPS_lbux, // Load Unsigned Byte Indexed +MIPS_dpa_w_ph, // Dot Product with Accumulate on Vector Integer Halfword Elements +MIPS_dpax_w_ph, // Cross Dot Product with Accumulate on Vector Integer Halfword Elements +MIPS_maq_sa_w_phl, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dpaqx_s_w_ph, // Cross Dot Product with Accumulation on Fractional Halfword Elements +MIPS_dps_w_ph, // Dot Product with Subtract on Vector Integer Half-Word Elements +MIPS_dpsx_w_ph, // Cross Dot Product with Subtract on Vector Integer Halfword Elements +MIPS_dpsqx_s_w_ph, // Cross Dot Product with Subtraction on Fractional Halfword Elements +MIPS_mulsa_w_ph, // Multiply and Subtract Vector Integer Halfword Elements and Accumulate +MIPS_maq_sa_w_phr, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dpaqx_sa_w_ph, // Cross Dot Product with Accumulation on Fractional Halfword Elements +MIPS_dpau_h_qbl, // Dot Product with Accumulate on Vector Unsigned Byte Elements +MIPS_dpsu_h_qbl, // Dot Product with Subtraction on Vector Unsigned Byte Elements +MIPS_dpsqx_sa_w_ph, // Cross Dot Product with Subtraction on Fractional Halfword Elements +MIPS_dpaq_s_w_ph, // Dot Product with Accumulation on Fractional Halfword Elements +MIPS_dpaq_sa_l_w, // Dot Product with Accumulate on Fractional Word Element +MIPS_maq_s_w_phl, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dpsq_s_w_ph, // Dot Product with Subtraction on Fractional Halfword Elements +MIPS_dpsq_sa_l_w, // Dot Product with Subtraction on Fractional Word Element +MIPS_mulsaq_s_w_ph, // Multiply And Subtract Vector Fractional Halfwords And Accumulate +MIPS_maq_s_w_phr, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dpau_h_qbr, // Dot Product with Accumulate on Vector Unsigned Byte Elements +MIPS_dpsu_h_qbr, // Dot Product with Subtraction on Vector Unsigned Byte Elements +MIPS_maq_sa_w_qhll, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_maq_sa_w_qhlr, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dmadd, // Multiply Vector Words And Accumulate +MIPS_dmsub, // Multiply Vector Words And Subtract From Accumulator +MIPS_maq_sa_w_qhrl, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dpau_h_obl, // Dot Product with Accumulate on Vector Unsigned Byte Elements +MIPS_dpsu_h_obl, // Dot Product with Subtract on Vector Unsigned Byte Elements +MIPS_maq_sa_w_qhrr, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dpaq_s_w_qh, // Dot Product with Accumulation on Fractional Halfword Elements +MIPS_dpaq_sa_l_pw, // Dot Product with Accumulate on Fractional Word Elements +MIPS_maq_s_w_qhll, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_maq_s_l_pwl, // Multiply with Accumulate Single Vector Fractional Word Element +MIPS_dpsq_s_w_qh, // Dot Product with Subtraction on Fractional Halfword Elements +MIPS_dpsq_sa_l_pw, // Dot Product with Subtraction on Fractional Word Elements +MIPS_maq_s_w_qhlr, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dmaddu, // Multiply Vector Unsigned Words And Accumulate +MIPS_mulsaq_s_w_qh, // Multiply And Subtract Vector Fractional Halfwords And Accumulate +MIPS_mulsaq_s_l_pw, // Multiply And Subtract Vector Fractional Words And Accumulate +MIPS_maq_s_w_qhrl, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_maq_s_l_pwr, // Multiply with Accumulate Single Vector Fractional Word Element +MIPS_dpau_h_obr, // Dot Product with Accumulate on Vector Unsigned Byte Elements +MIPS_dpsu_h_obr, // Dot Product with Subtract on Vector Unsigned Byte Elements +MIPS_maq_s_w_qhrr, // Multiply with Accumulate Single Vector Fractional Halfword Element +MIPS_dmsubu, // Multiply Vector Unsigned Words And Subtract From Accumulator +MIPS_extr_w, // Extract Word Value With Right Shift From Accumulator to GPR +MIPS_extrv_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR +MIPS_extp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR +MIPS_extpdp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos +MIPS_rddsp, // Read DSPControl Register Fields to a GPR +MIPS_shilo, // Shift an Accumulator Value Leaving the Result in the Same Accumulator +MIPS_extpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR +MIPS_extpdpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos +MIPS_wrdsp, // Write Fields to DSPControl Register from a GPR +MIPS_shilov, // Variable Shift of Accumulator Value Leaving the Result in the Same Accumulator +MIPS_extr_r_w, // Extract Word Value With Right Shift And Rounding From Accumulator to GPR +MIPS_extrv_r_w, // Extract Word Value With Variable Right Shift And Rounding From Accumulator to GPR +MIPS_extr_rs_w, // Extract Word Value With Right Shift From Accumulator to GPR +MIPS_extr_s_h, // Extract Halfword Value From Accumulator to GPR With Right Shift and Saturate +MIPS_extrv_rs_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR +MIPS_extrv_s_h, // Extract Halfword Value Variable From Accumulator to GPR With Right Shift and Saturate +MIPS_mthlip, // Copy LO to HI and a GPR to LO and Increment Pos by 32 +MIPS_dextr_w, // Extract Word Value With Right Shift From Accumulator to GPR +MIPS_dextr_l, // Extract Doubleword Value With Right Shift From Accumulator to GPR +MIPS_dextrv_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR +MIPS_dextrv_l, // Extract Doubleword Value With Variable Right Shift From Accumulator to GPR +MIPS_dextp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR +MIPS_dextpdp, // Extract Fixed Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos +MIPS_dshilo, // Shift an Accumulator Value Leaving the Result in the Same Accumulator +MIPS_dextpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR +MIPS_dextpdpv, // Extract Variable Bitfield From Arbitrary Position in Accumulator to GPR and Decrement Pos +MIPS_dshilov, // Variable Shift of Accumulator Value Leaving the Result in the Same Accumulator +MIPS_dextr_r_w, // Extract Word Value With Right Shift And Rounding From Accumulator to GPR +MIPS_dextr_r_l, // Extract Doubleword Value With Right Shift And Rounding From Accumulator to GPR +MIPS_dextrv_r_w, // Extract Word Value With Variable Right Shift And Rounding From Accumulator to GPR +MIPS_dextrv_r_l, // Extract Doubleword Value With Variable Right Shift And Rounding From Accumulator to GPR +MIPS_dextr_rs_w, // Extract Word Value With Right Shift From Accumulator to GPR +MIPS_dextr_s_h, // Extract Halfword Value From Accumulator to GPR With Right Shift and Saturate +MIPS_dextr_rs_l, // Extract Doubleword Value With Right Shift From Accumulator to GPR +MIPS_dextrv_rs_w, // Extract Word Value With Variable Right Shift From Accumulator to GPR +MIPS_dextrv_s_h, // Extract Halfword Value Variable From Accumulator to GPR With Right Shift and Saturate +MIPS_dextrv_rs_l, // Extract Doubleword Value With Variable Right Shift From Accumulator to GPR +MIPS_dmthlip, // Copy LO to HI and a GPR to LO and Increment Pos by 64 +MIPS_adduh_qb, // Unsigned Add Vector Quad-Bytes And Right Shift to Halve Results +MIPS_addqh_ph, // Add Fractional Halfword Vectors And Shift Right to Halve Results +MIPS_addqh_w, // Add Fractional Words And Shift Right to Halve Results +MIPS_subuh_qb, // Subtract Unsigned Bytes And Right Shift to Halve Results +MIPS_subqh_ph, // Subtract Fractional Halfword Vectors And Shift Right to Halve Results +MIPS_subqh_w, // Subtract Fractional Words And Shift Right to Halve Results +MIPS_adduh_r_qb, // Unsigned Add Vector Quad-Bytes And Right Shift to Halve Results +MIPS_addqh_r_ph, // Add Fractional Halfword Vectors And Shift Right to Halve Results +MIPS_addqh_r_w, // Add Fractional Words And Shift Right to Halve Results +MIPS_subuh_r_qb, // Subtract Unsigned Bytes And Right Shift to Halve Results +MIPS_subqh_r_ph, // Subtract Fractional Halfword Vectors And Shift Right to Halve Results +MIPS_subqh_r_w, // Subtract Fractional Words And Shift Right to Halve Results +MIPS_mul_ph, // Multiply Vector Integer HalfWords to Same Size Products +MIPS_mul_s_ph, // Multiply Vector Integer HalfWords to Same Size Products +MIPS_mulq_s_w, // Multiply Fractional Words to Same Size Product with Saturation +MIPS_mulq_rs_w, // Multiply Fractional Words to Same Size Product with Saturation and Rounding +MIPS_append, // Left Shift and Append Bits to the LSB +MIPS_balign, // Byte Align Contents from Two Registers +MIPS_prepend, // Right Shift and Prepend Bits to the MSB + +// Cavium Octeon II instructions +MIPS_laa, // Load Atomic Add Word +MIPS_laad, // Load Atomic Add Doubleword +MIPS_lac, // Load Atomic Clear Word +MIPS_lacd, // Load Atomic Clear Doubleword +MIPS_lad, // Load Atomic Decrement Word +MIPS_ladd, // Load Atomic Decrement Doubleword +MIPS_lai, // Load Atomic Increment Word +MIPS_laid, // Load Atomic Increment Doubleword +MIPS_las, // Load Atomic Set Word +MIPS_lasd, // Load Atomic Set Doubleword +MIPS_law, // Load Atomic Swap Word +MIPS_lawd, // Load Atomic Swap Doubleword +// we don't know the following mnemonics for sure +MIPS_lbx, // Load Byte Indexed +MIPS_lhux, // Load Halfword Unsigned Indexed +MIPS_lwux, // Load Word Unsigned Indexed +MIPS_qmac_00, // Q15 Multiply Accumulate +MIPS_qmac_01, // Q15 Multiply Accumulate +MIPS_qmac_02, // Q15 Multiply Accumulate +MIPS_qmac_03, // Q15 Multiply Accumulate +MIPS_qmacs_00, // Q15 Multiply Accumulate +MIPS_qmacs_01, // Q15 Multiply Accumulate +MIPS_qmacs_02, // Q15 Multiply Accumulate +MIPS_qmacs_03, // Q15 Multiply Accumulate +MIPS_zcb, // Zero Cache Block +MIPS_zcbt, // Zero Cache Block + +// MSA ASE +// some of these have the same name as existing mnemonics; to avoid ambiguity +// we use an msa_ prefix on all of them +MIPS_msa_sll_b, // Vector Shift Left +MIPS_msa_sll_h, // Vector Shift Left +MIPS_msa_sll_w, // Vector Shift Left +MIPS_msa_sll_d, // Vector Shift Left +MIPS_msa_slli_b, // Immediate Shift Left +MIPS_msa_slli_h, // Immediate Shift Left +MIPS_msa_slli_w, // Immediate Shift Left +MIPS_msa_slli_d, // Immediate Shift Left +MIPS_msa_sra_b, // Vector Shift Right Arithmetic +MIPS_msa_sra_h, // Vector Shift Right Arithmetic +MIPS_msa_sra_w, // Vector Shift Right Arithmetic +MIPS_msa_sra_d, // Vector Shift Right Arithmetic +MIPS_msa_srai_b, // Immediate Shift Right Arithmetic +MIPS_msa_srai_h, // Immediate Shift Right Arithmetic +MIPS_msa_srai_w, // Immediate Shift Right Arithmetic +MIPS_msa_srai_d, // Immediate Shift Right Arithmetic +MIPS_msa_srl_b, // Vector Shift Right Logical +MIPS_msa_srl_h, // Vector Shift Right Logical +MIPS_msa_srl_w, // Vector Shift Right Logical +MIPS_msa_srl_d, // Vector Shift Right Logical +MIPS_msa_srli_b, // Immediate Shift Right Logical +MIPS_msa_srli_h, // Immediate Shift Right Logical +MIPS_msa_srli_w, // Immediate Shift Right Logical +MIPS_msa_srli_d, // Immediate Shift Right Logical +MIPS_msa_bclr_b, // Vector Bit Clear +MIPS_msa_bclr_h, // Vector Bit Clear +MIPS_msa_bclr_w, // Vector Bit Clear +MIPS_msa_bclr_d, // Vector Bit Clear +MIPS_msa_bclri_b, // Immediate Bit Clear +MIPS_msa_bclri_h, // Immediate Bit Clear +MIPS_msa_bclri_w, // Immediate Bit Clear +MIPS_msa_bclri_d, // Immediate Bit Clear +MIPS_msa_bset_b, // Vector Bit Set +MIPS_msa_bset_h, // Vector Bit Set +MIPS_msa_bset_w, // Vector Bit Set +MIPS_msa_bset_d, // Vector Bit Set +MIPS_msa_bseti_b, // Immediate Bit Set +MIPS_msa_bseti_h, // Immediate Bit Set +MIPS_msa_bseti_w, // Immediate Bit Set +MIPS_msa_bseti_d, // Immediate Bit Set +MIPS_msa_bneg_b, // Vector Bit Negate +MIPS_msa_bneg_h, // Vector Bit Negate +MIPS_msa_bneg_w, // Vector Bit Negate +MIPS_msa_bneg_d, // Vector Bit Negate +MIPS_msa_bnegi_b, // Immediate Bit Negate +MIPS_msa_bnegi_h, // Immediate Bit Negate +MIPS_msa_bnegi_w, // Immediate Bit Negate +MIPS_msa_bnegi_d, // Immediate Bit Negate +MIPS_msa_binsl_b, // Vector Bit Insert Left +MIPS_msa_binsl_h, // Vector Bit Insert Left +MIPS_msa_binsl_w, // Vector Bit Insert Left +MIPS_msa_binsl_d, // Vector Bit Insert Left +MIPS_msa_binsli_b, // Immediate Bit Insert Left +MIPS_msa_binsli_h, // Immediate Bit Insert Left +MIPS_msa_binsli_w, // Immediate Bit Insert Left +MIPS_msa_binsli_d, // Immediate Bit Insert Left +MIPS_msa_binsr_b, // Vector Bit Insert Right +MIPS_msa_binsr_h, // Vector Bit Insert Right +MIPS_msa_binsr_w, // Vector Bit Insert Right +MIPS_msa_binsr_d, // Vector Bit Insert Right +MIPS_msa_binsri_b, // Immediate Bit Insert Right +MIPS_msa_binsri_h, // Immediate Bit Insert Right +MIPS_msa_binsri_w, // Immediate Bit Insert Right +MIPS_msa_binsri_d, // Immediate Bit Insert Right +MIPS_msa_addv_b, // Vector Add +MIPS_msa_addv_h, // Vector Add +MIPS_msa_addv_w, // Vector Add +MIPS_msa_addv_d, // Vector Add +MIPS_msa_addvi_b, // Immediate Add +MIPS_msa_addvi_h, // Immediate Add +MIPS_msa_addvi_w, // Immediate Add +MIPS_msa_addvi_d, // Immediate Add +MIPS_msa_subv_b, // Vector Subtract +MIPS_msa_subv_h, // Vector Subtract +MIPS_msa_subv_w, // Vector Subtract +MIPS_msa_subv_d, // Vector Subtract +MIPS_msa_subvi_b, // Immediate Subtract +MIPS_msa_subvi_h, // Immediate Subtract +MIPS_msa_subvi_w, // Immediate Subtract +MIPS_msa_subvi_d, // Immediate Subtract +MIPS_msa_max_s_b, // Vector Signed Maximum +MIPS_msa_max_s_h, // Vector Signed Maximum +MIPS_msa_max_s_w, // Vector Signed Maximum +MIPS_msa_max_s_d, // Vector Signed Maximum +MIPS_msa_maxi_s_b, // Immediate Signed Maximum +MIPS_msa_maxi_s_h, // Immediate Signed Maximum +MIPS_msa_maxi_s_w, // Immediate Signed Maximum +MIPS_msa_maxi_s_d, // Immediate Signed Maximum +MIPS_msa_max_u_b, // Vector Unsigned Maximum +MIPS_msa_max_u_h, // Vector Unsigned Maximum +MIPS_msa_max_u_w, // Vector Unsigned Maximum +MIPS_msa_max_u_d, // Vector Unsigned Maximum +MIPS_msa_maxi_u_b, // Immediate Unsigned Maximum +MIPS_msa_maxi_u_h, // Immediate Unsigned Maximum +MIPS_msa_maxi_u_w, // Immediate Unsigned Maximum +MIPS_msa_maxi_u_d, // Immediate Unsigned Maximum +MIPS_msa_min_s_b, // Vector Signed Minimum +MIPS_msa_min_s_h, // Vector Signed Minimum +MIPS_msa_min_s_w, // Vector Signed Minimum +MIPS_msa_min_s_d, // Vector Signed Minimum +MIPS_msa_mini_s_b, // Immediate Signed Minimum +MIPS_msa_mini_s_h, // Immediate Signed Minimum +MIPS_msa_mini_s_w, // Immediate Signed Minimum +MIPS_msa_mini_s_d, // Immediate Signed Minimum +MIPS_msa_min_u_b, // Vector Unsigned Minimum +MIPS_msa_min_u_h, // Vector Unsigned Minimum +MIPS_msa_min_u_w, // Vector Unsigned Minimum +MIPS_msa_min_u_d, // Vector Unsigned Minimum +MIPS_msa_mini_u_b, // Immediate Unsigned Minimum +MIPS_msa_mini_u_h, // Immediate Unsigned Minimum +MIPS_msa_mini_u_w, // Immediate Unsigned Minimum +MIPS_msa_mini_u_d, // Immediate Unsigned Minimum +MIPS_msa_max_a_b, // Vector Maximum Based on Absolute Values +MIPS_msa_max_a_h, // Vector Maximum Based on Absolute Values +MIPS_msa_max_a_w, // Vector Maximum Based on Absolute Values +MIPS_msa_max_a_d, // Vector Maximum Based on Absolute Values +MIPS_msa_min_a_b, // Vector Minimum Based on Absolute Value +MIPS_msa_min_a_h, // Vector Minimum Based on Absolute Value +MIPS_msa_min_a_w, // Vector Minimum Based on Absolute Value +MIPS_msa_min_a_d, // Vector Minimum Based on Absolute Value +MIPS_msa_ceq_b, // Vector Compare Equal +MIPS_msa_ceq_h, // Vector Compare Equal +MIPS_msa_ceq_w, // Vector Compare Equal +MIPS_msa_ceq_d, // Vector Compare Equal +MIPS_msa_ceqi_b, // Immediate Compare Equal +MIPS_msa_ceqi_h, // Immediate Compare Equal +MIPS_msa_ceqi_w, // Immediate Compare Equal +MIPS_msa_ceqi_d, // Immediate Compare Equal +MIPS_msa_clt_s_b, // Vector Compare Signed Less Than +MIPS_msa_clt_s_h, // Vector Compare Signed Less Than +MIPS_msa_clt_s_w, // Vector Compare Signed Less Than +MIPS_msa_clt_s_d, // Vector Compare Signed Less Than +MIPS_msa_clti_s_b, // Immediate Compare Signed Less Than +MIPS_msa_clti_s_h, // Immediate Compare Signed Less Than +MIPS_msa_clti_s_w, // Immediate Compare Signed Less Than +MIPS_msa_clti_s_d, // Immediate Compare Signed Less Than +MIPS_msa_clt_u_b, // Vector Compare Unsigned Less Than +MIPS_msa_clt_u_h, // Vector Compare Unsigned Less Than +MIPS_msa_clt_u_w, // Vector Compare Unsigned Less Than +MIPS_msa_clt_u_d, // Vector Compare Unsigned Less Than +MIPS_msa_clti_u_b, // Immediate Compare Unsigned Less Than +MIPS_msa_clti_u_h, // Immediate Compare Unsigned Less Than +MIPS_msa_clti_u_w, // Immediate Compare Unsigned Less Than +MIPS_msa_clti_u_d, // Immediate Compare Unsigned Less Than +MIPS_msa_cle_s_b, // Vector Compare Signed Less Than or Equal +MIPS_msa_cle_s_h, // Vector Compare Signed Less Than or Equal +MIPS_msa_cle_s_w, // Vector Compare Signed Less Than or Equal +MIPS_msa_cle_s_d, // Vector Compare Signed Less Than or Equal +MIPS_msa_clei_s_b, // Immediate Compare Signed Less Than or Equal +MIPS_msa_clei_s_h, // Immediate Compare Signed Less Than or Equal +MIPS_msa_clei_s_w, // Immediate Compare Signed Less Than or Equal +MIPS_msa_clei_s_d, // Immediate Compare Signed Less Than or Equal +MIPS_msa_cle_u_b, // Vector Compare Unsigned Less Than or Equal +MIPS_msa_cle_u_h, // Vector Compare Unsigned Less Than or Equal +MIPS_msa_cle_u_w, // Vector Compare Unsigned Less Than or Equal +MIPS_msa_cle_u_d, // Vector Compare Unsigned Less Than or Equal +MIPS_msa_clei_u_b, // Immediate Compare Unsigned Less Than or Equal +MIPS_msa_clei_u_h, // Immediate Compare Unsigned Less Than or Equal +MIPS_msa_clei_u_w, // Immediate Compare Unsigned Less Than or Equal +MIPS_msa_clei_u_d, // Immediate Compare Unsigned Less Than or Equal +MIPS_msa_ld_b, // Vector Load +MIPS_msa_ld_h, // Vector Load +MIPS_msa_ld_w, // Vector Load +MIPS_msa_ld_d, // Vector Load +MIPS_msa_st_b, // Vector Store +MIPS_msa_st_h, // Vector Store +MIPS_msa_st_w, // Vector Store +MIPS_msa_st_d, // Vector Store +MIPS_msa_sat_s_b, // Immediate Signed Saturate +MIPS_msa_sat_s_h, // Immediate Signed Saturate +MIPS_msa_sat_s_w, // Immediate Signed Saturate +MIPS_msa_sat_s_d, // Immediate Signed Saturate +MIPS_msa_sat_u_b, // Immediate Unsigned Saturate +MIPS_msa_sat_u_h, // Immediate Unsigned Saturate +MIPS_msa_sat_u_w, // Immediate Unsigned Saturate +MIPS_msa_sat_u_d, // Immediate Unsigned Saturate +MIPS_msa_add_a_b, // Vector Add Absolute Values +MIPS_msa_add_a_h, // Vector Add Absolute Values +MIPS_msa_add_a_w, // Vector Add Absolute Values +MIPS_msa_add_a_d, // Vector Add Absolute Values +MIPS_msa_adds_a_b, // Vector Saturated Add of Absolute Values +MIPS_msa_adds_a_h, // Vector Saturated Add of Absolute Values +MIPS_msa_adds_a_w, // Vector Saturated Add of Absolute Values +MIPS_msa_adds_a_d, // Vector Saturated Add of Absolute Values +MIPS_msa_adds_s_b, // Vector Signed Saturated Add of Signed Values +MIPS_msa_adds_s_h, // Vector Signed Saturated Add of Signed Values +MIPS_msa_adds_s_w, // Vector Signed Saturated Add of Signed Values +MIPS_msa_adds_s_d, // Vector Signed Saturated Add of Signed Values +MIPS_msa_adds_u_b, // Vector Unsigned Saturated Add of Unsigned Values +MIPS_msa_adds_u_h, // Vector Unsigned Saturated Add of Unsigned Values +MIPS_msa_adds_u_w, // Vector Unsigned Saturated Add of Unsigned Values +MIPS_msa_adds_u_d, // Vector Unsigned Saturated Add of Unsigned Values +MIPS_msa_ave_s_b, // Vector Signed Average +MIPS_msa_ave_s_h, // Vector Signed Average +MIPS_msa_ave_s_w, // Vector Signed Average +MIPS_msa_ave_s_d, // Vector Signed Average +MIPS_msa_ave_u_b, // Vector Unsigned Average +MIPS_msa_ave_u_h, // Vector Unsigned Average +MIPS_msa_ave_u_w, // Vector Unsigned Average +MIPS_msa_ave_u_d, // Vector Unsigned Average +MIPS_msa_aver_s_b, // Vector Signed Average Rounded +MIPS_msa_aver_s_h, // Vector Signed Average Rounded +MIPS_msa_aver_s_w, // Vector Signed Average Rounded +MIPS_msa_aver_s_d, // Vector Signed Average Rounded +MIPS_msa_aver_u_b, // Vector Unsigned Average Rounded +MIPS_msa_aver_u_h, // Vector Unsigned Average Rounded +MIPS_msa_aver_u_w, // Vector Unsigned Average Rounded +MIPS_msa_aver_u_d, // Vector Unsigned Average Rounded +MIPS_msa_subs_s_b, // Vector Signed Saturated Subtract of Signed Values +MIPS_msa_subs_s_h, // Vector Signed Saturated Subtract of Signed Values +MIPS_msa_subs_s_w, // Vector Signed Saturated Subtract of Signed Values +MIPS_msa_subs_s_d, // Vector Signed Saturated Subtract of Signed Values +MIPS_msa_subs_u_b, // Vector Unsigned Saturated Subtract of Unsigned Values +MIPS_msa_subs_u_h, // Vector Unsigned Saturated Subtract of Unsigned Values +MIPS_msa_subs_u_w, // Vector Unsigned Saturated Subtract of Unsigned Values +MIPS_msa_subs_u_d, // Vector Unsigned Saturated Subtract of Unsigned Values +MIPS_msa_subsus_u_b, // Vector Unsigned Saturated Subtract of Signed from Unsigned +MIPS_msa_subsus_u_h, // Vector Unsigned Saturated Subtract of Signed from Unsigned +MIPS_msa_subsus_u_w, // Vector Unsigned Saturated Subtract of Signed from Unsigned +MIPS_msa_subsus_u_d, // Vector Unsigned Saturated Subtract of Signed from Unsigned +MIPS_msa_subsuu_s_b, // Vector Signed Saturated Subtract of Unsigned Values +MIPS_msa_subsuu_s_h, // Vector Signed Saturated Subtract of Unsigned Values +MIPS_msa_subsuu_s_w, // Vector Signed Saturated Subtract of Unsigned Values +MIPS_msa_subsuu_s_d, // Vector Signed Saturated Subtract of Unsigned Values +MIPS_msa_asub_s_b, // Vector Absolute Values of Signed Subtract +MIPS_msa_asub_s_h, // Vector Absolute Values of Signed Subtract +MIPS_msa_asub_s_w, // Vector Absolute Values of Signed Subtract +MIPS_msa_asub_s_d, // Vector Absolute Values of Signed Subtract +MIPS_msa_asub_u_b, // Vector Absolute Values of Unsigned Subtract +MIPS_msa_asub_u_h, // Vector Absolute Values of Unsigned Subtract +MIPS_msa_asub_u_w, // Vector Absolute Values of Unsigned Subtract +MIPS_msa_asub_u_d, // Vector Absolute Values of Unsigned Subtract +MIPS_msa_mulv_b, // Vector Multiply +MIPS_msa_mulv_h, // Vector Multiply +MIPS_msa_mulv_w, // Vector Multiply +MIPS_msa_mulv_d, // Vector Multiply +MIPS_msa_maddv_b, // Vector Multiply and Add +MIPS_msa_maddv_h, // Vector Multiply and Add +MIPS_msa_maddv_w, // Vector Multiply and Add +MIPS_msa_maddv_d, // Vector Multiply and Add +MIPS_msa_msubv_b, // Vector Multiply and Subtract +MIPS_msa_msubv_h, // Vector Multiply and Subtract +MIPS_msa_msubv_w, // Vector Multiply and Subtract +MIPS_msa_msubv_d, // Vector Multiply and Subtract +MIPS_msa_div_s_b, // Vector Signed Divide +MIPS_msa_div_s_h, // Vector Signed Divide +MIPS_msa_div_s_w, // Vector Signed Divide +MIPS_msa_div_s_d, // Vector Signed Divide +MIPS_msa_div_u_b, // Vector Unsigned Divide +MIPS_msa_div_u_h, // Vector Unsigned Divide +MIPS_msa_div_u_w, // Vector Unsigned Divide +MIPS_msa_div_u_d, // Vector Unsigned Divide +MIPS_msa_mod_s_b, // Vector Signed Modulo +MIPS_msa_mod_s_h, // Vector Signed Modulo +MIPS_msa_mod_s_w, // Vector Signed Modulo +MIPS_msa_mod_s_d, // Vector Signed Modulo +MIPS_msa_mod_u_b, // Vector Unsigned Modulo +MIPS_msa_mod_u_h, // Vector Unsigned Modulo +MIPS_msa_mod_u_w, // Vector Unsigned Modulo +MIPS_msa_mod_u_d, // Vector Unsigned Modulo +MIPS_msa_dotp_s_h, // Vector Signed Dot Product +MIPS_msa_dotp_s_w, // Vector Signed Dot Product +MIPS_msa_dotp_s_d, // Vector Signed Dot Product +MIPS_msa_dotp_u_h, // Vector Unsigned Dot Product +MIPS_msa_dotp_u_w, // Vector Unsigned Dot Product +MIPS_msa_dotp_u_d, // Vector Unsigned Dot Product +MIPS_msa_dpadd_s_h, // Vector Signed Dot Product and Add +MIPS_msa_dpadd_s_w, // Vector Signed Dot Product and Add +MIPS_msa_dpadd_s_d, // Vector Signed Dot Product and Add +MIPS_msa_dpadd_u_h, // Vector Unsigned Dot Product and Add +MIPS_msa_dpadd_u_w, // Vector Unsigned Dot Product and Add +MIPS_msa_dpadd_u_d, // Vector Unsigned Dot Product and Add +MIPS_msa_dpsub_s_h, // Vector Signed Dot Product and Subtract +MIPS_msa_dpsub_s_w, // Vector Signed Dot Product and Subtract +MIPS_msa_dpsub_s_d, // Vector Signed Dot Product and Subtract +MIPS_msa_dpsub_u_h, // Vector Unsigned Dot Product and Subtract +MIPS_msa_dpsub_u_w, // Vector Unsigned Dot Product and Subtract +MIPS_msa_dpsub_u_d, // Vector Unsigned Dot Product and Subtract +MIPS_msa_sld_b, // GPR Columns Slide +MIPS_msa_sld_h, // GPR Columns Slide +MIPS_msa_sld_w, // GPR Columns Slide +MIPS_msa_sld_d, // GPR Columns Slide +MIPS_msa_sldi_b, // Immediate Columns Slide +MIPS_msa_sldi_h, // Immediate Columns Slide +MIPS_msa_sldi_w, // Immediate Columns Slide +MIPS_msa_sldi_d, // Immediate Columns Slide +MIPS_msa_splat_b, // GPR Element Splat +MIPS_msa_splat_h, // GPR Element Splat +MIPS_msa_splat_w, // GPR Element Splat +MIPS_msa_splat_d, // GPR Element Splat +MIPS_msa_splati_b, // Immediate Element Splat +MIPS_msa_splati_h, // Immediate Element Splat +MIPS_msa_splati_w, // Immediate Element Splat +MIPS_msa_splati_d, // Immediate Element Splat +MIPS_msa_pckev_b, // Vector Pack Even +MIPS_msa_pckev_h, // Vector Pack Even +MIPS_msa_pckev_w, // Vector Pack Even +MIPS_msa_pckev_d, // Vector Pack Even +MIPS_msa_pckod_b, // Vector Pack Odd +MIPS_msa_pckod_h, // Vector Pack Odd +MIPS_msa_pckod_w, // Vector Pack Odd +MIPS_msa_pckod_d, // Vector Pack Odd +MIPS_msa_ilvl_b, // Vector Interleave Left +MIPS_msa_ilvl_h, // Vector Interleave Left +MIPS_msa_ilvl_w, // Vector Interleave Left +MIPS_msa_ilvl_d, // Vector Interleave Left +MIPS_msa_ilvr_b, // Vector Interleave Right +MIPS_msa_ilvr_h, // Vector Interleave Right +MIPS_msa_ilvr_w, // Vector Interleave Right +MIPS_msa_ilvr_d, // Vector Interleave Right +MIPS_msa_ilvev_b, // Vector Interleave Even +MIPS_msa_ilvev_h, // Vector Interleave Even +MIPS_msa_ilvev_w, // Vector Interleave Even +MIPS_msa_ilvev_d, // Vector Interleave Even +MIPS_msa_ilvod_b, // Vector Interleave Odd +MIPS_msa_ilvod_h, // Vector Interleave Odd +MIPS_msa_ilvod_w, // Vector Interleave Odd +MIPS_msa_ilvod_d, // Vector Interleave Odd +MIPS_msa_vshf_b, // Vector Data Preserving Shuffle +MIPS_msa_vshf_h, // Vector Data Preserving Shuffle +MIPS_msa_vshf_w, // Vector Data Preserving Shuffle +MIPS_msa_vshf_d, // Vector Data Preserving Shuffle +MIPS_msa_srar_b, // Vector Shift Right Arithmetic Rounded +MIPS_msa_srar_h, // Vector Shift Right Arithmetic Rounded +MIPS_msa_srar_w, // Vector Shift Right Arithmetic Rounded +MIPS_msa_srar_d, // Vector Shift Right Arithmetic Rounded +MIPS_msa_srari_b, // Immediate Shift Right Arithmetic Rounded +MIPS_msa_srari_h, // Immediate Shift Right Arithmetic Rounded +MIPS_msa_srari_w, // Immediate Shift Right Arithmetic Rounded +MIPS_msa_srari_d, // Immediate Shift Right Arithmetic Rounded +MIPS_msa_srlr_b, // Vector Shift Right Logical Rounded +MIPS_msa_srlr_h, // Vector Shift Right Logical Rounded +MIPS_msa_srlr_w, // Vector Shift Right Logical Rounded +MIPS_msa_srlr_d, // Vector Shift Right Logical Rounded +MIPS_msa_srlri_b, // Immediate Shift Right Logical Rounded +MIPS_msa_srlri_h, // Immediate Shift Right Logical Rounded +MIPS_msa_srlri_w, // Immediate Shift Right Logical Rounded +MIPS_msa_srlri_d, // Immediate Shift Right Logical Rounded +MIPS_msa_hadd_s_h, // Vector Signed Horizontal Add +MIPS_msa_hadd_s_w, // Vector Signed Horizontal Add +MIPS_msa_hadd_s_d, // Vector Signed Horizontal Add +MIPS_msa_hadd_u_h, // Vector Unsigned Horizontal Add +MIPS_msa_hadd_u_w, // Vector Unsigned Horizontal Add +MIPS_msa_hadd_u_d, // Vector Unsigned Horizontal Add +MIPS_msa_hsub_s_h, // Vector Signed Horizontal Subtract +MIPS_msa_hsub_s_w, // Vector Signed Horizontal Subtract +MIPS_msa_hsub_s_d, // Vector Signed Horizontal Subtract +MIPS_msa_hsub_u_h, // Vector Unsigned Horizontal Subtract +MIPS_msa_hsub_u_w, // Vector Unsigned Horizontal Subtract +MIPS_msa_hsub_u_d, // Vector Unsigned Horizontal Subtract +MIPS_msa_and_v, // Vector Logical And +MIPS_msa_andi_b, // Immediate Logical And +MIPS_msa_or_v, // Vector Logical Or +MIPS_msa_ori_b, // Immediate Logical Or +MIPS_msa_nor_v, // Vector Logical Negated Or +MIPS_msa_nori_b, // Immediate Logical Negated Or +MIPS_msa_xor_v, // Vector Logical Exclusive Or +MIPS_msa_xori_b, // Immediate Logical Exclusive Or +MIPS_msa_bmnz_v, // Vector Bit Move If Not Zero +MIPS_msa_bmnzi_b, // Immediate Bit Move If Not Zero +MIPS_msa_bmz_v, // Vector Bit Move If Zero +MIPS_msa_bmzi_b, // Immediate Bit Move If Zero +MIPS_msa_bsel_v, // Vector Bit Select +MIPS_msa_bseli_b, // Immediate Bit Select +MIPS_msa_shf_b, // Immediate Set Shuffle Elements +MIPS_msa_shf_h, // Immediate Set Shuffle Elements +MIPS_msa_shf_w, // Immediate Set Shuffle Elements +MIPS_msa_bnz_v, // Immediate Branch If Not Zero (At Least One Element of Any Format Is Not Zero) +MIPS_msa_bz_v, // Immediate Branch If Zero (All Elements of Any Format Are Zero) +MIPS_msa_fill_b, // Vector Fill from GPR +MIPS_msa_fill_h, // Vector Fill from GPR +MIPS_msa_fill_w, // Vector Fill from GPR +MIPS_msa_fill_d, // Vector Fill from GPR +MIPS_msa_pcnt_b, // Vector Population Count +MIPS_msa_pcnt_h, // Vector Population Count +MIPS_msa_pcnt_w, // Vector Population Count +MIPS_msa_pcnt_d, // Vector Population Count +MIPS_msa_nloc_b, // Vector Leading Ones Count +MIPS_msa_nloc_h, // Vector Leading Ones Count +MIPS_msa_nloc_w, // Vector Leading Ones Count +MIPS_msa_nloc_d, // Vector Leading Ones Count +MIPS_msa_nlzc_b, // Vector Leading Zeros Count +MIPS_msa_nlzc_h, // Vector Leading Zeros Count +MIPS_msa_nlzc_w, // Vector Leading Zeros Count +MIPS_msa_nlzc_d, // Vector Leading Zeros Count +MIPS_msa_copy_s_b, // Element Copy to GPR Signed +MIPS_msa_copy_s_h, // Element Copy to GPR Signed +MIPS_msa_copy_s_w, // Element Copy to GPR Signed +MIPS_msa_copy_s_d, // Element Copy to GPR Signed +MIPS_msa_copy_u_b, // Element Copy to GPR Unsigned +MIPS_msa_copy_u_h, // Element Copy to GPR Unsigned +MIPS_msa_copy_u_w, // Element Copy to GPR Unsigned +MIPS_msa_copy_u_d, // Element Copy to GPR Unsigned +MIPS_msa_insert_b, // GPR Insert Element +MIPS_msa_insert_h, // GPR Insert Element +MIPS_msa_insert_w, // GPR Insert Element +MIPS_msa_insert_d, // GPR Insert Element +MIPS_msa_insve_b, // Element Insert Element +MIPS_msa_insve_h, // Element Insert Element +MIPS_msa_insve_w, // Element Insert Element +MIPS_msa_insve_d, // Element Insert Element +MIPS_msa_bnz_b, // Immediate Branch If All Elements Are Not Zero +MIPS_msa_bnz_h, // Immediate Branch If All Elements Are Not Zero +MIPS_msa_bnz_w, // Immediate Branch If All Elements Are Not Zero +MIPS_msa_bnz_d, // Immediate Branch If All Elements Are Not Zero +MIPS_msa_bz_b, // Immediate Branch If At Least One Element Is Zero +MIPS_msa_bz_h, // Immediate Branch If At Least One Element Is Zero +MIPS_msa_bz_w, // Immediate Branch If At Least One Element Is Zero +MIPS_msa_bz_d, // Immediate Branch If At Least One Element Is Zero +MIPS_msa_ldi_b, // Immediate Load +MIPS_msa_ldi_h, // Immediate Load +MIPS_msa_ldi_w, // Immediate Load +MIPS_msa_ldi_d, // Immediate Load +MIPS_msa_fcaf_w, // Vector Floating-Point Quiet Compare Always False +MIPS_msa_fcaf_d, // Vector Floating-Point Quiet Compare Always False +MIPS_msa_fcun_w, // Vector Floating-Point Quiet Compare Unordered +MIPS_msa_fcun_d, // Vector Floating-Point Quiet Compare Unordered +MIPS_msa_fceq_w, // Vector Floating-Point Quiet Compare Equal +MIPS_msa_fceq_d, // Vector Floating-Point Quiet Compare Equal +MIPS_msa_fcueq_w, // Vector Floating-Point Quiet Compare Unordered or Equal +MIPS_msa_fcueq_d, // Vector Floating-Point Quiet Compare Unordered or Equal +MIPS_msa_fclt_w, // Vector Floating-Point Quiet Compare Less Than +MIPS_msa_fclt_d, // Vector Floating-Point Quiet Compare Less Than +MIPS_msa_fcult_w, // Vector Floating-Point Quiet Compare Unordered or Less Than +MIPS_msa_fcult_d, // Vector Floating-Point Quiet Compare Unordered or Less Than +MIPS_msa_fcle_w, // Vector Floating-Point Quiet Compare Less or Equal +MIPS_msa_fcle_d, // Vector Floating-Point Quiet Compare Less or Equal +MIPS_msa_fcule_w, // Vector Floating-Point Quiet Compare Unordered or Less or Equal +MIPS_msa_fcule_d, // Vector Floating-Point Quiet Compare Unordered or Less or Equal +MIPS_msa_fsaf_w, // Vector Floating-Point Signaling Compare Always False +MIPS_msa_fsaf_d, // Vector Floating-Point Signaling Compare Always False +MIPS_msa_fsun_w, // Vector Floating-Point Signaling Compare Unordered +MIPS_msa_fsun_d, // Vector Floating-Point Signaling Compare Unordered +MIPS_msa_fseq_w, // Vector Floating-Point Signaling Compare Equal +MIPS_msa_fseq_d, // Vector Floating-Point Signaling Compare Equal +MIPS_msa_fsueq_w, // Vector Floating-Point Signaling Compare Unordered or Equal +MIPS_msa_fsueq_d, // Vector Floating-Point Signaling Compare Unordered or Equal +MIPS_msa_fslt_w, // Vector Floating-Point Signaling Compare Less Than +MIPS_msa_fslt_d, // Vector Floating-Point Signaling Compare Less Than +MIPS_msa_fsult_w, // Vector Floating-Point Signaling Compare Unordered or Less Than +MIPS_msa_fsult_d, // Vector Floating-Point Signaling Compare Unordered or Less Than +MIPS_msa_fsle_w, // Vector Floating-Point Signaling Compare Less or Equal +MIPS_msa_fsle_d, // Vector Floating-Point Signaling Compare Less or Equal +MIPS_msa_fsule_w, // Vector Floating-Point Signaling Compare Unordered or Less or Equal +MIPS_msa_fsule_d, // Vector Floating-Point Signaling Compare Unordered or Less or Equal +MIPS_msa_fadd_w, // Vector Floating-Point Addition +MIPS_msa_fadd_d, // Vector Floating-Point Addition +MIPS_msa_fsub_w, // Vector Floating-Point Subtraction +MIPS_msa_fsub_d, // Vector Floating-Point Subtraction +MIPS_msa_fmul_w, // Vector Floating-Point Multiplication +MIPS_msa_fmul_d, // Vector Floating-Point Multiplication +MIPS_msa_fdiv_w, // Vector Floating-Point Division +MIPS_msa_fdiv_d, // Vector Floating-Point Division +MIPS_msa_fmadd_w, // Vector Floating-Point Multiply-Add +MIPS_msa_fmadd_d, // Vector Floating-Point Multiply-Add +MIPS_msa_fmsub_w, // Vector Floating-Point Multiply-Sub +MIPS_msa_fmsub_d, // Vector Floating-Point Multiply-Sub +MIPS_msa_fexp2_w, // Vector Floating-Point Base 2 Exponentiation +MIPS_msa_fexp2_d, // Vector Floating-Point Base 2 Exponentiation +MIPS_msa_fexdo_h, // Vector Floating-Point Down-Convert Interchange Format +MIPS_msa_fexdo_w, // Vector Floating-Point Down-Convert Interchange Format +MIPS_msa_ftq_h, // Vector Floating-Point Convert to Fixed-Point +MIPS_msa_ftq_w, // Vector Floating-Point Convert to Fixed-Point +MIPS_msa_fmin_w, // Vector Floating-Point Minimum +MIPS_msa_fmin_d, // Vector Floating-Point Minimum +MIPS_msa_fmin_a_w, // Vector Floating-Point Minimum Based on Absolute Values +MIPS_msa_fmin_a_d, // Vector Floating-Point Minimum Based on Absolute Values +MIPS_msa_fmax_w, // Vector Floating-Point Maximum +MIPS_msa_fmax_d, // Vector Floating-Point Maximum +MIPS_msa_fmax_a_w, // Vector Floating-Point Maximum Based on Absolute Values +MIPS_msa_fmax_a_d, // Vector Floating-Point Maximum Based on Absolute Values +MIPS_msa_fcor_w, // Vector Floating-Point Quiet Compare Ordered +MIPS_msa_fcor_d, // Vector Floating-Point Quiet Compare Ordered +MIPS_msa_fcune_w, // Vector Floating-Point Quiet Compare Unordered or Not Equal +MIPS_msa_fcune_d, // Vector Floating-Point Quiet Compare Unordered or Not Equal +MIPS_msa_fcne_w, // Vector Floating-Point Quiet Compare Not Equal +MIPS_msa_fcne_d, // Vector Floating-Point Quiet Compare Not Equal +MIPS_msa_mul_q_h, // Vector Fixed-Point Multiply +MIPS_msa_mul_q_w, // Vector Fixed-Point Multiply +MIPS_msa_madd_q_h, // Vector Fixed-Point Multiply and Add +MIPS_msa_madd_q_w, // Vector Fixed-Point Multiply and Add +MIPS_msa_msub_q_h, // Vector Fixed-Point Multiply and Subtract +MIPS_msa_msub_q_w, // Vector Fixed-Point Multiply and Subtract +MIPS_msa_fsor_w, // Vector Floating-Point Signaling Compare Ordered +MIPS_msa_fsor_d, // Vector Floating-Point Signaling Compare Ordered +MIPS_msa_fsune_w, // Vector Floating-Point Signaling Compare Unordered or Not Equal +MIPS_msa_fsune_d, // Vector Floating-Point Signaling Compare Unordered or Not Equal +MIPS_msa_fsne_w, // Vector Floating-Point Signaling Compare Not Equal +MIPS_msa_fsne_d, // Vector Floating-Point Signaling Compare Not Equal +MIPS_msa_mulr_q_h, // Vector Fixed-Point Multiply Rounded +MIPS_msa_mulr_q_w, // Vector Fixed-Point Multiply Rounded +MIPS_msa_maddr_q_h, // Vector Fixed-Point Multiply and Add Rounded +MIPS_msa_maddr_q_w, // Vector Fixed-Point Multiply and Add Rounded +MIPS_msa_msubr_q_h, // Vector Fixed-Point Multiply and Subtract Rounded +MIPS_msa_msubr_q_w, // Vector Fixed-Point Multiply and Subtract Rounded +MIPS_msa_fclass_w, // Vector Floating-Point Class Mask +MIPS_msa_fclass_d, // Vector Floating-Point Class Mask +MIPS_msa_ftrunc_s_w, // Vector Floating-Point Truncate and Convert to Signed Integer +MIPS_msa_ftrunc_s_d, // Vector Floating-Point Truncate and Convert to Signed Integer +MIPS_msa_ftrunc_u_w, // Vector Floating-Point Truncate and Convert to Unsigned Integer +MIPS_msa_ftrunc_u_d, // Vector Floating-Point Truncate and Convert to Unsigned Integer +MIPS_msa_fsqrt_w, // Vector Floating-Point Square Root +MIPS_msa_fsqrt_d, // Vector Floating-Point Square Root +MIPS_msa_frsqrt_w, // Vector Approximate Floating-Point Reciprocal of Square Root +MIPS_msa_frsqrt_d, // Vector Approximate Floating-Point Reciprocal of Square Root +MIPS_msa_frcp_w, // Vector Approximate Floating-Point Reciprocal +MIPS_msa_frcp_d, // Vector Approximate Floating-Point Reciprocal +MIPS_msa_frint_w, // Vector Floating-Point Round to Integer +MIPS_msa_frint_d, // Vector Floating-Point Round to Integer +MIPS_msa_flog2_w, // Vector Floating-Point Base 2 Logarithm +MIPS_msa_flog2_d, // Vector Floating-Point Base 2 Logarithm +MIPS_msa_fexupl_w, // Vector Floating-Point Up-Convert Interchange Format Left +MIPS_msa_fexupl_d, // Vector Floating-Point Up-Convert Interchange Format Left +MIPS_msa_fexupr_w, // Vector Floating-Point Up-Convert Interchange Format Right +MIPS_msa_fexupr_d, // Vector Floating-Point Up-Convert Interchange Format Right +MIPS_msa_ffql_w, // Vector Floating-Point Convert from Fixed-Point Left +MIPS_msa_ffql_d, // Vector Floating-Point Convert from Fixed-Point Left +MIPS_msa_ffqr_w, // Vector Floating-Point Convert from Fixed-Point Right +MIPS_msa_ffqr_d, // Vector Floating-Point Convert from Fixed-Point Right +MIPS_msa_ftint_s_w, // Vector Floating-Point Convert to Signed Integer +MIPS_msa_ftint_s_d, // Vector Floating-Point Convert to Signed Integer +MIPS_msa_ftint_u_w, // Vector Floating-Point Round and Convert to Unsigned Integer +MIPS_msa_ftint_u_d, // Vector Floating-Point Round and Convert to Unsigned Integer +MIPS_msa_ffint_s_w, // Vector Floating-Point Round and Convert from Signed Integer +MIPS_msa_ffint_s_d, // Vector Floating-Point Round and Convert from Signed Integer +MIPS_msa_ffint_u_w, // Vector Floating-Point Convert from Unsigned Integer +MIPS_msa_ffint_u_d, // Vector Floating-Point Convert from Unsigned Integer +MIPS_msa_ctcmsa, // GPR Copy to MSA Control Register +MIPS_msa_cfcmsa, // GPR Copy from MSA Control Register +MIPS_msa_move_v, // Vector Move + +// MIPS R6 (LSA is also part of MSA) +MIPS_lsa, // Left Shift Add +MIPS_dlsa, // Doubleword Left Shift Add + +// MIPS R3 EVA +MIPS_lbe, // Load Byte EVA +MIPS_lbue, // Load Byte Unsigned EVA +MIPS_lhe, // Load Halfword EVA +MIPS_lhue, // Load Halfword Unsigned EVA +MIPS_lwe, // Load Word EVA +MIPS_sbe, // Store Byte EVA +MIPS_she, // Store Halfword EVA +MIPS_swe, // Store Word EVA +MIPS_lle, // Load Linked Word EVA +MIPS_sce, // Store Conditional Word EVA +MIPS_cachee, // Perform Cache Operation EVA +MIPS_prefe, // Prefetch EVA +MIPS_lwle, // Load Word Left EVA +MIPS_lwre, // Load Word Right EVA +MIPS_swle, // Store Word Left EVA +MIPS_swre, // Store Word Right EVA + +// new MIPS16e2 instructions +MIPS_movtz, // Move Conditional on T Equal to Zero +MIPS_movtn, // Move Zero Conditional on T Not Equal to Zero + +// interAptiv core custom instructions +MIPS_copyw, // Copy Data to Aligned Memory Location +MIPS_ucopyw, // Copy Data to Unaligned Memory Location + + +MIPS_last, + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +H8_null = 0, // Unknown Operation + +H8_add, // Add binary +H8_adds, // Add with sign extension +H8_addx, // Add with extend carry +H8_and, // Logical AND +H8_andc, // Logical AND with control register +H8_band, // Bit AND +H8_bra, // Branch always +H8_brn, // Branch never +H8_bhi, // Branch if higher +H8_bls, // Branch if lower or same +H8_bcc, // Branch if carry clear (higher or same) +H8_bcs, // Branch if carry set (lower) +H8_bne, // Branch if not equal +H8_beq, // Branch if equal +H8_bvc, // Branch if overflow clear +H8_bvs, // Branch if overflow set +H8_bpl, // Branch if plus +H8_bmi, // Branch if minus +H8_bge, // Branch if greates or equal +H8_blt, // Branch if less +H8_bgt, // Branch if greater +H8_ble, // Branch if less or equal +H8_bclr, // Bit clear +H8_biand, // Bit invert AND +H8_bild, // Bit invert load +H8_bior, // Bit invert OR +H8_bist, // Bit invert store +H8_bixor, // Bit invert XOR +H8_bld, // Bit load +H8_bnot, // Bit NOT +H8_bor, // Bit OR +H8_bset, // Bit set +H8_bsr, // Branch to subroutine +H8_bst, // Bit store +H8_btst, // Bit test +H8_bxor, // Bit XOR +H8_clrmac, // Clear MAC register +H8_cmp, // Compare +H8_daa, // Decimal adjust add +H8_das, // Decimal adjust subtract +H8_dec, // Decrement +H8_divxs, // Divide extended as signed +H8_divxu, // Divide extended as unsigned +H8_eepmov, // Move data to EEPROM +H8_exts, // Extend as signed +H8_extu, // Extend as unsigned +H8_inc, // Increment +H8_jmp, // Jump +H8_jsr, // Jump to subroutine +H8_ldc, // Load to control register +H8_ldm, // Load to multiple registers +H8_ldmac, // Load to MAC register +H8_mac, // Multiply and accumulate +H8_mov, // Move data +H8_movfpe, // Move from peripheral with E clock +H8_movtpe, // Move to peripheral with E clock +H8_mulxs, // Multiply extend as signed +H8_mulxu, // Multiply extend as unsigned +H8_neg, // Negate +H8_nop, // No operation +H8_not, // Logical complement +H8_or, // Logical OR +H8_orc, // Logical OR with control register +H8_pop, // Pop data from stack +H8_push, // Push data on stack +H8_rotl, // Rotate left +H8_rotr, // Rotate right +H8_rotxl, // Rotate with extend carry left +H8_rotxr, // Rotate with extend carry right +H8_rte, // Return from exception +H8_rts, // Return from subroutine +H8_shal, // Shift arithmetic left +H8_shar, // Shift arithmetic right +H8_shll, // Shift logical left +H8_shlr, // Shift logical right +H8_sleep, // Power down mode +H8_stc, // Store from control register +H8_stm, // Store from multiple registers +H8_stmac, // Store from MAC register +H8_sub, // Subtract binary +H8_subs, // Subtract with sign extension +H8_subx, // Subtract with extend carry +H8_tas, // Test and set +H8_trapa, // Trap always +H8_xor, // Logical XOR +H8_xorc, // Logical XOR with control register + +// H8SX +H8_rtel, // Returns from an exception, restoring data to multiple general registers +H8_rtsl, // Returns from a subroutine, restoring data to multiple general registers +H8_movmd, // Transfers a data block +H8_movsd, // Transfers a data block with zero detection +H8_bras, // Branch always after the next instruction (delay slot) +H8_movab, // MOVe effective Address/B +H8_movaw, // MOVe effective Address/W +H8_moval, // MOVe effective Address/L +H8_bsetne, // Bit SET if Not Equal +H8_bseteq, // Bit SET if EQual +H8_bclrne, // Bit CLeaR if Not Equal +H8_bclreq, // Bit CLeaR if Equal +H8_bstz, // Bit STore Zero flag +H8_bistz, // Bit Invert STore Zero flag +H8_bfld, // Bit Field LoaD +H8_bfst, // Bit Field STore +H8_muls, // MULtiply as Signed +H8_divs, // DIVide as Signed +H8_mulu, // MULtiply as Unsigned +H8_divu, // DIVide as Unsigned +H8_mulsu, // MULtiply as Signed +H8_muluu, // MULtiply as Unsigned +H8_brabc, // BRAnch if Bit Cleared +H8_brabs, // BRAnch if Bit Set +H8_bsrbc, // Branch to SubRoutine if Bit Cleared +H8_bsrbs, // Branch to SubRoutine if Bit Set + +H8_last, + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +PIC_null = 0, // Unknown Operation + +// BYTE-ORIENTED FILE REGISTER OPERATIONS + +PIC_addwf, // Add W and f +PIC_andwf, // AND W with f +PIC_clrf, // Clear f +PIC_clrw, // Clear W +PIC_comf, // Complement f +PIC_decf, // Decrement f +PIC_decfsz, // Decrement f, Skip if 0 +PIC_incf, // Increment f +PIC_incfsz, // Increment f, Skip if 0 +PIC_iorwf, // Inclusive OR W with f +PIC_movf, // Move f +PIC_movwf, // Move W to f +PIC_nop, // No Operation +PIC_rlf, // Rotate Left f through Carry +PIC_rrf, // Rotate Right f through Carry +PIC_subwf, // Subtract W from f +PIC_swapf, // Swap nibbles in f +PIC_xorwf, // Exclusive OR W with f + +// BIT-ORIENTED FILE REGISTER OPERATIONS + +PIC_bcf, // Bit Clear f +PIC_bsf, // Bit Set f +PIC_btfsc, // Bit Test f, Skip if Clear +PIC_btfss, // Bit Test f, Skip if Set + + +// LITERAL AND CONTROL OPERATIONS + +PIC_addlw, // Add literal and W +PIC_andlw, // AND literal with W +PIC_call, // Call subroutine +PIC_clrwdt, // Clear Watchdog Timer +PIC_goto, // Go to address +PIC_iorlw, // Inclusive OR literal with W +PIC_movlw, // Move literal to W +PIC_retfie, // Return from interrupt +PIC_retlw, // Return with literal in W +PIC_return, // Return from Subroutine +PIC_sleep, // Go into standby mode +PIC_sublw, // Subtract W from literal +PIC_xorlw, // Exclusive OR literal with W + +// ADDITIONAL INSTRUCTIONS TO MAINTAIN COMPITIBILITY WITH 12C5xx,16C5x + +PIC_option, // Load OPTION register +PIC_tris, // Load TRIS Register + +// MACROS + +PIC_movfw, // Move Contents of File Reg to W +PIC_tstf, // Test Contents of File Register +PIC_negf, // Negate File Register Contents +PIC_b, // Branch to Address +PIC_clrc, // Clear Carry +PIC_clrdc, // Clear Digit Carry +PIC_clrz, // Clear Zero +PIC_setc, // Set Carry +PIC_setdc, // Set Digit Carry +PIC_setz, // Set Zero +PIC_skpc, // Skip on Carry +PIC_skpdc, // Skip on Digit Carry +PIC_skpnc, // Skip on No Carry +PIC_skpndc, // Skip on No Digit Carry +PIC_skpnz, // Skip on No Zero +PIC_skpz, // Skip on Zero +PIC_bc, // Branch on Carry to Address k +PIC_bdc, // Branch on Digit Carry to k +PIC_bnc, // Branch on No Carry to k +PIC_bndc, // Branch on No Digit Carry to k +PIC_bnz, // Branch on No Zero to Address +PIC_bz, // Branch on Zero to Address k +PIC_addcf, // Add Carry to File Register +PIC_adddcf, // Add Digit to File Register +PIC_subcf, // Subtract Carry from File Reg + +// ADDITIONAL INSTRUCTIONS FOR 18Cxx + +// BYTE-ORIENTED FILE REGISTER OPERATIONS + +PIC_addwf3, // Add W and f +PIC_addwfc3, // Add W and Carry to f +PIC_andwf3, // AND W with f +PIC_clrf2, // Clear f +PIC_comf3, // Complement f +PIC_cpfseq2, // Compare f with W, Skip if == +PIC_cpfsgt2, // Compare f with W, Skip if > +PIC_cpfslt2, // Compare f with W, Skip if < +PIC_decf3, // Decrement f +PIC_decfsz3, // Decrement f, Skip if 0 +PIC_dcfsnz3, // Decrement f, Skip if not 0 +PIC_incf3, // Increment f +PIC_incfsz3, // Increment f, Skip if 0 +PIC_infsnz3, // Increment f, Skip if not 0 +PIC_iorwf3, // Inclusive OR W with f +PIC_movf3, // Move f +PIC_movff2, // Move fs to fd +PIC_movwf2, // Move W to f +PIC_mulwf2, // Multiply W with f +PIC_negf2, // Negate f +PIC_rlcf3, // Rotate Left f through Carry +PIC_rlncf3, // Rotate Left f +PIC_rrcf3, // Rotate Right f through Carry +PIC_rrncf3, // Rotate Right f +PIC_setf2, // Set f +PIC_subfwb3, // Substract f from W with borrow +PIC_subwf3, // Substract W from f +PIC_subwfb3, // Substract W from f with borrow +PIC_swapf3, // Swap nibbles in f +PIC_tstfsz2, // Test f, Skip if 0 +PIC_xorwf3, // Exclusive OR W with f + +// BIT-ORIENTED FILE REGISTER OPERATIONS + +PIC_bcf3, // Bit Clear f +PIC_bsf3, // Bit Set f +PIC_btfsc3, // Bit Test f, Skip if Clear +PIC_btfss3, // Bit Test f, Skip if Set +PIC_btg3, // Bit Toggle f + +// CONTROL OPERATIONS + +PIC_bc1, // Branch if Carry +PIC_bn1, // Branch if Negative +PIC_bnc1, // Branch if not Carry +PIC_bnn1, // Branch if not Negative +PIC_bnov1, // Branch if not Overflow +PIC_bnz1, // Branch if not Zero +PIC_bov1, // Branch if Overflow +PIC_bra1, // Branch unconditionally +PIC_bz1, // Branch if Zero +PIC_call2, // Call subroutine +// PIC_clrwdt +PIC_daw0, // Decimal Adjust W +// PIC_goto +// PIC_nop +// PIC_nop +PIC_pop0, // Pop top of return stack +PIC_push0, // Push top of return stack +PIC_rcall1, // Relative Call subroutine +PIC_reset0, // Software device Reset +PIC_retfie1, // Return from interrupt enable +// PIC_retlw +PIC_return1, // Return from Subroutine +// PIC_sleep + +// LITERAL OPERATIONS + +// PIC_addlw +// PIC_andlw +// PIC_iorlw +PIC_lfsr2, // Move literal to FSR +PIC_movlb1, // Move literal to BSR +// PIC_movlw +PIC_mullw1, // Multiply literal with W +// PIC_retlw +// PIC_sublw +// PIC_xorlw + +// DATA MEMORY <-> PROGRAM MEMORY OPERATIONS + +PIC_tblrd0, // Table Read +PIC_tblrd0p, // Table Read with post-increment +PIC_tblrd0m, // Table Read with post-decrement +PIC_tblrdp0, // Table Read with pre-increment +PIC_tblwt0, // Table Write +PIC_tblwt0p, // Table Write with post-increment +PIC_tblwt0m, // Table Write with post-decrement +PIC_tblwtp0, // Table Write with pre-increment + +// ADDITIONAL INSTRUCTIONS FOR 16F1x and 12F1x + +PIC_addwfc, // Add W and Carry to f +PIC_movlp, // Move literal to PCLATH +PIC_movlb, // Move literal to BSR +PIC_addfsr, // Add Literal to FSRn +PIC_asrf, // Arithmetic Right Shift +PIC_lslf, // Logical Left Shift +PIC_lsrf, // Logical Right Shift +PIC_subwfb, // Subtract with Borrow W from f +PIC_bra, // Relative Branch +PIC_brw, // Relative Branch with W +PIC_callw, // Call Subroutine with W +PIC_reset, // Software device Reset +PIC_moviw, // Move INDFn to W +PIC_movwi, // Move W to INDFn + +PIC_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +PIC16_null = 0, // Unknown Operation + +// Move Instructions +PIC16_EXCH, // Exchange Wns and Wnd +PIC16_MOV, // Move +PIC16_SWAP, // Byte or Nibble Swap Wn +PIC16_TBLRDH, // Table Read High +PIC16_TBLRDL, // Table Read Low +PIC16_TBLWTH, // Table Write High +PIC16_TBLWTL, // Table Write Low +// Only for PIC24E and dsPIC33E +PIC16_MOVPAG, // Move to Page Register + +// Math Instructions +PIC16_ADD, // Add +PIC16_ADDC, // Add with carry +PIC16_DAWB, // Decimal Adjust Wn +PIC16_DEC, // Decrement +PIC16_DEC2, // Decrement by 2 +PIC16_DIV, // Signed/Unsigned Integer Divide +PIC16_INC, // Increment +PIC16_INC2, // Increment by 2 +PIC16_MUL, // Integer Multiply +PIC16_SE, // Sign-Extend Ws +PIC16_SUB, // Subtract +PIC16_SUBB, // Subtract with Borrow +PIC16_SUBBR, // Subtract with Borrow +PIC16_SUBR, // Subtract +PIC16_ZE, // Zero - Extend Ws +// Only for PIC24E and dsPIC33E +PIC16_MULW, // Integer Multiply with 16-bit Result +// Only for dsPIC +PIC16_DIVF, // Fractional Divide + +// Logic Instructions +PIC16_AND, // AND +PIC16_CLR, // Clear f or WREG | Clear Wd +PIC16_COM, // Complement f | Complement Ws +PIC16_IOR, // Inclusive OR +PIC16_NEG, // Negate f | Negate Ws +PIC16_SETM, // Set f or WREG | Set Ws +PIC16_XOR, // Exclusive OR + +// Rotate/Shift Instructions +PIC16_ASR, // Arithmetic Shift Right +PIC16_LSR, // Logical Shift Right +PIC16_RLC, // Rotate Left through Carry +PIC16_RLNC, // Rotate Left without Carry +PIC16_RRC, // Rotate Right through Carry +PIC16_RRNC, // Rotate Right without Carry +PIC16_SL, // Shift Left + +// Bit Instructions +PIC16_BCLR, // Bit Clear f | Bit Clear in Ws +PIC16_BSET, // Bit Set f | Bit Set in Ws +PIC16_BSW, // Bit Write in Ws +PIC16_BTG, // Bit Toggle f | Bit Toggle in Ws +PIC16_BTST, // Bit Test f | Bit Test in Ws +PIC16_BTSTS, // Bit Test/Set f | Bit Test/Set in Ws +PIC16_FBCL, // Find First Bit Change from Left +PIC16_FF1L, // Find First One from Left +PIC16_FF1R, // Find First One from Right + + +// Compare/Skip and Compare/Branch Instructions +PIC16_BTSC, // Bit Test, Skip if Clear +PIC16_BTSS, // Bit Test, Skip if Set +PIC16_CP, // Compare, Set Status Flags +PIC16_CP0, // Compare, Set Status Flags +PIC16_CPB, // Compare using Borrow, set Status Flags +PIC16_CPSEQ, // Compare Wb with Wn, Skip if Equal (Wb = Wn) +PIC16_CPSGT, // Signed Compare Wb with Wn, Skip if Greater Than (Wb > Wn) +PIC16_CPSLT, // Signed Compare Wb with Wn, Skip if Less Than (Wb < Wn) +PIC16_CPSNE, // Signed Compare Wb with Wn, Skip if Not Equal (Wb != Wn) +// Only for PIC24E and dsPIC33E +PIC16_CPBEQ, // Compare Wb with Wn, branch if = +PIC16_CPBNE, // Compare Wb with Wn, Branch if Not Equal (Wb != Wn) +PIC16_CPBGT, // Signed Compare Wb with Wn, Branch if Greater Than (Wb > Wn) +PIC16_CPBLT, // Signed Compare Wb with Wn, Branch if Less Than (Wb < Wn) + +// Program Flow Instructions +PIC16_BRA, // Branch unconditionally/conditionally +PIC16_CALL, // Call Subroutine | Call Indirect Subroutine +PIC16_GOTO, // Unconditional Jump +PIC16_RCALL, // Relative Call | Relative Call +PIC16_REPEAT, // Repeat next instruction +PIC16_RETFIE, // Return from Interrupt +PIC16_RETLW, // Return with Literal in Wn +PIC16_RETURN, // Return +// Only for dsPIC +PIC16_DO, // Initialize Hardware Loop + +// Shadow/Stack Instructions +PIC16_LNK, // Allocate Stack Frame +PIC16_POP, // Pop TOS | Pop Shadow Registers +PIC16_PUSH, // Push to TOS | Push Shadow Registers +PIC16_ULNK, // De-allocate Stack Frame + +// Control Instructions +PIC16_CLRWDT, // Clear Watchdog Timer +PIC16_DISI, // Disable Interrupts Temporarily +PIC16_NOP, // No operation +PIC16_NOPR, // No operation +PIC16_PWRSAV, // Enter Power Saving Mode +PIC16_RESET, // Reset + +// DSP Instructions [Only for dsPIC30F, dsPIC33F and dsPIC33E] +PIC16_LAC, // Load Accumulator +PIC16_SAC, // Store Accumulator +PIC16_SFTAC, // Arithmetic Shift Accumulator +PIC16_CLR1, // Clear Accumulator, Prefetch Operands +PIC16_ED, // Euclidean Distance (No Accumulate) +PIC16_EDAC, // Euclidean Distance +PIC16_MAC, // Multiply and Accumulate +PIC16_MOVSAC, // Prefetch Operands and Store Accumulator +PIC16_MPY, // Multiply to Accumulator +PIC16_MSC, // Multiply and Subtract from Accumulator + +// ICD instructions +PIC16_BREAK, // ICD Break +PIC16_URUN, // ICD Run +PIC16_SSTEP, // ICD Single Step +PIC16_FEX, // ICD Execute + +PIC16_last, + + }; +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +SPARC_null = 0, // Unknown Operation + +// SPARC V9 instructions + +SPARC_add, // Add +SPARC_addcc, // Add and modify condition codes +SPARC_addc, // Add with carry +SPARC_addccc, // Add with carry and modify condition codes +SPARC_and, // And +SPARC_andcc, // And and modify condition codes +SPARC_andn, // And not +SPARC_andncc, // And not (and modify condition codes) +SPARC_b, // Branch on integer condition codes +SPARC_bp, // Branch on integer condition codes with prediction +SPARC_bpr, // Branch on contents of integer register with prediction +SPARC_call, // Call and link +SPARC_casa, // Compare and swap word in alternate space +SPARC_casxa, // Compare and swap doubleword in alternate space +SPARC_done, // Return from trap +SPARC_fabs, // Floating-point absolute value +SPARC_fadd, // Floating-point add +SPARC_fbp, // Branch on floating-point condition codes with prediction +SPARC_fb, // Branch on floating-point condition codes +SPARC_fcmp, // Floating-point compare +SPARC_fcmpe, // Floating-point compare (exception if unordered) +SPARC_fdiv, // Floating-point divide +SPARC_fdmulq, // Floating-point multiply double to quad +SPARC_flush, // Flush instruction memory +SPARC_flushw, // Flush register windows +SPARC_fmov, // Floating-point move +SPARC_fmovcc, // Conditional floating-point move +SPARC_fmovr, // Move floating-point register if integer register contents satisfy condition +SPARC_fmul, // Floating-point multiply +SPARC_fneg, // Floating-point negate +SPARC_fsmuld, // Floating-point multiply single to double +SPARC_fsqrt, // Floating-point square root +SPARC_fsub, // Floating-point subtract +SPARC_fstox, // Convert single floating point to 64-bit integer +SPARC_fdtox, // Convert doublee floating point to 64-bit integer +SPARC_fqtox, // Convert quad floating point to 64-bit integer +SPARC_fxtos, // Convert 64-bit integer to single floating point +SPARC_fxtod, // Convert 64-bit integer to double floating point +SPARC_fxtoq, // Convert 64-bit integer to quad floating point +SPARC_fitos, // Convert 32-bit integer to single floating point +SPARC_fdtos, // Convert single floating point to single floating point +SPARC_fqtos, // Convert quade floating point to single floating point +SPARC_fitod, // Convert 32-bit integer to double floating point +SPARC_fstod, // Convert single floating point to double floating point +SPARC_fqtod, // Convert quade floating point to double floating point +SPARC_fitoq, // Convert 32-bit integer to quad floating point +SPARC_fstoq, // Convert single floating point to quad floating point +SPARC_fdtoq, // Convert quade floating point to quad floating point +SPARC_fstoi, // Convert single floating point to 32-bit integer +SPARC_fdtoi, // Convert doublee floating point to 32-bit integer +SPARC_fqtoi, // Convert quad floating point to 32-bit integer +SPARC_illtrap, // Illegal instruction +SPARC_impdep1, // Implementation-dependent instruction +SPARC_impdep2, // Implementation-dependent instruction +SPARC_jmpl, // Jump and link +SPARC_ldd, // Load doubleword +SPARC_ldda, // Load doubleword from alternate space +SPARC_lddf, // Load double floating-point +SPARC_lddfa, // Load double floating-point from alternate space +SPARC_ldf, // Load floating-point +SPARC_ldfa, // Load floating-point from alternate space +SPARC_ldfsr, // Load floating-point state register lower +SPARC_ldqf, // Load quad floating-point +SPARC_ldqfa, // Load quad floating-point from alternate space +SPARC_ldsb, // Load signed byte +SPARC_ldsba, // Load signed byte from alternate space +SPARC_ldsh, // Load signed halfword +SPARC_ldsha, // Load signed halfword from alternate space +SPARC_ldstub, // Load-store unsigned byte +SPARC_ldstuba, // Load-store unsigned byte in alternate space +SPARC_ldsw, // Load signed word +SPARC_ldswa, // Load signed word from alternate space +SPARC_ldub, // Load unsigned byte +SPARC_lduba, // Load unsigned byte from alternate space +SPARC_lduh, // Load unsigned halfword +SPARC_lduha, // Load unsigned halfword from alternate space +SPARC_lduw, // Load unsigned word +SPARC_lduwa, // Load unsigned word from alternate space +SPARC_ldx, // Load extended +SPARC_ldxa, // Load extended from alternate space +SPARC_ldxfsr, // Load extended floating-point state register +SPARC_membar, // Memory barrier +SPARC_mov, // Move integer register if condition is satisfied +SPARC_movr, // Move integer register on contents of integer register +SPARC_mulscc, // Multiply step and modify condition codes +SPARC_mulx, // Multiply 64-bit integers +SPARC_nop, // No operation +SPARC_or, // Inclusive-or +SPARC_orcc, // Inclusive-or (and modify condition codes) +SPARC_orn, // Inclusive-or not +SPARC_orncc, // Inclusive-or not (and modify condition codes) +SPARC_popc, // Population count +SPARC_prefetch, // Prefetch data +SPARC_prefetcha, // Prefetch data from alternate space +SPARC_rd, // Read state register +SPARC_rdpr, // Read privileged register +SPARC_restore, // Restore caller's window +SPARC_restored, // Window has been restored +SPARC_retry, // Return from trap and retry +SPARC_return, // Return +SPARC_save, // Save caller's window +SPARC_saved, // Window has been saved +SPARC_sdiv, // 32-bit signed integer divide +SPARC_sdivcc, // 32-bit signed integer divide and modify condition codes +SPARC_sdivx, // 64-bit signed integer divide +SPARC_sethi, // Set high 22 bits of low word of integer register +SPARC_sir, // Software-initiated reset +SPARC_sll, // Shift left logical +SPARC_sllx, // Shift left logical, extended +SPARC_smul, // Signed integer multiply +SPARC_smulcc, // Signed integer multiply (and modify condition codes) +SPARC_sra, // Shift right arithmetic +SPARC_srax, // Shift right arithmetic, extended +SPARC_srl, // Shift right logical +SPARC_srlx, // Shift right logical, extended +SPARC_stb, // Store byte +SPARC_stba, // Store byte into alternate space +SPARC_stbar, // Store barrier +SPARC_std, // Store doubleword +SPARC_stda, // Store doubleword into alternate space +SPARC_stdf, // Store double floating-point +SPARC_stdfa, // Store double floating-point into alternate space +SPARC_stf, // Store floating-point +SPARC_stfa, // Store floating-point into alternate space +SPARC_stfsr, // Store floating-point state register +SPARC_sth, // Store halfword +SPARC_stha, // Store halfword into alternate space +SPARC_stqf, // Store quad floating-point +SPARC_stqfa, // Store quad floating-point into alternate space +SPARC_stw, // Store word +SPARC_stwa, // Store word into alternate space +SPARC_stx, // Store extended +SPARC_stxa, // Store extended into alternate space +SPARC_stxfsr, // Store extended floating-point state register +SPARC_sub, // Subtract +SPARC_subcc, // Subtract and modify condition codes +SPARC_subc, // Subtract with carry +SPARC_subccc, // Subtract with carry and modify condition codes +SPARC_swap, // Swap integer register with memory +SPARC_swapa, // Swap integer register with memory in alternate space +SPARC_taddcc, // Tagged add and modify condition codes +SPARC_taddcctv, // Tagged add and modify condition codes (trap on overflow) +SPARC_tsubcc, // Tagged subtract and modify condition codes +SPARC_tsubcctv, // Tagged subtract and modify condition codes (trap on overflow) +SPARC_t, // Trap on integer condition codes +SPARC_udiv, // Unsigned integer divide +SPARC_udivcc, // Unsigned integer divide and modify condition codes +SPARC_udivx, // 64-bit unsigned integer divide +SPARC_umul, // Unsigned integer multiply +SPARC_umulcc, // Unsigned integer multiply and modify condition codes +SPARC_wr, // Write Y register +SPARC_wrpr, // Write privileged register +SPARC_xnor, // Exclusive-nor +SPARC_xnorcc, // Exclusive-nor (and modify condition codes) +SPARC_xor, // Exclusive-or +SPARC_xorcc, // Exclusive-or (and modify condition codes) + +// Synthetic instructions + +SPARC_cmp, // Compare +SPARC_jmp, // Jump +SPARC_iprefetch, // Instruction prefetch +SPARC_tst, // Test +SPARC_ret, // Return from subroutine +SPARC_retl, // Return from leaf subroutine +SPARC_setuw, // Load unsigned constant +SPARC_setsw, // Load signed constant +SPARC_setx, // Load 64-bit constant +SPARC_signx, // Sign-extend 32-bit value to 64 bits +SPARC_not, // One's complement +SPARC_neg, // Two's complement +SPARC_cas, // Compare and swap +SPARC_casl, // Compare and swap, little endian +SPARC_casx, // Compare and swap extended +SPARC_casxl, // Compare and swap extended, little endian +SPARC_inc, // Increment +SPARC_inccc, // Increment and modify condition codes +SPARC_dec, // Deccrement +SPARC_deccc, // Decrement and modify condition codes +SPARC_btst, // Bit test +SPARC_bset, // Bit set +SPARC_bclr, // Bit clear +SPARC_btog, // Bit toggle +SPARC_clr, // Clear +SPARC_clrb, // Clear byte +SPARC_clrh, // Clear halfword +SPARC_clrx, // Clear extended word +SPARC_clruw, // Clear upper word +SPARC_pseudo_mov, // Move register + +// UtlraSPARC II extensions + +SPARC_alignaddress, // Calculate address for misaligned data access +SPARC_array, // 3-D address to blocked byte address conversion +SPARC_edge, // Edge boundary processing {little-endian} +SPARC_faligndata, // Perform data alignment for misaligned data +SPARC_fandnot1, // Negated src1 AND src2 (single precision) +SPARC_fandnot2, // src1 AND negated src2 (single precision) +SPARC_fand, // Logical AND (single precision) +SPARC_fcmpeq, // Four 16-bit/two 32-bit compare; set integer dest if src1 = src2 +SPARC_fcmpgt, // Four 16-bit/two 32-bit compare; set integer dest if src1 > src2 +SPARC_fcmple, // Four 16-bit/two 32-bit compare; set integer dest if src1 <= src2 +SPARC_fcmpne, // Four 16-bit/two 32-bit compare; set integer dest if src1 != src2 +SPARC_fexpand, // Four 8-bit to 16-bit expands +SPARC_fmul8sux16, // Signed upper 8/16-bit partitioned product of corresponding components +SPARC_fmul8ulx16, // Unsigned lower 8/16-bit partitioned product of corresponding components +SPARC_fmul8x16, // 8/16-bit partitioned product of corresponding components +SPARC_fmul8x16al, // 8/16-bit lower a partitioned product of 4 components +SPARC_fmul8x16au, // 8/16-bit upper a partitioned product of 4 components +SPARC_fmuld8sux16, // Signed upper 8/16-bit multiply 32-bit partitioned product of components +SPARC_fmuld8ulx16, // Unsigned lower 8/16-bit multiply 32-bit partitioned product of components +SPARC_fnand, // Logical NAND (single precision) +SPARC_fnor, // Logical NOR (single precision) +SPARC_fnot1, // Negate (1's complement) src1 (single precision) +SPARC_fnot2, // Negate (1's complement) src2 (single precision) +SPARC_fone, // One fill (single precision) +SPARC_fornot1, // Negated src1 OR src2 (single precision) +SPARC_fornot2, // src1 OR negated src2 (single precision) +SPARC_for, // Logical OR (single precision) +SPARC_fpackfix, // Two 32-bit to 16-bit fixed pack +SPARC_fpack, // Four 16-bit/two 32-bit pixel pack +SPARC_fpadd, // Four 16-bit/two 32-bit partitioned add (single precision) +SPARC_fpmerge, // Two 32-bit pixel to 64-bit pixel merge +SPARC_fpsub, // Four 16-bit/two 32-bit partitioned subtract (single precision) +SPARC_fsrc1, // Copy src1 (single precision) +SPARC_fsrc2, // Copy src2 (single precision) +SPARC_fxnor, // Logical XNOR (single precision) +SPARC_fxor, // Logical XOR (single precision) +SPARC_fzero, // Zero fill (single precision) +SPARC_pdist, // Distance between 8 8-bit components +SPARC_shutdown, // Power-down support +// SPARC_stdfa, // 8/16-bit store from a double precision FP register + +// V8 only instructions +SPARC_rett, // Return from trap + +// UA 2005 instructions +SPARC_bmask, // Byte Mask +SPARC_bshuffle, // Byte Shuffle +SPARC_edgen, // Edge boundary processing (no CC) {little-endian} +SPARC_rdhpr, // Read Hyperprivileged Register +SPARC_wrhpr, // Write Hyperprivileged Register +SPARC_siam, // Set Interval Arithmetic Mode + +SPARC_last, + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +HPPA_null = 0, // Unknown Operation + +HPPA_add, // Add +HPPA_addb, // Add and Branch +HPPA_addi, // Add to Immediate +HPPA_addib, // Add Immediate and Branch +HPPA_addil, // Add to Immediate Left +HPPA_and, // AND +HPPA_andcm, // AND complement +HPPA_b, // Branch +HPPA_bb, // Branch on Bit +HPPA_be, // Branch External +HPPA_blr, // Branch and Link Register +HPPA_break, // Break +HPPA_bv, // Branch Vectored +HPPA_bve, // Branch Vectored External +HPPA_cldd, // Coprocessor Load Doubleword +HPPA_cldw, // Coprocessor Load Word +HPPA_clrbts, // Clear Branch Target Stack +HPPA_cmpb, // Compare and Branch +HPPA_cmpclr, // Compare and Clear +HPPA_cmpib, // Compare Immediate and Branch +HPPA_cmpiclr, // Compare Immediate and Clear +HPPA_copr, // Coprocessor Operation +HPPA_cstd, // Coprocessor Store Doubleword +HPPA_cstw, // Coprocessor Store Word +HPPA_dcor, // Decimal Correct +HPPA_depd, // Deposit Doubleword +HPPA_depdi, // Deposit Doubleword Immediate +HPPA_depw, // Deposit Word +HPPA_depwi, // Deposit Word Immediate +HPPA_diag, // Diagnose +HPPA_ds, // Divide Step +HPPA_extrd, // Extract Doubleword +HPPA_extrw, // Extract Word +HPPA_fdc, // Flush Data Cache +HPPA_fdce, // Flush Data Cache Entry +HPPA_fic, // Flush Instruction Cache +HPPA_fice, // Flush Instruction Cache Entry +HPPA_hadd, // Halfword Parallel Add +HPPA_havg, // Halfword Parallel Average +HPPA_hshl, // Halfword Parallel Shift Left +HPPA_hshladd, // Halfword Parallel Shift Left and Add +HPPA_hshr, // Halfword Parallel Shift Right +HPPA_hshradd, // Halfword Parallel Shift Right and Add +HPPA_hsub, // Halfword Parallel Subtract +HPPA_idtlbt, // Insert Data TLB Translation +HPPA_iitlbt, // Insert Instruction TLB Translation +HPPA_lci, // Load Coherence Index +HPPA_ldb, // Load Byte +HPPA_ldcd, // Load and Clear Doubleword +HPPA_ldcw, // Load and Clear Word +HPPA_ldd, // Load Doubleword +HPPA_ldda, // Load Doubleword Absolute +HPPA_ldh, // Load Halfword +HPPA_ldil, // Load Immediate Left +HPPA_ldo, // Load Offset +HPPA_ldsid, // Load Space Identifier +HPPA_ldw, // Load Word +HPPA_ldwa, // Load Word Absolute +HPPA_lpa, // Load Physical Address +HPPA_mfctl, // Move From Control Register +HPPA_mfia, // Move From Instruction Address +HPPA_mfsp, // Move From Space Register +HPPA_mixh, // Mix Halfwords +HPPA_mixw, // Mix Words +HPPA_movb, // Move and Branch +HPPA_movib, // Move Immediate and Branch +HPPA_mtctl, // Move To Control Register +HPPA_mtsarcm, // Move To Shift Amount Register Complement +HPPA_mtsm, // Move To System Mask +HPPA_mtsp, // Move To Space Register +HPPA_or, // Inclusive OR +HPPA_pdc, // Purge Data Cache +HPPA_pdtlb, // Purge Data TLB +HPPA_pdtlbe, // Purge Data TLB Entry +HPPA_permh, // Permute Halfwords +HPPA_pitlb, // Purge Instruction TLB +HPPA_pitlbe, // Purge Instruction TLB Entry +HPPA_popbts, // Pop Branch Target Stack +HPPA_probe, // Probe Access +HPPA_probei, // Probe Access Immediate +HPPA_pushbts, // Push Branch Target Stack +HPPA_pushnom, // Push Nominated +HPPA_rfi, // Return From Interruption +HPPA_rsm, // Reset System Mask +HPPA_shladd, // Shift Left and Add +HPPA_shrpd, // Sihft Right Pair Doubleword +HPPA_shrpw, // Sihft Right Pair Word +HPPA_spop0, // Special Operation Zero +HPPA_spop1, // Special Operation One +HPPA_spop2, // Special Operation Two +HPPA_spop3, // Special Operation Three +HPPA_ssm, // Set System Mask +HPPA_stb, // Store Byte +HPPA_stby, // Store Bytes +HPPA_std, // Store Doubleword +HPPA_stda, // Store Doubleword Absolute +HPPA_stdby, // Store Doubleword Bytes +HPPA_sth, // Store Halfword +HPPA_stw, // Store Word +HPPA_stwa, // Store Word Absolute +HPPA_sub, // Subtract +HPPA_subi, // Subtract from Immediate +HPPA_sync, // Synchronize Caches +HPPA_syncdma, // Synchronize DMA +HPPA_uaddcm, // Unit Add Complement +HPPA_uxor, // Unit XOR +HPPA_xor, // Exclusive OR + +// Floating point instructions + +HPPA_fabs, // Floating-Point Absolute Value +HPPA_fadd, // Floating-Point Add +HPPA_fcmp, // Floating-Point Compare +HPPA_fcnv, // Floating-Point Convert +HPPA_fcpy, // Floating-Point Copy +HPPA_fdiv, // Floating-Point Divide +HPPA_fid, // Floating-Point Identity +HPPA_fldd, // Floating-Point Load Doubleword +HPPA_fldw, // Floating-Point Load Word +HPPA_fmpy, // Floating-Point Multiply +HPPA_fmpyadd, // Floating-Point Multiply/Add +HPPA_fmpyfadd, // Floating-Point Multiply Fused Add +HPPA_fmpynfadd, // Floating-Point Multiply Negate Fused Add +HPPA_fmpysub, // Floating-Point Multiply/Subtract +HPPA_fneg, // Floating-Point Negate +HPPA_fnegabs, // Floating-Point Negate Absolute Value +HPPA_frem, // Floating-Point Remainder +HPPA_frnd, // Floating-Point Round to Integer +HPPA_fsqrt, // Floating-Point Square Root +HPPA_fstd, // Floating-Point Store Doubleword +HPPA_fstw, // Floating-Point Store Word +HPPA_fsub, // Floating-Point Subtract +HPPA_ftest, // Floating-Point Test +HPPA_xmpyu, // Fixed-Point Multiply Unsigned + +// Performance Monitor Coprocessor + +HPPA_pmdis, // Performance Monitor Disable +HPPA_pmenb, // Performance Monitor Enable + +// Macros + +HPPA_call, // Call Subroutine +HPPA_ret, // Return From Subroutine +HPPA_shld, // Shift Left Doubleword +HPPA_shlw, // Shift Left Word +HPPA_shrd, // Shift Right Doubleword +HPPA_shrw, // Shift Right Word +HPPA_ldi, // Load Immediate +HPPA_copy, // Copy Register +HPPA_mtsar, // Move To %SAR +HPPA_nop, // No Operation + +HPPA_last, + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +H8500_null = 0, // Unknown Operation + +// Data transfer + +H8500_mov_g, // B/W Move data +H8500_mov_e, // B Move data +H8500_mov_i, // W Move data +H8500_mov_f, // B/W Move data +H8500_mov_l, // B/W Move data +H8500_mov_s, // B/W Move data +H8500_ldm, // W Pop data from the stack to one or more registers +H8500_stm, // W Push data from one or more registers onto the stack +H8500_xch, // W Exchange data between two general registers +H8500_swap, // B Exchange the upper and lower bytes in a general register +H8500_movtpe, // B Transfer data from a general register to memory +H8500_movfpe, // B Transfer data from memory to a general register + +// Arithmetic operations + +H8500_add_g, // B/W Addition +H8500_add_q, // B/W Addition +H8500_sub, // B/W Subtraction +H8500_adds, // B/W Addition +H8500_subs, // B/W Subtraction +H8500_addx, // B/W Addition with carry +H8500_subx, // B/W Subtraction with borrow +H8500_dadd, // B Decimal addition +H8500_dsub, // B Decimal subtraction +H8500_mulxu, // B/W Unsigned multiplication +H8500_divxu, // B/W Unsigned division +H8500_cmp_g, // B/W Compare data +H8500_cmp_e, // B Compare data +H8500_cmp_i, // W Compare data +H8500_exts, // B Convert byte to word by extending the sign bit +H8500_extu, // B Convert byte to word data by padding with zero bits +H8500_tst, // B/W Compare with 0 +H8500_neg, // B/W Negate +H8500_clr, // B/W Make zero +H8500_tas, // B Test and set + +// Logic Operations + +H8500_and, // B/W Logical AND +H8500_or, // B/W Logical OR +H8500_xor, // B/W Exclusive OR +H8500_not, // B/W Bitwise NOT + +// Shift Operations + +H8500_shal, // B/W Arithmetic shift left +H8500_shar, // B/W Arithmetic shift right +H8500_shll, // B/W Logical shift left +H8500_shlr, // B/W Logical shift right +H8500_rotl, // B/W Rotate left +H8500_rotr, // B/W Rotate right +H8500_rotxl, // B/W Rotate through carry left +H8500_rotxr, // B/W Rotate through carry right + +// Bit Manipulations + +H8500_bset, // B/W Test bit and set +H8500_bclr, // B/W Test bit and clear +H8500_bnot, // B/W Test bit and invert +H8500_btst, // B/W Test bit + +// Branching Instructions + +H8500_bra, // Branch Always +H8500_brn, // Branch Never +H8500_bhi, // Branch if High (C|Z = 0) +H8500_bls, // Branch if Low or Same (C|Z = 1) +H8500_bcc, // Branch if Carry Clear (C = 0) +H8500_bcs, // Branch if Carry Set (C = 1) +H8500_bne, // Branch if Not Equal (Z = 0) +H8500_beq, // Branch if Equal (Z = 1) +H8500_bvc, // Branch if Overflow Clear (V = 0) +H8500_bvs, // Branch if Overflow Set (V = 1) +H8500_bpl, // Branch if Plus (N = 0) +H8500_bmi, // Branch if Minus (N = 1) +H8500_bge, // Branch if Greater or Equal (N^V = 0) +H8500_blt, // Branch if Less Than (N^V = 1) +H8500_bgt, // Branch if Greater Than (Z|(N^V) = 0) +H8500_ble, // Branch if Less or Equal (Z|(N^V) = 1) +H8500_jmp, // Branch unconditionally (same page) +H8500_pjmp, // Branch unconditionally (specified page) +H8500_bsr, // Branch to subroutine (same page) +H8500_jsr, // Branch to subroutine (same page) +H8500_pjsr, // Branch to subroutine (specified page) +H8500_rts, // Return from subroutine (same page) +H8500_prts, // Return from subroutine (different page) +H8500_rtd, // Return from subroutine (same page) and adjust SP +H8500_prtd, // Return from subroutine (different page) and adjust SP +H8500_scb, // Control loop + +// System Control Instructions + +H8500_trapa, // Generate trap exception +H8500_trap_vs, // Generate trap exception if the V bit is set +H8500_rte, // Return from exception-handling routine +H8500_link, // Create stack frame +H8500_unlk, // Deallocate stack frame +H8500_sleep, // Go to power-down state +H8500_ldc, // B/W Move to control register +H8500_stc, // B/W Move from control register +H8500_andc, // B/W Logically AND control register +H8500_orc, // B/W Logically OR control register +H8500_xorc, // B/W Logically exclusive-OR control register +H8500_nop, // No operation +H8500_bpt, // + +H8500_last, + + }; + + + + +enum +{ +DSP56_null = 0, // Unknown Operation + +DSP56_abs, // Absolute Value +DSP56_adc, // Add Long with Carry +DSP56_add, // Addition +DSP56_addl, // Shift Left and Add +DSP56_addr, // Shift Right and Add +DSP56_and, // Logical AND +DSP56_andi, // AND Immediate to Control Register +DSP56_asl, // Arithmetic Shift Left +DSP56_asl4, // Arithmetic Shift Left 4 +DSP56_asr, // Arithmetic Shift Right +DSP56_asr4, // Arithmetic Shift Right 4 +DSP56_asr16, // Arithmetic Shift Right 16 +DSP56_bfchg, // Test Bit Field and Change +DSP56_bfclr, // Clear Bit Field +DSP56_bfset, // Set Bit Field +DSP56_bftsth, // Test Bit Field High +DSP56_bftstl, // Test Bit Field Low +DSP56_bcc, // Branch Conditionaly +DSP56_bchg, // Bit Test and Change +DSP56_bclr, // Bit Test and Clear +DSP56_bra, // Branch Always +DSP56_brclr, // Branch if Bit Clear +DSP56_brkcc, // Exit Current DO Loop Conditionally +DSP56_brset, // Branch if Bit Set +DSP56_bscc, // Branch to Subroutine Conditionaly +DSP56_bsclr, // Branch to Subroutine if Bit Clear +DSP56_bset, // Bit Test and Set +DSP56_bsr, // Branch to Subroutine +DSP56_bsset, // Branch to Subroutine if Bit Set +DSP56_btst, // Bit Test on Memory and Registers +DSP56_chkaau, // Check address ALU result +DSP56_clb, // Count Leading Bits +DSP56_clr, // Clear an Operand +DSP56_clr24, // Clear 24 MS-bits of Accumulator +DSP56_cmp, // Compare +DSP56_cmpm, // Compare Magnitude +DSP56_cmpu, // Compare Unsigned +DSP56_debug, // Enter Debug Mode +DSP56_debugcc, // Enter Debug Mode Conditionally +DSP56_dec, // Decrement by One +DSP56_dec24, // Decrement 24 MS-bit of Accumulator +DSP56_div, // Divide Iteration +DSP56_dmac, // Double-Precision Multiply-Accumulate With Right Shift +DSP56_do, // Start Hardware Loop +DSP56_do_f, // Start Infinite Loop +DSP56_dor, // Start PC-Relative Hardware Loop +DSP56_dor_f, // Start PC-Relative Infinite Loop +DSP56_enddo, // Exit from Hardware Loop +DSP56_eor, // Logical Exclusive OR +DSP56_extract, // Extract Bit Field +DSP56_extractu, // Extract Unsigned Bit Field +DSP56_ext, // Sign Extend Accumulator +DSP56_ill, // Illegal Instruction +DSP56_imac, // Integer Multiply-Accumulate +DSP56_impy, // Integer Multiply +DSP56_inc, // Increment by One +DSP56_inc24, // Increment 24 MS-bit of Accumulator +DSP56_insert, // Insert Bit Field +DSP56_jcc, // Jump Conditionally +DSP56_jclr, // Jump if Bit Clear +DSP56_jmp, // Jump +DSP56_jscc, // Jump to Subroutine Conditionally +DSP56_jsclr, // Jump to Subroutine if Bit Clear +DSP56_jset, // Jump if Bit Set +DSP56_jsr, // Jump to Subroutine +DSP56_jsset, // Jump to Subroutine if Bit Set +DSP56_lra, // Load PC-Reliative Address +DSP56_lsl, // Logical Shift Left +DSP56_lsr, // Logical Shift Right +DSP56_lua, // Load Updated Address +DSP56_lea, // Load Updated Address +DSP56_mac, // Signed Multiply-Accumulate +DSP56_maci, // Signed Multiply-Accumulate With Immediate Operand +DSP56_mac_s_u, // Mixed Multiply-Accumulate +DSP56_macr, // Signed Multiply-Accumulate and Round +DSP56_macri, // Signed Multiply-Accumulate and Round With Immediate Operand +DSP56_max, // Transfer by Signed Value +DSP56_maxm, // Transfer by Magnitude +DSP56_merge, // Merge Two Half Words +DSP56_move, // Move Data +DSP56_movec, // Move Control Register +DSP56_movei, // Move Immediate Short +DSP56_movem, // Move Program Memory +DSP56_movep, // Move Peripheral Data +DSP56_moves, // Move Absolute Short +DSP56_mpy, // Signed Multiply +DSP56_mpyi, // Signed Multiply With Immediate Operand +DSP56_mpy_s_u, // Mixed Multiply +DSP56_mpyr, // Signed Multiply and Round +DSP56_mpyri, // Signed Multiply and Round With Immediate Operand +DSP56_neg, // Negate Accumulator +DSP56_negc, // Negate Accumulator +DSP56_nop, // No Operation +DSP56_norm, // Norm Accumulator Iteration +DSP56_normf, // Fast Accumulator Normalization +DSP56_not, // Logical Complement +DSP56_or, // Logical Inclusive OR +DSP56_ori, // OR Immediate to Control Register +DSP56_pflush, // Program Cache Flush +DSP56_pflushun, // Program Cache Flush Unlocked Sectors +DSP56_pfree, // Program Cache Global Unlock +DSP56_plock, // Lock Instruction Cache Sector +DSP56_plockr, // Lock Instruction Cache Relative Sector +DSP56_punlock, // Unlock Instruction Cache Sector +DSP56_punlockr, // Unlock Instruction Cache Relative Sector +DSP56_rep, // Repeat Next Instruction +DSP56_repcc, // Repeat Next Instruction +DSP56_reset, // Reset On-Chip Peripheral Devices +DSP56_rnd, // Round Accumulator +DSP56_rol, // Rotate Left +DSP56_ror, // Rotate Right +DSP56_rti, // Return from Interrupt +DSP56_rts, // Return from Subroutine +DSP56_sbc, // Subtract Long with Carry +DSP56_stop, // Stop Processing (Low-Power Standby) +DSP56_sub, // Subtract +DSP56_subl, // Shift Left and Subtract +DSP56_subr, // Shift Right and Subtract +DSP56_swap, // Swap Accumulator Words +DSP56_tcc, // Transfer Conditionally +DSP56_tfr, // Transfer Data ALU Register +DSP56_tfr2, // Transfer Data ALU Register +DSP56_tfr3, // Transfer Data ALU Register +DSP56_trap, // Software Interrupt +DSP56_trapcc, // Software Interrupt Conditionally +DSP56_tst, // Test an Operand +DSP56_tst2, // Test an Operand +DSP56_vsl, // Viterbi Shift Left +DSP56_wait, // Wait for Interrupt or DMA Request (Low-Power Standby) +DSP56_zero, // Zero Extend Accumulator +DSP56_swi, // Software Interrupt (only for 56000) +DSP56_pmov, // Pseudo insn +DSP56_last, + +}; + + + + +enum +{ +DSP96_null = 0, // Unknown Operation + +DSP96_abs, // Absolute Value +DSP96_add, // Addition +DSP96_addc, // Add with Carry +DSP96_and, // Logical AND +DSP96_andc, // AND Immediate with Complement +DSP96_andi, // AND Immediate to Control Register +DSP96_asl, // Arithmetic Shift Left +DSP96_asr, // Arithmetic Shift Right +DSP96_bcc, // Branch Conditionally (indirect) +DSP96_bccd, // Branch Conditionally (direct) +DSP96_bchg, // Bit Test and Change +DSP96_bclr, // Bit Test and Clear +DSP96_bfind, // Find Leading One +DSP96_bra, // Branch Always +DSP96_brclr, // Branch if Bit Clear +DSP96_brset, // Branch if Bit Set +DSP96_bscc, // Branch to Subroutine Conditionally (indirect) +DSP96_bsccd, // Branch to Subroutine Conditionally (direct) +DSP96_bsclr, // Branch to Subroutine if Bit Clear +DSP96_bset, // Bit Test and Set +DSP96_bsr, // Branch to Subroutine (indirect) +DSP96_bsrd, // Branch to Subroutine (direct) +DSP96_bsset, // Branch to Subroutine if Bit Set +DSP96_btst, // Bit Test on Memory and Registers +DSP96_clr, // Clear an Operand +DSP96_cmp, // Compare +DSP96_cmpg, // Graphics Compare with Trivial Accept.Reject Flags +DSP96_debugcc, // Enter Debug Mode Conditionally +DSP96_dec, // Decrement by One +DSP96_do, // Start Hardware Loop +DSP96_dor, // Start PC-Relative Hardware Loop +DSP96_enddo, // Exit from Hardware Loop +DSP96_eor, // Logical Exclusive OR +DSP96_ext, // Sign Extend 16-Bit To 32-Bit +DSP96_extb, // Sign Extend 8-Bit to 32-Bit +DSP96_fabs, // Absolute Value +DSP96_fadd, // Add +DSP96_faddsub, // Add and Subtract +DSP96_fbcc, // Branch Conditionally (Floating-Point Condition) (indirect) +DSP96_fbccd, // Branch Conditionally (Floating-Point Condition) (direct) +DSP96_fbscc, // Branch to Subroutine Conditionally (Floating-Point Condition) (indirect) +DSP96_fbsccd, // Branch to Subroutine Conditionally (Floating-Point Condition) (direct) +DSP96_fclr, // Clear a Floating-Point Operand +DSP96_fcmp, // Compare +DSP96_fcmpg, // Graphics Compare with Trivial Accept.Reject Flags +DSP96_fcmpm, // Compare Magnitude +DSP96_fcopys, // Copy Sign +DSP96_fdebugcc, // Enter Debug Mode Conditionally +DSP96_fgetman, // Get Mantissa +DSP96_fint, // Convert to Floating-Point Integer +DSP96_fjcc, // Jump Conditionally (indirect) +DSP96_fjccd, // Jump Conditionally (direct) +DSP96_fjscc, // Jump to Subroutine Conditionally (indirect) +DSP96_fjsccd, // Jump to Subroutine Conditionally (direct) +DSP96_float, // Integer to Floating-Point Conversion +DSP96_floatu, // Unsigned Integer to SP Floating-Point Conversion +DSP96_floor, // Convert to Floating-Point Integer round to -Infinity +DSP96_fmove, // Move FP Data Register(s) +DSP96_fmpyfadd, // Multiply and Add +// DSP96_fmpyfaddx, // Multiply and Add (Single Extended Precision) (Handled with DSP96_fmpyfadd) +DSP96_fmpyfaddsub, // Multiply, Add and Subtract +// DSP96_fmpyfaddsubx, // Multiply, Add and Subtract (Single Extended Precision) (Handled with DSP96_fmpyfaddsub) +DSP96_fmpyfsub, // Multiply and Subtract +// DSP96_fmpyfsubx, // Multiply and Subtract (Single Extended Precision) (Handled with DSP96_fmpyfsub) +DSP96_fmpy, // Multiply +DSP96_fneg, // Change sign +DSP96_fscale, // Scale a Floating-Point Operand +DSP96_fseedd, // Reciprocal Approximation +DSP96_fseedr, // Square-Root Reciprocal Approximation +DSP96_fsub, // Subtract +DSP96_ftfr, // Transfer Floating-Point Register +DSP96_ftrapcc, // Conditional Software Interrupt +DSP96_ftst, // Test a floating-Point Operand +DSP96_getexp, // Get Exponent +DSP96_illegal, // Illegal Instruction +DSP96_inc, // Increment by One +DSP96_int, // Floating-Point to Integer Conversion +DSP96_intrz, // Floating-Point to Integer Conversion Round to Zero +DSP96_intu, // Floating-Point to Unsigned Integer Conversion +DSP96_inturz, // Floating-Point to Unsigned Integer Conversion Round to Zero +DSP96_jcc, // Jump Conditionally (indirect) +DSP96_jccd, // Jump Conditionally (direct) +DSP96_jclr, // Jump if Bit Clear +// DSP96_jmp, // Jump (The same as jcc with condition code = 11111) +DSP96_join, // Join two 16-Bit Integers +DSP96_joinb, // Join two 8-Bit Integers +DSP96_jscc, // Jump to Subroutine Conditionally +DSP96_jsccd, // Jump to Subroutine Conditionally +DSP96_jsclr, // Jump to Subroutine if Bit Clear +DSP96_jset, // Jump if Bit Set +// DSP96_jsr, // Jump to Subroutine ( The same as jscc with condition code = 11111) +DSP96_jsset, // Jump to Subroutine if Bit Set +DSP96_lea, // Load Effective Address +DSP96_lra, // Load PC Relative Address +DSP96_lsl, // Logical Shift Left +DSP96_lsr, // Logical Shift Right +DSP96_move, // Move Data Register(s) +DSP96_movec, // Move Control Register +DSP96_movei, // Move Immediate +DSP96_movem, // Move Program Memory +DSP96_movep, // Move Peripheral Data +DSP96_moves, // Move Absolute Short +DSP96_moveta, // Move Data Register(s) and Test Address +DSP96_mpys, // Signed Multiply +DSP96_mpyu, // Unsigned Multiply +DSP96_neg, // Negate Accumulator +DSP96_negc, // Negate with Carry +DSP96_nop, // No Operation +DSP96_not, // Logical Complement +DSP96_or, // Logical Inclusive OR +DSP96_orc, // OR With Compliment +DSP96_ori, // OR Immediate to Control Register +DSP96_rep, // Repeat Next Instruction +DSP96_reset, // Reset On-Chip Peripheral Devices +DSP96_rol, // Rotate Left +DSP96_ror, // Rotate Right +DSP96_rti, // Return from Interrupt +DSP96_rtr, // Return from Subroutine and Restore Status Register +DSP96_rts, // Return from Subroutine +DSP96_setw, // Set an Operand +DSP96_split, // Extract 16-Bit Integer +DSP96_splitb, // Extract 8-Bit Integer +DSP96_stop, // Stop Processing (Low Power Stand-by) +DSP96_sub, // Subtract +DSP96_subc, // Subtract with Carry +DSP96_tfr, // Transfer Data ALU Register +DSP96_trapcc, // Software Interrupt Conditionally +DSP96_tst, // Test an Operand +DSP96_wait, // Wait for Interrupt or DMA Request (Low Power Stand-by) +DSP96_last, + +}; + +enum PMNum // Parallel Move enumeration +{ + PM96_NoMove, + PM96_R2R, // Register to register parallel move + PM96_Update, // Move update + PM96_XYMem, // X or Y memory move + PM96_XYmemR, // X or Y memory and Registry move + PM96_Long, // Long Memory move + PM96_XY, // XY Memory move + + PM96_IFcc, // Integer if conditional Instruction without CCR update + // All the following moves are handled by IFcc + // PM96_FFcc, // Floating-Point if conditional Instruction without CCR, ER, IER update + // PM96_FFccU, // Floating-Point if conditional Instruction with CCR, ER, IER update + // PM96_IFccU, // Integer if conditional Instruction with CCR update +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +C166_null = 0, // Unknown Operation + +C166_add, // Integer Addition +C166_addb, // Integer Addition Byte +C166_addc, // Integer Addition with Carry +C166_addcb, // Integer Addition with Carry Byte +C166_and, // Logical AND +C166_andb, // Logical AND Byte +C166_ashr, // Arithmetic Shift Right +C166_atomic, // Begin ATOMIC Sequence +C166_band, // Bit Logical AND +C166_bclr, // Bit Clear +C166_bcmp, // Bit to Bit Compare +C166_bfldh, // Bit Field High Byte +C166_bfldl, // Bit Field Low Byte +C166_bmov, // Bit to Bit Move +C166_bmovn, // Bit to Bit Move and Negate +C166_bor, // Bit Logical OR +C166_bset, // Bit Set +C166_bxor, // Bit Logical XOR +C166_calla, // Call Subroutine Absolute +C166_calli, // Call Subroutine Indirect +C166_callr, // Call Subroutine Relative +C166_calls, // Call Inter-Segment Subroutine +C166_cmp, // Integer Compare +C166_cmpb, // Integer Compare Byte +C166_cmpd1, // Integer Compare and Decrement by 1 +C166_cmpd2, // Integer Compare and Decrement by 2 +C166_cmpi1, // Integer Compare and Increment by 1 +C166_cmpi2, // Integer Compare and Increment by 2 +C166_cpl, // Integer One's Complement +C166_cplb, // Integer One's Complement Byte +C166_diswdt, // Disable Watchdog Timer +C166_div, // 16-by-16 Signed Division +C166_divl, // 32-by-16 Signed Division +C166_divlu, // 32-by-16 Unsigned Division +C166_divu, // 16-by-16 Unsigned Division +C166_einit, // End of Intialization +C166_extr, // Begin Extended Register Sequence +C166_extp, // Begin Extended Page Sequence +C166_extpr, // Begin Extended Page and Register Sequence +C166_exts, // Begin Extended Segment Sequence +C166_extsr, // Begin Extended Segment and Register Sequence +C166_idle, // Enter Idle Mode +C166_jb, // Relative Jump if Bit Set +C166_jbc, // Relative Jump if Bit Set and Clear Bit +C166_jmpa, // Absolute Conditional Jump +C166_jmpi, // Indirect Conditional Jump +C166_jmpr, // Relative Conditional Jump +C166_jmps, // Absolute Inter-Segment Jump +C166_jnb, // Relative Jump if Bit Clear +C166_jnbs, // Relative Jump if Bit Clear and Set Bit +C166_mov, // Move Word +C166_movb, // Move Byte +C166_movbs, // Move Byte Sign Extend +C166_movbz, // Move Byte Zero Extend +C166_mul, // Signed Multiplication +C166_mulu, // Unsigned Multiplication +C166_neg, // Integer Two's Complement +C166_negb, // Integer Two's Complement Byte +C166_nop, // No Operation +C166_or, // Logical OR +C166_orb, // Logical OR Byte +C166_pcall, // Push Word and Call Subroutine Absolute +C166_pop, // Pop Word from System Stack +C166_prior, // Prioritize Register +C166_push, // Push Word on System Stack +C166_pwrdn, // Enter Power Down Mode +C166_ret, // Return from Subroutine +C166_reti, // Return from Interrupt Routine +C166_retp, // Return from Subroutine and Pop Word +C166_rets, // Return from Inter-Segment Subroutine +C166_rol, // Rotate Left +C166_ror, // Rotate Right +C166_scxt, // Switch Context +C166_shl, // Shift Left +C166_shr, // Shift Rightt +C166_srst, // Software Reset +C166_srvwdt, // Service Watchdog Timer +C166_sub, // Integer Subtraction +C166_subb, // Integer Subtraction Byte +C166_subc, // Integer Subtraction with Carry +C166_subcb, // Integer Subtraction with Carry Byte +C166_trap, // Software Trap +C166_xor, // Logical Exclusive OR +C166_xorb, // Logical Exclusive OR Byte + +// ST10 MAC instructions + +ST10_CoABS, // Absolute Value +ST10_CoADD, // Add +ST10_CoASHR, // Accumulator Arithmetic Shift Right with Optional Round +ST10_CoCMP, // Compare +ST10_CoLOAD, // Load Accumulator +ST10_CoMAC, // Multiply-Accumulate & Optional Round +ST10_CoMACM, // Multiply-Accumulate Parallel Data Move & Optional Round +ST10_CoMAX, // Maximum +ST10_CoMIN, // Minimum +ST10_CoMOV, // Memory to Memory Move +ST10_CoMUL, // Multiply & Optional Round +ST10_CoNEG, // Negate Accumulator with Optional Rounding +ST10_CoNOP, // No-Operation +ST10_CoRND, // Round Accumulator +ST10_CoSHL, // Accumulator Logical Shift Left +ST10_CoSHR, // Accumulator Logical Shift Right +ST10_CoSTORE, // Store a MAC-Unit Register +ST10_CoSUB, // Subtract + +// missing C166v2/ST10 instructions + +C166_enwdt, // Enable Watchdog Timer +C166_sbrk, // Software Break + +C166_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +ST20_null = 0, // Unknown Operation + +// C1 instructions + +ST20_adc, // add constant +ST20_add, // add +ST20_addc, // add with carry +ST20_ajw, // adjust work space +ST20_and, // and +ST20_arot, // anti-rotate stack +ST20_ashr, // arithmetic shift right +ST20_biquad, // biquad IIR filter step +ST20_bitld, // load bit +ST20_bitmask, // create bit mask +ST20_bitst, // store bit +ST20_breakpoint, // breakpoint +ST20_cj, // conditional jump +ST20_dequeue, // dequeue a process +ST20_divstep, // divide step +ST20_dup, // duplicate +ST20_ecall, // exception call +ST20_enqueue, // enqueue a process +ST20_eqc, // equals constant +ST20_eret, // exception return +ST20_fcall, // function call +ST20_gajw, // general adjust workspace +ST20_gt, // greater than +ST20_gtu, // greater than unsigned +ST20_io, // input/output +ST20_j, // jump +ST20_jab, // jump absolute +ST20_lbinc, // load byte and increment +ST20_ldc, // load constant +ST20_ldl, // load local +ST20_ldlp, // load local pointer +ST20_ldnl, // load non-local +ST20_ldnlp, // load non-local pointer +ST20_ldpi, // load pointer to instruction +ST20_ldprodid, // load product identity +ST20_ldtdesc, // load task descriptor +ST20_lsinc, // load sixteen and increment +ST20_lsxinc, // load sixteen sign extended and increment +ST20_lwinc, // load word and increment +ST20_mac, // multiply accumulate +ST20_mul, // multiply +ST20_nfix, // negative prefix +ST20_nop, // no operation +ST20_not, // bitwise not +ST20_opr, // operate +ST20_or, // or +ST20_order, // order +ST20_orderu, // unsigned order +ST20_pfix, // prefix +ST20_rev, // reverse +ST20_rmw, // read modify write +ST20_rot, // rotate stack +ST20_run, // run process +ST20_saturate, // saturate +ST20_sbinc, // store byte and increment +ST20_shl, // shift left +ST20_shr, // shift right +ST20_signal, // signal +ST20_smacinit, // initialize short multiply accumulate loop +ST20_smacloop, // short multiply accumulate loop +ST20_smul, // short multiply +ST20_ssinc, // store sixteen and increment +ST20_statusclr, // clear bits in status register +ST20_statusset, // set bits in status register +ST20_statustst, // test status register +ST20_stl, // store local +ST20_stnl, // store non-local +ST20_stop, // stop process +ST20_sub, // subtract +ST20_subc, // subtract with carry +ST20_swap32, // byte swap 32 +ST20_swinc, // store word and increment +ST20_timeslice, // timeslice +ST20_umac, // unsigned multiply accumulate +ST20_unsign, // unsign argument +ST20_wait, // wait +ST20_wsub, // word subscript +ST20_xbword, // sign extend byte to word +ST20_xor, // exclusive or +ST20_xsword, // sign extend sixteen to word + +// C2-C4 instructions + +ST20_alt, // alt start +ST20_altend, // alt end +ST20_altwt, // alt wait +ST20_bcnt, // byte count +ST20_bitcnt, // count bits set in word +ST20_bitrevnbits, // reverse bottom n bits in word +ST20_bitrevword, // reverse bits in word +ST20_bsub, // byte subscript +ST20_call, // call +ST20_causeerror, // cause error +ST20_cb, // check byte +ST20_cbu, // check byte unsigned +ST20_ccnt1, // check count from 1 +ST20_cflerr, // check floating point error +ST20_cir, // check in range +ST20_ciru, // check in range unsigned +ST20_clockdis, // clock disable +ST20_clockenb, // clock enable +ST20_clrhalterr, // clear halt-on error flag +ST20_crcbyte, // calculate CRC on byte +ST20_crcword, // calculate CRC on word +ST20_cs, // check sixteen +ST20_csngl, // check single +ST20_csu, // check sixteen unsigned +ST20_csub0, // check subscript from 0 +ST20_cword, // check word +ST20_devlb, // device load byte +ST20_devls, // device load sixteen +ST20_devlw, // device load word +ST20_devmove, // device move +ST20_devsb, // device store byte +ST20_devss, // device store sixteen +ST20_devsw, // device store word +ST20_diff, // difference +ST20_disc, // disable channel +ST20_diss, // disable skip +ST20_dist, // disable timer +ST20_div, // divide +ST20_enbc, // enable channel +ST20_enbs, // enable skip +ST20_enbt, // enable timer +ST20_endp, // end process +ST20_fmul, // fractional multiply +ST20_fptesterr, // test for FPU error +ST20_gcall, // general call +ST20_gintdis, // general interrupt disable +ST20_gintenb, // general interrupt enable +ST20_in, // input message +ST20_insertqueue, // insert at front of scheduler queue +ST20_intdis, // (localised) interrupt disable +ST20_intenb, // (localised) interrupt enable +ST20_iret, // interrupt return +ST20_ladd, // long add +ST20_lb, // load byte +ST20_lbx, // load byte and sign extend +ST20_ldclock, // load clock +ST20_lddevid, // load device identity +ST20_ldiff, // long diff +ST20_ldinf, // load infinity +ST20_ldiv, // long divide +ST20_ldmemstartval, // load value of MemStart address +ST20_ldpri, // load current priority +ST20_ldshadow, // load shadow registers +ST20_ldtimer, // load timer +ST20_ldtraph, // load trap handler +ST20_ldtrapped, // load trapped process status +ST20_lend, // loop end +ST20_lmul, // long multiply +ST20_ls, // load sixteen +ST20_lshl, // long shift left +ST20_lshr, // long shift right +ST20_lsub, // long subtract +ST20_lsum, // long sum +ST20_lsx, // load sixteen and sign extend +ST20_mint, // minimum integer +ST20_move, // move message +ST20_move2dall, // 2D block copy +ST20_move2dinit, // initialize data for 2D block move +ST20_move2dnonzero, // 2D block copy non-zero bytes +ST20_move2dzero, // 2D block copy zero bytes +ST20_norm, // normalize +ST20_out, // output message +ST20_outbyte, // output byte +ST20_outword, // output word +ST20_pop, // pop processor stack +ST20_postnormsn, // post-normalize correction of single length fp number +ST20_prod, // product +ST20_reboot, // reboot +ST20_rem, // remainder +ST20_resetch, // reset channel +ST20_restart, // restart +ST20_ret, // return +ST20_roundsn, // round single length floating point number +ST20_runp, // run process +ST20_satadd, // saturating add +ST20_satmul, // saturating multiply +ST20_satsub, // saturating subtract +ST20_saveh, // save high priority queue registers +ST20_savel, // save low priority queue registers +ST20_sb, // store byte +ST20_seterr, // set error flags +ST20_sethalterr, // set halt-on error flag +ST20_settimeslice, // set timeslicing status +ST20_slmul, // signed long multiply +ST20_ss, // store sixteen +ST20_ssub, // sixteen subscript +ST20_startp, // start process +ST20_stclock, // store clock register +ST20_sthb, // store high priority back pointer +ST20_sthf, // store high priority front pointer +ST20_stlb, // store low priority back pointer +ST20_stlf, // store low priority front pointer +ST20_stoperr, // stop on error +ST20_stopp, // stop process +ST20_stshadow, // store shadow registers +ST20_sttimer, // store timer +ST20_sttraph, // store trap handler +ST20_sttrapped, // store trapped process +ST20_sulmul, // signed timer unsigned long multiply +ST20_sum, // sum +ST20_swapqueue, // swap scheduler queue +ST20_swaptimer, // swap timer queue +ST20_talt, // timer alt start +ST20_taltwt, // timer alt wait +ST20_testerr, // test error flag +ST20_testhalterr, // test halt-on error flag +ST20_testpranal, // test processor analysing +ST20_tin, // timer input +ST20_trapdis, // trap disable +ST20_trapenb, // trap enable +ST20_tret, // trap return +ST20_unpacksn, // unpack single length fp number +ST20_wcnt, // word count +ST20_wsubdb, // form double word subscript +ST20_xdble, // extend to double +ST20_xword, // extend word + +ST20_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +ST7_null = 0, // Unknown Operation + +ST7_adc, // Add with Carry +ST7_add, // Addition +ST7_and, // Logical And +ST7_bcp, // Bit compare +ST7_bres, // Bit Reset +ST7_bset, // Bit Set +ST7_btjf, // Jump if bit is false +ST7_btjt, // Jump if bit is true +ST7_call, // Call subroutine +ST7_callr, // Call subroutine relative +ST7_clr, // Clear +ST7_cp, // Arithmetic Compare +ST7_cpl, // One Complement +ST7_dec, // Decrement +ST7_halt, // Halt +ST7_iret, // Interrupt routine return +ST7_inc, // Increment +ST7_jp, // Absolute Jump +ST7_jra, // Jump relative always +ST7_jrt, // Jump relative +ST7_jrf, // Never jump +ST7_jrih, // Jump if Port INT pin = 1 +ST7_jril, // Jump if Port INT pin = 0 +ST7_jrh, // Jump if H = 1 +ST7_jrnh, // Jump if H = 0 +ST7_jrm, // Jump if I = 1 +ST7_jrnm, // Jump if I = 0 +ST7_jrmi, // Jump if N = 1 (minus) +ST7_jrpl, // Jump if N = 0 (plus) +ST7_jreq, // Jump if Z = 1 (equal) +ST7_jrne, // Jump if Z = 0 (not equal) +ST7_jrc, // Jump if C = 1 +ST7_jrnc, // Jump if C = 0 +ST7_jrult, // Jump if C = 1 +ST7_jruge, // Jump if C = 0 +ST7_jrugt, // Jump if (C + Z = 0) +ST7_jrule, // Jump if (C + Z = 1) +ST7_ld, // Load +ST7_mul, // Multiply +ST7_neg, // Negate +ST7_nop, // No Operation +ST7_or, // OR Operation +ST7_pop, // Pop from the Stack +ST7_push, // Push onto the Stack +ST7_rcf, // Reset carry flag +ST7_ret, // Subroutine Return +ST7_rim, // Enable Interrupts +ST7_rlc, // Rotate left true +ST7_rrc, // Rotate right true +ST7_rsp, // Reset Stack Pointer +ST7_sbc, // Subtract with Carry +ST7_scf, // Set carry flag +ST7_sim, // Disable Interrupts +ST7_sla, // Shift left Arithmetic +ST7_sll, // Shift left Logic +ST7_srl, // Shift right Logic +ST7_sra, // Shift right Arithmetic +ST7_sub, // Substraction +ST7_swap, // SWAP nibbles +ST7_tnz, // Test for Neg & Zero +ST7_trap, // S/W trap +ST7_wfi, // Wait for Interrupt +ST7_xor, // Exclusive OR + +ST7_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +IA64_null, // 0 +IA64_0, // 1 +IA64_1, // 2 +IA64_a, // 3 +IA64_acq, // 4 +IA64_add, // 5 Add +IA64_addl, // 6 +IA64_addp4, // 7 Add pointer +IA64_adds, // 8 +IA64_alloc, // 9 Allocate stack frame +IA64_and, // 10 Logical AND +IA64_andcm, // 11 And complement +IA64_b, // 12 +IA64_bias, // 13 +IA64_br, // 14 Branch +IA64_break, // 15 Break +IA64_brl, // 16 Branch long +IA64_brp, // 17 Branch predict +IA64_bsw, // 18 Bank switch +IA64_c, // 19 +IA64_call, // 20 +IA64_cexit, // 21 +IA64_chk, // 22 Speculation check +IA64_cloop, // 23 +IA64_clr, // 24 +IA64_clrrrb, // 25 Clear RRB +IA64_cmp, // 26 Compare +IA64_cmp4, // 27 Compare word +IA64_cmpxchg1, // 28 Compare and exchange byte +IA64_cmpxchg2, // 29 Compare and exchange halfword +IA64_cmpxchg4, // 30 Compare and exchange word +IA64_cmpxchg8, // 31 Compare and exchange double word +IA64_cond, // 32 +IA64_cover, // 33 Cover stack frame +IA64_ctop, // 34 +IA64_czx1, // 35 Compute zero index +IA64_czx2, // 36 Compute zero index +IA64_d, // 37 +IA64_dep, // 38 Deposit +IA64_dpnt, // 39 +IA64_dptk, // 40 +IA64_e, // 41 +IA64_epc, // 42 Enter privileged code +IA64_eq, // 43 +IA64_excl, // 44 +IA64_exit, // 45 +IA64_exp, // 46 +IA64_extr, // 47 Extract +IA64_f, // 48 +IA64_fabs, // 49 Floating point absolute value +IA64_fadd, // 50 Floating point add +IA64_famax, // 51 Floating point absolute maximum +IA64_famin, // 52 Floating point absolute minimum +IA64_fand, // 53 Floating point logical and +IA64_fandcm, // 54 Floating point and complement +IA64_fault, // 55 +IA64_fc, // 56 Flush cache +IA64_fchkf, // 57 Floating point check flags +IA64_fclass, // 58 Floating point class +IA64_fclrf, // 59 Floating point clear flags +IA64_fcmp, // 60 Floating point compare +IA64_fcvt, // 61 Convert floating point to/from integer +IA64_fetchadd4, // 62 Fetch word and add immediate +IA64_fetchadd8, // 63 Fetch double word and add immediate +IA64_few, // 64 +IA64_fill, // 65 +IA64_flushrs, // 66 Flush register stack +IA64_fma, // 67 Floating point multiply add +IA64_fmax, // 68 Floating point maximum +IA64_fmerge, // 69 Floating point merge +IA64_fmin, // 70 Floating point minimum +IA64_fmix, // 71 Floating point mix +IA64_fmpy, // 72 Floating point multiply +IA64_fms, // 73 Floating point multiply subtract +IA64_fneg, // 74 Floating point negate +IA64_fnegabs, // 75 Floating point negate absolute value +IA64_fnma, // 76 Floating point negative multiply add +IA64_fnmpy, // 77 Floating point negative multiply +IA64_fnorm, // 78 Floating point normalize +IA64_for, // 79 Floating point logical or +IA64_fpabs, // 80 Floating point parallel absolute value +IA64_fpack, // 81 Floating point pack +IA64_fpamax, // 82 Floating point parallel absolute maximum +IA64_fpamin, // 83 Floating point parallel absolute minimum +IA64_fpcmp, // 84 Floating point parallel compare +IA64_fpcvt, // 85 Floating point parallel conversion +IA64_fpma, // 86 Floating point parallel multiply add +IA64_fpmax, // 87 Floating point parallel maximum +IA64_fpmerge, // 88 Floating point parallel merge +IA64_fpmin, // 89 Floating point parallel minimum +IA64_fpmpy, // 90 Floating point parallel multiply +IA64_fpms, // 91 Floating point parallel multiply subtract +IA64_fpneg, // 92 Floating point parallel negate +IA64_fpnegabs, // 93 Floating point parallel negate absolute value +IA64_fpnma, // 94 Floating point parallel negative multiply add +IA64_fpnmpy, // 95 Floating point parallel negative multiply +IA64_fprcpa, // 96 Floating point parallel reciprocal approximation +IA64_fprsqrta, // 97 Floating point parallel reciprocal square root approximation +IA64_frcpa, // 98 Floating point reciprocal approximation +IA64_frsqrta, // 99 Floating point reciprocal square root approximation +IA64_fselect, // 100 Floating point select +IA64_fsetc, // 101 Floating point set controls +IA64_fsub, // 102 Floating point subtract +IA64_fswap, // 103 Floating point swap +IA64_fsxt, // 104 Floating point sign extend +IA64_fwb, // 105 Flush write buffers +IA64_fx, // 106 +IA64_fxor, // 107 Floating point exclusive or +IA64_fxu, // 108 +IA64_g, // 109 +IA64_ga, // 110 +IA64_ge, // 111 +IA64_getf, // 112 Get floating point value or exponent or significand +IA64_geu, // 113 +IA64_gt, // 114 +IA64_gtu, // 115 +IA64_h, // 116 +IA64_hu, // 117 +IA64_i, // 118 +IA64_ia, // 119 +IA64_imp, // 120 +IA64_invala, // 121 Invalidate ALAT +IA64_itc, // 122 Insert translation cache +IA64_itr, // 123 Insert translation register +IA64_l, // 124 +IA64_ld1, // 125 Load byte +IA64_ld2, // 126 Load halfword +IA64_ld4, // 127 Load word +IA64_ld8, // 128 Load double word +IA64_ldf, // 129 Floating point load +IA64_ldf8, // 130 Floating point load +IA64_ldfd, // 131 Floating point load +IA64_ldfe, // 132 Floating point load +IA64_ldfp8, // 133 Floating point load pair +IA64_ldfpd, // 134 Floating point load pair +IA64_ldfps, // 135 Floating point load pair +IA64_ldfs, // 136 Floating point load +IA64_le, // 137 +IA64_leu, // 138 +IA64_lfetch, // 139 Line prefetch +IA64_loadrs, // 140 Load register stack +IA64_loop, // 141 +IA64_lr, // 142 +IA64_lt, // 143 +IA64_ltu, // 144 +IA64_lu, // 145 +IA64_m, // 146 +IA64_many, // 147 +IA64_mf, // 148 Memory fence +IA64_mix1, // 149 Mix bytes +IA64_mix2, // 150 Mix halfwords +IA64_mix4, // 151 Mix words +IA64_mov, // 152 Move register +IA64_movl, // 153 Move long immediate +IA64_mux1, // 154 Mux byte +IA64_mux2, // 155 Mux halfword +IA64_nc, // 156 +IA64_ne, // 157 +IA64_neq, // 158 +IA64_nge, // 159 +IA64_ngt, // 160 +IA64_nl, // 161 +IA64_nle, // 162 +IA64_nlt, // 163 +IA64_nm, // 164 +IA64_nop, // 165 No operation +IA64_nr, // 166 +IA64_ns, // 167 +IA64_nt1, // 168 +IA64_nt2, // 169 +IA64_nta, // 170 +IA64_nz, // 171 +IA64_or, // 172 Logical or +IA64_orcm, // 173 +IA64_ord, // 174 +IA64_pack2, // 175 Pack +IA64_pack4, // 176 Pack +IA64_padd1, // 177 Parallel add bytes +IA64_padd2, // 178 Parallel add halfwords +IA64_padd4, // 179 Parallel add words +IA64_pavg1, // 180 Parallel average bytes +IA64_pavg2, // 181 Parallel average halfwords +IA64_pavgsub1, // 182 Parallel average subtract bytes +IA64_pavgsub2, // 183 Parallel average subtract halfwords +IA64_pcmp1, // 184 Parallel compare bytes +IA64_pcmp2, // 185 Parallel compare halfwords +IA64_pcmp4, // 186 Parallel compare words +IA64_pmax1, // 187 Parallel maxmimum bytes +IA64_pmax2, // 188 Parallel maxmimum halfwords +IA64_pmin1, // 189 Parallel minimum bytes +IA64_pmin2, // 190 Parallel minimum halfwords +IA64_pmpy2, // 191 Parallel multiply +IA64_pmpyshr2, // 192 Parallel multiply and shift right +IA64_popcnt, // 193 Population count +IA64_pr, // 194 +IA64_probe, // 195 Probe address +IA64_psad1, // 196 Parallel sum of absolute difference +IA64_pshl2, // 197 Parallel shift left halfwords +IA64_pshl4, // 198 Parallel shift left words +IA64_pshladd2, // 199 Parallel shift left and Add +IA64_pshr2, // 200 Parallel shift right halfwords +IA64_pshr4, // 201 Parallel shift right words +IA64_pshradd2, // 202 Parallel shift right and Add +IA64_psub1, // 203 Parallel subtract bytes +IA64_psub2, // 204 Parallel subtract halfwords +IA64_psub4, // 205 Parallel subtract words +IA64_ptc, // 206 Purge translation cache +IA64_ptr, // 207 Purge translation register +IA64_r, // 208 +IA64_raz, // 209 +IA64_rel, // 210 +IA64_ret, // 211 +IA64_rfi, // 212 Return from interruption +IA64_rsm, // 213 Reset system mask +IA64_rum, // 214 Reset user mask +IA64_rw, // 215 +IA64_s, // 216 +IA64_s0, // 217 +IA64_s1, // 218 +IA64_s2, // 219 +IA64_s3, // 220 +IA64_sa, // 221 +IA64_se, // 222 +IA64_setf, // 223 Set floating point value, exponent, or significand +IA64_shl, // 224 Shift left +IA64_shladd, // 225 Shift left and Add +IA64_shladdp4, // 226 Shift left and Add pointer +IA64_shr, // 227 Shift right +IA64_shrp, // 228 Shift right pair +IA64_sig, // 229 +IA64_spill, // 230 +IA64_spnt, // 231 +IA64_sptk, // 232 +IA64_srlz, // 233 Serialize +IA64_ssm, // 234 Set system mask +IA64_sss, // 235 +IA64_st1, // 236 Store byte +IA64_st2, // 237 Store halfword +IA64_st4, // 238 Store word +IA64_st8, // 239 Store double word +IA64_stf, // 240 Store floating point +IA64_stf8, // 241 Store floating point +IA64_stfd, // 242 Store floating point +IA64_stfe, // 243 Store floating point +IA64_stfs, // 244 Store floating point +IA64_sub, // 245 Subtract +IA64_sum, // 246 Set user mask +IA64_sxt1, // 247 Sign extend byte +IA64_sxt2, // 248 Sign extend halfword +IA64_sxt4, // 249 Sign extend word +IA64_sync, // 250 Memory synchronization +IA64_tak, // 251 Translation access key +IA64_tbit, // 252 Test bit +IA64_thash, // 253 Translation hashed entry address +IA64_tnat, // 254 Test NaT +IA64_tpa, // 255 Translate to physical address +IA64_trunc, // 256 +IA64_ttag, // 257 Translation hashed entry tag +IA64_u, // 258 +IA64_unc, // 259 +IA64_unord, // 260 +IA64_unpack1, // 261 Unpack byte +IA64_unpack2, // 262 Unpack halfword +IA64_unpack4, // 263 Unpack word +IA64_uss, // 264 +IA64_uus, // 265 +IA64_uuu, // 266 +IA64_w, // 267 +IA64_wexit, // 268 +IA64_wtop, // 269 +IA64_x, // 270 +IA64_xchg1, // 271 Exchange bytes +IA64_xchg2, // 272 Exchange halfwords +IA64_xchg4, // 273 Exchange words +IA64_xchg8, // 274 Exchange double words +IA64_xf, // 275 +IA64_xma, // 276 Fixed point multiply add +IA64_xmpy, // 277 Fixed point multiply +IA64_xor, // 278 Exclusive or +IA64_xuf, // 279 +IA64_z, // 280 +IA64_zxt1, // 281 Zero extend byte +IA64_zxt2, // 282 Zero extend halfword +IA64_zxt4, // 283 Zero extend word +IA64_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +NET_null = 0, // Unknown Operation + +NET_add, // Add two values, returning a new value +NET_add_ovf, // Add signed integer values with overflow check +NET_add_ovf_un, // Add unsigned integer values with overflow check +NET_and, // Bitwise AND of two integral values, returns an integral value +NET_ann_arg, // +NET_ann_call, // Start of simple calling sequence +NET_ann_catch, // Start an exception filter or handler +NET_ann_data, // Multi-byte no operation +NET_ann_data_s, // Multi-byte no operation, short form +NET_ann_dead, // Stack location is no longer live +NET_ann_def, // SSA definition node +NET_ann_hoisted, // Start of the simple portion of a hoisted calling sequence +NET_ann_hoisted_call, // Start of complex argument evaluation +NET_ann_lab, // +NET_ann_live, // Mark a stack location as live +NET_ann_phi, // SSA definition node +NET_ann_ref, // SSA reference node +NET_ann_ref_s, // SSA reference node, short form +NET_arglist, // Return argument list handle for the current method +NET_beq, // Branch to target if equal +NET_beq_s, // Branch to target if equal, short form +NET_bge, // Branch to target if greater than or equal to +NET_bge_s, // Branch to target if greater than or equal to, short form +NET_bge_un, // Branch to target if greater than or equal to (unsigned or unordered) +NET_bge_un_s, // Branch to target if greater than or equal to (unsigned or unordered), short form +NET_bgt, // Branch to target if greater than +NET_bgt_s, // Branch to target if greater than, short form +NET_bgt_un, // Branch to target if greater than (unsigned or unordered) +NET_bgt_un_s, // Branch to target if greater than (unsigned or unordered), short form +NET_ble, // Branch to target if less than or equal to +NET_ble_s, // Branch to target if less than or equal to, short form +NET_ble_un, // Branch to target if less than or equal to (unsigned or unordered) +NET_ble_un_s, // Branch to target if less than or equal to (unsigned or unordered), short form +NET_blt, // Branch to target if less than +NET_blt_s, // Branch to target if less than, short form +NET_blt_un, // Branch to target if less than (unsigned or unordered) +NET_blt_un_s, // Branch to target if less than (unsigned or unordered), short form +NET_bne_un, // Branch to target if unequal or unordered +NET_bne_un_s, // Branch to target if unequal or unordered, short form +NET_box, // Convert value type to object reference +NET_br, // Branch to target +NET_br_s, // Branch to target, short form +NET_break, // Inform a debugger that a breakpoint has been reached +NET_brfalse, // Branch to target if value is zero (false) +NET_brfalse_s, // Branch to target if value is zero (false), short form +NET_brtrue, // Branch to target if value is non-zero (true) +NET_brtrue_s, // Branch to target if value is non-zero (true), short form +NET_call, // Call a method +NET_calli, // Call an indirect method +NET_callvirt, // Call a method associated with obj +NET_castclass, // Cast object to class +NET_ceq, // Push 1 (of type I4) if value1 equals value2, else 0 +NET_cgt, // Push 1 (of type I4) if value1 > value2, else 0 +NET_cgt_un, // Push 1 (of type I4) if value1 > value2, unsigned or unordered, else 0 +NET_ckfinite, // Throw ArithmeticException if value is not a finite number +NET_clt, // Push 1 (of type I4) if value1 < value2, else 0 +NET_clt_un, // Push 1 (of type I4) if value1 < value2, unsigned or unordered, else 0 +NET_conv_i, // Convert to I, pushing I on stack +NET_conv_i1, // Convert to I1, pushing I4 on stack +NET_conv_i2, // Convert to I2, pushing I4 on stack +NET_conv_i4, // Convert to I4, pushing I4 on stack +NET_conv_i8, // Convert to I8, pushing I8 on stack +NET_conv_ovf_i, // Convert to an I (on the stack as I) and throw an exception on overflow +NET_conv_ovf_i1, // Convert to an I1 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_i1_un, // Convert unsigned to an I1 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_i2, // Convert to an I2 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_i2_un, // Convert unsigned to an I2 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_i4, // Convert to an I4 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_i4_un, // Convert unsigned to an I4 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_i8, // Convert to an I8 (on the stack as I8) and throw an exception on overflow +NET_conv_ovf_i8_un, // Convert unsigned to an I8 (on the stack as I8) and throw an exception on overflow +NET_conv_ovf_i_un, // Convert to unsigned an I (on the stack as I) and throw an exception on overflow +NET_conv_ovf_u, // Convert to a U (on the stack as I) and throw an exception on overflow +NET_conv_ovf_u1, // Convert to a U1 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_u1_un, // Convert to unsigned a U1 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_u2, // Convert to a U2 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_u2_un, // Convert to unsigned a U2 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_u4, // Convert to a U4 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_u4_un, // Convert to unsigned a U3 (on the stack as I4) and throw an exception on overflow +NET_conv_ovf_u8, // Convert to a U8 (on the stack as I8) and throw an exception on overflow +NET_conv_ovf_u8_un, // Convert to unsigned a U8 (on the stack as I8) and throw an exception on overflow +NET_conv_ovf_u_un, // Convert to unsigned a U (on the stack as I) and throw an exception on overflow +NET_conv_r4, // Convert to R4, pushing F on stack +NET_conv_r8, // Convert to R8, pushing F on stack +NET_conv_r_un, // Convert unsigned integer to floating point, pushing F on stack +NET_conv_u, // Convert to U, pushing I on stack +NET_conv_u1, // Convert to U1, pushing I4 on stack +NET_conv_u2, // Convert to U2, pushing I4 on stack +NET_conv_u4, // Convert to U4, pushing I4 on stack +NET_conv_u8, // Convert to U8, pushing I8 on stack +NET_cpblk, // Copy data from memory to memory +NET_cpobj, // Copy a value type +NET_div, // Divide two values to return a quotient or floating point result +NET_div_un, // Divide two values, unsigned, returning a quotient +NET_dup, // Duplicate value on the top of the stack +NET_endfilter, // End filter clause of SEH exception handling +NET_endfinally, // End fault clause of an exception block +NET_initblk, // Set a block of memory to a given byte +NET_initobj, // Initialize a value type +NET_isinst, // Test if an object is an instance of a class or interface, returning NULL or an instance of that class or interface +NET_jmp, // Exit current method and jump to specified method +NET_ldarg, // Load argument numbered num onto stack +NET_ldarg_0, // Load argument 0 onto stack +NET_ldarg_1, // Load argument 1 onto stack +NET_ldarg_2, // Load argument 2 onto stack +NET_ldarg_3, // Load argument 3 onto stack +NET_ldarg_s, // Load argument numbered num onto stack, short form +NET_ldarga, // Fetch the address of argument +NET_ldarga_s, // Fetch the address of argument, short form +NET_ldc_i4, // Push num of type I4 onto the stack as I4 +NET_ldc_i4_0, // Push 0 onto the stack as I4 +NET_ldc_i4_1, // Push 1 onto the stack as I4 +NET_ldc_i4_2, // Push 2 onto the stack as I4 +NET_ldc_i4_3, // Push 3 onto the stack as I4 +NET_ldc_i4_4, // Push 4 onto the stack as I4 +NET_ldc_i4_5, // Push 5 onto the stack as I4 +NET_ldc_i4_6, // Push 6 onto the stack as I4 +NET_ldc_i4_7, // Push 7 onto the stack as I4 +NET_ldc_i4_8, // Push 8 onto the stack as I4 +NET_ldc_i4_m1, // Push -1 onto the stack as I4 +NET_ldc_i4_s, // Push num onto the stack as I4, short form +NET_ldc_i8, // Push num of type I8 onto the stack as I8 +NET_ldc_r4, // Push num of type R4 onto the stack as F +NET_ldc_r8, // Push num of type R8 onto the stack as F +NET_ldelem_i, // Load the element at index with type I onto the top of the stack as an I +NET_ldelem_i1, // Load the element at index with type I1 onto the top of the stack as an I4 +NET_ldelem_i2, // Load the element at index with type I2 onto the top of the stack as an I4 +NET_ldelem_i4, // Load the element at index with type I4 onto the top of the stack as an I4 +NET_ldelem_i8, // Load the element at index with type I8 onto the top of the stack as an I8 +NET_ldelem_r4, // Load the element at index with type R4 onto the top of the stack as an F +NET_ldelem_r8, // Load the element at index with type R8 onto the top of the stack as an F +NET_ldelem_ref, // Load the element at index, an object, onto the top of the stack as an O +NET_ldelem_u1, // Load the element at index with type U1 onto the top of the stack as an I4 +NET_ldelem_u2, // Load the element at index with type U2 onto the top of the stack as an I4 +NET_ldelem_u4, // Load the element at index with type U4 onto the top of the stack as an I4 +NET_ldelema, // Load the address of element at index onto the top of the stack +NET_ldfld, // Push the value of field of object on the stack +NET_ldflda, // Push the address of field of object on the stack +NET_ldftn, // Push a pointer to a method referenced by method on the stack +NET_ldind_i, // Indirect load value of type I as I stack +NET_ldind_i1, // Indirect load value of type I1 as I4 on stack +NET_ldind_i2, // Indirect load value of type I2 as I4 on stack +NET_ldind_i4, // Indirect load value of type I4 as I4 on stack +NET_ldind_i8, // Indirect load value of type I8 as I8 on stack +NET_ldind_r4, // Indirect load value of type R4 as F stack +NET_ldind_r8, // Indirect load value of type R8 as F stack +NET_ldind_ref, // Indirect load value of type object ref as O on stack +NET_ldind_u1, // Indirect load value of type U1 as I4 stack +NET_ldind_u2, // Indirect load value of type U2 as I4 stack +NET_ldind_u4, // Indirect load value of type U4 as I4 stack +NET_ldlen, // Push the length (of type U) of array on the stack +NET_ldloc, // Load local variable of index indx onto stack +NET_ldloc_0, // Load local variable 0 onto stack +NET_ldloc_1, // Load local variable 1 onto stack +NET_ldloc_2, // Load local variable 2 onto stack +NET_ldloc_3, // Load local variable 3 onto stack +NET_ldloc_s, // Load local variable of index indx onto stack, short form +NET_ldloca, // Load address of local variable +NET_ldloca_s, // Load address of local variable, short form +NET_ldnull, // Push null GC reference on the stack +NET_ldobj, // Copy instance of value type to the stack. +NET_ldsfld, // Push the value of field on the stack +NET_ldsflda, // Push the address of the static field on the stack +NET_ldstr, // Push a string object for the literal string +NET_ldtoken, // Convert metadata token to its runtime representation +NET_ldvirtftn, // Push address of virtual method on the stack +NET_leave, // Exit a protected region of code +NET_leave_s, // Exit a protected region of code, short form +NET_localloc, // Allocate space from the local memory pool +NET_mkrefany, // Push a typed reference to pointer of type class onto the stack +NET_mul, // Multiply values +NET_mul_ovf, // Multiply signed integer values. Signed result must fit in same size +NET_mul_ovf_un, // Multiply unsigned integer values. Unsigned result must fit in same size +NET_neg, // Negate value +NET_newarr, // Create a zero-based, one-dimensional array +NET_newobj, // Create a new object +NET_nop, // Do nothing +NET_not, // Bitwise complement +NET_or, // Bitwise OR of two integer values, returns an integer +NET_pop, // Pop a value from the stack +NET_refanytype, // Push the type token stored in a typed reference +NET_refanyval, // Push the address stored in a typed reference +NET_rem, // Remainder of dividing value1 by value2 +NET_rem_un, // Remainder of unsigned dividing value1 by value2 +NET_ret, // Return from method, possibly returning a value +NET_rethrow, // Rethrow the current exception +NET_shl, // Shift an integer to the left (shifting in zeros) +NET_shr, // Shift an integer right, (shift in sign), return an integer +NET_shr_un, // Shift an integer right, (shift in zero), return an integer +NET_sizeof, // Push the size, in bytes, of a value type as a U4 +NET_starg, // Store a value to argument +NET_starg_s, // Store a value to argument, short form +NET_stelem_i, // Replace array element at index with the I value on the stack +NET_stelem_i1, // Replace array element at index with the I1 value on the stack +NET_stelem_i2, // Replace array element at index with the I2 value on the stack +NET_stelem_i4, // Replace array element at index with the I4 value on the stack +NET_stelem_i8, // Replace array element at index with the I8 value on the stack +NET_stelem_r4, // Replace array element at index with the R4 value on the stack +NET_stelem_r8, // Replace array element at index with the R8 value on the stack +NET_stelem_ref, // Replace array element at index with the ref value on the stack +NET_stfld, // Store into a field of an object +NET_stind_i, // Store value of type I into memory at address +NET_stind_i1, // Store value of type I1 into memory at address +NET_stind_i2, // Store value of type I2 into memory at address +NET_stind_i4, // Store value of type I4 into memory at address +NET_stind_i8, // Store value of type I8 into memory at address +NET_stind_r4, // Store value of type R4 into memory at address +NET_stind_r8, // Store value of type R8 into memory at address +NET_stind_ref, // Store value of type object ref (type O) into memory at address +NET_stloc, // Pop value from stack into local variable +NET_stloc_0, // Pop value from stack into local variable 0 +NET_stloc_1, // Pop value from stack into local variable 1 +NET_stloc_2, // Pop value from stack into local variable 2 +NET_stloc_3, // Pop value from stack into local variable 3 +NET_stloc_s, // Pop value from stack into local variable, short form +NET_stobj, // Store a value type from the stack into memory +NET_stsfld, // Store a static field of a class +NET_sub, // Subtract value2 from value1, returning a new value +NET_sub_ovf, // Subtract I from an I. Signed result must fit in same size +NET_sub_ovf_un, // Subtract U from a U. Unsigned result must fit in same size +NET_switch, // Jump to one of N values +NET_tail_, // (prefix) subsequent call terminates current method +NET_throw, // Throw an exception +NET_unaligned_, // (prefix) subsequent pointer instruction may be unaligned +NET_unbox, // Convert boxed value type to its raw form +NET_volatile_, // (prefix) subsequent pointer reference is volatile +NET_xor, // Bitwise XOR of integer values, returns an integer +NET_ldelem, // Load the element at index onto the top of the stack +NET_stelem, // Replace array element at index with the ref value on the stack + +// 2.0 instructions +NET_unbox_any, // Extract a value-type from obj, its boxed representation +NET_constrained_, // (prefix) invoke a member on a value of a variable type +NET_no_, // (prefix) possibly skip a fault check +NET_readonly_, // (prefix) following instruction returns a controlled-mutability managed pointer + +NET_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * HCS12X opcodes added by alexbratovic@bratspeed.com 12/12/2007 + * XGATE opcodes added by alexbratovic@bratspeed.com 12/09/2009 + */ + + + + +enum +{ +MC12_null = 0, // Unknown Operation + +MC12_aba, // Add B to A +MC12_abx, // Add B to X +MC12_aby, // Add B to Y +MC12_adca, // Add with carry to A +MC12_adcb, // Add with carry to B +MC12_adda, // Add memory to A +MC12_addb, // Add memory to B +MC12_addd, // Add to D +MC12_anda, // AND A with memory +MC12_andb, // AND B with memory +MC12_andcc, // Logical AND CCR with memory +MC12_asl, // Arithmetic shift left memory +MC12_asla, // Arithmetic shift left A +MC12_aslb, // Arithmetic shift left B +MC12_asld, // Arithmetic shift left D +MC12_asr, // Arithmetic shift right memory +MC12_asra, // Arithmetic shift right A +MC12_asrb, // Arithmetic shift right B +MC12_bcc, // Branch if carry clear +MC12_bclr, // Clear bits in memory +MC12_bcs, // Branch if carry set +MC12_beq, // Branch if equal +MC12_bge, // Branch if greater than or equal +MC12_bgnd, // Enter background debug mode +MC12_bgt, // Branch if greater than +MC12_bhi, // Branch if higher +MC12_bhs, // Branch if higher or same +MC12_bita, // Bit test A +MC12_bitb, // Bit test B +MC12_ble, // Branch if less than or equal +MC12_blo, // Branch if lower +MC12_bls, // Branch if lower or same +MC12_blt, // Branch if less than +MC12_bmi, // Branch if minus +MC12_bne, // Branch if not equal +MC12_bpl, // Branch if plus +MC12_bra, // Branch always +MC12_brclr, // Branch if selected bits clear +MC12_brn, // Branch never +MC12_brset, // Branch if selected bits set +MC12_bset, // Set bits in memory +MC12_bsr, // Branch to subroutine +MC12_bvc, // Branch if overflow clear +MC12_bvs, // Branch if overflow set +MC12_call, // Call subroutine in expanded memory +MC12_cba, // Compare A to B +MC12_clc, // Clear C bit +MC12_cli, // Clear I bit +MC12_clr, // Clear memory +MC12_clra, // Clear A +MC12_clrb, // Clear B +MC12_clv, // Clear V bit +MC12_cmpa, // Compare A to memory +MC12_cmpb, // Compare B to memory +MC12_com, // One's complement memory +MC12_coma, // One's complement A +MC12_comb, // One's complement B +MC12_cpd, // Compare D to memory (16-bit) +MC12_cps, // Compare SP to memory (16-bit) +MC12_cpx, // Compare X to memory (16-bit) +MC12_cpy, // Compare Y to memory (16-bit) +MC12_daa, // Decimal adjust A +MC12_dbeq, // Decrement counter and branch if = 0 +MC12_dbne, // Decrement counter and branch if != 0 +MC12_dec, // Decrement memory +MC12_deca, // Decrement A +MC12_decb, // Decrement B +MC12_des, // Decrement SP +MC12_dex, // Decrement X +MC12_dey, // Decrement Y +MC12_ediv, // 32 by 16 divide (unsigned) Quotient->Y Remainder->D +MC12_edivs, // 32 by 16 divide (signed) Quotient->Y Remainder->D +MC12_emacs, // Multiply and accumulate (signed) +MC12_emaxd, // MAX of two unsigned 16-bit values result to accumulator +MC12_emaxm, // MAX of two unsigned 16-bit values result to memory +MC12_emind, // MIN of two unsigned 16-bit values result to accumulator +MC12_eminm, // MIN of two unsigned 16-bit values result to memory +MC12_emul, // 16 by 16 multiply (unsigned) +MC12_emuls, // 16 by 16 multiply (signed) +MC12_eora, // Exclusive OR A with memory +MC12_eorb, // Exclusive OR B with memory +MC12_etbl, // 16-bit table lookup and interpolate +MC12_exg, // Exchange register to register +MC12_fdiv, // 16 by 16 fractional divide Remainder->D +MC12_ibeq, // Increment counter and branch if = 0 +MC12_ibne, // Increment counter and branch if != 0 +MC12_idiv, // 16 by 16 integer divide (unsigned) Remainder->D +MC12_idivs, // 16 by 16 integer divide (signed) Remainder->D +MC12_inc, // Increment memory +MC12_inca, // Increment A +MC12_incb, // Increment B +MC12_ins, // Increment SP +MC12_inx, // Increment X +MC12_iny, // Increment Y +MC12_jmp, // Jump Address +MC12_jsr, // Jump to subroutine +MC12_lbcc, // Long branch if carry clear +MC12_lbcs, // Long branch if carry set +MC12_lbeq, // Long branch if equal +MC12_lbge, // Long branch if greater than or equal +MC12_lbgt, // Long branch if greater than +MC12_lbhi, // Long branch if higher +MC12_lbhs, // Long branch if higher or same +MC12_lble, // Long branch if less than or equal +MC12_lblo, // Long branch if lower +MC12_lbls, // Long branch if lower or same +MC12_lblt, // Long branch if less than +MC12_lbmi, // Long branch if minus +MC12_lbne, // Long branch if not equal +MC12_lbpl, // Long branch if plus +MC12_lbra, // Long branch always +MC12_lbrn, // Long branch never +MC12_lbvc, // Long branch if overflow clear +MC12_lbvs, // Long branch if overflow set +MC12_ldaa, // Load A +MC12_ldab, // Load B +MC12_ldd, // Load D +MC12_lds, // Load SP +MC12_ldx, // Load X +MC12_ldy, // Load Y +MC12_leas, // Load effective address into SP +MC12_leax, // Load effective address into X +MC12_leay, // Load effective address into Y +MC12_lsl, // Logic shift left memory +MC12_lsla, // Logic shift left A +MC12_lslb, // Logic shift left B +MC12_lsld, // Logic shift left D +MC12_lsr, // Logic shift right memory +MC12_lsra, // Logic shift right A +MC12_lsrb, // Logic shift right B +MC12_lsrd, // Logic shift right D +MC12_maxa, // MAX of two unsigned 8-bit values result to accumulator +MC12_maxm, // MAX of two unsigned 8-bit values result to memory +MC12_mem, // Membership function +MC12_mina, // MIN of two unsigned 8-bit values result to accumulator +MC12_minm, // MIN of two unsigned 8-bit values result to memory +MC12_movb, // Move byte (8-bit) +MC12_movw, // Move word (16-bit) +MC12_mul, // 8 by 8 multiply (unsigned) +MC12_neg, // Two's complement memory +MC12_nega, // Two's complement A +MC12_negb, // Two's complement B +MC12_nop, // Null operation +MC12_oraa, // OR A with memory +MC12_orab, // OR B with memory +MC12_orcc, // Logical OR CCR with memory +MC12_psha, // Push A +MC12_pshb, // Push B +MC12_pshc, // Push CCR +MC12_pshd, // Push D +MC12_pshx, // Push X +MC12_pshy, // Push Y +MC12_pula, // Pull A +MC12_pulb, // Pull B +MC12_pulc, // Pull CCR +MC12_puld, // Pull D +MC12_pulx, // Pull X +MC12_puly, // Pull Y +MC12_rev, // MIN-MAX rule evaluation +MC12_revw, // MIN-MAX rule evaluation +MC12_rol, // Rotate left memory through carry +MC12_rola, // Rotate left A through carry +MC12_rolb, // Rotate left B through carry +MC12_ror, // Rotate right memory through carry +MC12_rora, // Rotate right A through carry +MC12_rorb, // Rotate right B through carry +MC12_rtc, // Return from call +MC12_rti, // Return from interrupt +MC12_rts, // Return from subroutine +MC12_sba, // Subtract B from A +MC12_sbca, // Subtract with borrow from A +MC12_sbcb, // Subtract with borrow from B +MC12_sec, // Set C bit +MC12_sei, // Set I bit +MC12_sev, // Set V bit +MC12_sex, // Sign extend 8-Bit operand +MC12_staa, // Store A +MC12_stab, // Store B +MC12_std, // Store D +MC12_stop, // Stop +MC12_sts, // Store SP +MC12_stx, // Store X +MC12_sty, // Store Y +MC12_suba, // Subtract memory from A +MC12_subb, // Subtract memory from B +MC12_subd, // Subtract memory from D +MC12_swi, // Software interrupt +MC12_tab, // Transfer A to B +MC12_tap, // Transfer A to CCR +MC12_tba, // Transfer B to A +MC12_tbeq, // Test counter and branch if = 0 +MC12_tbl, // 8-bit table lookup and interpolate +MC12_tbne, // Test counter and branch if != 0 +MC12_tfr, // Transfer register to register +MC12_tpa, // Transfer CCR to A +MC12_trap, // Unimplemented opcode interrupt +MC12_tst, // Test memory for zero or minus +MC12_tsta, // Test A for zero or minus +MC12_tstb, // Test B for zero or minus +MC12_tsx, // Transfer SP to X +MC12_tsy, // Transfer SP to Y +MC12_txs, // Transfer X to SP +MC12_tys, // Transfer Y to SP +MC12_wai, // Wait for interrupt +MC12_wav, // Calculates numerator and denominator for weighted average calculation +MC12_wavr, // Resumes execution of interrupted WAV instruction +MC12_xgdx, // Exchange D with X +MC12_xgdy, // Exchange D with Y + +// Pseudoinstructions +MC12_skip1, // Skip one byte +MC12_skip2, // Skip two bytes + +// hcs12x only instructions, 16-bit unless indicated +MC12X_addx, // Add without Carry to X +MC12X_addy, // Add without Carry to Y +MC12X_aded, // Add with Carry to D(A:B) +MC12X_adex, // Add with Carry to X +MC12X_adey, // Add with Carry to Y +MC12X_andx, // Logical AND X with Memory +MC12X_andy, // Logical AND Y with Memory +MC12X_aslw, // Arithmetic Shift Left +MC12X_aslx, // Arithmetic Shift Left X +MC12X_asly, // Arithmetic Shift Left Y +MC12X_asrw, // Arithmetic Shift Right +MC12X_asrx, // Arithmetic Shift Right X +MC12X_asry, // Arithmetic Shift Right Y +MC12X_bitx, // Logical AND X with Memory, does not change X or Memory +MC12X_bity, // Logical AND Y with Memory, does not change Y or Memory +MC12X_btas, // Bit(s) test and Set in Memory, Set CCR flags +MC12X_clrw, // Clear Memory Location +MC12X_clrx, // Clear X +MC12X_clry, // Clear Y +MC12X_comw, // One's Complement Memory +MC12X_comx, // One's Complement X +MC12X_comy, // One's Complement Y +MC12X_cped, // Compare D to Memory with Borrow +MC12X_cpes, // Compare SP to Memory with Borrow +MC12X_cpex, // Compare X to Memory with Borrow +MC12X_cpey, // Compare Y to Memory with Borrow +MC12X_decw, // Decrement Memory +MC12X_decx, // Decrement X +MC12X_decy, // Decrement Y +MC12X_eorx, // Exclusive OR X with Memory +MC12X_eory, // Exclusive OR Y with Memory +MC12X_gldaa, // Load A from Global Memory (8-bit) +MC12X_gldab, // Load B from Global Memory (8-bit) +MC12X_gldd, // Load D(A:B) from Global Memory +MC12X_glds, // Load SP from Global Memory +MC12X_gldx, // Load X from Global Memory +MC12X_gldy, // Load Y from Global Memory +MC12X_gstaa, // Store A to Global Memory (8-bit) +MC12X_gstab, // Store B to Global Memory (8-bit) +MC12X_gstd, // Store D(A:B) to Global Memory +MC12X_gsts, // Store SP to Global Memory +MC12X_gstx, // Store X to Global Memory +MC12X_gsty, // Store Y to Global Memory +MC12X_incw, // Increment Memory +MC12X_incx, // Increment X +MC12X_incy, // Increment Y +MC12X_lsrw, // Logical Shift Memory to Right +MC12X_lsrx, // Logical Shift X to Right +MC12X_lsry, // Logical Shift Y to Right +MC12X_negw, // Two's Complement Memory +MC12X_negx, // Two's Complement X +MC12X_negy, // Two's Complement Y +MC12X_orx, // Logical OR X with memory +MC12X_ory, // Logical OR Y with memory +MC12X_pshcw, // Push CCR onto Stack (16-bit) +MC12X_pulcw, // Pull CCR from Stack (16-bit) +MC12X_rolw, // Rotate Memory Left through Carry +MC12X_rolx, // Rotate X Left through Carry +MC12X_roly, // Rotate Y Left through Carry +MC12X_rorw, // Rotate Memory Right through Carry +MC12X_rorx, // Rotate X Right through Carry +MC12X_rory, // Rotate Y Right through Carry +MC12X_sbed, // Subtract with Borrow from D +MC12X_sbex, // Subtract with Borrow from X +MC12X_sbey, // Subtract with Borrow from Y +MC12X_subx, // Subtract Memory from X +MC12X_suby, // Subtract Memory from Y +MC12X_tstw, // Test Memory for Zero or Minus +MC12X_tstx, // Test X for Zero or Minus +MC12X_tsty, // Test Y for Zero or Minus + +// hcs12x V2 cpu only instructions +MC12X_sys, // System call interrupt + +// hcs12x XGATE co-processor instructions +MC12XGATE_adc, // Add with Carry +MC12XGATE_add, // Add without Carry +MC12XGATE_addh, // Add Immediate 8 bit Constant (High Byte) +MC12XGATE_addl, // Add Immediate 8 bit Constant (Low Byte) +MC12XGATE_and, // Logical AND +MC12XGATE_andh, // Logical AND Immediate 8 bit Constant (High Byte) +MC12XGATE_andl, // Logical AND Immediate 8 bit Constant (Low Byte) +MC12XGATE_asr, // Arithmetic Shift Right +MC12XGATE_bcc, // Branch if Carry Cleared (Same as BHS) +MC12XGATE_bcs, // Branch if Carry Set (Same as BLO) +MC12XGATE_beq, // Branch if Equal +MC12XGATE_bfext, // Bit Field Extract +MC12XGATE_bffo, // Bit Field Find First One +MC12XGATE_bfins, // Bit Field Insert +MC12XGATE_bfinsi, // Bit Field Insert and Invert +MC12XGATE_bfinsx, // Bit Field Insert and XNOR +MC12XGATE_bge, // Branch if Greater than or Equal to Zero +MC12XGATE_bgt, // Branch if Greater than Zero +MC12XGATE_bhi, // Branch if Higher +MC12XGATE_bhs, // Branch if Higher or Same (Same as BCC) +MC12XGATE_bith, // Bit Test Immediate 8 bit Constant (High Byte) +MC12XGATE_bitl, // Bit Test Immediate 8 bit Constant (Low Byte) +MC12XGATE_ble, // Branch if Less or Equal to Zero +MC12XGATE_blo, // Branch if Carry Set (Same as BCS) +MC12XGATE_bls, // Branch if Lower or Same +MC12XGATE_blt, // Branch if Lower than Zero +MC12XGATE_bmi, // Branch if Minus +MC12XGATE_bne, // Branch if Not Equal +MC12XGATE_bpl, // Branch if Plus +MC12XGATE_bra, // Branch Always +MC12XGATE_brk, // Break +MC12XGATE_bvc, // Branch if Overflow Cleared +MC12XGATE_bvs, // Branch if Overflow Set +MC12XGATE_cmp, // Compare +MC12XGATE_cmpl, // Compare Immediate 8 bit Constant (Low Byte) +MC12XGATE_com, // One's Complement +MC12XGATE_cpc, // Compare with Carry +MC12XGATE_cpch, // Compare Immediate 8 bit Constant with Carry(High Byte) +MC12XGATE_csem, // Clear Semaphore +MC12XGATE_csl, // Logical Shift Left with Carry +MC12XGATE_csr, // Logical Shift Right with Carry +MC12XGATE_jal, // Jump and Link +MC12XGATE_ldb, // Load Byte from Memory (Low Byte) +MC12XGATE_ldh, // Load Immediate 8 bit Constant (High Byte) +MC12XGATE_ldl, // Load Immediate 8 bit Constant (Low Byte) +MC12XGATE_ldw, // Load Word from Memory +MC12XGATE_lsl, // Logical Shift Left +MC12XGATE_lsr, // Logical Shift Right +MC12XGATE_mov, // Move Register Content +MC12XGATE_neg, // Two's Complement +MC12XGATE_nop, // No Operation +MC12XGATE_or, // Logical OR +MC12XGATE_orh, // Logical OR Immediate 8 bit Constant (High Byte) +MC12XGATE_orl, // Logical OR Immediate 8 bit Constant (Low Byte) +MC12XGATE_par, // Calculate Parity +MC12XGATE_rol, // Rotate Left +MC12XGATE_ror, // Rotate Right +MC12XGATE_rts, // Return to Scheduler +MC12XGATE_sbc, // Subtract with Carry +MC12XGATE_sex, // Sign Extend Byte to Word +MC12XGATE_sif, // Set Interrupt Flag +MC12XGATE_ssem, // Set Semaphore +MC12XGATE_stb, // Store Byte to Memory (Low Byte) +MC12XGATE_stw, // Store Word to Memory +MC12XGATE_sub, // Subtract without Carry +MC12XGATE_subh, // Subtract Immediate 8 bit Constant (High Byte) +MC12XGATE_subl, // Subtract Immediate 8 bit Constant (Low Byte) +MC12XGATE_tfr, // Transfer from and to Special Registers +MC12XGATE_tst, // Test Register +MC12XGATE_xnor, // Logical Exclusive NOR +MC12XGATE_xnorh, // Logical Exclusive NOR Immediate 8 bit Constant (High Byte) +MC12XGATE_xnorl, // Logical Exclusive NOR Immediate 8 bit Constant (Low Byte) + +// Pseudo instructions that combine two IMM8 into IMM16 +MC12XGATE_add16, // Add Immediate 16 bit Constant +MC12XGATE_and16, // Logical AND Immediate 16 bit Constant +MC12XGATE_cmp16, // Compare Immediate 16 bit Constant +MC12XGATE_ldw16, // Load Immediate 16 bit Constant +MC12XGATE_or16, // Logical OR Immediate 16 bit Constant +MC12XGATE_sub16, // Subtract Immediate 16 bit Constant +MC12XGATE_xnor16, // Logical Exclusive NOR Immediate 16 bit Constant + +MC12_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + + MC6816_null = 0, // Unknown Operation + + // DATA MOVEMENT INSTRUCTIONS + // -------------------------- + + // LOAD INSTRUCTIONS + MC6816_ldaa, // Load A + MC6816_ldab, // Load B + MC6816_ldd, // Load D + MC6816_lde, // Load E + MC6816_lded, // Load Concatenated D and E + + // MOVE INSTRUCTIONS + MC6816_movb, // Move Byte + MC6816_movw, // Move Word + + // STORE INSTRUCTIONS + MC6816_staa, // Store A + MC6816_stab, // Store B + MC6816_std, // Store D + MC6816_ste, // Store E + MC6816_sted, // Store Concatenated D and E + + // TRANSFER INSTRUCTIONS + MC6816_tab, // Transfer A to B + MC6816_tba, // Transfer B to A + MC6816_tde, // Transfer D to E + MC6816_ted, // Transfer E to D + + // EXCHANGE INSTRUCTIONS + MC6816_xgab, // Exchange A with B + MC6816_xgde, // Exchange D with E + + // MATHEMATIC INSTRUCTIONS + // ----------------------- + + // ADDITION AND SUBSTRACTION INSTRUCTIONS + MC6816_aba, // Add B to A + MC6816_adca, // Add with Carry to A + MC6816_adcb, // Add with Carry to B + MC6816_adcd, // Add with Carry to D + MC6816_adce, // Add with Carry to E + MC6816_adda, // Add to A + MC6816_addb, // Add to B + MC6816_addd, // Add to D + MC6816_adde, // Add to E + MC6816_ade, // Add D to E + MC6816_sba, // Subtract B from A + MC6816_sbca, // Subtract with Carry from A + MC6816_sbcb, // Subtract with Carry from B + MC6816_sbcd, // Subtract with Carry from D + MC6816_sbce, // Subtract with Carry from E + MC6816_sde, // Subtract D from E + MC6816_suba, // Subtract from A + MC6816_subb, // Subtract from B + MC6816_subd, // Subtract from D + MC6816_sube, // Subtract from E + + // BINARY CODED DECIMAL INSTRUCTIONS + MC6816_daa, // Decimal Adjust A + MC6816_sxt, // Sign Extend B into A + + // COMPARE AND TEST INSTRUCTIONS + MC6816_cba, // Compare A to B + MC6816_cmpa, // Compare A to Memory + MC6816_cmpb, // Compare B to Memory + MC6816_cpd, // Compare D to Memory + MC6816_cpe, // Compare E to Memory + MC6816_tst, // Test for Zero or Minus + MC6816_tsta, // Test A for Zero or Minus + MC6816_tstb, // Test B for Zero or Minus + MC6816_tstd, // Test D for Zero or Minus + MC6816_tste, // Test E for Zero or Minus + MC6816_tstw, // Test for Zero or Minus Word + + // MULTIPLICATION AND DIVISION INSTRUCTIONS + MC6816_ediv, // Extended Unsigned Divide + MC6816_edivs, // Extended Signed Divide + MC6816_emul, // Extended Unsigned Multiply + MC6816_emuls, // Extended Signed Multiply + MC6816_fdiv, // Unsigned Fractional Divide + MC6816_fmuls, // Signed Fractional Multiply + MC6816_idiv, // Integer Divide + MC6816_mul, // Multiply + + // DECREMENT AND INCREMENT INSTRUCTIONS + MC6816_dec, // Decrement Memory + MC6816_deca, // Decrement A + MC6816_decb, // Decrement B + MC6816_decw, // Decrement Memory Word + MC6816_inc, // Increment Memory + MC6816_inca, // Increment A + MC6816_incb, // Increment B + MC6816_incw, // Increment Memory Word + + // CLEAR, COMPLEMENT, AND NEGATE INSTRUCTIONS + MC6816_clr, // Clear Memory + MC6816_clra, // Clear A + MC6816_clrb, // Clear B + MC6816_clrd, // Clear D + MC6816_clre, // Clear E + MC6816_clrw, // Clear Memory Word + MC6816_com, // One's Complement Byte + MC6816_coma, // One's Complement A + MC6816_comb, // One's Complement B + MC6816_comd, // One's Complement D + MC6816_come, // One's Complement E + MC6816_comw, // One's Complement Word + MC6816_neg, // Two's Complement Byte + MC6816_nega, // Two's Complement A + MC6816_negb, // Two's Complement B + MC6816_negd, // Two's Complement D + MC6816_nege, // Two's Complement E + MC6816_negw, // Two's Complement Word + + // BOOLEAN LOGIC INSTRUCTIONS + MC6816_anda, // AND A + MC6816_andb, // AND B + MC6816_andd, // AND D + MC6816_ande, // AND E + MC6816_eora, // Exclusive OR A + MC6816_eorb, // Exclusive OR B + MC6816_eord, // Exclusive OR D + MC6816_eore, // Exclusive OR E + MC6816_oraa, // OR A + MC6816_orab, // OR B + MC6816_ord, // OR D + MC6816_ore, // OR E + + // BIT TEST AND MANIPULATION INSTRUCTIONS + // -------------------------------------- + MC6816_bita, // Bit Test A + MC6816_bitb, // Bit Test B + MC6816_bclr, // Clear Bit(s) + MC6816_bclrw, // Clear Bit(s) Word + MC6816_bset, // Set Bit(s) + MC6816_bsetw, // Set Bit(s) Word + + // SHIFT AND ROTATE INSTRUCTIONS + // ----------------------------- + MC6816_lsr, // Logic Shift Right + MC6816_lsra, // Logic Shift Right A + MC6816_lsrb, // Logic Shift Right B + MC6816_lsrd, // Logic Shift Right D + MC6816_lsre, // Logic Shift Right E + MC6816_lsrw, // Logic Shift Right Word + MC6816_asl, // Arithmetic Shift Left + MC6816_asla, // Arithmetic Shift Left A + MC6816_aslb, // Arithmetic Shift Left B + MC6816_asld, // Arithmetic Shift Left D + MC6816_asle, // Arithmetic Shift Left E + MC6816_aslw, // Arithmetic Shift Left Word + MC6816_asr, // Arithmetic Shift Right + MC6816_asra, // Arithmetic Shift Right A + MC6816_asrb, // Arithmetic Shift Right B + MC6816_asrd, // Arithmetic Shift Right D + MC6816_asre, // Arithmetic Shift Right E + MC6816_asrw, // Arithmetic Shift Right Word + MC6816_rol, // Rotate Left + MC6816_rola, // Rotate Left A + MC6816_rolb, // Rotate Left B + MC6816_rold, // Rotate Left D + MC6816_role, // Rotate Left E + MC6816_rolw, // Rotate Left Word + MC6816_ror, // Rotate Right + MC6816_rora, // Rotate Right A + MC6816_rorb, // Rotate Right B + MC6816_rord, // Rotate Right D + MC6816_rore, // Rotate Right E + MC6816_rorw, // Rotate Right Word + + // PROGRAM CONTROL INSTRUCTIONS + // ---------------------------- + + // SHORT BRANCH INSTRUCTIONS + MC6816_bra, // Branch Always + MC6816_brn, // Branch Never + MC6816_bcc, // Branch If Carry Clear + MC6816_bcs, // Branch If Carry Set + MC6816_beq, // Branch If Equal to Zero + MC6816_bmi, // Branch If Minus + MC6816_bne, // Branch If Not Equal to Zero + MC6816_bpl, // Branch If Plus + MC6816_bvc, // Branch If Overflow Clear + MC6816_bvs, // Branch If Overflow Set + MC6816_bhi, // Branch If Higher + MC6816_bls, // Branch If Lower or Same + MC6816_bge, // Branch If Greater than or Equal to Zero + MC6816_bgt, // Branch If Greater than Zero + MC6816_ble, // Branch If Less than or Equal to Zero + MC6816_blt, // Branch If Less than Zero + + // LONG BRANCH INSTRUCTIONS + MC6816_lbra, // Long Branch Always + MC6816_lbrn, // Long Branch Never + MC6816_lbcc, // Long Branch If Carry Clear + MC6816_lbcs, // Long Branch If Carry Set + MC6816_lbeq, // Long Branch If Equal to Zero + MC6816_lbev, // Long Branch If EV Set + MC6816_lbmi, // Long Branch If Minus + MC6816_lbmv, // Long Branch If MV Set + MC6816_lbne, // Long Branch If Not Equal to Zero + MC6816_lbpl, // Long Branch If Plus + MC6816_lbvc, // Long Branch If Overflow Clear + MC6816_lbvs, // Long Branch If Overflow Set + MC6816_lbhi, // Long Branch If Higher + MC6816_lbls, // Long Branch If Lower or Same + MC6816_lbge, // Long Branch If Greater than or Equal to Zero + MC6816_lbgt, // Long Branch If Greater than Zero + MC6816_lble, // Long Branch If Less than or Equal to Zero + MC6816_lblt, // Long Branch If Less than Zero + + // BIT CONDITION BRANCH INSTRUCTIONS + MC6816_brclr, // Branch if Bits Clear + MC6816_brset, // Branch if Bits Set + + // JUMP INSTRUCTION + MC6816_jmp, // Jump + + // SUBROUTINE INSTRUCTIONS + MC6816_bsr, // Branch to Subroutine + MC6816_jsr, // Jump to Subroutine + MC6816_lbsr, // Long Branch to Subroutine + MC6816_rts, // Return From Subroutine + + // INTERRUPT INSTRUCTIONS + MC6816_rti, // Return from Interrupt + MC6816_swi, // Software Interrupt + + // INDEXING AND ADDRESS EXTENSION INSTRUCTIONS + // ------------------------------------------- + + // INDEXING INSTRUCTIONS + MC6816_abx, // Add B to IX + MC6816_aby, // Add B to IY + MC6816_abz, // Add B to IZ + MC6816_adx, // Add D to IX + MC6816_ady, // Add D to IY + MC6816_adz, // Add D to IZ + MC6816_aex, // Add E to IX + MC6816_aey, // Add E to IY + MC6816_aez, // Add E to IZ + MC6816_aix, // Add Immediate Value to IX + MC6816_aiy, // Add Immediate Value to IY + MC6816_aiz, // Add Immediate Value to IZ + MC6816_cpx, // Compare IX to Memory + MC6816_cpy, // Compare IY to Memory + MC6816_cpz, // Compare IZ to Memory + MC6816_ldx, // Load IX + MC6816_ldy, // Load IY + MC6816_ldz, // Load IZ + MC6816_stx, // Store IX + MC6816_sty, // Store IY + MC6816_stz, // Store IZ + MC6816_tsx, // Transfer SP to IX + MC6816_tsy, // Transfer SP to IY + MC6816_tsz, // Transfer SP to IZ + MC6816_txs, // Transfer IX to SP + MC6816_txy, // Transfer IX to IY + MC6816_txz, // Transfer IX to IZ + MC6816_tys, // Transfer IY to SP + MC6816_tyx, // Transfer IY to IX + MC6816_tyz, // Transfer IY to IZ + MC6816_tzs, // Transfer IZ to SP + MC6816_tzx, // Transfer IZ to IX + MC6816_tzy, // Transfer IZ to IY + MC6816_xgdx, // Exchange D with IX + MC6816_xgdy, // Exchange D with IY + MC6816_xgdz, // Exchange D with IZ + MC6816_xgex, // Exchange E with IX + MC6816_xgey, // Exchange E with IY + MC6816_xgez, // Exchange E with IZ + + // ADDRESS EXTENSION INSTRUCTIONS + MC6816_tbek, // Transfer B to EK + MC6816_tbsk, // Transfer B to SK + MC6816_tbxk, // Transfer B to XK + MC6816_tbyk, // Transfer B to YK + MC6816_tbzk, // Transfer B to ZK + MC6816_tekb, // Transfer EK to B + MC6816_tskb, // Transfer SK to B + MC6816_txkb, // Transfer XK to B + MC6816_tykb, // Transfer YK to B + MC6816_tzkb, // Transfer ZK to B + + // STACKING INSTRUCTIONS + // --------------------- + MC6816_ais, // Add Immediate Data to SP + MC6816_cps, // Compare SP to Memory + MC6816_lds, // Load SP + MC6816_sts, // Store SP + MC6816_psha, // Push A + MC6816_pshb, // Push B + MC6816_pshm, // Push Multiple Registers + MC6816_pula, // Pull A + MC6816_pulb, // Pull B + MC6816_pulm, // Pull Multiple Registers + + // CONDITION CODE INSTRUCTIONS + // --------------------------- + MC6816_andp, // AND CCR + MC6816_orp, // OR CCR + MC6816_tap, // Transfer A to CCR + MC6816_tdp, // Transfer D to CCR + MC6816_tpa, // Transfer CCR MSB to A + MC6816_tpd, // Transfer CCR to D + + // DIGITAL SIGNAL PROCESSING INSTRUCTIONS + // -------------------------------------- + MC6816_ace, // Add E to AM[31:15] + MC6816_aced, // Add concatenated E and D to AM + MC6816_aslm, // Arithmetic Shift Left AM + MC6816_asrm, // Arithmetic Shift Right AM + MC6816_clrm, // Clear AM + MC6816_ldhi, // Initialize HR and IR + MC6816_mac, // Multiply and Accumulate + MC6816_pshmac, // Push MAC State + MC6816_pulmac, // Pull MAC State + MC6816_rmac, // Repeating Multiply and Accumulate + MC6816_tdmsk, // Transfer D to XMSK:YMSK + MC6816_tedm, // Transfer E and T to AM[31:0] + MC6816_tem, // Transfer E to AM[31:16] + MC6816_tmer, // Transfer AM to E Rounded + MC6816_tmet, // Transfer AM to E Truncated + MC6816_tmxed, // Transfer AM t IX:E:D + + // STOP AND WAIT INSTRUCTIONS + // -------------------------- + MC6816_lpstop, // Low Power Stop + MC6816_wai, // Wait for Interrupt + + // BACKGROUND MODE AND NULL OPERATIONS + // ----------------------------------- + MC6816_bgnd, // Enter Background Debugging Mode + MC6816_nop, // Null operation + + MC6816_last +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +I960_null = 0, // Unknown Operation + +I960_addc, // Add ordinal with carry +I960_addi, // Add integer +I960_addo, // Add ordinal +I960_alterbit, // Alter bit +I960_and, // Src2 AND src1 +I960_andnot, // Src2 AND (NOT src1) +I960_atadd, // Atomic add +I960_atmod, // Atomic modify +I960_b, // Branch +I960_bal, // Branch and Link +I960_balx, // Branch and Link Extended +I960_bbc, // Check bit and branch if clear +I960_bbs, // Check bit and branch if set +I960_bno, // Branch if unordered/false +I960_bg, // Branch if greater +I960_be, // Branch if equal/true +I960_bge, // Branch if greater or equal +I960_bl, // Branch if less +I960_bne, // Branch if not equal +I960_ble, // Branch if less or equal +I960_bo, // Branch if ordered +I960_bx, // Branch Extended +I960_call, // Call +I960_calls, // Call system +I960_callx, // Call extended +I960_chkbit, // Check bit +I960_clrbit, // Clear bit +I960_cmpdeci, // Compare and decrement integer +I960_cmpdeco, // Compare and decrement ordinal +I960_cmpi, // Compare integer +I960_cmpibno, // Compare integer and branch if unordered +I960_cmpibg, // Compare integer and branch if greater +I960_cmpibe, // Compare integer and branch if equal +I960_cmpibge, // Compare integer and branch if greater or equal +I960_cmpibl, // Compare integer and branch if less +I960_cmpibne, // Compare integer and branch if not equal +I960_cmpible, // Compare integer and branch if less or equal +I960_cmpibo, // Compare integer and branch if ordered +I960_cmpinci, // Compare and increment integer +I960_cmpinco, // Compare and increment ordinal +I960_cmpo, // Compare ordinal +I960_cmpobg, // Compare ordinal and branch if greater +I960_cmpobe, // Compare ordinal and branch if equal +I960_cmpobge, // Compare ordinal and branch if greater or equal +I960_cmpobl, // Compare ordinal and branch if less +I960_cmpobne, // Compare ordinal and branch if not equal +I960_cmpoble, // Compare ordinal and branch if less or equal +I960_concmpi, // Conditional compare integer +I960_concmpo, // Conditional compare ordinal +I960_divi, // Divide integer +I960_divo, // Divide ordinal +I960_ediv, // Extended divide +I960_emul, // Extended multiply +I960_eshro, // Extended shift right ordinal +I960_extract, // Extract +I960_faultno, // Fault if unordered +I960_faultg, // Fault if greater +I960_faulte, // Fault if equal +I960_faultge, // Fault if greater or equal +I960_faultl, // Fault if less +I960_faultne, // Fault if not equal +I960_faultle, // Fault if less or equal +I960_faulto, // Fault if ordered +I960_flushreg, // Flush cached local register sets to memory +I960_fmark, // Force mark +I960_ld, // Load word +I960_lda, // Load address +I960_ldib, // Load integer byte +I960_ldis, // Load integer short +I960_ldl, // Load long +I960_ldob, // Load ordinal byte +I960_ldos, // Load ordinal short +I960_ldq, // Load quad +I960_ldt, // Load triple +I960_mark, // Mark +I960_modac, // Modify the AC register +I960_modi, // Modulo integer +I960_modify, // Modify +I960_modpc, // Modify the process controls register +I960_modtc, // Modify trace controls +I960_mov, // Move word +I960_movl, // Move long word +I960_movq, // Move quad word +I960_movt, // Move triple word +I960_muli, // Multiply integer +I960_mulo, // Multiply ordinal +I960_nand, // NOT (src2 AND src1) +I960_nor, // NOT (src2 OR src1) +I960_not, // NOT src1 +I960_notand, // (NOT src2) AND src1 +I960_notbit, // Not bit +I960_notor, // (NOT src2) or src1 +I960_or, // Src2 OR src1 +I960_ornot, // Src2 or (NOT src1) +I960_remi, // Remainder integer +I960_remo, // Remainder ordinal +I960_ret, // Return +I960_rotate, // Rotate left +I960_scanbit, // Scan for bit +I960_scanbyte, // Scan byte equal +I960_setbit, // Set bit +I960_shli, // Shift left integer +I960_shlo, // Shift left ordinal +I960_shrdi, // Shift right dividing integer +I960_shri, // Shift right integer +I960_shro, // Shift right ordinal +I960_spanbit, // Span over bit +I960_st, // Store word +I960_stib, // Store integer byte +I960_stis, // Store integer short +I960_stl, // Store long +I960_stob, // Store ordinal byte +I960_stos, // Store ordinal short +I960_stq, // Store quad +I960_stt, // Store triple +I960_subc, // Subtract ordinal with carry +I960_subi, // Subtract integer +I960_subo, // Subtract ordinal +I960_syncf, // Synchronize faults +I960_testno, // Test for unordered +I960_testg, // Test for greater +I960_teste, // Test for equal +I960_testge, // Test for greater or equal +I960_testl, // Test for less +I960_testne, // Test for not equal +I960_testle, // Test for less or equal +I960_testo, // Test for ordered +I960_xnor, // Src2 XNOR src1 +I960_xor, // Src2 XOR src1 + +// Cx instructions + +I960_sdma, // Set up a DMA controller channel +I960_sysctl, // Perform system control function +I960_udma, // Copy current DMA pointers to internal data RAM + +// Unknown instructions + +I960_dcinva, +I960_cmpob, +I960_cmpib, +I960_cmpos, +I960_cmpis, +I960_bswap, +I960_intdis, +I960_inten, +I960_synmov, +I960_synmovl, +I960_synmovq, +I960_cmpstr, +I960_movqstr, +I960_movstr, +I960_inspacc, +I960_ldphy, +I960_synld, +I960_fill, +I960_daddc, +I960_dsubc, +I960_dmovt, +I960_condrec, +I960_receive, +I960_intctl, +I960_icctl, +I960_dcctl, +I960_halt, +I960_send, +I960_sendserv, +I960_resumprcs, +I960_schedprcs, +I960_saveprcs, +I960_condwait, +I960_wait, +I960_signal, +I960_ldtime, +I960_addono, +I960_addino, +I960_subono, +I960_subino, +I960_selno, +I960_addog, +I960_addig, +I960_subog, +I960_subig, +I960_selg, +I960_addoe, +I960_addie, +I960_suboe, +I960_subie, +I960_sele, +I960_addoge, +I960_addige, +I960_suboge, +I960_subige, +I960_selge, +I960_addol, +I960_addil, +I960_subol, +I960_subil, +I960_sell, +I960_addone, +I960_addine, +I960_subone, +I960_subine, +I960_selne, +I960_addole, +I960_addile, +I960_subole, +I960_subile, +I960_selle, +I960_addoo, +I960_addio, +I960_suboo, +I960_subio, +I960_selo, + +// Floating point instructions + +I960_faddr, I960_fp_first = I960_faddr, +I960_faddrl, +I960_fatanr, +I960_fatanrl, +I960_fclassr, +I960_fclassrl, +I960_fcmpor, +I960_fcmporl, +I960_fcmpr, +I960_fcmprl, +I960_fcosr, +I960_fcosrl, +I960_fcpyrsre, +I960_fcpysre, +I960_fcvtilr, +I960_fcvtir, +I960_fcvtri, +I960_fcvtril, +I960_fcvtzri, +I960_fcvtzril, +I960_fdivr, +I960_fdivrl, +I960_fexpr, +I960_fexprl, +I960_flogbnr, +I960_flogbnrl, +I960_flogepr, +I960_flogeprl, +I960_flogr, +I960_flogrl, +I960_fmovr, +I960_fmovre, +I960_fmovrl, +I960_fmulr, +I960_fmulrl, +I960_fremr, +I960_fremrl, +I960_froundr, +I960_froundrl, +I960_fscaler, +I960_fscalerl, +I960_fsinr, +I960_fsinrl, +I960_fsqrtr, +I960_fsqrtrl, +I960_fsubr, +I960_fsubrl, +I960_ftanr, +I960_ftanrl, I960_fp_last = I960_ftanrl, + +I960_last, + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +F2MC_null = 0, // Unknown Operation + +// TRANSFER INSTRUCTIONS + +F2MC_mov, // Move byte data from source to destination +F2MC_movn, // Move immediate nibble data to A +F2MC_movx, // Move byte data with sign extension from source to A +F2MC_xch, // Exchange byte data of source to destination +F2MC_movw, // Move word data from source to destination +F2MC_xchw, // Exchange word data of source to destination +F2MC_movl, // Move long word data from source to destination + +// NUMERIC DATA OPERATIONS INSTRUCTIONS + +F2MC_add, // Add byte data of destination and source to destination +F2MC_addc1, // Add byte data of AL and AH with Carry to AL +F2MC_addc2, // Add byte data of A and effective address with Carry to A +F2MC_adddc, // Add decimal data of AL and AH with Carry to AL +F2MC_sub, // Subtract byte data of source from festination to destination +F2MC_subc1, // Subtract byte data of AL from AH with Carry to AL +F2MC_subc2, // Subtract byte data of effective address from A with Carry to A +F2MC_subdc, // Subtract decimal data of AL from AH with Carry to AL +F2MC_addw1, // Add word data of AH and AL to AL +F2MC_addw2, // Add word data of destination and source to destination +F2MC_addcw, // Add word data of A and effective address from A with Carry to A +F2MC_subw1, // Subtract word data of AL from AH to AL +F2MC_subw2, // Subtract word data of source from festination to destination +F2MC_subcw, // Subtract word data of A and effective address from A with carry to A +F2MC_addl, // Add long word data of destination and source to destination +F2MC_subl, // Subtract long word data of source from festination to destination +F2MC_inc, // Increment byte data +F2MC_dec, // Decrement byte data +F2MC_incw, // Increment word data +F2MC_decw, // Decrement word data +F2MC_incl, // Increment long word data +F2MC_decl, // Decrement long word data +F2MC_cmp1, // Compare byte data of AH and AL +F2MC_cmp2, // Compare byte data of destination and source +F2MC_cmpw1, // Compare word data of AH and AL +F2MC_cmpw2, // Compare word data of destination and source +F2MC_cmpl, // Compare long word data of destination and source +F2MC_divu1, // Divide unsigned AH by AL +F2MC_divu2, // Divide unsigned word data by unsigned byte data +F2MC_divuw, // Divide unsigned long word data by unsigned word data +F2MC_mulu1, // Multiply unsigned byte AH by AL +F2MC_mulu2, // Multiply unsigned byte data +F2MC_muluw1, // Multiply unsigned word AH by AL +F2MC_muluw2, // Multiply unsigned word data +F2MC_div1, // Divide AH by AL +F2MC_div2, // Divide word data by byte data +F2MC_divw, // Divide long word data by word data +F2MC_mul1, // Multiply byte AH by AL +F2MC_mul2, // Multiply byte data +F2MC_mulw1, // Multiply word AH by AL +F2MC_mulw2, // Multiply word data + +// LOGICAL DATA OPERATION INSTRUCTIONS + +F2MC_and, // And byte data of destination and source to destination +F2MC_or, // Or byte data of destination and source to destination +F2MC_xor, // Exclusive or byte data of destination and source to destination +F2MC_not, // Not byte data of destination +F2MC_andw1, // And word data of AH and AL to AL +F2MC_andw2, // And word data of destination and source to destination +F2MC_orw1, // Or word data of AH and AL to AL +F2MC_orw2, // Or word data of destination and source to destination +F2MC_xorw1, // Exclusive or word data of AH and AL to AL +F2MC_xorw2, // Exclusive or word data of destination and source to destination +F2MC_notw, // Not word data of destination +F2MC_andl, // And long word data of destination and source to destination +F2MC_orl, // Or long word data of destination and source to destination +F2MC_xorl, // Exclusive or long word data of destination and source to destination +F2MC_neg, // Negate byte data of destination +F2MC_negw, // Negate word data of destination +F2MC_nrml, // Normalize long word + +// SHIFT INSTRUCTIONS + +F2MC_rorc, // Rotate byte data of A with Carry to right +F2MC_rolc, // Rotate byte data of A with Carry to left +F2MC_asr, // Arithmetic shift byte data of A to right +F2MC_lsr, // Logical shift byte data of A to right +F2MC_lsl, // Logical shift byte data of A to left +F2MC_asrw1, // Arithmetic shift word data of A to right +F2MC_asrw2, // Arithmetic shift word data of A to right +F2MC_lsrw1, // Logical shift word data of A to right +F2MC_lsrw2, // Logical shift word data of A to right +F2MC_lslw1, // Logical shift word data of A to left +F2MC_lslw2, // Logical shift word data of A to left +F2MC_asrl, // Arithmetic shift long word data of A to right +F2MC_lsrl, // Logical shift long word data of A to right +F2MC_lsll, // Logical shift long word data of A to left + +// BRANCH INSTRUCTIONS + +F2MC_bz, // Branch if Zero +F2MC_bnz, // Branch if Not Zero +F2MC_bc, // Branch if Carry +F2MC_bnc, // Branch if Not Carry +F2MC_bn, // Branch if Negative +F2MC_bp, // Branch if Not Negative +F2MC_bv, // Branch if Overflow +F2MC_bnv, // Branch if Not Overflow +F2MC_bt, // Branch if Sticky +F2MC_bnt, // Branch if Not Sticky +F2MC_blt, // Branch if Overflow or Negative +F2MC_bge, // Branch if Not (Overflow or Negative) +F2MC_ble, // Branch if (Overflow xor Negative) or Zero +F2MC_bgt, // Branch if Not ((Overflow xor Negative) or Zero) +F2MC_bls, // Branch if Carry or Zero +F2MC_bhi, // Branch if Not (Carry or Zero) +F2MC_bra, // Branch unconditionally +F2MC_jmp, // Jump destination address +F2MC_jmpp, // Jump destination physical address +F2MC_call, // Call subroutine +F2MC_callv, // Call vectored subroutine +F2MC_callp, // Call physical address +F2MC_cbne, // Compare byte data and branch if not Equal +F2MC_cwbne, // Compare word data and branch if not Equal +F2MC_dbnz, // Decrement byte data and branch if not Zero +F2MC_dwbnz, // Decrement word data and branch if not Zero +F2MC_int, // Software interrupt +F2MC_intp, // Software interrupt +F2MC_int9, // Software interrupt +F2MC_reti, // Return from interrupt +F2MC_link, // Link and create new stack frame +F2MC_unlink, // Unlink and create new stack frame +F2MC_ret, // Return from subroutine +F2MC_retp, // Return from physical address + +// OTHER INSTRUCTIONS + +F2MC_pushw, // Push to stack memory +F2MC_popw, // Pop from stack memory +F2MC_jctx, // Jump context +// F2MC_and, +// F2MC_or, +// F2MC_mov, +F2MC_movea, // Move effective address to destination +F2MC_addsp, // Add word data of SP and immediate data to SP +// F2MC_mov, +F2MC_nop, // No operation +F2MC_adb, // ADB register +F2MC_dtb, // DTB register +F2MC_pcb, // PCB register +F2MC_spb, // SPB register +F2MC_ncc, // Flag change inhibit +F2MC_cmr, // Common register bank +F2MC_movb, // Move bit data +F2MC_setb, // Set bit +F2MC_clrb, // Clear bit +F2MC_bbc, // Branch if bit condition satisfied +F2MC_bbs, // Branch if bit condition satisfied +F2MC_sbbs, // Set bit and branch if bit set +F2MC_wbts, // Wait until bit condition satisfied +F2MC_wbtc, // Wait until bit condition satisfied +F2MC_swap, // Swap byte data of A +F2MC_swapw, // Swap word data of A +F2MC_ext, // Sign extend from byte data to word data +F2MC_extw, // Sign extend from word data to long word data +F2MC_zext, // Zero extendfrom byte data to word data +F2MC_zextw, // Zero extendfrom word data to long word data +F2MC_movsi, // Move string byte with addresses incremented +F2MC_movsd, // Move string byte with addresses decremented +F2MC_sceqi, // Scan string byte until Equal with address incremented +F2MC_sceqd, // Scan string byte until Equal with address decremented +F2MC_filsi, // Fill string byte +F2MC_movswi, // Move string word with address incremented +F2MC_movswd, // Move string word with address decremented +F2MC_scweqi, // Scan string word until Equal with address incremented +F2MC_scweqd, // Scan string word until Equal with address decremented +F2MC_filswi, // Fill string word + +// MACROS + +F2MC_bz16, // Branch if Zero +F2MC_bnz16, // Branch if Not Zero +F2MC_bc16, // Branch if Carry +F2MC_bnc16, // Branch if Not Carry +F2MC_bn16, // Branch if Negative +F2MC_bp16, // Branch if Not Negative +F2MC_bv16, // Branch if Overflow +F2MC_bnv16, // Branch if Not Overflow +F2MC_bt16, // Branch if Sticky +F2MC_bnt16, // Branch if Not Sticky +F2MC_blt16, // Branch if Overflow or Negative +F2MC_bge16, // Branch if Not (Overflow or Negative) +F2MC_ble16, // Branch if (Overflow xor Negative) or Zero +F2MC_bgt16, // Branch if Not ((Overflow xor Negative) or Zero) +F2MC_bls16, // Branch if Carry or Zero +F2MC_bhi16, // Branch if Not (Carry or Zero) + +F2MC_cbne16, // Compare byte data and branch if not Equal +F2MC_cwbne16, // Compare word data and branch if not Equal + +F2MC_dbnz16, // Decrement byte data and branch if not Zero +F2MC_dwbnz16, // Decrement word data and branch if not Zero + +F2MC_bbc16, // Branch if bit condition satisfied +F2MC_bbs16, // Branch if bit condition satisfied +F2MC_sbbs16, // Set bit and branch if bit set + +F2MC_last, + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +TMS320C3X_null = 0, // Unknown Operation + +TMS320C3X_ABSF, // Absolute value of a floating-point number +TMS320C3X_ABSI, // Absolute value of an integer +TMS320C3X_ADDC, // Add integers with carry +TMS320C3X_ADDF, // Add Floating-Point Values +TMS320C3X_ADDI, // Add Integer +TMS320C3X_AND, // Bitwise-Logical AND +TMS320C3X_ANDN, // Bitwise-Logical AND With Complement +TMS320C3X_ASH, // Arithmetic Shift +TMS320C3X_CMPF, // Compare Floating-Point Value +TMS320C3X_CMPI, // Compare Integer +TMS320C3X_FIX, // Floating-Point-to-Integer Conversion +TMS320C3X_FLOAT, // Integer-to-Floating-Point Conversion +TMS320C3X_IDLE, // Idle Until Interrupt +TMS320C3X_IDLE2, // Low-Power Idle +TMS320C3X_LDE, // Load Floating-Point Exponent +TMS320C3X_LDF, // Load Floating-Point Value +TMS320C3X_LDFI, // Load Floating-Point Value, Interlocked +TMS320C3X_LDI, // Load Integer +TMS320C3X_LDII, // Load Integer, Interlocked +TMS320C3X_LDM, // Load Floating-Point Mantissa +TMS320C3X_LSH, // Logical Shift +TMS320C3X_MPYF, // Multiply Floating-Point Value +TMS320C3X_MPYI, // Multiply Integer +TMS320C3X_NEGB, // Negative Integer With Borrow +TMS320C3X_NEGF, // Negate Floating-Point Value +TMS320C3X_NEGI, // Negate Integer +TMS320C3X_NOP, // No Operation +TMS320C3X_NORM, // Normalize +TMS320C3X_NOT, // Bitwise-Logical Complement +TMS320C3X_POP, // Pop Integer +TMS320C3X_POPF, // Pop Floating-Point Value +TMS320C3X_PUSH, // PUSH Integer +TMS320C3X_PUSHF, // PUSH Floating-Point Value +TMS320C3X_OR, // Bitwise-Logical OR +TMS320C3X_LOPOWER, // Divide Clock by 16 +TMS320C3X_MAXSPEED, // Restore Clock to Regular Speed +TMS320C3X_RND, // Round Floating-Point Value +TMS320C3X_ROL, // Rotate Left +TMS320C3X_ROLC, // Rotate Left Through Carry +TMS320C3X_ROR, // Rotate Right +TMS320C3X_RORC, // Rotate Right Through Carry +TMS320C3X_RPTS, // Repeat Single Instruction +TMS320C3X_STF, // Store Floating-Point Value +TMS320C3X_STFI, // Store Floating-Point Value, Interlocked +TMS320C3X_STI, // Store Integer +TMS320C3X_STII, // Store Integer, Interlocked +TMS320C3X_SIGI, // Signal, Interlocked +TMS320C3X_SUBB, // Subtract Integer With Borrow +TMS320C3X_SUBC, // Subtract Integer Conditionally +TMS320C3X_SUBF, // Subtract Floating-Point Value +TMS320C3X_SUBI, // Subtract Integer +TMS320C3X_SUBRB, // Subtract Reverse Integer With Borrow +TMS320C3X_SUBRF, // Subtract Reverse Floating-Point Value +TMS320C3X_SUBRI, // Subtract Reverse Integer +TMS320C3X_TSTB, // Test Bit Fields +TMS320C3X_XOR, // Bitwise-Exclusive OR +TMS320C3X_IACK, // Interrupt acknowledge + +TMS320C3X_ADDC3, // Add integers with carry (3-operand) +TMS320C3X_ADDF3, // Add floating-point values (3-operand) +TMS320C3X_ADDI3, // Add integers (3 operand) +TMS320C3X_AND3, // Bitwise-logical AND (3-operand) +TMS320C3X_ANDN3, // Bitwise-logical ANDN (3-operand) +TMS320C3X_ASH3, // Arithmetic shift (3-operand) +TMS320C3X_CMPF3, // Compare floating-point values (3-operand) +TMS320C3X_CMPI3, // Compare integers (3-operand) +TMS320C3X_LSH3, // Logical shift (3-operand) +TMS320C3X_MPYF3, // Multiply floating-point value (3-operand) +TMS320C3X_MPYI3, // Multiply integers (3-operand) +TMS320C3X_OR3, // Bitwise-logical OR (3-operand) +TMS320C3X_SUBB3, // Subtract integers with borrow (3-operand) +TMS320C3X_SUBF3, // Subtract floating-point values (3-operand) +TMS320C3X_SUBI3, // Subtract integers (3-operand) +TMS320C3X_TSTB3, // Test Bit Fields, 3-Operand +TMS320C3X_XOR3, // Bitwise-Exclusive OR, 3-Operand + +TMS320C3X_LDFcond, // Load floating-point value conditionally +TMS320C3X_LDIcond, // Load integer conditionally +TMS320C3X_BR, // Branch unconditionally (standard) +TMS320C3X_BRD, // Branch unconditionally (delayed) +TMS320C3X_CALL, // Call subroutine +TMS320C3X_RPTB, // Repeat block of instructions +TMS320C3X_SWI, // Software Interrupt +TMS320C3X_Bcond, // Branch conditionally +TMS320C3X_DBcond, // Decrement and branch conditionally +TMS320C3X_CALLcond, // Call subroutine conditionally +TMS320C3X_TRAPcond, // Trap Conditionally +TMS320C3X_RETIcond, // Return from interrupt conditionally +TMS320C3X_RETScond, // Return from subroutine conditionally +TMS320C3X_RETIU, // Return from interrupt unconditionally +TMS320C3X_RETSU, // Return from subroutine unconditionally + +TMS320C3X_NONE, // Pseudo insn (more accurate definition need) +TMS320C3X_MV_IDX, // Pseudo insn (move to next index need) +TMS320C3X_last, // last ID + +}; + + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +TMS320C54_null = 0, // Unknown Operation + +// ARITHMETIC OPERATIONS + +// ADD INSTRUCTIONS + +TMS320C54_add1, // Add to Accumulator +TMS320C54_add2, // Add to Accumulator +TMS320C54_add3, // Add to Accumulator +TMS320C54_addc, // Add to Accumulator With Carry +TMS320C54_addm, // Add Long-Immediate Value to Memory +TMS320C54_adds, // Add to Accumulator With Sign-Extension Suppressed + +// SUBTRACT INSTRUCTIONS + +TMS320C54_sub1, // Sub From Accumulator +TMS320C54_sub2, // Sub From Accumulator +TMS320C54_sub3, // Sub From Accumulator +TMS320C54_subb, // Sub From Accumulator With Borrow +TMS320C54_subc, // Subtract Conditionally +TMS320C54_subs, // Subtract From Accumulator With Sign Extension Suppressed + +// MULTIPLY INSTRUCTIONS + +TMS320C54_mpy2, // Multiply Without Rounding +TMS320C54_mpy3, // Multiply Without Rounding +TMS320C54_mpyr2, // Multiply With Rounding +TMS320C54_mpya, // Multiply by Accumulator A +TMS320C54_mpyu, // Multiply Unsigned +TMS320C54_squr, // Square + +// MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS + +TMS320C54_mac2, // Multiply Accumulate Without Rounding +TMS320C54_mac3, // Multiply Accumulate Without Rounding +TMS320C54_macr2, // Multiply Accumulate With Rounding +TMS320C54_macr3, // Multiply Accumulate With Rounding +TMS320C54_maca1, // Multiply by Accumulator A and Accumulate Without Rounding +TMS320C54_maca2, // Multiply by Accumulator A and Accumulate Without Rounding +TMS320C54_maca3, // Multiply by Accumulator A and Accumulate Without Rounding +TMS320C54_macar1, // Multiply by Accumulator A and Accumulate With Rounding +TMS320C54_macar2, // Multiply by Accumulator A and Accumulate With Rounding +TMS320C54_macar3, // Multiply by Accumulator A and Accumulate With Rounding +TMS320C54_macd, // Multiply by Program Memory and Accumulate With Delay +TMS320C54_macp, // Multiply by Program Memory and Accumulate +TMS320C54_macsu, // Multiply Signed by Unsigned and Accumulate +TMS320C54_mas2, // Multiply and Subtract Without Rounding +TMS320C54_mas3, // Multiply and Subtract Without Rounding +TMS320C54_masr2, // Multiply and Subtract With Rounding +TMS320C54_masr3, // Multiply and Subtract With Rounding +// TMS320C54_mas, +TMS320C54_masa1, // Multiply by Accumulator A and Subtract Without Rounding +TMS320C54_masa2, // Multiply by Accumulator A and Subtract Without Rounding +TMS320C54_masa3, // Multiply by Accumulator A and Subtract Without Rounding +TMS320C54_masar1, // Multiply by Accumulator A and Subtract With Rounding +TMS320C54_masar2, // Multiply by Accumulator A and Subtract With Rounding +TMS320C54_masar3, // Multiply by Accumulator A and Subtract With Rounding +TMS320C54_squra, // Square and Accumulate +TMS320C54_squrs, // Square and Subtract + +// DOUBLE INSTRUCTIONS + +TMS320C54_dadd2, // Double-Precision/Dual 16-Bit Add to Accumulator +TMS320C54_dadd3, // Double-Precision/Dual 16-Bit Add to Accumulator +TMS320C54_dadst, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract +TMS320C54_drsub, // Double-Precision/Dual 16-Bit Subtract From Long Word +TMS320C54_dsadt, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add +TMS320C54_dsub, // Double-Precision/Dual 16-Bit Subtract From Accumulator +TMS320C54_dsubt, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract + +// APPLICATION-SPECIFIC INSTRUCTIONS + +TMS320C54_abdst, // Absolute distance +TMS320C54_abs1, // Absolute Value of Accumulator +TMS320C54_abs2, // Absolute Value of Accumulator +TMS320C54_cmpl1, // Complement Accumulator +TMS320C54_cmpl2, // Complement Accumulator +TMS320C54_delay, // Memory Delay +TMS320C54_exp, // Accumulator Exponent +TMS320C54_firs, // Symmetrical Finite Impulse Response Filter +TMS320C54_lms, // Least Mean Square +TMS320C54_max, // Accumulator Maximum +TMS320C54_min, // Accumulator Minimum +TMS320C54_neg1, // Negate Accumulator +TMS320C54_neg2, // Negate Accumulator +TMS320C54_norm1, // Normalization +TMS320C54_norm2, // Normalization +TMS320C54_poly, // Polynominal Evaluation +TMS320C54_rnd1, // Round Accumulator +TMS320C54_rnd2, // Round Accumulator +TMS320C54_sat, // Saturate Accumulator +TMS320C54_sqdst, // Square Distance + +// LOGICAL OPERATIONS + +// AND INSTRUCTIONS + +TMS320C54_and1, // AND With Accumulator +TMS320C54_and2, // AND With Accumulator +TMS320C54_and3, // AND With Accumulator +TMS320C54_andm, // AND Memory With Long Immediate + +// OR INSTRUCTIONS + +TMS320C54_or1, // OR With Accumulator +TMS320C54_or2, // OR With Accumulator +TMS320C54_or3, // OR With Accumulator +TMS320C54_orm, // OR Memory With Constant + +// XOR INSTRUCTIONS + +TMS320C54_xor1, // Exclusive OR With Accumulator +TMS320C54_xor2, // Exclusive OR With Accumulator +TMS320C54_xor3, // Exclusive OR With Accumulator +TMS320C54_xorm, // Exclusive OR Memory With Constant + +// SHIFT INSTRUCTIONS + +TMS320C54_rol, // Rotate Accumulator +TMS320C54_roltc, // Rotate Accumulator Left Using TC +TMS320C54_ror, // Rotate Accumulator Right +TMS320C54_sfta2, // Shift Accumulator Arithmetically +TMS320C54_sfta3, // Shift Accumulator Arithmetically +TMS320C54_sftc, // Shift Accumulator Conditionally +TMS320C54_sftl2, // Shift Accumulator Logically +TMS320C54_sftl3, // Shift Accumulator Logically + +// TEST INSTRUCTIONS + +TMS320C54_bit, // Test Bit +TMS320C54_bitf, // Test Bit Field Specified by Immediate Value +TMS320C54_bitt, // Test Bit Specified by T +TMS320C54_cmpm, // Compare Memory With Long Immediate +TMS320C54_cmpr, // Compare Auxiliary Register with AR0 + +// PROGRAM CONTROL OPERATIONS + +// BRANCH INSTRUCTIONS + +TMS320C54_b, // Branch Unconditionally +TMS320C54_bd, // Branch Unconditionally +TMS320C54_bacc, // Branch to Location Specified by Accumulator +TMS320C54_baccd, // Branch to Location Specified by Accumulator +TMS320C54_banz, // Branch on Auxiliary Register Not Zero +TMS320C54_banzd, // Branch on Auxiliary Register Not Zero +TMS320C54_bc2, // Branch Conditionally +TMS320C54_bc3, // Branch Conditionally +TMS320C54_bcd2, // Branch Conditionally +TMS320C54_bcd3, // Branch Conditionally +TMS320C54_fb, // Far Branch Unconditionally +TMS320C54_fbd, // Far Branch Unconditionally +TMS320C54_fbacc, // Far Branch to Location Specified by Accumulator +TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator + +// CALL INSTRUCTIONS + +TMS320C54_cala, // Call Subroutine at Location Specified by Accumulator +TMS320C54_calad, // Call Subroutine at Location Specified by Accumulator +TMS320C54_call, // Call Unconditionally +TMS320C54_calld, // Call Unconditionally +TMS320C54_cc2, // Call Conditionally +TMS320C54_cc3, // Call Conditionally +TMS320C54_ccd2, // Call Conditionally +TMS320C54_ccd3, // Call Conditionally +TMS320C54_fcala, // Far Call Subroutine at Location Specified by Accumulator +TMS320C54_fcalad, // Far Call Subroutine at Location Specified by Accumulator +TMS320C54_fcall, // Far Call Unconditionally +TMS320C54_fcalld, // Far Call Unconditionally + +// INTERRUPT INSTRUCTIONS + +TMS320C54_intr, // Software Interrupt +TMS320C54_trap, // Software Interrupt + +// RETURN INSTRUCTIONS + +TMS320C54_fret, // Far Return +TMS320C54_fretd, // Far Return +TMS320C54_frete, // Enable Interrupts and Far Return From Interrupt +TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt +TMS320C54_rc1, // Return Conditionally +TMS320C54_rc2, // Return Conditionally +TMS320C54_rc3, // Return Conditionally +TMS320C54_rcd1, // Return Conditionally +TMS320C54_rcd2, // Return Conditionally +TMS320C54_rcd3, // Return Conditionally +TMS320C54_ret, // Return +TMS320C54_retd, // Return +TMS320C54_rete, // Enable Interrupts and Return From Interrupt +TMS320C54_reted, // Enable Interrupts and Return From Interrupt +TMS320C54_retf, // Enable Interrupts and Fast Return From Interrupt +TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt + +// REPEAT INSTRUCTIONS + +TMS320C54_rpt, // Repeat Next Instruction +TMS320C54_rptb, // Block Repeat +TMS320C54_rptbd, // Block Repeat +TMS320C54_rptz, // Repeat Next Instruction And Clear Accumulator + +// STACK MANIPULATING INSTRUCTIONS + +TMS320C54_frame, // Stack Pointer Immediate Offset +TMS320C54_popd, // Pop Top of Stack to Data Memory +TMS320C54_popm, // Pop Top of Stack to Memory-Mapped Register +TMS320C54_pshd, // Push Data-Memory Value Onto Stack +TMS320C54_pshm, // Push Memory-Mapped Register Onto Stack + +// MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS + +TMS320C54_idle, // Idle Until Interrupt +TMS320C54_mar, // Modify Auxiliary Register +TMS320C54_nop, // No Operation +TMS320C54_reset, // Software Reset +TMS320C54_rsbx1, // Reset Status Register Bit +TMS320C54_rsbx2, // Reset Status Register Bit +TMS320C54_ssbx1, // Set Status Register Bit +TMS320C54_ssbx2, // Set Status Register Bit +TMS320C54_xc2, // Execute Conditionally +TMS320C54_xc3, // Execute Conditionally + +// LOAD AND STORE OPERATIONS + +// LOAD INSTRUCTIONS + +TMS320C54_dld, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator +TMS320C54_ld1, // Load Accumulator With Shift +TMS320C54_ld2, // Load Accumulator With Shift +TMS320C54_ld3, // Load Accumulator With Shift +TMS320C54_ldm, // Load Memory-Mapped Register +TMS320C54_ldr, // Load Memory Value in Accumulator High With Rounding +TMS320C54_ldu, // Load Unsigned Memory Value +TMS320C54_ltd, // Load T and insert Delay + +// STORE INSTRUCTIONS + +TMS320C54_dst, // Store Accumulator in Long Word +TMS320C54_st, // Store T, TRN, or Immediate Value into Memory +TMS320C54_sth2, // Store Accumulator High Into Memory +TMS320C54_sth3, // Store Accumulator High Into Memory +TMS320C54_stl2, // Store Accumulator Low Into Memory +TMS320C54_stl3, // Store Accumulator Low Into Memory +TMS320C54_stlm, // Store Accumulator Low Into Memory-Mapped Register +TMS320C54_stm, // Store Immediate Value Into Memory-Mapped Register + +// CONDITIONAL STORE INSTRUCTIONS + +TMS320C54_cmps, // Compare, Select and Store Maximum +TMS320C54_saccd, // Store Accumulator Conditionally +TMS320C54_srccd, // Store Block Repeat Counter Conditionally +TMS320C54_strcd, // Store T Conditionally + +// PARALLEL LOAD AND STORE INSTRUCTIONS + +TMS320C54_st_ld, // Store Accumulator With Parallel Load + +// PARALLEL LOAD AND MULTIPLY INSTRUCTIONS + +TMS320C54_ld_mac, // Load Accumulator With Parallel Multiply Accumulate Without Rounding +TMS320C54_ld_macr, // Load Accumulator With Parallel Multiply Accumulate With Rounding +TMS320C54_ld_mas, // Load Accumulator With Parallel Multiply Subtract Without Rounding +TMS320C54_ld_masr, // Load Accumulator With Parallel Multiply Subtract With Rounding + +// PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS + +TMS320C54_st_add, // Store Accumulator With Parallel Add +TMS320C54_st_sub, // Store Accumulator With Parallel Subtract + +// PARALLEL STORE AND MULTIPLY INSTRUCTIONS + +TMS320C54_st_mac, // Store Accumulator With Parallel Multiply Accumulate Without Rounding +TMS320C54_st_macr, // Store Accumulator With Parallel Multiply Accumulate With Rounding +TMS320C54_st_mas, // Store Accumulator With Parallel Multiply Subtract Without Rounding +TMS320C54_st_masr, // Store Accumulator With Parallel Multiply Subtract With Rounding +TMS320C54_st_mpy, // Store Accumulator With Parallel Multiply + +// MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS + +TMS320C54_mvdd, // Move Data From Data Memory to Data Memory With X,Y Addressing +TMS320C54_mvdk, // Move Data From Data Memory to Data Memory With Destination Addressing +TMS320C54_mvdm, // Move Data From Data Memory to Memory-Mapped Register +TMS320C54_mvdp, // Move Data From Data Memory to Program Memory +TMS320C54_mvkd, // Move Data From Data Memory to Data Memory With Source Addressing +TMS320C54_mvmd, // Move Data From Memory-Mapped Register to Data Memory +TMS320C54_mvmm, // Move Data From Memory-Mapped Register to Memory-Mapped Register +TMS320C54_mvpd, // Move Data From Program Memory to Data Memory +TMS320C54_portr, // Read Data From Port +TMS320C54_portw, // Write Data to Port +TMS320C54_reada, // Read Program Memory Addressed by Accumulator A and Store in Data Memory +TMS320C54_writa, // Write Data to Program Memory Addressed by Accumulator A + +TMS320C54_last + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +TMS320C55_null = 0, // Unknown Operation + +// ARITHMETICAL OPERATIONS + +TMS320C55_abdst, // Absolute Distance +TMS320C55_abs1, // Absolute Value +TMS320C55_abs2, // Absolute Value + +TMS320C55_add1, // Addition +TMS320C55_add2, // Addition +TMS320C55_add3, // Addition +TMS320C55_add4, // Addition +TMS320C55_addv1, // Addition +TMS320C55_addv2, // Addition +TMS320C55_addrv1, // Addition and Round +TMS320C55_addrv2, // Addition and Round + +TMS320C55_maxdiff, // Compare and Select Maximum +TMS320C55_dmaxdiff, // Compare and Select 40-bit Maximum +TMS320C55_mindiff, // Compare and Select Minimum +TMS320C55_dmindiff, // Compare and Select 40-bit Minimum + +TMS320C55_addsubcc4, // Conditional Add or Subtract +TMS320C55_addsubcc5, // Conditional Add or Subtract +TMS320C55_addsub2cc, // Conditional Add or Subtract + +TMS320C55_sftcc, // Conditional Shift + +TMS320C55_subc2, // Conditional Subtract +TMS320C55_subc3, // Conditional Subtract + +TMS320C55_addsub, // Paralleled Add - Subtract +TMS320C55_subadd, // Parallel Subtract - Add + +TMS320C55_mpy_mpy, // Two Parallel Multiply +TMS320C55_mpy_mpyr, // Two Parallel Multiply, and Round +TMS320C55_mpy_mpy40, // Two Parallel Multiply, on 40 bits +TMS320C55_mpy_mpyr40, // Two Parallel Multiply, and Round on 40 bits +TMS320C55_mac_mpy, // Parallel Multiply - Accumulate +TMS320C55_macr_mpyr, // Parallel Multiply - Accumulate, and Round +TMS320C55_mac40_mpy40, // Parallel Multiply - Accumulate, on 40 bits +TMS320C55_macr40_mpyr40, // Parallel Multiply - Accumulate, and Round on 40 bits +TMS320C55_mas_mpy, // Parallel Multiply - Subtract +TMS320C55_masr_mpyr, // Parallel Multiply - Subtract, and Round +TMS320C55_mas40_mpy40, // Parallel Multiply - Subtract, on 40 bits +TMS320C55_masr40_mpyr40, // Parallel Multiply - Subtract, and Round on 40 bits +TMS320C55_amar_mpy, // Parallel Modify Auxiliary Register - Multiply +TMS320C55_amar_mpyr, // Parallel Modify Auxiliary Register - Multiply, and Round +TMS320C55_amar_mpy40, // Parallel Modify Auxiliary Register - Multiply, on 40 bits +TMS320C55_amar_mpyr40, // Parallel Modify Auxiliary Register - Multiply, and Round on 40 bits +TMS320C55_mac_mac, // Two Parallel Multiply and Accumulate +TMS320C55_macr_macr, // Two Parallel Multiply and Accumulate, and Round +TMS320C55_mac40_mac40, // Two Parallel Multiply and Accumulate, on 40 bits +TMS320C55_macr40_macr40, // Two Parallel Multiply and Accumulate, and Round on 40 bits +TMS320C55_mas_mac, // Parallel Multiply and Subtract - Multiply and Accumulate +TMS320C55_masr_macr, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round +TMS320C55_mas40_mac40, // Parallel Multiply and Subtract - Multiply and Accumulate, on 40 bits +TMS320C55_masr40_macr40, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round on 40 bits +TMS320C55_amar_mac, // Parallel Modify Auxiliary Register - Multiply and Accumulate +TMS320C55_amar_macr, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round +TMS320C55_amar_mac40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, on 40 bits +TMS320C55_amar_macr40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round on 40 bits +TMS320C55_mas_mas, // Two Parallel Multiply and Subtract +TMS320C55_masr_masr, // Two Parallel Multiply and Subtract, and Round +TMS320C55_mas40_mas40, // Two Parallel Multiply and Subtract, on 40 bits +TMS320C55_masr40_masr40, // Two Parallel Multiply and Subtract, and Round on 40 bits +TMS320C55_amar_mas, // Parallel Modify Auxiliary Register - Multiply and Subtract +TMS320C55_amar_masr, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round +TMS320C55_amar_mas40, // Parallel Modify Auxiliary Register - Multiply and Subtract, on 40 bits +TMS320C55_amar_masr40, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round on 40 bits +TMS320C55_mpy_mac, // Parallel Multiply - Multiply and Accumulate +TMS320C55_mpyr_macr, // Parallel Multiply - Multiply and Accumulate, and Round +TMS320C55_mpy40_mac40, // Parallel Multiply - Multiply and Accumulate, on 40 bits +TMS320C55_mpyr40_macr40, // Parallel Multiply - Multiply and Accumulate, and Round on 40 bits +TMS320C55_amar3, // Three Parallel Modify Auxiliary Registers + +TMS320C55_firsadd, // Parallel Multiply and Accumulate - Add +TMS320C55_firssub, // Parallel Multiply and Accumulate - Subtract + +TMS320C55_mpym_mov, // Parallel Multiply - Store +TMS320C55_mpymr_mov, // Parallel Multiply - Store, and Round +TMS320C55_macm_mov, // Parallel Multiply and Accumulate - Store +TMS320C55_macmr_mov, // Parallel Multiply and Accumulate - Store, and Round +TMS320C55_masm_mov, // Parallel Multiply and Subtract - Store +TMS320C55_masmr_mov, // Parallel Multiply and Subtract - Store, and Round +TMS320C55_add_mov, // Parallel Add - Store +TMS320C55_sub_mov, // Parallel Subtract - Store +TMS320C55_mov_mov, // Parallel Load - Store +TMS320C55_mov_aadd, // Parallel Store - aadd +TMS320C55_mov_add, // Parallel Store - Add +TMS320C55_amar_amar, // Parallel Modify Auxiliary Register - Modify Auxiliary Register +TMS320C55_add_asub, // Parallel Add - asub +TMS320C55_btst_mov, // Parallel Bit Test - Store +TMS320C55_mov_asub, // Parallel Store - asub + +TMS320C55_lms, // Least Mean Square + +TMS320C55_max1, // Maximum Comparison +TMS320C55_max2, // Maximum Comparison +TMS320C55_min1, // Minimum Comparison +TMS320C55_min2, // Minimum Comparison + +TMS320C55_cmp, // Memory Comparison +TMS320C55_cmpu, // Unsigned memory Comparison + +TMS320C55_aadd, // Add Two Registers +TMS320C55_asub, // Subtract Two Registers +TMS320C55_amov, // Move From Register to Register +TMS320C55_amar1, // Auxiliary Register Modification + +TMS320C55_sqr1, // Square +TMS320C55_sqr2, // Square +TMS320C55_sqrr1, // Square and Round +TMS320C55_sqrr2, // Square and Round +TMS320C55_mpy1, // Multiply +TMS320C55_mpy2, // Multiply +TMS320C55_mpy3, // Multiply +TMS320C55_mpyr1, // Multiply and Round +TMS320C55_mpyr2, // Multiply and Round +TMS320C55_mpyr3, // Multiply and Round +TMS320C55_mpyk2, // Multiply by Constant +TMS320C55_mpyk3, // Multiply by Constant +TMS320C55_mpykr2, // Multiply by Constant and Round +TMS320C55_mpykr3, // Multiply by Constant and Round +TMS320C55_mpym2, // Multiply Memory Value +TMS320C55_mpym3, // Multiply Memory Values +TMS320C55_mpymr2, // Multiply Memory Value and Round +TMS320C55_mpymr3, // Multiply Memory Values and Round +TMS320C55_mpym403, // Multiply Memory Values on 40 bits +TMS320C55_mpymr403, // Multiply Memory Values and Round on 40 bits +TMS320C55_mpymu3, // Unsigned multiply Memory Values +TMS320C55_mpymru3, // Unsigned multiply Memory Values and Round +TMS320C55_sqrm, // Square Memory Value +TMS320C55_sqrmr, // Square Memory Value, and Round +TMS320C55_mpymk, // Multiply Memory Value by Constant +TMS320C55_mpymkr, // Multiply Memory Value by Constant and Round + +TMS320C55_sqa1, // Square and Accumulate +TMS320C55_sqa2, // Square and Accumulate +TMS320C55_sqar1, // Square, Accumulate and Round +TMS320C55_sqar2, // Square, Accumulate and Round +TMS320C55_mac3, // Multiply and Accumulate +TMS320C55_mac4, // Multiply and Accumulate +TMS320C55_macr3, // Multiply, Accumulate and Round +TMS320C55_macr4, // Multiply, Accumulate and Round +TMS320C55_mack3, // Multiply by Constant and Accumulate +TMS320C55_mack4, // Multiply by Constant and Accumulate +TMS320C55_mackr3, // Multiply by Constant, Round and Accumulate +TMS320C55_mackr4, // Multiply by Constant, Round and Accumulate +TMS320C55_macm2, // Multiply and Accumulate Memory Values +TMS320C55_macm3, // Multiply and Accumulate Memory Values +TMS320C55_macm4, // Multiply and Accumulate Memory Values +TMS320C55_macmr2, // Multiply and Accumulate Memory Values, and Round +TMS320C55_macmr3, // Multiply and Accumulate Memory Values, and Round +TMS320C55_macmr4, // Multiply and Accumulate Memory Values, and Round +TMS320C55_macm403, // Multiply and Accumulate Memory Values, on 40 bits +TMS320C55_macm404, // Multiply and Accumulate Memory Values, on 40 bits +TMS320C55_macmr403, // Multiply and Accumulate Memory Values, and Round on 40 bits +TMS320C55_macmr404, // Multiply and Accumulate Memory Values, and Round on 40 bits +TMS320C55_macmz, // Multiply and Accumulate Memory Values +TMS320C55_macmrz, // Multiply and Accumulate Memory Values, and Round +TMS320C55_sqam2, // Square and Accumulate Memory Value +TMS320C55_sqam3, // Square and Accumulate Memory Values +TMS320C55_sqamr2, // Square and Accumulate Memory Value, and Round +TMS320C55_sqamr3, // Square and Accumulate Memory Values, and Round +TMS320C55_macmk3, // Multiply Memory Value by Constant and Accumulate +TMS320C55_macmk4, // Multiply Memory Value by Constant and Accumulate +TMS320C55_macmkr3, // Multiply Memory Value by Constant - Accumulate, and Round +TMS320C55_macmkr4, // Multiply Memory Value by Constant - Accumulate, and Round + +TMS320C55_sqs1, // Square and Subtract +TMS320C55_sqs2, // Square and Subtract +TMS320C55_sqsr1, // Square, Subtract and Round +TMS320C55_sqsr2, // Square, Subtract and Round + +TMS320C55_mas2, // Multiply and Subtract +TMS320C55_mas3, // Multiply and Subtract +TMS320C55_masr2, // Multiply, Subtract and Round +TMS320C55_masr3, // Multiply, Subtract and Round +TMS320C55_masm2, // Multiply and Subtract Memory Value +TMS320C55_masm3, // Multiply and Subtract Memory Values +TMS320C55_masm4, // Multiply and Subtract Memory Values +TMS320C55_masmr2, // Multiply and Subtract Memory Values, and Round +TMS320C55_masmr3, // Multiply and Subtract Memory Values, and Round +TMS320C55_masmr4, // Multiply and Subtract Memory Values, and Round +TMS320C55_masm403, // Multiply and Subtract Memory Values, on 40 bits +TMS320C55_masm404, // Multiply and Subtract Memory Values, on 40 bits +TMS320C55_masmr403, // Multiply and Subtract Memory Values, and Round on 40 bits +TMS320C55_masmr404, // Multiply and Subtract Memory Values, and Round on 40 bits +TMS320C55_sqsm2, // Square and Subtract Memory Values +TMS320C55_sqsm3, // Square and Subtract Memory Values +TMS320C55_sqsmr2, // Square and Subtract Memory Values, and Round +TMS320C55_sqsmr3, // Square and Subtract Memory Values, and Round + +TMS320C55_neg1, // Negation +TMS320C55_neg2, // Negation + +TMS320C55_mant_nexp, // Exponent and Mantissa +TMS320C55_exp, // Exponent + +TMS320C55_cmpand, // Compare and AND +TMS320C55_cmpandu, // Unsigned compare and AND +TMS320C55_cmpor, // Compare and OR +TMS320C55_cmporu, // Unsigned compare and OR + +TMS320C55_round1, // Round +TMS320C55_round2, // Round + +TMS320C55_sat1, // Saturate +TMS320C55_sat2, // Saturate +TMS320C55_satr1, // Saturate and Round +TMS320C55_satr2, // Saturate and Round + +TMS320C55_sfts2, // Signed Shift +TMS320C55_sfts3, // Signed Shift +TMS320C55_sftsc2, // Signed Shift with Carry +TMS320C55_sftsc3, // Signed Shift with Carry + +TMS320C55_sqdst, // Square distance + +TMS320C55_sub1, // Subtract +TMS320C55_sub2, // Subtract +TMS320C55_sub3, // Subtract +TMS320C55_sub4, // Subtract + +TMS320C55_band, // Bit Field Comparison + +TMS320C55_bfxpa, // Bit Field Expand + +TMS320C55_bfxtr, // Bit Field Extract + +TMS320C55_btst, // Bit Test +TMS320C55_bnot, // Bit NOT +TMS320C55_bclr2, // Bit Clear +TMS320C55_bset2, // Bit Set +TMS320C55_btstset, // Bit Test and Set +TMS320C55_btstclr, // Bit Test and Clear +TMS320C55_btstnot, // Bit Test and NOT +TMS320C55_btstp, // Bit Pair Test +TMS320C55_bclr1, // Bit Clear +TMS320C55_bset1, // Bit Set + +TMS320C55_amar2, // Load Effective Address to Extended Auxiliary Register +TMS320C55_popboth, // Pop Extended Auxiliary Register from Stack Pointers +TMS320C55_pshboth, // Push Extended Auxiliary Register to Stack Pointers + +// LOGICAL OPERATIONS + +TMS320C55_bcnt, // Count Bit Field + +TMS320C55_not1, // NOT +TMS320C55_not2, // NOT + +TMS320C55_and1, // AND +TMS320C55_and2, // AND +TMS320C55_and3, // AND + +TMS320C55_or1, // OR +TMS320C55_or2, // OR +TMS320C55_or3, // OR + +TMS320C55_xor1, // XOR +TMS320C55_xor2, // XOR +TMS320C55_xor3, // XOR + +TMS320C55_sftl2, // Logical Shift +TMS320C55_sftl3, // Logical Shift + +TMS320C55_rol, // Rotate Left + +TMS320C55_ror, // Rotate Right + +// MISCELLANEOUS OPERATIONS + +// MOVE OPERATIONS + +TMS320C55_swap, // Swap Registers +TMS320C55_swapp, // Swap Pair Registers +TMS320C55_swap4, // Swap 4 Registers + +TMS320C55_mov2, // Move Data +TMS320C55_mov3, // Move 2 Data +TMS320C55_mov402, // Move Data on 40 bits + +TMS320C55_delay, // Memory Delay + +TMS320C55_pop1, // Pop Top of Stack1 +TMS320C55_pop2, // Pop Top of Stack2 + +TMS320C55_psh1, // Pop Top of Stack3 +TMS320C55_psh2, // Pop Top of Stack4 + +// PROGRAM CONTROL OPERATIONS + +TMS320C55_bcc, // Branch Conditionally +TMS320C55_bccu, // Branch Conditionally + +TMS320C55_b, // Branch Unconditionally + +TMS320C55_callcc, // Call Conditionally + +TMS320C55_call, // Call Unconditionally + +TMS320C55_xcc, // Execute Conditionally +TMS320C55_xccpart, // Execute Conditionally + +TMS320C55_idle, // Idle + +TMS320C55_nop, // No Operation +TMS320C55_nop_16, // No Operation + +TMS320C55_rptblocal, // Repeat Block of Instructions Unconditionally +TMS320C55_rptb, // Repeat Block of Instructions Unconditionally + +TMS320C55_rptcc, // Repeat Single Instruction Conditionally + +TMS320C55_rpt, // Repeat Single Instruction Unconditionally +TMS320C55_rptadd, // Repeat Single Instruction Unconditionally and Add to Register +TMS320C55_rptsub, // Repeat Single Instruction Unconditionally and Subtract to Register + +TMS320C55_retcc, // Return Conditionally +TMS320C55_ret, // Return Unconditionally +TMS320C55_reti, // Return from Interrupt + +TMS320C55_intr, // Software Interrupt + +TMS320C55_reset, // Software Reset + +TMS320C55_trap, // Software Trap + +TMS320C55_last + +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +TRIMEDIA_null, + +TRIMEDIA_igtri, // signed compare greater with immediate +TRIMEDIA_igeqi, // signed compare greater or equal with immediate +TRIMEDIA_ilesi, // signed compare less with immediate +TRIMEDIA_ineqi, // signed compare not equal with immediate +TRIMEDIA_ieqli, // signed compare equal with immediate +TRIMEDIA_iaddi, // add with immediate +TRIMEDIA_ild16d, // signed 16-bit load with displacement +TRIMEDIA_ld32d, // 32-bit load with displacement +TRIMEDIA_uld8d, // unsigned 8-bit load with displacement +TRIMEDIA_lsri, // logical shift right immediate +TRIMEDIA_asri, // arithmetic shift right immediate +TRIMEDIA_asli, // arithmetic shift left immediate +TRIMEDIA_iadd, // signed add +TRIMEDIA_isub, // signed subtract +TRIMEDIA_igeq, // signed compare greater or equal +TRIMEDIA_igtr, // signed compare greater +TRIMEDIA_bitand, // bitwise logical AND +TRIMEDIA_bitor, // bitwise logical OR +TRIMEDIA_asr, // arithmetic shift right +TRIMEDIA_asl, // arithmetic shift left +TRIMEDIA_ifloat, // convert signed integer to floating-point +TRIMEDIA_ifixrz, // convert floating-point to integer with round toward zero +TRIMEDIA_fadd, // floating-point add +TRIMEDIA_imin, // signed minimum +TRIMEDIA_imax, // signed maximum +TRIMEDIA_iavgonep, // signed average +TRIMEDIA_ume8uu, // sum of absolute values of unsigned 8-bit differences +TRIMEDIA_imul, // signed multiply +TRIMEDIA_fmul, // floating-point multiply +TRIMEDIA_h_st8d, // hardware 8-bit store with displacement +TRIMEDIA_h_st16d, // hardware 16-bit store with displacement +TRIMEDIA_h_st32d, // hardware 32-bit store with displacement +TRIMEDIA_isubi, // subtract with immediate +TRIMEDIA_ugtr, // unsigned compare greater +TRIMEDIA_ugtri, // unsigned compare greater with immediate +TRIMEDIA_ugeq, // unsigned compare greater or equal +TRIMEDIA_ugeqi, // unsigned compare greater or equal with immediate +TRIMEDIA_ieql, // signed compare equal +TRIMEDIA_ueqli, // unsigned compare equal with immediate +TRIMEDIA_ineq, // signed compare not equal +TRIMEDIA_uneqi, // unsigned compare not equal +TRIMEDIA_ulesi, // unsigned compare less with immediate +TRIMEDIA_ileqi, // signed compare less or equal with immediate +TRIMEDIA_uleqi, // unsigned compare less or equal with immediate +TRIMEDIA_h_iabs, // hardware absolute value +TRIMEDIA_carry, // compute carry bit from unsigned add +TRIMEDIA_izero, // if zero select zero +TRIMEDIA_inonzero, // if nonzero select zero +TRIMEDIA_bitxor, // bitwise logical exclusive OR +TRIMEDIA_bitandinv, // bitwise logical AND NOT +TRIMEDIA_bitinv, // bitwise logical NOT +TRIMEDIA_sex16, // sign extend 16 bits +TRIMEDIA_packbytes, // pack least-significant bytes +TRIMEDIA_pack16lsb, // pack least-significant 16-bit halfwords +TRIMEDIA_pack16msb, // pack most-significant 16-bit halfwords +TRIMEDIA_ubytesel, // select unsigned byte +TRIMEDIA_ibytesel, // signed select byte +TRIMEDIA_mergelsb, // merge least-significant byte +TRIMEDIA_mergemsb, // merge most-significant byte +TRIMEDIA_ume8ii, // unsigned sum of absolute values of signed 8-bit differences +TRIMEDIA_h_dspiabs, // clipped signed absolute value +TRIMEDIA_dspiadd, // clipped signed add +TRIMEDIA_dspuadd, // clipped unsigned add +TRIMEDIA_dspisub, // clipped signed subtract +TRIMEDIA_dspusub, // clipped unsigned subtract +TRIMEDIA_dspidualadd, // dual clipped add of signed 16-bit halfwords +TRIMEDIA_dspidualsub, // dual clipped subtract of signed 16-bit halfwords +TRIMEDIA_h_dspidualabs, // dual clipped absolute value of signed 16-bit halfwords +TRIMEDIA_quadavg, // unsigned byte-wise quad average +TRIMEDIA_iclipi, // clip signed to signed +TRIMEDIA_uclipi, // clip signed to unsigned +TRIMEDIA_uclipu, // clip unsigned to unsigned +TRIMEDIA_iflip, // if non-zero negate +TRIMEDIA_dspuquadaddui, // quad clipped add of unsigned/signed bytes +TRIMEDIA_quadumin, // unsigned byte-wise quad minimum +TRIMEDIA_quadumax, // unsigned byte-wise quad maximum +TRIMEDIA_dualiclipi, // dual-16 clip signed to signed +TRIMEDIA_dualuclipi, // dual-16 clip signed to unsigned +TRIMEDIA_quadumulmsb, // unsigned quad 8-bit multiply most significant +TRIMEDIA_ufir8uu, // unsigned sum of products of unsigned bytes +TRIMEDIA_ifir8ui, // signed sum of products of unsigned/signed bytes +TRIMEDIA_ifir8ii, // signed sum of products of signed bytes +TRIMEDIA_ifir16, // sum of products of signed 16-bit halfwords +TRIMEDIA_ufir16, // sum of products of unsigned 16-bit halfwords +TRIMEDIA_dspidualmul, // dual clipped multiply of signed 16-bit halfwords +TRIMEDIA_lsr, // logical shift right +TRIMEDIA_rol, // rotate left +TRIMEDIA_roli, // rotate left by immediate +TRIMEDIA_funshift1, // funnel-shift 1 byte +TRIMEDIA_funshift2, // funnel-shift 2 bytes +TRIMEDIA_funshift3, // funnel-shift 3 bytes +TRIMEDIA_dualasr, // dual-16 arithmetic shift right +TRIMEDIA_mergedual16lsb,// merge dual 16-bit lsb bytes +TRIMEDIA_fdiv, // floating-point divide +TRIMEDIA_fdivflags, // IEEE status flags from floating-point divide +TRIMEDIA_fsqrt, // floating-point square root +TRIMEDIA_fsqrtflags, // IEEE status flags from floating-point square root +TRIMEDIA_faddflags, // IEEE status flags from floating-point add +TRIMEDIA_fsub, // floating-point subtract +TRIMEDIA_fsubflags, // IEEE status flags from floating-point subtract +TRIMEDIA_fabsval, // floating-point absolute value +TRIMEDIA_fabsvalflags, // IEEE status flags from floating-point absolute value +TRIMEDIA_ifloatrz, // convert signed integer to floating-point with rounding toward zero +TRIMEDIA_ifloatrzflags, // IEEE status flags from convert signed integer to floating-point with rounding toward zero +TRIMEDIA_ufloatrz, // convert unsigned integer to floating-point with round toward zero +TRIMEDIA_ufloatrzflags, // IEEE status flags from convert unsigned integer to floating-point with round toward zero +TRIMEDIA_ifixieee, // convert floating-point to integer using PCSW rounding mode +TRIMEDIA_ifixieeeflags, // IEEE status flags from convert floating-point to integer using PCSW rounding mode +TRIMEDIA_ufixieee, // convert floating-point to unsigned integer using PCSW rounding mode +TRIMEDIA_ufixieeeflags, // IEEE status flags from convert floating-point to unsigned integer using PCSW rounding mode +TRIMEDIA_ufixrz, // convert floating-point to unsigned integer with round toward zero +TRIMEDIA_ufixrzflags, // IEEE status flags from convert floating-point to unsigned integer with round toward zero +TRIMEDIA_ufloat, // convert unsigned integer to floating-point +TRIMEDIA_ufloatflags, // IEEE status flags from convert unsigned integer to floating-point +TRIMEDIA_ifixrzflags, // IEEE status flags from convert floating-point to integer with round toward zero +TRIMEDIA_ifloatflags, // IEEE status flags from convert signed integer to floating-point +TRIMEDIA_umul, // unsigned multiply +TRIMEDIA_imulm, // signed multiply, return most-significant 32 bits +TRIMEDIA_umulm, // unsigned multiply, return most-significant 32 bits +TRIMEDIA_dspimul, // clipped signed multiply +TRIMEDIA_dspumul, // clipped unsigned multiply +TRIMEDIA_fmulflags, // IEEE status flags from floating-point multiply +TRIMEDIA_fgtr, // floating-point compare greater +TRIMEDIA_fgtrflags, // IEEE status flags from floating-point compare greater +TRIMEDIA_fgeq, // floating-point compare greater or equal +TRIMEDIA_fgeqflags, // IEEE status flags from floating-point compare greater or equal +TRIMEDIA_feql, // floating-point compare equal +TRIMEDIA_feqlflags, // IEEE status flags from floating-point compare equal +TRIMEDIA_fneq, // floating-point compare not equal +TRIMEDIA_fneqflags, // IEEE status flags from floating-point compare not equal +TRIMEDIA_fsign, // sign of floating-point value +TRIMEDIA_fsignflags, // IEEE status flags from floating-point sign +TRIMEDIA_cycles, // read clock cycle counter, least-significant word +TRIMEDIA_hicycles, // read clock cycle counter, most-significant word +TRIMEDIA_readdpc, // read destination program counter +TRIMEDIA_readspc, // read source program counter +TRIMEDIA_readpcsw, // read program control and status word +TRIMEDIA_writespc, // write source program counter +TRIMEDIA_writedpc, // write destination program counter +TRIMEDIA_writepcsw, // write program control and status word +TRIMEDIA_curcycles, // read current clock cycle, least-significant word +TRIMEDIA_jmpt, // indirect jump on true +TRIMEDIA_ijmpt, // interruptible indirect jump on true +TRIMEDIA_jmpi, // jump immediate +TRIMEDIA_ijmpi, // interruptible jump immediate +TRIMEDIA_jmpf, // indirect jump on false +TRIMEDIA_ijmpf, // interruptible indirect jump on false +TRIMEDIA_iclr, // invalidate all instruction cache blocks +TRIMEDIA_uimm, // unsigned immediate +TRIMEDIA_ild8d, // signed 8-bit load with displacement +TRIMEDIA_ild8r, // signed 8-bit load with index +TRIMEDIA_uld8r, // unsigned 8-bit load with index +TRIMEDIA_ild16r, // signed 16-bit load with index +TRIMEDIA_ild16x, // signed 16-bit load with scaled index +TRIMEDIA_uld16d, // unsigned 16-bit load with displacement +TRIMEDIA_uld16r, // unsigned 16-bit load with index +TRIMEDIA_uld16x, // unsigned 16-bit load with scaled index +TRIMEDIA_ld32r, // 32-bit load with index +TRIMEDIA_ld32x, // 32-bit load with scaled index +TRIMEDIA_rdtag, // read data cache address tag +TRIMEDIA_rdstatus, // read data cache status bits +TRIMEDIA_dcb, // data cache copy back +TRIMEDIA_dinvalid, // invalidate data cache block +TRIMEDIA_prefd, // prefetch with displacement +TRIMEDIA_prefr, // prefetch with index +TRIMEDIA_pref16x, // prefetch with 16-bit scaled index +TRIMEDIA_pref32x, // prefetch with 32-bit scaled index +TRIMEDIA_allocd, // allocate a cache block with displacement +TRIMEDIA_allocr, // allocate a cache block with index +TRIMEDIA_allocx, // allocate a cache block with scaled index +TRIMEDIA_nop, + +// Pseudo-operations + +TRIMEDIA_alloc, // allocate a cache block +TRIMEDIA_dspiabs, // clipped signed absolute value +TRIMEDIA_dspidualabs, // dual clipped absolute value of signed 16-bit halfwords +TRIMEDIA_iabs, // absolute value +TRIMEDIA_ild16, // signed 16-bit load +TRIMEDIA_ild8, // signed 8-bit load +TRIMEDIA_ineg, // signed negate +TRIMEDIA_ld32, // 32-bit load +TRIMEDIA_pref, // prefetch +TRIMEDIA_sex8, // sign extend 8 bits +TRIMEDIA_st16, // 16-bit store +TRIMEDIA_st16d, // 16-bit store with displacement +TRIMEDIA_st32, // 32-bit store +TRIMEDIA_st32d, // 32-bit store with displacement +TRIMEDIA_st8, // 8-bit store +TRIMEDIA_st8d, // 8-bit store with displacement +TRIMEDIA_uld16, // unsigned 16-bit load +TRIMEDIA_uld8, // unsigned 8-bit load +TRIMEDIA_zex16, // zero extend 16 bits +TRIMEDIA_zex8, // zero extend 8 bits +TRIMEDIA_ident, // identity + +// Unused pseudo-operations: + +TRIMEDIA_iles, +TRIMEDIA_ileq, +TRIMEDIA_ules, +TRIMEDIA_uleq, +TRIMEDIA_fles, +TRIMEDIA_fleq, +TRIMEDIA_ueql, +TRIMEDIA_uneq, +TRIMEDIA_flesflags, +TRIMEDIA_fleqflags, +TRIMEDIA_borrow, +TRIMEDIA_umin, +TRIMEDIA_lsl, +TRIMEDIA_lsli, + +TRIMEDIA_last, + + }; + +/* + * NEC 78K0 processor module for IDA. + * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + + + +enum +{ +NEC_78K_0_null = 0, // Unknown Operation + +NEC_78K_0_mov, // Move Byte Data Transfer +NEC_78K_0_xch, // Exchange Byte Data +NEC_78K_0_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer +NEC_78K_0_xchw, // Exchange Word Data + +NEC_78K_0_add, // Add Byte Data Addition +NEC_78K_0_addc, // Add with Carry Addition of Byte Data with Carry +NEC_78K_0_sub, // Subtract Byte Data Subtraction +NEC_78K_0_subc, // Subtract with Carry Subtraction of Byte Data with Carry +NEC_78K_0_and, // And Logical Product of Byte Data +NEC_78K_0_or, // Or Logical Sum of Byte Data +NEC_78K_0_xor, // Exclusive Or Exclusive Logical Sum of Byte Data +NEC_78K_0_cmp, // Compare Byte Data Comparison + +NEC_78K_0_addw, // Add Word Data Addition +NEC_78K_0_subw, // Subtract Word Data Subtraction +NEC_78K_0_cmpw, // Compare Word Data Comparison + +NEC_78K_0_mulu, // Multiply Unsigned Multiplication of Data +NEC_78K_0_divuw, // Divide Unsigned Word Unsigned Division of Word Data + +NEC_78K_0_inc, // Increment Byte Data Increment +NEC_78K_0_dec, // Decrement Byte Data Decrement +NEC_78K_0_incw, // Increment Word Data Increment +NEC_78K_0_decw, // Decrement Word Data Decrement + +NEC_78K_0_ror, // Rotate Right Byte Data Rotation to the Right +NEC_78K_0_rol, // Rotate Left Byte Data Rotation to the Left +NEC_78K_0_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry +NEC_78K_0_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry +NEC_78K_0_ror4, // Rotate Right Digit Digit Rotation to the Right +NEC_78K_0_rol4, // Rotate Left Digit Digit Rotation to the Left + +NEC_78K_0_adjba, // Decimal Adjust Register for Addition Decimal Adjustment of Addition Result +NEC_78K_0_adjbs, // Decimal Adjust Register for Subtraction Decimal Adjustment of Subtraction Result + +NEC_78K_0_mov1, // Move Single Bit 1 Bit Data Transfer +NEC_78K_0_and1, // And Single Bit 1 Bit Data Logical Product +NEC_78K_0_or1, // Or Single Bit 1 Bit Data Logical Sum +NEC_78K_0_xor1, // Exclusive Or Single Bit 1 Bit Data Exclusive Logical Sum +NEC_78K_0_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set +NEC_78K_0_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear +NEC_78K_0_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation + +NEC_78K_0_call, // Call Subroutine Call (16 Bit Direct) +NEC_78K_0_callf, // Call Flag Subroutine Call (11 Bit Direct Specification) +NEC_78K_0_callt, // Call Table Subroutine Call (Refer to the Call Table) +NEC_78K_0_brk, // Break Software Vectored Interrupt +NEC_78K_0_ret, // Return Return from Subroutine +NEC_78K_0_retb, // Return from Interrupt Return from Hardware Vectored Interrupt +NEC_78K_0_reti, // Return from Break Return from Software Vectored Interrupt + +NEC_78K_0_push, // Push +NEC_78K_0_pop, // Pop + +NEC_78K_0_br, // Branch Unconditional Branch +NEC_78K_0_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1) +NEC_78K_0_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0) +NEC_78K_0_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1) +NEC_78K_0_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0) +NEC_78K_0_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1) +NEC_78K_0_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0) +NEC_78K_0_btclr, // Branch if True and Clear Conditional Branch and Clear by Bit Test (Byte Data Bit = 1) +NEC_78K_0_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1!= 0) + +NEC_78K_0_sel, // Select Register Bank Register Bank Selection + + +NEC_78K_0_nop, // No Operation +NEC_78K_0_EI, // Enable Interrupt +NEC_78K_0_DI, // Disable Interrupt +NEC_78K_0_HALT, // HALT Mode Set +NEC_78K_0_STOP, // Stop Mode Set + + +NEC_78K_0_last + + }; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + NEC_78K_0S_null = 0, // Unknown Operation + NEC_78K_0S_cmp, // Compare Byte Data Comparison + NEC_78K_0S_xor, // Exclusive Or Exclusive Logical Sum of Byte Data + NEC_78K_0S_and, // AND Logical Product of Byte Data + NEC_78K_0S_or, // OR Logical Sum of Byte Data + NEC_78K_0S_add, // ADD Byte Data Addition + NEC_78K_0S_sub, // Subtract Byte Data Subtraction + NEC_78K_0S_addc, // Add with Carry Addition of Byte Data with Carry + NEC_78K_0S_subc, // Subtract with Carry Subtraction of Byte Data with Carry + NEC_78K_0S_subw, // Subtract Word Data Subtraction + NEC_78K_0S_addw, // Add Word Data Addition + NEC_78K_0S_cmpw, // Compare Word Data Comparison + NEC_78K_0S_inc, // Increment Byte Data Increment + NEC_78K_0S_dec, // Decrement Byte Data Decrement + NEC_78K_0S_incw, // Increment Word Data Increment + NEC_78K_0S_decw, // Decrement Word Data Decrement + NEC_78K_0S_ror, // Rotate Right Byte Data Rotation to the Right + NEC_78K_0S_rol, // Rotate Left Byte Data Rotation to the Left + NEC_78K_0S_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry + NEC_78K_0S_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry + NEC_78K_0S_call, // CALL Subroutine Call (16 Bit Direct) + NEC_78K_0S_callt, // Call Table Subroutine Call (Call Table Reference) + NEC_78K_0S_ret, // Return from Subroutine + NEC_78K_0S_reti, // Return from Interrupt / Return from Hardware Vectored Interrupt + NEC_78K_0S_mov, // Move Byte Data Transfer + NEC_78K_0S_xch, // Exchange Byte Data Exchange + NEC_78K_0S_xchw, // Exchange Word Data Exchange + NEC_78K_0S_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set + NEC_78K_0S_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear + NEC_78K_0S_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation + NEC_78K_0S_push, // Push + NEC_78K_0S_pop, // Pop + NEC_78K_0S_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer + NEC_78K_0S_br, // Unconditional Branch + NEC_78K_0S_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1) + NEC_78K_0S_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0) + NEC_78K_0S_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1) + NEC_78K_0S_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0) + NEC_78K_0S_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1) + NEC_78K_0S_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0) + NEC_78K_0S_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1 != 0) + NEC_78K_0S_nop, // No Operation + NEC_78K_0S_EI, // Enable Interrupt + NEC_78K_0S_DI, // Disable Interrupt + NEC_78K_0S_HALT, // HALT Mode Set + NEC_78K_0S_STOP, // Stop Mode Set + NEC_78K_0S_last +}; + + + + +// The instruction types (``itype''s) +// M16C/60, M16C/20, M16C/Tiny and M16C/80 CPUs implements. + +enum m16c_itype_t +{ + M16C_null=0, // Unknown Operation + M16C_abs, // Absolute value + M16C_adc, // Add with carry + M16C_adcf, // Add carry flag + M16C_add, // Add without carry + M16C_adjnz, // Add & conditional jump + M16C_and, // Logically AND + M16C_band, // Logically AND bits + M16C_bclr, // Clear bit + M16C_bmcnd, // Conditional bit transfer + // conds (order is important; don't shuffle) (same order as the enum am_cnd8_t in m16c.hpp) + M16C_bmgeu, // Conditional bit transfer: Equal to or greater than; C == 1 + M16C_bmgtu, // Conditional bit transfer: Greater than + M16C_bmeq, // Conditional bit transfer: Equal to; Z == 1 + M16C_bmn, // Conditional bit transfer: Negative + M16C_bmle, // Conditional bit transfer: Equal to or smaller than (signed) + M16C_bmo, // Conditional bit transfer: Overflow; O == 1 + M16C_bmge, // Conditional bit transfer: Equal to or greater than (signed) + M16C_bmltu, // Conditional bit transfer: Smaller than; C == 0 + M16C_bmleu, // Conditional bit transfer: Equal to or smaller than + M16C_bmne, // Conditional bit transfer: Not equal; Z == 0 + M16C_bmpz, // Conditional bit transfer: Positive or zero + M16C_bmgt, // Conditional bit transfer: Greater than (signed) + M16C_bmno, // Conditional bit transfer: No overflow; O == 0 + M16C_bmlt, // Conditional bit transfer: Smaller than (signed) + // --- + M16C_bnand, // Logically AND inverted bits + M16C_bnor, // Logically OR inverted bits + M16C_bnot, // Invert bit + M16C_bntst, // Test inverted bit + M16C_bnxor, // Exclusive OR inverted bits + M16C_bor, // Logically OR bits + M16C_brk, // Debug interrupt + M16C_bset, // Set bit + M16C_btst, // Test bit + M16C_btstc, // Test bit & clear + M16C_btsts, // Test bit & set + M16C_bxor, // Exclusive OR bits + M16C_cmp, // Compare + M16C_dadc, // Decimal add with carry + M16C_dadd, // Decimal add without carry + M16C_dec, // Decrement + M16C_div, // Signed divide + M16C_divu, // Unsigned divide + M16C_divx, // Signed divide (extension) + M16C_dsbb, // Decimal subtract with borrow + M16C_dsub, // Decimal subtract without borrow + M16C_enter, // Build stack frame + M16C_exitd, // Deallocate stack frame + M16C_exts, // Extend sign + M16C_fclr, // Clear flag register bit + M16C_fset, // Set flag register bit + M16C_inc, // Increment + M16C_int, // Interrupt by INT instruction + M16C_into, // Interrupt on overflow + M16C_jcnd, // Jump on condition + // conds (order is important; don't shuffle) (same order as the enum am_cnd8_t in m16c.hpp) + M16C_jgeu, // Conditional jump: Equal to or greater than; C == 1 + M16C_jgtu, // Conditional jump: Greater than + M16C_jeq, // Conditional jump: Equal to; Z == 1 + M16C_jn, // Conditional jump: Negative + M16C_jle, // Conditional jump: Equal to or smaller than (signed) + M16C_jo, // Conditional jump: Overflow; O == 1 + M16C_jge, // Conditional jump: Equal to or greater than (signed) + M16C_jltu, // Conditional jump: Smaller than; C == 0 + M16C_jleu, // Conditional jump: Equal to or smaller than + M16C_jne, // Conditional jump: Not equal; Z == 0 + M16C_jpz, // Conditional jump: Positive or zero + M16C_jgt, // Conditional jump: Greater than (signed) + M16C_jno, // Conditional jump: No overflow; O == 0 + M16C_jlt, // Conditional jump: Smaller than (signed) + // --- + M16C_jmp, // Unconditional jump + M16C_jmpi, // Jump indirect + M16C_jmps, // Jump to special page + M16C_jsr, // Subroutine call + M16C_jsri, // Indirect subroutine call + M16C_jsrs, // Special page subroutine call + M16C_ldc, // Transfer to control register + M16C_ldctx, // Restore context + M16C_lde, // Transfer from extended data area + M16C_ldintb, // Load to INTB register + M16C_ldipl, // Set interrupt enable level + M16C_mov, // Transfer + M16C_mova, // Transfer effective address + M16C_movhh, // Xfer 4-bit data: src(8-bits)'s 4 hi bits -> dest(8-bits)'s 4 hi bits. + M16C_movhl, // Xfer 4-bit data: src(8-bits)'s 4 hi bits -> dest(8-bits)'s 4 lo bits. + M16C_movlh, // Xfer 4-bit data: src(8-bits)'s 4 lo bits -> dest(8-bits)'s 4 hi bits. + M16C_movll, // Xfer 4-bit data: src(8-bits)'s 4 lo bits -> dest(8-bits)'s 4 lo bits. + M16C_mul, // Signed multiply + M16C_mulu, // Unsigned multiply + M16C_neg, // Two's complement + M16C_nop, // No operation + M16C_not, // Invert all bits + M16C_or, // Logically OR + M16C_pop, // Restore register/memory + M16C_popc, // Restore control register + M16C_popm, // Restore multiple registers + M16C_push, // Save register/memory/immediate data + M16C_pusha, // Save effective address + M16C_pushc, // Save control register + M16C_pushm, // Save multiple registers + M16C_reit, // Return from interrupt + M16C_rmpa, // Calculate sum-of-products + M16C_rolc, // Rotate left with carry + M16C_rorc, // Rotate right with carry + M16C_rot, // Rotate + M16C_rts, // Return from subroutine + M16C_sbb, // Subtract with borrow + M16C_sbjnz, // Subtract & conditional jump + M16C_sha, // Shift arithmetic + M16C_shl, // Shift logical + M16C_smovb, // Transfer string backward + M16C_smovf, // Transfer string forward + M16C_sstr, // Store string + M16C_stc, // Transfer from control register + M16C_stctx, // Save context + M16C_ste, // Store to extended data area + M16C_stnz, // Conditional transfer: store on not zero + M16C_stz, // Conditional transfer: store on zero + M16C_stzx, // Conditional transfer: store on zero extension + M16C_sub, // Subtract without borrow + M16C_tst, // Test + M16C_und, // Interrupt for undefined instruction + M16C_wait, // Wait + M16C_xchg, // Exchange + M16C_xor, // Exclusive OR + + // M16C/80 specifics + M16C_addx, + M16C_bitindex, + M16C_brk2, // Debugger-only interrupt + M16C_clip, + M16C_cmpx, + M16C_extz, + M16C_freit, // Fast return from interrupt + M16C_indexb, + M16C_indexbd, + M16C_indexbs, + M16C_indexl, + M16C_indexld, + M16C_indexls, + M16C_indexw, + M16C_indexwd, + M16C_indexws, + M16C_max, + M16C_min, + M16C_movx, + M16C_mulex, + M16C_sccnd, + // conds (order is important; don't shuffle) (same order as the enum am_cnd8_t in m16c.hpp) + M16C_scgeu, // Conditional store: Equal to or greater than; C == 1 + M16C_scgtu, // Conditional store: Greater than + M16C_sceq, // Conditional store: Equal to; Z == 1 + M16C_scn, // Conditional store: Negative + M16C_scle, // Conditional store: Equal to or smaller than (signed) + M16C_sco, // Conditional store: Overflow; O == 1 + M16C_scge, // Conditional store: Equal to or greater than (signed) + M16C_scltu, // Conditional store: Smaller than; C == 0 + M16C_scleu, // Conditional store: Equal to or smaller than + M16C_scne, // Conditional store: Not equal; Z == 0 + M16C_scpz, // Conditional store: Positive or zero + M16C_scgt, // Conditional store: Greater than (signed) + M16C_scno, // Conditional store: No overflow; O == 0 + M16C_sclt, // Conditional store: Smaller than (signed) + // --- + M16C_scmpu, + M16C_sin, + M16C_smovu, + M16C_sout, + M16C_subx, + + // M32C specifics + M16C_shanc, // Shift arithmetic no carry + M16C_shlnc, // Shift logical no carry + + // R32C specifics + M16C_addf, + M16C_adsf, + M16C_cmpf, + M16C_cnvif, + M16C_divf, + M16C_ediv, + M16C_edivu, + M16C_edivx, + M16C_emul, + M16C_emulu, + M16C_exiti, + M16C_index1, + M16C_index2, + M16C_mulf, + M16C_mulx, + M16C_round, + M16C_stop, + M16C_subf, + M16C_suntil, + M16C_swhile, + + M16C_last +}; + + + + + + + +// exporting the ins.cpp array + +// m32r instructions declaration +enum +{ + m32r_null = 0, // Null instruction + m32r_add, // Add + m32r_add3, // Add 3-operand + m32r_addi, // Add immediate + m32r_addv, // Add with overflow checking + m32r_addv3, // Add 3-operand with overflow checking + m32r_addx, // Add with carry + m32r_and, // AND + m32r_and3, // AND 3-operand + m32r_bc, // Branch on C-bit + m32r_beq, // Branch on equal + m32r_beqz, // Branch on equal zero + m32r_bgez, // Branch on greater than or equal zero + m32r_bgtz, // Branch on greater than zero + m32r_bl, // Branch and link + m32r_blez, // Branch on less than or equal zero + m32r_bltz, // Branch on less than zero + m32r_bnc, // Branch on not C-bit + m32r_bne, // Branch on not equal + m32r_bnez, // Branch on not equal zero + m32r_bra, // Branch + m32r_cmp, // Compare + m32r_cmpi, // Compare immediate + m32r_cmpu, // Compare unsigned + m32r_cmpui, // Compare unsigned immediate + m32r_div, // Divide + m32r_divu, // Divide unsigned + m32r_jl, // Jump and link + m32r_jmp, // Jump + m32r_ld, // Load + m32r_ld24, // Load 24-bit immediate + m32r_ldb, // Load byte + m32r_ldh, // Load halfword + m32r_ldi, // Load immediate + m32r_ldub, // Load unsigned byte + m32r_lduh, // Load unsigned halfword + m32r_lock, // Load locked + m32r_machi, // Multiply-accumulate high-order halfwords + m32r_maclo, // Multiply-accumulate low-order halfwords + m32r_macwhi, // Multiply-accumulate word and high-order halfword + m32r_macwlo, // Multiply-accumulate word and low-order halfword + m32r_mul, // Multiply + m32r_mulhi, // Multiply high-order halfwords + m32r_mullo, // Multiply low-order halfwords + m32r_mulwhi, // Multiply word high-order halfwords + m32r_mulwlo, // Multiply word low-order halfwords + m32r_mv, // Move register + m32r_mvfachi, // Move from accumulator high-order word + m32r_mvfaclo, // Move from accumulator low-order word + m32r_mvfacmi, // Move from accumulator middle-order word + m32r_mvfc, // Move from control register + m32r_mvtachi, // Move to accumulator high-order word + m32r_mvtaclo, // Move to accumulator low-order word + m32r_mvtc, // Move to control register + m32r_neg, // Negate + m32r_nop, // No operation + m32r_not, // Logical NOT + m32r_or, // OR + m32r_or3, // OR 3-operand + m32r_push, // Push, mnem for st reg, @-sp + m32r_pop, // Pop, mnem for ld reg, @sp+ + m32r_rac, // Round accumulator + m32r_rach, // Round accumulator halfword + m32r_rem, // Remainder + m32r_remu, // Remainder unsigned + m32r_rte, // Return from EIT + m32r_seth, // Set high-order 16-bit + m32r_sll, // Shift left logical + m32r_sll3, // Shift left logical 3-operand + m32r_slli, // Shift left logical immediate + m32r_sra, // Shirt right arithmetic + m32r_sra3, // Shirt right arithmetic 3-operand + m32r_srai, // Shirt right arithmetic immediate + m32r_srl, // Shift right logical + m32r_srl3, // Shift right logical 3-operand + m32r_srli, // Shift right logical immediate + m32r_st, // Store + m32r_stb, // Store byte + m32r_sth, // Store halfword + m32r_sub, // Substract + m32r_subv, // Substract with overflow checking + m32r_subx, // Substract with borrow + m32r_trap, // Trap + m32r_unlock, // Store unlocked + m32r_xor, // Exclusive OR + m32r_xor3, // Exclusive OR 3-operand + + // M32RX : + + m32rx_bcl, + m32rx_bncl, + m32rx_cmpeq, + m32rx_cmpz, + m32rx_divh, + m32rx_jc, + m32rx_jnc, + m32rx_machi, // 'machi' 3-operand + m32rx_maclo, // 'maclo' 3-operand + m32rx_macwhi, // 'macwhi' 3-operand + m32rx_macwlo, // 'macwlo' 3-operand + m32rx_mulhi, // 'mulhi' 3-operand + m32rx_mullo, // 'mullo' 3-operand + m32rx_mulwhi, // 'mulwhi' 3-operand + m32rx_mulwlo, // 'mulwlo' 3-operand + m32rx_mvfachi, // 'mvfachi' 3-operand + m32rx_mvfaclo, // 'mvfaclo' 3-operand + m32rx_mvfacmi, // 'mvfacmi' 3-operand + m32rx_mvtachi, // 'mvtachi' 3-operand + m32rx_mvtaclo, // 'mvtaclo' 3-operand + m32rx_rac, // 'rac' 3 operand + m32rx_rach, // 'rach' 3 operand + m32rx_satb, + m32rx_sath, + m32rx_sat, + m32rx_pcmpbz, + m32rx_sadd, + m32rx_macwu1, + m32rx_msblo, + m32rx_mulwu1, + m32rx_maclh1, + m32rx_sc, + m32rx_snc, + +// Floating point + m32r_fadd, // Floating-point add + m32r_fsub, // Floating-point subtract + m32r_fmul, // Floating-point multiply + m32r_fdiv, // Floating-point divede + m32r_fmadd, // Floating-point multiply and add + m32r_fmsub, // Floating-point multiply and subtract + m32r_itof, // Integer to float + m32r_utof, // Unsigned integer to float + m32r_ftoi, // Float to integer + m32r_ftos, // Float to short + m32r_fcmp, // Floating-point compare + m32r_fcmpe, // Floating-point compare with exeption if unordered +// Bit Operation Instructions + m32r_bset, // Bit set + m32r_bclr, // Bit clear + m32r_btst, // Bit test + m32r_setpsw, // Set PSW + m32r_clrpsw, // Clear PSW + + m32r_last +}; + + + + + +enum +{ + m740_null = 0, // null instruction + m740_adc, // add with carry + m740_and, // logical and + m740_asl, // arithmetic shift left + m740_bbc, // branch on bit clear + m740_bbs, // branch on bit set + m740_bcc, // branch on carry clear + m740_bcs, // branch on carry set + m740_beq, // branch on equal + m740_bit, // test bit in memory with accumulator + m740_bmi, // branch on result minus + m740_bne, // branch on not equal + m740_bpl, // branch on result plus + m740_bra, // branch always + m740_brk, // force break + m740_bvc, // branch on overflow clear + m740_bvs, // branch on overflow set + m740_clb, // clear bit + m740_clc, // clear carry flag + m740_cld, // clear decimal mode + m740_cli, // clear interrupt disable status + m740_clt, // clear transfer flag + m740_clv, // clear overflow flag + m740_cmp, // compare + m740_com, // complement + m740_cpx, // compare memory and index register X + m740_cpy, // compare memory and index register Y + m740_dec, // decrement by one + m740_dex, // decrement index register X by one + m740_dey, // decrement index register Y by one + m740_div, // divide memory by accumulator + m740_eor, // exclusive or memory with accumulator + m740_inc, // increment by one + m740_inx, // increment index register X by one + m740_iny, // increment index register Y by one + m740_jmp, // jump + m740_jsr, // jump to subroutine + m740_lda, // load accumulator with memory + m740_ldm, // load immediate data to memory + m740_ldx, // load index register X from memory + m740_ldy, // load index register Y from memory + m740_lsr, // logical shift right + m740_mul, // multiply accumulator and memory + m740_nop, // no operation + m740_ora, // or memory with accumulator + m740_pha, // push accumulator on stack + m740_php, // push processor status on stack + m740_pla, // pull accumulator from stack + m740_plp, // pull processor status from stack + m740_rol, // rotate one bit left + m740_ror, // rotate one bit right + m740_rrf, // rotate right of four bits + m740_rti, // return from interrupt + m740_rts, // return from subroutine + m740_sbc, // subtract with carry + m740_seb, // set bit + m740_sec, // set carry flag + m740_sed, // set decimal mode + m740_sei, // set interrupt disable flag + m740_set, // set transfert flag + m740_sta, // store accumulator in memory + m740_stp, // stop + m740_stx, // store index register X in memory + m740_sty, // store index register Y in memory + m740_tax, // transfert accumulator to index register X + m740_tay, // transfert accumulator to index register Y + m740_tst, // test for negative or zero + m740_tsx, // transfert stack pointer to index register X + m740_txa, // transfert index register X to accumulator + m740_txs, // transfert index register X to stack pointer + m740_tya, // transfert index register Y to accumulator + m740_wit, // wait + + m740_last +}; + + + + + +enum +{ + // 7700 : + + m7700_null = 0, // null instruction + m7700_adc, // addition with carry + m7700_and, // logical AND + m7700_asl, // arithmetic shift left + m7700_bbc, // branch on bit clear + m7700_bbs, // branch on bit set + m7700_bcc, // branch on carry clear + m7700_bcs, // branch on carry set + m7700_beq, // branch on equal + m7700_bmi, // branch on result minus + m7700_bne, // branch on not equal + m7700_bpl, // branch on result plus + m7700_bra, // branch always + m7700_brk, // force break + m7700_bvc, // branch on overflow clear + m7700_bvs, // branch on overflow set + m7700_clb, // clear bit + m7700_clc, // clear carry flag + m7700_cli, // clear interrupt disable status + m7700_clm, // clear m flag + m7700_clp, // clear processor status + m7700_clv, // clear overflow flag + m7700_cmp, // compare + m7700_cpx, // compare memory and index register X + m7700_cpy, // compare memory and index register Y + m7700_dec, // decrement by one + m7700_dex, // decrement index register X by one + m7700_dey, // decrement index register Y by one + m7700_div, // divide + m7700_eor, // exclusive OR memory with accumulator + m7700_inc, // increment by one + m7700_inx, // increment index register X by one + m7700_iny, // increment index register Y by one + m7700_jmp, // jump + m7700_jsr, // jump to subroutine + m7700_lda, // load accumulator from memory + m7700_ldm, // load immediate to memory + m7700_ldt, // load immediate to data bank register + m7700_ldx, // load index register X from memory + m7700_ldy, // load index register Y from memory + m7700_lsr, // logical shift right + m7700_mpy, // multiply + m7700_mvn, // move negative + m7700_mvp, // move positive + m7700_nop, // no operation + m7700_ora, // OR memory with accumulator + m7700_pea, // push effective address + m7700_pei, // push effective indirect address + m7700_per, // push effective program counter relative address + m7700_pha, // push accumulator A on stack + m7700_phb, // push accumulator B on stack + m7700_phd, // push direct page register on stack + m7700_phg, // push program bank register on stack + m7700_php, // push processor status on stack + m7700_pht, // push data bank register on stack + m7700_phx, // push index register X on stack + m7700_phy, // push index register Y on stack + m7700_pla, // pull accumulator A from stack + m7700_plb, // pull accumulator B from stack + m7700_pld, // pull direct page register from stack + m7700_plp, // pull processor status from stack + m7700_plt, // pull data bank register from stack + m7700_plx, // pull index register X from stack + m7700_ply, // pull index register Y from stack + m7700_psh, // push + m7700_pul, // pull + m7700_rla, // rotate left accumulator A + m7700_rol, // rotate one bit left + m7700_ror, // rotate one bit right + m7700_rti, // return from interrupt + m7700_rtl, // return from subroutine long + m7700_rts, // return from subroutine + m7700_sbc, // subtract with carry + m7700_seb, // set bit + m7700_sec, // set carry flag + m7700_sei, // set interrupt disable status + m7700_sem, // set m flag + m7700_sep, // set processor status + m7700_sta, // store accumulator in memory + m7700_stp, // stop + m7700_stx, // store index register X in memory + m7700_sty, // store index register Y in memory + m7700_tad, // transfer accumulator A to direct page register + m7700_tas, // transfer accumulator A to stack pointer + m7700_tax, // transfer accumulator A to index register X + m7700_tay, // transfer accumulator A to index register Y + m7700_tbd, // transfer accumulator B to direct page register + m7700_tbs, // transfer accumulator B to stack pointer + m7700_tbx, // transfer accumulator B to index register X + m7700_tby, // transfer accumulator B to index register Y + m7700_tda, // transfer direct page register to accumulator A + m7700_tdb, // transfer direct page register to accumulator B + m7700_tsa, // transfer stack pointer to accumulator A + m7700_tsb, // transfer stack pointer to accumulator B + m7700_tsx, // transfer stack pointer to index register X + m7700_txa, // transfer index register X to accumulator A + m7700_txb, // transfer index register X to accumulator B + m7700_txs, // transfer index register X to stack pointer + m7700_txy, // transfer index register X to Y + m7700_tya, // transfer index register Y to accumulator A + m7700_tyb, // transfer index register Y to accumulator B + m7700_tyx, // transfer index register Y to X + m7700_wit, // wait + m7700_xab, // exchange accumulator A and B + + // 7750 : + + m7750_asr, // arithmetic shift right + m7750_divs, // divide with sign + m7750_exts, // extention with sign + m7750_extz, // extention zero + m7750_mpys, // multiply with sign + + m7700_last +}; + + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * MITSUBISHI 7900 Family + */ + + + +enum +{ +m7900_null = 0, // Unknown Operation + + +m7900_abs, // ABSolute +m7900_absd, // ABSolute at Double-word + +m7900_adc, // ADd with Carry +m7900_adcb, // ADd with Carry at Byte +m7900_adcd, // ADd with Carry at Double-word + +m7900_add, // Addition + +m7900_addb, // ADD at Byte +m7900_addd, // ADD at Double-word +m7900_addm, // ADD immediate and Memory +m7900_addmb, // ADD immediate and Memory at Byte +m7900_addmd, // ADD immediate and Memory at Double-word +m7900_adds, // ADD Stack pointer and immediate +m7900_addx, // ADD index register X and immediate +m7900_addy, // ADD index register Y and immediate + +m7900_and, // Logical AND +m7900_andb, // logical AND between immediate (Byte) + +m7900_andm, // logical AND between immediate value and Memory +m7900_andmb, // logical AND between immediate value and Memory (Byte) +m7900_andmd, // logical AND between immediate value and Memory (Double word) + +m7900_asl, // Arithmetic Shift to Left +m7900_asln, // Arithmetic Shift to Left by n bits +m7900_asldn, // Arithmetic Shift to Left by n bits (Double word) + + +m7900_asr, // Arithmeticshift to the right +m7900_asrn, // Arithmetic Shift to Right by n bits +m7900_asrdn, // Arithmetic Shift to Right by n bits (Double word) + +m7900_bbc, // Branch on Bit Clear +m7900_bbcb, // Branch on Bit Clear (Byte) +m7900_bbs, // Branch on Bit Set +m7900_bbsb, // Branch on Bit Set (Byte) + +m7900_bcc, // Branch on Carry Clear +m7900_bcs, // Branch on Carry Set +m7900_beq, // Branch on EQual +m7900_bge, // Branch on Greater or Equal +m7900_bgt, // Branch on Greater Than +m7900_bgtu, // Branch on Greater Than with Unsign +m7900_ble, // Branch on Less or Equal +m7900_bleu, // Branch on Less Equal with Unsign +m7900_blt, // Branch on Less Than +m7900_bmi, // Branch on result MInus +m7900_bne, // Branch on Not Equal +m7900_bpl, // Branch on result PLus +m7900_bra, // BRanch Always +m7900_bral, // BRanch Always + +m7900_brk, // force BReaK + +m7900_bsc, // Branch on Single bit Clear +m7900_bsr, // Branch to SubRoutine +m7900_bss, // Branch on Single bit Set + +m7900_bvc, // Branch on oVerflow Clear +m7900_bvs, // Branch on oVerflow Set + +m7900_cbeq, // Compare immediate and Branch on EQual +m7900_cbeqb, // Compare immediate and Branch on EQual at Byte +m7900_cbne, // Compare immediate and Branch on Not Equal +m7900_cbneb, // Compare immediate and Branch on Not Equal at Byte + +m7900_clc, // CLear Carry flag +m7900_cli, // CLear Interrupt disable status +m7900_clm, // CLear M flag +m7900_clp, // CLear Processor status + +m7900_clr, // CLeaR accumulator +m7900_clrb, // CLeaR accumulator at Byte +m7900_clrm, // CLeaR Memory +m7900_clrmb, // CLeaR Memory at Byte +m7900_clrx, // CLeaR index register X +m7900_clry, // CLeaR index register Y + +m7900_clv, // CLear oVerflow flag + +m7900_cmp, // CoMPare +m7900_cmpb, // CoMPare at Byte +m7900_cmpd, // CoMPare at Double-word +m7900_cmpm, // CoMPare immediate with Memory +m7900_cmpmb, // CoMPare immediate with Memory at Byte +m7900_cmpmd, // CoMPare immediate with Memory at Double-word + +m7900_cpx, // ComPare memory and index register X +m7900_cpy, // ComPare memory and index register Y + +m7900_debne, // DEcrement memory and Branch on Not Equal + +m7900_dec, // DECrement by one +m7900_dex, // DEcrement index register X by one +m7900_dey, // DEcrement index register Y by one + +m7900_div, // DIVide unsigned +m7900_divs, // DIVide with Sign +m7900_dxbne, // Decrement index register X and Branch on Not Equal +m7900_dybne, // Decrement index register Y and Branch on Not Equal + +m7900_eor, // Exclusive OR memory with accumulator +m7900_eorb, // Exclusive OR immediate with accumulator at Byte +m7900_eorm, // Exclusive OR immediate with Memory +m7900_eormb, // Exclusive OR immediate with Memory at Byte +m7900_eormd, // Exclusive OR immediate with Memory at Double-word + +m7900_exts, // EXTension Sign +m7900_extsd, // EXTension Sign at Double-word +m7900_extz, // EXTension Zero +m7900_extzd, // EXTension Zero at Double-word + +m7900_inc, // INCrement by one +m7900_inx, // INcrement index register X by one +m7900_iny, // INcrement index register y by one + +m7900_jmp, // Jump +m7900_jmpl, // Jump + +m7900_jsr, // Jump to SubRoutine +m7900_jsrl, // Jump to SubRoutine + + +m7900_lda, // LoaD Accumulator from memory +m7900_ldab, // LoaD Accumulator from memory at Byte +m7900_ldad, // LoaD Accumulator from memory at Double-word +m7900_lddn, // LoaD immediate to Direct page register n + +m7900_ldt, // LoaD immediate to DaTa bank register +m7900_ldx, // LoaD index register X from memory +m7900_ldxb, // LoaD index register X from memory at Byte +m7900_ldy, // LoaD index register Y from memory +m7900_ldyb, // LoaD index register Y from memory at Byte + +m7900_lsr, // Logical Shift Right +m7900_lsrn, // Logical n bits Shift Right +m7900_lsrdn, // Logical n bits Shift Right at Double-word + +m7900_movm, // MOVe Memory to memory +m7900_movmb, // MOVe Memory to memory at Byte +m7900_movr, // MOVe Repeat memory to memory +m7900_movrb, // MOVe Repeat memory to memory at Byte + +m7900_mpy, // MultiPlY +m7900_mpys, // MultiPlY with Sign + +m7900_mvn, // MoVe Negative +m7900_mvp, // MoVe Positive + +m7900_neg, // NEGative +m7900_negd, // NEGative at Double-word + +m7900_nop, // No OPeration + +m7900_ora, // OR memory with Accumulator +m7900_orab, // OR immediate with Accumulator at Byte +m7900_oram, // OR immediAte with Memory +m7900_oramb, // OR immediAte with Memory at Byte +m7900_oramd, // OR immediAte with Memory at Double-word + +m7900_pea, // Push Effective Address +m7900_pei, // Push Effective Indirect address +m7900_per, // Push Effective program counter Relative address +m7900_pha, // PusH accumulator A on stack +m7900_phb, // PusH accumulator B on stack +m7900_phd, // PusH Direct page register on stack +m7900_phdn, // PusH Direct page register n on stack +m7900_phg, // PusH proGram bank register on stack + +m7900_phldn, // PusH dpr n to stack and Load immediate to Dpr n + +m7900_php, // PusH Processor status on stack +m7900_pht, // PusH daTa bank register on stack +m7900_phx, // PusH index register X on stack +m7900_phy, // PusH index register Y on stack + +m7900_pla, // PuLl accumulator A from stack +m7900_plb, // PuLl accumulator B from stack +m7900_pld, // PuLl Direct page register from stack +m7900_pldn, // PuLl Direct page register n from stack +m7900_plp, // PuLl Processor status from stack +m7900_plt, // PuLl daTa bank register from stack +m7900_plx, // PuLl index register X from stack +m7900_ply, // PuLl index register Y from stack + +m7900_psh, // PuSH +m7900_pul, // PuLl + +m7900_rla, // Rotate Left accumulator A +m7900_rmpa, // Repeat Multiply and Accumulate + +m7900_rol, // ROtate one bit Left +m7900_roln, // n bits ROtate Left + +m7900_roldn, // n bits ROtate Left at Double-word + +m7900_ror, // ROtate one bit Right +m7900_rorn, // n bits ROtate Right +m7900_rordn, // n bits ROtate Right at Double-word + +m7900_rti, // Return from Interrupt +m7900_rtl, // ReTurn from subroutine Long +m7900_rtld, // ReTurn from subroutine Long and pull Direct page register n +m7900_rts, // ReTurn from Subroutine +m7900_rtsdn, // ReTurn from Subroutine and pull Direct page register n + + +m7900_sbc, // SuBtract with Carry +m7900_sbcb, // SuBtract with Carry at Byte +m7900_sbcd, // SuBtract with Carry at Double-word + + +m7900_sec, // SEt Carry flag +m7900_sei, // SEt Interrupt disable status +m7900_sem, // SEt M flag +m7900_sep, // SEt Processor status + + +m7900_sta, // STore Accumulator in memory +m7900_stab, // STore Accumulator in memory at Byte +m7900_stad, // STore Accumulator in memory at Double-word + + +m7900_stp, // SToP +m7900_stx, // STore index register X in memory +m7900_sty, // STore index register Y in memory + +m7900_sub, // SUBtract +m7900_subb, // SUBtract at Byte +m7900_subd, // SUBtract at Double-word +m7900_subm, // SUBtract immediate from Memory +m7900_submb, // SUBtract immediate from Memory at Byte +m7900_submd, // SUBtract immediate from Memory at Double-word +m7900_subs, // SUBtract Stack pointer +m7900_subx, // SUBtract immediate from index register X +m7900_suby, // SUBtract immediate from index register Y + + + +m7900_tadn, // Transfer accumulator A to Direct page register n + + +m7900_tas, // Transfer accumulator A to Stack pointer +m7900_tax, // Transfer accumulator A to index register X +m7900_tay, // Transfer accumulator A to index register Y + +m7900_tbdn, // Transfer accumulator B to Direct page register n + +m7900_tbs, // Transfer accumulator B to Stack pointer +m7900_tbx, // Transfer accumulator B to index register X +m7900_tby, // Transfer accumulator B to index register Y + +m7900_tdan, // Transfer Direct page register n to accumulator A +m7900_tdbn, // Transfer Direct page register n to accumulator B + +m7900_tds, // Transfer Direct page register to Stack pointer + + +m7900_tsa, // Transfer Stack pointer to accumulator A +m7900_tsb, // Transfer Stack pointer to accumulator B +m7900_tsd, // Transfer Stack pointer to Direct page register +m7900_tsx, // Transfer Stack pointer to index register X +m7900_txa, // Transfer index register X to accumulator A +m7900_txb, // Transfer index register X to accumulator B +m7900_txs, // Transfer index register X to Stack pointer +m7900_txy, // Transfer index register X to Y +m7900_tya, // Transfer index register Y to accumulator A +m7900_tyb, // Transfer index register Y to accumulator B +m7900_tyx, // Transfer index register Y to X + +m7900_wit, // WaIT + +m7900_xab, // eXchange accumulator A and B + +m7900_last // + + }; + + + + +enum +{ + st9_null = 0, // Unknown Operation. + st9_ld, // Load. + st9_ldw, // Load word. + st9_ldpp, // Load (using CSR) => (using CSR). + st9_ldpd, // Load (using DPRx) => (using CSR). + st9_lddp, // Load (using CSR) => (using DPRx). + st9_lddd, // Load (using DPRx) => (using DPRx). + st9_add, // Add. + st9_addw, // Add Word. + st9_adc, // Add with Carry. + st9_adcw, // Add Word with Carry. + st9_sub, // Substract. + st9_subw, // Substract Word. + st9_sbc, // Substract with Carry. + st9_sbcw, // Substract Word with Carry. + st9_and, // Logical AND. + st9_andw, // Logical Word AND. + st9_or, // Logical OR. + st9_orw, // Logical Word OR. + st9_xor, // Logical Exclusive OR. + st9_xorw, // Logical Word Exclusive OR. + st9_cp, // Compare. + st9_cpw, // Compare Word. + st9_tm, // Test under Mask. + st9_tmw, // Test Word under Mask. + st9_tcm, // Test Complement under Mask. + st9_tcmw, // Test Word Complement under Mask. + st9_inc, // Increment. + st9_incw, // Increment Word. + st9_dec, // Decrement. + st9_decw, // Decrement Word. + st9_sla, // Shift Left Arithmetic. + st9_slaw, // Shift Word Left Arithmetic. + st9_sra, // Shift Right Arithmetic. + st9_sraw, // Shift Word Right Arithmetic. + st9_rrc, // Rotate Right through Carry. + st9_rrcw, // Rotate Word Right through Carry. + st9_rlc, // Rotate Left through Carry. + st9_rlcw, // Rotate Word Left through Carry. + st9_ror, // Rotate Right. + st9_rol, // Rotate Left. + st9_clr, // Clear Register. + st9_cpl, // Complement Register. + st9_swap, // Swap Nibbles. + st9_da, // Decimal ajust. + st9_push, // Push on System Stack. + st9_pushw, // Push Word on System Stack. + st9_pea, // Push Effective Address on System Stack. + st9_pop, // Pop from System Stack. + st9_popw, // Pop Word from System Stack. + st9_pushu, // Push on User Stack. + st9_pushuw, // Push Word on User Stack. + st9_peau, // Push Effective Address on User Stack. + st9_popu, // Pop from User Stack. + st9_popuw, // Pop Word from User Stack. + st9_link, // Move System Stack Pointer upward; support for high-level language. + st9_unlink, // Move System Stack Pointer backward; support for high-level language. + st9_linku, // Move User Stack Pointer upward; support for high-level language. + st9_unlinku, // Move User Stack Pointer backward; support for high-level language. + st9_mul, // Multiply 8x8. + st9_div, // Divide 8x8. + st9_divws, // Divide Word Stepped 32/16. + st9_bset, // Bit Set. + st9_bres, // Bit Reset . + st9_bcpl, // Bit Complement. + st9_btset, // Bit Test and Set. + st9_bld, // Bit Load. + st9_band, // Bit AND. + st9_bor, // Bit OR. + st9_bxor, // Bit XOR. + st9_ret, // Return from Subroutine. + st9_rets, // Inter-segment Return to Subroutine. + st9_iret, // Return from Interrupt. + st9_jrcc, // Jump Relative if Condition ``cc'' is Met. + st9_jpcc, // Jump if Condition ``cc'' is Met. + st9_jp, // Unconditional Jump. + st9_jps, // Unconditional Inter-segment Jump. + st9_call, // Unconditional Call. + st9_calls, // Inter-segment Call to Subroutine. + st9_btjf, // Bit Test and Jump if False. + st9_btjt, // Bit Test and Jump if True. + st9_djnz, // Decrement a Working Register and Jump if Non Zero. + st9_dwjnz, // Decrement a Register Pair and Jump if Non Zero. + st9_cpjfi, // Compare and Jump on False. Otherwise Post Increment. + st9_cpjti, // Compare and Jump on True. Otherwise Post Increment. + st9_xch, // Exchange Registers. + st9_srp, // Set Register Pointer Long (16 working registers). + st9_srp0, // Set Register Pointer 0 (8 LSB working registers). + st9_srp1, // Set Register Pointer 1 (8 MSB working registers). + st9_spp, // Set Page Pointer. + st9_ext, // Sign Extend. + st9_ei, // Enable Interrupts. + st9_di, // Disable Interrupts. + st9_scf, // Set Carry Flag. + st9_rcf, // Reset Carry Flag. + st9_ccf, // Complement Carry Flag. + st9_spm, // Select Extended Memory addressing scheme through CSR Register. + st9_sdm, // Select Extended Memory addressing scheme through DPR Registers. + st9_nop, // No Operation. + st9_wfi, // Stop Program Execution and Wait for the next Enable Interrupt. + st9_halt, // Stop Program Execution until System Reset. + st9_etrap, // Undocumented instruction. + st9_eret, // Undocumented instruction. + st9_ald, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED. + st9_aldw, // PSEUDO INSTRUCTION. SHOULD NEVER BE USED. + st9_last +}; + + + + + +enum +{ + fr_null = 0, // null instruction + + fr_add, // add word data of source register / 4-bit immediate data to destination register + fr_add2, // add 4-bit immediate data to destination register + fr_addc, // add word data of source register and carry bit to destination register + fr_addn, // add word data of source register / immediate data to destination register + fr_addn2, // add immediate data to destination register + fr_sub, // subtract word data in source register from destination register + fr_subc, // subtract word data in source register and carry bit from destination register + fr_subn, // subtract word data in source register from destination register + fr_cmp, // compare word / immediate data in source register and destination register + fr_cmp2, // compare immediate data and destination register + fr_and, // and word data of source register to destination register / data in memory + fr_andh, // and half-word data of source register to data in memory + fr_andb, // and byte data of source register to data in memory + fr_or, // or word data of source register to destination register / data in memory + fr_orh, // or half-word data of source register to data in memory + fr_orb, // or byte data of source register to data in memory + fr_eor, // exclusive or word data of source register to destination register / data in memory + fr_eorh, // exclusive or half-word data of source register to data in memory + fr_eorb, // exclusive or byte data of source register to data in memory + fr_bandl, // and 4-bit immediate data to lower 4 bits of byte data in memory + fr_bandh, // and 4-bit immediate data to higher 4 bits of byte data in memory + fr_borl, // or 4-bit immediate data to lower 4 bits of byte data in memory + fr_borh, // or 4-bit immediate data to higher 4 bits of byte data in memory + fr_beorl, // eor 4-bit immediate data to lower 4 bits of byte data in memory + fr_beorh, // eor 4-bit immediate data to higher 4 bits of byte data in memory + fr_btstl, // test lower 4 bits of byte data in memory + fr_btsth, // test higher 4 bits of byte data in memory + fr_mul, // multiply word data + fr_mulu, // multiply unsigned word data + fr_mulh, // multiply half-word data + fr_muluh, // multiply unsigned half-word data + fr_div0s, // initial setting up for signed division + fr_div0u, // initial setting up for unsigned division + fr_div1, // main process of division + fr_div2, // correction when remainder is 0 + fr_div3, // correction when remainder is 0 + fr_div4s, // correction answer for signed division + fr_lsl, // logical shift to the left direction + fr_lsl2, // logical shift to the left direction + fr_lsr, // logical shift to the right direction + fr_lsr2, // logical shift to the right direction + fr_asr, // arithmetic shift to the right direction + fr_asr2, // arithmetic shift to the right direction + fr_ldi_32, // load immediate 32-bit data to destination register + fr_ldi_20, // load immediate 20-bit data to destination register + fr_ldi_8, // load immediate 8-bit data to destination register + fr_ld, // load word data in memory to register / program status register + fr_lduh, // load half-word data in memory to register + fr_ldub, // load byte data in memory to register + fr_st, // store word data in register / program status register to memory + fr_sth, // store half-word data in register to memory + fr_stb, // store byte data in register to memory + fr_mov, // move word data in source register / program status register to destination register / program status register + fr_jmp, // jump + fr_call, // call subroutine + fr_ret, // return from subroutine + fr_int, // software interrupt + fr_inte, // software interrupt for emulator + fr_reti, // return from interrupt + fr_bra, // branch relative if condition satisfied + fr_bno, // branch relative if condition satisfied + fr_beq, // branch relative if condition satisfied + fr_bne, // branch relative if condition satisfied + fr_bc, // branch relative if condition satisfied + fr_bnc, // branch relative if condition satisfied + fr_bn, // branch relative if condition satisfied + fr_bp, // branch relative if condition satisfied + fr_bv, // branch relative if condition satisfied + fr_bnv, // branch relative if condition satisfied + fr_blt, // branch relative if condition satisfied + fr_bge, // branch relative if condition satisfied + fr_ble, // branch relative if condition satisfied + fr_bgt, // branch relative if condition satisfied + fr_bls, // branch relative if condition satisfied + fr_bhi, // branch relative if condition satisfied + fr_dmov, // move word data from register / address to register / address + fr_dmovh, // move half-word data from register / address to register / address + fr_dmovb, // move byte data from register / address to register / address + fr_ldres, // load word data in memory to resource + fr_stres, // store word data in resource to memory + fr_copop, // coprocessor operation + fr_copld, // load 32-bit data from register to coprocessor register + fr_copst, // store 32-bit data from coprocessor register to register + fr_copsv, // save 32-bit data from coprocessor register to register + fr_nop, // no operation + fr_andccr, // and condition code register and immediate data + fr_orccr, // or condition code register and immediate data + fr_stilm, // set immediate data to interrupt level mask register + fr_addsp, // add stack pointer and immediate data + fr_extsb, // sign extend from byte data to word data + fr_extub, // unsign extend from byte data to word data + fr_extsh, // sign extend from byte data to word data + fr_extuh, // unsigned extend from byte data to word data + fr_ldm0, // load multiple registers + fr_ldm1, // load multiple registers + fr_stm0, // store multiple registers + fr_stm1, // store multiple registers + fr_enter, // enter function + fr_leave, // leave function + fr_xchb, // exchange byte data + fr_last // last instruction +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ +ALPHA_null = 0, // Unknown Operation + +ALPHA_addf, // Add F_floating +ALPHA_addg, // Add G_floating +ALPHA_addl, // Add longword +ALPHA_addl_v, // Add longword with overflow +ALPHA_addq, // Add quadword +ALPHA_addq_v, // Add quadword with overflow +ALPHA_adds, // Add S_floating +ALPHA_addt, // Add T_floating +ALPHA_amask, // Architecture mask +ALPHA_and, // Logical product +ALPHA_beq, // Branch if = zero +ALPHA_bge, // Branch if >= zero +ALPHA_bgt, // Branch if > zero +ALPHA_bic, // Bit clear +ALPHA_bis, // Logical sum +ALPHA_blbc, // Branch if low bit clear +ALPHA_blbs, // Branch if low bit set +ALPHA_ble, // Branch if <= zero +ALPHA_blt, // Branch if < zero +ALPHA_bne, // Branch if != zero +ALPHA_br, // Unconditional branch +ALPHA_bsr, // Branch to subroutine +ALPHA_call_pal, // Trap to PALcode +ALPHA_cmoveq, // CMOVE if = zero +ALPHA_cmovge, // CMOVE if >= zero +ALPHA_cmovgt, // CMOVE if > zero +ALPHA_cmovlbc, // CMOVE if low bit clear +ALPHA_cmovlbs, // CMOVE if low bit set +ALPHA_cmovle, // CMOVE if <= zero +ALPHA_cmovlt, // CMOVE if < zero +ALPHA_cmovne, // CMOVE if != zero +ALPHA_cmpbge, // Compare byte +ALPHA_cmpeq, // Compare signed quadword equal +ALPHA_cmpgeq, // Compare G_floating equal +ALPHA_cmpgle, // Compare G_floating less than or equal +ALPHA_cmpglt, // Compare G_floating less than +ALPHA_cmple, // Compare signed quadword less than or equal +ALPHA_cmplt, // Compare signed quadword less than +ALPHA_cmpteq, // Compare T_floating equal +ALPHA_cmptle, // Compare T_floating less than or equal +ALPHA_cmptlt, // Compare T_floating less than +ALPHA_cmptun, // Compare T_floating unordered +ALPHA_cmpule, // Compare unsigned quadword less than or equal +ALPHA_cmpult, // Compare unsigned quadword less than +ALPHA_cpys, // Copy sign +ALPHA_cpyse, // Copy sign and exponent +ALPHA_cpysn, // Copy sign negate +ALPHA_ctlz, // Count leading zero +ALPHA_ctpop, // Count population +ALPHA_cttz, // Count trailing zero +ALPHA_cvtdg, // Convert D_floating to G_floating +ALPHA_cvtgd, // Convert G_floating to D_floating +ALPHA_cvtgf, // Convert G_floating to F_floating +ALPHA_cvtgq, // Convert G_floating to quadword +ALPHA_cvtlq, // Convert longword to quadword +ALPHA_cvtqf, // Convert quadword to F_floating +ALPHA_cvtqg, // Convert quadword to G_floating +ALPHA_cvtql, // Convert quadword to longword +ALPHA_cvtqs, // Convert quadword to S_floating +ALPHA_cvtqt, // Convert quadword to T_floating +ALPHA_cvtst, // Convert S_floating to T_floating +ALPHA_cvttq, // Convert T_floating to quadword +ALPHA_cvtts, // Convert T_floating to S_floating +ALPHA_divf, // Divide F_floating +ALPHA_divg, // Divide G_floating +ALPHA_divs, // Divide S_floating +ALPHA_divt, // Divide T_floating +ALPHA_ecb, // Evict cache block +ALPHA_eqv, // Logical equivalence +ALPHA_excb, // Exception barrier +ALPHA_extbl, // Extract byte low +ALPHA_extlh, // Extract longword high +ALPHA_extll, // Extract longword low +ALPHA_extqh, // Extract quadword high +ALPHA_extql, // Extract quadword low +ALPHA_extwh, // Extract word high +ALPHA_extwl, // Extract word low +ALPHA_fbeq, // Floating branch if = zero +ALPHA_fbge, // Floating branch if >= zero +ALPHA_fbgt, // Floating branch if > zero +ALPHA_fble, // Floating branch if <= zero +ALPHA_fblt, // Floating branch if < zero +ALPHA_fbne, // Floating branch if != zero +ALPHA_fcmoveq, // FCMOVE if = zero +ALPHA_fcmovge, // FCMOVE if >= zero +ALPHA_fcmovgt, // FCMOVE if > zero +ALPHA_fcmovle, // FCMOVE if <= zero +ALPHA_fcmovlt, // FCMOVE if < zero +ALPHA_fcmovne, // FCMOVE if != zero +ALPHA_fetch, // Prefetch data +ALPHA_fetch_m, // Prefetch data, modify intent +ALPHA_ftois, // Floating to integer move, S_floating +ALPHA_ftoit, // Floating to integer move, T_floating +ALPHA_implver, // Implementation version +ALPHA_insbl, // Insert byte low +ALPHA_inslh, // Insert longword high +ALPHA_insll, // Insert longword low +ALPHA_insqh, // Insert quadword high +ALPHA_insql, // Insert quadword low +ALPHA_inswh, // Insert word high +ALPHA_inswl, // Insert word low +ALPHA_itoff, // Integer to floating move, F_floating +ALPHA_itofs, // Integer to floating move, S_floating +ALPHA_itoft, // Integer to floating move, T_floating +ALPHA_jmp, // Jump +ALPHA_jsr, // Jump to subroutine +ALPHA_jsr_coroutine,// Jump to subroutine return +ALPHA_lda, // Load address +ALPHA_ldah, // Load address high +ALPHA_ldbu, // Load zero-extended byte +ALPHA_ldwu, // Load zero-extended word +ALPHA_ldf, // Load F_floating +ALPHA_ldg, // Load G_floating +ALPHA_ldl, // Load sign-extended longword +ALPHA_ldl_l, // Load sign-extended longword locked +ALPHA_ldq, // Load quadword +ALPHA_ldq_l, // Load quadword locked +ALPHA_ldq_u, // Load unaligned quadword +ALPHA_lds, // Load S_floating +ALPHA_ldt, // Load T_floating +ALPHA_maxsb8, // Vector signed byte maximum +ALPHA_maxsw4, // Vector signed word maximum +ALPHA_maxub8, // Vector unsigned byte maximum +ALPHA_maxuw4, // Vector unsigned word maximum +ALPHA_mb, // Memory barrier +ALPHA_mf_fpcr, // Move from FPCR +ALPHA_minsb8, // Vector signed byte minimum +ALPHA_minsw4, // Vector signed word minimum +ALPHA_minub8, // Vector unsigned byte minimum +ALPHA_minuw4, // Vector unsigned word minimum +ALPHA_mskbl, // Mask byte low +ALPHA_msklh, // Mask longword high +ALPHA_mskll, // Mask longword low +ALPHA_mskqh, // Mask quadword high +ALPHA_mskql, // Mask quadword low +ALPHA_mskwh, // Mask word high +ALPHA_mskwl, // Mask word low +ALPHA_mt_fpcr, // Move to FPCR +ALPHA_mulf, // Multiply F_floating +ALPHA_mulg, // Multiply G_floating +ALPHA_mull, // Multiply longword +ALPHA_mull_v, // Multiply longword with overflow +ALPHA_mulq, // Multiply quadword +ALPHA_mulq_v, // Multiply quadword with overflow +ALPHA_muls, // Multiply S_floating +ALPHA_mult, // Multiply T_floating +ALPHA_ornot, // Logical sum with complement +ALPHA_perr, // Pixel error +ALPHA_pklb, // Pack longwords to bytes +ALPHA_pkwb, // Pack words to bytes +ALPHA_rc, // Read and clear +ALPHA_ret, // Return from subroutine +ALPHA_rpcc, // Read process cycle counter +ALPHA_rs, // Read and set +ALPHA_s4addl, // Scaled add longword by 4 +ALPHA_s4addq, // Scaled add quadword by 4 +ALPHA_s4subl, // Scaled subtract longword by 4 +ALPHA_s4subq, // Scaled subtract quadword by 4 +ALPHA_s8addl, // Scaled add longword by 8 +ALPHA_s8addq, // Scaled add quadword by 8 +ALPHA_s8subl, // Scaled subtract longword by 8 +ALPHA_s8subq, // Scaled subtract quadword by 8 +ALPHA_sextb, // Sign extend byte +ALPHA_sextw, // Sign extend word +ALPHA_sll, // Shift left logical +ALPHA_sqrtf, // Square root F_floating +ALPHA_sqrtg, // Square root G_floating +ALPHA_sqrts, // Square root S_floating +ALPHA_sqrtt, // Square root T_floating +ALPHA_sra, // Shift right arithmetic +ALPHA_srl, // Shift right logical +ALPHA_stb, // Store byte +ALPHA_stf, // Store F_floating +ALPHA_stg, // Store G_floating +ALPHA_sts, // Store S_floating +ALPHA_stl, // Store longword +ALPHA_stl_c, // Store longword conditional +ALPHA_stq, // Store quadword +ALPHA_stq_c, // Store quadword conditional +ALPHA_stq_u, // Store unaligned quadword +ALPHA_stt, // Store T_floating +ALPHA_stw, // Store word +ALPHA_subf, // Subtract F_floating +ALPHA_subg, // Subtract G_floating +ALPHA_subl, // Subtract longword +ALPHA_subl_v, // Subtract longword with overflow +ALPHA_subq, // Subtract quadword +ALPHA_subq_v, // Subtract quadword with overflow +ALPHA_subs, // Subtract S_floating +ALPHA_subt, // Subtract T_floating +ALPHA_trapb, // Trap barrier +ALPHA_umulh, // Unsigned multiply quadword high +ALPHA_unpkbl, // Unpack bytes to longwords +ALPHA_unpkbw, // Unpack bytes to words +ALPHA_wh64, // Write hint 64 bytes +ALPHA_wmb, // Write memory barrier +ALPHA_xor, // Logical difference +ALPHA_zap, // Zero bytes +ALPHA_zapnot, // Zero bytes not + +// Macros + +ALPHA_unop, // Universal NOP +ALPHA_nop, // Integer NOP +ALPHA_fnop, // Floating point NOP +ALPHA_clr, // Clear +ALPHA_fabs, // Floating point absolute value +ALPHA_fclr, // Floating point clear +ALPHA_fmov, // Floating point register move +ALPHA_fneg, // Floating point negate +ALPHA_mov, // Move to register +ALPHA_negl, // Negate longword +ALPHA_negl_v, // Negate longword with overflow +ALPHA_negq, // Negate quadword +ALPHA_negq_v, // Negate quadword with overflow +ALPHA_negf, // Negate F_floating +ALPHA_negg, // Negate G_floating +ALPHA_negs, // Negate S_floating +ALPHA_negt, // Negate T_floating +ALPHA_not, // Bitwise NOT +ALPHA_sextl, // Move sign extended +ALPHA_or, // Bitwise OR +ALPHA_andnot, // Bit clear +ALPHA_xornot, // Logical equivalence +ALPHA_br0, // Branch + +ALPHA_last, + +}; + + + + +enum +{ +KR1878_null = 0, // Unknown Operation + +KR1878_mov, +KR1878_cmp, // Compare +KR1878_add, // Addition +KR1878_sub, // Subtract +KR1878_and, // Logical AND +KR1878_or, // Logical Inclusive OR +KR1878_xor, // Logical Exclusive OR + +KR1878_movl, +KR1878_cmpl, // Compare +KR1878_addl, // Addition +KR1878_subl, // Subtract +KR1878_bic, +KR1878_bis, +KR1878_btg, +KR1878_btt, + +KR1878_swap, +KR1878_neg, +KR1878_not, +KR1878_shl, // Shift Left +KR1878_shr, // Shift Right +KR1878_shra, // Arithmetic Shift Right +KR1878_rlc, // Rotate Left +KR1878_rrc, // Rotate Right +KR1878_adc, // Add with Carry +KR1878_sbc, // Subtract with Carry + +KR1878_ldr, +KR1878_mtpr, +KR1878_mfpr, +KR1878_push, +KR1878_pop, +KR1878_sst, +KR1878_cst, +KR1878_tof, +KR1878_tdc, + +KR1878_jmp, // Jump +KR1878_jsr, // Jump to Subroutine +KR1878_jnz, // Jump +KR1878_jz, // Jump +KR1878_jns, // Jump +KR1878_js, // Jump +KR1878_jnc, // Jump +KR1878_jc, // Jump +KR1878_ijmp, // Jump +KR1878_ijsr, // Jump to Subroutine +KR1878_rts, // Return from Subroutine +KR1878_rtsc, // Return from Subroutine +KR1878_rti, // Return from Interrupt + +KR1878_nop, // No Operation +KR1878_wait, +KR1878_stop, +KR1878_reset, +KR1878_sksp, + +KR1878_last, + +}; + + + + +enum +{ +AD218X_null = 0, // Unknown Operation +// AMF subcodes +AD218X_amf_01, // op = op * op (rnd) +AD218X_amf_03, // op = mr + op * op (rnd) +AD218X_amf_02, // op = mr - op * op (rnd) +AD218X_amf_04, // op = op * op (ss) +AD218X_amf_05, // op = op * op (su) +AD218X_amf_06, // op = op * op (us) +AD218X_amf_07, // op = op * op (uu) +AD218X_amf_08, // op = mr + op * op +AD218X_amf_09, // op = mr + op * op +AD218X_amf_0a, // op = mr + op * op +AD218X_amf_0b, // op = mr + op * op +AD218X_amf_0c, // op = mr - op * op +AD218X_amf_0d, // op = mr - op * op +AD218X_amf_0e, // op = mr - op * op +AD218X_amf_0f, // op = mr - op * op +AD218X_amf_10, // op = op +AD218X_amf_11, // op = op + 1 +AD218X_amf_12, // op = op + op + C +AD218X_amf_13, // op = op + op +AD218X_amf_14, // op = not op +AD218X_amf_15, // op = - op +AD218X_amf_16, // op = op - op + C - 1 +AD218X_amf_17, // op = op - op +AD218X_amf_18, // op = op - 1 +AD218X_amf_19, // op = op - op +AD218X_amf_1a, // op = op - op + C - 1 +AD218X_amf_1b, // op = not op +AD218X_amf_1c, // op = op and op +AD218X_amf_1d, // op = op or op +AD218X_amf_1e, // op = op xor op +AD218X_amf_1f, // op = abs op +// Shifter subcodes +AD218X_shft_0, // sr = lshift op (hi) +AD218X_shft_1, // sr = sr or lshift op (hi) +AD218X_shft_2, // sr = lshift op (lo) +AD218X_shft_3, // sr = sr or lshift op (lo) +AD218X_shft_4, // sr = ashift op (hi) +AD218X_shft_5, // sr = sr or ashift op (hi) +AD218X_shft_6, // sr = ashift op (lo) +AD218X_shft_7, // sr = sr or ashift op (lo) +AD218X_shft_8, // sr = norm op (hi) +AD218X_shft_9, // sr = sr or norm op (hi) +AD218X_shft_a, // sr = norm op (lo) +AD218X_shft_b, // sr = sr or norm op (lo) +AD218X_shft_c, // sr = exp op (hi) +AD218X_shft_d, // sr = exp op (hix) +AD218X_shft_e, // sr = exp op (lo) +AD218X_shft_f, // sr = expadj op +// ALU/MAC specific options +AD218X_alu_00, // op = op + op + C [IF COND] X + Const +AD218X_alu_01, // op = op + op +AD218X_alu_02, // op = op - op + C - 1 [IF COND] X - Const +AD218X_alu_03, // op = op - op +AD218X_alu_04, // op = op - op + C - 1 [IF COND] Const - X +AD218X_alu_05, // op = op - op +AD218X_alu_06, // op = op and op [IF COND] X and,or,xor Const +AD218X_alu_07, // op = op or op +AD218X_alu_08, // op = op xor op +AD218X_alu_09, // op = op [IF COND] PASS constant; constant <> 0,1, -1 +AD218X_alu_0a, // op = op + 1 +AD218X_alu_0b, // op = op - 1 +AD218X_alu_0c, // divq op ALU Type 23 +AD218X_alu_0d, // divs op, op ALU Type 24 +AD218X_alu_0e, // none = op ALU Type 9, with no result +AD218X_alu_0f, // none = op + 1 +AD218X_alu_10, // none = op + op + C +AD218X_alu_11, // none = op + op +AD218X_alu_12, // none = not op +AD218X_alu_13, // none = - op +AD218X_alu_14, // none = op - op + C - 1 +AD218X_alu_15, // none = op - op +AD218X_alu_16, // none = op - 1 +AD218X_alu_17, // none = op - op + C - 1 +AD218X_alu_18, // none = op - op +AD218X_alu_19, // none = not op +AD218X_alu_1a, // none = op and op +AD218X_alu_1b, // none = op or op +AD218X_alu_1c, // none = op xor op +AD218X_alu_1d, // none = abs op +AD218X_mac_0, // op = 0 [IF COND] MAC CLEAR +AD218X_mac_1, // op = mr (rnd) [IF COND] MAC TRANSFER +AD218X_mac_2, // op = op * op (ss) [IF COND] X * X +AD218X_mac_3, // op = op * op (uu) +AD218X_mac_4, // op = op * op (rnd) +AD218X_mac_5, // op = mr + op * op (ss) [IF COND] MR + X * X +AD218X_mac_6, // op = mr + op * op (uu) +AD218X_mac_7, // op = mr + op * op (rnd) +AD218X_mac_8, // op = mr - op * op (ss) [IF COND] MR - X * X +AD218X_mac_9, // op = mr - op * op (uu) +AD218X_mac_a, // op = mr - op * op (rnd) +AD218X_mac_b, // if mv sat mr ALU/MAC Type 25 +// ALU/MAC Common case +AD218X_amf, // [IF COND] AMF +// Shifter Common case +AD218X_shft, // [IF COND] Shifter +// Shifter specific options. Shifter Type 15, const +AD218X_shifter_0, // sr = ashift op by op (hi) +AD218X_shifter_1, // sr = sr or ashift op by op (hi) +AD218X_shifter_2, // sr = ashift op by op (lo) +AD218X_shifter_3, // sr = sr or ashift op by op (lo) +AD218X_shifter_4, // sr = lshift op by op (hi) +AD218X_shifter_5, // sr = sr or lshift op by op (hi) +AD218X_shifter_6, // sr = lshift op by op (lo) +AD218X_shifter_7, // sr = sr or lshift op by op (lo) +// Data Movement +AD218X_move_0, // op = op Internal Data Move, Instruction Type 17: +AD218X_move_1, // op = op Load Register Immediate, Instruction Type 6: +AD218X_move_2, // op = op Load Non-Data Register Immediate, Instruction Type 7: +AD218X_move_3, // op = dm(op) Data Memory Read (Direct Address), Instruction Type 3: +AD218X_move_4, // op = dm(op, op) Data Memory Read, Instruction Type 4: +AD218X_move_5, // op = pm(op, op) Program Memory Read +AD218X_move_6, // dm(op) = op Data Memory Write (Direct Address) +AD218X_move_7, // dm(op, op) = op Data Memory Write, Instruction Type 4: +AD218X_move_8, // dm(op, op) = op Data Memory Write, Immediate Data, Instruction Type 2: +AD218X_move_9, // pm(op, op) = op Program Memory Write, Instruction Type 5 +AD218X_move_a, // op = io(op) I/O Memory Space Read/Write, Instruction Type 29: +AD218X_move_b, // io(op) = op +// Flow control +AD218X_jump, // Unconditional JUMP Direct, Instruction Type 10: +AD218X_jump_1, // Conditional JUMP Direct, Instruction Type 10: +AD218X_jump_2, // Unconditional JUMP Indirect, Instruction Type 19: +AD218X_jump_3, // Conditional JUMP Indirect, Instruction Type 19: +AD218X_jump_4, // Conditional JUMP on Flag In Direct Instruction Type 27: +AD218X_call, // Conditional CALL Direct, Instruction Type 10: +AD218X_call_1, // Conditional CALL Indirect, Instruction Type 19: +AD218X_call_2, // Conditional CALL on Flag In Direct Instruction Type 27: +AD218X_rts, // Unconditional Return, Instruction Type 20: +AD218X_rts_cond, // Conditional Return, Instruction Type 20: +AD218X_rti, // Unconditional Return, Instruction Type 20: +AD218X_rti_cond, // Conditional Return, Instruction Type 20: +AD218X_nop, // No operation, Instruction Type 30 +AD218X_do, // Do Until, Instruction Type 11: +// Misc +AD218X_idle, // Idle, Instruction Type 31: +AD218X_idle_1, +AD218X_flag_out, // Flag Out Mode Control Instruction Type 28: +AD218X_stack_ctl, // Stack Control, Instruction Type 26: +AD218X_mode_ctl, // Mode Control, Instruction Type 18: +AD218X_tops_w, // toppcstack = op Internal Data Move, Instruction Type 17: +AD218X_tops_r, // op = toppcstack +AD218X_ints_dis, // dis ints +AD218X_ints_ena, // ena ints +AD218X_modify, // modify(op, op) Modify Address Register, Instruction Type 21: +// ALU/MAC operation with Data Memory Read/Write +AD218X_double_move, // op = dm(op, op), op = pm(op, op) Data & Program Memory Read, Instruction Type 1: +AD218X_amf_move_0, // amf_cmd, op = dm(op, op) ALU/MAC operation with Data Memory Read, Instruction Type 4: +AD218X_amf_move_1, // amf_cmd, op = pm(op, op) ALU/MAC operation with Program Memory Read, Instruction Type 5: +AD218X_amf_move_2, // amf_cmd, op = dm(op, op) Shift operation with Data Memory Read, Instruction Type 12: +AD218X_amf_move_3, // amf_cmd, op = pm(op, op) Shift operation with Program Memory Read, Instruction Type 13: +AD218X_amf_move_4, // amf_cmd, op = op ALU/MAC operation with Data Register Move, Instruction Type 8: +AD218X_amf_move_5, // amf_cmd, op = op Shift operation with Data Register Move, Instruction Type 14: +AD218X_amf_move_6, // dm(op, op) = op, amf_cmd ALU/MAC operation with Data Memory Write, Instruction Type 4: +AD218X_amf_move_7, // pm(op, op) = op, amf_cmd ALU/MAC operation with Program Memory Write, Instruction Type 5: +AD218X_amf_move_8, // dm(op, op) = op, amf_cmd Shift operation with Data Memory Write, Instruction Type 12: +AD218X_amf_move_9, // pm(op, op) = op, amf_cmd Shift operation with Program Memory Write, Instruction Type 13: +AD218X_amf_move_a, // amf_cmd, op = dm(op, op), op = pm(op, op) ALU/MAC with Data and Program Memory Read, Instruction Type 1: +AD218X_last, + +}; + + + + +enum +{ +OAK_Dsp_null = 0, // Unknown Operation +OAK_Dsp_proc, // cmd need further process +// ALU-ALM subcodes +OAK_Dsp_or, // 000 Logical Or +OAK_Dsp_and, // 001 And +OAK_Dsp_xor, // 010 Exclusive Or +OAK_Dsp_add, // 011 Add +OAK_Dsp_alm_tst0, // 100 Test Bit-field for Zeros +OAK_Dsp_alm_tst1, // 101 Test Bit-field for Ones +OAK_Dsp_cmp, // 110 Compare +OAK_Dsp_sub, // 111 Subtract +// ALM subcodes +OAK_Dsp_alm_msu, // 1000 Multiply and Subtract Previous Product +OAK_Dsp_addh, // 1001 Add to High Accumulator +OAK_Dsp_addl, // 1010 Add to Low Accumulator +OAK_Dsp_subh, // 1011 Subtract from High Accumulator +OAK_Dsp_subl, // 1100 Subtract from Low Accumulator +OAK_Dsp_sqr, // 1101 Square +OAK_Dsp_sqra, // 1110 Square and Accumulate Previous Product +OAK_Dsp_cmpu, // 1111 Compare Unsigned +// MODA-MODB subcodes conditional +OAK_Dsp_shr, // 000 Shift Accumulator Right +OAK_Dsp_shr4, // 001 Shift Accumulator Right by 4 Bits +OAK_Dsp_shl, // 010 Shift Accumulator Left +OAK_Dsp_shl4, // 011 Shift Accumulator Left by 4 Bits +OAK_Dsp_ror, // 100 Rotate Accumulator Right through Carry +OAK_Dsp_rol, // 101 Rotate Accumulator Left through Carry +OAK_Dsp_clr, // 110 Clear Accumulator +OAK_Dsp_mod_reserved, // 111 Mod Reserved +// MODA subcodes conditional +OAK_Dsp_not, // 1000 Logical Not +OAK_Dsp_neg, // 1001 2's Complement of aX-accumulator +OAK_Dsp_rnd, // 1010 Round Upper 20 Bits of aX-accumulator +OAK_Dsp_pacr, // 1011 Product Move and Round to aX-accumulator +OAK_Dsp_clrr, // 1100 Clear and Round aX-accumulator +OAK_Dsp_inc, // 1101 Increment Accumulator by One +OAK_Dsp_dec, // 1110 Decrement aX-accumulator by One +OAK_Dsp_copy, // 1111 Copy aX-accumulator +// --- +OAK_Dsp_norm, // Normalize +OAK_Dsp_divs, // Division Step +// ALB subcodes +OAK_Dsp_set, // 000 Set Bit-field +OAK_Dsp_rst, // 001 Reset Bit-field +OAK_Dsp_chng, // 010 Change Bit-field +OAK_Dsp_addv, // 011 Add Long Immediate Value or Data Memory Location +OAK_Dsp_alb_tst0, // 100 Test Bit-field for Zeros +OAK_Dsp_alb_tst1, // 101 Test Bit-field for Ones +OAK_Dsp_cmpv, // 110 Compare Long Immediate Value to Register or Data Memory Location +OAK_Dsp_subv, // 111 Subtract Long Immediate Value from a Register or a Data Memory Location +// --- +OAK_Dsp_maxd, // Maximum between Data Memory Location and Accumulator +OAK_Dsp_max, // Maximum between Two Accumulators +OAK_Dsp_min, // Minimum between Two Accumulators +OAK_Dsp_lim, // Limit Accumulator (lim aX[, aX]) +// MUL subcodes +OAK_Dsp_mpy, // 000 Multiply +OAK_Dsp_mpysu, // 001 Multiply Signed by Unsigned +OAK_Dsp_mac, // 010 Multiply and Accumulate Previous Product +OAK_Dsp_macus, // 011 Multiply Unsigned by Signed and Accumulate Previous Product +OAK_Dsp_maa, // 100 Multiply and Accumulate Aligned Previous Product +OAK_Dsp_macuu, // 101 Multiply Unsigned by Unsigned and Accumulate Previous Product +OAK_Dsp_macsu, // 110 Multiply Signed by Unsigned and Accumulate Previous Product +OAK_Dsp_maasu, // 111 Multiply Signed by Unsigned and Accumulate Aligned Previous Product +//--- +OAK_Dsp_mpyi, // Multiply Signed Short Immediate +OAK_Dsp_msu, // Multiply and Subtract Previous Product +OAK_Dsp_tstb, // Test Specific Bit +OAK_Dsp_shfc, // Shift Accumulators according to Shift Value Register +OAK_Dsp_shfi, // Shift Accumulators by an Immediate Shift Value +OAK_Dsp_exp, // Evaluate the Exponent Value +//--- +OAK_Dsp_mov, // Move Data +OAK_Dsp_movp, // Move from Program Memory into Data Memory +OAK_Dsp_movs, // Move and Shift According to Shift Value Register +OAK_Dsp_movsi, // Move and Shift According to an Immediate Shift Value +OAK_Dsp_movr, // Move and Round +OAK_Dsp_movd, // Move from Data Memory into Program Memory +//--- +OAK_Dsp_push, // Push Register or Long Immediate Value onto Stack +OAK_Dsp_pop, // Pop from Stack into Register +//--- +OAK_Dsp_swap, // Swap aX- and bX-accumulators +OAK_Dsp_banke, // Bank Exchange +OAK_Dsp_rep, // Repeat Next Instruction +OAK_Dsp_bkrep, // Block-Repeat +OAK_Dsp_break, // Break from Block-repeat +//--- +OAK_Dsp_br, // Conditional Branch +OAK_Dsp_brr, // Relative Conditional Branch +OAK_Dsp_br_u, // UnConditional Branch +OAK_Dsp_brr_u, // Relative UnConditional Branch +OAK_Dsp_call, // Conditional Call Subroutine +OAK_Dsp_callr, // Relative Conditional Call Subroutine +OAK_Dsp_calla, // Call Subroutine at Location Specified by Accumulator +//--- +OAK_Dsp_ret, // Return Conditionally +OAK_Dsp_ret_u, // Return UnConditionally +OAK_Dsp_retd, // Delayed Return +OAK_Dsp_reti, // Return from Interrupt Conditionally +OAK_Dsp_reti_u, // Return from Interrupt UnConditionally +OAK_Dsp_retid, // Delayed Return from Interrupt +OAK_Dsp_rets, // Return with Short Immediate Parameter +//--- +OAK_Dsp_cntx, // Context Switching Store or Restore +OAK_Dsp_nop, // No operation +OAK_Dsp_modr, // Modify rN +OAK_Dsp_dint, // Disable Interrupt +OAK_Dsp_eint, // Enable Interrupt +//--- +OAK_Dsp_trap, // Software Interrupt +//--- +OAK_Dsp_lpg, // Load the Page Bits +OAK_Dsp_load, // Load Specific Fields into Registers +OAK_Dsp_mov_eu, // Move Data, eu +OAK_Dsp_last, + +}; + +/* + * TLCS900 processor module for IDA. + * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + + +// List of instructions + +// +enum +{ +T900_null = 0, // Unknown Operation +T900_ld, +T900_ldw, +T900_push, +T900_pushw, +T900_pop, +T900_popw, +T900_lda, +T900_ldar, +T900_ex, +T900_mirr, +T900_ldi, +T900_ldiw, +T900_ldir, +T900_ldirw, +T900_ldd, +T900_lddw, +T900_lddr, +T900_lddrw, +T900_cpi, +T900_cpir, +T900_cpd, +T900_cpdr, +T900_add, +T900_addw, +T900_adc, +T900_adcw, +T900_sub, +T900_subw, +T900_sbc, +T900_sbcw, +T900_cp, +T900_cpw, +T900_inc, +T900_incw, +T900_dec, +T900_decw, +T900_neg, +T900_extz, +T900_exts, +T900_daa, +T900_paa, +T900_cpl, +T900_mul, +T900_muls, +T900_div, +T900_divs, +T900_mula, +T900_minc1, +T900_minc2, +T900_minc4, +T900_mdec1, +T900_mdec2, +T900_mdec4, +T900_and, +T900_andw, +T900_or, +T900_orw, +T900_xor, +T900_xorw, +T900_ldcf, +T900_stcf, +T900_andcf, +T900_orcf, +T900_xorcf, +T900_rcf, +T900_scf, +T900_ccf, +T900_zcf, +T900_bit, +T900_res, +T900_set, +T900_chg, +T900_tset, +T900_bs1f, +T900_bs1b, +T900_nop, +T900_ei, +T900_di, +T900_swi, +T900_halt, +T900_ldc, +T900_ldx, +T900_link, +T900_unlk, +T900_ldf, +T900_incf, +T900_decf, +T900_scc, +T900_rlc, +T900_rlc_mem, +T900_rlcw_mem, +T900_rrc, +T900_rrc_mem, +T900_rrcw_mem, +T900_rl, +T900_rl_mem, +T900_rlw_mem, +T900_rr, +T900_rr_mem, +T900_rrw_mem, +T900_sla, +T900_sla_mem, +T900_slaw_mem, +T900_sra, +T900_sra_mem, +T900_sraw_mem, +T900_sll, +T900_sll_mem, +T900_sllw_mem, +T900_srl, +T900_srl_mem, +T900_srlw_mem, +T900_rld, +T900_rrd, +T900_jp, +T900_jp_cond, +T900_jr, +T900_jr_cond, +T900_jrl, +T900_jrl_cond, +T900_call, +T900_calr, +T900_djnz, +T900_ret, +T900_ret_cond, +T900_retd, +T900_reti, +T900_max, +T900_normal, +T900_last +}; + +/* + * Rockwell C39 processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + + +// List of instructions + +// +enum +{ +C39_null = 0, // Unknown Operation +C39_adc, +C39_add, +C39_anc, +C39_and, +C39_ane, +C39_arr, +C39_asl, +C39_asr, +C39_bar, +C39_bas, +C39_bbr, +C39_bbs, +C39_bcc, +C39_bcs, +C39_beq, +C39_bit, +C39_bmi, +C39_bne, +C39_bpl, +C39_bra, +C39_brk, +C39_bvc, +C39_bvs, +C39_clc, +C39_cld, +C39_cli, +C39_clv, +C39_clw, +C39_cmp, +C39_cpx, +C39_cpy, +C39_dcp, +C39_dec, +C39_dex, +C39_dey, +C39_eor, +C39_exc, +C39_inc, +C39_ini, +C39_inx, +C39_iny, +C39_isb, +C39_jmp, +C39_jpi, +C39_jsb, +C39_jsr, +C39_lab, +C39_lae, +C39_lai, +C39_lan, +C39_lax, +C39_lda, +C39_ldx, +C39_ldy, +C39_lii, +C39_lsr, +C39_lxa, +C39_mpa, +C39_mpy, +C39_neg, +C39_nop, +C39_nxt, +C39_ora, +C39_pha, +C39_phi, +C39_php, +C39_phw, +C39_phx, +C39_phy, +C39_pia, +C39_pla, +C39_pli, +C39_plp, +C39_plw, +C39_plx, +C39_ply, +C39_psh, +C39_pul, +C39_rba, +C39_rla, +C39_rmb, +C39_rnd, +C39_rol, +C39_ror, +C39_rra, +C39_rti, +C39_rts, +C39_sax, +C39_sba, +C39_sbc, +C39_sbx, +C39_sec, +C39_sed, +C39_sei, +C39_sha, +C39_shs, +C39_shx, +C39_shy, +C39_slo, +C39_smb, +C39_sre, +C39_sta, +C39_sti, +C39_stx, +C39_sty, +C39_tax, +C39_tay, +C39_taw, +C39_tip, +C39_tsx, +C39_twa, +C39_txa, +C39_txs, +C39_tya, +C39_last +}; + +/* + * National Semiconductor Corporation CR16 processor module for IDA. + * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + + +// list of instructions + +enum +{ +CR16_null = 0, // Unknown Operation +CR16_addb, +CR16_addw, +CR16_addub, +CR16_adduw, +CR16_addcb, +CR16_addcw, +CR16_andb, +CR16_andw, +CR16_ashub, +CR16_ashuw, +// !!! don't change sequence !!! +CR16_beq, +CR16_bne, +CR16_bcs, +CR16_bcc, +CR16_bhi, +CR16_bls, +CR16_bgt, +CR16_ble, +CR16_bfs, +CR16_bfc, +CR16_blo, +CR16_bhs, +CR16_blt, +CR16_bge, +CR16_br, +//---------------------------- +CR16_bal, +CR16_cmpb, +CR16_cmpw, +CR16_beq1b, +CR16_beq1w, +CR16_beq0b, +CR16_beq0w, +CR16_bne1b, +CR16_bne1w, +CR16_bne0b, +CR16_bne0w, +CR16_di, +CR16_ei, +CR16_excp, +// !!! don't change sequence !!! +CR16_jeq, +CR16_jne, +CR16_jcs, +CR16_jcc, +CR16_jhi, +CR16_jls, +CR16_jgt, +CR16_jle, +CR16_jfs, +CR16_jfc, +CR16_jlo, +CR16_jhs, +CR16_jlt, +CR16_jge, +CR16_jump, +//---------------------------- +CR16_jal, +CR16_loadb, +CR16_loadw, +CR16_loadm, +CR16_lpr, +CR16_lshb, +CR16_lshw, +CR16_movb, +CR16_movw, +CR16_movxb, +CR16_movzb, +CR16_movd, +CR16_mulb, +CR16_mulw, +CR16_mulsb, +CR16_mulsw, +CR16_muluw, +CR16_nop, +CR16_orb, +CR16_orw, +CR16_push, +CR16_pop, +CR16_popret, +CR16_retx, +// !!! don't change sequence !!! +CR16_seq, +CR16_sne, +CR16_scs, +CR16_scc, +CR16_shi, +CR16_sls, +CR16_sgt, +CR16_sle, +CR16_sfs, +CR16_sfc, +CR16_slo, +CR16_shs, +CR16_slt, +CR16_sge, +//---------------------------- +CR16_spr, +CR16_storb, +CR16_storw, +CR16_storm, +CR16_subb, +CR16_subw, +CR16_subcb, +CR16_subcw, +CR16_tbit, +CR16_tbitb, +CR16_tbitw, +CR16_sbitb, +CR16_sbitw, +CR16_cbitb, +CR16_cbitw, +CR16_wait, +CR16_eiwait, +CR16_xorb, +CR16_xorw, +CR16_last +}; + +/* + * Panasonic MN102 (PanaXSeries) processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + + +// List of instructions + +enum +{ +mn102_null = 0, // Unknown Operation +mn102_add, +mn102_addc, +mn102_addnf, +mn102_and, +mn102_asr, +mn102_bcc, +mn102_bccx, +mn102_bclr, +mn102_bcs, +mn102_bcsx, +mn102_beq, +mn102_beqx, +mn102_bge, +mn102_bgex, +mn102_bgt, +mn102_bgtx, +mn102_bhi, +mn102_bhix, +mn102_ble, +mn102_blex, +mn102_bls, +mn102_blsx, +mn102_blt, +mn102_bltx, +mn102_bnc, +mn102_bncx, +mn102_bne, +mn102_bnex, +mn102_bns, +mn102_bnsx, +mn102_bra, +mn102_bset, +mn102_btst, +mn102_bvc, +mn102_bvcx, +mn102_bvs, +mn102_bvsx, +mn102_cmp, +mn102_divu, +mn102_ext, +mn102_extx, +mn102_extxb, +mn102_extxbu, +mn102_extxu, +mn102_jmp, +mn102_jsr, +mn102_lsr, +mn102_mov, +mn102_movb, +mn102_movbu, +mn102_movx, +mn102_mul, +mn102_mulq, +mn102_mulqh, +mn102_mulql, +mn102_mulu, +mn102_nop, +mn102_not, +mn102_or, +mn102_pxst, +mn102_rol, +mn102_ror, +mn102_rti, +mn102_rts, +mn102_sub, +mn102_subc, +mn102_tbnz, +mn102_tbz, +mn102_xor, +mn102_last +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * PowerPC - RISC with very complex instructions + */ + + + +enum +{ +PPC_null = 0, // Unknown Operation +PPC_add, // Add +PPC_addc, // Add Carrying +PPC_adde, // Add Extended +PPC_addi, // Add Immediate +PPC_addic, // Add Immediate Carrying +PPC_addis, // Add Immediate Shifted +PPC_addme, // Add to Minus One Extended +PPC_addze, // Add to Zero Extended +PPC_and, // AND +PPC_andc, // AND with Complement +PPC_andi, // AND Immediate +PPC_andis, // AND Immediate Shifted +PPC_b, // Branch +PPC_bc, // Branch Conditional +PPC_bcctr, // Branch Conditional to Count Register +PPC_bclr, // Branch Conditional to Link Register +PPC_cmp, // Compare +PPC_cmpi, // Compare Immediate +PPC_cmpl, // Compare Logical +PPC_cmpli, // Compare Logical Immediate +PPC_cntlzd, // Count Leading Zeros Double Word +PPC_cntlzw, // Count Leading Zeros Word +PPC_crand, // Condition Register AND +PPC_crandc, // Condition Register AND with Complement +PPC_creqv, // Condition Register Equivalent +PPC_crnand, // Condition Register NAND +PPC_crnor, // Condition Register NOR +PPC_cror, // Condiiton Register OR +PPC_crorc, // Condition Register OR with Comlement +PPC_crxor, // Condition Register XOR +PPC_dcba, // +PPC_dcbf, // Data Cache Block Flush +PPC_dcbi, // Data Cache Block Invalidate +PPC_dcbst, // Data Cache Block Store +PPC_dcbt, // Data Cache Block Touch +PPC_dcbtst, // Data Cache Block Touch for Store +PPC_dcbz, // Data Cache Block Set to Zero +PPC_divd, // Divide Double Word +PPC_divdu, // Divide Double Word Unsigned +PPC_divw, // Divide Word +PPC_divwu, // Divide Word Unsigned +PPC_eciwx, // External Control In Word Indexed +PPC_ecowx, // External Control Out Word Indexed +PPC_eieio, // Enforce In-Order Execution of I/O +PPC_eqv, // Equivalent +PPC_extsb, // Extend Sign Byte +PPC_extsh, // Extend Sign Half Word +PPC_extsw, // Extend Sign Word +PPC_fabs, // Floating-Point Absolute Value +PPC_fadd, // Floating-Point Add +PPC_fadds, // Floating-Point Add (Single-Precision) +PPC_fcfid, // Floating-Point Convert from Integer Double Word +PPC_fcmpo, // Floating-Point Compare Ordered +PPC_fcmpu, // Floating-Point Compare Unordered +PPC_fctid, // Floating-Point Convert to Integer Double Word +PPC_fctidz, // Floating-Point Convert to Integer Double Word with Round toward Zero +PPC_fctiw, // Floating-Point Convert to Integer Word +PPC_fctiwz, // Floating-Point Convert to Integer Word with Round toward Zero +PPC_fdiv, // Floating-Point Divide +PPC_fdivs, // Floating-Point Divide Single-Precision +PPC_fmadd, // Floating-Point Multiply-Add +PPC_fmadds, // Floating-Point Multiply-Add Single-Precision +PPC_fmr, // Floating-Point Move Register +PPC_fmsub, // Floating-Point Multiply-Subtract +PPC_fmsubs, // Floating-Point Multiply-Subtract (Single-Precision) +PPC_fmul, // Floating-Point Multiply +PPC_fmuls, // Floating-Point Multiply Single-Precision +PPC_fnabs, // Floating-Point Negative Absolute Value +PPC_fneg, // Floating-Point Negate +PPC_fnmadd, // Floating-Point Negative Multiply-Add +PPC_fnmadds, // Floating-Point Negative Multiply-Add Single-Precision +PPC_fnmsub, // Floating-Point Negative Multiply-Subtract +PPC_fnmsubs, // Floating-Point Negative Multiply-Subtract Single-Precision +PPC_fres, // Floating-Point Reciprocal Estimate Single-Precision +PPC_frsp, // Floating-Point Round to Single-Precision +PPC_frsqrte, // Floating-Point Reciprocal Square Root Estimate +PPC_fsel, // Floating-Point Select +PPC_fsqrt, // Floating-Point Square Root +PPC_fsqrts, // Floating-Point Square Root Single-Precision +PPC_fsub, // Floating-Point Subtract +PPC_fsubs, // Floating-Point Subtract Single-Precision +PPC_icbi, // Instruction Cache Block Invalidate +PPC_isync, // Instruction Synchronize +PPC_lbz, // Load Byte and Zero +PPC_lbzu, // Load Byte and Zero with Update +PPC_lbzux, // Load Byte and Zero with Update Indexed +PPC_lbzx, // Load Byte and Zero Indexed +PPC_ld, // Load Double Word +PPC_ldarx, // Load Double Word and Reserve Indexed +PPC_ldu, // Load Double Word with Update +PPC_ldux, // Load Double Word with Update Indexed +PPC_ldx, // Load Double Word Indexed +PPC_lfd, // Load Floating-Point Double-Precision +PPC_lfdu, // Load Floating-Point Double-Precision with Update +PPC_lfdux, // Load Floating-Point Double-Precision with Update Indexed +PPC_lfdx, // Load Floating-Point Double-Precision Indexed +PPC_lfs, // Load Floating-Point Single-Precision +PPC_lfsu, // Load Floating-Point Single-Precision with Update +PPC_lfsux, // Load Floating-Point Single-Precision with Update Indexed +PPC_lfsx, // Load Floating-Point Single-Precision Indexed +PPC_lha, // Load Half Word Algebraic +PPC_lhau, // Load Half Word Algebraic with Update +PPC_lhaux, // Load Half Word Algebraic with Update Indexed +PPC_lhax, // Load Half Word Algebraic Indexed +PPC_lhbrx, // Load Half Word Byte-reverse Indexed +PPC_lhz, // Load Half Word and Zero +PPC_lhzu, // Load Half Word and Zero with Update +PPC_lhzux, // Load Half Word and Zero with Update Indexed +PPC_lhzx, // Load Half Word and Zero Indexed +PPC_lmw, // Load Multiple Word +PPC_lswi, // Load String Word Immediate +PPC_lswx, // Load String Word Indexed +PPC_lwa, // Load Word Algebraic +PPC_lwarx, // Load Word and Reserve Indexed +PPC_lwaux, // Load Word Algebraic with Update Indexed +PPC_lwax, // Load Word Algebraic Indexed +PPC_lwbrx, // Load Word Byte-Reverse Indexed +PPC_lwz, // Load Word and Zero +PPC_lwzu, // Load Word and Zero with Update +PPC_lwzux, // Load Word and Zero with Update Indexed +PPC_lwzx, // Load Word and Zero Indexed +PPC_mcrf, // Move Condition register Field +PPC_mcrfs, // Move to Condition Register from FPSCR +PPC_mcrxr, // Move to Condition Register from XER +PPC_mfcr, // Move from Condition Register +PPC_mffs, // Move from FPSCR +PPC_mfmsr, // Move from Machine State Register +PPC_mfspr, // Move from Special Purpose Register +PPC_mfsr, // Move from Segment Register +PPC_mfsrin, // Move from Segment Register Indexed +PPC_mftb, // Move from Time Base +PPC_mtcrf, // Move to Condition Register Fields +PPC_mtfsb0, // Move to FPSCR Bit 0 +PPC_mtfsb1, // Move to FPSCR Bit 1 +PPC_mtfsf, // Move to FPSCR Fields +PPC_mtfsfi, // Move to FPSCR Field Immediate +PPC_mtmsr, // Move to Machine State Register +PPC_mtmsrd, // Move to Machine State Register Double Word +PPC_mtspr, // Move to Special Purpose Register +PPC_mtsr, // Move to Segment Register +PPC_mtsrd, // Move to Segment Register Double Word +PPC_mtsrdin, // Move to Segment Register Indirect Double +PPC_mtsrin, // Move to Segment Register Indirect +PPC_mulhd, // Multiply High Double Word +PPC_mulhdu, // Multiply High Double Word Unsigned +PPC_mulhw, // Multiply High Word +PPC_mulhwu, // Multiply High Word Unsigned +PPC_mulld, // Multiply Low Double Word +PPC_mulli, // Multiply Low Immediate +PPC_mullw, // Multiply Low +PPC_nand, // NAND (not AND) +PPC_neg, // Negate +PPC_nor, // NOR (not OR) +PPC_or, // OR +PPC_orc, // OR with Complement +PPC_ori, // OR Immediate +PPC_oris, // OR Immediate Shifted +PPC_rfi, // Return from Interrupt +PPC_rfid, // Return from Interrupt Double Word +PPC_rldcl, // Rotate Left Double Word then Clear Left +PPC_rldcr, // Rotate Left Double Word then Clear Right +PPC_rldic, // Rotate Left Double Word Immediate then Clear +PPC_rldicl, // Rotate Left Double Word Immediate then Clear Left +PPC_rldicr, // Rotate Left Double Word Immediate then Clear Right +PPC_rldimi, // Rotate Left Double Word Immediate then Mask Insert +PPC_rlwimi, // Rotate Left Word Immediate then Mask Insert +PPC_rlwinm, // Rotate Left Word Immediate then AND with Mask +PPC_rlwnm, // Rotate Left Word then AND with Mask +PPC_sc, // System Call +PPC_slbia, // SLB Invalidate All, ISA 3.0 format +PPC_slbie, // SLB Invalidate Entry +PPC_sld, // Shift Left Double Word +PPC_slw, // Shift Left Word +PPC_srad, // Shift Right Algebraic Double Word +PPC_sradi, // Shift Right Algebraic Double Word Immediate +PPC_sraw, // Shift Right Algebraic Word +PPC_srawi, // Shift Right Algebraic Word Immediate +PPC_srd, // Shift Right Double Word +PPC_srw, // Shift Right Word +PPC_stb, // Store Byte +PPC_stbu, // Store Byte with Update +PPC_stbux, // Store Byte with Update Indexed +PPC_stbx, // Store Byte Indexed +PPC_std, // Store Double Word +PPC_stdcx, // Store Double Word Conditional Indexed +PPC_stdu, // Store Double Word with Update +PPC_stdux, // Store Double Word with Update Indexed +PPC_stdx, // Store Double Word Indexed +PPC_stfd, // Store Floating-Point Double-Precision +PPC_stfdu, // Store Floating-Point Double-Precision wiht Update +PPC_stfdux, // Store Floating-Point Double-Precision wiht Update Indexed +PPC_stfdx, // Store Floating-Point Double-Precision Indexed +PPC_stfiwx, // Store Floating-Point as Integer Word Indexed +PPC_stfs, // Store Floating-Point Single-Precision +PPC_stfsu, // Store Floating-Point Single-Precision with Update +PPC_stfsux, // Store Floating-Point Single-Precision with Update Indexed +PPC_stfsx, // Store Floating-Point Single-Precision Indexed +PPC_sth, // Store Half Word +PPC_sthbrx, // Store Half Word Byte-Reverse Indexed +PPC_sthu, // Store Half Word with Update +PPC_sthux, // Store Half Word with Update Indexed +PPC_sthx, // Store Half Word Indexed +PPC_stmw, // Store Multiple Word +PPC_stswi, // Store String Word Immediate +PPC_stswx, // Store String Word Indexed +PPC_stw, // Store Word +PPC_stwbrx, // Store Word Byte-Reverse Indexed +PPC_stwcx, // Store Word Conditional Indexed +PPC_stwu, // Store Word with Update +PPC_stwux, // Store Word with Update Indexed +PPC_stwx, // Store Word Indexed +PPC_subf, // Subtract from +PPC_subfc, // Subtract from Carrying +PPC_subfe, // Subtract from Extended +PPC_subfic, // Subtract from Immediate Carrying +PPC_subfme, // Subtract from Minus One Extended +PPC_subfze, // Subtract from Zero Extended +PPC_sync, // Synchronize +PPC_td, // Trap Double Word +PPC_tdi, // Trap Double Word Immediate +PPC_tlbia, // TLB Invalidate All +PPC_tlbie, // TLB Invalidate Entry, ISA 3.0 format +PPC_tlbsync, // TLB Synchronize +PPC_tw, // Trap Word +PPC_twi, // Trap Word Immediate +PPC_xor, // XOR +PPC_xori, // XOR Immediate +PPC_xoris, // XOR Immediate Shifted + +PPC_last_basic = PPC_xoris, + +// +// Simplified mnemonics +// + +PPC_cmpwi, // Compare Word Immediate +PPC_cmpw, // Compare Word +PPC_cmplwi, // Compare Logical Word Immediate +PPC_cmplw, // Compare Logical Word +PPC_cmpdi, // Compare Double Word Immediate +PPC_cmpd, // Compare Double Word +PPC_cmpldi, // Compare Logical Double Word Immediate +PPC_cmpld, // Compare Logical Double Word + +PPC_trap, // Trap Word Unconditionally +// "trapd" seems like a bug; no such mnemonic appears to exist as just plain +// "trap" is used regardless of word/doubleword, but we have to leave it here +// to not mess up existing databases +PPC_trapd, // Trap Double Word Unconditionally +PPC_twlgt, // Trap Word if Logically Greater Than +PPC_twllt, // Trap Word if Logically Less Than +PPC_tweq, // Trap Word if Equal +PPC_twlge, // Trap Word if Logically Greater Than or Equal +PPC_twlle, // Trap Word if Logically Less Than or Equal +PPC_twgt, // Trap Word if Greater Than +PPC_twge, // Trap Word if Greater Than or Equal +PPC_twlt, // Trap Word if Less Than +PPC_twle, // Trap Word if Less Than or Equal +PPC_twne, // Trap Word if Not Equal +PPC_twlgti, // Trap Word Immediate if Logically Greater Than +PPC_twllti, // Trap Word Immediate if Logically Less Than +PPC_tweqi, // Trap Word Immediate if Equal +PPC_twlgei, // Trap Word Immediate if Logically Greater Than or Equal +PPC_twllei, // Trap Word Immediate if Logically Less Than or Equal +PPC_twgti, // Trap Word Immediate if Greater Than +PPC_twgei, // Trap Word Immediate if Greater Than or Equal +PPC_twlti, // Trap Word Immediate if Less Than +PPC_twlei, // Trap Word Immediate if Less Than or Equal +PPC_twnei, // Trap Word Immediate if Not Equal +PPC_tdlgt, // Trap Double Word if Logically Greater Than +PPC_tdllt, // Trap Double Word if Logically Less Than +PPC_tdeq, // Trap Double Word if Equal +PPC_tdlge, // Trap Double Word if Logically Greater Than or Equal +PPC_tdlle, // Trap Double Word if Logically Less Than or Equal +PPC_tdgt, // Trap Double Word if Greater Than +PPC_tdge, // Trap Double Word if Greater Than or Equal +PPC_tdlt, // Trap Double Word if Less Than +PPC_tdle, // Trap Double Word if Less Than or Equal +PPC_tdne, // Trap Double Word if Not Equal +PPC_tdlgti, // Trap Double Word Immediate if Logically Greater Than +PPC_tdllti, // Trap Double Word Immediate if Logically Less Than +PPC_tdeqi, // Trap Double Word Immediate if Equal +PPC_tdlgei, // Trap Double Word Immediate if Logically Greater Than or Equal +PPC_tdllei, // Trap Double Word Immediate if Logically Less Than or Equal +PPC_tdgti, // Trap Double Word Immediate if Greater Than +PPC_tdgei, // Trap Double Word Immediate if Greater Than or Equal +PPC_tdlti, // Trap Double Word Immediate if Less Than +PPC_tdlei, // Trap Double Word Immediate if Less Than or Equal +PPC_tdnei, // Trap Double Word Immediate if Not Equal +// all trap mnemonics are covered as of Power ISA 2.07; t[dw]nl*, t[dw]lnl*, +// and t[dw]lng* are intentionally missing since they are redundant. in other +// words, the assembler supports (e.g.) both "logically less than or equal" +// (tdlei) in addition to "logically not greater than" (tdlngi)--a disassembler +// need not support both + +PPC_nop, // No Operation +PPC_not, // Complement Register +PPC_mr, // Move Register + +PPC_subi, // Subtract Immediate +PPC_subic, // Subtract Immediate Carrying +PPC_subis, // Subtract Immediate Shifted +PPC_li, // Load Immediate +PPC_lis, // Load Immediate Shifted + +PPC_crset, // Condition Register Set +PPC_crnot, // Condition Register NOT +PPC_crmove, // Condition Register Move +PPC_crclr, // Condition Register Clear + +PPC_mtxer, // Move to integer unit exception register +PPC_mtlr, // Move to link register +PPC_mtctr, // Move to count register +PPC_mtdsisr, // Move to DAE/source instruction service register +PPC_mtdar, // Move to data address register +PPC_mtdec, // Move to decrementer register +PPC_mtsrr0, // Move to status save/restore register 0 +PPC_mtsrr1, // Move to status save/restore register 1 +PPC_mtsprg0, // Move to general special purpose register 0 +PPC_mtsprg1, // Move to general special purpose register 1 +PPC_mtsprg2, // Move to general special purpose register 2 +PPC_mtsprg3, // Move to general special purpose register 3 +PPC_mttbl, // Move to time base register (lower) +PPC_mttbu, // Move to time base register (upper) +PPC_mfxer, // Move from integer unit exception register +PPC_mflr, // Move from link register +PPC_mfctr, // Move from count register +PPC_mfdsisr, // Move from DAE/source instruction service register +PPC_mfdar, // Move from data address register +PPC_mfdec, // Move from decrementer register +PPC_mfsrr0, // Move from status save/restore register 0 +PPC_mfsrr1, // Move from status save/restore register 1 +PPC_mfsprg0, // Move from general special purpose register 0 +PPC_mfsprg1, // Move from general special purpose register 1 +PPC_mfsprg2, // Move from general special purpose register 2 +PPC_mfsprg3, // Move from general special purpose register 3 +PPC_mftbl, // Move from time base register (lower) +PPC_mftbu, // Move from time base register (upper) +PPC_mfpvr, // Move from processor version register + +// suffixes: +// lr - goto lr +// ctr - goto ctr +// l - update lr +// a - absolute + +// branch forms not listed here or elsewhere in the file (e.g. bltlr) are +// being handled by emitting extra characters when printing the instructions +// instead of having separate enums + +PPC_balways, // Branch unconditionally +PPC_bt, // Branch if true +PPC_bf, // Branch if false +PPC_bdnz, // CTR--; branch if CTR non-zero +PPC_bdnzt, // CTR--; branch if CTR non-zero and condition is true +PPC_bdnzf, // CTR--; branch if CTR non-zero and condition is false +PPC_bdz, // CTR--; branch if CTR zero +PPC_bdzt, // CTR--; branch if CTR zero and condition is true +PPC_bdzf, // CTR--; branch if CTR zero and condition is false + +PPC_blt, // Branch if less than +PPC_ble, // Branch if less than or equal +PPC_beq, // Branch if equal +PPC_bge, // Branch if greater than or equal +PPC_bgt, // Branch if greater than +PPC_bne, // Branch if not equal +PPC_bso, // Branch if summary overflow +PPC_bns, // Branch if not summary overflow +// bun and bnu are intentionally missing from this list; they are handled by +// bso/bns (this is the result of historical differences between POWER and PPC +// mnemonics) + +PPC_extlwi, // Extract and Left Justify Immediate +PPC_extrwi, // Extract and Right Justify Immediate +PPC_inslwi, // Insert from Left Immediate +PPC_insrwi, // Insert from Right Immediate +PPC_rotlwi, // Rotate Left Immediate +PPC_rotrwi, // Rotate Right Immediate +PPC_rotlw, // Rotate Left +PPC_slwi, // Shift Left Immediate +PPC_srwi, // Shift Right Immediate +PPC_clrlwi, // Clear Left Immediate +PPC_clrrwi, // Clear Right Immediate +PPC_clrlslwi, // Clear Left and Shift Left Immediate + +// +// PowerPC Embedded Controller Instructions +// + +PPC_dccci, // Data cache congruence class invalidate (p.438-439) +PPC_dcread, // Data cache read (p.440-441) +PPC_icbt, // Instruction cache block touch (p.450-451) +PPC_iccci, // Instruction cache congruence class invalidate (p.452-453) +PPC_icread, // Instruction cache read (p.454-455) +PPC_mfdcr, // Move from device control register (p.484-485) +PPC_mtdcr, // Move to device control register (p.491-492) +PPC_rfci, // Return from critical interrupt (p.507) +PPC_tlbre, // TLB read entry (p.548-549) +PPC_tlbsx, // TLB search indexed (p.550) +PPC_tlbwe, // TLB write entry (p.552-553) +PPC_wrtee, // Write external enable (p.560) +PPC_wrteei, // Write external enable immediate (p.561) + +// +// New PowerPC instructions +// + +PPC_abs, // Absolute +PPC_clcs, // Cache Lines Compute Size +PPC_clf, // Cache Line Flush +PPC_cli, // Cache Line Invalidate +PPC_dclst, // Data Cache Line Store +PPC_div, // Divide +PPC_divs, // Divide Short +PPC_doz, // Different Or Zero +PPC_dozi, // Different Or Zero Immediate +PPC_frsqrtes, // Floating Reciprocal Square Root Estimate Single +PPC_hrfid, // Hypervisor Return from Interrupt Doubleword +PPC_lscbx, // Load String And Compare Byte Indexed +PPC_maskg, // Mask Generate +PPC_maskir, // Mask Insert From Register +PPC_mfsri, // Move From Segment Register Indirect +PPC_mul, // Multiply +PPC_nabs, // Negative Absolute +PPC_popcntb, // Population Count Bytes +PPC_rac, // Real Address Compute +PPC_rfsvc, // Return From SVC, obsolete, see ana.cpp +PPC_rlmi, // Rotate Left Then Mask Insert +PPC_rrib, // Rotate Right And Insert Bit +PPC_slbmfee, // SLB Move From Entry ESID +PPC_slbmfev, // SLB Move From Entry VSID +PPC_slbmte, // SLB Move To Entry +PPC_sle, // Shift Left Extended +PPC_sleq, // Shift Left Extended With MQ +PPC_sliq, // Shift Left Immediate With MQ +PPC_slliq, // Shift Left Long Immediate With MQ +PPC_sllq, // Shift Left Long With MQ +PPC_slq, // Shift Left With MQ +PPC_sraiq, // Shift Right Algebraic Immediate With MQ +PPC_sraq, // Shift Right Algebraic With MQ +PPC_sre, // Shift Right Extended +PPC_srea, // Shift Right Extended Algebraic +PPC_sreq, // Shift Right Extended With MQ +PPC_sriq, // Shift Right Immediate With MQ +PPC_srliq, // Shift Right Long Immediate With MQ +PPC_srlq, // Shift Right Long With MQ +PPC_srq, // Shift Right With MQ + +// New instructions + +PPC_mtocrf, // Move To One Condition Register Field +PPC_mfocrf, // Move From One Condition Register Field + +// Freescale e200z6 instructions +PPC_isel, // Integer Select +PPC_isellt, // Integer Select Less Than +PPC_iselgt, // Integer Select Greater Than +PPC_iseleq, // Integer Select Equal +PPC_dcblc, // Data Cache Block Lock Clear +PPC_dcbtls, // Data Cache Block Touch and Lock Set +PPC_dcbtstls, // Data Cache Block Touch for Store and Lock Set +PPC_icblc, // Instruction Cache Block Lock Clear +PPC_icbtls, // Instruction Cache Block Touch and Lock Set +PPC_tlbivax, // TLB Invalidate Virtual Address Indexed +PPC_rfdi, // Return from Debug Interrupt + +// Freescale MPC603e instructions (G2 core) + +PPC_tlbld, // Load Data TLB Entry +PPC_tlbli, // Load Instruction TLB Entry + +// SPE (Signal Processing Engine) instructions + +PPC_brinc, // Bit Reversed Increment +PPC_evabs, // Vector Absolute Value +PPC_evaddiw, // Vector Add Immediate Word +PPC_evaddsmiaaw, // Vector Add Signed, Modulo, Integer to Accumulator Word +PPC_evaddssiaaw, // Vector Add Signed, Saturate, Integer to Accumulator Word +PPC_evaddumiaaw, // Vector Add Unsigned, Modulo, Integer to Accumulator Word +PPC_evaddusiaaw, // Vector Add Unsigned, Saturate, Integer to Accumulator Word +PPC_evaddw, // Vector Add Word +PPC_evand, // Vector AND +PPC_evandc, // Vector AND with Complement +PPC_evcmpeq, // Vector Compare Equal +PPC_evcmpgts, // Vector Compare Greater Than Signed +PPC_evcmpgtu, // Vector Compare Greater Than Unsigned +PPC_evcmplts, // Vector Compare Less Than Signed +PPC_evcmpltu, // Vector Compare Less Than Unsigned +PPC_evcntlsw, // Vector Count Leading Signed Bits Word +PPC_evcntlzw, // Vector Count Leading Zeros Word +PPC_evdivws, // Vector Divide Word Signed +PPC_evdivwu, // Vector Divide Word Unsigned +PPC_eveqv, // Vector Equivalent +PPC_evextsb, // Vector Extend Sign Byte +PPC_evextsh, // Vector Extend Sign Halfword +PPC_evldd, // Vector Load Double Word into Double Word +PPC_evlddx, // Vector Load Double Word into Double Word Indexed +PPC_evldh, // Vector Load Double into Four Halfwords +PPC_evldhx, // Vector Load Double into Four Halfwords Indexed +PPC_evldw, // Vector Load Double into Two Words +PPC_evldwx, // Vector Load Double into Two Words Indexed +PPC_evlhhesplat, // Vector Load Halfword into Halfwords Even and Splat +PPC_evlhhesplatx, // Vector Load Halfword into Halfwords Even and Splat Indexed +PPC_evlhhossplat, // Vector Load Halfword into Halfword Odd Signed and Splat +PPC_evlhhossplatx, // Vector Load Halfword into Halfword Odd Signed and Splat Indexed +PPC_evlhhousplat, // Vector Load Halfword into Halfword Odd Unsigned and Splat +PPC_evlhhousplatx, // Vector Load Halfword into Halfword Odd Unsigned and Splat Indexed +PPC_evlwhe, // Vector Load Word into Two Halfwords Even +PPC_evlwhex, // Vector Load Word into Two Halfwords Even Indexed +PPC_evlwhos, // Vector Load Word into Two Halfwords Odd Signed (with sign extension) +PPC_evlwhosx, // Vector Load Word into Two Halfwords Odd Signed Indexed (with sign extension) +PPC_evlwhou, // Vector Load Word into Two Halfwords Odd Unsigned (zero-extended) +PPC_evlwhoux, // Vector Load Word into Two Halfwords Odd Unsigned Indexed (zero-extended) +PPC_evlwhsplat, // Vector Load Word into Two Halfwords and Splat +PPC_evlwhsplatx, // Vector Load Word into Two Halfwords and Splat Indexed +PPC_evlwwsplat, // Vector Load Word into Word and Splat +PPC_evlwwsplatx, // Vector Load Word into Word and Splat Indexed +PPC_evmergehi, // Vector Merge High +PPC_evmergehilo, // Vector Merge High/Low +PPC_evmergelo, // Vector Merge Low +PPC_evmergelohi, // Vector Merge Low/High +PPC_evmhegsmfaa, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Fractional and Accumulate +PPC_evmhegsmfan, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Fractional and Accumulate Negative +PPC_evmhegsmiaa, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Integer and Accumulate +PPC_evmhegsmian, // Vector Multiply Halfwords, Even, Guarded, Signed, Modulo, Integer and Accumulate Negative +PPC_evmhegumiaa, // Vector Multiply Halfwords, Even, Guarded, Unsigned, Modulo, Integer and Accumulate +PPC_evmhegumian, // Vector Multiply Halfwords, Even, Guarded, Unsigned, Modulo, Integer and Accumulate Negative +PPC_evmhesmf, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional +PPC_evmhesmfa, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional to Accumulator +PPC_evmhesmfaaw, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional and Accumulate into Words +PPC_evmhesmfanw, // Vector Multiply Halfwords, Even, Signed, Modulo, Fractional and Accumulate Negative into Words +PPC_evmhesmi, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer +PPC_evmhesmia, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer to Accumulator +PPC_evmhesmiaaw, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer and Accumulate into Words +PPC_evmhesmianw, // Vector Multiply Halfwords, Even, Signed, Modulo, Integer and Accumulate Negative into Words +PPC_evmhessf, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional +PPC_evmhessfa, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional to Accumulator +PPC_evmhessfaaw, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional and Accumulate into Words +PPC_evmhessfanw, // Vector Multiply Halfwords, Even, Signed, Saturate, Fractional and Accumulate Negative into Words +PPC_evmhessiaaw, // Vector Multiply Halfwords, Even, Signed, Saturate, Integer and Accumulate into Words +PPC_evmhessianw, // Vector Multiply Halfwords, Even, Signed, Saturate, Integer and Accumulate Negative into Words +PPC_evmheumi, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer +PPC_evmheumia, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer to Accumulator +PPC_evmheumiaaw, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer and Accumulate into Words +PPC_evmheumianw, // Vector Multiply Halfwords, Even, Unsigned, Modulo, Integer and Accumulate Negative into Words +PPC_evmheusiaaw, // Vector Multiply Halfwords, Even, Unsigned, Saturate, Integer and Accumulate into Words +PPC_evmheusianw, // Vector Multiply Halfwords, Even, Unsigned, Saturate, Integer and Accumulate Negative into Words +PPC_evmhogsmfaa, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Fractional and Accumulate +PPC_evmhogsmfan, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Fractional and Accumulate Negative +PPC_evmhogsmiaa, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Integer and Accumulate +PPC_evmhogsmian, // Vector Multiply Halfwords, Odd, Guarded, Signed, Modulo, Integer and Accumulate Negative +PPC_evmhogumiaa, // Vector Multiply Halfwords, Odd, Guarded, Unsigned, Modulo, Integer and Accumulate +PPC_evmhogumian, // Vector Multiply Halfwords, Odd, Guarded, Unsigned, Modulo, Integer and Accumulate Negative +PPC_evmhosmf, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional +PPC_evmhosmfa, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional to Accumulator +PPC_evmhosmfaaw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional and Accumulate into Words +PPC_evmhosmfanw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Fractional and Accumulate Negative into Words +PPC_evmhosmi, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer +PPC_evmhosmia, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer to Accumulator +PPC_evmhosmiaaw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer and Accumulate into Words +PPC_evmhosmianw, // Vector Multiply Halfwords, Odd, Signed, Modulo, Integer and Accumulate Negative into Words +PPC_evmhossf, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional +PPC_evmhossfa, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional to Accumulator +PPC_evmhossfaaw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional and Accumulate into Words +PPC_evmhossfanw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Fractional and Accumulate Negative into Words +PPC_evmhossiaaw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Integer and Accumulate into Words +PPC_evmhossianw, // Vector Multiply Halfwords, Odd, Signed, Saturate, Integer and Accumulate Negative into Words +PPC_evmhoumi, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer +PPC_evmhoumia, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer to Accumulator +PPC_evmhoumiaaw, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer and Accumulate into Words +PPC_evmhoumianw, // Vector Multiply Halfwords, Odd, Unsigned, Modulo, Integer and Accumulate Negative into Words +PPC_evmhousiaaw, // Vector Multiply Halfwords, Odd, Unsigned, Saturate, Integer and Accumulate into Words +PPC_evmhousianw, // Vector Multiply Halfwords, Odd, Unsigned, Saturate, Integer and Accumulate Negative into Words +PPC_evmra, // Initialize Accumulator +PPC_evmwhsmf, // Vector Multiply Word High Signed, Modulo, Fractional +PPC_evmwhsmfa, // Vector Multiply Word High Signed, Modulo, Fractional to Accumulator +PPC_evmwhsmi, // Vector Multiply Word High Signed, Modulo, Integer +PPC_evmwhsmia, // Vector Multiply Word High Signed, Modulo, Integer to Accumulator +PPC_evmwhssf, // Vector Multiply Word High Signed, Saturate, Fractional +PPC_evmwhssfa, // Vector Multiply Word High Signed, Saturate, Fractional to Accumulator +PPC_evmwhumi, // Vector Multiply Word High Unsigned, Modulo, Integer +PPC_evmwhumia, // Vector Multiply Word High Unsigned, Modulo, Integer to Accumulator +PPC_evmwlsmiaaw, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate into Words +PPC_evmwlsmianw, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate Negative in Words +PPC_evmwlssiaaw, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate into Words +PPC_evmwlssianw, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate Negative in Words +PPC_evmwlumi, // Vector Multiply Word Low Unsigned, Modulo, Integer +PPC_evmwlumia, // Vector Multiply Word Low Unsigned, Modulo, Integer to Accumulator +PPC_evmwlumiaaw, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate into Words +PPC_evmwlumianw, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate Negative in Words +PPC_evmwlusiaaw, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate into Words +PPC_evmwlusianw, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate Negative in Words +PPC_evmwsmf, // Vector Multiply Word Signed, Modulo, Fractional +PPC_evmwsmfa, // Vector Multiply Word Signed, Modulo, Fractional to Accumulator +PPC_evmwsmfaa, // Vector Multiply Word Signed, Modulo, Fractional and Accumulate +PPC_evmwsmfan, // Vector Multiply Word Signed, Modulo, Fractional and Accumulate Negative +PPC_evmwsmi, // Vector Multiply Word Signed, Modulo, Integer +PPC_evmwsmia, // Vector Multiply Word Signed, Modulo, Integer to Accumulator +PPC_evmwsmiaa, // Vector Multiply Word Signed, Modulo, Integer and Accumulate +PPC_evmwsmian, // Vector Multiply Word Signed, Modulo, Integer and Accumulate Negative +PPC_evmwssf, // Vector Multiply Word Signed, Saturate, Fractional +PPC_evmwssfa, // Vector Multiply Word Signed, Saturate, Fractional to Accumulator +PPC_evmwssfaa, // Vector Multiply Word Signed, Saturate, Fractional and Accumulate +PPC_evmwssfan, // Vector Multiply Word Signed, Saturate, Fractional and Accumulate Negative +PPC_evmwumi, // Vector Multiply Word Unsigned, Modulo, Integer +PPC_evmwumia, // Vector Multiply Word Unsigned, Modulo, Integer to Accumulator +PPC_evmwumiaa, // Vector Multiply Word Unsigned, Modulo, Integer and Accumulate +PPC_evmwumian, // Vector Multiply Word Unsigned, Modulo, Integer and Accumulate Negative +PPC_evnand, // Vector NAND +PPC_evneg, // Vector Negate +PPC_evnor, // Vector NOR +PPC_evor, // Vector OR +PPC_evorc, // Vector OR with Complement Form +PPC_evrlw, // Vector Rotate Left Word +PPC_evrlwi, // Vector Rotate Left Word Immediate +PPC_evrndw, // Vector Round Word +PPC_evsel, // Vector Select +PPC_evslw, // Vector Shift Left Word +PPC_evslwi, // Vector Shift Left Word Immediate +PPC_evsplatfi, // Vector Splat Fractional Immediate +PPC_evsplati, // Vector Splat Immediate +PPC_evsrwis, // Vector Shift Right Word Immediate Signed +PPC_evsrwiu, // Vector Shift Right Word Immediate Unsigned +PPC_evsrws, // Vector Shift Right Word Signed +PPC_evsrwu, // Vector Shift Right Word Unsigned +PPC_evstdd, // Vector Store Double of Double +PPC_evstddx, // Vector Store Double of Double Indexed +PPC_evstdh, // Vector Store Double of Four Halfwords +PPC_evstdhx, // Vector Store Double of Four Halfwords Indexed +PPC_evstdw, // Vector Store Double of Two Words +PPC_evstdwx, // Vector Store Double of Two Words Indexed +PPC_evstwhe, // Vector Store Word of Two Halfwords from Even +PPC_evstwhex, // Vector Store Word of Two Halfwords from Even Indexed +PPC_evstwho, // Vector Store Word of Two Halfwords from Odd +PPC_evstwhox, // Vector Store Word of Two Halfwords from Odd Indexed +PPC_evstwwe, // Vector Store Word of Word from Even +PPC_evstwwex, // Vector Store Word of Word from Even Indexed +PPC_evstwwo, // Vector Store Word of Word from Odd +PPC_evstwwox, // Vector Store Word of Word from Odd Indexed +PPC_evsubfsmiaaw, // Vector Subtract Signed, Modulo, Integer to Accumulator Word +PPC_evsubfssiaaw, // Vector Subtract Signed, Saturate, Integer to Accumulator Word +PPC_evsubfumiaaw, // Vector Subtract Unsigned, Modulo, Integer to Accumulator Word +PPC_evsubfusiaaw, // Vector Subtract Unsigned, Saturate, Integer to Accumulator Word +PPC_evsubfw, // Vector Subtract from Word +PPC_evsubifw, // Vector Subtract Immediate from Word +PPC_evxor, // Vector XOR + +// SPE.Embedded Float Scalar Double + +PPC_efdabs, // Floating-Point Double-Precision Absolute Value +PPC_efdadd, // Floating-Point Double-Precision Add +PPC_efdcfs, // Floating-Point Double-Precision Convert from Single-Precision +PPC_efdcfsf, // Convert Floating-Point Double-Precision from Signed Fraction +PPC_efdcfsi, // Convert Floating-Point Double-Precision from Signed Integer +PPC_efdcfsid, // Convert Floating-Point Double-Precision from Signed Integer Doubleword +PPC_efdcfuf, // Convert Floating-Point Double-Precision from Unsigned Fraction +PPC_efdcfui, // Convert Floating-Point Double-Precision from Unsigned Integer +PPC_efdcfuid, // Convert Floating-Point Double-Precision from Unsigned Integer Doubleword +PPC_efdcmpeq, // Floating-Point Double-Precision Compare Equal +PPC_efdcmpgt, // Floating-Point Double-Precision Compare Greater Than +PPC_efdcmplt, // Floating-Point Double-Precision Compare Less Than +PPC_efdctsf, // Convert Floating-Point Double-Precision to Signed Fraction +PPC_efdctsi, // Convert Floating-Point Double-Precision to Signed Integer +PPC_efdctsidz, // Convert Floating-Point Double-Precision to Signed Integer Doubleword with Round toward Zero +PPC_efdctsiz, // Convert Floating-Point Double-Precision to Signed Integer with Round toward Zero +PPC_efdctuf, // Convert Floating-Point Double-Precision to Unsigned Fraction +PPC_efdctui, // Convert Floating-Point Double-Precision to Unsigned Integer +PPC_efdctuidz, // Convert Floating-Point Double-Precision to Unsigned Integer Doubleword with Round toward Zero +PPC_efdctuiz, // Convert Floating-Point Double-Precision to Unsigned Integer with Round toward Zero +PPC_efddiv, // Floating-Point Double-Precision Divide +PPC_efdmul, // Floating-Point Double-Precision Multiply +PPC_efdnabs, // Floating-Point Double-Precision Negative Absolute Value +PPC_efdneg, // Floating-Point Double-Precision Negate +PPC_efdsub, // Floating-Point Double-Precision Subtract +PPC_efdtsteq, // Floating-Point Double-Precision Test Equal +PPC_efdtstgt, // Floating-Point Double-Precision Test Greater Than +PPC_efdtstlt, // Floating-Point Double-Precision Test Less Than +PPC_efscfd, // Floating-Point Single-Precision Convert from Double-Precision + +// SPE.Embedded Float Scalar Single + +PPC_efsabs, // Floating-Point Single-Precision Absolute Value +PPC_efsadd, // Floating-Point Single-Precision Add +PPC_efscfsf, // Convert Floating-Point Single-Precision from Signed Fraction +PPC_efscfsi, // Convert Floating-Point Single-Precision from Signed Integer +PPC_efscfuf, // Convert Floating-Point Single-Precision from Unsigned Fraction +PPC_efscfui, // Convert Floating-Point Single-Precision from Unsigned Integer +PPC_efscmpeq, // Floating-Point Single-Precision Compare Equal +PPC_efscmpgt, // Floating-Point Single-Precision Compare Greater Than +PPC_efscmplt, // Floating-Point Single-Precision Compare Less Than +PPC_efsctsf, // Convert Floating-Point Single-Precision to Signed Fraction +PPC_efsctsi, // Convert Floating-Point Single-Precision to Signed Integer +PPC_efsctsiz, // Convert Floating-Point Single-Precision to Signed Integer with Round toward Zero +PPC_efsctuf, // Convert Floating-Point Single-Precision to Unsigned Fraction +PPC_efsctui, // Convert Floating-Point Single-Precision to Unsigned Integer +PPC_efsctuiz, // Convert Floating-Point Single-Precision to Unsigned Integer with Round toward Zero +PPC_efsdiv, // Floating-Point Single-Precision Divide +PPC_efsmul, // Floating-Point Single-Precision Multiply +PPC_efsnabs, // Floating-Point Single-Precision Negative Absolute Value +PPC_efsneg, // Floating-Point Single-Precision Negate +PPC_efssub, // Floating-Point Single-Precision Subtract +PPC_efststeq, // Floating-Point Single-Precision Test Equal +PPC_efststgt, // Floating-Point Single-Precision Test Greater Than +PPC_efststlt, // Floating-Point Single-Precision Test Less Than + +// SPE.Embedded Float Vector + +PPC_evfsabs, // Vector Floating-Point Single-Precision Absolute Value +PPC_evfsadd, // Vector Floating-Point Single-Precision Add +PPC_evfscfsf, // Vector Convert Floating-Point Single-Precision from Signed Fraction +PPC_evfscfsi, // Vector Convert Floating-Point Single-Precision from Signed Integer +PPC_evfscfuf, // Vector Convert Floating-Point Single-Precision from Unsigned Fraction +PPC_evfscfui, // Vector Convert Floating-Point Single-Precision from Unsigned Integer +PPC_evfscmpeq, // Vector Floating-Point Single-Precision Compare Equal +PPC_evfscmpgt, // Vector Floating-Point Single-Precision Compare Greater Than +PPC_evfscmplt, // Vector Floating-Point Single-Precision Compare Less Than +PPC_evfsctsf, // Vector Convert Floating-Point Single-Precision to Signed Fraction +PPC_evfsctsi, // Vector Convert Floating-Point Single-Precision to Signed Integer +PPC_evfsctsiz, // Vector Convert Floating-Point Single-Precision to Signed Integer with Round toward Zero +PPC_evfsctuf, // Vector Convert Floating-Point Single-Precision to Unsigned Fraction +PPC_evfsctui, // Vector Convert Floating-Point Single-Precision to Unsigned Integer +PPC_evfsctuiz, // Vector Convert Floating-Point Single-Precision to Unsigned Integer with Round toward Zero +PPC_evfsdiv, // Vector Floating-Point Single-Precision Divide +PPC_evfsmul, // Vector Floating-Point Single-Precision Multiply +PPC_evfsnabs, // Vector Floating-Point Single-Precision Negative Absolute Value +PPC_evfsneg, // Vector Floating-Point Single-Precision Negate +PPC_evfssub, // Vector Floating-Point Single-Precision Subtract +PPC_evfststeq, // Vector Floating-Point Single-Precision Test Equal +PPC_evfststgt, // Vector Floating-Point Single-Precision Test Greater Than +PPC_evfststlt, // Vector Floating-Point Single-Precision Test Less Than + +// Missing instructions from Power ISA 2.06 + +// category: 64-bit +PPC_bpermd, // Bit Permute Doubleword +PPC_divde, // Divide Doubleword Extended +PPC_divdeu, // Divide Doubleword Extended Unsigned +PPC_ldbrx, // Load Doubleword Byte-Reverse Indexed +PPC_prtyd, // Parity Doubleword +PPC_stdbrx, // Store Doubleword Byte-Reverse Indexed +// category: Base +PPC_cmpb, // Compare Bytes +PPC_divwe, // Divide Word Extended +PPC_divweu, // Divide Word Extended Unsigned +PPC_lbarx, // Load Byte and Reserve Indexed +PPC_lharx, // Load Halfword and Reserve Indexed +PPC_popcntd, // Population Count Doubleword +PPC_popcntw, // Population Count Word +PPC_prtyw, // Parity Word +PPC_stbcx, // Store Byte Conditional Indexed +PPC_sthcx, // Store Halfword Conditional Indexed +// category: Binary Coded Decimal Assist +PPC_addg6s, // Add and Generate Sixes +PPC_cbcdtd, // Convert Binary Coded Decimal to Declets +PPC_cdtbcd, // Convert Declets To Binary Coded Decimal +// category: Decimal Floating-Point +PPC_dadd, // DFP Add +PPC_daddq, // DFP Add Quad +PPC_dcffix, // DFP Convert From Fixed +PPC_dcffixq, // DFP Convert From Fixed Quad +PPC_dcmpo, // DFP Compare Ordered +PPC_dcmpoq, // DFP Compare Ordered Quad +PPC_dcmpu, // DFP Compare Unordered +PPC_dcmpuq, // DFP Compare Unordered Quad +PPC_dctdp, // DFP Convert To DFP Long +PPC_dctfix, // DFP Convert To Fixed +PPC_dctfixq, // DFP Convert To Fixed Quad +PPC_dctqpq, // DFP Convert To DFP Extended +PPC_ddedpd, // DFP Decode DPD To BCD +PPC_ddedpdq, // DFP Decode DPD To BCD Quad +PPC_ddiv, // DFP Divide +PPC_ddivq, // DFP Divide Quad +PPC_denbcd, // DFP Encode BCD To DPD +PPC_denbcdq, // DFP Encode BCD To DPD Quad +PPC_diex, // DFP Insert Biased Exponent +PPC_diexq, // DFP Insert Biased Exponent Quad +PPC_dmul, // DFP Multiply +PPC_dmulq, // DFP Multiply Quad +PPC_dqua, // DFP Quantize +PPC_dquai, // DFP Quantize Immediate +PPC_dquaiq, // DFP Quantize Immediate Quad +PPC_dquaq, // DFP Quantize Quad +PPC_drdpq, // DFP Round To DFP Long +PPC_drintn, // DFP Round To FP Integer Without Inexact +PPC_drintnq, // DFP Round To FP Integer Without Inexact Quad +PPC_drintx, // DFP Round To FP Integer With Inexact +PPC_drintxq, // DFP Round To FP Integer With Inexact Quad +PPC_drrnd, // DFP Reround +PPC_drrndq, // DFP Reround Quad +PPC_drsp, // DFP Round To DFP Short +PPC_dscli, // DFP Shift Significand Left Immediate +PPC_dscliq, // DFP Shift Significand Left Immediate Quad +PPC_dscri, // DFP Shift Significand Right Immediate +PPC_dscriq, // DFP Shift Significand Right Immediate Quad +PPC_dsub, // DFP Subtract +PPC_dsubq, // DFP Subtract Quad +PPC_dtstdc, // DFP Test Data Class +PPC_dtstdcq, // DFP Test Data Class Quad +PPC_dtstdg, // DFP Test Data Group +PPC_dtstdgq, // DFP Test Data Group Quad +PPC_dtstex, // DFP Test Exponent +PPC_dtstexq, // DFP Test Exponent Quad +PPC_dtstsf, // DFP Test Significance +PPC_dtstsfq, // DFP Test Significance Quad +PPC_dxex, // DFP Extract Biased Exponent +PPC_dxexq, // DFP Extract Biased Exponent Quad +// category: Decorated Storage +PPC_dsn, // Decorated Storage Notify +PPC_lbdx, // Load Byte with Decoration Indexed +PPC_lddx, // Load Doubleword with Decoration Indexed +PPC_lfddx, // Load Floating Doubleword with Decoration Indexed +PPC_lhdx, // Load Halfword with Decoration Indexed +PPC_lwdx, // Load Word with Decoration Indexed +PPC_stbdx, // Store Byte with Decoration Indexed +PPC_stddx, // Store Doubleword with Decoration Indexed +PPC_stfddx, // Store Floating Doubleword with Decoration Indexed +PPC_sthdx, // Store Halfword with Decoration Indexed +PPC_stwdx, // Store Word with Decoration Indexed +// category: Embedded +PPC_mbar, // Memory Barrier +PPC_rfmci, // Return From Machine Check Interrupt +PPC_tlbilx, // TLB Invalidate Local +PPC_dci, // Data Cache Invalidate +PPC_ici, // Instruction Cache Invalidate +PPC_mfdcrux, // Move From Device Control Register User-mode Indexed +PPC_mfdcrx, // Move From Device Control Register Indexed +PPC_mtdcrux, // Move To Device Control Register User-mode Indexed +PPC_mtdcrx, // Move To Device Control Register Indexed +// category: Embedded.Enhanced Debug +PPC_dnh, // Debugger Notify Halt +// category: Embedded.Hypervisor +PPC_ehpriv, // Embedded Hypervisor Privilege +PPC_rfgi, // Return From Guest Interrupt +// category: Embedded.Processor Control +PPC_msgclr, // Message Clear +PPC_msgsnd, // Message Send +// category: Embedded.External PID +PPC_dcbfep, // Data Cache Block Flush by External PID +PPC_dcbstep, // Data Cache Block Store by External PID +PPC_dcbtep, // Data Cache Block Touch by External PID +PPC_dcbtstep, // Data Cache Block Touch for Store by External PID +PPC_dcbzep, // Data Cache Block set to Zero by External PID +PPC_evlddepx, // Vector Load Doubleword into Doubleword by External Process ID Indexed +PPC_evstddepx, // Vector Store Doubleword into Doubleword by External Process ID Indexed +PPC_icbiep, // Instruction Cache Block Invalidate by External PID +PPC_lbepx, // Load Byte by External Process ID Indexed +PPC_lfdepx, // Load Floating-Point Double by External Process ID Indexed +PPC_lhepx, // Load Halfword by External Process ID Indexed +PPC_lvepx, // Load Vector by External Process ID Indexed +PPC_lvepxl, // Load Vector by External Process ID Indexed LRU +PPC_lwepx, // Load Word by External Process ID Indexed +PPC_stbepx, // Store Byte by External Process ID Indexed +PPC_stfdepx, // Store Floating-Point Double by External Process ID Indexed +PPC_sthepx, // Store Halfword by External Process ID Indexed +PPC_stvepx, // Store Vector by External Process ID Indexed +PPC_stvepxl, // Store Vector by External Process ID Indexed LRU +PPC_stwepx, // Store Word by External Process ID Indexed +PPC_ldepx, // Load Doubleword by External Process ID Indexed +PPC_stdepx, // Store Doubleword by External Process ID Indexed +// category: Embedded.Performance Monitor +PPC_mfpmr, // Move From Performance Monitor Register +PPC_mtpmr, // Move To Performance Monitor Register +// category: Embedded.Thread Management +PPC_mftmr, // Move From Thread Management Register +PPC_mttmr, // Move To Thread Management Register +// category: Embedded.TLB Write Conditional +PPC_tlbsrx, // TLB Search and Reserve +// category: Floating-point +PPC_fcfids, // Floating Convert From Integer Doubleword Single +PPC_fcfidu, // Floating Convert From Integer Doubleword Unsigned +PPC_fcfidus, // Floating Convert From Integer Doubleword Unsigned Single +PPC_fctidu, // Floating Convert To Integer Doubleword Unsigned +PPC_fctiduz, // Floating Convert To Integer Doubleword Unsigned with round toward Zero +PPC_fctiwu, // Floating Convert To Integer Word Unsigned +PPC_fctiwuz, // Floating Convert To Integer Word Unsigned with round toward Zero +PPC_ftdiv, // Floating Test for software Divide +PPC_ftsqrt, // Floating Test for software Square Root +PPC_lfiwax, // Load Floating-Point as Integer Word Algebraic Indexed +PPC_lfiwzx, // Load Floating-Point as Integer Word and Zero Indexed +PPC_lfdp, // Load Floating-Point Double Pair +PPC_lfdpx, // Load Floating-Point Double Pair Indexed +PPC_stfdp, // Store Floating-Point Double Pair +PPC_stfdpx, // Store Floating-Point Double Pair Indexed +PPC_fcpsgn, // Floating Copy Sign +PPC_fre, // Floating Reciprocal Estimate +PPC_frim, // Floating Round to Integer Minus +PPC_frin, // Floating Round to Integer Nearest +PPC_frip, // Floating Round to Integer Plus +PPC_friz, // Floating Round to Integer Toward Zero +// category: Legacy Integer Multiply-Accumulate +PPC_macchw, // Multiply Accumulate Cross Halfword to Word Modulo Signed +PPC_macchws, // Multiply Accumulate Cross Halfword to Word Saturate Signed +PPC_macchwsu, // Multiply Accumulate Cross Halfword to Word Saturate Unsigned +PPC_macchwu, // Multiply Accumulate Cross Halfword to Word Modulo Unsigned +PPC_machhw, // Multiply Accumulate High Halfword to Word Modulo Signed +PPC_machhws, // Multiply Accumulate High Halfword to Word Saturate Signed +PPC_machhwsu, // Multiply Accumulate High Halfword to Word Saturate Unsigned +PPC_machhwu, // Multiply Accumulate High Halfword to Word Modulo Unsigned +PPC_maclhw, // Multiply Accumulate Low Halfword to Word Modulo Signed +PPC_maclhws, // Multiply Accumulate Low Halfword to Word Saturate Signed +PPC_maclhwsu, // Multiply Accumulate Low Halfword to Word Saturate Unsigned +PPC_maclhwu, // Multiply Accumulate Low Halfword to Word Modulo Unsigned +PPC_mulchw, // Multiply Cross Halfword to Word Signed +PPC_mulchwu, // Multiply Cross Halfword to Word Unsigned +PPC_mulhhw, // Multiply High Halfword to Word Signed +PPC_mulhhwu, // Multiply High Halfword to Word Unsigned +PPC_mullhw, // Multiply Low Halfword to Word Signed +PPC_mullhwu, // Multiply Low Halfword to Word Unsigned +PPC_nmacchw, // Negative Multiply Accumulate Cross Halfword to Word Modulo Signed +PPC_nmacchws, // Negative Multiply Accumulate Cross Halfword to Word Saturate Signed +PPC_nmachhw, // Negative Multiply Accumulate High Halfword to Word Modulo Signed +PPC_nmachhws, // Negative Multiply Accumulate High Halfword to Word Saturate Signed +PPC_nmaclhw, // Negative Multiply Accumulate Low Halfword to Word Modulo Signed +PPC_nmaclhws, // Negative Multiply Accumulate Low Halfword to Word Saturate Signed +// category: Legacy Move Assist +PPC_dlmzb, // Determine Leftmost Zero Byte +// category: Load/Store Quadword +PPC_lq, // Load Quadword +PPC_stq, // Store Quadword +// category: Server +PPC_doze, // Doze +PPC_lbzcix, // Load Byte and Zero Caching Inhibited Indexed +PPC_ldcix, // Load Doubleword Caching Inhibited Indexed +PPC_lhzcix, // Load Halfword and Zero Caching Inhibited Indexed +PPC_lwzcix, // Load Word and Zero Caching Inhibited Indexed +PPC_nap, // Nap +PPC_rvwinkle, // Rip Van Winkle +PPC_slbfee, // SLB Find Entry ESID +PPC_sleep, // Sleep +PPC_stbcix, // Store Byte Caching Inhibited Indexed +PPC_stdcix, // Store Doubleword Caching Inhibited Indexed +PPC_sthcix, // Store Halfword Caching Inhibited Indexed +PPC_stwcix, // Store Word Caching Inhibited Indexed +PPC_tlbiel, // TLB Invalidate Entry Local, ISA 3.0 format +// category: Vector +PPC_lvebx, // Load Vector Element Byte Indexed +PPC_lvehx, // Load Vector Element Halfword Indexed +PPC_lvewx, // Load Vector Element Word Indexed +PPC_lvsl, // Load Vector for Shift Left Indexed +PPC_lvsr, // Load Vector for Shift Right Indexed +PPC_lvx, // Load Vector Indexed +PPC_lvxl, // Load Vector Indexed LRU +PPC_mfvscr, // Move From Vector Status and Control Register +PPC_mtvscr, // Move To Vector Status and Control Register +PPC_stvebx, // Store Vector Element Byte Indexed +PPC_stvehx, // Store Vector Element Halfword Indexed +PPC_stvewx, // Store Vector Element Word Indexed +PPC_stvx, // Store Vector Indexed +PPC_stvxl, // Store Vector Indexed LRU +PPC_vaddcuw, // Vector Add and Write Carry-Out Unsigned Word +PPC_vaddfp, // Vector Add Single-Precision +PPC_vaddsbs, // Vector Add Signed Byte Saturate +PPC_vaddshs, // Vector Add Signed Halfword Saturate +PPC_vaddsws, // Vector Add Signed Word Saturate +PPC_vaddubm, // Vector Add Unsigned Byte Modulo +PPC_vaddubs, // Vector Add Unsigned Byte Saturate +PPC_vadduhm, // Vector Add Unsigned Halfword Modulo +PPC_vadduhs, // Vector Add Unsigned Halfword Saturate +PPC_vadduwm, // Vector Add Unsigned Word Modulo +PPC_vadduws, // Vector Add Unsigned Word Saturate +PPC_vand, // Vector Logical AND +PPC_vandc, // Vector Logical AND with Complement +PPC_vavgsb, // Vector Average Signed Byte +PPC_vavgsh, // Vector Average Signed Halfword +PPC_vavgsw, // Vector Average Signed Word +PPC_vavgub, // Vector Average Unsigned Byte +PPC_vavguh, // Vector Average Unsigned Halfword +PPC_vavguw, // Vector Average Unsigned Word +PPC_vcfsx, // Vector Convert From Signed Fixed-Point Word +PPC_vcfux, // Vector Convert From Unsigned Fixed-Point Word +PPC_vcmpbfp, // Vector Compare Bounds Single-Precision +PPC_vcmpeqfp, // Vector Compare Equal To Single-Precision +PPC_vcmpequb, // Vector Compare Equal To Unsigned Byte +PPC_vcmpequh, // Vector Compare Equal To Unsigned Halfword +PPC_vcmpequw, // Vector Compare Equal To Unsigned Word +PPC_vcmpgefp, // Vector Compare Greater Than or Equal To Single-Precision +PPC_vcmpgtfp, // Vector Compare Greater Than Single-Precision +PPC_vcmpgtsb, // Vector Compare Greater Than Signed Byte +PPC_vcmpgtsh, // Vector Compare Greater Than Signed Halfword +PPC_vcmpgtsw, // Vector Compare Greater Than Signed Word +PPC_vcmpgtub, // Vector Compare Greater Than Unsigned Byte +PPC_vcmpgtuh, // Vector Compare Greater Than Unsigned Halfword +PPC_vcmpgtuw, // Vector Compare Greater Than Unsigned Word +PPC_vctsxs, // Vector Convert To Signed Fixed-Point Word Saturate +PPC_vctuxs, // Vector Convert To Unsigned Fixed-Point Word Saturate +PPC_vexptefp, // Vector 2 Raised to the Exponent Estimate FloatingPoint +PPC_vlogefp, // Vector Log Base 2 Estimate Floating-Point +PPC_vmaddfp, // Vector Multiply-Add Single-Precision +PPC_vmaxfp, // Vector Maximum Single-Precision +PPC_vmaxsb, // Vector Maximum Signed Byte +PPC_vmaxsh, // Vector Maximum Signed Halfword +PPC_vmaxsw, // Vector Maximum Signed Word +PPC_vmaxub, // Vector Maximum Unsigned Byte +PPC_vmaxuh, // Vector Maximum Unsigned Halfword +PPC_vmaxuw, // Vector Maximum Unsigned Word +PPC_vmhaddshs, // Vector Multiply-High-Add Signed Halfword Saturate +PPC_vmhraddshs, // Vector Multiply-High-Round-Add Signed Halfword Saturate +PPC_vminfp, // Vector Minimum Single-Precision +PPC_vminsb, // Vector Minimum Signed Byte +PPC_vminsh, // Vector Minimum Signed Halfword +PPC_vminsw, // Vector Minimum Signed Word +PPC_vminub, // Vector Minimum Unsigned Byte +PPC_vminuh, // Vector Minimum Unsigned Halfword +PPC_vminuw, // Vector Minimum Unsigned Word +PPC_vmladduhm, // Vector Multiply-Low-Add Unsigned Halfword Modulo +PPC_vmrghb, // Vector Merge High Byte +PPC_vmrghh, // Vector Merge High Halfword +PPC_vmrghw, // Vector Merge High Word +PPC_vmrglb, // Vector Merge Low Byte +PPC_vmrglh, // Vector Merge Low Halfword +PPC_vmrglw, // Vector Merge Low Word +PPC_vmsummbm, // Vector Multiply-Sum Mixed Byte Modulo +PPC_vmsumshm, // Vector Multiply-Sum Signed Halfword Modulo +PPC_vmsumshs, // Vector Multiply-Sum Signed Halfword Saturate +PPC_vmsumubm, // Vector Multiply-Sum Unsigned Byte Modulo +PPC_vmsumuhm, // Vector Multiply-Sum Unsigned Halfword Modulo +PPC_vmsumuhs, // Vector Multiply-Sum Unsigned Halfword Saturate +PPC_vmulesb, // Vector Multiply Even Signed Byte +PPC_vmulesh, // Vector Multiply Even Signed Halfword +PPC_vmuleub, // Vector Multiply Even Unsigned Byte +PPC_vmuleuh, // Vector Multiply Even Unsigned Halfword +PPC_vmulosb, // Vector Multiply Odd Signed Byte +PPC_vmulosh, // Vector Multiply Odd Signed Halfword +PPC_vmuloub, // Vector Multiply Odd Unsigned Byte +PPC_vmulouh, // Vector Multiply Odd Unsigned Halfword +PPC_vnmsubfp, // Vector Negative Multiply-Subtract Single-Precision +PPC_vnor, // Vector Logical NOR +PPC_vor, // Vector Logical OR +PPC_vperm, // Vector Permute +PPC_vpkpx, // Vector Pack Pixel +PPC_vpkshss, // Vector Pack Signed Halfword Signed Saturate +PPC_vpkshus, // Vector Pack Signed Halfword Unsigned Saturate +PPC_vpkswss, // Vector Pack Signed Word Signed Saturate +PPC_vpkswus, // Vector Pack Signed Word Unsigned Saturate +PPC_vpkuhum, // Vector Pack Unsigned Halfword Unsigned Modulo +PPC_vpkuhus, // Vector Pack Unsigned Halfword Unsigned Saturate +PPC_vpkuwum, // Vector Pack Unsigned Word Unsigned Modulo +PPC_vpkuwus, // Vector Pack Unsigned Word Unsigned Saturate +PPC_vrefp, // Vector Reciprocal Estimate Single-Precision +PPC_vrfim, // Vector Round to Single-Precision Integer toward -Infinity +PPC_vrfin, // Vector Round to Single-Precision Integer Nearest +PPC_vrfip, // Vector Round to Single-Precision Integer toward +Infinity +PPC_vrfiz, // Vector Round to Single-Precision Integer toward Zero +PPC_vrlb, // Vector Rotate Left Byte +PPC_vrlh, // Vector Rotate Left Halfword +PPC_vrlw, // Vector Rotate Left Word +PPC_vrsqrtefp, // Vector Reciprocal Square Root Estimate Single-Precision +PPC_vsel, // Vector Select +PPC_vsl, // Vector Shift Left +PPC_vslb, // Vector Shift Left Byte +PPC_vsldoi, // Vector Shift Left Double by Octet Immediate +PPC_vslh, // Vector Shift Left Halfword +PPC_vslo, // Vector Shift Left by Octet +PPC_vslw, // Vector Shift Left Word +PPC_vspltb, // Vector Splat Byte +PPC_vsplth, // Vector Splat Halfword +PPC_vspltisb, // Vector Splat Immediate Signed Byte +PPC_vspltish, // Vector Splat Immediate Signed Halfword +PPC_vspltisw, // Vector Splat Immediate Signed Word +PPC_vspltw, // Vector Splat Word +PPC_vsr, // Vector Shift Right +PPC_vsrab, // Vector Shift Right Algebraic Byte +PPC_vsrah, // Vector Shift Right Algebraic Halfword +PPC_vsraw, // Vector Shift Right Algebraic Word +PPC_vsrb, // Vector Shift Right Byte +PPC_vsrh, // Vector Shift Right Halfword +PPC_vsro, // Vector Shift Right by Octet +PPC_vsrw, // Vector Shift Right Word +PPC_vsubcuw, // Vector Subtract and Write Carry-Out Unsigned Word +PPC_vsubfp, // Vector Subtract Single-Precision +PPC_vsubsbs, // Vector Subtract Signed Byte Saturate +PPC_vsubshs, // Vector Subtract Signed Halfword Saturate +PPC_vsubsws, // Vector Subtract Signed Word Saturate +PPC_vsububm, // Vector Subtract Unsigned Byte Modulo +PPC_vsububs, // Vector Subtract Unsigned Byte Saturate +PPC_vsubuhm, // Vector Subtract Unsigned Halfword Modulo +PPC_vsubuhs, // Vector Subtract Unsigned Halfword Saturate +PPC_vsubuwm, // Vector Subtract Unsigned Word Modulo +PPC_vsubuws, // Vector Subtract Unsigned Word Saturate +PPC_vsum2sws, // Vector Sum across Half Signed Word Saturate +PPC_vsum4sbs, // Vector Sum across Quarter Signed Byte Saturate +PPC_vsum4shs, // Vector Sum across Quarter Signed Halfword Saturate +PPC_vsum4ubs, // Vector Sum across Quarter Unsigned Byte Saturate +PPC_vsumsws, // Vector Sum across Signed Word Saturate +PPC_vupkhpx, // Vector Unpack High Pixel +PPC_vupkhsb, // Vector Unpack High Signed Byte +PPC_vupkhsh, // Vector Unpack High Signed Halfword +PPC_vupklpx, // Vector Unpack Low Pixel +PPC_vupklsb, // Vector Unpack Low Signed Byte +PPC_vupklsh, // Vector Unpack Low Signed Halfword +PPC_vxor, // Vector Logical XOR +// category: Vector-Scalar Floating-Point +PPC_lxsdx, // Load VSR Scalar Doubleword Indexed +PPC_lxvd2x, // Load VSR Vector Doubleword*2 Indexed +PPC_lxvdsx, // Load VSR Vector Doubleword & Splat Indexed +PPC_lxvw4x, // Load VSR Vector Word*4 Indexed +PPC_stxsdx, // Store VSR Scalar Doubleword Indexed +PPC_stxvd2x, // Store VSR Vector Doubleword*2 Indexed +PPC_stxvw4x, // Store VSR Vector Word*4 Indexed +PPC_xsabsdp, // VSX Scalar Absolute Value Double-Precision +PPC_xsadddp, // VSX Scalar Add Double-Precision +PPC_xscmpodp, // VSX Scalar Compare Ordered Double-Precision +PPC_xscmpudp, // VSX Scalar Compare Unordered Double-Precision +PPC_xscpsgndp, // VSX Scalar Copy Sign Double-Precision +PPC_xscvdpsp, // VSX Scalar Convert Double-Precision to SinglePrecision +PPC_xscvdpsxds, // VSX Scalar truncate Double-Precision to integer and Convert to Signed Fixed-Point Doubleword format with Saturate +PPC_xscvdpsxws, // VSX Scalar truncate Double-Precision to integer and Convert to Signed Fixed-Point Word format with Saturate +PPC_xscvdpuxds, // VSX Scalar truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Doubleword format with Saturate +PPC_xscvdpuxws, // VSX Scalar truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Word format with Saturate +PPC_xscvspdp, // VSX Scalar Convert Single-Precision to DoublePrecision format +PPC_xscvsxddp, // VSX Scalar Convert and round Signed Fixed-Point Doubleword to Double-Precision format +PPC_xscvuxddp, // VSX Scalar Convert and round Unsigned Fixed-Point Doubleword to Double-Precision format +PPC_xsdivdp, // VSX Scalar Divide Double-Precision +PPC_xsmaddadp, // VSX Scalar Multiply-Add Type-A Double-Precision +PPC_xsmaddmdp, // VSX Scalar Multiply-Add Type-M Double-Precision +PPC_xsmaxdp, // VSX Scalar Maximum Double-Precision +PPC_xsmindp, // VSX Scalar Minimum Double-Precision +PPC_xsmsubadp, // VSX Scalar Multiply-Subtract Type-A Double-Precision +PPC_xsmsubmdp, // VSX Scalar Multiply-Subtract Type-M Double-Precision +PPC_xsmuldp, // VSX Scalar Multiply Double-Precision +PPC_xsnabsdp, // VSX Scalar Negative Absolute Value Double-Precision +PPC_xsnegdp, // VSX Scalar Negate Double-Precision +PPC_xsnmaddadp, // VSX Scalar Negative Multiply-Add Type-A DoublePrecision +PPC_xsnmaddmdp, // VSX Scalar Negative Multiply-Add Type-M DoublePrecision +PPC_xsnmsubadp, // VSX Scalar Negative Multiply-Subtract Type-A DoublePrecision +PPC_xsnmsubmdp, // VSX Scalar Negative Multiply-Subtract Type-M DoublePrecision +PPC_xsrdpi, // VSX Scalar Round to Double-Precision Integer +PPC_xsrdpic, // VSX Scalar Round to Double-Precision Integer using Current rounding mode +PPC_xsrdpim, // VSX Scalar Round to Double-Precision Integer toward Infinity +PPC_xsrdpip, // VSX Scalar Round to Double-Precision Integer toward + Infinity +PPC_xsrdpiz, // VSX Scalar Round to Double-Precision Integer toward Zero +PPC_xsredp, // VSX Scalar Reciprocal Estimate Double-Precision +PPC_xsrsqrtedp, // VSX Scalar Reciprocal Square Root Estimate DoublePrecision +PPC_xssqrtdp, // VSX Scalar Square Root Double-Precision +PPC_xssubdp, // VSX Scalar Subtract Double-Precision +PPC_xstdivdp, // VSX Scalar Test for software Divide Double-Precision +PPC_xstsqrtdp, // VSX Scalar Test for software Square Root DoublePrecision +PPC_xvabsdp, // VSX Vector Absolute Value Double-Precision +PPC_xvabssp, // VSX Vector Absolute Value Single-Precision +PPC_xvadddp, // VSX Vector Add Double-Precision +PPC_xvaddsp, // VSX Vector Add Single-Precision +PPC_xvcmpeqdp, // VSX Vector Compare Equal To Double-Precision +PPC_xvcmpeqsp, // VSX Vector Compare Equal To Single-Precision +PPC_xvcmpgedp, // VSX Vector Compare Greater Than or Equal To Double-Precision +PPC_xvcmpgesp, // VSX Vector Compare Greater Than or Equal To SinglePrecision +PPC_xvcmpgtdp, // VSX Vector Compare Greater Than Double-Precision +PPC_xvcmpgtsp, // VSX Vector Compare Greater Than Single-Precision +PPC_xvcpsgndp, // VSX Vector Copy Sign Double-Precision +PPC_xvcpsgnsp, // VSX Vector Copy Sign Single-Precision +PPC_xvcvdpsp, // VSX Vector round and Convert Double-Precision to Single-Precision format +PPC_xvcvdpsxds, // VSX Vector truncate Double-Precision to integer and Convert to Signed Fixed-Point Doubleword Saturate +PPC_xvcvdpsxws, // VSX Vector truncate Double-Precision to integer and Convert to Signed Fixed-Point Word Saturate +PPC_xvcvdpuxds, // VSX Vector truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Doubleword format with Saturate +PPC_xvcvdpuxws, // VSX Vector truncate Double-Precision to integer and Convert to Unsigned Fixed-Point Word format with Saturate +PPC_xvcvspdp, // VSX Vector Convert Single-Precision to DoublePrecision +PPC_xvcvspsxds, // VSX Vector truncate Single-Precision to integer and Convert to Signed Fixed-Point Doubleword format with Saturate +PPC_xvcvspsxws, // VSX Vector truncate Single-Precision to integer and Convert to Signed Fixed-Point Word format with Saturate +PPC_xvcvspuxds, // VSX Vector truncate Single-Precision to integer and Convert to Unsigned Fixed-Point Doubleword format with Saturate +PPC_xvcvspuxws, // VSX Vector truncate Single-Precision to integer and Convert to Unsigned Fixed-Point Word Saturate +PPC_xvcvsxddp, // VSX Vector Convert and round Signed Fixed-Point Doubleword to Double-Precision format +PPC_xvcvsxdsp, // VSX Vector Convert and round Signed Fixed-Point Doubleword to Single-Precision format +PPC_xvcvsxwdp, // VSX Vector Convert Signed Fixed-Point Word to Double-Precision format +PPC_xvcvsxwsp, // VSX Vector Convert and round Signed Fixed-Point Word to Single-Precision format +PPC_xvcvuxddp, // VSX Vector Convert and round Unsigned Fixed-Point Doubleword to Double-Precision format +PPC_xvcvuxdsp, // VSX Vector Convert and round Unsigned Fixed-Point Doubleword to Single-Precision format +PPC_xvcvuxwdp, // VSX Vector Convert Unsigned Fixed-Point Word to Double-Precision format +PPC_xvcvuxwsp, // VSX Vector Convert and round Unsigned Fixed-Point Word to Single-Precision format +PPC_xvdivdp, // VSX Vector Divide Double-Precision +PPC_xvdivsp, // VSX Vector Divide Single-Precision +PPC_xvmaddadp, // VSX Vector Multiply-Add Type-A Double-Precision +PPC_xvmaddasp, // VSX Vector Multiply-Add Type-A Single-Precision +PPC_xvmaddmdp, // VSX Vector Multiply-Add Type-M Double-Precision +PPC_xvmaddmsp, // VSX Vector Multiply-Add Type-M Single-Precision +PPC_xvmaxdp, // VSX Vector Maximum Double-Precision +PPC_xvmaxsp, // VSX Vector Maximum Single-Precision +PPC_xvmindp, // VSX Vector Minimum Double-Precision +PPC_xvminsp, // VSX Vector Minimum Single-Precision +PPC_xvmsubadp, // VSX Vector Multiply-Subtract Type-A Double-Precision +PPC_xvmsubasp, // VSX Vector Multiply-Subtract Type-A Single-Precision +PPC_xvmsubmdp, // VSX Vector Multiply-Subtract Type-M Double-Precision +PPC_xvmsubmsp, // VSX Vector Multiply-Subtract Type-M Single-Precision +PPC_xvmuldp, // VSX Vector Multiply Double-Precision +PPC_xvmulsp, // VSX Vector Multiply Single-Precision +PPC_xvnabsdp, // VSX Vector Negative Absolute Value Double-Precision +PPC_xvnabssp, // VSX Vector Negative Absolute Value Single-Precision +PPC_xvnegdp, // VSX Vector Negate Double-Precision +PPC_xvnegsp, // VSX Vector Negate Single-Precision +PPC_xvnmaddadp, // VSX Vector Negative Multiply-Add Type-A DoublePrecision +PPC_xvnmaddasp, // VSX Vector Negative Multiply-Add Type-A SinglePrecision +PPC_xvnmaddmdp, // VSX Vector Negative Multiply-Add Type-M DoublePrecision +PPC_xvnmaddmsp, // VSX Vector Negative Multiply-Add Type-M SinglePrecision +PPC_xvnmsubadp, // VSX Vector Negative Multiply-Subtract Type-A DoublePrecision +PPC_xvnmsubasp, // VSX Vector Negative Multiply-Subtract Type-A SinglePrecision +PPC_xvnmsubmdp, // VSX Vector Negative Multiply-Subtract Type-M DoublePrecision +PPC_xvnmsubmsp, // VSX Vector Negative Multiply-Subtract Type-M SinglePrecision +PPC_xvrdpi, // VSX Vector Round to Double-Precision Integer +PPC_xvrdpic, // VSX Vector Round to Double-Precision Integer using Current rounding mode +PPC_xvrdpim, // VSX Vector Round to Double-Precision Integer toward Infinity +PPC_xvrdpip, // VSX Vector Round to Double-Precision Integer toward + Infinity +PPC_xvrdpiz, // VSX Vector Round to Double-Precision Integer toward Zero +PPC_xvredp, // VSX Vector Reciprocal Estimate Double-Precision +PPC_xvresp, // VSX Vector Reciprocal Estimate Single-Precision +PPC_xvrspi, // VSX Vector Round to Single-Precision Integer +PPC_xvrspic, // VSX Vector Round to Single-Precision Integer using Current rounding mode +PPC_xvrspim, // VSX Vector Round to Single-Precision Integer toward Infinity +PPC_xvrspip, // VSX Vector Round to Single-Precision Integer toward + Infinity +PPC_xvrspiz, // VSX Vector Round to Single-Precision Integer toward Zero +PPC_xvrsqrtedp, // VSX Vector Reciprocal Square Root Estimate DoublePrecision +PPC_xvrsqrtesp, // VSX Vector Reciprocal Square Root Estimate SinglePrecision +PPC_xvsqrtdp, // VSX Vector Square Root Double-Precision +PPC_xvsqrtsp, // VSX Vector Square Root Single-Precision +PPC_xvsubdp, // VSX Vector Subtract Double-Precision +PPC_xvsubsp, // VSX Vector Subtract Single-Precision +PPC_xvtdivdp, // VSX Vector Test for software Divide Double-Precision +PPC_xvtdivsp, // VSX Vector Test for software Divide Single-Precision +PPC_xvtsqrtdp, // VSX Vector Test for software Square Root DoublePrecision +PPC_xvtsqrtsp, // VSX Vector Test for software Square Root SinglePrecision +PPC_xxland, // VSX Logical AND +PPC_xxlandc, // VSX Logical AND with Complement +PPC_xxlnor, // VSX Logical NOR +PPC_xxlor, // VSX Logical OR +PPC_xxlxor, // VSX Logical XOR +PPC_xxmrghw, // VSX Merge High Word +PPC_xxmrglw, // VSX Merge Low Word +PPC_xxpermdi, // VSX Permute Doubleword Immediate +PPC_xxsel, // VSX Select +PPC_xxsldwi, // VSX Shift Left Double by Word Immediate +PPC_xxspltw, // VSX Splat Word +// category: Wait +PPC_wait, // Wait + +// Obsolete AltiVec instructions + +PPC_dss, // Data Stream Stop +PPC_dssall, // Data Stream Stop All +PPC_dst, // Data Stream Touch +PPC_dstt, // Data Stream Touch Transient +PPC_dstst, // Data Stream Touch for Store +PPC_dststt, // Data Stream Touch for Store Transient + +// Cell BE AltiVec extension +PPC_lvlx, // Load Vector Left Indexed +PPC_lvlxl, // Load Vector Left Indexed Last +PPC_lvrx, // Load Vector Right Indexed +PPC_lvrxl, // Load Vector Right Indexed Last +PPC_stvlx, // Store Vector Left Indexed +PPC_stvlxl, // Store Vector Left Indexed Last +PPC_stvrx, // Store Vector Right Indexed +PPC_stvrxl, // Store Vector Right Indexed Last + +// VLE instructions that don't have matching mnemonics +PPC_add16i, // [e_add16i] Add Immediate +PPC_add2i, // [e_add2i] Add (2 operand) Immediate and Record +PPC_add2is, // [e_add2is] Add (2 operand) Immediate Shifted +PPC_and2i, // [e_and2i] AND (two operand) Immediate +PPC_and2is, // [e_and2is] AND (2 operand) Immediate Shifted +PPC_cmp16i, // [e_cmp16i] Compare Immediate Word +PPC_cmph, // [e_cmph] Compare Halfword +PPC_cmph16i, // [e_cmph16i] Compare Halfword Immediate +PPC_cmphl, // [e_cmphl] Compare Halfword Logical +PPC_cmphl16i, // [e_cmphl16i] Compare Halfword Logical Immediate +PPC_cmpl16i, // [e_cmpl16i] Compare Logical Immediate Word +PPC_mull2i, // [e_mull2i] Multiply (2 operand) Low Immediate +PPC_or2i, // [e_or2i] OR (two operand) Immediate +PPC_or2is, // [e_or2is] OR (2 operand) Immediate Shifted +PPC_rlw, // [e_rlw] Rotate Left Word +PPC_rlwi, // [e_rlwi] Rotate Left Word Immediate +PPC_bclri, // [se_bclri] Bit Clear Immediate +// PPC_bctr, // [se_bctr] Branch to Count Register +// PPC_bctrl, // [se_bctrl] Branch to Count Register and Link +PPC_bgeni, // [se_bgeni] Bit Generate Immediate +PPC_bmaski, // [se_bmaski] Bit Mask Generate Immediate +PPC_bseti, // [se_bseti] Bit Set Immediate +PPC_btsti, // [se_btsti] Bit Test Immediate +PPC_extzb, // [se_extzb] Extend Zero Byte +PPC_extzh, // [se_extzh] Extend Zero Halfword +PPC_illegal, // [se_illegal] Illegal +PPC_mfar, // [se_mfar] Move from Alternate Register +PPC_mtar, // [se_mtar] Move To Alternate Register +PPC_sub, // [se_sub] Subtract +// simplified VLE mnemonics +PPC_sub16i, // [e_sub16i] Subtract Immediate +PPC_sub2i, // [e_sub2i] Subtract (2 operand) Immediate +PPC_sub2is, // [e_sub2is] Subtract (2 operand) Immediate Shifted + +// misc extended mnemonics +PPC_extldi, // Extract and Left Justify Immediate +PPC_extrdi, // Extract and Right Justify Immediate +PPC_insrdi, // Insert from Right Immediate +PPC_rotldi, // Rotate Left Immediate +PPC_rotrdi, // Rotate Right Immediate +PPC_rotld, // Rotate Left +PPC_sldi, // Shift Left Immediate +PPC_srdi, // Shift Right Immediate +PPC_clrldi, // Clear Left Immediate +PPC_clrrdi, // Clear Right Immediate +PPC_clrlsldi, // Clear Left and Shift Left Immediate + +PPC_xnop, // Extended No Operation +PPC_hnop, // Reserved no-op hint +PPC_dcbfl, // Data Cache Block Flush Local +PPC_dcbflp, // Data Cache Block Flush Local Primary +PPC_dcbtt, // Data Cache Block Touch +PPC_dcbtstt, // Data Cache Block Touch for Store +PPC_lwsync, // Lightweight Sync +PPC_ptesync, // Page Table Entry Sync +PPC_waitrsv, // Wait For Reservation Loss +PPC_waitimpl, // Wait For Implementation-specific Condition +PPC_evmr, // Vector Move +PPC_evnot, // Vector Not +PPC_mtcr, // Move to Condition Register +PPC_xvmovdp, // VSX Vector Copy Double-Precision +PPC_xvmovsp, // VSX Vector Copy Single-Precision +PPC_xxspltd, // VSX Splat Doubleword +PPC_xxmrghd, // VSX Merge High Doubleword +PPC_xxmrgld, // VSX Merge Low Doubleword +PPC_xxswapd, // VSX Swap Doubleword + +// Xbox 360 specific +PPC_dcbz128, // Data Cache Block Clear to Zero (128 bytes) +PPC_mtmsree, // Move to Machine State Register EE + +// new Xbox 360 instructions (VMX128) +PPC_vcfpsxws, // Vector Convert From Single-Precision to Signed Fixed-point Word Saturate +PPC_vcfpuxws, // Vector Convert From Single-Precision to Unsigned Fixed-point Word Saturate +PPC_vcsxwfp, // Vector Convert from Signed Fixed-point Word to Single-Precision +PPC_vcuxwfp, // Vector Convert from Unsigned Fixed-point Word to Single-Precision +PPC_vmaddcfp, // Vector Convert from Unsigned Fixed-point Word to Single-Precision +PPC_vmsum3fp, // Vector Multiply-Sum 3-way Single-Precision +PPC_vmsum4fp, // Vector Multiply-Sum 4-way Single-Precision +PPC_vmulfp, // Vector Multiply Single-Precision +PPC_vpermwi, // Vector Permute Word Immediate +PPC_vpkd3d, // Vector Pack D3Dtype, Rotate Left Immediate and Mask Insert +PPC_vrlimi, // Vector Rotate Left Immediate and Mask Insert +PPC_vupkd3d, // Vector Unpack D3Dtype + +// Paired Singles (750CL/Gekko/Broadway) +PPC_ps_cmpu0, // Paired Single Compare Unordered High +PPC_psq_lx, // Paired Single Quantized Load Indexed +PPC_psq_stx, // Paired Single Quantized Store Indexed +PPC_ps_sum0, // Paired Single Vector Sum High +PPC_ps_sum1, // Paired Single Vector Sum Low +PPC_ps_muls0, // Paired Single Multiply Scalar High +PPC_ps_muls1, // Paired Single Multiply Scalar Low +PPC_ps_madds0, // Paired Single Multiply-Add Scalar High +PPC_ps_madds1, // Paired Single Multiply-Add Scalar Low +PPC_ps_div, // Paired Single Divide +PPC_ps_sub, // Paired Single Subtract +PPC_ps_add, // Paired Single Add +PPC_ps_sel, // Paired Single Select +PPC_ps_res, // Paired Single Reciprocal Estimate +PPC_ps_mul, // Paired Single Multiply +PPC_ps_rsqrte, // Paired Single Reciprocal Square Root Estimate +PPC_ps_msub, // Paired Single Multiply-Subtract +PPC_ps_madd, // Paired Single Multiply-Add +PPC_ps_nmsub, // Paired Single Negative Multiply-Subtract +PPC_ps_nmadd, // Paired Single Negative Multiply-Add +PPC_ps_cmpo0, // Paired Single Compare Ordered High +PPC_psq_lux, // Paired Single Quantized Load with update Indexed +PPC_psq_stux, // Paired Single Quantized Store with update Indexed +PPC_ps_neg, // Paired Single Negate +PPC_ps_cmpu1, // Paired Single Compare Unordered Low +PPC_ps_mr, // Paired Single Move Register +PPC_ps_cmpo1, // Paired Single Compare Ordered Low +PPC_ps_nabs, // Paired Single Negative Absolute Value +PPC_ps_abs, // Paired Single Absolute Value +PPC_ps_merge00, // Paired Single Merge High +PPC_ps_merge01, // Paired Single Merge Direct +PPC_ps_merge10, // Paired Single Merge Swapped +PPC_ps_merge11, // Paired Single Merge Low +PPC_dcbz_l, // Data Cache Block Set to Zero Locked +PPC_psq_l, // Paired Single Quantized Load +PPC_psq_lu, // Paired Single Quantized Load update +PPC_psq_st, // Paired Single Quantized Store +PPC_psq_stu, // Paired Single Quantized Store update + +// additional SPE/EFPU2 instructions +PPC_evfsmadd, // Vector Floating-Point Single-Precision Multiply-Add +PPC_evfsmsub, // Vector Floating-Point Single-Precision Multiply-Subtract +PPC_evfssqrt, // Vector Floating-Point Single-Precision Square Root +PPC_evfsnmadd, // Vector Floating-Point Single-Precision Negative Multiply-Add +PPC_evfsnmsub, // Vector Floating-Point Single-Precision Negative Multiply-Subtract +PPC_evfsmax, // Vector Floating-Point Single-Precision Maximum +PPC_evfsmin, // Vector Floating-Point Single-Precision Minimum +PPC_evfsaddsub, // Vector Floating-Point Single-Precision Add / Subtract +PPC_evfssubadd, // Vector Floating-Point Single-Precision Subtract / Add +PPC_evfssum, // Vector Floating-Point Single-Precision Sums +PPC_evfsdiff, // Vector Floating-Point Single-Precision Differences +PPC_evfssumdiff,// Vector Floating-Point Single-Precision Sum / Difference +PPC_evfsdiffsum,// Vector Floating-Point Single-Precision Difference / Sum +PPC_evfsaddx, // Vector Floating-Point Single-Precision Add Exchanged +PPC_evfssubx, // Vector Floating-Point Single-Precision Subtract Exchanged +PPC_evfsaddsubx,// Vector Floating-Point Single-Precision Add / Subtract Exchanged +PPC_evfssubaddx,// Vector Floating-Point Single-Precision Subtract / Add Exchanged +PPC_evfsmulx, // Vector Floating-Point Single-Precision Multiply Exchanged +PPC_evfsmule, // Vector Floating-Point Single-Precision Multiply By Even Element +PPC_evfsmulo, // Vector Floating-Point Single-Precision Multiply By Odd Element +PPC_evfscfh, // Vector Convert Floating-Point Single-Precision from Half-Precision +PPC_evfscth, // Vector Convert Floating-Point Single-Precision to Half-Precision +PPC_efsmax, // Floating-Point Single-Precision Maximum +PPC_efsmin, // Floating-Point Single-Precision Minimum +PPC_efsmadd, // Floating-Point Single-Precision Multiply-Add +PPC_efsmsub, // Floating-Point Single-Precision Multiply-Subtract +PPC_efssqrt, // Floating-Point Single-Precision Square Root +PPC_efsnmadd, // Floating-Point Single-Precision Negative Multiply-Add +PPC_efsnmsub, // Floating-Point Single-Precision Negative Multiply-Subtract +PPC_efscfh, // Convert Floating-Point Single-Precision from Half-Precision +PPC_efscth, // Convert Floating-Point Single-Precision to Half-Precision + +// Volatile Context Save/Restore APU +PPC_lmvgprw, // Load Multiple Volatile GPR Word +PPC_stmvgprw, // Store Multiple Volatile GPR Word +PPC_lmvsprw, // Load Multiple Volatile SPR Word +PPC_stmvsprw, // Store Multiple Volatile SPR Word +PPC_lmvsrrw, // Load Multiple Volatile SRR Word +PPC_stmvsrrw, // Store Multiple Volatile SRR Word +PPC_lmvcsrrw, // Load Multiple Volatile CSRR Word +PPC_stmvcsrrw, // Store Multiple Volatile CSRR Word +PPC_lmvdsrrw, // Load Multiple Volatile DSRR Word +PPC_stmvdsrrw, // Store Multiple Volatile DSRR Word +PPC_lmvmcsrrw, // Load Multiple Volatile MCSRR Word +PPC_stmvmcsrrw, // Store Multiple Volatile MCSRR Word + +// SPE2 (Signal Processing Engine 2) instructions +PPC_evdotpwcssi, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer (to Accumulator) +PPC_evdotpwcsmi, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer (to Accumulator) +PPC_evdotpwcssfr, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotpwcssf, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotpwgasmf, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwxgasmf, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwgasmfr, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwxgasmfr, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwgssmf, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwxgssmf, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwgssmfr, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwxgssmfr, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwcssiaaw3, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer and Accumulate into Words 3 operand +PPC_evdotpwcsmiaaw3, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer and Accumulate into Words 3 operand +PPC_evdotpwcssfraaw3, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words 3 operand +PPC_evdotpwcssfaaw3, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional and Accumulate into Words 3 operand +PPC_evdotpwgasmfaa3, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotpwxgasmfaa3, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotpwgasmfraa3, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate 3 operand +PPC_evdotpwxgasmfraa3, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate 3 operand +PPC_evdotpwgssmfaa3, // Vector Multiply Word Complex, Real, Guarded, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotpwxgssmfaa3, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotpwgssmfraa3, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate 3 operand +PPC_evdotpwxgssmfraa3, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate 3 operand +PPC_evdotpwcssia, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer (to Accumulator) +PPC_evdotpwcsmia, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer (to Accumulator) +PPC_evdotpwcssfra, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotpwcssfa, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotpwgasmfa, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwxgasmfa, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwgasmfra, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwxgasmfra, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwgssmfa, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwxgssmfa, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpwgssmfra, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwxgssmfra, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evdotpwcssiaaw, // Vector Dot Product of Words, Complex, Signed, Saturate, Integer and Accumulate into Words +PPC_evdotpwcsmiaaw, // Vector Dot Product of Words, Complex, Signed, Modulo, Integer and Accumulate into Words +PPC_evdotpwcssfraaw, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words +PPC_evdotpwcssfaaw, // Vector Dot Product of Words, Complex, Signed, Saturate, Fractional and Accumulate into Words +PPC_evdotpwgasmfaa, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional and Accumulate +PPC_evdotpwxgasmfaa, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate +PPC_evdotpwgasmfraa, // Vector Dot Product of Words Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate +PPC_evdotpwxgasmfraa, // Vector Dot Product of Words Exchanged, Guarded, Add, Signed, Modulo, Fractional, Round and Accumulate +PPC_evdotpwgssmfaa, // Vector Multiply Word Complex, Real, Guarded, Signed, Modulo, Fractional and Accumulate +PPC_evdotpwxgssmfaa, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate +PPC_evdotpwgssmfraa, // Vector Dot Product of Words Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate +PPC_evdotpwxgssmfraa, // Vector Dot Product of Words Exchanged, Guarded, Subtract, Signed, Modulo, Fractional, Round and Accumulate +PPC_evdotphihcssi, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) +PPC_evdotplohcssi, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) +PPC_evdotphihcssf, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotplohcssf, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotphihcsmi, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) +PPC_evdotplohcsmi, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) +PPC_evdotphihcssfr, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotplohcssfr, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotphihcssiaaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words, 3 operand +PPC_evdotplohcssiaaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words, 3 operand +PPC_evdotphihcssfaaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words, 3 operand +PPC_evdotplohcssfaaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words, 3 operand +PPC_evdotphihcsmiaaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotplohcsmiaaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotphihcssfraaw3, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand +PPC_evdotplohcssfraaw3, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand +PPC_evdotphihcssia, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) +PPC_evdotplohcssia, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer (to Accumulator) +PPC_evdotphihcssfa, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotplohcssfa, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotphihcsmia, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) +PPC_evdotplohcsmia, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer (to Accumulator) +PPC_evdotphihcssfra, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotplohcssfra, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotphihcssiaaw, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words +PPC_evdotplohcssiaaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Integer and Accumulate into Words +PPC_evdotphihcssfaaw, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words +PPC_evdotplohcssfaaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional and Accumulate into Words +PPC_evdotphihcsmiaaw, // Vector Dot Product of High Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words +PPC_evdotplohcsmiaaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Modulo, Integer and Accumulate into Words +PPC_evdotphihcssfraaw, // Vector Dot Product of High Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words +PPC_evdotplohcssfraaw, // Vector Dot Product of Low Halfwords, Complex, Signed, Saturate, Fractional, Round and Accumulate into Words +PPC_evdotphausi, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer (to Accumulator) +PPC_evdotphassi, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer (to Accumulator) +PPC_evdotphasusi, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer (to Accumulator) +PPC_evdotphassf, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotphsssf, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotphaumi, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotphasmi, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotphasumi, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotphassfr, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotphssmi, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer (to Accumulator) +PPC_evdotphsssfr, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotphausiaaw3, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer and Accumulate into Words, 3 operand +PPC_evdotphassiaaw3, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer and Accumulate into Words, 3 operand +PPC_evdotphasusiaaw3, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer and Accumulate into Words, 3 operand +PPC_evdotphassfaaw3, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional and Accumulate into Words, 3 operand +PPC_evdotphsssiaaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Integer and Accumulate into Words, 3 operand +PPC_evdotphsssfaaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional and Accumulate into Words, 3 operand +PPC_evdotphaumiaaw3, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotphasmiaaw3, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotphasumiaaw3, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotphassfraaw3, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand +PPC_evdotphssmiaaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotphsssfraaw3, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round and Accumulate into Words, 3 operand +PPC_evdotphausia, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer (to Accumulator) +PPC_evdotphassia, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer (to Accumulator) +PPC_evdotphasusia, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer (to Accumulator) +PPC_evdotphassfa, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotphsssfa, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional (to Accumulator) +PPC_evdotphaumia, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotphasmia, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotphasumia, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotphassfra, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotphssmia, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer (to Accumulator) +PPC_evdotphsssfra, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round (to Accumulator) +PPC_evdotphausiaaw, // Vector Dot Product of Halfwords, Add, Unsigned, Saturate, Integer and Accumulate into Words +PPC_evdotphassiaaw, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Integer and Accumulate into Words +PPC_evdotphasusiaaw, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Saturate, Integer and Accumulate into Words +PPC_evdotphassfaaw, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional and Accumulate into Words +PPC_evdotphsssiaaw, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Integer and Accumulate into Words +PPC_evdotphsssfaaw, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional and Accumulate into Words +PPC_evdotphaumiaaw, // Vector Dot Product of Halfwords, Add, Unsigned, Modulo, Integer and Accumulate into Words +PPC_evdotphasmiaaw, // Vector Dot Product of Halfwords, Add, Signed, Modulo, Integer and Accumulate into Words +PPC_evdotphasumiaaw, // Vector Dot Product of Halfwords, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words +PPC_evdotphassfraaw, // Vector Dot Product of Halfwords, Add, Signed, Saturate, Fractional, Round and Accumulate into Words +PPC_evdotphssmiaaw, // Vector Dot Product of Halfwords, Subtract, Signed, Modulo, Integer and Accumulate into Words +PPC_evdotphsssfraaw, // Vector Dot Product of Halfwords, Subtract, Signed, Saturate, Fractional, Round and Accumulate into Words +PPC_evdotp4hgaumi, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotp4hgasmi, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hgasumi, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotp4hgasmf, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotp4hgssmi, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hgssmf, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotp4hxgasmi, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hxgasmf, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpbaumi, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotpbasmi, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotpbasumi, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotp4hxgssmi, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hxgssmf, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotp4hgaumiaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer and Accumulate, 3 operand +PPC_evdotp4hgasmiaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer and Accumulate, 3 operand +PPC_evdotp4hgasumiaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer and Accumulate, 3 operand +PPC_evdotp4hgasmfaa3, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional and Accumulate, 3 operand +PPC_evdotp4hgssmiaa3, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer and Accumulate 3 operand +PPC_evdotp4hgssmfaa3, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotp4hxgasmiaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer and Accumulate 3 operand +PPC_evdotp4hxgasmfaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotpbaumiaaw3, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotpbasmiaaw3, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotpbasumiaaw3, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words, 3 operand +PPC_evdotp4hxgssmiaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer and Accumulate 3 operand +PPC_evdotp4hxgssmfaa3, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate 3 operand +PPC_evdotp4hgaumia, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotp4hgasmia, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hgasumia, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotp4hgasmfa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotp4hgssmia, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hgssmfa, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotp4hxgasmia, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hxgasmfa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotpbaumia, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotpbasmia, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer (to Accumulator) +PPC_evdotpbasumia, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evdotp4hxgssmia, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer (to Accumulator) +PPC_evdotp4hxgssmfa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional (to Accumulator) +PPC_evdotp4hgaumiaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Unsigned, Modulo, Integer and Accumulate +PPC_evdotp4hgasmiaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Integer and Accumulate +PPC_evdotp4hgasumiaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed by Unsigned, Modulo, Integer and Accumulate +PPC_evdotp4hgasmfaa, // Vector Dot Product of Four Halfwords, Guarded, Add, Signed, Modulo, Fractional and Accumulate +PPC_evdotp4hgssmiaa, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Integer and Accumulate +PPC_evdotp4hgssmfaa, // Vector Dot Product of Four Halfwords, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate +PPC_evdotp4hxgasmiaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Integer and Accumulate +PPC_evdotp4hxgasmfaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Add, Signed, Modulo, Fractional and Accumulate +PPC_evdotpbaumiaaw, // Vector Dot Product of Bytes, Add, Unsigned, Modulo, Integer and Accumulate into Words +PPC_evdotpbasmiaaw, // Vector Dot Product of Bytes, Add, Signed, Modulo, Integer and Accumulate into Words +PPC_evdotpbasumiaaw, // Vector Dot Product of Bytes, Add, Signed by Unsigned, Modulo, Integer and Accumulate into Words +PPC_evdotp4hxgssmiaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Integer and Accumulate +PPC_evdotp4hxgssmfaa, // Vector Dot Product of Four Halfwords Exchanged, Guarded, Subtract, Signed, Modulo, Fractional and Accumulate +PPC_evdotpwausi, // Vector Dot Product of Words, Add, Unsigned, Saturate, integer (to Accumulator) +PPC_evdotpwassi, // Vector Dot Product of Words, Add, Signed, Saturate, integer (to Accumulator) +PPC_evdotpwasusi, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, integer (to Accumulator) +PPC_evdotpwaumi, // Vector Dot Product of Words, Add, Unsigned, Modulo, integer (to Accumulator) +PPC_evdotpwasmi, // Vector Dot Product of Words, Add, Signed, Modulo, integer (to Accumulator) +PPC_evdotpwasumi, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, integer (to Accumulator) +PPC_evdotpwssmi, // Vector Dot Product of Words, Subtract, Signed, Modulo, integer (to Accumulator) +PPC_evdotpwausiaa3, // Vector Dot Product of Words, Add, Unsigned, Saturate, Integer and Accumulate, 3 operand +PPC_evdotpwassiaa3, // Vector Dot Product of Words, Add, Signed, Saturate, Integer and Accumulate, 3 operand +PPC_evdotpwasusiaa3, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, Integer and Accumulate, 3 operand +PPC_evdotpwsssiaa3, // Vector Dot Product of Words, Subtract, Signed, Saturate, Integer and Accumulate, 3 operand +PPC_evdotpwaumiaa3, // Vector Dot Product of Words, Add, Unsigned, Modulo, Integer and Accumulate, 3 operand +PPC_evdotpwasmiaa3, // Vector Dot Product of Words, Add, Signed, Modulo, Integer and Accumulate, 3 operand +PPC_evdotpwasumiaa3, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, Integer and Accumulate, 3 operand +PPC_evdotpwssmiaa3, // Vector Dot Product of Words, Subtract, Signed, Modulo, Integer and Accumulate, 3 operand +PPC_evdotpwausia, // Vector Dot Product of Words, Add, Unsigned, Saturate, integer (to Accumulator) +PPC_evdotpwassia, // Vector Dot Product of Words, Add, Signed, Saturate, integer (to Accumulator) +PPC_evdotpwasusia, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, integer (to Accumulator) +PPC_evdotpwaumia, // Vector Dot Product of Words, Add, Unsigned, Modulo, integer (to Accumulator) +PPC_evdotpwasmia, // Vector Dot Product of Words, Add, Signed, Modulo, integer (to Accumulator) +PPC_evdotpwasumia, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, integer (to Accumulator) +PPC_evdotpwssmia, // Vector Dot Product of Words, Subtract, Signed, Modulo, integer (to Accumulator) +PPC_evdotpwausiaa, // Vector Dot Product of Words, Add, Unsigned, Saturate, Integer and Accumulate +PPC_evdotpwassiaa, // Vector Dot Product of Words, Add, Signed, Saturate, Integer and Accumulate +PPC_evdotpwasusiaa, // Vector Dot Product of Words, Add, Signed by Unsigned, Saturate, Integer and Accumulate +PPC_evdotpwsssiaa, // Vector Dot Product of Words, Subtract, Signed, Saturate, Integer and Accumulate +PPC_evdotpwaumiaa, // Vector Dot Product of Words, Add, Unsigned, Modulo, Integer and Accumulate +PPC_evdotpwasmiaa, // Vector Dot Product of Words, Add, Signed, Modulo, Integer and Accumulate +PPC_evdotpwasumiaa, // Vector Dot Product of Words, Add, Signed by Unsigned, Modulo, Integer and Accumulate +PPC_evdotpwssmiaa, // Vector Dot Product of Words, Subtract, Signed, Modulo, Integer and Accumulate +PPC_evaddih, // Vector Add Immediate Halfword +PPC_evaddib, // Vector Add Immediate Byte +PPC_evsubifh, // Vector Subtract Immediate from Halfword +PPC_evsubifb, // Vector Subtract Immediate from Byte +PPC_evabsb, // Vector Absolute Value Byte +PPC_evabsh, // Vector Absolute Value Halfword +PPC_evabsd, // Vector Absolute Value Doubleword +PPC_evabss, // Vector Absolute Value (Word) and Saturate +PPC_evabsbs, // Vector Absolute Value Byte and Saturate +PPC_evabshs, // Vector Absolute Value Halfword and Saturate +PPC_evabsds, // Vector Absolute Value Doubleword and Saturate +PPC_evnegwo, // Vector Negate Word Odd +PPC_evnegb, // Vector Negate Byte +PPC_evnegbo, // Vector Negate Byte Odd +PPC_evnegh, // Vector Negate Halfword +PPC_evnegho, // Vector Negate Halfwords Odd +PPC_evnegd, // Vector Negate Doubleword +PPC_evnegs, // Vector Negate (Word) and Saturate +PPC_evnegwos, // Vector Negate Word Odd and Saturate +PPC_evnegbs, // Vector Negate Byte and Saturate +PPC_evnegbos, // Vector Negate Byte Odd and Saturate +PPC_evneghs, // Vector Negate Halfword and Saturate +PPC_evneghos, // Vector Negate Halfwords Odd and Saturate +PPC_evnegds, // Vector Negate Doubleword and Saturate +PPC_evextzb, // Vector Extend Zero Byte +PPC_evextsbh, // Vector Extend Sign of Bytes (Odd) to Halfwords +PPC_evextsw, // Vector Extend Sign Word +PPC_evrndhb, // Vector Round Halfword to Byte +PPC_evrnddw, // Vector Round Doubleword to Word +PPC_evrndwhus, // Vector Round Word to Halfword Unsigned and Saturate +PPC_evrndwhss, // Vector Round Word to Halfword Signed and Saturate +PPC_evrndhbus, // Vector Round Halfword to Byte Unsigned and Saturate +PPC_evrndhbss, // Vector Round Halfword to Byte Signed and Saturate +PPC_evrnddwus, // Vector Round Doubleword to Word Unsigned and Saturate +PPC_evrnddwss, // Vector Round Doubleword to Word Signed and Saturate +PPC_evrndwnh, // Vector Round Word to Nearest Even Halfword +PPC_evrndhnb, // Vector Round Halfword to Nearest Even Byte +PPC_evrnddnw, // Vector Round Doubleword to Nearest Even Word +PPC_evrndwnhus, // Vector Round Word to Nearest Even Halfword Unsigned and Saturate +PPC_evrndwnhss, // Vector Round Word to Nearest Even Halfword Signed and Saturate +PPC_evrndhnbus, // Vector Round Halfword to Nearest Byte Unsigned and Saturate +PPC_evrndhnbss, // Vector Round Halfword to Nearest Even Byte Signed and Saturate +PPC_evrnddnwus, // Vector Round Doubleword to Nearest Even Word Unsigned and Saturate +PPC_evrnddnwss, // Vector Round Doubleword to Nearest Even Word Signed and Saturate +PPC_evcntlzh, // Vector Count Leading Zeros Halfword +PPC_evcntlsh, // Vector Count Leading Signed Bits Halfword +PPC_evpopcntb, // Vector Population Count Byte +PPC_circinc, // Circular Increment +PPC_evunpkhibui, // Vector Unpack High Bytes as Unsigned Integers +PPC_evunpkhibsi, // Vector Unpack High Bytes as Signed Integers +PPC_evunpkhihui, // Vector Extract High Halfwords as Unsigned Integers +PPC_evunpkhihsi, // Vector Extract High Halfwords as Signed Integers +PPC_evunpklobui, // Vector Unpack Low Bytes Unsigned Integers +PPC_evunpklobsi, // Vector Unpack Low Bytes as Signed Integers +PPC_evunpklohui, // Vector Unpack Low Halfwords as Unsigned Integers +PPC_evunpklohsi, // Vector Unpack Low Halfwords as Signed Integers +PPC_evunpklohf, // Vector Unpack Low Halfwords as Fractional +PPC_evunpkhihf, // Vector Unpack High Halfwords as Fractional +PPC_evunpklowgsf, // Vector Unpack Low Word to Guarded Signed Fraction +PPC_evunpkhiwgsf, // Vector Unpack High Word to Guarded Signed Fraction +PPC_evsatsduw, // Vector Saturate Signed Doubleword to Unsigned Word Range +PPC_evsatsdsw, // Vector Saturate Signed Doubleword to Signed Word Range +PPC_evsatshub, // Vector Saturate Signed Halfwords to Unsigned Byte Range +PPC_evsatshsb, // Vector Saturate Signed Halfwords to Signed Byte Range +PPC_evsatuwuh, // Vector Saturate Unsigned Words to Unsigned Halfword Range +PPC_evsatswsh, // Vector Saturate Signed Words to Signed Halfword Range +PPC_evsatswuh, // Vector Pack Signed Words to Unsigned Halfword Range +PPC_evsatuhub, // Vector Saturate Unsigned Halfwords to Unsigned Byte Range +PPC_evsatuduw, // Vector Saturate Unsigned Doubleword to Unsigned Word Range +PPC_evsatuwsw, // Vector Saturate Unsigned Words to Signed Word Range +PPC_evsatshuh, // Vector Saturate Signed Halfwords to Unsigned Halfword Range +PPC_evsatuhsh, // Vector Saturate Unsigned Halfwords to Signed Halfword Range +PPC_evsatswuw, // Vector Pack Signed Words to Unsigned Word Range +PPC_evsatswgsdf, // Vector Saturate Signed Word Guarded to Signed Doubleword Fractional +PPC_evsatsbub, // Vector Saturate Signed Bytes to Unsigned Byte Range +PPC_evsatubsb, // Vector Saturate Unsigned Bytes to Signed Byte Range +PPC_evmaxhpuw, // Vector Maximum of Halfword Pairs Unsigned to Word +PPC_evmaxhpsw, // Vector Maximum of Halfword Pairs Signed to Word +PPC_evmaxbpuh, // Vector Maximum of Byte Pairs Unsigned to Halfword +PPC_evmaxbpsh, // Vector Maximum of Byte Pairs Signed to Halfword +PPC_evmaxwpud, // Vector Maximum of Word Pair Unsigned to Doubleword +PPC_evmaxwpsd, // Vector Maximum of Word Pair Signed to Doubleword +PPC_evminhpuw, // Vector Minimum of Halfword Pairs Unsigned to Word +PPC_evminhpsw, // Vector Minimum of Halfword Pairs Signed to Word +PPC_evminbpuh, // Vector Minimum of Byte Pairs Unsigned to Halfword +PPC_evminbpsh, // Vector Minimum of Byte Pairs Signed to Halfword +PPC_evminwpud, // Vector Minimum of Word Pair Unsigned to Doubleword +PPC_evminwpsd, // Vector Minimum of Word Pair Signed to Doubleword +PPC_evmaxmagws, // Vector Maximum Magnitude Word Signed +PPC_evsl, // Vector Shift Left +PPC_evsli, // Vector Shift Left Immediate +PPC_evsplatie, // Vector Splat Immediate Even (to Accumulator) +PPC_evsplatib, // Vector Splat Immediate Byte (to Accumulator) +PPC_evsplatibe, // Vector Splat Immediate Byte Even (to Accumulator) +PPC_evsplatih, // Vector Splat Immediate Halfword (to Accumulator) +PPC_evsplatihe, // Vector Splat Immediate Halfword Even (to Accumulator) +PPC_evsplatid, // Vector Splat Immediate Doubleword (to Accumulator) +PPC_evsplatia, // Vector Splat Immediate (to Accumulator) +PPC_evsplatiea, // Vector Splat Immediate Even (to Accumulator) +PPC_evsplatiba, // Vector Splat Immediate Byte (to Accumulator) +PPC_evsplatibea, // Vector Splat Immediate Byte Even (to Accumulator) +PPC_evsplatiha, // Vector Splat Immediate Halfword (to Accumulator) +PPC_evsplatihea, // Vector Splat Immediate Halfword Even (to Accumulator) +PPC_evsplatida, // Vector Splat Immediate Doubleword (to Accumulator) +PPC_evsplatfio, // Vector Splat Fractional Immediate Odd (to Accumulator) +PPC_evsplatfib, // Vector Splat Fractional Immediate Byte (to Accumulator) +PPC_evsplatfibo, // Vector Splat Fractional Immediate Byte Odd (to Accumulator) +PPC_evsplatfih, // Vector Splat Fractional Immediate Halfword (to Accumulator) +PPC_evsplatfiho, // Vector Splat Fractional Immediate Halfword Odd (to Accumulator) +PPC_evsplatfid, // Vector Splat Fractional Immediate Doubleword (to Accumulator) +PPC_evsplatfia, // Vector Splat Fractional Immediate (to Accumulator) +PPC_evsplatfioa, // Vector Splat Fractional Immediate Odd (to Accumulator) +PPC_evsplatfiba, // Vector Splat Fractional Immediate Byte (to Accumulator) +PPC_evsplatfiboa, // Vector Splat Fractional Immediate Byte Odd (to Accumulator) +PPC_evsplatfiha, // Vector Splat Fractional Immediate Halfword (to Accumulator) +PPC_evsplatfihoa, // Vector Splat Fractional Immediate Halfword Odd (to Accumulator) +PPC_evsplatfida, // Vector Splat Fractional Immediate Doubleword (to Accumulator) +PPC_evcmpgtdu, // Vector Compare Greater Than Doubleword Unsigned +PPC_evcmpgtds, // Vector Compare Greater Than Doubleword Signed +PPC_evcmpltdu, // Vector Compare Less Than Doubleword Unsigned +PPC_evcmpltds, // Vector Compare Less Than Doubleword Signed +PPC_evcmpeqd, // Vector Compare Equal Doubleword +PPC_evswapbhilo, // Vector Swap Bytes High/Low +PPC_evswapblohi, // Vector Swap Bytes Low/High +PPC_evswaphhilo, // Vector Swap Halfwords High/Low +PPC_evswaphlohi, // Vector Swap Halfwords Low/High +PPC_evswaphe, // Vector Swap Halfwords Even +PPC_evswaphhi, // Vector Swap Halfwords High +PPC_evswaphlo, // Vector Swap Halfwords Low +PPC_evswapho, // Vector Swap Halfwords Odd +PPC_evinsb, // Vector Insert Byte +PPC_evxtrb, // Vector Extract Byte +PPC_evsplath, // Vector Splat Halfword +PPC_evsplatb, // Vector Splat Byte +PPC_evinsh, // Vector Insert Halfword +PPC_evclrbe, // Vector Clear Bytes Even +PPC_evclrbo, // Vector Clear Bytes Odd +PPC_evxtrh, // Vector Extract Halfword +PPC_evclrh, // Vector Clear Halfwords +PPC_evselbitm0, // Vector Select Bit if Mask is 0 +PPC_evselbitm1, // Vector Select Bit if Mask is 1 +PPC_evselbit, // Vector Select Bit +PPC_evperm, // Vector Permute +PPC_evperm2, // Vector Permute (form 2) +PPC_evperm3, // Vector Permute (form 3) +PPC_evxtrd, // Vector Extract Doubleword +PPC_evsrbu, // Vector Shift Right Byte Unsigned +PPC_evsrbs, // Vector Shift Right Byte Signed +PPC_evsrbiu, // Vector Shift Right Byte Immediate Unsigned +PPC_evsrbis, // Vector Shift Right Byte Immediate Signed +PPC_evslb, // Vector Shift Left Byte +PPC_evrlb, // Vector Rotate Left Byte +PPC_evslbi, // Vector Shift Left Byte Immediate +PPC_evrlbi, // Vector Rotate Left Byte Immediate +PPC_evsrhu, // Vector Shift Right Halfword Unsigned +PPC_evsrhs, // Vector Shift Right Halfword Signed +PPC_evsrhiu, // Vector Shift Right Halfword Immediate Unsigned +PPC_evsrhis, // Vector Shift Right Halfword Immediate Signed +PPC_evslh, // Vector Shift Left Halfword +PPC_evrlh, // Vector Rotate Left Halfword +PPC_evslhi, // Vector Shift Left Halfword Immediate +PPC_evrlhi, // Vector Rotate Left Halfword Immediate +PPC_evsru, // Vector Shift Right Unsigned +PPC_evsrs, // Vector Shift Right Signed +PPC_evsriu, // Vector Shift Right Immediate Unsigned +PPC_evsris, // Vector Shift Right Immediate Signed +PPC_evlvsl, // Load Vector for Shift Left +PPC_evlvsr, // Load Vector for Shift Right +PPC_evsroiu, // Vector Shift Right by Octet Immediate Unsigned +PPC_evsloi, // Vector Shift Left by Octet Immediate +PPC_evsrois, // Vector Shift Right by Octet Immediate Signed +PPC_evldbx, // Vector Load Double into Eight Bytes [with Modify] Indexed +PPC_evldb, // Vector Load Double into Eight Bytes [with Update] +PPC_evlhhsplathx, // Vector Load Halfword into Halfword and Splat Halfwords [with Modify] Indexed +PPC_evlhhsplath, // Vector Load Halfword into Halfword and Splat Halfwords [with Update] +PPC_evlwbsplatwx, // Vector Load Word as Bytes and Splat Words [with Modify] Indexed +PPC_evlwbsplatw, // Vector Load Word as Bytes and Splat Words [with Update] +PPC_evlwhsplatwx, // Vector Load Word as Halfwords and Splat Words [with Modify] Indexed +PPC_evlwhsplatw, // Vector Load Word as Halfwords and Splat Words [with Update] +PPC_evlbbsplatbx, // Vector Load Byte into Byte and Splat Bytes [with Modify] Indexed +PPC_evlbbsplatb, // Vector Load Byte into Byte and Splat Bytes [with Update] +PPC_evstdbx, // Vector Store Double of Eight Bytes [with Modify] Indexed +PPC_evstdb, // Vector Store Double of Eight Bytes [with Update] +PPC_evlwbex, // Vector Load Word into Four Bytes Even [with Modify] Indexed +PPC_evlwbe, // Vector Load Word into Four Bytes Even [with Update] +PPC_evlwboux, // Vector Load Word into Four Bytes Odd Unsigned [with Modify] Indexed +PPC_evlwbou, // Vector Load Word into Four Bytes Odd Unsigned [with Update] +PPC_evlwbosx, // Vector Load Word into Two Halfwords Odd Signed [with Modify] Indexed +PPC_evlwbos, // Vector Load Word into Four Bytes Odd Signed [with Update] +PPC_evstwbex, // Vector Store Word of Four Bytes from Even [with Modify] Indexed +PPC_evstwbe, // Vector Store Word of Four Bytes from Even [with Update] +PPC_evstwbox, // Vector Store Word of Four Bytes from Odd [with Modify] Indexed +PPC_evstwbo, // Vector Store Word of Four Bytes from Odd [with Update] +PPC_evstwbx, // Vector Store Word of Four Bytes [with Modify] Indexed +PPC_evstwb, // Vector Store Word of Four Bytes [with Update] +PPC_evsthbx, // Vector Store Halfword of Two Bytes [with Modify] Indexed +PPC_evsthb, // Vector Store Halfword of Two Bytes [with Update] +PPC_evlddmx, // Vector Load Double Word into Double Word [with Modify] Indexed +PPC_evlddu, // Vector Load Double Word into Double Word [with Update] +PPC_evldwmx, // Vector Load Double into Two Words [with Modify] Indexed +PPC_evldwu, // Vector Load Double into Two Words [with Update] +PPC_evldhmx, // Vector Load Double into Four Halfwords [with Modify] Indexed +PPC_evldhu, // Vector Load Double into Four Halfwords [with Update] +PPC_evldbmx, // Vector Load Double into Eight Bytes [with Modify] Indexed +PPC_evldbu, // Vector Load Double into Eight Bytes [with Update] +PPC_evlhhesplatmx, // Vector Load Halfword into Halfwords Even and Splat [with Modify] Indexed +PPC_evlhhesplatu, // Vector Load Halfword into Halfwords Even and Splat [with Update] +PPC_evlhhsplathmx, // Vector Load Halfword into Halfword and Splat Halfwords [with Modify] Indexed +PPC_evlhhsplathu, // Vector Load Halfword into Halfword and Splat Halfwords [with Update] +PPC_evlhhousplatmx, // Vector Load Halfword into Halfword Odd Unsigned and Splat [with Modify] Indexed +PPC_evlhhousplatu, // Vector Load Halfword into Halfword Odd Unsigned and Splat [with Update] +PPC_evlhhossplatmx, // Vector Load Halfword into Halfword Odd Signed and Splat [with Modify] Indexed +PPC_evlhhossplatu, // Vector Load Halfword into Halfword Odd Signed and Splat [with Update] +PPC_evlwhemx, // Vector Load Word into Two Halfwords Even [with Modify] Indexed +PPC_evlwheu, // Vector Load Word into Two Halfwords Even [with Update] +PPC_evlwbsplatwmx, // Vector Load Word as Bytes and Splat Words [with Modify] Indexed +PPC_evlwbsplatwu, // Vector Load Word as Bytes and Splat Words [with Update] +PPC_evlwhoumx, // Vector Load Word into Two Halfwords Odd Unsigned [with Modify] Indexed (zero-extended) +PPC_evlwhouu, // Vector Load Word into Two Halfwords Odd Unsigned (zero-extended) [with Update] +PPC_evlwhosmx, // Vector Load Word into Two Halfwords Odd Signed [with Modify] Indexed (with sign extension) +PPC_evlwhosu, // Vector Load Word into Two Halfwords Odd Signed (with sign extension) [with Update] +PPC_evlwwsplatmx, // Vector Load Word into Word and Splat [with Modify] Indexed +PPC_evlwwsplatu, // Vector Load Word into Word and Splat [with Update] +PPC_evlwhsplatwmx, // Vector Load Word as Halfwords and Splat Words [with Modify] Indexed +PPC_evlwhsplatwu, // Vector Load Word as Halfwords and Splat Words [with Update] +PPC_evlwhsplatmx, // Vector Load Word into Two Halfwords and Splat [with Modify] Indexed +PPC_evlwhsplatu, // Vector Load Word into Two Halfwords and Splat [with Update] +PPC_evlbbsplatbmx, // Vector Load Byte into Byte and Splat Bytes [with Modify] Indexed +PPC_evlbbsplatbu, // Vector Load Byte into Byte and Splat Bytes [with Update] +PPC_evstddmx, // Vector Store Double of Double [with Modify] Indexed +PPC_evstddu, // Vector Store Double of Double [with Update] +PPC_evstdwmx, // Vector Store Double of Two Words [with Modify] Indexed +PPC_evstdwu, // Vector Store Double of Two Words [with Update] +PPC_evstdhmx, // Vector Store Double of Four Halfwords [with Modify] Indexed +PPC_evstdhu, // Vector Store Double of Four Halfwords [with Update] +PPC_evstdbmx, // Vector Store Double of Eight Bytes [with Modify] Indexed +PPC_evstdbu, // Vector Store Double of Eight Bytes [with Update] +PPC_evlwbemx, // Vector Load Word into Four Bytes Even [with Modify] Indexed +PPC_evlwbeu, // Vector Load Word into Four Bytes Even [with Update] +PPC_evlwboumx, // Vector Load Word into Four Bytes Odd Unsigned [with Modify] Indexed +PPC_evlwbouu, // Vector Load Word into Four Bytes Odd Unsigned [with Update] +PPC_evlwbosmx, // Vector Load Word into Two Halfwords Odd Signed [with Modify] Indexed +PPC_evlwbosu, // Vector Load Word into Four Bytes Odd Signed [with Update] +PPC_evstwhemx, // Vector Store Word of Two Halfwords from Even [with Modify] Indexed +PPC_evstwheu, // Vector Store Word of Two Halfwords from Even [with Update] +PPC_evstwbemx, // Vector Store Word of Four Bytes from Even [with Modify] Indexed +PPC_evstwbeu, // Vector Store Word of Four Bytes from Even [with Update] +PPC_evstwhomx, // Vector Store Word of Two Halfwords from Odd [with Modify] Indexed +PPC_evstwhou, // Vector Store Word of Two Halfwords from Odd [with Update] +PPC_evstwbomx, // Vector Store Word of Four Bytes from Odd [with Modify] Indexed +PPC_evstwbou, // Vector Store Word of Four Bytes from Odd [with Update] +PPC_evstwwemx, // Vector Store Word of Word from Even [with Modify] Indexed +PPC_evstwweu, // Vector Store Word of Word from Even [with Update] +PPC_evstwbmx, // Vector Store Word of Four Bytes [with Modify] Indexed +PPC_evstwbu, // Vector Store Word of Four Bytes [with Update] +PPC_evstwwomx, // Vector Store Word of Word from Odd [with Modify] Indexed +PPC_evstwwou, // Vector Store Word of Word from Odd [with Update] +PPC_evsthbmx, // Vector Store Halfword of Two Bytes [with Modify] Indexed +PPC_evsthbu, // Vector Store Halfword of Two Bytes [with Update] +PPC_evmhusi, // Vector Multiply Halfword Unsigned, Saturate, Integer +PPC_evmhssi, // Vector Multiply Halfword Signed, Saturate, Integer +PPC_evmhsusi, // Vector Multiply Halfword Signed by Unsigned, Saturate, Integer +PPC_evmhssf, // Vector Multiply Halfword Signed, Saturate, Fractional +PPC_evmhumi, // Vector Multiply Halfword Unsigned, Modulo, Integer +PPC_evmhssfr, // Vector Multiply Halfword Signed, Saturate, Fractional and Round +PPC_evmhesumi, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmhosumi, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmbeumi, // Vector Multiply Bytes Even, Unsigned, Modulo, Integer (to Accumulator) +PPC_evmbesmi, // Vector Multiply Bytes Even, Signed, Modulo, Integer (to Accumulator) +PPC_evmbesumi, // Vector Multiply Bytes Even, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmboumi, // Vector Multiply Bytes Odd, Unsigned, Modulo, Integer (to Accumulator) +PPC_evmbosmi, // Vector Multiply Bytes Odd, Signed, Modulo, Integer (to Accumulator) +PPC_evmbosumi, // Vector Multiply Bytes Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmhesumia, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmhosumia, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmbeumia, // Vector Multiply Bytes Even, Unsigned, Modulo, Integer (to Accumulator) +PPC_evmbesmia, // Vector Multiply Bytes Even, Signed, Modulo, Integer (to Accumulator) +PPC_evmbesumia, // Vector Multiply Bytes Even, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmboumia, // Vector Multiply Bytes Odd, Unsigned, Modulo, Integer (to Accumulator) +PPC_evmbosmia, // Vector Multiply Bytes Odd, Signed, Modulo, Integer (to Accumulator) +PPC_evmbosumia, // Vector Multiply Bytes Odd, Signed by Unsigned, Modulo, Integer (to Accumulator) +PPC_evmwusiw, // Vector Multiply Word Unsigned, Saturate, Integer Word +PPC_evmwssiw, // Vector Multiply Word Signed, Saturate, Integer Word +PPC_evmwhssfr, // Vector Multiply Word High Signed, Saturate, Fractional and Round (to Accumulator) +PPC_evmwehgsmfr, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evmwehgsmf, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional (to Accumulator) +PPC_evmwohgsmfr, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evmwohgsmf, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional (to Accumulator) +PPC_evmwhssfra, // Vector Multiply Word High Signed, Saturate, Fractional and Round (to Accumulator) +PPC_evmwehgsmfra, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evmwehgsmfa, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional (to Accumulator) +PPC_evmwohgsmfra, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional, Round (to Accumulator) +PPC_evmwohgsmfa, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional (to Accumulator) +PPC_evaddusiaa, // Vector Add Unsigned, Saturate, Integer to Accumulator +PPC_evaddssiaa, // Vector Add Signed, Saturate, Integer to Accumulator +PPC_evsubfusiaa, // Vector Subtract from (Accumulator) Unsigned, Saturate, Integer to Accumulator +PPC_evsubfssiaa, // Vector Subtract from Signed, Saturate, Integer to Accumulator +PPC_evaddsmiaa, // Vector Add to Accumulator +PPC_evsubfsmiaa, // Vector Subtract from Accumulator to Accumulator +PPC_evaddh, // Vector Add Halfwords +PPC_evaddhss, // Vector Add Halfwords Signed and Saturate +PPC_evsubfh, // Vector Subtract from Halfword +PPC_evsubfhss, // Vector Subtract from Halfwords Signed and Saturate +PPC_evaddhx, // Vector Add Halfwords Exchanged +PPC_evaddhxss, // Vector Add Halfwords Exchanged, Signed and Saturate +PPC_evsubfhx, // Vector Subtract from Halfwords Exchanged +PPC_evsubfhxss, // Vector Subtract from Halfwords Exchanged, Signed and Saturate +PPC_evaddd, // Vector Add Doubleword +PPC_evadddss, // Vector Add Doubleword Signed and Saturate +PPC_evsubfd, // Vector Subtract from Doubleword +PPC_evsubfdss, // Vector Subtract from Doubleword Signed and Saturate +PPC_evaddb, // Vector Add Bytes +PPC_evaddbss, // Vector Add Bytes Signed and Saturate +PPC_evsubfb, // Vector Subtract from Byte +PPC_evsubfbss, // Vector Subtract from Byte Signed and Saturate +PPC_evaddsubfh, // Vector Add / Subtract from Halfword +PPC_evaddsubfhss, // Vector Add / Subtract from Halfword Signed and Saturate +PPC_evsubfaddh, // Vector Subtract from / Add Halfwords +PPC_evsubfaddhss, // Vector Subtract from / Add Halfwords Signed and Saturate +PPC_evaddsubfhx, // Vector Add / Subtract from Halfword Exchanged +PPC_evaddsubfhxss, // Vector Add / Subtract from Halfword Exchanged, Signed and Saturate +PPC_evsubfaddhx, // Vector Subtract from / Add Halfwords Exchanged +PPC_evsubfaddhxss, // Vector Subtract from / Add Halfwords Exchanged, Signed and Saturate +PPC_evadddus, // Vector Add Doubleword Unsigned and Saturate +PPC_evaddbus, // Vector Add Bytes Unsigned and Saturate +PPC_evsubfdus, // Vector Subtract from Doubleword Unsigned and Saturate +PPC_evsubfbus, // Vector Subtract from Byte Unsigned and Saturate +PPC_evaddwus, // Vector Add Word Unsigned and Saturate +PPC_evaddwxus, // Vector Add Word Exchanged Unsigned and Saturate +PPC_evsubfwus, // Vector Subtract from Word Unsigned and Saturate +PPC_evsubfwxus, // Vector Subtract from Word Exchanged Unsigned and Saturate +PPC_evadd2subf2h, // Vector Add Upper 2 and Subtract from Lower 2 Halfwords +PPC_evadd2subf2hss, // Vector Add Upper 2 and Subtract from Lower 2 Halfwords Signed and Saturate +PPC_evsubf2add2h, // Vector Subtract from Upper 2 / Add Lower 2 Halfwords +PPC_evsubf2add2hss, // Vector Subtract from Upper 2 / Add Lower 2 Halfwords Signed and Saturate +PPC_evaddhus, // Vector Add Halfwords Unsigned and Saturate +PPC_evaddhxus, // Vector Add Halfwords Exchanged, Unsigned and Saturate +PPC_evsubfhus, // Vector Subtract from Halfwords Unsigned and Saturate +PPC_evsubfhxus, // Vector Subtract from Halfwords Exchanged, Unsigned and Saturate +PPC_evaddwss, // Vector Add Word Signed and Saturate +PPC_evsubfwss, // Vector Subtract from Word Signed and Saturate +PPC_evaddwx, // Vector Add Word Exchanged +PPC_evaddwxss, // Vector Add Word Exchanged Signed and Saturate +PPC_evsubfwx, // Vector Subtract from Word Exchanged +PPC_evsubfwxss, // Vector Subtract from Word Exchanged Signed and Saturate +PPC_evaddsubfw, // Vector Add / Subtract from Word +PPC_evaddsubfwss, // Vector Add / Subtract from Word Signed and Saturate +PPC_evsubfaddw, // Vector Subtract from / Add Word +PPC_evsubfaddwss, // Vector Subtract from / Add Word Signed and Saturate +PPC_evaddsubfwx, // Vector Add / Subtract from Word Exchanged +PPC_evaddsubfwxss, // Vector Add / Subtract from Word Exchanged Signed and Saturate +PPC_evsubfaddwx, // Vector Subtract from / Add Word Exchanged +PPC_evsubfaddwxss, // Vector Subtract from / Add Word Exchanged Signed and Saturate +PPC_evmar, // Store Accumulator +PPC_evsumwu, // Vector Sum of Words Unsigned (to Accumulator) +PPC_evsumws, // Vector Sum of Words Signed (to Accumulator) +PPC_evsum4bu, // Vector Sum of 4 Bytes UnsIgned (to Accumulator) +PPC_evsum4bs, // Vector Sum of 4 Bytes SIgned (to Accumulator) +PPC_evsum2hu, // Vector Sum of 2 Halfwords Unsigned (to Accumulator) +PPC_evsum2hs, // Vector Sum of 2 Halfwords Signed (to Accumulator) +PPC_evdiff2his, // Vector Difference of 2 Halfwords Interleaved Signed (to Accumulator) +PPC_evsum2his, // Vector Sum of 2 Halfwords Interleaved Signed (to Accumulator) +PPC_evsumwua, // Vector Sum of Words Unsigned (to Accumulator) +PPC_evsumwsa, // Vector Sum of Words Signed (to Accumulator) +PPC_evsum4bua, // Vector Sum of 4 Bytes UnsIgned (to Accumulator) +PPC_evsum4bsa, // Vector Sum of 4 Bytes SIgned (to Accumulator) +PPC_evsum2hua, // Vector Sum of 2 Halfwords Unsigned (to Accumulator) +PPC_evsum2hsa, // Vector Sum of 2 Halfwords Signed (to Accumulator) +PPC_evdiff2hisa, // Vector Difference of 2 Halfwords Interleaved Signed (to Accumulator) +PPC_evsum2hisa, // Vector Sum of 2 Halfwords Interleaved Signed (to Accumulator) +PPC_evsumwuaa, // Vector Sum of Words Unsigned and Accumulate +PPC_evsumwsaa, // Vector Sum of Words Signed and Accumulate +PPC_evsum4buaaw, // Vector Sum of 4 Bytes Unsigned and Accumulate into Words +PPC_evsum4bsaaw, // Vector Sum of 4 Bytes Signed and Accumulate into Words +PPC_evsum2huaaw, // Vector Sum of 2 Halfwords Unsigned and Accumulate into Words +PPC_evsum2hsaaw, // Vector Sum of 2 Halfwords Signed and Accumulate into Words +PPC_evdiff2hisaaw, // Vector Difference of 2 Halfwords Interleaved Signed and Accumulate into Words +PPC_evsum2hisaaw, // Vector Sum of 2 Halfwords Interleaved Signed and Accumulate into Words +PPC_evdivwsf, // Vector Divide Word Signed Fractional +PPC_evdivwuf, // Vector Divide Word Unsigned Fractional +PPC_evdivs, // Vector Divide Signed +PPC_evdivu, // Vector Divide Unsigned +PPC_evaddwegsi, // Vector Add Word Even Guarded Signed Integer +PPC_evaddwegsf, // Vector Add Word Even Guarded Signed Fraction +PPC_evsubfwegsi, // Vector Subtract from Word Even Guarded Signed Integer +PPC_evsubfwegsf, // Vector Subtract from Word Even Guarded Signed Fraction +PPC_evaddwogsi, // Vector Add Word Odd Guarded Signed Integer +PPC_evaddwogsf, // Vector Add Word Odd Guarded Signed Fraction +PPC_evsubfwogsi, // Vector Subtract from Word Odd Guarded Signed Integer +PPC_evsubfwogsf, // Vector Subtract from Word Odd Guarded Signed Fraction +PPC_evaddhhiuw, // Vector Add Halfwords High Unsigned to Words +PPC_evaddhhisw, // Vector Add Halfwords High Signed to Words +PPC_evsubfhhiuw, // Vector Subtract from Halfwords High Unsigned to Words +PPC_evsubfhhisw, // Vector Subtract from Halfwords High Signed to Words +PPC_evaddhlouw, // Vector Add Halfwords Low Unsigned to Words +PPC_evaddhlosw, // Vector Add Halfwords Low Signed to Words +PPC_evsubfhlouw, // Vector Subtract from Halfwords Low Unsigned to Words +PPC_evsubfhlosw, // Vector Subtract from Halfwords Low Signed to Words +PPC_evmhesusiaaw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Saturate, Integer and Accumulate into Words +PPC_evmhosusiaaw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Saturate, Integer and Accumulate into Words +PPC_evmhesumiaaw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer and Accumulate into Words +PPC_evmhosumiaaw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer and Accumulate into Words +PPC_evmbeusiaah, // Vector Multiply Byte Even, Unsigned, Saturate, Integer and Accumulate Halfwords +PPC_evmbessiaah, // Vector Multiply Byte Even, Signed, Saturate, Integer and Accumulate Halfwords +PPC_evmbesusiaah, // Vector Multiply Byte Even, Signed by Unsigned, Saturate, Integer and Accumulate Halfwords +PPC_evmbousiaah, // Vector Multiply Byte Odd, Unsigned, Saturate, Integer and Accumulate Halfwords +PPC_evmbossiaah, // Vector Multiply Byte Odd, Signed, Saturate, Integer and Accumulate Halfwords +PPC_evmbosusiaah, // Vector Multiply Byte Odd, Signed by Unsigned, Saturate, Integer and Accumulate Halfwords +PPC_evmbeumiaah, // Vector Multiply Byte Even, Unsigned, Modulo, Integer and Accumulate Halfwords +PPC_evmbesmiaah, // Vector Multiply Byte Even, Signed, Modulo, Integer and Accumulate Halfwords +PPC_evmbesumiaah, // Vector Multiply Byte Even, Signed by Unsigned, Modulo, Integer and Accumulate Halfwords +PPC_evmboumiaah, // Vector Multiply Byte Odd, Unsigned, Modulo, Integer and Accumulate Halfwords +PPC_evmbosmiaah, // Vector Multiply Byte Odd, Signed, Modulo, Integer and Accumulate Halfwords +PPC_evmbosumiaah, // Vector Multiply Byte Odd, Signed by Unsigned, Modulo, Integer and Accumulate Halfwords +PPC_evmwlusiaaw3, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate in Words 3 operand +PPC_evmwlssiaaw3, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate in Words +PPC_evmwhssfraaw3, // Vector Multiply Word High Signed, Saturate, Fractional, Round and Accumulate into Words 3 operand +PPC_evmwhssfaaw3, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate into Words 3 operand +PPC_evmwhssfraaw, // Vector Multiply Word High Signed, Saturate, Fractional, Round and Accumulate into Words +PPC_evmwhssfaaw, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate into Words +PPC_evmwlumiaaw3, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate in Words 3 operand +PPC_evmwlsmiaaw3, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate in Words 3 operand +PPC_evmwusiaa, // Vector Multiply Word Unsigned, Saturate, Integer and Accumulate +PPC_evmwssiaa, // Vector Multiply Word Signed, Saturate, Integer and Accumulate +PPC_evmwehgsmfraa, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional, Round and Accumulate +PPC_evmwehgsmfaa, // Vector Multiply Word Even High Guarded Signed, Modulo, Fractional and Accumulate +PPC_evmwohgsmfraa, // Vector Multiply Word Odd High Guarded Signed, Modulo, Fractional, Round and Accumulate +PPC_evmwohgsmfaa, // Vector Multiply Word Odd High Guarded Signed, Modulo, Fractional and Accumulate +PPC_evmhesusianw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Saturate, Integer and Accumulate Negative into Words +PPC_evmhosusianw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Saturate, Integer and Accumulate Negative into Words +PPC_evmhesumianw, // Vector Multiply Halfwords, Even, Signed by Unsigned, Modulo, Integer and Accumulate Negative into Words +PPC_evmhosumianw, // Vector Multiply Halfwords, Odd, Signed by Unsigned, Modulo, Integer and Accumulate Negative into Words +PPC_evmbeusianh, // Vector Multiply Byte Even, Unsigned, Saturate, Integer and Accumulate Negative Halfwords +PPC_evmbessianh, // Vector Multiply Byte Even, Signed, Saturate, Integer and Accumulate Negative Halfwords +PPC_evmbesusianh, // Vector Multiply Byte Even, Signed by Unsigned, Saturate, Integer and Accumulate Negative Halfwords +PPC_evmbousianh, // Vector Multiply Byte Odd, Unsigned, Saturate, Integer and Accumulate Negative Halfwords +PPC_evmbossianh, // Vector Multiply Byte Odd, Signed, Saturate, Integer and Accumulate Negative Halfwords +PPC_evmbosusianh, // Vector Multiply Byte Odd, Signed by Unsigned, Saturate, Integer and Accumulate Negative Halfwords +PPC_evmbeumianh, // Vector Multiply Byte Even, Unsigned, Modulo, Integer and Accumulate Negative Halfwords +PPC_evmbesmianh, // Vector Multiply Byte Even, Signed, Modulo, Integer and Accumulate Negative Halfwords +PPC_evmbesumianh, // Vector Multiply Byte Even, Signed by Unsigned, Modulo, Integer and Accumulate Negative Halfwords +PPC_evmboumianh, // Vector Multiply Byte Odd, Unsigned, Modulo, Integer and Accumulate Negative Halfwords +PPC_evmbosmianh, // Vector Multiply Byte Odd, Signed, Modulo, Integer and Accumulate Negative Halfwords +PPC_evmbosumianh, // Vector Multiply Byte Odd, Signed by Unsigned, Modulo, Integer and Accumulate Negative Halfwords +PPC_evmwlusianw3, // Vector Multiply Word Low Unsigned, Saturate, Integer and Accumulate Negative in Words 3 operand +PPC_evmwlssianw3, // Vector Multiply Word Low Signed, Saturate, Integer and Accumulate Negative in Words 3 operand +PPC_evmwhssfranw3, // Vector Multiply Word High Signed, Saturate, Fractional, Round, and Accumulate Negative into Words 3 operand +PPC_evmwhssfanw3, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate Negative into Words 3 operand +PPC_evmwhssfranw, // Vector Multiply Word High Signed, Saturate, Fractional, Round, and Accumulate Negative into Words +PPC_evmwhssfanw, // Vector Multiply Word High Signed, Saturate, Fractional and Accumulate Negative into Words +PPC_evmwlumianw3, // Vector Multiply Word Low Unsigned, Modulo, Integer and Accumulate Negative in Words 3 operand +PPC_evmwlsmianw3, // Vector Multiply Word Low Signed, Modulo, Integer and Accumulate Negative in Words 3 operand +PPC_evmwusian, // Vector Multiply Word Unsigned, Saturate, Integer and Accumulate Negative +PPC_evmwssian, // Vector Multiply Word Signed, Saturate, Integer and Accumulate Negative +PPC_evmwehgsmfran, // Vector Multiply Word Even High, Guarded, Signed, Modulo, Fractional, Round and Accumulate Negative +PPC_evmwehgsmfan, // Vector Multiply Word Even High, Guarded, Signed, Modulo, Fractional and Accumulate Negative +PPC_evmwohgsmfran, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional, Round and Accumulate Negative +PPC_evmwohgsmfan, // Vector Multiply Word Odd, High, Guarded, Signed, Modulo, Fractional and Accumulate Negative +PPC_evseteqb, // Vector Set if Equal Byte [and Record] +PPC_evseteqh, // Vector Set if Equal Halfword [and Record] +PPC_evseteqw, // Vector Set if Equal Word [and Record] +PPC_evsetgthu, // Vector Set if Greater Than Halfword UnsIgned [and Record] +PPC_evsetgths, // Vector Set if Greater Than Halfword SIgned [and Record] +PPC_evsetgtwu, // Vector Set if Greater Than Word Unsigned [and Record] +PPC_evsetgtws, // Vector Set if Greater Than Word Signed [and Record] +PPC_evsetgtbu, // Vector Set if Greater Than Byte Unsigned [and Record] +PPC_evsetgtbs, // Vector Set if Greater Than Byte SIgned [and Record] +PPC_evsetltbu, // Vector Set if Less Than Byte Unsigned [and Record] +PPC_evsetltbs, // Vector Set if Less Than Byte SIgned [and Record] +PPC_evsetlthu, // Vector Set if Less Than Halfword UnsIgned [and Record] +PPC_evsetlths, // Vector Set if Less Than Halfword SIgned [and Record] +PPC_evsetltwu, // Vector Set if Less Than Word Unsigned [and Record] +PPC_evsetltws, // Vector Set if Less Than Word Signed [and Record] +PPC_evsaduw, // Vector Sum of Absolute Differences of Unsigned Words (to Accumulator) +PPC_evsadsw, // Vector Sum of Absolute Differences of Signed Words (to Accumulator) +PPC_evsad4ub, // Vector Sum of Absolute Differences of 4 Unsigned Bytes (to Accumulator) +PPC_evsad4sb, // Vector Sum of Absolute Differences of 4 Signed Bytes (to Accumulator) +PPC_evsad2uh, // Vector Sum of Absolute Differences of 2 Unsigned Halfwords (to Accumulator) +PPC_evsad2sh, // Vector Sum of Absolute Differences of 2 Signed Halfwords (to Accumulator) +PPC_evsaduwa, // Vector Sum of Absolute Differences of Unsigned Words (to Accumulator) +PPC_evsadswa, // Vector Sum of Absolute Differences of Signed Words (to Accumulator) +PPC_evsad4uba, // Vector Sum of Absolute Differences of 4 Unsigned Bytes (to Accumulator) +PPC_evsad4sba, // Vector Sum of Absolute Differences of 4 Signed Bytes (to Accumulator) +PPC_evsad2uha, // Vector Sum of Absolute Differences of 2 Unsigned Halfwords (to Accumulator) +PPC_evsad2sha, // Vector Sum of Absolute Differences of 2 Signed Halfwords (to Accumulator) +PPC_evabsdifuw, // Vector Absolute Difference of Unsigned Words +PPC_evabsdifsw, // Vector Absolute Difference of Signed Words +PPC_evabsdifub, // Vector Absolute Difference of Unsigned Bytes +PPC_evabsdifsb, // Vector Absolute Difference of Signed Bytes +PPC_evabsdifuh, // Vector Absolute Difference of Unsigned Halfwords +PPC_evabsdifsh, // Vector Absolute Difference of Signed Halfwords +PPC_evsaduwaa, // Vector Sum of Absolute Differences of Unsigned Words and Accumulate +PPC_evsadswaa, // Vector Sum of Absolute Differences of Signed Words and Accumulate +PPC_evsad4ubaaw, // Vector Sum of Absolute Differences of 4 Unsigned Bytes and Accumulate into Words +PPC_evsad4sbaaw, // Vector Sum of Absolute Differences of 4 Signed Bytes and Accumulate into Words +PPC_evsad2uhaaw, // Vector Sum of Absolute Differences of 2 Unsigned Halfwords and Accumulate into Words +PPC_evsad2shaaw, // Vector Sum of Absolute Differences of 2 Signed Halfwords and Accumulate into Words +PPC_evpkshubs, // Vector Pack Signed Halfwords to Unsigned Bytes and Saturate +PPC_evpkshsbs, // Vector Pack Signed Halfwords to Signed Bytes and Saturate +PPC_evpkswuhs, // Vector Pack Signed Words to Unsigned Halfwords and Saturate +PPC_evpkswshs, // Vector Pack Signed Words to Signed Halfwords and Saturate +PPC_evpkuhubs, // Vector Pack Unsigned Halfwords to Unsigned Bytes and Saturate +PPC_evpkuwuhs, // Vector Pack Unsigned Words to Unsigned Halfwords and Saturate +PPC_evpkswshilvs, // Vector Pack Signed Words to Signed Halfwords Interleaved and Saturate +PPC_evpkswgshefrs, // Vector Pack Signed Words Guarded to Signed Halfwords Even Fractional Round and Saturate +PPC_evpkswshfrs, // Vector Pack Signed Words to Signed Halfwords Fractional, Round and Saturate +PPC_evpkswshilvfrs, // Vector Pack Signed Words to Signed Halfwords Interleaved, Fractional, Round and Saturate +PPC_evpksdswfrs, // Vector Pack Signed Doublewords to Signed Words Fractional, Round and Saturate +PPC_evpksdshefrs, // Vector Pack Signed Doublewords to Signed Halfwords Even, Fractional, Round, and Saturate +PPC_evpkuduws, // Vector Pack Unsigned Doublewords to Unsigned Words and Saturate +PPC_evpksdsws, // Vector Pack Signed Doublewords to Signed Words and Saturate +PPC_evpkswgswfrs, // Vector Pack Signed Words Guarded to Signed Words Fractional Round and Saturate +PPC_evilveh, // Vector Interleave Even Halfwords +PPC_evilveoh, // Vector Interleave Even/Odd Halfwords +PPC_evilvhih, // Vector Interleave High Halfwords +PPC_evilvhiloh, // Vector Interleave High/Low Halfwords +PPC_evilvloh, // Vector Interleave Low Halfwords +PPC_evilvlohih, // Vector Interleave Low/High Halfwords +PPC_evilvoeh, // Vector Interleave Odd/Even Halfwords +PPC_evilvoh, // Vector Interleave Odd Halfwords +PPC_evdlveb, // Vector De-interleave Even Bytes +PPC_evdlveh, // Vector De-interleave Even Halfwords +PPC_evdlveob, // Vector De-interleave Even/Odd Bytes +PPC_evdlveoh, // Vector De-interleave Even/Odd Halfwords +PPC_evdlvob, // Vector De-interleave Odd Bytes +PPC_evdlvoh, // Vector De-interleave Odd Halfwords +PPC_evdlvoeb, // Vector De-interleave Odd/Even Bytes +PPC_evdlvoeh, // Vector De-interleave Odd/Even Halfwords +PPC_evmaxbu, // Vector Maximum Byte Unsigned +PPC_evmaxbs, // Vector Maximum Byte Signed +PPC_evmaxhu, // Vector Maximum Halfword Unsigned +PPC_evmaxhs, // Vector Maximum Halfword Signed +PPC_evmaxwu, // Vector Maximum Word Unsigned +PPC_evmaxws, // Vector Maximum Word Signed +PPC_evmaxdu, // Vector Maximum Doubleword Unsigned +PPC_evmaxds, // Vector Maximum Doubleword Signed +PPC_evminbu, // Vector Minimum Byte Unsigned +PPC_evminbs, // Vector Minimum Byte Signed +PPC_evminhu, // Vector Minimum Halfword Unsigned +PPC_evminhs, // Vector Minimum Halfword Signed +PPC_evminwu, // Vector Minimum Word Unsigned +PPC_evminws, // Vector Minimum Word Signed +PPC_evmindu, // Vector Minimum Doubleword Unsigned +PPC_evminds, // Vector Minimum Doubleword Signed +PPC_evavgwu, // Vector Average Word Unsigned +PPC_evavgws, // Vector Average Word Signed +PPC_evavgbu, // Vector Average Byte Unsigned +PPC_evavgbs, // Vector Average Byte Signed +PPC_evavghu, // Vector Average Halfword Unsigned +PPC_evavghs, // Vector Average Halfword Signed +PPC_evavgdu, // Vector Average Doubleword Unsigned +PPC_evavgds, // Vector Average Doubleword Signed +PPC_evavgwur, // Vector Average Word Unsigned with Round +PPC_evavgwsr, // Vector Average Word Signed with Round +PPC_evavgbur, // Vector Average Byte Unsigned with Round +PPC_evavgbsr, // Vector Average Byte Signed with Round +PPC_evavghur, // Vector Average Halfword Unsigned with Round +PPC_evavghsr, // Vector Average Halfword Signed with Round +PPC_evavgdur, // Vector Average Doubleword Unsigned with Round +PPC_evavgdsr, // Vector Average Doubleword Signed with Round + +// Some simplifications that were missed previously +PPC_tdui, // Trap Doubleword Unconditionally with Immediate +PPC_tdu, // Trap Doubleword Unconditionally +PPC_twui, // Trap Word Unconditionally with Immediate +PPC_twu, // Trap Word Unconditionally + +// Power ISA 2.07 +PPC_bctar, // Branch Conditional to Branch Target Address Register +PPC_clrbhrb, // Clear BHRB +PPC_mfbhrbe, // Move From Branch History Rolling Buffer +PPC_mtsle, // Move To Split Little Endian +PPC_mfvsrd, // Move From VSR Doubleword +PPC_mfvsrwz, // Move From VSR Word and Zero +PPC_mtvsrd, // Move To VSR Doubleword +PPC_mtvsrwa, // Move To VSR Word Algebraic +PPC_mtvsrwz, // Move To VSR Word and Zero +PPC_fmrgew, // Floating Merge Even Word +PPC_fmrgow, // Floating Merge Odd Word +PPC_vpksdss, // Vector Pack Signed Doubleword Signed Saturate +PPC_vpksdus, // Vector Pack Signed Doubleword Unsigned Saturate +PPC_vpkudus, // Vector Pack Unsigned Doubleword Unsigned Saturate +PPC_vpkudum, // Vector Pack Unsigned Doubleword Unsigned Modulo +PPC_vupkhsw, // Vector Unpack High Signed Word +PPC_vupklsw, // Vector Unpack Low Signed Word +PPC_vmrgew, // Vector Merge Even Word +PPC_vmrgow, // Vector Merge Odd Word +PPC_vaddudm, // Vector Add Unsigned Doubleword Modulo +PPC_vadduqm, // Vector Add Unsigned Quadword Modulo +PPC_vaddeuqm, // Vector Add Extended Unsigned Quadword Modulo +PPC_vaddcuq, // Vector Add & write Carry Unsigned Quadword +PPC_vaddecuq, // Vector Add Extended & write Carry Unsigned Quadword +PPC_vsubudm, // Vector Subtract Unsigned Doubleword Modulo +PPC_vsubuqm, // Vector Subtract Unsigned Quadword Modulo +PPC_vsubeuqm, // Vector Subtract Extended Unsigned Quadword Modulo +PPC_vsubcuq, // Vector Subtract & write Carry Unsigned Quadword +PPC_vsubecuq, // Vector Subtract Extended & write Carry Unsigned Quadword +PPC_vmulesw, // Vector Multiply Even Signed Word +PPC_vmuleuw, // Vector Multiply Even Unsigned Word +PPC_vmulosw, // Vector Multiply Odd Signed Word +PPC_vmulouw, // Vector Multiply Odd Unsigned Word +PPC_vmuluwm, // Vector Multiply Unsigned Word Modulo +PPC_vmaxsd, // Vector Maximum Signed Doubleword +PPC_vmaxud, // Vector Maximum Unsigned Doubleword +PPC_vminsd, // Vector Minimum Signed Doubleword +PPC_vminud, // Vector Minimum Unsigned Doubleword +PPC_vcmpequd, // Vector Compare Equal To Unsigned Doubleword +PPC_vcmpgtsd, // Vector Compare Greater Than Signed Doubleword +PPC_vcmpgtud, // Vector Compare Greater Than Unsigned Doubleword +PPC_veqv, // Vector Equivalence +PPC_vnand, // Vector NAND +PPC_vorc, // Vector OR with Complement +PPC_vrld, // Vector Rotate Left Doubleword +PPC_vsld, // Vector Shift Left Doubleword +PPC_vsrd, // Vector Shift Right Doubleword +PPC_vsrad, // Vector Shift Right Algebraic Doubleword +PPC_vcipher, // Vector AES Cipher +PPC_vcipherlast, // Vector AES Cipher Last +PPC_vncipher, // Vector AES Inverse Cipher +PPC_vncipherlast, // Vector AES Inverse Cipher Last +PPC_vsbox, // Vector AES S-Box +PPC_vshasigmad, // Vector SHA-512 Sigma Doubleword +PPC_vshasigmaw, // Vector SHA-256 Sigma Word +PPC_vpmsumb, // Vector Polynomial Multiply-Sum Byte +PPC_vpmsumd, // Vector Polynomial Multiply-Sum Doubleword +PPC_vpmsumh, // Vector Polynomial Multiply-Sum Halfword +PPC_vpmsumw, // Vector Polynomial Multiply-Sum Word +PPC_vpermxor, // Vector Permute and Exclusive-OR +PPC_vgbbd, // Vector Gather Bits by Byte by Doubleword +PPC_vclzb, // Vector Count Leading Zeros Byte +PPC_vclzh, // Vector Count Leading Zeros Halfword +PPC_vclzw, // Vector Count Leading Zeros Word +PPC_vclzd, // Vector Count Leading Zeros Doubleword +PPC_vpopcntb, // Vector Population Count Byte +PPC_vpopcntd, // Vector Population Count Doubleword +PPC_vpopcnth, // Vector Population Count Halfword +PPC_vpopcntw, // Vector Population Count Word +PPC_vbpermq, // Vector Bit Permute Quadword +PPC_bcdadd, // Decimal Add Modulo +PPC_bcdsub, // Decimal Subtract Modulo +PPC_lxsiwax, // Load VSX Scalar as Integer Word Algebraic Indexed +PPC_lxsspx, // Load VSX Scalar Single-Precision Indexed +PPC_lxsiwzx, // Load VSX Scalar as Integer Word and Zero Indexed +PPC_stxsiwx, // Store VSX Scalar as Integer Word Indexed +PPC_stxsspx, // Store VSR Scalar Word Indexed +PPC_xsaddsp, // VSX Scalar Add Single-Precision +PPC_xscvdpspn, // VSX Scalar Convert Double-Precision to Single-Precision format Non-signalling +PPC_xscvspdpn, // Scalar Convert Single-Precision to Double-Precision format Non-signalling +PPC_xscvsxdsp, // VSX Scalar Convert Signed Fixed-Point Doubleword to Single-Precision +PPC_xscvuxdsp, // VSX Scalar Convert Unsigned Fixed-Point Doubleword to Single-Precision +PPC_xsdivsp, // VSX Scalar Divide Single-Precision +PPC_xsmaddasp, // VSX Scalar Multiply-Add Type-A Single-Precision +PPC_xsmaddmsp, // VSX Scalar Multiply-Add Type-M Single-Precision +PPC_xsmsubasp, // VSX Scalar Multiply-Subtract Type-A Single-Precision +PPC_xsmsubmsp, // VSX Scalar Multiply-Subtract Type-M Single-Precision +PPC_xsmulsp, // VSX Scalar Multiply Single-Precision +PPC_xsnmaddasp, // VSX Scalar Negative Multiply-Add Type-A Single-Precision +PPC_xsnmaddmsp, // VSX Scalar Negative Multiply-Add Type-M Single-Precision +PPC_xsnmsubasp, // VSX Scalar Negative Multiply-Subtract Type-A Single-Precision +PPC_xsnmsubmsp, // VSX Scalar Negative Multiply-Subtract Type-M Single-Precision +PPC_xsresp, // VSX Scalar Reciprocal Estimate Single-Precision +PPC_xsrsp, // VSX Scalar Round to Single-Precision +PPC_xsrsqrtesp, // VSX Scalar Reciprocal Square Root Estimate Single-Precision +PPC_xssqrtsp, // VSX Scalar Square Root Single-Precision +PPC_xssubsp, // VSX Scalar Subtract Single-Precision +PPC_xxleqv, // VSX Logical Equivalence +PPC_xxlnand, // VSX Logical NAND +PPC_xxlorc, // VSX Logical OR with Complement +PPC_lqarx, // Load Quadword And Reserve Indexed +PPC_stqcx, // Store Quadword Conditional Indexed and record CR0 +PPC_tbegin, // Transaction Begin +PPC_tend, // Transaction End +PPC_tabort, // Transaction Abort +PPC_tabortwc, // Transaction Abort Word Conditional +PPC_tabortwci, // Transaction Abort Word Conditional Immediate +PPC_tabortdc, // Transaction Abort Doubleword Conditional +PPC_tabortdci, // Transaction Abort Doubleword Conditional Immediate +PPC_tsr, // Transaction Suspend or Resume +PPC_tcheck, // Transaction Check +PPC_rfebb, // Return from Event Based Branch +PPC_treclaim, // Transaction Reclaim +PPC_trechkpt, // Transaction Recheckpoint +PPC_msgsndp, // Message Send Privileged +PPC_msgclrp, // Message Clear Privileged +PPC_dcblq, // Data Cache Block Lock Query +PPC_icblq, // Instruction Cache Block Lock Query + +// Simplifications for Power ISA 2.07 +PPC_vmr, // Vector Move Register +PPC_vnot, // Vector Complement Register +PPC_tendall, // Transaction End All +PPC_tsuspend, // Transaction Suspend +PPC_tresume, // Transaction Resume +PPC_mtppr, // Move To Program Priority Register +PPC_mfppr, // Move From Program Priority Register +PPC_mtppr32, // Move To Program Priority Register 32-Bit +PPC_mfppr32, // Move From Program Priority Register 32-Bit +PPC_mtic, // Move To IC +PPC_mfic, // Move From IC +PPC_mtvtb, // Move to VTB +PPC_mfvtb, // Move From VTB +PPC_miso, // "or" Cache Control Hint +PPC_mdoio, // "or" Shared Resource Hint +PPC_mdoom, // "or" Shared Resource Hint +PPC_yield, // "or" Shared Resource Hint +// these are mentioned in the Power ISA 2.07 document but not implemented by +// binutils; since they are just simplifications better to ignore them than to +// emit "weird" mnemonics +// PPC_mtuamr, // Move To Authority Mask Register +// PPC_mfuamr, // Move From Authority Mask Register +// PPC_dcbtct, // Data Cache Block Touch +// PPC_dcbtds, // Data Cache Block Touch +// PPC_dcbna, // Data Cache Block Touch +// PPC_dcbtctep, // Data Cache Block Touch by External PID +// PPC_dcbtdsep, // Data Cache Block Touch by External PID +// PPC_dcbflep, // Data Cache Block Flush by External PID +// PPC_dcbflpep, // Data Cache Block Flush by External PID +// PPC_dcbtstctep, // Data Cache Block Touch for Store by External PID +// +// these are only needed by assemblers +// PPC_lxvx, // Load VSX Vector Doubleword*2 Indexed +// PPC_stxvx, // Store VSX Vector Doubleword*2 Indexed +// PPC_mffprd, // Move From FPR Doubleword +// PPC_mfvrd, // Move From VR Doubleword +// PPC_mffprwz, // Move From FPR Word and Zero +// PPC_mfvrwz, // Move From VR Word and Zero +// PPC_mtfprd, // Move To FPR Doubleword +// PPC_mtvrd, // Move To VR Doubleword +// PPC_mtfprwa, // Move To FPR Word Algebraic +// PPC_mtvrwa, // Move To VR Word Algebraic +// PPC_mtfprwz, // Move To FPR Word and Zero +// PPC_mtvrwz, // Move To VR Word and Zero + +// e500 core family, category ISAT, valid for VLE +// EREF_RM Rev. 1 (EIS 2.1) 06/2014 +PPC_addbss, // Add Byte Signed Saturate +PPC_addhss, // Add Halfword Signed Saturate +PPC_addwss, // Add Word Signed Saturate +PPC_addbus, // Add Byte Unsigned Saturate +PPC_addhus, // Add Halfword Unsigned Saturate +PPC_addwus, // Add Word Unsigned Saturate +PPC_mulhss, // Multiply Halfword SIgned Saturate +PPC_mulwss, // Multiply Word SIgned Saturate +PPC_mulhus, // Multiply Halfword Unsigned Saturate +PPC_mulwus, // Multiply Word Unsigned Saturate +PPC_sat, // Saturate +PPC_subfbss, // Subtract From Byte Signed Saturate +PPC_subfhss, // Subtract From Halfword Signed Saturate +PPC_subfwss, // Subtract From Word Signed Saturate +PPC_subfbus, // Subtract From Byte Unsigned Saturate +PPC_subfhus, // Subtract From Halfword Unsigned Saturate +PPC_subfwus, // Subtract From Word Unsigned Saturate +// simplified mnemonics for PPC_sat +PPC_satsbs, // Saturate +PPC_satubs, // Saturate +PPC_satsbu, // Saturate +PPC_satubu, // Saturate +PPC_abssb, // Saturate +PPC_absub, // Saturate +PPC_satshs, // Saturate +PPC_satuhs, // Saturate +PPC_satshu, // Saturate +PPC_satuhu, // Saturate +PPC_abssh, // Saturate +PPC_absuh, // Saturate +PPC_satsws, // Saturate +PPC_satuws, // Saturate +PPC_satswu, // Saturate +PPC_satuwu, // Saturate +PPC_abssw, // Saturate +PPC_absuw, // Saturate + +// e200 Enhanced Debug extension +PPC_dni, // Debugger Notify Interrupt + +// Power ISA Version 3.0 +PPC_slbieg, // SLB Invalidate Entry Global +PPC_slbiag, // SLB Invalidate All Global +PPC_slbsync, // SLB Synchronize + +PPC_addpcis, // Add PC Immediate Shifted +PPC_lnia, // Add PC Immediate Shifted +PPC_subpcis, // Add PC Immediate Shifted +PPC_cmpeqb, // Compare Equal Byte +PPC_cmprb, // Compare Ranged Byte +PPC_cnttzw, // Count Trailing Zeros Word +PPC_cnttzd, // Count Trailing Zeros Dword +PPC_darn, // Deliver A Random Number +PPC_extswsli, // Extend-Sign Word and Shift Left +PPC_maddhd, // Multiply-Add High Doublewor +PPC_maddhdu, // Multiply-Add High Doubleword Unsigned +PPC_maddld, // Multiply-Add Low Doubleword +PPC_mcrxrx, // Move to CR from XER Extended, PPC_mcrxr disappeared +PPC_setb, // Set Boolean +PPC_modsd, // Modulo Signed Dword +PPC_modud, // Modulo Unsigned Dword +PPC_modsw, // Modulo Signed Word +PPC_moduw, // Modulo Unsigned Word +PPC_mfvsrld, // Move From VSR Lower Doubleword +PPC_mtvsrdd, // Move To VSR Double Dword +PPC_mtvsrws, // Move To VSR Word & Splat +PPC_scv, // System Call Vectored +PPC_rfscv, // Return From System Call Vectored +PPC_stop, // Stop + +PPC_copy, // Copy +PPC_paste, // Paste +PPC_ldat, // Load Dword ATomic +PPC_lwat, // Load Word ATomic +PPC_stdat, // Store Dword ATomic +PPC_stwat, // Store Word ATomic +PPC_cpabort, // Copy-Paste Abort +PPC_wait30, // Wait for Interrupt + +PPC_dtstsfi, // DFP Test Significance Immediate +PPC_dtstsfiq, // DFP Test Significance Immediate Quad + +PPC_bcdcfn, // Decimal Convert From National & record +PPC_bcdcfz, // Decimal Convert From Zoned & record +PPC_bcdctn, // Decimal Convert To National & record +PPC_bcdctz, // Decimal Convert To Zoned & record +PPC_bcdctsq, // Decimal Convert To Signed Qword & record +PPC_bcdcfsq, // Decimal Convert From Signed Qword & record +PPC_bcdsetsgn, // Decimal Set Sign & record +PPC_bcdcpsgn, // Decimal CopySign & record +PPC_bcds, // Decimal Shift & record +PPC_bcdus, // Decimal Unsigned Shift & record +PPC_bcdsr, // Decimal Shift & Round & record +PPC_bcdtrunc, // Decimal Truncate & record +PPC_bcdutrunc, // Decimal Unsigned Truncate & record + +PPC_vabsdub, // Vector Absolute Difference Unsigned Byte +PPC_vabsduh, // Vector Absolute Difference Unsigned Hword +PPC_vabsduw, // Vector Absolute Difference Unsigned Word +PPC_vbpermd, // Vector Bit Permute Dword +PPC_vclzlsbb, // Vector Count Leading Zero Least-Significant Bits Byte +PPC_vctzlsbb, // Vector Count Trailing Zero Least-Significant Bits Byte +PPC_vcmpneb, // Vector Compare Not Equal Byte +PPC_vcmpnezb, // Vector Compare Not Equal or Zero Byte +PPC_vcmpneh, // Vector Compare Not Equal Hword +PPC_vcmpnezh, // Vector Compare Not Equal or Zero Hword +PPC_vcmpnew, // Vector Compare Not Equal Word +PPC_vcmpnezw, // Vector Compare Not Equal or Zero Word +PPC_vctzb, // Vector Count Trailing Zeros Byte +PPC_vctzh, // Vector Count Trailing Zeros Hword +PPC_vctzw, // Vector Count Trailing Zeros Word +PPC_vctzd, // Vector Count Trailing Zeros Dword +PPC_vextractub, // Vector Extract Unsigned Byte +PPC_vextractuh, // Vector Extract Unsigned Hword +PPC_vextractuw, // Vector Extract Unsigned Word +PPC_vextractd, // Vector Extract Dword +PPC_vextsb2w, // Vector Extend Sign Byte to Word +PPC_vextsb2d, // Vector Extend Sign Byte to Dword +PPC_vextsh2w, // Vector Extend Sign Hword to Word +PPC_vextsh2d, // Vector Extend Sign Hword to Dword +PPC_vextsw2d, // Vector Extend Sign Word to Dword +PPC_vextublx, // Vector Extract Unsigned Byte Left-Indexed +PPC_vextubrx, // Vector Extract Unsigned Byte Right-Indexed +PPC_vextuhlx, // Vector Extract Unsigned Hword Left-Indexed +PPC_vextuhrx, // Vector Extract Unsigned Hword Right-Indexed +PPC_vextuwlx, // Vector Extract Unsigned Word Left-Indexed +PPC_vextuwrx, // Vector Extract Unsigned Word Right-Indexed +PPC_vinsertb, // Vector Insert Byte +PPC_vinserth, // Vector Insert Hword +PPC_vinsertw, // Vector Insert Word +PPC_vinsertd, // Vector Insert Dword +PPC_vmul10uq, // Vector Multiply-by-10 Unsigned Qword +PPC_vmul10euq, // Vector Multiply-by-10 Extended Unsigned Qword +PPC_vmul10cuq, // Vector Multiply-by-10 & write Carry Unsigned Qword +PPC_vmul10ecuq, // Vector Multiply-by-10 Extended & write Carry Unsigned Qword +PPC_vnegw, // Vector Negate Word +PPC_vnegd, // Vector Negate Dword +PPC_vpermr, // Vector Permute Right-indexed +PPC_vprtybw, // Vector Parity Byte Word +PPC_vprtybd, // Vector Parity Byte Dword +PPC_vprtybq, // Vector Parity Byte Qword +PPC_vrlwnm, // Vector Rotate Left Word then AND with Mask +PPC_vrlwmi, // Vector Rotate Left Word then Mask Insert +PPC_vrldnm, // Vector Rotate Left Dword then AND with Mask +PPC_vrldmi, // Vector Rotate Left Dword then Mask Insert +PPC_vslv, // Vector Shift Left Variable +PPC_vsrv, // Vector Shift Right Variable + +PPC_lxsd, // Load VSX Scalar Dword +PPC_lxssp, // Load VSX Scalar Single +PPC_lxsibzx, // Load VSX Scalar as Integer Byte & Zero Indexed +PPC_lxsihzx, // Load VSX Scalar as Integer Hword & Zero Indexed +PPC_lxv, // Load VSX Vector +PPC_lxvb16x, // Load VSX Vector Byte*16 Indexed +PPC_lxvh8x, // Load VSX Vector Hword*8 Indexed +PPC_lxvl, // Load VSX Vector with Length +PPC_lxvll, // Load VSX Vector Left-justified with Length +PPC_lxvwsx, // Load VSX Vector Word & Splat Indexed +PPC_lxvx, // Load VSX Vector Indexed +PPC_stxsd, // Store VSX Scalar Dword +PPC_stxsibx, // Store VSX Scalar as Integer Byte Indexed +PPC_stxsihx, // Store VSX Scalar as Integer Hword Indexed +PPC_stxssp, // Store VSX Scalar SP +PPC_stxv, // Store VSX Vector +PPC_stxvb16x, // Store VSX Vector Byte*16 Indexed +PPC_stxvh8x, // Store VSX Vector Hword*8 Indexed +PPC_stxvl, // Store VSX Vector with Length +PPC_stxvll, // Store VSX Vector Left-justified with Length +PPC_stxvx, // Store VSX Vector Indexed + +PPC_xsabsqp, // VSX Scalar Absolute QP +PPC_xsaddqp, // VSX Scalar Add QP +PPC_xscmpexpqp, // VSX Scalar Compare Exponents QP +PPC_xscmpoqp, // VSX Scalar Compare Ordered QP +PPC_xscmpuqp, // VSX Scalar Compare Unordered QP +PPC_xscpsgnqp, // VSX Scalar Copy Sign QP +PPC_xscvdpqp, // VSX Scalar Convert DP to QP +PPC_xscvqpdp, // VSX Scalar Convert QP to DP +PPC_xscvqpsdz, // VSX Scalar Convert QP to Signed Dword truncate +PPC_xscvqpswz, // VSX Scalar Convert QP to Signed Word truncate +PPC_xscvqpudz, // VSX Scalar Convert QP to Unsigned Dword truncate +PPC_xscvqpuwz, // VSX Scalar Convert QP to Unsigned Word truncate +PPC_xscvsdqp, // VSX Scalar Convert Signed Dword to QP +PPC_xscvudqp, // VSX Scalar Convert Unsigned Dword to QP +PPC_xsdivqp, // VSX Scalar Divide QP +PPC_xsiexpqp, // VSX Scalar Insert Exponent QP +PPC_xsmaddqp, // VSX Scalar Multiply-Add QP +PPC_xsmsubqp, // VSX Scalar Multiply-Subtract QP +PPC_xsmulqp, // VSX Scalar Multiply QP +PPC_xsnabsqp, // VSX Scalar Negative Absolute QP +PPC_xsnegqp, // VSX Scalar Negate QP +PPC_xsnmaddqp, // VSX Scalar Negative Multiply-Add QP +PPC_xsnmsubqp, // VSX Scalar Negative Multiply-Subtract QP +PPC_xssqrtqp, // VSX Scalar Square Root QP +PPC_xssubqp, // VSX Scalar Subtract QP +PPC_xsxexpqp, // VSX Scalar Extract Exponent QP +PPC_xsxsigqp, // VSX Scalar Extract Significand QP +PPC_xststdcqp, // VSX Scalar Test Data Class QP +PPC_xsrqpxp, // VSX Scalar Round QP to XP +PPC_xsrqpi, // VSX Scalar Round QP to Integral [with Inexact] +PPC_xscmpeqdp, // VSX Scalar Compare Equal Double-Precision +PPC_xscmpexpdp, // VSX Scalar Compare Exponents DP +PPC_xscmpgedp, // VSX Scalar Compare Greater Than or Equal Double-Precision +PPC_xscmpgtdp, // VSX Scalar Compare Greater Than Double-Precision +PPC_xsiexpdp, // VSX Scalar Insert Exponent DP +PPC_xsmaxcdp, // VSX Scalar Maximum Type-C Double-Precision +PPC_xsmaxjdp, // VSX Scalar Maximum Type-J Double-Precision +PPC_xsmincdp, // VSX Scalar Minimum Type-C Double-Precision +PPC_xsminjdp, // VSX Scalar Minimum Type-J Double-Precision +PPC_xviexpdp, // VSX Vector Insert Exponent DP +PPC_xviexpsp, // VSX Vector Insert Exponent SP +PPC_xxextractuw,// VSX Vector Extract Unsigned Word +PPC_xxinsertw, // VSX Vector Insert Word +PPC_xxperm, // VSX Vector Permute +PPC_xxpermr, // VSX Vector Permute Right-indexed +PPC_xxspltib, // VSX Vector Splat Immediate Byte +PPC_xststdcdp, // VSX Scalar Test Data Class DP +PPC_xststdcsp, // VSX Scalar Test Data Class SP +PPC_xvtstdcdp, // VSX Vector Test Data Class DP +PPC_xvtstdcsp, // VSX Vector Test Data Class SP +PPC_xsxexpdp, // VSX Scalar Extract Exponent DP +PPC_xsxsigdp, // VSX Scalar Extract Significand DP +PPC_xscvdphp, // VSX Scalar Convert DP to HP +PPC_xscvhpdp, // VSX Scalar Convert HP to DP +PPC_xvxexpdp, // VSX Vector Extract Exponent DP +PPC_xvxexpsp, // VSX Vector Extract Exponent SP +PPC_xvxsigdp, // VSX Vector Extract Significand DP +PPC_xvxsigsp, // VSX Vector Extract Significand SP +PPC_xxbrd, // VSX Vector Byte-Reverse Dword +PPC_xxbrh, // VSX Vector Byte-Reverse Hword +PPC_xxbrq, // VSX Vector Byte-Reverse Qword +PPC_xxbrw, // VSX Vector Byte-Reverse Word +PPC_xvcvhpsp, // VSX Vector Convert HP to SP +PPC_xvcvsphp, // VSX Vector Convert SP to HP + +PPC_msgsync, // Message Synchronize + +// Instructions introduced in ISA 3.0 and withdrawn in ISA 3.0B : +// ldmx "Load Dword Monitored Indexed" +// xscmpnedp "VSX Scalar Compare Not Equal Double-Precision" +// xvcmpnedp[.] "VSX Vector Compare Not Equal Double-Precision" +// xvcmpnesp[.] "VSX Vector Compare Not Equal Single-Precision" + +// Power ISA Version 3.0 B +PPC_addex, // Add Extended using alternate carry +PPC_vmsumudm, // Vector Multiply-Sum Unsigned Doubleword Modulo +PPC_mffsce, // Move From FPSCR & Clear Enables +PPC_mffscdrn, // Move From FPSCR Control & set DRN +PPC_mffscdrni, // Move From FPSCR Control & set DRN Immediate +PPC_mffscrn, // Move From FPSCR Control & set RN +PPC_mffscrni, // Move From FPSCR Control & set RN Immediate +PPC_mffsl, // Move From FPSCR Lightweight + +// Cache Bypass Storage APU +PPC_lbdcbx, // Load Byte with Decoration Indexed Cache Bypass +PPC_lhdcbx, // Load Halfword with Decoration Indexed Cache Bypass +PPC_lwdcbx, // Load Word with Decoration Indexed Cache Bypass +PPC_stbdcbx, // Store Byte with Decoration Indexed Cache Bypass +PPC_sthdcbx, // Store Halfword with Decoration Indexed Cache Bypass +PPC_stwdcbx, // Store Word with Decoration Indexed Cache Bypass + +PPC_lbcbx, // Load Byte Indexed Cache Bypass +PPC_lhcbx, // Load Halfword Indexed Cache Bypass +PPC_lwcbx, // Load Word Indexed Cache Bypass +PPC_stbwtx, // Store Byte Indexed Cache Bypass +PPC_sthwtx, // Store Halfword Indexed Cache Bypass +PPC_stwwtx, // Store Word Indexed Cache Bypass +PPC_dsncb, // Decorated Storage Notify Cache Bypass + +// AIOP (E200Z490) +PPC_ldw, // Load Doubleword +PPC_stdw, // Store Doubleword +PPC_lqw, // Load Quadword +PPC_stqw, // Store Quadword +PPC_ldwcb, // Load Doubleword Cache Bypassed +PPC_ldbrw, // Load Byte Reversed Doubleword +PPC_ldwbrw, // Load Two Byte Reversed Words +PPC_stdwwt, // Store Doubleword with Write-Through +PPC_stdbrw, // Store Doubleword Bytes Reversed +PPC_stdwbrw, // Store Doubleword Byte Reversed in Word +PPC_lqdbrw, // Load Quadword Byte Reversed +PPC_stqdbrw, // Store Quadword Byte Reversed +PPC_lwbr, // Load Word Byte Reversed +PPC_lhbr, // Load Halfword Byte Reversed +PPC_stwbr, // Store Word Byte Reversed +PPC_sthbr, // Store Halfword Byte Reversed +PPC_ldwar, // Load Doubleword and reserve +PPC_stdwc, // Store Doubleword conditional on reservation +PPC_addb, // Add Two Bytes +PPC_addbu, // Add Two Unsigned Bytes +PPC_addh, // Add Two Halfwords +PPC_addhu, // Add Two Unsigned Halfwords +PPC_subfb, // Signed Byte One's Complement Add +PPC_subfbu, // Unsigned Byte One's Complement Add +PPC_subfh, // Signed Halfword One's Complement Subtract +PPC_subfhu, // Unsigned Halfword One's Complement Subtract +PPC_byterevw, // Reverse bytes in a word +PPC_byterevh, // Reverse bytes in each halfword +PPC_hwaccel, // Hardware Acceleration Request +PPC_hwacceli, // Hardware Acceleration Request +PPC_ordhwaccel, // Ordered Hardware Acceleration Request +PPC_ordhwacceli,// Ordered Hardware Acceleration Request +PPC_osmcmd, // Ordered Scope Management Command Request +PPC_mpure, // MPU Read Entry Instruction +PPC_mpuwe, // MPU Write Entry Instruction +PPC_mpusync, // MPU Synchronize Instruction + +// EFP 2.0 instructions +PPC_efdmax, // Floating-Point Double-Precision Maximum +PPC_efdmin, // Floating-Point Double-Precision Minimum +PPC_efdsqrt, // Floating-Point Double-Precision Square Root +PPC_efdcfh, // Convert Floating-Point Double-Precision from Half-Precision +PPC_efdcth, // Convert Floating-Point Double-Precision to Half-Precision + + +PPC_last, +}; + +/* +* Interactive disassembler (IDA). +* Copyright (c) 1990-2021 Hex-Rays +* ALL RIGHTS RESERVED. +* +*/ + + + +//---------------------------------------------------------------------- + + +enum NEC850_Instructions +{ + NEC850_NULL = 0, + + NEC850_BREAKPOINT, + NEC850_XORI, + NEC850_XOR, + NEC850_TST1, + NEC850_TST, + NEC850_TRAP, + NEC850_SUBR, + NEC850_SUB, + NEC850_STSR, + NEC850_ST_B, + NEC850_ST_H, + NEC850_ST_W, + NEC850_SST_B, + NEC850_SST_H, + NEC850_SST_W, + NEC850_SLD_B, + NEC850_SLD_H, + NEC850_SLD_W, + NEC850_SHR, + NEC850_SHL, + NEC850_SET1, + NEC850_SETF, + NEC850_SATSUBR, + NEC850_SATSUBI, + NEC850_SATSUB, + NEC850_SATADD, + NEC850_SAR, + NEC850_RETI, + NEC850_ORI, + NEC850_OR, + NEC850_NOT1, + NEC850_NOT, + NEC850_NOP, + NEC850_MULHI, + NEC850_MULH, + NEC850_MOVHI, + NEC850_MOVEA, + NEC850_MOV, + NEC850_LDSR, + NEC850_LD_B, + NEC850_LD_H, + NEC850_LD_W, + NEC850_JR, + NEC850_JMP, + NEC850_JARL, + NEC850_HALT, + NEC850_EI, + NEC850_DIVH, + NEC850_DI, + NEC850_CMP, + NEC850_CLR1, + NEC850_BV, + NEC850_BL, + NEC850_BZ, + NEC850_BNH, + NEC850_BN, + NEC850_BR, + NEC850_BLT, + NEC850_BLE, + NEC850_BNV, + NEC850_BNC, + NEC850_BNZ, + NEC850_BH, + NEC850_BP, + NEC850_BSA, + NEC850_BGE, + NEC850_BGT, + NEC850_ANDI, + NEC850_AND, + NEC850_ADDI, + NEC850_ADD, + + // + // V850E/E1/ES + // + NEC850_SWITCH, + NEC850_ZXB, + NEC850_SXB, + NEC850_ZXH, + NEC850_SXH, + NEC850_DISPOSE_r0, + NEC850_DISPOSE_r, + NEC850_CALLT, + NEC850_DBTRAP, + NEC850_DBRET, + NEC850_CTRET, + + NEC850_SASF, + + NEC850_PREPARE_sp, + NEC850_PREPARE_i, + + NEC850_MUL, + NEC850_MULU, + + NEC850_DIVH_r3, + NEC850_DIVHU, + NEC850_DIV, + NEC850_DIVU, + + NEC850_BSW, + NEC850_BSH, + NEC850_HSW, + + NEC850_CMOV, + + NEC850_SLD_BU, + NEC850_SLD_HU, + NEC850_LD_BU, + NEC850_LD_HU, + + // + // V850E2 + // + NEC850_ADF, // Add on condition flag + + NEC850_HSH, // Halfword swap halfword + NEC850_MAC, // Multiply and add word + NEC850_MACU, // Multiply and add word unsigned + + NEC850_SBF, // Subtract on condition flag + + NEC850_SCH0L, // Search zero from left + NEC850_SCH0R, // Search zero from right + NEC850_SCH1L, // Search one from left + NEC850_SCH1R, // Search one from right + + // + // V850E2M + // + NEC850_CAXI, // Compare and exchange for interlock + NEC850_DIVQ, // Divide word quickly + NEC850_DIVQU, // Divide word unsigned quickly + NEC850_EIRET, // Return from EI level exception + NEC850_FERET, // Return from FE level exception + NEC850_FETRAP, // FE-level Trap + NEC850_RMTRAP, // Runtime monitor trap + NEC850_RIE, // Reserved instruction exception + NEC850_SYNCE, // Synchronize exceptions + NEC850_SYNCM, // Synchronize memory + NEC850_SYNCP, // Synchronize pipeline + NEC850_SYSCALL, // System call + + // floating point (E1F only) + NEC850_CVT_SW, // Real to integer conversion + NEC850_TRNC_SW, // Real to integer conversion + NEC850_CVT_WS, // Integer to real conversion + NEC850_LDFC, // Load to Floating Controls + NEC850_LDFF, // Load to Floating Flags + NEC850_STFC, // Store Floating Controls + NEC850_STFF, // Store Floating Flags + NEC850_TRFF, // Transfer Floating Flags + + // floating point (E2M) + + NEC850_ABSF_D, // Floating-point Absolute Value (Double) + NEC850_ABSF_S, // Floating-point Absolute Value (Single) + NEC850_ADDF_D, // Floating-point Add (Double) + NEC850_ADDF_S, // Floating-point Add (Single) + NEC850_DIVF_D, // Floating-point Divide (Double) + NEC850_DIVF_S, // Floating-point Divide (Single) + NEC850_MAXF_D, // Floating-point Maximum (Double) + NEC850_MAXF_S, // Floating-point Maximum (Single) + NEC850_MINF_D, // Floating-point Minimum (Double) + NEC850_MINF_S, // Floating-point Minimum (Single) + NEC850_MULF_D, // Floating-point Multiply (Double) + NEC850_MULF_S, // Floating-point Multiply (Single) + NEC850_NEGF_D, // Floating-point Negate (Double) + NEC850_NEGF_S, // Floating-point Negate (Single) + NEC850_RECIPF_D, // Reciprocal of a floating-point value (Double) + NEC850_RECIPF_S, // Reciprocal of a floating-point value (Single + + NEC850_RSQRTF_D, // Reciprocal of the square root of a floating-point value (Double) + NEC850_RSQRTF_S, // Reciprocal of the square root of a floating-point value (Single) + NEC850_SQRTF_D, // Floating-point Square Root (Double) + NEC850_SQRTF_S, // Floating-point Square Root (Single) + NEC850_SUBF_D, // Floating-point Subtract (Double) + NEC850_SUBF_S, // Floating-point Subtract (Single) + NEC850_MADDF_S, // Floating-point Multiply-Add (Single) + NEC850_MSUBF_S, // Floating-point Multiply-Subtract (Single) + NEC850_NMADDF_S, // Floating-point Negate Multiply-Add (Single) + NEC850_NMSUBF_S, // Floating-point Negate Multiply-Subtract (Single) + + NEC850_CEILF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double) + NEC850_CEILF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double) + NEC850_CEILF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single) + NEC850_CEILF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single) + NEC850_CEILF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double) + NEC850_CEILF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double) + NEC850_CEILF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single) + NEC850_CEILF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single) + NEC850_CVTF_DL, // Floating-point Convert to Long Fixed-point Format (Double) + NEC850_CVTF_DS, // Floating-point Convert to Single Floating-point Format (Double) + NEC850_CVTF_DUL, // Floating-point Convert Double to Unsigned-Long (Double) + NEC850_CVTF_DUW, // Floating-point Convert Double to Unsigned-Word (Double) + NEC850_CVTF_DW, // Floating-point Convert to Single Fixed-point Format (Double) + NEC850_CVTF_LD, // Floating-point Convert to Single Floating-point Format (Double) + NEC850_CVTF_LS, // Floating-point Convert to Single Floating-point Format (Single) + NEC850_CVTF_SD, // Floating-point Convert to Double Floating-point Format (Double) + NEC850_CVTF_SL, // Floating-point Convert to Long Fixed-point Format (Single) + NEC850_CVTF_SUL, // Floating-point Convert Single to Unsigned-Long (Single) + NEC850_CVTF_SUW, // Floating-point Convert Single to Unsigned-Word (Single) + NEC850_CVTF_SW, // Floating-point Convert to Single Fixed-point Format (Single) + NEC850_CVTF_ULD, // Floating-point Convert Unsigned-Long to Double (Double) + NEC850_CVTF_ULS, // Floating-point Convert Unsigned-Long to Single (Single) + NEC850_CVTF_UWD, // Floating-point Convert Unsigned-Word to Double (Double) + NEC850_CVTF_UWS, // Floating-point Convert Unsigned-Word to Single (Single) + NEC850_CVTF_WD, // Floating-point Convert to Single Floating-point Format (Double) + NEC850_CVTF_WS, // Floating-point Convert to Single Floating-point Format (Single) + NEC850_FLOORF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double) + NEC850_FLOORF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double) + NEC850_FLOORF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single) + NEC850_FLOORF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single) + NEC850_FLOORF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double) + NEC850_FLOORF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double) + NEC850_FLOORF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single) + NEC850_FLOORF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single) + NEC850_TRNCF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double) + NEC850_TRNCF_DUL, // Floating-point Truncate Double to Unsigned-Long (Double) + NEC850_TRNCF_DUW, // Floating-point Truncate Double to Unsigned-Word (Double) + NEC850_TRNCF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double) + NEC850_TRNCF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single) + NEC850_TRNCF_SUL, // Floating-point Truncate Single to Unsigned-Long (Single) + NEC850_TRNCF_SUW, // Floating-point Truncate Single to Unsigned-Word (Single) + NEC850_TRNCF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single) + NEC850_CMPF_S, // Compares floating-point values (Single) + NEC850_CMPF_D, // Compares floating-point values (Double) + NEC850_CMOVF_S, // Floating-point conditional move (Single) + NEC850_CMOVF_D, // Floating-point conditional move (Double) + NEC850_TRFSR, // Transfers specified CC bit to Zero flag in PSW (Single) + + // + // RH850 + // + NEC850_SYNCI, // Synchronize instruction pipeline + NEC850_SNOOZE, // Snooze + NEC850_BINS, // Bitfield Insert + NEC850_ROTL, // Rotate Left + NEC850_LOOP, // Loop + NEC850_LD_DW, // Load Double Word + NEC850_ST_DW, // Store Double Word + NEC850_LDL_W, // Load Linked + NEC850_STC_W, // Store Conditional + NEC850_CLL, // Clear Load Link + NEC850_CACHE, // Cache operation + NEC850_PREF, // Prefetch + NEC850_PUSHSP, // Push registers to Stack + NEC850_POPSP, // Pop registers from Stack + + // new RH850 FP instructions + NEC850_CVTF_HS, // Floating-point Convert Half to Single (Single) + NEC850_CVTF_SH, // Floating-point Convert Single to Half (Single) + NEC850_FMAF_S, // Floating-point Fused-Multiply-add (Single) + NEC850_FMSF_S, // Floating-point Fused-Multiply-subtract (Single) + NEC850_FNMAF_S, // Floating-point Fused-Negate-Multiply-add (Single) + NEC850_FNMSF_S, // Floating-point Fused-Negate-Multiply-subtract (Single) + + // debug instructions + NEC850_DBPUSH, // + NEC850_DBCP, // + NEC850_DBTAG, // + NEC850_DBHVTRAP, // + + // virtualization instructions + NEC850_EST, // + NEC850_DST, // + NEC850_HVTRAP, // + NEC850_HVCALL, // + NEC850_LDVC_SR, // + NEC850_STVC_SR, // + NEC850_LDTC_GR, // + NEC850_STTC_GR, // + NEC850_LDTC_PC, // + NEC850_STTC_PC, // + NEC850_LDTC_SR, // + NEC850_STTC_SR, // + NEC850_LDTC_VR, // + NEC850_STTC_VR, // + + // TLB instructions + NEC850_TLBAI, // + NEC850_TLBR, // + NEC850_TLBS, // + NEC850_TLBVI, // + NEC850_TLBW, // + + NEC850_LAST_INSTRUCTION +}; + +/* + * Tricore Disassembly Module + * Version 1.0 + * Copyright (c) 2000 by Juergen Krumm + * ALL RIGHTS RESERVED + * + * + */ + + + +enum +{ + TRICORE_null = 0, // Unknown Operation + TRICORE_abs, + TRICORE_abs_b, + TRICORE_abs_h, + TRICORE_absdif, + TRICORE_absdif_b, + TRICORE_absdif_h, + TRICORE_absdifs, + TRICORE_absdifs_h, + TRICORE_abss, + TRICORE_abss_h, + TRICORE_add_b, + TRICORE_add_f, + TRICORE_add_h, + TRICORE_add16, + TRICORE_add16_a, + TRICORE_add32, + TRICORE_add32_a, + TRICORE_addc, + TRICORE_addi, + TRICORE_addih, + TRICORE_addih_a, + TRICORE_adds, + TRICORE_adds_h, + TRICORE_adds_hu, + TRICORE_adds_u, + TRICORE_adds16, + TRICORE_addsc_at, + TRICORE_addsc16_a, + TRICORE_addsc32_a, + TRICORE_addx, + TRICORE_and_and_t, + TRICORE_and_andn_t, + TRICORE_and_eq, + TRICORE_and_ge, + TRICORE_and_ge_u, + TRICORE_and_lt, + TRICORE_and_lt_u, + TRICORE_and_ne, + TRICORE_and_nor_t, + TRICORE_and_or_t, + TRICORE_and_t, + TRICORE_and16, + TRICORE_and32, + TRICORE_andn, + TRICORE_andn_t, + TRICORE_bisr16, + TRICORE_bisr32, + TRICORE_bmerge, + TRICORE_bsplit, + TRICORE_cachea_i, + TRICORE_cachea_w, + TRICORE_cachea_wi, + TRICORE_cadd16, + TRICORE_cadd32, + TRICORE_caddn16, + TRICORE_caddn32, + TRICORE_call16, + TRICORE_call32, + TRICORE_calla, + TRICORE_calli, + TRICORE_clo, + TRICORE_clo_h, + TRICORE_cls, + TRICORE_cls_h, + TRICORE_clz, + TRICORE_clz_h, + TRICORE_cmov16, + TRICORE_cmovn16, + TRICORE_cmp_f, + TRICORE_csub, + TRICORE_csubn, + TRICORE_debug16, + TRICORE_debug32, + TRICORE_dextr, + TRICORE_disable, + TRICORE_div_f, + TRICORE_dsync, + TRICORE_dvadj, + TRICORE_dvinit, + TRICORE_dvinit_b, + TRICORE_dvinit_bu, + TRICORE_dvinit_h, + TRICORE_dvinit_hu, + TRICORE_dvinit_u, + TRICORE_dvstep, + TRICORE_dvstep_u, + TRICORE_enable, + TRICORE_eq_a, + TRICORE_eq_b, + TRICORE_eq_h, + TRICORE_eq_w, + TRICORE_eq16, + TRICORE_eq32, + TRICORE_eqany_b, + TRICORE_eqany_h, + TRICORE_eqz_a, + TRICORE_extr, + TRICORE_extr_u, + TRICORE_ftoi, + TRICORE_ftoq31, + TRICORE_ftou, + TRICORE_ge, + TRICORE_ge_a, + TRICORE_ge_u, + TRICORE_imask, + TRICORE_ins_t, + TRICORE_insert, + TRICORE_insn_t, + TRICORE_isync, + TRICORE_itof, + TRICORE_ixmax, + TRICORE_ixmax_u, + TRICORE_ixmin, + TRICORE_ixmin_u, + TRICORE_j16, + TRICORE_j32, + TRICORE_ja, + TRICORE_jeq_a, + TRICORE_jeq16, + TRICORE_jeq32, + TRICORE_jge, + TRICORE_jge_u, + TRICORE_jgez16, + TRICORE_jgtz16, + TRICORE_ji16, + TRICORE_ji32, + TRICORE_jl, + TRICORE_jla, + TRICORE_jlez16, + TRICORE_jli, + TRICORE_jlt, + TRICORE_jlt_u, + TRICORE_jltz16, + TRICORE_jne_a, + TRICORE_jne16, + TRICORE_jne32, + TRICORE_jned, + TRICORE_jnei, + TRICORE_jnz16, + TRICORE_jnz16_a, + TRICORE_jnz16_t, + TRICORE_jnz32_a, + TRICORE_jnz32_t, + TRICORE_jz16, + TRICORE_jz16_a, + TRICORE_jz16_t, + TRICORE_jz32_a, + TRICORE_jz32_t, + TRICORE_ld_b, + TRICORE_ld_d, + TRICORE_ld_da, + TRICORE_ld_hu, + TRICORE_ld_q, + TRICORE_ld16_a, + TRICORE_ld16_bu, + TRICORE_ld16_h, + TRICORE_ld16_w, + TRICORE_ld32_a, + TRICORE_ld32_bu, + TRICORE_ld32_h, + TRICORE_ld32_w, + TRICORE_ldlcx, + TRICORE_ldmst, + TRICORE_lducx, + TRICORE_lea, + TRICORE_loop16, + TRICORE_loop32, + TRICORE_loopu, + TRICORE_lt_a, + TRICORE_lt_b, + TRICORE_lt_bu, + TRICORE_lt_h, + TRICORE_lt_hu, + TRICORE_lt_u, + TRICORE_lt_w, + TRICORE_lt_wu, + TRICORE_lt16, + TRICORE_lt32, + TRICORE_madd, + TRICORE_madd_f, + TRICORE_madd_h, + TRICORE_madd_q, + TRICORE_madd_u, + TRICORE_maddm_h, + TRICORE_maddms_h, + TRICORE_maddr_h, + TRICORE_maddr_q, + TRICORE_maddrs_h, + TRICORE_maddrs_q, + TRICORE_madds, + TRICORE_madds_h, + TRICORE_madds_q, + TRICORE_madds_u, + TRICORE_maddsu_h, + TRICORE_maddsum_h, + TRICORE_maddsums_h, + TRICORE_maddsur_h, + TRICORE_maddsurs_h, + TRICORE_maddsus_h, + TRICORE_max, + TRICORE_max_b, + TRICORE_max_bu, + TRICORE_max_h, + TRICORE_max_hu, + TRICORE_max_u, + TRICORE_mfcr, + TRICORE_min, + TRICORE_min_b, + TRICORE_min_bu, + TRICORE_min_h, + TRICORE_min_hu, + TRICORE_min_u, + TRICORE_mov_u, + TRICORE_mov16, + TRICORE_mov16_a, + TRICORE_mov16_aa, + TRICORE_mov16_d, + TRICORE_mov32, + TRICORE_mov32_a, + TRICORE_mov32_aa, + TRICORE_mov32_d, + TRICORE_movh, + TRICORE_movh_a, + TRICORE_msub, + TRICORE_msub_f, + TRICORE_msub_h, + TRICORE_msub_q, + TRICORE_msub_u, + TRICORE_msubad_h, + TRICORE_msubadm_h, + TRICORE_msubadms_h, + TRICORE_msubadr_h, + TRICORE_msubadrs_h, + TRICORE_msubads_h, + TRICORE_msubm_h, + TRICORE_msubms_h, + TRICORE_msubr_h, + TRICORE_msubr_q, + TRICORE_msubrs_h, + TRICORE_msubrs_q, + TRICORE_msubs, + TRICORE_msubs_h, + TRICORE_msubs_q, + TRICORE_msubs_u, + TRICORE_mtcr, + TRICORE_mul_f, + TRICORE_mul_h, + TRICORE_mul_q, + TRICORE_mul_u, + TRICORE_mul16, + TRICORE_mul32, + TRICORE_mulm_h, + TRICORE_mulms_h, + TRICORE_mulr_h, + TRICORE_mulr_q, + TRICORE_muls, + TRICORE_muls_u, + TRICORE_nand, + TRICORE_nand_t, + TRICORE_ne, + TRICORE_ne_a, + TRICORE_nez_a, + TRICORE_nop16, + TRICORE_nop32, + TRICORE_nor_t, + TRICORE_nor16, + TRICORE_nor32, + TRICORE_or_and_t, + TRICORE_or_andn_t, + TRICORE_or_eq, + TRICORE_or_ge, + TRICORE_or_ge_u, + TRICORE_or_lt, + TRICORE_or_lt_u, + TRICORE_or_ne, + TRICORE_or_nor_t, + TRICORE_or_or_t, + TRICORE_or_t, + TRICORE_or16, + TRICORE_or32, + TRICORE_orn, + TRICORE_orn_t, + TRICORE_pack, + TRICORE_parity, + TRICORE_q31tof, + TRICORE_qseed_f, + TRICORE_ret16, + TRICORE_ret32, + TRICORE_rfe16, + TRICORE_rfe32, + TRICORE_rfm, + TRICORE_rslcx, + TRICORE_rstv, + TRICORE_rsub16, + TRICORE_rsub32, + TRICORE_rsubs, + TRICORE_rsubs_u, + TRICORE_sat16_b, + TRICORE_sat16_bu, + TRICORE_sat16_h, + TRICORE_sat16_hu, + TRICORE_sat32_b, + TRICORE_sat32_bu, + TRICORE_sat32_h, + TRICORE_sat32_hu, + TRICORE_sel, + TRICORE_seln, + TRICORE_sh_and_t, + TRICORE_sh_andn_t, + TRICORE_sh_eq, + TRICORE_sh_ge, + TRICORE_sh_ge_u, + TRICORE_sh_h, + TRICORE_sh_lt, + TRICORE_sh_lt_u, + TRICORE_sh_nand_t, + TRICORE_sh_ne, + TRICORE_sh_nor_t, + TRICORE_sh_or_t, + TRICORE_sh_orn_t, + TRICORE_sh_xnor_t, + TRICORE_sh_xor_t, + TRICORE_sh16, + TRICORE_sh32, + TRICORE_sha_h, + TRICORE_sha16, + TRICORE_sha32, + TRICORE_shas, + TRICORE_st_d, + TRICORE_st_da, + TRICORE_st_q, + TRICORE_st_t, + TRICORE_st16_a, + TRICORE_st16_b, + TRICORE_st16_h, + TRICORE_st16_w, + TRICORE_st32_a, + TRICORE_st32_b, + TRICORE_st32_h, + TRICORE_st32_w, + TRICORE_stlcx, + TRICORE_stucx, + TRICORE_sub_b, + TRICORE_sub_f, + TRICORE_sub_h, + TRICORE_sub16, + TRICORE_sub16_a, + TRICORE_sub32, + TRICORE_sub32_a, + TRICORE_subc, + TRICORE_subs_h, + TRICORE_subs_hu, + TRICORE_subs_u, + TRICORE_subs16, + TRICORE_subs32, + TRICORE_subx, + TRICORE_svlcx, + TRICORE_swap_w, + TRICORE_syscall, + TRICORE_tlbdemap, + TRICORE_tlbflush_a, + TRICORE_tlbflush_b, + TRICORE_tlbmap, + TRICORE_tlbprobe_a, + TRICORE_tlbprobe_i, + TRICORE_trapsv, + TRICORE_trapv, + TRICORE_unpack, + TRICORE_updfl, + TRICORE_utof, + TRICORE_xnor, + TRICORE_xnor_t, + TRICORE_xor_eq, + TRICORE_xor_ge, + TRICORE_xor_ge_u, + TRICORE_xor_lt, + TRICORE_xor_lt_u, + TRICORE_xor_ne, + TRICORE_xor_t, + TRICORE_xor16, + TRICORE_xor32, + + // new v1.6 instructions + TRICORE_cachei_i, + TRICORE_cachei_w, + TRICORE_cachei_wi, + TRICORE_div, + TRICORE_div_u, + TRICORE_fcall, + TRICORE_fcalla, + TRICORE_fcalli, + TRICORE_fret16, + TRICORE_fret32, + TRICORE_ftoiz, + TRICORE_ftoq31z, + TRICORE_ftouz, + TRICORE_restore, + + // new v1.6.1 instructions + TRICORE_crc32, // Calculate CRC32 + TRICORE_wait, // Suspend execution until the next enabled interrupt or asynchronous trap event + TRICORE_cmpswap_w, // Compare and swap + TRICORE_swapmsk_w, // Swap under mask + + // new v1.6.2 instructions + TRICORE_crc32_b, // CRC32 for big endian data + TRICORE_crc32l_w, // CRC32 for little endian data + TRICORE_crcn, // Arbitrary width and polynomial CRC calculation + TRICORE_shuffle, // Reorder bytes within word + TRICORE_popcnt_w, // Count number of bits set in word + TRICORE_lha, // Load high bits of address value + + TRICORE_last +}; + + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + + ARC_null = 0, // Unknown Operation + + ARC_ld, // Load + ARC_lr, // Load from auxiliary register + ARC_st, // Store + ARC_sr, // Store to auxiliary register + ARC_store_instructions = ARC_sr, + ARC_flag, // Set flags + ARC_asr, // Arithmetic shift right + ARC_lsr, // Logical shift right + ARC_sexb, // Sign extend byte + ARC_sexw, // Sign extend word + ARC_sexh = ARC_sexw, + ARC_extb, // Zero extend byte + ARC_extw, // Zero extend word + ARC_exth = ARC_extw, + ARC_ror, // Rotate right + ARC_rrc, // Rotate right through carry + ARC_b, // Branch + ARC_bl, // Branch and link + ARC_lp, // Zero-overhead loop setup + ARC_j, // Jump + ARC_jl, // Jump and link + ARC_add, // Add + ARC_adc, // Add with carry + ARC_sub, // Subtract + ARC_sbc, // Subtract with carry + ARC_and, // Logical bitwise AND + ARC_or, // Logical bitwise OR + ARC_bic, // Logical bitwise AND with invert + ARC_xor, // Logical bitwise exclusive-OR + + // pseudo instructions + ARC_mov, // Move + ARC_nop, // No operation + ARC_lsl, // Logical shift left + ARC_rlc, // Rotate left through carry + + // arc7 + ARC_brk, // Breakpoint + ARC_sleep, // Sleep until interrupt or restart + + // arc8 + ARC_swi, // Software interrupt + + // extra optional instrutions + ARC_asl, // Arithmetic shift left + ARC_mul64, // Signed 32x32 multiply + ARC_mulu64, // Unsigned 32x32 multiply + ARC_max, // Maximum of two signed integers + ARC_min, // Minimum of two signed integers + ARC_swap, // Exchange upper and lower 16 bits + ARC_norm, // Normalize (find-first-bit) + + // ARCompact instructions + ARC_bbit0, // Branch if bit cleared to 0 + ARC_bbit1, // Branch if bit set to 1 + ARC_br, // Branch on compare + ARC_pop, // Restore register value from stack + ARC_push, // Store register value on stack + + ARC_abs, // Absolute value + ARC_add1, // Add with left shift by 1 bit + ARC_add2, // Add with left shift by 2 bits + ARC_add3, // Add with left shift by 3 bits + ARC_bclr, // Clear specified bit (to 0) + ARC_bmsk, // Bit Mask + ARC_bset, // Set specified bit (to 1) + ARC_btst, // Test value of specified bit + ARC_bxor, // Bit XOR + ARC_cmp, // Compare + ARC_ex, // Atomic Exchange + ARC_mpy, // Signed 32x32 multiply (low) + ARC_mpyh, // Signed 32x32 multiply (high) + ARC_mpym = ARC_mpyh, + ARC_mpyhu, // Unsigned 32x32 multiply (high) + ARC_mpyhm = ARC_mpyhu, + ARC_mpyu, // Unsigned 32x32 multiply (low) + ARC_neg, // Negate + ARC_not, // Logical bit inversion + ARC_rcmp, // Reverse Compare + ARC_rsub, // Reverse Subtraction + ARC_rtie, // Return from Interrupt/Exception + ARC_sub1, // Subtract with left shift by 1 bit + ARC_sub2, // Subtract with left shift by 2 bits + ARC_sub3, // Subtract with left shift by 3 bits + ARC_sync, // Synchronize + ARC_trap, // Raise an exception + ARC_tst, // Test + ARC_unimp, // Unimplemented instruction + + ARC_abss, // Absolute and saturate + ARC_abssw, // Absolute and saturate of word + ARC_abssh = ARC_abssw, + ARC_adds, // Add and saturate + ARC_addsdw, // Add and saturate dual word + ARC_asls, // Arithmetic shift left and saturate + ARC_asrs, // Arithmetic shift right and saturate + ARC_divaw, // Division assist + ARC_negs, // Negate and saturate + ARC_negsw, // Negate and saturate of word + ARC_negsh = ARC_negsw, + ARC_normw, // Normalize to 16 bits + ARC_normh = ARC_normw, + ARC_rnd16, // Round to word + ARC_rndh = ARC_rnd16, + ARC_sat16, // Saturate to word + ARC_sath = ARC_sat16, + ARC_subs, // Subtract and saturate + ARC_subsdw, // Subtract and saturate dual word + + // mac d16 + ARC_muldw, + ARC_muludw, + ARC_mulrdw, + ARC_macdw, + ARC_macudw, + ARC_macrdw, + ARC_msubdw, + + // 32x16 MUL/MAC + ARC_mululw, + ARC_mullw, + ARC_mulflw, + ARC_maclw, + ARC_macflw, + ARC_machulw, + ARC_machlw, + ARC_machflw, + ARC_mulhlw, + ARC_mulhflw, + + // Major 6 compact insns + ARC_acm, + ARC_addqbs, + ARC_avgqb, + ARC_clamp, + ARC_daddh11, + ARC_daddh12, + ARC_daddh21, + ARC_daddh22, + ARC_dexcl1, + ARC_dexcl2, + ARC_dmulh11, + ARC_dmulh12, + ARC_dmulh21, + ARC_dmulh22, + ARC_dsubh11, + ARC_dsubh12, + ARC_dsubh21, + ARC_dsubh22, + ARC_drsubh11, + ARC_drsubh12, + ARC_drsubh21, + ARC_drsubh22, + ARC_fadd, + ARC_fsadd = ARC_fadd, + ARC_fmul, + ARC_fsmul = ARC_fmul, + ARC_fsub, + ARC_fssub = ARC_fsub, + ARC_fxtr, + ARC_iaddr, + ARC_mpyqb, + ARC_sfxtr, + ARC_pkqb, + ARC_upkqb, + ARC_xpkqb, + + // ARCv2 only major 4 instructions + ARC_mpyw, // Signed 16x16 multiply + ARC_mpyuw, // Unsigned 16x16 multiply + ARC_bi, // Branch indexed + ARC_bih, // Branch indexed half-word + ARC_ldi, // Load indexed + ARC_aex, // Exchange with auxiliary register + ARC_bmskn, // Bit mask negated + ARC_seteq, // Set if equal + ARC_setne, // Set if not equal + ARC_setlt, // Set if less than + ARC_setge, // Set if greater or equal + ARC_setlo, // Set if lower than + ARC_seths, // Set if higher or same + ARC_setle, // Set if less than or equal + ARC_setgt, // Set if greater than + + ARC_rol, // Rotate left + ARC_llock, // Load locked + ARC_scond, // Store conditional + + ARC_seti, // Set interrupt enable and priority level + ARC_clri, // Cler and get interrupt enable and priority level + + // ARCv2 compact prolog / epilog instructions + ARC_enter, // Function prologue sequence + ARC_leave, // Function epilogue sequence + + // ARCv2 32-bit extension major 5 DOP instructions + ARC_div, // Signed integer divsion + ARC_divu, // Unsigned integer divsion + ARC_rem, // Signed integer remainder + ARC_remu, // Unsigned integer remainder + ARC_asrsr, // Shift right rounding and saturating + ARC_valgn2h, // Two-way 16-bit vector align + ARC_setacc, // Set the accumulator + ARC_mac, // Signed 32x32 multiply accumulate + ARC_macu, // Unsigned 32x32 multiply accumulate + ARC_dmpyh, // Sum of dual signed 16x16 multiplication + ARC_dmpyhu, // Sum of dual unsigned 16x16 multiplication + ARC_dmach, // Dual signed 16x16 multiply accumulate + ARC_dmachu, // Dual unsigned 16x16 multiply accumulate + ARC_vadd2h, // Dual 16-bit addition + ARC_vadds2h, // Dual 16-bit saturating addition + ARC_vsub2h, // Dual 16-bit subtraction + ARC_vsubs2h, // Dual 16-bit saturating subtraction + ARC_vaddsub2h, // Dual 16-bit addition/subtraction + ARC_vaddsubs2h, // Dual 16-bit saturating addition/subtraction + ARC_vsubadd2h, // Dual 16-bit subtraction/addition + ARC_vsubadds2h, // Dual 16-bit saturating subtraction/addition + ARC_mpyd, // Signed 32x32 multiply (wide) + ARC_mpydu, // Unsigned 32x32 multiply (wide) + ARC_macd, // Signed 32x32 multiply accumulate (wide) + ARC_macdu, // Unsigned 32x32 multiply accumulate (wide) + ARC_vmpy2h, // Dual signed 16x16 multiply (wide) + ARC_vmpy2hf, // Dual 16x16 saturating fractional multiply + ARC_vmpy2hu, // Dual unsigned 16x16 multiply (wide) + ARC_vmpy2hfr, // Dual 16x16 saturating rounded fractional multiply + ARC_vmac2h, // Dual signed 16x16 multiply (wide) + ARC_vmac2hf, // Dual 16x16 saturating fractional multiply + ARC_vmac2hu, // Dual unsigned 16x16 multiply (wide) + ARC_vmac2hfr, // Dual 16x16 saturating rounded fractional multiply + ARC_vmpy2hwf, // Dual 16x16 saturating fractional multiply (wide) + ARC_vasl2h, // Dual 16-bit arithmetic shift left + ARC_vasls2h, // Dual 16-bit saturating arithmetic shift left + ARC_vasr2h, // Dual 16-bit arithmetic shift right + ARC_vasrs2h, // Dual 16-bit saturating arithmetic shift right + ARC_vlsr2h, // Dual 16-bit logical shift right + ARC_vasrsr2h, // Dual 16-bit saturating rounded arithmetic shift right + ARC_vadd4b, // Quad 8-bit addition + ARC_vmax2h, // Dual 16-bit maximum + ARC_vsub4b, // Quad 8-bit subtraction + ARC_vmin2h, // Dual 16-bit minimum + ARC_adcs, // Signed saturating addition with carry in + ARC_sbcs, // Signed saturating subtraction with carry in + ARC_dmpyhwf, // Fractional saturating sum of dual 16x16 signed fractional multiply + ARC_vpack2hl, // Compose lower 16-bits + ARC_vpack2hm, // Compose upper 16-bits + ARC_dmpyhf, // Saturating sum of dual 16x16 signed fractional multiply + ARC_dmpyhfr, // Saturating rounded sum of dual 16x16 signed fractional multiply + ARC_dmachf, // Saturating sum of dual 16x16 signed fractional multiply accumulate + ARC_dmachfr, // Saturating rounded sum of dual 16x16 signed fractional multiply accumulate + ARC_vperm, // Byte permutation with zero or sign extension + ARC_bspush, // Bitstream push + + // ARCv2 32-bit extension major 5 SOP instructions + ARC_swape, // Swap byte ordering + ARC_lsl16, // Logical shift left by 16 bits + ARC_lsr16, // Logical shift right by 16 bits + ARC_asr16, // Arithmetic shift right by 16 bits + ARC_asr8, // Arithmetic shift right by 8 bits + ARC_lsr8, // Logical shift right by 8 bits + ARC_lsl8, // Logical shift left by 8 bits + ARC_rol8, // Rotate left by 8 bits + ARC_ror8, // Rotate right by 8 bits + ARC_ffs, // Find first set bit + ARC_fls, // Find last set bit + + ARC_getacc, // Get accumulator + ARC_normacc, // Normalize accumulator + ARC_satf, // Saturate according to flags + ARC_vpack2hbl, // Pack lower bytes into lower 16 bits + ARC_vpack2hbm, // Pack upper bytes into upper 16 bits + ARC_vpack2hblf, // Pack upper bytes into lower 16 bits + ARC_vpack2hbmf, // Pack lower bytes into upper 16 bits + ARC_vext2bhlf, // Pack lower 2 bytes into upper byte of 16 bits each + ARC_vext2bhmf, // Pack upper 2 bytes into upper byte of 16 bits each + ARC_vrep2hl, // Repeat lower 16 bits + ARC_vrep2hm, // Repeat upper 16 bits + ARC_vext2bhl, // Pack lower 2 bytes into zero extended 16 bits + ARC_vext2bhm, // Pack upper 2 bytes into zero extended 16 bits + ARC_vsext2bhl, // Pack lower 2 bytes into sign extended 16 bits + ARC_vsext2bhm, // Pack upper 2 bytes into sign extended 16 bits + ARC_vabs2h, // Dual 16-bit absolute value + ARC_vabss2h, // Dual saturating 16-bit absolute value + ARC_vneg2h, // Dual 16-bit negation + ARC_vnegs2h, // Dual saturating 16-bit negation + ARC_vnorm2h, // Dual 16-bit normalization + ARC_bspeek, // Bitstream peek + ARC_bspop, // Bitstream pop + ARC_sqrt, // Integer square root + ARC_sqrtf, // Fractional square root + + // ARCv2 32-bit extension major 5 ZOP instructions + ARC_aslacc, // Arithmetic shift of accumulator + ARC_aslsacc, // Saturating arithmetic shift of accumulator + ARC_flagacc, // Copy accumulator flags to status32 register + ARC_modif, // Update address pointer + + // ARCv2 32-bit extension major 6 DOP instructions + ARC_cmpyhnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply + ARC_cmpyhfr, // Fractional 16+16 bit complex saturating rounded multiply + ARC_cmpychfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply + ARC_vmsub2hf, // Dual 16x16 saturating fractional multiply subtract + ARC_vmsub2hfr, // Dual 16x16 saturating rounded fractional multiply subtract + ARC_cmpychnfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply + ARC_cmachnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply accumulate + ARC_cmachfr, // Fractional 16+16 bit complex saturating rounded unshifted accumulate + ARC_cmacchnfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply accumulate + ARC_cmacchfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply accumulate + ARC_mpyf, // Signed 32-bit fractional saturating multiply + ARC_mpyfr, // Signed 32-bit fractional saturating rounded multiply + ARC_macf, // Signed 32-bit fractional saturating multiply accumulate + ARC_macfr, // Signed 32-bit fractional saturating rounded multiply accumulate + ARC_msubf, // Signed 32-bit fractional saturating multiply subtract + ARC_msubfr, // Signed 32-bit fractional saturating rounded multiply subtract + ARC_divf, // Signed 32-bit fractional division + ARC_vmac2hnfr, // Dual signed 16-bit fractional saturating rounded multiply accumulate + ARC_vmsub2hnfr, // Dual signed 16-bit fractional saturating rounded multiply subtract + ARC_mpydf, // Signed 32-bit fractional multiply (wide) + ARC_macdf, // Signed 32-bit fractional multiply accumulate (wide) + ARC_msubwhfl, // Signed 32 x 16 (lower) fractional saturating multiply subtract + ARC_msubdf, // Signed 32-bit fractional multiply subtract (wide) + ARC_dmpyhbl, // Dual 16x8 signed multiply with lower two bytes + ARC_dmpyhbm, // Dual 16x8 signed multiply with upper two bytes + ARC_dmachbl, // Dual 16x8 signed multiply accumulate with lower two bytes + ARC_dmachbm, // Dual 16x8 signed multiply accumulate with upper two bytes + ARC_msubwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply subtract + ARC_cmpyhfmr, // Fractional 16+16 bit complex x 16bit real (upper) saturating rounded multiply + ARC_cbflyhf0r, // Fractional 16+16 bit complex FFT butterfly, first half + ARC_mpywhl, // Signed 32 x 16 (lower) multiply + ARC_macwhl, // Signed 32 x 16 (lower) multiply accumulate + ARC_mpywhul, // Unsigned 32 x 16 (lower) multiply + ARC_macwhul, // Unsigned 32 x 16 (lower) multiply accumulate + ARC_mpywhfm, // Signed 32 x 16 (upper) fractional saturating multiply + ARC_mpywhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply + ARC_macwhfm, // Signed 32 x 16 (upper) fractional saturating multiply accumulate + ARC_macwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply accumulate + ARC_mpywhfl, // Signed 32 x 16 (lower) fractional saturating multiply + ARC_mpywhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply + ARC_macwhfl, // Signed 32 x 16 (lower) fractional saturating multiply accumulate + ARC_macwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply accumulate + ARC_macwhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply accumulate + ARC_macwhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply accumulate + ARC_mpywhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply + ARC_mpywhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply + ARC_msubwhfm, // Signed 32 x 16 (upper) fractional saturating multiply subtract + ARC_msubwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply subtract + + // ARCv2 32-bit extension major 6 SOP instructions + ARC_cbflyhf1r, // Fractional 16+16 bit complex FFT butterfly, second half + + // ARCv2 FPU instructions + ARC_fscmp, // Single precision floating point compare + ARC_fscmpf, // Single precision floating point compare (IEEE 754 flag generation) + ARC_fsmadd, // Single precision floating point fused multiply add + ARC_fsmsub, // Single precision floating point fused multiply subtract + ARC_fsdiv, // Single precision floating point division + ARC_fcvt32, // Single precision floating point / integer conversion + ARC_fssqrt, // Single precision floating point square root + + // ARCv2 jump / execute indexed instructions + ARC_jli, // Jump and link indexed + ARC_ei, // Execute indexed + + ARC_kflag, // Set kernel flags + ARC_wevt, // Enter sleep state + + ARC_last, +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + + + +enum +{ + +TMS28_null = 0, // Unknown Operation + +TMS28_aborti, +TMS28_abs, +TMS28_abstc, +TMS28_add, +TMS28_addb, +TMS28_addcl, +TMS28_addcu, +TMS28_addl, +TMS28_addu, +TMS28_addul, +TMS28_adrk, +TMS28_and, +TMS28_andb, +TMS28_asp, +TMS28_asr, +TMS28_asr64, +TMS28_asrl, +TMS28_b, +TMS28_banz, +TMS28_bar, +TMS28_bf, +TMS28_c27map, +TMS28_c27obj, +TMS28_c28addr, +TMS28_c28map, +TMS28_c28obj, +TMS28_clrc, +TMS28_cmp, +TMS28_cmp64, +TMS28_cmpb, +TMS28_cmpl, +TMS28_cmpr, +TMS28_csb, +TMS28_dec, +TMS28_dint, +TMS28_dmac, +TMS28_dmov, +TMS28_eallow, +TMS28_edis, +TMS28_eint, +TMS28_estop0, +TMS28_estop1, +TMS28_ffc, +TMS28_flip, +TMS28_iack, +TMS28_idle, +TMS28_imacl, +TMS28_impyal, +TMS28_impyl, +TMS28_impysl, +TMS28_impyxul, +TMS28_in, +TMS28_inc, +TMS28_intr, +TMS28_iret, +TMS28_lb, +TMS28_lc, +TMS28_lcr, +TMS28_loopnz, +TMS28_loopz, +TMS28_lpaddr, +TMS28_lret, +TMS28_lrete, +TMS28_lretr, +TMS28_lsl, +TMS28_lsl64, +TMS28_lsll, +TMS28_lsr, +TMS28_lsr64, +TMS28_lsrl, +TMS28_mac, +TMS28_max, +TMS28_maxcul, +TMS28_maxl, +TMS28_min, +TMS28_mincul, +TMS28_minl, +TMS28_mov, +TMS28_mova, +TMS28_movad, +TMS28_movb, +TMS28_movdl, +TMS28_movh, +TMS28_movl, +TMS28_movp, +TMS28_movs, +TMS28_movu, +TMS28_movw, +TMS28_movx, +TMS28_movz, +TMS28_mpy, +TMS28_mpya, +TMS28_mpyb, +TMS28_mpys, +TMS28_mpyu, +TMS28_mpyxu, +TMS28_nasp, +TMS28_neg, +TMS28_neg64, +TMS28_negtc, +TMS28_nop, +TMS28_norm, +TMS28_not, +TMS28_or, +TMS28_orb, +TMS28_out, +TMS28_pop, +TMS28_pread, +TMS28_push, +TMS28_pwrite, +TMS28_qmacl, +TMS28_qmpyal, +TMS28_qmpyl, +TMS28_qmpysl, +TMS28_qmpyul, +TMS28_qmpyxul, +TMS28_rol, +TMS28_ror, +TMS28_rpt, +TMS28_sat, +TMS28_sat64, +TMS28_sb, +TMS28_sbbu, +TMS28_sbf, +TMS28_sbrk, +TMS28_setc, +TMS28_sfr, +TMS28_spm, +TMS28_sqra, +TMS28_sqrs, +TMS28_sub, +TMS28_subb, +TMS28_subbl, +TMS28_subcu, +TMS28_subcul, +TMS28_subl, +TMS28_subr, +TMS28_subrl, +TMS28_subu, +TMS28_subul, +TMS28_sxtb, +TMS28_tbit, +TMS28_tclr, +TMS28_test, +TMS28_trap, +TMS28_tset, +TMS28_uout, +TMS28_xb, +TMS28_xbanz, +TMS28_xcall, +TMS28_xmac, +TMS28_xmacd, +TMS28_xor, +TMS28_xorb, +TMS28_xpread, +TMS28_xpwrite, +TMS28_xret, +TMS28_xretc, +TMS28_zalr, +TMS28_zap, +TMS28_zapa, + +TMS28_last, + +}; + + + +enum +{ +UNSP_null = 0, // Unknown Operation + +// ALU +UNSP_add, // Add +UNSP_adc, // Add with Carry +UNSP_sub, // Subtract +UNSP_sbc, // Subtract with Carry +UNSP_cmp, // Compare +UNSP_cmpc, // Compare with Carry? +UNSP_neg, // Negate +UNSP_negc, // Negate with Carry? +UNSP_xor, // Exclusive-OR +UNSP_load, // Load +UNSP_or, // OR +UNSP_and, // AND +UNSP_test, // Test +UNSP_store, // Store + +UNSP_add_s, // Add (Simple) +UNSP_adc_s, // Add with Carry (Simple) +UNSP_sub_s, // Subtract (Simple) +UNSP_sbc_s, // Subtract with Carry (Simple) +UNSP_cmp_s, // Compare (Simple) +UNSP_cmpc_s, // Compare with Carry? (Simple) +UNSP_neg_s, // Negate (Simple) +UNSP_negc_s, // Negate with Carry? (Simple) +UNSP_xor_s, // Exclusive-OR (Simple) +UNSP_load_s, // Load (Simple) +UNSP_or_s, // OR (Simple) +UNSP_and_s, // AND (Simple) +UNSP_test_s, // Test (Simple) +UNSP_store_s, // Store (Simple) + + +// Misc +UNSP_retf, // Return Function +UNSP_reti, // Return Interrupt +UNSP_pop, // Pop from Stack +UNSP_push, // Push to Stack +UNSP_call, // Call +UNSP_goto, // Goto (far jump) +UNSP_nop, // NOP +UNSP_exp, // Effective Exponent + +// Jump +UNSP_jb, // Jump if Below (unsigned) [jcc, jnae] +UNSP_jae, // Jump if Above or Equal (unsigned) [jcs, jnb] +UNSP_jge, // Jump if Greater or Equal (signed) [jsc, jnl] +UNSP_jl, // Jump if Less (signed) [jss, jnge] +UNSP_jne, // Jump if Not Equal [jnz] +UNSP_je, // Jump if Equal [jz] +UNSP_jpl, // Jump if Positive +UNSP_jmi, // Jump if Negative +UNSP_jbe, // Jump if Below or Equal (unsigned) [jna] +UNSP_ja, // Jump if Above (unsigned) [jnbe] +UNSP_jle, // Jump if Less or Equal (signed) [jng] +UNSP_jg, // Jump if Greater (signed) [jnle] +UNSP_jvc, // Jump if Not Overflow +UNSP_jvs, // Jump if Overflow +UNSP_jmp, // Jump + +// Multiplication/Division +UNSP_mulss, // Multiply Signed * Signed +UNSP_mulus, // Multiply Unsigned * Signed +UNSP_muluu, // Multiply Unsigned * Unsigned +UNSP_divs, // Divide (Sign) +UNSP_divq, // Divide (Quotient) + +// Interrupt +UNSP_int1, // Interrupt flags +UNSP_int2, // Interrupt flags +UNSP_fir_mov, // FIR_MOV setting +UNSP_fraction, // FRACTION setting +UNSP_irq, // IRQ setting +UNSP_secbank, // SECBANK setting +UNSP_fiq, // FIQ setting +UNSP_irqnest, // IRQNEST setting +UNSP_break, // BREAK + +// Shift +UNSP_asr, // Arithmetic shift right +UNSP_asror, // Arithmetic shift right OR +UNSP_lsl, // Logical shift left +UNSP_lslor, // Logical shift left OR +UNSP_lsr, // Logical shift right +UNSP_lsror, // Logical shift right OR +UNSP_rol, // Rotate left +UNSP_ror, // Rotate right + +// Bitops +UNSP_tstb, // Test bit +UNSP_setb, // Set bit +UNSP_clrb, // Clear bit +UNSP_invb, // Invert bit + +UNSP_last, + }; + +/* + * Dalvik opcode enumeration. + */ + + +enum +{ + DALVIK_UNUSED = 0, + DALVIK_NOP, + + DALVIK_MOVE, + DALVIK_MOVE_FROM16, + DALVIK_MOVE_16, + DALVIK_MOVE_WIDE, + DALVIK_MOVE_WIDE_FROM16, + DALVIK_MOVE_WIDE_16, + DALVIK_MOVE_OBJECT, + DALVIK_MOVE_OBJECT_FROM16, + DALVIK_MOVE_OBJECT_16, + + DALVIK_MOVE_RESULT, + DALVIK_MOVE_RESULT_WIDE, + DALVIK_MOVE_RESULT_OBJECT, + DALVIK_MOVE_EXCEPTION, + + DALVIK_RETURN_VOID, + DALVIK_RETURN, + DALVIK_RETURN_WIDE, + DALVIK_RETURN_OBJECT, + + DALVIK_CONST_4, + DALVIK_CONST_16, + DALVIK_CONST, + DALVIK_CONST_HIGH16, + DALVIK_CONST_WIDE_16, + DALVIK_CONST_WIDE_32, + DALVIK_CONST_WIDE, + DALVIK_CONST_WIDE_HIGH16, + DALVIK_CONST_STRING, + DALVIK_CONST_STRING_JUMBO, + DALVIK_CONST_CLASS, + + DALVIK_MONITOR_ENTER, + DALVIK_MONITOR_EXIT, + + DALVIK_CHECK_CAST, + DALVIK_INSTANCE_OF, + + DALVIK_ARRAY_LENGTH, + + DALVIK_NEW_INSTANCE, + DALVIK_NEW_ARRAY, + + DALVIK_FILLED_NEW_ARRAY, + DALVIK_FILLED_NEW_ARRAY_RANGE, + DALVIK_FILL_ARRAY_DATA, + + DALVIK_THROW, + DALVIK_GOTO, + DALVIK_GOTO_16, + DALVIK_GOTO_32, + DALVIK_PACKED_SWITCH, + DALVIK_SPARSE_SWITCH, + + DALVIK_CMPL_FLOAT, + DALVIK_CMPG_FLOAT, + DALVIK_CMPL_DOUBLE, + DALVIK_CMPG_DOUBLE, + DALVIK_CMP_LONG, + + DALVIK_IF_EQ, + DALVIK_IF_NE, + DALVIK_IF_LT, + DALVIK_IF_GE, + DALVIK_IF_GT, + DALVIK_IF_LE, + DALVIK_IF_EQZ, + DALVIK_IF_NEZ, + DALVIK_IF_LTZ, + DALVIK_IF_GEZ, + DALVIK_IF_GTZ, + DALVIK_IF_LEZ, + + DALVIK_AGET, + DALVIK_AGET_WIDE, + DALVIK_AGET_OBJECT, + DALVIK_AGET_BOOLEAN, + DALVIK_AGET_BYTE, + DALVIK_AGET_CHAR, + DALVIK_AGET_SHORT, + DALVIK_APUT, + DALVIK_APUT_WIDE, + DALVIK_APUT_OBJECT, + DALVIK_APUT_BOOLEAN, + DALVIK_APUT_BYTE, + DALVIK_APUT_CHAR, + DALVIK_APUT_SHORT, + + DALVIK_IGET, + DALVIK_IGET_WIDE, + DALVIK_IGET_OBJECT, + DALVIK_IGET_BOOLEAN, + DALVIK_IGET_BYTE, + DALVIK_IGET_CHAR, + DALVIK_IGET_SHORT, + DALVIK_IPUT, + DALVIK_IPUT_WIDE, + DALVIK_IPUT_OBJECT, + DALVIK_IPUT_BOOLEAN, + DALVIK_IPUT_BYTE, + DALVIK_IPUT_CHAR, + DALVIK_IPUT_SHORT, + + DALVIK_SGET, + DALVIK_SGET_WIDE, + DALVIK_SGET_OBJECT, + DALVIK_SGET_BOOLEAN, + DALVIK_SGET_BYTE, + DALVIK_SGET_CHAR, + DALVIK_SGET_SHORT, + DALVIK_SPUT, + DALVIK_SPUT_WIDE, + DALVIK_SPUT_OBJECT, + DALVIK_SPUT_BOOLEAN, + DALVIK_SPUT_BYTE, + DALVIK_SPUT_CHAR, + DALVIK_SPUT_SHORT, + + DALVIK_INVOKE_VIRTUAL, + DALVIK_INVOKE_SUPER, + DALVIK_INVOKE_DIRECT, + DALVIK_INVOKE_STATIC, + DALVIK_INVOKE_INTERFACE, + + DALVIK_INVOKE_VIRTUAL_RANGE, + DALVIK_INVOKE_SUPER_RANGE, + DALVIK_INVOKE_DIRECT_RANGE, + DALVIK_INVOKE_STATIC_RANGE, + DALVIK_INVOKE_INTERFACE_RANGE, + + DALVIK_NEG_INT, + DALVIK_NOT_INT, + DALVIK_NEG_LONG, + DALVIK_NOT_LONG, + DALVIK_NEG_FLOAT, + DALVIK_NEG_DOUBLE, + DALVIK_INT_TO_LONG, + DALVIK_INT_TO_FLOAT, + DALVIK_INT_TO_DOUBLE, + DALVIK_LONG_TO_INT, + DALVIK_LONG_TO_FLOAT, + DALVIK_LONG_TO_DOUBLE, + DALVIK_FLOAT_TO_INT, + DALVIK_FLOAT_TO_LONG, + DALVIK_FLOAT_TO_DOUBLE, + DALVIK_DOUBLE_TO_INT, + DALVIK_DOUBLE_TO_LONG, + DALVIK_DOUBLE_TO_FLOAT, + DALVIK_INT_TO_BYTE, + DALVIK_INT_TO_CHAR, + DALVIK_INT_TO_SHORT, + + DALVIK_ADD_INT, + DALVIK_SUB_INT, + DALVIK_MUL_INT, + DALVIK_DIV_INT, + DALVIK_REM_INT, + DALVIK_AND_INT, + DALVIK_OR_INT, + DALVIK_XOR_INT, + DALVIK_SHL_INT, + DALVIK_SHR_INT, + DALVIK_USHR_INT, + + DALVIK_ADD_LONG, + DALVIK_SUB_LONG, + DALVIK_MUL_LONG, + DALVIK_DIV_LONG, + DALVIK_REM_LONG, + DALVIK_AND_LONG, + DALVIK_OR_LONG, + DALVIK_XOR_LONG, + DALVIK_SHL_LONG, + DALVIK_SHR_LONG, + DALVIK_USHR_LONG, + + DALVIK_ADD_FLOAT, + DALVIK_SUB_FLOAT, + DALVIK_MUL_FLOAT, + DALVIK_DIV_FLOAT, + DALVIK_REM_FLOAT, + DALVIK_ADD_DOUBLE, + DALVIK_SUB_DOUBLE, + DALVIK_MUL_DOUBLE, + DALVIK_DIV_DOUBLE, + DALVIK_REM_DOUBLE, + + DALVIK_ADD_INT_2ADDR, + DALVIK_SUB_INT_2ADDR, + DALVIK_MUL_INT_2ADDR, + DALVIK_DIV_INT_2ADDR, + DALVIK_REM_INT_2ADDR, + DALVIK_AND_INT_2ADDR, + DALVIK_OR_INT_2ADDR, + DALVIK_XOR_INT_2ADDR, + DALVIK_SHL_INT_2ADDR, + DALVIK_SHR_INT_2ADDR, + DALVIK_USHR_INT_2ADDR, + + DALVIK_ADD_LONG_2ADDR, + DALVIK_SUB_LONG_2ADDR, + DALVIK_MUL_LONG_2ADDR, + DALVIK_DIV_LONG_2ADDR, + DALVIK_REM_LONG_2ADDR, + DALVIK_AND_LONG_2ADDR, + DALVIK_OR_LONG_2ADDR, + DALVIK_XOR_LONG_2ADDR, + DALVIK_SHL_LONG_2ADDR, + DALVIK_SHR_LONG_2ADDR, + DALVIK_USHR_LONG_2ADDR, + + DALVIK_ADD_FLOAT_2ADDR, + DALVIK_SUB_FLOAT_2ADDR, + DALVIK_MUL_FLOAT_2ADDR, + DALVIK_DIV_FLOAT_2ADDR, + DALVIK_REM_FLOAT_2ADDR, + DALVIK_ADD_DOUBLE_2ADDR, + DALVIK_SUB_DOUBLE_2ADDR, + DALVIK_MUL_DOUBLE_2ADDR, + DALVIK_DIV_DOUBLE_2ADDR, + DALVIK_REM_DOUBLE_2ADDR, + + DALVIK_ADD_INT_LIT16, + DALVIK_RSUB_INT, // no _LIT16 suffix for this + DALVIK_MUL_INT_LIT16, + DALVIK_DIV_INT_LIT16, + DALVIK_REM_INT_LIT16, + DALVIK_AND_INT_LIT16, + DALVIK_OR_INT_LIT16, + DALVIK_XOR_INT_LIT16, + + DALVIK_ADD_INT_LIT8, + DALVIK_RSUB_INT_LIT8, + DALVIK_MUL_INT_LIT8, + DALVIK_DIV_INT_LIT8, + DALVIK_REM_INT_LIT8, + DALVIK_AND_INT_LIT8, + DALVIK_OR_INT_LIT8, + DALVIK_XOR_INT_LIT8, + DALVIK_SHL_INT_LIT8, + DALVIK_SHR_INT_LIT8, + DALVIK_USHR_INT_LIT8, + + DALVIK_IGET_VOLATILE, + DALVIK_IPUT_VOLATILE, + DALVIK_SGET_VOLATILE, + DALVIK_SPUT_VOLATILE, + DALVIK_IGET_OBJECT_VOLATILE, + + DALVIK_IGET_WIDE_VOLATILE, + DALVIK_IPUT_WIDE_VOLATILE, + DALVIK_SGET_WIDE_VOLATILE, + DALVIK_SPUT_WIDE_VOLATILE, + + // The "breakpoint" instruction is special, in that it should never + // be seen by anything but the debug interpreter. During debugging + // it takes the place of an arbitrary opcode, which means operations + // like "tell me the opcode width so I can find the next instruction" + // aren't possible. (This is correctable, but probably not useful.) + DALVIK_BREAKPOINT, + + DALVIK_THROW_VERIFICATION_ERROR, + + DALVIK_EXECUTE_INLINE, + DALVIK_EXECUTE_INLINE_RANGE, + + DALVIK_INVOKE_DIRECT_EMPTY, + DALVIK_RETURN_VOID_BARRIER, + DALVIK_IGET_QUICK, + DALVIK_IGET_WIDE_QUICK, + DALVIK_IGET_OBJECT_QUICK, + DALVIK_IPUT_QUICK, + DALVIK_IPUT_WIDE_QUICK, + DALVIK_IPUT_OBJECT_QUICK, + + DALVIK_INVOKE_VIRTUAL_QUICK, + DALVIK_INVOKE_VIRTUAL_QUICK_RANGE, + DALVIK_INVOKE_SUPER_QUICK, + DALVIK_INVOKE_SUPER_QUICK_RANGE, + DALVIK_IPUT_OBJECT_VOLATILE, + DALVIK_SGET_OBJECT_VOLATILE, + DALVIK_SPUT_OBJECT_VOLATILE, + + // dex-file format 038 + DALVIK_INVOKE_POLYMORPHIC, + DALVIK_INVOKE_POLYMORPHIC_RANGE, + DALVIK_INVOKE_CUSTOM, + DALVIK_INVOKE_CUSTOM_RANGE, + + DALVIK_LAST, +}; + +/* this file was entirely generated by gen_opc.py */ +enum +{ + s39_null = 0, + s39_a, // add (32) + s39_ad, // add normalized (long HFP) + s39_adb, // add (long BFP) + s39_adbr, // add (long BFP) + s39_adr, // add normalized (long HFP) + s39_adtr, // add (long DFP) + s39_adtra, // add (long DFP) + s39_ae, // add normalized (short HFP) + s39_aeb, // add (short BFP) + s39_aebr, // add (short BFP) + s39_aer, // add normalized (short HFP) + s39_afi, // add immediate (32) + s39_ag, // add (64) + s39_agf, // add (64 <- 32) + s39_agfi, // add immediate (64 <- 32) + s39_agfr, // add (64 <- 32) + s39_agh, // add halfword (64 <- 16) + s39_aghi, // add halfword immediate (64 <- 16) + s39_aghik, // add immediate (64 <- 16) + s39_agr, // add (64) + s39_agrk, // add (64) + s39_agsi, // add immediate (64 <- 8) + s39_ah, // add halfword (32 <- 16) + s39_ahhhr, // add high (32) + s39_ahhlr, // add high (32) + s39_ahi, // add halfword immediate (32 <- 16) + s39_ahik, // add immediate (32 <- 16) + s39_ahy, // add halfword (32 <- 16) + s39_aih, // add immediate high (32) + s39_al, // add logical (32) + s39_alc, // add logical with carry (32) + s39_alcg, // add logical with carry (64) + s39_alcgr, // add logical with carry (64) + s39_alcr, // add logical with carry (32) + s39_alfi, // add logical immediate (32) + s39_alg, // add logical (64) + s39_algf, // add logical (64 <- 32) + s39_algfi, // add logical immediate (64 <- 32) + s39_algfr, // add logical (64 <- 32) + s39_alghsik, // add logical with signed immediate (64 <- 16) + s39_algr, // add logical (64) + s39_algrk, // add logical (64) + s39_algsi, // add logical with signed immediate (64 <- 8) + s39_alhhhr, // add logical high (32) + s39_alhhlr, // add logical high (32) + s39_alhsik, // add logical with signed immediate (32 <- 16) + s39_alr, // add logical (32) + s39_alrk, // add logical (32) + s39_alsi, // add logical with signed immediate (32 <- 8) + s39_alsih, // add logical with signed immediate high (32) + s39_alsihn, // add logical with signed immediate high (32) + s39_aly, // add logical (32) + s39_ap, // add decimal + s39_ar, // add (32) + s39_ark, // add (32) + s39_asi, // add immediate (32 <- 8) + s39_au, // add unnormalized (short HFP) + s39_aur, // add unnormalized (short HFP) + s39_aw, // add unnormalized (long HFP) + s39_awr, // add unnormalized (long HFP) + s39_axbr, // add (extended BFP) + s39_axr, // add normalized (extended HFP) + s39_axtr, // add (extended DFP) + s39_axtra, // add (extended DFP) + s39_ay, // add (32) + s39_b, // unconditional branch + s39_bo, // branch on condition, jump on overflow / if ones + s39_bh, // branch on condition, jump on A high + s39_bnle, // branch on condition, jump on not low or equal + s39_bl, // branch on condition, jump on A low + s39_bnhe, // branch on condition, jump on not high or equal + s39_blh, // branch on condition, jump on low or high + s39_bne, // branch on condition, jump on A not equal B + s39_be, // branch on condition, jump on A equal B + s39_bnlh, // branch on condition, jump on not low or high + s39_bhe, // branch on condition, jump on high or equal + s39_bnl, // branch on condition, jump on A not low + s39_ble, // branch on condition, jump on low or equal + s39_bnh, // branch on condition, jump on A not high + s39_bno, // branch on condition, jump on not overflow / if not ones + s39_bor, // branch on condition, jump on overflow / if ones + s39_bhr, // branch on condition, jump on A high + s39_bnler, // branch on condition, jump on not low or equal + s39_blr, // branch on condition, jump on A low + s39_bnher, // branch on condition, jump on not high or equal + s39_blhr, // branch on condition, jump on low or high + s39_bner, // branch on condition, jump on A not equal B + s39_ber, // branch on condition, jump on A equal B + s39_bnlhr, // branch on condition, jump on not low or high + s39_bher, // branch on condition, jump on high or equal + s39_bnlr, // branch on condition, jump on A not low + s39_bler, // branch on condition, jump on low or equal + s39_bnhr, // branch on condition, jump on A not high + s39_bnor, // branch on condition, jump on not overflow / if not ones + s39_bakr, // branch and stack + s39_bal, // branch and link + s39_balr, // branch and link + s39_bas, // branch and save + s39_basr, // branch and save + s39_bassm, // branch and save and set mode + s39_bc, // branch on condition + s39_bcr, // branch on condition + s39_bct, // branch on count (32) + s39_bctg, // branch on count (64) + s39_bctgr, // branch on count (64) + s39_bctr, // branch on count (32) + s39_bi, // unconditional indirect branch + s39_bio, // branch indirect on condition, jump on overflow / if ones + s39_bih, // branch indirect on condition, jump on A high + s39_binle, // branch indirect on condition, jump on not low or equal + s39_bil, // branch indirect on condition, jump on A low + s39_binhe, // branch indirect on condition, jump on not high or equal + s39_bilh, // branch indirect on condition, jump on low or high + s39_bine, // branch indirect on condition, jump on A not equal B + s39_bie, // branch indirect on condition, jump on A equal B + s39_binlh, // branch indirect on condition, jump on not low or high + s39_bihe, // branch indirect on condition, jump on high or equal + s39_binl, // branch indirect on condition, jump on A not low + s39_bile, // branch indirect on condition, jump on low or equal + s39_binh, // branch indirect on condition, jump on A not high + s39_bino, // branch indirect on condition, jump on not overflow / if not ones + s39_bic, // branch indirect on condition + s39_bpp, // branch prediction preload + s39_bprp, // branch prediction relative preload + s39_br, // unconditional branch + s39_bras, // branch relative and save + s39_brasl, // branch relative and save long + s39_brc, // branch relative on condition + s39_brcl, // branch relative on condition long + s39_brct, // branch relative on count (32) + s39_brctg, // branch relative on count (64) + s39_brcth, // branch relative on count high (32) + s39_brxh, // branch relative on index high (32) + s39_brxhg, // branch relative on index high (64) + s39_brxle, // branch relative on index low or equal (32) + s39_brxlg, // branch relative on index low or equal (64) + s39_bsa, // branch and set authority + s39_bsg, // branch in subspace group + s39_bsm, // branch and set mode + s39_bxh, // branch on index high (32) + s39_bxhg, // branch on index high (64) + s39_bxle, // branch on index low or equal (32) + s39_bxleg, // branch on index low or equal (64) + s39_c, // compare (32) + s39_cd, // compare (long HFP) + s39_cdb, // compare (long BFP) + s39_cdbr, // compare (long BFP) + s39_cdfbr, // convert from fixed (32 to long BFP) + s39_cdfbra, // convert from fixed (32 to long BFP) + s39_cdfr, // convert from fixed (32 to long HFP) + s39_cdftr, // convert from fixed (32 to long DFP) + s39_cdgbr, // convert from fixed (64 to long BFP) + s39_cdgbra, // convert from fixed (64 to long BFP) + s39_cdgr, // convert from fixed (64 to long HFP) + s39_cdgtr, // convert from fixed (64 to long DFP) + s39_cdgtra, // convert from fixed (64 to long DFP) + s39_cdlfbr, // convert from logical (32 to long BFP) + s39_cdlftr, // convert from logical (32 to long DFP) + s39_cdlgbr, // convert from logical (64 to long BFP) + s39_cdlgtr, // convert from logical (64 to long DFP) + s39_cdpt, // convert from packed (to long DFP) + s39_cdr, // compare (long HFP) + s39_cds, // compare double and swap (32) + s39_cdsg, // compare double and swap (64) + s39_cdstr, // convert from signed packed (64 to long DFP) + s39_cdsy, // compare double and swap (32) + s39_cdtr, // compare (long DFP) + s39_cdutr, // convert from unsigned packed (64 to long DFP) + s39_cdzt, // convert from zoned (to long DFP) + s39_ce, // compare (short HFP) + s39_ceb, // compare (short BFP) + s39_cebr, // compare (short BFP) + s39_cedtr, // compare biased exponent (long DFP) + s39_cefbr, // convert from fixed (32 to short BFP) + s39_cefbra, // convert from fixed (32 to short BFP) + s39_cefr, // convert from fixed (32 to short HFP) + s39_cegbr, // convert from fixed (64 to short BFP) + s39_cegbra, // convert from fixed (64 to short BFP) + s39_cegr, // convert from fixed (64 to short HFP) + s39_celfbr, // convert from logical (32 to short BFP) + s39_celgbr, // convert from logical (64 to short BFP) + s39_cer, // compare (short HFP) + s39_cextr, // compare biased exponent (extended DFP) + s39_cfc, // compare and form codeword + s39_cfdbr, // convert to fixed (long BFP to 32) + s39_cfdbra, // convert to fixed (long BFP to 32) + s39_cfdr, // convert to fixed (long HFP to 32) + s39_cfdtr, // convert to fixed (long DFP to 32) + s39_cfebr, // convert to fixed (short BFP to 32) + s39_cfebra, // convert to fixed (short BFP to 32) + s39_cfer, // convert to fixed (short HFP to 32) + s39_cfi, // compare immediate (32) + s39_cfxbr, // convert to fixed (extended BFP to 32) + s39_cfxbra, // convert to fixed (extended BFP to 32) + s39_cfxr, // convert to fixed (extended HFP to 32) + s39_cfxtr, // convert to fixed (extended DFP to 32) + s39_cg, // compare (64) + s39_cgdbr, // convert to fixed (long BFP to 64) + s39_cgdbra, // convert to fixed (long BFP to 64) + s39_cgdr, // convert to fixed (long HFP to 64) + s39_cgdtr, // convert to fixed (long DFP to 64) + s39_cgdtra, // convert to fixed (long DFP to 64) + s39_cgebr, // convert to fixed (short BFP to 64) + s39_cgebra, // convert to fixed (short BFP to 64) + s39_cger, // convert to fixed (short HFP to 64) + s39_cgf, // compare (64 <- 32) + s39_cgfi, // compare immediate (64 <- 32) + s39_cgfr, // compare (64 <- 32) + s39_cgfrl, // compare relative long (64 <- 32) + s39_cgh, // compare halfword (64 <- 16) + s39_cghi, // compare halfword immediate (64 <- 16) + s39_cghrl, // compare halfword relative long (64 <- 16) + s39_cghsi, // compare halfword immediate (64 <- 16) + s39_cgib, // compare immediate and branch (64 <- 8) + s39_cgibh, // compare immediate and branch (64 <- 8), jump on A high + s39_cgibnhe, // compare immediate and branch (64 <- 8), jump on not high or equal + s39_cgiblh, // compare immediate and branch (64 <- 8), jump on low or high + s39_cgibnlh, // compare immediate and branch (64 <- 8), jump on not low or high + s39_cgibnl, // compare immediate and branch (64 <- 8), jump on A not low + s39_cgible, // compare immediate and branch (64 <- 8), jump on low or equal + s39_cgij, // compare immediate and branch relative (64 <- 8) + s39_cgijh, // compare immediate and branch relative (64 <- 8), jump on A high + s39_cgijnhe, // compare immediate and branch relative (64 <- 8), jump on not high or equal + s39_cgijlh, // compare immediate and branch relative (64 <- 8), jump on low or high + s39_cgijnlh, // compare immediate and branch relative (64 <- 8), jump on not low or high + s39_cgijnl, // compare immediate and branch relative (64 <- 8), jump on A not low + s39_cgijle, // compare immediate and branch relative (64 <- 8), jump on low or equal + s39_cgit, // compare immediate and trap (64 <- 16) + s39_cgith, // compare immediate and trap (64 <- 16), jump on A high + s39_cgitnhe, // compare immediate and trap (64 <- 16), jump on not high or equal + s39_cgitlh, // compare immediate and trap (64 <- 16), jump on low or high + s39_cgitnlh, // compare immediate and trap (64 <- 16), jump on not low or high + s39_cgitnl, // compare immediate and trap (64 <- 16), jump on A not low + s39_cgitle, // compare immediate and trap (64 <- 16), jump on low or equal + s39_cgr, // compare (64) + s39_cgrb, // compare and branch (64) + s39_cgrbh, // compare and branch (64), jump on A high + s39_cgrbnhe, // compare and branch (64), jump on not high or equal + s39_cgrblh, // compare and branch (64), jump on low or high + s39_cgrbnlh, // compare and branch (64), jump on not low or high + s39_cgrbnl, // compare and branch (64), jump on A not low + s39_cgrble, // compare and branch (64), jump on low or equal + s39_cgrj, // compare and branch relative (64) + s39_cgrjh, // compare and branch relative (64), jump on A high + s39_cgrjnhe, // compare and branch relative (64), jump on not high or equal + s39_cgrjlh, // compare and branch relative (64), jump on low or high + s39_cgrjnlh, // compare and branch relative (64), jump on not low or high + s39_cgrjnl, // compare and branch relative (64), jump on A not low + s39_cgrjle, // compare and branch relative (64), jump on low or equal + s39_cgrl, // compare relative long (64) + s39_cgrt, // compare and trap (64) + s39_cgrth, // compare and trap (64), jump on A high + s39_cgrtnhe, // compare and trap (64), jump on not high or equal + s39_cgrtlh, // compare and trap (64), jump on low or high + s39_cgrtnlh, // compare and trap (64), jump on not low or high + s39_cgrtnl, // compare and trap (64), jump on A not low + s39_cgrtle, // compare and trap (64), jump on low or equal + s39_cgxbr, // convert to fixed (extended BFP to 64) + s39_cgxbra, // convert to fixed (extended BFP to 64) + s39_cgxr, // convert to fixed (extended HFP to 64) + s39_cgxtr, // convert to fixed (extended DFP to 64) + s39_cgxtra, // convert to fixed (extended DFP to 64) + s39_ch, // compare halfword (32 <- 16) + s39_chf, // compare high (32) + s39_chhr, // compare high (32) + s39_chhsi, // compare halfword immediate (16 <- 16) + s39_chi, // compare halfword immediate (32 <- 16) + s39_chlr, // compare high (32) + s39_chrl, // compare halfword relative long (32 <- 16) + s39_chsi, // compare halfword immediate (32 <- 16) + s39_chy, // compare halfword (32 <- 16) + s39_cib, // comapre immediate and branch (32 <- 8) + s39_cibh, // comapre immediate and branch (32 <- 8), jump on A high + s39_cibnhe, // comapre immediate and branch (32 <- 8), jump on not high or equal + s39_ciblh, // comapre immediate and branch (32 <- 8), jump on low or high + s39_cibnlh, // comapre immediate and branch (32 <- 8), jump on not low or high + s39_cibnl, // comapre immediate and branch (32 <- 8), jump on A not low + s39_cible, // comapre immediate and branch (32 <- 8), jump on low or equal + s39_cih, // compare immediate high (32) + s39_cij, // compare immediate and branch relative (32 <- 8) + s39_cijh, // compare immediate and branch relative (32 <- 8), jump on A high + s39_cijnhe, // compare immediate and branch relative (32 <- 8), jump on not high or equal + s39_cijlh, // compare immediate and branch relative (32 <- 8), jump on low or high + s39_cijnlh, // compare immediate and branch relative (32 <- 8), jump on not low or high + s39_cijnl, // compare immediate and branch relative (32 <- 8), jump on A not low + s39_cijle, // compare immediate and branch relative (32 <- 8), jump on low or equal + s39_cit, // compare immediate and trap (32 <- 16) + s39_cith, // compare immediate and trap (32 <- 16), jump on A high + s39_citnhe, // compare immediate and trap (32 <- 16), jump on not high or equal + s39_citlh, // compare immediate and trap (32 <- 16), jump on low or high + s39_citnlh, // compare immediate and trap (32 <- 16), jump on not low or high + s39_citnl, // compare immediate and trap (32 <- 16), jump on A not low + s39_citle, // compare immediate and trap (32 <- 16), jump on low or equal + s39_cksm, // checksum + s39_cl, // compare logical (32) + s39_clc, // compare logical (character) + s39_clcl, // compare logical long + s39_clcle, // compare logical long extended + s39_clclu, // compare logical long unicode + s39_clfdbr, // convert to logical (long BFP to 32) + s39_clfdtr, // convert to logical (long DFP to 32) + s39_clfebr, // convert to logical (short BFP to 32) + s39_clfhsi, // compare logical immediate (32 <- 16) + s39_clfi, // compare logical immediate (32) + s39_clfit, // compare logical immediate and trap (32 <- 16) + s39_clfith, // compare logical immediate and trap (32 <- 16), jump on A high + s39_clfitnhe, // compare logical immediate and trap (32 <- 16), jump on not high or equal + s39_clfitlh, // compare logical immediate and trap (32 <- 16), jump on low or high + s39_clfitnlh, // compare logical immediate and trap (32 <- 16), jump on not low or high + s39_clfitnl, // compare logical immediate and trap (32 <- 16), jump on A not low + s39_clfitle, // compare logical immediate and trap (32 <- 16), jump on low or equal + s39_clfxbr, // convert to logical (extended BFP to 32) + s39_clfxtr, // convert to logical (extended DFP to 32) + s39_clg, // compare logical (64) + s39_clgdbr, // convert to logical (long BFP to 64) + s39_clgdtr, // convert to logical (long DFP to 64) + s39_clgebr, // convert to logical (short BFP to 64) + s39_clgf, // compare logical (64 <- 32) + s39_clgfi, // compare logical immediate (64 <- 32) + s39_clgfr, // compare logical (64 <- 32) + s39_clgfrl, // compare logical relative long (64 <- 32) + s39_clghrl, // compare logical relative long (64 <- 16) + s39_clghsi, // compare logical relative long (64 <- 16) + s39_clgib, // compare logical immediate and branch (64 <- 8) + s39_clgibh, // compare logical immediate and branch (64 <- 8), jump on A high + s39_clgibnhe, // compare logical immediate and branch (64 <- 8), jump on not high or equal + s39_clgiblh, // compare logical immediate and branch (64 <- 8), jump on low or high + s39_clgibnlh, // compare logical immediate and branch (64 <- 8), jump on not low or high + s39_clgibnl, // compare logical immediate and branch (64 <- 8), jump on A not low + s39_clgible, // compare logical immediate and branch (64 <- 8), jump on low or equal + s39_clgij, // compare logical immediate and branch relative (64 <- 8) + s39_clgijh, // compare logical immediate and branch relative (64 <- 8), jump on A high + s39_clgijnhe, // compare logical immediate and branch relative (64 <- 8), jump on not high or equal + s39_clgijlh, // compare logical immediate and branch relative (64 <- 8), jump on low or high + s39_clgijnlh, // compare logical immediate and branch relative (64 <- 8), jump on not low or high + s39_clgijnl, // compare logical immediate and branch relative (64 <- 8), jump on A not low + s39_clgijle, // compare logical immediate and branch relative (64 <- 8), jump on low or equal + s39_clgit, // compare logical immedate and trap (64 <- 16) + s39_clgith, // compare logical immedate and trap (64 <- 16), jump on A high + s39_clgitnhe, // compare logical immedate and trap (64 <- 16), jump on not high or equal + s39_clgitlh, // compare logical immedate and trap (64 <- 16), jump on low or high + s39_clgitnlh, // compare logical immedate and trap (64 <- 16), jump on not low or high + s39_clgitnl, // compare logical immedate and trap (64 <- 16), jump on A not low + s39_clgitle, // compare logical immedate and trap (64 <- 16), jump on low or equal + s39_clgr, // compare logical (64) + s39_clgrb, // compare logical and branch (64) + s39_clgrbh, // compare logical and branch (64), jump on A high + s39_clgrbnhe, // compare logical and branch (64), jump on not high or equal + s39_clgrblh, // compare logical and branch (64), jump on low or high + s39_clgrbnlh, // compare logical and branch (64), jump on not low or high + s39_clgrbnl, // compare logical and branch (64), jump on A not low + s39_clgrble, // compare logical and branch (64), jump on low or equal + s39_clgrj, // compare logical and branch relative (64) + s39_clgrjh, // compare logical and branch relative (64), jump on A high + s39_clgrjnhe, // compare logical and branch relative (64), jump on not high or equal + s39_clgrjlh, // compare logical and branch relative (64), jump on low or high + s39_clgrjnlh, // compare logical and branch relative (64), jump on not low or high + s39_clgrjnl, // compare logical and branch relative (64), jump on A not low + s39_clgrjle, // compare logical and branch relative (64), jump on low or equal + s39_clgrl, // compare logical relative long (64) + s39_clgrt, // compare logical and trap (64) + s39_clgrth, // compare logical and trap (64), jump on A high + s39_clgrtnhe, // compare logical and trap (64), jump on not high or equal + s39_clgrtlh, // compare logical and trap (64), jump on low or high + s39_clgrtnlh, // compare logical and trap (64), jump on not low or high + s39_clgrtnl, // compare logical and trap (64), jump on A not low + s39_clgrtle, // compare logical and trap (64), jump on low or equal + s39_clgt, // compare logical and trap (64) + s39_clgth, // compare logical and trap (64), jump on A high + s39_clgtnhe, // compare logical and trap (64), jump on not high or equal + s39_clgtlh, // compare logical and trap (64), jump on low or high + s39_clgtnlh, // compare logical and trap (64), jump on not low or high + s39_clgtnl, // compare logical and trap (64), jump on A not low + s39_clgtle, // compare logical and trap (64), jump on low or equal + s39_clgxbr, // convert to logical (extended BFP to 64) + s39_clgxtr, // convert to logical (extended DFP to 64) + s39_clhf, // compare logical high (32) + s39_clhhr, // compare logical high (32) + s39_clhhsi, // compare logical immediate (16 <- 16) + s39_clhlr, // compare logical high (32) + s39_clhrl, // compare logical relative long (32 <- 16) + s39_cli, // compare logical (immediate) + s39_clib, // compare logical immediate and branch (32 <- 8) + s39_clibh, // compare logical immediate and branch (32 <- 8), jump on A high + s39_clibnhe, // compare logical immediate and branch (32 <- 8), jump on not high or equal + s39_cliblh, // compare logical immediate and branch (32 <- 8), jump on low or high + s39_clibnlh, // compare logical immediate and branch (32 <- 8), jump on not low or high + s39_clibnl, // compare logical immediate and branch (32 <- 8), jump on A not low + s39_clible, // compare logical immediate and branch (32 <- 8), jump on low or equal + s39_clih, // compare logical immediate high (32) + s39_clij, // compare logical immediate and branch relative (32 <- 8) + s39_clijh, // compare logical immediate and branch relative (32 <- 8), jump on A high + s39_clijnhe, // compare logical immediate and branch relative (32 <- 8), jump on not high or equal + s39_clijlh, // compare logical immediate and branch relative (32 <- 8), jump on low or high + s39_clijnlh, // compare logical immediate and branch relative (32 <- 8), jump on not low or high + s39_clijnl, // compare logical immediate and branch relative (32 <- 8), jump on A not low + s39_clijle, // compare logical immediate and branch relative (32 <- 8), jump on low or equal + s39_cliy, // compare logical (immediate) + s39_clm, // compare logical character under mask (low) + s39_clmh, // compare logical character under mask (high) + s39_clmy, // compare logical (32) + s39_clr, // compare logical (32) + s39_clrb, // compare logical and branch (32) + s39_clrbh, // compare logical and branch (32), jump on A high + s39_clrbnhe, // compare logical and branch (32), jump on not high or equal + s39_clrblh, // compare logical and branch (32), jump on low or high + s39_clrbnlh, // compare logical and branch (32), jump on not low or high + s39_clrbnl, // compare logical and branch (32), jump on A not low + s39_clrble, // compare logical and branch (32), jump on low or equal + s39_clrj, // compare logical and branch relative (32) + s39_clrjh, // compare logical and branch relative (32), jump on A high + s39_clrjnhe, // compare logical and branch relative (32), jump on not high or equal + s39_clrjlh, // compare logical and branch relative (32), jump on low or high + s39_clrjnlh, // compare logical and branch relative (32), jump on not low or high + s39_clrjnl, // compare logical and branch relative (32), jump on A not low + s39_clrjle, // compare logical and branch relative (32), jump on low or equal + s39_clrl, // compare logical relative long (32) + s39_clrt, // compare logical and trap (32) + s39_clrth, // compare logical and trap (32), jump on A high + s39_clrtnhe, // compare logical and trap (32), jump on not high or equal + s39_clrtlh, // compare logical and trap (32), jump on low or high + s39_clrtnlh, // compare logical and trap (32), jump on not low or high + s39_clrtnl, // compare logical and trap (32), jump on A not low + s39_clrtle, // compare logical and trap (32), jump on low or equal + s39_clst, // compare logical string + s39_clt, // compare logical and trap (32) + s39_clth, // compare logical and trap (32), jump on A high + s39_cltnhe, // compare logical and trap (32), jump on not high or equal + s39_cltlh, // compare logical and trap (32), jump on low or high + s39_cltnlh, // compare logical and trap (32), jump on not low or high + s39_cltnl, // compare logical and trap (32), jump on A not low + s39_cltle, // compare logical and trap (32), jump on low or equal + s39_cly, // compare logical (32) + s39_cmpsc, // compression call + s39_cp, // compare decimal + s39_cpdt, // convert to packed (from long DFP) + s39_cpsdr, // copy sign (long) + s39_cpxt, // convert to packed (from extended DFP) + s39_cpya, // copy access + s39_cr, // compare (32) + s39_crb, // compare and branch (32) + s39_crbh, // compare and branch (32), jump on A high + s39_crbnhe, // compare and branch (32), jump on not high or equal + s39_crblh, // compare and branch (32), jump on low or high + s39_crbnlh, // compare and branch (32), jump on not low or high + s39_crbnl, // compare and branch (32), jump on A not low + s39_crble, // compare and branch (32), jump on low or equal + s39_crdte, // compare and replace DAT table entry + s39_crj, // compare and branch relative (32) + s39_crjh, // compare and branch relative (32), jump on A high + s39_crjnhe, // compare and branch relative (32), jump on not high or equal + s39_crjlh, // compare and branch relative (32), jump on low or high + s39_crjnlh, // compare and branch relative (32), jump on not low or high + s39_crjnl, // compare and branch relative (32), jump on A not low + s39_crjle, // compare and branch relative (32), jump on low or equal + s39_crl, // compare relative long (32) + s39_crt, // compare and trap (32) + s39_crth, // compare and trap (32), jump on A high + s39_crtnhe, // compare and trap (32), jump on not high or equal + s39_crtlh, // compare and trap (32), jump on low or high + s39_crtnlh, // compare and trap (32), jump on not low or high + s39_crtnl, // compare and trap (32), jump on A not low + s39_crtle, // compare and trap (32), jump on low or equal + s39_cs, // compare and swap (32) + s39_csch, // clear subchannel + s39_csdtr, // convert to signed packed (long DFP to 64) + s39_csg, // compare and swap (64) + s39_csp, // compare and swap and purge (32) + s39_cspg, // compare and swap and purge (64) + s39_csst, // compare and swap and store + s39_csxtr, // convert to signed packed (extended DFP to 128) + s39_csy, // compare and swap (32) + s39_cu12, // convert utf-8 to utf-16 + s39_cu14, // convert utf-8 to utf-32 + s39_cu21, // convert utf-16 to utf-8 + s39_cu24, // convert utf-16 to utf-32 + s39_cu41, // convert utf-32 to utf-8 + s39_cu42, // convert utf-32 to utf-16 + s39_cudtr, // convert to unsigned packed (long DFP to 64) + s39_cuse, // compare until substring equal + s39_cutfu, // convert utf-8 to unicode + s39_cuutf, // convert unicode to utf-8 + s39_cuxtr, // convert to unsigned packed (extended DFP to 128) + s39_cvb, // convert to binary (32) + s39_cvbg, // convert to binary (64) + s39_cvby, // convert to binary (32) + s39_cvd, // convert to decimal (32) + s39_cvdg, // convert to decimal (64) + s39_cvdy, // convert to decimal (32) + s39_cxbr, // compare (extended BFP) + s39_cxfbr, // convert from fixed (32 to extended BFP) + s39_cxfbra, // convert from fixed (32 to extended BFP) + s39_cxfr, // convert from fixed (32 to extended HFP) + s39_cxftr, // convert from fixed (32 to extended DFP) + s39_cxgbr, // convert from fixed (64 to extended BFP) + s39_cxgbra, // convert from fixed (64 to extended BFP) + s39_cxgr, // convert from fixed (64 to extended HFP) + s39_cxgtr, // convert from fixed (64 to extended DFP) + s39_cxgtra, // convert from fixed (64 to extended DFP) + s39_cxlfbr, // convert from logical (32 to extended BFP) + s39_cxlftr, // convert from logical (32 to extended DFP) + s39_cxlgbr, // convert from logical (64 to extended BFP) + s39_cxlgtr, // convert from logical (64 to extended DFP) + s39_cxpt, // convert from packed (to extended DFP) + s39_cxr, // compare (extended HFP) + s39_cxstr, // convert from singed packed (128 to extended DFP) + s39_cxtr, // compare (extended DFP) + s39_cxutr, // convert from unsigned packed (128 to extended DFP) + s39_cxzt, // convert from zoned (to extended DFP) + s39_cy, // compare (32) + s39_czdt, // convert to zoned (from long DFP) + s39_czxt, // convert to zoned (from extended DFP) + s39_d, // divide (32 <- 64) + s39_dd, // divide (long HFP) + s39_ddb, // divide (long BFP) + s39_ddbr, // divide (long BFP) + s39_ddr, // divide (long HFP) + s39_ddtr, // divide (long DFP) + s39_ddtra, // divide (long DFP) + s39_de, // divide (short HFP) + s39_deb, // divide (short BFP) + s39_debr, // divide (short BFP) + s39_der, // divide (short HFP) + s39_dfltcc, // + s39_diag, // diagnose + s39_didbr, // divide to integer (long BFP) + s39_diebr, // divide to integer (short BFP) + s39_dl, // divide logical (32 <- 64) + s39_dlg, // divide logical (64 <- 128) + s39_dlgr, // divide logical (64 <- 128) + s39_dlr, // divide logical (32 <- 64) + s39_dp, // divide decimal + s39_dr, // divide (32 <- 64) + s39_dsg, // divide single (64) + s39_dsgf, // divide single (64 <- 32) + s39_dsgfr, // divide single (64 <- 32) + s39_dsgr, // divide single (64) + s39_dxbr, // divide (extended BFP) + s39_dxr, // divide (extended HFP) + s39_dxtr, // divide (extended DFP) + s39_dxtra, // divide (extended DFP) + s39_ear, // extract access + s39_ecag, // extract cache attribute + s39_ecctr, // extract cpu counter + s39_ecpga, // extract coprocessor-group address + s39_ectg, // extract cpu time + s39_ed, // edit + s39_edmk, // edit and mark + s39_eedtr, // extract biased exponent (long DFP to 64) + s39_eextr, // extract biased exponent (extended DFP to 64) + s39_efpc, // extract fpc + s39_epair, // extract primary ASN and instance + s39_epar, // extract primary ASN + s39_epctr, // extract peripheral counter + s39_epsw, // extract psw + s39_ereg, // extract stacked registers (32) + s39_eregg, // extract stacked registers (64) + s39_esair, // extract secondary ASN and instance + s39_esar, // extract secondary ASN + s39_esdtr, // extract significance (long DFP to 64) + s39_esea, // extract and set extended authority + s39_esta, // extract stacked state + s39_esxtr, // extract significance (extended DFP to 64) + s39_etnd, // extract transaction nesting depth + s39_ex, // execute + s39_exrl, // execute relative long + s39_fidbr, // load fp integer (long BFP) + s39_fidbra, // load fp integer (long BFP) + s39_fidr, // load fp integer (long HFP) + s39_fidtr, // load fp integer (long DFP) + s39_fiebr, // load fp integer (short BFP) + s39_fiebra, // load fp integer (short BFP) + s39_fier, // load fp integer (short HFP) + s39_fixbr, // load fp integer (extended BFP) + s39_fixbra, // load fp integer (extended BFP) + s39_fixr, // load fp integer (extended HFP) + s39_fixtr, // load fp integer (extended DFP) + s39_flogr, // find leftmost one + s39_hdr, // halve (long HFP) + s39_her, // halve (short HFP) + s39_hsch, // halt subchannel + s39_iac, // insert address space control + s39_ic, // insert character + s39_icm, // insert characters under mask (low) + s39_icmh, // insert characters under mask (high) + s39_icmy, // insert characters under mask (low) + s39_icy, // insert character + s39_idte, // invalidate dat table entry + s39_iedtr, // insert biased exponent (64 to long DFP) + s39_iextr, // insert biased exponent (64 to extended DFP) + s39_iihf, // insert immediate (high) + s39_iihh, // inset immediate (high high) + s39_iihl, // insert immediate (high low) + s39_iilf, // insert immediate (low) + s39_iilh, // insert immediate (low high) + s39_iill, // insert immediate (low low) + s39_ipk, // insert PSW key + s39_ipm, // insert program mask + s39_ipte, // invalidate page table entry + s39_irbm, // insert reference bits multiple + s39_iske, // insert storage key extended + s39_ivsk, // insert virtual storage key + s39_j, // unconditional jump + s39_jo, // conditional jump, jump on overflow / if ones + s39_jh, // conditional jump, jump on A high + s39_jnle, // conditional jump, jump on not low or equal + s39_jl, // conditional jump, jump on A low + s39_jnhe, // conditional jump, jump on not high or equal + s39_jlh, // conditional jump, jump on low or high + s39_jne, // conditional jump, jump on A not equal B + s39_je, // conditional jump, jump on A equal B + s39_jnlh, // conditional jump, jump on not low or high + s39_jhe, // conditional jump, jump on high or equal + s39_jnl, // conditional jump, jump on A not low + s39_jle, // conditional jump, jump on low or equal + s39_jnh, // conditional jump, jump on A not high + s39_jno, // conditional jump, jump on not overflow / if not ones + s39_jg, // unconditional jump long + s39_jgo, // conditional jump long, jump on overflow / if ones + s39_jgh, // conditional jump long, jump on A high + s39_jgnle, // conditional jump long, jump on not low or equal + s39_jgl, // conditional jump long, jump on A low + s39_jgnhe, // conditional jump long, jump on not high or equal + s39_jglh, // conditional jump long, jump on low or high + s39_jgne, // conditional jump long, jump on A not equal B + s39_jge, // conditional jump long, jump on A equal B + s39_jgnlh, // conditional jump long, jump on not low or high + s39_jghe, // conditional jump long, jump on high or equal + s39_jgnl, // conditional jump long, jump on A not low + s39_jgle, // conditional jump long, jump on low or equal + s39_jgnh, // conditional jump long, jump on A not high + s39_jgno, // conditional jump long, jump on not overflow / if not ones + s39_kdb, // compare and signal (long BFP) + s39_kdbr, // compare and signal (long BFP) + s39_kdsa, // + s39_kdtr, // compare and signal (long DFP) + s39_keb, // compare and signal (short BFP) + s39_kebr, // compare and signal (short BFP) + s39_kimd, // compute intermediate message digest + s39_klmd, // compute last message digest + s39_km, // cipher message + s39_kma, // cipher message with authentication + s39_kmac, // compute message with authentication + s39_kmc, // cipher message with chaining + s39_kmctr, // cipher message with counter + s39_kmf, // cipher message with cipher feedback + s39_kmo, // cipher message with output feedback + s39_kxbr, // compare and signal (extended BFP) + s39_kxtr, // compare and signal (extended DFP) + s39_l, // load (32) + s39_la, // load address + s39_laa, // load and add (32) + s39_laag, // load and add (64) + s39_laal, // load and add logical (32) + s39_laalg, // load and add logical (64) + s39_lae, // load address extended + s39_laey, // load address extended + s39_lam, // load access multiple + s39_lamy, // load access multiple + s39_lan, // load and and (32) + s39_lang, // load and and (64) + s39_lao, // load and or (32) + s39_laog, // load and or (64) + s39_larl, // load address relative long + s39_lasp, // load address space parameters + s39_lat, // load and trap (32L <- 32) + s39_lax, // load and exclusive or (32) + s39_laxg, // load and exclusive or (64) + s39_lay, // load address + s39_lb, // load byte (32 <- 8) + s39_lbh, // load byte high (32 <- 8) + s39_lbr, // load byte (32 <- 8) + s39_lcbb, // load count to block boundary + s39_lcctl, // load cpu-counter-set controls + s39_lcdbr, // load complement (long BFP) + s39_lcdfr, // load complement (long) + s39_lcdr, // load complement (long HFP) + s39_lcebr, // load complement (short BFP) + s39_lcer, // load complement (short HFP) + s39_lcgfr, // load complement (64 <- 32) + s39_lcgr, // load complement (64) + s39_lcr, // load complement (32) + s39_lctl, // load control (32) + s39_lctlg, // load control (64) + s39_lcxbr, // load complement (extended BFP) + s39_lcxr, // load complement (extended HFP) + s39_ld, // load (long) + s39_lde, // load lengthened (short to long HFP) + s39_ldeb, // load lengthened (short to long BFP) + s39_ldebr, // load lengthened (short to long BFP) + s39_lder, // load lengthened (short to long HFP) + s39_ldetr, // load lengthened (short to long DFP) + s39_ldgr, // load fpr from gr (64 to long) + s39_ldr, // load (long) + s39_ldrv, // + s39_ldxbr, // load rounded (extended to long BFP) + s39_ldxbra, // load rounded (extended to long BFP) + s39_ldxr, // load rounded (extended to long HFP) + s39_ldxtr, // load rounded (extended to long HFP) + s39_ldy, // load (long) + s39_le, // load (short) + s39_ledbr, // load rounded (long to short BFP) + s39_ledbra, // load rounded (long to short BFP) + s39_ledr, // load rounded (long to short HFP) + s39_ledtr, // load rounded (long to short DFP) + s39_ler, // load short + s39_lerv, // + s39_lexbr, // load rounded (extended to short BFP) + s39_lexbra, // load rounded (extended to short BFP) + s39_lexr, // load rounded (extended to short HFP) + s39_ley, // load (short) + s39_lfas, // load fpc and signal + s39_lfh, // load high (32) + s39_lfhat, // load high and trap (32h <- 32) + s39_lfpc, // load fpc + s39_lg, // load (64) + s39_lgat, // load and trap (64) + s39_lgb, // load byte (64 <- 8) + s39_lgbr, // load byte (64 <- 8) + s39_lgdr, // load gr from fpr (long to 64) + s39_lgf, // load (64 <- 32) + s39_lgfi, // load immediate (64 <- 32) + s39_lgfr, // load (64 <- 32) + s39_lgfrl, // load relative long (64 <- 32) + s39_lgg, // load guarded (64) + s39_lgh, // load halfword (64 <- 16) + s39_lghi, // load halfword immediate (64 <- 16) + s39_lghr, // load halfword (64 <- 16) + s39_lghrl, // load halfword relative long (64 <- 16) + s39_lgr, // load (64) + s39_lgrl, // load relative long (64) + s39_lgsc, // load guarded storage controls + s39_lh, // load halfword (32 <- 16) + s39_lhh, // load halfword high (32 <- 16) + s39_lhi, // load halfword immediate (32) <- 16 + s39_lhr, // load halfword (32 <- 16) + s39_lhrl, // load halfword relative long (32 <- 16) + s39_lhy, // load halfword (32 <- 16) + s39_llc, // load logical character (32 <- 8) + s39_llch, // load logical character high (32 <- 8) + s39_llcr, // load logical character (32 <- 8) + s39_llgc, // load logical character (64 <- 8) + s39_llgcr, // load logical character (64 <- 8) + s39_llgf, // load logical (64 <- 32) + s39_llgfat, // load logical and trap (64 <- 32) + s39_llgfr, // load logical (64 <- 32) + s39_llgfrl, // load logical relative long (64 <- 32) + s39_llgfsg, // load logical and shift guarded (64 <- 32) + s39_llgh, // load logical halfword (64 <- 16) + s39_llghr, // load logical halfword (64 <- 16) + s39_llghrl, // load logical halfword relative long (64 <- 16) + s39_llgt, // load logical thirty one bits (64 <- 31) + s39_llgtat, // load logical thirty one bits and trap (64 <- 31) + s39_llgtr, // load logical thirty one bits (64 <- 31) + s39_llh, // load logical halfword (32 <- 16) + s39_llhh, // load logical halfword high (32 <- 16) + s39_llhr, // load logical halfword (32 <- 16) + s39_llhrl, // load logical halfword relative long (32 <- 16) + s39_llihf, // load logical immediate (high) + s39_llihh, // load logical immediate (high high) + s39_llihl, // load logical immediate (high low) + s39_llilf, // load logical immediate (low) + s39_llilh, // load logical immediate (low high) + s39_llill, // load logical immediate (low low) + s39_llzrgf, // load logical and zero rightmost byte (64 <- 32) + s39_lm, // load multiple (32) + s39_lmd, // load multiple disjoint (64 <- 32& 32) + s39_lmg, // load multiple (64) + s39_lmh, // load multiple high (32) + s39_lmy, // load multiple high (32) + s39_lndbr, // load negative (long BFP) + s39_lndfr, // load negative (long) + s39_lndr, // load negative (long HFP) + s39_lnebr, // load negative (short BFP) + s39_lner, // load negative (short HFP) + s39_lngfr, // load negative (64 <- 32) + s39_lngr, // load negative (64) + s39_lnr, // load negative (32) + s39_lnxbr, // load negative (extended BFP) + s39_lnxr, // load negative (extended HFP) + s39_loc, // load on condition (32) + s39_loco, // load on condition (32), jump on overflow / if ones + s39_loch, // load on condition (32), jump on A high + s39_locnle, // load on condition (32), jump on not low or equal + s39_locl, // load on condition (32), jump on A low + s39_locnhe, // load on condition (32), jump on not high or equal + s39_loclh, // load on condition (32), jump on low or high + s39_locne, // load on condition (32), jump on A not equal B + s39_loce, // load on condition (32), jump on A equal B + s39_locnlh, // load on condition (32), jump on not low or high + s39_loche, // load on condition (32), jump on high or equal + s39_locnl, // load on condition (32), jump on A not low + s39_locle, // load on condition (32), jump on low or equal + s39_locnh, // load on condition (32), jump on A not high + s39_locno, // load on condition (32), jump on not overflow / if not ones + s39_locfh, // load high on condition (32) + s39_locfho, // load high on condition (32), jump on overflow / if ones + s39_locfhh, // load high on condition (32), jump on A high + s39_locfhnle, // load high on condition (32), jump on not low or equal + s39_locfhl, // load high on condition (32), jump on A low + s39_locfhnhe, // load high on condition (32), jump on not high or equal + s39_locfhlh, // load high on condition (32), jump on low or high + s39_locfhne, // load high on condition (32), jump on A not equal B + s39_locfhe, // load high on condition (32), jump on A equal B + s39_locfhnlh, // load high on condition (32), jump on not low or high + s39_locfhhe, // load high on condition (32), jump on high or equal + s39_locfhnl, // load high on condition (32), jump on A not low + s39_locfhle, // load high on condition (32), jump on low or equal + s39_locfhnh, // load high on condition (32), jump on A not high + s39_locfhno, // load high on condition (32), jump on not overflow / if not ones + s39_locfhr, // load high on condition (32) + s39_locfhro, // load high on condition (32), jump on overflow / if ones + s39_locfhrh, // load high on condition (32), jump on A high + s39_locfhrnle, // load high on condition (32), jump on not low or equal + s39_locfhrl, // load high on condition (32), jump on A low + s39_locfhrnhe, // load high on condition (32), jump on not high or equal + s39_locfhrlh, // load high on condition (32), jump on low or high + s39_locfhrne, // load high on condition (32), jump on A not equal B + s39_locfhre, // load high on condition (32), jump on A equal B + s39_locfhrnlh, // load high on condition (32), jump on not low or high + s39_locfhrhe, // load high on condition (32), jump on high or equal + s39_locfhrnl, // load high on condition (32), jump on A not low + s39_locfhrle, // load high on condition (32), jump on low or equal + s39_locfhrnh, // load high on condition (32), jump on A not high + s39_locfhrno, // load high on condition (32), jump on not overflow / if not ones + s39_locg, // load on condition (64) + s39_locgo, // load on condition (64), jump on overflow / if ones + s39_locgh, // load on condition (64), jump on A high + s39_locgnle, // load on condition (64), jump on not low or equal + s39_locgl, // load on condition (64), jump on A low + s39_locgnhe, // load on condition (64), jump on not high or equal + s39_locglh, // load on condition (64), jump on low or high + s39_locgne, // load on condition (64), jump on A not equal B + s39_locge, // load on condition (64), jump on A equal B + s39_locgnlh, // load on condition (64), jump on not low or high + s39_locghe, // load on condition (64), jump on high or equal + s39_locgnl, // load on condition (64), jump on A not low + s39_locgle, // load on condition (64), jump on low or equal + s39_locgnh, // load on condition (64), jump on A not high + s39_locgno, // load on condition (64), jump on not overflow / if not ones + s39_locghi, // load halfword immediate on condition (64 <- 16) + s39_locghio, // load halfword immediate on condition (64 <- 16), jump on overflow / if ones + s39_locghih, // load halfword immediate on condition (64 <- 16), jump on A high + s39_locghinle, // load halfword immediate on condition (64 <- 16), jump on not low or equal + s39_locghil, // load halfword immediate on condition (64 <- 16), jump on A low + s39_locghinhe, // load halfword immediate on condition (64 <- 16), jump on not high or equal + s39_locghilh, // load halfword immediate on condition (64 <- 16), jump on low or high + s39_locghine, // load halfword immediate on condition (64 <- 16), jump on A not equal B + s39_locghie, // load halfword immediate on condition (64 <- 16), jump on A equal B + s39_locghinlh, // load halfword immediate on condition (64 <- 16), jump on not low or high + s39_locghihe, // load halfword immediate on condition (64 <- 16), jump on high or equal + s39_locghinl, // load halfword immediate on condition (64 <- 16), jump on A not low + s39_locghile, // load halfword immediate on condition (64 <- 16), jump on low or equal + s39_locghinh, // load halfword immediate on condition (64 <- 16), jump on A not high + s39_locghino, // load halfword immediate on condition (64 <- 16), jump on not overflow / if not ones + s39_locgr, // load on condition (64) + s39_locgro, // load on condition (64), jump on overflow / if ones + s39_locgrh, // load on condition (64), jump on A high + s39_locgrnle, // load on condition (64), jump on not low or equal + s39_locgrl, // load on condition (64), jump on A low + s39_locgrnhe, // load on condition (64), jump on not high or equal + s39_locgrlh, // load on condition (64), jump on low or high + s39_locgrne, // load on condition (64), jump on A not equal B + s39_locgre, // load on condition (64), jump on A equal B + s39_locgrnlh, // load on condition (64), jump on not low or high + s39_locgrhe, // load on condition (64), jump on high or equal + s39_locgrnl, // load on condition (64), jump on A not low + s39_locgrle, // load on condition (64), jump on low or equal + s39_locgrnh, // load on condition (64), jump on A not high + s39_locgrno, // load on condition (64), jump on not overflow / if not ones + s39_lochhi, // load halfword high immediate on condition (32 <- 16) + s39_lochhio, // load halfword high immediate on condition (32 <- 16), jump on overflow / if ones + s39_lochhih, // load halfword high immediate on condition (32 <- 16), jump on A high + s39_lochhinle, // load halfword high immediate on condition (32 <- 16), jump on not low or equal + s39_lochhil, // load halfword high immediate on condition (32 <- 16), jump on A low + s39_lochhinhe, // load halfword high immediate on condition (32 <- 16), jump on not high or equal + s39_lochhilh, // load halfword high immediate on condition (32 <- 16), jump on low or high + s39_lochhine, // load halfword high immediate on condition (32 <- 16), jump on A not equal B + s39_lochhie, // load halfword high immediate on condition (32 <- 16), jump on A equal B + s39_lochhinlh, // load halfword high immediate on condition (32 <- 16), jump on not low or high + s39_lochhihe, // load halfword high immediate on condition (32 <- 16), jump on high or equal + s39_lochhinl, // load halfword high immediate on condition (32 <- 16), jump on A not low + s39_lochhile, // load halfword high immediate on condition (32 <- 16), jump on low or equal + s39_lochhinh, // load halfword high immediate on condition (32 <- 16), jump on A not high + s39_lochhino, // load halfword high immediate on condition (32 <- 16), jump on not overflow / if not ones + s39_lochi, // load halfword immediate on condition (32 <- 16) + s39_lochio, // load halfword immediate on condition (32 <- 16), jump on overflow / if ones + s39_lochih, // load halfword immediate on condition (32 <- 16), jump on A high + s39_lochinle, // load halfword immediate on condition (32 <- 16), jump on not low or equal + s39_lochil, // load halfword immediate on condition (32 <- 16), jump on A low + s39_lochinhe, // load halfword immediate on condition (32 <- 16), jump on not high or equal + s39_lochilh, // load halfword immediate on condition (32 <- 16), jump on low or high + s39_lochine, // load halfword immediate on condition (32 <- 16), jump on A not equal B + s39_lochie, // load halfword immediate on condition (32 <- 16), jump on A equal B + s39_lochinlh, // load halfword immediate on condition (32 <- 16), jump on not low or high + s39_lochihe, // load halfword immediate on condition (32 <- 16), jump on high or equal + s39_lochinl, // load halfword immediate on condition (32 <- 16), jump on A not low + s39_lochile, // load halfword immediate on condition (32 <- 16), jump on low or equal + s39_lochinh, // load halfword immediate on condition (32 <- 16), jump on A not high + s39_lochino, // load halfword immediate on condition (32 <- 16), jump on not overflow / if not ones + s39_locr, // load on condition (32) + s39_locro, // load on condition (32), jump on overflow / if ones + s39_locrh, // load on condition (32), jump on A high + s39_locrnle, // load on condition (32), jump on not low or equal + s39_locrl, // load on condition (32), jump on A low + s39_locrnhe, // load on condition (32), jump on not high or equal + s39_locrlh, // load on condition (32), jump on low or high + s39_locrne, // load on condition (32), jump on A not equal B + s39_locre, // load on condition (32), jump on A equal B + s39_locrnlh, // load on condition (32), jump on not low or high + s39_locrhe, // load on condition (32), jump on high or equal + s39_locrnl, // load on condition (32), jump on A not low + s39_locrle, // load on condition (32), jump on low or equal + s39_locrnh, // load on condition (32), jump on A not high + s39_locrno, // load on condition (32), jump on not overflow / if not ones + s39_lpctl, // load peripheral-counter-set controls + s39_lpd, // load pair disjoint (32) + s39_lpdbr, // load positive (long BFP) + s39_lpdfr, // load positive (long) + s39_lpdg, // load pair disjoint (64) + s39_lpdr, // load positive (long HFP) + s39_lpebr, // load positive (short BFP) + s39_lper, // load positive (short HFP) + s39_lpgfr, // load positive (64 <- 32) + s39_lpgr, // load positive (64) + s39_lpp, // load program parameter + s39_lpq, // load pair from quadword (64&64 <- 128) + s39_lpr, // load positive (32) + s39_lpsw, // load PSW + s39_lpswe, // load psw extended + s39_lptea, // load page-table-entry address + s39_lpxbr, // load positive (extended BFP) + s39_lpxr, // load positive (extended HFP) + s39_lr, // load (32) + s39_lra, // load real address (32) + s39_lrag, // load real address (64) + s39_lray, // load real address (32) + s39_lrdr, // load rounded (extended to long HFP) + s39_lrer, // load rounded (long to short HFP) + s39_lrl, // load relative long (32) + s39_lrv, // load reversed (32) + s39_lrvg, // load reversed (64) + s39_lrvgr, // load reversed (64) + s39_lrvh, // load reversed (16) + s39_lrvr, // load reversed (32) + s39_lsctl, // load sampling controls + s39_lt, // load and test (32) + s39_ltdbr, // load and test (long BFP) + s39_ltdr, // load and test (long HFP) + s39_ltdtr, // load and test (long DFP) + s39_ltebr, // load and test (short BFP) + s39_lter, // load and test (short HFP) + s39_ltg, // load and test (64) + s39_ltgf, // load and test (64 <- 32) + s39_ltgfr, // load and test (64 <- 32) + s39_ltgr, // load and test (64) + s39_ltr, // load and test (32) + s39_ltxbr, // load and test (extended BFP) + s39_ltxr, // load and test (extended HFP) + s39_ltxtr, // load and test (extended DFP) + s39_lura, // load using real address (32) + s39_lurag, // load using real address (64) + s39_lxd, // load lengthened (long to extended HFP) + s39_lxdb, // load lengthened (long to extended BFP) + s39_lxdbr, // load lengthened (long to extended BFP) + s39_lxdr, // load lengthened (long to extended HFP) + s39_lxdtr, // load lengthened (long to extended DFP) + s39_lxe, // load lengthened (short to extended HFP) + s39_lxeb, // load lengthened (short to extended BFP) + s39_lxebr, // load lengthened (short to extended BFP) + s39_lxer, // load lengthened (short to extended HFP) + s39_lxr, // load (extended) + s39_ly, // load (32) + s39_lzdr, // load zero (long) + s39_lzer, // load zero (short) + s39_lzrf, // load and zero rightmost byte (32) + s39_lzrg, // load and zero rightmost byte (64) + s39_lzxr, // load zero (extended) + s39_m, // multiply (64 <- 32) + s39_mad, // multiply and add (long HFP) + s39_madb, // multiply and add (long BFP) + s39_madbr, // multiply and add (long BFP) + s39_madr, // multiply and add (long HFP) + s39_mae, // multiply and add (short HFP) + s39_maeb, // multiply and add (short BFP) + s39_maebr, // multiply and add (short BFP) + s39_maer, // multiply and add (short HFP) + s39_may, // multiply & add unnormalized (long to extended HFP) + s39_mayh, // multiply & add unnormalized (long to extended high HFP) + s39_mayhr, // multiply & add unnormalized (long to extended high HFP) + s39_mayl, // multiply & add unnormalized (long to extended low HFP) + s39_maylr, // multiply & add unnormalized (long to extended low HFP) + s39_mayr, // multiply & add unnormalized (long to extended HFP) + s39_mc, // monitor call + s39_md, // multiply (long HFP) + s39_mdb, // multiply (long BFP) + s39_mdbr, // multiply (long BFP) + s39_mde, // multiply (short to long HFP) + s39_mdeb, // multiply (short to long BFP) + s39_mdebr, // multiply (short to long BFP) + s39_mder, // multiply (short to long HFP) + s39_mdr, // multiply (long HFP) + s39_mdtr, // multiply (long DFP) + s39_mdtra, // multiply (long DFP) + s39_me, // multiply (short to long HFP) + s39_mee, // multiply (short HFP) + s39_meeb, // multiply (short BFP) + s39_meebr, // multiply (short BFP) + s39_meer, // multiply (short HFP) + s39_mer, // multiply (short to long HFP) + s39_mfy, // multiply (64 <- 32) + s39_mg, // multiply (128 <- 64) + s39_mgh, // multiply halfword (64 <- 16) + s39_mghi, // multiply halfword immediate (64 <- 16) + s39_mgrk, // multiply (128 <- 64) + s39_mh, // multiply halfword (32 <- 16) + s39_mhi, // multiply halfword immediate (32 <- 16) + s39_mhy, // multiply halfword (32 <- 16) + s39_ml, // multiply logical (64 <- 32) + s39_mlg, // multiply logical (128 <- 64) + s39_mlgr, // multiply logical (128 <- 64) + s39_mlr, // multiply logical (64 <- 32) + s39_mp, // multiply decimal + s39_mr, // multiply (64 <- 32) + s39_ms, // multiply single (32) + s39_msc, // multiply single (32) + s39_msch, // modify subchannel + s39_msd, // multiply and subtract (long HFP) + s39_msdb, // multiply and subtract (long BFP) + s39_msdbr, // multiply and subtract (long BFP) + s39_msdr, // multiply and subtract (long HFP) + s39_mse, // multiply and subtract (short HFP) + s39_mseb, // multiply and subtract (short BFP) + s39_msebr, // multiply and subtract (short BFP) + s39_mser, // multiply and subtract (short HFP) + s39_msfi, // multiply single immediate (32) + s39_msg, // multiply single (64) + s39_msgc, // multiply single (64) + s39_msgf, // multiply single (64 <- 32) + s39_msgfi, // multiply single immediate (64 <- 32) + s39_msgfr, // multiply single (64 <- 32) + s39_msgr, // multiply single (64) + s39_msgrkc, // multiply single (64) + s39_msr, // multiply single (32) + s39_msrkc, // multiply single (32) + s39_msta, // modify stacked state + s39_msy, // multiply single (32) + s39_mvc, // move (character) + s39_mvcdk, // move with destination key + s39_mvcin, // move inverse + s39_mvck, // move with key + s39_mvcl, // move long + s39_mvcle, // move long extended + s39_mvclu, // move long unicode + s39_mvcos, // move with optional specifications + s39_mvcp, // move to primary + s39_mvcrl, // + s39_mvcs, // move to secondary + s39_mvcsk, // move with source key + s39_mvghi, // move (64 <- 16) + s39_mvhhi, // move (16 <- 16) + s39_mvhi, // move (32 <- 16) + s39_mvi, // move (immediate) + s39_mviy, // move (immediate) + s39_mvn, // move numerics + s39_mvo, // move with offset + s39_mvpg, // move page + s39_mvst, // move string + s39_mvz, // move zones + s39_mxbr, // multiply (extended BFP) + s39_mxd, // multiply (long to extended HFP) + s39_mxdb, // multiply (long to extended BFP) + s39_mxdbr, // multiply (long to extended BFP) + s39_mxdr, // multiply (long to extended HFP) + s39_mxr, // multiply (extended HFP) + s39_mxtr, // multiply (extended DFP) + s39_mxtra, // multiply (extended DFP) + s39_my, // multiply unnormalized (long to extended HFP) + s39_myh, // multiply unnormalized (long to extended high HFP) + s39_myhr, // multiply unnormalized (long to extended high HFP) + s39_myl, // multiply unnormalized (long to extended low HFP) + s39_mylr, // multiply unnormalized (long to extended low HFP) + s39_myr, // multiply unnormalized (long to extended HFP) + s39_n, // and (32) + s39_nc, // and (character) + s39_ncgrk, // + s39_ncrk, // + s39_ng, // and (64) + s39_ngr, // and (64) + s39_ngrk, // and (64) + s39_ni, // and (immediate) + s39_niai, // next instruction access intent + s39_nihf, // and immediate (high) + s39_nihh, // and immediate (high high) + s39_nihl, // and immediate (high low) + s39_nilf, // and immediate (low) + s39_nilh, // and immediate (low high) + s39_nill, // and immediate (low low) + s39_niy, // and (immediate) + s39_nngrk, // + s39_nnrk, // + s39_nogrk, // + s39_nop, // no operation + s39_nopr, // no operation + s39_nork, // + s39_nr, // and (32) + s39_nrk, // and (32) + s39_ntstg, // nontransactional store (64) + s39_nxgrk, // + s39_nxrk, // + s39_ny, // and (32) + s39_o, // or (32) + s39_oc, // or (character) + s39_ocgrk, // + s39_ocrk, // + s39_og, // or (64) + s39_ogr, // or (64) + s39_ogrk, // or (64) + s39_oi, // or (immediate) + s39_oihf, // or immediate (high) + s39_oihh, // or immediate (high high) + s39_oihl, // or immediate (high low) + s39_oilf, // or immediate (low) + s39_oilh, // or immediate (low high) + s39_oill, // or immediate (low low) + s39_oiy, // or (immediate) + s39_or, // or (32) + s39_ork, // or (32) + s39_oy, // or (32) + s39_pack, // pack + s39_palb, // purge ALB + s39_pc, // program call + s39_pcc, // perform cryptographic computation + s39_pckmo, // perform cryptographic key management operation + s39_pfd, // prefetch data + s39_pfdrl, // prefetch data relative long + s39_pfmf, // perform frame management function + s39_pfpo, // perform floating point operation + s39_pgin, // page in + s39_pgout, // page out + s39_pka, // pack ascii + s39_pku, // pack unicode + s39_plo, // perform locked operation + s39_popcnt, // population count + s39_ppa, // perform processor assist + s39_ppno, // perform pseudorandom number operation + s39_pr, // program return + s39_prno, // perform pseudorandom number operation + s39_pt, // program transfer + s39_ptf, // perform topology function + s39_ptff, // perform timing facility function + s39_pti, // program transfer with instance + s39_ptlb, // purge TLB + s39_qadtr, // quantize (long DFP) + s39_qaxtr, // quantize (extended DFP) + s39_qctri, // query counter information + s39_qsi, // query sampling information + s39_rchp, // reset channel path + s39_risbg, // rotate then insert selected bits (64) + s39_risbgn, // rotate then insert selected bits (64) + s39_risbhg, // rotate then insert selected bits high (64) + s39_risblg, // rotate then insert selected bits low (64) + s39_rll, // rotate left single logical (32) + s39_rllg, // rotate left single logical (64) + s39_rnsbg, // rotate then and selected bits (64) + s39_rosbg, // rotate then or selected bits (64) + s39_rp, // resume program + s39_rrbe, // reset reference bit extended + s39_rrbm, // reset reference bits multiple + s39_rrdtr, // reround (long DFP) + s39_rrxtr, // reround (extended DFP) + s39_rsch, // resume subchannel + s39_rxsbg, // rotate then exclusive or selected bits (64) + s39_s, // subtract (32) + s39_sac, // set address space control + s39_sacf, // set address space control fast + s39_sal, // set address limit + s39_sam24, // set addressing mode 24 + s39_sam31, // set addressing mode 31 + s39_sam64, // set addressing mode 64 + s39_sar, // set access + s39_scctr, // set cpu counter + s39_schm, // set channel monitor + s39_sck, // set clock + s39_sckc, // set clock comparator + s39_sckpf, // set clock programmable field + s39_sd, // subtract normalized (long HFP) + s39_sdb, // subtract (long BFP) + s39_sdbr, // subtract (long BFP) + s39_sdr, // subtract normalized (long HFP) + s39_sdtr, // subtract normalized (long DFP) + s39_sdtra, // subtract normalized (long DFP) + s39_se, // subtract normalized (short HFP) + s39_seb, // subtract (short BFP) + s39_sebr, // subtract (short BFP) + s39_selgr, // + s39_selgro, // , jump on overflow / if ones + s39_selgrh, // , jump on A high + s39_selgrnle, // , jump on not low or equal + s39_selgrl, // , jump on A low + s39_selgrnhe, // , jump on not high or equal + s39_selgrlh, // , jump on low or high + s39_selgrne, // , jump on A not equal B + s39_selgre, // , jump on A equal B + s39_selgrnlh, // , jump on not low or high + s39_selgrhe, // , jump on high or equal + s39_selgrnl, // , jump on A not low + s39_selgrle, // , jump on low or equal + s39_selgrnh, // , jump on A not high + s39_selgrno, // , jump on not overflow / if not ones + s39_selhhhr, // + s39_selhhhro, // , jump on overflow / if ones + s39_selhhhrh, // , jump on A high + s39_selhhhrnle, // , jump on not low or equal + s39_selhhhrl, // , jump on A low + s39_selhhhrnhe, // , jump on not high or equal + s39_selhhhrlh, // , jump on low or high + s39_selhhhrne, // , jump on A not equal B + s39_selhhhre, // , jump on A equal B + s39_selhhhrnlh, // , jump on not low or high + s39_selhhhrhe, // , jump on high or equal + s39_selhhhrnl, // , jump on A not low + s39_selhhhrle, // , jump on low or equal + s39_selhhhrnh, // , jump on A not high + s39_selhhhrno, // , jump on not overflow / if not ones + s39_selr, // + s39_selro, // , jump on overflow / if ones + s39_selrh, // , jump on A high + s39_selrnle, // , jump on not low or equal + s39_selrl, // , jump on A low + s39_selrnhe, // , jump on not high or equal + s39_selrlh, // , jump on low or high + s39_selrne, // , jump on A not equal B + s39_selre, // , jump on A equal B + s39_selrnlh, // , jump on not low or high + s39_selrhe, // , jump on high or equal + s39_selrnl, // , jump on A not low + s39_selrle, // , jump on low or equal + s39_selrnh, // , jump on A not high + s39_selrno, // , jump on not overflow / if not ones + s39_ser, // subtract normalized (short HFP) + s39_sfasr, // set fpc and signal + s39_sfpc, // set fpc + s39_sg, // subtract (64) + s39_sgf, // subtract (64 <- 32) + s39_sgfr, // subtract (64 <- 32) + s39_sgh, // sintract halfword (64 <- 16) + s39_sgr, // subtract (64) + s39_sgrk, // subtract (64) + s39_sh, // subtract halfword (32 <- 16) + s39_shhhr, // subtract high (32) + s39_shhlr, // subtract high (32) + s39_shy, // subtract halfword (32 <- 16) + s39_sie, // start interpretive execution + s39_siga, // signal adapter + s39_sigp, // signal processor + s39_sl, // subtract logical (32) + s39_sla, // shift left single (32) + s39_slag, // shift left single (64) + s39_slak, // shift left single (32) + s39_slb, // subtract logical with borrow (32) + s39_slbg, // subtract logical with borrow (64) + s39_slbgr, // subtract logical with borrow (64) + s39_slbr, // subtract logical with borrow (32) + s39_slda, // shift left double (64) + s39_sldl, // shift left double logical (64) + s39_sldt, // shift significand left (long DFP) + s39_slfi, // subtract logical immediate (32) + s39_slg, // subtract logical (64) + s39_slgf, // subtract logical (64 <- 32) + s39_slgfi, // subtract logical (64 <- 32) + s39_slgfr, // subtract logical (64 <- 32) + s39_slgr, // subtract logical (64) + s39_slgrk, // subtract logical (64) + s39_slhhhr, // subtract logical high (32) + s39_slhhlr, // subtract logical high (32) + s39_sll, // shift left single logical (32) + s39_sllg, // shift left single logical (64) + s39_sllk, // shift left single logical (32) + s39_slr, // subtract logical (32) + s39_slrk, // subtract logical (32) + s39_slxt, // shift significand left (extended DFP) + s39_sly, // subtract logical (32) + s39_sortl, // + s39_sp, // subtract decimal + s39_spctr, // set peripheral counter + s39_spka, // set PSW key from address + s39_spm, // set program mask + s39_spt, // set CPU timer + s39_spx, // set prefix + s39_sqd, // square root (long HFP) + s39_sqdb, // square root (long BFP) + s39_sqdbr, // square root (long BFP) + s39_sqdr, // square root (long HFP) + s39_sqe, // square root (short HFP) + s39_sqeb, // square root (short BFP) + s39_sqebr, // square root (short BFP) + s39_sqer, // square root (short HFP) + s39_sqxbr, // square root (extended BFP) + s39_sqxr, // square root (extended HFP) + s39_sr, // subtract (32) + s39_sra, // shift right single (32) + s39_srag, // shift right single (64) + s39_srak, // shift right single (32) + s39_srda, // shift right double (64) + s39_srdl, // shift right double logical (64) + s39_srdt, // shift significand right (long DFP) + s39_srk, // subtract (32) + s39_srl, // shift right single logical (32) + s39_srlg, // shift right single logical (64) + s39_srlk, // shift right single logical (64) + s39_srnm, // set bfp rounding mode (2bit) + s39_srnmb, // set bfp rounding mode (3bit) + s39_srnmt, // set dfp rounding mode + s39_srp, // shift and round decimal + s39_srst, // search string + s39_srstu, // search string unicode + s39_srxt, // shift significand right (extended DFP) + s39_ssair, // set secondary ASN with instance + s39_ssar, // set secondary ASN + s39_ssch, // start subchannel + s39_sske, // set storage key extended + s39_ssm, // set system mask + s39_st, // store (32) + s39_stam, // store access multiple + s39_stamy, // store access multiple + s39_stap, // store CPU address + s39_stc, // store character + s39_stch, // store character high (8) + s39_stck, // store clock + s39_stckc, // store clock comparator + s39_stcke, // store clock extended + s39_stckf, // store clock fast + s39_stcm, // store characters under mask (low) + s39_stcmh, // store characters under mask (high) + s39_stcmy, // store characters under mask (low) + s39_stcps, // store channel path status + s39_stcrw, // store channel report word + s39_stctg, // store control (64) + s39_stctl, // store control (64) + s39_stcy, // store character + s39_std, // store (long) + s39_stdrv, // + s39_stdy, // store (long) + s39_ste, // store (short) + s39_sterv, // + s39_stey, // store (short) + s39_stfh, // store high (32) + s39_stfl, // store facility list + s39_stfle, // store facility list extended + s39_stfpc, // store fpc + s39_stg, // store (64) + s39_stgrl, // store relative long (64) + s39_stgsc, // store guarded storage controls + s39_sth, // store halfword (16) + s39_sthh, // store halfword high (16) + s39_sthrl, // store halfword relative long (16) + s39_sthy, // store halfword (16) + s39_stidp, // store CPU id + s39_stm, // store multiple (32) + s39_stmg, // store multiple (64) + s39_stmh, // store multiple high (32) + s39_stmy, // store multiple (32) + s39_stnsm, // store then and system mask + s39_stoc, // store on condition (32) + s39_stoco, // store on condition (32), jump on overflow / if ones + s39_stoch, // store on condition (32), jump on A high + s39_stocnle, // store on condition (32), jump on not low or equal + s39_stocl, // store on condition (32), jump on A low + s39_stocnhe, // store on condition (32), jump on not high or equal + s39_stoclh, // store on condition (32), jump on low or high + s39_stocne, // store on condition (32), jump on A not equal B + s39_stoce, // store on condition (32), jump on A equal B + s39_stocnlh, // store on condition (32), jump on not low or high + s39_stoche, // store on condition (32), jump on high or equal + s39_stocnl, // store on condition (32), jump on A not low + s39_stocle, // store on condition (32), jump on low or equal + s39_stocnh, // store on condition (32), jump on A not high + s39_stocno, // store on condition (32), jump on not overflow / if not ones + s39_stocfh, // store high on condition + s39_stocfho, // store high on condition, jump on overflow / if ones + s39_stocfhh, // store high on condition, jump on A high + s39_stocfhnle, // store high on condition, jump on not low or equal + s39_stocfhl, // store high on condition, jump on A low + s39_stocfhnhe, // store high on condition, jump on not high or equal + s39_stocfhlh, // store high on condition, jump on low or high + s39_stocfhne, // store high on condition, jump on A not equal B + s39_stocfhe, // store high on condition, jump on A equal B + s39_stocfhnlh, // store high on condition, jump on not low or high + s39_stocfhhe, // store high on condition, jump on high or equal + s39_stocfhnl, // store high on condition, jump on A not low + s39_stocfhle, // store high on condition, jump on low or equal + s39_stocfhnh, // store high on condition, jump on A not high + s39_stocfhno, // store high on condition, jump on not overflow / if not ones + s39_stocg, // store on condition (64) + s39_stocgo, // store on condition (64), jump on overflow / if ones + s39_stocgh, // store on condition (64), jump on A high + s39_stocgnle, // store on condition (64), jump on not low or equal + s39_stocgl, // store on condition (64), jump on A low + s39_stocgnhe, // store on condition (64), jump on not high or equal + s39_stocglh, // store on condition (64), jump on low or high + s39_stocgne, // store on condition (64), jump on A not equal B + s39_stocge, // store on condition (64), jump on A equal B + s39_stocgnlh, // store on condition (64), jump on not low or high + s39_stocghe, // store on condition (64), jump on high or equal + s39_stocgnl, // store on condition (64), jump on A not low + s39_stocgle, // store on condition (64), jump on low or equal + s39_stocgnh, // store on condition (64), jump on A not high + s39_stocgno, // store on condition (64), jump on not overflow / if not ones + s39_stosm, // store then or system mask + s39_stpq, // store pair to quadword + s39_stpt, // store CPU timer + s39_stpx, // store prefix + s39_strag, // store real address + s39_strl, // store relative long (32) + s39_strv, // store reversed (32) + s39_strvg, // store reversed (64) + s39_strvh, // store reversed (16) + s39_stsch, // store subchannel + s39_stsi, // store system information + s39_stura, // store using real address (32) + s39_sturg, // store using real address (64) + s39_sty, // store (32) + s39_su, // subtract unnormalized (short HFP) + s39_sur, // subtract unnormalized (short HFP) + s39_svc, // supervisor call + s39_sw, // subtract unnormalized (long HFP) + s39_swr, // subtract unnormalized (long HFP) + s39_sxbr, // subtract (extended BFP) + s39_sxr, // subtract normalized (extended HFP) + s39_sxtr, // subtract (extended DFP) + s39_sxtra, // subtract (extended DFP) + s39_sy, // subtract (32) + s39_tabort, // transaction abort + s39_tam, // test addressing mode + s39_tar, // test access + s39_tb, // test block + s39_tbdr, // convert HFP to BFP (long) + s39_tbedr, // convert HFP to BFP (long to short) + s39_tbegin, // transaction begin (nonconstrained) + s39_tbeginc, // transaction begin (constrained) + s39_tcdb, // test data class (long BFP) + s39_tceb, // test data class (short BFP) + s39_tcxb, // test data class (extended BFP) + s39_tdcdt, // test data class (long DFP) + s39_tdcet, // test data class (short DFP) + s39_tdcxt, // test data class (extended DFP) + s39_tdgdt, // test data group (long DFP) + s39_tdget, // test data group (short DFP) + s39_tdgxt, // test data group (extended DFP) + s39_tend, // transaction end + s39_thder, // convert BFP to HFP (short to long) + s39_thdr, // convert BFP to HFP (long) + s39_tm, // test under mask + s39_tmhh, // test under mask (high high) + s39_tmhl, // test under mask (high low) + s39_tmlh, // test under mask (low high) + s39_tmll, // test under mask (low low) + s39_tmy, // test under mask + s39_tp, // test decimal + s39_tpei, // test pending external interruption + s39_tpi, // test pending interruption + s39_tprot, // test protection + s39_tr, // translate + s39_trace, // trace (32) + s39_tracg, // trace (64) + s39_trap2, // trap + s39_trap4, // trap + s39_tre, // translate extended + s39_troo, // translate one to one + s39_trot, // translate one to two + s39_trt, // translate and test + s39_trte, // translate and test extended + s39_trto, // translate two to one + s39_trtr, // translate and test reverse + s39_trtre, // translate and test reverse extended + s39_trtt, // translate two to two + s39_ts, // test and set + s39_tsch, // test subchannel + s39_unpk, // unpack + s39_unpka, // unpack ascii + s39_unpku, // unpack unicode + s39_upt, // update tree + s39_va, // vector add + s39_vab, // vector add byte + s39_vac, // vector add with carry + s39_vacc, // vector add compute carry + s39_vaccb, // vector add compute carry byte + s39_vaccc, // vector add with carry compute carry + s39_vacccq, // vector add with carry compute carry quadword + s39_vaccf, // vector add compute carry word + s39_vaccg, // vector add compute carry doubleword + s39_vacch, // vector add compute carry halfword + s39_vaccq, // vector add compute carry quadword + s39_vacq, // vector add with carry quadword + s39_vaf, // vector add word + s39_vag, // vector add double word + s39_vah, // vector add halfword + s39_vap, // vector add decimal + s39_vaq, // vector add quad word + s39_vavg, // vector average + s39_vavgb, // vector average byte + s39_vavgf, // vector average word + s39_vavgg, // vector average double word + s39_vavgh, // vector average half word + s39_vavgl, // vector average logical + s39_vavglb, // vector average logical byte + s39_vavglf, // vector average logical word + s39_vavglg, // vector average logical double word + s39_vavglh, // vector average logical half word + s39_vbperm, // vector bit permute + s39_vcdg, // vector fp convert from fixed 64 bit + s39_vcdgb, // vector fp convert from fixed 64 bit + s39_vcdlg, // vector fp convert from logical 64 bit + s39_vcdlgb, // vector fp convert from logical 64 bit + s39_vcefb, // + s39_vcelfb, // + s39_vceq, // vector compare equal + s39_vceqb, // vector compare equal byte + s39_vceqbs, // vector compare equal byte + s39_vceqf, // vector compare equal word + s39_vceqfs, // vector compare equal word + s39_vceqg, // vector compare equal double word + s39_vceqgs, // vector compare equal double word + s39_vceqh, // vector compare equal half word + s39_vceqhs, // vector compare equal half word + s39_vcfeb, // + s39_vcfpl, // + s39_vcfps, // + s39_vcgd, // vector fp convert to fixed 64 bit + s39_vcgdb, // vector fp convert to fixed 64 bit + s39_vch, // vector compare high + s39_vchb, // vector compare high byte + s39_vchbs, // vector compare high byte + s39_vchf, // vector compare high word + s39_vchfs, // vector compare high word + s39_vchg, // vector compare high double word + s39_vchgs, // vector compare high double word + s39_vchh, // vector compare high half word + s39_vchhs, // vector compare high half word + s39_vchl, // vector compare high logical + s39_vchlb, // vector compare high logical byte + s39_vchlbs, // vector compare high logical byte + s39_vchlf, // vector compare high logical word + s39_vchlfs, // vector compare high logical word + s39_vchlg, // vector compare high logical double word + s39_vchlgs, // vector compare high logical double word + s39_vchlh, // vector compare high logical half word + s39_vchlhs, // vector compare high logical half word + s39_vcksm, // vector checksum + s39_vclfeb, // + s39_vclfp, // + s39_vclgd, // vector fp convert to logical 64 bit + s39_vclgdb, // vector fp convert to logical 64 bit + s39_vclz, // vector count leading zeros + s39_vclzb, // vector count leading zeros byte + s39_vclzf, // vector count leading zeros word + s39_vclzg, // vector count leading zeros doubleword + s39_vclzh, // vector count leading zeros halfword + s39_vcp, // vector compare decimal + s39_vcsfp, // + s39_vctz, // vector count trailing zeros + s39_vctzb, // vector count trailing zeros byte + s39_vctzf, // vector count trailing zeros word + s39_vctzg, // vector count trailing zeros doubleword + s39_vctzh, // vector count trailing zeros halfword + s39_vcvb, // vector convert to binary + s39_vcvbg, // vector convert to binary + s39_vcvd, // vector convert to decimal + s39_vcvdg, // vector convert to decimal + s39_vdp, // vector divide decimal + s39_vec, // vector element compare + s39_vecb, // vector element compare byte + s39_vecf, // vector element compare word + s39_vecg, // vector element compare double word + s39_vech, // vector element compare half word + s39_vecl, // vector element compare logical + s39_veclb, // vector element compare logical byte + s39_veclf, // vector element compare logical word + s39_veclg, // vector element compare logical double word + s39_veclh, // vector element compare logical half word + s39_verim, // vector element rotate and insert under mask + s39_verimb, // vector element rotate and insert under mask byte + s39_verimf, // vector element rotate and insert under mask word + s39_verimg, // vector element rotate and insert under mask doubleword + s39_verimh, // vector element rotate and insert under mask halfword + s39_verll, // vector element rotate left logical + s39_verllb, // vector element rotate left logical byte + s39_verllf, // vector element rotate left logical word + s39_verllg, // vector element rotate left logical doubleword + s39_verllh, // vector element rotate left logical halfword + s39_verllv, // vector element rotate left logical + s39_verllvb, // vector element rotate left logical byte + s39_verllvf, // vector element rotate left logical word + s39_verllvg, // vector element rotate left logical doubleword + s39_verllvh, // vector element rotate left logical halfword + s39_vesl, // vector element shift left + s39_veslb, // vector element shift left byte + s39_veslf, // vector element shift left word + s39_veslg, // vector element shift left doubleword + s39_veslh, // vector element shift left halfword + s39_veslv, // vector element shift left + s39_veslvb, // vector element shift left byte + s39_veslvf, // vector element shift left word + s39_veslvg, // vector element shift left doubleword + s39_veslvh, // vector element shift left halfword + s39_vesra, // vector element shift right arithmetic + s39_vesrab, // vector element shift right arithmetic byte + s39_vesraf, // vector element shift right arithmetic word + s39_vesrag, // vector element shift right arithmetic doubleword + s39_vesrah, // vector element shift right arithmetic halfword + s39_vesrav, // vector element shift right arithmetic + s39_vesravb, // vector element shift right arithmetic byte + s39_vesravf, // vector element shift right arithmetic word + s39_vesravg, // vector element shift right arithmetic doubleword + s39_vesravh, // vector element shift right arithmetic halfword + s39_vesrl, // vector element shift right logical + s39_vesrlb, // vector element shift right logical byte + s39_vesrlf, // vector element shift right logical word + s39_vesrlg, // vector element shift right logical doubleword + s39_vesrlh, // vector element shift right logical halfword + s39_vesrlv, // vector element shift right logical + s39_vesrlvb, // vector element shift right logical byte + s39_vesrlvf, // vector element shift right logical word + s39_vesrlvg, // vector element shift right logical doubleword + s39_vesrlvh, // vector element shift right logical halfword + s39_vfa, // vector fp add + s39_vfadb, // vector fp add long + s39_vfae, // vector find any element equal + s39_vfaeb, // vector find any element equal byte + s39_vfaebs, // vector find any element equal + s39_vfaef, // vector find any element equal word + s39_vfaefs, // vector find any element equal + s39_vfaeh, // vector find any element equal halfword + s39_vfaehs, // vector find any element equal + s39_vfaezb, // vector find any element equal + s39_vfaezbs, // vector find any element equal + s39_vfaezf, // vector find any element equal + s39_vfaezfs, // vector find any element equal + s39_vfaezh, // vector find any element equal + s39_vfaezhs, // vector find any element equal + s39_vfasb, // vector fp add short + s39_vfce, // vector fp compare equal + s39_vfcedb, // vector fp compare equal long + s39_vfcedbs, // vector fp compare equal long + s39_vfcesb, // vector fp compare equal short + s39_vfcesbs, // vector fp compare equal short + s39_vfch, // vector fp compare high + s39_vfchdb, // vector fp compare high long + s39_vfchdbs, // vector fp compare high long + s39_vfche, // vector fp compare high or equal + s39_vfchedb, // vector fp compare high or equal long + s39_vfchedbs, // vector fp compare high or equal long + s39_vfchesb, // vector fp compare high or equal short + s39_vfchesbs, // vector fp compare high or equal short + s39_vfchsb, // vector fp compare high short + s39_vfchsbs, // vector fp compare high short + s39_vfd, // vector fp divide + s39_vfddb, // vector fp divide long + s39_vfdsb, // vector fp divide short + s39_vfee, // vector find element equal + s39_vfeeb, // vector find element equal byte + s39_vfeebs, // vector find element equal byte + s39_vfeef, // vector find element equal word + s39_vfeefs, // vector find element equal word + s39_vfeeh, // vector find element equal halfword + s39_vfeehs, // vector find element equal halfword + s39_vfeezb, // vector find element equal byte + s39_vfeezbs, // vector find element equal byte + s39_vfeezf, // vector find element equal word + s39_vfeezfs, // vector find element equal word + s39_vfeezh, // vector find element equal halfword + s39_vfeezhs, // vector find element equal halfword + s39_vfene, // vector find element not equal + s39_vfeneb, // vector find element not equal byte + s39_vfenebs, // vector find element not equal byte + s39_vfenef, // vector find element not equal word + s39_vfenefs, // vector find element not equal word + s39_vfeneh, // vector find element not equal halfword + s39_vfenehs, // vector find element not equal halfword + s39_vfenezb, // vector find element not equal byte + s39_vfenezbs, // vector find element not equal byte + s39_vfenezf, // vector find element not equal word + s39_vfenezfs, // vector find element not equal word + s39_vfenezh, // vector find element not equal halfword + s39_vfenezhs, // vector find element not equal halfword + s39_vfi, // vector load fp integer + s39_vfidb, // vector load fp integer long + s39_vfisb, // vector load fp integer short + s39_vfkedb, // vector fp compare and signal equal long + s39_vfkedbs, // vector fp compare and signal equal long + s39_vfkesb, // vector fp compare and signal equal short + s39_vfkesbs, // vector fp compare and signal equal short + s39_vfkhdb, // vector fp compare and signal high long + s39_vfkhdbs, // vector fp compare and signal high long + s39_vfkhedb, // vector fp compare and signal high or equal long + s39_vfkhedbs, // vector fp compare and signal high or equal long + s39_vfkhesb, // vector fp compare and signal high or equal short + s39_vfkhesbs, // vector fp compare and signal high or equal short + s39_vfkhsb, // vector fp compare and signal high short + s39_vfkhsbs, // vector fp compare and signal high short + s39_vflcdb, // vector fp perform sign operation long + s39_vflcsb, // vector fp perform sign operation short + s39_vfll, // vector fp load lengthened + s39_vflls, // vector fp load lengthened + s39_vflndb, // vector fp perform sign operation long + s39_vflnsb, // vector fp perform sign operation short + s39_vflpdb, // vector fp perform sign operation long + s39_vflpsb, // vector fp perform sign operation short + s39_vflr, // vector fp load rounded + s39_vflrd, // vector fp load rounded long + s39_vfm, // vector fp multiply + s39_vfma, // vector fp multiply and add + s39_vfmadb, // vector fp multiply and add long + s39_vfmasb, // vector fp multiply and add short + s39_vfmax, // vector fp maximum + s39_vfmaxdb, // vector fp maximum long + s39_vfmaxsb, // vector fp maximum short + s39_vfmdb, // vector fp multiply long + s39_vfmin, // vector fp minimum + s39_vfmindb, // vector fp minimum long + s39_vfminsb, // vector fp minimum short + s39_vfms, // vector fp multiply and subtract + s39_vfmsb, // vector fp multiply short + s39_vfmsdb, // vector fp multiply and subtract long + s39_vfmssb, // vector fp multiply and subtract short + s39_vfnma, // vector fp negative multiply and add + s39_vfnmadb, // vector fp negative multiply and add long + s39_vfnmasb, // vector fp negative multiply and add short + s39_vfnms, // vector fp negative multiply and subtract + s39_vfnmsdb, // vector fp negative multiply and subtract long + s39_vfnmssb, // vector fp negative multiply and subtract short + s39_vfpso, // vector fp perform sign operation + s39_vfpsodb, // vector fp perform sign operation long + s39_vfpsosb, // vector fp perform sign operation short + s39_vfs, // vector fp subtract + s39_vfsdb, // vector fp subtract long + s39_vfsq, // vector fp square root + s39_vfsqdb, // vector fp square root long + s39_vfsqsb, // vector fp square root short + s39_vfssb, // vector fp subtract short + s39_vftci, // vector fp test data class immediate + s39_vftcidb, // vector fp test data class immediate + s39_vftcisb, // vector fp test data class immediate short + s39_vgbm, // vector generate byte mask + s39_vgef, // vector gather element (32) + s39_vgeg, // vector gather element (64) + s39_vgfm, // vector galois field multiply sum + s39_vgfma, // vector galois field multiply sum and accumulate + s39_vgfmab, // vector galois field multiply sum and accumulate byte + s39_vgfmaf, // vector galois field multiply sum and accumulate word + s39_vgfmag, // vector galois field multiply sum and accumulate doubleword + s39_vgfmah, // vector galois field multiply sum and accumulate halfword + s39_vgfmb, // vector galois field multiply sum byte + s39_vgfmf, // vector galois field multiply sum word + s39_vgfmg, // vector galois field multiply sum doubleword + s39_vgfmh, // vector galois field multiply sum halfword + s39_vgm, // vector generate mask + s39_vgmb, // vector generate mask byte + s39_vgmf, // vector generate mask word + s39_vgmg, // vector generate mask double word + s39_vgmh, // vector generate mask halfword + s39_vistr, // vector isolate string + s39_vistrb, // vector isolate string byte + s39_vistrbs, // vector isolate string byte + s39_vistrf, // vector isolate string word + s39_vistrfs, // vector isolate string word + s39_vistrh, // vector isolate string halfword + s39_vistrhs, // vector isolate string halfword + s39_vl, // vector load + s39_vlbb, // vector load to block boundary + s39_vlbr, // + s39_vlbrf, // + s39_vlbrg, // + s39_vlbrh, // + s39_vlbrq, // + s39_vlbrrep, // + s39_vlbrrepf, // + s39_vlbrrepg, // + s39_vlbrreph, // + s39_vlc, // vector load complement + s39_vlcb, // vector load complement byte + s39_vlcf, // vector load complement word + s39_vlcg, // vector load complement doubleword + s39_vlch, // vector load complement halfword + s39_vlde, // vector fp load lengthened + s39_vldeb, // vector fp load lengthened short to long + s39_vleb, // vector load byte element + s39_vlebrf, // + s39_vlebrg, // + s39_vlebrh, // + s39_vled, // vector fp load rounded + s39_vledb, // vector fp load rounded long to short + s39_vlef, // vector load element (32) + s39_vleg, // vector load element (64) + s39_vleh, // vector load element (16) + s39_vleib, // vector load element immediate (8) + s39_vleif, // vector load element immediate (32) + s39_vleig, // vector load element immediate (64) + s39_vleih, // vector load element immediate (16) + s39_vler, // + s39_vlerf, // + s39_vlerg, // + s39_vlerh, // + s39_vlgv, // vector load gr from vr element + s39_vlgvb, // vector load gr from vr byte element + s39_vlgvf, // vector load gr from vr word element + s39_vlgvg, // vector load gr from vr double word element + s39_vlgvh, // vector load gr from vr halfword element + s39_vlip, // vector load immediate decimal + s39_vll, // vector load with length + s39_vllebrz, // + s39_vllebrze, // + s39_vllebrzf, // + s39_vllebrzg, // + s39_vllebrzh, // + s39_vllez, // vector load logical element and zero + s39_vllezb, // vector load logical byte element and zero + s39_vllezf, // vector load logical word element and zero + s39_vllezg, // vector load logical double word element and zero + s39_vllezh, // vector load logical halfword element and zero + s39_vllezlf, // vector load logical word element and zero - left aligned + s39_vlm, // vector load multiple + s39_vlp, // vector load positive + s39_vlpb, // vector load positive byte + s39_vlpf, // vector load positive word + s39_vlpg, // vector load positive doubleword + s39_vlph, // vector load positive halfword + s39_vlr, // vector load + s39_vlrep, // vector load and replicate + s39_vlrepb, // vector load and replicate byte elements + s39_vlrepf, // vector load and replicate word elements + s39_vlrepg, // vector load and replicate double word elements + s39_vlreph, // vector load and replicate halfword elements + s39_vlrl, // vector load rightmost with immediate length + s39_vlrlr, // vector load rightmost with immediate length + s39_vlvg, // vector load VR element from GR + s39_vlvgb, // vector load VR byte element from GR + s39_vlvgf, // vector load VR word element from GR + s39_vlvgg, // vector load VR double word element from GR + s39_vlvgh, // vector load VR halfword element from GR + s39_vlvgp, // vector load VR from GRs disjoint + s39_vmae, // vector multiply and add even + s39_vmaeb, // vector multiply and add even byte + s39_vmaef, // vector multiply and add even word + s39_vmaeh, // vector multiply and add even halfword + s39_vmah, // vector multiply and add high + s39_vmahb, // vector multiply and add high byte + s39_vmahf, // vector multiply and add high word + s39_vmahh, // vector multiply and add high halfword + s39_vmal, // vector multiply and add low + s39_vmalb, // vector multiply and add low byte + s39_vmale, // vector multiply and add logical even + s39_vmaleb, // vector multiply and add logical even byte + s39_vmalef, // vector multiply and add logical even word + s39_vmaleh, // vector multiply and add logical even halfword + s39_vmalf, // vector multiply and add low word + s39_vmalh, // vector multiply and add logical high + s39_vmalhb, // vector multiply and add logical high byte + s39_vmalhf, // vector multiply and add logical high word + s39_vmalhh, // vector multiply and add logical high halfword + s39_vmalhw, // vector multiply and add low halfword + s39_vmalo, // vector multiply and add logical odd + s39_vmalob, // vector multiply and add logical odd byte + s39_vmalof, // vector multiply and add logical odd word + s39_vmaloh, // vector multiply and add logical odd halfword + s39_vmao, // vector multiply and add odd + s39_vmaob, // vector multiply and add odd byte + s39_vmaof, // vector multiply and add odd word + s39_vmaoh, // vector multiply and add odd halfword + s39_vme, // vector multiply even + s39_vmeb, // vector multiply even byte + s39_vmef, // vector multiply even word + s39_vmeh, // vector multiply even halfword + s39_vmh, // vector multiply high + s39_vmhb, // vector multiply high byte + s39_vmhf, // vector multiply high word + s39_vmhh, // vector multiply high halfword + s39_vml, // vector multiply low + s39_vmlb, // vector multiply low byte + s39_vmle, // vector multiply logical even + s39_vmleb, // vector multiply logical even byte + s39_vmlef, // vector multiply logical even word + s39_vmleh, // vector multiply logical even halfword + s39_vmlf, // vector multiply low word + s39_vmlh, // vector multiply logical high + s39_vmlhb, // vector multiply logical high byte + s39_vmlhf, // vector multiply logical high word + s39_vmlhh, // vector multiply logical high halfword + s39_vmlhw, // vector multiply low halfword + s39_vmlo, // vector multiply logical odd + s39_vmlob, // vector multiply logical odd byte + s39_vmlof, // vector multiply logical odd word + s39_vmloh, // vector multiply logical odd halfword + s39_vmn, // vector minimum + s39_vmnb, // vector minimum byte + s39_vmnf, // vector minimum word + s39_vmng, // vector minimum doubleword + s39_vmnh, // vector minimum halfword + s39_vmnl, // vector minimum logical + s39_vmnlb, // vector minimum logical byte + s39_vmnlf, // vector minimum logical word + s39_vmnlg, // vector minimum logical doubleword + s39_vmnlh, // vector minimum logical halfword + s39_vmo, // vector multiply odd + s39_vmob, // vector multiply odd byte + s39_vmof, // vector multiply odd word + s39_vmoh, // vector multiply odd halfword + s39_vmp, // vector multiply decimal + s39_vmrh, // vector merge high + s39_vmrhb, // vector merge high byte + s39_vmrhf, // vector merge high word + s39_vmrhg, // vector merge high double word + s39_vmrhh, // vector merge high halfword + s39_vmrl, // vector merge low + s39_vmrlb, // vector merge low byte + s39_vmrlf, // vector merge low word + s39_vmrlg, // vector merge low double word + s39_vmrlh, // vector merge low halfword + s39_vmsl, // vector multiply sum logical + s39_vmslg, // vector multiply sum logical double word + s39_vmsp, // vector multiply and shift decimal + s39_vmx, // vector maximum + s39_vmxb, // vector maximum byte + s39_vmxf, // vector maximum word + s39_vmxg, // vector maximum doubleword + s39_vmxh, // vector maximum halfword + s39_vmxl, // vector maximum logical + s39_vmxlb, // vector maximum logical byte + s39_vmxlf, // vector maximum logical word + s39_vmxlg, // vector maximum logical doubleword + s39_vmxlh, // vector maximum logical halfword + s39_vn, // vector and + s39_vnc, // vector and with complement + s39_vnn, // vector nand + s39_vno, // vector nor + s39_vnot, // vector not + s39_vnx, // vector not exclusive or + s39_vo, // vector or + s39_voc, // vector or with complement + s39_vone, // vector set to ones + s39_vpdi, // vector permute double word immediate + s39_vperm, // vector permute + s39_vpk, // vector pack + s39_vpkf, // vector pack word + s39_vpkg, // vector pack double word + s39_vpkh, // vector pack halfword + s39_vpkls, // vector pack logical saturate + s39_vpklsf, // vector pack logical saturate word + s39_vpklsfs, // vector pack logical saturate word + s39_vpklsg, // vector pack logical saturate double word + s39_vpklsgs, // vector pack logical saturate double word + s39_vpklsh, // vector pack logical saturate halfword + s39_vpklshs, // vector pack logical saturate halfword + s39_vpks, // vector pack saturate + s39_vpksf, // vector pack saturate word + s39_vpksfs, // vector pack saturate word + s39_vpksg, // vector pack saturate double word + s39_vpksgs, // vector pack saturate double word + s39_vpksh, // vector pack saturate halfword + s39_vpkshs, // vector pack saturate halfword + s39_vpkz, // vector pack zoned + s39_vpopct, // vector population count + s39_vpopctb, // vector population count byte + s39_vpopctf, // vector population count word + s39_vpopctg, // vector population count double word + s39_vpopcth, // vector population count halfword + s39_vpsop, // vector perform sign operation decimal + s39_vrep, // vector replicate + s39_vrepb, // vector replicate byte + s39_vrepf, // vector replicate word + s39_vrepg, // vector replicate double word + s39_vreph, // vector replicate halfword + s39_vrepi, // vector replicate immediate + s39_vrepib, // vector replicate immediate byte + s39_vrepif, // vector replicate immediate word + s39_vrepig, // vector replicate immediate double word + s39_vrepih, // vector replicate immediate halfword + s39_vrp, // vector remainder decimal + s39_vs, // vector subtract + s39_vsb, // vector subtract byte + s39_vsbcbi, // vector subtract with borrow compute borrow indication + s39_vsbcbiq, // vector subtract with borrow compute borrow indication quadword + s39_vsbi, // vector subtract with borrow indication + s39_vsbiq, // vector subtract with borrow indication quadword + s39_vscbi, // vector subtract compute borrow indication + s39_vscbib, // vector subtract compute borrow indication byte + s39_vscbif, // vector subtract compute borrow indication word + s39_vscbig, // vector subtract compute borrow indication doubleword + s39_vscbih, // vector subtract compute borrow indication halfword + s39_vscbiq, // vector subtract compute borrow indication quadword + s39_vscef, // vector scatter element (32) + s39_vsceg, // vector scatter element (64) + s39_vsdp, // vector shift and divide decimal + s39_vseg, // vector sign extend to double word + s39_vsegb, // vector sign extend byte to double word + s39_vsegf, // vector sign extend word to double word + s39_vsegh, // vector sign extend halfword to double word + s39_vsel, // vector select + s39_vsf, // vector subtract word + s39_vsg, // vector subtract doubleword + s39_vsh, // vector subtract halfword + s39_vsl, // vector shift left + s39_vslb, // vector shift left by byte + s39_vsld, // + s39_vsldb, // vector shift left double by byte + s39_vsp, // vector subtract decimal + s39_vsq, // vector subtract quadword + s39_vsra, // vector shift right arithmetic + s39_vsrab, // vector shift right arithmetic by byte + s39_vsrd, // + s39_vsrl, // vector shift right logical + s39_vsrlb, // vector shift right logical by byte + s39_vsrp, // vector shift and round decimal + s39_vst, // vector store + s39_vstbr, // + s39_vstbrf, // + s39_vstbrg, // + s39_vstbrh, // + s39_vstbrq, // + s39_vsteb, // vector store element (8) + s39_vstebrf, // + s39_vstebrg, // + s39_vstebrh, // + s39_vstef, // vector store element (32) + s39_vsteg, // vector store element (64) + s39_vsteh, // vector store element (16) + s39_vster, // + s39_vsterf, // + s39_vsterg, // + s39_vsterh, // + s39_vstl, // vector store with length + s39_vstm, // vector store multiple + s39_vstrc, // vector string range compare + s39_vstrcb, // vector string range compare byte + s39_vstrcbs, // vector string range compare byte + s39_vstrcf, // vector string range compare word + s39_vstrcfs, // vector string range compare word + s39_vstrch, // vector string range compare halfword + s39_vstrchs, // vector string range compare halfword + s39_vstrczb, // vector string range compare byte + s39_vstrczbs, // vector string range compare byte + s39_vstrczf, // vector string range compare word + s39_vstrczfs, // vector string range compare word + s39_vstrczh, // vector string range compare halfword + s39_vstrczhs, // vector string range compare halfword + s39_vstrl, // vector store rightmost with length + s39_vstrlr, // vector store rightmost with length + s39_vstrs, // + s39_vstrsb, // + s39_vstrsf, // + s39_vstrsh, // + s39_vstrszb, // + s39_vstrszf, // + s39_vstrszh, // + s39_vsum, // vector sum across word + s39_vsumb, // vector sum across word - byte elements + s39_vsumg, // vector sum across doubleword + s39_vsumgf, // vector sum across doubleword - word + s39_vsumgh, // vector sum across doubleword - halfword + s39_vsumh, // vector sum across word - halfword elements + s39_vsumq, // vector sum across quadword + s39_vsumqf, // vector sum across quadword - word elements + s39_vsumqg, // vector sum across quadword - doubleword elements + s39_vtm, // vector test under mask + s39_vtp, // vector test decimal + s39_vuph, // vector unpack high + s39_vuphb, // vector unpack high byte + s39_vuphf, // vector unpack high word + s39_vuphh, // vector unpack high halfword + s39_vupkz, // vector unpack zoned + s39_vupl, // vector unpack low + s39_vuplb, // vector unpack low byte + s39_vuplf, // vector unpack low word + s39_vuplh, // vector unpack logical high + s39_vuplhb, // vector unpack logical high byte + s39_vuplhf, // vector unpack logical high word + s39_vuplhh, // vector unpack logical high halfword + s39_vuplhw, // vector unpack low halfword + s39_vupll, // vector unpack logical low + s39_vupllb, // vector unpack logical low byte + s39_vupllf, // vector unpack logical low word + s39_vupllh, // vector unpack logical low halfword + s39_vzero, // vector set to zero + s39_wcdgb, // vector fp convert from fixed 64 bit + s39_wcdlgb, // vector fp convert from logical 64 bit + s39_wcefb, // + s39_wcelfb, // + s39_wcfeb, // + s39_wcgdb, // vector fp convert to fixed 64 bit + s39_wclfeb, // + s39_wclgdb, // vector fp convert to logical 64 bit + s39_wfadb, // vector fp add long + s39_wfasb, // scalar vector fp add scalar short + s39_wfaxb, // scalar vector fp add scalar extended + s39_wfc, // vector fp compare scalar + s39_wfcdb, // vector fp compare scalar long + s39_wfcedb, // vector fp compare equal long + s39_wfcedbs, // vector fp compare equal long + s39_wfcesb, // scalar vector fp compare equal scalar short + s39_wfcesbs, // scalar fp compare equal scalar short + s39_wfcexb, // scalar vector fp compare equal scalar extended + s39_wfcexbs, // scalar vector fp compare equal scalar extended + s39_wfchdb, // vector fp compare high long + s39_wfchdbs, // vector fp compare high long + s39_wfchedb, // vector fp compare high or equal long + s39_wfchedbs, // vector fp compare high or equal long + s39_wfchesb, // scalar vector fp compare high or equal scalar short + s39_wfchesbs, // scalar vector fp compare high or equal scalar short + s39_wfchexb, // scalar vector fp compare high or equal scalar extended + s39_wfchexbs, // scalar vector fp compare high or equal scalar extended + s39_wfchsb, // scalar vector fp compare high scalar short + s39_wfchsbs, // scalar vector fp compare high scalar short + s39_wfchxb, // scalar vector fp compare high scalar extended + s39_wfchxbs, // scalar vector fp compare high scalar extended + s39_wfcsb, // scalar vector fp compare scalar short + s39_wfcxb, // scalar vector fp compare scalar extended + s39_wfddb, // vector fp divide long + s39_wfdsb, // scalar vector fp divide scalar short + s39_wfdxb, // scalar vector fp divide scalar extended + s39_wfidb, // vector load fp integer long + s39_wfisb, // scalar vector load fp integer scalar short + s39_wfixb, // scalar vector load fp integer scalar extended + s39_wfk, // vector fp compare and signal scalar + s39_wfkdb, // vector fp compare and signal scalar long + s39_wfkedb, // vector fp compare and signal equal long + s39_wfkedbs, // vector fp compare and signal equal long + s39_wfkesb, // scalar vector fp compare and signal equal scalar short + s39_wfkesbs, // scalar fp compare and signal equal scalar short + s39_wfkexb, // scalar vector fp compare and signal equal scalar extended + s39_wfkexbs, // scalar vector fp compare and signal equal scalar extended + s39_wfkhdb, // vector fp compare and signal high long + s39_wfkhdbs, // vector fp compare and signal high long + s39_wfkhedb, // vector fp compare and signal high or equal long + s39_wfkhedbs, // vector fp compare and signal high or equal long + s39_wfkhesb, // scalar vector fp compare and signal high or equal scalar short + s39_wfkhesbs, // scalar vector fp compare and signal high or equal scalar short + s39_wfkhexb, // scalar vector fp compare and signal high or equal scalar extended + s39_wfkhexbs, // scalar vector fp compare and signal high or equal scalar extended + s39_wfkhsb, // scalar vector fp compare and signal high scalar short + s39_wfkhsbs, // scalar vector fp compare and signal high scalar short + s39_wfkhxb, // scalar vector fp compare and signal high scalar extended + s39_wfkhxbs, // scalar vector fp compare and signal high scalar extended + s39_wfksb, // scalar vector fp compare and signal scalar short + s39_wfkxb, // scalar vector fp compare and signal scalar extended + s39_wflcdb, // vector fp perform sign operation long + s39_wflcsb, // scalar vector fp perform sign operation scalar short + s39_wflcxb, // scalar vector fp perform sign operation scalar extended + s39_wflld, // scalar vector fp load lengthened long + s39_wflls, // scalar vector fp load lengthened short + s39_wflndb, // vector fp perform sign operation long + s39_wflnsb, // scalar vector fp perform sign operation scalar short + s39_wflnxb, // scalar vector fp perform sign operation scalar extended + s39_wflpdb, // vector fp perform sign operation long + s39_wflpsb, // scalar vector fp perform sign operation scalar short + s39_wflpxb, // scalar vector fp perform sign operation scalar extended + s39_wflrd, // scalar vector fp load rounded long + s39_wflrx, // scalar vector fp load rounded extended + s39_wfmadb, // vector fp multiply and add long + s39_wfmasb, // scalar vector fp multiply and add scalar short + s39_wfmaxb, // scalar vector fp multiply and add scalar extended + s39_wfmaxdb, // scalar fp maximum scalar long + s39_wfmaxsb, // scalar fp maximum scalar short + s39_wfmaxxb, // scalar fp maximum scalar extended + s39_wfmdb, // vector fp multiply long + s39_wfmindb, // scalar fp minimum scalar long + s39_wfminsb, // scalar fp minimum scalar short + s39_wfminxb, // scalar fp minimum scalar extended + s39_wfmsb, // scalar vector fp multiply scalar short + s39_wfmsdb, // vector fp multiply and subtract long + s39_wfmssb, // scalar vector fp multiply and subtract scalar short + s39_wfmsxb, // scalar vector fp multiply and subtract scalar extended + s39_wfmxb, // scalar vector fp multiply scalar extended + s39_wfnmadb, // scalar vector fp negative multiply and add scalar long + s39_wfnmasb, // scalar vector fp negative multiply and add scalar short + s39_wfnmaxb, // scalar vector fp negative multiply and add scalar extended + s39_wfnmsdb, // scalar vector fp negative multiply and subtract scalar long + s39_wfnmssb, // scalar vector fp negative multiply and subtract scalar short + s39_wfnmsxb, // scalar vector fp negative multiply and subtract scalar extended + s39_wfpsodb, // vector fp perform sign operation long + s39_wfpsosb, // scalar vector fp perform sign operation scalar short + s39_wfpsoxb, // scalar vector fp perform sign operation scalar extended + s39_wfsdb, // vector fp subtract long + s39_wfsqdb, // vector fp square root long + s39_wfsqsb, // scalar vector fp square root scalar short + s39_wfsqxb, // scalar vector fp square root scalar extended + s39_wfssb, // scalar vector fp subtract scalar short + s39_wfsxb, // scalar vector fp subtract scalar extended + s39_wftcidb, // vector fp test data class immediate + s39_wftcisb, // scalar vector fp test data class immediate scalar short + s39_wftcixb, // scalar vector fp test data class immediate scalar extended + s39_wldeb, // vector fp load lengthened short to long + s39_wledb, // vector fp load rounded long to short + s39_x, // exclusive or (32) + s39_xc, // exclusive or (character) + s39_xg, // exclusive or (64) + s39_xgr, // exclusive or (64) + s39_xgrk, // exclusive or (64) + s39_xi, // exclusive or (immediate) + s39_xihf, // exclusive or immediate (high) + s39_xilf, // exclusive or immediate (low) + s39_xiy, // exclusive or immediate (immediate) + s39_xr, // exclusive or (32) + s39_xrk, // exclusive or (32) + s39_xsch, // cancel subchannel + s39_xy, // exclusive or with long offset + s39_zap, // zero and add + s39_vx, // vector exclusive or + s39_last, +}; + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Risc-V module + * + */ + + + +enum +{ + RISCV_null = 0, // Unknown Operation + + // Set 32 bits + // I(nteger) extension + RISCV_lui, // Load Upper Immediate + RISCV_auipc, // Add Upper Immediate to pc + RISCV_jal, // Jump and link + RISCV_jalr, // Jump register rs1 & write pc +2 in rs1 + RISCV_beq, // Branch on equal + RISCV_bne, // Branch not equal + RISCV_blt, // Branch less than + RISCV_bge, // Branch greater or equal + RISCV_bltu, // Branch less than unsigned + RISCV_bgeu, // Branch greater or equal unsigned + RISCV_lb, // Load byte + RISCV_lh, // Load halfword + RISCV_lw, // Load word + RISCV_lbu, // Load byte unsigned + RISCV_lhu, // Load halfword unsigned + RISCV_sb, // Store byte + RISCV_sh, // Store halfword + RISCV_sw, // Store word + RISCV_addi, // Add immediate + RISCV_slti, // Set less than immediate + RISCV_sltiu, // Set less than immediate unsigned + RISCV_xori, // Xor immediate + RISCV_ori, // Or immediate + RISCV_andi, // And Immediate + RISCV_slli, // Shift left logical immediate + RISCV_srli, // Shift right logical immediate + RISCV_srai, // Shift right arithmetical immediate + RISCV_add, // Add integer + RISCV_sub, // Substract integer + RISCV_sll, // Shift left logical + RISCV_slt, // Set Less Than + RISCV_sltu, // Set Less Than unsigned + RISCV_xor, // eXclusive Or + RISCV_srl, // Shift right logical + RISCV_sra, // Shift right arithmetical + RISCV_or, // Or + RISCV_and, // And + RISCV_fence, // Fence + RISCV_ecall, // Ecall + RISCV_ebreak, // Ebreak + RISCV_uret, // User lvl return + RISCV_sret, // Supervisor lvl return + RISCV_mret, // Machine lvl return + RISCV_wfi, // Wait for interrupt + RISCV_sfence, // Supervisor fence + RISCV_hfenceb, // Hypervisor fence b + RISCV_hfenceg, // Hypervisor fence g + // Set 64 bits + // Integer extension + RISCV_lwu, // Load word unsigned + RISCV_ld, // Load double + RISCV_sd, // Store double + RISCV_addiw, // Add immediate word + RISCV_slliw, // Shift left logical immediate word + RISCV_srliw, // Shift right logical immediate word + RISCV_sraiw, // Shift right arithmetical immediate word + RISCV_addw, // Add integer word + RISCV_subw, // Substract integer word + RISCV_sllw, // Shift left logical word + RISCV_sltw, // Set Less Than word + RISCV_srlw, // Shift right logical word + RISCV_sraw, // Shift right arithmetical word + // Zifencei Standard extension + RISCV_fencei, // Fence immediate + // Zicsr Standard extension + RISCV_csrrw, // Atomic Read Write CSR + RISCV_csrrs, // Atomic Read and Set bit CSR + RISCV_csrrc, // Atomic Read and clear bit CSR + RISCV_csrrwi, // Atomic Read Write CSR immediate + RISCV_csrrsi, // Atomic Read and Set bit CSR immediate + RISCV_csrrci, // Atomic Read and clear bit CSR immediate + // M(ultiplication and divison for integer) extension + RISCV_mul, // Multiplication + RISCV_mulh, // Multiplication half (signed signed) + RISCV_mulhsu, // Multiplication half (signed unsigned) + RISCV_mulhu, // Multiplication half (unsigned unsigned) + RISCV_div, // Division + RISCV_divu, // Division unsigned + RISCV_rem, // Remainder of div + RISCV_remu, // Remainder of div unsigned + // 64b M(ultiplication and divison for integer) extension + RISCV_mulw, // Multiplication word + RISCV_divw, // Division word + RISCV_divuw, // Division unsigned word + RISCV_remw, // Remainder of div word + RISCV_remuw, // Remainder of div unsigned word + // A(tomic) operation standtard extension + RISCV_lr, // Load reserved + RISCV_sc, // Store conditional + RISCV_amoswap, // Atomic memory operation swap + RISCV_amoadd, // Atomic memory operation add + RISCV_amoxor, // Atomic memory operation xop + RISCV_amoand, // Atomic memory operation and + RISCV_amoor, // Atomic memory operation or + RISCV_amomin, // Atomic memory operation min + RISCV_amomax, // Atomic memory operation max + RISCV_amominu, // Atomic memory operation min unsigned + RISCV_amomaxu, // Atomic memory operation max unsigned + // simple precision F(loat) instruction extension + RISCV_flw, // Load word (32b) + RISCV_fsw, // Store word (32b) + RISCV_fmadd, // Multiply then add + RISCV_fmsub, // Multiply then substract + RISCV_fnmsub, // Multiply then negate then substract + RISCV_fnmadd, // Multiply then negate then add + RISCV_fadd, // Float addition + RISCV_fsub, // Float substraction + RISCV_fmul, // Float multiplication + RISCV_fdiv, // Float division + RISCV_fsqrt, // Float square root + RISCV_fsgnj, // Float sign injection + RISCV_fsgnjn, // Float sign injection negate + RISCV_fsgnjx, // Float sign injection xor between operands + RISCV_fmin, // Float minimum + RISCV_fmax, // Float maximum + RISCV_fcvtf2f, // F2F conve + RISCV_fcvtf2i, // F2I conve + RISCV_fcvti2f, // I2F conve + RISCV_fmv, // Mv + RISCV_feq, // Float equal + RISCV_flt, // Float less than + RISCV_fle, // Float less or equal than + RISCV_fclass, // Classify the float + // 64b simple precision F(loat) instruction extension + // D(ouble) precision float instruction extension + RISCV_fld, // Load double (64b) + RISCV_fsd, // Store double (64b) + // 64b D(ouble) precision float instruction + // Q(uadruple) precision float instruction extension + RISCV_flq, // Load quadruple (128b) + RISCV_fsq, // Store quadruple (128b) + // 64b Q(uadruple) precision float extension + // pseudo insn + RISCV_nop, // No operation + RISCV_li, // Load Immediate + RISCV_mv, // Copy register + RISCV_not, // One's complement + RISCV_neg, // Two's complement + RISCV_negw, // Two's complement word + RISCV_sext, // Sign extend word + RISCV_seqz, // Set if = zero + RISCV_snez, // Set if != zero + RISCV_sltz, // Set if < zero + RISCV_sgtz, // Set if > zero + RISCV_fabs, // Float absolute value + RISCV_fneg, // Float negate + RISCV_beqz, // Branch == 0 + RISCV_bnez, // Branch != 0 + RISCV_blez, // Branch <= 0 + RISCV_bgez, // Branch >= 0 + RISCV_bltz, // Branch < 0 + RISCV_bgtz, // Branch > 0 + RISCV_j, // Jump + RISCV_jr, // Jump register + RISCV_ret, // Return + RISCV_rdinstret, // Read instructions-retired counter + RISCV_rdcycle, // Read cycle counter + RISCV_rdtime, // Read real-time clock + RISCV_rdinstreth, // Read instructions-retired counter Upper 32 bits + RISCV_rdcycleh, // Read cycle counter Upper 32 bits + RISCV_rdtimeh, // Read real-time clock Upper 32 bits + RISCV_csrr, // Read CSR + RISCV_csrw, // Write CSR + RISCV_csrs, // Set bit CSR + RISCV_csrc, // Clear bit + RISCV_csrwi, // Write CSR immediate + RISCV_csrsi, // Set bit CSR immediate + RISCV_csrci, // Clear bit CSR immediate + RISCV_frcsr, // Read FP control/status register + RISCV_fscsr, // Write/Swap FP control/status register + RISCV_frrm, // Read FP rounding mode + RISCV_fsrm, // Write/Swap FP rounding mode + RISCV_frflags, // Read FP exception flags + RISCV_fsflags, // Write/Swap FP exception flags + // Macro + RISCV_la, // Load Address macro + RISCV_call, // Call macro + RISCV_tail, // Tail macro + RISCV_jump, // Jump macro + RISCV_last +}; + +/* + * Interactive disassembler (IDA). + * Renesas Electronics RL78 module + * + */ + + + +enum +{ + RL78_null = 0, // Unknown Operation + RL78_subw, // Subtract Word - Word Data Subtraction + RL78_movw, // Move Word - Word Data Transfer + RL78_call, // Call - Subroutine Call + RL78_clrw, // Clear Word - Word Data Clear + RL78_addw, // Add Word - Word Data Addition + RL78_ret, // Return - Return from Subroutine + RL78_sel, // Select Register Bank + RL78_push, // Push + RL78_onew, // One Word - Word Data 0001 Set + RL78_incw, // Increment Word - Word Data Increment + RL78_cmpw, // Compare Word - Word Data Comparison + RL78_bnz, // Branch if Not Zero + RL78_clrb, // Clear byte - Byte Data Clear + RL78_and, // And - Logical Product of Byte Data + RL78_or, // Or - Logical Sum of Byte Data + RL78_br, // Branch - Unconditional Branch + RL78_pop, // Pop + RL78_cmp, // Compare - Byte Data Comparison + RL78_decw, // Decrement Word - Word Data Decrement + RL78_inc, // Increment - Byte Data Increment + RL78_bz, // Branch if Zero + RL78_sknz, // Skip if not Z - Skip with Zero Flag (Z = 0) + RL78_sknh, // Skip if not Higher than - Skip with numeric value comparison ((Z \/ CY) = 1) + RL78_skh, // Skip if Higher than - Skip with numeric value comparison ((Z \/ CY) = 0) + RL78_xor1, // Exclusive Or Single Bit - 1 Bit Data Exclusive Logical Sum + RL78_or1, // Or Single Bit - 1 Bit Data Logical Sum + RL78_and1, // And Single Bit - 1 Bit Data Logical Product + RL78_mov1, // Move Single Bit - 1 Bit Data Transfer + RL78_clr1, // Clear Single Bit (Carry Flag) - 1 Bit Data Clear + RL78_set1, // Set Single Bit (Carry Flag) - 1 Bit Data Set + RL78_not1, // Not Single Bit (Carry Flag) - 1 Bit Data Logical Negation + RL78_skc, // Skip if CY - Skip with Carry Flag (CY = 1) + RL78_sknc, // Skip if not CY - Skip with Carry Flag (CY = 0) + RL78_skz, // Skip if Z - Skip with Zero Flag (Z = 1) + RL78_mov, // Move - Byte Data Transfer + RL78_btclr, // Branch if True and Clear - Conditional Branch and Clear by Bit Test (Byte Data Bit =1) + RL78_bt, // Branch if True - Conditional Branch by Bit Test (Byte Data Bit = 1) + RL78_bf, // Branch if False - Conditional Branch by Bit Test (Byte Data Bit = 0) + RL78_shl, // Shift Left - Logical Shift to the Left + RL78_shr, // Shift Right - Logical Shift to the Right + RL78_sar, // Shift Arithmetic Right - Arithmetic Shift to the Right + RL78_shlw, // Shift Left Word - Logical Shift to the Left + RL78_shrw, // Shift Right Word - Logical Shift to the Right + RL78_sarw, // Shift Arithmetic Right Word - Arithmetic Shift to the Right + RL78_bc, // Branch if Carry - Conditional Branch with Carry Flag (CY = 1) + RL78_bnc, // Branch if Not Carry - Conditional Branch with Carry Flag (CY = 0) + RL78_bh, // Branch if Higher than - Conditional branch by numeric value comparison ((Z \/ CY) = 0) + RL78_bnh, // Branch if Not Higher than - Conditional branch by numeric value comparison ((Z \/ CY) = 1) + RL78_add, // Add - Byte Data Addition + RL78_addc, // Add with Carry - Addition of Byte Data with Carry + RL78_sub, // Subtract - Byte Data Subtraction + RL78_subc, // Subtract with Carry -Subtraction of Byte Data with Carry + RL78_xor, // Exclusive Or - Exclusive Logical Sum of Byte Data + RL78_xch, // Exchange - Byte Data Transfer + RL78_dec, // Decrement - Byte Data Decrement + RL78_rolwc, // Rotate Left word with Carry - Word Data Rotation to the Left with Carry + RL78_xchw, // Exchange Word - Word Data Transfer + RL78_cmps, // Compare - Byte Data Comparison + RL78_movs, // Move and change PSW - Byte Data Transfer and PSW Change + RL78_halt, // Halt - HALT Mode Set + RL78_cmp0, // Compare 00H - Byte Data Zero Comparison + RL78_mulu, // Multiply Unsigned - Unsigned Multiplication of Data + RL78_oneb, // One byte - Byte Data 01H Set + RL78_ror, // Rotate Right - Byte Data Rotation to the Right + RL78_rol, // Rotate Left - Byte Data Rotation to the Left + RL78_rorc, // Rotate Right with Carry - Byte Data Rotation to the Right with Carry + RL78_rolc, // Rotate Left with Carry - Byte Data Rotation to the Left with Carry + RL78_brk, // Break - Software Vectored Interrupt + RL78_retb, // Return from Break - Return from Software Vectored Interrupt + RL78_reti, // Return from Interrupt - Return from Interrupt Vectored Interrupt + RL78_stop, // Stop - Stop Mode Set + RL78_nop, // No Operation + RL78_callt, // Call Table - Subroutine Call (Refer to the Call Table) + + RL78_last +}; + diff --git a/idasdk75/include/allow_deprecated.hpp b/idasdk76/include/allow_deprecated.hpp similarity index 100% rename from idasdk75/include/allow_deprecated.hpp rename to idasdk76/include/allow_deprecated.hpp diff --git a/idasdk76/include/auto.hpp b/idasdk76/include/auto.hpp new file mode 100644 index 0000000..caa8def --- /dev/null +++ b/idasdk76/include/auto.hpp @@ -0,0 +1,289 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _AUTO_HPP +#define _AUTO_HPP +#include <ida.hpp> + +/*! \file auto.hpp + + \brief Functions that work with the autoanalyzer queue. + + The autoanalyzer works when IDA is not busy processing + the user keystrokes. It has several queues, each queue having + its own priority. The analyzer stops when all queues are empty. + + A queue contains addresses or address ranges. + The addresses are kept sorted by their values. + The analyzer will process all addresses from the first queue, then + switch to the second queue and so on. + There are no limitations on the size of the queues. + + This file also contains functions that deal with the IDA status + indicator and the autoanalysis indicator. + You may use these functions to change the indicator value. +*/ + +typedef int atype_t; ///< identifies an autoanalysis queue - see \ref AU_ + +/// \defgroup AU_ Autoanalysis queues +/// Names and priorities of the analyzer queues +//@{ +const atype_t + AU_NONE = 00, ///< placeholder, not used + AU_UNK = 10, ///< 0: convert to unexplored + AU_CODE = 20, ///< 1: convert to instruction + AU_WEAK = 25, ///< 2: convert to instruction (ida decision) + AU_PROC = 30, ///< 3: convert to procedure start + AU_TAIL = 35, ///< 4: add a procedure tail + AU_FCHUNK=38, ///< 5: find func chunks + AU_USED = 40, ///< 6: reanalyze + AU_TYPE = 50, ///< 7: apply type information + AU_LIBF = 60, ///< 8: apply signature to address + AU_LBF2 = 70, ///< 9: the same, second pass + AU_LBF3 = 80, ///< 10: the same, third pass + AU_CHLB = 90, ///< 11: load signature file (file name is kept separately) + AU_FINAL=200; ///< 12: final pass +//@} + + +typedef int idastate_t; ///< IDA status indicator - see \ref st_ + +/// \defgroup st_ Status indicator states +//@{ +const idastate_t + // meaning + st_Ready = 0, ///< READY: IDA is doing nothing + st_Think = 1, ///< THINKING: Autoanalysis on, the user may press keys + st_Waiting = 2, ///< WAITING: Waiting for the user input + st_Work = 3; ///< BUSY: IDA is busy +//@} + + +/// Get current state of autoanalyzer. +/// If auto_state == ::AU_NONE, IDA is currently not running the analysis +/// (it could be temporarily interrupted to perform the user's requests, for example). + +idaman atype_t ida_export get_auto_state(void); + + +/// Set current state of autoanalyzer. +/// \param new_state new state of autoanalyzer +/// \return previous state + +idaman atype_t ida_export set_auto_state(atype_t new_state); + + +/// See ::get_auto_display +struct auto_display_t +{ + atype_t type = AU_NONE; + ea_t ea = BADADDR; + idastate_t state = st_Ready; +}; + +/// Get structure which holds the autoanalysis indicator contents + +idaman bool ida_export get_auto_display(auto_display_t *auto_display); + + +/// Change autoanalysis indicator value. +/// \param ea linear address being analyzed +/// \param type autoanalysis type (see \ref AU_) + +idaman void ida_export show_auto(ea_t ea, atype_t type=AU_NONE); + + +/// Show an address on the autoanalysis indicator. +/// The address is displayed in the form " @:12345678". +/// \param ea - linear address to display + +inline void show_addr(ea_t ea) { show_auto(ea); } + + +/// Change IDA status indicator value +/// \param st - new indicator status +/// \return old indicator status + +idaman idastate_t ida_export set_ida_state(idastate_t st); + + +/// Is it allowed to create stack variables automatically?. +/// This function should be used by IDP modules before creating stack vars. + +inline bool may_create_stkvars(void) +{ + return inf_should_create_stkvars() && get_auto_state() == AU_USED; +} + + +/// Is it allowed to trace stack pointer automatically?. +/// This function should be used by IDP modules before tracing sp. + +inline bool may_trace_sp(void) +{ + if ( inf_should_trace_sp() ) + { + atype_t auto_state = get_auto_state(); + return auto_state == AU_USED; + } + return false; +} + + +/// Put range of addresses into a queue. +/// 'start' may be higher than 'end', the kernel will swap them in this case. +/// 'end' doesn't belong to the range. + +idaman void ida_export auto_mark_range(ea_t start,ea_t end,atype_t type); + + +/// Put single address into a queue. Queues keep addresses sorted. + +inline void auto_mark(ea_t ea, atype_t type) +{ + auto_mark_range(ea, ea+1, type); +} + + +/// Remove range of addresses from a queue. +/// 'start' may be higher than 'end', the kernel will swap them in this case. +/// 'end' doesn't belong to the range. + +idaman void ida_export auto_unmark(ea_t start, ea_t end, atype_t type); + +// Convenience functions + +/// Plan to perform reanalysis +inline void plan_ea(ea_t ea) +{ + auto_mark(ea, AU_USED); +} +/// Plan to perform reanalysis +inline void plan_range(ea_t sEA, ea_t eEA) +{ + auto_mark_range(sEA, eEA, AU_USED); +} +/// Plan to make code +inline void auto_make_code(ea_t ea) +{ + auto_mark(ea, AU_CODE); +} +/// Plan to make code&function +inline void auto_make_proc(ea_t ea) +{ + auto_make_code(ea); + auto_mark(ea, AU_PROC); +} + +/// Plan to reanalyze callers of the specified address. +/// This function will add to ::AU_USED queue all instructions that +/// call (not jump to) the specified address. +/// \param ea linear address of callee +/// \param noret !=0: the callee doesn't return, mark to undefine subsequent +/// instructions in the caller. 0: do nothing. + +idaman void ida_export reanalyze_callers(ea_t ea, bool noret); + + +/// Delete all analysis info that IDA generated for for the given range + +idaman void ida_export revert_ida_decisions(ea_t ea1, ea_t ea2); + + +/// Plan to apply the callee's type to the calling point + +idaman void ida_export auto_apply_type(ea_t caller, ea_t callee); + +/// Plan to apply the tail_ea chunk to the parent +/// \param tail_ea linear address of start of tail +/// \param parent_ea linear address within parent. If BADADDR, automatically +/// try to find parent via xrefs. + +idaman void ida_export auto_apply_tail(ea_t tail_ea, ea_t parent_ea); + +/// Analyze the specified range. +/// Try to create instructions where possible. +/// Make the final pass over the specified range if specified. +/// This function doesn't return until the range is analyzed. +/// \retval 1 ok +/// \retval 0 Ctrl-Break was pressed + +idaman int ida_export plan_and_wait(ea_t ea1, ea_t ea2, bool final_pass=true); + + +/// Process everything in the queues and return true. +/// \return false if the user clicked cancel. +/// (the wait box must be displayed by the caller if desired) + +idaman bool ida_export auto_wait(void); + + +/// Process everything in the specified range and return true. +/// \return number of autoanalysis steps made. -1 if the user clicked cancel. +/// (the wait box must be displayed by the caller if desired) + +idaman ssize_t ida_export auto_wait_range(ea_t ea1, ea_t ea2); + + +/// Analyze one address in the specified range and return true. +/// \return if processed anything. false means that there is nothing to +/// process in the specified range. + +idaman bool ida_export auto_make_step(ea_t ea1, ea_t ea2); + + +/// Remove an address range (ea1..ea2) from queues ::AU_CODE, ::AU_PROC, ::AU_USED. +/// To remove an address range from other queues use auto_unmark() function. +/// 'ea1' may be higher than 'ea2', the kernel will swap them in this case. +/// 'ea2' doesn't belong to the range. + +idaman void ida_export auto_cancel(ea_t ea1, ea_t ea2); + + +/// Are all queues empty? +/// (i.e. has autoanalysis finished?). + +idaman bool ida_export auto_is_ok(void); + + +/// Peek into a queue 'type' for an address not lower than 'low_ea'. +/// Do not remove address from the queue. +/// \return the address or #BADADDR + +idaman ea_t ida_export peek_auto_queue(ea_t low_ea, atype_t type); + + +/// Retrieve an address from queues regarding their priority. +/// Returns #BADADDR if no addresses not lower than 'lowEA' and less than +/// 'highEA' are found in the queues. +/// Otherwise *type will have queue type. + +idaman ea_t ida_export auto_get(atype_t *type, ea_t lowEA, ea_t highEA); + + +/// Try to create instruction +/// \param ea linear address of callee +/// \return the length of the instruction or 0 + +idaman int ida_export auto_recreate_insn(ea_t ea); + + +/// Get autoanalyzer state + +idaman bool ida_export is_auto_enabled(void); + + +/// Temporarily enable/disable autoanalyzer. Not user-facing, but rather because +/// IDA sometimes need to turn AA on/off regardless of inf.s_genflags:INFFL_AUTO +/// \return old state + +idaman bool ida_export enable_auto(bool enable); + + + +#endif // _AUTO_HPP diff --git a/idasdk75/include/bitrange.hpp b/idasdk76/include/bitrange.hpp similarity index 100% rename from idasdk75/include/bitrange.hpp rename to idasdk76/include/bitrange.hpp diff --git a/idasdk76/include/bytes.hpp b/idasdk76/include/bytes.hpp new file mode 100644 index 0000000..627e378 --- /dev/null +++ b/idasdk76/include/bytes.hpp @@ -0,0 +1,2556 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef BYTES_HPP +#define BYTES_HPP + +#include <nalt.hpp> +#include <lines.hpp> +#include <range.hpp> + +typedef tid_t enum_t; // #include <enum.hpp> +class insn_t; + +/*! \file bytes.hpp + + \brief Contains functions that deal with individual byte characteristics. + + Each byte of the disassembled program is represented by a 32-bit + value. We will call this value 'flags'. The structure of the flags is + here. + + You are not allowed to inspect individual bits of flags and modify them directly. + Use special functions to inspect and/or modify flags. + + Flags are kept in a virtual array file (*.id1). + Addresses (ea) are all 32-bit (or 64-bit) quantities. +*/ + +//-------------------------------------------------------------------------- +/// Allocate flags for address range. +/// This function does not change the storage type of existing ranges. +/// Exit with an error message if not enough disk space. +/// \param start_ea should be lower than end_ea. +/// \param end_ea does not belong to the range. +/// \param stt ::storage_type_t +/// \return 0 if ok, otherwise an error code + +idaman error_t ida_export enable_flags(ea_t start_ea, ea_t end_ea, storage_type_t stt); + + +/// Deallocate flags for address range. +/// Exit with an error message if not enough disk space (this may occur too). +/// \param start_ea should be lower than end_ea. +/// \param end_ea does not belong to the range. +/// \return 0 if ok, otherwise return error code + +idaman error_t ida_export disable_flags(ea_t start_ea, ea_t end_ea); + + +/// Change flag storage type for address range. +/// \param start_ea should be lower than end_ea. +/// \param end_ea does not belong to the range. +/// \param stt ::storage_type_t +/// \return error code + +idaman error_t ida_export change_storage_type(ea_t start_ea, ea_t end_ea, storage_type_t stt); + + +/// Get next address in the program (i.e. next address which has flags). +/// \return #BADADDR if no such address exist. + +idaman ea_t ida_export next_addr(ea_t ea); + + +/// Get previous address in the program. +/// \return #BADADDR if no such address exist. + +idaman ea_t ida_export prev_addr(ea_t ea); + + +/// Get the first address of next contiguous chunk in the program. +/// \return #BADADDR if next chunk doesn't exist. + +idaman ea_t ida_export next_chunk(ea_t ea); + + +/// Get the last address of previous contiguous chunk in the program. +/// \return #BADADDR if previous chunk doesn't exist. + +idaman ea_t ida_export prev_chunk(ea_t ea); + + +/// Get start of the contiguous address block containing 'ea'. +/// \return #BADADDR if 'ea' doesn't belong to the program. + +idaman ea_t ida_export chunk_start(ea_t ea); + + +/// Get size of the contiguous address block containing 'ea'. +/// \return 0 if 'ea' doesn't belong to the program. + +idaman asize_t ida_export chunk_size(ea_t ea); + + +/// Search for a hole in the addressing space of the program. +/// \param bottom address to start searching +/// \param size size of desired block +/// \param step bit mask for the start of hole (0xF would align hole to a paragraph). +/// if 'step' is negative, the bottom address with be aligned. +/// otherwise the kernel will try to use it as is and align it +/// only when the hole is too small. +/// \return start of the hole or #BADADDR + +idaman ea_t ida_export free_chunk(ea_t bottom, asize_t size, int32 step); + + +/// Flag tester - see next_that(), prev_that() +typedef bool idaapi testf_t(flags_t flags, void *ud); + + +/// Find next address with a flag satisfying the function 'testf'. +/// \note do not pass is_unknown() to this function to find unexplored bytes. +/// It will fail under the debugger. To find unexplored bytes, use next_unknown(). +/// \param ea start searching at this address + 1 +/// \param maxea not included in the search range. +/// \param testf test function to find next address +/// \param ud user data - may point to anything. it will be passed to testf. +/// \return the found address or #BADADDR. + +idaman ea_t ida_export next_that( + ea_t ea, + ea_t maxea, + testf_t *testf, + void *ud=nullptr); + + +/// Similar to next_that(), but will find the next address that is unexplored + +inline ea_t idaapi next_unknown(ea_t ea, ea_t maxea) +{ + return next_that(ea, maxea, nullptr); +} + + +/// Find previous address with a flag satisfying the function 'testf'. +/// \note do not pass is_unknown() to this function to find unexplored bytes +/// It will fail under the debugger. To find unexplored bytes, use prev_unknown(). +/// \param ea start searching from this address - 1. +/// \param minea included in the search range. +/// \param testf test function to find previous address +/// \param ud user data - may point to anything. it will be passed to testf. +/// \return the found address or #BADADDR. + +idaman ea_t ida_export prev_that( + ea_t ea, + ea_t minea, + testf_t *testf, + void *ud=nullptr); + + +/// Similar to prev_that(), but will find the previous address that is unexplored + +inline ea_t idaapi prev_unknown(ea_t ea, ea_t minea) +{ + return prev_that(ea, minea, nullptr); +} + + +/// Get start of previous defined item. +/// \param ea begin search at this address +/// \param minea included in the search range +/// \return #BADADDR if none exists. + +idaman ea_t ida_export prev_head(ea_t ea, ea_t minea); + + +/// Get start of next defined item. +/// \param ea begin search at this address +/// \param maxea not included in the search range +/// \return #BADADDR if none exists. + +idaman ea_t ida_export next_head(ea_t ea, ea_t maxea); + + +/// Get address of previous non-tail byte. +/// \return #BADADDR if none exists. + +idaman ea_t ida_export prev_not_tail(ea_t ea); + + +/// Get address of next non-tail byte. +/// \return #BADADDR if none exists. + +idaman ea_t ida_export next_not_tail(ea_t ea); + + +/// Adjust the address and get the nearest visible address. +/// (i.e. an address which will appear in the disassembly) +/// \return #BADADDR only if no addresses are valid + +ea_t adjust_visea(ea_t ea); + + +/// Get previous visible address. +/// \return #BADADDR if none exists. + +idaman ea_t ida_export prev_visea(ea_t ea); + + +/// Get next visible address. +/// \return #BADADDR if none exists. + +idaman ea_t ida_export next_visea(ea_t ea); + + +/// Is an address the first visible address? + +bool is_first_visea(ea_t ea); + + +/// Is an address the last visible address? + +bool is_last_visea(ea_t ea); + + +/// Is the address visible on the screen (not hidden)? + +bool is_visible_finally(ea_t ea); // do we need to show anything + // at this address? + + + +/// Get the start address of the item at 'ea'. +/// If there is no current item, then 'ea' will be returned +/// (see definition at the end of bytes.hpp source) + +inline ea_t idaapi get_item_head(ea_t ea); + + +/// Get the end address of the item at 'ea'. The returned address +/// doesn't belong to the current item. Unexplored bytes are counted as +/// 1 byte entities. + +idaman ea_t ida_export get_item_end(ea_t ea); + + +/// Calculate maximal reasonable end address of a new item. +/// This function will limit the item with the current segment bounds. +/// \param ea linear address +/// \param how when to stop the search. A combination of \ref ITEM_END_ +/// \return end of new item. If it is not possible to create an item, +/// it will return 'ea'. + +idaman ea_t ida_export calc_max_item_end(ea_t ea, int how=15); +/// \defgroup ITEM_END_ Item end search flags +/// passed as 'how' parameter to calc_max_item_end() +//@{ +#define ITEM_END_FIXUP 0x0001 ///< stop at the first fixup +#define ITEM_END_INITED 0x0002 ///< stop when initialization changes + ///< i.e. + ///< - if is_loaded(ea): stop if uninitialized byte is encountered + ///< - if !is_loaded(ea): stop if initialized byte is encountered +#define ITEM_END_NAME 0x0004 ///< stop at the first named location +#define ITEM_END_XREF 0x0008 ///< stop at the first referenced location +//@} + + +/// Get size of item (instruction/data) in bytes. +/// Unexplored bytes have length of 1 byte. This function never returns 0. + +inline asize_t get_item_size(ea_t ea) { return get_item_end(ea) - ea; } + + + + +/// Is the specified address 'ea' present in the program? + +idaman bool ida_export is_mapped(ea_t ea); + + +/// Get flags for the specified address, extended form + +idaman flags_t ida_export get_flags_ex(ea_t ea, int how); + +#define GFE_VALUE 0x0001 ///< get flags with #FF_IVL & #MS_VAL. + ///< It is much slower under remote debugging + ///< because the kernel needs to read + ///< the process memory. + +/// \copydoc GFE_VALUE +inline flags_t idaapi get_flags(ea_t ea) { return get_flags_ex(ea, 0); } + + +/// Get flags value for address 'ea'. +/// \return 0 if address is not present in the program + +inline flags_t idaapi get_full_flags(ea_t ea) { return get_flags_ex(ea, GFE_VALUE); } + + +/// Get flag of the item at 'ea' even if it is a tail byte of some +/// array or structure. This function is used to get flags of structure members +/// or array elements. +/// \param from linear address of the instruction which refers to 'ea' +/// \param n number of operand which refers to 'ea' +/// \param ea the referenced address +/// \param appzero append a struct field name if the field offset is zero? +/// meaningful only if the name refers to a structure. +/// \return flags or 0 (if failed) + +idaman flags_t ida_export get_item_flag(ea_t from, int n, ea_t ea, bool appzero); + + +//-------------------------------------------------------------------------- +/// \defgroup FF_ Flags structure +/// Here we define the organization of ::flags_t values. +/// Low 8 bits contain value of corresponding byte of the program. +/// The next bit is set if the byte is initialized. +//@{ +#define MS_VAL 0x000000FFLU ///< Mask for byte value +#define FF_IVL 0x00000100LU ///< Byte has value ? +//@} + +/// Do flags contain byte value? + +inline THREAD_SAFE bool idaapi has_value(flags_t F) { return (F & FF_IVL) != 0; } + + +/// Delete byte value from flags. The corresponding byte becomes +/// uninitialized. + +idaman void ida_export del_value(ea_t ea); + + +/// Does the specified address have a byte value (is initialized?) + +idaman bool ida_export is_loaded(ea_t ea); + + +/// Get number of bits in a byte at the given address. +/// \return \ph{dnbits()} if the address doesn't +/// belong to a segment, otherwise the result depends on the +/// segment type + +idaman int ida_export nbits(ea_t ea); + + +/// Get number of bytes required to store a byte at the given address + +inline int bytesize(ea_t ea) + { return (nbits(ea)+7)/8; } + + +/// Get one byte (8-bit) of the program at 'ea'. +/// This function works only for 8bit byte processors. + +idaman uchar ida_export get_byte(ea_t ea); + + +/// Get one byte (8-bit) of the program at 'ea' from the database. +/// Works even if the debugger is active. +/// See also get_dbg_byte() to read the process memory directly. +/// This function works only for 8bit byte processors. + +idaman uchar ida_export get_db_byte(ea_t ea); + + +/// Get one word (16-bit) of the program at 'ea'. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// This function works only for 8bit byte processors. + +idaman ushort ida_export get_word(ea_t ea); + + +/// Get one dword (32-bit) of the program at 'ea'. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// This function works only for 8bit byte processors. + +idaman uint32 ida_export get_dword(ea_t ea); + + +/// Get one qword (64-bit) of the program at 'ea'. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// This function works only for 8bit byte processors. + +idaman uint64 ida_export get_qword(ea_t ea); + + +/// Get one wide byte of the program at 'ea'. +/// Some processors may access more than 8bit quantity at an address. +/// These processors have 32-bit byte organization from the IDA's point of view. + +idaman uint64 ida_export get_wide_byte(ea_t ea); + + +/// Get one wide word (2 'byte') of the program at 'ea'. +/// Some processors may access more than 8bit quantity at an address. +/// These processors have 32-bit byte organization from the IDA's point of view. +/// This function takes into account order of bytes specified in \inf{is_be()} + +idaman uint64 ida_export get_wide_word(ea_t ea); + + +/// Get two wide words (4 'bytes') of the program at 'ea'. +/// Some processors may access more than 8bit quantity at an address. +/// These processors have 32-bit byte organization from the IDA's point of view. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \note this function works incorrectly if \ph{nbits} > 16 + +idaman uint64 ida_export get_wide_dword(ea_t ea); + + +/// Get 8 bits of the program at 'ea'. +/// The main usage of this function is to iterate range of bytes. +/// Here is an example: +/// \code +/// uint64 v; +/// int nbit = 0; +/// for ( ... ) { +/// uchar byte = get_octet(&ea, &v, &nbit); +/// ... +/// } +/// \endcode +/// 'ea' is incremented each time when a new byte is read. +/// In the above example, it will be incremented in the first loop iteration. + +idaman uchar ida_export get_octet(ea_t *ea, uint64 *v, int *nbit); + + + +/// Get 16bits of the program at 'ea'. +/// \return 1 byte (getFullByte()) if the current processor has 16-bit byte, +/// otherwise return get_word() + +idaman uint32 ida_export get_16bit(ea_t ea); + + +/// Get not more than 32bits of the program at 'ea'. +/// \return 32 bit value, depending on \ph{nbits}: +/// - if ( nbits <= 8 ) return get_dword(ea); +/// - if ( nbits <= 16) return get_wide_word(ea); +/// - return get_wide_byte(ea); + +idaman uint32 ida_export get_32bit(ea_t ea); + + +/// Get not more than 64bits of the program at 'ea'. +/// \return 64 bit value, depending on \ph{nbits}: +/// - if ( nbits <= 8 ) return get_qword(ea); +/// - if ( nbits <= 16) return get_wide_dword(ea); +/// - return get_wide_byte(ea); + +idaman uint64 ida_export get_64bit(ea_t ea); + + +/// Get the value at of the item at 'ea'. +/// This function works with entities up to sizeof(ea_t) +/// (bytes, word, etc) +/// \param v pointer to the result. may be nullptr +/// \param ea linear address +/// \param size size of data to read. If 0, then the item +/// type at 'ea' will be used +/// \return success + +idaman bool ida_export get_data_value(uval_t *v, ea_t ea, asize_t size); + + +/// Visit all the patched bytes one byte at a time. +/// \param ea1 start linear address +/// \param ea2 end linear address +/// \param cb callback called for each found byte. +/// if the callback returns non-zero then that value will be +/// returned to the caller and the enumeration will be interrupted. +/// \param ud user data passed to the callback +/// \return the return value returned by the callback (if any) or zero +/// if the enumeration was completed. + +idaman int ida_export visit_patched_bytes( + ea_t ea1, + ea_t ea2, + int (idaapi *cb)(ea_t ea, qoff64_t fpos, uint64 o, uint64 v, void *ud), + void *ud = nullptr); + + +/// Get original byte value (that was before patching). +/// This function works for wide byte processors too. + +idaman uint64 ida_export get_original_byte(ea_t ea); + + +/// Get original word value (that was before patching). +/// This function works for wide byte processors too. +/// This function takes into account order of bytes specified in \inf{is_be()} + +idaman uint64 ida_export get_original_word(ea_t ea); + + +/// Get original dword (that was before patching) +/// This function works for wide byte processors too. +/// This function takes into account order of bytes specified in \inf{is_be()} + +idaman uint64 ida_export get_original_dword(ea_t ea); + + +/// Get original qword value (that was before patching) +/// This function DOESN'T work for wide byte processors too. +/// This function takes into account order of bytes specified in \inf{is_be()} + +idaman uint64 ida_export get_original_qword(ea_t ea); + + +/// Set value of one byte of the program. +/// This function modifies the database. If the debugger is active +/// then the debugged process memory is patched too. +/// \note The original value of the byte is completely lost and can't +/// be recovered by the get_original_byte() function. +/// See also put_dbg_byte() to write to the process memory directly when +/// the debugger is active. +/// This function can handle wide byte processors. +/// \param ea linear address +/// \param x byte value +/// \return true if the database has been modified + +idaman bool ida_export put_byte(ea_t ea, uint64 x); + + +/// Set value of one word of the program. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// This function works for wide byte processors too. +/// \note The original value of the word is completely lost and can't +/// be recovered by the get_original_word() function. +/// ea - linear address +/// x - word value + +idaman void ida_export put_word(ea_t ea, uint64 x); + + +/// Set value of one dword of the program. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// This function works for wide byte processors too. +/// \param ea linear address +/// \param x dword value +/// \note the original value of the dword is completely lost and can't +/// be recovered by the get_original_dword() function. + +idaman void ida_export put_dword(ea_t ea, uint64 x); + + +/// Set value of one qword (8 bytes) of the program. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// This function DOESN'T works for wide byte processors. +/// \param ea linear address +/// \param x qword value + +idaman void ida_export put_qword(ea_t ea, uint64 x); + + +/// Patch a byte of the program. The original value of the byte is saved +/// and can be obtained by get_original_byte(). +/// This function works for wide byte processors too. +/// \retval true the database has been modified, +/// \retval false the debugger is running and the process' memory +/// has value 'x' at address 'ea', or +/// the debugger is not running, and the IDB +/// has value 'x' at address 'ea already. + +idaman bool ida_export patch_byte(ea_t ea, uint64 x); + + +/// Patch a word of the program. The original value of the word is saved +/// and can be obtained by get_original_word(). +/// This function works for wide byte processors too. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \retval true the database has been modified, +/// \retval false the debugger is running and the process' memory +/// has value 'x' at address 'ea', or +/// the debugger is not running, and the IDB +/// has value 'x' at address 'ea already. + +idaman bool ida_export patch_word(ea_t ea, uint64 x); + + +/// Patch a dword of the program. The original value of the dword is saved +/// and can be obtained by get_original_dword(). +/// This function DOESN'T work for wide byte processors. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \retval true the database has been modified, +/// \retval false the debugger is running and the process' memory +/// has value 'x' at address 'ea', or +/// the debugger is not running, and the IDB +/// has value 'x' at address 'ea already. + +idaman bool ida_export patch_dword(ea_t ea, uint64 x); + + +/// Patch a qword of the program. The original value of the qword is saved +/// and can be obtained by get_original_qword(). +/// This function DOESN'T work for wide byte processors. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \retval true the database has been modified, +/// \retval false the debugger is running and the process' memory +/// has value 'x' at address 'ea', or +/// the debugger is not running, and the IDB +/// has value 'x' at address 'ea already. + +idaman bool ida_export patch_qword(ea_t ea, uint64 x); + + +/// Revert patched byte +/// \retval true byte was patched before and reverted now + +idaman bool ida_export revert_byte(ea_t ea); + + +/// Add a value to one byte of the program. +/// This function works for wide byte processors too. +/// \param ea linear address +/// \param value byte value + +idaman void ida_export add_byte(ea_t ea, uint32 value); + + +/// Add a value to one word of the program. +/// This function works for wide byte processors too. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \param ea linear address +/// \param value byte value + +idaman void ida_export add_word(ea_t ea, uint64 value); + + +/// Add a value to one dword of the program. +/// This function works for wide byte processors too. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \note this function works incorrectly if \ph{nbits} > 16 +/// \param ea linear address +/// \param value byte value + +idaman void ida_export add_dword(ea_t ea, uint64 value); + + +/// Add a value to one qword of the program. +/// This function does not work for wide byte processors. +/// This function takes into account order of bytes specified in \inf{is_be()} +/// \param ea linear address +/// \param value byte value + +idaman void ida_export add_qword(ea_t ea, uint64 value); + + +/// Return set of ranges with zero initialized bytes. +/// The returned set includes only big zero initialized ranges (at least >1KB). +/// Some zero initialized byte ranges may be not included. +/// Only zero bytes that use the sparse storage method (STT_MM) are reported. +/// \param zranges pointer to the return value. cannot be nullptr +/// \param range the range of addresses to verify. can be nullptr - means all ranges +/// \return true if the result is a non-empty set + +idaman bool ida_export get_zero_ranges(rangeset_t *zranges, const range_t *range); + + +/// Get the specified number of bytes of the program into the buffer. +/// If mask was specified it will contain a bitmap of initialized / uninitialized +/// database bytes. +/// \param ea linear address +/// \param buf buffer to hold bytes +/// \param size size of buffer in normal 8-bit bytes (sizeof(buf)) +/// \param gmb_flags combination of \ref GMB_ bits +/// \param mask bitmap of initialize/uninitialized bytes +/// (may be nullptr; must be at least (size+7)/8) +/// \return if the user cancelled, return -1; otherwise number of read bytes. + +idaman ssize_t ida_export get_bytes( + void *buf, + ssize_t size, + ea_t ea, + int gmb_flags=0, + void *mask=nullptr); + +/// \defgroup GMB_ flags for get_bytes() +//@{ +#define GMB_READALL 0x01 ///< try to read all bytes + ///< if this bit is not set, fail at first uninited byte +#define GMB_WAITBOX 0x02 ///< show wait box (may return -1 in this case) +///@} + + +/// Modify the specified number of bytes of the program. +/// This function does not save the original values of bytes. +/// See also patch_bytes(). +/// \param ea linear address +/// \param buf buffer with new values of bytes +/// \param size size of buffer in normal 8-bit bytes (sizeof(buf)) + +idaman void ida_export put_bytes(ea_t ea, const void *buf, size_t size); + + +/// Patch the specified number of bytes of the program. +/// Original values of bytes are saved and are available with get_original...() +/// functions. +/// See also put_bytes(). +/// \param ea linear address +/// \param buf buffer with new values of bytes +/// \param size size of buffer in normal 8-bit bytes (sizeof(buf)) + +idaman void ida_export patch_bytes(ea_t ea, const void *buf, size_t size); + +//------------------------------------------------------------------------- +/// \defgroup FF_states States +/// \ingroup FF_ +/// Represent general characteristics of a byte in the program. +/// +/// Each byte of the program may be in one of four states. +/// - unexplored +/// - start of instruction +/// - start of data +/// - second, third (tail) byte of instruction or data. +/// +/// Initially, all bytes of the program are unexplored. +/// IDA modifies flags and doing so converts bytes to instructions +/// and data. +//@{ + +/// \defgroup FF_statebits Bits: byte states +//@{ +#define MS_CLS 0x00000600LU ///< Mask for typing +#define FF_CODE 0x00000600LU ///< Code ? +#define FF_DATA 0x00000400LU ///< Data ? +#define FF_TAIL 0x00000200LU ///< Tail ? +#define FF_UNK 0x00000000LU ///< Unknown ? +//@} + +/// \defgroup FF_statefuncs Functions: examine byte states +//@{ + +/// Does flag denote start of an instruction? + +inline THREAD_SAFE bool idaapi is_code(flags_t F) { return (F & MS_CLS) == FF_CODE; } +inline THREAD_SAFE bool idaapi f_is_code(flags_t F, void *) { return is_code(F); } ///< \copydoc is_code() + + +/// Does flag denote start of data? + +inline THREAD_SAFE bool idaapi is_data(flags_t F) { return (F & MS_CLS) == FF_DATA; } +inline THREAD_SAFE bool idaapi f_is_data(flags_t F, void *) { return is_data(F); } ///< \copydoc is_data() + + +/// Does flag denote tail byte? + +inline THREAD_SAFE bool idaapi is_tail(flags_t F) { return (F & MS_CLS) == FF_TAIL; } +inline THREAD_SAFE bool idaapi f_is_tail(flags_t F, void *) { return is_tail(F); } ///< \copydoc is_tail() +inline THREAD_SAFE bool idaapi is_not_tail(flags_t F) { return !is_tail(F); } ///< \copydoc is_tail() +inline THREAD_SAFE bool idaapi f_is_not_tail(flags_t F, void *) { return is_not_tail(F); } ///< \copydoc is_tail() + + +/// Does flag denote unexplored byte? + +inline THREAD_SAFE bool idaapi is_unknown(flags_t F) { return (F & MS_CLS) == FF_UNK; } + + +/// Does flag denote start of instruction OR data? + +inline THREAD_SAFE bool idaapi is_head(flags_t F) { return (F & FF_DATA) != 0; } +inline THREAD_SAFE bool idaapi f_is_head(flags_t F, void *) { return is_head(F); } ///< \copydoc is_head() + +//@} FF_statefuncs +//@} FF_states + +/// del_items' callback function +typedef bool idaapi may_destroy_cb_t(ea_t); + +/// Convert item (instruction/data) to unexplored bytes. +/// The whole item (including the head and tail bytes) will be destroyed. +/// It is allowed to pass any address in the item to this function +/// \param ea any address within the first item to delete +/// \param flags combination of \ref DELIT_ +/// \param nbytes number of bytes in the range to be undefined +/// \param may_destroy optional routine invoked before deleting a head +/// item. If callback returns false then item has not to +/// be deleted and operation fails +/// \return true on sucessful operation, otherwise false + +idaman bool ida_export del_items( + ea_t ea, + int flags=0, + asize_t nbytes=1, + may_destroy_cb_t *may_destroy=nullptr); + +/// \defgroup DELIT_ Unexplored byte conversion flags +/// passed as 'flags' parameter to del_items() +//@{ +#define DELIT_SIMPLE 0x0000 ///< simply undefine the specified item(s) +#define DELIT_EXPAND 0x0001 ///< propagate undefined items; for example + ///< if removing an instruction removes all + ///< references to the next instruction, then + ///< plan to convert to unexplored the next + ///< instruction too. +#define DELIT_DELNAMES 0x0002 ///< delete any names at the specified + ///< address range (except for the starting + ///< address). this bit is valid if nbytes > 1 +#define DELIT_NOTRUNC 0x0004 ///< don't truncate the current function + ///< even if #AF_TRFUNC is set +#define DELIT_NOUNAME 0x0008 ///< reject to delete if a user name is + ///< in address range (except for the starting + ///< address). this bit is valid if nbytes > 1 +#define DELIT_NOCMT 0x0010 ///< reject to delete if a comment is + ///< in address range (except for the starting + ///< address). this bit is valid if nbytes > 1 +#define DELIT_KEEPFUNC 0x0020 ///< do not undefine the function start. + ///< Just delete xrefs, ops e.t.c. +//@} + + +//------------------------------------------------------------------------- +// Manual instructions (they are used to completely override an automatically +// generated instruction by a user specified string). + +/// Is the instruction overridden? +/// \param ea linear address of the instruction or data item + +idaman bool ida_export is_manual_insn(ea_t ea); // Is the instruction overridden? + + +/// Retrieve the user-specified string for the manual instruction. +/// \param buf output buffer +/// \param ea linear address of the instruction or data item +/// \return size of manual instruction or -1 + +idaman ssize_t ida_export get_manual_insn(qstring *buf, ea_t ea); + + +/// Set manual instruction string. +/// \param ea linear address of the instruction or data item +/// \param manual_insn "" - delete manual string. +/// nullptr - do nothing + +idaman void ida_export set_manual_insn(ea_t ea, const char *manual_insn); // Set user-specified string + + +//------------------------------------------------------------------------- +/*! \defgroup FF_statespecb Bits: specific state information + \ingroup FF_states + Flags keep information common to all four states of bytes. + This information will not be automatically discarded during + transitions between different states. +*/ +//@{ +#define MS_COMM 0x000FF800 ///< Mask of common bits +#define FF_COMM 0x00000800 ///< Has comment ? +#define FF_REF 0x00001000 ///< has references +#define FF_LINE 0x00002000 ///< Has next or prev lines ? +#define FF_NAME 0x00004000 ///< Has name ? +#define FF_LABL 0x00008000 ///< Has dummy name? +#define FF_FLOW 0x00010000 ///< Exec flow from prev instruction +#define FF_SIGN 0x00020000 ///< Inverted sign of operands +#define FF_BNOT 0x00040000 ///< Bitwise negation of operands +#define FF_UNUSED 0x00080000 ///< unused bit (was used for variable bytes) +//@} + +/// \defgroup FF_statespecf Functions: examine specific state information +/// \ingroup FF_states +//@{ + +/// Does the previous instruction exist and pass execution flow to the current byte? + +inline THREAD_SAFE bool idaapi is_flow(flags_t F) { return (F & FF_FLOW) != 0; } + + +/// Does the current byte have additional anterior or posterior lines? + +inline THREAD_SAFE bool idaapi has_extra_cmts(flags_t F) { return (F & FF_LINE) != 0; } +inline THREAD_SAFE bool idaapi f_has_extra_cmts(flags_t f, void *) { return has_extra_cmts(f); } + +/// Does the current byte have an indented comment? + +inline THREAD_SAFE bool idaapi has_cmt(flags_t F) { return (F & FF_COMM) != 0; } +inline THREAD_SAFE bool idaapi f_has_cmt(flags_t f, void *) { return has_cmt(f); } + +/// Does the current byte have cross-references to it? + +inline THREAD_SAFE bool idaapi has_xref(flags_t F) { return (F & FF_REF) != 0; } +inline THREAD_SAFE bool idaapi f_has_xref(flags_t f, void *) { return has_xref(f); } ///< \copydoc has_xref() + + +/// Does the current byte have non-trivial (non-dummy) name? + +inline THREAD_SAFE bool idaapi has_name(flags_t F) { return (F & FF_NAME) != 0; } +inline THREAD_SAFE bool idaapi f_has_name(flags_t f, void *) { return has_name(f); } ///< \copydoc has_name() + + + +#define FF_ANYNAME (FF_LABL|FF_NAME) + +/// Does the current byte have dummy (auto-generated, with special prefix) name? + +inline THREAD_SAFE bool idaapi has_dummy_name(flags_t F) { return (F & FF_ANYNAME) == FF_LABL; } +inline THREAD_SAFE bool idaapi f_has_dummy_name(flags_t f, void *) { return has_dummy_name(f); } ///< \copydoc has_dummy_name() + + +/// Does the current byte have auto-generated (no special prefix) name? + +inline THREAD_SAFE bool idaapi has_auto_name(flags_t F) { return (F & FF_ANYNAME) == FF_ANYNAME; } + + +/// Does the current byte have any name? + +inline THREAD_SAFE bool idaapi has_any_name(flags_t F) { return (F & FF_ANYNAME) != 0; } + + +/// Does the current byte have user-specified name? + +inline THREAD_SAFE bool idaapi has_user_name(flags_t F) { return (F & FF_ANYNAME) == FF_NAME; } +inline THREAD_SAFE bool idaapi f_has_user_name(flags_t F, void *) { return has_user_name(F); } ///< \copydoc has_user_name() + +// signness deals with the form of operands of the current instruction/data. +// inverted sign means the following: +// if the bit is clear |then when the bit is set +// and the output is |the output should be: +// ------------ |---------- +// unsigned |signed +// signed |unsigned +// + +/// Should sign of n-th operand inverted during output?. +/// allowed values of n: 0-first operand, 1-other operands + +idaman bool ida_export is_invsign(ea_t ea, flags_t F, int n); + + +/// Toggle sign of n-th operand. +/// allowed values of n: 0-first operand, 1-other operands + +idaman bool ida_export toggle_sign(ea_t ea, int n); + + +/// Should we negate the operand?. +/// \ash{a_bnot} should be defined in the idp module in order to work +/// with this function + +idaman bool ida_export is_bnot(ea_t ea, flags_t F, int n); +idaman bool ida_export toggle_bnot(ea_t ea, int n); ///< Toggle binary negation of operand. also see is_bnot() + + +/// Display leading zeroes in operands. +/// The global switch for the leading zeroes is in \inf{s_genflags} +/// The leading zeroes doesn't work if the octal numbers start with 0 + +idaman bool ida_export is_lzero(ea_t ea, int n); ///< Display leading zeroes? + ///< (takes into account \inf{s_genflags}) +idaman bool ida_export set_lzero(ea_t ea, int n); ///< Set toggle lzero bit +idaman bool ida_export clr_lzero(ea_t ea, int n); ///< Clear lzero bit +inline bool idaapi toggle_lzero(ea_t ea, int n) ///< Toggle lzero bit +{ + return (is_lzero(ea, n) ? clr_lzero : set_lzero)(ea, n); +} + +//@} FF_statespecf + + +/// Check if leading zeroes are important + +idaman bool ida_export leading_zero_important(ea_t ea, int n); + + +//------------------------------------------------------------------------- +/// \defgroup FF_op Instruction/Data operands +/// \ingroup FF_ +/// Represent instruction/data operands. +/// +/// IDA keeps 2 bitmasks: +/// - representation of the first operand +/// - representation of other operands (we will call this +/// 'representation of second operand' +/// although it is also applied to third, fourth, etc operands too) +/// +/// For data bytes, only the first bitmask is used (i.e. all elements of +/// an array have the same type). +//@{ + +/// \defgroup FF_opbits Bits: instruction operand types +//@{ +#define MS_0TYPE 0x00F00000LU ///< Mask for 1st arg typing +#define FF_0VOID 0x00000000LU ///< Void (unknown)? +#define FF_0NUMH 0x00100000LU ///< Hexadecimal number? +#define FF_0NUMD 0x00200000LU ///< Decimal number? +#define FF_0CHAR 0x00300000LU ///< Char ('x')? +#define FF_0SEG 0x00400000LU ///< Segment? +#define FF_0OFF 0x00500000LU ///< Offset? +#define FF_0NUMB 0x00600000LU ///< Binary number? +#define FF_0NUMO 0x00700000LU ///< Octal number? +#define FF_0ENUM 0x00800000LU ///< Enumeration? +#define FF_0FOP 0x00900000LU ///< Forced operand? +#define FF_0STRO 0x00A00000LU ///< Struct offset? +#define FF_0STK 0x00B00000LU ///< Stack variable? +#define FF_0FLT 0x00C00000LU ///< Floating point number? +#define FF_0CUST 0x00D00000LU ///< Custom representation? + +#define MS_1TYPE 0x0F000000LU ///< Mask for the type of other operands +#define FF_1VOID 0x00000000LU ///< Void (unknown)? +#define FF_1NUMH 0x01000000LU ///< Hexadecimal number? +#define FF_1NUMD 0x02000000LU ///< Decimal number? +#define FF_1CHAR 0x03000000LU ///< Char ('x')? +#define FF_1SEG 0x04000000LU ///< Segment? +#define FF_1OFF 0x05000000LU ///< Offset? +#define FF_1NUMB 0x06000000LU ///< Binary number? +#define FF_1NUMO 0x07000000LU ///< Octal number? +#define FF_1ENUM 0x08000000LU ///< Enumeration? +#define FF_1FOP 0x09000000LU ///< Forced operand? +#define FF_1STRO 0x0A000000LU ///< Struct offset? +#define FF_1STK 0x0B000000LU ///< Stack variable? +#define FF_1FLT 0x0C000000LU ///< Floating point number? +#define FF_1CUST 0x0D000000LU ///< Custom representation? +//@} + +/// \defgroup FF_opfuncs1 Functions: examine operand flags (specific operands) +//@{ + +/// Is the first operand defined? Initially operand has no defined representation + +inline THREAD_SAFE bool idaapi is_defarg0(flags_t F) { return (F & MS_0TYPE) != FF_0VOID; } + + +/// Is the second operand defined? Initially operand has no defined representation + +inline THREAD_SAFE bool idaapi is_defarg1(flags_t F) { return (F & MS_1TYPE) != FF_1VOID; } + + +/// Is the first operand offset? (example: push offset xxx) + +inline THREAD_SAFE bool idaapi is_off0(flags_t F) { return (F & MS_0TYPE) == FF_0OFF; } + + +/// Is the second operand offset? (example: mov ax, offset xxx) + +inline THREAD_SAFE bool idaapi is_off1(flags_t F) { return (F & MS_1TYPE) == FF_1OFF; } + + +/// Is the first operand character constant? (example: push 'a') + +inline THREAD_SAFE bool idaapi is_char0(flags_t F) { return (F & MS_0TYPE) == FF_0CHAR; } + + +/// Is the second operand character constant? (example: mov al, 'a') + +inline THREAD_SAFE bool idaapi is_char1(flags_t F) { return (F & MS_1TYPE) == FF_1CHAR; } + + +/// Is the first operand segment selector? (example: push seg seg001) + +inline THREAD_SAFE bool idaapi is_seg0(flags_t F) { return (F & MS_0TYPE) == FF_0SEG; } + + +/// Is the second operand segment selector? (example: mov dx, seg dseg) + +inline THREAD_SAFE bool idaapi is_seg1(flags_t F) { return (F & MS_1TYPE) == FF_1SEG; } + + +/// Is the first operand a symbolic constant (enum member)? + +inline THREAD_SAFE bool idaapi is_enum0(flags_t F) { return (F & MS_0TYPE) == FF_0ENUM; } + + +/// Is the second operand a symbolic constant (enum member)? + +inline THREAD_SAFE bool idaapi is_enum1(flags_t F) { return (F & MS_1TYPE) == FF_1ENUM; } + + +/// Is the first operand an offset within a struct? + +inline THREAD_SAFE bool idaapi is_stroff0(flags_t F) { return (F & MS_0TYPE) == FF_0STRO; } + + +/// Is the second operand an offset within a struct? + +inline THREAD_SAFE bool idaapi is_stroff1(flags_t F) { return (F & MS_1TYPE) == FF_1STRO; } + + +/// Is the first operand a stack variable? + +inline THREAD_SAFE bool idaapi is_stkvar0(flags_t F) { return (F & MS_0TYPE) == FF_0STK; } + + +/// Is the second operand a stack variable? + +inline THREAD_SAFE bool idaapi is_stkvar1(flags_t F) { return (F & MS_1TYPE) == FF_1STK; } + + +/// Is the first operand a floating point number? + +inline THREAD_SAFE bool idaapi is_float0(flags_t F) { return (F & MS_0TYPE) == FF_0FLT; } + + +/// Is the second operand a floating point number? + +inline THREAD_SAFE bool idaapi is_float1(flags_t F) { return (F & MS_1TYPE) == FF_1FLT; } + + +/// Does the first operand use a custom data representation? + +inline THREAD_SAFE bool idaapi is_custfmt0(flags_t F) { return (F & MS_0TYPE) == FF_0CUST; } + + +/// Does the second operand use a custom data representation? + +inline THREAD_SAFE bool idaapi is_custfmt1(flags_t F) { return (F & MS_1TYPE) == FF_1CUST; } + + +/// Is the first operand a number (i.e. binary, octal, decimal or hex?) + +idaman bool ida_export is_numop0(flags_t F); + + +/// Is the second operand a number (i.e. binary, octal, decimal or hex?) + +idaman bool ida_export is_numop1(flags_t F); + + +/// Get flags for first operand + +inline THREAD_SAFE flags_t get_optype_flags0(flags_t F) { return F & MS_0TYPE; } + + +/// Get flags for second operand + +inline THREAD_SAFE flags_t get_optype_flags1(flags_t F) { return F & MS_1TYPE; } + +//@} FF_opfuncs1 + +//------------------------------------------------------------------------- +// +// The following 2 masks are used with operand numbers +// +#define OPND_OUTER 0x80 ///< outer offset base (combined with operand number). + ///< used only in set, get, del_offset() functions +#define OPND_MASK 0x0F ///< mask for operand number +#define OPND_ALL OPND_MASK ///< all operands + +/*! \defgroup FF_opfuncs2 Functions: examine operand flags (arbitrary operand) + For the following functions, 'n' may be: + - 0 : first operand + - 1 : second operand + - #OPND_ALL : both operands - function returns 1 if the first + OR the second operand satisfies the condition +*/ +//@{ +idaman bool ida_export is_defarg(flags_t F, int n); ///< is defined? +idaman bool ida_export is_off(flags_t F, int n); ///< is offset? +idaman bool ida_export is_char(flags_t F, int n); ///< is character constant? +idaman bool ida_export is_seg(flags_t F, int n); ///< is segment? +idaman bool ida_export is_enum(flags_t F, int n); ///< is enum? +idaman bool ida_export is_manual(flags_t F, int n); ///< is forced operand? (use is_forced_operand()) +idaman bool ida_export is_stroff(flags_t F, int n); ///< is struct offset? +idaman bool ida_export is_stkvar(flags_t F, int n); ///< is stack variable? +idaman bool ida_export is_fltnum(flags_t F, int n); ///< is floating point number? +idaman bool ida_export is_custfmt(flags_t F, int n); ///< is custom data format? +idaman bool ida_export is_numop(flags_t F, int n); ///< is number (bin, oct, dec, hex)? +idaman bool ida_export is_suspop(ea_t ea, flags_t F, int n); ///< is suspicious operand? +//@} + +/// Should processor module create xrefs from the operand?. +/// Currently 'offset' and 'structure offset' operands create xrefs + +idaman bool ida_export op_adds_xrefs(flags_t F, int n); + + +/// (internal function) change representation of operand(s). +/// \param ea linear address +/// \param type new flag value (should be obtained from char_flag(), num_flag() and +/// similar functions) +/// \param n number of operand (0, 1, -1) +/// \retval 1 ok +/// \retval 0 failed (applied to a tail byte) + +idaman bool ida_export set_op_type(ea_t ea, flags_t type, int n); + + +/// Set operand representation to be 'segment'. +/// If applied to unexplored bytes, converts them to 16/32bit word data +/// \param ea linear address +/// \param n number of operand (0, 1, -1) +/// \return success + +idaman bool ida_export op_seg(ea_t ea, int n); + + +/// Set operand representation to be 'enum_t'. +/// If applied to unexplored bytes, converts them to 16/32bit word data +/// \param ea linear address +/// \param n number of operand (0, 1, -1) +/// \param id id of enum +/// \param serial the serial number of the constant in the enumeration, +/// usually 0. the serial numbers are used if the enumeration +/// contains several constants with the same value +/// \return success + +idaman bool ida_export op_enum(ea_t ea, int n, enum_t id, uchar serial); + + +/// Get enum id of 'enum' operand. +/// \param ea linear address +/// \param n number of operand (0, 1, -1) +/// \param serial pointer to variable to hold the serial number of the +/// constant in the enumeration +/// \return id of enum or #BADNODE + +idaman enum_t ida_export get_enum_id(uchar *serial, ea_t ea, int n); + + +/// Set operand representation to be 'struct offset'. +/// If applied to unexplored bytes, converts them to 16/32bit word data +/// \param insn the instruction +/// \param n number of operand (0, 1, -1) +/// \param path structure path (strpath). see nalt.hpp for more info. +/// \param path_len length of the structure path +/// \param delta struct offset delta. usually 0. denotes the difference +/// between the structure base and the pointer into the structure. +/// \return success + +idaman bool ida_export op_stroff( + const insn_t &insn, + int n, + const tid_t *path, + int path_len, + adiff_t delta); + + +/// Get struct path of operand. +/// \param path buffer for structure path (strpath). see nalt.hpp for more info. +/// \param delta struct offset delta +/// \param ea linear address +/// \param n number of operand (0, 1, -1) +/// \return length of strpath + +idaman int ida_export get_stroff_path(tid_t *path, adiff_t *delta, ea_t ea, int n); + +/// Set operand representation to be 'stack variable'. +/// Should be applied to an instruction within a function. +/// Should be applied after creating a stack var using +/// insn_t::create_stkvar(). +/// \param ea linear address +/// \param n number of operand (0, 1, -1) +/// \return success + +idaman bool ida_export op_stkvar(ea_t ea, int n); + + +/// Set forced operand. +/// \param ea linear address +/// \param n number of operand (0, 1, 2) +/// \param op text of operand +/// - nullptr: do nothing (return 0) +/// - "" : delete forced operand +/// \return success + +idaman bool ida_export set_forced_operand(ea_t ea, int n, const char *op); + + +/// Get forced operand. +/// \param buf output buffer, may be nullptr +/// \param ea linear address +/// \param n number of operand (0, 1, 2) +/// \return size of forced operand or -1 + +idaman ssize_t ida_export get_forced_operand(qstring *buf, ea_t ea, int n); + + +/// Is operand manually defined?. +/// \param ea linear address +/// \param n number of operand (0, 1, 2) + +idaman bool ida_export is_forced_operand(ea_t ea, int n); + + +//------------------------------------------------------------------------- +/*! \defgroup FF_opfuncs3 Functions: get type information bits for flags + Values of these functions are used as input to set_op_type() function +*/ +//@{ +inline constexpr flags_t idaapi char_flag(void) { return FF_1CHAR|FF_0CHAR; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi off_flag(void) { return FF_1OFF |FF_0OFF; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi enum_flag(void) { return FF_1ENUM|FF_0ENUM; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi stroff_flag(void) { return FF_1STRO|FF_0STRO; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi stkvar_flag(void) { return FF_1STK |FF_0STK; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi flt_flag(void) { return FF_1FLT |FF_0FLT; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi custfmt_flag(void) { return FF_1CUST|FF_0CUST; } ///< see \ref FF_opbits +inline constexpr flags_t idaapi seg_flag(void) { return FF_1SEG |FF_0SEG; } ///< see \ref FF_opbits + +idaman flags_t ida_export num_flag(void); ///< Get number of default base (bin, oct, dec, hex) +/// Get number flag of the base, regardless of current processor - better to use num_flag() +inline constexpr flags_t idaapi hex_flag(void) { return FF_1NUMH|FF_0NUMH; } +inline constexpr flags_t idaapi dec_flag(void) { return FF_1NUMD|FF_0NUMD; } ///< \copydoc hex_flag() +inline constexpr flags_t idaapi oct_flag(void) { return FF_1NUMO|FF_0NUMO; } ///< \copydoc hex_flag() +inline constexpr flags_t idaapi bin_flag(void) { return FF_1NUMB|FF_0NUMB; } ///< \copydoc hex_flag() +//@} + +/*! \defgroup FF_opfuncs4 Functions: set operand representation + The following functions set operand representation. + If they are applied to unexplored bytes, they convert them. + - no segment : fail + - 16bit segment : to 16bit word data + - 32bit segment : to dword + \param ea linear address + \param n number of operand (0, 1, -1) + \return success +*/ +//@{ +inline bool idaapi op_chr(ea_t ea, int n) { return set_op_type(ea, char_flag(), n); } ///< set op type to char_flag() +inline bool idaapi op_num(ea_t ea, int n) { return set_op_type(ea, num_flag(), n); } ///< set op type to num_flag() +inline bool idaapi op_hex(ea_t ea, int n) { return set_op_type(ea, hex_flag(), n); } ///< set op type to hex_flag() +inline bool idaapi op_dec(ea_t ea, int n) { return set_op_type(ea, dec_flag(), n); } ///< set op type to dec_flag() +inline bool idaapi op_oct(ea_t ea, int n) { return set_op_type(ea, oct_flag(), n); } ///< set op type to oct_flag() +inline bool idaapi op_bin(ea_t ea, int n) { return set_op_type(ea, bin_flag(), n); } ///< set op type to bin_flag() +inline bool idaapi op_flt(ea_t ea, int n) { return set_op_type(ea, flt_flag(), n); } ///< set op type to flt_flag() +//@} + +/// Set custom data format for operand (fid-custom data format id) + +idaman bool ida_export op_custfmt(ea_t ea, int n, int fid); + + +/// Remove operand representation information. +/// (set operand representation to be 'undefined') +/// \param ea linear address +/// \param n number of operand (0, 1, -1) +/// \return success + +idaman bool ida_export clr_op_type(ea_t ea, int n); + + +/// Get default base of number for the current processor. +/// \return 2, 8, 10, 16 + +idaman int ida_export get_default_radix(void); + + +/// Get radix of the operand, in: flags. +/// If the operand is not a number, returns get_default_radix() +/// \param F flags +/// \param n number of operand (0, 1, -1) +/// \return 2, 8, 10, 16 + +idaman int ida_export get_radix(flags_t F, int n); + + +//------------------------------------------------------------------------- +/// \defgroup FF_databits Bits: data bytes +//@{ +#define DT_TYPE 0xF0000000 ///< Mask for DATA typing + +#define FF_BYTE 0x00000000 ///< byte +#define FF_WORD 0x10000000 ///< word +#define FF_DWORD 0x20000000 ///< double word +#define FF_QWORD 0x30000000 ///< quadro word +#define FF_TBYTE 0x40000000 ///< tbyte +#define FF_STRLIT 0x50000000 ///< string literal +#define FF_STRUCT 0x60000000 ///< struct variable +#define FF_OWORD 0x70000000 ///< octaword/xmm word (16 bytes/128 bits) +#define FF_FLOAT 0x80000000 ///< float +#define FF_DOUBLE 0x90000000 ///< double +#define FF_PACKREAL 0xA0000000 ///< packed decimal real +#define FF_ALIGN 0xB0000000 ///< alignment directive +// 0xC0000000 ///< reserved +#define FF_CUSTOM 0xD0000000 ///< custom data type +#define FF_YWORD 0xE0000000 ///< ymm word (32 bytes/256 bits) +#define FF_ZWORD 0xF0000000 ///< zmm word (64 bytes/512 bits) +//@} + +/// \defgroup FF_datafuncs1 Functions: examine data bits +//@{ +inline constexpr flags_t idaapi code_flag(void) { return FF_CODE; } ///< #FF_CODE +inline constexpr flags_t idaapi byte_flag(void) { return FF_DATA|FF_BYTE; } ///< Get a flags_t representing a byte +inline constexpr flags_t idaapi word_flag(void) { return FF_DATA|FF_WORD; } ///< Get a flags_t representing a word +inline constexpr flags_t idaapi dword_flag(void) { return FF_DATA|FF_DWORD; } ///< Get a flags_t representing a double word +inline constexpr flags_t idaapi qword_flag(void) { return FF_DATA|FF_QWORD; } ///< Get a flags_t representing a quad word +inline constexpr flags_t idaapi oword_flag(void) { return FF_DATA|FF_OWORD; } ///< Get a flags_t representing a octaword +inline constexpr flags_t idaapi yword_flag(void) { return FF_DATA|FF_YWORD; } ///< Get a flags_t representing a ymm word +inline constexpr flags_t idaapi zword_flag(void) { return FF_DATA|FF_ZWORD; } ///< Get a flags_t representing a zmm word +inline constexpr flags_t idaapi tbyte_flag(void) { return FF_DATA|FF_TBYTE; } ///< Get a flags_t representing a tbyte +inline constexpr flags_t idaapi strlit_flag(void) { return FF_DATA|FF_STRLIT; } ///< Get a flags_t representing a string literal +inline constexpr flags_t idaapi stru_flag(void) { return FF_DATA|FF_STRUCT; } ///< Get a flags_t representing a struct +inline constexpr flags_t idaapi cust_flag(void) { return FF_DATA|FF_CUSTOM; } ///< Get a flags_t representing custom type data +inline constexpr flags_t idaapi align_flag(void) { return FF_DATA|FF_ALIGN; } ///< Get a flags_t representing an alignment directive +inline constexpr flags_t idaapi float_flag(void) { return FF_DATA|FF_FLOAT; } ///< Get a flags_t representing a float +inline constexpr flags_t idaapi double_flag(void) { return FF_DATA|FF_DOUBLE; } ///< Get a flags_t representing a double +inline constexpr flags_t idaapi packreal_flag(void) { return FF_DATA|FF_PACKREAL; } ///< Get a flags_t representing a packed decimal real + +inline THREAD_SAFE bool idaapi is_byte(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_BYTE; } ///< #FF_BYTE +inline THREAD_SAFE bool idaapi is_word(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_WORD; } ///< #FF_WORD +inline THREAD_SAFE bool idaapi is_dword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_DWORD; } ///< #FF_DWORD +inline THREAD_SAFE bool idaapi is_qword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_QWORD; } ///< #FF_QWORD +inline THREAD_SAFE bool idaapi is_oword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_OWORD; } ///< #FF_OWORD +inline THREAD_SAFE bool idaapi is_yword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_YWORD; } ///< #FF_YWORD +inline THREAD_SAFE bool idaapi is_zword(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_ZWORD; } ///< #FF_ZWORD +inline THREAD_SAFE bool idaapi is_tbyte(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_TBYTE; } ///< #FF_TBYTE +inline THREAD_SAFE bool idaapi is_float(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_FLOAT; } ///< #FF_FLOAT +inline THREAD_SAFE bool idaapi is_double(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_DOUBLE; } ///< #FF_DOUBLE +inline THREAD_SAFE bool idaapi is_pack_real(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_PACKREAL; } ///< #FF_PACKREAL +inline THREAD_SAFE bool idaapi is_strlit(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_STRLIT; } ///< #FF_STRLIT +inline THREAD_SAFE bool idaapi is_struct(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_STRUCT; } ///< #FF_STRUCT +inline THREAD_SAFE bool idaapi is_align(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_ALIGN; } ///< #FF_ALIGN +inline THREAD_SAFE bool idaapi is_custom(flags_t F) { return is_data(F) && (F & DT_TYPE) == FF_CUSTOM; } ///< #FF_CUSTOM + +inline THREAD_SAFE bool idaapi f_is_byte(flags_t F, void *) { return is_byte(F); } ///< See is_byte() +inline THREAD_SAFE bool idaapi f_is_word(flags_t F, void *) { return is_word(F); } ///< See is_word() +inline THREAD_SAFE bool idaapi f_is_dword(flags_t F, void *) { return is_dword(F); } ///< See is_dword() +inline THREAD_SAFE bool idaapi f_is_qword(flags_t F, void *) { return is_qword(F); } ///< See is_qword() +inline THREAD_SAFE bool idaapi f_is_oword(flags_t F, void *) { return is_oword(F); } ///< See is_oword() +inline THREAD_SAFE bool idaapi f_is_yword(flags_t F, void *) { return is_yword(F); } ///< See is_yword() +inline THREAD_SAFE bool idaapi f_is_tbyte(flags_t F, void *) { return is_tbyte(F); } ///< See is_tbyte() +inline THREAD_SAFE bool idaapi f_is_float(flags_t F, void *) { return is_float(F); } ///< See is_float() +inline THREAD_SAFE bool idaapi f_is_double(flags_t F, void *) { return is_double(F); } ///< See is_double() +inline THREAD_SAFE bool idaapi f_is_pack_real(flags_t F, void *) { return is_pack_real(F); } ///< See is_pack_real() +inline THREAD_SAFE bool idaapi f_is_strlit(flags_t F, void *) { return is_strlit(F); } ///< See is_strlit() +inline THREAD_SAFE bool idaapi f_is_struct(flags_t F, void *) { return is_struct(F); } ///< See is_struct() +inline THREAD_SAFE bool idaapi f_is_align(flags_t F, void *) { return is_align(F); } ///< See is_align() +inline THREAD_SAFE bool idaapi f_is_custom(flags_t F, void *) { return is_custom(F); } ///< See is_custom() + + +/// Do the given flags specify the same data type? + +inline THREAD_SAFE bool idaapi is_same_data_type(flags_t F1, flags_t F2) { return ((F1 ^ F2) & DT_TYPE) == 0; } + + +/// Get flags from size (in bytes). +/// Supported sizes: 1, 2, 4, 8, 16, 32. +/// For other sizes returns 0 + +idaman flags_t ida_export get_flags_by_size(size_t size); +//@} FF_datafuncs1 + + +/// \defgroup FF_datafuncs2 Functions: manipulate data bits +/// \param ea linear address +/// \param length size of array in bytes. should be divisible by the size of +/// one item of the specified type. +/// \return success +//@{ + +/// Convert to data (byte, word, dword, etc). +/// This function may be used to create arrays. +/// \param ea linear address +/// \param dataflag type of data. Value of function byte_flag(), word_flag(), etc. +/// \param size size of array in bytes. should be divisible by the size of +/// one item of the specified type. for variable sized items +/// it can be specified as 0, and the kernel will try to calculate the size. +/// \param tid type id. If the specified type is a structure, +/// then tid is structure id. Otherwise should be #BADNODE. +/// \return success + +idaman bool ida_export create_data( + ea_t ea, + flags_t dataflag, + asize_t size, + tid_t tid); + + +inline THREAD_SAFE flags_t idaapi calc_dflags(flags_t f, bool force) { return f | (force ? FF_COMM : 0); } +/// Convert to byte +inline bool idaapi create_byte(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_BYTE, force), length, BADNODE); +} +/// Convert to word +inline bool idaapi create_word(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_WORD, force), length, BADNODE); +} +/// Convert to dword +inline bool idaapi create_dword(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_DWORD, force), length, BADNODE); +} +/// Convert to quadword +inline bool idaapi create_qword(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_QWORD, force), length, BADNODE); +} +/// Convert to octaword/xmm word +inline bool idaapi create_oword(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_OWORD, force), length, BADNODE); +} +/// Convert to ymm word +inline bool idaapi create_yword(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_YWORD, force), length, BADNODE); +} +/// Convert to zmm word +inline bool idaapi create_zword(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_ZWORD, force), length, BADNODE); +} +/// Convert to tbyte +inline bool idaapi create_tbyte(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_TBYTE, force), length, BADNODE); +} +/// Convert to float +inline bool idaapi create_float(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_FLOAT, force), length, BADNODE); +} +/// Convert to double +inline bool idaapi create_double(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_DOUBLE, force), length, BADNODE); +} +/// Convert to packed decimal real +inline bool idaapi create_packed_real(ea_t ea, asize_t length, bool force=false) +{ + return create_data(ea, calc_dflags(FF_PACKREAL, force), length, BADNODE); +} +/// Convert to struct +inline bool idaapi create_struct(ea_t ea, asize_t length, tid_t tid, bool force=false) +{ + return create_data(ea, calc_dflags(FF_STRUCT, force), length, tid); +} +/// Convert to custom data type +inline bool idaapi create_custdata(ea_t ea, asize_t length, int dtid, int fid, bool force=false) +{ + return create_data(ea, calc_dflags(FF_CUSTOM, force), length, dtid|(fid<<16)); +} + + +/// Create an alignment item. +/// \param ea linear address +/// \param length size of the item in bytes. 0 means to infer from ALIGNMENT +/// \param alignment alignment exponent. Example: 3 means align to 8 bytes. +/// 0 means to infer from LENGTH +/// It is forbidden to specify both LENGTH and ALIGNMENT as 0. +/// \return success + +idaman bool ida_export create_align(ea_t ea, asize_t length, int alignment); + +/// Calculate the minimal possible alignment exponent. +/// \param length size of the item in bytes. +/// \return a value in the 1..32 range + +idaman int ida_export calc_min_align(asize_t length); + + +/// Calculate the maximal possible alignment exponent. +/// \param endea end address of the alignment item. +/// \return a value in the 0..32 range + +idaman int ida_export calc_max_align(ea_t endea); + +/// Calculate the default alignment exponent. +/// \param ea linear address +/// \param mina minimal possible alignment exponent. +/// \param maxa minimal possible alignment exponent. + +idaman int ida_export calc_def_align(ea_t ea, int mina, int maxa); + + +/// Convert to 16-bit quantity (take the byte size into account) + +idaman bool ida_export create_16bit_data(ea_t ea, asize_t length); + + +/// Convert to 32-bit quantity (take the byte size into account) + +idaman bool ida_export create_32bit_data(ea_t ea, asize_t length); + + +//@} FF_datafuncs2 + +//@} FF_op + +/// \defgroup ALOPT_ string literal length options +/// passed as 'options' parameter to get_max_strlit_length() +//@{ +#define ALOPT_IGNHEADS 0x01 ///< don't stop if another data item is encountered. + ///< only the byte values will be used to determine + ///< the string length. + ///< if not set, a defined data item or instruction + ///< will truncate the string +#define ALOPT_IGNPRINT 0x02 ///< if set, don't stop at non-printable codepoints, + ///< but only at the terminating character (or not + ///< unicode-mapped character (e.g., 0x8f in CP1252)) +#define ALOPT_IGNCLT 0x04 ///< if set, don't stop at codepoints that are not + ///< part of the current 'culture'; accept all + ///< those that are graphical (this is typically + ///< used used by user-initiated actions creating + ///< string literals.) +#define ALOPT_MAX4K 0x08 ///< if string length is more than 4K, return the + ///< accumulated length + +//@} + +/// Determine maximum length of string literal. +/// +/// If the string literal has a length prefix (e.g., STRTYPE_LEN2 has +/// a two-byte length prefix), the length of that prefix (i.e., 2) +/// will be part of the returned value. +/// +/// \param ea starting address +/// \param strtype string type. one of \ref STRTYPE_ +/// \param options combination of \ref ALOPT_ +/// \return length of the string in octets (octet==8bit) + +idaman size_t ida_export get_max_strlit_length( + ea_t ea, + int32 strtype, + int options = 0); + +/// \defgroup STRCONV_ string conversion flags +/// passed as 'flags' parameter to get_strlit_contents() +//@{ +#define STRCONV_ESCAPE 0x00000001 ///< convert non-printable characters to C escapes (\n, \xNN, \uNNNN) +#define STRCONV_REPLCHAR 0x00000002 ///< convert non-printable characters to the Unicode replacement character (U+FFFD) +#define STRCONV_INCLLEN 0x00000004 ///< for Pascal-style strings, include the prefixing length byte(s) as C-escaped sequence +//@} + +/// Get contents of string literal, as UTF-8-encoded codepoints. +/// This function returns the displayed part of the string +/// It works even if the string has not been created in the database yet. +/// +/// If 'len' is size_t(-1), it will be computed like so: +/// - if a string literal is present at 'ea', get_item_size() * bytesize(ea) will be used +/// - otherwise, get_max_strlit_length(..., ALOPT_IGNHEADS) will be used +/// +/// About 'maxcps': this specifies a limit to the number of codepoints, +/// not bytes in the UTF-8 output buffer. So for example although U+4e12 +/// will use 3 bytes in the output buffer, it still counts as only 1 +/// character -- unless STRCONV_ESCAPE is used. +/// If 'STRCONV_ESCAPE' is used, U+4e12 will be converted to the string +/// "\u4E12", and will use 6 bytes in the output buffer and also count +/// as 6 codepoints. +/// +/// If 'STRCONV_REPLCHAR', any undecodable byte will re represented +/// as U+FFFD, occupy 3 bytes in the output buffer, and count for 1 codepoint. +/// +/// \param[out] utf8 output buffer +/// \param[in] ea linear address of the string +/// \param[in] len length of the string, in octets (octet=8bit) +/// \param[in] type type of the string. one of \ref STRTYPE_ +/// \param[in, out] maxcps maximum length of codepoints, after possible +/// escaping, in output buffer (not counting terminating zero) +/// on exit, will be set to 0 if string got truncated +/// can be nullptr if not needed +/// \param[in] flags combination of \ref STRCONV_ +/// \return length of generated text (in bytes) or -1 + +idaman ssize_t ida_export get_strlit_contents( + qstring *utf8, + ea_t ea, + size_t len, + int32 type, + size_t *maxcps = nullptr, + int flags = 0); + + +/// Convert to string literal and give a meaningful name. +/// 'start' may be higher than 'end', the kernel will swap them in this case +/// \param start starting address +/// \param len length of the string in bytes. +/// if 0, then get_max_strlit_length() will be used +/// to determine the length +/// \param strtype string type. one of \ref STRTYPE_ +/// \return success + +idaman bool ida_export create_strlit(ea_t start, size_t len, int32 strtype); + + + +//------------------------------------------------------------------------- +/// \defgroup PSTF_ flags for use with get_strlit_type_info +//@{ +#define PSTF_TNORM 0 ///< use normal name +#define PSTF_TBRIEF 1 ///< use brief name (e.g., in the 'Strings' window) +#define PSTF_TINLIN 2 ///< use 'inline' name (e.g., in the structures comments) +#define PSTF_TMASK 3 ///< type mask +#define PSTF_HOTKEY 0x4 ///< have hotkey markers part of the name +#define PSTF_ENC 0x8 ///< if encoding is specified, append it +//@} + + +/// Get string type information: the string type name (possibly +/// decorated with hotkey markers), and the tooltip. +/// +/// \param out the output buffer +/// \param strtype the string type +/// \param out_tooltip an optional output buffer for the tooltip +/// \param flags or'ed PSTF_* constants +/// \return length of generated text + +idaman bool ida_export print_strlit_type( + qstring *out, + int32 strtype, + qstring *out_tooltip = nullptr, + int flags = 0); + + +/// Get additional information about an operand representation. +/// \param buf buffer to receive the result. may not be nullptr +/// \param ea linear address of item +/// \param n number of operand, 0 or 1 +/// \param flags flags of the item +/// \return nullptr if no additional representation information + +idaman opinfo_t *ida_export get_opinfo( + opinfo_t *buf, + ea_t ea, + int n, + flags_t flags); + + +/// Set additional information about an operand representation. +/// This function is a low level one. Only the kernel should use it. +/// \param ea linear address of the item +/// \param n number of operand, 0 or 1 +/// \param flag flags of the item +/// \param ti additional representation information +/// \param suppress_events do not generate changing_op_type and op_type_changed events +/// \return success + +idaman bool ida_export set_opinfo( + ea_t ea, + int n, + flags_t flag, + const opinfo_t *ti, + bool suppress_events=false); + + +/// Get size of data type specified in flags 'F'. +/// \param ea linear address of the item +/// \param F flags +/// \param ti additional information about the data type. For example, +/// if the current item is a structure instance, +/// then ti->tid is structure id. Otherwise is ignored (may be nullptr). +/// If specified as nullptr, will be automatically retrieved from the database +/// \return +/// - byte : 1 +/// - word : 2 +/// - etc... +/// +/// If flags doesn't specify a data, then return 1 + +idaman asize_t ida_export get_data_elsize(ea_t ea, flags_t F, const opinfo_t *ti=nullptr); + + +/// Get full size of data type specified in flags 'F'. +/// takes into account processors with wide bytes +/// e.g. returns 2 for a byte element with 16-bit bytes +inline asize_t get_full_data_elsize(ea_t ea, flags_t F, const opinfo_t *ti=nullptr) +{ + asize_t nbytes = get_data_elsize(ea, F, ti); + return nbytes * bytesize(ea); +} + + +/// Is the item at 'ea' variable size?. +/// \param ea linear address of the item +/// \param F flags +/// \param ti additional information about the data type. For example, +/// if the current item is a structure instance, +/// then ti->tid is structure id. Otherwise is ignored (may be nullptr). +/// If specified as nullptr, will be automatically retrieved from the database +/// \param itemsize if not nullptr and the item is varsize, itemsize +/// will contain the calculated item size (for struct types, the minimal size is returned) +/// \retval 1 varsize item +/// \retval 0 fixed item +/// \retval -1 error (bad data definition) + +idaman int ida_export is_varsize_item( + ea_t ea, + flags_t F, + const opinfo_t *ti=nullptr, + asize_t *itemsize=nullptr); + + +/// Can define item (instruction/data) of the specified 'length', starting at 'ea'? +/// \note if there is an item starting at 'ea', this function ignores it +/// \note this function converts to unexplored all encountered data items +/// with fixup information. Should be fixed in the future. +/// \param flags if not 0, then the kernel will ignore the data types +/// specified by the flags and destroy them. For example: +/// <pre> +/// 1000 dw 5 +/// 1002 db 5 ; undef +/// 1003 db 5 ; undef +/// 1004 dw 5 +/// 1006 dd 5 +/// </pre> +/// can_define_item(1000, 6, 0) - false because of dw at 1004 \n +/// can_define_item(1000, 6, word_flag()) - true, word at 1004 is destroyed +/// \return 1-yes, 0-no +/// +/// This function may return 0 if: +/// - a new item would cross segment boundaries +/// - a new item would overlap with existing items (except items specified by 'flags') + +idaman bool ida_export can_define_item(ea_t ea, asize_t length, flags_t flags); + +/// \defgroup FF_CODE Code bytes +/// \ingroup FF_ +/// Represent characteristics of instructions +//@{ + +//------------------------------------------------------------------------- +/// \defgroup FF_codebits Bits: code bytes +//@{ +#define MS_CODE 0xF0000000LU ///< Mask for code bits +#define FF_FUNC 0x10000000LU ///< function start? +// 0x20000000LU // not used +#define FF_IMMD 0x40000000LU ///< Has Immediate value ? +#define FF_JUMP 0x80000000LU ///< Has jump table or switch_info? +//@} + +/// \defgroup FF_codefuncs Functions: work with code bits +//@{ + +/// Has immediate value? + +inline THREAD_SAFE bool idaapi has_immd(flags_t F) { return is_code(F) && (F & FF_IMMD) != 0; } + + +/// Is function start? + +inline THREAD_SAFE bool idaapi is_func(flags_t F) { return is_code(F) && (F & FF_FUNC) != 0; } + + +/// Set 'has immediate operand' flag. +/// Returns true if the #FF_IMMD bit was not set and now is set + +idaman bool ida_export set_immd(ea_t ea); + + +//@} FF_codefuncs +//@} FF_CODE + +//----------------------------------------------------------------------- +// Custom data type and format definitions +//----------------------------------------------------------------------- + +/// Information about a data type +struct data_type_t +{ + int cbsize; ///< size of this structure + void *ud; ///< user-defined data to be passed to callbacks + int props; ///< properties +#define DTP_NODUP 0x0001 ///< do not use dup construct + const char *name; ///< name of the data type. must be unique + const char *menu_name; ///< Visible data type name to use in menus + ///< if nullptr, no menu item will be created + const char *hotkey; ///< Hotkey for the corresponding menu item + ///< if nullptr, no hotkey will be associated with the menu item + const char *asm_keyword; ///< keyword to use for this type in the assembly + ///< if nullptr, the data type cannot be used in the listing + ///< it can still be used in cpuregs window + asize_t value_size; ///< size of the value in bytes + + /// Should this type be shown in UI menus + /// \return success + bool is_present_in_menus() const { return menu_name != nullptr && asm_keyword != nullptr; } + + /// May create data? nullptr means always may + /// \param ud user-defined data + /// \param ea address of the future item + /// \param nbytes size of the future item + bool (idaapi *may_create_at)( + void *ud, + ea_t ea, + size_t nbytes); + + /// This function is used to determine size of the (possible) item at 'ea'. + /// This callback is required only for varsize datatypes. + /// \param ud user-defined data + /// \param ea address of the item + /// \param maxsize maximal size of the item + /// \return 0 if no such item can be created/displayed + asize_t (idaapi *calc_item_size)( + void *ud, + ea_t ea, + asize_t maxsize); + +#ifndef SWIG + DECLARE_COMPARISONS(data_type_t); +#endif +}; + +/// Information about a data format +struct data_format_t +{ + int32 cbsize; ///< size of this structure + void *ud; ///< user-defined data to be passed to callbacks + int props; ///< properties (currently 0) + const char *name; ///< Format name, must be unique + const char *menu_name; ///< Visible format name to use in menus + ///< if nullptr, no menu item will be created + const char *hotkey; ///< Hotkey for the corresponding menu item + ///< if nullptr, no hotkey will be associated with the menu item + asize_t value_size; ///< size of the value in bytes + ///< 0 means any size is ok + ///< data formats that are registered for standard types (dtid 0) + ///< may be called with any value_size (instruction operands only) + int32 text_width; ///< Usual width of the text representation + ///< This value is used to calculate the width + ///< of the control to display values of this type + + /// Should this format be shown in UI menus + /// \return success + bool is_present_in_menus() const { return menu_name != nullptr; } + + /// Convert to colored string. + /// \param ud user-defined data + /// \param out output buffer. may be nullptr + /// \param value value to print. may not be nullptr + /// \param size size of value in 8-bit bytes + /// \param current_ea current address (BADADDR if unknown) + /// \param operand_num current operand number + /// \param dtid custom data type id (0-standard built-in data type) + /// \return success + bool (idaapi *print)( + void *ud, + qstring *out, + const void *value, + asize_t size, + ea_t current_ea, + int operand_num, + int dtid); + + /// Convert from uncolored string. + /// \param ud user-defined data + /// \param value output buffer. may be nullptr + /// \param input input string. may not be nullptr + /// \param current_ea current address (BADADDR if unknown) + /// \param operand_num current operand number (-1 if unknown) + /// \param errstr buffer for error message + /// \return success + bool (idaapi *scan)( + void *ud, + bytevec_t *value, + const char *input, + ea_t current_ea, + int operand_num, + qstring *errstr); + + /// Analyze custom data format occurrence + /// This callback can be used to create xrefs from the current item. + /// This callback may be missing. + /// \param ud user-defined data + /// \param current_ea current address (BADADDR if unknown) + /// \param operand_num current operand number + void (idaapi *analyze)( + void *ud, + ea_t current_ea, + int operand_num); + +#ifndef SWIG + DECLARE_COMPARISONS(data_format_t); +#endif +}; + + +/// Register a new data type. +/// \param dtinfo description of the new data type +/// \return > 0 : id of the new custom data type, +/// < 0 : error when the custom data type with the same name has +/// already been registered +/// \note dtid 0 is reserved for built-in data types. + +idaman int ida_export register_custom_data_type(const data_type_t *dtinfo); + + +/// Unregister a data type. +/// When the idb is closed, all custom data types are automatically +/// unregistered, but since it happens too late (plugin modules could +/// already be unloaded) one has to unregister custom data types explicitly. +/// The ids of unregistered custom data types remain allocated and when the +/// same name is reused to register a custom data type, it will get assigned +/// the same id. +/// \param dtid data type to unregister +/// \retval true ok +/// \retval false no such dtid + +idaman bool ida_export unregister_custom_data_type(int dtid); + + +/// Register a new data format. +/// \param dtform description of the new data format +/// \return > 0 : id of the new custom data format, +/// < 0 : error when the custom data format with the same name has +/// already been registered to the data type +/// \note dfid 0 is unused. + +idaman int ida_export register_custom_data_format(const data_format_t *dtform); + + +/// Unregister a data format. +/// \sa unregister_custom_data_type() +/// \param dfid data format to unregister +/// \retval true ok +/// \retval false no such dfid + +idaman bool ida_export unregister_custom_data_format(int dfid); + + +/// Get definition of a registered custom data type. +/// \param dtid data type id +/// \return data type definition or nullptr + +idaman const data_type_t *ida_export get_custom_data_type(int dtid); + + +/// Get definition of a registered custom data format. +/// \param dfid data format id +/// \return data format definition or nullptr + +idaman const data_format_t *ida_export get_custom_data_format(int dfid); + + +/// Attach the data format to the data type. +/// \param dtid data type id that can use the data format. +/// 0 means all standard data types. Such data formats can be +/// applied to any data item or instruction operands. For +/// instruction operands, the data_format_t::value_size check +/// is not performed by the kernel. +/// \param dfid data format id +/// \retval true ok +/// \retval false no such `dtid', or no such `dfid', or the data format has +/// already been attached to the data type + +idaman bool ida_export attach_custom_data_format(int dtid, int dfid); + + +/// Detach the data format from the data type. +/// Unregistering a custom data type detaches all attached data formats, +/// no need to detach them explicitly. You still need unregister them. +/// Unregistering a custom data format detaches it from all attached data +/// types. +/// \param dtid data type id to detach data format from +/// \param dfid data format id to detach +/// \retval true ok +/// \retval false no such `dtid', or no such `dfid', or the data format was +/// not attached to the data type + +idaman bool ida_export detach_custom_data_format(int dtid, int dfid); + + +/// Is the custom data format attached to the custom data type? +/// \param dtid data type id +/// \param dfid data format id +/// \return true or false + +idaman bool ida_export is_attached_custom_data_format(int dtid, int dfid); + +/// Get list of registered custom data type ids. +/// \param out buffer for the output. may be nullptr +/// \param min_size minimum value size +/// \param max_size maximum value size +/// \return number of custom data types with the specified size limits + +idaman int ida_export get_custom_data_types( + intvec_t *out, + asize_t min_size=0, + asize_t max_size=BADADDR); + + +/// Get list of attached custom data formats for the specified data type. +/// \param out buffer for the output. may be nullptr +/// \param dtid data type id +/// \return number of returned custom data formats. if error, returns -1 + +idaman int ida_export get_custom_data_formats(intvec_t *out, int dtid); + + +/// Get id of a custom data type. +/// \param name name of the custom data type +/// \return id or -1 + +idaman int ida_export find_custom_data_type(const char *name); + + +/// Get id of a custom data format. +/// \param name name of the custom data format +/// \return id or -1 + +idaman int ida_export find_custom_data_format(const char *name); + + +//-------------------------------------------------------------------------- +// I N D E N T E D C O M M E N T S +//-------------------------------------------------------------------------- + +/// Set an indented comment. +/// \param ea linear address +/// \param comm comment string +/// - nullptr: do nothing (return 0) +/// - "" : delete comment +/// \param rptble is repeatable? +/// \return success + +idaman bool ida_export set_cmt(ea_t ea, const char *comm, bool rptble); + + +/// Get an indented comment. +/// \param buf output buffer, may be nullptr +/// \param ea linear address. may point to tail byte, the function +/// will find start of the item +/// \param rptble get repeatable comment? +/// \return size of comment or -1 + +idaman ssize_t ida_export get_cmt(qstring *buf, ea_t ea, bool rptble); + + +/// Append to an indented comment. +/// Creates a new comment if none exists. +/// Appends a newline character and the specified string otherwise. +/// \param ea linear address +/// \param str comment string to append +/// \param rptble append to repeatable comment? +/// \return success + +idaman bool ida_export append_cmt(ea_t ea, const char *str, bool rptble); + + +//-------------------------------------------------------------------- +// P R E D E F I N E D C O M M E N T S +//-------------------------------------------------------------------- + +/// Get predefined comment. +/// \param buf buffer for the comment +/// \param ins current instruction information +/// \return size of comment or -1 + +idaman ssize_t ida_export get_predef_insn_cmt( + qstring *buf, + const insn_t &ins); + + +//-------------------------------------------------------------------------- +// S E A R C H F U N C T I O N S +//-------------------------------------------------------------------------- +/// Find forward a byte with the specified value (only 8-bit value from the database). +/// example: ea=4 size=3 will inspect addresses 4, 5, and 6 +/// \param sEA linear address +/// \param size number of bytes to inspect +/// \param value value to find +/// \param bin_search_flags combination of \ref BIN_SEARCH_ +/// \return address of byte or #BADADDR + +idaman ea_t ida_export find_byte(ea_t sEA, asize_t size, uchar value, int bin_search_flags); + + +/// Find reverse a byte with the specified value (only 8-bit value from the database). +/// example: ea=4 size=3 will inspect addresses 6, 5, and 4 +/// \param sEA the lower address of the search range +/// \param size number of bytes to inspect +/// \param value value to find +/// \param bin_search_flags combination of \ref BIN_SEARCH_ +/// \return address of byte or #BADADDR + +idaman ea_t ida_export find_byter(ea_t sEA, asize_t size, uchar value, int bin_search_flags); + + +//------------------------------------------------------------------------- +struct compiled_binpat_t // compiled binary pattern compiled_binpat_t +{ + bytevec_t bytes; + bytevec_t mask; + rangevec_t strlits; // range of string literals, in _bytes_ ranges (not CPs) + int encidx; + + compiled_binpat_t() : encidx(-1) {} + bool all_bytes_defined() const { return mask.empty(); } + void qclear() { bytes.qclear(); mask.qclear(); strlits.qclear(); encidx = -1; } + + bool operator==(const compiled_binpat_t &r) const + { + return bytes == r.bytes + && mask == r.mask + && strlits == r.strlits + && encidx == r.encidx; + } + bool operator!=(const compiled_binpat_t &r) const { return !(*this == r); } +}; +DECLARE_TYPE_AS_MOVABLE(compiled_binpat_t); +typedef qvector<compiled_binpat_t> compiled_binpat_vec_t; + +#define PBSENC_DEF1BPU 0 /// Use the default 1 byte-per-unit IDB encoding +#define PBSENC_ALL -1 /// Use all IDB encodings + +/// Convert user-specified binary string to internal representation. +/// The 'in' parameter contains space-separated tokens: +/// \code +/// - numbers (numeric base is determined by 'radix') +/// - if value of number fits a byte, it is considered as a byte +/// - if value of number fits a word, it is considered as 2 bytes +/// - if value of number fits a dword,it is considered as 4 bytes +/// - "..." string constants +/// - 'x' single-character constants +/// - ? variable bytes +/// \endcode +/// +/// Note that string constants are surrounded with double quotes. +/// +/// Here are a few examples (assuming base 16): +/// \code +/// CD 21 - bytes 0xCD, 0x21 +/// 21CD - bytes 0xCD, 0x21 (little endian ) or 0x21, 0xCD (big-endian) +/// "Hello", 0 - the null terminated string "Hello" +/// L"Hello" - 'H', 0, 'e', 0, 'l', 0, 'l', 0, 'o', 0 +/// B8 ? ? ? ? 90 - byte 0xB8, 4 bytes with any value, byte 0x90 +/// \endcode +/// \param [out] out a vector of compiled binary patterns, for use with bin_search2() +/// \param ea linear address to convert for (the conversion depends on the +/// address, because the number of bits in a byte depend on the +/// segment type) +/// \param in input text string +/// \param radix numeric base of numbers (8,10,16) +/// \param strlits_encoding the target encoding into which the string +/// literals present in 'in', should be encoded. +/// Can be any from [1, get_encoding_qty()), or +/// the special values PBSENC_* +/// \param errbuf error buffer (can be nullptr) +/// \return false either in case of parsing error, or if at least one +/// requested target encoding couldn't encode the string +/// literals present in "in". +// true otherwise +idaman bool ida_export parse_binpat_str( + compiled_binpat_vec_t *out, + ea_t ea, + const char *in, + int radix, + int strlits_encoding=PBSENC_DEF1BPU, + qstring *errbuf=nullptr); + + +/// Search for a string in the program. +/// \param start_ea linear address, start of range to search +/// \param end_ea linear address, end of range to search (exclusive) +/// \param data the prepared data to search for (see parse_binpat_str()) +/// \param flags combination of \ref BIN_SEARCH_ +/// \return #BADADDR (if pressed Ctrl-Break or not found) or string address. + +idaman ea_t ida_export bin_search2( + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &data, + int flags); + +inline ea_t bin_search2( + ea_t start_ea, + ea_t end_ea, + const uchar *image, + const uchar *mask, + size_t len, + int flags) +{ + compiled_binpat_vec_t bbv; + compiled_binpat_t &bv = bbv.push_back(); + bv.bytes.append(image, len); + if ( mask != nullptr ) + bv.mask.append(mask, len); + return bin_search2(start_ea, end_ea, bbv, flags); +} + +//t +/// \defgroup BIN_SEARCH_ Search flags +/// passed as 'flags' parameter to bin_search() +//@{ +#define BIN_SEARCH_CASE 0x01 ///< case sensitive +#define BIN_SEARCH_NOCASE 0x00 ///< case insensitive +#define BIN_SEARCH_NOBREAK 0x02 ///< don't check for Ctrl-Break +#define BIN_SEARCH_INITED 0x04 ///< find_byte, find_byter: any initilized value +#define BIN_SEARCH_NOSHOW 0x08 ///< don't show search progress or update screen +#define BIN_SEARCH_FORWARD 0x00 ///< search forward for bytes +#define BIN_SEARCH_BACKWARD 0x10 ///< search backward for bytes +//@} + + +/// Find the next initialized address + +inline ea_t idaapi next_inited(ea_t ea, ea_t maxea) +{ + if ( ea >= maxea ) + return BADADDR; + ++ea; + return find_byte(ea, maxea-ea, 0, BIN_SEARCH_INITED); +} + +/// Find the previous initialized address + +inline ea_t idaapi prev_inited(ea_t ea, ea_t minea) +{ + if ( ea <= minea ) + return BADADDR; + --ea; + return find_byter(minea, ea-minea, 0, BIN_SEARCH_INITED); +} + +/// Compare 'len' bytes of the program starting from 'ea' with 'image'. +/// \param ea linear address +/// \param image bytes to compare with +/// \param mask array of 1/0 bytes, it's length is 'len'. 1 means to perform +/// the comparison of the corresponding byte. 0 means not to perform. +/// if mask == nullptr, then all bytes of 'image' will be compared. +/// if mask == #SKIP_FF_MASK then 0xFF bytes will be skipped +/// \param len length of block to compare in bytes. +/// \param sense_case case-sensitive comparison? +/// \retval 1 equal +/// \retval 0 not equal + +idaman bool ida_export equal_bytes( + ea_t ea, + const uchar *image, + const uchar *mask, + size_t len, + bool sense_case); + +/// Used by equal_bytes() to skip 0xFF when searching the program +#define SKIP_FF_MASK ((const uchar *)0xFF) + + + +//------------------------------------------------------------------------ +// H I D D E N A R E A S +//------------------------------------------------------------------------ + +/// Hidden ranges - address ranges which can be replaced by their descriptions. +/// There is also a possibility to hide individual items completely (nalt.hpp, hide_item) +/// \note After modifying any of this struct's fields please call update_hidden_range() + +struct hidden_range_t : public range_t +{ + char *description; ///< description to display if the range is collapsed + char *header; ///< header lines to display if the range is expanded + char *footer; ///< footer lines to display if the range is expanded + bool visible; ///< the range state + bgcolor_t color; ///< range color +}; + +/// Update hidden range information in the database. +/// You cannot use this function to change the range boundaries +/// \param ha range to update +/// \return success + +idaman bool ida_export update_hidden_range(const hidden_range_t *ha); + + +/// Mark a range of addresses as hidden. +/// The range will be created in the invisible state with the default color +/// \param ea1 linear address of start of the address range +/// \param ea2 linear address of end of the address range +/// \param description, header, footer range parameters +/// \return success + +idaman bool ida_export add_hidden_range( + ea_t ea1, + ea_t ea2, + const char *description, + const char *header, + const char *footer, + bgcolor_t color); + + +/// Get pointer to hidden range structure, in: linear address. +/// \param ea any address in the hidden range + +idaman hidden_range_t *ida_export get_hidden_range(ea_t ea); + + +/// Get pointer to hidden range structure, in: number of hidden range. +/// \param n number of hidden range, is in range 0..get_hidden_range_qty()-1 + +idaman hidden_range_t *ida_export getn_hidden_range(int n); + + +/// Get number of hidden ranges + +idaman int ida_export get_hidden_range_qty(void); + + +/// Get number of a hidden range. +/// \param ea any address in the hidden range +/// \return number of hidden range (0..get_hidden_range_qty()-1) + +idaman int ida_export get_hidden_range_num(ea_t ea); + + +/// Get pointer to previous hidden range. +/// \param ea any address in the program +/// \return ptr to hidden range or nullptr if previous hidden range doesn't exist + +idaman hidden_range_t *ida_export get_prev_hidden_range(ea_t ea); + + +/// Get pointer to next hidden range. +/// \param ea any address in the program +/// \return ptr to hidden range or nullptr if next hidden range doesn't exist + +idaman hidden_range_t *ida_export get_next_hidden_range(ea_t ea); + + +/// Get pointer to the first hidden range. +/// \return ptr to hidden range or nullptr + +idaman hidden_range_t *ida_export get_first_hidden_range(void); + + +/// Get pointer to the last hidden range. +/// \return ptr to hidden range or nullptr + +idaman hidden_range_t *ida_export get_last_hidden_range(void); + + +/// Delete hidden range. +/// \param ea any address in the hidden range +/// \return success + +idaman bool ida_export del_hidden_range(ea_t ea); + + +//-------------------------------------------------------------------------- +inline ea_t idaapi get_item_head(ea_t ea) +{ + if ( is_tail(get_flags(ea)) ) + ea = prev_not_tail(ea); + return ea; +} + +//------------------------------------------------------------------------ +// M E M O R Y M A P P I N G +//------------------------------------------------------------------------ + +/// IDA supports memory mapping. References to the addresses from +/// the mapped range use data and meta-data from the mapping range. +/// \note You should set flag PR2_MAPPING in ph.flag2 to use memory mapping + + +/// Add memory mapping range. +/// \param from start of the mapped range (nonexistent address) +/// \param to start of the mapping range (existent address) +/// \param size size of the range +/// \return success + +idaman bool ida_export add_mapping(ea_t from, ea_t to, asize_t size); + + +/// Delete memory mapping range. +/// \param ea any address in the mapped range + +idaman void ida_export del_mapping(ea_t ea); + + +/// Translate address according to current mappings. +/// \param ea address to translate +/// \return translated address + +idaman ea_t ida_export use_mapping(ea_t ea); + +/// Get number of mappings. + +idaman size_t ida_export get_mappings_qty(void); + +/// Get memory mapping range by its number. +/// \param from start of the mapped range +/// \param to start of the mapping range +/// \param size size of the range +/// \param n number of mapping range (0..get_mappings_qty()-1) +/// \return false if the specified range doesn't exist, +/// otherwise returns `from', `to', `size' +idaman bool ida_export get_mapping( + ea_t *from, + ea_t *to, + asize_t *size, + size_t n); + + +#ifndef BYTES_SOURCE // undefined bit masks so no one can use them directly +#undef MS_VAL +#undef FF_IVL +#undef MS_CLS +#undef FF_CODE +#undef FF_DATA +#undef FF_TAIL +#undef FF_UNK +#undef MS_COMM +#undef FF_COMM +#undef FF_REF +#undef FF_LINE +#undef FF_NAME +#undef FF_LABL +#undef FF_ANYNAME +#undef FF_FLOW +#undef FF_SIGN +#undef FF_BNOT +#undef MS_0TYPE +#undef FF_0VOID +#undef FF_0NUMH +#undef FF_0NUMD +#undef FF_0CHAR +#undef FF_0SEG +#undef FF_0OFF +#undef FF_0NUMB +#undef FF_0NUMO +#undef FF_0ENUM +#undef FF_0FOP +#undef FF_0STRO +#undef FF_0STK +#undef FF_0FLT +#undef FF_0CUST +#undef MS_1TYPE +#undef FF_1VOID +#undef FF_1NUMH +#undef FF_1NUMD +#undef FF_1CHAR +#undef FF_1SEG +#undef FF_1OFF +#undef FF_1NUMB +#undef FF_1NUMO +#undef FF_1ENUM +#undef FF_1FOP +#undef FF_1STRO +#undef FF_1STK +#undef FF_1FLT +#undef FF_1CUST +#undef DT_TYPE +#undef FF_BYTE +#undef FF_WORD +#undef FF_DWORD +#undef FF_QWORD +#undef FF_OWORD +#undef FF_YWORD +#undef FF_ZWORD +#undef FF_FLOAT +#undef FF_DOUBLE +#undef FF_TBYTE +#undef FF_PACKREAL +#undef FF_STRLIT +#undef FF_STRUCT +#undef FF_ALIGN +#undef FF_CUSTOM +#undef MS_CODE +#undef FF_FUNC +#undef FF_IMMD +//#undef FF_JUMP +#undef MS_TAIL +#undef TL_TSFT +#undef TL_TOFF +#undef MAX_TOFF +#endif // BYTES_SOURCE + +// byte array to hex string +inline THREAD_SAFE ssize_t get_hex_string(char *buf, size_t bufsize, const uchar *bytes, size_t len) +{ + const char *const start = buf; + const char *const end = buf + bufsize; + for ( size_t i = 0; i < len; i++ ) + buf += ::qsnprintf(buf, end - buf, "%02X", *bytes++); + return buf - start; +} + + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED ea_t ida_export bin_search(ea_t, ea_t, const uchar *, const uchar *, size_t, int, int); // use bin_search2() +idaman DEPRECATED uchar ida_export get_8bit(ea_t *ea, uint32 *v, int *nbit); // use get_octet() +#endif + + +#endif // BYTES_HPP diff --git a/idasdk76/include/compress.hpp b/idasdk76/include/compress.hpp new file mode 100644 index 0000000..38519a6 --- /dev/null +++ b/idasdk76/include/compress.hpp @@ -0,0 +1,173 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef COMPRESS_HPP +#define COMPRESS_HPP + +#include <diskio.hpp> + +/*! \file compress.hpp + + \brief Data compression functions + +*/ + +/// Compress data. +/// This function depends on the value of legacy_idb, so it is not completely +/// thread safe. However, legacy_idb does not change its value. +/// \return \ref PKZ_ + +idaman THREAD_SAFE int ida_export zip_deflate( + void *ud, + ssize_t (idaapi *file_reader)(void *ud, void *buf, size_t size), + ssize_t (idaapi *file_writer)(void *ud, const void *buf, size_t size)); + + +/// Uncompress data. +/// This function depends on the value of legacy_idb, so it is not completely +/// thread safe. However, legacy_idb does not change its value. +/// \return \ref PKZ_ + +idaman THREAD_SAFE int ida_export zip_inflate( + void *ud, + ssize_t (idaapi *file_reader)(void *ud, void *buf, size_t size), + ssize_t (idaapi *file_writer)(void *ud, const void *buf, size_t size)); + + +/// Process zip file and enumerate all files stored in it +/// \param zipfile name of zip file +/// \param callback callback for each file. params: +/// - ud: user data +/// - offset: offset in the zip file +/// - method: compression method (\ref compression_methods) +/// - csize: compressed size +/// - ucsize: uncompressed size +/// - attributes: file attributes +/// \param ud user data +/// \return \ref PKZ_ + +idaman THREAD_SAFE int ida_export process_zipfile( + const char *zipfile, + int (idaapi *callback)( + void *ud, + qoff64_t offset, + int method, + uint64 csize, + uint64 ucsize, + uint32 attributes, + const char *filename), + void *ud = NULL); + + +/// Process zip file and enumerate all files stored in it +/// \param li input file +/// \param callback callback for each file. params: +/// - ud: user data +/// - offset: offset in the zip file +/// - method: compression method (\ref compression_methods) +/// - csize: compressed size +/// - ucsize: uncompressed size +/// - attributes: file attributes +/// \param ud user data +/// \return \ref PKZ_ + +idaman THREAD_SAFE int ida_export process_zip_linput( + linput_t *li, + int (idaapi *callback)( + void *ud, + qoff64_t offset, + int method, + uint64 csize, + uint64 ucsize, + uint32 attributes, + const char *filename), + void *ud = NULL); + + +/// Search for specified entry in zip file, and calls the +/// callback with it, if found. +/// \param zipfile name of zip file +/// \param entry entry in zip file. E.g., "path/to/entry.dat" +/// \param callback callback for each file. params: +/// - ud: user data +/// - offset: offset in the zip file +/// - method: compression method (\ref compression_methods) +/// - csize: compressed size +/// - ucsize: uncompressed size +/// - attributes: file attributes +/// \param ud user data +/// \param case_sensitive should the search be case sensitive? +/// \return \ref PKZ_ + +idaman THREAD_SAFE int ida_export process_zipfile_entry( + const char *zipfile, + const char *entry, + int (idaapi *callback)( + void *ud, + qoff64_t offset, + int method, + uint64 csize, + uint64 ucsize, + uint32 attributes, + const char *filename), + void *ud = NULL, + bool case_sensitive = true); + + +/// \defgroup PKZ_ Compression error codes +/// Returned by functions in compress.hpp +//@{ +#define PKZ_OK 0 +#define PKZ_ERRNO 1 +#define PKZ_STREAM_ERROR 2 +#define PKZ_DATA_ERROR 3 +#define PKZ_MEM_ERROR 4 +#define PKZ_BUF_ERROR 5 +#define PKZ_VERSION_ERROR 6 +#define PKZ_RERR 777 // read error +#define PKZ_WERR 778 // write error +//@} + +/// \defgroup compression_methods Compression methods +/// passed as 'method' parameter to callback functions in compress.hpp +//@{ +#define STORED 0 +#define SHRUNK 1 +#define REDUCED1 2 +#define REDUCED2 3 +#define REDUCED3 4 +#define REDUCED4 5 +#define IMPLODED 6 +#define TOKENIZED 7 +#define DEFLATED 8 +#define NUM_METHODS 9 /* index of last method + 1 */ +//@} + +extern bool legacy_idb; ///< for old idb files + +/// Upon closing outer linput, perform one of these actions +enum linput_close_code_t +{ + LOC_CLOSE, ///< close the inner linput + LOC_UNMAKE, ///< unmake the inner linput + LOC_KEEP, ///< do nothing +}; + + +/// Create a linput to read a compressed input stream +/// \param in linput with compressed data, seeked to the stream beginning +/// \param insize size of compressed data. -1 - unknown +/// \param loc what to do upon closing the resulting linput +/// \return linput that can be used to read uncompressed data. +/// NULL if any error (no more linput descriptors). + +idaman THREAD_SAFE linput_t *ida_export create_zip_linput( + linput_t *in, + ssize_t insize=-1, + linput_close_code_t loc=LOC_CLOSE); + +#endif diff --git a/idasdk76/include/config.hpp b/idasdk76/include/config.hpp new file mode 100644 index 0000000..1efa3c5 --- /dev/null +++ b/idasdk76/include/config.hpp @@ -0,0 +1,543 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _CONFIG_HPP +#define _CONFIG_HPP + +//----------------------------------------------------------------------- +/// \defgroup IDPOPT_T Option value types +/// Passed as 'value_type' parameter to ::set_options_t callbacks +//@{ +#define IDPOPT_STR 1 ///< string constant (char *) +#define IDPOPT_NUM 2 ///< number (uval_t *) +#define IDPOPT_BIT 3 ///< bit, yes/no (int *) +#define IDPOPT_I64 5 ///< 64bit number (int64 *) +#define IDPOPT_CST 6 ///< lexer (lexer_t*) + ///< Custom type, starting with a '{' + ///< Values of this type should be handled by + ///< ::set_options_t callbacks. E.g.,: + ///< \code + ///< ERROR_STRINGS = + ///< { + ///< {0, "Unknown error"}, + ///< {1, "Missing filename"}, + ///< {5, "Out-of-memory"} + ///< } + ///< \endcode + ///< For values of this type, the data that will + ///< be passed as the callback's 'value' parameter + ///< is the lexer instance that is being used + ///< to parse the configuration file. + ///< You can use \ref parse_json() (see parsejson.hpp) + ///< to parse JSON-format data + ///< NB: the '{' is already consumed by the parser, + ///< so you need to push it again if it's a part of the JSON object +//@} + +/// \defgroup IDPOPT_RET Option result codes +/// Predefined return values for ::set_options_t callbacks +//@{ +#define IDPOPT_OK NULL ///< ok +#define IDPOPT_BADKEY ((char*)1) ///< illegal keyword +#define IDPOPT_BADTYPE ((char*)2) ///< illegal type of value +#define IDPOPT_BADVALUE ((char*)3) ///< illegal value (bad range, for example) +//@} + + +/// Callback - called when a config directive is processed in IDA. +/// Also see read_config_file() and processor_t::set_idp_options +/// \param keyword keyword encountered in IDA.CFG/user config file. +/// if NULL, then an interactive dialog form should be displayed +/// \param value_type type of value of the keyword - one of \ref IDPOPT_T +/// \param value pointer to value +/// \param idb_loaded true if the ev_oldfile/ev_newfile events have been generated? +/// \return one of \ref IDPOPT_RET, otherwise a pointer to an error message + +typedef const char *(idaapi set_options_t)( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded); + +/// \defgroup IDAOPT_PRIO Option priority +/// Specifies the priority of a configuration option. Since options may +/// be specified in different way, and applied in various orders, we need +/// option priorities. +/// Normally the default priority option does not overwrite the existing value +/// whereas the high priority one does. +/// High priority options may be stored in the database to be available +/// in the next session. +//@{ +#define IDPOPT_PRI_DEFAULT 1 ///< default priority - taken from config file +#define IDPOPT_PRI_HIGH 2 ///< high priority - received from UI or a script function +//@} + + +//------------------------------------------------------------------------- +/// Parse the value type for the value token 'value'. +/// This is mostly used for converting from values that a cfgopt_handler_t +/// receives, into data that callbacks +/// - processor_t::set_idp_options +/// - debugger_t::set_dbg_options +/// expect. +/// +/// Plugins that wish to use options shouldn't rely on this, +/// and use the cfgopt_t utility instead. +/// +/// \param out parsed data +/// \param lx the lexer in use +/// \param value the value token +/// \return true if guessing didn't lead to an error, false otherwise. +/// note that even if 'true' is returned, it doesn't mean the +/// type could be guessed: merely that no syntax error occurred. +class lexer_t; +struct token_t; +idaman bool ida_export parse_config_value( + idc_value_t *out, + lexer_t *lx, + const token_t &value); + +//------------------------------------------------------------------------- +typedef const char *(idaapi cfgopt_handler_t)( + lexer_t *lx, + const token_t &keyword, + const token_t &value); + +//------------------------------------------------------------------------- +typedef const char *(idaapi cfgopt_handler2_t)( + lexer_t *lx, + const token_t &keyword, + const token_t &value, + int64 param1, + int64 param2); + +//------------------------------------------------------------------------- +typedef const char *(idaapi cfgopt_handler3_t)( + lexer_t *lx, + const token_t &keyword, + const token_t &value, + int64 param1, + int64 param2, + void *obj); + +//----------------------------------------------------------------------- +/// used by cfgopt_t. You shouldn't have to deal with those directly. +#define IDPOPT_NUM_INT (0) +#define IDPOPT_NUM_CHAR (1 << 24) +#define IDPOPT_NUM_SHORT (2 << 24) +#define IDPOPT_NUM_RANGE (1 << 26) +#define IDPOPT_NUM_UNS (1 << 27) + +#define IDPOPT_BIT_UINT 0 +#define IDPOPT_BIT_UCHAR (1 << 24) +#define IDPOPT_BIT_USHORT (2 << 24) +#define IDPOPT_BIT_BOOL (3 << 24) + +#define IDPOPT_STR_QSTRING (1 << 24) +#define IDPOPT_STR_LONG (1 << 25) + +#define IDPOPT_I64_RANGES (1 << 24) +#define IDPOPT_I64_UNS (1 << 25) + +#define IDPOPT_CST_PARAMS (1 << 24) + +#define IDPOPT_MBROFF (1 << 18) + +//------------------------------------------------------------------------- +struct cfgopt_t; +idaman const char *ida_export cfgopt_t__apply( + const cfgopt_t *_this, + int vtype, + const void *vdata); +idaman const char *ida_export cfgopt_t__apply2( + const cfgopt_t *_this, + int vtype, + const void *vdata, + void *obj); + +//------------------------------------------------------------------------- +// cfgopt_t objects are suitable for being statically initialized, and +// passed to 'read_config_file'. +// +// E.g., +// --- +// static const cfgopt_t g_opts[] = +// { +// cfgopt_t("AUTO_UNDEFINE", &auto_undefine, -1, 1), +// cfgopt_t("NOVICE", &novice, true), +// cfgopt_t("EDITOR", editor_buf, sizeof(editor_buf)), +// cfgopt_t("SCREEN_PALETTE", set_screen_palette), // specific handler for SCREEN_PALETTE +// }; +// +// ... +// +// read_config_file("myfile", g_opts, qnumber(g_opts), other_handler) +// --- +// +// NOTES: +// * so-called 'long' strings (the default) can span on multiple lines, +// and are terminated by a ';' +struct cfgopt_t +{ + const char *name; + union + { + void *ptr; + size_t mbroff; // offset of a structure member + cfgopt_handler_t *hnd; // to avoid reinterpret_cast and gcc's error: + cfgopt_handler2_t *hnd2; // "a reinterpret_cast is not a constant expression" + cfgopt_handler3_t *hnd3; // + }; + int flags; + struct num_range_t + { + constexpr num_range_t(int64 _min, int64 _max) : minval(_min), maxval(_max) {} + int64 minval; + int64 maxval; + }; + struct params_t + { + constexpr params_t(int64 _p1, int64 _p2) : p1(_p1), p2(_p2) {} + int64 p1; + int64 p2; + }; + union + { + size_t buf_size; + num_range_t num_range; + uint32 bit_flags; + params_t params; + void *mbroff_obj; + }; + + // IDPOPT_STR + constexpr cfgopt_t(const char *_n, char *_p, size_t _sz, bool _long = true) + : name(_n), ptr(_p), flags(IDPOPT_STR | (_long ? IDPOPT_STR_LONG : 0)), buf_size(_sz) + {} + constexpr cfgopt_t(const char *_n, qstring *_p, bool _long = true) + : name(_n), ptr(_p), flags(IDPOPT_STR | IDPOPT_STR_QSTRING | (_long ? IDPOPT_STR_LONG : 0)), buf_size(0) + {} + + // IDPOPT_NUM + constexpr cfgopt_t(const char *_n, int *_p) + : name(_n), ptr(_p), flags(IDPOPT_NUM), buf_size(0) {} + constexpr cfgopt_t(const char *_n, uint *_p) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS), buf_size(0) {} + constexpr cfgopt_t(const char *_n, char *_p) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_CHAR), buf_size(0) {} + constexpr cfgopt_t(const char *_n, uchar *_p) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_CHAR), buf_size(0) {} + constexpr cfgopt_t(const char *_n, short *_p) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_SHORT), buf_size(0) {} + constexpr cfgopt_t(const char *_n, ushort *_p) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_SHORT), buf_size(0) {} + // IDPOPT_NUM + ranges + constexpr cfgopt_t(const char *_n, int *_p, int _min, int _max) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_RANGE), num_range(_min, _max) {} + constexpr cfgopt_t(const char *_n, uint *_p, uint _min, uint _max) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_RANGE), num_range(_min, _max) {} + constexpr cfgopt_t(const char *_n, char *_p, char _min, char _max) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_CHAR | IDPOPT_NUM_RANGE), num_range(_min, _max) {} + constexpr cfgopt_t(const char *_n, uchar *_p, uchar _min, uchar _max) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_CHAR | IDPOPT_NUM_RANGE), num_range(_min, _max) {} + constexpr cfgopt_t(const char *_n, short *_p, short _min, short _max) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_RANGE | IDPOPT_NUM_SHORT), num_range(_min, _max) {} + constexpr cfgopt_t(const char *_n, ushort *_p, ushort _min, ushort _max) + : name(_n), ptr(_p), flags(IDPOPT_NUM | IDPOPT_NUM_UNS | IDPOPT_NUM_RANGE | IDPOPT_NUM_SHORT), num_range(_min, _max) {} + + // IDPOPT_BIT + constexpr cfgopt_t(const char *_n, bool *_p, bool _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT | IDPOPT_BIT_BOOL), bit_flags(_flags) {} + constexpr cfgopt_t(const char *_n, uchar *_p, uchar _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT | IDPOPT_BIT_UCHAR), bit_flags(_flags) {} + constexpr cfgopt_t(const char *_n, ushort *_p, ushort _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT | IDPOPT_BIT_USHORT), bit_flags(_flags) {} + constexpr cfgopt_t(const char *_n, uint32 *_p, uint32 _flags) : name(_n), ptr(_p), flags(IDPOPT_BIT), bit_flags(_flags) {} + + // IDPOPT_I64 + constexpr cfgopt_t(const char *_n, int64 *_p) : name(_n), ptr(_p), flags(IDPOPT_I64), buf_size(0) {} + constexpr cfgopt_t(const char *_n, uint64 *_p) : name(_n), ptr(_p), flags(IDPOPT_I64 | IDPOPT_NUM_UNS), buf_size(0) {} + // IDPOPT_I64 + ranges + constexpr cfgopt_t(const char *_n, int64 *_p, int64 _min, int64 _max) + : name(_n), ptr(_p), flags(IDPOPT_I64 | IDPOPT_I64_RANGES), num_range(_min, _max) {} + constexpr cfgopt_t(const char *_n, uint64 *_p, uint64 _min, uint64 _max) + : name(_n), ptr(_p), flags(IDPOPT_I64 | IDPOPT_I64_UNS | IDPOPT_I64_RANGES), num_range(int64(_min), int64(_max)) {} + + // IDPOPT_CST + constexpr cfgopt_t(const char *_n, cfgopt_handler_t *_p) + : name(_n), hnd(_p), flags(IDPOPT_CST), buf_size(0) {} + // IDPOPT_CST + params + constexpr cfgopt_t(const char *_n, cfgopt_handler2_t *_p, int64 _p1=0, int64 _p2=0) + : name(_n), hnd2(_p), flags(IDPOPT_CST | IDPOPT_CST_PARAMS), params(_p1, _p2) {} + + // configuration option based on the offset of a structure member + + // IDPOPT_STR + template<class T> + constexpr cfgopt_t(const char *_n, qstring T:: *, size_t _mbroff, bool _long = true) + : name(_n), + mbroff(_mbroff), + flags(IDPOPT_MBROFF | IDPOPT_STR | IDPOPT_STR_QSTRING | (_long ? IDPOPT_STR_LONG : 0)), + buf_size(0) + {} +#define CFGOPT_QS(nm, cfgt, cfgm, _long) \ + cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm), _long) + +#define CFGOPT_INNER_QS(nm, cfgt, cfgm, mt, mf, _long) \ + cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf), _long) + + + // IDPOPT_NUM +#define CTR_CFGOPT(ctrtype, ctrflags) \ + template<class T> \ + constexpr cfgopt_t(const char *_n, ctrtype T:: *, size_t _mbroff) \ + : name(_n), \ + mbroff(_mbroff), \ + flags(IDPOPT_MBROFF|IDPOPT_NUM|ctrflags), \ + buf_size(0) \ + {} + CTR_CFGOPT(int, 0) + CTR_CFGOPT(uint, IDPOPT_NUM_UNS) + CTR_CFGOPT(char, IDPOPT_NUM_CHAR) + CTR_CFGOPT(uchar, IDPOPT_NUM_UNS|IDPOPT_NUM_CHAR) + CTR_CFGOPT(short, IDPOPT_NUM_SHORT) + CTR_CFGOPT(ushort, IDPOPT_NUM_SHORT|IDPOPT_NUM_UNS) +#undef CTR_CFGOPT + +#define CFGOPT_N(nm, cfgt, cfgm) \ + cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm)) + +#define CFGOPT_INNER_N(nm, cfgt, cfgm, mt, mf) \ + cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf)) + + + // IDPOPT_NUM + ranges +#define CTR_CFGOPT(ctrtype, ctrflags) \ + template<class T> \ + constexpr cfgopt_t(const char *_n, ctrtype T:: *, size_t _mbroff, int64 _min, int64 _max) \ + : name(_n), \ + mbroff(_mbroff), \ + flags(IDPOPT_MBROFF|IDPOPT_NUM|IDPOPT_NUM_RANGE|ctrflags), \ + num_range(_min, _max) \ + {} + CTR_CFGOPT(int, 0) + CTR_CFGOPT(uint, IDPOPT_NUM_UNS) + CTR_CFGOPT(char, IDPOPT_NUM_CHAR) + CTR_CFGOPT(uchar, IDPOPT_NUM_UNS|IDPOPT_NUM_CHAR) + CTR_CFGOPT(short, IDPOPT_NUM_SHORT) + CTR_CFGOPT(ushort, IDPOPT_NUM_SHORT|IDPOPT_NUM_UNS) +#undef CTR_CFGOPT + +#define CFGOPT_R(nm, cfgt, cfgm, min, max) \ + cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm), min, max) + +#define CFGOPT_INNER_R(nm, cfgt, cfgm, mt, mf, min, max) \ + cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf), min, max) + + + // IDPOPT_BIT +#define CTR_CFGOPT(ctrtype, ctrflags) \ + template<class T> \ + constexpr cfgopt_t(const char *_n, ctrtype T:: *, size_t _mbroff, ctrtype _flags) \ + : name(_n), \ + mbroff(_mbroff), \ + flags(IDPOPT_MBROFF|IDPOPT_BIT|ctrflags), \ + bit_flags(_flags) \ + {} + CTR_CFGOPT(bool, IDPOPT_BIT_BOOL); + CTR_CFGOPT(uchar, IDPOPT_BIT_UCHAR); + CTR_CFGOPT(ushort, IDPOPT_BIT_USHORT); + CTR_CFGOPT(uint32, 0); +#undef CTR_CFGOPT +#define CFGOPT_B(nm, cfgt, cfgm, _flags) \ + cfgopt_t(nm, &cfgt::cfgm, qoffsetof(cfgt, cfgm), _flags) + +#define CFGOPT_INNER_B(nm, cfgt, cfgm, mt, mf, _flags) \ + cfgopt_t(nm, &mt::mf, qoffsetof(cfgt, cfgm) + qoffsetof(mt, mf), _flags) + + + // IDPOPT_I64 + template<class T> + constexpr cfgopt_t(const char *_n, int64 T:: *, size_t _mbroff) + : name(_n), + mbroff(_mbroff), + flags(IDPOPT_MBROFF|IDPOPT_I64), + buf_size(0) + {} + template<class T> + constexpr cfgopt_t(const char *_n, uint64 T:: *, size_t _mbroff) + : name(_n), + mbroff(_mbroff), + flags(IDPOPT_MBROFF|IDPOPT_I64|IDPOPT_NUM_UNS), + buf_size(0) + {} + + // IDPOPT_I64 + ranges + template<class T> + constexpr cfgopt_t(const char *_n, int64 T:: *, size_t _mbroff, int64 _min, int64 _max) + : name(_n), + mbroff(_mbroff), + flags(IDPOPT_MBROFF|IDPOPT_I64|IDPOPT_I64_RANGES), + num_range(_min, _max) + {} + template<class T> + constexpr cfgopt_t(const char *_n, uint64 T:: *, size_t _mbroff, uint64 _min, uint64 _max) + : name(_n), + mbroff(_mbroff), + flags(IDPOPT_MBROFF|IDPOPT_I64|IDPOPT_I64_UNS|IDPOPT_I64_RANGES), + num_range(int64(_min), int64(_max)) + {} + + // IDPOPT_CST + params + constexpr cfgopt_t(const char *_n, cfgopt_handler3_t *_p, int64 _p1=0, int64 _p2=0) + : name(_n), hnd3(_p), flags(IDPOPT_MBROFF|IDPOPT_CST), params(_p1, _p2) {} + + int type() const { return flags & 0xf; } + int qualifier() const { return flags & 0xf000000; } + + const char *apply(int vtype, const void *vdata, void *obj=nullptr) const + { + return cfgopt_t__apply2(this, vtype, vdata, obj); + } +}; + +/// Parse the input, and apply options. +/// +/// \param input input file name, or string +/// \param is_file is input a string, or a file name +/// \param opts options destcriptions +/// \param nopts the number of entries present in the 'opts' array +/// \param defhdlr a handler to be called, if a directive couldn't be found in 'opts' +/// \param defines a list of preprocessor identifiers to define (so it is +/// possible to use #ifdef checks in the file.) +/// NB: the actual identifier defined by the parser will be +/// surrounded with double underscores (e.g., passing 'FOO' +/// will result in '__FOO__' being defined) +/// Additionally, the parser will also define a similar macro +/// with the current processor name (e.g., __ARM__) +/// \param ndefines the number of defines in the list +/// \param obj see cfgopt_t constructor based on the offset of a structure member +/// \return true if parsing finished without errors, false if there was a +/// syntax error, callback returned an error, or no file was found +/// at all. + +idaman bool ida_export read_config( + const char *input, + bool is_file, + const cfgopt_t opts[], + size_t nopts, + cfgopt_handler_t *defhdlr = NULL, + const char *const *defines = NULL, + size_t ndefines = 0); + +idaman bool ida_export read_config2( + const char *input, + bool is_file, + const cfgopt_t opts[], + size_t nopts, + cfgopt_handler_t *defhdlr = nullptr, + const char *const *defines = nullptr, + size_t ndefines = 0, + void *obj = nullptr); + +inline bool read_config_file2( + const char *filename, + const cfgopt_t opts[], + size_t nopts, + cfgopt_handler_t *defhdlr = nullptr, + const char *const *defines = nullptr, + size_t ndefines = 0, + void *obj = nullptr) +{ + return read_config2(filename, true, opts, nopts, defhdlr, defines, ndefines, obj); +} + +/// Search for all IDA system files with the given name. +/// This function will search, in that order, for the following files: +/// -# %IDADIR%/cfg/<file> +/// -# for each directory 'ONEDIR' in %IDAUSR%: %ONEDIR%/cfg/<file> +/// +/// For each directive in each of those files, the same processing as +/// that of read_config will be performed. + +inline bool read_config_file( + const char *filename, + const cfgopt_t opts[], + size_t nopts, + cfgopt_handler_t *defhdlr = NULL, + const char *const *defines = NULL, + size_t ndefines = 0) +{ + return read_config(filename, true, opts, nopts, defhdlr, defines, ndefines); +} + + +/// For each directive in 'string', the same processing as that of +/// read_config will be performed. +inline bool read_config_string( + const char *string, + const cfgopt_t opts[], + size_t nopts, + cfgopt_handler_t *defhdlr = NULL, + const char *const *defines = NULL, + size_t ndefines = 0) +{ + return read_config(string, false, opts, nopts, defhdlr, defines, ndefines); +} + + +/// Process one or more config directive(s). +/// \param directive the directives to process +/// \param priority priority \ref IDPOPT_RET +/// In the case of errors this function displays a message and exits. + +idaman void ida_export process_config_directive( + const char *directive, + int priority=IDPOPT_PRI_HIGH); + + +/// Register array of config options. +/// This function can be used by a plugin to register the config options. +/// After registering an option, it becomes usable by the +/// process_config_directive() function. +/// \param opts array of config options +/// \param nopts number of options to install. 0 means uninstall +/// \param cb callback that will be invoked upon changing a config option +/// \param obj see cfgopt_t constructor based on the offset of a structure member +/// \return success + +typedef void idaapi config_changed_cb_t(const cfgopt_t &opt, int vtype, const void *vdata); + +idaman bool ida_export register_cfgopts( + const cfgopt_t opts[], + size_t nopts, + config_changed_cb_t cb=nullptr, + void *obj=nullptr); + + +/// Get one of config parameters defined by CC_PARMS in ida.cfg. +/// All parameters for all compilers are stored in local map during last read +/// of ida.cfg - this function just returns previously stored parameter value for +/// given compiler (NULL if no such parameter) +idaman const char *ida_export cfg_get_cc_parm(comp_t compid, const char *name); + + +/// Get header path config parameter from ida.cfg. +/// Also see cfg_get_cc_parm() + +inline const char *cfg_get_cc_header_path(comp_t compid) +{ + return cfg_get_cc_parm(compid, "HEADER_PATH"); +} + + +/// Get predefined macros config parameter from ida.cfg. +/// Also see cfg_get_cc_parm() + +inline const char *cfg_get_cc_predefined_macros(comp_t compid) +{ + return cfg_get_cc_parm(compid, "PREDEFINED_MACROS"); +} + +#endif // _CONFIG_HPP diff --git a/idasdk76/include/dbg.hpp b/idasdk76/include/dbg.hpp new file mode 100644 index 0000000..52e7e67 --- /dev/null +++ b/idasdk76/include/dbg.hpp @@ -0,0 +1,2625 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef DBG_HPP +#define DBG_HPP + +#include <idp.hpp> +#include <idd.hpp> +#include <kernwin.hpp> // for callui() and ui_notification_t + +/*! \file dbg.hpp + + \brief Contains functions to control the debugging of a process. + + See \ref dbg_funcs for a complete explanation of these functions. + + These functions are inlined for the kernel. + They are not inlined for the user-interfaces. +*/ + +//-------------------------------------------------------------------- +// D E B U G G E R I N F O R M A T I O N +//-------------------------------------------------------------------- + +/// This structure contains information about the current debugger. +/// (NULL if no debugger was loaded) - see idd.hpp for details about this structure. +/// +/// All functions defined in this structure should only be called by the kernel !!! +idaman debugger_t ida_export_data *dbg; + +//-------------------------------------------------------------------- +// D E B U G G E R C A L L B A C K S +//-------------------------------------------------------------------- +/// Debugger notification codes. +/// +/// A plugin can receive notifications of all major events in the +/// debugger, by calling the hook_to_notification_point() function +/// with ::HT_DBG as ::hook_type_t (see loader.hpp for details about +/// installing and removing such callbacks). +/// +/// IDA generates two major different types of debugger notifications: +/// +/// - debugger event notification: +/// this notification monitors usual events occurring during the +/// execution of a process. +/// These event notifications are always generated for any process. +/// Some of these event notifications are interpreted by IDA +/// (high-level events), while others are directly generated by the +/// debugger module (low-level events). +/// Low-level events always return a ::debug_event_t structure as an argument. +/// +/// - debugger asynchronous function result notification: +/// such a notification occurs only when a debugger properly terminated +/// the execution of an asynchronous function (see \ref dbg_funcs) +/// +/// How to control the process execution (after the execution of all notification +/// handlers) from the notification handler: +/// +/// - to force the process to STOP: +/// call suspend_process(). +/// In this case, the current debugger command will be aborted and no new +/// request will be started. +/// +/// - to force the process to CONTINUE: +/// call continue_process(). +/// In this case, no new request will be started. +/// +/// - to start new debugger command(s): +/// call as many request_COMMAND() as needed, then call run_requests(). +/// In this case, the current debugger command (if any) will be aborted. +/// (see \ref dbg_funcs in this file for more details about requests) +/// +/// - else, the process execution will depend on the current debugger options or +/// object settings. Some examples: +/// - a new loaded library will stop the process depending on the associated debugger option. +/// - a breakpoint will stop the process depending on its properties. +/// +/// A plugin must not call asynchronous debugger functions from the notification handler! +/// Use the REQUEST QUEUE mechanism instead (request_...()). +/// +/// If the plugin wants to access the process memory from a notification point, +/// it should call invalidate_dbgmem_config() and/or invalidate_dbgmem_contents() +/// functions. The invalidate_dbgmem_config() is really slow, so do not call it +/// unless the process memory config have changed after the last time the process +/// was suspended. The invalidate_dbgmem_contents() is fast and flushes the +/// memory cache in the ida kernel. Without it, functions like get_byte() would +/// return stale values! +enum dbg_notification_t +{ + dbg_null = 0, + + // debugger low-level event notifications (see IDD.HPP for details). + + dbg_process_start, ///< \param event (const ::debug_event_t *) + ///< \note This event notification is also an asynchronous + ///< function result notification for start_process() ! + + dbg_process_exit, ///< \param event (const ::debug_event_t *) + ///< \note This event notification is also an asynchronous + ///< function result notification for start_process() ! + + dbg_process_attach, ///< \param event (const ::debug_event_t *) + ///< \note This event notification is also an asynchronous + ///< function result notification for start_process() ! + + dbg_process_detach, ///< \param event (const ::debug_event_t *) + ///< \note This event notification is also an asynchronous + ///< function result notification for start_process() ! + + dbg_thread_start, ///< \param event (const ::debug_event_t *) + + dbg_thread_exit, ///< \param event (const ::debug_event_t *) + + dbg_library_load, ///< \param event (const ::debug_event_t *) + + dbg_library_unload, ///< \param event (const ::debug_event_t *) + + dbg_information, ///< \param event (const ::debug_event_t *) + + dbg_exception, ///< \param event (const ::debug_event_t *) + ///< \param[out] warn (int *) filled with: + ///< - -1: display an exception warning dialog + ///< if the process is suspended. + ///< - 0: never display an exception warning dialog. + ///< - 1: always display an exception warning dialog. + + // debugger high-level event notifications + + dbg_suspend_process, ///< The process is now suspended. + ///< \param event (const ::debug_event_t *) + ///< \note This event notification is also an asynchronous + ///< function result notification for suspend_process() ! + + dbg_bpt, ///< A user defined breakpoint was reached. + ///< \param tid (::thid_t) + ///< \param bptea (::ea_t) + ///< \param[out] warn (int *) filled with: + ///< - -1: display an exception warning dialog + ///< if the process is suspended. + ///< - 0: never display an exception warning dialog. + ///< - 1: always display an exception warning dialog. + + dbg_trace, ///< A step occurred (one instruction was executed). This event + ///< notification is only generated if step tracing is enabled. + ///< \param tid (::thid_t) thread ID + ///< \param ip (::ea_t) current instruction pointer. + ///< usually points after the executed instruction + ///< \retval 1 do not log this trace event + ///< \retval 0 log it + + dbg_request_error, ///< An error occurred during the processing of a request. + ///< \param failed_command (::ui_notification_t) + ///< \param failed_dbg_notification (::dbg_notification_t) + + // debugger asynchronous function result notifications + // Please note some low-level event notifications also act as asynchronous + // function result notifications. + + dbg_step_into, ///< \param event (const ::debug_event_t *) + + dbg_step_over, ///< \param event (const ::debug_event_t *) + + dbg_run_to, ///< \param event (const ::debug_event_t *) + + dbg_step_until_ret, ///< \param event (const ::debug_event_t *) + + dbg_bpt_changed, ///< Breakpoint has been changed. + ///< \param bptev_code (int) \ref BPTEV_ + ///< \param bpt (::bpt_t *) + + dbg_started_loading_bpts, ///< Started loading breakpoint info from idb + dbg_finished_loading_bpts, ///< Finished loading breakpoint info from idb + + dbg_last, ///< The last debugger notification code +}; + +/// \defgroup BPTEV_ Breakpoint modification events +/// Passed as 'bptev_code' parameter to ::dbg_bpt_changed callback +//@{ +#define BPTEV_ADDED 0 ///< Breakpoint has been added +#define BPTEV_REMOVED 1 ///< Breakpoint has been removed +#define BPTEV_CHANGED 2 ///< Breakpoint has been modified +//@} + +#ifndef __UI__ + +//-------------------------------------------------------------------- +// D E B U G G E R F U N C T I O N S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs Debugger functions +/// +/// Control the debugging of a process. +/// +/// Debugger functions complete either SYNCHRONOUSLY or ASYNCHRONOUSLY: +/// +/// - SYNCHRONOUS FUNCTIONS execute the entire action before the function returns. +/// +/// - ASYNCHRONOUS FUNCTIONS return before the action has executed in its +/// entirety. They simply start the action, but the result of the action will +/// only be available later. For example, run_to() can execute a lot of +/// instructions before terminating. +/// Such functions provide a notification code to indicate the end of their +/// execution (see the 'Notification' keyword in the function documentation). +/// Install a callback using hook_to_notification_point() to be notified +/// when the action is terminated. +/// +/// DEBUGGER COMMANDS are functions who influence the execution of the debugged +/// process. They are available in 2 forms: +/// +/// - COMMAND(): (e.g. suspend_process()) +/// In this mode, the command will be directly executed. However, it is forbidden +/// to use asynchronous commands in this mode from a debugger notification handler +/// (see ::dbg_notification_t). +/// +/// - request_COMMAND(): (e.g. request_suspend_process()) +/// In this mode, a REQUEST to run the command will be memorized at the end of +/// the REQUEST QUEUE (see below). This is mandatory to use this mode for asynchronous +/// commands from a debugger notification handler (see ::dbg_notification_t). +/// +/// +/// The REQUEST QUEUE contains a list of planned debugger commands. +/// These commands will be started only in the following cases: +/// +/// - the previous command terminated, and no call to suspend_process() +/// or continue_process() occurred in the asynchronous function result +/// notification handler (if any). +/// +/// - run_requests() was called. +/// Please note that when called from a debugger notification handler the +/// queued requests will only be started after the execution of all +/// notification handlers. +/// +/// A request which fails to start (by returning 0) will generate a +/// ::dbg_request_error notification. +//@{ + +/// Execute requests until all requests are processed or an asynchronous +/// function is called. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return false if not all requests could be processed +/// (indicates an asynchronous function was started) +/// \note If called from a notification handler, the execution of requests will +/// be postponed to the end of the execution of all notification handlers. + +inline bool idaapi run_requests(void) { return callui(ui_dbg_run_requests).cnd; } + + +/// Get the current running request. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return ui_null if no running request + +inline ui_notification_t idaapi get_running_request(void) { return (ui_notification_t)callui(ui_dbg_get_running_request).i; } + + +/// Is a request currently running? + +inline bool is_request_running(void) { return get_running_request() != ui_null; } + + +/// Get the notification associated (if any) with the current running request. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return dbg_null if no running request + +inline dbg_notification_t idaapi get_running_notification(void) { return (dbg_notification_t)callui(ui_dbg_get_running_notification).i; } + + +/// Clear the queue of waiting requests. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \note If a request is currently running, this one isn't stopped. + +inline void idaapi clear_requests_queue(void) { callui(ui_dbg_clear_requests_queue); } +//@} dbg_funcs + +//-------------------------------------------------------------------- +// P R O C E S S C O M M A N D S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_cmds Process commands +/// \ingroup dbg_funcs +/// +/// Use these functions to manipulate the debugged process. +//@{ + +/// Return the state of the currently debugged process. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return one of \ref DSTATE_ + +inline int idaapi get_process_state(void) { return callui(ui_dbg_get_process_state).i; } + +#endif // __UI__ + +/// \defgroup DSTATE_ Debugged process states +/// See get_process_state(), set_process_state(), invalidate_dbg_state() +//@{ +#define DSTATE_SUSP -1 ///< process is suspended and will not continue +#define DSTATE_NOTASK 0 ///< no process is currently debugged +#define DSTATE_RUN 1 ///< process is running +//@} + +/// \defgroup DBGINV_ Debugged process invalidation options +/// See set_process_state() and invalidate_dbg_state() +//@{ +#define DBGINV_MEMORY 0x0001 ///< invalidate cached memory contents +#define DBGINV_MEMCFG 0x0002 ///< invalidate cached process segmentation +#define DBGINV_REGS 0x0004 ///< invalidate cached register values +#define DBGINV_ALL 0x7FFF ///< invalidate everything +#define DBGINV_REDRAW 0x8000 ///< refresh the screen +#define DBGINV_NONE 0 ///< invalidate nothing +//@} + +#ifndef __UI__ + +/// Set new state for the debugged process. +/// Notifies the IDA kernel about the change of the debugged process state. +/// For example, a debugger module could call this function when it knows +/// that the process is suspended for a short period of time. +/// Some IDA API calls can be made only when the process is suspended. +/// The process state is usually restored before returning control to the caller. +/// You must know that it is ok to change the process state, doing it at arbitrary +/// moments may crash the application or IDA. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param newstate new process state (one of \ref DSTATE_) +/// if #DSTATE_NOTASK is passed then the state is not changed +/// \param p_thid ptr to new thread id. may be NULL or pointer to #NO_THREAD. +/// the pointed variable will contain the old thread id upon return +/// \param dbginv \ref DBGINV_ +/// \return old debugger state (one of \ref DSTATE_) + +inline int idaapi set_process_state(int newstate, thid_t *p_thid, int dbginv) { return callui(ui_dbg_set_process_state, newstate, p_thid, dbginv).i; } + + +/// Invalidate cached debugger information. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param dbginv \ref DBGINV_ +/// \return current debugger state (one of \ref DSTATE_) + +inline int idaapi invalidate_dbg_state(int dbginv) +{ + return set_process_state(DSTATE_NOTASK, NULL, dbginv); +} + + +/// Start a process in the debugger. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_process_start} +/// \note You can also use the run_to() function to easily start the execution +/// of a process until a given address is reached. +/// \note For all parameters, a NULL value indicates the debugger will take +/// the value from the defined Process Options. +/// \param path path to the executable to start +/// \param args arguments to pass to process +/// \param sdir starting directory for the process +/// \retval -1 impossible to create the process +/// \retval 0 the starting of the process was cancelled by the user +/// \retval 1 the process was properly started + +inline int idaapi start_process( + const char *path = NULL, + const char *args = NULL, + const char *sdir = NULL) +{ + return callui(ui_dbg_start_process, path, args, sdir).i; +} + + +/// Post a start_process() request + +inline int idaapi request_start_process( + const char *path = NULL, + const char *args = NULL, + const char *sdir = NULL) +{ + return callui(ui_dbg_request_start_process, path, args, sdir).i; +} + + +/// Suspend the process in the debugger. +/// \sq{ +/// Type, +/// - Synchronous function (if in a notification handler) +/// - Asynchronous function (everywhere else) +/// - available as Request, +/// Notification, +/// - none (if in a notification handler) +/// - ::dbg_suspend_process (everywhere else) +/// } +/// \note The suspend_process() function can be called from a notification +/// handler to force the stopping of the process. +/// In this case, no notification will be generated. +/// When you suspend a process, the running command is always aborted. + +inline bool idaapi suspend_process(void) { return callui(ui_dbg_suspend_process).cnd; } + +/// Post a suspend_process() request + +inline bool idaapi request_suspend_process(void) { return callui(ui_dbg_request_suspend_process).cnd; } + + +/// Continue the execution of the process in the debugger. +/// \sq{Type, Synchronous function - available as Request, +/// Notification, none (synchronous function)} +/// \note The continue_process() function can be called from a notification +/// handler to force the continuation of the process. In this case +/// the request queue will not be examined, IDA will simply resume +/// execution. Usually it makes sense to call request_continue_process() +/// followed by run_requests(), so that IDA will first start a queued +/// request (if any) and then resume the application. + +inline bool idaapi continue_process(void) { return callui(ui_dbg_continue_process).cnd; } + +/// Post a continue_process() request. +/// \note This requires an explicit call to run_requests() + +inline bool idaapi request_continue_process(void) { return callui(ui_dbg_request_continue_process).cnd; } + + +/// Terminate the debugging of the current process. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_process_exit} + +inline bool idaapi exit_process(void) { return callui(ui_dbg_exit_process).cnd; } + +/// Post an exit_process() request. + +inline bool idaapi request_exit_process(void) { return callui(ui_dbg_request_exit_process).cnd; } + + +/// Take a snapshot of running processes and return their description. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param[out] array with information about each running process +/// \return number of processes or -1 on error + +inline ssize_t idaapi get_processes(procinfo_vec_t *proclist) { return callui(ui_dbg_get_processes, proclist).ssize; } + + +/// Attach the debugger to a running process. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_process_attach} +/// \note This function shouldn't be called as a request if #NO_PROCESS is used. +/// \param pid PID of the process to attach to. If #NO_PROCESS, a dialog box +/// will interactively ask the user for the process to attach to. +/// \retval -4 debugger was not inited +/// \retval -3 the attaching is not supported +/// \retval -2 impossible to find a compatible process +/// \retval -1 impossible to attach to the given process (process died, privilege +/// needed, not supported by the debugger plugin, ...) +/// \retval 0 the user cancelled the attaching to the process +/// \retval 1 the debugger properly attached to the process + +inline int idaapi attach_process(pid_t pid=NO_PROCESS, int event_id=-1) { return callui(ui_dbg_attach_process, pid, event_id).i; } + +/// Post an attach_process() request + +inline int idaapi request_attach_process(pid_t pid, int event_id) { return callui(ui_dbg_request_attach_process, pid, event_id).i; } + + +/// Detach the debugger from the debugged process. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_process_detach} + +inline bool idaapi detach_process(void) { return callui(ui_dbg_detach_process).cnd; } + +/// Post a detach_process() request + +inline bool idaapi request_detach_process(void) { return callui(ui_dbg_request_detach_process).cnd; } + + +/// Is the debugger busy?. +/// Some debuggers do not accept any commands while the debugged application +/// is running. For such a debugger, it is unsafe to do anything with the +/// database (even simple queries like get_byte may lead to undesired consequences). +/// Returns: true if the debugged application is running under such a debugger + +inline bool idaapi is_debugger_busy(void) { return callui(ui_dbg_is_busy).cnd; } + +//@} dbg_funcs_cmds + + +//-------------------------------------------------------------------- +// T H R E A D S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_threads Threads +/// \ingroup dbg_funcs +/// +/// Inspect/Manipulate threads of debugged process. +//@{ + +/// Get number of threads. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline int idaapi get_thread_qty(void) { return callui(ui_dbg_get_thread_qty).i; } + + +/// Get the ID of a thread. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of thread, is in range 0..get_thread_qty()-1 +/// \return #NO_THREAD if the thread doesn't exist. + +inline thid_t idaapi getn_thread(int n) { return (thid_t)callui(ui_dbg_getn_thread, n).i; } + + +/// Get current thread ID. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline thid_t idaapi get_current_thread(void) { return callui(ui_dbg_get_current_thread).i; } + + +/// Get the NAME of a thread +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of thread, is in range 0..get_thread_qty()-1 +/// or -1 for the current thread +/// \return thread name or NULL if the thread doesn't exist. + +inline const char *idaapi getn_thread_name(int n) { return callui(ui_dbg_getn_thread_name, n).cptr; } + + +/// Select the given thread as the current debugged thread. +/// All thread related execution functions will work on this thread. +/// The process must be suspended to select a new thread. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param tid ID of the thread to select +/// \return false if the thread doesn't exist. + +inline bool idaapi select_thread(thid_t tid) { return callui(ui_dbg_select_thread, tid).cnd; } + +/// Post a select_thread() request + +inline bool idaapi request_select_thread(thid_t tid) { return callui(ui_dbg_request_select_thread, tid).cnd; } + + +/// Suspend thread. +/// Suspending a thread may deadlock the whole application if the suspended +/// was owning some synchronization objects. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param tid thread id +/// \retval -1 network error +/// \retval 0 failed +/// \retval 1 ok + +inline int idaapi suspend_thread(thid_t tid) { return callui(ui_dbg_suspend_thread, tid).i; } + +/// Post a suspend_thread() request + +inline int idaapi request_suspend_thread(thid_t tid) { return callui(ui_dbg_request_suspend_thread, tid).i; } + + +/// Resume thread. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param tid thread id +/// \retval -1 network error +/// \retval 0 failed +/// \retval 1 ok + +inline int idaapi resume_thread(thid_t tid) { return callui(ui_dbg_resume_thread, tid).i; } + +/// Post a resume_thread() request + +inline int idaapi request_resume_thread(thid_t tid) { return callui(ui_dbg_request_resume_thread, tid).i; } + +//@} dbg_funcs_threads + + +//-------------------------------------------------------------------- +// M O D U L E S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_modules Modules +/// \ingroup dbg_funcs +/// +/// Functions to enumerate modules loaded into the process. +/// +/// \param modinfo structure to receive the answer +/// \return false if there are no (more) modules +/// +/// Typical loop to enumerate modules would look like: +/// \code +/// modinfo_t minfo; +/// for ( bool ok=get_first_module(&minfo); ok; ok=get_next_module(&minfo) ) +/// ... +/// \endcode +//@{ +inline bool idaapi get_first_module(modinfo_t *modinfo) ///< See \ref dbg_funcs_modules +{ return callui(ui_dbg_get_first_module, modinfo).cnd; } + +inline bool idaapi get_next_module(modinfo_t *modinfo) ///< See \ref dbg_funcs_modules +{ return callui(ui_dbg_get_next_module, modinfo).cnd; } + +//@} + + +//-------------------------------------------------------------------- +// E X E C U T I O N F L O W C O N T R O L C O M M A N D S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_flow Execution flow control +/// \ingroup dbg_funcs +/// +/// Use these functions to run instructions in the debugged process. +//@{ + +/// Execute one instruction in the current thread. +/// Other threads are kept suspended. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_step_into} + +inline bool idaapi step_into(void) { return callui(ui_dbg_step_into).cnd; } + +/// Post a step_into() request + +inline bool idaapi request_step_into(void) { return callui(ui_dbg_request_step_into).cnd; } + + +/// Execute one instruction in the current thread, +/// but without entering into functions. +/// Others threads keep suspended. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_step_over} + +inline bool idaapi step_over(void) { return callui(ui_dbg_step_over).cnd; } + +/// Post a step_over() request + +inline bool idaapi request_step_over(void) { return callui(ui_dbg_request_step_over).cnd; } + + +/// Execute the process until the given address is reached. +/// If no process is active, a new process is started. +/// Technically, the debugger sets up a temporary breakpoint at +/// the given address, and continues (or starts) the execution of +/// the whole process. +/// So, all threads continue their execution! +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_run_to} +/// \param ea target address +/// \param pid not used yet. please do not specify this parameter. +/// \param tid not used yet. please do not specify this parameter. + +inline bool idaapi run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_run_to, ea, pid, tid).cnd; } + +/// Post a run_to() request + +inline bool idaapi request_run_to(ea_t ea, pid_t pid = NO_PROCESS, thid_t tid = NO_THREAD) { return callui(ui_dbg_request_run_to, ea, pid, tid).cnd; } + +/// Execute instructions in the current thread until +/// a function return instruction is executed (aka "step out"). +/// Other threads are kept suspended. +/// \sq{Type, Asynchronous function - available as Request, +/// Notification, ::dbg_step_until_ret} + +inline bool idaapi step_until_ret(void) { return callui(ui_dbg_step_until_ret).cnd; } + +/// Post a step_until_ret() request + +inline bool idaapi request_step_until_ret(void) { return callui(ui_dbg_request_step_until_ret).cnd; } + + +/// How to resume the application. +/// Set resume mode but do not resume process. + +inline bool idaapi set_resume_mode(thid_t tid, resume_mode_t mode) { return callui(ui_dbg_set_resume_mode, tid, mode).cnd; } + +/// Post a set_resume_mode() request + +inline bool idaapi request_set_resume_mode(thid_t tid, resume_mode_t mode) { return callui(ui_dbg_request_set_resume_mode, tid, mode).cnd; } + +//@} dbg_funcs_flow + + +//-------------------------------------------------------------------- +// R E G I S T E R S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_regs Registers +/// \ingroup dbg_funcs +/// +/// Inspect/Manipulate registers for debugged process. +/// The debugger structure defines a set of hardware registers in \dbg{registers} +/// IDA also recognizes register names for each defined bit in bit registers. +/// You can use all these names to set or get a register value. +/// +/// For example, with the x86 Userland Win32 debugger you can use +/// register names like: +/// - "EAX", ... "EBP", "ESP", "EFL": for classical integer registers +/// - "CS", "DS", ... : for segment registers +/// - "ST0", "ST1", ... : for FPU registers +/// - "CF", "PF", "AF", "ZF", ... : for special bit values +//@{ + +/// Get register information +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi get_dbg_reg_info(const char *regname, register_info_t *ri) { return callui(ui_dbg_get_reg_info, regname, ri).cnd; } + +/// Read a register value from the current thread. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi get_reg_val(const char *regname, regval_t *regval) { return callui(ui_dbg_get_reg_val, regname, regval).cnd; } + +/// Get register value as an unsigned 64-bit int + +inline bool idaapi get_reg_val(const char *regname, uint64 *ival) { return callui(ui_dbg_get_reg_val_i, regname, ival).cnd; } + + +/// Get value of the SP register for the current thread. +/// Requires a suspended debugger. +inline bool idaapi get_sp_val(ea_t *out) { return callui(ui_dbg_get_sp_val, out).cnd; } + +/// Get value of the IP (program counter) register for the current thread. +/// Requires a suspended debugger. +inline bool idaapi get_ip_val(ea_t *out) { return callui(ui_dbg_get_ip_val, out).cnd; } + +/// Write a register value to the current thread. +/// \sq{Type, Synchronous function - available as Request, +/// Notification, none (synchronous function)} + +inline bool idaapi set_reg_val(const char *regname, const regval_t *regval) { return callui(ui_dbg_set_reg_val, regname, regval).cnd; } + +/// Write a register value to the current thread + +inline bool idaapi set_reg_val(const char *regname, uint64 ival) { return callui(ui_dbg_set_reg_val_i, regname, ival).cnd; } + +/// Post a set_reg_val() request + +inline bool idaapi request_set_reg_val(const char *regname, const regval_t *regval) { return callui(ui_dbg_request_set_reg_val, regname, regval).cnd; } + + +/// Does a register contain an integer value? +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi is_reg_integer(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i-2 == RVT_INT; } + + +/// Does a register contain a floating point value? +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi is_reg_float(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i-2 == RVT_FLOAT; } + + +/// Does a register contain a value of a custom data type? +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi is_reg_custom(const char *regname) { return callui(ui_dbg_get_reg_value_type, regname).i >= 2; } + +//@} dbg_funcs_regs + +#endif // __UI__ + +//-------------------------------------------------------------------- +// B R E A K P O I N T S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_bpts Breakpoints +/// \ingroup dbg_funcs +/// +/// Work with debugger breakpoints. +//@{ + + + +/// Helper function for ::bpt_location_t +int idaapi set_bptloc_string(const char *s); +const char *idaapi get_bptloc_string(int i); ///< \copydoc set_bptloc_string() + + +/// Breakpoint location types +enum bpt_loctype_t +{ + BPLT_ABS, ///< absolute address: ea + BPLT_REL, ///< relative address: module_path, offset + BPLT_SYM, ///< symbolic: symbol_name, offset + BPLT_SRC, ///< source level: filename, lineno +}; + +/// Describes a breakpoint location +struct bpt_location_t +{ +// private: + ea_t info; + int index; + bpt_loctype_t loctype; +// public: + bpt_loctype_t type(void) const { return loctype; } ///< Get bpt type + bool is_empty_path(void) const { return index == 0; } ///< No path/filename specified? (::BPLT_REL, ::BPLT_SRC) + const char *path(void) const { return get_bptloc_string(index); } ///< Get path/filename (::BPLT_REL, ::BPLT_SRC) + const char *symbol(void) const { return get_bptloc_string(index); } ///< Get symbol name (::BPLT_SYM) + int lineno(void) const { return int(info); } ///< Get line number (::BPLT_SRC) + uval_t offset(void) const { return (uval_t)info; } ///< Get offset (::BPLT_REL, ::BPLT_SYM) + ea_t ea(void) const { return info; } ///< Get address (::BPLT_ABS) + + bpt_location_t(void) : info(BADADDR), index(0), loctype(BPLT_ABS) {} ///< Constructor (default type is ::BPLT_ABS) + + /// Specify an absolute address location + void set_abs_bpt(ea_t a) + { + info = a; + loctype = BPLT_ABS; + } + + /// Specify a source level location + void set_src_bpt(const char *fn, int _lineno) + { + index = set_bptloc_string(fn); + info = _lineno; + loctype = BPLT_SRC; + } + + /// Specify a symbolic location + void set_sym_bpt(const char *_symbol, uval_t _offset=0) + { + index = set_bptloc_string(_symbol); + info = _offset; + loctype = BPLT_SYM; + } + + /// Specify a relative address location + void set_rel_bpt(const char *mod, uval_t _offset) + { + index = set_bptloc_string(mod); + info = _offset; + loctype = BPLT_REL; + } + + /// Lexically compare two breakpoint locations. + /// Bpt locations are first compared based on type (i.e. ::BPLT_ABS < ::BPLT_REL). + /// ::BPLT_ABS locations are compared based on their ea values. + /// For all other location types, locations are first compared based on their + /// string (path/filename/symbol), then their offset/lineno. + int compare(const bpt_location_t &r) const { return callui(ui_dbg_compare_bpt_locs, this, &r).i; } + bool operator==(const bpt_location_t &r) const { return compare(r) == 0; } + bool operator!=(const bpt_location_t &r) const { return compare(r) != 0; } + bool operator< (const bpt_location_t &r) const { return compare(r) < 0; } + bool operator> (const bpt_location_t &r) const { return compare(r) > 0; } + bool operator<=(const bpt_location_t &r) const { return compare(r) <= 0; } + bool operator>=(const bpt_location_t &r) const { return compare(r) >= 0; } + + /// Internal function + size_t print(qstring *buf) const; +}; + +/// Characteristics of a breakpoint +struct bpt_t +{ + size_t cb; ///< size of this structure + qstring cndbody; ///< Condition as entered by the user + bpt_location_t loc; ///< Location + pid_t pid; ///< breakpoint process id + thid_t tid; ///< breakpoint thread id + ea_t ea; ///< Address, if known. For #BPLT_SRC, index into an internal data struct + bpttype_t type; ///< Breakpoint type + int pass_count; ///< Number of times the breakpoint is hit before stopping + ///< (default is 0: stop always) + uint32 flags; ///< \ref BPT_T +/// \defgroup BPT_T Breakpoint property bits +/// Used by bpt_t::flags +//@{ +#define BPT_BRK 0x001 ///< suspend execution upon hit +#define BPT_TRACE 0x002 ///< add trace information upon hit +#define BPT_UPDMEM 0x004 ///< refresh the memory layout and contents before evaluating bpt condition +#define BPT_ENABLED 0x008 ///< enabled? +#define BPT_LOWCND 0x010 ///< condition is calculated at low level (on the server side) +#define BPT_TRACEON 0x020 ///< enable tracing when the breakpoint is reached +#define BPT_TRACE_INSN 0x040 ///< instruction tracing +#define BPT_TRACE_FUNC 0x080 ///< function tracing +#define BPT_TRACE_BBLK 0x100 ///< basic block tracing +#define BPT_TRACE_TYPES (BPT_TRACE_INSN|BPT_TRACE_FUNC|BPT_TRACE_BBLK) + ///< trace insns, functions, and basic blocks. + ///< if any of #BPT_TRACE_TYPES bits are set but #BPT_TRACEON is clear, + ///< then turn off tracing for the specified trace types +#define BPT_ELANG_MASK 0xF0000000u +#define BPT_ELANG_SHIFT 28 ///< index of the extlang (scripting language) of the condition +//@} + + uint32 props; ///< \ref BKPT_ +/// \defgroup BKPT_ Internal breakpoint properties +/// Used by bpt_t::props +//@{ +#define BKPT_BADBPT 0x01 ///< failed to write the bpt to the process memory (at least one location) +#define BKPT_LISTBPT 0x02 ///< include in bpt list (user-defined bpt) +#define BKPT_TRACE 0x04 ///< trace bpt; should not be deleted when the process gets suspended +#define BKPT_ACTIVE 0x08 ///< active? +#define BKPT_PARTIAL 0x10 ///< partially active? (some locations were not written yet) +#define BKPT_CNDREADY 0x20 ///< condition has been compiled +#define BKPT_FAKEPEND 0x40 ///< fake pending bpt: it is inactive but another + ///< bpt of the same type is active at the same address(es) +#define BKPT_PAGE 0x80 ///< written to the process as a page bpt. is available + ///< only after writing the bpt to the process. +//@} + + int size; ///< Size of the breakpoint (0 for software breakpoints) + int cndidx; ///< Internal number of the condition (<0-none) + + bpt_t(void) : cb(sizeof(*this)), pid(NO_PROCESS), tid(NO_THREAD), ea(BADADDR), + type(BPT_SOFT), pass_count(0), flags(BPT_BRK|BPT_ENABLED), + props(0), size(0), cndidx(-1) {} + + bool is_hwbpt(void) const { return type != BPT_SOFT; } ///< Is hardware breakpoint? + bool enabled(void) const { return (flags & BPT_ENABLED) != 0; } ///< Is breakpoint enabled? + bool is_low_level(void) const { return (flags & BPT_LOWCND) != 0; } ///< Is bpt condition calculated at low level? + bool badbpt(void) const { return (props & BKPT_BADBPT) != 0; } ///< Failed to write bpt to process memory? + bool listbpt(void) const { return (props & BKPT_LISTBPT) != 0; } ///< Include in the bpt list? + bool is_compiled(void) const { return (props & BKPT_CNDREADY) != 0; } ///< Condition has been compiled? + /// Written completely to process? + bool is_active(void) const { return (props & (BKPT_PARTIAL|BKPT_ACTIVE)) == BKPT_ACTIVE; } + /// Written partially to process? + bool is_partially_active(void) const { return (props & BKPT_PARTIAL) != 0; } + /// Not written to process at all? + bool is_inactive(void) const { return (props & (BKPT_PARTIAL|BKPT_ACTIVE)) == 0; } + /// Page breakpoint? + bool is_page_bpt(void) const { return (props & BKPT_PAGE) != 0; } + + /// Get bpt size + int get_size(void) const { return is_hwbpt() ? size : 1; } + /// Set bpt location to an absolute address + void set_abs_bpt(ea_t a) { loc.set_abs_bpt(a); ea = a; } + /// Set bpt location to a source line + void set_src_bpt(const char *fn, int lineno) { loc.set_src_bpt(fn, lineno); ea = BADADDR; } + /// Set bpt location to a symbol + void set_sym_bpt(const char *sym, uval_t o) { loc.set_sym_bpt(sym, o); ea = BADADDR; } + /// Set bpt location to a relative address + void set_rel_bpt(const char *mod, uval_t o) { loc.set_rel_bpt(mod, o); ea = BADADDR; } + + bool is_absbpt(void) const { return loc.type() == BPLT_ABS; } ///< Is absolute address breakpoint? + bool is_relbpt(void) const { return loc.type() == BPLT_REL; } ///< Is relative address breakpoint? + bool is_symbpt(void) const { return loc.type() == BPLT_SYM; } ///< Is symbolic breakpoint? + bool is_srcbpt(void) const { return loc.type() == BPLT_SRC; } ///< Is source level breakpoint? + + /// Does breakpoint trace anything? + bool is_tracemodebpt(void) const { return (flags & BPT_TRACE_TYPES) != 0; } + /// Is this a tracing breakpoint, and is tracing enabled? + bool is_traceonbpt(void) const { return is_tracemodebpt() && (flags & BPT_TRACEON) != 0; } + /// Is this a tracing breakpoint, and is tracing disabled? + bool is_traceoffbpt(void) const { return is_tracemodebpt() && (flags & BPT_TRACEON) == 0; } + /// Configure tracing options + bool set_trace_action(bool enable, int trace_types) + { + trace_types &= BPT_TRACE_TYPES; + if ( trace_types == 0 ) + return false; + flags |= trace_types; + setflag(flags, BPT_TRACEON, enable); + return true; + } + + /// Get the scripting language name for the condition string + const char *get_cnd_elang() const; + + /// Set the scripting language name for the condition string + /// \return false if too many languages were used + bool set_cnd_elang(const char *name); + + size_t get_cnd_elang_idx() const { return flags >> BPT_ELANG_SHIFT; } + + void set_cond(const char *cnd); ///< Internal function + bool eval_cond(ea_t ea, bool *fire, const char *bpt_type); ///< Internal function +}; +typedef qvector<bpt_t> bpt_vec_t; ///< vector of breakpoints + + +enum movbpt_code_t +{ + MOVBPT_OK, // moved ok + MOVBPT_NOT_FOUND, // source bpt not found + MOVBPT_DEST_BUSY, // destination location is busy (we already have such a bpt) + MOVBPT_BAD_TYPE, // BPLT_ABS is not supported +}; +typedef qvector<movbpt_code_t> movbpt_codes_t; + +struct movbpt_info_t +{ + bpt_location_t from; + bpt_location_t to; +}; +DECLARE_TYPE_AS_MOVABLE(movbpt_info_t); +typedef qvector<movbpt_info_t> movbpt_infos_t; + +#ifndef __UI__ + + +/// Get number of breakpoints. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline int idaapi get_bpt_qty(void) { return callui(ui_dbg_get_bpt_qty).i; } + + +/// Get the characteristics of a breakpoint. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of breakpoint, is in range 0..get_bpt_qty()-1 +/// \param[out] bpt filled with the characteristics. +/// \return false if no breakpoint exists + +inline bool idaapi getn_bpt(int n, bpt_t *bpt) { return callui(ui_dbg_getn_bpt, n, bpt).cnd; } + + +/// Get the characteristics of a breakpoint. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param ea any address in the breakpoint range +/// \param[out] bpt if not NULL, is filled with the characteristics. +/// \return false if no breakpoint exists + +inline bool idaapi get_bpt(ea_t ea, bpt_t *bpt) { return callui(ui_dbg_get_bpt, ea, bpt).cnd; } + + +/// Does a breakpoint exist at the given location? + +inline bool exist_bpt(ea_t ea) { return get_bpt(ea, NULL); } + + +/// Add a new breakpoint in the debugged process. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \note Only one breakpoint can exist at a given address. +/// \param ea any address in the process memory space. +/// Depending on the architecture, hardware breakpoints +/// always be setup at random address. For example, on x86, +/// hardware breakpoints should be aligned depending on their size. +/// Moreover, on the x86 architecture, it is impossible to setup +/// more than 4 hardware breakpoints. +/// \param size size of the breakpoint (irrelevant for software breakpoints): +/// As for the address, hardware breakpoints can't always be setup +/// with random size. +/// \param type type of the breakpoint (#BPT_SOFT for software breakpoint) +/// special case #BPT_DEFAULT (#BPT_SOFT|#BPT_EXEC): +/// try to add instruction breakpoint of the appropriate type +/// as follows: software bpt if supported, hwbpt otherwise + +inline bool idaapi add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_DEFAULT) { return callui(ui_dbg_add_oldbpt, ea, size, type).cnd; } + +/// Post an add_bpt(ea_t, asize_t, bpttype_t) request + +inline bool idaapi request_add_bpt(ea_t ea, asize_t size = 0, bpttype_t type = BPT_DEFAULT) { return callui(ui_dbg_request_add_oldbpt, ea, size, type).cnd; } + + +/// Add a new breakpoint in the debugged process. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param bpt Breakpoint to add. It describes the break condition, +/// type, flags, location (module relative, source breakpoint +/// or absolute) and other attributes. + +inline bool idaapi add_bpt(const bpt_t &bpt) { return callui(ui_dbg_add_bpt, &bpt).cnd; } + +/// Post an add_bpt(const bpt_t &) request + +inline bool idaapi request_add_bpt(const bpt_t &bpt) { return callui(ui_dbg_request_add_bpt, &bpt).cnd; } + + +/// Delete an existing breakpoint in the debugged process. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param ea any address in the breakpoint range + +inline bool idaapi del_bpt(ea_t ea) { return callui(ui_dbg_del_oldbpt, ea).cnd; } + +/// Post a del_bpt(ea_t) request + +inline bool idaapi request_del_bpt(ea_t ea) { return callui(ui_dbg_request_del_oldbpt, ea).cnd; } + + +/// Delete an existing breakpoint in the debugged process. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param bptloc Breakpoint location + +inline bool idaapi del_bpt(const bpt_location_t &bptloc) { return callui(ui_dbg_del_bpt, &bptloc).cnd; } + +/// Post a del_bpt(const bpt_location_t &) request + +inline bool idaapi request_del_bpt(const bpt_location_t &bptloc) { return callui(ui_dbg_request_del_bpt, &bptloc).cnd; } + + +/// Update modifiable characteristics of an existing breakpoint. +/// To update the breakpoint location, use change_bptlocs() +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \note Only the following fields can be modified: +/// - bpt_t::cndbody +/// - bpt_t::pass_count +/// - bpt_t::flags +/// - bpt_t::size +/// - bpt_t::type +/// \note Changing some properties will require removing and then re-adding +/// the breakpoint to the process memory (or the debugger backend), which +/// can lead to race conditions (i.e., breakpoint(s) can be missed) in +/// case the process is not suspended. +/// Here are a list of scenarios that will require the breakpoint +/// to be removed & then re-added: +/// - bpt_t::size is modified +/// - bpt_t::type is modified +/// - bpt_t::flags's BPT_ENABLED is modified +/// - bpt_t::flags's BPT_LOWCND is changed +/// - bpt_t::flags's BPT_LOWCND remains set, but cndbody changed + +inline bool idaapi update_bpt(const bpt_t *bpt) { return callui(ui_dbg_update_bpt, bpt).cnd; } + + +/// Find a breakpoint by location. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param bptloc Breakpoint location +/// \param bpt bpt is filled if the breakpoint was found + +inline bool idaapi find_bpt(const bpt_location_t &bptloc, bpt_t *bpt) { return callui(ui_dbg_find_bpt, &bptloc, bpt).cnd; } + + +/// Move breakpoint(s) from one location to another +/// \param movinfo what bpts to move and where to +/// \param codes vector of return codes, if detailed error info is required +/// \param del_hindering_bpts should delete hindering breakpoints? +/// \return number of moved bpts + +inline int idaapi change_bptlocs( + const movbpt_infos_t &movinfo, + movbpt_codes_t *codes = NULL, + bool del_hindering_bpts = true) +{ + return callui(ui_dbg_change_bptlocs, &movinfo, codes, del_hindering_bpts).i; +} + + + +/// \name enable/disable breakpoints +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// Enable or disable an existing breakpoint. +/// A disabled breakpoint isn't available anymore in the process. +//@{ +inline bool idaapi enable_bpt(ea_t ea, bool enable = true) { return callui(ui_dbg_enable_oldbpt, ea, enable).cnd; } +inline bool idaapi enable_bpt(const bpt_location_t &bptloc, bool enable = true) { return callui(ui_dbg_enable_bpt, &bptloc, enable).cnd; } +inline bool disable_bpt(ea_t ea) { return enable_bpt(ea, false); } +inline bool disable_bpt(const bpt_location_t &bptloc) { return enable_bpt(bptloc, false); } +inline bool idaapi request_enable_bpt(ea_t ea, bool enable = true) { return callui(ui_dbg_request_enable_oldbpt, ea, enable).cnd; } +inline bool idaapi request_enable_bpt(const bpt_location_t &bptloc, bool enable = true) { return callui(ui_dbg_request_enable_bpt, &bptloc, enable).cnd; } +inline bool request_disable_bpt(ea_t ea) { return request_enable_bpt(ea, false); } +inline bool request_disable_bpt(const bpt_location_t &bptloc) { return request_enable_bpt(bptloc, false); } +//@} + + +/// Check the breakpoint at the specified address. +/// \return one of \ref BPTCK_ + +inline int idaapi check_bpt(ea_t ea) { return callui(ui_dbg_check_bpt, ea).i; } + +#endif // __UI__ + +/// \defgroup BPTCK_ Breakpoint status codes +/// Return values for check_bpt() +//@{ +#define BPTCK_NONE -1 ///< breakpoint does not exist +#define BPTCK_NO 0 ///< breakpoint is disabled +#define BPTCK_YES 1 ///< breakpoint is enabled +#define BPTCK_ACT 2 ///< breakpoint is active (written to the process) +//@} + +#ifndef SWIG +/// Visit all breakpoints. +/// To use this class, derive your own class from it and call for_all_bpts(). +/// It is forbidden to add/del bpts from the visit_bpt() function. +/// If bpts are nevertheless modified, the enumeration should be stopped +struct bpt_visitor_t +{ + int _for_all_bpts(int bvflags); ///< do not use this function. + range_t range; ///< if specified, restricts the address range + const char *name; ///< if specified, restricts bpts to the ones that match the given name + bpt_visitor_t(void) : range(0, BADADDR), name(NULL) {} + /// Defines action taken when breakpoint is visited + virtual int idaapi visit_bpt(const bpt_t *bpt) = 0; + int idaapi for_all_bpts(int bvflags) + { + return callui(ui_dbg_for_all_bpts, this, bvflags).i; + } +}; + +/// \defgroup BVF_ Breakpoint visitor flags +/// Passed as 'bvflags' parameter to bpt_visitor_t::_for_all_bpts() +/// \note it is forbidden to modify bpt states from the bpt_visitor_t::visit_bpt() +/// function if #BVF_STATE is not #BVFS_ANY +//@{ +#define BVF_ABS 0x0001 ///< include absolute bpts +#define BVF_REL 0x0002 ///< include relative bpts +#define BVF_SYM 0x0004 ///< include symbolic bpts +#define BVF_SRC 0x0008 ///< include source bpts +#define BVF_ALL 0x000F ///< include all bpt location types +#define BVF_STATE 0x0030 ///< bpt state mask +#define BVFS_ANY 0x0000 ///< any state +#define BVFS_INPROC 0x0010 ///< written to process memory +#define BVFS_PENDING 0x0020 ///< pending +#define BVFS_DISABLED 0x0030 ///< disabled. +//@} +#endif // SWIG + + +//@} dbg_funcs_bpts + + +#ifndef __UI__ + +/// \defgroup dbg_funcs_tracing Tracing +/// \ingroup dbg_funcs +/// +/// Trace instructions/functions/basic blocks + +//-------------------------------------------------------------------- +// T R A C I N G B U F F E R +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_trcbuf Tracing buffer +/// \ingroup dbg_funcs_tracing +/// +/// Work with debugger trace buffer. +/// IDA memorizes various types of trace events in a circular buffer: +/// instruction tracing, function call and return, breakpoint access ... +//@{ + + +/// Specify the new size of the circular buffer. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param size if 0, buffer isn't circular and events are never removed. +/// If the new size is smaller than the existing number of trace events, +/// a corresponding number of trace events are removed. +/// \note If you specify 0, all available memory can be quickly used !!! + +inline bool idaapi set_trace_size(int size) { return callui(ui_dbg_set_trace_size, size).cnd; } + + +/// Clear all events in the trace buffer. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} + +inline void idaapi clear_trace(void) { callui(ui_dbg_clear_trace); } + +/// Post a clear_trace() request + +inline void idaapi request_clear_trace(void) { callui(ui_dbg_request_clear_trace); } + +//@} dbg_funcs_trcbuf + + +//-------------------------------------------------------------------- +// S T E P T R A C I N G +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_strace Step tracing +/// \ingroup dbg_funcs_tracing +/// +/// Plugins can use these functions to implement a custom tracing engine. +/// When enabled, IDA uses single-stepping feature of the debugger +/// and generates a dbg_trace notification after each step in the current thread. +/// Tracing buffer is not maintained in this mode (you need to use one of the +/// higher level tracing types for it) +//@{ + +/// Get current state of step tracing. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi is_step_trace_enabled(void) { return callui(ui_dbg_is_step_trace_enabled).cnd; } + + +/// \name Enable/Disable step tracing +/// Enable or disable the step tracing +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +/// \param enable +/// - 1 : enable step tracing +/// - 0 : disable step tracing +/// - -1 : temporarily disable step tracing +/// (trace-over breakpoints are conserved: +/// these could re-enable step tracing later) +//@{ + +inline bool idaapi enable_step_trace(int enable = 1) { return callui(ui_dbg_enable_step_trace, enable).cnd; } +inline bool disable_step_trace(void) { return enable_step_trace(0); } +inline bool idaapi request_enable_step_trace(int enable = 1) { return callui(ui_dbg_request_enable_step_trace, enable).cnd; } +inline bool request_disable_step_trace(void) { return request_enable_step_trace(false); } +//@} + +#endif // __UI__ + + +/// \defgroup ST_ Step trace options +/// Flags returned by get_step_trace_options() +//@{ +#define ST_OVER_DEBUG_SEG 0x01 ///< step tracing will be disabled when IP is in a debugger segment +#define ST_OVER_LIB_FUNC 0x02 ///< step tracing will be disabled when IP is in a library function +#define ST_ALREADY_LOGGED 0x04 ///< step tracing will be disabled when IP is already logged +#define ST_SKIP_LOOPS 0x08 ///< step tracing will try to skip loops already recorded +#define ST_DIFFERENTIAL 0x10 ///< tracing: log only new instructions (not previously logged) +/// mask of available options, to ensure compatibility with newer IDA versions +#define ST_OPTIONS_MASK (ST_OVER_DEBUG_SEG|ST_OVER_LIB_FUNC|ST_ALREADY_LOGGED|ST_SKIP_LOOPS|ST_DIFFERENTIAL) +#define ST_OPTIONS_DEFAULT (ST_OVER_DEBUG_SEG|ST_OVER_LIB_FUNC) +//@} + +/// specific options for instruction tracing (see set_insn_trace_options()) +#define IT_LOG_SAME_IP 0x01 ///< instruction tracing will log new instructions even when IP doesn't change +/// specific options for function tracing (see set_func_trace_options()) +#define FT_LOG_RET 0x01 ///< function tracing will log returning instructions +/// specific options for basic block tracing (see set_bblk_trace_options()) +#define BT_LOG_INSTS 0x01 ///< log all instructions in the current basic block + +#ifndef __UI__ + +/// Get current step tracing options. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return \ref ST_ + +inline int idaapi get_step_trace_options(void) { return callui(ui_dbg_get_step_trace_options).i; } + +/// Modify step tracing options. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} + +inline void idaapi set_step_trace_options(int options) { callui(ui_dbg_set_step_trace_options, options); } + +/// Post a set_step_trace_options() request + +inline void idaapi request_set_step_trace_options(int options) { callui(ui_dbg_request_set_step_trace_options, options); } + +//@} dbg_funcs_strace + + +//-------------------------------------------------------------------- +// I N S T R U C T I O N S T R A C I N G +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_trcins Instruction tracing +/// \ingroup dbg_funcs_tracing +/// +/// When instruction tracing is active, each executed instruction is stored +/// in the tracing buffer. +/// Internally, IDA uses step tracing to record register values after the +/// execution of the instruction. +//@{ + +/// Get current state of instruction tracing. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi is_insn_trace_enabled(void) { return callui(ui_dbg_is_insn_trace_enabled).cnd; } + +/// \name Enable/Disable instruction tracing +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +//@{ +inline bool idaapi enable_insn_trace(bool enable = true) { return callui(ui_dbg_enable_insn_trace, enable).cnd; } +inline bool disable_insn_trace(void) { return enable_insn_trace(false); } +inline bool idaapi request_enable_insn_trace(bool enable = true) { return callui(ui_dbg_request_enable_insn_trace, enable).cnd; } +inline bool request_disable_insn_trace(void) { return request_enable_insn_trace(false); } +//@} + + +/// Get current instruction tracing options. +/// Also see #IT_LOG_SAME_IP +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline int idaapi get_insn_trace_options(void) { return callui(ui_dbg_get_insn_trace_options).i; } + + +/// Modify instruction tracing options. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} + +inline void idaapi set_insn_trace_options(int options) { callui(ui_dbg_set_insn_trace_options, options); } + +/// Post a set_insn_trace_options() request + +inline void idaapi request_set_insn_trace_options(int options) { callui(ui_dbg_request_set_insn_trace_options, options); } + +//@} dbg_funcs_trcins + + +//-------------------------------------------------------------------- +// F U N C T I O N S T R A C I N G +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_trcfunc Functions tracing +/// \ingroup dbg_funcs_tracing +/// +/// Each call to a function or return from a function is stored +/// in the tracing buffer. +//@{ + +/// Get current state of functions tracing. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline bool idaapi is_func_trace_enabled(void) { return callui(ui_dbg_is_func_trace_enabled).cnd; } + + +/// \name Enable/Disable functions tracing +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +//@{ +inline bool idaapi enable_func_trace(bool enable = true) { return callui(ui_dbg_enable_func_trace, enable).cnd; } +inline bool disable_func_trace(void) { return enable_func_trace(false); } +inline bool idaapi request_enable_func_trace(bool enable = true) { return callui(ui_dbg_request_enable_func_trace, enable).cnd; } +inline bool request_disable_func_trace(void) { return request_enable_func_trace(false); } +//@} + + +/// Get current function tracing options. +/// Also see #FT_LOG_RET +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline int idaapi get_func_trace_options(void) { return callui(ui_dbg_get_func_trace_options).i; } + + +/// Modify function tracing options. +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} + +inline void idaapi set_func_trace_options(int options) { callui(ui_dbg_set_func_trace_options, options); } + +/// Post a set_func_trace_options() request + +inline void idaapi request_set_func_trace_options(int options) { callui(ui_dbg_request_set_func_trace_options, options); } + +//@} dbg_funcs_trcfunc + + +//-------------------------------------------------------------------- +// B A S I C B L O C K T R A C I N G +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_trcbb Basic block tracing +/// \ingroup dbg_funcs_tracing +//@{ + +// Modify basic block tracing options. +// Type: Synchronous function - available as Request +// Notification: none (synchronous function) + + +/// \name Enable/Disable basic blocks tracing +/// \sq{Type, Synchronous function - available as request, +/// Notification, none (synchronous function)} +//@{ +inline bool idaapi enable_bblk_trace(bool enable = true) { return callui(ui_dbg_enable_bblk_trace, enable).cnd; } +inline bool disable_bblk_trace(void) { return enable_bblk_trace(false); } +inline bool idaapi request_enable_bblk_trace(bool enable = true) { return callui(ui_dbg_request_enable_bblk_trace, enable).cnd; } +inline bool request_disable_bblk_trace(void) { return request_enable_bblk_trace(false); } +inline bool idaapi is_bblk_trace_enabled(void) { return callui(ui_dbg_is_bblk_trace_enabled).cnd; } +//@} + +/// Get current basic block tracing options. +/// Also see #BT_LOG_INSTS +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline int idaapi get_bblk_trace_options(void) { return callui(ui_dbg_get_bblk_trace_options).i; } + + +/// Modify basic block tracing options (see #BT_LOG_INSTS) + +inline void idaapi set_bblk_trace_options(int options) { callui(ui_dbg_set_bblk_trace_options, options); } + +/// Post a set_bblk_trace_options() request + +inline void idaapi request_set_bblk_trace_options(int options) { callui(ui_dbg_request_set_bblk_trace_options, options); } + +//@} dbg_funcs_trcbb + +#endif // __UI__ + +//-------------------------------------------------------------------- +// T R A C I N G E V E N T S +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_trcev Tracing events +/// \ingroup dbg_funcs_tracing +//@{ + +/// Trace event types +enum tev_type_t +{ + tev_none = 0, ///< no event + tev_insn, ///< an instruction trace + tev_call, ///< a function call trace + tev_ret, ///< a function return trace + tev_bpt, ///< write, read/write, execution trace + tev_mem, ///< memory layout changed + tev_event, ///< debug event occurred + tev_max, ///< first unused event type +}; + +typedef qvector<debug_event_t> dbgevt_vec_t; ///< vector of debug events + +/// Common information for all trace events +struct tev_info_t +{ + tev_type_t type; ///< trace event type + thid_t tid; ///< thread where the event was recorded + ea_t ea; ///< address where the event occurred +}; +typedef qvector<tev_info_t> tevinfo_vec_t; ///< vector of trace event info objects + + +/// Required typedef for get_insn_tev_reg_mem() +struct memreg_info_t +{ + ea_t ea; + bytevec_t bytes; +}; +DECLARE_TYPE_AS_MOVABLE(memreg_info_t); +typedef qvector<memreg_info_t> memreg_infos_t; + + +#ifndef __UI__ + +/// Get number of trace events available in trace buffer. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline int idaapi get_tev_qty(void) { return callui(ui_dbg_get_tev_qty).i; } + + +/// Get main information about a trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \param[out] tev_info result +/// \return success + +inline bool idaapi get_tev_info(int n, tev_info_t *tev_info) { return callui(ui_dbg_get_tev_info, n, tev_info).cnd; } + + +/// Read a register value from an instruction trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \param regname name of desired register +/// \param[out] regval result +/// \return false if not an instruction event. +/// \note This is the value of the register before the execution of +/// the instruction. + +inline bool idaapi get_insn_tev_reg_val(int n, const char *regname, regval_t *regval) { return callui(ui_dbg_get_insn_tev_reg_val, n, regname, regval).cnd; } + +inline bool idaapi get_insn_tev_reg_val(int n, const char *regname, uint64 *ival) { return callui(ui_dbg_get_insn_tev_reg_val_i, n, regname, ival).cnd; } + + +/// Read the memory pointed by register values from an instruction trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \param[out] memmap result +/// \return false if not an instruction event or no memory is available + +inline bool idaapi get_insn_tev_reg_mem(int n, memreg_infos_t *memmap) { return callui(ui_dbg_get_insn_tev_reg_mem, n, memmap).cnd; } + + +/// Read the resulting register value from an instruction trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \param regname name of desired register +/// \param[out] regval result +/// \return false if not an instruction trace event or register wasn't modified. + +inline bool idaapi get_insn_tev_reg_result(int n, const char *regname, regval_t *regval) { return callui(ui_dbg_get_insn_tev_reg_result, n, regname, regval).cnd; } + +inline bool idaapi get_insn_tev_reg_result(int n, const char *regname, uint64 *ival) { return callui(ui_dbg_get_insn_tev_reg_result_i, n, regname, ival).cnd; } + + +/// Get the called function from a function call trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \return #BADADDR if not a function call event. + +inline ea_t idaapi get_call_tev_callee(int n) { ea_t ea; callui(ui_dbg_get_call_tev_callee, n, &ea); return ea; } + + +/// Get the return address from a function return trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \return #BADADDR if not a function return event. + +inline ea_t idaapi get_ret_tev_return(int n) { ea_t ea; callui(ui_dbg_get_ret_tev_return, n, &ea); return ea; } + + +/// Get the address associated to a read, read/write or execution trace event. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \return #BADADDR if not a read, read/write or execution trace event. +/// \note Usually, a breakpoint is associated with a read, read/write or execution +/// trace event. However, the returned address could be any address in the +/// range of this breakpoint. +/// If the breakpoint was deleted after the trace event, the address no longer +/// corresponds to a valid breakpoint. + +inline ea_t idaapi get_bpt_tev_ea(int n) { ea_t ea; callui(ui_dbg_get_bpt_tev_ea, n, &ea); return ea; } + + +/// Get the memory layout, if any, for the specified tev object. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \param[out] mi result +/// \return false if the tev_t object is not of type ::tev_mem, true otherwise, +/// with the new memory layout in "mi". + +inline bool idaapi get_tev_memory_info(int n, meminfo_vec_t *mi) { return callui(ui_dbg_get_tev_memory_info, n, mi).cnd; } + + +/// Get the corresponding debug event, if any, for the specified tev object. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \param n number of trace event, is in range 0..get_tev_qty()-1. +/// 0 represents the latest added trace event. +/// \param[out] d result +/// \return false if the tev_t object doesn't have any associated debug +/// event, true otherwise, with the debug event in "d". + +inline bool idaapi get_tev_event(int n, debug_event_t *d) { return callui(ui_dbg_get_tev_event, n, d).cnd; } + + +/// Get the base address of the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return the base address of the currently loaded trace + +inline ea_t idaapi get_trace_base_address(void) { ea_t ea; callui(ui_dbg_get_trace_base_address, &ea); return ea; } + + +/// Set the base address of the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi set_trace_base_address(ea_t ea) { callui(ui_dbg_set_trace_base_address, ea); } + + +/// Add a thread to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi dbg_add_thread(thid_t tid) { callui(ui_dbg_add_thread, tid); } + + +/// Delete a thread from the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi dbg_del_thread(thid_t tid) { callui(ui_dbg_del_thread, tid); } + + +/// Add a new trace element to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi dbg_add_tev(tev_type_t type, thid_t tid, ea_t address) { callui(ui_dbg_add_tev, type, tid, address); } + +#endif // __UI__ + +/// Structure used for dbg_add_many_tevs() +struct tev_reg_value_t +{ + regval_t value; + int reg_idx; + + tev_reg_value_t(int _reg_idx = -1, uint64 _value = uint64(-1)) : reg_idx(_reg_idx) + { + value._set_int(_value); + } +}; +DECLARE_TYPE_AS_MOVABLE(tev_reg_value_t); +typedef qvector<tev_reg_value_t> tev_reg_values_t; ///< vector of trace event reg values + +/// Structure used for dbg_add_many_tevs() +struct tev_info_reg_t +{ + tev_info_t info; + tev_reg_values_t registers; +}; +DECLARE_TYPE_AS_MOVABLE(tev_info_reg_t); +typedef qvector<tev_info_reg_t> tevinforeg_vec_t; ///< vector of trace elements + + +/// Se dbg_add_insn_tev() +enum save_reg_values_t +{ + SAVE_ALL_VALUES = 0, + SAVE_DIFF, + SAVE_NONE +}; + +#ifndef __UI__ + +/// Add many new trace elements to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return false if the operation failed for any ::tev_info_t object + +inline bool idaapi dbg_add_many_tevs(tevinforeg_vec_t *new_tevs) { return callui(ui_dbg_add_many_tevs, new_tevs).cnd; } + + +/// Add a new instruction trace element to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return false if the operation failed, true otherwise + +inline bool idaapi dbg_add_insn_tev(thid_t tid, ea_t ea, save_reg_values_t save = SAVE_DIFF) { return callui(ui_dbg_add_insn_tev, tid, ea, save).cnd; } + + +/// Add a new breakpoint trace element to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} +/// \return false if the operation failed, true otherwise + +inline bool idaapi dbg_add_bpt_tev(thid_t tid, ea_t ea, ea_t bp) { return callui(ui_dbg_add_bpt_tev, tid, ea, bp).cnd; } + + +/// Add a new call trace element to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi dbg_add_call_tev(thid_t tid, ea_t caller, ea_t callee) { callui(ui_dbg_add_call_tev, tid, caller, callee); } + + +/// Add a new return trace element to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi dbg_add_ret_tev(thid_t tid, ea_t ret_insn, ea_t return_to) { callui(ui_dbg_add_ret_tev, tid, ret_insn, return_to); } + + +/// Add a new debug event to the current trace. +/// \sq{Type, Synchronous function, +/// Notification, none (synchronous function)} + +inline void idaapi dbg_add_debug_event(debug_event_t *event) { callui(ui_dbg_add_debug_event, event); } + +//@} dbg_funcs_trcev + + +//--------------------------------------------------------------------------- +// Trace management functions +//--------------------------------------------------------------------------- +/// \defgroup dbg_funcs_trcm Trace management functions +/// \ingroup dbg_funcs_tracing +//@{ + +/// Load a recorded trace file in the 'Tracing' window. +/// If the call succeeds and 'buf' is not null, the description of the +/// trace stored in the binary trace file will be returned in 'buf' + +inline bool idaapi load_trace_file(qstring *buf, const char *filename) { return callui(ui_dbg_load_trace_file, buf, filename).cnd; } + + +/// Save the current trace in the specified file + +inline bool idaapi save_trace_file(const char *filename, const char *description) { return callui(ui_dbg_save_trace_file, filename, description).cnd; } + + +/// Is the specified file a valid trace file for the current database? + +inline bool idaapi is_valid_trace_file(const char *filename) { return callui(ui_dbg_is_valid_trace_file, filename).cnd; } + + +/// Change the description of the specified trace file + +inline bool idaapi set_trace_file_desc(const char *filename, const char *description) { return callui(ui_dbg_set_trace_file_desc, filename, description).cnd; } + + +/// Get the file header of the specified trace file + +inline bool idaapi get_trace_file_desc(qstring *buf, const char *filename) { return callui(ui_dbg_get_trace_file_desc, buf, filename).cnd; } + + +/// Show the choose trace dialog + +inline bool idaapi choose_trace_file(qstring *buf) { return callui(ui_dbg_choose_trace_file, buf).cnd; } + + +/// Show difference between the current trace and the one from 'filename' + +inline bool idaapi diff_trace_file(const char *NONNULL filename) { return callui(ui_dbg_diff_trace_file, filename).cnd; } + + +/// Show the trace callgraph + +inline bool idaapi graph_trace(void) { return callui(ui_dbg_graph_trace).cnd; } + + +/// Set highlight trace parameters. + +inline void idaapi set_highlight_trace_options( + bool hilight, + bgcolor_t color, + bgcolor_t diff) +{ + callui(ui_dbg_set_highlight_trace_options, hilight, color, diff); +} + + +/// Set platform name of current trace + +inline void idaapi set_trace_platform(const char *platform) { callui(ui_dbg_set_trace_platform, platform); } + + +/// Get platform name of current trace + +inline const char *idaapi get_trace_platform() { return callui(ui_dbg_get_trace_platform).cptr; } + + +/// Set dynamic register set of current trace + +inline void idaapi set_trace_dynamic_register_set(dynamic_register_set_t &idaregs) { callui(ui_dbg_set_trace_dynamic_register_set, &idaregs); } + + +/// Get dynamic register set of current trace + +inline void idaapi get_trace_dynamic_register_set(dynamic_register_set_t *idaregs) { callui(ui_dbg_get_trace_dynamic_register_set, idaregs); } + +//@} dbg_funcs_trcm + +#endif // __UI__ + +//--------------------------------------------------------------------------- +// High level functions (usable from scripts) +//-------------------------------------------------------------------- +/// \defgroup dbg_funcs_high High level functions +/// \ingroup dbg_funcs +/// +/// These functions can be used from scripts +//@{ + +/// Wait for the next debugger event. +/// See also get_process_state() to get info about the current state +/// of the debugged application + +/// Debugger event codes +enum dbg_event_code_t +{ + DEC_NOTASK = -2, ///< process does not exist + DEC_ERROR = -1, ///< error + DEC_TIMEOUT = 0, ///< timeout +}; + +/// \defgroup WFNE_ Wait for debugger event flags +/// Passed as 'wfne' parameter to wait_for_next_event() +//@{ +#define WFNE_ANY 0x0001 ///< return the first event (even if it doesn't suspend the process) +#define WFNE_SUSP 0x0002 ///< wait until the process gets suspended +#define WFNE_SILENT 0x0004 ///< 1: be slient, 0:display modal boxes if necessary +#define WFNE_CONT 0x0008 ///< continue from the suspended state +#define WFNE_NOWAIT 0x0010 ///< do not wait for any event, immediately return ::DEC_TIMEOUT + ///< (to be used with #WFNE_CONT) +#define WFNE_USEC 0x0020 ///< timeout is specified in microseconds + ///< (minimum non-zero timeout is 40000us) +//@} + +/// \defgroup DOPT_ Debugger options +/// Passed as 'options' parameter to set_debugger_options() +//@{ +#define DOPT_SEGM_MSGS 0x00000001 ///< log debugger segments modifications +#define DOPT_START_BPT 0x00000002 ///< break on process start +#define DOPT_THREAD_MSGS 0x00000004 ///< log thread starts/exits +#define DOPT_THREAD_BPT 0x00000008 ///< break on thread start/exit +#define DOPT_BPT_MSGS 0x00000010 ///< log breakpoints +//#define DOPT_BINS_BPT 0x00000020 // break on breakpoint instruction +#define DOPT_LIB_MSGS 0x00000040 ///< log library loads/unloads +#define DOPT_LIB_BPT 0x00000080 ///< break on library load/unload +#define DOPT_INFO_MSGS 0x00000100 ///< log debugging info events +#define DOPT_INFO_BPT 0x00000200 ///< break on debugging information +#define DOPT_REAL_MEMORY 0x00000400 ///< do not hide breakpoint instructions +#define DOPT_REDO_STACK 0x00000800 ///< reconstruct the stack +#define DOPT_ENTRY_BPT 0x00001000 ///< break on program entry point +#define DOPT_EXCDLG 0x00006000 ///< exception dialogs: +# define EXCDLG_NEVER 0x00000000 ///< never display exception dialogs +# define EXCDLG_UNKNOWN 0x00002000 ///< display for unknown exceptions +# define EXCDLG_ALWAYS 0x00006000 ///< always display +#define DOPT_LOAD_DINFO 0x00008000 ///< automatically load debug files (pdb) +#define DOPT_END_BPT 0x00010000 ///< evaluate event condition on process end +#define DOPT_TEMP_HWBPT 0x00020000 ///< when possible use hardware bpts for temp bpts +#define DOPT_FAST_STEP 0x00040000 ///< prevent debugger memory refreshes when single-stepping +//@} + + +#ifndef __UI__ + +/// Wait for the next event. +/// +/// This function (optionally) resumes the process execution, +/// and waits for a debugger event until a possible timeout occurs. +/// +/// \param wfne combination of \ref WFNE_ constants +/// \param timeout number of seconds to wait, -1-infinity +/// \return either an event_id_t (if > 0), or a dbg_event_code_t (if <= 0) + +inline dbg_event_code_t idaapi wait_for_next_event(int wfne, int timeout) { return dbg_event_code_t(callui(ui_dbg_wait_for_next_event, wfne, timeout).i); } + + +/// Get the current debugger event + +inline const debug_event_t *idaapi get_debug_event(void) { return (const debug_event_t *)callui(ui_dbg_get_debug_event).vptr; } + + +/// Set debugger options. +/// Replaces debugger options with the specification combination \ref DOPT_ +/// \return the old debugger options + +inline uint idaapi set_debugger_options(uint options) { return callui(ui_dbg_set_debugger_options, options).i; } + + +/// Set remote debugging options. +/// Should be used before starting the debugger. +/// \param host If empty, IDA will use local debugger. +/// If NULL, the host will not be set. +/// \param pass If NULL, the password will not be set +/// \param port If -1, the default port number will be used + +inline void idaapi set_remote_debugger(const char *host, const char *pass, int port=-1) { callui(ui_dbg_set_remote_debugger, host, pass, port); } + + +/// Get process options. +/// Any of the arguments may be NULL + +inline void idaapi get_process_options( + qstring *path, + qstring *args, + qstring *sdir, + qstring *host, + qstring *pass, + int *port) +{ + callui(ui_dbg_get_process_options, path, args, sdir, host, pass, port); +} + + +/// Set process options. +/// Any of the arguments may be NULL, which means 'do not modify' + +inline void idaapi set_process_options( + const char *path, + const char *args, + const char *sdir, + const char *host, + const char *pass, + int port) +{ + callui(ui_dbg_set_process_options, path, args, sdir, host, pass, port); +} + + +/// Retrieve the exception information. +/// You may freely modify the returned vector and add/edit/delete exceptions +/// You must call store_exceptions() after any modifications +/// Note: exceptions with code zero, multiple exception codes or names are prohibited + +inline excvec_t *idaapi retrieve_exceptions(void) { return (excvec_t *)callui(ui_dbg_retrieve_exceptions).vptr; } + + +/// Update the exception information stored in the debugger module by +/// invoking its dbg->set_exception_info callback + +inline bool idaapi store_exceptions(void) { return callui(ui_dbg_store_exceptions).cnd; } + + +/// Convenience function: define new exception code. +/// \param code exception code (cannot be 0) +/// \param name exception name (cannot be empty or NULL) +/// \param desc exception description (maybe NULL) +/// \param flags combination of \ref EXC_ +/// \return failure message or NULL. +/// You must call store_exceptions() if this function succeeds + +inline const char *idaapi define_exception(uint code, const char *name, const char *desc, int flags) { return callui(ui_dbg_define_exception, code, name, desc, flags).cptr; } + +#endif // __UI__ + + +//-------------------------------------------------------------------- + +/// Is set_dbg_options() present in ::debugger_t? + +inline THREAD_SAFE bool have_set_options(const debugger_t *_dbg) +{ + return _dbg != NULL && _dbg->set_dbg_options != NULL; +} + +//-------------------------------------------------------------------- + +/// Convenience function to set debugger specific options. It checks if the debugger +/// is present and the function is present and calls it. + +inline const char *idaapi set_dbg_options( + debugger_t *_dbg, + const char *keyword, + int pri, + int value_type, + const void *value) +{ + const char *code = IDPOPT_BADKEY; + if ( have_set_options(_dbg) ) + code = _dbg->set_dbg_options(keyword, pri, value_type, value); + return code; +} + + +inline const char *idaapi set_dbg_default_options( + debugger_t *_dbg, + const char *keyword, + int value_type, + const void *value) +{ + return set_dbg_options(_dbg, keyword, IDPOPT_PRI_DEFAULT, value_type, value); +} + +inline const char *idaapi set_int_dbg_options( + debugger_t *_dbg, + const char *keyword, + int32 value) +{ + sval_t sv = value; + return set_dbg_default_options(_dbg, keyword, IDPOPT_NUM, &sv); +} + +#ifndef __KERNEL__ +/// Set options for ::dbg + +inline const char *idaapi set_dbg_options( + const char *keyword, + int pri, + int value_type, + const void *value) +{ + return set_dbg_options(dbg, keyword, pri, value_type, value); +} + +/// Set ::dbg options with #IDPOPT_PRI_DEFAULT + +inline const char *idaapi set_dbg_default_options( + const char *keyword, + int value_type, + const void *value) +{ + return set_dbg_options(keyword, IDPOPT_PRI_DEFAULT, value_type, value); +} + +/// Set an integer value option for ::dbg + +inline const char *idaapi set_int_dbg_options( + const char *keyword, + int32 value) +{ + sval_t sv = value; + return set_dbg_default_options(keyword, IDPOPT_NUM, &sv); +} +#endif // __KERNEL__ + +//@} dbg_funcs_high + +//--------------------------------------------------------------------------- +// S O U R C E I N F O R M A T I O N P R O V I D E R S +//--------------------------------------------------------------------------- +/// \defgroup dbg_funcs_srcinfo Source information providers +/// \ingroup dbg_funcs +/// +/// These providers supply information about the source files and lines +/// to the source level debugger. +/// +/// \note objects that inherit from ::qrefcnt_obj_t must be freed +/// using the release() method. do not use the 'delete' operator! +/// See description for qrefcnt_obj_t::release() +/// +/// Currently this interface is not frozen and may change. +/// We will freeze it once we settle things down. +//@{ + +class srcinfo_provider_t; + +class idc_value_t; +class rangeset_t; +class source_item_t; +class argloc_t; + +/// Maintain a reference count for source items +typedef qrefcnt_t<source_item_t> source_item_ptr; +/// Iterator for source items +typedef qiterator<source_item_ptr> _source_item_iterator; +/// Maintain a reference count for source item iterators +typedef qrefcnt_t<_source_item_iterator> source_item_iterator; +/// Vector of source items +typedef qvector<source_item_ptr> source_items_t; + +//-------------------------------------------------------------------------- +/// Execution context. Currently not defined in detail. Will probably +/// hold information about the execution context, like: +/// - thread id +/// - current register values +/// - stack frame address + +class eval_ctx_t +{ + int size_cb; +public: + eval_ctx_t(ea_t _ea) : size_cb(sizeof(*this)), ea(_ea) {} + ea_t ea; +}; + + +#ifndef __UI__ +class TWidget; +#endif + +//-------------------------------------------------------------------------- +/// Describes a source file +class source_file_t : public qrefcnt_obj_t +{ +public: + /// Call this function to free source_file_t + virtual void idaapi release() override = 0; + + /// Get source info provider. + /// There is no need to free or release it after using + virtual srcinfo_provider_t *idaapi get_provider(void) const = 0; + + /// Get path to the source file (or a symbolic name). + /// \param[out] errbuf pointer to buffer for the error message + virtual const char *idaapi get_path(qstring *errbuf) = 0; + + /// Open window with source code (optional function). + /// \param[out] strvec pointer to source text. the text should not be destroyed until the form is closed + /// \param[out] pview pointer to view that displays the source text (subview of TWidget) + /// \param lnnum,colnum cursor coordinates + virtual TWidget *open_srcview(strvec_t **strvec, TWidget **pview, int lnnum, int colnum) = 0; + + /// Read entire file (colored lines). + /// \param[out] buf pointer to output buffer + /// \param[out] errbuf pointer to buffer for the error message + virtual bool idaapi read_file(strvec_t *buf, qstring *errbuf) = 0; +}; + +/// Maintain a reference count for source file objects +typedef qrefcnt_t<source_file_t> source_file_ptr; +/// Iterator for source files +typedef qiterator<source_file_ptr> _source_file_iterator; +/// Maintain a reference count for source file iterators +typedef qrefcnt_t<_source_file_iterator> source_file_iterator; + +//-------------------------------------------------------------------------- +/// Kinds of source items. +/// Source items are organized into trees. Each tree starts with a MODULE. +/// Each MODULE consists of FUNC and STTVAR global items. +/// Each FUNC consists of STMTs (statements). +/// Each STMT contains some EXPRs (expressions). +enum src_item_kind_t +{ + SRCIT_NONE, ///< unknown + SRCIT_MODULE, ///< module + SRCIT_FUNC, ///< function + SRCIT_STMT, ///< a statement (if/while/for...) + SRCIT_EXPR, ///< an expression (a+b*c) + SRCIT_STTVAR, ///< static variable/code + SRCIT_LOCVAR ///< a stack, register, or register-relative local variable or parameter +}; + +//-------------------------------------------------------------------------- +/// Describes a subdivision of source information +class source_item_t : public qrefcnt_obj_t +{ +public: + /// Call this function to free source_item_t + virtual void idaapi release() override = 0; + + /// Get source files of the item + virtual source_file_iterator idaapi get_source_files() = 0; + + /// Get name of the item + virtual bool idaapi get_name(qstring *buf) const = 0; + + /// Get line number of the item (1-based) + virtual int idaapi get_lnnum() const = 0; + + /// Get ending line number (1-based.) + /// The returned line number is the next + /// line after the expression + virtual int idaapi get_end_lnnum() const = 0; + + /// Get column number of the item. + /// If unknown, return -1 + virtual int idaapi get_colnum() const = 0; + + /// Get ending column number. + /// The returned column number is the next + /// column after the expression. + /// If unknown, return -1 + virtual int idaapi get_end_colnum() const = 0; + + /// Get starting address of the item + virtual ea_t idaapi get_ea() const = 0; + + /// Get size of the item in bytes. + /// If the item is fragmented, return size + /// of the main fragment. + /// if unknown, return 0. + /// On error, return (asize_t) -1. + virtual asize_t idaapi get_size() const = 0; + + /// Get item boundaries as a set of ranges. + /// This function will be used to determine what breakpoints to set for + /// stepping into/stepping over the item. + virtual bool idaapi get_item_bounds(rangeset_t *set) const = 0; + + /// Get parent of the item. + /// \param max_kind maximal source item kind we are interested in. + /// for example, if max_kinds==#SRCIT_STMT, we are not interested + /// in expressions, only in the enclosing statement or function + virtual source_item_ptr idaapi get_parent(src_item_kind_t max_kind) const = 0; + + /// Create an iterator to enumerate all children of the item + virtual source_item_iterator idaapi create_children_iterator() = 0; + + /// Calculate a string to display as a hint. + /// \param hint output buffer for the hint (may by multiline & with colors) + /// \param ctx execution context. NULL means missing context. + /// \param nlines number of important lines in the hint + virtual bool idaapi get_hint( + qstring *hint, + const eval_ctx_t *ctx, + int *nlines) const = 0; + + /// Evaluate item value (meaningful only for expression items). + /// \param ctx execution context. NULL means missing context. + /// \param res buffer for the result (or exception if evaluation failed) + /// \param errbuf buffer for the error message + virtual bool idaapi evaluate( + const eval_ctx_t *ctx, + idc_value_t *res, + qstring *errbuf) const = 0; + + /// Do these two items have the same source?. + /// \retval false the source of the underlying data + /// differs between the two items. + /// \retval true when either the source of the underlying + /// data is the same for the two items, or + /// when such information is not available. + /// + /// E.g., A DWARF implementation of source_item_t will + /// return true if the two items are backed by DIEs + /// that have the same file offset. + virtual bool idaapi equals(const source_item_t *other) const = 0; + + /// \name Getters (for modification) + /// The following functions can be used to extract the item information + /// in order to modify it. For example, if the user wants to modify a variable + /// we will find what exactly needs to be modified. + //@{ + + /// Get item kind + virtual src_item_kind_t idaapi get_item_kind(const eval_ctx_t * /*ctx*/) const newapi { return SRCIT_NONE; } + /// Does this source item represent a statement? + bool is_stmt(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_STMT; } + /// Does this source item represent a module? + bool is_module(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_MODULE; } + /// Does this source item represent a function? + bool is_func(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_FUNC; } + /// Does this source item represent an expression? + bool is_expr(const eval_ctx_t *ctx) const { return get_item_kind(ctx) >= SRCIT_EXPR; } + /// Does this source item represent a stack, register, or register-relative local variable or parameter? + bool is_locvar(const eval_ctx_t *ctx) const { return get_item_kind(ctx) >= SRCIT_LOCVAR; } + /// Does this source item represent a static variable or code? + bool is_sttvar(const eval_ctx_t *ctx) const { return get_item_kind(ctx) == SRCIT_STTVAR; } + + /// Get source info provider. + /// The instance shouldn't be freed or released after using + virtual srcinfo_provider_t *idaapi get_provider(void) const = 0; + + /// Get the location for this source item + virtual bool idaapi get_location(argloc_t * /*out*/, const eval_ctx_t * /*ctx*/) const newapi { return false; } + + /// Get expression type + virtual bool idaapi get_expr_tinfo(tinfo_t *tif) const = 0; + //@} +}; + +#define SRCDBG_PROV_VERSION 4 + +//-------------------------------------------------------------------------- +/// Describes the mechanism used to retrieve source file information +class srcinfo_provider_t +{ +public: + /// size of this class + size_t cb; + + /// \ref SPF_ + int flags; +/// \defgroup SPF_ Source info provider property bits +/// Used by srcinfo_provider_t::flags +//@{ +#define SPF_DECOMPILER 0x0001 ///< is a decompiler? +#define SPF_ENABLED 0x0002 ///< enabled by the user + ///< (this bit is managed by ida) +#define SPF_ACTIVE 0x0004 ///< is willing to work with the current idb + ///< (this bit is managed by ida) +#define SPF_VERSION_MASK 0xFF000000 ///< Version mask, in the flags. + ///< No other flag should have a bit rank > 23. +//@} + + /// internal (unique) name of srcinfo provider + const char *name; + + /// external (displayable) name of srcinfo provider + const char *display_name; + + srcinfo_provider_t(const char *_name, const char *_display_name, int _flags=0) + : cb(sizeof(*this)), flags(_flags), name(_name), display_name(_display_name) + { + flags |= SRCDBG_PROV_VERSION << 24; + } + + /// Is the source info provider a decompiler? + bool is_decompiler(void) const { return (flags & SPF_DECOMPILER) != 0; } + /// Has the provider been enabled by the user? + bool is_enabled(void) const { return (flags & SPF_ENABLED) != 0; } + /// Is the provider willing to work with the current idb? + bool is_active(void) const { return (flags & SPF_ACTIVE) != 0; } + + /// See #SPF_VERSION_MASK + uint8 get_version() const { return (flags >> 24) & 0xFF; } + + /// Enable or disable the provider. + /// If the provider fails to initialize, it returns false, otherwise true + virtual bool idaapi enable_provider(bool enable) = 0; + + /// Configure srcinfo provider. + /// See the description of ::set_options_t + virtual const char *idaapi set_options( + const char *keyword, + int value_type, + const void *value) = 0; + + /// Inform the provider that a module got loaded. + /// The provider is not required to read the module information immediately; + /// it may postpone it until really required. + virtual void idaapi add_module(const char *path, ea_t base, asize_t size) = 0; + + /// Inform the provider that a module got unloaded. + virtual void idaapi del_module(ea_t base) = 0; + + /// Inform the provider that we will request for information now. + /// This function must be called before calling all functions below. + /// probably it will be called when the process gets suspended. + virtual void idaapi get_ready(void) = 0; + + /// Ask the provider if the source information has changed + /// and the screen should be refreshed. UI will call this function + /// periodically (when idle). if it returns a flag value other than #SPCH_NONE, + /// then the source information must be refreshed. + virtual int idaapi get_change_flags(void) = 0; +/// \defgroup SPCH_ Source info changed flags +/// Returned by srcinfo_provider_t::get_change_flags() +//@{ +#define SPCH_NONE 0x0000 ///< nothing has changed +#define SPCH_FILES 0x0001 ///< source files have changed +#define SPCH_ITEMS 0x0002 ///< source items have changed +#define SPCH_LINES 0x0004 ///< source line numbers have changed +//@} + + /// Locate source item by address. + /// The kernel will inquire all registered providers and use the best reply. + /// \param ea linear address + /// \param size size of the item + /// \param level the desired item level: + /// - ::SRCIT_STMT: a statement + /// - ::SRCIT_EXPR: an expression + /// - ::SRCIT_FUNC: a global code item + /// - SRCIT_xxxVAR: a global data item (the exact type is not checked) + /// \param may_decompile meaningful only for the decompiler. if set to false + /// and the function at 'ea' has not been decompiled yet, fail. + virtual source_item_iterator idaapi find_source_items( + ea_t ea, + asize_t size, + src_item_kind_t level, + bool may_decompile) = 0; + + /// Locate source item by a position in a source file. + /// if colnum == 0, return the statement that starts at the specified line. + /// if lnnum == 0, return information about all lines (colnum is ignored in this case) + virtual source_item_iterator idaapi find_source_items(source_file_t *sf, int lnnum, int colnum=0) = 0; + + /// Create iterators to enumerate files. + /// \param filename name of the source file to enumerate + virtual source_file_iterator idaapi create_file_iterator(const char *filename=NULL) = 0; + + /// Create iterators to enumerate items + virtual source_item_iterator idaapi create_item_iterator(const source_file_t *sf) = 0; + + /// Apply the debug information (types, functions, globals) + /// from the module whose path is 'path', to the IDB + virtual bool idaapi apply_module_info(const char * /*path*/) { return false; } + + /// Locate a global variable by its name. + /// \param name The variable name + /// \param ea The current address + /// \return the source item, or NULL + virtual source_item_ptr idaapi find_static_item(const char *name, ea_t ea) = 0; +}; + + +//-------------------------------------------------------------------------- +/// Register a source information provider. +/// Source information providers will call this function to register themselves +/// with IDA kernel. +/// Returns false: a service provider with this name already exists. + +inline bool idaapi register_srcinfo_provider(srcinfo_provider_t *sp) { return callui(ui_dbg_register_provider, sp).cnd; } + + +/// Unregister a source information provider. +/// Returns false: no such provider. + +inline bool idaapi unregister_srcinfo_provider(srcinfo_provider_t *sp) { return callui(ui_dbg_unregister_provider, sp).cnd; } + + +#ifndef __UI__ +class source_view_t; + +/// Create a source code view + +inline source_view_t *create_source_viewer( + TWidget **out_ccv, + TWidget *parent, + TWidget *custview, + source_file_ptr sf, + strvec_t *lines, + int lnnum, + int colnum, + int flags) +{ + return (source_view_t *) callui( + ui_create_source_viewer, out_ccv, parent, custview, &sf, + lines, lnnum, colnum, flags).vptr; +} + +#endif + +//-------------------------------------------------------------------------- +/// Get one byte of the debugged process memory. +/// \param x pointer to byte value +/// \param ea linear address +/// \return true success +/// \return false address inaccessible or debugger not running + +idaman bool ida_export get_dbg_byte(uint32 *x, ea_t ea); + + +/// Change one byte of the debugged process memory. +/// \param ea linear address +/// \param x byte value +/// \return true if the process memory has been modified + +idaman bool ida_export put_dbg_byte(ea_t ea, uint32 x); + +//@} dbg_funcs_srcinfo + +//-------------------------------------------------------------------------- +// D E B U G G E R M E M O R Y F U N C T I O N S F O R U I +//-------------------------------------------------------------------------- +/// \defgroup dbg_funcs_mem Debugger memory functions for UI +/// \ingroup dbg_funcs +/// +/// Inspect debugged process memory. +//@{ + +/// Set the memory information source for IDA kernel. +/// This function allows the kernel to use information coming from somewhere +/// other than the database (from the debugger, for example) +/// \param dbg_get_memory_config returns current memory configuration +/// in the dynamic memory allocated by qalloc(). +/// The kernel will qfree() it automatically. +/// If this argument is NULL, then the debugged +/// process memory is not used. +/// - n: number of ::range_t elements in the answer +/// \param memory_read read bytes from the debugged process memory +/// \param memory_write write bytes to the debugged process memory +/// (don't forget to call invalidate_dbgmem_contents() from it) + +idaman void ida_export set_dbgmem_source( + range_t *(idaapi*dbg_get_memory_config)(int *n), + int (idaapi*memory_read) (ea_t ea, void *buffer, int size), + int (idaapi*memory_write)(ea_t ea, const void *buffer, int size)); + + +/// Invalidate the debugged process memory configuration. +/// Call this function if the debugged process might have changed its memory +/// layout (allocated more memory, for example) + +idaman void ida_export invalidate_dbgmem_config(void); + + +/// Invalidate the debugged process memory contents. +/// Call this function each time the process has been stopped or the process +/// memory is modified. +/// If ea == #BADADDR, then the whole memory contents will be invalidated + +idaman void ida_export invalidate_dbgmem_contents(ea_t ea, asize_t size); + + +/// Is the debugger currently running? + +idaman bool ida_export is_debugger_on(void); + + +/// Is the address mapped to debugger memory? + +idaman bool ida_export is_debugger_memory(ea_t ea); + +//@} dbg_funcs_mem + +//------------------------------------------------------------------------ +#ifndef __UI__ // Not for the UI + + +/// \defgroup dbg_funcs_conv Misc +/// \ingroup dbg_funcs +/// +/// Convenience functions offered by the user interface +//@{ +inline ea_t idaapi get_tev_ea(int n) { ea_t ea; callui(ui_dbg_get_tev_ea, n, &ea); return ea; } +inline int idaapi get_tev_type(int n) { return callui(ui_dbg_get_tev_type, n).i; } +inline int idaapi get_tev_tid(int n) { return callui(ui_dbg_get_tev_tid, n).i; } +inline bool idaapi get_module_info(ea_t ea, modinfo_t *modinfo) { return callui(ui_dbg_get_module_info, ea, modinfo).cnd; } +inline void idaapi bring_debugger_to_front(void) { callui(ui_dbg_bring_to_front); } +inline bool idaapi collect_stack_trace(thid_t tid, call_stack_t *trace) { return callui(ui_dbg_collect_stack_trace, tid, trace).cnd; } +inline const char *idaapi get_debugger_event_cond(void) { return callui(ui_dbg_get_event_cond).cptr; } +inline void idaapi set_debugger_event_cond(const char *NONNULL evcond) { callui(ui_dbg_set_event_cond, evcond); } +inline bool idaapi load_debugger(const char *dbgname, bool use_remote) { return callui(ui_dbg_load_debugger, dbgname, use_remote).cnd; } +inline void idaapi get_manual_regions(meminfo_vec_t *ranges) { callui(ui_dbg_get_manual_regions, ranges); } +inline void idaapi set_manual_regions(const meminfo_vec_t *ranges) { callui(ui_dbg_set_manual_regions, ranges); } +inline void idaapi edit_manual_regions() { callui(ui_dbg_edit_manual_regions); } +inline void idaapi enable_manual_regions(bool enable) { callui(ui_dbg_enable_manual_regions, enable); } +inline int idaapi hide_all_bpts(void) { return callui(ui_dbg_hide_all_bpts).i; } +inline int idaapi handle_debug_event(const debug_event_t *ev, int rqflags) { return callui(ui_dbg_handle_debug_event, ev, rqflags).i; } +inline bool idaapi add_virt_module(const modinfo_t *mod) { return callui(ui_dbg_add_vmod, mod).cnd; } +inline bool idaapi del_virt_module(const ea_t base) { return callui(ui_dbg_del_vmod, base).cnd; } +inline int idaapi set_bptloc_string(const char *s) { return callui(ui_dbg_set_bptloc_string, s).i; } +inline const char *idaapi get_bptloc_string(int i) { return callui(ui_dbg_get_bptloc_string, i).cptr; } +inline int idaapi internal_cleanup_appcall(thid_t tid) { return callui(ui_dbg_internal_cleanup_appcall, tid).i; } +inline int idaapi internal_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value) { return callui(ui_dbg_internal_get_sreg_base, answer, tid, sreg_value).i; } +inline int idaapi internal_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize) { return callui(ui_dbg_internal_ioctl, fn, buf, size, poutbuf, poutsize).i; } +inline ssize_t idaapi read_dbg_memory(ea_t ea, void *buffer, size_t size) { return callui(ui_dbg_read_memory, ea, buffer, size).ssize; } +inline ssize_t idaapi write_dbg_memory(ea_t ea, const void *buffer, size_t size) { return callui(ui_dbg_write_memory, ea, buffer, size).ssize; } +inline int idaapi get_reg_vals(thid_t tid, int clsmask, regval_t *values) { return callui(ui_dbg_read_registers, tid, clsmask, values).i; } +inline int idaapi set_reg_val(thid_t tid, int regidx, const regval_t *value) { return callui(ui_dbg_write_register, tid, regidx, value).i; } +inline int idaapi get_dbg_memory_info(meminfo_vec_t *ranges) { return callui(ui_dbg_get_memory_info, ranges).i; } +inline void idaapi set_bpt_group(bpt_t &bpt, const char *grp_name) { callui(ui_dbg_set_bpt_group, &bpt, grp_name); } +inline bool idaapi set_bptloc_group(const bpt_location_t &bptloc, const char *grp_name) { return callui(ui_dbg_set_bptloc_group, &bptloc, grp_name).cnd; } +inline bool idaapi get_bpt_group(qstring *grp_name, const bpt_location_t &bptloc) { return callui(ui_dbg_get_bpt_group, grp_name, &bptloc).cnd; } +inline size_t idaapi list_bptgrps(qstrvec_t *bptgrps) { return callui(ui_dbg_list_bptgrps, bptgrps).ssize; } +inline bool idaapi rename_bptgrp(const char *old_name, const char *new_name) { return callui(ui_dbg_rename_bptgrp, old_name, new_name).cnd; } +inline bool idaapi del_bptgrp(const char *name) { return callui(ui_dbg_del_bptgrp, name).cnd; } +inline ssize_t idaapi get_grp_bpts(bpt_vec_t *bpts, const char *grp_name) { return callui(ui_dbg_get_grp_bpts, bpts, grp_name).ssize; } +inline const char *bpt_t::get_cnd_elang() const { return (const char *)(callui(ui_dbg_internal_get_elang, this).cptr); } +inline bool bpt_t::set_cnd_elang(const char *name) { return callui(ui_dbg_internal_set_elang, this, name).cnd; } +inline srcinfo_provider_t *idaapi get_srcinfo_provider(const char *name) { return (srcinfo_provider_t *)callui(ui_dbg_get_srcinfo_provider, name).vptr; } +inline bool idaapi get_global_var(srcinfo_provider_t *prov, ea_t ea, const char *name, source_item_ptr *out) { return callui(ui_dbg_get_global_var, prov, ea, name, out).cnd; } +inline bool idaapi get_local_var(srcinfo_provider_t *prov, ea_t ea, const char *name, source_item_ptr *out) { return callui(ui_dbg_get_local_var, prov, ea, name, out).cnd; } +inline bool idaapi get_local_vars(srcinfo_provider_t *prov, ea_t ea, source_items_t *out) { return callui(ui_dbg_get_local_vars, prov, ea, out).cnd; } +inline void idaapi add_path_mapping(const char *src, const char *dst) { callui(ui_dbg_add_path_mapping, src, dst); } +inline bool idaapi get_current_source_file(qstring *out) { return callui(ui_dbg_get_current_source_file, out).cnd; } +inline int idaapi get_current_source_line(void) { return callui(ui_dbg_get_current_source_line).i; } +inline bool idaapi srcdbg_step_into(void) { return callui(ui_dbg_srcdbg_step_into).cnd; } +inline bool idaapi srcdbg_request_step_into(void) { return callui(ui_dbg_srcdbg_request_step_into).cnd; } +inline bool idaapi srcdbg_step_over(void) { return callui(ui_dbg_srcdbg_step_over).cnd; } +inline bool idaapi srcdbg_request_step_over(void) { return callui(ui_dbg_srcdbg_request_step_over).cnd; } +inline bool idaapi srcdbg_step_until_ret(void) { return callui(ui_dbg_srcdbg_step_until_ret).cnd; } +inline bool idaapi srcdbg_request_step_until_ret(void) { return callui(ui_dbg_srcdbg_request_step_until_ret).cnd; } +inline drc_t idaapi dbg_bin_search(ea_t *out, ea_t start_ea, ea_t end_ea, const compiled_binpat_vec_t &data, int srch_flags, qstring *errbuf) + { return drc_t(callui(ui_dbg_bin_search, out, start_ea, end_ea, &data, srch_flags, errbuf).i); } +//@} dbg_funcs_conv + +inline bool idaapi dbg_can_query(debugger_t *_dbg) +{ + // Debugger can be queried IIF it is set and either currently in + // suspended state, or can be queried while not in suspended state + return _dbg != NULL && (_dbg->may_disturb() || get_process_state() < DSTATE_NOTASK); +} +#ifndef __KERNEL__ +inline bool idaapi dbg_can_query(void) +{ + return dbg_can_query(dbg); +} +#endif // __KERNEL__ +#endif // __UI__ + + +// internal kernel functions to lock the debugger memory configuration updates +// Do not use these functions! They will be removed! +idaman void ida_export lock_dbgmem_config(void); +idaman void ida_export unlock_dbgmem_config(void); + + +#endif diff --git a/idasdk76/include/demangle.hpp b/idasdk76/include/demangle.hpp new file mode 100644 index 0000000..a1d5d1f --- /dev/null +++ b/idasdk76/include/demangle.hpp @@ -0,0 +1,269 @@ +/* + * CPP/D/Swift Demangler. + * Copyright (c) 2000-2018 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _DEMANGLE_HPP +#define _DEMANGLE_HPP + +// int32 result code +#define ME_INTERR -1 // Internal error +#define ME_PARAMERR -2 // Input parameters are wrong +#define ME_ILLSTR -3 // Incorrectly mangled name +#define ME_SMALLANS -4 // Output buffer is too small + // This code is possible only with the 'old' calling + // form. With the new calling form the output buffer + // will have '...' as the last characters and the + // result code or'ed with the sign bit +#define ME_FRAME -5 // Partial demanging is possible (the input name has + // unrecognized suffix) +#define ME_NOCOMP -6 // Could not determine the compiler +#define ME_ERRAUTO -7 // Specified compiler is impossible for the input name +#define ME_NOHASHMEM -8 // Out of internal indexes-most likely bad input name +#define ME_NOSTRMEM -9 // Out of internal buffers (can't be!:) + +#define ME_NOERROR_LIMIT -10 // Lowest error number. Lower values + // signal about the truncated output name + // (the output buffer is too small) + +#define M_PRCMSK 0x0000000F // If = 0, then data +#define MT_DEFAULT 0x00000001 // 1 - default (for watcom/gnu only this) +#define MT_CDECL 0x00000002 // 2 - __cdecl +#define MT_PASCAL 0x00000003 // 3 - __pascal +#define MT_STDCALL 0x00000004 // 4 - __stdcall +#define MT_FASTCALL 0x00000005 // 5 - __fastcall +#define MT_THISCALL 0x00000006 // 6 - __thiscall [ms & bc => pragma only] +#define MT_FORTRAN 0x00000007 // 7 - __fortran +#define MT_SYSCALL 0x00000008 // 8 - __syscall [without ms] +#define MT_INTERRUPT 0x00000009 // 9 - __interrupt (only with __cdecl!) +#define MT_MSFASTCALL 0x0000000A // A - __msfastcall (bc) +#define MT_CLRCALL 0x0000000B // B - __clrcall (vc7) +#define MT_DMDCALL 0x0000000C // C - __dcall (dm D language abi) +#define MT_VECTORCALL 0x0000000D // D - __vectorcall (vc13) +#define MT_REGCALL 0x0000000E // E - __regcall (icl, clang) + +// reserved +#define MT_LOCALNAME 0x0000000F // f - might be function or data. Currently + // is used only for bc - as the + // identifier for local pascal labels + +#define M_SAVEREGS 0x00000010 // For functions with "__saveregs" + +#define M_CLASS 0x000000E0 // 0 - no keyword (not a member field) +#define MT_PUBLIC 0x00000020 // 1 - public +#define MT_PRIVATE 0x00000040 // 2 - private +#define MT_PROTECT 0x00000060 // 3 - protected +#define MT_MEMBER 0x00000080 // 4 - undetermined (bc/wat/gcc) +#define MT_VTABLE 0x000000A0 // 5 - vtable (bc/gnu) +#define MT_RTTI 0x000000C0 // 6 - typeinfo table (gcc3), witness table (Swift) +// reserved + +#define M_PARMSK 0x0000FF00 // Parameter number mask (excluding ellipsis) + // 255 - >= 255 +#define MT_PARSHF 8 // shift to PARMSK +#define MT_PARMAX 0xFF // Number limiter + // ATT: when CC is __vectorcall and mode is 'C' + // real argscount is unknown. This number is + // total sizeof of all arguments divided to + // sizeof of defptr +#define M_ELLIPSIS 0x00010000 // The function _certainly_ has '...' +#define MT_VOIDARG 0x0001FF00 // If = 0, the func(void), i.e. no parameters +#define M_STATIC 0x00020000 // static + // gcc3 - static data in a function + // might be encountered in object files and + // (possibly) in binaries with debug info +#define M_VIRTUAL 0x00040000 // virtual + // NOTE: for (D) not virtual -- this (counted!) +#define M_AUTOCRT 0x00080000 // Most likely "autogenerated" function (data) + // NOTE: +M_STATIC => "__linkproc__" (bc) + +#define M_TYPMASK 0x00700000 // Special functions (0-regular function) +#define MT_OPERAT 0x00100000 // 1 - operator +#define MT_CONSTR 0x00200000 // 2 - constructor +#define MT_DESTR 0x00300000 // 3 - destructor +#define MT_CASTING 0x00400000 // 4 - type conversion +#define MT_CLRCDTOR 0x00500000 // 5 - delphi2010 CLR ctor/dtor for packages +// reserved + +#define M_TRUNCATE 0x00800000 // Name was truncated by the compiler (bc/va) +#define M_THUNK 0x01000000 // [thunk]: +#define M_ANONNSP 0x02000000 // ms => Anonymous Namespace for field + // gc3 => Item placed in Anonymous namespace + // wat => anonymous_enum + // bc => + TMPLNAM = PascalTemplate (for DCC) + // If separate - "automatic" except_t + // from CBuilder for "external" variables + // or a template for global object + // constructor/destructor tables (for CBuilder + // as well) +#define M_TMPLNAM 0x04000000 // ms => template name (?) + // wat => + // bc => template name => its description table + // gc3 => any template funciton/data +#define M_DBGNAME 0x08000000 // ms => CV: + // wat => xxxx: (T?xxxx-form) + // bc => old pascal format (capitalized) + // gc3 => unicode symbols or 'vendor-extension' + // qualifiers are present + +#define M_COMPILER 0x70000000 // Compiler mask (0-unknown) +#define MT_MSCOMP 0x10000000 // 1 - microsoft/symantec +#define MT_BORLAN 0x20000000 // 2 - borland +#define MT_WATCOM 0x30000000 // 3 - watcom +#define MT_OTHER 0x40000000 // 4 - digital mars D language (start: _D) + // - apple Swift language (start: [_]_T) +// !!! The following definitions must be last and in this order! +#define MT_GNU 0x50000000 // 5 - GNU - (over VA for autodetection) +#define MT_GCC3 0x60000000 // 6 - gcc-v3 + // In the short form this answer is possible + // for GNU/VA as well, but gcc3 can be + // explicitly requested only with it. + // Autodetection works but not very reliable. +#define MT_VISAGE 0x70000000 // 7 - Visual Age - never autodetected + // In the short form this answer means VA + // or GNU. In the automatic mode GNU will + // be used! +//--------------------------------------------------------------------------- +// Flags to inhibit different parts of the demangled name +#define MNG_PTRMSK 0x7 // Memory model mask +// DO NOT change order in this group (PtrType) +#define MNG_DEFNEAR 0x0 // inhibit near, display everything else +#define MNG_DEFNEARANY 0x1 // inhibit near/__ptr64, display everything else +#define MNG_DEFFAR 0x2 // inhibit far, display everything else +#define MNG_NOPTRTYP16 0x3 // inhibit everything (disables vc7-extensions) +#define MNG_DEFHUGE 0x4 // inhibit huge, display everything else +#define MNG_DEFPTR64 0x5 // inhibit __pt64, display everything else + // ATT: in 64bit must be + MNG_NOTYPE|MNG_NOCALLC +#define MNG_DEFNONE 0x6 // display everything +#define MNG_NOPTRTYP 0x7 // inhibit everything +// +#define MNG_NODEFINIT 0x00000008 // Inhibit everything except the main name + // This flag is not recommended + // for __fastcall/__stdcall GCC3 names + // because there is a high probablity of + // incorrect demangling. Use it only when + // you are sure that the input is a + // cygwin/mingw function name +// +#define MNG_NOUNDERSCORE 0x00000010 // Inhibit underscores in __ccall, __pascal... + +#define MNG_NOTYPE 0x00000020 // Inhibit callc&based +#define MNG_NORETTYPE 0x00000040 // Inhibit return type of functions +#define MNG_NOBASEDT 0x00000080 // Inhibit base types + // NOTE: also inhibits "__linkproc__" + // NOTE: -"- 'implicit self types' (Swift) +#define MNG_NOCALLC 0x00000100 // Inhibit __pascal/__ccall/etc + // NOTE: also inhibits "extern (cc)" (D) +#define MNG_NOPOSTFC 0x00000200 // Inhibit postfix const +#define MNG_NOSCTYP 0x00000400 // Inhibit public/private/protected + // NOTE: also inhibits in/out/lazy for args (D) + // NOTE: -"- dynamic/super/override/... (Swift) +#define MNG_NOTHROW 0x00000800 // Inhibit throw description + // NOTE: also inhibits all funcattr (D) +#define MNG_NOSTVIR 0x00001000 // Inhibit "static" & "virtual" + // NOTE: also inhibits (D) top-level procs (<=) +#define MNG_NOECSU 0x00002000 // Inhibit class/struct/union/enum[/D:typedef] +#define MNG_NOCSVOL 0x00004000 // Inhibit const/volatile/restrict + // NOTE: also inhibits __unaligned (vc) + // NOTE: also inhibits transaction_safe(gcc) + // NOTE: also inhibits shared/immutable (D) + // NOTE: also inhibits prefix/postfix/infix/inout (Swift) +#define MNG_NOCLOSUR 0x00008000 // Inhibit __closure for borland + // 'reabstract thunk' description (Swift) +#define MNG_NOUNALG 0x00010000 // Inhibit __unaligned (see NOCSVOL) + // NOTE: also inhibit transaction_safe (see NOCSVOL) +#define MNG_NOMANAGE 0x00020000 // Inhibit __pin/__box/__gc for ms(.net) + // NOTE: also inhibit archetype/witness (Swift) + // NOTE: also ingibit [abi:xxxx] (gcc3) +#define MNG_NOMODULE 0x00040000 // Inhibit module names (Swift) +// 0x00080000 +// +#define MNG_SHORT_S 0x00100000 // signed (int) is displayed as s(int) +#define MNG_SHORT_U 0x00200000 // unsigned (int) is displayed as u(int) +#define MNG_ZPT_SPACE 0x00400000 // Display space after comma in the arglist + // NOTE: also spaces in name:type pair (Swift) + // and around Swift return clause -> +#define MNG_DROP_IMP 0x00800000 // Inhibit __declspec(dllimport) +// +// 0x01000000 +#define MNG_IGN_ANYWAY 0x02000000 // Ingore '_nn' at the end of name +#define MNG_IGN_JMP 0x04000000 // Ingore 'j_' at the beginning of name +#define MNG_MOVE_JMP 0x08000000 // Move 'j_' prefix to the demangled name + // If both MNG_IGN_JMP and MNG_MOVE_JMP + // are set then move the prefix only if + // the name was not truncated +// +#define MNG_COMPILER_MSK 0x70000000 // Compiler mask (0-autodetect) + +#define MNG_SHORT_FORM (MNG_NOTYPE|MNG_NORETTYPE|MNG_NOPOSTFC|MNG_NOPTRTYP \ + | MNG_NOSCTYP|MNG_NOTHROW|MNG_NOSTVIR|MNG_NOECSU|MNG_NOCLOSUR \ + | MNG_SHORT_U|MNG_DROP_IMP|MNG_NOUNALG|MNG_NOMANAGE \ + | MNG_IGN_JMP|MNG_MOVE_JMP|MNG_IGN_ANYWAY) +#define MNG_LONG_FORM (MNG_ZPT_SPACE | MNG_IGN_JMP | MNG_IGN_ANYWAY | MNG_NOPTRTYP) + +// The description of the following symbol is in the notes +#define MNG_CALC_VALID (MNG_COMPILER_MSK|MNG_IGN_JMP|MNG_IGN_ANYWAY) + +//--------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +#ifndef H2ASH + +#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_DEMANGLE__) +typedef int32 ida_export demangler_t( + char *answer, + uint answer_length, + const char *str, + uint32 disable_mask); +idaman demangler_t demangle; +#endif + +// If answer_length == 0 then no demangling is performed neither. The function +// will check if demangling is possible and what compiler is used to mangle +// the name. If the name cannot be demangled then the function will return 0. +// NOTE: the answer MT_MSCOMP+1 means __msfastcall +// (or borland class name with "_4" suffix) and the demangling is possible +// either as MS (__fastcall) or as bc (__msfastcall) +// NOTE: the answer MT_GCC3+1 means POSSIBLE mingw/cygwin with +// __stdcall/__fastcall but it might also mean ms-stdcall. +// In essense it means that the demangler cannot determine the compiler +// precisely. +// It also means that the demangling is possible in the gcc3 mode +// ONLY when the compiler is explicitly set to gcc3 and MNG_NODEFINIT +// bit is not set. + +// If answer == NULL then the demangler will return check if the demangling +// is possible and only return the flags. +// In this case answer_length should be enough to hold the demangled name. + +// NOTE: If int32(answer_length) < 0 then the demangler will calcuate the +// the number of purged bytes for the given name. In this case +// disable_mask may contain only bits included in MNG_CALC_VALID, +// and -answer_length must be equal to the register size (e.g. +// sizeof(uint16/uint32/uint64)). The value of the register size +// is used to check the numeric value in the ms stdcall/fastcall +// encoding (it is used in the gcc mode too). +// if return value <= 0 - no purged bytes or valid information. +// If (value & 1) != 0 - ms stdcall (definite npurged is value-1. +// If (value & 1) == 0 - 'encoded' counter (not implemented yet). + +// If answer != NULL (and answer_length != 0) - perform demangling and fill out. +// NOTE: if int32(answer_length) < 0 then the buffer size will be -answer_length +// but 'answer' is interpreted not as a pointer to the output buffer but +// as a pointer to pointer to the output buffer (char**). +// In this case if the function succeeds,a pointer to the answer end +// will be returned in the pointer (like stpcpy). In this form 'answer' +// cannot be NULL and *(char**)answer cannot be NULL. +// answer_length must be greater than 9 for the 'truncated' answer. + +typedef int mangled_name_type_t; +const mangled_name_type_t MANGLED_CODE = 0; +const mangled_name_type_t MANGLED_DATA = 1; +const mangled_name_type_t MANGLED_UNKNOWN = 2; + +idaman mangled_name_type_t ida_export get_mangled_name_type(const char *name); + +#endif // H2ASH +#endif // _DEMANGLE_HPP diff --git a/idasdk76/include/dirtree.hpp b/idasdk76/include/dirtree.hpp new file mode 100644 index 0000000..d346dd1 --- /dev/null +++ b/idasdk76/include/dirtree.hpp @@ -0,0 +1,468 @@ +/* + + This class is used to organize a directory tree on top of any + collection that allows for accessing its elements by an id (inode). + No requirements are imposed on the inodes apart from the forbidden + value -1 (it is used ot denote a bad inode). + + The dirspec_t class is used to specialize the dirtree. + + It can be used to introduce a directory structure for: + - local types + - structs + - enums + - functions + - names + - etc + +*/ + +#ifndef DIRTREE_HPP +#define DIRTREE_HPP + +//------------------------------------------------------------------------ +typedef qvector<inode_t> inodevec_t; // sequence of inodes + +/// Directory indexes are simple numbers like 0,1,2,3... +/// They are independent of inode numbers. +/// The root directory always exists and has the index 0 (\ref direntry_t::ROOTIDX). +typedef uval_t diridx_t; +typedef qvector<diridx_t> dirvec_t; // sequence of directory indexes + +// Directory entry: either a file or directory +// We use PACKED to save memory, without it we would spend 64 bits instead of +// 8 bits to store a 1-bit value on ida64. +#pragma pack(push, 1) +struct PACKED direntry_t +{ + uval_t idx; // diridx_t or inode_t + bool isdir; + + static const uval_t BADIDX = uval_t(-1); + static const uval_t ROOTIDX = 0; + + direntry_t(uval_t i=BADIDX, bool d=false) : idx(i), isdir(d) {} + bool valid() const { return idx != BADIDX; } + + bool operator==(const direntry_t &r) const + { + return idx == r.idx && isdir == r.isdir; + } + bool operator!=(const direntry_t &r) const + { + return !(*this == r); + } + bool operator<(const direntry_t &r) const + { + if ( !isdir && r.isdir ) + return true; + if ( isdir && !r.isdir ) + return false; + return idx < r.idx; + } +}; +#pragma pack(pop) +DECLARE_TYPE_AS_MOVABLE(direntry_t); +typedef qvector<direntry_t> direntry_vec_t; + +//------------------------------------------------------------------------ +/// Directory tree specialization. This is an abstract base class that +/// represents 'file items' of our directory structure. +struct dirspec_t +{ + uint32 flags; + enum + { + DSF_INODE_EA = 0x01, // inode is EA, will be handled during segment moving + DSF_PRIVRANGE = 0x02, // inode is tid_t, structure or enum id, will be handled during segment moving + }; + // netnode name to load/save directory tree + // if not specified the loading/storing operations are not supported + qstring nodename; + + dirspec_t(const char *nm=nullptr, uint32 f=0) : flags(f), nodename(nm) {} + + virtual ~dirspec_t() {} + + // get the entry name. for example, the structure name + // out may be nullptr; in this case get_name can be used to validate an inode. + // return false if the entry does not exist. + virtual bool get_name(qstring *out, inode_t inode) = 0; + // get the entry inode. for example, the structure id + virtual inode_t get_inode(diridx_t diridx, const char *name) = 0; + // print additional attributes of the entry. for example, is union? is mapped? + virtual qstring get_attrs(inode_t inode) const = 0; + // rename the entry + virtual bool rename_inode(inode_t inode, const char *newname) = 0; + // event: unlinked an inode + virtual void unlink_inode(inode_t) {} +}; + +//------------------------------------------------------------------------ +/// Position in the directory tree +struct dirtree_cursor_t +{ + diridx_t parent; + size_t rank; // item rank: index into parent.subdirs or parent.inodes + // if the index value is greated than parent.subdirs.size() + // then it points to parent.inodes (after -= parent.subdirs.size()) + dirtree_cursor_t(diridx_t _parent=direntry_t::BADIDX, size_t _rank=size_t(-1)) + : parent(_parent), rank(_rank) {} + bool valid() const { return parent != direntry_t::BADIDX || rank == 0; } + bool is_root_cursor() const { return parent == direntry_t::BADIDX && rank == 0; } + void set_root_cursor(void) { parent = direntry_t::BADIDX; rank = 0; } + + static dirtree_cursor_t root_cursor() + { + dirtree_cursor_t c; + c.set_root_cursor(); + return c; + } + + DECLARE_COMPARISONS(dirtree_cursor_t) + { + if ( parent < r.parent ) return -1; + if ( parent > r.parent ) return 1; + if ( rank < r.rank ) return -1; + if ( rank > r.rank ) return 1; + return 0; + } +}; +DECLARE_TYPE_AS_MOVABLE(dirtree_cursor_t); +typedef qvector<dirtree_cursor_t> dirtree_cursor_vec_t; + +//------------------------------------------------------------------------- +struct dirtree_selection_t : public dirtree_cursor_vec_t {}; + +//------------------------------------------------------------------------ +/// Helper class to iterate over files +struct dirtree_iterator_t +{ + qstring pattern; + dirtree_cursor_t cursor; +}; + +//------------------------------------------------------------------------ +// Directory tree: error codes +enum dterr_t +{ + DTE_OK, // ok + DTE_ALREADY_EXISTS, // item already exists + DTE_NOT_FOUND, // item not found + DTE_NOT_DIRECTORY, // item is not a directory + DTE_NOT_EMPTY, // directory is not empty + DTE_BAD_PATH, // invalid path + DTE_CANT_RENAME, // failed to rename an item + DTE_OWN_CHILD, // moving inside subdirectory of itself + DTE_MAX_DIR, // maximum directory count achieved + DTE_LAST, +}; + +class dirtree_t; +class dirtree_impl_t; +struct segm_move_infos_t; + +//------------------------------------------------------------------------ +// internal functions; use dirtree_t members instead +#ifndef SWIG +idaman dirtree_impl_t *ida_export create_dirtree(dirtree_t *dt, dirspec_t *ds); +idaman void ida_export delete_dirtree(dirtree_impl_t *d); +idaman bool ida_export load_dirtree(dirtree_impl_t *d); +idaman bool ida_export save_dirtree(dirtree_impl_t *d); +void reset_dirtree(dirtree_impl_t *d); +idaman const char *ida_export dirtree_errstr(dterr_t err); +idaman dterr_t ida_export dirtree_chdir(dirtree_impl_t *d, const char *path); +idaman void ida_export dirtree_getcwd(qstring *out, const dirtree_impl_t *d); +idaman void ida_export dirtree_resolve_path(direntry_t *de, const dirtree_impl_t *d, const char *path); +idaman void ida_export dirtree_resolve_cursor(direntry_t *de, const dirtree_impl_t *d, const dirtree_cursor_t &cursor); +idaman bool ida_export dirtree_get_entry_name(qstring *out, const dirtree_impl_t *d, const direntry_t &de); +idaman void ida_export dirtree_get_entry_attrs(qstring *out, const dirtree_impl_t *d, const direntry_t &de); +idaman ssize_t ida_export dirtree_get_dir_size(dirtree_impl_t *d, diridx_t diridx); +idaman bool ida_export dirtree_findfirst(dirtree_impl_t *d, dirtree_iterator_t *ff, const char *pattern); +idaman bool ida_export dirtree_findnext(dirtree_impl_t *d, dirtree_iterator_t *ff); +idaman bool ida_export dirtree_get_abspath_by_cursor(qstring *out, const dirtree_impl_t *d, const dirtree_cursor_t &cursor); +idaman bool ida_export dirtree_get_abspath_by_relpath(qstring *out, const dirtree_impl_t *d, const char *relpath); +idaman dterr_t ida_export dirtree_mkdir(dirtree_impl_t *d, const char *path); +idaman dterr_t ida_export dirtree_rmdir(dirtree_impl_t *d, const char *path); +idaman dterr_t ida_export dirtree_link(dirtree_impl_t *d, const char *path, bool do_link); +idaman dterr_t ida_export dirtree_link_inode(dirtree_impl_t *d, inode_t inode, bool do_link); +idaman dterr_t ida_export dirtree_rename(dirtree_impl_t *d, const char *from, const char *to); +idaman ssize_t ida_export dirtree_get_rank(const dirtree_impl_t *d, diridx_t diridx, const direntry_t &de); +idaman dterr_t ida_export dirtree_change_rank(dirtree_impl_t *d, const char *path, ssize_t rank_delta); +idaman void ida_export dirtree_get_parent_cursor(dirtree_cursor_t *out, const dirtree_impl_t *d, const dirtree_cursor_t &cursor); +idaman void ida_export notify_dirtree(dirtree_impl_t *d, bool added, inode_t inode); +idaman const char *ida_export dirtree_get_nodename(const dirtree_impl_t *d); +idaman void ida_export dirtree_set_nodename(dirtree_impl_t *d, const char *nm); +#endif // SWIG + + + +//------------------------------------------------------------------------ +/// Directory tree. +/// This class organizes a virtual directory tree over items that +/// are represented by dirspec_t. +class dirtree_t +{ + dirtree_impl_t *d; + + +public: + //lint -sem(dirtree_t::dirtree_t, custodial(1)) + dirtree_t(dirspec_t *ds) { d = create_dirtree(this, ds); } + ~dirtree_t() { delete_dirtree(d); } + + /// Get textual representation of the error code + static const char *errstr(dterr_t err) { return dirtree_errstr(err); } + + /// Change current directory + /// \param path new current directory + /// \return \ref dterr_t error code + dterr_t chdir(const char *path) { return dirtree_chdir(d, path); } + + /// Get current directory + /// \return the current working directory + qstring getcwd() const + { + qstring out; + dirtree_getcwd(&out, d); + return out; + } + + /// Get absolute path pointed by the cursor + /// \param cursor + /// \return path; empty string if error + /// \note see also resolve_cursor() + qstring get_abspath(const dirtree_cursor_t &cursor) const + { + qstring out; + dirtree_get_abspath_by_cursor(&out, d, cursor); + return out; + } + + /// Construct an absolute path from the specified relative path. + /// This function verifies the directory part of the specified path. + /// The last component of the specified path is not verified. + /// \param relpath relative path + /// \return path. empty path means wrong directory part of RELPATH + qstring get_abspath(const char *relpath) const + { + qstring out; + dirtree_get_abspath_by_relpath(&out, d, relpath); + return out; + } + + /// Resolve cursor + /// \param cursor to analyze + /// \return directory entry; + /// if the cursor is bad, the resolved entry will be invalid. + /// \note see also get_abspath() + direntry_t resolve_cursor(const dirtree_cursor_t &cursor) const + { + direntry_t de; + dirtree_resolve_cursor(&de, d, cursor); + return de; + } + + /// Resolve path + /// \param path to analyze + /// \return directory entry + direntry_t resolve_path(const char *path) const + { + direntry_t de; + dirtree_resolve_path(&de, d, path); + return de; + } + + static bool isdir(const direntry_t &de) { return de.valid() && de.isdir; } + static bool isfile(const direntry_t &de) { return de.valid() && !de.isdir; } + + /// Is a directory? + /// \param path to analyze + /// \return true if the specified path is a directory + bool isdir(const char *path) const + { + direntry_t de = resolve_path(path); + return isdir(de); + } + + /// Is a file? + /// \param path to analyze + /// \return true if the specified path is a file + bool isfile(const char *path) const + { + direntry_t de = resolve_path(path); + return isfile(de); + } + + /// Get entry name + /// \param de directory entry + /// \return name + qstring get_entry_name(const direntry_t &de) const + { + qstring out; + dirtree_get_entry_name(&out, d, de); + return out; + } + + /// Get dir size + /// \param diridx directory index + /// \return number of entries under this directory; + /// if error, return -1 + ssize_t get_dir_size(diridx_t diridx) const { return dirtree_get_dir_size(d, diridx); } + + /// Get entry attributes + /// \param de directory entry + /// \return name + qstring get_entry_attrs(const direntry_t &de) const + { + qstring out; + dirtree_get_entry_attrs(&out, d, de); + return out; + } + + /// Start iterating over files in a directory + /// \param ff directory iterator. it will be initialized by the function + /// \param pattern pattern to search for + /// \return success + bool findfirst(dirtree_iterator_t *ff, const char *pattern) const + { + return dirtree_findfirst(d, ff, pattern); + } + + /// Continue iterating over files in a directory + /// \param ff directory iterator + /// \return success + bool findnext(dirtree_iterator_t *ff) const + { + return dirtree_findnext(d, ff); + } + + /// Create a directory. + /// \param path directory to create + /// \return \ref dterr_t error code + dterr_t mkdir(const char *path) { return dirtree_mkdir(d, path); } + + /// Remove a directory. + /// \param path directory to delete + /// \return \ref dterr_t error code + dterr_t rmdir(const char *path) { return dirtree_rmdir(d, path); } + + /// Add a file item into a directory. + /// \param path path to item to add to a directory + /// \return \ref dterr_t error code + dterr_t link(const char *path) { return dirtree_link(d, path, true); } + + /// Remove a file item from a directory. + /// \param path path to item remove from a directory + /// \return \ref dterr_t error code + dterr_t unlink(const char *path) { return dirtree_link(d, path, false); } + + /// Add an inode into the current directory + /// \param inode + /// \return \ref dterr_t error code + dterr_t link(inode_t inode) { return dirtree_link_inode(d, inode, true); } + + /// Remove an inode from the current directory + /// \param inode + /// \return \ref dterr_t error code + dterr_t unlink(inode_t inode) { return dirtree_link_inode(d, inode, false); } + + /// Rename a directory entry. + /// \param from source path + /// \param to destination path + /// \return \ref dterr_t error code + /// \note This function can also rename the item + dterr_t rename(const char *from, const char *to) + { + return dirtree_rename(d, from, to); + } + + /// Get ordering rank of an item. + /// \param diridx index of the parent directory + /// \param de directory entry + /// \return number in a range of [0..n) where n is the number of entries in + /// the parent directory. -1 if error + ssize_t get_rank(diridx_t diridx, const direntry_t &de) const + { + return dirtree_get_rank(d, diridx, de); + } + + /// Change ordering rank of an item. + /// \param path path to the item + /// \param delta the amount of the change. positive numbers mean to move down + /// in the list; negative numbers mean to move up. + /// \return \ref dterr_t error code + /// \note All subdirectories go before all file entries. + dterr_t change_rank(const char *path, ssize_t rank_delta) + { + return dirtree_change_rank(d, path, rank_delta); + } + + /// Get parent cursor. + /// \param cursor a valid ditree cursor + /// \return cursor's parent + dirtree_cursor_t get_parent_cursor(const dirtree_cursor_t &cursor) const + { + dirtree_cursor_t parent; + dirtree_get_parent_cursor(&parent, d, cursor); + return parent; + } + + /// Load the tree structure from the netnode. + /// If dirspec_t::nodename is empty, the operation will be considered a success. + /// In addition, calling load() more than once will not do anything, + /// and will be considered a success. + /// \return success + /// \see dirspec_t::nodename. + bool load() + { + return load_dirtree(d); + } + + /// Save the tree structure to the netnode. + /// \return success + /// \see dirspec_t::nodename. + bool save() const + { + return save_dirtree(d); + } + + /// netnode name + const char *get_nodename() const + { + return dirtree_get_nodename(d); + } + + void set_nodename(const char *nm) + { + return dirtree_set_nodename(d, nm); + } + + /// Notify dirtree about a change of an inode. + /// \param add are we adding or deleting an inode? + /// \param inode inode in question + void notify_dirtree(bool added, inode_t inode) + { + ::notify_dirtree(d, added, inode); + } + +}; + +/// Built-in dirtree specializations: +enum dirtree_id_t +{ + DIRTREE_LOCAL_TYPES, + DIRTREE_STRUCTS, + DIRTREE_ENUMS, + DIRTREE_FUNCS, + DIRTREE_NAMES, + DIRTREE_IMPORTS, + DIRTREE_IDAPLACE_BOOKMARKS, + DIRTREE_STRUCTS_BOOKMARKS, + DIRTREE_ENUMS_BOOKMARKS, + DIRTREE_END, +}; +idaman dirtree_t *ida_export get_std_dirtree(dirtree_id_t id); + + +#endif // define DIRTREE_HPP diff --git a/idasdk76/include/diskio.hpp b/idasdk76/include/diskio.hpp new file mode 100644 index 0000000..24dc8bb --- /dev/null +++ b/idasdk76/include/diskio.hpp @@ -0,0 +1,621 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _DISKIO_HPP +#define _DISKIO_HPP + +#include <stdio.h> + +/*! \file diskio.hpp + + \brief File I/O functions for IDA + + You should not use standard C file I/O functions in modules. + Use functions from this header, pro.h and fpro.h instead. + + This file also declares a call_system() function. +*/ + +//------------------------------------------------------------------------- +// S E A R C H F O R F I L E S +//------------------------------------------------------------------------- + + +/// Get IDA directory (if subdir==NULL) +/// or the specified subdirectory (see \ref SUBDIR) + +idaman THREAD_SAFE const char *ida_export idadir(const char *subdir); + + +/// Search for IDA system file. +/// This function searches for a file in: +/// -# each directory specified by %IDAUSR% +/// -# ida directory [+ subdir] +/// and returns the first match. +/// \param[out] buf buffer for file name +/// \param bufsize size of output buffer +/// \param filename name of file to search +/// \param subdir if specified, the file is looked for in the specified subdirectory +/// of the ida directory first (see \ref SUBDIR) +/// \return NULL if not found, otherwise a pointer to full file name. + +idaman THREAD_SAFE char *ida_export getsysfile( + char *buf, + size_t bufsize, + const char *filename, + const char *subdir); + +/// \defgroup SUBDIR IDA subdirectories +/// Passed as 'subdir' parameter to idadir(), getsysfile(), and others. +//@{ +#define CFG_SUBDIR "cfg" +#define IDC_SUBDIR "idc" +#define IDS_SUBDIR "ids" +#define IDP_SUBDIR "procs" +#define LDR_SUBDIR "loaders" +#define SIG_SUBDIR "sig" +#define TIL_SUBDIR "til" +#define PLG_SUBDIR "plugins" +#define THM_SUBDIR "themes" +//@} + +/// Get user ida related directory. +/// \code +/// - if $IDAUSR is defined: +/// - the first element in $IDAUSR +/// - else +/// - default user directory ($HOME/.idapro or %APPDATA%Hex-Rays/IDA Pro) +/// \endcode + +idaman THREAD_SAFE const char *ida_export get_user_idadir(void); + + +/// Get list of directories in which to find a specific IDA resource +/// (see \ref SUBDIR). The order of the resulting list is as follows: +/// \code +/// - [$IDAUSR/subdir (0..N entries)] +/// - $IDADIR/subdir +/// \endcode +/// \param[out] dirs output vector for directory names +/// \param subdir name of the resource to list +/// \param flags \ref IDA_SUBDIR_ bits +/// \return number of directories appended to 'dirs' + +idaman THREAD_SAFE int ida_export get_ida_subdirs(qstrvec_t *dirs, const char *subdir, int flags=0); + +/// \defgroup IDA_SUBDIR_ Subdirectory modification flags +/// Passed as 'flags' parameter to get_ida_subdirs() +//@{ +#define IDA_SUBDIR_IDP 0x0001 ///< append the processor name as a subdirectory +#define IDA_SUBDIR_IDADIR_FIRST 0x0002 ///< $IDADIR/subdir will be first, not last +#define IDA_SUBDIR_ONLY_EXISTING 0x0004 ///< only existing directories will be present +//@} + + +/// Get a folder location by CSIDL (see \ref CSIDL). +/// Path should be of at least MAX_PATH size + +idaman THREAD_SAFE bool ida_export get_special_folder(char *buf, size_t bufsize, int csidl); + +/// \defgroup CSIDL Common CSIDLs +/// Passed as 'csidl' parameter to get_special_folder() +//@{ +#ifndef CSIDL_APPDATA +#define CSIDL_APPDATA 0x001a +#endif +#ifndef CSIDL_LOCAL_APPDATA +#define CSIDL_LOCAL_APPDATA 0x001c +#endif +#ifndef CSIDL_PROGRAM_FILES +#define CSIDL_PROGRAM_FILES 0x0026 +#endif +#ifndef CSIDL_PROGRAM_FILES_COMMON +#define CSIDL_PROGRAM_FILES_COMMON 0x002b +#endif +#ifndef CSIDL_PROGRAM_FILESX86 +#define CSIDL_PROGRAM_FILESX86 0x002a +#endif +//@} + +/// Enumerate files in the specified directory. +/// \param[out] answer buffer to contain the file name for which +/// file_enumerator_t::visit_file returns non-zero value +/// (may be NULL) +/// \param answer_size size of 'answer' +/// \param path directory to enumerate files in +/// \param fname mask of file names to enumerate +/// \param fv file_enumerator_t::visit_file function called for each file +/// - file: full file name (with path) +/// - if returns non-zero value, the enumeration +/// is stopped and the return code is +/// is returned to the caller. +/// the callback function +/// \return zero or the code returned by 'func' + +struct file_enumerator_t +{ + virtual int visit_file(const char *file) = 0; + virtual ~file_enumerator_t() {} +}; + +idaman THREAD_SAFE int ida_export enumerate_files2( + char *answer, + size_t answer_size, + const char *path, + const char *fname, + file_enumerator_t &fv); + + + +//------------------------------------------------------------------------- +// O P E N / R E A D / W R I T E / C L O S E F I L E S +//------------------------------------------------------------------------- + +/// \name Open/Read/Write/Close Files +/// There are two sets of "open file" functions. +/// The first set tries to open a file and returns success or failure. +/// The second set is "open or die": if the file cannot be opened +/// then the function will display an error message and exit. +//@{ + +/// Open a new file for write in text mode, deny write. +/// If a file exists, it will be removed. +/// \return NULL if failure + +idaman THREAD_SAFE FILE *ida_export fopenWT(const char *file); + + +/// Open a new file for write in binary mode, deny read/write. +/// If a file exists, it will be removed. +/// \return NULL if failure + +idaman THREAD_SAFE FILE *ida_export fopenWB(const char *file); + + +/// Open a file for read in text mode, deny none. +/// \return NULL if failure + +idaman THREAD_SAFE FILE *ida_export fopenRT(const char *file); + + +/// Open a file for read in binary mode, deny none. +/// \return NULL if failure + +idaman THREAD_SAFE FILE *ida_export fopenRB(const char *file); + + +/// Open a file for read/write in binary mode, deny write. +/// \return NULL if failure + +idaman THREAD_SAFE FILE *ida_export fopenM(const char *file); + + +/// Open a file for append in text mode, deny none. +/// \return NULL if failure + +idaman THREAD_SAFE FILE *ida_export fopenA(const char *file); + + +/// Open a file for read in binary mode or die, deny none. +/// If a file cannot be opened, this function displays a message and exits. + +idaman THREAD_SAFE FILE *ida_export openR(const char *file); + + +/// Open a file for read in text mode or die, deny none. +/// If a file cannot be opened, this function displays a message and exits. + +idaman THREAD_SAFE FILE *ida_export openRT(const char *file); + + +/// Open a file for read/write in binary mode or die, deny write. +/// If a file cannot be opened, this function displays a message and exits. + +idaman THREAD_SAFE FILE *ida_export openM(const char *file); + + +//@} + +//------------------------------------------------------------------------- +// F I L E S I Z E / D I S K S P A C E +//------------------------------------------------------------------------- + +/// Get length of file in bytes. +/// \param fp pointer to file + +idaman THREAD_SAFE uint64 ida_export qfsize(FILE *fp); + + +/// Change size of file or die. +/// If an error occurs, this function displays a message and exits. +/// \param fp pointer to file +/// \param size new size of file + +idaman THREAD_SAFE void ida_export echsize(FILE *fp, uint64 size); + + +/// Get free disk space in bytes. +/// \param path name of any directory on the disk to get information about + +idaman THREAD_SAFE uint64 ida_export get_free_disk_space(const char *path); + + +//------------------------------------------------------------------------- +// I / O P O R T D E F I N I T I O N S F I L E +//------------------------------------------------------------------------- +/// Describes an I/O port bit +struct ioport_bit_t +{ + qstring name; ///< name of the bit + qstring cmt; ///< comment +}; +DECLARE_TYPE_AS_MOVABLE(ioport_bit_t); +typedef qvector<ioport_bit_t> ioport_bits_t; + +/// Describes an I/O port +struct ioport_t +{ + ea_t address; ///< address of the port + qstring name; ///< name of the port + qstring cmt; ///< comment + ioport_bits_t bits; ///< bit names + void *userdata; ///< arbitrary data. initialized to NULL. + + ioport_t() + : address(0), userdata(NULL) + { + } +}; +DECLARE_TYPE_AS_MOVABLE(ioport_t); +typedef qvector<ioport_t> ioports_t; + +/// Read i/o port definitions from a config file. +/// +/// Each device definition in the input file begins with a line like this: +/// +/// \v{.devicename} +/// +/// After it go the port definitions in this format: +/// +/// \v{portname address} +/// +/// The bit definitions (optional) are represented like this: +/// +/// \v{portname.bitname bitnumber} +/// +/// Lines beginning with a space are ignored. +/// comment lines should be started with ';' character. +/// +/// The default device is specified at the start of the file: +/// +/// \v{.default device_name} +/// +/// \note It is permissible to have a symbol mapped to several addresses +/// but all addresses must be unique. +/// \param[out] ports output vector +/// \param device contains device name to load. If default_device[0] == 0 +/// then the default device is determined by .default directive +/// in the config file. +/// \param file config file name +/// \param callback callback to call when the input line can't be parsed normally. +/// - line: input line to parse +/// - returns error message. if NULL, then the line is parsed ok. +/// \return -1 on error or size of vector + +idaman THREAD_SAFE ssize_t ida_export read_ioports( + ioports_t *ports, + qstring *device, + const char *file, + const char *(idaapi *callback)( + const ioports_t &ports, + const char *line)=NULL); + + +struct ioports_fallback_t +{ + // returns success or fills ERRBUF with an error message + virtual bool handle(qstring *errbuf, const ioports_t &ports, const char *line) = 0; +}; + +idaman THREAD_SAFE ssize_t ida_export read_ioports2( + ioports_t *ports, + qstring *device, + const char *file, + ioports_fallback_t *callback=nullptr); + + +/// Allow the user to choose the ioport device. +/// \param[in,out] device in: contains default device name. If default_device[0] == 0 +/// then the default device is determined by .default directive +/// in the config file. +/// out: the selected device name +/// \param file config file name +/// \param parse_params if present (non NULL), then defines a callback which +/// will be called for all lines not starting with a dot (.) +/// This callback may parse these lines are prepare a simple +/// processor parameter string. This string will be displayed +/// along with the device name. +/// If it returns #IOPORT_SKIP_DEVICE, then the current +/// device will not be included in the list. +/// \retval true the user selected a device, its name is in 'device' +/// \retval false the selection was cancelled. if device=="NONE" upon return, +/// then no devices were found in the configuration file + +idaman THREAD_SAFE bool ida_export choose_ioport_device( + qstring *_device, + const char *file, + const char *(idaapi *parse_params)( + qstring *buf, + const char *line)=NULL); + +struct choose_ioport_parser_t +{ + /// \retval true and fill PARAM with a displayed string + /// \retval false and empty PARAM to skip the current device + /// \retval false and fill PARAM with an error message + virtual bool parse(qstring *param, const char *line) = 0; +}; + +idaman THREAD_SAFE bool ida_export choose_ioport_device2( + qstring *_device, + const char *file, + choose_ioport_parser_t *parse_params); + +/// See 'parse_params' parameter to choose_ioport_device() +#define IOPORT_SKIP_DEVICE ((const char *)(-1)) + + +/// Find ioport in the array of ioports + +idaman THREAD_SAFE const ioport_t *ida_export find_ioport(const ioports_t &ports, ea_t address); + + +/// Find ioport bit in the array of ioports + +idaman THREAD_SAFE const ioport_bit_t *ida_export find_ioport_bit(const ioports_t &ports, ea_t address, size_t bit); + + +//------------------------------------------------------------------------- +// S Y S T E M S P E C I F I C C A L L S +//------------------------------------------------------------------------- + +/// Execute a operating system command. +/// This function suspends the interface (Tvision), runs the command +/// and redraws the screen. +/// \param command command to execute. If NULL, an interactive shell is activated +/// \return the error code returned by system() call + +idaman THREAD_SAFE int ida_export call_system(const char *command); + + +//------------------------------------------------------------------------- +// L O A D E R I N P U T S O U R C E F U N C T I O N S +//------------------------------------------------------------------------- + +/// \name Loader Input Source +/// Starting with v4.8 IDA can load and run remote files. +/// In order to do that, we replace the FILE* in the loader modules +/// with an abstract input source (linput_t). The source might be linked to +/// a local or remote file. +//@{ + +class linput_t; ///< loader input source + + +/// linput types +enum linput_type_t +{ + LINPUT_NONE, ///< invalid linput + LINPUT_LOCAL, ///< local file + LINPUT_RFILE, ///< remote file (\dbg{open_file}, \dbg{read_file}) + LINPUT_PROCMEM, ///< debugged process memory (read_dbg_memory()) + LINPUT_GENERIC ///< generic linput +}; + + +/// Read the input source. +/// If failed, inform the user and ask him if he wants to continue. +/// If he does not, this function will not return (loader_failure() will be called). +/// This function may be called only from loaders! + +idaman void ida_export lread(linput_t *li, void *buf, size_t size); + + +/// Read the input source. +/// \return number of read bytes or -1 + +idaman ssize_t ida_export qlread(linput_t *li, void *buf, size_t size); + + +/// Read one line from the input source. +/// \return NULL if failure, otherwise 's' + +idaman char *ida_export qlgets(char *s, size_t len, linput_t *li); + + +/// Read one character from the input source. +/// \return EOF if failure, otherwise the read character + +idaman int ida_export qlgetc(linput_t *li); + + +/// Read multiple bytes and swap if necessary. +/// \param li input file +/// \param buf pointer to output buffer +/// \param size number of bytes to read +/// \param mf big endian? +/// \retval 0 ok +/// \retval -1 failure + +idaman int ida_export lreadbytes(linput_t *li, void *buf, size_t size, bool mf); + +/// Helper to define lread2bytes(), lread4bytes(), etc +#define DEF_LREADBYTES(read, type, size) \ +/*! \brief Read a value from linput - also see lreadbytes() */ \ +inline int idaapi read(linput_t *li, type *res, bool mf) \ + { return lreadbytes(li, res, size, mf); } +DEF_LREADBYTES(lread2bytes, int16, 2) +DEF_LREADBYTES(lread2bytes, uint16, 2) +DEF_LREADBYTES(lread4bytes, int32, 4) +DEF_LREADBYTES(lread4bytes, uint32, 4) +DEF_LREADBYTES(lread8bytes, int64, 8) +DEF_LREADBYTES(lread8bytes, uint64, 8) +#undef DEF_LREADBYTES + + +/// Read a zero-terminated string from the input. +/// If fpos == -1 then no seek will be performed. + +idaman char *ida_export qlgetz( + linput_t *li, + int64 fpos, + char *buf, + size_t bufsize); + + +/// Get the input source size + +idaman int64 ida_export qlsize(linput_t *li); + + +/// Set input source position. +/// \return the new position (not 0 as fseek!) + +idaman qoff64_t ida_export qlseek(linput_t *li, qoff64_t pos, int whence=SEEK_SET); + + +/// Get input source position + +inline qoff64_t idaapi qltell(linput_t *li) { return qlseek(li, 0, SEEK_CUR); } + + +/// Open loader input + +idaman linput_t *ida_export open_linput(const char *file, bool remote); + + +/// Close loader input + +idaman THREAD_SAFE void ida_export close_linput(linput_t *li); + + +/// Get FILE* from the input source. +/// If the input source is linked to a remote file, then return NULL. +/// Otherwise return the underlying FILE* +/// Please do not use this function if possible. + +idaman THREAD_SAFE FILE *ida_export qlfile(linput_t *li); + + +/// Convert FILE * to input source. +/// Used for temporary linput_t objects - call unmake_linput() to free +/// the slot after the use. + +idaman THREAD_SAFE linput_t *ida_export make_linput(FILE *fp); + +/// Free an linput_t object (also see make_linput()) + +idaman THREAD_SAFE void ida_export unmake_linput(linput_t *li); + + +/// Generic linput class - may be used to create a linput_t instance for +/// any data source +struct generic_linput_t +{ + /// \name Warning + /// The following two fields must be filled before calling create_generic_linput() + //@{ + uint64 filesize; ///< input file size + uint32 blocksize; ///< preferred block size to work with + ///< read/write sizes will be in multiples of this number. + ///< for example, 4096 is a nice value + ///< blocksize 0 means that the filesize is unknown. + ///< the internal cache will be disabled in this case. + ///< also, seeks from the file end will fail. + ///< blocksize=-1 means error. + //@} + virtual ssize_t idaapi read(qoff64_t off, void *buffer, size_t nbytes) = 0; + virtual ~generic_linput_t() {} +}; + +/// Create a generic linput +/// \param gl linput description. +/// this object will be destroyed by close_linput() +/// using "delete gl;" + +idaman THREAD_SAFE linput_t *ida_export create_generic_linput(generic_linput_t *gl); + +/// Trivial memory linput + +idaman THREAD_SAFE linput_t *ida_export create_bytearray_linput(const uchar *start, size_t size); + + +/// Create a linput for process memory. +/// This linput will use read_dbg_memory() to read data. +/// \param start starting address of the input +/// \param size size of the memory area to represent as linput +/// if unknown, may be passed as 0 + +idaman linput_t *ida_export create_memory_linput(ea_t start, asize_t size); + +/// Get linput type + +inline THREAD_SAFE linput_type_t idaapi get_linput_type(linput_t *li) +{ + return *(linput_type_t *)li; +} + +/// Object that will free an linput_t at destruction-time +typedef janitor_t<linput_t*> linput_janitor_t; +/// Free the linput_t +template <> inline linput_janitor_t::~janitor_t() +{ + close_linput(resource); +} + +//--------------------------------------------------------------------------- +/// Helper class - adapts linput to be used in extract_... functions +/// as a data supplier (see kernwin.hpp) +class linput_buffer_t +{ +public: + linput_buffer_t(linput_t *linput, int64 size=0): li(linput), lsize(size) {} + ssize_t read(void *buf, size_t n) + { + return qlread(li, buf, n); + } + bool eof() + { + if ( lsize == 0 ) + lsize = qlsize(li); + return qltell(li) >= lsize; + } +protected: + linput_t *li; +private: + int64 lsize; +}; + +//@} + +// ------------------------------------------------------------------------- + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED THREAD_SAFE FILE *ida_export ecreate(const char *file); +idaman DEPRECATED THREAD_SAFE void ida_export eclose(FILE *fp); +idaman DEPRECATED THREAD_SAFE void ida_export eread(FILE *fp, void *buf, size_t size); +idaman DEPRECATED THREAD_SAFE void ida_export ewrite(FILE *fp, const void *buf, size_t size); +idaman DEPRECATED THREAD_SAFE void ida_export eseek(FILE *fp, qoff64_t pos); +idaman DEPRECATED THREAD_SAFE int ida_export enumerate_files( + char *answer, + size_t answer_size, + const char *path, + const char *fname, + int (idaapi*func)(const char *file,void *ud), + void *ud=NULL); +#endif +#endif // _DISKIO_HPP diff --git a/idasdk76/include/entry.hpp b/idasdk76/include/entry.hpp new file mode 100644 index 0000000..eb68680 --- /dev/null +++ b/idasdk76/include/entry.hpp @@ -0,0 +1,106 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _ENTRY_HPP +#define _ENTRY_HPP + +/*! \file entry.hpp + + \brief Functions that deal with entry points + + Exported functions are considered as entry points as well. + + IDA maintains list of entry points to the program. + Each entry point: + - has an address + - has a name + - may have an ordinal number +*/ + +/// Get number of entry points + +idaman size_t ida_export get_entry_qty(void); + +/// \defgroup AEF_ entry flags +/// Passed as 'flags' parameter to add_entry(ea_t, const char *, int) +//@{ +#define AEF_UTF8 0x0 ///< the name is given in UTF-8 (default) +#define AEF_IDBENC 0x1 ///< the name is given in the IDB encoding; + ///< non-ASCII bytes will be decoded accordingly + ///< Specifying AEF_IDBENC also implies AEF_NODUMMY +#define AEF_NODUMMY 0x2 ///< automatically prepend the name with '_' if + ///< it begins with a dummy suffix. See also AEF_IDBENC +//@} + + +/// Add an entry point to the list of entry points. +/// \param ord ordinal number +/// if ordinal number is equal to 'ea' then ordinal is not used +/// \param ea linear address +/// \param name name of entry point. If the specified location already +/// has a name, the old name will be appended to the regular +/// comment. If name == NULL, then the old name will be retained. +/// \param makecode should the kernel convert bytes at the entry point +/// to instruction(s) +/// \param flags See AEF_* +/// \return success (currently always true) + +idaman bool ida_export add_entry(uval_t ord, ea_t ea, const char *name, bool makecode, int flags=AEF_UTF8); + + +/// Get ordinal number of an entry point. +/// \param idx internal number of entry point. Should be +/// in the range 0..get_entry_qty()-1 +/// \return ordinal number or 0. + +idaman uval_t ida_export get_entry_ordinal(size_t idx); + + +/// Get entry point address by its ordinal +/// \param ord ordinal number of entry point +/// \return address or #BADADDR + +idaman ea_t ida_export get_entry(uval_t ord); + + +/// Get name of the entry point by its ordinal. +/// \param buf output buffer, may be NULL +/// \param ord ordinal number of entry point +/// \return size of entry name or -1 + +idaman ssize_t ida_export get_entry_name(qstring *buf, uval_t ord); + + +/// Rename entry point. +/// \param ord ordinal number of the entry point +/// \param name name of entry point. If the specified location already +/// has a name, the old name will be appended to a repeatable +/// comment. +/// \param flags See AEF_* +/// \return success + +idaman bool ida_export rename_entry(uval_t ord, const char *name, int flags=AEF_UTF8); + + +/// Set forwarder name for ordinal. +/// \param ord ordinal number of the entry point +/// \param name forwarder name for entry point. +/// \param flags See AEF_* +/// \return success + +idaman bool ida_export set_entry_forwarder(uval_t ord, const char *name, int flags=AEF_UTF8); + + +/// Get forwarder name for the entry point by its ordinal. +/// \param buf output buffer, may be NULL +/// \param ord ordinal number of entry point +/// \return size of entry forwarder name or -1 + +idaman ssize_t ida_export get_entry_forwarder(qstring *buf, uval_t ord); + + +#endif // _ENTRY_HPP diff --git a/idasdk76/include/enum.hpp b/idasdk76/include/enum.hpp new file mode 100644 index 0000000..398d854 --- /dev/null +++ b/idasdk76/include/enum.hpp @@ -0,0 +1,371 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Enums and bitfields + * Bitfields will be abbreviated as "bf". + * + */ + +#ifndef _ENUM_HPP +#define _ENUM_HPP + +#include <nalt.hpp> + +/*! \file enum.hpp + + \brief Assembly level enum management + + Enums and bitfields are represented as ::enum_t. +*/ + +typedef tid_t enum_t; ///< Enums and bitfields + +typedef uval_t bmask_t; ///< unsigned value that describes a bitmask + ///< a bit mask is 32/64 bits. + +#define DEFMASK (bmask_t(-1)) ///< default bitmask + +typedef uval_t const_t; ///< members of enums + +/// Max number of identical constants allowed for one enum type +const uchar MAX_ENUM_SERIAL = 255; + + +/// Get number of declared ::enum_t types + +idaman size_t ida_export get_enum_qty(void); + + +/// Get enum by its index in the list of enums (0..get_enum_qty()-1). + +idaman enum_t ida_export getn_enum(size_t idx); + + +/// Get the index in the list of enums + +idaman uval_t ida_export get_enum_idx(enum_t id); + + +/// Get enum by name + +idaman enum_t ida_export get_enum(const char *name); + + +/// Is enum a bitfield? +/// (otherwise - plain enum, no bitmasks except for #DEFMASK are allowed) + +idaman bool ida_export is_bf(enum_t id); + + +/// Is enum collapsed? + +idaman bool ida_export is_enum_hidden(enum_t id); + + +/// Collapse enum + +idaman bool ida_export set_enum_hidden(enum_t id, bool hidden); + + +/// Does enum come from type library? + +idaman bool ida_export is_enum_fromtil(enum_t id); + + +/// Specify that enum comes from a type library + +idaman bool ida_export set_enum_fromtil(enum_t id, bool fromtil); + + +/// Is a ghost copy of a local type? + +idaman bool ida_export is_ghost_enum(enum_t id); + + +/// Specify that enum is a ghost copy of a local type + +idaman bool ida_export set_enum_ghost(enum_t id, bool ghost); + + +/// Get name of enum + +idaman ssize_t ida_export get_enum_name(qstring *out, enum_t id); + +/// Get name of enum +/// \param[out] out buffer to hold the name +/// \param id enum id +/// \param flags \ref ENFL_ + +idaman ssize_t ida_export get_enum_name2(qstring *out, enum_t id, int flags=0); + +/// \defgroup ENFL_ Enum name flags +/// Passed as 'flags' parameter to get_enum_name() +//@{ +#define ENFL_REGEX 0x0001 ///< apply regular expressions to beautify the name +//@} + +inline qstring get_enum_name(tid_t id, int flags=0) +{ + qstring name; + get_enum_name2(&name, id, flags); + return name; +} + + +/// Get the width of a enum element +/// allowed values: 0 (unspecified),1,2,4,8,16,32,64 + +idaman size_t ida_export get_enum_width(enum_t id); + + +/// See comment for get_enum_width() + +idaman bool ida_export set_enum_width(enum_t id, int width); + + +/// Get enum comment + +idaman ssize_t ida_export get_enum_cmt(qstring *buf, enum_t id, bool repeatable); + + +/// Get the number of the members of the enum + +idaman size_t ida_export get_enum_size(enum_t id); + + +/// Get flags determining the representation of the enum. +/// (currently they define the numeric base: octal, decimal, hex, bin) and signness. + +idaman flags_t ida_export get_enum_flag(enum_t id); + + +/// Get a reference to an enum member by its name + +idaman const_t ida_export get_enum_member_by_name(const char *name); + + +/// Get value of an enum member + +idaman uval_t ida_export get_enum_member_value(const_t id); + + +/// Get the parent enum of an enum member + +idaman enum_t ida_export get_enum_member_enum(const_t id); + + +/// Get bitmask of an enum member + +idaman bmask_t ida_export get_enum_member_bmask(const_t id); + + +/// Find an enum member by enum, value and bitmask +/// \note if serial -1, return a member with any serial + +idaman const_t ida_export get_enum_member(enum_t id, uval_t value, int serial, bmask_t mask); + + +/// \name Access to all used bitmasks in an enum +//@{ + +/// Get first bitmask in the enum (bitfield) +/// +/// \param enum_id id of enum (bitfield) +/// \return the smallest bitmask for enum, or DEFMASK +/// +idaman bmask_t ida_export get_first_bmask(enum_t id); + +/// Get last bitmask in the enum (bitfield) +/// +/// \param enum_id id of enum +/// \return the biggest bitmask for enum, or DEFMASK +idaman bmask_t ida_export get_last_bmask(enum_t id); + +/// Get next bitmask in the enum (bitfield) +/// +/// \param enum_id id of enum +/// \param value the current bitmask +/// \return value of a bitmask with value higher than the specified value, or DEFMASK +idaman bmask_t ida_export get_next_bmask(enum_t id, bmask_t bmask); + +/// Get prev bitmask in the enum (bitfield) +/// +/// \param enum_id id of enum +/// \param value the current bitmask +/// \return value of a bitmask with value lower than the specified value, or DEFMASK +idaman bmask_t ida_export get_prev_bmask(enum_t id, bmask_t bmask); +//@} + + +/// \name Access to all enum members with specified bitmask +/// \note these functions return values, not ::const_t! +//@{ +idaman uval_t ida_export get_first_enum_member(enum_t id, bmask_t bmask=DEFMASK); +idaman uval_t ida_export get_last_enum_member(enum_t id, bmask_t bmask=DEFMASK); +idaman uval_t ida_export get_next_enum_member(enum_t id, uval_t value, bmask_t bmask=DEFMASK); +idaman uval_t ida_export get_prev_enum_member(enum_t id, uval_t value, bmask_t bmask=DEFMASK); +//@} + + +/// Get name of an enum member by const_t + +idaman ssize_t ida_export get_enum_member_name(qstring *out, const_t id); + + +/// Get enum member's comment + +idaman ssize_t ida_export get_enum_member_cmt(qstring *buf, const_t id, bool repeatable); + + +/// \name Access to all enum members with specified value and mask +/// A sample loop looks like this: +/// \code +/// const_t main_cid; +/// uchar serial; +/// for ( const_t cid=main_cid=get_first_serial_enum_member(&serial, id, v, mask); +/// cid != BADNODE; +/// cid = get_next_serial_enum_member(&serial, main_cid) ) +/// { +/// ... +/// } +/// \endcode +/// The 'out_serial' argument of get_first_serial_enum_member/get_last_serial_enum_member can be NULL. +/// The 'in_out_serial' is required for the other functions. +//@{ +idaman const_t ida_export get_first_serial_enum_member(uchar *out_serial, enum_t id, uval_t value, bmask_t bmask); +idaman const_t ida_export get_last_serial_enum_member(uchar *out_serial, enum_t id, uval_t value, bmask_t bmask); +idaman const_t ida_export get_next_serial_enum_member(uchar *in_out_serial, const_t first_cid); +idaman const_t ida_export get_prev_serial_enum_member(uchar *in_out_serial, const_t first_cid); +//@} + + +/// Enum member visitor - see for_all_enum_members(). +/// Derive your visitor from this class. +struct enum_member_visitor_t +{ + /// Implements action to take when enum member is visited. + /// \return nonzero to stop the iteration + virtual int idaapi visit_enum_member(const_t cid, uval_t value) = 0; +}; + + +/// Visit all members of a given enum + +idaman int ida_export for_all_enum_members(enum_t id, enum_member_visitor_t &cv); + + +/// Get serial number of an enum member + +idaman uchar ida_export get_enum_member_serial(const_t cid); + + +/// Get corresponding type ordinal number + +idaman int32 ida_export get_enum_type_ordinal(enum_t id); + + +/// Set corresponding type ordinal number + +idaman void ida_export set_enum_type_ordinal(enum_t id, int32 ord); + + +//-------------------------------------------------------------------------- +// MANIPULATION + +/// Add new enum type. +/// - if idx==#BADADDR then add as the last idx +/// - if name==NULL then generate a unique name "enum_%d" + +idaman enum_t ida_export add_enum(size_t idx, const char *name, flags_t flag); + + +/// Delete an enum type + +idaman void ida_export del_enum(enum_t id); + + +/// Set serial number of enum. +/// Also see get_enum_idx(). + +idaman bool ida_export set_enum_idx(enum_t id, size_t idx); + + +/// Set 'bitfield' bit of enum (i.e. convert it to a bitfield) + +idaman bool ida_export set_enum_bf(enum_t id, bool bf); + + +/// Set name of enum type + +idaman bool ida_export set_enum_name(enum_t id,const char *name); + + +/// Set comment for enum type + +idaman bool ida_export set_enum_cmt(enum_t id,const char *cmt,bool repeatable); + + +/// Set data representation flags + +idaman bool ida_export set_enum_flag(enum_t id, flags_t flag); + + +/// Add member to enum type. +/// \return 0 if ok, otherwise one of \ref ENUM_MEMBER_ + +idaman int ida_export add_enum_member( + enum_t id, + const char *name, + uval_t value, + bmask_t bmask=DEFMASK); + + +/// \defgroup ENUM_MEMBER_ Add enum member result codes +/// Return values for add_enum_member() +//@{ +#define ENUM_MEMBER_ERROR_NAME 1 ///< already have member with this name (bad name) +#define ENUM_MEMBER_ERROR_VALUE 2 ///< already have 256 members with this value +#define ENUM_MEMBER_ERROR_ENUM 3 ///< bad enum id +#define ENUM_MEMBER_ERROR_MASK 4 ///< bad bmask +#define ENUM_MEMBER_ERROR_ILLV 5 ///< bad bmask and value combination (~bmask & value != 0) +//@} + + +/// Delete member of enum type + +idaman bool ida_export del_enum_member(enum_t id, uval_t value, uchar serial, bmask_t bmask); + + +/// Set name of enum member + +idaman bool ida_export set_enum_member_name(const_t id, const char *name); + + +/// Set comment for enum member + +inline bool set_enum_member_cmt(const_t id, const char *cmt, bool repeatable) +{ + return set_enum_cmt(id, cmt, repeatable); +} + + +/// Is bitmask one bit? + +inline THREAD_SAFE bool is_one_bit_mask(bmask_t mask) +{ + return (mask & (mask-1)) == 0; +} + + +/// \name Work with the bitmask name & comment +//@{ +idaman bool ida_export set_bmask_name(enum_t id, bmask_t bmask, const char *name); +idaman ssize_t ida_export get_bmask_name(qstring *out, enum_t id, bmask_t bmask); + +idaman bool ida_export set_bmask_cmt(enum_t id, bmask_t bmask, const char *cmt, bool repeatable); +idaman ssize_t ida_export get_bmask_cmt(qstring *buf, enum_t id, bmask_t bmask, bool repeatable); +//@} + +#endif // _ENUM_HPP diff --git a/idasdk76/include/err.h b/idasdk76/include/err.h new file mode 100644 index 0000000..4acf0ee --- /dev/null +++ b/idasdk76/include/err.h @@ -0,0 +1,96 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _ERR_H +#define _ERR_H + +#include <errno.h> + +/*! \file err.h + + \brief Thread safe functions that deal with error codes + +*/ + +/// Print error message to stderr (analog of perror) + +idaman THREAD_SAFE AS_PRINTF(1, 0) void ida_export vqperror(const char *format, va_list va); + + +/// Get error description string. +/// if _qerrno=-1, get_qerrno() will be used + +idaman THREAD_SAFE const char *ida_export qstrerror(error_t _qerrno); + + +/// A convenience function to generate error messages (returns "header: error message") + +idaman THREAD_SAFE char *ida_export get_errdesc(const char *header, error_t _qerrno=-1); + + +/// Get error message for MS Windows error codes + +idaman THREAD_SAFE char *ida_export winerr(int code); + + +/// errno or GetLastError() depending on the system. + +idaman THREAD_SAFE int ida_export qerrcode(int new_code=-1); + + +/// Get error string corresponding to qerrcode(). +/// if code == -1, then qerrcode() will be called. + +idaman const char *ida_export qerrstr(int code=-1); + + +#ifdef __cplusplus + +/// See vqperror() + +THREAD_SAFE AS_PRINTF(1, 2) inline void qperror(const char *format, ...) +{ + va_list va; + va_start(va, format); + vqperror(format, va); + va_end(va); +} + + +/// See set_qerrno() + +THREAD_SAFE inline void set_errno(int code) +{ + errno = code; + set_qerrno(eOS); +} +#endif + +// Internal functions +/// \cond + +// n=0..3 +idaman THREAD_SAFE void ida_export set_error_data(int n, size_t data); +idaman THREAD_SAFE void ida_export set_error_string(int n, const char *str); +idaman THREAD_SAFE size_t ida_export get_error_data(int n); +idaman THREAD_SAFE const char *ida_export get_error_string(int n); + +#define QPRM_TYPE(t,n,x) set_error_data(n-1, t(x)) +#define QPRM_CHAR(n,x) QPRM_TYPE(char,n,x) +#define QPRM_SHORT(n,x) QPRM_TYPE(short,n,x) +#define QPRM_INT(n,x) QPRM_TYPE(int,n,x) +#define QPRM_INT32(n,x) QPRM_TYPE(int32,n,x) +#define QPRM_UCHAR(n,x) QPRM_TYPE(uchar,n,x) +#define QPRM_USHORT(n,x) QPRM_TYPE(ushort,n,x) +#define QPRM_UINT(n,x) QPRM_TYPE(uint,n,x) +#define QPRM_UINT32(n,x) QPRM_TYPE(uint32,n,x) +#define QPRM(n,x) set_error_string(n-1, x) + +/// \endcond + +#endif + diff --git a/idasdk76/include/exehdr.h b/idasdk76/include/exehdr.h new file mode 100644 index 0000000..8ac6edc --- /dev/null +++ b/idasdk76/include/exehdr.h @@ -0,0 +1,67 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * EXE-file header layout + * + */ + +#ifndef __EXEHDR_H +#define __EXEHDR_H +#pragma pack(push, 1) + +struct exehdr +{ + uint16 exe_ident; +#define EXE_ID 0x5A4D // 'MZ' +#define EXE_ID2 0x4D5A // 'ZM' (DOS works with this also) + uint16 PartPag; + uint16 PageCnt; + uint16 ReloCnt; + uint16 HdrSize; + uint16 MinMem; + uint16 MaxMem; + uint16 ReloSS; + uint16 ExeSP; + uint16 ChkSum; + uint16 ExeIP; + uint16 ReloCS; + uint16 TablOff; + uint16 Overlay; +/* + uint16 res[4]; // Reserved words + uint16 oemid; // OEM identifier (for e_oeminfo) + uint16 oeminfo; // OEM information; e_oemid specific + uint16 res2[10]; // Reserved words + uint32 lfanew; // File address of new exe header +*/ + int32 CalcEXE_Length(void) + { + int32 len = PageCnt * 512L - HdrSize * 16; + if ( PartPag != 0 ) + len -= 512 - PartPag; + return len; + } + void CalcEXE_Pages(int32 len) + { + PartPag = uint16(len % 512); + PageCnt = uint16(len / 512); + if ( PartPag != 0 ) + PageCnt++; + } +}; + +struct exehdr_full: exehdr +{ + uint16 res[4]; // Reserved words + uint16 oemid; // OEM identifier (for e_oeminfo) + uint16 oeminfo; // OEM information; e_oemid specific + uint16 res2[10]; // Reserved words + uint32 lfanew; // File address of new exe header +}; + +#define PSPsize 0x100 +#define PE_PTROFF 0x3C +#pragma pack(pop) +#endif diff --git a/idasdk76/include/expr.hpp b/idasdk76/include/expr.hpp new file mode 100644 index 0000000..b0356c0 --- /dev/null +++ b/idasdk76/include/expr.hpp @@ -0,0 +1,1192 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _EXPR_H +#define _EXPR_H + +#include <ieee.h> +#include <idp.hpp> + +/*! \file expr.hpp + + \brief Functions that deal with C-like expressions and built-in IDC language. + + Functions marked #THREAD_SAFE may be called from any thread. + No simultaneous calls should be made for the same variable. + We protect only global structures, individual variables must + be protected manually. +*/ + +//------------------------------------------------------------------------ + +// Forward declarations +class idc_value_t; +class idc_class_t; +class idc_object_t; + +/// IDC script extension +#define IDC_LANG_EXT "idc" + +/// Convert IDC variable to a long (32/64bit) number. +/// \return v = 0 if impossible to convert to long + +idaman THREAD_SAFE error_t ida_export idcv_long(idc_value_t *v); + + +/// Convert IDC variable to a 64bit number. +/// \return v = 0 if impossible to convert to int64 + +idaman THREAD_SAFE error_t ida_export idcv_int64(idc_value_t *v); + + +/// Convert IDC variable to a long number. +/// \return +/// - v = 0 if IDC variable = "false" string +/// - v = 1 if IDC variable = "true" string +/// - v = number if IDC variable is number or string containing a number +/// - eTypeConflict if IDC variable = empty string + +idaman THREAD_SAFE error_t ida_export idcv_num(idc_value_t *v); + + +/// Convert IDC variable to a text string + +idaman THREAD_SAFE error_t ida_export idcv_string(idc_value_t *v); + + +/// Convert IDC variable to a floating point + +idaman THREAD_SAFE error_t ida_export idcv_float(idc_value_t *v); + + +/// Create an IDC object. The original value of 'v' is discarded (freed). +/// \param v variable to hold the object. any previous value will be cleaned +/// \param icls ptr to the desired class. NULL means "object" class +/// this ptr must be returned by add_idc_class() or find_idc_class() +/// \return always eOk + +idaman THREAD_SAFE error_t ida_export idcv_object( + idc_value_t *v, + const idc_class_t *icls=NULL); + + +/// Move 'src' to 'dst'. +/// This function is more effective than copy_idcv since it never copies big +/// amounts of data. + +idaman THREAD_SAFE error_t ida_export move_idcv( + idc_value_t *dst, + idc_value_t *src); + + +/// Copy 'src' to 'dst'. +/// For idc objects only a reference is copied. + +idaman THREAD_SAFE error_t ida_export copy_idcv( + idc_value_t *dst, + const idc_value_t &src); + + +/// Deep copy an IDC object. +/// This function performs deep copy of idc objects. +/// If 'src' is not an object, copy_idcv() will be called + +idaman THREAD_SAFE error_t ida_export deep_copy_idcv( + idc_value_t *dst, + const idc_value_t &src); + + +/// Free storage used by #VT_STR/#VT_OBJ IDC variables. +/// After this call the variable has a numeric value 0 + +idaman THREAD_SAFE void ida_export free_idcv(idc_value_t *v); + + +/// Swap 2 variables + +idaman THREAD_SAFE void ida_export swap_idcvs( + idc_value_t *v1, + idc_value_t *v2); + + +/// Retrieves the IDC object class name. +/// \param out qstring ptr for the class name. Can be NULL. +/// \param obj class instance variable +/// \return error code, eOk on success + +idaman THREAD_SAFE error_t ida_export get_idcv_class_name( + qstring *out, + const idc_value_t *obj); + + +/// Get an object attribute. +/// \param res buffer for the attribute value +/// \param obj variable that holds an object reference. +/// if obj is NULL it searches global variables, then user functions +/// \param attr attribute name +/// \param may_use_getattr may call getattr functions to calculate the attribute if it does not exist +/// \return error code, eOk on success + +idaman THREAD_SAFE error_t ida_export get_idcv_attr( + idc_value_t *res, + const idc_value_t *obj, + const char *attr, + bool may_use_getattr=false); + + +/// Set an object attribute. +/// \param obj variable that holds an object reference. +/// if obj is NULL then it tries to modify a global variable with the attribute name +/// \param attr attribute name +/// \param value new attribute value +/// \param may_use_setattr may call setattr functions for the class +/// \return error code, eOk on success + +idaman THREAD_SAFE error_t ida_export set_idcv_attr( + idc_value_t *obj, + const char *attr, + const idc_value_t &value, + bool may_use_setattr=false); + + +/// Delete an object attribute. +/// \param obj variable that holds an object reference +/// \param attr attribute name +/// \return error code, eOk on success + +idaman THREAD_SAFE error_t ida_export del_idcv_attr( + idc_value_t *obj, + const char *attr); + + +/// \name Enumerate object attributes +//@{ +idaman THREAD_SAFE const char *ida_export first_idcv_attr(const idc_value_t *obj); +idaman THREAD_SAFE const char *ida_export last_idcv_attr(const idc_value_t *obj); +idaman THREAD_SAFE const char *ida_export next_idcv_attr(const idc_value_t *obj, const char *attr); +idaman THREAD_SAFE const char *ida_export prev_idcv_attr(const idc_value_t *obj, const char *attr); +//@} + + +/// Get text representation of idc_value_t + +idaman bool ida_export print_idcv( + qstring *out, + const idc_value_t &v, + const char *name=NULL, + int indent=0); + + +/// Get slice. +/// \param res output variable that will contain the slice +/// \param v input variable (string or object) +/// \param i1 slice start index +/// \param i2 slice end index (excluded) +/// \param flags \ref VARSLICE_ or 0 +/// \returns eOk if success + +idaman THREAD_SAFE error_t ida_export get_idcv_slice( + idc_value_t *res, + const idc_value_t *v, + uval_t i1, + uval_t i2, + int flags=0); + +/// \defgroup VARSLICE_ IDC variable slice flags +/// Passed as 'flags' parameter to get_idcv_slice() and set_idcv_slice() +//@{ +#define VARSLICE_SINGLE 0x0001 ///< return single index (i2 is ignored) +//@} + +/// Set slice. +/// \param v variable to modify (string or object) +/// \param i1 slice start index +/// \param i2 slice end index (excluded) +/// \param in new value for the slice +/// \param flags \ref VARSLICE_ or 0 +/// \return eOk on success + +idaman THREAD_SAFE error_t ida_export set_idcv_slice( + idc_value_t *v, + uval_t i1, + uval_t i2, + const idc_value_t &in, + int flags=0); + + +//------------------------------------------------------------------------- +// IDC class related functions + +/// Create a new IDC class. +/// \param name name of the new class +/// \param super the base class for the new class. if the new class is not based +/// on any other class, pass NULL +/// \return pointer to the created class. If such a class already exists, a pointer +/// to it will be returned. +/// Pointers to other existing classes may be invalidated by this call. + +idaman THREAD_SAFE idc_class_t *ida_export add_idc_class( + const char *name, + const idc_class_t *super=NULL); + + +/// Find an existing IDC class by its name. +/// \param name name of the class +/// \return pointer to the class or NULL. +/// The returned pointer is valid until a new call to add_idc_class() + +idaman THREAD_SAFE idc_class_t *ida_export find_idc_class(const char *name); + + +/// Set an IDC class method. +/// \param icls pointer to the class +/// \param fullfuncname name of the function to call. use full method name: classname.funcname +/// \retval true success +/// \retval false the function could not be found + +idaman THREAD_SAFE bool ida_export set_idc_method(idc_class_t *icls, const char *fullfuncname); + + +/// \name Set user-defined functions to work with object attributes. +/// If the function name is NULL, the definitions are removed. +/// \return name of the old attribute function. NULL means error, "" means no previous attr func +//@{ +idaman THREAD_SAFE const char *ida_export set_idc_getattr(idc_class_t *icls, const char *fullfuncname); +idaman THREAD_SAFE const char *ida_export set_idc_setattr(idc_class_t *icls, const char *fullfuncname); +//@} + +/// Set a destructor for an idc class. +/// The destructor is called before deleting any object of the specified class. +/// Exceptions that escape the destructor are silently ignored, runtime errors too. + +idaman THREAD_SAFE const char *ida_export set_idc_dtor(idc_class_t *icls, const char *fullfuncname); + + +/// Dereference a #VT_REF variable. +/// \param v variable to dereference +/// \param vref_flags \ref VREF_ +/// \return pointer to the dereference result or NULL. +/// If returns NULL, qerrno is set to eExecBadRef "Illegal variable reference" + +idaman THREAD_SAFE idc_value_t *ida_export deref_idcv(idc_value_t *v, int vref_flags); + +/// \defgroup VREF_ Dereference IDC variable flags +/// Passed as 'vref_flags' parameter to deref_idcv() +//@{ +#define VREF_LOOP 0x0000 ///< dereference until we get a non #VT_REF +#define VREF_ONCE 0x0001 ///< dereference only once, do not loop +#define VREF_COPY 0x0002 ///< copy the result to the input var (v) +//@} + + +/// Create a variable reference. +/// Currently only references to global variables can be created. +/// \param ref ptr to the result +/// \param v variable to reference +/// \return success + +idaman THREAD_SAFE bool ida_export create_idcv_ref(idc_value_t *ref, const idc_value_t *v); + + +/// Add global IDC variable. +/// \param name name of the global variable +/// \return pointer to the created variable or existing variable. +/// NB: the returned pointer is valid until a new global var is added. + +idaman THREAD_SAFE idc_value_t *ida_export add_idc_gvar(const char *name); + + +/// Find an existing global IDC variable by its name. +/// \param name name of the global variable +/// \return pointer to the variable or NULL. +/// NB: the returned pointer is valid until a new global var is added. +/// FIXME: it is difficult to use this function in a thread safe manner + +idaman THREAD_SAFE idc_value_t *ida_export find_idc_gvar(const char *name); + + +//------------------------------------------------------------------------- +/// Class to hold idc values +class idc_value_t +{ +public: +/// \defgroup VT_ IDC value types +/// Used by idc_value_t::vtype +//@{ +#define VT_LONG 2 ///< Integer (see idc_value_t::num) +#define VT_FLOAT 3 ///< Floating point (see idc_value_t::e) +#define VT_WILD 4 ///< Function with arbitrary number of arguments. + ///< The actual number of arguments will be passed in idc_value_t::num. + ///< This value should not be used for ::idc_value_t. +#define VT_OBJ 5 ///< Object (see idc_value_t::obj) +#define VT_FUNC 6 ///< Function (see idc_value_t::funcidx) +#define VT_STR 7 ///< String (see qstr() and similar functions) +#define VT_PVOID 8 ///< void * +#define VT_INT64 9 ///< i64 +#define VT_REF 10 ///< Reference +//@} + char vtype = VT_LONG; ///< \ref VT_ + +#ifndef SWIG + union + { +#endif // SWIG + sval_t num; ///< #VT_LONG + fpvalue_t e; ///< #VT_FLOAT + idc_object_t *obj; + int funcidx; ///< #VT_FUNC + void *pvoid; ///< #VT_PVOID + int64 i64; ///< #VT_INT64 + uchar reserve[sizeof(qstring)]; ///< internal housekeeping: 64-bit qstring is bigger than 12 bytes +#ifndef SWIG + }; +#endif // SWIG + + /// Create a #VT_LONG value + idc_value_t(sval_t n=0) : num(n) {} + /// Create a $VT_LONG with an existing idc value + idc_value_t(const idc_value_t &r) { copy_idcv(this, r); } + /// Create a #VT_STR value + idc_value_t(const char *_str) : vtype(VT_STR) { new(&qstr()) qstring(_str); } + /// Create a #VT_STR value + idc_value_t(const qstring &_str) : vtype(VT_STR) { new(&qstr()) qstring(_str); } + /// Destructor + ~idc_value_t(void) { clear(); } + /// See free_idcv() + void clear(void) { free_idcv(this); } // put num 0 + /// Assign this value to an existing value + idc_value_t &operator = (const idc_value_t &r) + { + copy_idcv(this, r); + return *this; + } + qstring &qstr(void) { return *(qstring *)# } ///< #VT_STR + const qstring &qstr(void) const { return *(qstring *)# } ///< #VT_STR + const char *c_str(void) const { return qstr().c_str(); } ///< #VT_STR + const uchar *u_str(void) const { return (const uchar *)c_str(); } ///< #VT_STR + void swap(idc_value_t &v) { swap_idcvs(this, &v); } ///< Set this = r and v = this + bool is_zero(void) const { return vtype == VT_LONG && num == 0; } ///< Does value represent the integer 0? + bool is_integral(void) { return vtype == VT_LONG || vtype == VT_INT64; } ///< Does value represent a whole number? + /// Convertible types are #VT_LONG, #VT_FLOAT, #VT_INT64, and #VT_STR + bool is_convertible(void) const { return (vtype >= 1 && vtype <= VT_FLOAT) || vtype == VT_STR || vtype == VT_INT64; } + + /// \name Warning + /// The following functions do not free the existing data! + /// When the contents are unknown, use the functions without a leading underscore. + //@{ + void _create_empty_string(void) { vtype = VT_STR; new (&qstr()) qstring; } + void _set_string(const qstring &_str) + { + vtype = VT_STR; + new (&qstr()) qstring(_str); + } + void _set_string(const char *_str, size_t len) + { + vtype = VT_STR; + new (&qstr()) qstring(_str, len); + } + void _set_string(const char *_str) + { + size_t len = _str == NULL ? 0 : strlen(_str); + _set_string(_str, len); + } + void _set_long(sval_t v) { vtype = VT_LONG; num = v; } + void _set_pvoid(void *p) { vtype = VT_PVOID; pvoid = p; } + void _set_int64(int64 v) { vtype = VT_INT64; i64 = v; } + void _set_float(const fpvalue_t &f) { vtype = VT_FLOAT; e = f; } + //@} + + /// \name Setters + /// These functions ensure the previous value is cleared + //@{ + void create_empty_string(void) { clear(); _create_empty_string(); } + void set_string(const char *_str, size_t len) { clear(); _set_string(_str, len); } + void set_string(const char *_str) { clear(); _set_string(_str); } + void set_string(const qstring &_str) { clear(); _set_string(_str); } + void set_long(sval_t v) { clear(); _set_long(v); } + void set_pvoid(void *p) { clear(); vtype = VT_PVOID; pvoid = p; } + void set_int64(int64 v) { clear(); vtype = VT_INT64; i64 = v; } + void set_float(const fpvalue_t &f) { clear(); vtype = VT_FLOAT; e = f; } + //@} +}; + +/// Global idc variable +struct idc_global_t +{ + qstring name; + idc_value_t value; + idc_global_t(void) {} + idc_global_t(const char *n) : name(n) {} +}; +typedef qvector<idc_global_t> idc_vars_t; ///< vector of global idc variables + +/// Prototype of an external IDC function (implemented in C). +/// \param argv vector of input arguments. IDA will convert all arguments +/// to types specified by ext_idcfunc_t::args, except for #VT_WILD +/// \param r return value of the function or exception +/// \return 0 if ok, all other values indicate error. +/// the error code must be set with set_qerrno(): +/// - #eExecThrow - a new exception has been generated, see 'r' +/// - other values - runtime error has occurred + +typedef error_t idaapi idc_func_t(idc_value_t *argv, idc_value_t *r); + +#define eExecThrow 90 ///< See return value of ::idc_func_t + +/// Element of functions table. See idcfuncs_t::funcs +struct ext_idcfunc_t +{ + const char *name; ///< Name of function + idc_func_t *fptr; ///< Pointer to the Function + const char *args; ///< Type of arguments. Terminated with 0. + ///< #VT_WILD at the end means a variadic function. + ///< Actual number of arguments will be passed + ///< in res->num in this case. + const idc_value_t *defvals; ///< Default argument values. + ///< Only the rightmost arguments may have + ///< default values. + int ndefvals; ///< Number of default values. + int flags; ///< \ref EXTFUN_ +/// \defgroup EXTFUN_ Function description flags +/// Used by ext_idcfunc_t::flags +//@{ +#define EXTFUN_BASE 0x0001 ///< requires open database. +#define EXTFUN_NORET 0x0002 ///< does not return. the interpreter may + ///< clean up its state before calling it. +#define EXTFUN_SAFE 0x0004 ///< thread safe function. may be called + ///< from any thread. +//@} +}; + +/// Describes an array of IDC functions +struct idcfuncs_t +{ + size_t qnty; ///< Number of functions + ext_idcfunc_t *funcs; ///< Function table + + /// \name IDC Engine + /// IDC engine requires the following functions (all of them may be NULL) + //@{ + + /// Start IDC engine. Called before executing any IDC code. + error_t (idaapi *startup)(void); + + /// Stop IDC engine. Called when all IDC engines finish. + /// In other words, nested IDC engines do not call startup/shutdown. + error_t (idaapi *shutdown)(void); + + /// Initialize IDC engine. Called once at the very beginning of work. + /// This callback may create additional IDC classes, methods, etc. + void (idaapi *init_idc)(void); + + /// Terminate IDC engine. Called once at the very end of work. + void (idaapi *term_idc)(void); + + /// Is the database open? (used for #EXTFUN_BASE functions). + /// if this pointer is NULL, #EXTFUN_BASE is not checked. + bool (idaapi *is_database_open)(void); + + /// Convert an address to a string. + /// if this pointer is NULL, '%a' will be used. + size_t (idaapi *ea2str)(char *buf, size_t bufsize, ea_t ea); + + /// Should a variable name be accepted without declaration?. + /// When the parser encounters an unrecognized variable, this callback is called. + /// If it returns false, the parser generates the 'undefined variable' error + /// else the parser generates code to call to a set or get function, + /// depending on the current context. + /// If this pointer is NULL, undeclared variables won't be supported. + /// However, if 'resolver' object is provided to the parser, it will be used + /// to resolve such names to constants at the compilation time. + /// This callback is used by IDA to handle processor register names. + bool (idaapi *undeclared_variable_ok)(const char *name); + + //@} + + /// \name Indexes + /// Indexes into the 'f' array. non-positive values mean that the function does not exist + //@{ + + /// Retrieve value of an undeclared variable. + /// Expected prototype: get(#VT_STR varname) + int get_unkvar; + + /// Store a value to an undeclared variable. + /// Expected prototype: set(#VT_WILD new_value, #VT_STR varname) + int set_unkvar; + + /// Execute resolved function. + /// If 'resolver' was used to resolve an unknown name to a constant in a function + /// call context, such a call will be redirected here. + /// Expected prototype: exec_resolved_func(#VT_LONG func, #VT_WILD typeinfo, ...) + /// This callback is used in IDA for Appcall. + int exec_resolved_func; + + /// Calculate sizeof(type). + /// This function is used by the interpreter to calculate sizeof() expressions. + /// Please note that the 'type' argument is an IDC object of typeinfo class. + /// Expected prototype: calc_sizeof(#VT_OBJ typeinfo) + /// This callback requires support of the type system (available only in IDA kernel) + /// It should not be used by standalone IDC interpreters. + int calc_sizeof; + + /// Get address of the specified field using the type information from the idb. + /// This function is used to resolve expressions like 'mystr.field' where + /// mystr does not represent an IDC object but just a plain number. + /// The number is interpreted as an address in the current idb. + /// This function retrieves type information at this address and tried to find + /// the specified 'field'. It returns the address of the 'field' in the idb. + /// This callback should not be used by standalone IDC interpreters. + int get_field_ea; + + //@} +}; + +// Our idc_value_t and idc_global_t classes are freely movable with memcpy() +DECLARE_TYPE_AS_MOVABLE(idc_value_t); +DECLARE_TYPE_AS_MOVABLE(idc_global_t); + +//------------------------------------------------------------------------ +/// Add an IDC function. +/// This function does not modify the predefined kernel functions. +/// Example: +/// \code +/// static error_t idaapi myfunc5(idc_value_t *argv, idc_value_t *res) +/// { +/// msg("myfunc is called with arg0=%a and arg1=%s\n", argv[0].num, argv[1].str); +/// res->num = 5; // let's return 5 +/// return eOk; +/// } +/// static const char myfunc5_args[] = { VT_LONG, VT_STR, 0 }; +/// static const ext_idcfunc_t myfunc_desc = { "MyFunc5", myfunc5, myfunc5_args, NULL, 0, EXTFUN_BASE }; +/// +/// // after this: +/// add_idc_func(myfunc_desc); +/// +/// // there is a new IDC function which can be called like this: +/// MyFunc5(0x123, "test"); +/// +/// \endcode +/// \param func function description block. +/// \note If the function already exists, it will be replaced by the new function +/// \return success + +idaman THREAD_SAFE bool ida_export add_idc_func(const ext_idcfunc_t &func); + + +/// Delete an IDC function +/// +idaman THREAD_SAFE bool ida_export del_idc_func(const char *name); + + +// Find an idc function that starts with the given prefix. +// \param out buffer for the output name +// \param prefix prefix to search for +// \param n how many matches to skip +// Returns: success +idaman THREAD_SAFE bool ida_export find_idc_func( + qstring *out, + const char *prefix, + int n=0); + + +/// Possible syntax element highlighting style names +enum syntax_highlight_style +{ + HF_DEFAULT = 0, + HF_KEYWORD1 = 1, + HF_KEYWORD2 = 2, + HF_KEYWORD3 = 3, + HF_STRING = 4, + HF_COMMENT = 5, + HF_PREPROC = 6, + HF_NUMBER = 7, + + HF_MAX, +}; +#define HF_FIRST HF_KEYWORD1 + +struct highlighter_cbs_t +{ + virtual ~highlighter_cbs_t() {} + virtual void idaapi set_style(int32 /*start*/, int32 /*len*/, syntax_highlight_style /*style*/) {} + virtual int32 idaapi prev_block_state() { return 0; } + virtual int32 idaapi cur_block_state() { return 0; } + virtual void idaapi set_block_state(int32 /*state*/) {} +}; + +/// Base class for syntax highligters +struct syntax_highlighter_t +{ + /// Function for extlang syntax highlighting + /// \param context implementation specific context. can be NULL + /// \param ighlighter_cbs structure with set of callbacks + /// \param text part of text to colorize + typedef void idaapi block_highlighter_t( + void *context, + highlighter_cbs_t *highlighter_cbs, + const qstring &text); + syntax_highlighter_t(block_highlighter_t *bh=nullptr) : highlight_block(bh) {} + virtual ~syntax_highlighter_t() {} + block_highlighter_t *highlight_block; +}; + + +//------------------------------------------------------------------------ +/// External language (to support third party language interpreters) +struct extlang_t +{ + size_t size; ///< Size of this structure + uint32 flags; ///< Language features +#define EXTLANG_IDC 0x01 +#define EXTLANG_NS_AWARE 0x02 ///< Namespace-aware (see above.) + int32 refcnt; ///< Reference count + const char *name; ///< Language name + const char *fileext; ///< File name extension for the language + syntax_highlighter_t *highlighter; // Language syntax highlighter + + /// Compile an expression. + /// \param name name of the function which will + /// hold the compiled expression + /// \param current_ea current address. if unknown then #BADADDR + /// \param expr expression to compile + /// \param[out] errbuf error message if compilation fails + /// \return success + bool (idaapi *compile_expr)( + const char *name, + ea_t current_ea, + const char *expr, + qstring *errbuf); + + /// Compile (load) a file. + /// + /// If an extlang_t object claims to be namespace-aware, it means its + /// 'compile_file()' will have to create namespaces for _certain_ paths: + /// - plugins, + /// - loaders. + /// + /// For example, if compile_file() receives a hypothetical path: + /// .../loaders/myloader.py, + /// the namespace-aware extlang_t handling 'py' files will have to create + /// a namespace derived from the loader file name (without its extension), + /// i.e., '__loaders__myloader', into which the file will be compiled. + /// + /// Then, call_func() has to be prepared to receive a function name that + /// is namespace-qualified: "__loaders__myloader.accept_file()". + /// + /// compile_file() must handle the following 'special' paths, and create + /// the following namespaces to compile them into: + /// .../loaders/<filename> => '__loaders__<filename-noext>' + /// .../plugins/<filename> => '__plugins__<filename-noext>' + /// + /// Similarly, a namespace-aware extlang_t's load_procmod() + /// will have to load the processor module in its own namespace: + /// .../procs/<filename> => '__procs__<filename-noext>' + /// + /// \param file file name + /// \param[out] errbuf error message if compilation fails + bool (idaapi *compile_file)(const char *file, qstring *errbuf); + + /// Evaluate a previously compiled expression. + /// \param[out] result function result or exception + /// \param name function to call + /// \param nargs number of input arguments + /// \param args input arguments + /// \param[out] errbuf error message if evaluation fails + /// \return success + bool (idaapi *call_func)( + idc_value_t *result, + const char *name, + const idc_value_t args[], + size_t nargs, + qstring *errbuf); + + /// Compile and evaluate an expression. + /// \param[out] rv expression value or exception + /// \param current_ea current address. if unknown then BADADDR + /// \param expr expression to evaluate + /// \param[out] errbuf error message if evaluation fails + /// \return success + bool (idaapi *eval_expr)( + idc_value_t *rv, + ea_t current_ea, + const char *expr, + qstring *errbuf); + + /// Compile and execute a string with statements. + /// (see also: eval_expr() which works with expressions) + /// \param str input string to execute + /// \param[out] errbuf error message + /// \return success + bool (idaapi *eval_snippet)( + const char *str, + qstring *errbuf); + + /// Create an object instance. + /// \param result created object or exception + /// \param name object class name + /// \param args input arguments + /// \param nargs number of input arguments + /// \param errbuf error message if evaluation fails + /// \return success + bool (idaapi *create_object)( + idc_value_t *result, + const char *name, + const idc_value_t args[], + size_t nargs, + qstring *errbuf); + + /// Returns the attribute value of a given object from the global scope. + /// \param[out] result attribute value + /// \param obj object (may be NULL) + /// \param attr attribute name. + /// if NULL or empty string then the object instance name + /// (i.e. class name) should be returned. + /// \return success + bool (idaapi *get_attr)( + idc_value_t *result, + const idc_value_t *obj, + const char *attr); + + /// Sets the attribute value of a given object in the global scope. + /// \param obj object (may be NULL) + /// \param attr attribute name + /// \param value attribute value + /// \return success + bool (idaapi *set_attr)( + idc_value_t *obj, + const char *attr, + const idc_value_t &value); + + /// Calls a member function. + /// \param[out] result function result or exception + /// \param obj object instance + /// \param name method name to call + /// \param args input arguments + /// \param nargs number of input arguments + /// \param[out] errbuf error message if evaluation fails + /// \return success + bool (idaapi *call_method)( + idc_value_t *result, + const idc_value_t *obj, + const char *name, + const idc_value_t args[], + size_t nargs, + qstring *errbuf); + + /// Compile (load) a file with processor module. + /// + /// See the note about namespace-awareness in compile_file() + /// + /// \param[out] procobj created object or exception + /// \param path processor module file name + /// \param[out] errbuf error message if compilation fails + /// \retval true success + /// \retval false if errbuf is empty then file has been + /// loaded (compiled) successfully but + /// it doesn't contain processor module + bool (idaapi *load_procmod)( + idc_value_t *procobj, + const char *path, + qstring *errbuf); + + /// Unload previously loaded processor module. + /// \param path processor module file name + /// \param[out] errbuff error message if compilation fails + /// \return success + bool (idaapi *unload_procmod)( + const char *path, + qstring *errbuf); + + bool is_idc(void) const { return (flags & EXTLANG_IDC) != 0; } + bool is_namespace_aware(void) const { return (flags & EXTLANG_NS_AWARE) != 0; } + void release(void) {} +}; + +typedef qvector<extlang_t *> extlangs_t; ///< vector of external language descriptions +typedef qrefcnt_t<extlang_t> extlang_object_t; + +/// Get current active external language. + +idaman void *ida_export get_current_extlang(void); // do not use + +inline const extlang_object_t get_extlang(void) // use this function +{ + return extlang_object_t((extlang_t *)get_current_extlang()); +} + + +/// Install an external language interpreter. +/// Any previously registered interpreter will be automatically unregistered. +/// The installed extlang can be used in select_extlang(). +/// \param el description of the new language. must point to static storage. +/// \return extlang id; -1 means failure and will happen if the extlang has +/// already been installed + +idaman ssize_t ida_export install_extlang(extlang_t *el); + + +/// Uninstall an external language interpreter. +/// \return success + +idaman bool ida_export remove_extlang(extlang_t *el); + + +/// Selects the external language interpreter. +/// The specified extlang must be registered before selecting it. +/// It will be used to evaluate expressions entered in dialog boxes. +/// It will also replace the eval_expr() and eval_expr_long() functions. +/// \return success + +idaman bool ida_export select_extlang(extlang_t *el); + + +struct extlang_visitor_t +{ + virtual ssize_t idaapi visit_extlang(extlang_t *extlang) = 0; +}; + +/// Process all registered extlangs +// \param ev visitor object +// \param select temporarily select extlang for the duration of the visit +// \return 0 or the first non-zero value returned by visit_extlang() + +idaman ssize_t ida_export for_all_extlangs(extlang_visitor_t &ev, bool select=false); + + +// Helper function to search for extlang +enum find_extlang_kind_t +{ + FIND_EXTLANG_BY_EXT, + FIND_EXTLANG_BY_NAME, + FIND_EXTLANG_BY_IDX, +}; + +// do not use +idaman void *ida_export find_extlang(const void *str, find_extlang_kind_t kind); + + +/// Get the extlang that can handle the given file extension + +inline extlang_object_t find_extlang_by_ext(const char *ext) +{ + return extlang_object_t((extlang_t *)find_extlang(ext, FIND_EXTLANG_BY_EXT)); +} + +/// Find an extlang by name + +inline extlang_object_t find_extlang_by_name(const char *name) +{ + return extlang_object_t((extlang_t *)find_extlang(name, FIND_EXTLANG_BY_NAME)); +} + +/// Find an extlang by index + +inline extlang_object_t find_extlang_by_index(size_t idx) +{ + return extlang_object_t((extlang_t *)find_extlang(&idx, FIND_EXTLANG_BY_IDX)); +} + + + +//------------------------------------------------------------------------ +/// Set or append a header path. +/// IDA looks for the include files in the appended header paths, +/// then in the ida executable directory. +/// \param path list of directories to add (separated by ';') +/// may be NULL, in this case nothing is added +/// \param add true: append. +/// false: remove old paths. +/// \retval true success +/// \retval false no memory + +idaman THREAD_SAFE bool ida_export set_header_path(const char *path, bool add); + + +/// Get full name of IDC file name. +/// Search for file in list of include directories, IDCPATH directory +/// and system directories. +/// \param buf buffer for the answer +/// \param bufsize size of buffer +/// \param file file name without full path +/// \return NULL is file not found. +/// otherwise returns pointer to buf + +idaman THREAD_SAFE char *ida_export get_idc_filename( + char *buf, + size_t bufsize, + const char *file); + + +/// Compile and execute "main" function from system file. +/// \param file file name with IDC function(s). +/// The file will be searched using get_idc_filename(). +/// \param complain_if_no_file +/// - 1: display warning if the file is not found +/// - 0: don't complain if file doesn't exist +/// \retval 1 ok, file is compiled and executed +/// \retval 0 failure, compilation or execution error, warning is displayed + +idaman THREAD_SAFE bool ida_export exec_system_script( + const char *file, + bool complain_if_no_file=true); + + +/// Compile and calculate an expression. +/// \param res pointer to result. The result will be converted +/// to 32/64bit number. Use eval_expr() if you +/// need the result of another type. +/// \param where the current linear address in the addressing space of the +/// program being disassembled. it will be used to resolve +/// names of local variables, etc. +/// if not applicable, then should be #BADADDR +/// \param line a text line with IDC expression +/// \param[out] errbuf buffer for the error message +/// \retval true ok +/// \retval false error, see errbuf + +idaman bool ida_export eval_expr_long( + sval_t *res, + ea_t where, + const char *line, + qstring *errbuf=NULL); + +/// See eval_expr_long() + +inline bool idaapi eval_expr_long( + uval_t *res, + ea_t where, + const char *line, + qstring *errbuf=NULL) +{ + return eval_expr_long((sval_t *)res, where, line, errbuf); +} + + +/// Compile and calculate an expression. +/// \param rv pointer to the result +/// \param where the current linear address in the addressing space of the +/// program being disassembled. If will be used to resolve +/// names of local variables etc. +/// if not applicable, then should be #BADADDR. +/// \param line the expression to evaluate +/// \param[out] errbuf buffer for the error message +/// \retval true ok +/// \retval false error, see errbuf + +idaman bool ida_export eval_expr( + idc_value_t *rv, + ea_t where, + const char *line, + qstring *errbuf=NULL); + + +/// Same as eval_expr(), but will always use the IDC interpreter regardless of the +/// currently installed extlang. + +idaman bool ida_export eval_idc_expr( + idc_value_t *rv, + ea_t where, + const char *buf, + qstring *errbuf=NULL); + + +/// Compile a text file with IDC function(s). +/// \param file name of file to compile +/// if NULL, then "File not found" is returned. +/// \param[out] errbuf buffer for the error message +/// \param cpl_flags \ref CPL_ or 0 +/// \retval true ok +/// \retval false error, see errbuf + +/// \defgroup CPL_ Flags for compile_idc_file() +//@{ +#define CPL_DEL_MACROS 0x0001 ///< delete macros at the end of compilation +#define CPL_USE_LABELS 0x0002 ///< allow program labels in the script +#define CPL_ONLY_SAFE 0x0004 ///< allow calls of only thread-safe functions +//@} + +idaman THREAD_SAFE bool ida_export compile_idc_file( + const char *file, + qstring *errbuf=NULL, + int cpl_flags = CPL_DEL_MACROS|CPL_USE_LABELS); + + +/// Compile text with IDC function(s). +/// \param line line with IDC function(s) (can't be NULL!) +/// \param[out] errbuf buffer for the error message +/// \param resolver callback object to get values of undefined variables +/// This object will be called if IDC function contains +/// references to undefined variables. May be NULL. +/// \param only_safe_funcs if true, any calls to functions without #EXTFUN_SAFE flag +/// will lead to a compilation error. +/// \retval true ok +/// \retval false error, see errbuf + +struct idc_resolver_t +{ + virtual uval_t idaapi resolve_name(const char *name) = 0; +}; + +idaman THREAD_SAFE bool ida_export compile_idc_text( + const char *line, + qstring *errbuf=NULL, + idc_resolver_t *resolver=NULL, + bool only_safe_funcs=false); + + +/// Compile text with IDC statements. +/// \param func name of the function to create out of the snippet +/// \param text text to compile +/// \param[out] errbuf buffer for the error message +/// \param resolver callback object to get values of undefined variables +/// This object will be called if IDC function contains +/// references to undefined variables. May be NULL. +/// \param only_safe_funcs if true, any calls to functions without #EXTFUN_SAFE flag +/// will lead to a compilation error. +/// \retval true ok +/// \retval false error, see errbuf + +idaman bool ida_export compile_idc_snippet( + const char *func, + const char *text, + qstring *errbuf=NULL, + idc_resolver_t *resolver=NULL, + bool only_safe_funcs=false); + + +// Execution of IDC code can generate exceptions. Exception objects +// will have the following attributes: +// file - the source file name +// line - the line number that was executing when the exception occurred +// func - the function name +// pc - bytecode program counter +// For runtime errors, the following additional attributes exist: +// qerrno - runtime error code +// description - text description of the runtime error + +/// Execute an IDC function. +/// \param[out] result pointer to idc_value_t to hold the return value of the function. +/// If execution fails, this variable will contain +/// the exception information. +/// Can be NULL if return value is not required. +/// \param fname function name. User-defined functions, built-in functions, +/// and plugin-defined functions are accepted. +/// \param args array of parameters +/// \param argsnum number of parameters to pass to 'fname'. +/// This number should be equal to number of parameters +/// the function expects. +/// \param[out] errbuf buffer for the error message +/// \param resolver callback object to get values of undefined variables +/// This object will be called if IDC function contains +/// references to undefined variables. May be NULL. +/// \retval true ok +/// \retval false error, see errbuf + +idaman bool ida_export call_idc_func( + idc_value_t *result, + const char *fname, + const idc_value_t args[], + size_t argsnum, + qstring *errbuf=NULL, + idc_resolver_t *resolver=NULL); + + +/// Compile and execute IDC function(s) from file. +/// \param result ptr to idc_value_t to hold result of the function. +/// If execution fails, this variable will contain +/// the exception information. +/// You may pass NULL if you are not interested in the returned +/// value. +/// \param path text file containing text of IDC functions +/// \param func function name to execute +/// \param args array of parameters +/// \param argsnum number of parameters to pass to 'fname' +/// This number should be equal to number of parameters +/// the function expects. +/// \param[out] errbuf buffer for the error message +/// \retval true ok +/// \retval false error, see errbuf + +THREAD_SAFE inline bool exec_idc_script( + idc_value_t *result, + const char *path, + const char *func, + const idc_value_t args[], + size_t argsnum, + qstring *errbuf=NULL) +{ + if ( !compile_idc_file(path, errbuf) ) + return false; + return call_idc_func(result, func, args, argsnum, errbuf); +} + + +/// Compile and execute IDC statements or expressions. +/// \param result ptr to idc_value_t to hold result of the function. +/// If execution fails, this variable will contain +/// the exception information. +/// You may pass NULL if you are not interested in the returned +/// value. +/// \param line body of IDC the function +/// \param[out] errbuf buffer for the error message +/// \param resolver callback object to get values of undefined variables +/// This object will be called if IDC function contains +/// references to undefined variables. May be NULL. +/// \return success +/// \note see also eval_idc_expr() + + +idaman bool ida_export eval_idc_snippet( + idc_value_t *result, + const char *line, + qstring *errbuf=NULL, + idc_resolver_t *resolver=NULL); + + +//------------------------------------------------------------------------ +/// Setup lowcnd callbacks to read/write registers. +/// These callbacks will be used by the idc engine to read/write registers +/// while calculating low level breakpoint conditions for local debuggers. + +idaman void ida_export setup_lowcnd_regfuncs(idc_func_t *getreg, idc_func_t *setreg); + +//------------------------------------------------------------------------ +/// Extract type & data from the idc_value_t instance that +/// was passed to parse_config_value(). +/// +/// \param vtype pointer to storage that will hold the type (\ref IDPOPT_T) +/// \param vdata pointer to storage that contains the value (see \ref IDPOPT_T +/// for what type of data is pointed to.) +/// \param v the value holder +/// \return true in case of success, false if 'v' is of unexpected type +inline THREAD_SAFE bool get_idptype_and_data(int *vtype, const void **vdata, const idc_value_t &v) +{ + switch ( v.vtype ) + { + case VT_STR: *vtype = IDPOPT_STR, *vdata = v.c_str(); break; + case VT_LONG: *vtype = IDPOPT_NUM; *vdata = &v.num; break; + case VT_WILD: *vtype = IDPOPT_BIT; *vdata = &v.num; break; + case VT_INT64: *vtype = IDPOPT_I64; *vdata = &v.i64; break; + case VT_PVOID: *vtype = IDPOPT_CST; *vdata = v.pvoid; break; + default: return false; + } + return true; +} + +/// Create an idc execution exception object. +/// This helper function can be used to return an exception from C++ code to IDC. +/// In other words this function can be called from idc_func_t() callbacks. +/// Sample usage: if ( !ok ) return throw_idc_exception(r, "detailed error msg"); +/// \param r object to hold the exception object +/// \param desc exception description +/// \return eExecThrow + +idaman error_t ida_export throw_idc_exception(idc_value_t *r, const char *desc); + + +#endif /* _EXPR_H */ diff --git a/idasdk76/include/fixup.hpp b/idasdk76/include/fixup.hpp new file mode 100644 index 0000000..38fa593 --- /dev/null +++ b/idasdk76/include/fixup.hpp @@ -0,0 +1,572 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef FIXUP_HPP +#define FIXUP_HPP + +#include <nalt.hpp> +#include <segment.hpp> + +/*! \file fixup.hpp + + \brief Functions that deal with fixup information + + A loader should setup fixup information using set_fixup(). +*/ + +//-------------------------------------------------------------------------- +/// Fixup information structure + +typedef uint16 fixup_type_t; ///< see \ref fixup_type_t +/// \defgroup fixup_type_t Types of fixups +/// Fixup may be of standard or custom type. Standard types fall into +/// range 1..FIXUP_CUSTOM-1 and custom types fall into range +/// FIXUP_CUSTOM..MAX_UINT16. +/// \note Fixup type 0 is unused. +/// \name Fixup standard types +//@{ +#define FIXUP_OFF8 13 ///< 8-bit offset +#define FIXUP_OFF16 1 ///< 16-bit offset +#define FIXUP_SEG16 2 ///< 16-bit base--logical segment base (selector) +#define FIXUP_PTR16 3 ///< 32-bit long pointer (16-bit base:16-bit + ///< offset) +#define FIXUP_OFF32 4 ///< 32-bit offset +#define FIXUP_PTR32 5 ///< 48-bit pointer (16-bit base:32-bit offset) +#define FIXUP_HI8 6 ///< high 8 bits of 16bit offset +#define FIXUP_HI16 7 ///< high 16 bits of 32bit offset +#define FIXUP_LOW8 8 ///< low 8 bits of 16bit offset +#define FIXUP_LOW16 9 ///< low 16 bits of 32bit offset +#define V695_FIXUP_VHIGH 10 ///< obsolete +#define V695_FIXUP_VLOW 11 ///< obsolete +#define FIXUP_OFF64 12 ///< 64-bit offset +#define FIXUP_OFF8S 14 ///< 8-bit signed offset +#define FIXUP_OFF16S 15 ///< 16-bit signed offset +#define FIXUP_OFF32S 16 ///< 32-bit signed offset +//#define FIXUP_ 0xE +#define FIXUP_CUSTOM 0x8000 ///< start of the custom types range +//@} + +/// Is fixup processed by processor module? +inline THREAD_SAFE bool is_fixup_custom(fixup_type_t type) +{ + return (type & FIXUP_CUSTOM) != 0; +} + +/// \defgroup FIXUPF_ Fixup flags +/// Used by fixup_data_t +//@{ +/// fixup is relative to the linear address `base'. Otherwise fixup is +/// relative to the start of the segment with `sel' selector. +#define FIXUPF_REL 0x0001 +/// target is a location (otherwise - segment). +/// Use this bit if the target is a symbol rather than an offset from the +/// beginning of a segment. +#define FIXUPF_EXTDEF 0x0002 +/// fixup is ignored by IDA +/// - disallows the kernel to convert operands +/// - this fixup is not used during output +#define FIXUPF_UNUSED 0x0004 +/// fixup was not present in the input file +#define FIXUPF_CREATED 0x0008 +/// additional flags. The bits from this mask are not stored in the database +/// and can be used by the loader at its discretion. +#define FIXUPF_LOADER_MASK 0xF0000000 +//@} + +struct fixup_handler_t; +struct fixup_data_t +{ +protected: + fixup_type_t type; // fixup type + uint32 flags; // FIXUPF_... bits + uval_t base; // base for relative fixups + +public: + sel_t sel; ///< selector of the target segment. + ///< BADSEL means an absolute (zero based) target. + ///< \sa FIXUPF_REL + + ea_t off; ///< target offset + ///< \note The target is calculated as + ///< `get_base() + off`. + + adiff_t displacement; ///< displacement (offset from the target) + +public: + fixup_data_t() + : type(0), + flags(0), + base(0), + sel(BADSEL), + off(0), + displacement(0) {} + fixup_data_t(fixup_type_t type_, uint32 flags_ = 0) + : type(type_), + flags(flags_), + base(0), + sel(BADSEL), + off(0), + displacement(0) {} + + /// Fixup type \ref fixup_type_t + fixup_type_t get_type(void) const { return type; } + void set_type(fixup_type_t type_) { type = type_; } + void set_type_and_flags(fixup_type_t type_, uint32 flags_ = 0) + { + type = type_; + flags = flags_; + } + + bool is_custom(void) const; ///< \ref is_fixup_custom() + + /// Fixup flags \ref FIXUPF_ + uint32 get_flags() const { return flags; } + + bool is_extdef(void) const { return (flags & FIXUPF_EXTDEF) != 0; } + void set_extdef(void) { flags |= FIXUPF_EXTDEF; } + void clr_extdef(void) { flags &= ~FIXUPF_EXTDEF; } + + bool is_unused(void) const { return (flags & FIXUPF_UNUSED) != 0; } + void set_unused(void) { flags |= FIXUPF_UNUSED; } + void clr_unused(void) { flags &= ~FIXUPF_UNUSED; } + + /// Is fixup relative? + bool has_base(void) const { return (flags & FIXUPF_REL) != 0; } + + /// Is fixup artificial? + bool was_created(void) const { return (flags & FIXUPF_CREATED) != 0; } + + /// Get base of fixup. + /// \note The target is calculated as `get_base() + off`. + /// \sa FIXUPF_REL + ea_t get_base() const + { + return has_base() ? base : sel != BADSEL ? sel2ea(sel) : 0; + } + + /// Set base of fixup. + /// The target should be set before a call of this function. + void set_base(ea_t new_base) + { + ea_t target = get_base() + off; + flags |= FIXUPF_REL; + base = new_base; + off = target - base; + } + + void set_sel(const segment_t *seg) + { + sel = seg == NULL ? BADSEL : seg->sel; + } + + /// Set selector of fixup to the target. + /// The target should be set before a call of this function. + void set_target_sel() + { + ea_t target = get_base() + off; + set_sel(getseg(target)); + flags &= ~FIXUPF_REL; + base = 0; // just in case + off = target - get_base(); + } + + void set(ea_t source) const; ///< \ref set_fixup() + bool get(ea_t source); ///< \ref get_fixup() + + /// \ref get_fixup_handler() + const fixup_handler_t *get_handler() const; + + /// \ref get_fixup_desc() + const char *get_desc(qstring *buf, ea_t source) const; + + // TODO rewrite to the inline implementation which uses + // fixup_handler_t::size + int calc_size() const; ///< \ref calc_fixup_size() + uval_t get_value(ea_t ea) const; ///< \ref get_fixup_value() + bool patch_value(ea_t ea) const; ///< \ref patch_fixup_value() + +}; + +/// Get fixup information + +idaman bool ida_export get_fixup(fixup_data_t *fd, ea_t source); + + +/// Check that a fixup exists at the given address + +inline bool exists_fixup(ea_t source) +{ + return get_fixup(NULL, source); +} + + +/// Set fixup information. You should fill ::fixup_data_t and call this +/// function and the kernel will remember information in the database. +/// \param source the fixup source address, i.e. the address modified by +/// the fixup +/// \param fd fixup data + +idaman void ida_export set_fixup(ea_t source, const fixup_data_t &fd); + + +/// Delete fixup information + +idaman void ida_export del_fixup(ea_t source); + + +/// \name Enumerate addresses with fixup information: +//@{ +/// Get the first address with fixup information +/// +/// \return the first address with fixup information, or BADADDR +idaman ea_t ida_export get_first_fixup_ea(void); + +/// Find next address with fixup information +/// +/// \param ea current address +/// \return the next address with fixup information, or BADADDR +idaman ea_t ida_export get_next_fixup_ea(ea_t ea); + +/// Find previous address with fixup information +/// +/// \param ea current address +/// \return the previous address with fixup information, or BADADDR +idaman ea_t ida_export get_prev_fixup_ea(ea_t ea); +//@} + + +/// Get handler of standard or custom fixup + +idaman const fixup_handler_t * ida_export get_fixup_handler(fixup_type_t type); + + +/// Use fixup information for an address. +/// This function converts item_ea flags to offsets/segments. +/// For undefined bytes, you may set item_ea == fixup_ea. In this case this +/// function will create an item (byte, word, dword) there. +/// \param item_ea start address of item to modify +/// \param fixup_ea address of fixup record +/// \param n number of operand. may be 0, 1, 2, or OPND_ALL +/// \param is_macro is the instruction at 'item_ea' a macro? +/// if yes, then partial fixups (HIGH, LOW) won't be applied +/// \retval false no fixup at fixup_ea or it has #FIXUPF_UNUSED flag +/// \retval true ok, the fixup information was applied + +idaman bool ida_export apply_fixup(ea_t item_ea, ea_t fixup_ea, int n, bool is_macro); + + +/// Get the operand value. +/// This function get fixup bytes from data or an instruction at `ea' and +/// convert them to the operand value (maybe partially). +/// It is opposite in meaning to the `patch_fixup_value()`. +/// For example, FIXUP_HI8 read a byte at `ea' and shifts it left by 8 bits, +/// or AArch64's custom fixup BRANCH26 get low 26 bits of the insn at `ea' +/// and shifts it left by 2 bits. +/// This function is mainly used to get a relocation addend. +/// \param ea address to get fixup bytes from, the size of the fixup +/// bytes depends on the fixup type. +/// \sa fixup_handler_t::size +/// \param type fixup type +/// \retval operand value + +idaman uval_t ida_export get_fixup_value(ea_t ea, fixup_type_t type); + + +/// Patch the fixup bytes. +/// This function updates data or an instruction at `ea' to the fixup bytes. +/// For example, FIXUP_HI8 updates a byte at `ea' to the high byte of +/// `fd->off', or AArch64's custom fixup BRANCH26 updates low 26 bits of the +/// insn at `ea' to the value of `fd->off' shifted right by 2. +/// \param ea address where data are changed, the size of the changed data +/// depends on the fixup type. +/// \sa fixup_handler_t::size +/// \param fd fixup data +/// \retval false the fixup bytes do not fit (e.g. `fd->off' is greater +/// than 0xFFFFFFC for BRANCH26). The database is changed +/// even in this case. + +idaman bool ida_export patch_fixup_value(ea_t ea, const fixup_data_t &fd); + + +/// Get FIXUP description comment. + +idaman const char *ida_export get_fixup_desc( + qstring *buf, + ea_t source, + const fixup_data_t &fd); + + +/// Calculate size of fixup in bytes (the number of bytes the fixup patches) +/// \retval -1 means error + +idaman int ida_export calc_fixup_size(fixup_type_t type); + + +//-------------------------------------------------------------------------- +// inline implementation +inline bool fixup_data_t::is_custom(void) const +{ + return is_fixup_custom(type); +} +inline void fixup_data_t::set(ea_t source) const +{ + set_fixup(source, *this); +} + +inline bool fixup_data_t::get(ea_t source) +{ + return get_fixup(this, source); +} + +inline const char *fixup_data_t::get_desc(qstring *buf, ea_t source) const +{ + return get_fixup_desc(buf, source, *this); +} + +inline int fixup_data_t::calc_size() const +{ + return calc_fixup_size(type); +} + +inline uval_t fixup_data_t::get_value(ea_t ea) const +{ + return get_fixup_value(ea, type); +} + +inline bool fixup_data_t::patch_value(ea_t ea) const +{ + return patch_fixup_value(ea, *this); +} + +inline const fixup_handler_t *fixup_data_t::get_handler() const +{ + return get_fixup_handler(type); +} + + +/// \name Custom fixups +/// Processor modules and plugins may register custom fixup handlers. File +/// loaders should use find_custom_fixup() function to find the handler +/// created by the processor module. The custom fixup handlers will be +/// unregistered automatically before the database gets closed. +//@{ + +//-------------------------------------------------------------------------- +/// Implements the core behavior of a custom fixup +struct fixup_handler_t +{ + int32 cbsize; ///< size of this structure + const char *name; ///< Format name, must be unique + uint32 props; ///< \ref FHF_ +/// \defgroup FHF_ Fixup handler properties +/// Used by fixup_handler_t::props +//@{ +#define FHF_VERIFY 0x0001 ///< verify that the value fits into WIDTH + ///< bits. If this property is not set we + ///< just truncate the value. +#define FHF_CODE 0x0002 ///< verify that ITEM_EA in std_apply() points + ///< to an instruction. +#define FHF_FORCE_CODE 0x0004 ///< if ITEM_EA in std_apply() points to an + ///< unknown item, then convert it to code. + ///< this property is valid only with FHF_CODE. +#define FHF_ABS_OPVAL 0x0008 ///< create absolute refinfo in std_apply() + ///< because the operand also has the absolute + ///< value (usually for o_near operands) +#define FHF_SIGNED 0x0010 ///< the operand value is signed. + ///< create a refinfo with REFINFO_SIGNEDOP in + ///< std_apply() +//@} + /// Is the operand value signed? + bool is_signed() const { return (props & FHF_SIGNED) != 0; } + +/// \defgroup fh_options Tuning options +//@{ + /// The examples below show how these options work. + /// \sa std_patch_value() std_get_value() + uint8 size; ///< size in bytes + uint8 width; ///< number of significant bits before shifting + uint8 shift; ///< number of bits to shift right before patching. + ///< The following should be true: + ///< width - shift <= size * 8 + uint8 rsrv4; // reserved + + uint32 reftype; ///< reference info type and flags, + ///< std_apply() produces an offset of this type +//@} + + /// Apply a fixup: take it into account while analyzing the file. + /// Usually it consists of converting the operand into an offset expression. + /// \sa apply_fixup() + /// If this callback is not specified then std_apply() is used. + bool (idaapi *apply)( + const fixup_handler_t *fh, + ea_t item_ea, + ea_t fixup_ea, + int opnum, + bool is_macro, + const fixup_data_t &fd); + + /// Get the operand value. + /// This callback is called from get_fixup_value(). + /// \sa get_fixup_value() + /// If this callback is not specified then std_get_value() is used. + uval_t (idaapi *get_value)(const fixup_handler_t *fh, ea_t ea); + + /// Patch the fixup bytes. + /// This callback is called from patch_fixup_value() or after changing the + /// fixup (e.g. after it was moved from one location to another). + /// If this callback is not specified then std_patch_value() is used. + /// \sa patch_fixup_value() + /// \retval false the fixup bytes do not fit. The database is changed + /// even in this case. + bool (idaapi *patch_value)( + const fixup_handler_t *fh, + ea_t ea, + const fixup_data_t &fd); + +#ifndef SWIG + DECLARE_COMPARISONS(fixup_handler_t); +#endif +}; + + +/// \name std_apply() +/// This internal function takes \ref fh_options and \ref FHF_ to convert +/// the fixup to an offset. + +/// \name std_patch_value() +/// This internal function takes \ref fh_options and \ref FHF_ to determine +/// how to patch the bytes. +/// 1) it verifies that the fixup value fits to the fixup_handler_t::width +/// bits if the FHF_VERIFY property is specified, +/// 2) it discards bits that do not fit, +/// 3) it shifts the result right by fixup_handler_t::shift bits, +/// 4) it puts the result to the rightmost bits of fixup_handler_t::size +/// bytes at the given address. +/// For example, FIXUP_HI8 uses size = 1, and width = 16, and shift = 8, and +/// property FHF_VERIFY, or MIPS's custom fixup BRANCH26 uses size = 4, +/// and width = 28, and shift = 2. +/// In details: +/// a) size = 1, width = 16, shift = 8 +/// - the value to patch is masked with 0xFFFF (width=16) +/// - then it is shifted right by 8 bits (shift=8) +/// - then the result is patched to the 8bit data at the fixup address +/// e.g. +/// 0xXX the original data +/// 0x1234 the value +/// 0x0012 the shifted value +/// 0x12 the patched data +/// b) size = 4, width = 28, shift = 2 +/// - the value to patch is masked with 0xFFFFFFF (width=28) +/// - then it is shifted right by 2 bits (shift=2) +/// - then the result is patched in the low 26 bits of the 32bit +/// e.g. +/// 0x10000000 an instruction at the fixup address +/// 0x0000005C the value +/// 0x00000017 the shifted value +/// 0x10000017 the patched insn + +/// \name std_get_value() +/// This internal function takes \ref fh_options to determine how to get the +/// operand value. +/// It is opposite in meaning to the std_patch_value(). +/// 1) it gets the fixup_handler_t::size bytes at the given address, +/// 2) it shifts the result left by fixup_handler_t::shift bits, +/// 3) it returns the rightmost fixup_handler_t::width bits as a signed +/// value. +/// In details: +/// b) size = 4, width = 28, shift = 2 +/// - it gets 4 bytes from the fixup address (the branch insn) +/// - then it shifts this dword left by 2 bits (shift=2) +/// - then the result is masked with 0xFFFFFFF (width=28) +/// e.g. +/// 0x10000017 the insn +/// 0x4000005C the unshifted value +/// 0x0000005C the masked result + + +/// Register a new custom fixup. +/// This function must be called by a processor module or plugin, but not +/// by a file loader. File loaders should use find_custom_fixup() function +/// to find the handler created by the processor module. +/// \return id of the new custom fixup handler with FIXUP_CUSTOM bit set or +/// 0 (e.g. when the custom fixup handler with the same name was +/// already registered). + +idaman fixup_type_t ida_export register_custom_fixup( + const fixup_handler_t *cfh); + + +/// Unregister a new custom fixup format. Should be called by the processor +/// module before the database gets closed. + +idaman bool ida_export unregister_custom_fixup(fixup_type_t type); + + +/// Get id of a custom fixup handler. +/// \param name name of the custom fixup handler +/// \return id with FIXUP_CUSTOM bit set or 0 + +idaman fixup_type_t ida_export find_custom_fixup(const char *name); + +//@} + + +//-------------------------------------------------------------------------- +/// Collect fixup records for the specified range. +/// Partially overlapping records will be reported too. +/// \return success (false means no fixup info have been found) + +struct fixup_info_t +{ + ea_t ea; + fixup_data_t fd; +}; +DECLARE_TYPE_AS_MOVABLE(fixup_info_t); +typedef qvector<fixup_info_t> fixups_t; + +idaman bool ida_export get_fixups(fixups_t *out, ea_t ea, asize_t size); + + +/// Does the specified address range contain any fixup information? + +inline bool contains_fixups(ea_t ea, asize_t size) +{ + return get_fixups(NULL, ea, size); +} + + +/// Relocate the bytes with fixup information once more (generic function). +/// This function may be called from loader_t::move_segm() if it suits the goal. +/// If loader_t::move_segm is not defined then this function will be called +/// automatically when moving segments or rebasing the entire program. +/// Special parameter values (from = BADADDR, size = 0, to = delta) are used +/// when the function is called from rebase_program(delta). + +idaman void ida_export gen_fix_fixups(ea_t from, ea_t to, asize_t size); + + +/// Handle two fixups in a macro. +/// We often combine two instruction that load parts of a value into one +/// macro instruction. For example: +/// ARM: ADRP X0, #var@PAGE +/// ADD X0, X0, #var@PAGEOFF --> ADRL X0, var +/// MIPS: lui $v0, %hi(var) +/// addiu $v0, $v0, %lo(var) --> la $v0, var +/// When applying the fixups that fall inside such a macro, we should convert +/// them to one refinfo. This function does exactly that. +/// It should be called from the apply() callback of a custom fixup. +/// \return success ('false' means that RI was not changed) + +idaman bool ida_export handle_fixups_in_macro( + refinfo_t *ri, + ea_t ea, + fixup_type_t other, + uint32 macro_reft_and_flags); + + +#endif // FIXUP_HPP diff --git a/idasdk76/include/fpro.h b/idasdk76/include/fpro.h new file mode 100644 index 0000000..53865b2 --- /dev/null +++ b/idasdk76/include/fpro.h @@ -0,0 +1,223 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __FPRO_H +#define __FPRO_H + +#include <pro.h> +#include <stdio.h> + +/*! \file fpro.h + + \brief System independent counterparts of FILE* related functions from Clib + + You should not use C standard I/O functions in your modules. + The reason: Each module compiled with Borland + (and statically linked to Borland's library) will host a copy of + the FILE * information. + + So, if you open a file in the plugin and pass the handle to the + kernel, the kernel will not be able to use it. + + If you really need to use the standard functions, define USE_STANDARD_FILE_FUNCTIONS. + In this case do not mix them with q... functions. +*/ + +#if !defined(USE_STANDARD_FILE_FUNCTIONS) && !defined(__CODE_CHECKER__) +#undef stdin +#undef stdout +#undef stderr +#undef fgetc +#undef fputc +#define stdin dont_use_stdin ///< use gets() +#define stdout dont_use_stdout ///< use qprintf() +#define stderr dont_use_stderr ///< use qeprintf() +#define fopen dont_use_fopen ///< use qfopen() +#define fread dont_use_fread ///< use qfread() +#define fwrite dont_use_fwrite ///< use qfwrite() +#define ftell dont_use_ftell ///< use qftell() +#define fseek dont_use_fseek ///< use qfseek() +#define fclose dont_use_fclose ///< use qfclose() +#define fflush dont_use_fflush ///< use qflush() +#define fputc dont_use_fputc ///< use qfputc() +#define fgetc dont_use_fgetc ///< use qfgetc() +#define fgets dont_use_fgets ///< use qfgets() +#define fputs dont_use_fputs ///< use qfputs() +#define vfprintf dont_use_vfprintf ///< use qvfprintf() +#define vfscanf dont_use_vfscanf ///< use qvfscanf() +#define fprintf dont_use_fprintf ///< use qfprintf() +#define fscanf dont_use_fscanf ///< use qfscanf() +#endif + + +/// \name File I/O +/// The following functions work just like their counterparts from Clib, +/// only they are safer, system independent, and they set qerrno (see get_qerrno()). +//@{ +idaman THREAD_SAFE FILE *ida_export qfopen(const char *file, const char *mode); +idaman THREAD_SAFE ssize_t ida_export qfread(FILE *fp, void *buf, size_t n); +idaman THREAD_SAFE ssize_t ida_export qfwrite(FILE *fp, const void *buf, size_t n); +idaman THREAD_SAFE qoff64_t ida_export qftell(FILE *fp); +idaman THREAD_SAFE int ida_export qfseek(FILE *fp, qoff64_t offset, int whence); +idaman THREAD_SAFE int ida_export qfclose(FILE *fp); +idaman THREAD_SAFE int ida_export qflush(FILE *fp); +idaman THREAD_SAFE int ida_export qfputc(int chr, FILE *fp); +idaman THREAD_SAFE int ida_export qfgetc(FILE *fp); +idaman THREAD_SAFE char *ida_export qfgets(char *s, size_t len, FILE *fp); +idaman THREAD_SAFE int ida_export qfputs(const char *s, FILE *fp); +idaman FILE *ida_export qtmpfile(void); +idaman THREAD_SAFE int ida_export qunlink(const char *fname); +idaman THREAD_SAFE int ida_export qaccess(const char *fname, int mode); +idaman THREAD_SAFE char *ida_export qgets(char *line, size_t linesize); + +idaman THREAD_SAFE AS_PRINTF(2, 0) int ida_export qvfprintf(FILE *fp, const char *format, va_list va); +idaman THREAD_SAFE AS_PRINTF(1, 0) int ida_export qvprintf(const char *format, va_list va); +idaman THREAD_SAFE AS_PRINTF(1, 0) int ida_export qveprintf(const char *format, va_list va); +idaman THREAD_SAFE AS_SCANF(2, 0) int ida_export qvfscanf(FILE *fp, const char *format, va_list va); + +#ifdef __cplusplus +THREAD_SAFE AS_PRINTF(2, 3) inline int qfprintf(FILE *fp, const char *format, ...) +{ + va_list va; + va_start(va, format); + int code = qvfprintf(fp, format, va); + va_end(va); + return code; +} + +THREAD_SAFE AS_PRINTF(1, 2) inline int qprintf(const char *format, ...) +{ + va_list va; + va_start(va, format); + int code = qvprintf(format, va); + va_end(va); + return code; +} + +THREAD_SAFE AS_PRINTF(1, 2) inline int qeprintf(const char *format, ...) +{ + va_list va; + va_start(va, format); + int code = qveprintf(format, va); + va_end(va); + return code; +} + +THREAD_SAFE AS_SCANF(2, 3) inline int qfscanf(FILE *fp, const char *format, ...) +{ + va_list va; + va_start(va, format); + int code = qvfscanf(fp, format, va); + va_end(va); + return code; +} +#endif +//@} + + +/// Read line from file (the newline is removed from the output buffer) +/// \param buf output buffer +/// \param fp pointer to file +/// \return -1 or length of line + +idaman THREAD_SAFE ssize_t ida_export qgetline(qstring *buf, FILE *fp); + +/// Rename a file: 'newname' may exist, and will be deleted + +idaman THREAD_SAFE int ida_export qrename(const char *oldfname, const char *newfname); + +/// Move a file - more powerful version of qrename +/// \retval 0 success +/// \retval -1 system error +/// \retval else a combination of flags to be given for successful move +idaman THREAD_SAFE int ida_export qmove(const char *oldfname, const char *newfname, uint32 flags); +enum +{ + QMOVE_CROSS_FS = 0x01, // UNIX: allow moving between different filesystem + QMOVE_OVERWRITE = 0x02, // Overwrite existing file + QMOVE_OVR_RO = 0x04, // Overwrite file even if it is write-protected +}; + +/// Copy a file. +/// \param from source file name +/// \param to destination file name +/// \param overwrite overwrite output if it exists? +/// \param cb user callback. return false to abort the copy loop +/// \param ud user data passed back to cb +/// \param flags reserved (should be zero) +/// \retval -1 input file not found +/// \retval -2 output file not writable +/// \retval -3 output file already exists while overwrite is false +/// \retval -4 write failure +/// \retval -5 interrupted from the callback + +idaman THREAD_SAFE int ida_export qcopyfile( + const char *from, + const char *to, + bool overwrite = true, + bool (idaapi *cb)(uint64 pos, uint64 total, void *ud)=NULL, + void *ud = NULL, + int flags = 0); + + +/// Get temporary file name. +/// Returns absolute path, includes directory, and uses TEMP/TMP vars. + +idaman char *ida_export qtmpnam(char *buf, size_t bufsize); + + +/// File janitor: will close a file at destruction-time +typedef janitor_t<FILE*> file_janitor_t; +template <> inline file_janitor_t::~janitor_t() +{ + qfclose(resource); +} + +/// \name readbytes/writebytes +/// Add-ins for 2..32 byte read/writes. +/// \param fp pointer to file +/// \param res value read from file +/// \param size size of value in bytes (1..32) +/// \param mostfirst is MSB first? (0/1) +/// \retval 0 All these functions return 0 on success +//@{ +idaman THREAD_SAFE int ida_export freadbytes(FILE *fp,void *res,int size,int mostfirst); +idaman THREAD_SAFE int ida_export fwritebytes(FILE *fp,const void *l,int size,int mostfirst); + +#ifdef __cplusplus +#define DEF_FREADBYTES(read, write, type, size) \ + inline THREAD_SAFE int read(FILE *fp, type *res, bool mostfirst) \ + { return freadbytes(fp, res, size, mostfirst); } \ + inline THREAD_SAFE int write(FILE *fp, const type *res, bool mostfirst) \ + { return fwritebytes(fp, res, size, mostfirst); } +DEF_FREADBYTES(fread2bytes, fwrite2bytes, int16, 2) +DEF_FREADBYTES(fread2bytes, fwrite2bytes, uint16, 2) +DEF_FREADBYTES(fread4bytes, fwrite4bytes, int32, 4) +DEF_FREADBYTES(fread4bytes, fwrite4bytes, uint32, 4) +DEF_FREADBYTES(fread8bytes, fwrite8bytes, longlong, 8) +DEF_FREADBYTES(fread8bytes, fwrite8bytes, ulonglong, 8) +#else +#define fread2bytes(fp,v,mf) freadbytes(fp,v,2,mf) +#define fwrite2bytes(fp,v,mf) fwritebytes(fp,v,2,mf) +#define fread4bytes(fp,v,mf) freadbytes(fp,v,4,mf) +#define fwrite4bytes(fp,v,mf) fwritebytes(fp,v,4,mf) +#define fread8bytes(fp,v,mf) freadbytes(fp,v,8,mf) +#define fwrite8bytes(fp,v,mf) fwritebytes(fp,v,8,mf) +#endif +//@} + +#if !defined(feof) || !defined(ferror) +// If feof() and ferror() are not macros, we cannot use them +// Fortunately, for borland and vc they are macros, so there is no problem +// GCC defines them as functions: I have no idea whether they will work or not +// Anyway we remove the error directive from this file +// so the plugins can be compiled with gcc +//#error feof or ferror are not macros! +#endif + + +#endif diff --git a/idasdk76/include/frame.hpp b/idasdk76/include/frame.hpp new file mode 100644 index 0000000..c21e74b --- /dev/null +++ b/idasdk76/include/frame.hpp @@ -0,0 +1,609 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _FRAME_HPP +#define _FRAME_HPP +#include <idp.hpp> + +/*! \file frame.hpp + + \brief Routines to manipulate function stack frames, stack + variables, register variables and local labels. + + The frame is represented as a structure: + <pre> + +------------------------------------------------+ + | function arguments | + +------------------------------------------------+ + | return address (isn't stored in func_t) | + +------------------------------------------------+ + | saved registers (SI, DI, etc - func_t::frregs) | + +------------------------------------------------+ <- typical BP + | | | + | | | func_t::fpd + | | | + | | <- real BP + | local variables (func_t::frsize) | + | | + | | + +------------------------------------------------+ <- SP + </pre> + + To access the structure of a function frame, use: + - get_struc() (use func_t::frame as structure ID) + - get_frame(const func_t *pfn) + - get_frame(ea_t ea) +*/ + +class struc_t; +class member_t; +class op_t; + +// We need to trace value of SP register. For this we introduce +// an array of SP register change points. + +// SP register change point +// +// NOTE: To manipulate/modify stack points, please use the specialized +// functions provided below in this file (stack pointer change points) + +struct stkpnt_t +{ + ea_t ea; // linear address + sval_t spd; // here we keep a cumulative difference from [BP-frsize] + + stkpnt_t &operator=(const stkpnt_t &) = default; + DECLARE_COMPARISONS(stkpnt_t) + { + if ( ea < r.ea ) + return -1; + if ( ea > r.ea ) + return 1; + return 0; + } +}; +DECLARE_TYPE_AS_MOVABLE(stkpnt_t); +// we declare a struct to be able to forward declare it in other files +struct stkpnts_t : public qvector<stkpnt_t> +{ + DECLARE_COMPARISONS(stkpnts_t) { return compare_containers(*this, r); } +}; + +//-------------------------------------------------------------------------- +// F R A M E M A N I P U L A T I O N +//-------------------------------------------------------------------------- + +/// Add function frame. +/// \param pfn pointer to function structure +/// \param frsize size of function local variables +/// \param frregs size of saved registers +/// \param argsize size of function arguments range which will be purged upon return. +/// this parameter is used for __stdcall and __pascal calling conventions. +/// for other calling conventions please pass 0. +/// \retval 1 ok +/// \retval 0 failed (no function, frame already exists) + +idaman bool ida_export add_frame( + func_t *pfn, + sval_t frsize, + ushort frregs, + asize_t argsize); + + +/// Delete a function frame. +/// \param pfn pointer to function structure +/// \return success + +idaman bool ida_export del_frame(func_t *pfn); + + +/// Set size of function frame. +/// Note: The returned size may not include all stack arguments. It does so +/// only for __stdcall and __fastcall calling conventions. To get the entire +/// frame size for all cases use get_struc_size(get_frame(pfn)). +/// \param pfn pointer to function structure +/// \param frsize size of function local variables +/// \param frregs size of saved registers +/// \param argsize size of function arguments that will be purged +/// from the stack upon return +/// \return success + +idaman bool ida_export set_frame_size( + func_t *pfn, + asize_t frsize, + ushort frregs, + asize_t argsize); + + +/// Get full size of a function frame. +/// This function takes into account size of local variables + size of +/// saved registers + size of return address + number of purged bytes. +/// The purged bytes correspond to the arguments of the functions with +/// __stdcall and __fastcall calling conventions. +/// \param pfn pointer to function structure, may be NULL +/// \return size of frame in bytes or zero + +idaman asize_t ida_export get_frame_size(const func_t *pfn); + + +/// Get size of function return address. +/// \param pfn pointer to function structure, can't be NULL + +idaman int ida_export get_frame_retsize(const func_t *pfn); + +/// Parts of a frame +enum frame_part_t +{ + FPC_ARGS, + FPC_RETADDR, + FPC_SAVREGS, + FPC_LVARS, +}; + +/// Get offsets of the frame part in the frame. +/// \param range pointer to the output buffer with the frame part +/// start/end(exclusive) offsets, can't be NULL +/// \param pfn pointer to function structure, can't be NULL +/// \param part frame part + +idaman void ida_export get_frame_part(range_t *range, const func_t *pfn, frame_part_t part); + +/// Get starting address of arguments section + +inline ea_t frame_off_args(const func_t *pfn) +{ + range_t range; + get_frame_part(&range, pfn, FPC_ARGS); + return range.start_ea; +} + +/// Get starting address of return address section + +inline ea_t frame_off_retaddr(const func_t *pfn) +{ + range_t range; + get_frame_part(&range, pfn, FPC_RETADDR); + return range.start_ea; +} + +/// Get starting address of saved registers section + +inline ea_t frame_off_savregs(const func_t *pfn) +{ + range_t range; + get_frame_part(&range, pfn, FPC_SAVREGS); + return range.start_ea; +} + +/// Get start address of local variables section + +inline ea_t frame_off_lvars(const func_t *pfn) +{ + range_t range; + get_frame_part(&range, pfn, FPC_LVARS); + return range.start_ea; +} + +/// Does the given offset lie within the arguments section? + +inline bool processor_t::is_funcarg_off(const func_t *pfn, uval_t frameoff) const +{ + range_t args; + get_frame_part(&args, pfn, FPC_ARGS); + return stkup() + ? frameoff < args.end_ea + : frameoff >= args.start_ea; +} + +/// Does the given offset lie within the local variables section? + +inline sval_t processor_t::lvar_off(const func_t *pfn, uval_t frameoff) const +{ + range_t lvars; + get_frame_part(&lvars, pfn, FPC_LVARS); + return stkup() + ? frameoff - lvars.start_ea + : lvars.end_ea - frameoff; +} + +/// Get pointer to function frame. +/// \param pfn pointer to function structure + +idaman struc_t *ida_export get_frame(const func_t *pfn); + +/// Get pointer to function frame. +/// \param ea any address in the function + +inline struc_t *get_frame(ea_t ea) { return get_frame(get_func(ea)); } + + +/// Convert struct offsets into fp-relative offsets. +/// This function converts the offsets inside the struc_t object +/// into the frame pointer offsets (for example, EBP-relative). + +inline sval_t soff_to_fpoff(func_t *pfn, uval_t soff) +{ + return soff - pfn->frsize + pfn->fpd; +} + + +/// Update frame pointer delta. +/// \param pfn pointer to function structure +/// \param fpd new fpd value. +/// cannot be bigger than the local variable range size. +/// \return success + +idaman bool ida_export update_fpd(func_t *pfn, asize_t fpd); + + +/// Set the number of purged bytes for a function or data item (funcptr). +/// This function will update the database and plan to reanalyze items +/// referencing the specified address. It works only for processors +/// with #PR_PURGING bit in 16 and 32 bit modes. +/// \param ea address of the function of item +/// \param nbytes number of purged bytes +/// \param override_old_value may overwrite old information about purged bytes +/// \return success + +idaman bool ida_export set_purged(ea_t ea, int nbytes, bool override_old_value); + + +/// Get function by its frame id. +/// \warning this function works only with databases created by IDA > 5.6 +/// \param frame_id id of the function frame +/// \return start address of the function or #BADADDR + +idaman ea_t ida_export get_func_by_frame(tid_t frame_id); + + +//-------------------------------------------------------------------------- +// S T A C K V A R I A B L E S +//-------------------------------------------------------------------------- + +/// Get pointer to stack variable. +/// \param actval actual value used to fetch stack variable +/// this pointer may point to 'v' +/// \param insn the instruction +/// \param x reference to instruction operand +/// \param v immediate value in the operand (usually x.addr) +/// \return NULL or ptr to stack variable + +idaman member_t *ida_export get_stkvar( + sval_t *actval, + const insn_t &insn, + const op_t &x, + sval_t v); + +/// Automatically add stack variable if doesn't exist. +/// Processor modules should use insn_t::create_stkvar(). +/// \param insn the instruction +/// \param x reference to instruction operand +/// \param v immediate value in the operand (usually x.addr) +/// \param flags \ref STKVAR_1 +/// \return success + +idaman bool ida_export add_stkvar(const insn_t &insn, const op_t &x, sval_t v, int flags); + +/// \defgroup STKVAR_1 Add stkvar flags +/// Passed as 'flags' parameter to add_stkvar() +//@{ +#define STKVAR_VALID_SIZE 0x0001 ///< x.dtyp contains correct variable type + ///< (for insns like 'lea' this bit must be off) + ///< in general, dr_O references do not allow + ///< to determine the variable size +//@} + +/// Define/redefine a stack variable. +/// \param pfn pointer to function +/// \param name variable name, NULL means autogenerate a name +/// \param off offset of the stack variable in the frame. +/// negative values denote local variables, positive - function arguments. +/// \param flags variable type flags (byte_flag() for a byte variable, for example) +/// \param ti additional type information (like offsets, structs, etc) +/// \param nbytes number of bytes occupied by the variable +/// \return success + +idaman bool ida_export define_stkvar( + func_t *pfn, + const char *name, + sval_t off, + flags_t flags, + const opinfo_t *ti, + asize_t nbytes); + + +/// Build automatic stack variable name. +/// \param buf pointer to buffer +/// \param pfn pointer to function (can't be NULL!) +/// \param v value of variable offset +/// \return length of stack variable name or -1 + +idaman ssize_t ida_export build_stkvar_name( + qstring *buf, + const func_t *pfn, + sval_t v); + + +/// Calculate offset of stack variable in the frame structure. +/// \param pfn pointer to function (can't be NULL!) +/// \param insn the instruction +/// \param n number of operand: (0..#UA_MAXOP-1) +/// -1 if error, return #BADADDR +/// \return #BADADDR if some error (issue a warning if stack frame is bad) + +idaman ea_t ida_export calc_stkvar_struc_offset( + func_t *pfn, + const insn_t &insn, + int n); + + +/// Find and delete wrong frame info. +/// Namely, we delete: +/// - unreferenced stack variable definitions +/// - references to dead stack variables (i.e. operands displayed in red) +/// these operands will be untyped and most likely displayed in hex. +/// We also plan to reanalyze instruction with the stack frame references +/// \param pfn pointer to the function +/// \param should_reanalyze callback to determine which instructions to reanalyze +/// \return number of deleted definitions + +idaman int ida_export delete_wrong_frame_info( + func_t *pfn, + bool idaapi should_reanalyze(const insn_t &insn)); + + +//-------------------------------------------------------------------------- +// R E G I S T E R V A R I A B L E S +//-------------------------------------------------------------------------- +/// \defgroup regvar Register variables +/// Definition of ::regvar_t and related functions +//@{ + +idaman void ida_export free_regvar(struct regvar_t *v); + +/// A register variable allows the user to rename a general processor register +/// to a meaningful name. +/// IDA doesn't check whether the target assembler supports the register renaming. +/// All register definitions will appear at the beginning of the function. +struct regvar_t : public range_t +{ + char *canon = nullptr; ///< canonical register name (case-insensitive) + char *user = nullptr; ///< user-defined register name + char *cmt = nullptr; ///< comment to appear near definition + + regvar_t() {} + regvar_t(const regvar_t &r) : range_t(r) + { + canon = ::qstrdup(r.canon); + user = ::qstrdup(r.user); + cmt = ::qstrdup(r.cmt); + } + ~regvar_t() { free_regvar(this); } + regvar_t &operator=(const regvar_t &r) + { + if ( this != &r ) + { + free_regvar(this); + new (this) regvar_t(r); + } + return *this; + } + void swap(regvar_t &r) + { + uchar buf[sizeof(*this)]; + memcpy(buf, &r, sizeof(buf)); + memcpy(&r, this, sizeof(buf)); + memcpy(this, buf, sizeof(buf)); + } +#ifndef SWIG + DECLARE_COMPARISONS(regvar_t); +#endif +}; +DECLARE_TYPE_AS_MOVABLE(regvar_t); + +/// Define a register variable. +/// \param pfn function in which the definition will be created +/// \param ea1,ea2 range of addresses within the function where the definition +/// will be used +/// \param canon name of a general register +/// \param user user-defined name for the register +/// \param cmt comment for the definition +/// \return \ref REGVAR_ERROR_ + +idaman int ida_export add_regvar( + func_t *pfn, + ea_t ea1, + ea_t ea2, + const char *canon, + const char *user, + const char *cmt); +/// \defgroup REGVAR_ERROR_ Register variable error codes +/// Return values for functions in described in \ref regvar +//@{ +#define REGVAR_ERROR_OK 0 ///< all ok +#define REGVAR_ERROR_ARG (-1) ///< function arguments are bad +#define REGVAR_ERROR_RANGE (-2) ///< the definition range is bad +#define REGVAR_ERROR_NAME (-3) ///< the provided name(s) can't be accepted +//@} + +/// Find a register variable definition (powerful version). +/// One of 'canon' and 'user' should be NULL. +/// If both 'canon' and 'user' are NULL it returns the first regvar +/// definition in the range. +/// \param pfn function in question +/// \param ea1,ea2 range of addresses to search. +/// ea1==BADADDR means the entire function +/// \param canon name of a general register +/// \param user user-defined name for the register +/// \return NULL-not found, otherwise ptr to regvar_t + +idaman regvar_t *ida_export find_regvar(func_t *pfn, ea_t ea1, ea_t ea2, const char *canon, const char *user); + + +/// Find a register variable definition. +/// \param pfn function in question +/// \param ea current address +/// \param canon name of a general register +/// \return NULL-not found, otherwise ptr to regvar_t + +inline regvar_t *find_regvar(func_t *pfn, ea_t ea, const char *canon) +{ + return find_regvar(pfn, ea, ea+1, canon, NULL); +} + + +/// Is there a register variable definition? +/// \param pfn function in question +/// \param ea current address + +inline bool has_regvar(func_t *pfn, ea_t ea) +{ + return find_regvar(pfn, ea, ea+1, NULL, NULL) != NULL; +} + + +/// Rename a register variable. +/// \param pfn function in question +/// \param v variable to rename +/// \param user new user-defined name for the register +/// \return \ref REGVAR_ERROR_ + +idaman int ida_export rename_regvar(func_t *pfn, regvar_t *v, const char *user); + + +/// Set comment for a register variable. +/// \param pfn function in question +/// \param v variable to rename +/// \param cmt new comment +/// \return \ref REGVAR_ERROR_ + +idaman int ida_export set_regvar_cmt(func_t *pfn, regvar_t *v, const char *cmt); + + +/// Delete a register variable definition. +/// \param pfn function in question +/// \param ea1,ea2 range of addresses within the function where the definition holds +/// \param canon name of a general register +/// \return \ref REGVAR_ERROR_ + +idaman int ida_export del_regvar(func_t *pfn, ea_t ea1, ea_t ea2, const char *canon); + +//@} regvar + +//-------------------------------------------------------------------------- +// S P R E G I S T E R C H A N G E P O I N T S +//-------------------------------------------------------------------------- + +/// Add automatic SP register change point. +/// \param pfn pointer to function. may be NULL. +/// \param ea linear address where SP changes. +/// usually this is the end of the instruction which +/// modifies the stack pointer (\cmd{ea}+\cmd{size}) +/// \param delta difference between old and new values of SP +/// \return success + +idaman bool ida_export add_auto_stkpnt(func_t *pfn, ea_t ea, sval_t delta); + + +/// Add user-defined SP register change point. +/// \param ea linear address where SP changes +/// \param delta difference between old and new values of SP +/// \return success + +idaman bool ida_export add_user_stkpnt(ea_t ea, sval_t delta); + + +/// Delete SP register change point. +/// \param pfn pointer to function. may be NULL. +/// \param ea linear address +/// \return success + +idaman bool ida_export del_stkpnt(func_t *pfn, ea_t ea); + + +/// Get difference between the initial and current values of ESP. +/// \param pfn pointer to function. may be NULL. +/// \param ea linear address of an instruction +/// \return 0 or the difference, usually a negative number. +/// returns the sp-diff before executing the instruction. + +idaman sval_t ida_export get_spd(func_t *pfn, ea_t ea); + + +/// Get effective difference between the initial and current values of ESP. +/// This function returns the sp-diff used by the instruction. +/// The difference between get_spd() and get_effective_spd() is present only +/// for instructions like "pop [esp+N]": they modify sp and use the modified value. +/// \param pfn pointer to function. may be NULL. +/// \param ea linear address +/// \return 0 or the difference, usually a negative number + +idaman sval_t ida_export get_effective_spd(func_t *pfn, ea_t ea); + + +/// Get modification of SP made at the specified location +/// \param pfn pointer to function. may be NULL. +/// \param ea linear address +/// \return 0 if the specified location doesn't contain a SP change point. +/// otherwise return delta of SP modification. + +idaman sval_t ida_export get_sp_delta(func_t *pfn, ea_t ea); + + +/// Recalculate SP delta for an instruction that stops execution. +/// The next instruction is not reached from the current instruction. +/// We need to recalculate SP for the next instruction. +/// +/// This function will create a new automatic SP register change +/// point if necessary. It should be called from the emulator (emu.cpp) +/// when auto_state == ::AU_USED if the current instruction doesn't pass +/// the execution flow to the next instruction. +/// \param cur_ea linear address of the current instruction +/// \retval 1 new stkpnt is added +/// \retval 0 nothing is changed + +idaman bool ida_export recalc_spd(ea_t cur_ea); + + +/// An xref to an argument or variable located in a function's stack frame +struct xreflist_entry_t +{ + ea_t ea; ///< Location of the insn referencing the stack frame member + uchar opnum; ///< Number of the operand of that instruction + uchar type; ///< The type of xref (::cref_t & ::dref_t) + + DECLARE_COMPARISONS(xreflist_entry_t) + { + int code = ::compare(ea, r.ea); + if ( code == 0 ) + { + code = ::compare(type, r.type); + if ( code == 0 ) + code = ::compare(opnum, r.opnum); + } + return code; + } +}; +DECLARE_TYPE_AS_MOVABLE(xreflist_entry_t); +typedef qvector<xreflist_entry_t> xreflist_t; ///< vector of xrefs to variables in a function's stack frame + +/// Fill 'out' with a list of all the xrefs made from function 'pfn', to +/// the argument or variable 'mptr' in 'pfn's stack frame. +/// \param out the list of xrefs to fill. +/// \param pfn the function to scan. +/// \param mptr the argument/variable in pfn's stack frame. + +idaman void ida_export build_stkvar_xrefs(xreflist_t *out, func_t *pfn, const member_t *mptr); + + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED ea_t ida_export get_min_spd_ea(func_t *pfn); +idaman DEPRECATED int ida_export delete_unreferenced_stkvars(func_t *pfn); +idaman DEPRECATED int ida_export delete_wrong_stkvar_ops(func_t *pfn); +#endif + +#endif // _FRAME_HPP diff --git a/idasdk76/include/funcs.hpp b/idasdk76/include/funcs.hpp new file mode 100644 index 0000000..d3b9618 --- /dev/null +++ b/idasdk76/include/funcs.hpp @@ -0,0 +1,984 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef FUNCS_HPP +#define FUNCS_HPP +#include <range.hpp> +#include <bytes.hpp> + +/*! \file funcs.hpp + + \brief Routines for working with functions within the disassembled program. + + This file also contains routines for working with library signatures + (e.g. FLIRT). + + Each function consists of function chunks. At least one function chunk + must be present in the function definition - the function entry chunk. + Other chunks are called function tails. There may be several of them + for a function. + + A function tail is a continuous range of addresses. + It can be used in the definition of one or more functions. + One function using the tail is singled out and called the tail owner. + This function is considered as 'possessing' the tail. + get_func() on a tail address will return the function possessing the tail. + You can enumerate the functions using the tail by using ::func_parent_iterator_t. + + Each function chunk in the disassembly is represented as an "range" (a range + of addresses, see range.hpp for details) with characteristics. + + A function entry must start with an instruction (code) byte. +*/ + +struct stkpnt_t; // #include <frame.hpp> +struct regvar_t; // #include <frame.hpp> +struct llabel_t; // #include <frame.hpp> +class insn_t; // #include <ua.hpp> + +idaman void ida_export free_regarg(struct regarg_t *v); + +/// Register argument description. +/// regargs are destroyed when the full function type is determined. +struct regarg_t +{ + int reg = 0; + type_t *type = nullptr; + char *name = nullptr; + + regarg_t() {} + regarg_t(const regarg_t &r) : reg(r.reg) + { + type = (type_t *)::qstrdup((char *)r.type); + name = ::qstrdup(r.name); + } + ~regarg_t() { free_regarg(this); } + regarg_t &operator=(const regarg_t &r) + { + if ( this != &r ) + { + free_regarg(this); + new (this) regarg_t(r); + } + return *this; + } + void swap(regarg_t &r) + { + std::swap(reg, r.reg); + std::swap(type, r.type); + std::swap(name, r.name); + } +#ifndef SWIG + DECLARE_COMPARISONS(regarg_t); +#endif + +}; +DECLARE_TYPE_AS_MOVABLE(regarg_t); + +//------------------------------------------------------------------------ +/// A function is a set of continuous ranges of addresses with characteristics +class func_t : public range_t +{ +public: + uint64 flags; ///< \ref FUNC_ +/// \defgroup FUNC_ Function flags +/// Used by func_t::flags +//@{ +#define FUNC_NORET 0x00000001 ///< Function doesn't return +#define FUNC_FAR 0x00000002 ///< Far function +#define FUNC_LIB 0x00000004 ///< Library function + +#define FUNC_STATICDEF 0x00000008 ///< Static function + +#define FUNC_FRAME 0x00000010 ///< Function uses frame pointer (BP) +#define FUNC_USERFAR 0x00000020 ///< User has specified far-ness + ///< of the function +#define FUNC_HIDDEN 0x00000040 ///< A hidden function chunk +#define FUNC_THUNK 0x00000080 ///< Thunk (jump) function +#define FUNC_BOTTOMBP 0x00000100 ///< BP points to the bottom of the stack frame +#define FUNC_NORET_PENDING 0x00200 ///< Function 'non-return' analysis must be performed. + ///< This flag is verified upon func_does_return() +#define FUNC_SP_READY 0x00000400 ///< SP-analysis has been performed. + ///< If this flag is on, the stack + ///< change points should not be not + ///< modified anymore. Currently this + ///< analysis is performed only for PC +#define FUNC_FUZZY_SP 0x00000800 ///< Function changes SP in untraceable way, + ///< for example: and esp, 0FFFFFFF0h +#define FUNC_PROLOG_OK 0x00001000 ///< Prolog analysis has be performed + ///< by last SP-analysis +#define FUNC_PURGED_OK 0x00004000 ///< 'argsize' field has been validated. + ///< If this bit is clear and 'argsize' + ///< is 0, then we do not known the real + ///< number of bytes removed from + ///< the stack. This bit is handled + ///< by the processor module. +#define FUNC_TAIL 0x00008000 ///< This is a function tail. + ///< Other bits must be clear + ///< (except #FUNC_HIDDEN). +#define FUNC_LUMINA 0x00010000 ///< Function info is provided by Lumina. + +#define FUNC_RESERVED 0x8000000000000000LL ///< Reserved (for internal usage) +//@} + + /// Is a far function? + bool is_far(void) const { return (flags & FUNC_FAR) != 0; } + /// Does function return? + bool does_return(void) const { return (flags & FUNC_NORET) == 0; } + /// Has SP-analysis been performed? + bool analyzed_sp(void) const { return (flags & FUNC_SP_READY) != 0; } + /// Needs prolog analysis? + bool need_prolog_analysis(void) const { return (flags & FUNC_PROLOG_OK) == 0; } +#ifndef SWIG + union + { + /// attributes of a function entry chunk + struct + { +#endif // SWIG + // + // Stack frame of the function. It is represented as a structure: + // + // +------------------------------------------------+ + // | function arguments | + // +------------------------------------------------+ + // | return address (isn't stored in func_t) | + // +------------------------------------------------+ + // | saved registers (SI, DI, etc - func_t::frregs) | + // +------------------------------------------------+ <- typical BP + // | | | + // | | | func_t::fpd + // | | | + // | | <- real BP + // | local variables (func_t::frsize) | + // | | + // | | + // +------------------------------------------------+ <- SP + // + uval_t frame; ///< netnode id of frame structure - see frame.hpp + asize_t frsize; ///< size of local variables part of frame in bytes. + ///< If #FUNC_FRAME is set and #fpd==0, the frame pointer + ///< (EBP) is assumed to point to the top of the local + ///< variables range. + ushort frregs; ///< size of saved registers in frame. This range is + ///< immediately above the local variables range. + asize_t argsize; ///< number of bytes purged from the stack + ///< upon returning + asize_t fpd; ///< frame pointer delta. (usually 0, i.e. realBP==typicalBP) + ///< use update_fpd() to modify it. + + bgcolor_t color; ///< user defined function color + + // the following fields should not be accessed directly: + + uint32 pntqty; ///< number of SP change points + stkpnt_t *points; ///< array of SP change points. + ///< use ...stkpnt...() functions to access this array. + + int regvarqty; ///< number of register variables (-1-not read in yet) + ///< use find_regvar() to read register variables + regvar_t *regvars; ///< array of register variables. + ///< this array is sorted by: start_ea. + ///< use ...regvar...() functions to access this array. + + int llabelqty; ///< number of local labels + llabel_t *llabels; ///< local labels. + ///< this array shouldn't be accessed directly; name.hpp + ///< functions should be used instead. + + int regargqty; ///< number of register arguments. + ///< During analysis IDA tries to guess the register + ///< arguments. It stores store the guessing outcome + ///< in this field. As soon as it determines the final + ///< function prototype, regargqty is set to zero. + regarg_t *regargs; ///< unsorted array of register arguments. + ///< use ...regarg...() functions to access this array. + ///< regargs are destroyed when the full function + ///< type is determined. + + int tailqty; ///< number of function tails + range_t *tails; ///< array of tails, sorted by ea. + ///< use func_tail_iterator_t to access function tails. +#ifndef SWIG + }; + /// attributes of a function tail chunk + struct + { +#endif // SWIG + ea_t owner; ///< the address of the main function possessing this tail + int refqty; ///< number of referers + ea_t *referers; ///< array of referers (function start addresses). + ///< use func_parent_iterator_t to access the referers. +#ifndef SWIG + }; + }; +#endif // SWIG + + func_t(ea_t start=0, ea_t end=0, flags_t f=0) + : range_t(start, end), flags(f|FUNC_NORET_PENDING), frame(BADNODE), + frsize(0), frregs(0), argsize(0), fpd(0), color(DEFCOLOR), + pntqty(0), points(nullptr), + regvarqty(0), regvars(nullptr), + llabelqty(0), llabels(nullptr), + regargqty(0), regargs(nullptr), + tailqty(0), tails(nullptr) + { + } +#ifndef SWIG + DECLARE_COMPARISONS(func_t); +#endif +}; +DECLARE_TYPE_AS_MOVABLE(func_t); + +/// Does function describe a function entry chunk? +inline bool is_func_entry(const func_t *pfn) { return pfn != nullptr && (pfn->flags & FUNC_TAIL) == 0; } +/// Does function describe a function tail chunk? +inline bool is_func_tail(const func_t *pfn) { return pfn != nullptr && (pfn->flags & FUNC_TAIL) != 0; } + + +/// Lock function pointer +/// Locked pointers are guaranteed to remain valid until they are unlocked. +/// Ranges with locked pointers cannot be deleted or moved. + +idaman void ida_export lock_func_range(const func_t *pfn, bool lock); + +/// Helper class to lock a function pointer so it stays valid +class lock_func +{ + const func_t *pfn; +public: + lock_func(const func_t *_pfn) : pfn(_pfn) + { + lock_func_range(pfn, true); + } + ~lock_func(void) + { + lock_func_range(pfn, false); + } +}; + +/// Is the function pointer locked? + +idaman bool ida_export is_func_locked(const func_t *pfn); + +//-------------------------------------------------------------------- +// F U N C T I O N S +//-------------------------------------------------------------------- +/// Get pointer to function structure by address. +/// \param ea any address in a function +/// \return ptr to a function or nullptr. +/// This function returns a function entry chunk. + +idaman func_t *ida_export get_func(ea_t ea); + + +/// Get the containing tail chunk of 'ea'. +/// \retval -1 means 'does not contain ea' +/// \retval 0 means the 'pfn' itself contains ea +/// \retval >0 the number of the containing function tail chunk + +idaman int ida_export get_func_chunknum(func_t *pfn, ea_t ea); + +/// Does the given function contain the given address? + +inline bool func_contains(func_t *pfn, ea_t ea) +{ + return get_func_chunknum(pfn, ea) >= 0; +} + +/// Do two addresses belong to the same function? +inline bool is_same_func(ea_t ea1, ea_t ea2) +{ + func_t *pfn = get_func(ea1); + return pfn != nullptr && func_contains(pfn, ea2); +} + +/// Get pointer to function structure by number. +/// \param n number of function, is in range 0..get_func_qty()-1 +/// \return ptr to a function or nullptr. +/// This function returns a function entry chunk. + +idaman func_t *ida_export getn_func(size_t n); + + +/// Get total number of functions in the program + +idaman size_t ida_export get_func_qty(void); + + +/// Get ordinal number of a function. +/// \param ea any address in the function +/// \return number of function (0..get_func_qty()-1). +/// -1 means 'no function at the specified address'. + +idaman int ida_export get_func_num(ea_t ea); + + +/// Get pointer to the previous function. +/// \param ea any address in the program +/// \return ptr to function or nullptr if previous function doesn't exist + +idaman func_t *ida_export get_prev_func(ea_t ea); + + +/// Get pointer to the next function. +/// \param ea any address in the program +/// \return ptr to function or nullptr if next function doesn't exist + +idaman func_t *ida_export get_next_func(ea_t ea); + + +/// Get function ranges. +/// \param ranges buffer to receive the range info +/// \param pfn ptr to function structure +/// \return end address of the last function range (BADADDR-error) + +idaman ea_t ida_export get_func_ranges(rangeset_t *ranges, func_t *pfn); + + +/// Get function comment. +/// \param buf buffer for the comment +/// \param pfn ptr to function structure +/// \param repeatable get repeatable comment? +/// \return size of comment or -1 +/// In fact this function works with function chunks too. + +idaman ssize_t ida_export get_func_cmt(qstring *buf, const func_t *pfn, bool repeatable); + + +/// Set function comment. +/// This function works with function chunks too. +/// \param pfn ptr to function structure +/// \param cmt comment string, may be multiline (with '\n'). +/// Use empty str ("") to delete comment +/// \param repeatable set repeatable comment? + +idaman bool ida_export set_func_cmt(const func_t *pfn, const char *cmt, bool repeatable); + + +/// Update information about a function in the database (::func_t). +/// You must not change the function start and end addresses using this function. +/// Use set_func_start() and set_func_end() for it. +/// \param pfn ptr to function structure +/// \return success + +idaman bool ida_export update_func(func_t *pfn); + + +/// Add a new function. +/// If the fn->end_ea is #BADADDR, then IDA will try to determine the +/// function bounds by calling find_func_bounds(..., #FIND_FUNC_DEFINE). +/// \param pfn ptr to filled function structure +/// \return success + +idaman bool ida_export add_func_ex(func_t *pfn); + + +/// Add a new function. +/// If the function end address is #BADADDR, then IDA will try to determine +/// the function bounds by calling find_func_bounds(..., #FIND_FUNC_DEFINE). +/// \param ea1 start address +/// \param ea2 end address +/// \return success + +inline bool add_func(ea_t ea1, ea_t ea2=BADADDR) +{ + func_t fn(ea1, ea2); + return add_func_ex(&fn); +} + + +/// Delete a function. +/// \param ea any address in the function entry chunk +/// \return success + +idaman bool ida_export del_func(ea_t ea); + + +/// Move function chunk start address. +/// \param ea any address in the function +/// \param newstart new end address of the function +/// \return \ref MOVE_FUNC_ + +idaman int ida_export set_func_start(ea_t ea, ea_t newstart); +/// \defgroup MOVE_FUNC_ Function move result codes +/// Return values for set_func_start() +//@{ +#define MOVE_FUNC_OK 0 ///< ok +#define MOVE_FUNC_NOCODE 1 ///< no instruction at 'newstart' +#define MOVE_FUNC_BADSTART 2 ///< bad new start address +#define MOVE_FUNC_NOFUNC 3 ///< no function at 'ea' +#define MOVE_FUNC_REFUSED 4 ///< a plugin refused the action +//@} + + +/// Move function chunk end address. +/// \param ea any address in the function +/// \param newend new end address of the function +/// \return success + +idaman bool ida_export set_func_end(ea_t ea, ea_t newend); + + +/// Reanalyze a function. +/// This function plans to analyzes all chunks of the given function. +/// Optional parameters (ea1, ea2) may be used to narrow the analyzed range. +/// \param pfn pointer to a function +/// \param ea1 start of the range to analyze +/// \param ea2 end of range to analyze +/// \param analyze_parents meaningful only if pfn points to a function tail. +/// if true, all tail parents will be reanalyzed. +/// if false, only the given tail will be reanalyzed. + +idaman void ida_export reanalyze_function( + func_t *pfn, + ea_t ea1=0, + ea_t ea2=BADADDR, + bool analyze_parents=false); + + +/// Determine the boundaries of a new function. +/// This function tries to find the start and end addresses of a new function. +/// It calls the module with \ph{func_bounds} in order to fine tune +/// the function boundaries. +/// \param nfn structure to fill with information +/// \ nfn->start_ea points to the start address of the new function. +/// \param flags \ref FIND_FUNC_F +/// \return \ref FIND_FUNC_R + +idaman int ida_export find_func_bounds(func_t *nfn, int flags); + +/// \defgroup FIND_FUNC_F Find function bounds flags +/// Passed as 'flags' parameter to find_func_bounds() +//@{ +#define FIND_FUNC_NORMAL 0x0000 ///< stop processing if undefined byte is encountered +#define FIND_FUNC_DEFINE 0x0001 ///< create instruction if undefined byte is encountered +#define FIND_FUNC_IGNOREFN 0x0002 ///< ignore existing function boundaries. + ///< by default the function returns function boundaries + ///< if ea belongs to a function. +#define FIND_FUNC_KEEPBD 0x0004 ///< do not modify incoming function boundaries, + ///< just create instructions inside the boundaries. +//@} + +/// \defgroup FIND_FUNC_R Find function bounds result codes +/// Return values for find_func_bounds() +//@{ +#define FIND_FUNC_UNDEF 0 ///< function has instructions that pass execution flow to unexplored bytes. + ///< nfn->end_ea will have the address of the unexplored byte. +#define FIND_FUNC_OK 1 ///< ok, 'nfn' is ready for add_func() +#define FIND_FUNC_EXIST 2 ///< function exists already. + ///< its bounds are returned in 'nfn'. +//@} + + +/// Get function name. +/// \param out buffer for the answer +/// \param ea any address in the function +/// \return length of the function name + +idaman ssize_t ida_export get_func_name(qstring *out, ea_t ea); + + +/// Calculate function size. +/// This function takes into account all fragments of the function. +/// \param pfn ptr to function structure + +idaman asize_t ida_export calc_func_size(func_t *pfn); + + +/// Get function bitness (which is equal to the function segment bitness). +/// pfn==nullptr => returns 0 +/// \retval 0 16 +/// \retval 1 32 +/// \retval 2 64 + +idaman int ida_export get_func_bitness(const func_t *pfn); + +/// Get number of bits in the function addressing +inline int idaapi get_func_bits(const func_t *pfn) { return 1 << (get_func_bitness(pfn)+4); } + +/// Get number of bytes in the function addressing +inline int idaapi get_func_bytes(const func_t *pfn) { return get_func_bits(pfn)/8; } + + +/// Is the function visible (not hidden)? + +inline bool is_visible_func(func_t *pfn) { return (pfn->flags & FUNC_HIDDEN) == 0; } + +/// Is the function visible (event after considering #SCF_SHHID_FUNC)? +inline bool is_finally_visible_func(func_t *pfn) +{ + return (inf_get_cmtflg() & SCF_SHHID_FUNC) != 0 || is_visible_func(pfn); +} + +/// Set visibility of function + +idaman void ida_export set_visible_func(func_t *pfn, bool visible); + + +/// Give a meaningful name to function if it consists of only 'jump' instruction. +/// \param pfn pointer to function (may be nullptr) +/// \param oldname old name of function. +/// if old name was in "j_..." form, then we may discard it +/// and set a new name. +/// if oldname is not known, you may pass nullptr. +/// \return success + +idaman int ida_export set_func_name_if_jumpfunc(func_t *pfn, const char *oldname); + + +/// Calculate target of a thunk function. +/// \param pfn pointer to function (may not be nullptr) +/// \param fptr out: will hold address of a function pointer (if indirect jump) +/// \return the target function or #BADADDR + +idaman ea_t ida_export calc_thunk_func_target(func_t *pfn, ea_t *fptr); + + +/// Does the function return?. +/// To calculate the answer, #FUNC_NORET flag and is_noret() are consulted +/// The latter is required for imported functions in the .idata section. +/// Since in .idata we have only function pointers but not functions, we have +/// to introduce a special flag for them. + +idaman bool ida_export func_does_return(ea_t callee); + + +/// Plan to reanalyze noret flag. +/// This function does not remove FUNC_NORET if it is already present. +/// It just plans to reanalysis. + +idaman bool ida_export reanalyze_noret_flag(ea_t ea); + + +/// Signal a non-returning instruction. +/// This function can be used by the processor module to tell the kernel +/// about non-returning instructions (like call exit). The kernel will +/// perform the global function analysis and find out if the function +/// returns at all. This analysis will be done at the first call to func_does_return() +/// \return true if the instruction 'noret' flag has been changed + +idaman bool ida_export set_noret_insn(ea_t insn_ea, bool noret); + + +//-------------------------------------------------------------------- +// F U N C T I O N C H U N K S +//-------------------------------------------------------------------- +/// Get pointer to function chunk structure by address. +/// \param ea any address in a function chunk +/// \return ptr to a function chunk or nullptr. +/// This function may return a function entry as well as a function tail. + +idaman func_t *ida_export get_fchunk(ea_t ea); + + +/// Get pointer to function chunk structure by number. +/// \param n number of function chunk, is in range 0..get_fchunk_qty()-1 +/// \return ptr to a function chunk or nullptr. +/// This function may return a function entry as well as a function tail. + +idaman func_t *ida_export getn_fchunk(int n); + + +/// Get total number of function chunks in the program + +idaman size_t ida_export get_fchunk_qty(void); + + +/// Get ordinal number of a function chunk in the global list of function chunks. +/// \param ea any address in the function chunk +/// \return number of function chunk (0..get_fchunk_qty()-1). +/// -1 means 'no function chunk at the specified address'. + +idaman int ida_export get_fchunk_num(ea_t ea); + + +/// Get pointer to the previous function chunk in the global list. +/// \param ea any address in the program +/// \return ptr to function chunk or nullptr if previous function chunk doesn't exist + +idaman func_t *ida_export get_prev_fchunk(ea_t ea); + + +/// Get pointer to the next function chunk in the global list. +/// \param ea any address in the program +/// \return ptr to function chunk or nullptr if next function chunk doesn't exist + +idaman func_t *ida_export get_next_fchunk(ea_t ea); + + +//-------------------------------------------------------------------- +// Functions to manipulate function chunks + +/// Append a new tail chunk to the function definition. +/// If the tail already exists, then it will simply be added to the function tail list +/// Otherwise a new tail will be created and its owner will be set to be our function +/// If a new tail cannot be created, then this function will fail. +/// \param ea1 start of the tail. If a tail already exists at the specified address +/// it must start at 'ea1' +/// \param ea2 end of the tail. If a tail already exists at the specified address +/// it must end at 'ea2'. If specified as BADADDR, IDA will determine +/// the end address itself. + +idaman bool ida_export append_func_tail(func_t *pfn, ea_t ea1, ea_t ea2); + + +/// Remove a function tail. +/// If the tail belongs only to one function, it will be completely removed. +/// Otherwise if the function was the tail owner, the first function using +/// this tail becomes the owner of the tail. + +idaman bool ida_export remove_func_tail(func_t *pfn, ea_t tail_ea); + + +/// Set a function as the possessing function of a function tail. +/// The function should already refer to the tail (after append_func_tail). + +idaman bool ida_export set_tail_owner(func_t *fnt, ea_t func_start); + + +// Auxiliary function(s) to be used in func_..._iterator_t + +class func_parent_iterator_t; +class func_tail_iterator_t; +class func_item_iterator_t; + +/// Declare helper functions for ::func_item_iterator_t +#define DECLARE_FUNC_ITERATORS(prefix) \ +prefix bool ida_export func_tail_iterator_set(func_tail_iterator_t *fti, func_t *pfn, ea_t ea);\ +prefix bool ida_export func_tail_iterator_set_ea(func_tail_iterator_t *fti, ea_t ea);\ +prefix bool ida_export func_parent_iterator_set(func_parent_iterator_t *fpi, func_t *pfn);\ +prefix bool ida_export func_item_iterator_next(func_item_iterator_t *fii, testf_t *testf, void *ud);\ +prefix bool ida_export func_item_iterator_prev(func_item_iterator_t *fii, testf_t *testf, void *ud);\ +prefix bool ida_export func_item_iterator_decode_prev_insn(func_item_iterator_t *fii, insn_t *out); \ +prefix bool ida_export func_item_iterator_decode_preceding_insn(func_item_iterator_t *fii, eavec_t *visited, bool *p_farref, insn_t *out); +DECLARE_FUNC_ITERATORS(idaman) + +/// Helper function to accept any address +inline THREAD_SAFE bool idaapi f_any(flags_t, void *) { return true; } + +/// Class to enumerate all function tails sorted by addresses. +/// Enumeration is started with main(), first(), or last(). +/// If first() is used, the function entry chunk will be excluded from the enumeration. +/// Otherwise it will be included in the enumeration (for main() and last()). +/// The loop may continue until the next() or prev() function returns false. +/// These functions return false when the enumeration is over. +/// The tail chunks are always sorted by their addresses. +/// +/// Sample code: +/// \code +/// func_tail_iterator_t fti(pfn); +/// for ( bool ok=fti.first(); ok; ok=fti.next() ) +/// const range_t &a = fti.chunk(); +/// .... +/// \endcode +/// +/// If the 'ea' parameter is used in the constructor, then the iterator is positioned +/// at the chunk containing the specified 'ea'. Otherwise it is positioned at the +/// function entry chunk. +/// If 'pfn' is specified as nullptr then the set() function will fail, +/// but it is still possible to use the class. In this case the iteration will be +/// limited by the segment boundaries. +/// The function main chunk is locked during the iteration. +/// It is also possible to enumerate one single arbitrary range using set_range() +/// This function is mainly designed to be used from ::func_item_iterator_t. +class func_tail_iterator_t +{ + func_t *pfn; + int idx; + range_t seglim; // valid and used only if pfn == nullptr +public: + func_tail_iterator_t(void) : pfn(nullptr), idx(-1) {} + func_tail_iterator_t(func_t *_pfn, ea_t ea=BADADDR) : pfn(nullptr) { set(_pfn, ea); } + ~func_tail_iterator_t(void) + { + // if was iterating over function chunks, unlock the main chunk + if ( pfn != nullptr ) + lock_func_range(pfn, false); + } + bool set(func_t *_pfn, ea_t ea=BADADDR) { return func_tail_iterator_set(this, _pfn, ea); } + bool set_ea(ea_t ea) { return func_tail_iterator_set_ea(this, ea); } + // set an arbitrary range + bool set_range(ea_t ea1, ea_t ea2) + { + this->~func_tail_iterator_t(); + pfn = nullptr; + idx = -1; + seglim = range_t(ea1, ea2); + return !seglim.empty(); + } + const range_t &chunk(void) const + { + if ( pfn == nullptr ) + return seglim; + return idx >= 0 && idx < pfn->tailqty ? pfn->tails[idx] : *(range_t*)pfn; + } + bool first(void) { if ( pfn != nullptr ) { idx = 0; return pfn->tailqty > 0; } return false; } // get only tail chunks + bool last(void) { if ( pfn != nullptr ) { idx = pfn->tailqty - 1; return true; } return false; } // get all chunks (the entry chunk last) + bool next(void) { if ( pfn != nullptr && idx+1 < pfn->tailqty ) { idx++; return true; } return false; } + bool prev(void) { if ( idx >= 0 ) { idx--; return true; } return false; } + bool main(void) { idx = -1; return pfn != nullptr; } // get all chunks (the entry chunk first) +}; + + +/// Function to iterate function chunks (all of them including the entry chunk) +/// \param pfn pointer to the function +/// \param func function to call for each chunk +/// \param ud user data for 'func' +/// \param include_parents meaningful only if pfn points to a function tail. +/// if true, all tail parents will be iterated. +/// if false, only the given tail will be iterated. + +idaman void ida_export iterate_func_chunks( + func_t *pfn, + void (idaapi *func)(ea_t ea1, ea_t ea2, void *ud), + void *ud=nullptr, + bool include_parents=false); + + +/// Class to enumerate all function instructions and data sorted by addresses. +/// The function entry chunk items are enumerated first regardless of their addresses +/// +/// Sample code: +/// \code +/// func_item_iterator_t fii; +/// for ( bool ok=fii.set(pfn, ea); ok; ok=fii.next_addr() ) +/// ea_t ea = fii.current(); +/// .... +/// \endcode +/// +/// If 'ea' is not specified in the call to set(), then the enumeration starts at +/// the function entry point. +/// If 'pfn' is specified as nullptr then the set() function will fail, +/// but it is still possible to use the class. In this case the iteration will be +/// limited by the segment boundaries. +/// It is also possible to enumerate addresses in an arbitrary range using set_range(). +class func_item_iterator_t +{ + func_tail_iterator_t fti; + ea_t ea; +public: + func_item_iterator_t(void) : ea(BADADDR) {} + func_item_iterator_t(func_t *pfn, ea_t _ea=BADADDR) { set(pfn, _ea); } + /// Set a function range. if pfn == nullptr then a segment range will be set. + bool set(func_t *pfn, ea_t _ea=BADADDR) + { + ea = (_ea != BADADDR || pfn == nullptr) ? _ea : pfn->start_ea; + return fti.set(pfn, _ea); + } + /// Set an arbitrary range + bool set_range(ea_t ea1, ea_t ea2) { ea = ea1; return fti.set_range(ea1, ea2); } + bool first(void) { if ( !fti.main() ) return false; ea=fti.chunk().start_ea; return true; } + bool last(void) { if ( !fti.last() ) return false; ea=fti.chunk().end_ea; return true; } + ea_t current(void) const { return ea; } + const range_t &chunk(void) const { return fti.chunk(); } + bool next(testf_t *func, void *ud) { return func_item_iterator_next(this, func, ud); } + bool prev(testf_t *func, void *ud) { return func_item_iterator_prev(this, func, ud); } + bool next_addr(void) { return next(f_any, nullptr); } + bool next_head(void) { return next(f_is_head, nullptr); } + bool next_code(void) { return next(f_is_code, nullptr); } + bool next_data(void) { return next(f_is_data, nullptr); } + bool next_not_tail(void) { return next(f_is_not_tail, nullptr); } + bool prev_addr(void) { return prev(f_any, nullptr); } + bool prev_head(void) { return prev(f_is_head, nullptr); } + bool prev_code(void) { return prev(f_is_code, nullptr); } + bool prev_data(void) { return prev(f_is_data, nullptr); } + bool prev_not_tail(void) { return prev(f_is_not_tail, nullptr); } + bool decode_prev_insn(insn_t *out) { return func_item_iterator_decode_prev_insn(this, out); } + bool decode_preceding_insn(eavec_t *visited, bool *p_farref, insn_t *out) + { return func_item_iterator_decode_preceding_insn(this, visited, p_farref, out); } +}; + +/// Class to enumerate all function parents sorted by addresses. +/// Enumeration is started with first() or last(). +/// The loop may continue until the next() or prev() function returns false. +/// The parent functions are always sorted by their addresses. +/// The tail chunk is locked during the iteration. +/// +/// Sample code: +/// \code +/// func_parent_iterator_t fpi(fnt); +/// for ( bool ok=fpi.first(); ok; ok=fpi.next() ) +/// ea_t parent = fpi.parent(); +/// .... +/// \endcode +class func_parent_iterator_t +{ + func_t *fnt; + int idx; +public: + func_parent_iterator_t(void) : fnt(nullptr), idx(0) {} + func_parent_iterator_t(func_t *_fnt) : fnt(nullptr) { set(_fnt); } + ~func_parent_iterator_t(void) + { + if ( fnt != nullptr ) + lock_func_range(fnt, false); + } + bool set(func_t *_fnt) { return func_parent_iterator_set(this, _fnt); } + ea_t parent(void) const { return fnt->referers[idx]; } + bool first(void) { idx = 0; return is_func_tail(fnt) && fnt->refqty > 0; } + bool last(void) { idx = fnt->refqty - 1; return idx >= 0; } + bool next(void) { if ( idx+1 < fnt->refqty ) { idx++; return true; } return false; } + bool prev(void) { if ( idx > 0 ) { idx--; return true; } return false; } + void reset_fnt(func_t *_fnt) { fnt = _fnt; } // for internal use only! +}; + + +/// \name Get prev/next address in function +/// Unlike func_item_iterator_t which always enumerates the main function +/// chunk first, these functions respect linear address ordering. +//@{ +idaman ea_t ida_export get_prev_func_addr(func_t *pfn, ea_t ea); +idaman ea_t ida_export get_next_func_addr(func_t *pfn, ea_t ea); +//@} + +//-------------------------------------------------------------------- +/// \name +/// Functions to work with temporary register argument definitions +//@{ +idaman void ida_export read_regargs(func_t *pfn); +idaman void ida_export add_regarg(func_t *pfn, int reg, const tinfo_t &tif, const char *name); +//@} + +//-------------------------------------------------------------------- +// L I B R A R Y M O D U L E S I G N A T U R E S +//-------------------------------------------------------------------- + +/// \defgroup IDASGN_ Error codes for signature functions: +/// See calc_idasgn_state() and del_idasgn() +//@{ +#define IDASGN_OK 0 ///< ok +#define IDASGN_BADARG 1 ///< bad number of signature +#define IDASGN_APPLIED 2 ///< signature is already applied +#define IDASGN_CURRENT 3 ///< signature is currently being applied +#define IDASGN_PLANNED 4 ///< signature is planned to be applied +//@} + +/// Add a signature file to the list of planned signature files. +/// \param fname file name. should not contain directory part. +/// \return 0 if failed, otherwise number of planned (and applied) signatures + +idaman int ida_export plan_to_apply_idasgn(const char *fname); // plan to use library + + +/// Apply a signature file to the specified address. +/// \param signame short name of signature file (the file name without path) +/// \param ea address to apply the signature +/// \param is_startup if set, then the signature is treated as a startup one +/// for startup signature ida doesn't rename the first +/// function of the applied module. +/// \return \ref LIBFUNC_ + +idaman int ida_export apply_idasgn_to(const char *signame, ea_t ea, bool is_startup); + + +/// Get number of signatures in the list of planned and applied signatures. +/// \return 0..n + +idaman int ida_export get_idasgn_qty(void); + + +/// Get number of the the current signature. +/// \return 0..n-1 + +idaman int ida_export get_current_idasgn(void); + + +/// Get state of a signature in the list of planned signatures +/// \param n number of signature in the list (0..get_idasgn_qty()-1) +/// \return state of signature or #IDASGN_BADARG + +idaman int ida_export calc_idasgn_state(int n); + + +/// Remove signature from the list of planned signatures. +/// \param n number of signature in the list (0..get_idasgn_qty()-1) +/// \return #IDASGN_OK, #IDASGN_BADARG, #IDASGN_APPLIED + +idaman int ida_export del_idasgn(int n); + + +/// Get information about a signature in the list. +/// \param signame buffer for the name of the signature. +/// (short form, only base name without the directory part +/// will be stored). +/// if signame == nullptr, then the name won't be returned. +/// \param optlibs buffer for the names of the optional libraries +/// if optlibs == nullptr, then the optional libraries are not returned +/// \param n number of signature in the list (0..get_idasgn_qty()-1) +/// \return number of successfully recognized modules using this signature. +/// -1 means the 'n' is a bad argument, i.e. no signature with this +/// number exists.. + +idaman int32 ida_export get_idasgn_desc( + qstring *signame, + qstring *optlibs, + int n); + + +class idasgn_t; + +/// Get idasgn header by a short signature name. +/// \param name short name of a signature +/// \return nullptr if can't find the signature + +idaman idasgn_t *ida_export get_idasgn_header_by_short_name(const char *name); + + +/// Get full description of the signature by its short name. +/// \param buf the output buffer +/// \param name short name of a signature +/// \return size of signature description or -1 + +idaman ssize_t ida_export get_idasgn_title( + qstring *buf, + const char *name); + +/// Determine compiler/vendor using the startup signatures. +/// If determined, then appropriate signature files are included into +/// the list of planned signature files. + +idaman void ida_export determine_rtl(void); + + +/// Apply a startup signature file to the specified address. +/// \param ea address to apply the signature to; usually \inf{start_ea} +/// \param startup the name of the signature file without path and extension +/// \return true if successfully applied the signature + +idaman bool ida_export apply_startup_sig(ea_t ea, const char *startup); + + +/// Apply the currently loaded signature file to the specified address. +/// If a library function is found, then create a function and name +/// it accordingly. +/// \param ea any address in the program +/// \returns \ref LIBFUNC_ + +idaman int ida_export try_to_add_libfunc(ea_t ea); + + +/// \defgroup LIBFUNC_ Library function codes +/// Return values for try_to_add_libfunc() and apply_idasgn_to() +//@{ +#define LIBFUNC_FOUND 0 ///< ok, library function is found +#define LIBFUNC_NONE 1 ///< no, this is not a library function +#define LIBFUNC_DELAY 2 ///< no decision because of lack of information +//@} + +// KERNEL mode functions + +/// \cond +/// kept in the sdk because inlined +inline void save_signatures(void) {} +bool invalidate_sp_analysis(func_t *pfn); +inline bool invalidate_sp_analysis(ea_t ea) + { return invalidate_sp_analysis(get_func(ea)); } +/// \endcond + + +#endif diff --git a/idasdk76/include/gdl.hpp b/idasdk76/include/gdl.hpp new file mode 100644 index 0000000..361be5e --- /dev/null +++ b/idasdk76/include/gdl.hpp @@ -0,0 +1,365 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * + * Graph drawing support + * + */ + +#ifndef __GDLDRAW_HPP +#define __GDLDRAW_HPP + +#include <funcs.hpp> + +/*! \file gdl.hpp + + \brief Low level graph drawing operations + +*/ + +//------------------------------------------------------------------------- +// forward declarations: +class node_iterator; +class qflow_chart_t; +class gdl_graph_t; + +/// Flow chart block types +enum fc_block_type_t +{ + fcb_normal, ///< normal block + fcb_indjump, ///< block ends with indirect jump + fcb_ret, ///< return block + fcb_cndret, ///< conditional return block + fcb_noret, ///< noreturn block + fcb_enoret, ///< external noreturn block (does not belong to the function) + fcb_extern, ///< external normal block + fcb_error, ///< block passes execution past the function end +}; + +#ifndef SWIG +#define DECLARE_HELPER(decl) \ +decl node_iterator *ida_export node_iterator_goup(node_iterator *); \ +decl void ida_export create_qflow_chart(qflow_chart_t &); \ +decl bool ida_export append_to_flowchart(qflow_chart_t &, ea_t, ea_t); \ +decl fc_block_type_t ida_export fc_calc_block_type(const qflow_chart_t &, size_t); \ +decl bool ida_export create_multirange_qflow_chart(qflow_chart_t &, const rangevec_t &); +#else +#define DECLARE_HELPER(decl) +#endif // SWIG + +DECLARE_HELPER(idaman) + +//------------------------------------------------------------------------- +/// Set of integer constants +class intset_t : public std::set<int> +{ +public: + DEFINE_MEMORY_ALLOCATION_FUNCS() + size_t idaapi print(char *buf, size_t bufsize) const; + const char *idaapi dstr(void) const; + bool has(int value) const + { + const_iterator p = find(value); + const_iterator q = end(); + return p != q; + } +}; + +typedef qvector<intvec_t> array_of_intvec_t; + +/// Map of integer constants to integer constants +class intmap_t : public std::map<int, int> +{ +public: + DEFINE_MEMORY_ALLOCATION_FUNCS() + size_t idaapi print(char *buf, size_t bufsize) const; + const char *idaapi dstr(void) const; +}; + +typedef qvector<intmap_t> array_of_intmap_t; + +//------------------------------------------------------------------------- +/// Set of graph nodes +class node_set_t : public intset_t +{ +public: + idaapi node_set_t(void) {} + idaapi node_set_t(int node) { insert(node); } + idaapi node_set_t(const gdl_graph_t *g); + bool idaapi add(int node) { return insert(node).second; } + void idaapi sub(int node) { erase(node); } + void idaapi sub(const node_set_t &r); + void idaapi add(const node_set_t &r); + void idaapi intersect(const node_set_t &r); + void idaapi extract(intvec_t &out) const; + int idaapi first(void) const { return empty() ? -1 : *begin(); } +}; + +typedef qvector<node_set_t> array_of_node_set_t; + +//------------------------------------------------------------------------- +/// Node iterator (used to draw graphs) +class node_iterator +{ + DECLARE_HELPER(friend) + friend class gdl_graph_t; + const gdl_graph_t *g; + int i; + node_iterator &_goup(void); + node_iterator &goup(void) { return *node_iterator_goup(this); } +public: + node_iterator(const gdl_graph_t *_g, int n) : g(_g), i(n) {} + node_iterator &operator++(void) { i++; return goup(); } + bool operator==(const node_iterator &n) const { return i == n.i && g == n.g; } + bool operator!=(const node_iterator &n) const { return !(*this == n); } + int operator*(void) const { return i; } +}; + +//------------------------------------------------------------------------- +/// gdl graph interface - includes only functions required to draw it +class gdl_graph_t +{ + // does a path from 'm' to 'n' exist? + bool idaapi path(node_set_t &visited, int m, int n) const; +public: + DEFINE_MEMORY_ALLOCATION_FUNCS() + virtual ~gdl_graph_t() {} + virtual char *idaapi get_node_label(char *iobuf, int iobufsize, int n) const { qnotused(iobufsize); qnotused(n); iobuf[0] = '\0'; return iobuf; } + virtual void idaapi print_graph_attributes(FILE *fp) const { qnotused(fp); } + virtual bool idaapi print_node(FILE *fp, int n) const { qnotused(fp); qnotused(n); return false; } + virtual bool idaapi print_edge(FILE *fp, int i, int j) const { qnotused(fp); qnotused(i); qnotused(j); return false; } + virtual void idaapi print_node_attributes(FILE *fp, int n) const { qnotused(fp); qnotused(n); } + virtual int idaapi size(void) const = 0; // number of the max node number + virtual int idaapi node_qty(void) const { return size(); } // number of alive nodes + virtual bool idaapi exists(int node) const { qnotused(node); return true; } + virtual int idaapi entry(void) const { return 0; } + virtual int idaapi exit(void) const { return size()-1; } + virtual int idaapi nsucc(int node) const = 0; + virtual int idaapi npred(int node) const = 0; + virtual int idaapi succ(int node, int i) const = 0; + virtual int idaapi pred(int node, int i) const = 0; + virtual bool idaapi empty(void) const { return node_qty() == 0; } + virtual bgcolor_t idaapi get_node_color(int n) const { qnotused(n); return DEFCOLOR; } + virtual bgcolor_t idaapi get_edge_color(int i, int j) const { qnotused(i); qnotused(j); return DEFCOLOR; } + void idaapi gen_gdl(FILE *fp) const; + void idaapi gen_gdl(const char *file) const; + size_t idaapi nedge(int node, bool ispred) const { return ispred ? npred(node) : nsucc(node); } + int idaapi edge(int node, int i, bool ispred) const { return ispred ? pred(node, i) : succ(node, i); } + int idaapi front(void) { return *begin(); } + node_iterator idaapi begin(void) const { return node_iterator(this, 0).goup(); } + node_iterator idaapi end(void) const { return node_iterator(this, size()); } + // does a path from 'm' to 'n' exist? + bool idaapi path_exists(int m, int n) const { node_set_t v; return path(v, m, n); } + + void idaapi gen_dot(FILE *fp) const; + void idaapi gen_dot(const char *file) const; +}; + + +/// Create GDL file for graph + +idaman void ida_export gen_gdl(const gdl_graph_t *g, const char *fname); + + +/// Display GDL file by calling wingraph32. +/// The exact name of the grapher is taken from the configuration file +/// and set up by setup_graph_subsystem(). +/// \return error code from os, 0 if ok + +idaman int ida_export display_gdl(const char *fname); + + +//------------------------------------------------------------------------- +// Build and display program graphs + +/// Build and display a flow graph. +/// \param filename output file name. the file extension is not used. maybe NULL. +/// \param title graph title +/// \param pfn function to graph +/// \param ea1, ea2 if pfn == NULL, then the address range +/// \param gflags combination of \ref CHART_1. +/// if none of #CHART_GEN_DOT, #CHART_GEN_GDL, #CHART_WINGRAPH +/// is specified, the function will return false +/// \return success. if fails, a warning message is displayed on the screen + +idaman bool ida_export gen_flow_graph( + const char *filename, + const char *title, + func_t *pfn, + ea_t ea1, + ea_t ea2, + int gflags); + +/// \defgroup CHART_1 Flow graph building flags +/// Passed as flags parameter to: +/// - gen_flow_graph() +/// - gen_simple_call_chart() +/// - gen_complex_call_chart() +//@{ +#define CHART_PRINT_NAMES 0x1000 ///< print labels for each block? +#define CHART_GEN_DOT 0x2000 ///< generate .dot file (file extension is forced to .dot) +#define CHART_GEN_GDL 0x4000 ///< generate .gdl file (file extension is forced to .gdl) +#define CHART_WINGRAPH 0x8000 ///< call grapher to display the graph +//@} + + +/// Build and display a simple function call graph. +/// \param filename output file name. the file extension is not used. maybe NULL. +/// \param wait message to display during graph building +/// \param title graph title +/// \param gflags combination of #CHART_NOLIBFUNCS and \ref CHART_1. +/// if none of #CHART_GEN_DOT, #CHART_GEN_GDL, #CHART_WINGRAPH +/// is specified, the function will return false. +/// \return success. if fails, a warning message is displayed on the screen + +idaman bool ida_export gen_simple_call_chart( + const char *filename, + const char *wait, + const char *title, + int gflags); + + +/// Build and display a complex xref graph. +/// \param filename output file name. the file extension is not used. maybe NULL. +/// \param wait message to display during graph building +/// \param title graph title +/// \param ea1, ea2 address range +/// \param flags combination of \ref CHART_2 and \ref CHART_1. +/// if none of #CHART_GEN_DOT, #CHART_GEN_GDL, #CHART_WINGRAPH +/// is specified, the function will return false. +/// \param recursion_depth optional limit of recursion +/// \return success. if fails, a warning message is displayed on the screen + +idaman bool ida_export gen_complex_call_chart( + const char *filename, + const char *wait, + const char *title, + ea_t ea1, + ea_t ea2, + int flags, + int32 recursion_depth=-1); + +/// \defgroup CHART_2 Call chart building flags +/// Passed as flags parameter to gen_complex_call_chart() +//@{ +#define CHART_NOLIBFUNCS 0x0400 ///< don't include library functions in the graph +#define CHART_REFERENCING 0x0001 ///< references to the addresses in the list +#define CHART_REFERENCED 0x0002 ///< references from the addresses in the list +#define CHART_RECURSIVE 0x0004 ///< analyze added blocks +#define CHART_FOLLOW_DIRECTION 0x0008 ///< analyze references to added blocks only in the direction of the reference who discovered the current block +#define CHART_IGNORE_XTRN 0x0010 +#define CHART_IGNORE_DATA_BSS 0x0020 +#define CHART_IGNORE_LIB_TO 0x0040 ///< ignore references to library functions +#define CHART_IGNORE_LIB_FROM 0x0080 ///< ignore references from library functions +#define CHART_PRINT_COMMENTS 0x0100 +#define CHART_PRINT_DOTS 0x0200 ///< print dots if xrefs exist outside of the range recursion depth +//@} + + +/// Setup the user-defined graph colors and graph viewer program. +/// This function is called by the GUI at the beginning, so no need to call +/// it again. + +idaman void ida_export setup_graph_subsystem(const char *_grapher, bgcolor_t (idaapi *get_graph_color)(int color)); + + +//-V:cancellable_graph_t:730 not all members of a class are initialized inside the constructor +class cancellable_graph_t : public gdl_graph_t +{ +public: + mutable bool cancelled; + char padding[3]; // make the class nicely aligned. otherwise we have problems + // with gcc in qflow_chart_t. + cancellable_graph_t(void) : cancelled(false) {} + virtual ~cancellable_graph_t() {} + bool idaapi check_cancel(void) const; +}; + +//-------------------------------------------------------------------------- +/// Information about a basic block of a \ref qflow_chart_t +struct qbasic_block_t : public range_t +{ + intvec_t succ; ///< list of node successors + intvec_t pred; ///< list of node predecessors +}; + +/// Does this block never return? +inline THREAD_SAFE bool is_noret_block(fc_block_type_t btype) +{ + return btype == fcb_noret || btype == fcb_enoret; +} + +/// Does this block return? +inline THREAD_SAFE bool is_ret_block(fc_block_type_t btype) +{ + return btype == fcb_ret || btype == fcb_cndret; +} + +/// \defgroup FC_ Flow chart flags +/// Passed as 'flags' parameter to qflow_chart_t +//@{ +#define FC_PRINT 0x0001 ///< print names (used only by display_flow_chart()) +#define FC_NOEXT 0x0002 ///< do not compute external blocks. Use this to prevent jumps leaving the + ///< function from appearing in the flow chart. Unless specified, the + ///< targets of those outgoing jumps will be present in the flow + ///< chart under the form of one-instruction blocks +#define FC_RESERVED 0x0004 // former FC_PREDS +#define FC_APPND 0x0008 ///< multirange flowchart (set by append_to_flowchart) +#define FC_CHKBREAK 0x0010 ///< build_qflow_chart() may be aborted by user +#define FC_CALL_ENDS 0x0020 ///< call instructions terminate basic blocks +#define FC_NOPREDS 0x0040 ///< do not compute predecessor lists +//@} + +/// A flow chart for a function, or a set of address ranges +class qflow_chart_t : public cancellable_graph_t +{ +public: + typedef qvector<qbasic_block_t> blocks_t; + DECLARE_HELPER(friend) + qstring title; + range_t bounds; ///< overall bounds of the qflow_chart_t instance + func_t *pfn = nullptr; ///< the function this instance was built upon + int flags = 0; ///< flags. See \ref FC_ + blocks_t blocks; ///< basic blocks + int nproper = 0; ///< number of basic blocks belonging to the specified range + + idaapi qflow_chart_t(void) {} + idaapi qflow_chart_t(const char *_title, func_t *_pfn, ea_t _ea1, ea_t _ea2, int _flags) + : title(_title), bounds(_ea1, _ea2), pfn(_pfn), flags(_flags) + { + refresh(); + } + virtual ~qflow_chart_t() {} + void idaapi create(const char *_title, func_t *_pfn, ea_t _ea1, ea_t _ea2, int _flags) + { + title = _title; + pfn = _pfn; + bounds = range_t(_ea1, _ea2); + flags = _flags; + refresh(); + } + void idaapi create(const char *_title, const rangevec_t &ranges, int _flags) + { + title = _title; + flags = _flags; + create_multirange_qflow_chart(*this, ranges); + } + void idaapi append_to_flowchart(ea_t ea1, ea_t ea2) { ::append_to_flowchart(*this, ea1, ea2); } + void idaapi refresh(void) { create_qflow_chart(*this); } + fc_block_type_t calc_block_type(size_t blknum) const + { return fc_calc_block_type(*this, blknum); } + bool is_ret_block(size_t blknum) const { return ::is_ret_block(calc_block_type(blknum)); } + bool is_noret_block(size_t blknum) const { return ::is_noret_block(calc_block_type(blknum)); } + virtual void idaapi print_node_attributes(FILE *fp, int n) const override { qnotused(fp); qnotused(n); } + virtual int idaapi nsucc(int node) const override { return int(blocks[node].succ.size()); } + virtual int idaapi npred(int node) const override { return int(blocks[node].pred.size()); } + virtual int idaapi succ(int node, int i) const override { return blocks[node].succ[i]; } + virtual int idaapi pred(int node, int i) const override { return blocks[node].pred[i]; } + virtual char *idaapi get_node_label(char *iobuf, int iobufsize, int n) const override { qnotused(iobuf); qnotused(iobufsize); qnotused(n); return NULL; } + virtual int idaapi size(void) const override { return int(blocks.size()); } + bool idaapi print_names(void) const { return (flags & FC_PRINT) != 0; } +}; + +#endif // __GDLDRAW_HPP diff --git a/idasdk76/include/graph.hpp b/idasdk76/include/graph.hpp new file mode 100644 index 0000000..1ecffe6 --- /dev/null +++ b/idasdk76/include/graph.hpp @@ -0,0 +1,1782 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * Graph type definitions + * + * Due to the use of STL and virtual functions, some parts of this + * interface might be incompatible with compilers other than Visual Studio + * on Windows and gcc on Unix systems + */ + +#ifndef __GRAPH_DEF_HPP +#define __GRAPH_DEF_HPP + +#include <math.h> +#include <pro.h> +#include <gdl.hpp> +#include <idp.hpp> +#include <kernwin.hpp> + +/*! \file graph.hpp + + \brief Graph view management + +*/ + +class func_t; +class abstract_graph_t; + +//------------------------------------------------------------------------- +/// \defgroup NIF_ Node info flags +/// Passed as 'flags' parameter to set_node_info(). +/// Also see node_info_t::get_flags_for_valid(). +//@{ +#define NIF_BG_COLOR (1 << 0) ///< node_info_t::bg_color +#define NIF_FRAME_COLOR (1 << 1) ///< node_info_t::frame_color +#define NIF_EA (1 << 2) ///< node_info_t::ea +#define NIF_TEXT (1 << 3) ///< node_info_t::text +#define NIF_FLAGS (1 << 4) ///< node_info_t::flags +#define NIF_ALL (NIF_BG_COLOR | NIF_FRAME_COLOR | NIF_EA | NIF_TEXT | NIF_FLAGS) +//@} + +//------------------------------------------------------------------------- +/// \defgroup GLICTL_ graph_location_info_t control flags +/// Passed as 'flags' parameter to viewer_set_gli() and viewer_get_gli(). +//@{ +#define GLICTL_CENTER (1 << 0) ///< the gli should be set/get as center +//@} + +/// Information about a node in a graph +struct node_info_t +{ +private: + size_t cb; ///< size of this structure +public: + node_info_t() + : cb(sizeof(*this)), + bg_color(DEFCOLOR), + frame_color(DEFCOLOR), + flags(0), + ea(BADADDR) {} + bgcolor_t bg_color; ///< background color + bgcolor_t frame_color; ///< color of enclosing frame +#define NIFF_SHOW_CONTENTS (1 << 0) // force show contents of huge node + uint32 flags; ///< flags + ea_t ea; ///< address + qstring text; ///< node contents + + /// Has valid #bg_color? + inline bool valid_bg_color() const { return bg_color != DEFCOLOR; } + /// Has valid #frame_color? + inline bool valid_frame_color() const { return frame_color != DEFCOLOR; } + /// Has valid #ea? + inline bool valid_ea() const { return ea != BADADDR; } + /// Has non-empty #text? + inline bool valid_text() const { return !text.empty(); } + /// Has valid #flags? + inline bool valid_flags() const { return flags != 0; } + + /// Get combination of \ref NIF_ describing which attributes are valid + inline uint32 get_flags_for_valid() const + { + uint32 F = 0; + if ( valid_bg_color() ) + F |= NIF_BG_COLOR; + if ( valid_frame_color() ) + F |= NIF_FRAME_COLOR; + if ( valid_ea() ) + F |= NIF_EA; + if ( valid_text() ) + F |= NIF_TEXT; + if ( valid_flags() ) + F |= NIF_FLAGS; + return F; + } +}; + +/// Graph instances have a unique id (see mutable_graph_t::gid) +typedef ea_t graph_id_t; + + +/// Get node info. +/// \param out result +/// \param gid id of desired graph +/// \param node node number +/// \return success + +idaman bool ida_export get_node_info(node_info_t *out, graph_id_t gid, int node); + + +/// Set node info. +/// \param gid id of desired graph +/// \param node node number +/// \param ni node info to use +/// \param flags combination of \ref NIF_, +/// identifying which fields of 'ni' will be used + +idaman void ida_export set_node_info(graph_id_t gid, int node, const node_info_t &ni, uint32 flags); + + +/// Delete the ::node_info_t for the given node + +idaman void ida_export del_node_info(graph_id_t gid, int node); + + +/// Clear node info for the given node. +/// \param gid id of desired graph +/// \param node node number +/// \param flags combination of \ref NIF_, +/// identifying which fields of ::node_info_t +/// will be cleared + +idaman void ida_export clr_node_info(graph_id_t gid, int node, uint32 flags); + + +//------------------------------------------------------------------------- +/// Node ordering in a graph. +/// Maps a node number to a number describing its +/// order in the graph (and vice versa). +class node_ordering_t +{ + intvec_t node_by_order; ///< ordered sequence of node numbers + intvec_t order_by_node; ///< node number => index in #node_by_order + + void ensure_order_by_node() + { + if ( order_by_node.empty() ) + { + size_t n = size(); + order_by_node.resize(n, -1); + for ( size_t i = 0; i < n; i++ ) + { + int idx = node_by_order[i]; + if ( idx != -1 ) + order_by_node[idx] = i; + } + } + } + +public: + DEFINE_MEMORY_ALLOCATION_FUNCS() + void idaapi clear(void) + { + node_by_order.clear(); + order_by_node.clear(); + } + + void idaapi resize(int n) + { + clear(); + if ( n >= 0 ) + node_by_order.resize(n, -1); + } + + size_t idaapi size(void) const + { + return node_by_order.size(); + } + + void idaapi set(int _node, int num) + { + ensure_order_by_node(); + if ( num >= 0 && num < node_by_order.size() + && _node >= 0 && _node < order_by_node.size() ) + { + node_by_order[num] = _node; + order_by_node[_node] = num; + } + } + + bool idaapi clr(int _node) + { + if ( _node < 0 ) + return false; + ensure_order_by_node(); + if ( _node >= order_by_node.size() ) + return false; + int old = order_by_node[_node]; + if ( old < 0 || old >= node_by_order.size() ) + return false; + order_by_node[_node] = -1; + node_by_order[old] = -1; + // shift all order numbers higher than the deleted order number by one + size_t n = size(); + for ( size_t i = 0; i < n; i++ ) + if ( order_by_node[i] > old ) + order_by_node[i]--; + int rest = n - old - 1; + if ( rest > 0 ) + memmove(&node_by_order[old], &node_by_order[old+1], rest*sizeof(int)); + return true; + } + + int idaapi node(size_t _order) const + { + return _order < node_by_order.size() ? node_by_order[_order] : -1; + } + + int idaapi order(int _node) + { + ensure_order_by_node(); + return (_node >= 0 && _node < order_by_node.size()) ? order_by_node[_node] : -1; + } +}; + +//------------------------------------------------------------------------- +/// Edge connecting two graph nodes +struct edge_t +{ + int src; ///< source node number + int dst; ///< destination node number + idaapi edge_t(void) : src(0), dst(0) {} + idaapi edge_t(int x, int y) : src(x), dst(y) {} + bool idaapi operator < (const edge_t &y) const + { return src < y.src || (src == y.src && dst < y.dst); } + bool idaapi operator == (const edge_t &y) const + { return src == y.src && dst == y.dst; } + bool idaapi operator != (const edge_t &y) const + { return src != y.src || dst != y.dst; } +}; +DECLARE_TYPE_AS_MOVABLE(edge_t); + +typedef qvector<edge_t> edgevec_t; ///< vector of graph edges +struct edgeset_t; +struct edge_segs_vec_t; +struct edge_infos_t; +struct destset_t; + +enum edge_type_t +{ + edge_error = 0, + edge_tree = 1, + edge_forward = 2, + edge_back = 3, + edge_cross = 4, + edge_subgraph = 5 // edge of a subgraph (used in collapse) +}; + +//------------------------------------------------------------------------- +class edge_typer_t; + +//------------------------------------------------------------------------- +/// Node visitor - see abstract_graph_t::visit_nodes() +class graph_node_visitor_t +{ + node_set_t visited; ///< set of previously visited nodes +public: + /// Reset visited nodes + void idaapi reinit(void) { visited.clear(); } + /// Mark node as visited + void idaapi set_visited(int n) { visited.add(n); } + /// Have we already visited the given node? + bool idaapi is_visited(int n) const { return visited.has(n); } + + /// Implements action to take when a node is visited + virtual int idaapi visit_node(int /*node*/) { return 0; } + /// Should the edge between 'n' and 'm' be ignored? + virtual bool idaapi is_forbidden_edge(int /*n*/, int /*m*/) const { return false; } + + virtual ~graph_node_visitor_t() {} +}; + +//------------------------------------------------------------------------- +/// Path visitor - see abstract_graph_t::visit_paths() +struct graph_path_visitor_t +{ + intvec_t path; ///< current path + bool prune; ///< walk_forward(): prune := true + ///< means to stop the current path + + + virtual int idaapi walk_forward(int /*node*/) { return 0; } + virtual int idaapi walk_backward(int /*node*/) { return 0; } + + virtual ~graph_path_visitor_t() {} +}; + +//------------------------------------------------------------------------- +/// Coordinate in a graph view +struct point_t +{ + int x, y; + point_t(void) : x(0), y(0) {} + point_t(int _x, int _y) : x(_x), y(_y) {} + point_t &add(const point_t &r) + { + x += r.x; + y += r.y; + return *this; + } + point_t &sub(const point_t &r) + { + x -= r.x; + y -= r.y; + return *this; + } + template <class T> void div(T d) + { + x /= d; + y /= d; + } + void negate(void) + { + x = -x; + y = -y; + } +#ifdef VCL_H + point_t(const TPoint &p) : x(p.x), y(p.y) {} +#endif + bool operator ==(const point_t &r) const { return x == r.x && y == r.y; } + bool operator !=(const point_t &r) const { return !(*this == r); } + const char *idaapi dstr(void) const; + size_t idaapi print(char *buf, size_t bufsize) const; +}; +DECLARE_TYPE_AS_MOVABLE(point_t); +typedef qvector<point_t> pointvec_t; + +/// Calculate distance between p and q +inline THREAD_SAFE double calc_dist(point_t p, point_t q) +{ + double dx = q.x - p.x; + double dy = q.y - p.y; + return sqrt(dx*dx+dy*dy); +} + +/// Ordered sequence of points +class pointseq_t : public pointvec_t +{ +public: + const char *idaapi dstr(void) const; + size_t idaapi print(char *buf, size_t bufsize) const; +}; + +/// A rectangle in a graph view +struct rect_t +{ + int left; + int top; + int right; + int bottom; + rect_t(void) : left(0), top(0), right(0), bottom(0) {} + rect_t(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} + rect_t(const point_t &p0, const point_t &p1) + : left (qmin(p0.x, p1.x)), + top (qmin(p0.y, p1.y)), + right (qmax(p0.x, p1.x)), + bottom(qmax(p0.y, p1.y)) {} + int width(void) const { return right - left; } + int height(void) const { return bottom - top; } + void move_to(const point_t &p) + { + int dx = p.x - left; + int dy = p.y - top; + move_by(point_t(dx, dy)); + } + void move_by(const point_t &p) + { + left += p.x; + right += p.x; + top += p.y; + bottom += p.y; + } + point_t center(void) const + { + return point_t((left+right)/2, (top+bottom)/2); + } + point_t topleft(void) const + { + return point_t(left, top); + } + point_t bottomright(void) const + { + return point_t(right, bottom); + } + void grow(int delta) + { + left -= delta; + right += delta; + top -= delta; + bottom += delta; + } + void intersect(const rect_t &r) + { + if ( left < r.left ) + left = r.left; + if ( right > r.right ) + right = r.right; + if ( top < r.top ) + top = r.top; + if ( bottom > r.bottom ) + bottom = r.bottom; + } + void make_union(const rect_t &r) + { + if ( left > r.left ) + left = r.left; + if ( right < r.right ) + right = r.right; + if ( top > r.top ) + top = r.top; + if ( bottom < r.bottom ) + bottom = r.bottom; + } + bool empty(void) const + { + return left >= right || top >= bottom; + } + bool is_intersection_empty(const rect_t &r) const + { + return left >= r.right + || right <= r.left + || top >= r.bottom + || bottom <= r.top; + } + bool contains(const point_t &p) const + { + return left <= p.x + && right > p.x + && top <= p.y + && bottom > p.y; + } + int area(void) const { return width()*height(); } + bool idaapi operator == (const rect_t &r) const + { + return left == r.left + && right == r.right + && top == r.top + && bottom == r.bottom; + } + bool idaapi operator != (const rect_t &r) const { return !(*this == r); } + bool idaapi operator < (const rect_t &r) const; +#ifdef VCL_H + const TRect &operator()(void) const { return *(TRect *)this; } + TRect &operator()(void) { return *(TRect *)this; } + rect_t(const TRect &r) : left(r.left), top(r.top), right(r.right), bottom(r.bottom) {} +#endif +}; +DECLARE_TYPE_AS_MOVABLE(rect_t); + +//--------------------------------------------------------------------------- +/// Coordinate in a graph view (double precision) +struct TPointDouble +{ + double x, y; + TPointDouble(void) : x(0.0), y(0.0) {} + TPointDouble(double a, double b) : x(a), y(b) {} + TPointDouble(const point_t &r) : x(r.x), y(r.y) {} + void add(const TPointDouble &r) + { + x += r.x; + y += r.y; + } + void sub(const TPointDouble &r) + { + x -= r.x; + y -= r.y; + } + void negate(void) + { + x = -x; + y = -y; + } + template <class T> void div(T d) + { + x /= d; + y /= d; + } + bool operator ==(const TPointDouble &r) const { return x == r.x && y == r.y; } //-V550 An odd precise comparison: x == r.x + bool operator !=(const TPointDouble &r) const { return !(*this == r); } +}; + +//--------------------------------------------------------------------------- +typedef int layout_type_t; ///< see \ref layout_ +/// \defgroup layout_ Proximity view layouts +//@{ +const layout_type_t + layout_none = 0, + layout_digraph = 1, + layout_tree = 2, + layout_circle = 3, + layout_polar_tree = 4, + layout_orthogonal = 5, + layout_radial_tree = 6; +//@} + +/// Attributes of a graph edge +struct edge_info_t +{ + bgcolor_t color; ///< edge color + int width; ///< edge width + int srcoff; ///< source: edge port offset from the left + int dstoff; ///< destination: edge port offset from the left + pointseq_t layout; ///< describes geometry of edge +#if !defined(_MSC_VER) || _MSC_VER >= 1600 + void idaapi reverse_layout(void) { std::reverse(layout.begin(), layout.end()); } +#endif + void idaapi add_layout_point(point_t p); + idaapi edge_info_t(void) : color(DEFCOLOR), width(1), srcoff(-1), dstoff(-1) {} +}; + +/// Edge layout point +//-V:edge_layout_point_t:690 lacks the '=' operator +struct edge_layout_point_t +{ + int pidx; ///< index into edge_info_t::layout + edge_t e; ///< parent edge + idaapi edge_layout_point_t(void) : pidx(-1), e(-1, -1) {} + idaapi edge_layout_point_t(const edge_layout_point_t &r) : pidx(r.pidx), e(r.e) {} + idaapi edge_layout_point_t(const edge_t &_e, int _pidx) : pidx(_pidx), e(_e) {} + int idaapi compare(const edge_layout_point_t &r) const + { + if ( e < r.e ) + return -1; + if ( r.e < e ) + return 1; + return ::compare(pidx, r.pidx); + } + bool idaapi operator == (const edge_layout_point_t &r) const + { + return pidx == r.pidx && e == r.e; + } + bool idaapi operator != (const edge_layout_point_t &r) const + { + return !(*this == r); + } +}; + +/// Element of a graph selection - could be a node or edge layout point. +/// See ::screen_graph_selection_t. +struct selection_item_t +{ + bool is_node; ///< represents a selected node? + int node; ///< node number (is_node = true) + edge_layout_point_t elp; ///< edge layout point (is_node = false) + idaapi selection_item_t(void) : is_node(false), node(-1) {} + idaapi selection_item_t(int n) : is_node(true), node(n) {} + idaapi selection_item_t(edge_layout_point_t &_elp) + : is_node(false), node(-1), elp(_elp) {} + idaapi selection_item_t(edge_t e, int idx) + : is_node(false), node(-1), elp(e, idx) {} + idaapi selection_item_t(class graph_item_t &); + int idaapi compare(const selection_item_t &r) const + { + if ( is_node != r.is_node ) + return is_node - r.is_node; + if ( is_node ) + return ::compare(node, r.node); + return elp.compare(r.elp); + } + bool idaapi operator == (const selection_item_t &r) const + { return compare(r) == 0; } + bool idaapi operator != (const selection_item_t &r) const + { return compare(r) != 0; } + bool idaapi operator < (const selection_item_t &r) const + { return compare(r) < 0; } +}; + + +/// Selection in a graph. +/// (A list of nodes and edge layout points). +/// This selection is used to move a subgraph on the screen. +typedef qvector<selection_item_t> screen_graph_selection_base_t; + +struct screen_graph_selection_t : public screen_graph_selection_base_t +{ + bool idaapi has(const selection_item_t &item) const + { return (const_iterator)find(item) != end(); } + void idaapi add(const screen_graph_selection_t &s) + { + for ( screen_graph_selection_t::const_iterator p=s.begin(); p != s.end(); ++p ) + add_unique(*p); + } + void idaapi sub(const screen_graph_selection_t &s) + { + for ( screen_graph_selection_t::const_iterator p=s.begin(); p != s.end(); ++p ) + del(*p); + } + void idaapi add_node(int node) { add_unique(selection_item_t(node)); } + void idaapi del_node(int node) { del(selection_item_t(node)); } + void idaapi add_point(edge_t e, int idx) { add_unique(selection_item_t(e, idx)); } + void idaapi del_point(edge_t e, int idx) { del(selection_item_t(e, idx)); } + + size_t idaapi nodes_count() const { return items_count(true); } + size_t idaapi points_count() const { return items_count(false); } + size_t idaapi items_count(bool look_for_nodes) const + { + size_t cnt = 0; + for ( size_t i = 0, sz = size(); i < sz; ++i ) + if ( at(i).is_node == look_for_nodes ) + ++cnt; + return cnt; + } +}; + +/// Sub-segment of a graph edge +struct edge_segment_t +{ + edge_t e; + int nseg; + int x0, x1; + size_t idaapi length(void) const { return abs(x1-x0); } + bool idaapi toright(void) const { return x1 > x0; } // horizontal segment to the right + bool idaapi operator < (const edge_segment_t &r) const + { + return e < r.e; +/* // longest edges first + int ll = x1 - x0; if ( ll < 0 ) ll = -ll; + int rl = r.x1 - r.x0; if ( rl < 0 ) rl = -rl; + if ( rl < ll ) + return true; + if ( rl == ll ) + return e < r.e; + return false;*/ + } +}; + +//--------------------------------------------------------------------------- +/// See ::graph_item_t +enum graph_item_type_t +{ // valid graph_item_t fields: + git_none, ///< nothing + git_edge, ///< edge (graph_item_t::e, graph_item_t::n. n is farthest edge endpoint) + git_node, ///< node title (graph_item_t::n) + git_tool, ///< node title button (graph_item_t::n, graph_item_t::b) + git_text, ///< node text (graph_item_t::n, graph_item_t::p) + git_elp, ///< edge layout point (graph_item_t::elp) +}; + +/// Describes a sub-item of a graph +class graph_item_t +{ +public: + graph_item_type_t type; ///< type + edge_t e; ///< edge source and destination + int n; ///< node number + int b; ///< button number + point_t p; ///< text coordinates in the node + edge_layout_point_t elp; ///< edge layout point + bool operator == (const graph_item_t &r) const; + bool is_node(void) const { return type >= git_node && type <= git_text; } + bool is_edge(void) const { return type == git_edge || type == git_elp; } +}; + +//------------------------------------------------------------------------- +/// One dimensional range +struct interval_t +{ + int x0, x1; // x0 always <= x1, otherwise the interval is empty + bool empty(void) const { return x0 < x1; } + void intersect(const interval_t &r) + { + if ( x0 < r.x0 ) + x0 = r.x0; + if ( x1 > r.x1 ) + x1 = r.x1; + } + void make_union(const interval_t &r) + { + if ( x0 > r.x0 ) + x0 = r.x0; + if ( x1 < r.x1 ) + x1 = r.x1; + } + void move_by(int shift) + { + x0 += shift; + x1 += shift; + } + interval_t(void) : x0(0), x1(0) {} + interval_t(int y0, int y1) + { + x0 = qmin(y0, y1); + x1 = qmax(y0, y1); + } + interval_t(const edge_segment_t &s) + { + x0 = qmin(s.x0, s.x1); + x1 = qmax(s.x0, s.x1); + } + int length(void) const { return x1 - x0; } + bool contains(int x) const { return x0 <= x && x <= x1; } + bool operator ==(const interval_t &r) const { return x0 == r.x0 && x1 == r.x1; } + bool operator !=(const interval_t &r) const { return !(*this == r); } +}; + +//------------------------------------------------------------------------- +/// Organize graph nodes by row +struct row_info_t +{ + intvec_t nodes; ///< list of nodes at the row + int top; ///< top y coord of the row + int bottom; ///< bottom y coord of the row + int height(void) const { return bottom - top; } + row_info_t(void) : top(0), bottom(0) {} +}; +typedef qvector<row_info_t> graph_row_info_t; ///< vector of row infos + +static const int ygap = 30; +static const int xgap = 10; +static const int arrow_height = 10; +static const int arrow_width = 8; + +struct graph_location_info_t; +class graph_visitor_t; + +//------------------------------------------------------------------------- +/// Abstract graph interface +class abstract_graph_t : public gdl_graph_t +{ + void idaapi find_entries(node_set_t &entries) const; + void idaapi depth_first(int root, struct depth_first_info_t &di) const; + size_t idaapi remove_reachable(int n, node_set_t *s) const; + int idaapi longest_path(int n, intvec_t &tops, int row_height) const; + size_t idaapi sort_layer_nodes( + const row_info_t &r1, + const intmap_t &lpi1, + row_info_t &r2, + intmap_t &lpi2, + bool ispred) const; + size_t idaapi calc_cross_num( + const intvec_t &r1, + const intvec_t &r2, + const intmap_t &lpi1, + bool ispred) const; + size_t idaapi num_crossings(const graph_row_info_t &gri, const array_of_intmap_t &nodepi) const; + int idaapi calc_x_coord(const row_info_t &ri, int idx, bool ispred, int first_added_node) const; + void idaapi try_move_down(intvec_t &tops, int n, int row_height) const; + +protected: + /// Returns one entry point for each connected component + void idaapi get_connected_components(intvec_t &entries) const; + + /// Find longest paths from the entries. take into account node heights. + /// if row_height > 0, then use it instead of real node heights. + /// return max distance found + int idaapi calc_longest_pathes( + const node_set_t &entries, + intvec_t &tops, + int row_height) const; + + /// Move entry nodes down as much as possible + void idaapi move_nodes_down( + intvec_t &tops, + const node_ordering_t &post, + int first_reverser_node, + int row_height) const; + + /// Create graph row info from 'tops' + void idaapi create_graph_row_info( + const intvec_t &tops, + graph_row_info_t &gri, + int graph_height) const; + + /// Calculate height of each row + void idaapi calc_row_heights(graph_row_info_t &gri) const; + + /// Minimize crossings + void idaapi minimize_crossings(graph_row_info_t &gri) const; + + /// Calculate x coords of all nodes + void idaapi set_x_coords( + const graph_row_info_t &gri, + const node_set_t &selfrefs, + int first_added_node); + + /// Gather information about all edge segments + void idaapi gather_edge_segments( + const graph_row_info_t &gri, + edge_segs_vec_t &ges) const; + + /// Make all edges rectangular + void idaapi make_rect_edges( + graph_row_info_t &gri, + const edge_segs_vec_t &ges, + int first_reverser_node); + + /// Assign ports to edges + void idaapi assign_edge_ports( + const graph_row_info_t &gri, + const node_set_t &selfrefs); + + /// Recalculate width of all edges + void idaapi recalc_edge_widths( + const edgeset_t &back_edges, + const edge_infos_t &self_edges); + + /// Clear layout information in the graph + void idaapi clear_layout_info(void); + + void idaapi depth_first( + node_ordering_t *pre, + node_ordering_t *post, + edge_typer_t *et) const; + + void idaapi create_spanning_tree( + edge_typer_t *et, + node_set_t *entries, + edgeset_t *back_edges, + node_ordering_t *pre, + node_ordering_t *post) const; + + void idaapi tree_layout(edge_typer_t &et, const node_set_t &entries); + + /// Is there a path from M to N which terminates with a back edge to N? + bool idaapi path_back(const array_of_node_set_t &domin, int m, int n) const; + bool idaapi path_back(edge_typer_t &et, int m, int n) const; + + /// Visit nodes starting from 'node', depth first + int idaapi visit_nodes(int node, graph_node_visitor_t &gv) const; + + /// Visit all possible paths starting from 'node'. + /// A path cannot contain the same node twice. + int idaapi visit_paths(int node, graph_path_visitor_t &gv) const; + +public: + qstring title; ///< graph title + bool rect_edges_made; ///< have create rectangular edges? + layout_type_t current_layout; ///< see \ref layout_ + point_t circle_center; ///< for layout_circle + int circle_radius; ///< for layout_circle + hook_cb_t *callback; ///< user-defined callback + void *callback_ud; ///< user data for #callback + + idaapi abstract_graph_t(void) + : rect_edges_made(false), + current_layout(layout_none), + circle_radius(0), + callback(NULL), + callback_ud(NULL) + {} + virtual ~abstract_graph_t() {} + void idaapi clear(void); + void idaapi dump_graph(const char *header) const; + bool idaapi calc_bounds(rect_t *r); + void idaapi calc_fitting_params( + const rect_t &area, + const rect_t &r, + graph_location_info_t *gli, + double max_zoom); + bool idaapi calc_fitting_params( + const rect_t &area, + graph_location_info_t *gli, + double max_zoom); + int idaapi for_all_nodes_edges(graph_visitor_t &nev, bool visit_nodes=true); + // get edge ports - fills s, d arguments and returns edge_info_t + const edge_info_t *idaapi get_edge_ports( + edge_t e, + point_t &s, + point_t &d) const; + // add edges from/to the node + void idaapi add_node_edges(edgevec_t &dlist, int node); + const rect_t &idaapi nrect(int n) const + { return (CONST_CAST(abstract_graph_t *)(this))->nrect(n); } + const edge_info_t *idaapi get_edge(edge_t e) const + { return (CONST_CAST(abstract_graph_t *)(this))->get_edge(e); } + virtual rect_t &idaapi nrect(int n) = 0; + virtual edge_info_t *idaapi get_edge(edge_t e) = 0; + virtual abstract_graph_t *idaapi clone(void) const = 0; + + bool idaapi create_tree_layout(void); + bool idaapi create_circle_layout(point_t p, int radius); + bool idaapi create_polar_tree_layout(point_t p, int radius); + bool idaapi create_radial_tree_layout(point_t p, int radius); + bool idaapi create_orthogonal_layout(void); + + void set_callback(hook_cb_t *_callback, void *_ud) + { + callback = _callback; + callback_ud = _ud; + } + ssize_t vgrcall(int code, va_list va) + { + if ( callback != NULL ) + return callback(callback_ud, code, va); + return 0; + } + ssize_t grcall(int code, ...) + { + va_list va; + va_start(va, code); + ssize_t result = vgrcall(code, va); + va_end(va); + return result; + } +}; + +/// For some reason GCC insists on putting the vtable into object files, +/// even though we only use ::mutable_graph_t by pointer. +/// This looks like a linker bug. We fix it by declaring functions as pure virtual +/// when plugins are compiled. +#if defined(__GNUC__) && (defined(__KERNEL__) || !defined(__UI__)) // compiling a plugin or the kernel with gcc? +#define GCC_PUREVIRT = 0 +#else +#define GCC_PUREVIRT +#endif + +//------------------------------------------------------------------------- +struct edge_infos_wrapper_t +{ + edge_infos_wrapper_t(); + edge_infos_wrapper_t(const edge_infos_wrapper_t &other); + edge_infos_wrapper_t &idaapi operator=(const edge_infos_wrapper_t &other); + ~edge_infos_wrapper_t() { clear(); } + void clear(); + + edge_infos_t *ptr; +}; + +#ifdef _DEBUG +#define CHKNODEIDX(n) QASSERT(1385, int(n) >= 0) +#else +#define CHKNODEIDX(n) +#endif + +/// The base class used to display graphs in IDA. +/// +/// The mutable_graph_t introduces the following notions on top of +/// the ones that parent classes already provide: +/// * ability to add/remove nodes +/// * ability to add/remove edges +/// * grouping/ungrouping nodes +/// * expanding/collapsing existing groups +/// +/// While the adding/removing of nodes & edges is, in itself, a fairly +/// straightforward notion, 'groups' can be a bit more tricky to +/// figure out. +/// +/// For the purpose of illustrating what 'groups' are, and how they +/// are handled, let's assume that we are analyzing a binary that +/// contains multiple bits of connected information scattered all over +/// the place in a read-only '.rodata' segment. +/// +/// In order to simplify analysis that scattered-but-connected data, +/// the user might choose to write a small plugin that represents the +/// data in a graph form: +/// +/// +-----------------------------+ +/// | Driver object #1 | +/// | address: 0x400100 | +/// | size: 0x200 bytes | +/// +-------------+---------------+ +/// | +/// +------------------------+ +/// | +/// +-----------+-----------------+ +/// | Driver object #2 | +/// | address: 0x407380 | +/// | size: 0x180 bytes | +/// | (seems to maintain state of | +/// | the I/O ports) | +/// +----+-------+----------------+ +/// | | +/// +---------------+ +----------------+ +/// | | +/// +-------------+-----------+ +-------+-------------+ +/// | Unknown object #1 | | Driver object #3 | +/// | address: 0x404100 | | address: 0x402000 | +/// | size: 0x80 bytes | | size: 4KB | +/// | (credentials?) | | (mostly mutexes) | +/// +-------------------------+ +---------------------+ +/// +/// In this case, the graph has 4 nodes, each showing some information +/// that is relevant to the analyst. +/// In order to implement this, the plugin must keep, somewhere in +/// memory, the relevant information about the nodes. In this case, it +/// would have a set of 4 items, from which the nodes texts can be +/// generated and provided back to IDA's UI. +/// +/// If one was to call the following methods on the mutable_graph_t +/// instance that is being displayed by IDA, one would get: +/// +/// mutable_graph_t::size() -> 4 +/// mutable_graph_t::node_qty() -> 4 +/// +/// Let's now assume the user decides the 2 first nodes are not +/// that interesting after all, and groups them together, in a node +/// labeled "irrelevant". +/// +/// Then, IDA will modify the mutable_graph_t by adding it a 5th node, +/// which represents that group +/// It's worth pointing out that, it's the mutable_graph_t itself +/// that's doing all the bookkeeping about the groups: the user plugin +/// doesn't need to do anything at all +/// +/// In addition, calling the methods above now yields: +// +/// mutable_graph_t::size() -> 5 +/// mutable_graph_t::node_qty() -> 3 +/// +class mutable_graph_t : public abstract_graph_t +{ + typedef abstract_graph_t inherited; + friend ssize_t idaapi graph_dispatcher(void *, int code, va_list va); + int idaapi _find_subgraph_node(int group, int n) const; + void idaapi collapse_edges(const intvec_t &nodes, int group); + void idaapi del_node_keep_edges(int n); + void idaapi add_dest(destset_t &ne, edge_t e, int g); + void idaapi reverse_edges( + const edgeset_t &back_edges, + edge_infos_t &self_edges, + node_set_t &entries); + void idaapi layout_self_reference_edges(const edge_infos_t &selfrefs); + void idaapi restore_edges(int first_reserver_node, bool failed); + + void idaapi add_layer_nodes(graph_row_info_t &gri, intvec_t &tops); + void idaapi del_layer_nodes(graph_row_info_t &gri, int first_added_node); + void idaapi fix_collapsed_group_edges(void); + +public: + uval_t gid; ///< graph id - unique for the database + ///< for flowcharts it is equal to the function start_ea + intvec_t belongs; ///< the subgraph the node belongs to + ///< INT_MAX means that the node doesn't exist + ///< sign bit means collapsed node + bytevec_t node_flags; ///< node flags +#define MTG_GROUP_NODE 0x01 ///< is group node? +#define MTG_DOT_NODE 0x02 ///< is dot node? +#define MTG_NON_DISPLAYABLE_NODE 0x08 ///< for disassembly graphs - non-displayable nodes have a visible + ///< area that is too large to generate disassembly lines for without + ///< IDA slowing down significantly (see MAX_VISIBLE_NODE_AREA) + + // groups: original edges without considering any group info + array_of_intvec_t org_succs; + array_of_intvec_t org_preds; + + array_of_intvec_t succs; + array_of_intvec_t preds; + typedef qvector<rect_t> node_layout_t; + node_layout_t nodes; + edge_infos_wrapper_t edges; + + idaapi mutable_graph_t(uval_t id); + idaapi mutable_graph_t(const abstract_graph_t &g, uval_t id); + virtual ~mutable_graph_t() {} + + /// Get the total number of nodes (including group nodes, and + /// including hidden nodes.) + /// + /// See also node_qty() + /// + /// \return the total number of nodes in the graph + virtual int idaapi size(void) const override { return int(succs.size()); } + + /// Get the number of visible nodes (the list can be retrieved using + /// gdl.hpp's node_iterator) + /// + /// See also size() + /// + /// \return the number of visible nodes + virtual int idaapi node_qty(void) const override; + + /// Clears all nodes & edges information in this instance + /// (does not remove node_info_t stored in the database.) + void idaapi clear(void); + + /// Is the graph (visually) empty? + /// \return true if there are no visible nodes + virtual bool idaapi empty(void) const override; + + /// Is the node visible? + /// + /// \param node the node number + /// \return success + virtual bool idaapi exists(int node) const override { return is_visible_node(node); } +#define COLLAPSED_NODE 0x80000000 + + /// Get the node that currently visually represents 'node'. + /// This will find the "closest" parent group node that's visible, + /// by attempting to walk up the group nodes that contain + /// 'node', and will stop when it finds a node that is currently + /// visible. + /// + /// See also get_group_node() + // + /// \param node the node + /// \return the node that represents 'node', or 'node' if it's not + /// part of any group + int idaapi get_node_representative(int node); + + int idaapi get_node_group(int node) const { CHKNODEIDX(node); return (belongs[node] & ~COLLAPSED_NODE); } + void idaapi set_node_group(int node, int group) { CHKNODEIDX(node); belongs[node] = group | (belongs[node] & COLLAPSED_NODE); } + bool idaapi is_deleted_node(int node) const { CHKNODEIDX(node); return belongs[node] == INT_MAX; } + void idaapi set_deleted_node(int node) { CHKNODEIDX(node); belongs[node] = INT_MAX; } + bool idaapi is_subgraph_node(int node) const { return get_node_group(node) != node; } + bool idaapi is_dot_node(int node) const { CHKNODEIDX(node); return (node_flags[node] & MTG_DOT_NODE) != 0; } + bool idaapi is_group_node(int node) const { CHKNODEIDX(node); return (node_flags[node] & MTG_GROUP_NODE) != 0; } + bool idaapi is_displayable_node(int node) const { CHKNODEIDX(node); return (node_flags[node] & MTG_NON_DISPLAYABLE_NODE) == 0; } + bool idaapi is_simple_node(int node) const { return !is_group_node(node); } + bool idaapi is_collapsed_node(int node) const { CHKNODEIDX(node); return (belongs[node] & COLLAPSED_NODE) != 0; } + bool idaapi is_uncollapsed_node(int node) const { return is_group_node(node) && !is_collapsed_node(node); } + + /// Is the node currently visible? + /// + /// An invisible node is a node that's part of a group that's + /// currently collapsed. + /// + /// \param node the node + /// \return success + bool idaapi is_visible_node(int node) const; + + /// Is there any group node in the graph? + /// + /// \return success + bool idaapi groups_are_present(void) const; + + // iterate subgraph nodes, return -1 at the end + int idaapi get_first_subgraph_node(int group) const { return _find_subgraph_node(group, 0); } + int idaapi get_next_subgraph_node(int group, int current) const { return _find_subgraph_node(group, current+1); } + void idaapi insert_visible_nodes(intvec_t &nodes, int group) const; + void idaapi insert_simple_nodes(intvec_t &nodes, int group) const; + bool idaapi check_new_group(const intvec_t &nodes, intvec_t &refined); + + /// Create a new group node, that will contain all the nodes in + /// 'nodes'. + /// + /// \param nodes the nodes that will be part of the group + /// \return the group node, or -1 in case of error + int idaapi create_group(const intvec_t &nodes); + + /// Delete a group node. + /// + /// This deletes the group node only; it does not delete nodes that + /// are part of the group. + /// + /// \param group the group node + /// \return success + bool idaapi delete_group(int group); + + /// Expand/collapse a group node + /// + /// \param group the group node + /// \param expand whether to expand or collapse + /// \return success + bool idaapi change_group_visibility(int group, bool expand); + + /// Change visibility of multiple group nodes + /// + /// \param nodes the group nodes + /// \param expand whether to expand or collapse + /// \return success (true if any group node was modified) + bool idaapi change_visibility(const intvec_t &nodes, bool expand); + + virtual int idaapi nsucc(int b) const override { CHKNODEIDX(b); return (int)succs[b].size(); } + virtual int idaapi npred(int b) const override { CHKNODEIDX(b); return (int)preds[b].size(); } + virtual int idaapi succ(int b, int i) const override { CHKNODEIDX(b); return succs[b][i]; } + virtual int idaapi pred(int b, int i) const override { CHKNODEIDX(b); return preds[b][i]; } + const intvec_t &idaapi succset(int b) const { CHKNODEIDX(b); return succs[b]; } + const intvec_t &idaapi predset(int b) const { CHKNODEIDX(b); return preds[b]; } + + void idaapi reset(void) { resize(0); } + + /// Recompute the layout, according to the value of + /// 'current_layout'. + /// + /// \return success + virtual bool idaapi redo_layout(void) GCC_PUREVIRT; + + /// Resize the graph to 'n' nodes + /// + /// \param n the new size + virtual void idaapi resize(int n) GCC_PUREVIRT; + + /// Add a node, possibly with a specific geometry + /// + /// \param r the node geometry (can be nullptr) + /// \return the new node + virtual int idaapi add_node(const rect_t *r) GCC_PUREVIRT; + + /// Delete a node + /// + /// \param n the node to delete + /// \return the number of deleted edges + virtual ssize_t idaapi del_node(int n) GCC_PUREVIRT; // returns number of deleted edges + + virtual bool idaapi add_edge(int i, int j, const edge_info_t *ei) GCC_PUREVIRT; + virtual bool idaapi del_edge(int i, int j) GCC_PUREVIRT; // true: found and deleted the edge + virtual bool idaapi replace_edge(int i, int j, int x, int y) GCC_PUREVIRT; + + /// Refresh the graph + /// + /// A graph needs refreshing when it's "backing data". E.g., if the + /// number (or contents) of the objects in the above example, + /// change. + /// + /// Let's say the user's plugin ends up finding a 5th piece of + /// scattered data. It should then add it to its internal list + /// of known objects, and tell IDA that the graph needs to be + /// refreshed, using refresh_viewer(). + /// This will cause IDA to: + /// - discard all its internal rendering information, + /// - call mutable_graph_t::refresh() on the graph so that the + /// user's plugin has a chance to "sync" the number of nodes & + /// edges that this graph contains, to the information that the + /// plugin has collected so far + /// - re-create internal rendering information, and + /// - repaint the view + /// + /// \return success + virtual bool idaapi refresh(void) GCC_PUREVIRT; + + virtual mutable_graph_t *idaapi clone(void) const override GCC_PUREVIRT; + + // get node rectangle + const rect_t &idaapi nrect(int n) const + { return (CONST_CAST(mutable_graph_t *)(this))->nrect(n); } + virtual rect_t &idaapi nrect(int n) override; + virtual edge_info_t *idaapi get_edge(edge_t e) override GCC_PUREVIRT; + + virtual bool idaapi set_nrect(int n, const rect_t &r) GCC_PUREVIRT; + virtual bool idaapi set_edge(edge_t e, const edge_info_t *ei) GCC_PUREVIRT; + + bool idaapi create_digraph_layout(void); + + void idaapi del_custom_layout(void); + bool idaapi get_custom_layout(void); + void idaapi set_custom_layout(void) const; + bool idaapi get_graph_groups(void); + void idaapi set_graph_groups(void) const; + virtual ea_t idaapi calc_group_ea(const intvec_t & /*nodes*/) newapi { return BADADDR; } + + point_t idaapi calc_center_of(const intvec_t &nodes) const; + void idaapi move_to_same_place(const intvec_t &collapsing_nodes, point_t p); + void idaapi move_grouped_nodes(const intvec_t &groups, const mutable_graph_t *ng); + + virtual bool idaapi is_user_graph() newapi { return false; } +}; + +//------------------------------------------------------------------------- +/// Visit all nodes and edges in a graph +class graph_visitor_t +{ +protected: + abstract_graph_t *g; + virtual int idaapi visit_node(int n, rect_t &r) = 0; + virtual int idaapi visit_edge(edge_t e, edge_info_t *ei) = 0; + friend int idaapi abstract_graph_t::for_all_nodes_edges(graph_visitor_t &nev, bool visit_nodes); +}; + +//------------------------------------------------------------------------- +/// Graph notification codes +enum graph_notification_t +{ + // Callbacks called by IDA (plugins can hook to them): + + grcode_calculating_layout, ///< calculating user-defined graph layout. + ///< \param g (::mutable_graph_t *) + ///< \retval 0 not implemented + ///< \retval 1 graph layout calculated by the plugin + + grcode_layout_calculated, ///< graph layout calculated. + ///< \param g (::mutable_graph_t *) + ///< \param layout_succeeded (bool) + ///< \retval 0 must return 0 + + grcode_changed_graph, ///< new graph has been set. + ///< \param g (::mutable_graph_t *) + ///< \retval 0 must return 0 + + grcode_reserved, + + grcode_clicked, ///< graph is being clicked. + ///< this callback allows you to ignore some clicks. + ///< it occurs too early, internal graph variables are not updated yet. + ///< current_item1, current_item2 point to the same thing. + ///< item2 has more information. + ///< see also: ::custom_viewer_click_t + ///< \param gv (::graph_viewer_t *) + ///< \param current_item1 (::selection_item_t *) + ///< \param current_item2 (::graph_item_t *) + ///< \retval 0 ok + ///< \retval 1 ignore click + + grcode_dblclicked, ///< a graph node has been double clicked. + ///< \param gv (::graph_viewer_t *) + ///< \param current_item (::selection_item_t *) + ///< \retval 0 ok + ///< \retval 1 ignore click + + grcode_creating_group, ///< a group is being created. + ///< this provides an opportunity for the + ///< graph to forbid creation of the group. + ///< Note that groups management is done by the + ///< mutable_graph_t instance itself: there is + ///< no need to modify the graph in this callback. + ///< \param g (::mutable_graph_t *) + ///< \param nodes (::intvec_t *) + ///< \retval 0 ok + ///< \retval 1 forbid group creation + + grcode_deleting_group, ///< a group is being deleted. + ///< this provides an opportunity for the + ///< graph to forbid deletion of the group. + ///< Note that groups management is done by the + ///< mutable_graph_t instance itself: there is + ///< no need to modify the graph in this callback. + ///< \param g (::mutable_graph_t *) + ///< \param old_group (int) + ///< \retval 0 ok + ///< \retval 1 forbid group deletion + + grcode_group_visibility, ///< a group is being collapsed/uncollapsed + ///< this provides an opportunity for the graph + ///< to forbid changing the visibility of the group. + ///< Note that groups management is done by the + ///< mutable_graph_t instance itself: there is + ///< no need to modify the graph in this callback. + ///< \param g (::mutable_graph_t *) + ///< \param group (int) + ///< \param expand (bool) + ///< \retval 0 ok + ///< \retval 1 forbid group modification + + grcode_gotfocus, ///< a graph viewer got focus. + ///< \param gv (::graph_viewer_t *) + ///< \retval 0 must return 0 + + grcode_lostfocus, ///< a graph viewer lost focus. + ///< \param gv (::graph_viewer_t *) + ///< \retval 0 must return 0 + + grcode_user_refresh, ///< refresh user-defined graph nodes and edges + ///< This is called when the UI considers that it is + ///< necessary to recreate the graph layout, and thus + ///< has to ensure that the 'mutable_graph_t' instance + ///< it is using, is up-to-date. + ///< For example: + ///< - at graph creation-time + ///< - if a refresh_viewer() call was made + ///< \param g (::mutable_graph_t *) + ///< \return success + + grcode_reserved2, + + grcode_user_text, ///< retrieve text for user-defined graph node. + ///< NB: do not use anything calling GDI! + ///< \param g (::mutable_graph_t *) + ///< \param node (int) + ///< \param result (const char **) + ///< \param bg_color (::bgcolor_t *) may be NULL + ///< \return success, result must be filled + + grcode_user_size, ///< calculate node size for user-defined graph. + ///< \param g (::mutable_graph_t *) + ///< \param node (int) + ///< \param cx (int *) + ///< \param cy (int *) + ///< \retval 0 did not calculate. ida will use node text size + ///< \retval 1 calculated. ida will add node title to the size + + grcode_user_title, ///< render node title of a user-defined graph. + ///< \param g (::mutable_graph_t *) + ///< \param node (int) + ///< \param title_rect (::rect_t *) + ///< \param title_bg_color (int) + ///< \param dc (HDC) + ///< \retval 0 did not render, ida will fill it with title_bg_color + ///< \retval 1 rendered node title + + grcode_user_draw, ///< render node of a user-defined graph. + ///< NB: draw only on the specified DC and nowhere else! + ///< \param g (::mutable_graph_t *) + ///< \param node (int) + ///< \param node_rect (::rect_t *) + ///< \param dc (HDC) + ///< \retval 0 not rendered + ///< \retval 1 rendered + + grcode_user_hint, ///< retrieve hint for the user-defined graph. + ///< \param g (::mutable_graph_t *) + ///< \param mousenode (int) + ///< \param mouseedge_src (int) + ///< \param mouseedge_dst (int) + ///< \param hint (char **) must be allocated by qalloc() or qstrdup() + ///< \retval 0 use default hint + ///< \retval 1 use proposed hint + + grcode_destroyed, ///< graph is being destroyed. Note that this doesn't mean + ///< the graph viewer is being destroyed; this only means + ///< that the graph that is being displayed by it is being + ///< destroyed, and that, e.g., any possibly cached data should + ///< be invalidated (this event can happen when, for example, + ///< the user decides to group nodes together: that operation + ///< will effectively create a new graph, that will replace + ///< the old one.) + ///< To be notified when the graph viewer itself is being destroyed, + ///< please see notification 'view_close', in kernwin.hpp + ///< \param g (::mutable_graph_t *) + ///< \retval 0 must return 0 + + //------------------------------------------------------------------------- + // Callbacks callable from plugins (see inline functions below): + //------------------------------------------------------------------------- + + // graph_viewer_t (or IDA View graph) manipulation. + grcode_create_graph_viewer = 256, ///< use create_graph_viewer() + grcode_get_graph_viewer, ///< use get_graph_viewer() + grcode_get_viewer_graph, ///< use get_viewer_graph() + grcode_create_mutable_graph, ///< use create_mutable_graph() + grcode_set_viewer_graph, ///< use set_viewer_graph() + grcode_refresh_viewer, ///< use refresh_viewer() + grcode_fit_window, ///< use viewer_fit_window() + grcode_get_curnode, ///< use viewer_get_curnode() + grcode_center_on, ///< use viewer_center_on() + grcode_get_selection, ///< use viewer_get_selection() + + // mutable_graph_t (and abstract_graph_t) manipulation. + grcode_del_custom_layout, ///< use mutable_graph_t::del_custom_layout() + grcode_set_custom_layout, ///< use mutable_graph_t::set_custom_layout() + grcode_set_graph_groups, ///< use mutable_graph_t::set_graph_groups() + grcode_clear, ///< use mutable_graph_t::clear() + grcode_create_digraph_layout, ///< use mutable_graph_t::create_digraph_layout() + grcode_create_tree_layout, ///< use abstract_graph_t::create_tree_layout() + grcode_create_circle_layout, ///< use abstract_graph_t::create_circle_layout() + grcode_get_node_representative, ///< use mutable_graph_t::get_node_representative() + grcode_find_subgraph_node, ///< use mutable_graph_t::_find_subgraph_node() + grcode_create_group, ///< use mutable_graph_t::create_group() + grcode_get_custom_layout, ///< use mutable_graph_t::get_custom_layout() + grcode_get_graph_groups, ///< use mutable_graph_t::get_graph_groups() + grcode_empty, ///< use mutable_graph_t::empty() + grcode_is_visible_node, ///< use mutable_graph_t::is_visible_node() + grcode_delete_group, ///< use mutable_graph_t::delete_group() + grcode_change_group_visibility, ///< use mutable_graph_t::change_group_visibility() + grcode_set_edge, ///< use mutable_graph_t::set_edge() + grcode_node_qty, ///< use mutable_graph_t::node_qty() + grcode_nrect, ///< use mutable_graph_t::nrect() + + // More graph_viewer_t manipulation. + grcode_set_titlebar_height, ///< use viewer_set_titlebar_height() + grcode_create_user_graph_place, ///< use create_user_graph_place() + grcode_create_disasm_graph1, ///< use create_disasm_graph(ea_t ea) + grcode_create_disasm_graph2, ///< use create_disasm_graph(const rangevec_t &ranges) + grcode_set_node_info, ///< use viewer_set_node_info() + grcode_get_node_info, ///< use viewer_get_node_info() + grcode_del_node_info, ///< use viewer_del_node_info() + + // Deprecated. Those were meant to work with intset_t, that we now got rid of. + grcode_viewer_create_groups, + grcode_viewer_delete_groups, + grcode_viewer_groups_visibility, + + // + grcode_viewer_create_groups_vec, ///< use viewer_create_groups() + grcode_viewer_delete_groups_vec, ///< use viewer_delete_groups() + grcode_viewer_groups_visibility_vec,///< use viewer_set_groups_visibility() + grcode_delete_mutable_graph, ///< use delete_mutable_graph() + grcode_edge_infos_wrapper_copy, ///< use edge_infos_wrapper_t::operator=() + grcode_edge_infos_wrapper_clear, ///< use edge_infos_wrapper_t::clear() + + // + grcode_attach_menu_item, + + // + grcode_set_gli, ///< use viewer_set_gli() + grcode_get_gli, ///< use viewer_get_gli() +}; + + +//------------------------------------------------------------------------- +#ifndef SWIG +/// \name grentry +/// IDA designates a function for handling graph operations (::grentry). +/// This function accepts a notification code (::graph_notification_t), +/// along with a list of relevant arguments, and handles the action appropriately +/// (similar to ::callui in kernwin.hpp). +//@{ + + +inline ssize_t grentry(graph_notification_t event_code, ...) +{ + va_list va; + va_start(va, event_code); + ssize_t code = invoke_callbacks(HT_GRAPH, event_code, va); + va_end(va); + return code; +} +//@} +#endif + + +//------------------------------------------------------------------------- +struct group_crinfo_t +{ + intvec_t nodes; + qstring text; +}; +typedef qvector<group_crinfo_t> groups_crinfos_t; + +#ifndef __UI__ + +typedef TWidget graph_viewer_t; ///< graph view opaque structure + + +/// Create a custom graph viewer. +/// \param title the widget title +/// \param id graph id +/// \param callback callback to handle graph notifications +/// (::graph_notification_t) +/// \param ud user data passed to callback +/// \param title_height node title height +/// \return new viewer + +inline graph_viewer_t *idaapi create_graph_viewer( + const char *title, + uval_t id, + hook_cb_t *callback, + void *ud, + int title_height, + TWidget *parent=NULL) +{ + graph_viewer_t *gv = NULL; + grentry(grcode_create_graph_viewer, title, &gv, id, callback, ud, title_height, parent); + return gv; +} + + +/// Get custom graph viewer for given form + +inline graph_viewer_t *idaapi get_graph_viewer(TWidget *parent) { graph_viewer_t *gv = NULL; grentry(grcode_get_graph_viewer, parent, &gv); return gv; } + + +/// Create a new empty graph with given id + +inline mutable_graph_t *idaapi create_mutable_graph(uval_t id) { mutable_graph_t *g = NULL; grentry(grcode_create_mutable_graph, id, &g); return g; } + + +/// Create a graph for the function that contains 'ea' + +inline mutable_graph_t *idaapi create_disasm_graph(ea_t ea) { mutable_graph_t *g = NULL; grentry(grcode_create_disasm_graph1, ea, &g); return g; } + + +/// Create a graph using an arbitrary set of ranges + +inline mutable_graph_t *idaapi create_disasm_graph(const rangevec_t &ranges) { mutable_graph_t *g = NULL; grentry(grcode_create_disasm_graph2, &ranges, &g); return g; } + + +/// Get graph object for given custom graph viewer + +inline mutable_graph_t *idaapi get_viewer_graph(graph_viewer_t *gv) { mutable_graph_t *g = NULL; grentry(grcode_get_viewer_graph, gv, &g); return g; } + + +/// Set the underlying graph object for the given viewer + +inline void idaapi set_viewer_graph(graph_viewer_t *gv, mutable_graph_t *g) { grentry(grcode_set_viewer_graph, gv, g); } + + +/// Redraw the graph in the given view + +inline void idaapi refresh_viewer(graph_viewer_t *gv) { grentry(grcode_refresh_viewer, gv); } + + +/// Fit graph viewer to its parent form + +inline void idaapi viewer_fit_window(graph_viewer_t *gv) { grentry(grcode_fit_window, gv); } + + +/// Get number of currently selected node (-1 if none) + +inline int idaapi viewer_get_curnode(graph_viewer_t *gv) { return grentry(grcode_get_curnode, gv); } + + +/// Center the graph view on the given node + +inline void idaapi viewer_center_on(graph_viewer_t *gv, int node) { grentry(grcode_center_on, gv, node); } + +/// Set location info for given graph view +/// If flags contains GLICTL_CENTER, then the gli will be set to be +/// the center of the view. Otherwise it will be the top-left. + +inline void idaapi viewer_set_gli( + graph_viewer_t *gv, + const graph_location_info_t *gli, + uint32 flags = 0) +{ + grentry(grcode_set_gli, gv, gli, flags); +} + + +/// Get location info for given graph view +/// If flags contains GLICTL_CENTER, then the gli that will be retrieved, will +/// be the one at the center of the view. Otherwise it will be the top-left. + +inline bool idaapi viewer_get_gli( + graph_location_info_t *out, + graph_viewer_t *gv, + uint32 flags = 0) +{ + return grentry(grcode_get_gli, out, gv, flags) == 0; +} + + +/// Set node info for node in given viewer (see set_node_info()) + +inline void idaapi viewer_set_node_info( + graph_viewer_t *gv, + int n, + const node_info_t &ni, + uint32 flags) +{ + grentry(grcode_set_node_info, gv, n, &ni, flags); +} + + +/// Get node info for node in given viewer (see get_node_info()) + +inline bool idaapi viewer_get_node_info( + graph_viewer_t *gv, + node_info_t *out, + int n) +{ + return grentry(grcode_get_node_info, gv, out, n) == 1; +} + + +/// Delete node info for node in given viewer (see del_node_info()) + +inline void idaapi viewer_del_node_info(graph_viewer_t *gv, int n) +{ + grentry(grcode_del_node_info, gv, n); +} + + +/// This will perform an operation similar to what happens when +/// a user manually selects a set of nodes, right-clicks and selects +/// "Create group". This is a wrapper around mutable_graph_t::create_group +/// that will, in essence: +/// - clone the current graph +/// - for each group_crinfo_t, attempt creating group in that new graph +/// - if all were successful, animate to that new graph. +/// \note this accepts parameters that allow creating +/// of multiple groups at once; which means only one graph +/// animation will be triggered. + +inline bool idaapi viewer_create_groups( + graph_viewer_t *gv, + intvec_t *out_group_nodes, + const groups_crinfos_t &gi) +{ + return grentry(grcode_viewer_create_groups_vec, gv, out_group_nodes, &gi) == 1; +} + + +/// Wrapper around mutable_graph_t::delete_group. +/// This function will: +/// - clone the current graph +/// - attempt deleting the groups in that new graph +/// - if successful, animate to that new graph. + +inline bool idaapi viewer_delete_groups( + graph_viewer_t *gv, + const intvec_t &groups, + int new_current = -1) +{ + return grentry(grcode_viewer_delete_groups_vec, gv, &groups, new_current) == 1; +} + + +/// Wrapper around mutable_graph_t::change_visibility. +/// This function will: +/// - clone the current graph +/// - attempt changing visibility of the groups in that new graph +/// - if successful, animate to that new graph. + +inline bool idaapi viewer_set_groups_visibility( + graph_viewer_t *gv, + const intvec_t &groups, + bool expand, + int new_current = -1) +{ + return grentry(grcode_viewer_groups_visibility_vec, gv, &groups, + expand, new_current) == 1; +} + + +/// Attach a previously-registered action to the view's context menu. +/// See kernwin.hpp for how to register actions. +/// \param name action name +/// \return success + +inline bool idaapi viewer_attach_menu_item(graph_viewer_t *g, const char *name) +{ + return grentry(grcode_attach_menu_item, g, name) != 0; +} + + +/// Get currently selected items for graph viewer + +inline bool idaapi viewer_get_selection( + graph_viewer_t *gv, + screen_graph_selection_t *sgs) +{ + return grentry(grcode_get_selection, gv, sgs) != 0; +} + + +/// Set height of node title bars (::grcode_set_titlebar_height) + +inline int idaapi viewer_set_titlebar_height(graph_viewer_t *gv, int height) +{ + return grentry(grcode_set_titlebar_height, gv, height); +} + + +/// Delete graph object. +/// \warning use this only if you are dealing with ::mutable_graph_t instances +/// that have not been used together with a ::graph_viewer_t. +/// If you have called set_viewer_graph() with your graph, the graph's +/// lifecycle will be managed by the viewer, and you shouldn't +/// interfere with it + +inline void idaapi delete_mutable_graph(mutable_graph_t *g) +{ + grentry(grcode_delete_mutable_graph, g); +} + + +inline void idaapi mutable_graph_t::del_custom_layout(void) { grentry(grcode_del_custom_layout, this); } +inline void idaapi mutable_graph_t::set_custom_layout(void) const { grentry(grcode_set_custom_layout, this); } +inline void idaapi mutable_graph_t::set_graph_groups(void) const { grentry(grcode_set_graph_groups, this); } +inline void idaapi mutable_graph_t::clear(void) { grentry(grcode_clear, this); } +inline bool idaapi mutable_graph_t::create_digraph_layout(void) { return grentry(grcode_create_digraph_layout, this) != 0; } +inline bool idaapi abstract_graph_t::create_tree_layout(void) { return grentry(grcode_create_tree_layout, this) != 0; } +inline bool idaapi abstract_graph_t::create_circle_layout(point_t c, int radius) { return grentry(grcode_create_circle_layout, this, c.x, c.y, radius) != 0; } +inline int idaapi mutable_graph_t::get_node_representative(int node) { return grentry(grcode_get_node_representative, this, node); } +inline int idaapi mutable_graph_t::_find_subgraph_node(int gr, int n) const { return grentry(grcode_find_subgraph_node, this, gr, n); } +inline int idaapi mutable_graph_t::create_group(const intvec_t &_nodes) { return grentry(grcode_create_group, this, &_nodes); } +inline bool idaapi mutable_graph_t::get_custom_layout(void) { return grentry(grcode_get_custom_layout, this) != 0; } +inline bool idaapi mutable_graph_t::get_graph_groups(void) { return grentry(grcode_get_graph_groups, this) != 0; } +inline bool idaapi mutable_graph_t::empty(void) const { return grentry(grcode_empty, this) != 0; } +inline bool idaapi mutable_graph_t::is_visible_node(int node) const { return grentry(grcode_is_visible_node, this, node) != 0; } +inline bool idaapi mutable_graph_t::delete_group(int group) { return grentry(grcode_delete_group, this, group) != 0; } +inline bool idaapi mutable_graph_t::change_group_visibility(int gr, bool exp) { return grentry(grcode_change_group_visibility, this, gr, exp) != 0; } +inline bool idaapi mutable_graph_t::set_edge(edge_t e, const edge_info_t *ei) { return grentry(grcode_set_edge, this, e.src, e.dst, ei) != 0; } +inline int idaapi mutable_graph_t::node_qty(void) const { return grentry(grcode_node_qty, this); } +inline rect_t &idaapi mutable_graph_t::nrect(int n) { rect_t *r; grentry(grcode_nrect, this, n, &r); return *r; } + +inline edge_infos_wrapper_t &idaapi edge_infos_wrapper_t::operator=( + const edge_infos_wrapper_t &other) +{ + grentry(grcode_edge_infos_wrapper_copy, this, &other); return *this; +} + +inline void edge_infos_wrapper_t::clear() +{ + grentry(grcode_edge_infos_wrapper_clear, this); +} + + + +/// Structure returned by get_custom_viewer_place() if the first +/// parameter is a graph viewer. +struct user_graph_place_t : public place_t +{ + int node; +}; + + +/// Get a copy of a ::user_graph_place_t (returns a pointer to static storage) + +inline user_graph_place_t *create_user_graph_place(int node, int lnnum) { user_graph_place_t *r; grentry(grcode_create_user_graph_place, node, lnnum, &r); return r; } + +#endif // UI + +#endif // __GRAPH_DEF_HPP diff --git a/idasdk76/include/help.h b/idasdk76/include/help.h new file mode 100644 index 0000000..8bf882e --- /dev/null +++ b/idasdk76/include/help.h @@ -0,0 +1,73 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _HELP_H +#define _HELP_H + +typedef int help_t; /* Help messages are referred by ints */ + +// Get pointer to message text by its message id +// The message texts are read from ida.hlp at the beginning +// Returns: pointer to message text (NULL is never returned by IDA) + +idaman THREAD_SAFE const char *ida_export itext(help_t msg_id); + +#ifdef __KERNWIN_HPP +GCC_DIAG_OFF(format-nonliteral); +NORETURN inline void Err(help_t format, ...) +{ + va_list va; + va_start(va, format); + verror(itext(format), va); + // NOTREACHED +} + +inline void Warn(help_t format, ...) +{ + va_list va; + va_start(va, format); + vwarning(itext(format), va); + va_end(va); +} + +inline void Info(help_t format, ...) +{ + va_list va; + va_start(va, format); + vinfo(itext(format), va); + va_end(va); +} + +inline int Message(help_t format,...) +{ + va_list va; + va_start(va, format); + int nbytes = vmsg(itext(format), va); + va_end(va); + return nbytes; +} + +inline int vask_yn(int deflt, help_t format, va_list va) +{ + return vask_yn(deflt, itext(format), va); +} + +inline int ask_yn(int deflt, help_t format, ...) +{ + va_list va; + va_start(va, format); + int code = vask_yn(deflt, itext(format), va); + va_end(va); + return code; +} +GCC_DIAG_ON(format-nonliteral); +#endif + +#ifndef NO_OBSOLETE_FUNCS +#endif + +#endif /* _HELP_H */ diff --git a/idasdk76/include/ida.hpp b/idasdk76/include/ida.hpp new file mode 100644 index 0000000..5e0f18b --- /dev/null +++ b/idasdk76/include/ida.hpp @@ -0,0 +1,1306 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _IDA_HPP +#define _IDA_HPP + +#include <pro.h> +#include <range.hpp> + +class plugin_t; +struct plugmod_t; + +/*! \file ida.hpp + + \brief Contains the ::inf structure definition and some + functions common to the whole IDA project. + + The ::inf structure is saved in the database and contains information + specific to the current program being disassembled. + Initially it is filled with values from ida.cfg. + + Although it is not a good idea to change values in ::inf + structure (because you will overwrite values taken from ida.cfg), + you are allowed to do it if you feel it necessary. + +*/ + +//-------------------------------------------------------------------------- +/// Known input file formats (kept in \inf{filetype}): +enum filetype_t +{ + f_EXE_old, ///< MS DOS EXE File + f_COM_old, ///< MS DOS COM File + f_BIN, ///< Binary File + f_DRV, ///< MS DOS Driver + f_WIN, ///< New Executable (NE) + f_HEX, ///< Intel Hex Object File + f_MEX, ///< MOS Technology Hex Object File + f_LX, ///< Linear Executable (LX) + f_LE, ///< Linear Executable (LE) + f_NLM, ///< Netware Loadable Module (NLM) + f_COFF, ///< Common Object File Format (COFF) + f_PE, ///< Portable Executable (PE) + f_OMF, ///< Object Module Format + f_SREC, ///< R-records + f_ZIP, ///< ZIP file (this file is never loaded to IDA database) + f_OMFLIB, ///< Library of OMF Modules + f_AR, ///< ar library + f_LOADER, ///< file is loaded using LOADER DLL + f_ELF, ///< Executable and Linkable Format (ELF) + f_W32RUN, ///< Watcom DOS32 Extender (W32RUN) + f_AOUT, ///< Linux a.out (AOUT) + f_PRC, ///< PalmPilot program file + f_EXE, ///< MS DOS EXE File + f_COM, ///< MS DOS COM File + f_AIXAR, ///< AIX ar library + f_MACHO, ///< Mac OS X + f_PSXOBJ, ///< Sony Playstation PSX object file +}; + +/// Is unstructured input file? +inline bool is_filetype_like_binary(filetype_t ft) +{ return ft == f_BIN || ft == f_HEX || ft == f_MEX || ft == f_SREC; } + +//-------------------------------------------------------------------------- + +typedef uchar comp_t; ///< target compiler id +typedef uchar cm_t; ///< calling convention and memory model + +/// Information about the target compiler +struct compiler_info_t +{ + comp_t id = 0; ///< compiler id (see \ref COMP_) + cm_t cm = 0; ///< memory model and calling convention (see \ref CM_) + uchar size_i = 0; ///< sizeof(int) + uchar size_b = 0; ///< sizeof(bool) + uchar size_e = 0; ///< sizeof(enum) + uchar defalign = 0; ///< default alignment for structures + uchar size_s = 0; ///< short + uchar size_l = 0; ///< long + uchar size_ll = 0; ///< longlong + uchar size_ldbl = 0; ///< longdouble (if different from \ph{tbyte_size}) +}; + +//-------------------------------------------------------------------------- +/// Storage types for flag bits +enum storage_type_t +{ + STT_CUR = -1, ///< use current storage type (may be used only as a function argument) + STT_VA = 0, ///< regular storage: virtual arrays, an explicit flag for each byte + STT_MM = 1, ///< memory map: sparse storage. useful for huge objects + STT_DBG = 2, ///< memory map: temporary debugger storage. used internally +}; + +/// \def{EA64_ALIGN, Maintain 64-bit alignments in 64-bit mode} +#ifdef __EA64__ +#define EA64_ALIGN(n) uint32 n; +#else +#define EA64_ALIGN(n) +#endif + +//-------------------------------------------------------------------------- +/// The database parameters. +/// This structure is kept in the ida database. +/// It contains the essential parameters for the current program +#define IDAINFO_TAG_SIZE 3 +#define IDAINFO_PROCNAME_SIZE 16 +#define IDAINFO_STRLIT_PREF_SIZE 16 +struct idainfo +{ + char tag[IDAINFO_TAG_SIZE]; ///< 'IDA' + char zero; ///< this field is not present in the database + ushort version; ///< Version of database + char procname[IDAINFO_PROCNAME_SIZE]; ///< Name of the current processor (with \0) + + ushort s_genflags; ///< \ref INFFL_ +/// \defgroup INFFL_ General idainfo flags +/// Used by idainfo::s_genflags +//@{ +#define INFFL_AUTO 0x01 ///< Autoanalysis is enabled? +#define INFFL_ALLASM 0x02 ///< may use constructs not supported by + ///< the target assembler +#define INFFL_LOADIDC 0x04 ///< loading an idc file that contains database info +#define INFFL_NOUSER 0x08 ///< do not store user info in the database +#define INFFL_READONLY 0x10 ///< (internal) temporary interdiction to modify the database +#define INFFL_CHKOPS 0x20 ///< check manual operands? (unused) +#define INFFL_NMOPS 0x40 ///< allow non-matched operands? (unused) +#define INFFL_GRAPH_VIEW 0x80 ///< currently using graph options (\dto{graph}) +//@} + + uint32 lflags; ///< \ref LFLG_ +/// \defgroup LFLG_ Misc. database flags +/// used by idainfo::lflags +//@{ +#define LFLG_PC_FPP 0x00000001 ///< decode floating point processor instructions? +#define LFLG_PC_FLAT 0x00000002 ///< 32-bit program (or higher)? +#define LFLG_64BIT 0x00000004 ///< 64-bit program? +#define LFLG_IS_DLL 0x00000008 ///< Is dynamic library? +#define LFLG_FLAT_OFF32 0x00000010 ///< treat ::REF_OFF32 as 32-bit offset for 16bit segments (otherwise try SEG16:OFF16) +#define LFLG_MSF 0x00000020 ///< Byte order: is MSB first? +#define LFLG_WIDE_HBF 0x00000040 ///< Bit order of wide bytes: high byte first? + ///< (wide bytes: \ph{dnbits} > 8) +#define LFLG_DBG_NOPATH 0x00000080 ///< do not store input full path in debugger process options +#define LFLG_SNAPSHOT 0x00000100 ///< memory snapshot was taken? +#define LFLG_PACK 0x00000200 ///< pack the database? +#define LFLG_COMPRESS 0x00000400 ///< compress the database? +#define LFLG_KERNMODE 0x00000800 ///< is kernel mode binary? +//@} + +/// \defgroup IDB_ IDB pack modes +/// Used by idainfo::get_pack_mode +//@{ +#define IDB_UNPACKED 0 ///< leave database components unpacked +#define IDB_PACKED 1 ///< pack database components into .idb +#define IDB_COMPRESSED 2 ///< compress & pack database components +//@} + + uint32 database_change_count; ///< incremented after each byte and regular + ///< segment modifications + + ushort filetype; ///< The input file type + + ushort ostype; ///< OS type the program is for + ///< bit definitions in libfuncs.hpp + + ushort apptype; ///< Application type + ///< bit definitions in libfuncs.hpp + + uchar asmtype; ///< target assembler number + + uchar specsegs; ///< What format do special segments use? 0-unspecified, 4-entries are 4 bytes, 8- entries are 8 bytes. + + uint32 af; ///< \ref AF_ +/// \defgroup AF_ Analysis flags +/// used by idainfo::af +//@{ +#define AF_CODE 0x00000001 ///< Trace execution flow +#define AF_MARKCODE 0x00000002 ///< Mark typical code sequences as code +#define AF_JUMPTBL 0x00000004 ///< Locate and create jump tables +#define AF_PURDAT 0x00000008 ///< Control flow to data segment is ignored +#define AF_USED 0x00000010 ///< Analyze and create all xrefs +#define AF_UNK 0x00000020 ///< Delete instructions with no xrefs + +#define AF_PROCPTR 0x00000040 ///< Create function if data xref data->code32 exists +#define AF_PROC 0x00000080 ///< Create functions if call is present +#define AF_FTAIL 0x00000100 ///< Create function tails +#define AF_LVAR 0x00000200 ///< Create stack variables +#define AF_STKARG 0x00000400 ///< Propagate stack argument information +#define AF_REGARG 0x00000800 ///< Propagate register argument information +#define AF_TRACE 0x00001000 ///< Trace stack pointer +#define AF_VERSP 0x00002000 ///< Perform full SP-analysis. (\ph{verify_sp}) +#define AF_ANORET 0x00004000 ///< Perform 'no-return' analysis +#define AF_MEMFUNC 0x00008000 ///< Try to guess member function types +#define AF_TRFUNC 0x00010000 ///< Truncate functions upon code deletion + +#define AF_STRLIT 0x00020000 ///< Create string literal if data xref exists +#define AF_CHKUNI 0x00040000 ///< Check for unicode strings +#define AF_FIXUP 0x00080000 ///< Create offsets and segments using fixup info +#define AF_DREFOFF 0x00100000 ///< Create offset if data xref to seg32 exists +#define AF_IMMOFF 0x00200000 ///< Convert 32bit instruction operand to offset +#define AF_DATOFF 0x00400000 ///< Automatically convert data to offsets + +#define AF_FLIRT 0x00800000 ///< Use flirt signatures +#define AF_SIGCMT 0x01000000 ///< Append a signature name comment for recognized anonymous library functions +#define AF_SIGMLT 0x02000000 ///< Allow recognition of several copies of the same function +#define AF_HFLIRT 0x04000000 ///< Automatically hide library functions + +#define AF_JFUNC 0x08000000 ///< Rename jump functions as j_... +#define AF_NULLSUB 0x10000000 ///< Rename empty functions as nullsub_... + +#define AF_DODATA 0x20000000 ///< Coagulate data segs at the final pass +#define AF_DOCODE 0x40000000 ///< Coagulate code segs at the final pass +#define AF_FINAL 0x80000000 ///< Final pass of analysis +//@} + uint32 af2; ///< \ref AF2_ +/// \defgroup AF2_ Analysis flags 2 +/// Used by idainfo::af2 +//@{ +#define AF2_DOEH 0x00000001 ///< Handle EH information +#define AF2_DORTTI 0x00000002 ///< Handle RTTI information +#define AF2_MACRO 0x00000004 ///< Try to combine several instructions + ///< into a macro instruction +/// remaining 29 bits are reserved +//@} + uval_t baseaddr; ///< base address of the program (paragraphs) + sel_t start_ss; ///< selector of the initial stack segment + sel_t start_cs; ///< selector of the segment with the main entry point + ea_t start_ip; ///< IP register value at the start of + ///< program execution + ea_t start_ea; ///< Linear address of program entry point + ea_t start_sp; ///< SP register value at the start of + ///< program execution + ea_t main; ///< address of main() + ea_t min_ea; ///< current limits of program + ea_t max_ea; ///< maxEA is excluded + ea_t omin_ea; ///< original minEA (is set after loading the input file) + ea_t omax_ea; ///< original maxEA (is set after loading the input file) + + ea_t lowoff; ///< Low limit for offsets + ///< (used in calculation of 'void' operands) + ea_t highoff; ///< High limit for offsets + ///< (used in calculation of 'void' operands) + + uval_t maxref; ///< Max tail for references + + range_t privrange; ///< Range of addresses reserved for internal use. + ///< Initially (MAXADDR, MAXADDR+0x800000) + sval_t netdelta; ///< Delta value to be added to all adresses for mapping to netnodes. + ///< Initially 0 + + /// CROSS REFERENCES + uchar xrefnum; ///< Number of references to generate + ///< in the disassembly listing + ///< 0 - xrefs won't be generated at all + uchar type_xrefnum; ///< Number of references to generate + ///< in the struct & enum windows + ///< 0 - xrefs won't be generated at all + uchar refcmtnum; ///< Number of comment lines to + ///< generate for refs to string literals + ///< or demangled names + ///< 0 - such comments won't be + ///< generated at all + uchar s_xrefflag; ///< \ref SW_X +/// \defgroup SW_X Xref options +/// Used by idainfo::s_xrefflag +//@{ +#define SW_SEGXRF 0x01 ///< show segments in xrefs? +#define SW_XRFMRK 0x02 ///< show xref type marks? +#define SW_XRFFNC 0x04 ///< show function offsets? +#define SW_XRFVAL 0x08 ///< show xref values? (otherwise-"...") +//@} + + /// NAMES + ushort max_autoname_len; ///< max autogenerated name length (without zero byte) + char nametype; ///< \ref NM_ +/// \defgroup NM_ Dummy names representation types +/// Used by idainfo::nametype +//@{ +#define NM_REL_OFF 0 +#define NM_PTR_OFF 1 +#define NM_NAM_OFF 2 +#define NM_REL_EA 3 +#define NM_PTR_EA 4 +#define NM_NAM_EA 5 +#define NM_EA 6 +#define NM_EA4 7 +#define NM_EA8 8 +#define NM_SHORT 9 +#define NM_SERIAL 10 +//@} + + uint32 short_demnames; ///< short form of demangled names + uint32 long_demnames; ///< long form of demangled names + ///< see demangle.h for definitions + uchar demnames; ///< \ref DEMNAM_ +/// \defgroup DEMNAM_ Demangled name flags +/// used by idainfo::demnames +//@{ +#define DEMNAM_MASK 3 ///< mask for name form +#define DEMNAM_CMNT 0 ///< display demangled names as comments +#define DEMNAM_NAME 1 ///< display demangled names as regular names +#define DEMNAM_NONE 2 ///< don't display demangled names +#define DEMNAM_GCC3 4 ///< assume gcc3 names (valid for gnu compiler) +#define DEMNAM_FIRST 8 ///< override type info +//@} + + uchar listnames; ///< \ref LN_ +/// \defgroup LN_ Name list options +/// Used by idainfo::listnames +//@{ +#define LN_NORMAL 0x01 ///< include normal names +#define LN_PUBLIC 0x02 ///< include public names +#define LN_AUTO 0x04 ///< include autogenerated names +#define LN_WEAK 0x08 ///< include weak names +//@} + + /// DISASSEMBLY LISTING DETAILS + uchar indent; ///< Indentation for instructions + uchar comment; ///< Indentation for comments + ushort margin; ///< max length of data lines + ushort lenxref; ///< max length of line with xrefs + uint32 outflags; ///< \ref OFLG_ +/// \defgroup OFLG_ output flags +/// used by idainfo::outflags +//@{ +#define OFLG_SHOW_VOID 0x002 ///< Display void marks? +#define OFLG_SHOW_AUTO 0x004 ///< Display autoanalysis indicator? +#define OFLG_GEN_NULL 0x010 ///< Generate empty lines? +#define OFLG_SHOW_PREF 0x020 ///< Show line prefixes? +#define OFLG_PREF_SEG 0x040 ///< line prefixes with segment name? +#define OFLG_LZERO 0x080 ///< generate leading zeroes in numbers +#define OFLG_GEN_ORG 0x100 ///< Generate 'org' directives? +#define OFLG_GEN_ASSUME 0x200 ///< Generate 'assume' directives? +#define OFLG_GEN_TRYBLKS 0x400 ///< Generate try/catch directives? +//@} + + uchar s_cmtflg; ///< \ref SCF_ +/// \defgroup SCF_ Comment options +/// Used by idainfo::s_cmtflg +//@{ +#define SCF_RPTCMT 0x01 ///< show repeatable comments? +#define SCF_ALLCMT 0x02 ///< comment all lines? +#define SCF_NOCMT 0x04 ///< no comments at all +#define SCF_LINNUM 0x08 ///< show source line numbers +#define SCF_TESTMODE 0x10 ///< testida.idc is running +#define SCF_SHHID_ITEM 0x20 ///< show hidden instructions +#define SCF_SHHID_FUNC 0x40 ///< show hidden functions +#define SCF_SHHID_SEGM 0x80 ///< show hidden segments +//@} + + uchar s_limiter; ///< \ref LMT_ +/// \defgroup LMT_ Delimiter options +/// Used by idainfo::s_limiter +//@{ +#define LMT_THIN 0x01 ///< thin borders +#define LMT_THICK 0x02 ///< thick borders +#define LMT_EMPTY 0x04 ///< empty lines at the end of basic blocks +//@} + + short bin_prefix_size; ///< # of instruction bytes (opcodes) to show in line prefix + uchar s_prefflag; ///< \ref PREF_ +/// \defgroup PREF_ Line prefix options +/// Used by idainfo::s_prefflag +//@{ +#define PREF_SEGADR 0x01 ///< show segment addresses? +#define PREF_FNCOFF 0x02 ///< show function offsets? +#define PREF_STACK 0x04 ///< show stack pointer? +#define PREF_PFXTRUNC 0x08 ///< truncate instruction bytes if they would need more than 1 line +//@} + + /// STRING LITERALS + uchar strlit_flags; ///< \ref STRF_ +/// \defgroup STRF_ string literal flags +/// Used by idainfo::strlit_flags +//@{ +#define STRF_GEN 0x01 ///< generate names? +#define STRF_AUTO 0x02 ///< names have 'autogenerated' bit? +#define STRF_SERIAL 0x04 ///< generate serial names? +#define STRF_UNICODE 0x08 ///< unicode strings are present? +#define STRF_COMMENT 0x10 ///< generate auto comment for string references? +#define STRF_SAVECASE 0x20 ///< preserve case of strings for identifiers +//@} + uchar strlit_break; ///< string literal line break symbol + char strlit_zeroes; ///< leading zeroes + int32 strtype; ///< current ascii string type + ///< see nalt.hpp for string types + char strlit_pref[IDAINFO_STRLIT_PREF_SIZE]; ///< prefix for string literal names + uval_t strlit_sernum; ///< serial number + + // DATA ITEMS + uval_t datatypes; ///< data types allowed in data carousel + + /// COMPILER + compiler_info_t cc; ///< Target compiler + uint32 abibits; ///< ABI features. Depends on info returned by get_abi_name() + ///< Processor modules may modify them in set_compiler + +/// \defgroup ABI_ abi options +/// Used by idainfo::abibits +//@{ +#define ABI_8ALIGN4 0x00000001 ///< 4 byte alignment for 8byte scalars (__int64/double) inside structures? +#define ABI_PACK_STKARGS 0x00000002 ///< do not align stack arguments to stack slots +#define ABI_BIGARG_ALIGN 0x00000004 ///< use natural type alignment for argument if the alignment exceeds native word size + ///< (e.g. __int64 argument should be 8byte aligned on some 32bit platforms) +#define ABI_STACK_LDBL 0x00000008 ///< long double arguments are passed on stack +#define ABI_STACK_VARARGS 0x00000010 ///< varargs are always passed on stack (even when there are free registers) +#define ABI_HARD_FLOAT 0x00000020 ///< use the floating-point register set +#define ABI_SET_BY_USER 0x00000040 ///< compiler/abi were set by user flag and require SETCOMP_BY_USER flag to be changed +#define ABI_GCC_LAYOUT 0x00000080 ///< use gcc layout for udts (used for mingw) +#define ABI_MAP_STKARGS 0x00000100 ///< register arguments are mapped to stack area (and consume stack slots) +#define ABI_HUGEARG_ALIGN 0x00000200 ///< use natural type alignment for an argument + ///< even if its alignment exceeds double native word size + ///< (the default is to use double word max). + ///< e.g. if this bit is set, __int128 has 16-byte alignment. + ///< this bit is not used by ida yet +#define ABI_EXPLICIT_STKOFFS 0x00400 ///< stack locations of function arguments are + ///< specified explicitly. also, + ///< return values on the stack are ok +//@} + + uint32 appcall_options; ///< appcall options, see idd.hpp + EA64_ALIGN(padding); + ///< total size for 32bit: 216 bytes + ///< for 64bit: 296 bytes + +}; +#ifdef __EA64__ +CASSERT(sizeof(idainfo) == 280); +#else +CASSERT(sizeof(idainfo) == 200); +#endif + +#if !defined(NO_OBSOLETE_FUNCS) +#define SW_RPTCMT SCF_RPTCMT +#define SW_ALLCMT SCF_ALLCMT +#define SW_NOCMT SCF_NOCMT +#define SW_LINNUM SCF_LINNUM +#define SW_TESTMODE SCF_TESTMODE +#define SW_SHHID_ITEM SCF_SHHID_ITEM +#define SW_SHHID_FUNC SCF_SHHID_FUNC +#define SW_SHHID_SEGM SCF_SHHID_SEGM +#endif + +// we have to continue to export INF for old plugins +#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_INF__) +idaman idainfo ida_export_data inf; ///< program specific information +#endif + +enum inftag_t +{ + INF_VERSION = 0, + INF_PROCNAME = 1, + INF_GENFLAGS = 2, + INF_LFLAGS = 3, + INF_DATABASE_CHANGE_COUNT = 4, + INF_FILETYPE = 5, + INF_OSTYPE = 6, + INF_APPTYPE = 7, + INF_ASMTYPE = 8, + INF_SPECSEGS = 9, + INF_AF = 10, + INF_AF2 = 11, + INF_BASEADDR = 12, + INF_START_SS = 13, + INF_START_CS = 14, + INF_START_IP = 15, + INF_START_EA = 16, + INF_START_SP = 17, + INF_MAIN = 18, + INF_MIN_EA = 19, + INF_MAX_EA = 20, + INF_OMIN_EA = 21, + INF_OMAX_EA = 22, + INF_LOWOFF = 23, + INF_HIGHOFF = 24, + INF_MAXREF = 25, + INF_PRIVRANGE = 26, + INF_PRIVRANGE_START_EA = 27, + INF_PRIVRANGE_END_EA = 28, + INF_NETDELTA = 29, + INF_XREFNUM = 30, + INF_TYPE_XREFNUM = 31, + INF_REFCMTNUM = 32, + INF_XREFFLAG = 33, + INF_MAX_AUTONAME_LEN = 34, + INF_NAMETYPE = 35, + INF_SHORT_DEMNAMES = 36, + INF_LONG_DEMNAMES = 37, + INF_DEMNAMES = 38, + INF_LISTNAMES = 39, + INF_INDENT = 40, + INF_COMMENT = 41, + INF_MARGIN = 42, + INF_LENXREF = 43, + INF_OUTFLAGS = 44, + INF_CMTFLG = 45, + INF_LIMITER = 46, + INF_BIN_PREFIX_SIZE = 47, + INF_PREFFLAG = 48, + INF_STRLIT_FLAGS = 49, + INF_STRLIT_BREAK = 50, + INF_STRLIT_ZEROES = 51, + INF_STRTYPE = 52, + INF_STRLIT_PREF = 53, + INF_STRLIT_SERNUM = 54, + INF_DATATYPES = 55, + INF_CC = 56, + INF_CC_ID = 57, + INF_CC_CM = 58, + INF_CC_SIZE_I = 59, + INF_CC_SIZE_B = 60, + INF_CC_SIZE_E = 61, + INF_CC_DEFALIGN = 62, + INF_CC_SIZE_S = 63, + INF_CC_SIZE_L = 64, + INF_CC_SIZE_LL = 65, + INF_CC_SIZE_LDBL = 66, + INF_ABIBITS = 67, + INF_APPCALL_OPTIONS = 68, + + // root node fields + INF_FILE_FORMAT_NAME = 69, ///< file format name for loader modules + INF_GROUPS = 70, ///< segment group information (see init_groups()) + INF_H_PATH = 71, ///< C header path + INF_C_MACROS = 72, ///< C predefined macros + INF_INCLUDE = 73, ///< assembler include file name + INF_DUALOP_GRAPH = 74, ///< Graph text representation options + INF_DUALOP_TEXT = 75, ///< Text text representation options + INF_MD5 = 76, ///< MD5 of the input file + INF_IDA_VERSION = 77, ///< version of ida which created the database + INF_STR_ENCODINGS = 78, ///< a list of encodings for the program strings + INF_DBG_BINPATHS = 79, ///< unused (20 indexes) + INF_SHA256 = 80, ///< SHA256 of the input file + INF_ABINAME = 81, ///< ABI name (processor specific) + INF_ARCHIVE_PATH = 82, ///< archive file path + INF_PROBLEMS = 83, ///< problem lists + + INF_SELECTORS = 84, ///< 2..63 are for selector_t blob (see init_selectors()) + INF_NOTEPAD = 85, ///< notepad blob, occupies 1000 indexes (1MB of text) + INF_SRCDBG_PATHS = 86, ///< source debug paths, occupies 20 indexes + INF_SRCDBG_UNDESIRED = 87, ///< user-closed source files, occupies 20 indexes + INF_INITIAL_VERSION = 88, ///< initial version of database + INF_CTIME = 89, ///< database creation timestamp + INF_ELAPSED = 90, ///< seconds database stayed open + INF_NOPENS = 91, ///< how many times the database is opened + INF_CRC32 = 92, ///< input file crc32 + INF_IMAGEBASE = 93, ///< image base + INF_IDSNODE = 94, ///< ids modnode id (for import_module) + INF_FSIZE = 95, ///< input file size + INF_OUTFILEENC = 96, ///< output file encoding index + INF_INPUT_FILE_PATH = 97, + INF_LAST = 98, +}; + +/// get program specific information (a scalar value) +/// \param tag one of inftag_t constants +/// \return the requested info. if wrong tag is specified, return 0 +idaman size_t ida_export getinf(inftag_t tag); + +/// get program specific information (a non-scalar value) +/// \param tag one of inftag_t constants +/// \param buf output buffer +/// \param bufsize size of the output buffer +/// \return number of bytes stored in the buffer (<0 - not defined) +idaman ssize_t ida_export getinf_buf(inftag_t tag, void *buf, size_t bufsize); + +/// get program specific information (a non-scalar value) +/// \param tag one of inftag_t constants +/// \param buf output buffer +/// \return number of bytes stored in the buffer (<0 - not defined) +idaman ssize_t ida_export getinf_str(qstring *buf, inftag_t tag); + +/// get a flag value +/// \param tag one of inftag_t constants +/// \param flag a flag in the field +/// \return whether the flag is set +idaman bool ida_export getinf_flag(inftag_t tag, uint32 flag); + +/// set program specific information +/// \param tag one of inftag_t constants +/// \return success +idaman bool ida_export setinf(inftag_t tag, ssize_t value); + +/// set program specific information +/// \param tag one of inftag_t constants +/// \param buf ptr to new value +/// \param bufsize size of the new value, calculated as strlen(buf)+1 if not specified +/// \return success +idaman bool ida_export setinf_buf(inftag_t tag, const void *buf, size_t bufsize=0); + +/// set a flag value +/// \param tag one of inftag_t constants +/// \param flag a flag in the field +/// \param value whether to set, or clear the flag +/// \return the previous value +idaman bool ida_export setinf_flag(inftag_t tag, uint32 flag, bool value=true); + +/// undefine a program specific information +/// \param tag one of inftag_t constants +/// \return success +idaman bool ida_export delinf(inftag_t tag); + + +// <INF_ACCESSORS> +inline ushort inf_get_version() { return ushort(getinf(INF_VERSION)); } +inline bool inf_set_version(ushort _v) { return setinf(INF_VERSION, ssize_t(_v)); } + +inline ushort inf_get_genflags() { return ushort(getinf(INF_GENFLAGS)); } +inline bool inf_set_genflags(ushort _v) { return setinf(INF_GENFLAGS, ssize_t(_v)); } +inline bool inf_is_auto_enabled(void) { return getinf_flag(INF_GENFLAGS, INFFL_AUTO); } +inline bool inf_set_auto_enabled(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_AUTO, _v); } +inline bool inf_use_allasm(void) { return getinf_flag(INF_GENFLAGS, INFFL_ALLASM); } +inline bool inf_set_use_allasm(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_ALLASM, _v); } +inline bool inf_loading_idc(void) { return getinf_flag(INF_GENFLAGS, INFFL_LOADIDC); } +inline bool inf_set_loading_idc(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_LOADIDC, _v); } +inline bool inf_no_store_user_info(void) { return getinf_flag(INF_GENFLAGS, INFFL_NOUSER); } +inline bool inf_set_no_store_user_info(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_NOUSER, _v); } +inline bool inf_readonly_idb(void) { return getinf_flag(INF_GENFLAGS, INFFL_READONLY); } +inline bool inf_set_readonly_idb(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_READONLY, _v); } +inline bool inf_check_manual_ops(void) { return getinf_flag(INF_GENFLAGS, INFFL_CHKOPS); } +inline bool inf_set_check_manual_ops(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_CHKOPS, _v); } +inline bool inf_allow_non_matched_ops(void) { return getinf_flag(INF_GENFLAGS, INFFL_NMOPS); } +inline bool inf_set_allow_non_matched_ops(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_NMOPS, _v); } +inline bool inf_is_graph_view(void) { return getinf_flag(INF_GENFLAGS, INFFL_GRAPH_VIEW); } +inline bool inf_set_graph_view(bool _v=true) { return setinf_flag(INF_GENFLAGS, INFFL_GRAPH_VIEW, _v); } + +inline uint32 inf_get_lflags() { return uint32(getinf(INF_LFLAGS)); } +inline bool inf_set_lflags(uint32 _v) { return setinf(INF_LFLAGS, ssize_t(_v)); } +inline bool inf_decode_fpp(void) { return getinf_flag(INF_LFLAGS, LFLG_PC_FPP); } +inline bool inf_set_decode_fpp(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_PC_FPP, _v); } +// unfortunately the name inf_is_32bit was used in the past to mean inf_is_32bit_or_higher. +// it was misleading, this is why we have more explicit names now. +inline bool inf_is_32bit_or_higher(void) { return getinf_flag(INF_LFLAGS, LFLG_PC_FLAT); } +inline bool inf_is_32bit_exactly(void) { return (getinf(INF_LFLAGS) & (LFLG_PC_FLAT|LFLG_64BIT)) == LFLG_PC_FLAT; } +inline bool inf_set_32bit(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_PC_FLAT, _v); } +inline bool inf_is_16bit(void) { return !inf_is_32bit_or_higher(); } +inline bool inf_is_64bit(void) { return getinf_flag(INF_LFLAGS, LFLG_64BIT); } +inline bool inf_set_64bit(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_64BIT, _v); } +inline bool inf_is_dll(void) { return getinf_flag(INF_LFLAGS, LFLG_IS_DLL); } +inline bool inf_set_dll(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_IS_DLL, _v); } +inline bool inf_is_flat_off32(void) { return getinf_flag(INF_LFLAGS, LFLG_FLAT_OFF32); } +inline bool inf_set_flat_off32(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_FLAT_OFF32, _v); } +inline bool inf_is_be(void) { return getinf_flag(INF_LFLAGS, LFLG_MSF); } +inline bool inf_set_be(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_MSF, _v); } +inline bool inf_is_wide_high_byte_first(void) { return getinf_flag(INF_LFLAGS, LFLG_WIDE_HBF); } +inline bool inf_set_wide_high_byte_first(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_WIDE_HBF, _v); } +inline bool inf_dbg_no_store_path(void) { return getinf_flag(INF_LFLAGS, LFLG_DBG_NOPATH); } +inline bool inf_set_dbg_no_store_path(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_DBG_NOPATH, _v); } +inline bool inf_is_snapshot(void) { return getinf_flag(INF_LFLAGS, LFLG_SNAPSHOT); } +inline bool inf_set_snapshot(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_SNAPSHOT, _v); } +inline bool inf_pack_idb(void) { return getinf_flag(INF_LFLAGS, LFLG_PACK); } +inline bool inf_set_pack_idb(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_PACK, _v); } +inline bool inf_compress_idb(void) { return getinf_flag(INF_LFLAGS, LFLG_COMPRESS); } +inline bool inf_set_compress_idb(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_COMPRESS, _v); } +inline bool inf_is_kernel_mode(void) { return getinf_flag(INF_LFLAGS, LFLG_KERNMODE); } +inline bool inf_set_kernel_mode(bool _v=true) { return setinf_flag(INF_LFLAGS, LFLG_KERNMODE, _v); } + +inline uint inf_get_app_bitness(void) // return 16, 32, or 64 +{ +#ifdef __EA64__ + uint32 f = getinf(INF_LFLAGS) & (LFLG_PC_FLAT|LFLG_64BIT); + return f == 0 ? 16 : f == LFLG_PC_FLAT ? 32 : 64; +#else + return inf_is_32bit_or_higher() ? 32 : 16; +#endif +} + +inline uint32 inf_get_database_change_count() { return uint32(getinf(INF_DATABASE_CHANGE_COUNT)); } +inline bool inf_set_database_change_count(uint32 _v) { return setinf(INF_DATABASE_CHANGE_COUNT, ssize_t(_v)); } + +inline filetype_t inf_get_filetype() { return filetype_t(getinf(INF_FILETYPE)); } +inline bool inf_set_filetype(filetype_t _v) { return setinf(INF_FILETYPE, ssize_t(_v)); } + +inline ushort inf_get_ostype() { return ushort(getinf(INF_OSTYPE)); } +inline bool inf_set_ostype(ushort _v) { return setinf(INF_OSTYPE, ssize_t(_v)); } + +inline ushort inf_get_apptype() { return ushort(getinf(INF_APPTYPE)); } +inline bool inf_set_apptype(ushort _v) { return setinf(INF_APPTYPE, ssize_t(_v)); } + +inline uchar inf_get_asmtype() { return uchar(getinf(INF_ASMTYPE)); } +inline bool inf_set_asmtype(uchar _v) { return setinf(INF_ASMTYPE, ssize_t(_v)); } + +inline uchar inf_get_specsegs() { return uchar(getinf(INF_SPECSEGS)); } +inline bool inf_set_specsegs(uchar _v) { return setinf(INF_SPECSEGS, ssize_t(_v)); } + +inline uint32 inf_get_af() { return uint32(getinf(INF_AF)); } +inline bool inf_set_af(uint32 _v) { return setinf(INF_AF, ssize_t(_v)); } +inline bool inf_trace_flow(void) { return getinf_flag(INF_AF, AF_CODE); } +inline bool inf_set_trace_flow(bool _v=true) { return setinf_flag(INF_AF, AF_CODE, _v); } +inline bool inf_mark_code(void) { return getinf_flag(INF_AF, AF_MARKCODE); } +inline bool inf_set_mark_code(bool _v=true) { return setinf_flag(INF_AF, AF_MARKCODE, _v); } +inline bool inf_create_jump_tables(void) { return getinf_flag(INF_AF, AF_JUMPTBL); } +inline bool inf_set_create_jump_tables(bool _v=true) { return setinf_flag(INF_AF, AF_JUMPTBL, _v); } +inline bool inf_noflow_to_data(void) { return getinf_flag(INF_AF, AF_PURDAT); } +inline bool inf_set_noflow_to_data(bool _v=true) { return setinf_flag(INF_AF, AF_PURDAT, _v); } +inline bool inf_create_all_xrefs(void) { return getinf_flag(INF_AF, AF_USED); } +inline bool inf_set_create_all_xrefs(bool _v=true) { return setinf_flag(INF_AF, AF_USED, _v); } +inline bool inf_del_no_xref_insns(void) { return getinf_flag(INF_AF, AF_UNK); } +inline bool inf_set_del_no_xref_insns(bool _v=true) { return setinf_flag(INF_AF, AF_UNK, _v); } +inline bool inf_create_func_from_ptr(void) { return getinf_flag(INF_AF, AF_PROCPTR); } +inline bool inf_set_create_func_from_ptr(bool _v=true) { return setinf_flag(INF_AF, AF_PROCPTR, _v); } +inline bool inf_create_func_from_call(void) { return getinf_flag(INF_AF, AF_PROC); } +inline bool inf_set_create_func_from_call(bool _v=true) { return setinf_flag(INF_AF, AF_PROC, _v); } +inline bool inf_create_func_tails(void) { return getinf_flag(INF_AF, AF_FTAIL); } +inline bool inf_set_create_func_tails(bool _v=true) { return setinf_flag(INF_AF, AF_FTAIL, _v); } +inline bool inf_should_create_stkvars(void) { return getinf_flag(INF_AF, AF_LVAR); } +inline bool inf_set_should_create_stkvars(bool _v=true) { return setinf_flag(INF_AF, AF_LVAR, _v); } +inline bool inf_propagate_stkargs(void) { return getinf_flag(INF_AF, AF_STKARG); } +inline bool inf_set_propagate_stkargs(bool _v=true) { return setinf_flag(INF_AF, AF_STKARG, _v); } +inline bool inf_propagate_regargs(void) { return getinf_flag(INF_AF, AF_REGARG); } +inline bool inf_set_propagate_regargs(bool _v=true) { return setinf_flag(INF_AF, AF_REGARG, _v); } +inline bool inf_should_trace_sp(void) { return getinf_flag(INF_AF, AF_TRACE); } +inline bool inf_set_should_trace_sp(bool _v=true) { return setinf_flag(INF_AF, AF_TRACE, _v); } +inline bool inf_full_sp_ana(void) { return getinf_flag(INF_AF, AF_VERSP); } +inline bool inf_set_full_sp_ana(bool _v=true) { return setinf_flag(INF_AF, AF_VERSP, _v); } +inline bool inf_noret_ana(void) { return getinf_flag(INF_AF, AF_ANORET); } +inline bool inf_set_noret_ana(bool _v=true) { return setinf_flag(INF_AF, AF_ANORET, _v); } +inline bool inf_guess_func_type(void) { return getinf_flag(INF_AF, AF_MEMFUNC); } +inline bool inf_set_guess_func_type(bool _v=true) { return setinf_flag(INF_AF, AF_MEMFUNC, _v); } +inline bool inf_truncate_on_del(void) { return getinf_flag(INF_AF, AF_TRFUNC); } +inline bool inf_set_truncate_on_del(bool _v=true) { return setinf_flag(INF_AF, AF_TRFUNC, _v); } +inline bool inf_create_strlit_on_xref(void) { return getinf_flag(INF_AF, AF_STRLIT); } +inline bool inf_set_create_strlit_on_xref(bool _v=true) { return setinf_flag(INF_AF, AF_STRLIT, _v); } +inline bool inf_check_unicode_strlits(void) { return getinf_flag(INF_AF, AF_CHKUNI); } +inline bool inf_set_check_unicode_strlits(bool _v=true) { return setinf_flag(INF_AF, AF_CHKUNI, _v); } +inline bool inf_create_off_using_fixup(void) { return getinf_flag(INF_AF, AF_FIXUP); } +inline bool inf_set_create_off_using_fixup(bool _v=true) { return setinf_flag(INF_AF, AF_FIXUP, _v); } +inline bool inf_create_off_on_dref(void) { return getinf_flag(INF_AF, AF_DREFOFF); } +inline bool inf_set_create_off_on_dref(bool _v=true) { return setinf_flag(INF_AF, AF_DREFOFF, _v); } +inline bool inf_op_offset(void) { return getinf_flag(INF_AF, AF_IMMOFF); } +inline bool inf_set_op_offset(bool _v=true) { return setinf_flag(INF_AF, AF_IMMOFF, _v); } +inline bool inf_data_offset(void) { return getinf_flag(INF_AF, AF_DATOFF); } +inline bool inf_set_data_offset(bool _v=true) { return setinf_flag(INF_AF, AF_DATOFF, _v); } +inline bool inf_use_flirt(void) { return getinf_flag(INF_AF, AF_FLIRT); } +inline bool inf_set_use_flirt(bool _v=true) { return setinf_flag(INF_AF, AF_FLIRT, _v); } +inline bool inf_append_sigcmt(void) { return getinf_flag(INF_AF, AF_SIGCMT); } +inline bool inf_set_append_sigcmt(bool _v=true) { return setinf_flag(INF_AF, AF_SIGCMT, _v); } +inline bool inf_allow_sigmulti(void) { return getinf_flag(INF_AF, AF_SIGMLT); } +inline bool inf_set_allow_sigmulti(bool _v=true) { return setinf_flag(INF_AF, AF_SIGMLT, _v); } +inline bool inf_hide_libfuncs(void) { return getinf_flag(INF_AF, AF_HFLIRT); } +inline bool inf_set_hide_libfuncs(bool _v=true) { return setinf_flag(INF_AF, AF_HFLIRT, _v); } +inline bool inf_rename_jumpfunc(void) { return getinf_flag(INF_AF, AF_JFUNC); } +inline bool inf_set_rename_jumpfunc(bool _v=true) { return setinf_flag(INF_AF, AF_JFUNC, _v); } +inline bool inf_rename_nullsub(void) { return getinf_flag(INF_AF, AF_NULLSUB); } +inline bool inf_set_rename_nullsub(bool _v=true) { return setinf_flag(INF_AF, AF_NULLSUB, _v); } +inline bool inf_coagulate_data(void) { return getinf_flag(INF_AF, AF_DODATA); } +inline bool inf_set_coagulate_data(bool _v=true) { return setinf_flag(INF_AF, AF_DODATA, _v); } +inline bool inf_coagulate_code(void) { return getinf_flag(INF_AF, AF_DOCODE); } +inline bool inf_set_coagulate_code(bool _v=true) { return setinf_flag(INF_AF, AF_DOCODE, _v); } +inline bool inf_final_pass(void) { return getinf_flag(INF_AF, AF_FINAL); } +inline bool inf_set_final_pass(bool _v=true) { return setinf_flag(INF_AF, AF_FINAL, _v); } + +inline uint32 inf_get_af2() { return uint32(getinf(INF_AF2)); } +inline bool inf_set_af2(uint32 _v) { return setinf(INF_AF2, ssize_t(_v)); } +inline bool inf_handle_eh(void) { return getinf_flag(INF_AF2, AF2_DOEH); } +inline bool inf_set_handle_eh(bool _v=true) { return setinf_flag(INF_AF2, AF2_DOEH, _v); } +inline bool inf_handle_rtti(void) { return getinf_flag(INF_AF2, AF2_DORTTI); } +inline bool inf_set_handle_rtti(bool _v=true) { return setinf_flag(INF_AF2, AF2_DORTTI, _v); } +inline bool inf_macros_enabled(void) { return getinf_flag(INF_AF2, AF2_MACRO); } +inline bool inf_set_macros_enabled(bool _v=true) { return setinf_flag(INF_AF2, AF2_MACRO, _v); } + +inline uval_t inf_get_baseaddr() { return uval_t(getinf(INF_BASEADDR)); } +inline bool inf_set_baseaddr(uval_t _v) { return setinf(INF_BASEADDR, ssize_t(_v)); } + +inline sel_t inf_get_start_ss() { return sel_t(getinf(INF_START_SS)); } +inline bool inf_set_start_ss(sel_t _v) { return setinf(INF_START_SS, ssize_t(_v)); } + +inline sel_t inf_get_start_cs() { return sel_t(getinf(INF_START_CS)); } +inline bool inf_set_start_cs(sel_t _v) { return setinf(INF_START_CS, ssize_t(_v)); } + +inline ea_t inf_get_start_ip() { return ea_t(getinf(INF_START_IP)); } +inline bool inf_set_start_ip(ea_t _v) { return setinf(INF_START_IP, ssize_t(_v)); } + +inline ea_t inf_get_start_ea() { return ea_t(getinf(INF_START_EA)); } +inline bool inf_set_start_ea(ea_t _v) { return setinf(INF_START_EA, ssize_t(_v)); } + +inline ea_t inf_get_start_sp() { return ea_t(getinf(INF_START_SP)); } +inline bool inf_set_start_sp(ea_t _v) { return setinf(INF_START_SP, ssize_t(_v)); } + +inline ea_t inf_get_main() { return ea_t(getinf(INF_MAIN)); } +inline bool inf_set_main(ea_t _v) { return setinf(INF_MAIN, ssize_t(_v)); } + +inline ea_t inf_get_min_ea() { return ea_t(getinf(INF_MIN_EA)); } +inline bool inf_set_min_ea(ea_t _v) { return setinf(INF_MIN_EA, ssize_t(_v)); } + +inline ea_t inf_get_max_ea() { return ea_t(getinf(INF_MAX_EA)); } +inline bool inf_set_max_ea(ea_t _v) { return setinf(INF_MAX_EA, ssize_t(_v)); } + +inline ea_t inf_get_omin_ea() { return ea_t(getinf(INF_OMIN_EA)); } +inline bool inf_set_omin_ea(ea_t _v) { return setinf(INF_OMIN_EA, ssize_t(_v)); } + +inline ea_t inf_get_omax_ea() { return ea_t(getinf(INF_OMAX_EA)); } +inline bool inf_set_omax_ea(ea_t _v) { return setinf(INF_OMAX_EA, ssize_t(_v)); } + +inline ea_t inf_get_lowoff() { return ea_t(getinf(INF_LOWOFF)); } +inline bool inf_set_lowoff(ea_t _v) { return setinf(INF_LOWOFF, ssize_t(_v)); } + +inline ea_t inf_get_highoff() { return ea_t(getinf(INF_HIGHOFF)); } +inline bool inf_set_highoff(ea_t _v) { return setinf(INF_HIGHOFF, ssize_t(_v)); } + +inline uval_t inf_get_maxref() { return uval_t(getinf(INF_MAXREF)); } +inline bool inf_set_maxref(uval_t _v) { return setinf(INF_MAXREF, ssize_t(_v)); } + +inline sval_t inf_get_netdelta() { return sval_t(getinf(INF_NETDELTA)); } +inline bool inf_set_netdelta(sval_t _v) { return setinf(INF_NETDELTA, ssize_t(_v)); } + +inline uchar inf_get_xrefnum() { return uchar(getinf(INF_XREFNUM)); } +inline bool inf_set_xrefnum(uchar _v) { return setinf(INF_XREFNUM, ssize_t(_v)); } + +inline uchar inf_get_type_xrefnum() { return uchar(getinf(INF_TYPE_XREFNUM)); } +inline bool inf_set_type_xrefnum(uchar _v) { return setinf(INF_TYPE_XREFNUM, ssize_t(_v)); } + +inline uchar inf_get_refcmtnum() { return uchar(getinf(INF_REFCMTNUM)); } +inline bool inf_set_refcmtnum(uchar _v) { return setinf(INF_REFCMTNUM, ssize_t(_v)); } + +inline uchar inf_get_xrefflag() { return uchar(getinf(INF_XREFFLAG)); } +inline bool inf_set_xrefflag(uchar _v) { return setinf(INF_XREFFLAG, ssize_t(_v)); } +inline bool inf_show_xref_seg(void) { return getinf_flag(INF_XREFFLAG, SW_SEGXRF); } +inline bool inf_set_show_xref_seg(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_SEGXRF, _v); } +inline bool inf_show_xref_tmarks(void) { return getinf_flag(INF_XREFFLAG, SW_XRFMRK); } +inline bool inf_set_show_xref_tmarks(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_XRFMRK, _v); } +inline bool inf_show_xref_fncoff(void) { return getinf_flag(INF_XREFFLAG, SW_XRFFNC); } +inline bool inf_set_show_xref_fncoff(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_XRFFNC, _v); } +inline bool inf_show_xref_val(void) { return getinf_flag(INF_XREFFLAG, SW_XRFVAL); } +inline bool inf_set_show_xref_val(bool _v=true) { return setinf_flag(INF_XREFFLAG, SW_XRFVAL, _v); } + +inline ushort inf_get_max_autoname_len() { return ushort(getinf(INF_MAX_AUTONAME_LEN)); } +inline bool inf_set_max_autoname_len(ushort _v) { return setinf(INF_MAX_AUTONAME_LEN, ssize_t(_v)); } + +inline char inf_get_nametype() { return char(getinf(INF_NAMETYPE)); } +inline bool inf_set_nametype(char _v) { return setinf(INF_NAMETYPE, ssize_t(_v)); } + +inline uint32 inf_get_short_demnames() { return uint32(getinf(INF_SHORT_DEMNAMES)); } +inline bool inf_set_short_demnames(uint32 _v) { return setinf(INF_SHORT_DEMNAMES, ssize_t(_v)); } + +inline uint32 inf_get_long_demnames() { return uint32(getinf(INF_LONG_DEMNAMES)); } +inline bool inf_set_long_demnames(uint32 _v) { return setinf(INF_LONG_DEMNAMES, ssize_t(_v)); } + +inline uchar inf_get_demnames() { return uchar(getinf(INF_DEMNAMES)); } +inline bool inf_set_demnames(uchar _v) { return setinf(INF_DEMNAMES, ssize_t(_v)); } + +inline uchar inf_get_listnames() { return uchar(getinf(INF_LISTNAMES)); } +inline bool inf_set_listnames(uchar _v) { return setinf(INF_LISTNAMES, ssize_t(_v)); } + +inline uchar inf_get_indent() { return uchar(getinf(INF_INDENT)); } +inline bool inf_set_indent(uchar _v) { return setinf(INF_INDENT, ssize_t(_v)); } + +inline uchar inf_get_comment() { return uchar(getinf(INF_COMMENT)); } +inline bool inf_set_comment(uchar _v) { return setinf(INF_COMMENT, ssize_t(_v)); } + +inline ushort inf_get_margin() { return ushort(getinf(INF_MARGIN)); } +inline bool inf_set_margin(ushort _v) { return setinf(INF_MARGIN, ssize_t(_v)); } + +inline ushort inf_get_lenxref() { return ushort(getinf(INF_LENXREF)); } +inline bool inf_set_lenxref(ushort _v) { return setinf(INF_LENXREF, ssize_t(_v)); } + +inline uint32 inf_get_outflags() { return uint32(getinf(INF_OUTFLAGS)); } +inline bool inf_set_outflags(uint32 _v) { return setinf(INF_OUTFLAGS, ssize_t(_v)); } +inline bool inf_show_void(void) { return getinf_flag(INF_OUTFLAGS, OFLG_SHOW_VOID); } +inline bool inf_set_show_void(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_SHOW_VOID, _v); } +inline bool inf_show_auto(void) { return getinf_flag(INF_OUTFLAGS, OFLG_SHOW_AUTO); } +inline bool inf_set_show_auto(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_SHOW_AUTO, _v); } +inline bool inf_gen_null(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_NULL); } +inline bool inf_set_gen_null(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_NULL, _v); } +inline bool inf_show_line_pref(void) { return getinf_flag(INF_OUTFLAGS, OFLG_SHOW_PREF); } +inline bool inf_set_show_line_pref(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_SHOW_PREF, _v); } +inline bool inf_line_pref_with_seg(void) { return getinf_flag(INF_OUTFLAGS, OFLG_PREF_SEG); } +inline bool inf_set_line_pref_with_seg(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_PREF_SEG, _v); } +inline bool inf_gen_lzero(void) { return getinf_flag(INF_OUTFLAGS, OFLG_LZERO); } +inline bool inf_set_gen_lzero(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_LZERO, _v); } +inline bool inf_gen_org(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_ORG); } +inline bool inf_set_gen_org(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_ORG, _v); } +inline bool inf_gen_assume(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_ASSUME); } +inline bool inf_set_gen_assume(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_ASSUME, _v); } +inline bool inf_gen_tryblks(void) { return getinf_flag(INF_OUTFLAGS, OFLG_GEN_TRYBLKS); } +inline bool inf_set_gen_tryblks(bool _v=true) { return setinf_flag(INF_OUTFLAGS, OFLG_GEN_TRYBLKS, _v); } + +inline uchar inf_get_cmtflg() { return uchar(getinf(INF_CMTFLG)); } +inline bool inf_set_cmtflg(uchar _v) { return setinf(INF_CMTFLG, ssize_t(_v)); } +inline bool inf_show_repeatables(void) { return getinf_flag(INF_CMTFLG, SCF_RPTCMT); } +inline bool inf_set_show_repeatables(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_RPTCMT, _v); } +inline bool inf_show_all_comments(void) { return getinf_flag(INF_CMTFLG, SCF_ALLCMT); } +inline bool inf_set_show_all_comments(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_ALLCMT, _v); } +inline bool inf_hide_comments(void) { return getinf_flag(INF_CMTFLG, SCF_NOCMT); } +inline bool inf_set_hide_comments(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_NOCMT, _v); } +inline bool inf_show_src_linnum(void) { return getinf_flag(INF_CMTFLG, SCF_LINNUM); } +inline bool inf_set_show_src_linnum(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_LINNUM, _v); } +inline bool inf_test_mode(void) { return getinf_flag(INF_CMTFLG, SCF_TESTMODE); } +inline bool inf_show_hidden_insns(void) { return getinf_flag(INF_CMTFLG, SCF_SHHID_ITEM); } +inline bool inf_set_show_hidden_insns(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_SHHID_ITEM, _v); } +inline bool inf_show_hidden_funcs(void) { return getinf_flag(INF_CMTFLG, SCF_SHHID_FUNC); } +inline bool inf_set_show_hidden_funcs(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_SHHID_FUNC, _v); } +inline bool inf_show_hidden_segms(void) { return getinf_flag(INF_CMTFLG, SCF_SHHID_SEGM); } +inline bool inf_set_show_hidden_segms(bool _v=true) { return setinf_flag(INF_CMTFLG, SCF_SHHID_SEGM, _v); } + +inline uchar inf_get_limiter() { return uchar(getinf(INF_LIMITER)); } +inline bool inf_set_limiter(uchar _v) { return setinf(INF_LIMITER, ssize_t(_v)); } +inline bool inf_is_limiter_thin(void) { return getinf_flag(INF_LIMITER, LMT_THIN); } +inline bool inf_set_limiter_thin(bool _v=true) { return setinf_flag(INF_LIMITER, LMT_THIN, _v); } +inline bool inf_is_limiter_thick(void) { return getinf_flag(INF_LIMITER, LMT_THICK); } +inline bool inf_set_limiter_thick(bool _v=true) { return setinf_flag(INF_LIMITER, LMT_THICK, _v); } +inline bool inf_is_limiter_empty(void) { return getinf_flag(INF_LIMITER, LMT_EMPTY); } +inline bool inf_set_limiter_empty(bool _v=true) { return setinf_flag(INF_LIMITER, LMT_EMPTY, _v); } + +inline short inf_get_bin_prefix_size() { return short(getinf(INF_BIN_PREFIX_SIZE)); } +inline bool inf_set_bin_prefix_size(short _v) { return setinf(INF_BIN_PREFIX_SIZE, ssize_t(_v)); } + +inline uchar inf_get_prefflag() { return uchar(getinf(INF_PREFFLAG)); } +inline bool inf_set_prefflag(uchar _v) { return setinf(INF_PREFFLAG, ssize_t(_v)); } +inline bool inf_prefix_show_segaddr(void) { return getinf_flag(INF_PREFFLAG, PREF_SEGADR); } +inline bool inf_set_prefix_show_segaddr(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_SEGADR, _v); } +inline bool inf_prefix_show_funcoff(void) { return getinf_flag(INF_PREFFLAG, PREF_FNCOFF); } +inline bool inf_set_prefix_show_funcoff(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_FNCOFF, _v); } +inline bool inf_prefix_show_stack(void) { return getinf_flag(INF_PREFFLAG, PREF_STACK); } +inline bool inf_set_prefix_show_stack(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_STACK, _v); } +inline bool inf_prefix_truncate_opcode_bytes(void) { return getinf_flag(INF_PREFFLAG, PREF_PFXTRUNC); } +inline bool inf_set_prefix_truncate_opcode_bytes(bool _v=true) { return setinf_flag(INF_PREFFLAG, PREF_PFXTRUNC, _v); } + +inline uchar inf_get_strlit_flags() { return uchar(getinf(INF_STRLIT_FLAGS)); } +inline bool inf_set_strlit_flags(uchar _v) { return setinf(INF_STRLIT_FLAGS, ssize_t(_v)); } +inline bool inf_strlit_names(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_GEN); } +inline bool inf_set_strlit_names(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_GEN, _v); } +inline bool inf_strlit_name_bit(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_AUTO); } +inline bool inf_set_strlit_name_bit(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_AUTO, _v); } +inline bool inf_strlit_serial_names(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_SERIAL); } +inline bool inf_set_strlit_serial_names(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_SERIAL, _v); } +inline bool inf_unicode_strlits(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_UNICODE); } +inline bool inf_set_unicode_strlits(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_UNICODE, _v); } +inline bool inf_strlit_autocmt(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_COMMENT); } +inline bool inf_set_strlit_autocmt(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_COMMENT, _v); } +inline bool inf_strlit_savecase(void) { return getinf_flag(INF_STRLIT_FLAGS, STRF_SAVECASE); } +inline bool inf_set_strlit_savecase(bool _v=true) { return setinf_flag(INF_STRLIT_FLAGS, STRF_SAVECASE, _v); } + +inline uchar inf_get_strlit_break() { return uchar(getinf(INF_STRLIT_BREAK)); } +inline bool inf_set_strlit_break(uchar _v) { return setinf(INF_STRLIT_BREAK, ssize_t(_v)); } + +inline char inf_get_strlit_zeroes() { return char(getinf(INF_STRLIT_ZEROES)); } +inline bool inf_set_strlit_zeroes(char _v) { return setinf(INF_STRLIT_ZEROES, ssize_t(_v)); } + +inline int32 inf_get_strtype() { return int32(getinf(INF_STRTYPE)); } +inline bool inf_set_strtype(int32 _v) { return setinf(INF_STRTYPE, ssize_t(_v)); } + +inline uval_t inf_get_strlit_sernum() { return uval_t(getinf(INF_STRLIT_SERNUM)); } +inline bool inf_set_strlit_sernum(uval_t _v) { return setinf(INF_STRLIT_SERNUM, ssize_t(_v)); } + +inline uval_t inf_get_datatypes() { return uval_t(getinf(INF_DATATYPES)); } +inline bool inf_set_datatypes(uval_t _v) { return setinf(INF_DATATYPES, ssize_t(_v)); } + +inline uint32 inf_get_abibits() { return uint32(getinf(INF_ABIBITS)); } +inline bool inf_set_abibits(uint32 _v) { return setinf(INF_ABIBITS, ssize_t(_v)); } +inline bool inf_is_mem_aligned4(void) { return getinf_flag(INF_ABIBITS, ABI_8ALIGN4); } +inline bool inf_set_mem_aligned4(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_8ALIGN4, _v); } +inline bool inf_pack_stkargs(void) { return getinf_flag(INF_ABIBITS, ABI_PACK_STKARGS); } +inline bool inf_set_pack_stkargs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_PACK_STKARGS, _v); } +inline bool inf_big_arg_align(void) { return getinf_flag(INF_ABIBITS, ABI_BIGARG_ALIGN); } +inline bool inf_set_big_arg_align(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_BIGARG_ALIGN, _v); } +inline bool inf_stack_ldbl(void) { return getinf_flag(INF_ABIBITS, ABI_STACK_LDBL); } +inline bool inf_set_stack_ldbl(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_STACK_LDBL, _v); } +inline bool inf_stack_varargs(void) { return getinf_flag(INF_ABIBITS, ABI_STACK_VARARGS); } +inline bool inf_set_stack_varargs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_STACK_VARARGS, _v); } +inline bool inf_is_hard_float(void) { return getinf_flag(INF_ABIBITS, ABI_HARD_FLOAT); } +inline bool inf_set_hard_float(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_HARD_FLOAT, _v); } +inline bool inf_abi_set_by_user(void) { return getinf_flag(INF_ABIBITS, ABI_SET_BY_USER); } +inline bool inf_set_abi_set_by_user(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_SET_BY_USER, _v); } +inline bool inf_use_gcc_layout(void) { return getinf_flag(INF_ABIBITS, ABI_GCC_LAYOUT); } +inline bool inf_set_use_gcc_layout(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_GCC_LAYOUT, _v); } +inline bool inf_map_stkargs(void) { return getinf_flag(INF_ABIBITS, ABI_MAP_STKARGS); } +inline bool inf_set_map_stkargs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_MAP_STKARGS, _v); } +inline bool inf_huge_arg_align(void) { return getinf_flag(INF_ABIBITS, ABI_HUGEARG_ALIGN); } +inline bool inf_set_huge_arg_align(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_HUGEARG_ALIGN, _v); } +inline bool inf_explicit_stkoffs(void) { return getinf_flag(INF_ABIBITS, ABI_EXPLICIT_STKOFFS); } +inline bool inf_set_explicit_stkoffs(bool _v=true) { return setinf_flag(INF_ABIBITS, ABI_EXPLICIT_STKOFFS, _v); } + +inline uint32 inf_get_appcall_options() { return uint32(getinf(INF_APPCALL_OPTIONS)); } +inline bool inf_set_appcall_options(uint32 _v) { return setinf(INF_APPCALL_OPTIONS, ssize_t(_v)); } + +inline ea_t inf_get_privrange_start_ea() { return ea_t(getinf(INF_PRIVRANGE_START_EA)); } +inline bool inf_set_privrange_start_ea(ea_t _v) { return setinf(INF_PRIVRANGE_START_EA, ssize_t(_v)); } + +inline ea_t inf_get_privrange_end_ea() { return ea_t(getinf(INF_PRIVRANGE_END_EA)); } +inline bool inf_set_privrange_end_ea(ea_t _v) { return setinf(INF_PRIVRANGE_END_EA, ssize_t(_v)); } + +inline comp_t inf_get_cc_id() { return comp_t(getinf(INF_CC_ID)); } +inline bool inf_set_cc_id(comp_t _v) { return setinf(INF_CC_ID, ssize_t(_v)); } + +inline cm_t inf_get_cc_cm() { return cm_t(getinf(INF_CC_CM)); } +inline bool inf_set_cc_cm(cm_t _v) { return setinf(INF_CC_CM, ssize_t(_v)); } + +inline uchar inf_get_cc_size_i() { return uchar(getinf(INF_CC_SIZE_I)); } +inline bool inf_set_cc_size_i(uchar _v) { return setinf(INF_CC_SIZE_I, ssize_t(_v)); } + +inline uchar inf_get_cc_size_b() { return uchar(getinf(INF_CC_SIZE_B)); } +inline bool inf_set_cc_size_b(uchar _v) { return setinf(INF_CC_SIZE_B, ssize_t(_v)); } + +inline uchar inf_get_cc_size_e() { return uchar(getinf(INF_CC_SIZE_E)); } +inline bool inf_set_cc_size_e(uchar _v) { return setinf(INF_CC_SIZE_E, ssize_t(_v)); } + +inline uchar inf_get_cc_defalign() { return uchar(getinf(INF_CC_DEFALIGN)); } +inline bool inf_set_cc_defalign(uchar _v) { return setinf(INF_CC_DEFALIGN, ssize_t(_v)); } + +inline uchar inf_get_cc_size_s() { return uchar(getinf(INF_CC_SIZE_S)); } +inline bool inf_set_cc_size_s(uchar _v) { return setinf(INF_CC_SIZE_S, ssize_t(_v)); } + +inline uchar inf_get_cc_size_l() { return uchar(getinf(INF_CC_SIZE_L)); } +inline bool inf_set_cc_size_l(uchar _v) { return setinf(INF_CC_SIZE_L, ssize_t(_v)); } + +inline uchar inf_get_cc_size_ll() { return uchar(getinf(INF_CC_SIZE_LL)); } +inline bool inf_set_cc_size_ll(uchar _v) { return setinf(INF_CC_SIZE_LL, ssize_t(_v)); } + +inline uchar inf_get_cc_size_ldbl() { return uchar(getinf(INF_CC_SIZE_LDBL)); } +inline bool inf_set_cc_size_ldbl(uchar _v) { return setinf(INF_CC_SIZE_LDBL, ssize_t(_v)); } + +inline bool inf_get_procname(char *buf, size_t bufsize=IDAINFO_PROCNAME_SIZE) +{ + return getinf_buf(INF_PROCNAME, buf, bufsize); +} +inline qstring inf_get_procname() +{ + char buf[IDAINFO_PROCNAME_SIZE]; + if ( !getinf_buf(INF_PROCNAME, buf, sizeof(buf)) ) + buf[0] = '\0'; + return qstring(buf); +} +inline bool inf_set_procname(const char *_v, size_t len=size_t(-1)) +{ + if ( _v == NULL ) + return false; + if ( len == size_t(-1) ) + len = ::qstrlen(_v); + return setinf_buf(INF_PROCNAME, _v, qmin(len, IDAINFO_PROCNAME_SIZE)); +} + +inline bool inf_get_strlit_pref(char *buf, size_t bufsize=IDAINFO_STRLIT_PREF_SIZE) +{ + return getinf_buf(INF_STRLIT_PREF, buf, bufsize); +} +inline qstring inf_get_strlit_pref() +{ + char buf[IDAINFO_STRLIT_PREF_SIZE]; + if ( !getinf_buf(INF_STRLIT_PREF, buf, sizeof(buf)) ) + buf[0] = '\0'; + return qstring(buf); +} +inline bool inf_set_strlit_pref(const char *_v, size_t len=size_t(-1)) +{ + if ( _v == NULL ) + return false; + if ( len == size_t(-1) ) + len = ::qstrlen(_v); + return setinf_buf(INF_STRLIT_PREF, _v, qmin(len, IDAINFO_STRLIT_PREF_SIZE)); +} + +inline bool inf_get_cc(compiler_info_t *out) { return getinf_buf(INF_CC, out, sizeof(*out)); } +inline bool inf_set_cc(const compiler_info_t &_v) { return setinf_buf(INF_CC, &_v, sizeof(_v)); } + +inline bool inf_get_privrange(range_t *out) { return getinf_buf(INF_PRIVRANGE, out, sizeof(*out)); } +inline bool inf_set_privrange(const range_t &_v) { return setinf_buf(INF_PRIVRANGE, &_v, sizeof(_v)); } + +// </INF_ACCESSORS> + +inline range_t inf_get_privrange() { range_t r; inf_get_privrange(&r); return r; } + +/// Get/set low/high 16bit halves of inf.af +inline ushort inf_get_af_low() { return inf_get_af() & 0xffff; } +inline void inf_set_af_low(ushort saf) { uint32 af = (inf_get_af() & 0xffff0000) | saf; inf_set_af(af); } +inline ushort inf_get_af_high() { return (inf_get_af() >> 16) & 0xffff; } +inline void inf_set_af_high(ushort saf2) { uint32 af = (inf_get_af() & 0xffff) | (saf2 << 16); inf_set_af(af); } +/// Get/set low 16bit half of inf.af2 +inline ushort inf_get_af2_low() { return inf_get_af2() & 0xffff; } +inline void inf_set_af2_low(ushort saf) { uint32 af2 = (inf_get_af2() & 0xffff0000) | saf; inf_set_af2(af2); } + +inline int inf_get_pack_mode() +{ + uint32 lflags = inf_get_lflags(); + return (lflags & LFLG_COMPRESS) != 0 ? IDB_COMPRESSED + : (lflags & LFLG_PACK) != 0 ? IDB_PACKED + : IDB_UNPACKED; +} + +inline int inf_set_pack_mode(int pack_mode) +{ + int old = inf_get_pack_mode(); + uint32 lflags = inf_get_lflags(); + setflag(lflags, LFLG_COMPRESS, pack_mode == IDB_COMPRESSED); + setflag(lflags, LFLG_PACK, pack_mode == IDB_PACKED); + inf_set_lflags(lflags); + return old; +} + +inline void inf_inc_database_change_count(int cnt=1) +{ inf_set_database_change_count(inf_get_database_change_count()+cnt); } + +/// Get #DEMNAM_MASK bits of #demnames +inline uchar inf_get_demname_form(void) { return uchar(inf_get_demnames() & DEMNAM_MASK); } + +inline uval_t inf_postinc_strlit_sernum(uval_t cnt=1) +{ + uval_t was = inf_get_strlit_sernum(); + inf_set_strlit_sernum(was + cnt); + return was; +} + +inline bool inf_like_binary(void) +{ return is_filetype_like_binary(inf_get_filetype()); } + + + +//------------------------------------------------------------------------- +/// max number of operands allowed for an instruction + +#define UA_MAXOP 8 + + +/// Get default disassembly line options + +inline int calc_default_idaplace_flags(void) +{ + return 0; +} + +//------------------------------------------------------------------------- +/// \def{MAXADDR, Start of the private netnode range} +/// In the past this was the maximal address of the disassembly listing. +#ifdef __EA64__ +#ifdef __GNUC__ +#define MAXADDR 0xFF00000000000000ll +#else +#define MAXADDR 0xFF00000000000000ui64 +#endif +#else +#define MAXADDR 0xFF000000L +#endif + + +//------------------------------------------------------------------------- +/// Convert (sel,off) value to a linear address + +inline ea_t idaapi to_ea(sel_t reg_cs, uval_t reg_ip) +{ + return (reg_cs << 4) + reg_ip; +} + +/// \def{IDB_EXT32, Database file extension for 32-bit programs} +/// \def{IDB_EXT64, Database file extension for 64-bit programs} +/// \def{IDB_EXT, Database file extension} +#define IDB_EXT32 "idb" +#define IDB_EXT64 "i64" +#ifdef __EA64__ +#define IDB_EXT IDB_EXT64 +#else +#define IDB_EXT IDB_EXT32 +#endif + +//-------------------------------------------------------------------------- +/// Callback provided to hook_to_notification_point(). +/// A plugin can hook to a notification point and receive notifications +/// of all major events in IDA. The callback function will be called +/// for each event. +/// \param user_data data supplied in call to hook_to_notification_point() +/// \param notification_code processor_t::event_t or ::ui_notification_t or +/// debugger_t::event_t, depending on the hook type +/// \param va additional parameters supplied with the notification. +/// see the event descriptions for information +/// \retval 0 ok, the event should be processed further +/// \retval !=0 the event is blocked and should be discarded. +/// in the case of processor modules, the returned value is used +/// as the return value of processor_t::notify() + +typedef ssize_t idaapi hook_cb_t(void *user_data, int notification_code, va_list va); + +/// Types of events that be hooked to with hook_to_notification_point() +enum hook_type_t +{ + HT_IDP, ///< Hook to the processor module. + ///< The callback will receive all processor_t::event_t events. + HT_UI, ///< Hook to the user interface. + ///< The callback will receive all ::ui_notification_t events. + HT_DBG, ///< Hook to the debugger. + ///< The callback will receive all ::dbg_notification_t events. + HT_IDB, ///< Hook to the database events. + ///< These events are separated from the ::HT_IDP group + ///< to speed things up (there are too many plugins and + ///< modules hooking to the ::HT_IDP). Some essential events + ///< are still generated in th ::HT_IDP group: + ///< make_code, make_data + ///< This list is not exhaustive. + ///< A common trait of all events in this group: the kernel + ///< does not expect any reaction to the event and does not + ///< check the return code. For event names, see ::idb_event. + HT_DEV, ///< Internal debugger events. + ///< Not stable and undocumented for the moment + HT_VIEW, ///< Custom/IDA views notifications. + ///< Refer to ::view_notification_t + ///< for notification codes + HT_OUTPUT, ///< Output window notifications. + ///< Refer to ::msg_notification_t + ///< (::view_notification_t) + HT_GRAPH, ///< Handling graph operations + ///< (::graph_notification_t) + HT_IDD, ///< Hook to the debugger plugin. + ///< The callback will receive all debugger_t::event_t events. + HT_LAST +}; + + +/// Register a callback for a class of events in IDA + +idaman bool ida_export hook_to_notification_point( + hook_type_t hook_type, + hook_cb_t *cb, + void *user_data = NULL); + + +/// Unregister a callback (also see hook_to_notification_point()). +/// A plugin should unhook before being unloaded +/// (preferably in its termination function). +/// If different callbacks have the same callback function pointer +/// and user_data is not NULL, only the callback whose associated +/// user defined data matches will be removed. +/// \return number of unhooked functions. + +idaman int ida_export unhook_from_notification_point( + hook_type_t hook_type, + hook_cb_t *cb, + void *user_data = NULL); + + +/// Generate event notification. +/// \param hook_type hook type +/// \param notification_code event code +/// \param va additional arguments +/// \return !=0: event processed + +idaman ssize_t ida_export invoke_callbacks(hook_type_t hook_type, int notification_code, va_list va); + + +/// Implements action to take when the event was processed by the notification callback +/// (i.e. when the notification callback returns non-zero code). +/// All the registered (\ref register_post_event_visitor()) post-event visitors will be +/// called in turn after the event was processed by one of the notification callbacks. + +struct post_event_visitor_t +{ + /// Action for post-event management. + /// May change the result of the processed event or data carried by the event. + /// \param code the notification callback or other post-event action + /// return code (result of the processed event) + /// \param notification_code event code + /// \param va additional arguments, the same as for processed event + /// \return result of the event processed + + virtual ssize_t idaapi handle_post_event( + ssize_t code, + int notification_code, + va_list va) = 0; + + virtual ~post_event_visitor_t() {} +}; + + +/// Register the post-event visitor. +/// The kernel will not take ownership, nor delete the VISITOR instance. +/// Therefore, it's up to the plugin to handle it. +/// In addition, the post_event_visitor_t will be automatically unregistered +/// when the owner plugin is unloaded from memory. +/// \param hook_type hook type +/// \param visitor post-event visitor +/// \param owner the owner plugin of the post_event_visitor_t type +/// \return success + +idaman bool ida_export register_post_event_visitor( + hook_type_t hook_type, + post_event_visitor_t *visitor, + const plugmod_t *owner); + + +/// Unregister the post-event visitor. +/// \param hook_type hook type +/// \param visitor post-event visitor +/// \return success + +idaman bool ida_export unregister_post_event_visitor( + hook_type_t hook_type, + post_event_visitor_t *visitor); + + +/// Get the current database context ID +/// \return the database context ID, or -1 if no current database +idaman ssize_t ida_export get_dbctx_id(); + +/// Get number of database contexts +/// \return number of database contexts +idaman size_t ida_export get_dbctx_qty(); + +/// Switch to the database with the provided context ID +/// \param idx the index of the database to switch to +/// \return the current dbctx_t instance or nullptr +idaman struct dbctx_t *ida_export switch_dbctx(size_t idx); + + + +#endif // _IDA_HPP diff --git a/idasdk76/include/ida_highlighter.hpp b/idasdk76/include/ida_highlighter.hpp new file mode 100644 index 0000000..e09fd2f --- /dev/null +++ b/idasdk76/include/ida_highlighter.hpp @@ -0,0 +1,146 @@ +#ifndef IDA_HIGHLIGHTER +#define IDA_HIGHLIGHTER + +#include <expr.hpp> + +idaman void ida_export code_highlight_block(void *context, highlighter_cbs_t *highlighter_cbs, const qstring &text); + +// returns the length of text to colorize +// negative values may have special meaning in the future. +typedef ssize_t idaapi external_colorizer_t(syntax_highlight_style *color, const char *str); +typedef qvector<external_colorizer_t *> external_colorizers_t; + +// returns true if identifier is colorized +typedef bool idaapi external_ident_colorizer_t(syntax_highlight_style *color, const qstring &ident); +typedef qvector<external_ident_colorizer_t *> external_ident_colorizers_t; + + +#define MLTCMTMASK 0xF +#define PREPROC_FLAG 0x10 + +// Common implementation of syntax_highlighter_t used in different parts of IDA +//-V:ida_syntax_highlighter_t:730 not all members of a class are initialized inside the constructor +struct ida_syntax_highlighter_t : syntax_highlighter_t +{ +protected: + // keys of keywords_t point to memory from keyword_strings. + // once allocated, this buffer won't be moved in the memory. + qstrvec_t keyword_memory; + // helper class so that keywords_t gets sorted by string contents, not pointer values. + struct plain_char_ptr_t + { + const char *ptr; + plain_char_ptr_t(const char *p = NULL) : ptr(p) {} + bool operator <(const plain_char_ptr_t &r) const + { + return strcmp(ptr, r.ptr) < 0; + } + bool operator ==(const plain_char_ptr_t &r) const + { + return strcmp(ptr, r.ptr) == 0; + } + }; + struct multicmt_t + { + qstring open_multicmt; + qstring close_multicmt; + multicmt_t() {} + multicmt_t(const char *_open_multicmt, const char *_close_multicmt) : + open_multicmt(_open_multicmt), + close_multicmt(_close_multicmt) + {} + }; + + // typedef std::map<plain_char_ptr_t, syntax_highlight_style> keywords_t; + struct keywords_style_t + { + qvector<plain_char_ptr_t> keywords; + syntax_highlight_style style; + }; + typedef qvector<keywords_style_t> keywords_t; + //typedef qvector<plain_char_ptr_t> keywords_t; + typedef qvector<multicmt_t> multicmtvec_t; + keywords_t keywords; + + qstring open_cmt; // string that opens a regular line comment + multicmtvec_t multicmts; + char literal_closer; // either close_strconst or close_chrconst for the current literal + + // color mappings + syntax_highlight_style text_color = HF_DEFAULT; + syntax_highlight_style comment_color = HF_COMMENT; + syntax_highlight_style string_color = HF_STRING; + syntax_highlight_style preprocessor_color = HF_PREPROC; + + external_colorizers_t external_colorizers; + external_ident_colorizers_t external_ident_colorizers; + + // work variables + const char *input; // pointer to the start of the input buffer + const char *pending; // pointer in the input buffer + syntax_highlight_style style = HF_DEFAULT; // current highlighting style + + bool pending_nonspaces_present(const char *end) + { + for ( const char *p = pending; p != end; ++p ) + if ( !qisspace(*p) ) + return true; + return false; + } + + const char *parse_literal_const(highlighter_cbs_t *highlighter_cbs, const char *ptr, char literal_closer); + void flush_output(highlighter_cbs_t *highlighter_cbs, const char *ptr, syntax_highlight_style style); + void handle_cmt(highlighter_cbs_t *highlighter_cbs, int mcmt_idx, const char **ptr); + void handle_preproc(highlighter_cbs_t *highlighter_cbs, const char **ptr); + +public: + // if any of the following features is not needed, just zero them out: + char open_strconst; // character that opens a string constant + char close_strconst; // character that closes a string constant + char open_chrconst; // character that closes a character constant + char close_chrconst; // character that opens a character constant + char escape_char; // backslash + char preprocessor_char; // # + + ida_syntax_highlighter_t() : syntax_highlighter_t(&code_highlight_block) {} + + void highlight_block_ex(highlighter_cbs_t *highlighter_cbs, const qstring &text); + void add_external_colorizer(external_colorizer_t *th) { external_colorizers.push_back(th); } + void add_external_ident_colorizer(external_ident_colorizer_t *th) { external_ident_colorizers.push_back(th); } + void set_open_cmt(const char *begin) { open_cmt = begin; } + void add_multi_line_comment(const char *begin, const char *end) + { + multicmt_t &mcmt = multicmts.push_back(); + mcmt.open_multicmt = begin; + mcmt.close_multicmt = end; + } + + void add_keywords(const char *kwstr, syntax_highlight_style _style) + { + char *ctx; + // in order not to allocate every keyword separately, we allocate the whole + // kwstr string at once and will just store pointers to it in the map. + qstring &mem = keyword_memory.push_back(); + mem = kwstr; + keywords_style_t *pair_p = NULL; + for ( int i = 0; i < keywords.size(); i++ ) + { + if ( keywords[i].style == _style ) + { + pair_p = &keywords[i]; + break; + } + } + if ( pair_p == NULL ) + { + keywords_style_t &pair = keywords.push_back(); + pair_p = &pair; + pair_p->style = _style; + } + for ( char *kw = qstrtok(mem.begin(), "|", &ctx); kw != NULL; kw = qstrtok(NULL, "|", &ctx) ) + pair_p->keywords.push_back(kw); + } +}; + + +#endif // IDA_HIGHLIGHTER diff --git a/idasdk76/include/idd.hpp b/idasdk76/include/idd.hpp new file mode 100644 index 0000000..633d1e7 --- /dev/null +++ b/idasdk76/include/idd.hpp @@ -0,0 +1,1966 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _IDD_HPP +#define _IDD_HPP + +#include <ieee.h> +#include <range.hpp> +#include <ua.hpp> + +/*! \file idd.hpp + + \brief Contains definition of the interface to IDD modules. + + The interface consists of structures describing the target + debugged processor and a debugging API. +*/ + +/// The IDD interface version number +#define IDD_INTERFACE_VERSION 27 + +class idc_value_t; +class tinfo_t; + +//==================================================================== +// +// Process and Threads +// + +typedef int pid_t; ///< process id +typedef int thid_t; ///< thread id + +#define NO_PROCESS pid_t(-1) ///< No process +#define NO_THREAD 0 ///< No thread. + ///< in ::PROCESS_STARTED this value + ///< can be used to specify that + ///< the main thread has not been created. + ///< It will be initialized later + ///< by a ::THREAD_STARTED event. + +/// Process information +struct process_info_t +{ + pid_t pid; ///< process id + qstring name; ///< process name +}; +DECLARE_TYPE_AS_MOVABLE(process_info_t); +typedef qvector<process_info_t> procinfo_vec_t; + +//-------------------------------------------------------------------- +/// Runtime attributes of the debugger/process. +/// It is guaranteed that these attributes are really valid after start/attach process +struct debapp_attrs_t +{ + int32 cbsize; ///< control field: size of this structure + + /// address size of the process. + /// Since 64-bit debuggers usually can debug 32-bit applications, we cannot + /// rely on sizeof(ea_t) to detect the current address size. The following + /// variable should be used instead. It is initialized with 8 for 64-bit + /// debuggers but they should adjust it as soon as they learn that a + /// 32-bit application is being debugged. + /// For 32-bit debuggers it is initialized with 4. + int addrsize; + + qstring platform; ///< platform name process is running/debugging under. + ///< (is used as a key value in exceptions.cfg) + +/// \def{DEF_ADDRSIZE, Default address size - see debapp_attrs_t::addrsize} +#ifdef __EA64__ +#define DEF_ADDRSIZE 8 +#else +#define DEF_ADDRSIZE 4 +#endif + + int is_be; + + /// Constructor - initialize with #DEF_ADDRSIZE + debapp_attrs_t() + : cbsize(sizeof(debapp_attrs_t)), + addrsize(DEF_ADDRSIZE), + is_be(-1) + {} +}; + +//==================================================================== +// +// Registers +// + +typedef unsigned char register_class_t; ///< Each register is associated to + ///< a register class. + ///< example: "segment", "mmx", ... + +/// Debuggee register information +struct register_info_t +{ + const char *name; ///< Register name. + uint32 flags; ///< \ref REGISTER_ +/// \defgroup REGISTER_ Register info attribute flags +/// Used by register_info_t::flags +//@{ +#define REGISTER_READONLY 0x0001 ///< the user can't modify the current value of this register +#define REGISTER_IP 0x0002 ///< instruction pointer +#define REGISTER_SP 0x0004 ///< stack pointer +#define REGISTER_FP 0x0008 ///< frame pointer +#define REGISTER_ADDRESS 0x0010 ///< may contain an address +#define REGISTER_CS 0x0020 ///< code segment +#define REGISTER_SS 0x0040 ///< stack segment +#define REGISTER_NOLF 0x0080 ///< displays this register without returning to the next line + ///< allowing the next register to be displayed to its right (on the same line) +#define REGISTER_CUSTFMT 0x0100 ///< register should be displayed using a custom data format. + ///< the format name is in bit_strings[0] + ///< the corresponding ::regval_t will use ::bytevec_t +//@} + register_class_t register_class; ///< segment, mmx, etc. + op_dtype_t dtype; ///< Register size (see \ref dt_) + const char *const *bit_strings; ///< strings corresponding to each bit of the register. + ///< (NULL = no bit, same name = multi-bits mask) + uval_t default_bit_strings_mask; ///< mask of default bits +}; +DECLARE_TYPE_AS_MOVABLE(register_info_t); +typedef qvector<register_info_t> register_info_vec_t; + +//-------------------------------------------------------------------------- +struct dynamic_register_set_t +{ + typedef qvector<const char *> const_char_vec_t; + + register_info_vec_t ri_vec; + qstrvec_t strvec; + const_char_vec_t classname_ptrs; + qvector<const_char_vec_t> bit_strings_ptrs_vec; + + void clear(void) + { + ri_vec.clear(); + strvec.clear(); + classname_ptrs.clear(); + bit_strings_ptrs_vec.clear(); + } + + void add_register( + const char *name, + int flags, + op_dtype_t dtype, + register_class_t register_class, + const char *const *bit_strings, + uval_t bits_mask) + { + // Allocate bit_strings. + if ( bit_strings != nullptr ) + { + size_t num_bits = (flags & REGISTER_CUSTFMT) != 0 ? 1 + : dtype == dt_word ? 16 + : dtype == dt_dword ? 32 + : dtype == dt_qword ? 64 + : 0; + QASSERT(1795, num_bits != 0); + const_char_vec_t &ptrvec = bit_strings_ptrs_vec.push_back(); + ptrvec.resize(num_bits, nullptr); + for ( size_t i = 0; i < num_bits; i++ ) + { + if ( bit_strings[i] != nullptr ) + { + qstring &field_name = strvec.push_back(); + field_name = bit_strings[i]; + ptrvec[i] = field_name.c_str(); + } + } + bit_strings = ptrvec.begin(); + } + + // Allocate name. + qstring ®name = strvec.push_back(); + regname = name; + + // Add entry for register. + register_info_t &ri = ri_vec.push_back(); + ri.name = regname.c_str(); + ri.flags = flags; + ri.dtype = dtype; + ri.register_class = register_class; + ri.bit_strings = bit_strings; + ri.default_bit_strings_mask = bits_mask; + } + + void set_regclasses(const char **register_classes) + { + while ( *register_classes != nullptr ) + { + qstring ®ister_class = strvec.push_back(); + register_class = *register_classes++; + classname_ptrs.push_back(register_class.begin()); + } + classname_ptrs.push_back(nullptr); + } + + // Values for debugger_t. + size_t nregs(void) { return ri_vec.size(); } + register_info_t *registers(void) { return ri_vec.begin(); } + const char **regclasses(void) { return classname_ptrs.begin(); } +}; + +// helper functions: +idaman THREAD_SAFE void ida_export serialize_dynamic_register_set( + bytevec_t *buf, + dynamic_register_set_t &idaregs); +idaman THREAD_SAFE void ida_export deserialize_dynamic_register_set( + dynamic_register_set_t *idaregs, + memory_deserializer_t &mmdsr); + +//==================================================================== +// +// Memory +// + +/// Used by debugger modules to report memory are information to IDA kernel. +/// It is ok to return empty fields if information is not available. +struct memory_info_t : public range_t +{ + qstring name; ///< Memory range name + qstring sclass; ///< Memory range class name + ea_t sbase; ///< Segment base (meaningful only for segmented architectures, e.g. 16-bit x86) + ///< The base is specified in paragraphs (i.e. shifted to the right by 4) + uchar bitness; ///< Number of bits in segment addresses (0-16bit, 1-32bit, 2-64bit) + uchar perm; ///< Memory range permissions (0-no information): see segment.hpp + memory_info_t(void) + : sbase(0),bitness(0),perm(0) {} + bool operator ==(const memory_info_t &r) const + { + return start_ea == r.start_ea + && end_ea == r.end_ea + && name == r.name + && sclass == r.sclass + && sbase == r.sbase + && bitness == r.bitness + && perm == r.perm; + } + bool operator !=(const memory_info_t &r) const { return !(*this == r); } +}; +DECLARE_TYPE_AS_MOVABLE(memory_info_t); +typedef qvector<memory_info_t> meminfo_vec_t; ///< vector of memory info objects + +/// Used by debugger modules to keep track of images that are not mapped uniformly into memory. +struct scattered_segm_t : public range_t +{ + qstring name; ///< name of the segment +}; +DECLARE_TYPE_AS_MOVABLE(scattered_segm_t); +typedef qvector<scattered_segm_t> scattered_image_t; ///< vector of scattered segments + +//==================================================================== +// +// Debug events +// + +/// Debug event codes +enum event_id_t +{ + NO_EVENT = 0x00000000, ///< Not an interesting event. This event can be + ///< used if the debugger module needs to return + ///< an event but there are no valid events. + PROCESS_STARTED = 0x00000001, ///< New process has been started. + PROCESS_EXITED = 0x00000002, ///< Process has been stopped. + THREAD_STARTED = 0x00000004, ///< New thread has been started. + THREAD_EXITED = 0x00000008, ///< Thread has been stopped. + BREAKPOINT = 0x00000010, ///< Breakpoint has been reached. IDA will complain + ///< about unknown breakpoints, they should be reported + ///< as exceptions. + STEP = 0x00000020, ///< One instruction has been executed. Spurious + ///< events of this kind are silently ignored by IDA. + EXCEPTION = 0x00000040, ///< Exception. + LIB_LOADED = 0x00000080, ///< New library has been loaded. + LIB_UNLOADED = 0x00000100, ///< Library has been unloaded. + INFORMATION = 0x00000200, ///< User-defined information. + ///< This event can be used to return empty information + ///< This will cause IDA to call get_debug_event() + ///< immediately once more. + PROCESS_ATTACHED = 0x00000400, ///< Successfully attached to running process. + PROCESS_DETACHED = 0x00000800, ///< Successfully detached from process. + PROCESS_SUSPENDED= 0x00001000, ///< Process has been suspended. + ///< This event can be used by the debugger module + ///< to signal if the process spontaneously gets + ///< suspended (not because of an exception, + ///< breakpoint, or single step). IDA will silently + ///< switch to the 'suspended process' mode without + ///< displaying any messages. + TRACE_FULL = 0x00002000, ///< The trace buffer of the tracer module is full + ///< and IDA needs to read it before continuing +}; + +// helper functions: +struct debug_event_t; +idaman THREAD_SAFE void ida_export free_debug_event(debug_event_t *ev); +idaman THREAD_SAFE void ida_export copy_debug_event(debug_event_t *ev, const debug_event_t &r); +idaman THREAD_SAFE void ida_export set_debug_event_code(debug_event_t *ev, event_id_t id); + +/// Describes a module load event. +/// (see ::PROCESS_STARTED, ::PROCESS_ATTACHED, ::LIB_LOADED) +struct modinfo_t +{ + qstring name; ///< full name of the module + ea_t base; ///< module base address. if unknown pass #BADADDR + asize_t size; ///< module size. if unknown pass 0 + ea_t rebase_to; ///< if not #BADADDR, then rebase the program to the specified address +}; +DECLARE_TYPE_AS_MOVABLE(modinfo_t); +typedef qvector<modinfo_t> modinfovec_t; + +/// Describes a breakpoint event. +/// (see ::BREAKPOINT) +struct bptaddr_t +{ + ea_t hea; ///< Possible address referenced by hardware breakpoints + ea_t kea; ///< Address of the triggered bpt from the kernel's point + ///< of view. (for some systems with special memory mappings, + ///< the triggered ea might be different from event ea). + ///< Use to #BADADDR for flat memory model. + bptaddr_t(): hea(BADADDR), kea(BADADDR) {} +}; + +/// Describes an exception. +/// (see ::EXCEPTION) +struct excinfo_t +{ + uint32 code; ///< Exception code + bool can_cont; ///< Execution of the process can continue after this exception? + ea_t ea; ///< Possible address referenced by the exception + qstring info; ///< Exception message +}; + +/// This structure is used only when detailed information +/// about a debug event is needed. +struct debug_event_t +{ + pid_t pid; ///< Process where the event occurred + thid_t tid; ///< Thread where the event occurred + ea_t ea; ///< Address where the event occurred + bool handled; ///< Is event handled by the debugger?. + ///< (from the system's point of view) + ///< Meaningful for ::EXCEPTION events +private: + event_id_t _eid; +#ifndef SWIG + char bytes[qmax(sizeof(modinfo_t), sizeof(excinfo_t))]; + void check_usage(uint32 req) { QASSERT(1502, (_eid & req) != 0); } +#endif + +public: + debug_event_t(void) : + pid(NO_PROCESS), + tid(NO_THREAD), + ea(BADADDR), + handled(false), + _eid(NO_EVENT) + { + memset(bytes, 0, sizeof(bytes)); + } + debug_event_t(const debug_event_t &r) : _eid(NO_EVENT) { copy(r); } + ~debug_event_t(void) { clear(); } + debug_event_t &operator =(const debug_event_t &r) { return copy(r); } + debug_event_t ©(const debug_event_t &r) { copy_debug_event(this, r); return *this; } + + /// clear the dependent information (see below), set event code to NO_EVENT + void clear(void) { free_debug_event(this); } + + void clear_all(void) + { + clear(); + pid = NO_PROCESS; + tid = NO_THREAD; + ea = BADADDR; + handled = false; + } + + /// Event code + event_id_t eid() const { return _eid; } + + /// Set event code. + /// If the new event code is compatible with the old one + /// then the dependent information (see below) will be preserved. + /// Otherwise the event will be cleared and the new event code will be set. + void set_eid(event_id_t id) { set_debug_event_code(this, id); } + + /// Information that depends on the event code: + + ///< ::PROCESS_STARTED, ::PROCESS_ATTACHED, ::LIB_LOADED + modinfo_t &modinfo() + { + check_usage(PROCESS_STARTED | PROCESS_ATTACHED | LIB_LOADED); + return *(modinfo_t *)bytes; + } + ///< ::PROCESS_EXITED, ::THREAD_EXITED + int &exit_code() + { + check_usage(PROCESS_EXITED | THREAD_EXITED); + return *(int *)bytes; + } + ///< ::THREAD_STARTED (thread name) + ///< ::LIB_UNLOADED (unloaded library name) + ///< ::INFORMATION (will be displayed in the output window if not empty) + qstring &info() + { + check_usage(THREAD_STARTED | LIB_UNLOADED | INFORMATION); + return *(qstring *)bytes; + } + ///< ::BREAKPOINT + bptaddr_t &bpt() + { + check_usage(BREAKPOINT); + return *(bptaddr_t *)bytes; + } + ///< ::EXCEPTION + excinfo_t &exc() + { + check_usage(EXCEPTION); + return *(excinfo_t *)bytes; + } + + const modinfo_t &modinfo() const { return CONST_CAST(debug_event_t*)(this)->modinfo(); } + const int &exit_code() const { return CONST_CAST(debug_event_t*)(this)->exit_code(); } + const qstring &info() const { return CONST_CAST(debug_event_t*)(this)->info(); } + const bptaddr_t &bpt() const { return CONST_CAST(debug_event_t*)(this)->bpt(); } + const excinfo_t &exc() const { return CONST_CAST(debug_event_t*)(this)->exc(); } + + modinfo_t &set_modinfo(event_id_t id) + { + set_eid(id); + return modinfo(); + } + + void set_exit_code(event_id_t id, int code) + { + set_eid(id); + exit_code() = code; + } + + qstring &set_info(event_id_t id) + { + set_eid(id); + return info(); + } + + bptaddr_t &set_bpt(void) + { + set_eid(BREAKPOINT); + return bpt(); + } + + excinfo_t &set_exception(void) + { + set_eid(EXCEPTION); + return exc(); + } + + /// On some systems with special memory mappings the triggered ea might be + /// different from the actual ea. Calculate the address to use. + ea_t bpt_ea(void) const + { + return _eid == BREAKPOINT && bpt().kea != BADADDR ? bpt().kea : ea; + } + + friend THREAD_SAFE void ida_export free_debug_event(debug_event_t *ev); + friend THREAD_SAFE void ida_export copy_debug_event(debug_event_t *ev, const debug_event_t &r); + friend THREAD_SAFE void ida_export set_debug_event_code(debug_event_t *ev, event_id_t id); +}; +DECLARE_TYPE_AS_MOVABLE(debug_event_t); + +typedef int bpttype_t; ///< hardware breakpoint type (see \ref BPT_H) + +/// \defgroup BPT_H Hardware breakpoint ids +/// Fire the breakpoint upon one of these events +//@{ +const bpttype_t + BPT_WRITE = 1, ///< Write access + BPT_READ = 2, ///< Read access + BPT_RDWR = 3, ///< Read/write access + BPT_SOFT = 4, ///< Software breakpoint + BPT_EXEC = 8, ///< Execute instruction + BPT_DEFAULT = (BPT_SOFT|BPT_EXEC); ///< Choose bpt type automatically +//@} + +/// Exception information +struct exception_info_t +{ + uint code; ///< exception code + uint32 flags; ///< \ref EXC_ +/// \defgroup EXC_ Exception info flags +/// Used by exception_info_t::flags +//@{ +#define EXC_BREAK 0x0001 ///< break on the exception +#define EXC_HANDLE 0x0002 ///< should be handled by the debugger? +#define EXC_MSG 0x0004 ///< instead of a warning, log the exception to the output window +#define EXC_SILENT 0x0008 ///< do not warn or log to the output window +//@} + + /// Should we break on the exception? + bool break_on(void) const { return (flags & EXC_BREAK) != 0; } + + /// Should we handle the exception? + bool handle(void) const { return (flags & EXC_HANDLE) != 0; } + + qstring name; ///< Exception standard name + qstring desc; ///< Long message used to display info about the exception + + exception_info_t(void) : code(0), flags(0) {} + exception_info_t(uint _code, uint32 _flags, const char *_name, const char *_desc) + : code(_code), flags(_flags), name(_name), desc(_desc) {} +}; +DECLARE_TYPE_AS_MOVABLE(exception_info_t); +typedef qvector<exception_info_t> excvec_t; ///< vector of exception info objects + +/// Structure to hold a register value. +/// Small values (up to 64-bit integers and floating point values) use +/// #RVT_INT and #RVT_FLOAT types. For bigger values the bytes() vector is used. +struct regval_t +{ +/// \defgroup RVT_ Register value types +/// Used by regval_t::rvtype +//@{ +#define RVT_INT (-1) ///< integer +#define RVT_FLOAT (-2) ///< floating point +#define RVT_UNAVAILABLE (-3) ///< unavailable + ///< other values mean custom data type +//@} + int32 rvtype = RVT_INT; ///< one of \ref RVT_ +#ifndef SWIG + union + { +#endif + uint64 ival; ///< 8: integer value + fpvalue_t fval; ///< 12: floating point value in the internal representation (see ieee.h) +#ifndef SWIG + uchar reserve[sizeof(bytevec_t)]; ///< bytevec_t: custom data type (use bytes() to access it) + }; +#endif + regval_t() : ival(~uint64(0)) {} + ~regval_t() { clear(); } + regval_t(const regval_t &r) { *this = r; } + + /// Assign this regval to the given value + regval_t &operator = (const regval_t &r) + { + if ( this == &r ) + return *this; + if ( r.rvtype >= 0 ) + { + if ( rvtype >= 0 ) + bytes() = r.bytes(); + else + new (&bytes()) bytevec_t(r.bytes()); + } + else // r.rvtype < 0 + { + if ( rvtype >= 0 ) + bytes().~bytevec_t(); + memcpy(&fval, &r.fval, sizeof(fval)); + } + rvtype = r.rvtype; + return *this; + } + + /// Clear register value + void clear(void) + { + if ( rvtype >= 0 ) + { + bytes().~bytevec_t(); + rvtype = RVT_INT; + } + } + + /// Compare two regvals with '==' + bool operator == (const regval_t &r) const + { + if ( rvtype == r.rvtype ) + { + if ( rvtype == RVT_UNAVAILABLE ) + return true; + if ( rvtype == RVT_INT ) + return ival == r.ival; + return memcmp(get_data(), r.get_data(), get_data_size()) == 0; + } + return false; + } + + /// Compare two regvals with '!=' + bool operator != (const regval_t &r) const { return !(*this == r); } + + /// Set this = r and r = this + void swap(regval_t &r) { qswap(*this, r); } + + /// Use set_int() + void _set_int(uint64 x) { ival = x; } + /// Use set_float() + void _set_float(const fpvalue_t &x) { fval = x; rvtype = RVT_FLOAT; } + /// Use set_bytes(const uchar *, size_t) + void _set_bytes(const uchar *data, size_t size) { new (&bytes()) bytevec_t(data, size); rvtype = 0; } + /// Use set_bytes(const bytevec_t &) + void _set_bytes(const bytevec_t &v) { new (&bytes()) bytevec_t(v); rvtype = 0; } + /// Use set_bytes(void) + bytevec_t &_set_bytes(void) { new (&bytes()) bytevec_t; rvtype = 0; return bytes(); } + /// Use set_unavailable(void) + void _set_unavailable(void) { ival = 0; rvtype = RVT_UNAVAILABLE; } + + /// \name Setters + /// These functions ensure that the previous value is cleared + //@{ + /// Set int value (ival) + void set_int(uint64 x) { clear(); _set_int(x); } + /// Set float value (fval) + void set_float(const fpvalue_t &x) { clear(); _set_float(x); } + /// Set custom regval with raw data + void set_bytes(const uchar *data, size_t size) { clear(); _set_bytes(data, size); } + /// Set custom value with existing bytevec + void set_bytes(const bytevec_t &v) { clear(); _set_bytes(v); } + /// Initialize this regval to an empty custom value + bytevec_t &set_bytes(void) { clear(); _set_bytes(); return bytes(); } + /// Mark as unavailable + void set_unavailable(void) { clear(); _set_unavailable(); } + + //@} + + /// \name Getters + //@{ + /// Get custom value + bytevec_t &bytes(void) { return *(bytevec_t *)reserve; } + /// Get const custom value + const bytevec_t &bytes(void) const { return *(bytevec_t *)reserve; } + /// Get pointer to value + void *get_data(void) { return rvtype >= 0 ? (void *)bytes().begin() : (void *)&fval; } + /// Get const pointer to value + const void *get_data(void) const { return rvtype >= 0 ? (void *)bytes().begin() : (void *)&fval; } + /// Get size of value + size_t get_data_size(void) const + { + if ( rvtype >= 0 ) + return bytes().size(); + if ( rvtype == RVT_INT ) + return sizeof(ival); + if ( rvtype == RVT_FLOAT ) + return sizeof(fval); + return 0; + } + //@} +}; +DECLARE_TYPE_AS_MOVABLE(regval_t); +typedef qvector<regval_t> regvals_t; ///< vector register value objects + +/// Instruction operand information +struct idd_opinfo_t +{ + bool modified; ///< the operand is modified (written) by the instruction + ea_t ea; ///< operand address (#BADADDR - no address) + regval_t value; ///< operand value. custom data is represented by 'bytes'. + int debregidx; ///< for custom data: index of the corresponding register in dbg->registers + int value_size; ///< size of the value in bytes + + idd_opinfo_t(void) : modified(false), ea(BADADDR), debregidx(-1), value_size(0) {} +}; + +/// Call stack trace information +struct call_stack_info_t +{ + ea_t callea; ///< the address of the call instruction. + ///< for the 0th frame this is usually just the current value of EIP. + ea_t funcea; ///< the address of the called function + ea_t fp; ///< the value of the frame pointer of the called function + bool funcok; ///< is the function present? + bool operator==(const call_stack_info_t &r) const + { + return callea == r.callea + && funcea == r.funcea + && funcok == r.funcok + && fp == r.fp; + } + bool operator!=(const call_stack_info_t &r) const { return !(*this == r); } +}; +DECLARE_TYPE_AS_MOVABLE(call_stack_info_t); +struct call_stack_t : public qvector<call_stack_info_t> {}; ///< defined as struct so it can be forward-declared + +//------------------------------------------------------------------------- +THREAD_SAFE inline void append_regval(bytevec_t &s, const regval_t &value) +{ + s.pack_dd(value.rvtype+2); + if ( value.rvtype == RVT_INT ) + { + s.pack_dq(value.ival+1); + } + else if ( value.rvtype == RVT_FLOAT ) + { + s.append(&value.fval, sizeof(value.fval)); + } + else if ( value.rvtype != RVT_UNAVAILABLE ) + { + const bytevec_t &b = value.bytes(); + s.pack_dd(b.size()); + s.append(b.begin(), b.size()); + } +} + +//------------------------------------------------------------------------- +template <class T> +THREAD_SAFE inline void extract_regval(regval_t *out, T &v) +{ + out->clear(); + out->rvtype = extract_dd(v) - 2; + if ( out->rvtype == RVT_INT ) + { + out->ival = extract_dq(v) - 1; + } + else if ( out->rvtype == RVT_FLOAT ) + { + extract_obj(v, &out->fval, sizeof(out->fval)); + } + else if ( out->rvtype != RVT_UNAVAILABLE ) + { + bytevec_t &b = out->_set_bytes(); + int size = extract_dd(v); + b.resize(size); + extract_obj(v, b.begin(), size); + } +} + +//------------------------------------------------------------------------- +template <class T> +THREAD_SAFE inline void extract_regvals( + regval_t *values, + int n, + T &v, + const uchar *regmap) +{ + for ( int i=0; i < n && !v.eof(); i++ ) + if ( regmap == NULL || test_bit(regmap, i) ) + extract_regval(&values[i], v); +} + +//-------------------------------------------------------------------------- +THREAD_SAFE inline void unpack_regvals( + regval_t *values, + int n, + const uchar *regmap, + memory_deserializer_t &mmdsr) +{ + extract_regvals(values, n, mmdsr, regmap); +} + + +/// Call a function from the debugged application. +/// \param[out] r function return value +/// - for #APPCALL_MANUAL, r will hold the new stack point value +/// - for #APPCALL_DEBEV, r will hold the exception information upon failure +/// and the return code will be eExecThrow +/// \param func_ea address to call +/// \param tid thread to use. #NO_THREAD means to use the current thread +/// \param ptif pointer to type of the function to call +/// \param argv array of arguments +/// \param argnum number of actual arguments +/// \return #eOk if successful, otherwise an error code + +idaman error_t ida_export dbg_appcall( + idc_value_t *retval, + ea_t func_ea, + thid_t tid, + const tinfo_t *ptif, + idc_value_t *argv, + size_t argnum); + + +/// Cleanup after manual appcall. +/// \param tid thread to use. #NO_THREAD means to use the current thread +/// The application state is restored as it was before calling the last appcall(). +/// Nested appcalls are supported. +/// \return #eOk if successful, otherwise an error code + +idaman error_t ida_export cleanup_appcall(thid_t tid); + + +/// Return values for get_debug_event() +enum gdecode_t +{ + GDE_ERROR = -1, ///< error + GDE_NO_EVENT, ///< no debug events are available + GDE_ONE_EVENT, ///< got one event, no more available yet + GDE_MANY_EVENTS, ///< got one event, more events available +}; + +/// Input argument for update_bpts() +struct update_bpt_info_t +{ + ea_t ea; ///< in: bpt address + bytevec_t orgbytes; ///< in(del), out(add): original bytes (only for swbpts) + bpttype_t type; ///< in: bpt type + int size; ///< in: bpt size (only for hwbpts) + uchar code; ///< in: 0. #BPT_SKIP entries must be skipped by the debugger module + ///< out: \ref BPT_ + pid_t pid; ///< in: process id + thid_t tid; ///< in: thread id + + update_bpt_info_t() + : ea(BADADDR), type(BPT_SOFT), size(0), code(0), pid(NO_PROCESS), tid(NO_THREAD) {} + + /// facilitate update_bpt_vec_t::find() + bool operator==(const update_bpt_info_t &b) const + { + return ea == b.ea && type == b.type; + } +}; +DECLARE_TYPE_AS_MOVABLE(update_bpt_info_t); +typedef qvector<update_bpt_info_t> update_bpt_vec_t; ///< vector of update breakpoint info objects + +/// Input argument for update_lowcnds(). +/// Server-side low-level breakpoint conditions +struct lowcnd_t +{ + ea_t ea; ///< address of the condition + qstring cndbody; ///< new condition. empty means 'remove condition' + ///< the following fields are valid only if condition is not empty: + bpttype_t type; ///< existing breakpoint type + bytevec_t orgbytes; ///< original bytes (if type==#BPT_SOFT) + insn_t cmd; ///< decoded instruction at 'ea' + ///< (used for processors without single step feature, e.g. arm) + bool compiled; ///< has 'cndbody' already been compiled? + int size; ///< breakpoint size (if type!=#BPT_SOFT) +}; +typedef qvector<lowcnd_t> lowcnd_vec_t; ///< vector of low-level breakpoint conditions + +/// Output argument for ev_suspended +/// New thread names +struct thread_name_t +{ + thid_t tid; ///< thread + qstring name; ///< new thread name +}; +typedef qvector<thread_name_t> thread_name_vec_t; ///< vector of thread names + +//==================================================================== +/// How to resume the application. The corresponding bit for \ref DBG_FLAG_ +/// must be set in order to use a resume mode. +enum resume_mode_t +{ + RESMOD_NONE, ///< no stepping, run freely + RESMOD_INTO, ///< step into call (the most typical single stepping) + RESMOD_OVER, ///< step over call + RESMOD_OUT, ///< step out of the current function (run until return) + RESMOD_SRCINTO, ///< until control reaches a different source line + RESMOD_SRCOVER, ///< next source line in the current stack frame + RESMOD_SRCOUT, ///< next source line in the previous stack frame + RESMOD_USER, ///< step out to the user code + RESMOD_HANDLE, ///< step into the exception handler + RESMOD_MAX, +}; + +//==================================================================== +// Tracing bits +#define STEP_TRACE 0x01 // lowest level trace. trace buffers are not maintained +#define INSN_TRACE 0x02 // instruction tracing +#define FUNC_TRACE 0x04 // function tracing +#define BBLK_TRACE 0x08 // basic block tracing + +//==================================================================== +/// Debugger return codes. +/// Success if positive (> DRC_NONE). +enum drc_t +{ + DRC_EVENTS = 3, ///< success, there are pending events + DRC_CRC = 2, ///< success, but the input file crc does not match + DRC_OK = 1, ///< success + DRC_NONE = 0, ///< reaction to the event not implemented + DRC_FAILED = -1, ///< failed or false + DRC_NETERR = -2, ///< network error + DRC_NOFILE = -3, ///< file not found + DRC_IDBSEG = -4, ///< use idb segmentation + DRC_NOPROC = -5, ///< the process does not exist anymore + DRC_NOCHG = -6, ///< no changes + DRC_ERROR = -7, ///< unclassified error, may be complemented by errbuf +}; + +//==================================================================== +/// This structure describes a debugger API module. +/// (functions needed to debug a process on a specific +/// operating system). +/// +/// The address of this structure must be put into the ::dbg variable by +/// the plugin_t::init() function of the debugger plugin. +struct debugger_t +{ + int version; ///< Expected kernel version, + ///< should be #IDD_INTERFACE_VERSION + const char *name; ///< Short debugger name like win32 or linux + int id; ///< one of \ref DEBUGGER_ID_ + + /// \defgroup DEBUGGER_ID_ Debugger API module id + /// Used by debugger_t::id + //@{ + #define DEBUGGER_ID_X86_IA32_WIN32_USER 0 ///< Userland win32 processes (win32 debugging APIs) + #define DEBUGGER_ID_X86_IA32_LINUX_USER 1 ///< Userland linux processes (ptrace()) + #define DEBUGGER_ID_X86_IA32_MACOSX_USER 3 ///< Userland MAC OS X processes + #define DEBUGGER_ID_ARM_IPHONE_USER 5 ///< iPhone 1.x + #define DEBUGGER_ID_X86_IA32_BOCHS 6 ///< BochsDbg.exe 32 + #define DEBUGGER_ID_6811_EMULATOR 7 ///< MC6812 emulator (beta) + #define DEBUGGER_ID_GDB_USER 8 ///< GDB remote + #define DEBUGGER_ID_WINDBG 9 ///< WinDBG using Microsoft Debug engine + #define DEBUGGER_ID_X86_DOSBOX_EMULATOR 10 ///< Dosbox MS-DOS emulator + #define DEBUGGER_ID_ARM_LINUX_USER 11 ///< Userland arm linux + #define DEBUGGER_ID_TRACE_REPLAYER 12 ///< Fake debugger to replay recorded traces + #define DEBUGGER_ID_X86_PIN_TRACER 14 ///< PIN Tracer module + #define DEBUGGER_ID_DALVIK_USER 15 ///< Dalvik + #define DEBUGGER_ID_XNU_USER 16 ///< XNU Kernel + #define DEBUGGER_ID_ARM_MACOS_USER 17 ///< Userland arm MAC OS + //@} + + const char *processor; ///< Required processor name. + ///< Used for instant debugging to load the correct + ///< processor module + + uint32 flags; /// \ref DBG_FLAG_ + uint32 flags2; /// \ref DBG_FLAG2_ + /// may be set inside debugger_t::init_debugger() except of the severals + + /// \defgroup DBG_FLAG_ Debugger module features + /// Used by debugger_t::flags + //@{ + #define DBG_FLAG_REMOTE 0x00000001 ///< Remote debugger (requires remote host name unless #DBG_FLAG_NOHOST) + #define DBG_FLAG_NOHOST 0x00000002 ///< Remote debugger with does not require network params (host/port/pass). + ///< (a unique device connected to the machine) + #define DBG_FLAG_FAKE_ATTACH 0x00000004 ///< ::PROCESS_ATTACHED is a fake event + ///< and does not suspend the execution + #define DBG_FLAG_HWDATBPT_ONE 0x00000008 ///< Hardware data breakpoints are + ///< one byte size by default + #define DBG_FLAG_CAN_CONT_BPT 0x00000010 ///< Debugger knows to continue from a bpt. + ///< This flag also means that the debugger module + ///< hides breakpoints from ida upon read_memory + #define DBG_FLAG_NEEDPORT 0x00000020 ///< Remote debugger requires port number (to be used with DBG_FLAG_NOHOST) + #define DBG_FLAG_DONT_DISTURB 0x00000040 ///< Debugger can handle only + ///< get_debug_event(), + ///< request_pause(), + ///< exit_process(). + ///< when the debugged process is running. + ///< The kernel may also call service functions + ///< (file I/O, map_address, etc) + #define DBG_FLAG_SAFE 0x00000080 ///< The debugger is safe (probably because it just emulates the application + ///< without really running it) + #define DBG_FLAG_CLEAN_EXIT 0x00000100 ///< IDA must suspend the application and remove + ///< all breakpoints before terminating the application. + ///< Usually this is not required because the application memory + ///< disappears upon termination. + #define DBG_FLAG_USE_SREGS 0x00000200 ///< Take segment register values into account (non flat memory) + #define DBG_FLAG_NOSTARTDIR 0x00000400 ///< Debugger module doesn't use startup directory + #define DBG_FLAG_NOPARAMETERS 0x00000800 ///< Debugger module doesn't use commandline parameters + #define DBG_FLAG_NOPASSWORD 0x00001000 ///< Remote debugger doesn't use password + #define DBG_FLAG_CONNSTRING 0x00002000 ///< Display "Connection string" instead of "Hostname" and hide the "Port" field + #define DBG_FLAG_SMALLBLKS 0x00004000 ///< If set, IDA uses 256-byte blocks for caching memory contents. + ///< Otherwise, 1024-byte blocks are used + #define DBG_FLAG_MANMEMINFO 0x00008000 ///< If set, manual memory region manipulation commands + ///< will be available. Use this bit for debugger modules + ///< that cannot return memory layout information + #define DBG_FLAG_EXITSHOTOK 0x00010000 ///< IDA may take a memory snapshot at ::PROCESS_EXITED event + #define DBG_FLAG_VIRTHREADS 0x00020000 ///< Thread IDs may be shuffled after each debug event. + ///< (to be used for virtual threads that represent cpus for windbg kmode) + #define DBG_FLAG_LOWCNDS 0x00040000 ///< Low level breakpoint conditions are supported. + #define DBG_FLAG_DEBTHREAD 0x00080000 ///< Supports creation of a separate thread in ida + ///< for the debugger (the debthread). + ///< Most debugger functions will be called from debthread (exceptions are marked below) + ///< The debugger module may directly call only #THREAD_SAFE functions. + ///< To call other functions please use execute_sync(). + ///< The debthread significantly increases debugging + ///< speed, especially if debug events occur frequently (to be tested) + #define DBG_FLAG_DEBUG_DLL 0x00100000 ///< Can debug standalone DLLs. + ///< For example, Bochs debugger can debug any snippet of code + #define DBG_FLAG_FAKE_MEMORY 0x00200000 ///< get_memory_info()/read_memory()/write_memory() work with the idb. + ///< (there is no real process to read from, as for the replayer module) + ///< the kernel will not call these functions if this flag is set. + ///< however, third party plugins may call them, they must be implemented. + #define DBG_FLAG_ANYSIZE_HWBPT 0x00400000 ///< The debugger supports arbitrary size hardware breakpoints. + #define DBG_FLAG_TRACER_MODULE 0x00800000 ///< The module is a tracer, not a full featured debugger module + #define DBG_FLAG_PREFER_SWBPTS 0x01000000 ///< Prefer to use software breakpoints + #define DBG_FLAG_LAZY_WATCHPTS 0x02000000 ///< Watchpoints are triggered before the offending instruction is executed. + ///< The debugger must temporarily disable the watchpoint and single-step + ///< before resuming. + #define DBG_FLAG_FAST_STEP 0x04000000 ///< Do not refresh memory layout info after single stepping + //@} + + /// \defgroup DBG_FLAG2_ Debugger module features + /// Used by debugger_t::flags2 + //@{ + #define DBG_HAS_GET_PROCESSES 0x00000001 ///< supports ev_get_processes + #define DBG_HAS_ATTACH_PROCESS 0x00000002 ///< supports ev_attach_process + #define DBG_HAS_DETACH_PROCESS 0x00000004 ///< supports ev_detach_process + #define DBG_HAS_REQUEST_PAUSE 0x00000008 ///< supports ev_request_pause + #define DBG_HAS_SET_EXCEPTION_INFO \ + 0x00000010 ///< supports ev_set_exception_info + #define DBG_HAS_THREAD_SUSPEND 0x00000020 ///< supports ev_thread_suspend + #define DBG_HAS_THREAD_CONTINUE 0x00000040 ///< supports ev_thread_continue + #define DBG_HAS_SET_RESUME_MODE 0x00000080 ///< supports ev_set_resume_mode + ///< cannot be set inside the debugger_t::init_debugger() + #define DBG_HAS_THREAD_GET_SREG_BASE \ + 0x00000100 ///< supports ev_thread_get_sreg_base + #define DBG_HAS_CHECK_BPT 0x00000200 ///< supports ev_check_bpt + #define DBG_HAS_OPEN_FILE 0x00000400 ///< supports ev_open_file, ev_close_file, ev_read_file, ev_write_file + #define DBG_HAS_UPDATE_CALL_STACK \ + 0x00000800 ///< supports ev_update_call_stack + #define DBG_HAS_APPCALL 0x00001000 ///< supports ev_appcall, ev_cleanup_appcall + #define DBG_HAS_REXEC 0x00002000 ///< supports ev_rexec + #define DBG_HAS_MAP_ADDRESS 0x00004000 ///< supports ev_map_address, + ///< avoid using this bit, especially together with DBG_FLAG_DEBTHREAD + ///< because it may cause big slow downs + //@} + + bool is_remote(void) const { return (flags & DBG_FLAG_REMOTE) != 0; } + bool must_have_hostname(void) const + { return (flags & (DBG_FLAG_REMOTE|DBG_FLAG_NOHOST)) == DBG_FLAG_REMOTE; } + bool can_continue_from_bpt(void) const + { return (flags & DBG_FLAG_CAN_CONT_BPT) != 0; } + bool may_disturb(void) const + { return (flags & DBG_FLAG_DONT_DISTURB) == 0; } + bool is_safe(void) const + { return (flags & DBG_FLAG_SAFE) != 0; } + bool use_sregs(void) const + { return (flags & DBG_FLAG_USE_SREGS) != 0; } + size_t cache_block_size(void) const + { return (flags & DBG_FLAG_SMALLBLKS) != 0 ? 256 : 1024; } + bool use_memregs(void) const + { return (flags & DBG_FLAG_MANMEMINFO) != 0; } + bool may_take_exit_snapshot(void) const + { return (flags & DBG_FLAG_EXITSHOTOK) != 0; } + bool virtual_threads(void) const + { return (flags & DBG_FLAG_VIRTHREADS) != 0; } + bool supports_lowcnds(void) const + { return (flags & DBG_FLAG_LOWCNDS) != 0; } + bool supports_debthread(void) const + { return (flags & DBG_FLAG_DEBTHREAD) != 0; } + bool can_debug_standalone_dlls(void) const + { return (flags & DBG_FLAG_DEBUG_DLL) != 0; } + bool fake_memory(void) const + { return (flags & DBG_FLAG_FAKE_MEMORY) != 0; } + + bool has_get_processes(void) const + { return (flags2 & DBG_HAS_GET_PROCESSES) != 0; } + bool has_attach_process(void) const + { return (flags2 & DBG_HAS_ATTACH_PROCESS) != 0; } + bool has_detach_process(void) const + { return (flags2 & DBG_HAS_DETACH_PROCESS) != 0; } + bool has_request_pause(void) const + { return (flags2 & DBG_HAS_REQUEST_PAUSE) != 0; } + bool has_set_exception_info(void) const + { return (flags2 & DBG_HAS_SET_EXCEPTION_INFO) != 0; } + bool has_thread_suspend(void) const + { return (flags2 & DBG_HAS_THREAD_SUSPEND) != 0; } + bool has_thread_continue(void) const + { return (flags2 & DBG_HAS_THREAD_CONTINUE) != 0; } + bool has_set_resume_mode(void) const + { return (flags2 & DBG_HAS_SET_RESUME_MODE) != 0; } + bool has_thread_get_sreg_base(void) const + { return (flags2 & DBG_HAS_THREAD_GET_SREG_BASE) != 0; } + bool has_check_bpt(void) const + { return (flags2 & DBG_HAS_CHECK_BPT) != 0; } + bool has_open_file(void) const + { return (flags2 & DBG_HAS_OPEN_FILE) != 0; } + bool has_update_call_stack(void) const + { return (flags2 & DBG_HAS_UPDATE_CALL_STACK) != 0; } + bool has_appcall(void) const + { return (flags2 & DBG_HAS_APPCALL) != 0; } + bool has_rexec(void) const + { return (flags2 & DBG_HAS_REXEC) != 0; } + bool has_map_address(void) const + { return (flags2 & DBG_HAS_MAP_ADDRESS) != 0; } + + const char **regclasses; ///< Array of register class names + int default_regclasses; ///< Mask of default printed register classes + register_info_t *registers; ///< Array of registers. Use regs() to access it + int nregs; ///< Number of registers + + // A function for accessing the 'registers' array + inline register_info_t ®s(int idx) + { + return registers[idx]; + } + + int memory_page_size; ///< Size of a memory page. Usually 4K + + const uchar *bpt_bytes; ///< A software breakpoint instruction + uchar bpt_size; ///< Size of the software breakpoint instruction in bytes + uchar filetype; ///< Input file type for the instant debugger. + ///< This value will be used after attaching to a new process. + ushort resume_modes; ///< \ref DBG_RESMOD_ + /// \defgroup DBG_RESMOD_ Resume modes + /// Used by debugger_t::resume_modes + //@{ + #define DBG_RESMOD_STEP_INTO 0x0001 ///< ::RESMOD_INTO is available + #define DBG_RESMOD_STEP_OVER 0x0002 ///< ::RESMOD_OVER is available + #define DBG_RESMOD_STEP_OUT 0x0004 ///< ::RESMOD_OUT is available + #define DBG_RESMOD_STEP_SRCINTO 0x0008 ///< ::RESMOD_SRCINTO is available + #define DBG_RESMOD_STEP_SRCOVER 0x0010 ///< ::RESMOD_SRCOVER is available + #define DBG_RESMOD_STEP_SRCOUT 0x0020 ///< ::RESMOD_SRCOUT is available + #define DBG_RESMOD_STEP_USER 0x0040 ///< ::RESMOD_USER is available + #define DBG_RESMOD_STEP_HANDLE 0x0080 ///< ::RESMOD_HANDLE is available + //@} + bool is_resmod_avail(int resmod) const + { return (resume_modes & (1 << (resmod - 1))) != 0; } + +#if !defined(_MSC_VER) // this compiler complains :( + static const int default_port_number = 23946; +#define DEBUGGER_PORT_NUMBER debugger_t::default_port_number +#else +#define DEBUGGER_PORT_NUMBER 23946 +#endif + + /// Set debugger options (parameters that are specific to the debugger module). + /// See the definition of ::set_options_t for arguments. + /// See the convenience function in dbg.hpp if you need to call it. + /// The kernel will generate this event after reading the debugger specific + /// config file (arguments are: keyword="", type=#IDPOPT_STR, value="") + /// This event is optional. + /// This event is generated in the main thread + const char *(idaapi *set_dbg_options)( + const char *keyword, + int pri, + int value_type, + const void *value); + + /// Callback notification codes. + /// + /// They are passed to notify() when certain events occur in the kernel, + /// allowing the debugger plugin to take appropriate actions. + /// + /// Debugger plugins must implement the desired reaction to these events + /// in the notify() function. + /// + /// The notify() function should not be called directly. See inline functions + /// below. + enum event_t + { + /// Initialize debugger. + /// This event is generated in the main thread. + /// \param hostname (const char *) + /// \param portnum (int) + /// \param password (const char *) + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_FAILED + ev_init_debugger, + + /// Terminate debugger. + /// This event is generated in the main thread. + /// \return ::DRC_OK, ::DRC_FAILED + ev_term_debugger, + + /// Return information about the running processes. + /// This event is generated in the main thread. + /// Available if \ref DBG_HAS_GET_PROCESSES is set + /// \param procs (::procinfo_vec_t *) + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_get_processes, + + /// Start an executable to debug. + /// This event is generated in debthread. + /// Must be implemented. + /// \param path (const char *) path to executable + /// \param args (const char *) arguments to pass to executable + /// \param startdir (const char *) initial working directory of new process + /// \param dbg_proc_flags (uint32) \ref DBG_PROC_ + /// \param input_path (const char *) path to the file that was used to create the idb file + /// It is not always the same as 'path' - e.g. if we are analyzing + /// a dll and want to launch an executable that loads it. + /// \param input_file_crc32 (uint32) CRC value for 'input_path' + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_CRC, ::DRC_FAILED, ::DRC_NETERR, ::DRC_NOFILE + ev_start_process, + + /// Attach to an existing running process. + /// event_id should be equal to -1 if not attaching to a crashed process. + /// This event is generated in debthread. + /// Available if \ref DBG_HAS_ATTACH_PROCESS is set + /// \param pid (::pid_t) process id to attach + /// \param event_id (int) event to trigger upon attaching + /// \param dbg_proc_flags (uint32) \ref DBG_PROC_ + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_attach_process, + + /// Detach from the debugged process. + /// May be generated while the process is running or suspended. + /// Must detach from the process in any case. + /// The kernel will repeatedly call get_debug_event() until ::PROCESS_DETACHED is received. + /// In this mode, all other events will be automatically handled and process will be resumed. + /// This event is generated from debthread. + /// Available if \ref DBG_HAS_DETACH_PROCESS is set + /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_detach_process, + + /// Retrieve process- and debugger-specific runtime attributes. + /// This event is generated in the main thread. + /// \param out_pattrs (::debapp_attrs_t *) + /// \return ::DRC_NONE, ::DRC_OK + ev_get_debapp_attrs, + + /// Rebase database if the debugged program has been rebased by the system. + /// This event is generated in the main thread. + /// \param new_base (::ea_t) + /// \return ::DRC_NONE, ::DRC_OK + ev_rebase_if_required_to, + + /// Prepare to pause the process. + /// Normally the next get_debug_event() will pause the process + /// If the process is sleeping, + /// then the pause will not occur until the process wakes up. + /// If the debugger module does not react to this event, + /// then it will be impossible to pause the program. + /// This event is generated in debthread. + /// Available if \ref DBG_HAS_REQUEST_PAUSE is set + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_request_pause, + + /// Stop the process. + /// May be generated while the process is running or suspended. + /// Must terminate the process in any case. + /// The kernel will repeatedly call get_debug_event() until ::PROCESS_EXITED is received. + /// In this mode, all other events will be automatically handled and process will be resumed. + /// This event is generated in debthread. + /// Must be implemented. + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_exit_process, + + /// Get a pending debug event and suspend the process. + /// This event will be generated regularly by IDA. + /// This event is generated in debthread. + /// IMPORTANT: the BREAKPOINT/EXCEPTION/STEP events must be reported + /// only after reporting other pending events for a thread. + /// Must be implemented. + /// \param code (::gdecode_t *) + /// \param event (::debug_event_t *) + /// \param timeout_ms (int) + /// \retval ignored + ev_get_debug_event, + + /// Continue after handling the event. + /// This event is generated in debthread. + /// Must be implemented. + /// \param event (::debug_event_t *) + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_resume, + + /// Set exception handling. + /// This event is generated in debthread or the main thread. + /// Available if \ref DBG_HAS_SET_EXCEPTION_INFO is set + /// \param info (::exception_info_t *) + /// \param qty (int) + /// \return ::DRC_NONE, ::DRC_OK + ev_set_exception_info, + + /// This event will be generated by the kernel each time + /// it has suspended the debugger process and refreshed the database. + /// The debugger module may add information to the database if it wants. + /// + /// The reason for introducing this event is that when an event line + /// LOAD_DLL happens, the database does not reflect the memory state yet + /// and therefore we can't add information about the dll into the database + /// in the get_debug_event() event. + /// Only when the kernel has adjusted the database we can do it. + /// Example: for imported PE DLLs we will add the exported event + /// names to the database. + /// + /// This event is generated in the main thread. + /// \param dlls_added (bool) + /// \param thr_names (::thread_name_vec_t *) (for the kernel only, must be NULL) + /// \return ::DRC_NONE, ::DRC_OK + ev_suspended, + + /// \name Threads + /// The following events manipulate threads. + /// These events are generated in debthread. + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + //@{ + + /// Suspend a running thread + /// Available if \ref DBG_HAS_THREAD_SUSPEND is set + /// \param tid (::thid_t) + ev_thread_suspend, + + /// Resume a suspended thread + /// Available if \ref DBG_HAS_THREAD_CONTINUE is set + /// \param tid (::thid_t) + ev_thread_continue, + + /// Specify resume action + /// Available if \ref DBG_HAS_SET_RESUME_MODE is set + /// \param tid (::thid_t) + /// \param resmod (::resume_mode_t) + ev_set_resume_mode, + + //@} + + /// Read thread registers. + /// This event is generated in debthread. + /// Must be implemented. + /// \param tid (::thid_t) thread id + /// \param clsmask (int) bitmask of register classes to read + /// \param values (::regval_t *) pointer to vector of regvals for all registers. + /// regval must have debugger_t::nregs elements + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_read_registers, + + /// Write one thread register. + /// This event is generated in debthread. + /// Must be implemented. + /// \param tid (::thid_t) thread id + /// \param regidx (int) register index + /// \param value (const ::regval_t *) new value of the register + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_write_register, + + /// Get information about the base of a segment register. + /// Currently used by the IBM PC module to resolve references like fs:0. + /// This event is generated in debthread. + /// Available if \ref DBG_HAS_THREAD_GET_SREG_BASE is set + /// \param answer (::ea_t *) pointer to the answer. can't be NULL. + /// \param tid (::thid_t) thread id + /// \param sreg_value (int) value of the segment register (returned by get_reg_val()) + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_NONE, ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_thread_get_sreg_base, + + /// \name Memory manipulation + /// The following events manipulate bytes in the memory. + //@{ + + /// Get information on the memory ranges. + /// The debugger module fills 'ranges'. The returned vector must be sorted. + /// This event is generated in debthread. + /// Must be implemented. + /// \param ranges (::meminfo_vec_t *) + /// \param errbuf (::qstring *) may be NULL + /// \retval ::DRC_OK new memory layout is returned + /// \retval ::DRC_FAILED, ::DRC_NETERR, ::DRC_NOPROC, ::DRC_NOCHG, ::DRC_IDBSEG + ev_get_memory_info, + + /// Read process memory. + /// This event is generated in debthread. + /// \param nbytes (size_t *) number of read bytes + /// \param ea (::ea_t) + /// \param buffer (void *) + /// \param size (::size_t) + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NOPROC + ev_read_memory, + + /// Write process memory. + /// This event is generated in debthread. + /// \param nbytes (size_t *) number of written bytes + /// \param ea (::ea_t) + /// \param buffer (const void *) + /// \param size (::size_t) + /// \param errbuf (::qstring *) may be NULL + /// \retval ::DRC_OK, ::DRC_FAILED, ::DRC_NOPROC + ev_write_memory, + + //@} + + /// Is it possible to set breakpoint? + /// This event is generated in debthread or in the main thread if debthread + /// is not running yet. + /// It is generated to verify hardware breakpoints. + /// Available if \ref DBG_HAS_CHECK_BPT is set + /// \param bptvc (int *) breakpoint verification codes \ref BPT_ + /// \param type (::bpttype_t) \ref BPT_H + /// \param ea (::ea_t) + /// \param len (int) + /// \return ::DRC_OK, ::DRC_NONE + ev_check_bpt, + + /// Add/del breakpoints. + /// bpts array contains nadd bpts to add, followed by ndel bpts to del. + /// This event is generated in debthread. + /// \param nbpts (int *) number of updated breakpoints + /// \param bpts (::update_bpt_info_t *) + /// \param nadd (int) + /// \param ndel (int) + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NETERR + ev_update_bpts, + + /// Update low-level (server side) breakpoint conditions. + /// This event is generated in debthread. + /// \param nupdated (int *) number of updated conditions + /// \param lowcnds (const ::lowcnd_t *) + /// \param nlowcnds (int) + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK, ::DRC_NETERR + ev_update_lowcnds, + + /// \name Remote file + /// Open/close/read/write a remote file. + /// These events are generated in the main thread + /// Available if \ref DBG_HAS_OPEN_FILE is set + //@{ + + /// \param file (const char *) + /// \param fsize (::uint64 *) + /// \param readonly (bool) + /// \param errbuf (::qstring *) may be NULL + /// \retval (int) handle + /// \retval -1 error + ev_open_file, + + /// \param fn (int) handle + /// \return ignored + ev_close_file, + + /// \param fn (int) handle + /// \param off (::qoff64_t) + /// \param buf (void *) + /// \param size (size_t) + /// \param errbuf (::qstring *) may be NULL + /// \retval number of read bytes + ev_read_file, + + /// \param fn (int) handle + /// \param off (::qoff64_t) + /// \param buf (const void *) + /// \param size (size_t) + /// \param errbuf (::qstring *) may be NULL + /// \retval number of written bytes + ev_write_file, + + //@} + + /// Map process address. + /// The debugger module may ignore this event. + /// This event is generated in debthread. + /// IDA will generate this event only if \ref DBG_HAS_MAP_ADDRESS is set. + /// \param mapped (::ea_t *) mapped address or #BADADDR + /// \param off (::ea_t) offset to map + /// \param regs (const ::regval_t *) current register values. + /// if regs == NULL, then perform global mapping, + /// which is independent on used registers + /// usually such a mapping is a trivial identity mapping + /// \param regnum (int) required mapping. + /// May be specified as a segment register number or a regular + /// register number if the required mapping can be deduced from it. + /// For example, esp implies that ss should be used. + /// \return ::DRC_NONE, ::DRC_OK see MAPPED + ev_map_address, + + /// Get pointer to debugger specific events. + /// This event returns a pointer to a structure that holds pointers to + /// debugger module specific events. For information on the structure + /// layout, please check the corresponding debugger module. Most debugger + /// modules return NULL because they do not have any extensions. Available + /// extensions may be generated from plugins. + /// This event is generated in the main thread. + /// \param ext (void **) + /// \return ::DRC_NONE, ::DRC_OK see EXT + ev_get_debmod_extensions, + + /// Calculate the call stack trace for the given thread. + /// This event is generated when the process is suspended and should fill the 'trace' object + /// with the information about the current call stack. If this event returns DRC_NONE, IDA + /// will try to invoke a processor-specific mechanism (see processor_t::ev_update_call_stack). + /// If the current processor module does not implement stack tracing, then IDA will fall back + /// to a generic algorithm (based on the frame pointer chain) to calculate the trace. + /// This event is ideal if the debugging targets manage stack frames in a peculiar way, + /// requiring special analysis. + /// This event is generated in the main thread. + /// Available if \ref DBG_HAS_UPDATE_CALL_STACK is set + /// \param tid (::thid_t) + /// \param trace (::call_stack_t *) + /// \retval ::DRC_NONE false or not implemented + /// \return ::DRC_OK success + ev_update_call_stack, + + /// Call application function. + /// This event calls a function from the debugged application. + /// This event is generated in debthread + /// Available if \ref HAS_APPCALL is set + /// \param[out] blob_ea (::ea_t *) ea of stkargs blob, + /// #BADADDR if failed and errbuf is filled + /// \param func_ea (::ea_t) address to call + /// \param tid (::thid_t) thread to use + /// \param fti (const ::func_type_data_t *) type information for the generated event + /// \param nargs (int) number of actual arguments + /// \param regargs (const ::regobjs_t *) information about register arguments + /// \param stkargs (::relobj_t *) memory blob to pass as stack arguments + /// (usually contains pointed data) + /// it must be relocated by the callback but not changed otherwise + /// \param retregs (::regobjs_t *) event return registers. + /// \param[out] errbuf (::qstring *) the error message. if empty on failure, see EVENT. + /// should not be filled if an appcall exception + /// happened but #APPCALL_DEBEV is set + /// \param[out] event (::debug_event_t *) the last debug event that occurred during appcall execution + /// filled only if the appcall execution fails and #APPCALL_DEBEV is set + /// \param options (int) appcall options, usually taken from \inf{appcall_options}. + /// possible values: combination of \ref APPCALL_ or 0 + /// \retval ::DRC_NONE + /// \retval ::DRC_OK, see BLOB_EA + ev_appcall, + + /// Cleanup after appcall(). + /// The debugger module must keep the stack blob in the memory until this event + /// is generated. It will be generated by the kernel for each successful appcall(). + /// There is an exception: if #APPCALL_MANUAL, IDA may not call cleanup_appcall. + /// If the user selects to terminate a manual appcall, then cleanup_appcall will be generated. + /// Otherwise, the debugger module should terminate the appcall when the generated + /// event returns. + /// This event is generated in debthread. + /// Available if \ref HAS_APPCALL is set + /// \param tid (::thid_t) + /// \retval ::DRC_EVENTS success, there are pending events + /// \retval ::DRC_OK success + /// \retval ::DRC_FAILED failed + /// \retval ::DRC_NETERR network error + ev_cleanup_appcall, + + /// Evaluate a low level breakpoint condition at 'ea'. + /// Other evaluation errors are displayed in a dialog box. + /// This call is used by IDA when the process has already been temporarily + /// suspended for some reason and IDA has to decide whether the process + /// should be resumed or definitely suspended because of a breakpoint + /// with a low level condition. + /// This event is generated in debthread. + /// \param tid (::thid_t) + /// \param ea (::ea_t) + /// \param errbuf (::qstring *) may be NULL + /// \retval ::DRC_OK condition is satisfied + /// \retval ::DRC_FAILED not satisfied + /// \retval ::DRC_NETERR network error + ev_eval_lowcnd, + + /// Perform a debugger-specific event. + /// This event is generated in debthread + /// \param fn (int) + /// \param buf (const void *) + /// \param size (size_t) + /// \param poutbuf (void **) + /// \param poutsize (ssize_t *) + /// \param errbuf (::qstring *) may be NULL + /// \retval DRC_... + ev_send_ioctl, + + /// Enable/Disable tracing. + /// The kernel will generated this event if the debugger plugin set DBG_FLAG_TRACER_MODULE. + /// TRACE_FLAGS can be a set of #STEP_TRACE, #INSN_TRACE, #BBLK_TRACE or #FUNC_TRACE. + /// This event is generated in the main thread. + /// \param tid (::thid_t) + /// \param enable (bool) + /// \param trace_flags (int) + /// \return ::DRC_OK, ::DRC_FAILED, ::DRC_NONE + ev_dbg_enable_trace, + + /// Is tracing enabled? + /// The kernel will generated this event if the debugger plugin set DBG_FLAG_TRACER_MODULE. + /// TRACE_BIT can be one of the following: #STEP_TRACE, #INSN_TRACE, #BBLK_TRACE or #FUNC_TRACE + /// \param tid (::thid_t) + /// \param tracebit (int) + /// \retval ::DRC_OK bit is set + /// \retval ::DRC_NONE bit is not set or not implemented + ev_is_tracing_enabled, + + /// Execute a command on the remote computer. + /// Available if \ref DBG_HAS_REXEC is set + /// \param cmdline (const char *) + /// \return (int) exit code + ev_rexec, + + /// Get the path to a file containing source debug info for the given module. + /// This allows srcinfo providers to call into the debugger when looking for debug info. + /// It is useful in certain cases like the iOS debugger, which is a remote debugger but + /// the remote debugserver does not provide dwarf info. So, we allow the debugger client + /// to decide where to look for debug info locally. + /// \param path (qstring *) output path (file might not exist) + /// \param base (::ea_t) base address of a module in the target process + /// \return ::DRC_NONE, ::DRC_OK result stored in PATH + ev_get_srcinfo_path, + + /// Search for a binary pattern in the program. + /// \param out (::ea_t *) binary pattern address + /// \param start_ea (::ea_t) linear address, start of range to search + /// \param end_ea (::ea_t) linear address, end of range to search (exclusive) + /// \param data (const ::compiled_binpat_vec_t *) + /// the prepared data to search for (see parse_binpat_str()) + /// \param srch_flags (int) combination of \ref BIN_SEARCH_ + /// \param errbuf (::qstring *) may be NULL + /// \return ::DRC_OK EA contains the binary pattern address + /// \retval ::DRC_FAILED not found + /// \retval ::DRC_NONE not implemented + /// \retval ::DRC_NETERR, ::DRC_ERROR + ev_bin_search, + }; + + /// Event notification callback. + /// It will be hooked to the HT_IDD notification point + /// when the debugger is loaded and unhooked during + /// the debugger unloading. + /// The debugger plugin will be the last one + /// who will receive the notification. + hook_cb_t *callback; + + /// Event notification handler + ssize_t notify(event_t event_code, ...) + { + va_list va; + va_start(va, event_code); + ssize_t code = invoke_callbacks(HT_IDD, event_code, va); + va_end(va); + return code; + } + drc_t notify_drc(event_t event_code, ...) + { + va_list va; + va_start(va, event_code); + drc_t code = drc_t(invoke_callbacks(HT_IDD, event_code, va)); + va_end(va); + return code; + } + + /// \defgroup DBG_PROC_ Debug process flags + /// Passed as 'dbg_proc_flags' parameter to debugger_t::start_process + //@{ + #define DBG_PROC_IS_DLL 0x01 ///< database contains a dll (not exe) + #define DBG_PROC_IS_GUI 0x02 ///< using gui version of ida + #define DBG_PROC_32BIT 0x04 ///< application is 32-bit + #define DBG_PROC_64BIT 0x08 ///< application is 64-bit + #define DBG_NO_TRACE 0x10 ///< do not trace the application (mac/linux) + #define DBG_HIDE_WINDOW 0x20 ///< application should be hidden on startup (windows) + #define DBG_SUSPENDED 0x40 ///< application should be suspended on startup (mac) + //@} + + /// \defgroup BPT_ Breakpoint verification codes + /// Return values for debugger_t::check_bpt + //@{ + #define BPT_OK 0 ///< breakpoint can be set + #define BPT_INTERNAL_ERR 1 ///< interr occurred when verifying breakpoint + #define BPT_BAD_TYPE 2 ///< bpt type is not supported + #define BPT_BAD_ALIGN 3 ///< alignment is invalid + #define BPT_BAD_ADDR 4 ///< ea is invalid + #define BPT_BAD_LEN 5 ///< bpt len is invalid + #define BPT_TOO_MANY 6 ///< reached max number of supported breakpoints + #define BPT_READ_ERROR 7 ///< failed to read memory at bpt ea + #define BPT_WRITE_ERROR 8 ///< failed to write memory at bpt ea + #define BPT_SKIP 9 ///< update_bpts(): do not process bpt + #define BPT_PAGE_OK 10 ///< update_bpts(): ok, added a page bpt + //@} + + /// \defgroup APPCALL_ Appcall options + /// Passed as 'options' parameter to debugger_t::appcall + //@{ + #define APPCALL_MANUAL 0x0001 ///< Only set up the appcall, do not run. + ///< debugger_t::cleanup_appcall will not be generated by ida! + #define APPCALL_DEBEV 0x0002 ///< Return debug event information + #define APPCALL_TIMEOUT 0x0004 ///< Appcall with timeout. + ///< If timed out, errbuf will contain "timeout". + ///< See #SET_APPCALL_TIMEOUT and #GET_APPCALL_TIMEOUT + /// Set appcall timeout in milliseconds + #define SET_APPCALL_TIMEOUT(msecs) ((uint(msecs) << 16)|APPCALL_TIMEOUT) + /// Timeout value is contained in high 2 bytes of 'options' parameter + #define GET_APPCALL_TIMEOUT(options) (uint(options) >> 16) + //@} + + // Notification helpers, should be used instead of direct dbg->notify(...) calls + inline bool init_debugger(const char *hostname, int portnum, const char *password, qstring *errbuf=NULL); + inline bool term_debugger(void); + inline drc_t get_processes(procinfo_vec_t *procs, qstring *errbuf=NULL); + inline drc_t start_process(const char *path, + const char *args, + const char *startdir, + uint32 dbg_proc_flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf=NULL); + inline drc_t attach_process(pid_t pid, int event_id, uint32 dbg_proc_flags, qstring *errbuf=NULL); + inline drc_t detach_process(qstring *errbuf=NULL); + inline bool get_debapp_attrs(debapp_attrs_t *out_pattrs); + inline void rebase_if_required_to(ea_t new_base); + inline drc_t request_pause(qstring *errbuf=NULL); + inline drc_t exit_process(qstring *errbuf=NULL); + inline gdecode_t get_debug_event(debug_event_t *event, int timeout_ms); + inline drc_t resume(const debug_event_t *event, qstring *errbuf=NULL); + inline void set_exception_info(const exception_info_t *info, int qty); + inline void suspended(bool dlls_added, thread_name_vec_t *thr_names=NULL); + inline drc_t thread_suspend(thid_t tid, qstring *errbuf=NULL); + inline drc_t thread_continue(thid_t tid, qstring *errbuf=NULL); + inline drc_t set_resume_mode(thid_t tid, resume_mode_t resmod, qstring *errbuf=NULL); + inline drc_t read_registers(thid_t tid, int clsmask, regval_t *values, qstring *errbuf=NULL); + inline drc_t write_register(thid_t tid, int regidx, const regval_t *value, qstring *errbuf=NULL); + inline drc_t thread_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value, qstring *errbuf=NULL); + inline drc_t get_memory_info(meminfo_vec_t &ranges, qstring *errbuf=NULL); + inline drc_t read_memory(size_t *nbytes, ea_t ea, void *buffer, size_t size, qstring *errbuf=NULL); + inline drc_t write_memory(size_t *nbytes, ea_t ea, const void *buffer, size_t size, qstring *errbuf=NULL); + inline drc_t check_bpt(int *bptvc, bpttype_t type, ea_t ea, int len); + inline drc_t update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf=NULL); + inline drc_t update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf=NULL); + inline int open_file(const char *file, uint64 *fsize, bool readonly, qstring *errbuf=NULL); + inline void close_file(int fn); + inline ssize_t read_file(int fn, qoff64_t off, void *buf, size_t size, qstring *errbuf=NULL); + inline ssize_t write_file(int fn, qoff64_t off, const void *buf, size_t size, qstring *errbuf=NULL); + inline ea_t map_address(ea_t off, const regval_t *regs, int regnum); + inline const void *get_debmod_extensions(void); + inline bool update_call_stack(thid_t tid, call_stack_t *trace); + inline ea_t appcall( + ea_t func_ea, + thid_t tid, + const struct func_type_data_t *fti, + int nargs, + const struct regobjs_t *regargs, + struct relobj_t *stkargs, + struct regobjs_t *retregs, + qstring *errbuf, + debug_event_t *event, + int options); + inline drc_t cleanup_appcall(thid_t tid); + inline drc_t eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf=NULL); + inline drc_t send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize, qstring *errbuf=NULL); + inline bool dbg_enable_trace(thid_t tid, bool enable, int trace_flags); + inline bool is_tracing_enabled(thid_t tid, int tracebit); + inline int rexec(const char *cmdline); + inline bool get_srcinfo_path(qstring *path, ea_t base); + inline drc_t bin_search( + ea_t *out, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &data, + int srch_flags, + qstring *errbuf=NULL); +}; + +#ifndef __X86__ + CASSERT(sizeof(debugger_t) == 104); +#else + CASSERT(sizeof(debugger_t) == 60); +#endif + + +#define RQ_MASKING 0x0001 // masking step handler: unless errors, tmpbpt handlers won't be generated + // should be used only with request_internal_step() +#define RQ_SUSPEND 0x0002 // suspending step handler: suspends the app + // handle_debug_event: suspends the app +#define RQ_NOSUSP 0x0000 // running step handler: continues the app +#define RQ_IGNWERR 0x0004 // ignore breakpoint write failures +#define RQ_SILENT 0x0008 // all: no dialog boxes +#define RQ_VERBOSE 0x0000 // all: display dialog boxes +#define RQ_SWSCREEN 0x0010 // handle_debug_event: switch screens +#define RQ__NOTHRRF 0x0020 // handle_debug_event: do not refresh threads +#define RQ_PROCEXIT 0x0040 // snapshots: the process is exiting +#define RQ_IDAIDLE 0x0080 // handle_debug_event: ida is idle +#define RQ_SUSPRUN 0x0100 // handle_debug_event: suspend at PROCESS_STARTED +#define RQ_RESUME 0x0200 // handle_debug_event: resume application +#define RQ_RESMOD 0xF000 // resume_mode_t +#define RQ_RESMOD_SHIFT 12 +#define RQ_INTO (RESMOD_INTO << RQ_RESMOD_SHIFT) + +inline bool debugger_t::init_debugger(const char *hostname, int portnum, const char *password, qstring *errbuf) +{ + return notify_drc(ev_init_debugger, hostname, portnum, password, errbuf) == DRC_OK; +} +inline bool debugger_t::term_debugger(void) +{ + return notify_drc(ev_term_debugger) == DRC_OK; +} +inline drc_t debugger_t::get_processes(procinfo_vec_t *procs, qstring *errbuf) +{ + return notify_drc(ev_get_processes, procs, errbuf); +} +inline drc_t debugger_t::start_process( + const char *path, + const char *args, + const char *startdir, + uint32 dbg_proc_flags, + const char *input_path, + uint32 input_file_crc32, + qstring *errbuf) +{ + return notify_drc(ev_start_process, path, args, startdir, dbg_proc_flags, input_path, input_file_crc32, errbuf); +} +inline drc_t debugger_t::attach_process(pid_t pid, int event_id, uint32 dbg_proc_flags, qstring *errbuf) +{ + return notify_drc(ev_attach_process, pid, event_id, dbg_proc_flags, errbuf); +} +inline drc_t debugger_t::detach_process(qstring *errbuf) +{ + return notify_drc(ev_detach_process, errbuf); +} +inline bool debugger_t::get_debapp_attrs(debapp_attrs_t *out_pattrs) +{ + return notify_drc(ev_get_debapp_attrs, out_pattrs) != DRC_NONE; +} +inline void debugger_t::rebase_if_required_to(ea_t new_base) +{ + notify_drc(ev_rebase_if_required_to, new_base); +} +inline drc_t debugger_t::request_pause(qstring *errbuf) +{ + return notify_drc(ev_request_pause, errbuf); +} +inline drc_t debugger_t::exit_process(qstring *errbuf) +{ + return notify_drc(ev_exit_process, errbuf); +} +inline gdecode_t debugger_t::get_debug_event(debug_event_t *event, int timeout_ms) +{ + gdecode_t code = GDE_ERROR; + notify_drc(ev_get_debug_event, &code, event, timeout_ms); + return code; +} +inline drc_t debugger_t::resume(const debug_event_t *event, qstring *errbuf) +{ + return notify_drc(ev_resume, event, errbuf); +} +inline void debugger_t::set_exception_info(const exception_info_t *info, int qty) +{ + notify_drc(ev_set_exception_info, info, qty); +} +inline void debugger_t::suspended(bool dlls_added, thread_name_vec_t *thr_names) +{ + notify_drc(ev_suspended, dlls_added, thr_names); +} +inline drc_t debugger_t::thread_suspend(thid_t tid, qstring *errbuf) +{ + return notify_drc(ev_thread_suspend, tid, errbuf); +} +inline drc_t debugger_t::thread_continue(thid_t tid, qstring *errbuf) +{ + return notify_drc(ev_thread_continue, tid, errbuf); +} +inline drc_t debugger_t::set_resume_mode(thid_t tid, resume_mode_t resmod, qstring *errbuf) +{ + return notify_drc(ev_set_resume_mode, tid, resmod, errbuf); +} +inline drc_t debugger_t::read_registers(thid_t tid, int clsmask, regval_t *values, qstring *errbuf) +{ + return notify_drc(ev_read_registers, tid, clsmask, values, errbuf); +} +inline drc_t debugger_t::write_register(thid_t tid, int regidx, const regval_t *value, qstring *errbuf) +{ + return notify_drc(ev_write_register, tid, regidx, value, errbuf); +} +inline drc_t debugger_t::thread_get_sreg_base(ea_t *answer, thid_t tid, int sreg_value, qstring *errbuf) +{ + return notify_drc(ev_thread_get_sreg_base, answer, tid, sreg_value, errbuf); +} +inline drc_t debugger_t::get_memory_info(meminfo_vec_t &ranges, qstring *errbuf) +{ + return notify_drc(ev_get_memory_info, &ranges, errbuf); +} +inline drc_t debugger_t::read_memory(size_t *nbytes, ea_t ea, void *buffer, size_t size, qstring *errbuf) +{ + return notify_drc(ev_read_memory, nbytes, ea, buffer, size, errbuf); +} +inline drc_t debugger_t::write_memory(size_t *nbytes, ea_t ea, const void *buffer, size_t size, qstring *errbuf) +{ + return notify_drc(ev_write_memory, nbytes, ea, buffer, size, errbuf); +} +inline drc_t debugger_t::check_bpt(int *bptvc, bpttype_t type, ea_t ea, int len) +{ + return notify_drc(ev_check_bpt, bptvc, type, ea, len); +} +inline drc_t debugger_t::update_bpts(int *nbpts, update_bpt_info_t *bpts, int nadd, int ndel, qstring *errbuf) +{ + return notify_drc(ev_update_bpts, nbpts, bpts, nadd, ndel, errbuf); +} +inline drc_t debugger_t::update_lowcnds(int *nupdated, const lowcnd_t *lowcnds, int nlowcnds, qstring *errbuf) +{ + return notify_drc(ev_update_lowcnds, nupdated, lowcnds, nlowcnds, errbuf); +} +inline int debugger_t::open_file(const char *file, uint64 *fsize, bool readonly, qstring *errbuf) +{ + return int(notify(ev_open_file, file, fsize, readonly, errbuf)); +} +inline void debugger_t::close_file(int fn) +{ + notify(ev_close_file, fn); +} +inline ssize_t debugger_t::read_file(int fn, qoff64_t off, void *buf, size_t size, qstring *errbuf) +{ + return notify(ev_read_file, fn, off, buf, size, errbuf); +} +inline ssize_t debugger_t::write_file(int fn, qoff64_t off, const void *buf, size_t size, qstring *errbuf) +{ + return notify(ev_write_file, fn, off, buf, size, errbuf); +} +inline ea_t debugger_t::map_address(ea_t off, const regval_t *rvs, int regnum) +{ + ea_t mapped; + return notify_drc(ev_map_address, &mapped, off, rvs, regnum) == DRC_OK + ? mapped + : off; +} +inline const void *debugger_t::get_debmod_extensions(void) +{ + void *ext; + if ( notify_drc(ev_get_debmod_extensions, &ext) != DRC_OK ) + ext = NULL; + return ext; +} +inline bool debugger_t::update_call_stack(thid_t tid, call_stack_t *trace) +{ + return notify_drc(ev_update_call_stack, tid, trace) != DRC_NONE; +} +inline ea_t debugger_t::appcall( + ea_t func_ea, + thid_t tid, + const struct func_type_data_t *fti, + int nargs, + const struct regobjs_t *regargs, + struct relobj_t *stkargs, + struct regobjs_t *retregs, + qstring *errbuf, + debug_event_t *event, + int options) +{ + ea_t blob_ea; + if ( notify_drc(ev_appcall, &blob_ea, func_ea, tid, fti, nargs, regargs, stkargs, retregs, errbuf, event, options) != DRC_OK ) + { + blob_ea = BADADDR; + if ( errbuf != NULL ) + *errbuf = "Debugger plugin does not support an application function call"; + } + return blob_ea; +} +inline drc_t debugger_t::cleanup_appcall(thid_t tid) +{ + return notify_drc(ev_cleanup_appcall, tid); +} +inline drc_t debugger_t::eval_lowcnd(thid_t tid, ea_t ea, qstring *errbuf) +{ + return notify_drc(ev_eval_lowcnd, tid, ea, errbuf); +} +inline drc_t debugger_t::send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize, qstring *errbuf) +{ + return notify_drc(ev_send_ioctl, fn, buf, size, poutbuf, poutsize, errbuf); +} +inline bool debugger_t::dbg_enable_trace(thid_t tid, bool enable, int trace_flags) +{ + return notify_drc(ev_dbg_enable_trace, tid, enable, trace_flags) == DRC_OK; +} +inline bool debugger_t::is_tracing_enabled(thid_t tid, int tracebit) +{ + return notify_drc(ev_is_tracing_enabled, tid, tracebit) == DRC_OK; +} +inline int debugger_t::rexec(const char *cmdline) +{ + return int(notify(ev_rexec, cmdline)); +} +inline bool debugger_t::get_srcinfo_path(qstring *path, ea_t base) +{ + return notify_drc(ev_get_srcinfo_path, path, base) == DRC_OK; +} +inline drc_t debugger_t::bin_search( + ea_t *out, + ea_t start_ea, + ea_t end_ea, + const compiled_binpat_vec_t &data, + int srch_flags, + qstring *errbuf) +{ + return notify_drc(ev_bin_search, out, start_ea, end_ea, &data, srch_flags, errbuf); +} +#endif // _IDD_HPP diff --git a/idasdk76/include/idp.hpp b/idasdk76/include/idp.hpp new file mode 100644 index 0000000..27f6411 --- /dev/null +++ b/idasdk76/include/idp.hpp @@ -0,0 +1,3157 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _IDP_HPP +#define _IDP_HPP + +#include <fpro.h> +#include <ieee.h> +#include <nalt.hpp> +#include <segment.hpp> +#include <funcs.hpp> +#include <ua.hpp> +#include <bitrange.hpp> +#include <config.hpp> + +/*! \file idp.hpp + + \brief Contains definition of the interface to IDP modules. + + The interface consists of two structures: + - definition of target assembler: ::ash + - definition of current processor: ::ph + + These structures contain information about target processor and assembler features. + + It also defines two groups of kernel events: + - processor_t::event_t processor related events + - idb_event:event_code_t database related events + + The processor related events are used to communicate with the processor module. + The database related events are used to inform any interested parties, like + plugins or processor modules, about the changes in the database. + +*/ + +typedef int help_t; ///< message id from ida.hlp + +struct outctx_t; +struct regval_t; +struct stkpnts_t; +struct simd_info_t; +struct reg_accesses_t; +struct call_stack_t; +class merge_data_t; + +/// The interface version number. +/// \note see also #IDA_SDK_VERSION from pro.h + +#define IDP_INTERFACE_VERSION 700 + +//----------------------------------------------------------------------- +/// Structure used to describe byte streams +/// (for "ret" instruction and empirics) +struct bytes_t +{ + uchar len; + const uchar *bytes; +}; + +//----------------------------------------------------------------------- +/// Internal representation of processor instructions. +/// Definition of all internal instructions are kept in special arrays. +/// One of such arrays describes instruction names and features. +struct instruc_t +{ + const char *name; ///< instruction name + uint32 feature; ///< combination of \ref CF_ +/// \defgroup CF_ Instruction feature bits +/// Used by instruc_t::feature +//@{ +#define CF_STOP 0x00001 ///< Instruction doesn't pass execution to the + ///< next instruction +#define CF_CALL 0x00002 ///< CALL instruction (should make a procedure here) +#define CF_CHG1 0x00004 ///< The instruction modifies the first operand +#define CF_CHG2 0x00008 ///< The instruction modifies the second operand +#define CF_CHG3 0x00010 ///< The instruction modifies the third operand +#define CF_CHG4 0x00020 ///< The instruction modifies 4 operand +#define CF_CHG5 0x00040 ///< The instruction modifies 5 operand +#define CF_CHG6 0x00080 ///< The instruction modifies 6 operand +#define CF_USE1 0x00100 ///< The instruction uses value of the first operand +#define CF_USE2 0x00200 ///< The instruction uses value of the second operand +#define CF_USE3 0x00400 ///< The instruction uses value of the third operand +#define CF_USE4 0x00800 ///< The instruction uses value of the 4 operand +#define CF_USE5 0x01000 ///< The instruction uses value of the 5 operand +#define CF_USE6 0x02000 ///< The instruction uses value of the 6 operand +#define CF_JUMP 0x04000 ///< The instruction passes execution using indirect + ///< jump or call (thus needs additional analysis) +#define CF_SHFT 0x08000 ///< Bit-shift instruction (shl,shr...) +#define CF_HLL 0x10000 ///< Instruction may be present in a high level + ///< language function. +#define CF_CHG7 0x020000 ///< The instruction modifies the 7th operand +#define CF_CHG8 0x040000 ///< The instruction modifies the 8th operand +#define CF_USE7 0x080000 ///< The instruction uses value of the 7th operand +#define CF_USE8 0x100000 ///< The instruction uses value of the 8th operand +//@} +}; + + +/// Does an instruction with the specified feature modify the i-th operand? + +inline THREAD_SAFE bool has_cf_chg(uint32 feature, uint opnum) +{ + static const int bits[] = + { + CF_CHG1, CF_CHG2, CF_CHG3, CF_CHG4, + CF_CHG5, CF_CHG6, CF_CHG7, CF_CHG8, + }; + CASSERT(qnumber(bits) == UA_MAXOP); + return opnum < UA_MAXOP && (feature & bits[opnum]) != 0; +} + + +/// Does an instruction with the specified feature use a value of the i-th operand? + +inline THREAD_SAFE bool has_cf_use(uint32 feature, uint opnum) +{ + static const int bits[] = + { + CF_USE1, CF_USE2, CF_USE3, CF_USE4, + CF_USE5, CF_USE6, CF_USE7, CF_USE8, + }; + CASSERT(qnumber(bits) == UA_MAXOP); + return opnum < UA_MAXOP && (feature & bits[opnum]) != 0; +} + + +/// Does the specified instruction have the specified feature? + +idaman bool ida_export has_insn_feature(int icode, uint32 bit); + + + +/// Is the instruction a "call"? + +idaman bool ida_export is_call_insn(const insn_t &insn); + + +/// Is the instruction a "return"? + +idaman bool ida_export is_ret_insn(const insn_t &insn, bool strict=true); + + +/// Is the instruction an indirect jump? + +idaman bool ida_export is_indirect_jump_insn(const insn_t &insn); + + +/// Is the instruction the end of a basic block? + +idaman bool ida_export is_basic_block_end(const insn_t &insn, bool call_insn_stops_block); + + +//===================================================================== +/// Describes the target assembler. +/// An IDP module may have several target assemblers. +/// In this case you should create a structure for each supported +/// assembler. +struct asm_t +{ + uint32 flag; ///< \ref AS_ +/// \defgroup AS_ Assembler feature bits +/// Used by asm_t::flag. +//@{ +#define AS_OFFST 0x00000001L ///< offsets are 'offset xxx' ? +#define AS_COLON 0x00000002L ///< create colons after data names ? +#define AS_UDATA 0x00000004L ///< can use '?' in data directives + +#define AS_2CHRE 0x00000008L ///< double char constants are: "xy +#define AS_NCHRE 0x00000010L ///< char constants are: 'x +#define AS_N2CHR 0x00000020L ///< can't have 2 byte char consts + + // String literals: +#define AS_1TEXT 0x00000040L ///< 1 text per line, no bytes +#define AS_NHIAS 0x00000080L ///< no characters with high bit +#define AS_NCMAS 0x00000100L ///< no commas in ascii directives + +#define AS_HEXFM 0x00000E00L ///< mask - hex number format +#define ASH_HEXF0 0x00000000L ///< 34h +#define ASH_HEXF1 0x00000200L ///< h'34 +#define ASH_HEXF2 0x00000400L ///< 34 +#define ASH_HEXF3 0x00000600L ///< 0x34 +#define ASH_HEXF4 0x00000800L ///< $34 +#define ASH_HEXF5 0x00000A00L ///< <^R > (radix) +#define AS_DECFM 0x00003000L ///< mask - decimal number format +#define ASD_DECF0 0x00000000L ///< 34 +#define ASD_DECF1 0x00001000L ///< #34 +#define ASD_DECF2 0x00002000L ///< 34. +#define ASD_DECF3 0x00003000L ///< .34 +#define AS_OCTFM 0x0001C000L ///< mask - octal number format +#define ASO_OCTF0 0x00000000L ///< 123o +#define ASO_OCTF1 0x00004000L ///< 0123 +#define ASO_OCTF2 0x00008000L ///< 123 +#define ASO_OCTF3 0x0000C000L ///< @123 +#define ASO_OCTF4 0x00010000L ///< o'123 +#define ASO_OCTF5 0x00014000L ///< 123q +#define ASO_OCTF6 0x00018000L ///< ~123 +#define ASO_OCTF7 0x0001C000L ///< q'123 +#define AS_BINFM 0x000E0000L ///< mask - binary number format +#define ASB_BINF0 0x00000000L ///< 010101b +#define ASB_BINF1 0x00020000L ///< ^B010101 +#define ASB_BINF2 0x00040000L ///< %010101 +#define ASB_BINF3 0x00060000L ///< 0b1010101 +#define ASB_BINF4 0x00080000L ///< b'1010101 +#define ASB_BINF5 0x000A0000L ///< b'1010101' + +#define AS_UNEQU 0x00100000L ///< replace undefined data items with EQU (for ANTA's A80) +#define AS_ONEDUP 0x00200000L ///< One array definition per line +#define AS_NOXRF 0x00400000L ///< Disable xrefs during the output file generation +#define AS_XTRNTYPE 0x00800000L ///< Assembler understands type of extern symbols as ":type" suffix +#define AS_RELSUP 0x01000000L ///< Checkarg: 'and','or','xor' operations with addresses are possible +#define AS_LALIGN 0x02000000L ///< Labels at "align" keyword are supported. +#define AS_NOCODECLN 0x04000000L ///< don't create colons after code names +#define AS_NOSPACE 0x10000000L ///< No spaces in expressions +#define AS_ALIGN2 0x20000000L ///< .align directive expects an exponent rather than a power of 2 + ///< (.align 5 means to align at 32byte boundary) +#define AS_ASCIIC 0x40000000L ///< ascii directive accepts C-like escape sequences + ///< (\\n,\\x01 and similar) +#define AS_ASCIIZ 0x80000000L ///< ascii directive inserts implicit zero byte at the end +//@} + uint16 uflag; ///< user defined flags (local only for IDP) + ///< you may define and use your own bits + const char *name; ///< Assembler name (displayed in menus) + help_t help; ///< Help screen number, 0 - no help + const char *const *header; ///< array of automatically generated header lines + ///< they appear at the start of disassembled text + const char *origin; ///< org directive + const char *end; ///< end directive + const char *cmnt; ///< comment string (see also cmnt2) + char ascsep; ///< string literal delimiter + char accsep; ///< char constant delimiter + const char *esccodes; ///< special chars that cannot appear + ///< as is in string and char literals + + // Data representation (db,dw,...): + const char *a_ascii; ///< string literal directive + const char *a_byte; ///< byte directive + const char *a_word; ///< word directive + const char *a_dword; ///< NULL if not allowed + const char *a_qword; ///< NULL if not allowed + const char *a_oword; ///< NULL if not allowed + const char *a_float; ///< float; 4bytes; NULL if not allowed + const char *a_double; ///< double; 8bytes; NULL if not allowed + const char *a_tbyte; ///< long double; NULL if not allowed + const char *a_packreal; ///< packed decimal real NULL if not allowed + const char *a_dups; ///< array keyword. the following + ///< sequences may appear: + ///< - #h header + ///< - #d size + ///< - #v value + ///< - #s(b,w,l,q,f,d,o) size specifiers + ///< for byte,word, + ///< dword,qword, + ///< float,double,oword + const char *a_bss; ///< uninitialized data directive + ///< should include '%s' for the + ///< size of data + const char *a_equ; ///< 'equ' Used if AS_UNEQU is set + const char *a_seg; ///< 'seg ' prefix (example: push seg seg001) + + const char *a_curip; ///< current IP (instruction pointer) symbol in assembler + + /// Generate function header lines. + /// If NULL, then function headers are displayed as normal lines + void (idaapi *out_func_header)(outctx_t &ctx, func_t *); + + /// Generate function footer lines. + /// If NULL, then a comment line is displayed + void (idaapi *out_func_footer)(outctx_t &ctx, func_t *); + + const char *a_public; ///< "public" name keyword. NULL-use default, ""-do not generate + const char *a_weak; ///< "weak" name keyword. NULL-use default, ""-do not generate + const char *a_extrn; ///< "extern" name keyword + const char *a_comdef; ///< "comm" (communal variable) + + /// Get name of type of item at ea or id. + /// (i.e. one of: byte,word,dword,near,far,etc...) + ssize_t (idaapi *get_type_name)( + qstring *buf, + flags_t flag, + ea_t ea_or_id); + + const char *a_align; ///< "align" keyword + + char lbrace; ///< left brace used in complex expressions + char rbrace; ///< right brace used in complex expressions + + const char *a_mod; ///< % mod assembler time operation + const char *a_band; ///< & bit and assembler time operation + const char *a_bor; ///< | bit or assembler time operation + const char *a_xor; ///< ^ bit xor assembler time operation + const char *a_bnot; ///< ~ bit not assembler time operation + const char *a_shl; ///< << shift left assembler time operation + const char *a_shr; ///< >> shift right assembler time operation + const char *a_sizeof_fmt; ///< size of type (format string) + + uint32 flag2; ///< \ref AS2_ +/// \defgroup AS2_ Secondary assembler feature bits +/// Used by asm_t::flag2 +//@{ +#define AS2_BRACE 0x00000001 ///< Use braces for all expressions +#define AS2_STRINV 0x00000002 ///< Invert meaning of \inf{wide_high_byte_first} for text strings + ///< (For processors with bytes bigger than 8 bits) +#define AS2_BYTE1CHAR 0x00000004 ///< One symbol per processor byte + ///< Meaningful only for wide byte processors +#define AS2_IDEALDSCR 0x00000008 ///< Description of struc/union is in + ///< the 'reverse' form (keyword before name) + ///< the same as in borland tasm ideal +#define AS2_TERSESTR 0x00000010 ///< 'terse' structure initialization form + ///< NAME<fld,fld,...> is supported +#define AS2_COLONSUF 0x00000020 ///< addresses may have ":xx" suffix + ///< this suffix must be ignored when extracting + ///< the address under the cursor +#define AS2_YWORD 0x00000040 ///< a_yword field is present and valid +//@} + + const char *cmnt2; ///< comment close string (usually NULL) + ///< this is used to denote a string which + ///< closes comments, for example, if the + ///< comments are represented with (* ... *) + ///< then cmnt = "(*" and cmnt2 = "*)" + const char *low8; ///< low8 operation, should contain %s for the operand + const char *high8; ///< high8 + const char *low16; ///< low16 + const char *high16; ///< high16 + const char *a_include_fmt; ///< the include directive (format string) + const char *a_vstruc_fmt; ///< if a named item is a structure and displayed + ///< in the verbose (multiline) form then display the name + ///< as printf(a_strucname_fmt, typename) + ///< (for asms with type checking, e.g. tasm ideal) + const char *a_rva; ///< 'rva' keyword for image based offsets + ///< (see #REFINFO_RVAOFF) + const char *a_yword; ///< 32-byte (256-bit) data; NULL if not allowed + ///< requires #AS2_YWORD +}; +#ifndef __X86__ +CASSERT(sizeof(asm_t) == 408); +#else +CASSERT(sizeof(asm_t) == 208); +#endif + +// forward declarations for notification helpers +struct proc_def_t; +struct extlang_t; +class qflow_chart_t; +struct libfunc_t; +struct fixup_data_t; +struct idd_opinfo_t; +class argloc_t; +struct func_type_data_t; +struct regobjs_t; +class callregs_t; +struct funcarg_t; + +//-------------------------------------------------------------------------- +struct event_listener_t +{ + size_t listener_flags = 0; // reserved + /// Callback to handle events. The event code depends on the event + /// group where the callback is attached to. + virtual ssize_t idaapi on_event(ssize_t code, va_list va) = 0; + virtual ~event_listener_t() {} +}; + +/// Install an event listener. +/// The installed listener will be called for all kernel events of the specified +/// type (\ref hook_type_t). +/// \param hook_type one of \ref hook_type_t constants +/// \param cb The event listener object +/// \param owner The listener owner. Points to an instance of: plugin_t, +/// processor_t, or loader_t. Can be nullptr, which means +/// undefined owner. The owner is used by the kernel for +/// automatic removal of the event listener when the owner is +/// unloaded from the memory. +/// \param hkcb_flags combination of \ref HKCB_ bits +/// \return success +idaman bool ida_export hook_event_listener( + hook_type_t hook_type, + event_listener_t *cb, + const void *owner, + int hkcb_flags=0); +/// \defgroup HKCB_ Hook installation bits. +//@{ +#define HKCB_GLOBAL 0x0001 ///< is global event listener? if true, the listener + ///< will survive database closing and opening. it + ///< will stay in the memory until explicitly + ///< unhooked. otherwise the kernel will delete it + ///< as soon as the owner is unloaded. + ///< should be used only with PLUGIN_FIX plugins. +//@} + +/// Uninstall an event listener. +/// \param hook_type one of \ref hook_type_t constants +/// \param cb the listener object +/// \return success +/// Uninstalling a listener is necessary only for global listeners and +/// listeners with undefined owner. Other listeners are uninstalled +/// automatically when the owner module is unloaded. +idaman bool ida_export unhook_event_listener( + hook_type_t hook_type, + event_listener_t *cb); + +/// Declare listener with a context +#define DECLARE_LISTENER(listener_type, ctx_type, ctx_name) \ + struct listener_type : public event_listener_t \ + { \ + ctx_type &ctx_name; \ + listener_type(ctx_type &_ctx) : ctx_name(_ctx) {} \ + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; \ + } + +//===================================================================== +/// Describes a processor module (IDP). +/// An IDP file may have only one such structure called LPH. +/// The kernel will copy it to ::ph structure and use ::ph. +struct processor_t +{ + int32 version; ///< Expected kernel version, + ///< should be #IDP_INTERFACE_VERSION + int32 id; ///< one of \ref PLFM_ +/// \defgroup PLFM_ Processor IDs +/// Used by processor_t::id. +/// Numbers above 0x8000 are reserved for the third-party modules +//@{ +#define PLFM_386 0 ///< Intel 80x86 +#define PLFM_Z80 1 ///< 8085, Z80 +#define PLFM_I860 2 ///< Intel 860 +#define PLFM_8051 3 ///< 8051 +#define PLFM_TMS 4 ///< Texas Instruments TMS320C5x +#define PLFM_6502 5 ///< 6502 +#define PLFM_PDP 6 ///< PDP11 +#define PLFM_68K 7 ///< Motorola 680x0 +#define PLFM_JAVA 8 ///< Java +#define PLFM_6800 9 ///< Motorola 68xx +#define PLFM_ST7 10 ///< SGS-Thomson ST7 +#define PLFM_MC6812 11 ///< Motorola 68HC12 +#define PLFM_MIPS 12 ///< MIPS +#define PLFM_ARM 13 ///< Advanced RISC Machines +#define PLFM_TMSC6 14 ///< Texas Instruments TMS320C6x +#define PLFM_PPC 15 ///< PowerPC +#define PLFM_80196 16 ///< Intel 80196 +#define PLFM_Z8 17 ///< Z8 +#define PLFM_SH 18 ///< Renesas (formerly Hitachi) SuperH +#define PLFM_NET 19 ///< Microsoft Visual Studio.Net +#define PLFM_AVR 20 ///< Atmel 8-bit RISC processor(s) +#define PLFM_H8 21 ///< Hitachi H8/300, H8/2000 +#define PLFM_PIC 22 ///< Microchip's PIC +#define PLFM_SPARC 23 ///< SPARC +#define PLFM_ALPHA 24 ///< DEC Alpha +#define PLFM_HPPA 25 ///< Hewlett-Packard PA-RISC +#define PLFM_H8500 26 ///< Hitachi H8/500 +#define PLFM_TRICORE 27 ///< Tasking Tricore +#define PLFM_DSP56K 28 ///< Motorola DSP5600x +#define PLFM_C166 29 ///< Siemens C166 family +#define PLFM_ST20 30 ///< SGS-Thomson ST20 +#define PLFM_IA64 31 ///< Intel Itanium IA64 +#define PLFM_I960 32 ///< Intel 960 +#define PLFM_F2MC 33 ///< Fujistu F2MC-16 +#define PLFM_TMS320C54 34 ///< Texas Instruments TMS320C54xx +#define PLFM_TMS320C55 35 ///< Texas Instruments TMS320C55xx +#define PLFM_TRIMEDIA 36 ///< Trimedia +#define PLFM_M32R 37 ///< Mitsubishi 32bit RISC +#define PLFM_NEC_78K0 38 ///< NEC 78K0 +#define PLFM_NEC_78K0S 39 ///< NEC 78K0S +#define PLFM_M740 40 ///< Mitsubishi 8bit +#define PLFM_M7700 41 ///< Mitsubishi 16bit +#define PLFM_ST9 42 ///< ST9+ +#define PLFM_FR 43 ///< Fujitsu FR Family +#define PLFM_MC6816 44 ///< Motorola 68HC16 +#define PLFM_M7900 45 ///< Mitsubishi 7900 +#define PLFM_TMS320C3 46 ///< Texas Instruments TMS320C3 +#define PLFM_KR1878 47 ///< Angstrem KR1878 +#define PLFM_AD218X 48 ///< Analog Devices ADSP 218X +#define PLFM_OAKDSP 49 ///< Atmel OAK DSP +#define PLFM_TLCS900 50 ///< Toshiba TLCS-900 +#define PLFM_C39 51 ///< Rockwell C39 +#define PLFM_CR16 52 ///< NSC CR16 +#define PLFM_MN102L00 53 ///< Panasonic MN10200 +#define PLFM_TMS320C1X 54 ///< Texas Instruments TMS320C1x +#define PLFM_NEC_V850X 55 ///< NEC V850 and V850ES/E1/E2 +#define PLFM_SCR_ADPT 56 ///< Processor module adapter for processor modules written in scripting languages +#define PLFM_EBC 57 ///< EFI Bytecode +#define PLFM_MSP430 58 ///< Texas Instruments MSP430 +#define PLFM_SPU 59 ///< Cell Broadband Engine Synergistic Processor Unit +#define PLFM_DALVIK 60 ///< Android Dalvik Virtual Machine +#define PLFM_65C816 61 ///< 65802/65816 +#define PLFM_M16C 62 ///< Renesas M16C +#define PLFM_ARC 63 ///< Argonaut RISC Core +#define PLFM_UNSP 64 ///< SunPlus unSP +#define PLFM_TMS320C28 65 ///< Texas Instruments TMS320C28x +#define PLFM_DSP96K 66 ///< Motorola DSP96000 +#define PLFM_SPC700 67 ///< Sony SPC700 +#define PLFM_AD2106X 68 ///< Analog Devices ADSP 2106X +#define PLFM_PIC16 69 ///< Microchip's 16-bit PIC +#define PLFM_S390 70 ///< IBM's S390 +#define PLFM_XTENSA 71 ///< Tensilica Xtensa +#define PLFM_RISCV 72 ///< RISC-V +#define PLFM_RL78 73 ///< Renesas RL78 +//@} + + uint32 flag; ///< \ref PR_ +/// \defgroup PR_ Processor feature bits +/// Used by processor_t::flag +//@{ +#define PR_SEGS 0x000001 ///< has segment registers? +#define PR_USE32 0x000002 ///< supports 32-bit addressing? +#define PR_DEFSEG32 0x000004 ///< segments are 32-bit by default +#define PR_RNAMESOK 0x000008 ///< allow user register names for location names +//#define PR_DB2CSEG 0x0010 // .byte directive in code segments +// // should define even number of bytes +// // (used by AVR processor) +#define PR_ADJSEGS 0x000020 ///< IDA may adjust segments' starting/ending addresses. +#define PR_DEFNUM 0x0000C0 ///< mask - default number representation +#define PRN_HEX 0x000000 ///< hex +#define PRN_OCT 0x000040 ///< octal +#define PRN_DEC 0x000080 ///< decimal +#define PRN_BIN 0x0000C0 ///< binary +#define PR_WORD_INS 0x000100 ///< instruction codes are grouped 2bytes in binary line prefix +#define PR_NOCHANGE 0x000200 ///< The user can't change segments and code/data attributes + ///< (display only) +#define PR_ASSEMBLE 0x000400 ///< Module has a built-in assembler and will react to ev_assemble +#define PR_ALIGN 0x000800 ///< All data items should be aligned properly +#define PR_TYPEINFO 0x001000 ///< the processor module supports type information callbacks + ///< ALL OF THEM SHOULD BE IMPLEMENTED! +#define PR_USE64 0x002000 ///< supports 64-bit addressing? +#define PR_SGROTHER 0x004000 ///< the segment registers don't contain the segment selectors. +#define PR_STACK_UP 0x008000 ///< the stack grows up +#define PR_BINMEM 0x010000 ///< the processor module provides correct segmentation for binary files + ///< (i.e. it creates additional segments) + ///< The kernel will not ask the user to specify the RAM/ROM sizes +#define PR_SEGTRANS 0x020000 ///< the processor module supports the segment translation feature + ///< (meaning it calculates the code + ///< addresses using the map_code_ea() function) +#define PR_CHK_XREF 0x040000 ///< don't allow near xrefs between segments with different bases +#define PR_NO_SEGMOVE 0x080000 ///< the processor module doesn't support move_segm() + ///< (i.e. the user can't move segments) +//#define PR_FULL_HIFXP 0x100000 // ::REF_VHIGH operand value contains full operand +// // (not only the high bits) Meaningful if \ph{high_fixup_bits} +#define PR_USE_ARG_TYPES 0x200000 ///< use \ph{use_arg_types} callback +#define PR_SCALE_STKVARS 0x400000 ///< use \ph{get_stkvar_scale} callback +#define PR_DELAYED 0x800000 ///< has delayed jumps and calls + ///< if this flag is set, \ph{is_basic_block_end}, \ph{has_delay_slot} + ///< should be implemented +#define PR_ALIGN_INSN 0x1000000 ///< allow ida to create alignment instructions arbitrarily. + ///< Since these instructions might lead to other wrong instructions + ///< and spoil the listing, IDA does not create them by default anymore +#define PR_PURGING 0x2000000 ///< there are calling conventions which may purge bytes from the stack +#define PR_CNDINSNS 0x4000000 ///< has conditional instructions +#define PR_USE_TBYTE 0x8000000 ///< ::BTMT_SPECFLT means _TBYTE type +#define PR_DEFSEG64 0x10000000 ///< segments are 64-bit by default +#define PR_OUTER 0x20000000 ///< has outer operands (currently only mc68k) +//@} + + uint32 flag2; ///< \ref PR2_ +/// \defgroup PR2_ Processor additional feature bits +/// Used by processor_t::flag2 +//@{ +#define PR2_MAPPINGS 0x000001 ///< the processor module uses memory mapping +#define PR2_IDP_OPTS 0x000002 ///< the module has processor-specific configuration options +#define PR2_REALCVT 0x000004 ///< the module has a custom 'ev_realcvt' implementation (otherwise IEEE-754 format is assumed) +#define PR2_CODE16_BIT 0x000008 ///< low bit of code addresses has special meaning + ///< e.g. ARM Thumb, MIPS16 +#define PR2_MACRO 0x000010 ///< processor supports macro instructions +#define PR2_USE_CALCREL 0x000020 ///< (Lumina) the module supports calcrel info +#define PR2_REL_BITS 0x000040 ///< (Lumina) calcrel info has bits granularity, not bytes - construction flag only +//@} + + bool has_idp_opts(void) const { return (flag2 & PR2_IDP_OPTS) != 0; } ///< #PR_IDP_OPTS + bool has_realcvt(void) const { return (flag2 & PR2_REALCVT) != 0; } ///< #PR_REALCVT + bool has_segregs(void) const { return (flag & PR_SEGS) != 0; } ///< #PR_SEGS + bool use32(void) const { return (flag & (PR_USE64|PR_USE32)) != 0; } ///< #PR_USE64 or #PR_USE32 + bool use64(void) const { return (flag & PR_USE64) != 0; } ///< #PR_USE64 + bool ti(void) const { return (flag & PR_TYPEINFO) != 0; } ///< #PR_TYPEINFO + bool stkup(void) const { return (flag & PR_STACK_UP) != 0; } ///< #PR_STACK_UP + bool use_tbyte(void) const { return (flag & PR_USE_TBYTE) != 0; } ///< #PR_USE_TBYTE + bool use_mappings(void) const { return (flag2 & PR2_MAPPINGS) != 0; } ///< #PR2_MAPPINGS + bool has_code16_bit(void) const { return (flag2 & PR2_CODE16_BIT) != 0; } ///< #PR2_CODE16_BIT + bool supports_macros(void) const { return (flag2 & PR2_MACRO) != 0; } ///< #PR2_MACRO + bool supports_calcrel(void) const { return (flag2 & PR2_USE_CALCREL) != 0; } ///< #PR2_USE_CALCREL + bool calcrel_in_bits(void) const { return (flag2 & PR2_REL_BITS) != 0; } ///< #PR2_REL_BITS + + + /// Get segment bitness + /// \retval 2 #PR_DEFSEG64 + /// \retval 1 #PR_DEFSEG32 + /// \retval 0 none specified + + int get_segm_bitness(void) const { return (flag & PR_DEFSEG64) != 0 ? 2 : (flag & PR_DEFSEG32) != 0; } + + int32 cnbits; ///< Number of bits in a byte + ///< for code segments (usually 8). + ///< IDA supports values up to supported + ///< address bits size + int32 dnbits; ///< Number of bits in a byte + ///< for non-code segments (usually 8). + ///< IDA supports values up to supported + ///< address bit size + + /// \name Byte size + /// Number of 8bit bytes required to hold one byte of the target processor. + //@{ + int cbsize(void) { return (cnbits+7)/8; } ///< for code segments + int dbsize(void) { return (dnbits+7)/8; } ///< for non-code segments + //@} + + /// \name Names + /// IDP module may support several compatible processors. + /// The following arrays define processor names: + //@{ + const char *const *psnames; ///< short processor names (NULL terminated). + ///< Each name should be shorter than 9 characters + const char *const *plnames; ///< long processor names (NULL terminated). + ///< No restriction on name lengths. + //@} + + inline int get_proc_index(); ///< \retval currently selected processor subtype (index into psnames/plnames) + + const asm_t *const *assemblers; ///< pointer to array of target + ///< assembler definitions. You may + ///< change this array when current + ///< processor is changed. + ///< (NULL terminated) + +/// Custom instruction codes defined by processor extension plugins +/// must be greater than or equal to this +#define CUSTOM_INSN_ITYPE 0x8000 + +/// processor_t::use_regarg_type uses this bit in the return value +/// to indicate that the register value has been spoiled +#define REG_SPOIL 0x80000000L + + typedef const regval_t &(idaapi regval_getter_t)( + const char *name, + const regval_t *regvalues); + + //<hookgen IDP> + + /// Callback notification codes. + /// + /// These are passed to notify() when certain events occur in the kernel, + /// allowing the processor module to take the appropriate action. + /// + /// If you are not developing a processor module, you do not need to + /// use the codes directly many of them already have a corresponding function + /// to use instead (\idpcode{is_call_insn} vs is_call_insn(ea_t), for example). + /// + /// If you are developing a processor module, your notify() function + /// must implement the desired behavior when called with a given code. + /// Not all events need to be handled, some of them are optional. + enum event_t + { + ev_init, ///< The IDP module is just loaded. + ///< \param idp_modname (const char *) processor module name + ///< \retval <0 on failure + + ev_term, ///< The IDP module is being unloaded + + ev_newprc, ///< Before changing processor type. + ///< \param pnum (int) processor number in the array of processor names + ///< \param keep_cfg (bool) true: do not modify kernel configuration + ///< \retval 1 ok + ///< \retval <0 prohibit + + ev_newasm, ///< Before setting a new assembler. + ///< \param asmnum (int) + ///< See also ev_asm_installed + + ev_newfile, ///< A new file has been loaded. + ///< \param fname (char *) input file name + + ev_oldfile, ///< An old file has been loaded. + ///< \param fname (char *) input file name + + ev_newbinary, ///< IDA is about to load a binary file. + ///< \param filename (char *) binary file name + ///< \param fileoff (::qoff64_t) offset in the file + ///< \param basepara (::ea_t) base loading paragraph + ///< \param binoff (::ea_t) loader offset + ///< \param nbytes (::uint64) number of bytes to load + + ev_endbinary, ///< IDA has loaded a binary file. + ///< \param ok (bool) file loaded successfully? + + ev_set_idp_options, ///< Set IDP-specific configuration option + ///< Also see set_options_t in config.hpp + ///< \param keyword (const char *) + ///< \param value_type (int) + ///< \param value (const void *) + ///< \param errbuf (const char **) - a error message will be returned here (can be NULL) + ///< \param idb_loaded (bool) true if the ev_oldfile/ev_newfile events have been generated + ///< \retval 1 ok + ///< \retval 0 not implemented + ///< \retval -1 error (and message in errbuf) + + ev_set_proc_options, ///< Called if the user specified an option string in the command line: + ///< -p<processor name>:<options>. + ///< Can be used for setting a processor subtype. + ///< Also called if option string is passed to set_processor_type() + ///< and IDC's SetProcessorType(). + ///< \param options (const char *) + ///< \param confidence (int) + ///< 0: loader's suggestion + ///< 1: user's decision + ///< \retval <0 if bad option string + + ev_ana_insn, ///< Analyze one instruction and fill 'out' structure. + ///< This function shouldn't change the database, flags or anything else. + ///< All these actions should be performed only by emu_insn() function. + ///< \insn_t{ea} contains address of instruction to analyze. + ///< \param out (::insn_t *) + ///< \return length of the instruction in bytes, 0 if instruction can't be decoded. + ///< \retval 0 if instruction can't be decoded. + + ev_emu_insn, ///< Emulate instruction, create cross-references, plan to analyze + ///< subsequent instructions, modify flags etc. Upon entrance to this function, + ///< all information about the instruction is in 'insn' structure. + ///< \param insn (const ::insn_t *) + ///< \retval 1 ok + ///< \retval -1 the kernel will delete the instruction + + ev_out_header, ///< Function to produce start of disassembled text + ///< \param outctx (::outctx_t *) + ///< \retval void + + ev_out_footer, ///< Function to produce end of disassembled text + ///< \param outctx (::outctx_t *) + ///< \retval void + + ev_out_segstart, ///< Function to produce start of segment + ///< \param outctx (::outctx_t *) + ///< \param seg (::segment_t *) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_out_segend, ///< Function to produce end of segment + ///< \param outctx (::outctx_t *) + ///< \param seg (::segment_t *) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_out_assumes, ///< Function to produce assume directives + ///< when segment register value changes. + ///< \param outctx (::outctx_t *) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_out_insn, ///< Generate text representation of an instruction in 'ctx.insn' + ///< outctx_t provides functions to output the generated text. + ///< This function shouldn't change the database, flags or anything else. + ///< All these actions should be performed only by emu_insn() function. + ///< \param outctx (::outctx_t *) + ///< \retval void + + ev_out_mnem, ///< Generate instruction mnemonics. + ///< This callback should append the colored mnemonics to ctx.outbuf + ///< Optional notification, if absent, out_mnem will be called. + ///< \param outctx (::outctx_t *) + ///< \retval 1 if appended the mnemonics + ///< \retval 0 not implemented + + ev_out_operand, ///< Generate text representation of an instruction operand + ///< outctx_t provides functions to output the generated text. + ///< All these actions should be performed only by emu_insn() function. + ///< \param outctx (::outctx_t *) + ///< \param op (const ::op_t *) + ///< \retval 1 ok + ///< \retval -1 operand is hidden + + ev_out_data, ///< Generate text representation of data items + ///< This function may change the database and create cross-references + ///< if analyze_only is set + ///< \param outctx (::outctx_t *) + ///< \param analyze_only (bool) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_out_label, ///< The kernel is going to generate an instruction + ///< label line or a function header. + ///< \param outctx (::outctx_t *) + ///< \param colored_name (const char *) + ///< \retval <0 if the kernel should not generate the label + ///< \retval 0 not implemented or continue + + ev_out_special_item, ///< Generate text representation of an item in a special segment + ///< i.e. absolute symbols, externs, communal definitions etc + ///< \param outctx (::outctx_t *) + ///< \param segtype (uchar) + ///< \retval 1 ok + ///< \retval 0 not implemented + ///< \retval -1 overflow + + ev_gen_stkvar_def, ///< Generate stack variable definition line + ///< Default line is + ///< varname = type ptr value, + ///< where 'type' is one of byte,word,dword,qword,tbyte + ///< \param outctx (::outctx_t *) + ///< \param mptr (const ::member_t *) + ///< \param v (sval_t) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_gen_regvar_def, ///< Generate register variable definition line. + ///< \param outctx (::outctx_t *) + ///< \param v (::regvar_t *) + ///< \retval >0 ok, generated the definition text + ///< \retval 0 not implemented + + ev_gen_src_file_lnnum, ///< Callback: generate analog of: + ///< \code + ///< #line "file.c" 123 + ///< \endcode + ///< directive. + ///< \param outctx (::outctx_t *) output context + ///< \param file (const char *) source file (may be NULL) + ///< \param lnnum (size_t) line number + ///< \retval 1 directive has been generated + ///< \retval 0 not implemented + + ev_creating_segm, ///< A new segment is about to be created. + ///< \param seg (::segment_t *) + ///< \retval 1 ok + ///< \retval <0 segment should not be created + + ev_moving_segm, ///< May the kernel move the segment? + ///< \param seg (::segment_t *) segment to move + ///< \param to (::ea_t) new segment start address + ///< \param flags (int) combination of \ref MSF_ + ///< \retval 0 yes + ///< \retval <0 the kernel should stop + + ev_coagulate, ///< Try to define some unexplored bytes. + ///< This notification will be called if the + ///< kernel tried all possibilities and could + ///< not find anything more useful than to + ///< convert to array of bytes. + ///< The module can help the kernel and convert + ///< the bytes into something more useful. + ///< \param start_ea (::ea_t) + ///< \return number of converted bytes + + ev_undefine, ///< An item in the database (insn or data) is being deleted. + ///< \param ea (ea_t) + ///< \retval 1 do not delete srranges at the item end + ///< \retval 0 srranges can be deleted + + ev_treat_hindering_item, ///< An item hinders creation of another item. + ///< \param hindering_item_ea (::ea_t) + ///< \param new_item_flags (::flags_t) (0 for code) + ///< \param new_item_ea (::ea_t) + ///< \param new_item_length (::asize_t) + ///< \retval 0 no reaction + ///< \retval !=0 the kernel may delete the hindering item + + ev_rename, ///< The kernel is going to rename a byte. + ///< \param ea (::ea_t) + ///< \param new_name (const char *) + ///< \param flags (int) \ref SN_ + ///< \retval <0 if the kernel should not rename it. + ///< \retval 2 to inhibit the notification. I.e., + ///< the kernel should not rename, but + ///< 'set_name()' should return 'true'. + ///< also see \idpcode{renamed} + ///< the return value is ignored when kernel is going to delete name + + ev_is_far_jump, ///< is indirect far jump or call instruction? + ///< meaningful only if the processor has 'near' and 'far' reference types + ///< \param icode (int) + ///< \retval 0 not implemented + ///< \retval 1 yes + ///< \retval -1 no + + ev_is_sane_insn, ///< Is the instruction sane for the current file type?. + ///< \param insn (const ::insn_t*) the instruction + ///< \param no_crefs (int) + ///< 1: the instruction has no code refs to it. + ///< ida just tries to convert unexplored bytes + ///< to an instruction (but there is no other + ///< reason to convert them into an instruction) + ///< 0: the instruction is created because + ///< of some coderef, user request or another + ///< weighty reason. + ///< \retval >=0 ok + ///< \retval <0 no, the instruction isn't + ///< likely to appear in the program + + ev_is_cond_insn, ///< Is conditional instruction? + ///< \param insn (const ::insn_t *) instruction address + ///< \retval 1 yes + ///< \retval -1 no + ///< \retval 0 not implemented or not instruction + + ev_is_call_insn, ///< Is the instruction a "call"? + ///< \param insn (const ::insn_t *) instruction + ///< \retval 0 unknown + ///< \retval <0 no + ///< \retval 1 yes + + ev_is_ret_insn, ///< Is the instruction a "return"? + ///< \param insn (const ::insn_t *) instruction + ///< \param strict (bool) + ///< 1: report only ret instructions + ///< 0: include instructions like "leave" + ///< which begins the function epilog + ///< \retval 0 unknown + ///< \retval <0 no + ///< \retval 1 yes + + ev_may_be_func, ///< Can a function start here? + ///< \param insn (const ::insn_t*) the instruction + ///< \param state (int) autoanalysis phase + ///< 0: creating functions + ///< 1: creating chunks + ///< \return probability 1..100 + + ev_is_basic_block_end, ///< Is the current instruction end of a basic block?. + ///< This function should be defined for processors + ///< with delayed jump slots. + ///< \param insn (const ::insn_t*) the instruction + ///< \param call_insn_stops_block (bool) + ///< \retval 0 unknown + ///< \retval <0 no + ///< \retval 1 yes + + ev_is_indirect_jump, ///< Determine if instruction is an indirect jump. + ///< If #CF_JUMP bit cannot describe all jump types + ///< jumps, please define this callback. + ///< \param insn (const ::insn_t*) the instruction + ///< \retval 0 use #CF_JUMP + ///< \retval 1 no + ///< \retval 2 yes + + ev_is_insn_table_jump, ///< Reserved + + ev_is_switch, ///< Find 'switch' idiom. + ///< It will be called for instructions marked with #CF_JUMP. + ///< \param si (switch_info_t *), out + ///< \param insn (const ::insn_t *) instruction possibly belonging to a switch + ///< \retval 1 switch is found, 'si' is filled + ///< \retval -1 no switch found + ///< \retval 0 not implemented + + ev_calc_switch_cases, ///< Calculate case values and targets for a custom jump table. + ///< \param casevec (::casevec_t *) vector of case values (may be NULL) + ///< \param targets (::eavec_t *) corresponding target addresses (my be NULL) + ///< \param insn_ea (::ea_t) address of the 'indirect jump' instruction + ///< \param si (::switch_info_t *) switch information + ///< \retval 1 ok + ///< \retval <=0 failed + + ev_create_switch_xrefs, ///< Create xrefs for a custom jump table. + ///< \param jumpea (::ea_t) address of the jump insn + ///< \param si (const ::switch_info_t *) switch information + ///< \return must return 1 + ///< Must be implemented if module uses custom jump tables, \ref SWI_CUSTOM + + ev_is_align_insn, ///< Is the instruction created only for alignment purposes?. + ///< Do not directly call this function, use ::is_align_insn() + ///< \param ea (ea_t) - instruction address + ///< \retval number of bytes in the instruction + + ev_is_alloca_probe, ///< Does the function at 'ea' behave as __alloca_probe? + ///< \param ea (::ea_t) + ///< \retval 1 yes + ///< \retval 0 no + + ev_delay_slot_insn, ///< Get delay slot instruction + ///< \param ea (::ea_t *) in: instruction address in question, + ///< out: (if the answer is positive) + ///< if the delay slot contains valid insn: + ///< the address of the delay slot insn + ///< else: + ///< BADADDR (invalid insn, e.g. a branch) + ///< \param bexec (bool *) execute slot if jumping, + ///< initially set to 'true' + ///< \param fexec (bool *) execute slot if not jumping, + ///< initally set to 'true' + ///< \retval 1 positive answer + ///< \retval <=0 ordinary insn + ///< \note Input EA may point to the instruction with a delay slot or + ///< to the delay slot instruction itself. + + ev_is_sp_based, ///< Check whether the operand is relative to stack pointer or frame pointer + ///< This event is used to determine how to output a stack variable + ///< If not implemented, then all operands are sp based by default. + ///< Implement this event only if some stack references use frame pointer + ///< instead of stack pointer. + ///< \param mode (int *) out, combination of \ref OP_FP_SP + ///< \param insn (const insn_t *) + ///< \param op (const op_t *) + ///< \retval 0 not implemented + ///< \retval 1 ok + + ev_can_have_type, ///< Can the operand have a type as offset, segment, decimal, etc? + ///< (for example, a register AX can't have a type, meaning that the user can't + ///< change its representation. see bytes.hpp for information about types and flags) + ///< \param op (const ::op_t *) + ///< \retval 0 unknown + ///< \retval <0 no + ///< \retval 1 yes + + ev_cmp_operands, ///< Compare instruction operands + ///< \param op1 (const ::op_t*) + ///< \param op2 (const ::op_t*) + ///< \retval 1 equal + ///< \retval -1 not equal + ///< \retval 0 not implemented + + ev_adjust_refinfo, ///< Called from apply_fixup before converting operand to reference. + ///< Can be used for changing the reference info. + ///< (e.g. the PPC module adds REFINFO_NOBASE for some references) + ///< \param ri (refinfo_t *) + ///< \param ea (::ea_t) instruction address + ///< \param n (int) operand number + ///< \param fd (const fixup_data_t *) + ///< \retval <0 do not create an offset + ///< \retval 0 not implemented or refinfo adjusted + + ev_get_operand_string, ///< Request text string for operand (cli, java, ...). + ///< \param buf (qstring *) + ///< \param insn (const ::insn_t*) the instruction + ///< \param opnum (int) operand number, -1 means any string operand + ///< \retval 0 no string (or empty string) + ///< \retval >0 original string length without terminating zero + + ev_get_reg_name, ///< Generate text representation of a register. + ///< Most processor modules do not need to implement this callback. + ///< It is useful only if \ph{reg_names}[reg] does not provide + ///< the correct register name. + ///< \param buf (qstring *) output buffer + ///< \param reg (int) internal register number as defined in the processor module + ///< \param width (size_t) register width in bytes + ///< \param reghi (int) if not -1 then this function will return the register pair + ///< \retval -1 if error + ///< \retval strlen(buf) if success + + ev_str2reg, ///< Convert a register name to a register number. + ///< The register number is the register index in the \ph{reg_names} array + ///< Most processor modules do not need to implement this callback + ///< It is useful only if \ph{reg_names}[reg] does not provide + ///< the correct register names + ///< \param regname (const char *) + ///< \retval register number + 1 + ///< \retval 0 not implemented or could not be decoded + + ev_get_autocmt, ///< Callback: get dynamic auto comment. + ///< Will be called if the autocomments are enabled + ///< and the comment retrieved from ida.int starts with + ///< '$!'. 'insn' contains valid info. + ///< \param buf (qstring *) output buffer + ///< \param insn (const ::insn_t*) the instruction + ///< \retval 1 new comment has been generated + ///< \retval 0 callback has not been handled. + ///< the buffer must not be changed in this case + + ev_get_bg_color, ///< Get item background color. + ///< Plugins can hook this callback to color disassembly lines dynamically + ///< \param color (::bgcolor_t *), out + ///< \param ea (::ea_t) + ///< \retval 0 not implemented + ///< \retval 1 color set + + ev_is_jump_func, ///< Is the function a trivial "jump" function?. + ///< \param pfn (::func_t *) + ///< \param jump_target (::ea_t *) + ///< \param func_pointer (::ea_t *) + ///< \retval <0 no + ///< \retval 0 don't know + ///< \retval 1 yes, see 'jump_target' and 'func_pointer' + + ev_func_bounds, ///< find_func_bounds() finished its work. + ///< The module may fine tune the function bounds + ///< \param possible_return_code (int *), in/out + ///< \param pfn (::func_t *) + ///< \param max_func_end_ea (::ea_t) (from the kernel's point of view) + ///< \retval void + + ev_verify_sp, ///< All function instructions have been analyzed. + ///< Now the processor module can analyze the stack pointer + ///< for the whole function + ///< \param pfn (::func_t *) + ///< \retval 0 ok + ///< \retval <0 bad stack pointer + + ev_verify_noreturn, ///< The kernel wants to set 'noreturn' flags for a function. + ///< \param pfn (::func_t *) + ///< \retval 0: ok. any other value: do not set 'noreturn' flag + + ev_create_func_frame, ///< Create a function frame for a newly created function + ///< Set up frame size, its attributes etc + ///< \param pfn (::func_t *) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_get_frame_retsize, ///< Get size of function return address in bytes + ///< If this event is not implemented, the kernel will assume + ///< - 8 bytes for 64-bit function + ///< - 4 bytes for 32-bit function + ///< - 2 bytes otherwise + ///< \param frsize (int *) frame size (out) + ///< \param pfn (const ::func_t *), can't be NULL + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_get_stkvar_scale_factor, ///< Should stack variable references be multiplied by + ///< a coefficient before being used in the stack frame?. + ///< Currently used by TMS320C55 because the references into + ///< the stack should be multiplied by 2 + ///< \return scaling factor + ///< \retval 0 not implemented + ///< \note #PR_SCALE_STKVARS should be set to use this callback + + ev_demangle_name, ///< Demangle a C++ (or another language) name into a user-readable string. + ///< This event is called by ::demangle_name() + ///< \param res (int32 *) value to return from ::demangle_name() + ///< \param out (::qstring *) output buffer. may be NULL + ///< \param name (const char *) mangled name + ///< \param disable_mask (uint32) flags to inhibit parts of output or compiler info/other (see MNG_) + ///< \param demreq (demreq_type_t) operation to perform + ///< \retval 1 if success + ///< \retval 0 not implemented + ///< \note if you call ::demangle_name() from the handler, protect against recursion! + + // the following 5 events are very low level + // take care of possible recursion + ev_add_cref, ///< A code reference is being created. + ///< \param from (::ea_t) + ///< \param to (::ea_t) + ///< \param type (::cref_t) + ///< \retval <0 cancel cref creation + ///< \retval 0 not implemented or continue + + ev_add_dref, ///< A data reference is being created. + ///< \param from (::ea_t) + ///< \param to (::ea_t) + ///< \param type (::dref_t) + ///< \retval <0 cancel dref creation + ///< \retval 0 not implemented or continue + + ev_del_cref, ///< A code reference is being deleted. + ///< \param from (::ea_t) + ///< \param to (::ea_t) + ///< \param expand (bool) + ///< \retval <0 cancel cref deletion + ///< \retval 0 not implemented or continue + + ev_del_dref, ///< A data reference is being deleted. + ///< \param from (::ea_t) + ///< \param to (::ea_t) + ///< \retval <0 cancel dref deletion + ///< \retval 0 not implemented or continue + + ev_coagulate_dref, ///< Data reference is being analyzed. + ///< plugin may correct 'code_ea' (e.g. for thumb mode refs, we clear the last bit) + ///< \param from (::ea_t) + ///< \param to (::ea_t) + ///< \param may_define (bool) + ///< \param code_ea (::ea_t *) + ///< \retval <0 failed dref analysis, >0 done dref analysis + ///< \retval 0 not implemented or continue + + ev_may_show_sreg, ///< The kernel wants to display the segment registers + ///< in the messages window. + ///< \param current_ea (::ea_t) + ///< \retval <0 if the kernel should not show the segment registers. + ///< (assuming that the module has done it) + ///< \retval 0 not implemented + + ev_loader_elf_machine, ///< ELF loader machine type checkpoint. + ///< A plugin check of the 'machine_type'. If it is the desired one, + ///< the the plugin fills 'p_procname' with the processor name + ///< (one of the names present in \ph{psnames}). + ///< 'p_pd' is used to handle relocations, otherwise can be left untouched. + ///< This event occurs for each newly loaded ELF file + ///< \param li (linput_t *) + ///< \param machine_type (int) + ///< \param p_procname (const char **) + ///< \param p_pd (proc_def_t **) (see ldr\elf.h) + ///< \retval e_machine value (if it is different from the + ///< original e_machine value, procname and 'p_pd' will be ignored + ///< and the new value will be used) + + ev_auto_queue_empty, ///< One analysis queue is empty. + ///< \param type (::atype_t) + ///< \retval void + ///< see also \ref idb_event::auto_empty_finally + + ev_validate_flirt_func, ///< Flirt has recognized a library function. + ///< This callback can be used by a plugin or proc module + ///< to intercept it and validate such a function. + ///< \param start_ea (::ea_t) + ///< \param funcname (const char *) + ///< \retval -1 do not create a function, + ///< \retval 0 function is validated + + ev_adjust_libfunc_ea, ///< Called when a signature module has been matched against + ///< bytes in the database. This is used to compute the + ///< offset at which a particular module's libfunc should + ///< be applied. + ///< \param sig (const idasgn_t *) + ///< \param libfun (const libfunc_t *) + ///< \param ea (::ea_t *) \note 'ea' initially contains the ea_t of the + ///< start of the pattern match + ///< \retval 1 the ea_t pointed to by the third argument was modified. + ///< \retval <=0 not modified. use default algorithm. + + ev_assemble, ///< Assemble an instruction. + ///< (display a warning if an error is found). + ///< \param bin (::uchar *) pointer to output opcode buffer + ///< \param ea (::ea_t) linear address of instruction + ///< \param cs (::ea_t) cs of instruction + ///< \param ip (::ea_t) ip of instruction + ///< \param use32 (bool) is 32bit segment? + ///< \param line (const char *) line to assemble + ///< \return size of the instruction in bytes + + ev_extract_address, ///< Extract address from a string. + ///< \param out_ea (ea_t *), out + ///< \param screen_ea (ea_t) + ///< \param string (const char *) + ///< \param position (size_t) + ///< \retval 1 ok + ///< \retval 0 kernel should use the standard algorithm + ///< \retval -1 error + + ev_realcvt, ///< Floating point -> IEEE conversion + ///< \param m (void *) ptr to processor-specific floating point value + ///< \param e (fpvalue_t *) IDA representation of a floating point value + ///< \param swt (uint16) operation (see realcvt() in ieee.h) + ///< \retval 0 not implemented + ///< \retval 1 ok + ///< \retval \ref REAL_ERROR_ on error + + ev_gen_asm_or_lst, ///< Callback: generating asm or lst file. + ///< The kernel calls this callback twice, at the beginning + ///< and at the end of listing generation. The processor + ///< module can intercept this event and adjust its output + ///< \param starting (bool) beginning listing generation + ///< \param fp (FILE *) output file + ///< \param is_asm (bool) true:assembler, false:listing + ///< \param flags (int) flags passed to gen_file() + ///< \param outline (html_line_cb_t **) ptr to ptr to outline callback. + ///< if this callback is defined for this code, it will be + ///< used by the kernel to output the generated lines + ///< \retval void + + ev_gen_map_file, ///< Generate map file. If not implemented + ///< the kernel itself will create the map file. + ///< \param nlines (int *) number of lines in map file (-1 means write error) + ///< \param fp (FILE *) output file + ///< \retval 0 not implemented + ///< \retval 1 ok + ///< \retval -1 write error + + ev_create_flat_group, ///< Create special segment representing the flat group. + ///< \param image_base (::ea_t) + ///< \param bitness (int) + ///< \param dataseg_sel (::sel_t) + ///< return value is ignored + + ev_getreg, ///< IBM PC only internal request, + ///< should never be used for other purpose + ///< Get register value by internal index + ///< \param regval (uval_t *), out + ///< \param regnum (int) + ///< \retval 1 ok + ///< \retval 0 not implemented + ///< \retval -1 failed (undefined value or bad regnum) + + ev_analyze_prolog, ///< Analyzes function prolog, epilog, and updates + ///< purge, and function attributes + ///< \param ea (::ea_t) start of function + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_calc_spdelta, ///< Calculate amount of change to sp for the given insn. + ///< This event is required to decompile code snippets. + ///< \param spdelta (::sval_t *) + ///< \param insn (const ::insn_t *) + ///< \retval 1 ok + ///< \retval 0 not implemented + + ev_calcrel, ///< Reserved + ev_find_reg_value, ///< Find register value via a register tracker. + ///< The returned value in 'out' is valid + ///< before executing the instruction. + ///< \param out (uval_t *) pointer to the found value + ///< \param pinsn (const ::insn_t *) instruction + ///< \param reg (int) register index + ///< \retval 1 if implemented, and value was found + ///< \retval 0 not implemented, -1 decoding failed, or no value found + + ev_find_op_value, ///< Find operand value via a register tracker. + ///< The returned value in 'out' is valid + ///< before executing the instruction. + ///< \param out (uval_t *) pointer to the found value + ///< \param pinsn (const ::insn_t *) instruction + ///< \param opn (int) operand index + ///< \retval 1 if implemented, and value was found + ///< \retval 0 not implemented, -1 decoding failed, or no value found + + ev_replaying_undo, ///< Replaying an undo/redo buffer + ///< \param action_name (const char *) action that we perform undo/redo for. may be NULL for intermediary buffers. + ///< \param vec (const undo_records_t *) + ///< \param is_undo (bool) true if performing undo, false if performing redo + ///< This event may be generated multiple times per undo/redo + ev_ending_undo, ///< Ended undoing/redoing an action + ///< \param action_name (const char *) action that we finished undoing/redoing. is not NULL. + ///< \param is_undo (bool) true if performing undo, false if performing redo + + ev_set_code16_mode, ///< Some processors have ISA 16-bit mode + ///< e.g. ARM Thumb mode, PPC VLE, MIPS16 + ///< Set ISA 16-bit mode + ///< \param ea (ea_t) address to set new ISA mode + ///< \param code16 (bool) true for 16-bit mode, false for 32-bit mode + ev_get_code16_mode, ///< Get ISA 16-bit mode + ///< \param ea (ea_t) address to get the ISA mode + ///< \retval 1 16-bit mode + ///< \retval 0 not implemented or 32-bit mode + + ev_get_procmod, ///< Get pointer to the processor module object. + ///< All processor modules must implement this. + ///< The pointer is returned as size_t. + + ev_asm_installed, ///< After setting a new assembler + ///< \param asmnum (int) + ///< See also ev_newasm + + ev_get_reg_accesses, ///< Get info about the registers that are used/changed by an instruction. + ///< \param accvec (::reg_accesses_t*) out: info about accessed registers + ///< \param insn (const ::insn_t *) instruction in question + ///< \param flags (int) reserved, must be 0 + ///< \retval -1 if accvec is nullptr + ///< \retval 1 found the requested access (and filled accvec) + ///< \retval 0 not implemented + + ev_is_control_flow_guard, ///< Detect if an instruction is a "thunk call" to a flow guard function (equivalent to call reg/return/nop) + ///< \param p_reg (int *) indirect register number, may be -1 + ///< \param insn (const ::insn_t *) call/jump instruction + ///< \retval -1 no thunk detected + ///< \retval 1 indirect call + ///< \retval 2 security check routine call (NOP) + ///< \retval 3 return thunk + ///< \retval 0 not implemented + + ev_broadcast, ///< Broadcast call + ///< \param magic (::int64) a magic number + ///< Other parameters and the return value depend on the magic + + ev_create_merge_handlers, ///< Create merge handlers, if needed + ///< \param md (::merge_data_t *) + ///< This event is generated immediately after + ///< opening idbs. + ///< \return must be 0 + + ev_last_cb_before_debugger, ///< START OF DEBUGGER CALLBACKS + + ev_next_exec_insn = 1000, ///< Get next address to be executed + ///< This function must return the next address to be executed. + ///< If the instruction following the current one is executed, then it must return #BADADDR + ///< Usually the instructions to consider are: jumps, branches, calls, returns. + ///< This function is essential if the 'single step' is not supported in hardware. + ///< \param target (::ea_t *), out: pointer to the answer + ///< \param ea (::ea_t) instruction address + ///< \param tid (int) current therad id + ///< \param getreg (::processor_t::regval_getter_t *) function to get register values + ///< \param regvalues (const ::regval_t *) register values array + ///< \retval 0 unimplemented + ///< \retval 1 implemented + + ev_calc_step_over, ///< Calculate the address of the instruction which will be + ///< executed after "step over". The kernel will put a breakpoint there. + ///< If the step over is equal to step into or we cannot calculate + ///< the address, return #BADADDR. + ///< \param target (::ea_t *) pointer to the answer + ///< \param ip (::ea_t) instruction address + ///< \retval 0 unimplemented + ///< \retval 1 implemented + + ev_calc_next_eas, ///< Calculate list of addresses the instruction in 'insn' + ///< may pass control to. + ///< This callback is required for source level debugging. + ///< \param res (::eavec_t *), out: array for the results. + ///< \param insn (const ::insn_t*) the instruction + ///< \param over (bool) calculate for step over (ignore call targets) + ///< \retval <0 incalculable (indirect jumps, for example) + ///< \retval >=0 number of addresses of called functions in the array. + ///< They must be put at the beginning of the array (0 if over=true) + + ev_get_macro_insn_head, ///< Calculate the start of a macro instruction. + ///< This notification is called if IP points to the middle of an instruction + ///< \param head (::ea_t *), out: answer, #BADADDR means normal instruction + ///< \param ip (::ea_t) instruction address + ///< \retval 0 unimplemented + ///< \retval 1 implemented + + ev_get_dbr_opnum, ///< Get the number of the operand to be displayed in the + ///< debugger reference view (text mode). + ///< \param opnum (int *) operand number (out, -1 means no such operand) + ///< \param insn (const ::insn_t*) the instruction + ///< \retval 0 unimplemented + ///< \retval 1 implemented + + ev_insn_reads_tbit, ///< Check if insn will read the TF bit. + ///< \param insn (const ::insn_t*) the instruction + ///< \param getreg (::processor_t::regval_getter_t *) function to get register values + ///< \param regvalues (const ::regval_t *) register values array + ///< \retval 2 yes, will generate 'step' exception + ///< \retval 1 yes, will store the TF bit in memory + ///< \retval 0 no + + ev_clean_tbit, ///< Clear the TF bit after an insn like pushf stored it in memory. + ///< \param ea (::ea_t) instruction address + ///< \param getreg (::processor_t::regval_getter_t *) function to get register values + ///< \param regvalues (const ::regval_t *) register values array + ///< \retval 1 ok + ///< \retval 0 failed + + ev_get_idd_opinfo, ///< Get operand information. + ///< This callback is used to calculate the operand + ///< value for double clicking on it, hints, etc. + ///< \param opinf (::idd_opinfo_t *) the output buffer + ///< \param ea (::ea_t) instruction address + ///< \param n (int) operand number + ///< \param thread_id (int) current thread id + ///< \param getreg (::processor_t::regval_getter_t *) function to get register values + ///< \param regvalues (const ::regval_t *) register values array + ///< \retval 1 ok + ///< \retval 0 failed + + ev_get_reg_info, ///< Get register information by its name. + ///< example: "ah" returns: + ///< - main_regname="eax" + ///< - bitrange_t = { offset==8, nbits==8 } + ///< + ///< This callback may be unimplemented if the register + ///< names are all present in \ph{reg_names} and they all have + ///< the same size + ///< \param main_regname (const char **), out + ///< \param bitrange (::bitrange_t *), out: position and size of the value within 'main_regname' (empty bitrange == whole register) + ///< \param regname (const char *) + ///< \retval 1 ok + ///< \retval -1 failed (not found) + ///< \retval 0 unimplemented + + ev_update_call_stack, ///< Calculate the call stack trace for the given thread. + ///< This callback is invoked when the process is suspended and should fill + ///< the 'trace' object with the information about the current call stack. + ///< Note that this callback is NOT invoked if the current debugger backend + ///< implements stack tracing via debugger_t::event_t::ev_update_call_stack. + ///< The debugger-specific algorithm takes priority. Implementing this callback + ///< in the processor module is useful when multiple debugging platforms follow + ///< similar patterns, and thus the same processor-specific algorithm can be + ///< used for different platforms. + ///< \param stack (::call_stack_t *) result + ///< \param tid (int) thread id + ///< \param getreg (::processor_t::regval_getter_t *) function to get register values + ///< \param regvalues (const ::regval_t *) register values array + ///< \retval 1 ok + ///< \retval -1 failed + ///< \retval 0 unimplemented + + // END OF DEBUGGER CALLBACKS + + // START OF TYPEINFO CALLBACKS TODO: get this into doxygen output + // The codes below will be called only if #PR_TYPEINFO is set. + // Please note that some codes are optional but the more codes + // are implemented, the better the analysis. + + ev_last_cb_before_type_callbacks, + + ev_setup_til = 2000, ///< Setup default type libraries. (called after loading + ///< a new file into the database). + ///< The processor module may load tils, setup memory + ///< model and perform other actions required to set up + ///< the type system. + ///< This is an optional callback. + ///< \param none + ///< \retval void + + ev_get_abi_info, ///< Get all possible ABI names and optional extensions for given compiler + ///< abiname/option is a string entirely consisting of letters, digits and underscore + ///< \param abi_names (qstrvec_t *) - all possible ABis each in form abiname-opt1-opt2-... + ///< \param abi_opts (qstrvec_t *) - array of all possible options in form "opt:description" or opt:hint-line#description + ///< \param comp (comp_t) - compiler ID + ///< \retval 0 not implemented + ///< \retval 1 ok + + ev_max_ptr_size, ///< Get maximal size of a pointer in bytes. + ///< \param none + ///< \return max possible size of a pointer + + ev_get_default_enum_size, ///< Get default enum size. Not generated anymore. + ///< inf_get_cc_size_e() is used instead + + ev_get_cc_regs, ///< Get register allocation convention for given calling convention + ///< \param regs (::callregs_t *), out + ///< \param cc (::cm_t) + ///< \retval 1 + ///< \retval 0 not implemented + + ev_get_stkarg_offset, ///< Get offset from SP to the first stack argument. + ///< For example: pc: 0, hppa: -0x34, ppc: 0x38 + ///< \param none + ///< \return the offset (usually 0) + + ev_shadow_args_size, ///< Get size of shadow args in bytes. + ///< \param[out] shadow_args_size (int *) + ///< \param pfn (::func_t *) (may be NULL) + ///< \retval 1 if filled *shadow_args_size + ///< \retval 0 not implemented + + ev_get_simd_types, ///< Get SIMD-related types according to given attributes ant/or argument location + ///< \param out (::simd_info_vec_t *) + ///< \param simd_attrs (const ::simd_info_t *), may be NULL + ///< \param argloc (const ::argloc_t *), may be NULL + ///< \param create_tifs (bool) return valid tinfo_t objects, create if neccessary + ///< \retval number of found types + ///< \retval -1 error + ///< If name==NULL, initialize all SIMD types + + ev_calc_cdecl_purged_bytes, + ///< Calculate number of purged bytes after call. + ///< \param ea (::ea_t) address of the call instruction + ///< \return number of purged bytes (usually add sp, N) + + ev_calc_purged_bytes, ///< Calculate number of purged bytes by the given function type. + ///< \param[out] p_purged_bytes (int *) ptr to output + ///< \param fti (const ::func_type_data_t *) func type details + ///< \retval 1 + ///< \retval 0 not implemented + + ev_calc_retloc, ///< Calculate return value location. + ///< \param[out] retloc (::argloc_t *) + ///< \param rettype (const tinfo_t *) + ///< \param cc (::cm_t) + ///< \retval 0 not implemented + ///< \retval 1 ok, + ///< \retval -1 error + + ev_calc_arglocs, ///< Calculate function argument locations. + ///< This callback should fill retloc, all arglocs, and stkargs. + ///< This callback is never called for ::CM_CC_SPECIAL functions. + ///< \param fti (::func_type_data_t *) points to the func type info + ///< \retval 0 not implemented + ///< \retval 1 ok + ///< \retval -1 error + + ev_calc_varglocs, ///< Calculate locations of the arguments that correspond to '...'. + ///< \param ftd (::func_type_data_t *), inout: info about all arguments (including varargs) + ///< \param[out] aux_regs (::regobjs_t *) buffer for hidden register arguments, may be NULL + ///< \param[out] aux_stkargs (::relobj_t *) buffer for hidden stack arguments, may be NULL + ///< \param nfixed (int) number of fixed arguments + ///< \retval 0 not implemented + ///< \retval 1 ok + ///< \retval -1 error + ///< On some platforms variadic calls require + ///< passing additional information: for example, + ///< number of floating variadic arguments must + ///< be passed in rax on gcc-x64. The locations + ///< and values that constitute this additional + ///< information are returned in the buffers + ///< pointed by aux_regs and aux_stkargs + + ev_adjust_argloc, ///< Adjust argloc according to its type/size + ///< and platform endianess + ///< \param argloc (argloc_t *), inout + ///< \param type (const tinfo_t *), may be NULL + ///< NULL means primitive type of given size + ///< \param size (int) + ///< 'size' makes no sense if type != NULL + ///< (type->get_size() should be used instead) + ///< \retval 0 not implemented + ///< \retval 1 ok + ///< \retval -1 error + + ev_lower_func_type, ///< Get function arguments which should be converted to pointers when lowering function prototype. + ///< The processor module can also modify 'fti' in order to make non-standard conversion + ///< of some arguments. + ///< \param argnums (intvec_t *), out - numbers of arguments to be converted to pointers in acsending order + ///< \param fti (::func_type_data_t *), inout func type details + ///< (special values -1/-2 for return value - position of hidden 'retstr' argument: -1 - at the beginning, -2 - at the end) + ///< \retval 0 not implemented + ///< \retval 1 argnums was filled + ///< \retval 2 argnums was filled and made substantial changes to fti + + ev_equal_reglocs, ///< Are 2 register arglocs the same?. + ///< We need this callback for the pc module. + ///< \param a1 (::argloc_t *) + ///< \param a2 (::argloc_t *) + ///< \retval 1 yes + ///< \retval -1 no + ///< \retval 0 not implemented + + ev_use_stkarg_type, ///< Use information about a stack argument. + ///< \param ea (::ea_t) address of the push instruction which + ///< pushes the function argument into the stack + ///< \param arg (const ::funcarg_t *) argument info + ///< \retval 1 ok + ///< \retval <=0 failed, the kernel will create a comment with the + ///< argument name or type for the instruction + + ev_use_regarg_type, ///< Use information about register argument. + ///< \param[out] idx (int *) pointer to the returned value, may contain: + ///< - idx of the used argument, if the argument is defined + ///< in the current instruction, a comment will be applied by the kernel + ///< - idx | #REG_SPOIL - argument is spoiled by the instruction + ///< - -1 if the instruction doesn't change any registers + ///< - -2 if the instruction spoils all registers + ///< \param ea (::ea_t) address of the instruction + ///< \param rargs (const ::funcargvec_t *) vector of register arguments + ///< (including regs extracted from scattered arguments) + ///< \retval 1 + ///< \retval 0 not implemented + + ev_use_arg_types, ///< Use information about callee arguments. + ///< \param ea (::ea_t) address of the call instruction + ///< \param fti (::func_type_data_t *) info about function type + ///< \param rargs (::funcargvec_t *) array of register arguments + ///< \retval 1 (and removes handled arguments from fti and rargs) + ///< \retval 0 not implemented + + ev_arg_addrs_ready, ///< Argument address info is ready. + ///< \param caller (::ea_t) + ///< \param n (int) number of formal arguments + ///< \param tif (tinfo_t *) call prototype + ///< \param addrs (::ea_t *) argument intilization addresses + ///< \retval <0 do not save into idb; other values mean "ok to save" + + ev_decorate_name, ///< Decorate/undecorate a C symbol name. + ///< \param outbuf (::qstring *) output buffer + ///< \param name (const char *) name of symbol + ///< \param mangle (bool) true-mangle, false-unmangle + ///< \param cc (::cm_t) calling convention + ///< \param type (const ::tinfo_t *) name type (NULL-unknown) + ///< \retval 1 if success + ///< \retval 0 not implemented or failed + + ev_arch_changed, ///< The loader is done parsing arch-related + ///< information, which the processor module + ///< might want to use to finish its + ///< initialization. + ///< \retval 1 if success + ///< \retval 0 not implemented or failed + + ev_last_cb_before_loader, + + // END OF TYPEINFO CALLBACKS + + ev_loader=3000, ///< This code and higher ones are reserved + ///< for the loaders. + ///< The arguments and the return values are + ///< defined by the loaders + }; + + /// Event notification handler + hook_cb_t *_notify; + static ssize_t notify(event_t event_code, ...) + { + va_list va; + va_start(va, event_code); + ssize_t code = invoke_callbacks(HT_IDP, event_code, va); + va_end(va); + return code; + } + + // Notification helpers, should be used instead of direct ph.notify(...) calls + inline static ssize_t init(const char *idp_modname); + inline static ssize_t term(); + inline static ssize_t newprc(int pnum, bool keep_cfg); + inline static ssize_t newasm(int asmnum); + inline static ssize_t asm_installed(int asmnum); + inline static ssize_t newfile(const char *fname); + inline static ssize_t oldfile(const char *fname); + inline static ssize_t newbinary(const char *filename, qoff64_t fileoff, ea_t basepara, ea_t binoff, uint64 nbytes); + inline static ssize_t endbinary(bool ok); + inline static ssize_t creating_segm(segment_t *seg); + inline static ssize_t assemble(uchar *_bin, ea_t ea, ea_t cs, ea_t ip, bool _use32, const char *line); + inline static ssize_t ana_insn(insn_t *out); + inline static ssize_t emu_insn(const insn_t &insn); + inline static ssize_t out_header(outctx_t &ctx); + inline static ssize_t out_footer(outctx_t &ctx); + inline static ssize_t out_segstart(outctx_t &ctx, segment_t *seg); + inline static ssize_t out_segend(outctx_t &ctx, segment_t *seg); + inline static ssize_t out_assumes(outctx_t &ctx); + inline static ssize_t out_insn(outctx_t &ctx); + inline static ssize_t out_mnem(outctx_t &ctx); + inline static ssize_t out_operand(outctx_t &ctx, const op_t &op); + inline static ssize_t out_data(outctx_t &ctx, bool analyze_only); + inline static ssize_t out_label(outctx_t &ctx, const char *colored_name); + inline static ssize_t out_special_item(outctx_t &ctx, uchar segtype); + inline static ssize_t gen_stkvar_def(outctx_t &ctx, const class member_t *mptr, sval_t v); + inline static ssize_t gen_regvar_def(outctx_t &ctx, regvar_t *v); + inline static ssize_t gen_src_file_lnnum(outctx_t &ctx, const char *file, size_t lnnum); + inline static ssize_t rename(ea_t ea, const char *new_name, int flags); + inline static ssize_t may_show_sreg(ea_t current_ea); + inline static ssize_t coagulate(ea_t start_ea); + inline static void auto_queue_empty(/*atype_t*/ int type); + + inline static ssize_t func_bounds(int *possible_return_code, func_t *pfn, ea_t max_func_end_ea); + inline static ssize_t may_be_func(const insn_t &insn, int state); + inline static ssize_t is_sane_insn(const insn_t &insn, int no_crefs); + inline static ssize_t cmp_operands(const op_t &op1, const op_t &op2); + inline static ssize_t is_jump_func(func_t *pfn, ea_t *jump_target, ea_t *func_pointer); + inline static ssize_t is_basic_block_end(const insn_t &insn, bool call_insn_stops_block); + inline static ssize_t getreg(uval_t *rv, int regnum); + inline static ssize_t undefine(ea_t ea); + inline static ssize_t moving_segm(segment_t *seg, ea_t to, int flags); + inline static ssize_t is_sp_based(const insn_t &insn, const op_t &x); + inline static ssize_t is_far_jump(int icode); + inline static ssize_t is_call_insn(const insn_t &insn); + inline static ssize_t is_ret_insn(const insn_t &insn, bool strict); + inline static ssize_t is_align_insn(ea_t ea); + inline static ssize_t can_have_type(const op_t &op); + inline static ssize_t get_stkvar_scale_factor(); + inline static ssize_t demangle_name(int32 *res, qstring *out, const char *name, uint32 disable_mask, /*demreq_type_t*/ int demreq); + inline static ssize_t create_flat_group(ea_t image_base, int bitness, sel_t dataseg_sel); + inline static ssize_t is_alloca_probe(ea_t ea); + inline static ssize_t get_reg_name(qstring *buf, int reg, size_t width, int reghi); + inline static ssize_t gen_asm_or_lst(bool starting, FILE *fp, bool is_asm, int flags, /*html_line_cb_t ** */ void *outline); + inline static ssize_t gen_map_file(int *nlines, FILE *fp); + inline static ssize_t get_autocmt(qstring *buf, const insn_t &insn); + inline static ssize_t loader_elf_machine(linput_t *li, int machine_type, const char **p_procname, proc_def_t **p_pd); + inline static ssize_t is_indirect_jump(const insn_t &insn); + inline static ssize_t verify_noreturn(func_t *pfn); + inline static ssize_t verify_sp(func_t *pfn); + inline static ssize_t create_func_frame(func_t *pfn); + inline static ssize_t get_frame_retsize(int *retsize, const func_t *pfn); + inline static ssize_t analyze_prolog(ea_t fct_ea); + inline static ssize_t calc_spdelta(sval_t *spdelta, const insn_t &ins); + inline static ssize_t calcrel(bytevec_t *out_relbits, size_t *out_consumed, ea_t ea); + inline static ssize_t get_reg_accesses(reg_accesses_t *accvec, const insn_t &insn, int flags); + inline static ssize_t is_control_flow_guard(int *p_reg, const insn_t *insn); + inline static ssize_t find_reg_value(uval_t *out, const insn_t &insn, int reg); + inline static ssize_t find_op_value(uval_t *out, const insn_t &insn, int op); + inline static ssize_t treat_hindering_item(ea_t hindering_item_ea, flags_t new_item_flags, ea_t new_item_ea, asize_t new_item_length); + inline static ssize_t extract_address(ea_t *out_ea, ea_t screen_ea, const char *string, size_t x); + inline static ssize_t str2reg(const char *regname); + inline static ssize_t is_switch(switch_info_t *si, const insn_t &insn); + inline static ssize_t create_switch_xrefs(ea_t jumpea, const switch_info_t &si); + inline static ssize_t calc_switch_cases(/*casevec_t * */void *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si); + inline static ssize_t get_bg_color(bgcolor_t *color, ea_t ea); + inline static ssize_t validate_flirt_func(ea_t start_ea, const char *funcname); + inline static ssize_t get_operand_string(qstring *buf, const insn_t &insn, int opnum); + inline static ssize_t add_cref(ea_t from, ea_t to, cref_t type); + inline static ssize_t add_dref(ea_t from, ea_t to, dref_t type); + inline static ssize_t del_cref(ea_t from, ea_t to, bool expand); + inline static ssize_t del_dref(ea_t from, ea_t to); + inline static ssize_t coagulate_dref(ea_t from, ea_t to, bool may_define, ea_t *code_ea); + inline static const char *set_idp_options(const char *keyword, int vtype, const void *value, bool idb_loaded = true); + inline static ssize_t set_proc_options(const char *options, int confidence); + inline static ssize_t adjust_libfunc_ea(const idasgn_t &sig, const libfunc_t &libfun, ea_t *ea); + inline static fpvalue_error_t realcvt(void *m, fpvalue_t *e, uint16 swt); + inline bool delay_slot_insn(ea_t *ea, bool *bexec, bool *fexec); + inline static ssize_t adjust_refinfo(refinfo_t *ri, ea_t ea, int n, const fixup_data_t &fd); + inline static ssize_t is_cond_insn(const insn_t &insn); + inline static ssize_t set_code16_mode(ea_t ea, bool code16 = true); + inline static bool get_code16_mode(ea_t ea); + inline static ssize_t next_exec_insn(ea_t *target, ea_t ea, int tid, regval_getter_t *_getreg, const regval_t ®values); + inline static ssize_t calc_step_over(ea_t *target, ea_t ip); + inline static ssize_t get_macro_insn_head(ea_t *head, ea_t ip); + inline static ssize_t get_dbr_opnum(int *opnum, const insn_t &insn); + inline static ssize_t insn_reads_tbit(const insn_t &insn, regval_getter_t *_getreg, const regval_t ®values); + inline static ssize_t get_idd_opinfo(idd_opinfo_t *opinf, ea_t ea, int n, int thread_id, regval_getter_t *_getreg, const regval_t ®values); + inline static ssize_t calc_next_eas(eavec_t *res, const insn_t &insn, bool over); + inline static ssize_t clean_tbit(ea_t ea, regval_getter_t *_getreg, const regval_t ®values); + inline static const char *get_reg_info(const char *regname, bitrange_t *bitrange); + inline static ssize_t update_call_stack(call_stack_t *stack, int tid, regval_getter_t *_getreg, const regval_t ®values); + inline static ssize_t setup_til(); + inline static ssize_t max_ptr_size(); + inline static ssize_t calc_cdecl_purged_bytes(ea_t ea); + inline static ssize_t equal_reglocs(const argloc_t &a1, const argloc_t &a2); + inline static ssize_t decorate_name(qstring *outbuf, const char *name, bool mangle, cm_t cc, const tinfo_t &type); + inline static ssize_t calc_retloc(argloc_t *retloc, const tinfo_t &rettype, cm_t cc); + inline static ssize_t calc_varglocs(func_type_data_t *ftd, regobjs_t *regs, relobj_t *stkargs, int nfixed); + inline static ssize_t calc_arglocs(func_type_data_t *fti); + inline static ssize_t use_stkarg_type(ea_t ea, const funcarg_t &arg); + inline static ssize_t use_regarg_type(int *idx, ea_t ea, /*const funcargvec_t * */void *rargs); + inline static ssize_t use_arg_types(ea_t ea, func_type_data_t *fti, /*funcargvec_t * */void *rargs); + inline static ssize_t calc_purged_bytes(int *p_purged_bytes, const func_type_data_t &fti); + inline static ssize_t shadow_args_size(int *shadow_size, func_t *pfn); + inline static ssize_t get_cc_regs(callregs_t *regs, cm_t cc); + inline static ssize_t get_simd_types(/*simd_info_vec_t * */void *out, const simd_info_t *simd_attrs, const argloc_t *argloc, bool create_tifs); + inline static ssize_t arg_addrs_ready(ea_t caller, int n, const tinfo_t &tif, ea_t *addrs); + inline static ssize_t adjust_argloc(argloc_t *argloc, const tinfo_t *type, int size); + inline static ssize_t lower_func_type(intvec_t *argnums, func_type_data_t *fti); + inline static ssize_t get_abi_info(qstrvec_t *abi_names, qstrvec_t *abi_opts, comp_t comp); + inline static ssize_t arch_changed(); + inline static ssize_t create_merge_handlers(merge_data_t *md); +/// \defgroup OP_FP_SP SP/FP operand flags +/// Return values for processor_t::is_sp_based() +//@{ +#define OP_FP_BASED 0x00000000 ///< operand is FP based +#define OP_SP_BASED 0x00000001 ///< operand is SP based +#define OP_SP_ADD 0x00000000 ///< operand value is added to the pointer +#define OP_SP_SUB 0x00000002 ///< operand value is subtracted from the pointer +//@} + + /// Get the stack variable scaling factor. + /// Useful for processors who refer to the stack with implicit scaling factor. + /// TMS320C55 for example: SP(#1) really refers to (SP+2) + int get_stkvar_scale(void) + { + if ( (flag & PR_SCALE_STKVARS) == 0 ) + return 1; + int scale = notify(ev_get_stkvar_scale_factor); + if ( scale == 0 ) + error("Request ph.get_stkvar_scale_factor should be implemented"); + else if ( scale <= 0 ) + error("Invalid return code from ph.get_stkvar_scale_factor request"); + return scale; + } + + // Processor register information: + const char *const *reg_names; ///< array of register names + int32 regs_num; ///< number of registers + + /// \name Segment registers + /// Segment register information (use virtual CS and DS registers if your + /// processor doesn't have segment registers): + //@{ + int32 reg_first_sreg; ///< number of first segment register + int32 reg_last_sreg; ///< number of last segment register + int32 segreg_size; ///< size of a segment register in bytes + //@} + + /// \name Virtual segment registers + /// If your processor doesn't have segment registers, + /// you should define 2 virtual segment registers for CS and DS. + /// Let's call them rVcs and rVds. + //@{ + int32 reg_code_sreg; ///< number of CS register + int32 reg_data_sreg; ///< number of DS register + //@} + + + /// \name Empirics + //@{ + const bytes_t *codestart; ///< Array of typical code start sequences. + ///< This array is used when a new file + ///< is loaded to find the beginnings of code + ///< sequences. + ///< This array is terminated with + ///< a zero length item. + const bytes_t *retcodes; ///< Array of 'return' instruction opcodes. + ///< This array is used to determine + ///< form of autogenerated locret_... + ///< labels. + ///< The last item of it should be { 0, NULL } + ///< This array may be NULL + ///< Better way of handling return instructions + ///< is to define the \idpcode{is_ret_insn} callback in + ///< the notify() function + //@} + + /// \name Instruction set + //@{ + int32 instruc_start; ///< icode of the first instruction + int32 instruc_end; ///< icode of the last instruction + 1 + + /// Does the given value specify a valid instruction for this instruction set?. + /// See #instruc_start and #instruc_end + bool is_canon_insn(uint16 itype) const { return itype >= instruc_start && itype < instruc_end; } + + const instruc_t *instruc; ///< Array of instructions + //@} + + /// Size of long double (tbyte) for this processor + /// (meaningful only if \ash{a_tbyte} != NULL) + size_t tbyte_size; + + /// Number of digits in floating numbers after the decimal point. + /// If an element of this array equals 0, then the corresponding + /// floating point data is not used for the processor. + /// This array is used to align numbers in the output. + /// - real_width[0] - number of digits for short floats (only PDP-11 has them) + /// - real_width[1] - number of digits for "float" + /// - real_width[2] - number of digits for "double" + /// - real_width[3] - number of digits for "long double" + /// + /// Example: IBM PC module has { 0,7,15,19 } + char real_width[4]; + + /// Icode of return instruction. It is ok to give any of possible return instructions + int32 icode_return; + + /// Reserved, currently equals to NULL + void *unused_slot; + + inline void ensure_processor(void); + inline size_t sizeof_ldbl() const; + inline ssize_t get_stkarg_offset() const; + inline bool is_funcarg_off(const func_t *pfn, uval_t frameoff) const; + inline sval_t lvar_off(const func_t *pfn, uval_t frameoff) const; + inline bool is_lumina_usable() const; +}; +#ifndef __X86__ +CASSERT(sizeof(processor_t) == 144); +#else +CASSERT(sizeof(processor_t) == 104); +#endif + +// The following two structures contain information about the current +// processor and assembler. + +//-V:ph:688 local variable ph with the same name +#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_PH__) +idaman processor_t ida_export_data ph; ///< current processor +idaman asm_t ida_export_data ash; ///< current assembler +#endif + +idaman processor_t *ida_export get_ph(); +#define PH (*get_ph()) +idaman asm_t *ida_export get_ash(); +#define ASH (*get_ash()) + +/// Hex-Rays decompiler dispatcher. +/// All interaction with the decompiler is carried out by the intermediary of this dispatcher. +typedef void *hexdsp_t(int code, ...); +idaman hexdsp_t *ida_export get_hexdsp(); +#define HEXDSP get_hexdsp() + +// terminate dispatcher, kernel only -] +idaman void ida_export set_hexdsp(hexdsp_t hrdsp); +// -[ + +#ifndef SWIG +// ignore_micro manager: can be used in modules/plugins as a base class +struct ignore_micro_t +{ + //-------------------------------------------------------------------------- + /// \name Ignore micro + /// netnode to keep information about various kinds of instructions + //@{ + netnode ignore_micro; + +#define IM_NONE 0 // regular instruction +#define IM_PROLOG 1 // prolog instruction +#define IM_EPILOG 2 // epilog instruction +#define IM_SWITCH 3 // switch instruction (the indirect jump should not be marked) + + inline void init_ignore_micro(void) { ignore_micro.create("$ ignore micro"); } + inline void term_ignore_micro(void) { ignore_micro = BADNODE; } + inline char get_ignore_micro(ea_t ea) const { return ignore_micro.charval_ea(ea, 0); } + inline void set_ignore_micro(ea_t ea, uchar im_type) { ignore_micro.charset_ea(ea, im_type, 0); } + inline void clr_ignore_micro(ea_t ea) { ignore_micro.chardel_ea(ea, 0); } + inline ea_t next_marked_insn(ea_t ea) { return node2ea(ignore_micro.charnext(ea2node(ea), 0)); } + inline void mark_prolog_insn(ea_t ea) { set_ignore_micro(ea, IM_PROLOG); } + inline void mark_epilog_insn(ea_t ea) { set_ignore_micro(ea, IM_EPILOG); } + inline void mark_switch_insn(ea_t ea) { set_ignore_micro(ea, IM_SWITCH); } + inline bool is_prolog_insn(ea_t ea) const { return get_ignore_micro(ea) == IM_PROLOG; } + inline bool is_epilog_insn(ea_t ea) const { return get_ignore_micro(ea) == IM_EPILOG; } + inline bool is_switch_insn(ea_t ea) const { return get_ignore_micro(ea) == IM_SWITCH; } + inline bool should_ignore_micro(ea_t ea) const { return get_ignore_micro(ea) != IM_NONE; } + //@} +}; +#endif // SWIG + +// Each processor module subclasses this class and reacts to HT_IDP events +struct procmod_t : public event_listener_t, public ignore_micro_t +{ + processor_t &ph; + asm_t &ash; + size_t procmod_flags = 0; + size_t reserved = 0; // for the future + procmod_t() : ph(PH), ash(ASH) {} +}; + +struct plugmod_t +{ + size_t owner = 0; // internal info used by the kernel + size_t reserved = 0; // for the future + + /// Invoke the plugin. + virtual bool idaapi run(size_t arg) = 0; + + /// Helper function to hook event listeners. + bool hook_event_listener( + hook_type_t hook_type, + event_listener_t *cb, + int hkcb_flags=0) + { + return ::hook_event_listener(hook_type, cb, this, hkcb_flags); + } + + /// Virtual destructor. + virtual ~plugmod_t() {} +}; + +inline ssize_t processor_t::init(const char *idp_modname) +{ + return notify(ev_init, idp_modname); +} +inline ssize_t processor_t::term() +{ + return notify(ev_term); +} +inline ssize_t processor_t::newprc(int pnum, bool keep_cfg) +{ + return notify(ev_newprc, pnum, keep_cfg); +} +inline ssize_t processor_t::newasm(int asmnum) +{ + return notify(ev_newasm, asmnum); +} +inline ssize_t processor_t::asm_installed(int asmnum) +{ + return notify(ev_asm_installed, asmnum); +} +inline ssize_t processor_t::get_reg_accesses(reg_accesses_t *accvec, const insn_t &insn, int flags) +{ + return notify(ev_get_reg_accesses, accvec, &insn, flags); +} +inline ssize_t processor_t::is_control_flow_guard(int *p_reg, const insn_t *insn) +{ + return processor_t::notify(ev_is_control_flow_guard, p_reg, insn); +} +inline ssize_t processor_t::newfile(const char *fname) +{ + return notify(ev_newfile, fname); +} +inline ssize_t processor_t::oldfile(const char *fname) +{ + return notify(ev_oldfile, fname); +} +inline ssize_t processor_t::newbinary(const char *filename, qoff64_t fileoff, ea_t basepara, ea_t binoff, uint64 nbytes) +{ + return notify(ev_newbinary, filename, fileoff, basepara, binoff, nbytes); +} +inline ssize_t processor_t::endbinary(bool ok) +{ + return notify(ev_endbinary, ok); +} +inline ssize_t processor_t::creating_segm(segment_t *seg) +{ + return notify(ev_creating_segm, seg); +} +inline ssize_t processor_t::assemble(uchar *_bin, ea_t ea, ea_t cs, ea_t ip, bool _use32, const char *line) +{ + return notify(ev_assemble, _bin, ea, cs, ip, _use32, line, _bin); +} +inline ssize_t processor_t::ana_insn(insn_t *out) +{ + return notify(ev_ana_insn, out); +} +inline ssize_t processor_t::emu_insn(const insn_t &insn) +{ + return notify(ev_emu_insn, &insn); +} +inline ssize_t processor_t::out_header(outctx_t &ctx) +{ + return notify(ev_out_header, &ctx); +} +inline ssize_t processor_t::out_footer(outctx_t &ctx) +{ + return notify(ev_out_footer, &ctx); +} +inline ssize_t processor_t::out_segstart(outctx_t &ctx, segment_t *seg) +{ + return notify(ev_out_segstart, &ctx, seg); +} +inline ssize_t processor_t::out_segend(outctx_t &ctx, segment_t *seg) +{ + return notify(ev_out_segend, &ctx, seg); +} +inline ssize_t processor_t::out_assumes(outctx_t &ctx) +{ + return notify(ev_out_assumes, &ctx); +} +inline ssize_t processor_t::out_insn(outctx_t &ctx) +{ + return notify(ev_out_insn, &ctx); +} +inline ssize_t processor_t::out_mnem(outctx_t &ctx) +{ + return notify(ev_out_mnem, &ctx); +} +inline ssize_t processor_t::out_operand(outctx_t &ctx, const op_t &op) +{ + return notify(ev_out_operand, &ctx, &op); +} +inline ssize_t processor_t::out_data(outctx_t &ctx, bool analyze_only) +{ + return notify(ev_out_data, &ctx, analyze_only); +} +inline ssize_t processor_t::out_label(outctx_t &ctx, const char *colored_name) +{ + return notify(ev_out_label, &ctx, colored_name); +} +inline ssize_t processor_t::out_special_item(outctx_t &ctx, uchar segtype) +{ + return notify(ev_out_special_item, &ctx, segtype); +} +inline ssize_t processor_t::gen_stkvar_def(outctx_t &ctx, const class member_t *mptr, sval_t v) +{ + return notify(ev_gen_stkvar_def, &ctx, mptr, v); +} +inline ssize_t processor_t::gen_regvar_def(outctx_t &ctx, regvar_t *v) +{ + return notify(ev_gen_regvar_def, &ctx, v); +} +inline ssize_t processor_t::gen_src_file_lnnum(outctx_t &ctx, const char *file, size_t lnnum) +{ + return notify(ev_gen_src_file_lnnum, &ctx, file, lnnum); +} +inline ssize_t processor_t::rename(ea_t ea, const char *new_name, int flags) +{ + return notify(ev_rename, ea, new_name, flags); +} +inline ssize_t processor_t::may_show_sreg(ea_t current_ea) +{ + return notify(ev_may_show_sreg, current_ea); +} +inline ssize_t processor_t::coagulate(ea_t start_ea) +{ + return notify(ev_coagulate, start_ea); +} +inline void processor_t::auto_queue_empty(/*atype_t*/ int type) +{ + notify(ev_auto_queue_empty, type); +} +inline ssize_t processor_t::func_bounds(int *possible_return_code, func_t *pfn, ea_t max_func_end_ea) +{ + return notify(ev_func_bounds, possible_return_code, pfn, max_func_end_ea); +} +inline ssize_t processor_t::may_be_func(const insn_t &insn, int state) +{ + return notify(ev_may_be_func, &insn, state); +} +inline ssize_t processor_t::is_sane_insn(const insn_t &insn, int no_crefs) +{ + return notify(ev_is_sane_insn, &insn, no_crefs); +} +inline ssize_t processor_t::cmp_operands(const op_t &op1, const op_t &op2) +{ + return notify(ev_cmp_operands, &op1, &op2); +} +inline ssize_t processor_t::is_jump_func(func_t *pfn, ea_t *jump_target, ea_t *func_pointer) +{ + return notify(ev_is_jump_func, pfn, jump_target, func_pointer); +} +inline ssize_t processor_t::is_basic_block_end(const insn_t &insn, bool call_insn_stops_block) +{ + return notify(ev_is_basic_block_end, &insn, call_insn_stops_block); +} +inline ssize_t processor_t::getreg(uval_t *rv, int regnum) +{ + return notify(ev_getreg, rv, regnum); +} +inline ssize_t processor_t::undefine(ea_t ea) +{ + return notify(ev_undefine, ea); +} +inline ssize_t processor_t::moving_segm(segment_t *seg, ea_t to, int flags) +{ + return notify(ev_moving_segm, seg, to, flags); +} +inline ssize_t processor_t::is_sp_based(const insn_t &insn, const op_t &x) +{ + int mode; + int code = notify(ev_is_sp_based, &mode, &insn, &x); + return code == 0 ? OP_SP_BASED : mode; +} +inline ssize_t processor_t::is_far_jump(int icode) +{ + return notify(ev_is_far_jump, icode); +} +inline ssize_t processor_t::is_call_insn(const insn_t &insn) +{ + return notify(ev_is_call_insn, &insn); +} +inline ssize_t processor_t::is_ret_insn(const insn_t &insn, bool strict) +{ + return notify(ev_is_ret_insn, &insn, strict); +} +inline ssize_t processor_t::is_align_insn(ea_t ea) +{ + return notify(ev_is_align_insn, ea); +} +inline ssize_t processor_t::can_have_type(const op_t &op) +{ + return notify(ev_can_have_type, &op); +} +inline ssize_t processor_t::get_stkvar_scale_factor() +{ + return notify(ev_get_stkvar_scale_factor); +} +inline ssize_t processor_t::demangle_name(int32 *res, qstring *out, const char *name, uint32 disable_mask, /*demreq_type_t*/ int demreq) +{ + return notify(ev_demangle_name, res, out, name, disable_mask, demreq); +} +inline ssize_t processor_t::create_flat_group(ea_t image_base, int bitness, sel_t dataseg_sel) +{ + return notify(ev_create_flat_group, image_base, bitness, dataseg_sel); +} +inline ssize_t processor_t::is_alloca_probe(ea_t ea) +{ + return notify(ev_is_alloca_probe, ea); +} +inline ssize_t processor_t::get_reg_name(qstring *buf, int reg, size_t width, int reghi) +{ + return notify(ev_get_reg_name, buf, reg, width, reghi); +} +inline ssize_t processor_t::gen_asm_or_lst(bool starting, FILE *fp, bool is_asm, int flags, /*html_line_cb_t ** */ void *outline) +{ + return notify(ev_gen_asm_or_lst, starting, fp, is_asm, flags, outline); +} +inline ssize_t processor_t::gen_map_file(int *nlines, FILE *fp) +{ + return notify(ev_gen_map_file, nlines, fp); +} +inline ssize_t processor_t::get_autocmt(qstring *buf, const insn_t &insn) +{ + return notify(ev_get_autocmt, buf, &insn); +} +inline ssize_t processor_t::loader_elf_machine(linput_t *li, int machine_type, const char **p_procname, proc_def_t **p_pd) +{ + return notify(ev_loader_elf_machine, li, machine_type, p_procname, p_pd); +} +inline ssize_t processor_t::is_indirect_jump(const insn_t &insn) +{ + return notify(ev_is_indirect_jump, &insn); +} +inline ssize_t processor_t::verify_noreturn(func_t *pfn) +{ + return notify(ev_verify_noreturn, pfn); +} +inline ssize_t processor_t::verify_sp(func_t *pfn) +{ + return notify(ev_verify_sp, pfn); +} +inline ssize_t processor_t::create_func_frame(func_t *pfn) +{ + return notify(ev_create_func_frame, pfn); +} +inline ssize_t processor_t::get_frame_retsize(int *retsize, const func_t *pfn) +{ + return notify(ev_get_frame_retsize, retsize, pfn); +} +inline ssize_t processor_t::analyze_prolog(ea_t fct_ea) +{ + return notify(ev_analyze_prolog, fct_ea); +} +inline ssize_t processor_t::calc_spdelta(sval_t *spdelta, const insn_t &insn) +{ + return notify(ev_calc_spdelta, spdelta, &insn); +} +inline ssize_t processor_t::calcrel(bytevec_t *out_relbits, size_t *out_consumed, ea_t ea) +{ + return notify(ev_calcrel, out_relbits, out_consumed, ea); +} +inline ssize_t processor_t::find_reg_value(uval_t *out, const insn_t &insn, int reg) +{ + return notify(ev_find_reg_value, out, &insn, reg); +} +inline ssize_t processor_t::find_op_value(uval_t *out, const insn_t &insn, int opn) +{ + return notify(ev_find_op_value, out, &insn, opn); +} +inline ssize_t processor_t::treat_hindering_item(ea_t hindering_item_ea, flags_t new_item_flags, ea_t new_item_ea, asize_t new_item_length) +{ + return notify(ev_treat_hindering_item, hindering_item_ea, new_item_flags, new_item_ea, new_item_length); +} +inline ssize_t processor_t::extract_address(ea_t *out_ea, ea_t screen_ea, const char *string, size_t x) +{ + return notify(ev_extract_address, out_ea, screen_ea, string, x); +} +inline ssize_t processor_t::str2reg(const char *regname) +{ + return notify(ev_str2reg, regname); +} +inline ssize_t processor_t::is_switch(switch_info_t *si, const insn_t &insn) +{ + return notify(ev_is_switch, si, &insn); +} +inline ssize_t processor_t::create_switch_xrefs(ea_t jumpea, const switch_info_t &si) +{ + return notify(ev_create_switch_xrefs, jumpea, &si); +} +inline ssize_t processor_t::calc_switch_cases(/*casevec_t * */void *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si) +{ + return notify(ev_calc_switch_cases, casevec, targets, insn_ea, &si); +} +inline ssize_t processor_t::get_bg_color(bgcolor_t *color, ea_t ea) +{ + return notify(ev_get_bg_color, color, ea); +} +inline ssize_t processor_t::validate_flirt_func(ea_t start_ea, const char *funcname) +{ + return notify(ev_validate_flirt_func, start_ea, funcname); +} +inline ssize_t processor_t::get_operand_string(qstring *buf, const insn_t &insn, int opnum) +{ + return notify(ev_get_operand_string, buf, &insn, opnum); +} +inline ssize_t processor_t::add_cref(ea_t from, ea_t to, cref_t type) +{ + return notify(ev_add_cref, from, to, type); +} +inline ssize_t processor_t::add_dref(ea_t from, ea_t to, dref_t type) +{ + return notify(ev_add_dref, from, to, type); +} +inline ssize_t processor_t::del_cref(ea_t from, ea_t to, bool expand) +{ + return notify(ev_del_cref, from, to, expand); +} +inline ssize_t processor_t::del_dref(ea_t from, ea_t to) +{ + return notify(ev_del_dref, from, to); +} +inline ssize_t processor_t::coagulate_dref(ea_t from, ea_t to, bool may_define, ea_t *code_ea) +{ + return notify(ev_coagulate_dref, from, to, may_define, code_ea); +} +inline const char *processor_t::set_idp_options(const char *keyword, int vtype, const void *value, bool idb_loaded) +{ + const char *errmsg = IDPOPT_BADKEY; + int code = notify(ev_set_idp_options, keyword, vtype, value, &errmsg, idb_loaded); + return code == 1 ? IDPOPT_OK : code == 0 ? IDPOPT_BADKEY : errmsg; +} +inline ssize_t processor_t::set_proc_options(const char *options, int confidence) +{ + return notify(ev_set_proc_options, options, confidence); +} +inline ssize_t processor_t::adjust_libfunc_ea(const idasgn_t &sig, const libfunc_t &libfun, ea_t *ea) +{ + return notify(ev_adjust_libfunc_ea, &sig, &libfun, ea); +} +inline fpvalue_error_t processor_t::realcvt(void *m, fpvalue_t *e, uint16 swt) +{ + return (fpvalue_error_t)notify(ev_realcvt, m, e, swt); +} +inline ssize_t processor_t::adjust_refinfo(refinfo_t *ri, ea_t ea, int n, const fixup_data_t &fd) +{ + return notify(ev_adjust_refinfo, ri, ea, n, &fd); +} +inline ssize_t processor_t::is_cond_insn(const insn_t &insn) +{ + return notify(ev_is_cond_insn, &insn); +} +inline ssize_t processor_t::set_code16_mode(ea_t ea, bool code16) +{ + return notify(ev_set_code16_mode, ea, code16); +} +inline bool processor_t::get_code16_mode(ea_t ea) +{ + return notify(ev_get_code16_mode, ea) == 1; +} +inline ssize_t processor_t::next_exec_insn(ea_t *target, ea_t ea, int tid, regval_getter_t *_getreg, const regval_t ®values) +{ + return notify(ev_next_exec_insn, target, ea, tid, _getreg, ®values); +} +inline ssize_t processor_t::calc_step_over(ea_t *target, ea_t ip) +{ + return notify(ev_calc_step_over, target, ip); +} +inline ssize_t processor_t::get_macro_insn_head(ea_t *head, ea_t ip) +{ + return notify(ev_get_macro_insn_head, head, ip); +} +inline ssize_t processor_t::get_dbr_opnum(int *opnum, const insn_t &insn) +{ + return notify(ev_get_dbr_opnum, opnum, &insn); +} +inline ssize_t processor_t::insn_reads_tbit(const insn_t &insn, regval_getter_t *_getreg, const regval_t ®values) +{ + return notify(ev_insn_reads_tbit, &insn, _getreg, ®values); +} +inline ssize_t processor_t::get_idd_opinfo(idd_opinfo_t *opinf, ea_t ea, int n, int thread_id, regval_getter_t *_getreg, const regval_t ®values) +{ + return notify(ev_get_idd_opinfo, opinf, ea, n, thread_id, _getreg, ®values); +} +inline ssize_t processor_t::update_call_stack(call_stack_t *stack, int thread_id, regval_getter_t *_getreg, const regval_t ®values) +{ + return notify(ev_update_call_stack, stack, thread_id, _getreg, ®values); +} +inline ssize_t processor_t::calc_next_eas(eavec_t *res, const insn_t &insn, bool over) +{ + return notify(ev_calc_next_eas, res, &insn, over); +} +inline ssize_t processor_t::clean_tbit(ea_t ea, regval_getter_t *_getreg, const regval_t ®values) +{ + return notify(ev_clean_tbit, ea, _getreg, ®values); +} +inline ssize_t processor_t::setup_til() +{ + return notify(ev_setup_til); +} +inline ssize_t processor_t::max_ptr_size() +{ + return notify(ev_max_ptr_size); +} +inline ssize_t processor_t::calc_cdecl_purged_bytes(ea_t ea) +{ + return notify(ev_calc_cdecl_purged_bytes, ea); +} +inline ssize_t processor_t::get_stkarg_offset() const +{ + return ti() ? notify(ev_get_stkarg_offset) : 0; +} +inline ssize_t processor_t::equal_reglocs(const argloc_t &a1, const argloc_t &a2) +{ + return notify(ev_equal_reglocs, &a1, &a2); +} +inline ssize_t processor_t::decorate_name(qstring *outbuf, const char *name, bool mangle, cm_t cc, const tinfo_t &type) +{ + return notify(ev_decorate_name, outbuf, name, mangle, cc, &type); +} +inline ssize_t processor_t::calc_retloc(argloc_t *retloc, const tinfo_t &rettype, cm_t cc) +{ + return notify(ev_calc_retloc, retloc, &rettype, cc); +} +inline ssize_t processor_t::calc_varglocs(func_type_data_t *ftd, regobjs_t *regs, relobj_t *stkargs, int nfixed) +{ + return notify(ev_calc_varglocs, ftd, regs, stkargs, nfixed); +} +inline ssize_t processor_t::calc_arglocs(func_type_data_t *fti) +{ + return notify(ev_calc_arglocs, fti); +} +inline ssize_t processor_t::use_stkarg_type(ea_t ea, const funcarg_t &arg) +{ + return notify(ev_use_stkarg_type, ea, &arg); +} +inline ssize_t processor_t::use_regarg_type(int *idx, ea_t ea, /*const funcargvec_t * */void *rargs) +{ + return notify(ev_use_regarg_type, idx, ea, rargs); +} +inline ssize_t processor_t::use_arg_types(ea_t ea, func_type_data_t *fti, /*funcargvec_t * */void *rargs) +{ + return notify(ev_use_arg_types, ea, fti, rargs); +} +inline ssize_t processor_t::calc_purged_bytes(int *p_purged_bytes, const func_type_data_t &fti) +{ + return notify(ev_calc_purged_bytes, p_purged_bytes, &fti); +} +inline ssize_t processor_t::shadow_args_size(int *shadow_size, func_t *pfn) +{ + return notify(ev_shadow_args_size, shadow_size, pfn); +} +inline ssize_t processor_t::get_cc_regs(callregs_t *regs, cm_t cc) +{ + return notify(ev_get_cc_regs, regs, cc); +} +inline ssize_t processor_t::get_simd_types(/*simd_info_vec_t * */void *out, const simd_info_t *simd_attrs, const argloc_t *argloc, bool create_tifs) +{ + return notify(ev_get_simd_types, out, simd_attrs, argloc, create_tifs); +} +inline ssize_t processor_t::arg_addrs_ready(ea_t caller, int n, const tinfo_t &tif, ea_t *addrs) +{ + return notify(ev_arg_addrs_ready, caller, n, &tif, addrs); +} +inline ssize_t processor_t::adjust_argloc(argloc_t *argloc, const tinfo_t *type, int size) +{ + return notify(ev_adjust_argloc, argloc, type, size); +} +inline ssize_t processor_t::lower_func_type(intvec_t *argnums, func_type_data_t *fti) +{ + return notify(ev_lower_func_type, argnums, fti); +} +inline ssize_t processor_t::get_abi_info(qstrvec_t *abi_names, qstrvec_t *abi_opts, comp_t comp) +{ + return notify(ev_get_abi_info, abi_names, abi_opts, comp); +} +inline ssize_t processor_t::arch_changed() +{ + return notify(ev_arch_changed); +} +inline ssize_t processor_t::create_merge_handlers(merge_data_t *md) +{ + return notify(ev_create_merge_handlers, md); +} + +idaman int ida_export str2reg(const char *p); ///< Get any reg number (-1 on error) + + +/// If the instruction at 'ea' looks like an alignment instruction, +/// return its length in bytes. Otherwise return 0. + +idaman int ida_export is_align_insn(ea_t ea); + + +/// Get text representation of a register. +/// For most processors this function will just return \ph{reg_names}[reg]. +/// If the processor module has implemented processor_t::get_reg_name, it will be +/// used instead +/// \param buf output buffer +/// \param reg internal register number as defined in the processor module +/// \param width register width in bytes +/// \param reghi if specified, then this function will return the register pair +/// \return length of register name in bytes or -1 if failure + +idaman ssize_t ida_export get_reg_name(qstring *buf, int reg, size_t width, int reghi = -1); + + +/// Get register information - useful for registers like al, ah, dil, etc. +/// Example: this function for "al" returns "eax" in 32bit mode +/// \return main register name (NULL no such register) + +inline const char *processor_t::get_reg_info(const char *regname, bitrange_t *bitrange) +{ + const char *r2; + int code = notify(ev_get_reg_info, &r2, bitrange, regname); + if ( code == 0 ) // not implemented? + { + if ( ::str2reg(regname) != -1 ) + { + if ( bitrange != NULL ) + bitrange->reset(); + return regname; + } + return NULL; + } + return code == 1 ? r2 : NULL; +} + +/// Get register number and size from register name +struct reg_info_t +{ + int reg; ///< register number + int size; ///< register size + DECLARE_COMPARISONS(reg_info_t) + { + if ( reg != r.reg ) + return reg > r.reg ? 1 : -1; + if ( size != r.size ) + return size > r.size ? 1 : -1; + return 0; + } +}; +DECLARE_TYPE_AS_MOVABLE(reg_info_t); +typedef qvector<reg_info_t> reginfovec_t; ///< vector of register info objects + + +/// Get register info by name. +/// \param[out] ri result +/// \param regname name of register +/// \return success + +idaman bool ida_export parse_reg_name(reg_info_t *ri, const char *regname); + + +/// Possible memory and register access types. +enum access_type_t ENUM_SIZE(uchar) +{ + NO_ACCESS = 0, + WRITE_ACCESS = 1, + READ_ACCESS = 2, + RW_ACCESS = WRITE_ACCESS | READ_ACCESS, +}; + +/// Information about a register accessed by an instruction. +struct reg_access_t +{ + int regnum = 0; ///< register number (only entire registers) + bitrange_t range; ///< bitrange inside the register + access_type_t access_type = NO_ACCESS; + uchar opnum = 0; ///< operand number + + bool have_common_bits(const reg_access_t &r) const + { + return regnum == r.regnum && range.has_common(r.range); + } + + bool operator==(const reg_access_t &r) const + { + return regnum == r.regnum + && range == r.range + && access_type == r.access_type + && opnum == r.opnum; + } + + bool operator!=(const reg_access_t &r) const + { + return !(*this == r); + } +}; +DECLARE_TYPE_AS_MOVABLE(reg_access_t); +typedef qvector<reg_access_t> reg_access_vec_t; + +struct reg_accesses_t : public reg_access_vec_t {}; + + +inline bool insn_t::is_canon_insn(const processor_t &_ph) const // see ::insn_t in ua.hpp +{ + return _ph.is_canon_insn(itype); +} + +inline const char *insn_t::get_canon_mnem(const processor_t &_ph) const // see ::insn_t in ua.hpp +{ + return is_canon_insn(_ph) ? _ph.instruc[itype-_ph.instruc_start].name : NULL; +} + +inline uint32 insn_t::get_canon_feature(const processor_t &_ph) const // ::insn_t in ua.hpp +{ + return is_canon_insn(_ph) ? _ph.instruc[itype-_ph.instruc_start].feature : 0; +} + + +/// Get size of long double +inline size_t processor_t::sizeof_ldbl() const +{ + return inf_get_cc_size_ldbl() ? inf_get_cc_size_ldbl() : tbyte_size; +} + +/// Flags passed as 'level' parameter to set_processor_type() +enum setproc_level_t +{ + SETPROC_IDB = 0, ///< set processor type for old idb + SETPROC_LOADER = 1, ///< set processor type for new idb; + ///< if the user has specified a compatible processor, + ///< return success without changing it. + ///< if failure, call loader_failure() + SETPROC_LOADER_NON_FATAL = 2, ///< the same as SETPROC_LOADER but non-fatal failures. + SETPROC_USER = 3, ///< set user-specified processor + ///< used for -p and manual processor change at later time +}; + +/// Set target processor type. +/// Once a processor module is loaded, it cannot be replaced until we close the idb. +/// \param procname name of processor type (one of names present in \ph{psnames}) +/// \param level \ref SETPROC_ +/// \return success + +idaman bool ida_export set_processor_type( + const char *procname, + setproc_level_t level); + + +/// Get name of the current processor module. +/// The name is derived from the file name. +/// For example, for IBM PC the module is named "pc.w32" (windows version), +/// then the module name is "PC" (uppercase). +/// If no processor module is loaded, this function will return NULL +/// \param buf the output buffer, should be at least #QMAXFILE length +/// \param bufsize size of output buffer + +idaman char *ida_export get_idp_name(char *buf, size_t bufsize); + + +/// Set target assembler. +/// \param asmnum number of assembler in the current processor module +/// \return success + +idaman bool ida_export set_target_assembler(int asmnum); + + +/// Helper function to get the delay slot instruction +inline bool processor_t::delay_slot_insn(ea_t *ea, bool *bexec, bool *fexec) +{ + bool ok = (flag & PR_DELAYED) != 0; + if ( ok ) + { + bool be = true; + bool fe = true; + ok = notify(ev_delay_slot_insn, ea, &be, &fe) == 1; + if ( ok ) + { + if ( bexec != NULL ) + *bexec = be; + if ( fexec != NULL ) + *fexec = fe; + } + } + return ok; +} + +/// IDB event group. Some events are still in the processor group, so you will +/// need to hook to both groups. These events do not return anything. +/// +/// The callback function should return 0 but the kernel won't check it. +/// Use the hook_to_notification_point() function to install your callback. +namespace idb_event +{ + //<hookgen IDB> + + /// IDB event codes + enum event_code_t + { + closebase, ///< The database will be closed now + + savebase, ///< The database is being saved + + upgraded, ///< The database has been upgraded + ///< and the receiver can upgrade its info as well + ///< \param from (int) - old IDB version + + auto_empty, ///< Info: all analysis queues are empty. + ///< This callback is called once when the + ///< initial analysis is finished. If the queue is + ///< not empty upon the return from this callback, + ///< it will be called later again. + + auto_empty_finally, ///< Info: all analysis queues are empty definitively. + ///< This callback is called only once. + + determined_main, ///< The main() function has been determined. + ///< \param main (::ea_t) address of the main() function + local_types_changed, ///< Local types have been changed + + extlang_changed, ///< The list of extlangs or the default extlang was changed. + ///< \param kind (int) + ///< 0: extlang installed + ///< 1: extlang removed + ///< 2: default extlang changed + ///< \param el (::extlang_t *) pointer to the extlang affected + ///< \param idx (int) extlang index + + idasgn_loaded, ///< FLIRT signature has been loaded + ///< for normal processing (not for + ///< recognition of startup sequences). + ///< \param short_sig_name (const char *) + + kernel_config_loaded, ///< This event is issued when ida.cfg is parsed. + ///< \param pass_number (int) + + loader_finished, ///< External file loader finished its work. + ///< Use this event to augment the existing loader functionality. + ///< \param li (linput_t *) + ///< \param neflags (::uint16) \ref NEF_ + ///< \param filetypename (const char *) + + flow_chart_created, ///< Gui has retrieved a function flow chart. + ///< Plugins may modify the flow chart in this callback. + ///< \param fc (qflow_chart_t *) + + compiler_changed, ///< The kernel has changed the compiler information. + ///< (\inf{cc} structure; \ref get_abi_name) + ///< \param adjust_inf_fields (::bool) may change inf fields? + + changing_ti, ///< An item typestring (c/c++ prototype) is to be changed. + ///< \param ea (::ea_t) + ///< \param new_type (const ::type_t *) + ///< \param new_fnames (const ::p_list *) + + ti_changed, ///< An item typestring (c/c++ prototype) has been changed. + ///< \param ea (::ea_t) + ///< \param type (const ::type_t *) + ///< \param fnames (const ::p_list *) + + changing_op_ti, ///< An operand typestring (c/c++ prototype) is to be changed. + ///< \param ea (::ea_t) + ///< \param n (int) + ///< \param new_type (const ::type_t *) + ///< \param new_fnames (const ::p_list *) + op_ti_changed, ///< An operand typestring (c/c++ prototype) has been changed. + ///< \param ea (::ea_t) + ///< \param n (int) + ///< \param type (const ::type_t *) + ///< \param fnames (const ::p_list *) + + changing_op_type, ///< An operand type (offset, hex, etc...) is to be changed. + ///< \param ea (::ea_t) + ///< \param n (int) eventually or'ed with OPND_OUTER or OPND_ALL + ///< \param opinfo (const opinfo_t *) additional operand info + op_type_changed, ///< An operand type (offset, hex, etc...) has been set or deleted. + ///< \param ea (::ea_t) + ///< \param n (int) eventually or'ed with OPND_OUTER or OPND_ALL + + enum_created, ///< An enum type has been created. + ///< \param id (::enum_t) + + deleting_enum, ///< An enum type is to be deleted. + ///< \param id (::enum_t) + enum_deleted, ///< An enum type has been deleted. + ///< \param id (::enum_t) + + renaming_enum, ///< An enum or enum member is to be renamed. + ///< \param id (::tid_t) + ///< \param is_enum (bool) + ///< \param newname (const char *) + enum_renamed, ///< An enum or member has been renamed. + ///< \param id (::tid_t) + + changing_enum_bf, ///< An enum type 'bitfield' attribute is to be changed. + ///< \param id (::enum_t) + ///< \param new_bf (bool) + enum_bf_changed, ///< An enum type 'bitfield' attribute has been changed. + ///< \param id (::enum_t) + + changing_enum_cmt, ///< An enum or member type comment is to be changed. + ///< \param id (::tid_t) + ///< \param repeatable (bool) + ///< \param newcmt (const char *) + enum_cmt_changed, ///< An enum or member type comment has been changed. + ///< \param id (::tid_t) + ///< \param repeatable (bool) + + enum_member_created, ///< An enum member has been created. + ///< \param id (::enum_t) + ///< \param cid (::const_t) + + deleting_enum_member, ///< An enum member is to be deleted. + ///< \param id (::enum_t) + ///< \param cid (::const_t) + enum_member_deleted, ///< An enum member has been deleted. + ///< \param id (::enum_t) + ///< \param cid (::const_t) + + struc_created, ///< A new structure type has been created. + ///< \param struc_id (::tid_t) + + deleting_struc, ///< A structure type is to be deleted. + ///< \param sptr (::struc_t *) + struc_deleted, ///< A structure type has been deleted. + ///< \param struc_id (::tid_t) + + changing_struc_align, ///< A structure type is being changed (the struct alignment). + ///< \param sptr (::struc_t *) + struc_align_changed, ///< A structure type has been changed (the struct alignment). + ///< \param sptr (::struc_t *) + + renaming_struc, ///< A structure type is to be renamed. + ///< \param id (::tid_t) + ///< \param oldname (const char *) + ///< \param newname (const char *) + struc_renamed, ///< A structure type has been renamed. + ///< \param sptr (::struc_t *) + + expanding_struc, ///< A structure type is to be expanded/shrunk. + ///< \param sptr (::struc_t *) + ///< \param offset (::ea_t) + ///< \param delta (::adiff_t) + struc_expanded, ///< A structure type has been expanded/shrank. + ///< \param sptr (::struc_t *) + + struc_member_created, ///< A structure member has been created. + ///< \param sptr (::struc_t *) + ///< \param mptr (::member_t *) + + deleting_struc_member, ///< A structure member is to be deleted. + ///< \param sptr (::struc_t *) + ///< \param mptr (::member_t *) + struc_member_deleted, ///< A structure member has been deleted. + ///< \param sptr (::struc_t *) + ///< \param member_id (::tid_t) + ///< \param offset (::ea_t) + + renaming_struc_member, ///< A structure member is to be renamed. + ///< \param sptr (::struc_t *) + ///< \param mptr (::member_t *) + ///< \param newname (const char *) + struc_member_renamed, ///< A structure member has been renamed. + ///< \param sptr (::struc_t *) + ///< \param mptr (::member_t *) + + changing_struc_member, ///< A structure member is to be changed. + ///< \param sptr (::struc_t *) + ///< \param mptr (::member_t *) + ///< \param flag (::flags_t) + ///< \param ti (const ::opinfo_t *) + ///< \param nbytes (::asize_t) + struc_member_changed, ///< A structure member has been changed. + ///< \param sptr (::struc_t *) + ///< \param mptr (::member_t *) + + changing_struc_cmt, ///< A structure type comment is to be changed. + ///< \param struc_id (::tid_t) + ///< \param repeatable (bool) + ///< \param newcmt (const char *) + struc_cmt_changed, ///< A structure type comment has been changed. + ///< \param struc_id (::tid_t) + ///< \param repeatable_cmt (bool) + + segm_added, ///< A new segment has been created. + ///< \param s (::segment_t *) + ///< See also adding_segm + + deleting_segm, ///< A segment is to be deleted. + ///< \param start_ea (::ea_t) + segm_deleted, ///< A segment has been deleted. + ///< \param start_ea (::ea_t) + ///< \param end_ea (::ea_t) + + changing_segm_start, ///< Segment start address is to be changed. + ///< \param s (::segment_t *) + ///< \param new_start (::ea_t) + ///< \param segmod_flags (int) + segm_start_changed, ///< Segment start address has been changed. + ///< \param s (::segment_t *) + ///< \param oldstart (::ea_t) + + changing_segm_end, ///< Segment end address is to be changed. + ///< \param s (::segment_t *) + ///< \param new_end (::ea_t) + ///< \param segmod_flags (int) + segm_end_changed, ///< Segment end address has been changed. + ///< \param s (::segment_t *) + ///< \param oldend (::ea_t) + + changing_segm_name, ///< Segment name is being changed. + ///< \param s (::segment_t *) + ///< \param oldname (const char *) + segm_name_changed, ///< Segment name has been changed. + ///< \param s (::segment_t *) + ///< \param name (const char *) + + changing_segm_class, ///< Segment class is being changed. + ///< \param s (::segment_t *) + segm_class_changed, ///< Segment class has been changed. + ///< \param s (::segment_t *) + ///< \param sclass (const char *) + + segm_attrs_updated, ///< Segment attributes has been changed. + ///< \param s (::segment_t *) + ///< This event is generated for secondary segment + ///< attributes (examples: color, permissions, etc) + + segm_moved, ///< Segment has been moved. + ///< \param from (::ea_t) + ///< \param to (::ea_t) + ///< \param size (::asize_t) + ///< \param changed_netmap (bool) + ///< See also \ref idb_event::allsegs_moved + + allsegs_moved, ///< Program rebasing is complete. + ///< This event is generated after series of + ///< segm_moved events + ///< \param info (::segm_move_infos_t *) + + func_added, ///< The kernel has added a function. + ///< \param pfn (::func_t *) + + func_updated, ///< The kernel has updated a function. + ///< \param pfn (::func_t *) + + set_func_start, ///< Function chunk start address will be changed. + ///< \param pfn (::func_t *) + ///< \param new_start (::ea_t) + + set_func_end, ///< Function chunk end address will be changed. + ///< \param pfn (::func_t *) + ///< \param new_end (::ea_t) + + deleting_func, ///< The kernel is about to delete a function. + ///< \param pfn (::func_t *) + // + frame_deleted, ///< The kernel has deleted a function frame. + ///< \param pfn (::func_t *) + + thunk_func_created, ///< A thunk bit has been set for a function. + ///< \param pfn (::func_t *) + + func_tail_appended, ///< A function tail chunk has been appended. + ///< \param pfn (::func_t *) + ///< \param tail (::func_t *) + + deleting_func_tail, ///< A function tail chunk is to be removed. + ///< \param pfn (::func_t *) + ///< \param tail (const ::range_t *) + + func_tail_deleted, ///< A function tail chunk has been removed. + ///< \param pfn (::func_t *) + ///< \param tail_ea (::ea_t) + + tail_owner_changed, ///< A tail chunk owner has been changed. + ///< \param tail (::func_t *) + ///< \param owner_func (::ea_t) + ///< \param old_owner (::ea_t) + + func_noret_changed, ///< #FUNC_NORET bit has been changed. + ///< \param pfn (::func_t *) + + stkpnts_changed, ///< Stack change points have been modified. + ///< \param pfn (::func_t *) + + updating_tryblks, ///< About to update tryblk information + ///< \param tbv (const ::tryblks_t *) + tryblks_updated, ///< Updated tryblk information + ///< \param tbv (const ::tryblks_t *) + + deleting_tryblks, ///< About to delete tryblk information in given range + ///< \param range (const ::range_t *) + // + sgr_changed, ///< The kernel has changed a segment register value. + ///< \param start_ea (::ea_t) + ///< \param end_ea (::ea_t) + ///< \param regnum (int) + ///< \param value (::sel_t) + ///< \param old_value (::sel_t) + ///< \param tag (::uchar) \ref SR_ + + make_code, ///< An instruction is being created. + ///< \param insn (const ::insn_t*) + + make_data, ///< A data item is being created. + ///< \param ea (::ea_t) + ///< \param flags (::flags_t) + ///< \param tid (::tid_t) + ///< \param len (::asize_t) + + destroyed_items, ///< Instructions/data have been destroyed in [ea1,ea2). + ///< \param ea1 (::ea_t) + ///< \param ea2 (::ea_t) + ///< \param will_disable_range (bool) + + renamed, ///< The kernel has renamed a byte. + ///< See also the \idpcode{rename} event + ///< \param ea (::ea_t) + ///< \param new_name (const char *) can be nullptr + ///< \param local_name (bool) + ///< \param old_name (const char *) can be nullptr + + byte_patched, ///< A byte has been patched. + ///< \param ea (::ea_t) + ///< \param old_value (::uint32) + + changing_cmt, ///< An item comment is to be changed. + ///< \param ea (::ea_t) + ///< \param repeatable_cmt (bool) + ///< \param newcmt (const char *) + cmt_changed, ///< An item comment has been changed. + ///< \param ea (::ea_t) + ///< \param repeatable_cmt (bool) + + changing_range_cmt, ///< Range comment is to be changed. + ///< \param kind (::range_kind_t) + ///< \param a (const ::range_t *) + ///< \param cmt (const char *) + ///< \param repeatable (bool) + range_cmt_changed, ///< Range comment has been changed. + ///< \param kind (::range_kind_t) + ///< \param a (const ::range_t *) + ///< \param cmt (const char *) + ///< \param repeatable (bool) + + extra_cmt_changed, ///< An extra comment has been changed. + ///< \param ea (::ea_t) + ///< \param line_idx (int) + ///< \param cmt (const char *) + + item_color_changed, ///< An item color has been changed. + ///< \param ea (::ea_t) + ///< \param color (::bgcolor_t) + ///< if color==DEFCOLOR, the the color is deleted. + + callee_addr_changed, ///< Callee address has been updated by the user. + ///< \param ea (::ea_t) + ///< \param callee (::ea_t) + + bookmark_changed, ///< Boomarked position changed. + ///< \param index (::uint32) + ///< \param pos (::const lochist_entry_t *) + ///< \param desc (::const char *) + ///< \param operation (int) 0-added, 1-updated, 2-deleted + ///< if desc==NULL, then the bookmark was deleted. + + sgr_deleted, ///< The kernel has deleted a segment register value. + ///< \param start_ea (::ea_t) + ///< \param end_ea (::ea_t) + ///< \param regnum (int) + + adding_segm, ///< A segment is being created. + ///< \param s (::segment_t *) + + func_deleted, ///< A function has been deleted. + ///< \param func_ea (::ea_t) + + dirtree_mkdir, ///< Dirtree: a directory has been created. + ///< \param dt (::dirtree_t *) + ///< \param path (::const char *) + + dirtree_rmdir, ///< Dirtree: a directory has been deleted. + ///< \param dt (::dirtree_t *) + ///< \param path (::const char *) + + dirtree_link, ///< Dirtree: an item has been linked/unlinked. + ///< \param dt (::dirtree_t *) + ///< \param path (::const char *) + ///< \param link (::bool) + + dirtree_move, ///< Dirtree: a directory or item has been moved. + ///< \param dt (::dirtree_t *) + ///< \param from (::const char *) + ///< \param to (::const char *) + + dirtree_rank, ///< Dirtree: a directory or item rank has been changed. + ///< \param dt (::dirtree_t *) + ///< \param path (::const char *) + ///< \param rank (::size_t) + + dirtree_rminode, ///< Dirtree: an inode became unavailable. + ///< \param dt (::dirtree_t *) + ///< \param inode (::inode_t) + + dirtree_segm_moved, ///< Dirtree: inodes were changed due to + ///< a segment movement or a program rebasing + ///< \param dt (::dirtree_t *) + }; +} + + +/// the kernel will use this function to generate idb_events + +inline void gen_idb_event(idb_event::event_code_t code, ...) +{ + va_list va; + va_start(va, code); + invoke_callbacks(HT_IDB, code, va); + va_end(va); +} + +inline int processor_t::get_proc_index(void) +{ + qstring curproc = inf_get_procname(); + int i = 0; + while ( psnames[i] != nullptr ) + { + if ( curproc == psnames[i] ) + return i; + i++; + } + // should not reach here + INTERR(10336); +} + +/// Starting from IDA v7.5 all modules should use the following 3 functions +/// to handle idb specific static data because now the kernel supports +/// opening and working with multiple idbs files simultaneously. +/// See the source code of the processor modules in the SDK for the usage examples. + +/// Register pointer to database specific module data. +/// \param data_id initially the pointed-to value must be 0, the kernel will fill +/// it with a unique id. once assigned, the data_id does not change. +/// \param data_ptr pointer to the data to register +/// \return data_ptr. +/// The registered pointer can later be retrieved using get_module_data() + +idaman void *ida_export set_module_data(int *data_id, void *data_ptr); + + +/// Unregister pointer to database specific module data. +/// \param data_id an data_id that was assigned by set_module_data() +/// \return previously registered pointer for the current database. +/// it can be deallocated now. +/// Multiple calls to this function with the same id are forbidden. + +idaman void *ida_export clr_module_data(int data_id); + + + +/// Get pointer to the database specific module data. +/// \param data_id data id that was initialized by set_module_data() +/// \return previously registered pointer for the current database + +idaman void *ida_export get_module_data(int data_id); + +// Convenience macros to handle the module data. +// They assume the existence of a global variable "int data_id" +#define SET_MODULE_DATA(type) (type *)set_module_data(&data_id, new type) +#define GET_MODULE_DATA(type) ((type *)get_module_data(data_id)) + + +#endif // _IDP_HPP diff --git a/idasdk76/include/ieee.h b/idasdk76/include/ieee.h new file mode 100644 index 0000000..241c27e --- /dev/null +++ b/idasdk76/include/ieee.h @@ -0,0 +1,263 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + + * Floating Point Number Libary. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + */ + +#include <pro.h> +#ifndef _IEEE_H_ +#define _IEEE_H_ + +/*! \file ieee.h + + \brief IEEE floating point functions + +*/ + +struct fpvalue_t; // processor-independent representation of floats + +#define FPVAL_NWORDS 6 // number of words in fpvalue_t + +/// Floating value kinds. +/// They are useful when checking for NaN/Inf +enum fpvalue_kind_t +{ + FPV_BADARG, ///< wrong value of max_exp + FPV_NORM, ///< regular value + FPV_NAN, ///< NaN + FPV_PINF, ///< positive infinity + FPV_NINF, ///< negative infinity +}; + +/// \name max_exp values +/// Common values for max_exp (for IEEE floating point values) +//@{ +const uint32 + MAXEXP_FLOAT = 0x80, + MAXEXP_DOUBLE = 0x400, + MAXEXP_LNGDBL = 0x4000; +//@} + +/// \defgroup REAL_ERROR_ Floating point/IEEE Conversion codes +/// Return values for ieee_realcvt and processor_t::realcvt_t request +enum fpvalue_error_t +{ + REAL_ERROR_OK = 0, ///< no error + REAL_ERROR_FORMAT = -1, ///< realcvt: not supported format for current .idp + REAL_ERROR_RANGE = -2, ///< realcvt: number too big (small) for store (mem NOT modified) + REAL_ERROR_BADDATA = -3, ///< realcvt: illegal real data for load (IEEE data not filled) + REAL_ERROR_FPOVER = 1, ///< floating overflow or underflow + REAL_ERROR_BADSTR = 2, ///< asctoreal: illegal input string + REAL_ERROR_ZERODIV = 3, ///< ediv: divide by 0 + REAL_ERROR_INTOVER = 4, ///< eetol*: integer overflow +}; + +/// Standard IEEE 754 floating point conversion function +/// \param m pointer to data +/// \param out internal IEEE format data +/// \param swt operation: +/// - 000: load trunc. float (DEC ^F) 2 bytes (m->e) +/// - 001: load float 4 bytes (m->e) +/// - 003: load double 8 bytes (m->e) +/// - 004: load long double 10 bytes (m->e) +/// - 005: load long double 12 bytes (m->e) +/// - 010: store trunc. float (DEC ^F) 2 bytes (e->m) +/// - 011: store float 4 bytes (e->m) +/// - 013: store double 8 bytes (e->m) +/// - 014: store long double 10 bytes (e->m) +/// - 015: store long double 12 bytes (e->m) +/// bit 0x80 forces little endian even for big endian processors +/// \return fpvalue_error_t + +idaman THREAD_SAFE fpvalue_error_t ida_export ieee_realcvt(void *m, fpvalue_t *out, uint16 swt); + +// Helper functions. Better use members of fpvalue_t, they are nicer. +idaman THREAD_SAFE void ida_export realtoasc(char *buf, size_t bufsize, const fpvalue_t &x, uint mode); +idaman THREAD_SAFE fpvalue_error_t ida_export asctoreal(const char **sss, fpvalue_t *out); +idaman THREAD_SAFE void ida_export eltoe(sval_t l, fpvalue_t *vout); +idaman THREAD_SAFE void ida_export eltoe64(int64 l, fpvalue_t *vout); +idaman THREAD_SAFE void ida_export eltoe64u(uint64 l, fpvalue_t *vout); +idaman THREAD_SAFE fpvalue_error_t ida_export eetol(sval_t *out, const fpvalue_t &a, bool roundflg); +idaman THREAD_SAFE fpvalue_error_t ida_export eetol64(int64 *out, const fpvalue_t &a, bool roundflg); +idaman THREAD_SAFE fpvalue_error_t ida_export eetol64u(uint64 *out, const fpvalue_t &a, bool roundflg); +idaman THREAD_SAFE fpvalue_error_t ida_export eldexp(const fpvalue_t &a, int32 pwr2, fpvalue_t *zout); +idaman THREAD_SAFE fpvalue_error_t ida_export eadd(const fpvalue_t &a, const fpvalue_t &b, fpvalue_t *zout, bool subflg); +idaman THREAD_SAFE fpvalue_error_t ida_export emul(const fpvalue_t &a, const fpvalue_t &b, fpvalue_t *zout); +idaman THREAD_SAFE fpvalue_error_t ida_export ediv(const fpvalue_t &a, const fpvalue_t &b, fpvalue_t *zout); +idaman THREAD_SAFE int ida_export ecmp(const fpvalue_t &a, const fpvalue_t &b); +idaman THREAD_SAFE fpvalue_kind_t ida_export get_fpvalue_kind(const fpvalue_t &a, uint16 reserved = 0); + +//------------------------------------------------------------------------ +/// Processor-independent representation of a floating point value. +/// IDA uses this structure to store and manipulate floating point values. +struct fpvalue_t +{ + uint16 w[FPVAL_NWORDS]; + + void clear(void) { memset(this, 0, sizeof(*this)); } + DECLARE_COMPARISONS(fpvalue_t) { return ecmp(*this, r); } + + /// Convert to the processor-independent representation. + fpvalue_error_t from_half(uint16 fpval) { return ieee_realcvt(&fpval, this, sizeof(fpval)/2-1); } + fpvalue_error_t from_float(float fpval) { return ieee_realcvt(&fpval, this, sizeof(fpval)/2-1); } + fpvalue_error_t from_double(double fpval) { return ieee_realcvt(&fpval, this, sizeof(fpval)/2-1); } + + /// Convert from the processor-independent representation. + fpvalue_error_t to_half(uint16 *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|(sizeof(*fpval)/2-1)); } + fpvalue_error_t to_float(float *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|(sizeof(*fpval)/2-1)); } + fpvalue_error_t to_double(double *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|(sizeof(*fpval)/2-1)); } + + /// Conversions for 10-byte floating point values. + fpvalue_error_t from_10bytes(const void *fpval) { return ieee_realcvt((void *)fpval, this, 4); } + fpvalue_error_t to_10bytes(void *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|4); } + + /// Conversions for 12-byte floating point values. + fpvalue_error_t from_12bytes(const void *fpval) { return ieee_realcvt((void*)fpval, this, 5); } + fpvalue_error_t to_12bytes(void *fpval) const { return ieee_realcvt(fpval, (fpvalue_t*)this, 8|5); } + + /// Convert string to IEEE. + /// \param p_str pointer to pointer to string. it will advanced. + fpvalue_error_t from_str(const char **p_str) { return asctoreal(p_str, this); } + + /// Convert IEEE to string. + /// \param mode broken down into: + /// - low byte: number of digits after '.' + /// - second byte: FPNUM_LENGTH + /// - third byte: FPNUM_DIGITS + void to_str(char *buf, size_t bufsize, uint mode) const { realtoasc(buf, bufsize, *this, mode); } + + /// Convert integer to IEEE + void from_sval(sval_t x) { eltoe(x, this); } + void from_int64(int64 x) { eltoe64(x, this); } + void from_uint64(uint64 x) { eltoe64u(x, this); } + + /// Convert IEEE to integer (+-0.5 if round) + fpvalue_error_t to_sval(sval_t *out, bool round=false) const { return eetol(out, *this, round); } + fpvalue_error_t to_int64(int64 *out, bool round=false) const { return eetol64(out, *this, round); } + fpvalue_error_t to_uint64(uint64 *out, bool round=false) const { return eetol64u(out, *this, round); } + + /// Arithmetic operations + fpvalue_error_t fadd(const fpvalue_t &y) { return eadd(*this, y, this, false); } + fpvalue_error_t fsub(const fpvalue_t &y) { return eadd(*this, y, this, true); } + fpvalue_error_t fmul(const fpvalue_t &y) { return emul(*this, y, this); } + fpvalue_error_t fdiv(const fpvalue_t &y) { return ediv(*this, y, this); } + + /// Multiply by a power of 2. + fpvalue_error_t mul_pow2(int32 power_of_2) { return eldexp(*this, power_of_2, this); } + + /// Calculate absolute value. + void eabs() { w[FPVAL_NWORDS-1] &= 0x7fff; } + + /// Is negative value? + bool is_negative() const { return (w[FPVAL_NWORDS-1] & 0x8000) != 0; } + + /// Negate. + void negate() + { + if ( w[FPVAL_NWORDS-1] != 0 ) + w[FPVAL_NWORDS-1] ^= 0x8000; + } + + /// Get value kind. + fpvalue_kind_t get_kind() const { return get_fpvalue_kind(*this, 0); } +}; + +//------------------------------------------------------------------------] +/// The exponent of 1.0 +#define IEEE_EXONE (0x3fff) + +/// \name Prototypes +/// IDP module event prototype -- should be implemented in idp +//@{ + +/// Floating point conversion function: implemented by \ph{realcvt}. +/// See ieee_realcvt + +fpvalue_error_t idaapi realcvt(void *m, fpvalue_t *out, uint16 swt); + + +/// Little endian + +fpvalue_error_t l_realcvt(void *m, fpvalue_t *out, uint16 swt); + + +/// Big endian + +fpvalue_error_t b_realcvt(void *m, fpvalue_t *out, uint16 swt); + +//@} + +/// Exponent in fpvalue_t for NaN and Inf +#define E_SPECIAL_EXP 0x7fff + +/// 0.0 +extern const fpvalue_t ieee_ezero; +#define EZERO { 0, 0000000,0000000,0000000,0000000,0000000 } + +/// 1.0 +extern const fpvalue_t ieee_eone; +#define EONE { 0, 0000000,0000000,0000000,0100000,IEEE_EXONE } + +/// 2.0 +extern const fpvalue_t ieee_etwo; + +/// 32.0 +extern const fpvalue_t ieee_e32; + +/// 6.93147180559945309417232121458176568075500134360255E-1 +extern const fpvalue_t ieee_elog2; + +/// 1.41421356237309504880168872420969807856967187537695E0 +extern const fpvalue_t ieee_esqrt2; + +/// 2/sqrt(PI) = 1.12837916709551257389615890312154517168810125865800E0 +extern const fpvalue_t ieee_eoneopi; + +/// 3.14159265358979323846264338327950288419716939937511E0 +extern const fpvalue_t ieee_epi; + +/// 5.7721566490153286060651209008240243104215933593992E-1 +extern const fpvalue_t ieee_eeul; + +#if !defined(NO_OBSOLETE_FUNCS) || defined(IEEE_SOURCE) //-[ +#define IEEE_NI (FPVAL_NWORDS+3) // Number of 16 bit words in ::eNI +#define IEEE_E 1 // Array offset to exponent +#define IEEE_M 2 // Array offset to high guard word +/// There is one more internal format used by IDA to store intermediate values. +/// - 0 : sign (0/1) +/// - 1 : exponent (based of #IEEE_EXONE). If exp = 0, value = 0. +/// - 2 : high word of mantissa (always zero after normalize) +typedef uint16 eNI[IEEE_NI]; + +#ifdef IEEE_SOURCE +# define IEEE_DEPRECATED +#else +# define IEEE_DEPRECATED DEPRECATED +#endif +inline IEEE_DEPRECATED void ecleaz(eNI x) { memset(x, 0, sizeof(eNI)); } +idaman IEEE_DEPRECATED THREAD_SAFE void ida_export emovo(const eNI a, fpvalue_t *vout); /// Move eNI => eNE +idaman IEEE_DEPRECATED THREAD_SAFE void ida_export emovi(const fpvalue_t &a, eNI vout); /// Move eNE => eNI +idaman IEEE_DEPRECATED THREAD_SAFE int ida_export eshift(eNI x, int sc); /// Shift NI format up (+) or down +/// Normalize and round off. +/// \param s the internal format number to be rounded +/// \param lost indicates whether or not the number is exact. +/// this is the so-called sticky bit. +/// \param subflg indicates whether the number was obtained +/// by a subtraction operation. In that case if lost is nonzero +/// then the number is slightly smaller than indicated. +/// \param exp the biased exponent, which may be negative. +/// the exponent field of "s" is ignored but is replaced by +/// "exp" as adjusted by normalization and rounding. +/// \param rndbase if 0 => is the rounding control. +/// else is processor defined base (rndprc) +/// \return success +idaman IEEE_DEPRECATED THREAD_SAFE bool ida_export emdnorm(eNI s, bool lost, bool subflg, int32 exp, int rndbase); + +#endif + +#endif diff --git a/idasdk76/include/intel.hpp b/idasdk76/include/intel.hpp new file mode 100644 index 0000000..e755e76 --- /dev/null +++ b/idasdk76/include/intel.hpp @@ -0,0 +1,1232 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _INTEL_HPP +#define _INTEL_HPP +#include <ua.hpp> +#include <typeinf.hpp> +#include <allins.hpp> + +#define PROC_MAXOP 5 // max number of operands +CASSERT(PROC_MAXOP <= UA_MAXOP); + +//--------------------------------- +// Intel 80x86 insn_t.auxpref bits +#define aux_lock 0x00000001 +#define aux_rep 0x00000002 +#define aux_repne 0x00000004 +#define aux_use32 0x00000008 // segment type is 32-bits +#define aux_use64 0x00000010 // segment type is 64-bits +#define aux_large 0x00000020 // offset field is 32-bit (16-bit is not enough) +#define aux_short 0x00000040 // short (byte) displacement used +#define aux_sgpref 0x00000080 // a segment prefix byte is not used +#define aux_oppref 0x00000100 // operand size prefix byte is not used +#define aux_adpref 0x00000200 // address size prefix byte is not used +#define aux_basess 0x00000400 // SS based instruction +#define aux_natop 0x00000800 // operand size is not overridden by prefix +#define aux_natad 0x00001000 // addressing mode is not overridden by prefix +#define aux_fpemu 0x00002000 // FP emulator instruction +#define aux_vexpr 0x00004000 // VEX-encoded instruction +#define aux_bnd 0x00008000 // MPX-encoded instruction +#define aux_evex 0x00010000 // EVEX-encoded instruction +#define aux_xop 0x00020000 // XOP-encoded instruction +#define aux_xacquire 0x00040000 // HLE prefix hints +#define aux_xrelease 0x00080000 // HLE prefix hints + +//--------------------------------- +// operand types and other customization: +#define o_trreg o_idpspec0 // IDP specific type +#define o_dbreg o_idpspec1 // IDP specific type +#define o_crreg o_idpspec2 // IDP specific type +#define o_fpreg o_idpspec3 // IDP specific type +#define o_mmxreg o_idpspec4 // IDP specific type +#define o_xmmreg o_idpspec5 // xmm register +#define o_ymmreg o_idpspec5+1 // ymm register +#define o_zmmreg o_idpspec5+2 // zmm register +#define o_kreg o_idpspec5+3 // opmask register + +// 04.10.97: For o_mem,o_near,o_far we keep segment information as +// segrg - number of segment register to use +// if it is == SEGREG_IMM, then the segment was specified as an immediate +// value, look at segsel. + +#define segrg specval_shorts.high +#define SEGREG_IMM 0xFFFF // this value of segrg means that + // segment selector value is in + // "segsel": +#define segsel specval_shorts.low +#define hasSIB specflag1 +#define sib specflag2 +#define rex insnpref // REX byte for 64-bit mode, or bits from the VEX byte if vexpr() + +// Op6 is used for opmask registers in EVEX. +// specflags from Op6 are used to extend insn_t. +#define evex_flags Op6.specflag2 // bits from the EVEX byte if evexpr() + +#define cr_suff specflag1 // o_crreg: D suffix for cr registers (used for CR8D) + +// bits in insn_t.evex_flags: +const int EVEX_R = 0x01; // High-16 register specifier modifier +const int EVEX_L = 0x02; // Vector length/RC +const int EVEX_z = 0x04; // Zeroing/Merging +const int EVEX_b = 0x08; // Broadcast/RC/SAE Context +const int EVEX_V = 0x10; // High-16 NDS/VIDX register specifier + +// bits in insn_t.rex: +const int REX_W = 8; // 64-bit operand size +const int REX_R = 4; // modrm reg field extension +const int REX_X = 2; // sib index field extension +const int REX_B = 1; // modrm r/m, sib base, or opcode reg fields extension +const int VEX_L = 0x80; // 256-bit operation (YMM register) + +typedef short regnum_t; + +enum RegNo +{ + R_none = -1, + R_ax = 0, + R_cx, // 1 + R_dx, // 2 + R_bx, // 3 + R_sp, // 4 + R_bp, // 5 + R_si, // 6 + R_di, // 7 + R_r8, // 8 + R_r9, // 9 + R_r10, // 10 + R_r11, // 11 + R_r12, // 12 + R_r13, // 13 + R_r14, // 14 + R_r15, // 15 + + R_al, + R_cl, + R_dl, + R_bl, + R_ah, + R_ch, + R_dh, + R_bh, + + R_spl, + R_bpl, + R_sil, + R_dil, + + R_ip, + + R_es, // 0 + R_cs, // 1 + R_ss, // 2 + R_ds, // 3 + R_fs, + R_gs, + + R_cf, // main cc's + R_zf, + R_sf, + R_of, + + R_pf, // additional cc's + R_af, + R_tf, + R_if, + R_df, + + R_efl, // eflags + + // the following registers will be used in the disassembly + // starting from ida v5.7 + + R_st0, // floating point registers (not used in disassembly) + R_st1, + R_st2, + R_st3, + R_st4, + R_st5, + R_st6, + R_st7, + R_fpctrl,// fpu control register + R_fpstat,// fpu status register + R_fptags,// fpu tags register + + R_mm0, // mmx registers + R_mm1, + R_mm2, + R_mm3, + R_mm4, + R_mm5, + R_mm6, + R_mm7, + + R_xmm0, // xmm registers + R_xmm1, + R_xmm2, + R_xmm3, + R_xmm4, + R_xmm5, + R_xmm6, + R_xmm7, + R_xmm8, + R_xmm9, + R_xmm10, + R_xmm11, + R_xmm12, + R_xmm13, + R_xmm14, + R_xmm15, + R_mxcsr, + + R_ymm0, // AVX 256-bit registers + R_ymm1, + R_ymm2, + R_ymm3, + R_ymm4, + R_ymm5, + R_ymm6, + R_ymm7, + R_ymm8, + R_ymm9, + R_ymm10, + R_ymm11, + R_ymm12, + R_ymm13, + R_ymm14, + R_ymm15, + + R_bnd0, // MPX registers + R_bnd1, + R_bnd2, + R_bnd3, + + R_xmm16, // AVX-512 extended XMM registers + R_xmm17, + R_xmm18, + R_xmm19, + R_xmm20, + R_xmm21, + R_xmm22, + R_xmm23, + R_xmm24, + R_xmm25, + R_xmm26, + R_xmm27, + R_xmm28, + R_xmm29, + R_xmm30, + R_xmm31, + + R_ymm16, // AVX-512 extended YMM registers + R_ymm17, + R_ymm18, + R_ymm19, + R_ymm20, + R_ymm21, + R_ymm22, + R_ymm23, + R_ymm24, + R_ymm25, + R_ymm26, + R_ymm27, + R_ymm28, + R_ymm29, + R_ymm30, + R_ymm31, + + R_zmm0, // AVX-512 ZMM registers + R_zmm1, + R_zmm2, + R_zmm3, + R_zmm4, + R_zmm5, + R_zmm6, + R_zmm7, + R_zmm8, + R_zmm9, + R_zmm10, + R_zmm11, + R_zmm12, + R_zmm13, + R_zmm14, + R_zmm15, + R_zmm16, + R_zmm17, + R_zmm18, + R_zmm19, + R_zmm20, + R_zmm21, + R_zmm22, + R_zmm23, + R_zmm24, + R_zmm25, + R_zmm26, + R_zmm27, + R_zmm28, + R_zmm29, + R_zmm30, + R_zmm31, + + R_k0, // AVX-512 opmask registers + R_k1, + R_k2, + R_k3, + R_k4, + R_k5, + R_k6, + R_k7, + + R_last, +}; + +CASSERT(R_last == 173); + +inline bool is_segreg(int r) { return r >= R_es && r <= R_gs; } +inline bool is_fpureg(int r) { return r >= R_st0 && r <= R_st7; } +inline bool is_mmxreg(int r) { return r >= R_mm0 && r <= R_mm7; } +inline bool is_xmmreg(int r) { return r >= R_xmm0 && r <= R_xmm15; } +inline bool is_ymmreg(int r) { return r >= R_ymm0 && r <= R_ymm15; } + +int cvt_to_wholereg(int _reg, bool allow_high_byte_regs); // byte reg -> whole reg +int calc_dbg_reg_index(const char *name); + +//------------------------------------------------------------------------- +// is conditional branch? +inline bool insn_jcc(const insn_t &insn) +{ + switch ( insn.itype ) + { + case NN_ja: + case NN_jae: + case NN_jb: + case NN_jbe: + case NN_jc: + case NN_je: + case NN_jg: + case NN_jge: + case NN_jl: + case NN_jle: + case NN_jna: + case NN_jnae: + case NN_jnb: + case NN_jnbe: + case NN_jnc: + case NN_jne: + case NN_jng: + case NN_jnge: + case NN_jnl: + case NN_jnle: + case NN_jno: + case NN_jnp: + case NN_jns: + case NN_jnz: + case NN_jo: + case NN_jp: + case NN_jpe: + case NN_jpo: + case NN_js: + case NN_jz: + return true; + } + return false; +} + +//------------------------------------------------------------------------- +inline bool insn_default_opsize_64(const insn_t &insn) +{ + if ( insn_jcc(insn) ) + return true; + switch ( insn.itype ) + { + // use ss + case NN_pop: + case NN_popf: + case NN_popfq: + case NN_push: + case NN_pushf: + case NN_pushfq: + case NN_retn: + case NN_retf: + case NN_retnq: + case NN_retfq: + case NN_call: + case NN_callfi: + case NN_callni: + case NN_enter: + case NN_enterq: + case NN_leave: + case NN_leaveq: + + // near branches + case NN_jcxz: + case NN_jecxz: + case NN_jrcxz: + case NN_jmp: + case NN_jmpni: + case NN_jmpshort: + case NN_loop: + case NN_loopq: + case NN_loope: + case NN_loopqe: + case NN_loopne: + case NN_loopqne: + return true; + } + return false; +} + +inline bool mode16(const insn_t &insn) { return (insn.auxpref & (aux_use32|aux_use64)) == 0; } // 16-bit mode? +inline bool mode32(const insn_t &insn) { return (insn.auxpref & aux_use32) != 0; } // 32-bit mode? +inline bool mode64(const insn_t &insn) { return (insn.auxpref & aux_use64) != 0; } // 64-bit mode? +inline bool natad(const insn_t &insn) { return (insn.auxpref & aux_natad) != 0; } // natural address size (no prefixes)? +inline bool natop(const insn_t &insn) { return (insn.auxpref & aux_natop) != 0; } // natural operand size (no prefixes)? +inline bool vexpr(const insn_t &insn) { return (insn.auxpref & aux_vexpr) != 0; } // VEX encoding used +inline bool evexpr(const insn_t &insn) { return (insn.auxpref & aux_evex) != 0; } // EVEX encoding used +inline bool xopexpr(const insn_t &insn) { return (insn.auxpref & aux_xop) != 0; } // XOP encoding used + +inline bool ad16(const insn_t &insn) // is current addressing 16-bit? +{ + int p = insn.auxpref & (aux_use32|aux_use64|aux_natad); + return p == aux_natad || p == aux_use32; +} + +inline bool ad32(const insn_t &insn) // is current addressing 32-bit? +{ + int p = insn.auxpref & (aux_use32|aux_use64|aux_natad); + return p == (aux_natad|aux_use32) + || p == 0 + || p == aux_use64; +} + +inline bool ad64(const insn_t &insn) // is current addressing 64-bit? +{ +#ifdef __EA64__ + int p = insn.auxpref & (aux_use32|aux_use64|aux_natad); + return p == (aux_natad|aux_use64); +#else + qnotused(insn); + return false; +#endif +} + +inline bool op16(const insn_t &insn) // is current operand size 16-bit? +{ + int p = insn.auxpref & (aux_use32|aux_use64|aux_natop); + return p == aux_natop // 16-bit segment, no prefixes + || p == aux_use32 // 32-bit segment, 66h + || p == aux_use64 && (insn.rex & REX_W) == 0; // 64-bit segment, 66h, no rex.w +} + +inline bool op32(const insn_t &insn) // is current operand size 32-bit? +{ + int p = insn.auxpref & (aux_use32|aux_use64|aux_natop); + return p == 0 // 16-bit segment, 66h + || p == (aux_use32|aux_natop) // 32-bit segment, no prefixes + || p == (aux_use64|aux_natop) && (insn.rex & REX_W) == 0; // 64-bit segment, 66h, no rex.w +} + +inline bool op64(const insn_t &insn) // is current operand size 64-bit? +{ +#ifdef __EA64__ + return mode64(insn) + && ((insn.rex & REX_W) != 0 + || natop(insn) && insn_default_opsize_64(insn)); // 64-bit segment, rex.w or insns-64 +#else + qnotused(insn); + return false; +#endif +} + +inline bool op256(const insn_t &insn) // is VEX.L == 1 or EVEX.L'L == 01? +{ + return (insn.rex & VEX_L) != 0 + && (vexpr(insn) + || xopexpr(insn) + || evexpr(insn) && (insn.evex_flags & EVEX_L) == 0); +} + +inline bool op512(const insn_t &insn) // is EVEX.L'L == 10? +{ + return evexpr(insn) && (insn.rex & VEX_L) == 0 && (insn.evex_flags & EVEX_L) != 0; +} + +inline bool is_vsib(const insn_t &insn) // does instruction use VSIB variant of the sib byte? +{ + switch ( insn.itype ) + { + case NN_vgatherdps: + case NN_vgatherdpd: + case NN_vgatherqps: + case NN_vgatherqpd: + case NN_vpgatherdd: + case NN_vpgatherdq: + case NN_vpgatherqd: + case NN_vpgatherqq: + + case NN_vscatterdps: + case NN_vscatterdpd: + case NN_vscatterqps: + case NN_vscatterqpd: + case NN_vpscatterdd: + case NN_vpscatterdq: + case NN_vpscatterqd: + case NN_vpscatterqq: + + case NN_vgatherpf0dps: + case NN_vgatherpf0qps: + case NN_vgatherpf0dpd: + case NN_vgatherpf0qpd: + case NN_vgatherpf1dps: + case NN_vgatherpf1qps: + case NN_vgatherpf1dpd: + case NN_vgatherpf1qpd: + + case NN_vscatterpf0dps: + case NN_vscatterpf0qps: + case NN_vscatterpf0dpd: + case NN_vscatterpf0qpd: + case NN_vscatterpf1dps: + case NN_vscatterpf1qps: + case NN_vscatterpf1dpd: + case NN_vscatterpf1qpd: + return true; + } + return false; +} + +inline regnum_t vsib_index_fixreg(const insn_t &insn, regnum_t index) +{ + switch ( insn.itype ) + { + case NN_vscatterdps: + case NN_vscatterqps: + case NN_vscatterqpd: + case NN_vpscatterdd: + case NN_vpscatterqd: + case NN_vpscatterqq: + + case NN_vpgatherdd: + case NN_vpgatherqd: + case NN_vpgatherqq: + case NN_vgatherdps: + case NN_vgatherqps: + case NN_vgatherqpd: + if ( index > 15 ) + index += op512(insn) ? R_zmm0 : op256(insn) ? (R_ymm16 - 16) : (R_xmm16 - 16); + else + index += op512(insn) ? R_zmm0 : op256(insn) ? R_ymm0 : R_xmm0; + break; + + case NN_vscatterdpd: + case NN_vpscatterdq: + + case NN_vgatherdpd: + case NN_vpgatherdq: + if ( index > 15 ) + index += op512(insn) ? (R_ymm16 - 16) : (R_xmm16 - 16); + else + index += op512(insn) ? R_ymm0 : R_xmm0; + break; + + case NN_vgatherpf0dps: + case NN_vgatherpf0qps: + case NN_vgatherpf0qpd: + case NN_vgatherpf1dps: + case NN_vgatherpf1qps: + case NN_vgatherpf1qpd: + + case NN_vscatterpf0dps: + case NN_vscatterpf0qps: + case NN_vscatterpf0qpd: + case NN_vscatterpf1dps: + case NN_vscatterpf1qps: + case NN_vscatterpf1qpd: + index += R_zmm0; + break; + + case NN_vgatherpf0dpd: + case NN_vgatherpf1dpd: + case NN_vscatterpf0dpd: + case NN_vscatterpf1dpd: + if ( index > 15 ) + index += R_ymm16 - 16; + else + index += R_ymm0; + break; + } + return index; +} + +inline int sib_base(const insn_t &insn, const op_t &x) // get extended sib base +{ + int base = x.sib & 7; +#ifdef __EA64__ + if ( insn.rex & REX_B ) + base |= 8; +#else + qnotused(insn); +#endif + return base; +} + +inline regnum_t sib_index(const insn_t &insn, const op_t &x) // get extended sib index +{ + regnum_t index = regnum_t((x.sib >> 3) & 7); +#ifdef __EA64__ + if ( (insn.rex & REX_X) != 0 ) + index |= 8; +#endif + if ( is_vsib(insn) ) + { + if ( (insn.evex_flags & EVEX_V) != 0 ) + index |= 16; + index = vsib_index_fixreg(insn, index); + } + return index; +} + +inline int sib_scale(const op_t &x) +{ + int scale = (x.sib >> 6) & 3; + return scale; +} + +// get the base register of the operand with a displacement +// NB: for 16-bit code, returns a phrase number +// use x86_base_reg() if you need to handle 16-bit instructions +inline int x86_base(const insn_t &insn, const op_t &x) +{ + return x.hasSIB ? sib_base(insn, x) : x.phrase; +} + +// get the base register of the operand with a displacement +// returns correct register for 16-bit code too +inline int x86_base_reg(const insn_t &insn, const op_t &x) +{ + if ( x.hasSIB ) + { + if ( x.type == o_mem ) + return R_none; + return sib_base(insn, x); // base register is encoded in the SIB + } + else if ( !ad16(insn) ) + { + return x.phrase; // 'phrase' contains the base register number + } + else if ( x.phrase == ushort(R_none) ) + { + return R_sp; + } + switch ( x.phrase ) + { + case 0: // [BX+SI] + case 1: // [BX+DI] + case 7: // [BX] + return R_bx; + case 2: // [BP+SI] + case 3: // [BP+DI] + case 6: // [BP] + return R_bp; + case 4: // [SI] + return R_si; + case 5: // [DI] + return R_di; + default: + INTERR(10259); + } +} + +const int INDEX_NONE = 4; // no index register is present +// get the index register of the operand with a displacement +inline int x86_index(const insn_t &insn, const op_t &x) +{ + return x.hasSIB ? sib_index(insn, x) : INDEX_NONE; +} + +inline int x86_index_reg(const insn_t &insn, const op_t &x) +{ + if ( x.hasSIB ) + { + int idx = sib_index(insn, x); + if ( idx != INDEX_NONE ) + return idx; + return R_none; + } + if ( !ad16(insn) ) + return R_none; + switch ( x.phrase ) + { + case 0: // [BX+SI] + case 2: // [BP+SI] + return R_si; + case 1: // [BX+DI] + case 3: // [BP+DI] + return R_di; + case 4: // [SI] + case 5: // [DI] + case 7: // [BX] + case 6: // [BP] + return R_none; + default: + INTERR(10260); + } +} +// get the scale factor of the operand with a displacement +inline int x86_scale(const op_t &x) +{ + return x.hasSIB ? sib_scale(x) : 0; +} + +// does the operand have a displacement? +inline int has_displ(const op_t &x) +{ + return x.type == o_displ || x.type == o_mem && x.hasSIB; +} + +// does the insn refer to the TLS variable? +inline bool has_tls_segpref(const insn_t &insn) +{ + if ( insn.segpref == 0 ) + return false; + return mode64(insn) && insn.segpref == R_fs + || mode32(insn) && insn.segpref == R_gs; +} + +// should we treat the memory operand as a displacement? +inline bool mem_as_displ(const insn_t &insn, const op_t &x) +{ + // the operand should be an offset and it should be the TLS variable + // or the second operand of "lea" instruction + // .text:08000000 mov eax, gs:(ti1 - static_TP) + // .text:08000E8F lea ecx, (_ZN4dmngL4sessE - _GLOBAL_OFFSET_TABLE_) + return (has_tls_segpref(insn) || insn.itype == NN_lea) + && is_off(get_flags(insn.ea), x.n); +} + +// does the operand refer to stack? (sp or bp based) +bool is_stack_ref(const insn_t &insn, const op_t &x, int breg); + +// return addressing width in form of dt_... constant +inline op_dtype_t address_dtype(const insn_t &insn) +{ + return char(ad64(insn) ? dt_qword : ad32(insn) ? dt_dword : dt_word); +} + +// return operand width in form of dt_... constant +inline op_dtype_t operand_dtype(const insn_t &insn) +{ + return char(op64(insn) ? dt_qword : op32(insn) ? dt_dword : op16(insn) ? dt_word : dt_byte); +} + +inline bool is_io_insn(const insn_t &insn) +{ + return insn.itype == NN_ins + || insn.itype == NN_outs + || insn.itype == NN_out + || insn.itype == NN_in; +} + +//--------------------------------- +#define PROCMOD_NODE_NAME "$ vmm functions" +#define PROCMOD_NAME pc + +const char callee_tag = 'A'; +const char fbase_tag = 'b'; +const char frame_tag = 'f'; +const char purge_tag = 'p'; +const char ret_tag = 'r'; +const char pushinfo_tag = 's'; +const char is_ptr_tag = 'P'; +const char finally_tag = 'F'; +const char handler_tag = 'h'; +const char vxd_tag1 = 'V'; +const char vxd_tag2 = 'W'; + +// fbase reg is a register used to access data for the current function +// it is usually initialized by __i686_get_pc_thunk() function + +struct fbase_reg_t +{ + ea_t value; + ea_t minea; // address where the fbase reg is defined + int16 reg; +}; + +// the second operand of lea instruction should not be treated as memory reference +// unless there is cs: prefix or the user has specified 'offset' flag +// in other cases lea is used for arbirary calculations +inline bool is_arith_lea(const insn_t &insn, const op_t &x) +{ + return insn.itype == NN_lea + && x.segrg != R_cs + && !is_off(get_flags(insn.ea), x.n); +} + +// the following operand types are ignored for imul's third operand +inline bool is_forbidden_imul_flag(const insn_t &insn, const op_t &x, flags_t F) +{ + if ( x.n == 2 && insn.Op2.shown() ) + return is_off1(F) || is_stroff1(F) || is_stkvar1(F); + return false; +} + +inline bool is_push_ecx(uchar b) +{ + return b == 0x51; // push ecx +} + +inline bool is_push_eax(uchar b) +{ + return b == 0x50; // push eax +} + +inline bool is_push_edx(uchar b) +{ + return b == 0x52; // push edx +} + +inline bool is_push_ebx(uchar b) +{ + return b == 0x53; // push ebx +} + +inline bool is_volatile_reg(int r) +{ + return r != R_bx + && r != R_bp + && r != R_si + && r != R_di + && r != R_r12 + && r != R_r13 + && r != R_r14 + && r != R_r15; +} + +//------------------------------------------------------------------ +struct pushreg_t +{ + ea_t ea; // instruction ea + sval_t off; // offset from the frame top (sp delta) + sval_t width; // register width (or number of allocated bytes) + regnum_t reg; // register number (R_none means stack space allocation) + uint16 flags; // additional flags +#define PRF_NONE 0x0000 // Entry describes a push or an allocation +#define PRF_MOVE 0x0001 // Entrz describes a register save by a move instruction +#define PRF_SPILL 0x0002 // Indicates that entry is located before local stack region +#define PRF_MASK (PRF_MOVE | PRF_SPILL) +}; + +struct pushinfo_t +{ + enum { PUSHINFO_VERSION = 4 }; + int flags; +#define PINF_SEHCALL 0x0001 // call to SEH_prolog is present +#define PINF_SEHMAN 0x0002 // Manual SEH setup +#define PINF_COOKIE 0x0004 // Has security cookie +#define PINF_ALIGNED 0x0008 // Lvars are align stred (visual studio) +#define PINF_VARARG 0x0010 // Vararg prolog (currently used for gcc64) +#define PINF_BPOFF 0x0020 // xmm_stkoff/reg_stkoff are from rbp (otherwise from rsp) +#define PINF_HAVE_SSIZE 0x0040 // pushinfo_t structure contains its own size (field 'cb') +#define PINF_PSI_FLAGS 0x0080 // pushreg_t structure contains flags field + qvector<pushreg_t> psi; // stack allocation instructions + ssize_t bpidx = -1; // index into psi + uint32 spoiled = 0; // bitmask of spoiled registers at the end of prolog + + eavec_t prolog_insns; // additional prolog instruction addresses + // (in addition to instructions from psi) + + typedef qvector<eavec_t> pop_info_t; + pop_info_t pops; // pop insns for pushs (indexes shifted by one) + // in other words, this is epilog instructions + // index 0: epilog insns not linked to a push insn + // 1..psi.size(): epilog insns for each push insn + // usually there will be only one pop for each push. + // but there might be several pops for each push. + // (because the function has several returns) + + int eh_type; // function has exception handling + // low 16 bits: type, high 16 bits: version +#define EH_NONE 0 // no EH found +#define EH_VCSEH 1 // SEH (__except_handlerN, __SEH_prologN) +#define EH_VCCPPEH 2 // MSVC C++ EH (_EH_prolog[N]) + int seh_ver() + { + if ( (eh_type & 0xFFFF) == EH_VCSEH ) + return (eh_type >> 16) & 0xFFFF; + return 0; + } + int eh_ver() + { + if ( (eh_type & 0xFFFF) == EH_VCCPPEH ) + return (eh_type >> 16) & 0xFFFF; + return 0; + } + + ea_t eh_info = BADADDR; // for SEH: scopetable address, for C++ EH: __ehhandler address + + // for gcc64 vararg (see PINF_VARARG): + sval_t xmm_stkoff = 0; // offset from ebp to xmm savearea + sval_t reg_stkoff = 0; // offset from ebp to gpreg savearea + // these 2 offsets are either from rsp or rbp + // see PINF_BPOFF for that + int xmm_nsaved = 0; // number of saved xmm regs + int reg_nsaved = 0; // number of saved general purpose regs + + int cb = sizeof(pushinfo_t); // size of this structure + + pushinfo_t(void) : flags(PINF_HAVE_SSIZE|PINF_PSI_FLAGS), eh_type(EH_NONE) {} +}; + +enum spec_func_type_t +{ + SF_NONE, + SF_EH_PROLOG, + SF_SEH_PROLOG, + SF_SEH_EPILOG, + SF_ALLOCA, + SF_CHK, + SF_SYSINIT, + SF_EH_EPILOG, + SF_LSTRCATN, +}; + +inline bool is_mingw_abi(void) +{ + if ( default_compiler() != COMP_MS ) + return false; // "mingw" abi can be defined only for MSVC + qstring abiname; + get_abi_name(&abiname); + return abiname == "mingw"; +} + +inline bool is_msabi(void) +{ + comp_t cc = default_compiler(); + return cc == COMP_MS || cc == COMP_UNK && inf_get_filetype() == f_PE; +} + +inline int pc_shadow_area_size() +{ + return inf_is_64bit() && is_msabi() ? 4 * 8 : 0; +} + +struct regval_t; +typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); + +// Structure where information about a mmx/xmm/ymm type is returned +struct mmtype_t +{ + const char *name; + const type_t *type; + const type_t *fields; + tinfo_t tif; +}; + +//---------------------------------------------------------------------- +// The following events are supported by the PC module in the processor_t::notify() function +namespace pc_module_t +{ + enum event_codes_t + { + ev_set_difbase = processor_t::ev_loader, + // set AFIDP_DIFBASE flag + // in: int onoff + // Returns: nothing + ev_restore_pushinfo,// Restore function prolog info from the database + // in: pushinfo_t *pi + // ea_t func_start + // Returns: 1-ok, otherwise-failed + ev_save_pushinfo, // Save function prolog info to the database + // in: ea_t func_start + // pushinfo_t *pi + // Returns: 1-ok, otherwise-failed + ev_prolog_analyzed, // This event is generated by the PC module + // at the end of prolog analysis. Plugins may + // hook to it and improve the analysis. + // in: ea_t first_past_prolog_insn + // pushinfo_t *pi + // Returns: 1-ok, 2-ok but do not automatically verify epilog + ev_verify_epilog, // Verify function epilog + // in: int *answer + // pushinfo_t *pi + // const insn_t *insn + // 'insn' structure must be filled with the first epilog instruction + // number of verified epilog instructions will be in the 'answer' + // returns: 1-ok, otherwise-failed + obsolete_ev_find_reg_value, // not used anymore, use ev_find_reg_value + ev_dbgtools_path, // Returns the configuration value of the debugging tools path (from IDA.CFG) + // in: char *path + // size_t path_size + // returns: 1-if value is set, 0-if value not set in IDA.CFG + ev_is_get_pc_thunk, // Detect get_pc_thunk calls + // in: RegNo *p_reg, + // ea_t *p_end + // const insn_t *ins + // returns: 1-found, -1-not found, 0-not implemented + + ev_vxd_loaded, // notification: a virtual device driver (Vxd) is loaded + + ev_get_borland_template_node, + // out: netnode *node + // returns: 1-found, -1-not found + ev_clear_borland_template_node, + // returns: nothing + ev_borland_template,// Applies Borland RTTI template for the given address + // in: ea_t ea, + // bool bp_mode if false - bc + // bool recursive + // returns: 1-created, -1-not created + ev_get_segval, // Get segment for the specified instruction operand + // in: ea_t *out, + // const insn_t *insn, + // const op_t *x + // returns: 1-success + ev_get_idpflags, // Get idpflags + // in: uint32 *idpflags + // returns: 1 success, fill IDPFLAGS + ev_get_ret_target, // Some 'ret' insns do not return from the function but are used for short jumps + // (for example: push off; ret). The following functions mark such 'ret' instructions. + // in: ea_t ea + // ea_t *target + // returns: 1 success, fill TARGET + ev_set_ret_target, // in: ea_t ea + // ea_t target + ev_del_ret_target, // in: ea_t ea + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline void set_difbase(int onoff) + { + processor_t::notify(idp_ev(ev_set_difbase), onoff); + } + + inline bool restore_pushinfo(pushinfo_t *pi, ea_t func_start) + { + return processor_t::notify(idp_ev(ev_restore_pushinfo), pi, func_start) == 1; + } + + inline bool save_pushinfo(ea_t func_start, pushinfo_t *pi) + { + return processor_t::notify(idp_ev(ev_restore_pushinfo), func_start, pi) == 1; + } + + inline int prolog_analyzed(ea_t first_past_prolog_insn, pushinfo_t *pi) + { + return processor_t::notify(idp_ev(ev_prolog_analyzed), first_past_prolog_insn, pi); + } + + inline bool verify_epilog(int *answer, pushinfo_t *pi, const insn_t &insn) + { + return processor_t::notify(idp_ev(ev_verify_epilog), answer, pi, &insn) == 1; + } + + inline bool dbgtools_path(char *path, size_t path_size) + { + return processor_t::notify(idp_ev(ev_dbgtools_path), path, path_size) == 1; + } + + inline int is_get_pc_thunk(RegNo *p_reg, ea_t *p_end, const insn_t &insn) + { + return processor_t::notify(idp_ev(ev_is_get_pc_thunk), p_reg, p_end, &insn); + } + + inline int vxd_loaded() + { + return processor_t::notify(idp_ev(ev_vxd_loaded)); + } + + inline bool get_borland_template_node(netnode *node) + { + return processor_t::notify(idp_ev(ev_get_borland_template_node), node) > 0; + } + + inline void clear_borland_template_node(void) + { + processor_t::notify(idp_ev(ev_clear_borland_template_node)); + } + + inline bool borland_template(ea_t ea, bool bp_mode, bool recursive) + { + return processor_t::notify(idp_ev(ev_borland_template), + ea, + bp_mode, + recursive) > 0; + } + + inline ea_t get_segval(const insn_t &insn, const op_t &x) + { + ea_t ea = BADADDR; + processor_t::notify(idp_ev(ev_get_segval), &ea, &insn, &x); + return ea; + } + + inline uint32 get_idpflags() + { + uint32 idpflags; + processor_t::notify(idp_ev(ev_get_idpflags), &idpflags); + return idpflags; + } + + inline bool get_ret_target(ea_t ea, ea_t *target) + { + return processor_t::notify(idp_ev(ev_get_ret_target), ea, target) == 1; + } + + inline void set_ret_target(ea_t ea, ea_t target) + { + processor_t::notify(idp_ev(ev_set_ret_target), ea, target); + } + + inline void del_ret_target(ea_t ea) + { + processor_t::notify(idp_ev(ev_del_ret_target), ea); + } + +} + +//------------------------------------------------------------------------- +#define AFIDP_PUSH 0x0001 // push seg; push num; is converted to offset +#define AFIDP_NOP 0x0002 // db 90h after jmp is converted to nop + +#define AFIDP_MOVOFF 0x0004 // mov reg, numoff <- convert to offset + // mov segreg, immseg + +#define AFIDP_MOVOFF2 0x0008 // mov z, numoff <- convert to offset + // mov z, immseg + // where z - o_mem, o_displ +#define AFIDP_ZEROINS 0x0010 // allow zero opcode instructions: + // add [bx+si], al (16bit) + // add [eax], al (32bit) + // add [rax], al (64bit) + +#define AFIDP_BRTTI 0x0020 // Advanced analysis of Borlands RTTI +#define AFIDP_UNKRTTI 0x0040 // -"- with 'unknown_libname' +#define AFIDP_EXPFUNC 0x0080 // for PE? bc(ms?) - expanding + // function (exception subblock) +#define AFIDP_DIFBASE 0x0100 // Allow references with different segment bases +#define AFIDP_NOPREF 0x0200 // Don't display superfluous prefixes +#define AFIDP_NOVXD 0x0400 // Don't interpret int 20 as VxDcall +#define AFIDP_NOFPEMU 0x0800 // Disable FPU emulation instructions +#define AFIDP_SHOWRIP 0x1000 // Explicit RIP-addressing +#define AFIDP_NOSEH 0x2000 // Disable SEH/EH analysis +#define AFIDP_INT3STOP 0x4000 // int 3 may stop code flow + // call <func> + // int 3 <- this is likely a no-return guard +#define AFIDP_NOAGGRJMPS 0x8000 // Don't aggressively convert jumps to thunk functions + // 'NO' is used to simplify upgrading existing idbs + +inline bool should_af_push(void) { return (pc_module_t::get_idpflags() & AFIDP_PUSH) != 0; } +inline bool should_af_nop(void) { return (pc_module_t::get_idpflags() & AFIDP_NOP) != 0; } +inline bool should_af_movoff(void) { return (pc_module_t::get_idpflags() & AFIDP_MOVOFF) != 0; } +inline bool should_af_movoff2(void) { return (pc_module_t::get_idpflags() & AFIDP_MOVOFF2) != 0; } +inline bool should_af_zeroins(void) { return (pc_module_t::get_idpflags() & AFIDP_ZEROINS) != 0; } +inline bool should_af_brtti(void) { return (pc_module_t::get_idpflags() & AFIDP_BRTTI) != 0; } +inline bool should_af_urtti(void) { return (pc_module_t::get_idpflags() & AFIDP_UNKRTTI) != 0; } +inline bool should_af_fexp(void) { return (pc_module_t::get_idpflags() & AFIDP_EXPFUNC) != 0; } +inline bool should_af_difbase(void) { return (pc_module_t::get_idpflags() & AFIDP_DIFBASE) != 0; } +inline bool should_af_nopref(void) { return (pc_module_t::get_idpflags() & AFIDP_NOPREF) != 0; } +inline bool should_af_vxd(void) { return (pc_module_t::get_idpflags() & AFIDP_NOVXD) == 0; } +inline bool should_af_fpemu(void) { return (pc_module_t::get_idpflags() & AFIDP_NOFPEMU) == 0; } +inline bool should_af_showrip(void) { return (pc_module_t::get_idpflags() & AFIDP_SHOWRIP) != 0; } +inline bool should_af_seh(void) { return (pc_module_t::get_idpflags() & AFIDP_NOSEH) == 0; } +inline bool should_af_int3stop(void) { return (pc_module_t::get_idpflags() & AFIDP_INT3STOP) != 0; } +inline bool should_af_aggrjmps(void) { return (pc_module_t::get_idpflags() & AFIDP_NOAGGRJMPS) == 0; } + +//------------------------------------------------------------------------- +inline bool get_ret_target(ea_t ea, ea_t *target) { return pc_module_t::get_ret_target(ea, target); } +inline void set_ret_target(ea_t ea, ea_t target) { return pc_module_t::set_ret_target(ea, target); } +inline void del_ret_target(ea_t ea) { return pc_module_t::del_ret_target(ea); } + +//------------------------------------------------------------------------- +// Don't use the following define's with underscores at the start! +#define _PT_486p 0x00000001 +#define _PT_486r 0x00000002 +#define _PT_386p 0x00000004 +#define _PT_386r 0x00000008 +#define _PT_286p 0x00000010 +#define _PT_286r 0x00000020 +#define _PT_086 0x00000040 +#define _PT_586p 0x00000080 // Pentium real mode +#define _PT_586r 0x00000100 // Pentium protected mode +#define _PT_686r 0x00000200 // Pentium Pro real +#define _PT_686p 0x00000400 // Pentium Pro protected +#define _PT_mmx 0x00000800 // MMX extensions +#define _PT_pii 0x00001000 // Pentium II +#define _PT_3d 0x00002000 // 3DNow! extensions +#define _PT_piii 0x00004000 // Pentium III +#define _PT_k7 0x00008000 // AMD K7 +#define _PT_p4 0x00010000 // Pentium 4 +#define _PT_sse3 0x00020000 // SSE3 + SSSE3 +#define _PT_sse4 0x00040000 // SSE4.1 + SSE4.2 + +// +// The following values mean 'is XXX processor or better?' +// + +#define PT_sse4 _PT_sse4 +#define PT_sse3 (_PT_sse3 | _PT_sse4 ) +#define PT_p4 ( PT_sse3 | _PT_p4 ) +#define PT_k7 ( PT_p4 | _PT_k7 ) +#define PT_piii ( PT_k7 | _PT_piii ) +#define PT_k62 ( PT_piii | _PT_3d ) +#define PT_3d _PT_3d +#define PT_pii ( PT_piii | _PT_pii ) +#define PT_mmx (_PT_mmx | _PT_3d ) +#define PT_686p ( PT_pii | _PT_686p ) +#define PT_686r ( PT_686p | _PT_686r ) +#define PT_586p ( PT_686r | _PT_586p ) +#define PT_586r ( PT_586p | _PT_586r ) +#define PT_486p ( PT_586r | _PT_486p ) +#define PT_486r ( PT_486p | _PT_486r ) +#define PT_386p ( PT_486r | _PT_386p ) +#define PT_386r ( PT_386p | _PT_386r ) +#define PT_286p ( PT_386r | _PT_286p ) +#define PT_286r ( PT_286p | _PT_286r ) +#define PT_086 ( PT_286r | _PT_086 ) + +// +// The following values mean 'is exactly XXX processor?' +// + +#define PT_ismmx (_PT_mmx ) +#define PT_is686 (_PT_686r | _PT_686p) +#define PT_is586 (_PT_586r | _PT_586p) +#define PT_is486 (_PT_486r | _PT_486p) +#define PT_is386 (_PT_386r | _PT_386p) +#define PT_is286 (_PT_286r | _PT_286p) +#define PT_is086 (_PT_086) + +//--------------------------------------------------------------------- +inline bool isProtected(uint32 type) +{ + return (type + & (_PT_286p + | _PT_386p + | _PT_486p + | _PT_586p + | _PT_686p + | _PT_pii)) != 0; +} + +inline bool isAMD(uint32 type) { return (type & PT_k7 ) != 0; } +inline bool isp4(uint32 type) { return (type & PT_p4 ) != 0; } +inline bool isp3(uint32 type) { return (type & PT_piii) != 0; } +inline bool is3dnow(uint32 type) { return (type & PT_3d ) != 0; } +inline bool ismmx(uint32 type) { return (type & PT_mmx ) != 0; } +inline bool isp2(uint32 type) { return (type & PT_pii ) != 0; } +inline bool is686(uint32 type) { return (type & PT_686r) != 0; } +inline bool is586(uint32 type) { return (type & PT_586r) != 0; } +inline bool is486(uint32 type) { return (type & PT_486r) != 0; } +inline bool is386(uint32 type) { return (type & PT_386r) != 0; } // is 386 or better ? +inline bool is286(uint32 type) { return (type & PT_286r) != 0; } // is 286 or better ? + +#endif // _INTEL_HPP diff --git a/idasdk76/include/jumptable.hpp b/idasdk76/include/jumptable.hpp new file mode 100644 index 0000000..d5cfa94 --- /dev/null +++ b/idasdk76/include/jumptable.hpp @@ -0,0 +1,839 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __JUMPTABLE_HPP +#define __JUMPTABLE_HPP + +#include <pro.h> +#include <ua.hpp> // op_t +#include <nalt.hpp> // switch_info_t, jumptable_info_t + +// Class to check for a jump table sequence. +// This class should be used in preference to the hard encoding of jump table sequences +// because it allows for: +// - instruction rescheduling +// - intermingling the jump sequence with other instructions +// - sequence variants +// +// For this class: +// all instructions of the sequence are numbered starting from the last instruction. +// The last instruction has the number 0. +// The instruction before the last instruciton has the number 1, etc. +// There is a virtual function jpiN() for each instruction of the sequence +// These functions return true if 'insn' is filled with the required instruction +// +// The comparison is made in the match() function: +// +// ea points to the last instruction of the sequence (instruction #0) +// +// the 'depends' array contains dependencies between the instructions of the sequence. +// For example: +// ARM thumb LDRH switch +// 7 SUB Ra, #minv (optional) +// 6 CMP Ra, #size +// 5 BCS defea +// 4 ADR Rb, jt +// 3 ADD Rb, Rb, Ra +// 2 LDRH Rb, [Rb,Ra] +// 1 LSL Rb, Rb, #1 +// 0 ADD PC, Rb +// In this sequence, instruction #0 depends on the value of Rb which is produced +// by the instruction #1. So, the instruction #0 depends on #1. Therefore, depends[0] +// will contain '1' as its element. +// The instruction #3 depends on 2 registers: Ra and Rb, or in other words, +// it depends on the instructions #4 and #6. Therefore, depends[2] will contain { 4, 6 } +// Maximum 4 dependencies per instruction are allowed. +// +// FIXME +// The 'roots' array contains the first instruction of the dependency chains. +// In our case we can say that there are 2 dependency chains: +// 0 -> 1 -> 2 -> 3 -> 4 +// -> 6 -> 7 +// 5 -> 6 +// Therefore the roots array will consist of {1, 5}. +// 0 denotes the end of the chain and cannot be the root of a dependency chain +// Usually 1 is a root of any jump sequence. +// +// The dependency array allows for checking for optimized sequences of instructions. +// If 2 instructions are not dependent on each other, they may appear in any order. +// (for example, the instruction #4 and the instruction sequence #5-6-7 may appear +// in any order because they do not depend on each other) +// Also any other instructions not modifying the register values may appear between +// the instructions of the sequence (due to the instruction rescheduling performed +// by the compiler). +// +// Provision for optional instructions: +// The presence of an optional instruction in the sequence (like #7) is signalled +// by a negative number of the dependency in the 'depends' array. +// +// Provision for variable instructions: +// In some cases several variants of the same instructions may be supported. +// For example, the instruction #5 might be BCS as well as BGE. It is the job of +// the jpi5() function to check for all variants. +// +// In order to use the 'jump_pattern_t' class you should derive another class from it +// and define the jpiN() virtual functions. +// Then you have to define the 'depends' and 'roots' arrays and call the match() +// function. +// If you processor contains instructions who modify registers in peculiar ways +// you might want to override the check_spoiled() function. + + +//---------------------------------------------------------------------- +// Macro to declare implementation of methods of jump_pattern_t +class jump_pattern_t; +// tracked registers +// We use the 'size' term to denote the number of bits involved in the insn. +// E.g. an operand of type dt_byte has 8-bit size. +// We store the current size (the number of used bits) in the DTYPE field +// of the 'op_t' structure. It may differ from the size of operand in the +// insn. See the comment for set_moved(). +// We extend the 'op_dtype_t' type by some negative constants to denote +// sizes from 2 to 7 bits. +typedef qvector<op_t> tracked_regs_t; +#define DECLARE_JUMP_PATTERN_HELPERS(decl)\ +decl void ida_export check_spoiled_jpt(const jump_pattern_t *_this, tracked_regs_t *_regs); \ +decl bool ida_export match_jpt(jump_pattern_t *_this);\ +decl bool ida_export same_value_jpt(jump_pattern_t *_this, const op_t &op, int r_i);\ +decl bool ida_export track_value_until_address_jpt(jump_pattern_t *_this, op_t *op, ea_t ea);\ +decl void ida_export combine_regs_jpt(jump_pattern_t *_this, tracked_regs_t *dst, const tracked_regs_t &src, ea_t ea);\ +decl void ida_export mark_switch_insns_jpt(const jump_pattern_t *_this, int last, int);\ +decl bool ida_export set_moved_jpt(const jump_pattern_t *_this, const op_t &dst, const op_t &src, tracked_regs_t &_regs, op_dtype_t real_dst_dtype, op_dtype_t real_src_dtype); + +DECLARE_JUMP_PATTERN_HELPERS(idaman) + +class jump_pattern_t +{ +protected: + // 32-bit operand generates a 32-bit result, zero- or sign-extended to a + // 64-bit result. This flag may be overwritten in processor modules. + // For example: + // ARM: MOV W8, #0x3C will clear the upper 32 bits of X8, + // PC : mov eax, 3Ch will clear the upper 32 bits of rax + bool modifying_r32_spoils_r64; + +public: + typedef bool (jump_pattern_t::*check_insn_t)(void); + inline jump_pattern_t( + switch_info_t *si, // may be NULL + const char (*depends)[4], + int last_reg); + + insn_t insn; // current instruction + switch_info_t *si; // answers will be here + + enum + { + NINS = 16, // the maximum length of the sequence + INS_MASK = 0x0F, + }; + ea_t eas[NINS]; + bool skip[NINS]; // do not check the Nth insn if skip[N] is true + int non_spoiled_reg; // if non_spoiled_reg was spoiled then we stop + // matching + check_insn_t check[NINS]; + // this is the hidden return value of the jpiN() methods. If it is set and + // jpiN() returned 'true' then we stop processing the dependency chain. If + // it is set and jpiN() returned 'false' then we stop checking the insns + // in the current basic block and we are switching to the next one (and we + // fail if there is no such block). + bool stop_matching; + // this flag can be analyzed by jpiN(). It means that the current insn is + // in the linear flow from the previous insn. It is always 'true' if the + // insn has JPT_NEAR flag. + bool in_linear_flow; + // this address can be analyzed by jpiN(). It means the end of the current + // block. It may help if we want to check in-block jumps. + ea_t block_end; + + #define JPT_OPT 0x10 // the dependent insn might be missing + #define JPT_NEAR 0x20 // the dependent insn must be in the linear flow + + const char (*depends)[4]; // instruction, on which we depend, and + // additional JPT_... flags + + // mark swith instructions to be ignored by the decompiler + // do not mark the indirect jmp (eas[0]) as ignored + // it will be used to recognize switch idioms + // unmark NLOWCASE insns after LAST (in the case of SWI_HXNOLOWCASE flag) + void mark_switch_insns(int last = NINS - 1, int nlowcase = 0) const + { + mark_switch_insns_jpt(this, last, nlowcase); + } + + // for fragmented switch idioms, cmp/jbe might be located in a separate + // fragment. we must not mark these instructions as part of the switch + // idiom because doing so would spoil the program logic for the decompiler + // and make the switch operator unreachable. the following vector keeps + // addresses of all instructions which must not be marked. this vector is + // maintained by derived classes. + eavec_t remote_code; + // extra insns used to calculate values (discovered by find_op_value) + eavec_t extra_insn_eas; + // tracked registers + tracked_regs_t regs; + + // handle a possible delay slot situation + // while walking backwards in the execution flow + // if <branch> is false and <ea> is in a delay + // slot of a branch likely instruction + // then set <ea> to the branch instruction + // (=annul the delay slot) + // if <branch> is true and the instruction at <ea> + // has a delay slot then set <ea> to the delay slot + // (=execute the delay slot) + virtual void process_delay_slot(ea_t &/*ea*/, bool /*branch*/) const {} + + // an artificial register to track the address of the conditional jump + // .value - condition + // .addr - address of the conditional jump + // .specval - address of the default case + // the derived class can use .reg to track the condition register + enum + { + o_condjump = 99, + cc_inc_ncases = 0x01, // increment ncases + cc_check_max_ncases = 0x02, // comparison with the maximum value + }; + + // compare supported operands + virtual bool equal_ops(const op_t &x, const op_t &y) const + { + if ( x.type != y.type ) + return false; + switch ( x.type ) + { + case o_void: + // consider spoiled values as not equal + return false; + case o_reg: + // ignore difference in the data size of registers + return x.reg == y.reg; + case o_condjump: + // we do not track the condition flags + return true; + } + return false; + } + + // return true if the instruction `insn' is a move one, + // there is no need check spoiled registers in this case + virtual bool handle_mov(tracked_regs_t & /*_regs*/ ) + { + return false; + } + // does the instruction `insn' spoil `_regs' ? + virtual void check_spoiled(tracked_regs_t *_regs) const + { + check_spoiled_jpt(this, _regs); + } + // some binaries use the following pattern + // xor eax, eax | mov al, cl + // so we can extend dtype of the operand from dt_byte to dt_dword + virtual op_dtype_t extend_dtype(const op_t &op) const + { + return op.dtype; // do not extend + } + + // these methods are not virtual and should be used in processor + // module only + inline void track(int reg, int r_i, op_dtype_t dtype); + inline void trackop(const op_t &op, int r_i); + inline bool is_spoiled(int r_i) { return regs[r_i].type == o_void; } + inline bool is_equal(int reg, int r_i, op_dtype_t dtype); + inline bool is_equal(const op_t &op, int r_i); + inline bool same_value(const op_t &op, int r_i); + inline bool track_value_until_address(op_t *op, ea_t ea); + + virtual bool jpi0(void) = 0; + virtual bool jpi1(void) { return false; } + virtual bool jpi2(void) { return false; } + virtual bool jpi3(void) { return false; } + virtual bool jpi4(void) { return false; } + virtual bool jpi5(void) { return false; } + virtual bool jpi6(void) { return false; } + virtual bool jpi7(void) { return false; } + virtual bool jpi8(void) { return false; } + virtual bool jpi9(void) { return false; } + virtual bool jpia(void) { return false; } + virtual bool jpib(void) { return false; } + virtual bool jpic(void) { return false; } + virtual bool jpid(void) { return false; } + virtual bool jpie(void) { return false; } + virtual bool jpif(void) { return false; } + // jpi<n> will be called if pre_jpi returns true + virtual bool pre_jpi(int /*n*/) { return true; } + + bool match(const insn_t &_insn) { insn = _insn; return match_jpt(this); } + + // remove compiler warnings -- class with virtual functions MUST have virtual destructor + virtual ~jump_pattern_t() {} + + // helpers for mov instruction tracing (see methods handle_mov(), + // check_spoiled() above) + inline static void set_spoiled(tracked_regs_t *_regs); + inline void set_spoiled(tracked_regs_t *_regs, const op_t &op) const; + // track 'mov' insn: dst <- src + // it returns 'true' if insn changes any of the tracked registers + // REAL_DST_DTYPE is the size that will be changed in the DST operand by + // the insn. It can be greater than the operand size because some insns + // clear the upper bits. For example: + // xor eax, eax | mov ax, cx REAL_DST_DTYPE is 32 + // xor bh, bh | mov bl, cl REAL_DST_DTYPE is 16 + // Extending of the 32-bit register to 64 bits is performed automatically + // based on the modifying_r32_spoils_r64 flag. + // REAL_SRC_DTYPE is the size that will be used in the SRC operand by the + // insn. It can be less than the operand size. For example: + // ARM: AND W8, W8, #0xFF will use 8 bits of X8, + // PC : cwde will use 16 bits of rax. + bool set_moved( + const op_t &dst, + const op_t &src, + tracked_regs_t &_regs, + op_dtype_t real_dst_dtype = dt_void, + op_dtype_t real_src_dtype = dt_void) const + { + return set_moved_jpt(this, dst, src, _regs, real_dst_dtype, real_src_dtype); + } + // calculate state of registers before a conditional jump <ea> as the + // combination of states of each branch + void combine_regs( + tracked_regs_t *dst, + const tracked_regs_t &src, + ea_t ea) + { + combine_regs_jpt(this, dst, src, ea); + } + +protected: + bool match_tree(); + bool follow_tree(ea_t ea, int n); + bool same_value_impl(const op_t &op, int r_i); + bool track_value_until_address_impl(op_t *op, ea_t ea); + + inline bool equal_ops_dtype(const op_t &op, const op_t ®) const; + static inline bool is_narrower(op_dtype_t dt1, op_dtype_t dt2); + enum + { + dt_7bit = 255, + dt_6bit = 254, + dt_5bit = 253, + dt_4bit = 252, + dt_3bit = 251, + dt_2bit = 250, + }; + static inline int get_dtype_nbits(op_dtype_t dtype); + + // helper for check_spoiled() + // TODO introduce new virtual methods spoils() and spoils_flags() and + // replace check_spoiled() by non-virtual method + inline void check_spoiled_not_reg( + tracked_regs_t *_regs, + uint maxop = UA_MAXOP) const; + + DECLARE_JUMP_PATTERN_HELPERS(friend) +}; + +//---------------------------------------------------------------------- +// kinds of jump tables +enum { JT_NONE = 0, JT_SWITCH, JT_CALL }; +// It returns a nonzero JT_... kind if it found a jump pattern. This kind is +// passed to the check_table() function. +typedef int is_pattern_t(switch_info_t *si, const insn_t &insn, procmod_t *procmod); +// It returns a refined kind. For example, JT_NONE if the found jump pattern +// is not a switch, or JT_CALL if it is a call of a func from an array +typedef int table_checker_t( + switch_info_t *si, + ea_t jump_ea, + int is_pattern_res, + procmod_t *pm); +// check a flat 32/16/8 bit jump table -- the most common case +idaman int ida_export check_flat_jump_table( + switch_info_t *si, + ea_t jump_ea, + int is_pattern_res = JT_SWITCH); + +// This function finds a switch. It calls functions from the PATTERNS +// array in turn until the first one returns a nonzero value. +// If a suitable pattern is found, it calls check_table() for the final +// check, passing a nonzero result code of the 'is_pattern_t' function. +// If the CHECK_TABLE parameter is NULL then check_flat_jump_table() is +// called. +// NAME is used for a debug output. +// It returns 'false' if INSN is not a switch or it is a call of a func from +// an array. In the latter case it defines this array. +idaman bool ida_export check_for_table_jump( + switch_info_t *si, + const insn_t &insn, + is_pattern_t *const patterns[], + size_t qty, + table_checker_t *check_table = NULL, + const char *name = NULL); + +//---------------------------------------------------------------------- +// sometimes the size of the jump table is misdetected +// check if any of the would-be targets point into the table +// and if so, truncate it +// if 'ignore_refs' is false, also stop at first data reference +idaman void ida_export trim_jtable( + switch_info_t *si, + ea_t jump_ea, + bool ignore_refs = false); + +//---------------------------------------------------------------------- +// this function find the size of the jump table for indirect switches +// (indirect switches have the values table which contains indexes into +// the jump table) +// in: si->ncases has the size of the values table +// out: si->jcases is initialized +idaman bool ida_export find_jtable_size(switch_info_t *si); + +//---------------------------------------------------------------------- +// get default jump address from the jump table. +// This method can be used only for a sparse nonindirect switch with default +// case in the jump table. +idaman ea_t ida_export find_defjump_from_table( + ea_t jump_ea, + const switch_info_t &si); + +//---------------------------------------------------------------------- +// get the specified target from the jump table. +idaman ea_t ida_export get_jtable_target( + ea_t jump_ea, + const switch_info_t &si, + int i); + + +//---------------------------------------------------------------------- +// iterate instructions in the backward execution flow +//lint -esym(1512,backward_flow_iterator_t*) destructor is not virtual +template<class State,class Ctrl> +// State: default constructor, operator= +// Ctrl: combine_regs(State *, const State& ,ea_t) +// process_delay_slot(ea_t &/*ea*/, bool /*branch*/) +struct backward_flow_iterator_t +{ +public: + ea_t cur_ea; // current address + State ®s; // current state of the tracked registers + Ctrl &ctrl; // to combine state + bool only_near; // should we follow only the linear flow? + uint max_insn_cnt; + +protected: + //lint --e{958} padding is required + func_t *pfn; // to check bounds + const segment_t *seg; + ea_t start_ea; + ea_t cur_end; // end of current basic block + uint insn_cnt; + // visited basic blocks: + // key_type - start of the block, mapped_type - end of the block; + typedef std::map<ea_t, ea_t> visited_t; + visited_t visited; + // waiting basic blocks: + // key_type - end of the block, mapped_type - state at the end; + struct state_t + { + State regs; + uint insn_cnt; + state_t() : regs(), insn_cnt(UINT_MAX) {} + }; + typedef std::map<ea_t, state_t> waiting_t; + waiting_t waiting; + +public: + backward_flow_iterator_t( + ea_t start_ea_, + State &start_regs, + Ctrl &ctrl_, + bool only_near_, + uint max_insn_cnt_ = 0) + : cur_ea(start_ea_), + regs(start_regs), + ctrl(ctrl_), + only_near(only_near_), + max_insn_cnt(max_insn_cnt_), + pfn(NULL), + seg(NULL), + start_ea(start_ea_), + cur_end(BADADDR), + insn_cnt(0), + visited(), + waiting() + { + // to check bounds + pfn = get_func(start_ea); + if ( pfn == NULL ) + { + seg = getseg(start_ea); + QASSERT(10183, seg != NULL); + } + } + + // fl_U : no previous instruction (start of a function or a cycle, + // or non linear flow if ONLY_NEAR is true), + // fl_F : got previous instruction by linear flow, + // fl_JF: got previous instruction by jump; + inline cref_t prev_insn(); + // stop iterating the current basic block, switch to the lowest waiting + // block + inline cref_t skip_block(); + + inline ea_t get_cur_end() const + { + return cur_end == BADADDR ? cur_ea : cur_end; + } + +protected: + // find visited basic block containing the address + // it returns the pointer to the address of the block end or NULL + inline ea_t *find_visited(ea_t ea); + // get the lowest to start_ea waiting block + inline cref_t get_waiting(); + // combine insn counter - count the shortest path + static inline void combine_insn_cnt(uint *dst, uint src) + { + if ( src < *dst ) + *dst = src; + } + + bool check_bounds() const + { + if ( pfn != NULL ) + return func_contains(pfn, cur_ea); + return seg->contains(cur_ea); + } +}; + +//------------------------------------------------------------------------- +// simple backward flow iterator +struct no_regs_t {}; +struct simple_bfi_t + : public backward_flow_iterator_t<no_regs_t, simple_bfi_t> +{ + typedef backward_flow_iterator_t<no_regs_t, simple_bfi_t> base_t; + +protected: + no_regs_t regs_; + +public: + simple_bfi_t(ea_t ea) + : base_t(ea, regs_, *this, false) {} + static void combine_regs(no_regs_t *, const no_regs_t &, ea_t) {} + static void process_delay_slot(ea_t &, bool) {} +}; + + +//====================================================================== +// inline implementation +//---------------------------------------------------------------------- +//-V:jump_pattern_t:730 not all members of a class are initialized inside the constructor +inline jump_pattern_t::jump_pattern_t( + switch_info_t *_si, + const char (*_depends)[4], + int last_reg) + : modifying_r32_spoils_r64(true), + si(_si), + non_spoiled_reg(-1), + in_linear_flow(false), + depends(_depends), + regs() +{ + if ( si != NULL ) + si->clear(); + regs.resize(last_reg + 1); +} + +//---------------------------------------------------------------------- +inline bool jump_pattern_t::equal_ops_dtype( + const op_t &op, + const op_t ®) const +{ + if ( !equal_ops(op, reg) ) + return false; + // operand should be wider than a tracked register + // e.g. after 'cmp cl, imm' we cannot use cx + if ( !is_narrower(op.dtype, reg.dtype) ) + return true; + // we believe that dword is widened to qword + if ( modifying_r32_spoils_r64 && op.dtype == dt_dword ) + return true; + // try to extend + if ( !is_narrower(extend_dtype(op), reg.dtype) ) + return true; + return false; +} + +//---------------------------------------------------------------------- +// return true if size1 is narrow than size2 +inline bool jump_pattern_t::is_narrower(op_dtype_t dt1, op_dtype_t dt2) +{ + if ( dt1 < dt_2bit ) + return dt2 < dt_2bit && dt1 < dt2; + else + return dt2 < dt_2bit || dt1 < dt2; +} + +//---------------------------------------------------------------------- +inline int jump_pattern_t::get_dtype_nbits(op_dtype_t dtype) +{ + switch ( dtype ) + { + case dt_byte: return 8; + case dt_word: return 16; + case dt_dword: return 32; + case dt_qword: return 64; + case dt_7bit: return 7; + case dt_6bit: return 6; + case dt_5bit: return 5; + case dt_4bit: return 4; + case dt_3bit: return 3; + case dt_2bit: return 2; + default: return -1; + } +} + +//---------------------------------------------------------------------- +inline void jump_pattern_t::check_spoiled_not_reg( + tracked_regs_t *_regs, + uint maxop) const +{ + uint32 feature = insn.get_canon_feature(PH); + if ( feature == 0 ) + return; + for ( uint i = 0; i < maxop; ++i ) + { + if ( has_cf_chg(feature, i) + && insn.ops[i].type != o_void + && insn.ops[i].type != o_reg ) + { + set_spoiled(_regs, insn.ops[i]); + } + } +} + +//---------------------------------------------------------------------- +inline void jump_pattern_t::track(int reg, int r_i, op_dtype_t dtype) +{ + regs[r_i].type = o_reg; + regs[r_i].reg = reg; + regs[r_i].dtype = dtype; +} +inline void jump_pattern_t::trackop(const op_t &op, int r_i) +{ + regs[r_i] = op; +} + +//---------------------------------------------------------------------- +inline bool jump_pattern_t::is_equal(int reg, int r_i, op_dtype_t dtype) +{ + op_t op; + op.type = o_reg; + op.reg = reg; + op.dtype = dtype; + return is_equal(op, r_i); +} +inline bool jump_pattern_t::is_equal(const op_t &op, int r_i) +{ + if ( regs[r_i].type == o_void ) + { + // there is no reason to continue match + stop_matching = true; + return false; + } + return equal_ops_dtype(op, regs[r_i]); +} + +//---------------------------------------------------------------------- +inline bool jump_pattern_t::same_value(const op_t &op, int r_i) +{ + return same_value_jpt(this, op, r_i); +} + +//---------------------------------------------------------------------- +inline bool jump_pattern_t::track_value_until_address(op_t *op, ea_t ea) +{ + return track_value_until_address_jpt(this, op, ea); +} + +//---------------------------------------------------------------------- +inline void jump_pattern_t::set_spoiled(tracked_regs_t *__regs) +{ + tracked_regs_t &_regs = *__regs; + // spoil all registers + for ( size_t i = 0; i < _regs.size(); ++i ) + _regs[i].type = o_void; +} +inline void jump_pattern_t::set_spoiled(tracked_regs_t *__regs, const op_t &op) const +{ + tracked_regs_t &_regs = *__regs; + for ( size_t i = 0; i < _regs.size(); ++i ) + if ( equal_ops(_regs[i], op) ) + _regs[i].type = o_void; // spoil register +} + +//---------------------------------------------------------------------- +// find the previous instruction in code flow +// take into account branches and potential delay slots +template<class State,class Ctrl> +inline cref_t backward_flow_iterator_t<State,Ctrl>::prev_insn() +{ + size_t refcnt = 0; + // check visited basic block + ea_t *visited_end = find_visited(cur_ea); + if ( visited_end == NULL ) + { + // analyze references to the current address + flags_t F = get_flags(cur_ea); + if ( is_flow(F) ) + ++refcnt; + if ( has_xref(F) && !is_func(F) ) // do not count jumps to function + { + xrefblk_t xb; + for ( bool ok = xb.first_to(cur_ea, XREF_FAR); + ok && xb.iscode; + ok = xb.next_to() ) + { + // count only xrefs from jumps + if ( xb.type == fl_JF || xb.type == fl_JN ) + { + if ( only_near ) + { + if ( refcnt > 0 ) + return fl_U; + // do not consider the flow through another switch as linear + if ( (get_flags(xb.from) & FF_JUMP) != 0 ) + return fl_U; + } + ++refcnt; + ea_t ea = xb.from; + ctrl.process_delay_slot(ea, true); + // ignore jumps from already visited blocks + if ( find_visited(ea) != NULL ) + continue; + // add basic block to the waiting set (combine state of the + // tracked registers at the jump source) + state_t &src_state = waiting[ea]; + ctrl.combine_regs(&src_state.regs, regs, ea); + combine_insn_cnt(&src_state.insn_cnt, insn_cnt); + } + } + } + + if ( cur_end == BADADDR ) + cur_end = cur_ea; + + // try ordinary flow + if ( is_flow(F) ) + { + ea_t prev_ea = prev_not_tail(cur_ea); + if ( prev_ea != BADADDR ) + { + cur_ea = prev_ea; + if ( check_bounds() + && (max_insn_cnt == 0 || insn_cnt < max_insn_cnt) ) + { + ++insn_cnt; + // remove reached waiting basic block + typename waiting_t::iterator w = waiting.find(cur_ea); + if ( w != waiting.end() ) + { + ctrl.combine_regs(®s, w->second.regs, cur_ea); + combine_insn_cnt(&insn_cnt, w->second.insn_cnt); + waiting.erase(w); + } + else + { + ctrl.process_delay_slot(cur_ea, false); + } + return fl_F; + } + } + // choose another branch + } + + // save block [cur_ea, cur_end] as visited + visited[cur_ea] = cur_end; + } + else if ( cur_end != BADADDR ) + { + // reach visited basic block => extend it + *visited_end = cur_end; + } + + // get the lowest waiting block + cref_t ret = get_waiting(); + // consider one xref as a linear flow + if ( ret == fl_JF && refcnt == 1 && waiting.empty() ) + ret = fl_F; + return ret; +} + +//---------------------------------------------------------------------- +template<class State,class Ctrl> +inline cref_t backward_flow_iterator_t<State,Ctrl>::skip_block() +{ + // check visited basic block + ea_t *visited_end = find_visited(cur_ea); + if ( visited_end == NULL ) + { + if ( cur_end == BADADDR ) + cur_end = cur_ea; + // save block [cur_ea, cur_end] as visited + visited[cur_ea] = cur_end; + } + else if ( cur_end != BADADDR ) + { + // reach visited basic block => extend it + *visited_end = cur_end; + } + + // get the lowest waiting block + return get_waiting(); +} + +//---------------------------------------------------------------------- +template<class State,class Ctrl> +inline cref_t backward_flow_iterator_t<State,Ctrl>::get_waiting() +{ + while ( !waiting.empty() ) + { + typename waiting_t::iterator w = waiting.upper_bound(start_ea); + if ( w != waiting.begin() ) + --w; + cur_ea = w->first; + if ( check_bounds() ) + { + cur_end = BADADDR; + regs = w->second.regs; + insn_cnt = w->second.insn_cnt; + waiting.erase(w); + return fl_JF; + } + waiting.erase(w); + } + return fl_U; +} + +//---------------------------------------------------------------------- +template<class State,class Ctrl> +inline ea_t *backward_flow_iterator_t<State,Ctrl>::find_visited(ea_t ea) +{ + visited_t::iterator v = visited.upper_bound(ea); + // assert: v == visited.end() || v->first > ea + if ( v == visited.begin() ) + return NULL; + --v; + // assert: v->first <= ea + if ( ea > v->second ) + return NULL; + return &v->second; +} + + +#endif diff --git a/idasdk76/include/kernwin.hpp b/idasdk76/include/kernwin.hpp new file mode 100644 index 0000000..33fbc4f --- /dev/null +++ b/idasdk76/include/kernwin.hpp @@ -0,0 +1,7761 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +/*! \file kernwin.hpp + + \brief Defines the interface between the kernel and the UI. + + It contains: + - the UI dispatcher notification codes (::ui_notification_t) + - convenience functions for UI services + - structures which hold information about the + lines (disassembly, structures, enums) generated + by the kernel + - functions to interact with the user (dialog boxes) + - some string and conversion functions. +*/ + +#ifndef __KERNWIN_HPP +#define __KERNWIN_HPP +//-V:DEF_SET_METHOD:524 equivalent function bodies +//-V:DEF_FIELD_METHOD:524 +//-V:place_t:730 not all members of a class are initialized inside the constructor +//-V:structplace_t:730 +//-V:idaplace_t:730 +//-V:enumplace_t:730 + +#ifndef SWIG +typedef uchar color_t; ///< see <lines.hpp> +typedef uval_t bmask_t; ///< see <enum.hpp> +typedef tid_t enum_t; ///< see <enum.hpp> +struct rangevec_t; ///< see <range.hpp> +class location_t; ///< see <moves.hpp> +struct lochist_entry_t; ///< see <moves.hpp> +struct strwinsetup_t; ///< see <strlist.hpp> +struct renderer_info_t; ///< see <moves.hpp> +struct segm_move_infos_t; ///< see <moves.hpp> +struct load_info_t; ///< see <loader.hpp> +#endif // SWIG + +/// Message box kinds +enum mbox_kind_t +{ + mbox_internal, ///< internal error + mbox_info, + mbox_warning, + mbox_error, + mbox_nomem, + mbox_feedback, + mbox_readerror, + mbox_writeerror, + mbox_filestruct, + mbox_wait, + mbox_hide, + mbox_replace, +}; + + +/// List chooser types +enum choose_type_t +{ + chtype_generic, ///< the generic choose() function + chtype_idasgn, ///< see choose_idasgn() + chtype_entry, ///< see choose_entry() + chtype_name, ///< see choose_name() + chtype_stkvar_xref, ///< see choose_stkvar_xref() + chtype_xref, ///< see choose_xref() + chtype_enum, ///< see choose_enum() + chtype_enum_by_value, ///< Deprecated. See ::chtype_enum_by_value_and_size + chtype_func, ///< see choose_func() + chtype_segm, ///< see choose_segm() + chtype_struc, ///< see choose_struc() + chtype_strpath, ///< see choose_struc_path() + chtype_idatil, ///< see choose_til() + chtype_enum_by_value_and_size, ///< see choose_enum_by_value() + chtype_srcp, ///< see choose_srcp() +}; + + +enum beep_t ///< Beep types +{ + beep_default = 0 +}; + + +// Notify UI about various events. The kernel will call this function +// when something interesting for the UI happens. +// The UI should avoid calling the kernel from this callback. + +class func_t; +class segment_t; +struct sreg_range_t; +class struc_t; +class member_t; +class plugin_t; +struct plugmod_t; +struct procmod_t; +class minsn_t; +class idc_value_t; +class linput_t; +class snapshot_t; + +/// TWidget renderer type +enum tcc_renderer_type_t +{ + TCCRT_INVALID = 0, ///< invalid + TCCRT_FLAT, ///< flat view + TCCRT_GRAPH, ///< graph view + TCCRT_PROXIMITY ///< proximity view +}; + +/// TWidget ::place_t type +enum tcc_place_type_t +{ + TCCPT_INVALID = 0, ///< invalid + TCCPT_PLACE, ///< ::place_t + TCCPT_SIMPLELINE_PLACE, ///< ::simpleline_place_t + TCCPT_IDAPLACE, ///< ::idaplace_t + TCCPT_ENUMPLACE, ///< ::enumplace_t + TCCPT_STRUCTPLACE ///< ::structplace_t +}; + +/// Represents mouse button for view_mouse_event_t objects +enum vme_button_t +{ + VME_UNKNOWN, ///< unknown mouse button + VME_LEFT_BUTTON, ///< left mouse button + VME_RIGHT_BUTTON, ///< right mouse button + VME_MID_BUTTON, ///< middle mouse button +}; + +//------------------------------------------------------------------------- +/// \defgroup SETMENU_ Set menu flags +/// Passed as 'flags' parameter to attach_action_to_menu() +/// In case menupath == NULL new item will be added to the end of menu even when +/// SETMENU_APP is not set. SETMENU_FIRST can be used to change this behaviour +/// Note: The upper 16 bits are reserved for UI internal use. +//@{ +#define SETMENU_POSMASK 0x3 +#define SETMENU_INS 0x0 ///< add menu item before the specified path (default) +#define SETMENU_APP 0x1 ///< add menu item after the specified path +#define SETMENU_FIRST 0x2 ///< add item to the beginning of menu +//@} + +/// \defgroup CREATETB_ create toolbar flags +/// Passed as 'flags' parameter to create_toolbar() +//@{ +#define CREATETB_ADV 0x1 ///< toolbar is for 'advanced mode' only +//@} + +//------------------------------------------------------------------------- +/// \defgroup HIF_ set_highlightr flags +/// Passed as 'flags' parameter to set_highlight() +//@{ +#define HIF_IDENTIFIER 0x1 ///< text is an identifier (i.e., when searching for the current highlight, SEARCH_IDENT will be used) +#define HIF_REGISTER 0x2 ///< text represents a register (aliases/subregisters will be highlit as well) +#define HIF_LOCKED 0x4 ///< locked; clicking/moving the cursor around doesn't change the highlight +#define HIF_NOCASE 0x8 ///< case insensitive +//@} + +#define REG_HINTS_MARKER SCOLOR_ON "\x7F" +#define REG_HINTS_MARKER_LEN 2 +#define SRCDBG_HINTS_MARKER SCOLOR_ON "\x7E" +#define SRCDBG_HINTS_MARKER_LEN 2 + + +/// \defgroup CDVF_ Code viewer flags +/// passed as 'flags' parameter to create_code_viewer() +//@{ +#define CDVF_NOLINES 0x0001 ///< don't show line numbers +#define CDVF_LINEICONS 0x0002 ///< icons can be drawn over the line control +#define CDVF_STATUSBAR 0x0004 ///< keep the status bar in the custom viewer +//@} + +/// \defgroup IDCHK_ IDC hotkey error codes +/// return values for add_idc_hotkey() +//@{ +#define IDCHK_OK 0 ///< ok +#define IDCHK_ARG -1 ///< bad argument(s) +#define IDCHK_KEY -2 ///< bad hotkey name +#define IDCHK_MAX -3 ///< too many IDC hotkeys +//@} + +/// \defgroup WIDGET_CLOSE Form close flags +/// passed as options to close_widget() +//@{ +#define WCLS_SAVE 0x1 ///< save state in desktop config +#define WCLS_NO_CONTEXT 0x2 ///< don't change the current context (useful for toolbars) +#define WCLS_DONT_SAVE_SIZE 0x4 ///< don't save size of the window +#define WCLS_DELETE_LATER 0x8 ///< assign the deletion of the widget to the UI loop ///< \return void +#define WCLS_CLOSE_LATER WCLS_DELETE_LATER +//@} + +/// \defgroup DP_ Docking positions +/// passed as 'orient' parameter to set_dock_pos() +//@{ +#define DP_LEFT 0x0001 ///< Dock src_form to the left of dest_form +#define DP_TOP 0x0002 ///< Dock src_form above dest_form +#define DP_RIGHT 0x0004 ///< Dock src_form to the right of dest_form +#define DP_BOTTOM 0x0008 ///< Dock src_form below dest_form +#define DP_INSIDE 0x0010 ///< Create a new tab bar with both src_form and dest_form +#define DP_TAB 0x0040 ///< Place src_form into a tab next to dest_form, + ///< if dest_form is in a tab bar + ///< (otherwise the same as #DP_INSIDE) +#define DP_BEFORE 0x0020 ///< place src_form before dst_form in the tab bar instead of after + ///< used with #DP_INSIDE. +#define DP_FLOATING 0x0080 ///< Make src_form floating +#define DP_SZHINT 0x0100 ///< When floating or in a splitter (i.e., not tabbed), + ///< use the widget's size hint to determine the best + ///< geometry (Qt only) +//@} + +/// \defgroup CDVF_ Code viewer flags +/// passed as 'flags' parameter to create_code_viewer() +//@{ +#define CDVF_NOLINES 0x0001 ///< don't show line numbers +#define CDVF_LINEICONS 0x0002 ///< icons can be drawn over the line control +#define CDVF_STATUSBAR 0x0004 ///< keep the status bar in the custom viewer +//@} + +/// \defgroup SVF_ Source viewer creation flags +/// passed as 'flags' parameter to callback for ::ui_create_source_viewer +//@{ +#define SVF_COPY_LINES 0x0000 ///< keep a local copy of '*lines' +#define SVF_LINES_BYPTR 0x0001 ///< remember the 'lines' ptr. do not make a copy of '*lines' +//@} + +/// \defgroup CVNF_ Custom viewer navigation flags +/// passed as 'flags' parameter to custom_viewer_jump() +//@{ +#define CVNF_LAZY (1 << 0) ///< try and move the cursor to a line displaying the + ///< place_t if possible. This might disregard the Y + ///< position in case of success +#define CVNF_JUMP (1 << 1) ///< push the current position in this viewer's + ///< lochist_t before going to the new location +#define CVNF_ACT (1 << 2) ///< activate (i.e., switch to) the viewer. + ///< Activation is performed before the new + ///< lochist_entry_t instance is actually copied + ///< to the viewer's lochist_t (otherwise, if the + ///< viewer was invisible its on_location_changed() + ///< handler wouldn't be called.) +//@} +/// \defgroup WIDGET_OPEN Widget open flags +/// passed as options to open_form() and display_widget() +//@{ +// +#define WOPN_RESTORE 0x00000004u ///< if the widget was the only widget in a floating area the + ///< last time it was closed, it will be restored as + ///< floating, with the same position+size as before +#define WOPN_PERSIST 0x00000040u ///< widget will remain available when starting or stopping debugger sessions +#define WOPN_CLOSED_BY_ESC 0x00000080u ///< override idagui.cfg:CLOSED_BY_ESC: esc will close +#define WOPN_NOT_CLOSED_BY_ESC 0x00000100u ///< override idagui.cfg:CLOSED_BY_ESC: esc will not close +#define WOPN_DP_MASK 0x0FFF0000u +#define WOPN_DP_SHIFT 16 +#define WOPN_DP_LEFT (DP_LEFT << WOPN_DP_SHIFT) + ///< Dock widget to the left of dest_ctrl +#define WOPN_DP_TOP (DP_TOP << WOPN_DP_SHIFT) + ///< Dock widget above dest_ctrl +#define WOPN_DP_RIGHT (DP_RIGHT << WOPN_DP_SHIFT) + ///< Dock widget to the right of dest_ctrl +#define WOPN_DP_BOTTOM (DP_BOTTOM << WOPN_DP_SHIFT) + ///< Dock widget below dest_ctrl +#define WOPN_DP_INSIDE (DP_INSIDE << WOPN_DP_SHIFT) + ///< Create a new tab bar with both widget and dest_ctrl +#define WOPN_DP_TAB (DP_TAB << WOPN_DP_SHIFT) + ///< Place widget into a tab next to dest_ctrl, + ///< if dest_ctrl is in a tab bar + ///< (otherwise the same as #WOPN_DP_INSIDE) +#define WOPN_DP_BEFORE (DP_BEFORE << WOPN_DP_SHIFT) + ///< place widget before dst_form in the tab bar instead of after + ///< used with #WOPN_DP_INSIDE and #WOPN_DP_TAB +#define WOPN_DP_FLOATING (DP_FLOATING << WOPN_DP_SHIFT) + ///< Make widget floating +#define WOPN_DP_SZHINT (DP_SZHINT << WOPN_DP_SHIFT) + ///< when floating or in a splitter (i.e., not tabbed), + ///< use the widget's size hint to determine the best + ///< geometry (Qt only) +#define WOPN_DP_INSIDE_BEFORE (WOPN_DP_INSIDE | WOPN_DP_BEFORE) +#define WOPN_DP_TAB_BEFORE (WOPN_DP_TAB | WOPN_DP_BEFORE) +#define WOPN_GET_DP(v) (((v) & WOPN_DP_MASK) >> WOPN_DP_SHIFT) +//@} + +/// \defgroup RENADDR_DIALOGS Dialogs for "Rename address" +//@{ +#define RENADDR_IDA 0 ///< dialog for "IDA View" +#define RENADDR_HR 1 ///< dialog for "Pseudocode" + ///< additional flags: + ///< 0x01 Library function + ///< 0x02 Mark as decompiled +//@} + +#ifndef SWIG +/// Callui return codes. +/// The size of this type should be 4 bytes at most, +/// otherwise different compilers return it differently +union callui_t +{ + bool cnd; + char i8; + int i; + short i16; + int32 i32; + uchar u8; + ushort u16; + uint32 u32; + char *cptr; + void *vptr; + ssize_t ssize; + func_t *fptr; + segment_t *segptr; + struc_t *strptr; + plugin_t *pluginptr; + sreg_range_t *sraptr; +}; + +/// Events marked as 'ui:' should be used as a parameter to callui(). +/// (See convenience functions like get_screen_ea()) +/// Events marked as 'cb:' are designed to be callbacks and should not +/// be used in callui(). The user may hook to ::HT_UI events to catch them + +enum ui_notification_t +{ + ui_null = 0, + + ui_range, ///< cb: The disassembly range has been changed (\inf{min_ea} ... \inf{max_ea}). + ///< UI should redraw the scrollbars. See also: ::ui_lock_range_refresh + ///< \param none + ///< \return void + + ui_refresh_choosers, ///< cb: The list (chooser) window contents have been changed (names, signatures, etc). + ///< UI should redraw them. Please consider request_refresh() instead + ///< \param none + ///< \return void + + ui_idcstart, ///< cb: Start of IDC engine work. + ///< \param none + ///< \return void + + ui_idcstop, ///< cb: Stop of IDC engine work. + ///< \param none + ///< \return void + + ui_suspend, ///< cb: Suspend graphical interface. + ///< Only the text version. + ///< Interface should respond to it. + ///< \param none + ///< \return void + + ui_resume, ///< cb: Resume the suspended graphical interface. + ///< Only the text version. + ///< Interface should respond to it + ///< \param none + ///< \return void + + ui_broadcast, ///< cb: broadcast call + ///< \param magic (::int64) a magic number + ///< \param ... other parameters depend on the given magic + ///< modules may hook to this event and reply to the caller. + ///< for example, the decompiler uses it to communicate + ///< its entry point to other plugins + + ui_read_selection, ///< ui: see read_selection() + + ui_read_range_selection, ///< ui: see read_range_selection() + + ui_unmarksel, ///< ui: see unmark_selection() + + ui_screenea, ///< ui: see get_screen_ea() + + ui_saving, ///< cb: The kernel is flushing its buffers to the disk. + ///< The user interface should save its state. + ///< Parameters: none + ///< Returns: none + + ui_saved, ///< cb: The kernel has saved the database. + ///< This callback just informs the interface. + ///< Note that at the time this notification is sent, + ///< the internal paths are not updated yet, + ///< and calling get_path(PATH_TYPE_IDB) will return + ///< the previous path. + ///< \param path (const char *) the database path + ///< \return void + + ui_refreshmarked, ///< ui: see refresh_idaview() + + ui_refresh, ///< ui: see refresh_idaview_anyway() + + ui_choose, ///< ui: Allow the user to choose an object. + ///< Always use the helper inline functions for this code. + ///< See \ref ui_choose_funcs for a list of such functions. + ///< \param type (::choose_type_t) type of chooser to display + ///< \param ... other parameters depend on the given type + ///< \return depends on the given type + + ui_close_chooser, ///< ui: see close_chooser() + + ui_banner, ///< ui: see banner() + + ui_setidle, ///< ui: Set a function to call at idle times. + ///< \param func (int (*)(void)) pointer to function that will be called + ///< \return void + + ui_database_closed, ///< cb: The database has been closed. + ///< See also processor_t::closebase, it occurs earlier. + ///< See also ui_initing_database. + ///< This is not the same as IDA exiting. If you need + ///< to perform cleanup at the exiting time, use qatexit(). + ///< \param none + ///< \return void + + ui_beep, ///< ui: see beep() + + ui_is_msg_inited, ///< ui: see is_msg_inited() + + ui_msg, ///< ui: Show a message in the message window. + ///< \param format (const char *) format of message body + ///< \param va (va_list) format args + ///< \return number of bytes output + + ui_mbox, ///< ui: Show a message box. + ///< \param kind (::mbox_kind_t) + ///< \param format (const char *) format of message body + ///< \param va (va_list]) format args + ///< \return void + + ui_clr_cancelled, ///< ui: see clr_cancelled() + + ui_set_cancelled, ///< ui: see set_cancelled() + + ui_test_cancelled, ///< ui: see user_cancelled() + + ui_ask_buttons, ///< ui: see ask_yn() and ask_buttons() + + ui_ask_file, ///< ui: see ask_file() + + ui_ask_form, ///< ui: see \ref FORM_C + + ui_ask_text, ///< ui: see ask_text() + + ui_ask_str, ///< ui: see ask_str() + + ui_ask_addr, ///< ui: see ask_addr() + + ui_ask_seg, ///< ui: see ask_seg() + + ui_ask_long, ///< ui: see ask_long() + + ui_add_idckey, ///< ui: see add_idc_hotkey() + + ui_obsolete_del_idckey, + ///< ui: see ui_del_idckey() + + ui_analyzer_options, ///< ui: see analyzer_options() + + ui_load_file, ///< ui: see ui_load_new_file() + + ui_run_dbg, ///< ui: see ui_run_debugger() + + ui_get_cursor, ///< ui: see get_cursor() + + ui_get_curline, ///< ui: see get_curline() + + ui_copywarn, ///< ui: see display_copyright_warning() + + ui_noabort, ///< ui: Disable 'abort' menu item - the database was not compressed. + ///< \param none + ///< \return void + + ui_lock_range_refresh,///< ui: Lock the ui_range refreshes. + ///< The ranges will not be refreshed until the corresponding + ///< ::ui_unlock_range_refresh is issued. + ///< \param none + ///< \return void + + ui_unlock_range_refresh,///< ui: Unlock the ::ui_range refreshes. + ///< If the number of locks is back to zero, then refresh the ranges. + ///< \param none + ///< \return void + + ui_genfile_callback, ///< cb: handle html generation. + ///< \param html_header_cb_t ** + ///< \param html_footer_cb_t ** + ///< \param html_line_cb_t ** + ///< \return void + + ui_open_url, ///< ui: see open_url() + + ui_hexdumpea, ///< ui: Return the current address in a hex view. + ///< \param result (::ea_t *) + ///< \param hexdump_num (int) + ///< \return void + + ui_get_key_code, ///< ui: see get_key_code() + + ui_setup_plugins_menu,///< ui: setup plugins submenu + ///< \param none + ///< \return void + + ui_get_kernel_version,///< ui: see get_kernel_version() + + ui_is_idaq, ///< ui: see is_idaq() + + ui_refresh_navband, ///< ui: see refresh_navband() + + ui_debugger_menu_change, ///< cb: debugger menu modification detected + ///< \param enable (bool) + ///< true: debugger menu has been added, or a different debugger has been selected + ///< false: debugger menu will be removed (user switched to "No debugger") + ///< \return void + + ui_get_curplace, ///< ui: see get_custom_viewer_place(). See also ui_get_custom_viewer_location + + ui_obsolete_display_widget, + ui_close_widget, ///< ui: see close_widget() + + ui_activate_widget, ///< ui: see activate_widget() + + ui_find_widget, ///< ui: see find_widget() + + ui_get_current_widget, + ///< ui: see get_current_widget() + + ui_widget_visible, ///< TWidget is displayed on the screen. + ///< Use this event to populate the window with controls + ///< \param widget (TWidget *) + ///< \return void + + ui_widget_closing, ///< TWidget is about to close. + ///< This event precedes ui_widget_invisible. Use this + ///< to perform some possible actions relevant to + ///< the lifecycle of this widget + ///< \param widget (TWidget *) + ///< \return void + + ui_widget_invisible, ///< TWidget is being closed. + ///< Use this event to destroy the window controls + ///< \param widget (TWidget *) + ///< \return void + + ui_get_ea_hint, ///< cb: ui wants to display a simple hint for an address. + ///< Use this event to generate a custom hint + ///< See also more generic ::ui_get_item_hint + ///< \param buf (::qstring *) + ///< \param ea (::ea_t) + ///< \return true if generated a hint + + ui_get_item_hint, ///< cb: ui wants to display multiline hint for an item. + ///< See also more generic ::ui_get_custom_viewer_hint + ///< \param[out] hint (::qstring *) the output string + ///< \param ea (ea_t) or item id like a structure or enum member + ///< \param max_lines (int) maximal number of lines + ///< \param[out] important_lines (int *) number of important lines. if zero, output is ignored + ///< \return true if generated a hint + + ui_refresh_custom_viewer, + ///< ui: see refresh_custom_viewer() + + ui_destroy_custom_viewer, + ///< ui: see destroy_custom_viewer() + + ui_jump_in_custom_viewer, + ///< ui: see jumpto() + + ui_get_custom_viewer_curline, + ///< ui: see get_custom_viewer_curline() + + ui_get_current_viewer,///< ui: see get_current_viewer() + + ui_is_idaview, ///< ui: see is_idaview() + + ui_get_custom_viewer_hint, + ///< cb: ui wants to display a hint for a viewer (idaview or custom). + ///< Every subscriber is supposed to append the hint lines + ///< to HINT and increment IMPORTANT_LINES accordingly. + ///< Completely overwriting the existing lines in HINT + ///< is possible but not recommended. + ///< If the REG_HINTS_MARKER sequence is found in the + ///< returned hints string, it will be replaced with the + ///< contents of the "regular" hints. + ///< If the SRCDBG_HINTS_MARKER sequence is found in the + ///< returned hints string, it will be replaced with the + ///< contents of the source-level debugger-generated hints. + ///< The following keywords might appear at the beginning of the + ///< returned hints: + ///< HIGHLIGHT text\n + ///< where text will be highlighted + ///< CAPTION caption\n + ///< caption for the hint widget + ///< \param[out] hint (::qstring *) the output string, + ///< on input contains hints from the previous subscribes + ///< \param viewer (TWidget*) viewer + ///< \param place (::place_t *) current position in the viewer + ///< \param[out] important_lines (int *) number of important lines, + ///< should be incremented, + ///< if zero, the result is ignored + ///< \retval 0 continue collecting hints with other subscribers + ///< \retval 1 stop collecting hints + + ui_set_custom_viewer_range, + ///< ui: set_custom_viewer_range() + + ui_database_inited, ///< cb: database initialization has completed. + ///< the kernel is about to run idc scripts + ///< \param is_new_database (int) + ///< \param idc_script (const char *) - may be NULL + ///< \return void + ///< See also ui_initing_database. + ///< This event is called for both new and old databases. + + ui_ready_to_run, ///< cb: all UI elements have been initialized. + ///< Automatic plugins may hook to this event to + ///< perform their tasks. + ///< \param none + ///< \return void + + ui_set_custom_viewer_handler, + ///< ui: see set_custom_viewer_handler(). + ///< also see other examples in \ref ui_scvh_funcs + + ui_refresh_chooser, ///< ui: see refresh_chooser() + + ui_open_builtin, ///< ui: open a window of a built-in type. see \ref ui_open_builtin_funcs + + ui_preprocess_action, ///< cb: ida ui is about to handle a user action. + ///< \param name (const char *) ui action name. + ///< these names can be looked up in ida[tg]ui.cfg + ///< \retval 0 ok + ///< \retval nonzero a plugin has handled the command + + ui_postprocess_action,///< cb: an ida ui action has been handled + + ui_set_custom_viewer_mode, + ///< ui: switch between graph/text modes. + ///< \param custom_viewer (TWidget *) + ///< \param graph_view (bool) + ///< \param silent (bool) + ///< \return bool success + + ui_gen_disasm_text, ///< ui: see gen_disasm_text() + + ui_gen_idanode_text, ///< cb: generate disassembly text for a node. + ///< Plugins may intercept this event and provide + ///< custom text for an IDA graph node + ///< They may use gen_disasm_text() for that. + ///< \param text (text_t *) + ///< \param fc (qflow_chart_t *) + ///< \param node (int) + ///< \return bool text_has_been_generated + + ui_install_cli, ///< ui: see: + ///< install_command_interpreter(), + ///< remove_command_interpreter() + + ui_execute_sync, ///< ui: see execute_sync() + + ui_get_chooser_obj, ///< ui: see get_chooser_obj() + + ui_enable_chooser_item_attrs, + ///< ui: see enable_chooser_item_attrs() + + ui_get_chooser_item_attrs, + ///< cb: get item-specific attributes for a chooser. + ///< This callback is generated only after enable_chooser_attrs() + ///< \param chooser (const ::chooser_base_t *) + ///< \param n (::size_t) + ///< \param attrs (::chooser_item_attrs_t *) + ///< \return void + + ui_set_dock_pos, ///< ui: see set_dock_pos() + + ui_get_opnum, ///< ui: see get_opnum() + + ui_install_custom_datatype_menu, + ///< ui: install/remove custom data type menu item. + ///< \param dtid (int) data type id + ///< \param install (bool) + ///< \return success + + ui_install_custom_optype_menu, + ///< ui: install/remove custom operand type menu item. + ///< \param fid (int) format id + ///< \param install (bool) + ///< \return success + + ui_get_range_marker, ///< ui: Get pointer to function. + ///< see mark_range_for_refresh(ea_t, asize_t). + ///< This function will be called by the kernel when the + ///< database is changed + ///< \param none + ///< \return vptr: (idaapi*marker)(ea_t ea, asize_t) or NULL + + ui_lookup_key_code, ///< ui: see lookup_key_code() + + ui_load_custom_icon_file, + ///< ui: see load_custom_icon(const char *) + + ui_load_custom_icon, ///< ui: see load_custom_icon(const void *, unsigned int, const char *) + + ui_free_custom_icon, ///< ui: see free_custom_icon() + + ui_process_action, ///< ui: see process_ui_action() + + ui_create_code_viewer,///< ui: see create_code_viewer() + + ui_addons, ///< ui: see \ref ui_addons_funcs + + ui_execute_ui_requests, + ///< ui: see execute_ui_requests(ui_request_t, ...) + + ui_execute_ui_requests_list, + ///< ui: see execute_ui_requests(ui_requests_t) + + ui_register_timer, ///< ui: see register_timer() + + ui_unregister_timer, ///< ui: see unregister_timer() + + ui_take_database_snapshot, + ///< ui: see take_database_snapshot() + + ui_restore_database_snapshot, + ///< ui: see restore_database_snapshot() + + ui_set_code_viewer_line_handlers, + ///< ui: see set_code_viewer_line_handlers() + + ui_obsolete_refresh_custom_code_viewer, + + ui_create_source_viewer, + ///< ui: Create new source viewer. + ///< \param top_tl (TWidget **) toplevel widget of created source viewer (can be NULL) + ///< \param parent (TWidget *) + ///< \param custview (TWidget *) + ///< \param path (const char *) + ///< \param lines (strvec_t *) + ///< \param lnnum (int) + ///< \param colnum (int) + ///< \param flags (int) (\ref SVF_) + ///< \return source_view_t * + + ui_get_tab_size, ///< ui: see get_tab_size() + + ui_repaint_qwidget, ///< ui: see repaint_custom_viewer() + + ui_custom_viewer_set_userdata, + ///< ui: Change ::place_t user data for a custom view. + ///< \param custom_viewer (TWidget *) + ///< \param user_data (void *) + ///< \return old user_data + + ui_jumpto, ///< ui: see jumpto(ea_t, int, int) + + ui_cancel_exec_request, + ///< ui: see cancel_exec_request() + + ui_open_form, ///< ui: see vopen_form() + + ui_unrecognized_config_directive, + ///< ui: Possibly handle an extra config directive, + ///< passed through '-d' or '-D'. + ///< \param directive (const char *) The config directive + ///< \return char * - one of \ref IDPOPT_RET + ///< See also register_cfgopts, which is better + + ui_get_output_cursor, ///< ui: see get_output_cursor() + + ui_get_output_curline,///< ui: see get_output_curline() + + ui_get_output_selected_text, + ///< ui: see get_output_selected_text() + + ui_get_renderer_type, ///< ui: see get_view_renderer_type() + + ui_set_renderer_type, ///< ui: see set_view_renderer_type() + + ui_get_viewer_user_data, + ///< ui: see get_viewer_user_data() + + ui_get_viewer_place_type, + ///< ui: see get_viewer_place_type() + + ui_ea_viewer_history_push_and_jump, + ///< ui: see ea_viewer_history_push_and_jump() + + ui_ea_viewer_history_info, + ///< ui: see get_ea_viewer_history_info() + + ui_register_action, + ///< ui: see register_action() + + ui_unregister_action, + ///< ui: see unregister_action() + + ui_attach_action_to_menu, + ///< ui: see attach_action_to_menu() + + ui_detach_action_from_menu, + ///< ui: see detach_action_from_menu() + + ui_attach_action_to_popup, + ///< ui: see attach_action_to_popup() + + ui_detach_action_from_popup, + ///< ui: see detach_action_from_popup() + + ui_attach_dynamic_action_to_popup, + ///< ui: see create attach_dynamic_action_to_popup() + + ui_attach_action_to_toolbar, + ///< ui: see attach_action_to_toolbar() + + ui_detach_action_from_toolbar, + ///< ui: see detach_action_from_toolbar() + + ui_updating_actions, ///< cb: IDA is about to update all actions. If your plugin + ///< needs to perform expensive operations more than once + ///< (e.g., once per action it registers), you should do them + ///< only once, right away. + ///< \param ctx (::action_update_ctx_t *) + ///< \return void + + ui_updated_actions, ///< cb: IDA is done updating actions. + ///< \param none + ///< \return void + + ui_populating_widget_popup, + ///< cb: IDA is populating the context menu for a widget. + ///< This is your chance to attach_action_to_popup(). + ///< + ///< Have a look at ui_finish_populating_widget_popup, + ///< if you want to augment the + ///< context menu with your own actions after the menu + ///< has had a chance to be properly populated by the + ///< owning component or plugin (which typically does it + ///< on ui_populating_widget_popup.) + ///< + ///< \param widget (TWidget *) + ///< \param popup_handle (TPopupMenu *) + ///< \param ctx (const action_activation_ctx_t *) + ///< \return void + ///< + ///< ui: see ui_finish_populating_widget_popup + + ui_finish_populating_widget_popup, + ///< cb: IDA is about to be done populating the + ///< context menu for a widget. + ///< This is your chance to attach_action_to_popup(). + ///< + ///< \param widget (TWidget *) + ///< \param popup_handle (TPopupMenu *) + ///< \param ctx (const action_activation_ctx_t *) + ///< \return void + ///< + ///< ui: see ui_populating_widget_popup + + ui_update_action_attr, + ///< ui: see \ref ui_uaa_funcs + + ui_get_action_attr, ///< ui: see \ref ui_gaa_funcs + + ui_plugin_loaded, ///< cb: The plugin was loaded in memory. + ///< \param plugin_info (const ::plugin_info_t *) + + ui_plugin_unloading, ///< cb: The plugin is about to be unloaded + ///< \param plugin_info (const ::plugin_info_t *) + + ui_get_widget_type, ///< ui: see get_widget_type() + + ui_current_widget_changed, + ///< cb: The currently-active TWidget changed. + ///< \param widget (TWidget *) + ///< \param prev_widget (TWidget *) + ///< \return void + + ui_get_widget_title, ///< ui: see get_widget_title() + + ui_obsolete_get_user_strlist_options, + ///< ui: see get_user_strlist_options() + + ui_create_custom_viewer, + ///< ui: see create_viewer() + + ui_custom_viewer_jump,///< ui: set the current location, and have the viewer display it + ///< \param v (TWidget *) + ///< \param loc (const lochist_entry_t *) + ///< \param flags (uint32) or'ed combination of CVNF_* values + ///< \return success + + ui_set_custom_viewer_handlers, + ///< ui: see set_custom_viewer_handlers() + + ui_get_registered_actions, + ///< ui: see get_registered_actions() + + ui_create_toolbar, ///< ui: see create_toolbar() + ui_delete_toolbar, ///< ui: see delete_toolbar() + ui_create_menu, ///< ui: see create_menu() + ui_delete_menu, ///< ui: see delete_menu() + ui_obsolete_set_nav_colorizer, + ui_get_chooser_data, ///< ui: see get_chooser_data() + ui_get_highlight, ///< ui: see get_highlight() + ui_set_highlight, ///< ui: see set_highlight() + + ui_set_mappings, ///< ui: Show current memory mappings + ///< and allow the user to change them. + ui_create_empty_widget, + ///< ui: see create_empty_widget() + + ui_msg_clear, ///< ui: see msg_clear() + ui_msg_save, ///< ui: see msg_save() + ui_msg_get_lines, ///< ui: see msg_get_lines() + + ui_chooser_default_enter, + ///< ui: jump to the address returned by get_ea() callback in the + ///< case of the non-modal choosers + ///< \param chooser (const ::chooser_base_t *) + ///< \param n/sel (::size_t *) for chooser_t + ///< (::sizevec_t *) for chooser_multi_t + ///< \return int chooser_t::cbres_t + + ui_screen_ea_changed, + ///< cb: The "current address" changed + ///< \param ea (ea_t) + ///< \param prev_ea (ea_t) + ///< \return void + + ui_get_active_modal_widget, + ///< ui: see get_active_modal_widget() + + ui_navband_pixel, ///< ui: see get_navband_pixel + ui_navband_ea, ///< ui: see get_navband_ea + ui_get_window_id, ///< ui: set get_window_id (GUI only) + + ui_create_desktop_widget, + ///< cb: create a widget, to be placed in the widget tree (at desktop-creation time.) + ///< \param title (const char *) + ///< \param cfg (const jobj_t *) + ///< \return TWidget * the created widget, or null + + ui_strchoose, ///< ui: undocumented + + + ui_set_nav_colorizer, ///< ui: see set_nav_colorizer() + ui_display_widget, ///< ui: see display_widget() + + ui_get_lines_rendering_info, + ///< cb: get lines rendering information + ///< \param out (lines_rendering_output_t *) + ///< \param widget (const TWidget *) + ///< \param info (const lines_rendering_input_t *) + ///< \return void + + ui_sync_sources, + ///< ui: [un]synchronize sources + ///< \param what (const sync_source_t *) + ///< \param with (const sync_source_t *) + ///< \param sync (bool) + ///< \return success + + ui_get_widget_config, ///< cb: retrieve the widget configuration (it will be passed + ///< back at ui_create_desktop_widget-, and ui_set_widget_config-time) + ///< \param widget (const TWidget *) + ///< \param cfg (jobj_t *) + ///< \return void + + ui_set_widget_config, ///< cb: set the widget configuration + ///< \param widget (const TWidget *) + ///< \param cfg (const jobj_t *) + ///< \return void + + ui_get_custom_viewer_location, + ///< ui: see get_custom_viewer_location() + ///< \param out (lochist_entry_t *) + ///< \param custom_viewer (TWidget *) + ///< \param mouse (bool) + + ui_initing_database, ///< cb: database initialization has started. + ///< \return void + ///< See also ui_database_inited. + ///< This event is called for both new and old databases. + + ui_destroying_procmod, ///< cb: The processor module is about to be destroyed + ///< \param procmod (const ::procmod_t *) + + ui_destroying_plugmod, ///< cb: The plugin object is about to be destroyed + ///< \param plugmod (const ::plugmod_t *) + ///< \param entry (const ::plugin_t *) + + ui_update_file_history, ///< ui: manipulate the file history + ///< \param add_path (const char *) + ///< \param del_path (const char *) + + ui_cancel_thread_exec_requests, + ///< ui: see cancel_thread_exec_requests() + + ui_get_synced_group, + ///< ui: see get_synced_group() + + ui_show_rename_dialog, ///< ui: undocumented + ///< Rename address dialog -] + ///< \param ea (ea_t) + ///< \param ndialog (int) dialog number \ref RENADDR_DIALOGS + ///< \param[inout] hr_flags (ushort *) additional flags + ///< \return success + + ui_desktop_applied, ///< cb: a desktop has been applied + ///< \param name (const char *) the desktop name + ///< \param from_idb (bool) the desktop was stored in the IDB (false if it comes from the registry) + ///< \param type (int) the desktop type (1-disassembly, 2-debugger, 3-merge) + + ui_choose_bookmark, + ///< ui: modal chooser (legacy) + ///< \param n (uint32 *) input: default slot, output: chosen bookmark index + ///< \param entry (const lochist_entry_t *) entry with place type + ///< \param ud (void *) user data + +// -[ + ui_last, ///< the last notification code + + ui_dbg_begin = 1000, ///< debugger callgates. should not be used directly, see dbg.hpp for details + ui_dbg_run_requests = ui_dbg_begin, + ui_dbg_get_running_request, + ui_dbg_get_running_notification, + ui_dbg_clear_requests_queue, + ui_dbg_get_process_state, + ui_dbg_start_process, + ui_dbg_request_start_process, + ui_dbg_suspend_process, + ui_dbg_request_suspend_process, + ui_dbg_continue_process, + ui_dbg_request_continue_process, + ui_dbg_exit_process, + ui_dbg_request_exit_process, + ui_dbg_get_thread_qty, + ui_dbg_getn_thread, + ui_dbg_select_thread, + ui_dbg_request_select_thread, + ui_dbg_step_into, + ui_dbg_request_step_into, + ui_dbg_step_over, + ui_dbg_request_step_over, + ui_dbg_run_to, + ui_dbg_request_run_to, + ui_dbg_step_until_ret, + ui_dbg_request_step_until_ret, + ui_dbg_get_bpt_qty, + ui_dbg_add_oldbpt, + ui_dbg_request_add_oldbpt, + ui_dbg_del_oldbpt, + ui_dbg_request_del_oldbpt, + ui_dbg_enable_oldbpt, + ui_dbg_request_enable_oldbpt, + ui_dbg_set_trace_size, + ui_dbg_clear_trace, + ui_dbg_request_clear_trace, + ui_dbg_is_step_trace_enabled, + ui_dbg_enable_step_trace, + ui_dbg_request_enable_step_trace, + ui_dbg_get_step_trace_options, + ui_dbg_set_step_trace_options, + ui_dbg_request_set_step_trace_options, + ui_dbg_is_insn_trace_enabled, + ui_dbg_enable_insn_trace, + ui_dbg_request_enable_insn_trace, + ui_dbg_get_insn_trace_options, + ui_dbg_set_insn_trace_options, + ui_dbg_request_set_insn_trace_options, + ui_dbg_is_func_trace_enabled, + ui_dbg_enable_func_trace, + ui_dbg_request_enable_func_trace, + ui_dbg_get_func_trace_options, + ui_dbg_set_func_trace_options, + ui_dbg_request_set_func_trace_options, + ui_dbg_get_tev_qty, + ui_dbg_get_tev_info, + ui_dbg_get_call_tev_callee, + ui_dbg_get_ret_tev_return, + ui_dbg_get_bpt_tev_ea, + ui_dbg_get_reg_value_type, + ui_dbg_get_processes, + ui_dbg_attach_process, + ui_dbg_request_attach_process, + ui_dbg_detach_process, + ui_dbg_request_detach_process, + ui_dbg_get_first_module, + ui_dbg_get_next_module, + ui_dbg_bring_to_front, + ui_dbg_get_current_thread, + ui_dbg_wait_for_next_event, + ui_dbg_get_debug_event, + ui_dbg_set_debugger_options, + ui_dbg_set_remote_debugger, + ui_dbg_load_debugger, + ui_dbg_retrieve_exceptions, + ui_dbg_store_exceptions, + ui_dbg_define_exception, + ui_dbg_suspend_thread, + ui_dbg_request_suspend_thread, + ui_dbg_resume_thread, + ui_dbg_request_resume_thread, + ui_dbg_get_process_options, + ui_dbg_check_bpt, + ui_dbg_set_process_state, + ui_dbg_get_manual_regions, + ui_dbg_set_manual_regions, + ui_dbg_enable_manual_regions, + ui_dbg_set_process_options, + ui_dbg_is_busy, + ui_dbg_hide_all_bpts, + ui_dbg_edit_manual_regions, + ui_dbg_get_sp_val, + ui_dbg_get_ip_val, + ui_dbg_get_reg_val, + ui_dbg_set_reg_val, + ui_dbg_request_set_reg_val, + ui_dbg_get_insn_tev_reg_val, + ui_dbg_get_insn_tev_reg_result, + ui_dbg_register_provider, + ui_dbg_unregister_provider, + ui_dbg_handle_debug_event, + ui_dbg_add_vmod, + ui_dbg_del_vmod, + ui_dbg_compare_bpt_locs, + ui_dbg_save_bpts, + ui_dbg_set_bptloc_string, + ui_dbg_get_bptloc_string, + ui_dbg_internal_appcall, + ui_dbg_internal_cleanup_appcall, + ui_dbg_internal_get_sreg_base, + ui_dbg_internal_ioctl, + ui_dbg_read_memory, + ui_dbg_write_memory, + ui_dbg_read_registers, + ui_dbg_write_register, + ui_dbg_get_memory_info, + ui_dbg_get_event_cond, + ui_dbg_set_event_cond, + ui_dbg_enable_bpt, + ui_dbg_request_enable_bpt, + ui_dbg_del_bpt, + ui_dbg_request_del_bpt, + ui_dbg_map_source_path, + ui_dbg_map_source_file_path, + ui_dbg_modify_source_paths, + ui_dbg_is_bblk_trace_enabled, + ui_dbg_enable_bblk_trace, + ui_dbg_request_enable_bblk_trace, + ui_dbg_get_bblk_trace_options, + ui_dbg_set_bblk_trace_options, + ui_dbg_request_set_bblk_trace_options, + // trace management + ui_dbg_load_trace_file, + ui_dbg_save_trace_file, + ui_dbg_is_valid_trace_file, + ui_dbg_set_trace_file_desc, + ui_dbg_get_trace_file_desc, + ui_dbg_choose_trace_file, + ui_dbg_diff_trace_file, + ui_dbg_graph_trace, + ui_dbg_get_tev_memory_info, + ui_dbg_get_tev_event, + ui_dbg_get_insn_tev_reg_mem, + // breakpoint management (new codes were introduced in v6.3) + ui_dbg_getn_bpt, + ui_dbg_get_bpt, + ui_dbg_find_bpt, + ui_dbg_add_bpt, + ui_dbg_request_add_bpt, + ui_dbg_update_bpt, + ui_dbg_for_all_bpts, + ui_dbg_get_tev_ea, + ui_dbg_get_tev_type, + ui_dbg_get_tev_tid, + ui_dbg_get_trace_base_address, + // calluis for creating traces from scratch (added in 6.4) + ui_dbg_set_trace_base_address, + ui_dbg_add_tev, + ui_dbg_add_insn_tev, + ui_dbg_add_call_tev, + ui_dbg_add_ret_tev, + ui_dbg_add_bpt_tev, + ui_dbg_add_debug_event, + ui_dbg_add_thread, + ui_dbg_del_thread, + ui_dbg_add_many_tevs, + ui_dbg_set_bpt_group, + ui_dbg_set_highlight_trace_options, + ui_dbg_set_trace_platform, + ui_dbg_get_trace_platform, + // added in 6.6 + ui_dbg_internal_get_elang, + ui_dbg_internal_set_elang, + + // added in 6.7 + ui_dbg_load_dbg_dbginfo, + ui_dbg_set_resume_mode, + ui_dbg_request_set_resume_mode, + ui_dbg_set_bptloc_group, + ui_dbg_list_bptgrps, + ui_dbg_rename_bptgrp, + ui_dbg_del_bptgrp, + ui_dbg_get_grp_bpts, + ui_dbg_get_bpt_group, + ui_dbg_change_bptlocs, + + // added in 7.1 + ui_dbg_collect_stack_trace, + ui_dbg_get_module_info, + + // source-level debugging + ui_dbg_get_srcinfo_provider, + ui_dbg_get_global_var, + ui_dbg_get_local_var, + ui_dbg_get_local_vars, + ui_dbg_add_path_mapping, + ui_dbg_get_current_source_file, + ui_dbg_get_current_source_line, + + ui_dbg_srcdbg_step_into, + ui_dbg_srcdbg_request_step_into, + ui_dbg_srcdbg_step_over, + ui_dbg_srcdbg_request_step_over, + ui_dbg_srcdbg_step_until_ret, + ui_dbg_srcdbg_request_step_until_ret, + + ui_dbg_getn_thread_name, + ui_dbg_bin_search, + + ui_dbg_get_insn_tev_reg_val_i, + ui_dbg_get_insn_tev_reg_result_i, + ui_dbg_get_reg_val_i, + ui_dbg_set_reg_val_i, + + ui_dbg_get_reg_info, + + ui_dbg_set_trace_dynamic_register_set, + ui_dbg_get_trace_dynamic_register_set, + + ui_dbg_end, + + // Debugging notifications +#ifdef _DEBUG + debug_obsolete_assert_thread_waitready = ui_dbg_end +#endif +}; + + +//-------------------------------------------------------------------------- + + +/// Pointer to the user-interface dispatcher function. +/// This pointer is in the kernel + +idaman callui_t ida_export_data (idaapi*callui)(ui_notification_t what,...); + + +/// After calling init_kernel() the ui must call this function. +/// It will open the database specified in the command line. +/// If the database did not exist, a new database will be created and +/// the input file will be loaded. +/// \return 0-ok, otherwise an exit code + +idaman int ida_export init_database(int argc, const char *const *argv, int *newfile); + + +/// The database termination function. +/// This function should be called to close the database. + +idaman void ida_export term_database(void); + + +/// See error() + +idaman NORETURN AS_PRINTF(1, 0) void ida_export verror(const char *format, va_list va); + + +/// See show_hex() + +idaman AS_PRINTF(3, 0) void ida_export vshow_hex( + const void *dataptr, + size_t len, + const char *format, + va_list va); + + +/// See show_hex_file() + +idaman AS_PRINTF(4, 0) void ida_export vshow_hex_file( + linput_t *li, + int64 pos, + size_t count, + const char *format, + va_list va); + + +#endif // SWIG + +/// Get IDA kernel version (in a string like "5.1"). + +inline ssize_t get_kernel_version(char *buf, size_t bufsize) +{ + return callui(ui_get_kernel_version, buf, bufsize).ssize; +} + +//-------------------------------------------------------------------------- +// K E R N E L S E R V I C E S F O R U I +//-------------------------------------------------------------------------- +// +// Generating text for the disassembly, enum, and structure windows. + +/*! \brief Denotes a displayed line. + + (location_t would be a better name but it is too late to rename it now) + + An object may be displayed on one or more lines. All lines of an object are + generated at once and kept in a linearray_t class. + + place_t is an abstract class, another class must be derived from it. \n + Currently the following classes are used in IDA: + + idaplace_t - disassembly view \n + enumplace_t - enum view \n + structplace_t - structure view + + Example (idaplace_t): \verbatim + + 004015AC + 004015AC loc_4015AC: ; CODE XREF: sub_4014B8+C5j + 004015AC xor eax, eax \endverbatim + + The first line is denoted by idaplace_t with ea=4015AC, lnnum=0 \n + The second line is denoted by idaplace_t with ea=4015AC, lnnum=1 \n + The third line is denoted by idaplace_t with ea=4015AC, lnnum=2 + + NB: the place_t class may change in the future, do not rely on it +*/ +class place_t +{ +public: + int lnnum; ///< Number of line within the current object + place_t(void) {} ///< Constructor + place_t(int ln) : lnnum(ln) {} ///< Constructor + DEFINE_MEMORY_ALLOCATION_FUNCS() + + /// Generate a short description of the location. + /// This description is used on the status bar. + /// \param out_buf the output buffer + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + virtual void idaapi print(qstring *out_buf, void *ud) const = 0; + + /// Map the location to a number. + /// This mapping is used to draw the vertical scrollbar. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + virtual uval_t idaapi touval(void *ud) const = 0; + + /// Clone the location. + /// \return a pointer to a copy of the current location in dynamic memory + virtual place_t *idaapi clone(void) const = 0; + + /// Copy the specified location object to the current object + virtual void idaapi copyfrom(const place_t *from) = 0; + + /// Map a number to a location. + /// When the user clicks on the scrollbar and drags it, we need to determine + /// the location corresponding to the new scrollbar position. This function + /// is used to determine it. It builds a location object for the specified 'x' + /// and returns a pointer to it. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + /// \param x number to map + /// \param lnnum line number to initialize 'lnnum' + /// \return a freshly allocated object. See also PCF_MAKEPLACE_ALLOCATES + virtual place_t *idaapi makeplace(void *ud, uval_t x, int lnnum) const= 0; + + /// Deprecated. Please consider compare2(const place_t *, void *) instead. + virtual int idaapi compare(const place_t *t2) const = 0; + + /// Adjust the current location to point to a displayable object. + /// This function validates the location and makes sure that it points to + /// an existing object. For example, if the location points to the middle + /// of an instruction, it will be adjusted to point to the beginning of the + /// instruction. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + virtual void idaapi adjust(void *ud) = 0; + + /// Move to the previous displayable location. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + /// \return success + virtual bool idaapi prev(void *ud) = 0; + + /// Move to the next displayable location. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + /// \return success + virtual bool idaapi next(void *ud) = 0; + + /// Are we at the first displayable object?. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + /// \return true if the current location points to the first displayable object + virtual bool idaapi beginning(void *ud) const = 0; + + /// Are we at the last displayable object?. + /// \param ud pointer to user-defined context data. Is supplied by ::linearray_t + /// \return true if the current location points to the last displayable object + virtual bool idaapi ending(void *ud) const = 0; + + /// Generate text lines for the current location. + /// \param out storage for the lines + /// \param out_deflnnum pointer to the cell that will contain the number of + /// the most 'interesting' generated line + /// \param out_pfx_color pointer to the cell that will contain the line prefix color + /// \param out_bgcolor pointer to the cell that will contain the background color + /// \param ud pointer to user-defined context data. Is supplied by linearray_t + /// \param maxsize the maximum number of lines to generate + /// \return number of generated lines + virtual int idaapi generate( + qstrvec_t *out, + int *out_deflnnum, + color_t *out_pfx_color, + bgcolor_t *out_bgcolor, + void *ud, + int maxsize) const = 0; + + /// Serialize this instance. + /// It is fundamental that all instances of a particular subclass + /// of of place_t occupy the same number of bytes when serialized. + /// \param out buffer to serialize into + virtual void idaapi serialize(bytevec_t *out) const = 0; + + /// De-serialize into this instance. + /// 'pptr' should be incremented by as many bytes as + /// de-serialization consumed. + /// \param pptr pointer to a serialized representation of a place_t of this type. + /// \param end pointer to end of buffer. + /// \return whether de-serialization was successful + virtual bool idaapi deserialize(const uchar **pptr, const uchar *end) = 0; + + /// Get the place's ID (i.e., the value returned by register_place_class()) + /// \return the id + virtual int idaapi id() const = 0; + + /// Get this place type name. + /// All instances of a given class must return the same string. + /// \return the place type name. Please try and pick something that is + /// not too generic, as it might clash w/ other plugins. A good + /// practice is to prefix the class name with the name + /// of your plugin. E.g., "myplugin:srcplace_t". + virtual const char *idaapi name() const = 0; + + /// Map the location to an ea_t. + /// \return the corresponding ea_t, or BADADDR; + virtual ea_t idaapi toea() const { return BADADDR; } + + /// Rebase the place instance + /// \param infos the segments that were moved + /// \return true if place was rebased, false otherwise + virtual bool idaapi rebase(const segm_move_infos_t & /*infos*/ ) { return true; } + + /// Visit this place, possibly 'unhiding' a section of text. + /// If entering that place required some expanding, a place_t + /// should be returned that represents that section, plus some + /// flags for later use by 'leave()'. + /// \param out_flags flags to be used together with the place_t that is + /// returned, in order to restore the section to its + /// original state when leave() is called. + /// \return a place_t corresponding to the beginning of the section + /// of text that had to be expanded. That place_t's leave() will + /// be called with the flags contained in 'out_flags' when the user + /// navigates away from it. + virtual place_t *idaapi enter(uint32 * /*out_flags*/) const { return NULL; } + + /// Leave this place, possibly 'hiding' a section of text that was + /// previously expanded (at enter()-time.) + virtual void idaapi leave(uint32 /*flags*/) const {} + + /// Compare two locations except line numbers (lnnum). + /// This function is used to organize loops. + /// For example, if the user has selected an range, its boundaries are remembered + /// as location objects. Any operation within the selection will have the following + /// look: for ( loc=starting_location; loc < ending_location; loc.next() ) + /// In this loop, the comparison function is used. + /// \param t2 the place to compare this one to. + /// \param ud pointer to user-defined context data. + /// \retval -1 if the current location is less than 't2' + /// \retval 0 if the current location is equal to than 't2' + /// \retval 1 if the current location is greater than 't2' + virtual int idaapi compare2(const place_t *t2, void * /*ud*/) const { return compare(t2); } +}; + +#define DEFAULT_PLACE_LNNUM -1 + +/// compare places and their lnnums +idaman int ida_export l_compare(const place_t *t1, const place_t *t2); +idaman int ida_export l_compare2(const place_t *t1, const place_t *t2, void *ud); + +#ifndef SWIG + +//-------------------------------------------------------------------------- +/// Helper to define exported functions for ::place_t implementations +#define define_place_exported_functions(classname) \ +class classname; \ +idaman void ida_export classname ## __print(const classname *, qstring *, void*); \ +idaman uval_t ida_export classname ## __touval(const classname *,void*); \ +idaman place_t * ida_export classname ## __clone(const classname *); \ +idaman void ida_export classname ## __copyfrom(classname *,const place_t*); \ +idaman place_t * ida_export classname ## __makeplace(const classname *,void*,uval_t,int); \ +idaman int ida_export classname ## __compare(const classname *,const place_t*); \ +idaman int ida_export classname ## __compare2(const classname *,const place_t*, void*); \ +idaman void ida_export classname ## __adjust(classname *,void*); \ +idaman bool ida_export classname ## __prev(classname *,void*); \ +idaman bool ida_export classname ## __next(classname *,void*); \ +idaman bool ida_export classname ## __beginning(const classname *,void*); \ +idaman bool ida_export classname ## __ending(const classname *,void*); \ +idaman int ida_export classname ## __generate( \ + const classname *, \ + qstrvec_t*, \ + int*, \ + color_t*, \ + bgcolor_t*, \ + void*, \ + int); \ +idaman void ida_export classname ## __serialize(const classname *, bytevec_t *out); \ +idaman bool ida_export classname ## __deserialize(classname *, const uchar **, const uchar *); \ +idaman int ida_export classname ## __id(const classname *); \ +idaman const char *ida_export classname ## __name(const classname *); \ +idaman ea_t ida_export classname ## __toea(const classname *); \ +idaman place_t * ida_export classname ## __enter(const classname *, uint32 *); \ +idaman void ida_export classname ## __leave(const classname *, uint32); \ +idaman bool ida_export classname ## __rebase(classname *, const segm_move_infos_t &); + + +/// Helper to define virtual functions in ::place_t implementations +#define define_place_virtual_functions(class) \ + virtual void idaapi print(qstring *buf, void *ud) const override \ + { class ## __print(this, buf, ud); } \ + virtual uval_t idaapi touval(void *ud) const override \ + { return class ## __touval(this,ud); } \ + virtual place_t *idaapi clone(void) const override \ + { return class ## __clone(this); } \ + virtual void idaapi copyfrom(const place_t *from) override \ + { class ## __copyfrom(this,from); } \ + virtual place_t *idaapi makeplace( \ + void *ud, \ + uval_t x, \ + int _lnnum) const override \ + { return class ## __makeplace(this,ud,x,_lnnum); } \ + virtual int idaapi compare(const place_t *t2) const override \ + { return class ## __compare(this, t2); } \ + virtual void idaapi adjust(void *ud) override \ + { class ## __adjust(this,ud); } \ + virtual bool idaapi prev(void *ud) override \ + { return class ## __prev(this,ud); } \ + virtual bool idaapi next(void *ud) override \ + { return class ## __next(this,ud); } \ + virtual bool idaapi beginning(void *ud) const override \ + { return class ## __beginning(this,ud); } \ + virtual bool idaapi ending(void *ud) const override \ + { return class ## __ending(this,ud); } \ + virtual int idaapi generate( \ + qstrvec_t *_out, \ + int *_out_lnnum, \ + color_t *_out_pfx_color, \ + bgcolor_t *_out_bg_color, \ + void *_ud, \ + int _max) const override \ + { \ + return class ## __generate( \ + this, _out, _out_lnnum, _out_pfx_color, \ + _out_bg_color, _ud, _max); \ + } \ + virtual void idaapi serialize(bytevec_t *out) const override \ + { class ## __serialize(this, out); } \ + virtual bool idaapi deserialize( \ + const uchar **pptr, \ + const uchar *end) override \ + { return class ## __deserialize(this, pptr, end); } \ + virtual int idaapi id() const override \ + { return class ## __id(this); } \ + virtual const char * idaapi name() const override \ + { return class ## __name(this); } \ + virtual ea_t idaapi toea() const override \ + { return class ## __toea(this); } \ + virtual place_t *idaapi enter(uint32 *out_flags) const override \ + { return class ## __enter(this, out_flags); } \ + virtual void idaapi leave(uint32 flags) const override \ + { return class ## __leave(this, flags); } \ + virtual bool idaapi rebase(const segm_move_infos_t &infos) override \ + { return class ## __rebase(this, infos); } \ + virtual int idaapi compare2(const place_t *t2, void *ud) const override \ + { return class ## __compare2(this, t2, ud); } + +define_place_exported_functions(simpleline_place_t) + + +#endif // SWIG + +//-------------------------------------------------------------------------- + +/*! \defgroup simpleline Simpleline interface + + \brief IDA custom viewer sample. + + It is enough to create an object of ::strvec_t class, put all lines + into it and create a custom ida viewer (::ui_create_custom_viewer). + \code + strvec_t sv; + // fill it with lines... + simpleline_place_t s1; + simpleline_place_t s2(sv.size()-1); + cv = (TWidget *)callui(ui_create_custom_viewer, + "My title", + &s1, + &s2, + &s1, + 0, + &sv).vptr; + \endcode + This will produce a nice colored text view. + Also see the SDK's 'custview' and 'hexview' plugins for more complete examples. +*/ +//@{ + +/// Maintain basic information for a line in a custom view +struct simpleline_t +{ + qstring line; ///< line text + color_t color; ///< line prefix color + bgcolor_t bgcolor; ///< line background color + simpleline_t(void) : color(1), bgcolor(DEFCOLOR) {} ///< Constructor (default colors) + simpleline_t(color_t c, const char *str) : line(str), color(c), bgcolor(DEFCOLOR) {} ///< Constructor + simpleline_t(const char *str) : line(str), color(1), bgcolor(DEFCOLOR) {} ///< Constructor + simpleline_t(const qstring &str) : line(str), color(1), bgcolor(DEFCOLOR) {} ///< Constructor + DEFINE_MEMORY_ALLOCATION_FUNCS() +}; + +/// A collection of simple lines to populate a custom view. +/// This is an example of what you would pass as the 'ud' argument to create_custom_viewer() +typedef qvector<simpleline_t> strvec_t; + +/// A location in a view populated by a ::strvec_t +class simpleline_place_t : public place_t +{ +public: + uint32 n; ///< line number + simpleline_place_t(void) { n = 0; lnnum = 0; } ///< Constructor + simpleline_place_t(int _n) { n = _n; lnnum = 0; } ///< Constructor + define_place_virtual_functions(simpleline_place_t); +}; +//@} + +//-------------------------------------------------------------------------- +// user defined data for linearray_t: use ptr to result of calc_default_idaplace_flags() +#ifndef SWIG +define_place_exported_functions(idaplace_t) +#endif // SWIG +/// A location in a disassembly view +class idaplace_t : public place_t +{ +public: + ea_t ea; ///< address + idaplace_t(void) {} ///< Constructor + idaplace_t(ea_t x, int ln) : place_t(ln), ea(x) {} ///< Constructor + define_place_virtual_functions(idaplace_t); +}; + +//-------------------------------------------------------------------------- +// user defined data for linearray_t: NULL +#ifndef SWIG +define_place_exported_functions(enumplace_t) +#endif // SWIG +/// A location in an enum view +class enumplace_t : public place_t +{ +public: + size_t idx; ///< enum serial number + bmask_t bmask; ///< enum member bitmask + uval_t value; ///< enum member value + uchar serial; ///< enum member serial number + enumplace_t(void) {} ///< Constructor + enumplace_t(size_t i, bmask_t m, uval_t v, uchar s, int ln) ///< Constructor + : place_t(ln), idx(i), bmask(m), value(v), serial(s) {} + define_place_virtual_functions(enumplace_t); +}; + +//-------------------------------------------------------------------------- +// user defined data for linearray_t: ea_t *pea +// if pea != NULL then the function stack frame is displayed, *pea == function start +// else normal structure list is displayed +#ifndef SWIG +define_place_exported_functions(structplace_t) +#endif // SWIG +/// A location in a struct view +class structplace_t : public place_t +{ +public: + uval_t idx; ///< struct serial number + uval_t offset; ///< offset within struct + structplace_t(void) {} ///< Constructor + structplace_t(uval_t i, uval_t o, int ln) : place_t(ln), idx(i), offset(o) {} ///< Constructor + define_place_virtual_functions(structplace_t); +}; + +//------------------------------------------------------------------------- +/// A location in a hex view +#ifndef SWIG +define_place_exported_functions(hexplace_t) +struct outctx_base_t; +struct hexplace_gen_t; +class hexview_t; +idaman void ida_export hexplace_t__out_one_item( + const hexplace_t *_this, + outctx_base_t &ctx, + const hexplace_gen_t *hg, + int itemno, + color_t *color, + color_t patch_or_edit); +idaman size_t ida_export hexplace_t__ea2str( + char *buf, + size_t bufsize, + const hexplace_gen_t *hg, + ea_t ea); +#endif // SWIG + +#define HEXPLACE_COLOR_EDITED COLOR_SYMBOL +#define HEXPLACE_COLOR_PATCHED COLOR_VOIDOP +#define HEXPLACE_COLOR_SHOWSPACES COLOR_RESERVED1 + +// A helper, used as 'userdata' for generating lines in a hexplace_t +// None of the function pointers can be NULL +struct hexplace_gen_t +{ + // data format to display + enum data_kind_t + { + dk_float, + dk_int, + dk_addr_names, + dk_addr_text, + }; + enum int_format_t + { + if_hex, + if_signed, + if_unsigned, + }; + // result of get_byte_value() + enum byte_kind_t + { + BK_VALID, // has a valid value + BK_INVALIDADDR, // address is invalid + BK_NOVALUE, // address is valid but contains no value + }; + + virtual bool is_editing() const = 0; + virtual bool is_editing_text() const = 0; + virtual bool is_curitem_changed() const = 0; + virtual bool is_edited_byte(ea_t ea, uint64 *out_value=NULL) const = 0; + virtual byte_kind_t get_byte_value( + ea_t ea, + uint64 *out_value, + bool *out_edited) const = 0; + virtual void get_encoding(qstring *out) const = 0; + virtual ea_t get_cur_item_ea() const = 0; + virtual void get_cur_item_text(qstring *out) const = 0; + virtual int get_alignment() const = 0; + virtual int get_line_len(ea_t ea) const = 0; + virtual int get_items_per_line() const = 0; + virtual int get_bytes_per_item() const = 0; + virtual int get_item_width(ea_t ea) const = 0; + virtual data_kind_t get_data_kind() const = 0; + virtual int_format_t get_int_format() const = 0; + virtual bool has_central_separator() const = 0; + virtual bool show_text() const = 0; + virtual bool show_segaddr() const = 0; + virtual int get_bitness() const = 0; + + bool is_addr_kind() const + { + data_kind_t k = get_data_kind(); + return k == dk_addr_names || k == dk_addr_text; + } +}; + +//------------------------------------------------------------------------- +// class to represent lines in a hex dump window +// one line consists of hv->grid.items_per_line items +// each item is hv->grid.bytes_per_item bytes for 8-bit bytes or one "wide" byte +class hexplace_t : public idaplace_t +{ +protected: + ea_t sol; // EA at start-of-line +public: + hexplace_t(ea_t _ea, short ln) : idaplace_t(_ea, ln), sol(_ea) {} + define_place_virtual_functions(hexplace_t); + + void out_one_item( + outctx_base_t &ctx, + const hexplace_gen_t *hg, + int itemno, + color_t *color, + color_t patch_or_edit) const + { + hexplace_t__out_one_item(this, ctx, hg, itemno, color, patch_or_edit); + } + + // convert ea to text + // use seg:off if segment base is not zero + // otherwise print just the address + static size_t ea2str(char *buf, size_t bufsize, const hexplace_gen_t *hg, ea_t ea) + { + return hexplace_t__ea2str(buf, bufsize, hg, ea); + } + +}; + +//------------------------------------------------------------------------- +#define PCF_EA_CAPABLE 0x00000001 ///< toea() implementation returns meaningful data +#define PCF_MAKEPLACE_ALLOCATES 0x00000002 ///< makeplace() returns a freshly allocated (i.e., non-static) + ///< instance. All new code should pass that flag to + ///< register_place_class(), and the corresponding + ///< makeplace() class implementation should + ///< return new instances. + +//------------------------------------------------------------------------- +idaman int ida_export internal_register_place_class( + const place_t *tmplate, + int flags, + const plugin_t *owner, + int sdk_version); + + +//------------------------------------------------------------------------- +/// Register information about a place_t class. +/// +/// The kernel will not take ownership, nor delete the 'tmplate' instance. +/// Therefore, it's up to the plugin to handle it (the recommended way +/// of doing it is to pass address of a const static instance.) +/// In addition, the place_t will be automatically unregistered when the owner +/// plugin is unloaded from memory. +/// \param tmplate the place_t template +/// \param flags or'ed combination of PCF_* flags. You should always +/// pass at least PCF_MAKEPLACE_ALLOCATES, and have the +/// place_t::makeplace() implementation create new instances. +/// \param owner the owner plugin of the place_t type. Cannot be NULL. +/// \return the place_t ID, or -1 if an error occurred. +inline int register_place_class( + const place_t *tmplate, + int flags, + const plugin_t *owner) +{ + return internal_register_place_class(tmplate, flags, owner, IDA_SDK_VERSION); +} + +//------------------------------------------------------------------------- +/// Get information about a previously-registered place_t class. +/// See also register_place_class(). +/// \param out_flags output flags (can be NULL) +/// \param out_sdk_version sdk version the place was created with (can be NULL) +/// \param id place class ID +/// \return the place_t template, or NULL if not found +idaman const place_t *ida_export get_place_class( + int *out_flags, + int *out_sdk_version, + int id); + +//------------------------------------------------------------------------- +/// See get_place_class() +inline const place_t *get_place_class_template(int id) +{ + return get_place_class(NULL, NULL, id); +} + +//------------------------------------------------------------------------- +/// See get_place_class() +inline bool is_place_class_ea_capable(int id) +{ + int flags; + if ( get_place_class(&flags, NULL, id) == NULL ) + return false; + return (flags & PCF_EA_CAPABLE) != 0; +} + +//------------------------------------------------------------------------- +/// Get the place class ID for the place that has been registered as 'name'. +/// \param name the class name +/// \return the place class ID, or -1 if not found +idaman int ida_export get_place_class_id(const char *name); + +#ifndef __UI__ + // A TWidget represents any user-facing widget present in IDA. + // E.g., "IDA View-*", "Hex View-*", "Imports", "General registers", ... + class TWidget; +#else + #ifdef __QT__ + namespace QT + { + class QWidget; + }; + typedef QT::QWidget TWidget; + #else + class TView; + typedef TView TWidget; + #endif +#endif + +//------------------------------------------------------------------------- +class sync_source_t +{ + uchar storage[16]; + + const TWidget **get_widget_ptr_storage() const + { + return (const TWidget **) &storage[sizeof(storage) - sizeof(TWidget *)]; + } + +public: + sync_source_t(); // No + sync_source_t(const TWidget *_view) + { + memset(storage, 0, sizeof(storage)); + *get_widget_ptr_storage() = _view; + storage[0] = '\0'; + } + sync_source_t(const char *_regname) + { + QASSERT(1716, _regname[0] != '\0'); + memset(storage, 0, sizeof(storage)); + qstrncpy((char *) storage, _regname, sizeof(storage)); + } + + bool operator==(const sync_source_t &_o) const + { + return memcmp(storage, _o.storage, sizeof(storage)) == 0; + } + bool operator!=(const sync_source_t &_o) const + { + return !((*this) == _o); + } + + bool is_register() const { return storage[0] != '\0'; } + bool is_widget() const { return !is_register(); } + const TWidget *get_widget() const + { + QASSERT(1717, is_widget()); + return *get_widget_ptr_storage(); + } + const char *get_register() const + { + QASSERT(1718, is_register()); + return (const char *) storage; + } +}; +DECLARE_TYPE_AS_MOVABLE(sync_source_t); +CASSERT(sizeof(sync_source_t) == 16); +typedef qvector<sync_source_t> sync_source_vec_t; + +struct synced_group_t : public sync_source_vec_t +{ + bool has_widget(const TWidget *v) const { return has(sync_source_t((TWidget *) v)); } + bool has_register(const char *r) const { return has(sync_source_t(r)); } + bool has(const sync_source_t &ss) const { return find(ss) != end(); } +}; + +//------------------------------------------------------------------------- +/// Converts from an entry with a given place type, to another entry, +/// with another place type, to be used with the view 'view'. Typically +/// used when views are synchronized. +/// The 'renderer_info_t' part of 'dst' will be pre-filled with +/// the current renderer_info_t of 'view', while the 'place_t' instance +/// will always be NULL. +enum lecvt_code_t +{ + LECVT_CANCELED = -1, + LECVT_ERROR = 0, + LECVT_OK = 1, +}; + +#define LECVT_WITHIN_LISTING 0x1 // only perform conversion if the location is contained in the current listing (e.g., in the decompiler, don't decompile other functions) +typedef lecvt_code_t idaapi lochist_entry_cvt2_t( + lochist_entry_t *dst, + const lochist_entry_t &src, + TWidget *view, + uint32 flags); + +//------------------------------------------------------------------------- +/// Register a converter, that will be used for the following reasons: +/// - determine what view can be synchronized with what other view +/// - when views are synchronized, convert the location from one view, +/// into an appropriate location in the other view +/// - if one of p1 or p2 is "idaplace_t", and the other is PCF_EA_CAPABLE, +/// then the converter will also be called when the user wants to jump to +/// an address (e.g., by pressing "g"). In that case, from's place_t's lnnum +/// will be set to -1 (i.e., can be used to descriminate between proper +/// synchronizations, and jump to's if needed.) +/// +/// Note: the converter can be used to convert in both directions, and can be +/// called with its 'from' being of the class of 'p1', or 'p2'. +/// If you want your converter to work in only one direction (e.g., from +/// 'my_dictionary_place_t' -> 'my_definition_place_t'), you can have it +/// return false when it is called with a lochist_entry_t's whose place is +/// of type 'my_definition_place_t'. +/// +/// Note: Whenever one of the 'p1' or 'p2' places is unregistered, +/// corresponding converters will be automatically unregistered as well. +/// +/// \param p1 the name of the first place_t class this converter can convert from/to +/// \param p2 the name of the second place_t class this converter can convert from/to +/// \param cvt the converter +idaman void ida_export register_loc_converter2( + const char *p1, + const char *p2, + lochist_entry_cvt2_t *cvt); + +//------------------------------------------------------------------------- +/// Search for a place converter from lochist_entry_t's with places of type +/// 'p1' to lochist_entry_t's with places of type 'p2'. +/// \param p1 the name of the place_t class to convert from +/// \param p2 the name of the place_t class to convert to +/// \return a converter, or NULL if none found +idaman lochist_entry_cvt2_t *ida_export lookup_loc_converter2( + const char *p1, + const char *p2); + + + +//---------------------------------------------------------------------- +/// A position in a text window +class twinpos_t +{ +public: + place_t *at; ///< location in view + int x; ///< cursor x + twinpos_t(void) { at=NULL; x=0; } ///< Constructor + twinpos_t(place_t *t) { at=t; x=0; } ///< Constructor + twinpos_t(place_t *t,int x0) { at=t; x=x0; } ///< Constructor + DEFINE_MEMORY_ALLOCATION_FUNCS() +}; + +/// A line in a text window +class twinline_t +{ +public: + place_t *at; ///< location in view + qstring line; ///< line contents + color_t prefix_color; ///< line prefix color + bgcolor_t bg_color; ///< line background color + bool is_default; ///< is this the default line of the current location? + twinline_t(void) ///< Constructor + { + at = NULL; + prefix_color = 1; + bg_color = DEFCOLOR; + is_default = false; + } + twinline_t(place_t *t, color_t pc, bgcolor_t bc) ///< Constructor + { + at = t; + prefix_color = pc; + bg_color = bc; + is_default = false; + } + DEFINE_MEMORY_ALLOCATION_FUNCS() +}; +DECLARE_TYPE_AS_MOVABLE(twinline_t); + +/// A group of lines in a text window +typedef qvector<twinline_t> text_t; + +#ifndef SWIG + +/// Helper for declaring member functions of the ::linearray_t class +#define DECLARE_LINEARRAY_HELPERS(decl) \ +decl void ida_export linearray_t_ctr(linearray_t *, void *ud); \ +decl void ida_export linearray_t_dtr(linearray_t *); \ +decl int ida_export linearray_t_set_place(linearray_t *, const place_t *new_at); \ +decl bool ida_export linearray_t_beginning(const linearray_t *); \ +decl bool ida_export linearray_t_ending(const linearray_t *); \ +decl const qstring *ida_export linearray_t_down(linearray_t *); \ +decl const qstring *ida_export linearray_t_up(linearray_t *); + +class linearray_t; +DECLARE_LINEARRAY_HELPERS(idaman) +#else +# define DECLARE_LINEARRAY_HELPERS(decl) +#endif // SWIG + +/// The group of lines corresponding to a single place within a view +class linearray_t +{ + DECLARE_LINEARRAY_HELPERS(friend) + int _set_place(const place_t *new_at); + const qstring *_down (void); + const qstring *_up (void); + + qstrvec_t lines; // lines corresponding to the current place_t + place_t *at; + void *ud; // user defined data (UD) + // its meaning depends on the place_t used + color_t prefix_color; // prefix color + bgcolor_t bg_color; // background color + qstring extra; // the last line of the previous location after moving down + int dlnnum; // default line number (if unknown, -1) + + int getlines(void); + void cleanup(void); + +public: + + linearray_t(void *_ud) { linearray_t_ctr(this, _ud); } ///< Constructor + ~linearray_t(void) { linearray_t_dtr(this); } ///< Constructor + DEFINE_MEMORY_ALLOCATION_FUNCS() + + /// Position the array. + /// This function must be called before calling any other member functions. + /// + /// ::linearray_t doesn't own ::place_t structures. + /// The caller must take care of place_t objects. + /// + /// \param new_at new position of the array + /// \return the delta of lines that the linearray_t had to adjust the place by. \n + /// For example, if the place_t has a lnnum of 5, but it turns out, upon generating lines, \n + /// that the number of lines for that particular place is only 2, then 3 will be returned. + int set_place(const place_t *new_at) { return linearray_t_set_place(this, new_at); } + + /// Get the current place. + /// If called before down(), then returns place of line which will be returned by down(). + /// If called after up(), then returns place if line returned by up(). + place_t *get_place (void) const { return at; } + + /// Get current background color. + /// (the same behavior as with get_place(): good before down() and after up()) + bgcolor_t get_bg_color(void) const { return bg_color; } + + /// Get current prefix color. + /// (the same behavior as with get_place(): good before down() and after up()) + bgcolor_t get_pfx_color(void) const { return prefix_color; } + + /// Get default line number. + /// (the same behavior as with get_place(): good before down() and after up()) + int get_dlnnum(void) const { return dlnnum; } + + /// Get number of lines for the current place. + /// (the same behavior as with get_place(): good before down() and after up()) + int get_linecnt(void) const { return int(lines.size()); } + + /// Get pointer to user data + void *userdata(void) const { return ud; } + + /// Change the user data + void set_userdata(void *userd) { ud = userd; } + + /// Are we at the beginning? + bool beginning(void) const { return linearray_t_beginning(this); } + + // Are we at the end? + bool ending(void) const { return linearray_t_ending(this); } + + /// Get a line from down direction. + /// place is ok BEFORE + const qstring *down(void) + { return linearray_t_down(this); } + + /// Get a line from up direction. + /// place is ok AFTER + const qstring *up(void) + { return linearray_t_up(this); } + +}; + +//------------------------------------------------------------------------- +typedef qvector<const twinline_t*> section_lines_refs_t; +typedef qvector<section_lines_refs_t> sections_lines_refs_t; + +//------------------------------------------------------------------------- +/// Contains information necessary for plugins to compute extra +/// information needed for rendering. +struct lines_rendering_input_t +{ + int cb; + sections_lines_refs_t sections_lines; ///< references to the lines that are used for rendering + const synced_group_t *sync_group; ///< the 'synced' group 'widget' (see ui_get_lines_rendering_info) belongs to, or NULL + + lines_rendering_input_t() + : cb(sizeof(*this)), + sync_group(NULL) {} +}; + +//------------------------------------------------------------------------- +/// \defgroup CK_ keys +/// passed as 'bg_color' of a line_rendering_output_entry_t, to use +/// a CSS property of the widget ('qproperty-line-bgovl-extra-N') +/// instead of a direct color +//@{ +// +#define CK_TRACE 80 ///< traced address +#define CK_TRACE_OVL 81 ///< overlay trace address +#define CK_EXTRA1 82 ///< extra background overlay #1 +#define CK_EXTRA2 83 ///< extra background overlay #2 +#define CK_EXTRA3 84 ///< extra background overlay #3 +#define CK_EXTRA4 85 ///< extra background overlay #4 +#define CK_EXTRA5 86 ///< extra background overlay #5 +#define CK_EXTRA6 87 ///< extra background overlay #6 +#define CK_EXTRA7 88 ///< extra background overlay #7 +#define CK_EXTRA8 89 ///< extra background overlay #8 +#define CK_EXTRA9 90 ///< extra background overlay #9 +#define CK_EXTRA10 91 ///< extra background overlay #10 +#define CK_EXTRA11 92 ///< extra background overlay #11 +#define CK_EXTRA12 93 ///< extra background overlay #12 +#define CK_EXTRA13 94 ///< extra background overlay #13 +#define CK_EXTRA14 95 ///< extra background overlay #14 +#define CK_EXTRA15 96 ///< extra background overlay #15 +#define CK_EXTRA16 97 ///< extra background overlay #16 + +//@} + +/// \defgroup LROEF_ line_rendering_output_entry_t flags +/// used by 'flags' of a line_rendering_output_entry_t +//@{ +#define LROEF_MASK 0x00FFFFFF +#define LROEF_FULL_LINE 0x00000000 ///< full line background +#define LROEF_CPS_RANGE 0x00000001 ///< background for range of chars +//@} + +struct line_rendering_output_entry_t +{ + const twinline_t *line; + uint32 flags; ///< \ref LROEF_ + + // 0x00000000: nothing + // 0xAABBGGRR: where AA is 0: BBGGRR contains a key (CK_*) to a color property + // 0xAABBGGRR: where AA is !0: 0xAABBGGRR is the background color, with alpha value, to be applied to that line + // + // The 'bg_color' specified here, will be applied on top of the background + // color that was computed for 'line', which itself can be: + // - none (i.e., the default background color), + // - a possible value stored in the IDB (see 'set_item_color()'), + // - a value provided by processor_t::ev_get_bg_color + // The value provided here should typically be partly transparent + // so that it doesn't obstruct the computed background color + // (the best, by far, is to stick to CK_* keys: their corresponding + // colors typically have partial translucency, and each theme can + // customize them.) + bgcolor_t bg_color; + + int cpx; ///< number of char to start from, valid if LROEF_CPS_RANGE + int nchars; ///< chars count, valid if LROEF_CPS_RANGE + + line_rendering_output_entry_t(const twinline_t *_line, uint32 _flags=0, bgcolor_t _bg_color=0) + : line(_line), flags(_flags), bg_color(_bg_color), cpx(-1), nchars(-1) {} + + line_rendering_output_entry_t(const twinline_t *_line, int _cpx, int _nchars, uint32 _flags, bgcolor_t _bg_color) + : line(_line), flags(_flags|LROEF_CPS_RANGE), bg_color(_bg_color), cpx(_cpx), nchars(_nchars) {} + + bool is_bg_color_empty() const { return bg_color == 0; } + bool is_bg_color_key() const { return (bg_color & 0xFF000000) == 0 && !is_bg_color_empty(); } + bool is_bg_color_direct() const { return (bg_color & 0xFF000000) != 0; } + + bool operator==(const line_rendering_output_entry_t &r) const + { + bool ok = (flags & LROEF_MASK) == (r.flags & LROEF_MASK) + && line == r.line + && bg_color == r.bg_color; + if ( ok && (flags & LROEF_CPS_RANGE) != 0 ) + ok = cpx == r.cpx && nchars == r.nchars; + return ok; + } + + bool operator!=(const line_rendering_output_entry_t &r) const + { return !(*this == r); } +}; +DECLARE_TYPE_AS_MOVABLE(line_rendering_output_entry_t); +typedef qvector<line_rendering_output_entry_t*> line_rendering_output_entries_refs_t; + +//------------------------------------------------------------------------- +struct lines_rendering_output_t +{ + line_rendering_output_entries_refs_t entries; + uint32 flags; + + lines_rendering_output_t() : flags(0) {} + ~lines_rendering_output_t() + { + clear(); + } + + void clear() + { + for ( size_t i = 0, n = entries.size(); i < n; ++i ) + delete entries[i]; + } + + bool operator==(const lines_rendering_output_t &r) const + { + if ( flags != r.flags ) + return false; + const size_t n = entries.size(); + if ( n != r.entries.size() ) + return false; + for ( size_t i = 0; i < n; ++i ) + if ( *entries[i] != *r.entries[i] ) + return false; + return true; + } + + bool operator!=(const lines_rendering_output_t &r) const + { return !(*this == r); } + + void swap(lines_rendering_output_t &r) + { + qswap(flags, r.flags); + entries.swap(r.entries); + } +}; + + +#ifndef SWIG +/// Bitmask of builtin window types to be refreshed: +idaman uint64 ida_export get_dirty_infos(void); +#endif // SWIG + + +/// Request a refresh of a builtin window. +/// \param mask \ref IWID_ +/// \param cnd set if true or clear flag otherwise + +idaman void ida_export request_refresh(uint64 mask, bool cnd=true); +inline void clear_refresh_request(uint64 mask) { request_refresh(mask, false); } + + +/// Get a refresh request state +/// \param mask \ref IWID_ +/// \returns the state (set or cleared) + +idaman bool ida_export is_refresh_requested(uint64 mask); + + +//------------------------------------------------------------------------- +typedef int twidget_type_t; ///< \ref BWN_ + +/// \defgroup BWN_ Window types +/// also see \ref ui_open_builtin_funcs +//@{ +#define BWN_UNKNOWN -1 ///< unknown window +#define BWN_EXPORTS 0 ///< exports +#define BWN_IMPORTS 1 ///< imports +#define BWN_NAMES 2 ///< names +#define BWN_FUNCS 3 ///< functions +#define BWN_STRINGS 4 ///< strings +#define BWN_SEGS 5 ///< segments +#define BWN_SEGREGS 6 ///< segment registers +#define BWN_SELS 7 ///< selectors +#define BWN_SIGNS 8 ///< signatures +#define BWN_TILS 9 ///< type libraries +#define BWN_LOCTYPS 10 ///< local types +#define BWN_CALLS 11 ///< function calls +#define BWN_PROBS 12 ///< problems +#define BWN_BPTS 13 ///< breakpoints +#define BWN_THREADS 14 ///< threads +#define BWN_MODULES 15 ///< modules +#define BWN_TRACE 16 ///< tracing view +#define BWN_CALL_STACK 17 ///< call stack +#define BWN_XREFS 18 ///< xrefs +#define BWN_SEARCH 19 ///< search results +#define BWN_FRAME 25 ///< function frame +#define BWN_NAVBAND 26 ///< navigation band +#define BWN_ENUMS 27 ///< enumerations +#define BWN_STRUCTS 28 ///< structures +#define BWN_DISASM 29 ///< disassembly views +#define BWN_DUMP 30 ///< hex dumps +#define BWN_NOTEPAD 31 ///< notepad +#define BWN_OUTPUT 32 ///< the text area, in the output window +#define BWN_CLI 33 ///< the command-line, in the output window +#define BWN_WATCH 34 ///< the 'watches' debugger window +#define BWN_LOCALS 35 ///< the 'locals' debugger window +#define BWN_STKVIEW 36 ///< the 'Stack view' debugger window +#define BWN_CHOOSER 37 ///< a non-builtin chooser +#define BWN_SHORTCUTCSR 38 ///< the shortcuts chooser (Qt version only) +#define BWN_SHORTCUTWIN 39 ///< the shortcuts window (Qt version only) +#define BWN_CPUREGS 40 ///< one of the 'General registers', 'FPU register', ... debugger windows +#define BWN_SO_STRUCTS 41 ///< the 'Structure offsets' dialog's 'Structures and Unions' panel +#define BWN_SO_OFFSETS 42 ///< the 'Structure offsets' dialog's offset panel +#define BWN_CMDPALCSR 43 ///< the command palette chooser (Qt version only) +#define BWN_CMDPALWIN 44 ///< the command palette window (Qt version only) +#define BWN_SNIPPETS 45 ///< the 'Execute script' window +#define BWN_CUSTVIEW 46 ///< custom viewers +#define BWN_ADDRWATCH 47 ///< the 'Watch List' window +#define BWN_PSEUDOCODE 48 ///< hexrays decompiler views +#define BWN_CALLS_CALLERS 49 ///< function calls, callers +#define BWN_CALLS_CALLEES 50 ///< function calls, callees +#define BWN_MDVIEWCSR 51 ///< lumina metadata view chooser +#define BWN_DISASM_ARROWS 52 ///< disassembly arrows widget +#define BWN_CV_LINE_INFOS 53 ///< custom viewers' lineinfo widget +#define BWN_SRCPTHMAP_CSR 54 ///< "Source paths..."'s path mappings chooser +#define BWN_SRCPTHUND_CSR 55 ///< "Source paths..."'s undesired paths chooser +#define BWN_UNDOHIST 56 ///< Undo history +#define BWN_SNIPPETS_CSR 57 ///< the list of snippets in the 'Execute script' window +#define BWN_SCRIPTS_CSR 58 ///< the "Recent scripts" chooser +#define BWN_BOOKMARKS 59 ///< a persistent 'Bookmarks' widget +// #define BWN_DIFF_MERGE 60 ///< the "Diff/merge" 2-3 panels view + +/// Alias. Some BWN_* were confusing, and thus have been renamed. +/// This is to ensure bw-compat. +#define BWN_STACK BWN_CALL_STACK +#define BWN_DISASMS BWN_DISASM ///< \copydoc BWN_STACK +#define BWN_DUMPS BWN_DUMP ///< \copydoc BWN_STACK +#define BWN_SEARCHS BWN_SEARCH ///< \copydoc BWN_STACK +//@} + +/// \defgroup IWID_ Window refresh flags +/// passed as 'mask' parameter to request_refresh() +//@{ +#define IWID_EXPORTS (1ULL << BWN_EXPORTS ) ///< exports (0) +#define IWID_IMPORTS (1ULL << BWN_IMPORTS ) ///< imports (1) +#define IWID_NAMES (1ULL << BWN_NAMES ) ///< names (2) +#define IWID_FUNCS (1ULL << BWN_FUNCS ) ///< functions (3) +#define IWID_STRINGS (1ULL << BWN_STRINGS ) ///< strings (4) +#define IWID_SEGS (1ULL << BWN_SEGS ) ///< segments (5) +#define IWID_SEGREGS (1ULL << BWN_SEGREGS ) ///< segment registers (6) +#define IWID_SELS (1ULL << BWN_SELS ) ///< selectors (7) +#define IWID_SIGNS (1ULL << BWN_SIGNS ) ///< signatures (8) +#define IWID_TILS (1ULL << BWN_TILS ) ///< type libraries (9) +#define IWID_LOCTYPS (1ULL << BWN_LOCTYPS ) ///< local types (10) +#define IWID_CALLS (1ULL << BWN_CALLS ) ///< function calls (11) +#define IWID_PROBS (1ULL << BWN_PROBS ) ///< problems (12) +#define IWID_BPTS (1ULL << BWN_BPTS ) ///< breakpoints (13) +#define IWID_THREADS (1ULL << BWN_THREADS ) ///< threads (14) +#define IWID_MODULES (1ULL << BWN_MODULES ) ///< modules (15) +#define IWID_TRACE (1ULL << BWN_TRACE ) ///< tracing view (16) +#define IWID_CALL_STACK (1ULL << BWN_CALL_STACK ) ///< call stack (17) +#define IWID_XREFS (1ULL << BWN_XREFS ) ///< xrefs (18) +#define IWID_SEARCH (1ULL << BWN_SEARCH ) ///< search results (19) +#define IWID_FRAME (1ULL << BWN_FRAME ) ///< function frame (25) +#define IWID_NAVBAND (1ULL << BWN_NAVBAND ) ///< navigation band (26) +#define IWID_ENUMS (1ULL << BWN_ENUMS ) ///< enumerations (27) +#define IWID_STRUCTS (1ULL << BWN_STRUCTS ) ///< structures (28) +#define IWID_DISASM (1ULL << BWN_DISASM ) ///< disassembly views (29) +#define IWID_DUMP (1ULL << BWN_DUMP ) ///< hex dumps (30) +#define IWID_NOTEPAD (1ULL << BWN_NOTEPAD ) ///< notepad (31) +#define IWID_OUTPUT (1ULL << BWN_OUTPUT ) ///< output (32) +#define IWID_CLI (1ULL << BWN_CLI ) ///< input line (33) +#define IWID_WATCH (1ULL << BWN_WATCH ) ///< watches (34) +#define IWID_LOCALS (1ULL << BWN_LOCALS ) ///< locals (35) +#define IWID_STKVIEW (1ULL << BWN_STKVIEW ) ///< stack view (36) +#define IWID_CHOOSER (1ULL << BWN_CHOOSER ) ///< chooser (37) +#define IWID_SHORTCUTCSR (1ULL << BWN_SHORTCUTCSR ) ///< shortcuts chooser (38) +#define IWID_SHORTCUTWIN (1ULL << BWN_SHORTCUTWIN ) ///< shortcuts window (39) +#define IWID_CPUREGS (1ULL << BWN_CPUREGS ) ///< registers (40) +#define IWID_SO_STRUCTS (1ULL << BWN_SO_STRUCTS ) ///< stroff (41) +#define IWID_SO_OFFSETS (1ULL << BWN_SO_OFFSETS ) ///< stroff (42) +#define IWID_CMDPALCSR (1ULL << BWN_CMDPALCSR ) ///< command palette (43) +#define IWID_CMDPALWIN (1ULL << BWN_CMDPALWIN ) ///< command palette (44) +#define IWID_SNIPPETS (1ULL << BWN_SNIPPETS ) ///< snippets (45) +#define IWID_CUSTVIEW (1ULL << BWN_CUSTVIEW ) ///< custom viewers (46) +#define IWID_ADDRWATCH (1ULL << BWN_ADDRWATCH ) ///< address watches (47) +#define IWID_PSEUDOCODE (1ULL << BWN_PSEUDOCODE ) ///< decompiler (48) +#define IWID_CALLS_CALLERS (1ULL << BWN_CALLS_CALLERS) ///< funcalls, callers (49) +#define IWID_CALLS_CALLEES (1ULL << BWN_CALLS_CALLEES) ///< funcalls, callees (50) +#define IWID_MDVIEWCSR (1ULL << BWN_MDVIEWCSR ) ///< lumina md view (51) +#define IWID_DISASM_ARROWS (1ULL << BWN_DISASM_ARROWS) ///< arrows widget (52) +#define IWID_CV_LINE_INFOS (1ULL << BWN_CV_LINE_INFOS) ///< lineinfo widget (53) +#define IWID_SRCPTHMAP_CSR (1ULL << BWN_SRCPTHMAP_CSR) ///< mappings chooser (54) +#define IWID_SRCPTHUND_CSR (1ULL << BWN_SRCPTHUND_CSR) ///< undesired chooser (55) +#define IWID_UNDOHIST (1ULL << BWN_UNDOHIST ) ///< Undo history (56) +#define IWID_SNIPPETS_CSR (1ULL << BWN_SNIPPETS_CSR ) ///< snippets chooser (57) +#define IWID_SCRIPTS_CSR (1ULL << BWN_SCRIPTS_CSR ) ///< recent scripts (58) +#define IWID_BOOKMARKS (1ULL << BWN_BOOKMARKS) ///< bookmarks list (59) +// #define IWID_DIFF_MERGE (1ULL << BWN_DIFF_MERGE ) ///< diff/merge view (60) + +#define IWID_IDAMEMOS (IWID_DISASMS|IWID_DUMPS ) ///< disassembly + hex dump views +#define IWID_ALL 0xFFFFFFFFFFFFFFFFULL ///< mask + +/// Alias. Some IWID_* were confusing, and thus have been renamed. +/// This is to ensure bw-compat. +#define IWID_STACK IWID_CALL_STACK +#define IWID_DISASMS IWID_DISASM +#define IWID_DUMPS IWID_DUMP +#define IWID_SEARCHS IWID_SEARCH +//@} + +/// Does the given widget type specify a chooser widget? + +inline bool is_chooser_widget(twidget_type_t t) +{ + return t == BWN_CHOOSER + || (t >= BWN_EXPORTS && t <= BWN_SEARCH && t != BWN_CALLS) + || t == BWN_SHORTCUTCSR + || t == BWN_CMDPALCSR + || t == BWN_CALLS_CALLERS + || t == BWN_CALLS_CALLEES + || t == BWN_MDVIEWCSR + || t == BWN_SRCPTHMAP_CSR + || t == BWN_SRCPTHUND_CSR + || t == BWN_UNDOHIST + || t == BWN_SNIPPETS_CSR + || t == BWN_SCRIPTS_CSR + || t == BWN_BOOKMARKS; +} + + +#ifndef SWIG +//--------------------------------------------------------------------------- +// D E B U G G I N G F U N C T I O N S +//--------------------------------------------------------------------------- + +/// Controls debug messages - combination of \ref IDA_DEBUG_ +idaman uint32 ida_export_data debug; + +/// \defgroup IDA_DEBUG_ IDA debug bits +/// used by ::debug +//@{ +#define IDA_DEBUG_DREFS 0x00000001 ///< drefs +#define IDA_DEBUG_OFFSET 0x00000002 ///< offsets +#define IDA_DEBUG_FLIRT 0x00000004 ///< flirt +#define IDA_DEBUG_IDP 0x00000008 ///< idp module +#define IDA_DEBUG_LDR 0x00000010 ///< ldr module +#define IDA_DEBUG_PLUGIN 0x00000020 ///< plugin module +#define IDA_DEBUG_IDS 0x00000040 ///< ids files +#define IDA_DEBUG_CONFIG 0x00000080 ///< config file +#define IDA_DEBUG_CHECKMEM 0x00000100 ///< check heap consistency +#define IDA_DEBUG_CHECKARG 0x00000200 ///< checkarg +#define IDA_DEBUG_DEMANGLE 0x00000400 ///< demangler +#define IDA_DEBUG_QUEUE 0x00000800 ///< queue +#define IDA_DEBUG_ROLLBACK 0x00001000 ///< rollback +#define IDA_DEBUG_ALREADY 0x00002000 ///< already data or code +#define IDA_DEBUG_TIL 0x00004000 ///< type system +#define IDA_DEBUG_NOTIFY 0x00008000 ///< show all notifications +#define IDA_DEBUG_DEBUGGER 0x00010000 ///< debugger +#define IDA_DEBUG_APPCALL 0x00020000 ///< appcall +#define IDA_DEBUG_SRCDBG 0x00040000 ///< source debugging +#define IDA_DEBUG_ACCESSIBILITY 0x00080000 ///< accessibility +#define IDA_DEBUG_NETWORK 0x00100000 ///< network +#define IDA_DEBUG_INTERNET IDA_DEBUG_NETWORK ///< internet connection (for API backward compatibility) +#define IDA_DEBUG_SIMPLEX 0x00200000 ///< full stack analysis +#define IDA_DEBUG_DBGINFO 0x00400000 ///< handling of debug info (e.g. pdb, dwarf) +#define IDA_DEBUG_LUMINA 0x00800000 ///< lumina related +#define IDA_DEBUG_THEMES 0x01000000 ///< themes +#define IDA_DEBUG_REGEX 0x02000000 ///< regular expression +#define IDA_DEBUG_ALWAYS 0xFFFFFFFF ///< everything +//@} + + +/// Display debug message. +/// \param ida_debug_bits \ref IDA_DEBUG_, also see ::debug +/// \param format printf()-style format +/// \return number of bytes output +/// Note: use deb() macro + +AS_PRINTF(1, 2) inline int ida_deb(const char *format, ...) +{ + va_list va; + va_start(va, format); + int nbytes = callui(ui_msg, format, va).i; + va_end(va); + return nbytes; +} + +#define deb(ida_debug_bits, ...) \ + do \ + { \ + if ( (debug & (ida_debug_bits)) != 0 ) \ + ida_deb(__VA_ARGS__); \ + } while ( false ) + + +/// Checking heap is not available anymore. +#define checkmem() do {} while (0) // ida_checkmem(__FILE__, __LINE__) +/// \copydoc checkmem() +idaman void ida_export ida_checkmem(const char *file, int line); + + +/// Display hex dump in the messages window + +AS_PRINTF(3, 4) inline void show_hex( + const void *dataptr, + size_t len, + const char *format, + ...) +{ + va_list va; + va_start(va,format); + vshow_hex(dataptr, len, format, va); + va_end(va); +} + + +/// Display hex dump of a file in the messages window + +AS_PRINTF(4, 5) inline void show_hex_file( + linput_t *li, + int64 pos, + size_t count, + const char *format, + ...) +{ + va_list va; + va_start(va,format); + vshow_hex_file(li, pos, count, format, va); + va_end(va); +} +#endif // SWIG + +//------------------------------------------------------------------------- +// U I S E R V I C E F U N C T I O N S +//------------------------------------------------------------------------- + +/// \defgroup CH_ Generic chooser flags +/// used as 'chooser_base_t::flags' +//@{ +/// Modal chooser +#define CH_MODAL 0x00000001 +/// The chooser instance's lifecycle is not tied to the lifecycle of the +/// widget showing its contents. Closing the widget will not destroy the +/// chooser structure. This allows for, e.g., static global chooser instances +/// that don't need to be allocated on the heap. Also stack-allocated chooser +/// instances must set this bit. +#define CH_KEEP 0x00000002 +/// The chooser will allow multi-selection (only for GUI choosers). This bit +/// is set when using the chooser_multi_t structure. +#define CH_MULTI 0x00000004 +///< Obsolete +#define CH_MULTI_EDIT 0x00000008 +/// do not display ok/cancel/help/search buttons. +/// Meaningful only for gui modal windows because non-modal windows do not +/// have any buttons anyway. Text mode does not have them neither. +#define CH_NOBTNS 0x00000010 +/// generate ui_get_chooser_item_attrs (gui only) +#define CH_ATTRS 0x00000020 +/// use the chooser before opening the database +#define CH_NOIDB 0x00000040 +/// if a non-modal chooser was already open, change selection to the default +/// one +#define CH_FORCE_DEFAULT 0x00000080 +/// allow to insert new items +#define CH_CAN_INS 0x00000100 +/// allow to delete existing item(s) +#define CH_CAN_DEL 0x00000200 +/// allow to edit existing item(s) +#define CH_CAN_EDIT 0x00000400 +/// allow to refresh chooser +#define CH_CAN_REFRESH 0x00000800 + +/// open with quick filter enabled and focused +#define CH_QFLT 0x00001000 +#define CH_QFTYP_SHIFT 13 +#define CH_QFTYP_DEFAULT 0 ///< set quick filtering type to the possible existing default for this chooser +#define CH_QFTYP_NORMAL (1 << CH_QFTYP_SHIFT) ///< normal (i.e., lexicographical) quick filter type +#define CH_QFTYP_WHOLE_WORDS (2 << CH_QFTYP_SHIFT) ///< whole words quick filter type +#define CH_QFTYP_REGEX (3 << CH_QFTYP_SHIFT) ///< regex quick filter type +#define CH_QFTYP_FUZZY (4 << CH_QFTYP_SHIFT) ///< fuzzy search quick filter type +#define CH_QFTYP_MASK (0x7 << CH_QFTYP_SHIFT) + +/// don't show a status bar +#define CH_NO_STATUS_BAR 0x00010000 + +/// restore floating position if present (equivalent of WOPN_RESTORE) (GUI version only) +#define CH_RESTORE 0x00020000 + +/// triggering a 'edit/rename' (i.e., F2 shortcut) on a cell, +/// should call the edit() callback for the corresponding row. +#define CH_RENAME_IS_EDIT 0x00040000 + +#define CH_BUILTIN_SHIFT 19 +#define CH_BUILTIN(id) ((id+1) << CH_BUILTIN_SHIFT) +/// Mask for builtin chooser numbers. Plugins should not use them. +#define CH_BUILTIN_MASK (0x3F << CH_BUILTIN_SHIFT) + +/// The chooser can provide a dirtree_t, meaning a tree-like structure +/// can be provided to the user (instead of a flat table) +#define CH_HAS_DIRTREE 0x02000000 + +#define CH_TM_NO_TREE 0x00000000 ///< chooser will show up in no-tree mode +#define CH_TM_FOLDERS_ONLY 0x04000000 ///< chooser will show in folders-only mode +#define CH_TM_FULL_TREE 0x08000000 ///< chooser will show in no-tree mode +#define CH_TM_SHIFT 26 +#define CH_TM_MASK (0x3 << CH_TM_SHIFT) + +/// The chooser can be used in a diffing/merging workflow +#define CH_HAS_DIFF 0x10000000 + +/// The chooser will not have sorting abilities +#define CH_NO_SORT 0x20000000 + +/// The chooser will not have filtering abilities +#define CH_NO_FILTER 0x40000000 + +//#define CH_FREE 0x80000000 +//@} + +/// \defgroup CHCOL_ Chooser column flags +/// used by 'widths' parameter for \ref choosers +//@{ +#define CHCOL_PLAIN 0x00000000 ///< plain string +#define CHCOL_PATH 0x00010000 ///< file path +#define CHCOL_HEX 0x00020000 ///< hexadecimal number +#define CHCOL_DEC 0x00030000 ///< decimal number +#define CHCOL_EA 0x00040000 ///< address +#define CHCOL_FNAME 0x00050000 ///< function name +#define CHCOL_FORMAT 0x00070000 ///< column format mask + +#define CHCOL_DEFHIDDEN 0x00100000 ///< column should be hidden by default +#define CHCOL_DRAGHINT 0x00200000 ///< the column number that will be used + ///< to build hints for the dragging undo + ///< label. This should be provided for at + ///< most one column for any given chooser. +#define CHCOL_INODENAME 0x00400000 ///< if CH_HAS_DIRTREE has been specified, + ///< this instructs the chooser that this + ///< column shows the inode name. This + ///< should be provided for at most one + ///< column for any given chooser. +//@} + + +/// \defgroup CHITEM_ Chooser item property bits +/// used by chooser_item_attrs_t::flags +//@{ +#define CHITEM_BOLD 0x0001 ///< display the item in bold +#define CHITEM_ITALIC 0x0002 ///< display the item in italic +#define CHITEM_UNDER 0x0004 ///< underline the item +#define CHITEM_STRIKE 0x0008 ///< strikeout the item +#define CHITEM_GRAY 0x0010 ///< gray out the item +//@} + +/// \name Chooser title +/// prefixes to be used in the chooser title +//@{ +#define CHOOSER_NOMAINMENU "NOMAINMENU\n" ///< do not display main menu +#define CHOOSER_NOSTATUSBAR "NOSTATUSBAR\n" ///< do not display status bar (obsolete. Use CH_NO_STATUS_BAR instead) +//@} + +class dirtree_t; + +/// Chooser item attributes +struct chooser_item_attrs_t +{ + int cb; ///< size of this structure. + ///< the callback must check this field and fill only + ///< the existing fields. the first 2 fields always exist: + int flags; ///< \ref CHITEM_ + bgcolor_t color; ///< item color + chooser_item_attrs_t() + : cb(sizeof(chooser_item_attrs_t)), + flags(0), + color(DEFCOLOR) {} + void reset(void) ///< restore to defaults + { + cb = sizeof(chooser_item_attrs_t); + flags = 0; + color = DEFCOLOR; + } +}; + +/// Chooser object. #chooser +struct chooser_base_t +{ +#ifdef SWIG + %immutable; +#endif +protected: + uint32 version; ///< version of the class + + uint32 flags; ///< \ref CH_ + +public: + // TODO reduce to 4 values + // embedded chooser: width, height. Other values are ignored. + // qt: y1 == -2 => minimal height (and centered) + // Other values are ignored. + int x0; ///< screen position, \ref choosers + int y0; + int x1; + int y1; + int width; ///< (in chars) + int height; ///< (in chars) + + const char *title; ///< menu title (includes ptr to help). + ///< May have chooser title prefixes (see "Chooser + ///< title" above). + int columns; ///< number of columns + const int *widths; ///< column widths + ///< - low 16 bits of each value hold the column width + ///< - high 16 bits are flags (see \ref CHCOL_) + const char *const *header; + ///< header line; contains the tooltips, and column name + ///< for each of 'columns' columns. + ///< When tooltips need to be provided, the syntax + ///< should be: "#tooltip#column-name". (Otherwise, + ///< the syntax is simply "column-name".) + int icon; ///< default icon + + /// \defgroup chooser_index Special values of the chooser index + /// Used in the following contexts: + /// 1. as the return value of the choose() function + /// 2. as the `idx` field of the return value of the get_item_index(), + /// ins(), del(), edit(), enter(), refresh() callbacks of the + /// `chooser_t` structure + /// 3. as the parameter `n` of the chooser_t::refresh() callback + /// Usage matrix + // Context | 1 | 2 | 3 + // --------------------------- + // NO_SELECTION | X | X | X + // EMPTY_CHOOSER | X | | + // ALREADY_EXISTS | X | | + //@{ + enum + { + NO_SELECTION = -1, ///< there is no selected item + EMPTY_CHOOSER = -2, ///< the chooser has no data and cannot be + ///< displayed + ALREADY_EXISTS = -3, ///< the non-modal chooser with the same data is + ///< already open + NO_ATTR = -4, ///< reserved for IDAPython + }; + //@} + + enum { POPUP_INS, POPUP_DEL, POPUP_EDIT, POPUP_REFRESH, NSTDPOPUPS }; + /// array of custom popup menu names. + /// Used to replace labels for the standard handlers (Insert, Delete, + /// Edit, Refresh). \n + /// An empty name means that the default name will be used. + /// \note Availability of items in the popup menu is determined by the + /// `CH_CAN_...` flags. + qstring popup_names[NSTDPOPUPS]; + + int deflt_col; ///< Column that will have focus. + + chooser_base_t( + uint32 flags_ = 0, + int columns_ = 0, + const int *widths_ = NULL, + const char *const *header_ = NULL, + const char *title_ = NULL) + : version(1), + flags(flags_), + x0(-1), y0(-1), x1(-1), y1(-1), + width(0), + height(0), + title(title_), + columns(columns_), + widths(widths_), + header(header_), + icon(-1), + deflt_col(0) {} + virtual ~chooser_base_t() {} + DEFINE_MEMORY_ALLOCATION_FUNCS() + + // called when the corresponding widget is destroyed. + // + // In some rare cases where multiple chooser_base_t instance can + // be backed by the same data (\sa get_obj_id), and a second instance + // is created while the first is already displayed (therefore making + // that second instance a duplicate), the second instance will be + // destroyed through this method (and chooser_base_t::ALREADY_EXISTS + // will be returned from choose().) + void call_destructor() + { + if ( (flags & CH_KEEP) == 0 ) + delete this; + } + + /// get pointer to some custom data. + /// \note These data are also called "the underlying object". + /// Now this method is used only in the ActionsInspector class and + /// ida_kernwin.Choose IDAPython's class. + virtual void *get_chooser_obj() { return this; } + + /// get the id of the chooser data. + /// The choosers are the same if they have the same data ids. + /// \param[out] len length of the id. If it is 0 then it is considered + /// that the method returned an unique id. + /// \return address of the id or NULL in the case len == 0 + virtual const void *get_obj_id(size_t *len) const + { + // return the unique id + *len = 0; + return NULL; + } + + /// do the current and the given objects hold the same data? + bool is_same(const chooser_base_t *other) const + { + size_t len1; + const void *id1 = get_obj_id(&len1); + size_t len2; + const void *id2 = other->get_obj_id(&len2); + return len1 == len2 && len1 != 0 && memcmp(id1, id2, len1) == 0; + } + + /// is an operation allowed? + bool can_ins() const { return (flags & CH_CAN_INS ) != 0; } + bool can_del() const { return (flags & CH_CAN_DEL ) != 0; } + bool can_edit() const { return (flags & CH_CAN_EDIT ) != 0; } + bool can_refresh() const { return (flags & CH_CAN_REFRESH) != 0; } + + /// is a popup action allowed? + bool popup_allowed(int i) const + { + switch ( i ) + { + case POPUP_INS: return can_ins(); + case POPUP_DEL: return can_del(); + case POPUP_EDIT: return can_edit(); + case POPUP_REFRESH: return can_refresh(); + default: return false; + } + } + bool is_status_bar_hidden() const { return (flags & CH_NO_STATUS_BAR) != 0; } + bool should_restore_geometry() const { return (flags & CH_RESTORE) != 0; } + /// is choose modal? + bool is_modal() const { return (flags & CH_MODAL) != 0; } + /// is multi-selection allowed? + bool is_multi() const { return (flags & CH_MULTI) != 0; } + /// should chooser generate ui_get_chooser_item_attrs events? + bool ask_item_attrs() const { return (flags & CH_ATTRS) != 0; } + /// can use the chooser before opening the database? + bool is_noidb() const { return (flags & CH_NOIDB) != 0; } + /// should selection of the already opened non-modal chooser be changed? + bool is_force_default() const { return (flags & CH_FORCE_DEFAULT) != 0; } + /// get number of the built-in chooser + uint get_builtin_number() const + { + return ((flags & CH_BUILTIN_MASK) >> CH_BUILTIN_SHIFT) - 1; + } + /// enable or disable generation of ui_get_chooser_item_attrs events + void set_ask_item_attrs(bool enable) + { + if ( enable ) + flags |= CH_ATTRS; + else + flags &= ~CH_ATTRS; + } + // check chooser version + void check_version(uint32 ver) const { QASSERT(40217, version >= ver); } + // should the quick filter be visible at startup? + bool is_quick_filter_visible_initially() const { return (flags & CH_QFLT) != 0; } + // what mode should the quick filter initially be put in? + int get_quick_filter_initial_mode() const { return flags & CH_QFTYP_MASK; } + // does the chooser have the ability to show a tree view? + bool has_dirtree() const { return (flags & CH_HAS_DIRTREE) != 0; } + // does the chooser have the ability to participate in a diff/merge workflow? + bool has_diff_capability() const { return (flags & CH_HAS_DIFF) != 0; } + // does chooser have sorting abilities? + bool can_sort() const { return (flags & CH_NO_SORT) == 0; } + // does chooser have filtering abilities? + bool can_filter() const { return (flags & CH_NO_FILTER) == 0; } + // should renaming trigger the 'edit' callback? + bool should_rename_trigger_edit() const { return (flags & CH_RENAME_IS_EDIT) != 0; } + + /// initialize the chooser and populate it. + /// \retval false the chooser is empty, do not display it + virtual bool idaapi init() { return true; } + + /// get the number of elements in the chooser + virtual size_t idaapi get_count() const = 0; + + /// get a description of an element. + /// \param[out] out vector of strings. \n + /// will receive the contents of each column + /// \param[out] out_icon element's icon id, -1 - no icon + /// \param[out] out_attrs element attributes + /// \param n element number (0..get_count()-1) + virtual void idaapi get_row( + qstrvec_t *out, + int *out_icon, + chooser_item_attrs_t *out_attrs, + size_t n) const = 0; + + /// get an address of an element. + /// Used to set breakpoint in any chooser which implements this callback. + /// \param n element number (0-based) + /// \return the effective address, BADADDR if the element has no address + virtual ea_t idaapi get_ea(size_t /*n*/) const { return BADADDR; } + + /// return value of ins(), del(), edit(), enter(), refresh() callbacks + /// + /// If the chooser implements get_dirtree(), and has ins() and/or del() + /// capabilities, the meaning of the returned index(es) combined with + /// ALL_CHANGED and SELECTION_CHANGED must be as follows: + /// - for ins(): the index (in case of a chooser_t, or first index + /// in case of a chooser_multi_t), will be the index of the row + /// that was inserted. + /// - for del(): the index (or indexes in case of a chooser_multi_t), + /// will be the index(es) of the row(s) that was(were) deleted. + enum cbres_t + { + NOTHING_CHANGED, + ALL_CHANGED, + SELECTION_CHANGED, + }; + + /// The chooser window is closed. + virtual void idaapi closed() {} + +protected: + // the default names of the standard handlers are different for the qt- + // and txt-versions of the chooser + void init_popup_names(const char *const default_popup_names[NSTDPOPUPS]) + { + for ( int i = 0; i < NSTDPOPUPS; ++i ) + { + if ( popup_names[i].empty() ) + popup_names[i] = default_popup_names[i]; + } + } +#ifdef SWIG + %mutable; +#endif +}; + +#ifndef SWIG + +/// The chooser object without multi-selection. +struct chooser_t : public chooser_base_t +{ + /// Return value of ins(), del(), edit(), enter(), refresh() callbacks + struct cbret_t + { + ssize_t idx; + cbres_t changed; + cbret_t() : idx(NO_SELECTION), changed(NOTHING_CHANGED) {} + cbret_t(ssize_t idx_, cbres_t changed_ = ALL_CHANGED) + : idx(idx_), changed(changed_) {} + }; + + chooser_t(uint32 flags_ = 0, + int columns_ = 0, + const int *widths_ = NULL, + const char *const *header_ = NULL, + const char *title_ = NULL) + : chooser_base_t( + (flags_ & ~CH_MULTI), + columns_, widths_, header_, + title_) {} + + /// Display a generic list chooser and allow the user to select an item. + /// May be overridden in derived choosers. + /// \param deflt default selection or NO_SELECTION + /// see the choose() function below + //lint -sem(chooser_t::choose,custodial(t)) + inline ssize_t choose(ssize_t deflt = 0); + + /// Get the position (index) of the item. + /// A simple chooser considers `item_data` as an index. + /// \param item_data pointer to some data that identifies the item + /// \return idx item index, + /// NO_SELECTION - there is no item with such data + virtual ssize_t idaapi get_item_index(const void *item_data) const newapi + { + // no calculation when `item_data` already is an index + return *(const ssize_t *)item_data; + } + + /// Type of ins(), del(), edit(), enter(), refresh() callbacks + typedef cbret_t (idaapi chooser_t::*cb_t)(size_t n); + + /// User asked to insert an element. + virtual cbret_t idaapi ins(ssize_t /*n*/) newapi { return cbret_t(); } + + /// User deleted an element. + /// \param n index of the element to delete + /// \return idx index of the selected item (cursor) + /// changed what is changed + virtual cbret_t idaapi del(size_t /*n*/) newapi { return cbret_t(); } + + /// User asked to edit an element. + /// \param n index of the element to edit + /// \return idx index of the selected item (cursor) + /// changed what is changed + virtual cbret_t idaapi edit(size_t /*n*/) newapi { return cbret_t(); } //-V524 body is equal to del() + + /// User pressed the enter key. + /// \param n index of the element where <Enter> was pressed + /// \retval false nothing changed + /// \return idx index of the selected item (cursor) + /// changed what is changed + inline virtual cbret_t idaapi enter(size_t n) newapi + { + cbres_t changed = cbres_t(callui(ui_chooser_default_enter, this, &n).i); + return cbret_t(n, changed); + } + + /// The chooser needs to be refreshed. + /// \param n index of the selected (current) item + /// \return idx new index of the current item + /// (as it may change during refresh) + /// changed what is changed + virtual cbret_t idaapi refresh(ssize_t n) newapi + { + return cbret_t(n, ALL_CHANGED); + } + + /// Selection changed (cursor moved). + /// \note This callback is not supported in the txt-version. + /// \param n index of the new selected item + virtual void idaapi select(ssize_t /*n*/) const newapi {} + + /// get the dirtree_t that will be used to present a tree-like + /// structure to the user (see CH_HAS_DIRTREE) + /// \return the dirtree_t, or NULL + virtual dirtree_t *idaapi get_dirtree() newapi { return NULL; } + + /// Map an item index to a dirtree_t inode + /// This is necessary only if CH_HAS_DIRTREE is specified + /// \param n index of the item + /// \return the inode number + virtual inode_t idaapi index_to_inode(size_t /*n*/) const newapi { return inode_t(BADADDR); } + + /// Map an item index to a diffpos_t + /// This is necessary only if CH_HAS_DIFF is specified + /// \param n index of the item + /// \return the diffpos + virtual diffpos_t idaapi index_to_diffpos(size_t /*n*/) const newapi { return diffpos_t(-1); } + +protected: + ssize_t new_sel_after_del(size_t n) const + { + size_t cnt = get_count(); + // assert: n < cnt + return n + 1 < cnt + ? n + 1 + : n - 1; // the last item deleted => no selection + } + ssize_t adjust_last_item(size_t n) const + { + size_t cnt = get_count(); + if ( cnt == 0 ) + return NO_SELECTION; + // take in account deleting of the last item(s) + return n < cnt ? n : cnt - 1; + } +}; + +/// The chooser object with multi-selection. +struct chooser_multi_t : public chooser_base_t +{ + chooser_multi_t( + uint32 flags_ = 0, + int columns_ = 0, + const int *widths_ = NULL, + const char *const *header_ = NULL, + const char *title_ = NULL) + : chooser_base_t( + flags_ | CH_MULTI, + columns_, widths_, header_, + title_) {} + + /// Display a generic list chooser and allow the user to select an item. + /// May be overridden in derived choosers. + /// \param deflt default selection (may be empty) + /// see the choose() function below + //lint -sem(chooser_multi_t::choose,custodial(t)) + inline ssize_t choose(const sizevec_t &deflt = sizevec_t()); + + /// Get the positions of the items. + /// A simple chooser considers `item_data` as a list of indexes. + /// \param[in,out] sel items indexes + /// \param item_data pointer to some data that identifies the items + virtual void idaapi get_item_index( + sizevec_t *sel, + const void *item_data) const newapi + { + // no calculation when `item_data` already is a vector + *sel = *(const sizevec_t *)item_data; + } + + /// Type of ins(), del(), edit(), enter(), refresh() callbacks + typedef cbres_t (idaapi chooser_multi_t::*cb_t)(sizevec_t *sel); + + /// User asked to insert an element. + virtual cbres_t idaapi ins(sizevec_t * /*sel*/) newapi + { + return NOTHING_CHANGED; + } + + /// User deleted elements. + /// \param[in,out] sel selected items + /// \return what is changed + virtual cbres_t idaapi del(sizevec_t * /*sel*/) newapi + { + return NOTHING_CHANGED; + } + + /// User asked to edit an element. + /// \param[in,out] sel selected items + /// \return what is changed + virtual cbres_t idaapi edit(sizevec_t * /*sel*/) newapi + { + return NOTHING_CHANGED; + } + + /// User pressed the enter key. + /// \param[in,out] sel selected items + /// \return what is changed + virtual cbres_t idaapi enter(sizevec_t *sel) newapi + { + return cbres_t(callui(ui_chooser_default_enter, this, sel).i); + } + + /// The chooser needs to be refreshed. + /// It returns the new positions of the selected items. + /// \param[in,out] sel selected items + /// \return what is changed + virtual cbres_t idaapi refresh(sizevec_t * /*sel*/) newapi + { + return ALL_CHANGED; + } + + /// Selection changed + /// \note This callback is not supported in the txt-version. + /// \param sel new selected items + virtual void idaapi select(const sizevec_t &/*sel*/) const newapi {} + + /// get the dirtree_t that will be used to present a tree-like + /// structure to the user (see CH_HAS_DIRTREE) + /// \return the dirtree_t, or NULL + virtual dirtree_t *idaapi get_dirtree() newapi { return NULL; } + + /// Map an item index to a dirtree_t inode + /// This is necessary only if CH_HAS_DIRTREE is specified + /// \param n index of the item + /// \return the inode number + virtual inode_t idaapi index_to_inode(size_t /*n*/) const newapi { return inode_t(BADADDR); } + + /// Map an item index to a diffpos_t + /// This is necessary only if CH_HAS_DIFF is specified + /// \param n index of the item + /// \return the diffpos + virtual diffpos_t idaapi index_to_diffpos(size_t /*n*/) const newapi { return diffpos_t(-1); } + +protected: + // used in the del() callback to iterate + static bool next_item_to_del(sizevec_t *sel); + ssize_t new_sel_after_del(const sizevec_t &sel) const; + void adjust_last_item(sizevec_t *sel, size_t n) const; +}; + + +/// Multi line text control, used to embed a text control in a form +struct textctrl_info_t +{ + size_t cb; ///< size of this structure + qstring text; ///< in, out: text control value + uint16 flags; ///< \ref TXTF_ +/// \defgroup TXTF_ Text control property bits +/// used by textctrl_info_t::flags +//@{ +#define TXTF_AUTOINDENT 0x0001 ///< auto-indent on new line +#define TXTF_ACCEPTTABS 0x0002 ///< Tab key inserts 'tabsize' spaces +#define TXTF_READONLY 0x0004 ///< text cannot be edited (but can be selected and copied) +#define TXTF_SELECTED 0x0008 ///< shows the field with its text selected +#define TXTF_MODIFIED 0x0010 ///< gets/sets the modified status +#define TXTF_FIXEDFONT 0x0020 ///< the control uses IDA's fixed font +#define TXTF_LINENUMBERS 0x0040 ///< the text editor widget should display line numbers +//@} + uint16 tabsize; ///< how many spaces a single tab will indent + textctrl_info_t(): cb(sizeof(textctrl_info_t)), flags(0), tabsize(0) {} ///< Constructor +}; + +/// \defgroup choosers Functions: generic list choosers +/// These functions display a window that allows the user to select items +//@{ + + +/// Display a generic list chooser (n-column) and allow the user to select +/// an item. +/// The closed() callback will be called when the window is closed. +/// In addition, after the window is closed, the chooser instance +/// will be delete()d unless CH_KEEP is specified (useful for global, or +/// stack-allocated chooser instances, that must not be deleted.) +/// \param def_item pointer to some data that identifies the default item +/// For modal choosers: +/// \return the index of the selected item (0-based) +/// \retval chooser_base_t::NO_SELECTION the user refused to choose +/// anything (pressed Esc). +/// \retval chooser_base_t::EMPTY_CHOOSER the chooser was not created +/// because the init() callback has returned 'false' +/// For non-modal choosers: +/// \retval 0 the chooser was created successfully +/// \retval chooser_base_t::ALREADY_EXISTS did not open a new chooser +/// because a chooser with the same object is already open. If +/// CH_FORCE_DEFAULT is set, the cursor of the chooser will be +/// positioned to the new item. + +//lint -sem(choose,custodial(1)) +ssize_t choose(chooser_base_t *ch, const void *def_item); + +inline ssize_t chooser_t::choose(ssize_t deflt) +{ + // chooser uses the default implementation of the get_item_index() + // callback + return ::choose(this, &deflt); +} + +inline ssize_t chooser_multi_t::choose(const sizevec_t &deflt) +{ + // chooser uses the default implementation of the get_item_index() + // callback + return ::choose(this, &deflt); +} + +//@} + +#endif // SWIG + +//------------------------------------------------------------------------- +enum navaddr_type_t +{ + nat_lib = 0, + nat_fun, + nat_cod, + nat_dat, + nat_und, + nat_ext, + nat_err, + nat_gap, + nat_cur, + nat_auto, // auto-analysis cursor color + nat_lum, // related to lumina + nat_hlo, // highlight outline + nat_last +}; + +/// Navigation band colorizer function. +/// +/// If ea==BADADDR, then 'nbytes' is a navaddr_type_t, and the colorizer +/// is in charge of returning the color associated to that type of address. +/// This is used for maintaining the legend in-sync with the colors used to +/// display the addresses in the navigation bar. +/// +/// \param ea address to calculate the color of, or BADADDR (see above) +/// \param nbytes number of bytes, this can be ignored for quick&dirty approach +/// \param ud user data +/// \return color of the specified address in RGB + +typedef uint32 idaapi nav_colorizer_t(ea_t ea, asize_t nbytes, void *ud); + + +/// Install new navigation band colorizer (::ui_set_nav_colorizer). + +inline void set_nav_colorizer( + nav_colorizer_t **out_was_func, + void **out_was_ud, + nav_colorizer_t *func, + void *ud) +{ + callui(ui_set_nav_colorizer, out_was_func, out_was_ud, func, ud); +} + +/// Custom viewer & code viewer handler types +enum custom_viewer_handler_id_t +{ + CVH_USERDATA, + CVH_KEYDOWN, ///< see ::custom_viewer_keydown_t + CVH_POPUP, ///< see ::custom_viewer_popup_t + CVH_DBLCLICK, ///< see ::custom_viewer_dblclick_t + CVH_CURPOS, ///< see ::custom_viewer_curpos_t + CVH_CLOSE, ///< see ::custom_viewer_close_t + CVH_CLICK, ///< see ::custom_viewer_click_t + CVH_QT_AWARE, ///< see set_custom_viewer_qt_aware() + CVH_HELP, ///< see ::custom_viewer_help_t + CVH_MOUSEMOVE, ///< see ::custom_viewer_mouse_moved_t + + CDVH_USERDATA = 1000, ///< see set_code_viewer_user_data() + CDVH_SRCVIEW, ///< see set_code_viewer_is_source() + CDVH_LINES_CLICK, ///< see ::code_viewer_lines_click_t + CDVH_LINES_DBLCLICK, ///< see ::code_viewer_lines_click_t + CDVH_LINES_POPUP, ///< see ::code_viewer_lines_click_t + CDVH_LINES_DRAWICON, ///< see ::code_viewer_lines_icon_t + CDVH_LINES_LINENUM, ///< see ::code_viewer_lines_linenum_t + CDVH_LINES_ICONMARGIN, ///< see set_code_viewer_lines_icon_margin() + CDVH_LINES_RADIX, ///< see set_code_viewer_lines_radix() + CDVH_LINES_ALIGNMENT ///< see set_code_viewer_lines_alignment() +}; + +//------------------------------------------------------------------------- +/// state & 1 => Shift is pressed \n +/// state & 2 => Alt is pressed \n +/// state & 4 => Ctrl is pressed \n +/// state & 8 => Mouse left button is pressed \n +/// state & 16 => Mouse right button is pressed \n +/// state & 32 => Mouse middle button is pressed \n +/// state & 128 => Meta is pressed (OSX only) +#define VES_SHIFT (1 << 0) +#define VES_ALT (1 << 1) +#define VES_CTRL (1 << 2) +#define VES_MOUSE_LEFT (1 << 3) +#define VES_MOUSE_RIGHT (1 << 4) +#define VES_MOUSE_MIDDLE (1 << 5) +#define VES_META (1 << 7) +typedef int view_event_state_t; + +//------------------------------------------------------------------------- +/// Notification codes for events in the message window +enum msg_notification_t +{ + msg_activated, ///< The message window is activated. + ///< \param none + ///< \return void + + msg_deactivated, ///< The message window is deactivated. + ///< \param none + ///< \return void + + msg_click, ///< Click event. + ///< \param x (int) x-coordinate + ///< \param y (int) y-coordinate + ///< \param state (::view_event_state_t) + ///< \retval 1 handled + ///< \retval 0 not handled (invoke default handler) + + msg_dblclick, ///< Double click event. + ///< \param x (int) x-coordinate + ///< \param y (int) y-coordinate + ///< \param state (::view_event_state_t) + ///< \retval 1 handled + ///< \retval 0 not handled (invoke default handler) + + msg_closed, ///< View closed. + ///< \param none + ///< \return void + + msg_keydown, ///< Key down event. + ///< \param key (int) + ///< \param state (::view_event_state_t) + ///< \retval 1 handled + ///< \retval 0 not handled (invoke default handler) +}; + +//------------------------------------------------------------------------- +/// Information about a position relative to the renderer +struct renderer_pos_info_t +{ + /// Constructor + renderer_pos_info_t() : node(-1), cx(-1), cy(-1), sx(-1) {} + + int node; ///< the node, or -1 if the current renderer + ///< is not a graph renderer. + + short cx; ///< the X coords of the character in the current line. + ///< When in graph mode: X coords of the character in 'node'. \n + ///< When in flat mode: X coords of the character in the line, w/o \n + ///< taking scrolling into consideration. + + short cy; ///< the Y coords of the character. + ///< When in graph mode: Y coords of the character in 'node'. \n + ///< When in flat mode: Line number, starting from the top. + + short sx; ///< the number of chars that are scrolled (flat mode only) + + bool operator == (const renderer_pos_info_t &r) const + { return node == r.node && cx == r.cx && cy == r.cy && sx == r.sx; } + bool operator != (const renderer_pos_info_t &r) const + { return !(*this == r); } +}; + +//------------------------------------------------------------------------- +struct selection_item_t; + +//------------------------------------------------------------------------- +/// Abstraction of location in flat view/graph views +/// (out of 'view_mouse_event_t' to make it easy for SWiG to wrap) +union view_mouse_event_location_t +{ + ea_t ea; ///< flat view (rtype == ::TCCRT_FLAT) + const selection_item_t *item; ///< graph views (rtype != ::TCCRT_FLAT). + ///< NULL if mouse is not currently over an item. +}; + + +/// Information about a mouse action within a view +struct view_mouse_event_t +{ + tcc_renderer_type_t rtype; ///< type of renderer that received the event + + uint32 x; ///< screen x coordinate + uint32 y; ///< screen y coordinate + + typedef view_mouse_event_location_t location_t; + location_t location; ///< location where event was generated + + view_event_state_t state; ///< contains information about what buttons are CURRENTLY pressed + ///< on the keyboard and mouse. view_mouse_event_t instances created + ///< in functions like mouseReleaseEvent() won't contain any information + ///< about the mouse, because it has been released. + + vme_button_t button; ///< represents which mouse button was responsible for generating the event. + ///< This field does not care about the current state of the mouse. + + renderer_pos_info_t renderer_pos; ///< position where event was generated, relative to the renderer +}; + +//------------------------------------------------------------------------- +/// Notification codes sent by the UI for IDAView or custom viewer events. +/// These notification codes should be used together with ::HT_VIEW hook type. +enum view_notification_t +{ + view_activated, ///< A view is activated + ///< \param view (TWidget *) + + view_deactivated, ///< A view is deactivated + ///< \param view (TWidget *) + + view_keydown, ///< Key down event + ///< \param view (TWidget *) + ///< \param key (int) + ///< \param state (::view_event_state_t) + + view_click, ///< Click event + ///< \param view (TWidget *) + ///< \param event (const ::view_mouse_event_t *) + + view_dblclick, ///< Double click event + ///< \param view (TWidget *) + ///< \param event (const ::view_mouse_event_t *) + + view_curpos, ///< Cursor position changed + ///< \param view (TWidget *) + + view_created, ///< A view is being created. + ///< \param view (TWidget *) + + view_close, ///< View closed + ///< \param view (TWidget *) + + view_switched, ///< A view's renderer has changed. + ///< \param view (TWidget *) + ///< \param rt (::tcc_renderer_type_t) + + view_mouse_over, ///< The user moved the mouse over (or out of) a node or an edge. + ///< This is only relevant in a graph view. + ///< \param view (TWidget *) + ///< \param event (const ::view_mouse_event_t *) + + view_loc_changed, ///< The location for the view has changed (can be either + ///< the place_t, the renderer_info_t, or both.) + ///< \param view (TWidget *) + ///< \param now (const lochist_entry_t *) + ///< \param was (const lochist_entry_t *) + + view_mouse_moved, ///< The mouse moved on the view + ///< \param view (TWidget *) + ///< \param event (const ::view_mouse_event_t *) +}; + +#ifndef SWIG + +/// The user has pressed a key + +typedef bool idaapi custom_viewer_keydown_t(TWidget *cv, int vk_key, int shift, void *ud); + + +/// The user right clicked. See ::ui_populating_widget_popup, too. + +typedef void idaapi custom_viewer_popup_t(TWidget *cv, void *ud); + + +/// The user moved the mouse. + +typedef void idaapi custom_viewer_mouse_moved_t(TWidget *cv, int shift, view_mouse_event_t *e, void *ud); + + +/// The user clicked + +typedef bool idaapi custom_viewer_click_t(TWidget *cv, int shift, void *ud); + + +/// The user double clicked + +typedef bool idaapi custom_viewer_dblclick_t(TWidget *cv, int shift, void *ud); + + +/// Deprecated. +/// +/// See custom_viewer_location_changed_t for a more +/// competent, and general solution. + +typedef void idaapi custom_viewer_curpos_t(TWidget *cv, void *ud); + + +/// Custom viewer is being destroyed + +typedef void idaapi custom_viewer_close_t(TWidget *cv, void *ud); + + +/// Custom viewer: the user pressed F1 +/// If the return value != -1, it is treated as a help context to display (from ida.hlp) + +typedef int idaapi custom_viewer_help_t(TWidget *cv, void *ud); + + +/// Fine-tune 'loc->place()' according to the X position (i.e., 'loc->renderer_info().pos.cx') +/// +/// You can consider that the place_t object is a 'row cursor' in the +/// list of lines that fill the screen. But, it is only a 'vertical' +/// cursor: e.g., the simpleline_place_t has the 'n' mumber, which +/// specifies what line the place_t corresponds to, in the backing +/// strvec_t instance. +//// +/// However, some views have a place that can be sensitive to the X +/// coordinates of the view's cursor. Think of the "Hex View-1", or +/// the "Pseudocode-A" views: when moving the cursor on the X axis, +/// the 'row cursor' will not change (since we are moving on the same +/// line), but the corresponding 'ea_t' might. +/// +/// For such tricky situations, we provide the following callback, that +/// will provide the ability to update the 'loc->place()'s internal state +/// according to 'loc->renderer_info().pos.cx' so +/// that it really reflects the current cursor position. +/// Most custom viewers will not need to implement this, but if some data +/// in your place_t instances is dependent upon the X coordinate of the +/// cursor, you'll probably want to. +/// +/// Called whenever the user moves the cursor around (mouse, keyboard) +/// +/// Note: this callback should only ever read 'loc->renderer_info()', +/// not modify it. Doing so will result in undefined behavior. + +typedef void idaapi custom_viewer_adjust_place_t(TWidget *v, lochist_entry_t *loc, void *ud); + + +/// Does the line pointed to by pline include pitem, and if so at what X coordinate? +/// +/// place_t instances can be considered as a 'cursor' in a set of lines (see +/// custom_viewer_adjust_place_t), but they can be 'tuned' to +/// correctly represent the current position (e.g., hexrays decompiler plugins +/// tune its place_t instances so they contain the real, current 'ea_t', that +/// corresponds to the C-like expression that's shown at the X coordinate +/// within that line.) +/// +/// But then, when the viewer has to determine whether a certain twinline_t +/// in fact displays the current place, the sublcass's implementation of +/// place_t::compare() might lead it to think that the current twinline_t's +/// place_t is not correct (e.g., because the 'ea_t' has been fine-tuned +/// according to the caret's X coordinates.) +/// +/// Thus, if your plugin implements custom_viewer_adjust_place_t, +/// you probably want to implement this as well, or refreshes might be +/// unnecessarily frequent, leading to a worse user experience. +/// +/// This is typically called when the user moves the cursor around. +/// return +/// -1 if pitem is not included in pline +/// -2 pitem points to the entire line +/// >= 0 for the X coordinate within the pline, where pitem points + +typedef int idaapi custom_viewer_get_place_xcoord_t(TWidget *v, const place_t *pline, const place_t *pitem, void *ud); + + +enum locchange_reason_t +{ + lcr_unknown, + lcr_goto, + lcr_user_switch, // user pressed <Space> + lcr_auto_switch, // automatic switch + lcr_jump, + lcr_navigate, // navigate back & forward + lcr_scroll, // user used scrollbars + lcr_internal, // misc. other reasons +}; + +#define LCMD_SYNC (1 << 0) +class locchange_md_t // location change metadata +{ +protected: + uchar cb; + uchar r; + uchar f; + uchar reserved; + +public: + locchange_md_t(locchange_reason_t _reason, bool _sync) + : cb(sizeof(*this)), r(uchar(_reason)), f(_sync ? LCMD_SYNC : 0), reserved(0) {} + locchange_reason_t reason() const { return locchange_reason_t(r); } + bool is_sync() const { return (f & LCMD_SYNC) != 0; } +}; +CASSERT(sizeof(locchange_md_t) == sizeof(uint32)); +DECLARE_TYPE_AS_MOVABLE(locchange_md_t); + +/// The user asked to navigate to the given location. +/// +/// This gives the view the possibility of declining the move. +/// Reasons for this can be: +/// - the location cannot be displayed, +/// - going there requires a long-running operation, that can be +/// canceled by the user (e.g., in case of the hexrays plugins: +/// during decompilation of the target function.) +/// - ... +/// +/// This is called before the new location is committed to the view's history. +/// +/// return +/// 0 if the move is accepted +/// != 0 otherwise + +typedef int idaapi custom_viewer_can_navigate_t( + TWidget *v, + const lochist_entry_t *now, + const locchange_md_t &md, + void *ud); + + +/// The viewer's location (i.e., place, or cursor) changed. + +typedef void idaapi custom_viewer_location_changed_t( + TWidget *v, + const lochist_entry_t *was, + const lochist_entry_t *now, + const locchange_md_t &md, + void *ud); + + +// Code viewer handlers for the lineinfo widget located to the left of the text. + +/// The user clicked, right clicked or double clicked. +/// pos: the clicked icon number. -1 means the click occurred on space not reserved to icons. + +typedef void idaapi code_viewer_lines_click_t(TWidget *c, const place_t *p, int pos, int shift, void *ud); + + +/// Icon drawing. +/// \param pos the icon number, will be 0,1,2,3... \n +/// can be modified to skip positions and draw at the specified one +/// \return the id of the icon to draw. If bitwise or'ed with 0x80000000, +/// IDA calls this function once more with pos+1 to retrieve one more icon. + +typedef int idaapi code_viewer_lines_icon_t(TWidget *cv, const place_t *p, int *pos, void *ud); + + +/// Calculate the line number. Return false to not print any number. + +typedef bool idaapi code_viewer_lines_linenum_t(TWidget *cv, const place_t *p, uval_t *num, void *ud); + +#endif // SWIG + +//------------------------------------------------------------------------ + +/// Command line interpreter. +/// Provides functionality for the command line (located at the bottom of the main window). +/// Only GUI version of IDA supports CLIs. +struct cli_t +{ + size_t size; ///< size of this structure + int32 flags; ///< \ref CLIF_ +/// \defgroup CLIF_ CLI attributes +/// used by cli_t::flags +//@{ +#define CLIF_QT_AWARE 1 ///< keydown event will use Qt key codes +//@} + const char *sname; ///< short name (displayed on the button) + const char *lname; ///< long name (displayed in the menu) + const char *hint; ///< hint for the input line + + /// Callback: the user pressed Enter. + /// CLI is free to execute the line immediately or ask for more lines. + /// \param line command to execute (utf-8-encoded) + /// \retval true executed line + /// \retval false ask for more lines + bool (idaapi *execute_line)(const char *line); + + void *unused; + + /// Callback: a keyboard key has been pressed. + /// This callback is optional. + /// It is a generic callback and the CLI is free to do whatever it wants. + /// \param line current input line (in/out argument) + /// \param p_x pointer to current x coordinate of the cursor (in/out) + /// \param p_sellen pointer to current selection length (usually 0) + /// \param p_vk_key pointer to virtual key code (in/out). + /// if the key has been handled, it should be reset to 0 by CLI + /// \param shift shift state + /// \retval true modified input line or x coordinate or selection length + /// \retval false otherwise + bool (idaapi *keydown)( + qstring *line, + int *p_x, + int *p_sellen, + int *p_vk_key, + int shift); + + /// Callback: the user pressed Tab/Shift+Tab. + /// This callback is optional. + /// \param[out] out_completions results of completion + /// \param[out] out_match_start the codepoint index in the line, where match starts + /// \param[out] out_match_end the codepoint index in the line, where ends ends + /// \param line command line + /// \param x codepoint index of the cursor in line + /// \retval true got results + /// \retval false otherwise + bool (idaapi *find_completions)( + qstrvec_t *out_completions, + int *out_match_start, + int *out_match_end, + const char *line, + int x); +}; + +//--------------------------------------------------------------------------- +/// \defgroup MFF_ Exec request flags +/// passed as 'reqf' parameter to execute_sync() +//@{ +#define MFF_FAST 0x0000 ///< Execute code as soon as possible. + ///< this mode is ok for calling ui related functions + ///< that do not query the database. + +#define MFF_READ 0x0001 ///< Execute code only when ida is idle and it is safe + ///< to query the database. + ///< this mode is recommended only + ///< for code that does not modify the database. + ///< (nb: ida may be in the middle of executing + ///< another user request, for example it may be waiting + ///< for him to enter values into a modal dialog box) + +#define MFF_WRITE 0x0002 ///< Execute code only when ida is idle and it is safe + ///< to modify the database. in particular, + ///< this flag will suspend execution if there is + ///< a modal dialog box on the screen + ///< this mode can be used to call any ida api function + ///< #MFF_WRITE implies #MFF_READ + +#define MFF_NOWAIT 0x0004 ///< Do not wait for the request to be executed. + ///< the caller should ensure that the request is not + ///< destroyed until the execution completes. + ///< if not, the request will be ignored. + ///< the request must be created using the 'new' operator + ///< to use it with this flag. + ///< it can be used in cancel_exec_request(). + ///< This flag can be used to delay the code execution + ///< until the next UI loop run even from the main thread. +//@} + + +/// Execute code in the main thread - to be used with execute_sync(). +struct exec_request_t +{ + /// Internal magic + enum { MFF_MAGIC = 0x12345678 }; + + /// Can this request be executed? + bool valid(void) const + { + return (code & ~7) == MFF_MAGIC && (sem != NULL || (code & MFF_NOWAIT) != 0); + } + + int code; ///< temporary location, used internally + + qsemaphore_t sem; ///< semaphore to communicate with the main thread. + ///< If NULL, will be initialized by execute_sync(). + + /// Callback to be executed. + /// If this function raises an exception, execute_sync() never returns. + virtual int idaapi execute(void) = 0; + + /// Constructor + exec_request_t(void) : code(0), sem(NULL) {} + + /// Destructor + // FIXME: windows: gcc compiled plugins cannot use exec_request_t because the destructor + // is generated differently! + virtual ~exec_request_t(void) { qsem_free(sem); sem = NULL; code = 0; } +}; + +//--------------------------------------------------------------------------- +/// Base class for defining UI requests. +/// Override the run() method and insert your code. +class ui_request_t +{ +public: + /// Run the UI request + /// \retval false remove the request from the queue + /// \retval true reschedule the request and run it again + virtual bool idaapi run() = 0; + virtual ~ui_request_t() {} +}; + +/// List of UI requests. The ui_request_t is allocated by the caller +/// but its ownership is transferred to the execute_ui_requests(). +/// The ui_request_t instance will be deleted as soon as it is executed and +/// was not rescheduled for another run. +class ui_requests_t : public qlist<ui_request_t *> +{ + DECLARE_UNCOPYABLE(ui_requests_t) +public: + ui_requests_t() {} ///< Constructor + ~ui_requests_t() ///< Destructor + { + for ( iterator p=begin(); p != end(); ++p ) + delete *p; + } +}; + +/// Snapshot restoration completion callback. see restore_database_snapshot() +typedef void idaapi ss_restore_cb_t(const char *errmsg, void *ud); + +/// \defgroup UIJMP_ Jump flags +/// passed as 'uijmp_flags' parameter to jumpto() +//@{ +#define UIJMP_ACTIVATE 0x0001 ///< activate the new window +#define UIJMP_DONTPUSH 0x0002 ///< do not remember the current address + ///< in the navigation history +#define UIJMP_VIEWMASK 0x000C +#define UIJMP_ANYVIEW 0x0000 ///< jump in any ea_t-capable view +#define UIJMP_IDAVIEW 0x0004 ///< jump in idaview +#define UIJMP_IDAVIEW_NEW 0x0008 ///< jump in new idaview +//@} + +struct screen_graph_selection_t; +struct dirtree_selection_t; +typedef uval_t const_t; + +//------------------------------------------------------------------------- +// Current selection +struct action_ctx_base_cur_sel_t +{ + twinpos_t from; ///< start of selection + twinpos_t to; ///< end of selection + + action_ctx_base_cur_sel_t() { reset(); } + void reset() + { + from.at = NULL; + from.x = -1; + to.at = NULL; + to.x = -1; + } +}; + +//------------------------------------------------------------------------- +union action_ctx_base_source_t +{ + chooser_base_t *chooser; + + action_ctx_base_source_t() { reset(); } + void reset() + { + chooser = NULL; + } +}; + +//------------------------------------------------------------------------- +/// Maintain information about the current state of the UI. +/// This allows actions to behave appropriately (see ::action_handler_t) +struct action_ctx_base_t +{ + /// Constructor + action_ctx_base_t() + { + reset(); + } + +/// \defgroup ACF_ Action context property bits +/// used by action_ctx_base_t::cur_flags +//@{ +#define ACF_HAS_SELECTION (1 << 0) ///< there is currently a valid selection +#define ACF_XTRN_EA (1 << 1) ///< cur_ea is in 'externs' segment +#define ACF_HAS_FIELD_DIRTREE_SELECTION (1 << 2) ///< 'cur_enum_member' and 'dirtree_selection' fields are present +#define ACF_HAS_SOURCE (1 << 3) ///< 'source' field is present +//@} + + /// Invalidate all context info + void reset() + { + widget = NULL; + widget_type = BWN_UNKNOWN; + widget_title.clear(); + chooser_selection.clear(); + action = NULL; + + // + cur_flags = ACF_HAS_FIELD_DIRTREE_SELECTION | ACF_HAS_SOURCE; + cur_ea = BADADDR; + cur_value = BADADDR; + cur_func = cur_fchunk = NULL; + cur_struc = NULL; cur_strmem = NULL; + cur_enum = enum_t(-1); + cur_seg = NULL; + cur_sel.reset(); + regname = NULL; + focus = NULL; + graph_selection = NULL; + cur_enum_member = const_t(-1); + dirtree_selection = NULL; + source.reset(); + } + TWidget *widget; + twidget_type_t widget_type; ///< type of current widget + qstring widget_title; ///< title of current widget + sizevec_t chooser_selection; ///< current chooser selection (0-based) + const char *action; ///< action name + + uint32 cur_flags; ///< Current address information. see \ref ACF_ + + /// Check if the given flag is set + inline bool has_flag(uint32 flag) const { return (cur_flags & flag) == flag; } + + ea_t cur_ea; ///< the current EA of the position in the view + uval_t cur_value; ///< the possible address, or value the cursor is positioned on + + func_t *cur_func; ///< the current function + func_t *cur_fchunk; ///< the current function chunk + + struc_t *cur_struc; ///< the current structure + member_t *cur_strmem; ///< the current structure member + + enum_t cur_enum; ///< the current enum + + segment_t *cur_seg; ///< the current segment + + action_ctx_base_cur_sel_t cur_sel; ///< the currently selected range. also see #ACF_HAS_SELECTION + + const char *regname; ///< register name (if widget_type == BWN_CPUREGS and context menu opened on register) + + TWidget *focus; ///< The focused widget in case it is not the 'form' itself (e.g., the 'quick filter' input in choosers.) + + screen_graph_selection_t *graph_selection; ///< the current graph selection (if in a graph view) + const_t cur_enum_member; + + dirtree_selection_t *dirtree_selection; ///< the current dirtree_t selection (if applicable) + + action_ctx_base_source_t source; ///< the underlying chooser_base_t (if 'widget' is a chooser widget) +}; + +//------------------------------------------------------------------------- +/// Instances of this class will be filled with information that is +/// commonly used by actions when they need to +/// be activated. This is so they don't have to perform (possibly) +/// costly operations more than once. +typedef action_ctx_base_t action_activation_ctx_t; + +//------------------------------------------------------------------------- +/// Instances of this class will be filled with information that is +/// commonly used by actions when they need to +/// update. This is so they don't have to perform (possibly) +/// costly operations more than once. +typedef action_ctx_base_t action_update_ctx_t; + +#define AHF_VERSION 1 ///< action handler version (used by action_handler_t::flags) +#define AHF_VERSION_MASK 0xFF ///< mask for action_handler_t::flags + +//------------------------------------------------------------------------- +/// Action states - returned by action_handler_t::update() +enum action_state_t +{ + AST_ENABLE_ALWAYS, ///< enable action and do not call action_handler_t::update() anymore + + AST_ENABLE_FOR_IDB, ///< enable action for the current idb. + ///< call action_handler_t::update() when a database is opened/closed + + AST_ENABLE_FOR_WIDGET, ///< enable action for the current widget. + ///< call action_handler_t::update() when a widget gets/loses focus + + AST_ENABLE, ///< enable action - call action_handler_t::update() when anything changes + + AST_DISABLE_ALWAYS, ///< disable action and do not call action_handler_t::action() anymore + AST_DISABLE_FOR_IDB, ///< analog of ::AST_ENABLE_FOR_IDB + AST_DISABLE_FOR_WIDGET, ///< analog of ::AST_ENABLE_FOR_WIDGET + AST_DISABLE, ///< analog of ::AST_ENABLE +}; + + +/// Check if the given action state is one of AST_ENABLE* + +inline bool is_action_enabled(action_state_t s) +{ + return s <= AST_ENABLE; +} + +//------------------------------------------------------------------------- +/// Manages the behavior of a registered action +struct action_handler_t +{ + int flags; ///< internal - for version management + + /// Constructor + action_handler_t(int _f = 0) : flags(_f) { flags |= AHF_VERSION; } + + /// Activate an action. + /// This function implements the core behavior of an action. + /// It is called when the action is triggered, from a menu, from + /// a popup menu, from the toolbar, or programmatically. + /// \returns non-zero: all IDA windows will be refreshed + virtual int idaapi activate(action_activation_ctx_t *ctx) = 0; + + /// Update an action. + /// This is called when the context of the UI changed, and we need to let the + /// action update some of its properties if needed (label, icon, ...) + /// + /// In addition, this lets IDA know whether the action is enabled, + /// and when it should be queried for availability again. + /// + /// Note: This callback is not meant to change anything in the + /// application's state, except by calling one (or many) of + /// the "update_action_*()" functions on this very action. + virtual action_state_t idaapi update(action_update_ctx_t *ctx) = 0; + + /// Destructor + virtual ~action_handler_t() {} +}; + +/// Describe an action to be registered (see register_action()) +struct action_desc_t +{ + int cb; ///< size of this structure + const char *name; ///< the internal name of the action; must be unique. + ///< a way to reduce possible conflicts is to prefix it + ///< with some specific prefix. E.g., "myplugin:doSthg". + + const char *label; ///< the label of the action, possibly with an accelerator + ///< key definition (e.g., "~J~ump to operand") + + action_handler_t *handler; ///< the action handler, for activating/updating. + ///< please read the comments at register_action(). + + const void *owner; ///< either the plugin_t, or plugmod_t responsible for + ///< registering the action. Can be NULL + ///< Please see \ref ACTION_DESC_LITERAL_PLUGMOD + + const char *shortcut; ///< an optional shortcut definition. E.g., "Ctrl+Enter" + const char *tooltip; ///< an optional tooltip for the action + int icon; ///< an optional icon ID to use + +/// \defgroup ADF_ Action flags +/// used by register_action(). The upper 16 bits are reserved. +//@{ +#define ADF_OWN_HANDLER 0x01 ///< handler is owned by the action; it'll be + ///< destroyed when the action is unregistered. + ///< You shouldn't have to use this. +#define ADF_NO_UNDO 0x02 ///< the action does not create an undo point. + ///< useful for actions that do not modify the database. +#define ADF_OT_MASK 0x0C ///< Owner type mask +#define ADF_OT_PLUGIN 0x00 ///< Owner is a plugin_t +#define ADF_OT_PLUGMOD 0x04 ///< Owner is a plugmod_t +#define ADF_OT_PROCMOD 0x08 ///< Owner is a procmod_t +#define ADF_GLOBAL 0x10 ///< Register the action globally, so that it's + ///< available even if no IDB is present +#define ADF_NO_HIGHLIGHT 0x20 ///< After activating, do not update the highlight + ///< according to what's under the cursor (listings only.) +//@} + int flags; ///< See \ref ADF_ +}; + +/// Get an ::action_desc_t instance with the provided plugmod_t as the owner +/// This is meant for plugins +#define ACTION_DESC_LITERAL_PLUGMOD(name, label, handler, plgmod, shortcut, tooltip, icon) \ + { sizeof(action_desc_t), name, label, handler, plgmod, shortcut, tooltip, icon, ADF_OT_PLUGMOD } + +/// Get an ::action_desc_t instance with the provided procmod_t as the owner +/// This is meant for processor modules implementing processor_t::ev_get_procmod +#define ACTION_DESC_LITERAL_PROCMOD(name, label, handler, prcmod, shortcut, tooltip, icon) \ + { sizeof(action_desc_t), name, label, handler, prcmod, shortcut, tooltip, icon, ADF_OT_PROCMOD } + +/// Get an ::action_desc_t instance with a given owner and flags +#define ACTION_DESC_LITERAL_OWNER(name, label, handler, owner, shortcut, tooltip, icon, flags) \ + { sizeof(action_desc_t), name, label, handler, owner, shortcut, tooltip, icon, flags } + +/// For attach_dynamic_action_to_popup() only +#define DYNACTION_DESC_LITERAL(label, handler, shortcut, tooltip, icon) \ + { sizeof(action_desc_t), NULL, label, handler, NULL, shortcut, tooltip, icon, ADF_OWN_HANDLER } + +/// Codes for getting/setting action attributes +enum action_attr_t +{ + AA_NONE, ///< no effect + AA_LABEL, ///< see update_action_label() + AA_SHORTCUT, ///< see update_action_shortcut() + AA_TOOLTIP, ///< see update_action_tooltip() + AA_ICON, ///< see update_action_icon() + AA_STATE, ///< see update_action_state() + AA_CHECKABLE, ///< see update_action_checkable() + AA_CHECKED, ///< see update_action_checked() + AA_VISIBILITY, ///< see update_action_visibility() +}; + +#ifndef SWIG +// Handlers to be used with create_custom_viewer() +class custom_viewer_handlers_t +{ + int cb; +public: + custom_viewer_handlers_t( + custom_viewer_keydown_t *_keyboard = NULL, + custom_viewer_popup_t *_popup = NULL, + custom_viewer_mouse_moved_t *_mouse_moved = NULL, + custom_viewer_click_t *_click = NULL, + custom_viewer_dblclick_t *_dblclick = NULL, + custom_viewer_curpos_t *_curpos = NULL, + custom_viewer_close_t *_close = NULL, + custom_viewer_help_t *_help = NULL, + custom_viewer_adjust_place_t *_adjust_place = NULL, + custom_viewer_get_place_xcoord_t *_get_place_xcoord = NULL, + custom_viewer_location_changed_t *_location_changed = NULL, + custom_viewer_can_navigate_t *_can_navigate = NULL) + : cb(sizeof(*this)), + keyboard(_keyboard), + popup(_popup), + mouse_moved(_mouse_moved), + click(_click), + dblclick(_dblclick), + curpos(_curpos), + close(_close), + help(_help), + adjust_place(_adjust_place), + get_place_xcoord(_get_place_xcoord), + location_changed(_location_changed), + can_navigate(_can_navigate) + {} + custom_viewer_keydown_t *keyboard; + custom_viewer_popup_t *popup; + custom_viewer_mouse_moved_t *mouse_moved; + custom_viewer_click_t *click; + custom_viewer_dblclick_t *dblclick; + custom_viewer_curpos_t *curpos; + custom_viewer_close_t *close; + custom_viewer_help_t *help; + custom_viewer_adjust_place_t *adjust_place; + custom_viewer_get_place_xcoord_t *get_place_xcoord; + custom_viewer_location_changed_t *location_changed; + custom_viewer_can_navigate_t *can_navigate; +}; +#endif // SWIG + + +#ifndef __UI__ // Not for the UI + +// Convenience functions offered by the user interface + +/// Execute a list of UI requests (::ui_execute_ui_requests_list). +/// \returns a request id: a unique number that can be used to cancel the request + +THREAD_SAFE inline int execute_ui_requests(ui_requests_t *reqs) +{ + return callui(ui_execute_ui_requests_list, reqs).i; +} + + +/// Execute a variable number of UI requests (::ui_execute_ui_requests). +/// The UI requests will be dispatched in the context of the main thread. +/// \param req pointer to the first request ,use NULL to terminate the var arg request list +/// \return a request id: a unique number that can be used to cancel the request + +THREAD_SAFE inline int execute_ui_requests(ui_request_t *req, ...) +{ + va_list va; + va_start(va, req); + int req_id = callui(ui_execute_ui_requests, req, va).i; + va_end(va); + return req_id; +} + + +/// Try to cancel an asynchronous exec request (::ui_cancel_exec_request). +/// \param req_id request id +/// \retval true successfully canceled +/// \retval false request has already been processed. + +THREAD_SAFE inline bool cancel_exec_request(int req_id) +{ + return callui(ui_cancel_exec_request, req_id).cnd; +} + + +/// Try to cancel asynchronous exec requests created by the specified thread. +/// \param tid thread id +/// \return number of the canceled requests. + +THREAD_SAFE inline int cancel_thread_exec_requests(qthread_t tid) +{ + return callui(ui_cancel_thread_exec_requests, tid).i; +} + +/// Get the group of widgets/registers +/// this view is synchronized with +/// \param w the widget +/// \return the group of widgets/registers, or NULL + +inline const synced_group_t *get_synced_group(const TWidget *w) +{ + return (synced_group_t *) callui(ui_get_synced_group, w).vptr; +} + +/// Jump to the specified address (::ui_jumpto). +/// \param ea destination +/// \param opnum -1: don't change x coord +/// \param uijmp_flags \ref UIJMP_ +/// \return success + +inline bool jumpto(ea_t ea, int opnum=-1, int uijmp_flags=UIJMP_ACTIVATE) +{ + return callui(ui_jumpto, ea, opnum, uijmp_flags).cnd; +} + + +/// Show a banner dialog box (::ui_banner). +/// \param wait time to wait before closing +/// \retval 1 ok +/// \retval 0 esc was pressed + +inline bool banner(int wait) { return callui(ui_banner, wait).cnd; } + + +/// Can we use msg() functions? + +THREAD_SAFE inline bool is_msg_inited(void) { return callui(ui_is_msg_inited).cnd; } + + +/// Refresh marked windows (::ui_refreshmarked) + +inline void refresh_idaview(void) { callui(ui_refreshmarked); } + + +/// Refresh all disassembly views (::ui_refresh), forces an immediate refresh. +/// Please consider request_refresh() instead + +inline void refresh_idaview_anyway(void) { callui(ui_refresh); } + + +/// Allow the user to set analyzer options. (show a dialog box) (::ui_analyzer_options) + +inline void analyzer_options(void) { callui(ui_analyzer_options); } + + +/// Get the address at the screen cursor (::ui_screenea) + +inline ea_t get_screen_ea(void) { ea_t ea; callui(ui_screenea, &ea); return ea; } + + +/// Get current operand number, -1 means no operand (::ui_get_opnum) + +inline int get_opnum(void) { return callui(ui_get_opnum).i; } + + +/// Get the cursor position on the screen (::ui_get_cursor). +/// \note coordinates are 0-based +/// \param[out] x x-coordinate +/// \param[out] y y-coordinate +/// \retval true pointers are filled +/// \retval false no disassembly window open + +inline bool get_cursor(int *x, int *y) { return callui(ui_get_cursor, x, y).cnd; } + + +/// Get coordinates of the output window's cursor (::ui_get_output_cursor). +/// \note coordinates are 0-based +/// \note this function will succeed even if the output window is not visible +/// \param[out] x column +/// \param[out] y line number (global, from the start of output) +/// \retval false the output window has been destroyed. +/// \retval true pointers are filled + +inline bool get_output_cursor(int *x, int *y) { return callui(ui_get_output_cursor, x, y).cnd; } + + +/// Get current line from the disassemble window (::ui_get_curline). +/// \return cptr current line with the color codes +/// (use tag_remove() to remove the color codes) + +inline const char *get_curline(void) { return callui(ui_get_curline).cptr; } + + +/// Open the given url (::ui_open_url) + +inline void open_url(const char *url) { callui(ui_open_url, url); } + + +/// Get the current address in a hex view. +/// \param hexdump_num number of hexview window + +inline ea_t get_hexdump_ea(int hexdump_num) { ea_t ea; callui(ui_hexdumpea, &ea, hexdump_num); return ea; } + + +/// Get keyboard key code by its name (::ui_get_key_code) + +inline ushort get_key_code(const char *keyname) { return callui(ui_get_key_code, keyname).i16; } + + +/// Get shortcut code previously created by ::ui_get_key_code. +/// \param key key constant +/// \param shift modifiers +/// \param is_qt are we using gui version? + +inline ushort lookup_key_code(int key, int shift, bool is_qt) { return callui(ui_lookup_key_code, key, shift, is_qt).i16; } + + +/// Refresh navigation band if changed (::ui_refresh_navband). +/// \param force refresh regardless + +inline void refresh_navband(bool force) { callui(ui_refresh_navband, force); } + + +/// Mark a non-modal custom chooser for a refresh (::ui_refresh_chooser). +/// \param title title of chooser +/// \return success + +inline bool refresh_chooser(const char *title) { return callui(ui_refresh_chooser, title).cnd; } + + +/// Close a non-modal chooser (::ui_close_chooser). +/// \param title window title of chooser to close +/// \return success + +inline bool close_chooser(const char *title) { return callui(ui_close_chooser, title).cnd; } + + +/// Install command line interpreter (::ui_install_cli) + +inline void install_command_interpreter(const cli_t *cp) { callui(ui_install_cli, cp, true); } + + +/// Remove command line interpreter (::ui_install_cli) + +inline void remove_command_interpreter(const cli_t *cp) { callui(ui_install_cli, cp, false); } + + +/// Generate disassembly text for a range. +/// \param[out] text result +/// \param ea1 start address +/// \param ea2 end address +/// \param truncate_lines (on idainfo::margin) + +inline void gen_disasm_text(text_t &text, ea_t ea1, ea_t ea2, bool truncate_lines) { callui(ui_gen_disasm_text, &text, ea1, ea2, truncate_lines); } + + +/// Execute code in the main thread. +/// \param req request specifying the code to execute +/// \param reqf \ref MFF_ +/// \return if \ref #MFF_NOWAIT is specified, return the request id. +/// otherwise return the value returned by exec_request_t::execute(). + +THREAD_SAFE inline int execute_sync(exec_request_t &req, int reqf) { return callui(ui_execute_sync, &req, reqf).i; } + + +/// Set the docking position of a widget (::ui_set_dock_pos). +/// \param src_ctrl title of widget to dock +/// \param dest_ctrl where to dock: if NULL or invalid then create +/// a new tab relative to current active tab +/// \param orient \ref DP_ +/// \param left,top,right,bottom dimensions of dock, if not specified or invalid then +/// create the widget in the center of the screen with the +/// default size +/// \return success + +inline bool set_dock_pos(const char *src_ctrl, const char *dest_ctrl, int orient, int left = 0, int top = 0, int right = 0, int bottom = 0) +{ + return callui(ui_set_dock_pos, src_ctrl, dest_ctrl, orient, left, top, right, bottom).cnd; +} + + +/// Load an icon from a file (::ui_load_custom_icon_file). +/// Also see load_custom_icon(const void *, unsigned int, const char *) +/// \param file_name path to file +/// \return icon id + +inline int load_custom_icon(const char *file_name) { return callui(ui_load_custom_icon_file, file_name).i; } + + +/// Load an icon and return its id (::ui_load_custom_icon). +/// \param ptr pointer to raw image data +/// \param len image data length +/// \param format image format +/// \return icon id + +inline int load_custom_icon(const void *ptr, unsigned int len, const char *format) { return callui(ui_load_custom_icon, ptr, len, format).i; } + + +/// Free an icon loaded with load_custom_icon() (::ui_free_custom_icon). + +inline void free_custom_icon(int icon_id) { callui(ui_free_custom_icon, icon_id); } + + +/// Processes a UI action by name. +/// \param name action name +/// \param flags reserved/not used +/// \param param reserved/not used + +inline bool process_ui_action(const char *name, int flags=0, void *param=NULL) +{ + return callui(ui_process_action, name, flags, param).cnd; +} + + +/// Take a database snapshot (::ui_take_database_snapshot). +/// \param ss in/out parameter. +/// - in: description, flags +/// - out: filename, id +/// \param err_msg optional error msg buffer +/// \return success + +inline bool take_database_snapshot( + snapshot_t *ss, + qstring *err_msg) +{ + return callui(ui_take_database_snapshot, ss, err_msg).cnd; +} + + +/// Restore a database snapshot. +/// Note: This call is asynchronous. When it is completed, the callback will be triggered. +/// \param ss snapshot instance (see build_snapshot_tree()) +/// \param cb A callback that will be triggered with a NULL string. +/// on success and an actual error message on failure. +/// \param ud user data passed to be passed to the callback +/// \return false if restoration could not be started (snapshot file was not found). \n +/// If the returned value is True then check if the operation succeeded from the callback. + +inline bool restore_database_snapshot( + const snapshot_t *ss, + ss_restore_cb_t *cb, + void *ud) +{ + return callui(ui_restore_database_snapshot, ss, cb, ud).cnd; +} + +/// Timer opaque handle +typedef struct __qtimer_t {} *qtimer_t; + + +/// Register a timer (::ui_register_timer). +/// Timer functions are thread-safe and the callback is executed +/// in the context of the main thread. +/// \param interval_ms interval in milliseconds +/// \param callback the callback can return -1 to unregister the timer; +/// any other value >= 0 defines the new interval for the timer +/// \param ud callback params +/// \return handle to registered timer (use this handle to unregister it), or NULL + +THREAD_SAFE inline qtimer_t register_timer( + int interval_ms, + int (idaapi *callback)(void *ud), + void *ud) +{ + return (qtimer_t)(callui(ui_register_timer, interval_ms, callback, ud).vptr); +} + + +/// Unregister a timer (::ui_unregister_timer). +/// \param t handle to a registered timer +/// \return success + +THREAD_SAFE inline bool unregister_timer(qtimer_t t) +{ + return callui(ui_unregister_timer, t).cnd; +} + +//------------------------------------------------------------------------- + +/// Create a new action (::ui_register_action). +/// After an action has been created, it is possible to attach it +/// to menu items (attach_action_to_menu()), or to popup menus +/// (attach_action_to_popup()). +/// +/// Because the actions will need to call the handler's activate() and +/// update() methods at any time, you shouldn't build your action handler +/// on the stack. +/// +/// Please see the SDK's "ht_view" plugin for an example how +/// to register actions. +/// \param desc action to register +/// \return success + +inline bool register_action(const action_desc_t &desc) +{ + return callui(ui_register_action, &desc).cnd; +} + + +/// Delete a previously-registered action (::ui_unregister_action). +/// \param name name of action +/// \return success + +inline bool unregister_action(const char *name) +{ + return callui(ui_unregister_action, name).cnd; +} + + +/// Get a list of all currently-registered actions +/// \param out the list of actions to be filled +inline void get_registered_actions(qstrvec_t *out) +{ + callui(ui_get_registered_actions, out); +} + + +/// Create a toolbar with the given name, label and optional position +/// \param name name of toolbar (must be unique) +/// \param label label of toolbar +/// \param before if non-NULL, the toolbar before which the new toolbar will be inserted +/// \param flags a combination of \ref CREATETB_, to determine toolbar position +/// \return success +inline bool create_toolbar( + const char *name, + const char *label, + const char *before = NULL, + int flags = 0) +{ + return callui(ui_create_toolbar, name, label, before, flags).cnd; +} + + +/// Delete an existing toolbar +/// \param name name of toolbar +/// \return success +inline bool delete_toolbar(const char *name) +{ + return callui(ui_delete_toolbar, name).cnd; +} + + +/// Create a menu with the given name, label and optional position, +/// either in the menubar, or as a submenu. +/// If 'menupath' is non-NULL, it provides information about where +/// the menu should be positioned. +/// First, IDA will try and resolve the corresponding menu by its name. +/// If such an existing menu is found and is present in the menubar, +/// then the new menu will be inserted in the menubar before it. +/// Otherwise, IDA will try to resolve 'menupath' as it would for +/// attach_action_to_menu() and, if found, add the new menu like so: +/// \code +/// // The new 'My menu' submenu will appear in the 'Comments' submenu +/// // before the 'Enter comment..." command +/// create_menu("(...)", "My menu", "Edit/Comments/Enter comment..."); +/// \endcode +/// or +/// \code +/// // The new 'My menu' submenu will appear at the end of the +/// // 'Comments' submenu. +/// create_menu("(...)", "My menu", "Edit/Comments/"); +/// \endcode +/// If the above fails, the new menu will be appended to the menubar. +/// \param name name of menu (must be unique) +/// \param label label of menu +/// \param menupath where should the menu be inserted +/// \return success +inline bool create_menu( + const char *name, + const char *label, + const char *menupath=NULL) +{ + return callui(ui_create_menu, name, label, menupath).cnd; +} + + +/// Delete an existing menu +/// \param name name of menu +/// \return success +inline bool delete_menu(const char *name) +{ + return callui(ui_delete_menu, name).cnd; +} + + +/// Attach a previously-registered action to the menu (::ui_attach_action_to_menu). +/// \note You should not change top level menu, or the Edit,Plugins submenus +/// If you want to modify the debugger menu, do it at the ui_debugger_menu_change +/// event (ida might destroy your menu item if you do it elsewhere). +/// \param menupath path to the menu item after or before which the insertion will take place. \n +/// - Example: Debug/StartProcess +/// - Whitespace, punctuation are ignored. +/// - It is allowed to specify only the prefix of the menu item. +/// - Comparison is case insensitive. +/// - menupath may start with the following prefixes: +/// - [S] - modify the main menu of the structure window +/// - [E] - modify the main menu of the enum window +/// \param name the action name +/// \param flags a combination of \ref SETMENU_, to determine menu item position +/// \return success + +inline bool attach_action_to_menu( + const char *menupath, + const char *name, + int flags) +{ + return callui(ui_attach_action_to_menu, menupath, name, flags).cnd; +} + + +/// Detach an action from the menu (::ui_detach_action_from_menu). +/// \param menupath path to the menu item +/// \param name the action name +/// \return success + +inline bool detach_action_from_menu( + const char *menupath, + const char *name) +{ + return callui(ui_detach_action_from_menu, menupath, name).cnd; +} + + +/// Attach an action to an existing toolbar (::ui_attach_action_to_toolbar). +/// \param toolbar_name the name of the toolbar +/// \param name the action name +/// \return success + +inline bool attach_action_to_toolbar( + const char *toolbar_name, + const char *name) +{ + return callui(ui_attach_action_to_toolbar, toolbar_name, name).cnd; +} + + +/// Detach an action from the toolbar (::ui_detach_action_from_toolbar). +/// \param toolbar_name the name of the toolbar +/// \param name the action name +/// \return success + +inline bool detach_action_from_toolbar( + const char *toolbar_name, + const char *name) +{ + return callui(ui_detach_action_from_toolbar, toolbar_name, name).cnd; +} + + +/// Helper. +/// +/// You are not encouraged to use this, as it mixes flags for +/// both register_action(), and attach_action_to_menu(). +/// +/// The only reason for its existence is to make it simpler +/// to port existing plugins to the new actions API. + +inline bool register_and_attach_to_menu( + const char *menupath, + const char *name, + const char *label, + const char *shortcut, + int flags, + action_handler_t *handler, + void *owner, + int action_desc_t_flags) +{ + action_desc_t desc = ACTION_DESC_LITERAL_OWNER(name, label, handler, owner, shortcut, NULL, -1, action_desc_t_flags); + if ( !register_action(desc) ) + return false; + if ( !attach_action_to_menu(menupath, name, (flags & SETMENU_POSMASK)) ) + { + unregister_action(name); + return false; + } + return true; +} + +//------------------------------------------------------------------------ +// Get VCL global variables +class TPopupMenu; + +/// Display a widget, dock it if not done before +/// \param widget widget to display +/// \param options \ref WIDGET_OPEN +/// \param dest_ctrl where to dock: if NULL or invalid then +/// use the active docker if there is not +/// create a new tab relative to current active tab + +inline void display_widget(TWidget *widget, uint32 options, const char *dest_ctrl=NULL) +{ + callui(ui_display_widget, widget, options, dest_ctrl); +} + + +/// Close widget (::ui_close_widget, only gui version). +/// \param widget pointer to the widget to close +/// \param options \ref WIDGET_CLOSE + +inline void close_widget(TWidget *widget, int options) +{ + callui(ui_close_widget, widget, options); +} + + +/// Activate widget (only gui version) (::ui_activate_widget). +/// \param widget existing widget to display +/// \param take_focus give focus to given widget + +inline void activate_widget(TWidget *widget, bool take_focus) +{ + callui(ui_activate_widget, widget, take_focus); +} + + +/// Find widget with the specified caption (only gui version) (::ui_find_widget). +/// NB: this callback works only with the tabbed widgets! +/// \param caption title of tab, or window title if widget is not tabbed +/// \return pointer to the TWidget, NULL if none is found + +inline TWidget *find_widget(const char *caption) +{ + return (TWidget *) callui(ui_find_widget, caption).vptr; +} + + +/// Get a pointer to the current widget (::ui_get_current_widget). + +inline TWidget *get_current_widget(void) +{ + return (TWidget *) callui(ui_get_current_widget).vptr; +} + + +/// Get the type of the TWidget * (::ui_get_widget_type). + +inline twidget_type_t get_widget_type(TWidget *widget) +{ + return twidget_type_t(callui(ui_get_widget_type, widget).i); +} + + +/// Get the TWidget's title (::ui_get_widget_title). + +inline bool get_widget_title(qstring *buf, TWidget *widget) +{ + return callui(ui_get_widget_title, buf, widget).cnd; +} + +/// Create new ida viewer based on ::place_t (::ui_create_custom_viewer). +/// \param title name of viewer +/// \param minplace first location of the viewer +/// \param maxplace last location of the viewer +/// \param curplace set current location +/// \param rinfo renderer information (can be NULL) +/// \param ud contents of viewer +/// \param handlers handlers for the viewer (can be NULL) +/// \param parent widget to hold viewer +/// \return pointer to resulting viewer + +inline TWidget *create_custom_viewer( + const char *title, + const place_t *minplace, + const place_t *maxplace, + const place_t *curplace, + const renderer_info_t *rinfo, + void *ud, + const custom_viewer_handlers_t *cvhandlers, + void *cvhandlers_ud, + TWidget *parent = NULL) +{ + return (TWidget*) callui( + ui_create_custom_viewer, title, minplace, + maxplace, curplace, rinfo, ud, cvhandlers, cvhandlers_ud, parent).vptr; +} + + +/// Append 'loc' to the viewer's history, and cause the viewer +/// to display it. +///< \param v (TWidget *) +///< \param loc (const lochist_entry_t &) +///< \param flags (uint32) or'ed combination of CVNF_* values +///< \return success + +inline bool custom_viewer_jump( + TWidget *v, + const lochist_entry_t &loc, + uint32 flags=0) +{ + return callui(ui_custom_viewer_jump, v, &loc, flags).cnd; +} + + +/// Push current location in the history and jump to the given location (::ui_ea_viewer_history_push_and_jump). +/// This will jump in the given ea viewer and also in other synchronized views. +/// \param v ea viewer +/// \param ea jump destination +/// \param x,y coords on screen +/// \param lnnum desired line number of given address + +inline bool ea_viewer_history_push_and_jump(TWidget *v, ea_t ea, int x, int y, int lnnum) +{ + return callui(ui_ea_viewer_history_push_and_jump, v, ea, x, y, lnnum).cnd; +} + + +/// Get information about what's in the history (::ui_ea_viewer_history_info). +/// \param[out] nback number of available back steps +/// \param[out] nfwd number of available forward steps +/// \param v ea viewer +/// \retval false if the given ea viewer does not exist +/// \retval true otherwise + +inline bool get_ea_viewer_history_info(int *nback, int *nfwd, TWidget *v) +{ + return callui(ui_ea_viewer_history_info, nback, nfwd, v).cnd; +} + + +/// Refresh custom ida viewer (::ui_refresh_custom_viewer) + +inline void refresh_custom_viewer(TWidget *custom_viewer) +{ + callui(ui_refresh_custom_viewer, custom_viewer); +} + + +/// Repaint the given widget immediately (::ui_repaint_qwidget) + +inline void repaint_custom_viewer(TWidget *custom_viewer) +{ + callui(ui_repaint_qwidget, custom_viewer); +} + + +/// Destroy custom ida viewer + +inline void destroy_custom_viewer(TWidget *custom_viewer) +{ + callui(ui_destroy_custom_viewer, custom_viewer); +} + + +/// Set cursor position in custom ida viewer. +/// \param custom_viewer view +/// \param place target position +/// \param x desired cursor position (column) +/// \param y desired cursor position (line) +/// \return success + +inline bool jumpto(TWidget *custom_viewer, place_t *place, int x, int y) +{ + return callui(ui_jump_in_custom_viewer, custom_viewer, place, x, y).cnd; +} + + +/// Get current place in a custom viewer (::ui_get_curplace). +/// +/// See also the more complete get_custom_viewer_location() +/// +/// \param custom_viewer view +/// \param mouse mouse position (otherwise cursor position) +/// \param[out] x x coordinate +/// \param[out] y y coordinate + +inline place_t *get_custom_viewer_place( + TWidget *custom_viewer, + bool mouse, + int *x, + int *y) +{ + return (place_t *)callui(ui_get_curplace, custom_viewer, mouse, x, y).vptr; +} + + +/// Get the current location in a custom viewer (::ui_get_custom_viewer_location). +inline bool get_custom_viewer_location( + lochist_entry_t *out, + TWidget *custom_viewer, + bool mouse=false) +{ + return callui(ui_get_custom_viewer_location, out, custom_viewer, mouse).cnd; +} + +/// Are we running inside IDA Qt? + +inline bool is_idaq() +{ + return callui(ui_is_idaq).cnd; +} + + +/// Insert a previously-registered action into the widget's popup menu (::ui_attach_action_to_popup). +/// This function has two "modes": 'single-shot', and 'permanent'. +/// \param widget target widget +/// \param popup_handle target popup menu +/// - if non-NULL, the action is added to this popup +/// menu invocation (i.e., 'single-shot') +/// - if NULL, the action is added to a list of actions +/// that should always be present in context menus for this widget +/// (i.e., 'permanent'.) +/// \param name action name +/// \param popuppath can be NULL +/// \param flags a combination of SETMENU_ flags (see \ref SETMENU_) +/// \return success + +inline bool attach_action_to_popup( + TWidget *widget, + TPopupMenu *popup_handle, + const char *name, + const char *popuppath = NULL, + int flags = 0) +{ + return callui(ui_attach_action_to_popup, widget, popup_handle, name, popuppath, flags).cnd; +} + + +/// Remove a previously-registered action, from the list of 'permanent' +/// context menu actions for this widget (::ui_detach_action_from_popup). +/// This only makes sense if the action has been added to 'widget's list +/// of permanent popup actions by calling attach_action_to_popup +/// in 'permanent' mode. +/// \param widget target widget +/// \param name action name + +inline bool detach_action_from_popup(TWidget *widget, const char *name) +{ + return callui(ui_detach_action_from_popup, widget, name).cnd; +} + + +/// Create & insert an action into the widget's popup menu (::ui_attach_dynamic_action_to_popup). +/// \note action_desc_t::handler for 'desc' must be instantiated using 'new', as it +/// will be 'delete'd when the action is unregistered. +/// \param widget target widget +/// \param popup_handle target popup +/// \param desc created with #DYNACTION_DESC_LITERAL +/// \param popuppath can be NULL +/// \param flags a combination of SETMENU_ constants (see \ref SETMENU_) +/// \param buf a buffer, to retrieve the generated action name - can be NULL +/// \return success + +inline bool attach_dynamic_action_to_popup( + TWidget *widget, + TPopupMenu *popup_handle, + const action_desc_t &desc, + const char *popuppath = NULL, + int flags = 0, + qstring *buf = NULL) +{ + return callui(ui_attach_dynamic_action_to_popup, widget, + popup_handle, &desc, popuppath, flags, buf).cnd; +} + +/// \defgroup ui_uaa_funcs Functions: update actions +/// Convenience functions for ::ui_update_action_attr +//@{ + +/// Update an action's label (::ui_update_action_attr). +/// \param name action name +/// \param label new label +/// \return success + +inline bool update_action_label(const char *name, const char *label) +{ + return callui(ui_update_action_attr, name, AA_LABEL, label).cnd; +} + + +/// Update an action's shortcut (::ui_update_action_attr). +/// \param name action name +/// \param shortcut new shortcut +/// \return success + +inline bool update_action_shortcut(const char *name, const char *shortcut) +{ + return callui(ui_update_action_attr, name, AA_SHORTCUT, shortcut).cnd; +} + + +/// Update an action's tooltip (::ui_update_action_attr). +/// \param name action name +/// \param tooltip new tooltip +/// \return success + +inline bool update_action_tooltip(const char *name, const char *tooltip) +{ + return callui(ui_update_action_attr, name, AA_TOOLTIP, tooltip).cnd; +} + + +/// Update an action's icon (::ui_update_action_attr). +/// \param name action name +/// \param icon new icon id +/// \return success + +inline bool update_action_icon(const char *name, int icon) +{ + return callui(ui_update_action_attr, name, AA_ICON, &icon).cnd; +} + + +/// Update an action's state (::ui_update_action_attr). +/// \param name action name +/// \param state new state +/// \return success + +inline bool update_action_state(const char *name, action_state_t state) +{ + return callui(ui_update_action_attr, name, AA_STATE, &state).cnd; +} + + +/// Update an action's checkability (::ui_update_action_attr). +/// \param name action name +/// \param checkable new checkability +/// \return success + +inline bool update_action_checkable(const char *name, bool checkable) +{ + return callui(ui_update_action_attr, name, AA_CHECKABLE, &checkable).cnd; +} + + +/// Update an action's checked state (::ui_update_action_attr). +/// \param name action name +/// \param checked new checked state +/// \return success + +inline bool update_action_checked(const char *name, bool checked) +{ + return callui(ui_update_action_attr, name, AA_CHECKED, &checked).cnd; +} + + +/// Update an action's visibility (::ui_update_action_attr). +/// \param name action name +/// \param visible new visibility +/// \return success + +inline bool update_action_visibility(const char *name, bool visible) +{ + return callui(ui_update_action_attr, name, AA_VISIBILITY, &visible).cnd; +} + +//@} + +/// \defgroup ui_gaa_funcs Functions: get action attributes +/// Convenience functions for ::ui_get_action_attr +//{ + +/// Get an action's label (::ui_get_action_attr). +/// \param[out] label the action label +/// \param name the action name +/// \return success + +inline bool get_action_label(qstring *label, const char *name) +{ + return callui(ui_get_action_attr, name, AA_LABEL, label).cnd; +} + + +/// Get an action's shortcut (::ui_get_action_attr). +/// \param[out] shortcut the action shortcut +/// \param name the action name +/// \return success + +inline bool get_action_shortcut(qstring *shortcut, const char *name) +{ + return callui(ui_get_action_attr, name, AA_SHORTCUT, shortcut).cnd; +} + + +/// Get an action's tooltip (::ui_get_action_attr). +/// \param[out] tooltip the action tooltip +/// \param name the action name +/// \return success + +inline bool get_action_tooltip(qstring *tooltip, const char *name) +{ + return callui(ui_get_action_attr, name, AA_TOOLTIP, tooltip).cnd; +} + + +/// Get an action's icon (::ui_get_action_attr). +/// \param name the action name +/// \param[out] icon the icon id +/// \return success + +inline bool get_action_icon(const char *name, int *icon) +{ + return callui(ui_get_action_attr, name, AA_ICON, icon).cnd; +} + + +/// Get an action's state (::ui_get_action_attr). +/// \param name the action name +/// \param[out] state the action's state +/// \return success + +inline bool get_action_state(const char *name, action_state_t *state) +{ + return callui(ui_get_action_attr, name, AA_STATE, state).cnd; +} + + +/// Get an action's checkability (::ui_get_action_attr). +/// \param name the action name +/// \param[out] checkable the action's checkability +/// \return success + +inline bool get_action_checkable(const char *name, bool *checkable) +{ + return callui(ui_get_action_attr, name, AA_CHECKABLE, checkable).cnd; +} + + +/// Get an action's checked state (::ui_get_action_attr). +/// \param name the action name +/// \param[out] checked the action's checked state +/// \return success + +inline bool get_action_checked(const char *name, bool *checked) +{ + return callui(ui_get_action_attr, name, AA_CHECKED, checked).cnd; +} + + +/// Get an action's visibility (::ui_get_action_attr). +/// \param name the action name +/// \param[out] visibility the action's visibility +/// \return success + +inline bool get_action_visibility(const char *name, bool *visibility) +{ + return callui(ui_get_action_attr, name, AA_VISIBILITY, visibility).cnd; +} + +//@} + +/// \defgroup ui_scvh_funcs Functions: custom viewer handlers +/// Convenience functions for ::ui_set_custom_viewer_handler +//@{ + +/// Set handlers for custom viewer events +/// Any of these handlers may be NULL + +inline void set_custom_viewer_handlers( + TWidget *custom_viewer, + const custom_viewer_handlers_t *cvh, + void *cvh_ud) +{ + callui(ui_set_custom_viewer_handlers, custom_viewer, cvh, cvh_ud); +} + + +/// Set a handler for a custom viewer event (::ui_set_custom_viewer_handler). +/// see also ::ui_set_custom_viewer_handlers +/// \param custom_viewer the custom viewer +/// \param handler_id one of CVH_ in ::custom_viewer_handler_id_t +/// \param handler_or_data can be a handler or data. see examples in \ref ui_scvh_funcs +/// \return old value of the handler or data + +inline void *set_custom_viewer_handler( + TWidget *custom_viewer, + custom_viewer_handler_id_t handler_id, + void *handler_or_data) +{ + return callui(ui_set_custom_viewer_handler, custom_viewer, handler_id, + handler_or_data).vptr; +} + + +/// Allow the given viewer to interpret Qt events (::ui_set_custom_viewer_handler) + +inline bool set_custom_viewer_qt_aware(TWidget *custom_viewer) +{ + return callui(ui_set_custom_viewer_handler, custom_viewer, CVH_QT_AWARE).cnd; +} + +//@} + + +/// Get current line of custom viewer (::ui_get_custom_viewer_curline). +/// The returned line contains color codes +/// \param custom_viewer view +/// \param mouse mouse position (otherwise cursor position) +/// \return pointer to contents of current line + +inline const char *get_custom_viewer_curline(TWidget *custom_viewer, bool mouse) +{ + return callui(ui_get_custom_viewer_curline, custom_viewer, mouse).cptr; +} + + +/// Get current line of output window (::ui_get_output_curline). +/// \param buf output buffer +/// \param mouse current for mouse pointer? +/// \return false if output contains no text + +inline bool get_output_curline(qstring *buf, bool mouse) +{ + return callui(ui_get_output_curline, buf, mouse).cnd; +} + + +/// Returns selected text from output window (::ui_get_output_selected_text). +/// \param buf output buffer +/// \return true if there is a selection + +inline bool get_output_selected_text(qstring *buf) +{ + return callui(ui_get_output_selected_text, buf).cnd; +} + + +/// Get current ida viewer (idaview or custom viewer) (::ui_get_current_viewer) + +inline TWidget *get_current_viewer(void) +{ + return (TWidget *)callui(ui_get_current_viewer).vptr; +} + + +/// Get the type of renderer currently in use in the given view (::ui_get_renderer_type) + +inline tcc_renderer_type_t get_view_renderer_type(TWidget *v) +{ + return tcc_renderer_type_t(callui(ui_get_renderer_type, v).i); +} + + +/// Set the type of renderer to use in a view (::ui_set_renderer_type) + +inline void set_view_renderer_type(TWidget *v, tcc_renderer_type_t rt) +{ + callui(ui_set_renderer_type, v, rt); +} + + +/// Set position range for custom viewer (::ui_set_custom_viewer_range) + +inline void set_custom_viewer_range( + TWidget *custom_viewer, + const place_t *minplace, + const place_t *maxplace) +{ + callui(ui_set_custom_viewer_range, custom_viewer, minplace, maxplace); +} + + +/// Create an empty widget, serving as a container for custom +/// user widgets + +inline TWidget *create_empty_widget(const char *title, int icon = -1) +{ + return (TWidget *) callui(ui_create_empty_widget, title, icon).vptr; +} + + +/// Clear the "Output" window + +inline void msg_clear() +{ + callui(ui_msg_clear); +} + + +/// Save the "Output" window contents into a file +/// \param path The path of the file to save the contents into. +/// An empty path means that the user will be prompted for +/// the destination and, if the file already exists, the user +/// will be asked to confirm before overriding its contents. +/// Upon return, 'path' will contain the path that the user +/// chose. +/// \return success + +inline bool msg_save(qstring &path) +{ + return callui(ui_msg_save, &path).cnd; +} + + +/// Retrieve the last 'count' lines from the output window, in reverse +/// order (from most recent, to least recent) +/// \param out Output storage +/// \param count The number of lines to retrieve. -1 means: all + +inline void msg_get_lines(qstrvec_t *out, int count=-1) +{ + callui(ui_msg_get_lines, out, count); +} + + +/// Get the current, active modal TWidget instance. +/// Note that in this context, the "wait dialog" is not considered: +/// this function will return NULL even if it is currently shown. +/// \return TWidget * the active modal widget, or NULL + +inline TWidget *get_active_modal_widget(void) +{ + return (TWidget *) callui(ui_get_active_modal_widget).vptr; +} + + +/// Translate the provided ea_t, into its pixel position (plus pixel ranges) +/// on the navigation band. + +inline int get_navband_pixel(bool *out_is_vertical, ea_t ea) +{ + return callui(ui_navband_pixel, out_is_vertical, ea).i; +} + + +/// Translate the pixel position on the navigation band, into an address + +inline ea_t get_navband_ea(int pixel) +{ + ea_t ea = BADADDR; + callui(ui_navband_ea, &ea, pixel); + return ea; +} + + +/// Get the system-specific window ID (GUI version only) +/// \param the name of the window (NULL means the main IDA window) +/// \return the low-level window ID + +inline void *get_window_id(const char *name=NULL) +{ + return callui(ui_get_window_id, name).vptr; +} + + +/// Is the given custom view an idaview? (::ui_is_idaview) + +inline bool is_idaview(TWidget *v) +{ + return callui(ui_is_idaview, v).cnd; +} + + +/// Get the selected range boundaries (::ui_read_selection). +/// \param v view +/// \param[out] p1 start of selection +/// \param[out] p2 end of selection +/// \retval false no range is selected +/// \retval true ok, start and end are filled + +inline bool read_selection(TWidget *v, twinpos_t *p1, twinpos_t *p2) +{ + return callui(ui_read_selection, v, p1, p2).cnd; +} + + +/// Get the address range for the selected range boundaries, +/// this is the convenient function for read_selection() +/// \param v view, NULL means the last active window +/// containing addresses +/// \param[out] ea1 start ea +/// \param[out] ea2 end ea +/// \retval 0 no range is selected \n +/// \retval 1 ok, start ea and end ea are filled + +inline bool read_range_selection(TWidget *v, ea_t *ea1, ea_t *ea2) +{ + return callui(ui_read_range_selection, v, ea1, ea2).cnd; +} + + +/// Unmark selection (::ui_unmarksel) + +inline void unmark_selection(void) { callui(ui_unmarksel); } + + +/// Create a code viewer (::ui_create_code_viewer). +/// A code viewer contains on the left side a widget representing the +/// line numbers, and on the right side, the child widget passed as +/// parameter. +/// It will inherit its title from the child widget. +/// +/// \param custview the custom view to be added +/// \param flags \ref CDVF_ +/// \param parent widget to contain the new code viewer + +inline TWidget *create_code_viewer( + TWidget *custview, + int flags = 0, + TWidget *parent = NULL) +{ + return (TWidget*)callui(ui_create_code_viewer, custview, flags, parent).vptr; +} + + +/// Set a handler for a code viewer event (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs +/// \param code_viewer the code viewer +/// \param handler_id one of CDVH_ in ::custom_viewer_handler_id_t +/// \param handler_or_data can be a handler or data. see examples in \ref ui_scvh_funcs +/// \return old value of the handler or data + +inline void *set_code_viewer_handler( + TWidget *code_viewer, + custom_viewer_handler_id_t handler_id, + void *handler_or_data) +{ + return callui(ui_set_custom_viewer_handler, code_viewer, handler_id, + handler_or_data).vptr; +} + + +/// Set the user data on a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs + +inline bool set_code_viewer_user_data(TWidget *code_viewer, void *ud) +{ + return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_USERDATA, ud).cnd; +} + + +/// Get the user data from a custom viewer (::ui_get_viewer_user_data) + +inline void *get_viewer_user_data(TWidget *viewer) +{ + return callui(ui_get_viewer_user_data, viewer).vptr; +} + + +/// Get the type of ::place_t instances a viewer uses & creates (::ui_get_viewer_place_type). + +inline tcc_place_type_t get_viewer_place_type(TWidget *viewer) +{ + return tcc_place_type_t(callui(ui_get_viewer_place_type, viewer).i); +} + + +/// Set handlers for code viewer line events. +/// Any of these handlers may be NULL + +inline void set_code_viewer_line_handlers( + TWidget *code_viewer, + code_viewer_lines_click_t *click_handler, + code_viewer_lines_click_t *popup_handler, + code_viewer_lines_click_t *dblclick_handler, + code_viewer_lines_icon_t *drawicon_handler, + code_viewer_lines_linenum_t *linenum_handler) +{ + callui(ui_set_code_viewer_line_handlers, code_viewer, click_handler, + popup_handler, dblclick_handler, drawicon_handler, linenum_handler); +} + + +/// Set space allowed for icons in the margin of a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs + +inline bool set_code_viewer_lines_icon_margin(TWidget *code_viewer, int margin) +{ + return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_LINES_ICONMARGIN, margin).cnd; +} + + +/// Set alignment for lines in a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs + +inline bool set_code_viewer_lines_alignment(TWidget *code_viewer, int align) +{ + return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_LINES_ALIGNMENT, align).cnd; +} + + +/// Set radix for values displayed in a code viewer (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs + +inline bool set_code_viewer_lines_radix(TWidget *code_viewer, int radix) +{ + return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_LINES_RADIX, radix).cnd; +} + + +/// Specify that the given code viewer is used to display source code (::ui_set_custom_viewer_handler). \ingroup ui_scvh_funcs + +inline bool set_code_viewer_is_source(TWidget *code_viewer) +{ + return callui(ui_set_custom_viewer_handler, code_viewer, CDVH_SRCVIEW).cnd; +} + + +/// Get the size of a tab in spaces (::ui_get_tab_size). +/// \param path the path of the source view for which the tab size is requested. +/// - if NULL, the default size is returned. + +inline int get_tab_size(const char *path) +{ + return callui(ui_get_tab_size, path).i; +} + + +/// Clear "Cancelled" flag (::ui_clr_cancelled) + +THREAD_SAFE inline void clr_cancelled(void) { callui(ui_clr_cancelled); } + + +/// Set "Cancelled" flag (::ui_set_cancelled) + +THREAD_SAFE inline void set_cancelled(void) { callui(ui_set_cancelled); } + + +/// Test the ctrl-break flag (::ui_test_cancelled). +/// \retval 1 Ctrl-Break is detected, a message is displayed +/// \retval 2 Ctrl-Break is detected again, a message is not displayed +/// \retval 0 Ctrl-Break is not detected + +THREAD_SAFE inline bool user_cancelled(void) { return callui(ui_test_cancelled).cnd; } + + +/// Display a load file dialog and load file (::ui_load_file). +/// \param[out] temp_file name of the file with the extracted archive member. +/// \param[in,out] filename the name of input file as is, +/// library or archive name +/// \param[in,out] pli loader input source, +/// may be changed to point to temp_file +/// \param neflags combination of NEF_... bits (see \ref NEF_) +/// \param[in,out] ploaders list of loaders which accept file, +/// may be changed for loaders of temp_file +/// \retval true file was successfully loaded +/// \retval false otherwise + +inline bool ui_load_new_file( + qstring *temp_file, + qstring *filename, + linput_t **pli, + ushort neflags, + load_info_t **ploaders) +{ + return callui(ui_load_file, temp_file, filename, pli, neflags, ploaders).cnd; +} + + +/// Load a debugger plugin and run the specified program (::ui_run_dbg). +/// \param dbgopts value of the -r command line switch +/// \param exename name of the file to run +/// \param argc number of arguments for the executable +/// \param argv argument vector +/// \return success + +inline bool ui_run_debugger( + const char *dbgopts, + const char *exename, + int argc, + const char *const *argv) +{ + return callui(ui_run_dbg, dbgopts, exename, argc, argv).cnd; +} + + +/// Load debugging information from a file. +/// \param path path to file +/// \param li loader input. if NULL, check DBG_NAME_KEY +/// \param base loading address +/// \param verbose dump status to message window + +inline bool load_dbg_dbginfo( + const char *path, + linput_t *li=NULL, + ea_t base=BADADDR, + bool verbose=false) +{ + return callui(ui_dbg_load_dbg_dbginfo, path, li, base, verbose).cnd; +} + + +/// Add hotkey for IDC function (::ui_add_idckey). +/// \param hotkey hotkey name +/// \param idcfunc IDC function name +/// \return \ref IDCHK_ + +inline int add_idc_hotkey(const char *hotkey, const char *idcfunc) +{ + return callui(ui_add_idckey, hotkey, idcfunc).i; +} + + +/// Get the highlighted identifier in the viewer (::ui_get_highlight). +/// \param out_str buffer to copy identifier to +/// \param viewer the viewer +/// \param out_flags storage for the flags +/// \return false if no identifier is highlighted + +inline bool get_highlight(qstring *out_str, TWidget *viewer, uint32 *out_flags) +{ + return callui(ui_get_highlight, out_str, viewer, out_flags).cnd; +} + + +/// Set the highlighted identifier in the viewer (::ui_set_highlight). +/// \param viewer the viewer +/// \param str the text to match, or NULL to remove current +/// \param flags combination of HIF_... bits (see \ref HIF_) +/// \return false if an error occurred + +inline bool set_highlight(TWidget *viewer, const char *str, int flags) +{ + return callui(ui_set_highlight, viewer, str, flags).cnd; +} + + +#ifndef SWIG +/// Pointer to range marker function (for idaviews and hexviews) +/// This pointer is initialized by setup_range_marker() + +extern void (idaapi*range_marker)(ea_t ea, asize_t size); + + +/// Initialize pointer to idaview marker + +inline void setup_range_marker(void) +{ + void *ptr = callui(ui_get_range_marker).vptr; + if ( ptr != NULL ) + range_marker = reinterpret_cast<void (idaapi*)(ea_t, asize_t)>(ptr); +} + +/// Inform the UI about any modifications of [ea, ea+size) + +inline void mark_range_for_refresh(ea_t ea, asize_t size) +{ + if ( range_marker != NULL ) + range_marker(ea, size); +} + + +/// Tell UI to refresh all idaviews and hexviews + +inline void mark_all_eaviews_for_refresh(void) +{ + if ( range_marker != NULL ) + range_marker(0, BADADDR); +} + +/// Ignores range_marker during the lifetime of the object. +/// Refreshes all idaviews and hexviews at the end. +struct range_marker_suspender_t +{ + void (idaapi *backup)(ea_t ea, asize_t size); + range_marker_suspender_t(void) + { + backup = range_marker; + range_marker = NULL; + } + ~range_marker_suspender_t(void) + { + range_marker = backup; + mark_all_eaviews_for_refresh(); + } +}; +#endif // SWIG + + +/// \defgroup ui_open_builtin_funcs Functions: open built-in windows +/// Convenience functions for ::ui_open_builtin +//@{ + +/// Open the exports window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_exports_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_EXPORTS, ea).vptr; +} + + +/// Open the exports window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_imports_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_IMPORTS, ea).vptr; +} + + +/// Open the names window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_names_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_NAMES, ea).vptr; +} + + +/// Open the 'Functions' window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_funcs_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_FUNCS, ea).vptr; +} + + +/// Open the 'Strings' window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \param selstart,selend only display strings that occur within this range +/// \return pointer to resulting window + +inline TWidget *open_strings_window(ea_t ea, ea_t selstart=BADADDR, ea_t selend=BADADDR) +{ + return (TWidget *) callui(ui_open_builtin, BWN_STRINGS, ea, selstart, selend).vptr; +} + + +/// Open the segments window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_segments_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_SEGS, ea).vptr; +} + + +/// Open the segment registers window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_segregs_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_SEGREGS, ea).vptr; +} + + +/// Open the selectors window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_selectors_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_SELS, 0).vptr; +} + + +/// Open the signatures window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_signatures_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_SIGNS, 0).vptr; +} + + +/// Open the type libraries window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_tils_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_TILS, 0).vptr; +} + + +/// Open the local types window (::ui_open_builtin). +/// \param ordinal ordinal of type to select by default +/// \return pointer to resulting window + +inline TWidget *open_loctypes_window(int ordinal) +{ + return (TWidget *) callui(ui_open_builtin, BWN_LOCTYPS, ordinal).vptr; +} + + +/// Open the function calls window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_calls_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_CALLS, ea).vptr; +} + +/// Open the problems window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_problems_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_PROBS, ea).vptr; +} + + +/// Open the breakpoints window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_bpts_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_BPTS, ea).vptr; +} + + +/// Open the threads window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_threads_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_THREADS, 0).vptr; +} + + +/// Open the modules window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_modules_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_MODULES, 0).vptr; +} + + +/// Open the tracing window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_trace_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_TRACE, 0).vptr; +} + + +/// Open the call stack window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_stack_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_STACK, 0).vptr; +} + + +/// Open the cross references window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_xrefs_window(ea_t ea) +{ + return (TWidget *) callui(ui_open_builtin, BWN_XREFS, ea).vptr; +} + + +/// Open the frame window for the given function (::ui_open_builtin). +/// \param pfn function to analyze +/// \param offset offset where the cursor is placed +/// \return pointer to resulting window if 'pfn' is a valid function and the window was displayed, \n +/// NULL otherwise + +inline TWidget *open_frame_window(func_t *pfn, uval_t offset) +{ + return (TWidget *) callui(ui_open_builtin, BWN_FRAME, pfn, offset).vptr; +} + + +/// Open the navigation band window (::ui_open_builtin). +/// \param ea sets the address of the navband arrow +/// \param zoom sets the navband zoom level +/// \return pointer to resulting window + +inline TWidget *open_navband_window(ea_t ea, int zoom) +{ + return (TWidget *) callui(ui_open_builtin, BWN_NAVBAND, ea, zoom).vptr; +} + + +/// Open the enums window (::ui_open_builtin). +/// \param const_id index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_enums_window(tid_t const_id=BADADDR) +{ + return (TWidget *) callui(ui_open_builtin, BWN_ENUMS, const_id).vptr; +} + + +/// Open the structs window (::ui_open_builtin). +/// \param id index of entry to select by default +/// \param offset offset where the cursor is placed +/// \return pointer to resulting window + +inline TWidget *open_structs_window(tid_t id=BADADDR, uval_t offset=0) +{ + return (TWidget *) callui(ui_open_builtin, BWN_STRUCTS, id, offset).vptr; +} + + +/// Open a disassembly view (::ui_open_builtin). +/// \param window_title title of view to open +/// \param ranges if != NULL, then display a flow chart with the specified ranges +/// \return pointer to resulting window + +inline TWidget *open_disasm_window(const char *window_title, const rangevec_t *ranges=NULL) +{ + return (TWidget *) callui(ui_open_builtin, BWN_DISASMS, window_title, BADADDR, ranges, 0).vptr; +} + + +/// Open a hexdump view (::ui_open_builtin). +/// \param window_title title of view to open +/// \return pointer to resulting window + +inline TWidget *open_hexdump_window(const char *window_title) +{ + return (TWidget *) callui(ui_open_builtin, BWN_DUMPS, window_title, BADADDR, 0).vptr; +} + + +/// Open the notepad window (::ui_open_builtin). +/// \return pointer to resulting window + +inline TWidget *open_notepad_window(void) +{ + return (TWidget *) callui(ui_open_builtin, BWN_NOTEPAD, 0).vptr; +} + + +/// Open the bookmarks window (::ui_open_builtin). +/// \param ea index of entry to select by default +/// \return pointer to resulting window + +inline TWidget *open_bookmarks_window(TWidget *w) +{ + return (TWidget *) callui(ui_open_builtin, BWN_BOOKMARKS, w, 0).vptr; +} + + +//@} + +/// [Un]synchronize sources +/// \param what +/// \param with +/// \param sync +/// \return success +inline bool sync_sources( + const sync_source_t &what, + const sync_source_t &with, + bool sync) +{ + return callui(ui_sync_sources, &what, &with, sync).cnd; +} + + +/// \defgroup ui_choose_funcs Functions: built-in choosers +/// Convenience functions for ::ui_choose and ::choose_type_t +//@{ + + +/// Choose a signature (::ui_choose, ::chtype_idasgn). +/// \return name of selected signature, NULL if none selected + +inline char *choose_idasgn(void) +{ + return callui(ui_choose, chtype_idasgn).cptr; +} + + +/// Choose a type library (::ui_choose, ::chtype_idatil). +/// \param buf output buffer to store the library name +/// \retval true 'buf' was filled with the name of the selected til +/// \retval false otherwise + +inline bool choose_til(qstring *buf) +{ + return callui(ui_choose, chtype_idatil, buf).cnd; +} + + +/// Choose an entry point (::ui_choose, ::chtype_entry). +/// \param title chooser title +/// \return ea of selected entry point, #BADADDR if none selected + +inline ea_t choose_entry(const char *title) +{ + ea_t ea; + callui(ui_choose, chtype_entry, &ea, title); + return ea; +} + + +/// Choose a name (::ui_choose, ::chtype_name). +/// \param title chooser title +/// \return ea of selected name, #BADADDR if none selected + +inline ea_t choose_name(const char *title) +{ + ea_t ea; + callui(ui_choose, chtype_name, &ea, title); + return ea; +} + + +/// Choose an xref to a stack variable (::ui_choose, ::chtype_name). +/// \param pfn function +/// \param mptr variable +/// \return ea of the selected xref, BADADDR if none selected + +inline ea_t choose_stkvar_xref(func_t *pfn, member_t *mptr) +{ + ea_t ea; + callui(ui_choose, chtype_stkvar_xref, &ea, pfn, mptr); + return ea; +} + + +/// Choose an xref to an address (::ui_choose, ::chtype_xref). +/// \param to referenced address +/// \return ea of selected xref, BADADDR if none selected + +inline ea_t choose_xref(ea_t to) +{ + ea_t ea; + callui(ui_choose, chtype_xref, &ea, to); + return ea; +} + + +/// Choose an enum (::ui_choose, ::chtype_enum). +/// \param title chooser title +/// \param default_id id of enum to select by default +/// \return enum id of selected enum, #BADNODE if none selected + +inline enum_t choose_enum(const char *title, enum_t default_id) +{ + enum_t enum_id = default_id; + callui(ui_choose, chtype_enum, &enum_id, title); + return enum_id; +} + + +/// Choose an enum, restricted by value & size (::ui_choose, ::chtype_enum_by_value_and_size). +/// If the given value cannot be found initially, this function will +/// ask if the user would like to import a standard enum. +/// \param title chooser title +/// \param default_id id of enum to select by default +/// \param value value to search for +/// \param nbytes size of value +/// \param[out] serial serial number of imported enum member, if one was found +/// \return enum id of selected (or imported) enum, #BADNODE if none was found + +inline enum_t choose_enum_by_value( + const char *title, + enum_t default_id, + uint64 value, + int nbytes, + uchar *serial) +{ + enum_t enum_id = default_id; + callui(ui_choose, chtype_enum_by_value_and_size, &enum_id, title, value, nbytes, serial); + return enum_id; +} + + +/// Choose a function (::ui_choose, ::chtype_func). +/// \param title chooser title +/// \param default_ea ea of function to select by default +/// \return pointer to function that was selected, NULL if none selected + +inline func_t *choose_func(const char *title, ea_t default_ea) +{ + return callui(ui_choose, chtype_func, title, default_ea).fptr; +} + + +/// Choose a segment (::ui_choose, ::chtype_segm). +/// \param title chooser title +/// \param default_ea ea of segment to select by default +/// \return pointer to segment that was selected, NULL if none selected + +inline segment_t *choose_segm(const char *title, ea_t default_ea) +{ + return callui(ui_choose, chtype_segm, title, default_ea).segptr; +} + + +/// Choose a structure (::ui_choose, ::chtype_segm). +/// \param title chooser title; +/// \return pointer to structure that was selected, NULL if none selected + +inline struc_t *choose_struc(const char *title) +{ + return callui(ui_choose, chtype_struc, title).strptr; +} + + +/// Choose a segment register change point (::ui_choose, ::chtype_srcp). +/// \param title chooser title +/// \return pointer to segment register range of selected change point, NULL if none selected + +inline sreg_range_t *choose_srcp(const char *title) +{ + return callui(ui_choose, chtype_srcp, title).sraptr; +} + +//@} + +#ifndef SWIG + +/// Get path to a structure offset (for nested structures/enums) (::ui_choose, ::chtype_strpath). + +inline int choose_struc_path( + const char *title, + tid_t strid, + uval_t offset, + adiff_t delta, + bool appzero, + tid_t *path) +{ + return callui(ui_choose, chtype_strpath, title, strid, + offset, delta, appzero, path).i; +} + + + + +/// Invoke the chooser with a chooser object (::ui_choose, ::chtype_generic). +/// see the choose() function above + +//lint -sem(choose,custodial(1)) +inline ssize_t choose(chooser_base_t *ch, const void *def_item) +{ + return callui(ui_choose, chtype_generic, ch, def_item).ssize; +} + +#endif // SWIG + + +/// Get the underlying object of the specified chooser (::ui_get_chooser_obj). +/// +/// This attemps to find the choser by its title and, if found, returns +/// the result of calling its chooser_base_t::get_chooser_obj() method. +/// +/// \note This is object is chooser-specific. +/// \return the object that was used to create the chooser + +inline void *get_chooser_obj(const char *chooser_caption) +{ + return callui(ui_get_chooser_obj, chooser_caption).vptr; +} + +/// Get the text corresponding to the index N in the chooser data. +/// Use -1 to get the header. + +inline bool get_chooser_data( + qstrvec_t *out, + const char *chooser_caption, + int n) +{ + return callui(ui_get_chooser_data, out, chooser_caption, n).cnd; +} + + +/// Enable item-specific attributes for chooser items (::ui_enable_chooser_item_attrs). +/// For example: color list items differently depending on a criterium. \n +/// If enabled, the chooser will generate ui_get_chooser_item_attrs \n +/// events that can be intercepted by a plugin to modify the item attributes. \n +/// This event is generated only in the GUI version of IDA. \n +/// Specifying #CH_ATTRS bit at the chooser creation time has the same effect. +/// \return success + +inline bool idaapi enable_chooser_item_attrs(const char *chooser_caption, bool enable) +{ + return callui(ui_enable_chooser_item_attrs, chooser_caption, enable).cnd; +} + + +/// See show_wait_box() + +THREAD_SAFE AS_PRINTF(1, 0) inline void show_wait_box_v(const char *format, va_list va) +{ + callui(ui_mbox, mbox_wait, format, va); +} + + +/// Display a dialog box with "Please wait...". +/// If the text message starts with "HIDECANCEL\n", the cancel button \n +/// won't be displayed in the dialog box and you don't need to check \n +/// for cancellations with user_cancelled(). Plugins must call hide_wait_box() \n +/// to close the dialog box, otherwise the user interface will be disabled. +/// +/// Note that, if the wait dialog is already visible, show_wait_box() will \n +/// 1) push the currently-displayed text on a stack \n +/// 2) display the new text \n +/// Then, when hide_wait_box() is called, if that stack isn't empty its top \n +/// label will be popped and restored in the wait dialog. \n +/// This implies that a plugin should call hide_wait_box() exactly as many \n +/// times as it called show_wait_box(), or the wait dialog might remain \n +/// visible and block the UI. \n +/// Also, in case the plugin knows the wait dialog is currently displayed, \n +/// alternatively it can call replace_wait_box(), to replace the text of the\n +/// dialog without pushing the currently-displayed text on the stack. +THREAD_SAFE AS_PRINTF(1, 2) inline void show_wait_box(const char *format, ...) +{ + va_list va; + va_start(va, format); + show_wait_box_v(format, va); + va_end(va); +} + + +/// Hide the "Please wait dialog box" + +THREAD_SAFE inline void hide_wait_box(void) +{ + // stupid watcom requires va_list should not be NULL + callui(ui_mbox, mbox_hide, NULL, &callui); +} + + +/// Replace the label of "Please wait dialog box" + +THREAD_SAFE AS_PRINTF(1, 2) inline void replace_wait_box(const char *format, ...) +{ + va_list va; + va_start(va, format); + callui(ui_mbox, mbox_replace, format, va); + va_end(va); +} + + +/// Issue a beeping sound (::ui_beep). +/// \param beep_type ::beep_t + +inline void beep(beep_t beep_type=beep_default) +{ + callui(ui_beep, beep_type); +} + + +/// Display copyright warning (::ui_copywarn). +/// \return yes/no + +inline bool display_copyright_warning(void) +{ + return callui(ui_copywarn).cnd; +} + +#endif // __UI__ END OF UI SERVICE FUNCTIONS + + +/// Show a message box asking to send the input file to support@hex-rays.com. +/// \param format the reason why the input file is bad + +THREAD_SAFE AS_PRINTF(1, 2) inline void ask_for_feedback(const char *format, ...) +{ + va_list va; + va_start(va, format); + callui(ui_mbox, mbox_feedback, format, va); + va_end(va); +} + + +/// Display a dialog box and wait for the user to input an address (::ui_ask_addr). +/// \param addr in/out parameter. contains pointer to the address. +/// \param format printf() style format string with the question +/// \retval 0 the user pressed Esc. +/// \retval 1 ok, the user entered an address + +AS_PRINTF(2, 3) inline bool ask_addr(ea_t *addr, const char *format, ...) +{ + va_list va; + va_start(va, format); + bool ok = callui(ui_ask_addr, addr, format, va).cnd; + va_end(va); + return ok; +} + + +/// Display a dialog box and wait for the user to input an segment name (::ui_ask_seg). +/// This function allows to enter segment register names, segment base +/// paragraphs, segment names to denote a segment. +/// \param sel in/out parameter. contains selector of the segment +/// \param format printf() style format string with the question +/// \retval 0 if the user pressed Esc. \n +/// \retval 1 ok, the user entered an segment name + +AS_PRINTF(2, 3) inline bool ask_seg(sel_t *sel, const char *format, ...) +{ + va_list va; + va_start(va, format); + bool ok = callui(ui_ask_seg, sel, format, va).cnd; + va_end(va); + return ok; +} + + +/// Display a dialog box and wait for the user to input an number (::ui_ask_long). +/// The number is represented in C-style. +/// This function allows to enter any IDC expression and +/// properly calculates it. +/// \param value in/out parameter. contains pointer to the number +/// \param format printf() style format string with the question +/// \retval 0 if the user pressed Esc. \n +/// \retval 1 ok, the user entered a valid number. + +AS_PRINTF(2, 3) inline bool ask_long(sval_t *value, const char *format, ...) +{ + va_list va; + va_start(va, format); + bool ok = callui(ui_ask_long, value, format, va).cnd; + va_end(va); + return ok; +} + + +//--------------------------------------------------------------------------- +// E R R O R / W A R N I N G / I N F O D I A L O G B O X E S +//--------------------------------------------------------------------------- + +/// If this variable is set, then dialog boxes will not appear on the screen. +/// Warning/info messages are shown in the messages window. \n +/// The default value of user input dialogs will be returned to the +/// caller immediately. \n +/// This variable is used to enable unattended work of ida. + +idaman bool ida_export_data batch; + + +/// Exiting because of a a fatal error? +/// Is non-zero if we are exiting with from the error() function. + +idaman int ida_export_data errorexit; + + +/// Display error dialog box and exit. +/// If you just want to display an error message and let IDA continue, +/// do NOT use this function! Use warning() or info() instead. +/// \param format printf() style message string. +/// It may have some prefixes, see 'Format of dialog box' for details. + +THREAD_SAFE AS_PRINTF(1, 2) NORETURN inline void error(const char *format,...) +{ + va_list va; + va_start(va, format); + verror(format, va); + // NOTREACHED +} + + +/// Display warning dialog box and wait for the user to press Enter or Esc. +/// This messagebox will by default contain a "Don't display this message again" \n +/// checkbox if the message is repetitively displayed. If checked, the message \n +/// won't be displayed anymore during the current IDA session. \n +/// \param format printf() style format string. +/// It may have some prefixes, see 'Format of dialog box' for details. + +THREAD_SAFE AS_PRINTF(1, 0) inline void vwarning(const char *format, va_list va) +{ + callui(ui_mbox, mbox_warning, format, va); +} + +THREAD_SAFE AS_PRINTF(1, 2) inline void warning(const char *format, ...) +{ + va_list va; + va_start(va, format); + vwarning(format, va); + va_end(va); +} + + +/// Display info dialog box and wait for the user to press Enter or Esc. +/// This messagebox will by default contain a "Don't display this message again" \n +/// checkbox. If checked, the message will never be displayed anymore (state saved \n +/// in the Windows registry or the idareg.cfg file for a non-Windows version). +/// \param format printf() style format string. +/// It may have some prefixes, see 'Format of dialog box' for details. + +THREAD_SAFE AS_PRINTF(1, 0) inline void vinfo(const char *format, va_list va) +{ + callui(ui_mbox, mbox_info, format, va); +} + +THREAD_SAFE AS_PRINTF(1, 2) inline void info(const char *format, ...) +{ + va_list va; + va_start(va, format); + vinfo(format, va); + va_end(va); +} + + +/// Display "no memory for module ..." dialog box and exit. +/// \param format printf() style message string. + +THREAD_SAFE AS_PRINTF(1, 0) NORETURN inline void vnomem(const char *format, va_list va) +{ + callui(ui_mbox, mbox_nomem, format, va); + // NOTREACHED + abort(); // to suppress compiler warning or error +} + +THREAD_SAFE AS_PRINTF(1, 2) NORETURN inline void nomem(const char *format, ...) +{ + va_list va; + va_start(va, format); + vnomem(format, va); + // NOTREACHED +} + + +/// Output a formatted string to the output window [analog of printf()]. +/// Everything appearing on the output window may be written +/// to a text file. For this the user should define the following environment +/// variable: \n +/// set IDALOG=idalog.txt +/// +/// \param format printf() style message string. +/// \return number of bytes output + +THREAD_SAFE AS_PRINTF(1, 0) inline int vmsg(const char *format, va_list va) +{ + return callui(ui_msg, format, va).i; +} + +THREAD_SAFE AS_PRINTF(1, 2) inline int msg(const char *format, ...) +{ + va_list va; + va_start(va, format); + int nbytes = vmsg(format, va); + va_end(va); + return nbytes; +} + + + +#ifndef SWIG + +/*! \defgroup FORM_C ask_form()/open_form() + + \brief This module describes how to generate a custom form. + + <pre> + + The following keywords might appear at the beginning of the 'form' argument + (case insensitive): + + STARTITEM number + + where number is a number of input field the cursor will stand on. + By default the cursor is in the first field of the dialog box. + The input fields are numbered from 0 (the first field is field 0). + + BUTTON name caption + + Alternative caption for a button. It may contain the character + to highlight in this form: ~Y~es + Valid button names are: YES, NO, CANCEL + For example: + BUTTON YES Please do + BUTTON NO Nope + BUTTON CANCEL NONE + + By default the NO button is not displayed. If it is displayed, then + the return value of the function will be different! + (see the function description) + + Empty text means that there won't be any corresponding button. + (you may also use NONE as the caption to hide it) + + A * after the button name means that this button will be the default: + + BUTTON CANCEL* Cancel + + Next, if the dialog box is kept in IDA.HLP, the following may appear: + (this defines help context for the whole dialog box) + + @hlpMessageName[] + + If the form is not in IDA.HLP file, then it can have a built-in + help message. In this case the help screen should be enclosed in the + following keywords: + + HELP + .... + .... + .... + ENDHELP + + Each keyword should be on a separate line. + + Next there must be the title line and two empty lines. + Most of the text in the dialog box text string is copied to the dialog + without modification. There are three special cases: + + - dynamic labels (format parameters) + - callback arguments + - input fields + + For example, this dialog box: + + ------ format: + Sample dialog box + + + This is sample dialog box for %A + using address %$ + + <~E~nter value:N::18::> + + ------ + + Contains two dynamic labels (text %A and address %$) and one input field + (numerical input box with the label "Enter value"). + + Parameters for the dynamic labels and input fields are taken from the + function's input arguments (va_list). The corresponding argument should + contain a pointer (sic, pointer) to the value to be displayed. + + The dialog box above should be called as + + \code + char *string = "something"; + ea_t addr = someaddr; + uval_t answer = 0; + int ok = ask_form(format, string, &addr, &answer); + \endcode + + + Dynamic labels are used to specify variant parts of the dialog box text. + They use the following syntax: + + %nT + + where + n - optional decimal field ID, which may be used in the + ::form_actions_t calls to get/set label value at runtime + T - a character specifying type of input field. All input field + types (except B and K) are valid format specifiers. See below + for the list. + + + There are two special specifiers for callbacks: + + The combination '%/' corresponds to a callback function that will be + called when any of the fields is modified. The callback type is ::formchgcb_t. + There can be only one such callback. It corresponds to the first variadic + argument regardless of its exact position in the format string. + + The combination '%*' is used to store user data (void *) in the form. + This data can be later retrieved from the ::formchgcb_t callback via the + form action method get_ud(). + + Input fields use the following syntax: + + <label:type:width:swidth:@hlp[]> + + where + label - any text string serving as label for the input field + the label may contain an accelerator key like this: "~O~pen" + (O is the accelerator key; Alt-O will work too) + type - a character specifying type of input field. + The form() function will perform initial validation of + value specified by the user and convert it appropriately. + See table of input field types below. The type can be followed + by a decimal number, an input field ID. + width - for A, I, T, X: decimal number specifying size of the buffer + passed for text input fields (including terminating 0). + if omitted or <0, assumed to be at least MAXSTR + + for B, k: the code generated when the user presses the button (passed to the button callback) + for f (path to file) this attribute specifies the dialog type: + 0-'open file' dialog box + 1-'save file' dialog box + for F (folder) it is ignored (buffer is assumed to be at least QMAXPATH long) + for b (dropdown list) this attribute specifies the readonly attribute: + 0 - read-only dropdown list + > 0 - editable dropdown list + for i, q: decimal number specifying maximum possible number + of characters that can be entered into the input field + for the rest of controls: this field is ignored + swidth -decimal number specifying width of visible part of input field. + this number may be omitted. + @hlp[]- help context for the input field. you may replace the + help context with '::' (two colons) if you don't want to + specify help context. The help context is a number of help + page from IDA.HLP file. + + + Input field types va_list parameter + ----------------- ----------------- + + q - UTF-8 string ::qstring* + h - HTML text char * (only for GUI version; only for dynamic labels; no input) + S - segment ::sel_t* + N - hex number, C notation ::uval_t* + n - signed hex number, C notation ::sval_t* + L - C notation number ::uint64* + (prefix 0x - hex, 0 - octal, otherwise decimal) + l - same as L but with optional sign ::int64* + M - hex number, no "0x" prefix ::uval_t* + D - decimal number ::sval_t* + O - octal number, C notation ::sval_t* + Y - binary number, "0b" prefix ::sval_t* + H - char value, C notation ::sval_t* + $ - address ::ea_t* + I - ident char* at least #MAXNAMELEN size (obsolete, will be removed) + i - ident ::qstring* + B - button ::buttoncb_t* + k - txt: button (same as B)/gui: hyperlink ::buttoncb_t* + K - color button ::bgcolor_t* + F - path to folder char* at least #QMAXPATH size + f - path to file char* at least #QMAXPATH size + T - type declaration char* at least #MAXSTR size, obsolete, see below + y - type declaration ::qstring* + X - command char* at least #MAXSTR size + E - chooser ::chooser_base_t * - embedded chooser + ::sizevec_t * - in/out: selected lines (0-based) + (NB: this field takes two args) + t - multi line text control ::textctrl_info_t * + b - dropdown list ::qstrvec_t * - the list of items + int* or ::qstring* - the preselected item + (::qstring* when the combo is editable, i.e. width field is >0) + + A - UTF-8 string char* at least MAXSTR size, obsolete. Use 'q' instead. + + The M, n, N, D, O, Y, H, $ fields try to parse the input as an IDC expression + and convert the result into the required value type + + If the buffer for 'F' field contains filemasks and descriptions like this: + *.exe|Executable files,*.dll|Dll files + they will be used in the dialog box filter. + + The hint message can be specified before the label enclosed in '#': + + <#hint message#label:...> + + Radiobuttons and checkboxes are represented by: + + <label:type> + <label:type>> - end of block + + where valid types are C and R + (you may use lowercase 'c' and 'r' if you need to create two radiobutton + or checkbox groups on the same lines). The field ID of the whole group + can be specified between the brackets: <label:type>ID> + + field types va_list parameter + ----------- ----------------- + + C - checkbox ushort* bit mask of checkboxes + R - radiobutton ushort* number of radiobutton + + The box title and hint messages can be specified like this: + + <#item hint#title#box hint#label:type> + + The title and the box hint can be specified only in the first item of the box. + If the hint doesn't exist, it should be specified as an empty hint (##title##) + The subsequent items can have an item hint only: + + <#item hint#label:type> + + Initial values of input fields are specified in the corresponding + input/output parameters (taken from va_list array). + + OK, Cancel and (possibly) Help buttons are displayed at the bottom of + the dialog box automatically. Their captions can be changed by the BUTTON + keywords described at the beginning of this page. + + Input field definition examples: + + <Kernel analyzer options ~1~:B:0:::> + <~A~nalysis enabled:C> + <~I~ndicator enabled:C>> + <Names pre~f~ix :A:15:15::> + <~O~utput file:f:1:64::> + <~O~utput directory:F::64::> + + Resizable fields can be separated by splitters (GUI only). + + A vertical splitter is represented by <|>. E.g.,: + <~Chooser~:E1:0:40:::><|><~E~ditor:t2:0:40:::> + whereas a horizontal splitter is represented by <->. E.g.,: + <~Chooser~:E1:0:40:::> + <-> + <~E~ditor:t2:0:40:::> + + </pre> +*/ +//@{ +//---------------------------------------------------------------------- +// F O R M S - C O M P L E X D I A L O G B O X E S +//---------------------------------------------------------------------- + +/// See ask_form() + +inline int vask_form(const char *format, va_list va) +{ + return callui(ui_ask_form, format, va).i; +} + +/// Display a dialog box and wait for the user. +/// If the form contains the "BUTTON NO <title>" keyword, then the return values +/// are the same as in the ask_yn() function (\ref ASKBTN_) +/// \param form dialog box as a string. see \ref FORM_C +/// \retval 0 the user pressed Esc, no memory to display or form syntax error +/// a dialog box (a warning is displayed in this case). +/// all variables retain their original values. +/// \retval 1 ok, all input fields are filled and validated. +/// \retval -1 the form had BUTTON CANCEL and the user cancelled the dialog + +inline int ask_form(const char *form, ...) +{ + va_list va; + va_start(va, form); + int code = vask_form(form, va); + va_end(va); + return code; +} + + +/// Create and/or activate dockable modeless form (::ui_open_form). +/// \param format string +/// \param flags \ref WIDGET_OPEN +/// \param va args +/// \return pointer to resulting TWidget + +inline TWidget *vopen_form(const char *format, uint32 flags, va_list va) +{ + return (TWidget *)callui(ui_open_form, format, flags, va).vptr; +} + + +/// Display a dockable modeless dialog box and return a handle to it. +/// \param form dialog box as a string. see \ref FORM_C +/// \param flags \ref WIDGET_OPEN +/// \return handle to the form or NULL. +/// the handle can be used with TWidget functions: close_widget()/activate_widget()/etc + +inline TWidget *open_form(const char *form, uint32 flags, ...) +{ + va_list va; + va_start(va, flags); + TWidget *widget = vopen_form(form, flags, va); + va_end(va); + return widget; +} + +//@} FORM_C + + +/// Functions available from ::formchgcb_t. +/// For getters/setters for specific field values, see #DEF_SET_METHOD. +struct form_actions_t +{ + /// Get value of an input field. + /// \return false if no such field id or invalid field type (B) + virtual bool idaapi _get_field_value(int field_id, void *buf) = 0; + + /// Set value of an input field. + /// \return false if no such field id or invalid field type (B) + virtual bool idaapi _set_field_value(int field_id, const void *buf) = 0; + + /// Enable or disable an input field. + /// \return false if no such field id + virtual bool idaapi enable_field(int field_id, bool enable) = 0; + + /// Show or hide an input field. + /// \return false if no such field id + virtual bool idaapi show_field(int field_id, bool display) = 0; + + /// Move/Resize an input field. + /// Parameters specified as -1 are not modified. + /// \return false no such field id + virtual bool idaapi move_field(int field_id, int x, int y, int w, int h) = 0; + + /// Get currently focused input field. + /// \return -1 if no such field + virtual int idaapi get_focused_field(void) = 0; + + /// Set currently focused input field. + /// \return false if no such field id + virtual bool idaapi set_focused_field(int field_id) = 0; + + /// Refresh a field + virtual void idaapi refresh_field(int field_id) = 0; + + /// Close the form + virtual void idaapi close(int close_normally) = 0; + + /// Retrieve the user data specified through %* + virtual void *idaapi get_ud() = 0; + + /// Get value of an UTF-8 string input field. + /// \return false if no such field id or invalid field type (B) + virtual bool idaapi _get_str_field_value(int field_id, char *buf, const size_t bufsize) = 0; + +/// Helper to define functions in ::form_actions_t that get/set field values of different types. +/// Please see this file's source code for specific uses. +#define DEF_SET_METHOD(NAME, TYPE) \ + inline bool idaapi set_ ## NAME ## _value(int field_id, const TYPE *val) \ + { \ + return _set_field_value(field_id, val); \ + } +/// \copydoc DEF_SET_METHOD +#define DEF_FIELD_METHOD(NAME, TYPE) \ + inline bool idaapi get_ ## NAME ## _value(int field_id, TYPE *val) \ + { \ + return _get_field_value(field_id, val); \ + } \ + DEF_SET_METHOD(NAME, TYPE) +/// \copydoc DEF_SET_METHOD +#define DEF_STR_FIELD_METHOD(NAME ) \ + inline bool idaapi get_ ## NAME ## _value(int field_id, char *buf, const size_t bufsize) \ + { \ + return _get_str_field_value(field_id, buf, bufsize); \ + } \ + DEF_SET_METHOD(NAME, char) + + // get/set value of radio button (r, R) + DEF_FIELD_METHOD(radiobutton, ushort) + // get/set value of radio button group + DEF_FIELD_METHOD(rbgroup, ushort) + // get/set value of check box (c, C) + DEF_FIELD_METHOD(checkbox, ushort) + // get/set value of check box group + DEF_FIELD_METHOD(cbgroup, ushort) + // get/set value of color control (K) + DEF_FIELD_METHOD(color, bgcolor_t) + // get/set embedded chooser selected items (E) + DEF_FIELD_METHOD(chooser, sizevec_t) + // get/set value of editable combo box (b when field 'width' >0) + DEF_FIELD_METHOD(combobox, qstring) + // get/set selected item of read-only combo box (b when field 'width' ==0) + DEF_FIELD_METHOD(combobox, int) + // get/set value of multiline text input control (t) + DEF_FIELD_METHOD(text, textctrl_info_t) + // get/set text of buttons + DEF_FIELD_METHOD(button, qstring) + // get/set value of dynamic label (%) + DEF_STR_FIELD_METHOD(label) + // get/set string value (A, I, T) + DEF_STR_FIELD_METHOD(string) + // get/set string value (q) + DEF_FIELD_METHOD(string, qstring) + // get/set value of segment (S) + DEF_FIELD_METHOD(segment, sel_t) + // get/set signed value (n,D,O,Y,H) + DEF_FIELD_METHOD(signed, sval_t) + // get/set unsigned value (N, M) + DEF_FIELD_METHOD(unsigned, uval_t) + // get/set value of default base (usually hex) number (l) + DEF_FIELD_METHOD(int64, int64) + // get/set value of default base (usually hex) number (L) + DEF_FIELD_METHOD(uint64, uint64) + // get/set address value ($) + DEF_FIELD_METHOD(ea, ea_t) + // get/set path value (F,f) + DEF_STR_FIELD_METHOD(path) + // get/set identifier value (I) + DEF_FIELD_METHOD(ident, qstring) + +#undef DEF_FIELD_METHOD +#undef DEF_SET_METHOD +#undef DEF_STR_FIELD_METHOD +}; + + +/// Callback. Called when an input field is modified. +/// The callback will be also called before displaying the form and as soon +/// as the user presses OK. +/// \param field_id id of the modified field +/// \retval -1 form is going to be displayed +/// \retval -2 form is going to be closed with OK. +/// \retval >0 form will be closed + +typedef int idaapi formchgcb_t(int field_id, form_actions_t &fa); + + +/// Callback. Called when a button is clicked. +/// \param button_code button code as specified in the form +/// \retval 0 currently ignored + +typedef int idaapi buttoncb_t(int button_code, form_actions_t &fa); + + +#endif // SWIG + +//--------------------------------------------------------------------------- +// Y E S / N O D I A L O G B O X +//--------------------------------------------------------------------------- + +/// \defgroup ASKBTN_ Button IDs +/// used by ask_yn() and ask_buttons() +//@{ +#define ASKBTN_YES 1 ///< Yes button +#define ASKBTN_NO 0 ///< No button +#define ASKBTN_CANCEL -1 ///< Cancel button +#define ASKBTN_BTN1 1 ///< First (Yes) button +#define ASKBTN_BTN2 0 ///< Second (No) button +#define ASKBTN_BTN3 -1 ///< Third (Cancel) button +//@} + + +THREAD_SAFE AS_PRINTF(5, 0) inline int vask_buttons( + const char *Yes, + const char *No, + const char *Cancel, + int deflt, + const char *format, + va_list va) +{ + return callui(ui_ask_buttons, Yes, No, Cancel, deflt, format, va).i; +} + + +AS_PRINTF(2, 0) inline int vask_yn(int deflt, const char *format, va_list va) +{ + return vask_buttons(NULL, NULL, NULL, deflt, format, va); +} + + +/// Display a dialog box and get choice from "Yes", "No", "Cancel". +/// \param deflt default choice: one of \ref ASKBTN_ +/// \param format The question in printf() style format +/// \return the selected button (one of \ref ASKBTN_). Esc key returns #ASKBTN_CANCEL. + +AS_PRINTF(2, 3) inline int ask_yn(int deflt, const char *format, ...) +{ + va_list va; + va_start(va, format); + int code = vask_yn(deflt, format, va); + va_end(va); + return code; +} + + +/// Display a dialog box and get choice from maximum three possibilities (::ui_ask_buttons). +/// \note for all buttons: +/// - use "" or NULL to take the default name for the button. +/// - use 'format' to hide the cancel button +/// \param Yes text for the first button +/// \param No text for the second button +/// \param Cancel text for the third button +/// \param deflt default choice: one of \ref ASKBTN_ +/// \param format printf-style format string for question. It may have some prefixes, see below. +/// \param va parameters for the format string +/// \return one of \ref ASKBTN_ specifying the selected button (Esc key returns Cancel/3rd button value) + +AS_PRINTF(5, 6) inline int ask_buttons( + const char *Yes, + const char *No, + const char *Cancel, + int deflt, + const char *format, + ...) +{ + va_list va; + va_start(va, format); + int code = vask_buttons(Yes, No, Cancel, deflt, format, va); + va_end(va); + return code; +} + +//------------------------------------------------------------------------ +/* Format of dialog box (actually they are mutliline strings + delimited by newline characters) + + The very first line of dialog box can specify a dialog box + title if the following line appears: + + TITLE title string + + + Then, the next line may contain an icon to display + in the GUI version (ignored by the text version): + + ICON NONE (no icon) + INFO (information icon) + QUESTION (question icon) + WARNING (warning icon) + ERROR (error icon) + + + Then, the next line may contain a 'Don't display this message again' + checkbox. If this checkbox is selected and the user didn't select cancel, + the button he selected is saved and automatically returned. + + AUTOHIDE NONE (no checkbox) + DATABASE (return value is saved to database) + REGISTRY (return value is saved to Windows registry or idareg.cfg + if non-Windows version) + SESSION (return value is saved for the current IDA session) + It is possible to append "*" to the AUTOHIDE keywords to have this checkbox + initially checked. For example: "AUTOHIDE REGISTRY*" + + To hide the cancel button the following keyword can be used: + + HIDECANCEL + + To enable rich text (i.e., HTML) in the Qt version of IDA, + the following keyword can be used: + + RICHTEXT + + Please note that the user still can cancel the dialog box by pressing Esc + or clicking on the 'close window' button. + + Finally, if the dialog box is kept in IDA.HLP, the following may appear + to add a Help button (this defines help context for the whole dialog box): + + @hlpMessageName[] + + + Each keyword should be alone on a line. + + Next, a format string must be specified. + To center message lines in the text version, start them with '\3' character + (currently ignored in the GUI version). +*/ + +//--------------------------------------------------------------------------- +// A S K S T R I N G O F T E X T +//--------------------------------------------------------------------------- + +/// Display a dialog box and wait for the user to input a text string (::ui_ask_str). +/// Use this function to ask one-line text. For multiline input, use ask_text(). +/// This function will trim the trailing spaces. +/// \param str qstring to fill. Can contain the default value. Cannot be NULL. +/// \param hist category of history lines. an arbitrary number. \n +/// this number determines lines accessible in the history \n +/// of the user input (when he presses down arrow) \n +/// One of \ref HIST_ should be used here +/// \param format printf() style format string with the question +/// \return false if the user cancelled the dialog, otherwise returns true. + +AS_PRINTF(3, 0) inline bool vask_str( + qstring *str, + int hist, + const char *format, + va_list va) +{ + return callui(ui_ask_str, str, hist, format, va).cnd; +} + +AS_PRINTF(3, 4) inline bool ask_str(qstring *str, int hist, const char *format, ...) +{ + va_list va; + va_start(va, format); + bool result = vask_str(str, hist, format, va); + va_end(va); + return result; +} + +/// \defgroup HIST_ Input line history constants +/// passed as 'hist' parameter to ask_str() +//@{ +#define HIST_SEG 1 ///< segment names +#define HIST_CMT 2 ///< comments +#define HIST_SRCH 3 ///< search substrings +#define HIST_IDENT 4 ///< names +#define HIST_FILE 5 ///< file names +#define HIST_TYPE 6 ///< type declarations +#define HIST_CMD 7 ///< commands +#define HIST_DIR 8 ///< directory names (text version only) +//@} + + +/// Display a dialog box and wait for the user to input an identifier. +/// If the user enters a non-valid identifier, this function displays a warning +/// and allows the user to correct it. +/// \param str qstring to fill. Can contain the default value. Cannot be NULL. +/// \param format printf() style format string with the question +/// \return false if the user cancelled the dialog, otherwise returns true. + +AS_PRINTF(2, 3) inline bool ask_ident(qstring *str, const char *format, ...) +{ + va_list va; + va_start(va, format); + bool result = vask_str(str, HIST_IDENT, format, va); + va_end(va); + return result; +} + + +/// Display a dialog box and wait for the user to input multiline text (::ui_ask_text). +/// \param answer output buffer +/// \param max_size maximum size of text in bytes including terminating zero (0 for unlimited) +/// \param defval default value. will be displayed initially in the input line. +/// may be NULL. +/// \param format printf() style format string with the question. +/// the following options are accepted at its beginning: +/// "ACCEPT TABS\n": accept tabulations in the input +/// "NORMAL FONT\n": use regular font (otherwise the notepad font) +/// \return false-if the user pressed Esc, otherwise returns true. + +AS_PRINTF(4, 0) inline bool vask_text( + qstring *answer, + size_t max_size, + const char *defval, + const char *format, + va_list va) +{ + return callui(ui_ask_text, answer, max_size, defval, format, va).cnd; +} + +AS_PRINTF(4, 5) inline bool ask_text( + qstring *answer, + size_t max_size, + const char *defval, + const char *format, + ...) +{ + va_list va; + va_start(va, format); + bool result = vask_text(answer, max_size, defval, format, va); + va_end(va); + return result; +} + + +//--------------------------------------------------------------------------- +// A S K A D D R E S S E S , N A M E S , N U M B E R S , E T C . +//--------------------------------------------------------------------------- + +/// Display a dialog box and wait for the user to input a file name (::ui_ask_file). +/// This function displays a window with file names present in the directory +/// pointed to by 'defval'. +/// +/// The 'format' parameter can contain a 'FILTER' description, of the +/// form 'description1|{wildcard1}+|...|descriptionN|{wildcardsN}+', +/// where each file type description has a corresponding set of one +/// (or more) ';'-separated mask(s). E.g., +/// \code +/// Text files|*.txt|Executable files|*.exe;*.bin +/// \endcode +/// +/// \param for_saving will the filename be used to save a file? +/// \param defval default value. will be displayed initially in the input line. +/// may be NULL may be or a wildcard file name. +/// \param format printf-style format string with the dialog title, possibly including a filter. +/// \return NULL the user cancelled the dialog. +/// Otherwise the user entered a valid file name. + +AS_PRINTF(3, 0) inline char *vask_file( + bool for_saving, + const char *defval, + const char *format, + va_list va) +{ + return callui(ui_ask_file, for_saving, defval, format, va).cptr; +} + + +AS_PRINTF(3, 4) inline char *ask_file( + bool for_saving, + const char *defval, + const char *format, + ...) +{ + va_list va; + va_start(va, format); + char *answer = vask_file(for_saving, defval, format, va); + va_end(va); + return answer; +} + + +//--------------------------------------------------------------------------- +// A D D - O N S +//--------------------------------------------------------------------------- + +/// Information about an installed add-on (e.g. a plugin) +struct addon_info_t +{ + size_t cb; //< size of this structure + const char *id; //< product code, e.g. "com.hexrays.hexx86w". Must be unique + const char *name; //< descriptive name, e.g. "Hex-Rays x86 Decompiler (Windows)" + const char *producer; //< e.g. "Hex-Rays SA" + const char *version; //< version string, e.g. 1.5.110408 + const char *url; //< URL of the product http://www.hex-rays.com/decompiler.shtml + const char *freeform; //< any string, e.g. "Copyright (c) 2007-2021 Hex-Rays" + const void *custom_data; //< custom data (license ID etc). Can be NULL. Not displayed in UI. + size_t custom_size; + + /// Constructor + addon_info_t() + : cb(sizeof(addon_info_t)), + id(nullptr), + name(nullptr), + producer(nullptr), + version(nullptr), + url(nullptr), + freeform(nullptr), + custom_data(nullptr), + custom_size(0) + {} +}; + +#ifndef __UI__ + +/// \defgroup ui_addons_funcs Functions: add-ons +/// Convenience functions for ::ui_addons +//@{ + +/// Register an add-on. Show its info in the About box. +/// For plugins, should be called from init() function +/// (repeated calls with the same product code overwrite previous entries) +/// returns: index of the add-on in the list, or -1 on error + +inline int register_addon(const addon_info_t *info) +{ + return callui(ui_addons, 0, info).i; +} + + +/// Get number of installed addons + +inline int addon_count() +{ + return callui(ui_addons, 1).i; +} + + +/// Get info about a registered addon with a given product code. +/// info->cb must be valid! +/// NB: all pointers are invalidated by next call to register_addon or get_addon_info +/// \return false if not found + +inline bool get_addon_info(const char *id, addon_info_t *info) +{ + return callui(ui_addons, 2, id, info).cnd; +} + + +/// Get info about a registered addon with specific index. +/// info->cb must be valid! +/// NB: all pointers are invalidated by next call to register_addon or get_addon_info +/// \return false if index is out of range + +inline bool get_addon_info_idx(int index, addon_info_t *info) +{ + return callui(ui_addons, 3, index, info).cnd; +} + +//@} ui_addons_funcs + +#endif + +//--------------------------------------------------------------------------- +// S T R I N G F U N C T I O N S +//--------------------------------------------------------------------------- +/// \defgroup str_funcs Functions: strings +/// functions that manipulate strings +//@{ + +/// Add space characters to the colored string so that its length will be at least +/// 'len' characters. Don't trim the string if it is longer than 'len'. +/// \param str pointer to colored string to modify (may not be NULL) +/// \param bufsize size of the buffer with the string +/// \param len the desired length of the string +/// \return pointer to the end of input string + +idaman THREAD_SAFE char *ida_export add_spaces(char *str, size_t bufsize, ssize_t len); + + +/// Remove trailing space characters from a string. +/// \param str pointer to string to modify (may be NULL) +/// \return pointer to input string + +idaman THREAD_SAFE char *ida_export trim(char *str); + + +/// Skip whitespaces in the string. +/// \return pointer to first non-whitespace char in given string + +idaman THREAD_SAFE const char *ida_export skip_spaces(const char *ptr); +inline char *skip_spaces(char *ptr) ///< \copydoc skip_spaces() + { return CONST_CAST(char*)(skip_spaces((const char *)ptr)); } + +/// Map strings to integer values - see strarray() +struct strarray_t +{ + int code; + const char *text; +}; + + +/// \defgroup CLNL_ line cleanup flags +/// Passed as 'flags' parameter to qcleanline() +//@{ +#define CLNL_RTRIM (1 << 0) ///< Remove trailing space characters. +#define CLNL_LTRIM (1 << 1) ///< Remove leading space characters. +#define CLNL_FINDCMT (1 << 2) ///< Search for the comment symbol everywhere in the line, not only at the beginning + +#define CLNL_TRIM (CLNL_RTRIM|CLNL_LTRIM) +//@} + +/// Performs some cleanup operations to a line. +/// \param buf string to modify +/// \param cmt_char character that denotes the start of a comment: +/// - the entire text is removed if the line begins with +/// this character (ignoring leading spaces) +/// - all text after (and including) this character is removed +/// if flag CLNL_FINDCMT is set +/// \param flags a combination of \ref CLNL_. defaults to CLNL_TRIM +/// \return length of line + +idaman THREAD_SAFE ssize_t ida_export qcleanline( + qstring *buf, + char cmt_char='\0', + uint32 flags=CLNL_TRIM|CLNL_FINDCMT); + + +/// Find a line with the specified code in the ::strarray_t array. +/// If the last element of the array has code==0 then it is considered as the default entry. \n +/// If no default entry exists and the code is not found, strarray() returns "". + +idaman THREAD_SAFE const char *ida_export strarray(const strarray_t *array, size_t array_size, int code); + + +/// Convert linear address to UTF-8 string + +idaman size_t ida_export ea2str(char *buf, size_t bufsize, ea_t ea); + +#ifndef SWIG + +//--------------------------------------------------------------------------- +// C O N V E R S I O N S +//--------------------------------------------------------------------------- +/// \defgroup conv Functions: string conversion +/// functions that convert between string encodings +//@{ + +/// Convert linear address to UTF-8 string +inline bool ea2str(qstring *out, ea_t ea) +{ + char tmp[MAXSTR]; + if ( ea2str(tmp, sizeof(tmp), ea) <= 0 ) + return false; + *out = tmp; + return true; +} + + +/// Convert string to linear address. +/// Tries to interpret the string as: \n +/// 1) "current IP" keyword if supported by assembler (e.g. "$" in x86) \n +/// 2) segment:offset expression, where "segment" may be a name or a fixed segment register (e.g. cs, ds) \n +/// 3) just segment name/register (translated to segment's start address) \n +/// 4) a name in the database (or debug name during debugging) \n +/// 5) +delta or -delta, where numerical 'delta' is added to or subtracted from 'screenEA' \n +/// 6) if all else fails, try to evaluate 'str' as an IDC expression + +idaman bool ida_export str2ea(ea_t *ea_ptr, const char *str, ea_t screen_ea); + + +/// Same as str2ea() but possibly with some steps skipped. +/// \param flags \ref S2EAOPT_ + +idaman bool ida_export str2ea_ex(ea_t *ea_ptr, const char *str, ea_t screen_ea, int flags); + +/// \defgroup S2EAOPT_ String to address conversion flags +/// passed as 'flags' parameter to str2ea_ex() +//@{ +#define S2EAOPT_NOCALC 0x00000001 ///< don't try to interpret string as IDC (or current extlang) expression +//@} + + +/// Convert a number in C notation to an address. +/// decimal: 1234 \n +/// octal: 0123 \n +/// hexadecimal: 0xabcd \n +/// binary: 0b00101010 + +idaman bool ida_export atoea(ea_t *pea, const char *str); + + +/// Convert segment selector to UTF-8 string + +idaman size_t ida_export stoa(qstring *buf, ea_t from, sel_t seg); + + +/// Convert UTF-8 string to segment selector. +/// \retval 0 fail +/// \retval 1 ok (hex) +/// \retval 2 ok (segment name or reg) + +idaman int ida_export atos(sel_t *seg, const char *str); + + +#define MAX_NUMBUF (128+8) ///< 16-byte value in binary base (0b00101010...) + + +/// Get the number of UTF-8 characters required to represent +/// a number with the specified number of bytes and radix. +/// \param nbytes if 0, use default number of bytes, usually 4 or 8 depending on __EA64__ +/// \param radix if 0, use default radix, usually 16 + +idaman size_t ida_export b2a_width(int nbytes, int radix); + + +/// Convert number to UTF-8 string (includes leading zeroes). +/// \param x value to convert +/// \param buf output buffer +/// \param bufsize size of output buffer +/// \param nbytes 1, 2, 3, or 4 +/// \param radix 2, 8, 10, or 16 +/// \return size of resulting string + +idaman size_t ida_export b2a32(char *buf, size_t bufsize, uint32 x, int nbytes, int radix); + + +/// Same as b2a32(), but can handle 'nbytes' = 8 + +idaman size_t ida_export b2a64(char *buf, size_t bufsize, uint64 x, int nbytes, int radix); + + + +/// Get max number of UTF-8 characters required to represent +/// a given type of value, with a given size (without leading zeroes). +/// \param nbytes size of number +/// \param flag should be one of FF_ for #MS_0TYPE +/// \param n if 1, shr 'flag' by 4 + +idaman size_t ida_export btoa_width(int nbytes, flags_t flag, int n); + + +/// Same as b2a32(), but will generate a string without any leading zeroes. +/// Can be used to output some numbers in the instructions. + +idaman size_t ida_export btoa32(char *buf, size_t bufsize, uint32 x, int radix=0); + + +/// 64-bit equivalent of btoa32() + +idaman size_t ida_export btoa64(char *buf, size_t bufsize, uint64 x, int radix=0); + + +/// 128-bit equivalent of btoa32() + +idaman size_t ida_export btoa128(char *buf, size_t bufsize, uint128 x, int radix=0); + +#ifdef __EA64__ +#define b2a b2a64 +#define btoa btoa64 +#define atob atob64 +#else +#define b2a b2a32 ///< shortcut for number->string conversion, see b2a32() +#define btoa btoa32 ///< shortcut for number->string conversion, see btoa32() +#define atob atob32 ///< shortcut for string->number conversion, see atob32() +#endif + + +/// Convert instruction operand immediate number to UTF-8. +/// This is the main function to output numbers in the instruction operands. \n +/// It prints the number with or without the leading zeroes depending on the flags. \n +/// This function is called from out_value(). Please use out_value() if you can. + +idaman size_t ida_export numop2str( + char *buf, + size_t bufsize, + ea_t ea, + int n, + uint64 x, + int nbytes, + int radix=0); + + +/// Convert UTF-8 to a number using the current assembler formats. +/// e.g. for ibmpc, '12o' is octal, '12h' is hex, etc. +/// \return success + +idaman bool ida_export atob32(uint32 *x, const char *str); + + +/// 64-bit equivalent of atob32() + +idaman bool ida_export atob64(uint64 *x, const char *str); // returns 1-ok + + +/// Auxiliary function. +/// Print displacement to a name (+disp or -disp) in the natural radix +/// \param buf output buffer to append to +/// \param disp displacement to output. 0 leads to no modifications +/// \param tag whether to output color tags + +idaman void ida_export append_disp(qstring *buf, adiff_t disp, bool tag=true); + + +/// Convert RADIX50 -> UTF-8. +/// \param p pointer to UTF-8 string +/// \param r pointer to radix50 string +/// \param k number of elements in the input string \n +/// (element of radix50 string is a word) \n +/// (element of UTF-8 string is a character) +/// \return number of elements left unprocessed in the input string, \n +/// because the input string contains unconvertible elements. \n +/// 0-ok, all elements are converted + +idaman THREAD_SAFE int ida_export r50_to_asc(char *p, const ushort *r, int k); + + +/// Convert UTF-8 -> RADIX50 (see r50_to_asc()) + +int THREAD_SAFE asc_to_r50(ushort *r, const char *p, int k); + + +//@} Conversion functions +//@} String functions + +//---------------------------------------------------------------------------- + +/// Calculate CRC32 (polynom 0xEDB88320, zlib compatible). +/// \note in IDA versions before 6.0 a different, incompatible algorithm was used + +idaman THREAD_SAFE uint32 ida_export calc_crc32(uint32 crc, const void *buf, size_t len); + + +/// Calculate an input source CRC32 + +idaman THREAD_SAFE uint32 ida_export calc_file_crc32(linput_t *fp); + + +/// Match a string with a regular expression. +/// \retval 0 no match +/// \retval 1 match +/// \retval -1 error + +idaman int ida_export regex_match(const char *str, const char *pattern, bool sense_case); + + +//---------------------------------------------------------------------------- +/// \cond +#define IS_BUTTONCB_T(v) (std::is_same<decltype(v), buttoncb_t>::value) +#define IS_FORMCHGCB_T(v) (std::is_same<decltype(v), formchgcb_t>::value) +#define IS_TEXTCTRL_INFO_T(v) (std::is_base_of<textctrl_info_t, std::remove_reference<decltype(v)>::type>::value) +#define IS_CHOOSER_BASE_T(v) (std::is_base_of<chooser_base_t, std::remove_reference<decltype(v)>::type>::value) + +/// \endcond + +#endif // SWIG + +//---------------------------------------------------------------------------- +/// \defgroup winkeys Compatibility Windows virtual keys +/// compatibility windows virtual keys to use in plugins which are not Qt aware. (check the #CVH_QT_AWARE flag) +/// these keys are provided for compilation of older plugins that use windows virtual keys on all platforms. +/// those constants are currently passed to cli_t->keydown and customview/CVH_KEYDOWN handlers. +//@{ +#define IK_CANCEL 0x03 +#define IK_BACK 0x08 +#define IK_TAB 0x09 +#define IK_CLEAR 0x0C +#define IK_RETURN 0x0D +#define IK_SHIFT 0x10 +#define IK_CONTROL 0x11 +#define IK_MENU 0x12 +#define IK_PAUSE 0x13 +#define IK_CAPITAL 0x14 +#define IK_KANA 0x15 +#define IK_ESCAPE 0x1B +#define IK_MODECHANGE 0x1F +#define IK_SPACE 0x20 +#define IK_PRIOR 0x21 +#define IK_NEXT 0x22 +#define IK_END 0x23 +#define IK_HOME 0x24 +#define IK_LEFT 0x25 +#define IK_UP 0x26 +#define IK_RIGHT 0x27 +#define IK_DOWN 0x28 +#define IK_SELECT 0x29 +#define IK_PRINT 0x2A +#define IK_EXECUTE 0x2B +#define IK_SNAPSHOT 0x2C +#define IK_INSERT 0x2D +#define IK_DELETE 0x2E +#define IK_HELP 0x2F +#define IK_LWIN 0x5B +#define IK_RWIN 0x5C +#define IK_APPS 0x5D +#define IK_SLEEP 0x5F +#define IK_NUMPAD0 0x60 +#define IK_NUMPAD1 0x61 +#define IK_NUMPAD2 0x62 +#define IK_NUMPAD3 0x63 +#define IK_NUMPAD4 0x64 +#define IK_NUMPAD5 0x65 +#define IK_NUMPAD6 0x66 +#define IK_NUMPAD7 0x67 +#define IK_NUMPAD8 0x68 +#define IK_NUMPAD9 0x69 +#define IK_MULTIPLY 0x6A +#define IK_ADD 0x6B +#define IK_SEPARATOR 0x6C +#define IK_SUBTRACT 0x6D +#define IK_DECIMAL 0x6E +#define IK_DIVIDE 0x6F +#define IK_F1 0x70 +#define IK_F2 0x71 +#define IK_F3 0x72 +#define IK_F4 0x73 +#define IK_F5 0x74 +#define IK_F6 0x75 +#define IK_F7 0x76 +#define IK_F8 0x77 +#define IK_F9 0x78 +#define IK_F10 0x79 +#define IK_F11 0x7A +#define IK_F12 0x7B +#define IK_F13 0x7C +#define IK_F14 0x7D +#define IK_F15 0x7E +#define IK_F16 0x7F +#define IK_F17 0x80 +#define IK_F18 0x81 +#define IK_F19 0x82 +#define IK_F20 0x83 +#define IK_F21 0x84 +#define IK_F22 0x85 +#define IK_F23 0x86 +#define IK_F24 0x87 +#define IK_NUMLOCK 0x90 +#define IK_SCROLL 0x91 +#define IK_OEM_FJ_MASSHOU 0x93 +#define IK_OEM_FJ_TOUROKU 0x94 +#define IK_LSHIFT 0xA0 +#define IK_RSHIFT 0xA1 +#define IK_LCONTROL 0xA2 +#define IK_RCONTROL 0xA3 +#define IK_LMENU 0xA4 +#define IK_RMENU 0xA5 +#define IK_BROWSER_BACK 0xA6 +#define IK_BROWSER_FORWARD 0xA7 +#define IK_BROWSER_REFRESH 0xA8 +#define IK_BROWSER_STOP 0xA9 +#define IK_BROWSER_SEARCH 0xAA +#define IK_BROWSER_FAVORITES 0xAB +#define IK_BROWSER_HOME 0xAC +#define IK_VOLUME_MUTE 0xAD +#define IK_VOLUME_DOWN 0xAE +#define IK_VOLUME_UP 0xAF +#define IK_MEDIA_NEXT_TRACK 0xB0 +#define IK_MEDIA_PREV_TRACK 0xB1 +#define IK_MEDIA_STOP 0xB2 +#define IK_MEDIA_PLAY_PAUSE 0xB3 +#define IK_LAUNCH_MAIL 0xB4 +#define IK_LAUNCH_MEDIA_SELECT 0xB5 +#define IK_LAUNCH_APP1 0xB6 +#define IK_LAUNCH_APP2 0xB7 +#define IK_OEM_1 0xBA +#define IK_OEM_PLUS 0xBB +#define IK_OEM_COMMA 0xBC +#define IK_OEM_MINUS 0xBD +#define IK_OEM_PERIOD 0xBE +#define IK_OEM_2 0xBF +#define IK_OEM_3 0xC0 +#define IK_OEM_4 0xDB +#define IK_OEM_5 0xDC +#define IK_OEM_6 0xDD +#define IK_OEM_7 0xDE +#define IK_OEM_102 0xE2 +#define IK_PLAY 0xFA +#define IK_ZOOM 0xFB +#define IK_OEM_CLEAR 0xFE +//@} + +/// Enumeration of form callback special values +enum cb_id +{ + CB_INIT = -1, + CB_YES = -2, + CB_CLOSE = -3, + CB_INVISIBLE = -4, // corresponds to ui_widget_invisible + CB_DESTROYING = -5, // when the actual widget tree is being destroyed +}; + +#ifndef SWIG +//------------------------------------------------------------------------- +inline void place_t__serialize(const place_t *_this, bytevec_t *out) +{ + out->pack_dd(_this->lnnum); +} + +//------------------------------------------------------------------------- +inline bool place_t__deserialize(place_t *_this, const uchar **pptr, const uchar *end) +{ + if ( *pptr >= end ) + return false; + _this->lnnum = unpack_dd(pptr, end); + return true; +} +#endif + + +#ifndef NO_OBSOLETE_FUNCS +/// Deprecated. Please use ACTION_DESC_LITERAL_* instead. +#define ACTION_DESC_LITERAL(name, label, handler, shortcut, tooltip, icon)\ + { sizeof(action_desc_t), name, label, handler, &PLUGIN, shortcut, tooltip, icon, ADF_OT_PLUGIN } + +inline void get_user_strlist_options(strwinsetup_t *out) +{ + callui(ui_obsolete_get_user_strlist_options, out); +} +inline bool del_idc_hotkey(const char *hotkey) +{ + return callui(ui_obsolete_del_idckey, hotkey).cnd; +} +#endif + +#endif // __KERNWIN_HPP diff --git a/idasdk76/include/lex.hpp b/idasdk76/include/lex.hpp new file mode 100644 index 0000000..0844f9a --- /dev/null +++ b/idasdk76/include/lex.hpp @@ -0,0 +1,351 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef LEX_HPP +#define LEX_HPP + +#include <ieee.h> + +/*! \file lex.hpp + + \brief Tools for parsing C-like input + + Functions in this file use objects of opaque type lexer_t. + To create a lexer_t instance, use create_lexer(). +*/ + +typedef ushort lxtype; ///< see \ref lx_ + +/// \defgroup lx_ Parser token types +/// See token_t::type +/// \note All separators have their ASCII codes as lxtype +//@{ +const lxtype + lx_end = 1, ///< no more tokens + lx_ident = 2, ///< ident + lx_number = 3, ///< long constant + lx_string = 4, ///< string constant (token_t.chr != 0 => unicode string) + lx_char = 5, ///< char constant + lx_typename = 6, ///< user-defined type + lx_float = 7, ///< IEEE floating point constant + lx_int64 = 8, ///< int64 constant + lx_key = 128; ///< keywords start. All keys are lx_key + keynum. \n + ///< Two-char separators are: (c1 + (c2 << 8)). \n + ///< Three-char separators: + ///< - "<<=" = ('<' + ('<'<<8)) + '=' + ///< - ">>=" = ('>' + ('>'<<8)) + '=' +//@} + + +/// Parser token +struct token_t +{ + qstring str; ///< idents & strings + lxtype type = 0; ///< see \ref lx_ + sval_t num = 0; ///< long & char constants + union + { + bool unicode = false; ///< (::lx_string: != 0 => unicode string) + bool is_unsigned; ///< (::lx_number, ::lx_int64: != 0 => unsigned value) + }; + union + { + fpvalue_t fnum; ///< floating point constant + int64 i64; ///< ::lx_int64 + }; + token_t() : fnum() {} +}; +DECLARE_TYPE_AS_MOVABLE(token_t); + +class lexer_t; // lexical analyzer, opaque structure + + +/// Preprocessor callback for unknown tokens. +/// Will be called when preprocessor calculates the value of #if expression. + +typedef error_t lx_resolver_t(lexer_t *lx, void *ud, token_t *curtok, sval_t *res); + +#ifdef _MSC_VER +#pragma warning(push) +// Conversion from 'type1 ' to 'type_2' is sign-extended. This may cause unexpected runtime behavior. +// We want this sign-extension to happen, since it comes mostly from HANDLEs. +// (see https://msdn.microsoft.com/en-us/library/ms235307.aspx ) +#pragma warning(disable:4826) +#endif + +/// Preprocessor cast +struct cast_t +{ + bool is_unsigned; + int size; + + cast_t() + { + reset(); + } + void reset(void) + { + is_unsigned = false; + size = 0; + } +}; + +struct lex_value_t +{ + bool is_unsigned; + union + { + int64 val; + uint64 uval; + }; + + lex_value_t() + { + reset(); + } + void set(const lex_value_t &v) + { + set_val(v.val, v.is_unsigned); + } + void reset(void) + { + set_val(0, true); + } + void set_val(int64 v, bool _is_unsigned) + { + is_unsigned = _is_unsigned; + val = v; + } + + uint64 get_uval(void) const + { + return val; + } + int64 get_val(void) const + { + return val; + } + + bool is_zero(void) const + { + return get_val() == 0; + } + + void perform_cast(const cast_t &cast); + + void unary_minus(const lex_value_t &v); + void unary_plus(const lex_value_t &v); + void unary_not(const lex_value_t &v); + void bitwise_not(const lex_value_t &v); + + void mul(const lex_value_t &v); + void div(const lex_value_t &v); + void mod(const lex_value_t &v); + void add(const lex_value_t &v); + void sub(const lex_value_t &v); + + void shift_right(const lex_value_t &v); + void shift_left(const lex_value_t &v); + void bitwise_and(const lex_value_t &v); + void bitwise_xor(const lex_value_t &v); + void bitwise_or(const lex_value_t &v); + void logical_and(const lex_value_t &v); + void logical_or(const lex_value_t &v); + + void cmpge(const lex_value_t &v); + void cmple(const lex_value_t &v); + void cmplt(const lex_value_t &v); + void cmpgt(const lex_value_t &v); + void cmpeq(const lex_value_t &v); + void cmpneq(const lex_value_t &v); +}; + +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +/// Preprocessor callbacks for casts. +/// Will be called when preprocessor calculates the value of #if expression. + +typedef error_t lx_parse_cast_t(lexer_t *lx, cast_t *cast, token_t *ct); + +/// Preprocessor callback. +/// It will be called for each input line. +/// \return an error code (0-ok) + +typedef int idaapi lx_preprocessor_cb(void *ud, const char *fname, int nl, const char *line); + + +/// Callback for #pragma directives. +/// \return an error code (0-ok) + +typedef int idaapi lx_pragma_cb(void *ud, const char *line); + + +/// Callback for #warning directives. +/// \return an error code (0-ok) + +typedef int idaapi lx_warning_cb(void *ud, const char *line); + + +/// Callback for #define directives +/// \return an error code (0-ok) + +typedef int idaapi lx_macro_cb( + void *ud, + const char *name, + const char *body, + int nargs, + bool isfunc, + bool is_new_macro); + + +/// Callback for #undef directives +/// \return an error code (0-ok) + +typedef int idaapi lx_undef_cb(void *ud, const char *name); + + +/// Create new lexical analyzer and set its keyword table. +/// If keys==NULL, then set the default C keyword table + +idaman lexer_t *ida_export create_lexer( + const char *const *keys, + size_t size, + void *ud=NULL); + + +/// Destroy a lexical analyzer + +idaman void ida_export destroy_lexer(lexer_t *lx); + + +/// Define a macro + +idaman error_t ida_export lex_define_macro( + lexer_t *lx, + const char *macro, + const char *body, + int nargs=0, + bool isfunc=false); + +/// Undefine a macro + +idaman void ida_export lex_undefine_macro( + lexer_t *lx, + const char *macro); + +/// Set lexer options. +/// \param options \ref LXOPT_ +/// \return the old options + +idaman int ida_export lex_set_options(lexer_t *lx, int options); + +/// \defgroup LXOPT_ Lexer options +/// Passed as 'options' parameter to lex_set_options(). +/// By default all options are on. +//@{ +#define LXOPT_PARSE_FLOATS 0x0001 ///< enable floating point constants +#define LXOPT_REQ_SEPARATOR 0x0002 ///< require a separator between a number and an ident or a character/string constant or dot +#define LXOPT_NOCASE_FILES 0x0004 ///< case-insensitive file search +#define LXOPT_C99_CONSTANTS 0x0008 ///< the size and sign of constants depend on the value itself and the 'U', 'L', and 'LL' + ///< modifier suffixes. otherwise the constant is always considered as signed and the size + ///< depends only on the number of bytes in the value +//@} + + +/// Get next token +/// \param p_lnnum line number where the token starts + +idaman error_t ida_export lex_get_token(lexer_t *lx, token_t *t); +idaman error_t ida_export lex_get_token2(lexer_t *lx, token_t *t, int32 *p_lnnum); + + +/// Enumerate all macros. +/// Do so until 'cb' returns non-zero. + +idaman int ida_export lex_enum_macros( + const lexer_t *lx, + int idaapi cb(const char *name, const char *body, int nargs, bool isfunc, void *ud), + void *ud=NULL); + + +/// Debug: get text representation of token + +idaman const char *ida_export lex_print_token(qstring *buf, const token_t *t); + + +//------------------------------------------------------------------------- +/// \name String oriented functions +//@{ + +/// Set the input line and the macro table. +/// if macros==NULL, the macro table will not be changed. + +idaman error_t ida_export lex_init_string( + lexer_t *lx, + const char *line, + void *macros=NULL); +//@} + +//------------------------------------------------------------------------- +/// \name File oriented functions +//@{ + +/// Initialization: file may be NULL. +/// Also see lex_term_file(). + +idaman error_t ida_export lex_init_file(lexer_t *lx, const char *file); + + +/// Error handling. +/// if level > 0, then return information about the enclosing file which +/// included the current one. + +idaman const char *ida_export lex_get_file_line( + lexer_t *lx, + int32 *linenum, + const char **lineptr, + int level=0); + + +/// Termination: also see lex_init_file() + +idaman void ida_export lex_term_file(lexer_t *lx, bool del_macros); +//@} + +//------------------------------------------------------------------------- +/// \name Token stack +//@{ +typedef qstack<token_t> tokenstack_t; ///< see get_token(), unget_token() + + +/// Retrieve token from a stack or lexer. +/// If buf is not empty then get the token on top of the stack. +/// If buf is empty then gen the next token from the lexer. +/// \return success + +inline bool get_token(token_t *t, lexer_t *lx, tokenstack_t &buf) +{ + if ( !buf.empty() ) + *t = buf.pop(); + else if ( lex_get_token(lx, t) != eOk ) + return false; + return true; +} + + +/// Push a token back onto the token stack + +inline void unget_token(const token_t &t, tokenstack_t &buf) +{ + buf.push(t); +} +//@} + + +#endif // LEX_HPP diff --git a/idasdk76/include/lines.hpp b/idasdk76/include/lines.hpp new file mode 100644 index 0000000..b2d9203 --- /dev/null +++ b/idasdk76/include/lines.hpp @@ -0,0 +1,595 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _LINES_HPP +#define _LINES_HPP + +#include <ida.hpp> + +/*! \file lines.hpp + + \brief High level functions that deal with the generation + of the disassembled text lines. + + This file also contains definitions for the syntax highlighting. + + Finally there are functions that deal with anterior/posterior + user-defined lines. +*/ + +struct range_t; + +//--------------------------------------------------------------------------- +// C O L O R D E F I N I T I O N S +//--------------------------------------------------------------------------- + +/// \defgroup color_def Color definitions +/// +/// Here we describe the structure of embedded escape sequences used to +/// implement syntax highlighting. +/// +/// IDP module should insert appropriate escape characters into the +/// output lines as necessary. This approach allows to create an IDP +/// module without the syntax highlighting too - just don't use +/// escape sequences. +/// +/// A typical color sequence looks like this: +/// +/// #COLOR_ON COLOR_xxx text #COLOR_OFF COLOR_xxx +/// +/// The first 2 items turn color 'xxx' on, then the text follows, +/// and the color is turned off by two last items. +/// +/// For the convenience we've defined a set of macro definitions +/// and functions to deal with colors. +//@{ + +/// \defgroup color_esc Color escape characters +/// Initiate/Terminate a color tag +//@{ +#define COLOR_ON '\1' ///< Escape character (ON). + ///< Followed by a color code (::color_t). +#define COLOR_OFF '\2' ///< Escape character (OFF). + ///< Followed by a color code (::color_t). +#define COLOR_ESC '\3' ///< Escape character (Quote next character). + ///< This is needed to output '\1' and '\2' + ///< characters. +#define COLOR_INV '\4' ///< Escape character (Inverse foreground and background colors). + ///< This escape character has no corresponding #COLOR_OFF. + ///< Its action continues until the next #COLOR_INV or end of line. + +#define SCOLOR_ON "\1" ///< Escape character (ON) +#define SCOLOR_OFF "\2" ///< Escape character (OFF) +#define SCOLOR_ESC "\3" ///< Escape character (Quote next character) +#define SCOLOR_INV "\4" ///< Escape character (Inverse colors) + +/// Is the given char a color escape character? +inline THREAD_SAFE bool requires_color_esc(char c) { return c >= COLOR_ON && c <= COLOR_INV; } +//@} + +typedef uchar color_t; ///< color tag - see \ref COLOR_ +/// \defgroup COLOR_ Color tags +/// Specify a color for a syntax item +//@{ +const color_t + COLOR_DEFAULT = 0x01, ///< Default + COLOR_REGCMT = 0x02, ///< Regular comment + COLOR_RPTCMT = 0x03, ///< Repeatable comment (comment defined somewhere else) + COLOR_AUTOCMT = 0x04, ///< Automatic comment + COLOR_INSN = 0x05, ///< Instruction + COLOR_DATNAME = 0x06, ///< Dummy Data Name + COLOR_DNAME = 0x07, ///< Regular Data Name + COLOR_DEMNAME = 0x08, ///< Demangled Name + COLOR_SYMBOL = 0x09, ///< Punctuation + COLOR_CHAR = 0x0A, ///< Char constant in instruction + COLOR_STRING = 0x0B, ///< String constant in instruction + COLOR_NUMBER = 0x0C, ///< Numeric constant in instruction + COLOR_VOIDOP = 0x0D, ///< Void operand + COLOR_CREF = 0x0E, ///< Code reference + COLOR_DREF = 0x0F, ///< Data reference + COLOR_CREFTAIL = 0x10, ///< Code reference to tail byte + COLOR_DREFTAIL = 0x11, ///< Data reference to tail byte + COLOR_ERROR = 0x12, ///< Error or problem + COLOR_PREFIX = 0x13, ///< Line prefix + COLOR_BINPREF = 0x14, ///< Binary line prefix bytes + COLOR_EXTRA = 0x15, ///< Extra line + COLOR_ALTOP = 0x16, ///< Alternative operand + COLOR_HIDNAME = 0x17, ///< Hidden name + COLOR_LIBNAME = 0x18, ///< Library function name + COLOR_LOCNAME = 0x19, ///< Local variable name + COLOR_CODNAME = 0x1A, ///< Dummy code name + COLOR_ASMDIR = 0x1B, ///< Assembler directive + COLOR_MACRO = 0x1C, ///< Macro + COLOR_DSTR = 0x1D, ///< String constant in data directive + COLOR_DCHAR = 0x1E, ///< Char constant in data directive + COLOR_DNUM = 0x1F, ///< Numeric constant in data directive + COLOR_KEYWORD = 0x20, ///< Keywords + COLOR_REG = 0x21, ///< Register name + COLOR_IMPNAME = 0x22, ///< Imported name + COLOR_SEGNAME = 0x23, ///< Segment name + COLOR_UNKNAME = 0x24, ///< Dummy unknown name + COLOR_CNAME = 0x25, ///< Regular code name + COLOR_UNAME = 0x26, ///< Regular unknown name + COLOR_COLLAPSED= 0x27, ///< Collapsed line + COLOR_FG_MAX = 0x28, ///< Max color number + + // Fictive colors + + COLOR_ADDR = COLOR_FG_MAX, ///< hidden address marks. + ///< the address is represented as 8digit + ///< hex number: 01234567. + ///< it doesn't have #COLOR_OFF pair. + ///< NB: for 64-bit IDA, the address is 16digit. + + COLOR_OPND1 = COLOR_ADDR+1, ///< Instruction operand 1 + COLOR_OPND2 = COLOR_ADDR+2, ///< Instruction operand 2 + COLOR_OPND3 = COLOR_ADDR+3, ///< Instruction operand 3 + COLOR_OPND4 = COLOR_ADDR+4, ///< Instruction operand 4 + COLOR_OPND5 = COLOR_ADDR+5, ///< Instruction operand 5 + COLOR_OPND6 = COLOR_ADDR+6, ///< Instruction operand 6 + COLOR_OPND7 = COLOR_ADDR+7, ///< Instruction operand 7 + COLOR_OPND8 = COLOR_ADDR+8, ///< Instruction operand 8 + + + COLOR_RESERVED1= COLOR_ADDR+11,///< This tag is reserved for internal IDA use + COLOR_LUMINA = COLOR_ADDR+12;///< Lumina-related, only for the navigation band +//@} + +/// Size of a tagged address (see ::COLOR_ADDR) +#define COLOR_ADDR_SIZE (sizeof(ea_t)*2) + +/// \defgroup SCOLOR_ Color string constants +/// These definitions are used with the #COLSTR macro +//@{ +#define SCOLOR_DEFAULT "\x01" ///< Default +#define SCOLOR_REGCMT "\x02" ///< Regular comment +#define SCOLOR_RPTCMT "\x03" ///< Repeatable comment (defined not here) +#define SCOLOR_AUTOCMT "\x04" ///< Automatic comment +#define SCOLOR_INSN "\x05" ///< Instruction +#define SCOLOR_DATNAME "\x06" ///< Dummy Data Name +#define SCOLOR_DNAME "\x07" ///< Regular Data Name +#define SCOLOR_DEMNAME "\x08" ///< Demangled Name +#define SCOLOR_SYMBOL "\x09" ///< Punctuation +#define SCOLOR_CHAR "\x0A" ///< Char constant in instruction +#define SCOLOR_STRING "\x0B" ///< String constant in instruction +#define SCOLOR_NUMBER "\x0C" ///< Numeric constant in instruction +#define SCOLOR_VOIDOP "\x0D" ///< Void operand +#define SCOLOR_CREF "\x0E" ///< Code reference +#define SCOLOR_DREF "\x0F" ///< Data reference +#define SCOLOR_CREFTAIL "\x10" ///< Code reference to tail byte +#define SCOLOR_DREFTAIL "\x11" ///< Data reference to tail byte +#define SCOLOR_ERROR "\x12" ///< Error or problem +#define SCOLOR_PREFIX "\x13" ///< Line prefix +#define SCOLOR_BINPREF "\x14" ///< Binary line prefix bytes +#define SCOLOR_EXTRA "\x15" ///< Extra line +#define SCOLOR_ALTOP "\x16" ///< Alternative operand +#define SCOLOR_HIDNAME "\x17" ///< Hidden name +#define SCOLOR_LIBNAME "\x18" ///< Library function name +#define SCOLOR_LOCNAME "\x19" ///< Local variable name +#define SCOLOR_CODNAME "\x1A" ///< Dummy code name +#define SCOLOR_ASMDIR "\x1B" ///< Assembler directive +#define SCOLOR_MACRO "\x1C" ///< Macro +#define SCOLOR_DSTR "\x1D" ///< String constant in data directive +#define SCOLOR_DCHAR "\x1E" ///< Char constant in data directive +#define SCOLOR_DNUM "\x1F" ///< Numeric constant in data directive +#define SCOLOR_KEYWORD "\x20" ///< Keywords +#define SCOLOR_REG "\x21" ///< Register name +#define SCOLOR_IMPNAME "\x22" ///< Imported name +#define SCOLOR_SEGNAME "\x23" ///< Segment name +#define SCOLOR_UNKNAME "\x24" ///< Dummy unknown name +#define SCOLOR_CNAME "\x25" ///< Regular code name +#define SCOLOR_UNAME "\x26" ///< Regular unknown name +#define SCOLOR_COLLAPSED "\x27" ///< Collapsed line +#define SCOLOR_ADDR "\x28" ///< Hidden address mark +//@} + +//----------------- Line prefix colors -------------------------------------- +/// \defgroup COLOR_PFX Line prefix colors +/// Note: line prefix colors are not used in processor modules +//@{ +#define COLOR_DEFAULT 0x01 ///< Default +#define COLOR_SELECTED 0x02 ///< Selected +#define COLOR_LIBFUNC 0x03 ///< Library function +#define COLOR_REGFUNC 0x04 ///< Regular function +#define COLOR_CODE 0x05 ///< Single instruction +#define COLOR_DATA 0x06 ///< Data bytes +#define COLOR_UNKNOWN 0x07 ///< Unexplored byte +#define COLOR_EXTERN 0x08 ///< External name definition segment +#define COLOR_CURITEM 0x09 ///< Current item +#define COLOR_CURLINE 0x0A ///< Current line +#define COLOR_HIDLINE 0x0B ///< Hidden line +#define COLOR_LUMFUNC 0x0C ///< Lumina function +#define COLOR_BG_MAX 0x0D ///< Max color number + +#define PALETTE_SIZE (COLOR_FG_MAX+COLOR_BG_MAX) +//@} + + +/// This macro is used to build colored string constants (e.g. for format strings) +/// \param str string literal to surround with color tags +/// \param tag one of SCOLOR_xxx constants +#define COLSTR(str,tag) SCOLOR_ON tag str SCOLOR_OFF tag + + +//------------------------------------------------------------------------ + +/// \defgroup color_conv Convenience functions +/// Higher level convenience functions are defined in ua.hpp. +/// Please use the following functions only if functions from ua.hpp +/// are not useful in your case. +//@{ + +/// Insert an address mark into a string. +/// \param buf pointer to the output buffer; the tag will be appended or inserted into it +/// \param ea address to include +/// \param ins if true, the tag will be inserted at the beginning of the buffer + +idaman THREAD_SAFE void ida_export tag_addr(qstring *buf, ea_t ea, bool ins=false); + + +/// Move pointer to a 'line' to 'cnt' positions right. +/// Take into account escape sequences. +/// \param line pointer to string +/// \param cnt number of positions to move right +/// \return moved pointer + +idaman THREAD_SAFE const char *ida_export tag_advance(const char *line, int cnt); + + +/// Move the pointer past all color codes. +/// \param line can't be NULL +/// \return moved pointer, can't be NULL + +idaman THREAD_SAFE const char *ida_export tag_skipcodes(const char *line); + + +/// Skip one color code. +/// This function should be used if you are interested in color codes +/// and want to analyze all of them. +/// Otherwise tag_skipcodes() function is better since it will skip all colors at once. +/// This function will skip the current color code if there is one. +/// If the current symbol is not a color code, it will return the input. +/// \return moved pointer + +idaman THREAD_SAFE const char *ida_export tag_skipcode(const char *line); + + +/// Calculate length of a colored string +/// This function computes the length in unicode codepoints of a line +/// \return the number of codepoints in the line, or -1 on error + +idaman THREAD_SAFE ssize_t ida_export tag_strlen(const char *line); + + +/// Remove color escape sequences from a string. +/// \param buf output buffer with the string, cannot be NULL. +/// \param str input string, cannot be NULL. +/// \param init_level used to verify that COLOR_ON and COLOR_OFF tags are balanced +/// \return length of resulting string, -1 if error + +idaman THREAD_SAFE ssize_t ida_export tag_remove(qstring *buf, const char *str, int init_level=0); + +inline THREAD_SAFE ssize_t idaapi tag_remove(qstring *buf, const qstring &str, int init_level=0) +{ + return tag_remove(buf, str.c_str(), init_level); +} + +inline THREAD_SAFE ssize_t idaapi tag_remove(qstring *buf, int init_level=0) +{ + if ( buf->empty() ) + return 0; + return tag_remove(buf, buf->begin(), init_level); +} + +//@} color_conv + +//@} color_def + + +/// Get prefix color for line at 'ea' +/// \return \ref COLOR_PFX +idaman color_t ida_export calc_prefix_color(ea_t ea); + +/// Get background color for line at 'ea' +/// \return RGB color +idaman bgcolor_t ida_export calc_bg_color(ea_t ea); + + +//------------------------------------------------------------------------ +// S O U R C E F I L E S +//------------------------------------------------------------------------ + +/// \name Source files +/// IDA can keep information about source files used to create the program. +/// Each source file is represented by a range of addresses. +/// A source file may contain several address ranges. +//@{ + +/// Mark a range of address as belonging to a source file. +/// An address range may belong only to one source file. +/// A source file may be represented by several address ranges. +/// \param ea1 linear address of start of the address range +/// \param ea2 linear address of end of the address range (excluded) +/// \param filename name of source file. +/// \return success + +idaman bool ida_export add_sourcefile(ea_t ea1, ea_t ea2, const char *filename); + + +/// Get name of source file occupying the given address. +/// \param ea linear address +/// \param bounds pointer to the output buffer with the address range +/// for the current file. May be NULL. +/// \return NULL if source file information is not found, +/// otherwise returns pointer to file name + +idaman const char *ida_export get_sourcefile(ea_t ea, range_t *bounds=NULL); + + +/// Delete information about the source file. +/// \param ea linear address +/// \return success + +idaman bool ida_export del_sourcefile(ea_t ea); +//@} + +//------------------------------------------------------------------------ +// G E N E R A T I O N O F D I S A S S E M B L E D T E X T +//------------------------------------------------------------------------ + +/// \name Generation of disassembled text +//@{ + +/// User-defined line-prefixes are displayed just after the autogenerated +/// line prefixes in the disassembly listing. +/// There is no need to call this function explicitly. +/// Use the user_defined_prefix_t class. +/// \param prefix_len prefixed length. if 0, then uninstall UDP +/// \param udp object to generate user-defined prefix +/// \param install true:install, false:uninstall +/// \param owner pointer to the plugin_t that owns UDP +/// if non-NULL, then the object will be uninstalled and destroyed +/// when the plugin gets unloaded +idaman bool ida_export install_user_defined_prefix( + size_t prefix_len, + struct user_defined_prefix_t *udp, + const void *owner); + +/// Class to generate user-defined prefixes in the disassembly listing. +struct user_defined_prefix_t +{ + /// Creating a user-defined prefix object installs it. + user_defined_prefix_t(size_t prefix_len, const void *owner) + { + install_user_defined_prefix(prefix_len, this, owner); + } + + /// Destroying a user-defined prefix object uninstalls it. + virtual idaapi ~user_defined_prefix_t() + { + install_user_defined_prefix(0, this, nullptr); + } + + // Get a user-defined prefix. + /// This callback must be overridden by the derived class. + /// \param out the output buffer + /// \param ea the current address + /// \param insn the current instruction. if the current item is not + /// an instruction, then insn.itype is zero. + /// \param indent see explanations for \ref gen_printf() + /// \param line the line to be generated. + /// the line usually contains color tags. + /// this argument can be examined to decide + /// whether to generate the prefix. + virtual void idaapi get_user_defined_prefix( + qstring *vout, + ea_t ea, + const class insn_t &insn, + int lnnum, + int indent, + const char *line) = 0; +}; + +//@} + +//------------------------------------------------------------------------ +// A N T E R I O R / P O S T E R I O R L I N E S +//------------------------------------------------------------------------ + +/// \name Anterior/Posterior lines +//@{ + +/// See higher level functions below + +idaman AS_PRINTF(3, 0) bool ida_export vadd_extra_line( + ea_t ea, + int vel_flags, // see VEL_... + const char *format, + va_list va); + +#define VEL_POST 0x01 // append posterior line +#define VEL_CMT 0x02 // append comment line + + +/// Add anterior/posterior non-comment line(s). +/// \param ea linear address +/// \param isprev do we add anterior lines? (0-no, posterior) +/// \param format printf() style format string. may contain \\n to denote new lines. +/// \return true if success + +AS_PRINTF(3, 4) inline bool add_extra_line(ea_t ea, bool isprev, const char *format, ...) +{ + va_list va; + va_start(va,format); + int vel_flags = (isprev ? 0 : VEL_POST); + bool ok = vadd_extra_line(ea, vel_flags, format, va); + va_end(va); + return ok; +} + + +/// Add anterior/posterior comment line(s). +/// \param ea linear address +/// \param isprev do we add anterior lines? (0-no, posterior) +/// \param format printf() style format string. may contain \\n to denote +/// new lines. The resulting string should not contain comment +/// characters (;), the kernel will add them automatically. +/// \return true if success + +AS_PRINTF(3, 4) inline bool add_extra_cmt(ea_t ea, bool isprev, const char *format, ...) +{ + va_list va; + va_start(va,format); + int vel_flags = (isprev ? 0 : VEL_POST) | VEL_CMT; + bool ok = vadd_extra_line(ea, vel_flags, format, va); + va_end(va); + return ok; +} + + +/// Add anterior comment line(s) at the start of program. +/// \param format printf() style format string. may contain \\n to denote +/// new lines. The resulting string should not contain comment +/// characters (;), the kernel will add them automatically. +/// \return true if success + +AS_PRINTF(1, 2) inline bool add_pgm_cmt(const char *format, ...) +{ + va_list va; + va_start(va,format); + bool ok = vadd_extra_line(inf_get_min_ea(), VEL_CMT, format, va); + va_end(va); + return ok; +} + +//@} + +///---------------------------------------------------------------------\cond +/// The following functions are used in kernel only: + +// Generate disassembly (many lines) and put them into a buffer +// Returns number of generated lines +idaman int ida_export generate_disassembly( + qstrvec_t *out, // buffer to hold generated lines + int *lnnum, // number of "the most interesting" line + ea_t ea, // address to generate disassembly for + int maxsize, // maximum number of lines + bool as_stack); // Display undefined items as 2/4/8 bytes + +// Generate one line of disassembly +// This function discards all "non-interesting" lines +// It is designed to generate one-line descriptions +// of addresses for lists, etc. +idaman bool ida_export generate_disasm_line( + qstring *buf, // output buffer + ea_t ea, // address to generate disassembly for + int flags=0); +#define GENDSM_FORCE_CODE (1 << 0) // generate a disassembly line as if + // there is an instruction at 'ea' +#define GENDSM_MULTI_LINE (1 << 1) // if the instruction consists of several lines, + // produce all of them (useful for parallel instructions) +#define GENDSM_REMOVE_TAGS (1 << 2) // remove tags from output buffer + +/// Get length of the line prefix that was used for the last generated line + +idaman int ida_export get_last_pfxlen(void); + + +// Get pointer to the sequence of characters denoting 'close comment' +// empty string means no comment (the current assembler has no open-comment close-comment pairs) +// This function uses ash.cmnt2 + +idaman const char *ida_export closing_comment(void); + + +// Every anterior/posterior line has its number. +// Anterior lines have numbers from E_PREV +// Posterior lines have numbers from E_NEXT + +const int E_PREV = 1000; +const int E_NEXT = 2000; + +idaman int ida_export get_first_free_extra_cmtidx(ea_t ea, int start); +idaman void ida_export update_extra_cmt(ea_t ea, int what, const char *str); +idaman void ida_export del_extra_cmt(ea_t ea, int what); +idaman ssize_t ida_export get_extra_cmt(qstring *buf, ea_t ea, int what); +idaman void ida_export delete_extra_cmts(ea_t ea, int what); + +idaman ea_t ida_export align_down_to_stack(ea_t newea); +idaman ea_t ida_export align_up_to_stack(ea_t ea1, ea_t ea2=BADADDR); + +// A helper class, to encode from UTF-8, -> into the target encoding. +// This is typically used when generating listings (or any kind of +// output file.) +struct encoder_t +{ + // whether or not a message should be printed, letting the + // user know that some text couldn't be recoded properly + enum notify_recerr_t + { + nr_none, + nr_once, + }; + + virtual ~encoder_t() {} + virtual bool idaapi get_bom(bytevec_t *out) const = 0; + // returns true if conversion was entirely successful, false otherwise. + // codepoints that couldn't be converted, will be output as C + // literal-escaped UTF-8 sequences (e.g., "\xC3\xD9"), and if + // 'nr_once' was passed at creation-time, a one-time notification + // well be output in the messages window. + virtual bool idaapi encode(qstring *s) const = 0; + // encode()s the UTF-8 string composed by format + args, and + // returns true if all the resulting bytes could be written to + // the output file. + AS_PRINTF(3, 4) virtual bool idaapi print(FILE *out, const char *format, ...) const = 0; + // should a file be opened as binary, or should it rather be opened + // in text mode? This will have an importance in how '\n' characters + // are possibly converted into '\x0A\x0D' on windows, which is most + // inappropriate when output'ing e.g., UTF-16, UTF-32.. + virtual bool idaapi requires_binary_mode() const = 0; +}; + +// Create the encoder with the given target encoding. If -1 is passed +// then the effective target encoding will be computed like so: +// if ( encidx < 0 ) +// { +// encidx = get_outfile_encoding_idx(); +// if ( encidx == STRENC_DEFAULT ) +// encidx = get_default_encoding_idx(BPU_1B); +// } +idaman encoder_t *ida_export create_encoding_helper( + int encidx=-1, + encoder_t::notify_recerr_t nr=encoder_t::nr_once); + +/// Callback functions to output lines: +//@{ +typedef int idaapi html_header_cb_t(FILE *fp); +typedef int idaapi html_footer_cb_t(FILE *fp); +typedef int idaapi html_line_cb_t( + FILE *fp, + const qstring &line, + bgcolor_t prefix_color, + bgcolor_t bg_color); +#define gen_outline_t html_line_cb_t +//@} + +///-------------------------------------------------------------------\endcond + + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED void ida_export set_user_defined_prefix( // use install_user_defined_prefix() + size_t width, + void (idaapi *get_user_defined_prefix)( + qstring *buf, + ea_t ea, + int lnnum, + int indent, + const char *line)); +#endif + +#endif diff --git a/idasdk76/include/llong.hpp b/idasdk76/include/llong.hpp new file mode 100644 index 0000000..1f08317 --- /dev/null +++ b/idasdk76/include/llong.hpp @@ -0,0 +1,293 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _LLONG_HPP +#define _LLONG_HPP + +//--------------------------------------------------------------------------- +#if defined(_MSC_VER) + +typedef unsigned __int64 ulonglong; +typedef __int64 longlong; + +#elif defined(__GNUC__) + +typedef unsigned long long ulonglong; +typedef long long longlong; + +#endif + +//--------------------------------------------------------------------------- +#ifdef __cplusplus +inline constexpr longlong make_longlong(uint32 ll,int32 hh) { return ll | (longlong(hh) << 32); } +inline constexpr ulonglong make_ulonglong(uint32 ll,int32 hh) { return ll | (ulonglong(hh) << 32); } +inline uint32 low(const ulonglong &x) { return uint32(x); } +inline uint32 high(const ulonglong &x) { return uint32(x>>32); } +inline uint32 low(const longlong &x) { return uint32(x); } +inline int32 high(const longlong &x) { return uint32(x>>32); } +#else +#define make_longlong(ll,hh) (ll | (longlong(hh) << 32)) +#define make_ulonglong(ll,hh) (ll | (ulonglong(hh) << 32)) +#endif + +idaman THREAD_SAFE longlong ida_export llong_scan( + const char *buf, + int radix, + const char **end); +#ifndef swap64 + idaman THREAD_SAFE ulonglong ida_export swap64(ulonglong); +# ifdef __cplusplus + inline longlong swap64(longlong x) + { + return longlong(swap64(ulonglong(x))); + } +# endif +#endif + +//--------------------------------------------------------------------------- +// 128 BIT NUMBERS +//--------------------------------------------------------------------------- +#ifdef __HAS_INT128__ + +typedef unsigned __int128 uint128; +typedef __int128 int128; + +inline int128 make_int128(ulonglong ll,longlong hh) { return ll | (int128(hh) << 64); } +inline uint128 make_uint128(ulonglong ll,ulonglong hh) { return ll | (uint128(hh) << 64); } +inline ulonglong low(const uint128 &x) { return ulonglong(x); } +inline ulonglong high(const uint128 &x) { return ulonglong(x>>64); } +inline ulonglong low(const int128 &x) { return ulonglong(x); } +inline longlong high(const int128 &x) { return ulonglong(x>>64); } + +#else +#ifdef __cplusplus +//-V:uint128:730 not all members of a class are initialized inside the constructor +class uint128 +{ + ulonglong l; + ulonglong h; + friend class int128; +public: + uint128(void) {} + uint128(uint x) { l = x; h = 0; } + uint128(int x) { l = x; h = (x < 0)? -1 : 0; } + uint128(ulonglong x) { l = x; h = 0; } + uint128(longlong x) { l = x; h = (x < 0) ? -1 : 0; } + uint128(ulonglong ll, ulonglong hh) { l = ll; h = hh; } + friend ulonglong low (const uint128 &x) { return x.l; } + friend ulonglong high(const uint128 &x) { return x.h; } + friend uint128 operator+(const uint128 &x, const uint128 &y); + friend uint128 operator-(const uint128 &x, const uint128 &y); + friend uint128 operator/(const uint128 &x, const uint128 &y); + friend uint128 operator%(const uint128 &x, const uint128 &y); + friend uint128 operator*(const uint128 &x, const uint128 &y); + friend uint128 operator|(const uint128 &x, const uint128 &y); + friend uint128 operator&(const uint128 &x, const uint128 &y); + friend uint128 operator^(const uint128 &x, const uint128 &y); + friend uint128 operator>>(const uint128 &x, int cnt); + friend uint128 operator<<(const uint128 &x, int cnt); + uint128 &operator+=(const uint128 &y); + uint128 &operator-=(const uint128 &y); + uint128 &operator/=(const uint128 &y); + uint128 &operator%=(const uint128 &y); + uint128 &operator*=(const uint128 &y); + uint128 &operator|=(const uint128 &y); + uint128 &operator&=(const uint128 &y); + uint128 &operator^=(const uint128 &y); + uint128 &operator>>=(int cnt); + uint128 &operator<<=(int cnt); + uint128 &operator++(void); + uint128 &operator--(void); + friend uint128 operator+(const uint128 &x) { return x; } + friend uint128 operator-(const uint128 &x); + friend uint128 operator~(const uint128 &x) { return uint128(~x.l,~x.h); } + friend int operator==(const uint128 &x, const uint128 &y) { return x.l == y.l && x.h == y.h; } + friend int operator!=(const uint128 &x, const uint128 &y) { return x.l != y.l || x.h != y.h; } + friend int operator> (const uint128 &x, const uint128 &y) { return x.h > y.h || (x.h == y.h && x.l > y.l); } + friend int operator< (const uint128 &x, const uint128 &y) { return x.h < y.h || (x.h == y.h && x.l < y.l); } + friend int operator>=(const uint128 &x, const uint128 &y) { return x.h > y.h || (x.h == y.h && x.l >= y.l); } + friend int operator<=(const uint128 &x, const uint128 &y) { return x.h < y.h || (x.h == y.h && x.l <= y.l); } +}; + +//-V:int128:730 not all members of a class are initialized inside the constructor +class int128 +{ + ulonglong l; + longlong h; + friend class uint128; +public: + int128(void) {} + int128(uint x) { l = x; h = 0; } + int128(int x) { l = x; h = (x < 0) ? -1 : 0; } + int128(ulonglong x) { l = x; h = 0; } + int128(longlong x) { l = x; h = (x < 0) ? -1 : 0; } + int128(ulonglong ll, ulonglong hh) { l=ll; h=hh; } + int128(const uint128 &x) { l=x.l; h=x.h; } + friend ulonglong low (const int128 &x) { return x.l; } + friend ulonglong high(const int128 &x) { return x.h; } + friend int128 operator+(const int128 &x, const int128 &y); + friend int128 operator-(const int128 &x, const int128 &y); + friend int128 operator/(const int128 &x, const int128 &y); + friend int128 operator%(const int128 &x, const int128 &y); + friend int128 operator*(const int128 &x, const int128 &y); + friend int128 operator|(const int128 &x, const int128 &y); + friend int128 operator&(const int128 &x, const int128 &y); + friend int128 operator^(const int128 &x, const int128 &y); + friend int128 operator>>(const int128 &x, int cnt); + friend int128 operator<<(const int128 &x, int cnt); + int128 &operator+=(const int128 &y); + int128 &operator-=(const int128 &y); + int128 &operator/=(const int128 &y); + int128 &operator%=(const int128 &y); + int128 &operator*=(const int128 &y); + int128 &operator|=(const int128 &y); + int128 &operator&=(const int128 &y); + int128 &operator^=(const int128 &y); + int128 &operator>>=(int cnt); + int128 &operator<<=(int cnt); + int128 &operator++(void); + int128 &operator--(void); + friend int128 operator+(const int128 &x) { return x; } + friend int128 operator-(const int128 &x); + friend int128 operator~(const int128 &x) { return int128(~x.l,~x.h); } + friend int operator==(const int128 &x, const int128 &y) { return x.l == y.l && x.h == y.h; } + friend int operator!=(const int128 &x, const int128 &y) { return x.l != y.l || x.h != y.h; } + friend int operator> (const int128 &x, const int128 &y) { return x.h > y.h || (x.h == y.h && x.l > y.l); } + friend int operator< (const int128 &x, const int128 &y) { return x.h < y.h || (x.h == y.h && x.l < y.l); } + friend int operator>=(const int128 &x, const int128 &y) { return x.h > y.h || (x.h == y.h && x.l >= y.l); } + friend int operator<=(const int128 &x, const int128 &y) { return x.h < y.h || (x.h == y.h && x.l <= y.l); } +}; + +inline int128 make_int128(ulonglong ll, longlong hh) { return int128(ll, hh); } +inline uint128 make_uint128(ulonglong ll, longlong hh) { return uint128(ll, hh); } +idaman THREAD_SAFE void ida_export swap128(uint128 *x); + +//--------------------------------------------------------------------------- +inline uint128 operator+(const uint128 &x, const uint128 &y) +{ + ulonglong h = x.h + y.h; + ulonglong l = x.l + y.l; + if ( l < x.l ) + h = h + 1; + return uint128(l,h); +} + +//--------------------------------------------------------------------------- +inline uint128 operator-(const uint128 &x, const uint128 &y) +{ + ulonglong h = x.h - y.h; + ulonglong l = x.l - y.l; + if ( l > x.l ) + h = h - 1; + return uint128(l,h); +} + +//--------------------------------------------------------------------------- +inline uint128 operator|(const uint128 &x, const uint128 &y) +{ + return uint128(x.l | y.l, x.h | y.h); +} + +//--------------------------------------------------------------------------- +inline uint128 operator&(const uint128 &x, const uint128 &y) +{ + return uint128(x.l & y.l, x.h & y.h); +} + +//--------------------------------------------------------------------------- +inline uint128 operator^(const uint128 &x, const uint128 &y) +{ + return uint128(x.l ^ y.l, x.h ^ y.h); +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator+=(const uint128 &y) +{ + return *this = *this + y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator-=(const uint128 &y) +{ + return *this = *this - y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator|=(const uint128 &y) +{ + return *this = *this | y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator&=(const uint128 &y) +{ + return *this = *this & y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator^=(const uint128 &y) +{ + return *this = *this ^ y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator/=(const uint128 &y) +{ + return *this = *this / y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator%=(const uint128 &y) +{ + return *this = *this % y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator*=(const uint128 &y) +{ + return *this = *this * y; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator<<=(int cnt) +{ + return *this = *this << cnt; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator>>=(int cnt) +{ + return *this = *this >> cnt; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator++(void) +{ + if ( ++l == 0 ) + ++h; + return *this; +} + +//--------------------------------------------------------------------------- +inline uint128 &uint128::operator--(void) +{ + if ( l == 0 ) + --h; + --l; + return *this; +} + +//--------------------------------------------------------------------------- +inline uint128 operator-(const uint128 &x) +{ + return ~x + 1; +} + +#endif // ifdef __cplusplus +#endif // ifdef __HAS_INT128__ + +#endif // define _LLONG_HPP diff --git a/idasdk76/include/loader.hpp b/idasdk76/include/loader.hpp new file mode 100644 index 0000000..0dbcd36 --- /dev/null +++ b/idasdk76/include/loader.hpp @@ -0,0 +1,1042 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _LOADER_HPP +#define _LOADER_HPP +#include <ida.hpp> + +/*! \file loader.hpp + + \brief Definitions of IDP, LDR, PLUGIN module interfaces + + This file also contains: + - functions to load files into the database + - functions to generate output files + - high level functions to work with the database (open, save, close) + + The LDR interface consists of one structure: loader_t \n + The IDP interface consists of one structure: processor_t \n + The PLUGIN interface consists of one structure: plugin_t + + Modules can't use standard FILE* functions. + They must use functions from <fpro.h> + + Modules can't use standard memory allocation functions. + They must use functions from <pro.h> + + The exported entry #1 in the module should point to the + the appropriate structure. (loader_t for LDR module, for example) +*/ + +//---------------------------------------------------------------------- +// DEFINITION OF LDR MODULES +//---------------------------------------------------------------------- + +class linput_t; // loader input source. see diskio.hpp for the functions +struct extlang_t; // check expr.hpp +struct plugmod_t; // idp.hpp + +/// Loader description block - must be exported from the loader module +struct loader_t +{ + uint32 version; ///< api version, should be #IDP_INTERFACE_VERSION + uint32 flags; ///< \ref LDRF_ +/// \defgroup LDRF_ Loader flags +/// Used by loader_t::flags +//@{ +#define LDRF_RELOAD 0x0001 ///< loader recognizes #NEF_RELOAD flag +#define LDRF_REQ_PROC 0x0002 ///< Requires a processor to be set. + ///< if this bit is not set, load_file() must + ///< call set_processor_type(..., SETPROC_LOADER) +//@} + + /// Check input file format. + /// This function will be called one or more times depending on the result value. + /// \param[out] fileformat name of file format + /// \param[out] processor desired processor (optional) + /// \param li input file + /// \param filename name of the input file, + /// if it is an archive member name then the actual file doesn't exist + /// \return + /// 1 if file format is recognized, and fills 'fileformatname', otherwise returns 0. + /// This function may return a unique file format number instead of 1. + /// To get this unique number, please contact the author. + /// If the return value is ORed with #ACCEPT_ARCHIVE, then + /// it is an archive loader. Its process_archive() will be called + /// instead of load_file(). + /// If the return value is ORed with #ACCEPT_CONTINUE, then + /// this function will be called another time. + /// If the return value is ORed with #ACCEPT_FIRST, then this format + /// should be placed first in the "load file" dialog box. + /// In the sorting order of file formats the archive formats have priority. + int (idaapi *accept_file)( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *filename); + +/// Specify that a file format is served by archive loader +/// See loader_t::accept_file +#define ACCEPT_ARCHIVE 0x2000 +/// Specify that the function must be called another time +/// See loader_t::accept_file +#define ACCEPT_CONTINUE 0x4000 +/// Specify that a file format should be place first in "load file" dialog box. +/// See loader_t::accept_file +#define ACCEPT_FIRST 0x8000 + + /// Load file into the database. + /// \param li input file + /// \param neflags \ref NEF_ + /// \param fileformatname name of type of the file + /// (it was returned by #accept_file) + /// + /// If this function fails, loader_failure() should be called + void (idaapi *load_file)( + linput_t *li, + ushort neflags, + const char *fileformatname); +/// \defgroup NEF_ Load file flags +/// Passed as 'neflags' parameter to loader_t::load_file +//@{ +#define NEF_SEGS 0x0001 ///< Create segments +#define NEF_RSCS 0x0002 ///< Load resources +#define NEF_NAME 0x0004 ///< Rename entries +#define NEF_MAN 0x0008 ///< Manual load +#define NEF_FILL 0x0010 ///< Fill segment gaps +#define NEF_IMPS 0x0020 ///< Create import segment +#define NEF_FIRST 0x0080 ///< This is the first file loaded + ///< into the database. +#define NEF_CODE 0x0100 ///< for load_binary_file(): + ///< load as a code segment +#define NEF_RELOAD 0x0200 ///< reload the file at the same place: + ///< - don't create segments + ///< - don't create fixup info + ///< - don't import segments + ///< - etc + ///< load only the bytes into the base. + ///< a loader should have #LDRF_RELOAD + ///< bit set +#define NEF_FLAT 0x0400 ///< Autocreate FLAT group (PE) +#define NEF_MINI 0x0800 ///< Create mini database (do not copy + ///< segment bytes from the input file; + ///< use only the file header metadata) +#define NEF_LOPT 0x1000 ///< Display additional loader options dialog +#define NEF_LALL 0x2000 ///< Load all segments without questions +//@} + + /// Create output file from the database. + /// This function may be absent. + /// If fp == NULL, then this function returns: + /// - 0: can't create file of this type + /// - 1: ok, can create file of this type + /// + /// If fp != NULL, then this function should create the output file + int (idaapi *save_file)(FILE *fp, const char *fileformatname); + + /// Take care of a moved segment (fix up relocations, for example). + /// This function may be absent. + /// A special calling method \code move_segm(BADADDR, delta, 0, formatname); \endcode + /// means that the whole program has been moved in the memory (rebased) by delta bytes + /// \param from previous linear address of the segment + /// \param to current linear address of the segment + /// \param size size of the moved segment + /// \param fileformatname the file format + /// \retval 1 ok + /// \retval 0 failure + int (idaapi *move_segm)( + ea_t from, + ea_t to, + asize_t size, + const char *fileformatname); + + /// Display list of archive members and let the user select one. + /// Extract the selected archive member into a temporary file. + /// \param[out] temp_file name of the file with the extracted archive member. + /// \param li input file + /// \param[in,out] module_name in: name of archive + /// out: name of the extracted archive member + /// \param[in,out] neflags \ref NEF_ + /// \param fileformatname name of type of the file + /// (it was returned by #accept_file) + /// \param defmember extract the specified member, + /// for example "subdir/member.exe", + /// may be NULL + /// \param errbuf error message if 0 is returned, + /// may be NULL + /// \return -1-cancelled by the user, 1-ok, 0-error, see errbuf for details + int (idaapi *process_archive)( + qstring *temp_file, + linput_t *li, + qstring *module_name, + ushort *neflags, + const char *fileformatname, + const char *defmember, + qstring *errbuf); +}; + + +/// See loader_failure() + +idaman AS_PRINTF(1, 0) NORETURN void ida_export vloader_failure(const char *format, va_list va); + + +/// Display a message about a loader failure and stop the loading process. +/// The kernel will destroy the database. +/// If format == NULL, no message will be displayed +/// This function does not return (it longjumps)! +/// It may be called only from loader_t::load_file + +AS_PRINTF(1, 2) NORETURN inline void loader_failure(const char *format=NULL, ...) +{ + va_list va; + va_start(va, format); + vloader_failure(format, va); +} + +//------------------------------------------------------------------------- +#if defined(__NT__) +# define DLLEXT "dll" +#elif defined(__LINUX__) +# define DLLEXT "so" +#elif defined(__MAC__) +# define DLLEXT "dylib" +#else +# error Unknown loader ext +#endif + +//---------------------------------------------------------------------- +/// \def{LOADER_DLL, Pattern to find loader files} +#ifdef __EA64__ +# define LOADER_DLL "*64." DLLEXT +#else +# define LOADER_DLL "*." DLLEXT +#endif + +//---------------------------------------------------------------------- +// Functions for the UI to load files +//---------------------------------------------------------------------- +/// List of loaders +struct load_info_t +{ + load_info_t *next; + qstring dllname; + qstring ftypename; + qstring processor; ///< desired processor name + filetype_t ftype; + uint32 loader_flags; ///< copy of loader_t::flags + uint32 lflags; ///< \ref LIF_ + int pri; ///< 2-archldr, 1-place first, 0-normal priority + +/// \defgroup LIF_ loader info flags +/// Used by load_info_t::lflags +//@{ +#define LIF_ARCHLDR 0x0001 ///< archive loader +//@} + + bool is_archldr(void) { return (lflags & LIF_ARCHLDR) != 0; } +}; +DECLARE_TYPE_AS_MOVABLE(load_info_t); + +/// Build list of potential loaders + +idaman load_info_t *ida_export build_loaders_list(linput_t *li, const char *filename); + + +/// Free the list of loaders + +idaman void ida_export free_loaders_list(load_info_t *list); + + +/// Get name of loader from its DLL file +/// (for example, for PE files we will get "PE"). +/// This function modifies the original string and returns a pointer into it. +/// NB: if the file extension is a registered extlang extension (e.g. py or idc) +/// the extension is retained + +idaman char *ida_export get_loader_name_from_dll(char *dllname); + + +/// Get name of loader used to load the input file into the database. +/// If no external loader was used, returns -1. +/// Otherwise copies the loader file name without the extension in the buf +/// and returns its length +/// (for example, for PE files we will get "PE"). +/// For scripted loaders, the file extension is retained. + +idaman ssize_t ida_export get_loader_name(char *buf, size_t bufsize); + + +/// Load a binary file into the database. +/// This function usually is called from ui. +/// \param filename the name of input file as is +/// (if the input file is from library, then +/// this is the name from the library) +/// \param li loader input source +/// \param _neflags \ref NEF_. For the first file, +/// the flag #NEF_FIRST must be set. +/// \param fileoff Offset in the input file +/// \param basepara Load address in paragraphs +/// \param binoff Load offset (load_address=(basepara<<4)+binoff) +/// \param nbytes Number of bytes to load from the file. +/// - 0: up to the end of the file +/// +/// If nbytes is bigger than the number of +/// bytes rest, the kernel will load as much +/// as possible +/// \retval true ok +/// \retval false failed (couldn't open the file) + +idaman bool ida_export load_binary_file( + const char *filename, + linput_t *li, + ushort _neflags, + qoff64_t fileoff, + ea_t basepara, + ea_t binoff, + uint64 nbytes); + + +/// Load a non-binary file into the database. +/// This function usually is called from ui. +/// \param filename the name of input file as is +/// (if the input file is from library, then +/// this is the name from the library) +/// \param li loader input source +/// \param sysdlldir a directory with system dlls. Pass "." if unknown. +/// \param _neflags \ref NEF_. For the first file +/// the flag #NEF_FIRST must be set. +/// \param loader pointer to ::load_info_t structure. +/// If the current IDP module has \ph{loader} != NULL +/// then this argument is ignored. +/// \return success + +idaman bool ida_export load_nonbinary_file( + const char *filename, + linput_t *li, + const char *sysdlldir, + ushort _neflags, + load_info_t *loader); + + +/// Calls loader_t::process_archive() +/// For parameters and return value description +/// look at loader_t::process_archive(). +/// Additional parameter: +/// \param loader pointer to ::load_info_t structure. + +idaman int ida_export process_archive( + qstring *temp_file, + linput_t *li, + qstring *module_name, + ushort *neflags, + const char *defmember, + const load_info_t *loader, + qstring *errbuf=NULL); + +//-------------------------------------------------------------------------- +/// Output file types +enum ofile_type_t +{ + OFILE_MAP = 0, ///< MAP file + OFILE_EXE = 1, ///< Executable file + OFILE_IDC = 2, ///< IDC file + OFILE_LST = 3, ///< Disassembly listing + OFILE_ASM = 4, ///< Assembly + OFILE_DIF = 5, ///< Difference +}; + +//------------------------------------------------------------------ +/// Generate an output file. +/// \param otype type of output file. +/// \param fp the output file handle +/// \param ea1 start address. For some file types this argument is ignored +/// \param ea2 end address. For some file types this argument is ignored +/// as usual in ida, the end address of the range is not included +/// \param flags \ref GENFLG_ +/// +/// For ::OFILE_EXE: +/// \retval 0 can't generate exe file +/// \retval 1 ok +/// +/// For other file types: +/// \return number of the generated lines. -1 if an error occurred + +idaman int ida_export gen_file(ofile_type_t otype, FILE *fp, ea_t ea1, ea_t ea2, int flags); + +/// \defgroup GENFLG_ Generate file flags +/// Passed as 'flags' parameter to gen_file() +//@{ +#define GENFLG_MAPSEG 0x0001 ///< ::OFILE_MAP: generate map of segments +#define GENFLG_MAPNAME 0x0002 ///< ::OFILE_MAP: include dummy names +#define GENFLG_MAPDMNG 0x0004 ///< ::OFILE_MAP: demangle names +#define GENFLG_MAPLOC 0x0008 ///< ::OFILE_MAP: include local names +#define GENFLG_IDCTYPE 0x0008 ///< ::OFILE_IDC: gen only information about types +#define GENFLG_ASMTYPE 0x0010 ///< ::OFILE_ASM,::OFILE_LST: gen information about types too +#define GENFLG_GENHTML 0x0020 ///< ::OFILE_ASM,::OFILE_LST: generate html (::ui_genfile_callback will be used) +#define GENFLG_ASMINC 0x0040 ///< ::OFILE_ASM,::OFILE_LST: gen information only about types +//@} + +//---------------------------------------------------------------------- +// Helper functions for the loaders & ui +//---------------------------------------------------------------------- + +/// Load portion of file into the database. +/// This function will include (ea1..ea2) into the addressing space of the +/// program (make it enabled). +/// \param li pointer of input source +/// \param pos position in the file +/// \param ea1,ea2 range of destination linear addresses +/// \param patchable should the kernel remember correspondence of +/// file offsets to linear addresses. +/// \retval 1 ok +/// \retval 0 read error, a warning is displayed +/// \note The storage type of the specified range will be changed to STT_VA. + +idaman int ida_export file2base( + linput_t *li, + qoff64_t pos, + ea_t ea1, + ea_t ea2, + int patchable); + +#define FILEREG_PATCHABLE 1 ///< means that the input file may be + ///< patched (i.e. no compression, + ///< no iterated data, etc) +#define FILEREG_NOTPATCHABLE 0 ///< the data is kept in some encoded + ///< form in the file. + + +/// Load database from the memory. +/// This function works for wide byte processors too. +/// \param memptr pointer to buffer with bytes +/// \param ea1,ea2 range of destination linear addresses +/// \param fpos position in the input file the data is taken from. +/// if == -1, then no file position correspond to the data. +/// \return 1 always +/// \note The storage type of the specified range will be changed to STT_VA. + +idaman int ida_export mem2base(const void *memptr, ea_t ea1, ea_t ea2, qoff64_t fpos); + + +/// Unload database to a binary file. +/// This function works for wide byte processors too. +/// \param fp pointer to file +/// \param pos position in the file +/// \param ea1,ea2 range of source linear addresses +/// \return 1-ok(always), write error leads to immediate exit + +idaman int ida_export base2file(FILE *fp, qoff64_t pos, ea_t ea1, ea_t ea2); + + +/// Extract a module for an archive file. +/// Parse an archive file, show the list of modules to the user, allow him to +/// select a module, extract the selected module to a file (if the extract module +/// is an archive, repeat the process). +/// This function can handle ZIP, AR, AIXAR, OMFLIB files. +/// The temporary file will be automatically deleted by IDA at the end. +/// \param[in,out] filename in: input file. +/// out: name of the selected module. +/// \param bufsize size of the buffer with 'filename' +/// \param[out] temp_file_ptr will point to the name of the file that +/// contains the extracted module +/// \param is_remote is the input file remote? +/// \retval true ok +/// \retval false something bad happened (error message has been displayed to the user) + +idaman bool ida_export extract_module_from_archive( + char *filename, + size_t bufsize, + char **temp_file_ptr, + bool is_remote); + + +/// Add long comment at \inf{min_ea}. +/// - Input file: .... +/// - File format: .... +/// +/// This function should be called only from the loader to describe the input file. + +idaman void ida_export create_filename_cmt(void); + + +/// Get the input file type. +/// This function can recognize libraries and zip files. + +idaman filetype_t ida_export get_basic_file_type(linput_t *li); + + +/// Get name of the current file type. +/// The current file type is kept in \inf{filetype}. +/// \param buf buffer for the file type name +/// \param bufsize its size +/// \return size of answer, this function always succeeds + +idaman size_t ida_export get_file_type_name(char *buf, size_t bufsize); + + +//---------------------------------------------------------------------- +// Work with IDS files: read and use information from them +// + +/// See ::importer_t +struct impinfo_t +{ + const char *dllname; + void (idaapi*func)(uval_t num, const char *name, uval_t node); + uval_t node; +}; + + +/// Callback for checking dll module - passed to import_module(). +/// \param li pointer to input file +/// \param ii import info. +/// If the function finds that ii.dllname does not match +/// the module name passed to import_module(), it returns 0. \n +/// Otherwise it calls ii.func for each exported entry. \n +/// If ii.dllname==NULL then ii.func will be called +/// with num==0 and name==dllname. +/// \retval 0 dllname doesn't match, import_module() should continue +/// \retval 1 ok + +typedef int idaapi importer_t(linput_t *li, impinfo_t *ii); + + +/// Find and import a DLL module. +/// This function adds information to the database (renames functions, etc). +/// \param module name of DLL +/// \param windir system directory with dlls +/// \param modnode node with information about imported entries. +/// either altval or supval arrays may be absent. +/// the node should never be deleted. +/// - imports by ordinals: +/// altval(ord) contains linear address +/// - imports by name: +/// supval(ea) contains the imported name +/// \param importer callback function (may be NULL) to check dll module +/// \param ostype type of operating system (subdir name). +/// NULL means the IDS directory itself (not recommended) + +idaman void ida_export import_module( + const char *module, + const char *windir, + uval_t modnode, + importer_t *importer, + const char *ostype); + + +/// Load and apply IDS file. +/// This function loads the specified IDS file and applies it to the database. +/// If the program imports functions from a module with the same name +/// as the name of the ids file being loaded, then only functions from this +/// module will be affected. Otherwise (i.e. when the program does not import +/// a module with this name) any function in the program may be affected. +/// \param fname name of file to apply +/// \retval 1 ok +/// \retval 0 some error (a message is displayed). +/// if the ids file does not exist, no message is displayed + +idaman int ida_export load_ids_module(char *fname); + + +//---------------------------------------------------------------------- +// DEFINITION OF PLUGIN MODULES +//---------------------------------------------------------------------- +/// A plugin is a module in the plugins subdirectory that can perform +/// an action asked by the user. (usually via pressing a hotkey) +class plugin_t +{ +public: + int version; ///< Should be equal to #IDP_INTERFACE_VERSION + int flags; ///< \ref PLUGIN_ +/// \defgroup PLUGIN_ Plugin features +/// Used by plugin_t::flags +//@{ +#define PLUGIN_MOD 0x0001 ///< Plugin changes the database. + ///< IDA won't call the plugin if + ///< the processor module prohibited any changes. +#define PLUGIN_DRAW 0x0002 ///< IDA should redraw everything after calling the plugin. +#define PLUGIN_SEG 0x0004 ///< Plugin may be applied only if the current address belongs to a segment +#define PLUGIN_UNL 0x0008 ///< Unload the plugin immediately after calling 'run'. + ///< This flag may be set anytime. + ///< The kernel checks it after each call to 'run' + ///< The main purpose of this flag is to ease + ///< the debugging of new plugins. +#define PLUGIN_HIDE 0x0010 ///< Plugin should not appear in the Edit, Plugins menu. + ///< This flag is checked at the start. +#define PLUGIN_DBG 0x0020 ///< A debugger plugin. init() should put + ///< the address of ::debugger_t to dbg. +#define PLUGIN_PROC 0x0040 ///< Load plugin when a processor module is loaded. (and keep it + ///< until the processor module is unloaded) +#define PLUGIN_FIX 0x0080 ///< Load plugin when IDA starts and keep it in the memory until IDA stops +#define PLUGIN_MULTI 0x0100 ///< The plugin can work with multiple idbs in parallel. + ///< init() returns a pointer to a plugmod_t object + ///< run/term functions are not used. + ///< Virtual functions of plugmod_t are used instead. +#define PLUGIN_SCRIPTED 0x8000 ///< Scripted plugin. Should not be used by plugins, + ///< the kernel sets it automatically. +//@} + + plugmod_t *(idaapi *init)(void); ///< Initialize plugin - returns a pointer to plugmod_t +#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_PLUGIN_RETURN_CODES__) +/// \defgroup PLUGIN_INIT Plugin initialization codes +/// Return values for plugin_t::init() +/// Deprecated, please update your plugins to use PLUGIN_MULTI. +//@{ +#define PLUGIN_SKIP nullptr ///< Plugin doesn't want to be loaded +#define PLUGIN_OK ((plugmod_t *)1) ///< Plugin agrees to work with the current database. + ///< It will be loaded as soon as the user presses the hotkey +#define PLUGIN_KEEP ((plugmod_t *)2) ///< Plugin agrees to work with the current database and wants to stay in the memory +//@} +#endif + + void (idaapi *term)(void); ///< Terminate plugin. This function will be called + ///< when the plugin is unloaded. May be NULL. + ///< Must be NULL for PLUGIN_MULTI plugins + bool (idaapi *run)(size_t arg); ///< Invoke plugin. + ///< Must be NULL for PLUGIN_MULTI plugins + const char *comment; ///< Long comment about the plugin. + ///< it could appear in the status line + ///< or as a hint + const char *help; ///< Multiline help about the plugin + const char *wanted_name; ///< The preferred short name of the plugin + const char *wanted_hotkey; ///< The preferred hotkey to run the plugin +}; + +#ifndef __X86__ + CASSERT(sizeof(plugin_t) == 64); +#else + CASSERT(sizeof(plugin_t) == 36); +#endif + +#if !defined(__KERNEL__) && !defined(PLUGIN_SUBMODULE) +idaman ida_module_data plugin_t PLUGIN; // (declaration for plugins) +#endif + +/// Get plugin options from the command line. +/// If the user has specified the options in the -Oplugin_name:options +/// format, them this function will return the 'options' part of it +/// The 'plugin' parameter should denote the plugin name +/// Returns NULL if there we no options specified + +idaman const char *ida_export get_plugin_options(const char *plugin); + + +//-------------------------------------------------------------------------- +/// Pattern to find plugin files +#ifdef __EA64__ +# define PLUGIN_DLL "*64." DLLEXT +#else +# define PLUGIN_DLL "*." DLLEXT +#endif + + +// LOW LEVEL DLL LOADING FUNCTIONS +// Only the kernel should use these functions! +/// \cond +#define LNE_MAXSEG 10 // Max number of segments + +#if 0 +extern char dlldata[4096]; // Reserved place for DLL data +#define DLLDATASTART 0xA0 // Absolute offset of dlldata +extern char ldrdata[64]; // Reserved place for LOADER data +#define LDRDATASTART (DLLDATASTART+sizeof(dlldata)) // Absolute offset of ldrdata +#endif + +struct idadll_t +{ + void *dllinfo[LNE_MAXSEG]; + void *entry; // first entry point of DLL + idadll_t(void) { dllinfo[0] = NULL; entry = NULL; } + bool is_loaded(void) const { return dllinfo[0] != NULL; } +}; + +#define MODULE_ENTRY_LOADER "LDSC" +#define MODULE_ENTRY_PLUGIN "PLUGIN" +#define MODULE_ENTRY_IDP "LPH" + +int _load_core_module( + idadll_t *dllmem, + const char *file, + const char *entry); + // dllmem - allocated segments + // dos: segment 1 (data) isn't allocated + // Returns 0 - ok, else: +#define RE_NOFILE 1 /* No such file */ +#define RE_NOTIDP 2 /* Not IDP file */ +#define RE_NOPAGE 3 /* Can't load: bad segments */ +#define RE_NOLINK 4 /* No linkage info */ +#define RE_BADRTP 5 /* Bad relocation type */ +#define RE_BADORD 6 /* Bad imported ordinal */ +#define RE_BADATP 7 /* Bad relocation atype */ +#define RE_BADMAP 8 /* DLLDATA offset is invalid */ + +void load_core_module_or_die( + idadll_t *dllmem, + const char *file, + const char *entry); +idaman bool ida_export load_core_module( + idadll_t *dllmem, + const char *file, + const char *entry); + +idaman void ida_export free_dll(idadll_t *dllmem); +/// \endcond + +/// Processor name +struct idp_name_t +{ + qstring lname; ///< long processor name + qstring sname; ///< short processor name + bool hidden; ///< is hidden + idp_name_t() : hidden(false) {} +}; +DECLARE_TYPE_AS_MOVABLE(idp_name_t); +typedef qvector<idp_name_t> idp_names_t; ///< vector of processor names + +/// Processor module description +struct idp_desc_t +{ + qstring path; ///< module file name + time_t mtime; ///< time of last modification + qstring family; ///< processor's family + idp_names_t names; ///< processor names + bool is_script; ///< the processor module is a script + bool checked; ///< internal, for cache management + idp_desc_t(): mtime(time_t(-1)), is_script(false), checked(false) {} +}; +DECLARE_TYPE_AS_MOVABLE(idp_desc_t); +typedef qvector<idp_desc_t> idp_descs_t; ///< vector of processor module descriptions + + +/// Get IDA processor modules descriptions + +idaman const idp_descs_t *ida_export get_idp_descs(void); + + +//-------------------------------------------------------------------------- +/// \def{IDP_DLL, Pattern to find idp files} +#ifdef __EA64__ +# define IDP_DLL "*64." DLLEXT +#else +# define IDP_DLL "*." DLLEXT +#endif + + +//-------------------------------------------------------------------------- +/// Structure to store Plugin information +struct plugin_info_t +{ + plugin_info_t *next; ///< next plugin information + char *path; ///< full path to the plugin + char *org_name; ///< original short name of the plugin + char *name; ///< short name of the plugin + ///< it will appear in the menu + ushort org_hotkey; ///< original hotkey to run the plugin + ushort hotkey; ///< current hotkey to run the plugin + size_t arg; ///< argument used to call the plugin + plugin_t *entry; ///< pointer to the plugin if it is already loaded + idadll_t dllmem; + int flags; ///< a copy of plugin_t::flags + char *comment; ///< a copy of plugin_t::comment +}; + + +/// Get pointer to the list of plugins. (some plugins might be listed several times +/// in the list - once for each configured argument) + +idaman plugin_info_t *ida_export get_plugins(void); + + +/// Find a user-defined plugin and optionally load it. +/// \param name short plugin name without path and extension, +/// or absolute path to the file name +/// \param load_if_needed if the plugin is not present in the memory, try to load it +/// \return pointer to plugin description block + +idaman plugin_t *ida_export find_plugin(const char *name, bool load_if_needed=false); + +inline plugin_t *load_plugin(const char *name) +{ + return find_plugin(name, true); +} + + +/// Run a loaded plugin with the specified argument. +/// \param ptr pointer to plugin description block +/// \param arg argument to run with + +idaman bool ida_export run_plugin(const plugin_t *ptr, size_t arg); + + +/// Load & run a plugin + +inline bool idaapi load_and_run_plugin(const char *name, size_t arg) +{ + return run_plugin(load_plugin(name), arg); +} + + +/// Run a plugin as configured. +/// \param ptr pointer to plugin information block + +idaman bool ida_export invoke_plugin(plugin_info_t *ptr); + + +/// Information for the user interface about available debuggers +struct dbg_info_t +{ + plugin_info_t *pi; + struct debugger_t *dbg; + dbg_info_t(plugin_info_t *_pi, struct debugger_t *_dbg) : pi(_pi), dbg(_dbg) {} +}; +DECLARE_TYPE_AS_MOVABLE(dbg_info_t); + + +/// Get information about available debuggers + +idaman size_t ida_export get_debugger_plugins(const dbg_info_t **array); + + +/// Initialize plugins with the specified flag + +idaman void ida_export init_plugins(int flag); + + +/// Terminate plugins with the specified flag + +idaman void ida_export term_plugins(int flag); + + +//------------------------------------------------------------------------ + +/// Get offset in the input file which corresponds to the given ea. +/// If the specified ea can't be mapped into the input file offset, +/// return -1. + +idaman qoff64_t ida_export get_fileregion_offset(ea_t ea); + + +/// Get linear address which corresponds to the specified input file offset. +/// If can't be found, return #BADADDR + +idaman ea_t ida_export get_fileregion_ea(qoff64_t offset); + + +//------------------------------------------------------------------------ +/// Generate an exe file (unload the database in binary form). +/// \return fp the output file handle. if fp == NULL then return: +/// - 1: can generate an executable file +/// - 0: can't generate an executable file +/// \retval 1 ok +/// \retval 0 failed + +idaman int ida_export gen_exe_file(FILE *fp); + + +//------------------------------------------------------------------------ +/// Reload the input file. +/// This function reloads the byte values from the input file. +/// It doesn't modify the segmentation, names, comments, etc. +/// \param file name of the input file. if file == NULL then returns: +/// - 1: can reload the input file +/// - 0: can't reload the input file +/// \param is_remote is the file located on a remote computer with +/// the debugger server? +/// \return success + +idaman bool ida_export reload_file(const char *file, bool is_remote); + + +//--------------------------------------------------------------------------- +// S N A P S H O T F U N C T I O N S + +/// Maximum database snapshot description length +#define MAX_DATABASE_DESCRIPTION 128 + +class snapshot_t; +typedef qvector<snapshot_t *> snapshots_t; ///< vector of database snapshots + +/// Snapshot attributes +class snapshot_t +{ +private: + snapshot_t &operator=(const snapshot_t &); + snapshot_t(const snapshot_t &); + + int compare(const snapshot_t &r) const + { + return ::compare(id, r.id); + } + +public: + qtime64_t id; ///< snapshot ID. This value is computed using qgettimeofday() + uint16 flags; ///< \ref SSF_ +/// \defgroup SSF_ Snapshot flags +/// Used by snapshot_t::flags +//@{ +#define SSF_AUTOMATIC 0x0001 ///< automatic snapshot +//@} + char desc[MAX_DATABASE_DESCRIPTION]; ///< snapshot description + char filename[QMAXPATH]; ///< snapshot file name + snapshots_t children; ///< snapshot children + DEFINE_MEMORY_ALLOCATION_FUNCS() + DECLARE_COMPARISON_OPERATORS(snapshot_t) + void clear() + { + for ( snapshots_t::iterator p=children.begin(); + p != children.end(); + ++p ) + { + delete *p; + } + children.clear(); + } + + snapshot_t(): id(0), flags(0) + { + filename[0] = desc[0] = '\0'; + } + + ~snapshot_t() + { + clear(); + } +}; +DECLARE_TYPE_AS_MOVABLE(snapshot_t); + +//------------------------------------------------------------------------ +/// Build the snapshot tree. +/// \param root snapshot root that will contain the snapshot tree elements. +/// \return success + +idaman bool ida_export build_snapshot_tree(snapshot_t *root); + + +//------------------------------------------------------------------------ +/// Update the snapshot attributes. +/// \note only the snapshot description can be updated. +/// \param filename snapshot file name or NULL for the current database +/// \param root snapshot root (returned from build_snapshot_tree()) +/// \param attr snapshot instance containing the updated attributes +/// \param uf \ref SSUF_ +/// \return success +idaman bool ida_export update_snapshot_attributes( + const char *filename, + const snapshot_t *root, + const snapshot_t *attr, + int uf); + +/// \defgroup SSUF_ Snapshot update flags +/// Passed as 'uf' parameter to update_snapshot_attributes() +//@{ +#define SSUF_DESC 0x00000001 ///< Update the description +#define SSUF_PATH 0x00000002 ///< Update the path +#define SSUF_FLAGS 0x00000004 ///< Update the flags +//@} + +//------------------------------------------------------------------------ +/// Visit the snapshot tree. +/// \param root snapshot root to start the enumeration from +/// \param callback callback called for each child. return 0 to continue enumeration +/// and non-zero to abort enumeration +/// \param ud user data. will be passed back to the callback +/// \return true-ok, false-failed + +idaman int ida_export visit_snapshot_tree( + snapshot_t *root, + int (idaapi *callback)(snapshot_t *ss, void *ud), + void *ud=NULL); + + +/// Flush buffers to the disk + +idaman int ida_export flush_buffers(void); + + +/// Is the database considered as trusted? + +idaman bool ida_export is_trusted_idb(void); + +//------------------------------------------------------------------------ +/// Save current database using a new file name. +/// \param outfile output database file name +/// \param flags \ref DBFL_ +/// \param root optional: snapshot tree root. +/// \param attr optional: snapshot attributes +/// \note when both root and attr are not NULL then the snapshot +/// attributes will be updated, otherwise the snapshot attributes +/// will be inherited from the current database. +/// \return success + +idaman bool ida_export save_database( + const char *outfile, + uint32 flags, + const snapshot_t *root = NULL, + const snapshot_t *attr = NULL); + +/// \defgroup DBFL_ Database flags +/// Used to manage saving/closing of a database +//@{ +#define DBFL_KILL 0x01 ///< delete unpacked database +#define DBFL_COMP 0x02 ///< collect garbage +#define DBFL_BAK 0x04 ///< create backup file (if !DBFL_KILL) +#define DBFL_TEMP 0x08 ///< temporary database +//@} + +/// Get the current database flag +/// \param dbfl flag \ref DBFL_ +/// \returns the state of the flag (set or cleared) + +idaman bool ida_export is_database_flag(uint32 dbfl); + +/// Set or clear database flag +/// \param dbfl flag \ref DBFL_ +/// \param cnd set if true or clear flag otherwise + +idaman void ida_export set_database_flag(uint32 dbfl, bool cnd=true); +inline void clr_database_flag(uint32 dbfl) { set_database_flag(dbfl, false); } + +/// Is a temporary database? +inline bool is_temp_database(void) { return is_database_flag(DBFL_TEMP); } + + +//------------------------------------------------------------------------ +/// \defgroup PATH_TYPE_ Types of the file pathes +//@{ +enum path_type_t +{ + PATH_TYPE_CMD, ///< full path to the file specified in the command line + PATH_TYPE_IDB, ///< full path of IDB file + PATH_TYPE_ID0, ///< full path of ID0 file +}; +//@} + +/// Get the file path +/// \param pt file path type \ref PATH_TYPE_ +/// \returns file path, never returns NULL +idaman const char *ida_export get_path(path_type_t pt); + +/// Set the file path +/// \param pt file path type \ref PATH_TYPE_ +/// \param path new file path, +/// use NULL or empty string to clear the file path +idaman void ida_export set_path(path_type_t pt, const char *path); + + +/// Check the file extension +/// \returns true if it is the reserved extension +idaman bool ida_export is_database_ext(const char *ext); + + +/// Get the value of the ELF_DEBUG_FILE_DIRECTORY configuration +/// directive. +idaman const char *ida_export get_elf_debug_file_directory(); + +/// \cond + +#endif diff --git a/idasdk75/include/md5.h b/idasdk76/include/md5.h similarity index 100% rename from idasdk75/include/md5.h rename to idasdk76/include/md5.h diff --git a/idasdk76/include/moves.hpp b/idasdk76/include/moves.hpp new file mode 100644 index 0000000..95065f3 --- /dev/null +++ b/idasdk76/include/moves.hpp @@ -0,0 +1,391 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __MOVES_HPP +#define __MOVES_HPP + +#include <dirtree.hpp> + +//------------------------------------------------------------------------- +struct graph_location_info_t +{ + double zoom; // zoom level, 1.0 == 100%, 0 means auto position + double orgx; // graph origin, x coord + double orgy; // graph origin, y coord + graph_location_info_t(void) : zoom(0), orgx(0), orgy(0) {} + bool operator == (const graph_location_info_t &r) const + { return zoom == r.zoom && orgx == r.orgx && orgy == r.orgy; } //-V550 An odd precise comparison: zoom == r.zoom + bool operator != (const graph_location_info_t &r) const + { return !(*this == r); } + void serialize(bytevec_t *out) const; + bool deserialize(memory_deserializer_t &mmdsr); +}; + +//------------------------------------------------------------------------- +inline void graph_location_info_t::serialize(bytevec_t *out) const +{ + CASSERT(sizeof(graph_location_info_t) == 3*8); + out->append(this, sizeof(graph_location_info_t)); +} + +//------------------------------------------------------------------------- +inline bool graph_location_info_t::deserialize(memory_deserializer_t &mmdsr) +{ + return mmdsr.unpack_obj(this, sizeof(graph_location_info_t)) != NULL; +} + +//------------------------------------------------------------------------- +struct segm_move_info_t +{ + segm_move_info_t(ea_t _from = 0, ea_t _to = 0, size_t _sz = 0) + : from(_from), to(_to), size(_sz) {} + ea_t from, to; + size_t size; + + bool operator == (const segm_move_info_t &r) const + { return from == r.from && to == r.to && size == r.size; } + bool operator != (const segm_move_info_t &r) const + { return !(*this == r); } +}; +DECLARE_TYPE_AS_MOVABLE(segm_move_info_t); +typedef qvector<segm_move_info_t> segm_move_info_vec_t; + +struct segm_move_infos_t : public segm_move_info_vec_t +{ + const segm_move_info_t *find(ea_t ea) const + { + for ( size_t i = 0; i < size(); ++i ) + { + const segm_move_info_t &cur = at(i); + if ( ea >= cur.from && ea < cur.from + cur.size ) + return &cur; + } + return NULL; + } +}; + +//------------------------------------------------------------------------- +class place_t; + +//------------------------------------------------------------------------- +struct renderer_info_pos_t // out of renderer_info_t, to enable SWiG parsing +{ + int node; + short cx; + short cy; + + renderer_info_pos_t() : node(-1), cx(-1), cy(-1) {} + bool operator == (const renderer_info_pos_t &r) const + { return node == r.node && cx == r.cx && cy == r.cy; } + bool operator != (const renderer_info_pos_t &r) const + { return !(*this == r); } + void serialize(bytevec_t *out) const; + bool deserialize(memory_deserializer_t &mmdsr); +}; + +//------------------------------------------------------------------------- +inline void renderer_info_pos_t::serialize(bytevec_t *out) const +{ + out->pack_dd(node); + out->pack_dw(cx); + out->pack_dw(cy); +} + +//------------------------------------------------------------------------- +inline bool renderer_info_pos_t::deserialize(memory_deserializer_t &mmdsr) +{ + node = mmdsr.unpack_dd(); + cx = mmdsr.unpack_dw(); + if ( mmdsr.empty() ) + return false; + cy = mmdsr.unpack_dw(); + return true; +} + +//------------------------------------------------------------------------- +struct renderer_info_t +{ + graph_location_info_t gli; + typedef renderer_info_pos_t pos_t; + pos_t pos; + tcc_renderer_type_t rtype = TCCRT_INVALID; + + bool operator == (const renderer_info_t &r) const + { return rtype == r.rtype && pos == r.pos && gli == r.gli; } + bool operator != (const renderer_info_t &r) const + { return !(*this == r); } +}; + + +//------------------------------------------------------------------------- +class lochist_t; +struct lochist_entry_t; +struct expanded_area_t; + +#define LSEF_PLACE (1 << 0) +#define LSEF_RINFO (1 << 1) +#define LSEF_PTYPE (1 << 2) +#define LSEF_ALL (LSEF_PLACE|LSEF_RINFO|LSEF_PTYPE) + +#ifndef SWIG +#define DEFINE_LOCHIST_T_HELPERS(decl) \ + decl void ida_export lochist_t_register_live(lochist_t &); \ + decl void ida_export lochist_t_deregister_live(lochist_t &); \ + decl bool ida_export lochist_t_init (lochist_t &, const char *, const place_t &, void *, uint32); \ + decl void ida_export lochist_t_jump (lochist_t &, bool try_to_unhide, const lochist_entry_t &e); \ + decl bool ida_export lochist_t_fwd (lochist_t &, uint32 cnt, bool try_to_unhide); \ + decl bool ida_export lochist_t_back (lochist_t &, uint32 cnt, bool try_to_unhide); \ + decl bool ida_export lochist_t_seek (lochist_t &, uint32 index, bool try_to_unhide, bool apply_cur); \ + decl const lochist_entry_t *ida_export lochist_t_get_current(const lochist_t &); \ + decl uint32 ida_export lochist_t_current_index(const lochist_t &); \ + decl void ida_export lochist_t_set (lochist_t &, uint32, const lochist_entry_t &); \ + decl bool ida_export lochist_t_get (lochist_entry_t *, const lochist_t &, uint32); \ + decl uint32 ida_export lochist_t_size (const lochist_t &);\ + decl void ida_export lochist_t_save (const lochist_t &); \ + decl void ida_export lochist_t_clear (lochist_t &); +#else +#define DEFINE_LOCHIST_T_HELPERS(decl) +#endif // SWIG +DEFINE_LOCHIST_T_HELPERS(idaman) + +#ifndef SWIG +#define DEFINE_LOCHIST_ENTRY_T_HELPERS(decl) \ + decl void ida_export lochist_entry_t_serialize(bytevec_t *, const lochist_entry_t &); \ + decl bool ida_export lochist_entry_t_deserialize(lochist_entry_t *, const uchar **, const uchar *const, const place_t *); +#else +#define DEFINE_LOCHIST_ENTRY_T_HELPERS(decl) +#endif // SWIG +DEFINE_LOCHIST_ENTRY_T_HELPERS(idaman) + +//------------------------------------------------------------------------- +struct lochist_entry_t +{ + renderer_info_t rinfo; + place_t *plce; + + lochist_entry_t() : plce(NULL) {} + lochist_entry_t(const place_t *p, const renderer_info_t &r) + : rinfo(r), plce((place_t *) p) + { + if ( plce != NULL ) + plce = plce->clone(); + } +#ifndef SWIG + lochist_entry_t(const lochist_t &s); +#endif // SWIG + lochist_entry_t(const lochist_entry_t &other) : plce(NULL) { *this = other; } + ~lochist_entry_t() { clear(); } + const renderer_info_t &renderer_info() const { return rinfo; } + const place_t *place() const { return plce; } + + renderer_info_t &renderer_info() { return rinfo; } + place_t *place() { return plce; } + + void set_place(const place_t *p) { clear(); if ( p != NULL ) plce = p->clone(); } + void set_place(const place_t &p) { set_place(&p); } + + bool is_valid() const { return plce != NULL; } + + lochist_entry_t &operator=(const lochist_entry_t &r) + { + clear(); + (*this).rinfo = r.rinfo; + if ( r.plce != NULL ) + plce = r.plce->clone(); + return *this; + } + + void acquire_place(place_t *in_p) + { clear(); plce = in_p; } + + void serialize(bytevec_t *out) const { lochist_entry_t_serialize(out, *this); } + bool deserialize(const uchar **ptr, const uchar *const end, const place_t *tmplate) + { return lochist_entry_t_deserialize(this, ptr, end, tmplate); } + +private: + void clear() + { + if ( plce != NULL ) + qfree(plce); + plce = NULL; + } + + friend class lochist_t; + DEFINE_LOCHIST_T_HELPERS(friend) + DEFINE_LOCHIST_ENTRY_T_HELPERS(friend) +}; +DECLARE_TYPE_AS_MOVABLE(lochist_entry_t); +typedef qvector<lochist_entry_t> lochist_entry_vec_t; + +#define UNHID_SEGM 0x0001 // unhid a segment at 'target' +#define UNHID_FUNC 0x0002 // unhid a function at 'target' +#define UNHID_RANGE 0x0004 // unhid an range at 'target' + +#define DEFAULT_CURSOR_Y 0xFFFF +#define DEFAULT_LNNUM -1 +#define CURLOC_LIST "$ curlocs" +#define MAX_MARK_SLOT 1024 // Max number of marked locations + +//------------------------------------------------------------------------- +class lochist_t +{ + void *ud; + + DEFINE_LOCHIST_T_HELPERS(friend) + + lochist_entry_t cur; + netnode node; + +#define LHF_HISTORY_DISABLED (1 << 0) // enable history? + uint32 flags; + +public: + lochist_t() : flags(0) { lochist_t_register_live(*this); } + ~lochist_t() { lochist_t_deregister_live(*this); } + bool is_history_enabled() const { return (flags & LHF_HISTORY_DISABLED) == 0; } + int get_place_id() const + { + const place_t *p = cur.place(); + return p == NULL ? -1 : p->id(); + } + bool init(const char *stream_name, const place_t *_defpos, void *_ud, uint32 _flags) + { return lochist_t_init(*this, stream_name, *_defpos, _ud, _flags); } + + nodeidx_t netcode() const + { return node; } + + void jump(bool try_to_unhide, const lochist_entry_t &e) + { lochist_t_jump(*this, try_to_unhide, e); } + + uint32 current_index() const + { return lochist_t_current_index(*this); } + + bool seek(uint32 index, bool try_to_unhide) + { return lochist_t_seek(*this, index, try_to_unhide, true); } + + bool fwd(uint32 cnt, bool try_to_unhide) + { return lochist_t_fwd(*this, cnt, try_to_unhide); } + + bool back(uint32 cnt, bool try_to_unhide) + { return lochist_t_back(*this, cnt, try_to_unhide); } + + void save() const + { lochist_t_save(*this); } + + void clear() + { lochist_t_clear(*this); } + + const lochist_entry_t &get_current() const + { return *lochist_t_get_current(*this); } + + void set_current(const lochist_entry_t &e) + { return set(current_index(), e); } + + void set(uint32 index, const lochist_entry_t &e) + { lochist_t_set(*this, index, e); } + + bool get(lochist_entry_t *out, uint32 index) const + { return lochist_t_get(out, *this, index); } + + uint32 size(void) const + { return lochist_t_size(*this); } + + const place_t *get_template_place() const + { return cur.place(); } +}; +DECLARE_TYPE_AS_MOVABLE(lochist_t); + +//------------------------------------------------------------------------- +#ifndef SWIG +idaman uint32 ida_export bookmarks_t_mark(const lochist_entry_t &, uint32, const char *, const char *, void *); +idaman bool ida_export bookmarks_t_get(lochist_entry_t *, qstring *, uint32 *, void *); +idaman bool ida_export bookmarks_t_get_desc(qstring *, const lochist_entry_t &, uint32, void *); +idaman bool ida_export bookmarks_t_set_desc(qstring, const lochist_entry_t &, uint32, void *); +idaman uint32 ida_export bookmarks_t_find_index(const lochist_entry_t &, void *); +idaman uint32 ida_export bookmarks_t_size(const lochist_entry_t &, void *); +idaman bool ida_export bookmarks_t_erase(const lochist_entry_t &, uint32, void *); +idaman dirtree_id_t ida_export bookmarks_t_get_dirtree_id(const lochist_entry_t &, void *); +#endif // SWIG + +//------------------------------------------------------------------------- +class bookmarks_t +{ + bookmarks_t(); // No. + ~bookmarks_t() {} +public: +#define BOOKMARKS_CHOOSE_INDEX (uint32(-1)) +#define BOOKMARKS_BAD_INDEX (uint32(-1)) +#define BOOKMARKS_PROMPT_WITH_HINT_PREFIX '\x01' + + // Mark/unmark position + // index - the marked position number (0..MAX_MARK_SLOT) + // if specified as BOOKMARKS_CHOOSE_INDEX: ask the user to select the mark slot. + // title - if index == BOOKMARKS_CHOOSE_INDEX, then the window caption of + // the dialog which will appear on the screen. title==NULL will + // lead to the default caption: "please select a mark slot" + // desc - description of the marked position. If NULL, IDA will show a + // dialog box asking the user to enter the description. + // If non-NULL but starts with BOOKMARKS_PROMPT_WITH_HINT_PREFIX, + // IDA will also prompt the user, but with a pre-filled value + // starting at &desc[1]. + // returns used marker number (BOOKMARKS_BAD_INDEX - none) + static uint32 mark( + const lochist_entry_t &e, + uint32 index, + const char *title, + const char *desc, + void *ud) + { return bookmarks_t_mark(e, index, title, desc, ud); } + + // 'out_entry' MUST: + // - contain a valid place_t*; data will be deserialized into it + // - have a valid, corresponding tcc_place_type_t + static bool get( + lochist_entry_t *out_entry, + qstring *out_desc, + uint32 *index, // index==BOOKMARKS_CHOOSE_INDEX? let the user choose + void *ud) + { return bookmarks_t_get(out_entry, out_desc, index, ud); } + + static bool get_desc( + qstring *out, + const lochist_entry_t &e, + uint32 index, + void *ud) + { return bookmarks_t_get_desc(out, e, index, ud); } + + static uint32 find_index( + const lochist_entry_t &e, + void *ud) + { return bookmarks_t_find_index(e, ud); } + + static uint32 size( + const lochist_entry_t &e, + void *ud) + { return bookmarks_t_size(e, ud); } + + static bool erase( + const lochist_entry_t &e, + uint32 index, + void *ud) + { return bookmarks_t_erase(e, index, ud); } + + static dirtree_id_t get_dirtree_id( + const lochist_entry_t &e, + void *ud) + { return bookmarks_t_get_dirtree_id(e, ud); } +}; + +//------------------------------------------------------------------------- +inline lochist_entry_t::lochist_entry_t(const lochist_t &lh) + : plce(NULL) +{ + *this = lh.get_current(); +} + + +#endif // __MOVES_HPP diff --git a/idasdk76/include/nalt.hpp b/idasdk76/include/nalt.hpp new file mode 100644 index 0000000..1701b71 --- /dev/null +++ b/idasdk76/include/nalt.hpp @@ -0,0 +1,1705 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef NALT_HPP +#define NALT_HPP + +#include <ida.hpp> +#include <netnode.hpp> + +/*! \file nalt.hpp + + \brief Definitions of various information kept in netnodes + + Each address in the program has a corresponding netnode: netnode(ea). + + If we have no information about an address, the corresponding + netnode is not created. + Otherwise we will create a netnode and save information in it. + All variable length information (names, comments, offset information, etc) + is stored in the netnode. + + Don't forget that some information is already stored in the flags (bytes.hpp) + + \warning + Many of the functions in this file are very low level (they are marked + as low level functions). Use them only if you can't find higher level + function to set/get/del information. + + You can create your own nodes in IDP module and store information + in them. See ::netnode. +*/ + +/// \defgroup NALT_ Structure of altvals array +/// Structure of altvals array of netnode(ea). +/// altvals is a virtual array of 32-bit longs attached to a netnode. +/// the size of this array is unlimited. Unused indexes are not kept in the +/// database. We use only first several indexes to this array. +//@{ +#define NALT_ENUM uval_t(-2) ///< reserved for enums, see enum.hpp +#define NALT_WIDE uval_t(-1) ///< 16-bit byte value +#define NALT_SWITCH 1 ///< switch idiom address (used at jump targets) +//#define NALT_OBASE1 2 // offset base 2 +#define NALT_STRUCT 3 ///< struct id +//#define NALT_SEENF 4 // 'seen' flag (used in structures) +//#define NALT_OOBASE0 5 // outer offset base 1 +//#define NALT_OOBASE1 6 // outer offset base 2 +//#define NALT_XREFPOS 7 // saved xref address in the xrefs window +#define NALT_AFLAGS 8 ///< additional flags for an item +#define NALT_LINNUM 9 ///< source line number +#define NALT_ABSBASE 10 ///< absolute segment location +#define NALT_ENUM0 11 ///< enum id for the first operand +#define NALT_ENUM1 12 ///< enum id for the second operand +//#define NALT_STROFF0 13 // struct offset, struct id for the first operand +//#define NALT_STROFF1 14 // struct offset, struct id for the second operand +#define NALT_PURGE 15 ///< number of bytes purged from the stack when a function is called indirectly +#define NALT_STRTYPE 16 ///< type of string item +#define NALT_ALIGN 17 ///< alignment value if the item is #FF_ALIGN + ///< (should by equal to power of 2) +//#define NALT_HIGH0 18 // linear address of byte referenced by +// // high 16 bits of an offset (FF_0HIGH) +//#define NALT_HIGH1 19 // linear address of byte referenced by +// // high 16 bits of an offset (FF_1HIGH) +#define NALT_COLOR 20 ///< instruction/data background color +//@} + +/// \defgroup NSUP_ Structure of supvals array +/// Structure of supvals array of netnode(ea). +/// Supvals is a virtual array of objects of arbitrary length attached +/// to a netnode (length of one element is limited by #MAXSPECSIZE, though) +/// We use first several indexes to this array: +//@{ +#define NSUP_CMT 0 ///< regular comment +#define NSUP_REPCMT 1 ///< repeatable comment +#define NSUP_FOP1 2 ///< forced operand 1 +#define NSUP_FOP2 3 ///< forced operand 2 +#define NSUP_JINFO 4 ///< jump table info +#define NSUP_ARRAY 5 ///< array parameters +#define NSUP_OMFGRP 6 ///< OMF: group of segments (not used anymore) +#define NSUP_FOP3 7 ///< forced operand 3 +#define NSUP_SWITCH 8 ///< switch information +#define NSUP_REF0 9 ///< complex reference information for operand 1 +#define NSUP_REF1 10 ///< complex reference information for operand 2 +#define NSUP_REF2 11 ///< complex reference information for operand 3 +#define NSUP_OREF0 12 ///< outer complex reference information for operand 1 +#define NSUP_OREF1 13 ///< outer complex reference information for operand 2 +#define NSUP_OREF2 14 ///< outer complex reference information for operand 3 +#define NSUP_STROFF0 15 ///< stroff: struct path for the first operand +#define NSUP_STROFF1 16 ///< stroff: struct path for the second operand +#define NSUP_SEGTRANS 17 ///< segment translations +#define NSUP_FOP4 18 ///< forced operand 4 +#define NSUP_FOP5 19 ///< forced operand 5 +#define NSUP_FOP6 20 ///< forced operand 6 +#define NSUP_REF3 21 ///< complex reference information for operand 4 +#define NSUP_REF4 22 ///< complex reference information for operand 5 +#define NSUP_REF5 23 ///< complex reference information for operand 6 +#define NSUP_OREF3 24 ///< outer complex reference information for operand 4 +#define NSUP_OREF4 25 ///< outer complex reference information for operand 5 +#define NSUP_OREF5 26 ///< outer complex reference information for operand 6 +#define NSUP_XREFPOS 27 ///< saved xref address and type in the xrefs window +#define NSUP_CUSTDT 28 ///< custom data type id +#define NSUP_GROUPS 29 ///< SEG_GRP: pack_dd encoded list of selectors +#define NSUP_ARGEAS 30 ///< instructions that initialize call arguments +#define NSUP_FOP7 31 ///< forced operand 7 +#define NSUP_FOP8 32 ///< forced operand 8 +#define NSUP_REF6 33 ///< complex reference information for operand 7 +#define NSUP_REF7 34 ///< complex reference information for operand 8 +#define NSUP_OREF6 35 ///< outer complex reference information for operand 7 +#define NSUP_OREF7 36 ///< outer complex reference information for operand 8 + +// values E_PREV..E_NEXT+1000 are reserved (1000..2000..3000 decimal) + +/// SP change points blob (see funcs.cpp). +/// values NSUP_POINTS..NSUP_POINTS+0x1000 are reserved +#define NSUP_POINTS 0x1000 + +/// manual instruction. +/// values NSUP_MANUAL..NSUP_MANUAL+0x1000 are reserved +#define NSUP_MANUAL 0x2000 + +/// type information. +/// values NSUP_TYPEINFO..NSUP_TYPEINFO+0x1000 are reserved +#define NSUP_TYPEINFO 0x3000 + +/// register variables. +/// values NSUP_REGVAR..NSUP_REGVAR+0x1000 are reserved +#define NSUP_REGVAR 0x4000 + +/// local labels. +/// values NSUP_LLABEL..NSUP_LLABEL+0x1000 are reserved +#define NSUP_LLABEL 0x5000 + +/// register argument type/name descriptions +/// values NSUP_REGARG..NSUP_REGARG+0x1000 are reserved +#define NSUP_REGARG 0x6000 + +/// function tails or tail referers +/// values NSUP_FTAILS..NSUP_FTAILS+0x1000 are reserved +#define NSUP_FTAILS 0x7000 + +/// graph group information +/// values NSUP_GROUP..NSUP_GROUP+0x1000 are reserved +#define NSUP_GROUP 0x8000 + +/// operand type information. +/// values NSUP_OPTYPES..NSUP_OPTYPES+0x100000 are reserved +#define NSUP_OPTYPES 0x9000 + +/// function metadata before lumina information was applied +/// values NSUP_ORIGFMD..NSUP_ORIGFMD+0x1000 are reserved +#define NSUP_ORIGFMD 0x109000 + +//@} + +/// \defgroup NALT_X Netnode xref tags +/// Tag values to store xrefs (see cref.cpp) +//@{ +#define NALT_CREF_TO 'X' ///< code xref to, idx: target address +#define NALT_CREF_FROM 'x' ///< code xref from, idx: source address +#define NALT_DREF_TO 'D' ///< data xref to, idx: target address +#define NALT_DREF_FROM 'd' ///< data xref from, idx: source address +//@} + +/// \defgroup N_TAG Netnode graph tags +/// Tag values to store graph info +//@{ +#define NSUP_GR_INFO 'g' ///< group node info: color, ea, text +#define NALT_GR_LAYX 'p' ///< group layout ptrs, hash: md5 of 'belongs' +#define NSUP_GR_LAYT 'l' ///< group layouts, idx: layout pointer +//@} + +/// Patch netnode tag +#define PATCH_TAG 'P' + +/// Get netnode for the specified address. + +idaman nodeidx_t ida_export ea2node(ea_t ea); +idaman ea_t ida_export node2ea(nodeidx_t ndx); +inline netnode getnode(ea_t ea) { return netnode(ea2node(ea)); } + +//-------------------------------------------------------------------------- +// C O N V E N I E N C E F U N C T I O N S +//-------------------------------------------------------------------------- + +/// \name Get structure ID +/// Returns the struct id of the struct type at the specified address. +/// Use this function when is_struct()==true +//@{ + +idaman tid_t ida_export get_strid(ea_t ea); + +//@} + +/// \name xrefpos +//@{ +/// Position of cursor in the window with cross-references to the address. +/// Used by the user-interface. +struct xrefpos_t +{ + ea_t ea; + uchar type; // the type of xref (::cref_t & ::dref_t) + xrefpos_t(ea_t ea_ = BADADDR, uchar type_ = 0) : ea(ea_), type(type_) {} + bool is_valid() const { return ea != BADADDR; } +}; + +idaman ssize_t ida_export get_xrefpos(xrefpos_t *out, ea_t ea); +idaman void ida_export set_xrefpos(ea_t ea, const xrefpos_t *in); +inline void idaapi del_xrefpos(ea_t ea) { getnode(ea).supdel(NSUP_XREFPOS); } + +//@} + +/// \defgroup AFL_ Additional flags for the location +/// All 32-bits of the main flags (bytes.hpp) are used up. +/// Additional flags keep more information about addresses. +/// AFLNOTE: DO NOT use these flags directly unless there is absolutely no way. +/// They are too low level and may corrupt the database. +//@{ +#define AFL_LINNUM 0x00000001L ///< has line number info +#define AFL_USERSP 0x00000002L ///< user-defined SP value +#define AFL_PUBNAM 0x00000004L ///< name is public (inter-file linkage) +#define AFL_WEAKNAM 0x00000008L ///< name is weak +#define AFL_HIDDEN 0x00000010L ///< the item is hidden completely +#define AFL_MANUAL 0x00000020L ///< the instruction/data is specified by the user +#define AFL_NOBRD 0x00000040L ///< the code/data border is hidden +#define AFL_ZSTROFF 0x00000080L ///< display struct field name at 0 offset when displaying an offset. + ///< example: + ///< \v{offset somestruct.field_0} + ///< if this flag is clear, then + ///< \v{offset somestruct} +#define AFL_BNOT0 0x00000100L ///< the 1st operand is bitwise negated +#define AFL_BNOT1 0x00000200L ///< the 2nd operand is bitwise negated +#define AFL_LIB 0x00000400L ///< item from the standard library. + ///< low level flag, is used to set + ///< #FUNC_LIB of ::func_t +#define AFL_TI 0x00000800L ///< has typeinfo? (#NSUP_TYPEINFO); used only for addresses, not for member_t +#define AFL_TI0 0x00001000L ///< has typeinfo for operand 0? (#NSUP_OPTYPES) +#define AFL_TI1 0x00002000L ///< has typeinfo for operand 1? (#NSUP_OPTYPES+1) +#define AFL_LNAME 0x00004000L ///< has local name too (#FF_NAME should be set) +#define AFL_TILCMT 0x00008000L ///< has type comment? (such a comment may be changed by IDA) +#define AFL_LZERO0 0x00010000L ///< toggle leading zeroes for the 1st operand +#define AFL_LZERO1 0x00020000L ///< toggle leading zeroes for the 2nd operand +#define AFL_COLORED 0x00040000L ///< has user defined instruction color? +#define AFL_TERSESTR 0x00080000L ///< terse structure variable display? +#define AFL_SIGN0 0x00100000L ///< code: toggle sign of the 1st operand +#define AFL_SIGN1 0x00200000L ///< code: toggle sign of the 2nd operand +#define AFL_NORET 0x00400000L ///< for imported function pointers: doesn't return. + ///< this flag can also be used for any instruction + ///< which halts or finishes the program execution +#define AFL_FIXEDSPD 0x00800000L ///< sp delta value is fixed by analysis. + ///< should not be modified by modules +#define AFL_ALIGNFLOW 0x01000000L ///< the previous insn was created for alignment purposes only +#define AFL_USERTI 0x02000000L ///< the type information is definitive. + ///< (comes from the user or type library) + ///< if not set see #AFL_TYPE_GUESSED +#define AFL_RETFP 0x04000000L ///< function returns a floating point value +#define AFL_USEMODSP 0x08000000L ///< insn modifes SP and uses the modified value + ///< example: pop [rsp+N] +#define AFL_NOTCODE 0x10000000L ///< autoanalysis should not create code here +#define AFL_NOTPROC 0x20000000L ///< autoanalysis should not create proc here +#define AFL_TYPE_GUESSED 0xC2000000L ///< who guessed the type information? +#define AFL_IDA_GUESSED 0x00000000L ///< the type is guessed by IDA +#define AFL_HR_GUESSED_FUNC 0x40000000L ///< the function type is guessed by the decompiler +#define AFL_HR_GUESSED_DATA 0x80000000L ///< the data type is guessed by the decompiler +#define AFL_HR_DETERMINED 0xC0000000L ///< the type is definitely guessed by the decompiler +//@} + +/// \name Work with additional location flags +/// See \ref AFL_ +//@{ +using aflags_t = flags_t; +idaman void ida_export set_aflags(ea_t ea, aflags_t flags); +idaman void ida_export upd_abits(ea_t ea, aflags_t clr_bits, aflags_t set_bits); +idaman void ida_export set_abits(ea_t ea, aflags_t bits); +idaman void ida_export clr_abits(ea_t ea, aflags_t bits); +idaman aflags_t ida_export get_aflags(ea_t ea); +idaman void ida_export del_aflags(ea_t ea); + +inline bool has_aflag_linnum(aflags_t flags) { return (flags & AFL_LINNUM) != 0; } +inline bool is_aflag_usersp(aflags_t flags) { return (flags & AFL_USERSP) != 0; } +inline bool is_aflag_public_name(aflags_t flags) { return (flags & AFL_PUBNAM) != 0; } +inline bool is_aflag_weak_name(aflags_t flags) { return (flags & AFL_WEAKNAM) != 0; } +inline bool is_aflag_hidden_item(aflags_t flags) { return (flags & AFL_HIDDEN) != 0; } +inline bool is_aflag_manual_insn(aflags_t flags) { return (flags & AFL_MANUAL) != 0; } +inline bool is_aflag_hidden_border(aflags_t flags) { return (flags & AFL_NOBRD) != 0; } +inline bool is_aflag_zstroff(aflags_t flags) { return (flags & AFL_ZSTROFF) != 0; } +inline bool is_aflag__bnot0(aflags_t flags) { return (flags & AFL_BNOT0) != 0; } +inline bool is_aflag__bnot1(aflags_t flags) { return (flags & AFL_BNOT1) != 0; } +inline bool is_aflag_libitem(aflags_t flags) { return (flags & AFL_LIB) != 0; } +inline bool has_aflag_ti(aflags_t flags) { return (flags & AFL_TI) != 0; } +inline bool has_aflag_ti0(aflags_t flags) { return (flags & AFL_TI0) != 0; } +inline bool has_aflag_ti1(aflags_t flags) { return (flags & AFL_TI1) != 0; } +inline bool has_aflag_lname(aflags_t flags) { return (flags & AFL_LNAME) != 0; } +inline bool is_aflag_tilcmt(aflags_t flags) { return (flags & AFL_TILCMT) != 0; } +inline bool is_aflag_lzero0(aflags_t flags) { return (flags & AFL_LZERO0) != 0; } +inline bool is_aflag_lzero1(aflags_t flags) { return (flags & AFL_LZERO1) != 0; } +inline bool is_aflag_colored_item(aflags_t flags) { return (flags & AFL_COLORED) != 0; } +inline bool is_aflag_terse_struc(aflags_t flags) { return (flags & AFL_TERSESTR) != 0; } +inline bool is_aflag__invsign0(aflags_t flags) { return (flags & AFL_SIGN0) != 0; } +inline bool is_aflag__invsign1(aflags_t flags) { return (flags & AFL_SIGN1) != 0; } +inline bool is_aflag_noret(aflags_t flags) { return (flags & AFL_NORET) != 0; } +inline bool is_aflag_fixed_spd(aflags_t flags) { return (flags & AFL_FIXEDSPD) != 0; } +inline bool is_aflag_align_flow(aflags_t flags) { return (flags & AFL_ALIGNFLOW)!= 0; } +inline bool is_aflag_userti(aflags_t flags) { return (flags & AFL_USERTI) != 0; } +inline bool is_aflag_retfp(aflags_t flags) { return (flags & AFL_RETFP) != 0; } +inline bool uses_aflag_modsp(aflags_t flags) { return (flags & AFL_USEMODSP) != 0; } +inline bool is_aflag_notcode(aflags_t flags) { return (flags & AFL_NOTCODE) != 0; } +inline bool is_aflag_notproc(aflags_t flags) { return (flags & AFL_NOTPROC) != 0; } +inline bool is_aflag_type_guessed_by_ida(aflags_t flags) { return (flags & AFL_TYPE_GUESSED) == AFL_IDA_GUESSED; } +inline bool is_aflag_func_guessed_by_hexrays(aflags_t flags) { return (flags & AFL_TYPE_GUESSED) == AFL_HR_GUESSED_FUNC; } +inline bool is_aflag_data_guessed_by_hexrays(aflags_t flags) { return (flags & AFL_TYPE_GUESSED) == AFL_HR_GUESSED_DATA; } +inline bool is_aflag_type_determined_by_hexrays(aflags_t flags) { return (flags & AFL_TYPE_GUESSED) == AFL_HR_DETERMINED; } +inline bool is_aflag_type_guessed_by_hexrays(aflags_t flags) +{ + flags = flags & AFL_TYPE_GUESSED; + return flags == AFL_HR_GUESSED_FUNC + || flags == AFL_HR_GUESSED_DATA + || flags == AFL_HR_DETERMINED; +} + +inline bool is_hidden_item(ea_t ea) { return is_aflag_hidden_item(get_aflags(ea)); } +inline void hide_item(ea_t ea) { set_abits(ea, AFL_HIDDEN); } +inline void unhide_item(ea_t ea) { clr_abits(ea, AFL_HIDDEN); } + +inline bool is_hidden_border(ea_t ea) { return is_aflag_hidden_border(get_aflags(ea)); } +inline void hide_border(ea_t ea) { set_abits(ea, AFL_NOBRD); } +inline void unhide_border(ea_t ea) { clr_abits(ea, AFL_NOBRD); } + +inline bool uses_modsp(ea_t ea) { return uses_aflag_modsp(get_aflags(ea)); } +inline void set_usemodsp(ea_t ea) { set_abits(ea, AFL_USEMODSP); } +inline void clr_usemodsp(ea_t ea) { clr_abits(ea, AFL_USEMODSP); } + +inline bool is_zstroff(ea_t ea) { return is_aflag_zstroff(get_aflags(ea)); } +inline void set_zstroff(ea_t ea) { set_abits(ea, AFL_ZSTROFF); } +inline void clr_zstroff(ea_t ea) { clr_abits(ea, AFL_ZSTROFF); } + +inline bool is__bnot0(ea_t ea) { return is_aflag__bnot0(get_aflags(ea)); } +inline void set__bnot0(ea_t ea) { set_abits(ea, AFL_BNOT0); } +inline void clr__bnot0(ea_t ea) { clr_abits(ea, AFL_BNOT0); } + +inline bool is__bnot1(ea_t ea) { return is_aflag__bnot1(get_aflags(ea)); } +inline void set__bnot1(ea_t ea) { set_abits(ea, AFL_BNOT1); } +inline void clr__bnot1(ea_t ea) { clr_abits(ea, AFL_BNOT1); } + +inline bool is_libitem(ea_t ea) { return is_aflag_libitem(get_aflags(ea)); } +inline void set_libitem(ea_t ea) { set_abits(ea, AFL_LIB); } +inline void clr_libitem(ea_t ea) { clr_abits(ea, AFL_LIB); } + +inline bool has_ti(ea_t ea) { return has_aflag_ti(get_aflags(ea)); } +inline void set_has_ti(ea_t ea) { set_abits(ea, AFL_TI); } +inline void clr_has_ti(ea_t ea) { clr_abits(ea, AFL_TI); } + +inline bool has_ti0(ea_t ea) { return has_aflag_ti0(get_aflags(ea)); } +inline void set_has_ti0(ea_t ea) { set_abits(ea, AFL_TI0); } +inline void clr_has_ti0(ea_t ea) { clr_abits(ea, AFL_TI0); } + +inline bool has_ti1(ea_t ea) { return has_aflag_ti1(get_aflags(ea)); } +inline void set_has_ti1(ea_t ea) { set_abits(ea, AFL_TI1); } +inline void clr_has_ti1(ea_t ea) { clr_abits(ea, AFL_TI1); } + +inline bool has_lname(ea_t ea) { return has_aflag_lname(get_aflags(ea)); } +inline void set_has_lname(ea_t ea) { set_abits(ea, AFL_LNAME); } +inline void clr_has_lname(ea_t ea) { clr_abits(ea, AFL_LNAME); } + +inline bool is_tilcmt(ea_t ea) { return is_aflag_tilcmt(get_aflags(ea)); } +inline void set_tilcmt(ea_t ea) { set_abits(ea, AFL_TILCMT); } +inline void clr_tilcmt(ea_t ea) { clr_abits(ea, AFL_TILCMT); } + +inline bool is_usersp(ea_t ea) { return is_aflag_usersp(get_aflags(ea)); } +inline void set_usersp(ea_t ea) { set_abits(ea, AFL_USERSP); } +inline void clr_usersp(ea_t ea) { clr_abits(ea, AFL_USERSP); } + +inline bool is_lzero0(ea_t ea) { return is_aflag_lzero0(get_aflags(ea)); } +inline void set_lzero0(ea_t ea) { set_abits(ea, AFL_LZERO0); } +inline void clr_lzero0(ea_t ea) { clr_abits(ea, AFL_LZERO0); } + +inline bool is_lzero1(ea_t ea) { return is_aflag_lzero1(get_aflags(ea)); } +inline void set_lzero1(ea_t ea) { set_abits(ea, AFL_LZERO1); } +inline void clr_lzero1(ea_t ea) { clr_abits(ea, AFL_LZERO1); } + +inline bool is_colored_item(ea_t ea) { return is_aflag_colored_item(get_aflags(ea)); } +inline void set_colored_item(ea_t ea) { set_abits(ea, AFL_COLORED); } // use set_item_color() +inline void clr_colored_item(ea_t ea) { clr_abits(ea, AFL_COLORED); } // use del_item_color() + +inline bool is_terse_struc(ea_t ea) { return is_aflag_terse_struc(get_aflags(ea)); } +inline void set_terse_struc(ea_t ea) { set_abits(ea, AFL_TERSESTR); } +inline void clr_terse_struc(ea_t ea) { clr_abits(ea, AFL_TERSESTR); } + +inline bool is__invsign0(ea_t ea) { return is_aflag__invsign0(get_aflags(ea)); } +inline void set__invsign0(ea_t ea) { set_abits(ea, AFL_SIGN0); } +inline void clr__invsign0(ea_t ea) { clr_abits(ea, AFL_SIGN0); } + +inline bool is__invsign1(ea_t ea) { return is_aflag__invsign1(get_aflags(ea)); } +inline void set__invsign1(ea_t ea) { set_abits(ea, AFL_SIGN1); } +inline void clr__invsign1(ea_t ea) { clr_abits(ea, AFL_SIGN1); } + +inline bool is_noret(ea_t ea) { return is_aflag_noret(get_aflags(ea)); } +inline void set_noret(ea_t ea) { set_abits(ea, AFL_NORET); } +inline void clr_noret(ea_t ea) { clr_abits(ea, AFL_NORET); } + +inline bool is_fixed_spd(ea_t ea) { return is_aflag_fixed_spd(get_aflags(ea)); } +inline void set_fixed_spd(ea_t ea) { set_abits(ea, AFL_FIXEDSPD); } +inline void clr_fixed_spd(ea_t ea) { clr_abits(ea, AFL_FIXEDSPD); } + +inline bool is_align_flow(ea_t ea) { return is_aflag_align_flow(get_aflags(ea)); } +inline void set_align_flow(ea_t ea) { set_abits(ea, AFL_ALIGNFLOW); } +inline void clr_align_flow(ea_t ea) { clr_abits(ea, AFL_ALIGNFLOW); } + +inline bool is_userti(ea_t ea) { return is_aflag_userti(get_aflags(ea)); } +inline void set_userti(ea_t ea) { upd_abits(ea, AFL_TYPE_GUESSED, AFL_USERTI); } +inline void clr_userti(ea_t ea) { clr_abits(ea, AFL_TYPE_GUESSED); } // use set_ida_guessed_type() + +inline bool is_retfp(ea_t ea) { return is_aflag_retfp(get_aflags(ea)); } +inline void set_retfp(ea_t ea) { set_abits(ea, AFL_RETFP); } +inline void clr_retfp(ea_t ea) { clr_abits(ea, AFL_RETFP); } + +inline bool is_notproc(ea_t ea) { return is_aflag_notproc(get_aflags(ea)); } +inline void set_notproc(ea_t ea) { set_abits(ea, AFL_NOTPROC); } +inline void clr_notproc(ea_t ea) { clr_abits(ea, AFL_NOTPROC); } + +inline bool is_type_guessed_by_ida(ea_t ea) { return is_aflag_type_guessed_by_ida(get_aflags(ea)); } +inline bool is_func_guessed_by_hexrays(ea_t ea) { return is_aflag_func_guessed_by_hexrays(get_aflags(ea)); } +inline bool is_data_guessed_by_hexrays(ea_t ea) { return is_aflag_data_guessed_by_hexrays(get_aflags(ea)); } +inline bool is_type_determined_by_hexrays(ea_t ea) { return is_aflag_type_determined_by_hexrays(get_aflags(ea)); } +inline bool is_type_guessed_by_hexrays(ea_t ea) { return is_aflag_type_guessed_by_hexrays(get_aflags(ea)); } + +inline void set_type_guessed_by_ida(ea_t ea) { upd_abits(ea, AFL_TYPE_GUESSED, AFL_IDA_GUESSED); } +inline void set_func_guessed_by_hexrays(ea_t ea) { upd_abits(ea, AFL_TYPE_GUESSED, AFL_HR_GUESSED_FUNC); } +inline void set_data_guessed_by_hexrays(ea_t ea) { upd_abits(ea, AFL_TYPE_GUESSED, AFL_HR_GUESSED_DATA); } +inline void set_type_determined_by_hexrays(ea_t ea) { upd_abits(ea, AFL_TYPE_GUESSED, AFL_HR_DETERMINED); } +//@} + +/// Mark address so that it cannot be converted to instruction +idaman void ida_export set_notcode(ea_t ea); + +/// Clear not-code mark +inline void clr_notcode(ea_t ea) { clr_abits(ea, AFL_NOTCODE); } + +/// Is the address marked as not-code? +inline bool is_notcode(ea_t ea) { return is_aflag_notcode(get_aflags(ea)); } + + +/// Change visibility of item at given ea + +inline void set_visible_item(ea_t ea, bool visible) +{ + if ( visible ) + unhide_item(ea); + else + hide_item(ea); +} + +/// Test visibility of item at given ea + +inline bool is_visible_item(ea_t ea) { return !is_hidden_item(ea); } + + +/// Is instruction visible? + +inline bool is_finally_visible_item(ea_t ea) +{ + return (inf_get_cmtflg() & SCF_SHHID_ITEM) != 0 || is_visible_item(ea); +} + + +/// \name Source line numbers +/// They are sometimes present in object files. +//@{ +idaman void ida_export set_source_linnum(ea_t ea, uval_t lnnum); +idaman uval_t ida_export get_source_linnum(ea_t ea); +idaman void ida_export del_source_linnum(ea_t ea); +//@} + +/// \name Absolute segment base address +/// These functions may be used if necessary (despite of the AFLNOTE above). +//@{ +inline ea_t get_absbase(ea_t ea) +{ + ea_t x; + return getnode(ea).supval(NALT_ABSBASE, &x, sizeof(x), atag) > 0 ? ea_t(x-1) : ea_t(-1); +} +inline void set_absbase(ea_t ea, ea_t x) +{ + x++; + getnode(ea).supset(NALT_ABSBASE, &x, sizeof(x), atag); +} +inline void del_absbase(ea_t ea) { getnode(ea).supdel(NALT_ABSBASE, atag); } +//@} + +/// \name Purged bytes +/// Number of bytes purged from the stack when a function is called indirectly +/// get_ind_purged() may be used if necessary (despite of the AFLNOTE above). +/// Use set_purged() to modify this value (do not use set_ind_purged()) +//@{ +inline ea_t get_ind_purged(ea_t ea) +{ + ea_t x; + return getnode(ea).supval(NALT_PURGE, &x, sizeof(x), atag) > 0 ? ea_t(x-1) : ea_t(-1); +} +inline void set_ind_purged(ea_t ea, ea_t x) +{ + x++; + getnode(ea).supset(NALT_PURGE, &x, sizeof(x), atag); +} +inline void del_ind_purged(ea_t ea) { getnode(ea).supdel(NALT_PURGE, atag); } +//@} + +/// \name Get type of string +/// Use higher level function get_opinfo(). +//@{ +inline uint32 get_str_type(ea_t ea) +{ + uint32 x; + return getnode(ea).supval(NALT_STRTYPE, &x, sizeof(x), atag) > 0 ? uint32(x-1) : uint32(-1); +} +inline void set_str_type(ea_t ea, uint32 x) +{ + x++; + getnode(ea).supset(NALT_STRTYPE, &x, sizeof(x), atag); +} +inline void del_str_type(ea_t ea) { getnode(ea).supdel(NALT_STRTYPE, atag); } +//@} + +// Number of bytes per "units" in a string. E.g., ASCII, Windows-1252, +// UTF-8 all take up one byte per unit, while UTF-16 variations take 2 and +// UTF-32 variations take 4. +// (Note that an "unit" in this context is not necessarily a character, +// since UTF-8-encoded characters can be encoded in up to 4 bytes, +// and UTF-16-encoded characters can be encoded in up to 2 bytes.) +#define STRWIDTH_1B 0 +#define STRWIDTH_2B 1 +#define STRWIDTH_4B 2 +#define STRWIDTH_MASK 0x03 + +// The string layout; how the string is laid out in data. +#define STRLYT_TERMCHR 0 +#define STRLYT_PASCAL1 1 +#define STRLYT_PASCAL2 2 +#define STRLYT_PASCAL4 3 +#define STRLYT_MASK 0xFC +#define STRLYT_SHIFT 2 + + +/// \defgroup STRTYPE_ String type codes +//@{ +///< Character-terminated string. The termination characters are kept in +///< the next bytes of string type. +#define STRTYPE_TERMCHR (STRWIDTH_1B|STRLYT_TERMCHR<<STRLYT_SHIFT) +///< C-style string. +#define STRTYPE_C STRTYPE_TERMCHR +///< Zero-terminated 16bit chars +#define STRTYPE_C_16 (STRWIDTH_2B|STRLYT_TERMCHR<<STRLYT_SHIFT) +///< Zero-terminated 32bit chars +#define STRTYPE_C_32 (STRWIDTH_4B|STRLYT_TERMCHR<<STRLYT_SHIFT) +///< Pascal-style, one-byte length prefix +#define STRTYPE_PASCAL (STRWIDTH_1B|STRLYT_PASCAL1<<STRLYT_SHIFT) +///< Pascal-style, 16bit chars, one-byte length prefix +#define STRTYPE_PASCAL_16 (STRWIDTH_2B|STRLYT_PASCAL1<<STRLYT_SHIFT) +///< Pascal-style, two-byte length prefix +#define STRTYPE_LEN2 (STRWIDTH_1B|STRLYT_PASCAL2<<STRLYT_SHIFT) +///< Pascal-style, 16bit chars, two-byte length prefix +#define STRTYPE_LEN2_16 (STRWIDTH_2B|STRLYT_PASCAL2<<STRLYT_SHIFT) +///< Pascal-style, four-byte length prefix +#define STRTYPE_LEN4 (STRWIDTH_1B|STRLYT_PASCAL4<<STRLYT_SHIFT) +///< Pascal-style, 16bit chars, four-byte length prefix +#define STRTYPE_LEN4_16 (STRWIDTH_2B|STRLYT_PASCAL4<<STRLYT_SHIFT) +//@} + +/// \name Work with string type codes +/// See \ref STRTYPE_ +//@{ +inline THREAD_SAFE uchar idaapi get_str_type_code(int32 strtype) { return uchar(strtype); } +inline THREAD_SAFE char get_str_term1(int32 strtype) { return char(strtype>>8); } +inline THREAD_SAFE char get_str_term2(int32 strtype) { return char(strtype>>16); } + // if the second termination character is + // '\0', then it doesn't exist. +/// Get index of the string encoding for this string +inline THREAD_SAFE uchar idaapi get_str_encoding_idx(int32 strtype) { return uchar(strtype>>24); } + +inline THREAD_SAFE bool is_pascal(int32 strtype) +{ + int lyt = get_str_type_code(strtype) >> STRLYT_SHIFT; + return lyt >= STRLYT_PASCAL1 && lyt <= STRLYT_PASCAL4; +} + +inline THREAD_SAFE size_t get_str_type_prefix_length(int32 strtype) +{ + switch ( get_str_type_code(strtype) ) + { + case STRTYPE_LEN4_16: + case STRTYPE_LEN4: + return 4; + case STRTYPE_LEN2_16: + case STRTYPE_LEN2: + return 2; + case STRTYPE_PASCAL_16: + case STRTYPE_PASCAL: + return 1; + } + return 0; +} +//@} + +#define STRENC_DEFAULT 0x00 ///< use default encoding for this type (see get_default_encoding_idx()) +#define STRENC_NONE 0xFF ///< force no-conversion encoding + +/// \name Alignment value +/// (should be power of 2) +/// These functions may be used if necessary (despite of the AFLNOTE above). +//@{ +inline uint32 get_alignment(ea_t ea) +{ + uint32 x; + return getnode(ea).supval(NALT_ALIGN, &x, sizeof(x), atag) > 0 ? uint32(x-1) : uint32(-1); +} +inline void set_alignment(ea_t ea,uint32 x) +{ + x++; + getnode(ea).supset(NALT_ALIGN, &x, sizeof(x), atag); +} +inline void del_alignment(ea_t ea) { getnode(ea).supdel(NALT_ALIGN, atag); } +//@} + + +/// \name Instruction/Data background color +//@{ +idaman void ida_export set_item_color(ea_t ea, bgcolor_t color); +idaman bgcolor_t ida_export get_item_color(ea_t ea); // returns DEFCOLOR if no color +idaman bool ida_export del_item_color(ea_t ea); +//@} + + +//------------------------------------------------------------------------- +/// \name Array representation +//@{ +/// Describes how to display an array +struct array_parameters_t +{ + int32 flags; +#define AP_ALLOWDUPS 0x00000001L ///< use 'dup' construct +#define AP_SIGNED 0x00000002L ///< treats numbers as signed +#define AP_INDEX 0x00000004L ///< display array element indexes as comments +#define AP_ARRAY 0x00000008L ///< create as array (this flag is not stored in database) +#define AP_IDXBASEMASK 0x000000F0L ///< mask for number base of the indexes +#define AP_IDXDEC 0x00000000L ///< display indexes in decimal +#define AP_IDXHEX 0x00000010L ///< display indexes in hex +#define AP_IDXOCT 0x00000020L ///< display indexes in octal +#define AP_IDXBIN 0x00000030L ///< display indexes in binary + + int32 lineitems; ///< number of items on a line + int32 alignment; ///< -1 - don't align. + ///< 0 - align automatically. + ///< else item width +}; +idaman ssize_t ida_export get_array_parameters(array_parameters_t *out, ea_t ea); +idaman void ida_export set_array_parameters(ea_t ea, const array_parameters_t *in); +inline void idaapi del_array_parameters(ea_t ea) { getnode(ea).supdel(NSUP_ARRAY); } +//@} + +//-------------------------------------------------------------------------- +/// Information about a switch statement +struct switch_info_t +{ + uint32 flags; ///< \ref SWI_ +/// \defgroup SWI_ Switch info flags +/// Used by switch_info_t::flags +//@{ +#define SWI_SPARSE 0x00000001 ///< sparse switch (value table present) + ///< otherwise lowcase present +#define SWI_V32 0x00000002 ///< 32-bit values in table +#define SWI_J32 0x00000004 ///< 32-bit jump offsets +#define SWI_VSPLIT 0x00000008 ///< value table is split (only for 32-bit values) +#define SWI_USER 0x00000010 ///< user specified switch (starting from version 2) +#define SWI_DEF_IN_TBL 0x00000020 ///< default case is an entry in the jump table. + ///< This flag is applicable in 2 cases: + ///< 1. The sparse indirect switch (i.e. a switch with a values table) + ///< <jump table size> == <value table size> + 1. + ///< The default case entry is the last one in the table + ///< (or the first one in the case of an inversed jump table). + ///< 2. The switch with insns in the jump table. + ///< The default case entry is before the first entry of the table. + ///< See also the find_defjump_from_table() helper function. +#define SWI_JMP_INV 0x00000040 ///< jumptable is inversed. (last entry is + ///< for first entry in values table) +#define SWI_SHIFT_MASK 0x00000180 ///< use formula (element<<shift) + elbase to find jump targets +#define SWI_ELBASE 0x00000200 ///< elbase is present (otherwise the base of the switch + ///< segment will be used) +#define SWI_JSIZE 0x00000400 ///< jump offset expansion bit +#define SWI_VSIZE 0x00000800 ///< value table element size expansion bit +#define SWI_SEPARATE 0x00001000 ///< create an array of individual elements (otherwise separate items) +#define SWI_SIGNED 0x00002000 ///< jump table entries are signed +#define SWI_CUSTOM 0x00004000 ///< custom jump table. + ///< \ph{create_switch_xrefs} will be called to create code xrefs + ///< for the table. Custom jump table must be created by the + ///< module (see also #SWI_STDTBL) +//#define SWI_EXTENDED 0x00008000 ///< reserved +#define SWI_INDIRECT 0x00010000 ///< value table elements are used as indexes into the jump table + ///< (for sparse switches) +#define SWI_SUBTRACT 0x00020000 ///< table values are subtracted from the elbase instead of being added +#define SWI_HXNOLOWCASE 0x00040000 ///< lowcase value should not be used by the decompiler (internal flag) +#define SWI_STDTBL 0x00080000 ///< custom jump table with standard table formatting. + ///< ATM IDA doesn't use SWI_CUSTOM for switches with standard + ///< table formatting. So this flag can be considered as obsolete. +#define SWI_DEFRET 0x00100000 ///< return in the default case (defjump==BADADDR) +#define SWI_SELFREL 0x00200000 ///< jump address is relative to the element not to ELBASE +#define SWI_JMPINSN 0x00400000 ///< jump table entries are insns. For such entries SHIFT has a + ///< different meaning. It denotes the number of insns in the + ///< entry. For example, 0 - the entry contains the jump to the + ///< case, 1 - the entry contains one insn like a 'mov' and jump + ///< to the end of case, and so on. +#define SWI_VERSION 0x00800000 ///< the structure contains the VERSION member +//@} + + /// See #SWI_SHIFT_MASK. + /// possible answers: 0..3. + int get_shift(void) const { return ((flags & SWI_SHIFT_MASK) >> 7); } + + /// See #SWI_SHIFT_MASK + void set_shift(int shift) + { + flags &= ~SWI_SHIFT_MASK; + flags |= ((shift & 3) << 7); + } + + int get_jtable_element_size(void) const + { // this brain damaged logic is needed for compatibility with old versions + int code = flags & (SWI_J32|SWI_JSIZE); + if ( code == 0 ) + return 2; + if ( code == SWI_J32 ) + return 4; + if ( code == SWI_JSIZE ) + return 1; + return 8; + } + void set_jtable_element_size(int size) + { + flags &= ~SWI_J32|SWI_JSIZE; + switch ( size ) + { + case 4: + flags |= SWI_J32; + break; + case 1: + flags |= SWI_JSIZE; + break; + case 8: + flags |= SWI_J32|SWI_JSIZE; + break; + case 2: + break; + default: + INTERR(1297); + } + } + int get_vtable_element_size(void) const + { + int code = flags & (SWI_V32|SWI_VSIZE); + if ( code == 0 ) + return 2; + if ( code == SWI_V32 ) + return 4; + if ( code == SWI_VSIZE ) + return 1; + return 8; + } + void set_vtable_element_size(int size) + { + flags &= ~SWI_V32|SWI_VSIZE; + switch ( size ) + { + case 4: + flags |= SWI_V32; + break; + case 1: + flags |= SWI_VSIZE; + break; + case 8: + flags |= SWI_V32|SWI_VSIZE; + break; + case 2: + break; + default: + INTERR(1298); + } + } + + bool has_default(void) const { return defjump != BADADDR; } + bool has_elbase(void) const { return (flags & SWI_ELBASE) != 0; } + bool is_sparse(void) const { return (flags & SWI_SPARSE) != 0; } + bool is_custom(void) const { return (flags & SWI_CUSTOM) != 0; } + bool is_indirect(void) const { return (flags & SWI_INDIRECT) != 0; } + bool is_subtract(void) const { return (flags & SWI_SUBTRACT) != 0; } + bool is_nolowcase(void) const { return (flags & SWI_HXNOLOWCASE) != 0; } + bool use_std_table(void) const { return !is_custom() || (flags & SWI_STDTBL) != 0; } + bool is_user_defined() const + { + return get_version() >= 2 && (flags & SWI_USER) != 0; + } + + ushort ncases; ///< number of cases (excluding default) + ea_t jumps; ///< jump table start address + union + { + ea_t values; ///< values table address (if #SWI_SPARSE is set) + uval_t lowcase; ///< the lowest value in cases + }; + ea_t defjump; ///< default jump address (#BADADDR if no default case) + ea_t startea; ///< start of the switch idiom + int jcases; ///< number of entries in the jump table (SWI_INDIRECT) + + sval_t ind_lowcase; + sval_t get_lowcase(void) const { return is_indirect() ? ind_lowcase : lowcase; } + ea_t elbase; ///< element base + + int regnum; ///< the switch expression as a value of the REGNUM register + ///< before the instruction at EXPR_EA. -1 means 'unknown' + op_dtype_t regdtype; ///< size of the switch expression register as dtype + + int get_jtable_size(void) const { return is_indirect() ? jcases : ncases; } + void set_jtable_size(int size) + { + if ( is_indirect() ) + jcases = size; + else + ncases = uint16(size); + } + void set_elbase(ea_t base) + { + elbase = base; + flags |= SWI_ELBASE; + } + + void set_expr(int r, op_dtype_t dt) { regnum = r; regdtype = dt; } + + /// get separate parts of the switch + bool get_jrange_vrange(range_t *jrange = NULL, range_t *vrange = NULL) const + { + if ( !use_std_table() ) + return false; + if ( jrange != NULL ) + { + int n = get_jtable_size(); + if ( (flags & SWI_DEF_IN_TBL) != 0 ) + ++n; + int jsize = get_jtable_element_size(); + *jrange = range_t(jumps, jumps + jsize * n); + } + if ( vrange != NULL && is_sparse() ) + { + int vsize = get_vtable_element_size(); + *vrange = range_t(values, values + vsize * ncases); + } + return true; + } + + uval_t custom; ///< information for custom tables (filled and used by modules) + + enum { SWITCH_INFO_VERSION = 2 }; + int version; + int get_version() const + { + return (flags & SWI_VERSION) == 0 ? 1 : version; + } + + // version 2 + ea_t expr_ea; ///< the address before that the switch expression is in REGNUM. + ///< If BADADDR, then the first insn marked as IM_SWITCH after + ///< STARTEA is used. + eavec_t marks; ///< the insns marked as IM_SWITCH. They used to delete the switch. + + switch_info_t(void) + : flags(SWI_VERSION), + ncases(0), + jumps(BADADDR), + lowcase(0), + defjump(BADADDR), + startea(BADADDR), + jcases(0), + ind_lowcase(0), + elbase(0), + regnum(-1), + regdtype(0), + custom(0), + version(SWITCH_INFO_VERSION), + expr_ea(BADADDR), + marks() {} + void clear(void) { *this = switch_info_t(); } +}; + +/// \name Switch info +/// See ::switch_info_t, xref.hpp for related functions +//@{ +idaman ssize_t ida_export get_switch_info(switch_info_t *out, ea_t ea); +idaman void ida_export set_switch_info(ea_t ea, const switch_info_t &in); +idaman void ida_export del_switch_info(ea_t ea); +//@} + +/// \name Switch parent +/// Address which holds the switch info (::switch_info_t). Used at the jump targets. +//@{ +inline ea_t get_switch_parent(ea_t ea) +{ + ea_t x; + return getnode(ea).supval(NALT_SWITCH, &x, sizeof(x), atag) > 0 ? ea_t(x-1) : ea_t(-1); +} +inline void set_switch_parent(ea_t ea,ea_t x) +{ + x++; + getnode(ea).supset(NALT_SWITCH, &x, sizeof(x), atag); +} +inline void del_switch_parent(ea_t ea) { getnode(ea).supdel(NALT_SWITCH, atag); } +//@} + +/// \name Custom data types +//@{ +/// Information about custom data types +struct custom_data_type_ids_t +{ + int16 dtid; ///< data type id + int16 fids[UA_MAXOP]; ///< data format ids + + void set(tid_t tid) + { + memset(fids, -1, sizeof(fids)); + dtid = ushort(tid); + fids[0] = ushort(tid >> 16); + } +#ifndef SWIG + DECLARE_COMPARISONS(custom_data_type_ids_t); +#endif +}; +idaman int ida_export get_custom_data_type_ids(custom_data_type_ids_t *cdis, ea_t ea); +idaman void ida_export set_custom_data_type_ids(ea_t ea, const custom_data_type_ids_t *cdis); +inline void idaapi del_custom_data_type_ids(ea_t ea) { getnode(ea).supdel(NSUP_CUSTDT); } +//@} + +typedef uchar reftype_t; ///< see \ref reftype_ +/// \defgroup reftype_ Types of references +/// References are represented in the following form: +/// +/// \v{target + tdelta - base} +/// +/// If the target is not present, then it will be calculated using +/// +/// \v{target = operand_value - tdelta + base} +/// +/// The target must be present for LOW and HIGH reference types +//@{ +const reftype_t + V695_REF_OFF8 = 0, ///< reserved + REF_OFF16 = 1, ///< 16bit full offset + REF_OFF32 = 2, ///< 32bit full offset + REF_LOW8 = 3, ///< low 8bits of 16bit offset + REF_LOW16 = 4, ///< low 16bits of 32bit offset + REF_HIGH8 = 5, ///< high 8bits of 16bit offset + REF_HIGH16 = 6, ///< high 16bits of 32bit offset + V695_REF_VHIGH = 7, ///< obsolete + V695_REF_VLOW = 8, ///< obsolete + REF_OFF64 = 9, ///< 64bit full offset + REF_OFF8 = 10, ///< 8bit full offset + REF_LAST = REF_OFF8; +//@} + +/// Can the target be calculated using operand value? + +inline bool is_reftype_target_optional(reftype_t type); + +/// Get REF_... constant from size +/// Supported sizes: 1,2,4,8,16 +/// For other sizes returns reftype_t(-1) + +idaman reftype_t ida_export get_reftype_by_size(size_t size); + +/// Information about a reference +struct refinfo_t +{ + ea_t target; ///< reference target (#BADADDR-none) + ea_t base; ///< base of reference (may be BADADDR) + adiff_t tdelta; ///< offset from the target + uint32 flags; ///< \ref REFINFO_ +/// \defgroup REFINFO_ Reference info flags +/// Used by refinfo_t::flags +//@{ +#define REFINFO_TYPE 0x000F ///< reference type (reftype_t), or custom + ///< reference ID if REFINFO_CUSTOM set +#define REFINFO_RVAOFF 0x0010 ///< based reference (rva) + ///< refinfo_t::base will be forced to get_imagebase() + ///< such a reference is displayed with the \ash{a_rva} keyword +#define REFINFO_PASTEND 0x0020 ///< reference past an item + ///< it may point to an nonexistent address + ///< do not destroy alignment dirs +#define REFINFO_CUSTOM 0x0040 ///< a custom reference. + ///< see custom_refinfo_handler_t. + ///< the id of the custom refinfo is + ///< stored under the REFINFO_TYPE mask. +#define REFINFO_NOBASE 0x0080 ///< don't create the base xref + ///< implies that the base can be any value + ///< nb: base xrefs are created only if the offset base + ///< points to the middle of a segment +#define REFINFO_SUBTRACT 0x0100 ///< the reference value is subtracted from the base value instead of (as usual) being added to it +#define REFINFO_SIGNEDOP 0x0200 ///< the operand value is sign-extended (only supported for REF_OFF8/16/32/64) +//@} + + reftype_t type(void) const + { + return reftype_t(flags & (REFINFO_TYPE | REFINFO_CUSTOM)); + } + + bool is_target_optional() const ///< \ref is_reftype_target_optional() + { + reftype_t rt = flags & (REFINFO_TYPE | REFINFO_CUSTOM); + return is_reftype_target_optional(rt); + } + + bool no_base_xref(void) const { return (flags & REFINFO_NOBASE) != 0; } + bool is_pastend(void) const { return (flags & REFINFO_PASTEND) != 0; } + bool is_rvaoff(void) const { return (flags & REFINFO_RVAOFF) != 0; } + bool is_custom(void) const { return (flags & REFINFO_CUSTOM) != 0; } + bool is_subtract(void) const { return (flags & REFINFO_SUBTRACT) != 0; } + bool is_signed(void) const { return (flags & REFINFO_SIGNEDOP) != 0; } + + // RT can include REFINFO_CUSTOM bit + void set_type(reftype_t rt) + { + flags &= ~(REFINFO_TYPE | REFINFO_CUSTOM); + flags |= rt; + } + + // init the structure with some default values + // reft_and_flags should be REF_xxx optionally ORed with some REFINFO_xxx flags + void init(uint32 reft_and_flags, ea_t _base = 0, ea_t _target = BADADDR, adiff_t _tdelta = 0) + { + flags = reft_and_flags; + base = _base; + target = _target; + tdelta = _tdelta; + } + + // internal use +#ifndef SWIG + ea_t _get_target(adiff_t opval) const; + ea_t _get_value(ea_t target) const; + adiff_t _get_opval(adiff_t opval) const; + DECLARE_COMPARISONS(refinfo_t); +#endif +}; + +/// Manage a custom refinfo type +/// Custom refinfos are usually used to handle custom fixups, +/// but can also be used to display non-standard references. +struct custom_refinfo_handler_t +{ + int32 cbsize; ///< size of this structure + const char *name; ///< Format name, must be unique + const char *desc; ///< Refinfo description to use in Ctrl-R dialog + int props; ///< properties (currently 0) +/// \defgroup RHF_ Refinfo handler properties +/// Used by custom_refinfo_handler_t::props +//@{ +#define RHF_TGTOPT 0x0001 ///< can the target be calculated using + ///< operand value? +//@} + + // this callback prepares the full offset expression in buf and + // returns 1 if it is a simple expression or 2 if it is a complex one. + // Or this callback checks the compliance of opval and fullvalue, + // and possibly updates values of target and fullvalue, + // and prepares the format, + // and returns 3 to continue standard processing with updated values. + // Or this callback just prepares the format and returns 4 to continue. + // It returns 0 in the case of error. + // It is guaranteed that before calling this callback, the + // calc_reference_data() callback is always called. + int (idaapi *gen_expr)( + qstring *buf, + qstring *format, // buffer for the format (if retcode>=3) + ea_t ea, + int opnum, + const refinfo_t &ri, + ea_t from, + adiff_t *opval, // the output value is not used + ea_t *target, // the target prepared by calc_reference_data() + ea_t *fullvalue, + int getn_flags); + + // this callback replaces calc_target. + // It calculates target and base, + // and calculates an internal variable fullvalue, + // and checks the compliance of opval and fullvalue, + // and returns the success flag. + bool (idaapi *calc_reference_data)( + ea_t *target, + ea_t *base, + ea_t from, + const refinfo_t &ri, + adiff_t opval); + + // just custom format + void (idaapi *get_format)(qstring *format); + +#ifndef SWIG + DECLARE_COMPARISONS(custom_refinfo_handler_t); +#endif +}; + + +/// Register a new custom refinfo type. + +idaman int ida_export register_custom_refinfo(const custom_refinfo_handler_t *crh); + + +/// Unregister a new custom refinfo type. + +idaman bool ida_export unregister_custom_refinfo(int crid); + + +/// Get id of a custom refinfo type. + +idaman int ida_export find_custom_refinfo(const char *name); + + +/// Get definition of a registered custom refinfo type. + +idaman const custom_refinfo_handler_t *ida_export get_custom_refinfo(int crid); + + +/// Get refinfo handler + +inline const custom_refinfo_handler_t *idaapi get_custom_refinfo_handler( + const refinfo_t &ri) +{ + return ri.is_custom() ? get_custom_refinfo(ri.type()) : NULL; +} + +// inline implementaion +inline bool is_reftype_target_optional(reftype_t type) +{ + if ( (type & REFINFO_CUSTOM) != 0 ) + { + const custom_refinfo_handler_t *cfh = get_custom_refinfo(type); + if ( cfh == NULL ) + return false; + return (cfh->props & RHF_TGTOPT) != 0; + } + switch ( type ) + { + case REF_OFF8: + case REF_OFF16: + case REF_OFF32: + case REF_OFF64: + return true; + } + return false; +} + + +/// Get descriptions of all standard and custom refinfo types. + +struct refinfo_desc_t +{ + uint32 type; ///< Refinfo type, see \ref REFINFO_ + ///< Custom refinfo has REFINFO_CUSTOM bit. + const char *name; ///< Refinfo name + const char *desc; ///< Refinfo description to use in Ctrl-R dialog +}; +DECLARE_TYPE_AS_MOVABLE(refinfo_desc_t); +typedef qvector<refinfo_desc_t> refinfo_desc_vec_t; +idaman void ida_export get_refinfo_descs(refinfo_desc_vec_t *descs); + + +#define MAXSTRUCPATH 32 ///< maximal inclusion depth of unions + +/// Information for structure offsets. +/// ids[0] contains the id of the structure. +/// ids[1..len-1] contain ids of the structure members used in the structure offset +/// expression. +/// len is the length of the path, i.e. the number of elements in 'ids' +struct strpath_t +{ + int len; + tid_t ids[MAXSTRUCPATH]; // for union member ids + adiff_t delta; +#ifndef SWIG + DECLARE_COMPARISONS(strpath_t); +#endif +}; + +/// See opinfo_t::ec +struct enum_const_t +{ + tid_t tid; + uchar serial; +#ifndef SWIG + DECLARE_COMPARISONS(enum_const_t) + { + COMPARE_FIELDS(tid); + COMPARE_FIELDS(serial); + return 0; + } +#endif +}; + +/// Additional information about an operand type +union opinfo_t +{ + refinfo_t ri; ///< for offset members + tid_t tid; ///< for struct, etc. members + strpath_t path; ///< for stroff + int32 strtype; ///< for strings (\ref STRTYPE_) + enum_const_t ec; ///< for enums + custom_data_type_ids_t cd; ///< for custom data +#ifndef SWIG + int compare_opinfos(const opinfo_t &r, flags_t flag, int n) const; +#endif +}; + +//-V:printop_t:730 Not all members of a class are initialized inside the constructor +struct printop_t +{ + flags_t flags; // new operand representation flags + opinfo_t ti; // new operand type +#define POF_VALID_TI 0x1 // is operand type initialized? +#define POF_VALID_AFLAGS 0x2 // internal + uchar features; // features this instance holds + int suspop; // out: will be set by print_operand() + aflags_t aflags; // additional aflags + + printop_t() : flags(0), features(0), suspop(0), aflags(0) {} //-V730 'ti' is not initialized + bool is_ti_initialized() const { return (features & POF_VALID_TI) == POF_VALID_TI; } + void set_ti_initialized(bool v=true) { setflag(features, POF_VALID_TI, v); } + bool is_aflags_initialized() const { return (features & POF_VALID_AFLAGS) == POF_VALID_AFLAGS; } + void set_aflags_initialized(bool v=true) { setflag(features, POF_VALID_AFLAGS, v); } + + const opinfo_t *get_ti() const { return is_ti_initialized() ? &ti : NULL; } +}; + +/// \name Get/Set refinfo +/// n may be 0, 1, 2, #OPND_MASK. +/// #OPND_OUTER may be used too. +/// Don't use these functions, see get_opinfo(), set_opinfo() +//@{ +idaman bool ida_export set_refinfo_ex(ea_t ea, int n, const refinfo_t *ri); +idaman bool ida_export set_refinfo( + ea_t ea, + int n, + reftype_t type, + ea_t target=BADADDR, + ea_t base=0, + adiff_t tdelta=0); +idaman bool ida_export get_refinfo(refinfo_t *ri, ea_t ea, int n); +idaman bool ida_export del_refinfo(ea_t ea, int n); +//@} + +//-------------------------------------------------------------------------- +/// \name Structure paths +/// Structure paths for unions and structures with unions (strpath) +/// a structure path is an array of id's. +/// the first id is the id of the structure itself. +/// additional id's (if any) specify which member of a union we should select +/// the maximal size of array is #MAXSTRUCPATH. +/// strpaths are used to determine how to display structure offsets. +//@{ +idaman void ida_export write_struc_path(ea_t ea, int idx, const tid_t *path, int plen, adiff_t delta); +idaman int ida_export read_struc_path(tid_t *path, adiff_t *delta, ea_t ea, int idx); // returns plen +//@} + +//@} + + +//-------------------------------------------------------------------------- +// type information (ti) storage +// up to 256 operands are supported for ti. + +typedef uchar type_t; +typedef uchar p_list; +class tinfo_t; + +/// \name Types +/// Work with function/data types +/// These functions may be used if necessary (despite of the AFLNOTE above). +//@{ +idaman bool ida_export get_tinfo(tinfo_t *tif, ea_t ea); +idaman bool ida_export set_tinfo(ea_t ea, const tinfo_t *tif); +inline void idaapi del_tinfo(ea_t ea) { set_tinfo(ea, NULL); } +//@} + +/// \name Operand types +/// These functions may be used if necessary (despite of the AFLNOTE above). +//@{ +idaman bool ida_export get_op_tinfo(tinfo_t *tif, ea_t ea, int n); +idaman bool ida_export set_op_tinfo(ea_t ea, int n, const tinfo_t *tif); +inline void idaapi del_op_tinfo(ea_t ea, int n) { set_op_tinfo(ea, n, NULL); } +//@} + +//------------------------------------------------------------------------// +/// \defgroup RIDX_ Rootnode indexes: +//@{ + +// supvals +#define RIDX_FILE_FORMAT_NAME 1 ///< file format name for loader modules +#define RIDX_SELECTORS 2 ///< 2..63 are for selector_t blob (see init_selectors()) +#define RIDX_GROUPS 64 ///< segment group information (see init_groups()) +#define RIDX_H_PATH 65 ///< C header path +#define RIDX_C_MACROS 66 ///< C predefined macros +#define RIDX_SMALL_IDC_OLD 67 ///< Instant IDC statements (obsolete) +#define RIDX_NOTEPAD 68 ///< notepad blob, occupies 1000 indexes (1MB of text) +#define RIDX_INCLUDE 1100 ///< assembler include file name +#define RIDX_SMALL_IDC 1200 ///< Instant IDC statements, blob +#define RIDX_DUALOP_GRAPH 1300 ///< Graph text representation options +#define RIDX_DUALOP_TEXT 1301 ///< Text text representation options +#define RIDX_MD5 1302 ///< MD5 of the input file +#define RIDX_IDA_VERSION 1303 ///< version of ida which created the database + +#define RIDX_STR_ENCODINGS 1305 ///< a list of encodings for the program strings +#define RIDX_SRCDBG_PATHS 1306 ///< source debug paths, occupies 20 indexes +#define RIDX_DBG_BINPATHS 1328 ///< unused (20 indexes) +#define RIDX_SHA256 1349 ///< SHA256 of the input file +#define RIDX_ABINAME 1350 ///< ABI name (processor specific) +#define RIDX_ARCHIVE_PATH 1351 ///< archive file path +#define RIDX_PROBLEMS 1352 ///< problem lists +#define RIDX_SRCDBG_UNDESIRED 1353 ///< user-closed source files, occupies 20 indexes + +// altvals +#define RIDX_ALT_VERSION uval_t(-1) ///< initial version of database +#define RIDX_ALT_CTIME uval_t(-2) ///< database creation timestamp +#define RIDX_ALT_ELAPSED uval_t(-3) ///< seconds database stayed open +#define RIDX_ALT_NOPENS uval_t(-4) ///< how many times the database is opened +#define RIDX_ALT_CRC32 uval_t(-5) ///< input file crc32 +#define RIDX_ALT_IMAGEBASE uval_t(-6) ///< image base +#define RIDX_ALT_IDSNODE uval_t(-7) ///< ids modnode id (for import_module) +#define RIDX_ALT_FSIZE uval_t(-8) ///< input file size +#define RIDX_ALT_OUTFILEENC uval_t(-9) ///< output file encoding index +//@} + +//--------------------------------------------------------------------------- +/// Get file name only of the input file +idaman ssize_t ida_export get_root_filename(char *buf, size_t bufsize); + +/// Get debugger input file name/path (see #LFLG_DBG_NOPATH) +idaman ssize_t ida_export dbg_get_input_path(char *buf, size_t bufsize); + +// The following functions should eventually be replaced by exported functions +#ifndef __KERNEL__ +/// Get full path of the input file +inline ssize_t idaapi get_input_file_path(char *buf, size_t bufsize) +{ + return getinf_buf(INF_INPUT_FILE_PATH, buf, bufsize); +} + +/// Set full path of the input file +inline void set_root_filename(const char *file) { setinf_buf(INF_INPUT_FILE_PATH, file); } + +/// Get size of input file in bytes +inline size_t idaapi retrieve_input_file_size(void) { return getinf(INF_FSIZE); } + +/// Get input file crc32 stored in the database. +/// it can be used to check that the input file has not been changed. +inline uint32 idaapi retrieve_input_file_crc32(void) { return uint32(getinf(INF_CRC32)); } + +/// Get input file md5 +inline bool idaapi retrieve_input_file_md5(uchar hash[16]) { return getinf_buf(INF_MD5, hash, 16) == 16; } + +/// Get input file sha256 +inline bool idaapi retrieve_input_file_sha256(uchar hash[32]) { return getinf_buf(INF_SHA256, hash, 32) == 32; } + +/// Get name of the include file +inline ssize_t idaapi get_asm_inc_file(qstring *buf) { return getinf_str(buf, INF_INCLUDE); } + +/// Set name of the include file +inline bool idaapi set_asm_inc_file(const char *file) { return setinf_buf(INF_INCLUDE, file); } + +/// Get image base address +inline ea_t idaapi get_imagebase(void) { return getinf(INF_IMAGEBASE); } + +/// Set image base address +inline void idaapi set_imagebase(ea_t base) { setinf(INF_IMAGEBASE, base); } + +/// Get ids modnode +inline netnode idaapi get_ids_modnode(void) { return getinf(INF_IDSNODE); } + +/// Set ids modnode +inline void idaapi set_ids_modnode(netnode id) { setinf(INF_IDSNODE, id); } + +/// Get archive file path from which input file was extracted +inline ssize_t idaapi get_archive_path(qstring *buf) { return getinf_str(buf, INF_ARCHIVE_PATH); } + +/// Set archive file path from which input file was extracted +inline bool set_archive_path(const char *file) { return setinf_buf(INF_ARCHIVE_PATH, file); } + +/// Get file format name for loader modules +inline ssize_t idaapi get_loader_format_name(qstring *buf) { return getinf_str(buf, INF_FILE_FORMAT_NAME); } + +/// Set file format name for loader modules +inline void set_loader_format_name(const char *name) { setinf_buf(INF_FILE_FORMAT_NAME, name); } + +/// Get version of ida which created the database (string format like "7.5") +inline ssize_t idaapi get_initial_ida_version(qstring *ver) { return getinf_str(ver, INF_IDA_VERSION); } + +/// Get notead text +inline ssize_t idaapi get_ida_notepad_text(qstring *text) { return getinf_str(text, INF_NOTEPAD); } + +/// Set notead text +inline void idaapi set_ida_notepad_text(const char *text, size_t size=0) { setinf_buf(INF_NOTEPAD, text, size); } + +/// Get source debug paths +inline ssize_t idaapi get_srcdbg_paths(qstring *paths) { return getinf_str(paths, INF_SRCDBG_PATHS); } + +/// Set source debug paths +inline void idaapi set_srcdbg_paths(const char *paths) { setinf_buf(INF_SRCDBG_PATHS, paths); } + +/// Get user-closed source files +inline ssize_t idaapi get_srcdbg_undesired_paths(qstring *paths) { return getinf_str(paths, INF_SRCDBG_UNDESIRED); } + +/// Set user-closed source files +inline void idaapi set_srcdbg_undesired_paths(const char *paths) { setinf_buf(INF_SRCDBG_UNDESIRED, paths); } + +/// Get version of ida which created the database (numeric format like 750) +inline ushort idaapi get_initial_ida_version() { return getinf(INF_INITIAL_VERSION); } + +/// Get database creation timestamp +inline time_t idaapi get_idb_ctime() { return getinf(INF_CTIME); } + +/// Get seconds database stayed open +inline size_t idaapi get_elapsed_secs() { return getinf(INF_ELAPSED); } + +/// Get number of times the database is opened +inline size_t idaapi get_idb_nopens() { return getinf(INF_NOPENS); } + +#endif + +//--------------------------------------------------------------------------- +/// \name String encodings +/// Encoding names can be a codepage names (CP1251, windows-1251), +/// charset name (Shift-JIS, UTF-8), or just codepage number (866, 932). +/// user-accessible encodings are counted from 1 +/// (index 0 is reserved) +//@{ + +/// Get total number of encodings (counted from 0) + +idaman int ida_export get_encoding_qty(); + + +/// Get encoding name for specific index (1-based). +/// \return NULL if idx is out of bounds + +idaman const char *ida_export get_encoding_name(int idx); + + +/// Add a new encoding (e.g. "UTF-8"). +/// \return its index (1-based) +/// if it's already in the list, return its index + +idaman int ida_export add_encoding(const char *encoding); + + +/// Delete an encoding (1-based) + +idaman bool ida_export del_encoding(int idx); + + +/// Change name for an encoding (1-based) + +idaman bool ida_export rename_encoding(int idx, const char *encoding); + + +#define BPU_1B 1 +#define BPU_2B 2 +#define BPU_4B 4 + +/// Get the amount of bytes per unit (e.g., 2 for UTF-16, 4 for UTF-32) +/// for the encoding with the given index. +/// +/// \param idx the encoding index +/// \return the number of bytes per units (1/2/4); -1 means error + +idaman int ida_export get_encoding_bpu(int idx); + + +//------------------------------------------------------------------------- +inline int get_strtype_bpu(int32 strtype) +{ + int w = get_str_type_code(strtype) & STRWIDTH_MASK; + return w == STRWIDTH_2B ? BPU_2B : (w == STRWIDTH_4B ? BPU_4B : BPU_1B); +} + +/// Get default encoding index for a specific string type. +/// \param bpu the amount of bytes per unit (e.g., 1 for ASCII, CP1252, UTF-8..., 2 for UTF-16, 4 for UTF-32) +/// 0 means no specific encoding is set - byte values are displayed without conversion. + +idaman int ida_export get_default_encoding_idx(int bpu); + +/// set default encoding for a string type +/// \param bpu the amount of bytes per unit +/// \param idx the encoding index +/// idx can be 0 to disable encoding conversion + +idaman bool ida_export set_default_encoding_idx(int bpu, int idx); + + +/// Get encoding name for this strtype + +inline const char *idaapi encoding_from_strtype(int32 strtype) +{ + uchar enc = get_str_encoding_idx(strtype); + if ( enc == 0 ) + enc = get_default_encoding_idx(get_strtype_bpu(strtype)); + return get_encoding_name(enc); // will return NULL if enc is 0 +} + + +/// Get the index of the encoding used when producing files +/// 0 means no that the IDB's default 1 byte-per-unit encoding is used + +idaman int ida_export get_outfile_encoding_idx(); + + +/// set encoding to be used when producing files +/// \param idx the encoding index +/// idx can be 0 to use the IDB's default 1-byte-per-unit encoding + +idaman bool ida_export set_outfile_encoding_idx(int idx); + + +//@} + +//------------------------------------------------------------------------// +/// \name Functions to work with imports +//@{ + +/// Get number of import modules + +idaman uint ida_export get_import_module_qty(); + + +/// Get import module name. +/// \retval true ok +/// \retval false bad index + +idaman bool ida_export get_import_module_name(qstring *buf, int mod_index); + + +/// Callback for enumerating imports. +/// \param ea import address +/// \param name import name (NULL if imported by ordinal) +/// \param ord import ordinal (0 for imports by name) +/// \param param user parameter passed to enum_import_names() +/// \retval 1 ok +/// \retval 0 stop enumeration + +typedef int idaapi import_enum_cb_t(ea_t ea, const char *name, uval_t ord, void *param); + + +/// Enumerate imports from specific module. +/// \retval 1 finished ok +/// \retval -1 error +/// \retval other callback return value (<=0) + +idaman int ida_export enum_import_names(int mod_index, import_enum_cb_t *callback, void *param=NULL); + + +/// Delete all imported modules information + +idaman void ida_export delete_imports(void); +//@} + + +/// Check consistency of name records, return number of bad ones + +idaman int ida_export validate_idb_names2(bool do_repair); + + +#ifndef SWIG +#if !defined(NO_OBSOLETE_FUNCS) +//-------------------------------------------------------------------------- +/// \name Ignore micro +/// netnode to keep information about various kinds of instructions +//@{ +extern netnode ignore_micro; + +#define IM_NONE 0 // regular instruction +#define IM_PROLOG 1 // prolog instruction +#define IM_EPILOG 2 // epilog instruction +#define IM_SWITCH 3 // switch instruction (the indirect jump should not be marked) + +inline void init_ignore_micro(void) { ignore_micro.create("$ ignore micro"); } +inline void term_ignore_micro(void) { ignore_micro = BADNODE; } +inline char get_ignore_micro(ea_t ea) { return ignore_micro.charval_ea(ea, 0); } +inline void set_ignore_micro(ea_t ea, uchar im_type) { ignore_micro.charset_ea(ea, im_type, 0); } +inline void clr_ignore_micro(ea_t ea) { ignore_micro.chardel_ea(ea, 0); } +inline ea_t next_marked_insn(ea_t ea) { return node2ea(ignore_micro.charnext(ea2node(ea), 0)); } +inline void mark_prolog_insn(ea_t ea) { set_ignore_micro(ea, IM_PROLOG); } +inline void mark_epilog_insn(ea_t ea) { set_ignore_micro(ea, IM_EPILOG); } +inline void mark_switch_insn(ea_t ea) { set_ignore_micro(ea, IM_SWITCH); } +inline bool is_prolog_insn(ea_t ea) { return get_ignore_micro(ea) == IM_PROLOG; } +inline bool is_epilog_insn(ea_t ea) { return get_ignore_micro(ea) == IM_EPILOG; } +inline bool is_switch_insn(ea_t ea) { return get_ignore_micro(ea) == IM_SWITCH; } +inline bool should_ignore_micro(ea_t ea) { return get_ignore_micro(ea) != IM_NONE; } +//@} +#endif +#endif // SWIG + +//-------------------------------------------------------------------------- +// Set address of .got section +inline void set_gotea(ea_t gotea) +{ + netnode n; + n.create("$ got"); + n.altset(0, ea2node(gotea)+1); +} + +//-------------------------------------------------------------------------- +// Get address of .got section +inline ea_t get_gotea(void) +{ + netnode n("$ got"); + return exist(n) ? node2ea(n.altval(0) - 1) : BADADDR; +} + + +#if !defined(NO_OBSOLETE_FUNCS) +idaman DEPRECATED int ida_export validate_idb_names(); // use validate_idb_names2 +#endif + +#ifndef BYTES_SOURCE // undefined bit masks so no one can use them directly +#undef AFL_LINNUM +#undef AFL_USERSP +#undef AFL_PUBNAM +#undef AFL_WEAKNAM +#undef AFL_HIDDEN +#undef AFL_MANUAL +#undef AFL_NOBRD +#undef AFL_ZSTROFF +#undef AFL_BNOT0 +#undef AFL_BNOT1 +#undef AFL_LIB +#undef AFL_TI +#undef AFL_TI0 +#undef AFL_TI1 +#undef AFL_LNAME +#undef AFL_TILCMT +#undef AFL_LZERO0 +#undef AFL_LZERO1 +#undef AFL_COLORED +#undef AFL_TERSESTR +#undef AFL_SIGN0 +#undef AFL_SIGN1 +#undef AFL_NORET +#undef AFL_FIXEDSPD +#undef NALT_ENUM +#undef NALT_WIDE +#undef NALT_SWITCH +//#undef NALT_STRUCT +#undef NALT_XREFPOS +#undef NALT_AFLAGS +#undef NALT_LINNUM +#undef NALT_ABSBASE +//#undef NALT_ENUM0 +//#undef NALT_ENUM1 +#undef NALT_PURGE +#undef NALT_STRTYPE +#undef NALT_ALIGN +#undef NALT_COLOR +#undef NSUP_CMT +#undef NSUP_REPCMT +#undef NSUP_FOP1 +#undef NSUP_FOP2 +#undef NSUP_JINFO +#undef NSUP_ARRAY +#undef NSUP_OMFGRP +#undef NSUP_FOP3 +#undef NSUP_SWITCH +#undef NSUP_REF0 +#undef NSUP_REF1 +#undef NSUP_REF2 +#undef NSUP_OREF0 +#undef NSUP_OREF1 +#undef NSUP_OREF2 +#undef NSUP_STROFF0 +#undef NSUP_STROFF1 +#undef NSUP_SEGTRANS +#undef NSUP_FOP4 +#undef NSUP_FOP5 +#undef NSUP_FOP6 +#undef NSUP_FOP7 +#undef NSUP_FOP8 +#undef NSUP_REF3 +#undef NSUP_REF4 +#undef NSUP_REF5 +#undef NSUP_REF6 +#undef NSUP_REF7 +#undef NSUP_OREF3 +#undef NSUP_OREF4 +#undef NSUP_OREF5 +#undef NSUP_OREF6 +#undef NSUP_OREF7 +#undef NSUP_MANUAL +#undef NSUP_FTAILS +#undef NSUP_GROUP +#endif + +#endif // NALT_HPP diff --git a/idasdk76/include/name.hpp b/idasdk76/include/name.hpp new file mode 100644 index 0000000..824283a --- /dev/null +++ b/idasdk76/include/name.hpp @@ -0,0 +1,786 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _NAME_HPP +#define _NAME_HPP + +#include <ida.hpp> + +/*! \file name.hpp + + \brief Functions that deal with names. + + A non-tail address of the program may have a name. + Tail addresses (i.e. the addresses in the middle of an instruction or + data item) cannot have names. +*/ + +class func_t; // funcs.hpp +typedef uchar color_t; // lines.hpp + +/// Maximum length of a name in IDA (with the trailing zero) +#define MAXNAMELEN 512 + + +/// Name prefix used by IDA for the imported functions +#define FUNC_IMPORT_PREFIX "__imp_" + + +/// Set or delete name of an item at the specified address. +/// An item can be anything: instruction, function, data byte, word, string, +/// structure, etc... +/// Include name into the list of names. +/// \param ea linear address. +/// do nothing if ea is not valid (return 0). +/// tail bytes can't have names. +/// \param name new name. +/// - NULL: do nothing (return 0). +/// - "" : delete name. +/// - otherwise this is a new name. +/// \param flags \ref SN_. +/// If a bit is not specified, then the corresponding action is not performed +/// and the name will retain the same bits as before calling this function. +/// For new names, default is: non-public, non-weak, non-auto. +/// \retval 1 ok, name is changed +/// \retval 0 failure, a warning is displayed + +idaman bool ida_export set_name(ea_t ea, const char *name, int flags=0); + +/// \defgroup SN_ Set name flags +/// Passed as 'flag' parameter to set_name(ea_t, const char *, int) +//@{ +#define SN_CHECK 0x00 +#define SN_NOCHECK 0x01 ///< Don't fail if the name contains invalid characters. + ///< If this bit is clear, all invalid chars + ///< (those !is_ident_cp()) will be replaced + ///< by SUBSTCHAR + ///< List of valid characters is defined in ida.cfg +#define SN_PUBLIC 0x02 ///< if set, make name public +#define SN_NON_PUBLIC 0x04 ///< if set, make name non-public +#define SN_WEAK 0x08 ///< if set, make name weak +#define SN_NON_WEAK 0x10 ///< if set, make name non-weak +#define SN_AUTO 0x20 ///< if set, make name autogenerated +#define SN_NON_AUTO 0x40 ///< if set, make name non-autogenerated +#define SN_NOLIST 0x80 ///< if set, exclude name from the list. + ///< if not set, then include the name into + ///< the list (however, if other bits are set, + ///< the name might be immediately excluded + ///< from the list). +#define SN_NOWARN 0x100 ///< don't display a warning if failed +#define SN_LOCAL 0x200 ///< create local name. a function should exist. + ///< local names can't be public or weak. + ///< also they are not included into the list of names + ///< they can't have dummy prefixes. +#define SN_IDBENC 0x400 ///< the name is given in the IDB encoding; + ///< non-ASCII bytes will be decoded accordingly. + ///< Specifying SN_IDBENC also implies SN_NODUMMY +#define SN_FORCE 0x800 ///< if the specified name is already present + ///< in the database, try variations with a + ///< numerical suffix like "_123" +#define SN_NODUMMY 0x1000 ///< automatically prepend the name with '_' if it + ///< begins with a dummy suffix such as 'sub_'. + ///< See also SN_IDBENC +#define SN_DELTAIL 0x2000 ///< if name cannot be set because of a tail byte, + ///< delete the hindering item +//@} + +inline bool force_name(ea_t ea, const char *name, int flags=0) +{ + return set_name(ea, name, flags|SN_FORCE|SN_NODUMMY); +} + +/// \name Delete a name of a program item +/// \param ea linear address +/// \retval 1 ok, name is deleted +/// \retval 0 failure, invalid address +//@{ +inline bool del_global_name(ea_t ea) { return set_name(ea,"", SN_NOWARN); } +inline bool del_local_name(ea_t ea) { return set_name(ea,"", SN_LOCAL|SN_NOWARN); } +//@} + +/// Give an autogenerated (dummy) name. +/// Autogenerated names have special prefixes (loc_...). +/// \param from linear address of the operand which references to the address +/// \param ea linear address +/// \retval 1 ok, dummy name is generated or the byte already had a name +/// \retval 0 failure, invalid address or tail byte + +idaman bool ida_export set_dummy_name(ea_t from, ea_t ea); // give dummy name + + +/// \name Set/Clear bit in flags for 'autogenerated but meaningful name' +/// This bit affects value of has_user_name(), has_auto_name() functions. +/// \param ea linear address +/// \retval 1 ok +/// \retval 0 no meaningful name is present at the specified address +//@{ +idaman bool ida_export make_name_auto(ea_t ea); +idaman bool ida_export make_name_user(ea_t ea); +//@} + + +enum ucdr_kind_t +{ + UCDR_STRLIT = 0x01, // string literals + UCDR_NAME = 0x02, // regular (unmangled) names + UCDR_MANGLED = 0x04, // mangled names + UCDR_TYPE = 0x08, // type names +}; + +enum nametype_t +{ + // identifier (e.g., function name) + VNT_IDENT = UCDR_NAME|UCDR_MANGLED, + // type name (can contain '<', '>', ...) + VNT_TYPE = UCDR_TYPE, + // UDT (structure, union, enum) member + VNT_UDTMEM = UCDR_NAME, + // string literal + VNT_STRLIT = UCDR_STRLIT, + VNT_VISIBLE = VNT_UDTMEM,// visible cp (obsolete; will be deleted) +}; + +/// Validate a name. +/// This function replaces all invalid characters in the name with SUBSTCHAR. +/// However, it will return false if name is valid but not allowed to be an +/// identifier (is a register name). +/// +/// \param[in,out] name ptr to name. the name will be modified +/// \param type the type of name we want to validate +/// \param flags see SN_* . Only SN_IDBENC is currently considered +/// +/// \return success + +idaman bool ida_export validate_name( + qstring *name, + nametype_t type, + int flags = 0); + + +/// Is the given codepoint acceptable in the given context? + +idaman bool ida_export is_valid_cp(wchar32_t cp, nametype_t kind, void *data=NULL); + + +/// Mark the given codepoint (or range) as acceptable or unacceptable in the given context +/// If 'endcp' is not BADCP, it is considered to be the end of the range: +/// [cp, endcp), and is not included in the range + +idaman void ida_export set_cp_validity(ucdr_kind_t kind, wchar32_t cp, wchar32_t endcp=BADCP, bool valid=true); + + +/// Is the given codepoint (or range) acceptable in the given context? +/// If 'endcp' is not BADCP, it is considered to be the end of the range: +/// [cp, endcp), and is not included in the range + +idaman bool ida_export get_cp_validity(ucdr_kind_t kind, wchar32_t cp, wchar32_t endcp=BADCP); + + +/// Can a character appear in a name? (present in ::NameChars or ::MangleChars) + +inline bool is_ident_cp(wchar32_t cp) { return is_valid_cp(cp, VNT_IDENT); } + + +/// Can a character appear in a string literal (present in ::StrlitChars) +/// If 'specific_ranges' are specified, those will be used instead of +/// the ones corresponding to the current culture (only if ::StrlitChars +/// is configured to use the current culture) + +inline bool is_strlit_cp(wchar32_t cp, const rangeset_crefvec_t *specific_ranges=NULL) +{ return is_valid_cp(cp, VNT_STRLIT, (void *) specific_ranges); } + + +/// Can a character be displayed in a name? (present in ::NameChars) + +inline bool is_visible_cp(wchar32_t cp) +{ return is_valid_cp(cp, VNT_VISIBLE); } + + +/// Is a valid name? (including ::MangleChars) + +idaman bool ida_export is_ident(const char *name); + + +/// Is valid user-specified name? (valid name & !dummy prefix). +/// \param name name to test. may be NULL. +/// \retval 1 yes +/// \retval 0 no + +idaman bool ida_export is_uname(const char *name); + + +/// Is valid type name? +/// \param name name to test. may be NULL. +/// \retval 1 yes +/// \retval 0 no + +idaman bool ida_export is_valid_typename(const char *name); + + +/// Is dummy name? +/// \param name name to test. may be NULL. +/// \return #BADADDR if not, otherwise the address denoted by the name + +idaman ea_t ida_export dummy_name_ea(const char *name); + + +/// Extract a name or address from the specified string. +/// \param[out] out output buffer for the identifier +/// \param line input string +/// \param x x coordinate of cursor +/// \return -1 if cannot extract. otherwise length of the name + +idaman ssize_t ida_export extract_name(qstring *out, const char *line, int x); + + +/// Remove name from the list of names +/// \param ea address of the name + +idaman void ida_export hide_name(ea_t ea); + + +/// Insert name to the list of names + +idaman void ida_export show_name(ea_t ea); + + +/// Get address of the name. +/// Dummy names (like byte_xxxx where xxxx are hex digits) are parsed by this +/// function to obtain the address. The database is not consulted for them. +/// This function works only with regular names. +/// \param from linear address where the name is used. +/// if not applicable, then should be #BADADDR. +/// \param name any name in the program or NULL +/// \return address of the name or #BADADDR + +idaman ea_t ida_export get_name_ea(ea_t from, const char *name); + + +/// Get address of the name used in the expression for the address +/// \param from address of the operand which references to the address +/// \param to the referenced address +/// \return address of the name used to represent the operand + +idaman ea_t ida_export get_name_base_ea(ea_t from, ea_t to); + + +/// Get value of the name. +/// This function knows about: regular names, enums, special segments, etc. +/// \param[out] value pointer to variable with answer +/// \param from linear address where the name is used +/// if not applicable, then should be BADADDR +/// \param name any name in the program or NULL +/// \return \ref NT_ + +idaman int ida_export get_name_value(uval_t *value, ea_t from, const char *name); + +/// \defgroup NT_ Name value result codes +/// Return values for get_name_value() +//@{ +#define NT_NONE 0 ///< name doesn't exist or has no value +#define NT_BYTE 1 ///< name is byte name (regular name) +#define NT_LOCAL 2 ///< name is local label +#define NT_STKVAR 3 ///< name is stack variable name +#define NT_ENUM 4 ///< name is symbolic constant +#define NT_ABS 5 ///< name is absolute symbol (#SEG_ABSSYM) +#define NT_SEG 6 ///< name is segment or segment register name +#define NT_STROFF 7 ///< name is structure member +#define NT_BMASK 8 ///< name is a bit group mask name +#define NT_REGVAR 9 ///< name is a renamed register (*value is idx into pfn->regvars) +//@} + + +/// Additional information for get_ea_name() function +struct getname_info_t +{ + size_t cb; ///< size of this struct + int32 inhibitor; ///< codes to inhibit parts of demangled name (see \ref MNG_). + ///< Usually this is one of \inf{short_demnames} or \inf{long_demnames}. + int32 demform; ///< demangle only if \inf{demnames} is equal to 'demform'. + int32 demcode; ///< out: return value of demangler + getname_info_t(void) : cb(sizeof(*this)), inhibitor(0), demform(0), demcode(0) {} +}; + + +/// Get name at the specified address. +/// \param[out] out buffer to hold the name +/// \param ea linear address +/// \param gtn_flags how exactly the name should be retrieved. +/// combination of \ref GN_ bits +/// \param gtni additional information for name demangling +/// Please use the convenience functions declared below instead of calling +/// get_ea_name directly. +/// \return success + +idaman ssize_t ida_export get_ea_name( + qstring *out, + ea_t ea, + int gtn_flags=0, + getname_info_t *gtni=NULL); + +/// \defgroup GN_ bits for get_ea_name() function. There is a convenience +/// function calc_gtn_flags() to calculate the GN_LOCAL flag +//@{ +#define GN_VISIBLE 0x0001 ///< replace forbidden characters by SUBSTCHAR +#define GN_COLORED 0x0002 ///< return colored name +#define GN_DEMANGLED 0x0004 ///< return demangled name +#define GN_STRICT 0x0008 ///< fail if cannot demangle +#define GN_SHORT 0x0010 ///< use short form of demangled name +#define GN_LONG 0x0020 ///< use long form of demangled name +#define GN_LOCAL 0x0040 ///< try to get local name first; if failed, get global +#define GN_ISRET 0x0080 ///< for dummy names: use retloc +#define GN_NOT_ISRET 0x0100 ///< for dummy names: do not use retloc +#define GN_NOT_DUMMY 0x0200 ///< do not return a dummy name + +//@} + +// Convenience functions for get_ea_name returning ssize_t + +inline ssize_t get_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, gtn_flags); +} + +inline ssize_t idaapi get_visible_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, GN_VISIBLE|gtn_flags); +} + +inline ssize_t idaapi get_colored_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, GN_VISIBLE|GN_COLORED|gtn_flags); +} + +inline ssize_t idaapi get_short_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, GN_VISIBLE|GN_DEMANGLED|GN_SHORT|gtn_flags); +} + +inline ssize_t idaapi get_long_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, GN_VISIBLE|GN_DEMANGLED|GN_LONG|gtn_flags); +} + +inline ssize_t idaapi get_colored_short_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_SHORT|gtn_flags); +} + +inline ssize_t idaapi get_colored_long_name(qstring *out, ea_t ea, int gtn_flags=0) +{ + return get_ea_name(out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_LONG|gtn_flags); +} + +inline ssize_t idaapi get_demangled_name( + qstring *out, + ea_t ea, + int32 inhibitor, + int demform, + int gtn_flags=0) +{ + getname_info_t gtni; + gtni.inhibitor = inhibitor; + gtni.demform = demform; + gtn_flags |= GN_VISIBLE | GN_DEMANGLED; + return get_ea_name(out, ea, gtn_flags, >ni); +} + +inline ssize_t idaapi get_colored_demangled_name( + qstring *out, + ea_t ea, + int32 inhibitor, + int demform, + int gtn_flags=0) +{ + return get_demangled_name(out, ea, inhibitor, demform, gtn_flags|GN_COLORED); +} + +// Convenience functions for get_ea_name returning qstring + +inline qstring get_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, gtn_flags); + return out; +} + +inline qstring get_visible_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, GN_VISIBLE|gtn_flags); + return out; +} + +inline qstring idaapi get_colored_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, GN_VISIBLE|GN_COLORED|gtn_flags); + return out; +} + +inline qstring idaapi get_short_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, GN_VISIBLE|GN_DEMANGLED|GN_SHORT|gtn_flags); + return out; +} + +inline qstring idaapi get_long_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, GN_VISIBLE|GN_DEMANGLED|GN_LONG|gtn_flags); + return out; +} + +inline qstring idaapi get_colored_short_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_SHORT|gtn_flags); + return out; +} + +inline qstring idaapi get_colored_long_name(ea_t ea, int gtn_flags=0) +{ + qstring out; + get_ea_name(&out, ea, GN_VISIBLE|GN_COLORED|GN_DEMANGLED|GN_LONG|gtn_flags); + return out; +} + +inline qstring idaapi get_demangled_name( + ea_t ea, + int32 inhibitor, + int demform, + int gtn_flags=0) +{ + qstring out; + getname_info_t gtni; + gtni.inhibitor = inhibitor; + gtni.demform = demform; + gtn_flags |= GN_VISIBLE | GN_DEMANGLED; + get_ea_name(&out, ea, gtn_flags, >ni); + return out; +} + +inline qstring idaapi get_colored_demangled_name( + ea_t ea, + int32 inhibitor, + int demform, + int gtn_flags=0) +{ + qstring out; + get_demangled_name(&out, ea, inhibitor, demform, gtn_flags|GN_COLORED); + return out; +} + +/// Calculate flags for get_ea_name() function +#ifdef FUNCS_HPP +inline int calc_gtn_flags(ea_t from, ea_t ea) +{ + return func_contains(get_func(from), ea) ? GN_LOCAL : 0; +} +#endif + +/// Get name color. +/// \param from linear address where the name is used. +/// if not applicable, then should be #BADADDR. +/// The kernel returns a local name color if the reference is +/// within a function, i.e. 'from' and 'ea' belong to the same function. +/// \param ea linear address + +idaman color_t ida_export get_name_color(ea_t from, ea_t ea); + + +/// \defgroup GETN_ Name expression flags +/// Passed as 'flags' parameter to get_name_expr() +//@{ +#define GETN_APPZERO 0x0001 ///< meaningful only if the name refers to a structure. + ///< append a struct field name if the field offset is zero? +#define GETN_NOFIXUP 0x0002 ///< ignore the fixup information when producing the name +#define GETN_NODUMMY 0x0004 ///< do not create a new dummy name but pretend it exists +//@} + +/// Convert address to name expression (name with a displacement). +/// This function takes into account fixup information and returns +/// a colored name expression (in the form <name> +/- <offset>). +/// It also knows about structure members and arrays. +/// If the specified address doesn't have a name, a dummy name is generated. +/// \param[out] out output buffer for the name +/// \param from linear address of instruction operand or data referring to +/// the name. This address will be used to get fixup information, +/// so it should point to exact position of the operand in the +/// instruction. +/// \param n number of referencing operand. for data items specify 0 +/// \param ea address to convert to name expression +/// \param off the value of name expression. this parameter is used only to +/// check that the name expression will have the wanted value. +/// 'off' may be equal to BADADDR but this is discouraged +/// because it prohibits checks. +/// \param flags \ref GETN_ +/// \return < 0 if address is not valid, no segment or other failure. +/// otherwise the length of the name expression in characters. + +idaman ssize_t ida_export get_name_expr( + qstring *out, + ea_t from, + int n, + ea_t ea, + uval_t off, + int flags=GETN_APPZERO); + +/// Get a nice colored name at the specified address. +/// Ex: +/// - segment:sub+offset +/// - segment:sub:local_label +/// - segment:label +/// - segment:address +/// - segment:address+offset +/// \param[out] buf buffer to hold the name +/// \param ea linear address +/// \param flags \ref GNCN_ +/// \return the length of the generated name in bytes. + +idaman ssize_t ida_export get_nice_colored_name( + qstring *buf, + ea_t ea, + int flags=0); + +/// \defgroup GNCN_ Nice colored name flags +/// Passed as 'flags' parameter to get_nice_colored_name() +//@{ +#define GNCN_NOSEG 0x0001 ///< ignore the segment prefix when producing the name +#define GNCN_NOCOLOR 0x0002 ///< generate an uncolored name +#define GNCN_NOLABEL 0x0004 ///< don't generate labels +#define GNCN_NOFUNC 0x0008 ///< don't generate funcname+... expressions +#define GNCN_SEG_FUNC 0x0010 ///< generate both segment and function names (default is to omit segment name if a function name is present) +#define GNCN_SEGNUM 0x0020 ///< segment part is displayed as a hex number +#define GNCN_REQFUNC 0x0040 ///< return 0 if the address does not belong to a function +#define GNCN_REQNAME 0x0080 ///< return 0 if the address can only be represented as a hex number +#define GNCN_NODBGNM 0x0100 ///< don't use debug names +#define GNCN_PREFDBG 0x0200 ///< if using debug names, prefer debug names over function names +//@} + + +/// Append names of struct fields to a name if the name is a struct name. +/// \param out pointer to the output buffer +/// \param disp displacement from the name +/// \param n number of operand n which the name appears +/// \param path path in the struct. path is an array of id's. +/// maximal length of array is #MAXSTRUCPATH. +/// the first element of the array is the structure id. +/// consecutive elements are id's of used union members (if any). +/// \param plen size of path array +/// \param flags the input flags. they will be returned if the struct +/// cannot be found. +/// \param delta delta to add to displacement +/// \param appzero should append a struct field name if the displacement is zero? +/// \return flags of the innermost struct member or the input flags + +idaman flags_t ida_export append_struct_fields( + qstring *out, + adiff_t *disp, + int n, + const tid_t *path, + int plen, + flags_t flags, + adiff_t delta, + bool appzero); + + +/// Get offset within a structure if the operand refers to structure. +/// Ex: +/// \v{mov ax, somedata.field5-2 (before it was max ax, 3)} +/// for this instruction, op #1 the function will return +/// - disp: the value of 'field5', i.e. 5 +/// - delta: -2 +/// - path: the existing path if any +/// \param disp pointer to displacement (answer will be here) +/// \param delta pointer to displacement delta (answer will be here) +/// \param path existing strpath (if any) +/// \param ea linear address of instruction/data +/// \param n number of operand +/// \return if success, then length of path + 1. +/// if failed, then 0. + +idaman int ida_export get_struct_operand( + adiff_t *disp, + adiff_t *delta, + tid_t *path, + ea_t ea, + int n); + + +/// \name Work with publicness of a name +//@{ +idaman bool ida_export is_public_name(ea_t ea); +idaman void ida_export make_name_public(ea_t ea); +idaman void ida_export make_name_non_public(ea_t ea); +//@} + + +/// \name Work with weak names. +//@{ +idaman bool ida_export is_weak_name(ea_t ea); +idaman void ida_export make_name_weak(ea_t ea); +idaman void ida_export make_name_non_weak(ea_t ea); +//@} + +/// \name Work with the list of names +//@{ + +/// Get number of names in the list + +idaman size_t ida_export get_nlist_size(void); + +/// Get index of the name in the list +/// \warning returns the closest match. +/// may return idx >= size. + +idaman size_t ida_export get_nlist_idx(ea_t ea); + +/// Is the name included into the name list? + +idaman bool ida_export is_in_nlist(ea_t ea); + +/// Get address from the list at 'idx' + +idaman ea_t ida_export get_nlist_ea(size_t idx); + +/// Get name using idx + +idaman const char *ida_export get_nlist_name(size_t idx); + +/// Rebuild the name list + +idaman void ida_export rebuild_nlist(void); +//@} + +/// Renumber dummy names + +idaman void ida_export reorder_dummy_names(void); + +/// Specify strategy for retrieving debug names +enum debug_name_how_t +{ + DEBNAME_EXACT, ///< find a name at exactly the specified address + DEBNAME_LOWER, ///< find a name with the address >= the specified address + DEBNAME_UPPER, ///< find a name with the address > the specified address + DEBNAME_NICE, ///< find a name with the address <= the specified address +}; + +/// ea, name pair +struct ea_name_t +{ + ea_t ea; + qstring name; + ea_name_t(void) : ea(BADADDR) {} + ea_name_t(ea_t _ea, const qstring &_name) : ea(_ea), name(_name) {} +}; +DECLARE_TYPE_AS_MOVABLE(ea_name_t); +typedef qvector<ea_name_t> ea_name_vec_t; ///< vector of ea,name pairs + +/// \name Debug names +/// Debug names exist during the debugging session. +/// The kernel does not verify them for anything and happily accepts +/// any string as a name. +//@{ +idaman int ida_export set_debug_names(const ea_t *addrs, const char *const *names, int qty); +idaman bool ida_export set_debug_name(ea_t ea, const char *name); +idaman ssize_t ida_export get_debug_name( + qstring *out, + ea_t *ea_ptr, + debug_name_how_t how); +idaman void ida_export del_debug_names(ea_t ea1, ea_t ea2); +idaman ea_t ida_export get_debug_name_ea(const char *name); +idaman void ida_export get_debug_names(ea_name_vec_t *names, ea_t ea1, ea_t ea2); +//@} + + +enum demreq_type_t +{ + DQT_NPURGED_8 = -8, // only calculate number of purged bytes (sizeof(arg)==8) + DQT_NPURGED_4 = -4, // only calculate number of purged bytes (sizeof(arg)==4) + DQT_NPURGED_2 = -2, // only calculate number of purged bytes (sizeof(arg)==2) + DQT_COMPILER = 0, // only detect compiler that generated the name + DQT_NAME_TYPE = 1, // only detect the name type (data/code) + DQT_FULL = 2, // really demangle +}; + +/// Demangle a name. +/// \param out output buffer +/// \param name name to demangle +/// \param disable_mask bits to inhibit parts of demangled name (see \ref MNG_). +/// by the M_COMPILER bits a specific compiler can be +/// selected (see \ref MT_). +/// \return ME_... or MT__ bitmasks from demangle.hpp + +idaman int32 ida_export demangle_name( + qstring *out, + const char *name, + uint32 disable_mask, + demreq_type_t demreq=DQT_FULL); + +/// Demangle a name. +inline qstring idaapi demangle_name( + const char *name, + uint32 disable_mask, + demreq_type_t demreq=DQT_FULL) +{ + qstring out; + demangle_name(&out, name, disable_mask, demreq); + return out; +} + + +inline int32 detect_compiler_using_demangler(const char *name) +{ + return demangle_name(NULL, name, 0, DQT_COMPILER); +} + +/// What name types to ignore +typedef int ignore_name_def_t; +const ignore_name_def_t + ignore_none = 0, + ignore_regvar = 1, + ignore_llabel = 2, + ignore_stkvar = 3, + ignore_glabel = 4; + +/// Is the name defined locally in the specified function? +/// \param pfn pointer to function +/// \param name name to check +/// \param ignore_name_def which names to ignore when checking +/// \param ea1 the starting address of the range inside the function (optional) +/// \param ea2 the ending address of the range inside the function (optional) +/// \return true if the name has been defined +idaman bool ida_export is_name_defined_locally( + func_t *pfn, + const char *name, + ignore_name_def_t ignore_name_def, + ea_t ea1=BADADDR, + ea_t ea2=BADADDR); + +// Clean a name. +// This function removes punctuation marks (underscores and dots) from both +// ends of the name, and other typical prefixes/suffixes. Name is assumed to +// have the following format: [j_][@][.][_*][imp_]name[@digits][_NN] +// \param out output buffer +// \param ea address of the name (used to remove the module name) +// if != BADADDR, the optional prefix (module name) will be +// removed +// \param name name to clean +// \param flags combination of CN_... bits +// \return true if returned a non-empty name +idaman bool ida_export cleanup_name( + qstring *out, + ea_t ea, + const char *name, + uint32 flags=0); + +#define CN_KEEP_TRAILING__DIGITS 0x01 // do not remove "_\d+" at the end of name + + +#endif // _NAME_HPP diff --git a/idasdk76/include/netnode.hpp b/idasdk76/include/netnode.hpp new file mode 100644 index 0000000..8139d5b --- /dev/null +++ b/idasdk76/include/netnode.hpp @@ -0,0 +1,1123 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _NETNODE_HPP +#define _NETNODE_HPP + +/*! \file netnode.hpp + + \brief Functions that provide the lowest level public interface to the database. + + (Namely, Btree). To learn more about Balanced Trees: + http://www.bluerwhite.org/btree/ + + We don't use Btree directly. + Instead, we have another layer built on the top of Btree. + Here is a brief explanation of this layer. + + An object called "netnode" is modeled on the top of Btree. + Each netnode has a unique id: a 32-bit value (64-bit for ida64). + Usually there is a trivial mapping of the linear addresses used in + the program to netnodes. If we have additional information about + an address (a comment is attached to it, for example), this + information is stored in the corresponding netnode. + See nalt.hpp to see how the kernel uses netnodes. + Also, some netnodes have no corresponding linear address (however, they still + have an id). They are used to store information not related to a particular + address. + + Each netnode _may_ have the following attributes: + + - a name: an arbitrary non-empty string, up to 255KB-1 bytes + + - a value: arbitrary sized object, max size is MAXSPECSIZE + + - altvals: a sparse array of 32-bit values. + indexes in this array may be 8-bit or 32-bit values + + - supvals: an array of arbitrary sized objects. (size of each + object is limited by MAXSPECSIZE) + indexes in this array may be 8-bit or 32-bit values + + - charvals: a sparse array of 8-bit values. + indexes in this array may be 8-bit or 32-bit values + + - hashvals: a hash (an associative array). + indexes in this array are strings + values are arbitrary sized (max size is MAXSPECSIZE) + + Initially a new netnode contains no information at all so no disk space + is used for it. As you add new information, the netnode grows. + + All arrays that are attached to the netnode behave in the same manner. + Initially: + - all members of altvals/charvals array are zeroes + - all members of supvals/hashvals array are undefined + + If you need to store objects bigger that MAXSPECSIZE, please note that + there are high-level functions to store arbitrary sized objects in supvals. + See setblog/getblob and other blob-related functions. + + You may use netnodes to store additional information about the program. + Limitations on the use of netnodes are the following: + + - use netnodes only if you could not find a kernel service to + store your type of information + + - do not create netnodes with valid identifier names. + Use the "$ " prefix (or any other prefix with characters not allowed + in the identifiers for the names of your netnodes. + Although you will probably not destroy anything by + accident, using already defined names for the names of your + netnodes is still discouraged. + + - you may create as many netnodes as you want (creation of an unnamed + netnode does not increase the size of the database). + however, since each netnode has a number, creating too many netnodes + could lead to the exhaustion of the netnode numbers (the numbering + starts at 0xFF000000) + + - remember that netnodes are automatically saved to the disk + by the kernel. + + Advanced info: + + In fact a netnode may contain up to 256 arrays of arbitrary sized + objects (not only the 4 listed above). Each array has an 8-bit tag. + Usually tags are represented by character constants. For example, altvals + and supvals are simply 2 of 256 arrays, with the tags 'A' and 'S' respectively. + +*/ + +#include <range.hpp> + +//-------------------------------------------------------------------------- +/// Maximum length of a netnode name. WILL BE REMOVED IN THE FUTURE +const int MAXNAMESIZE = 512; + +/// Maximum length of a name. We permit names up to 32KB-1 bytes. +const int MAX_NODENAME_SIZE = 32*1024; + +/// Maximum length of strings or objects stored in a supval array element +const int MAXSPECSIZE = 1024; + +/// \typedef{nodeidx_t, numbers are 64 bit for 64 bit IDA} +#ifdef __EA64__ +typedef uint64 nodeidx_t; +#else +typedef uint32 nodeidx_t; +#endif + +/// A number to represent a bad netnode reference +#define BADNODE nodeidx_t(-1) + +/// \defgroup nn_res Reserved netnode tags +/// Tags internally used in netnodes. You should not use them +/// for your tagged alt/sup/char/hash arrays. +//@{ +const uchar atag = 'A'; ///< Array of altvals +const uchar stag = 'S'; ///< Array of supvals +const uchar htag = 'H'; ///< Array of hashvals +const uchar vtag = 'V'; ///< Value of netnode +const uchar ntag = 'N'; ///< Name of netnode +const uchar ltag = 'L'; ///< Links between netnodes +//@} + +// Internal bit used to request ea2node() mapping of alt and sup indexes +const int NETMAP_IDX = 0x100; +// Internal bit used to request ea2node() mapping of alt values. +// Such values are stored after being incremented by one. +const int NETMAP_VAL = 0x200; +// Internal bit used to make sure a string obtained with getblob() is +// null-terminated. +const int NETMAP_STR = 0x400; +// Internal bit: use 8-bit indexes. +const int NETMAP_X8 = 0x800; +// Internal bit: use 8-bit values. +const int NETMAP_V8 = 0x1000; + +/// visitor to be used by altadjust2 to skip the adjustment of some altvals +struct altadjust_visitor_t +{ + virtual bool should_skip(nodeidx_t ea) = 0; +}; + +/// \name Helper functions +/// They should not be called directly! See ::netnode +//@{ +class netnode; +class linput_t; +idaman bool ida_export netnode_check(netnode *, const char *name, size_t namlen, bool create); +idaman void ida_export netnode_kill(netnode *); +idaman bool ida_export netnode_start(netnode *); +idaman bool ida_export netnode_end(netnode *); +idaman bool ida_export netnode_next(netnode *); +idaman bool ida_export netnode_prev(netnode *); +idaman ssize_t ida_export netnode_get_name(nodeidx_t num, qstring *out); +idaman bool ida_export netnode_rename(nodeidx_t num, const char *newname, size_t namlen); +idaman ssize_t ida_export netnode_valobj(nodeidx_t num, void *buf, size_t bufsize); +idaman ssize_t ida_export netnode_valstr(nodeidx_t num, char *buf, size_t bufsize); +idaman ssize_t ida_export netnode_qvalstr(nodeidx_t num, qstring *buf); +idaman bool ida_export netnode_set(nodeidx_t num, const void *value, size_t length); +idaman bool ida_export netnode_delvalue(nodeidx_t num); +idaman nodeidx_t ida_export netnode_altval(nodeidx_t num, nodeidx_t alt, int tag); +idaman uchar ida_export netnode_charval(nodeidx_t num, nodeidx_t alt, int tag); +idaman nodeidx_t ida_export netnode_altval_idx8(nodeidx_t num, uchar alt, int tag); +idaman uchar ida_export netnode_charval_idx8(nodeidx_t num, uchar alt, int tag); +idaman ssize_t ida_export netnode_supval(nodeidx_t num, nodeidx_t alt, void *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_supstr(nodeidx_t num, nodeidx_t alt, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qsupstr(nodeidx_t num, qstring *buf, nodeidx_t alt, int tag); +idaman bool ida_export netnode_supset(nodeidx_t num, nodeidx_t alt, const void *value, size_t length, int tag); +idaman bool ida_export netnode_supdel(nodeidx_t num, nodeidx_t alt, int tag); +idaman nodeidx_t ida_export netnode_lower_bound(nodeidx_t num, nodeidx_t cur, int tag); +idaman nodeidx_t ida_export netnode_supfirst(nodeidx_t num, int tag); +idaman nodeidx_t ida_export netnode_supnext(nodeidx_t num, nodeidx_t cur, int tag); +idaman nodeidx_t ida_export netnode_suplast(nodeidx_t num, int tag); +idaman nodeidx_t ida_export netnode_supprev(nodeidx_t num, nodeidx_t cur, int tag); +idaman ssize_t ida_export netnode_supval_idx8(nodeidx_t num, uchar alt, void *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_supstr_idx8(nodeidx_t num, uchar alt, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qsupstr_idx8(nodeidx_t num, qstring *buf, uchar alt, int tag); +idaman bool ida_export netnode_supset_idx8(nodeidx_t num, uchar alt, const void *value, size_t length, int tag); +idaman bool ida_export netnode_supdel_idx8(nodeidx_t num, uchar alt, int tag); +idaman nodeidx_t ida_export netnode_lower_bound_idx8(nodeidx_t num, uchar alt, int tag); +idaman nodeidx_t ida_export netnode_supfirst_idx8(nodeidx_t num, int tag); +idaman nodeidx_t ida_export netnode_supnext_idx8(nodeidx_t num, uchar alt, int tag); +idaman nodeidx_t ida_export netnode_suplast_idx8(nodeidx_t num, int tag); +idaman nodeidx_t ida_export netnode_supprev_idx8(nodeidx_t num, uchar alt, int tag); +idaman bool ida_export netnode_supdel_all(nodeidx_t num, int tag); +idaman int ida_export netnode_supdel_range(nodeidx_t num, nodeidx_t idx1, nodeidx_t idx2, int tag); +idaman int ida_export netnode_supdel_range_idx8(nodeidx_t num, nodeidx_t idx1, nodeidx_t idx2, int tag); +idaman ssize_t ida_export netnode_hashval(nodeidx_t num, const char *idx, void *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_hashstr(nodeidx_t num, const char *idx, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qhashstr(nodeidx_t num, qstring *buf, const char *idx, int tag); +idaman nodeidx_t ida_export netnode_hashval_long(nodeidx_t num, const char *idx, int tag); +idaman bool ida_export netnode_hashset(nodeidx_t num, const char *idx, const void *value, size_t length, int tag); +idaman bool ida_export netnode_hashdel(nodeidx_t num, const char *idx, int tag); +idaman ssize_t ida_export netnode_hashfirst(nodeidx_t num, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qhashfirst(nodeidx_t num, qstring *buf, int tag); +idaman ssize_t ida_export netnode_hashnext(nodeidx_t num, const char *idx, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qhashnext(nodeidx_t num, qstring *buf, const char *idx, int tag); +idaman ssize_t ida_export netnode_hashlast(nodeidx_t num, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qhashlast(nodeidx_t num, qstring *buf, int tag); +idaman ssize_t ida_export netnode_hashprev(nodeidx_t num, const char *idx, char *buf, size_t bufsize, int tag); +idaman ssize_t ida_export netnode_qhashprev(nodeidx_t num, qstring *buf, const char *idx, int tag); +idaman size_t ida_export netnode_blobsize(nodeidx_t num, nodeidx_t start, int tag); +idaman void *ida_export netnode_getblob(nodeidx_t num, void *buf, size_t *bufsize, nodeidx_t start, int tag); +idaman ssize_t ida_export netnode_qgetblob(nodeidx_t num, bytevec_t *buf, size_t elsize, nodeidx_t start, int tag); +idaman bool ida_export netnode_setblob(nodeidx_t num, const void *buf, size_t size, nodeidx_t start, int tag); +idaman int ida_export netnode_delblob(nodeidx_t num, nodeidx_t start, int tag); +idaman bool ida_export netnode_inited(void); +idaman bool ida_export netnode_is_available(void); +idaman size_t ida_export netnode_copy(nodeidx_t num, nodeidx_t count, nodeidx_t target, bool move); +idaman size_t ida_export netnode_altshift(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, int tag); +idaman size_t ida_export netnode_charshift(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, int tag); +idaman size_t ida_export netnode_supshift(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, int tag); +idaman void ida_export netnode_altadjust(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, bool (idaapi *should_skip)(nodeidx_t ea)); +idaman void ida_export netnode_altadjust2(nodeidx_t num, nodeidx_t from, nodeidx_t to, nodeidx_t size, altadjust_visitor_t &av); +idaman bool ida_export netnode_exist(const netnode &n); +//@} + +//-------------------------------------------------------------------------- +// N E T N O D E +//-------------------------------------------------------------------------- + +/// Definition of the IDA database node. +/// Note that the size of the 'netnode' class is 4 bytes and it can be +/// freely casted to 'uint32' and back. This makes it easy to store +/// information about the program location in the netnodes. +/// Please pass netnodes to functions by value. +class netnode +{ + /// \cond + friend class netlink; + /// \endcond +public: + + //-------------------------------------------------------------------------- + /// \name Constructors, conversions and assignments + //@{ + + /// Constructor to create a netnode to access information about the + /// specified linear address (possibly missing) + netnode(nodeidx_t num=BADNODE) { netnodenumber = num; } + + /// Conversion from netnode to a linear address + operator nodeidx_t() const { return netnodenumber; } + + /// Construct an instance of netnode class to access the specified netnode. + /// \param _name name of netnode + /// \param namlen length of the name. may be omitted, in this + /// case the length will be calculated with strlen() + /// \param do_create true: create the netnode if it doesn't exist yet. + /// false: don't create the netnode, set netnumber to #BADNODE if + /// it doesn't exist + netnode(const char *_name, size_t namlen=0, bool do_create=false) + { + netnode_check(this, _name, namlen, do_create); + } + + //@} + + /// Does the specified netnode exist?. + /// \retval true there is some information attached to the netnode. + /// \retval false unnamed netnode without any information + friend bool exist(const netnode &n) { return netnode_exist(n); } + + /// Does the netnode with the specified netnode exist? + static bool exist(const char *_name) { return netnode(_name) != BADNODE; } + + //-------------------------------------------------------------------------- + /// \name Create/Delete + /// \note You can check if a netnode already exists with exist() + //@{ + + /// Create a named netnode. + /// \param _name name of netnode to create. + /// names of user-defined netnodes must have the "$ " prefix + /// in order to avoid clashes with program byte names. + /// \param namlen length of the name. if not specified, it will be + /// calculated using strlen() + /// \retval 1 ok, the node is created + /// \retval 0 the node already exists. you may use the netnode class to access it. + bool create(const char *_name, size_t namlen=0) + { + return netnode_check(this, _name, namlen, true); + } + + /// Create unnamed netnode. + /// \retval 1 ok + /// \retval 0 should not happen, indicates internal error + bool create(void) { return create(nullptr); } + + /// Delete a netnode with all information attached to it + void kill(void) { netnode_kill(this); } + + //@} + + //-------------------------------------------------------------------------- + /// \name Netnode names + //@{ + + /// Get the netnode name. + /// \return -1 if netnode is unnamed (buf is untouched in this case), + /// otherwise the name length + ssize_t get_name(qstring *buf) const + { + return netnode_get_name(*this, buf); + } + + /// Rename a netnode. + /// \param newname new name of netnode. nullptr or "" means to delete name. + /// names of user-defined netnodes must have the "$ " prefix + /// in order to avoid clashes with program byte names. + /// \param namlen length of new name. if not specified, it will be + /// calculated using strlen() + /// \retval 1 ok + /// \retval 0 failed, newname is already used + bool rename(const char *newname, size_t namlen=0) + { + return netnode_rename(*this, newname, namlen); + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Value of netnode + //@{ + + /// Get value of netnode. + /// Netnode values are arbitrary sized objects with max size is #MAXSPECSIZE. + /// NB: do not use this function for strings - see valstr(). + /// \return length of value, -1 if no value present + ssize_t valobj(void *buf, size_t bufsize) const + { + return netnode_valobj(*this, buf, bufsize); + } + + /// Get string value of netnode. + /// See explanations for supstr() function about the differences between valobj() + /// and valstr() + /// \return length of value, -1 if no value present + ssize_t valstr(qstring *buf) const + { + return netnode_qvalstr(*this, buf); + } + + /// \sa valstr(qstring *buf) const + ssize_t valstr(char *buf, size_t bufsize) const + { + return netnode_valstr(*this, buf, bufsize); + } + + /// Set value of netnode. + /// \param value pointer to value + /// \param length length of value. if not specified, it will be calculated + /// using strlen() + /// \returns 1 - ok + bool set(const void *value, size_t length=0) + { + return netnode_set(*this, value, length); + } + + /// Delete value of netnode. + /// \retval 1 ok + /// \retval 0 failed, netnode is bad or other error + bool delvalue(void) + { + return netnode_delvalue(*this); + } + + /// Value of netnode as a long number: + bool set_long(nodeidx_t x) { return set(&x, sizeof(x)); } + bool value_exists(void) const { return valobj(nullptr, 0) >= 0; } + nodeidx_t long_value(void) const + { + nodeidx_t v = 0; + if ( valobj(&v, sizeof(v)) > 0 ) + return v; + return BADNODE; + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Arrays of altvals. + /// altvals: a sparse array of 32-bit values. + /// indexes in this array may be 8-bit or 32-bit values + //@{ + + /// Get altval element of the specified array. + /// \param alt index into array of altvals + /// \param tag tag of array. may be omitted + /// \return value of altval element. nonexistent altval members are returned + /// as zeroes + nodeidx_t altval(nodeidx_t alt, uchar tag=atag) const + { + return netnode_altval(*this, alt, tag); + } + nodeidx_t altval_ea(ea_t ea, uchar tag=atag) const + { + return netnode_altval(*this, ea, tag|NETMAP_IDX); + } + + /// Set value of altval array. + /// \param alt index into array of altvals + /// \param value new value of altval element + /// \param tag tag of array + /// \retval 1 ok + /// \retval 0 failed, normally should not occur + bool altset(nodeidx_t alt, nodeidx_t value, uchar tag=atag) + { + return netnode_supset(*this, alt, &value, sizeof(value), tag); + } + bool altset_ea(ea_t ea, nodeidx_t value, uchar tag=atag) + { + return netnode_supset(*this, ea, &value, sizeof(value), tag|NETMAP_IDX); + } + + /// Delete element of altval array. + /// \param alt index into array of altvals + /// \param tag tag of array + /// \retval 1 ok + /// \retval 0 failed, element doesn't exist + bool altdel(nodeidx_t alt, uchar tag=atag) + { + return netnode_supdel(*this, alt, tag); + } + bool altdel_ea(ea_t ea, uchar tag=atag) + { + return netnode_supdel(*this, ea, tag|NETMAP_IDX); + } + + /// Store/retrieve/delete an address value in the netnode that corresponds + /// to an address. + bool easet(ea_t ea, ea_t addr, uchar tag) + { + return netnode_supset(*this, ea, &addr, sizeof(addr), tag|NETMAP_IDX|NETMAP_VAL); + } + ea_t eaget(ea_t ea, uchar tag) const + { + return netnode_altval(*this, ea, tag|NETMAP_IDX|NETMAP_VAL); + } + bool eadel(ea_t ea, uchar tag) + { + return netnode_supdel(*this, ea, tag|NETMAP_IDX); + } + + bool easet_idx(nodeidx_t idx, ea_t addr, uchar tag) + { + return netnode_supset(*this, idx, &addr, sizeof(addr), tag|NETMAP_VAL); + } + ea_t eaget_idx(nodeidx_t idx, uchar tag) + { + return netnode_altval(*this, idx, tag|NETMAP_VAL); + } + + bool easet_idx8(uchar idx, ea_t addr, uchar tag) + { + return netnode_supset_idx8(*this, idx, &addr, sizeof(addr), tag|NETMAP_VAL); + } + ea_t eaget_idx8(uchar idx, uchar tag) const + { + return netnode_altval_idx8(*this, idx, tag|NETMAP_VAL); + } + bool eadel_idx8(uchar idx, uchar tag) + { + return netnode_supdel_idx8(*this, idx, tag); + } + + /// Get first existing element of altval array. + /// \param tag tag of array + /// \return index of first existing element of altval array, + /// #BADNODE if altval array is empty + nodeidx_t altfirst(uchar tag=atag) const + { + return supfirst(tag); + } + + /// Get next existing element of altval array. + /// \param cur current index + /// \param tag tag of array + /// \return index of the next existing element of altval array, + /// #BADNODE if no more altval array elements exist + nodeidx_t altnext(nodeidx_t cur, uchar tag=atag) const + { + return supnext(cur, tag); + } + + /// Get last element of altval array. + /// \param tag tag of array + /// \return index of last existing element of altval array, + /// #BADNODE if altval array is empty + nodeidx_t altlast(uchar tag=atag) const + { + return suplast(tag); + } + + /// Get previous existing element of altval array. + /// \param cur current index + /// \param tag tag of array + /// \return index of the previous existing element of altval array, + /// #BADNODE if no more altval array elements exist + nodeidx_t altprev(nodeidx_t cur, uchar tag=atag) const + { + return supprev(cur, tag); + } + + /// Shift the altval array elements. + /// Moves the array elements at (from..from+size) to (to..to+size) + /// \return number of shifted elements + size_t altshift(nodeidx_t from, nodeidx_t to, nodeidx_t size, uchar tag=atag) + { + return netnode_altshift(*this, from, to, size, tag); + } + + /// Adjust values of altval arrays elements. + /// All altvals in the range from+1..from+size+1 and adjusted to have + /// values in the range to+1..to+size+1. + /// The parameter should_skip() can be used to skip the adjustment of some altvals + void altadjust(nodeidx_t from, nodeidx_t to, nodeidx_t size, bool (idaapi *should_skip)(nodeidx_t ea)=nullptr) + { + netnode_altadjust(*this, from, to, size, should_skip); + } + void altadjust2(nodeidx_t from, nodeidx_t to, nodeidx_t size, altadjust_visitor_t &av) + { + netnode_altadjust2(*this, from, to, size, av); + } + + + //@} + + /// \name Arrays of altvals: 8-bit values + /// The following functions behave in the same manner as the functions + /// described above. The only difference is that the array value is 8-bits. + /// - index: 32 bits + /// - value: 8 bits + //@{ + uchar charval(nodeidx_t alt, uchar tag) const { return netnode_charval(*this, alt, tag); } + bool charset(nodeidx_t alt, uchar val, uchar tag) { return supset(alt, &val, sizeof(val), tag); } + bool chardel(nodeidx_t alt, uchar tag) { return supdel(alt, tag); } + uchar charval_ea(ea_t ea, uchar tag) const { return netnode_charval(*this, ea, tag|NETMAP_IDX); } + bool charset_ea(ea_t ea, uchar val, uchar tag) { return netnode_supset(*this, ea, &val, sizeof(val), tag|NETMAP_IDX); } + bool chardel_ea(ea_t ea, uchar tag) { return netnode_supdel(*this, ea, tag|NETMAP_IDX); } + nodeidx_t charfirst(uchar tag) const { return supfirst(tag); } + nodeidx_t charnext(nodeidx_t cur, uchar tag) const { return supnext(cur, tag); } + nodeidx_t charlast(uchar tag) const { return suplast(tag); } + nodeidx_t charprev(nodeidx_t cur, uchar tag) const { return supprev(cur, tag); } + size_t charshift(nodeidx_t from, nodeidx_t to, nodeidx_t size, uchar tag) + { return netnode_charshift(*this, from, to, size, tag); } + //@} + + /// \name Arrays of altvals: 8-bit indexes + /// Another set of functions to work with altvals. + /// The only difference is that the array index is 8-bits, + /// and therefore the array may contain up to 256 elements only. + /// - index: 8 bits + /// - value: 32 bits + //@{ + nodeidx_t altval_idx8(uchar alt, uchar tag) const { return netnode_altval_idx8(*this, alt, tag); } + bool altset_idx8(uchar alt, nodeidx_t val, uchar tag) { return supset_idx8(alt, &val, sizeof(val), tag); } + bool altdel_idx8(uchar alt, uchar tag) { return supdel_idx8(alt, tag); } + nodeidx_t altfirst_idx8(uchar tag) const { return supfirst_idx8(tag); } + nodeidx_t altnext_idx8(uchar cur, uchar tag) const { return supnext_idx8(cur, tag); } + nodeidx_t altlast_idx8(uchar tag) const { return suplast_idx8(tag); } + nodeidx_t altprev_idx8(uchar cur, uchar tag) const { return supprev_idx8(cur, tag); } + //@} + + /// \name More altvals + /// Another set of functions to work with altvals. + /// - index: 8 bits + /// - value: 8 bits + //@{ + uchar charval_idx8(uchar alt, uchar tag) const { return netnode_charval_idx8(*this, alt, tag); } + bool charset_idx8(uchar alt, uchar val, uchar tag) { return supset_idx8(alt, &val, sizeof(val), tag); } + //-V::524 equivalent functions + bool chardel_idx8(uchar alt, uchar tag) { return supdel_idx8(alt, tag); } + nodeidx_t charfirst_idx8(uchar tag) const { return supfirst_idx8(tag); } + nodeidx_t charnext_idx8(uchar cur, uchar tag) const { return supnext_idx8(cur, tag); } + nodeidx_t charlast_idx8(uchar tag) const { return suplast_idx8(tag); } + nodeidx_t charprev_idx8(uchar cur, uchar tag) const { return supprev_idx8(cur, tag); } + //@} + + /// \name Delete altvals + /// \note To delete range of elements in an altval array, see supdel_range() + //@{ + + /// Delete all elements of altval array. + /// This function may be applied to 32-bit and 8-bit altval arrays. + /// This function deletes the whole altval array. + /// \return success + bool altdel(void) + { + return supdel_all(atag); + } + + /// Delete all elements of the specified altval array. + /// This function may be applied to 32-bit and 8-bit altval arrays. + /// This function deletes the whole altval array. + /// \param tag tag of array + /// \return success + bool altdel_all(uchar tag=atag) + { + return supdel_all(tag); + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Arrays of supvals + /// supvals: an array of arbitrary sized objects. + /// (size of each object is limited by #MAXSPECSIZE). + /// indexes in this array may be 8-bit or 32-bit values. + //@{ + + /// Get value of the specified supval array element. + /// NB: do not use this function to retrieve strings, see supstr()! + /// \param alt index into array of supvals + /// \param buf output buffer, may be nullptr + /// \param bufsize size of output buffer + /// \param tag tag of array. Default: stag + /// \return size of value, -1 if element doesn't exist + ssize_t supval(nodeidx_t alt, void *buf, size_t bufsize, uchar tag=stag) const + { return netnode_supval(*this, alt, buf, bufsize, tag); } + ssize_t supval_ea(ea_t ea, void *buf, size_t bufsize, uchar tag=stag) const + { return netnode_supval(*this, ea, buf, bufsize, tag|NETMAP_IDX); } + + /// Get string value of the specified supval array element. + /// The differences between supval() and supstr() are the following: + /// -# Strings are stored with the terminating zero in the old databases. + /// supval() returns the exact size of the stored object (with + /// the terminating zero) but supstr returns the string length without + /// the terminating zero. supstr() can handle strings stored with or + /// without the terminating zero. + /// -# supstr() makes sure that the string is terminated with 0 even if + /// the string was stored in the database without it or the output + /// buffer is too small to hold the entire string. In the latter case + /// the string will be truncated but still will have the terminating zero. + /// + /// If you do not use the string length returned by supval/supstr() functions + /// and you are sure that the output buffer is big enough to hold the entire + /// string and the string has been stored in the database with the terminating + /// zero, then you can continue to use supval() instead of supstr(). + /// + /// \param buf output buffer, may be nullptr + /// \param alt index into array of supvals + /// \param tag tag of array. Default: stag + /// \return length of the output string, -1 if element doesn't exist + ssize_t supstr(qstring *buf, nodeidx_t alt, uchar tag=stag) const + { return netnode_qsupstr(*this, buf, alt, tag); } + ssize_t supstr_ea(qstring *buf, ea_t ea, uchar tag=stag) const + { return netnode_qsupstr(*this, buf, ea, tag|NETMAP_IDX); } + + /// \sa supstr(qstring *buf, nodeidx_t alt, uchar tag=stag) const + ssize_t supstr(nodeidx_t alt, char *buf, size_t bufsize, uchar tag=stag) const + { return netnode_supstr(*this, alt, buf, bufsize, tag); } + ssize_t supstr_ea(ea_t ea, char *buf, size_t bufsize, uchar tag=stag) const + { return netnode_supstr(*this, ea, buf, bufsize, tag|NETMAP_IDX); } + + /// Set value of supval array element. + /// \param alt index into array of supvals + /// \param value pointer to supval value + /// \param length length of 'value'. If not specified, the length is calculated + /// using strlen()+1. + /// \param tag tag of array + /// \retval 1 ok + /// \retval 0 should not occur - indicates internal error + bool supset(nodeidx_t alt, const void *value, size_t length=0, uchar tag=stag) + { return netnode_supset(*this, alt, value, length, tag); } + bool supset_ea(ea_t ea, const void *value, size_t length=0, uchar tag=stag) + { return netnode_supset(*this, ea, value, length, tag|NETMAP_IDX); } + + /// Delete supval element. + /// \param alt index into array of supvals + /// \param tag tag of array + /// \retval true deleted + /// \retval false element does not exist + bool supdel(nodeidx_t alt, uchar tag=stag) + { return netnode_supdel(*this, alt, tag); } + bool supdel_ea(ea_t ea, uchar tag=stag) + { return netnode_supdel(*this, ea, tag|NETMAP_IDX); } + + /// Get lower bound of existing elements of supval array. + /// \param cur current index + /// \param tag tag of array + /// \return index of first existing element of supval array >= cur + /// #BADNODE if supval array is empty + nodeidx_t lower_bound(nodeidx_t cur, uchar tag=stag) const + { return netnode_lower_bound(*this, cur, tag); } + nodeidx_t lower_bound_ea(ea_t ea, uchar tag=stag) const + { return netnode_lower_bound(*this, ea, tag|NETMAP_IDX); } + + /// Get first existing element of supval array. + /// \param tag tag of array + /// \return index of first existing element of supval array, + /// #BADNODE if supval array is empty + nodeidx_t supfirst(uchar tag=stag) const + { return netnode_supfirst(*this, tag); } + + /// Get next existing element of supval array. + /// \param cur current index + /// \param tag tag of array + /// \return index of the next existing element of supval array, + /// #BADNODE if no more supval array elements exist + nodeidx_t supnext(nodeidx_t cur, uchar tag=stag) const + { return netnode_supnext(*this, cur, tag); } + + /// Get last existing element of supval array. + /// \param tag tag of array + /// \return index of last existing element of supval array, + /// #BADNODE if supval array is empty + nodeidx_t suplast(uchar tag=stag) const + { return netnode_suplast(*this, tag); } + + /// Get previous existing element of supval array. + /// \param cur current index + /// \param tag tag of array + /// \return index of the previous existing element of supval array + /// #BADNODE if no more supval array elements exist + nodeidx_t supprev(nodeidx_t cur, uchar tag=stag) const + { return netnode_supprev(*this, cur, tag); } + + + /// Shift the supval array elements. + /// Moves the array elements at (from..from+size) to (to..to+size) + /// \return number of shifted elements + size_t supshift(nodeidx_t from, nodeidx_t to, nodeidx_t size, uchar tag=stag) + { return netnode_supshift(*this, from, to, size, tag); } + + //@} + + /// \name Arrays of supvals: 8-bit indexes + /// The following functions behave in the same manner as the functions + /// described above. The only difference is that the array index is 8-bits + /// and therefore the array may contains up to 256 elements only. + //@{ + ssize_t supval_idx8(uchar alt, void *buf, size_t bufsize, uchar tag) const { return netnode_supval_idx8(*this, alt, buf, bufsize, tag); } + ssize_t supstr_idx8(uchar alt, char *buf, size_t bufsize, uchar tag) const { return netnode_supstr_idx8(*this, alt, buf, bufsize, tag); } + ssize_t supstr_idx8(qstring *buf, uchar alt, uchar tag) const { return netnode_qsupstr_idx8(*this, buf, alt, tag); } + bool supset_idx8(uchar alt, const void *value, size_t length, uchar tag) { return netnode_supset_idx8(*this, alt, value, length, tag); } + bool supdel_idx8(uchar alt, uchar tag) { return netnode_supdel_idx8(*this, alt, tag); } + nodeidx_t lower_bound_idx8(uchar alt, uchar tag) const { return netnode_lower_bound_idx8(*this, alt, tag); } + nodeidx_t supfirst_idx8(uchar tag) const { return netnode_supfirst_idx8(*this, tag); } + nodeidx_t supnext_idx8(uchar alt, uchar tag) const { return netnode_supnext_idx8(*this, alt, tag); } + nodeidx_t suplast_idx8(uchar tag) const { return netnode_suplast_idx8(*this, tag); } + nodeidx_t supprev_idx8(uchar alt, uchar tag) const { return netnode_supprev_idx8(*this, alt, tag); } + //@} + + /// \name Delete supvals + //@{ + + /// Delete all elements of supval array. + /// This function may be applied to 32-bit and 8-bit supval arrays. + /// This function deletes the whole supval array. + /// \return success + bool supdel(void) + { + return supdel_all(stag); + } + + /// Delete all elements of the specified supval array. + /// This function may be applied to 32-bit and 8-bit supval arrays. + /// This function deletes the whole supval array. + /// \return success + bool supdel_all(uchar tag) + { + return netnode_supdel_all(*this, tag); + } + + /// Delete range of elements in the specified supval array. + /// Elements in range [idx1, idx2) will be deleted. + /// \note This function can also be used to delete a range of altval elements + /// \param idx1 first element to delete + /// \param idx2 last element to delete + 1 + /// \param tag tag of array + /// \return number of deleted elements + int supdel_range(nodeidx_t idx1, nodeidx_t idx2, uchar tag) + { + return netnode_supdel_range(*this, idx1, idx2, tag); + } + /// Same as above, but accepts 8-bit indexes + int supdel_range_idx8(uchar idx1, uchar idx2, uchar tag) + { + return netnode_supdel_range_idx8(*this, idx1, idx2, tag); + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Hashes + /// Associative arrays indexed by strings. + /// hashvals: Indexes in this array are strings. + /// Values are arbitrary sized (max size is #MAXSPECSIZE) + //@{ + + /// Get value of the specified hash element. + /// \param idx index into hash + /// \param buf output buffer, may be nullptr + /// \param bufsize output buffer size + /// \param tag tag of hash. Default: htag + /// \return -1 if element doesn't exist or idx is nullptr. + /// otherwise returns the value size in bytes + ssize_t hashval(const char *idx, void *buf, size_t bufsize, uchar tag=htag) const + { return netnode_hashval(*this, idx, buf, bufsize, tag); } + + /// Similar to supstr(), but accepts a hash index + ssize_t hashstr(qstring *buf, const char *idx, uchar tag=htag) const + { return netnode_qhashstr(*this, buf, idx, tag); } + + /// \sa hashstr(qstring *buf, const char *idx, uchar tag=htag) const + ssize_t hashstr(const char *idx, char *buf, size_t bufsize, uchar tag=htag) const + { return netnode_hashstr(*this, idx, buf, bufsize, tag); } + + /// Get value of the specified hash element. + /// \param idx index into hash + /// \param tag tag of hash. Default: htag + /// \return value of hash element (it should be set using hashset(nodeidx_t)), + /// 0 if the element does not exist + nodeidx_t hashval_long(const char *idx, uchar tag=htag) const + { return netnode_hashval_long(*this, idx, tag); } + + /// Set value of hash element. + /// \param idx index into hash + /// \param value pointer to value + /// \param length length of 'value'. If not specified, the length is calculated + /// using strlen()+1. + /// \param tag tag of hash. Default: htag + /// \retval 1 ok + /// \retval 0 should not occur - indicates internal error + bool hashset(const char *idx, const void *value, size_t length=0, uchar tag=htag) + { return netnode_hashset(*this, idx, value, length, tag); } + + /// Set value of hash element to long value. + /// \param idx index into hash + /// \param value new value of hash element + /// \param tag tag of hash. Default: htag + /// \retval 1 ok + /// \retval 0 should not occur - indicates internal error + bool hashset(const char *idx, nodeidx_t value, uchar tag=htag) + { return hashset(idx, &value, sizeof(value), tag); } + + /// Delete hash element. + /// \param idx index into hash + /// \param tag tag of hash. Default: htag + /// \retval true deleted + /// \retval false element does not exist + bool hashdel(const char *idx, uchar tag=htag) + { return netnode_hashdel(*this, idx, tag); } + + /// Get first existing element of hash. + /// \note elements of hash are kept sorted in lexical order + /// \param buf output buffer, may be nullptr + /// \param tag tag of hash. Default: htag + /// \return size of index of first existing element of hash, + /// -1 if hash is empty + ssize_t hashfirst(qstring *buf, uchar tag=htag) const + { return netnode_qhashfirst(*this, buf, tag); } + + /// \sa hashfirst(qstring *buf, uchar tag=htag) const + ssize_t hashfirst(char *buf, size_t bufsize, uchar tag=htag) const + { return netnode_hashfirst(*this, buf, bufsize, tag); } + + /// Get next existing element of hash. + /// \note elements of hash are kept sorted in lexical order + /// \param buf output buffer, may be nullptr + /// \param idx current index into hash + /// \param tag tag of hash. Default: htag + /// \return size of index of the next existing element of hash, + /// -1 if no more hash elements exist + ssize_t hashnext(qstring *buf, const char *idx, uchar tag=htag) const + { return netnode_qhashnext(*this, buf, idx, tag); } + + /// \sa hashnext(qstring *buf, const char *idx, uchar tag=htag) const + ssize_t hashnext(const char *idx, char *buf, size_t bufsize, uchar tag=htag) const + { return netnode_hashnext(*this, idx, buf, bufsize, tag); } + + /// Get last existing element of hash. + /// \note elements of hash are kept sorted in lexical order + /// \param buf output buffer, may be nullptr + /// \param tag tag of hash. Default: htag + /// \return size of index of last existing element of hash, + /// -1 if hash is empty + ssize_t hashlast(qstring *buf, uchar tag=htag) const + { return netnode_qhashlast(*this, buf, tag); } + + /// \sa hashlast(qstring *buf, uchar tag=htag) const + ssize_t hashlast(char *buf, size_t bufsize, uchar tag=htag) const + { return netnode_hashlast(*this, buf, bufsize, tag); } + + /// Get previous existing element of supval array. + /// \note elements of hash are kept sorted in lexical order + /// \param buf output buffer, may be nullptr + /// \param idx current index into hash + /// \param tag tag of hash. Default: htag + /// \return size of index of the previous existing element of hash, + /// -1 if no more hash elements exist + ssize_t hashprev(qstring *buf, const char *idx, uchar tag=htag) const + { return netnode_qhashprev(*this, buf, idx, tag); } + + /// \sa hashprev(qstring *buf, const char *idx, uchar tag=htag) const + ssize_t hashprev(const char *idx, char *buf, size_t bufsize, uchar tag=htag) const + { return netnode_hashprev(*this, idx, buf, bufsize, tag); } + + /// Delete all elements of hash. + /// This function deletes the whole hash. + /// \param tag tag of hash. Default: htag + /// \return success + bool hashdel_all(uchar tag=htag) + { + return supdel_all(tag); + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Blobs + /// Virtually unlimited size binary objects. + /// Blobs are stored in several supval array elements. + //@{ + + /// Get size of blob. + /// \param _start index of the first supval element used to store blob + /// \param tag tag of supval array + /// \return number of bytes required to store a blob + size_t blobsize(nodeidx_t _start, uchar tag) + { + return netnode_blobsize(*this, _start, tag); + } + size_t blobsize_ea(ea_t ea, uchar tag) + { + return netnode_blobsize(*this, ea, tag|NETMAP_IDX); + } + + /// Get blob from a netnode. + /// \param buf buffer to read into. if nullptr, the buffer will be + /// allocated using qalloc() + /// \param[in, out] bufsize in: size of 'buf' in bytes (if buf == nullptr then meaningless). + /// out: size of the blob if it exists. + /// bufsize may be nullptr + /// \param _start index of the first supval element used to store blob + /// \param tag tag of supval array + /// \return nullptr if blob doesn't exist, + /// otherwise returns pointer to blob + void *getblob( + void *buf, + size_t *bufsize, + nodeidx_t _start, + uchar tag) + { + return netnode_getblob(*this, buf, bufsize, _start, tag); + } + void *getblob_ea( + void *buf, + size_t *bufsize, + ea_t ea, + uchar tag) + { + return netnode_getblob(*this, buf, bufsize, ea, tag|NETMAP_IDX); + } + + /// Get blob from a netnode. + /// \param blob output ::qvector buffer + /// \param _start index of the first supval element used to store blob + /// \param tag tag of supval array + /// \return -1 if blob doesn't exist, size of blob otherwise + template <class T> + ssize_t getblob( + qvector<T> *blob, + nodeidx_t _start, + uchar tag) + { + return netnode_qgetblob(*this, (bytevec_t *)blob, sizeof(T), _start, tag); + } + template <class T> + ssize_t getblob_ea( + qvector<T> *blob, + ea_t ea, + uchar tag) + { + return netnode_qgetblob(*this, (bytevec_t *)blob, sizeof(T), nodeidx_t(ea), tag|NETMAP_IDX); + } + + /// Get blob from a netnode into a qstring* and make sure the string is + /// null-terminated. + /// \param buf output ::qstring buffer + /// \param _start index of the first supval element used to store blob + /// \param tag tag of supval array + /// \return -1 if blob doesn't exist + /// size of string (including terminating null) otherwise + ssize_t getblob( + qstring *buf, + nodeidx_t _start, + uchar tag) + { + return netnode_qgetblob(*this, (bytevec_t *)buf, 1, _start, tag|NETMAP_STR); + } + + /// Store a blob in a netnode. + /// \param buf pointer to blob to save + /// \param size size of blob in bytes + /// \param _start index of the first supval element used to store blob + /// \param tag tag of supval array + /// \return success + bool setblob( + const void *buf, + size_t size, + nodeidx_t _start, + uchar tag) + { + return netnode_setblob(*this, buf, size, _start, tag); + } + bool setblob_ea( + const void *buf, + size_t size, + ea_t ea, + uchar tag) + { + return netnode_setblob(*this, buf, size, ea, tag|NETMAP_IDX); + } + + /// Delete a blob. + /// \param _start index of the first supval element used to store blob + /// \param tag tag of supval array + /// \return number of deleted supvals + int delblob(nodeidx_t _start, uchar tag) + { + return netnode_delblob(*this, _start, tag); + } + int delblob_ea(ea_t ea, uchar tag) + { + return netnode_delblob(*this, ea, tag|NETMAP_IDX); + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Enumerate all netnodes + //@{ + + /// Get first netnode in the graph. + /// Sets netnodenumber to the lowest existing number. + /// \retval true ok + /// \retval false graph is empty + bool start(void) + { + return netnode_start(this); + } + + /// Get last netnode in the graph. + /// Sets netnodenumber to the highest existing number. + /// \retval true ok + /// \retval false graph is empty + bool end(void) + { + return netnode_end(this); + } + + /// Get next netnode in the graph. + /// Sets netnodenumber to the next existing number + /// \retval true ok + /// \retval false no more netnodes + bool next(void) + { + return netnode_next(this); + } + + /// Get prev netnode in the graph. + /// Sets netnodenumber to the previous existing number + /// \retval true ok + /// \retval false no more netnodes + bool prev(void) + { + return netnode_prev(this); + } + + //@} + + //-------------------------------------------------------------------------- + /// \name Move and copy netnodes + /// \param destnode the destination netnode + /// \param count how many netnodes to copy + /// \return number of copied/moved keys, #BADNODE if failure or not enough memory + //@{ + size_t copyto(netnode destnode, nodeidx_t count=1) { return netnode_copy(netnodenumber, count, destnode.netnodenumber, false); } + size_t moveto(netnode destnode, nodeidx_t count=1) { return netnode_copy(netnodenumber, count, destnode.netnodenumber, true); } + //@} + + //-------------------------------------------------------------------------- + /// \name Netnode comparisons + //@{ + bool operator==(netnode &n) const { return netnodenumber == n.netnodenumber; } + bool operator!=(netnode &n) const { return netnodenumber != n.netnodenumber; } + bool operator==(nodeidx_t x) const { return netnodenumber == x; } + bool operator!=(nodeidx_t x) const { return netnodenumber != x; } + //@} + + + static bool inited(void) { return netnode_inited(); } + static bool is_available(void) { return netnode_is_available(); } + +private: + // The netnode number. + // Usually this is the linear address that the netnode keeps information about. + nodeidx_t netnodenumber; +}; +#ifdef __EA64__ +CASSERT(sizeof(netnode) == 8); +#else +CASSERT(sizeof(netnode) == 4); +#endif + +//----------------------------------------------------------------------- + +/// The root node is used by the kernel, do not use it directly in your modules. +/// Its name: "Root Node" +#if !defined(NO_OBSOLETE_FUNCS) || defined(__DEFINE_ROOT_NODE__) +idaman netnode ida_export_data root_node; +#endif + + +#endif // _NETNODE_HPP diff --git a/idasdk76/include/network.hpp b/idasdk76/include/network.hpp new file mode 100644 index 0000000..03c040f --- /dev/null +++ b/idasdk76/include/network.hpp @@ -0,0 +1,486 @@ +#ifndef NETWORK_HPP +#define NETWORK_HPP + +#include <pro.h> + +#ifdef __NT__ +# if !defined(AF_MAX) +# include <ws2tcpip.h> +# endif +# define SYSTEM "Windows" +# define socklen_t int +# define SHUT_RD SD_RECEIVE +# define SHUT_WR SD_SEND +# define SHUT_RDWR SD_BOTH +#else // not NT, i.e. UNIX +# include <netinet/in.h> +# include <netinet/tcp.h> +# include <arpa/inet.h> +# include <netdb.h> +# define closesocket(s) close(s) +# define SOCKET size_t +# define INVALID_SOCKET size_t(-1) +# define SOCKET_ERROR (-1) +# if defined(__LINUX__) +# if defined(__ARM__) +# if defined(__ANDROID__) +# define SYSTEM "Android" +# else +# define SYSTEM "ARM Linux" +# endif +# else +# if defined(__ANDROID__) +# define SYSTEM "Android x86" +# else +# define SYSTEM "Linux" +# endif +# endif + // linux debugger cannot be multithreaded because it uses thread_db. + // i doubt that this library is meant to be used with multiple + // applications simultaneously. +# define __SINGLE_THREADED_SERVER__ +# elif defined(__MAC__) +# define SYSTEM "Mac OS X" +# else +# error "Unknown platform" +# endif +# include <sys/socket.h> +# include <netinet/in.h> +#endif + +#ifndef __X86__ +# define _SYSBITS " 64-bit" +#else +# define _SYSBITS " 32-bit" +#endif + +#ifdef TESTABLE_BUILD +# ifdef __EA64__ +# define SYSBITS _SYSBITS " (sizeof ea=64)" +# else +# define SYSBITS _SYSBITS " (sizeof ea=32)" +# endif +#else +# define SYSBITS _SYSBITS +#endif + +#ifdef __SINGLE_THREADED_SERVER__ +# define __SERVER_TYPE__ "ST" +#else +# define __SERVER_TYPE__ "MT" +#endif + +#define TIMEOUT (1000/25) // timeout for polling (ms) +#define TIMEOUT_INFINITY -1 +#define RECV_HELLO_TIMEOUT 1000 // timeout for the first packet (ms) +#define RECV_TIMEOUT_PERIOD 10000 // timeout for recv (ms) + +// bidirectional codes (client <-> server) +enum base_packet_id_t +{ + RPC_OK = 0, // response: function call succeeded + RPC_UNK, // response: unknown function code + RPC_MEM, // response: no memory + base_packet_id_last +}; + +#define RPC_OPEN 3 // server->client: i'm ready, the very first packet + +#define RPC_EVENT 4 // server->client: debug event ready, followed by debug_event +#define RPC_EVOK 5 // client->server: event processed (in response to RPC_EVENT) +#define RPC_CANCELLED 6 // client->server: operation was cancelled by the user +// we need EVOK to handle the situation when the debug +// event was detected by the server during polling and +// was sent to the client using RPC_EVENT but client has not received it yet +// and requested GET_DEBUG_EVENT. In this case we should not +// call remote_get_debug_event() but instead force the client +// to use the event sent by RPC_EVENT. +// In other words, if the server has sent RPC_EVENT but has not +// received RPC_EVOK, it should fail all GET_DEBUG_EVENTS. + +// client->server codes +#define RPC_INIT 10 +#define RPC_TERM 11 +#define RPC_GET_PROCESSES 12 +#define RPC_START_PROCESS 13 +#define RPC_EXIT_PROCESS 14 +#define RPC_ATTACH_PROCESS 15 +#define RPC_DETACH_PROCESS 16 +#define RPC_GET_DEBUG_EVENT 17 +#define RPC_PREPARE_TO_PAUSE_PROCESS 18 +#define RPC_STOPPED_AT_DEBUG_EVENT 19 +#define RPC_CONTINUE_AFTER_EVENT 20 +#define RPC_TH_SUSPEND 21 +#define RPC_TH_CONTINUE 22 +#define RPC_SET_RESUME_MODE 23 +#define RPC_GET_MEMORY_INFO 24 +#define RPC_READ_MEMORY 25 +#define RPC_WRITE_MEMORY 26 +#define RPC_UPDATE_BPTS 27 +#define RPC_UPDATE_LOWCNDS 28 +#define RPC_EVAL_LOWCND 29 +#define RPC_ISOK_BPT 30 +#define RPC_READ_REGS 31 +#define RPC_WRITE_REG 32 +#define RPC_GET_SREG_BASE 33 +#define RPC_SET_EXCEPTION_INFO 34 + +#define RPC_OPEN_FILE 35 +#define RPC_CLOSE_FILE 36 +#define RPC_READ_FILE 37 +#define RPC_WRITE_FILE 38 +#define RPC_IOCTL 39 // both client and the server may send this packet +#define RPC_UPDATE_CALL_STACK 40 +#define RPC_APPCALL 41 +#define RPC_CLEANUP_APPCALL 42 +#define RPC_REXEC 43 +#define RPC_GET_SCATTERED_IMAGE 44 +#define RPC_GET_IMAGE_UUID 45 +#define RPC_GET_SEGM_START 46 +#define RPC_BIN_SEARCH 47 + +// server->client codes +#define RPC_SET_DEBUG_NAMES 50 +#define RPC_SYNC_STUB 51 +#define RPC_ERROR 52 +#define RPC_MSG 53 +#define RPC_WARNING 54 +#define RPC_HANDLE_DEBUG_EVENT 55 +#define RPC_REPORT_IDC_ERROR 56 +#define RPC_IMPORT_DLL 57 + +#pragma pack(push, 1) + +struct PACKED rpc_packet_t +{ // fields are always sent in the network order + uint32 length; // length of the packet (do not count length & code) + uchar code; // function code +}; +CASSERT(sizeof(rpc_packet_t) == 5); +#pragma pack(pop) + +enum rpc_notification_type_t +{ + rnt_unknown = 0, + rnt_msg, + rnt_warning, + rnt_error, +}; + +#define DEFINE_ONE_NOTIFICATION_FUNCTION(FuncName, NotifCode, RpcEngineInst) \ + AS_PRINTF(2, 3) void FuncName(const char *format, ...) \ + { \ + va_list va; \ + va_start(va, format); \ + dvnotif(NotifCode, RpcEngineInst, format, va); \ + va_end(va); \ + } + +#define DEFINE_ALL_NOTIFICATION_FUNCTIONS(RpcEngineInst) \ + DEFINE_ONE_NOTIFICATION_FUNCTION(dmsg, 0, RpcEngineInst) \ + DEFINE_ONE_NOTIFICATION_FUNCTION(dwarning, 1, RpcEngineInst) \ + DEFINE_ONE_NOTIFICATION_FUNCTION(derror, -1, RpcEngineInst) + +class rpc_engine_t; + +//------------------------------------------------------------------------- +AS_PRINTF(2, 0) ssize_t dvnotif_client( + int code, + const char *format, + va_list va); + +#ifdef __NT__ +# define IRSERR_TIMEOUT WAIT_TIMEOUT +#else +# define IRSERR_TIMEOUT ETIME +#endif +#define IRSERR_CANCELLED -0xE5CA7E // escape +#define IRSERR_SKIP_ITER -0x5217 // skip recv() in rpc_engine_t's recv_data loop + +//------------------------------------------------------------------------- +// idarpc_stream_t +//------------------------------------------------------------------------- +// the idarpc_stream_t structure is not defined. +// it is used as an opaque type provided by the transport level. +// the transport level defines its own local type for it. +struct idarpc_stream_t; + +idarpc_stream_t *irs_new(bool use_tls=false); +bool irs_init_client(idarpc_stream_t *irs, const char *hostname, int port_number); +bool irs_init_server( + idarpc_stream_t *irs, + const char *hostname, + int port_number, + const char *certchain=nullptr, + const char *privkey=nullptr); +bool irs_accept(idarpc_stream_t *irs, idarpc_stream_t *listener); +bool irs_handshake(idarpc_stream_t *irs, int timeout_ms = -1); +int irs_ready(idarpc_stream_t *irs, int timeout_ms = -1); +ssize_t irs_recv(idarpc_stream_t *irs, void *buf, size_t n); +ssize_t irs_send(idarpc_stream_t *irs, const void *buf, size_t n); +void irs_term(idarpc_stream_t **pirs, int shutdown_flags = -1); +int irs_get_error(idarpc_stream_t *irs); +const char *irs_strerror(idarpc_stream_t *irs); +bool irs_peername(idarpc_stream_t *irs, qstring *out, bool lookupname = true); +bool irs_sockname(idarpc_stream_t *irs, qstring *out, bool lookupname = true); + +enum progress_loop_ctrl_t +{ + plc_proceed, + plc_skip_iter, + plc_cancel, +}; +typedef progress_loop_ctrl_t irs_progress_cb_t(bool receiving, size_t processed, size_t total, void *); +void irs_set_progress_cb(idarpc_stream_t *irs, int ms, irs_progress_cb_t cb, void *ud=NULL); +struct irs_cancellable_op_t +{ + idarpc_stream_t *irs; + irs_cancellable_op_t(idarpc_stream_t *_irs, bool receiving, size_t goal=0); + ~irs_cancellable_op_t(); + void inc_progress(size_t progress); +}; + +//------------------------------------------------------------------------- +typedef qtime64_t utc_timestamp_t; +typedef uint64 lofi_timestamp_t; // low-fidelity timestamp. Only encodes up to 1/10th seconds + +//------------------------------------------------------------------------- +THREAD_SAFE inline lofi_timestamp_t to_lofi_timestamp(qtime64_t ts) +{ + const uint64 s = get_secs(ts); + const uint64 us = get_usecs(ts); + return s * 10 + us / (100 * 1000); +} + +//------------------------------------------------------------------------- +THREAD_SAFE inline qtime64_t from_lofi_timestamp(lofi_timestamp_t lts) +{ + return make_qtime64(lts / 10, (lts % 10) * (100 * 1000)); +} + + +//------------------------------------------------------------------------- +// base_dispatcher_t + client_handler_t +//------------------------------------------------------------------------- +struct client_handler_t +{ + FILE *channels[16]; + idarpc_stream_t *irs; + qstring peer_name; + uint32 session_id; + utc_timestamp_t session_start; + bool verbose; + + void close_all_channels(); + void clear_channels(); + int find_free_channel() const; + + client_handler_t(idarpc_stream_t *_irs, bool _verbose); + virtual ~client_handler_t(); + + virtual bool handle() = 0; // true - delete this + virtual void shutdown_gracefully(int signum) = 0; + + //lint -sem(client_handler_t::term_irs,cleanup) + void term_irs(); + + AS_PRINTF(2, 3) int lprintf(const char *format, ...) const; + +private: + DECLARE_UNCOPYABLE(client_handler_t); +}; + +//------------------------------------------------------------------------- +struct client_handlers_list_t +{ + typedef std::map<client_handler_t *, qthread_t> storage_t; + storage_t storage; + + virtual ~client_handlers_list_t() {} + virtual void lock() {} + virtual void unlock() {} + virtual bool is_multi_threaded() const { return false; } +}; + +//------------------------------------------------------------------------- +struct mt_client_handlers_list_t : public client_handlers_list_t +{ + qmutex_t mutex; + + mt_client_handlers_list_t() { mutex = qmutex_create(); QASSERT(1540, mutex != NULL); } + virtual ~mt_client_handlers_list_t() { qmutex_free(mutex); } + virtual void lock() override { qmutex_lock(mutex); } + virtual void unlock() override { qmutex_unlock(mutex); } + virtual bool is_multi_threaded() const override { return true; } +}; + +//------------------------------------------------------------------------- +struct base_dispatcher_t +{ + qstring ipv4_address; + qstring certchain; + qstring privkey; + idarpc_stream_t *irs = nullptr; + client_handlers_list_t *clients_list = nullptr; + ushort port_number = -1; + bool use_tls = false; + bool verbose = false; + + base_dispatcher_t(bool multi_threaded); + virtual ~base_dispatcher_t(); + NORETURN void dispatch(); + + virtual void collect_cliopts(cliopts_t *out); + + // + void install_signal_handlers(); + + // + virtual client_handler_t *new_client_handler(idarpc_stream_t *_irs) = 0; + void delete_client_handler(client_handler_t *inst); + + virtual void shutdown_gracefully(int signum); + + +private: + void handle_session(client_handler_t *handler); + void add_to_clients_list(client_handler_t *handler, qthread_t t); + DECLARE_UNCOPYABLE(base_dispatcher_t); +}; + +//------------------------------------------------------------------------- +// packing/unpacking utils +//------------------------------------------------------------------------- +bytevec_t prepare_rpc_packet(uchar code); +void finalize_packet(bytevec_t &pkt); +//const char *get_rpc_name(int code); + +//------------------------------------------------------------------------- +struct rpc_connection_params_t +{ + size_t cb; + qstring host; + ushort port; + bool tls; + + rpc_connection_params_t( + const char *_host=nullptr, + ushort _port=0, + bool _tls=true) + : cb(sizeof(*this)), host(_host), port(_port), tls(_tls) {} +}; + +//------------------------------------------------------------------------- +// rpc_engine_t +//------------------------------------------------------------------------- +#define VERBOSE_ENABLED +#ifdef VERBOSE_ENABLED +#define verb(x) do { if ( verbose ) msg x; } while(0) +#define verb_eng(engine, x) do { if ( (engine)->verbose ) msg x; } while(0) +#else +#define verb(x) //msg x +#define verb_eng(engine, x) +#endif +#define verbev(x) //msg x + +//------------------------------------------------------------------------- +struct rpc_packet_data_t +{ + uchar code; + + rpc_packet_data_t(uchar _code) : code(_code) {} + virtual ~rpc_packet_data_t() {} + virtual void serialize(bytevec_t *out, int version) const = 0; + virtual bool deserialize(const uchar **ptr, size_t len, int version) = 0; +}; + +//------------------------------------------------------------------------- +typedef int ioctl_handler_t( + class rpc_engine_t *rpc, + int fn, + const void *buf, + size_t size, + void **poutbuf, + ssize_t *poutsize); + +//------------------------------------------------------------------------- +typedef rpc_packet_data_t *rpc_packet_instantiator_t(const uchar *ptr, size_t len, int version); + +//------------------------------------------------------------------------- +struct rpc_packet_type_desc_t +{ + uchar code; + const char *name; + rpc_packet_instantiator_t *instantiate; +}; +DECLARE_TYPE_AS_MOVABLE(rpc_packet_type_desc_t); +typedef qvector<rpc_packet_type_desc_t> rpc_packet_type_desc_vec_t; + +//--------------------------------------------------------------------------- +class rpc_engine_t +{ +public: + bool network_error; + + // pointer to the ioctl request handler, in case you + // need to handle ioctl requests from the server. + ioctl_handler_t *ioctl_handler; + int recv_timeout; + bool is_client; + bool logged_in; + +protected: + void register_packet_type_descs(const rpc_packet_type_desc_t *ptypes, size_t cnt); + const rpc_packet_type_desc_t *find_packet_type_desc(int code) const; + const rpc_packet_type_desc_t *find_packet_type_desc(const char *name) const; + +public: + rpc_engine_t(bool is_client); + virtual ~rpc_engine_t() {} + + int handle_ioctl_packet(bytevec_t &pkt, const uchar *ptr, const uchar *end); + + // low-level: deal with bytes, and don't handle "conversations". + int send_data(bytevec_t &data); + rpc_packet_t *recv_packet(); + + virtual rpc_packet_t *send_request_and_receive_reply(bytevec_t &pkt) = 0; + + virtual idarpc_stream_t *get_irs() const = 0; + AS_PRINTF(3, 0) virtual ssize_t send_notif(int code, const char *format, va_list va); + + virtual bool get_broken_connection(void) { return false; } + virtual void set_broken_connection(void) {} + + int send_ioctl(int fn, const void *buf, size_t size, void **poutbuf, ssize_t *poutsize); + void set_ioctl_handler(ioctl_handler_t *h) { ioctl_handler = h; } + + DEFINE_ALL_NOTIFICATION_FUNCTIONS(this); + +private: + rpc_packet_type_desc_vec_t ptypes; + + int recv_data(void *out, size_t len); + + AS_PRINTF(3,0) static ssize_t dvnotif(int code, rpc_engine_t *rpc, const char *format, va_list va); +}; + +//------------------------------------------------------------------------- +AS_PRINTF(3, 0) ssize_t dvnotif_rpc( + int code, + rpc_engine_t *rpc, + const char *format, + va_list va); + +//--------------------------------------------------------------------------- +AS_PRINTF(1, 0) int vlprintf(const char *format, va_list va); +AS_PRINTF(1, 2) int lprintf(const char *format, ...); +void set_lprintf_output(FILE *out); + +//--------------------------------------------------------------------------- +THREAD_SAFE inline size_t format_timestamp(char *buf, size_t bufsize, qtime64_t ts) +{ + return qstrftime64(buf, bufsize, "%Y-%m-%d %H:%M:%S", ts); +} + +#endif // NETWORK_HPP diff --git a/idasdk76/include/offset.hpp b/idasdk76/include/offset.hpp new file mode 100644 index 0000000..0efa237 --- /dev/null +++ b/idasdk76/include/offset.hpp @@ -0,0 +1,254 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _OFFSET_HPP +#define _OFFSET_HPP + +#include <nalt.hpp> +#include <segment.hpp> + +/*! \file offset.hpp + + \brief Functions that deal with offsets. + + "Being an offset" is a characteristic of an operand. + This means that operand or its part represent offset from + some address in the program. This linear address is called + "offset base". Some operands may have 2 offsets simultaneously. + Generally, IDA doesn't handle this except for Motorola outer offsets. + Thus there may be two offset values in an operand: simple offset and + outer offset. + + Outer offsets are handled by specifying special operand number: + it should be ORed with #OPND_OUTER value. + + See bytes.hpp for further explanation of operand numbers. +*/ + + +/// Get default reference type depending on the segment. +/// \return one of ::REF_OFF8,::REF_OFF16,::REF_OFF32 + +idaman reftype_t ida_export get_default_reftype(ea_t ea); + + +/// Convert operand to a reference. +/// To delete an offset, use clr_op_type() function. +/// \param ea linear address. +/// if 'ea' has unexplored bytes, try to convert them to +/// - no segment: fail +/// - 16bit segment: to 16bit word data +/// - 32bit segment: to dword +/// \param n number of operand (may be ORed with #OPND_OUTER) +/// - 0: first +/// - 1: second +/// - 2: third +/// - #OPND_MASK: all operands +/// \param ri reference information +/// \return success + +idaman bool ida_export op_offset_ex(ea_t ea, int n, const refinfo_t *ri); + + +/// See op_offset_ex() + +idaman bool ida_export op_offset( + ea_t ea, + int n, + uint32 type_and_flags, + ea_t target=BADADDR, + ea_t base=0, + adiff_t tdelta=0); + + +/// Convert operand to a reference with the default reference type + +inline bool op_plain_offset(ea_t ea, int n, ea_t base) +{ + reftype_t reftype = get_default_reftype(ea); + return op_offset(ea, n, reftype, BADADDR, base) != 0; +} + + +/// Get offset base value +/// \param ea linear address +/// \param n number of operand +/// \return offset base or #BADADDR + +inline ea_t get_offbase(ea_t ea, int n) +{ + refinfo_t ri; + if ( !get_refinfo(&ri, ea, n) ) + return BADADDR; + return ri.base; +} + + +/// Get offset expression (in the form "offset name+displ"). +/// This function uses offset translation function (\ph{translate}) if your IDP +/// module has such a function. Translation function is used to map linear +/// addresses in the program (only for offsets). +/// +/// Example: suppose we have instruction at linear address 0x00011000: +/// \v{mov ax, [bx+7422h]} +/// and at ds:7422h: +/// \v{array dw ...} +/// We want to represent the second operand with an offset expression, so +/// then we call: +/// \v{ +/// get_offset_expresion(0x001100, 1, 0x001102, 0x7422, buf); +/// | | | | | +/// | | | | +output buffer +/// | | | +value of offset expression +/// | | +address offset value in the instruction +/// | +the second operand +/// +address of instruction +/// } +/// and the function will return a colored string: +/// \v{offset array} +/// \param buf output buffer to hold offset expression +/// \param ea start of instruction or data with the offset expression +/// \param n number of operand (may be ORed with #OPND_OUTER) +/// - 0: first operand +/// - 1: second operand +/// \param from linear address of instruction operand or data referring to +/// the name. This address will be used to get fixup information, +/// so it should point to exact position of operand in the +/// instruction. +/// \param offset value of operand or its part. The function will return +/// text representation of this value as offset expression. +/// \param getn_flags combination of: +/// - #GETN_APPZERO: meaningful only if the name refers to +/// a structure. appends the struct field name +/// if the field offset is zero +/// - #GETN_NODUMMY: do not generate dummy names for the expression +/// but pretend they already exist +/// (useful to verify that the offset expression +/// can be represented) +/// \retval 0 can't convert to offset expression +/// \retval 1 ok, a simple offset expression +/// \retval 2 ok, a complex offset expression + + +idaman int ida_export get_offset_expression( + qstring *buf, + ea_t ea, + int n, + ea_t from, + adiff_t offset, + int getn_flags=0); + + +/// See get_offset_expression() + +idaman int ida_export get_offset_expr( + qstring *buf, + ea_t ea, + int n, + const refinfo_t &ri, + ea_t from, + adiff_t offset, + int getn_flags=0); + + +/// Does the specified address contain a valid OFF32 value?. +/// For symbols in special segments the displacement is not taken into account. +/// If yes, then the target address of OFF32 will be returned. +/// If not, then #BADADDR is returned. + +idaman ea_t ida_export can_be_off32(ea_t ea); + + +/// Try to calculate the offset base +/// This function takes into account the fixup information, +/// current ds and cs values. +/// \param ea the referencing instruction/data address +/// \param n operand number +/// - 0: first operand +/// - 1: other operand +/// \return output base address or #BADADDR + +idaman ea_t ida_export calc_offset_base(ea_t ea, int n); + + +/// Try to calculate the offset base. +/// 2 bases are checked: current ds and cs. +/// If fails, return #BADADDR + +idaman ea_t ida_export calc_probable_base_by_value(ea_t ea, uval_t off); + + +/// Calculate the target and base addresses of an offset expression. +/// The calculated target and base addresses are returned in the locations +/// pointed by 'base' and 'target'. In case 'ri.base' is #BADADDR, the +/// function calculates the offset base address from the referencing +/// instruction/data address. +/// The target address is copied from ri.target. If ri.target is #BADADDR +/// then the target is calculated using the base address and 'opval'. +/// This function also checks if 'opval' matches the full value of the +/// reference and takes in account the memory-mapping. +/// \param target output target address +/// \param base output base address +/// \param from the referencing instruction/data address +/// \param ri reference info block from the database +/// \param opval operand value (usually op_t::value or op_t::addr) +/// \return success +idaman bool ida_export calc_reference_data( + ea_t *target, + ea_t *base, + ea_t from, + const refinfo_t &ri, + adiff_t opval); + + +/// Add xrefs for a reference from the given instruction (\insn_t{ea}). +/// This function creates a cross references to the target and the base. +/// insn_t::add_off_drefs() calls this function to create xrefs for +/// 'offset' operand. +/// \param insn the referencing instruction +/// \param from the referencing instruction/data address +/// \param ri reference info block from the database +/// \param opval operand value (usually op_t::value or op_t::addr) +/// \param type type of xref +/// \param opoff offset of the operand from the start of instruction +/// \return the target address of the reference +idaman ea_t ida_export add_refinfo_dref( + const insn_t &insn, + ea_t from, + const refinfo_t &ri, + adiff_t opval, + dref_t type, + int opoff); + + +/// Calculates the target, using the provided refinfo_t + +inline ea_t calc_target(ea_t from, adiff_t opval, const refinfo_t &ri) +{ + ea_t target; + if ( !calc_reference_data(&target, NULL, from, ri, opval) ) + return BADADDR; + return target; +} + +/// Retrieves refinfo_t structure and calculates the target + +inline ea_t calc_target(ea_t from, ea_t ea, int n, adiff_t opval) +{ + refinfo_t ri; + return get_refinfo(&ri, ea, n) ? calc_target(from, opval, ri) : BADADDR; +} + +/// Calculate the value of the reference base. + +inline ea_t calc_basevalue(ea_t target, ea_t base) +{ + return base - get_segm_base(getseg(target)); +} + + +#endif // _OFFSET_HPP diff --git a/idasdk76/include/parsejson.hpp b/idasdk76/include/parsejson.hpp new file mode 100644 index 0000000..e2eef7f --- /dev/null +++ b/idasdk76/include/parsejson.hpp @@ -0,0 +1,260 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef PARSEJSON_HPP +#define PARSEJSON_HPP + +/*! \file parsejson.hpp + + \brief Tools for parsing JSON-formatted input + + See also lex.hpp/parse.hpp for finer-grained functions & documentation. +*/ +#include <lex.hpp> + +//--------------------------------------------------------------------------- +enum jtype_t +{ + JT_UNKNOWN = 0, + JT_NUM, + JT_STR, + JT_OBJ, + JT_ARR, + JT_BOOL, +}; + +//--------------------------------------------------------------------------- +struct jobj_t; +struct jarr_t; + +#define DECLARE_JVALUE_HELPERS(decl) \ + decl void ida_export jvalue_t_clear(jvalue_t *); \ + decl void ida_export jvalue_t_copy(jvalue_t *, const jvalue_t &); + + +struct jvalue_t; +DECLARE_JVALUE_HELPERS(idaman) + +//------------------------------------------------------------------------- +struct jvalue_t +{ + jvalue_t() : _type(JT_UNKNOWN), _num(0) {} + jvalue_t(const jvalue_t &o) : _type(JT_UNKNOWN) { jvalue_t_copy(this, o); } + ~jvalue_t() { clear(); } + + void clear() { jvalue_t_clear(this); } + + jvalue_t &operator=(const jvalue_t &o) { jvalue_t_copy(this, o); return *this; } + + jtype_t type() const { return _type; } + int64 num() const { QASSERT(1277, _type == JT_NUM); return _num; } + const char *str() const { QASSERT(1278, _type == JT_STR); return _str->c_str(); } + const qstring &qstr() const { QASSERT(1623, _type == JT_STR); return *_str; } + const jobj_t &obj() const { QASSERT(1279, _type == JT_OBJ); return *_obj; } + const jarr_t &arr() const { QASSERT(1280, _type == JT_ARR); return *_arr; } + bool vbool() const { QASSERT(1281, _type == JT_BOOL); return _bool; } + jobj_t &obj() { QASSERT(1282, _type == JT_OBJ); return *_obj; } + jarr_t &arr() { QASSERT(1283, _type == JT_ARR); return *_arr; } + + //lint -sem(jvalue_t::set_str, custodial(1)) function takes ownership of its argument + //lint -sem(jvalue_t::set_obj, custodial(1)) function takes ownership of its argument + //lint -sem(jvalue_t::set_arr, custodial(1)) function takes ownership of its argument + void set_num(int64 i) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_NUM; _num = i; } + void set_str(qstring *s) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_STR; _str = s; } + void set_obj(jobj_t *o) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_OBJ; _obj = o; } + void set_arr(jarr_t *a) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_ARR; _arr = a; } + void set_bool(bool b) { if ( _type != JT_UNKNOWN ) clear(); _type = JT_BOOL; _bool = b; } + + jobj_t *extract_obj() { QASSERT(1624, _type == JT_OBJ); jobj_t *o = _obj; _obj = NULL; _type = JT_UNKNOWN; return o; } + jarr_t *extract_arr() { QASSERT(1625, _type == JT_ARR); jarr_t *a = _arr; _arr = NULL; _type = JT_UNKNOWN; return a; } + + void swap(jvalue_t &r) + { + qswap(_type, r._type); + qswap(_str, r._str); + } + +private: + DECLARE_JVALUE_HELPERS(friend) + + jtype_t _type; + + union + { + int64 _num; + qstring *_str; + jobj_t *_obj; + jarr_t *_arr; + bool _bool; + }; +}; +DECLARE_TYPE_AS_MOVABLE(jvalue_t); +typedef qvector<jvalue_t> jvalues_t; + +//--------------------------------------------------------------------------- +struct kvp_t +{ + qstring key; + jvalue_t value; +}; +DECLARE_TYPE_AS_MOVABLE(kvp_t); + +//------------------------------------------------------------------------- +struct jobj_t : public qvector<kvp_t> +{ + bool has_value(const char *k) const { return get_value(k) != NULL; } + jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN) + { + jvalue_t *v = NULL; + for ( size_t i = 0, _n = size(); i < _n; ++i ) + { + if ( at(i).key == k ) + { + if ( t == JT_UNKNOWN || at(i).value.type() == t ) + v = &at(i).value; + break; + } + } + return v; + } + + const jvalue_t *get_value(const char *k, jtype_t t=JT_UNKNOWN) const + { + return ((jobj_t *) this)->get_value(k, t); + } + + const jvalue_t *get_value_or_fail(const char *k, jtype_t t=JT_UNKNOWN) const + { + const jvalue_t *v = get_value(k, t); + QASSERT(1289, v != NULL); + return v; + } + + jvalue_t *get_value_or_new(const char *key) + { + jvalue_t *v = get_value(key); + if ( v == NULL ) + { + kvp_t &kvp = push_back(); + kvp.key = key; + v = &kvp.value; + } + return v; + } + + int64 get_num(const char *k) const { return get_value_or_fail(k)->num(); } + bool get_bool(const char *k) const { return get_value_or_fail(k)->vbool(); } + const char *get_str(const char *k) const { return get_value_or_fail(k)->str(); } + const jobj_t &get_obj(const char *k) const { return get_value_or_fail(k)->obj(); } + const jarr_t &get_arr(const char *k) const { return get_value_or_fail(k)->arr(); } + +#define DEFINE_FLAG_GETTER(Type, JType, GetExpr) \ + bool get(Type *out, const char *k) const \ + { \ + const jvalue_t *v = get_value(k, JType); \ + bool ok = v != NULL; \ + if ( ok ) \ + *out = GetExpr; \ + return ok; \ + } +#define DEFINE_DFLT_GETTER(Type, JType, GetExpr) \ + Type get(const char *k, Type dflt) const \ + { \ + const jvalue_t *v = get_value(k, JType); \ + return v != NULL ? GetExpr : dflt; \ + } +#define DEFINE_SETTER(Type, SetExpr) \ + void put(const char *key, Type value) \ + { \ + jvalue_t *v = get_value_or_new(key); \ + SetExpr; \ + } +#define DEFINE_ACCESSORS(Type, ConstType, JType, GetExpr, SetExpr) \ + DEFINE_FLAG_GETTER(ConstType, JType, GetExpr) \ + DEFINE_DFLT_GETTER(ConstType, JType, GetExpr) \ + DEFINE_SETTER(Type, SetExpr) + + DEFINE_ACCESSORS(int, int, JT_NUM, v->num(), v->set_num(value)); + DEFINE_ACCESSORS(int64, int64, JT_NUM, v->num(), v->set_num(value)); + DEFINE_ACCESSORS(bool, bool, JT_BOOL, v->vbool(), v->set_bool(value)); + DEFINE_ACCESSORS(jarr_t *, const jarr_t *, JT_ARR, &v->arr(), v->set_arr(value)); // setter takes ownership + DEFINE_ACCESSORS(jobj_t *, const jobj_t *, JT_OBJ, &v->obj(), v->set_obj(value)); // setter takes ownership + DEFINE_ACCESSORS(const char *, const char *, JT_STR, v->str(), v->set_str(new qstring(value))); +#undef DEFINE_ACCESSORS +#undef DEFINE_SETTER +#undef DEFINE_DFLT_GETTER +#undef DEFINE_FLAG_GETTER + + bool get(qstring *out, const char *k) const + { + const jvalue_t *v = get_value(k, JT_STR); + bool ok = v != NULL; + if ( ok ) + *out = v->qstr(); + return ok; + } + + const qstring &get(const char *k, const qstring &dflt) const + { + const jvalue_t *v = get_value(k, JT_STR); + return v != NULL ? v->qstr() : dflt; + } + + void put(const char *key, const qstring &value) + { + jvalue_t *v = get_value_or_new(key); + v->set_str(new qstring(value)); + } +}; +DECLARE_TYPE_AS_MOVABLE(jobj_t); + +//--------------------------------------------------------------------------- +struct jarr_t +{ + jvalues_t values; + + size_t count_items_with_type(jtype_t t) const + { + size_t cnt = 0; + for ( size_t i = 0, n = values.size(); i < n; ++i ) + if ( values[i].type() == t ) + ++cnt; + return cnt; + } + + bool is_homogeneous(jtype_t t) const + { + return count_items_with_type(t) == values.size(); + } +}; +DECLARE_TYPE_AS_MOVABLE(jarr_t); + +//--------------------------------------------------------------------------- +// Note: If 'ungot_tokens' is not NULL, its contents will be used before fetching tokens from the lexer +idaman THREAD_SAFE error_t ida_export parse_json(jvalue_t *out, lexer_t *lx, tokenstack_t *ungot_tokens = NULL); +idaman THREAD_SAFE error_t ida_export parse_json_string(jvalue_t *out, const char *s); + +//------------------------------------------------------------------------- +#define SJF_PRETTY 0x1 +idaman THREAD_SAFE bool ida_export serialize_json( + qstring *out, + const jvalue_t &v, + uint32 flags=0); + +inline THREAD_SAFE bool serialize_json( + qstring *out, + const jobj_t *o, + uint32 flags=0) +{ + jvalue_t v; + v.set_obj((jobj_t *) o); + bool rc = serialize_json(out, v, flags); + v.extract_obj(); + return rc; +} + +#endif // PARSEJSON_HPP diff --git a/idasdk76/include/pro.h b/idasdk76/include/pro.h new file mode 100644 index 0000000..e98fd7e --- /dev/null +++ b/idasdk76/include/pro.h @@ -0,0 +1,4847 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _PRO_H +#define _PRO_H + +/*! \file pro.h + + \brief This is the first header included in the IDA project. + + It defines the most common types, functions and data. + Also, it tries to make system dependent definitions. + + The following preprocessor macros are used in the project + (the list may be incomplete) + + Platform must be specified as one of: + + __NT__ - MS Windows (all platforms) \n + __LINUX__ - Linux \n + __MAC__ - MAC OS X + + __EA64__ - 64-bit address size (sizeof(ea_t)==8) \n + + __X86__ - 32-bit debug servers (sizeof(void*)==4) \n + __X64__ - x64 processor (sizeof(void*)==8) default \n + __PPC__ - PowerPC \n + __ARM__ - ARM +*/ + +/// IDA SDK v7.6 +#define IDA_SDK_VERSION 760 + +//--------------------------------------------------------------------------- +#if !defined(__NT__) && !defined(__LINUX__) && !defined(__MAC__) +# if defined(_MSC_VER) +# define __NT__ +# elif defined(__APPLE__) +# define __MAC__ +# elif defined(__linux__) +# define __LINUX__ +# else +# error "Please define one of: __NT__, __LINUX__, __MAC__" +# endif +#endif + +// Linux or Mac imply Unix +#if defined(__LINUX__) || defined(__MAC__) +#define __UNIX__ +#endif + +/// \def{BADMEMSIZE, Invalid memory size} +#ifndef __X86__ +#define BADMEMSIZE 0x7FFFFFFFFFFFFFFFull +#else +#define BADMEMSIZE 0x7FFFFFFFul +#endif + +/// \def{ENUM_SIZE, Specify size of enum values} +#define ENUM_SIZE(t) : t + +#ifndef SWIG +#include <stdlib.h> /* size_t, NULL, memory */ +#include <stdarg.h> +#include <stddef.h> +#include <stdio.h> +#include <assert.h> +#include <limits.h> +#include <ctype.h> +#include <time.h> +#ifdef __cplusplus +#include <new> +#include <string> +#endif +#if defined(__NT__) +# include <malloc.h> +#endif + +/// \def{WIN32_LEAN_AND_MEAN, compile faster} +#if defined(_MSC_VER) +# define WIN32_LEAN_AND_MEAN +# include <string.h> +# include <io.h> +# include <direct.h> +#else +# include <wchar.h> +# include <string.h> +# include <unistd.h> +# include <sys/stat.h> +# include <errno.h> +#endif +#ifdef __cplusplus +# include <set> +# include <map> +# include <algorithm> +#endif +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> + +#endif // SWIG + +#define STL_SUPPORT_PRESENT + +//--------------------------------------------------------------------------- +/// \def{EXTERNC, specify C linkage} +/// \def{C_INCLUDE, helper for 'extern "C" {}' statements} +/// \def{C_INCLUDE_END, \copydoc C_INCLUDE} +/// \def{INLINE, inline keyword for c++} +#if defined(__cplusplus) || defined(SWIG) +#define EXTERNC extern "C" +#define C_INCLUDE EXTERNC \ + { + +#define C_INCLUDE_END } +#define INLINE inline +#else +#define EXTERNC +#define C_INCLUDE +#define C_INCLUDE_END +#define INLINE __inline +#endif + +//--------------------------------------------------------------------------- +#ifndef MAXSTR +#define MAXSTR 1024 ///< maximum string size +#endif + +#define SMAXSTR QSTRINGIZE(MAXSTR) ///< get #MAXSTR as a string + +/// \def{NT_CDECL, Some NT functions require __cdecl calling convention} +#ifdef __NT__ +#define NT_CDECL __cdecl +#else +#define NT_CDECL +#endif + +/// \def{DEPRECATED, identifies parts of the IDA API that are considered deprecated} +/// \def{NORETURN, function does not return} +/// \def{PACKED, type is packed} +/// \def{AS_PRINTF, function accepts printf-style format and args} +/// \def{AS_SCANF, function accepts scanf-style format and args} +/// \def{WARN_UNUSED_RESULT, warn if a function returns a result that is never used} +#if defined(SWIG) +#define constexpr +#define DEPRECATED +#define NORETURN +#define PACKED +#define AS_STRFTIME(format_idx) +#define AS_PRINTF(format_idx, varg_idx) +#define AS_SCANF(format_idx, varg_idx) +#define WARN_UNUSED_RESULT +#elif defined(__GNUC__) +#define DEPRECATED __attribute__((deprecated)) +#define NORETURN __attribute__((noreturn)) +#define PACKED __attribute__((__packed__)) +#define AS_STRFTIME(format_idx) __attribute__((format(strftime, format_idx, 0))) +#define AS_PRINTF(format_idx, varg_idx) __attribute__((format(printf, format_idx, varg_idx))) +#define AS_SCANF(format_idx, varg_idx) __attribute__((format(scanf, format_idx, varg_idx))) +#define WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#else +#define DEPRECATED __declspec(deprecated) +#define NORETURN __declspec(noreturn) +#define PACKED +#define AS_STRFTIME(format_idx) +#define AS_PRINTF(format_idx, varg_idx) +#define AS_SCANF(format_idx, varg_idx) +#define WARN_UNUSED_RESULT _Check_return_ +#endif + +/// \def{GCC_DIAG_OFF, disable a specific GCC warning for the following code} +/// \def{GCC_DIAG_ON, enable or restore a specific GCC warning for the following code} +#if defined(__GNUC__) && !defined(SWIG) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402 +#define GCC_DIAG_JOINSTR(x,y) _QSTRINGIZE(x ## y) +# define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x) +# define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x) +# if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 406) || defined(__clang__) +# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(push) \ + GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) +# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(pop) +# else +# define GCC_DIAG_OFF(x) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x)) +# define GCC_DIAG_ON(x) GCC_DIAG_PRAGMA(warning GCC_DIAG_JOINSTR(-W,x)) +# endif +#else +# define GCC_DIAG_OFF(x) +# define GCC_DIAG_ON(x) +#endif + +// A function attribute to disable ASAN +#if defined(__clang__) || defined (__GNUC__) +# define DISABLE_ASAN __attribute__((no_sanitize_address)) +#else +# define DISABLE_ASAN +#endif + +#if defined(DONT_DEPRECATE) +#undef DEPRECATED +#define DEPRECATED +#endif + +//--------------------------------------------------------------------------- + +#define __MF__ 0 ///< byte sex of our platform (Most significant byte First). + ///< 0: little endian (Intel 80x86). + ///< 1: big endian (PowerPC). + +//--------------------------------------------------------------------------- +/// Macro to avoid of message 'Parameter x is never used' +#define qnotused(x) (void)x + +#ifdef __clang__ +# define NONNULL _Nonnull +#else +# define NONNULL +#endif + +// this macro can be used as a suffix for declarations/definitions instead of qnotused() +#if defined(__clang__) || defined(__GNUC__) +# define QUNUSED __attribute__((unused)) +#else +# define QUNUSED +#endif + +/// \def{va_argi, GNU C complains about some data types in va_arg because they are promoted to int and proposes to replace them by int} +#ifdef __GNUC__ +#define va_argi(va, type) ((type)va_arg(va, int)) +#else +#define va_argi(va, type) va_arg(va, type) +#endif + +//--------------------------------------------------------------------------- +#define CONST_CAST(x) const_cast<x> ///< cast a const to non-const +#define _QSTRINGIZE(x) #x ///< return x as a string. See #SMAXSTR for example +#define QSTRINGIZE(x) _QSTRINGIZE(x) ///< see #_QSTRINGIZE + +//--------------------------------------------------------------------------- + +/// \def{idaapi, specifies __stdcall calling convention} +/// \def{ida_export, functions marked with this keyword are available as part of the IDA SDK} +/// \def{idaman, specifies c linkage} +/// \def{ida_export_data, data items marked with this keyword are available as part of the IDA SDK} +/// \def{ida_module_data, identifies a data item that will be exported} +/// \def{ida_local, identifies a non-public type definition} +#if defined(SWIG) // for SWIG + #define idaapi + #define idaman + #define ida_export + #define ida_export_data + #define ida_module_data + #define __fastcall + #define ida_local +#elif defined(APIDEF) // for API DEF files + #define idaapi + #define idaman + #define ida_export ida_export + #define ida_export_data ida_export_data + #define ida_module_data + #define __fastcall + #define ida_local +#elif defined(__NT__) // MS Windows + #define idaapi __stdcall + #define ida_export idaapi + #ifdef __CODE_CHECKER__ + // tell lint that this function will be exported + #define idaman EXTERNC __declspec(dllexport) + #else + #define idaman EXTERNC + #endif + #if defined(__KERNEL__) // kernel + #define ida_export_data + #define ida_module_data + #else // modules + #define ida_export_data __declspec(dllimport) + #define ida_module_data __declspec(dllexport) + #endif + #define ida_local +#elif defined(__UNIX__) // for unix + #define idaapi + #if defined(__MAC__) + #define idaman EXTERNC __attribute__((visibility("default"))) + #define ida_local __attribute__((visibility("hidden"))) + #else + #if __GNUC__ >= 4 + #define idaman EXTERNC __attribute__ ((visibility("default"))) + #define ida_local __attribute__((visibility("hidden"))) + #else + #define idaman EXTERNC + #define ida_local + #endif + #endif + #define ida_export + #define ida_export_data + #define ida_module_data + #define __fastcall +#endif + +/// Functions callable from any thread are marked with this keyword +#define THREAD_SAFE + +/// This keyword is used to introduce new virtual functions that do not override +/// any existing virtual function +#define newapi + +//--------------------------------------------------------------------------- +#ifndef __cplusplus +typedef int bool; //-V607 Ownerless typedef +#define false 0 +#define true 1 +#endif + +//--------------------------------------------------------------------------- +// Linux C mode compiler already has these types defined +#if !defined(__LINUX__) || defined(__cplusplus) +typedef unsigned char uchar; ///< unsigned 8 bit value +typedef unsigned short ushort; ///< unsigned 16 bit value +typedef unsigned int uint; ///< unsigned 32 bit value +#endif + +typedef char int8; ///< signed 8 bit value +typedef signed char sint8; ///< signed 8 bit value +typedef unsigned char uint8; ///< unsigned 8 bit value +typedef short int16; ///< signed 16 bit value +typedef unsigned short uint16; ///< unsigned 16 bit value +typedef int int32; ///< signed 32 bit value +typedef unsigned int uint32; ///< unsigned 32 bit value + +#include <llong.hpp> + +typedef longlong int64; ///< signed 64 bit value +typedef ulonglong uint64; ///< unsigned 64 bit value + +/// \fn{int64 qatoll(const char *nptr), Convert string to 64 bit integer} +#if defined(__UNIX__) +INLINE int64 qatoll(const char *nptr) { return atoll(nptr); } +#elif defined(_MSC_VER) +INLINE int64 qatoll(const char *nptr) { return _atoi64(nptr); } +#else +INLINE int64 qatoll(const char *nptr) { return atol(nptr); } +#endif + +// VS2010 lacks strtoull +#ifdef _MSC_VER +#define strtoull _strtoui64 +#endif + +/// \typedef{wchar16_t, 2-byte char} +/// \typedef{wchar32_t, 4-byte char} +#if defined(_MSC_VER) +typedef wchar_t wchar16_t; +typedef uint32 wchar32_t; +#elif defined(__GNUC__) +typedef uint16 wchar16_t; +typedef uint32 wchar32_t; +#endif + +/// Signed size_t - used to check for size overflows when the counter becomes +/// negative. Also signed size_t allows us to signal an error condition using +/// a negative value, for example, as a function return value. +#if !defined(_SSIZE_T_DEFINED) && !defined(__ssize_t_defined) && !defined(__GNUC__) +typedef ptrdiff_t ssize_t; +#endif + +/// \def{FMT_64, compiler-specific printf format specifier for 64-bit numbers} +/// \def{FMT_Z, compiler-specific printf format specifier for size_t} +/// \def{FMT_ZX, compiler-specific printf format specifier for size_t, hex} +/// \def{FMT_ZS, compiler-specific printf format specifier for ssize_t} +#if defined(__GNUC__) && !defined(__MINGW32__) + #define FMT_64 "ll" + #define FMT_Z "zu" + #define FMT_ZX "zX" + #define FMT_ZS "zd" +#elif defined(_MSC_VER) && _MSC_VER >= 1900 + #define FMT_64 "I64" + #define FMT_Z "zu" + #define FMT_ZX "zX" + #define FMT_ZS "td" +#elif defined(_MSC_VER) || defined(__MINGW32__) + #define FMT_64 "I64" + #ifndef __X86__ + #define FMT_Z "I64u" + #define FMT_ZX "I64X" + #define FMT_ZS "I64d" + #else + #define FMT_Z "u" + #define FMT_ZX "X" + #define FMT_ZS "d" + #endif +#elif !defined(SWIG) + #error "unknown compiler" +#endif + +/// \typedef{ea_t, effective address} +/// \typedef{sel_t, segment selector} +/// \typedef{asize_t, memory chunk size} +/// \typedef{adiff_t, address difference} +/// \def{SVAL_MIN, minimum value for an object of type int} +/// \def{SVAL_MAX, maximum value for an object of type int} +/// \def{FMT_EA, format specifier for ::ea_t values} +#ifdef __EA64__ + typedef uint64 ea_t; + typedef uint64 sel_t; + typedef uint64 asize_t; + typedef int64 adiff_t; + #define FMT_EA FMT_64 + #ifdef __GNUC__ + #define SVAL_MIN LLONG_MIN + #define SVAL_MAX LLONG_MAX + #else + #define SVAL_MIN _I64_MIN + #define SVAL_MAX _I64_MAX + #endif +#else + typedef uint32 ea_t; + typedef uint32 sel_t; + typedef uint32 asize_t; + typedef int32 adiff_t; + #define SVAL_MIN INT_MIN + #define SVAL_MAX INT_MAX + #define FMT_EA "" +#endif + +typedef asize_t uval_t; ///< unsigned value used by the processor. + ///< - for 32-bit ::ea_t - ::uint32 + ///< - for 64-bit ::ea_t - ::uint64 +typedef adiff_t sval_t; ///< signed value used by the processor. + ///< - for 32-bit ::ea_t - ::int32 + ///< - for 64-bit ::ea_t - ::int64 + +typedef uint64 ea64_t; ///< 64-bit address, regardless of IDA bitness. + ///< we need this type for interoperability with + ///< debug servers, lumina, etc + +/// Error code (errno) +typedef int error_t; + +typedef uint8 op_dtype_t; + +/// The inode_t type is the specialization specific inode number. +/// For example, it can represent a local type ordinal or a structure id. +typedef uval_t inode_t; + +// A position in the difference source. +// This is an abstract value that depends on the difference source. +// It should be something that can be used to conveniently retrieve information +// from a difference source. For example, for the name list it can be the index +// in the name list. For structure view it can be the position in the list of structs. +// Please note that this is not necessarily an address. However, for the purpose +// of comparing the contents of the disassembly listing it can be an address. +// +// diffpos_t instances must have the following property: adding or removing +// items to diff_source_t should not invalidate the existing diffpos_t instances. +// They must stay valid after adding or removing items to diff_source_t. +// Naturally, deleting an item pointed by diffpos_t may render it incorrect, +// this is acceptable and expected. +typedef size_t diffpos_t; +constexpr diffpos_t BADDIFF = diffpos_t(-1); + +#ifdef __cplusplus +#define DEFARG(decl, val) decl = val +#else +#define DEFARG(decl, val) decl +#endif + +#ifndef SWIG +#define BADADDR ea_t(-1) ///< this value is used for 'bad address' +#define BADSEL sel_t(-1) ///< 'bad selector' value +#define BADADDR64 ea64_t(-1ULL) + +//------------------------------------------------------------------------- +// Time related functions + +typedef int32 qtime32_t; ///< we use our own time type because time_t + ///< can be 32-bit or 64-bit depending on the compiler +typedef uint64 qtime64_t; ///< 64-bit time value expressed as seconds and + ///< microseconds since the Epoch + +/// Get the 'seconds since the epoch' part of a qtime64_t + +INLINE THREAD_SAFE uint32 get_secs(qtime64_t t) +{ + return (uint32)(t>>32); +} + + +/// Get the microseconds part of a qtime64_t + +INLINE THREAD_SAFE uint32 get_usecs(qtime64_t t) +{ + return (uint32)(t); +} + + +/// Get a ::qtime64_t instance from a seconds value and microseconds value. +/// \param secs seconds +/// \param usecs microseconds + +INLINE THREAD_SAFE qtime64_t make_qtime64(uint32 secs, DEFARG(int32 usecs,0)) +{ + return ((qtime64_t)(secs) << 32) | usecs; +} + + +/// Converts calendar time into a string. +/// Puts 'wrong timestamp\\n' into the buffer if failed +/// \param buf output buffer +/// \param bufsize size of the output buffer +/// \param t calendar time +/// \return success + +idaman THREAD_SAFE bool ida_export qctime(char *buf, size_t bufsize, qtime32_t t); + + +/// Converts calendar time into a string using Coordinated Universal Time (UTC). +/// Function is equivalent to asctime(gmtime(t)). +/// Puts 'wrong timestamp\\n' into the buffer if failed. +/// \param buf output buffer +/// \param bufsize of the output buffer +/// \param t calendar time +/// \return success + +idaman THREAD_SAFE bool ida_export qctime_utc(char *buf, size_t bufsize, qtime32_t t); + + +/// Converts a time value to a tm structure. +/// \param[out] _tm result +/// \param t local time +/// \returns success + +idaman THREAD_SAFE bool ida_export qlocaltime(struct tm *_tm, qtime32_t t); + + +/// Same as qlocaltime(struct tm *, qtime32_t), but accepts a 64-bit time value + +INLINE THREAD_SAFE bool qlocaltime64(struct tm *_tm, qtime64_t t) +{ + return qlocaltime(_tm, get_secs(t)); +} + + +/// Get string representation of a qtime32_t. +/// Copies into 'buf' the content of 'format', expanding its format specifiers into the +/// corresponding values that represent the time described in 't', with a limit of 'bufsize' characters +/// see http://www.cplusplus.com/reference/ctime/strftime/ for more +/// \param buf output buffer +/// \param bufsize of the output buffer +/// \param format format string +/// \param t time value +/// \return length of the resulting string + +idaman AS_STRFTIME(3) THREAD_SAFE size_t ida_export qstrftime( + char *buf, + size_t bufsize, + const char *format, + qtime32_t t); + + +/// Same as qstrftime(), but accepts a 64-bit time value + +idaman AS_STRFTIME(3) THREAD_SAFE size_t ida_export qstrftime64( + char *buf, + size_t bufsize, + const char *format, + qtime64_t t); + + +/// Suspend execution for given number of milliseconds + +idaman THREAD_SAFE void ida_export qsleep(int milliseconds); + + +/// High resolution timer. +/// On Unix systems, returns current time in nanoseconds. +/// On Windows, returns a high resolution counter (QueryPerformanceCounter) +/// \return stamp in nanoseconds + +idaman THREAD_SAFE uint64 ida_export get_nsec_stamp(void); + +/// Get the current time with microsecond resolution (in fact the resolution +/// is worse on windows) + +idaman THREAD_SAFE qtime64_t ida_export qtime64(void); + + +/// Generate a random buffer. +/// \param[out] buffer pointer to result +/// \param bufsz size of buffer +/// \return success + +idaman THREAD_SAFE bool ida_export gen_rand_buf(void *buffer, size_t bufsz); + + +#define qoff64_t int64 ///< file offset + +/// Describes miscellaneous file attributes +struct qstatbuf +{ + uint64 qst_dev; ///< ID of device containing file + uint32 qst_ino; ///< inode number + uint32 qst_mode; ///< protection + uint32 qst_nlink; ///< number of hard links + uint32 qst_uid; ///< user ID of owner + uint32 qst_gid; ///< group ID of owner + uint64 qst_rdev; ///< device ID (if special file) + qoff64_t qst_size; ///< total size, in bytes + int32 qst_blksize; ///< blocksize for file system I/O + int32 qst_blocks; ///< number of 512B blocks allocated + qtime64_t qst_atime; ///< time of last access + qtime64_t qst_mtime; ///< time of last modification + qtime64_t qst_ctime; ///< time of last status change +}; + +// non standard functions are missing: +#ifdef _MSC_VER +#if _MSC_VER <= 1200 +# define for if(0); else for ///< MSVC <= 1200 is not compliant to the ANSI standard +#else +# pragma warning(disable : 4200) ///< zero-sized array in structure (non accept from cmdline) +# if _MSC_VER >= 1921 && _MSC_VER < 1924 // avoid compiler bug: +# pragma function(memmove) // https://developercommunity.visualstudio.com/content/problem/583227/vs-2019-cl-1921277022-memmove-instrinsic-optimizat.html +# endif +#endif +/// \name VS posix names +/// Shut up Visual Studio (VS deprecated posix names but there seems to be no good reason for that) +//@{ +#define chdir _chdir +#define fileno _fileno +#define getcwd _getcwd +#define memicmp _memicmp +# define F_OK 0 +# define W_OK 2 +# define R_OK 4 +//@} +#endif + +/// Is this IDA kernel? If not, we are executing a standalone application +idaman bool ida_export_data is_ida_kernel; + +//--------------------------------------------------------------------------- +/* error codes */ +/*--------------------------------------------------*/ + +#define eOk 0 ///< no error +#define eOS 1 ///< os error, see errno +#define eDiskFull 2 ///< disk full +#define eReadError 3 ///< read error +#define eFileTooLarge 4 ///< file too large + + +/// Set qerrno + +idaman THREAD_SAFE error_t ida_export set_qerrno(error_t code); + + +/// Get qerrno + +idaman THREAD_SAFE error_t ida_export get_qerrno(void); + +//--------------------------------------------------------------------------- +// debugging macros +/// \def{ZZZ, debug print} +/// \def{BPT, trigger a breakpoint from IDA. also see #INTERR} +#define ZZZ msg("%s:%d\n", __FILE__, __LINE__) +#if defined(__GNUC__) +# define BPT __builtin_trap() +#elif defined(_MSC_VER) // Visual C++ +# define BPT __debugbreak() +# ifdef __CODE_CHECKER__ + NORETURN void __debugbreak(void); +# endif +#endif + +/// \def{CASSERT, results in a compile error if the cnd is not true} +#ifdef __CODE_CHECKER__ +#define CASSERT(cnd) extern int pclint_cassert_dummy_var +#else +#define CASSERT(cnd) static_assert((cnd), QSTRINGIZE(cnd)) +#endif + +/// \def{INTERR, Show internal error message and terminate execution abnormally. +/// When IDA is being run under a debugger this will ensure that +/// the debugger will break immediately.} +#ifdef __CODE_CHECKER__ +#define INTERR(code) interr(code) +#else +#define INTERR(code) do { if ( under_debugger ) BPT; interr(code); } while(1) +#endif + +#define QASSERT(code, cond) do if ( !(cond) ) INTERR(code); while (0) ///< run time assertion +#define QBUFCHECK(buf, size, src) ida_fill_buffer(buf, size, src, __FILE__, __LINE__) ///< run time assertion +idaman bool ida_export_data under_debugger; ///< is IDA running under a debugger? + +#define INTERR_EXC_FMT "Internal error %d occurred when running a script. Either\n" \ + " - the script misused the IDA API, or\n" \ + " - there is a logic error in IDA\n" \ + "Please check the script first.\n" \ + "If it appears correct, send a bug report to <support@hex-rays.com>.\n" \ + "In any case we strongly recommend you to restart IDA as soon as possible." + +#ifdef __cplusplus +struct interr_exc_t : public std::exception +{ + int code; + interr_exc_t(int _code) : code(_code) {} +}; +#endif // __cplusplus +idaman THREAD_SAFE NORETURN void ida_export interr(int code); ///< Show internal error message and terminate execution + +// Should an 'interr()' throw an 'interr_exc_t' instance, +// or terminate IDA (the default)? +idaman bool ida_export_data interr_should_throw; + +//--------------------------------------------------------------------------- +idaman THREAD_SAFE void *ida_export qalloc(size_t size); ///< System independent malloc +idaman THREAD_SAFE void *ida_export qrealloc(void *alloc, size_t newsize); ///< System independent realloc +idaman THREAD_SAFE void *ida_export qcalloc(size_t nitems, size_t itemsize); ///< System independent calloc +idaman THREAD_SAFE void ida_export qfree(void *alloc); ///< System independent free +idaman THREAD_SAFE char *ida_export qstrdup(const char *string); ///< System independent strdup +#define qnew(t) ((t*)qalloc(sizeof(t))) ///< create a new object in memory +/// \def{qnewarray, qalloc_array() is safer than qnewarray} +#define qnewarray(t,n) use_qalloc_array + +/// Use this class to avoid integer overflows when allocating arrays +#ifdef __cplusplus +template <class T> +T *qalloc_array(size_t n) +{ + return (T *)qcalloc(n, sizeof(T)); +} + +/// Use this class to avoid integer overflows when allocating arrays +template <class T> +T *qrealloc_array(T *ptr, size_t n) +{ + size_t nbytes = n * sizeof(T); + if ( nbytes < n ) + return NULL; // integer overflow + return (T *)qrealloc(ptr, nbytes); +} + +/// \def{qnumber, determine capacity of an array} +#ifdef __GNUC__ +# define qnumber(arr) ( \ + 0 * sizeof(reinterpret_cast<const ::qnumber_check_type *>(arr)) \ + + 0 * sizeof(::qnumber_check_type::check_type((arr), &(arr))) \ + + sizeof(arr) / sizeof((arr)[0]) ) + struct qnumber_check_type + { + struct is_pointer; + struct is_array {}; + template <typename T> + static is_pointer check_type(const T *, const T *const *); + static is_array check_type(const void *, const void *); + }; +#elif defined(_MSC_VER) && !defined(__CODE_CHECKER__) +# define qnumber(array) _countof(array) +#else // poor man's implementation for other compilers and lint +# define qnumber(array) (sizeof(array)/sizeof(array[0])) +#endif +#endif // __cplusplus + +#define qoffsetof offsetof + +/// \def{set_vva, extracts a va_list passed as a variadic function argument} +/// \def{va_copy, copy a va_list} +#if defined(__GNUC__) && !defined(__X86__) && !(defined(__clang__) && defined(__ARM__)) + // gcc64 and clang x86_64 use special array-type va_list, so we have to resort to tricks like these + #define set_vva(va2, vp) va_copy(va2, *(va_list*)va_arg(vp, void*)) +#else + #ifndef va_copy + #define va_copy(dst, src) dst = src + #endif + #if defined(__clang__) + #define set_vva(va2, vp) va2 = va_arg(vp, va_list) + #else + #define set_vva(va2, vp) va_copy(va2, va_arg(vp, va_list)) + #endif +#endif + + +/// Reverse memory block. +/// Analog of strrev() function +/// \param buf pointer to buffer to reverse +/// \param size size of buffer +/// \return pointer to buffer + +idaman THREAD_SAFE void *ida_export memrev(void *buf, ssize_t size); + +#if defined(__GNUC__) && !defined(_WIN32) +idaman THREAD_SAFE int ida_export memicmp(const void *x, const void *y, size_t size); +#endif + +//--------------------------------------------------------------------------- +/* strings */ +/// \def{strnicmp, see 'VS posix names'} +/// \def{stricmp, see 'VS posix names'} +#ifdef __GNUC__ +#define strnicmp strncasecmp +#define stricmp strcasecmp +#elif defined(_MSC_VER) +#define strnicmp _strnicmp +#define stricmp _stricmp +#endif + + +/// Replace all occurrences of a character within a string. +/// \param str to modify +/// \param char1 char to be replaced +/// \param char2 replacement char +/// \return pointer to resulting string + +idaman THREAD_SAFE char *ida_export strrpl(char *str, int char1, int char2); + + +/// Get tail of a string +INLINE THREAD_SAFE char *tail(char *str) { return strchr(str, '\0'); } +#ifdef __cplusplus +/// \copydoc tail(char *) +inline THREAD_SAFE const char *tail(const char *str) { return strchr(str, '\0'); } +#endif + + +/// A safer strncpy - makes sure that there is a terminating zero. +/// nb: this function doesn't fill the whole buffer zeroes as strncpy does +/// nb: ssize_t(dstsize) must be > 0 + +idaman THREAD_SAFE char *ida_export qstrncpy(char *dst, const char *src, size_t dstsize); + + +/// A safer stpncpy - returns pointer to the end of the destination +/// nb: ssize_t(dstsize) must be > 0 + +idaman THREAD_SAFE char *ida_export qstpncpy(char *dst, const char *src, size_t dstsize); + + +/// A safer strncat - accepts the size of the 'dst' as 'dstsize' and returns dst +/// nb: ssize_t(dstsize) must be > 0 + +idaman THREAD_SAFE char *ida_export qstrncat(char *dst, const char *src, size_t dstsize); + + +/// Thread-safe version of strtok + +idaman THREAD_SAFE char *ida_export qstrtok(char *s, const char *delim, char **save_ptr); + + +/// Convert the string to lowercase + +idaman THREAD_SAFE char *ida_export qstrlwr(char *str); + + +/// Convert the string to uppercase + +idaman THREAD_SAFE char *ida_export qstrupr(char *str); + + +/// Find one string in another (Case insensitive analog of strstr()). +/// \param s1 string to be searched +/// \param s2 string to search for +/// \return a pointer to the first occurrence of s2 within s1, NULL if none exists + +idaman THREAD_SAFE const char *ida_export stristr(const char *s1, const char *s2); + + +#ifdef __cplusplus +/// Same as stristr(const char *, const char *) but returns a non-const result +inline char *idaapi stristr(char *s1, const char *s2) { return CONST_CAST(char *)(stristr((const char *)s1, s2)); } +#endif + +/// \defgroup ctype Functions to test ASCII char attributes +/// The is...() functions in ctype.h will misbehave with 'char' argument. We introduce more robust functions. +/// These functions only operate on ascii chars and are intended to be locale-independent. +//@{ +INLINE THREAD_SAFE bool ida_local qisascii(char c) { return (c & ~0x7f) == 0; } +INLINE THREAD_SAFE bool ida_local qisspace(char c) { return qisascii(c) && isspace((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qisalpha(char c) { return qisascii(c) && isalpha((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qisalnum(char c) { return qisascii(c) && isalnum((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qispunct(char c) { return qisascii(c) && ispunct((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qislower(char c) { return qisascii(c) && islower((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qisupper(char c) { return qisascii(c) && isupper((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qisprint(char c) { return qisascii(c) && isprint((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qisdigit(char c) { return qisascii(c) && isdigit((uchar)(c)) != 0; } +INLINE THREAD_SAFE bool ida_local qisxdigit(char c) { return qisascii(c) && isxdigit((uchar)(c)) != 0; } +//@} + +/// Get lowercase equivalent of given char +INLINE THREAD_SAFE int ida_local qtolower(char c) { return tolower((uchar)(c)); } +/// Get uppercase equivalent of given char +INLINE THREAD_SAFE int ida_local qtoupper(char c) { return toupper((uchar)(c)); } + +// We forbid using dangerous functions in IDA +#if !defined(USE_DANGEROUS_FUNCTIONS) && !defined(__CODE_CHECKER__) +#undef strcpy +#define strcpy dont_use_strcpy ///< use qstrncpy() +#define stpcpy dont_use_stpcpy ///< use qstpncpy() +#define strncpy dont_use_strncpy ///< use qstrncpy() +#define strcat dont_use_strcat ///< use qstrncat() +#define strncat dont_use_strncat ///< use qstrncat() +#define gets dont_use_gets ///< use qfgets() +#define sprintf dont_use_sprintf ///< use qsnprintf() +#define snprintf dont_use_snprintf ///< use qsnprintf() +#define wsprintfA dont_use_wsprintf ///< use qsnprintf() +#undef strcmpi +#undef strncmpi +#define strcmpi dont_use_strcmpi ///< use stricmp() +#define strncmpi dont_use_strncmpi ///< use strnicmp() +#define getenv dont_use_getenv ///< use qgetenv() +#define setenv dont_use_setenv ///< use qsetenv() +#define putenv dont_use_putenv ///< use qsetenv() +#define strtok dont_use_strrok ///< use qstrtok() +#undef strlwr +#undef strupr +#define strlwr dont_use_strlwr ///< use qstrlwr() +#define strupr dont_use_strupr ///< use qstrupr() +#define waitid dont_use_waitid ///< use qwait() +#define waitpid dont_use_waitpid ///< use qwait() +#define wait dont_use_wait ///< use qwait() +#endif + +//--------------------------------------------------------------------------- +#define streq(s1, s2) (strcmp((s1), (s2)) == 0) ///< convenient check for string equality +#define strieq(s1, s2) (stricmp((s1), (s2)) == 0) ///< see #streq +#define strneq(s1, s2, count) (strncmp((s1), (s2), (count)) == 0) ///< see #streq +#define strnieq(s1, s2, count) (strnicmp((s1), (s2), (count)) == 0) ///< see #streq + +//--------------------------------------------------------------------------- +/// \defgroup qsnprintf qsnprintf/qsscanf +/// safer versions of sprintf/sscanf +/// +/// Our definitions of sprintf-like functions support one additional format specifier +/// +/// "%a" which corresponds to ::ea_t +/// +/// Usual optional fields like the width can be used too: %04a. +/// The width specifier will be doubled for 64-bit version. +/// These function return the number of characters _actually written_ to the output string. +/// excluding the terminating zero. (which is different from the snprintf). +/// They always terminate the output with a zero byte (if n > 0). +//@{ +idaman AS_PRINTF(3, 4) THREAD_SAFE int ida_export qsnprintf(char *buffer, size_t n, const char *format, ...); ///< A safer snprintf +idaman AS_SCANF (2, 3) THREAD_SAFE int ida_export qsscanf(const char *input, const char *format, ...); ///< A safer sscanf +idaman AS_PRINTF(3, 0) THREAD_SAFE int ida_export qvsnprintf(char *buffer, size_t n, const char *format, va_list va); ///< See qsnprintf() +idaman AS_SCANF (2, 0) THREAD_SAFE int ida_export qvsscanf(const char *input, const char *format, va_list va); ///< See qsscanf() +idaman AS_PRINTF(3, 4) THREAD_SAFE int ida_export append_snprintf(char *buf, const char *end, const char *format, ...); ///< Append result of sprintf to 'buf' +//@} + +//--------------------------------------------------------------------------- +/// qsnprintf that does not check its arguments. +/// Normally gcc complains about the non-literal formats. However, sometimes we +/// still need to call qsnprintf with a dynamically built format string. +/// OTOH, there are absolutely no checks of the input arguments, so be careful! +GCC_DIAG_OFF(format-nonliteral); +INLINE int nowarn_qsnprintf(char *buf, size_t size, const char *format, ...) +{ + va_list va; + int code; + va_start(va, format); +#ifdef __cplusplus + code = ::qvsnprintf(buf, size, format, va); +#else + code = qvsnprintf(buf, size, format, va); +#endif + va_end(va); + return code; +} +GCC_DIAG_ON(format-nonliteral); + +//--------------------------------------------------------------------------- +/// \def{QMAXPATH, maximum number of characters in a path specification} +/// \def{QMAXFILE, maximum number of characters in a filename specification} +#if defined(__NT__) +#define QMAXPATH 260 +#define QMAXFILE 260 +#else +#define QMAXPATH PATH_MAX +#define QMAXFILE PATH_MAX +#endif + +idaman THREAD_SAFE char *ida_export vqmakepath(char *buf, size_t bufsize, const char *s1, va_list); ///< See qmakepath() + + +/// Construct a path from a null-terminated sequence of strings. +/// \param buf output buffer. Can be == s1, but must not be NULL +/// \param bufsize size of buffer +/// \return pointer to result + +idaman THREAD_SAFE char *ida_export qmakepath(char *buf, size_t bufsize, const char *s1, ...); + + +/// Get the current working directory. +/// \param buf output buffer +/// \param bufsize size of buffer +/// This function calls error() if any problem occurs. + +idaman void ida_export qgetcwd(char *buf, size_t bufsize); + + +/// Change the current working directory. +/// \param path the new directory +/// The possible return values are the same as those of the POSIX 'chdir' + +idaman int ida_export qchdir(const char *path); + + +/// Get the directory part of the path. +/// path and buf may point to the same buffer +/// \param[out] buf buffer for the directory part. can be NULL. +/// \param[out] bufsize size of this buffer +/// \param path path to split +/// \retval true ok +/// \retval false input buffer did not have the directory part. +/// In this case the buffer is filled with "." + +idaman THREAD_SAFE bool ida_export qdirname(char *buf, size_t bufsize, const char *path); + + +/// Construct filename from base name and extension. +/// \param buf output buffer. Can be == base, but must not be NULL +/// \param bufsize size of buffer +/// \param base base name +/// \param ext extension +/// \return pointer to result + +idaman THREAD_SAFE char *ida_export qmakefile( + char *buf, + size_t bufsize, + const char *base, + const char *ext); + + +/// Split filename into base name and extension. +/// \param file filename, may be changed +/// \param base filled with base part, can be NULL +/// \param ext filled with extension part, can be NULL +/// \return the base part + +idaman THREAD_SAFE char *ida_export qsplitfile(char *file, char **base, char **ext); + + +/// Is the file name absolute (not relative to the current dir?) + +idaman THREAD_SAFE bool ida_export qisabspath(const char *file); + + +/// Get the file name part of the given path. +/// \return NULL if path is NULL + +idaman THREAD_SAFE const char *ida_export qbasename(const char *path); + +#ifdef __cplusplus +/// Same as qbasename(const char *), but accepts and returns non-const char pointers +inline char *qbasename(char *path) { return CONST_CAST(char *)(qbasename((const char *)path)); } +#endif + + +/// Convert relative path to absolute path + +idaman THREAD_SAFE char *ida_export qmake_full_path(char *dst, size_t dstsize, const char *src); + + +/// Search for a file in the PATH environment variable or the current directory. +/// \param buf output buffer to hold the full file path +/// \param bufsize output buffer size +/// \param file the file name to look for. If the file is an absolute path +/// then buf will return the file value. +/// \param search_cwd search the current directory if file was not found in the PATH +/// \return true if the file was found and false otherwise + +idaman THREAD_SAFE bool ida_export search_path( + char *buf, + size_t bufsize, + const char *file, + bool search_cwd); + +/// Delimiter of directory lists +#if defined(__UNIX__) +#define DELIMITER ":" ///< for Unix - ';' for Windows +#else +#define DELIMITER ";" ///< for MS DOS, Windows, other systems - ':' for Unix +#endif + + +/// Set file name extension unconditionally. +/// \param outbuf buffer to hold the answer. may be the same +/// as the file name. +/// \param bufsize output buffer size +/// \param file the file name +/// \param ext new extension (with or without '.') +/// \return pointer to the new file name + +idaman THREAD_SAFE char *ida_export set_file_ext( + char *outbuf, + size_t bufsize, + const char *file, + const char *ext); + + +/// Get pointer to extension of file name. +/// \param file filename +/// \return pointer to the file extension or NULL if extension doesn't exist + +idaman THREAD_SAFE const char *ida_export get_file_ext(const char *file); + +/// Does the given file name have an extension? +#ifdef __cplusplus +inline THREAD_SAFE bool idaapi has_file_ext(const char *file) + { return get_file_ext(file) != NULL; } +#endif + + +/// Set file name extension if none exists. +/// This function appends the extension to a file name. +/// It won't change file name if extension already exists +/// \param buf output buffer +/// \param bufsize size of the output buffer +/// \param file file name +/// \param ext extension (with or without '.') +/// \return pointer to the new file name + +#ifdef __cplusplus +inline THREAD_SAFE char *idaapi make_file_ext( + char *buf, + size_t bufsize, + const char *file, + const char *ext) +{ + if ( has_file_ext(file) ) + return ::qstrncpy(buf, file, bufsize); + else + return set_file_ext(buf, bufsize, file, ext); +} +#endif + + +/// Sanitize the file name. +/// Remove the directory path, and replace wildcards ? * and chars<' ' with _. +/// If the file name is empty, then: +/// - namesize != 0: generate a new temporary name, return true +/// - namesize == 0: return false + +idaman THREAD_SAFE bool ida_export sanitize_file_name(char *name, size_t namesize); + +//--------------------------------------------------------------------------- +/* input/output */ +/*--------------------------------------------------*/ +#if !defined(__NT__) && !defined(_MSC_VER) +#define O_BINARY 0 +#endif + +#ifndef SEEK_SET +# define SEEK_SET 0 ///< beginning of file +# define SEEK_CUR 1 ///< current position of the file * +# define SEEK_END 2 ///< end of file * +#endif + +/*--------------------------------------------------*/ +/* you should use these functions for file i/o */ + + +/// Works the same as it's counterpart from Clib. +/// The only difference is that it sets 'qerrno' variable too + +idaman THREAD_SAFE int ida_export qopen(const char *file, int mode); + + +/// Open file with given sharing_mode (use O_RDONLY, O_WRONLY, O_RDWR flags), sets qerrno + +idaman THREAD_SAFE int ida_export qopen_shared(const char *file, int mode, int share_mode); + + +/// Create new file with O_RDWR, sets qerrno + +idaman THREAD_SAFE int ida_export qcreate(const char *file, int stat); + +idaman THREAD_SAFE int ida_export qread(int h, void *buf, size_t n); ///< \copydoc qopen +idaman THREAD_SAFE int ida_export qwrite(int h, const void *buf, size_t n); ///< \copydoc qopen +idaman THREAD_SAFE qoff64_t ida_export qtell(int h); ///< \copydoc qopen +idaman THREAD_SAFE qoff64_t ida_export qseek(int h, int64 offset, int whence); ///< \copydoc qopen +idaman THREAD_SAFE int ida_export qclose(int h); ///< \copydoc qopen +idaman THREAD_SAFE int ida_export qdup(int h); ///< \copydoc qopen +idaman THREAD_SAFE int ida_export qfsync(int h); ///< \copydoc qopen + + +/// Get the file size. +/// This function may return 0 if the file is not found. + +idaman THREAD_SAFE uint64 ida_export qfilesize(const char *fname); + +/// Get file length in bytes. +/// \param h file descriptor +/// \return file length in bytes, -1 if error + +idaman THREAD_SAFE uint64 ida_export qfilelength(int h); + +/// Change file size. +/// \param h file descriptor +/// \param fsize desired size +/// \retval 0 on success +/// \retval -1 otherwise and qerrno is set + +idaman THREAD_SAFE int ida_export qchsize(int h, uint64 fsize); + +/// Create an empty directory. +/// \param file name (or full path) of directory to be created +/// \param mode permissions (only used on unix systems) +/// \return 0 success +/// \return -1 otherwise and qerrno is set + +idaman THREAD_SAFE int ida_export qmkdir(const char *file, int mode); + +/// Delete a directory. +/// \param file name (or full path) of directory to be removed +/// \return 0 success +/// \return -1 otherwise and qerrno is set + +idaman THREAD_SAFE int ida_export qrmdir(const char *file); + +/// Does the given file exist? + +idaman THREAD_SAFE bool ida_export qfileexist(const char *file); + + +/// Does the given path specify a directory? + +idaman THREAD_SAFE bool ida_export qisdir(const char *file); + +/// Get file status +idaman THREAD_SAFE int ida_export qstat(const char *path, struct qstatbuf *buf); +idaman THREAD_SAFE int ida_export qfstat(int fd, struct qstatbuf *buf); + +//--------------------------------------------------------------------------- +/// Add a function to be called at exit time + +idaman THREAD_SAFE void ida_export qatexit(void (idaapi *func)(void)); + + +/// Remove a previously added exit-time function + +idaman THREAD_SAFE void ida_export del_qatexit(void (idaapi*func)(void)); + +#endif // SWIG + + +/// Call qatexit functions, shut down UI and kernel, and exit. +/// \param code exit code + +idaman THREAD_SAFE NORETURN void ida_export qexit(int code); + +//--------------------------------------------------------------------------- +#define qmin(a,b) ((a) < (b)? (a): (b)) ///< universal min +#define qmax(a,b) ((a) > (b)? (a): (b)) ///< universal max +#ifdef __cplusplus +template <class T> T qabs(T x) { return x < 0 ? -x : x; } +#else +int qabs(int x) { return x < 0 ? -x : x; } +#endif + +//---------------------------------------------------------------------- +/// Test if 'bit' is set in 'bitmap' +INLINE THREAD_SAFE bool idaapi test_bit(const uchar *bitmap, size_t bit) +{ + return (bitmap[bit/8] & (1<<(bit&7))) != 0; +} +/// Set 'bit' in 'bitmap' +INLINE THREAD_SAFE void idaapi set_bit(uchar *bitmap, size_t bit) +{ + uchar *p = bitmap + bit/8; + *p = (uchar)(*p | (1<<(bit&7))); +} +/// Clear 'bit' in 'bitmap' +INLINE THREAD_SAFE void idaapi clear_bit(uchar *bitmap, size_t bit) +{ + uchar *p = bitmap + bit/8; + *p = (uchar)(*p & ~(1<<(bit&7))); +} +/// Set bits between [low, high) in 'bitmap' +INLINE THREAD_SAFE void idaapi set_bits(uchar *bitmap, size_t low, size_t high) +{ + size_t bit; + for ( bit = low; bit < high; ++bit ) + set_bit(bitmap, bit); +} +/// Clear bits between [low, high) in 'bitmap' +INLINE THREAD_SAFE void idaapi clear_bits(uchar *bitmap, size_t low, size_t high) +{ + size_t bit; + for ( bit = low; bit < high; ++bit ) + clear_bit(bitmap, bit); +} +/// Set first 'nbits' of 'bitmap' +INLINE THREAD_SAFE void idaapi set_all_bits(uchar *bitmap, size_t nbits) +{ + memset(bitmap, 0xFF, (nbits+7)/8); + if ( (nbits & 7) != 0 ) + { + uchar *p = bitmap + nbits/8; + *p = (uchar)(*p & ~((1 << (nbits&7))-1)); + } +} +/// Clear first 'nbits' of 'bitmap' +INLINE THREAD_SAFE void idaapi clear_all_bits(uchar *bitmap, size_t nbits) +{ + memset(bitmap, 0, (nbits+7)/8); +} + +/// calculate ceil(log2(d64)) or floor(log2(d64)), +/// it returns 0 if d64 == 0 +idaman int ida_export log2ceil(uint64 d64); +idaman int ida_export log2floor(uint64 d64); + +/// calculate number of set bits (the population count) +idaman int ida_export bitcount(uint64 x); + +/// round up or down to a power of 2 +idaman uint32 ida_export round_up_power2(uint32 x); +idaman uint32 ida_export round_down_power2(uint32 x); + +#ifdef __cplusplus +//---------------------------------------------------------------------- +/// Functions to work with intervals +namespace interval +{ + /// max offset of the interval (assume s != 0) + inline THREAD_SAFE uval_t last(uval_t off, asize_t s) + { + return off + s - 1; + } + /// Do (off1,s1) and (off2,s2) overlap? + inline THREAD_SAFE bool overlap(uval_t off1, asize_t s1, uval_t off2, asize_t s2) + { + return s1 != 0 && s2 != 0 && off2 <= last(off1, s1) && off1 <= last(off2, s2); + } + /// Does (off1,s1) include (off2,s2)? + inline THREAD_SAFE bool includes(uval_t off1, asize_t s1, uval_t off2, asize_t s2) + { + return s1 != 0 && off2 >= off1 && last(off2, s2) <= last(off1, s1); + } + /// Does (off1,s1) contain off? + inline THREAD_SAFE bool contains(uval_t off1, asize_t s1, uval_t off) + { + return s1 != 0 && off >= off1 && off <= last(off1, s1); + } +} +#endif + +//---------------------------------------------------------------------- +#ifdef __cplusplus +/// Shift by the amount exceeding the operand size*8 is undefined by the standard. +/// Indeed, GNUC may decide not to rotate the operand in some cases. +/// We have to check this manually. +template <class T> T left_shift(const T &value, int shift) +{ + return shift >= sizeof(T)*8 ? 0 : (value << shift); +} +/// \copydoc left_shift +template <class T> T right_ushift(const T &value, int shift) +{ + return shift >= sizeof(T)*8 ? 0 : (value >> shift); +} +/// \copydoc left_shift +template <class T> T right_sshift(const T &value, int shift) +{ + return shift >= sizeof(T)*8 ? (value >= 0 ? 0 : -1) : (value >> shift); +} + +/// Rotate left +template<class T> T qrotl(T value, size_t count) +{ + const size_t nbits = sizeof(T) * 8; + count %= nbits; + + T high = value >> (nbits - count); + value <<= count; + value |= high; + return value; +} + +/// Rotate right +template<class T> T qrotr(T value, size_t count) +{ + const size_t nbits = sizeof(T) * 8; + count %= nbits; + + T low = value << (nbits - count); + value >>= count; + value |= low; + return value; +} + +/// Make a mask of 'count' bits +template <class T> T make_mask(int count) +{ + return left_shift<T>(1, count) - 1; +} + +/// Set a 'bit' in 'where' if 'value' if not zero +template<class T, class U> void idaapi setflag(T &where, U bit, bool cnd) +{ + if ( cnd ) + where = T(where | bit); + else + where = T(where & ~T(bit)); +} + +/// Check that unsigned multiplication does not overflow +template<class T> bool is_mul_ok(T count, T elsize) +{ + CASSERT((T)(-1) > 0); // make sure T is unsigned + if ( elsize == 0 || count == 0 ) + return true; + return count <= ((T)(-1)) / elsize; +} + +/// Check that unsigned or unsigned+signed addition does not overflow +template<class U, class T> bool is_add_ok(U x, T y) +{ + CASSERT((U)(-1) > 0); // make sure U is unsigned + return y >= 0 ? y <= ((U)(-1)) - x : -y <= x; +} + +/// Check that unsigned division is permissible +template <class T> bool is_udiv_ok(T, T b) +{ + CASSERT((T)(-1) > 0); // make sure T is unsigned + return b != 0; // forbid x/0 +} + +/// Check that signed division is permissible +template <class T> bool is_sdiv_ok(T a, T b) +{ + CASSERT((T)(-1) < 0); // make sure T is signed + T minval = left_shift((T)1, sizeof(T)*8-1); + return b != 0 && !(a == minval && b == -1); // forbid x/0, MINVAL/-1 +} + +/// \def{OPERATOR_NEW, GCC does not check for an integer overflow in 'operator new[]'. We have to do it +/// ourselves. Please note that 'char' arrays can still be allocated with +/// plain 'operator new'.} +#ifdef __GNUC__ +# define OPERATOR_NEW(type, count) (is_mul_ok(size_t(count), sizeof(type)) \ + ? new type[count] \ + : (type *)qalloc_or_throw(BADMEMSIZE)) +#else +# define OPERATOR_NEW(type, count) new type[count] +#endif + +#endif // __cplusplus + +//------------------------------------------------------------------------- +/// Sign-, or zero-extend the value 'v' to occupy 64 bits. +/// The value 'v' is considered to be of size 'nbytes'. + +idaman uint64 ida_export extend_sign(uint64 v, int nbytes, bool sign_extend); + + +/// We cannot use multi-character constants because they are not portable - use this macro instead +#define MC2(c1, c2) ushort(((c2)<<8)|c1) +#define MC3(c1, c2, c3) uint32(((((c3)<<8)|(c2))<<8)|c1) ///< \copydoc MC2 +#define MC4(c1, c2, c3, c4) uint32(((((((c4)<<8)|(c3))<<8)|(c2))<<8)|c1) ///< \copydoc MC2 + + +//--------------------------------------------------------------------------- +/// Read at most 4 bytes from file. +/// \param h file handle +/// \param res value read from file +/// \param size size of value in bytes (1,2,4) +/// \param mf is MSB first? +/// \return 0 on success, nonzero otherwise + +idaman THREAD_SAFE int ida_export readbytes(int h, uint32 *res, int size, bool mf); + + +/// Write at most 4 bytes to file. +/// \param h file handle +/// \param l value to write +/// \param size size of value in bytes (1,2,4) +/// \param mf is MSB first? +/// \return 0 on success, nonzero otherwise + +idaman THREAD_SAFE int ida_export writebytes(int h, uint32 l, int size, bool mf); + + +/// Read a 2 byte entity from a file. +/// \param h file handle +/// \param res value read from file +/// \param mf is MSB first? +/// \return 0 on success, nonzero otherwise + +idaman THREAD_SAFE int ida_export read2bytes(int h, uint16 *res, bool mf); + +#define read4bytes(h, res, mf) readbytes(h, res, 4, mf) ///< see readbytes() +#define write2bytes(h, l, mf) writebytes(h, l, 2, mf) ///< see writebytes() +#define write4bytes(h, l, mf) writebytes(h, l, 4, mf) ///< see writebytes() + +//--------------------------------------------------------------------------- +/// \fn{uint32 swap32(uint32 x), Switch endianness of given value} +/// \fn{ushort swap16(ushort x), \copydoc swap32} +/// \def{swap32, Switch endianness of given value} +/// \def{swap16, \copydoc swap32} +#ifdef __cplusplus +# ifndef swap32 +inline THREAD_SAFE uint32 swap32(uint32 x) + { return (x>>24) | (x<<24) | ((x>>8) & 0x0000FF00L) | ((x<<8) & 0x00FF0000L); } +# endif +# ifndef swap16 +inline THREAD_SAFE ushort swap16(ushort x) + { return ushort((x<<8) | (x>>8)); } +# endif +#else +# ifndef swap32 +# define swap32(x) uint32((x>>24) | (x<<24) | ((x>>8) & 0x0000FF00L) | ((x<<8) & 0x00FF0000L)) +# endif +# ifndef swap16 +# define swap16(x) ushort((x<<8) | (x>>8)) +# endif +#endif + +/// \def{swapea, Switch endianness of an ::ea_t value} +#ifdef __EA64__ +#define swapea swap64 +#else +#define swapea swap32 +#endif + +/// \def{qhtons, \copydoc swap32} +/// \def{qntohs, \copydoc swap32} +/// \def{qhtonl, \copydoc swap32} +/// \def{qntohl, \copydoc swap32} +#if __MF__ +#define qhtonl(x) (x) +#define qntohl(x) (x) +#define qhtons(x) (x) +#define qntohs(x) (x) +#else +#define qhtons(x) swap16(x) +#define qntohs(x) swap16(x) +#define qhtonl(x) swap32(x) +#define qntohl(x) swap32(x) +#endif + + +/// Swap endianness of a given value in memory. +/// \param dst result of swap +/// \param src value to be swapped +/// \param size size of value: can be 1, 2, 4, 8, or 16. +/// For any other values of size this function does nothing + +idaman THREAD_SAFE void ida_export swap_value(void *dst, const void *src, int size); + + +idaman THREAD_SAFE void ida_export reloc_value(void *value, int size, adiff_t delta, bool mf); + + +/// Rotate left - can be used to rotate a value to the right if the count is negative. +/// \param x value to rotate +/// \param count shift amount +/// \param bits number of bits to rotate (32 will rotate a dword) +/// \param offset number of first bit to rotate. +/// (bits=8 offset=16 will rotate the third byte of the value) +/// \return the rotated value + +idaman THREAD_SAFE uval_t ida_export rotate_left(uval_t x, int count, size_t bits, size_t offset); + + +#ifdef __cplusplus +/// Swap 2 objects of the same type using memory copies +template <class T> inline THREAD_SAFE void qswap(T &a, T &b) +{ + char temp[sizeof(T)]; + memcpy(&temp, &a, sizeof(T)); + memcpy(&a, &b, sizeof(T)); + memcpy(&b, &temp, sizeof(T)); +} + +//--------------------------------------------------------------------------- +#ifndef SWIG +//-V:unpack_db:656 Variables are initialized through the call to the same function +//-V:unpack_dw:656 +//-V:unpack_dd:656 +//-V:unpack_ea:656 +//-V:unpack_ea64:656 +//-V:unpack_str:656 +//-V:unpack_ds:656 + +/// \defgroup pack Pack/Unpack +/// Functions for packing and unpacking values +//{ + +/// Pack a byte into a character string. +/// This function encodes numbers using an encoding similar to UTF. +/// The smaller the number, the better the packing. +/// \param ptr pointer to output buffer +/// \param end pointer to end of output buffer +/// \param x value to pack +/// \return pointer to end of resulting string + +THREAD_SAFE inline uchar *idaapi pack_db(uchar *ptr, uchar *end, uchar x) +{ + if ( ptr < end ) + *ptr++ = x; + return ptr; +} + + +/// Unpack a byte from a character string, pack_db() + +THREAD_SAFE inline uchar idaapi unpack_db(const uchar **pptr, const uchar *end) +{ + const uchar *ptr = *pptr; + uchar x = 0; + if ( ptr < end ) + x = *ptr++; + *pptr = ptr; + return x; +} + +idaman THREAD_SAFE uchar *ida_export pack_dw(uchar *ptr, uchar *end, uint16 x); ///< pack a word, see pack_db() +idaman THREAD_SAFE uchar *ida_export pack_dd(uchar *ptr, uchar *end, uint32 x); ///< pack a double word, see pack_db() +idaman THREAD_SAFE uchar *ida_export pack_dq(uchar *ptr, uchar *end, uint64 x); ///< pack a quadword, see pack_db() +idaman THREAD_SAFE ushort ida_export unpack_dw(const uchar **pptr, const uchar *end); ///< unpack a word, see unpack_db() +idaman THREAD_SAFE uint32 ida_export unpack_dd(const uchar **pptr, const uchar *end); ///< unpack a double word, see unpack_db() +idaman THREAD_SAFE uint64 ida_export unpack_dq(const uchar **pptr, const uchar *end); ///< unpack a quadword, see unpack_db() + +/// Pack an ea value into a character string, see pack_dd()/pack_dq() + +THREAD_SAFE inline uchar *pack_ea(uchar *ptr, uchar *end, ea_t ea) +{ +#ifdef __EA64__ + return pack_dq(ptr, end, ea); +#else + return pack_dd(ptr, end, ea); +#endif +} + +/// Unpack an ea value, see unpack_dd()/unpack_dq() + +THREAD_SAFE inline ea_t unpack_ea(const uchar **ptr, const uchar *end) +{ +#ifdef __EA64__ + return unpack_dq(ptr, end); +#else + return unpack_dd(ptr, end); +#endif +} + +/// Unpack an ea value (always use 64bit, use delta 1) +THREAD_SAFE inline ea64_t unpack_ea64(const uchar **ptr, const uchar *end) +{ + return unpack_dq(ptr, end) - 1; +} + + +/// Unpack an object of a known size. +/// \param destbuf output buffer +/// \param destsize size of output buffer +/// \param pptr pointer to packed object +/// \param end pointer to end of packed object +/// \return pointer to the destination buffer. +/// if any error, returns NULL. + +THREAD_SAFE inline void *idaapi unpack_obj( + void *destbuf, + size_t destsize, + const uchar **pptr, + const uchar *end) +{ + const uchar *src = *pptr; + const uchar *send = src + destsize; + if ( send < src || send > end ) + return NULL; + *pptr = send; + return memcpy(destbuf, src, destsize); +} + + +/// Unpack an object of an unknown size (packed with append_buf()). +/// \param pptr pointer to packed object +/// \param end pointer to end of packed object +/// \return pointer to the destination buffer, which is allocated in the dynamic memory. \n +/// the caller should use qfree() to deallocate it. \n +/// if any error, returns NULL. \n +/// NB: zero size objects will return NULL too. + +THREAD_SAFE inline void *idaapi unpack_buf(const uchar **pptr, const uchar *end) +{ + size_t size = unpack_dd(pptr, end); + if ( size == 0 ) + return NULL; + const uchar *src = *pptr; + const uchar *srcend = src + size; + if ( srcend < src || srcend > end ) + return NULL; + void *dst = qalloc(size); + if ( dst != NULL ) + { + memcpy(dst, src, size); + *pptr = srcend; + } + return dst; +} + + +/// In-place version of unpack_obj(). +/// It does not copy any data. It just returns a pointer to the object in the packed string. +/// If any error, it returns NULL. + +THREAD_SAFE inline const void *idaapi unpack_obj_inplace( + const uchar **pptr, + const uchar *end, + size_t objsize) +{ + const uchar *ret = *pptr; + const uchar *rend = ret + objsize; + if ( rend < ret || rend > end ) + return NULL; + *pptr = rend; + return ret; +} + + +/// In-place version of unpack_buf(). +/// It does not copy any data. It just returns a pointer to the object in the packed string. +/// If any error, it returns NULL. + +THREAD_SAFE inline const void *idaapi unpack_buf_inplace( + const uchar **pptr, + const uchar *end) +{ + size_t objsize = unpack_dd(pptr, end); + return unpack_obj_inplace(pptr, end, objsize); +} + + +/// Pack a string. +/// \param ptr pointer to output buffer +/// \param end pointer to end of output buffer +/// \param x string to pack. If NULL, empty string is packed +/// \param len number of chars to pack. If 0, the length of given string is used +/// \return pointer to end of packed string + +idaman THREAD_SAFE uchar *ida_export pack_ds( + uchar *ptr, + uchar *end, + const char *x, + size_t len=0); + + +/// Unpack a string. +/// \param pptr pointer to packed string +/// \param end pointer to end of packed string +/// \param empty_null if true, then return NULL for empty strings. \n +/// otherwise return an empty string (not NULL). +/// \return pointer to unpacked string. \n +/// this string will be allocated in dynamic memory. \n +/// the caller should use qfree() to deallocate it. + +idaman THREAD_SAFE char *ida_export unpack_ds( + const uchar **pptr, + const uchar *end, + bool empty_null); + +/// Unpack a string. +/// \param dst pointer to buffer string will be copied to +/// \param dstsize buffer size +/// \param pptr pointer to packed string +/// \param end pointer to end of packed string +/// \return success +THREAD_SAFE inline bool unpack_ds_to_buf( + char *dst, + size_t dstsize, + const uchar **pptr, + const uchar *end) +{ + const void *buf = unpack_buf_inplace(pptr, end); + if ( buf == NULL ) + return false; + size_t size = *pptr - (const uchar *)buf; + if ( size >= dstsize ) + size = dstsize - 1; + memcpy(dst, buf, size); + dst[size] = '\0'; + return true; +} + + +/// Unpack an LEB128 encoded (DWARF-3 style) signed/unsigned value. +/// Do not use this function directly - see \ref unp_templates + +idaman THREAD_SAFE bool ida_export unpack_xleb128( + void *res, + int nbits, + bool is_signed, + const uchar **pptr, + const uchar *end); + +/// \defgroup unp_templates Template unpacking +/// Template functions that can unpack values +//@{ + +template <class T> +inline THREAD_SAFE bool unpack_uleb128(T *res, const uchar **pptr, const uchar *end) +{ + CASSERT((T)(-1) > 0); // make sure T is unsigned + return unpack_xleb128(res, sizeof(T)*8, false, pptr, end); +} + +template <class T> +inline THREAD_SAFE bool unpack_sleb128(T *res, const uchar **pptr, const uchar *end) +{ + CASSERT((T)(-1) < 0); // make sure T is signed + return unpack_xleb128(res, sizeof(T)*8, true, pptr, end); +} + +//@} Template unpacking functions + +// packed sizes +/// \cond +static constexpr int ea_packed_size = sizeof(ea_t) + sizeof(ea_t)/4; // 5 or 10 bytes +static constexpr int dq_packed_size = 10; +static constexpr int dd_packed_size = 5; +static constexpr int dw_packed_size = 3; +/// \endcond + +inline THREAD_SAFE int ds_packed_size(const char *s) { return s ? int(strlen(s)+dd_packed_size) : 1; } + +//---------------------------------------------------------------------------- +inline THREAD_SAFE int dw_size(uchar first_byte) +{ + return (first_byte & 0x80) == 0 ? 1 + : (first_byte & 0xC0) == 0xC0 ? 3 + : 2; +} + +//---------------------------------------------------------------------------- +inline THREAD_SAFE int dd_size(uchar first_byte) +{ + return (first_byte & 0x80) == 0x00 ? 1 + : (first_byte & 0xC0) != 0xC0 ? 2 + : (first_byte & 0xE0) == 0xE0 ? 5 + : 4; +} + +//---------------------------------------------------------------------------- +// unpack data from an object which must have the following functions: +// ssize_t read(void *buf, size_t count) +// bool eof() - return true if there is no more data to read +template <class T> +inline THREAD_SAFE uchar extract_db(T &v) +{ + uchar x = 0; + v.read(&x, 1); + return x; +} + +template <class T> +inline THREAD_SAFE void *extract_obj(T &v, void *destbuf, size_t destsize) +{ + if ( destsize == 0 ) + return NULL; + return v.read(destbuf, destsize) == destsize ? destbuf : NULL; +} + +template <class T> +inline THREAD_SAFE uint16 extract_dw(T &v) +{ + uchar packed[dw_packed_size]; + packed[0] = extract_db(v); + int psize = dw_size(packed[0]); + extract_obj(v, &packed[1], psize-1); + const uchar *ptr = packed; + return unpack_dw(&ptr, packed + psize); +} + +template <class T> +inline THREAD_SAFE uint32 extract_dd(T &v) +{ + uchar packed[dd_packed_size]; + packed[0] = extract_db(v); + int psize = dd_size(packed[0]); + extract_obj(v, &packed[1], psize-1); + const uchar *ptr = packed; + return unpack_dd(&ptr, packed + psize); +} + +template <class T> +inline THREAD_SAFE uint64 extract_dq(T &v) +{ + uint32 l = extract_dd(v); + uint32 h = extract_dd(v); + return make_ulonglong(l, h); +} + +template <class T> +inline THREAD_SAFE ea_t extract_ea(T &v) +{ +#ifdef __EA64__ + return extract_dq(v); +#else + return extract_dd(v); +#endif +} + +template <class T> +inline THREAD_SAFE void *extract_buf(T &v, size_t size) +{ + void *buf = qalloc(size); + if ( buf == NULL ) + return NULL; + return extract_obj(v, buf, size); +} + +template <class T> +inline THREAD_SAFE void *extract_array(T &v, size_t *sz, size_t maxsize) +{ + size_t size = extract_dd(v); + if ( size == 0 || size > maxsize ) + return NULL; + *sz = size; + return extract_buf(v, size); +} + +inline const char *unpack_str(const uchar **pptr, const uchar *end) +{ // zero terminated string, return inplace ptr + const uchar *ptr = *pptr; + const uchar *str = ptr; + do + if ( ptr >= end ) + return nullptr; // no terminating zero? + while ( *ptr++ != '\0' ); + *pptr = ptr; + return (char*)str; +} + +//@} Packing functions +#endif // SWIG +#endif // cplusplus + +/// \name Safe buffer append +/// In the following macros, 'buf' must be always less than 'end'. +/// When we run up to the end, we put a 0 there and don't increase buf anymore +//@{ +/// Append a character to the buffer checking the buffer size +#define APPCHAR(buf, end, chr) \ + do \ + { \ + char __chr = (chr); \ + QASSERT(518, (buf) < (end)); \ + *(buf)++ = __chr; \ + if ( (buf) >= (end) ) \ + { \ + (buf) = (end)-1; \ + (buf)[0] = '\0'; \ + } \ + } while (0) + +/// Put a zero byte at buffer. +/// NB: does not increase buf pointer! +#define APPZERO(buf, end) \ + do \ + { \ + QASSERT(519, (buf) < (end)); \ + *(buf) = '\0'; \ + } while (0) + +/// Append a string to the buffer checking the buffer size +#define APPEND(buf, end, name) \ + do \ + { \ + QASSERT(520, (buf) < (end)); \ + const char *__ida_in = (name); \ + while ( true ) \ + { \ + if ( (buf) == (end)-1 ) \ + { \ + (buf)[0] = '\0'; \ + break; \ + } \ + if ( (*(buf) = *__ida_in++) == '\0' ) \ + break; \ + (buf)++; \ + } \ + } while ( 0 ) +//@} + +/// qalloc() 'size' bytes, and throw a "not enough memory" error if failed + +idaman THREAD_SAFE void *ida_export qalloc_or_throw(size_t size); + + +/// qrealloc() 'ptr' by 'size', and throw a "not enough memory" error if failed + +idaman THREAD_SAFE void *ida_export qrealloc_or_throw(void *ptr, size_t size); + + +/// Change capacity of given qvector. +/// \param vec a pointer to a qvector +/// \param old a pointer to the qvector's array +/// \param cnt number of elements to reserve +/// \param elsize size of each element +/// \return a pointer to the newly allocated array + +idaman THREAD_SAFE void *ida_export qvector_reserve(void *vec, void *old, size_t cnt, size_t elsize); + +#if defined(__cplusplus) + /// \def{PLACEMENT_DELETE, bcc complains about placement delete} + /// \def{DEFINE_MEMORY_ALLOCATION_FUNCS, + /// Convenience macro to declare memory allocation functions. + /// It must be used for all classes that can be allocated/freed by the IDA kernel.} + #if defined(SWIG) + #define DEFINE_MEMORY_ALLOCATION_FUNCS() + #else + #define PLACEMENT_DELETE void operator delete(void *, void *) {} + #define DEFINE_MEMORY_ALLOCATION_FUNCS() \ + void *operator new (size_t _s) { return qalloc_or_throw(_s); } \ + void *operator new[](size_t _s) { return qalloc_or_throw(_s); } \ + void *operator new(size_t /*size*/, void *_v) { return _v; } \ + void operator delete (void *_blk) { qfree(_blk); } \ + void operator delete[](void *_blk) { qfree(_blk); } \ + PLACEMENT_DELETE + #endif + +/// Macro to declare standard inline comparison operators +#define DECLARE_COMPARISON_OPERATORS(type) \ + bool operator==(const type &r) const { return compare(r) == 0; } \ + bool operator!=(const type &r) const { return compare(r) != 0; } \ + bool operator< (const type &r) const { return compare(r) < 0; } \ + bool operator> (const type &r) const { return compare(r) > 0; } \ + bool operator<=(const type &r) const { return compare(r) <= 0; } \ + bool operator>=(const type &r) const { return compare(r) >= 0; } + +/// Macro to declare comparisons for our classes. +/// All comparison operators call the compare() function which returns -1/0/1 +#define DECLARE_COMPARISONS(type) \ + DECLARE_COMPARISON_OPERATORS(type) \ + int compare(const type &r) const + +// Internal declarations to detect movable types +/// \cond +// Can we move around objects of type T using simple memcpy/memmove?. +// This class can be specialized for any type T to improve qvector's behavior. +template <class T> struct ida_movable_type +{ + static constexpr bool value = std::is_pod<T>::value; +}; +#define DECLARE_TYPE_AS_MOVABLE(T) template <> struct ida_movable_type<T> { static constexpr bool value = true; } +template <class T> inline constexpr THREAD_SAFE bool may_move_bytes(void) +{ + return ida_movable_type<T>::value; +} +/// \endcond + +/// Move data down in memory. +/// \param dst destination ptr +/// \param src source ptr +/// \param cnt number of elements to move +template<class T> +inline void shift_down(T *dst, T *src, size_t cnt) +{ + if ( may_move_bytes<T>() ) + { + memmove(dst, src, cnt*sizeof(T)); + } + else + { + ssize_t s = cnt; + while ( --s >= 0 ) + { + new(dst) T(std::move(*src)); + src->~T(); + ++src; + ++dst; + } + } +} +/// Move data up in memory. +/// \param dst destination ptr +/// \param src source ptr +/// \param cnt number of elements to move +template<class T> +inline void shift_up(T *dst, T *src, size_t cnt) +{ + if ( may_move_bytes<T>() ) + { + memmove(dst, src, cnt*sizeof(T)); + } + else + { + ssize_t s = cnt; + dst += s; + src += s; + while ( --s >= 0 ) + { + --src; + --dst; + new(dst) T(std::move(*src)); + src->~T(); + } + } +} + + +//--------------------------------------------------------------------------- +/// Reimplementation of vector class from STL. +/// Only the most essential functions are implemented. \n +/// The vector container accepts objects agnostic to their positions +/// in the memory because it will move them arbitrarily (realloc and memmove). \n +/// The reason why we have it is because it is not compiler dependent +/// (hopefully) and therefore can be used in IDA API. +template <class T> class qvector +{ + T *array; + size_t n, alloc; + friend void *ida_export qvector_reserve(void *vec, void *old, size_t cnt, size_t elsize); + /// Copy contents of given qvector into this one + qvector<T> &assign(const qvector<T> &x) + { + size_t _newsize = x.n; + if ( _newsize > 0 ) + { + array = (T*)qalloc_or_throw(_newsize * sizeof(T)); + alloc = _newsize; + copy_range(x, 0, _newsize); + } + return *this; + } + /// Copies a range of elements from another qvector. + void copy_range(const qvector<T> &x, size_t from, size_t _newsize) + { + if ( std::is_trivially_copyable<T>::value ) + { + memcpy(array + from, x.array + from, (_newsize-from)*sizeof(T)); + } + else + { + for ( size_t i = from; i < _newsize; i++ ) + new(array+i) T(x.array[i]); + } + n = _newsize; + } + /// Resizes to a smaller size, destroying elements if needed. + void resize_less(size_t _newsize) + { + if ( !std::is_trivially_destructible<T>::value ) + { + size_t _size = n; + for ( size_t i = _newsize; i < _size; i++ ) + array[i].~T(); + } + n = _newsize; + } + /// Resizes to a bigger size, and zeroes the new elements (they + /// should be of a std::is_trivially_constructible type). + void resize_more_trivial(size_t _newsize) + { + reserve(_newsize); + memset(array+n, 0, (_newsize-n)*sizeof(T)); + n = _newsize; + } + /// Resizes to a bigger size with a given element. + void resize_more(size_t _newsize, const T &x) + { + reserve(_newsize); + for ( size_t i = n; i < _newsize; i++ ) + new(array+i) T(x); + n = _newsize; + } + + bool ref_within_range(const T &x) const + { + const T *const p = &x; + return p >= array && p < array + alloc; + } + +public: + typedef T value_type; ///< the type of objects contained in this qvector + /// Constructor + qvector(void) : array(NULL), n(0), alloc(0) {} + /// Constructor - creates a new qvector identical to 'x' + qvector(const qvector<T> &x) : array(NULL), n(0), alloc(0) { assign(x); } +#ifndef SWIG + /// Move constructor + qvector(qvector<T> &&x) noexcept + { + array = x.array; x.array = nullptr; + n = x.n; x.n = 0; + alloc = x.alloc; x.alloc = 0; + } +#endif + /// Destructor + ~qvector(void) + { + if ( std::is_trivially_destructible<T>::value ) + qfree(array); + else + clear(); + } + DEFINE_MEMORY_ALLOCATION_FUNCS() + /// Append a new element to the end the qvector. + void push_back(const T &x) + { +#ifdef TESTABLE_BUILD + QASSERT(1907, !ref_within_range(x)); +#endif + reserve(n+1); + new (array+n) T(x); + ++n; + } +#ifndef SWIG + /// Append a new element to the end the qvector with a move semantics. + void push_back(T &&x) + { +#ifdef TESTABLE_BUILD + QASSERT(1977, !ref_within_range(x)); +#endif + reserve(n+1); + new (array+n) T(x); + ++n; + } +#endif + /// Append a new empty element to the end of the qvector. + /// \return a reference to this new element + T &push_back(void) + { + reserve(n+1); + T *ptr = array + n; + new (ptr) T; + ++n; + return *ptr; + } + /// Remove the last element in the qvector + void pop_back(void) + { + if ( n > 0 ) + array[--n].~T(); + } + size_t size(void) const { return n; } ///< Get the number of elements in the qvector + bool empty(void) const { return n == 0; } ///< Does the qvector have 0 elements? + const T &operator[](size_t _idx) const { return array[_idx]; } ///< Allows use of typical c-style array indexing for qvectors + T &operator[](size_t _idx) { return array[_idx]; } ///< Allows use of typical c-style array indexing for qvectors + const T &at(size_t _idx) const { return array[_idx]; } ///< Get element at index '_idx' + T &at(size_t _idx) { return array[_idx]; } ///< Get element at index '_idx' + const T &front(void) const { return array[0]; } ///< Get the first element in the qvector + T &front(void) { return array[0]; } ///< Get the first element in the qvector + const T &back(void) const { return array[n-1]; } ///< Get the last element in the qvector + T &back(void) { return array[n-1]; } ///< Get the last element in the qvector + /// Destroy all elements but do not free memory + void qclear(void) + { + resize_less(0); + } + /// Destroy all elements and free memory + void clear(void) + { + if ( array != NULL ) + { + qclear(); + qfree(array); + array = NULL; + alloc = 0; + } + } + /// Allow assignment of one qvector to another using '=' + qvector<T> &operator=(const qvector<T> &x) + { + if ( this != &x ) + { + clear(); + assign(x); + } + return *this; + } +#ifndef SWIG + /// Move assignment operator + qvector<T> &operator=(qvector<T> &&x) noexcept + { + if ( this != &x ) + { + clear(); + array = x.array; x.array = nullptr; + n = x.n; x.n = 0; + alloc = x.alloc; x.alloc = 0; + } + return *this; + } +#endif + /// Resize to the given size. + /// If the given size (_newsize) is less than the current size (n) of the qvector, then the last n - _newsize elements are simply deleted. \n + /// If the given size is greater than the current size, the qvector is grown to _newsize, and the last _newsize - n elements will be filled with copies of 'x'. \n + /// If the given size is equal to the current size, this function does nothing. + void resize(size_t _newsize, const T &x) + { +#ifdef TESTABLE_BUILD + QASSERT(1908, !ref_within_range(x)); +#endif + if ( _newsize < n ) + resize_less(_newsize); + else if ( _newsize > n ) + resize_more(_newsize, x); + } + /// Same as resize(size_t, const T &), but extra space is filled with empty elements + void resize(size_t _newsize) + { + if ( std::is_trivially_constructible<T>::value && _newsize > n ) + resize_more_trivial(_newsize); + else + resize(_newsize, T()); + } +#ifndef SWIG + // Resize the array but do not initialize elements + void resize_noinit(size_t _newsize) + { + CASSERT(std::is_trivially_constructible<T>::value); + CASSERT(std::is_trivially_destructible<T>::value); + reserve(_newsize); + n = _newsize; + } +#endif + /// Add an element to the end of the qvector, which will be a new T() if x is not given + void grow(const T &x=T()) + { +#ifdef TESTABLE_BUILD + QASSERT(1909, !ref_within_range(x)); +#endif + reserve(n+1); + new(array+n) T(x); + ++n; + } + /// Get the number of elements that this qvector can contain - not the same + /// as the number of elements currently in the qvector (size()) + size_t capacity(void) const { return alloc; } + /// Increase the capacity of the qvector. If cnt is not greater than the current capacity + /// this function does nothing. + void reserve(size_t cnt) + { + if ( cnt > alloc ) + { + if ( may_move_bytes<T>() ) + { + array = (T *)qvector_reserve(this, array, cnt, sizeof(T)); + } + else + { + size_t old_alloc = alloc; + T *new_array = (T *)qvector_reserve(this, NULL, cnt, sizeof(T)); + size_t new_alloc = alloc; + alloc = old_alloc; + shift_down(new_array, array, n); + qfree(array); + array = new_array; + alloc = new_alloc; + } + } + } + /// Shrink the capacity down to the current number of elements + void truncate(void) + { + if ( alloc > n ) + { + array = (T*)qrealloc(array, n*sizeof(T)); // should not fail + alloc = n; + } + } + /// Replace all attributes of this qvector with that of 'r', and vice versa. + /// Effectively sets this = r and r = this without copying/allocating any memory. + void swap(qvector<T> &r) noexcept + { + T *array2 = array; + size_t n2 = n; + size_t alloc2 = alloc; + + array = r.array; + n = r.n; + alloc = r.alloc; + + r.array = array2; + r.n = n2; + r.alloc = alloc2; + } + /// Empty the qvector and return a pointer to it's contents. + /// The caller must free the result of this function + T *extract(void) + { + truncate(); + alloc = 0; + n = 0; + T *res = array; + array = NULL; + return res; + } + /// Populate the qvector with dynamic memory. + /// The qvector must be empty before calling this method! + void inject(T *s, size_t len) + { + array = s; + alloc = len; + n = len; + } + /// Allow ability to test the equality of two qvectors using '=='. + bool operator == (const qvector<T> &r) const + { + if ( n != r.n ) + return false; + for ( size_t i=0; i < n; i++ ) + if ( array[i] != r[i] ) + return false; + return true; + } + /// Allow ability to test equality of two qvectors using '!=' + bool operator != (const qvector<T> &r) const { return !(*this == r); } + + typedef T *iterator; + typedef const T *const_iterator; + + iterator begin(void) { return array; } ///< Get an iterator that points to the first element in the qvector + iterator end(void) { return array + n; } ///< Get an iterator that points to the end of the qvector (NOT the last element) + const_iterator begin(void) const { return array; } ///< Get a const iterator that points to the first element in the qvector + const_iterator end(void) const { return array + n; } ///< Get a const iterator that points to the end of the qvector (NOT the last element) + /// Insert an element into the qvector at a specified position. + /// \param it an iterator that points to the desired position of the new element + /// \param x the element to insert + /// \return an iterator that points to the newly inserted element + iterator insert(iterator it, const T &x) + { +#ifdef TESTABLE_BUILD + QASSERT(1910, !ref_within_range(x)); +#endif + size_t idx = it - array; + reserve(n+1); + T *p = array + idx; + size_t rest = end() - p; + shift_up(p+1, p, rest); + new(p) T(x); + n++; + return iterator(p); + } +#ifndef SWIG + /// Insert an element into the qvector with a move semantics. + iterator insert(iterator it, T &&x) + { +#ifdef TESTABLE_BUILD + QASSERT(1978, !ref_within_range(x)); +#endif + size_t idx = it - array; + reserve(n+1); + T *p = array + idx; + size_t rest = end() - p; + shift_up(p+1, p, rest); + new(p) T(x); + n++; + return iterator(p); + } +#endif + /// Insert a several elements to the qvector at a specified position. + /// \param it position at which new elements will be inserted + /// \param first pointer to first element to be inserted + /// \param last pointer to end of elements to be inserted (the element pointed to by 'last' will not be included) + /// \return an iterator that points to the first newly inserted element. + template <class it2> iterator insert(iterator it, it2 first, it2 last) + { + size_t cnt = last - first; + if ( cnt == 0 ) + return it; + + size_t idx = it - array; + reserve(n+cnt); + T *p = array + idx; + size_t rest = end() - p; + shift_up(p+cnt, p, rest); + while ( first != last ) + { + new(p) T(*first); + ++p; + ++first; + } + n += cnt; + return iterator(array+idx); + } + /// Remove an element from the qvector. + /// \param it pointer to element to be removed + /// \return pointer to the element that took its place + iterator erase(iterator it) + { + it->~T(); + size_t rest = end() - it - 1; + shift_down(it, it+1, rest); + n--; + return it; + } + /// Remove a subset of the qvector. + /// \param first pointer to head of subset to be removed + /// \param last pointer to end of subset to be removed (element pointed to by last will not be removed) + /// \return a pointer to the element that took the place of 'first' + iterator erase(iterator first, iterator last) + { + for ( T *p=first; p != last; ++p ) + p->~T(); + size_t rest = end() - last; + shift_down(first, last, rest); + n -= last - first; + return first; + } + // non-standard extensions: + /// Find an element in the qvector. + /// \param x element to find + /// \return an iterator that points to the first occurrence of 'x' + iterator find(const T &x) + { + iterator p; + const_iterator e; + for ( p=begin(), e=end(); p != e; ++p ) + if ( x == *p ) + break; + return p; + } + /// \copydoc find + const_iterator find(const T &x) const + { + const_iterator p, e; + for ( p=begin(), e=end(); p != e; ++p ) + if ( x == *p ) + break; + return p; + } +#ifndef SWIG + /// Find index of the specified value or return -1 + ssize_t index(const T &x) const + { + for ( const_iterator p=begin(), e=end(); p != e; ++p ) + if ( x == *p ) + return p - begin(); + return -1; + } + /// Add an element to the end of the qvector + void add(const T &x) { push_back(x); } + void add(T &&x) { push_back(x); } +#endif + /// Does the qvector contain x? + bool has(const T &x) const { return find(x) != end(); } + /// Add an element to the end of the qvector - only if it isn't already present. + /// \param x the element to add + /// \return false if 'x' is already in the qvector, true otherwise + bool add_unique(const T &x) + { + if ( has(x) ) + return false; + push_back(x); + return true; + } + /// Find an element and remove it. + /// \param x the element to remove + /// \return false if 'x' was not found, true otherwise + bool del(const T &x) + { + iterator p = find(x); + if ( p == end() ) + return false; + erase(p); + return true; + } +#ifndef SWIG + const char *dstr(void) const; // debug print +#endif +}; + +typedef qvector<uval_t> uvalvec_t; ///< vector of unsigned values +typedef qvector<sval_t> svalvec_t; ///< vector of signed values +typedef qvector<ea_t> eavec_t; ///< vector of addresses +typedef qvector<int> intvec_t; ///< vector of integers +typedef qvector<bool> boolvec_t; ///< vector of bools +typedef qvector<size_t> sizevec_t; ///< vector of sizes + +/// Reimplementation of stack class from STL. +/// The reason why we have it is because it is not compiler dependent +/// (hopefully) and therefore can be used in IDA API +template<class T> +class qstack : public qvector<T> +{ + typedef qvector<T> inherited; +public: + T pop(void) + { + T v = inherited::back(); + inherited::pop_back(); + return v; + } + const T &top(void) const + { + return inherited::back(); + } + T &top(void) { return CONST_CAST(T&)(CONST_CAST(const qstack<T>*)(this)->top()); } + void push(const T &v) + { + inherited::push_back(v); + } +}; + +/// Standard lexical comparison. +/// \return -1 if a < b, 1 if a > b, and 0 if a == b +template <class T> int lexcompare(const T &a, const T &b) +{ + if ( a < b ) + return -1; + if ( a > b ) + return 1; + return 0; +} + +/// Lexical comparison of two vectors. Also see lexcompare(). +/// \return 0 if the two vectors are identical +/// 1 if 'a' is larger than 'b' +/// -1 if 'a' is smaller than 'b' +/// otherwise return the first nonzero lexical comparison between each element in 'a' and 'b' +template <class T> int lexcompare_vectors(const T &a, const T &b) +{ + if ( a.size() != b.size() ) + return a.size() > b.size() ? 1 : -1; + for ( int i=0; i < a.size(); i++ ) + { + int code = lexcompare(a[i], b[i]); + if ( code != 0 ) + return code; + } + return 0; +} + +/// Smart pointer to objects derived from ::qrefcnt_obj_t +template <class T> +class qrefcnt_t +{ + T *ptr; + void delref(void) + { + if ( ptr != NULL && --ptr->refcnt == 0 ) + ptr->release(); + } +public: + explicit qrefcnt_t(T *p) : ptr(p) {} + qrefcnt_t(const qrefcnt_t &r) : ptr(r.ptr) + { + if ( ptr != NULL ) + ptr->refcnt++; + } + qrefcnt_t &operator=(const qrefcnt_t &r) + { + delref(); + ptr = r.ptr; + if ( ptr != NULL ) + ptr->refcnt++; + return *this; + } + ~qrefcnt_t(void) + { + delref(); + } + void reset(void) + { + delref(); + ptr = NULL; + } + operator T *() const + { + return ptr; + } + T *operator ->() const + { + return ptr; + } + T &operator *() const + { + return *ptr; + } +}; + +/// Base class for reference count objects +class qrefcnt_obj_t +{ +public: + int refcnt; ///< counter + /// Constructor + qrefcnt_obj_t(void) : refcnt(1) {} + /// Call destructor. + /// We use release() instead of operator delete() to maintain binary + /// compatibility with all compilers (vc and gcc use different vtable layouts + /// for operator delete) + virtual void idaapi release(void) = 0; +}; + +/// Interface class for iterator types. +template <class T> +class qiterator : public qrefcnt_obj_t +{ +public: + typedef T value_type; + virtual bool idaapi first(void) = 0; + virtual bool idaapi next(void) = 0; + virtual T idaapi operator *(void) = 0; + virtual T get(void) newapi { return this->operator*(); } +}; + + +/// \name strlen +/// Get the length of the given string +//@{ +inline THREAD_SAFE size_t idaapi qstrlen(const char *s) { return strlen(s); } +inline THREAD_SAFE size_t idaapi qstrlen(const uchar *s) { return strlen((const char *)s); } +idaman THREAD_SAFE size_t ida_export qstrlen(const wchar16_t *s); +//@} + +/// \name strcmp +/// Lexical comparison of strings. +/// \return 0 if two strings are identical +/// > 0 if 's1' is larger than 's2' +/// < 0 if 's2' is larger than 's1' +/// otherwise return first nonzero comparison between chars in 's1' and 's2' +//@{ +inline THREAD_SAFE int idaapi qstrcmp(const char *s1, const char *s2) { return strcmp(s1, s2); } +inline THREAD_SAFE int idaapi qstrcmp(const uchar *s1, const uchar *s2) { return strcmp((const char *)s1, (const char *)s2); } +idaman THREAD_SAFE int ida_export qstrcmp(const wchar16_t *s1, const wchar16_t *s2); +//@} + +/// \name strstr +/// Find a string within another string. +/// \return a pointer to the first occurrence of 's2' within 's1', NULL if s2 is not found in s1 +//@{ +inline THREAD_SAFE const char *idaapi qstrstr(const char *s1, const char *s2) { return strstr(s1, s2); } +inline THREAD_SAFE const uchar *idaapi qstrstr(const uchar *s1, const uchar *s2) { return (const uchar *)strstr((const char *)s1, (const char *)s2); } +//@} + +/// \name strchr +/// Find a character within a string. +/// \return a pointer to the first occurrence of 'c' within 's1', NULL if c is not found in s1 +//@{ +inline THREAD_SAFE char *idaapi qstrchr(char *s1, char c) { return strchr(s1, c); } +inline THREAD_SAFE const char *idaapi qstrchr(const char *s1, char c) { return strchr(s1, c); } +inline THREAD_SAFE uchar *idaapi qstrchr(uchar *s1, uchar c) { return (uchar *)strchr((char *)s1, c); } +inline THREAD_SAFE const uchar *idaapi qstrchr(const uchar *s1, uchar c) { return (const uchar *)strchr((const char *)s1, c); } +idaman THREAD_SAFE const wchar16_t *ida_export qstrchr(const wchar16_t *s1, wchar16_t c); +inline THREAD_SAFE wchar16_t *idaapi qstrchr(wchar16_t *s1, wchar16_t c) + { return (wchar16_t *)qstrchr((const wchar16_t *)s1, c); } +//@} + +/// \name qstrrchr +/// Find a last occurrence of a character within a string. +/// \return a pointer to the last occurrence of 'c' within 's1', NULL if c is not found in s1 +//@{ +inline THREAD_SAFE const char *idaapi qstrrchr(const char *s1, char c) { return strrchr(s1, c); } +inline THREAD_SAFE char *idaapi qstrrchr(char *s1, char c) { return strrchr(s1, c); } +inline THREAD_SAFE const uchar *idaapi qstrrchr(const uchar *s1, uchar c) { return (const uchar *)strrchr((const char *)s1, c); } +inline THREAD_SAFE uchar *idaapi qstrrchr(uchar *s1, uchar c) { return (uchar *)strrchr((const char *)s1, c); } +idaman THREAD_SAFE const wchar16_t *ida_export qstrrchr(const wchar16_t *s1, wchar16_t c); +inline THREAD_SAFE wchar16_t *idaapi qstrrchr(wchar16_t *s1, wchar16_t c) + { return (wchar16_t *)qstrrchr((const wchar16_t *)s1, c); } +//@} + + +/// Reimplementation of the string class from STL. +/// Only the most essential functions are implemented. +/// The reason why we have this is because it is not compiler dependent +/// (hopefully) and therefore can be used in IDA API +template<class qchar> +class _qstring //-V:_qstring:690 The class implements the '=' operator, but lacks a copy constructor. It is dangerous to use such a class. +{ + qvector<qchar> body; + void assign(const qchar *ptr, size_t len) + { + body.resize_noinit(len+1); + memmove(body.begin(), ptr, len*sizeof(qchar)); + body[len] = '\0'; + } +public: + /// Constructor + _qstring(void) {} + /// Constructor - creates a new qstring from an existing char * + _qstring(const qchar *ptr) + { + if ( ptr != NULL ) + assign(ptr, ::qstrlen(ptr)); + } + /// Constructor - creates a new qstring using first 'len' chars from 'ptr' + _qstring(const qchar *ptr, size_t len) + { + if ( len > 0 ) + assign(ptr, len); + } + void swap(_qstring<qchar> &r) { body.swap(r.body); } ///< Swap contents of two qstrings. see qvector::swap() + size_t length(void) const { size_t l = body.size(); return l ? l - 1 : 0; } ///< Get number of chars in this qstring (not including terminating zero) + size_t size(void) const { return body.size(); } ///< Get number of chars in this qstring (including terminating zero) + size_t capacity(void) const { return body.capacity(); } ///< Get number of chars this qstring can contain (including terminating zero) + + /// Resize to the given size. + /// The resulting qstring will have length() = s, and size() = s+1 \n + /// if 's' is greater than the current size then the extra space is filled with 'c'. \n + /// if 's' is less than the current size then the trailing chars are removed + void resize(size_t s, qchar c) + { + size_t oldsize = body.size(); + if ( oldsize != 0 && s >= oldsize ) + body[oldsize-1] = c; // erase the terminating zero + body.resize(s+1, c); + body[s] = 0; // ensure the terminating zero + } + /// Similar to resize(size_t, qchar) - but any extra space is filled with zeroes + void resize(size_t s) + { + if ( s == 0 ) + { + body.clear(); + } + else + { + body.resize(s+1); + body[s] = 0; // ensure the terminating zero + } + } + void remove_last(int cnt=1) + { + ssize_t len = body.size() - cnt; + if ( len <= 1 ) + { + body.clear(); + } + else + { + body.resize_noinit(len); + body[len-1] = 0; + } + } + void reserve(size_t cnt) { body.reserve(cnt); } ///< Increase capacity the qstring. see qvector::reserve() + void clear(void) { body.clear(); } ///< Clear qstring and free memory + void qclear(void) { body.qclear(); } ///< Clear qstring but do not free memory yet + bool empty(void) const { return body.size() <= 1; } ///< Does the qstring have 0 non-null elements? + /// Convert the qstring to a char * + const qchar *c_str(void) const + { + static const qchar nullstr[] = { 0 }; + return body.empty() ? nullstr : &body[0]; + } + typedef qchar *iterator; + typedef const qchar *const_iterator; + iterator begin(void) { return body.begin(); } ///< Get a pointer to the beginning of the qstring + const_iterator begin(void) const { return body.begin(); } ///< Get a const pointer to the beginning of the qstring + iterator end(void) { return body.end(); } ///< Get a pointer to the end of the qstring (this is not the terminating zero) + const_iterator end(void) const { return body.end(); } ///< Get a const pointer to the end of the qstring (this is not the terminating zero) + /// Allow assignment of qstrings using '=' + _qstring &operator=(const qchar *str) + { + size_t len = str == NULL ? 0 : ::qstrlen(str); + if ( len > 0 ) + assign(str, len); + else + qclear(); + return *this; + } + _qstring &operator=(const _qstring &qstr) + { + if ( this != &qstr ) + { + size_t len = qstr.length(); + if ( len > 0 ) + assign(qstr.begin(), len); + else + qclear(); + } + return *this; + } + /// Append a char using '+=' + _qstring &operator+=(qchar c) + { + return append(c); + } + /// Append another qstring using '+=' + _qstring &operator+=(const _qstring &r) + { + return append(r); + } + /// Get result of appending two qstrings using '+' + _qstring operator+(const _qstring &r) const + { + _qstring s = *this; + s += r; + return s; + } + DECLARE_COMPARISONS(_qstring) + { + return ::qstrcmp(c_str(), r.c_str()); + } + /// Test equality of a qstring and a const char* using '==' + bool operator==(const qchar *r) const + { + return ::qstrcmp(c_str(), r) == 0; + } + bool operator!=(const qchar *r) const { return !(*this == r); } ///< Test equality of a qstring and a const char* with '!=' + /// Compare two qstrings using '<'. see qstrcmp() + bool operator<(const qchar *r) const + { + return ::qstrcmp(c_str(), r) < 0; + } + /// Retrieve char at index 'idx' using '[]' + const qchar &operator[](size_t idx) const + { + if ( !body.empty() || idx ) + return body[idx]; + static const qchar nullstr[] = { 0 }; + return nullstr[0]; + } + /// Retrieve char at index 'idx' using '[]' + qchar &operator[](size_t idx) + { + if ( !body.empty() || idx ) + return body[idx]; + static qchar nullstr[] = { 0 }; + return nullstr[0]; + } + const qchar &at(size_t idx) const { return body.at(idx); } ///< Retrieve const char at index 'idx' + qchar &at(size_t idx) { return body.at(idx); } ///< Retrieve char at index 'idx' + /// Extract C string from _qstring. Must qfree() it. + qchar *extract(void) { return body.extract(); } + /// Assign this qstring to an existing char *. + /// See qvector::inject(T *, size_t) + void inject(qchar *s, size_t len) + { + body.inject(s, len); + } + /// Same as to inject(qchar *, size_t), with len = strlen(s) + void inject(qchar *s) + { + if ( s != NULL ) + { + size_t len = ::qstrlen(s) + 1; + body.inject(s, len); + } + } + /// Get the last qchar in the string (for concatenation checks) + qchar last(void) const + { + size_t len = length(); + return len == 0 ? '\0' : body[len-1]; + } + /// Find a substring. + /// \param str the substring to look for + /// \param pos starting position + /// \return the position of the beginning of the first occurrence of str, _qstring::npos of none exists + size_t find(const qchar *str, size_t pos=0) const + { + if ( pos <= length() ) + { + const qchar *beg = c_str(); + const qchar *ptr = ::qstrstr(beg+pos, str); + if ( ptr != NULL ) + return ptr - beg; + } + return npos; + } + /// Replace all occurrences of 'what' with 'with'. + /// \return false if 'what' is not found in the qstring, true otherwise + bool replace(const qchar *what, const qchar *with) + { + _qstring result; + size_t len_what = ::qstrlen(what); + const qchar *_start = c_str(); + const qchar *last_pos = _start; + while ( true ) + { + const qchar *pos = ::qstrstr(last_pos, what); + if ( pos == NULL ) + break; + size_t n = pos - last_pos; + if ( n > 0 ) + result.append(last_pos, n); + result.append(with); + last_pos = pos + len_what; + } + // no match at all? + if ( last_pos == _start ) + return false; + // any pending characters? + if ( *last_pos ) + result.append(last_pos); + swap(result); + return true; + } + /// Same as find(const qchar *, size_t), but takes a qstring parameter + size_t find(const _qstring &str, size_t pos=0) const { return find(str.c_str(), pos); } + /// Find a character in the qstring. + /// \param c the character to look for + /// \param pos starting position + /// \return index of first occurrence of 'c' if c is found, _qstring::npos otherwise + size_t find(qchar c, size_t pos=0) const + { + if ( pos <= length() ) + { + const qchar *beg = c_str(); + const qchar *ptr = qstrchr(beg+pos, c); + if ( ptr != NULL ) + return ptr - beg; + } + return npos; + } + /// Search backwards for a character in the qstring. + /// \param c the char to look for + /// \param pos starting position + /// \return index of first occurrence of 'c' if c is found, _qstring::npos otherwise + size_t rfind(qchar c, size_t pos=0) const + { + if ( pos <= length() ) + { + const qchar *beg = c_str(); + const qchar *ptr = qstrrchr(beg+pos, c); + if ( ptr != NULL ) + return ptr - beg; + } + return npos; + } + /// Get a substring. + /// \param pos starting position + /// \param n ending position (non-inclusive) + /// \return the resulting substring + _qstring<qchar> substr(size_t pos=0, size_t n=npos) const + { + size_t endp = qmin(length(), n); + if ( pos >= endp ) + pos = endp; + return _qstring<qchar>(c_str()+pos, endp-pos); + } + /// Remove characters from the qstring. + /// \param idx starting position + /// \param cnt number of characters to remove + _qstring &remove(size_t idx, size_t cnt) + { + size_t len = length(); + if ( idx < len && cnt != 0 ) + { + cnt += idx; + if ( cnt < len ) + { + iterator p1 = body.begin() + cnt; + iterator p2 = body.begin() + idx; + memmove(p2, p1, (len-cnt)*sizeof(qchar)); + idx += len - cnt; + } + body.resize_noinit(idx+1); + body[idx] = '\0'; + } + return *this; + } + /// Insert a character into the qstring. + /// \param idx position of insertion (if idx >= length(), the effect is the same as append) + /// \param c char to insert + _qstring &insert(size_t idx, qchar c) + { + size_t len = length(); + body.resize_noinit(len+2); + body[len+1] = '\0'; + if ( idx < len ) + { + iterator p1 = body.begin() + idx; + memmove(p1+1, p1, (len-idx)*sizeof(qchar)); + len = idx; + } + body[len] = c; + return *this; + } + /// Insert a string into the qstring. + /// \param idx position of insertion (if idx >= length(), the effect is the same as append) + /// \param str the string to insert + /// \param addlen number of chars from 'str' to insert + _qstring &insert(size_t idx, const qchar *str, size_t addlen) + { + size_t len = length(); + body.resize_noinit(len+addlen+1); + body[len+addlen] = '\0'; + if ( idx < len ) + { + iterator p1 = body.begin() + idx; + iterator p2 = p1 + addlen; + memmove(p2, p1, (len-idx)*sizeof(qchar)); + len = idx; + } + memmove(body.begin()+len, str, addlen*sizeof(qchar)); + return *this; + } + /// Same as insert(size_t, const qchar *, size_t), but all chars in str are inserted + _qstring &insert(size_t idx, const qchar *str) + { + if ( str != NULL ) + { + size_t addlen = ::qstrlen(str); + insert(idx, str, addlen); + } + return *this; + } + /// Same as insert(size_t, const qchar *), but takes a qstring parameter + _qstring &insert(size_t idx, const _qstring &qstr) + { + size_t len = length(); + size_t add = qstr.length(); + body.resize_noinit(len+add+1); + body[len+add] = '\0'; + if ( idx < len ) + { + iterator p1 = body.begin() + idx; + iterator p2 = p1 + add; + memmove(p2, p1, (len-idx)*sizeof(qchar)); + len = idx; + } + memcpy(body.begin()+len, qstr.begin(), add*sizeof(qchar)); + return *this; + } + _qstring &insert(qchar c) { return insert(0, c); } ///< Prepend the qstring with 'c' + _qstring &insert(const qchar *str) { return insert(0, str); } ///< Prepend the qstring with 'str' + _qstring &insert(const _qstring &qstr) { return insert(0, qstr); } ///< Prepend the qstring with 'qstr' + /// Append c to the end of the qstring + _qstring &append(qchar c) + { + size_t len = length(); + body.resize_noinit(len+2); + body[len] = c; + body[len+1] = '\0'; + return *this; + } + /// Append a string to the qstring. + /// \param str the string to append + /// \param addlen number of characters from 'str' to append + _qstring &append(const qchar *str, size_t addlen) + { + size_t len = length(); + body.resize_noinit(len+addlen+1); + body[len+addlen] = '\0'; + memmove(body.begin()+len, str, addlen*sizeof(qchar)); + return *this; + } + /// Same as append(const qchar *, size_t), but all chars in 'str' are appended + _qstring &append(const qchar *str) + { + if ( str != NULL ) + { + size_t addlen = ::qstrlen(str); + append(str, addlen); + } + return *this; + } + /// Same as append(const qchar *), but takes a qstring argument + _qstring &append(const _qstring &qstr) + { + size_t add = qstr.length(); + if ( add != 0 ) + { + size_t len = length(); + body.resize_noinit(len+add+1); + body[len+add] = '\0'; + memcpy(body.begin()+len, qstr.begin(), add*sizeof(qchar)); + } + return *this; + } + /// Append result of qvsnprintf() to qstring + AS_PRINTF(2, 0) _qstring &cat_vsprnt(const char *format, va_list va) + { // since gcc64 forbids reuse of va_list, we make a copy for the second call: + va_list copy; + va_copy(copy, va); + size_t add = ::qvsnprintf(NULL, 0, format, va); + if ( add != 0 ) + { + size_t len = length(); + body.resize_noinit(len+add+1); + ::qvsnprintf(body.begin()+len, add+1, format, copy); + } + return *this; + } + /// Replace qstring with the result of qvsnprintf() + AS_PRINTF(2, 0) _qstring &vsprnt(const char *format, va_list va) + { // since gcc64 forbids reuse of va_list, we make a copy for the second call: + va_list copy; + va_copy(copy, va); + body.clear(); + size_t add = ::qvsnprintf(NULL, 0, format, va); + if ( add != 0 ) + { + body.resize_noinit(add+1); + ::qvsnprintf(body.begin(), add+1, format, copy); + } + return *this; + } + /// Append result of qsnprintf() to qstring + AS_PRINTF(2, 3) _qstring &cat_sprnt(const char *format, ...) + { + va_list va; + va_start(va, format); + cat_vsprnt(format, va); + va_end(va); + return *this; + } + /// Replace qstring with the result of qsnprintf() + AS_PRINTF(2, 3) _qstring &sprnt(const char *format, ...) + { + va_list va; + va_start(va, format); + vsprnt(format, va); + va_end(va); + return *this; + } + /// Replace qstring with the result of qsnprintf() + /// \sa inline int nowarn_qsnprintf(char *buf, size_t size, const char *format, ...) + GCC_DIAG_OFF(format-nonliteral); + _qstring &nowarn_sprnt(const char *format, ...) //-V524 body is equal to sprnt + { + va_list va; + va_start(va, format); + vsprnt(format, va); + va_end(va); + return *this; + } + GCC_DIAG_ON(format-nonliteral); + /// Fill qstring with a character. + /// The qstring is resized if necessary until 'len' chars have been filled + /// \param pos starting position + /// \param c the character to fill + /// \param len number of positions to fill with 'c' + _qstring &fill(size_t pos, qchar c, size_t len) + { + size_t endp = pos + len + 1; + if ( body.size() < endp ) + { + body.resize_noinit(endp); + body[endp-1] = '\0'; + } + memset(body.begin()+pos, c, len); + return *this; + } + /// Clear contents of qstring and fill with 'c' + _qstring &fill(qchar c, size_t len) + { + body.qclear(); + if ( len > 0 ) + resize(len, c); + return *this; + } + /// Remove all instances of the specified char from the beginning of the qstring + _qstring <rim(qchar blank = ' ') + { + if ( !empty() ) + { + iterator b = body.begin(); + iterator e = body.end()-1; + while ( b < e && *b == blank ) + b++; + if ( b > body.begin() ) + { + memmove(body.begin(), b, sizeof(qchar)*(e-b+1)); + resize(e-b); + } + } + return *this; + } + /// Remove all instances of the specified char from the end of the qstring + _qstring &rtrim(qchar blank = ' ') + { + if ( !empty() ) + { + iterator b = body.begin(); + iterator e = body.end()-1; + while ( e > b && *(e-1) == blank ) + e--; + resize(e-b); + } + return *this; + } + /// Remove all instances of the specified char from both ends of the qstring + _qstring &trim2(qchar blank = ' ') + { + rtrim(blank); + ltrim(blank); + return *this; + } + /// Invalid position + static constexpr size_t npos = (size_t) -1; +}; +typedef _qstring<char> qstring; ///< regular string +typedef _qstring<uchar> qtype; ///< type string +typedef _qstring<wchar16_t> qwstring; ///< unicode string +typedef qvector<qstring> qstrvec_t; ///< vector of strings +typedef qvector<qwstring> qwstrvec_t; ///< vector of unicode strings + +/// Vector of bytes (use for dynamic memory) +class bytevec_t: public qvector<uchar> +{ +public: + /// Constructor + bytevec_t() {} + /// Constructor - fill bytevec with 'sz' bytes from 'buf' + bytevec_t(const void *buf, size_t sz) { append(buf, sz); } + /// Append bytes to the bytevec + /// \param buf pointer to buffer that will be appended + /// \param sz size of buffer + bytevec_t &append(const void *buf, size_t sz) + { + if ( sz > 0 ) + { + size_t cur_sz = size(); + size_t new_sz = cur_sz + sz; + if ( new_sz < cur_sz ) + new_sz = BADMEMSIZE; // integer overflow, ask too much and it will throw + resize(new_sz); + memcpy(begin() + cur_sz, buf, sz); + } + return *this; + } + /// Pack a byte and append the result to the bytevec + void pack_db(uint8 x) { push_back(x); } + /// Pack a word and append the result to the bytevec + void pack_dw(uint16 x) + { + uchar packed[dw_packed_size]; + size_t len = ::pack_dw(packed, packed+sizeof(packed), x) - packed; + append(packed, len); + } + /// Pack a dword and append the result to the bytevec + void pack_dd(uint32 x) + { + uchar packed[dd_packed_size]; + size_t len = ::pack_dd(packed, packed+sizeof(packed), x) - packed; + append(packed, len); + } + /// Pack a quadword and append the result to the bytevec + void pack_dq(uint64 x) + { + uchar packed[dq_packed_size]; + size_t len = ::pack_dq(packed, packed+sizeof(packed), x) - packed; + append(packed, len); + } + /// Pack an ea value and append the result to the bytevec + void pack_ea(ea_t x) + { + uchar packed[ea_packed_size]; + size_t len = ::pack_ea(packed, packed+sizeof(packed), x) - packed; + append(packed, len); + } + /// Pack an ea value (64bits) and append the result to the bytevec + /// We pass ea_t as a 64-bit quantity (to be able to debug 32-bit programs with ida64) + /// adding 1 to the address ensures that BADADDR is passed correctly. + /// without it, 32-bit server would return 0xffffffff and ida64 would not consider it + /// as a BADADDR. + void pack_ea64(ea64_t ea) + { +#ifdef __X86__ + if ( ea == BADADDR ) + ea = 0xFFFFFFFFFFFFFFFFULL; +#endif + return pack_dq(ea+1); + } + /// Pack a string (length+contents) and append the result to the bytevec + void pack_ds(const char *x) + { + if ( x == nullptr ) + x = ""; + size_t len = strlen(x); +#ifndef __X86__ + QASSERT(4, len <= 0xFFFFFFFF); +#endif + pack_dd(len); + append(x, len); + } + /// Pack a string (zero-terminated) and append the result to the bytevec + void pack_str(const char *str) + { + if ( str == NULL ) + str = ""; + size_t len = strlen(str) + 1; + append(str, len); + } + /// Pack a string (zero-terminated) and append the result to the bytevec + void pack_str(const qstring &s) + { + // the opposite operation is 'unpack_str()' which gets the length + // when it encounters a terminating '\0'. Since we don't store the + // string length, we cannot store zeroes that 's' might contain + // and thus we cannot rely on its length(). + pack_str(s.c_str()); + } + /// Pack an object of size 'len' and append the result to the bytevec + void pack_buf(const void *buf, size_t len) + { +#ifndef __X86__ + QASSERT(5, len <= 0xFFFFFFFF); +#endif + pack_dd(len); + append(buf, len); + } + /// Pack an object of size 'len' and append the result to the bytevec + void pack_bytevec(const bytevec_t &b) + { + pack_buf(b.begin(), b.size()); + } + /// Pack an eavec and append the result to the bytevec. + /// Also see unpack_eavec(). + /// \param ea when we pack an eavec, we only store the differences between each + /// value and this parameter. \n + /// This is because groups of ea values will likely be similar, and therefore + /// the differences will usually be small. \n + /// A good example is packing the addresses of a function prologue. \n + /// One can pass the start ea of the function as this parameter, + /// which results in a quick and efficient packing/unpacking. \n + /// (Just be sure to use the func's start ea when unpacking, of course) + /// \param vec eavec to pack + void pack_eavec(ea_t ea, const eavec_t &vec) + { + int nelems = vec.size(); + pack_dw(nelems); // 16bits, fixme! + ea_t old = ea; + for ( int i=0; i < nelems; i++ ) + { + ea_t nea = vec[i]; + pack_ea(nea-old); + old = nea; + } + } + + /// Grow the bytevec and fill with a value + /// \param sz number of bytes to add to bytevec + /// \param filler filler value + bytevec_t &growfill(size_t sz, uchar filler=0) + { + if ( sz > 0 ) + { + size_t cur_sz = size(); + size_t new_sz = cur_sz + sz; + if ( new_sz < cur_sz ) + new_sz = BADMEMSIZE; // integer overflow, ask too much and it will throw + resize(new_sz, filler); + } + return *this; + } + /// See qvector::inject(T *, size_t) + void inject(void *buf, size_t len) + { + qvector<uchar>::inject((uchar *)buf, len); + } + + /// Append the hexadecimal representation of bytes to the string + void tohex(qstring *out) const + { + size_t len = out->length(); + out->resize(len + size() * 2); + char *p = out->begin() + len; + char *end = out->end(); + for ( uchar c: *this ) + { + ::qsnprintf(p, end - p, "%02X", c); + p += 2; + } + } + /// Initialize from a hexadecimal string + /// It returns 'false' if the string is invalid + bool fromhex(const qstring &str) + { + resize(str.length() / 2); + const char *p = str.begin(); + for ( uchar &c: *this ) + { + uint b = 0; + if ( ::qsscanf(p, "%02X", &b) != 1 || b > 0xFF ) + break; + c = uchar(b); + p += 2; + } + return p == str.begin() + str.length(); + } + + /// Is the specified bit set in the bytevec? + bool test_bit(size_t bit) const { return ::test_bit(begin(), bit); } + /// Set the specified bit + void set_bit(size_t bit) { ::set_bit(begin(), bit); } + /// Clear the specified bit + void clear_bit(size_t bit) { ::clear_bit(begin(), bit); } + /// See set_all_bits(uchar *, size_t) + void set_all_bits(size_t nbits) { resize((nbits+7)/8); ::set_all_bits(begin(), nbits); } + /// See clear_all_bits(uchar *, size_t) + void clear_all_bits(size_t nbits) { ::clear_all_bits(begin(), nbits); } + /// For each bit that is set in 'b', set the corresponding bit in this bytevec + void set_bits(const bytevec_t &b) + { + size_t nbytes = b.size(); + if ( size() < nbytes ) + resize(nbytes); + for ( size_t i=0; i < nbytes; i++ ) + at(i) |= b[i]; + } + /// Set each bit between [low, high) + void set_bits(size_t low, size_t high) { ::set_bits(begin(), low, high); } + /// For each bit that is set in 'b', the clear the corresponding bit in this bytevec + void clear_bits(const bytevec_t &b) + { + size_t nbytes = qmin(size(), b.size()); + iterator p = begin(); + for ( size_t i=0; i < nbytes; i++, ++p ) + *p = (uchar)(*p & ~b[i]); + } + /// Clear each bit between [low, high) + void clear_bits(size_t low, size_t high) { ::clear_bits(begin(), low, high); } +}; + +/// Relocation information (relocatable objects - see ::relobj_t) +struct reloc_info_t : public bytevec_t +{ +/// \defgroup RELOBJ_ Relocatable object info flags +/// used by relobj_t::ri +//@{ +#define RELOBJ_MASK 0xF ///< the first byte describes the relocation entry types +#define RELSIZE_1 0 ///< 8-bit relocations +#define RELSIZE_2 1 ///< 16-bit relocations +#define RELSIZE_4 2 ///< 32-bit relocations +#define RELSIZE_8 3 ///< 64-bit relocations +#define RELSIZE_CUST 15 ///< custom relocations, should be handled internally +#define RELOBJ_CNT 0x80 ///< counter present (not used yet) +//@} +}; + +idaman THREAD_SAFE bool ida_export relocate_relobj(struct relobj_t *_relobj, ea_t ea, bool mf); + +/// Relocatable object +struct relobj_t : public bytevec_t +{ + ea_t base; ///< current base + reloc_info_t ri; ///< relocation info + + relobj_t(void) : base(0) {} + bool relocate(ea_t ea, bool mf) { return relocate_relobj(this, ea, mf); } ///< mf=1:big endian +}; + +#define QLIST_DEFINED ///< signal that the qlist class has been defined +/// Linked list +/// Note: linked list is not movable! +template <class T> class qlist +{ + struct listnode_t + { + listnode_t *next; + listnode_t *prev; + void fix_links(size_t len) + { + if ( len == 0 ) + { + next = this; + prev = this; + } + else + { + next->prev = this; + prev->next = this; + } + } + }; + + struct datanode_t : public listnode_t + { + T data; + }; + + listnode_t node; + size_t length; + + void init(void) + { + node.next = &node; + node.prev = &node; + length = 0; + } + +public: + typedef T value_type; + class const_iterator; +/// Used for defining the 'iterator' and 'const_iterator' classes for qlist +#define DEFINE_LIST_ITERATOR(iter, constness, cstr) \ + class iter \ + { \ + friend class qlist<T>; \ + constness listnode_t *cur; \ + iter(constness listnode_t *x) : cur(x) {} \ + public: \ + typedef constness T value_type; \ + iter(void) : cur(NULL) {} \ + iter(const iter &x) : cur(x.cur) {} \ + cstr \ + iter &operator=(const iter &x) { cur = x.cur; return *this; } \ + bool operator==(const iter &x) const { return cur == x.cur; } \ + bool operator!=(const iter &x) const { return cur != x.cur; } \ + constness T &operator*(void) const { return ((datanode_t*)cur)->data; } \ + constness T *operator->(void) const { return &(operator*()); } \ + iter &operator++(void) /* prefix ++ */ \ + { \ + cur = cur->next; \ + return *this; \ + } \ + iter operator++(int) /* postfix ++ */ \ + { \ + iter tmp = *this; \ + ++(*this); \ + return tmp; \ + } \ + iter &operator--(void) /* prefix -- */ \ + { \ + cur = cur->prev; \ + return *this; \ + } \ + iter operator--(int) /* postfix -- */ \ + { \ + iter tmp = *this; \ + --(*this); \ + return tmp; \ + } \ + }; + DEFINE_LIST_ITERATOR(iterator,, friend class const_iterator; ) + DEFINE_LIST_ITERATOR(const_iterator, const, const_iterator(const iterator &x) : cur(x.cur) {} ) + +/// Used to define qlist::reverse_iterator and qlist::const_reverse_iterator +#define DEFINE_REVERSE_ITERATOR(riter, iter) \ + class riter \ + { \ + iter p; \ + public: \ + riter(void) {} \ + riter(const iter &x) : p(x) {} \ + typename iter::value_type &operator*(void) const { iter q=p; return *--q; } \ + typename iter::value_type *operator->(void) const { return &(operator*()); } \ + riter &operator++(void) { --p; return *this; } \ + riter operator++(int) { iter q=p; --p; return q; } \ + riter &operator--(void) { ++p; return *this; } \ + riter operator--(int) { iter q=p; ++p; return q; } \ + bool operator==(const riter &x) const { return p == x.p; } \ + bool operator!=(const riter &x) const { return p != x.p; } \ + }; + DEFINE_REVERSE_ITERATOR(reverse_iterator, iterator) + DEFINE_REVERSE_ITERATOR(const_reverse_iterator, const_iterator) +#undef DEFINE_LIST_ITERATOR +#undef DEFINE_REVERSE_ITERATOR + /// Constructor + qlist(void) { init(); } + /// Constructor - creates a qlist identical to 'x' + qlist(const qlist<T> &x) + { + init(); + insert(begin(), x.begin(), x.end()); + } + /// Destructor + ~qlist(void) + { + clear(); + } + DEFINE_MEMORY_ALLOCATION_FUNCS() + + /// Construct a new qlist using '=' + qlist<T> &operator=(const qlist<T> &x) + { + if ( this != &x ) + { + iterator first1 = begin(); + iterator last1 = end(); + const_iterator first2 = x.begin(); + const_iterator last2 = x.end(); + while ( first1 != last1 && first2 != last2 ) + *first1++ = *first2++; + if ( first2 == last2 ) + erase(first1, last1); + else + insert(last1, first2, last2); + } + return *this; + } + /// Set this = x and x = this, without copying any memory + void swap(qlist<T> &x) + { + std::swap(node, x.node); + std::swap(length, x.length); + node.fix_links(length); + x.node.fix_links(x.length); + } + + iterator begin(void) { return node.next; } ///< Get a pointer to the head of the list + iterator end(void) { return &node; } ///< Get a pointer to the end of the list + bool empty(void) const { return length == 0; } ///< Get true if the list has 0 elements + size_t size(void) const { return length; } ///< Get the number of elements in the list + T &front(void) { return *begin(); } ///< Get the first element in the list + T &back(void) { return *(--end()); } ///< Get the last element in the list + + const_iterator begin(void) const { return node.next; } ///< \copydoc begin + const_iterator end(void) const { return &node; } ///< \copydoc end + const T&front(void) const { return *begin(); } ///< \copydoc front + const T&back(void) const { return *(--end()); } ///< \copydoc end + + reverse_iterator rbegin() { return reverse_iterator(end()); } ///< Get a reverse iterator that points to end of list. See DEFINE_REVERSE_ITERATOR + reverse_iterator rend() { return reverse_iterator(begin()); } ///< Get a reverse iterator that points to beginning of list. See DEFINE_REVERSE_ITERATOR + const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } ///< See rbegin() + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } ///< See rend() + + /// Insert an element into the qlist. + /// \param p the position to insert the element + /// \param x the element to be inserted + /// \return position of newly inserted element + iterator insert(iterator p, const T &x) + { + datanode_t *tmp = (datanode_t*)qalloc_or_throw(sizeof(datanode_t)); + new (&(tmp->data)) T(x); + linkin(p, tmp); + return tmp; + } + /// Insert an empty element into the qlist. + /// \param p position to insert the element + /// \return reference to this new element + iterator insert(iterator p) + { + datanode_t *tmp = (datanode_t*)qalloc_or_throw(sizeof(datanode_t)); + new (&(tmp->data)) T(); + linkin(p, tmp); + return tmp; + } + /// Insert all elements between 'first' and 'last' (non-inclusive) + /// at position pointed to by 'p' + template <class it2> void insert(iterator p, it2 first, it2 last) + { + while ( first != last ) + insert(p, *first++); + } + /// Insert at beginning of list + void push_front(const T &x) { insert(begin(), x); } + /// Insert at end of list + void push_back(const T &x) { insert(end(), x); } + /// Insert empty element at end of list + T &push_back(void) + { + iterator p = insert(end()); + return ((datanode_t *)p.cur)->data; + } + /// Erase element at position pointed to by 'p' + iterator erase(iterator p) + { + listnode_t *q = p.cur->next; + p.cur->prev->next = p.cur->next; + p.cur->next->prev = p.cur->prev; + ((datanode_t*)p.cur)->data.~T(); + qfree(p.cur); + --length; + return q; + } + /// Erase all elements between 'p1' and 'p2' + void erase(iterator p1, iterator p2) + { + while ( p1 != p2 ) + p1 = erase(p1); + } + /// Erase all elements in the qlist + void clear(void) { erase(begin(), end()); } + /// Erase first element of the qlist + void pop_front(void) { erase(begin()); } + /// Erase last element of the qlist + void pop_back(void) { iterator tmp = end(); erase(--tmp); } + /// Compare two qlists with '==' + bool operator==(const qlist<T> &x) const + { + if ( length != x.length ) + return false; + const_iterator q=x.begin(); + for ( const_iterator p=begin(), e=end(); p != e; ++p,++q ) + if ( *p != *q ) + return false; + return true; + } + /// Compare two qlists with != + bool operator!=(const qlist<T> &x) const { return !(*this == x); } +private: + void linkin(iterator p, listnode_t *tmp) + { + tmp->next = p.cur; + tmp->prev = p.cur->prev; + p.cur->prev->next = tmp; + p.cur->prev = tmp; + ++length; + } +}; + +// Our containers do not care about their addresses. They can be moved around with simple memcpy +/// \cond +template <class T> struct ida_movable_type<qvector<T> > { static constexpr bool value = true; }; +template <class T> struct ida_movable_type<_qstring<T> > { static constexpr bool value = true; }; +template <class T> struct ida_movable_type<qlist<T> > { static constexpr bool value = false; }; +template <class T> struct ida_movable_type<qiterator<T> > { static constexpr bool value = true; }; +/// \endcond + +//---------------------------------------------------------------------------- +#ifndef SWIG +/// Unpack a vector of ea values. +/// \param[out] vec resulting vector +/// \param ea base value that was used to pack the eavec (see pack_eavec()) +/// \param ptr pointer to packed eavec +/// \param end pointer to end of packed eavec + +THREAD_SAFE inline void unpack_eavec( + eavec_t *vec, + ea_t ea, + const uchar **ptr, + const uchar *end) +{ + ea_t old = ea; + int n = unpack_dw(ptr, end); + vec->resize(n); + for ( int i=0; i < n; i++ ) + { + old += unpack_ea(ptr, end); + vec->at(i) = old; + } +} + +THREAD_SAFE inline bool unpack_bytevec( + bytevec_t *out, + const uchar **pptr, + const uchar *end) +{ + uint32 nbytes = unpack_dd(pptr, end); + if ( nbytes == 0 ) + return true; + const size_t old_size = out->size(); + out->resize(old_size + nbytes); + return unpack_obj(out->begin() + old_size, nbytes, pptr, end) != NULL; +} + +inline bool unpack_str(qstring *out, const uchar **pptr, const uchar *end) +{ // zero terminated string, append to qstring + const char *str = unpack_str(pptr, end); + if ( str == nullptr ) + return false; + out->append(str, ((char*)*pptr-str) - 1); + return true; +} + +// Convenience struct for unpacking a data stream +THREAD_SAFE struct memory_deserializer_t +{ + const uchar *ptr; + const uchar *end; + + memory_deserializer_t(const qstring &s) : ptr((uchar*)s.begin()), end(ptr+s.size()) {} + memory_deserializer_t(const bytevec_t &b) : ptr(b.begin()), end(b.end()) {} + memory_deserializer_t(const uchar *p, const uchar *e) : ptr(p), end(e) {} + memory_deserializer_t(const void *p, size_t s) : ptr((uchar*)p), end(ptr+s) {} + bool empty() const { return ptr >= end; } + size_t size() const { return end-ptr; } + bool advance(size_t s) { if ( size() < s ) return false; ptr += s; return true; } + uint8 unpack_db() { return ::unpack_db(&ptr, end); } + uint16 unpack_dw() { return ::unpack_dw(&ptr, end); } + uint32 unpack_dd() { return ::unpack_dd(&ptr, end); } + uint64 unpack_dq() { return ::unpack_dq(&ptr, end); } + ea_t unpack_ea() { return ::unpack_ea(&ptr, end); } + ea64_t unpack_ea64() { return ::unpack_ea64(&ptr, end); } + // unpack zero terminated string + const char *unpack_str() { return ::unpack_str(&ptr, end); } + bool unpack_str(qstring *out) { return ::unpack_str(out, &ptr, end); } + // string with length prefix (dd), return string allocated in the heap + char *unpack_ds(bool empty_null=false) + { + return ::unpack_ds(&ptr, end, empty_null); + } + // string with length prefix (dd), return in the specified buffer + bool unpack_ds_to_buf(char *buf, size_t bufsize) + { + return ::unpack_ds_to_buf(buf, bufsize, &ptr, end); + } + const void *unpack_obj_inplace(size_t objsize) + { + return ::unpack_obj_inplace(&ptr, end, objsize); + } + const void *unpack_buf_inplace() + { + return ::unpack_buf_inplace(&ptr, end); + } + const void *unpack_obj(void *obj, size_t objsize) + { + return ::unpack_obj(obj, objsize, &ptr, end); + } + const void *unpack_buf() + { + return ::unpack_buf(&ptr, end); + } + void unpack_eavec(eavec_t *vec, ea_t ea) + { + ::unpack_eavec(vec, ea, &ptr, end); + } + bool unpack_bytevec(bytevec_t *out) + { + return ::unpack_bytevec(out, &ptr, end); + } + #define SCALAR_TYPE(n) class T, typename std::enable_if<std::is_scalar<T>::value && sizeof(T) == n, int>::type = 0 + template <SCALAR_TYPE(1)> void unpack(T *out) { *out = (T)unpack_db(); } + template <SCALAR_TYPE(2)> void unpack(T *out) { *out = unpack_dw(); } + template <SCALAR_TYPE(4)> void unpack(T *out) { *out = unpack_dd(); } + template <SCALAR_TYPE(8)> void unpack(T *out) { *out = unpack_dq(); } + #undef SCALAR_TYPE + void unpack(qstring *out) { *out = unpack_str(); } + template <class T> + void unpack(qvector<T> *out) + { + uint32 cnt = unpack_dd(); + out->qclear(); + out->reserve(cnt); + for ( size_t i = 0; i < cnt; i++ ) + unpack(&out->push_back()); + } + // linput_t like interface + ssize_t read(void *obj, size_t objsize) { return unpack_obj(obj, objsize) ? objsize : -1; } + bool eof() const { return empty(); } +}; +#define DECLARE_MEMORY_DESERIALIZER(name) \ + name(const void *p, size_t s) : memory_deserializer_t(p, s) {} \ + using memory_deserializer_t::unpack; \ + +#endif // SWIG + +//------------------------------------------------------------------------- +/// Resource janitor to facilitate use of the RAII idiom +template <typename T> +struct janitor_t +{ + janitor_t(T &r) : resource(r) {} ///< Constructor + ~janitor_t(); ///< We provide no implementation for this function, you should + ///< provide specialized implementation yourself +protected: + T &resource; +}; + +#ifndef SWIG +//------------------------------------------------------------------------- +/// Template to compare any 2 values of the same type. Returns -1/0/1 +template <typename, typename = void> +struct has_compare_method : std::false_type {}; +// std::void_t is from c++17, so we declare it ourselves +template< class... > using qvoid_t = void; +template <typename T> +struct has_compare_method<T, qvoid_t<decltype(std::declval<T>().compare(std::declval<T>()))>> + : std::true_type {}; +template <class T, typename std::enable_if<has_compare_method<T>::value, int>::type = 0> +int compare(const T &a, const T &b) +{ + return a.compare(b); +} +template <class T, typename std::enable_if<!has_compare_method<T>::value, int>::type = 0> +int compare(const T &a, const T &b) +{ + if ( a < b ) + return -1; + if ( a > b ) + return 1; + return 0; +} + +//------------------------------------------------------------------------- +template <class T> +int compare(const qvector<T> &a, const qvector<T> &b) +{ + return compare_containers(a, b); +} + +//------------------------------------------------------------------------- +template <class T> +int compare(const qlist<T> &a, const qlist<T> &b) +{ + return compare_containers(a, b); +} + +//------------------------------------------------------------------------- +template <class T, class U> +int compare(const std::pair<T, U> &a, const std::pair<T, U> &b) +{ + int code = compare(a.first, b.first); + if ( code != 0 ) + return code; + return compare(a.second, b.second); +} + +//------------------------------------------------------------------------- +/// Template to compare any 2 containers of the same type. Returns -1/0/1 +template <class T> +int compare_containers(const T &l, const T &r) +{ + auto p = std::begin(l); + auto pe = std::end(l); + auto q = std::begin(r); + auto qe = std::end(r); + for ( ; p != pe && q != qe; ++p,++q ) + { + int code = compare(*p, *q); + if ( code != 0 ) + return code; + } + if ( p == pe && q != qe ) + return -1; + if ( p != pe && q == qe ) + return 1; + return 0; +} + +#define COMPARE_POINTERS2(ptr, cmp) \ + do \ + { \ + if ( ptr != NULL && r.ptr != NULL ) \ + { \ + int _code = cmp(*ptr, *r.ptr); \ + if ( _code != 0 ) \ + return _code; \ + } \ + else if ( r.ptr != NULL ) \ + { \ + return -1; \ + } \ + else if ( ptr != NULL ) \ + { \ + return 1; \ + } \ + } while (0) + +#define COMPARE_POINTERS(ptr) COMPARE_POINTERS2(ptr, ::compare) + +#define COMPARE_FIELDS(fld) \ + do \ + { \ + int _code = ::compare(fld, r.fld); \ + if ( _code != 0 ) \ + return _code; \ + } while (0) + +// reverse order +#define COMPARE_FIELDS_REV(fld) \ + do \ + { \ + int _code = ::compare(r.fld, fld); \ + if ( _code != 0 ) \ + return _code; \ + } while (0) + +template <class T, class U> +int compare(const std::map<T, U> &a, const std::map<T, U> &b) +{ + return compare_containers(a, b); +} + +template <class T> +int compare(const std::set<T> &a, const std::set<T> &b) +{ + return compare_containers(a, b); +} + +#endif + +//------------------------------------------------------------------------- +/// Align element up to nearest boundary +template <class T> T align_up(T val, int elsize) +{ + int mask = elsize - 1; + val += mask; + val &= ~mask; + return val; +} + +//------------------------------------------------------------------------- +/// Align element down to nearest boundary +template <class T> T align_down(T val, int elsize) +{ + int mask = elsize - 1; + val &= ~mask; + return val; +} + +//------------------------------------------------------------------------- +/// Declare class as uncopyable. +/// (copy assignment and copy ctr are undefined, so if anyone calls them, +/// there will be a compilation or link error) +#define DECLARE_UNCOPYABLE(T) T &operator=(const T &); T(const T &); + +#ifndef SWIG +//------------------------------------------------------------------------- +// check the variable type +/// \cond +#define IS_QSTRING(v) (std::is_base_of<qstring, std::remove_reference<decltype(v)>::type>::value) +#define IS_SIZEVEC_T(v) (std::is_base_of<sizevec_t, std::remove_reference<decltype(v)>::type>::value) +#define IS_QSTRVEC_T(v) (std::is_base_of<qstrvec_t, std::remove_reference<decltype(v)>::type>::value) + +/// \endcond +#endif + +#endif // __cplusplus + +#ifndef __cplusplus +typedef struct bytevec_tag bytevec_t; +typedef struct qstring_tag qstring; +typedef struct qwstring_tag qwstring; +#endif + +/// Encode base64 + +idaman THREAD_SAFE bool ida_export base64_encode(qstring *output, const void *input, size_t size); + +/// Decode base64 + +idaman THREAD_SAFE bool ida_export base64_decode(bytevec_t *output, const char *input, size_t size); ///< Decode base64 + + +/// Convert tabulations to spaces +/// \param out output buffer to append to +/// \param str input string. cannot be equal to out->c_str() +/// \param tabsize tabulation size +/// \returns true-replaced some tabs + +idaman THREAD_SAFE bool ida_export replace_tabs(qstring *out, const char *str, int tabsize); + + +/// \defgroup c_str_conv Functions: c strings +/// String C-style conversions (convert \\n to a newline and vice versa) +//@{ +idaman THREAD_SAFE char *ida_export str2user(char *dst, const char *src, size_t dstsize); ///< Make a user representation +idaman THREAD_SAFE char *ida_export user2str(char *dst, const char *src, size_t dstsize); ///< Make an internal representation +idaman THREAD_SAFE char ida_export back_char(const char **p); ///< Translate char after '\\' +#ifdef __cplusplus +idaman THREAD_SAFE void ida_export qstr2user(qstring *dst, const char *src, int nsyms=-1);///< see str2user() +inline THREAD_SAFE void qstr2user(qstring *dst, const qstring &src) { qstr2user(dst, src.c_str(), src.length()); } +idaman THREAD_SAFE void ida_export user2qstr(qstring *dst, const qstring &src); ///< see user2str() +#else +idaman THREAD_SAFE void ida_export qstr2user(qstring *dst, const qstring *src); ///< see str2user() +idaman THREAD_SAFE void ida_export user2qstr(qstring *dst, const qstring *src); ///< see user2str() +#endif +//@} + + +/// Does byte sequence consist of valid UTF-8-encoded codepoints? +/// \param in the byte sequence +/// \returns success + +idaman THREAD_SAFE bool ida_export is_valid_utf8(const char *in); + + +#ifdef __cplusplus + +/// UTF-8 -> UTF-16 +/// \param out the output buffer +/// \param in the input UTF-8 byte stream +/// \param nsyms the number of UTF-8-encoded codepoints in the byte stream +/// \returns success +idaman THREAD_SAFE bool ida_export utf8_utf16(qwstring *out, const char *in, int nsyms=-1); + + +/// UTF-16 -> UTF-8 +/// \param out the output buffer +/// \param in the input UTF-16 stream +/// \param nsyms the number of 16-bit items in 'in'. This does not necessarily +/// correspond to the number of codepoints: each surrogate pair +/// will take 2 items. +/// \returns success +idaman THREAD_SAFE bool ida_export utf16_utf8(qstring *out, const wchar16_t *in, int nsyms=-1); + + +inline bool is_lead_surrogate(wchar32_t wch) { return 0xD800 <= wch && wch < 0xDC00; } +inline bool is_tail_surrogate(wchar32_t wch) { return 0xDC00 <= wch && wch <= 0xDFFF; } +inline wchar32_t utf16_surrogates_to_cp(wchar16_t lead_surrogate, wchar16_t tail_surrogate) +{ + return (0x10000 + (wchar32_t(lead_surrogate & 0x3FF) << 10)) | (tail_surrogate & 0x3FF); +} + + +/// \defgroup IDBDEC_ IDB default encoding -> UTF-8 encoding flags +/// used by idb_utf8 +//@{ +#define IDBDEC_ESCAPE 0x00000001 ///< convert non-printable characters to C escapes (\n, \xNN, \uNNNN) +//@} + +/// IDB default C string encoding -> UTF-8 +/// \returns success (i.e., all bytes converted) + +idaman THREAD_SAFE bool ida_export idb_utf8(qstring *out, const char *in, int nsyms=-1, int flags=0); + + +#ifdef __NT__ +// These are typically used in the text UI (TUI), and +// also to convert argv to UTF-8 at startup. +idaman THREAD_SAFE bool ida_export change_codepage( + qstring *out, + const char *in, + int incp, + int outcp); +#ifndef CP_ACP +#define CP_ACP 0 +#endif +#ifndef CP_OEM +#define CP_OEM 1 +#endif +#ifndef CP_UTF8 +#define CP_UTF8 65001 +#endif +INLINE THREAD_SAFE bool acp_utf8(qstring *out, const char *in) +{ + return change_codepage(out, in, CP_ACP, CP_UTF8); +} +#else // !__NT__ +INLINE THREAD_SAFE bool idaapi change_codepage(qstring *, const char *, int, int) { return false; } +#endif // __NT__ + + +//------------------------------------------------------------------------- +// helpers to compose 16/32-bit wchar's from [M]UTF-8-encoded data +inline THREAD_SAFE wchar16_t utf8_wchar16(uchar b0, uchar b1) +{ + return (wchar16_t(b0 & 0x1f) << 6) | (b1 & 0x3f); +} + +//------------------------------------------------------------------------- +inline THREAD_SAFE wchar16_t utf8_wchar16(uchar b0, uchar b1, uchar b2) +{ + return (wchar16_t(b0 & 0x0f) << 12) + | (wchar16_t(b1 & 0x3f) << 6) + | (b2 & 0x3f); +} + +//------------------------------------------------------------------------- +inline THREAD_SAFE wchar32_t utf8_wchar32(uchar b0, uchar b1, uchar b2, uchar b3) +{ + return (wchar32_t(b0 & 0x07) << 18) + | (wchar32_t(b1 & 0x3f) << 12) + | (wchar32_t(b2 & 0x3f) << 6) + | (b3 & 0x3f); +} + +#endif // __cplusplus + + +#define BADCP wchar32_t(-1) + +/// Read one UTF-8 character from string. if error, return BADCP + +idaman THREAD_SAFE wchar32_t ida_export get_utf8_char(const char **pptr); + + +/// Get the UTF-8 character from string, before 'p'. +/// +/// \param out_cp the output codepoint storage. May be NULL. +/// \param p the pointer, pointing in the 'begin' string right after the UTF-8-encoded codepoint we want to retrieve +/// \param begin the beginning of the string +/// \returns success + +idaman THREAD_SAFE bool ida_export prev_utf8_char(wchar32_t *out_cp, const char **p, const char *begin); + + +/// Advance by n codepoints into the UTF-8 buffer. +/// +/// Each bad byte (i.e., can't be decoded as UTF-8) will count as 1 codepoint. +/// In addition, encountering an unexpected end-of-string (i.e., '\0') will +/// cause this function to stop and return a non-zero value. +/// +/// \param putf8 a pointer to the UTF-8 bytes buffer to advance into +/// \param n the number of codepoints to advance into the buffer +/// \returns the number of codepoints that we failed to decode, thus: +/// 0 - success, >0 - a terminating zero was encountered. + +idaman THREAD_SAFE size_t ida_export skip_utf8(const char **putf8, size_t n); + + +/// Encode the codepoint into a UTF-8 byte sequence, and add terminating zero +/// \param out output buffer (must be at least MAX_UTF8_SEQ_LEN bytes wide) +/// \param cp the codepoint to encode +/// \returns how many bytes were put into the output buffer +/// (without the terminating zero), or size_t(-1) on failure + +idaman THREAD_SAFE ssize_t ida_export put_utf8_char(char *out, wchar32_t cp); + + +/// Is the provided codepoint graphical? + +idaman THREAD_SAFE bool ida_export is_cp_graphical(wchar32_t cp); + + +// Get number of codepoints in UTF-8 string. Any 'bad' byte +// (i.e., can't be decoded) counts for 1 codepoint. + +idaman THREAD_SAFE size_t ida_export qustrlen(const char *utf8); + + +/// A safer strncpy - makes sure that there is a terminating zero. +/// nb: this function doesn't truncate the last UTF-8 character. +/// \sa qstrncpy() +/// \retval false if the input buffer was truncated + +idaman THREAD_SAFE bool ida_export qustrncpy(char *dst, const char *utf8, size_t dstsize); + + +// A few Unicode-related helpful defines + +#define CP_BOM 0xFEFF +#define UTF8_BOM "\xEF\xBB\xBF" +#define UTF8_BOM_SZ (sizeof(UTF8_BOM) - 1) + +#define UTF16LE_BOM "\xFF\xFE" +#define UTF16BE_BOM "\xFE\xFF" +#define UTF16_BOM_SZ (sizeof(UTF16LE_BOM) - 1) + +#define UTF32LE_BOM "\xFF\xFE\x00\x00" +#define UTF32BE_BOM "\x00\x00\xFE\xFF" +#define UTF32_BOM_SZ (sizeof(UTF32LE_BOM) - 1) + +#define CP_ELLIPSIS 0x2026 +#define UTF8_ELLIPSIS "\xE2\x80\xA6" +#define UTF8_ELLIPSIS_SZ (sizeof(UTF8_ELLIPSIS) - 1) + +#define CP_REPLCHAR 0xFFFD +#define UTF8_REPLCHAR "\xEF\xBF\xBD" +#define UTF8_REPLCHAR_SZ (sizeof(UTF8_REPLCHAR) - 1) + + +// To cover unicode, 4 bytes is enough. Still, from the UTF-8 spec at +// https://tools.ietf.org/html/rfc3629: +// "Another security issue occurs when encoding to UTF-8: the ISO/IEC +// 10646 description of UTF-8 allows encoding character numbers up to +// U+7FFFFFFF, yielding sequences of up to 6 bytes. There is therefore +// a risk of buffer overflow if the range of character numbers is not +// explicitly limited to U+10FFFF or if buffer sizing doesn't take into +// account the possibility of 5- and 6-byte sequences." +// Furthermore, since buffers holding UTF-8 sequences are usually placed +// onto the stack, it's probably not a bad thing to make them 8-bytes +// aligned -- and keep room for a terminating zero, too. +#define MAX_UTF8_SEQ_LEN (6 + 1 + 1) + + + +/// \defgroup CEF_ Convert encoding flags +/// used by convert_encoding +//@{ +#define CEF_RETERR 0x1 // return -1 if iconv() returns -1 +//@} + +/// Convert data from encoding fromcode into tocode. +/// \param flags see CEF_* +/// \return number of input bytes converted (can be less than actual size if there was an invalid character) +/// -1 if source or target encoding is not supported +/// possible encoding names: windows codepages ("CP1251" etc), charset names ("Shift-JIS"), and many encodings supported by iconv + +idaman ssize_t ida_export convert_encoding( + bytevec_t *out, + const char *fromcode, + const char *tocode, + const uchar *indata, + ssize_t insize, + DEFARG(int flags,0)); + +#ifdef __cplusplus +inline ssize_t convert_encoding( + bytevec_t *out, + const char *fromcode, + const char *tocode, + const bytevec_t *indata, + DEFARG(int flags,0)) +{ + QASSERT(1451, ssize_t(indata->size()) >= 0); + return convert_encoding(out, fromcode, tocode, indata->begin(), indata->size(), flags); +} +#endif + +#define ENC_WIN1252 "windows-1252" +#define ENC_UTF8 "UTF-8" +#define ENC_MUTF8 "MUTF-8" // modified UTF-8, used by Dalvik and Java (https://en.wikipedia.org/wiki/UTF-8#Modified_UTF-8) +#define ENC_UTF16 "UTF-16" +#define ENC_UTF16LE "UTF-16LE" +#define ENC_UTF16BE "UTF-16BE" +#define ENC_UTF32 "UTF-32" +#define ENC_UTF32LE "UTF-32LE" +#define ENC_UTF32BE "UTF-32BE" + + + +#ifndef CP_UTF8 +#define CP_UTF8 65001 ///< UTF-8 codepage +#endif + +#ifndef CP_UTF16 +#define CP_UTF16 1200 ///< UTF-16 codepage +#endif + +#ifdef __NT__ +# ifndef INVALID_FILE_ATTRIBUTES +# define INVALID_FILE_ATTRIBUTES ((DWORD)-1) ///< old Visual C++ compilers were not defining this +# endif +# ifndef BELOW_NORMAL_PRIORITY_CLASS +# define BELOW_NORMAL_PRIORITY_CLASS 0x00004000 ///< \copydoc INVALID_FILE_ATTRIBUTES +# endif +#endif + +#define SUBSTCHAR '_' ///< default char, used if a char cannot be represented in a codepage + +typedef uint32 flags_t; ///< 32-bit flags for each address +typedef ea_t tid_t; ///< type id (for enums, structs, etc) + +typedef uint32 bgcolor_t; ///< background color in RGB +#define DEFCOLOR bgcolor_t(-1) ///< default color (used in function, segment definitions) + +//------------------------------------------------------------------------- +// Command line +//------------------------------------------------------------------------- + +#ifdef __cplusplus +/// Tools for command line parsing +struct channel_redir_t +{ + int fd; ///< channel number + qstring file; ///< file name to redirect to/from. + ///< if empty, the channel must be closed. + int flags; ///< \ref IOREDIR_ +/// \defgroup IOREDIR_ i/o redirection flags +/// used by channel_redir_t::flags +//@{ +#define IOREDIR_INPUT 0x01 ///< input redirection +#define IOREDIR_OUTPUT 0x02 ///< output redirection +#define IOREDIR_APPEND 0x04 ///< append, do not overwrite the output file +#define IOREDIR_QUOTED 0x08 ///< the file name was quoted +//@} + bool is_input(void) const { return (flags & IOREDIR_INPUT) != 0; } + bool is_output(void) const { return (flags & IOREDIR_OUTPUT) != 0; } + bool is_append(void) const { return (flags & IOREDIR_APPEND) != 0; } + bool is_quoted(void) const { return (flags & IOREDIR_QUOTED) != 0; } + int start; ///< begin of the redirection string in the command line + int length; ///< length of the redirection string in the command line +}; +typedef qvector<channel_redir_t> channel_redirs_t; ///< vector of channel_redir_t objects +#else +typedef struct channel_redirs_tag channel_redirs_t; +typedef struct qstrvec_tag qstrvec_t; +#endif + +/// Parse a space separated string (escaping with backslash is supported). +/// \param[out] args a string vector to hold the results +/// \param[out] redirs map of channel redirections found in cmdline +/// - if NULL, redirections won't be parsed +/// - if there are syntax errors in redirections, consider them as arguments +/// \param cmdline the string to be parsed +/// \param flags #LP_PATH_WITH_ARGS or 0 +/// \return the number of parsed arguments + +idaman THREAD_SAFE size_t ida_export parse_command_line( + qstrvec_t *args, + channel_redirs_t *redirs, + const char *cmdline, + int flags); + + +/// Copy and expand command line arguments. +/// For '@filename' arguments the file contents are inserted into the resulting argv. +/// Format of the file: one switch per line, ';' for comment lines +/// On windows, argv will also be interpreted as OEM codepage, and +/// will be decoded as such and re-encoded into UTF-8. +/// \param[out] p_argc size of the returned argv array +/// \param argc number of entries in argv array +/// \param argv array of strings +/// \return new argv (terminated by NULL). +/// It must be freed with free_argv() + +char **expand_argv(int *p_argc, int argc, const char *const argv[]); + + +/// Free 'argc' elements of 'argv' + +INLINE void free_argv(int argc, char **argv) +{ + int i; + if ( argv != NULL ) + { + for ( i = 0; i < argc; i++ ) + qfree(argv[i]); + qfree(argv); + } +} + + +/// Quote a command line argument if it contains escape characters. +/// For example, *.c will be converted into "*.c" because * may be inadvertently +/// expanded by the shell +/// \return true: modified 'arg' + +idaman bool ida_export quote_cmdline_arg(qstring *arg); + +//------------------------------------------------------------------------- +// Command-line tools +//------------------------------------------------------------------------- +typedef void cliopt_handler_t(const char *value, void *ud); +typedef void cliopt_poly_handler_t(int argc, const char **argv, void *ud); +struct cliopt_t +{ + char shortname; + const char *longname; + const char *help; + cliopt_handler_t *handler; + int nargs; // number of arguments. Can be 0, 1 or -1. + // If '-1', it means 'poly_handler' will be used +}; +DECLARE_TYPE_AS_MOVABLE(cliopt_t); + +struct cliopts_t; +#ifndef SWIG +# define DEFINE_CLIOPTS_T_HELPERS(decl) \ + decl void ida_export cliopts_t_add(cliopts_t &, const cliopt_t *, size_t); \ + decl void ida_export cliopts_t_apply(cliopts_t &, int, const char *[], void *); \ + decl const cliopt_t *ida_export cliopts_t_find_short(const cliopts_t &, char); \ + decl const cliopt_t *ida_export cliopts_t_find_long(const cliopts_t &, const char *); \ + decl NORETURN void ida_export cliopts_t_usage(const cliopts_t &, bool); +#else +# define DEFINE_CLIOPTS_T_HELPERS(decl) +#endif // SWIG +DEFINE_CLIOPTS_T_HELPERS(idaman) + +struct cliopts_t : public qvector<cliopt_t> +{ + qstring prog_name; + qstring epilog; + typedef AS_PRINTF(1, 2) int usage_printer_t(const char *format, ...); + usage_printer_t *printer; + + cliopts_t(usage_printer_t *_printer) + : printer(_printer) {} + + void add(const cliopt_t *opts, size_t nopts) { cliopts_t_add(*this, opts, nopts); } + void apply(int argc, const char *argv[], void *ud=nullptr) { cliopts_t_apply(*this, argc, argv, ud); } + const cliopt_t *find_short(char shortname) const { return cliopts_t_find_short(*this, shortname); } + const cliopt_t *find_long(const char *longname) const { return cliopts_t_find_long(*this, longname); } + void usage(bool is_error=true) const { return cliopts_t_usage(*this, is_error); } + +private: + DEFINE_CLIOPTS_T_HELPERS(friend); +}; + +//------------------------------------------------------------------------- +// INSTANT DEBUGGING +//------------------------------------------------------------------------- + +#ifdef __cplusplus +/// Options for instant debugging +struct instant_dbgopts_t +{ + qstring debmod; ///< name of debugger module + qstring env; ///< config variables for debmod. example: DEFAULT_CPU=13;MAXPACKETSIZE=-1 + qstring host; ///< remote hostname (if remote debugging) + qstring pass; ///< password for the remote debugger server + int port = 0; ///< port number for the remote debugger server + int pid = -1; ///< process to attach to (-1: ask the user) + int event_id = -1; ///< event to trigger upon attaching + bool attach = false; ///< should attach to a process? +}; +#else +struct instant_dbgopts_t; +#endif + +/// Parse the -r command line switch (for instant debugging). +/// r_switch points to the value of the -r switch. Example: win32@localhost+ +/// \return true-ok, false-parse error + +idaman bool ida_export parse_dbgopts(struct instant_dbgopts_t *ido, const char *r_switch); + + +//------------------------------------------------------------------------- +// PROCESSES +//------------------------------------------------------------------------- + +/// Information for launching a process with IDA API +/// Note: all string data such as paths (e.g., 'path', 'args' & 'startdir') +/// or 'env' should be UTF-8 encoded. +struct launch_process_params_t +{ + size_t cb; ///< size of this structure + int flags; ///< \ref LP_ +/// \defgroup LP_ Launch process flags +/// used by launch_process_params_t::flags +//@{ +#define LP_NEW_CONSOLE 0x0001 ///< create new console (only ms windows) +#define LP_TRACE 0x0002 ///< debug: unix: ptrace(TRACEME), windows: DEBUG_PROCESS +#define LP_PATH_WITH_ARGS 0x0004 ///< 'args' contains executable path too +#define LP_USE_SHELL 0x0008 ///< use shell to launch the command. + ///< 'path' is ignored in this case. +#define LP_LAUNCH_32_BIT 0x0010 ///< prefer to launch 32-bit part of file (only mac) +#define LP_LAUNCH_64_BIT 0x0020 ///< prefer to launch 64-bit part of file (only mac) + ///< only one of LP_LAUNCH_*_BIT bits can be specified +#define LP_NO_ASLR 0x0040 ///< disable ASLR (only mac) +#define LP_DETACH_TTY 0x0080 ///< detach the current tty (unix) +#define LP_HIDE_WINDOW 0x0100 ///< tries to hide new window on startup (only windows) +#define LP_SUSPENDED 0x0200 ///< suspends the process on startup (only mac) +//@} + const char *path; ///< file to run + const char *args; ///< command line arguments + ssize_t in_handle; ///< handle for stdin or -1 + ssize_t out_handle; ///< handle for stdout or -1 + ssize_t err_handle; ///< handle for stderr or -1 + char *env; ///< zero separated environment variables that will be appended + ///< to the existing environment block (existing variables will be updated). + ///< each variable has the following form: var=value\0 + ///< must be terminated with two zero bytes! + const char *startdir; ///< current directory for the new process + void *info; ///< os specific info (on windows it points to PROCESS_INFORMATION) + ///< on unix, not used +#ifdef __cplusplus + launch_process_params_t(void) ///< constructor + : cb(sizeof(*this)), flags(0), path(NULL), args(NULL), + in_handle(-1), out_handle(-1), err_handle(-1), + env(NULL), startdir(NULL), info(NULL) {} +#endif +}; + +/// Launch the specified process in parallel. +/// \return handle (unix: child pid), NULL - error + +#ifdef __cplusplus +idaman THREAD_SAFE void *ida_export launch_process( + const launch_process_params_t &lpp, + qstring *errbuf=NULL); +#else +idaman THREAD_SAFE void *ida_export launch_process( + const struct launch_process_params_t *lpp, + qstring *errbuf); +#endif + +/// Forcibly terminate a running process. +/// \returns 0-ok, otherwise an error code that can be passed to winerr() + +idaman THREAD_SAFE int ida_export term_process(void *handle); + + +/// Wait for state changes in a child process (UNIX only). +/// Here: child, status, flags - the same as in system call waitpid() +/// \param timeout_ms timeout in milliseconds + +idaman THREAD_SAFE int ida_export qwait_timed(int *status, int child, int flags, int timeout_ms); + +#if defined(__UNIX__) +# ifdef WCONTINUED +# define QWCONTINUED WCONTINUED +# else +# define QWCONTINUED 8 +# endif +# ifdef WNOHANG +# define QWNOHANG WNOHANG +# else +# define QWNOHANG 1 +# endif +inline THREAD_SAFE int qwait(int *status, int child, int flags) +{ + return qwait_timed(status, child, flags, (flags & QWNOHANG) != 0 ? 0 : -1); +} +#endif + + +/// Check whether process has terminated or not. +/// \param handle process handle to wait for +/// \param[out] exit_code pointer to the buffer for the exit code +/// \param msecs how long to wait. special values: +/// - 0: do not wait +/// - 1 or -1: wait infinitely +/// - other values: timeout in milliseconds +/// \retval 0 process has exited, and the exit code is available. +/// if *exit_code < 0: the process was killed with a signal -*exit_code +/// \retval 1 process has not exited yet +/// \retval -1 error happened, see error code for winerr() in *exit_code + +idaman THREAD_SAFE int ida_export check_process_exit( + void *handle, + int *exit_code, + DEFARG(int msecs,-1)); + +/// Teletype control +enum tty_control_t +{ + TCT_UNKNOWN = 0, + TCT_OWNER, + TCT_NOT_OWNER +}; + + +/// Check if the current process is the owner of the TTY specified +/// by 'fd' (typically an opened descriptor to /dev/tty). + +idaman THREAD_SAFE enum tty_control_t ida_export is_control_tty(int fd); + + +/// If the current terminal is the controlling terminal of the calling +/// process, give up this controlling terminal. +/// \note The current terminal is supposed to be /dev/tty + +idaman THREAD_SAFE void ida_export qdetach_tty(void); + + +/// Make the current terminal the controlling terminal of the calling +/// process. +/// \note The current terminal is supposed to be /dev/tty + +idaman THREAD_SAFE void ida_export qcontrol_tty(void); + +//------------------------------------------------------------------------- +/// THREADS +//------------------------------------------------------------------------- + +/// Thread callback function +typedef int idaapi qthread_cb_t(void *ud); + +/// Thread opaque handle +#ifdef __cplusplus +#define OPAQUE_HANDLE(n) typedef struct __ ## n {} *n +#else +#define OPAQUE_HANDLE(n) typedef struct __ ## n { char __dummy; } *n +#endif +OPAQUE_HANDLE(qthread_t); + + +/// Create a thread and return a thread handle + +idaman THREAD_SAFE qthread_t ida_export qthread_create(qthread_cb_t *thread_cb, void *ud); + + +/// Free a thread resource (does not kill the thread) +/// (calls pthread_detach under unix) + +idaman THREAD_SAFE void ida_export qthread_free(qthread_t q); + + +/// Wait a thread until it terminates + +idaman THREAD_SAFE bool ida_export qthread_join(qthread_t q); + + +/// Forcefully kill a thread (calls pthread_cancel under unix) + +idaman THREAD_SAFE bool ida_export qthread_kill(qthread_t q); + + +/// Get current thread. Must call qthread_free() to free it! + +idaman THREAD_SAFE qthread_t ida_export qthread_self(void); + + +/// Is the current thread the same as 'q'? + +idaman THREAD_SAFE bool ida_export qthread_same(qthread_t q); + + +/// Are two threads equal? + +idaman THREAD_SAFE bool ida_export qthread_equal(qthread_t q1, qthread_t q2); + + +/// Are we running in the main thread? + +idaman THREAD_SAFE bool ida_export is_main_thread(void); + + +/// Thread safe function to work with the environment + +idaman THREAD_SAFE bool ida_export qsetenv(const char *varname, const char *value); +idaman THREAD_SAFE bool ida_export qgetenv(const char *varname, DEFARG(qstring *buf,NULL)); ///< \copydoc qsetenv + + +//------------------------------------------------------------------------- +/// Semaphore. +/// Named semaphores are public, nameless ones are local to the process +//------------------------------------------------------------------------- +OPAQUE_HANDLE(qsemaphore_t); + +idaman THREAD_SAFE qsemaphore_t ida_export qsem_create(const char *name, int init_count); ///< Create a new semaphore +idaman THREAD_SAFE bool ida_export qsem_free(qsemaphore_t sem); ///< Free a semaphore +idaman THREAD_SAFE bool ida_export qsem_post(qsemaphore_t sem); ///< Unlock a semaphore +idaman THREAD_SAFE bool ida_export qsem_wait(qsemaphore_t sem, int timeout_ms); ///< Lock and decrement a semaphore. timeout = -1 means block indefinitely + +//------------------------------------------------------------------------- +/// Mutex +//------------------------------------------------------------------------- +OPAQUE_HANDLE(qmutex_t); +idaman THREAD_SAFE bool ida_export qmutex_free(qmutex_t m); ///< Free a mutex +idaman THREAD_SAFE qmutex_t ida_export qmutex_create(void); ///< Create a new mutex +idaman THREAD_SAFE bool ida_export qmutex_lock(qmutex_t m); ///< Lock a mutex +idaman THREAD_SAFE bool ida_export qmutex_unlock(qmutex_t m); ///< Unlock a mutex + + +#ifdef __cplusplus +/// Mutex locker object. Will lock a given mutex upon creation and unlock it when the object is destroyed +class qmutex_locker_t +{ + qmutex_t lock; +public: + qmutex_locker_t(qmutex_t _lock) : lock(_lock) { qmutex_lock(lock); } + ~qmutex_locker_t(void) { qmutex_unlock(lock); } +}; +#endif + +//------------------------------------------------------------------------- +// PIPES +//------------------------------------------------------------------------- +#ifdef __NT__ +typedef void *qhandle_t; ///< MS Windows HANDLE +const qhandle_t NULL_PIPE_HANDLE = nullptr; +#else +typedef int qhandle_t; ///< file handle in Unix +const qhandle_t NULL_PIPE_HANDLE = -1; +#endif + + +/// Create a pipe. +/// \param[out] handles +/// - handles[0] : read handle +/// - handles[1] : write handle +/// \return error code (0-ok) + +idaman THREAD_SAFE int ida_export qpipe_create(qhandle_t handles[2]); + + +/// Read from a pipe. \return number of read bytes. -1-error + +idaman THREAD_SAFE ssize_t ida_export qpipe_read(qhandle_t handle, void *buf, size_t size); + + +/// Write to a pipe. \return number of written bytes. -1-error + +idaman THREAD_SAFE ssize_t ida_export qpipe_write(qhandle_t handle, const void *buf, size_t size); + + +/// Close a pipe. \return error code (0-ok) + +idaman THREAD_SAFE int ida_export qpipe_close(qhandle_t handle); + + +/// Wait for file/socket/pipe handles. +/// \param[out] idx handle index +/// \param handles handles to wait for +/// \param n number of handles +/// \param write_bitmask bitmask of indexes of handles opened for writing +/// \param timeout_ms timeout value in milliseconds +/// \return error code. on timeout, returns 0 and sets idx to -1 + +idaman THREAD_SAFE int ida_export qwait_for_handles( + int *idx, + const qhandle_t *handles, + int n, + uint32 write_bitmask, + int timeout_ms); + + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED THREAD_SAFE bool ida_export unpack_memory(void *buf, size_t size, const uchar **pptr, const uchar *end); // use unpack_obj +#endif // NO_OBSOLETE_FUNCS + +#endif /* _PRO_H */ diff --git a/idasdk76/include/problems.hpp b/idasdk76/include/problems.hpp new file mode 100644 index 0000000..fca2c77 --- /dev/null +++ b/idasdk76/include/problems.hpp @@ -0,0 +1,104 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _PROBLEMS_HPP +#define _PROBLEMS_HPP + +/*! \file problems.hpp + + \brief Functions that deal with the list of problems. + + There are several problem lists. An address may be inserted to any list. + The kernel simply maintains these lists, no additional processing + is done. + + The problem lists are accessible for the user + from the View->Subviews->Problems menu item. + + Addresses in the lists are kept sorted. In general IDA just maintains + these lists without using them during analysis (except PR_ROLLED). + +*/ + +typedef uchar problist_id_t; ///< see \ref PR_ + +/// \defgroup PR_ Problem types +//@{ +const problist_id_t + PR_NOBASE = 1, ///< Can't find offset base + PR_NONAME = 2, ///< Can't find name + PR_NOFOP = 3, ///< Can't find forced op (not used anymore) + PR_NOCMT = 4, ///< Can't find comment (not used anymore) + PR_NOXREFS = 5, ///< Can't find references + PR_JUMP = 6, ///< Jump by table !!!! ignored + PR_DISASM = 7, ///< Can't disasm + PR_HEAD = 8, ///< Already head + PR_ILLADDR = 9, ///< Exec flows beyond limits + PR_MANYLINES = 10, ///< Too many lines + PR_BADSTACK = 11, ///< Failed to trace the value of the stack pointer + PR_ATTN = 12, ///< Attention! Probably erroneous situation. + PR_FINAL = 13, ///< Decision to convert to instruction/data is made by IDA + PR_ROLLED = 14, ///< The decision made by IDA was wrong and rolled back + PR_COLLISION = 15, ///< FLAIR collision: the function with the given name already exists + PR_DECIMP = 16, ///< FLAIR match indecision: the patterns matched, but not the function(s) being referenced + PR_END = 17; ///< Number of problem types +//@} + +/// Get the human-friendly description of the problem, +/// if one was provided to remember_problem. +/// \param buf a buffer to store the message into. +/// \param t problem list type. +/// \param ea linear address. +/// \return the message length or -1 if none + +idaman ssize_t ida_export get_problem_desc(qstring *buf, problist_id_t t, ea_t ea); + + +/// Insert an address to a list of problems. +/// Display a message saying about the problem (except of ::PR_ATTN,::PR_FINAL) +/// ::PR_JUMP is temporarily ignored. +/// \param type problem list type +/// \param ea linear address +/// \param msg a user-friendly message to be displayed instead of +/// the default more generic one associated with +/// the type of problem. Defaults to NULL. + +idaman void ida_export remember_problem(problist_id_t type, ea_t ea, const char *msg = NULL); + + +/// Get an address from the specified problem list. +/// The address is not removed from the list. +/// \param type problem list type +/// \param lowea the returned address will be higher or equal +/// than the specified address +/// \return linear address or #BADADDR + +idaman ea_t ida_export get_problem(problist_id_t type, ea_t lowea); + + +/// Remove an address from a problem list +/// \param type problem list type +/// \param ea linear address +/// \return success + +idaman bool ida_export forget_problem(problist_id_t type, ea_t ea); + + +/// Get problem list description + +idaman const char *ida_export get_problem_name(problist_id_t type, bool longname=true); + + +/// Check if the specified address is present in the problem list + +idaman bool ida_export is_problem_present(problist_id_t t, ea_t ea); + + +inline bool was_ida_decision(ea_t ea) { return is_problem_present(PR_FINAL, ea); } + + +#endif // _PROBLEMS_HPP diff --git a/idasdk76/include/prodir.h b/idasdk76/include/prodir.h new file mode 100644 index 0000000..adfe987 --- /dev/null +++ b/idasdk76/include/prodir.h @@ -0,0 +1,172 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _PRODIR_H +#define _PRODIR_H + +//-V:qffblk_t:730 not all members of a class are initialized inside the constructor +//-V:qffblk64_t:730 + + +/*! \file prodir.h + + \brief Unified interface to qfindfirst(),qfindnext(),qfindclose() functions. + + These are low level functions, it is better to use enumerate_files2(). +*/ + +/// \def{DIRCHAR, Path separator} +/// \def{SDIRCHAR, Path separator as a string} +/// \def{DRVCHAR, Windows drive separator} +#ifdef __NT__ +#define __FAT__ +#define SDIRCHAR "\\" +#define DIRCHAR '\\' +#define DRVCHAR ':' +#else +#define SDIRCHAR "/" +#define DIRCHAR '/' +#endif + +/// Extension character is '.' for all systems +#define EXTCHAR '.' + +//---------------------------------------------------------------------------- +/// \struct{qffblk_t, Various file statistics returned by qfind()-like functions} +/// \var{qffblk_t::ff_name, file path} +/// \var{qffblk_t::ff_fsize, file size} +/// \var{qffblk_t::ff_attrib, file attribute} +/// \var{qffblk_t::ff_ftime, file time stamp (ms dos fat format)} +/// \var{qffblk_t::ff_fdate, file date stamp (ms dos fat format)} +/// \def{FA_RDONLY, File cannot be opened for writing} +/// \def{FA_DIREC, Directory} +/// \def{FA_ARCH, File has not been backed up} +/// \def{MAXPATH, Size limit of qffblk_t::ff_name} +#if defined(__UNIX__) + #define MAXPATH QMAXPATH + struct qffblk_t // Unix + { + // user fields: + int ff_attrib; + #define FA_DIREC S_IFDIR + #define FA_ARCH 0 + #define FA_RDONLY 0 + char ff_name[QMAXPATH]; + uint32 ff_fsize; + uint16 ff_fdate; + uint16 ff_ftime; + // private fields: + void *filelist; + int fileidx, fileqty; + char dirpath[QMAXPATH]; + char pattern[QMAXPATH]; + int attr; + qffblk_t(void) : filelist(NULL), fileqty(0) {} + }; +#elif !defined(__X86__) + // Win64 - use Visual Studio's ffblk + #define MAXPATH _MAX_PATH + struct qffblk_t + { + // inlined __finddata64_t from Visual Studio (for compatibility with IDA 7.0 API) + unsigned attrib; + // Time values are stored in UTC format. + __time64_t time_create; // -1 for FAT file systems + __time64_t time_access; // -1 for FAT file systems + __time64_t time_write; + __int64 size; + char name[260]; // NB: file name is assumed to be UTF-8 + intptr_t handle; // handle returned by _wfindfirst64 + int attr; // attr value passed to qfindfirst. only FA_DIREC is checked + #define FA_RDONLY 0x01 + #define FA_DIREC 0x10 + #define FA_ARCH 0x20 + #define ff_name name + #define ff_attrib attrib + #define ff_fsize size + unsigned short ff_ftime; // FAT/DOS format modification time + unsigned short ff_fdate; // FAT/DOS format modification date + qffblk_t(void) : handle(-1) {} + }; + CASSERT(sizeof(qffblk_t) == 0x140); +#else + #define MAXPATH 260 + struct qffblk_t // Win32 - use Borland's ffblk (IDA 6.95 API compatibility) + { + long ff_reserved; + long ff_fsize; + unsigned long ff_attrib; + #define FA_RDONLY 0x01 + #define FA_DIREC 0x10 + #define FA_ARCH 0x20 + unsigned short ff_ftime; + unsigned short ff_fdate; + char ff_name[MAXPATH]; + qffblk_t(void) : ff_reserved(0) {} + }; +#endif + +/// \def{MAXDRIVE, Max drive name size} +/// \def{MAXDIR, Max directory name size} +/// \def{MAXFILE, Max file name size} +/// \def{MAXEXT, Max file extension size} +#if defined(__UNIX__) + #define MAXDRIVE QMAXPATH + #define MAXDIR QMAXPATH + #define MAXFILE QMAXPATH + #define MAXEXT QMAXPATH +#else + #define MAXDRIVE _MAX_DRIVE + #define MAXDIR _MAX_DIR + #define MAXFILE _MAX_FNAME + #define MAXEXT _MAX_EXT +#endif + +/// Find first file that matches the pattern. +/// \param pattern file name pattern, usually with * and ? wildcards +/// \param blk structure that will hold the answer. +/// blk->ff_name will hold the file name, for example. +/// \param attr the desired file types (#FA_DIREC for directories only or 0 for both directories and files) +/// \return 0 if found a file, other values mean error (check qerrno) + +idaman THREAD_SAFE int ida_export qfindfirst( + const char *pattern, + struct qffblk64_t *blk, + int attr); + + +/// Find next file that matches the pattern. +/// \param blk structure that holds the current state. +/// blk->ff_name will hold the next file name upon return. +/// \return 0 if found the next file, other values mean error (check qerrno) + +idaman THREAD_SAFE int ida_export qfindnext(struct qffblk64_t *blk); + +/// Stop the file enumeration and free internal structures. +/// \note usually there is no need to call this function manually, it is called +/// from the ::qffblk64_t destructor. +/// \param blk file enumeration structure + +idaman THREAD_SAFE void ida_export qfindclose(struct qffblk64_t *blk); + + +/// Common structure with 64-bit ff_fsize - see ::qffblk_t. +struct qffblk64_t +{ + int ff_attrib; + char ff_name[QMAXPATH]; + uint64 ff_fsize; + uint16 ff_fdate; + uint16 ff_ftime; + // private field + struct qffblk_t base; + + qffblk64_t(void) {} + ~qffblk64_t(void) { qfindclose(this); } +}; + +#endif // _PRODIR_H diff --git a/idasdk75/include/pronet.h b/idasdk76/include/pronet.h similarity index 100% rename from idasdk75/include/pronet.h rename to idasdk76/include/pronet.h diff --git a/idasdk76/include/range.hpp b/idasdk76/include/range.hpp new file mode 100644 index 0000000..951ed75 --- /dev/null +++ b/idasdk76/include/range.hpp @@ -0,0 +1,290 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _RANGE_HPP +#define _RANGE_HPP + +/*! \file range.hpp + + \brief Contains the definition of ::range_t. + + A range is a non-empty continuous range of addresses (specified by + its start and end addresses, the end address is excluded from the + range). + + Ranges are stored in the Btree part of the IDA database. + To learn more about Btrees (Balanced Trees): + http://www.bluerwhite.org/btree/ +*/ + +#ifndef SWIG +struct range_t; +/// Helper function. Should not be called directly! +idaman size_t ida_export range_t_print(const range_t *, char *buf, size_t bufsize); +#endif + +//-------------------------------------------------------------------------- +/// Base class for an range. This class is used as a base class for +/// a class with real information - see segment.hpp for example. +/// The end address points beyond the range. +struct range_t +{ + friend size_t ida_export range_t_print(const range_t *cb, char *buf, size_t bufsize); + ea_t start_ea; ///< start_ea included + ea_t end_ea; ///< end_ea excluded + /// Constructor + range_t(void) : start_ea(0), end_ea(0) {} + /// Constructor + range_t(ea_t ea1, ea_t ea2) : start_ea(ea1), end_ea(ea2) {} + + /// Compare two range_t instances, based on the start_ea + int compare(const range_t &r) const { return start_ea > r.start_ea ? 1 : start_ea < r.start_ea ? -1 : 0; } + + bool operator ==(const range_t &r) const { return compare(r) == 0; } ///< Compare two range_t's with '==' + bool operator !=(const range_t &r) const { return compare(r) != 0; } ///< Compare two range_t's with '!=' + bool operator > (const range_t &r) const { return compare(r) > 0; } ///< Compare two range_t's with '<' + bool operator < (const range_t &r) const { return compare(r) < 0; } ///< Compare two range_t's with '>' + + /// Is 'ea' in the address range? + bool contains(ea_t ea) const { return start_ea <= ea && end_ea > ea; } + + /// Is every ea in 'r' also in this range_t? + bool contains(const range_t &r) const { return r.start_ea >= start_ea && r.end_ea <= end_ea; } + + /// Is there an ea in 'r' that is also in this range_t? + bool overlaps(const range_t &r) const { return r.start_ea < end_ea && start_ea < r.end_ea; } + + /// Set #start_ea, #end_ea to 0 + void clear(void) { start_ea = end_ea = 0; } + + /// Is the size of the range_t <= 0? + bool empty(void) const { return start_ea >= end_ea; } + + /// Get #end_ea - #start_ea + asize_t size(void) const { return end_ea - start_ea; } + + /// Assign the range_t to the intersection between the range_t and 'r' + void intersect(const range_t &r) + { + if ( start_ea < r.start_ea ) + start_ea = r.start_ea; + if ( end_ea > r.end_ea ) + end_ea = r.end_ea; + if ( end_ea < start_ea ) + end_ea = start_ea; + } + + /// Ensure that the range_t includes 'ea' + void extend(ea_t ea) + { + if ( start_ea > ea ) + start_ea = ea; + if ( end_ea < ea ) + end_ea = ea; + } + + /// Print the range_t. + /// \param buf the output buffer + /// \param bufsize the size of the buffer + size_t print(char *buf, size_t bufsize) const { return range_t_print(this, buf, bufsize); } +}; +DECLARE_TYPE_AS_MOVABLE(range_t); +typedef qvector<range_t> rangevec_base_t; +struct rangevec_t : public rangevec_base_t /// Vector of range_t instances +{ +}; + +//-------------------------------------------------------------------------- +// Various kinds of ranges, see +// \ref idb_event::changing_range_cmt +// \ref idb_event::range_cmt_changed +enum range_kind_t +{ + RANGE_KIND_UNKNOWN, + RANGE_KIND_FUNC, ///< \ref func_t + RANGE_KIND_SEGMENT, ///< \ref segment_t + RANGE_KIND_HIDDEN_RANGE, ///< \ref hidden_range_t +}; + +//-------------------------------------------------------------------------- +/// Helper functions. Should not be called directly! +#ifndef SWIG +#define RANGESET_HELPER_DEFINITIONS(decl) \ +decl bool ida_export rangeset_t_add(rangeset_t *, const range_t &range);\ +decl bool ida_export rangeset_t_sub(rangeset_t *, const range_t &range);\ +decl bool ida_export rangeset_t_add2(rangeset_t *, const rangeset_t &aset);\ +decl bool ida_export rangeset_t_sub2(rangeset_t *, const rangeset_t &aset);\ +decl bool ida_export rangeset_t_has_common(const rangeset_t *, const range_t &range, bool strict);\ +decl bool ida_export rangeset_t_has_common2(const rangeset_t *, const rangeset_t &aset);\ +decl bool ida_export rangeset_t_contains(const rangeset_t *, const rangeset_t &aset);\ +decl size_t ida_export rangeset_t_print(const rangeset_t *, char *buf, size_t bufsize);\ +decl bool ida_export rangeset_t_intersect(rangeset_t *, const rangeset_t &aset);\ +decl const range_t *ida_export rangeset_t_find_range(const rangeset_t *, ea_t ea);\ +decl ea_t ida_export rangeset_t_next_addr(const rangeset_t *, ea_t ea);\ +decl ea_t ida_export rangeset_t_prev_addr(const rangeset_t *, ea_t ea);\ +decl ea_t ida_export rangeset_t_next_range(const rangeset_t *, ea_t ea);\ +decl ea_t ida_export rangeset_t_prev_range(const rangeset_t *, ea_t ea);\ +decl rangevec_t::const_iterator ida_export rangeset_t_lower_bound(const rangeset_t *, ea_t ea);\ +decl rangevec_t::const_iterator ida_export rangeset_t_upper_bound(const rangeset_t *, ea_t ea);\ +decl void ida_export rangeset_t_swap(rangeset_t *, rangeset_t &r); +#else +#define RANGESET_HELPER_DEFINITIONS(decl) +#endif // SWIG + +class rangeset_t; + +RANGESET_HELPER_DEFINITIONS(idaman) + +/// An ordered set of non-overlapping address ranges +class rangeset_t +{ + rangevec_t bag; + mutable const range_t *cache; + int undo_code = -1; + + RANGESET_HELPER_DEFINITIONS(friend) + bool verify(void) const; +public: + DEFINE_MEMORY_ALLOCATION_FUNCS() + /// Constructor + rangeset_t(void) : cache(NULL) {} + /// Constructor - Initialize set with 'range' + rangeset_t(const range_t &range): cache(NULL) { if ( !range.empty() ) bag.push_back(range); } + /// Constructor - Initialize set with 'ivs' + rangeset_t(const rangeset_t &ivs) : bag(ivs.bag), cache(NULL) {} + rangeset_t &operator=(const rangeset_t &ivs) { bag = ivs.bag; cache = NULL; return *this; } + /// Set this = 'r' and 'r' = this. See qvector::swap() + void swap(rangeset_t &r) { rangeset_t_swap(this, r); } + + /// Add an address range to the set. + /// If 'range' intersects an existing element e, then e is extended + /// to include 'range', and any superfluous elements (subsets of e) are removed. + /// \param range address range to add. cannot be empty + /// \return false if 'range' was not added (the set was unchanged) + bool add(const range_t &range) { return rangeset_t_add(this, range); } + + /// Create a new range_t from 'start' and 'end' and add it to the set + bool add(ea_t start, ea_t _end) { return add(range_t(start, _end)); } + + /// Add each element of 'aset' to the set. + /// \return false if no elements were added (the set was unchanged) + bool add(const rangeset_t &aset) { return rangeset_t_add2(this, aset); } + + /// Subtract an address range from the set. + /// All subsets of 'range' will be removed, and all elements that intersect + /// 'range' will be truncated/split so they do not include 'range'. + /// \param range address range to subtract. cannot be empty. + /// \return false if 'range' was not subtracted (the set was unchanged) + bool sub(const range_t &range) { return rangeset_t_sub(this, range); } + + /// Subtract an ea (an range of size 1) from the set. See sub(const range_t &) + bool sub(ea_t ea) { return sub(range_t(ea, ea+1)); } + + /// Subtract each range in 'aset' from the set + /// \return false if nothing was subtracted (the set was unchanged) + bool sub(const rangeset_t &aset) { return rangeset_t_sub2(this, aset); } + + /// Is there an ea in 'range' that is also in the rangeset? + bool has_common(const range_t &range) const + { return rangeset_t_has_common(this, range, false); } + + /// Is every ea in 'range' contained in the rangeset? + bool includes(const range_t &range) const + { return rangeset_t_has_common(this, range, true); } + + /// Print each range_t in the rangeset + size_t print(char *buf, size_t bufsize) const + { return rangeset_t_print(this, buf, bufsize); } + + /// Size in bytes + asize_t count(void) const; + + /// Get the range_t at index 'idx' + const range_t &getrange(int idx) const { return bag[idx]; } + + /// Get the last range_t in the set + const range_t &lastrange(void) const { return bag.back(); } + + /// Get the number of range_t elements in the set + size_t nranges(void) const { return bag.size(); } + + /// Does the set have zero elements + bool empty(void) const { return bag.empty(); } + + /// Delete all elements from the set. See qvector::clear() + void clear(void) { bag.clear(); cache = NULL; } + + /// Does any element of 'aset' overlap with an element in this rangeset?. See range_t::overlaps() + bool has_common(const rangeset_t &aset) const + { return rangeset_t_has_common2(this, aset); } + + /// Does an element of the rangeset contain 'ea'? See range_t::contains(ea_t) + bool contains(ea_t ea) const { return !empty() && find_range(ea) != NULL; } + + /// Is every element in 'aset' contained in an element of this rangeset?. See range_t::contains(range_t) + bool contains(const rangeset_t &aset) const + { return rangeset_t_contains(this, aset); } + + /// Set the rangeset to its intersection with 'aset'. + /// \return false if the set was unchanged + bool intersect(const rangeset_t &aset) + { return rangeset_t_intersect(this, aset); } + + /// Is every element in the rangeset contained in an element of 'aset'? + bool is_subset_of(const rangeset_t &aset) const { return aset.contains(*this); } + + /// Do this rangeset and 'aset' have identical elements? + bool is_equal(const rangeset_t &aset) const { return bag == aset.bag; } + + bool operator==(const rangeset_t &aset) const { return is_equal(aset); } ///< Compare two rangesets with '==' + bool operator!=(const rangeset_t &aset) const { return !is_equal(aset); } ///< Compare two rangesets with '!=' + + typedef rangevec_t::iterator iterator; ///< Iterator for rangesets + typedef rangevec_t::const_iterator const_iterator; ///< Const iterator for rangesets + const_iterator begin(void) const { return bag.begin(); } ///< Get an iterator that points to the first element in the set + const_iterator end(void) const { return bag.end(); } ///< Get an iterator that points to the end of the set. (This is NOT the last element) + iterator begin(void) { return bag.begin(); } ///< \copydoc begin + iterator end(void) { return bag.end(); } ///< \copydoc end + + /// Get the first range that contains at least one ea_t value greater than 'ea' + const_iterator lower_bound(ea_t ea) const { return rangeset_t_lower_bound(this, ea); } + + /// Get the first range such that every ea_t value in this range is strictly greater than 'ea' + const_iterator upper_bound(ea_t ea) const { return rangeset_t_upper_bound(this, ea); } + + /// Get the element from the set that contains 'ea'. + /// \return NULL if there is no such element + const range_t *find_range(ea_t ea) const + { return rangeset_t_find_range(this, ea); } + + /// When searching the rangeset, we keep a cached element to help speed up searches. + /// \return a pointer to the cached element + const range_t *cached_range(void) const { return cache; } + + /// Get the smallest ea_t value greater than 'ea' contained in the rangeset + ea_t next_addr(ea_t ea) const { return rangeset_t_next_addr(this, ea); } + + /// Get the largest ea_t value less than 'ea' contained in the rangeset + ea_t prev_addr(ea_t ea) const { return rangeset_t_prev_addr(this, ea); } + + /// Get the smallest ea_t value greater than 'ea' that is not in the same range as 'ea' + ea_t next_range(ea_t ea) const { return rangeset_t_next_range(this, ea); } + + /// Get the largest ea_t value less than 'ea' that is not in the same range as 'ea' + ea_t prev_range(ea_t ea) const { return rangeset_t_prev_range(this, ea); } + + /// Subtract the address range (from, from+size) and add the range (to, to+size) + int move_chunk(ea_t from, ea_t to, asize_t size); + + /// TODO: return code borrowed from va.hpp, same with move_chunk() + int check_move_args(ea_t from, ea_t to, asize_t size); +}; +DECLARE_TYPE_AS_MOVABLE(rangeset_t); +typedef qvector<rangeset_t> array_of_rangesets; ///< Array of rangeset_t objects +typedef qvector<const rangeset_t*> rangeset_crefvec_t; + +#endif // _RANGE_HPP diff --git a/idasdk76/include/regex.h b/idasdk76/include/regex.h new file mode 100644 index 0000000..c6f8c1d --- /dev/null +++ b/idasdk76/include/regex.h @@ -0,0 +1,239 @@ +/************************************************* +* Perl-Compatible Regular Expressions * +*************************************************/ + +/* PCRE2 is a library of functions to support regular expressions whose syntax +and semantics are as close as possible to those of the Perl 5 language. + + Written by Philip Hazel + Original API code Copyright (c) 1997-2012 University of Cambridge + New API code Copyright (c) 2016 University of Cambridge + +----------------------------------------------------------------------------- +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of the University of Cambridge nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +----------------------------------------------------------------------------- +*/ + + +#ifndef _REGEX_H_ +#define _REGEX_H_ +#ifdef __cplusplus +#include <kernwin.hpp> +#endif + +#include <pro.h> + +#ifdef __GNUC__ +#undef __P +#endif + +typedef off_t regoff_t; +/* The structure representing a compiled regular expression. */ + +struct regex_t +{ + int re_magic; + size_t re_nsub; /* number of parenthesized subexpressions */ + const char *re_endp; /* end pointer for REG_PEND */ + void *re_g; /* none of your business :-) */ +}; + +/* The structure in which a captured offset is returned. */ + +struct regmatch_t +{ + regoff_t rm_so; /* start of match */ + regoff_t rm_eo; /* end of match */ +}; +#ifndef REG_ICASE +/* Options, mostly defined by POSIX, but with some extras. */ + +#define REG_ICASE 0x0001 /* Maps to PCRE2_CASELESS */ +#define REG_NEWLINE 0x0002 /* Maps to PCRE2_MULTILINE */ +#define REG_NOTBOL 0x0004 /* Maps to PCRE2_NOTBOL */ +#define REG_NOTEOL 0x0008 /* Maps to PCRE2_NOTEOL */ +#define REG_DOTALL 0x0010 /* NOT defined by POSIX; maps to PCRE2_DOTALL */ +#define REG_NOSUB 0x0020 /* Maps to PCRE2_NO_AUTO_CAPTURE */ +#define REG_UTF 0x0040 /* NOT defined by POSIX; maps to PCRE2_UTF */ +#define REG_STARTEND 0x0080 /* BSD feature: pass subject string by so,eo */ +#define REG_NOTEMPTY 0x0100 /* NOT defined by POSIX; maps to PCRE2_NOTEMPTY */ +#define REG_UNGREEDY 0x0200 /* NOT defined by POSIX; maps to PCRE2_UNGREEDY */ +#define REG_UCP 0x0400 /* NOT defined by POSIX; maps to PCRE2_UCP */ + +/* This is not used by PCRE2, but by defining it we make it easier +to slot PCRE2 into existing programs that make POSIX calls. */ + +#define REG_EXTENDED 0 +#define REG_TRACE 0 // unsupported by PCRE2 + +/* Error values. Not all these are relevant or used by the wrapper. */ + + +enum +{ + REG_ASSERT = 1, /* internal error ? */ + REG_BADBR, /* invalid repeat counts in {} */ + REG_BADPAT, /* pattern error */ + REG_BADRPT, /* ? * + invalid */ + REG_EBRACE, /* unbalanced {} */ + REG_EBRACK, /* unbalanced [] */ + REG_ECOLLATE, /* collation error - not relevant */ + REG_ECTYPE, /* bad class */ + REG_EESCAPE, /* bad escape sequence */ + REG_EMPTY, /* empty expression */ + REG_EPAREN, /* unbalanced () */ + REG_ERANGE, /* bad range inside [] */ + REG_ESIZE, /* expression too big */ + REG_ESPACE, /* failed to get memory */ + REG_ESUBREG, /* bad back reference */ + REG_INVARG, /* bad argument */ + REG_NOMATCH /* match failed */ +}; +#endif //REG_ICASE + +/* The functions */ + +// compile the regular expression +idaman THREAD_SAFE int ida_export qregcomp( + struct regex_t *preg, + const char *pattern, + int cflags); + +// mapping from error codes returned by qregcomp() and qregexec() to a string +idaman THREAD_SAFE size_t ida_export qregerror( + int errcode, + const struct regex_t *preg, + char *errbuf, + size_t errbuf_size); + +// match regex against a string +idaman THREAD_SAFE int ida_export qregexec( + const struct regex_t *preg, + const char *str, + size_t nmatch, + struct regmatch_t pmatch[], + int eflags); + +// free any memory allocated by qregcomp +idaman THREAD_SAFE void ida_export qregfree(struct regex_t *preg); + + +#ifdef __cplusplus + +//------------------------------------------------------------------------- +class refcnted_regex_t : public qrefcnt_obj_t +{ + regex_t regex; + + refcnted_regex_t() + { + regex = {}; + } + virtual ~refcnted_regex_t() + { + qregfree(®ex); + } +public: + virtual void idaapi release(void) override + { + delete this; + } + int exec(const char *string, size_t nmatch, regmatch_t pmatch[], int eflags) + { + return qregexec(®ex, string, nmatch, pmatch, eflags); + } + int process_errors(int code, qstring *errmsg) + { + if ( code != 0 && errmsg != NULL ) + { + char errbuf[MAXSTR]; + qregerror(code, ®ex, errbuf, sizeof(errbuf)); + *errmsg = errbuf; + } + return code; + } + static refcnted_regex_t *create(const qstring &text, bool case_insensitive, qstring *errmsg) + { + if ( text.empty() ) + return NULL; + refcnted_regex_t *p = new refcnted_regex_t(); + int rflags = REG_EXTENDED; + if ( case_insensitive ) + rflags |= REG_ICASE; + int code = qregcomp(&p->regex, text.begin(), rflags); + if ( p->process_errors(code, errmsg) != 0 ) + { + // It is unnecessary to qregfree() here: the deletion of 'p' will + // call qregfree (but anyway, even that is unnecessary, because + // if we end up here, it means qregcomp() failed, and when that + // happens, qregcomp() frees the regex itself.) + delete p; + p = NULL; + } + return p; + } + size_t nsub(void) + { + /* number of parenthesized subexpressions */ + return regex.re_nsub; + } + DECLARE_UNCOPYABLE(refcnted_regex_t); +}; +typedef qrefcnt_t<refcnted_regex_t> regex_ptr_t; + +//--------------------------------------------------------------------------- +struct regex_cache_t +{ + regex_ptr_t &find_or_create(const qstring &str) + { + regex_cache_map_t::iterator it = cache.find(str); + if ( it == cache.end() ) + { + qstring errmsg; + regex_ptr_t rx = regex_ptr_t(refcnted_regex_t::create(str, false, &errmsg)); + if ( rx == NULL ) + error("%s", errmsg.c_str()); + it = cache.insert(regex_cache_map_t::value_type(str, rx)).first; + } + return it->second; + } + +private: + typedef std::map<qstring,regex_ptr_t> regex_cache_map_t; + regex_cache_map_t cache; +}; + +#endif //__cplusplus + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED THREAD_SAFE int ida_export regcomp(struct regex_t *preg, const char *pattern, int cflags); +idaman DEPRECATED THREAD_SAFE size_t ida_export regerror(int errcode, const struct regex_t *preg, char *errbuf, size_t errbuf_size); +idaman DEPRECATED THREAD_SAFE int ida_export regexec(const struct regex_t *preg, const char *str, size_t nmatch, struct regmatch_t pmatch[], int eflags); +idaman DEPRECATED THREAD_SAFE void ida_export regfree(struct regex_t *preg); +#endif + +#endif /* !_REGEX_H_ */ diff --git a/idasdk76/include/registry.hpp b/idasdk76/include/registry.hpp new file mode 100644 index 0000000..b016c10 --- /dev/null +++ b/idasdk76/include/registry.hpp @@ -0,0 +1,375 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __REGISTRY_HPP +#define __REGISTRY_HPP + +/*! \file registry.hpp + + \brief Registry related functions + + IDA uses the registry to store global configuration options that must + persist after IDA has been closed. + + On Windows, IDA uses the Windows registry directly. On Unix systems, the registry + is stored in a file (typically ~/.idapro/ida.reg). + + The root key for accessing IDA settings in the registry is defined by #ROOT_KEY_NAME. +*/ + +/// Key used to store IDA settings in registry (Windows version). +/// \note this name is automatically prepended to all +/// key names passed to functions in this file. +#define ROOT_KEY_NAME "Software\\Hex-Rays\\IDA" + +/// \cond +// Low level functions. DO NOT USE THEM. See the wrappers below. +// 'mode' is: +// - 0: data is a raw buffer, and its datalen must be able to hold the entire binary contents +// - 1: data is a raw buffer, and its datalen doesn't need to be able to hold the entire binary contents +// - 2: data is a ::bytevec_t*, datalen is ignored. +idaman bool ida_export reg_bin_op( + const char *name, + bool save, + void *data, + size_t datalen, + const char *subkey, + int mode = 0); +idaman bool ida_export reg_str_get(qstring *buf, const char *name, const char *subkey); +idaman void ida_export reg_str_set(const char *name, const char *subkey, const char *buf); +idaman int ida_export reg_int_op( + const char *name, + bool save, + int value, + const char *subkey = NULL); +/// \endcond + +/// Types of values stored in the registry +enum regval_type_t +{ + reg_unknown = 0, ///< unknown + reg_sz = 1, ///< utf8 string + reg_binary = 3, ///< binary data + reg_dword = 4 ///< 32-bit number +}; + + +/// Delete a key from the registry +idaman bool ida_export reg_delete_subkey(const char *name); + +/// Delete a subtree from the registry +idaman bool ida_export reg_delete_tree(const char *name); + +/// Delete a value from the registry. +/// \param name value name +/// \param subkey parent key +/// \return success + +idaman bool ida_export reg_delete(const char *name, const char *subkey = NULL); + + +/// Is there already a key with the given name? + +idaman bool ida_export reg_subkey_exists(const char *name); + + +/// Is there already a value with the given name? +/// \param name value name +/// \param subkey parent key + +idaman bool ida_export reg_exists(const char *name, const char *subkey = NULL); + + +/// Retrieve the child names of the given key. +/// \param out result +/// \param name key name +/// \param subkeys if true, collect subkey names. if false, collect value names. +/// \return false if the given key does not exist + +idaman bool ida_export reg_subkey_children(qstrvec_t *out, const char *name, bool subkeys); + + +/// Get data type of a given value. +/// \param out result +/// \param name value name +/// \param subkey key name +/// \return false if the [key+]value doesn't exist + +idaman bool ida_export reg_data_type(regval_type_t *out, const char *name, const char *subkey = NULL); + + +/// Retrieve all string values associated with the given key. +/// Also see reg_update_strlist(). + +idaman void ida_export reg_read_strlist(qstrvec_t *list, const char *subkey); + + +/// Update list of strings associated with given key. +/// \param subkey key name +/// \param add string to be added to list, can be NULL +/// \param maxrecs limit list to this size +/// \param rem string to be removed from list, can be NULL +/// \param ignorecase ignore case for 'add' and 'rem' + +idaman void ida_export reg_update_strlist( + const char *subkey, + const char *add, + size_t maxrecs, + const char *rem = NULL, + bool ignorecase = false); + + +/// Write binary data to the registry. +/// \param name value name +/// \param data input, must not be NULL +/// \param datalen length of input in bytes +/// \param subkey key name + +inline void reg_write_binary( + const char *name, + const void *data, + size_t datalen, + const char *subkey = NULL) +{ + reg_bin_op(name, true, CONST_CAST(void *)(data), datalen, subkey); +} + + +/// Read binary data from the registry. +/// \param name value name +/// \param[out] data result, must not be NULL +/// \param datalen length of out buffer in bytes +/// \param subkey key name +/// \return false if 'data' is not large enough to hold all data present. +/// in this case 'data' is left untouched. + +inline bool reg_read_binary( + const char *name, + void *data, + size_t datalen, + const char *subkey = NULL) +{ + return reg_bin_op(name, false, data, datalen, subkey); +} + + +/// Read a chunk of binary data from the registry. +/// This function succeeds even in the case of a partial read. +/// \param name value name +/// \param[out] data result, must not be NULL +/// \param datalen length of output buffer in bytes +/// \param subkey key name +/// \return success + +inline bool reg_read_binary_part( + const char *name, + void *data, + size_t datalen, + const char *subkey = NULL) +{ + return reg_bin_op(name, false, data, datalen, subkey, 1); +} + + +/// Read binary data from the registry. +/// \param name value name +/// \param[out] data output buffer, must not be NULL +/// \param subkey key name +/// \return success + +inline bool reg_read_binary( + const char *name, + bytevec_t *data, + const char *subkey = NULL) +{ + return reg_bin_op(name, false, data, 0, subkey, 2); +} + + +/// Write a string to the registry. +/// \param name value name +/// \param utf8 utf8-encoded string +/// \param subkey key name + +inline void reg_write_string( + const char *name, + const char *utf8, + const char *subkey = NULL) +{ + reg_str_set(name, subkey, utf8); +} + + +/// Read a string from the registry. +/// \param[out] utf8 output buffer +/// \param name value name +/// \param subkey key name +/// \return success + +inline bool reg_read_string( + qstring *utf8, + const char *name, + const char *subkey = NULL) +{ + return reg_str_get(utf8, name, subkey); +} + + +/// Read integer value from the registry. +/// \param name value name +/// \param defval default value +/// \param subkey key name +/// \return the value read from the registry, or 'defval' if the read failed + +inline int reg_read_int(const char *name, int defval, const char *subkey = NULL) +{ + return reg_int_op(name, false, defval, subkey); +} + + +/// Write integer value to the registry. +/// \param name value name +/// \param value value to write +/// \param subkey key name + +inline void reg_write_int(const char *name, int value, const char *subkey = NULL) +{ + reg_int_op(name, true, value, subkey); +} + + +/// Read boolean value from the registry. +/// \param name value name +/// \param defval default value +/// \param subkey key name +/// \return boolean read from registry, or 'defval' if the read failed + +inline bool reg_read_bool(const char *name, bool defval, const char *subkey = NULL) +{ + return reg_int_op(name, false, int(defval), subkey) != 0; +} + + +/// Write boolean value to the registry. +/// \param name value name +/// \param value boolean to write (nonzero = true) +/// \param subkey key name + +inline void reg_write_bool(const char *name, int value, const char *subkey = NULL) +{ + reg_int_op(name, true, value != 0, subkey); +} + + +/// Get all subkey names of given key + +inline bool reg_subkey_subkeys(qstrvec_t *out, const char *name) +{ + return reg_subkey_children(out, name, true); +} + + +/// Get all value names under given key + +inline bool reg_subkey_values(qstrvec_t *out, const char *name) +{ + return reg_subkey_children(out, name, false); +} + + +/// Update registry with a file list. +/// Case sensitivity will vary depending on the target OS. +/// \note 'add' and 'rem' must be UTF-8, just like for regular string operations. + +inline void reg_update_filestrlist( + const char *subkey, + const char *add, + size_t maxrecs, + const char *rem = NULL) +{ + reg_update_strlist( + subkey, add, maxrecs, rem, + #ifdef __NT__ // Ignore case in Windows + true + #else + false + #endif + ); +} + +//----------------------------------------------------------------------------- +// INTERNALS + +/// \cond +#define _RVN_(f) regname_ ## f + +#ifndef __DEFINE_REG_NAMES__ +#define REG_VAL_NAME(n,s) \ + extern const char _RVN_(n)[] +#else +#define REG_VAL_NAME(n,s) \ + extern const char _RVN_(n)[]; \ + const char _RVN_(n)[] = s +#endif + +#define REG_BOOL_FUNC(func, valname) \ +REG_VAL_NAME(func, valname); \ +inline void regset_ ## func(bool value) \ + { reg_write_bool(_RVN_(func), value); } \ +inline bool regget_ ## func(bool def) \ + { return reg_read_bool(_RVN_(func), def); } + +#define REG_INT_FUNC(func, valname) \ +REG_VAL_NAME(func,valname); \ +inline void regset_ ## func(int value) \ +{ \ + reg_int_op(_RVN_(func), true, value); \ +} \ +inline int regget_ ## func(int def=0) \ +{ \ + return reg_int_op(_RVN_(func), false, def); \ +} + +idaman void ida_export reg_load(void); +idaman void ida_export reg_flush(void); + +// if using history functions below, you have to define the following two variables +extern const char regkey_history[]; +extern int max_history_files; // max number of files in the file menu + // and in the welcome box +#define MAX_HISTORY_FILES_DEF 10 // default value + +inline void regget_history(qstrvec_t *list) +{ +#ifdef DEMO + qnotused(list); +#else + reg_read_strlist(list, regkey_history); +#endif +} + +inline void reg_update_history(const char *addfile, const char *removefile = NULL) +{ +#ifdef DEMO + qnotused(addfile); + qnotused(removefile); +#else + // On Windows avoid duplicate upper/lower-case entries + // by using reg_update_filestrlist() which takes care of case sensitivity + reg_update_filestrlist(regkey_history, addfile, max_history_files, removefile); +#endif +} + +inline void reg_history_size_truncate(void) +{ +#ifndef DEMO + reg_update_strlist(regkey_history, NULL, max_history_files, NULL); +#endif +} +/// \endcond + +#endif // __REGISTRY_HPP diff --git a/idasdk76/include/search.hpp b/idasdk76/include/search.hpp new file mode 100644 index 0000000..54a231a --- /dev/null +++ b/idasdk76/include/search.hpp @@ -0,0 +1,167 @@ +/* + * Interactive disassembler (IDA). + * ALL RIGHTS RESERVED. + * Copyright (c) 1990-2021 Hex-Rays + * + */ + +#ifndef __SEARCH_HPP +#define __SEARCH_HPP + +/*! \file search.hpp + + \brief Middle-level search functions + + They all are controlled by \ref SEARCH_ +*/ + +/// \defgroup SEARCH_ Search flags +//@{ +#define SEARCH_UP 0x000 ///< search towards lower addresses +#define SEARCH_DOWN 0x001 ///< search towards higher addresses +#define SEARCH_NEXT 0x002 ///< skip the starting address when searching. + ///< this bit is useful only for search(), bin_search2(), find_reg_access(). + ///< find_.. functions skip the starting address automatically. +#define SEARCH_CASE 0x004 ///< case-sensitive search (case-insensitive otherwise) +#define SEARCH_REGEX 0x008 ///< regular expressions in search string (supported only for the text search) +#define SEARCH_NOBRK 0x010 ///< do not test if the user clicked cancel to interrupt the search +#define SEARCH_NOSHOW 0x020 ///< do not display the search progress/refresh screen +#define SEARCH_IDENT 0x080 ///< search for an identifier (text search). + ///< it means that the characters before + ///< and after the match cannot be is_visible_char(). +#define SEARCH_BRK 0x100 ///< return #BADADDR if the search was cancelled. +#define SEARCH_USE 0x200 ///< find_reg_access: search for a use (read access) +#define SEARCH_DEF 0x400 ///< find_reg_access: search for a definition (write access) +//@} + + +/// Is the #SEARCH_DOWN bit set? + +inline THREAD_SAFE bool search_down(int sflag) { return (sflag & SEARCH_DOWN) != 0; } + + +/// \name find_... functions +/// \param ea start ea +/// \param sflag combination of \ref SEARCH_ +/// \param[out] opnum filled with operand number whenever relevant +/// \return first ea at which the search criteria is met +//@{ + + +/// Find next error or problem + +idaman ea_t ida_export find_error(ea_t ea, int sflag, int *opnum=NULL); + + +/// Find next operand without any type info + +idaman ea_t ida_export find_notype(ea_t ea, int sflag, int *opnum=NULL); + + +/// Find next unexplored address + +idaman ea_t ida_export find_unknown(ea_t ea, int sflag); + + +/// Find next ea that is the start of an instruction or data + +idaman ea_t ida_export find_defined(ea_t ea, int sflag); + + +/// Find next suspicious operand + +idaman ea_t ida_export find_suspop(ea_t ea, int sflag, int *opnum=NULL); + + +/// Find next data address + +idaman ea_t ida_export find_data(ea_t ea,int sflag); + + +/// Find next code address + +idaman ea_t ida_export find_code(ea_t ea,int sflag); + + +/// Find next code address that does not belong to a function + +idaman ea_t ida_export find_not_func(ea_t ea,int sflag); + + +/// Find next immediate operand with the given value + +idaman ea_t ida_export find_imm(ea_t ea, int sflag, uval_t search_value, int *opnum=NULL); + + +/// See search() + +idaman ea_t ida_export find_text(ea_t start_ea, int y, int x, const char *ustr, int sflag); + + +/// Find access to a register. +/// \param out pointer to the output buffer. must be non-null. +/// upon success contains info about the found register. +/// upon failed search for a read access out->range contains +/// the info about the non-redefined parts of the register. +/// \param start_ea starting address +/// \param end_ea ending address. BADADDR means that the end limit is missing. +/// otherwise, if the search direction is SEARCH_UP, +/// END_EA must be lower than START_EA. +/// \param regname the register to search for. +/// \param sflag combination of \ref SEARCH_ bits. +/// \note This function does not care about the control flow and +/// probes all instructions in the specified range, starting from START_EA. +/// Only direct references to registers are detected. Function calls and +/// system traps are ignored. +/// \return the found address. BADADDR if not found or error. +idaman ea_t ida_export find_reg_access( + struct reg_access_t *out, + ea_t start_ea, + ea_t end_ea, + const char *regname, + int sflag); + +//@} + +class place_t; + + +/// Search for a text substring (low level function). +/// \param ud line array parameter +/// \param[in,out] start pointer to starting place: +/// - start->ea: starting address +/// - start->lnnum: starting Y coordinate +/// \param end pointer to ending place: +/// - end->ea: ending address +/// - end->lnnum: ending Y coordinate +/// \param[in,out] startx pointer to starting X coordinate +/// \param str substring to search for. +/// \param sflag \ref SEARCH_ +/// \retval 0 substring not found +/// \retval 1 substring found. The matching position is returned in: +/// - start->ea: address +/// - start->lnnum: Y coordinate +/// - *startx: X coordinate +/// \retval 2 search was cancelled by ctrl-break. +/// The farthest searched address is +/// returned in the same manner as in the successful return (1). +/// \retval 3 the input regular expression is bad. +/// The error message was displayed. + +idaman int ida_export search( + void *ud, + place_t *start, + const place_t *end, + int *startx, + const char *str, + int sflag); + + +#if !defined(NO_OBSOLETE_FUNCS) +idaman DEPRECATED int ida_export user2bin(uchar *, uchar *, ea_t, const char *, int, bool); // use parse_binpat_str() +idaman DEPRECATED ea_t ida_export find_binary(ea_t, ea_t, const char *, int, int); // use bin_search2() + +#endif + + +#endif // __SEARCH_HPP diff --git a/idasdk76/include/segment.hpp b/idasdk76/include/segment.hpp new file mode 100644 index 0000000..e15e64b --- /dev/null +++ b/idasdk76/include/segment.hpp @@ -0,0 +1,1212 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _SEGMENT_HPP +#define _SEGMENT_HPP + +#include <ida.hpp> +#include <range.hpp> // segments are range of addresses + // with characteristics + +/*! \file segment.hpp + + \brief Functions that deal with segments. + + IDA requires that all program addresses belong to segments + (each address must belong to exactly one segment). + The situation when an address doesn't belong to any segment + is allowed as a temporary situation only when the user changes program + segmentation. Bytes outside a segment can't be converted to + instructions, have names, comments, etc. + Each segment has its start address, ending address and represents + a contiguous range of addresses. There might be unused holes between + segments. + + Each segment has its unique segment selector. This selector is used + to distinguish the segment from other segments. For 16-bit programs + the selector is equal to the segment base paragraph. For 32-bit + programs there is special array to translate the selectors to + the segment base paragraphs. A selector is a 32/64 bit value. + + The segment base paragraph determines the offsets in the segment. + If the start address of the segment == (base << 4) then the first + offset in the segment will be 0. The start address should be + higher or equal to (base << 4). + We will call the offsets in the segment 'virtual addresses'. + So, the virtual address of the first byte of the segment is + + (start address of segment - segment base linear address) + + For IBM PC, the virtual address corresponds to the offset part of the address. + For other processors (Z80, for example), virtual addresses correspond + to Z80 addresses and linear addresses are used only internally. + For MS Windows programs the segment base paragraph is 0 and therefore + the segment virtual addresses are equal to linear addresses. +*/ + +/// \defgroup seg Segments +/// \copybrief segment.hpp + + +/// Maximum number of segment registers is 16 (see segregs.hpp) +#define SREG_NUM 16 + + +//------------------------------------------------------------------------- +// D E F I N I T O N O F S E G M E N T S T R U C T U R E +//------------------------------------------------------------------------- +/// \defgroup seg_t Segment structure +/// Definition of ::segment_t and related functions +/// \ingroup seg +//@{ + +/// Describes a program segment +class segment_t : public range_t +{ +public: +/* 8 */ uval_t name; ///< use get/set_segm_name() functions +/* 12 */ uval_t sclass; ///< use get/set_segm_class() functions +/* 16 */ uval_t orgbase; ///< this field is IDP dependent. + ///< you may keep your information about + ///< the segment here + +/* 20 */ uchar align; ///< \ref sa_ +/// \defgroup sa_ Segment alignment codes +/// \ingroup seg_t +/// Used by segment_t::align +//@{ +#define saAbs 0 ///< Absolute segment. +#define saRelByte 1 ///< Relocatable, byte aligned. +#define saRelWord 2 ///< Relocatable, word (2-byte) aligned. +#define saRelPara 3 ///< Relocatable, paragraph (16-byte) aligned. +#define saRelPage 4 ///< Relocatable, aligned on 256-byte boundary +#define saRelDble 5 ///< Relocatable, aligned on a double word (4-byte) + ///< boundary. +#define saRel4K 6 ///< This value is used by the PharLap OMF for page (4K) + ///< alignment. It is not supported by LINK. +#define saGroup 7 ///< Segment group +#define saRel32Bytes 8 ///< 32 bytes +#define saRel64Bytes 9 ///< 64 bytes +#define saRelQword 10 ///< 8 bytes +#define saRel128Bytes 11 ///< 128 bytes +#define saRel512Bytes 12 ///< 512 bytes +#define saRel1024Bytes 13 ///< 1024 bytes +#define saRel2048Bytes 14 ///< 2048 bytes +#define saRel_MAX_ALIGN_CODE saRel2048Bytes +//@} + +/* 21 */ uchar comb; ///< \ref sc_ +/// \defgroup sc_ Segment combination codes +/// \ingroup seg_t +/// Used by segment_t::comb +//@{ +#define scPriv 0 ///< Private. Do not combine with any other program + ///< segment. +#define scGroup 1 ///< Segment group +#define scPub 2 ///< Public. Combine by appending at an offset that meets + ///< the alignment requirement. +#define scPub2 4 ///< As defined by Microsoft, same as C=2 (public). +#define scStack 5 ///< Stack. Combine as for C=2. This combine type forces + ///< byte alignment. +#define scCommon 6 ///< Common. Combine by overlay using maximum size. +#define scPub3 7 ///< As defined by Microsoft, same as C=2 (public). +#define sc_MAX_COMB_CODE scPub3 +//@} + +/* 22 */ uchar perm; ///< \ref SEGPERM_ (0 means no information) +/// \defgroup SEGPERM_ Segment permissions +/// \ingroup seg_t +/// Used by segment_t::perm +//@{ +#define SEGPERM_EXEC 1 ///< Execute +#define SEGPERM_WRITE 2 ///< Write +#define SEGPERM_READ 4 ///< Read +#define SEGPERM_MAXVAL (SEGPERM_EXEC + SEGPERM_WRITE + SEGPERM_READ) +//@} + +/* 23 */ uchar bitness; ///< Number of bits in the segment addressing + ///< - 0: 16 bits + ///< - 1: 32 bits + ///< - 2: 64 bits +#define SEG_MAX_BITNESS_CODE 2 + + /// Is a 16-bit segment? + bool is_16bit(void) const { return bitness == 0; } + /// Is a 32-bit segment? + bool is_32bit(void) const { return bitness == 1; } + /// Is a 64-bit segment? + bool is_64bit(void) const { return bitness == 2; } + /// Get number of address bits + int abits(void) const { return 1<<(bitness+4); } + /// Get number of address bytes + int abytes(void) const { return abits() / 8; } + +/// \defgroup SFL_ Segment flags +/// \ingroup seg_t +/// Used by segment_t::flags + +/* 24 */ ushort flags; ///< \ref SFL_ + +/// IDP dependent field (IBM PC: if set, ORG directive is not commented out) +/// \ingroup SFL_ +#define SFL_COMORG 0x01 + + /// \name Segment flag: ORG directive + /// See #SFL_COMORG + //@{ + bool comorg(void) const { return (flags & SFL_COMORG) != 0; } + void set_comorg(void) { flags |= SFL_COMORG; } + void clr_comorg(void) { flags &= ~SFL_COMORG; } + //@} + +/// Orgbase is present? (IDP dependent field) +/// \ingroup SFL_ +#define SFL_OBOK 0x02 + + /// \name Segment flag: orgbase + /// See #SFL_OBOK + //@{ + bool ob_ok(void) const { return (flags & SFL_OBOK) != 0; } + void set_ob_ok(void) { flags |= SFL_OBOK; } + void clr_ob_ok(void) { flags &= ~SFL_OBOK; } + //@} + +/// Is the segment hidden? +/// \ingroup SFL_ +#define SFL_HIDDEN 0x04 + + /// \name Segment flag: hidden + /// See #SFL_HIDDEN + //@{ + bool is_visible_segm(void) const { return (flags & SFL_HIDDEN) == 0; } + void set_visible_segm(bool visible) { setflag(flags, SFL_HIDDEN, !visible); } + //@} + +/// Is the segment created for the debugger?. +/// Such segments are temporary and do not have permanent flags. +/// \ingroup SFL_ +#define SFL_DEBUG 0x08 + + /// \name Segment flag: debugger segment + /// See #SFL_DEBUG + //@{ + bool is_debugger_segm(void) const { return (flags & SFL_DEBUG) != 0; } + void set_debugger_segm(bool debseg) { setflag(flags, SFL_DEBUG, debseg); } + //@} + +/// Is the segment created by the loader? +/// \ingroup SFL_ +#define SFL_LOADER 0x10 + + /// \name Segment flag: loader segment + /// See #SFL_LOADER + //@{ + bool is_loader_segm(void) const { return (flags & SFL_LOADER) != 0; } + void set_loader_segm(bool ldrseg) { setflag(flags, SFL_LOADER, ldrseg); } + //@} + +/// Hide segment type (do not print it in the listing) +/// \ingroup SFL_ +#define SFL_HIDETYPE 0x20 + + /// \name Segment flag: hide segment type + /// See #SFL_HIDETYPE + //@{ + bool is_hidden_segtype(void) const { return (flags & SFL_HIDETYPE) != 0; } + void set_hidden_segtype(bool hide) { setflag(flags, SFL_HIDETYPE, hide); } + //@} + +/// Header segment (do not create offsets to it in the disassembly) +/// \ingroup SFL_ +#define SFL_HEADER 0x40 + + /// \name Segment flag: header segment + /// See #SFL_HEADER + //@{ + bool is_header_segm(void) const { return (flags & SFL_HEADER) != 0; } + void set_header_segm(bool on) { setflag(flags, SFL_HEADER, on); } + //@} + + /// Ephemeral segments are not analyzed automatically + /// (no flirt, no functions unless required, etc). + /// Most likely these segments will be destroyed at the end of the + /// debugging session unless the user changes their status. + bool is_ephemeral_segm(void) const + { return (flags & (SFL_DEBUG|SFL_LOADER)) == SFL_DEBUG; } + +/* 28 */ sel_t sel; ///< segment selector - should be unique. You can't + ///< change this field after creating the segment. + ///< Exception: 16bit OMF files may have several + ///< segments with the same selector, but this is not + ///< good (no way to denote a segment exactly) + ///< so it should be fixed in the future. + +/* 32 */ sel_t defsr[SREG_NUM];///< default segment register values. + ///< first element of this array keeps information + ///< about value of \ph{reg_first_sreg} + +/* 96 */ uchar type; ///< segment type (see \ref SEG_). + ///< The kernel treats different segment types differently. + ///< Segments marked with '*' contain no instructions + ///< or data and are not declared as 'segments' in + ///< the disassembly. + +/// \defgroup SEG_ Segment types +/// \ingroup seg_t +/// Used by segment_t::type +//@{ +#define SEG_NORM 0 ///< unknown type, no assumptions +#define SEG_XTRN 1 ///< * segment with 'extern' definitions. + ///< no instructions are allowed +#define SEG_CODE 2 ///< code segment +#define SEG_DATA 3 ///< data segment +#define SEG_IMP 4 ///< java: implementation segment +#define SEG_GRP 6 ///< * group of segments +#define SEG_NULL 7 ///< zero-length segment +#define SEG_UNDF 8 ///< undefined segment type (not used) +#define SEG_BSS 9 ///< uninitialized segment +#define SEG_ABSSYM 10 ///< * segment with definitions of absolute symbols +#define SEG_COMM 11 ///< * segment with communal definitions +#define SEG_IMEM 12 ///< internal processor memory & sfr (8051) +#define SEG_MAX_SEGTYPE_CODE SEG_IMEM +//@} + +/* 100 */ bgcolor_t color; ///< the segment color + + /// Update segment information. You must call this function after modification + /// of segment characteristics. Note that not all fields of segment structure + /// may be modified directly, there are special functions to modify some fields. + /// \return success + inline bool update(void); + + /// Constructor + segment_t(void) + : name(0), + sclass(0), + orgbase(0), + align(0), + comb(0), + perm(0), + bitness(0), + flags(0), + sel(0), + type(SEG_NORM), + color(DEFCOLOR) + { + memset(defsr, 0, sizeof(defsr)); + } + +#ifndef SWIG + DECLARE_COMPARISONS(segment_t); +#endif +}; // total 104/192 bytes + +#ifdef __EA64__ +CASSERT(sizeof(segment_t) == 192); +#else +CASSERT(sizeof(segment_t) == 104); +#endif + +/// See #SFL_HIDDEN +inline bool is_visible_segm(segment_t *s) { return s->is_visible_segm(); } +/// See #SFL_HIDDEN, #SCF_SHHID_SEGM +inline bool is_finally_visible_segm(segment_t *s) +{ + return (inf_get_cmtflg() & SCF_SHHID_SEGM) != 0 || is_visible_segm(s); +} +/// See #SFL_HIDDEN +idaman void ida_export set_visible_segm(segment_t *s, bool visible); + + +/// Has segment a special type?. +/// (#SEG_XTRN, #SEG_GRP, #SEG_ABSSYM, #SEG_COMM) + +idaman bool ida_export is_spec_segm(uchar seg_type); + + +/// Does the address belong to a segment with a special type?. +/// (#SEG_XTRN, #SEG_GRP, #SEG_ABSSYM, #SEG_COMM) +/// \param ea linear address + +idaman bool ida_export is_spec_ea(ea_t ea); + + +/// Lock segment pointer +/// Locked pointers are guaranteed to remain valid until they are unlocked. +/// Ranges with locked pointers cannot be deleted or moved. + +idaman void ida_export lock_segm(const segment_t *segm, bool lock); + +/// Helper class to lock a segment pointer so it stays valid +class lock_segment +{ + const segment_t *segm; +public: + lock_segment(const segment_t *_segm) : segm(_segm) + { + lock_segm(segm, true); + } + ~lock_segment(void) + { + lock_segm(segm, false); + } +}; + +/// Is a segment pointer locked? +idaman bool ida_export is_segm_locked(const segment_t *segm); + +//@} seg_t + +//------------------------------------------------------------------------- +// S E G M E N T S E L E C T O R S +// +/// \defgroup seg_sel Segment selectors +/// \ingroup seg +/// The kernel maintains a table to translate selector values to +/// segment base paragraphs. A Paragraph is a 16byte quantity. +/// This table and translation is necessary because IBM PC uses +/// 16bit selectors in instructions but segments may reside anywhere +/// in the linear addressing space. For example, if a segment with +/// selector 5 resides at 0x400000, we need to have selector translation +/// 5 -> 0x400000. +/// For 16bit programs the selector translation table is usually empty, +/// selector values are equal to segment base paragraphs. +//@{ +//------------------------------------------------------------------------- + +/// Get description of selector (0..get_selector_qty()-1) + +idaman bool ida_export getn_selector(sel_t *sel, ea_t *base, int n); + + +/// Get number of defined selectors + +idaman size_t ida_export get_selector_qty(void); + + +/// Allocate a selector for a segment if necessary. +/// You must call this function before calling add_segm_ex(). +/// add_segm() calls this function itself, so you don't need to +/// allocate a selector. +/// This function will allocate a selector if 'segbase' requires more than +/// 16 bits and the current processor is IBM PC. +/// Otherwise it will return the segbase value. +/// \param segbase a new segment base paragraph +/// \return the allocated selector number + +idaman sel_t ida_export setup_selector(ea_t segbase); + + +/// Allocate a selector for a segment unconditionally. +/// You must call this function before calling add_segm_ex(). +/// add_segm() calls this function itself, so you don't need to +/// allocate a selector. +/// This function will allocate a new free selector and setup its mapping +/// using find_free_selector() and set_selector() functions. +/// \param segbase a new segment base paragraph +/// \return the allocated selector number + +idaman sel_t ida_export allocate_selector(ea_t segbase); + + +/// Find first unused selector. +/// \return a number >= 1 + +idaman sel_t ida_export find_free_selector(void); + + +/// Set mapping of selector to a paragraph. +/// You should call this function _before_ creating a segment +/// which uses the selector, otherwise the creation of the segment will fail. +/// \param selector number of selector to map +/// - if selector == #BADSEL, then return 0 (fail) +/// - if the selector has had a mapping, old mapping is destroyed +/// - if the selector number is equal to paragraph value, then the mapping is +/// destroyed because we don't need to keep trivial mappings. +/// \param paragraph paragraph to map selector +/// \retval 1 ok +/// \retval 0 failure (bad selector or too many mappings) + +idaman int ida_export set_selector(sel_t selector, ea_t paragraph); + + +/// Delete mapping of a selector. +/// Be wary of deleting selectors that are being used in the program, this +/// can make a mess in the segments. +/// \param selector number of selector to remove from the translation table + +idaman void ida_export del_selector(sel_t selector); + + +/// Get mapping of a selector. +/// \param selector number of selector to translate +/// \return paragraph the specified selector is mapped to. +/// if there is no mapping, returns 'selector'. + +idaman ea_t ida_export sel2para(sel_t selector); + + +/// Get mapping of a selector as a linear address. +/// \param selector number of selector to translate to linear address +/// \return linear address the specified selector is mapped to. +/// if there is no mapping, returns to_ea(selector,0); + +inline ea_t idaapi sel2ea(sel_t selector) +{ + if ( selector == BADSEL ) + return BADADDR; + return to_ea(sel2para(selector), 0); +} + + +/// Find a selector that has mapping to the specified paragraph. +/// \param base paragraph to search in the translation table +/// \return selector value or base + +idaman sel_t ida_export find_selector(ea_t base); + + +/// Enumerate all selectors from the translation table. +/// This function calls 'func' for each selector in the translation table. +/// If 'func' returns non-zero code, enumeration is stopped and this code +/// is returned. +/// \param func callback function +/// - sel: selector number +/// - para: selector mapping +/// \return 0 or code returned by 'func'. + +idaman int ida_export enumerate_selectors(int (idaapi *func)(sel_t sel,ea_t para)); + + +/// Enumerate all segments with the specified selector. +/// This function will call the callback function 'func' for each +/// segment that has the specified selector. Enumeration starts +/// from the last segment and stops at the first segment (reverse order). +/// If the callback function 'func' returns a value != #BADADDR, the +/// enumeration is stopped and this value is returned to the caller. +/// \param selector segments that have this selector are enumerated +/// \param func callback function +/// - s: pointer to segment structure +/// - ud: user data +/// \param ud pointer to user data. this pointer will be passed +/// to the callback function +/// \return #BADADDR or the value returned by the callback function 'func' + +idaman ea_t ida_export enumerate_segments_with_selector( + sel_t selector, + ea_t (idaapi *func)(segment_t *s, void *ud), + void *ud=NULL); + + +/// Get pointer to segment structure. +/// This function finds a segment by its selector. If there are several +/// segments with the same selectors, the last one will be returned. +/// \param selector a segment with the specified selector will be returned +/// \return pointer to segment or NULL + +idaman segment_t *ida_export get_segm_by_sel(sel_t selector); + +//@} seg_sel + +//------------------------------------------------------------------------- +// S E G M E N T M A N I P U L A T I O N F U N C T I O N S +//------------------------------------------------------------------------- +/// \defgroup seg_man Segment manipulation functions +/// Add/Delete/Modify segments +/// \ingroup seg +//@{ + +/// Add a new segment. +/// If a segment already exists at the specified range of addresses, +/// this segment will be truncated. Instructions and data in the old +/// segment will be deleted if the new segment has another addressing +/// mode or another segment base address. +/// \param s pointer to filled segment structure. +/// segment selector should have proper mapping (see set_selector()). +/// - if s.start_ea==#BADADDR then s.start_ea <- get_segm_base(&s) +/// - if s.end_ea==#BADADDR, then a segment up to the next segment +/// will be created (if the next segment doesn't exist, then +/// 1 byte segment will be created). +/// - if the s.end_ea < s.start_ea, then fail. +/// - if s.end_ea is too high and the new segment would overlap +/// the next segment, s.end_ea is adjusted properly. +/// \param name name of new segment. may be NULL. +/// if specified, the segment is immediately renamed +/// \param sclass class of the segment. may be NULL. +/// if specified, the segment class is immediately changed +/// \param flags \ref ADDSEG_ +/// \retval 1 ok +/// \retval 0 failed, a warning message is displayed + +idaman bool ida_export add_segm_ex( + segment_t *NONNULL s, + const char *name, + const char *sclass, + int flags); +/// \defgroup ADDSEG_ Add segment flags +/// Passed as 'flags' parameter to add_segm_ex() +//@{ +#define ADDSEG_NOSREG 0x0001 ///< set all default segment register values to #BADSEL + ///< (undefine all default segment registers) +#define ADDSEG_OR_DIE 0x0002 ///< qexit() if can't add a segment +#define ADDSEG_NOTRUNC 0x0004 ///< don't truncate the new segment at the beginning of the next segment if they overlap. + ///< destroy/truncate old segments instead. +#define ADDSEG_QUIET 0x0008 ///< silent mode, no "Adding segment..." in the messages window +#define ADDSEG_FILLGAP 0x0010 ///< fill gap between new segment and previous one. + ///< i.e. if such a gap exists, and this gap is less + ///< than 64K, then fill the gap by extending the + ///< previous segment and adding .align directive + ///< to it. This way we avoid gaps between segments. + ///< too many gaps lead to a virtual array failure. + ///< it cannot hold more than ~1000 gaps. +#define ADDSEG_SPARSE 0x0020 ///< use sparse storage method for the new ranges + ///< of the created segment. please note that the + ///< ranges that were already enabled before + ///< creating the segment will not change their + ///< storage type. +#define ADDSEG_NOAA 0x0040 ///< do not mark new segment for auto-analysis +#define ADDSEG_IDBENC 0x0080 ///< 'name' and 'sclass' are given in the IDB encoding; + ///< non-ASCII bytes will be decoded accordingly +//@} + + +/// Add a new segment, second form. +/// Segment alignment is set to #saRelByte. +/// Segment combination is "public" or "stack" (if segment class is "STACK"). +/// Addressing mode of segment is taken as default (16bit or 32bit). +/// Default segment registers are set to #BADSEL. +/// If a segment already exists at the specified range of addresses, +/// this segment will be truncated. Instructions and data in the old +/// segment will be deleted if the new segment has another addressing +/// mode or another segment base address. +/// \param para segment base paragraph. +/// if paragraph can't fit in 16bit, then a new selector is +/// allocated and mapped to the paragraph. +/// \param start start address of the segment. +/// if start==#BADADDR then start <- to_ea(para,0). +/// \param end end address of the segment. end address should be higher than +/// start address. For emulate empty segments, use #SEG_NULL segment +/// type. If the end address is lower than start address, then fail. +/// If end==#BADADDR, then a segment up to the next segment +/// will be created (if the next segment doesn't exist, then +/// 1 byte segment will be created). +/// If 'end' is too high and the new segment would overlap +/// the next segment, 'end' is adjusted properly. +/// \param name name of new segment. may be NULL +/// \param sclass class of the segment. may be NULL. +/// type of the new segment is modified if class is one of +/// predefined names: +/// - "CODE" -> #SEG_CODE +/// - "DATA" -> #SEG_DATA +/// - "CONST" -> #SEG_DATA +/// - "STACK" -> #SEG_BSS +/// - "BSS" -> #SEG_BSS +/// - "XTRN" -> #SEG_XTRN +/// - "COMM" -> #SEG_COMM +/// - "ABS" -> #SEG_ABSSYM +/// \retval 1 ok +/// \retval 0 failed, a warning message is displayed + +idaman bool ida_export add_segm( + ea_t para, + ea_t start, + ea_t end, + const char *name, + const char *sclass, + int flags=0); + + +/// Delete a segment. +/// \param ea any address belonging to the segment +/// \param flags \ref SEGMOD_ +/// \retval 1 ok +/// \retval 0 failed, no segment at 'ea'. + +idaman bool ida_export del_segm(ea_t ea, int flags); + +/// \defgroup SEGMOD_ Segment modification flags +/// Used by functions in \ref seg_man +//@{ +#define SEGMOD_KILL 0x0001 ///< disable addresses if segment gets shrinked or deleted +#define SEGMOD_KEEP 0x0002 ///< keep information (code & data, etc) +#define SEGMOD_SILENT 0x0004 ///< be silent +#define SEGMOD_KEEP0 0x0008 ///< flag for internal use, don't set +#define SEGMOD_KEEPSEL 0x0010 ///< do not try to delete unused selector +#define SEGMOD_NOMOVE 0x0020 ///< don't move info from the start of segment to the new start address + ///< (for set_segm_start()) +#define SEGMOD_SPARSE 0x0040 ///< use sparse storage if extending the segment + ///< (for set_segm_start(), set_segm_end()) +//@} + + +/// Get number of segments + +idaman int ida_export get_segm_qty(void); + + +/// Get pointer to segment by linear address. +/// \param ea linear address belonging to the segment +/// \return NULL or pointer to segment structure + +idaman segment_t *ida_export getseg(ea_t ea); + + +/// Get pointer to segment by its number. +/// \warning Obsoleted because it can slow down the debugger (it has to refresh the whole +/// memory segmentation to calculate the correct answer) +/// \param n segment number in the range (0..get_segm_qty()-1) +/// \returns NULL or pointer to segment structure + +idaman segment_t *ida_export getnseg(int n); + + +/// Get number of segment by address. +/// \param ea linear address belonging to the segment +/// \return -1 if no segment occupies the specified address. +/// otherwise returns number of the specified segment (0..get_segm_qty()-1) +idaman int ida_export get_segm_num(ea_t ea); + + +/// Get pointer to the next segment +idaman segment_t *ida_export get_next_seg(ea_t ea); +/// Get pointer to the previous segment +idaman segment_t *ida_export get_prev_seg(ea_t ea); + +/// Get pointer to the first segment +idaman segment_t *ida_export get_first_seg(void); +/// Get pointer to the last segment +idaman segment_t *ida_export get_last_seg(void); + + +/// Get pointer to segment by its name. +/// If there are several segments with the same name, returns the first of them. +/// \param name segment name. may be NULL. +/// \return NULL or pointer to segment structure + +idaman segment_t *ida_export get_segm_by_name(const char *name); + + +/// Set segment end address. +/// The next segment is shrinked to allow expansion of the specified segment. +/// The kernel might even delete the next segment if necessary. +/// The kernel will ask the user for a permission to destroy instructions +/// or data going out of segment scope if such instructions exist. +/// \param ea any address belonging to the segment +/// \param newend new end address of the segment +/// \param flags \ref SEGMOD_ +/// \retval 1 ok +/// \retval 0 failed, a warning message is displayed + +idaman bool ida_export set_segm_end(ea_t ea, ea_t newend, int flags); + + +/// Set segment start address. +/// The previous segment is trimmed to allow expansion of the specified segment. +/// The kernel might even delete the previous segment if necessary. +/// The kernel will ask the user for a permission to destroy instructions +/// or data going out of segment scope if such instructions exist. +/// \param ea any address belonging to the segment +/// \param newstart new start address of the segment +/// note that segment start address should be higher than +/// segment base linear address. +/// \param flags \ref SEGMOD_ +/// \retval 1 ok +/// \retval 0 failed, a warning message is displayed + +idaman bool ida_export set_segm_start(ea_t ea, ea_t newstart, int flags); + + +/// Move segment start. +/// The main difference between this function and set_segm_start() is +/// that this function may expand the previous segment while set_segm_start() +/// never does it. So, this function allows to change bounds of two segments +/// simultaneously. If the previous segment and the specified segment +/// have the same addressing mode and segment base, then instructions +/// and data are not destroyed - they simply move from one segment +/// to another. Otherwise all instructions/data which migrate +/// from one segment to another are destroyed. +/// \note this function never disables addresses. +/// \param ea any address belonging to the segment +/// \param newstart new start address of the segment +/// note that segment start address should be higher than +/// segment base linear address. +/// \param mode policy for destroying defined items +/// - 0: if it is necessary to destroy defined items, +/// display a dialog box and ask confirmation +/// - 1: if it is necessary to destroy defined items, +/// just destroy them without asking the user +/// - -1: if it is necessary to destroy defined items, +/// don't destroy them (i.e. function will fail) +/// - -2: don't destroy defined items (function will succeed) +/// \retval 1 ok +/// \retval 0 failed, a warning message is displayed + +idaman bool ida_export move_segm_start(ea_t ea, ea_t newstart, int mode); + + +/// Move a segment to a new address. +/// This function moves all information to the new address. +/// It fixes up address sensitive information in the kernel. +/// The total effect is equal to reloading the segment to the target address. +/// For the file format dependent address sensitive information, loader_t::move_segm is called. +/// Also IDB notification event idb_event::segm_moved is called. +/// \param s segment to move +/// \param to new segment start address +/// \param flags \ref MSF_ +/// \return \ref MOVE_SEGM_ + +idaman int ida_export move_segm(segment_t *s, ea_t to, int flags=0); + +/// \defgroup MSF_ Move segment flags +/// Passed as 'flags' parameter to move_segm() and rebase_program() +//@{ +#define MSF_SILENT 0x0001 ///< don't display a "please wait" box on the screen +#define MSF_NOFIX 0x0002 ///< don't call the loader to fix relocations +#define MSF_LDKEEP 0x0004 ///< keep the loader in the memory (optimization) +#define MSF_FIXONCE 0x0008 ///< call loader only once with the special calling method. + ///< valid for rebase_program(). see loader_t::move_segm. +#define MSF_PRIORITY 0x0020 ///< loader segments will overwrite any existing debugger segments when moved. + ///< valid for move_segm() +#define MSF_NETNODES 0x0080 ///< move netnodes instead of changing inf.netdelta (this is slower) + ///< valid for rebase_program() +//@} + +/// \defgroup MOVE_SEGM_ Move segment result codes +/// Return values for move_segm() add rebase_program() +//@{ +#define MOVE_SEGM_OK 0 ///< all ok +#define MOVE_SEGM_PARAM -1 ///< The specified segment does not exist +#define MOVE_SEGM_ROOM -2 ///< Not enough free room at the target address +#define MOVE_SEGM_IDP -3 ///< IDP module forbids moving the segment +#define MOVE_SEGM_CHUNK -4 ///< Too many chunks are defined, can't move +#define MOVE_SEGM_LOADER -5 ///< The segment has been moved but the loader complained +#define MOVE_SEGM_ODD -6 ///< Cannot move segments by an odd number of bytes +#define MOVE_SEGM_ORPHAN -7 ///< Orphan bytes hinder segment movement +#define MOVE_SEGM_DEBUG -8 ///< Debugger segments cannot be moved +//@} + + +/// Rebase the whole program by 'delta' bytes. +/// \param delta number of bytes to move the program +/// \param flags \ref MSF_ +/// it is recommended to use #MSF_FIXONCE so that the loader takes +/// care of global variables it stored in the database +/// \return \ref MOVE_SEGM_ + +idaman int ida_export rebase_program(adiff_t delta, int flags); + + +/// Convert a debugger segment to a regular segment and vice versa. +/// When converting debug->regular, the memory contents will be copied +/// to the database. +/// \param s segment to modify +/// \param is_deb_segm new status of the segment +/// \return \ref CSS_ + +idaman int ida_export change_segment_status(segment_t *s, bool is_deb_segm); + +/// \defgroup CSS_ Change segment status result codes +/// Return values for change_segment_status() +//@{ +#define CSS_OK 0 ///< ok +#define CSS_NODBG -1 ///< debugger is not running +#define CSS_NORANGE -2 ///< could not find corresponding memory range +#define CSS_NOMEM -3 ///< not enough memory (might be because the segment + ///< is too big) +#define CSS_BREAK -4 ///< memory reading process stopped by user +//@} + + +/// Take a memory snapshot of the running process. +/// \param only_loader_segs only is_loader_segm() segments will be affected +/// \return success + +idaman bool ida_export take_memory_snapshot(bool only_loader_segs); + + +/// Is the database a miniidb created by the debugger?. +/// \return true if the database contains no segments +/// or only debugger segments + +idaman bool ida_export is_miniidb(void); + + +/// Internal function + +idaman bool ida_export set_segm_base(segment_t *s, ea_t newbase); + +//@} seg_man + +//------------------------------------------------------------------------- +// S E G M E N T G R O U P S +//------------------------------------------------------------------------- +/// \defgroup seg_grp Segment groups +/// \ingroup seg +//@{ + + +/// Create a new group of segments (used OMF files). +/// \param grp selector of group segment (segment type is #SEG_GRP) +/// You should create an 'empty' (1 byte) group segment +/// It won't contain anything and will be used to +/// redirect references to the group of segments to the +/// common selector. +/// \param sel common selector of all segments belonging to the segment +/// You should create all segments within the group with the +/// same selector value. +/// \return 1 ok +/// \return 0 too many groups (see #MAX_GROUPS) + +idaman int ida_export set_group_selector(sel_t grp, sel_t sel); + +#define MAX_GROUPS 8 ///< max number of segment groups + + +/// Get common selector for a group of segments. +/// \param grpsel selector of group segment +/// \return common selector of the group or 'grpsel' if no such group is found + +idaman sel_t ida_export get_group_selector(sel_t grpsel); + +//@} seg_grp + +//------------------------------------------------------------------------- +// S E G M E N T T R A N S L A T I O N S +/// +/// \defgroup seg_trans Segment translations +/// \ingroup seg +/// +/// Used to represent overlayed memory banks. +/// Segment translations are used to redirect access to overlayed segments +/// so that the correct overlay is accessed. Each segment has its own +/// translation list. For example, suppose we have +/// four segments: +/// <pre> +/// A 1000-2000 +/// B 1000-2000 +/// C 2000-3000 +/// D 2000-3000 +/// </pre> +/// A and B occupy the same virtual addresses. The same with C and D. +/// Segment A works with segment C, segment B works with segment D. +/// +/// So all references from A to 2000-3000 should go to C. For this +/// we add translation C for segment A. The same with B,D: add +/// translation D for segment B. Also, we need to specify the correct +/// segment to be accessed from C, thus we add translation A for segment C. +/// And we add translation B for segment D. +/// +/// After this, all references to virtual addresses 2000-3000 made from A +/// go to segment C (even if segment A would be large and occupy 1000-3000) +/// So, we need the following translations: +/// <pre> +/// A: C +/// B: D +/// C: A +/// D: B +/// </pre> +/// With translations, the segments may reside at any linear addresses, +/// all references will pass through the translation mechanism and go to the +/// correct segment. +/// +/// Segment translation works only for code segments (see map_code_ea()) +//@{ +//------------------------------------------------------------------------- + +/// Add segment translation. +/// \param segstart start address of the segment to add translation to +/// \param mappedseg start address of the overlayed segment +/// \retval 1 ok +/// \retval 0 too many translations or bad segstart + +idaman bool ida_export add_segment_translation(ea_t segstart, ea_t mappedseg); + +#define MAX_SEGM_TRANSLATIONS 64 ///< max number of segment translations + + +/// Set new translation list. +/// \param segstart start address of the segment to add translation to +/// \param transmap vector of segment start addresses for the translation list. +/// If transmap is empty, the translation list is deleted. +/// \retval 1 ok +/// \retval 0 too many translations or bad segstart + +idaman bool ida_export set_segment_translations(ea_t segstart, const eavec_t &transmap); + + +/// Delete the translation list +/// \param segstart start address of the segment to delete translation list + +idaman void ida_export del_segment_translations(ea_t segstart); + + +/// Get segment translation list. +/// \param transmap vector of segment start addresses for the translation list +/// \param segstart start address of the segment to get information about +/// \return -1 if no translation list or bad segstart. +/// otherwise returns size of translation list. + +idaman ssize_t ida_export get_segment_translations(eavec_t *transmap, ea_t segstart); +//@} seg_trans + +//------------------------------------------------------------------------- +// S E G M E N T C O M M E N T S +// +/// \defgroup seg_cmt Segment comments +/// \ingroup seg +/// +/// Segment comments are rarely used yet. +/// The user may define a segment comment by pressing ':' +/// while standing on the segment name at the segment start. +/// +/// The main advantage of segment comments compared to anterior +/// lines (see lines.hpp) is that they are attached to a segment, +/// not to an address and they will move with the start of segment +/// if the segment boundaries change. +/// +/// You may set segment comments in your LDR module to describe +/// characteristics of a segment in comments. +/// +/// Repeatable segment comments are not used at all, because I don't +/// know where they should be repeated. +//@{ +//------------------------------------------------------------------------- + +/// Get segment comment. +/// \param buf buffer for the comment +/// \param s pointer to segment structure +/// \param repeatable 0: get regular comment. +/// 1: get repeatable comment. +/// \return size of comment or -1 + +idaman ssize_t ida_export get_segment_cmt(qstring *buf, const segment_t *s, bool repeatable); + + +/// Set segment comment. +/// \param s pointer to segment structure +/// \param cmt comment string, may be multiline (with '\n'). +/// maximal size is 4096 bytes. +/// Use empty str ("") to delete comment +/// \param repeatable 0: set regular comment. +/// 1: set repeatable comment. +/// + +idaman void ida_export set_segment_cmt(const segment_t *s, const char *cmt, bool repeatable); + + +/// Generate segment footer line as a comment line. +/// This function may be used in IDP modules to generate segment footer +/// if the target assembler doesn't have 'ends' directive. + +idaman void ida_export std_out_segm_footer(struct outctx_t &ctx, segment_t *seg); + +//@} seg_cmt + +//------------------------------------------------------------------------- +// S E G M E N T N A M E S +//------------------------------------------------------------------------- +/// \defgroup seg_name Segment names +/// \ingroup seg +/// Various ways to retrieve the name of a segment +//@{ + +/// Rename segment. +/// The new name is validated (see validate_name). +/// A segment always has a name. If you hadn't specified a name, +/// the kernel will assign it "seg###" name where ### is segment number. +/// \param s pointer to segment (may be NULL) +/// \param name new segment name +/// \param flags ADDSEG_IDBENC or 0 +/// \retval 1 ok, name is good and segment is renamed +/// \retval 0 failure, name is bad or segment is NULL + +idaman int ida_export set_segm_name( + segment_t *s, + const char *name, + int flags=0); + + +/// Get true segment name by pointer to segment. +/// \param buf output buffer. cannot be NULL +/// \param s pointer to segment +/// \param flags 0-return name as is; 1-substitute bad symbols with _ +/// 1 corresponds to GN_VISIBLE +/// \return size of segment name (-1 if s==NULL) + +idaman ssize_t ida_export get_segm_name(qstring *buf, const segment_t *s, int flags=0); + + +/// Get segment name by pointer to segment. +/// \param buf output buffer. cannot be NULL +/// \param s pointer to segment +/// \return size of segment name (-1 if s==NULL) + +inline ssize_t idaapi get_visible_segm_name(qstring *buf, const segment_t *s) +{ + return get_segm_name(buf, s, 1); +} + + +/// Get colored segment name expression in the form (segname + displacement). +/// \param buf output buffer to hold segment expression +/// \param from linear address of instruction operand or data referring to +/// the name. This address will be used to get fixup information, +/// so it should point to exact position of operand in the +/// instruction. +/// \param sel value to convert to segment expression +/// \return size of segment expression or -1 + +ssize_t get_segm_expr(qstring *buf, ea_t from, sel_t sel); + +//@} seg_name + +//------------------------------------------------------------------------- +// S E G M E N T C L A S S E S A N D T Y P E S +//------------------------------------------------------------------------- +/// \defgroup seg_type Segment classes and types +/// \ingroup seg +/// See \ref SEG_ +//@{ + +/// Get segment class. +/// Segment class is arbitrary text (max 8 characters). +/// \param buf output buffer. cannot be NULL. +/// \param s pointer to segment +/// \return size of segment class (-1 if s==NULL or bufsize<=0) + +idaman ssize_t ida_export get_segm_class(qstring *buf, const segment_t *s); + + +/// Set segment class. +/// \param s pointer to segment (may be NULL) +/// \param sclass segment class (may be NULL). +/// If segment type is #SEG_NORM and segment class is one of predefined +/// names, then segment type is changed to: +/// - "CODE" -> #SEG_CODE +/// - "DATA" -> #SEG_DATA +/// - "STACK" -> #SEG_BSS +/// - "BSS" -> #SEG_BSS +/// - if "UNK" then segment type is reset to #SEG_NORM. +/// \retval 1 ok, name is good and segment is renamed +/// \retval 0 failure, name is NULL or bad or segment is NULL + +idaman int ida_export set_segm_class(segment_t *s, const char *sclass, int flags=0); + + +/// Get segment type. +/// \param ea any linear address within the segment +/// \return \ref SEG_, #SEG_UNDF if no segment found at 'ea' + +idaman uchar ida_export segtype(ea_t ea); + +//@} seg_type + +//------------------------------------------------------------------------- +// S E G M E N T A L I G N M E N T A N D C O M B I N A T I O N +//------------------------------------------------------------------------- +/// \defgroup seg_align Segment alignment and combination +/// \ingroup seg +//@{ + +/// Get text representation of segment alignment code. +/// \return text digestable by IBM PC assembler. + +idaman const char *ida_export get_segment_alignment(uchar align); + + +/// Get text representation of segment combination code. +/// \return text digestable by IBM PC assembler. + +idaman const char *ida_export get_segment_combination(uchar comb); + +//@} seg_align + +//------------------------------------------------------------------------- +// S E G M E N T A D D R E S S I N G +//------------------------------------------------------------------------- +/// \defgroup seg_addr Segment addressing +/// \ingroup seg +//@{ + +/// Get segment base paragraph. +/// Segment base paragraph may be converted to segment base linear address +/// using to_ea() function. +/// In fact, to_ea(get_segm_para(s), 0) == get_segm_base(s). +/// \param s pointer to segment +/// \return 0 if s == NULL, +/// the segment base paragraph + +idaman ea_t ida_export get_segm_para(const segment_t *s); + + +/// Get segment base linear address. +/// Segment base linear address is used to calculate virtual addresses. +/// The virtual address of the first byte of the segment will be +/// (start address of segment - segment base linear address) +/// \param s pointer to segment +/// \return 0 if s == NULL, +/// otherwise segment base linear address + +idaman ea_t ida_export get_segm_base(const segment_t *s); + + +/// Change segment addressing mode (16, 32, 64 bits). +/// You must use this function to change segment addressing, never change +/// the 'bitness' field directly. +/// This function will delete all instructions, comments and names in the segment +/// \param s pointer to segment +/// \param bitness new addressing mode of segment +/// - 2: 64bit segment +/// - 1: 32bit segment +/// - 0: 16bit segment +/// \return success + +idaman bool ida_export set_segm_addressing(segment_t *s, size_t bitness); + +//@} seg_addr + +//----------------------------------------------------------------------- + +/// Does the address belong to a debug segment? + +inline bool is_debugger_segm(ea_t ea) +{ + segment_t *s = getseg(ea); + return s != NULL && s->is_debugger_segm(); +} + +/// Does the address belong to an ephemeral segment? + +inline bool is_ephemeral_segm(ea_t ea) +{ + segment_t *s = getseg(ea); + return s != NULL && s->is_ephemeral_segm(); +} + +//------------------------------------------------------------------------- +inline ea_t correct_address(ea_t ea, ea_t from, ea_t to, ea_t size, bool skip_check=false) +{ + if ( skip_check || (ea >= from && ea < from+size) ) + ea += to - from; + return ea; +} + +//------------------------------------------------------------------------- +idaman bool ida_export update_segm(segment_t *s); + +inline bool segment_t::update(void) +{ + return update_segm(this); +} + +/// Truncate and sign extend a delta depending on the segment +idaman adiff_t ida_export segm_adjust_diff(const segment_t *s, adiff_t delta); + +/// Truncate an address depending on the segment +idaman ea_t ida_export segm_adjust_ea(const segment_t *s, ea_t ea); + +#endif // _SEGMENT_HPP diff --git a/idasdk76/include/segregs.hpp b/idasdk76/include/segregs.hpp new file mode 100644 index 0000000..c9a55f1 --- /dev/null +++ b/idasdk76/include/segregs.hpp @@ -0,0 +1,179 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _SRAREA_HPP +#define _SRAREA_HPP + +#include <range.hpp> + +/*! \file segregs.hpp + + \brief Functions that deal with the segment registers. + + If your processor doesn't use segment registers, then these functions + are of no use for you. However, you should define + two virtual segment registers - CS and DS (for code segment and + data segment) and specify their internal numbers in the LPH structure + (processor_t::reg_code_sreg and processor_t::reg_data_sreg). +*/ + +//------------------------------------------------------------------------- +/// The values of the segment registers are kept as address ranges. The segment +/// register does not change its value within one address range. +/// The processor module finds segment register change points and splits +/// ::sreg_range_t ranges so that a new sreg_range_t range is started at +/// each segment register change point. The kernel deletes sreg_range_t +/// if an instruction is converted back to unexplored bytes. +/// +/// So, we have information about a segment register by keeping information +/// about the range of addresses where segment register does not change the value. +/// +/// Note that each segment has information about the default values of +/// the segment registers. This information is used if the value of a segment +/// register could not be determined. +struct sreg_range_t : public range_t +{ + sel_t val; ///< segment register value + uchar tag; ///< \ref SR_ + +/// \defgroup SR_ Segment register range tags +/// Used by sreg_range_t::tag +//@{ +#define SR_inherit 1 ///< the value is inherited from the previous range +#define SR_user 2 ///< the value is specified by the user +#define SR_auto 3 ///< the value is determined by IDA +#define SR_autostart 4 ///< used as #SR_auto for segment starting address +//@} +}; +DECLARE_TYPE_AS_MOVABLE(sreg_range_t); + + +/// Get value of a segment register. +/// This function uses segment register range and default segment register +/// values stored in the segment structure. +/// \param ea linear address in the program +/// \param rg number of the segment register +/// \return value of the segment register, #BADSEL if value is unknown. + +idaman sel_t ida_export get_sreg(ea_t ea, int rg); + + +/// Create a new segment register range. +/// This function is used when the IDP emulator detects that a segment +/// register changes its value. +/// \param ea linear address where the segment register will +/// have a new value. if ea==#BADADDR, nothing to do. +/// \param rg the number of the segment register +/// \param v the new value of the segment register. If the value is +/// unknown, you should specify #BADSEL. +/// \param tag the register info tag. see \ref SR_ +/// \param silent if false, display a warning() in the case of failure +/// \return success + +idaman bool ida_export split_sreg_range( + ea_t ea, + int rg, + sel_t v, + uchar tag, + bool silent=false); + + +/// Set default value of a segment register for a segment. +/// \param sg pointer to segment structure +/// if NULL, then set the register for all segments +/// \param rg number of segment register +/// \param value its default value. this value will be used by get_sreg() +/// if value of the register is unknown at the specified address. +/// \return success + +idaman bool ida_export set_default_sreg_value(segment_t *sg, int rg, sel_t value); + + +/// Set the segment register value at the next instruction. +/// This function is designed to be called from idb_event::sgr_changed handler +/// in order to contain the effect of changing a segment +/// register value only until the next instruction. +/// +/// It is useful, for example, in the ARM module: the modification +/// of the T register does not affect existing instructions later in the code. +/// \param ea1 address to start to search for an instruction +/// \param ea2 the maximal address +/// \param rg the segment register number +/// \param value the segment register value + +idaman void ida_export set_sreg_at_next_code(ea_t ea1, ea_t ea2, int rg, sel_t value); + + +/// Get segment register range by linear address. +/// \param out segment register range +/// \param ea any linear address in the program +/// \param rg the segment register number +/// \return success + +idaman bool ida_export get_sreg_range(sreg_range_t *out, ea_t ea, int rg); + + +/// Get segment register range previous to one with address. +/// \note more efficient then get_sreg_range(reg, ea-1) +/// \param out segment register range +/// \param ea any linear address in the program +/// \param rg the segment register number +/// \return success + +idaman bool ida_export get_prev_sreg_range(sreg_range_t *out, ea_t ea, int rg); + + +/// Set default value of DS register for all segments + +idaman void ida_export set_default_dataseg(sel_t ds_sel); + + +/// Get number of segment register ranges. +/// \param rg the segment register number + +idaman size_t ida_export get_sreg_ranges_qty(int rg); + + +/// Get segment register range by its number. +/// \param out segment register range +/// \param rg the segment register number +/// \param n number of range (0..qty()-1) +/// \return success + +idaman bool ida_export getn_sreg_range(sreg_range_t *out, int rg, int n); + + +/// Get number of segment register range by address. +/// \param ea any address in the range +/// \param rg the segment register number +/// \return -1 if no range occupies the specified address. +/// otherwise returns number of +/// the specified range (0..get_srranges_qty()-1) + +idaman int ida_export get_sreg_range_num(ea_t ea, int rg); + + +/// Delete segment register range started at ea. +/// When a segment register range is deleted, +/// the previous range is extended to cover the empty space. +/// The segment register range at the beginning of a segment cannot be deleted. +/// \param ea start_ea of the deleted range +/// \param rg the segment register number +/// \return success + +idaman bool ida_export del_sreg_range(ea_t ea, int rg); + + +/// Duplicate segment register ranges. +/// \param dst_rg number of destination segment register +/// \param src_rg copy ranges from +/// \param map_selector map selectors to linear addresses using sel2ea() + +idaman void ida_export copy_sreg_ranges(int dst_rg, int src_rg, bool map_selector=false); + + +#endif // _SRAREA_HPP diff --git a/idasdk76/include/strlist.hpp b/idasdk76/include/strlist.hpp new file mode 100644 index 0000000..71028fa --- /dev/null +++ b/idasdk76/include/strlist.hpp @@ -0,0 +1,78 @@ +/* + * The Interactive Disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _STRLIST_HPP +#define _STRLIST_HPP + +/*! \file strlist.hpp + + \brief Functions that deal with the string list + + While the kernel keeps the string list, it does not update it. + The string list is not used by the kernel because + keeping it up-to-date would slow down IDA without any benefit. + If the string list is not cleared using clear_strlist(), the list will be + saved to the database and restored on the next startup. + + The users of this list should call build_strlist() if they need an + up-to-date version. +*/ + +/// Structure to keep string list parameters +struct strwinsetup_t +{ + strwinsetup_t() + : minlen(-1), display_only_existing_strings(0), + only_7bit(1), ignore_heads(0) {} + bytevec_t strtypes; // set of allowed string types + sval_t minlen; + uchar display_only_existing_strings; + uchar only_7bit; + uchar ignore_heads; +}; + +/// Information about one string from the string list +struct string_info_t +{ + ea_t ea; + int length; // in octets + int type; + string_info_t() : ea(BADADDR), length(0), type(0) {} + string_info_t(ea_t _ea) : ea(_ea), length(0), type(0) {} + bool operator<(const string_info_t &r) const { return ea < r.ea; } +}; +DECLARE_TYPE_AS_MOVABLE(string_info_t); + + +/// Get the static string list options + +idaman const strwinsetup_t *ida_export get_strlist_options(); + + +/// Rebuild the string list. + +idaman void ida_export build_strlist(); + + +/// Clear the string list. + +idaman void ida_export clear_strlist(); + + +/// Get number of elements in the string list. +/// The list will be loaded from the database (if saved) or +/// built from scratch. + +idaman size_t ida_export get_strlist_qty(void); + + +/// Get nth element of the string list (n=0..get_strlist_qty()-1) + +idaman bool ida_export get_strlist_item(string_info_t *si, size_t n); + + +#endif // _STRLIST_HPP diff --git a/idasdk76/include/struct.hpp b/idasdk76/include/struct.hpp new file mode 100644 index 0000000..ffacb70 --- /dev/null +++ b/idasdk76/include/struct.hpp @@ -0,0 +1,661 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +/*! \file struct.hpp + + \brief Structure type management (assembly level types) + +*/ + +#ifndef _STRUCT_HPP +#define _STRUCT_HPP +#include <bytes.hpp> + +#define STRUC_SEPARATOR '.' ///< structname.fieldname + +/// Describes a member of an assembly level structure +class member_t +{ +public: + tid_t id; ///< name(), cmt, rptcmt + ea_t soff; ///< start offset (for unions - number of the member 0..n) + ea_t eoff; ///< end offset + flags_t flag; ///< type+representation bits +// private: + uint32 props; ///< \ref MF_ +/// \defgroup MF_ Struct member properties +/// Used by member_t::props +//@{ +#define MF_OK 0x00000001 ///< is the member ok? (always yes) +#define MF_UNIMEM 0x00000002 ///< is a member of a union? +#define MF_HASUNI 0x00000004 ///< has members of type "union"? +#define MF_BYTIL 0x00000008 ///< the member was created due to the type system +#define MF_HASTI 0x00000010 ///< has type information? +#define MF_BASECLASS 0x00000020 ///< a special member representing base class +#define MF_DTOR 0x00000040 ///< a special member representing destructor +#define MF_DUPNAME 0x00000080 ///< duplicate name resolved with _N suffix (N==soff) +//@} + + /// Is a member of a union? + bool unimem(void) const { return (props & MF_UNIMEM) != 0; } + /// Has members of type "union"? + bool has_union(void) const { return (props & MF_HASUNI) != 0; } + /// Was the member created due to the type system? + bool by_til(void) const { return (props & MF_BYTIL) != 0; } + /// Has type information? + bool has_ti(void) const { return (props & MF_HASTI) != 0; } + /// Is a base class member? + bool is_baseclass(void) const { return (props & MF_BASECLASS) != 0; } + /// Duplicate name was resolved during import? + bool is_dupname(void) const { return (props & MF_DUPNAME) != 0; } + /// Is a virtual destructor? + bool is_destructor(void) const { return (props & MF_DTOR) != 0; } + /// Get start offset (for unions - returns 0) + ea_t get_soff(void) const { return unimem() ? 0 : soff; } +}; + +/// Information about a structure type (assembly level) +//-V:struc_t:730 not all members of a class are initialized inside the constructor +class struc_t +{ +protected: + struc_t(void) {} ///< plugins may not create struc_t instances. they should + ///< use add_struc() and get_struc() +public: + tid_t id; ///< struct id + uint32 memqty; ///< number of members + member_t *members; ///< only defined members are stored here. + ///< there may be gaps between members. + ushort age; ///< not used + uint32 props; ///< \ref SF_ +/// \defgroup SF_ Structure properties +/// Used by struc_t::props +//@{ +#define SF_VAR 0x00000001 ///< is variable size structure (varstruct)? + ///< a variable size structure is one with + ///< the zero size last member. + ///< if the last member is a varstruct, then the current + ///< structure is a varstruct too. +#define SF_UNION 0x00000002 ///< is a union? + ///< varunions are prohibited! +#define SF_HASUNI 0x00000004 ///< has members of type "union"? +#define SF_NOLIST 0x00000008 ///< don't include in the chooser list +#define SF_TYPLIB 0x00000010 ///< the structure comes from type library +#define SF_HIDDEN 0x00000020 ///< the structure is collapsed +#define SF_FRAME 0x00000040 ///< the structure is a function frame +#define SF_ALIGN 0x00000F80 ///< alignment (shift amount: 0..31) +#define SF_GHOST 0x00001000 ///< ghost copy of a local type +//@} + + /// Is variable size structure? + bool is_varstr(void) const { return (props & SF_VAR) != 0; } + /// Is a union? + bool is_union(void) const { return (props & SF_UNION) != 0; } + /// Has members of type "union"? + bool has_union(void) const { return (props & SF_HASUNI) != 0; } + /// Is included in chooser list? + /// Use \ref set_struc_listed to change the listed status + bool is_choosable(void) const { return (props & SF_NOLIST) == 0; } + /// Does structure come from a type library? + bool from_til(void) const { return (props & SF_TYPLIB) != 0; } + /// Is the structure collapsed? + /// Use \ref set_struc_hidden to change the hidden status + bool is_hidden(void) const { return (props & SF_HIDDEN) != 0; } + /// Is this structure a function frame? + bool is_frame(void) const { return (props & SF_FRAME) != 0; } + /// See #SF_ALIGN + int get_alignment(void) const { return (props & SF_ALIGN) >> 7; } + /// Is a ghost copy of a local type? + bool is_ghost(void) const { return (props & SF_GHOST) != 0; } + + /// Do not use; use set_struc_align() + void set_alignment(int shift) + { + props &= ~SF_ALIGN; + props |= (shift << 7) & SF_ALIGN; + } + + void set_ghost(bool _is_ghost) { setflag(props, SF_GHOST, _is_ghost); } + + mutable int32 ordinal; ///< corresponding local type ordinal number +}; + +/// \name Internal structures list +/// IDA maintains an internal vector of known structures. +/// Use these functions to work with this vector. +//@{ + +/// Get number of known structures + +idaman size_t ida_export get_struc_qty(void); + + +/// Get index of first structure. +/// \return #BADADDR if no known structures, 0 otherwise + +idaman uval_t ida_export get_first_struc_idx(void); + + +/// Get index of last structure. +/// \return #BADADDR if no known structures, get_struc_qty()-1 otherwise + +idaman uval_t ida_export get_last_struc_idx(void); + + +/// Get previous struct index. +/// \return #BADADDR if resulting index is negative, otherwise idx - 1 + +inline THREAD_SAFE uval_t get_prev_struc_idx(uval_t idx) { return idx == BADNODE ? idx : idx - 1; } + + +/// Get next struct index. +/// \return #BADADDR if resulting index is out of bounds, otherwise idx++ + +idaman uval_t ida_export get_next_struc_idx(uval_t idx); + + +/// Get internal number of the structure + +idaman uval_t ida_export get_struc_idx(tid_t id); + + +/// Get struct id by struct number + +idaman tid_t ida_export get_struc_by_idx(uval_t idx); + + +/// Get pointer to struct type info + +idaman struc_t *ida_export get_struc(tid_t id); + +//@} + + +/// Get struct id by name + +inline tid_t get_struc_id(const char *name) +{ + tid_t id = node2ea(netnode(name)); + return get_struc(id) == NULL ? BADADDR : id; +} + + +/// Get struct name by id +/// \param[out] out buffer to hold the name +/// \param id struct id +/// \param flags \ref STRNFL_ + +idaman ssize_t ida_export get_struc_name(qstring *out, tid_t id, int flags=0); + +/// \defgroup STRNFL_ Struct name flags +/// Passed as 'flags' parameter to get_struc_name() +//@{ +#define STRNFL_REGEX 0x0001 ///< apply regular expressions to beautify the name +//@} + +inline qstring get_struc_name(tid_t id, int flags=0) +{ + qstring name; + get_struc_name(&name, id, flags); + return name; +} + +/// Get struct comment + +inline ssize_t get_struc_cmt(qstring *buf, tid_t id, bool repeatable) { return getnode(id).supstr(buf, repeatable != 0); } + + +/// Get struct size (also see get_struc_size(tid_t)) + +idaman asize_t ida_export get_struc_size(const struc_t *sptr); + +/// Get struct size (also see get_struc_size(const struc_t *)) + +inline asize_t get_struc_size(tid_t id) { return get_struc_size(get_struc(id)); } + + +/// \name Struct offsets +/// \note for unions, soff == number of the current member +//@{ + +/// Get offset of member with largest offset less than 'offset'. +/// \return #BADADDR if no prev offset + +idaman ea_t ida_export get_struc_prev_offset(const struc_t *sptr, ea_t offset); + + +/// Get offset of member with smallest offset larger than 'offset'. +/// \return #BADADDR if no next offset + +idaman ea_t ida_export get_struc_next_offset(const struc_t *sptr, ea_t offset); + + +/// Get offset of last member. +/// \return #BADADDR if memqty == 0 + +idaman ea_t ida_export get_struc_last_offset(const struc_t *sptr); + + +/// Get offset of first member. +/// \return #BADADDR if memqty == 0 + +idaman ea_t ida_export get_struc_first_offset(const struc_t *sptr); + + +/// For unions: returns number of members, for structs: returns size of structure + +inline ea_t get_max_offset(struc_t *sptr) +{ + if ( sptr == NULL ) + return 0; // just to avoid GPF + return sptr->is_union() + ? sptr->memqty + : get_struc_size(sptr); +} + +//@} + +/// Is variable size structure? + +inline bool is_varstr(tid_t id) +{ + struc_t *sptr = get_struc(id); + return sptr != NULL && sptr->is_varstr(); +} + +/// Is a union? + +inline bool is_union(tid_t id) +{ + struc_t *sptr = get_struc(id); + return sptr != NULL && sptr->is_union(); +} + + +/// Get containing structure of member by its full name "struct.field" + +idaman struc_t *ida_export get_member_struc(const char *fullname); + + +/// Get child struct if member is a struct + +idaman struc_t *ida_export get_sptr(const member_t *mptr); + + +/// Get member at given offset + +idaman member_t *ida_export get_member(const struc_t *sptr, asize_t offset); + +/// Get member id at given offset + +inline tid_t get_member_id(const struc_t *sptr, asize_t offset) +{ + member_t *mptr = get_member(sptr, offset); + return mptr != NULL ? mptr->id : BADADDR; +} + + +/// Get the innermost member at the given offset +/// \param[in] sptr the starting structure +/// \param[out] sptr the innermost structure +/// \param[in] offset offset into the starting structure +/// \param[out] offset remaining offset into the returned member +/// \retval a member in SPTR (it is not a structure) or 'nullptr' + +idaman member_t *ida_export get_innermost_member(struc_t **sptr, asize_t *offset); + + +/// Get a member by its name, like "field44" + +idaman member_t *ida_export get_member_by_name(const struc_t *sptr, const char *membername); + + +/// Get a member by its fully qualified name, "struct.field" + +idaman member_t *ida_export get_member_by_fullname(struc_t **sptr_place, const char *fullname); + + +/// Get a member's fully qualified name, "struct.field" + +inline ssize_t idaapi get_member_fullname(qstring *out, tid_t mid) { return getnode(mid).get_name(out); } + + +/// Get name of structure member + +idaman ssize_t ida_export get_member_name(qstring *out, tid_t mid); + +inline qstring get_member_name(tid_t mid) +{ + qstring name; + get_member_name(&name, mid); + return name; +} + + +/// Get comment of structure member + +inline ssize_t idaapi get_member_cmt(qstring *buf, tid_t mid, bool repeatable) { return getnode(mid).supstr(buf, repeatable != 0); } + + +/// Get size of structure member. +/// May return 0 for the last member of varstruct. +/// For union members, returns member_t::eoff. + +inline asize_t get_member_size(const member_t *NONNULL mptr) { return mptr->unimem() ? mptr->eoff : (mptr->eoff - mptr->soff); } + + +/// Is variable size member? + +idaman bool ida_export is_varmember(const member_t *mptr); + + +/// Get member that is most likely referenced by the specified offset. +/// Useful for offsets > sizeof(struct). + +idaman member_t *ida_export get_best_fit_member(const struc_t *sptr, asize_t offset); + + +/// Get the next member idx, if it does not exist, return -1 + +idaman ssize_t ida_export get_next_member_idx(const struc_t *sptr, asize_t off); + + +/// Get the prev member idx, if it does not exist, return -1 + +idaman ssize_t ida_export get_prev_member_idx(const struc_t *sptr, asize_t off); + +//-------------------------------------------------------------------------- +// manipulation + +/// Create a structure type. +/// if idx==#BADADDR then add as the last idx. +/// if name==NULL then a name will be generated "struct_%d". + +idaman tid_t ida_export add_struc(uval_t idx, const char *name, bool is_union=false); + + +/// Delete a structure type + +idaman bool ida_export del_struc(struc_t *sptr); + + +/// Set internal number of struct. +/// Also see get_struc_idx(), get_struc_by_idx(). + +idaman bool ida_export set_struc_idx(const struc_t *sptr, uval_t idx); + + +/// Set structure alignment (#SF_ALIGN) + +idaman bool ida_export set_struc_align(struc_t *sptr, int shift); + + +/// Set structure name + +idaman bool ida_export set_struc_name(tid_t id, const char *name); + + +/// Set structure comment + +idaman bool ida_export set_struc_cmt(tid_t id, const char *cmt, bool repeatable); + + +/// Return values for add_struc_member() +enum struc_error_t +{ + STRUC_ERROR_MEMBER_OK = 0, ///< success + STRUC_ERROR_MEMBER_NAME = -1, ///< already has member with this name (bad name) + STRUC_ERROR_MEMBER_OFFSET = -2, ///< already has member at this offset + STRUC_ERROR_MEMBER_SIZE = -3, ///< bad number of bytes or bad sizeof(type) + STRUC_ERROR_MEMBER_TINFO = -4, ///< bad typeid parameter + STRUC_ERROR_MEMBER_STRUCT = -5, ///< bad struct id (the 1st argument) + STRUC_ERROR_MEMBER_UNIVAR = -6, ///< unions can't have variable sized members + STRUC_ERROR_MEMBER_VARLAST = -7, ///< variable sized member should be the last member in the structure + STRUC_ERROR_MEMBER_NESTED = -8, ///< recursive structure nesting is forbidden +}; + + +/// Add member to existing structure. +/// \param sptr structure to modify +/// \param fieldname if NULL, then "anonymous_#" name will be generated +/// \param offset #BADADDR means add to the end of structure +/// \param flag type + representation bits +/// \param mt additional info about member type. +/// must be present for +/// structs, offsets, enums, strings, +/// struct offsets. +/// \param nbytes if == 0 then the structure +/// will be a varstruct. +/// in this case the member should be +/// the last member in the structure + +idaman struc_error_t ida_export add_struc_member( + struc_t *sptr, + const char *fieldname, + ea_t offset, + flags_t flag, + const opinfo_t *mt, + asize_t nbytes); + + +/// Delete member at given offset + +idaman bool ida_export del_struc_member(struc_t *sptr, ea_t offset); + + +/// Delete members which occupy range of offsets (off1..off2). +/// \return number of deleted members or -1 on error + +idaman int ida_export del_struc_members(struc_t *sptr, ea_t off1, ea_t off2); + + +/// Set name of member at given offset + +idaman bool ida_export set_member_name(struc_t *sptr, ea_t offset,const char *name); + + +/// Set type of member at given offset (also see add_struc_member()) + +idaman bool ida_export set_member_type(struc_t *sptr, ea_t offset, flags_t flag,const opinfo_t *mt, asize_t nbytes); + + +/// Set member comment + +idaman bool ida_export set_member_cmt(member_t *mptr,const char *cmt, bool repeatable); + + +/// Expand/Shrink structure type + +idaman bool ida_export expand_struc(struc_t *sptr, ea_t offset, adiff_t delta, bool recalc=true); + + +/// Update struct information in the database (internal function) + +idaman void ida_export save_struc(struc_t *sptr, bool may_update_ltypes=true); + + +/// Hide/unhide a struct type +inline void idaapi set_struc_hidden(struc_t *sptr, bool is_hidden) +{ + setflag(sptr->props, SF_HIDDEN, is_hidden); + save_struc(sptr, false); +} + +/// Add/remove a struct type from the struct list +inline void idaapi set_struc_listed(struc_t *sptr, bool is_listed) +{ + setflag(sptr->props, SF_NOLIST, !is_listed); + save_struc(sptr, false); +} + +/// Member type information (return values for set_member_tinfo()) +enum smt_code_t +{ + SMT_BADARG = -6, ///< bad parameters + SMT_NOCOMPAT = -5, ///< the new type is not compatible with the old type + SMT_WORSE = -4, ///< the new type is worse than the old type + SMT_SIZE = -3, ///< the new type is incompatible with the member size + SMT_ARRAY = -2, ///< arrays are forbidden as function arguments + SMT_OVERLAP = -1, ///< member would overlap with members that cannot be deleted + SMT_FAILED = 0, ///< failed to set new member type + SMT_OK = 1, ///< success: changed the member type + SMT_KEEP = 2, ///< no need to change the member type, the old type is better +}; + + +/// Get tinfo for given member + +idaman bool ida_export get_member_tinfo(tinfo_t *tif, const member_t *mptr); + + +/// Delete tinfo for given member + +idaman bool ida_export del_member_tinfo(struc_t *sptr, member_t *mptr); + + +/// Set tinfo for given member. +/// \param sptr containing struct +/// \param mptr target member +/// \param memoff offset within member +/// \param tif type info +/// \param flags \ref SET_MEMTI_ + +idaman smt_code_t ida_export set_member_tinfo( + struc_t *sptr, + member_t *mptr, + uval_t memoff, + const tinfo_t &tif, + int flags); + +/// \defgroup SET_MEMTI_ Set member tinfo flags +/// Passed as 'flags' parameter to set_member_tinfo() +//@{ +#define SET_MEMTI_MAY_DESTROY 0x0001 ///< may destroy other members +#define SET_MEMTI_COMPATIBLE 0x0002 ///< new type must be compatible with the old +#define SET_MEMTI_FUNCARG 0x0004 ///< mptr is function argument (cannot create arrays) +#define SET_MEMTI_BYTIL 0x0008 ///< new type was created by the type subsystem +#define SET_MEMTI_USERTI 0x0010 ///< user-specified type +//@} + + +/// Try to get tinfo for given member - if failed, generate a tinfo using information about the +/// member id from the disassembly + +idaman bool ida_export get_or_guess_member_tinfo(tinfo_t *tif, const member_t *mptr); + + +/// Get operand type info for member + +inline opinfo_t *retrieve_member_info(opinfo_t *buf, const member_t *mptr) +{ + if ( mptr == NULL ) + return NULL; + return get_opinfo(buf, mptr->id, 0, mptr->flag); +} + + +/// Is member name prefixed with "anonymous"? + +inline THREAD_SAFE bool is_anonymous_member_name(const char *name) +{ + return name == NULL + || strncmp(name, "anonymous", 9) == 0; +} + + +/// Is member name an auto-generated name? + +inline THREAD_SAFE bool is_dummy_member_name(const char *name) +{ + return name == NULL + || strncmp(name, "arg_", 4) == 0 + || strncmp(name, "var_", 4) == 0 + || is_anonymous_member_name(name); +} + + +/// Check if the specified member id points to a struct member + +inline member_t *idaapi get_member_by_id( + qstring *out_mname, // note: id 'out_mname' is important for SWiG + tid_t mid, + struc_t **sptr_place) +{ + if ( get_member_fullname(out_mname, mid) > 0 ) + return get_member_by_fullname(sptr_place, out_mname->begin()); + return NULL; +} + + +/// Check if the specified member id points to a struct member. convenience function + +inline member_t *idaapi get_member_by_id(tid_t mid, struc_t **sptr_place=NULL) +{ + qstring buf; + return get_member_by_id(&buf, mid, sptr_place); +} + + +/// Is a member id? + +inline bool is_member_id(tid_t mid) +{ + return get_member_by_id(mid) != NULL; +} + + +/// Is a special member with the name beginning with ' '? + +idaman bool ida_export is_special_member(tid_t id); + + +/// Implements action to take when a field is visited with visit_stroff_fields() +struct ida_local struct_field_visitor_t +{ + virtual int idaapi visit_field(struc_t *sptr, member_t *mptr) = 0; +}; + + +//-------------------------------------------------------------------------- +/// Visit structure fields in a stroff expression or in a reference to a struct data variable. +/// This function can be used to enumerate all components of an expression like 'a.b.c'. +/// \param sfv visitor object +/// \param path struct path (path[0] contains the initial struct id) +/// \param plen len +/// \param[in,out] disp offset into structure +/// \param appzero should visit field at offset zero? + +idaman flags_t ida_export visit_stroff_fields( + struct_field_visitor_t &sfv, + const tid_t *path, + int plen, + adiff_t *disp, + bool appzero); + + +//-------------------------------------------------------------------------- +/// Should display a structure offset expression as the structure size? + +inline bool stroff_as_size(int plen, const struc_t *sptr, asize_t value) +{ + return plen == 1 + && value > 0 + && sptr != NULL + && !sptr->is_varstr() + && value == get_struc_size(sptr); +} + +//------------------------------------------------------------------------- +// F U N C T I O N S F O R T H E K E R N E L +//------------------------------------------------------------------------- + +///-------------------------------------------------------------------\cond +inline void save_structs(void) {} +///----------------------------------------------------------------\endcond + + +#endif // _STRUCT_HPP diff --git a/idasdk76/include/tryblks.hpp b/idasdk76/include/tryblks.hpp new file mode 100644 index 0000000..ebc2c5c --- /dev/null +++ b/idasdk76/include/tryblks.hpp @@ -0,0 +1,218 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 2016-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Module independent exception description + */ + +#ifndef TRYBLKS_HPP +#define TRYBLKS_HPP + +/*! \file tryblks.hpp + * + * \brief Architecture independent exception handling info. + * + * Try blocks have the following general properties: + * - A try block specifies a possibly fragmented guarded code region. + * - Each try block has always at least one catch/except block description + * - Each catch block contains its boundaries and a filter. + * - Additionally a catch block can hold sp adjustment and the offset to the + * exception object offset (C++). + * - Try blocks can be nested. Nesting is automatically calculated at the retrieval time. + * - There may be (nested) multiple try blocks starting at the same address. + * + * See examples in tests/input/src/eh_tests. + * + */ + +// We use end_ea=BADADDR if the exact boundaries are unknown of any range. + +//---------------------------------------------------------------------------- +// An exception handler clause (the body of __except or catch statement) +struct try_handler_t : public rangevec_t +{ + sval_t disp; // displacement to the stack region of the guarded region. + // if it is valid, it is fpreg relative. + // -1 means unknown. + int fpreg; // frame register number used in handler. -1 means none. + + try_handler_t() : disp(-1), fpreg(-1) {} + void clear(void) + { + rangevec_t::clear(); + disp = -1; + fpreg = -1; + } +}; +DECLARE_TYPE_AS_MOVABLE(try_handler_t); + +//---------------------------------------------------------------------------- +// __except() {} statement +struct seh_t : public try_handler_t +{ + rangevec_t filter; // boundaries of the filter callback. if filter is empty, + ea_t seh_code; // then use seh_code +#define SEH_CONTINUE BADADDR // EXCEPTION_CONTINUE_EXECUTION (-1) +#define SEH_SEARCH ea_t(0) // EXCEPTION_CONTINUE_SEARCH (0) (alias of __finally) +#define SEH_HANDLE ea_t(1) // EXCEPTION_EXECUTE_HANDLER (1) + void clear(void) + { + try_handler_t::clear(); + filter.clear(); + seh_code = SEH_CONTINUE; + } +}; +DECLARE_TYPE_AS_MOVABLE(seh_t); + +//---------------------------------------------------------------------------- +// catch() {} statement +struct catch_t : public try_handler_t +{ + sval_t obj; // fpreg relative displacement to the exception object. -1 if unknown. + sval_t type_id; // the type caught by this catch. -1 means "catch(...)" +#define CATCH_ID_ALL sval_t(-1) // catch(...) +#define CATCH_ID_CLEANUP sval_t(-2) // a cleanup handler invoked if exception occures + + catch_t() : obj(-1), type_id(-1) {} +}; +DECLARE_TYPE_AS_MOVABLE(catch_t); +typedef qvector<catch_t> catchvec_t; + +//---------------------------------------------------------------------------- +class tryblk_t : public rangevec_t // block guarded by try/__try {...} statements +{ +#ifndef SWIG + char reserve[qmax(sizeof(catchvec_t), sizeof(seh_t))]; // seh_t or catchvec_t +#endif + uchar cb; // size of tryblk_t + uchar kind; // one of the following kinds +#define TB_NONE 0 // empty +#define TB_SEH 1 // MS SEH __try/__except/__finally +#define TB_CPP 2 // C++ language try/catch + +public: + uchar level; // nesting level, calculated by get_tryblks() + + // C++ try/catch block (TB_CPP) + catchvec_t &cpp() { return *(( catchvec_t *)reserve); } + const catchvec_t &cpp() const { return *((const catchvec_t *)reserve); } + + // SEH __except/__finally case (TB_SEH) + seh_t &seh() { return *(( seh_t *)reserve); } + const seh_t &seh() const { return *((const seh_t *)reserve); } + + tryblk_t() : rangevec_t(), cb(sizeof(*this)), kind(TB_NONE), level(0) { reserve[0] = '\0'; } + ~tryblk_t() { clear(); } + tryblk_t(const tryblk_t &r) : rangevec_t(), kind(TB_NONE) { *this = r; } + uchar get_kind(void) const { return kind; } + bool empty(void) const { return kind == TB_NONE; } + bool is_seh(void) const { return kind == TB_SEH; } + bool is_cpp(void) const { return kind == TB_CPP; } + + + //------------------------------------------------------------------------- + tryblk_t &operator=(const tryblk_t &r) + { + if ( this != &r ) // don't copy yourself + { + if ( kind != TB_NONE ) + clear(); + kind = r.kind; + level = r.level; + rangevec_t::operator=(r); + + if ( kind == TB_SEH ) + new (reserve) seh_t(r.seh()); + else if ( kind == TB_CPP ) + new (reserve) catchvec_t(r.cpp()); + } + return *this; + } + + //------------------------------------------------------------------------- + void clear(void) + { + if ( kind == TB_CPP ) + cpp().~catchvec_t(); + else if ( kind == TB_SEH ) + seh().~seh_t(); + kind = TB_NONE; + } + + //------------------------------------------------------------------------- + seh_t &set_seh(void) + { + if ( kind != TB_SEH ) + { + clear(); + new (reserve) seh_t; + kind = TB_SEH; + } + else + { + seh().clear(); + } + return seh(); + } + + //------------------------------------------------------------------------- + catchvec_t &set_cpp(void) + { + if ( kind != TB_CPP ) + { + clear(); + new (reserve) catchvec_t; + kind = TB_CPP; + } + else + { + cpp().clear(); + } + return cpp(); + } +}; +DECLARE_TYPE_AS_MOVABLE(tryblk_t); +typedef qvector<tryblk_t> tryblks_t; + +///------------------------------------------------------------------------- +/// Retrieve try block information from the specified address range. +/// Try blocks are sorted by starting address and their nest levels calculated. +/// \param tbv output buffer; may be NULL +/// \param range address range to change +/// \return number of found try blocks + +idaman size_t ida_export get_tryblks(tryblks_t *tbv, const range_t &range); + +/// Delete try block information in the specified range. +/// \param range the range to be cleared + +idaman void ida_export del_tryblks(const range_t &range); + + +/// Add one try block information. +/// \param tb try block to add. +/// \return error code; 0 means good + +idaman int ida_export add_tryblk(const tryblk_t &tb); + +/// \defgroup TBERR_ Try block handling error codes +//@{ +#define TBERR_OK 0 ///< ok +#define TBERR_START 1 ///< bad start address +#define TBERR_END 2 ///< bad end address +#define TBERR_ORDER 3 ///< bad address order +#define TBERR_EMPTY 4 ///< empty try block +#define TBERR_KIND 5 ///< illegal try block kind +#define TBERR_NO_CATCHES 6 ///< no catch blocks at all +#define TBERR_INTERSECT 7 ///< range would intersect inner tryblk +//@} + +/// Find the start address of the system eh region including the argument. +/// \param ea search address +/// \return start address of surrounding tryblk, otherwise BADADDR + +idaman ea_t ida_export find_syseh(ea_t ea); + + +#endif // TRYBLKS_HPP diff --git a/idasdk76/include/typeinf.hpp b/idasdk76/include/typeinf.hpp new file mode 100644 index 0000000..1070131 --- /dev/null +++ b/idasdk76/include/typeinf.hpp @@ -0,0 +1,4396 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Type Information. + * + */ + +#ifndef _TYPEINF_HPP +#define _TYPEINF_HPP +#include <idp.hpp> +#include <name.hpp> + +/*! \file typeinf.hpp + + \brief Describes the type information records in IDA. + + The recommended way of using type info is to use the ::tinfo_t class. + The type information is internally kept as an array of bytes terminated by 0. + + Items in brackets [] are optional and sometimes are omitted. + ::type_t... means a sequence of ::type_t bytes which defines a type. + + \note to work with the types of instructions or data in the database, + use get_tinfo()/set_tinfo() and similar functions. +*/ + +/// byte sequence used to describe a type in IDA (see \ref tf) +typedef uchar type_t; +/// pascal-like string: dt length, characters +typedef uchar p_string; +/// several ::p_string's +typedef uchar p_list; + +struct til_t; // type information library +class lexer_t; // lexical analyzer +class argloc_t; // argument location +class tinfo_t; // type info object + +struct func_type_data_t; +struct til_bucket_t; +struct til_stream_t; + +//------------------------------------------------------------------------ +#define RESERVED_BYTE 0xFF ///< multifunctional purpose +//------------------------------------------------------------------------ +/// \defgroup tf Type flags +/// Here we describe the byte arrays used to describe type information +//@{ + +/// \defgroup tf_mask Masks +//@{ +const type_t TYPE_BASE_MASK = 0x0F; ///< the low 4 bits define the basic type +const type_t TYPE_FLAGS_MASK = 0x30; ///< type flags - they have different + ///< meaning depending on the basic type +const type_t TYPE_MODIF_MASK = 0xC0; ///< modifiers. + ///< - for ::BT_ARRAY see \ref tf_array + ///< - ::BT_VOID can have them ONLY in 'void *' + +const type_t TYPE_FULL_MASK = (TYPE_BASE_MASK | TYPE_FLAGS_MASK); ///< basic type with type flags +//@} + +/*! \defgroup tf_unk Basic type: unknown & void + ::BT_UNK and ::BT_VOID with non-zero type flags can be used in function + (and struct) declarations to describe the function arguments or structure + fields if only their size is known. They may be used in ida to describe + the user input. + + For struct used also as 'single-field-alignment-suffix' + [__declspec(align(x))] with ::TYPE_MODIF_MASK == ::TYPE_FULL_MASK. +*/ +//@{ +const type_t BT_UNK = 0x00; ///< unknown +const type_t BT_VOID = 0x01; ///< void +const type_t BTMT_SIZE0 = 0x00; ///< ::BT_VOID - normal void; ::BT_UNK - don't use +const type_t BTMT_SIZE12 = 0x10; ///< size = 1 byte if ::BT_VOID; 2 if ::BT_UNK +const type_t BTMT_SIZE48 = 0x20; ///< size = 4 bytes if ::BT_VOID; 8 if ::BT_UNK +const type_t BTMT_SIZE128 = 0x30; ///< size = 16 bytes if ::BT_VOID; unknown if ::BT_UNK + ///< (IN struct alignment - see below) +//@} + +/// \defgroup tf_int Basic type: integer +//@{ +const type_t BT_INT8 = 0x02; ///< __int8 +const type_t BT_INT16 = 0x03; ///< __int16 +const type_t BT_INT32 = 0x04; ///< __int32 +const type_t BT_INT64 = 0x05; ///< __int64 +const type_t BT_INT128 = 0x06; ///< __int128 (for alpha & future use) +const type_t BT_INT = 0x07; ///< natural int. (size provided by idp module) +const type_t BTMT_UNKSIGN = 0x00; ///< unknown signedness +const type_t BTMT_SIGNED = 0x10; ///< signed +const type_t BTMT_USIGNED = 0x20; ///< unsigned +const type_t BTMT_UNSIGNED = BTMT_USIGNED; +const type_t BTMT_CHAR = 0x30; ///< specify char or segment register + ///< - ::BT_INT8 - char + ///< - ::BT_INT - segment register + ///< - other BT_INT... - don't use +//@} + +/// \defgroup tf_bool Basic type: bool +//@{ +const type_t BT_BOOL = 0x08; ///< bool +const type_t BTMT_DEFBOOL = 0x00; ///< size is model specific or unknown(?) +const type_t BTMT_BOOL1 = 0x10; ///< size 1byte +const type_t BTMT_BOOL2 = 0x20; ///< size 2bytes - !inf_is_64bit() +const type_t BTMT_BOOL8 = 0x20; ///< size 8bytes - inf_is_64bit() +const type_t BTMT_BOOL4 = 0x30; ///< size 4bytes +//@} + +/// \defgroup tf_float Basic type: float +//@{ +const type_t BT_FLOAT = 0x09; ///< float +const type_t BTMT_FLOAT = 0x00; ///< float (4 bytes) +const type_t BTMT_DOUBLE = 0x10; ///< double (8 bytes) +const type_t BTMT_LNGDBL = 0x20; ///< long double (compiler specific) +const type_t BTMT_SPECFLT = 0x30; ///< float (variable size). + ///< if \ph{use_tbyte()} then use \ph{tbyte_size}, + ///< otherwise 2 bytes +//@} + +/// \defgroup tf_last_basic Basic type: last +//@{ +const type_t _BT_LAST_BASIC = BT_FLOAT; ///< the last basic type, + ///< all basic types may be followed by + ///< [tah-typeattrs] +//@} + +/*! \defgroup tf_ptr Derived type: pointer + Pointers to undeclared yet ::BT_COMPLEX types are prohibited +*/ +//@{ +const type_t BT_PTR = 0x0A; ///< pointer. + ///< has the following format: + ///< [db sizeof(ptr)]; [tah-typeattrs]; type_t... +const type_t BTMT_DEFPTR = 0x00; ///< default for model +const type_t BTMT_NEAR = 0x10; ///< near +const type_t BTMT_FAR = 0x20; ///< far +const type_t BTMT_CLOSURE = 0x30; ///< closure. + ///< - if ptr to ::BT_FUNC - __closure. + ///< in this case next byte MUST be + ///< #RESERVED_BYTE, and after it ::BT_FUNC + ///< - else the next byte contains sizeof(ptr) + ///< allowed values are 1 - \varmem{ph,processor_t,max_ptr_size} + ///< - if value is bigger than \varmem{ph,processor_t,max_ptr_size}, + ///< based_ptr_name_and_size() is called to + ///< find out the typeinfo +//@} + +/*! \defgroup tf_array Derived type: array + For ::BT_ARRAY, the BTMT_... flags must be equivalent to the BTMT_... flags of its elements +*/ +//@{ +const type_t BT_ARRAY = 0x0B; ///< array +const type_t BTMT_NONBASED = 0x10; ///< \code + /// if set + /// array base==0 + /// format: dt num_elem; [tah-typeattrs]; type_t... + /// if num_elem==0 then the array size is unknown + /// else + /// format: da num_elem, base; [tah-typeattrs]; type_t... \endcode + /// used only for serialization +const type_t BTMT_ARRESERV = 0x20; ///< reserved bit +//@} + +/*! \defgroup tf_func Derived type: function + Ellipsis is not taken into account in the number of parameters + The return type cannot be ::BT_ARRAY or ::BT_FUNC. +*/ +//@{ +const type_t BT_FUNC = 0x0C; ///< function. + ///< format: <pre> + /// optional: ::CM_CC_SPOILED | num_of_spoiled_regs + /// if num_of_spoiled_reg == BFA_FUNC_MARKER: + /// ::bfa_byte + /// if (bfa_byte & BFA_FUNC_EXT_FORMAT) != 0 + /// ::fti_bits (only low bits: FTI_SPOILED,...,FTI_VIRTUAL) + /// num_of_spoiled_reg times: spoiled reg info (see extract_spoiledreg) + /// else + /// bfa_byte is function attribute byte (see \ref BFA_...) + /// else: + /// num_of_spoiled_reg times: spoiled reg info (see extract_spoiledreg) + /// ::cm_t ... calling convention and memory model + /// [tah-typeattrs]; + /// ::type_t ... return type; + /// [serialized argloc_t of returned value (if ::CM_CC_SPECIAL{PE} && !return void); + /// if !::CM_CC_VOIDARG: + /// dt N (N=number of parameters) + /// if ( N == 0 ) + /// if ::CM_CC_ELLIPSIS or ::CM_CC_SPECIALE + /// func(...) + /// else + /// parameters are unknown + /// else + /// N records: + /// ::type_t ... (i.e. type of each parameter) + /// [serialized argloc_t (if ::CM_CC_SPECIAL{PE})] (i.e. place of each parameter) + /// [#FAH_BYTE + de( \ref funcarg_t::flags )] </pre> + +const type_t BTMT_DEFCALL = 0x00; ///< call method - default for model or unknown +const type_t BTMT_NEARCALL = 0x10; ///< function returns by retn +const type_t BTMT_FARCALL = 0x20; ///< function returns by retf +const type_t BTMT_INTCALL = 0x30; ///< function returns by iret + ///< in this case cc MUST be 'unknown' +//@} + +/// \defgroup tf_complex Derived type: complex +//@{ +const type_t BT_COMPLEX = 0x0D; ///< struct/union/enum/typedef. + ///< format: <pre> + /// [dt N (N=field count) if !::BTMT_TYPEDEF] + /// if N == 0: + /// p_string name (unnamed types have names "anon_...") + /// [sdacl-typeattrs]; + /// else, for struct & union: + /// if N == 0x7FFE // Support for high (i.e., > 4095) members count + /// N = deserialize_de() + /// ALPOW = N & 0x7 + /// MCNT = N >> 3 + /// if MCNT == 0 + /// empty struct + /// if ALPOW == 0 + /// ALIGN = get_default_align() + /// else + /// ALIGN = (1 << (ALPOW - 1)) + /// [sdacl-typeattrs]; + /// else, for enums: + /// if N == 0x7FFE // Support for high enum entries count. + /// N = deserialize_de() + /// [tah-typeattrs]; </pre> + /// +const type_t BTMT_STRUCT = 0x00; ///< struct: + ///< MCNT records: type_t; [sdacl-typeattrs]; +const type_t BTMT_UNION = 0x10; ///< union: + ///< MCNT records: type_t... +const type_t BTMT_ENUM = 0x20; ///< enum: + ///< next byte bte_t (see below) + ///< N records: de delta(s) + ///< OR + ///< blocks (see below) +const type_t BTMT_TYPEDEF = 0x30; ///< named reference + ///< always p_string name + +const type_t BT_BITFIELD = 0x0E; ///< bitfield (only in struct) + ///< ['bitmasked' enum see below] + ///< next byte is dt + ///< ((size in bits << 1) | (unsigned ? 1 : 0)) +const type_t BTMT_BFLDI8 = 0x00; ///< __int8 +const type_t BTMT_BFLDI16 = 0x10; ///< __int16 +const type_t BTMT_BFLDI32 = 0x20; ///< __int32 +const type_t BTMT_BFLDI64 = 0x30; ///< __int64 +//@} + +const type_t BT_RESERVED = 0x0F; ///< RESERVED + + +//------------------------------------------------------------------------ +/*! \defgroup tf_modifiers Type modifiers + "const volatile" types are forbidden +*/ +//@{ +const type_t BTM_CONST = 0x40; ///< const +const type_t BTM_VOLATILE = 0x80; ///< volatile +//@} + +//------------------------------------------------------------------------ +/// \defgroup tf_enum Special enum definitions +//@{ +typedef uchar bte_t; ///< Enum type flags + +const bte_t BTE_SIZE_MASK = 0x07; ///< storage size. + ///< - if == 0 then inf_get_cc_size_e() + ///< - else 1 << (n -1) = 1,2,4...64 +const bte_t BTE_RESERVED = 0x08; ///< must be 0, in order to distinguish + ///< from a tah-byte +const bte_t BTE_BITFIELD = 0x10; ///< 'subarrays'. In this case ANY record + ///< has the following format: + ///< - 'de' mask (has name) + ///< - 'dt' cnt + ///< - cnt records of 'de' values + ///< (cnt CAN be 0) + ///< \note delta for ALL subsegment is ONE +const bte_t BTE_OUT_MASK = 0x60; ///< output style mask +const bte_t BTE_HEX = 0x00; ///< hex +const bte_t BTE_CHAR = 0x20; ///< char or hex +const bte_t BTE_SDEC = 0x40; ///< signed decimal +const bte_t BTE_UDEC = 0x60; ///< unsigned decimal +const bte_t BTE_ALWAYS = 0x80; ///< this bit MUST be present +//@} + +/// \defgroup tf_conv_segreg Convenience definitions: segment register +//@{ +const type_t BT_SEGREG = (BT_INT | BTMT_CHAR); ///< segment register +//@} + +/// \defgroup tf_conv_unk Convenience definitions: unknown types +//@{ +const type_t BT_UNK_BYTE = (BT_VOID | BTMT_SIZE12); ///< 1 byte +const type_t BT_UNK_WORD = (BT_UNK | BTMT_SIZE12); ///< 2 bytes +const type_t BT_UNK_DWORD = (BT_VOID | BTMT_SIZE48); ///< 4 bytes +const type_t BT_UNK_QWORD = (BT_UNK | BTMT_SIZE48); ///< 8 bytes +const type_t BT_UNK_OWORD = (BT_VOID | BTMT_SIZE128); ///< 16 bytes +const type_t BT_UNKNOWN = (BT_UNK | BTMT_SIZE128); ///< unknown size - for parameters +//@} + +//------------------------------------------------------------------------ +/// \defgroup tf_shortcuts Convenience definitions: shortcuts +//@{ +const type_t BTF_BYTE = BT_UNK_BYTE; ///< byte +const type_t BTF_UNK = BT_UNKNOWN; ///< unknown +const type_t BTF_VOID = BT_VOID | BTMT_SIZE0; ///< void + +const type_t BTF_INT8 = BT_INT8 | BTMT_SIGNED; ///< signed byte +const type_t BTF_CHAR = BT_INT8 | BTMT_CHAR; ///< signed char +const type_t BTF_UCHAR = BT_INT8 | BTMT_USIGNED; ///< unsigned char +const type_t BTF_UINT8 = BT_INT8 | BTMT_USIGNED; ///< unsigned byte + +const type_t BTF_INT16 = BT_INT16 | BTMT_SIGNED; ///< signed short +const type_t BTF_UINT16 = BT_INT16 | BTMT_USIGNED; ///< unsigned short + +const type_t BTF_INT32 = BT_INT32 | BTMT_SIGNED; ///< signed int +const type_t BTF_UINT32 = BT_INT32 | BTMT_USIGNED; ///< unsigned int + +const type_t BTF_INT64 = BT_INT64 | BTMT_SIGNED; ///< signed long +const type_t BTF_UINT64 = BT_INT64 | BTMT_USIGNED; ///< unsigned long + +const type_t BTF_INT128 = BT_INT128 | BTMT_SIGNED; ///< signed 128-bit value +const type_t BTF_UINT128 = BT_INT128 | BTMT_USIGNED; ///< unsigned 128-bit value + +const type_t BTF_INT = BT_INT | BTMT_UNKSIGN; ///< int, unknown signedness +const type_t BTF_UINT = BT_INT | BTMT_USIGNED; ///< unsigned int +const type_t BTF_SINT = BT_INT | BTMT_SIGNED; ///< singed int + +const type_t BTF_BOOL = BT_BOOL; ///< boolean + +const type_t BTF_FLOAT = BT_FLOAT | BTMT_FLOAT; ///< float +const type_t BTF_DOUBLE = BT_FLOAT | BTMT_DOUBLE; ///< double +const type_t BTF_LDOUBLE = BT_FLOAT | BTMT_LNGDBL; ///< long double +const type_t BTF_TBYTE = BT_FLOAT | BTMT_SPECFLT; ///< see ::BTMT_SPECFLT + +const type_t BTF_STRUCT = BT_COMPLEX | BTMT_STRUCT; ///< struct +const type_t BTF_UNION = BT_COMPLEX | BTMT_UNION; ///< union +const type_t BTF_ENUM = BT_COMPLEX | BTMT_ENUM; ///< enum +const type_t BTF_TYPEDEF = BT_COMPLEX | BTMT_TYPEDEF; ///< typedef +//@} + +//@} tf + +//------------------------------------------------------------------------ +// convenience functions: + +inline THREAD_SAFE bool is_type_const(type_t t) { return (t & BTM_CONST) != 0; } ///< See ::BTM_CONST +inline THREAD_SAFE bool is_type_volatile(type_t t) { return (t & BTM_VOLATILE) != 0; } ///< See ::BTM_VOLATILE + +inline THREAD_SAFE type_t get_base_type(type_t t) { return (t & TYPE_BASE_MASK); } ///< Get get basic type bits (::TYPE_BASE_MASK) +inline THREAD_SAFE type_t get_type_flags(type_t t) { return (t & TYPE_FLAGS_MASK); } ///< Get type flags (::TYPE_FLAGS_MASK) +inline THREAD_SAFE type_t get_full_type(type_t t) { return (t & TYPE_FULL_MASK); } ///< Get basic type bits + type flags (::TYPE_FULL_MASK) + +/// Is the type_t the last byte of type declaration? +/// (there are no additional bytes after a basic type, see ::_BT_LAST_BASIC) +inline THREAD_SAFE bool is_typeid_last(type_t t) { return(get_base_type(t) <= _BT_LAST_BASIC); } + +/// Identifies an unknown or void type with a known size (see \ref tf_unk) +inline THREAD_SAFE bool is_type_partial(type_t t) { return(get_base_type(t) <= BT_VOID) && get_type_flags(t) != 0; } + +inline THREAD_SAFE bool is_type_void(type_t t) { return(get_full_type(t) == BTF_VOID); } ///< See ::BTF_VOID +inline THREAD_SAFE bool is_type_unknown(type_t t) { return(get_full_type(t) == BT_UNKNOWN); } ///< See ::BT_UNKNOWN + +inline THREAD_SAFE bool is_type_ptr(type_t t) { return(get_base_type(t) == BT_PTR); } ///< See ::BT_PTR +inline THREAD_SAFE bool is_type_complex(type_t t) { return(get_base_type(t) == BT_COMPLEX); } ///< See ::BT_COMPLEX +inline THREAD_SAFE bool is_type_func(type_t t) { return(get_base_type(t) == BT_FUNC); } ///< See ::BT_FUNC +inline THREAD_SAFE bool is_type_array(type_t t) { return(get_base_type(t) == BT_ARRAY); } ///< See ::BT_ARRAY + +inline THREAD_SAFE bool is_type_typedef(type_t t) { return(get_full_type(t) == BTF_TYPEDEF); } ///< See ::BTF_TYPEDEF +inline THREAD_SAFE bool is_type_sue(type_t t) { return is_type_complex(t) && !is_type_typedef(t); } ///< Is the type a struct/union/enum? +inline THREAD_SAFE bool is_type_struct(type_t t) { return(get_full_type(t) == BTF_STRUCT); } ///< See ::BTF_STRUCT +inline THREAD_SAFE bool is_type_union(type_t t) { return(get_full_type(t) == BTF_UNION); } ///< See ::BTF_UNION +inline THREAD_SAFE bool is_type_struni(type_t t) { return(is_type_struct(t) || is_type_union(t)); } ///< Is the type a struct or union? +inline THREAD_SAFE bool is_type_enum(type_t t) { return(get_full_type(t) == BTF_ENUM); } ///< See ::BTF_ENUM + +inline THREAD_SAFE bool is_type_bitfld(type_t t) { return(get_base_type(t) == BT_BITFIELD); } ///< See ::BT_BITFIELD + + +/// Does the type_t specify one of the basic types in \ref tf_int? +inline THREAD_SAFE bool is_type_int(type_t bt) { bt = get_base_type(bt); return bt >= BT_INT8 && bt <= BT_INT; } + +/// Does the type specify a 128-bit value? (signed or unsigned, see \ref tf_int) +inline THREAD_SAFE bool is_type_int128(type_t t) +{ + return get_full_type(t) == (BT_INT128|BTMT_UNKSIGN) + || get_full_type(t) == (BT_INT128|BTMT_SIGNED); +} + +/// Does the type specify a 64-bit value? (signed or unsigned, see \ref tf_int) +inline THREAD_SAFE bool is_type_int64(type_t t) +{ + return get_full_type(t) == (BT_INT64|BTMT_UNKSIGN) + || get_full_type(t) == (BT_INT64|BTMT_SIGNED); +} + +/// Does the type specify a 32-bit value? (signed or unsigned, see \ref tf_int) +inline THREAD_SAFE bool is_type_int32(type_t t) +{ + return get_full_type(t) == (BT_INT32|BTMT_UNKSIGN) + || get_full_type(t) == (BT_INT32|BTMT_SIGNED); +} + +/// Does the type specify a 16-bit value? (signed or unsigned, see \ref tf_int) +inline THREAD_SAFE bool is_type_int16(type_t t) +{ + return get_full_type(t) == (BT_INT16|BTMT_UNKSIGN) + || get_full_type(t) == (BT_INT16|BTMT_SIGNED); +} + +/// Does the type specify a char value? (signed or unsigned, see \ref tf_int) +inline THREAD_SAFE bool is_type_char(type_t t) // chars are signed by default(?) +{ + return get_full_type(t) == (BT_INT8|BTMT_CHAR) + || get_full_type(t) == (BT_INT8|BTMT_SIGNED); +} + +/// Is the type a pointer, array, or function type? +inline THREAD_SAFE bool is_type_paf(type_t t) +{ + t = get_base_type(t); + return t >= BT_PTR && t <= BT_FUNC; +} + +/// Is the type a pointer or array type? +inline THREAD_SAFE bool is_type_ptr_or_array(type_t t) { t = get_base_type(t); return t == BT_PTR || t == BT_ARRAY; } +/// Is the type a floating point type? +inline THREAD_SAFE bool is_type_floating(type_t t) { return get_base_type(t) == BT_FLOAT; } // any floating type +/// Is the type an integral type (char/short/int/long/bool)? +inline THREAD_SAFE bool is_type_integral(type_t t) { return get_full_type(t) > BT_VOID && get_base_type(t) <= BT_BOOL; } +/// Is the type an extended integral type? (integral or enum) +inline THREAD_SAFE bool is_type_ext_integral(type_t t) { return is_type_integral(t) || is_type_enum(t); } +/// Is the type an arithmetic type? (floating or integral) +inline THREAD_SAFE bool is_type_arithmetic(type_t t) { return get_full_type(t) > BT_VOID && get_base_type(t) <= BT_FLOAT; } +/// Is the type an extended arithmetic type? (arithmetic or enum) +inline THREAD_SAFE bool is_type_ext_arithmetic(type_t t) { return is_type_arithmetic(t) || is_type_enum(t); } + +inline THREAD_SAFE bool is_type_uint(type_t t) { return get_full_type(t) == BTF_UINT; } ///< See ::BTF_UINT +inline THREAD_SAFE bool is_type_uchar(type_t t) { return get_full_type(t) == BTF_UCHAR; } ///< See ::BTF_UCHAR +inline THREAD_SAFE bool is_type_uint16(type_t t) { return get_full_type(t) == BTF_UINT16; } ///< See ::BTF_UINT16 +inline THREAD_SAFE bool is_type_uint32(type_t t) { return get_full_type(t) == BTF_UINT32; } ///< See ::BTF_UINT32 +inline THREAD_SAFE bool is_type_uint64(type_t t) { return get_full_type(t) == BTF_UINT64; } ///< See ::BTF_UINT64 +inline THREAD_SAFE bool is_type_uint128(type_t t) { return get_full_type(t) == BTF_UINT128; } ///< See ::BTF_UINT128 +inline THREAD_SAFE bool is_type_ldouble(type_t t) { return get_full_type(t) == BTF_LDOUBLE; } ///< See ::BTF_LDOUBLE +inline THREAD_SAFE bool is_type_double(type_t t) { return get_full_type(t) == BTF_DOUBLE; } ///< See ::BTF_DOUBLE +inline THREAD_SAFE bool is_type_float(type_t t) { return get_full_type(t) == BTF_FLOAT; } ///< See ::BTF_FLOAT +inline THREAD_SAFE bool is_type_tbyte(type_t t) { return get_full_type(t) == BTF_TBYTE; } ///< See ::BTF_FLOAT +inline THREAD_SAFE bool is_type_bool(type_t t) { return get_base_type(t) == BT_BOOL; } ///< See ::BTF_BOOL + +/*! \defgroup tattr Type attributes + \ingroup tf + The type attributes start with the type attribute header byte (::TAH_BYTE), + followed by attribute bytes +*/ +//@{ +#define TAH_BYTE 0xFE ///< type attribute header byte +#define FAH_BYTE 0xFF ///< function argument attribute header byte + +#define MAX_DECL_ALIGN 0x000F + +/// \defgroup tattr_ext Extended type attributes +//@{ +#define TAH_HASATTRS 0x0010 ///< has extended attributes +//@} + +/// \defgroup tattr_udt Type attributes for udts +//@{ +#define TAUDT_UNALIGNED 0x0040 ///< struct: unaligned struct +#define TAUDT_MSSTRUCT 0x0020 ///< struct: gcc msstruct attribute +#define TAUDT_CPPOBJ 0x0080 ///< struct: a c++ object, not simple pod type +#define TAUDT_VFTABLE 0x0100 ///< struct: is virtual function table +//@} + +/// \defgroup tattr_field Type attributes for udt fields +//@{ +#define TAFLD_BASECLASS 0x0020 ///< field: do not include but inherit from the current field +#define TAFLD_UNALIGNED 0x0040 ///< field: unaligned field +#define TAFLD_VIRTBASE 0x0080 ///< field: virtual base (not supported yet) +#define TAFLD_VFTABLE 0x0100 ///< field: ptr to virtual function table +//@} + +/// \defgroup tattr_ptr Type attributes for pointers +//@{ +#define TAPTR_PTR32 0x0020 ///< ptr: __ptr32 +#define TAPTR_PTR64 0x0040 ///< ptr: __ptr64 +#define TAPTR_RESTRICT 0x0060 ///< ptr: __restrict +#define TAPTR_SHIFTED 0x0080 ///< ptr: __shifted(parent_struct, delta) +//@} + +/// \defgroup tattr_enum Type attributes for enums +//@{ +#define TAENUM_64BIT 0x0020 ///< enum: store 64-bit values +#define TAENUM_UNSIGNED 0x0040 ///< enum: unsigned +#define TAENUM_SIGNED 0x0080 ///< enum: signed +//@} + +#define TAH_ALL 0x01F0 ///< all defined bits + +//@} tattr + + +/// The TAH byte (type attribute header byte) denotes the start of type attributes. +/// (see "tah-typeattrs" in the type bit definitions) + +inline THREAD_SAFE bool is_tah_byte(type_t t) +{ + return t == TAH_BYTE; +} + + +/// Identify an sdacl byte. +/// The first sdacl byte has the following format: 11xx000x. +/// The sdacl bytes are appended to udt fields. They indicate the start of type +/// attributes (as the tah-bytes do). The sdacl bytes are used in the udt +/// headers instead of the tah-byte. This is done for compatibility with old +/// databases, they were already using sdacl bytes in udt headers and as udt +/// field postfixes. +/// (see "sdacl-typeattrs" in the type bit definitions) + +inline THREAD_SAFE bool is_sdacl_byte(type_t t) +{ + return ((t & ~TYPE_FLAGS_MASK) ^ TYPE_MODIF_MASK) <= BT_VOID; +} + +#ifndef SWIG +/// Compare two bytevecs with '<'. +/// v1 is considered less than v2 if either: +/// - v1.size() < v2.size() +/// - there is some i such that v1[i] < v2[i] + +inline THREAD_SAFE bool operator <(const bytevec_t &v1, const bytevec_t &v2) +{ + size_t n = qmin(v1.size(), v2.size()); + for ( size_t i=0; i < n; i++ ) + { + uchar k1 = v1[i]; + uchar k2 = v2[i]; + if ( k1 < k2 ) + return true; + if ( k1 > k2 ) + return false; + } + return v1.size() < v2.size(); +} +#endif + +/// \addtogroup tattr_ext Extended type attributes +//@{ +/// Extended type attributes. +struct type_attr_t +{ + qstring key; ///< one symbol keys are reserved to be used by the kernel + ///< the ones starting with an underscore are reserved too + bytevec_t value; ///< attribute bytes + bool operator < (const type_attr_t &r) const { return key < r.key; } + bool operator >= (const type_attr_t &r) const { return !(*this < r); } +}; +DECLARE_TYPE_AS_MOVABLE(type_attr_t); + +/// this vector must be sorted by keys +typedef qvector<type_attr_t> type_attrs_t; + +typedef int type_sign_t; ///< type signedness +const type_sign_t + no_sign = 0, ///< no sign, or unknown + type_signed = 1, ///< signed type + type_unsigned = 2; ///< unsigned type +//@} + +//--------------------------------------------------------------------------- +idaman bool ida_export append_argloc(qtype *out, const argloc_t &vloc); ///< Serialize argument location +idaman bool ida_export extract_argloc(argloc_t *vloc, const type_t **ptype, bool is_retval); ///< Deserialize argument location + +idaman const type_t *ida_export resolve_typedef(const til_t *til, const type_t *type); + +// low level functions to be used in predicate_t::should_display() +// in other places please use tinfo_t +inline bool is_restype_void(const til_t *til, const type_t *type) +{ + type = resolve_typedef(til, type); + return type != NULL && is_type_void(*type); +} + +inline bool is_restype_enum(const til_t *til, const type_t *type) +{ + type = resolve_typedef(til, type); + return type != NULL && is_type_enum(*type); +} + +inline bool is_restype_struni(const til_t *til, const type_t *type) +{ + type = resolve_typedef(til, type); + return type != NULL && is_type_struni(*type); +} + +inline bool is_restype_struct(const til_t *til, const type_t *type) +{ + type = resolve_typedef(til, type); + return type != NULL && is_type_struct(*type); +} + +// Get a base type for the specified size. +// This function prefers to return integer types +// \param size size in bytes; should be 1,2,4,8,16 or sizeof(floating point) +// \return BT_INT.. or BT_FLOAT... or BT_UNK + +idaman type_t ida_export get_scalar_bt(int size); + + +//------------------------------------------------------------------------ +/// Type Information Library +//------------------------------------------------------------------------ +struct til_t +{ + char *name = nullptr; ///< short file name (without path and extension) + char *desc = nullptr; ///< human readable til description + int nbases = 0; ///< number of base tils + til_t **base = nullptr; ///< tils that our til is based on + uint32 flags = 0; ///< \ref TIL_ +/// \defgroup TIL_ Type info library property bits +/// used by til_t::flags +//@{ +#define TIL_ZIP 0x0001 ///< pack buckets using zip +#define TIL_MAC 0x0002 ///< til has macro table +#define TIL_ESI 0x0004 ///< extended sizeof info (short, long, longlong) +#define TIL_UNI 0x0008 ///< universal til for any compiler +#define TIL_ORD 0x0010 ///< type ordinal numbers are present +#define TIL_ALI 0x0020 ///< type aliases are present (this bit is used only on the disk) +#define TIL_MOD 0x0040 ///< til has been modified, should be saved +#define TIL_STM 0x0080 ///< til has extra streams +#define TIL_SLD 0x0100 ///< sizeof(long double) +//@} + /// Has the til been modified? (#TIL_MOD) + inline bool is_dirty(void) const { return (flags & TIL_MOD) != 0; } + /// Mark the til as modified (#TIL_MOD) + inline void set_dirty(void) { flags |= TIL_MOD; } + compiler_info_t cc; ///< information about the target compiler + til_bucket_t *syms = nullptr; ///< symbols + til_bucket_t *types = nullptr; ///< types + til_bucket_t *macros = nullptr; ///< macros + int nrefs = 0; ///< number of references to the til + int nstreams = 0; ///< number of extra streams + til_stream_t **streams = nullptr; ///< symbol stream storage +}; + + +/// Initialize a til + +idaman til_t *ida_export new_til(const char *name, const char *desc); + + +/// Add multiple base tils. +/// \param[out] errbuf error message +/// \param ti target til +/// \param tildir directory where specified tils can be found. +/// NULL means all default til subdirectories. +/// \param bases comma separated list of til names +/// \param gen_events generate corresponding IDB events +/// \return one of \ref TIL_ADD_ + +idaman int ida_export add_base_tils(qstring *errbuf, til_t *ti, const char *tildir, const char *bases, bool gen_events); + +/// \defgroup TIL_ADD_ Add TIL result codes +/// returned by add_base_tils() +//@{ +#define TIL_ADD_FAILED 0 ///< see errbuf +#define TIL_ADD_OK 1 ///< some tils were added +#define TIL_ADD_ALREADY 2 ///< the base til was already added +//@} + + +/// Load til from a file. +/// Failure to load base tils are reported into 'errbuf'. They do not prevent +/// loading of the main til. +/// \param name filename of the til. If it's an absolute path, tildir is ignored. +/// - NB: the file extension is forced to .til +/// \param[out] errbuf error message +/// \param tildir directory where to load the til from. +/// NULL means default til subdirectories. +/// \return pointer to resulting til, NULL if failed and error message is in errbuf + +idaman til_t *ida_export load_til(const char *name, qstring *errbuf, const char *tildir=NULL); + + +/// Sort til (use after modifying it). +/// \return false if no memory or bad parameter + +idaman bool ida_export sort_til(til_t *ti); + + +/// Collect garbage in til. +/// Must be called before storing the til. +/// \return true if any memory was freed + +idaman bool ida_export compact_til(til_t *ti); + + +/// Store til to a file. +/// If the til contains garbage, it will be collected before storing the til. +/// Your plugin should call compact_til() before calling store_til(). +/// \param ti type library to store +/// \param tildir directory where to store the til. NULL means current directory. +/// \param name filename of the til. If it's an absolute path, tildir is ignored. +/// - NB: the file extension is forced to .til +/// \return success + +idaman bool ida_export store_til(til_t *ti, const char *tildir, const char *name); + + +/// Free memory allocated by til + +idaman void ida_export free_til(til_t *ti); + + +/// Get human-readable til description + +idaman til_t *ida_export load_til_header(const char *tildir, const char *name, qstring *errbuf); + + +//------------------------------------------------------------------------ +/// \defgroup CM_ CM +/// Calling convention & Model +//@{ + +/// \defgroup CM_ptr Default pointer size +//@{ +const cm_t CM_MASK = 0x03; +const cm_t CM_UNKNOWN = 0x00; ///< unknown +const cm_t CM_N8_F16 = 0x01; ///< if sizeof(int)<=2: near 1 byte, far 2 bytes +const cm_t CM_N64 = 0x01; ///< if sizeof(int)>2: near 8 bytes, far 8 bytes +const cm_t CM_N16_F32 = 0x02; ///< near 2 bytes, far 4 bytes +const cm_t CM_N32_F48 = 0x03; ///< near 4 bytes, far 6 bytes +//@} +/// \defgroup CM_M_ Model +//@{ +const cm_t CM_M_MASK = 0x0C; +const cm_t CM_M_NN = 0x00; ///< small: code=near, data=near (or unknown if CM_UNKNOWN) +const cm_t CM_M_FF = 0x04; ///< large: code=far, data=far +const cm_t CM_M_NF = 0x08; ///< compact: code=near, data=far +const cm_t CM_M_FN = 0x0C; ///< medium: code=far, data=near + +/// Does the given model specify far code?. +inline THREAD_SAFE bool is_code_far(cm_t cm) { return((cm & 4) != 0); } +/// Does the given model specify far data?. +inline THREAD_SAFE bool is_data_far(cm_t cm) { return((cm &= CM_M_MASK) && cm != CM_M_FN); } +//@} + +/// \defgroup CM_CC_ Calling convention +//@{ +const cm_t CM_CC_MASK = 0xF0; +const cm_t CM_CC_INVALID = 0x00; ///< this value is invalid +const cm_t CM_CC_UNKNOWN = 0x10; ///< unknown calling convention +const cm_t CM_CC_VOIDARG = 0x20; ///< function without arguments + ///< if has other cc and argnum == 0, + ///< represent as f() - unknown list +const cm_t CM_CC_CDECL = 0x30; ///< stack +const cm_t CM_CC_ELLIPSIS = 0x40; ///< cdecl + ellipsis +const cm_t CM_CC_STDCALL = 0x50; ///< stack, purged +const cm_t CM_CC_PASCAL = 0x60; ///< stack, purged, reverse order of args +const cm_t CM_CC_FASTCALL = 0x70; ///< stack, purged (x86), first args are in regs (compiler-dependent) +const cm_t CM_CC_THISCALL = 0x80; ///< stack, purged (x86), first arg is in reg (compiler-dependent) +const cm_t CM_CC_MANUAL = 0x90; ///< special case for compiler specific (not used) +const cm_t CM_CC_SPOILED = 0xA0; ///< This is NOT a cc! Mark of __spoil record + ///< the low nibble is count and after n {spoilreg_t} + ///< present real cm_t byte. if n == BFA_FUNC_MARKER, + ///< the next byte is the function attribute byte. +const cm_t CM_CC_RESERVE4 = 0xB0; +const cm_t CM_CC_RESERVE3 = 0xC0; +const cm_t CM_CC_SPECIALE = 0xD0; ///< ::CM_CC_SPECIAL with ellipsis +const cm_t CM_CC_SPECIALP = 0xE0; ///< Equal to ::CM_CC_SPECIAL, but with purged stack +const cm_t CM_CC_SPECIAL = 0xF0; ///< usercall: locations of all arguments + ///< and the return value are explicitly specified +//@} CM_CC_ + +//@} CM_ + +/*! \defgroup BFA_ Function attribute byte + \ingroup tf_func + Zero attribute byte is forbidden. +*/ +//@{ +const type_t BFA_NORET = 0x01; ///< __noreturn +const type_t BFA_PURE = 0x02; ///< __pure +const type_t BFA_HIGH = 0x04; ///< high level prototype (with possibly hidden args) +const type_t BFA_STATIC = 0x08; ///< static +const type_t BFA_VIRTUAL = 0x10; ///< virtual + +const cm_t BFA_FUNC_MARKER = 0x0F; ///< This is NOT a cc! (used internally as a marker) +const type_t BFA_FUNC_EXT_FORMAT = 0x80; ///< This is NOT a real attribute (used internally as marker for extended format) +//@} + +#ifndef SWIG +/// Helper to declare common ::argloc_t related functions +#define ARGLOC_HELPER_DEFINITIONS(decl) \ +decl void ida_export copy_argloc(argloc_t *dst, const argloc_t *src); \ +decl void ida_export cleanup_argloc(argloc_t *vloc);\ +decl int ida_export compare_arglocs(const argloc_t &a, const argloc_t &b); +#else +#define ARGLOC_HELPER_DEFINITIONS(decl) +#endif // SWIG +ARGLOC_HELPER_DEFINITIONS(idaman) + +/// \defgroup argloc Argument locations +/// \ingroup CM_ +//@{ + +/// Specifies the location type of a function argument - see \ref ALOC_ +typedef int argloc_type_t; +/// \defgroup ALOC_ Argument location types +//@{ +const argloc_type_t + ALOC_NONE = 0, ///< none + ALOC_STACK = 1, ///< stack offset + ALOC_DIST = 2, ///< distributed (scattered) + ALOC_REG1 = 3, ///< one register (and offset within it) + ALOC_REG2 = 4, ///< register pair + ALOC_RREL = 5, ///< register relative + ALOC_STATIC = 6, ///< global address + ALOC_CUSTOM = 7; ///< custom argloc (7 or higher) +//@} + +/// Register-relative argument location +struct rrel_t +{ + sval_t off; ///< displacement from the address pointed by the register + int reg; ///< register index (into \varmem{ph,processor_t,reg_names}) +}; + +class scattered_aloc_t; + +/// Description of a custom argloc. Custom arglocs can be added by plugins in order +/// to describe the locations unsupported by the ida kernel. +struct custloc_desc_t +{ + size_t cbsize; ///< size of this structure + const char *name; ///< name of the custom argloc type. must be unique + + /// Copy src into empty_dst + void (idaapi *copy)(argloc_t *empty_dst, const argloc_t &src); + + /// Clear contents of loc before it is modified (may be NULL) + void (idaapi *cleanup)(argloc_t *loc); + + /// May be NULL + bool (idaapi *verify)( + const argloc_t &loc, + int size, + const rangeset_t *gaps, + bool part_of_scattered); + + /// Lexical comparison of two arglocs + int (idaapi *compare)(const argloc_t &a, const argloc_t &b); + + /// Get textual description of the location (not the value at the location!) + size_t (idaapi *print)( + char *buf, + size_t bufsize, + const argloc_t &loc, + asize_t size, + int praloc_flags); // PRALOC_... + + /// Dereference the struct/union pointed by 'strloc': take member at offset 'off' + /// (or use the field name), improve member 'tif' if necessary + bool (idaapi *deref_field)( + argloc_t *out, + tinfo_t *tif, + const argloc_t &strloc, + const tinfo_t &struct_tif, + asize_t off, + const qstring &name); + + /// Dereference the array pointed by 'arrloc': take member number 'n' + /// (element size is 'elsize'), improve member 'tif' if necessary + bool (idaapi *deref_array)( + argloc_t *out, + tinfo_t *tif, + const argloc_t &arrloc, + const tinfo_t &array_tif, + asize_t n, + asize_t elsize); + + /// Dereference the pointer at 'loc': retrieve location of the pointed object, + /// improve 'tif' of the pointed object if necessary + bool (idaapi *deref_ptr)( + argloc_t *out, + tinfo_t *tif, + const argloc_t &ptrloc); + + /// Read the pointer at 'loc': retrieve value of a simple object. + /// the object value must fit value_u. + bool (idaapi *read_value)( + value_u *value, + const argloc_t &loc, + int size, + const tinfo_t &tif); + + /// Update value at 'loc'. if idcv is VT_LONG/VT_INT64/VT_FLOAT, the value + /// in native format is copied to 'scalar_value' for your convenience. otherwise + /// please use 'idcv' and not 'scalar_value'. + bool (idaapi *write_value)( + const argloc_t &loc, + const idc_value_t &idcv, + const value_u &scalar_value, + int size, + qstring *errbuf); + + /// Calc max natural string length at 'loc' in the debugged process memory + asize_t (idaapi *calc_string_length)( + const argloc_t &loc, + const tinfo_t &string_tif); + + /// Retrieve string at 'loc' from the debugged process memory, + /// returns quoted string value + bool (idaapi *get_string)( + qstring *out, + tinfo_t *elem_tif, + const argloc_t &loc, + const tinfo_t &string_tif, + size_t len); + + /// Retrieve size of array at 'loc' (number of elements) + asize_t (idaapi *guess_array_size)( + const argloc_t &loc, + const tinfo_t &array_tif); + + /// Retrieve type of the object at 'loc' + bool (idaapi *get_tinfo)( + tinfo_t *out, + const argloc_t &loc); + + /// Calculate the number of children for the given location. + /// (arrays, structs, ptrs may have children and therefore be expanded) + int (idaapi *calc_number_of_children)(const argloc_t &loc, const tinfo_t &tif); + + /// Get string containing a printable representation of the pointer at 'loc'. + /// Returns the number of characters printed. + /// May be NULL. + size_t (idaapi *print_ptr_value)( + char *buf, + size_t bufsize, + bool *is_valid_ptr, + const argloc_t &loc, + const tinfo_t &tif); +}; + + +/// Save a custom argloc +idaman int ida_export install_custom_argloc(const custloc_desc_t *custloc); +/// Delete the custom argloc at the given index +idaman bool ida_export remove_custom_argloc(int idx); +/// Retrieve the custom argloc at the given index +idaman const custloc_desc_t *ida_export retrieve_custom_argloc(int idx); + +/// Describes an argument location. +/// A typical argument is stored in one location, either a register or a stack slot. \n +/// However, some arguments can be stored in multiple locations, for example in a pair \n +/// of registers. In some really complex cases an argument can be located in multiple \n +/// registers and some stack slots. This class can describe all these cases. +class argloc_t // #argloc +{ +public: + typedef size_t biggest_t; + +private: + argloc_type_t type; + union + { + sval_t sval; // ::ALOC_STACK, ::ALOC_STATIC + uint32 reginfo; // ::ALOC_REG1, ::ALOC_REG2 + rrel_t *rrel; // ::ALOC_RREL + scattered_aloc_t *dist; // ::ALOC_DIST + void *custom; // ::ALOC_CUSTOM + biggest_t biggest; // to facilitate manipulation of this union + }; + ARGLOC_HELPER_DEFINITIONS(friend) + +public: + argloc_t(void) : type(ALOC_NONE), biggest(0) {} ///< Constructor + argloc_t(const argloc_t &r) : type(ALOC_NONE) { copy_argloc(this, &r); } ///< Constructor + ~argloc_t(void) { cleanup_argloc(this); } ///< Destructor + argloc_t &operator=(const argloc_t &r) { copy_argloc(this, &r); return *this; } ///< Constructor + DEFINE_MEMORY_ALLOCATION_FUNCS() + + /// Assign this == r and r == this + void swap(argloc_t &r) + { + biggest_t tmp = biggest; biggest = r.biggest; r.biggest = tmp; + argloc_type_t t = type; type = r.type; r.type = t; + } + + const char *dstr(void) const; + + argloc_type_t atype(void) const { return type; } ///< Get type (\ref ALOC_) + bool is_reg1(void) const { return type == ALOC_REG1; } ///< See ::ALOC_REG1 + bool is_reg2(void) const { return type == ALOC_REG2; } ///< See ::ALOC_REG2 + bool is_reg(void) const { return type == ALOC_REG1 || type == ALOC_REG2; } ///< is_reg1() || is_reg2() + bool is_rrel(void) const { return type == ALOC_RREL; } ///< See ::ALOC_RREL + bool is_ea(void) const { return type == ALOC_STATIC; } ///< See ::ALOC_STATIC + bool is_stkoff(void) const { return type == ALOC_STACK; } ///< See ::ALOC_STACK + bool is_scattered(void) const { return type == ALOC_DIST; } ///< See ::ALOC_DIST + inline bool has_reg() const; ///< TRUE if argloc has a register part + inline bool has_stkoff() const; ///< TRUE if argloc has a stack part + inline bool is_mixed_scattered() const; ///< mixed scattered: consists of register and stack parts + bool is_fragmented(void) const { return type == ALOC_DIST || type == ALOC_REG2; } ///< is_scattered() || is_reg2() + bool is_custom(void) const { return type >= ALOC_CUSTOM; } ///< See ::ALOC_CUSTOM + bool is_badloc(void) const { return type == ALOC_NONE; } ///< See ::ALOC_NONE + + /// Get the register info. + /// Use when atype() == ::ALOC_REG1 or ::ALOC_REG2 + int reg1(void) const { return uint16(reginfo); } + + /// Get offset from the beginning of the register in bytes. + /// Use when atype() == ::ALOC_REG1 + int regoff(void) const { return uint16(reginfo >> 16); } + + /// Get info for the second register. + /// Use when atype() == ::ALOC_REG2 + int reg2(void) const { return uint16(reginfo >> 16); } + + /// Get all register info. + /// Use when atype() == ::ALOC_REG1 or ::ALOC_REG2 + uint32 get_reginfo(void) const { return reginfo; } + + /// Get the stack offset. + /// Use if atype() == ::ALOC_STACK + sval_t stkoff(void) const { return sval; } + + /// Get the global address. + /// Use when atype() == ::ALOC_STATIC + ea_t get_ea(void) const { return sval; } + + /// Get scattered argument info. + /// Use when atype() == ::ALOC_DIST + scattered_aloc_t &scattered(void) { return *dist; } + const scattered_aloc_t &scattered(void) const { return *dist; } ///< copydoc scattered() + + /// Get register-relative info. + /// Use when atype() == ::ALOC_RREL + rrel_t &get_rrel(void) { return *rrel; } + const rrel_t &get_rrel(void) const { return *rrel; } ///< copydoc get_rrel() + + /// Get custom argloc info. + /// Use if atype() == ::ALOC_CUSTOM + void *get_custom(void) const { return custom; } + + /// Get largest element in internal union + biggest_t get_biggest(void) const { return biggest; } + + // be careful with these functions, they do not cleanup! + void _set_badloc(void) { type = ALOC_NONE; } ///< Use set_badloc() + void _set_reg1(int reg, int off=0) { type = ALOC_REG1; reginfo = reg | (off << 16); } ///< Use set_reg1() + void _set_reg2(int _reg1, int _reg2) { type = ALOC_REG2; reginfo = _reg1 | (_reg2 << 16); } ///< Use set_reg2() + void _set_stkoff(sval_t off) { type = ALOC_STACK; sval = off; } ///< Use set_stkoff() + void _set_ea(ea_t _ea) { type = ALOC_STATIC; sval = _ea; } ///< Use set_ea + /// Use consume_rrel() + bool _consume_rrel(rrel_t *p) //lint -sem(argloc_t::_consume_rrel, custodial(1)) + { + if ( p == NULL ) + return false; + type = ALOC_RREL; + rrel = p; + return true; + } + /// Use consume_scattered() + bool _consume_scattered(scattered_aloc_t *p) + { + if ( p == NULL ) + return false; + type = ALOC_DIST; + dist = p; + return true; + } + + /// Set custom argument location (careful - this function does not clean up!) + void _set_custom(argloc_type_t ct, void *pdata) { type = ct; custom = pdata; } + + /// Set biggest element in internal union (careful - this function does not clean up!) + void _set_biggest(argloc_type_t ct, biggest_t data) { type = ct; biggest = data; } + + /// Set register location + void set_reg1(int reg, int off=0) { cleanup_argloc(this); _set_reg1(reg, off); } + + /// Set secondary register location + void set_reg2(int _reg1, int _reg2) { cleanup_argloc(this); _set_reg2(_reg1, _reg2); } + + /// Set stack offset location + void set_stkoff(sval_t off) { cleanup_argloc(this); _set_stkoff(off); } + + /// Set static ea location + void set_ea(ea_t _ea) { cleanup_argloc(this); _set_ea(_ea); } + + /// Set register-relative location - can't be NULL + void consume_rrel(rrel_t *p) { cleanup_argloc(this); _consume_rrel(p); } + + /// Set distributed argument location + void consume_scattered(scattered_aloc_t *p) { cleanup_argloc(this); _consume_scattered(p); } + + /// Set to invalid location + void set_badloc(void) { cleanup_argloc(this); } + + /// Calculate offset that can be used to compare 2 similar arglocs + sval_t calc_offset(void) const + { + switch ( type ) + { + default: + case ALOC_NONE: + case ALOC_DIST: + case ALOC_REG2: + return -1; + case ALOC_RREL: + return rrel->off; + case ALOC_STACK: + case ALOC_STATIC: + return sval; + case ALOC_REG1: + return reg1(); + } + } + + /// Move the location to point 'delta' bytes further + bool advance(int delta) + { + switch ( type ) + { + case ALOC_REG1: + _set_reg1(reg1()+delta, regoff()); + break; + case ALOC_STACK: + case ALOC_STATIC: + sval += delta; + break; + case ALOC_RREL: + rrel->off += delta; + break; + default: + return false; + } + return true; + } + + /// Set register offset to justify it to the upper part of _SLOTSIZE + void justify_reg_high(size_t size, size_t _slotsize) + { + if ( is_reg1() ) + _set_reg1(reg1(), size < _slotsize ? _slotsize - size : 0); + } + + /// Set stack offset to right-justify it in _SLOTSIZE + void justify_stkoff_right(size_t size, size_t _slotsize) + { + if ( is_stkoff() ) + { + sval_t off = align_down(stkoff(), _slotsize); + if ( size < _slotsize ) + off += _slotsize - size; + _set_stkoff(off); + } + } + + DECLARE_COMPARISONS(argloc_t) + { + return compare_arglocs(*this, r); + } +}; +DECLARE_TYPE_AS_MOVABLE(argloc_t); +typedef qvector<argloc_t> arglocs_t; ///< vector of argument locations + +/// Subsection of an argument location +struct argpart_t : public argloc_t +{ + ushort off; ///< offset from the beginning of the argument + ushort size; ///< the number of bytes + DEFINE_MEMORY_ALLOCATION_FUNCS() + argpart_t(const argloc_t &a) : argloc_t(a), off(0xFFFF), size(0) {} ///< Constructor + argpart_t(void) : off(0xFFFF), size(0) {} ///< Constructor + argpart_t ©_from(const argloc_t &a) { *(argloc_t*)this = a; return *this; } + + /// Does this argpart have a valid offset? + bool bad_offset(void) const { return off == 0xFFFF; } + + /// Does this argpart have a valid size? + bool bad_size(void) const { return size == 0; } + + /// Compare two argparts, based on their offset + bool operator < (const argpart_t &r) const { return off < r.off; } + + /// Assign this = r and r = this + void swap(argpart_t &r) + { + argloc_t::swap(r); + qswap(off, r.off); + qswap(size, r.size); + } +}; +DECLARE_TYPE_AS_MOVABLE(argpart_t); +typedef qvector<argpart_t> argpartvec_t; + +/// Used to manage arguments that are described by multiple locations (also see ::ALOC_DIST) +class scattered_aloc_t : public argpartvec_t +{ +public: + DEFINE_MEMORY_ALLOCATION_FUNCS() +}; +DECLARE_TYPE_AS_MOVABLE(scattered_aloc_t); + + +/// Verify argloc_t. +/// \param size total size of the variable +/// \param gaps if not NULL, specifies gaps in structure definition. +/// these gaps should not map to any argloc, but everything else must be covered +/// \return 0 if ok, otherwise an interr code. + +idaman int ida_export verify_argloc(const argloc_t &vloc, int size, const rangeset_t *gaps); + + +/// Verify and optimize scattered argloc into simple form. +/// All new arglocs must be processed by this function. +/// \retval true success +/// \retval false the input argloc was illegal + +idaman bool ida_export optimize_argloc(argloc_t *vloc, int size, const rangeset_t *gaps); + + +/// Convert an argloc to human readable form + +idaman size_t ida_export print_argloc( + char *buf, + size_t bufsize, + const argloc_t &vloc, + int size=0, + int vflags=0); +#define PRALOC_VERIFY 0x01 ///< interr if illegal argloc +#define PRALOC_STKOFF 0x02 ///< print stack offsets + + +/// Visit all argument locations. The callback will not receive ::ALOC_DIST/::ALOC_REG2 types, +/// they will be converted into smaller argloc types (::ALOC_REG1 or other) +struct aloc_visitor_t +{ + virtual int idaapi visit_location(argloc_t &v, int off, int size) = 0; + virtual ~aloc_visitor_t() {} +}; + +/// Compress larger argloc types and initiate the aloc visitor +idaman int ida_export for_all_arglocs(aloc_visitor_t &vv, argloc_t &vloc, int size, int off=0); + +/// Same as ::aloc_visitor_t, but may not modify the argloc +struct const_aloc_visitor_t +{ + virtual int idaapi visit_location(const argloc_t &v, int off, int size) = 0; + virtual ~const_aloc_visitor_t() {} +}; + +/// See for_all_arglocs() +inline int idaapi for_all_const_arglocs(const_aloc_visitor_t &vv, const argloc_t &vloc, int size, int off=0) +{ + return for_all_arglocs(*(aloc_visitor_t*)(&vv), + CONST_CAST(argloc_t&)(vloc), + size, + off); +} + +//-------------------------------------------------------------------------- +/// \defgroup C_PC_ Standard C-language models for x86 +/// \ingroup CM_ +//@{ +const cm_t C_PC_TINY = (CM_N16_F32 | CM_M_NN); +const cm_t C_PC_SMALL = (CM_N16_F32 | CM_M_NN); +const cm_t C_PC_COMPACT = (CM_N16_F32 | CM_M_NF); +const cm_t C_PC_MEDIUM = (CM_N16_F32 | CM_M_FN); +const cm_t C_PC_LARGE = (CM_N16_F32 | CM_M_FF); +const cm_t C_PC_HUGE = (CM_N16_F32 | CM_M_FF); +const cm_t C_PC_FLAT = (CM_N32_F48 | CM_M_NN); +//@} + + +/// Get the calling convention + +inline THREAD_SAFE cm_t get_cc(cm_t cm) { return(cm & CM_CC_MASK); } + + +/// Does the calling convention specify argument locations explicitly? + +inline THREAD_SAFE bool is_user_cc(cm_t cm) +{ + cm_t cc = get_cc(cm); + return cc >= CM_CC_SPECIALE; +} + + +/// Does the calling convention use ellipsis? + +inline THREAD_SAFE bool is_vararg_cc(cm_t cm) +{ + cm_t cc = get_cc(cm); + return cc == CM_CC_ELLIPSIS || cc == CM_CC_SPECIALE; +} + + +/// Does the calling convention clean the stack arguments upon return?. +/// \note this function is valid only for x86 code + +inline THREAD_SAFE bool is_purging_cc(cm_t cm) +{ + cm_t cc = get_cc(cm); + return cc == CM_CC_STDCALL || cc == CM_CC_PASCAL || cc == CM_CC_SPECIALP || cc == CM_CC_FASTCALL || cc == CM_CC_THISCALL; +} + +//-------------------------------------------------------------------------- +/// Function argument passing: how GP & FP registers cooperate with each other +enum argreg_policy_t +{ + ARGREGS_POLICY_UNDEFINED, + ARGREGS_GP_ONLY, ///< GP registers used for all arguments + ARGREGS_INDEPENDENT, ///< FP/GP registers used separately (like gcc64) + ARGREGS_BY_SLOTS, ///< fixed FP/GP register per each slot (like vc64) + ARGREGS_FP_CONSUME_GP, ///< FP register also consumes one or more GP regs but not vice versa (aix ppc ABI) + ARGREGS_MIPS_O32, ///< MIPS ABI o32 +}; + +//@} argloc + +class callregs_t; + +/// Register allocation calling convention. +/// (allocation policy, arrays of GP and FP registers) +class callregs_t +{ + bool set_inds(int *p_ind1, int *p_ind2, int ind) const + { + if ( ind == -1 ) + return false; + *p_ind1 = ind; + *p_ind2 = by_slots() ? ind : -1; + return true; + } + + // copy -1-terminated array to a vector + static void set_regarray(intvec_t *regvec, const int *regarray) + { + regvec->clear(); + if ( regarray != NULL ) + while ( *regarray != -1 ) + regvec->push_back(*regarray++); + } + void calc_nregs() + { + nregs = gpregs.size(); + if ( policy == ARGREGS_INDEPENDENT || policy == ARGREGS_FP_CONSUME_GP ) + nregs += int(fpregs.size()); + } + +public: + argreg_policy_t policy; ///< argument policy + int nregs; ///< max number of registers that can be used in a call + intvec_t gpregs; ///< array of gp registers + intvec_t fpregs; ///< array of fp registers + + /// Constructor + callregs_t(): policy(ARGREGS_POLICY_UNDEFINED), nregs(0) {} + + /// Constructor - initialize with the given request (see init_regs()) + callregs_t(cm_t cc): policy(ARGREGS_POLICY_UNDEFINED), nregs(0) + { + init_regs(cc); + } + + /// Init policy & registers for given CC. + void init_regs(cm_t cc) + { + processor_t::get_cc_regs(this, get_cc(cc)); + } + + // policy-specific options + bool by_slots() const { return policy == ARGREGS_BY_SLOTS; } + + /// Init policy & registers (arrays are -1-terminated) + void set(argreg_policy_t _policy, const int *gprs, const int *fprs) + { + policy = _policy; + set_regarray(&gpregs, gprs); + set_regarray(&fpregs, fprs); + calc_nregs(); + } + + /// Set policy and registers to invalid values + void reset() + { + set(ARGREGS_POLICY_UNDEFINED, NULL, NULL); + } + + /// Get max number of registers may be used in a function call. + static int regcount(cm_t cc) + { + callregs_t vr(cc); return vr.nregs; + } + + // return index of register, -1 else + static int findreg(const intvec_t ®s, int r) + { + intvec_t::const_iterator p = regs.find(r); + return p == regs.end() ? -1 : (p-regs.begin()); + } + + /// Get register indexes within GP/FP arrays. + /// (-1 -> is not present in the corresponding array) + bool reginds(int *gp_ind, int *fp_ind, int r) const + { + return findregs(gp_ind, fp_ind, r, gpregs, fpregs); + } + +protected: + /// Search for register r in gprs and fprs. + /// If found, fill gp_ind and fp_ind based on #policy + bool findregs(int *gp_ind, int *fp_ind, int r, const intvec_t &gprs, const intvec_t &fprs) const + { + *gp_ind = *fp_ind = -1; + return set_inds(gp_ind, fp_ind, findreg(gprs, r)) + || set_inds(fp_ind, gp_ind, findreg(fprs, r)); + } +}; + +//-------------------------------------------------------------------------- +/// \defgroup CC +/// Target compiler +//@{ + +/// \defgroup COMP_ Compiler IDs +//@{ +const comp_t COMP_MASK = 0x0F; +const comp_t COMP_UNK = 0x00; ///< Unknown +const comp_t COMP_MS = 0x01; ///< Visual C++ +const comp_t COMP_BC = 0x02; ///< Borland C++ +const comp_t COMP_WATCOM = 0x03; ///< Watcom C++ +// const comp_t COMP_ = 0x04 +// const comp_t COMP_ = 0x05 +const comp_t COMP_GNU = 0x06; ///< GNU C++ +const comp_t COMP_VISAGE = 0x07; ///< Visual Age C++ +const comp_t COMP_BP = 0x08; ///< Delphi +//---- +const comp_t COMP_UNSURE = 0x80; ///< uncertain compiler id +//@} + + +/// \defgroup CC_funcs Functions: work with compiler IDs +//@{ + +/// Get compiler bits + +inline THREAD_SAFE comp_t get_comp(comp_t comp) { return(comp & COMP_MASK); } + + +/// Get full compiler name + +idaman const char *ida_export get_compiler_name(comp_t id); + + +/// Get abbreviated compiler name + +idaman const char *ida_export get_compiler_abbr(comp_t id); + +/// Collection of compiler descriptions +typedef qvector<comp_t> compvec_t; + + +/// Get names of all built-in compilers + +idaman void ida_export get_compilers(compvec_t *ids, qstrvec_t *names, qstrvec_t *abbrs); + + +/// See ::COMP_UNSURE + +inline THREAD_SAFE comp_t is_comp_unsure(comp_t comp) { return (comp & COMP_UNSURE); } + + +/// Get compiler specified by \varmem{inf,idainfo,cc} + +inline comp_t default_compiler(void) { return get_comp(inf_get_cc_id()); } + + +/// Is the target compiler ::COMP_GNU? + +inline bool is_gcc(void) { return default_compiler() == COMP_GNU; } + + +/// Is the target compiler 32 bit gcc? + +inline bool is_gcc32(void) { return is_gcc() && !inf_is_64bit(); } + + +/// Is the target compiler 64 bit gcc? + +inline bool is_gcc64(void) { return is_gcc() && inf_is_64bit(); } + + +/// Should use the struct/union layout as done by gcc? + +inline bool gcc_layout(void) { return is_gcc() || (inf_get_abibits() & ABI_GCC_LAYOUT) != 0; } + + +/// Change current compiler. +/// \param cc compiler to switch to +/// \param flags \ref SETCOMP_ +/// \param abiname ABI name +/// \return success + +idaman bool ida_export set_compiler( + const compiler_info_t &cc, + int flags, + const char *abiname=NULL); + +/// \defgroup SETCOMP_ Set compiler flags +//@{ +#define SETCOMP_OVERRIDE 0x0001 ///< may override old compiler info +#define SETCOMP_ONLY_ID 0x0002 ///< cc has only 'id' field + ///< the rest will be set to defaults + ///< corresponding to the program bitness +#define SETCOMP_ONLY_ABI 0x0004 ///< ignore cc field complete, use only abiname +#define SETCOMP_BY_USER 0x0008 ///< invoked by user, cannot be replaced by module/loader +//@} + + +/// Set the compiler id (see \ref COMP_) + +inline bool idaapi set_compiler_id(comp_t id, const char *abiname=NULL) +{ + compiler_info_t cc; + cc.id = id; + return set_compiler(cc, SETCOMP_ONLY_ID, abiname); +} + +/// Set abi name (see \ref COMP_) + +inline bool idaapi set_abi_name(const char *abiname, bool user_level = false) +{ + compiler_info_t cc; + cc.id = 0; + int flags = SETCOMP_ONLY_ABI | (user_level ? SETCOMP_BY_USER : 0); + return set_compiler(cc, flags, abiname); +} + +/// Get ABI name. +/// \return length of the name (>=0) + +idaman ssize_t ida_export get_abi_name(qstring *out); + + +/// Add/remove/check ABI option +/// General form of full abi name: abiname-opt1-opt2-... or -opt1-opt2-... +/// \param abi_opts - ABI options to add/remove in form opt1-opt2-... +/// \param user_level - initiated by user if TRUE (==SETCOMP_BY_USER) +/// \return success +idaman bool ida_export append_abi_opts(const char *abi_opts, bool user_level = false); +idaman bool ida_export remove_abi_opts(const char *abi_opts, bool user_level = false); + +/// \param compstr - compiler description in form <abbr>:<abiname> +/// \param user_level - initiated by user if TRUE +/// \return success +idaman bool ida_export set_compiler_string(const char *compstr, bool user_level); + + +//------------------------------------------------------------------------- +inline bool is_golang_abi(void) +{ + if ( !is_gcc() ) + return false; // "golang" abi can be defined only for GCC + qstring abiname; + get_abi_name(&abiname); + return abiname == "golang"; +} + +//------------------------------------------------------------------------- +inline bool use_golang_abi(cm_t cm) +{ + cm_t cc = get_cc(cm); + return (cc == CM_CC_FASTCALL || cc == CM_CC_VOIDARG) && is_golang_abi(); +} + +//@} CC_funcs +//@} CC + +//-------------------------------------------------------------------------- +const size_t BADSIZE = size_t(-1); ///< bad type size +#define MAX_FUNC_ARGS 256 ///< max number of function arguments + +//-------------------------------------------------------------------------- +/// abstractness of declaration (see h2ti()) +enum abs_t { abs_unk, abs_no, abs_yes }; +enum sclass_t ///< storage class +{ + sc_unk, ///< unknown + sc_type, ///< typedef + sc_ext, ///< extern + sc_stat, ///< static + sc_reg, ///< register + sc_auto, ///< auto + sc_friend, ///< friend + sc_virt ///< virtual +}; + +/// \defgroup parse_tinfo Type parsing +/// Format/Parse/Print type information +//@{ + +/// \defgroup HTI_ Type formatting flags +//@{ +#define HTI_CPP 0x00000001 ///< C++ mode (not implemented) +#define HTI_INT 0x00000002 ///< debug: print internal representation of types +#define HTI_EXT 0x00000004 ///< debug: print external representation of types +#define HTI_LEX 0x00000008 ///< debug: print tokens +#define HTI_UNP 0x00000010 ///< debug: check the result by unpacking it +#define HTI_TST 0x00000020 ///< test mode: discard the result +#define HTI_FIL 0x00000040 ///< "input" is file name, + ///< otherwise "input" contains a C declaration +#define HTI_MAC 0x00000080 ///< define macros from the base tils +#define HTI_NWR 0x00000100 ///< no warning messages +#define HTI_NER 0x00000200 ///< ignore all errors but display them +#define HTI_DCL 0x00000400 ///< don't complain about redeclarations +#define HTI_NDC 0x00000800 ///< don't decorate names +#define HTI_PAK 0x00007000 ///< explicit structure pack value (#pragma pack) +#define HTI_PAK_SHIFT 12 ///< shift for #HTI_PAK. This field should + ///< be used if you want to remember an explicit + ///< pack value for each structure/union type. + ///< See #HTI_PAK... definitions +#define HTI_PAKDEF 0x00000000 ///< default pack value +#define HTI_PAK1 0x00001000 ///< #pragma pack(1) +#define HTI_PAK2 0x00002000 ///< #pragma pack(2) +#define HTI_PAK4 0x00003000 ///< #pragma pack(4) +#define HTI_PAK8 0x00004000 ///< #pragma pack(8) +#define HTI_PAK16 0x00005000 ///< #pragma pack(16) + +#define HTI_HIGH 0x00008000 ///< assume high level prototypes + ///< (with hidden args, etc) +#define HTI_LOWER 0x00010000 ///< lower the function prototypes +#define HTI_RAWARGS 0x00020000 ///< leave argument names unchanged (do not remove underscores) +//@} + + +/// This callback will be called for each type/variable declaration. +/// \param name var/func/type name +/// \param tif type info +/// \param cmt main comment +/// \param value symbol value +/// \param cb_data data passed to callback +/// \retval T_CBBRKDEF the type declaration won't be saved in the til + +typedef int idaapi h2ti_type_cb( + const char *name, + const tinfo_t &tif, + const char *cmt, + const uint64 *value, + void *cb_data); + + +/// Specify a printing callback when parsing types. +/// See h2ti() and parse_decls(). +typedef AS_PRINTF(1, 2) int printer_t(const char *format, ...); + + +/// Convert declarations to type_t*. +/// This is a low level function - use parse_decls() or parse_decl() +/// \param ti type info library +/// \param lx input lexer. may be NULL. always destroyed by h2ti() +/// \param input file name or C declaration +/// \param flags combination of \ref HTI_ +/// \param type_cb callback - for each type +/// \param var_cb callback - for each var +/// \param print_cb may pass msg() here +/// \param _cb_data data passed to callbacks +/// \param _isabs the expected abstracness of the type declaration(s) +/// \return number of errors (they are displayed using print_cb). zero means ok + +idaman int ida_export h2ti( + til_t *ti, + lexer_t *lx, + const char *input, + int flags=HTI_HIGH, + h2ti_type_cb *type_cb=NULL, + h2ti_type_cb *var_cb=NULL, + printer_t *print_cb=NULL, + void *_cb_data=NULL, + abs_t _isabs=abs_unk); + + +/// Parse ONE declaration. +/// If the input string contains more than one declaration, the first complete +/// type declaration (#PT_TYP) or the last variable declaration (#PT_VAR) will be used. +/// \note name & tif may be empty after the call! +/// \param[out] tif type info +/// \param[out] out declared name +/// \param til type library to use. may be NULL +/// \param decl C declaration to parse +/// \param flags combination of \ref PT_ bits +/// \retval true ok +/// \retval false declaration is bad, the error message is displayed if !PT_SIL + +idaman bool ida_export parse_decl( + tinfo_t *tif, + qstring *out, + til_t *til, + const char *decl, + int flags); + +/// \defgroup PT_ Type parsing flags +//@{ +#define PT_SIL 0x0001 ///< silent, no messages +#define PT_NDC 0x0002 ///< don't decorate names +#define PT_TYP 0x0004 ///< return declared type information +#define PT_VAR 0x0008 ///< return declared object information +#define PT_PACKMASK 0x0070 ///< mask for pack alignment values +#define PT_HIGH 0x0080 ///< assume high level prototypes + ///< (with hidden args, etc) +#define PT_LOWER 0x0100 ///< lower the function prototypes +#define PT_REPLACE 0x0200 ///< replace the old type (used in idc) +#define PT_RAWARGS 0x0400 ///< leave argument names unchanged (do not remove underscores) +//@} + + +/// Convert \ref PT_ to \ref HTI_. +/// Type parsing flags lesser than 0x10 don't have stable meaning and will be ignored +/// (more on these flags can be seen in idc.idc) + +inline THREAD_SAFE int convert_pt_flags_to_hti(int pt_flags) +{ + return ((pt_flags >> 4) & 0x1f) << HTI_PAK_SHIFT; +} + + +/// Parse many declarations and store them in a til. +/// If there are any errors, they will be printed using 'printer'. +/// This function uses default include path and predefined macros from the +/// database settings. It always uses the #HTI_DCL bit. +/// \param til type library to store the result +/// \param input input string or file name (see hti_flags) +/// \param printer function to output error messages (use msg or NULL or your own callback) +/// \param hti_flags combination of \ref HTI_ +/// \return number of errors, 0 means ok. + +idaman int ida_export parse_decls( + til_t *til, + const char *input, + printer_t *printer, + int hti_flags); + + +/// Get type declaration for the specified address. +/// \param out output buffer +/// \param ea address +/// \param prtype_flags combination of \ref PRTYPE_ +/// \return success + +idaman bool ida_export print_type(qstring *out, ea_t ea, int prtype_flags); + + +/// \defgroup PRTYPE_ Type printing flags +//@{ +#define PRTYPE_1LINE 0x0000 ///< print to one line +#define PRTYPE_MULTI 0x0001 ///< print to many lines +#define PRTYPE_TYPE 0x0002 ///< print type declaration (not variable declaration) +#define PRTYPE_PRAGMA 0x0004 ///< print pragmas for alignment +#define PRTYPE_SEMI 0x0008 ///< append ; to the end +#define PRTYPE_CPP 0x0010 ///< use c++ name (only for print_type()) +#define PRTYPE_DEF 0x0020 ///< tinfo_t: print definition, if available +#define PRTYPE_NOARGS 0x0040 ///< tinfo_t: do not print function argument names +#define PRTYPE_NOARRS 0x0080 ///< tinfo_t: print arguments with #FAI_ARRAY as pointers +#define PRTYPE_NORES 0x0100 ///< tinfo_t: never resolve types (meaningful with PRTYPE_DEF) +#define PRTYPE_RESTORE 0x0200 ///< tinfo_t: print restored types for #FAI_ARRAY and #FAI_STRUCT +#define PRTYPE_NOREGEX 0x0400 ///< do not apply regular expressions to beautify name +#define PRTYPE_COLORED 0x0800 ///< add color tag COLOR_SYMBOL for any parentheses, commas and colons +//@} + +//@} parse_tinfo + + +/// \defgroup named_types Named types +/// functions to work with named types +//@{ + + +/// Get named typeinfo. +/// The returned pointers are pointers to static storage. \n +/// They are valid until free_til(), set_named_type(), del_named_type(), \n +/// rename_named_type(), set_numbered_type(), del_numbered_type(), \n +/// and idb structure/enum manipulation (in other words, until ::til_t is changed). +/// \param ti pointer to type information library +/// \param name name of type +/// \param ntf_flags combination of \ref NTF_ +/// \param type ptr to ptr to output buffer for the type info +/// \param fields ptr to ptr to the field/args names. may be NULL +/// \param cmt ptr to ptr to the main comment. may be NULL +/// \param fieldcmts ptr to ptr to the field/args comments. may be NULL +/// \param sclass ptr to storage class +/// \param value ptr to symbol value. for types, ptr to the ordinal number +/// \retval 0 can't find the named type (or name==NULL) +/// \retval 1 ok, the buffers are filled with information (if not NULL) +/// \retval 2 ok, found it in a base til + +idaman int ida_export get_named_type( + const til_t *ti, + const char *name, + int ntf_flags, + const type_t **type=NULL, + const p_list **fields=NULL, + const char **cmt=NULL, + const p_list **fieldcmts=NULL, + sclass_t *sclass=NULL, + uint32 *value=NULL); + +/// \defgroup NTF_ Flags for named types +//@{ +#define NTF_TYPE 0x0001 ///< type name +#define NTF_SYMU 0x0008 ///< symbol, name is unmangled ('func') +#define NTF_SYMM 0x0000 ///< symbol, name is mangled ('_func') + ///< only one of #NTF_TYPE and #NTF_SYMU, #NTF_SYMM can be used +#define NTF_NOBASE 0x0002 ///< don't inspect base tils (for get_named_type) +#define NTF_REPLACE 0x0004 ///< replace original type (for set_named_type) +#define NTF_UMANGLED 0x0008 ///< name is unmangled (don't use this flag) +#define NTF_NOCUR 0x0020 ///< don't inspect current til file (for get_named_type) +#define NTF_64BIT 0x0040 ///< value is 64bit +#define NTF_FIXNAME 0x0080 ///< force-validate the name of the type when setting + ///< (set_named_type, set_numbered_type only) +#define NTF_IDBENC 0x0100 ///< the name is given in the IDB encoding; + ///< non-ASCII bytes will be decoded accordingly + ///< (set_named_type, set_numbered_type only) +#define NTF_CHKSYNC 0x0200 ///< check that synchronization to IDB passed OK + ///< (set_numbered_type, set_named_type) +//@} + + +/// See get_named_type() above. +/// \note If the value in the 'ti' library is 32-bit, it will +/// be sign-extended before being stored in the 'value' pointer. + +inline int idaapi get_named_type64( + const til_t *ti, + const char *name, + int ntf_flags, + const type_t **type=NULL, + const p_list **fields=NULL, + const char **cmt=NULL, + const p_list **fieldcmts=NULL, + sclass_t *sclass=NULL, + uint64 *value=NULL) +{ + return get_named_type(ti, name, ntf_flags | NTF_64BIT, + type, fields, cmt, fieldcmts, sclass, (uint32 *)value); +} + + +/// Error codes for save_tinfo functions: +enum tinfo_code_t +{ + TERR_OK = 0, ///< ok + TERR_SAVE = -1, ///< failed to save + TERR_SERIALIZE = -2, ///< failed to serialize + TERR_WRONGNAME = -3, ///< name is not acceptable + TERR_BADSYNC = -4, ///< failed to synchronize with IDB +}; + + +/// Delete information about a symbol. +/// \param ti type library +/// \param name name of symbol +/// \param ntf_flags combination of \ref NTF_ +/// \return success + +idaman bool ida_export del_named_type(til_t *ti, const char *name, int ntf_flags); + + +/// Enumerate types. +/// Returns mangled names. +/// Never returns anonymous types. To include it, enumerate types by ordinals. + +idaman const char *ida_export first_named_type(const til_t *ti, int ntf_flags); + + +/// \copydoc first_named_type() + +idaman const char *ida_export next_named_type(const til_t *ti, const char *name, int ntf_flags); + + +/// Copy a named type from one til to another. +/// This function will copy the specified type and all dependent types +/// from the source type library to the destination library. +/// \param dsttil Destination til. It must have orginal types enabled +/// \param srctil Source til. +/// \param name name of the type to copy +/// \return ordinal number of the copied type. 0 means error + +idaman uint32 ida_export copy_named_type( + til_t *dsttil, + const til_t *srctil, + const char *name); + + +/// Decorate/undecorate a C symbol name. +/// \param out output buffer +/// \param name name of symbol +/// \param mangle true-mangle, false-unmangle +/// \param cc calling convention +/// \param type name type (NULL-unknown) +/// \return success + +idaman bool ida_export decorate_name( + qstring *out, + const char *name, + bool mangle, + cm_t cc=CM_CC_UNKNOWN, + const tinfo_t *type = NULL); + + +/// Generic function for decorate_name() (may be used in IDP modules) + +idaman bool ida_export gen_decorate_name( + qstring *out, + const char *name, + bool mangle, + cm_t cc, + const tinfo_t *type); + + +/// Get C or C++ form of the name. +/// \param out output buffer +/// \param name original (mangled or decorated) name +/// \param type name type if known, otherwise NULL +/// \param ccn_flags one of \ref CCN_ + +idaman ssize_t ida_export calc_c_cpp_name( + qstring *out, + const char *name, + const tinfo_t *type, + int ccn_flags); +/// \defgroup CCN_ C/C++ naming flags +//@{ +#define CCN_C 0x00 // prepare C name +#define CCN_CPP 0x01 // prepare C++ name +//@} + +//@} named_types + +//-------------------------------------------------------------------------- +/// \defgroup numbered_types Numbered types +/// Functions to work with numbered (ordinal) types. +/// Numbered types may be named or anonymous. +/// They are referenced by their ordinal number. Access to them is faster because +/// there is no need to resolve their names. Also, they can stay anonymous +/// and be aliased. They can be used only in the local type library +/// created by IDA (in idati). +//@{ + +/// Enable the use of numbered types in til. +/// Currently it is impossible to disable numbered types once they are enabled + +idaman bool ida_export enable_numbered_types(til_t *ti, bool enable); + + +/// Retrieve a type by its ordinal number + +idaman bool ida_export get_numbered_type( + const til_t *ti, + uint32 ordinal, + const type_t **type=NULL, + const p_list **fields=NULL, + const char **cmt=NULL, + const p_list **fieldcmts=NULL, + sclass_t *sclass=NULL); + + +/// Allocate a range of ordinal numbers for new types. +/// \param ti type library +/// \param qty number of ordinals to allocate +/// \return the first ordinal. 0 means failure. + +idaman uint32 ida_export alloc_type_ordinals(til_t *ti, int qty); + + +/// \call2{alloc_type_ordinals,ti,1} + +inline uint32 alloc_type_ordinal(til_t *ti) { return alloc_type_ordinals(ti, 1); } + + +/// Get number of allocated ordinals. +/// \return uint32(-1) if failed + +idaman uint32 ida_export get_ordinal_qty(const til_t *ti); + + +/// Store a type in the til. +/// 'name' may be NULL for anonymous types. +/// The specified ordinal must be free (no other type is using it). +/// For ntf_flags, only #NTF_REPLACE is consulted. + +idaman tinfo_code_t ida_export set_numbered_type( + til_t *ti, + uint32 ordinal, + int ntf_flags, + const char *name, + const type_t *type, + const p_list *fields=NULL, + const char *cmt=NULL, + const p_list *fldcmts=NULL, + const sclass_t *sclass=NULL); + + +/// Delete a numbered type + +idaman bool ida_export del_numbered_type(til_t *ti, uint32 ordinal); + + +/// Create a type alias. +/// Redirects all references to source type to the destination type. +/// This is equivalent to instantaneous replacement all reference to srctype by dsttype. + +idaman bool ida_export set_type_alias(til_t *ti, uint32 src_ordinal, uint32 dst_ordinal); + + +/// Find the final alias destination. +/// If the ordinal has not been aliased, return the specified ordinal itself +/// If failed, returns 0. + +idaman uint32 ida_export get_alias_target(const til_t *ti, uint32 ordinal); + + +/// Get type ordinal by its name + +inline int32 get_type_ordinal(const til_t *ti, const char *name) +{ + uint32 ordinal = 0; + get_named_type(ti, name, NTF_TYPE|NTF_NOBASE, NULL, NULL, NULL, NULL, NULL, &ordinal); + return ordinal; +} + +/// Get type name (if exists) by its ordinal. +/// If the type is anonymous, returns "". If failed, returns NULL + +idaman const char *ida_export get_numbered_type_name(const til_t *ti, uint32 ordinal); + + +/// Create anonymous name for numbered type. This name can be used +/// to reference a numbered type by its ordinal +/// Ordinal names have the following format: '#' + set_de(ord) +/// Returns: -1 if error, otherwise the name length + +idaman ssize_t ida_export create_numbered_type_name(qstring *buf, int32 ord); + + +/// Check if the name is an ordinal name. +/// Ordinal names have the following format: '#' + set_de(ord) + +idaman bool ida_export is_ordinal_name(const char *name, uint32 *ord=NULL); + + +/// Get ordinal number of an idb type (struct/enum). +/// The 'type' parameter is used only to determine the kind of the type (struct or enum) +/// Use this function to find out the correspondence between idb types and til types + +idaman int ida_export get_ordinal_from_idb_type(const char *name, const type_t *type); + + +/// Is the specified idb type automatically synchronized? + +inline bool idaapi is_autosync(const char *name, const type_t *type) +{ + return get_ordinal_from_idb_type(name, type) != -1; +} +inline bool idaapi is_autosync(const char *name, const tinfo_t &tif); ///< copydoc is_autosync(const char*, const type_t *) + + +/// Generate a name like $hex_numbers based on the field types and names + +idaman void ida_export build_anon_type_name( + qstring *buf, + const type_t *type, + const p_list *fields); + + +const uint32 BADORD = uint32(-1); ///< invalid type ordinal + + +/// Compact numbered types to get rid of empty slots. +/// \param ti type library to compact +/// \param min_ord minimal ordinal number to start to compact. lower +/// ordinals are not modified +/// \param p_ordmap the resulting mapping +/// (for example, the new ordinal of min_ord will be in ordmap[0]) +/// \param flags reserved +/// \return number of freed type slots + +idaman int ida_export compact_numbered_types( + til_t *ti, + uint32 min_ord=0, + intvec_t *p_ordmap=NULL, + int flags=0); + +//@} numbered_types + +//-------------------------------------------------------------------------- +/// \defgroup vftable_types Link between vftable types and addresses +//@{ + +/// Get address of a virtual function table. +/// \param ordinal ordinal number of a vftable type. +/// \return address of the corresponding virtual function table in the current database. + +idaman ea_t ida_export get_vftable_ea(uint32 ordinal); + + +/// Get ordinal number of the virtual function table. +/// \param vftable_ea address of a virtual function table. +/// \return ordinal number of the corresponding vftable type. 0 - failure. + +idaman uint32 ida_export get_vftable_ordinal(ea_t vftable_ea); + + +/// Set the address of a vftable instance for a vftable type. +/// \param vftable_ea address of a virtual function table. +/// \param ordinal ordinal number of the corresponding vftable type. +/// \return success + +idaman bool ida_export set_vftable_ea(uint32 ordinal, ea_t vftable_ea); + + +/// Delete the address of a vftable instance for a vftable type. +/// \param ordinal ordinal number of a vftable type. +/// \return success + +inline bool del_vftable_ea(uint32 ordinal) { return set_vftable_ea(ordinal, BADADDR); } + + +//@} vftable_types + +//-------------------------------------------------------------------------- +// ALIGNMENT + +/// Get default alignment for structure fields. +/// \return one of 1,2,4,8,... + +inline size_t get_default_align(void) { return inf_get_cc_defalign(); } + + +/// Get alignment delta for the a structure field. +/// \param cur_tot_size the structure size calculated so far +/// \param elem_size size of the current field. +/// the whole structure should be calculated +/// \param algn the structure alignment (0,1,2,4,8...) + +inline THREAD_SAFE void align_size(size_t &cur_tot_size, size_t elem_size, size_t algn) +{ + size_t al = elem_size; + if ( algn != 0 && algn < al ) + al = algn; + cur_tot_size = align_up(cur_tot_size, al); +} + +/// Dereference a pointer. +/// \param[out] ptr_ea in/out parameter +/// - in: address of the pointer +/// - out: the pointed address +/// \param tif type of the pointer +/// \param[out] closure_obj closure object (not used yet) +/// \return success + +idaman bool ida_export deref_ptr( + ea_t *ptr_ea, + const tinfo_t &tif, + ea_t *closure_obj=NULL); + + +/// Remove pointer of a type. +/// (i.e. convert "char *" into "char"). +/// Optionally remove the "lp" (or similar) prefix of the input name. +/// If the input type is not a pointer, then fail. + +idaman bool ida_export remove_tinfo_pointer(tinfo_t *tif, const char **pname, const til_t *til=NULL); + +/// Copy a named type from til to idb. +/// \param til type library +/// \param idx the position of the new type in the list of types (structures or enums). +/// -1 means at the end of the list +/// \param name the type name +/// \param flags combination of \ref IMPTYPE_ +/// \return #BADNODE on error + +idaman tid_t ida_export import_type(const til_t *til, int idx, const char *name, int flags=0); + +/// \defgroup IMPTYPE_ Import type flags +/// passed as 'flags' parameter to import_type() +//@{ +#define IMPTYPE_VERBOSE 0x0001 ///< more verbose output (dialog boxes may appear) +#define IMPTYPE_OVERRIDE 0x0002 ///< override existing type +#define IMPTYPE_LOCAL 0x0004 ///< the type is local, the struct/enum won't be marked as til type. + ///< there is no need to specify this bit if til==idati, + ///< the kernel will set it automatically +//@} + +/// Load a til file. +/// \param name til name +/// \param flags combination of \ref ADDTIL_F +/// \return one of \ref ADDTIL_R + +idaman int ida_export add_til(const char *name, int flags); + +/// \defgroup ADDTIL_F Load TIL flags +/// passed as 'flags' parameter to add_til() +//@{ +#define ADDTIL_DEFAULT 0x0000 ///< default behavior +#define ADDTIL_INCOMP 0x0001 ///< load incompatible tils +#define ADDTIL_SILENT 0x0002 ///< do not ask any questions +//@} + +/// \defgroup ADDTIL_R Load TIL result codes +/// return values for add_til() +//@{ +#define ADDTIL_FAILED 0 ///< something bad, the warning is displayed +#define ADDTIL_OK 1 ///< ok, til is loaded +#define ADDTIL_COMP 2 ///< ok, but til is not compatible with the current compiler +#define ADDTIL_ABORTED 3 ///< til was not loaded (incompatible til rejected by user) +//@} + + +/// Unload a til file + +idaman bool ida_export del_til(const char *name); + + +/// Apply the specified named type to the address. +/// \param ea linear address +/// \param name the type name, e.g. "FILE" +/// \return success + +idaman bool ida_export apply_named_type(ea_t ea, const char *name); + + +/// Apply the specified type to the specified address. +/// This function sets the type and tries to convert the item at the specified +/// address to conform the type. +/// \param ea linear address +/// \param tif type string in internal format +/// \param flags combination of \ref TINFO_ +/// \returns success + +idaman bool ida_export apply_tinfo( + ea_t ea, + const tinfo_t &tif, + uint32 flags); + +/// \defgroup TINFO_ Apply tinfo flags +/// passed as 'flags' parameter to apply_tinfo() +//@{ +#define TINFO_GUESSED 0x0000 ///< this is a guessed type +#define TINFO_DEFINITE 0x0001 ///< this is a definite type +#define TINFO_DELAYFUNC 0x0002 ///< if type is a function and no function exists at ea, + ///< schedule its creation and argument renaming to auto-analysis + ///< otherwise try to create it immediately +#define TINFO_STRICT 0x0004 ///< never convert given type to another one before applying +//@} + + +/// Apply the specified type to the address. +/// This function parses the declaration and calls apply_tinfo() +/// \param til type library +/// \param ea linear address +/// \param decl type declaration in C form +/// \param flags flags to pass to apply_tinfo (#TINFO_DEFINITE is always passed) +/// \return success + +idaman bool ida_export apply_cdecl(til_t *til, ea_t ea, const char *decl, int flags=0); + + +/// Apply the type of the called function to the calling instruction. +/// This function will append parameter comments and rename the local +/// variables of the calling function. It also stores information about +/// the instructions that initialize call arguments in the database. +/// Use get_arg_addrs() to retrieve it if necessary. Alternatively it is +/// possible to hook to processor_t::arg_addrs_ready event. +/// \param caller linear address of the calling instruction. +/// must belong to a function. +/// \param tif type info +/// \return success + +idaman bool ida_export apply_callee_tinfo(ea_t caller, const tinfo_t &tif); + + +/// Retrieve argument initialization addresses. +/// This function retrieves information about argument addresses. +/// This information is stored in the database by apply_callee_tinfo(). +/// \param out linear addresses of the instructions that load call arguments +/// \param caller address of the call instruction +/// \return success + +idaman bool ida_export get_arg_addrs(eavec_t *out, ea_t caller); + + +/// Apply the specified type and name to the address. +/// This function checks if the address already has a type. If the old type \n +/// does not exist or the new type is 'better' than the old type, then the \n +/// new type will be applied. A type is considered better if it has more \n +/// information (e.g. ::BTMT_STRUCT is better than ::BT_INT). \n +/// The same logic is with the name: if the address already have a meaningful \n +/// name, it will be preserved. Only if the old name does not exist or it \n +/// is a dummy name like byte_123, it will be replaced by the new name. +/// \param dea linear address +/// \param tif type string in the internal format +/// \param name new name for the address +/// \return success + +idaman bool ida_export apply_once_tinfo_and_name( + ea_t dea, + const tinfo_t &tif, + const char *name); + + +// To retrieve the type information attach to an address, use get_tinfo() function +// (see nalt.hpp) + + +/// Generate a type information about the id from the disassembly. +/// id can be a structure/union/enum id or an address. +/// \return one of \ref GUESS_ + +idaman int ida_export guess_tinfo(tinfo_t *tif, tid_t id); + +/// \defgroup GUESS_ Guess tinfo codes +/// return values for guess_tinfo() +//@{ +#define GUESS_FUNC_FAILED 0 ///< couldn't guess the function type +#define GUESS_FUNC_TRIVIAL 1 ///< the function type doesn't have interesting info +#define GUESS_FUNC_OK 2 ///< ok, some non-trivial information is gathered +//@} + + +// The following functions should eventually be replaced by exported functions +#ifndef __KERNEL__ +/// Set include directory path the target compiler +inline void set_c_header_path(const char *incdir) { setinf_buf(INF_H_PATH, incdir); } + +/// Get the include directory path of the target compiler +inline ssize_t get_c_header_path(qstring *buf) { return getinf_str(buf, INF_H_PATH); } + +/// Set predefined macros for the target compiler +inline void set_c_macros(const char *macros) { setinf_buf(INF_C_MACROS, macros); } + +/// Get predefined macros for the target compiler +inline ssize_t get_c_macros(qstring *buf) { return getinf_str(buf, INF_C_MACROS); } +#endif + +//------------------------------------------------------------------------ +// HIGH LEVEL FUNCTIONS TO SUPPORT TILS IN THE IDA KERNEL + +/// Pointer to the local type library - this til is private for each IDB file +/// Function that accepts til_t* uses local type library instead of NULL. + +idaman const til_t *ida_export get_idati(void); + + +/// Extract information from a tinfo_t. +/// \param[out] psize size of tif +/// \param[out] pflags description of type using flags_t +/// \param[out] mt info for non-scalar types +/// \param tif the type to inspect +/// \param[out] alsize alignment + +idaman bool ida_export get_idainfo_by_type( + size_t *out_size, + flags_t *out_flags, + opinfo_t *out_mt, + const tinfo_t &tif, + size_t *out_alsize=NULL); + +//------------------------------------------------------------------------ +// Type information object: tinfo_t + +struct ptr_type_data_t; +struct udt_type_data_t; +struct enum_type_data_t; +struct array_type_data_t; +struct typedef_type_data_t; +struct bitfield_type_data_t; + +/// IDs for common types +enum stock_type_id_t +{ + STI_PCHAR, ///< char * + STI_PUCHAR, ///< uint8 * + STI_PCCHAR, ///< const char * + STI_PCUCHAR, ///< const uint8 * + STI_PBYTE, ///< _BYTE * + STI_PINT, ///< int * + STI_PUINT, ///< unsigned int * + STI_PVOID, ///< void * + STI_PPVOID, ///< void ** + STI_PCVOID, ///< const void * + STI_ACHAR, ///< char[] + STI_AUCHAR, ///< uint8[] + STI_ACCHAR, ///< const char[] + STI_ACUCHAR, ///< const uint8[] + STI_FPURGING, ///< void __userpurge(int) + STI_FDELOP, ///< void __cdecl(void *) + STI_MSGSEND, ///< void *(void *, const char *, ...) + STI_AEABI_LCMP, ///< int __fastcall(int64 x, int64 y) + STI_AEABI_ULCMP, ///< int __fastcall(uint64 x, uint64 y) + STI_DONT_USE, ///< unused stock type id; should not be used + STI_SIZE_T, ///< size_t + STI_SSIZE_T, ///< ssize_t + STI_AEABI_MEMCPY, ///< void __fastcall(void *, const void *, size_t) + STI_AEABI_MEMSET, ///< void __fastcall(void *, size_t, int) + STI_AEABI_MEMCLR, ///< void __fastcall(void *, size_t) + STI_RTC_CHECK_2, ///< int16 __fastcall(int16 x) + STI_RTC_CHECK_4, ///< int32 __fastcall(int32 x) + STI_RTC_CHECK_8, ///< int64 __fastcall(int64 x) + STI_LAST +}; + +/// Constants to be used with get_udt_details() +enum gtd_udt_t +{ + GTD_CALC_LAYOUT = 0, ///< calculate udt layout + GTD_NO_LAYOUT = BTM_VOLATILE, ///< don't calculate udt layout + ///< please note that udt layout may have been + ///< calculated earlier + GTD_DEL_BITFLDS = BTM_CONST, ///< delete udt bitfields +}; + +/// Constants to be used with get_func_details() +enum gtd_func_t +{ + GTD_CALC_ARGLOCS = 0, ///< calculate func arg locations + GTD_NO_ARGLOCS = BTM_VOLATILE, ///< don't calculate func arg locations + ///< please note that the locations may have been + ///< calculated earlier +}; + +/// Constants to be used with get_size() +enum gts_code_t +{ + GTS_NESTED = 0x01, ///< nested type (embedded into a udt) + GTS_BASECLASS = 0x02, ///< is baseclass of a udt +}; + +/// \defgroup SUDT_ UDT serialization flags +/// passed as 'sudt_flags' parameter of helpers declared in #DECLARE_TINFO_HELPERS +//@{ +#define SUDT_SORT 0x0001 ///< fields are not sorted by offset, sort them first +#define SUDT_ALIGN 0x0002 ///< recalculate field alignments, struct packing, etc + ///< to match the offsets and size info +#define SUDT_GAPS 0x0004 ///< allow to fill gaps with additional members (_BYTE[]) +#define SUDT_UNEX 0x0008 ///< references to nonexistent member types are acceptable + ///< in this case it is better to set the corresponding + ///< udt_member_t::fda field to the type alignment. if this + ///< field is not set, ida will try to guess the alignment. +#define SUDT_FAST 0x0010 ///< serialize without verifying offsets and alignments + +#define SUDT_CONST 0x0040 ///< only for serialize_udt: make type const +#define SUDT_VOLATILE 0x0080 ///< only for serialize_udt: make type volatile + +#define SUDT_TRUNC 0x0100 ///< serialize: truncate useless strings from fields, fldcmts +//@} + +/// Macro to declare common tinfo_t related functions +#define DECLARE_TINFO_HELPERS(decl)\ +decl void ida_export copy_tinfo_t(tinfo_t *_this, const tinfo_t &r); \ +decl void ida_export clear_tinfo_t(tinfo_t *_this);\ +decl bool ida_export create_tinfo(tinfo_t *_this, type_t bt, type_t bt2, void *ptr);\ +decl int ida_export verify_tinfo(uint32 typid);\ +decl bool ida_export get_tinfo_details(uint32 typid, type_t bt2, void *buf);\ +decl size_t ida_export get_tinfo_size(uint32 *p_effalign, uint32 typid, int gts_code);\ +decl size_t ida_export get_tinfo_pdata(void *outptr, uint32 typid, int what);\ +decl size_t ida_export get_tinfo_property(uint32 typid, int gta_prop);\ +decl size_t ida_export set_tinfo_property(tinfo_t *tif, int sta_prop, size_t x);\ +decl bool ida_export serialize_tinfo(qtype *type, qtype *fields, qtype *fldcmts, const tinfo_t *tif, int sudt_flags);\ +decl bool ida_export deserialize_tinfo(tinfo_t *tif, const til_t *til, const type_t **ptype, const p_list **pfields, const p_list **pfldcmts);\ +decl int ida_export find_tinfo_udt_member(struct udt_member_t *udm, uint32 typid, int strmem_flags);\ +decl bool ida_export print_tinfo(qstring *result, const char *prefix, int indent, int cmtindent, int flags, const tinfo_t *tif, const char *name, const char *cmt);\ +decl const char *ida_export dstr_tinfo(const tinfo_t *tif);\ +decl int ida_export visit_subtypes(struct tinfo_visitor_t *visitor, struct type_mods_t *out, const tinfo_t &tif, const char *name, const char *cmt);\ +decl bool ida_export compare_tinfo(uint32 t1, uint32 t2, int tcflags);\ +decl int ida_export lexcompare_tinfo(uint32 t1, uint32 t2, int);\ +decl bool ida_export get_stock_tinfo(tinfo_t *tif, stock_type_id_t id);\ +decl uint64 ida_export read_tinfo_bitfield_value(uint32 typid, uint64 v, int bitoff);\ +decl uint64 ida_export write_tinfo_bitfield_value(uint32 typid, uint64 dst, uint64 v, int bitoff);\ +decl bool ida_export get_tinfo_attr(uint32 typid, const qstring &key, bytevec_t *bv, bool all_attrs);\ +decl bool ida_export set_tinfo_attr(tinfo_t *tif, const type_attr_t &ta, bool may_overwrite);\ +decl bool ida_export del_tinfo_attr(tinfo_t *tif, const qstring &key, bool make_copy);\ +decl bool ida_export get_tinfo_attrs(uint32 typid, type_attrs_t *tav, bool include_ref_attrs);\ +decl bool ida_export set_tinfo_attrs(tinfo_t *tif, type_attrs_t *ta);\ +decl uint32 ida_export score_tinfo(const tinfo_t *tif);\ +decl tinfo_code_t ida_export save_tinfo(tinfo_t *tif, til_t *til, size_t ord, const char *name, int ntf_flags);\ +decl bool ida_export append_tinfo_covered(rangeset_t *out, uint32 typid, uint64 offset);\ +decl bool ida_export calc_tinfo_gaps(rangeset_t *out, uint32 typid);\ +decl bool ida_export name_requires_qualifier(qstring *out, uint32 typid, const char *name, uint64 offset);\ + +DECLARE_TINFO_HELPERS(idaman) + +/*! \defgroup tf_nontrivial Nontrivial types + \ingroup tf + bits 0..5: base type \n + bits 6..7: const & volatile bits \n + bit 8: 'is_typeref' bit \n + bits 9..31: type detail idx +*/ +//@{ +const int FIRST_NONTRIVIAL_TYPID = 0x100; ///< Denotes the first bit describing a nontrivial type +const int TYPID_ISREF = 0x100; ///< Identifies that a type that is a typeref +const int TYPID_SHIFT = 9; ///< First type detail bit +//@} + +//-V:create_array:678 An object is used as an argument to its own method. +//-V:create_ptr:678 +/// Primary mechanism for managing type information +class tinfo_t // #tinfo_t #tif +{ + uint32 typid; /// byte sequence describing the type + bool create_type(type_t decl_type, type_t bt2, void *details) + { + return create_tinfo(this, decl_type, bt2, details); + } + /// Get the type details. + /// The information is copied to the user-supplied buffer. + /// Also check out convenience functions below (get_ptr_details, etc), they work faster because + /// they do not copy the entire type info but only the desired part of it. + bool get_type_details(type_t bt2, void *buf) const { return get_tinfo_details(typid, bt2, buf); } + void copy(const tinfo_t &r) { copy_tinfo_t(this, r); } + DECLARE_TINFO_HELPERS(friend) + friend struct type_detail_t; + friend tinfo_t remove_pointer(const tinfo_t &tif); + /// Various type properties (properties are a 32-bit scalar values) + enum gta_prop_t + { + GTA_DECLALIGN, ///< declared alignment + GTA_RESOLVE, ///< real type (fully resolve eventual type references) + GTA_REALTYPE, ///< real type (do not fully resolve type refs) + GTA_TYPE_SIGN, ///< get type sign + GTA_FROM_SUBTIL, ///< is from a subtil (not from main til) + GTA_IS_FORWARD, ///< is forward declaration? + GTA_IS_FUNCPTR, ///< is a pointer to a function? + GTA_ORDINAL, ///< get initial type ordinal + GTA_FINAL_ORDINAL, ///< get final (resolved) type ordinal + GTA_PTR_OBJ, ///< ptr: pointed type + GTA_SAFE_PTR_OBJ, ///< ptr: pointed type or type itself + GTA_ARRAY_ELEM, ///< array: array element + GTA_ARRAY_NELEMS, ///< array: number of elements + GTA_PTRARR_SUBTIF, ///< ptr&array: pointed object or array element (nb: deletes current tif) + GTA_PTRARR_SIZE, ///< ptr&array: get size of subtype + GTA_UNPADDED_SIZE, ///< udt: sizeof baseclass when embedded into a derived class + GTA_UDT_NMEMBERS, ///< udt: get number of udt members + GTA_IS_SMALL_UDT, ///< udt: is small udt (can be passed in regs) + GTA_ONEMEM_TYPE, ///< udt&array: object consisting of one member: type of the member + GTA_ENUM_BASE_TYPE, ///< enum: get enum base type + GTA_FUNC_CC, ///< func: calling convention + GTA_PURGED_BYTES, ///< func: number of purged bytes + GTA_IS_HIGH_TYPE, ///< func: is high type + GTA_FUNC_NARGS, ///< func: number of arguments + GTA_FUNC_RET, ///< func: get function return type + GTA_FUNC_ARG, ///< func: get type of function arg + GTA_LAST_FUNC_ARG = GTA_FUNC_ARG + 255, + GTA_IS_SSE_TYPE, ///< is a SSE vector type? + GTA_IS_ANON_UDT, ///< is anonymous struct/union? + GTA_IS_VFTABLE, ///< is vftable? + GTA_HAS_VFTABLE, ///< has vftable? + GTA_IS_SHIFTED_PTR, ///< is a shifted pointer? + GTA_IS_VARSTRUCT, ///< is a variable-size structure? + }; + enum sta_prop_t ///< set type property + { + STA_DECLALIGN, ///< set declared alignment + STA_TYPE_SIGN, ///< set type sign + STA_UDT_ALIGN, ///< calculate udt field alignments + }; + enum gta_pdata_t ///< get info returned by pointer + { + GTP_NAME, ///< get referenced name + GTP_NEXT_NAME, ///< get immediately next referenced name + GTP_FINAL_NAME, ///< get final referenced name + GTP_TIL, ///< get type library + }; + +public: + /// Constructor + tinfo_t(): typid(BT_UNK) {} + /// Constructor - can only be used to initialize simple types! + explicit tinfo_t(type_t decl_type) : typid(decl_type) {} + /// Constructor + tinfo_t(const tinfo_t &r) : typid(0) { copy(r); } + /// Copy contents of given tinfo into this one + tinfo_t &operator=(const tinfo_t &r) { copy(r); return *this; } + /// Destructor + ~tinfo_t(void) { clear(); } + /// Clear contents of this tinfo, and remove from the type system + void clear(void) { clear_tinfo_t(this); } + /// Assign this = r and r = this + void swap(tinfo_t &r) { uint32 tmp = typid; typid = r.typid; r.typid = tmp; } + DEFINE_MEMORY_ALLOCATION_FUNCS() + + /// Create a tinfo_t object for an existing named type. + /// \param til type library to use + /// \param name name of the type to link to + /// \param decl_type if the reference was explicitly specified with the type tag \n + /// (::BTF_STRUCT/::BTF_UNION/::BTF_ENUM) you may specify it. \n + /// the kernel will accept only the specified tag after resolving \n + /// the type. If the resolved type does not correspond to the \n + /// explicitly specified tag, the type will be considered as undefined \n + /// \param resolve true: immediately resolve the type and return success code. + /// false: return true but do not immediately resolve the type + /// \param try_ordinal true: try to replace name reference by an ordinal reference + inline bool get_named_type( + const til_t *til, + const char *name, + type_t decl_type=BTF_TYPEDEF, + bool resolve=true, + bool try_ordinal=true); + + /// Create a tinfo_t object for an existing ordinal type. + /// \param til type library to use + /// \param ordinal number of the type to link to + /// \param decl_type if the reference was explicitly specified with the type tag + /// (BTF_STRUCT/BTF_UNION/BTF_ENUM) you may specify it. + /// the kernel will accept only the specified tag after resolving + /// the type. If the resolved type does not correspond to the + /// explicitly specified tag, the type will be considered as undefined + /// \param resolve true: immediately resolve the type and return success code + /// false: return true but do not immediately resolve the type + inline bool get_numbered_type( + const til_t *til, + uint32 ordinal, + type_t decl_type=BTF_TYPEDEF, + bool resolve=true); + + /// Serialize tinfo_t object into a type string. + bool serialize( + qtype *type, + qtype *fields=NULL, + qtype *fldcmts=NULL, + int sudt_flags=SUDT_FAST|SUDT_TRUNC) const + { + return serialize_tinfo(type, fields, fldcmts, this, sudt_flags); + } + + /// Deserialize a type string into a tinfo_t object + bool deserialize( + const til_t *til, + const type_t **ptype, + const p_list **pfields=NULL, + const p_list **pfldcmts=NULL) + { + return deserialize_tinfo(this, til, ptype, pfields, pfldcmts); + } + /// \copydoc deserialize() + bool deserialize( + const til_t *til, + const qtype *ptype, + const qtype *pfields=NULL, + const qtype *pfldcmts=NULL) + { + const type_t *tp = ptype->begin(); + const p_list *fp = pfields == NULL ? NULL : pfields->begin(); + const p_list *cp = pfldcmts == NULL ? NULL : pfldcmts->begin(); + return deserialize(til, &tp, fp == NULL ? NULL : &fp, cp == NULL ? NULL : &cp); + } + + /// Is the type object correct?. + /// It is possible to create incorrect types. For example, we can define a + /// function that returns a enum and then delete the enum type. + /// If this function returns false, the type should not be used in + /// disassembly. Please note that this function does not verify all + /// involved types: for example, pointers to undefined types are permitted. + bool is_correct(void) const { return verify_tinfo(typid) == 0; } + + /// Get the resolved base type. + /// Deserialization options: + /// - if full=true, the referenced type will be deserialized fully, + /// this may not always be desirable (slows down things) + /// - if full=false, we just return the base type, the referenced type will be + /// resolved again later if necessary + /// (this may lead to multiple resolvings of the same type) + /// imho full=false is a better approach because it does not perform + /// unnecessary actions just in case. however, in some cases the caller knows + /// that it is very likely that full type info will be required. in those cases + /// full=true makes sense + type_t get_realtype(bool full=false) const { return (type_t)get_tinfo_property(typid, full ? GTA_RESOLVE : GTA_REALTYPE); } + + /// Get declared type (without resolving type references; they are returned as is). + /// Obviously this is a very fast function and should be used instead of get_realtype() + /// if possible. + THREAD_SAFE type_t get_decltype(void) const { return type_t(typid); } + + /// Was tinfo_t initialized with some type info or not? + THREAD_SAFE bool empty(void) const { return get_decltype() == BT_UNK; } + + /// Is the type really present? (not a reference to a missing type, for example) + bool present(void) const { return get_realtype() != BT_UNK; } + + /// Get the type size in bytes. + /// \param p_effalign buffer for the alignment value + /// \param gts_code combination of GTS_... constants + /// \return ::BADSIZE in case of problems + size_t get_size(uint32 *p_effalign=NULL, int gts_code=0) const { return get_tinfo_size(p_effalign, typid, gts_code); } + + /// Get the type size in bytes without the final padding, in bytes. + /// For some UDTs get_unpadded_size() != get_size() + size_t get_unpadded_size(void) const { return get_tinfo_property(typid, GTA_UNPADDED_SIZE); } + + /// Get type sign + type_sign_t get_sign(void) const { return get_tinfo_property(typid, GTA_TYPE_SIGN); } + + /// Is this a signed type? + bool is_signed(void) const { return get_sign() == type_signed; } + + /// Is this an unsigned type? + bool is_unsigned(void) const { return get_sign() == type_unsigned; } + + /// Get declared alignment of the type + uchar get_declalign(void) const { return uchar(get_tinfo_property(typid, GTA_DECLALIGN)); } + + /// Set declared alignment of the type + bool set_declalign(uchar declalign) { return set_tinfo_property(this, STA_DECLALIGN, declalign) != 0; } + + /// Is this type a type reference?. + /// Type references cannot be modified. Once created, they do not change. + /// Because of this, the set_... functions applied to typerefs create + /// a new type id. Other types are modified directly. + THREAD_SAFE bool is_typeref(void) const { return (typid & TYPID_ISREF) != 0; } + + /// Does this type refer to a nontrivial type? + THREAD_SAFE bool has_details(void) const { return typid >= FIRST_NONTRIVIAL_TYPID; } + + /// Does a type refer to a name?. + /// If yes, fill the provided buffer with the type name and return true. + /// Names are returned for numbered types too: either a user-defined nice name + /// or, if a user-provided name does not exist, an ordinal name + /// (like #xx, see create_numbered_type_name()). + bool get_type_name(qstring *out) const { return is_typeref() && get_tinfo_pdata(out, typid, GTP_NAME); } + + /// Use in the case of typedef chain (TYPE1 -> TYPE2 -> TYPE3...TYPEn). + /// \return the name of the last type in the chain (TYPEn). + /// if there is no chain, returns TYPE1 + bool get_final_type_name(qstring *out) const { return is_typeref() && get_tinfo_pdata(out, typid, GTP_FINAL_NAME); } + + /// Use In the case of typedef chain (TYPE1 -> TYPE2 -> TYPE3...TYPEn). + /// \return the name of the next type in the chain (TYPE2). + /// if there is no chain, returns failure + bool get_next_type_name(qstring *out) const { return is_typeref() && get_tinfo_pdata(out, typid, GTP_NEXT_NAME); } + + /// Get type ordinal (only if the type was created as a numbered type, 0 if none) + uint32 get_ordinal(void) const { return get_tinfo_property(typid, GTA_ORDINAL); } + + /// Get final type ordinal (0 is none) + uint32 get_final_ordinal(void) const { return get_tinfo_property(typid, GTA_FINAL_ORDINAL); } + + /// Get the type library for tinfo_t + const til_t *get_til(void) const { const til_t *til; get_tinfo_pdata(&til, typid, GTP_TIL); return til; } + + /// Was the named type found in some base type library (not the top level type library)?. + /// If yes, it usually means that the type comes from some loaded type library, + /// not the local type library for the database + bool is_from_subtil(void) const { return is_typeref() && get_tinfo_property(typid, GTA_FROM_SUBTIL); } + + /// Is this a forward declaration?. + /// Forward declarations are placeholders: the type definition does not exist + bool is_forward_decl(void) const { return get_tinfo_property(typid, GTA_IS_FORWARD) != 0; } + + THREAD_SAFE bool is_decl_const(void) const { return is_type_const(get_decltype()); } ///< \isdecl{is_type_const} + THREAD_SAFE bool is_decl_volatile(void) const { return is_type_volatile(get_decltype()); } ///< \isdecl{is_type_volatile} + THREAD_SAFE bool is_decl_void(void) const { return is_type_void(get_decltype()); } ///< \isdecl{is_type_void} + THREAD_SAFE bool is_decl_partial(void) const { return is_type_partial(get_decltype()); } ///< \isdecl{is_type_partial} + THREAD_SAFE bool is_decl_unknown(void) const { return is_type_unknown(get_decltype()); } ///< \isdecl{is_type_unknown} + THREAD_SAFE bool is_decl_last(void) const { return is_typeid_last(get_decltype()); } ///< \isdecl{is_typeid_last} + THREAD_SAFE bool is_decl_ptr(void) const { return is_type_ptr(get_decltype()); } ///< \isdecl{is_type_ptr} + THREAD_SAFE bool is_decl_array(void) const { return is_type_array(get_decltype()); } ///< \isdecl{is_type_array} + THREAD_SAFE bool is_decl_func(void) const { return is_type_func(get_decltype()); } ///< \isdecl{is_type_func} + THREAD_SAFE bool is_decl_complex(void) const { return is_type_complex(get_decltype()); } ///< \isdecl{is_type_complex} + THREAD_SAFE bool is_decl_typedef(void) const { return is_type_typedef(get_decltype()); } ///< \isdecl{is_type_typedef} + THREAD_SAFE bool is_decl_sue(void) const { return is_type_sue(get_decltype()); } ///< \isdecl{is_type_sue} + THREAD_SAFE bool is_decl_struct(void) const { return is_type_struct(get_decltype()); } ///< \isdecl{is_type_struct} + THREAD_SAFE bool is_decl_union(void) const { return is_type_union(get_decltype()); } ///< \isdecl{is_type_union} + THREAD_SAFE bool is_decl_udt(void) const { return is_type_struni(get_decltype()); } ///< \isdecl{is_type_struni} + THREAD_SAFE bool is_decl_enum(void) const { return is_type_enum(get_decltype()); } ///< \isdecl{is_type_enum} + THREAD_SAFE bool is_decl_bitfield(void) const { return is_type_bitfld(get_decltype()); } ///< \isdecl{is_type_bitfld} + THREAD_SAFE bool is_decl_int128(void) const { return is_type_int128(get_decltype()); } ///< \isdecl{is_type_int128} + THREAD_SAFE bool is_decl_int64(void) const { return is_type_int64(get_decltype()); } ///< \isdecl{is_type_int64} + THREAD_SAFE bool is_decl_int32(void) const { return is_type_int32(get_decltype()); } ///< \isdecl{is_type_int32} + THREAD_SAFE bool is_decl_int16(void) const { return is_type_int16(get_decltype()); } ///< \isdecl{is_type_int16} + THREAD_SAFE bool is_decl_int(void) const { return is_type_int(get_decltype()); } ///< \isdecl{is_type_int} + THREAD_SAFE bool is_decl_char(void) const { return is_type_char(get_decltype()); } ///< \isdecl{is_type_char} + THREAD_SAFE bool is_decl_uint(void) const { return is_type_uint(get_decltype()); } ///< \isdecl{is_type_uint} + THREAD_SAFE bool is_decl_uchar(void) const { return is_type_uchar(get_decltype()); } ///< \isdecl{is_type_uchar} + THREAD_SAFE bool is_decl_uint16(void) const { return is_type_uint16(get_decltype()); } ///< \isdecl{is_type_uint16} + THREAD_SAFE bool is_decl_uint32(void) const { return is_type_uint32(get_decltype()); } ///< \isdecl{is_type_uint32} + THREAD_SAFE bool is_decl_uint64(void) const { return is_type_uint64(get_decltype()); } ///< \isdecl{is_type_uint64} + THREAD_SAFE bool is_decl_uint128(void) const { return is_type_uint128(get_decltype()); } ///< \isdecl{is_type_uint128} + THREAD_SAFE bool is_decl_ldouble(void) const { return is_type_ldouble(get_decltype()); } ///< \isdecl{is_type_ldouble} + THREAD_SAFE bool is_decl_double(void) const { return is_type_double(get_decltype()); } ///< \isdecl{is_type_double} + THREAD_SAFE bool is_decl_float(void) const { return is_type_float(get_decltype()); } ///< \isdecl{is_type_float} + THREAD_SAFE bool is_decl_tbyte(void) const { return is_type_tbyte(get_decltype()); } ///< \isdecl{is_type_tbyte} + THREAD_SAFE bool is_decl_floating(void) const { return is_type_floating(get_decltype()); } ///< \isdecl{is_type_floating} + THREAD_SAFE bool is_decl_bool(void) const { return is_type_bool(get_decltype()); } ///< \isdecl{is_type_bool} + THREAD_SAFE bool is_decl_paf(void) const { return is_type_paf(get_decltype()); } ///< \isdecl{is_type_paf} + THREAD_SAFE bool is_well_defined(void) const { return !empty() && !is_decl_partial(); } ///< !(empty()) && !(is_decl_partial()) + + // Probe the resolved type for various attributes: + bool is_const(void) const { return is_type_const(get_realtype()); } ///< \isreal{is_type_const} + bool is_volatile(void) const { return is_type_volatile(get_realtype()); } ///< \isreal{is_type_volatile} + bool is_void(void) const { return is_type_void(get_realtype()); } ///< \isreal{is_type_void} + bool is_partial(void) const { return is_type_partial(get_realtype()); } ///< \isreal{is_type_partial} + bool is_unknown(void) const { return is_type_unknown(get_realtype()); } ///< \isreal{is_type_unknown} + bool is_ptr(void) const { return is_type_ptr(get_realtype()); } ///< \isreal{is_type_ptr} + bool is_array(void) const { return is_type_array(get_realtype()); } ///< \isreal{is_type_array} + bool is_func(void) const { return is_type_func(get_realtype()); } ///< \isreal{is_type_func} + bool is_complex(void) const { return is_type_complex(get_realtype()); } ///< \isreal{is_type_complex} + bool is_struct(void) const { return is_type_struct(get_realtype()); } ///< \isreal{is_type_struct} + bool is_union(void) const { return is_type_union(get_realtype()); } ///< \isreal{is_type_union} + bool is_udt(void) const { return is_type_struni(get_realtype()); } ///< \isreal{is_type_struni} + bool is_enum(void) const { return is_type_enum(get_realtype()); } ///< \isreal{is_type_enum} + bool is_sue(void) const { return is_type_sue(get_realtype()); } ///< \isreal{is_type_sue} + bool is_bitfield(void) const { return is_type_bitfld(get_realtype()); } ///< \isreal{is_type_bitfld} + bool is_int128(void) const { return is_type_int128(get_realtype()); } ///< \isreal{is_type_int128} + bool is_int64(void) const { return is_type_int64(get_realtype()); } ///< \isreal{is_type_int64} + bool is_int32(void) const { return is_type_int32(get_realtype()); } ///< \isreal{is_type_int32} + bool is_int16(void) const { return is_type_int16(get_realtype()); } ///< \isreal{is_type_int16} + bool is_int(void) const { return is_type_int(get_realtype()); } ///< \isreal{is_type_int} + bool is_char(void) const { return is_type_char(get_realtype()); } ///< \isreal{is_type_char} + bool is_uint(void) const { return is_type_uint(get_realtype()); } ///< \isreal{is_type_uint} + bool is_uchar(void) const { return is_type_uchar(get_realtype()); } ///< \isreal{is_type_uchar} + bool is_uint16(void) const { return is_type_uint16(get_realtype()); } ///< \isreal{is_type_uint16} + bool is_uint32(void) const { return is_type_uint32(get_realtype()); } ///< \isreal{is_type_uint32} + bool is_uint64(void) const { return is_type_uint64(get_realtype()); } ///< \isreal{is_type_uint64} + bool is_uint128(void) const { return is_type_uint128(get_realtype()); } ///< \isreal{is_type_uint128} + bool is_ldouble(void) const { return is_type_ldouble(get_realtype()); } ///< \isreal{is_type_ldouble} + bool is_double(void) const { return is_type_double(get_realtype()); } ///< \isreal{is_type_double} + bool is_float(void) const { return is_type_float(get_realtype()); } ///< \isreal{is_type_float} + bool is_tbyte(void) const { return is_type_tbyte(get_realtype()); } ///< \isreal{is_type_tbyte} + bool is_bool(void) const { return is_type_bool(get_realtype()); } ///< \isreal{is_type_bool} + bool is_paf(void) const { return is_type_paf(get_realtype()); } ///< \isreal{is_type_paf} + bool is_ptr_or_array(void) const { return is_type_ptr_or_array(get_realtype()); } ///< \isreal{is_type_ptr_or_array} + bool is_integral(void) const { return is_type_integral(get_realtype()); } ///< \isreal{is_type_integral} + bool is_ext_integral(void) const { return is_type_ext_integral(get_realtype()); } ///< \isreal{is_type_ext_integral} + bool is_floating(void) const { return is_type_floating(get_realtype()); } ///< \isreal{is_type_floating} + bool is_arithmetic(void) const { return is_type_arithmetic(get_realtype()); } ///< \isreal{is_type_arithmetic} + bool is_ext_arithmetic(void) const { return is_type_ext_arithmetic(get_realtype()); } ///< \isreal{is_type_ext_arithmetic} + /// Does the type represent a single number? + bool is_scalar(void) const { type_t bt = get_realtype(); return get_base_type(bt) <= BT_PTR || is_type_enum(bt); } + + /// Get the pointer info. + bool get_ptr_details(ptr_type_data_t *pi) const + { + return get_type_details(BT_PTR|BTM_VOLATILE, pi); + } + + /// Get the array specific info + bool get_array_details(array_type_data_t *ai) const + { + return get_type_details(BT_ARRAY, ai); + } + + /// Get the enum specific info + bool get_enum_details(enum_type_data_t *ei) const + { + return get_type_details(BTF_ENUM, ei); + } + + /// Get the bitfield specific info + bool get_bitfield_details(bitfield_type_data_t *bi) const + { + return get_type_details(BT_BITFIELD, bi); + } + + /// Get the udt specific info + bool get_udt_details(udt_type_data_t *udt, gtd_udt_t gtd=GTD_CALC_LAYOUT) const + { + return get_type_details(BTF_STRUCT|gtd, udt); + } + + /// Get only the function specific info for this tinfo_t + bool get_func_details(func_type_data_t *fi, gtd_func_t gtd=GTD_CALC_ARGLOCS) const + { + return get_type_details(BT_FUNC|gtd, fi); + } + + /// Is this pointer to a function? + bool is_funcptr(void) const { return get_tinfo_property(typid, GTA_IS_FUNCPTR) != 0; } + + /// Is a shifted pointer? + bool is_shifted_ptr(void) const { return get_tinfo_property(typid, GTA_IS_SHIFTED_PTR) != 0; } + + /// Is a variable-size structure? + bool is_varstruct(void) const { return get_tinfo_property(typid, GTA_IS_VARSTRUCT) != 0; } + + /// ::BT_PTR & ::BT_ARRAY: get size of pointed object or array element. On error returns -1 + int get_ptrarr_objsize(void) const { return get_tinfo_property(typid, GTA_PTRARR_SIZE); } + + /// ::BT_PTR & ::BT_ARRAY: get the pointed object or array element. + /// If the current type is not a pointer or array, return empty type info. + tinfo_t get_ptrarr_object(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_PTRARR_SUBTIF); return r; } + + /// ::BT_PTR: get type of pointed object. + /// If the current type is not a pointer, return empty type info. + /// See also get_ptrarr_object() and remove_pointer() + tinfo_t get_pointed_object(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_PTR_OBJ); return r; } + + /// Is "void *"?. This function does not check the pointer attributes and type modifiers + bool is_pvoid(void) const { return get_pointed_object().is_void(); } + + /// ::BT_ARRAY: get type of array element. See also get_ptrarr_object() + tinfo_t get_array_element(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_ARRAY_ELEM); return r; } + + /// ::BT_ARRAY: get number of elements (-1 means error) + int get_array_nelems(void) const { return get_tinfo_property(typid, GTA_ARRAY_NELEMS); } + + /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Get type of n-th arg (-1 means return type, see get_rettype()) + tinfo_t get_nth_arg(int n) const + { + tinfo_t r; + if ( n >= -1 && n < MAX_FUNC_ARGS ) + r.typid = get_tinfo_property(typid, GTA_FUNC_ARG+n); + return r; + } + + /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Get the function's return type + tinfo_t get_rettype(void) const { return get_nth_arg(-1); } + + /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Calculate number of arguments (-1 - error) + int get_nargs(void) const { return get_tinfo_property(typid, GTA_FUNC_NARGS); } + + /// ::BT_FUNC or ::BT_PTR ::BT_FUNC: Get calling convention + cm_t get_cc(void) const { return (cm_t)get_tinfo_property(typid, GTA_FUNC_CC); } + bool is_user_cc(void) const { return ::is_user_cc(get_cc()); } ///< \tinfocc{is_user_cc} + bool is_vararg_cc(void) const { return ::is_vararg_cc(get_cc()); } ///< \tinfocc{is_vararg_cc} + bool is_purging_cc(void) const { return ::is_purging_cc(get_cc()); } ///< \tinfocc{is_purging_cc} + + /// ::BT_FUNC: Calculate number of purged bytes + int calc_purged_bytes(void) const { return get_tinfo_property(typid, GTA_PURGED_BYTES); } + + /// ::BT_FUNC: Is high level type? + bool is_high_func(void) const { return get_tinfo_property(typid, GTA_IS_HIGH_TYPE) != 0; } + + /// ::BTF_STRUCT,::BTF_UNION: Find a udt member. + /// - at the specified offset (#STRMEM_OFFSET) + /// - with the specified index (#STRMEM_INDEX) + /// - with the specified type (#STRMEM_TYPE) + /// - with the specified name (#STRMEM_NAME) + /// \return the index of the found member or -1 + int find_udt_member(struct udt_member_t *udm, int strmem_flags) const { return find_tinfo_udt_member(udm, typid, strmem_flags); } +/// \defgroup STRMEM_ Find UDT member flags +/// used by 'strmem_flags' parameter to find_udt_member() +//@{ +#define STRMEM_MASK 0x0007 +#define STRMEM_OFFSET 0x0000 ///< get member by offset + ///< - in: udm->offset - is a member offset in bits +#define STRMEM_INDEX 0x0001 ///< get member by number + ///< - in: udm->offset - is a member number +#define STRMEM_AUTO 0x0002 ///< get member by offset if struct, or get member by index if union + ///< - nb: union: index is stored in the udm->offset field! + ///< - nb: struct: offset is in bytes (not in bits)! +#define STRMEM_NAME 0x0003 ///< get member by name + ///< - in: udm->name - the desired member name. +#define STRMEM_TYPE 0x0004 ///< get member by type. + ///< - in: udm->type - the desired member type. + ///< member types are compared with tinfo_t::equals_to() +#define STRMEM_SIZE 0x0005 ///< get member by size. + ///< - in: udm->size - the desired member size. +#define STRMEM_MINS 0x0006 ///< get smallest member by size. +#define STRMEM_MAXS 0x0007 ///< get biggest member by size. +#define STRMEM_VFTABLE 0x10000000 + ///< can be combined with #STRMEM_OFFSET, #STRMEM_AUTO + ///< get vftable instead of the base class +#define STRMEM_SKIP_EMPTY 0x20000000 + ///< can be combined with #STRMEM_OFFSET, #STRMEM_AUTO + ///< skip empty members (i.e. having zero size) + ///< only last empty member can be returned +#define STRMEM_CASTABLE_TO 0x40000000 + ///< can be combined with #STRMEM_TYPE: + ///< member type must be castable to the specified type +#define STRMEM_ANON 0x80000000 + ///< can be combined with #STRMEM_NAME: + ///< look inside anonymous members too. +//@} + + /// Get number of udt members. -1-error + int get_udt_nmembers(void) const { return get_tinfo_property(typid, GTA_UDT_NMEMBERS); } + + /// Is an empty struct/union? (has no fields) + bool is_empty_udt(void) const { return get_udt_nmembers() == 0; } + + /// Is a small udt? (can fit a register or a pair of registers) + bool is_small_udt(void) const { return get_tinfo_property(typid, GTA_IS_SMALL_UDT) != 0; } + + /// Requires full qualifier? (name is not unique) + /// \param out qualifier. may be NULL + /// \param name field name + /// \param off field offset in bits + /// \return if the name is not unique, returns true + bool requires_qualifier(qstring *out, const char *name, uint64 offset) const { return name_requires_qualifier(out, typid, name, offset); } + + /// Calculate set of covered bytes for the type + /// \param out pointer to the output buffer. covered bytes will be appended to it. + bool append_covered(rangeset_t *out, uint64 offset=0) const { return append_tinfo_covered(out, typid, offset); } + + /// Calculate set of padding bytes for the type + /// \param out pointer to the output buffer; old buffer contents will be lost. + bool calc_gaps(rangeset_t *out) const { return calc_tinfo_gaps(out, typid); } + + /// Floating value or an object consisting of one floating member entirely + bool is_one_fpval(void) const { return get_onemember_type().is_floating(); } + + /// Is a SSE vector type? + bool is_sse_type(void) const { return get_tinfo_property(typid, GTA_IS_SSE_TYPE) != 0; } + + /// Is an anonymous struct/union? + /// We assume that types with names are anonymous if the name starts with $ + bool is_anonymous_udt(void) const { return get_tinfo_property(typid, GTA_IS_ANON_UDT) != 0; } + + /// Is a vftable type? + bool is_vftable(void) const { return get_tinfo_property(typid, GTA_IS_VFTABLE) != 0; } + + /// Has a vftable? + bool has_vftable(void) const { return get_tinfo_property(typid, GTA_HAS_VFTABLE) != 0; } + + /// Get enum base type (convert enum to integer type) + /// Returns ::BT_UNK if failed to convert + type_t get_enum_base_type(void) const { return (type_t)get_tinfo_property(typid, GTA_ENUM_BASE_TYPE); } + + /// For objects consisting of one member entirely: return type of the member + tinfo_t get_onemember_type(void) const { tinfo_t r; r.typid = get_tinfo_property(typid, GTA_ONEMEM_TYPE); return r; } + + /// Calculate the type score (the higher - the nicer is the type) + uint32 calc_score(void) const { return score_tinfo(this); } + + /// Get a C-like string representation of the type. + /// \param out output string + /// \param name name of type + /// \param prtype_flags \ref PRTYPE_ + /// \param indent structure level indent + /// \param cmtindent comment indent + /// \param prefix string prepended to each line + /// \param cmt comment text + /// \return success + bool print( + qstring *out, + const char *name=NULL, + int prtype_flags=PRTYPE_1LINE, + int indent=0, + int cmtindent=0, + const char *prefix=NULL, + const char *cmt=NULL) const + { + return print_tinfo(out, prefix, indent, cmtindent, prtype_flags, this, name, cmt); + } + + /// Function to facilitate debugging + const char *dstr(void) const { return dstr_tinfo(this); } + + /// Get type attributes (all_attrs: include attributes of referenced types, if any) + bool get_attrs(type_attrs_t *tav, bool all_attrs=false) const { return get_tinfo_attrs(typid, tav, all_attrs); } + + /// Get a type attribute + bool get_attr(const qstring &key, bytevec_t *bv, bool all_attrs=true) const { return get_tinfo_attr(typid, key, bv, all_attrs); } + + /// Set type attributes. If necessary, a new typid will be created. + /// this function modifies tav! (returns old attributes, if any) + /// \return false: bad attributes + bool set_attrs(type_attrs_t *tav) { return set_tinfo_attrs(this, tav); } + + /// Set a type attribute. If necessary, a new typid will be created. + bool set_attr(const type_attr_t &ta, bool may_overwrite=true) { return set_tinfo_attr(this, ta, may_overwrite); } + + /// Del all type attributes. typerefs cannot be modified by this function. + void del_attrs(void) { set_tinfo_attrs(this, NULL); } + + /// Del a type attribute. typerefs cannot be modified by this function. + bool del_attr(const qstring &key, bool make_copy=true) { return del_tinfo_attr(this, key, make_copy); } + + bool create_simple_type(type_t decl_type) { return create_type(decl_type, BT_INT, NULL); } + bool create_ptr(const ptr_type_data_t &p, type_t decl_type=BT_PTR) { return create_type(decl_type, BT_PTR|BTM_VOLATILE, (void*)&p); } + bool create_array(const array_type_data_t &p, type_t decl_type=BT_ARRAY) { return create_type(decl_type, BT_ARRAY, (void*)&p); } + bool create_bitfield(const bitfield_type_data_t &p, type_t decl_type=BT_BITFIELD) { return create_type(decl_type, BT_BITFIELD, (void*)&p); } + bool create_typedef(const typedef_type_data_t &p, type_t decl_type=BTF_TYPEDEF, bool try_ordinal=true) + { + type_t bt2 = try_ordinal ? BTF_TYPEDEF : BTF_TYPEDEF|BTM_VOLATILE; + return create_type(decl_type, bt2, (void *)&p); + } + + /// \name Convenience functions + //@{ + inline bool create_ptr(const tinfo_t &tif, uchar bps=0, type_t decl_type=BT_PTR); + inline bool create_array(const tinfo_t &tif, uint32 nelems=0, uint32 base=0, type_t decl_type=BT_ARRAY); + inline void create_typedef(const til_t *til, const char *name, type_t decl_type=BTF_TYPEDEF, bool try_ordinal=true) { get_named_type(til, name, decl_type, false, try_ordinal); } + inline void create_typedef(const til_t *til, uint ord, type_t decl_type=BTF_TYPEDEF) { get_numbered_type(til, ord, decl_type, false); } + inline bool create_bitfield(uchar nbytes, uchar width, bool is_unsigned=false, type_t decl_type=BT_BITFIELD); + //@} + + /// \name Warning + /// These functions consume 'p' (make it empty) + //@{ + bool create_udt(udt_type_data_t &p, type_t decl_type) { return create_type(decl_type, BTF_STRUCT, &p); } + bool create_enum(enum_type_data_t &p, type_t decl_type=BTF_ENUM) { return create_type(decl_type, BTF_ENUM, &p); } + bool create_func(func_type_data_t &p, type_t decl_type=BT_FUNC) { return create_type(decl_type, BT_FUNC, &p); } + //@} + + /// \name Store type + /// Store the type info in the type library as a named or numbered type. + /// The tinfo_t object will be replaced by a reference to the created type. + /// Allowed bits for ntf_flags: #NTF_NOBASE, #NTF_REPLACE + //@{ + tinfo_code_t set_named_type(til_t *til, const char *name, int ntf_flags=0) { return save_tinfo(this, til, 0, name, ntf_flags|NTF_TYPE); } + tinfo_code_t set_symbol_type(til_t *til, const char *name, int ntf_flags=0) { return save_tinfo(this, til, 0, name, ntf_flags); } // NTF_SYMM and NTF_SYMU are permitted + tinfo_code_t set_numbered_type(til_t *til, uint32 ord, int ntf_flags=0, const char *name=NULL) { return save_tinfo(this, til, ord, name, ntf_flags); } + //@} + + /// Create a forward declaration. + /// decl_type: ::BTF_STRUCT, ::BTF_UNION, or ::BTF_ENUM + tinfo_code_t create_forward_decl(til_t *til, type_t decl_type, const char *name, int ntf_flags=0) + { + create_typedef(til, "", decl_type, false); + return set_named_type(til, name, ntf_flags); + } + + /// Get stock type information. + /// This function can be used to get tinfo_t for some common types. + /// The same tinfo_t will be returned for the same id, thus saving memory + /// and increasing the speed + /// Please note that retrieving the STI_SIZE_T or STI_SSIZE_T stock type, + /// will also have the side-effect of adding that type to the 'idati' TIL, + /// under the well-known name 'size_t' or 'ssize_t' (respectively). + static tinfo_t get_stock(stock_type_id_t id) { tinfo_t t; get_stock_tinfo(&t, id); return t; } + + /// Convert an array into a pointer. + /// type[] => type * + inline bool convert_array_to_ptr(void); + + /// Replace the current type with the ptr obj or array element. + /// This function performs one of the following conversions: + /// - type[] => type + /// - type* => type + /// If the conversion is performed successfully, return true + inline bool remove_ptr_or_array(void) + { + tinfo_t tif = get_ptrarr_object(); + if ( tif.empty() ) + return false; + swap(tif); + return true; + } + + /// Change the type sign. Works only for the types that may have sign + bool change_sign(type_sign_t sign) { return set_tinfo_property(this, STA_TYPE_SIGN, sign) != 0; } + + /// Calculate the udt alignments using the field offsets/sizes and the total udt size + /// This function does not work on typerefs + bool calc_udt_aligns(int sudt_flags=SUDT_GAPS) + { return set_tinfo_property(this, STA_UDT_ALIGN, sudt_flags) != 0; } + + /// \name Bitfields + /// Helper functions to store/extract bitfield values + //@{ + uint64 read_bitfield_value(uint64 v, int bitoff) const { return read_tinfo_bitfield_value(typid, v, bitoff); } + uint64 write_bitfield_value(uint64 dst, uint64 v, int bitoff) const { return write_tinfo_bitfield_value(typid, dst, v, bitoff); } + //@} + + /// \name Modifiers + /// Work with type modifiers: const and volatile + //@{ + type_t get_modifiers(void) const { return typid & TYPE_MODIF_MASK; } + void set_modifiers(type_t mod) { if ( !empty() ) typid = (typid & ~TYPE_MODIF_MASK) | (mod & TYPE_MODIF_MASK); } + void set_const(void) { if ( !empty() ) typid |= BTM_CONST; } + void set_volatile(void) { if ( !empty() ) typid |= BTM_VOLATILE; } + void clr_const(void) { typid &= ~BTM_CONST; } + void clr_volatile(void) { typid &= ~BTM_VOLATILE; } + void clr_const_volatile(void) { typid &= ~TYPE_MODIF_MASK; } + //@} + + DECLARE_COMPARISONS(tinfo_t) + { // simple comparison: good enough to organize std::map, etc + // for this function "unsigned char" and "uchar" are different + // for deeper comparison see compare_with() + return lexcompare_tinfo(typid, r.typid, 0); + } +/// \defgroup TCMP_ tinfo_t comparison flags +/// passed as 'tcflags' parameter to tinfo_t::compare_with() +//@{ +#define TCMP_EQUAL 0x0000 ///< are types equal? +#define TCMP_IGNMODS 0x0001 ///< ignore const/volatile modifiers +#define TCMP_AUTOCAST 0x0002 ///< can t1 be cast into t2 automatically? +#define TCMP_MANCAST 0x0004 ///< can t1 be cast into t2 manually? +#define TCMP_CALL 0x0008 ///< can t1 be called with t2 type? +#define TCMP_DELPTR 0x0010 ///< remove pointer from types before comparing +#define TCMP_DECL 0x0020 ///< compare declarations without resolving them +#define TCMP_ANYBASE 0x0040 ///< accept any base class when casting +#define TCMP_SKIPTHIS 0x0080 ///< skip the first function argument in comparison +//@} + /// Compare two types, based on given flags (see \ref TCMP_) + bool compare_with(const tinfo_t &r, int tcflags=0) const { return compare_tinfo(typid, r.typid, tcflags); } + bool equals_to(const tinfo_t &r) const { return compare_with(r, 0); } + bool is_castable_to(const tinfo_t &target) const { return compare_with(target, TCMP_AUTOCAST); } + bool is_manually_castable_to(const tinfo_t &target) const { return compare_with(target, TCMP_MANCAST); } +}; +DECLARE_TYPE_AS_MOVABLE(tinfo_t); +typedef qvector<tinfo_t> tinfovec_t; ///< vector of tinfo objects + +//------------------------------------------------------------------------ +/// SIMD type info +struct simd_info_t +{ + const char *name; ///< name of SIMD type (NULL-undefined) + tinfo_t tif; ///< SIMD type (empty-undefined) + uint16 size; ///< SIMD type size in bytes (0-undefined) + type_t memtype; ///< member type + ///< BTF_INT8/16/32/64/128, BTF_UINT8/16/32/64/128 + ///< BTF_INT - integrals of any size/sign + ///< BTF_FLOAT, BTF_DOUBLE + ///< BTF_TBYTE - floatings of any size + ///< BTF_UNION - union of integral and floating types + ///< BTF_UNK - undefined + + simd_info_t(const char *nm = NULL, uint16 sz = 0, type_t memt = BTF_UNK) + : name(nm), size(sz), memtype(memt) {} + + bool match_pattern(const simd_info_t *pattern) + { + if ( pattern == NULL ) + return true; + if ( pattern->size != 0 && pattern->size != size + || pattern->name != NULL && !streq(pattern->name, name) + || !pattern->tif.empty() && !pattern->tif.compare_with(tif) ) + { + return false; + } + if ( pattern->memtype == BTF_UNK || pattern->memtype == memtype ) + return true; + return pattern->memtype == BTF_TBYTE && is_type_float(memtype) + || pattern->memtype == BTF_INT && is_type_int(memtype); + } +}; +DECLARE_TYPE_AS_MOVABLE(simd_info_t); +typedef qvector<simd_info_t> simd_info_vec_t; + +//------------------------------------------------------------------------ +/// Use func_type_data_t::guess_cc() +idaman cm_t ida_export guess_func_cc( + const func_type_data_t &fti, + int npurged, + int cc_flags); +/// Use func_type_data_t::dump() +idaman bool ida_export dump_func_type_data( + qstring *out, + const func_type_data_t &fti, + int praloc_bits); + +//------------------------------------------------------------------------ +/// Pointer type information (see tinfo_t::get_ptr_details()) +struct ptr_type_data_t // #ptr +{ + tinfo_t obj_type; ///< pointed object type + tinfo_t closure; ///< cannot have both closure and based_ptr_size + uchar based_ptr_size; + uchar taptr_bits; ///< TAH bits + tinfo_t parent; ///< Parent struct + int32 delta; ///< Offset from the beginning of the parent struct + ptr_type_data_t( + tinfo_t c=tinfo_t(), + uchar bps=0, + tinfo_t p=tinfo_t(), + int32 d=0) + : closure(c), based_ptr_size(bps), taptr_bits(0), parent(p), delta(d) {} + DEFINE_MEMORY_ALLOCATION_FUNCS() + void swap(ptr_type_data_t &r) { qswap(*this, r); } ///< Set this = r and r = this + bool operator == (const ptr_type_data_t &r) const + { + return obj_type == r.obj_type + && closure == r.closure + && based_ptr_size == r.based_ptr_size; + } + bool operator != (const ptr_type_data_t &r) const { return !(*this == r); } + bool is_code_ptr(void) const { return obj_type.is_func(); } ///< Are we pointing to code? + bool is_shifted() const { return delta != 0; } +}; +DECLARE_TYPE_AS_MOVABLE(ptr_type_data_t); + +//------------------------------------------------------------------------ +/// Array type information (see tinfo_t::get_array_details()) +struct array_type_data_t // #array +{ + tinfo_t elem_type; ///< element type + uint32 base; ///< array base + uint32 nelems; ///< number of elements + array_type_data_t(size_t b=0, size_t n=0) : base(b), nelems(n) {} ///< Constructor + DEFINE_MEMORY_ALLOCATION_FUNCS() + void swap(array_type_data_t &r) { qswap(*this, r); } ///< set this = r and r = this +}; +DECLARE_TYPE_AS_MOVABLE(array_type_data_t); + +//------------------------------------------------------------------------- +/// Information about a single function argument +struct funcarg_t +{ + argloc_t argloc; ///< argument location + qstring name; ///< argument name (may be empty) + qstring cmt; ///< argument comment (may be empty) + tinfo_t type; ///< argument type + uint32 flags = 0; ///< \ref FAI_ +/// \defgroup FAI_ Function argument property bits +/// used by funcarg_t::flags +//@{ +#define FAI_HIDDEN 0x0001 ///< hidden argument +#define FAI_RETPTR 0x0002 ///< pointer to return value. implies hidden +#define FAI_STRUCT 0x0004 ///< was initially a structure +#define FAI_ARRAY 0x0008 ///< was initially an array + ///< see "__org_typedef" or "__org_arrdim" type attributes + ///< to determine the original type +#define FAI_UNUSED 0x0010 ///< argument is not used by the function +#define TA_ORG_TYPEDEF "__org_typedef" ///< the original typedef name (simple string) +#define TA_ORG_ARRDIM "__org_arrdim" ///< the original array dimension (pack_dd) +#define TA_FORMAT "format" ///< info about the 'format' argument + ///< 3 times pack_dd: + ///< \ref format_functype_t, + ///< argument number of 'format', + ///< argument number of '...' +//@} + bool operator == (const funcarg_t &r) const + { + return argloc == r.argloc + && name == r.name +// && cmt == r.cmt + && type == r.type; + } + bool operator != (const funcarg_t &r) const { return !(*this == r); } +}; +DECLARE_TYPE_AS_MOVABLE(funcarg_t); +typedef qvector<funcarg_t> funcargvec_t; ///< vector of function argument objects + +/// Function type information (see tinfo_t::get_func_details()) +struct func_type_data_t : public funcargvec_t // #func +{ + int flags = 0; ///< \ref FTI_ +/// \defgroup FTI_ Function type data property bits +/// used by func_type_data_t::flags +//@{ +#define FTI_SPOILED 0x0001 ///< information about spoiled registers is present +#define FTI_NORET 0x0002 ///< noreturn +#define FTI_PURE 0x0004 ///< __pure +#define FTI_HIGH 0x0008 ///< high level prototype (with possibly hidden args) +#define FTI_STATIC 0x0010 ///< static +#define FTI_VIRTUAL 0x0020 ///< virtual +#define FTI_CALLTYPE 0x00C0 ///< mask for FTI_*CALL +#define FTI_DEFCALL 0x0000 ///< default call +#define FTI_NEARCALL 0x0040 ///< near call +#define FTI_FARCALL 0x0080 ///< far call +#define FTI_INTCALL 0x00C0 ///< interrupt call +#define FTI_ARGLOCS 0x0100 ///< info about argument locations has been calculated + ///< (stkargs and retloc too) +#define FTI_ALL 0x01FF ///< all defined bits +//@} + tinfo_t rettype; ///< return type + argloc_t retloc; ///< return location + uval_t stkargs = 0; ///< size of stack arguments (not used in build_func_type) + reginfovec_t spoiled; ///< spoiled register information. + ///< if spoiled register info is present, it overrides + ///< the standard spoil info (eax, edx, ecx for x86) + cm_t cc = 0; ///< calling convention + void swap(func_type_data_t &r) { qswap(*this, r); } + bool is_high(void) const { return (flags & FTI_HIGH) != 0; } + bool is_noret(void) const { return (flags & FTI_NORET) != 0; } + bool is_pure(void) const { return (flags & FTI_PURE) != 0; } + int get_call_method(void) const { return flags & FTI_CALLTYPE; } + cm_t get_cc(void) const + { + cm_t ret = ::get_cc(cc); + // if the calling convention is not specified, use the default one + if ( ret <= CM_CC_UNKNOWN ) + ret = ::get_cc(inf_get_cc_cm()); + return ret; + } + bool is_vararg_cc() const { return ::is_vararg_cc(cc); } + /// Guess function calling convention + /// use the following info: argument locations and 'stkargs' + cm_t guess_cc(int purged, int cc_flags) const + { + return guess_func_cc(*this, purged, cc_flags); + } +#define CC_CDECL_OK 0x01 ///< can use __cdecl calling convention? +#define CC_ALLOW_ARGPERM 0x02 ///< disregard argument order? +#define CC_ALLOW_REGHOLES 0x04 ///< allow holes in register argument list? +#define CC_HAS_ELLIPSIS 0x08 ///< function has a variable list of arguments? + /// Dump information that is not always visible in the function prototype. + /// (argument locations, return location, total stkarg size) + bool dump(qstring *out, int praloc_bits=PRALOC_STKOFF) const + { + return dump_func_type_data(out, *this, praloc_bits); + } + bool use_golang_abi() const { return ::use_golang_abi(get_cc()); } +}; + +/// Function index for the 'format' attribute. +enum format_functype_t +{ + FMTFUNC_PRINTF, + FMTFUNC_SCANF, + FMTFUNC_STRFTIME, + FMTFUNC_STRFMON, +}; + +//------------------------------------------------------------------------- +/// Describes an enum value +struct enum_member_t +{ + qstring name; + qstring cmt; + uint64 value; + DEFINE_MEMORY_ALLOCATION_FUNCS() + bool operator == (const enum_member_t &r) const + { + return name == r.name +// && cmt == r.cmt + && value == r.value; + } + bool operator != (const enum_member_t &r) const { return !(*this == r); } + void swap(enum_member_t &r) { qswap(*this, r); } +}; +DECLARE_TYPE_AS_MOVABLE(enum_member_t); +typedef qvector<enum_member_t> enum_member_vec_t; ///< vector of enum values + +/// Enum type information (see tinfo_t::get_enum_details()) +struct enum_type_data_t : public enum_member_vec_t // #enum +{ + intvec_t group_sizes; ///< if present, specifies bitfield group sizes + ///< each group starts with a mask member + uint32 taenum_bits; ///< \ref tattr_enum + bte_t bte; ///< enum member sizes (shift amount) and style + enum_type_data_t(bte_t _bte=BTE_ALWAYS|BTE_HEX) : taenum_bits(0), bte(_bte) {} + DEFINE_MEMORY_ALLOCATION_FUNCS() + + bool is_64bit(void) const { return (taenum_bits & TAENUM_64BIT) != 0; } + bool is_hex(void) const { return (bte & BTE_OUT_MASK) == BTE_HEX; } + bool is_char(void) const { return (bte & BTE_OUT_MASK) == BTE_CHAR; } + bool is_sdec(void) const { return (bte & BTE_OUT_MASK) == BTE_SDEC; } + bool is_udec(void) const { return (bte & BTE_OUT_MASK) == BTE_UDEC; } + int calc_nbytes(void) const + { + int emsize = bte & BTE_SIZE_MASK; + return emsize != 0 ? 1 << (emsize-1) : inf_get_cc_size_e(); + } + uint64 calc_mask(void) const { return make_mask<uint64>(calc_nbytes()*8); } + void swap(enum_type_data_t &r) { qswap(*this, r); } ///< swap two instances +}; +DECLARE_TYPE_AS_MOVABLE(enum_type_data_t); + +//------------------------------------------------------------------------- +/// Type information for typedefs +struct typedef_type_data_t // #typedef +{ + const til_t *til; ///< type library to use when resolving + union + { + const char *name; ///< is_ordref=false: target type name. we do not own this pointer! + uint32 ordinal; ///< is_ordref=true: type ordinal number + }; + bool is_ordref; ///< is reference by ordinal? + bool resolve; ///< should resolve immediately? + typedef_type_data_t(const til_t *_til, const char *_name, bool _resolve=false) + : name(_name), is_ordref(false), resolve(_resolve) { til = _til == NULL ? get_idati() : _til; } + typedef_type_data_t(const til_t *_til, uint32 ord, bool _resolve=false) + : ordinal(ord), is_ordref(true), resolve(_resolve) { til = _til == NULL ? get_idati() : _til; } + DEFINE_MEMORY_ALLOCATION_FUNCS() + void swap(typedef_type_data_t &r) { qswap(*this, r); } +}; +DECLARE_TYPE_AS_MOVABLE(typedef_type_data_t); + +//------------------------------------------------------------------------- +/// An object to represent struct or union members +struct udt_member_t // #udm +{ + uint64 offset; ///< member offset in bits + uint64 size; ///< size in bits + qstring name; ///< member name + qstring cmt; ///< member comment + tinfo_t type; ///< member type + int effalign; ///< effective field alignment (in bytes) + uint32 tafld_bits; ///< TAH bits + uchar fda; ///< field alignment (shift amount) + udt_member_t(void) + : offset(0), size(0), effalign(0), tafld_bits(0), fda(0) + { + } + bool is_bitfield(void) const { return type.is_decl_bitfield(); } + bool is_zero_bitfield(void) const { return size == 0 && is_bitfield(); } + bool is_unaligned(void) const { return (tafld_bits & TAFLD_UNALIGNED) != 0; } + bool is_baseclass(void) const { return (tafld_bits & TAFLD_BASECLASS) != 0; } + bool is_virtbase(void) const { return (tafld_bits & TAFLD_VIRTBASE) != 0; } + bool is_vftable(void) const { return (tafld_bits & TAFLD_VFTABLE) != 0; } + void set_unaligned(void) { tafld_bits |= TAFLD_UNALIGNED; } + void set_baseclass(void) { tafld_bits |= TAFLD_BASECLASS; } + void set_virtbase(void) { tafld_bits |= TAFLD_VIRTBASE; } + void set_vftable(void) { tafld_bits |= TAFLD_VFTABLE; } + void clr_unaligned(void) { tafld_bits &= ~TAFLD_UNALIGNED; } + void clr_baseclass(void) { tafld_bits &= ~TAFLD_BASECLASS; } + void clr_virtbase(void) { tafld_bits &= ~TAFLD_VIRTBASE; } + void clr_vftable(void) { tafld_bits &= ~TAFLD_VFTABLE; } + uint64 begin(void) const { return offset; } + uint64 end(void) const { return offset + size; } + bool operator < (const udt_member_t &r) const + { + return offset < r.offset; + } + bool operator == (const udt_member_t &r) const + { + return offset == r.offset + && size == r.size + && name == r.name +// && cmt == r.cmt + && type == r.type + && fda == r.fda + && tafld_bits == r.tafld_bits + && effalign == r.effalign; + } + bool operator != (const udt_member_t &r) const { return !(*this == r); } + DEFINE_MEMORY_ALLOCATION_FUNCS() + void swap(udt_member_t &r) { qswap(*this, r); } + // the user cannot enter anonymous fields in ida (they can come only from tils), + // so we use the following trick: if the field type starts with $ and the name + // with __, then we consider the field as anonymous + bool is_anonymous_udm() const + { + return name[0] == '_' && name[1] == '_' && type.is_anonymous_udt(); + } +}; +DECLARE_TYPE_AS_MOVABLE(udt_member_t); +typedef qvector<udt_member_t> udtmembervec_t; ///< vector of udt member objects + + +/// An object to represent struct or union types (see tinfo_t::get_udt_details()) +struct udt_type_data_t : public udtmembervec_t // #udt +{ + size_t total_size; ///< total structure size in bytes + size_t unpadded_size; ///< unpadded structure size in bytes + uint32 effalign; ///< effective structure alignment (in bytes) + uint32 taudt_bits; ///< TA... and TAUDT... bits + uchar sda; ///< declared structure alignment (shift amount+1). 0 - unspecified + uchar pack; ///< #pragma pack() alignment (shift amount) + bool is_union; ///< is union or struct? + + udt_type_data_t(void) + : total_size(0), unpadded_size(0), effalign(0), + taudt_bits(0), sda(0), pack(0), + is_union(false) + { + } + void swap(udt_type_data_t &r) { qswap(*this, r); } + DEFINE_MEMORY_ALLOCATION_FUNCS() + bool is_unaligned(void) const { return (taudt_bits & TAUDT_UNALIGNED) != 0; } + bool is_msstruct(void) const { return (taudt_bits & TAUDT_MSSTRUCT) != 0; } + bool is_cppobj(void) const { return (taudt_bits & TAUDT_CPPOBJ) != 0; } + bool is_vftable(void) const { return (taudt_bits & TAUDT_VFTABLE) != 0; } + void set_vftable(void) { taudt_bits |= TAUDT_VFTABLE; } + + bool is_last_baseclass(size_t idx) // we assume idx is valid + { + return at(idx).is_baseclass() + && (idx+1 == size() || !at(idx+1).is_baseclass()); + } +}; +DECLARE_TYPE_AS_MOVABLE(udt_type_data_t); + +// The type name of a virtual function table (__vftable) of a class is +// constructed by appending the following suffix to the class name. +// In the case of multiple inheritance we append the vft offset +// to the class name (with format %04X) +// Example: CLS_0024_vtbl is used for the vft located at the offset 0x24 of CLS + +#define VTBL_SUFFIX "_vtbl" + +// The member name of a virtual function table +// Complex cases are not handled yet. + +#define VTBL_MEMNAME "__vftable" + +//------------------------------------------------------------------------- +/// Bitfield type information (see tinfo_t::get_bitfield_details()) +struct bitfield_type_data_t // #bitfield +{ + uchar nbytes; ///< enclosing type size (1,2,4,8 bytes) + uchar width; ///< number of bits + bool is_unsigned; ///< is bitfield unsigned? + bitfield_type_data_t(uchar _nbytes=0, uchar _width=0, bool _is_unsigned=false) + : nbytes(_nbytes), width(_width), is_unsigned(_is_unsigned) + { + } + bool serialize(qtype *type, type_t mods) const; + DECLARE_COMPARISONS(bitfield_type_data_t) + { + if ( nbytes != r.nbytes ) + return nbytes > r.nbytes ? 1 : -1; + if ( width != r.width ) + return width > r.width ? 1 : -1; + if ( is_unsigned ) + { + if ( !r.is_unsigned ) + return 1; + } + else + { + if ( r.is_unsigned ) + return -1; + } + return 0; + } + void swap(bitfield_type_data_t &r) { qswap(*this, r); } +}; +DECLARE_TYPE_AS_MOVABLE(bitfield_type_data_t); + +//-------------------------------------------------------------------------- +// This tag can be used at the beginning of +// udt_member_t::cmt +// funcarg_t::cmt +// enum_member_t::cmt +// to specify the line number where it is defined. +// Example: "\x05123." means the line number 123 +#define TPOS_LNNUM "\x05" + +//------------------------------------------------------------------------- +// return argument alignment (which depends on ABI and natural type alignment) +inline int get_arg_align(int type_align, int slotsize) +{ + if ( type_align > slotsize*2 && !inf_huge_arg_align() ) + type_align = slotsize*2; + return type_align < slotsize + ? inf_pack_stkargs() ? type_align : slotsize + : inf_big_arg_align() ? type_align : slotsize; +} + +inline int get_arg_align(const tinfo_t &tif, int slotsize) +{ + uint32 align = 0; + tif.get_size(&align); + return get_arg_align(align, slotsize); +} + +inline sval_t align_stkarg_up(sval_t spoff, int type_align, int slotsize) +{ + uint32 align = get_arg_align(type_align, slotsize); + return align_up(spoff, align); +} + +inline sval_t align_stkarg_up(sval_t spoff, const tinfo_t &tif, int slotsize) +{ + uint32 align = get_arg_align(tif, slotsize); + return align_up(spoff, align); +} + +inline bool argloc_t::has_reg() const +{ + if ( !is_scattered() ) + return is_reg(); + for ( const auto &part : scattered() ) + if ( part.is_reg() ) + return true; + return false; +}; + +inline bool argloc_t::has_stkoff() const +{ + if ( !is_scattered() ) + return is_stkoff(); + for ( const auto &part : scattered() ) + if ( part.is_stkoff() ) + return true; + return false; +}; + +inline bool argloc_t::is_mixed_scattered() const +{ + if ( !is_scattered() ) + return false; + bool reg_found = false; + bool stkoff_found = false; + for ( const auto &part : scattered() ) + { + if ( part.is_reg() ) + reg_found = true; + if ( part.is_stkoff() ) + stkoff_found = true; + } + return reg_found && stkoff_found; +}; + +inline bool tinfo_t::get_named_type( + const til_t *til, + const char *name, + type_t decl_type, + bool resolve, + bool try_ordinal) +{ + typedef_type_data_t tp(til, name, resolve); + return create_typedef(tp, decl_type, try_ordinal); +} + +inline bool tinfo_t::get_numbered_type( + const til_t *til, + uint32 ordinal, + type_t decl_type, + bool resolve) +{ + typedef_type_data_t tp(til, ordinal, resolve); + return create_typedef(tp, decl_type, false); +} + +inline bool tinfo_t::create_ptr( + const tinfo_t &tif, + uchar bps, + type_t decl_type) +{ + ptr_type_data_t pi(tinfo_t(), bps); + pi.obj_type = tif; + return create_ptr(pi, decl_type); +} + +inline bool tinfo_t::create_array( + const tinfo_t &tif, + uint32 nelems, + uint32 base, + type_t decl_type) +{ + array_type_data_t ai(base, nelems); + ai.elem_type = tif; + return create_array(ai, decl_type); +} + +inline bool tinfo_t::create_bitfield( + uchar nbytes, + uchar width, + bool _is_unsigned, + type_t decl_type) +{ + bitfield_type_data_t bi(nbytes, width, _is_unsigned); + return create_bitfield(bi, decl_type); +} + +inline bool tinfo_t::convert_array_to_ptr(void) +{ + bool ok = false; + array_type_data_t ai; + if ( get_array_details(&ai) ) + { + ptr_type_data_t pi; + pi.obj_type.swap(ai.elem_type); + create_ptr(pi); + ok = true; + } + return ok; +} + +/// ::BT_PTR: If the current type is a pointer, return the pointed object. +/// If the current type is not a pointer, return the current type. +/// See also get_ptrarr_object() and get_pointed_object() +inline tinfo_t remove_pointer(const tinfo_t &tif) +{ + tinfo_t r; + r.typid = get_tinfo_property(tif.typid, tinfo_t::GTA_SAFE_PTR_OBJ); + return r; +} + +/// Information about how to modify the current type, used by ::tinfo_visitor_t. +struct type_mods_t +{ + tinfo_t type; ///< current type + qstring name; ///< current type name + qstring cmt; ///< comment for current type + int flags; ///< \ref TVIS_ +/// \defgroup TVIS_ Type modification bits +/// used by type_mods_t::flags +//@{ +#define TVIS_TYPE 0x0001 ///< new type info is present +#define TVIS_NAME 0x0002 ///< new name is present +#define TVIS_CMT 0x0004 ///< new comment is present +//@} + type_mods_t(void) : flags(0) {} + void clear(void) { flags = 0; } + + /// The visit_type() function may optionally save the modified type info. + /// Use the following functions for that. The new name and comment will be applied + /// only if the current tinfo element has storage for them. + void set_new_type(const tinfo_t &t) { type = t; flags |= TVIS_TYPE; } + void set_new_name(const qstring &n) { name = n; flags |= TVIS_NAME; } + void set_new_cmt(const qstring &c) { cmt = c; flags |= TVIS_CMT; } + + bool has_type(void) const { return (flags & TVIS_TYPE) != 0; } + bool has_name(void) const { return (flags & TVIS_NAME) != 0; } + bool has_cmt(void) const { return (flags & TVIS_CMT) != 0; } + bool has_info(void) const { return flags != 0; } +}; + +/// Visit all subtypes of a type. Derive your visitor from this class and use apply_to() +struct tinfo_visitor_t +{ + int state; ///< \ref TVST_ +/// \defgroup TVST_ tinfo visitor states +/// used by tinfo_visitor_t::state +//@{ +#define TVST_PRUNE 0x01 ///< don't visit children of current type +#define TVST_DEF 0x02 ///< visit type definition (meaningful for typerefs) +#define TVST_LEVEL 0x04 // has level member (internal use) +//@} + int level; // recursion level (internal use) + tinfo_visitor_t(int s=0) : state(s|TVST_LEVEL), level(0) {} + + virtual ~tinfo_visitor_t() {} + + /// Visit a subtype. + /// this function must be implemented in the derived class. + /// it may optionally fill out with the new type info. this can be used to + /// modify types (in this case the 'out' argument of apply_to() may not be NULL) + /// return 0 to continue the traversal. + /// return !=0 to stop the traversal. + virtual int idaapi visit_type( + type_mods_t *out, + const tinfo_t &tif, + const char *name, + const char *cmt) = 0; + + /// To refuse to visit children of the current type, use this: + void prune_now(void) { state |= TVST_PRUNE; } + + /// Call this function to initiate the traversal + int apply_to(const tinfo_t &tif, type_mods_t *out=NULL, const char *name=NULL, const char *cmt=NULL) + { + return visit_subtypes(this, out, tif, name, cmt); + } +}; + + +//------------------------------------------------------------------------ +// Definitions for packing/unpacking idc objects + +/// Object that represents a register +struct regobj_t +{ + int regidx; ///< index into dbg->registers + int relocate; ///< 0-plain num, 1-must relocate + bytevec_t value; + size_t size(void) const { return value.size(); } +}; +DECLARE_TYPE_AS_MOVABLE(regobj_t); +typedef qvector<regobj_t> regobjvec_t; + +struct regobjs_t : public regobjvec_t {}; /// Collection of register objects + + +/// Read a typed idc object from the database + +idaman error_t ida_export unpack_idcobj_from_idb( + idc_value_t *obj, + const tinfo_t &tif, + ea_t ea, + const bytevec_t *off0, // if !NULL: bytevec that represents object at 'ea' + int pio_flags=0); +#define PIO_NOATTR_FAIL 0x0004 ///< missing attributes are not ok +#define PIO_IGNORE_PTRS 0x0008 ///< do not follow pointers + + +/// Read a typed idc object from the byte vector + +idaman error_t ida_export unpack_idcobj_from_bv( + idc_value_t *obj, + const tinfo_t &tif, + const bytevec_t &bytes, + int pio_flags=0); + + +/// Write a typed idc object to the database + +idaman error_t ida_export pack_idcobj_to_idb( + const idc_value_t *obj, + const tinfo_t &tif, + ea_t ea, + int pio_flags=0); + + +/// Write a typed idc object to the byte vector. +/// Byte vector may be non-empty, this function will append data to it + +idaman error_t ida_export pack_idcobj_to_bv( + const idc_value_t *obj, + const tinfo_t &tif, + relobj_t *bytes, + void *objoff, // NULL - append object to 'bytes' + // if not NULL: + // in: int32*: offset in 'bytes' for the object + // -1 means 'do not store the object itself in bytes + // store only pointed objects' + // out: data for object (if *(int32*)objoff == -1) + int pio_flags=0); + + +/// Helper function for the processor modules. +/// to be called from \ph{use_stkarg_type} + +idaman bool ida_export apply_tinfo_to_stkarg( + const insn_t &insn, + const op_t &x, + uval_t v, + const tinfo_t &tif, + const char *name); + +//------------------------------------------------------------------------ +// Helper struct for the processor modules: process call arguments +struct argtinfo_helper_t +{ + size_t reserved = 0; + + virtual ~argtinfo_helper_t() {} + + /// Set the operand type as specified + virtual bool idaapi set_op_tinfo( + const insn_t &insn, + const op_t &x, + const tinfo_t &tif, + const char *name) = 0; + + /// Is the current insn a stkarg load?. + /// if yes: + /// - src: index of the source operand in \insn_t{ops} + /// - dst: index of the destination operand in \insn_t{ops} + /// \insn_t{ops}[dst].addr is expected to have the stack offset + virtual bool idaapi is_stkarg_load(const insn_t &insn, int *src, int *dst) = 0; + + /// The call instruction with a delay slot?. + virtual bool idaapi has_delay_slot(ea_t /*caller*/) { return false; } + + /// This function is to be called by the processor module in response + /// to ev_use_arg_types. + inline void use_arg_tinfos(ea_t caller, func_type_data_t *fti, funcargvec_t *rargs); +}; + +/// Do not call this function directly, use argtinfo_helper_t +idaman void ida_export gen_use_arg_tinfos2( + struct argtinfo_helper_t *_this, + ea_t caller, + func_type_data_t *fti, + funcargvec_t *rargs); + +inline void argtinfo_helper_t::use_arg_tinfos( + ea_t caller, + func_type_data_t *fti, + funcargvec_t *rargs) +{ + gen_use_arg_tinfos2(this, caller, fti, rargs); +} + +//------------------------------------------------------------------------- + +/// Looks for a hole at the beginning of the stack arguments. Will make use +/// of the IDB's func_t function at that place (if present) to help determine +/// the presence of such a hole. + +idaman bool ida_export func_has_stkframe_hole(ea_t ea, const func_type_data_t &fti); + +//------------------------------------------------------------------------- +/// Interface class - see ::ida_lowertype_helper_t +class lowertype_helper_t +{ +public: + virtual bool idaapi func_has_stkframe_hole( + const tinfo_t &candidate, + const func_type_data_t &candidate_data) = 0; + + virtual int idaapi get_func_purged_bytes( + const tinfo_t &candidate, + const func_type_data_t &candidate_data) = 0; +}; + +//------------------------------------------------------------------------- +/// An implementation of ::lowertype_helper_t that has access to the +/// IDB, and thus can help spot holes in the stack arguments. +class ida_lowertype_helper_t : public lowertype_helper_t +{ + const tinfo_t &tif; + ea_t ea; + int purged_bytes; + +public: + ida_lowertype_helper_t(const tinfo_t &_tif, ea_t _ea, int _pb) + : tif(_tif), ea(_ea), purged_bytes(_pb) {} + + virtual bool idaapi func_has_stkframe_hole( + const tinfo_t &candidate, + const func_type_data_t &candidate_data) override + { + return candidate == tif + ? ::func_has_stkframe_hole(ea, candidate_data) + : false; + } + + virtual int idaapi get_func_purged_bytes( + const tinfo_t &candidate, + const func_type_data_t &) override + { + return candidate == tif + ? purged_bytes + : -1; + } +}; + +//------------------------------------------------------------------------- +/// Lower type. +/// Inspect the type and lower all function subtypes using lower_func_type(). \n +/// We call the prototypes usually encountered in source files "high level" \n +/// They may have implicit arguments, array arguments, big structure retvals, etc \n +/// We introduce explicit arguments (i.e. 'this' pointer) and call the result \n +/// "low level prototype". See #FTI_HIGH. +/// +/// In order to improve heuristics for recognition of big structure retvals, \n +/// it is recommended to pass a helper that will be used to make decisions. \n +/// That helper will be used only for lowering 'tif', and not for the children \n +/// types walked through by recursion. +/// \retval 1 removed #FTI_HIGH, +/// \retval 2 made substantial changes +/// \retval -1 failure + +idaman int ida_export lower_type( + til_t *til, + tinfo_t *tif, + const char *name=NULL, + lowertype_helper_t *_helper=NULL); + + +/// Replace references to ordinal types by name references. +/// This function 'unties' the type from the current local type library +/// and makes it easier to export it. +/// \param til type library to use. may be NULL. +/// \param tif type to modify (in/out) +/// \retval number of replaced subtypes, -1 on failure + +idaman int ida_export replace_ordinal_typerefs(til_t *til, tinfo_t *tif); + + +/// See begin_type_updating() +enum update_type_t +{ + UTP_ENUM, + UTP_STRUCT, +}; + +/// Mark the beginning of a large update operation on the types. +/// Can be used with add_enum_member(), add_struc_member, etc... +/// Also see end_type_updating() + +idaman void ida_export begin_type_updating(update_type_t utp); + + +/// Mark the end of a large update operation on the types (see begin_type_updating()) + +idaman void ida_export end_type_updating(update_type_t utp); + +//-------------------------------------------------------------------------- +/// See format_cdata() +struct format_data_info_t +{ + int ptvf; /// \ref PTV_ +/// \defgroup PTV_ C data formatting properties +/// used by format_data_info_t::ptvf +//@{ +#define PTV_DEREF 0x0001 ///< take value to print from the debugged process. + ///< #VT_LONG: the address is specified by idc_value_t::num + ///< #VT_PVOID: argloc_t is pointed by idc_value_t::pvoid +#define PTV_QUEST 0x0002 ///< print '?' for uninited data +#define PTV_EMPTY 0x0004 ///< return empty string for uninited data + ///< should not specify PTV_QUEST and PTV_EMPTY together +#define PTV_CSTR 0x0008 ///< print constant strings inline +#define PTV_EXPAND 0x0010 ///< print only top level on separate lines + ///< max_length applies to separate lines + ///< margin is ignored +#define PTV_LZHEX 0x0020 ///< print hex numbers with leading zeroes +#define PTV_STPFLT 0x0040 ///< fail on bad floating point numbers + ///< (if not set, just print ?flt for them) +#define PTV_SPACE 0x0080 ///< add spaces after commas and around braces +#define PTV_DEBUG 0x0100 ///< format output for debugger +#define PTV_NOPTR 0x0200 ///< prevent pointer values from appearing in the output +#define PTV_NTOP 0x40000000 ///< internal flag, do not use +#define PTV_KEEP 0x80000000 ///< internal flag, do not use +//@} + int radix; ///< number representation (8,10,16) + int max_length; ///< max length of the formatted text (0 means no limit) + ///< should be used to format huge arrays for the screen, + ///< we cannot display the whole array anyway + ///< if this limit is hit, the function returns false + ///< and qerrno is set to eMaxLengthExceeded + int arrbase; ///< for arrays: the first element of array to print + int arrnelems; ///< for arrays: number of elements to print + int margin; ///< length of one line (0 means to print everything on one line) + ///< if an item cannot be printed in a shorter way, + ///< some output lines can be considerably longer + ///< 1 means each item on its own line + int indent; ///< how many spaces to use to indent nested structures/arrays + + format_data_info_t(void) + : ptvf(PTV_EMPTY|PTV_CSTR|PTV_SPACE), radix(10), max_length(0), + arrbase(0), arrnelems(0), + margin(80), indent(2) {} +}; + +/// Additional information about the output lines +struct valinfo_t +{ + argloc_t loc; + qstring label; + tinfo_t type; + valinfo_t(argloc_t l=argloc_t(), const char *name=NULL, const tinfo_t &tif=tinfo_t()) + : loc(l), label(name), type(tif) {} + void swap(valinfo_t &r) + { + loc.swap(r.loc); + label.swap(r.label); + type.swap(r.type); + } + DEFINE_MEMORY_ALLOCATION_FUNCS() +}; +DECLARE_TYPE_AS_MOVABLE(valinfo_t); + + +/// Text representation of a data value (value string). +/// This structure is used before we decide how to represent it, +/// on one line or on many lines +class valstr_t +{ +public: + qstring oneline; ///< result if printed on one line in UTF-8 encoding + size_t length; ///< length if printed on one line + struct valstrs_t *members; ///< strings for members, each member separately + valinfo_t *info; ///< additional info + int props; ///< temporary properties, used internally +#define VALSTR_OPEN 0x01 ///< printed opening curly brace '{' + + valstr_t(void) : length(0), members(NULL), info(NULL), props(0) {} + ~valstr_t(void); + DEFINE_MEMORY_ALLOCATION_FUNCS() +private: + struct flatten_args_t + { + const valstr_t *may_not_collapse; + int ptvf; + int max_length; + int margin; + int indent; + }; + friend struct valstr_sink_t; + void update_length(int ptvf); + void set_oneline(const char *line, int len) + { + oneline.append(line, len); + length = oneline.length(); + } + void consume_oneline(const qstring &line) + { + oneline.append(line); + length = oneline.length(); + } + bool append_char(char c, int max_length); + bool convert_to_one_line(int ptvf, int max_length); + bool flatten(const flatten_args_t &flargs, int level); +}; +DECLARE_TYPE_AS_MOVABLE(valstr_t); +typedef qvector<valstr_t> valstrvec_t; + +struct valstrs_t : public valstrvec_t {}; ///< Collection of value strings + +inline valstr_t::~valstr_t(void) +{ + delete members; + delete info; +} + + +/// Format a data value as a C initializer. +/// \param outvec buffer for the formatted string(s). may be NULL +/// \param idc_value value to format +/// \param tif type of the data to format. +/// if NULL and #PTV_DEREF is specified, take tinfo from idb +/// \param vtree more detailed output info +/// \param fdi formatting options +/// \return success. if failed, see qerrno for more info + +idaman bool ida_export format_cdata( + qstrvec_t *outvec, + const idc_value_t &idc_value, + const tinfo_t *tif, + valstr_t *vtree=NULL, + const format_data_info_t *fdi=NULL); + +/// Flush formatted text +struct text_sink_t +{ + /// \return 0-ok, otherwise print_cdata will stop + virtual int idaapi print(const char *str) = 0; +}; + + +/// The same as format_cdata(), but instead of returning the answer in a vector, print it. +/// This function can handle very huge data volume without using too much memory. +/// As soon as the output text becomes too long, the function prints it and +/// flushes its internal buffers. +/// \retval 0 ok +/// \retval -1 printing failed, check qerrno +/// \retval else code returned by text_sink_t::print() + +idaman int ida_export print_cdata( + text_sink_t &printer, + const idc_value_t &idc_value, + const tinfo_t *tif, + const format_data_info_t *fdi=NULL); + +//------------------------------------------------------------------------- +#define PDF_INCL_DEPS 0x1 ///< Include all type dependencies +#define PDF_DEF_FWD 0x2 ///< Allow forward declarations +#define PDF_DEF_BASE 0x4 ///< Include base types: __int8, __int16, etc.. +#define PDF_HEADER_CMT 0x8 ///< Prepend output with a descriptive comment + +typedef qvector<uint32> ordvec_t; + +/// Print types (and possibly their dependencies) in a format suitable +/// for use in a header file. This is the reverse parse_decls(). +/// \param printer a handler for printing text +/// \param til the type library holding the ordinals +/// \param ordinals ordinals of types to export. NULL means: all ordinals in til +/// \param flags flags for the algorithm. A combination of PDF_* constants +/// \retval >0 the number of types exported +/// \retval 0 an error occurred +/// \retval <0 the negated number of types exported. There were minor errors +/// and the resulting output might not be compilable. + +idaman int ida_export print_decls( + text_sink_t &printer, + til_t *til, + const ordvec_t *ordinals, + uint32 flags); + + +/// Calculate max number of lines of a formatted c data, when expanded (#PTV_EXPAND). +/// \param loc location of the data (::ALOC_STATIC or ::ALOC_CUSTOM) +/// \param tif type info +/// \param dont_deref_ptr consider 'ea' as the ptr value +/// \retval 0 data is not expandable +/// \retval -1 error, see qerrno +/// \retval else the max number of lines + +idaman int ida_export calc_number_of_children( + const argloc_t &loc, + const tinfo_t &tif, + bool dont_deref_ptr=false); + + +/// Format a C number. +/// \param buf output buffer +/// \param bufsize size of the output buffer +/// \param value number to format +/// \param size size of the number in bytes (1,2,4,8,16) +/// \param pcn combination of \ref PCN_ + +idaman size_t ida_export format_c_number( + char *buf, + size_t bufsize, + uint128 value, + int size, + int pcn=0); + +/// \defgroup PCN_ C Number formatting flags +/// passed as 'pcn' parameter to format_c_number() +//@{ +#define PCN_RADIX 0x07 ///< number base to use +#define PCN_DEC 0x00 ///< decimal +#define PCN_HEX 0x01 ///< hexadecimal +#define PCN_OCT 0x02 ///< octal +#define PCN_CHR 0x03 ///< character +#define PCN_UNSIGNED 0x08 ///< add 'u' suffix +#define PCN_LZHEX 0x10 ///< print leading zeroes for hexdecimal number +#define PCN_NEGSIGN 0x20 ///< print negated value (-N) for negative numbers +#define PCN_DECSEXT 0x40 ///< automatically extend sign of signed decimal numbers +//@} + + +/// Return a C expression that can be used to represent an enum member. +/// If the value does not correspond to any single enum member, this function tries +/// to find a bitwise combination of enum members that correspond to it. +/// If more than half of value bits do not match any enum members, it fails. +/// \param buf output buffer +/// \param tif enumeration type +/// \param serial which enumeration member to use (0 means the first with the given value) +/// \param value value to search in the enumeration type. only 32-bit number can be handled yet +/// \return success + +idaman bool ida_export get_enum_member_expr( + qstring *buf, + const tinfo_t &tif, + int serial, + uint64 value); + +inline bool idaapi is_autosync(const char *name, const tinfo_t &tif) +{ + type_t decl_type = tif.get_decltype(); + return get_ordinal_from_idb_type(name, &decl_type) != -1; +} + +//------------------------------------------------------------------------- +// Dialogs to choose a symbol from a type library +//------------------------------------------------------------------------ + +/// A symbol in a type library +struct til_symbol_t +{ + const char *name; ///< symbol name + const til_t *til; ///< pointer to til + til_symbol_t(const char *n = NULL, const til_t *t = NULL): name(n), til(t) {} +}; +DECLARE_TYPE_AS_MOVABLE(til_symbol_t); + + +/// Helper class for choose_named_type(). +/// Controls which types are displayed when choosing types. + +struct predicate_t +{ + virtual bool idaapi should_display( + const til_t *til, + const char *name, + const type_t *type, + const p_list *fields) = 0; + virtual ~predicate_t() {} +}; + + +/// Choose a type from a type library. +/// \param out_sym pointer to be filled with the chosen type +/// \param root_til pointer to starting til (the function will inspect the base tils if allowed by flags) +/// \param title title of listbox to display +/// \param ntf_flags combination of \ref NTF_ +/// \param predicate predicate to select types to display (maybe NULL) +/// \return false if nothing is chosen, otherwise true + +idaman bool ida_export choose_named_type( + til_symbol_t *out_sym, + const til_t *root_til, + const char *title, + int ntf_flags, + predicate_t *predicate=NULL); + + +/// Controls which types are displayed/selected when choosing local types. +/// \retval 0 skip type +/// \retval 1 include + +typedef int idaapi local_tinfo_predicate_t(uint32 ord, const tinfo_t &type, void *ud); + + +/// Choose a type from the local type library. +/// \param ti pointer to til +/// \param title title of listbox to display +/// \param func predicate to select types to display (maybe NULL) +/// \param def_ord ordinal to position cursor before choose +/// \param ud user data +/// \return == 0 means nothing is chosen, otherwise an ordinal number + +idaman uint32 ida_export choose_local_tinfo( + const til_t *ti, + const char *title, + local_tinfo_predicate_t *func = NULL, + uint32 def_ord = 0, + void *ud = NULL); + + +/// Choose a type from the local type library and specify the pointer shift value. +/// \param delta pointer shift value +/// \param ti pointer to til +/// \param title title of listbox to display +/// \param func predicate to select types to display (maybe NULL) +/// \param def_ord ordinal to position cursor before choose +/// \param ud user data +/// \return == 0 means nothing is chosen, otherwise an ordinal number + +idaman uint32 ida_export choose_local_tinfo_and_delta( + int32 *delta, + const til_t *ti, + const char *title, + local_tinfo_predicate_t *func = NULL, + uint32 def_ord = 0, + void *ud = NULL); + + +#ifndef NO_OBSOLETE_FUNCS +typedef bool idaapi set_op_tinfo_t(const insn_t &insn, const op_t &x, const tinfo_t &type, const char *name); +typedef bool idaapi is_stkarg_load_t(const insn_t &insn, int *src, int *dst); +typedef bool idaapi has_delay_slot_t(ea_t caller); +idaman DEPRECATED void ida_export gen_use_arg_tinfos(ea_t caller, func_type_data_t *fti, funcargvec_t *rargs, set_op_tinfo_t *set_optype, is_stkarg_load_t *is_stkarg_load, has_delay_slot_t *has_delay_slot); // gen_use_arg_tinfos2 +#endif + +#endif // _TYPEINF_HPP diff --git a/idasdk76/include/ua.hpp b/idasdk76/include/ua.hpp new file mode 100644 index 0000000..cb5b7ff --- /dev/null +++ b/idasdk76/include/ua.hpp @@ -0,0 +1,1470 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _UA_HPP +#define _UA_HPP + +#include <kernwin.hpp> // for btoa() +#include <lines.hpp> // for colors +#include <xref.hpp> // add_cref() +#include <bytes.hpp> // get_byte(), ... + +/*! \file ua.hpp + + \brief Functions that deal with the disassembling of program instructions. + + There are 2 kinds of functions: + - functions that are called from the kernel + to disassemble an instruction. These functions + call IDP module for it. + - functions that are called from IDP module to + disassemble an instruction. We will call them + 'helper functions'. + + Disassembly of an instruction is made in three steps: + -# analysis: ana.cpp + -# emulation: emu.cpp + -# conversion to text: out.cpp + + The kernel calls the IDP module to perform these steps. + At first, the kernel always calls the analysis. The analyzer + must decode the instruction and fill the insn_t instance + that it receives through its callback. + It must not change anything in the database. + + The second step, the emulation, is called for each instruction. + This step must make necessary changes to the database, + plan analysis of subsequent instructions, track register + values, memory contents, etc. Please keep in mind that the kernel may call + the emulation step for any address in the program - there is no + ordering of addresses. Usually, the emulation is called + for consecutive addresses but this is not guaranteed. + + The last step, conversion to text, is called each time an instruction + is displayed on the screen. The kernel will always call the analysis step + before calling the text conversion step. + The emulation and the text conversion steps should use the information stored + in the insn_t instance they receive. They should not access the bytes + of the instruction and decode it again - this should only be done in + the analysis step. +*/ + +struct procmod_t; +struct processor_t; +struct asm_t; + +/// \defgroup operands Operands +/// Work with instruction operands + +//-------------------------------------------------------------------------- +// T Y P E O F O P E R A N D +//-------------------------------------------------------------------------- +typedef uchar optype_t; ///< see \ref o_ +/// \defgroup o_ Operand types +/// \ingroup operands +/// +/// Various types of instruction operands. +/// The kernel already knows about some operand types and associates them +/// with fields in ::op_t. +/// +/// IDA also allows you define processor specific operand types (o_idpspec...). +/// You are free to give any meaning to these types. We suggest you to create a +/// #define to use mnemonic names. However, don't forget that the kernel will +/// know nothing about operands of those types. +/// You may use any additional fields of ::op_t to store +/// processor specific operand information. +//@{ +const optype_t + o_void = 0, ///< No Operand. + o_reg = 1, ///< General Register (al,ax,es,ds...). + o_mem = 2, ///< Direct Memory Reference (DATA). + o_phrase = 3, ///< Memory Ref [Base Reg + Index Reg]. + o_displ = 4, ///< Memory Ref [Base Reg + Index Reg + Displacement]. + o_imm = 5, ///< Immediate Value. + o_far = 6, ///< Immediate Far Address (CODE). + o_near = 7, ///< Immediate Near Address (CODE). + o_idpspec0 = 8, ///< processor specific type. + o_idpspec1 = 9, ///< processor specific type. + o_idpspec2 = 10, ///< processor specific type. + o_idpspec3 = 11, ///< processor specific type. + o_idpspec4 = 12, ///< processor specific type. + o_idpspec5 = 13; ///< processor specific type. + ///< (there can be more processor specific types) +//@} + +/// \var o_reg +/// The register number should be stored in op_t::reg. +/// All processor registers, including special registers, can be +/// represented by this operand type. +/// +/// \var o_mem +/// A direct memory data reference whose target address is known at compilation time. +/// The target virtual address is stored in op_t::addr and the full address +/// is calculated as to_ea( \insn_t{cs}, op_t::addr ). For the processors with +/// complex memory organization the final address can be calculated +/// using other segment registers. For flat memories, op_t::addr is the final +/// address and \insn_t{cs} is usually equal to zero. In any case, the address +/// within the segment should be stored in op_t::addr. +/// +/// \var o_phrase +/// A memory reference using register contents. Indexed, register based, +/// and other addressing modes can be represented with the operand type. +/// This addressing mode cannot contain immediate values (use ::o_displ instead). +/// The phrase number should be stored in op_t::phrase. To denote the pre-increment +/// and similar features please use additional operand fields like op_t::specflag... +/// Usually op_t::phrase contains the register number and additional information +/// is stored in op_t::specflags... Please note that this operand type cannot +/// contain immediate values (except the scaling coefficients). +/// +/// \var o_displ +/// A memory reference using register contents with displacement. +/// The displacement should be stored in the op_t::addr field. The rest of information +/// is stored the same way as in ::o_phrase. +/// +/// \var o_imm +/// Any operand consisting of only a number is represented by this operand type. +/// The value should be stored in op_t::value. You may sign extend short (1-2 byte) values. +/// In any case don't forget to specify op_t::dtype (should be set for all operand types). +/// +/// \var o_far +/// If the current processor has a special addressing mode for inter-segment +/// references, then this operand type should be used instead of ::o_near. +/// If you want, you may use #PR_CHK_XREF in \ph{flag} to disable inter-segment +/// calls if ::o_near operand type is used. Currently only IBM PC uses this flag. +/// +/// \var o_near +/// A direct memory code reference whose target address is known at the compilation time. +/// The target virtual address is stored in op_t::addr and the final address +/// is always to_ea(\insn_t{cs}, op_t::addr). Usually this operand type is used for +/// the branches and calls whose target address is known. If the current +/// processor has 2 different types of references for inter-segment and intra-segment +/// references, then this should be used only for intra-segment references. +/// +/// If the above operand types do not cover all possible addressing modes, +/// then use o_idpspec... operand types. + +//-------------------------------------------------------------------------- +// O P E R A N D O F I N S T R U C T I O N +//-------------------------------------------------------------------------- +/// \defgroup operands_t Operand structure +/// \ingroup operands +/// Definition of ::op_t and related items. + +/// Operand of an instruction. \ingroup operands_t +/// This structure is filled by the analyzer. +/// Upon entrance to the analyzer, some fields of this structure are initialized: +/// - #type: ::o_void +/// - #offb: 0 +/// - #offo: 0 +/// - #flags: #OF_SHOW +class op_t +{ +public: + + /// Number of operand (0,1,2). Initialized once at the start of work. + /// You have no right to change its value. + uchar n = 0; + + /// Type of operand (see \ref o_) + optype_t type = o_void; + + /// Offset of operand value from the instruction start (0 means unknown). + /// Of course this field is meaningful only for certain types of operands. + /// Leave it equal to zero if the operand has no offset. + /// This offset should point to the 'interesting' part of operand. + /// For example, it may point to the address of a function in + /// \v{call func} + /// or it may point to bytes holding '5' in + /// \v{mov ax, [bx+5]} + /// Usually bytes pointed to this offset are relocated (have fixup information). + char offb = 0; + + /// Same as #offb (some operands have 2 numeric values used to form an operand). + /// This field is used for the second part of operand if it exists. + /// Currently this field is used only for outer offsets of Motorola processors. + /// Leave it equal to zero if the operand has no offset. + char offo = 0; + + uchar flags = 0; ///< \ref OF_ +/// \defgroup OF_ Operand flags +/// \ingroup operands_t +/// Used by op_t::flags +//@{ +#define OF_NO_BASE_DISP 0x80 ///< base displacement doesn't exist. + ///< meaningful only for ::o_displ type. + ///< if set, base displacement (op_t::addr) + ///< doesn't exist. +#define OF_OUTER_DISP 0x40 ///< outer displacement exists. + ///< meaningful only for ::o_displ type. + ///< if set, outer displacement (op_t::value) exists. +#define PACK_FORM_DEF 0x20 ///< packed factor defined. + ///< (!::o_reg + #dt_packreal) +#define OF_NUMBER 0x10 ///< the operand can be converted to a number only +#define OF_SHOW 0x08 ///< should the operand be displayed? +//@} + + /// Set operand to be shown + void set_shown() { flags |= OF_SHOW; } + /// Set operand to hidden + void clr_shown() { flags &= ~OF_SHOW; } + /// Is operand set to be shown? + bool shown() const { return (flags & OF_SHOW) != 0; } + + /// Type of operand value (see \ref dt_). Usually first 9 types are used. + /// This is the type of the operand itself, not the size of the addressing mode. + /// for example, byte ptr [epb+32_bit_offset] will have #dt_byte type. + op_dtype_t dtype = 0; +/// \defgroup dt_ Operand value types +/// \ingroup operands_t +/// Used by op_t::dtype +//@{ +// from here.. +#define dt_byte 0 ///< 8 bit integer +#define dt_word 1 ///< 16 bit integer +#define dt_dword 2 ///< 32 bit integer +#define dt_float 3 ///< 4 byte floating point +#define dt_double 4 ///< 8 byte floating point +#define dt_tbyte 5 ///< variable size (\ph{tbyte_size}) floating point +#define dt_packreal 6 ///< packed real format for mc68040 +// ...to here the order should not be changed, see mc68000 +#define dt_qword 7 ///< 64 bit integer +#define dt_byte16 8 ///< 128 bit integer +#define dt_code 9 ///< ptr to code (not used?) +#define dt_void 10 ///< none +#define dt_fword 11 ///< 48 bit +#define dt_bitfild 12 ///< bit field (mc680x0) +#define dt_string 13 ///< pointer to asciiz string +#define dt_unicode 14 ///< pointer to unicode string +#define dt_ldbl 15 ///< long double (which may be different from tbyte) +#define dt_byte32 16 ///< 256 bit integer +#define dt_byte64 17 ///< 512 bit integer +#define dt_half 18 ///< 2-byte floating point +//@} + + // REG + union + { + uint16 reg; ///< number of register (::o_reg) + uint16 phrase; ///< number of register phrase (::o_phrase,::o_displ). + ///< you yourself define numbers of phrases + ///< as you like + }; + + /// Is register operand? + bool is_reg(int r) const { return type == o_reg && reg == r; } + + // Next 12 bytes are used by mc68k for some float types + + // VALUE + union + { + uval_t value; ///< operand value (::o_imm) or + ///< outer displacement (::o_displ+#OF_OUTER_DISP). + ///< integer values should be in IDA's (little-endian) order. + ///< when using ieee_realcvt(), floating point values should be in the processor's native byte order. + ///< #dt_double and #dt_qword values take up 8 bytes (value and addr fields for 32-bit modules). + ///< NB: in case a #dt_dword/#dt_qword immediate is forced to float by user, + ///< the kernel converts it to processor's native order before calling FP conversion routines. + + /// This structure is defined for + /// your convenience only + struct + { + uint16 low; + uint16 high; + } value_shorts; + }; + + /// Is immediate operand? + bool is_imm(uval_t v) const { return type == o_imm && value == v; } + + // VIRTUAL ADDRESS (offset within the segment) + union + { + ea_t addr; ///< virtual address pointed or used by the operand. + ///< (::o_mem,::o_displ,::o_far,::o_near) + + /// This structure is defined for + /// your convenience only + struct + { + uint16 low; + uint16 high; + } addr_shorts; + }; + + // IDP SPECIFIC INFORMATION + union + { + ea_t specval; ///< This field may be used as you want. + /// This structure is defined for + /// your convenience only + struct + { + uint16 low; ///< IBM PC: segment register number (::o_mem,::o_far,::o_near) + uint16 high; ///< IBM PC: segment selector value (::o_mem,::o_far,::o_near) + } specval_shorts; + }; + + /// \name Special flags + /// The following fields are used only in idp modules. + /// You may use them as you want to store additional information about + /// the operand. + //@{ + char specflag1 = 0; + char specflag2 = 0; + char specflag3 = 0; + char specflag4 = 0; + //@} +}; + + +//-------------------------------------------------------------------------- +// I N S T R U C T I O N +//-------------------------------------------------------------------------- +/// \defgroup instruction Instruction +/// Definition of ::insn_t and related items. + +/// Structure to hold information about an instruction. \ingroup instruction +/// This structure is filled by the analysis step of IDP and used by +/// the emulation and conversion to text steps. The kernel uses this structure too. +/// All structure fields except #cs, #ip, #ea, and op_t::n,op_t::flags of #ops +/// are initialized to zero by the kernel. The rest should be filled by ana(). + +class insn_t; +#define DECLARE_INSN_HELPERS(decl) \ +decl bool ida_export insn_create_op_data(const insn_t &insn, ea_t ea, int opoff, op_dtype_t dtype); \ +decl void ida_export insn_add_cref(const insn_t &insn, ea_t to, int opoff, cref_t type); \ +decl void ida_export insn_add_dref(const insn_t &insn, ea_t to, int opoff, dref_t type); \ +decl ea_t ida_export insn_add_off_drefs(const insn_t &insn, const op_t &x, dref_t type, int outf); \ +decl bool ida_export insn_create_stkvar(const insn_t &insn, const op_t &x, adiff_t v, int flags); + +DECLARE_INSN_HELPERS(idaman) + +//-V:insn_t:730 not all members of a class are initialized inside the constructor +class insn_t +{ +public: + insn_t() : ea(BADADDR), itype(0), size(0) {} + + /// Current segment base paragraph. Initialized by the kernel. + ea_t cs; + + /// Virtual address of the instruction (address within the segment). + /// Initialized by the kernel. + ea_t ip; + + /// Linear address of the instruction. + /// Initialized by the kernel. + ea_t ea; + + /// Internal code of instruction (only for canonical insns - not user defined!). + /// IDP should define its own instruction codes. These codes are usually + /// defined in ins.hpp. The array of instruction names and features (ins.cpp) + /// is accessed using this code. + uint16 itype; + + inline bool is_canon_insn(const processor_t &ph) const; ///< see \ph{is_canon_insn()} + inline uint32 get_canon_feature(const processor_t &ph) const; ///< see instruc_t::feature + inline const char *get_canon_mnem(const processor_t &ph) const; ///< see instruc_t::name + + /// Size of instruction in bytes. + /// The analyzer should put here the actual size of the instruction. + uint16 size; + + union + { + uint32 auxpref; ///< processor dependent field + uint16 auxpref_u16[2]; + uint8 auxpref_u8[4]; + }; + /*u*/ char segpref; ///< processor dependent field + /*u*/ char insnpref; ///< processor dependent field + + /*u*/ int16 flags; ///< \ref INSN_ + + op_t ops[UA_MAXOP]; ///< array of operands + + /// \defgroup Op_ Operand shortcuts + /// \ingroup instruction + /// Used for accessing members of insn_t::ops + //@{ + #define Op1 ops[0] ///< first operand + #define Op2 ops[1] ///< second operand + #define Op3 ops[2] ///< third operand + #define Op4 ops[3] ///< fourth operand + #define Op5 ops[4] ///< fifth operand + #define Op6 ops[5] ///< sixth operand + #define Op7 ops[6] ///< seventh operand + #define Op8 ops[7] ///< eighth operand + //@} + +/// \defgroup INSN_ Instruction flags +/// \ingroup instruction +/// Used by insn_t::flags +//@{ +#define INSN_MACRO 0x01 ///< macro instruction +#define INSN_MODMAC 0x02 ///< may modify the database to make room for the macro insn +#define INSN_64BIT 0x04 ///< belongs to 64bit segment? +//@} + + /// Is a macro instruction? + bool is_macro(void) const { return (flags & INSN_MACRO) != 0; } + + /// Belongs to a 64bit segment? +#ifdef __EA64__ + bool is_64bit(void) const { return (flags & INSN_64BIT) != 0; } +#else + bool is_64bit(void) const { return false; } +#endif + + /// \name Analysis helpers + /// The following functions return the next byte, 2 bytes, 4 bytes, + /// and 8 bytes of insn. They use and modify the size field (\insn_t{size}). + /// Normally they are used in the analyzer to get bytes of the instruction. + /// \warning These methods work only for normal (8bit) byte processors! + //@{ + uint8 get_next_byte() + { + uint8 x = get_byte(ea + size); + size += 1; + return x; + } + uint16 get_next_word() + { + uint16 x = get_word(ea + size); + size += 2; + return x; + } + uint32 get_next_dword() + { + uint32 x = get_dword(ea + size); + size += 4; + return x; + } + uint64 get_next_qword() + { + uint64 x = get_qword(ea + size); + size += 8; + return x; + } + //@} + + /// \name Emulator helpers + //@{ + + /// Convert to data using information about operand value type (op_t::dtype). + /// Emulator could use this function to convert unexplored bytes to data + /// when an instruction references them. + /// This function creates data only if the address was unexplored. + /// \param ea linear address to be converted to data + /// \param opoff offset of the operand from the start of instruction + /// if the offset is unknown, then 0 + /// \param dtype operand value type (from op_t::dtype) + /// \retval true ok + /// \retval false failed to create data item + + bool create_op_data(ea_t ea_, int opoff, op_dtype_t dtype) const + { + return insn_create_op_data(*this, ea_, opoff, dtype); + } + + /// Convenient alias + bool create_op_data(ea_t ea_, const op_t &op) const + { + return insn_create_op_data(*this, ea_, op.offb, op.dtype); + } + + + /// Create or modify a stack variable in the function frame. + /// The emulator could use this function to create stack variables + /// in the function frame before converting the operand to a stack variable. + /// Please check with may_create_stkvars() before calling this function. + /// \param x operand (used to determine the addressing type) + /// \param v a displacement in the operand + /// \param flags_ \ref STKVAR_2 + /// \retval 1 ok, a stack variable exists now + /// \retval 0 no, couldn't create stack variable + + bool create_stkvar(const op_t &x, adiff_t v, int flags_) const + { + return insn_create_stkvar(*this, x, v, flags_); + } + + /// \defgroup STKVAR_2 Stack variable flags + /// Passed as 'flags' parameter to create_stkvar() + //@{ +#define STKVAR_VALID_SIZE 0x0001 ///< x.dtype contains correct variable type + ///< (for insns like 'lea' this bit must be off) + ///< in general, dr_O references do not allow + ///< to determine the variable size + //@} + + + /// Add a code cross-reference from the instruction. + /// \param opoff offset of the operand from the start of instruction. + /// if the offset is unknown, then 0. + /// \param to target linear address + /// \param type type of xref + + void add_cref(ea_t to, int opoff, cref_t type) const + { + insn_add_cref(*this, to, opoff, type); + } + + + /// Add a data cross-reference from the instruction. + /// See add_off_drefs() - usually it can be used in most cases. + /// \param opoff offset of the operand from the start of instruction + /// if the offset is unknown, then 0 + /// \param to target linear address + /// \param type type of xref + + void add_dref(ea_t to, int opoff, dref_t type) const + { + insn_add_dref(*this, to, opoff, type); + } + + + /// Add xrefs for an operand of the instruction. + /// This function creates all cross references for 'enum', 'offset' and + /// 'structure offset' operands. + /// Use add_off_drefs() in the presence of negative offsets. + /// \param x reference to operand + /// \param type type of xref + /// \param outf out_value() flags. These flags should match + /// the flags used to output the operand + /// \return if is_off(): the reference target address (the same as calc_reference_data). + /// if is_stroff(): #BADADDR because for stroffs the target address is unknown + /// else: #BADADDR because enums do not represent addresses + + ea_t add_off_drefs(const op_t &x, dref_t type, int outf) const + { + return insn_add_off_drefs(*this, x, type, outf); + } + + //@} + +}; +#ifdef __EA64__ +CASSERT(sizeof(insn_t) == 360); +#else +CASSERT(sizeof(insn_t) == 216); +#endif + +//-------------------------------------------------------------------------- +// V A L U E O F O P E R A N D +//-------------------------------------------------------------------------- +#ifndef SWIG +/// This structure is used to pass values of bytes to helper functions. +union value_u +{ + uint8 v_char; + uint16 v_short; + uint32 v_long; + uint64 v_int64; + uval_t v_uval; + struct dq_t { uint32 low; uint32 high; } _dq; + struct dt_t { uint32 low; uint32 high; uint16 upper; } dt; + struct d128_t { uint64 low; uint64 high; } d128; + uint8 byte16[16]; + uint32 dword3[3]; +}; + +#endif // SWIG + +/// Get immediate values at the specified address. +/// This function decodes instruction at the specified address or inspects +/// the data item. It finds immediate values and copies them to 'out'. +/// This function will store the original value of the operands in 'out', +/// unless the last bits of 'F' are "...0 11111111", in which case the +/// transformed values (as needed for printing) will be stored instead. +/// \param out array of immediate values (at least 2*#UA_MAXOP elements) +/// \param ea address to analyze +/// \param n number of operand (0..#UA_MAXOP-1), -1 means all operands +/// \param F flags for the specified address +/// \param cache optional already decoded instruction or buffer for it. +/// if the cache does not contain the decoded instruction, +/// it will be updated (useful if we call get_immvals for the same +/// address multiple times) +/// \return number of immediate values (0..2*#UA_MAXOP) + +idaman size_t ida_export get_immvals( + uval_t *out, + ea_t ea, + int n, + flags_t F, + insn_t *cache=NULL); + + +/// Get immediate ready-to-print values at the specified address +/// \param out array of immediate values (at least 2*#UA_MAXOP elements) +/// \param ea address to analyze +/// \param n number of operand (0..#UA_MAXOP-1), -1 means all operands +/// \param F flags for the specified address +/// \param cache optional already decoded instruction or buffer for it. +/// if the cache does not contain the decoded instruction, +/// it will be updated (useful if we call get_immvals for the same +/// address multiple times) +/// \return number of immediate values (0..2*#UA_MAXOP) + +inline size_t get_printable_immvals( + uval_t *out, + ea_t ea, + int n, + flags_t F, + insn_t *cache=NULL) +{ + F &= ~0x100; // no FF_IVL... + F |= 0xFF; // ...but a value of 0xFF + return get_immvals(out, ea, n, F, cache); +} + + +/// Number of instructions to look back. +/// This variable is not used by the kernel. +/// Its value may be specified in ida.cfg: +/// LOOKBACK = <number>. +/// IDP may use it as you like it. +/// (TMS module uses it) + +idaman int ida_export get_lookback(void); + + +//-------------------------------------------------------------------------- +// I D P H E L P E R F U N C T I O N S - C O M M O N +//-------------------------------------------------------------------------- + +/// \name Address translation +/// The following functions can be used by processor modules to map +/// addresses from one region to another. They are especially useful +/// for microprocessors that map the same memory region to multiple address +/// ranges or use memory bank switching. +/// The user can use the following techniques to desribe address translations: +/// - some processors support the segment transation feature. +/// the user can specify the mapping in Edit, Segments, Change segment translation +/// - the user can specify mapping for an individual direct call instruction +/// by specifying it as an offset (Edit, Operand types, Offset) +/// - specify the value of the data segment virtual register (ds). +/// it will be used to calculate data addresses +//@{ + +/// Get data segment for the instruction operand. +/// 'opnum' and 'rgnum' are meaningful only if the processor +/// has segment registers. + +idaman ea_t ida_export calc_dataseg(const insn_t &insn, int n=-1, int rgnum=-1); + +/// Map a data address. +/// \param insn the current instruction +/// \param addr the referenced address to map +/// \param opnum operand number + +inline ea_t map_data_ea(const insn_t &insn, ea_t addr, int opnum=-1) +{ + return to_ea(calc_dataseg(insn, opnum), addr); +} + +inline ea_t map_data_ea(const insn_t &insn, const op_t &op) +{ + return map_data_ea(insn, op.addr, op.n); +} + +/// Map a code address. +/// This function takes into account the segment translations. +/// \param insn the current instruction +/// \param addr the referenced address to map +/// \param opnum operand number + +idaman ea_t ida_export map_code_ea(const insn_t &insn, ea_t addr, int opnum); + +inline ea_t map_code_ea(const insn_t &insn, const op_t &op) +{ + return map_code_ea(insn, op.addr, op.n); +} + +inline ea_t map_ea(const insn_t &insn, const op_t &op, bool iscode) +{ + return iscode ? map_code_ea(insn, op) : map_data_ea(insn, op); +} + +inline ea_t map_ea(const insn_t &insn, ea_t addr, int opnum, bool iscode) +{ + return iscode ? map_code_ea(insn, addr, opnum) : map_data_ea(insn, addr, opnum); +} + +//@} + +//-------------------------------------------------------------------------- +// I D P H E L P E R F U N C T I O N S - O U T P U T +//-------------------------------------------------------------------------- +struct outctx_base_t +{ + // information for creating one line + ea_t insn_ea; + qstring outbuf; // buffer for the current output line + // once ready, it is moved to lnar + ssize_t regname_idx; // to rename registers + int suspop; // controls color for out_long() + flags_t F; // flag bits for insn_ea + uval_t *outvalues; // at least 2*UA_MAXOP elements + int outvalue_getn_flags; // additional flags for print_operand() + void *user_data; // pointer to be used by the processor module for any purpose + void *kern_data; // internal info used by the kernel + + // information for generating many lines + qstrvec_t *lnar; // vector of output lines + int lnar_maxsize; // max permitted size of lnar + int default_lnnum; // index of the most important line in lnar + + qstring line_prefix; // usually segname:offset + ssize_t prefix_len; // visible length of line_prefix + int ctxflags; // various bits +#define CTXF_MAIN 0x00001 // produce only the essential line(s) +#define CTXF_MULTI 0x00002 // enable multi-line essential lines +#define CTXF_CODE 0x00004 // display as code regardless of the database flags +#define CTXF_STACK 0x00008 // stack view +#define CTXF_GEN_XREFS 0x00010 // generate the xrefs along with the next line +#define CTXF_XREF_STATE 0x00060 // xref state: +#define XREFSTATE_NONE 0x00 // not generated yet +#define XREFSTATE_GO 0x20 // being generated +#define XREFSTATE_DONE 0x40 // have been generated +#define CTXF_GEN_CMT 0x00080 // generate the comment along with the next line +#define CTXF_CMT_STATE 0x00300 // comment state: +#define COMMSTATE_NONE 0x000 // not generated yet +#define COMMSTATE_GO 0x100 // being generated +#define COMMSTATE_DONE 0x200 // have been generated +#define CTXF_VOIDS 0x00400 // display void marks +#define CTXF_NORMAL_LABEL 0x00800 // generate plain label (+demangled label as cmt) +#define CTXF_DEMANGLED_LABEL 0x01000 // generate only demangled label as comment +#define CTXF_LABEL_OK 0x02000 // the label have been generated +#define CTXF_DEMANGLED_OK 0x04000 // the label has been demangled successfully +#define CTXF_OVSTORE_PRNT 0x08000 // out_value should store modified values +#define CTXF_OUTCTX_T 0x10000 // instance is, in fact, a outctx_t +#define CTXF_DBLIND_OPND 0x20000 // an operand was printed with double indirection (e.g. =var in arm) +#define CTXF_BINOP_STATE 0xC0000 // opcode bytes state: +#define BINOPSTATE_NONE 0x00000 // not generated yet +#define BINOPSTATE_GO 0x40000 // being generated +#define BINOPSTATE_DONE 0x80000 // have been generated + + + // internal data used by the kernel + int ind0; + ea_t cmt_ea; // indirectly referenced address (used to generate cmt) + qstring cmtbuf; // indented comment + const char *cmtptr; // rest of indented comment + color_t cmtcolor; // comment color + + inline bool only_main_line() const { return (ctxflags & CTXF_MAIN) != 0; } + inline bool multiline() const { return (ctxflags & CTXF_MULTI) != 0; } + inline bool force_code() const { return (ctxflags & CTXF_CODE) != 0; } + inline bool stack_view() const { return (ctxflags & CTXF_STACK) != 0; } + inline bool display_voids() const { return (ctxflags & CTXF_VOIDS) != 0; } + inline void set_gen_xrefs(bool on=true) { setflag(ctxflags, CTXF_GEN_XREFS, on); } + inline int get_xrefgen_state() const { return ctxflags & CTXF_XREF_STATE; } + inline void set_gen_cmt(bool on=true) { setflag(ctxflags, CTXF_GEN_CMT, on); } + inline int get_cmtgen_state() const { return ctxflags & CTXF_CMT_STATE; } + inline int get_binop_state() const { return ctxflags & CTXF_BINOP_STATE; } + inline void clr_gen_label(void) { ctxflags &= ~(CTXF_NORMAL_LABEL|CTXF_DEMANGLED_LABEL); } + inline void set_gen_label(void) { ctxflags |= CTXF_NORMAL_LABEL; } + inline void set_gen_demangled_label(void) { ctxflags |= CTXF_DEMANGLED_LABEL; ctxflags &= ~CTXF_NORMAL_LABEL; } + inline void set_comment_addr(ea_t ea) { cmt_ea = ea; } + inline void set_dlbind_opnd(void) { ctxflags |= CTXF_DBLIND_OPND; } + inline bool print_label_now() const + { + return (ctxflags & (CTXF_LABEL_OK|CTXF_MAIN)) == 0 // label not ready + && (ctxflags & (CTXF_NORMAL_LABEL|CTXF_DEMANGLED_LABEL)) != 0; // requested it + } + int forbid_annotations() + { // temporarily forbid printing of xrefs, label, cmt + int bits = CTXF_GEN_XREFS|CTXF_NORMAL_LABEL|CTXF_DEMANGLED_LABEL|CTXF_GEN_CMT; + int saved_flags = ctxflags & bits; + ctxflags &= ~bits; + return saved_flags; + } + void restore_ctxflags(int saved_flags) + { + ctxflags |= saved_flags; + } + + outctx_base_t(ea_t ea, flags_t flags, int _suspop=0) + : insn_ea(ea), regname_idx(-1), suspop(_suspop), F(flags), + outvalues(NULL), outvalue_getn_flags(0), user_data(NULL), kern_data(NULL), + lnar(NULL), lnar_maxsize(0), default_lnnum(-1), + prefix_len(0), ctxflags(0), ind0(0), cmt_ea(BADADDR), cmtptr(NULL), cmtcolor(0xFF) + { + outbuf.reserve(MAXSTR); + } + virtual ~outctx_base_t(void); + + ///------------------------------------------------------------------------- + /// Functions to append text to the current output buffer (outbuf) + + /// Append a formatted string to the output string. + /// \return the number of characters appended + AS_PRINTF(2, 3) void out_printf(const char *format, ...) + { + va_list va; + va_start(va, format); + out_vprintf(format, va); + va_end(va); + } + + GCC_DIAG_OFF(format-nonliteral); + void nowarn_out_printf(const char *format, ...) //-V524 body is equal to out_printf + { + va_list va; + va_start(va, format); + out_vprintf(format, va); + va_end(va); + } + GCC_DIAG_ON(format-nonliteral); + + virtual AS_PRINTF(2, 0) void idaapi out_vprintf(const char *format, va_list va); + + /// Output immediate value. + /// Try to use this function to output all constants of instruction operands. + /// This function outputs a number from x.addr or x.value in the form + /// determined by ::uFlag. It outputs a colored text. + /// - -1 is output with #COLOR_ERROR + /// - 0 is output as a number or character or segment + /// \param x value to output + /// \param outflags \ref OOF_ + /// \return flags of the output value + virtual flags_t idaapi out_value(const op_t &x, int outf=0); + + /// \defgroup OOF_ Output value flags + /// Flags passed to out_value(). + /// (don't use #OOF_SIGNMASK and #OOF_WIDTHMASK, they are for the kernel) + //@{ +#define OOF_SIGNMASK 0x0003 ///< sign symbol (+/-) output +#define OOFS_IFSIGN 0x0000 ///< output sign if needed +#define OOFS_NOSIGN 0x0001 ///< don't output sign, forbid the user to change the sign +#define OOFS_NEEDSIGN 0x0002 ///< always out sign (+-) +#define OOF_SIGNED 0x0004 ///< output as signed if < 0 +#define OOF_NUMBER 0x0008 ///< always as a number +#define OOF_WIDTHMASK 0x0070 ///< width of value in bits +#define OOFW_IMM 0x0000 ///< take from x.dtype +#define OOFW_8 0x0010 ///< 8 bit width +#define OOFW_16 0x0020 ///< 16 bit width +#define OOFW_24 0x0030 ///< 24 bit width +#define OOFW_32 0x0040 ///< 32 bit width +#define OOFW_64 0x0050 ///< 64 bit width +#define OOF_ADDR 0x0080 ///< output x.addr, otherwise x.value +#define OOF_OUTER 0x0100 ///< output outer operand +#define OOF_ZSTROFF 0x0200 ///< meaningful only if is_stroff(uFlag) + ///< append a struct field name if + ///< the field offset is zero? + ///< if #AFL_ZSTROFF is set, then this flag + ///< is ignored. +#define OOF_NOBNOT 0x0400 ///< prohibit use of binary not +#define OOF_SPACES 0x0800 ///< do not suppress leading spaces + ///< currently works only for floating point numbers +#define OOF_ANYSERIAL 0x1000 ///< if enum: select first available serial + //@} + + /// Output a character with #COLOR_SYMBOL color. + virtual void idaapi out_symbol(char c); + + /// Append a character multiple times + virtual void idaapi out_chars(char c, int n); + + /// Appends spaces to outbuf until its tag_strlen becomes 'len' + void out_spaces(ssize_t len) { add_spaces(&outbuf, len); } + virtual void idaapi add_spaces(qstring *buf, ssize_t len); + + /// Output a string with the specified color. + virtual void idaapi out_line(const char *str, color_t color=0); + + /// Output a string with #COLOR_KEYWORD color. + inline void out_keyword(const char *str) + { + out_line(str, COLOR_KEYWORD); + } + + /// Output a character with #COLOR_REG color. + inline void out_register(const char *str) + { + out_line(str, COLOR_REG); + } + + /// Output "turn color on" escape sequence + virtual void idaapi out_tagon(color_t tag); + + /// Output "turn color off" escape sequence + virtual void idaapi out_tagoff(color_t tag); + + /// Output "address" escape sequence + virtual void idaapi out_addr_tag(ea_t ea); + + /// Output a colored line with register names in it. + /// The register names will be substituted by user-defined names (regvar_t) + /// Please note that out_tagoff tries to make substitutions too (when called with COLOR_REG) + virtual void idaapi out_colored_register_line(const char *str); + + /// Output one character. + /// The character is output without color codes. + /// see also out_symbol() + virtual void idaapi out_char(char c) { outbuf.append(c); } + + /// Output a number with the specified base (binary, octal, decimal, hex) + /// The number is output without color codes. + /// see also out_long() + virtual void idaapi out_btoa(uval_t Word, char radix=0); + + /// \fn void out_long(sval_t, char) + /// Output a number with appropriate color. + /// Low level function. Use out_value() if you can. + /// if 'suspop' is set then + /// this function uses #COLOR_VOIDOP instead of #COLOR_NUMBER. + /// 'suspop' is initialized: + /// - in out_one_operand() + /// - in ..\ida\gl.cpp (before calling \ph{d_out()}) + /// \param v value to output + /// \param radix base (2,8,10,16) + /// \param suspop ::suspop + /// - suspop==0: operand is ok + /// - suspop==1: operand is suspicious and should be output with #COLOR_VOIDOP + /// - suspop==2: operand can't be output as requested and should be output with #COLOR_ERROR + virtual void idaapi out_long(sval_t v, char radix); + + /// Output a name expression. + /// \param x instruction operand referencing the name expression + /// \param ea address to convert to name expression + /// \param off the value of name expression. this parameter is used only to + /// check that the name expression will have the wanted value. + /// You may pass #BADADDR for this parameter but I discourage it + /// because it prohibits checks. + /// \return true if the name expression has been produced + virtual bool idaapi out_name_expr( + const op_t &x, + ea_t ea, + adiff_t off=BADADDR); + + // Generate the closing comment if if it required by the assembler + + inline void close_comment(void) { out_line(closing_comment()); } + + ///------------------------------------------------------------------------- + /// Functions to populate the output line array (lnar) + + /// Move the contents of the output buffer to the line array (outbuf->lnar) + /// The kernel augments the outbuf contents with additional text like + /// the line prefix, user-defined comments, xrefs, etc at this call. + virtual bool idaapi flush_outbuf(int indent=-1); + + /// Append contents of 'buf' to the line array. + /// Behaves like flush_outbuf but accepts an arbitrary buffer + virtual bool idaapi flush_buf(const char *buf, int indent=-1); + + /// Finalize the output context. + /// \return the number of generated lines. + virtual int idaapi term_outctx(const char *prefix=NULL); + + /// See gen_printf() + virtual AS_PRINTF(3, 0) bool idaapi gen_vprintf( + int indent, + const char *format, + va_list va); + + /// printf-like function to add lines to the line array. + /// \param indent indention of the line. + /// if indent == -1, the kernel will indent the line + /// at \inf{indent}. if indent < 0, -indent will be used for indention. + /// The first line printed with indent < 0 is considered as the + /// most important line at the current address. Usually it is + /// the line with the instruction itself. This line will be + /// displayed in the cross-reference lists and other places. + /// If you need to output an additional line before the main line + /// then pass DEFAULT_INDENT instead of -1. The kernel will know + /// that your line is not the most important one. + /// \param format printf style colored line to generate + /// \return overflow, lnar_maxsize has been reached + + AS_PRINTF(3, 4) inline bool gen_printf(int indent, const char *format, ...) + { + va_list va; + va_start(va, format); + bool code = gen_vprintf(indent, format, va); + va_end(va); + return code; + } +#define DEFAULT_INDENT 0xFFFF + + /// Generate empty line. This function does nothing if generation of empty + /// lines is disabled. + /// \return overflow, lnar_maxsize has been reached + + virtual bool idaapi gen_empty_line(void); + + + /// Generate thin border line. This function does nothing if generation + /// of border lines is disabled. + /// \param solid generate solid border line (with =), otherwise with - + /// \return overflow, lnar_maxsize has been reached + + virtual bool idaapi gen_border_line(bool solid=false); + + /// See gen_cmt_line() + virtual AS_PRINTF(3, 0) bool idaapi gen_colored_cmt_line_v( + color_t color, + const char *format, + va_list va); + + /// See gen_cmt_line() + + AS_PRINTF(2, 0) inline bool gen_cmt_line_v(const char *format, va_list va) + { + return gen_colored_cmt_line_v(COLOR_AUTOCMT, format, va); + } + + /// Generate one non-indented comment line, colored with ::COLOR_AUTOCMT. + /// \param format printf() style format line. The resulting comment line + /// should not include comment character (;) + /// \return overflow, lnar_maxsize has been reached + + AS_PRINTF(2, 3) inline bool gen_cmt_line(const char *format, ...) + { + va_list va; + va_start(va, format); + bool code = gen_cmt_line_v(format, va); + va_end(va); + return code; + } + + /// Generate one non-indented comment line, colored with ::COLOR_COLLAPSED. + /// \param format printf() style format line. The resulting comment line + /// should not include comment character (;) + /// \return overflow, lnar_maxsize has been reached + + AS_PRINTF(2, 3) inline bool gen_collapsed_line(const char *format, ...) + { + va_list va; + va_start(va,format); + bool answer = gen_colored_cmt_line_v(COLOR_COLLAPSED, format, va); + va_end(va); + return answer; + } + + /// Generate big non-indented comment lines. + /// \param cmt comment text. may contain \\n characters to denote new lines. + /// should not contain comment character (;) + /// \param color color of comment text (one of \ref COLOR_) + /// \return overflow, lnar_maxsize has been reached + + virtual bool idaapi gen_block_cmt(const char *cmt, color_t color); + + //------------------------------------------------------------------------- + /// Initialization; normally used only by the kernel + virtual void idaapi setup_outctx(const char *prefix, int makeline_flags); +#define MAKELINE_NONE 0x00 +#define MAKELINE_BINPREF 0x01 // allow display of binary prefix +#define MAKELINE_VOID 0x02 // allow display of '<suspicious>' marks +#define MAKELINE_STACK 0x04 // allow display of sp trace prefix + + virtual ssize_t idaapi retrieve_cmt(void) { return -1; } + virtual ssize_t idaapi retrieve_name(qstring *, color_t *) { return -1; } + virtual bool idaapi gen_xref_lines(void) { return false; } + + virtual void idaapi init_lines_array(qstrvec_t *answers, int maxsize); + + virtual member_t *idaapi get_stkvar(const op_t &, uval_t, sval_t *, int *); + + void gen_empty_line_without_annotations(void) + { + int saved_flags = forbid_annotations(); + gen_empty_line(); + restore_ctxflags(saved_flags); + } + + +protected: + virtual bool idaapi flush_and_reinit(void); + virtual void idaapi append_user_prefix(const char *, int) {} + virtual void idaapi add_aux_prefix(const char *, int) {} + virtual void idaapi out_label_addr_tag(void) {} + virtual void idaapi out_aux_cmts(void) {} +}; + +//-------------------------------------------------------------------------- +// This class is used to print instructions and data items +struct outctx_t : public outctx_base_t +{ + // kernel only data: + ea_t bin_ea; // Current binary format EA + char bin_state; // =0 not generated,1-in process,2-finished + int gl_bpsize = 0; // binary line prefix size + int bin_width = 0; + + // instruction to display: + insn_t insn; // valid only when ph.out_insn() is called + + // colorized and demangled label of the current address + qstring curlabel; + + // opinfo_t to use for out_value() + const printop_t *wif; + + // processor module and its description + procmod_t *procmod; + processor_t &ph; + asm_t &ash; + + // out_value() saves the printed values here + uval_t saved_immvals[UA_MAXOP] = { 0 }; + + outctx_t( + procmod_t *p, + processor_t &ph, + asm_t &ash, + ea_t ea, + flags_t flags=0, + int _suspop=0, + const printop_t *_wif=NULL); + ~outctx_t(void) + { + } + virtual void idaapi setup_outctx(const char *prefix, int flags) override; + virtual ssize_t idaapi retrieve_cmt(void) override; + virtual ssize_t idaapi retrieve_name(qstring *, color_t *) override; + virtual bool idaapi gen_xref_lines(void) override; + void set_bin_state(int value) + { + bin_state = value; + ctxflags &= ~CTXF_BINOP_STATE; + ctxflags |= value == 0 ? BINOPSTATE_NONE + : value == 1 ? BINOPSTATE_GO + : BINOPSTATE_DONE; + } + + /// Output instruction mnemonic for 'insn' using information in 'ph.instruc' array. + /// This function outputs a colored text. + /// It should be called from \ph{ev_out_insn()} or \ph{ev_out_mnem()} handler. + /// It will output at least one space after the instruction. + /// mnemonic even if the specified 'width' is not enough. + /// \param width width of field with mnemonic. + /// if < 0, then 'postfix' will be output before + /// the mnemonic, i.e. as a prefix + /// \param postfix optional postfix added to the instruction mnemonic + virtual void idaapi out_mnem(int width=8, const char *postfix=NULL) newapi; + + /// Output custom mnemonic for 'insn'. + /// E.g. if it should differ from the one in 'ph.instruc'. + /// This function outputs colored text. See \ref out_mnem + /// \param mnem custom mnemonic + /// \param width width of field with mnemonic. + /// if < 0, then 'postfix' will be output before + /// the mnemonic, i.e. as a prefix + /// \param postfix optional postfix added to 'mnem' + virtual void idaapi out_custom_mnem( + const char *mnem, + int width=8, + const char *postfix=NULL) newapi; + + /// Output instruction mnemonic using information in 'insn'. + /// It should be called from \ph{ev_out_insn()} and + /// it will call \ph{ev_out_mnem()} or \ref out_mnem. + /// This function outputs a colored text. + virtual void idaapi out_mnemonic(void) newapi; + + /// Use this function to output an operand of an instruction. + /// This function checks for the existence of a manually defined operand + /// and will output it if it exists. + /// It should be called from \ph{ev_out_insn()} and it will call \ph{ev_out_operand()}. + /// This function outputs a colored text. + /// \param n number of operand + /// \retval 1 operand is displayed + /// \retval 0 operand is hidden + virtual bool idaapi out_one_operand(int n) newapi; + + /// Get the immediate values used at the specified address. + /// This function can handle instructions and data items. + /// \param out array of values, size at least 2*UA_MAXOP + /// \param i operand number + /// \return number of immediate values + virtual size_t idaapi get_immvals(uval_t *out, int i) newapi; + + /// Print all operand values as commented character constants. + /// This function is used to comment void operands with their representation + /// in the form of character constants. + /// This function outputs a colored text. + virtual void idaapi out_immchar_cmts(void) newapi; + + virtual void idaapi gen_func_header(func_t *pfn) newapi; + virtual void idaapi gen_func_footer(const func_t *pfn) newapi; + + // display data items and undefined bytes. + virtual void idaapi out_data(bool analyze_only) newapi; + + // generate declaration for item in a special segment + // return: 0-ok, 1-overflow + virtual bool idaapi out_specea(uchar segtype) newapi; + + // convenience functions for processor modules + // print lines from ash.header + virtual void idaapi gen_header_extra() newapi; + + // flags for gen_header() +#define GH_PRINT_PROC (1 << 0) // processor name +#define GH_PRINT_ASM (1 << 1) // selected assembler +#define GH_PRINT_BYTESEX (1 << 2) // byte sex +#define GH_PRINT_HEADER (1 << 3) // lines from ash.header +#define GH_BYTESEX_HAS_HIGHBYTE (1 << 4) // describe inf.is_wide_high_byte_first() +#define GH_PRINT_PROC_AND_ASM (GH_PRINT_PROC | GH_PRINT_ASM) +#define GH_PRINT_PROC_ASM_AND_BYTESEX (GH_PRINT_PROC_AND_ASM | GH_PRINT_BYTESEX) +#define GH_PRINT_ALL (GH_PRINT_PROC_ASM_AND_BYTESEX | GH_PRINT_HEADER) +#define GH_PRINT_ALL_BUT_BYTESEX (GH_PRINT_PROC_AND_ASM | GH_PRINT_HEADER) + virtual void idaapi gen_header( + int flags = GH_PRINT_PROC_AND_ASM, + const char *proc_name = NULL, + const char *proc_flavour = NULL) newapi; +}; + +//-------------------------------------------------------------------------- +/// Create a new output context. +/// To delete it, just use "delete pctx" + +idaman outctx_base_t *ida_export create_outctx(ea_t ea, flags_t F=0, int suspop=0); + + +/// Print instruction mnemonics. +/// \param out output buffer +/// \param ea linear address of the instruction +/// \return success + +idaman bool ida_export print_insn_mnem(qstring *out, ea_t ea); + + +/// \defgroup FCBF_ format flags +/// Used by format_charlit +//@{ +#define FCBF_CONT 0x00000001 ///< don't stop on decoding, or any other kind of error +#define FCBF_ERR_REPL 0x00000002 ///< in case of an error, use a CP_REPLCHAR instead + ///< of a hex representation of the problematic byte + +#define FCBF_FF_LIT 0x00000004 ///< in case of codepoints == 0xFF, use it as-is (i.e., LATIN SMALL LETTER Y WITH DIAERESIS) + ///< If both this, and FCBF_REPL are specified, + ///< this will take precedence + +#define FCBF_DELIM 0x00000008 ///< add the 'ash'-specified delimiters around the generated data. + ///< Note: if those are not defined and the INFFL_ALLASM is not set, + ///< format_charlit() will return an error +//@} + + +/// Format character literal. +/// +/// Try and format 'size' bytes pointed to by '*ptr', as literal characters, +/// using the 'encidx' encoding, and with the specified 'flags' directives. +/// +/// By default, format_charlit() will fail and return an error, in +/// any of the following cases: +/// - a byte cannot be decoded using the specified (or default) encoding +/// - a codepoint is < 0x20 (i.e., ' ') +/// - a codepoint is present in 'ash.esccodes' +/// - a codepoint is 0xFF +/// - a codepoint is >= 0x80, and AS_NHIAS was specified in ash.flag +/// The function can be told to keep going instead of bailing out, for any +/// of these situations, by using one of the FCBF_*_OK flags. +/// +/// If the function is told to proceed on a specific error, by default +/// it will format the byte as a C-encoded byte value (i.e., '\xNN'), +/// unless the corresponding FCBF_*_REPL flag is passed, in which case +/// the problematic byte/codepoint will be replaced by the Unicode +/// replacement character in the output. +/// +/// \param out output buffer (can be NULL) +/// \param ptr pointer to pointer to bytes to print (will be advanced +/// by the number of bytes that were successfully printed) +/// \param size size of input value in bytes +/// \param flags \ref FCBF_ +/// \param encidx the 1 byte-per-unit encoding to use (or 0 to use the default 1 BPU encoding) +/// \return success + +idaman bool ida_export format_charlit( + qstring *out, + const uchar **ptr, + size_t size, + uint32 flags=0, + int encidx=0); + + +/// Print a floating point value. +/// \param buf output buffer. may be NULL +/// \param bufsize size of the output buffer +/// \param v floating point value in processor native format +/// \param size size of the value in bytes +/// \return true ok +/// \return false can't represent as floating point number + +idaman bool ida_export print_fpval(char *buf, size_t bufsize, const void *v, int size); + + +//-------------------------------------------------------------------------- +// I D P H E L P E R F U N C T I O N S - E M U L A T O R +//-------------------------------------------------------------------------- +/// Get flags for op_t::dtype field +idaman flags_t ida_export get_dtype_flag(op_dtype_t dtype); +/// Get size of opt_::dtype field +idaman size_t ida_export get_dtype_size(op_dtype_t dtype); +/// Get op_t::dtype from size +idaman op_dtype_t ida_export get_dtype_by_size(asize_t size); + +/// Is a floating type operand? +inline bool is_floating_dtype(op_dtype_t dtype) +{ + return dtype == dt_float + || dtype == dt_double + || dtype == dt_tbyte + || dtype == dt_ldbl + || dtype == dt_half; +} + + +//-------------------------------------------------------------------------- +// K E R N E L I N T E R F A C E T O I D P F U N C T I O N S +//-------------------------------------------------------------------------- +/// Create an instruction at the specified address. +/// This function checks if an instruction is present at the specified address +/// and will try to create one if there is none. It will fail if there is +/// a data item or other items hindering the creation of the new instruction. +/// This function will also fill the 'out' structure. +/// \param ea linear address +/// \param out the resulting instruction +/// \return the length of the instruction or 0 +idaman int ida_export create_insn(ea_t ea, insn_t *out=NULL); + + +/// Analyze the specified address and fill 'out'. +/// This function does not modify the database. +/// It just tries to interpret the specified address as an instruction and fills +/// the 'out' structure. +/// \param out the resulting instruction +/// \param ea linear address +/// \return the length of the (possible) instruction or 0 + +idaman int ida_export decode_insn(insn_t *out, ea_t ea); + +/// Can the bytes at address 'ea' be decoded as instruction? +/// \param ea linear address +/// \return whether or not the contents at that address could be a valid instruction + +inline bool can_decode(ea_t ea) { insn_t insn; return decode_insn(&insn, ea) > 0; } + + +/// Generate text representation for operand #n. +/// This function will generate the text representation of the specified +/// operand (includes color codes.) +/// \param out output buffer +/// \param ea the item address (instruction or data) +/// \param n operand number (0,1,2...). meaningful only for instructions +/// \param flags \ref GETN_ +/// Currently only #GETN_NODUMMY is accepted. +/// \param newtype if specified, print the operand using the specified type +/// \return success + +idaman bool ida_export print_operand( + qstring *out, + ea_t ea, + int n, + int getn_flags=0, + struct printop_t *newtype=NULL); + + +//-------------------------------------------------------------------------- +// Helper functions for the processor emulator/analyzer +//-------------------------------------------------------------------------- + +/// Decode previous instruction if it exists, fill 'out'. +/// \param out the resulting instruction +/// \param ea the address to decode the previous instruction from +/// \return the previous instruction address (#BADADDR-no such insn) + +idaman ea_t ida_export decode_prev_insn(insn_t *out, ea_t ea); + + +/// Decode preceding instruction in the execution flow. +/// Prefer far xrefs from addresses < the current to ordinary flows. +/// \param ea the address to decode the preceding instruction from +/// \param out the resulting instruction +/// \return the preceding instruction address (#BADADDR-no such insn) and 'out'. +/// *p_farref will contain 'true' if followed an xref, false otherwise. + +idaman ea_t ida_export decode_preceding_insn(insn_t *out, ea_t ea, bool *p_farref=NULL); + + +/// Helper class for processor modules to build macro instructions. +struct macro_constructor_t +{ + size_t reserved = 0; + + virtual ~macro_constructor_t() {} + + /// Construct a macro instruction. + /// This function may be called from ana() to generate a macro instruction. + /// + /// The real work is done by the 'build_macro()' virtual function. + /// It must be defined by the processor module. + /// + /// construct_macro() modifies the database using the info provided + /// by build_macro(). It verifies if the instruction can really be created + /// (for example, that other items do not hinder), may plan to reanalyze + /// the macro, etc. + /// If the macro instructions are disabled by the user, construct_macro() + /// will destroy the macro instruction. Note: if INSN_MODMAC is not set in + /// insn.flags, the database will not be modified. + /// + /// \param insn the instruction to modify into a macro + /// \param enable enable macro generation + /// \retval true the macro instruction is generated in 'insn' + /// \retval false did not create a macro + inline bool construct_macro(insn_t *insn, bool enable); + + /// Try to extend the instruction. + /// \param insn Instruction to modify, usually the first + /// instruction of the macro + /// \param may_go_forward Is it ok to consider the next instruction for the macro? + /// This argument may be false, for example, if there is + /// a cross reference to the end of INSN. In this case + /// creating a macro is not desired. However, it may still + /// be useful to perform minor tweaks to the instruction + /// using the information about the surrounding instructions. + /// \return true if created an macro instruction. + /// This function may modify 'insn' and return false; these changes will be + /// accepted by the kernel but the instruction will not be considered as a macro. + virtual bool idaapi build_macro(insn_t *insn, bool may_go_forward) = 0; +}; + +// Do not directly call this function, use macro_constructor_t +idaman bool ida_export construct_macro2( + macro_constructor_t *_this, + insn_t *insn, + bool enable); + +inline bool macro_constructor_t::construct_macro(insn_t *insn, bool enable) +{ + return construct_macro2(this, insn, enable); +} + + +/// Does the instruction spoil any register from 'regs'?. +/// This function checks the \ref CF_ flags from the instructions array. +/// Only ::o_reg operand types are consulted. +/// \param insn the instruction +/// \return index in the 'regs' array or -1 + +idaman int ida_export get_spoiled_reg(const insn_t &insn, const uint32 *regs, size_t n); + + +//------------------------------------------------------------------------- + +#ifndef NO_OBSOLETE_FUNCS +idaman DEPRECATED bool ida_export print_charlit(char *buf, const void *ptr, int size); +idaman DEPRECATED bool ida_export construct_macro(insn_t &insn, bool enable, bool (idaapi *build_macro)(insn_t &insn, bool may_go_forward)); // use construct_macro2() +#endif // NO_OBSOLETE_FUNCS + +#endif // _UA_HPP diff --git a/idasdk75/include/workarounds.hpp b/idasdk76/include/workarounds.hpp similarity index 100% rename from idasdk75/include/workarounds.hpp rename to idasdk76/include/workarounds.hpp diff --git a/idasdk76/include/xref.hpp b/idasdk76/include/xref.hpp new file mode 100644 index 0000000..3a8c13f --- /dev/null +++ b/idasdk76/include/xref.hpp @@ -0,0 +1,417 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _XREF_HPP +#define _XREF_HPP + +/*! \file xref.hpp + + \brief Functions that deal with cross-references + + There are 2 types of xrefs: CODE and DATA references. + All xrefs are kept in the bTree except ordinary execution flow + to the next instruction. Ordinary execution flow to + the next instruction is kept in flags (see bytes.hpp) + + The source address of a cross-reference must be an item head (is_head) + or a structure member id. + + Cross-references are automatically sorted. +*/ + +class func_t; // #include <funcs.hpp> +class member_t; // #include <struct.hpp> + +//--------------------------------------------------------------------------- +// C R O S S - R E F E R E N C E T Y P E S +//--------------------------------------------------------------------------- + +/// \defgroup xref_type Cross-Reference types +/// Describe categories of code/data xrefs. +/// \note IDA handles the xrefs automatically and may delete an xref +/// added by the user if it does not contain the #XREF_USER bit. +//@{ + +/// CODE xref types +enum cref_t +{ + fl_U, ///< unknown -- for compatibility with old + ///< versions. Should not be used anymore. + fl_CF = 16, ///< Call Far + ///< This xref creates a function at the + ///< referenced location + fl_CN, ///< Call Near + ///< This xref creates a function at the + ///< referenced location + fl_JF, ///< Jump Far + fl_JN, ///< Jump Near + fl_USobsolete, ///< User specified (obsolete) + fl_F, ///< Ordinary flow: used to specify execution + ///< flow to the next instruction. +}; + +/// DATA xref types +enum dref_t +{ + dr_U, ///< Unknown -- for compatibility with old + ///< versions. Should not be used anymore. + dr_O, ///< Offset + ///< The reference uses 'offset' of data + ///< rather than its value + ///< OR + ///< The reference appeared because the "OFFSET" + ///< flag of instruction is set. + ///< The meaning of this type is IDP dependent. + dr_W, ///< Write access + dr_R, ///< Read access + dr_T, ///< Text (for forced operands only) + ///< Name of data is used in manual operand + dr_I, ///< Informational + ///< (a derived java class references its base + ///< class informationally) + dr_S, ///< Reference to enum member (symbolic constant) +}; + + +/// \defgroup XREF_T Cross-Reference type flags +/// These flags are combined with a ::cref_t or ::dref_t value to describe the +/// type of a cross reference. +/// These bits are accessible to the kernel. +//@{ +#define XREF_USER 0x20 ///< User specified xref. + ///< This xref will not be deleted by IDA. + ///< This bit should be combined with + ///< the existing xref types (::cref_t & ::dref_t) + ///< Cannot be used for fl_F xrefs +#define XREF_TAIL 0x40 ///< Reference to tail byte in extrn symbols +#define XREF_BASE 0x80 ///< Reference to the base part of an offset +#define XREF_MASK 0x1F ///< Mask to get xref type + +#define XREF_PASTEND 0x100 ///< Reference is past item. This bit may be passed to + ///< add_dref() functions but it won't be saved in + ///< the database. It will prevent the destruction + ///< of eventual alignment directives. +//@} + +/// Get character describing the xref type. +/// \param xrtype combination of \ref XREF_T and a ::cref_t of ::dref_t value +idaman char ida_export xrefchar(char xrtype); + +//@} xref_type + +//--------------------------------------------------------------------------- +// A D D / D E L E T E C R O S S - R E F E R E N C E S +//--------------------------------------------------------------------------- + +/// Create a code cross-reference. +/// \param from linear address of referencing instruction +/// \param to linear address of referenced instruction +/// \param type cross-reference type +/// \return success + +idaman bool ida_export add_cref(ea_t from, ea_t to, cref_t type); + + +/// Delete a code cross-reference. +/// \param from linear address of referencing instruction +/// \param to linear address of referenced instruction +/// \param expand policy to delete the referenced instruction +/// - 1: plan to delete the referenced instruction if it has +/// no more references. +/// - 0: don't delete the referenced instruction even if no +/// more cross-references point to it +/// \retval true if the referenced instruction will be deleted + +idaman bool ida_export del_cref(ea_t from, ea_t to, bool expand); + + +/// Create a data cross-reference. +/// \param from linear address of referencing instruction or data +/// \param to linear address of referenced data +/// \param type cross-reference type +/// \return success (may fail if user-defined xref exists from->to) + +idaman bool ida_export add_dref(ea_t from, ea_t to, dref_t type); + + +/// Delete a data cross-reference. +/// \param from linear address of referencing instruction or data +/// \param to linear address of referenced data + +idaman void ida_export del_dref(ea_t from, ea_t to); + + +//------------------------------------------------------------------------- +// E N U M E R A T E ( G E T ) C R O S S - R E F E R E N C E S +//------------------------------------------------------------------------- + +struct xrefblk_t; +/// \name Helper functions +/// Should not be called directly! +//@{ +idaman bool ida_export xrefblk_t_first_from(xrefblk_t *,ea_t from,int flags); +idaman bool ida_export xrefblk_t_next_from(xrefblk_t *); +idaman bool ida_export xrefblk_t_first_to(xrefblk_t *,ea_t to,int flags); +idaman bool ida_export xrefblk_t_next_to(xrefblk_t *); +//@} + +/// Structure to enumerate all xrefs. +/// This structure provides a way to access cross-references from a given address. +/// For example: +/// +/// \code +/// xrefblk_t xb; +/// for ( bool ok=xb.first_from(ea, XREF_ALL); ok; ok=xb.next_from() ) +/// { +/// // xb.to - contains the referenced address +/// } +/// \endcode +/// or: +/// \code +/// xrefblk_t xb; +/// for ( bool ok=xb.first_to(ea, XREF_ALL); ok; ok=xb.next_to() ) +/// { +/// // xb.from - contains the referencing address +/// } +/// \endcode +/// +/// First, all code references will be returned, then all data references. +/// If you need only code references, stop calling next() as soon as you get a dref. +/// +/// If you need only data references, pass #XREF_DATA flag to first(). +/// You may not modify the contents of a xrefblk_t structure! It is read only. +struct xrefblk_t +{ + ea_t from; ///< the referencing address - filled by first_to(),next_to() + ea_t to; ///< the referenced address - filled by first_from(), next_from() + uchar iscode; ///< 1-is code reference; 0-is data reference + uchar type; ///< type of the last returned reference (::cref_t & ::dref_t) + uchar user; ///< 1-is user defined xref, 0-defined by ida + +/// \defgroup XREF_ Xref enumeration flags +/// Passed as 'flags' parameter to functions in ::xrefblk_t +//@{ +#define XREF_ALL 0x00 ///< return all references +#define XREF_FAR 0x01 ///< don't return ordinary flow xrefs +#define XREF_DATA 0x02 ///< return data references only +//@} + + /// \name Get first/next + /// The following functions first return code references, then data references. + /// If you need only code references, you need to check 'iscode' after each call. + /// If you need only data references, use #XREF_DATA bit. + /// \param flags \ref XREF_ + /// \retval 1 ok + /// \retval 0 no more xrefs + //@{ + + /// Get first xref from the given address (store in #to) + bool first_from(ea_t _from, int flags) + { return xrefblk_t_first_from(this, _from, flags); } + + /// Get next xref from address provided to first_from() + bool next_from(void) + { return xrefblk_t_next_from(this); } + + /// Get xref to given address (store in #from) + bool first_to(ea_t _to, int flags) + { return xrefblk_t_first_to(this, _to, flags); } + + /// Get next xref to address provided to first_to() + bool next_to(void) + { return xrefblk_t_next_to(this); } + + /// Get xref from '_from' that comes after '_to' + bool next_from(ea_t _from, ea_t _to, int flags) + { + if ( first_from(_from, flags) ) + { + to = _to; + return next_from(); + } + return false; + } + + /// Get xref to '_to' that comes after '_from' + bool next_to(ea_t _from, ea_t _to, int flags) + { + if ( first_to(_to, flags) ) + { + from = _from; + return next_to(); + } + return false; + } + + //@} +}; + +//------------------------------------------------------------------------- +/// Get first data referenced from the specified address. +/// \param from linear address of referencing instruction or data +/// \return linear address of first (lowest) data referenced from the specified address. +/// Return #BADADDR if the specified instruction/data doesn't reference +/// to anything. + +idaman ea_t ida_export get_first_dref_from(ea_t from); + + +/// Get next data referenced from the specified address. +/// \param from linear address of referencing instruction or data +/// \param current linear address of current referenced data. +/// This value is returned by get_first_dref_from() or +/// previous call to get_next_dref_from() functions. +/// \return linear address of next data or #BADADDR. + +idaman ea_t ida_export get_next_dref_from(ea_t from, ea_t current); + + +/// Get address of instruction/data referencing to the specified data. +/// \param to linear address of referencing instruction or data +/// \return #BADADDR if nobody refers to the specified data. + +idaman ea_t ida_export get_first_dref_to(ea_t to); + + +/// Get address of instruction/data referencing to the specified data +/// \param to linear address of referencing instruction or data +/// \param current current linear address. +/// This value is returned by get_first_dref_to() or +/// previous call to get_next_dref_to() functions. +/// \return #BADADDR if nobody refers to the specified data. + +idaman ea_t ida_export get_next_dref_to(ea_t to, ea_t current); + + +/// Get first instruction referenced from the specified instruction. +/// If the specified instruction passes execution to the next instruction +/// then the next instruction is returned. Otherwise the lowest referenced +/// address is returned (remember that xrefs are kept sorted!). +/// \param from linear address of referencing instruction +/// \return first referenced address. +/// If the specified instruction doesn't reference to other instructions +/// then returns #BADADDR. + +idaman ea_t ida_export get_first_cref_from(ea_t from); + + +/// Get next instruction referenced from the specified instruction. +/// \param from linear address of referencing instruction +/// \param current linear address of current referenced instruction +/// This value is returned by get_first_cref_from() or +/// previous call to get_next_cref_from() functions. +/// \return next referenced address or #BADADDR. + +idaman ea_t ida_export get_next_cref_from(ea_t from, ea_t current); + + +/// Get first instruction referencing to the specified instruction. +/// If the specified instruction may be executed immediately after its +/// previous instruction then the previous instruction is returned. +/// Otherwise the lowest referencing address is returned. +/// (remember that xrefs are kept sorted!). +/// \param to linear address of referenced instruction +/// \return linear address of the first referencing instruction or #BADADDR. + +idaman ea_t ida_export get_first_cref_to(ea_t to); + + +/// Get next instruction referencing to the specified instruction. +/// \param to linear address of referenced instruction +/// \param current linear address of current referenced instruction +/// This value is returned by get_first_cref_to() or +/// previous call to get_next_cref_to() functions. +/// \return linear address of the next referencing instruction or #BADADDR. + +idaman ea_t ida_export get_next_cref_to(ea_t to, ea_t current); + + +/// \name Far code references +/// The following functions are similar to get_{first|next}_cref_{from|to} +/// functions. The only difference is that they don't take into account +/// ordinary flow of execution. Only jump and call xrefs are returned. +/// (fcref means "far code reference") +//@{ +idaman ea_t ida_export get_first_fcref_from(ea_t from); +idaman ea_t ida_export get_next_fcref_from(ea_t from, ea_t current); +idaman ea_t ida_export get_first_fcref_to(ea_t to); +idaman ea_t ida_export get_next_fcref_to(ea_t to, ea_t current); +//@} + + +/// Has a location external to the function references? + +idaman bool ida_export has_external_refs(func_t *pfn, ea_t ea); + + +//------------------------------------------------------------------------- +// S W I T C H T A B L E F U N C T I O N S +//------------------------------------------------------------------------- +#ifdef NALT_HPP + +/// Create switch table from the switch information. +/// Usually there is no need to call this function directly because the kernel +/// will call it for the result of \ph{is_switch()}. +/// \param insn_ea address of the 'indirect jump' instruction +/// \param si switch information +/// \return success + +idaman bool ida_export create_switch_table( + ea_t insn_ea, + const switch_info_t &si); + + +/// Create code xrefs for the switch table. +/// This function creates xrefs from the indirect jump. +/// Usually there is no need to call this function directly because the kernel +/// will call it for switch tables +/// \param insn_ea address of the 'indirect jump' instruction +/// \param si switch information + +idaman void ida_export create_switch_xrefs( + ea_t insn_ea, + const switch_info_t &si); + + +/// Vector of case values - see calc_switch_cases() +typedef qvector<svalvec_t> casevec_t; + + +/// Get detailed information about the switch table cases. +/// \param casevec vector of case values... +/// \param targets ...and corresponding target addresses +/// \param insn_ea address of the 'indirect jump' instruction +/// \param si switch information +/// \return success + +idaman bool ida_export calc_switch_cases( + casevec_t *casevec, + eavec_t *targets, + ea_t insn_ea, + const switch_info_t &si); + +/// Delete information created by the call of create_switch_table(). +/// It delete parent address for each switch target. +/// \param insn_ea address of the 'indirect jump' instruction +/// \param si switch information +idaman void ida_export delete_switch_table( + ea_t jump_ea, + const switch_info_t &si); + +#endif + +//------------------------------------------------------------------------- +// F U N C T I O N S F O R T H E K E R N E L +//------------------------------------------------------------------------- + +/// \cond +idaman bool ida_export create_xrefs_from(ea_t ea); // returns false: no item at ea +idaman void ida_export delete_all_xrefs_from(ea_t ea, bool expand); +/// \endcond + + +#endif // _XREF_HPP diff --git a/idasdk76/install_make.txt b/idasdk76/install_make.txt new file mode 100644 index 0000000..b0b8f46 --- /dev/null +++ b/idasdk76/install_make.txt @@ -0,0 +1,179 @@ + + +Please read "readme.txt" before reading this file! + + +Preparing the build environment on MS Windows +--------------------------------------------- + + Prerequisites + ============= + + In addition to the compiler specified in readme.txt, Cygwin is required + on MS Windows. It is available from: + + https://www.cygwin.com/ + + Make sure to install the 32-bit version of Cygwin (setup-x86.exe) and to + install the 'make' package. + + + Build environment + ================= + + On MS Windows, you may build the SDK using either the Cygwin shell or the + Command Prompt (either cmd.exe or a Developer Command Prompt for Visual + Studio). + + If you wish to use the Cygwin shell to build the SDK, start it with: + + > C:\cygwin\cygwin.bat + + If you wish to use the Command Prompt, you must add Cygwin's bin directory + to your PATH: + + > set PATH=C:\cygwin\bin;%PATH% + + You should then navigate to IDA's SDK directory, for example: + + > cd C:\idasdk + + The MS Windows build automatically generates a configuration file from the + top-level directory of the SDK. To build this configuration file directly, + invoke make from the top-level directory with: + + C:\idasdk>make env + + or, in a cygwin shell: + + /cygdrive/c/idasdk $ make env + + If this file is not generated, you will hit this error message: + + cl : Command line error D8022 : cannot open '../../x64_win_vc_32.cfg' + + + Preparing the SDK + ================= + + The SDK provides a linker wrapper under the 'bin' directory. You may have to + set the executable flag on the 'bin\ld.exe' binary. + + You must add the SDK's bin directory to your PATH. + + On MS Windows' Command Prompt: + + C:\idasdk>set PATH=C:\idasdk\bin;%PATH% + + or, in a cygwin shell: + + /cygdrive/c/idasdk $ export PATH=/cygdrive/c/idasdk/bin:$PATH + + (please note that the separator is ':' here, not ';' as it would in cmd.exe) + + +Preparing the build environment on Linux and Mac OS X +----------------------------------------------------- + + You must add the SDK's bin directory to your PATH. + + $ export PATH=~/idasdk/bin:$PATH + + +Target platform +--------------- + + The target platform must be specified using one of the following environment + variables: + + - MS Windows: __NT__ + - Linux: __LINUX__ + - Mac OS X: __MAC__ + + If no target platform is specified, the build defaults to MS Windows (__NT__). + + It is a good idea to specify the platform directly on your ~/.bashrc file: + - MS Windows (Cygwin): + export __NT__=1 + - Linux: + export __LINUX__=1 + - Mac OS X: + export __MAC__=1 + + +How to build the SDK from the command-line +------------------------------------------ + + All source files are the same for all platforms and are compiled using the + same makefiles. The build commands are different between operating systems. + + + On Linux and Mac OS X + ===================== + + It should suffice to invoke 'make' directly: + + make + + If you did not export the target platform's environment variable, you may + specify the target in the command line, for example: + + make __LINUX__=1 + + To build for IDA64 (64-bit ea_t size): + + make __EA64__=1 + + Please note that both ida32 and ida64 are 64-bit applications. + + To build 32-bit debug servers, you must set the __X86__ variable. This can + be achieved in the command line with: + + make __X86__=1 + + You may also run the 'idamake.pl' script instead of 'make'. It is a post- + processing script for make, and will prevent the printing of some warnings + which cannot be disabled in the compiler. For example, there is this warning + from gcc: + + warning: format ‘%a’ expects argument of type ‘double’, but argument 2 has type ‘ea_t {aka unsigned int}’ [-Wformat=] + + There is also an environment option IDAMAKE_SIMPLIFY which can be passed to + 'idamake.pl', which turns on filtering of compiler command line. + + Some examples: + make __LINUX__=1 -- non-optimized linux build + make NDEBUG=1 __MAC__=1 -- optimized mac build + make NDEBUG=1 __NT__=1 __EA64__=1 -- optimized ida64 windows build + IDAMAKE_SIMPLIFY=1 idamake.pl [...] -- filter build system output + + + On MS Windows + ============= + + The build target is selected by using special bat files, present in the bin/ + directory + + mo.bat - will build components for ida.exe + mmo.bat - will build components for ida64.exe + + Note that 'm*.bat' files accept a '-j' argument, to parallelize the build: + + E.g, + + C:\idasdk>mo.bat -j 12 + + or, in a cygwin shell: + + /cygdrive/c/idasdk $ mo.bat -j 12 + +Aliases +------- + + Creating aliases for the build commands is a good idea. I have the following + in my .bashrc file: + + export __LINUX__=1 + export PATH=~/idasdk/bin:$PATH + alias mx='make 2>&1' + alias mmx='__EA64__=1 make 2>&1' diff --git a/idasdk75/install_visual.txt b/idasdk76/install_visual.txt similarity index 100% rename from idasdk75/install_visual.txt rename to idasdk76/install_visual.txt diff --git a/idasdk75/ldr/aif/aif.cpp b/idasdk76/ldr/aif/aif.cpp similarity index 100% rename from idasdk75/ldr/aif/aif.cpp rename to idasdk76/ldr/aif/aif.cpp diff --git a/idasdk75/ldr/aif/aif.h b/idasdk76/ldr/aif/aif.h similarity index 100% rename from idasdk75/ldr/aif/aif.h rename to idasdk76/ldr/aif/aif.h diff --git a/idasdk75/ldr/aif/aifcmn.cpp b/idasdk76/ldr/aif/aifcmn.cpp similarity index 100% rename from idasdk75/ldr/aif/aifcmn.cpp rename to idasdk76/ldr/aif/aifcmn.cpp diff --git a/idasdk76/ldr/aif/makefile b/idasdk76/ldr/aif/makefile new file mode 100644 index 0000000..885b8e0 --- /dev/null +++ b/idasdk76/ldr/aif/makefile @@ -0,0 +1,14 @@ +PROC=aif + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)aif$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../aof/aof.h ../idaldr.h aif.cpp aif.h \ + aifcmn.cpp diff --git a/idasdk76/ldr/amiga/amiga.cpp b/idasdk76/ldr/amiga/amiga.cpp new file mode 100644 index 0000000..7e2cc2f --- /dev/null +++ b/idasdk76/ldr/amiga/amiga.cpp @@ -0,0 +1,610 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2020 by Ilfak Guilfanov, <ig@datarescue.com> + * ALL RIGHTS RESERVED. + * + * AMIGA hunk file loader + * + */ + + +#include "../idaldr.h" +#include "amiga.hpp" + +#define SkipLong(Longs) do { if ( qlseek(li, 4 * qoff64_t(Longs), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 ) +#define SkipWord(Words) do { if ( qlseek(li, 2 * qoff64_t(Words), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 ) +#define SkipByte(Bytes) do { if ( qlseek(li, 1 * qoff64_t(Bytes), SEEK_CUR) == -1 ) goto TRUNCATED_INPUT; } while ( 0 ) + +//------------------------------------------------------------------------------ +static void ask_for_help(void) +{ + ask_for_feedback("This file contains some untested records"); +} + +//------------------------------------------------------------------------------ +static char *read_name(linput_t *li, char *buf, size_t bufsize, int Longs) +{ + if ( ssize_t(bufsize) > 0 ) + { + size_t sz = Longs; + if ( sz != 0 ) + { + sz *= 4; + if ( sz >= bufsize ) + sz = bufsize-1; + lread(li, buf, sz); + } + buf[sz] = '\0'; + } + return buf; +} + +//------------------------------------------------------------------------------ +void idaapi load_file(linput_t *li,ushort /*_neflags*/,const char * /*fileformatname*/) +{ + set_processor_type("68040", SETPROC_LOADER); + + uint32 Type, Data, i; + int nums; + char NameString[MAXSTR]; + bool has_header = false; + bool shortreloc = false; + ea_t start = to_ea(inf_get_baseaddr(), 0); + ea_t end = start; + +// +// The first pass +// + qoff64_t fsize = qlsize(li); + qlseek(li, 0); + while ( true ) + { + i = (uint32)qlread(li, &Type, sizeof(Type)); + if ( i != sizeof(Type) ) + { + if ( i != 0 ) + warning("There %s %u extra byte%s at end of file.", + i == 1 ? "is" : "are", + i, + i == 1 ? "" : "s"); + break; + } + Type = swap32(Type); + + if ( Type == HUNK_DREL32 && has_header ) + Type = HUNK_DREL32EXE; + + switch ( Type & 0xFFFF ) + { + case HUNK_UNIT: + read_name(li, NameString, sizeof(NameString), mf_readlong(li)); + break; + case HUNK_NAME: + read_name(li, NameString, sizeof(NameString), mf_readlong(li)); + break; + case HUNK_LIB: + SkipLong(1); + break; + case HUNK_INDEX: + SkipLong(mf_readlong(li)); + break; + case HUNK_CODE: + case HUNK_PPC_CODE: + case HUNK_DATA: + case HUNK_BSS: + { + Data = mf_readlong(li); + Data <<= 2; + Data &= 0x7FFFFFFF; + start = free_chunk(end, Data, -0xF); + end = start + Data; + if ( end < start ) + loader_failure("Segment address overlow: %a..%a", start, end); + const char *sname = NULL; + sel_t sel = get_segm_qty() + 1; + set_selector(sel, 0); + switch ( Type & 0xFFFF ) + { + case HUNK_PPC_CODE: + set_processor_type("ppc", SETPROC_LOADER); + sname = "PPC_CODE"; + break; + case HUNK_CODE: + sname = "CODE"; + if ( inf_get_start_cs() == BADSEL ) + { + inf_set_start_cs(sel); + inf_set_start_ip(start); + } + break; + case HUNK_DATA: + sname = "DATA"; + break; + case HUNK_BSS: + sname = "BSS"; + break; + } + if ( (Type & 0xFFFF) != HUNK_BSS ) + { + uint64 rest = fsize - qltell(li); + if ( end-start > rest ) + loader_failure("Too big segment %a..%a", start, end); + file2base(li, qltell(li), start, end, FILEREG_PATCHABLE); + } + segment_t s; + s.sel = setup_selector(sel); + s.start_ea = start; + s.end_ea = end; + s.align = saRelByte; + s.comb = scPub; + s.bitness = PH.get_segm_bitness(); + add_segm_ex(&s, sname, sname, ADDSEG_NOSREG|ADDSEG_SPARSE); + } + break; + case HUNK_RELOC32SHORT: + case HUNK_DREL32EXE: + shortreloc = true; + // no break + case HUNK_RELRELOC32: + case HUNK_ABSRELOC16: + case HUNK_RELRELOC26: + case HUNK_RELOC32: + case HUNK_RELOC16: + case HUNK_RELOC8: + case HUNK_DREL32: + case HUNK_DREL16: + case HUNK_DREL8: + nums = 0; + while ( true ) + { + if ( qltell(li) >= fsize ) +TRUNCATED_INPUT: + loader_failure("Truncated file"); + Data = shortreloc ? mf_readshort(li) : mf_readlong(li); + if ( Data == 0 ) + break; + shortreloc ? mf_readshort(li) : mf_readlong(li); + if ( shortreloc ) + SkipWord(Data); + else + SkipLong(Data); + nums += Data; + } + if ( (nums & 1) == 0 && shortreloc ) + SkipWord(1); + shortreloc = false; + break; + case HUNK_EXT: + while ( true ) + { + if ( qltell(li) >= fsize ) + goto TRUNCATED_INPUT; + Data = mf_readlong(li); + if ( Data == 0 ) + break; + /* Is it followed by a symbol name? */ + if ( Data & 0xFFFFFF ) + read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); + + /* Remember extension type. */ + int32 exttype = (Data >> 24) & 0xFF; + + /* Display value of symbol. */ + if ( exttype == EXT_DEF || exttype == EXT_ABS || exttype == EXT_RES ) + mf_readlong(li); + + /* Skip relocation information. */ + if ( exttype == EXT_REF32 + || exttype == EXT_REF16 + || exttype == EXT_REF8 +// || exttype == EXT_DEXT32 +// || exttype == EXT_DEXT16 +// || exttype == EXT_DEXT8 +// || exttype == EXT_RELREF32 + || exttype == EXT_RELREF26 ) + { + SkipLong(mf_readlong(li)); + } + + /* Display size of common block. */ + if ( exttype == EXT_COMMON ) + { + mf_readlong(li); + SkipLong(mf_readlong(li)); + } + } + break; + case HUNK_SYMBOL: + while ( true ) + { + if ( qltell(li) >= fsize ) + goto TRUNCATED_INPUT; + Data = mf_readlong(li); + if ( Data == 0 ) + break; + read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); + mf_readlong(li); + } + break; + case HUNK_DEBUG: + SkipLong(mf_readlong(li)); + break; + case HUNK_END: + break; + case HUNK_HEADER: + { + has_header = true; + while ( true ) + { + if ( qltell(li) >= fsize ) + goto TRUNCATED_INPUT; + Data = mf_readlong(li); + if ( Data == 0 ) + break; + read_name(li, NameString, sizeof(NameString), Data); + } + mf_readlong(li); + int32 From = mf_readlong(li); + int32 To = mf_readlong(li); + SkipLong(To-From+1); + } + break; + case HUNK_OVERLAY: + { + int32 TabSize = mf_readlong(li); + if ( TabSize ) + { + mf_readlong(li); + SkipLong(TabSize); + } + int32 hunktype = mf_readlong(li); + if ( TabSize && hunktype >= HUNK_UNIT && hunktype <= HUNK_ABSRELOC16 ) + qlseek(li, -4, SEEK_CUR); + } + break; + case HUNK_BREAK: + break; + default: + warning("Unknown hunk type %04X - Aborting!", Type & 0xFFFF); + return; + } + } + +// +// The second pass +// + qlseek(li, 0); + int nseg = 0; + while ( true ) + { + i = (uint32)qlread(li, &Type, sizeof(Type)); + if ( i != sizeof(Type) ) + break; + Type = swap32(Type); + + if ( Type == HUNK_DREL32 && has_header ) + Type = HUNK_DREL32EXE; + + switch ( Type & 0xFFFF ) + { + case HUNK_UNIT: + read_name(li, NameString, sizeof(NameString), mf_readlong(li)); + add_pgm_cmt("Unit: %s", NameString); + break; + case HUNK_NAME: + read_name(li, NameString, sizeof(NameString), mf_readlong(li)); + add_pgm_cmt("Title: %s", NameString); + break; + case HUNK_LIB: + mf_readlong(li); + break; + case HUNK_INDEX: + SkipLong(mf_readlong(li)); + break; + case HUNK_CODE: + case HUNK_PPC_CODE: + case HUNK_DATA: + case HUNK_BSS: + Data = mf_readlong(li); + Data <<= 2; + Data &= 0x7FFFFFFF; + if ( (Type & 0xFFFF) != HUNK_BSS ) + SkipByte(Data); + nseg++; + break; + case HUNK_RELOC32SHORT: + case HUNK_DREL32EXE: + shortreloc = true; + // no break + case HUNK_RELRELOC32: + case HUNK_ABSRELOC16: + case HUNK_RELRELOC26: + case HUNK_RELOC32: + case HUNK_RELOC16: + case HUNK_RELOC8: + case HUNK_DREL32: + case HUNK_DREL16: + case HUNK_DREL8: + nums = 0; + while ( (Data=(shortreloc ? mf_readshort(li) : mf_readlong(li))) != 0 ) + { + uint32 dat2 = shortreloc ? mf_readshort(li) : mf_readlong(li); + segment_t *s = get_segm_by_sel(dat2+1); + segment_t *ssrc = get_segm_by_sel(nseg); + ea_t base = BADADDR; + if ( ssrc != NULL ) + base = ssrc->start_ea; + else + s = NULL; + int elsize = shortreloc ? 2 : 4; + validate_array_count_or_die(li, Data, elsize, "Number of relocations"); + for ( uint32 dat3 = Data; dat3; --dat3 ) + { + uint32 off = shortreloc ? mf_readshort(li) : mf_readlong(li); + if ( s != NULL ) + { + ea_t src = base + off; + ea_t dst = s->start_ea; + ea_t target = BADADDR; + fixup_type_t fd_type = 0; + switch ( Type & 0xFFFF ) + { + case HUNK_RELRELOC32: + case HUNK_RELOC32: + case HUNK_DREL32: + case HUNK_RELOC32SHORT: + case HUNK_DREL32EXE: + target = get_dword(src)+dst; + put_dword(src, target); + fd_type = FIXUP_OFF32; + break; + case HUNK_ABSRELOC16: + case HUNK_RELRELOC26: + case HUNK_RELOC16: + case HUNK_DREL16: + target = get_word(src)+dst; + put_word(src, target); + fd_type = FIXUP_OFF16; + break; + case HUNK_RELOC8: + case HUNK_DREL8: + target = get_byte(src)+dst; + put_byte(src, (uint32)target); + fd_type = FIXUP_OFF8; + break; + } + if ( fd_type != 0 ) + { + fixup_data_t fd(fd_type); + fd.sel = dat2 + 1; + fd.off = target; + fd.set(src); + } + } + else + { + ask_for_help(); + } + } + nums += Data; + } + if ( (nums & 1) == 0 && shortreloc ) + SkipWord(1); + shortreloc = false; + break; + case HUNK_EXT: + ask_for_help(); + while ( (Data=mf_readlong(li)) != 0 ) + { + switch ( (Data >> 24) & 0xFF ) + { + case EXT_DEF: msg(" EXT_DEF"); break; + case EXT_ABS: msg(" EXT_ABS"); break; + case EXT_RES: msg(" EXT_RES"); break; + case EXT_REF32: msg(" EXT_REF32"); break; + case EXT_COMMON: msg(" EXT_COMMON"); break; + case EXT_REF16: msg(" EXT_REF16"); break; + case EXT_REF8: msg(" EXT_REF8"); break; +// case EXT_DEXT32: msg(" EXT_DEXT32"); break; +// case EXT_DEXT16: msg(" EXT_DEXT16"); break; +// case EXT_DEXT8: msg(" EXT_DEXT8"); break; +// case EXT_RELREF32: msg(" EXT_RELREF32"); break; +// case EXT_RELREF26: msg(" EXT_RELREF26"); break; +// case EXT_RELCOMMON: msg(" EXT_RELCOMMON"); break; + default: msg(" EXT_??? (%02x)\n",(Data >> 24) & 0xFF); break; + } + + /* Is it followed by a symbol name? */ + + if ( Data & 0xFFFFFF ) + { + read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); + msg(" %s", NameString); + } + + /* Remember extension type. */ + int32 exttype = (Data >> 24) & 0xFF; + + /* Display value of symbol. */ + if ( exttype == EXT_DEF || exttype == EXT_ABS || exttype == EXT_RES ) + { + if ( !(Data & 0xFFFFFF) ) + msg(" ???"); + + Data = mf_readlong(li); + msg("%08X", Data); + } + + /* Skip relocation information. */ + if ( exttype == EXT_REF32 + || exttype == EXT_REF16 + || exttype == EXT_REF8 +// || exttype == EXT_DEXT32 +// || exttype == EXT_DEXT16 +// || exttype == EXT_DEXT8 +// || exttype == EXT_RELREF32 + || exttype == EXT_RELREF26 ) + { + Data = mf_readlong(li); + msg("= %u entr%s", Data, Data == 1 ? "y" : "ies"); + SkipLong(Data); + } + + /* Display size of common block. */ + if ( exttype == EXT_COMMON ) + { + Data = mf_readlong(li); + + msg(" Size = %u bytes", Data << 2); + Data = mf_readlong(li); + SkipLong(Data); + } + msg("\n"); + } + break; + case HUNK_SYMBOL: + while ( (Data=mf_readlong(li)) != 0 ) + { + /* Display name. */ + read_name(li, NameString, sizeof(NameString), Data & 0xFFFFFF); + + /* Display value. */ + Data = mf_readlong(li); + + segment_t *ssrc = get_segm_by_sel(nseg); + if ( ssrc == NULL ) + ask_for_help(); + else + set_name(ssrc->start_ea+Data, NameString, SN_NOCHECK | SN_NOWARN | SN_IDBENC); + } + break; + case HUNK_DEBUG: + SkipLong(mf_readlong(li)); + break; + case HUNK_END: + break; + case HUNK_HEADER: + { + has_header = true; + while ( (Data=mf_readlong(li)) != 0 ) + read_name(li, NameString, sizeof(NameString), Data); + mf_readlong(li); + int32 From = mf_readlong(li); + int32 To = mf_readlong(li); + SkipLong(To-From+1); + } + break; + case HUNK_OVERLAY: + { + int32 TabSize = mf_readlong(li); + if ( TabSize ) + { + mf_readlong(li); + SkipLong(TabSize); + } + int32 hunktype = mf_readlong(li); + if ( TabSize && hunktype >= HUNK_UNIT && hunktype <= HUNK_ABSRELOC16 ) + qlseek(li, -4, SEEK_CUR); + } + break; + case HUNK_BREAK: + break; + default: + warning("Unknown hunk type %04X - Aborting!", Type & 0xFFFF); + return; + } + } + + create_filename_cmt(); +} + +//-------------------------------------------------------------------------- +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + qlseek(li, 0); + uint32 type; + if ( qlread(li, &type, sizeof(uint32)) == sizeof(uint32) + && swap32(type) == HUNK_HEADER ) + { + *fileformatname = "Amiga hunk file"; + *processor = "68040"; + return 1; + } + return 0; +} + +//-------------------------------------------------------------------------- +int idaapi move_segm_relocs(ea_t from, ea_t to, asize_t size, const char *fileformatname) +{ + qnotused(size); + qnotused(fileformatname); + if ( from == BADADDR ) + { + // The entire program is being rebased. + // In this case, 'to' actually contains a delta value; the number of bytes + // forward (positive) or backward (negative) that the whole database is + // being moved. + ea_t delta = to; + + // fix up relocations + fixup_data_t fd; + + for ( ea_t xEA = get_first_fixup_ea(); xEA != BADADDR; xEA = get_next_fixup_ea(xEA) ) + { + show_addr(xEA); + + get_fixup(&fd, xEA); + fd.off += delta; + + switch ( fd.get_type() ) + { + case FIXUP_OFF8: + put_byte(xEA, fd.off); + break; + case FIXUP_OFF16: + put_word(xEA, fd.off); + break; + case FIXUP_OFF32: + put_dword(xEA, fd.off); + break; + } + + set_fixup(xEA, fd); + } + + // Record the new image base address. + inf_set_baseaddr(inf_get_baseaddr() + delta); + // set_imagebase(new_base); + } + + return 1; +} + +//-------------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + move_segm_relocs, + NULL, +}; diff --git a/idasdk75/ldr/amiga/amiga.hpp b/idasdk76/ldr/amiga/amiga.hpp similarity index 100% rename from idasdk75/ldr/amiga/amiga.hpp rename to idasdk76/ldr/amiga/amiga.hpp diff --git a/idasdk76/ldr/amiga/makefile b/idasdk76/ldr/amiga/makefile new file mode 100644 index 0000000..fc584f7 --- /dev/null +++ b/idasdk76/ldr/amiga/makefile @@ -0,0 +1,13 @@ +PROC=amiga + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)amiga$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h amiga.cpp amiga.hpp diff --git a/idasdk76/ldr/aof/aof.cpp b/idasdk76/ldr/aof/aof.cpp new file mode 100644 index 0000000..d09900d --- /dev/null +++ b/idasdk76/ldr/aof/aof.cpp @@ -0,0 +1,724 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-97 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + * ARM Object File Loader + * ---------------------- + * This module allows IDA to load ARM object files into + * its database and to disassemble them correctly. + * + * NOTE 1: for the moment only B/BL instruction relocations are + * supported. I cannot find other relocation examples so + * they are not implemented yet. + * + * NOTE 2: Thumb modules are not supported. + * + * This module automatically detects the byte sex and sets inf.mf + * variable accrodingly. + * + * + */ + +#include "../idaldr.h" +#include "aof.h" + +//-------------------------------------------------------------------------- +NORETURN static void nomem(void) +{ + nomem("AOF loader"); +} + +//-------------------------------------------------------------------------- +static void *read_chunk(linput_t *li, const chunk_entry_t &ce) +{ + void *chunk = qalloc_array<char>(ce.size); + if ( chunk == NULL ) + nomem(); + qlseek(li, ce.file_offset); + lread(li, chunk, ce.size); + return chunk; +} + +//-------------------------------------------------------------------------- +static void check_chunk_ptr( + const chunk_entry_t &ce, + const void *chunkstart, + const void *chunkptr, + size_t ptrsize) +{ + const char *p0 = (const char*)chunkstart; + const char *p1 = (const char*)chunkptr; + if ( p1 < p0 || p1 + ptrsize < p0 || (p1 + ptrsize - p0) > ce.size ) + loader_failure("Corrupted file"); +} + +//-------------------------------------------------------------------------- +static void check_chunk_str( + const chunk_entry_t &ce, + const void *chunkstart, + const void *chunkptr) +{ + const char *p0 = (const char*)chunkstart; + const char *p1 = (const char*)chunkptr; + if ( p1 >= p0 ) + { + const char *chunk_end = p0 + ce.size; + while ( p1 < chunk_end ) + { + if ( *p1 == '\0' ) + return; + ++p1; + } + } + loader_failure("Corrupted file"); +} + +//-------------------------------------------------------------------------- +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + chunk_header_t hd; + if ( qlread(li, &hd, sizeof(hd)) != sizeof(hd) ) + return 0; + if ( hd.ChunkFileId != AOF_MAGIC && hd.ChunkFileId != AOF_MAGIC_B ) + return 0; + if ( hd.num_chunks > hd.max_chunks ) + return 0; + + *fileformatname = "ARM Object File"; + *processor = "arm"; + return 1; +} + +//-------------------------------------------------------------------------- +static void create32( + sel_t sel, + ea_t start_ea, + ea_t end_ea, + const char *name, + const char *classname) +{ + set_selector(sel, 0); + + segment_t s; + s.sel = sel; + s.start_ea = start_ea; + s.end_ea = end_ea; + s.align = saRelByte; + s.comb = scPub; + s.bitness = 1; // 32-bit + + if ( !add_segm_ex(&s, name, classname, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure(); +} + +//-------------------------------------------------------------------------- +static ea_t get_area_base(int idx) +{ + segment_t *s = get_segm_by_sel(idx+1); + if ( s == NULL ) + return BADADDR; + return s->start_ea; +} + +//-------------------------------------------------------------------------- +static ea_t find_area( + const chunk_entry_t &ce, + const area_header_t *ah, + int maxarea, + const char *strings, + const char *areaname) +{ + for ( int i=0; i < maxarea; i++, ah++ ) + { + const char *name = strings + size_t(ah->name); + check_chunk_str(ce, strings, name); + if ( streq(name, areaname) ) + return get_area_base(i); + } + return BADADDR; +} + +//-------------------------------------------------------------------------- +static ea_t create_spec_seg( + int *nsegs, + int nelem, + const char *name, + uchar seg_type) +{ + ea_t ea = BADADDR; + if ( nelem != 0 ) + { + nelem *= 4; + ea = free_chunk(inf_get_max_ea(), nelem, 0xFFF); + (*nsegs)++; + create32(*nsegs, ea, ea+nelem, name, CLASS_DATA); + segment_t *s = getseg(ea); + s->type = seg_type; + s->update(); + set_arm_segm_flags(s->start_ea, 2 << SEGFL_SHIFT); // alignment + } + return ea; +} + +//-------------------------------------------------------------------------- +static void process_name(ea_t ea, const char *name, uint32 flags, bool iscode) +{ + // ignore aux names -- they hinder data creation + if ( strstr(name, "$litpool_e$") != NULL ) + return; + if ( flags & SF_PUB ) + { + add_entry(ea, ea, name, iscode, AEF_IDBENC); + make_name_public(ea); + } + else + { + force_name(ea, name, SN_IDBENC); + } + if ( flags & SF_WEAK ) + make_name_weak(ea); + if ( flags & SF_ICASE ) + add_extra_cmt(ea, true, "Case-insensitive label"); + if ( flags & SF_STRNG ) + add_extra_cmt(ea, true, "Strong name"); +} + +//-------------------------------------------------------------------------- +static void reloc_insn(ea_t ea, uint32 rvalue, uint32 type) +{ + uint32 code = get_dword(ea); + switch ( (code >> 24) & 0xF ) + { + case 0x0A: // B + case 0x0B: // BL + { + int32 off = code & 0x00FFFFFFL; + if ( off & 0x00800000L ) + off |= ~0x00FFFFFFL; // extend sign + off <<= 2; + off += rvalue; + off >>= 2; + off &= 0xFFFFFFL; + code &= 0xFF000000L; + code |= off; + put_dword(ea, code); + } + break; + default: + warning("This relocation type is not implemented yet\n" + "\3%a: reloc insn rvalue=%x, rt=%lx", ea, rvalue, + type & RF_II); + break; + } +} + +//-------------------------------------------------------------------------- +inline void swap_chunk_entry(chunk_entry_t *ce) +{ + ce->file_offset = swap32(ce->file_offset); + ce->size = swap32(ce->size); +} + +//-------------------------------------------------------------------------- +static void swap_aof_header(aof_header_t *ahd) +{ + ahd->obj_file_type = swap32(ahd->obj_file_type); + ahd->version = swap32(ahd->version); + ahd->num_areas = swap32(ahd->num_areas); + ahd->num_syms = swap32(ahd->num_syms); + ahd->entry_area = swap32(ahd->entry_area); + ahd->entry_offset = swap32(ahd->entry_offset); +} + +//-------------------------------------------------------------------------- +static void swap_area_header(area_header_t *ah) +{ + ah->name = swap32(ah->name); + ah->flags = swap32(ah->flags); + ah->size = swap32(ah->size); + ah->num_relocs = swap32(ah->num_relocs); + ah->baseaddr = swap32(ah->baseaddr); +} + +//-------------------------------------------------------------------------- +static void swap_sym(sym_t *s) +{ + s->name = swap32(s->name); + s->flags = swap32(s->flags); + s->value = swap32(s->value); + s->area = swap32(s->area); +} + +//-------------------------------------------------------------------------- +// +// load file into the database. +// +void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) +{ + int i; + chunk_header_t hd; + set_processor_type("arm", SETPROC_LOADER); + lread(li, &hd, sizeof(hd)); + if ( hd.ChunkFileId == AOF_MAGIC_B ) // BIG ENDIAN + { + inf_set_be(true); + hd.max_chunks = swap32(hd.max_chunks); + hd.num_chunks = swap32(hd.num_chunks); + } + + validate_array_count_or_die(li, hd.max_chunks, sizeof(chunk_entry_t), "Number of chunks"); + chunk_entry_t *ce = qalloc_array<chunk_entry_t>(size_t(hd.max_chunks)); + if ( ce == NULL ) + nomem(); + lread(li, ce, sizeof(chunk_entry_t)*size_t(hd.max_chunks)); + if ( inf_is_be() ) + for ( i=0; i < hd.max_chunks; i++ ) + swap_chunk_entry(ce+i); + + int head = -1; // AOF Header + int area = -1; // Areas + int idfn = -1; // Identification + int symt = -1; // Symbol Table + int strt = -1; // String Table + + for ( i=0; i < hd.max_chunks; i++ ) + { + if ( ce[i].file_offset == 0 ) + continue; + if ( strneq(ce[i].chunkId, OBJ_HEAD, sizeof(ce[i].chunkId)) ) + head = i; + if ( strneq(ce[i].chunkId, OBJ_AREA, sizeof(ce[i].chunkId)) ) + area = i; + if ( strneq(ce[i].chunkId, OBJ_IDFN, sizeof(ce[i].chunkId)) ) + idfn = i; + if ( strneq(ce[i].chunkId, OBJ_SYMT, sizeof(ce[i].chunkId)) ) + symt = i; + if ( strneq(ce[i].chunkId, OBJ_STRT, sizeof(ce[i].chunkId)) ) + strt = i; + } + if ( head == -1 || area == -1 || strt == -1 || symt == -1 || idfn == -1 ) + { + qfree(ce); + loader_failure("One of required chunks is missing"); + } + + char *strings = (char *)read_chunk(li, ce[strt]); + aof_header_t *ahd = (aof_header_t *)read_chunk(li, ce[head]); + check_chunk_ptr(ce[head], ahd, ahd, sizeof(aof_header_t)); + if ( inf_is_be() ) + swap_aof_header(ahd); + +// +// Areas +// + + area_header_t *ah = (area_header_t *)(ahd + 1); + if ( inf_is_be() ) + { + for ( i=0; i < ahd->num_areas; i++ ) + { + check_chunk_ptr(ce[head], ahd, ah+i, sizeof(area_header_t)); + swap_area_header(ah+i); + } + } + qoff64_t offset = ce[area].file_offset; + inf_set_specsegs(inf_is_64bit() ? 8 : 4); + ea_t ea = to_ea(inf_get_baseaddr(), 0); + for ( i=0; i < ahd->num_areas; i++, ah++ ) + { + check_chunk_ptr(ce[head], ahd, ah, sizeof(area_header_t)); + if ( ah->flags & AREA_DEBUG ) + { + offset += ah->size; + offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); + continue; + } + if ( ah->flags & AREA_ABS ) + { + ea = ah->baseaddr; + if ( free_chunk(ea, ah->size, 1) != ea ) + error("Cannot allocate area at %a", ea); + } + else + { + ea = free_chunk(ea, ah->size, 0xFFF); + } + if ( (ah->flags & AREA_BSS) == 0 ) + { + ea_t end = ea + ah->size; + uint64 fsize = qlsize(li); + if ( offset > fsize + || fsize-offset < ah->size + || end < ea ) + { + loader_failure("Corrupted file"); + } + file2base(li, offset, ea, end, FILEREG_PATCHABLE); + offset += ah->size; + } + const char *name = strings + size_t(ah->name); + check_chunk_str(ce[strt], strings, name); + const char *classname; + if ( ah->flags & AREA_CODE ) + classname = CLASS_CODE; + else if ( ah->flags & (AREA_BSS|AREA_COMREF) ) + classname = CLASS_BSS; + else + classname = CLASS_DATA; + create32(i+1, ea, ea+ah->size, name, classname); + + segment_t *s = getseg(ea); + ushort sflags = (ah->flags & 0x1F) << SEGFL_SHIFT; // alignment + if ( ah->flags & AREA_BASED ) + sflags |= (SEGFL_BASED|ah->get_based_reg()); + if ( ah->flags & AREA_PIC ) + sflags |= SEGFL_PIC; + if ( ah->flags & AREA_REENTR ) + sflags |= SEGFL_REENTR; + if ( ah->flags & AREA_HALFW ) + sflags |= SEGFL_HALFW; + if ( ah->flags & AREA_INTER ) + sflags |= SEGFL_INTER; + if ( ah->flags & AREA_COMMON ) + sflags |= SEGFL_COMDEF; + if ( ah->flags & (AREA_COMMON|AREA_COMREF) ) + s->comb = scCommon; + if ( ah->flags & AREA_RDONLY ) + s->perm = SEGPERM_READ; + if ( ah->flags & AREA_ABS ) + s->align = saAbs; + s->update(); + set_arm_segm_flags(s->start_ea, sflags); + + if ( i == 0 ) + { + create_filename_cmt(); + char *id = (char *)read_chunk(li, ce[idfn]); + check_chunk_str(ce[idfn], id, id); + add_pgm_cmt("Translator : %s", id); + qfree(id); + } + + if ( ah->flags & AREA_CODE ) + { + if ( (ah->flags & AREA_32BIT) == 0 ) + add_pgm_cmt("The 26-bit area"); + if ( (ah->flags & AREA_EXTFP) != 0 ) + add_pgm_cmt("Extended FP instructions are used"); + if ( (ah->flags & AREA_NOCHK) != 0 ) + add_pgm_cmt("No Software Stack Check"); + if ( (ah->flags & AREA_THUMB) != 0 ) + add_pgm_cmt("Thumb code area"); + } + else + { + if ( (ah->flags & AREA_SHARED) != 0 ) + add_pgm_cmt("Shared Library Stub Data"); + } + ea += ah->size; + offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); + } + int nsegs = i; + +// +// Symbol Table +// + + ah = (area_header_t *)(ahd + 1); + uint32 *delta = qalloc_array<uint32>(size_t(ahd->num_syms)); + if ( delta == NULL ) + nomem(); + memset(delta, 0, sizeof(uint32)*size_t(ahd->num_syms)); + sym_t *syms = (sym_t *)read_chunk(li, ce[symt]); + if ( inf_is_be() ) + { + for ( i=0; i < ahd->num_syms; i++ ) + { + check_chunk_ptr(ce[symt], syms, syms+i, sizeof(sym_t)); + swap_sym(syms+i); + } + } + int n_undef = 0; + int n_abs = 0; + int n_comm = 0; + + for ( i=0; i < ahd->num_syms; i++ ) + { + sym_t *s = syms + i; + check_chunk_ptr(ce[symt], syms, syms+i, sizeof(sym_t)); + if ( s->flags & SF_DEF ) + { + if ( s->flags & SF_ABS ) + { + n_abs++; + } + else + { + const char *areaname = strings + size_t(s->area); + check_chunk_str(ce[strt], strings, areaname); + ea_t areabase = find_area(ce[strt], ah, size_t(ahd->num_areas), strings, areaname); + delta[i] = (uint32)areabase; + ea_t symea = areabase + s->value; + const char *name = strings + size_t(s->name); + check_chunk_str(ce[strt], strings, name); + if ( s->value == 0 && strcmp(areaname, name) == 0 ) + continue; // HACK! + process_name(symea, name, s->flags, segtype(areabase) == SEG_CODE); + } + } + else + { + if ( (s->flags & SF_PUB) && (s->flags & SF_COMM) ) // ref to common + n_comm++; + else + n_undef++; + } + } + + ea_t abs_ea = create_spec_seg(&nsegs, n_abs, NAME_ABS, SEG_ABSSYM); + ea_t undef_ea = create_spec_seg(&nsegs, n_undef, NAME_UNDEF, SEG_XTRN); + ea_t comm_ea = create_spec_seg(&nsegs, n_comm, NAME_COMMON, SEG_COMM); + if ( n_abs+n_undef+n_comm != 0 ) + { + for ( i=0; i < ahd->num_syms; i++ ) + { + sym_t *s = syms + i; + const char *name = strings + size_t(s->name); + check_chunk_str(ce[strt], strings, name); + if ( s->flags & SF_DEF ) + { + if ( s->flags & SF_ABS ) + { + if ( inf_get_specsegs() == 8 ) + { + put_qword(abs_ea, s->value); + create_qword(abs_ea, 8); + } + else + { + put_dword(abs_ea, s->value); + create_dword(abs_ea, 4); + } + process_name(abs_ea, name, s->flags, false); + delta[i] = s->value; + s->value = uint32(abs_ea - delta[i]); + abs_ea += inf_get_specsegs(); + } + } + else + { + if ( (s->flags & SF_PUB) && (s->flags & SF_COMM) ) // ref to common + { + if ( inf_get_specsegs() == 8 ) + put_qword(comm_ea, s->value); + else + put_dword(comm_ea, s->value); + process_name(comm_ea, name, s->flags, false); + delta[i] = (uint32)comm_ea; + comm_ea += inf_get_specsegs(); + } + else + { + put_dword(undef_ea, 0xE1A0F00E); // RET + process_name(undef_ea, name, s->flags, false); + delta[i] = (uint32)undef_ea; + undef_ea += inf_get_specsegs(); + } + s->value = 0; + } + } + } + +// +// Relocations +// + + offset = ce[area].file_offset; + for ( i=0; i < ahd->num_areas; i++, ah++ ) + { + if ( ah->flags & AREA_DEBUG ) + { + offset += ah->size; + offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); + continue; + } + if ( (ah->flags & AREA_BSS) == 0 ) + offset += ah->size; + qlseek(li, offset); + ea_t base = get_area_base(i); + validate_array_count(li, &ah->num_relocs, sizeof(reloc_t), "Number of relocs", offset); + for ( int j=0; j < ah->num_relocs; j++ ) + { + reloc_t r; + lread(li, &r, sizeof(reloc_t)); + if ( inf_is_be() ) + { + r.type = swap32(r.type); + r.offset = swap32(r.offset); + } + size_t sid = r.sid(); + ea_t rvalue; + ea_t target; + fixup_data_t fd; + if ( r.type & RF_A ) + { + if ( sid >= ahd->num_syms ) + loader_failure("Bad relocation record at file offset %" FMT_64 "x", qltell(li)-sizeof(reloc_t)); + rvalue = delta[sid]; + target = syms[sid].value + rvalue; + fd.set_extdef(); + } + else + { + rvalue = get_area_base((int)sid); + target = rvalue; + if ( rvalue == BADADDR ) + loader_failure("Bad reference to area %" FMT_Z " at file offset %" FMT_64 "x", sid, qltell(li)-sizeof(reloc_t)); + } + segment_t *s = getseg(target); + if ( s == NULL ) + loader_failure("Can't find area for relocation target %a at %" FMT_64 "x", target, qltell(li)-sizeof(reloc_t)); + fd.sel = s->sel; + fd.off = target - get_segm_base(s); + if ( (r.type & RF_R) != 0 ) + { + if ( (r.type & RF_A) != 0 ) + { + // R=1 B=0 or R=1 B=1 + // This specifies PC-relative relocation: to the subject field + // is added the difference between the relocation value and + // the base of the area containing the subject field. + // In pseudo C: + // subject_field = subject_field + + // (relocation_value - + // base_of_area_containing(subject_field)) + rvalue -= base; + } + else + { + // + // As a special case, if A is 0, and the relocation value is + // specified as the base of the area containing the subject + // field, it is not added and: + // subject_field = subject_field - + // base_of_area_containing(subject_field) + // This caters for relocatable PC-relative branches to fixed + // target addresses. If R is 1, B is usually 0. A B value of 1 + // is used to denote that the inter-link-unit value of a + // branch destination is to be used, rather than the more + // usual intra-link-unit value. + rvalue = -base; + } + } + else + { + if ( (r.type & RF_B) != 0 ) + { // R=0 B=1 + // This specifies based area relocation. The relocation value + // must be an address within a based data area. The subject + // field is incremented by the difference between this value + // and the base address of the consolidated based area group + // (the linker consolidates all areas based on the same base + // register into a single, contiguous region of the output + // image). In pseudo C: + // subject_field = subject_field + + // (relocation_value - + // base_of_area_group_containing(relocation_value)) + // For example, when generating re-entrant code, the C + // compiler places address constants in an adcon area based + // on register sb, and loads them using sb relative LDRs. + // At link time, separate adcon areas will be merged and sb + // will no longer point where presumed at compile time. B + // type relocation of the LDR instructions corrects for this. + rvalue -= get_area_base((int)sid); + } + else + { // R=0 B=0 + // This specifies plain additive relocation: the relocation + // value is added to the subject field. In pseudo C: + // subject_field = subject_field + relocation_value + /* nothing to do */; + } + } + ea_t relea = base + r.offset; + switch ( r.type & RF_FT ) + { + case RF_FT_BYTE: // 00 the field to be relocated is a byte + fd.set_type(FIXUP_OFF8); + fd.displacement = get_byte(relea); + add_byte(relea, (uint32)rvalue); + break; + case RF_FT_HALF: // 01 the field to be relocated is a halfword (two bytes) + fd.set_type(FIXUP_OFF16); + fd.displacement = get_word(relea); + add_word(relea, rvalue); + break; + case RF_FT_WORD: // 10 the field to be relocated is a word (four bytes) + fd.set_type(FIXUP_OFF32); + fd.displacement = get_dword(relea); + add_dword(relea, rvalue); + break; + case RF_FT_INSN: // 11 the field to be relocated is an instruction or instruction sequence + reloc_insn(relea, (uint32)rvalue, r.type); + break; + } + fd.set(relea); + } + offset += qoff64_t(ah->num_relocs) * sizeof(reloc_t); + } + + if ( ahd->entry_area != 0 ) + { + inf_set_start_cs(ahd->entry_area); + inf_set_start_ip(ahd->entry_offset); + inf_set_start_ea(ahd->entry_offset); + } + + qfree(syms); + qfree(delta); + qfree(ahd); + qfree(strings); + qfree(ce); + inf_set_baseaddr(0); +} + +//---------------------------------------------------------------------- +// +// LOADER DESCRIPTION BLOCK +// +//---------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk75/ldr/aof/aof.h b/idasdk76/ldr/aof/aof.h similarity index 100% rename from idasdk75/ldr/aof/aof.h rename to idasdk76/ldr/aof/aof.h diff --git a/idasdk76/ldr/aof/makefile b/idasdk76/ldr/aof/makefile new file mode 100644 index 0000000..e836e9a --- /dev/null +++ b/idasdk76/ldr/aof/makefile @@ -0,0 +1,20 @@ +PROC=aof + +include ../loader.mak + +#---------------------------------------------------------------------- +# the 'unlib' target must be called explicitly +.PHONY: +unlib: $(F)unlib$(B) +$(F)unlib$(B): $(call dumb_target, pro, $(F)unlib$(O)) + +# MAKEDEP dependency list ------------------ +$(F)aof$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h aof.cpp aof.h +$(F)unlib$(O) : $(I)fpro.h $(I)llong.hpp $(I)pro.h aof.h unlib.cpp diff --git a/idasdk75/ldr/aof/unlib.cpp b/idasdk76/ldr/aof/unlib.cpp similarity index 100% rename from idasdk75/ldr/aof/unlib.cpp rename to idasdk76/ldr/aof/unlib.cpp diff --git a/idasdk76/ldr/aout/aout.cpp b/idasdk76/ldr/aout/aout.cpp new file mode 100644 index 0000000..1186c76 --- /dev/null +++ b/idasdk76/ldr/aout/aout.cpp @@ -0,0 +1,660 @@ +/* + * This Loader Module is written by Yury Haron + * + */ + +/* + L O A D E R for a.out (Linux) +*/ + +#include "../idaldr.h" +//#define DEBUG +#include "aout.h" +#include "common.cpp" +#include "../../module/sparc/notify_codes.hpp" + +class aout_t +{ +public: + exec ex; + nlist *symtab; + char *strtab; + uint32 symcount; // number of symbols in symtab + + uint32 text; // first address of each section + uint32 data; + uint32 bss; + uint32 extrn; + uint32 top; // next available address + + uint32 treloff; // file offset of each section + uint32 dreloff; + uint32 symoff; + uint32 stroff; + + bool msb; + + aout_t(void) + { + memset((void*) this, 0, sizeof(*this)); + } + ~aout_t() + { + if ( symtab != NULL ) + { + qfree(symtab); + symtab = NULL; + } + if ( strtab != NULL ) + { + qfree(strtab); + strtab = NULL; + } + } +}; + +//-------------------------------------------------------------------------- +static const char *guess_processor(const exec &ex) +{ + if ( N_MACHTYPE(ex) ) + { + switch ( N_MACHTYPE(ex) ) + { + case M_386: + case M_386_NETBSD: + return "metapc"; + + case M_ARM: + case M_ARM6_NETBSD: + return "arm"; + + case M_SPARC: + return "sparcb"; + + default: + break; + } + } + return NULL; +} + +//-------------------------------------------------------------------------- +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + exec ex; + int i = get_aout_file_format_index(li, &ex); +#ifdef DEBUG + msg("getfmtindex=%d\n", i); +#endif + + if ( i == 0 ) + return 0; + + static const char *const ff[] = + { + "demand-paged executable with NULL-ptr check", // q + "object or impure executable", // o + "demand-paged executable", // z + "core", // c + "pure executable", // n + "OpenBSD demand-paged executable", // zo + }; + fileformatname->sprnt("a.out (%s)", ff[i-1]); + *processor = guess_processor(ex); +#ifdef DEBUG + msg("%s\n", fileformatname.c_str()); +#endif + return f_AOUT; +} + +//-------------------------------------------------------------------------- +static void create32( + processor_t &ph, + ushort sel, + ea_t start_ea, + ea_t end_ea, + const char *name, + const char *classname) +{ + set_selector(sel, 0); + if ( !add_segm(sel, start_ea, end_ea, name, classname, ADDSEG_SPARSE) ) + loader_failure(); + if ( ph.id == PLFM_386 ) + set_segm_addressing(getseg(start_ea), 1); +} + +//-------------------------------------------------------------------------- +bool ana_hdr(processor_t &ph, linput_t *li, exec *_ex) +{ + bool msb = false; + exec &ex = *_ex; + lread(li, &ex, sizeof(ex)); + + if ( N_BADMAG(ex) ) + { + swap_exec(ex); + msb = true; + msg("Assuming big-endian...\n"); + } + const char *proc = guess_processor(ex); + if ( proc != NULL ) + { + set_processor_type(proc, SETPROC_LOADER); + if ( N_MACHTYPE(ex) == M_SPARC ) + sparc_module_t::set_v8(true); // set SPARC_V8 parameter + } + else + { + if ( ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "AUTOHIDE REGISTRY\n" + "Missing machine type. Continue?") <= ASKBTN_NO ) + { + loader_failure(); + } + if ( ph.id == -1 ) + set_processor_type(inf_get_procname().c_str(), SETPROC_LOADER); + } + return msb; +} + +//-------------------------------------------------------------------------- +inline fixup_type_t get_hi22_reltype() +{ + static fixup_type_t hi22_reltype = FIXUP_CUSTOM; + if ( hi22_reltype == FIXUP_CUSTOM ) + hi22_reltype = find_custom_fixup("HI22"); + return hi22_reltype; +} + +//-------------------------------------------------------------------------- +inline fixup_type_t get_lo10_reltype() +{ + static fixup_type_t lo10_reltype = FIXUP_CUSTOM; + if ( lo10_reltype == FIXUP_CUSTOM ) + lo10_reltype = find_custom_fixup("LO10"); + return lo10_reltype; +} + +//-------------------------------------------------------------------------- +static void do_fixup(uint32 where, uint32 delta, uint32 target, fixup_type_t type, int external) +{ + fixup_data_t fd(type); + if ( external ) + fd.set_extdef(); + + fd.displacement = delta; + if ( external ) + target -= delta; + + segment_t *s = getseg(target); + if ( s != NULL ) + { + fd.sel = s->sel; + fd.off = target - get_segm_base(s); + } + else + { + fd.off = target; + } + fd.set(where); +} + +#define S_MASK(x) ((1 << (x)) - 1) + +//---------------------------------------------------------------------- +static void do_relocation_sparc( + linput_t *li, + const aout_t &ctx, + uint32 off, + uint32 len, + int seg) +{ + const segment_t *seg_p = getnseg(seg); + if ( seg_p == NULL ) + { + msg("relocation data for missing segment %d ignored\n", seg); + return; + } + uint32 base = seg == 1 ? ctx.text : ctx.data; +#ifdef DEBUG + msg("seg %d base 0x%08X\n", seg, base); +#endif + + // load relocation table + uint32 relcount = len / sizeof(reloc_info_sparc); + validate_array_count(li, &relcount, sizeof(reloc_info_sparc), "Relocation count", off); + if ( relcount == 0 ) + return; + reloc_info_sparc *reltab = qalloc_array<reloc_info_sparc>(relcount); + if ( reltab == NULL ) + loader_failure("Unable to allocate relocation table for %u entries\n", relcount); + qlseek(li, off); + for ( reloc_info_sparc *rel = reltab; rel < reltab + relcount; rel++ ) + { + uint32 temp = 0; + lread4bytes(li, &rel->r_address, ctx.msb); + lread4bytes(li, &temp, ctx.msb); + lread4bytes(li, &rel->r_addend, ctx.msb); + rel->r_index = (temp >> 8) & 0x00FFFFFF; + rel->r_extern = (temp >> 7) & 1; + rel->r_type = (reloc_type_sparc) ((temp) & 0x1F); + +#ifdef DEBUG + if ( rel->r_address >= 0x80C8 && rel->r_address <= 0x8200 ) + msg("%08X: index=0x%06X extern=%d type=%02X addend=0x%08X\n", + rel->r_address, rel->r_index, rel->r_extern, rel->r_type, rel->r_addend); +#endif + } + + + // perform relocation + for ( reloc_info_sparc *rel = reltab; rel < reltab + relcount; rel++ ) + { + uint32 where = base + rel->r_address; + uint32 instr = get_dword(where); + fixup_type_t type = FIXUP_OFF32; + uint32 target = where; + uint32 value; + uint32 merged; +#ifdef DEBUG + value = instr; + merged = instr; +#endif + + if ( rel->r_extern ) + { + if ( rel->r_index >= ctx.symcount ) + { + msg("%08X: relocation to extern symbol idx %08X out of bounds, ignored\n", where, rel->r_index); + continue; + } + nlist *sym = &ctx.symtab[rel->r_index]; + + // The in-database address for this symbol was set when loading the symtab. + target = sym->n_value; + target += rel->r_addend; + +/* + if ( (sym->n_type & N_TYPE ) != N_ABS && + (sym->n_type & N_TYPE) != N_COMM) + target += where; + + if ( (rel->r_type == SPARC_RELOC_PC10 ) || + (rel->r_type == SPARC_RELOC_PC22)) + target -= where; +*/ + } + else + { + if ( rel->r_type == SPARC_RELOC_HI22 || rel->r_type == SPARC_RELOC_LO10 ) + target = rel->r_addend; + if ( seg == 2 && rel->r_type == SPARC_RELOC_32 ) + target = rel->r_addend; +/* + if ( (rel->r_index == N_TEXT ) || + (rel->r_index == N_DATA) || + (rel->r_index == N_BSS)) + target = rel->r_addend; +*/ + } + + uint32 delta = 0; + switch ( rel->r_type ) + { + case SPARC_RELOC_32: + value = instr; + target += value; + merged = target; + break; + case SPARC_RELOC_WDISP30: + value = (instr & S_MASK(30)); + target += value; + merged = (instr & ~S_MASK(30)) | ((target >> 2) & S_MASK(30)); + break; + case SPARC_RELOC_WDISP22: + value = (instr & S_MASK(22)); + target += value; + merged = (instr & ~S_MASK(22)) | ((target >> 2) & S_MASK(22)); + break; + case SPARC_RELOC_HI22: + value = (instr & S_MASK(22)) << 10; + target += value; + merged = (instr & ~S_MASK(22)) | ((target >> 10) & S_MASK(22)); + delta = 0; //-(target & S_MASK(10)); + type = get_hi22_reltype(); + break; + case SPARC_RELOC_LO10: + value = (instr & S_MASK(10)); + target += value; + merged = (instr & ~S_MASK(10)) | ((target) & S_MASK(10)); + type = get_lo10_reltype(); + break; + default: + msg("Unsupported sparc relocation type 0x%02X, ignored\n", rel->r_type); + continue; + } + +#ifdef DEBUG +// if ( rel->r_address < 0x300 ) +// msg("%08X: %08X -> %08X (%08X -> %08X)\n", where, instr, merged, value, target); +#endif + + put_dword(where, merged); + do_fixup(where, rel->r_extern ? rel->r_addend : delta, target, type, rel->r_extern); + } + + qfree(reltab); +} + + +//---------------------------------------------------------------------- +static void do_relocation(linput_t *li, const aout_t &ctx, uint32 off, uint32 len, int seg) +{ + switch ( N_MACHTYPE(ctx.ex) ) + { + case M_SPARC: + do_relocation_sparc(li, ctx, off, len, seg); + break; + default: + msg("Warning: Relocation in image file not supported yet for this processor\n"); + break; + } +} + + +//---------------------------------------------------------------------- +void load_syms(linput_t *li, aout_t &ctx) +{ + // get string table length + uint32 tabsize = 0; + qlseek(li, ctx.stroff); + lread4bytes(li, &tabsize, ctx.msb); +#ifdef DEBUG + msg("symoff=0x%08x symlen=0x%08x stroff=0x%08x strlen=0x%08x\n", + ctx.symoff, ctx.ex.a_syms, ctx.stroff, tabsize); +#endif + + // load string table + char *strtab = (char *)qalloc(tabsize+1); + if ( strtab == NULL ) + loader_failure("Unable to allocate string table for %u bytes\n", tabsize+1); + qlseek(li, ctx.stroff); + lreadbytes(li, strtab, tabsize, false); + strtab[tabsize] = '\0'; // ensure trailing zero + + // load symbol table + ctx.symcount = ctx.ex.a_syms / sizeof(nlist); + validate_array_count_or_die(li, ctx.symcount, sizeof(nlist), + "Number of symbols", ctx.symoff); + nlist *symtab = qalloc_array<nlist>(ctx.symcount); + if ( symtab == NULL ) + loader_failure("Unable to allocate symbol table for %u entries\n", ctx.symcount); + qlseek(li, ctx.symoff); + uint32 extern_count = 0; + for ( nlist *sym = symtab; sym < symtab + ctx.symcount; sym++ ) + { + lread4bytes(li, &sym->n_un.n_strx, ctx.msb); + lreadbytes(li, &sym->n_type, 1, ctx.msb); + lreadbytes(li, &sym->n_other, 1, ctx.msb); + lread2bytes(li, &sym->n_desc, ctx.msb); + lread4bytes(li, &sym->n_value, ctx.msb); + + if ( sym->n_type == N_EXT ) + extern_count++; + } + + // create extern section + uint32 extern_base = ctx.top; + if ( extern_count != 0 ) + { + // create new segment + add_segm(0, extern_base, extern_base + (extern_count * 4), "extern", "XTRN", ADDSEG_SPARSE); + ctx.extrn = extern_base; + ctx.top += extern_count * 4; + } + + + // import symbols +#ifdef DEBUG + int i = 0; +#endif + uint32 i_extern = 0; + for ( nlist *sym = symtab; sym < symtab + ctx.symcount; sym++ ) + { + if ( sym->n_type & N_STAB ) // debug stab info, not a symbol + continue; + + if ( sym->n_type == N_EXT ) + { + sym->n_value = extern_base + (i_extern * 4); + if ( getseg(sym->n_value) ) + put_dword(sym->n_value, 0); + i_extern++; + } + + if ( getseg(sym->n_value) != NULL ) + { + if ( sym->n_un.n_strx < tabsize ) + { + set_name(sym->n_value, strtab + sym->n_un.n_strx, + (sym->n_type & N_EXT ? SN_PUBLIC : SN_NON_PUBLIC)|SN_NOCHECK|SN_NOWARN|SN_IDBENC); + } + else + { + msg("%08X: type=0x%02X other=0x%02X desc=0x%04X: bad str offset %08X\n", + sym->n_value, sym->n_type, sym->n_other, sym->n_desc, + sym->n_un.n_strx); + } + } + + if ( (sym->n_type & N_TYPE) == N_ABS ) + { +#ifdef DEBUG + msg("%04X: %08X: type=0x%02X other=0x%02X desc=0x%04X: %s\n", + i, sym->n_value, sym->n_type, sym->n_other, sym->n_desc, + strtab + sym->n_un.n_strx); +#endif + } +#ifdef DEBUG + i++; +#endif + } + + ctx.strtab = strtab; + ctx.symtab = symtab; +} + +//-------------------------------------------------------------------------- +static void handle_ld_info(linput_t *li, int diroff, int base) +{ + lddir_t lddir; + qlseek(li, diroff); + lread(li, &lddir, sizeof(lddir)); + + ld_info_t ldinfo; + qlseek(li, lddir.ldinfo-base); + lread(li, &ldinfo, sizeof(ldinfo)); + + qoff64_t fpos = ldinfo.symbols - base; + int nsyms = (ldinfo.strings - ldinfo.symbols) / sizeof(ld_symbol_t); + validate_array_count(li, &nsyms, sizeof(ld_symbol_t), "Symbol count", fpos); + qlseek(li, fpos); + for ( int i=0; i < nsyms; i++ ) + { + ld_symbol_t sym; + lread(li, &sym, sizeof(sym)); + + char name[MAXSTR]; + qlgetz(li, ldinfo.strings + sym.nameoff - base, name, sizeof(name)); + + set_name(sym.addr, name, SN_IDBENC); + if ( (sym.flags & (AOUT_LD_FUNC|AOUT_LD_DEF)) == AOUT_LD_FUNC ) + { // imported function + put_byte(sym.addr, 0xC3); // return + if ( sym.addr <= ldinfo.ldentry ) + warning("interr: symbol #%d (%s) is not in the plt", i, name); + } + } +} + +//-------------------------------------------------------------------------- +// +// load file into the database. +// +void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) +{ + processor_t &ph = PH; + aout_t ctx; + exec &ex = ctx.ex; + ctx.msb = ana_hdr(ph, li, &ex); + ctx.symtab = NULL; + ctx.symcount = 0; + ctx.strtab = NULL; + ctx.treloff = N_TRELOFF(ex); + ctx.dreloff = N_DRELOFF(ex); + ctx.symoff = N_SYMOFF(ex); + ctx.stroff = N_STROFF(ex); + + int txtoff = N_TXTOFF(ex); + int txtadr; + + switch ( ph.id ) + { + case PLFM_SPARC: + txtoff = N_TXTOFF_SPARC(ex); + txtadr = N_TXTADDR_SPARC(ex); + ctx.treloff = N_TRELOFF_SPARC(ex); + ctx.dreloff = N_DRELOFF_SPARC(ex); + ctx.symoff = N_SYMOFF_SPARC(ex); + ctx.stroff = N_STROFF_SPARC(ex); + break; + + case PLFM_ARM: + txtadr = N_TXTADDR_ARM(ex); + break; + + default: + txtadr = N_TXTADDR(ex); + switch ( N_MAGIC(ex) ) + { +// case NMAGIC: +// case CMAGIC: + default: + loader_failure("This image type is not supported yet"); + + case ZMAGIC: + if ( qlsize(li) < ex.a_text + ex.a_data + N_SYMSIZE(ex) + txtoff ) + { + txtoff = 0; + txtadr = 0x1000; + } + else if ( txtoff < 512 ) + { + loader_failure("Size of demand page < size of block"); + } + // fallthrough + case QMAGIC: + if ( ex.a_text & 0xFFF || ex.a_data & 0xFFF ) + loader_failure("Executable is not page aligned"); + break; + + case OMAGIC: + txtoff = sizeof(ex); + break; + } + break; + } + + inf_set_baseaddr(0); + + uint32 base, top; + top = base = txtadr; + if ( ex.a_text || ex.a_data ) + { + top += ex.a_text; +// msg("txtoff=%d, base=%d top=%d end=%d\n", txtoff, base, top, top+ex.a_data); + file2base(li, txtoff, base, top + ex.a_data, FILEREG_PATCHABLE); + if ( ex.a_text ) + { + create32(ph, 1, base, top, NAME_CODE, CLASS_CODE); + inf_set_start_cs(1); + inf_set_start_ip(ex.a_entry); + ctx.text = base; + } + if ( ex.a_data ) + { + base = top; + create32(ph, 2, base, top += ex.a_data, NAME_DATA, CLASS_DATA); + set_default_dataseg(2); + ctx.data = base; + } + } + if ( ex.a_bss ) + { + create32(ph, 3, top, top + ex.a_bss, NAME_BSS, CLASS_BSS); + ctx.bss = top; + } + ctx.top = top + ex.a_bss; + + if ( ex.a_syms ) + load_syms(li, ctx); + + if ( N_TRSIZE(ex) ) + do_relocation(li, ctx, ctx.treloff, N_TRSIZE(ex), 1); + if ( N_DRSIZE(ex) ) + do_relocation(li, ctx, ctx.dreloff, N_DRSIZE(ex), 2); + +// We come in here for the regular a.out style of shared libraries */ +// ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || +// return -ENOEXEC; +// } +// For QMAGIC, the starting address is 0x20 into the page. We mask +// this off to get the starting address for the page */ +// start_addr = ex.a_entry & 0xfffff000; +////// + + if ( ph.id != PLFM_SPARC && N_FLAGS(ex) & EX_PIC ) + handle_ld_info(li, ex.a_text, txtadr); + + create_filename_cmt(); + add_pgm_cmt("Flag value: %Xh", N_FLAGS(ex)); +} + +//---------------------------------------------------------------------- +// +// LOADER DESCRIPTION BLOCK +// +//---------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk76/ldr/aout/aout.h b/idasdk76/ldr/aout/aout.h new file mode 100644 index 0000000..2675cca --- /dev/null +++ b/idasdk76/ldr/aout/aout.h @@ -0,0 +1,283 @@ +#ifndef __AOUT_H__ +#define __AOUT_H__ +#pragma pack(push, 1) + +struct exec +{ + uint32 a_info; // Use macros N_MAGIC, etc for access + uint32 a_text; // length of text, in bytes + uint32 a_data; // length of data, in bytes + uint32 a_bss; // length of bss area for file, in bytes + uint32 a_syms; // length of symbol table data in file, in bytes + uint32 a_entry; // start address + uint32 a_trsize; // length of relocation info for text, in bytes + uint32 a_drsize; // length of relocation info for data, in bytes +// Added for i960 +// uint32 a_tload; // Text runtime load adderr +// uint32 a_dload; // Data runtime load address +// uchar a_talign; // Alignment of text segment +// uchar a_dalign; // Alignmrnt of data segment +// uchar a_balign; // Alignment of bss segment +// char a_relaxable;// Enough info for linker relax +}; +//==================== +#define N_TRSIZE(a) ((a).a_trsize) +#define N_DRSIZE(a) ((a).a_drsize) +#define N_SYMSIZE(a) ((a).a_syms) + +#define N_DYNAMIC(exec) ((exec).a_info & 0x80000000ul) + +#define N_MAGIC(exec) ((exec).a_info & 0xffff) +#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff)) +#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff) +//==================== +enum machine_type +{ +// M_OLDSUN2 = 0, + M_UNKNOWN = 0, + M_68010 = 1, + M_68020 = 2, + M_SPARC = 3, + /*-----------------11.07.98 04:09------------------- + * skip a bunch so we don't run into any of suns numbers */ + /*-----------------11.07.98 04:09------------------- + * make these up for the ns32k*/ + M_NS32032 = (64), /* ns32032 running ? */ + M_NS32532 = (64 + 5), /* ns32532 running mach */ + M_386 = 100, + M_29K = 101, /* AMD 29000 */ + M_386_DYNIX = 102, /* Sequent running dynix */ + M_ARM = 103, /* Advanced Risc Machines ARM */ + M_SPARCLET = 131, /* SPARClet = M_SPARC + 128 */ + M_386_NETBSD = 134, /* NetBSD/i386 binary */ + M_68K_NETBSD = 135, /* NetBSD/m68k binary */ + M_68K4K_NETBSD = 136, /* NetBSD/m68k4k binary */ + M_532_NETBSD = 137, /* NetBSD/ns32k binary */ + M_SPARC_NETBSD = 138, /* NetBSD/sparc binary */ + M_PMAX_NETBSD = 139, /* NetBSD/pmax (MIPS little-endian) binary */ + M_VAX_NETBSD = 140, /* NetBSD/vax binary */ + M_ALPHA_NETBSD = 141, /* NetBSD/alpha binary */ + M_ARM6_NETBSD = 143, /* NetBSD/arm32 binary */ + M_SPARCLET_1 = 147, /* 0x93, reserved */ + M_MIPS1 = 151, /* MIPS R2000/R3000 binary */ + M_MIPS2 = 152, /* MIPS R4000/R6000 binary */ + M_SPARCLET_2 = 163, /* 0xa3, reserved */ + M_SPARCLET_3 = 179, /* 0xb3, reserved */ + M_SPARCLET_4 = 195, /* 0xc3, reserved */ + M_HP200 = 200, /* HP 200 (68010) BSD binary */ + M_HP300 = (300 % 256), /* HP 300 (68020+68881) BSD binary */ + M_HPUX = (0x20c % 256), /* HP 200/300 HPUX binary */ + M_SPARCLET_5 = 211, /* 0xd3, reserved */ + M_SPARCLET_6 = 227, /* 0xe3, reserved */ + M_SPARCLET_7 = 243 /* 0xf3, reserved */ +}; +//==================== +#define OMAGIC 0407 // object file or impure executable +#define NMAGIC 0410 // pure executeable +#define ZMAGIC 0413 // demand-paged executable +#define BMAGIC 0415 // Used by a b.out object +#define QMAGIC 0314 // demand-paged executable with the header in the text. + // The first page is unmapped to help trap NULL pointer + // referenced +#define CMAGIC 0421 // core file +//==================== +// Flags: +#define EX_PIC 0x80 /* contains position independent code */ +#define EX_DYNAMIC 0x40 /* contains run-time link-edit info */ +#define EX_DPMASK 0xC0 /* mask for the above */ +//==================== + +#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \ + && N_MAGIC(x) != NMAGIC \ + && N_MAGIC(x) != ZMAGIC \ + && N_MAGIC(x) != QMAGIC) + +#define _N_HDROFF(x) (1024 - sizeof(struct exec)) + +#define N_TXTOFF(x) \ + (N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \ + (N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec))) + +#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text) +#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data) +#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x)) +#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x)) +#define N_STROFF(x) (N_SYMOFF(x) + (x).a_syms) + +// Address of text segment in memory after it is loaded +#define PAGE_SIZE (1UL << 12) +#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0) + +#define PAGE_SIZE_ARM 0x8000UL +#define N_TXTADDR_ARM(x) (N_MAGIC(x) == QMAGIC ? 0 : PAGE_SIZE_ARM) + +// Address of data segment in memory after it is loaded. (for linux) +/* +#define SEGMENT_SIZE 1024 +#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1)) +#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text) +#define N_DATADDR(x) \ + (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) : \ + (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) +// Address of bss segment in memory after it is loaded +#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data) +*/ +//======================== +struct nlist +{ + union + { + int32 n_strx; + } n_un; + uchar n_type; + char n_other; + short n_desc; + uint32 n_value; +}; + +#define N_UNDF 0 // Undefined symbol +#define N_ABS 2 // Absolute symbol -- addr +#define N_TEXT 4 // Text sym -- offset in text segment +#define N_DATA 6 // Data sym -- offset in data segment +#define N_BSS 8 // BSS sym -- offset in bss segment +#define N_COMM 0x12 // Common symbol (visible after shared) +#define N_FN 0x1F // File name of .o file +#define N_FN_SEQ 0x0C // N_FN from Sequent compilers + +#define N_EXT 1 // External (ORed wits UNDF, ABS, TEXT, DATA or BSS) +#define N_TYPE 0x1E +#define N_STAB 0xE0 // If present - debug symbol + +#define N_INDR 0xA // symbol refernced to another symbol + +#define N_SETA 0x14 // Absolute set element symbol +#define N_SETT 0x16 // Text set element symbol +#define N_SETD 0x18 // Data set element symbol +#define N_SETB 0x1A // Bss set element symbol + +#define N_SETV 0x1C // Pointer to set vector in data area. (from LD) + +#define N_WARNING 0x1E // Text has warnings + +// Weak symbols +#define N_WEAKU 0x0D // Weak undefined +#define N_WEAKA 0x0E // Weak Absolute +#define N_WEAKT 0x0F // Weak Text +#define N_WEAKD 0x10 // Weak Data +#define N_WEAKB 0x11 // Weak BSS + +//======================= + +struct relocation_info +{ + int32 r_address; // Adress (within segment) to be relocated + uint32 r_symbolnum:24;// The meaning of r_symbolnum depends on r_extern + uint32 r_pcrel:1; // Nonzero means value is a pc-relative offset + uint32 r_length:2; // Length (exp of 2) of the field to be relocated. + uint32 r_extern:1; // 1 => relocate with value of symbol. + // r_symbolnum is the index of the symbol + // in file's the symbol table. + // 0 => relocate with the address of a segment. + // r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS + uint32 r_bsr:1; + uint32 r_disp:1; + uint32 r_pad:2; +}; + +//============================ +// The SPARC_ prefix is added to the canonical names below to avoid a name +// conflict if other architectures are added + +enum reloc_type_sparc +{ + SPARC_RELOC_8, SPARC_RELOC_16, SPARC_RELOC_32, // simplest relocs + SPARC_RELOC_DISP8, SPARC_RELOC_DISP16, SPARC_RELOC_DISP32, // disp's (pc-rel) + SPARC_RELOC_WDISP30, SPARC_RELOC_WDISP22, // SR word disp's + SPARC_RELOC_HI22, SPARC_RELOC_22, // SR 22-bit relocs + SPARC_RELOC_13, SPARC_RELOC_LO10, // SR 13&10-bit relocs + SPARC_RELOC_SFA_BASE, SPARC_RELOC_SFA_OFF13, // SR S.F.A. relocs + SPARC_RELOC_BASE10, SPARC_RELOC_BASE13, SPARC_RELOC_BASE22, // base_relative pic + SPARC_RELOC_PC10, SPARC_RELOC_PC22, // special pc-rel pic + SPARC_RELOC_JMP_TBL, // jmp_tbl_rel in pic + SPARC_RELOC_SEGOFF16, // ShLib offset-in-seg + SPARC_RELOC_GLOB_DAT, SPARC_RELOC_JMP_SLOT, SPARC_RELOC_RELATIVE, // rtld relocs +}; + +struct reloc_info_sparc +{ + uint32 r_address; // relocation address (offset in segment) + uint32 r_index:24; // segment index or symbol index + uint32 r_extern:1; // if F, r_index==SEG#, if T, SYM index + uint32 :2; // unused + uint32 r_type:5; // type of relocation to perform + uint32 r_addend; // addend for relocation value +}; + +CASSERT(sizeof(reloc_info_sparc) == 12); + +#define N_PAGSIZ_SPARC(x) 0x02000 +#define N_SEGSIZ_SPARC(x) N_PAGSIZ_SPARC + +#define N_TXTOFF_SPARC(x) ((N_MAGIC(x) == ZMAGIC) ? 0 : sizeof (struct exec)) +#define N_TXTADDR_SPARC(x) \ + ((N_MAGIC(x) == OMAGIC) ? (x).a_entry \ + : ((N_MAGIC(x) == ZMAGIC) && ((x).a_entry < N_PAGSIZ_SPARC(x)) ? 0 \ + : N_PAGSIZ_SPARC(x)) \ + ) + +#define N_DATOFF_SPARC(x) (N_TXTOFF_SPARC(x) + (x).a_text) +#define N_DATADDR_SPARC(x) \ + ((N_MAGIC(x) == OMAGIC) ? (N_TXTADDR_SPARC(x) + (x).a_text) \ + : (N_SEGSIZ_SPARC(x)+((N_TXTADDR_SPARC(x)+(x).a_text-1) \ + & ~(N_SEGSIZ_SPARC(x)-1)))) + +#define N_BSSADDR_SPARC(x) (N_DATADDR_SPARC(x) + (x).a_data) + +#define N_TRELOFF_SPARC(x) (N_DATOFF_SPARC(x) + (x).a_data) +#define N_DRELOFF_SPARC(x) (N_TRELOFF_SPARC(x) + N_TRSIZE(x)) +#define N_SYMOFF_SPARC(x) (N_DRELOFF_SPARC(x) + N_DRSIZE(x)) +#define N_STROFF_SPARC(x) (N_SYMOFF_SPARC(x) + (x).a_syms) + + +//============================ +// Dynamic loader info (restored from a binary form in pc_bsd.aout, not exact): + +struct lddir_t +{ + uint32 unknown0; // 8 + uint32 unknown1; // offset dword_5010 + uint32 ldinfo; +}; + +struct ld_info_t +{ + uint32 unknown0; // 0 + uint32 onemoretable; + uint32 unknown1; // 0 + uint32 off_5060; // points to the end of this struct + uint32 ldentry; // main dynamic loader entry + uint32 imports; + uint32 pairs; // pairs of symbol numbers + uint32 symbols; + uint32 unknown2; // 0 + uint32 unknown3; // 16h + uint32 strings; + uint32 unknown4; // 310h + uint32 unknown5; // 4000h + uint32 unknown6; // 148h + uint32 unknown7; // offset dword_5000 +}; + +struct ld_symbol_t +{ + uint32 nameoff; // offset from the beginning of the string table + uint32 flags; +#define AOUT_LD_FUNC 0x200 +#define AOUT_LD_DEF 0x004 // defined, otherwise - imported +#define AOUT_LD_DATA 0x002 // data + uint32 addr; // pointer to the object + uint32 zero; // always zero? +}; + +#pragma pack(pop) +#endif diff --git a/idasdk75/ldr/aout/common.cpp b/idasdk76/ldr/aout/common.cpp similarity index 100% rename from idasdk75/ldr/aout/common.cpp rename to idasdk76/ldr/aout/common.cpp diff --git a/idasdk76/ldr/aout/makefile b/idasdk76/ldr/aout/makefile new file mode 100644 index 0000000..553c7bb --- /dev/null +++ b/idasdk76/ldr/aout/makefile @@ -0,0 +1,14 @@ +PROC=aout + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)aout$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../../module/sparc/notify_codes.hpp \ + ../idaldr.h aout.cpp aout.h common.cpp diff --git a/idasdk75/ldr/ar/aixar.hpp b/idasdk76/ldr/ar/aixar.hpp similarity index 100% rename from idasdk75/ldr/ar/aixar.hpp rename to idasdk76/ldr/ar/aixar.hpp diff --git a/idasdk75/ldr/ar/ar.hpp b/idasdk76/ldr/ar/ar.hpp similarity index 100% rename from idasdk75/ldr/ar/ar.hpp rename to idasdk76/ldr/ar/ar.hpp diff --git a/idasdk75/ldr/ar/arcmn.cpp b/idasdk76/ldr/ar/arcmn.cpp similarity index 100% rename from idasdk75/ldr/ar/arcmn.cpp rename to idasdk76/ldr/ar/arcmn.cpp diff --git a/idasdk75/ldr/coff/dbxstcla.h b/idasdk76/ldr/coff/dbxstcla.h similarity index 100% rename from idasdk75/ldr/coff/dbxstcla.h rename to idasdk76/ldr/coff/dbxstcla.h diff --git a/idasdk75/ldr/coff/storclas.h b/idasdk76/ldr/coff/storclas.h similarity index 100% rename from idasdk75/ldr/coff/storclas.h rename to idasdk76/ldr/coff/storclas.h diff --git a/idasdk76/ldr/coff/syms.h b/idasdk76/ldr/coff/syms.h new file mode 100644 index 0000000..bef09e4 --- /dev/null +++ b/idasdk76/ldr/coff/syms.h @@ -0,0 +1,862 @@ +#ifndef _H_SYMS +#define _H_SYMS + +#include <../ldr/coff/storclas.h> +#pragma pack(push, 1) + +#define SYMNMLEN 8 /* Number of characters in a symbol name */ +#define FILNMLEN 14 /* Number of characters in a file name */ +#define DIMNUM 4 /* Number of array dimensions in auxiliary entry */ + +struct coff_sym_t // here for efd(di) and ldr/dbg +{ + union + { + char _n_name[SYMNMLEN]; /* old COFF version */ + struct + { + int32 _n_zeroes; /* new == 0 */ + int32 _n_offset; /* offset into string table */ + } _n_n; +// char *_n_nptr[2]; /* allows for overlaying */ + } _n; + uint32 n_value; /* value of symbol */ + uint16 n_scnum; /* section number */ + uint16 n_type; /* type and derived type */ + uchar n_sclass; /* storage class */ + uchar n_numaux; /* number of aux. entries */ +}; + +struct coff_sym64_t +{ + uint64 n_value64; /* value of symbol */ + uint32 n_offset64; /* offset into string table */ + uint16 n_scnum; /* section number */ + union + { + unsigned short _n_type; /* type and derived type */ + struct + { + unsigned char _n_lang; /* source language id */ + unsigned char _n_cpu; /* cputype id */ + } _n_lc; + } _n_tylc; + char n_sclass; /* storage class */ + char n_numaux; /* number of aux. entries */ +}; + +#define IDA_SYM_SZ (SYMNMLEN + 8 + 4 + 2 + 2*1) + +struct ida_sym_t // internal, translated form +{ + union + { + char _n_name[SYMNMLEN]; /* old for short name (<=8) */ + struct + { + int32 _n_zeroes; /* for long name == 0 */ + int32 _n_offset; /* offset into string table */ + } _n_n; + } _n; + uint64 n_value; /* value of symbol */ + uint32 n_scnum; /* section number */ + uint16 n_type; /* type and derived type */ + uchar n_sclass; /* storage class */ + uchar n_numaux; /* number of aux. entries */ +}; + +DECLARE_TYPE_AS_MOVABLE(ida_sym_t); + +#define COFF_SYM_SZ (SYMNMLEN + 4 + 2*2 + 2*1) +#define COFF_SYM64_SZ (8 + 4 + 2 + 2 + 2*1) +#define n_name _n._n_name +#define n_nptr _n._n_nptr[1] +#define n_zeroes _n._n_n._n_zeroes +#define n_offset _n._n_n._n_offset + +/* + * Relocatable symbols have a section number of the + * section in which they are defined. Otherwise, section + * numbers have the following meanings: + */ +#define N_UNDEF 0 // undefined symbol +#define N_ABS uint16(-1) // value of symbol is absolute +#define N_DEBUG uint16(-2) // special debugging symbol -- value of symbol is meaningless +#define N_TV uint16(-3) // indicates symbol needs transfer vector (preload) +#define P_TV uint16(-4) // indicates symbol needs transfer vector (postload) + +/* + * The fundamental type of a symbol packed into the low + * 4 bits of the word. + */ + +#if 0 +#define _EF ".ef" +#endif + +/* + * Type of a symbol, in low N bits of the word + */ +#define T_NULL 0 +#define T_VOID 1 /* function argument (only used by compiler) */ +#define T_CHAR 2 /* character */ +#define T_SHORT 3 /* short integer */ +#define T_INT 4 /* integer */ +#define T_LONG 5 /* long integer */ +#define T_FLOAT 6 /* floating point */ +#define T_DOUBLE 7 /* double word */ +#define T_STRUCT 8 /* structure */ +#define T_UNION 9 /* union */ +#define T_ENUM 10 /* enumeration */ +#define T_MOE 11 /* member of enumeration*/ +#define T_UCHAR 12 /* unsigned character */ +#define T_USHORT 13 /* unsigned short */ +#define T_UINT 14 /* unsigned integer */ +#define T_ULONG 15 /* unsigned long */ +#define T_LNGDBL 16 /* long double */ + +/* + * derived types, in n_type +*/ +#define DT_NON (0) /* no derived type */ +#define DT_PTR (1) /* pointer */ +#define DT_FCN (2) /* function */ +#define DT_ARY (3) /* array */ + +/* + * type packing constants + */ + +#define IDA_N_BTMASK 017 +#define IDA_N_TMASK 060 +#define IDA_N_TMASK1 0300 +#define IDA_N_TMASK2 0360 +#define IDA_N_BTSHFT 4 +#define IDA_N_TSHIFT 2 + +//-------------------------------------------------------------------------- + /* Basic Type of x */ + +#define IDA_BTYPE(x) ((x) & IDA_N_BTMASK) + + /* Is x a pointer ? */ + +#define IDA_ISPTR(x) (((x) & IDA_N_TMASK) == (DT_PTR << IDA_N_BTSHFT)) + + /* Is x a function ? */ + +#define IDA_ISFCN(x) (((x) & IDA_N_TMASK) == (DT_FCN << IDA_N_BTSHFT)) + + /* Is x an array ? */ + +#define IDA_ISARY(x) (((x) & IDA_N_TMASK) == (DT_ARY << IDA_N_BTSHFT)) + + /* Is x a structure, union, or enumeration TAG? */ + +#define IDA_ISTAG(x) ((x)==C_STRTAG || (x)==C_UNTAG || (x)==C_ENTAG) + +#define IDA_INCREF(x) ((((x)&~IDA_N_BTMASK)<<IDA_N_TSHIFT)|(DT_PTR<<IDA_N_BTSHFT)|(x&IDA_N_BTMASK)) + +#define IDA_DECREF(x) ((((x)>>IDA_N_TSHIFT)&~IDA_N_BTMASK)|((x)&IDA_N_BTMASK)) + +/************************************************************************* + * + * AUXILIARY ENTRY FORMAT + * + *************************************************************************/ + +typedef union auxent +{ + struct + { + int32 x_tagndx; /* str, un, or enum tag indx */ +#define x_exptr x_tagndx /* exception table offset */ + union + { + struct + { + uint16 x_lnno; /* declaration line number */ + uint16 x_size; /* str, union, array size */ + } x_lnsz; + int32 x_fsize; /* size of function */ + } x_misc; + union + { + struct + { /* if ISFCN, tag, or .bb */ + int32 x_lnnoptr; /* ptr to fcn line # */ + int32 x_endndx; /* entry ndx past block end */ + } x_fcn; + struct + { /* if ISARY, up to 4 dimen. */ + uint16 x_dimen[DIMNUM]; + } x_ary; + } x_fcnary; + uint16 x_tvndx; /* tv index */ + } x_sym; + + struct + { + struct + { + struct + { + int x_lnno; + } x_lnsz; + } x_misc; + char pad[13]; + char x_auxtype; + } x_sym64; + + union + { + char x_fname[FILNMLEN]; + struct + { + uint32 x_zeroes; + uint32 x_offset; + } _x; + } x_file; + + struct + { + int32 x_scnlen; /* section length */ + uint16 x_nreloc; /* number of relocation entries */ + uint16 x_nlinno; /* number of line numbers */ + uint32 x_chksum; /* checksumm for comdat's */ + uint16 x_asscnt; /* section number to associate with */ + uchar x_select; /* comdat selection type */ +#define SSEL_NODUPL 1 // no duplicate +#define SSEL_ANY 2 // select any +#define SSEL_SIZE 3 +#define SSEL_EXACT 4 // by checksumm +#define SSEL_ASSOC 5 // associative +#define SSEL_LARGEST 6 +#define SSEL_NEWEST 7 + uchar __align__; /* for COFF+ only */ + uint16 x_asscnt_hi; /* for COFF+ only - hi part of x_asscnt */ + } x_scn; // always <= sizeof(SYMENT) :) + + struct + { + int32 x_tvfill; /* tv fill value */ + uint16 x_tvlen; /* length of .tv */ + uint16 x_tvran[2]; /* tv range */ + } x_tv; /* info about .tv section (in auxent of symbol .tv)) */ + + /****************************************** + * RS/6000-specific auxent - last auxent for every external symbol + ******************************************/ + struct + { + int32 x_scnlen; /* csect length */ + int32 x_parmhash; /* parm type hash index */ + uint16 x_snhash; /* sect num with parm hash */ + uchar x_smtyp; /* symbol align and type */ + /* 0-4 - Log 2 of alignment */ + /* 5-7 - symbol type */ +#define SMTYP_ALIGN(x) ((x) >> 3) /* log2 of alignment */ +#define SMTYP_SMTYP(x) ((x) & 0x7) /* symbol type */ +/* Symbol type values: */ +#define XTY_ER 0 /* External reference */ +#define XTY_SD 1 /* Csect definition */ +#define XTY_LD 2 /* Label definition */ +#define XTY_CM 3 /* .BSS */ +#define XTY_EM 4 /* Error message */ +#define XTY_US 5 /* "Reserved for internal use" */ + uchar x_smclas; /* storage mapping class */ +#define XMC_PR 0 /* Read-only program code */ +#define XMC_RO 1 /* Read-only constant */ +#define XMC_DB 2 /* Read-only debug dictionary table */ +#define XMC_TC 3 /* Read-write general TOC entry */ +#define XMC_UA 4 /* Read-write unclassified */ +#define XMC_RW 5 /* Read-write data */ +#define XMC_GL 6 /* Read-only global linkage */ +#define XMC_XO 7 /* Read-only extended operation */ +#define XMC_SV 8 /* Read-only supervisor call */ +#define XMC_BS 9 /* Read-write BSS */ +#define XMC_DS 10 /* Read-write descriptor csect */ +#define XMC_UC 11 /* Read-write unnamed Fortran common */ +#define XMC_TI 12 /* Read-only traceback index csect */ +#define XMC_TB 13 /* Read-only traceback table csect */ +/* 14 ??? */ +#define XMC_TC0 15 /* Read-write TOC anchor */ +#define XMC_TD 16 /* Read-write data in TOC */ + int32 x_stab; /* dbx stab info index */ + uint16 x_snstab; /* sect num with dbx stab */ + } x_csect; /* csect definition information */\ + +/* XCOFF64 _csect */ + struct + { + uint32 x_scnlen_lo; + int32 x_parmhash; + uint16 x_snhash; + uchar x_smtyp; + uchar x_smclas; +#define XMC_SV64 17 +#define XMC_SV2364 18 + int32 x_scnlen_hi; + char pad; + char x_auxtype; + } x_csect64; + + /****************************************** + * I960-specific *2nd* aux. entry formats + ******************************************/ + struct + { +#define x_stdindx x_stindx /* This is a very old typo that keeps getting propagated. */ + int32 x_stindx; /* sys. table entry */ + } x_sc; /* system call entry */ + + struct + { + uint32 x_balntry; /* BAL entry point */ + } x_bal; /* BAL-callable function */ + +} AUXENT; + +/* Defines for "special" symbols */ + +#if vax +#define _ETEXT "_etext" +#define _EDATA "_edata" +#define _END "_end" +#else +#define _ETEXT "etext" +#define _EDATA "edata" +#define _END "end" +#endif + +#define _START "_start" + +//================================================================================ +// ECOFF symbols +//================================================================================ + +#define estNil 0 /* Nuthin' special */ +#define estGlobal 1 /* external symbol */ +#define estStatic 2 /* static */ +#define estParam 3 /* procedure argument */ +#define estLocal 4 /* local variable */ +#define estLabel 5 /* label */ +#define estProc 6 /* " " Procedure */ +#define estBlock 7 /* beginnning of block */ +#define estEnd 8 /* end (of anything) */ +#define estMember 9 /* member (of anything - struct/union/enum */ +#define estTypedef 10 /* type definition */ +#define estFile 11 /* file name */ +#define estRegReloc 12 /* register relocation */ +#define estForward 13 /* forwarding address */ +#define estStaticProc 14 /* load time only static procs */ +#define estConstant 15 /* const */ +#define estStaParam 16 /* Fortran static parameters */ + /* These new symbol types have been recently added to SGI machines. */ +#define estStruct 26 /* Beginning of block defining a struct type */ +#define estUnion 27 /* Beginning of block defining a union type */ +#define estEnum 28 /* Beginning of block defining an enum type */ +#define estIndirect 34 /* Indirect type specification */ + /* Pseudo-symbols - internal to debugger */ +#define estStr 60 /* string */ +#define estNumber 61 /* pure number (ie. 4 NOR 2+2) */ +#define estExpr 62 /* 2+2 vs. 4 */ +#define estType 63 /* post-coersion SER */ +#define estMax 64 + +#define escNil 0 +#define escText 1 /* text symbol */ +#define escData 2 /* initialized data symbol */ +#define escBss 3 /* un-initialized data symbol */ +#define escRegister 4 /* value of symbol is register number */ +#define escAbs 5 /* value of symbol is absolute */ +#define escUndefined 6 /* who knows? */ +#define escCdbLocal 7 /* variable's value is IN se->va.?? */ +#define escBits 8 /* this is a bit field */ +#define escCdbSystem 9 /* variable's value is IN CDB's address space */ +#define escDbx 9 /* overlap dbx internal use */ +#define escRegImage 10 /* register value saved on stack */ +#define escInfo 11 /* symbol contains debugger information */ +#define escUserStruct 12 /* address in struct user for current process */ +#define escSData 13 /* load time only small data */ +#define escSBss 14 /* load time only small common */ +#define escRData 15 /* load time only read only data */ +#define escVar 16 /* Var parameter (fortran,pascal) */ +#define escCommon 17 /* common variable */ +#define escSCommon 18 /* small common */ +#define escVarRegister 19 /* Var parameter in a register */ +#define escVariant 20 /* Variant record */ +#define escSUndefined 21 /* small undefined(external) data */ +#define escInit 22 /* .init section symbol */ +#define escBasedVar 23 /* Fortran or PL/1 ptr based var */ +#define escXData 24 /* exception handling data */ +#define escPData 25 /* Procedure section */ +#define escFini 26 /* .fini section */ +#define escRConst 27 /* .rconst section */ +#define escMax 32 + +struct ecoff_hdr +{ + uint16 magic; +#define ECOFF_SYM_MAGIC 0x1992 + uint16 vstamp; + uint32 ilineMax; + uint32 idnMax; + uint32 ipdMax; + uint32 isymMax; + uint32 ioptMax; + uint32 iauxMax; + uint32 issMax; + uint32 issExtMax; + uint32 ifdMax; + uint32 crfd; + uint32 iextMax; + uint64 cbLine; + uint64 cbLineOffset; + uint64 cbDnOffset; + uint64 cbPdOffset; + uint64 cbSymOffset; + uint64 cbOptOffset; + uint64 cbAuxOffset; + uint64 cbSsOffset; + uint64 cbSsExtOffset; + uint64 cbFdOffset; + uint64 cbRfdOffset; + uint64 cbExtOffset; +}; + +struct ecoff_fdr +{ + uint64 f_adr; + uint64 f_cbLineOffset; + uint64 f_cbLine; + uint64 f_cbSs; + uint32 f_rss; + uint32 f_issBase; + uint32 f_isymBase; + uint32 f_csym; + uint32 f_ilineBase; + uint32 f_cline; + uint32 f_ioptBase; + uint32 f_copt; + uint32 f_ipdFirst; + uint32 f_cpd; + uint32 f_iauxBase; + uint32 f_caux; + uint32 f_rfdBase; + uint32 f_crfd; + uchar f_bits1; + uchar f_bits2[3]; + uchar f_padding[4]; +}; + +/* Procedure descriptor external record */ + +struct ecoff_pdr +{ + uint64 adr; + uint64 cbLineOffset; + uint32 isym; + uint32 iline; + uint32 regmask; + uint32 regoffset; + uint32 iopt; + uint32 fregmask; + uint32 fregoffset; + uint32 frameoffset; + uint32 lnLow; + uint32 lnHigh; + uchar gp_prologue; + uchar bits1; + uchar bits2; + uchar localoff; + uint16 framereg; + uint16 pcreg; +}; + +/* Line numbers */ + +struct ecoff_line +{ + uint32 l_line; +}; + +/* Symbol external record */ + +#define SYM_BITS1_ST_BIG 0xFC +#define SYM_BITS1_ST_SH_BIG 2 +#define SYM_BITS1_ST_LITTLE 0x3F +#define SYM_BITS1_ST_SH_LITTLE 0 + +#define SYM_BITS1_SC_BIG 0x03 +#define SYM_BITS1_SC_SH_LEFT_BIG 3 +#define SYM_BITS1_SC_LITTLE 0xC0 +#define SYM_BITS1_SC_SH_LITTLE 6 + +#define SYM_BITS2_SC_BIG 0xE0 +#define SYM_BITS2_SC_SH_BIG 5 +#define SYM_BITS2_SC_LITTLE 0x07 +#define SYM_BITS2_SC_SH_LEFT_LITTLE 2 + +#define SYM_BITS2_RESERVED_BIG 0x10 +#define SYM_BITS2_RESERVED_LITTLE 0x08 + +#define SYM_BITS2_INDEX_BIG 0x0F +#define SYM_BITS2_INDEX_SH_LEFT_BIG 16 +#define SYM_BITS2_INDEX_LITTLE 0xF0 +#define SYM_BITS2_INDEX_SH_LITTLE 4 + +#define SYM_BITS3_INDEX_SH_LEFT_BIG 8 +#define SYM_BITS3_INDEX_SH_LEFT_LITTLE 4 + +#define SYM_BITS4_INDEX_SH_LEFT_BIG 0 +#define SYM_BITS4_INDEX_SH_LEFT_LITTLE 12 + +struct ecoff_sym +{ + uint64 s_value; + uint32 s_iss; + uchar s_bits1; + uchar s_bits2; + uchar s_bits3; + uchar s_bits4; + uchar st(bool mf) + { + return mf + ? ((s_bits1 & SYM_BITS1_ST_BIG ) >> SYM_BITS1_ST_SH_BIG) + : ((s_bits1 & SYM_BITS1_ST_LITTLE) >> SYM_BITS1_ST_SH_LITTLE); + } + uchar sc(bool mf) + { + return mf + ? (((s_bits1 & SYM_BITS1_SC_BIG ) << SYM_BITS1_SC_SH_LEFT_BIG) + | ((s_bits2 & SYM_BITS2_SC_BIG ) >> SYM_BITS2_SC_SH_BIG)) + : (((s_bits1 & SYM_BITS1_SC_LITTLE) >> SYM_BITS1_SC_SH_LITTLE) + | ((s_bits2 & SYM_BITS2_SC_LITTLE) << SYM_BITS2_SC_SH_LEFT_LITTLE)); + } + uint32 index(bool mf) + { + return mf + ? (((s_bits2 & SYM_BITS2_INDEX_BIG) << SYM_BITS2_INDEX_SH_LEFT_BIG) + | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_BIG) + | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_BIG)) + : (((s_bits2 & SYM_BITS2_INDEX_LITTLE) >> SYM_BITS2_INDEX_SH_LITTLE) + | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_LITTLE) + | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_LITTLE)); + } +}; + +/* The auxiliary type information is the same on all known ECOFF + targets. The internal forms are + defined in coff/sym.h, which was originally donated by MIPS + Computer Systems. */ + +/* Type information external record */ + +struct ecoff_tir +{ + uchar t_bits1; + uchar t_tq45; + uchar t_tq01; + uchar t_tq23; + bool fBitfield(bool mf) { return (t_bits1 & (mf ? 0x80 : 0x01)) != 0; } + bool continued(bool mf) { return (t_bits1 & (mf ? 0x40 : 0x02)) != 0; } + uchar bt(bool mf) { return mf ? (t_bits1 & 0x3F) >> 0 : (t_bits1 & 0xFC) >> 2; } + uchar tq4(bool mf) { return mf ? (t_tq45 & 0xF0) >> 4 : (t_tq45 & 0x0F) >> 0; } + uchar tq5(bool mf) { return mf ? (t_tq45 & 0x0F) >> 0 : (t_tq45 & 0xF0) >> 4; } + uchar tq0(bool mf) { return mf ? (t_tq01 & 0xF0) >> 4 : (t_tq01 & 0x0F) >> 0; } + uchar tq1(bool mf) { return mf ? (t_tq01 & 0x0F) >> 0 : (t_tq01 & 0xF0) >> 4; } + uchar tq2(bool mf) { return mf ? (t_tq23 & 0xF0) >> 4 : (t_tq23 & 0x0F) >> 0; } + uchar tq3(bool mf) { return mf ? (t_tq23 & 0x0F) >> 0 : (t_tq23 & 0xF0) >> 4; } +}; + +/* Relative symbol external record */ + +struct ecoff_rndx +{ + uchar r_bits[4]; + uint16 rfd(bool mf) + { + return mf + ? (r_bits[0] << 4) | ((r_bits[1] & 0xF0) >> 4) + : (r_bits[0] << 0) | ((r_bits[1] & 0x0F) << 8); + } + uint32 index(bool mf) + { + return mf + ? ((r_bits[1] & 0x0F) << 16) + | (r_bits[2] << 8) + | (r_bits[3] << 0) + : ((r_bits[1] & 0xF0) >> 4) + | (r_bits[2] << 4) + | (r_bits[3] << 12); + } +}; + +/* Auxiliary symbol information external record */ + +union ecoff_aux +{ + ecoff_tir a_ti; + ecoff_rndx a_rndx; + uint32 a_dnLow; + uint32 a_dnHigh; + uint32 a_isym; + uint32 a_iss; + uint32 a_width; + uint32 a_count; +}; + +/* External symbol external record */ + +struct ecoff_ext +{ + ecoff_sym es_asym; + uchar es_bits1; + uchar es_bits2[3]; + uint32 es_ifd; +}; + +/* Dense numbers external record */ + +struct ecoff_dnr +{ + uint32 d_rfd; + uint32 d_index; +}; + +/* Relative file descriptor */ + +struct ecoff_rfd +{ + uint32 rfd; +}; + +/* Optimizer symbol external record */ + +struct ecoff_opt +{ + uchar o_bits1; + uchar o_bits2; + uchar o_bits3; + uchar o_bits4; + ecoff_rndx o_rndx; + uint32 o_offset; + uchar ot(void) { return o_bits1; } + uint32 value(bool mf) + { + return mf + ? ((uint32(o_bits2) << 16) + | (uint32(o_bits3) << 8) + | (uint32(o_bits4) << 0)) + : ((uint32(o_bits2) << 0) + | (uint32(o_bits3) << 8) + | (uint32(o_bits4) << 16)); + } +}; + +//--------------------------------------------------------------------------- +// MIPS symbolic information +//--------------------------------------------------------------------------- + +struct mips_ecoff_hdr +{ + uint16 magic; +#define MIPS_SYM_MAGIC 0x7002 + uint16 vstamp; + uint32 ilineMax; + uint32 cbLine; + uint32 cbLineOffset; + uint32 idnMax; + uint32 cbDnOffset; + uint32 ipdMax; + uint32 cbPdOffset; + uint32 isymMax; + uint32 cbSymOffset; + uint32 ioptMax; + uint32 cbOptOffset; + uint32 iauxMax; + uint32 cbAuxOffset; + uint32 issMax; + uint32 cbSsOffset; + uint32 issExtMax; + uint32 cbSsExtOffset; + uint32 ifdMax; + uint32 cbFdOffset; + uint32 crfd; + uint32 cbRfdOffset; + uint32 iextMax; + uint32 cbExtOffset; +}; + +struct mips_ecoff_fdr +{ + uint32 f_adr; + uint32 f_rss; + uint32 f_issBase; + uint32 f_cbSs; + uint32 f_isymBase; + uint32 f_csym; + uint32 f_ilineBase; + uint32 f_cline; + uint32 f_ioptBase; + uint32 f_copt; + uint16 f_ipdFirst; + uint16 f_cpd; + uint32 f_iauxBase; + uint32 f_caux; + uint32 f_rfdBase; + uint32 f_crfd; + uchar f_bits1; + uchar f_bits2[3]; + uint32 f_cbLineOffset; + uint32 f_cbLine; +}; + +/* Procedure descriptor external record */ + +struct mips_ecoff_pdr +{ + uint32 adr; + uint32 isym; + uint32 iline; + uint32 regmask; + uint32 regoffset; + uint32 iopt; + uint32 fregmask; + uint32 fregoffset; + uint32 frameoffset; + uint16 framereg; + uint16 pcreg; + uint32 lnLow; + uint32 lnHigh; + uint32 cbLineOffset; +}; + +/* Line numbers */ + +struct mips_ecoff_line +{ + uint32 l_line; +}; + +/* Symbol external record */ + +struct mips_ecoff_sym +{ + uint32 s_iss; + uint32 s_value; + uchar s_bits1; + uchar s_bits2; + uchar s_bits3; + uchar s_bits4; + uchar st(bool mf) + { + return mf + ? ((s_bits1 & SYM_BITS1_ST_BIG ) >> SYM_BITS1_ST_SH_BIG) + : ((s_bits1 & SYM_BITS1_ST_LITTLE) >> SYM_BITS1_ST_SH_LITTLE); + } + uchar sc(bool mf) + { + return mf + ? (((s_bits1 & SYM_BITS1_SC_BIG ) << SYM_BITS1_SC_SH_LEFT_BIG) + | ((s_bits2 & SYM_BITS2_SC_BIG ) >> SYM_BITS2_SC_SH_BIG)) + : (((s_bits1 & SYM_BITS1_SC_LITTLE) >> SYM_BITS1_SC_SH_LITTLE) + | ((s_bits2 & SYM_BITS2_SC_LITTLE) << SYM_BITS2_SC_SH_LEFT_LITTLE)); + } + uint32 index(bool mf) + { + return mf + ? (((s_bits2 & SYM_BITS2_INDEX_BIG) << SYM_BITS2_INDEX_SH_LEFT_BIG) + | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_BIG) + | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_BIG)) + : (((s_bits2 & SYM_BITS2_INDEX_LITTLE) >> SYM_BITS2_INDEX_SH_LITTLE) + | (s_bits3 << SYM_BITS3_INDEX_SH_LEFT_LITTLE) + | (s_bits4 << SYM_BITS4_INDEX_SH_LEFT_LITTLE)); + } +}; + +#define mips_ecoff_aux ecoff_aux + +/* External symbol external record */ + +struct mips_ecoff_ext +{ + uchar es_bits1; + uchar es_bits2; + uint16 es_ifd; + mips_ecoff_sym es_asym; +}; + +#define mips_ecoff_dnr ecoff_dnr +#define mips_ecoff_rfd ecoff_rfd +#define mips_ecoff_opt ecoff_opt + +/* segment information */ +struct ic_seginfo_t +{ + const ida_sym_t *sym = nullptr; // comdat symbol + ea_t start = BADADDR; // segment start address, BADADDR - not loaded + adiff_t delta = 0; // difference between the loaded address + // and address in the file + ea_t paddr = 0; // s_paddr from the segment descriptor +}; +DECLARE_TYPE_AS_MOVABLE(ic_seginfo_t); +struct ic_seginfos_t : public qvector<ic_seginfo_t> {}; + +//---------------------------------------------------------------------- +inline bool is_arm_switcher(const char *name) +{ + return strncmp(name, "$CODE", 5) == 0 + && (name[5] == '1' || name[5] == '3') + && (name[6] == '6' || name[6] == '2') + && name[7] == '\0'; +} + +struct i960_sym_t; +struct coff_sym_ex_t; +struct ida_filhdr_t; +struct ida_scnhdr_t; + +//---------------------------------------------------------------------- +class ida_syms_t +{ + struct coff_vars_t &ctx; + qstring str_table; // standard COFF string table (includes size in first 4 bytes) + qstring dtable; // XCOFF debug table (does not include size) + + void from_coff960(const i960_sym_t *pc, uint nsyms, bool coff_hdr_mf); + void from_bigcoff(const coff_sym_ex_t *pc, uint nsyms, bool coff_hdr_mf); + void from_xcoff64(const coff_sym64_t *pc, uint nsyms, bool coff_hdr_mf); + void from_coffsym(const coff_sym_t *pc, uint nsyms, bool coff_hdr_mf); +public: + qvector<ida_sym_t> symtab; + + ida_syms_t(coff_vars_t &_ctx) : ctx(_ctx) {} + bool str_table_from_file(linput_t *li, bool coff_hdr_mf); + bool str_table_from_mem(const void *buf, size_t bufsize, bool coff_hdr_mf); + bool load_from_file( + linput_t *li, + const ida_filhdr_t &fh, + bool coff_hdr_mf); + bool load_from_mem(const void *symbuf, size_t bufsize, uint32 nsyms, bool coff_hdr_mf); +#if !defined(COMPILE_DBG_LOADER) + void load_xcoff_debug_table(linput_t *li, const qvector<ida_scnhdr_t> &sechdrs); +#endif + const ida_sym_t *load_external_coff_symbols(linput_t *li, ida_filhdr_t &hf, bool mf); + + void qclear() + { + str_table.qclear(); + dtable.qclear(); + symtab.qclear(); + } + + void copy_from_str_table(char *buf, size_t bufsz, uint32 off, bool use_dtable = false) const; + const char *get_segment_name(const char *name, size_t fixlen, char *buffer, size_t bufsize, uint32 f_magic) const; + bool getaux(uint symidx, AUXENT &aux, uint &n_aux) const; + char *getname(uint symidx, char *buf, size_t bufsize) const; +}; + +#pragma pack(pop) +#endif /* _H_SYMS */ diff --git a/idasdk75/ldr/dos/cv.hpp b/idasdk76/ldr/dos/cv.hpp similarity index 100% rename from idasdk75/ldr/dos/cv.hpp rename to idasdk76/ldr/dos/cv.hpp diff --git a/idasdk76/ldr/dos/dos.cpp b/idasdk76/ldr/dos/dos.cpp new file mode 100644 index 0000000..2347560 --- /dev/null +++ b/idasdk76/ldr/dos/dos.cpp @@ -0,0 +1,762 @@ +/* + * This Loader Module is written by Ilfak Guilfanov and + * rewriten by Yury Haron + * + */ +/* + L O A D E R for MS-DOS file format's +*/ + +#include "../idaldr.h" +#include <exehdr.h> +#include <setjmp.h> +#include <typeinf.hpp> +#include "dos_ovr.h" +#include "cv.hpp" + +static const char fn_ovr[] = "MS-DOS executable (perhaps overlayed)", + fn_exe[] = "MS-DOS executable (EXE)", + fn_drv[] = "MS-DOS SYS-file (perhaps device driver)"; +const char e_exe[] = "exe"; + +static jmp_buf jmpb; + +#define R_ss 18 // this comes from intel.hpp + +//-------------------------------------------------------------------------- +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *filename) +{ + static int order = 0; + if ( order >= 4 ) + return 0; + + uint32 fLen = qlsize(li); + const char *file_ext = get_file_ext(filename); + if ( file_ext == NULL ) + file_ext = ""; + + exehdr E; + *processor = "metapc"; + switch ( order ) + { + case 0: + if ( fLen <= sizeof(E) ) + { + order = 3; // check for com + break; + } + + CASSERT(sizeof(E) >= 16); + lread(li, &E, sizeof(E)); + if ( E.exe_ident != EXE_ID && E.exe_ident != EXE_ID2 + || E.HdrSize*16 < sizeof(E) ) + { + order = 2; // check for drv + break; + } + if ( fLen < E.HdrSize*16 ) + return 0; + if ( E.ReloCnt != 0 ) + { + if ( E.TablOff + (E.ReloCnt*4) > fLen + || E.TablOff != 0 && E.TablOff < sizeof(E) + || E.TablOff == 0 ) + { + return 0; + } + } + if ( E.CalcEXE_Length() < fLen - E.HdrSize*16 + && PrepareOverlayType(li, &E) != ovr_noexe ) + { + *fileformatname = fn_ovr; + ++order; + return f_EXE | ACCEPT_CONTINUE; + } + // no break + case 1: + *fileformatname = fn_exe; + order = 5; // done + return f_EXE; + + case 2: + case 3: + break; + + default: + return 0; + } + + if ( ++order == 3 ) + { + if ( strieq(file_ext, "sys") || strieq(file_ext, "drv") ) + { + *fileformatname = fn_drv; + return f_DRV | ACCEPT_CONTINUE; + } + order++; // 4 + } + + if ( strieq(file_ext, "com") ) + { // com files must be readable + // on wince, file .exe files are unreadable. we do not want them to + // be detected as com files + qlseek(li, 0); + if ( qlread(li, &fLen, 1) == 1 ) + { + *fileformatname = "MS-DOS COM-file"; + return f_COM; + } + } + return 0; +} + +//------------------------------------------------------------------------- +NORETURN void errstruct(void) +{ + if ( ask_yn(ASKBTN_CANCEL, + "HIDECANCEL\n" + "Bad file structure or read error.\n" + "Proceed with the loaded infomration?") <= ASKBTN_NO ) + { + loader_failure(); + } + longjmp(jmpb, 1); +#ifdef __CODEGEARC__ + exit(0); // suppress compiler error +#endif +} + +//------------------------------------------------------------------------- +int CheckCtrlBrk(void) +{ + if ( user_cancelled() ) + { + if ( ask_yn(ASKBTN_NO, + "HIDECANCEL\n" + "Do you really want to abort loading?") > ASKBTN_NO ) + { + loader_failure(); + } + clr_cancelled(); + return 1; + } + return 0; +} + +//------------------------------------------------------------------------- +void add_segm_by_selector(sel_t base, const char *sclass) +{ + segment_t *ptr = get_segm_by_sel(base); + + if ( ptr == NULL || ptr->sel != base ) + { + ea_t ea = sel2ea(base); + if ( ea > inf_get_omax_ea() ) + inf_set_omax_ea(ea); + + segment_t s; + s.sel = base; + s.start_ea = sel2ea(base); + s.end_ea = inf_get_omax_ea(); + s.align = saRelByte; + s.comb = sclass != NULL && strcmp(sclass, "STACK") == 0 ? scStack : scPub; + add_segm_ex(&s, NULL, sclass, ADDSEG_SPARSE | ADDSEG_NOSREG); + } +} + +//------------------------------------------------------------------------- +// +// For all addresses in relocation table: +// add 'delta' +// if ( dosegs ) then make segments +// +static void doRelocs(int16 delta, bool dosegs, netnode ovr_info) +{ + + if ( ovr_info == BADNODE ) + return; + + fixup_data_t fd(FIXUP_SEG16); + for ( ea_t xEA = ovr_info.altfirst(); xEA != BADADDR; xEA = ovr_info.altnext(xEA) ) + { + show_addr(xEA); + + uint16 curval = get_word(xEA); + uint16 base = curval + delta; + if ( base < curval && delta > 0 ) + { + ask_for_feedback("%a: fixup overflow; skipping fixup processing", xEA); + break; + } + put_word(xEA, base); + fd.sel = base; + fd.set(xEA); + if ( dosegs ) + add_segm_by_selector(base, NULL); + CheckCtrlBrk(); + } +} + +//-------------------------------------------------------------------------- +static void create_msdos_segments(bool com_mode, netnode ovr_info) +{ + // msg("Creating segments...\n"); + add_segm_by_selector(find_selector(inf_get_start_cs()), CLASS_CODE); + if ( com_mode ) // COM/DRV + { + set_segm_start(inf_get_omin_ea(), inf_get_omin_ea(), SEGMOD_KILL); + inf_set_min_ea(inf_get_omin_ea()); + + segment_t *s = getseg(inf_get_min_ea()); + if ( s ) + { + s->set_comorg(); // i display ORG directive + s->update(); + } + } + if ( inf_get_start_ss() != BADSEL && inf_get_start_ss() != inf_get_start_cs() ) + add_segm_by_selector(inf_get_start_ss(), CLASS_STACK); + else // specify the sp value for the first segment + set_default_sreg_value(get_segm_by_sel(inf_get_start_cs()), R_ss, inf_get_start_cs()); + doRelocs(inf_get_baseaddr(), true, ovr_info); + + ea_t ea = inf_get_omin_ea(); + ea_t omea = inf_get_omax_ea(); + for ( int i = 0; ea < omea; ) + { + segment_t *sptr = getnseg(i); + if ( sptr == NULL || ea < sptr->start_ea ) + { + msg("Dummy segment at 0x%a (next segment at 0x%a)\n", + ea, + sptr == NULL ? BADADDR : sptr->start_ea); + add_segm_by_selector(unsigned(ea>>4), "DUMMY"); + } + else + { + ea = sptr->end_ea; + if ( !is_mapped(ea) ) + ea = next_addr(ea); + ++i; + } + } +} + +//-------------------------------------------------------------------------- +bool pos_read(linput_t *li, uint32 pos, void *buf, size_t size) +{ + qlseek(li, pos); + return qlread(li, buf, size) != size; +} + +//-------------------------------------------------------------------------- +static ea_t FindDseg(void) +{ + ea_t dea = to_ea(inf_get_start_cs(), inf_get_start_ip()); + + if ( get_byte(dea) == 0x9A ) // call far + { + dea = to_ea(sel2para(get_word(dea+3)), get_word(dea+1)); + inf_set_strtype(STRTYPE_PASCAL); + } + // + // Borland startup + // + uchar code = get_byte(dea); + uchar reg = code & 7; + if ( (code & ~7) == 0xB8 // mov reg, ???? + && ((get_byte(dea+3) == 0x8E + && ((code=get_byte(dea+4)) & ~7) == 0xD8 // mov ds, reg + && (code & 7) == reg) + || (get_byte(dea+3) == 0x2E // mov cs:@DGROUP, reg + && get_byte(dea+4) == 0x89 + && ((code = get_byte(dea+5)) & 0x8F) == 6 + && ((code>>3) & 7) == reg)) ) + { + segment_t *s = get_segm_by_sel(get_word(dea + 1)); + return s == NULL ? BADADDR : s->start_ea; + } + // + // Watcom startup + // + if ( get_byte(dea) == 0xE9 ) // jmp ??? + { + dea = dea + 3 + get_word(dea + 1); + if ( get_byte(dea + 0) == 0xFB // sti + && get_byte(dea + 1) == 0xB9 ) // mov cx, ??? + { + segment_t *s = get_segm_by_sel(get_word(dea + 2)); + return s == NULL ? BADADDR : s->start_ea; + } + } + // + // Generic: find copyright notice + // + static const char *const copyr[] = + { + " - Copyright", + // "Borland C++ - Copyright 1991 Borland Intl.", + // "Turbo-C - Copyright (c) 1988 Borland Intl.", + // "Turbo C - Copyright 1989 Borland Intl.", + // "Turbo C++ - Copyright 1990 Borland Intl.", + // "MS Run-Time Library - Copyright (c)", + NULL + }; + for ( const char *const *p = copyr; *p != NULL; ++p ) + { + msg("Looking for '%s'...\n", *p); + ea_t dataea = bin_search2(inf_get_min_ea(), + inf_get_max_ea(), + (uchar *)*p, + NULL, + strlen(*p), + BIN_SEARCH_CASE|BIN_SEARCH_FORWARD); + if ( dataea != BADADDR ) + return dataea; + } + return BADADDR; +} + +//-------------------------------------------------------------------------- +static void setup_default_ds_register(sel_t ds_value) +{ + segment_t *dseg; + + if ( ds_value != BADSEL ) + { + dseg = get_segm_by_sel(ds_value); + goto setname; + } + msg("Searching for the data segment...\n"); + switch ( inf_get_filetype() ) + { + case f_EXE: // Find default data seg + { + ea_t dataea = FindDseg(); + if ( dataea == BADADDR ) + return; + dseg = getseg(dataea); + if ( dseg == NULL ) + return; + } + dseg->align = saRelPara; + ds_value = dseg->sel; +setname: + set_segm_class(dseg, CLASS_DATA); + set_segm_name(dseg, "dseg"); + break; + case f_COM: + ds_value = find_selector(inf_get_start_cs()); + break; + default: + return; + } + msg("Default DS register: 0x%*a\n", 4, ds_value); + set_default_dataseg(ds_value); +} + +//-------------------------------------------------------------------------- +// +// load file into the database. +// +void idaapi load_file(linput_t *li, ushort neflag, const char *fileformatname) +{ + exehdr E; + netnode ovr_info = BADNODE; + volatile int type = 0; // volatile because of setjmp() + volatile sel_t dseg = BADSEL; + volatile o_type ovr_type = ovr_noexe; + + processor_t &ph = PH; + if ( setjmp(jmpb) == 0 ) + { + set_processor_type("metapc", SETPROC_LOADER); + + type = strieq(fileformatname, fn_ovr) ? 3 + : strieq(fileformatname, fn_exe) ? 2 + : strieq(fileformatname, fn_drv) ? 1 + : 0; + + clr_cancelled(); + + uval_t start_off; + uval_t fcoresize; + cm_t cm = inf_get_cc_cm() & CM_CC_MASK; + if ( type < 2 ) // COM/DRV + { + inf_set_cc_cm(cm | C_PC_SMALL); + if ( !type ) // f_COM + { + inf_set_start_ip(0x100); + inf_set_min_ea(to_ea(inf_get_baseaddr(), inf_get_start_ip())); + } + else + { // f_DRV + inf_set_start_ip(BADADDR); + inf_set_min_ea(to_ea(inf_get_baseaddr(), 0 /*binoff*/)); + // binoff has no sense for COM/DRV + } + inf_set_start_cs(inf_get_baseaddr()); + start_off = 0; + fcoresize = qlsize(li); + inf_set_max_ea(inf_get_min_ea() + fcoresize); + } + else + { // EXE (/OVR) + inf_set_cc_cm(cm | C_PC_LARGE); + lread(li, &E, sizeof(E)); + if ( !E.ReloCnt + && ask_yn(ASKBTN_YES, + "HIDECANCEL\nPossibly packed file, continue?") <= ASKBTN_NO ) + { + loader_failure(); + } + inf_set_start_ss(E.ReloSS); + inf_set_start_cs(E.ReloCS); + inf_set_start_sp(E.ExeSP); + inf_set_start_ip(E.ExeIP); + // take into account pointers like FFF0:0100 + // FFF0 should be treated as signed in this case + if ( inf_get_start_cs() >= 0xFFF0 || inf_get_start_ss() >= 0xFFF0 ) + { + if ( inf_get_baseaddr() < 0x10 ) + inf_set_baseaddr(0x10); + if ( inf_get_start_cs() >= 0xFFF0 ) + inf_set_start_cs(short(inf_get_start_cs())); + if ( inf_get_start_ss() >= 0xFFF0 ) + inf_set_start_ss(short(inf_get_start_ss())); + } + inf_set_start_ss(inf_get_start_ss() + inf_get_baseaddr()); + inf_set_start_cs(inf_get_start_cs() + inf_get_baseaddr()); + inf_set_min_ea(to_ea(inf_get_baseaddr(), 0)); + fcoresize = E.CalcEXE_Length(); + + ovr_info.create(LDR_INFO_NODE); + ovr_info.set((char *)&E, sizeof(E)); + + // i Check for file size + uint32 fsize = qlsize(li) - E.HdrSize*16; + if ( fcoresize > fsize ) + fcoresize = fsize; + if ( type == 2 + && fcoresize < fsize + && ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "The input file has extra information at the end\n" + "(tail %Xh, loaded %ah), continue?", + fsize, + fcoresize) <= ASKBTN_NO ) + { + loader_failure(); + } + inf_set_max_ea(inf_get_min_ea() + fcoresize); + + ea_t stackEA = to_ea(inf_get_start_ss(), inf_get_start_sp()); + if ( inf_get_max_ea() < stackEA ) + inf_set_max_ea(stackEA); + msg("Reading relocation table...\n"); + if ( E.ReloCnt ) + { + qlseek(li, E.TablOff); + for ( int i = 0; i < E.ReloCnt; ++i ) + { + ushort buf[2]; + + lread(li, buf, sizeof(buf)); + + ea_t xEA = to_ea((ushort)(inf_get_baseaddr() + buf[1]), buf[0]); // we need ushort() here! + if ( xEA >= inf_get_max_ea() ) + errstruct(); + ovr_info.altset(xEA, 1); + } + } + start_off = E.HdrSize * 16; + // i preset variable for overlay loading + if ( type == 3 ) + ovr_type = PrepareOverlayType(li, &E); + } + // next 2 strings for create_msdos_segments & CppOverlays + inf_set_omin_ea(inf_get_min_ea()); + inf_set_omax_ea(inf_get_max_ea()); + + file2base(li, start_off, inf_get_min_ea(), inf_get_min_ea() + fcoresize, + FILEREG_PATCHABLE); + + if ( ovr_type != ovr_cpp ) + { + if ( type == 3 || (neflag & NEF_SEGS) ) + create_msdos_segments((type <= 1), ovr_info); + else + doRelocs(inf_get_baseaddr(), false, ovr_info); + } + + create_filename_cmt(); + add_pgm_cmt("Base Address: %ah Range: %ah-%ah Loaded length: %ah", + inf_get_baseaddr(), inf_get_min_ea(), inf_get_max_ea(), fcoresize); + if ( type >= 2 ) + { // f_EXE + linput_t *volatile lio = NULL; + add_pgm_cmt("Entry Point : %a:%a", inf_get_start_cs(), inf_get_start_ip()); + if ( type == 2 // && E.CalcEXE_Length() < qlsize(li) - E.HdrSize*16 + && (lio = CheckExternOverlays()) != NULL ) + { + ++type; + } + if ( type != 3 ) + { + ovr_info.altset(-1, type); // EXE without overlays + } + else + { + switch ( ovr_type ) + { + case ovr_pascal: + lio = li; + // fallthrough + case ovr_noexe: + LoadPascalOverlays(lio); + if ( ovr_type == ovr_noexe ) + close_linput(lio); + break; + + case ovr_cpp: + dseg = LoadCppOverlays(li); + doRelocs(inf_get_baseaddr(), false, ovr_info); + break; + + case ovr_ms: + dseg = LoadMsOverlays(li, E.Overlay == 0); + break; + } + } + } + } + + setup_default_ds_register(dseg); // former SRcreate() + if ( dseg != BADSEL && ovr_type == ovr_ms ) + { + segment_t *s = get_segm_by_sel(find_selector(inf_get_start_cs())); + if ( s != NULL ) + set_default_sreg_value(s, ph.reg_data_sreg, s->sel); + } + inf_set_start_ea((inf_get_start_ip() == BADADDR) + ? BADADDR + : to_ea(sel2para(inf_get_start_cs()), inf_get_start_ip())); + if ( inf_get_start_ip() != BADADDR ) + { + uval_t val; + if ( type < 2 ) + val = find_selector(inf_get_start_cs()); // COM/DRV + else if ( get_str_type_code(inf_get_strtype()) == STRTYPE_PASCAL ) + val = get_sreg(inf_get_start_ea(), ph.reg_data_sreg); // i set in [srareaovl.cpp]FindDseg + else + val = inf_get_baseaddr() - 0x10; + split_sreg_range(inf_get_start_ea(), ph.reg_data_sreg, val, SR_autostart, true); + } + + if ( inf_get_filetype() == f_COM ) + { + inf_set_lowoff(0x100); + } + else + { + // check for the debug information + char debug_magic[4]; + qlseek(li, -8, SEEK_END); + lread(li, debug_magic, 4); + if ( is_codeview_magic(debug_magic) ) + load_dbg_dbginfo(NULL, li); + } +} + +//-------------------------------------------------------------------------- +static int expand_file(FILE *fp, uint32 pos) +{ + // return chsize(li, pos) || qfseek(fp, pos, SEEK_SET); + // but qchsize(), which does not fill with zeroes. + uint32 curpos = qftell(fp); + QASSERT(20041, curpos <= pos); + while ( curpos < pos ) + { + if ( qfputc(0, fp) == EOF ) + return 0; + ++curpos; + } + return 1; +} + +//-------------------------------------------------------------------------- +// +// generate binary file. +// +int idaapi save_file(FILE *fp, const char * /*fileformatname*/) +{ + int retcode; + uint32 codeoff; + netnode ovr_info(LDR_INFO_NODE, 0, 0); + + if ( fp == NULL ) + return ovr_info == BADNODE || ovr_info.altval(-1) == 2; + + if ( ovr_info != BADNODE ) // f_EXE + { + exehdr E; + ovr_info.valobj(&E, sizeof(E)); + + if ( qfwrite(fp, &E, sizeof(E)) != sizeof(E) ) + return 0; + if ( E.ReloCnt ) + { + if ( !expand_file(fp, E.TablOff) ) + return 0; + + for ( uval_t x = ovr_info.altfirst(); + x != BADADDR; + x = ovr_info.altnext(x) ) + { + ushort buf[2]; + + buf[1] = ushort((x >> 4) - inf_get_baseaddr()); + buf[0] = ushort(x) & 0xF; + if ( qfwrite(fp, buf, sizeof(buf)) != sizeof(buf) ) + return 0; + } + } + codeoff = E.HdrSize * 16; + if ( !expand_file(fp, codeoff) ) + return 0; + } + else + { + codeoff = 0; // f_COM, f_DRV + } + + doRelocs(-inf_get_baseaddr(), 0, ovr_info); + retcode = base2file(fp, codeoff, inf_get_omin_ea(), inf_get_omax_ea()); + doRelocs(inf_get_baseaddr(), 0, ovr_info); + return retcode; +} + +//---------------------------------------------------------------------- +static int idaapi move_segm(ea_t from, ea_t to, asize_t /*size*/, const char * /*fileformatname*/) +{ + // Before relocating, we need all of the relocation entries, which were + // part of the original executable file and consequently stored in our + // private loader node. + netnode ovr_info(LDR_INFO_NODE, 0, 0); + if ( ovr_info == BADNODE ) + { + // Can't find our private loader node. + msg("Couldn't find dos.ldr node, assuming file has no relocations.\n"); + return 1; + } + + if ( from == BADADDR ) + { + // The entire program is being rebased. + // In this case, 'to' actually contains a delta value; the number of bytes + // forward (positive) or backward (negative) that the whole database is + // being moved. + int32 delta = to; + + // If the delta is not a multiple of 16 bytes, we can't reliably + // relocate the executable. + if ( (delta % 16) != 0 ) + { + warning("DOS images can only be relocated to 16-byte boundaries."); + return 0; + } + + // Fixup the relocation entry netnode. It contains entries that point + // to locations that needed fixups when the image was located at its + // old address. Change the entries so that they point to the appropriate + // places in the new image location. + ea_t current_base = uint32(inf_get_baseaddr() << 4); + ea_t new_base = current_base + delta; + ovr_info.altshift(current_base, new_base, inf_get_privrange_start_ea()); + + // remember bases for later remapping of segment regs + std::map<ea_t, ea_t> segmap; + + // Now that the relocation entries point to the correct spots, go fix + // those spots up so that they point to the correct places. + doRelocs(delta >> 4, false, ovr_info); + + // IDA has adjusted all segment start and end addresses to cover their + // new effective address ranges, but we, the loader, must finish the + // job by rebasing each segment. + for ( int i = 0; i < get_segm_qty(); ++i ) + { + segment_t *seg = getnseg(i); + ea_t curbase = get_segm_base(seg); // Returns base in EA + ea_t newbase = curbase + delta; + set_segm_base(seg, newbase >> 4); // Expects base in Paragraphs + segmap[curbase >> 4] = newbase >> 4; + seg->update(); + } + + // fix up segment registers + // rebase segment registers + processor_t &ph = PH; + for ( int sr = 0; sr < SREG_NUM; ++sr ) + { + int sra_num = get_sreg_ranges_qty(ph.reg_first_sreg + sr); + for ( int i = 0; i < sra_num; ++i ) + { + sreg_range_t sra; + if ( !getn_sreg_range(&sra, sr, i) ) + break; + sel_t reg = sra.val; + if ( reg != BADSEL ) + { + std::map<ea_t, ea_t>::const_iterator p = segmap.find(reg); + if ( p != segmap.end() ) + split_sreg_range(sra.start_ea, ph.reg_first_sreg + sr, p->second, SR_auto, true); + } + } + } + + // Record the new image base address. + inf_set_baseaddr(new_base >> 4); + set_imagebase(new_base); + } + + return 1; +} + +//---------------------------------------------------------------------- +// +// LOADER DESCRIPTION BLOCK +// +//---------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + // loader flags + 0, + + // check input file format. if recognized, then return 1 + // and fill 'fileformatname'. + // otherwise return 0 + accept_file, + + // load file into the database. + load_file, + + // create output file from the database. + // this function may be absent. + save_file, + + // take care of a moved segment (fix up relocations, for example) + move_segm, + NULL, +}; diff --git a/idasdk76/ldr/dos/dos_ovr.cpp b/idasdk76/ldr/dos/dos_ovr.cpp new file mode 100644 index 0000000..7a53d59 --- /dev/null +++ b/idasdk76/ldr/dos/dos_ovr.cpp @@ -0,0 +1,1068 @@ +/* + * This Loader Module is written by Ilfak Guilfanov and + * rewriten by Yury Haron + * + */ +/* + L O A D E R pard of MS-DOS file format's (overlayed EXE) +*/ + +#include "../idaldr.h" +#include <struct.hpp> +#include <exehdr.h> +#include "dos_ovr.h" + +static const char *const stub_class = "STUBSEG"; +static const char *const stub_name_fmt = "stub%03d"; +static const char *const ovr_class = "OVERLAY"; +static const char *const ovr_name_fmt = "ovr%03d"; + +static uint32 ovr_off = 0; + +//------------------------------------------------------------------------ +o_type PrepareOverlayType(linput_t *li, exehdr *E) +{ + uint32 flen = qlsize(li); + uint32 base = E->HdrSize * 16; + uint32 loadend = base + E->CalcEXE_Length(); + uint32 fbovoff; + fbov_t fbov; + + ovr_off = 0; + + for ( fbovoff = (loadend + 0xF) & ~0xF; ; fbovoff += 0x10 ) + { + if ( pos_read(li, fbovoff, &fbov, sizeof(fbov)) ) + break; + if ( fbov.fb != FB_MAGIC ) + break; + if ( fbov.ov == OV_MAGIC ) + { + ovr_off = fbovoff; + return (fbov.exeinfo > loadend + || fbov.ovrsize > (flen - fbovoff) + || fbov.segnum <= 0) + ? ovr_pascal + : ovr_cpp; + } + } + + exehdr e1; + fbovoff = (loadend + 511) & ~511; + flen -= fbovoff; + if ( !pos_read(li, fbovoff, &e1, sizeof(e1)) + && e1.exe_ident == EXE_ID // only MZ ! + && flen >= (base = e1.HdrSize*16) + && e1.TablOff + (e1.ReloCnt*4) <= (flen -= base) + && e1.CalcEXE_Length() <= flen ) + { + ovr_off = fbovoff; + return ovr_ms; + } + return ovr_noexe; +} + +//------------------------------------------------------------------------ +static bool isStubPascal(ea_t ea) +{ + return get_word(ea) == 0x3FCD // int 3F + && (int32)get_dword(ea+4) > 0 // fileoff + && get_word(ea+8) != 0 // codesize + && (short)get_word(ea+10) >= 0 // relsize (assume max 32k) + && (short)get_word(ea+12) > 0 // nentries + && (short)get_word(ea+12) < (0x7FFF / sizeof(ovrentry_t)) // nentries + && is_mapped(to_ea(inf_get_baseaddr() + get_word(ea+14), 0)); // prevstub +} + +//------------------------------------------------------------------------ +linput_t *CheckExternOverlays(void) +{ + char buf[MAXSTR]; + const char *p; + if ( get_input_file_path(buf, sizeof(buf)) <= 0 + || (p=strrchr(buf, '.')) == NULL + || stricmp(++p, e_exe) != 0 ) + { + return NULL; + } + + for ( segment_t *s = get_first_seg(); s != NULL; s = get_next_seg(s->start_ea) ) + { + ea_t ea = s->start_ea; + if ( isStubPascal(ea) ) + { + switch ( ask_yn(ASKBTN_NO, + "This file contains reference to Pascal-stype overlays\n" + "Do you want to load it?") ) + { + + case ASKBTN_NO: + return NULL; + case ASKBTN_CANCEL: + loader_failure(); + default: // Yes + break; + } + while ( true ) + { + p = ask_file(false, + set_file_ext(buf, sizeof(buf), buf, "ovr"), + "Please enter pascal overlays file"); + CheckCtrlBrk(); + if ( p == NULL ) + return NULL; + + linput_t *li = open_linput(p, false); + if ( li != NULL ) + return li; + warning("Pascal style overlays file '%s' is not found", p); + } + } + } + return NULL; +} + +//------------------------------------------------------------------------ +static void removeBytes(void) +{ + ea_t ea = inf_get_omin_ea(); + + msg("Deleting bytes which do not belong to any segment...\n"); + for ( int i = 0; ; ++i ) + { + if ( ea >= inf_get_omax_ea() ) + break; + + segment_t *sptr = getnseg(i); + + if ( ea < sptr->start_ea ) + { + show_addr(ea); + deb(IDA_DEBUG_LDR, + "Deleting bytes at %a..%a (they do not belong to any segment)...\n", + ea, + sptr->start_ea); + if ( disable_flags(ea,sptr->start_ea) ) + { + warning("Maximal number of segments is reached, some bytes are out of segments"); + return; + } + CheckCtrlBrk(); + } + ea = sptr->end_ea; + } +} + +//------------------------------------------------------------------------ +static int add_struc_fld( + struc_t *st, + flags_t flag, + size_t sz, + const char *name, + const char *cmt) +{ + int i = add_struc_member(st, name, BADADDR, flag, NULL, sz); + if ( i == 0 && cmt != NULL ) + set_member_cmt(get_member_by_name(st, name), cmt, false); + return i; +} + +//------------------------------------------------------ +static void describeStub(ea_t stubEA) +{ + static const char stubSname[] = "_stub_descr"; + static tid_t id = 0; + + if ( id == 0 + && (id=get_struc_id(stubSname)) == BADNODE ) + { + struc_t *st = get_struc(add_struc(BADADDR, stubSname)); + if ( st == NULL ) + goto badst; + st->props |= SF_NOLIST; + if ( add_struc_fld(st, byte_flag()|hex_flag(), 2, + "int_code", "Overlay manager interrupt") + || add_struc_fld(st, word_flag()|hex_flag(), sizeof(short), + "memswap", "Runtime memory swap address") + || add_struc_fld(st, dword_flag()|hex_flag(), sizeof(int32), + "fileoff", "Offset in the file to the code") + || add_struc_fld(st, word_flag()|hex_flag(), sizeof(short), + "codesize", "Code size") + || add_struc_fld(st, word_flag()|hex_flag(), sizeof(short), + "relsize", "Relocation area size") + || add_struc_fld(st, word_flag()|dec_flag(), sizeof(short), + "nentries", "Number of overlay entries") + || add_struc_fld(st, word_flag()|seg_flag(), sizeof(short), + "prevstub", "Previous stub") + || add_struc_fld(st, byte_flag()|hex_flag(), STUBUNK_SIZE, + "workarea", NULL) ) + { +badst: + warning("Failed to create stub structure descriptor"); + id = BADNODE; + } + else + { + array_parameters_t apt; + apt.flags = AP_ALLOWDUPS; + apt.lineitems = 8; + apt.alignment = -1; // nonalign + set_array_parameters(get_member_id(st, 0), &apt); + set_array_parameters(get_member_id(st,offsetof(stub_t,unknown)), &apt); + // st->props |= SF_NOLIST; + // save_struc(st, true); + id = st->id; + } + } + + ushort tmp = get_word(stubEA + offsetof(stub_t, prevstub)); + if ( tmp != 0 ) + put_word(stubEA + offsetof(stub_t, prevstub), uint16(tmp + inf_get_baseaddr())); + + tmp = get_word(stubEA + offsetof(stub_t, nentries)); + + if ( id != BADNODE ) + { + del_items(stubEA, DELIT_EXPAND, sizeof(stub_t)); + create_struct(stubEA, sizeof(stub_t), id); + } + + stubEA += sizeof(stub_t); + + if ( tmp != 0 ) + { + do + { + auto_make_proc(stubEA); + stubEA += 5; + CheckCtrlBrk(); + } while ( --tmp ); + } +} + +//------------------------------------------------------------------------ +static void load_overlay( + linput_t *li, + uint32 exeinfo, + ea_t stubEA, + segment_t *s, + qoff64_t fboff) +{ + ea_t entEA = stubEA + sizeof(stub_t); + stub_t stub; + + if ( get_bytes(&stub, sizeof(stub), stubEA) != sizeof(stub) ) + errstruct(); + msg("Overlay stub at %a, code at %a...\n", stubEA, s->start_ea); + if ( stub.CDh != 0xCD ) + errstruct(); // bad stub + + // i now load overlay code: + bool waszero = false; + if ( !stub.codesize ) // IDA doesn't allow 0 length segments + { + ++stub.codesize; + waszero = true; + } + s->end_ea = s->start_ea + stub.codesize; + file2base(li, fboff+stub.fileoff, s->start_ea, s->end_ea, + fboff == 0 + ? FILEREG_NOTPATCHABLE + : FILEREG_PATCHABLE); + if ( waszero ) + { + s->type = SEG_NULL; + stub.codesize = 0; + } + + uint i; + for ( i = 0; i < stub.nentries; ++i ) + { + show_addr(entEA); + put_byte(entEA, 0xEA); // jmp far + ushort offset = get_word(entEA+2); + put_word(entEA+1, offset); // offset + put_word(entEA+3, s->sel); // selector + auto_make_proc(to_ea(sel2para(s->sel), offset)); + entEA += sizeof(ovrentry_t); + CheckCtrlBrk(); + } + + qoff64_t fpos = fboff + stub.fileoff + stub.codesize; + qlseek(li, fpos); + + fixup_data_t fd(FIXUP_SEG16); + + uint relcnt = stub.relsize / 2; + validate_array_count(li, &relcnt, sizeof(ushort), "Relocation count", fpos); + if ( relcnt != 0 ) + { + ushort *relb = qalloc_array<ushort>(relcnt); + if ( !relb ) + nomem("overlay relocation table"); + + lread(li, relb, sizeof(ushort)*relcnt); + int32 pos = qltell(li); // must?? + + ushort *relc = relb; + do + { + if ( *relc > stub.codesize ) + errstruct(); + + ea_t xEA = s->start_ea + *relc++; + show_addr(xEA); + ushort relseg = get_word(xEA); + if ( exeinfo != 0 ) + { + seginfo_t si; + + if ( pos_read(li, exeinfo + relseg, &si, sizeof(si)) ) + errstruct(); + relseg = si.seg; + } + + fd.sel = relseg + inf_get_baseaddr(); + fd.set(xEA); + put_word(xEA, ushort(fd.sel)); + CheckCtrlBrk(); + } while ( --relcnt ); + qfree(relb); + qlseek(li, pos); + } +} + +//------------------------------------------------------------------------ +static void add_seg16(ea_t ea) +{ + segment_t s; + s.sel = ea >> 4; + s.start_ea = ea; + s.end_ea = BADADDR; + s.align = saRelByte; + s.comb = scPub; + add_segm_ex(&s, NULL, NULL, ADDSEG_NOSREG | ADDSEG_SPARSE); +} + +//------------------------------------------------------------------------ +static sel_t AdjustStub(ea_t ea) // returns prev stub +{ + segment_t *seg = getseg(ea); + + if ( ea != seg->start_ea ) + add_seg16(ea); + + ushort nentries = get_word(ea+12); + uint32 segsize = sizeof(stub_t) + nentries * sizeof(ovrentry_t); + seg = getseg(ea); + + asize_t realsize = seg->end_ea - seg->start_ea; + if ( segsize > realsize ) + return BADSEL; // this stub is bad + + if ( segsize != realsize ) + { + ea_t next = seg->start_ea + segsize; + + set_segm_end(seg->start_ea, next, 0); + next += 0xF; + next &= ~0xF; + if ( is_mapped(next) ) + { + segment_t *s = getseg(next); + if ( s == NULL ) + add_seg16(next); + } + } + return get_word(ea + 14); +} + +//------------------------------------------------------------------------ +void LoadPascalOverlays(linput_t *li) +{ + // AdjustPascalOverlay + ea_t minea = inf_get_min_ea(); + ea_t maxea = inf_get_max_ea(); + for ( ea_t ea = minea; ea < maxea; ) + { + ea &= ~0xF; + if ( isStubPascal(ea) ) + { + AdjustStub(ea); + ea = getseg(ea)->end_ea; + ea += 0xF; + CheckCtrlBrk(); + } + else + { + ea += 0x10; + } + } + //- + ea_t ea; + int i = 0; + for ( segment_t *s0 = get_first_seg(); s0 != NULL; s0 = get_next_seg(ea), ++i ) + { + ea = s0->start_ea; + + if ( get_byte(ea) != 0xCD || get_byte(ea+1) != 0x3F ) + continue; + set_segm_class(s0, stub_class); + char sname[32]; + qsnprintf(sname, sizeof(sname), stub_name_fmt, i); + set_segm_name(s0, sname); + + segment_t s; + s.comb = scPub; + s.align = saRelPara; + s.start_ea = (inf_get_max_ea() + 0xF) & ~0xF; + s.sel = setup_selector(s.start_ea >> 4); + // 04.06.99 ig: what is exeinfo and why it is passed as 0 here? + load_overlay(li, 0/*???*/, ea, &s, ovr_off); // i + qsnprintf(sname, sizeof(sname), ovr_name_fmt, i); + if ( !add_segm_ex(&s, sname, ovr_class, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure(); + describeStub(ea); + CheckCtrlBrk(); + } + removeBytes(); +} + +//------------------------------------------------------------------------ +static ea_t CppInfoBase(fbov_t *fbov) +{ + seginfo_t si; + ea_t siEA = get_fileregion_ea(fbov->exeinfo); + + if ( siEA == BADADDR + || get_bytes(&si, sizeof(si), siEA) != sizeof(si) ) + { + errstruct(); + } + + if ( (si.flags & SI_OVR) && si.seg ) // possible truncation + { + ushort lseg = si.seg; + + msg("Probbly the input file was truncated by 'unp -h'. Searching the base...\n"); + do + { + if ( si.seg > lseg ) + errstruct(); + lseg = si.seg; + + if ( siEA < inf_get_omin_ea()+sizeof(si) + || get_bytes(&si, sizeof(si), siEA -= sizeof(si)) != sizeof(si) ) + { + errstruct(); + } + fbov->exeinfo -= sizeof(si); + CheckCtrlBrk(); + } while ( si.seg ); + add_pgm_cmt("Real (before unp -h) EXEinfo=%08X", fbov->exeinfo); + } + return siEA; +} + +//------------------------------------------------------------------------ +sel_t LoadCppOverlays(linput_t *li) +{ + fbov_t fbov; + sel_t dseg = BADSEL; + + if ( pos_read(li, ovr_off, &fbov, sizeof(fbov)) ) + errstruct(); + add_pgm_cmt("Overlays: base=%08X, size=%08X, EXEinfo=%08X", + ovr_off, fbov.ovrsize, fbov.exeinfo); + ovr_off += sizeof(fbov_t); + + if ( fbov.segnum == 0 ) + errstruct(); + + ea_t siEA = CppInfoBase(&fbov); + ushort lseg = 0; + for ( int32 i = 0; i < fbov.segnum; ++i ) + { + seginfo_t si; + + if ( get_bytes(&si, sizeof(si), siEA) != sizeof(si) ) + errstruct(); + siEA += sizeof(si); + + if ( si.maxoff == 0xFFFF ) + continue; // skip EXEINFO & OVRDATA + if ( si.maxoff <= si.minoff ) + continue; + if ( si.seg < lseg ) + errstruct(); + lseg = si.seg; + + si.seg += (ushort)inf_get_baseaddr(); + + const char *sclass = NULL; + segment_t s; // i initialize segment_t with 0s + s.align = saRelByte; + s.comb = scPub; + if ( si.seg == inf_get_start_ss() ) + { + sclass = CLASS_STACK; + s.type = SEG_DATA; + s.comb = scStack; + } + if ( si.flags & SI_COD ) + { + sclass = CLASS_CODE; + s.type = SEG_CODE; + } + if ( si.flags & SI_DAT ) + { + sclass = CLASS_BSS; + s.type = SEG_DATA; + dseg = si.seg; + } + s.name = 0; + if ( si.flags & SI_OVR ) + { + s.align = saRelPara; + s.start_ea = (inf_get_max_ea() + 0xF) & ~0xF; + s.sel = setup_selector(s.start_ea >> 4); + // i end_ea is set in load_overlay() + load_overlay(li, fbov.exeinfo, to_ea(si.seg, 0), &s, ovr_off); + if ( s.type != SEG_NULL ) + s.type = SEG_CODE; + char sname[32]; + qsnprintf(sname, sizeof(sname), ovr_name_fmt, i); + if ( !add_segm_ex(&s, sname, ovr_class, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure(); + s.name = 0; + s.type = SEG_NORM; // undefined segment type + sclass = stub_class; + } + s.sel = si.seg; + s.start_ea = to_ea(s.sel, si.minoff); + s.end_ea = to_ea(s.sel, si.maxoff); + if ( !add_segm_ex(&s, NULL, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure(); + if ( si.flags & SI_OVR ) + { + describeStub(s.start_ea); + char sname[32]; + qsnprintf(sname, sizeof(sname), stub_name_fmt, i); + set_segm_name(&s, sname); + } + CheckCtrlBrk(); + } + removeBytes(); + return dseg; +} + +//------------------------------------------------------------------------ +//+ +//------------------------------------------------------------------------ +static netnode msnode; + +struct modsc_t +{ + uint32 bpos; + uint32 size; + ushort Toff; + ushort Hsiz; + ushort Rcnt; + ushort Mpara; +}; + +static ea_t ref_off_EA; +static ea_t ref_ind_EA; +static uint ref_oi_cnt; + +//------------------------------------------------------------------------ +static uint CreateMsOverlaysTable(linput_t *li, bool *PossibleDynamic) +{ + modsc_t o; + uint Count = 0; + uint32 flen = qlsize(li); + + o.bpos = ovr_off; + msnode.create(); + msg("Searching for the overlays in the file...\n"); + while ( o.bpos + sizeof(exehdr) < flen ) + { + exehdr E; + uint32 delta; + + if ( pos_read(li, o.bpos, &E, sizeof(E)) ) + errstruct(); + + o.size = E.CalcEXE_Length(); + delta = (uint32)(o.Hsiz = E.HdrSize) * 16; + o.Toff = E.TablOff; + o.Rcnt = E.ReloCnt; + o.Mpara = (ushort)((o.size + 0xF) >> 4); + + uint32 ost = flen - o.bpos; + if ( E.exe_ident != EXE_ID // only MZ ! + || ost < delta + || (uint32)o.Toff + (E.ReloCnt*4) > (ost -= delta) + || o.size > ost ) + { + return Count; + } + CheckCtrlBrk(); + + msnode.supset(++Count, &o, sizeof(o)); + ovr_off = o.bpos + delta + o.size; + uint32 d2 = align_up(ovr_off, 512); + if ( o.bpos == d2 ) + { + warning("Too small overflay size %u, stopped processing them", delta+o.size); + break; + } + o.bpos = d2; + if ( E.Overlay != Count ) + *PossibleDynamic = false; + } + ovr_off = 0; + return Count; +} + +//------------------------------------------------------------------------ +static void LoadMsOvrData(linput_t *li, uint Count, bool Dynamic) +{ + fixup_data_t fd(FIXUP_SEG16); + for ( uint i = 1; i <= Count; ++i ) + { + modsc_t o; + + // skip dropped overlays + if ( msnode.supval(i, &o, sizeof(o)) != sizeof(o) ) + continue; + + segment_t s; + s.comb = scPub; + s.align = saRelPara; + s.start_ea = (inf_get_max_ea() + 0xF) & ~0xF; + s.sel = setup_selector(s.start_ea >> 4); + msnode.altset(i, s.sel); + s.end_ea = s.start_ea + ((uint32)o.Mpara << 4); + file2base(li, + o.bpos + o.Hsiz*16LL, + s.start_ea, + s.start_ea + o.size, + FILEREG_PATCHABLE); + char sname[32]; + qsnprintf(sname, sizeof(sname), ovr_name_fmt, i); + if ( !add_segm_ex(&s, sname, ovr_class, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure(); + + qlseek(li, o.bpos + o.Toff); + + for ( uint j = o.Rcnt; j; --j ) + { + ushort buf[2]; + + lread(li, buf, sizeof(buf)); + +// ATTENTION!!! if Dynamic (ms-autopositioning) segment part of relocation +// address == pseudodata segment to load (from data in ovr!) +// We should checked it but don't have any testcase + ea_t xEA = Dynamic + ? s.start_ea + buf[0] + : s.start_ea + to_ea(buf[1], buf[0]); + + if ( xEA >= s.end_ea ) + errstruct(); + + show_addr(xEA); + + ushort ubs = ushort(get_word(xEA) + inf_get_baseaddr()); + put_word(xEA, ubs); + fd.sel = ubs; + fd.set(xEA); + add_segm_by_selector(ubs, CLASS_CODE); + CheckCtrlBrk(); + } + } +} + +//------------------------------------------------------------------------ +static sel_t SearchMsOvrTable(uint *Cnt) +{ + modsc_t dsc; + if ( msnode.supval(1, &dsc, sizeof(dsc)) != sizeof(dsc) ) + { +interr: + error("Internal error"); + } + + uint32 src[2] = { 0, dsc.bpos }; + ea_t dstea, sea, ea = inf_get_min_ea(); + uint AddSkip, Count = *Cnt; + uint i, j; // watcom ... + segment_t *s; + + msg("Searching the overlay reference data table...\n"); + while ( ea + sizeof(src) < inf_get_max_ea() + && (sea = bin_search2(ea, + inf_get_max_ea(), + (uchar *)src, + NULL, + sizeof(src), + BIN_SEARCH_CASE | BIN_SEARCH_NOBREAK | BIN_SEARCH_FORWARD)) != BADADDR ) + { + ea = sea + sizeof(uint32); + s = getseg(ea); + if ( s == NULL + || ea - s->start_ea < sizeof(uint32)*(Count+1) + || ea + (2*sizeof(uint32) * Count) > s->end_ea ) + { +nextfndadd: + ea += sizeof(uint32); +nextfnd: + continue; + } + + AddSkip = 0; + for ( i = 2; i <= Count + AddSkip; ++i ) + { + ea += sizeof(uint32); + uint32 pos = get_dword(ea); + + if ( pos == 0 ) + { + ++AddSkip; + if ( ea + (2*sizeof(uint32) * (Count+AddSkip-i)) > s->end_ea ) + goto nextfnd; + } + else + { + if ( msnode.supval(i - AddSkip, &dsc, sizeof(dsc)) != sizeof(dsc) ) + goto interr; + if ( pos != dsc.bpos ) + goto nextfndadd; + } + } + goto found; + } +badtable: + ref_oi_cnt = (uint)-1; + return BADSEL; + +found: + if ( AddSkip ) + { + ea = sea + sizeof(uint32); + for ( i = 2; i <= Count; ++i ) + { + if ( !get_dword(ea += sizeof(uint32)) ) + { + if ( !AddSkip ) + goto interr; + --AddSkip; + for ( j = Count; j >= i; --j ) + { + if ( msnode.supval(j, &dsc, sizeof(dsc)) != sizeof(dsc) ) + goto interr; + msnode.supset(j+1, &dsc, sizeof(dsc)); + } + msnode.supdel(i); + ++Count; + CheckCtrlBrk(); + } + } + if ( AddSkip ) + goto interr; + } + + //msg("Found disk blocks table\n"); + ea = sea - ((Count-1) * sizeof(ushort)) - 1; // -1 -- unification + do + { + ea = bin_search2(s->start_ea, + ea+1, + (uchar *)src, + NULL, + sizeof(ushort), + BIN_SEARCH_CASE | BIN_SEARCH_NOBREAK | BIN_SEARCH_BACKWARD); + if ( ea == BADADDR ) + goto badtable; + } while ( (sea - ea) % sizeof(ushort) ); + + ref_oi_cnt = (sea - ea) / sizeof(ushort); + if ( ref_oi_cnt <= 1 ) + goto badtable; + ref_ind_EA = ea; + + //msg("Check all tables...\n"); + j = Count; + while ( (ea += sizeof(ushort)) < sea ) + { + i = get_word(ea); + if ( i > j ) + { + if ( j == *Cnt ) + goto badtable; + j = i; + } + } + if ( (i = j - Count) != 0 ) + { + AddSkip = i; + do + { + if ( get_dword(sea - sizeof(uint32)) ) + break; + if ( (ref_oi_cnt -= 2) <= 1 ) + goto badtable; + sea -= sizeof(uint32); + } while ( --i ); + AddSkip -= i; + for ( j = Count; j; --j ) + { + if ( msnode.supval(j, &dsc, sizeof(dsc)) != sizeof(dsc) ) + msnode.supdel(j + AddSkip); + else + msnode.supset(j + AddSkip, &dsc, sizeof(dsc)); + } + do + { + msnode.supdel(++j); + } + while ( j < AddSkip ); + Count += AddSkip; + CheckCtrlBrk(); + if ( i ) + { + ea = sea + Count*sizeof(uint32); + Count += i; + do + { + if ( get_dword(ea += sizeof(uint32)) ) + goto badtable; + } + while ( --i ); + } + } + + dstea = sea; + + ea = ref_ind_EA - (ref_oi_cnt*sizeof(ushort)); + if ( get_prev_fixup_ea(ea+1) != ea ) + ask_for_feedback("Absent relocation at start of offset table"); + + ref_off_EA = ea; + + sea = ref_ind_EA; + AddSkip = 0; // added 07.04.2015 (bmpcad) + for ( i = 1; i < ref_oi_cnt; ++i ) + { + ea += sizeof(ushort); + sea += sizeof(ushort); + + uint rsz; + j = get_word(sea); + if ( !j ) + { + if ( i <= Count ) + goto badofftb; + ++AddSkip; + continue; + } + + rsz = get_word(ea); + + if ( msnode.supval(j, &dsc, sizeof(dsc)) != sizeof(dsc) ) + { + if ( rsz ) + goto badofftb; + msg("An overlay index %u in the table of indexes points to a missing overlay\n", i); + } + else if ( rsz >= dsc.size ) + { +badofftb: + ask_for_feedback("Incompatible offset table"); + AddSkip = 0; + break; + } + } + + sea = dstea + (Count+1+AddSkip)*sizeof(uint32); + for ( i = 1; i <= Count; ++i ) + { + sea += sizeof(uint32); + uint32 dt = get_dword(sea); + + if ( msnode.supval(i, &dsc, sizeof(dsc)) != sizeof(dsc) ) + { + if ( dt ) + { +badmemtb: + ask_for_feedback("Incompatible mem-size table"); + } + continue; + } + + if ( !dt ) + { + ask_for_feedback("Zero overlay memory size in description table"); + goto badtable; + } + + if ( dt < dsc.Mpara || dt >= 0x1000 ) + goto badmemtb; + + // Possiblee needed for segment with unitialized data at top, but not sampled... + if ( dt > dsc.Mpara ) + { + dsc.Mpara = (ushort)dt; + msnode.supset(i, &dsc, sizeof(dsc)); + } + } + + for ( i = 0; i < AddSkip; i++ ) + { + sea += sizeof(uint32); + if ( get_dword(sea) != 0 ) + { + ask_for_feedback("Incompatible extension in overlay tables"); + break; + } + } + + msg("All tables OK\n"); + create_word(ref_off_EA, i = (ref_oi_cnt - AddSkip)*sizeof(ushort)); + force_name(ref_off_EA, "ovr_off_tbl"); + create_word(ref_ind_EA, i); + force_name(ref_ind_EA, "ovr_index_tbl"); + *Cnt = Count; + i = (Count + 1) * sizeof(uint32); + create_dword(dstea, i); + force_name(dstea, "ovr_start_tbl"); + dstea += i + (AddSkip * sizeof(uint32)); + create_dword(dstea, i); + force_name(dstea, "ovr_memsiz_tbl"); + return s->sel; +} + +//------------------------------------------------------------------------ +static segment_t *MsOvrStubSeg(uint *stub_cnt, ea_t r_top, sel_t dseg) +{ + msg("Searching for the stub segment...\n"); + int count = get_segm_qty(); + for ( int i = 0; i < count; ++i ) + { + segment_t *seg = getnseg(i); + if ( seg->sel == dseg ) + continue; + ea_t ea = seg->start_ea; + uchar buf[3*sizeof(ushort)]; + + if ( ea >= r_top ) + break; + + if ( get_bytes(buf, sizeof(buf), ea) != sizeof(buf) ) + continue; + if ( *(uint32 *)buf || *(ushort *)&buf[sizeof(uint32)] ) + continue; + + uint cnt = 0; + uchar frs = (uchar)-1; + while ( (ea += sizeof(buf)) < seg->end_ea - sizeof(buf) ) + { + if ( (frs = get_byte(ea)) != 0xCD || get_byte(ea+1) != 0x3F ) + break; + ushort ind = get_word(ea + sizeof(ushort)); + if ( !ind || ind > ref_oi_cnt ) + break; + ++cnt; + CheckCtrlBrk(); + } + if ( !frs && cnt >= ref_oi_cnt ) + { + *stub_cnt = cnt; + return seg; + } + } + return NULL; +} + +//------------------------------------------------------------------------ +static void CreateMsStubProc(segment_t *s, uint stub_cnt) +{ + ea_t ea = s->start_ea; + + set_segm_name(s, "STUB"); + set_segm_class(s, CLASS_CODE); + create_byte(ea, 3*sizeof(ushort)); + ea += 3*sizeof(ushort); + msg("Patching the overlay stub-segment...\n"); + for ( uint ind, i = 0; i < stub_cnt; ++i, ea += 3*sizeof(ushort) ) + { + ind = get_word(ea+2); + if ( ind != 0 ) + { + if ( ind >= ref_oi_cnt ) + { +badref: + ask_for_feedback("Illegal reference in overlay call interrupt"); + continue; + } + + ind *= sizeof(ushort); + uint off = (uint)get_word(ea+4) + get_word(ref_off_EA + ind); + ind = get_word(ref_ind_EA + ind); // overlay number + ushort sel = (ushort)msnode.altval(ind); + modsc_t o; + if ( msnode.supval(ind, &o, sizeof(o)) != sizeof(o) ) + goto badref; + if ( off >= o.size ) + goto badref; + + show_addr(ea); + put_byte(ea, 0xEA); // jmp far + put_word(ea+1, off); // offset + put_word(ea+3, sel); // selector + put_byte(ea+5, 0x90); // NOP -> for autoanalisis + auto_make_proc(ea); + auto_make_proc(to_ea(sel2para(sel), off)); + CheckCtrlBrk(); + } + } + create_align(ea, s->end_ea - ea, 0); +} + +//------------------------------------------------------------------------ +sel_t LoadMsOverlays(linput_t *li, bool PossibleDynamic) +{ + sel_t dseg = BADSEL; + uint Cnt = CreateMsOverlaysTable(li, &PossibleDynamic); + + if ( ovr_off ) + warning("File has extra information\n" + "\3Loading 0x%X bytes, total file size 0x%" FMT_64 "X", + ovr_off, qlsize(li)); + + if ( Cnt ) + { + dseg = SearchMsOvrTable(&Cnt); + if ( dseg != BADSEL ) + PossibleDynamic = false; + else if ( !PossibleDynamic ) + ask_for_feedback("Cannot find the overlay call data table"); + + ea_t r_top = inf_get_max_ea(); + LoadMsOvrData(li, Cnt, PossibleDynamic); + + if ( ref_oi_cnt != (uint)-1 ) + { + uint stub_cnt; + segment_t *s = MsOvrStubSeg(&stub_cnt, r_top, dseg); + + if ( s != NULL ) + CreateMsStubProc(s, stub_cnt); + else + ask_for_feedback("The overlay-manager segment not found"); + } + } + msnode.kill(); + return dseg; +} diff --git a/idasdk76/ldr/dos/dos_ovr.h b/idasdk76/ldr/dos/dos_ovr.h new file mode 100644 index 0000000..34a8bc7 --- /dev/null +++ b/idasdk76/ldr/dos/dos_ovr.h @@ -0,0 +1,85 @@ +/* + * Interactive disassembler (IDA). + * Version 3.00 + * Copyright (c) 1990-94 by Ilfak Guilfanov. (2:5020/209@fidonet) + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _DOS_OVR_H_ +#define _DOS_OVR_H_ + +// the following structures are 1-byte aligned (!) +#pragma pack(push,1) + +struct fbov_t +{ + ushort fb; +#define FB_MAGIC 0x4246 + ushort ov; +#define OV_MAGIC 0x564F + uint32 ovrsize; + uint32 exeinfo; + int32 segnum; +}; + +struct seginfo_t +{ + ushort seg; + ushort maxoff; // FFFF - unknown + ushort flags; +#define SI_COD 0x0001 +#define SI_OVR 0x0002 +#define SI_DAT 0x0004 + ushort minoff; +}; + +struct stub_t +{ + uchar CDh; // 0 + uchar intnum; // 1 + ushort memswap; // 2 + int32 fileoff; // 4 + ushort codesize; // 8 + ushort relsize; // 10 + ushort nentries; // 12 + ushort prevstub; // 14 +#define STUBUNK_SIZE (0x20-0x10) + uchar unknown[STUBUNK_SIZE]; +}; + +struct ovrentry_t +{ + ushort int3f; + ushort off; + char segc; +}; + +CASSERT(sizeof(ovrentry_t) == 5); + +struct ms_entry +{ + uchar CDh; + uchar intnum; // normally 3Fh + ushort ovr_index; + ushort entry_off; +}; + +bool pos_read(linput_t *fp, uint32 pos, void *buf, size_t size); +int CheckCtrlBrk(void); +void add_segm_by_selector(sel_t base, const char *sclass); +extern const char e_exe[]; +// +enum o_type { ovr_noexe, ovr_pascal, ovr_cpp, ovr_ms }; + +o_type PrepareOverlayType(linput_t *fp, exehdr *E); +linput_t *CheckExternOverlays(void); +sel_t LoadCppOverlays(linput_t *fp); +sel_t LoadMsOverlays(linput_t *fp, bool PossibleDynamic); +void LoadPascalOverlays(linput_t *fp); + +NORETURN void errstruct(void); + +#pragma pack(pop) + +#endif diff --git a/idasdk76/ldr/dos/makefile b/idasdk76/ldr/dos/makefile new file mode 100644 index 0000000..8c9a7d9 --- /dev/null +++ b/idasdk76/ldr/dos/makefile @@ -0,0 +1,24 @@ +PROC=dos +O1=dos_ovr + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)dos$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ + cv.hpp dos.cpp dos_ovr.h +$(F)dos_ovr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp \ + $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ + dos_ovr.cpp dos_ovr.h diff --git a/idasdk76/ldr/dump/dump.cpp b/idasdk76/ldr/dump/dump.cpp new file mode 100644 index 0000000..2116cd8 --- /dev/null +++ b/idasdk76/ldr/dump/dump.cpp @@ -0,0 +1,348 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov (ig@datarescue.com) + * http://www.datarescue.com + * ALL RIGHTS RESERVED. + * + */ + +#include "../idaldr.h" + +//-------------------------------------------------------------------------- +static int make_words(char *line, char **words, int maxwords) +{ + while ( qisspace(*line) ) + line++; + int i; + for ( i=0; *line && i < maxwords; i++ ) + { + words[i] = line; + while ( !qisspace(*line) && *line != '\0' ) + line++; + if ( *line != '\0' ) + *line++ = '\0'; + while ( qisspace(*line) ) + line++; + } + return i; +} + +//-------------------------------------------------------------------------- +inline uint32 hex(char *&word) +{ + return strtoul(word, &word, 16); +} + +//-------------------------------------------------------------------------- +inline uint32 oct(char *&word) +{ + return strtoul(word, &word, 8); +} + +#define FAILED \ + do \ + { \ + deb(IDA_DEBUG_LDR, \ + "failed at %d (input file line %d)\n", \ + __LINE__, \ + nl); \ + return 0; \ + } while ( false ) + +//-------------------------------------------------------------------------- +static int idaapi accept_file( + qstring *fileformatname, + qstring *, + linput_t *li, + const char *) +{ + char line[MAXSTR]; + char *words[MAXSTR]; + + // We try to interpret the input file as a text + // file with a dump format, i.e. all lines should look like + +// 00000020: 59 69 74 54-55 B6 3E F7-D6 B9 C9 B9-45 E6 A4 52 +// 0020: 59 69 74 54 55 B6 3E F7 D6 B9 C9 B9 45 E6 A4 52 +// 1000: 12 23 34 56 78 +// 0100: 31 C7 1D AF 32 04 1E 32 05 1E 3C 32 07 1E 21 D9 +// 12 23 34 56 78 + + // and similar lines + // We allow non-ascii characters at the end of the line + // We skip empty lines + + ssize_t p0len = -1; // length of the first word's hex part + char w0sep[10]; // separator after the first word + w0sep[0] = '\0'; + int nl = 0; + int nontrivial_line_count = 0; + bool no_more_lines = false; + bool has_star = false; + uint32 adr, oldadr=0; + while ( qlgets(line, sizeof(line), li) ) + { + nl++; + strrpl(line, '-', ' '); + int nw = make_words(line, words, qnumber(words)); + if ( line[0] == ';' || line[0] == '#' || nw == 0 ) + { + if ( has_star ) + FAILED; + continue; + } + if ( no_more_lines ) + FAILED; + // od -x format may contain '*' lines which mean repetition + if ( strcmp(words[0], "*") == 0 && nw == 1 ) + { + if ( nontrivial_line_count == 0 ) + FAILED; + if ( has_star ) + FAILED; + has_star = true; + continue; + } + has_star = false; + nontrivial_line_count++; + // the first word must be a number (more than one digit) + char *ptr = words[0]; + adr = hex(ptr); + ssize_t p0 = ptr - words[0]; + if ( p0 <= 1 || p0 > 16 ) + FAILED; + if ( nontrivial_line_count > 1 && p0 < p0len ) + FAILED; + p0len = p0; + // take the separator from the first line + if ( nontrivial_line_count == 1 ) + { + qstrncpy(w0sep, ptr, sizeof(w0sep)); + while ( *ptr ) + if ( strchr(":>-.", *ptr++) == NULL ) + FAILED; + } + else + { + if ( strcmp(w0sep, ptr) != 0 ) + FAILED; + } + bool haspref = p0len >= 4 || w0sep[0] != '\0'; + if ( haspref ) + { + // if the line contains only the address, then don't accept lines anymore + if ( nw == 1 ) + { + if ( nontrivial_line_count == 1 ) + FAILED; + no_more_lines = true; + if ( adr <= oldadr ) + FAILED; + } + else + { + // the remaining words should be numbers with at least 1 position + // (at least the second word should be so) + ptr = words[1]; + hex(ptr); + if ( ptr == words[1] ) + FAILED; + } + } + oldadr = adr; + } + if ( nontrivial_line_count == 0 || has_star ) + FAILED; + + *fileformatname = "Dump file"; + return 1; +} + +//-------------------------------------------------------------------------- +static uchar bytes[MAXSTR/2]; +static bool iscode; +static sel_t sel; +static ea_t sea; +static ea_t eea; +static ushort neflag; + +static void copy(const ea_t ea, const ea_t top) +{ + if ( sea == BADADDR ) + { + if ( neflag & NEF_SEGS ) + { + const char *sname = iscode ? "CODE" : "DATA"; + sel = setup_selector(0); + add_segm(sel, ea, top, sname, sname); + } + sea = ea; + eea = top; + } + else + { + if ( eea < top ) + { // if the gap > 256KB, use sparse storage + int flags = top - eea > 256 * 1024 ? SEGMOD_SPARSE : 0; + eea = top; + set_segm_end(sea, eea, flags); + } + } + mem2base(bytes, ea, top, -1); +} + +//-------------------------------------------------------------------------- +void idaapi load_file(linput_t *li, ushort _neflag, const char * /*fileformatname*/) +{ + char line[MAXSTR]; + char *words[MAXSTR]; + + neflag = _neflag; + iscode = (neflag & NEF_CODE) != 0; + sel = BADSEL; + sea = BADADDR; + ea_t ea = 0; + ea_t top= 0; + bool octpref = false; + bool octnum = false; + size_t fill = 0; + + // Since we made all the checks in accept_file, + // here we don't repeat them + + size_t max_p0len = 0; + char w0sep[10]; // separator after the first word + w0sep[0] = '\0'; + int nontrivial_line_count = 0; + while ( qlgets(line, sizeof(line), li) ) + { + strrpl(line, '-', ' '); + if ( line[0] == ';' || line[0] == '#' ) + continue; + int n = make_words(line, words, qnumber(words)); + if ( n == 0 ) + continue; + nontrivial_line_count++; + ssize_t bi; + // od -x format may contain '*' lines which mean repetition + if ( strcmp(words[0], "*") == 0 && n == 1 ) + { + fill = size_t(top - ea); + octpref = true; // od -x have octal prefixes + continue; + } + // the first word must be a number (more than one digit) + char *ptr = words[0]; + uint32 w0 = octpref ? oct(ptr) : hex(ptr); + // length of the first word's hex part + size_t p0len = ptr - words[0]; + if ( p0len > max_p0len ) + max_p0len = p0len; + + // take the separator from the first line + if ( nontrivial_line_count == 1 ) + qstrncpy(w0sep, ptr, sizeof(w0sep)); + + // process '*' and fill the gap + if ( fill > 0 ) + { + while ( top < w0 ) + { + ea = top; + top = ea + fill; + copy(ea, top); + } + } + + int idx = 0; + if ( w0sep[0] != '\0' || p0len >= 4 ) + { + if ( nontrivial_line_count > 1 && !octpref && top != w0 ) + { + // strange, the sequence is not contiguous + // check if the prefixes are octal (od -x) + ptr = words[0]; + if ( oct(ptr) == top ) + { + octpref = true; + ptr = words[0]; + w0 = oct(ptr); + } + } + ea = w0; + idx = 1; + } + else + { + ea = top; + } + for ( bi=0; idx < n; idx++ ) //lint !e443 + { + ptr = words[idx]; + if ( nontrivial_line_count == 1 && !octnum && strlen(ptr) == 6 ) + { + oct(ptr); + if ( ptr-words[idx] == 6 ) + octnum = true; + ptr = words[idx]; +// msg("ptr=%s octnum=%d\n", ptr, octnum); + } + uint32 b = octnum ? oct(ptr) : hex(ptr); + ssize_t nc = ptr - words[idx]; + if ( nc < 2 ) + { + // we tolerate one-letter separators between numbers + if ( words[idx][1] == '\0' && strchr("\xA6|-:", words[idx][0]) != NULL ) + continue; + break; + } + nc /= octnum ? 3 : 2; // number of bytes + *(uint32 *)&bytes[bi] = b; + bi += nc; + } + top = ea + bi; + copy(ea, top); + } + + if ( neflag & NEF_SEGS ) + { + size_t bitness = eea >= 0x10000 || max_p0len > 4 ? 1 : 0; // 32/16 +#ifdef __EA64__ + if ( eea >= ea_t(0x100000000ull) || max_p0len > 8 ) + bitness = 2; // 64 +#endif + if ( bitness != 0 ) + { + set_segm_addressing(getseg(sea), bitness); + inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); + } + set_default_dataseg(sel); + } + if ( (neflag & NEF_RELOAD) == 0 ) + create_filename_cmt(); +} + +//-------------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + LDRF_REQ_PROC // requires the target processor to the set +| LDRF_RELOAD, // supports reloading the input file +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, + NULL, + NULL, +}; diff --git a/idasdk76/ldr/dump/makefile b/idasdk76/ldr/dump/makefile new file mode 100644 index 0000000..328768c --- /dev/null +++ b/idasdk76/ldr/dump/makefile @@ -0,0 +1,13 @@ +PROC=dump + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)dump$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h dump.cpp diff --git a/idasdk75/ldr/elf/common.cpp b/idasdk76/ldr/elf/common.cpp similarity index 100% rename from idasdk75/ldr/elf/common.cpp rename to idasdk76/ldr/elf/common.cpp diff --git a/idasdk76/ldr/elf/elf.h b/idasdk76/ldr/elf/elf.h new file mode 100644 index 0000000..ebdc96c --- /dev/null +++ b/idasdk76/ldr/elf/elf.h @@ -0,0 +1,3249 @@ +#ifndef __ELF_H__ +#define __ELF_H__ + +#include <diskio.hpp> +#include <fixup.hpp> + +#pragma pack(push, 4) + +// gcc does not allow to initialize indexless arrays for some reason +// put an arbitrary number here. the same with visual c++ +#if defined(__GNUC__) || defined(_MSC_VER) +#define MAXRELSYMS 64 +#else +#define MAXRELSYMS +#endif + +struct elf_loader_t; +struct elf_file_info_t; +typedef Elf64_Shdr elf_shdr_t; +typedef Elf64_Phdr elf_phdr_t; +struct elf_sym_t : public Elf64_Sym +{ + elf_sym_t() + { + st_name = 0; + st_info = 0; + st_other = 0; + st_shndx = 0; + st_value = 0; + st_size = 0; + } +}; +typedef Elf64_Dyn elf_dyn_t; +typedef Elf64_Rel elf_rel_t; +struct elf_rela_t : public Elf64_Rela +{ + elf_rela_t() + { + r_offset = 0; + r_info = 0; + r_addend = 0; + } +}; + +typedef qvector<elf_rela_t> elf_rela_vec_t; + +class reader_t; +struct sym_rel; +typedef uint32 elf_sym_idx_t; +struct elf_symbol_version_t; +struct dynamic_info_t; + +typedef uint32 elf_shndx_t; +typedef qvector<elf_shdr_t> elf_shdrs_t; +typedef qvector<elf_phdr_t> elf_phdrs_t; + +//---------------------------------------------------------------------------- +struct elf_ehdr_t : public Elf64_Ehdr +{ + elf_shndx_t real_shnum; // number of entries in the SHT + // (may be greater than 0xFF00) + elf_shndx_t real_shstrndx; // section name string table section index + // (may be greater than 0xFF00) + + bool has_pht() const { return e_phoff != 0; } + void set_no_pht() + { + e_phoff = 0; + e_phnum = 0; + } + + bool has_sht() const { return e_shoff != 0; } + void set_no_sht() + { + e_shoff = 0; + e_shnum = 0; + real_shnum = 0; + } + bool is_valid_shndx(elf_shndx_t idx) const + { + return idx < real_shnum; + } + + bool has_shstrtab() const { return real_shstrndx != 0; } +}; + +//------------------------------------------------------------------------- +typedef Elf64_Chdr elf_chdr_t; + +//---------------------------------------------------------------------------- +// rel_data_t holds whatever relocation information appears to be common +// to most ELF relocation "algorithms", as defined in the per-CPU +// addenda. +// Note: Most comments below were picked from the abi386.pdf file. +struct rel_data_t +{ + // Relocation type: R_<processor>_<reloc-type>. + uint32 type; + + // abi386.pdf: This means the place (section offset or address) of + // the storage unit being relocated (computed using r_offset). + ea_t P; + + // abi386.pdf: This means the value of the symbol whose index + // resides in the relocation entry. + uval_t S; + + // S, plus addend + ea_t Sadd; + + // Whether the 'reloc' parameter passed to 'proc_handle_reloc()' + // is a REL, or a RELA (the actual reloc entry object + // itself will always be a elf_rela_t instance). + enum rel_entry_t + { + re_rel, + re_rela + }; + rel_entry_t rel_entry; + bool is_rel() const { return rel_entry == re_rel; } + bool is_rela() const { return !is_rel(); } +}; + + +//-------------------------------------------------------------------------- +enum slice_type_t +{ + SLT_INVALID = 0, + SLT_SYMTAB = 1, + SLT_DYNSYM = 2, + SLT_WHOLE = 3, +}; +struct symrel_idx_t +{ + symrel_idx_t() : type(SLT_INVALID), idx(0) {} + symrel_idx_t(slice_type_t t, elf_sym_idx_t i) : type(t), idx(i) {} + + slice_type_t type; + elf_sym_idx_t idx; + + bool operator==(const symrel_idx_t &other) const + { + return other.type == type + && other.idx == idx; + } + bool operator<(const symrel_idx_t &other) const + { + if ( type < other.type ) + return true; + if ( type > other.type ) + return false; + return idx < other.idx; + } +}; + +//---------------------------------------------------------------------------- +struct got_access_t : public range_t +{ + elf_loader_t &ldr; + // the name _GLOBAL_OFFSET_TABLE_ + static const char gtb_name[]; + + // is the given symbol the _GLOBAL_OFFSET_TABLE_? + static bool is_symbol_got(const sym_rel &sym, const char *name); + + got_access_t(elf_loader_t &_ldr) : range_t(0, 0), ldr(_ldr) {} + + // Get the start address of the GOT. + // If no GOT currently exists, and 'create' is true, one will + // be created in a segment called ".got". + // If no GOT exists or an error occurred while creating .got segment, + // the function returns 0. + ea_t get_start_ea(elf_file_info_t &finfo, bool create = false); + + // + void set_start_ea(ea_t ea) { start_ea = ea; } + + // get .got segment using the storage of well-known sections. + // If it didn't exist and the flag `create' is set then create an empty + // ".got" segment with the given initial size. + // Set the flag `create' if such segment is just created. + // If .got segment doesn't exist or an error occurred while creating it, + // the function returns NULL. + segment_t *get_got_segment(elf_file_info_t &finfo, bool *create, uint32 init_size = 0) const; + + // Some relocations, such as ARM's R_ARM_TLS_IE32, require that a got entry + // be present in the linked file, in order to point to that entry. + // However, when we are loading a simple relocatable ELF object file, + // there's no GOT present. This is problematic because, + // although we _could_ be taking a shortcut and patch the fixup to refer + // to the extern:__variable directly, it is semantically different. + // As as example, when we meet: + // LDR R3, #00000000 ; R_ARM_TLS_IE32; Offset in GOT to __libc_errno + // generating: + // LDR R3, [__libc_errno_tls_offset] + // is not the same as: + // LDR R3, [address, in got, of libc_errno_tls_offset] + // + // This is obviously the last formatting that's correct, as we don't + // even *know* what the address of __libc_errno_tls_offset is; we just + // know where to go and look for it. + // + // The solution is to create a .got section anyway, and allocate an entry + // in there with the name of the symbol, suffixed with '_tpoff'. + // + // - finfo : The elf file info (reader, ...) + // - sym : The symbol. We create the one entry for each symbol of + // each GOT-type. + // - suffix : A suffix, to be added to the symbol name. We consider + // the suffix as a GOT-type of the entry. It is sometimes + // necessary to create multiple entries for the symbol. + // E.g., '_tpoff', '_ptr', ... + // - created : The flag indicating the allocation of the new entry. + // - n : The number of allocated entries. + // - returns : An address in the .got segment. + // 0 is returned in the case of error. + ea_t allocate_entry( + elf_file_info_t &finfo, + const sym_rel &sym, + const char *suffix, + bool *created = NULL, + size_t n = 1); + + // Get the ea in the GOT section, corresponding + // the the 'A' addend. + // + // * If the file already had a GOT section, then + // the returned ea is simply got_segment->start_ea + A. + // * On the other hand, if this file had no GOT + // this calls #allocate_got_entry(). + // + // - finfo : The elf file info (reader, ...) + // - A : The 'addend' (i.e., displacement) in the GOT. + // Ignored if the original file had *no* GOT. + // - sym : The symbol. + // Ignored if the original file *did* have a GOT. + // - suffix : A suffix, to be added to the symbol name. E.g., '_tpoff', '_ptr', ... + // Ignored if the original file *did* have a GOT. + // + // - returns : An address in the GOT segment, possibly creating one. + // 0 is returned in the case of error. + ea_t get_or_allocate_entry( + elf_file_info_t &finfo, + uval_t A, + const sym_rel &sym, + const char *suffix); + + // create GOT entry for the address (used in MIPS local entries) + ea_t allocate_entry( + elf_file_info_t &finfo, + ea_t addr, + bool *created = NULL, + size_t n = 1); + +private: + // used only when original file has no GOT. + // an unique id of the symbol's GOT entry + struct symrel_id_t + { + symrel_idx_t idx; // symbol + const char *suffix; // subtype of the GOT-entry + symrel_id_t(symrel_idx_t idx_, const char *suffix_) + : idx(idx_), suffix(suffix_) {} + bool operator<(const symrel_id_t &rhs) const + { + if ( idx < rhs.idx ) + return true; + if ( !(idx == rhs.idx) ) + return false; + return strcmp(suffix, rhs.suffix) < 0; + } + }; + std::map<symrel_id_t,ea_t> allocated_sym_entries; + std::map<ea_t,ea_t> allocated_addr_entries; +}; + + +//---------------------------------------------------------------------------- +struct reloc_tools_t +{ + // dynamic information + const dynamic_info_t *di; + // reader_t container, with preprocessed data + elf_file_info_t *finfo; + // GOT accessor/creator. + got_access_t got; + ea_t load_base; + + reloc_tools_t(elf_loader_t &_ldr, const dynamic_info_t *di_, + elf_file_info_t *finfo_, const ea_t load_base); + bool section_header_overlaps(elf_shndx_t sh_idx) const; + bool has_dlt() const; +}; + +//-------------------------------------------------------------------------- +// GOT support for the relocatable files. +// the addend of the GOT reloc is applied to the insn, +// 'P - A' should point to the current or to the next insn +bool check_got_addend(ea_t P, adiff_t A, adiff_t good_addend); +bool check_got_addend(ea_t P, adiff_t A, adiff_t good1, adiff_t good2); + +//-------------------------------------------------------------------------- +namespace tls_relocs_t +{ + // generic TLS relocs + enum type_t + { + BAD, + NTPOFF, // variant 2: @ntpoff(x) (x86) or @tpoff(x) (x64), calculates + // the negative TLS offset relative to the TLS block end; + // variant 1: TPREL(S+A), resolves to the offset from the + // current thread pointer (TP) of the thread local variable. + DTPOFF, // @dtpoff(x), calculates the TLS offset relative to the + // TLS block; + // DTPREL(S+A), resolves to the offset from its module's TLS + // block of the thread local variable. + PTPOFF, // $x@tpoff (x86 only), calculates the _positive_ TLS + // offset relative to the TLS block end. + DTPMOD, // @dtpmod(x), calculates the object identifier of the + // object containing a TLS symbol; + // LDM(S), resolves to the load module index of the symbol S. + DESC, // TLSDESC(S+A), resolves to a contiguous pair of 64-bit + // values which contain a 'tlsdesc' structure describing the + // thread local variable. The first entry holds a pointer to + // the variable's TLS descriptor resolver function and the + // second entry holds a platform-specific offset or pointer. + GOTGD, // @tlsgd(x) (x86) or @tlsgd(%rip) (x64), allocates two + // contiguous entries in the GOT to hold a `tls_index' + // structure, uses the offset of the first entry. + GOTLD, // @tlsldm(x) (x86) or @tlsld(%rip) (x64), allocates two + // contiguous entries in the GOT to hold a `tls_index' + // structure, uses the offset of the first entry. The + // `ti_tlsoffset' field of the `tls_index' is set to 0. + GOTIE, // @gotntpoff(x) (x86) or @gottpoff(%rip) (x64), allocates + // an entry in the GOT, uses the offset of this entry. The + // entry holds a variable offset in the initial TLS block. + // This negative offset is relative to the TLS blocks end. + // GTPREL(S+A), represents a 64-bit entry in the GOT for the + // offset from the current thread pointer (TP) of the + // thread local variable, see TPREL(S+A). + // @indntpoff(x) (x86), like GOTIE but uses the absolute + // GOT slot address (got_mode_t::ABS). + GOTIEP, // @tpoff(x) (x86 only), allocates an entry in the GOT, + // uses the offset of this entry. The entry holds a + // variable offset in the initial TLS block. This + // _positive_ offset is relative to the TLS blocks end. + GOTDESC, // GTLSDESC(S+A), represents a consecutive pair of 64-bit + // entries in the GOT which contain a 'tlsdesc' structure. + }; + inline bool is_got_reloc(type_t type) + { + return type >= GOTGD; + } + + // GOT slot addressing mode + enum got_mode_t + { + GOT, // offset in GOT + ABS, // absolute address + RIP, // offset relative to P-A (the linker sets the addend + // so that it points to the next insn) + }; +}; + +//-------------------------------------------------------------------------- +struct proc_def_t +{ + elf_loader_t &ldr; + reader_t &reader; + uint32 relsyms[MAXRELSYMS] = { 0 }; // relocation types which must be to loaded symbols + +#define E_RELOC_PATCHING (const char *)1 +#define E_RELOC_UNKNOWN (const char *)2 +#define E_RELOC_UNIMPL (const char *)3 +#define E_RELOC_UNTESTED (const char *)4 +#define E_RELOC_NOSYM (const char *)5 +#define E_RELOC_LAST (const char *)6 + const char *stubname = nullptr; + + // order in which relocations should be applied. A name denotes a section + // to which we are applying relocations. NULL means all other sections. + enum { MAXRELORDERS = 5 }; + const char *relsecord[MAXRELORDERS] = { nullptr }; + + // types of supported special segments + enum spec_type_t + { + SPEC_XTRN, + SPEC_COMM, + SPEC_ABS, + SPEC_TLS, + NSPEC_SEGMS + }; + // additional reserved indexes of special segments (see MIPS) + uint16 additional_spec_secidx[NSPEC_SEGMS] = { 0 }; + + // TLS support of the static access model (0 - no static model) + // TP - static thread pointer, TCB - thread control block + // variant 1 (if tls_tcb_size < 0): + // +---+---+----------------------- + // |TCB|xxx| + // +---+---+----------------------- + // ^ TP ^ TLS offset of modules + // variant 2 (if tls_tcb_size > 0): + // +----------------------+---+---+ + // | |xxx|TCB| + // +----------------------+---+---+ + // ^ TLS offset of modules ^ TP + int tls_tcb_size = 0; + int tls_tcb_align = 0; // if bit 0 set then store TP at the start of TCB + +#define AUTO_NO_CTOR 0x01 // disbale ctor/dtor renaming +#define AUTO_NO_DATA 0x02 // disable data coagulation +#define AUTO_NO_NAME 0x04 // disable Alternative name storing +#define AUTO_NO_THUNK 0x08 // disable plt-thunk renaming +// see set_reloc_cmt() for other bits +#define AUTO_NO_CTBL_MASK (AUTO_NO_DATA | AUTO_NO_CTOR) + ushort auto_mode = AUTO_NO_DATA; + ushort patch_mode = 0; + + proc_def_t(elf_loader_t &_ldr, reader_t &reader); + virtual ~proc_def_t() {} + + // the sequence of callbacks during the call of elf_load_file() + // proc_is_acceptable_image_type + // proc_on_start_data_loading + // proc_should_load_section* (for each section before load) + // proc_load_unknown_sec* (for each section with unknown type) + // proc_on_create_section* (for each section before defining segment) + // proc_handle_dynamic_tag* (for each dynamic tag) + // proc_describe_flag_bit* (for each flag from header.e_flags) + // proc_on_loading_symbols* (for each symbol table) + // proc_handle_special_symbol* (for each symbol from unknown section) + // proc_handle_symbol* (for each symbol) + // proc_handle_reloc* (for each relocation) + // proc_create_got_offsets* ( TODO ) + // proc_perform_patching* (up to 2 times, see above) + // proc_convert_pic_got* ( TODO ) + // proc_adjust_entry* (for init_ea, fini_ea, header.e_entry) + // proc_on_end_data_loading + + virtual bool proc_supports_relocs() const; + + // Relocator function. + // Note: symbol might be NULL + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools); + + // Force conversion of all GOT entries to offsets + virtual bool proc_create_got_offsets( + const elf_shdr_t *gotps, + reloc_tools_t *tools); + + // Patcher function + // There are 2 passes distinguishable by function argument gotps: + // 1. ELF_RPL_PTEST NULL - check ".plt" section + // 2. pass 2 gotplt + virtual bool proc_perform_patching( + const elf_shdr_t *plt, + const elf_shdr_t *gotps); + + // Convert PIC form of loading '_GLOBAL_OFFSET_TABLE_[]' of address + virtual bool proc_can_convert_pic_got() const; + virtual size_t proc_convert_pic_got( + const segment_t *gotps, + reloc_tools_t *tools); + + // Return a bit description from e_flags and remove it. + // This function may be called in a loop to document all bits. + virtual const char *proc_describe_flag_bit(uint32 *e_flags); + + // called for processor-specific section types + virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force); + + // called for each dynamic tag. It returns NULL to continue with a + // standard tag processing, or "" to finish tag processing, or the + // description of the tag to show. + virtual const char *proc_handle_dynamic_tag(const Elf64_Dyn *dyn); + + virtual bool proc_is_acceptable_image_type(ushort filetype); + + // called after header loading (before load_pht/load_simage) + virtual void proc_on_start_data_loading(elf_ehdr_t &header); + + // called after loading data from the input file + virtual bool proc_on_end_data_loading(); + + virtual void proc_on_loading_symbols(); + + virtual bool proc_handle_symbol(sym_rel &sym, const char *symname); + + // Handle a dynamic symbol + virtual void proc_handle_dynsym( + const sym_rel &symrel, + elf_sym_idx_t isym, + const char *symname); + + // 0-reaccept, 1-set name only, else: non-existing section + virtual int proc_handle_special_symbol( + sym_rel *st, + const char *name, + ushort type); + + // called from a function should_load_segment for _every_ section. + // It returns 'false' to skip loading of the given section. + virtual bool proc_should_load_section( + const elf_shdr_t &sh, + elf_shndx_t idx, + const qstring &name); + + // called before the segment creation. It may set <sa> to the ea at + // which a given section should be loaded. In the other case the + // default segment ea computation is used. Also it may return 'false' + // to skip creation of a segment for this section. + virtual bool proc_on_create_section( + const elf_shdr_t &sh, + const qstring &name, + ea_t *sa); + + virtual const char *calc_procname(uint32 *e_flags, const char *procname); + + // for some 64-bit architectures e_entry holds not a real entry point + // but a function descriptor + // E.g. 64-bit PowerPC ELF Application Binary Interface Supplement 1.9 + // section 4.1. ELF Header + // "The e_entry field in the ELF header holds the address of a function + // descriptor. This function descriptor supplies both the address of the + // function entry point and the initial value of the TOC pointer + // register." + // this callback should translate this address to the real entry. + virtual ea_t proc_adjust_entry(ea_t entry); + + // helper functions + bool in_relsyms(uint32 r_type) const + { + for ( int i=0; i < MAXRELSYMS; ++i ) + { + if ( relsyms[i] == 0 ) + break; + if ( relsyms[i] == r_type ) + return true; + } + return false; + } + + bool section_in_relsecord(const qstring &name) const + { + for ( int i = 0; i < MAXRELORDERS; ++i ) + { + if ( relsecord[i] == NULL ) + return false; + if ( name == relsecord[i] ) + return true; + } + return false; + } + + // Note: this function should be used only for complex cases. + // For simple relocations it is recommended to use + // set_reloc_fixup(). + void set_reloc( + ea_t P, // The ea of the data to be modified. + ea_t target_ea, // The ea that the instruction would point to, + // if it were interpreted by the CPU. + uval_t patch_data, // The data to be inserted at 'P'. Depending on whether + // 'type' is a 64-bit fixup type or not, either the + // first 32-bits, or the full 64 bits of 'data' will be + // put in the database. Of course, this patch data + // must hold the possible instruction bits, if they + // are interleaved w/ the address data + // (e.g., R_ARM_THM_MOVW_ABS_NC, ...). + adiff_t displ, + fixup_type_t type, // The type of the relocation, see fixup.hpp's FIXUP_*. + // It may be standard or custom. + uval_t offbase = 0, // base of the relative fixup + uint32 flags = 0, // The flags of the relocation, see fixup.hpp's FIXUPF_*. + // You can specify additional flags: +#define FIXUPF_ELF_DO_NOT_PATCH 0x80000000 // do not patch at all +#define FIXUPF_ELF_FIXUP_PATCH 0x40000000 // do not use patch_data, patch + // using patch_fixup_value() +#define FIXUPF_ELF_DISPLACEMENT 0x20000000 // set displacement flag + // (even rel_mode == 1) +#define FIXUPF_ELF_SET_RELATIVE 0x10000000 // set fixup base + // (even offbase == 0) + adiff_t fixup_offset=0); // offset of the fixup relative to P + + // this function patches the relocatable field using patch_fixup_value() + // and store the fixup. + // It set the displacement taking in account the addend, the fact that + // the symbol is external or it is a section. + // It uses static variables REL_MODE and PRGEND. + // It is recommended to use set_reloc_fixup() instead of set_reloc(), + // because it makes the code clearer. + void set_reloc_fixup( + ea_t P, // ea of the reloc + ea_t S, // symbol of the reloc + adiff_t A, // addend of the reloc + fixup_type_t type, // the type of the fixup to store, see fixup.hpp's FIXUP_*. + // It may be standard or custom. + bool do_not_patch = false, // do not patch at all + uval_t offbase = 0, // base of the relative fixup + adiff_t fixup_offset = 0); // offset of the fixup relative to P + + void process_TLS( + tls_relocs_t::type_t type, + tls_relocs_t::got_mode_t got_mode, + fixup_type_t fixup_type, + const char *cfh_name, + ea_t P, + ea_t S, + adiff_t A, + const sym_rel *symbol, + const elf_rela_t &reloc_info, + reloc_tools_t *tools); + + // allocate GOT-entry and return it in GOT_ENTRY_EA + // \param P relocation address (to show in messages) + // \param S data to place in the entry + // \param symbol symbol of the entry, + // we allocate the single entry for the symbol, + // we create a label for the entry if the symbol has a name, + // if it is NULL we allocate the entry for the S address + bool process_GOT( + ea_t *got_ea, // may be NULL + ea_t *got_entry_ea, // not NULL + ea_t P, + ea_t S, + const sym_rel *symbol, + reloc_tools_t *tools); + + enum reloc_cmt_id_t + { + RCM_NONE = -1, + RCM_PIC = 0, + RCM_ATT = 1, + RCM_COPY = 2, + RCM_TLS = 3, + RCM_IREL = 4, + }; + void set_reloc_cmt(ea_t ea, reloc_cmt_id_t cmt) const; + void set_thunk_name( + ea_t ea, + ea_t name_ea, + const char *prefix = ".", + const char *postfix = ""); +}; + +//---------------------------------------------------------------------------- +struct arm_base_t : public proc_def_t +{ + bool already_parsed = false; + + arm_base_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; + virtual void proc_on_loading_symbols() override; + virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_arm_t : public arm_base_t +{ + fixup_type_t prel31_reltype = FIXUP_CUSTOM; + + elf_arm_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual bool proc_perform_patching( + const elf_shdr_t *plt, + const elf_shdr_t *gotps) override; + virtual bool proc_can_convert_pic_got() const override { return true; } + virtual size_t proc_convert_pic_got( + const segment_t *gotps, + reloc_tools_t *tools) override; + virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; + virtual bool proc_on_create_section( + const elf_shdr_t &sh, + const qstring &name, + ea_t *sa) override; +}; + +//---------------------------------------------------------------------------- +struct elf_aarch64_t : public arm_base_t +{ + elf_aarch64_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual bool proc_perform_patching( + const elf_shdr_t *plt, + const elf_shdr_t *gotps) override; +#ifndef __EA64__ + virtual bool proc_supports_relocs() const override { return false; } +#endif +private: + bool aarch64_process_TLS( + int rel_type, + ea_t P, + ea_t S, + adiff_t A, + const sym_rel *symbol, + const elf_rela_t &reloc_info, + reloc_tools_t *tools); +}; + +//---------------------------------------------------------------------------- +struct elf_alpha_t : public proc_def_t +{ + const elf_shdr_t *sh_plt = nullptr; // for R_ALPHA_JMP_SLOT + + elf_alpha_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; + virtual bool proc_should_load_section( + const elf_shdr_t &sh, + elf_shndx_t idx, + const qstring &name) override; +}; + +//---------------------------------------------------------------------------- +struct elf_avr_t : public proc_def_t +{ + netnode avr_helper; + fixup_type_t avr16_reltype = FIXUP_CUSTOM; + + elf_avr_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +}; + +//-------------------------------------------------------------------------- +struct elf_c166_t : public proc_def_t +{ + elf_c166_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; +}; + +//---------------------------------------------------------------------------- +struct arc_base_t : public proc_def_t +{ + arc_base_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual void proc_handle_dynsym( + const sym_rel &symrel, + elf_sym_idx_t isym, + const char *symname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_arcompact_t : public arc_base_t +{ + elf_arcompact_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +}; + +//---------------------------------------------------------------------------- +struct elf_arc_t : public arc_base_t +{ + elf_arc_t(elf_loader_t &l, reader_t &r) : arc_base_t(l, r) {} + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +}; + +//---------------------------------------------------------------------------- +struct elf_h8_t : public proc_def_t +{ + elf_h8_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_fr_t : public proc_def_t +{ + elf_fr_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +}; + +//---------------------------------------------------------------------------- +struct elf_i960_t : public proc_def_t +{ + elf_i960_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +}; + +//---------------------------------------------------------------------------- +struct elf_ia64_t : public proc_def_t +{ + elf_ia64_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; +}; + +//---------------------------------------------------------------------------- +struct elf_hppa_t : public proc_def_t +{ + fixup_type_t l21_reltype = FIXUP_CUSTOM; + fixup_type_t r11_reltype = FIXUP_CUSTOM; + + elf_hppa_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; +}; + +//---------------------------------------------------------------------------- +struct ppc_base_t : public proc_def_t +{ + fixup_type_t ha16_reltype = FIXUP_CUSTOM; + + // PLT support + enum plt_type_t + { + PLT_UNKNOWN, + PLT_SKIP, // illegal .plt section + PLT_BSS, // PLT entry contains executable code + PLT_SECURE, // PLT entry contains address + PLT_FARCALL, // PLT_BSS + should add .plt_farcall + PLT_64, // PLT entry contains function description + PLT_64V2, // PLT entry contains global entry point + }; + plt_type_t plt_type = PLT_UNKNOWN; + ea_t plt_start = BADADDR; + asize_t plt_size = 0; + bool is_dt_ppc_got_present = false; + + ppc_base_t(elf_loader_t &ldr, reader_t &reader); + virtual bool proc_should_load_section( + const elf_shdr_t &sh, + elf_shndx_t idx, + const qstring &name) override; +protected: + const char *process_JMP_SLOT(const sym_rel *symbol, ea_t P, ea_t target_ea); + int32 calc_plt_entry(adiff_t off) const; + asize_t calc_plt_size(uint32 n) const; +}; + +//---------------------------------------------------------------------------- +struct elf_ppc_t : public ppc_base_t +{ + elf_ppc_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_perform_patching( + const elf_shdr_t *plt, + const elf_shdr_t *gotps) override; + virtual const char *proc_handle_dynamic_tag(const Elf64_Dyn *dyn) override; + virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; + virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; +public: + const char *process_EMB_SDA21(ea_t P, ea_t target_ea, uint32 insn); + const char *process_GOT( + uchar type, + ea_t P, + ea_t S, + const sym_rel *symbol, + reloc_tools_t *tools, + reloc_cmt_id_t got_entry_cmt = RCM_NONE); +}; + +//---------------------------------------------------------------------------- +struct elf_ppc64_t : public ppc_base_t +{ + // how did we define the `toc_base_ea`? + // Doc: "To support position-independent code, a Global Offset Table (GOT) + // shall be constructed by the link editor in the data segment when linking + // code that contains any of the various R_PPC64_GOT* relocations or when + // linking code that references the **.TOC.** address. The GOT consists of + // an 8-byte header that contains **the TOC base** (the first TOC base when + // multiple TOCs are present), followed by an array of 8-byte addresses." + enum toc_type_t + { + TOC_UNK, + // For the relocatable object file: + TOC_CREATED, // it points to the created .tocstart section + // For the executable or shared object file: + TOC_SECTION, // it points to the first TOC's section + TOC_GOT, // we got it as the first GOT entry + TOC_SYMBOL, // it points to the .TOC. symbol + }; + toc_type_t toc_type = TOC_UNK; + + symrel_idx_t toc_sym_idx; // index of the .TOC. symbol + + // the TOC base + // We prepare this address for a relocatable object file because for an + // executable or shared object the linker already defines and uses such + // a symbol. Doc: "relocation types that refer to .TOC. may only appear + // in relocatable object files, not in executables or shared objects". + // For an executable or shared object we get this address in the same way + // but we overwrite it using the .TOC. symbol or the first GOT entry. + ea_t toc_base_ea = BADADDR; + + // offset of the TOC base from the TOC start + adiff_t toc_base_offset = 0x8000; + + bool got_already_checked = false; + + elf_ppc64_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_on_end_data_loading() override; + virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; + virtual bool proc_on_create_section( + const elf_shdr_t &sh, + const qstring &name, + ea_t *sa) override; + virtual ea_t proc_adjust_entry(ea_t entry) override; +private: + const char *process_TOC16( + uchar type, + ea_t P, + ea_t S, + adiff_t A); + void set_offset_to_toc(ea_t ea) const; + void improve_toc_using_got(); +}; + +//-------------------------------------------------------------------------- +struct pc_base_t : public proc_def_t +{ + bool plt_warned = false; + pc_base_t(elf_loader_t &ldr, reader_t &reader); + bool patch_jmp_slot_target( + const reloc_tools_t *reloc_tools, + bool is_64, + ea_t fixup_ea, + ea_t final_ea); + bool patch_irelative_target( + bool is_64, + ea_t fixup_ea, + ea_t final_ea, + const reloc_tools_t *reloc_tools); +}; + +//-------------------------------------------------------------------------- +struct elf_pc_t : public pc_base_t +{ + elf_pc_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +private: + bool convert_got32x( + ea_t P, + ea_t S, + reloc_tools_t *tools); + bool convert_call_jmp(ea_t P, ea_t S); + bool convert_mov_mem_to_imm(ea_t P, ea_t S); + bool convert_test(ea_t P, ea_t S); + bool convert_binop(ea_t P, ea_t S, uchar opcode); + bool convert_mov_to_lea(ea_t P, ea_t S, reloc_tools_t *tools); + bool patch_glob_dat_target( + ea_t fixup_ea, + ea_t final_ea, + const reloc_tools_t *tools); + bool intel_process_TLS( + int rel_type, + ea_t P, + ea_t S, + adiff_t A, + const sym_rel *symbol, + const elf_rela_t &reloc_info, + reloc_tools_t *tools); +}; + +//---------------------------------------------------------------------------- +struct elf_m16c_t : public proc_def_t +{ + elf_m16c_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_on_create_section( + const elf_shdr_t &sh, + const qstring &name, + ea_t *sa) override; + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_m32r_t : public proc_def_t +{ + elf_m32r_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_mc12_t : public proc_def_t +{ + elf_mc12_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +}; + +//---------------------------------------------------------------------------- +struct elf_mc68k_t : public proc_def_t +{ + elf_mc68k_t(elf_loader_t &ldr, reader_t &reader); + virtual bool proc_supports_relocs() const override { return false; } + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +}; + +//---------------------------------------------------------------------------- +struct elf_s390_t : public proc_def_t +{ + fixup_type_t pc16_reltype = FIXUP_CUSTOM; + fixup_type_t pc32_reltype = FIXUP_CUSTOM; + fixup_type_t lo12_reltype = FIXUP_CUSTOM; + fixup_type_t lo20_reltype = FIXUP_CUSTOM; + + elf_s390_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual bool proc_on_end_data_loading() override; +private: + bool s390_process_TLS( + int rel_type, + ea_t P, + ea_t S, + adiff_t A, + const sym_rel *symbol, + const elf_rela_t &reloc_info, + reloc_tools_t *tools); + bool handle_plt1_64(ea_t ea); +}; + +//---------------------------------------------------------------------------- +struct elf_mips_t : public proc_def_t +{ + fixup_type_t ha16_reltype = FIXUP_CUSTOM; + fixup_type_t lo16_reltype = FIXUP_CUSTOM; + fixup_type_t off16_reltype = FIXUP_CUSTOM; + fixup_type_t b26_reltype = FIXUP_CUSTOM; + fixup_type_t mips16_b26_reltype = FIXUP_CUSTOM; + fixup_type_t mips16_ha16_reltype = FIXUP_CUSTOM; + fixup_type_t mips16_lo16_reltype = FIXUP_CUSTOM; + fixup_type_t mips16_off16_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_b26_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_ha16_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_lo16_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_off16_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_b16_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_b10_reltype = FIXUP_CUSTOM; + fixup_type_t mmips_b7_reltype = FIXUP_CUSTOM; + + ea_t save_rsolve = BADADDR; + bool isPS2IRX = false; + bool isPSP = false; + bool use_relocs = true; + // The g_localgotno node will be used twice: + // 1) When processing SHT_DYNSYM syms, to associate a symbol with a .got slot + // 2) After processing symbols, during the 'patch' phase, to create + // all relocs in all "local" .got entries at the beginning of the .got. + int g_localgotno = 0; + elf_sym_idx_t g_gotsym = 0; + // offset of the gp value from the GOT start + const adiff_t gpval_offset = 0x7FF0; + // initial value of GP (GP0) + // for executable and shared objects it is the actual gp value + // for relocatable objects it is the offset of the gp value from the global area start + ea_t initial_gp = BADADDR; + // start of the global data area. this area should be addressable using $gp. + ea_t global_data_ea = BADADDR; + + ea_t last_hi16_ea = BADADDR; + adiff_t last_hi16_addend = 0; + uchar last_hi16_rel_type = 0; + bool last_hi16_done = false; + + bool got_inited = false; + + elf_mips_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual bool proc_create_got_offsets( + const elf_shdr_t *gotps, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual bool proc_load_unknown_sec(Elf64_Shdr *sh, bool force) override; + virtual int proc_handle_special_symbol( + sym_rel *st, + const char *name, + ushort type) override; + virtual const char *proc_handle_dynamic_tag(const Elf64_Dyn *dyn) override; + virtual bool proc_is_acceptable_image_type(ushort filetype) override; + virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; + virtual bool proc_on_end_data_loading() override; + virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; + virtual void proc_handle_dynsym( + const sym_rel &symrel, + elf_sym_idx_t isym, + const char *symname) override; + virtual bool proc_on_create_section( + const elf_shdr_t &sh, + const qstring &name, + ea_t *sa) override; + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; +private: + void relocate_psp_section1( + off_t file_offset, + size_t sec_size, + const sym_rel *symbol); + void set_initial_gp(uint64 offset, bool options=true); + ea_t get_final_gp(reloc_tools_t *tools); + + typedef fixup_type_t (elf_mips_t::*get_rel_type_t)(); + static const get_rel_type_t hlo_relocs[3][3]; + fixup_type_t get_ha16_reltype(); + fixup_type_t get_lo16_reltype(); + fixup_type_t get_off16_reltype(); + fixup_type_t get_b26_reltype(); + fixup_type_t get_mips16_b26_reltype(); + fixup_type_t get_mips16_ha16_reltype(); + fixup_type_t get_mips16_lo16_reltype(); + fixup_type_t get_mips16_off16_reltype(); + fixup_type_t get_mmips_b26_reltype(); + fixup_type_t get_mmips_ha16_reltype(); + fixup_type_t get_mmips_lo16_reltype(); + fixup_type_t get_mmips_off16_reltype(); + fixup_type_t get_mmips_b16_reltype(); + fixup_type_t get_mmips_b10_reltype(); + fixup_type_t get_mmips_b7_reltype(); + + enum reloc_kind_t { NONE, MIPS, MIPS16, MICROMIPS }; + enum reloc_hlo_t { HA16, LO16, OFF16 }; + static reloc_kind_t find_reloc16_kind(uchar rel_type); + fixup_type_t get_reloc16_fixup( + reloc_hlo_t hlo, + reloc_kind_t reloc_kind); + + enum symkind_t { SYM, LOCALGP, GPDISP }; + void process_ahl_reloc( + uchar rel_type, + ea_t P, + ea_t S, + symkind_t symkind, + bool is_rela, + adiff_t A, + reloc_tools_t *tools); + bool get_ssym_ea(ea_t *ssym_ea, uint8 ssym, ea_t P) const; + bool is_inside_got(reloc_tools_t *tools, ea_t P); + + // convenient function to use instead of proc_def_t::set_reloc() + void _set_reloc( + ea_t P, + fixup_type_t type, + ea_t target_ea, + adiff_t displ = 0, + uval_t offbase = 0); +}; + +//---------------------------------------------------------------------------- +struct elf_v800_t : public proc_def_t +{ + elf_v800_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +}; + +//---------------------------------------------------------------------------- +struct elf_v850_t : public proc_def_t +{ + elf_v850_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_sparc_t : public proc_def_t +{ + fixup_type_t hi22_reltype = FIXUP_CUSTOM; + fixup_type_t lo10_reltype = FIXUP_CUSTOM; + + elf_sparc_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; + virtual void proc_on_start_data_loading(elf_ehdr_t &header) override; + virtual bool proc_can_convert_pic_got() const override { return true; } + virtual size_t proc_convert_pic_got( + const segment_t *gotps, + reloc_tools_t *tools) override; + + fixup_type_t get_hi22_reltype(); + fixup_type_t get_lo10_reltype(); +}; + +//---------------------------------------------------------------------------- +struct elf_mn10200_t : public proc_def_t +{ + elf_mn10200_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +}; + +//---------------------------------------------------------------------------- +struct elf_mn10300_t : public proc_def_t +{ + elf_mn10300_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +}; + +//---------------------------------------------------------------------------- +struct elf_riscv_t : public proc_def_t +{ + fixup_type_t hi20_reltype = FIXUP_CUSTOM; + fixup_type_t got20_reltype = FIXUP_CUSTOM; + fixup_type_t lo12i_reltype = FIXUP_CUSTOM; + fixup_type_t lo12s_reltype = FIXUP_CUSTOM; + fixup_type_t call_reltype = FIXUP_CUSTOM; + std::map<ea_t,ea_t> symtable; + + elf_riscv_t(elf_loader_t &ldr, reader_t &reader); + + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual bool proc_handle_symbol(sym_rel &sym, const char *symname) override; + virtual bool proc_on_create_section( + const elf_shdr_t &sh, + const qstring &name, + ea_t *sa) override; + + fixup_type_t get_hi20_reltype(); + fixup_type_t get_got20_reltype(); + fixup_type_t get_lo12i_reltype(); + fixup_type_t get_lo12s_reltype(); + fixup_type_t get_call_reltype(); +}; + +//---------------------------------------------------------------------------- +struct elf_sh_t : public proc_def_t +{ + elf_sh_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *calc_procname(uint32 *e_flags, const char *procname) override; + virtual void proc_handle_dynsym( + const sym_rel &symrel, + elf_sym_idx_t isym, + const char *symname) override; +}; + +//---------------------------------------------------------------------------- +struct elf_st9_t : public proc_def_t +{ + elf_st9_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +}; + +//---------------------------------------------------------------------------- +struct elf_x64_t : public pc_base_t +{ + // TODO use this custom fixup in RIP-based relocs + fixup_type_t rip_reltype = FIXUP_CUSTOM; + + elf_x64_t(elf_loader_t &ldr, reader_t &reader); + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; +private: + bool convert_gotpcrelx(int rel_type, ea_t P, ea_t S); + bool x64_process_TLS( + int rel_type, + ea_t P, + ea_t S, + adiff_t A, + const sym_rel *symbol, + const elf_rela_t &reloc_info, + reloc_tools_t *tools); + bool convert_call_jmp(ea_t P, ea_t S); + bool convert_mov_to_lea(ea_t P, ea_t S); + bool convert_mov_mem_to_imm(int rel_type, ea_t P, ea_t S); + bool convert_test_binop(int rel_type, ea_t P, ea_t S, uchar opcode); +}; + +//---------------------------------------------------------------------------- +struct elf_tricore_t : public proc_def_t +{ + fixup_type_t ha16_reltype = FIXUP_CUSTOM; + + elf_tricore_t(elf_loader_t &l, reader_t &r) : proc_def_t(l, r) {} + virtual const char *proc_handle_reloc( + const rel_data_t &rel_data, + const sym_rel *symbol, + const elf_rela_t *reloc, + reloc_tools_t *tools) override; + virtual const char *proc_describe_flag_bit(uint32 *e_flags) override; +private: + void make_reloc( + const rel_data_t &rel_data, + ea_t target_ea, + uval_t patch_data, + fixup_type_t type, + bool nodispl = false); + void tricore_handle_reloc(const rel_data_t &rel_data, ea_t target_ea); + void tricore_reloc_relB(const rel_data_t &rel_data, ea_t target_ea); + void tricore_reloc_absB(const rel_data_t &rel_data, ea_t target_ea); + void tricore_reloc_abs(const rel_data_t &rel_data, ea_t target_ea); + void tricore_reloc_br(const rel_data_t &rel_data, ea_t target_ea); + void tricore_reloc_rlc( + const rel_data_t &rel_data, + uint32 patch_data, + fixup_type_t fixup_type); + void tricore_reloc_bol( + const rel_data_t &rel_data, + uint32 patch_data, + fixup_type_t fixup_type); +}; + +//---------------------------------------------------------------------------- +struct sym_rel; +class symrel_cache_t +{ +public: + + symrel_cache_t() + : storage(), + dynsym_index(0) {} + + static void check_type(slice_type_t t) + { + QASSERT(20098, t > SLT_INVALID && t <= SLT_WHOLE); + } + + elf_sym_idx_t slice_size(slice_type_t t) const { return elf_sym_idx_t(slice_end(t) - slice_start(t)); } + const sym_rel &get(slice_type_t t, elf_sym_idx_t idx) const { return storage[slice_start(t) + idx]; } + sym_rel &get(slice_type_t t, elf_sym_idx_t idx) { return storage[slice_start(t) + idx]; } + sym_rel &append(slice_type_t t); + + void qclear(uint64 room) + { + // the number in the section header may be too big (see + // pc_bad_nyms_elf.elf) so we limit it + if ( room > 65536 ) + room = 65536; + storage.qclear(); + storage.reserve(room); + } + + symrel_idx_t get_idx(const sym_rel *symbol) const; + + // this method is used in pattern/pelf.cpp + struct ptr_t : public symrel_idx_t + { + ptr_t() : symrel_idx_t(), symbols(NULL) {} + ptr_t(symrel_cache_t *s, symrel_idx_t i) + : symrel_idx_t(i), + symbols(s) {} + symrel_cache_t *symbols; + sym_rel &deref() const { return symbols->get(type, idx); } + }; + ptr_t get_ptr(const sym_rel &sym) + { + return ptr_t(this, get_idx(&sym)); + } + +private: + qvector<sym_rel> storage; + size_t dynsym_index; + size_t slice_start(slice_type_t t) const; + size_t slice_end(slice_type_t t) const; +}; + +//-------------------------------------------------------------------------- +// relocation speed +struct sym_rel +{ + mutable qstring original_name; + qstring name; // temporary for NOTYPE only + elf_sym_t original; + uint64 size; + uval_t value; // absolute value or addr + elf_shndx_t sec; // index of the section to which this symbol + // applies. For special sections it is 0 (see + // original.st_shndx). + uchar bind; // binding + char type; // type (-1 - not defined, + // -2 UNDEF SYMTAB symbol which probably is + // the same as the DYNSYM symbol, + // -3 to add an additional comment to relocs to + // unloaded symbols) + uchar flags; + + sym_rel() + : original(), + size(0), + value(0), + sec(0), + bind(0), + type(0), + flags(0) {} + + sym_rel(const sym_rel &r) + { + original_name = r.original_name; + name = r.name; + original = r.original; + size = r.size; + value = r.value; + sec = r.sec; + bind = r.bind; + type = r.type; + flags = r.flags; + } + + sym_rel &operator=(const sym_rel &r) + { + if ( this == &r ) + return *this; + this->~sym_rel(); + new (this) sym_rel(r); + return *this; + } + + void swap(sym_rel &r) + { + qswap(*this, r); + } + + void set_section_index(const reader_t &reader); + bool defined_in_special_section() const + { + CASSERT(SHN_HIRESERVE == 0xFFFF); + // assert: original.st_shndx <= SHN_HIRESERVE + return sec == 0 && original.st_shndx >= SHN_LORESERVE; + } + // for debug purpose + const char *get_section_str(char *buf, size_t bufsize) const + { + if ( defined_in_special_section() ) + qsnprintf(buf, bufsize, "%04X", uint(original.st_shndx)); + else + qsnprintf(buf, bufsize, "%u", sec); + return buf; + } + + bool overlaps(elf_shndx_t section_index, uint64 offset) const + { + return sec == section_index + && offset >= value + && offset < value + size; + } + + void set_name(const qstring &n) + { + set_name(n.c_str()); + } + + void set_name(const char *n) + { + name.qclear(); + if ( n != NULL && n[0] != '\0' ) + name = n; + } + + ea_t get_ea(const reader_t &reader, ea_t _debug_segbase=0) const; + + const qstring &get_original_name(const reader_t &reader) const; + + void set_flag(uchar flag) { flags |= flag; } + bool has_flag(uchar flag) const { return (flags & flag) != 0; } + void clr_flag(uchar flag) { flags &= ~flag; } +}; +DECLARE_TYPE_AS_MOVABLE(sym_rel); + +//-------------------------------------------------------------------------- +inline symrel_idx_t symrel_cache_t::get_idx(const sym_rel *symbol) const +{ + qvector<sym_rel>::const_iterator beg = storage.begin(); + if ( symbol == NULL || symbol < beg || symbol > storage.end() ) + return symrel_idx_t(); + size_t idx = symbol - beg; + if ( idx < dynsym_index ) + return symrel_idx_t(SLT_SYMTAB, elf_sym_idx_t(idx)); + else + return symrel_idx_t(SLT_DYNSYM, elf_sym_idx_t(idx - dynsym_index)); +} + +void overflow(ea_t fixaddr, ea_t ea); +void std_handle_dynsym(const sym_rel &symrel, elf_sym_idx_t, const char *symname); + +#define CASE_NAME(n) case n: return # n +const char *get_reloc_name(const reader_t &reader, int type); + +void parse_attributes(reader_t &reader, uint32 offset, size_t size); +int elf_machine_2_proc_module_id(reader_t &reader); + +//-------------------------------------------------------------------------- +// user parameters. these definitions and the input form are interdependent +// if you change the 'dialog_form' string, change these definitions too! +// (and don't forget to update the environment variables in the hints files) + +// IDA_ELF_LOAD_OPTS (may be set by environment variable) +#define ELF_USE_PHT 0x0001 // Use PHT if available +#define ELF_USE_SHT 0x0002 // Use SHT if available +#define ELF_LD_CHNK 0x0004 // Load huge segments by chunks + +// IDA_ELF_PATCH_MODE (may be set by environment variable) +#define ELF_RPL_PLP 0x0001 // Replace PIC form of 'Procedure Linkage Table' to non PIC form +#define ELF_RPL_PLD 0x0002 // Direct jumping from PLT (without GOT) irrespective of its form +#define ELF_RPL_GL 0x0004 // Convert PIC form of loading '_GLOBAL_OFFSET_TABLE_[]' of address +#define ELF_RPL_GOTX 0x0010 // Convert PIC form of name@GOT +#define ELF_AT_LIB 0x0020 // Mark 'allocated' objects as library-objects (MIPS only) +#define ELF_BUG_GOT 0x0040 // Force conversion of all GOT entries to offsets +#define ELF_FORM_MASK 0x0FFF // Mask for 'dialog_form' options + +// noform bits +#define ELF_DIS_GPLT 0x4000 // disable search got reference in plt +#define ELF_DIS_OFFW 0x8000 // can present offset bypass segment's + +#define ELF_RPL_PTEST (ELF_RPL_PLP | ELF_RPL_PLD) + +#define FLAGS_CMT(bit, text) if ( *e_flags & bit ) \ + { \ + *e_flags &= ~bit; \ + return text; \ + } + +//-------------------------------------------------------------------------- +inline uval_t make64(uval_t oldval, uval_t newval, uval_t mask) +{ + return (oldval & ~mask) | (newval & mask); +} + +//-------------------------------------------------------------------------- +inline uint32 make32(uint32 oldval, uint32 newval, uint32 mask) +{ + return (oldval & ~mask) | (newval & mask); +} + +#define MASK(x) ((uval_t(1) << x) - 1) + +const uval_t M32 = uint32(-1); +const uval_t M24 = MASK(24); +const uval_t M16 = MASK(16); +const uval_t M8 = MASK(8); + +inline uval_t extend_sign(uval_t value, uint bits) +{ + uval_t mask = make_mask<uval_t>(bits); + return (value & left_shift<uval_t>(1, bits-1)) != 0 + ? value | ~mask + : value & mask; +} + +#undef MASK + +#pragma pack(pop) + +//---------------------------------------------------------------------------- +struct dynamic_linking_tables_t +{ + dynamic_linking_tables_t() + : offset(0), + addr(0), + size(0), + link(0) {} + + dynamic_linking_tables_t(size_t _o, ea_t _a, size_t _s, elf_shndx_t _l) + : offset(_o), + addr(_a), + size(_s), + link(_l) {} + + bool is_valid() const { return offset != 0; } + + size_t offset; + ea_t addr; + size_t size; + elf_shndx_t link; +}; + +//---------------------------------------------------------------------------- +class dynamic_linking_tables_provider_t +{ +public: + dynamic_linking_tables_provider_t() + : dlt() {} + const dynamic_linking_tables_t &get_dynamic_linking_tables_info() const { return dlt; } + bool has_valid_dynamic_linking_tables_info() const { return dlt.is_valid(); } + void set_dynlink_table_info(size_t offset, ea_t addr, size_t size, int link) + { + dlt = dynamic_linking_tables_t(offset, addr, size, link); + } + +private: + dynamic_linking_tables_t dlt; +}; + +//---------------------------------------------------------------------------- +enum dynamic_info_type_t +{ + DIT_STRTAB, + DIT_SYMTAB, + DIT_REL, + DIT_RELA, + DIT_ANDROID_REL, + DIT_ANDROID_RELA, + DIT_PLT, + DIT_HASH, + DIT_GNU_HASH, + DIT_PREINIT_ARRAY, + DIT_INIT_ARRAY, + DIT_FINI_ARRAY, + DIT_VERDEF, + DIT_VERNEED, + DIT_VERSYM, + DIT_TYPE_COUNT, // number of dyninfo types +}; + +//---------------------------------------------------------------------------- +// various information parsed from the .dynamic section or DYNAMIC segment +struct dynamic_info_t +{ + dynamic_info_t() + { + memset(this, 0, sizeof(dynamic_info_t)); + } + + void initialize(const reader_t &reader); + + struct entry_t + { + entry_t() { clear(); } + bool is_valid() const { return offset > 0 && size != 0; } + int64 offset; + uint64 addr; + uint64 size; + uint16 entsize; + uint32 info; + + void clear() + { + offset = 0; + addr = 0; + size = 0; + entsize = 0; + info = 0; + } + + void guess_size(const sizevec_t &offsets) + { + size = BADADDR; + for ( int i = 0; i < offsets.size(); i++ ) + { + size_t off = offsets[i]; + if ( offset != 0 && off > offset ) + size = qmin(size, off - offset); + } + if ( size == BADADDR ) + size = 0; + } + } entries[DIT_TYPE_COUNT]; + + entry_t &strtab() { return entries[DIT_STRTAB]; } + entry_t &symtab() { return entries[DIT_SYMTAB]; } + const entry_t &strtab() const { return entries[DIT_STRTAB]; } + const entry_t &symtab() const { return entries[DIT_SYMTAB]; } + entry_t &rel() { return entries[DIT_REL]; } + entry_t &rela() { return entries[DIT_RELA]; } + entry_t &plt() { return entries[DIT_PLT]; } + entry_t &hash() { return entries[DIT_HASH]; } + entry_t &gnu_hash() { return entries[DIT_GNU_HASH]; } + entry_t &preinit_array() { return entries[DIT_PREINIT_ARRAY]; } + entry_t &init_array() { return entries[DIT_INIT_ARRAY]; } + entry_t &fini_array() { return entries[DIT_FINI_ARRAY]; } + entry_t &verdef() { return entries[DIT_VERDEF]; } + entry_t &verneed() { return entries[DIT_VERNEED]; } + entry_t &versym() { return entries[DIT_VERSYM]; } + + const entry_t &rel() const { return entries[DIT_REL]; } + const entry_t &rela() const { return entries[DIT_RELA]; } + const entry_t &plt() const { return entries[DIT_PLT]; } + + uint32 plt_rel_type; // type of entries in the PLT relocation table (DT_RELENT) + + static qstring d_un_str(const reader_t &reader, int64 d_tag, int64 d_un); + static const char *d_tag_str(const reader_t &reader, int64 d_tag); // may return null + static qstring d_tag_str_ext(const reader_t &reader, int64 d_tag); + + // Fill a "fake" header, typically to be used w/ + // a buffered_input_t. + bool fill_section_header(elf_shdr_t *sh, dynamic_info_type_t type) const; +}; + +//---------------------------------------------------------------------------- +// Well-known sections +enum wks_t +{ + WKS_BSS = 1, + WKS_BORLANDCOMMENT, + WKS_COMMENT, + WKS_DATA, + WKS_DYNAMIC, + WKS_DYNSYM, + WKS_GOT, + WKS_GOTPLT, + WKS_HASH, + WKS_INTERP, + WKS_NOTE, + WKS_PLT, + WKS_RODATA, + WKS_SYMTAB, + WKS_TEXT, + WKS_OPD, + WKS_SYMTAB_SHNDX, + WKS_DYNSYM_SHNDX, + WKS_PLTGOT, + WKS_VERDEF, + WKS_VERNEED, + WKS_VERSYM, + WKS_PLTSEC, + WKS_GNU_DEBUGDATA, + WKS_LAST +}; + +class section_headers_t : public dynamic_linking_tables_provider_t +{ + elf_shdrs_t headers; + uint32 wks_lut[WKS_LAST]; + reader_t *reader; + bool initialized; + bool got_is_original; // Was .got section present in the input file? + dynamic_info_t::entry_t strtab; + + friend class reader_t; + + section_headers_t(reader_t *_r) + : reader(_r), initialized(false), got_is_original(false), strtab() + { + memset(wks_lut, 0, sizeof(wks_lut)); + } + void assert_initialized() const + { + QASSERT(20099, initialized); + } +public: + bool is_initialized() const { return initialized; } + const elf_shdr_t *getn(elf_shndx_t index) const; + const elf_shdr_t *get_wks(wks_t wks) const + { + elf_shndx_t index = get_index(wks); + return index == 0 ? NULL : getn(index); + } + const elf_shdr_t *get(uint32 sh_type, const char *name) const; + +#define CONST_THIS CONST_CAST(const section_headers_t*)(this) +#define NCONST_SHDR(x) CONST_CAST(elf_shdr_t *)(x) + elf_shdr_t *getn(elf_shndx_t index) { return NCONST_SHDR(CONST_THIS->getn(index)); } + elf_shdr_t *get_wks(wks_t wks) { return NCONST_SHDR(CONST_THIS->get_wks(wks)); } + elf_shdr_t *get(uint32 sh_type, const char *name) { return NCONST_SHDR(CONST_THIS->get(sh_type, name)); } +#undef CONST_THIS +#undef NCONST_SHDR + + // Look for '.rel.<section_name>', or '.rela.<section_name>'. + const elf_shdr_t *get_rel_for(elf_shndx_t index, bool *is_rela = NULL) const; + elf_shndx_t get_index(wks_t wks) const; + void set_index(wks_t wks, elf_shndx_t index); + int add(const elf_shdr_t &); + void clear() // FIXME: This shouldn't be part of the public API + { + headers.clear(); + memset(wks_lut, 0, sizeof(wks_lut)); + } + bool empty() const { return headers.empty(); } + void resize(size_t size) { headers.resize(size); } // FIXME: This shouldn't be part of the public API + bool get_name(qstring *out, elf_shndx_t index) const; + bool get_name(qstring *out, const elf_shdr_t*) const; + bool get_name(qstring *out, const elf_shdr_t &sh) const { return get_name(out, &sh); } + elf_shdrs_t::const_iterator begin() const { return headers.begin(); } + elf_shdrs_t::const_iterator end () const { return headers.end(); } + elf_shdrs_t::iterator begin() { return headers.begin(); } + elf_shdrs_t::iterator end () { return headers.end(); } + size_t size() { return headers.size(); } + + const char *sh_type_str(uint32 sh_type) const; // may return null + qstring sh_type_qstr(uint32 sh_type) const; + + bool is_got_original(void) const { return got_is_original; } + void set_got_original(void) { got_is_original = true; } + + // Get the size of the section. That is, the minimum between + // what is advertized (sh_size) and the number of bytes between + // this, and the next section. + uint64 get_size_in_file(const elf_shdr_t &sh) const; + + // Read the section contents into the 'out' byte vector. + // This doesn't blindly rely on sh.sh_size, but will use + // get_size_in_file() instead. + // Also, the position of the linput_t will be preserved. + void read_file_contents(bytevec_t *out, const elf_shdr_t &sh) const; + + bool read_gnu_debuglink(qstring *out_link, uint32 *out_crc) const; +}; + +//---------------------------------------------------------------------------- +class program_headers_t : public dynamic_linking_tables_provider_t +{ + elf_phdrs_t pheaders; + ea_t image_base; + reader_t *reader; + bool initialized; +public: + program_headers_t(reader_t *_r) + : image_base(BADADDR), reader(_r), initialized(false) + { + } + elf_phdrs_t::const_iterator begin() const { return pheaders.begin(); } + elf_phdrs_t::const_iterator end () const { return pheaders.end(); } + elf_phdrs_t::iterator begin() { return pheaders.begin(); } + elf_phdrs_t::iterator end () { return pheaders.end(); } + elf_phdr_t *get(uint32 index) { assert_initialized(); return &pheaders[index]; } + ea_t get_image_base() const { return image_base; } + void set_image_base(ea_t ea) { image_base = ea; } + inline size_t size() const { return pheaders.size(); } + void resize(size_t sz) { pheaders.resize(sz); } // FIXME: This shouldn't be part of the pu + const char *p_type_str(uint32 p_type) const; // may return null + qstring p_type_qstr(uint32 p_type) const; + + // Get the size of the segment. That is, the minimum between + // what is advertized (p_filesz) and the number of bytes between + // this, and the next segment. + uint64 get_size_in_file(const elf_phdr_t &p) const; + + // Read the segment contents into the 'out' byte vector. + // This doesn't blindly rely on p.p_size, but will use + // get_size_in_file() instead. + // Also, the position of the linput_t will be preserved. + void read_file_contents(bytevec_t *out, const elf_phdr_t &p) const; + +private: + friend class reader_t; + void assert_initialized() const { QASSERT(20100, initialized); } +}; + +//---------------------------------------------------------------------------- +// Note Section +// Sections of type SHT_NOTE and program header elements of type PT_NOTE + +// entry +struct elf_note_t +{ + qstring name; // entry owner or originator + qstring desc; // descriptor + uint32 type; // interpretation of descriptor + + // fill entry and return new start offset + static bool unpack(elf_note_t *entry, size_t *start, const bytevec_t &buf, bool mf); + +private: + static bool unpack_sz(size_t *out, size_t *start, const bytevec_t &buf, bool mf); + static bool unpack_strz(qstring *out, const bytevec_t &buf, size_t start, size_t len); + static bool unpack_mem(qstring *out, const bytevec_t &buf, size_t start, size_t len, bool as_strz=false); +}; +typedef qvector<elf_note_t> elf_notes_t; + +// entry originators and types +#define NT_NAME_GNU "GNU" +#define NT_GNU_BUILD_ID 3 + +class notes_t +{ +public: + notes_t(reader_t *_r) : reader(_r), initialized(false) + {} + + elf_notes_t::const_iterator begin() const { return notes.begin(); } + elf_notes_t::const_iterator end () const { return notes.end(); } + void clear(void) { notes.clear(); } + void add(const bytevec_t &buf); + + // convenience functions + + // Build ID + bool get_build_id(qstring *out) const; + +private: + reader_t *reader; + elf_notes_t notes; + bool initialized; + + friend class reader_t; + void assert_initialized() const { QASSERT(20082, initialized); } +}; + +const char *d_note_gnu_type_str(uint64 type); +const char *d_note_linux_type_str(uint64 type); +const char *d_note_core_type_str(uint64 type); + +//---------------------------------------------------------------------------- +class arch_specific_t +{ +public: + virtual ~arch_specific_t() {} + virtual void on_start_symbols(reader_t &/*reader*/) {} + virtual void on_symbol_read(reader_t &/*reader*/, sym_rel &/*sym*/) {} +}; + +//---------------------------------------------------------------------------- +//-V:reader_t:730 Not all members of a class are initialized inside the constructor +class reader_t +{ +public: + // Type definitions + // DOCME + enum unhandled_section_handling_t + { + ush_none = 0, + ush_load, + ush_skip + }; + + /* + * The list of notifications to which the user of the reader + * can react. + * It is documented as follows: + * 1) a short description of the notification, and possibly a hint + * on how it should be considered/treated. + * 2) the list of arguments, to be consumed in a vararg fashion. + */ + enum errcode_t + { + /* + * The "class" of the ELF module is not properly defined. It + * should really be one of (ELFCLASS32, ELFCLASS64). + * We will fallback to the ELFCLASS32 class. + * - uint8: the ELF class, as defined in the file. + */ + BAD_CLASS = 1, + + /* + * The size of the ELF header conflicts with what was expected. + * - uint16: the size of the ELF header, as defined in the file + * (i.e., eh_ehsize) + * - uint16: the expected size. + */ + BAD_EHSIZE, + + /* + * The byte ordering is not properly defineed. It should + * really be one of (ELFDATA2LSB, ELFDATA2MSB). + * We will fallback to the ELFDATA2LSB ordering. + * - uint8: the byte ordering, as defined in the file. + */ + BAD_ENDIANNESS, + + /* + * The ELF module defines there are Program Header entries, + * but it defines an entry size to be of an odd size. + * We will fallback to the default size for program header + * entries, which depends on the "class" of this ELF module. + * - uint16: the size of a program header entry, as defined in + * the file. + * - uint16: the expected size (to which we will fallback). + */ + BAD_PHENTSIZE, + + /* + * The ELF module either: + * 1) defines an offset for the Program Header entries data but a + * count of 0 entries, or + * 2) defines no offset for the Program Header entries data but a + * count of 1+ entries. + * We will not use the program header table. + * - uint16: the number of entries, as defined in the file. + * - uint64: the offset for the entries data. + */ + BAD_PHLOC, + + /* + * The ELF module defines there are Section Header entries, + * but it defines an entry size to be of an odd size. + * We will fallback to the default size for section header + * entries, which depends on the "class" of this ELF module. + * - uint16: the size of a section header entry, as defined in + * the file. + * - uint16: the expected size (to which we will fallback). + */ + BAD_SHENTSIZE, + + /* + * The ELF module: + * 1) defines an offset for the Section Header entries data but a + * count of 0 entries, or + * 2) defines no offset for the Section Header entries data but a + * count of 1+ entries, or + * 3) defines too many entries, which would cause an EOF to occur + * while reading those. + * We will not use the section header table. + * - uint32: the number of entries, as defined in the file. + * - uint64: the offset for the entries data. + * - int64 : the size of the file. + */ + BAD_SHLOC, + + /* + * The reader has encountered an unhandled section. + * - uint16 : The index of the section header. + * - Elf64_Shdr*: A pointer to the section header structure. + * If handled, this notification should return a + * "unhandled_section_handling_t", specifying how the + * reader should proceed with it. + */ + UNHANDLED_SECHDR, + + /* + * The reader has encountered an unhandled section, + * which even the reader instance user couldn't handle. + * - uint16 : The index of the section header. + * - Elf64_Shdr*: A pointer to the section header structure. + */ + UNKNOWN_SECHDR, + + /* + * The reader has spotted that the section's address + * in memory (i.e., sh_addr) is not aligned on the + * specified alignment (i.e., sh_addralign). + * - uint16 : The index of the section header. + * - Elf64_Shdr*: A pointer to the section header structure. + */ + BAD_SECHDR_ALIGN, + + /* + * The section header 0 is supposed to be SHT_NULL. But it wasn't. + */ + BAD_SECHDR0, + + /* + * The type of file (e_type) appears to be ET_CORE, and the + * machine is SPARC. Those files usually have wrong SHT's. We + * will rather opt for the PHT view. + */ + USING_PHT_SPARC_CORE, + + /* + * TLS definitions occurred more than once in the file. + */ + EXCESS_TLS_DEF, + + /* + * The section with the given name is being redefined. + * - const char *: The name of the section + */ + SECTION_REDEFINED, + + /* + * While parsing the dynamic_info_t, the reader spotted + * an invalid value for the DT_PLTREL entry. + * - uint32: The 'value' of that entry. + */ + BAD_DYN_PLT_TYPE, + + /* + * One of the symbols in the symbols tables has a bad binding. + * - unsigned char: The binding. + */ + BAD_SYMBOL_BINDING, + + /* + * The ELF module has a Section Header String Table index, but + * it is out-of-bounds. + * - uint32: the section header string table index; + * - uint16: the number of section header entries; + */ + BAD_SHSTRNDX, + + /* + * The ELF module has Program Header entries, which means it's + * ready to be loaded as a process image, but claims it is of + * type ET_REL which makes it a relocatable object file. + */ + CONFLICTING_FILE_TYPE, + + LAST_WARNING = CONFLICTING_FILE_TYPE, + + /* + * Couldn't read as many bytes as required. + * This is a fatal issue, and should be treated as such. + * - size_t: expected bytes. + * - size_t: actually read. + * - int32 : position in file when reading was initiated. + */ + ERR_READ, + + LAST_ERROR = ERR_READ + }; + + // Data members + program_headers_t pheaders; + section_headers_t sections; + symrel_cache_t symbols; + dynamic_info_t::entry_t sym_strtab; // for SYMTAB + dynamic_info_t::entry_t dyn_strtab; // for DYNSYM + + struct standard_sizes_in_file_t + { + int ehdr; + int phdr; + int shdr; + + struct + { + uint sym; + int dyn; + int rel; + int rela; + } entries; + + struct + { + uint sym; // DT_SYMENT + uint rel; // DT_RELENT + uint rela; // DT_RELAENT + } dyn; + + struct + { + int elf_addr; + int elf_off; + int elf_xword; + int elf_sxword; + } types; + } stdsizes; + +private: + linput_t *li; + int64 sif; // ELF start in file + uint64 filesize; + // Handle an error. If this function returns false, the reader will stop. + bool (*handle_error)(const reader_t &reader, errcode_t notif, ...); + elf_ehdr_t header; + + struct mapping_t + { + uint64 offset; + uint64 size; + uint64 ea; + }; + qvector<mapping_t> mappings; + + arch_specific_t *arch_specific; + adiff_t load_bias; // An offset to apply to the ea's + // when loading the program in memory. + // real endianness and bitness of the file + // some loaders (e.g. Linux) ignore values in the ident header + // so we set the effective ones here + bool eff_msb; + bool eff_64; // is elf64? + bool seg_64; // segments are 32bit or 64bit? + + bool check_ident(); +public: + reader_t(linput_t *_li, int64 _start_in_file = 0); + ~reader_t() + { + delete arch_specific; + } + void set_linput(linput_t *_li) { li = _li; } + linput_t *get_linput() const { return li; } + void set_load_bias(adiff_t lb) { load_bias = lb; } + adiff_t get_load_bias() const { return load_bias; } + + bool is_warning(errcode_t notif) const; + bool is_error(errcode_t notif) const; + ssize_t prepare_error_string(char *buf, size_t bufsize, reader_t::errcode_t notif, va_list va) const; + + void set_handler(bool (*_handler)(const reader_t &reader, errcode_t notif, ...)); + + int read_addr(void *buf) const; + int read_off(void *buf) const; + int read_xword(void *buf) const; + int read_sxword(void *buf) const; + int read_word(uint32 *buf) const; + int read_half(uint16 *buf) const; + int read_byte(uint8 *buf) const; + int read_symbol(elf_sym_t *buf) const; + int safe_read(void *buf, size_t size, bool apply_endianness = true) const; + + bool read_ident(); // false - bad elf file + + // Is the file a valid relocatable file? That is, it must have + // the ET_REL ehdr e_type, and have a proper section table. + bool is_valid_rel_file() const + { + return sections.initialized && !sections.empty() && get_header().e_type == ET_REL; + } + const elf_ident_t &get_ident() const { return header.e_ident; } + + bool read_header(); + elf_ehdr_t &get_header () { return header; } + const elf_ehdr_t &get_header () const { return header; } + + bool read_section_headers(); + bool read_program_headers(); + bool read_notes(notes_t *notes); + + // Android elf files can have a prelink. + // If such a prelink was found, this will return 'true' and + // '*base' will be set to that prelink address. + bool read_prelink_base(uint32 *base); + + int64 get_start_in_file() const { return sif; } + + // Seek to section header #index. + // (Note that this does not seek to the section's contents!) + bool seek_to_section_header(elf_shndx_t index) + { + uint64 pos = header.e_shoff + uint64(index) * uint64(header.e_shentsize); + if ( pos < header.e_shoff ) + return false; + if ( seek(pos) == -1 ) + return false; + return true; + } + + // read the section header from the current position + // (should be called after seek_to_section_header) + bool read_section_header(elf_shdr_t *sh); + + // Seek to program header #index. + // (Note that this does not seek to the segment's contents!) + bool seek_to_program_header(uint32 index) + { + uint64 pos = header.e_phoff + uint64(index) * uint64(header.e_phentsize); + if ( pos < header.e_phoff ) + return false; + if ( seek(pos) == -1 ) + return false; + return true; + } + + // read the compression header from the current position + // (should be called after seek_to_compression_header) + bool read_compression_header(elf_chdr_t *out); + + // Get the current position, in the elf module (which could + // start at an offset different than 0 in the file). + int64 tell() const { return qltell(li) - sif; } + int64 size() const { return filesize - sif; } + + // Seek in the elf module, at the given position. If the elf module has an + // offset in the file, it will be added to 'pos' to compose the final + // position in file. + qoff64_t seek(int64 pos) const { return qlseek(li, sif+pos); } + + // + elf_sym_idx_t rel_info_index(const elf_rela_t &r) const; + uint32 rel_info_type(const elf_rela_t &r) const; + void set_rel_info_index(elf_rela_t *r, uint32 symidx) const; + void set_rel_info_type(elf_rela_t *r, uint32 type) const; + + void add_mapping(const elf_phdr_t &p); + // Searches all defined mappings for one that would + // encompass 'ea'. Returns -1 if not found. + int64 file_offset(uint64 ea) const; + // Searches all defined mappings for one that would + // encompass file offset 'offset'. Returns BADADDR if not found. + ea_t file_vaddr(uint64 offset) const; + + elf_shndx_t get_shndx_at(uint64 offset) const; + + // string tables + void set_sh_strtab( + dynamic_info_t::entry_t &strtab, + const elf_shdr_t &strtab_sh, + bool replace); + void set_di_strtab( + dynamic_info_t::entry_t &strtab, + const dynamic_info_t::entry_t &strtab_di); + bool get_string_at(qstring *out, uint64 offset) const; + bool get_name( + qstring *out, + const dynamic_info_t::entry_t &strtab, + uint32 name_idx) const; + bool get_name(qstring *out, slice_type_t slice_type, uint32 name_idx) const; + + // Sets the dynamic info + typedef qvector<elf_dyn_t> dyninfo_tags_t; + bool read_dynamic_info_tags( + dyninfo_tags_t *dyninfo_tags, + const dynamic_linking_tables_t &dlt); + bool parse_dynamic_info( + dynamic_info_t *dyninfo, + const dyninfo_tags_t &dyninfo_tags); + + // Symbol versions + bool read_symbol_versions( + elf_symbol_version_t *symver, + const dynamic_info_t &di, + bool use_pht); + + arch_specific_t *get_arch_specific() const { return arch_specific; } + + // Human-friendly representations of + // header (or ident) values. + const char *file_type_str() const; + const char *os_abi_str() const; + const char *machine_name_str() const; // may return NULL + qstring get_machine_name() const; + + // effective endianness + bool is_msb() const { return eff_msb; } + // effective bitness (elf32 or elf64) + bool is_64() const { return eff_64; } + // effective bitness for segments + int get_seg_bitness() const { return seg_64 ? 2 : 1; } + + // pointer size for some 64bit ABIs may be 32bit + bool is_32_ptr() const + { + return !is_64() + || header.e_machine == EM_PPC64 + && header.e_ident.osabi == ELFOSABI_CELLOSLV2 + || header.e_machine == EM_X86_64 + && header.e_ident.osabi == ELFOSABI_NACL; + } + + bool is_arm() const + { + return header.e_machine == EM_ARM || header.e_machine == EM_AARCH64; + } + bool is_mips() const + { + return header.e_machine == EM_MIPS; + } + + // validate section size and return number of elements + void validate_section_size( + uint64 *count, + size_t *entsize, + const elf_shdr_t §ion, + const char *counter_name); +}; + +//---------------------------------------------------------------------------- +struct input_status_t +{ + input_status_t(const reader_t &_reader) + : reader(_reader), + pos(reader.tell()) + { + } + + qoff64_t seek(int64 new_pos) + { + return reader.seek(new_pos); + } + + ~input_status_t() + { + reader.seek(pos); + } +private: + const reader_t &reader; + int64 pos; + input_status_t(); +}; + +//---------------------------------------------------------------------------- +#define _safe(expr) if ( (expr) < 0 ) return false +struct elf_verdef_t : public Elf_Verdef +{ + bool read(const reader_t &reader) + { + _safe(reader.read_half(&vd_version)); + _safe(reader.read_half(&vd_flags)); + _safe(reader.read_half(&vd_ndx)); + _safe(reader.read_half(&vd_cnt)); + _safe(reader.read_word(&vd_hash)); + _safe(reader.read_word(&vd_aux)); + _safe(reader.read_word(&vd_next)); + return true; + } + uint16 cnt() + { + return vd_cnt; + } + uint32 aux() + { + return vd_aux; + } + uint32 next() + { + return vd_next; + } +}; + +//---------------------------------------------------------------------------- +struct elf_verdaux_t : public Elf_Verdaux +{ + bool read(const reader_t &reader) + { + _safe(reader.read_word(&vda_name)); + _safe(reader.read_word(&vda_next)); + return true; + } + uint32 next() + { + return vda_next; + } +}; + +//---------------------------------------------------------------------------- +struct elf_verneed_t : public Elf_Verneed +{ + bool read(const reader_t &reader) + { + _safe(reader.read_half(&vn_version)); + _safe(reader.read_half(&vn_cnt)); + _safe(reader.read_word(&vn_file)); + _safe(reader.read_word(&vn_aux)); + _safe(reader.read_word(&vn_next)); + return true; + } + uint16 cnt() + { + return vn_cnt; + } + uint32 aux() + { + return vn_aux; + } + uint32 next() + { + return vn_next; + } +}; + +//---------------------------------------------------------------------------- +struct elf_vernaux_t : public Elf_Vernaux +{ + bool read(const reader_t &reader) + { + _safe(reader.read_word(&vna_hash)); + _safe(reader.read_half(&vna_flags)); + _safe(reader.read_half(&vna_other)); + _safe(reader.read_word(&vna_name)); + _safe(reader.read_word(&vna_next)); + return true; + } + uint32 next() + { + return vna_next; + } +#undef _safe +}; + +//---------------------------------------------------------------------------- +struct symbol_verdaux_t +{ + int64 offset; + size_t name; // index in symver.version_names +}; +DECLARE_TYPE_AS_MOVABLE(symbol_verdaux_t); +typedef qvector<symbol_verdaux_t> symbol_verdaux_vec_t; + +//---------------------------------------------------------------------------- +struct symbol_verdef_t +{ + int64 offset; + symbol_verdaux_vec_t auxs; + uint16 flags; + uint16 ndx; +}; +DECLARE_TYPE_AS_MOVABLE(symbol_verdef_t); +typedef qvector<symbol_verdef_t> symbol_verdef_vec_t; + +//---------------------------------------------------------------------------- +struct symbol_vernaux_t +{ + int64 offset; + size_t name; // index in symver.version_names + uint16 other; +}; +DECLARE_TYPE_AS_MOVABLE(symbol_vernaux_t); +typedef qvector<symbol_vernaux_t> symbol_vernaux_vec_t; + +//---------------------------------------------------------------------------- +struct symbol_verneed_t +{ + int64 offset; + size_t name; // index in symver.file_names + symbol_vernaux_vec_t auxs; +}; +DECLARE_TYPE_AS_MOVABLE(symbol_verneed_t); +typedef qvector<symbol_verneed_t> symbol_verneed_vec_t; + +//---------------------------------------------------------------------------- +struct vermap_item_t +{ + size_t fname_idx; // index in symver.file_names + size_t vname_idx; // index in symver.version_names +}; + +//---------------------------------------------------------------------------- +typedef std::map<uint16, vermap_item_t> symbol_version_map_t; + +//---------------------------------------------------------------------------- +struct elf_symbol_version_t +{ + // from DT_VERDEF + symbol_verdef_vec_t defs; + // from DT_VERNEED + symbol_verneed_vec_t reqs; + // from DT_VERSYM + qvector<uint16> symbols; + + // item with VER_FLG_BASE in verdaux + size_t def_base; // index in file_names + + // file and version strings referenced throughout this structure + qstrvec_t file_names; + qstrvec_t version_names; + + // map for entries in DT_VERSYM + symbol_version_map_t vermap; + + elf_symbol_version_t() + : def_base(0) + {} +}; + +//---------------------------------------------------------------------------- +template<typename T> class buffered_input_t +{ +protected: + reader_t &reader; + uint64 offset; + uint64 count; + size_t isize; // entry size + + qvector<T> buffer; + uint64 read; // number of items we already read from the input + uint32 cur; // ptr to the next item in 'buffer' to be served + uint32 end; // number of items in 'buffer' + +public: + buffered_input_t(reader_t &_reader, const elf_shdr_t §ion) + : reader(_reader), + offset(section.sh_offset), + count (0), + isize (section.sh_entsize), + read (0), + cur (0), + end (0) + { + count = reader.sections.get_size_in_file(section); + if ( isize != 0 ) + count /= isize; + } + buffered_input_t( + reader_t &_reader, + uint64 _offset, + uint64 _count, + size_t entsize) + : reader(_reader), + offset(_offset), + count (_count), + isize (entsize), + read (0), + cur (0), + end (0) {} + virtual ~buffered_input_t() {} + + virtual bool next(T *&storage) newapi + { + if ( cur >= end ) + { + uint64 left = count - read; + if ( left == 0 ) + return false; + buffer.resize(left); + + cur = 0; + if ( read == 0 ) + start_reading(); + end = read_items(left); + if ( end == 0 ) + return false; + read += end; + } + + if ( cur >= end ) + return false; + + storage = &buffer[cur]; + cur++; + return true; + } + +private: + buffered_input_t(); + // default and dumb implementation of read_items() + // it reads items one by one from the input. + // see other implementations in template specializations + ssize_t read_items(size_t max) + { + size_t i = 0; + if ( is_mul_ok<uint64>(read, isize) && is_mul_ok(max, isize) ) + { + input_status_t save_excursion(reader); + if ( save_excursion.seek(offset + (read * isize)) != -1 ) + for ( ; i < max; i++ ) + if ( !read_item(buffer[i]) ) + break; + } + return i; + } + + bool read_item(T &) { return false; } + void start_reading() {} +}; + +class buffered_rel_t : public buffered_input_t<elf_rel_t> +{ + typedef buffered_input_t<elf_rel_t> inherited; + elf_rela_t rela; // to return from next_rela() + +public: + buffered_rel_t(reader_t &_reader, const elf_shdr_t §ion) + : inherited(_reader, section) {} + buffered_rel_t( + reader_t &_reader, + uint64 _offset, + uint64 _count, + size_t entsize) + : inherited(_reader, _offset, _count, entsize) {} + bool next_rela(elf_rela_t *&storage) + { + elf_rel_t *rel; + if ( !inherited::next(rel) ) + return false; + rela.r_offset = rel->r_offset; + rela.r_info = rel->r_info; + rela.r_addend = 0; + storage = &rela; + return true; + } +}; + +class buffered_rela_t : public buffered_input_t<elf_rela_t> +{ + typedef buffered_input_t<elf_rela_t> inherited; + + bool packed; +public: + buffered_rela_t(reader_t &_reader, const elf_shdr_t §ion, bool _packed) + : inherited(_reader, section), packed(_packed) {} + buffered_rela_t( + reader_t &_reader, + uint64 _offset, + uint64 _count, + size_t entsize, + bool _packed) + : inherited(_reader, _offset, _count, entsize), packed(_packed) {} + virtual bool next(elf_rela_t *&storage) override; + bool next_rela(elf_rela_t *&storage) { return next(storage); } +}; + +//-------------------------------------------------------------------------- +struct shdr_def_t +{ + range_t range; + sel_t sel; // selectors of loaded sections, + // BADSEL-section not loaded + bool may_overlap; // may overlap with other sections. + // no warning is shown, but sh_overlaps is still set. + + shdr_def_t() : sel(BADSEL), may_overlap(false) {} + shdr_def_t(const elf_shdr_t *sh, bool may_overlap_ = false) + : range(ea_t(sh->sh_offset), ea_t(sh->sh_offset + sh->sh_size)), + sel(BADSEL), + may_overlap(may_overlap_) {} +}; +DECLARE_TYPE_AS_MOVABLE(shdr_def_t); +typedef qvector<shdr_def_t> shdr_defs_t; + +//-------------------------------------------------------------------------- +// description of special segments +struct elf_spec_segm_t +{ + //lint --e{958} Padding of ... is required to align member on ... boundary + // description + const char *seg_name = nullptr; + uint16 shn_type = 0; + uchar seg_type = 0; + // allocation + uint32 nsyms = 0; + ea_t start = 0; + ea_t end = 0; + ea_t cur = 0; + + elf_spec_segm_t(uchar seg_type_=0, const char *seg_name_=nullptr, uint16 shn_type_=0) + : seg_name(seg_name_), + shn_type(shn_type_), + seg_type(seg_type_) + { + } + + static proc_def_t::spec_type_t symbol2spec( + const proc_def_t *pd, + uint16 secidx, + ushort type); + bool not_allocated() const { return start == 0 && end == 0; } + + bool allocate_spec_segm(elf_loader_t &ldr, reader_t &reader); + + // it shrinks the segment and returns its new end + ea_t end_seg(); +}; + +//------------------------------------------------------------------------- +struct elf_range_info_t +{ + ea_t start; + ea_t end; + int64 offset; +}; +DECLARE_TYPE_AS_MOVABLE(elf_range_info_t); +typedef std::map<ea_t, elf_range_info_t> range_info_map_t; +typedef range_info_map_t::const_iterator range_info_map_citerator_t; + +class loaded_ranges_t +{ + rangeset_t ranges; + range_info_map_t range_info_map; + +public: + bool add(int64 offset, ea_t start, ea_t _end) + { + bool ok = ranges.add(start, _end); + if ( ok ) + { + elf_range_info_t &info = range_info_map[start]; + info.start = start; + info.end = _end; + info.offset = offset; + } + return ok; + } + const range_t *find_range(ea_t ea) const + { + return ranges.find_range(ea); + } + ea_t next_range(ea_t ea) const + { + return ranges.next_range(ea); + } + const elf_range_info_t *range_info(ea_t ea) const + { + const range_t *range = ranges.find_range(ea); + if ( range == NULL ) + return NULL; + range_info_map_citerator_t it = range_info_map.find(range->start_ea); + if ( it == range_info_map.end() ) + return NULL; + return &it->second; + } +}; + +//-------------------------------------------------------------------------- +class tlsinfo2_public_t +{ + friend struct process_tls_t; + friend struct elf_loader_t; + struct tlsinfo2_t *pimpl; +public: + tlsinfo2_public_t(elf_loader_t &l); + tlsinfo2_public_t(); + ~tlsinfo2_public_t(); + void set_env(reader_t &reader_, elf_spec_segm_t &spec_tls_); + void set_from_ph(const elf_phdr_t &p); + // should be called after set_from_ph() + void set_from_tdata_sh( + const elf_shdr_t &sh, + elf_shndx_t secidx, + const char *name); + // should be called after set_from_ph() + void set_from_tbss_sh( + const elf_shdr_t &sh, + elf_shndx_t secidx, + const char *name); + void create_tls_template(); + // define 'tls_index' structures + void analyze_tis(); + ea_t get_tls_end() const; + ea_t symbol2ea(const sym_rel &symrel) const; +}; + +//---------------------------------------------------------------------------- +class gnu_debugdata_t +{ +public: + enum xz_ret_t + { + XZRET_OK, + XZRET_OUT_OF_MEMORY, + XZRET_DECODE_ERROR, + XZRET_CHECKSUM_ERROR, + XZRET_BAD_HEADERS + }; + +private: + bytevec_t decompressed; + linput_t *li = nullptr; + elf_file_info_t *finfo = nullptr; + xz_ret_t xz_comment = XZRET_OK; + +public: + ~gnu_debugdata_t() + { + clear_finfo(); + clear_li(); + } + + elf_file_info_t *file_info() { return finfo; } + + xz_ret_t comment() const { return xz_comment; } + + bool init(); + bool create_reader(const bytevec_t &compressed); + +private: + void clear_li(); + void clear_finfo(); + +protected: + xz_ret_t xz_decompress_memory(bytevec_t *buf_out, const bytevec_t &buf_in); +}; + +//-------------------------------------------------------------------------- +struct elf_loader_t +{ + linput_t *li = nullptr; + struct processor_t &ph; + elf_spec_segm_t spec_segms[proc_def_t::NSPEC_SEGMS]; + + sel_t cursel = 0; + sel_t datasel = 0; + + elf_shndx_t ct_sec = 0; + elf_shndx_t dt_sec = 0; + ea_t init_ea = 0; + ea_t fini_ea = 0; + ea_t init_proc_ea = 0; + ea_t fini_proc_ea = 0; + + tlsinfo2_public_t tlsinfo2; + + proc_def_t *pd = nullptr; + + qstrvec_t implibs; + netnode impnode = BADNODE; + + qstring interpreter; + + netnode elfnode; + + // The program end. Does *not* contain the 'extern' segment. It does, + // however, contain .bss and .tbss data. + ea_t prgend = 0; + + // index of the _GLOBAL_OFFSET_TABLE_ symbol for the relocatable files + symrel_idx_t got_sym_idx; + + // This symbol is used only for debugging purposes. + // It specifies the segment base to be used for all segments. + // Usually it is zero (ELF files use flat memory without any segments) + uval_t debug_segbase = 0; + + loaded_ranges_t loaded_ranges; + size_t overlapped_range_cnt = 0; + + // structure ids for VERDEF, VERDAUX, etc + tid_t verdef_sid = BADADDR; + tid_t verdaux_sid = BADADDR; + tid_t vernaux_sid = BADADDR; + tid_t verneed_sid = BADADDR; + tid_t prstatus_sid = BADADDR; + tid_t prpsinfo_sid = BADADDR; + tid_t elf_sym_sid = BADADDR; + tid_t elf_rel_sid = BADADDR; + tid_t elf_rela_sid = BADADDR; + + size_t stubsize = 0; + ea_t topaddr = 0; + + ushort neflags; + fixup_type_t ptpoff_reltype = FIXUP_CUSTOM; + + bool broken_output_warning_displayed = false; + bool widebyte = false; + bool was_empty_idb = false; + bool gnuunx_loaded = false; // loaded gnuunx.til? + bool rel_present = false; + char rel_mode = 0; // 1 - STT_SECTION + // 0 - !STT_SECTION + //-1 - STT_NOTYPE or undefined + + gnu_debugdata_t gnu_debugdata; + + elf_loader_t(linput_t *li, ushort neflags); + ~elf_loader_t(); + void load_file(); + ushort ana_hdr(reader_t &reader); + void collect_loader_options(struct elf_load_options *load_opts); + const char *get_processor_name( + reader_t &reader, + const elf_ehdr_t &header, + bool msb); + size_t max_loaded_size(ea_t ea, size_t size) const; + bool is_range_loaded(ea_t ea, size_t size) const; + bool load_section_headers(reader_t &reader); + elf_file_info_t *find_companion_file( + const reader_t &main_reader, + const notes_t ¬es, + const elf_load_options &load_opts, + rangevec_t *loaded_notes); + ea_t preload_pht(reader_t &reader); + void load_pht( + reader_t &reader, + const elf_load_options &load_opts, + rangevec_t *loaded_notes); + bool should_load_segment( + reader_t &reader, + const elf_shdr_t *sh, + elf_shndx_t idx, + const qstring &name); + bool is_uniform(reader_t &reader, size_t offset, asize_t size); + void find_and_load_gaps(reader_t &reader); + void load_section_contents( + elf_file_info_t &finfo, + rangevec_t *loaded_notes); + bool belongs_to_skipped_section( + elf_file_info_t &finfo, + const sym_rel &sym); + void detect_overlapping_pht(int64 offset, ea_t startaddr, ea_t endaddr); + void validate_dynamic_info(reader_t &reader, dynamic_info_t *di) const; + void annotate_headers(reader_t &reader); + void annotate_loaded_notes(reader_t &reader, const rangevec_t &loaded_notes); + void annotate_note_core(reader_t &reader, const struct print_note_t ¬e); + void make_verdef_section( + reader_t &reader, + const dynamic_info_t::entry_t &entry, + const elf_symbol_version_t &symver); + void make_verneed_section( + reader_t &reader, + const dynamic_info_t::entry_t &entry, + const elf_symbol_version_t &symver); + void make_versym_section( + reader_t &reader, + const dynamic_info_t::entry_t &entry, + const elf_symbol_version_t &symver); + void make_rel_section( + reader_t &reader, + const dynamic_info_t::entry_t &entry, + bool is_rela, + const char *name); + void make_symtab_section(reader_t &reader, const dynamic_info_t::entry_t &entry); + ea_t unwide_ea(ea_t ea, const char *diagn) const; + void preprocess_symbols( + elf_file_info_t &finfo, + const elf_load_options &load_opts); + bool extract_gnu_debugdata(reader_t &main_reader); + int load_symbols( + elf_file_info_t &finfo, + slice_type_t slice_type, + uint32 section_symbols_count, + bool skip_undef_symbols); + void apply_file_symbols(elf_file_info_t &finfo); + void check_notype_symbols( + elf_file_info_t &finfo, + slice_type_t slice_type); + void define_gotnode(elf_file_info_t &finfo, const elf_dyn_t &dyn); + void describe_public( + ea_t ea, + ushort bind, + int entry_flag, + const char *name, + const elf_symbol_version_t *symver=NULL, + elf_sym_idx_t symidx=0); + ea_t create_addonce_var( + ea_t ea, + uint64 valsiz, + uchar seg_typ, + ushort type, + ushort bind, + bool isfunc, + const char *name, + const elf_symbol_version_t *symver, + elf_sym_idx_t symidx); + ea_t declare_spec( + reader_t &reader, + uint16 secidx, + uint64 size, + ushort type, + ushort bind, + bool isfunc, + const char *name, + const elf_symbol_version_t *symver=NULL, + elf_sym_idx_t symidx=0); + void count_spec_symbols( + reader_t &reader, + slice_type_t slice_type, + bool skip_undef_symbols); + bool call_add_segm_ex( + segment_t *s, + const char *name, + const char *sclass, + int flags) const; + bool add_or_merge_segm( + segment_t *s, + const char *name, + const char *sclass, + int flags); + bool do_define_segment( + reader_t &reader, + ea_t *out_sa, + ea_t *out_topseg, + elf_shdr_t &sh, + const qstring &name); + bool define_segment( + elf_file_info_t &finfo, + elf_shdr_t &sh, + elf_shndx_t idx, + const qstring &name, + bool force_load, + ea_t *startaddr = nullptr, + asize_t *_size = nullptr); + void load_huge_segment( + reader_t &reader, + const segment_t &s, + const elf_phdr_t &p, + const char *sclass, + const char *name, + int flags); + // create a new segment where a previous segment ended (at the top). + // Allocate new selector for the new segment. If the flag use_cursel is + // set then use currently allocated segment selector and allocate a new + // one after creation. + segment_t *create_segment_at_top( + reader_t &reader, + uchar type, + const char *name, + asize_t size, + uchar align, + bool use_cursel = false); + void look_for_prgend_symbols(reader_t &reader); + // for the relocation object file calculate a start address of the + // segment where previous segment ended (at the top). For executable or + // shared objects this function returns the address from <sh>. + ea_t get_default_segment_ea(reader_t &reader, const elf_shdr_t &sh) const; + bool should_rename(ushort type, const char *name) const; + void check_for_gnuc(const char *name); + void convert_sub_table(reader_t &reader, const elf_shdr_t *pps, char lsym); + void elf_get_rebased_eas(reader_t &reader, ea_t *pimagebase, ea_t *pload_base); + void load_ids_info(void); + // get fixup for PTPOFF generic TLS reloc, + // it returns FIXUP_CUSTOM if this reloc isn't supported + fixup_type_t get_ptpoff_reltype(); + void comment_rename(ea_t ea, const char *name); + void broken_output_warning(void); + asize_t map_range_from_file( + reader_t &reader, + int64 offset, + ea_t startaddr, + ea_t endaddr, + const elf_phdr_t *pht_entry = NULL); + // FIXME this is wrong! it will be replaced by process_TLS() + // It is assumed the 'in_out_offset' is relative to the start of + // the TLS block at runtime. Since those blocks have the following layout: + // +---------------+ + // | | + // | .tdata | + // | | + // +---------------+ + // | | + // | .tbss | + // | | + // +---------------+ + // we'll associate 'in_out_offset' to either the '.tdata' segment, + // or the '.tbss' one, depending on whether it overflows + // .tdata or not. + // + // As a side-effect, note that the value pointed to by 'in_out_offset' will + // be different after this function returns, in case it lands into '.tbss'. + // (it will be: in_out_offset_after = in_out_offset - segment_size(".tdata")) + ea_t get_tls_ea_by_offset(uint32 *in_out_offset); + void relocate_rela( + reader_t &reader, + const elf_rela_t &rel, + bool is_rela, + int reloc_idx, // Current index in relocation section + slice_type_t slice_type, + uint32 info_idx, + const char *segname, + reloc_tools_t &tools); + void relocate_section_mips( + reader_t &reader, + const elf_shdr_t §ion, + const char *segname, + slice_type_t slice_type, + reloc_tools_t &tools, + bool packed, + int info_idx, + uint64 count, + size_t entsize); + void relocate_section( + elf_file_info_t &finfo, + const elf_shdr_t §ion, + const char *segname, + slice_type_t slice_type, + reloc_tools_t &tools, + bool packed); + void process_relocations( + elf_file_info_t &finfo, + const dynamic_info_t &di, + reloc_tools_t &tools); + bool use_displ_for_symbol(ea_t S, adiff_t A) + { + if ( S >= prgend ) + return true; + if ( rel_mode == 1 ) // symbol is STT_SECTION ? + { + segment_t *s = getseg(S); + return s == NULL || A < 0 || A >= s->size(); + } + return false; + } +}; + +//-------------------------------------------------------------------------- +inline int check_alignment(uint64 align) +{ + if ( align > 1 && align <= 4096 && (align & (align - 1)) == 0 ) + return int(align); + return 1; // ignore alignment +} + +ushort get_algn_value(uval_t algn); +void get_versioned_symbol_name( + qstring *out, + const char *symname, + const elf_symbol_version_t &symver, + uint16 idx); +void annotate_got0(const reader_t &reader, ea_t got0); +void annotate_loaded_notes( + const reader_t &reader, + const rangevec_t &loaded_notes); +void set_got_entry(ea_t ea, const char *name, int flags, const char *suffix = "_ptr"); + +#endif diff --git a/idasdk76/ldr/elf/elfbase.h b/idasdk76/ldr/elf/elfbase.h new file mode 100644 index 0000000..5b326eb --- /dev/null +++ b/idasdk76/ldr/elf/elfbase.h @@ -0,0 +1,1014 @@ +#ifndef __ELFBASE_H__ +#define __ELFBASE_H__ +#pragma pack(push, 4) + +//========================================================================= +struct elf_ident_t +{ + uint32 magic; +#if __MF__ +# define ELF_MAGIC 0x7F454C46 // big endian \x7FELF +#else +# define ELF_MAGIC 0x464C457F // litte endian \x7FELF +#endif + uint8 elf_class; +#define ELFCLASSNONE 0 // Invalid class +#define ELFCLASS32 1 // 32bit object +#define ELFCLASS64 2 // 64bit object + uint8 bytesex; +#define ELFDATANONE 0 // Invalid data encoding +#define ELFDATA2LSB 1 // low byte first +#define ELFDATA2MSB 2 // high byte first + uint8 version; // file version + uint8 osabi; // Operating System/ABI indication +#define ELFOSABI_NONE 0 // UNIX System V ABI +#define ELFOSABI_HPUX 1 // HP-UX operating system +#define ELFOSABI_NETBSD 2 // NetBSD +#define ELFOSABI_LINUX 3 // GNU/Linux +#define ELFOSABI_HURD 4 // GNU/Hurd +#define ELFOSABI_SOLARIS 6 // Solaris +#define ELFOSABI_AIX 7 // AIX +#define ELFOSABI_IRIX 8 // IRIX +#define ELFOSABI_FREEBSD 9 // FreeBSD +#define ELFOSABI_TRU64 10 // TRU64 UNIX +#define ELFOSABI_MODESTO 11 // Novell Modesto +#define ELFOSABI_OPENBSD 12 // OpenBSD +#define ELFOSABI_OPENVMS 13 // OpenVMS +#define ELFOSABI_NSK 14 // Hewlett-Packard Non-Stop Kernel +#define ELFOSABI_AROS 15 // Amiga Research OS +#define ELFOSABI_C6000_ELFABI 64 // Texas Instruments TMS320C6 bare-metal +#define ELFOSABI_C6000_LINUX 65 // TI TMS320C6 MMU-less Linux platform +#define ELFOSABI_ARM 97 // ARM +#define ELFOSABI_CELLOSLV2 102 // PS3 lv2 OS +#define ELFOSABI_NACL 123 // ChromeOS Native Client +#define ELFOSABI_STANDALONE 255 // Standalone (embedded) application + uint8 abiversion; // ABI version + uint8 pad[7]; + + bool is_valid() const { return magic == ELF_MAGIC; } + bool is_msb() const { return bytesex == ELFDATA2MSB; } + bool is_64() const { return elf_class == ELFCLASS64; } +}; + +struct Elf32_Ehdr +{ + elf_ident_t e_ident; + uint16 e_type; // enum ET + uint16 e_machine; // enum EM + uint32 e_version; // enum EV + uint32 e_entry; // virtual start address + uint32 e_phoff; // off to program header table's (pht) + uint32 e_shoff; // off to section header table's (sht) + uint32 e_flags; // EF_machine_flag + uint16 e_ehsize; // header's size + uint16 e_phentsize; // size of pht element + uint16 e_phnum; // entry counter in pht + uint16 e_shentsize; // size of sht element + uint16 e_shnum; // entry count in sht + uint16 e_shstrndx; // sht index in name table +}; + + +enum elf_ET +{ + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Share object file + ET_CORE = 4, // Core file + ET_LOOS = 0xfe00u, // OS specific + ET_HIOS = 0xfeffu, // OS specific + ET_LOPROC = 0xff00u, // Processor specific + ET_HIPROC = 0xffffu // Processor specific +}; + +enum elf_EM +{ + EM_NONE = 0, // No machine + EM_M32 = 1, // AT & T WE 32100 + EM_SPARC = 2, // Sparc + EM_386 = 3, // Intel 80386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, + // ATTENTION!!! in documentation present next values + // EM_860 = 6, // Intel 80860 + // EM_MIPS = 7, // MIPS RS3000 + // in linux RS3000 = 8, !!! + // taken from linux + EM_860 = 7, + EM_MIPS = 8, // Mips 3000 (officialy, big-endian only) + EM_S370 = 9, // IBM System370 + EM_MIPS_RS3_BE = 10, // MIPS R3000 Big Endian + // EM_SPARC_64 = 11, // SPARC v9 + EM_PARISC = 15, // HPPA + EM_VPP550 = 17, // Fujitsu VPP500 + EM_SPARC32PLUS = 18, // Sun's v8plus + EM_I960 = 19, // Intel 960 + EM_PPC = 20, // Power PC + EM_PPC64 = 21, // 64-bit PowerPC + EM_S390 = 22, // IBM S/390 + EM_SPU = 23, // Cell Broadband Engine Synergistic Processor Unit + EM_CISCO7200 = 25, // Cisco 7200 Series Router (MIPS) + EM_CISCO3620 = 30, // Cisco 3620/3640 Router (MIPS, IDT R4700) + EM_V800 = 36, // NEC V800 series + EM_FR20 = 37, // Fujitsu FR20 + EM_RH32 = 38, // TRW RH32 + EM_MCORE = 39, // Motorola M*Core (May also be taken by Fujitsu MMA) + EM_ARM = 40, // ARM + EM_OLD_ALPHA = 41, // Digital Alpha + EM_SH = 42, // Renesas (formerly Hitachi) / SuperH SH + EM_SPARC64 = 43, // Sparc v9 64-bit + EM_TRICORE = 44, // Siemens Tricore embedded processor + EM_ARC = 45, // ARC Cores + EM_H8300 = 46, // Renesas (formerly Hitachi) H8/300 + EM_H8300H = 47, // Renesas (formerly Hitachi) H8/300H + EM_H8S = 48, // Renesas (formerly Hitachi) H8S + EM_H8500 = 49, // Renesas (formerly Hitachi) H8/500 + EM_IA64 = 50, // Intel Itanium IA64 + EM_MIPS_X = 51, // Stanford MIPS-X + EM_COLDFIRE = 52, // Motorola Coldfire + EM_6812 = 53, // Motorola MC68HC12 + EM_MMA = 54, // Fujitsu Multimedia Accelerator + EM_PCP = 55, // Siemens PCP + EM_NCPU = 56, // Sony nCPU embedded RISC processor + EM_NDR1 = 57, // Denso NDR1 microprocesspr + EM_STARCORE = 58, // Motorola Star*Core processor + EM_ME16 = 59, // Toyota ME16 processor + EM_ST100 = 60, // STMicroelectronics ST100 processor + EM_TINYJ = 61, // Advanced Logic Corp. TinyJ embedded processor + EM_X86_64 = 62, // Advanced Micro Devices X86-64 processor + EM_PDSP = 63, // Sony DSP Processor + EM_PDP10 = 64, // DEC PDP-10 + EM_PDP11 = 65, // DEC PDP-11 + EM_FX66 = 66, // Siemens FX66 microcontroller + EM_ST9 = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller + EM_ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller + EM_68HC16 = 69, // Motorola MC68HC16 + EM_6811 = 70, // Motorola MC68HC11 + EM_68HC08 = 71, // Motorola MC68HC08 + EM_68HC05 = 72, // Motorola MC68HC05 + EM_SVX = 73, // Silicon Graphics SVx + EM_ST19 = 74, // STMicroelectronics ST19 8-bit cpu + EM_VAX = 75, // Digital VAX + EM_CRIS = 76, // Axis Communications 32-bit embedded processor + EM_JAVELIN = 77, // Infineon Technologies 32-bit embedded cpu + EM_FIREPATH = 78, // Element 14 64-bit DSP processor + EM_ZSP = 79, // LSI Logic's 16-bit DSP processor + EM_MMIX = 80, // Donald Knuth's educational 64-bit processor + EM_HUANY = 81, // Harvard's machine-independent format + EM_PRISM = 82, // SiTera Prism + EM_AVR = 83, // Atmel AVR 8-bit microcontroller + EM_FR = 84, // Fujitsu FR Family + EM_D10V = 85, // Mitsubishi D10V + EM_D30V = 86, // Mitsubishi D30V + EM_V850 = 87, // NEC v850 (GNU compiler) + + EM_NECV850E = 0x70FC, // ^ + EM_NECV850 = 0x70FF, // | + EM_NECV850E2 = 0x71EA, // | + EM_NECV850ES = 0x73CE, // | + EM_NECV850E2R1 = 0x73FD, // |This group is used by the Renesas CA850 toolchain + EM_NECV850E2R2 = 0x73FE, // | + EM_NECV850E2R3 = 0x73FF, // | + EM_NECV850E2R4 = 0x7400, // | + EM_NECV850E3V5 = 0x74FB, // v + + EM_CYGNUS_V850 = 0x9080,// V850 backend magic number. Written in the absense of an ABI. + + EM_M32R = 88, // Renesas M32R (formerly Mitsubishi M32R) + EM_MN10300 = 89, // Matsushita MN10300 + EM_MN10200 = 90, // Matsushita MN10200 + EM_PJ = 91, // picoJava + EM_OPENRISC = 92, // OpenRISC 32-bit embedded processor + EM_ARCOMPACT = 93, // ARC Cores (ARCompact ISA) + EM_XTENSA = 94, // Tensilica Xtensa Architecture + EM_VIDEOCORE = 95, // Alphamosaic VideoCore processor + EM_TMM_GPP = 96, // Thompson Multimedia General Purpose Processor + EM_NS32K = 97, // National Semiconductor 32000 series + EM_TPC = 98, // Tenor Network TPC processor + EM_SNP1K = 99, // Trebia SNP 1000 processor + EM_ST200 = 100, // STMicroelectronics ST200 microcontroller + EM_IP2K = 101, // Ubicom IP2022 micro controller + EM_MAX = 102, // MAX Processor + EM_CR = 103, // National Semiconductor CompactRISC + EM_F2MC16 = 104, // Fujitsu F2MC16 + EM_MSP430 = 105, // TI msp430 micro controller + EM_BLACKFIN = 106, // ADI Blackfin + EM_SE_C33 = 107, // S1C33 Family of Seiko Epson processors + EM_SEP = 108, // Sharp embedded microprocessor + EM_ARCA = 109, // Arca RISC Microprocessor + EM_UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University + EM_EXCESS = 111, // eXcess: 16/32/64-bit configurable embedded CPU + EM_DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor + EM_ALTERA_NIOS2 = 113, // Altera Nios II soft-core processor + EM_CRX = 114, // National Semiconductor CRX + EM_XGATE = 115, // Motorola XGATE embedded processor + EM_C166 = 116, // Infineon C16x/XC16x processor + EM_M16C = 117, // Renesas M16C series microprocessors + EM_DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal Controller + EM_CE = 119, // Freescale Communication Engine RISC core + EM_M32C = 120, // Renesas M32C series microprocessors + EM_TSK3000 = 131, // Altium TSK3000 core + EM_RS08 = 132, // Freescale RS08 embedded processor + EM_ECOG2 = 134, // Cyan Technology eCOG2 microprocessor + EM_SCORE = 135, // Sunplus Score + EM_DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor + EM_VIDEOCORE3 = 137, // Broadcom VideoCore III processor + EM_LATTICEMICO32 = 138, // RISC processor for Lattice FPGA architecture + EM_SE_C17 = 139, // Seiko Epson C17 family + EM_TI_C6000 = 140, // Texas Instruments TMS320C6000 family + EM_MMDSP_PLUS = 160, // STMicroelectronics 64bit VLIW Data Signal Processor + EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor + EM_R32C = 162, // Renesas R32C series microprocessors + EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family + EM_QDSP6 = 164, // QUALCOMM DSP6 Processor + EM_8051 = 165, // Intel 8051 and variants + EM_STXP7X = 166, // STMicroelectronics STxP7x family + EM_NDS32 = 167, // Andes Technology compact code size embedded RISC processor family + EM_ECOG1 = 168, // Cyan Technology eCOG1X family + EM_ECOG1X = 168, // Cyan Technology eCOG1X family + EM_MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers + EM_XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor + EM_MANIK = 171, // M2000 Reconfigurable RISC Microprocessor + EM_CRAYNV2 = 172, // Cray Inc. NV2 vector architecture + EM_RX = 173, // Renesas RX family + EM_METAG = 174, // Imagination Technologies META processor architecture + EM_MCST_ELBRUS = 175, // MCST Elbrus general purpose hardware architecture + EM_ECOG16 = 176, // Cyan Technology eCOG16 family + EM_CR16 = 177, // National Semiconductor CompactRISC 16-bit processor + EM_ETPU = 178, // Freescale Extended Time Processing Unit + EM_SLE9X = 179, // Infineon Technologies SLE9X core + EM_L1OM = 180, // Intel L1OM (Larrabee) + EM_K1OM = 181, // Intel K1OM + EM_INTEL182 = 182, // Reserved by Intel + EM_AARCH64 = 183, // ARM 64-bit architecture + EM_ARM184 = 184, // Reserved by ARM + EM_AVR32 = 185, // Atmel Corporation 32-bit microprocessor family + EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller + EM_TILE64 = 187, // Tilera TILE64 multicore architecture family + EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family + EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor core + EM_CUDA = 190, // NVIDIA CUDA architecture + EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family + EM_CLOUDSHIELD = 192, // CloudShield architecture family + EM_COREA_1ST = 193, // KIPO-KAIST Core-A 1st generation processor family + EM_COREA_2ND = 194, // KIPO-KAIST Core-A 2nd generation processor family + EM_ARC_COMPACT2 = 195, // Synopsys ARCompact V2 + EM_OPEN8 = 196, // Open8 8-bit RISC soft processor core + EM_RL78 = 197, // Renesas RL78 family + EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor + EM_78K0R = 199, // Renesas 78K0R family + EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller + EM_BA1 = 201, // Beyond BA1 CPU architecture + EM_BA2 = 202, // Beyond BA2 CPU architecture + EM_XCORE = 203, // XMOS xCORE processor family + EM_MCHP_PIC = 204, // Microchip 8-bit PIC(r) + /* reserved 205-209 */ + EM_KM32 = 210, // KM211 KM32 + EM_KMX32 = 211, // KM211 KMX32 + EM_EMX16 = 212, // KM211 KMX16 + EM_EMX8 = 213, // KM211 KMX8 + EM_KVARC = 214, // KM211 KVARC + EM_CDP = 215, // Paneve CDP + EM_COGE = 216, // Cognitive Smart Memory Processor + EM_COOL = 217, // Bluechip CoolEngine + EM_NORC = 218, // Nanoradio Optimized RISC + EM_CSR_KALIMBA = 219, // CSR Kalimba + EM_Z80 = 220, // Zilog Z80 + EM_VISIUM = 221, // Controls and Data Services VISIUMcore + EM_FT32 = 222, // FTDI Chip FT32 + EM_MOXIE = 223, // Moxie processor + EM_AMDGPU = 224, // AMD GPU + /* reserved 225-242 */ + EM_RISCV = 243, // RISC-V + + EM_CYGNUS_POWERPC = 0x9025, // Cygnus PowerPC ELF backend + EM_ALPHA = 0x9026, // DEC Alpha + EM_S390_OLD = 0xa390 // old S/390 backend magic number. Written in the absence of an ABI. +}; + +enum elf_EV +{ + EV_NONE = 0, // None version + EV_CURRENT = 1 // Current version + // in linux header + // EV_NUM = 2 +}; + +// special section indexes +enum elh_SHN +{ + SHN_UNDEF = 0, // undefined/missing/... + SHN_LORESERVE = 0xff00, + SHN_LOPROC = 0xff00, + SHN_HIPROC = 0xff1f, + SHN_ABS = 0xfff1, // absolute value + SHN_COMMON = 0xfff2, // common values (fortran/c) + SHN_XINDEX = 0xffff, // the escape value + SHN_HIRESERVE = 0xffff +}; +//========== + +struct Elf32_Shdr +{ + uint32 sh_name; // index in string table + uint32 sh_type; // enum SHT + uint32 sh_flags; // enum SHF + uint32 sh_addr; // address in memory (or 0) + uint32 sh_offset; // offset in file + uint32 sh_size; // section size in bytes + uint32 sh_link; // index in symbol table + uint32 sh_info; // extra information + uint32 sh_addralign; // 0 & 1 => no alignment + uint32 sh_entsize; // size symbol table or eq. +}; + + +enum elf_SHT +{ + SHT_NULL = 0, // inactive - no assoc. section + SHT_PROGBITS = 1, // internal program information + SHT_SYMTAB = 2, // symbol table (static) + SHT_STRTAB = 3, // string table + SHT_RELA = 4, // relocation entries + SHT_HASH = 5, // symbol hash table + SHT_DYNAMIC = 6, // inf. for dynamic linking + SHT_NOTE = 7, // additional info + SHT_NOBITS = 8, // no placed in file + SHT_REL = 9, // relocation entries without explicit address + SHT_SHLIB = 10, // RESERVED + SHT_DYNSYM = 11, // Dynamic Symbol Table + SHT_COMDAT = 12, // COMDAT group directory -> SHT_HP_COMDAT */ + // abi 3 + SHT_INIT_ARRAY = 14, // Array of ptrs to init functions + SHT_FINI_ARRAY = 15, // Array of ptrs to finish functions + SHT_PREINIT_ARRAY = 16, // Array of ptrs to pre-init funcs + SHT_GROUP = 17, // Section contains a section group + SHT_SYMTAB_SHNDX = 18, // Indicies for SHN_XINDEX entries + // SHT_NUM = 12, + SHT_LOOS = 0x60000000ul, + SHT_HIOS = 0x6ffffffful, + SHT_LOPROC = 0x70000000ul, + SHT_HIPROC = 0x7ffffffful, + SHT_LOUSER = 0x80000000ul, + SHT_HIUSER = 0xfffffffful, + + // From binutils-2.27/elfcpp/elfcpp.h + // The remaining values are not in the standard. + // Incremental build data. + SHT_GNU_INCREMENTAL_INPUTS = 0x6fff4700, + SHT_GNU_INCREMENTAL_SYMTAB = 0x6fff4701, + SHT_GNU_INCREMENTAL_RELOCS = 0x6fff4702, + SHT_GNU_INCREMENTAL_GOT_PLT = 0x6fff4703, + SHT_GNU_ATTRIBUTES = 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU style dynamic hash table. + SHT_GNU_LIBLIST = 0x6ffffff7, // List of prelink dependencies. + SHT_GNU_verdef = 0x6ffffffd, // Versions defined by file. + SHT_GNU_verneed = 0x6ffffffe, // Versions needed by file. + SHT_GNU_versym = 0x6fffffff, // Symbol versions. + + // http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-94076.html#OSLLGchapter6-73445 + SHT_SUNW_ancillary = 0x6fffffee, + SHT_SUNW_capchain = 0x6fffffef, + SHT_SUNW_capinfo = 0x6ffffff0, + SHT_SUNW_symsort = 0x6ffffff1, + SHT_SUNW_tlssort = 0x6ffffff2, + SHT_SUNW_LDYNSYM = 0x6ffffff3, + SHT_SUNW_dof = 0x6ffffff4, + SHT_SUNW_cap = 0x6ffffff5, + SHT_SUNW_SIGNATURE = 0x6ffffff6, + SHT_SUNW_ANNOTATE = 0x6ffffff7, + SHT_SUNW_DEBUGSTR = 0x6ffffff8, + SHT_SUNW_DEBUG = 0x6ffffff9, + SHT_SUNW_move = 0x6ffffffa, + SHT_SUNW_COMDAT = 0x6ffffffb, + SHT_SUNW_syminfo = 0x6ffffffc, + SHT_SUNW_verdef = 0x6ffffffd, + SHT_SUNW_verneed = 0x6ffffffe, + SHT_SUNW_versym = 0x6fffffff, + + // http://llvm.org/doxygen/namespacellvm_1_1ELF.html + SHT_ANDROID_REL = 0x60000001, + SHT_ANDROID_RELA = 0x60000002, +}; + +// section by index 0 == +// { 0, SHT_NULL, 0, 0, 0, 0, SHN_UNDEF, 0, 0, 0 }; + +enum elf_SHF +{ + SHF_WRITE = (1 << 0), // writable data + SHF_ALLOC = (1 << 1), // occupies memory + SHF_EXECINSTR = (1 << 2), // machine instruction + + SHF_MERGE = (1 << 4), // can be merged + SHF_STRINGS = (1 << 5), // contains nul-terminated strings + SHF_INFO_LINK = (1 << 6), // sh_info contains SHT index + SHF_LINK_ORDER = (1 << 7), // preserve order after combining + SHF_OS_NONCONFORMING = (1 << 8), // non-standard os specific handling required + SHF_GROUP = (1 << 9), // section is memory of a group + SHF_TLS = (1 << 10), // section holds thread-local data + SHF_COMPRESSED = (1 << 11), // section containing compressed data + + SHF_MASKOS = 0x0ff00000, // os specific + SHF_MASKPROC = 0xf0000000, // processor specific +}; + +enum elf_GRP +{ + GRP_COMDAT = 0x00000001, // This is a COMDAT group. + GRP_MASKOS = 0x0ff00000, // OS-specific flags + GRP_MASKPROC = 0xf0000000, // Processor-specific flags +}; + +// COMDAT selection criteria. +// (value of sh_info of a SHT_COMDAT section) +// ref: OS/2 Application Binary Interface for PowerPC (32-bit) +enum elf_COMDAT +{ + COMDAT_NONE = 0, // Invalid selection criteria. + COMDAT_NOMATCH =1, // Only one instance of a SHT_COMDAT section of the + // given name is allowed. + COMDAT_PICKANY =2, // Pick any instance of a SHT_COMDAT section of the + // given name. + COMDAT_SAMESIZE =3, // Pick any instance of a SHT_COMDAT section of the + // given name but all instances of SHT_COMDAT + // sections of the given name must have the same size. +}; + +struct Elf32_Sym +{ + uint32 st_name; // index in string table + uint32 st_value; // absolute value or addr + uint32 st_size; // 0-unknow or no, elsewere symbol size in bytes + uchar st_info; // type and attribute (thee below) + uchar st_other; // ==0 + uint16 st_shndx; // index in section header table +}; + +#define ELF_ST_BIND(i) ((i)>>4) +#define ELF_ST_TYPE(i) ((i)&0xf) +#define ELF_ST_INFO(b,t) (((b)<<4)+((t)&0xf)) +/* This macro disassembles and assembles a symbol's visibility into + the st_other field. The STV_ defines specificy the actual visibility. */ +#define ELF_ST_VISIBILITY(v) ((v) & 0x3) + +enum elf_ST_BIND +{ + STB_LOCAL = 0, + STB_GLOBAL = 1, + STB_WEAK = 2, + STB_LOOS = 10, // OS-specific + STB_GNU_UNIQUE = 10, // Symbol is unique in namespace + STB_HIOS = 12, + STB_LOPROC = 13, // processor- + STB_HIPROC = 15, // specific + STB_INVALID = 254 +}; + +enum elf_ST_TYPE +{ + STT_NOTYPE = 0, + STT_OBJECT = 1, // associated with data object + STT_FUNC = 2, // associated with function or execut. code + STT_SECTION = 3, + STT_FILE = 4, // name of source file + STT_COMMON = 5, // Uninitialized common section + STT_TLS = 6, // TLS-data object + STT_LOOS = 10, // OS- + STT_HIOS = 12, // specific + STT_LOPROC = 13, // processor- + STT_HIPROC = 15, // specific + STT_GNU_IFUNC = 10, // Symbol is an indirect code object +}; + +enum elf_ST_VISIBILITY +{ + STV_DEFAULT = 0, /* Visibility is specified by binding type */ + STV_INTERNAL = 1, /* OS specific version of STV_HIDDEN */ + STV_HIDDEN = 2, /* Can only be seen inside currect component */ + STV_PROTECTED = 3, /* Treat as STB_LOCAL inside current component */ +}; + +/* Special values for the st_other field in the symbol table. These + are used in an Irix 5 dynamic symbol table. */ +enum elf_ST_OTHER +{ + STO_DEFAULT = STV_DEFAULT, + STO_INTERNAL = STV_INTERNAL, + STO_HIDDEN = STV_HIDDEN, + STO_PROTECTED = STV_PROTECTED, +/* This bit is used on Irix to indicate a symbol whose definition + is optional - if, at final link time, it cannot be found, no + error message should be produced. */ + STO_OPTIONAL = (1 << 2), +}; + +// relocation +struct Elf32_Rel +{ + uint32 r_offset; // virtual address + uint32 r_info; // type of relocation +}; + +#define ELF32_R_SYM(i) ((i)>>8) +#define ELF32_R_TYPE(i) ((unsigned char)(i)) +#define ELF32_R_INFO(s,t) (((s)<<8)+(unsigned char)(t)) + +struct Elf32_Rela +{ + uint32 r_offset; + uint32 r_info; + int32 r_addend; // constant to compute +}; + +struct Elf32_Chdr +{ + uint32 ch_type; + uint32 ch_size; + uint32 ch_addralign; +}; + +//=================Loading & dynamic linking======================== +// program header +struct Elf32_Phdr +{ + uint32 p_type; // Segment type. see below + uint32 p_offset; // from beginning of file at 1 byte of segment resides + uint32 p_vaddr; // virtual addr of 1 byte + uint32 p_paddr; // reserved for system + uint32 p_filesz; // may be 0 + uint32 p_memsz; // my be 0 + uint32 p_flags; // for PT_LOAD access mask (PF_xxx) + uint32 p_align; // 0/1-no, +}; + +enum elf_SEGFLAGS +{ + PF_X = (1 << 0), // Segment is executable + PF_W = (1 << 1), // Segment is writable + PF_R = (1 << 2), // Segment is readable + + // PaX flags (for PT_PAX_FLAGS) + PF_PAGEEXEC = (1 << 4), // Enable PAGEEXEC + PF_NOPAGEEXEC = (1 << 5), // Disable PAGEEXEC + PF_SEGMEXEC = (1 << 6), // Enable SEGMEXEC + PF_NOSEGMEXEC = (1 << 7), // Disable SEGMEXEC + PF_MPROTECT = (1 << 8), // Enable MPROTECT + PF_NOMPROTECT = (1 << 9), // Disable MPROTECT + PF_RANDEXEC = (1 << 10), // Enable RANDEXEC + PF_NORANDEXEC = (1 << 11), // Disable RANDEXEC + PF_EMUTRAMP = (1 << 12), // Enable EMUTRAMP + PF_NOEMUTRAMP = (1 << 13), // Disable EMUTRAMP + PF_RANDMMAP = (1 << 14), // Enable RANDMMAP + PF_NORANDMMAP = (1 << 15), // Disable RANDMMAP + + PF_MASKOS = 0x0FF00000, // OS-specific reserved bits + PF_MASKPROC = 0xF0000000, // Processor-specific reserved bits +}; + +enum elf_SEGTYPE +{ + PT_NULL = 0, // ignore entries in program table + PT_LOAD = 1, // loadable segmen described in _filesz & _memsz + PT_DYNAMIC = 2, // dynamic linking information + PT_INTERP = 3, // path name to interpreter (loadable) + PT_NOTE = 4, // auxilarry information + PT_SHLIB = 5, // reserved. Has no specified semantics + PT_PHDR = 6, // location & size program header table + PT_TLS = 7, // Thread local storage segment + PT_LOOS = 0x60000000ul, // OS- + PT_HIOS = 0x6ffffffful, // specific + PT_LOPROC = 0x70000000ul, // processor- + PT_HIPROC = 0x7ffffffful, // specific + // + PT_PAX_FLAGS = (PT_LOOS + 0x5041580), // PaX flags + + // From binutils-2.27/elfcpp/elfcpp.h + // The remaining values are not in the standard. + PT_GNU_EH_FRAME = 0x6474e550, // Frame unwind information. + PT_GNU_STACK = 0x6474e551, // Stack flags. + PT_GNU_RELRO = 0x6474e552, // Read only after relocation. + + // http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-83432.html#OSLLGchapter6-69880 + PT_SUNW_UNWIND = 0x6464e550, + PT_SUNW_EH_FRAME = 0x6474e550, + PT_SUNWBSS = 0x6ffffffa, + PT_SUNWSTACK = 0x6ffffffb, + PT_SUNWDTRACE = 0x6ffffffc, + PT_SUNWCAP = 0x6ffffffd, +}; + +//=================Dynamic section=============================== +struct Elf32_Dyn +{ + int32 d_tag; // see below + union + { + uint32 d_val; // integer value with various interpretation + uint32 d_ptr; // programm virtual adress + } d_un; +}; + +enum elf_DTAG +{ + DT_NULL = 0, // (-) end ofd _DYNAMIC array + DT_NEEDED = 1, // (v) str-table offset name to needed library + DT_PLTRELSZ = 2, // (v) tot.size in bytes of relocation entries + DT_PLTGOT = 3, // (p) see below + DT_HASH = 4, // (p) addr. of symbol hash table + DT_STRTAB = 5, // (p) addr of string table + DT_SYMTAB = 6, // (p) addr of symbol table + DT_RELA = 7, // (p) addr of relocation table + DT_RELASZ = 8, // (v) size in bytes of DT_RELA table + DT_RELAENT = 9, // (v) size in bytes of DT_RELA entry + DT_STRSZ = 10, // (v) size in bytes of string table + DT_SYMENT = 11, // (v) size in byte of symbol table entry + DT_INIT = 12, // (p) addr. of initialization function + DT_FINI = 13, // (p) addr. of termination function + DT_SONAME = 14, // (v) offs in str.-table - name of shared object + DT_RPATH = 15, // (v) offs in str-table - search patch + DT_SYMBOLIC = 16, // (-) start search of shared object + DT_REL = 17, // (p) similar to DT_RELA + DT_RELSZ = 18, // (v) tot.size in bytes of DT_REL + DT_RELENT = 19, // (v) size in bytes of DT_REL entry + DT_PLTREL = 20, // (v) type of relocation (DT_REL or DT_RELA) + DT_DEBUG = 21, // (p) not specified + DT_TEXTREL = 22, // (-) segment permisson + DT_JMPREL = 23, // (p) addr of dlt procedure (if present) + DT_BIND_NOW = 24, + DT_INIT_ARRAY = 25, + DT_FINI_ARRAY = 26, + DT_INIT_ARRAYSZ = 27, + DT_FINI_ARRAYSZ = 28, + DT_RUNPATH = 29, + DT_FLAGS = 30, +#define DF_ORIGIN 0x01 +#define DF_SYMBOLIC 0x02 +#define DF_TEXTREL 0x04 +#define DF_BIND_NOW 0x08 +#define DF_STATIC_TLS 0x10 + DT_ENCODING = 31, + DT_PREINIT_ARRAY = 32, + DT_PREINIT_ARRAYSZ = 33, + DT_LOOS = 0x60000000ul, // OS-specific + DT_HIOS = 0x6ffffffful, // + + // http://docs.oracle.com/cd/E53394_01/html/E54813/chapter6-42444.html#OSLLGchapter6-tbl-52 + DT_SUNW_AUXILIARY = 0x6000000d, + DT_SUNW_RTLDINF = 0x6000000e, + DT_SUNW_FILTER = 0x6000000e, + DT_SUNW_CAP = 0x60000010, + DT_SUNW_SYMTAB = 0x60000011, + DT_SUNW_SYMSZ = 0x60000012, + DT_SUNW_ENCODING = 0x60000013, + DT_SUNW_SORTENT = 0x60000013, + DT_SUNW_SYMSORT = 0x60000014, + DT_SUNW_SYMSORTSZ = 0x60000015, + DT_SUNW_TLSSORT = 0x60000016, + DT_SUNW_TLSSORTSZ = 0x60000017, + DT_SUNW_CAPINFO = 0x60000018, + DT_SUNW_STRPAD = 0x60000019, + DT_SUNW_CAPCHAIN = 0x6000001a, + DT_SUNW_LDMACH = 0x6000001b, + DT_SUNW_CAPCHAINENT = 0x6000001d, + DT_SUNW_CAPCHAINSZ = 0x6000001f, + DT_SUNW_PARENT = 0x60000021, + DT_SUNW_ASLR = 0x60000023, + DT_SUNW_RELAX = 0x60000025, + DT_SUNW_NXHEAP = 0x60000029, + DT_SUNW_NXSTACK = 0x6000002b, + + // https://github.com/amplab/ray-core/tree/master/src/tools/relocation_packer + DT_ANDROID_REL = 0x6000000f, + DT_ANDROID_RELSZ = 0x60000010, + DT_ANDROID_RELA = 0x60000011, + DT_ANDROID_RELASZ = 0x60000012, + + // From binutils-2.27/elfcpp/elfcpp.h + // Some of the values below are also present the Oracle documentation. + // All of these types are supported both for GNU and Solaris. + DT_VALRNGLO = 0x6ffffd00ul, + DT_GNU_PRELINKED = 0x6ffffdf5ul, + DT_GNU_CONFLICTSZ = 0x6ffffdf6ul, + DT_GNU_LIBLISTSZ = 0x6ffffdf7ul, + DT_CHECKSUM = 0x6ffffdf8ul, + DT_PLTPADSZ = 0x6ffffdf9ul, + DT_MOVEENT = 0x6ffffdfaul, + DT_MOVESZ = 0x6ffffdfbul, + DT_FEATURE = 0x6ffffdfcul, +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + DT_POSFLAG_1 = 0x6ffffdfdul, +#define DF_P1_LAZYLOAD 0x00000001 +#define DF_P1_GROUPPERM 0x00000002 + DT_SYMINSZ = 0x6ffffdfeul, + DT_SYMINENT = 0x6ffffdfful, + DT_VALRNGHI = 0x6ffffdfful, + DT_ADDRRNGLO = 0x6ffffe00ul, + DT_GNU_HASH = 0x6ffffef5ul, // GNU-style hash table. + DT_TLSDESC_PLT = 0x6ffffef6ul, + DT_TLSDESC_GOT = 0x6ffffef7ul, + DT_GNU_CONFLICT = 0x6ffffef8ul, // Start of conflict section + DT_GNU_LIBLIST = 0x6ffffef9ul, + DT_CONFIG = 0x6ffffefaul, + DT_DEPAUDIT = 0x6ffffefbul, + DT_AUDIT = 0x6ffffefcul, + DT_PLTPAD = 0x6ffffefdul, + DT_MOVETAB = 0x6ffffefeul, + DT_SYMINFO = 0x6ffffefful, + DT_ADDRRNGHI = 0x6ffffefful, + DT_RELACOUNT = 0x6ffffff9ul, + DT_RELCOUNT = 0x6ffffffaul, + DT_FLAGS_1 = 0x6ffffffbul, +#define DF_1_NOW 0x00000001 +#define DF_1_GLOBAL 0x00000002 +#define DF_1_GROUP 0x00000004 +#define DF_1_NODELETE 0x00000008 +#define DF_1_LOADFLTR 0x00000010 +#define DF_1_INITFIRST 0x00000020 +#define DF_1_NOOPEN 0x00000040 +#define DF_1_ORIGIN 0x00000080 +#define DF_1_DIRECT 0x00000100 +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 +#define DF_1_NODEFLIB 0x00000800 +#define DF_1_NODUMP 0x00001000 +#define DF_1_CONFALT 0x00002000 +#define DF_1_ENDFILTEE 0x00004000 +#define DF_1_DISPRELDNE 0x00008000 +#define DF_1_DISPRELPND 0x00010000 +#define DF_1_NODIRECT 0x00020000 +#define DF_1_IGNMULDEF 0x00040000 +#define DF_1_NOKSYMS 0x00080000 +#define DF_1_NOHDR 0x00100000 +#define DF_1_EDITED 0x00200000 +#define DF_1_NORELOC 0x00400000 +#define DF_1_SYMINTPOSE 0x00800000 +#define DF_1_GLOBAUDIT 0x01000000 +#define DF_1_SINGLETON 0x02000000 +#define DF_1_STUB 0x04000000 +#define DF_1_PIE 0x08000000 +#define DF_1_KMOD 0x10000000 +#define DF_1_WEAKFILTER 0x20000000 +#define DF_1_NOCOMMON 0x40000000 + DT_VERDEF = 0x6ffffffcul, + DT_VERDEFNUM = 0x6ffffffdul, + DT_VERNEED = 0x6ffffffeul, + DT_VERNEEDNUM = 0x6ffffffful, + DT_VERSYM = 0x6ffffff0ul, + + // + DT_LOPROC = 0x70000000ul, // (?) processor- + DT_HIPROC = 0x7ffffffful, // (?) specific + + // + DT_AUXILIARY = 0x7ffffffdul, + DT_USED = 0x7ffffffeul, + DT_FILTER = 0x7ffffffful, +}; + +//---------------------------------------------------------------------- +// ELF Notes + +enum +{ + NT_GNU_ABI_TAG = 1, + NT_GNU_HWCAP = 2, + NT_GNU_BUILD_ID = 3, + NT_GNU_GOLD_VERSION = 4, + NT_GNU_PROPERTY_TYPE_0 = 5, +}; + +#define NT_PRSTATUS 1 +#define NT_FPREGSET 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_PRXFPREG 0x46e62b7f +#define NT_PPC_VMX 0x100 +#define NT_PPC_VSX 0x102 +#define NT_PPC_TAR 0x103 +#define NT_PPC_PPR 0x104 +#define NT_PPC_DSCR 0x105 +#define NT_PPC_EBB 0x106 +#define NT_PPC_PMU 0x107 +#define NT_PPC_TM_CGPR 0x108 +#define NT_PPC_TM_CFPR 0x109 +#define NT_PPC_TM_CVMX 0x10a +#define NT_PPC_TM_CVSX 0x10b +#define NT_PPC_TM_SPR 0x10c +#define NT_PPC_TM_CTAR 0x10d +#define NT_PPC_TM_CPPR 0x10e +#define NT_PPC_TM_CDSCR 0x10f +#define NT_386_TLS 0x200 +#define NT_386_IOPERM 0x201 +#define NT_X86_XSTATE 0x202 +#define NT_S390_HIGH_GPRS 0x300 +#define NT_S390_TIMER 0x301 +#define NT_S390_TODCMP 0x302 +#define NT_S390_TODPREG 0x303 +#define NT_S390_CTRS 0x304 +#define NT_S390_PREFIX 0x305 +#define NT_S390_LAST_BREAK 0x306 +#define NT_S390_SYSTEM_CALL 0x307 +#define NT_S390_TDB 0x308 +#define NT_S390_VXRS_LOW 0x309 +#define NT_S390_VXRS_HIGH 0x30a +#define NT_S390_GS_CB 0x30b +#define NT_S390_GS_BC 0x30c +#define NT_ARM_VFP 0x400 +#define NT_ARM_TLS 0x401 +#define NT_ARM_HW_BREAK 0x402 +#define NT_ARM_HW_WATCH 0x403 +#define NT_ARM_SVE 0x405 +#define NT_SIGINFO 0x53494749 +#define NT_FILE 0x46494c45 + +#define NT_PSTATUS 10 +#define NT_FPREGS 12 +#define NT_PSINFO 13 +#define NT_LWPSTATUS 16 +#define NT_LWPSINFO 17 +#define NT_WIN32PSTATUS 18 + +//===============================elf64 types============================= +struct Elf64_Ehdr +{ + elf_ident_t e_ident; + uint16 e_type; + uint16 e_machine; + uint32 e_version; + uint64 e_entry; // Entry point virtual address + uint64 e_phoff; // Program header table file offset + uint64 e_shoff; // Section header table file offset + uint32 e_flags; + uint16 e_ehsize; + uint16 e_phentsize; + uint16 e_phnum; + uint16 e_shentsize; + uint16 e_shnum; + uint16 e_shstrndx; +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Ehdr); + +struct Elf64_Shdr +{ + uint32 sh_name; // Section name, index in string tbl + uint32 sh_type; // Type of section + uint64 sh_flags; // Miscellaneous section attributes + uint64 sh_addr; // Section virtual addr at execution + uint64 sh_offset; // Section file offset + uint64 sh_size; // Size of section in bytes + uint32 sh_link; // Index of another section + uint32 sh_info; // Additional section information + uint64 sh_addralign; // Section alignment + uint64 sh_entsize; // Entry size if section holds table +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Shdr); + +// +struct Elf64_Sym +{ + uint32 st_name; // Symbol name, index in string tbl + uint8 st_info; // Type and binding attributes + uint8 st_other; // No defined meaning, 0 + uint16 st_shndx; // Associated section index + uint64 st_value; // Value of the symbol + uint64 st_size; // Associated symbol size +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Sym); + +struct Elf64_Rel +{ + uint64 r_offset; // Location at which to apply the action + uint64 r_info; // index and type of relocation +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Rel); + +struct Elf64_Rela +{ + uint64 r_offset; // Location at which to apply the action + uint64 r_info; // index and type of relocation + int64 r_addend; // Constant addend used to compute value +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Rela); + +struct Elf64_Chdr +{ + uint32 ch_type; + uint32 ch_reserved; + uint64 ch_size; + uint64 ch_addralign; +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Chdr); + + +//#define ELF64_R_SYM(i) ((i) >> 32) +//#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +//#define ELF64_R_INFO(s,t) (((bfd_vma) (s) << 32) + (bfd_vma) (t)) +#define ELF64_R_SYM(i) uint32((i) >> 32) +#define ELF64_R_TYPE(i) uint32(i) + + +struct Elf64_Phdr +{ + uint32 p_type; + uint32 p_flags; + uint64 p_offset; // Segment file offset + uint64 p_vaddr; // Segment virtual address + uint64 p_paddr; // Segment physical address + uint64 p_filesz; // Segment size in file + uint64 p_memsz; // Segment size in memory + uint64 p_align; // Segment alignment, file & memory +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Phdr); + +struct Elf64_Dyn +{ + uint64 d_tag; // entry tag value + uint64 d_un; +}; +DECLARE_TYPE_AS_MOVABLE(Elf64_Dyn); + +//======================================================================= +// Version information types + +struct Elf_Verdef +{ + uint16 vd_version; + uint16 vd_flags; + uint16 vd_ndx; + uint16 vd_cnt; + uint32 vd_hash; + uint32 vd_aux; + uint32 vd_next; +}; +DECLARE_TYPE_AS_MOVABLE(Elf_Verdef); + +// Flags for vd_flags +#define VER_FLG_BASE 0x1 +#define VER_FLG_WEAK 0x2 +#define VER_FLG_INFO 0x4 + +struct Elf_Verdaux +{ + uint32 vda_name; + uint32 vda_next; +}; +DECLARE_TYPE_AS_MOVABLE(Elf_Verdaux); + +struct Elf_Verneed +{ + uint16 vn_version; + uint16 vn_cnt; + uint32 vn_file; + uint32 vn_aux; + uint32 vn_next; +}; +DECLARE_TYPE_AS_MOVABLE(Elf_Verneed); + +struct Elf_Vernaux +{ + uint32 vna_hash; + uint16 vna_flags; + uint16 vna_other; + uint32 vna_name; + uint32 vna_next; +}; +DECLARE_TYPE_AS_MOVABLE(Elf_Vernaux); + +//======================================================================= +// Definitions for other modules + +#define ELFNODE "$ elfnode" // value: Elf64_Ehdr +#define ELF_PHT_TAG 'p' // supval(idx): Elf64_Phdr +#define ELF_SHT_TAG 's' // supval(idx): Elf64_Shdr +#define TLSNODE "$ tls" // altval(0): the TLS template address + 1 + // altval(-1): size of the TLS template + // see tlsinfo2_t::create_tls_template() +#define ATTRNODE "$ attributes" // hashval(vendorname) - nodeidx of netnode with attribute list + // in that node: + // supval(tag): string value + // altval(tag): integer value + 1 + // Tag_compatibility uses both + // Tag_also_compatible_with (for 'aeabi') stores sub-tag number in default altval + // and its value in supval('c') or altval('c') +#define ELFSEGMMAPPINGS "$ elfsegmmap" // Holds a list of mappings for segments, conceptually of the form: + // (wanted_start_ea, wanted_size, mapped_start_ea) + // Note: Only the segments whose mapped EA is *not* the EA that the + // binary file advertises for that segment will be present in + // this netnode, not all segments. + // This netnode should be iterated on using altfirst/altnext. + // + // idx: wanted_start_ea + // altval(idx): mapped_start_ea + // altval(idx, 's'): wanted_size + +#define ATTR_VENDOR_EABI "aeabi" +#define ATTR_VENDOR_GNU "gnu" +#define ATTR_VENDOR_ARM "ARM" + +#pragma pack(pop) +#endif // __ELFBASE_H__ diff --git a/idasdk76/ldr/elf/elfr_arm.h b/idasdk76/ldr/elf/elfr_arm.h new file mode 100644 index 0000000..dd9c25a --- /dev/null +++ b/idasdk76/ldr/elf/elfr_arm.h @@ -0,0 +1,542 @@ +#ifndef __ELFR_ARM_H__ +#define __ELFR_ARM_H__ + +#ifndef __ELFBASE_H__ +#include "elfbase.h" +#endif + +// relocation field - word32 with HIGH BYTE FIRST!!! +// A- from Elf32_Rela +// B- Loading address of shared object (REAL section when symbol defined) +// (not) G- offset into global objet table +// (not) GOT- adress of global object table +// (not) L- linkage table entry +// P- place of storage unit (computed using r_offset) +// S- value of symbol +enum elf_RTYPE_arm +{ + + R_ARM_NONE = 0, // No reloc + R_ARM_PC24 = 1, // S-P+A (relative 26 bit branch) + R_ARM_ABS32 = 2, // S+A + R_ARM_REL32 = 3, // S-P+A + R_ARM_LDR_PC_G0 = 4, // S-P+A + R_ARM_ABS16 = 5, // S+A + R_ARM_ABS12 = 6, // S+A + R_ARM_THM_ABS5 = 7, // S+A + R_ARM_ABS8 = 8, // S+A + R_ARM_SBREL32 = 9, // S-B+A + R_ARM_THM_CALL = 10, // S-P+A + R_ARM_THM_PC8 = 11, // S-P+A + R_ARM_BREL_ADJ = 12, // S-B+A + R_ARM_TLS_DESC = 13, // + R_ARM_THM_SWI8 = 14, // S+A (obsolete) + R_ARM_XPC25 = 15, // S-P+A (obsolete) + R_ARM_THM_XPC22 = 16, // S-P+A (obsolete) + R_ARM_TLS_DTPMOD32 = 17, /* ID of module containing symbol */ + R_ARM_TLS_DTPOFF32 = 18, /* Offset in TLS block */ + R_ARM_TLS_TPOFF32 = 19, /* Offset in static TLS block */ +// linux-specific + R_ARM_COPY = 20, // none (copy symbol at runtime) + R_ARM_GLOB_DAT = 21, // S (create .got entry) + R_ARM_JUMP_SLOT = 22, // S (create .plt entry) + R_ARM_RELATIVE = 23, // B+A (adjust by programm base) + R_ARM_GOTOFF32 = 24, // S+A-GOT (32bit offset to .got) + R_ARM_BASE_PREL = 25, // B+A-P + R_ARM_GOT_BREL = 26, // G+A-GOT (32bit .got entry) + R_ARM_PLT32 = 27, // L+A-P (32bit .plt entry) + + R_ARM_CALL = 28, + R_ARM_JUMP24 = 29, + R_ARM_THM_JUMP24 = 30, // ((S + A) | T) - P + R_ARM_BASE_ABS = 31, // B + A + R_ARM_ALU_PCREL7_0 = 32, + R_ARM_ALU_PCREL15_8 = 33, + R_ARM_ALU_PCREL23_15 = 34, + R_ARM_LDR_SBREL_11_0 = 35, + R_ARM_ALU_SBREL_19_12 = 36, + R_ARM_ALU_SBREL_27_20 = 37, + R_ARM_TARGET1 = 38, + R_ARM_ROSEGREL32 = 39, + R_ARM_V4BX = 40, + R_ARM_TARGET2 = 41, + R_ARM_PREL31 = 42, + R_ARM_MOVW_ABS_NC = 43, // Static ARM (S + A) | T + R_ARM_MOVT_ABS = 44, // Static ARM S + A + R_ARM_MOVW_PREL_NC = 45, // Static ARM ((S + A) | T) - P + R_ARM_MOVT_PREL = 46, // Static ARM S + A - P + R_ARM_THM_MOVW_ABS_NC = 47, // Static Thumb32 (S + A) | T + R_ARM_THM_MOVT_ABS = 48, // Static Thumb32 S + A + R_ARM_THM_MOVW_PREL_NC= 49, // Static Thumb32 ((S + A) | T) - P + R_ARM_THM_MOVT_PREL = 50, // Static Thumb32 S + A - P + R_ARM_THM_JUMP19 = 51, // Static Thumb32 ((S + A) | T) - P + R_ARM_THM_JUMP6 = 52, // Static Thumb16 S + A - P + R_ARM_THM_ALU_PREL_11_0= 53, // Static Thumb32 ((S + A) | T) - Pa + R_ARM_THM_PC12 = 54, // Static Thumb32 S + A - Pa + R_ARM_ABS32_NOI = 55, // Static Data S + A + R_ARM_REL32_NOI = 56, // Static Data S + A - P + R_ARM_ALU_PC_G0_NC = 57, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G0 = 58, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G1_NC = 59, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G1 = 60, // Static ARM ((S + A) | T) - P + R_ARM_ALU_PC_G2 = 61, // Static ARM ((S + A) | T) - P + R_ARM_LDR_PC_G1 = 62, // Static ARM S + A - P + R_ARM_LDR_PC_G2 = 63, // Static ARM S + A - P + R_ARM_LDRS_PC_G0 = 64, // Static ARM S + A - P + + R_ARM_LDRS_PC_G1 = 65, // Static ARM S + A - P + R_ARM_LDRS_PC_G2 = 66, // Static ARM S + A - P + R_ARM_LDC_PC_G0 = 67, // Static ARM S + A - P + R_ARM_LDC_PC_G1 = 68, // Static ARM S + A - P + R_ARM_LDC_PC_G2 = 69, // Static ARM S + A - P + R_ARM_ALU_SB_G0_NC = 70, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G0 = 71, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G1_NC = 72, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G1 = 73, // Static ARM ((S + A) | T) - B(S) + R_ARM_ALU_SB_G2 = 74, // Static ARM ((S + A) | T) - B(S) + R_ARM_LDR_SB_G0 = 75, // Static ARM S + A - B(S) + R_ARM_LDR_SB_G1 = 76, // Static ARM S + A - B(S) + R_ARM_LDR_SB_G2 = 77, // Static ARM S + A - B(S) + R_ARM_LDRS_SB_G0 = 78, // Static ARM S + A - B(S) + R_ARM_LDRS_SB_G1 = 79, // Static ARM S + A - B(S) + R_ARM_LDRS_SB_G2 = 80, // Static ARM S + A - B(S) + R_ARM_LDC_SB_G0 = 81, // Static ARM S + A - B(S) + R_ARM_LDC_SB_G1 = 82, // Static ARM S + A - B(S) + R_ARM_LDC_SB_G2 = 83, // Static ARM S + A - B(S) + R_ARM_MOVW_BREL_NC = 84, // Static ARM ((S + A) | T) - B(S) + R_ARM_MOVT_BREL = 85, // Static ARM S + A - B(S) + R_ARM_MOVW_BREL = 86, // Static ARM ((S + A) | T) - B(S) + R_ARM_THM_MOVW_BREL_NC = 87, // Static Thumb32 ((S + A) | T) - B(S) + R_ARM_THM_MOVT_BREL = 88, // Static Thumb32 S + A - B(S) + R_ARM_THM_MOVW_BREL = 89, // Static Thumb32 ((S + A) | T) - B(S) + R_ARM_TLS_GOTDESC = 90, // Static Data + R_ARM_TLS_CALL = 91, // Static ARM + R_ARM_TLS_DESCSEQ = 92, // Static ARM TLS relaxation + R_ARM_THM_TLS_CALL = 93, // Static Thumb32 + R_ARM_PLT32_ABS = 94, // Static Data PLT(S) + A + + R_ARM_GOT_ABS = 95, // G+A + R_ARM_GOT_PREL = 96, // G+A-P + R_ARM_GOT_BREL12 = 97, // G+A-GOT + R_ARM_GOTOFF12 = 98, // S+A-GOT + R_ARM_GOTRELAX = 99, + R_ARM_GNU_VTENTRY = 100, + R_ARM_GNU_VTINHERIT = 101, + + R_ARM_THM_PC11 = 102, /* Cygnus extension to abi: Thumb unconditional branch. */ + R_ARM_THM_PC9 = 103, /* Cygnus extension to abi: Thumb conditional branch. */ + R_ARM_THM_JUMP11 = 102, // Static Thumb16 S + A - P + R_ARM_THM_JUMP8 = 103, // Static Thumb16 S + A - P + R_ARM_TLS_GD32 = 104, // Static Data GOT(S) + A - P + R_ARM_TLS_LDM32 = 105, // Static Data GOT(S) + A - P + R_ARM_TLS_LDO32 = 106, // Static Data S + A - TLS + R_ARM_TLS_IE32 = 107, // Static Data GOT(S) + A - P + R_ARM_TLS_LE32 = 108, // Static Data S + A - tp + R_ARM_TLS_LDO12 = 109, // Static ARM S + A - TLS + R_ARM_TLS_LE12 = 110, // Static ARM S + A - tp + R_ARM_TLS_IE12GP = 111, // Static ARM GOT(S) + A - GOT_ORG + R_ARM_PRIVATE_0 = 112, // Private (n = 0, 1, ... 15) + R_ARM_PRIVATE_1 = 113, + R_ARM_PRIVATE_2 = 114, + R_ARM_PRIVATE_3 = 115, + R_ARM_PRIVATE_4 = 116, + R_ARM_PRIVATE_5 = 117, + R_ARM_PRIVATE_6 = 118, + R_ARM_PRIVATE_7 = 119, + R_ARM_PRIVATE_8 = 120, + R_ARM_PRIVATE_9 = 121, + R_ARM_PRIVATE_10 = 122, + R_ARM_PRIVATE_11 = 123, + R_ARM_PRIVATE_12 = 124, + R_ARM_PRIVATE_13 = 125, + R_ARM_PRIVATE_14 = 126, + R_ARM_PRIVATE_15 = 127, + R_ARM_ME_TOO = 128, // Obsolete + R_ARM_THM_TLS_DESCSEQ16 = 129,// Static Thumb16 + R_ARM_THM_TLS_DESCSEQ32 = 130,// Static Thumb32 + R_ARM_THM_GOT_BREL12 = 131, // GOT entry relative to GOT origin, 12 bit (Thumb32 LDR). + R_ARM_THM_ALU_ABS_G0_NC = 132, + R_ARM_THM_ALU_ABS_G1_NC = 133, + R_ARM_THM_ALU_ABS_G2_NC = 134, + R_ARM_THM_ALU_ABS_G3_NC = 135, + + // 136 - 139 Unallocated + // 140 - 159 Dynamic Reserved for future allocation + + R_ARM_IRELATIVE = 160, + + // 161 - 255 Unallocated + +// +// ATT: R_ARM_RXPC25 used ONLY in OLD_ABI (+ 15 OTHER relocs!) +// dynamic sections only + R_ARM_RXPC25 = 249, // (BLX) call between segments +// + R_ARM_RSBREL32 = 250, // (Word) SBrelative offset + R_ARM_THM_RPC22 = 251, // (Thumb BL/BLX) call between segments + R_ARM_RREL32 = 252, // (Word) inter-segment offset + R_ARM_RABS32 = 253, // (Word) Target segment displacement + R_ARM_RPC24 = 254, // (BL/BLX) call between segment + R_ARM_RBASE = 255 // segment being relocated +}; + +// X is the result of a relocation operation, before any masking or bit-selection +// Page(expr) is the page address of the expression expr, defined as (expr & ~0xFFF) +// GOT is the address of the Global Offset Table +// GDAT(S+A) represents a 64-bit entry in the GOT for address S+A +// G(expr) is the address of the GOT entry for the expression expr +// Delta(S) if S is a normal symbol, resolves to the difference between +// the static link address of S and the execution address of S. +// If S is the null symbol (ELF symbol index 0), resolves to the difference +// between the static link address of P and the execution address of P. +// Indirect(expr) represents the result of calling expr as a function. +// The result is the return value from the function that is returned in r0. +// [msb:lsb] is a bit-mask operation representing the selection of bits in a value +enum elf_RTYPE_aarch64 +{ + R_AARCH64_NONE = 0x100, + + // ILP32 relocations + R_AARCH64_P32_ABS32 = 1,/* Direct 32 bit. */ + R_AARCH64_P32_COPY = 180,/* Copy symbol at runtime. */ + R_AARCH64_P32_GLOB_DAT = 181,/* Create GOT entry. */ + R_AARCH64_P32_JUMP_SLOT = 182,/* Create PLT entry. */ + R_AARCH64_P32_RELATIVE = 183,/* Adjust by program base. */ + R_AARCH64_P32_TLS_DTPMOD = 184,/* Module number, 32 bit. */ + R_AARCH64_P32_TLS_DTPREL = 185,/* Module-relative offset, 32 bit. */ + R_AARCH64_P32_TLS_TPREL = 186,/* TP-relative offset, 32 bit. */ + R_AARCH64_P32_TLSDESC = 187,/* TLS Descriptor. */ + R_AARCH64_P32_IRELATIVE = 188,/* STT_GNU_IFUNC relocation. */ + + // 4.6.5 Static Data relocations + R_AARCH64_ABS64 = 0x101, // S + A + R_AARCH64_ABS32 = 0x102, // S + A + R_AARCH64_ABS16 = 0x103, + R_AARCH64_PREL64 = 0x104, + R_AARCH64_PREL32 = 0x105, + R_AARCH64_PREL16 = 0x106, + + // 4.6.6 Static AArch64 relocations + R_AARCH64_MOVW_UABS_G0 = 0x107, + R_AARCH64_MOVW_UABS_G0_NC = 0x108, + R_AARCH64_MOVW_UABS_G1 = 0x109, + R_AARCH64_MOVW_UABS_G1_NC = 0x10a, + R_AARCH64_MOVW_UABS_G2 = 0x10b, + R_AARCH64_MOVW_UABS_G2_NC = 0x10c, + R_AARCH64_MOVW_UABS_G3 = 0x10d, + R_AARCH64_MOVW_SABS_G0 = 0x10e, + R_AARCH64_MOVW_SABS_G1 = 0x10f, + R_AARCH64_MOVW_SABS_G2 = 0x110, + + R_AARCH64_LD_PREL_LO19 = 0x111, + R_AARCH64_ADR_PREL_LO21 = 0x112, + R_AARCH64_ADR_PREL_PG_HI21 = 0x113, // Page(S+A) - Page(P); Set an ADRP immediate value to bits [32:12] of the X + R_AARCH64_ADR_PREL_PG_HI21_NC = 0x114, + R_AARCH64_ADD_ABS_LO12_NC = 0x115, // S+A; Set an ADD immediate value to bits [11:0] of X + R_AARCH64_LDST8_ABS_LO12_NC = 0x116, + + R_AARCH64_TSTBR14 = 0x117, + R_AARCH64_CONDBR19 = 0x118, + R_AARCH64_JUMP26 = 0x11a, // S+A-P; Set a B immediate field to bits [27:2] of X + R_AARCH64_CALL26 = 0x11b, // S+A-P; Set a CALL immediate field to bits [27:2] of X + + R_AARCH64_LDST16_ABS_LO12_NC = 0x11c, + R_AARCH64_LDST32_ABS_LO12_NC = 0x11d, + R_AARCH64_LDST64_ABS_LO12_NC = 0x11e, // S+A; Set the LD/ST immediate value to bits [11:3] of X + + R_AARCH64_MOVW_PREL_G0 = 0x11f, + R_AARCH64_MOVW_PREL_G0_NC = 0x120, + R_AARCH64_MOVW_PREL_G1 = 0x121, + R_AARCH64_MOVW_PREL_G1_NC = 0x122, + R_AARCH64_MOVW_PREL_G2 = 0x123, + R_AARCH64_MOVW_PREL_G2_NC = 0x124, + R_AARCH64_MOVW_PREL_G3 = 0x125, + + R_AARCH64_LDST128_ABS_LO12_NC = 0x12b, + + R_AARCH64_MOVW_GOTOFF_G0 = 0x12c, + R_AARCH64_MOVW_GOTOFF_G0_NC = 0x12d, + R_AARCH64_MOVW_GOTOFF_G1 = 0x12e, + R_AARCH64_MOVW_GOTOFF_G1_NC = 0x12f, + R_AARCH64_MOVW_GOTOFF_G2 = 0x130, + R_AARCH64_MOVW_GOTOFF_G2_NC = 0x131, + R_AARCH64_MOVW_GOTOFF_G3 = 0x132, + + R_AARCH64_GOTREL64 = 0x133, + R_AARCH64_GOTREL32 = 0x134, + + R_AARCH64_GOT_LD_PREL19 = 0x135, + R_AARCH64_LD64_GOTOFF_LO15 = 0x136, + R_AARCH64_ADR_GOT_PAGE = 0x137, // Page(G(GDAT(S+A)))-Page(P); Set the immediate value of an ADRP to bits [32:12] of X + R_AARCH64_LD64_GOT_LO12_NC = 0x138, // G(GDAT(S+A)); Set the LD/ST immediate field to bits [11:3] of X + R_AARCH64_LD64_GOTPAGE_LO15 = 0x139, + + R_AARCH64_TLSGD_ADR_PREL21 = 0x200, + R_AARCH64_TLSGD_ADR_PAGE21 = 0x201, + R_AARCH64_TLSGD_ADD_LO12_NC = 0x202, + R_AARCH64_TLSGD_MOVW_G1 = 0x203, + R_AARCH64_TLSGD_MOVW_G0_NC = 0x204, + + R_AARCH64_TLSLD_ADR_PREL21 = 0x205, + R_AARCH64_TLSLD_ADR_PAGE21 = 0x206, + R_AARCH64_TLSLD_ADD_LO12_NC = 0x207, + R_AARCH64_TLSLD_MOVW_G1 = 0x208, + R_AARCH64_TLSLD_MOVW_G0_NC = 0x209, + R_AARCH64_TLSLD_LD_PREL19 = 0x20a, + R_AARCH64_TLSLD_MOVW_DTPREL_G2 = 0x20b, + R_AARCH64_TLSLD_MOVW_DTPREL_G1 = 0x20c, + R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC = 0x20d, + R_AARCH64_TLSLD_MOVW_DTPREL_G0 = 0x20e, + R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC = 0x20f, + R_AARCH64_TLSLD_ADD_DTPREL_HI12 = 0x210, + R_AARCH64_TLSLD_ADD_DTPREL_LO12 = 0x211, + R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC = 0x212, + R_AARCH64_TLSLD_LDST8_DTPREL_LO12 = 0x213, + R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC = 0x214, + R_AARCH64_TLSLD_LDST16_DTPREL_LO12 = 0x215, + R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC = 0x216, + R_AARCH64_TLSLD_LDST32_DTPREL_LO12 = 0x217, + R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC = 0x218, + R_AARCH64_TLSLD_LDST64_DTPREL_LO12 = 0x219, + R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC = 0x21a, + + R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 = 0x21b, + R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC = 0x21c, + R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 = 0x21d, + R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC = 0x21e, + R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 = 0x21f, + + R_AARCH64_TLSLE_MOVW_TPREL_G2 = 0x220, + R_AARCH64_TLSLE_MOVW_TPREL_G1 = 0x221, + R_AARCH64_TLSLE_MOVW_TPREL_G1_NC = 0x222, + R_AARCH64_TLSLE_MOVW_TPREL_G0 = 0x223, + R_AARCH64_TLSLE_MOVW_TPREL_G0_NC = 0x224, + R_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x225, + R_AARCH64_TLSLE_ADD_TPREL_LO12 = 0x226, + R_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x227, + R_AARCH64_TLSLE_LDST8_TPREL_LO12 = 0x228, + R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC = 0x229, + R_AARCH64_TLSLE_LDST16_TPREL_LO12 = 0x22a, + R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC = 0x22b, + R_AARCH64_TLSLE_LDST32_TPREL_LO12 = 0x22c, + R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC = 0x22d, + R_AARCH64_TLSLE_LDST64_TPREL_LO12 = 0x22e, + R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC = 0x22f, + + R_AARCH64_TLSDESC_LD_PREL19 = 0x230, + R_AARCH64_TLSDESC_ADR_PREL21 = 0x231, + R_AARCH64_TLSDESC_ADR_PAGE21 = 0x232, // R_AARCH64_TLSDESC_ADR_PAGE + R_AARCH64_TLSDESC_LD64_LO12 = 0x233, // R_AARCH64_TLSDESC_LD64_LO12_NC + R_AARCH64_TLSDESC_ADD_LO12 = 0x234, // R_AARCH64_TLSDESC_ADD_LO12_NC + R_AARCH64_TLSDESC_OFF_G1 = 0x235, + R_AARCH64_TLSDESC_OFF_G0_NC = 0x236, + R_AARCH64_TLSDESC_LDR = 0x237, + R_AARCH64_TLSDESC_ADD = 0x238, + R_AARCH64_TLSDESC_CALL = 0x239, + + R_AARCH64_TLSLE_LDST128_TPREL_LO12 = 0x23a, + R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC = 0x23b, + + R_AARCH64_TLSLD_LDST128_DTPREL_Lo12 = 0x23c, + R_AARCH64_TLSLD_LDST128_DTPREL_Lo12_NC= 0x23d, + + // 4.6.11 Dynamic relocations + R_AARCH64_COPY = 0x400, + R_AARCH64_GLOB_DAT = 0x401, + R_AARCH64_JUMP_SLOT = 0x402, + R_AARCH64_RELATIVE = 0x403, + R_AARCH64_TLS_DTPREL64 = 0x404, + R_AARCH64_TLS_DTPMOD64 = 0x405, + R_AARCH64_TLS_TPREL64 = 0x406, + R_AARCH64_TLSDESC = 0x407, + R_AARCH64_IRELATIVE = 0x408, +}; + +// Flags: +#define EF_ARM_RELEXEC 0x00000001 // dynamic only how to relocation +#define EF_ARM_HASENTRY 0x00000002 // e_entry is real start address + +// GNU flags (EABI version = 0) +#define EF_ARM_INTERWORK 0x00000004 // interworking enabled +#define EF_ARM_APCS_26 0x00000008 // APCS-26 used (otherwise APCS-32) +#define EF_ARM_APCS_FLOAT 0x00000010 // floats passed in float registers +#define EF_ARM_PIC 0x00000020 // Position-independent code +#define EF_ARM_ALIGN8 0x00000040 // 8-bit struct alignment +#define EF_ARM_NEW_ABI 0x00000080 // New ABI +#define EF_ARM_OLD_ABI 0x00000100 // Old ABI +#define EF_ARM_SOFT_FLOAT 0x00000200 // software FP +#define EF_ARM_VFP_FLOAT 0x00000400 // VFP float format +#define EF_ARM_MAVERICK_FLOAT 0x00000800 // Maverick float format + +// ARM flags: +#define EF_ARM_SYMSARESORTED 0x00000004 // Each subsection of the symbol table is sorted by symbol value (NB conflicts with EF_INTERWORK) +#define EF_ARM_DYNSYMSUSESEGIDX 0x00000008 // Symbols in dynamic symbol tables that are defined in sections + // included in program segment n have st_shndx = n + 1. (NB conflicts with EF_APCS26) +#define EF_ARM_MAPSYMSFIRST 0x00000010 // Mapping symbols precede other local symbols in the symbol + // table (NB conflicts with EF_APCS_FLOAT) +#define EF_ARM_LE8 0x00400000 // LE-8 code +#define EF_ARM_BE8 0x00800000 // BE-8 code for ARMv6 or later +#define EF_ARM_EABIMASK 0xFF000000 // ARM EABI version + +/* Additional symbol types for Thumb. */ +#define STT_ARM_TFUNC STT_LOPROC /* A Thumb function. */ +#define STT_ARM_16BIT STT_HIPROC /* A Thumb label. */ + +// patching GOT loading, +// discard auxiliary values in plt/got +// can present offset bypass segment +#define ELF_RPL_ARM_DEFAULT (ELF_RPL_GL | ELF_DIS_OFFW | ELF_DIS_GPLT) + +enum elf_SHT_ARM +{ + SHT_ARM_EXIDX = 0x70000001, // Exception Index table + SHT_ARM_PREEMPTMAP = 0x70000002, // BPABI DLL dynamic linking pre-emption map + SHT_ARM_ATTRIBUTES = 0x70000003, // Object file compatibility attributes + SHT_ARM_DEBUGOVERLAY = 0x70000004, // + SHT_ARM_OVERLAYSECTION = 0x70000005, // +}; + +enum elf_PT_ARM +{ + // From binutils-2.27/elfcpp/elfcpp.h + PT_ARM_ARCHEXT = 0x70000000, // Platform architecture compatibility information + PT_ARM_EXIDX = 0x70000001, // Exception unwind tables +}; + +enum elf_PT_AARCH64 +{ + // From binutils-2.27/elfcpp/elfcpp.h + PT_AARCH64_ARCHEXT = 0x70000000, // Platform architecture compatibility information + PT_AARCH64_UNWIND = 0x70000001, // Exception unwind tables +}; + +enum eabi_tags_t +{ + Tag_NULL, + Tag_File, // (=1) <uint32: byte-size> <attribute>* + Tag_Section, // (=2) <uint32: byte-size> <section number>* 0 <attribute>* + Tag_Symbol, // (=3) <unit32: byte-size> <symbol number>* 0 <attribute>* + Tag_CPU_raw_name, // (=4), NTBS + Tag_CPU_name, // (=5), NTBS + Tag_CPU_arch, // (=6), uleb128 + Tag_CPU_arch_profile, // (=7), uleb128 + Tag_ARM_ISA_use, // (=8), uleb128 + Tag_THUMB_ISA_use, // (=9), uleb128 + Tag_FP_arch, // (=10), uleb128 (formerly Tag_VFP_arch = 10) + Tag_VFP_arch = Tag_FP_arch, + Tag_WMMX_arch, // (=11), uleb128 + Tag_NEON_arch, // (=12), uleb128 + Tag_PCS_config, // (=13), uleb128 + Tag_ABI_PCS_R9_use, // (=14), uleb128 + Tag_ABI_PCS_RW_data, // (=15), uleb128 + Tag_ABI_PCS_RO_data, // (=16), uleb128 + Tag_ABI_PCS_GOT_use, // (=17), uleb128 + Tag_ABI_PCS_wchar_t, // (=18), uleb128 + Tag_ABI_FP_rounding, // (=19), uleb128 + Tag_ABI_FP_denormal, // (=20), uleb128 + Tag_ABI_FP_exceptions, // (=21), uleb128 + Tag_ABI_FP_user_exceptions, // (=22), uleb128 + Tag_ABI_FP_number_model, // (=23), uleb128 + Tag_ABI_align_needed, // (=24), uleb128 + Tag_ABI_align8_needed = Tag_ABI_align_needed, + Tag_ABI_align_preserved, // (=25), uleb128 + Tag_ABI_align8_preserved = Tag_ABI_align_preserved, + Tag_ABI_enum_size, // (=26), uleb128 + Tag_ABI_HardFP_use, // (=27), uleb128 + Tag_ABI_VFP_args, // (=28), uleb128 + Tag_ABI_WMMX_args, // (=29), uleb128 + Tag_ABI_optimization_goals, // (=30), uleb128 + Tag_ABI_FP_optimization_goals, // (=31), uleb128 + Tag_compatibility, // (=32), uleb128: flag, NTBS: vendor-name + Tag_CPU_unaligned_access=34, // (=34), uleb128 + Tag_FP_HP_extension=36, // (=36), uleb128 (formerly Tag_VFP_HP_extension = 36) + Tag_VFP_HP_extension = Tag_FP_HP_extension, + Tag_ABI_FP_16bit_format=38, // (=38), uleb128 + Tag_MPextension_use=42, // (=42), uleb128 + Tag_DIV_use=44, // (=44), uleb128 + Tag_nodefaults=64, // (=64), uleb128: ignored (write as 0) + Tag_also_compatible_with, // (=65), NTBS: data; ULEB128-encoded tag followed by a value of that tag. + Tag_T2EE_use, // (=66), uleb128 + Tag_conformance, // (=67), string: ABI-version + Tag_Virtualization_use, // (=68), uleb128 + Tag_MPextension_use_legacy=70, // (=70), +}; + +//---------------------------------------------------------------------------- +class arm_arch_specific_t : public arch_specific_t +{ +public: + enum isa_t + { + isa_arm = 1, + isa_thumb + }; + typedef void isa_handler_t( + reader_t &reader, + sym_rel &symbol, + isa_t isa, + bool force); +private: + typedef std::map<uint64, isa_t> section_isa_ranges_t; + typedef std::map<elf_shndx_t, section_isa_ranges_t> isa_ranges_t; + + isa_ranges_t isa_ranges; + std::set<ea_t> forced_isas; + + isa_handler_t *isa_handler = nullptr; + ea_t debug_segbase = 0; + bool has_mapsym = false; + bool track_mapsym = false; + bool be8_code = false; + + void notify_isa(reader_t &reader, sym_rel &symbol, isa_t isa, bool force) + { + if ( isa_handler != NULL ) + isa_handler(reader, symbol, isa, force); + } + + isa_t get_isa(const sym_rel &symbol) const; + void set_isa(const sym_rel &symbol, isa_t isa); + + friend void arm_isa_handler( + reader_t &reader, + sym_rel &symbol, + arm_arch_specific_t::isa_t isa, + bool force); + +public: + virtual ~arm_arch_specific_t() {} + virtual void on_start_symbols(reader_t &reader) override; + virtual void on_symbol_read(reader_t &reader, sym_rel &sym) override; + bool is_mapping_symbol(const char *name) const; + bool has_mapping_symbols() const { return has_mapsym; } + + // Tracking mapping symbols can be useful for + // determining whether a certain function is using + // the Thumb or ARM ISA. + // In some ELF files, the only way to know what ISA + // certain functions are in is by looking at some + // mapping symbols (i.e., '$a', '$t'). + // By default, tracking of such symbols in an + // instance of this class is _not_ enabled. + void set_mapping_symbols_tracking(bool track) { track_mapsym = track; } + bool is_mapping_symbols_tracking() const { return track_mapsym; } + + void set_isa_handler(isa_handler_t *ih, ea_t dea) + { + isa_handler = ih; + debug_segbase = dea; + } + + void set_be8(bool be8) { be8_code = be8; } + bool is_be8() { return be8_code; } +}; + +//---------------------------------------------------------------------------- +// Specific flags that will be set on sym_rel instances. +enum arm_sym_rel_flags +{ + thumb_function = 1 +}; + +#endif diff --git a/idasdk76/ldr/elf/elfr_avr.h b/idasdk76/ldr/elf/elfr_avr.h new file mode 100644 index 0000000..8e8ae8c --- /dev/null +++ b/idasdk76/ldr/elf/elfr_avr.h @@ -0,0 +1,87 @@ +#ifndef __ELFR_AVR_H__ +#define __ELFR_AVR_H__ + +#ifndef __ELFBASE_H__ +#include "elfbase.h" +#endif + +enum elf_RTYPE_avr +{ + R_AVR_NONE = 0, + R_AVR_32 = 1, + R_AVR_7_PCREL = 2, + R_AVR_13_PCREL = 3, + R_AVR_16 = 4, + R_AVR_16PM = 5, + R_AVR_LO8_LDI = 6, + R_AVR_HI8_LDI = 7, + R_AVR_HH8_LDI = 8, + R_AVR_LO8_LDI_NEG = 9, + R_AVR_HI8_LDI_NEG = 10, + R_AVR_HH8_LDI_NEG = 11, + R_AVR_LO8_LDI_PM = 12, + R_AVR_HI8_LDI_PM = 13, + R_AVR_HH8_LDI_PM = 14, + R_AVR_LO8_LDI_PM_NEG = 15, + R_AVR_HI8_LDI_PM_NEG = 16, + R_AVR_HH8_LDI_PM_NEG = 17, + R_AVR_CALL = 18, + // *nix obj's specific + R_AVR_LDI = 19, + R_AVR_6 = 20, + R_AVR_6_ADIW = 21, + R_AVR_MS8_LDI = 22, + R_AVR_MS8_LDI_NEG = 23, + R_AVR_LO8_LDI_GS = 24, + R_AVR_HI8_LDI_GS = 25, + R_AVR_8 = 26, + R_AVR_8_LO8 = 27, + R_AVR_8_HI8 = 28, + R_AVR_8_HLO8 = 29, + R_AVR_DIFF8 = 30, + R_AVR_DIFF16 = 31, + R_AVR_DIFF32 = 32, + R_AVR_LDS_STS_16 = 33, + R_AVR_PORT6 = 34, + R_AVR_PORT5 = 35, + R_AVR_32_PCREL = 36, +}; + +// Flags: +// If bit #7 is set, it is assumed that the elf file uses local symbols +// as reference for the relocations so that linker relaxation is possible. +#define EF_AVR_LINKRELAX_PREPARED 0x80 + +// Processor specific flags for the ELF header e_flags field. +#define EF_AVR_MACH 0x7F +#define E_AVR_MACH_AVR1 1 +#define E_AVR_MACH_AVR2 2 +#define E_AVR_MACH_AVR25 25 +#define E_AVR_MACH_AVR3 3 +#define E_AVR_MACH_AVR31 31 +#define E_AVR_MACH_AVR35 35 +#define E_AVR_MACH_AVR4 4 +#define E_AVR_MACH_AVR5 5 +#define E_AVR_MACH_AVR51 51 +#define E_AVR_MACH_AVR6 6 +#define E_AVR_MACH_TINY 100 +#define E_AVR_MACH_XMEGA1 101 +#define E_AVR_MACH_XMEGA2 102 +#define E_AVR_MACH_XMEGA3 103 +#define E_AVR_MACH_XMEGA4 104 +#define E_AVR_MACH_XMEGA5 105 +#define E_AVR_MACH_XMEGA6 106 +#define E_AVR_MACH_XMEGA7 107 + +// netnode flag's and constant +#define AVR_INFO_NODENAME "$ atmel" +#define ELF_AVR_TAG 'f' +#define ELF_AVR_LDI_NEG 1 +#define ELF_AVR_RAM_OFF 2 +#define ELF_AVR_EEP_OFF 3 +#define ELF_AVR_ABS_OFF 4 +#define ELF_AVR_RAMBASE 0x800000 +#define ELF_AVR_EEPROMBASE 0x810000 +#define ELF_AVR_ABSBASE 0x1000000 + +#endif diff --git a/idasdk75/ldr/elf/elfr_ia64.h b/idasdk76/ldr/elf/elfr_ia64.h similarity index 100% rename from idasdk75/ldr/elf/elfr_ia64.h rename to idasdk76/ldr/elf/elfr_ia64.h diff --git a/idasdk76/ldr/elf/elfr_mips.h b/idasdk76/ldr/elf/elfr_mips.h new file mode 100644 index 0000000..7093db1 --- /dev/null +++ b/idasdk76/ldr/elf/elfr_mips.h @@ -0,0 +1,476 @@ +#ifndef __ELFR_MIP_H__ +#define __ELFR_MIP_H__ + +#ifndef __ELFBASE_H__ +#include "elfbase.h" +#endif + +#include "elf.h" + +// +// e_flags +// + +#define EF_MIPS_NOREORDER 0x00000001 // At least one .noreorder directive appears in the source. +#define EF_MIPS_PIC 0x00000002 // File contains position independent code. +#define EF_MIPS_CPIC 0x00000004 // Code in file uses the standard calling sequence for calling osition independent code. +#define EF_MIPS_UGEN_ALLOC 0x00000008 +#define EF_MIPS_UCODE 0x00000010 // Code in file uses UCODE (obsolete) +#define EF_MIPS_ABI2 0x00000020 // Code in file uses new ABI (-n32 on Irix 6). +#define EF_MIPS_DYNAMIC 0x00000040 // MIPS dynamic +#define EF_MIPS_OPTIONS_FIRST 0x00000080 +#define EF_MIPS_32BITMODE 0x00000100 // Indicates code compiled for a 64-bit machine in 32-bit mode. (regs are 32-bits wide.) +#define EF_MIPS_FP64 0x00000200 // 32-bit machine but FP registers are 64-bit (gcc -mfp64) +#define EF_MIPS_NAN2008 0x00000400 // Uses IEE 754-2008 NaN encoding +#define EF_MIPS_ARCH 0xF0000000 // Four bit MIPS architecture field. +#define E_MIPS_ARCH_1 0x00000000 // -mips1 code. +#define E_MIPS_ARCH_2 0x10000000 // -mips2 code. +#define E_MIPS_ARCH_3 0x20000000 // -mips3 code. +#define E_MIPS_ARCH_4 0x30000000 // -mips4 code. +#define E_MIPS_ARCH_5 0x40000000 // -mips5 code. +#define E_MIPS_ARCH_32 0x50000000 // -mips32 code. +#define E_MIPS_ARCH_64 0x60000000 // -mips64 code. +#define E_MIPS_ARCH_32R2 0x70000000 // -mips32r2 +#define E_MIPS_ARCH_64R2 0x80000000 // -mips64r2 +#define E_MIPS_ARCH_32R6 0x90000000 // -mips32r6 +#define E_MIPS_ARCH_64R6 0xA0000000 // -mips64r6 +#define EF_MIPS_ABI 0x0000F000 // The ABI of the file. Also see EF_MIPS_ABI2 above. +#define E_MIPS_ABI_O32 0x00001000 // The original o32 abi. +#define E_MIPS_ABI_O64 0x00002000 // O32 extended to work on 64 bit architectures +#define E_MIPS_ABI_EABI32 0x00003000 // EABI in 32 bit mode +#define E_MIPS_ABI_EABI64 0x00004000 // EABI in 64 bit mode +#define EF_MIPS_ARCH_ASE 0x0F000000 // Architectural Extensions used by this file +#define EF_MIPS_ARCH_ASE_MDMX 0x08000000 // Use MDMX multimedia extensions +#define EF_MIPS_ARCH_ASE_M16 0x04000000 // Use MIPS-16 ISA extensions +#define EF_MIPS_ARCH_ASE_MICROMIPS 0x02000000 // Use microMIPS ISA extensions + +/* Machine variant if we know it. This field was invented at Cygnus, + but it is hoped that other vendors will adopt it. If some standard + is developed, this code should be changed to follow it. */ + +#define EF_MIPS_MACH 0x00FF0000 + +/* Cygnus is choosing values between 80 and 9F; + 00 - 7F should be left for a future standard; + the rest are open. */ + +#define E_MIPS_MACH_3900 0x00810000 // R3900/Toshiba TX39 +#define E_MIPS_MACH_4010 0x00820000 // +#define E_MIPS_MACH_4100 0x00830000 +#define E_MIPS_MACH_4650 0x00850000 +#define E_MIPS_MACH_4120 0x00870000 +#define E_MIPS_MACH_4111 0x00880000 +#define E_MIPS_MACH_MIPS32_4K 0x00890000 +#define E_MIPS_MACH_SB1 0x008A0000 // SiByte SB-1 +#define E_MIPS_MACH_OCTEON 0x008B0000 // Cavium Networks OCTEON +#define E_MIPS_MACH_XLR 0x008C0000 // RMI XLR +#define E_MIPS_MACH_OCTEON2 0x008D0000 // Cavium Networks OCTEON 2 +#define E_MIPS_MACH_OCTEON3 0x008E0000 // Cavium Networks OCTEON 3 +#define E_MIPS_MACH_5400 0x00910000 +#define E_MIPS_MACH_5900 0x00920000 // r5900 (Sony Playstation 2 Emotion Engine) +#define E_MIPS_MACH_5500 0x00980000 +#define E_MIPS_MACH_9000 0x00990000 +#define E_MIPS_MACH_LS2E 0x00A00000 // Loongson/Godson 2E +#define E_MIPS_MACH_LS2F 0x00A10000 // Loongson/Godson 2F +#define E_MIPS_MACH_ALLEGREX 0x00A20000 // Allegrex (Sony PlayStation Portable) +#define E_MIPS_MACH_LS3A 0x00A20000 // Loongson/Godson 3A + +// +// p_flags +// + +#define PF_MIPS_LOCAL 0x10000000 // special p_flags + +// relocation field - word32 with HIGH BYTE FIRST!!! +// A- from Elf32_Rela +// B- Loading address of shared object +// G- offset into global objet table +// GOT- adress of global object table +// L- linkage table entry +// P- plase of storage unit (computed using r_offset) +// S- value of symbol +enum elf_RTYPE_mips +{ + R_MIPS_NONE = 0, // No reloc + R_MIPS_16 = 1, + R_MIPS_32 = 2, // S+A-P Direct32 + R_MIPS_REL = 3, // S+A Relative32 + R_MIPS_26 = 4, // S+A Relative26 + R_MIPS_HI16 = 5, + R_MIPS_LO16 = 6, + R_MIPS_GPREL = 7, // S+A Relative16 + R_MIPS_LITERAL = 8, + R_MIPS_GOT = 9, + R_MIPS_PC16 = 10, + R_MIPS_CALL = 11, // Call16 + R_MIPS_GPREL32 = 12, + + R_MIPS_SHIFT5 = 16, + R_MIPS_SHIFT6 = 17, + R_MIPS_64 = 18, + R_MIPS_GOT_DISP = 19, + R_MIPS_GOT_PAGE = 20, + R_MIPS_GOT_OFST = 21, + R_MIPS_GOT_HI16 = 22, + R_MIPS_GOT_LO16 = 23, + R_MIPS_SUB = 24, + R_MIPS_INSERT_A = 25, + R_MIPS_INSERT_B = 26, + R_MIPS_DELETE = 27, + R_MIPS_HIGHER = 28, + R_MIPS_HIGHEST = 29, + R_MIPS_CALL_HI16 = 30, + R_MIPS_CALL_LO16 = 31, + R_MIPS_SCN_DISP = 32, + R_MIPS_REL16 = 33, + R_MIPS_ADD_IMMEDIATE = 34, + R_MIPS_PJUMP = 35, + R_MIPS_RELGOT = 36, + R_MIPS_JALR = 37, + R_MIPS_TLS_DTPMOD32 = 38, + R_MIPS_TLS_DTPREL32 = 39, + R_MIPS_TLS_DTPMOD64 = 40, + R_MIPS_TLS_DTPREL64 = 41, + R_MIPS_TLS_GD = 42, + R_MIPS_TLS_LDM = 43, + R_MIPS_TLS_DTPREL_HI16 = 44, + R_MIPS_TLS_DTPREL_LO16 = 45, + R_MIPS_TLS_GOTTPREL = 46, + R_MIPS_TLS_TPREL32 = 47, + R_MIPS_TLS_TPREL64 = 48, + R_MIPS_TLS_TPREL_HI16 = 49, + R_MIPS_TLS_TPREL_LO16 = 50, + + R_MIPS_GLOB_DAT = 51, + R_MIPS_PC21_S2 = 60, + R_MIPS_PC26_S2 = 61, + R_MIPS_PC18_S3 = 62, + R_MIPS_PC19_S2 = 63, + R_MIPS_PCHI16 = 64, + R_MIPS_PCLO16 = 65, + + R_MIPS16_26 = 100, + R_MIPS16_GPREL = 101, + R_MIPS16_GOT16 = 102, + R_MIPS16_CALL16 = 103, + R_MIPS16_HI16 = 104, + R_MIPS16_LO16 = 105, + + R_MIPS16_TLS_GD = 106, + R_MIPS16_TLS_LDM = 107, + R_MIPS16_TLS_DTPREL_HI16= 108, + R_MIPS16_TLS_DTPREL_LO16= 109, + R_MIPS16_TLS_GOTTPREL = 110, + R_MIPS16_TLS_TPREL_HI16 = 111, + R_MIPS16_TLS_TPREL_LO16 = 112, + R_MIPS16_PC16_S1 = 113, + + // For these two: + // http://sourceware.org/ml/binutils/2008-07/txt00000.txt + R_MIPS_COPY = 126, + R_MIPS_JUMP_SLOT = 127, + + // from binutils/include/elf/mips.h + R_MICROMIPS_26_S1 = 133, + R_MICROMIPS_HI16 = 134, + R_MICROMIPS_LO16 = 135, + R_MICROMIPS_GPREL16 = 136, + R_MICROMIPS_LITERAL = 137, + R_MICROMIPS_GOT16 = 138, + R_MICROMIPS_PC7_S1 = 139, + R_MICROMIPS_PC10_S1 = 140, + R_MICROMIPS_PC16_S1 = 141, + R_MICROMIPS_CALL16 = 142, + R_MICROMIPS_GOT_DISP = 145, + R_MICROMIPS_GOT_PAGE = 146, + R_MICROMIPS_GOT_OFST = 147, + R_MICROMIPS_GOT_HI16 = 148, + R_MICROMIPS_GOT_LO16 = 149, + R_MICROMIPS_SUB = 150, + R_MICROMIPS_HIGHER = 151, + R_MICROMIPS_HIGHEST = 152, + R_MICROMIPS_CALL_HI16 = 153, + R_MICROMIPS_CALL_LO16 = 154, + R_MICROMIPS_SCN_DISP = 155, + R_MICROMIPS_JALR = 156, + R_MICROMIPS_HI0_LO16 = 157, + /* TLS relocations. */ + R_MICROMIPS_TLS_GD = 162, + R_MICROMIPS_TLS_LDM = 163, + R_MICROMIPS_TLS_DTPREL_HI16 = 164, + R_MICROMIPS_TLS_DTPREL_LO16 = 165, + R_MICROMIPS_TLS_GOTTPREL = 166, + R_MICROMIPS_TLS_TPREL_HI16 = 169, + R_MICROMIPS_TLS_TPREL_LO16 = 170, + /* microMIPS GP- and PC-relative relocations. */ + R_MICROMIPS_GPREL7_S2 = 172, + R_MICROMIPS_PC23_S2 = 173, + + R_MIPS_PC32 = 248, + R_MIPS_EH = 249, + R_MIPS_GNU_REL16_S2 = 250, + R_MIPS_GNU_VTINHERIT = 253, + R_MIPS_GNU_VTENTRY = 254, + + // artificial types for the complex 32bit relocs + R_MIPS_GPDISP_LO16 = 200, + R_MIPS_GPDISP_HI16 = 201, + R_MICROMIPS_GPDISP_HI16 = 202, + R_MICROMIPS_GPDISP_LO16 = 203, +}; + +enum elf_ET_MIPS +{ + ET_IRX = 0xFF80u, // IRX file for PS2's IOP + ET_PSPEXEC = 0xFFA0u // Sony PSP executable file +}; + +enum elf_PHT_MIPS +{ + PT_MIPS_IOPMOD = 0x70000080, // Sony PS2 IOP module extension + PT_MIPS_EEMOD = 0x70000090, // Sony PS2 EE module extension + PT_MIPS_PSPREL = 0x700000A0, // Sony PRX relocations (ELF-style) + PT_MIPS_PSPREL2 = 0x700000A1, // Sony PRX relocations (packed) + + // From binutils-2.27/elfcpp/elfcpp.h + PT_MIPS_REGINFO = 0x70000000, // Register usage information. Identifies one .reginfo section. + PT_MIPS_RTPROC = 0x70000001, // Runtime procedure table. + PT_MIPS_OPTIONS = 0x70000002, // .MIPS.options section. + PT_MIPS_ABIFLAGS = 0x70000003, // .MIPS.abiflags section. +}; + +enum elf_DTAG_MIPS +{ + DT_MIPS_RLD_VERSION = 0x70000001, /* 32 bit version number for runtime linker interface. */ + DT_MIPS_TIME_STAMP = 0x70000002, /* Time stamp. */ + DT_MIPS_ICHECKSUM = 0x70000003, /* Checksum of external strings and common sizes. */ + DT_MIPS_IVERSION = 0x70000004, /* Index of version string in string table. */ + DT_MIPS_FLAGS = 0x70000005, /* 32 bits of flags. */ + DT_MIPS_BASE_ADDRESS = 0x70000006, /* Base address of the segment. */ + DT_MIPS_MSYM = 0x70000007, /* adress of the msym table */ + DT_MIPS_CONFLICT = 0x70000008, /* Address of .conflict section. */ + DT_MIPS_LIBLIST = 0x70000009, /* Address of .liblist section. */ + DT_MIPS_LOCAL_GOTNO = 0x7000000a, /* Number of local global offset table entries. */ + DT_MIPS_CONFLICTNO = 0x7000000b, /* Number of entries in the .conflict section. */ + DT_MIPS_LIBLISTNO = 0x70000010, /* Number of entries in the .liblist section. */ + DT_MIPS_SYMTABNO = 0x70000011, /* Number of entries in the .dynsym section. */ + DT_MIPS_UNREFEXTNO = 0x70000012, /* Index of first external dynamic symbol not referenced locally. */ + DT_MIPS_GOTSYM = 0x70000013, /* Index of first dynamic symbol in global offset table. */ + DT_MIPS_HIPAGENO = 0x70000014, /* Number of page table entries in global offset table. */ + DT_MIPS_RLD_MAP = 0x70000016, /* Address of run time loader map, used for debugging. */ + DT_MIPS_DELTA_CLASS = 0x70000017, /* Delta C++ class definition. */ + DT_MIPS_DELTA_CLASS_NO = 0x70000018, /* Number of entries in DT_MIPS_DELTA_CLASS. */ + DT_MIPS_DELTA_INSTANCE = 0x70000019, /* Delta C++ class instances. */ + DT_MIPS_DELTA_INSTANCE_NO = 0x7000001a, /* Number of entries in DT_MIPS_DELTA_INSTANCE. */ + DT_MIPS_DELTA_RELOC = 0x7000001b, /* Delta relocations. */ + DT_MIPS_DELTA_RELOC_NO = 0x7000001c, /* Number of entries in DT_MIPS_DELTA_RELOC. */ + DT_MIPS_DELTA_SYM = 0x7000001d, /* Delta symbols that Delta relocations refer to. */ + DT_MIPS_DELTA_SYM_NO = 0x7000001e, /* Number of entries in DT_MIPS_DELTA_SYM. */ + DT_MIPS_DELTA_CLASSSYM = 0x70000020, /* Delta symbols that hold class declarations. */ + DT_MIPS_DELTA_CLASSSYM_NO = 0x70000021, /* Number of entries in DT_MIPS_DELTA_CLASSSYM. */ + DT_MIPS_CXX_FLAGS = 0x70000022, /* Flags indicating information about C++ flavor. */ + DT_MIPS_PIXIE_INIT = 0x70000023, /* Pixie information (???). */ + DT_MIPS_SYMBOL_LIB = 0x70000024, /* Address of .MIPS.symlib */ + DT_MIPS_LOCALPAGE_GOTIDX = 0x70000025, /* The GOT index of the first PTE for a segment */ + DT_MIPS_LOCAL_GOTIDX = 0x70000026, /* The GOT index of the first PTE for a local symbol */ + DT_MIPS_HIDDEN_GOTIDX = 0x70000027, /* The GOT index of the first PTE for a hidden symbol */ + DT_MIPS_PROTECTED_GOTIDX = 0x70000028, /* The GOT index of the first PTE for a protected symbol */ + DT_MIPS_OPTIONS = 0x70000029, /* Address of `.MIPS.options'. */ + DT_MIPS_INTERFACE = 0x7000002a, /* Address of `.interface'. */ + DT_MIPS_DYNSTR_ALIGN = 0x7000002b, /* ??? */ + DT_MIPS_INTERFACE_SIZE = 0x7000002c, /* Size of the .interface section. */ + DT_MIPS_RLD_TEXT_RESOLVE_ADDR= 0x7000002d, /* Size of rld_text_resolve function stored in the GOT. */ + DT_MIPS_PERF_SUFFIX = 0x7000002e, /* Default suffix of DSO to be added by rld on dlopen() calls. */ + DT_MIPS_COMPACT_SIZE = 0x7000002f, /* Size of compact relocation section (O32). */ + DT_MIPS_GP_VALUE = 0x70000030, /* GP value for auxiliary GOTs. */ + DT_MIPS_AUX_DYNAMIC = 0x70000031, /* Address of auxiliary .dynamic. */ + DT_MIPS_PLTGOT = 0x70000032, /* Address of the base of the PLTGOT */ + DT_MIPS_RWPLT = 0x70000034, /* Points to the base of a writable PLT. */ +}; + +enum elf_SHN_MIPS +{ + SHN_MIPS_ACOMMON = 0xff00, // Defined and allocated common symbol. Value is virtual address. + SHN_MIPS_TEXT = 0xff01, // Defined and allocated text symbol. Value is virtual address. + SHN_MIPS_DATA = 0xff02, // Defined and allocated data symbol. Value is virtual address. + SHN_MIPS_SCOMMON = 0xff03, // Small common symbol. + SHN_MIPS_SUNDEFINED = 0xff04 // Small undefined symbol. +}; + +enum elf_SHF_MIPS +{ + SHF_MIPS_GPREL = 0x10000000, // Section must be part of global data area. + SHF_MIPS_MERGE = 0x20000000, // Section data should be merged to eliminate duplication + SHF_MIPS_ADDR = 0x40000000, // Section data is addresses by default. Address size to be inferred from section entry size. + SHF_MIPS_STRING = 0x80000000, // Section data is string data by default + SHF_MIPS_NOSTRIP = 0x08000000, // Section data may not be stripped + SHF_MIPS_LOCAL = 0x04000000, // Section data local to process + SHF_MIPS_NAMES = 0x02000000, // Linker must generate implicit hidden weak names + SHF_MIPS_NODUPE = 0x01000000, // Section contains text/data which may be replicated in other sections. Linker must retain only one copy. +}; + +enum elf_SHT_MIPS +{ + SHT_MIPS_LIBLIST = 0x70000000, // contains the set of dynamic shared objects used when statically linking. + SHT_MIPS_MSYM = 0x70000001, // unknown Irix5 usage + SHT_MIPS_CONFLICT = 0x70000002, // list of confliction symbols + SHT_MIPS_GPTAB = 0x70000003, // Section contains the global pointer table. + SHT_MIPS_UCODE = 0x70000004, // microcode information + SHT_MIPS_DEBUG = 0x70000005, // start of debugging information + SHT_MIPS_REGINFO = 0x70000006, // Section contains register usage information. + SHT_MIPS_RELD = 0x70000009, // Dynamic relocation? + SHT_MIPS_IFACE = 0x7000000B, // Subprogram interface information + SHT_MIPS_CONTENT = 0x7000000C, // Section content classification + SHT_MIPS_OPTIONS = 0x7000000D, // General options + SHT_MIPS_DELTASYM = 0x7000001B, // Delta C++: symbol table + SHT_MIPS_DELTAINST = 0x7000001C, // Delta C++: instance table + SHT_MIPS_DELTACLASS = 0x7000001D, // Delta C++: class table + SHT_MIPS_DWARF = 0x7000001E, // DWARF debugging section. + SHT_MIPS_DELTADECL = 0x7000001F, // Delta C++: declarations + SHT_MIPS_SYMBOL_LIB = 0x70000020, // unknown Irix6 usage + SHT_MIPS_EVENTS = 0x70000021, // Events section. + SHT_MIPS_TRANSLATE = 0x70000022, // ??? + SHT_MIPS_PIXIE = 0x70000023, // Special pixie sections + SHT_MIPS_XLATE = 0x70000024, // Address translation table + SHT_MIPS_XLATE_DEBUG = 0x70000025, // SGI internal address translation table + SHT_MIPS_WHIRL = 0x70000026, // Intermediate code + SHT_MIPS_EH_REGION = 0x70000027, // C++ exception handling region info + SHT_MIPS_XLATE_OLD = 0x70000028, // Obsolete + SHT_MIPS_PDR_EXCEPTION = 0x70000029, // Runtime procedure descriptor table exception information (ucode) + SHT_MIPS_IOPMOD = 0x70000080, // .ipmod section for PS2 IRXs + SHT_MIPS_PSPREL = 0x700000A0, // PSP executable relocation section + // VU overlay table (PS2?) + SHT_DVP_OVERLAY_TABLE = 0x7FFFF420, + SHT_DVP_OVERLAY = 0x7FFFF421, +}; + +// Special values for the st_other field in the symbol table. +enum elf_STO_MIPS +{ + // Two topmost bits denote the MIPS ISA for .text symbols: + // + 00 -- standard MIPS code, + // + 10 -- microMIPS code, + // + 11 -- MIPS16 code; requires the following two bits to be set too. + // Note that one of the MIPS16 bits overlaps with STO_MIPS_PIC. + STO_MIPS_ISA = 0xc0, + + // The MIPS psABI was updated in 2008 with support for PLTs and copy + // relocs. There are therefore two types of nonzero SHN_UNDEF functions: + // PLT entries and traditional MIPS lazy binding stubs. We mark the former + // with STO_MIPS_PLT to distinguish them from the latter. + STO_MIPS_PLT = 0x8, + + // This value is used to mark PIC functions in an object that mixes + // PIC and non-PIC. Note that this bit overlaps with STO_MIPS16, + // although MIPS16 symbols are never considered to be MIPS_PIC. + STO_MIPS_PIC = 0x20, + + // This value is used for a mips16 .text symbol. + STO_MIPS16 = 0xf0, + + // This value is used for a microMIPS .text symbol. To distinguish from + // STO_MIPS16, we set top two bits to be 10 to denote STO_MICROMIPS. The + // mask is STO_MIPS_ISA. + STO_MICROMIPS = 0x80 +}; + +// .MIPS.options descriptor kinds +enum elf_ODK_MIPS +{ + ODK_NULL = 0, // Undefined + ODK_REGINFO = 1, // Register usage information + ODK_EXCEPTIONS = 2, // Exception processing options + ODK_PAD = 3, // Section padding options + ODK_HWPATCH = 4, // Hardware patches applied + ODK_FILL = 5, // Linker fill value + ODK_TAGS = 6, // Space for tool identification + ODK_HWAND = 7, // Hardware AND patches applied + ODK_HWOR = 8, // Hardware OR patches applied + ODK_GP_GROUP = 9, // GP group to use for text/data sections + ODK_IDENT = 10, // ID information + ODK_PAGESIZE = 11, // Page size information +}; + +// PSP-specific encoding of r_info field +// segment in which the relocation resides +// i.e. relocation is at pht[ofs_base].p_vaddr + r_offset +#define ELF32_R_OFS_BASE(i) (((i)>>8) & 0xFF) +// segment number with the target +// i.e. the final address should be adjusted with pht[ofs_base].p_vaddr +#define ELF32_R_ADDR_BASE(i) (((i)>>16) & 0xFF) + + +// MIPS ELF 64 relocation info access macros. +// they assume BE byte order of the packed r_type field +#define ELF64_MIPS_R_SSYM(i) (((i) >> 24) & 0xff) +#define ELF64_MIPS_R_TYPE3(i) (((i) >> 16) & 0xff) +#define ELF64_MIPS_R_TYPE2(i) (((i) >> 8) & 0xff) +#define ELF64_MIPS_R_TYPE(i) ((i) & 0xff) + +// Values found in the r_ssym field of a relocation entry. +// No relocation. +#define RSS_UNDEF 0 +// Value of GP. +#define RSS_GP 1 +// Value of GP in object being relocated. +#define RSS_GP0 2 +// Address of location being relocated. +#define RSS_LOC 3 + +// MIPS .msym table entry +struct Elf32_Msym +{ + uint32 ms_hash_value; // Contains the hash value computed from the name of the corresponding dynamic symbol + uint32 ms_info; // Contains both the dynamic relocation index and the symbol flags field. +}; + +#define ELF32_MS_REL_INDEX(i) ((i) >> 8) +#define ELF32_MS_FLAGS(i) ((i) & 0xff) +#define ELF32_MS_INFO(r,f) (((r) << 8) + ((f) & 0xff)) + +// MIPS .liblist entry +typedef struct +{ + uint32 l_name; // Records the name of a shared library dependency. + // The value is a string table index. This name can be a + // full pathname, relative pathname, or file name. + uint32 l_time_stamp;// Records the time stamp of a shared library dependency. + uint32 l_checksum; // Records the checksum of a shared library dependency. + uint32 l_version; // Records the interface version of a shared library dependency. + // The value is a string table index. + uint32 l_flags; +} Elf64_Lib; + +// bits for l_flags: +#define LL_NONE 0 +#define LL_EXACT_MATCH 0x1 // Requires that the run-time dynamic shared library file match + // exactly the shared library file used at static link time. +#define LL_IGNORE_INT_VER 0x2 // Ignores any version incompatibility between the dynamic + // shared library file and the shared library file used at link time. +#define LL_REQUIRE_MINOR 0x4 // Marks shared library dependencies that should be loaded with + // a suffix appended to the name. The DT_SO_SUFFIX entry in + // the .dynamic section records the name of this suffix. This is + // used by object instrumentation tools to distinguish + // instrumented shared libraries. +#define LL_EXPORTS 0x8 // Marks entries for shared libraries that are not loaded as direct + // dependencies of an object. +#define LL_DELAY_LOAD 0x10 +#define LL_DELTA 0x20 + +//.reginfo section +struct Elf32_RegInfo +{ + uint32 ri_gprmask; + uint32 ri_cprmask[4]; + uint32 ri_gp_value; +}; + +void set_mips_compact_encoding(ea_t ea, bool enable); +void relocate_psp_section(Elf64_Shdr *rsh, linput_t *li); +inline bool is_psp_file(const reader_t &reader) +{ + return reader.get_header().e_machine == EM_MIPS + && reader.get_header().e_type == ET_PSPEXEC; +} + +#endif diff --git a/idasdk76/ldr/elf/elfr_ppc.h b/idasdk76/ldr/elf/elfr_ppc.h new file mode 100644 index 0000000..d4d50fe --- /dev/null +++ b/idasdk76/ldr/elf/elfr_ppc.h @@ -0,0 +1,383 @@ +#ifndef __ELFR_PPC_H__ +#define __ELFR_PPC_H__ + +#ifndef __ELFBASE_H__ +#include "elfbase.h" +#endif + +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag */ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib flag */ + +// PowerPC 64 ABI version +#define EF_PPC64_ABI_MASK 3 // original function descriptor using ABI +#define EF_PPC64_UNK_ABI 0 // unspecified or not using any features + // affected by the differences +#define EF_PPC64_AIX_ABI 1 // original function descriptor using ABI +#define EF_PPC64_V2_ABI 2 // revised ABI without function descriptors + +enum elf_ET_PPC +{ + ET_PS3PRX = 0xFFA4, // Sony PS3 PRX +}; + +enum elf_SHT_PPC +{ + SHT_PS3PRX_RELA = 0x700000A4, // Sony PS3 PRX relocations +}; + +enum elf_PHT_PPC +{ + PHT_PS3PRX_RELA = 0x700000A4, // Sony PS3 PRX relocations +}; + +enum elf_DT_PPC +{ + DT_PPC_GOT = (DT_LOPROC + 0x0), // address of _GLOBAL_OFFSET_TABLE_ +}; + +// relocation field - word32 with HIGH BYTE FIRST!!! +// A- from Elf32_Rela +// B- Loading address of shared object +// G- offset into global objet table +// GOT- adress of global object table +// L- linkage table entry +// P- plase of storage unit (computed using r_offset) +// S- value of symbol +enum elf_RTYPE_ppc +{ + R_PPC_NONE = 0, // No reloc + R_PPC_ADDR32 = 1, // S+A-P Direct 32 bit + R_PPC_ADDR24 = 2, + R_PPC_ADDR16 = 3, + R_PPC_ADDR16_LO = 4, + R_PPC_ADDR16_HI = 5, + R_PPC_ADDR16_HA = 6, + R_PPC_ADDR14 = 7, + R_PPC_ADDR14_BRTAKEN = 8, + R_PPC_ADDR14_BRNTAKEN = 9, + R_PPC_REL24 = 10, // S+A relative 24 bit + R_PPC_REL14 = 11, + R_PPC_REL14_BRTAKEN = 12, + R_PPC_REL14_BRNTAKEN = 13, + R_PPC_GOT16 = 14, + R_PPC_GOT16_LO = 15, + R_PPC_GOT16_HI = 16, + R_PPC_GOT16_HA = 17, + R_PPC_PLTREL24 = 18, + R_PPC_COPY = 19, + R_PPC_GLOB_DAT = 20, + R_PPC_JMP_SLOT = 21, + R_PPC_RELATIVE = 22, + R_PPC_LOCAL24PC = 23, + R_PPC_UADDR32 = 24, + R_PPC_UADDR16 = 25, + R_PPC_REL32 = 26, + R_PPC_PLT32 = 27, + R_PPC_PLTREL32 = 28, + R_PPC_PLT16_LO = 29, + R_PPC_PLT16_HI = 30, + R_PPC_PLT16_HA = 31, + R_PPC_SDAREL16 = 32, + R_PPC_SECTOFF = 33, + R_PPC_SECTOFF_LO = 34, + R_PPC_SECTOFF_HI = 35, + R_PPC_SECTOFF_HA = 36, + R_PPC_ADDR30 = 37, // word30 (S + A - P) >> 2 + + + // some undocumented relocs used by freescale + // some seem to be the same as official VLE relocs below + // NB! they conflict with some PPC64 relocations + R_PPC_FVLE_REL8 = 38, // same as R_PPC_VLE_REL8? + R_PPC_FVLE_REL15 = 39, // same as R_PPC_VLE_REL15? + R_PPC_FVLE_REL24 = 40, // same as R_PPC_VLE_REL24? + R_PPC_FVLE_ADDR8 = 44, // ?? + R_PPC_FVLE_ADDR4 = 45, // ?? + R_PPC_FVLE_SDA = 47, // same as R_PPC_VLE_SDA21? + R_PPC_FVLE_LO16A = 49, // same as R_PPC_VLE_LO16A? + R_PPC_FVLE_HI16A = 50, // same as R_PPC_VLE_HI16A? + R_PPC_FVLE_HA16A = 51, // same as R_PPC_VLE_HA16A? + R_PPC_FVLE_LO16D = 56, // same as R_PPC_VLE_LO16D? + R_PPC_FVLE_HI16D = 57, // same as R_PPC_VLE_HI16D? + R_PPC_FVLE_HA16D = 58, // same as R_PPC_VLE_HA16D? + + /* Relocs added to support TLS. */ + R_PPC_TLS = 67, + R_PPC_DTPMOD32 = 68, + R_PPC_TPREL16 = 69, + R_PPC_TPREL16_LO = 70, + R_PPC_TPREL16_HI = 71, + R_PPC_TPREL16_HA = 72, + R_PPC_TPREL32 = 73, + R_PPC_DTPREL16 = 74, + R_PPC_DTPREL16_LO = 75, + R_PPC_DTPREL16_HI = 76, + R_PPC_DTPREL16_HA = 77, + R_PPC_DTPREL32 = 78, + R_PPC_GOT_TLSGD16 = 79, + R_PPC_GOT_TLSGD16_LO = 80, + R_PPC_GOT_TLSGD16_HI = 81, + R_PPC_GOT_TLSGD16_HA = 82, + R_PPC_GOT_TLSLD16 = 83, + R_PPC_GOT_TLSLD16_LO = 84, + R_PPC_GOT_TLSLD16_HI = 85, + R_PPC_GOT_TLSLD16_HA = 86, + R_PPC_GOT_TPREL16 = 87, + R_PPC_GOT_TPREL16_LO = 88, + R_PPC_GOT_TPREL16_HI = 89, + R_PPC_GOT_TPREL16_HA = 90, + R_PPC_GOT_DTPREL16 = 91, + R_PPC_GOT_DTPREL16_LO = 92, + R_PPC_GOT_DTPREL16_HI = 93, + R_PPC_GOT_DTPREL16_HA = 94, + R_PPC_TLSGD = 95, + R_PPC_TLSLD = 96, + + R_PPC_EMB_NADDR32 = 101, // word32 (A - S) + R_PPC_EMB_NADDR16 = 102, // half16* (A - S) + R_PPC_EMB_NADDR16_LO = 103, // half16 #lo(A - S) + R_PPC_EMB_NADDR16_HI = 104, // half16 #hi(A - S) + R_PPC_EMB_NADDR16_HA = 105, // half16 #ha(A - S) + R_PPC_EMB_SDA_I16 = 106, // half16* T + R_PPC_EMB_SDA2_I16 = 107, // half16* U + R_PPC_EMB_SDA2REL = 108, // half16* S + A - _SDA2_BASE_ + R_PPC_EMB_SDA21 = 109, // low21 Y || (X + A) + R_PPC_EMB_MRKREF = 110, // none See below + R_PPC_EMB_RELSEC16 = 111, // half16* V + A + R_PPC_EMB_RELST_LO = 112, // half16 #lo(W + A) + R_PPC_EMB_RELST_HI = 113, // half16 #hi(W + A) + R_PPC_EMB_RELST_HA = 114, // half16 #ha(W + A) + R_PPC_EMB_BIT_FLD = 115, // word32* See below + R_PPC_EMB_RELSDA = 116, // half16* X + A. See below + R_PPC_EMB_RELOC_120 = 120, // half16* S + A + R_PPC_EMB_RELOC_121 = 121, // half16* Same calculation as U, except that the value 0 is used instead of _SDA2_BASE_. + +/* The R_PPC_DIAB_SDA21_xx relocation modes work like the R_PPC_EMB_SDA21 mode + * and the R_PPC_DIAB_RELSDA_xx relocation modes work like the R_PPC_EMB_RELSDA mode + * with the following exceptions: + * If the symbol is in .data, .sdata, .bss, .sbss the symbol is DATA relative + (r13 base pointer/_SDA_BASE_ base address) + * If the symbol is in .text, .sdata2, .sbss2 the symbol is CODE relative + (r2 base pointer/_SDA_BASE2_ base address) + * Otherwise the symbol is absolute (r0 base pointer/0 base address) + */ + R_PPC_DIAB_SDA21_LO = 180, // half21 Y || #lo(X + A) + R_PPC_DIAB_SDA21_HI = 181, // half21 Y || #hi(X + A) + R_PPC_DIAB_SDA21_HA = 182, // half21 Y || #ha(X + A) + R_PPC_DIAB_RELSDA_LO = 183, // half16 #lo(X + A) + R_PPC_DIAB_RELSDA_HI = 184, // half16 #hi(X + A) + R_PPC_DIAB_RELSDA_HA = 185, // half16 #ha(X + A) + R_PPC_DIAB_IMTO = 186, + R_PPC_DIAB_IMT = 187, + R_PPC_DIAB_ADDR0 = 188, + R_PPC_DIAB_OVERRIDE0 = 189, + R_PPC_DIAB_VTBL32 = 190, + R_PPC_DIAB_LAST = 191, + + R_PPC_EMB_SPE_DOUBLE = 201, // mid5* (#lo(S + A)) >> 3 + R_PPC_EMB_SPE_WORD = 202, // mid5* (#lo(S + A)) >> 2 + R_PPC_EMB_SPE_HALF = 203, // mid5* (#lo(S + A)) >> 1 + R_PPC_EMB_SPE_DOUBLE_SDAREL = 204, // mid5* (#lo(S + A - _SDA_BASE_)) >> 3 + R_PPC_EMB_SPE_WORD_SDAREL = 205, // mid5* (#lo(S + A - _SDA_BASE_)) >> 2 + R_PPC_EMB_SPE_HALF_SDAREL = 206, // mid5* (#lo(S + A - _SDA_BASE_)) >> 1 + R_PPC_EMB_SPE_DOUBLE_SDA2REL = 207, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 3 + R_PPC_EMB_SPE_WORD_SDA2REL = 208, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 2 + R_PPC_EMB_SPE_HALF_SDA2REL = 209, // mid5* (#lo(S + A - _SDA2_BASE_)) >> 1 + R_PPC_EMB_SPE_DOUBLE_SDA0REL = 210, // mid5* (#lo(S + A)) >> 3 + R_PPC_EMB_SPE_WORD_SDA0REL = 211, // mid5* (#lo(S + A)) >> 2 + R_PPC_EMB_SPE_HALF_SDA0REL = 212, // mid5* (#lo(S + A)) >> 1 + R_PPC_EMB_SPE_DOUBLE_SDA = 213, // mid10* Y || ((#lo(X + A)) >> 3) + R_PPC_EMB_SPE_WORD_SDA = 214, // mid10* Y || ((#lo(X + A)) >> 2) + R_PPC_EMB_SPE_HALF_SDA = 215, // mid10* Y || ((#lo(X + A)) >> 1) + + R_PPC_VLE_REL8 = 216, // bdh8 (S + A - P) >> 1 + R_PPC_VLE_REL15 = 217, // bdh15 (S + A - P) >> 1 + R_PPC_VLE_REL24 = 218, // bdh24 (S + A - P) >> 1 + R_PPC_VLE_LO16A = 219, // split16a #lo(S + A) + R_PPC_VLE_LO16D = 220, // split16d #lo(S + A) + R_PPC_VLE_HI16A = 221, // split16a #hi(S + A) + R_PPC_VLE_HI16D = 222, // split16d #hi(S + A) + R_PPC_VLE_HA16A = 223, // split16a #ha(S + A) + R_PPC_VLE_HA16D = 224, // split16d #ha(S + A) + R_PPC_VLE_SDA21 = 225, // low21, split20 Y || (X + A) + R_PPC_VLE_SDA21_LO = 226, // low21, split20 Y || #lo(X + A) + R_PPC_VLE_SDAREL_LO16A = 227, // split16a #lo(X + A) + R_PPC_VLE_SDAREL_LO16D = 228, // split16d #lo(X + A) + R_PPC_VLE_SDAREL_HI16A = 229, // split16a #hi(X + A) + R_PPC_VLE_SDAREL_HI16D = 230, // split16d #hi(X + A) + R_PPC_VLE_SDAREL_HA16A = 231, // split16a #ha(X + A) + R_PPC_VLE_SDAREL_HA16D = 232, // split16d #ha(X + A) + + R_PPC_REL16DX_HA = 246, + + R_PPC_IRELATIVE = 248, // GNU extension to support local ifunc. + /* GNU relocs used in PIC code sequences. */ + R_PPC_REL16 = 249, // half16* S + A - P + R_PPC_REL16_LO = 250, // half16 #lo(S + A - P) + R_PPC_REL16_HI = 251, // half16 #hi(S + A - P) + R_PPC_REL16_HA = 252, // half16 #la(S + A - P) + + R_PPC_GNU_VTINHERIT = 253, + R_PPC_GNU_VTENTRY = 254, +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ + R_PPC_TOC16 = 255, + + // PowerPC64 relocations. Many (but not all) of them are the same as for PPC32 + R_PPC64_NONE = R_PPC_NONE, + R_PPC64_ADDR32 = R_PPC_ADDR32, /* 32bit absolute address. */ + R_PPC64_ADDR24 = R_PPC_ADDR24, /* 26bit address, word aligned. */ + R_PPC64_ADDR16 = R_PPC_ADDR16, /* 16bit absolute address. */ + R_PPC64_ADDR16_LO = R_PPC_ADDR16_LO, /* lower 16bits of abs. address. */ + R_PPC64_ADDR16_HI = R_PPC_ADDR16_HI, /* high 16bits of abs. address. */ + R_PPC64_ADDR16_HA = R_PPC_ADDR16_HA, /* adjusted high 16bits. */ + R_PPC64_ADDR14 = R_PPC_ADDR14, /* 16bit address, word aligned. */ + R_PPC64_ADDR14_BRTAKEN = R_PPC_ADDR14_BRTAKEN, + R_PPC64_ADDR14_BRNTAKEN = R_PPC_ADDR14_BRNTAKEN, + R_PPC64_REL24 = R_PPC_REL24, /* PC relative 26 bit, word aligned. */ + R_PPC64_REL14 = R_PPC_REL14, /* PC relative 16 bit. */ + R_PPC64_REL14_BRTAKEN = R_PPC_REL14_BRTAKEN, + R_PPC64_REL14_BRNTAKEN = R_PPC_REL14_BRNTAKEN, + R_PPC64_GOT16 = R_PPC_GOT16, + R_PPC64_GOT16_LO = R_PPC_GOT16_LO, + R_PPC64_GOT16_HI = R_PPC_GOT16_HI, + R_PPC64_GOT16_HA = R_PPC_GOT16_HA, + R_PPC64_PLTREL24 = R_PPC_PLTREL24, + R_PPC64_COPY = R_PPC_COPY, + R_PPC64_GLOB_DAT = R_PPC_GLOB_DAT, + R_PPC64_JMP_SLOT = R_PPC_JMP_SLOT, + R_PPC64_RELATIVE = R_PPC_RELATIVE, + R_PPC64_LOCAL24PC = R_PPC_LOCAL24PC, + R_PPC64_UADDR32 = R_PPC_UADDR32, + R_PPC64_UADDR16 = R_PPC_UADDR16, + R_PPC64_REL32 = R_PPC_REL32, + R_PPC64_PLT32 = R_PPC_PLT32, + R_PPC64_PLTREL32 = R_PPC_PLTREL32, + R_PPC64_PLT16_LO = R_PPC_PLT16_LO, + R_PPC64_PLT16_HI = R_PPC_PLT16_HI, + R_PPC64_PLT16_HA = R_PPC_PLT16_HA, + R_PPC64_SDAREL16 = R_PPC_SDAREL16, + R_PPC64_SECTOFF = R_PPC_SECTOFF, + R_PPC64_SECTOFF_LO = R_PPC_SECTOFF_LO, + R_PPC64_SECTOFF_HI = R_PPC_SECTOFF_HI, + R_PPC64_SECTOFF_HA = R_PPC_SECTOFF_HA, + + R_PPC64_ADDR30 = 37, /* word30 (S + A - P) >> 2. */ + R_PPC64_ADDR64 = 38, /* doubleword64 S + A. */ + R_PPC64_ADDR16_HIGHER = 39, /* half16 #higher(S + A). */ + R_PPC64_ADDR16_HIGHERA = 40, /* half16 #highera(S + A). */ + R_PPC64_ADDR16_HIGHEST = 41, /* half16 #highest(S + A). */ + R_PPC64_ADDR16_HIGHESTA = 42, /* half16 #highesta(S + A). */ + R_PPC64_UADDR64 = 43, /* doubleword64 S + A. */ + R_PPC64_REL64 = 44, /* doubleword64 S + A - P. */ + R_PPC64_PLT64 = 45, /* doubleword64 L + A. */ + R_PPC64_PLTREL64 = 46, /* doubleword64 L + A - P. */ + R_PPC64_TOC16 = 47, /* half16* S + A - .TOC. */ + R_PPC64_TOC16_LO = 48, /* half16 #lo(S + A - .TOC.). */ + R_PPC64_TOC16_HI = 49, /* half16 #hi(S + A - .TOC.). */ + R_PPC64_TOC16_HA = 50, /* half16 #ha(S + A - .TOC.). */ + R_PPC64_TOC = 51, /* doubleword64 .TOC. */ + R_PPC64_PLTGOT16 = 52, /* half16* M + A. */ + R_PPC64_PLTGOT16_LO = 53, /* half16 #lo(M + A). */ + R_PPC64_PLTGOT16_HI = 54, /* half16 #hi(M + A). */ + R_PPC64_PLTGOT16_HA = 55, /* half16 #ha(M + A). */ + + R_PPC64_ADDR16_DS = 56, /* half16ds* (S + A) >> 2. */ + R_PPC64_ADDR16_LO_DS = 57, /* half16ds #lo(S + A) >> 2. */ + R_PPC64_GOT16_DS = 58, /* half16ds* (G + A) >> 2. */ + R_PPC64_GOT16_LO_DS = 59, /* half16ds #lo(G + A) >> 2. */ + R_PPC64_PLT16_LO_DS = 60, /* half16ds #lo(L + A) >> 2. */ + R_PPC64_SECTOFF_DS = 61, /* half16ds* (R + A) >> 2. */ + R_PPC64_SECTOFF_LO_DS = 62, /* half16ds #lo(R + A) >> 2. */ + R_PPC64_TOC16_DS = 63, /* half16ds* (S + A - .TOC.) >> 2. */ + R_PPC64_TOC16_LO_DS = 64, /* half16ds #lo(S + A - .TOC.) >> 2. */ + R_PPC64_PLTGOT16_DS = 65, /* half16ds* (M + A) >> 2. */ + R_PPC64_PLTGOT16_LO_DS = 66, /* half16ds #lo(M + A) >> 2. */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ + R_PPC64_TLS = 67, /* none (sym+add)@tls */ + R_PPC64_DTPMOD64 = 68, /* doubleword64 (sym+add)@dtpmod */ + R_PPC64_TPREL16 = 69, /* half16* (sym+add)@tprel */ + R_PPC64_TPREL16_LO = 70, /* half16 (sym+add)@tprel@l */ + R_PPC64_TPREL16_HI = 71, /* half16 (sym+add)@tprel@h */ + R_PPC64_TPREL16_HA = 72, /* half16 (sym+add)@tprel@ha */ + R_PPC64_TPREL64 = 73, /* doubleword64 (sym+add)@tprel */ + R_PPC64_DTPREL16 = 74, /* half16* (sym+add)@dtprel */ + R_PPC64_DTPREL16_LO = 75, /* half16 (sym+add)@dtprel@l */ + R_PPC64_DTPREL16_HI = 76, /* half16 (sym+add)@dtprel@h */ + R_PPC64_DTPREL16_HA = 77, /* half16 (sym+add)@dtprel@ha */ + R_PPC64_DTPREL64 = 78, /* doubleword64 (sym+add)@dtprel */ + R_PPC64_GOT_TLSGD16 = 79, /* half16* (sym+add)@got@tlsgd */ + R_PPC64_GOT_TLSGD16_LO = 80, /* half16 (sym+add)@got@tlsgd@l */ + R_PPC64_GOT_TLSGD16_HI = 81, /* half16 (sym+add)@got@tlsgd@h */ + R_PPC64_GOT_TLSGD16_HA = 82, /* half16 (sym+add)@got@tlsgd@ha */ + R_PPC64_GOT_TLSLD16 = 83, /* half16* (sym+add)@got@tlsld */ + R_PPC64_GOT_TLSLD16_LO = 84, /* half16 (sym+add)@got@tlsld@l */ + R_PPC64_GOT_TLSLD16_HI = 85, /* half16 (sym+add)@got@tlsld@h */ + R_PPC64_GOT_TLSLD16_HA = 86, /* half16 (sym+add)@got@tlsld@ha */ + R_PPC64_GOT_TPREL16_DS = 87, /* half16ds* (sym+add)@got@tprel */ + R_PPC64_GOT_TPREL16_LO_DS = 88, /* half16ds (sym+add)@got@tprel@l */ + R_PPC64_GOT_TPREL16_HI = 89, /* half16 (sym+add)@got@tprel@h */ + R_PPC64_GOT_TPREL16_HA = 90, /* half16 (sym+add)@got@tprel@ha */ + R_PPC64_GOT_DTPREL16_DS = 91, /* half16ds* (sym+add)@got@dtprel */ + R_PPC64_GOT_DTPREL16_LO_DS = 92, /* half16ds (sym+add)@got@dtprel@l */ + R_PPC64_GOT_DTPREL16_HI = 93, /* half16 (sym+add)@got@dtprel@h */ + R_PPC64_GOT_DTPREL16_HA = 94, /* half16 (sym+add)@got@dtprel@ha */ + R_PPC64_TPREL16_DS = 95, /* half16ds* (sym+add)@tprel */ + R_PPC64_TPREL16_LO_DS = 96, /* half16ds (sym+add)@tprel@l */ + R_PPC64_TPREL16_HIGHER = 97, /* half16 (sym+add)@tprel@higher */ + R_PPC64_TPREL16_HIGHERA = 98, /* half16 (sym+add)@tprel@highera */ + R_PPC64_TPREL16_HIGHEST = 99, /* half16 (sym+add)@tprel@highest */ + R_PPC64_TPREL16_HIGHESTA = 100, /* half16 (sym+add)@tprel@highesta */ + R_PPC64_DTPREL16_DS = 101, /* half16ds* (sym+add)@dtprel */ + R_PPC64_DTPREL16_LO_DS = 102, /* half16ds (sym+add)@dtprel@l */ + R_PPC64_DTPREL16_HIGHER = 103, /* half16 (sym+add)@dtprel@higher */ + R_PPC64_DTPREL16_HIGHERA = 104, /* half16 (sym+add)@dtprel@highera */ + R_PPC64_DTPREL16_HIGHEST = 105, /* half16 (sym+add)@dtprel@highest */ + R_PPC64_DTPREL16_HIGHESTA = 106, /* half16 (sym+add)@dtprel@highesta */ +#if 0 + // These relocation types appear in David Anderson's libdwarf and + // dwarfdump only. The PPC 64-Bit ELF V2 ABI uses these numbers for + // different types (see below). + R_PPC64_TOC32 = 107, /* word32 (.TOC. & 0xffff_ffff) */ + R_PPC64_DTPMOD32 = 108, /* word32 (@dtpmod & 0xffff_ffff) */ + R_PPC64_TPREL32 = 109, /* word32 (@tprel & 0xffff_ffff) */ + R_PPC64_DTPREL32 = 110, /* word32 (@dtprel & 0xffff_ffff) */ +#else + // The PPC 64-Bit ELF V2 ABI uses these numbers for different types + R_PPC64_TLSGD = 107, // used as markers on thread local + R_PPC64_TLSLD = 108, // storage (TLS) code sequences + R_PPC64_TOCSAVE = 109, // this relocation type indicates a + // position where a TOC save may be + // inserted in the function to avoid a + // TOC save as part of the PLT stub code + R_PPC64_ADDR16_HIGH = 110, // half16 #hi(S + A) + R_PPC64_ADDR16_HIGHA = 111, // half16 #ha(S + A) + R_PPC64_TPREL16_HIGH = 112, // half16 #hi(@tprel) + R_PPC64_TPREL16_HIGHA = 113, // half16 #ha(@tprel) + R_PPC64_DTPREL16_HIGH = 114, // half16 #hi(@dtprel) + R_PPC64_DTPREL16_HIGHA = 115, // half16 #ha(@dtprel) + R_PPC64_REL24_NOTOC = 116, // low24* (S + A - P) >> 2 + R_PPC64_ADDR64_LOCAL = 117, // doubleword64 S + A (see 3.5.4) +#endif + R_PPC64_JMP_IREL = 247, // GNU extension to support local ifunc + // The PPC 64-Bit ELF V2 ABI + R_PPC64_IRELATIVE = 248, // It is used to implement the + // STT_GNU_IFUNC framework + R_PPC64_REL16 = R_PPC_REL16, // half16* S + A - P + R_PPC64_REL16_LO = R_PPC_REL16_LO, // half16 #lo(S + A - P) + R_PPC64_REL16_HI = R_PPC_REL16_HI, // half16* #hi(S + A - P) + R_PPC64_REL16_HA = R_PPC_REL16_HA, // half16* #la(S + A - P) +}; + +// flags for VLE code +#define SHF_PPC_VLE 0x10000000 /* section header flag */ +#define PF_PPC_VLE 0x10000000 /* program header flag */ + +// patching GOT loading, +// discard auxiliary values in plt/got +// can present offset bypass segment +#define ELF_RPL_PPC_DEFAULT (ELF_RPL_GL | ELF_DIS_OFFW | ELF_DIS_GPLT) + +#endif diff --git a/idasdk76/ldr/elf/reader.cpp b/idasdk76/ldr/elf/reader.cpp new file mode 100644 index 0000000..a02becb --- /dev/null +++ b/idasdk76/ldr/elf/reader.cpp @@ -0,0 +1,3558 @@ + +#ifndef ELF_READER_CPP +#define ELF_READER_CPP + +#include <functional> + +#include <pro.h> +#include <diskio.hpp> + +#include "elfbase.h" +#include "elf.h" +#include "elfr_arm.h" +#include "elfr_mips.h" +#include "elfr_ia64.h" +#include "elfr_ppc.h" +#include "../idaldr.h" + +//---------------------------------------------------------------------------- +ssize_t reader_t::prepare_error_string( + char *buf, + size_t bufsize, + reader_t::errcode_t code, + va_list va) const +{ + int len; + switch ( code ) + { + case BAD_CLASS: + { + int eclass = va_arg(va, int); + len = qsnprintf(buf, bufsize, + "Unknown ELF class %d (should be %d for 32-bit, %d for 64-bit)", + eclass, + ELFCLASS32, + ELFCLASS64); + } + break; + case BAD_ENDIANNESS: + { + int endian = va_arg(va, int); + if ( endian != ELFDATA2LSB && endian != ELFDATA2MSB ) + len = qsnprintf(buf, bufsize, + "Unknown ELF byte sex %d (should be %d for LSB, %d for MSB)", + endian, + ELFDATA2LSB, + ELFDATA2MSB); + else + len = qsnprintf(buf, bufsize, + "Bad ELF byte sex %d for the indicated machine", + endian); + } + break; + case BAD_EHSIZE: + { + int sz = va_arg(va, int); + int fb = va_arg(va, int); + len = qsnprintf(buf, bufsize, + "The ELF header entry size is invalid (%d, expected %d)", + sz, fb); + } + break; + case BAD_PHENTSIZE: + { + int sz = va_arg(va, int); + int fb = va_arg(va, int); + len = qsnprintf(buf, bufsize, + "PHT entry size is invalid: %d. Falling back to %d", + sz, fb); + } + break; + case BAD_PHLOC: + len = qstpncpy(buf, "The PHT table size or offset is invalid", bufsize) - buf; + break; + case BAD_SHENTSIZE: + len = qstpncpy(buf, "The SHT entry size is invalid", bufsize) - buf; + break; + case BAD_SHLOC: + len = qstpncpy(buf, "SHT table size or offset is invalid", bufsize) - buf; + break; + case BAD_DYN_PLT_TYPE: + len = qsnprintf(buf, bufsize, "Bad DT_PLTREL value (%d)", va_arg(va, int)); + break; + case CONFLICTING_FILE_TYPE: + len = qstpncpy(buf, "ELF file with PHT cannot be ET_REL", bufsize) - buf; + break; + case BAD_SHSTRNDX: + { + uint idx = va_arg(va, uint); + uint num = va_arg(va, uint); + len = qsnprintf(buf, bufsize, + "Section header string table index %u is out of bounds", + idx); + if ( num > 0 ) + len += qsnprintf(buf + len, bufsize - len, + " (max %u)", num - 1); + } + break; + case ERR_READ: + { + size_t d1 = va_arg(va, size_t); // size + size_t d2 = va_arg(va, size_t); // return code + qnotused(d1); + qnotused(d2); + len = qsnprintf(buf, bufsize, + "Bad file structure or read error (offset %" FMT_64 "u)", + va_arg(va, int64)); + } + break; + default: + if ( is_error(code) ) + INTERR(20034); + len = qsnprintf(buf, bufsize, "Unknown ELF warning %d", code); + break; + } + return len; +} + +//---------------------------------------------------------------------------- +static bool default_error_handler(const reader_t &reader, reader_t::errcode_t code, ...) +{ + va_list va; + va_start(va, code); + char buf[MAXSTR]; + reader.prepare_error_string(buf, sizeof(buf), code, va); + va_end(va); + + warning("%s", buf); + return reader.is_warning(code); // resume after warnings +} + +//---------------------------------------------------------------------------- +const qstring &sym_rel::get_original_name(const reader_t &reader) const +{ + if ( original_name.empty() ) + { + symrel_idx_t sym_idx = reader.symbols.get_idx(this); + reader.get_name(&original_name, sym_idx.type, original.st_name); + } + + return original_name; +} + +//---------------------------------------------------------------------------- +ea_t sym_rel::get_ea(const reader_t &reader, ea_t _debug_segbase) const +{ + ea_t ea = value; + if ( reader.is_valid_rel_file() || is_psp_file(reader) ) + { + const elf_shdr_t *sh = reader.sections.getn(sec); + if ( sh != NULL ) + ea += sh->sh_addr; + } + else + { + ea += _debug_segbase; + } + return ea; +} + +//---------------------------------------------------------------------------- +void sym_rel::set_section_index(const reader_t &reader) +{ + sec = 0; + if ( original.st_shndx == SHN_XINDEX ) + { + symrel_idx_t sym_idx = reader.symbols.get_idx(this); + const elf_shdr_t *sh_shndx; + switch ( sym_idx.type ) + { + case SLT_SYMTAB: + sh_shndx = reader.sections.get_wks(WKS_SYMTAB_SHNDX); + break; + case SLT_DYNSYM: + sh_shndx = reader.sections.get_wks(WKS_DYNSYM_SHNDX); + break; + default: + INTERR(20088); + } + // doc: "The section is an array of Elf32_Word values." + uint64 offset = sym_idx.idx * sizeof(uint32); + if ( sh_shndx != NULL + && sh_shndx->sh_offset != 0 + && offset < sh_shndx->sh_size ) + { + sec = reader.get_shndx_at(sh_shndx->sh_offset + offset); + } + if ( sec == 0 ) + { + warning("AUTOHIDE SESSION\n" + "Illegal section indirect index for symbol %u", + sym_idx.idx); + } + } + else if ( original.st_shndx < SHN_LORESERVE ) + { + sec = original.st_shndx; + } +} + +//---------------------------------------------------------------------------- +reader_t::reader_t(linput_t *_li, int64 _start_in_file) + : pheaders(this), + sections(this), + sym_strtab(), + dyn_strtab(), + li(_li), + sif(_start_in_file), + mappings(), + arch_specific(NULL), + load_bias(0), + eff_msb(false), + eff_64(false), + seg_64(false) +{ + set_handler(default_error_handler); + filesize = qlsize(li); +} + +//---------------------------------------------------------------------------- +bool reader_t::is_warning(errcode_t code) const +{ + return code <= LAST_WARNING; +} + +//---------------------------------------------------------------------------- +bool reader_t::is_error(errcode_t code) const +{ + QASSERT(20035, code <= LAST_ERROR); + return code > LAST_WARNING; +} + +//------------------------------------------------------------------------- +static bool _silent_handler(const reader_t &reader, reader_t::errcode_t code, ...) +{ + return reader.is_warning(code); // resume after warnings +} + +//---------------------------------------------------------------------------- +void reader_t::set_handler(bool (*_handler)(const reader_t &reader, errcode_t code, ...)) +{ + handle_error = _handler == NULL ? _silent_handler : _handler; +} + +bool reader_t::read_ident() +{ + input_status_t save_excursion(*this); + if ( save_excursion.seek(0) == -1 ) + return false; + + uint64 fsize = size(); + uint64 fpos = tell(); + if ( fpos >= fsize ) + return false; + uint64 bytes_left = fsize - fpos; + if ( bytes_left < sizeof(elf_ident_t) ) + return false; + + memset(&header, 0, sizeof(header)); + + if ( qlread(li, &header.e_ident, sizeof(elf_ident_t)) != sizeof(elf_ident_t) ) + return false; + + if ( !header.e_ident.is_valid() ) + return false; + + size_t ehdr_sz = is_64() ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr); + if ( bytes_left < ehdr_sz ) + return false; + + return true; +} + +//---------------------------------------------------------------------------- +int reader_t::safe_read(void *buf, size_t sz, bool apply_endianness) const +{ + int rc = lreadbytes(li, buf, sz, apply_endianness && is_msb()); + if ( rc < 0 ) + handle_error(*this, ERR_READ, sz, size_t(rc), qltell(li)); + return rc; +} + +//---------------------------------------------------------------------------- +int reader_t::read_addr(void *buf) const +{ + return safe_read(buf, stdsizes.types.elf_addr); +} + +//---------------------------------------------------------------------------- +int reader_t::read_off(void *buf) const +{ + return safe_read(buf, stdsizes.types.elf_off); +} + +//---------------------------------------------------------------------------- +int reader_t::read_xword(void *buf) const +{ + return safe_read(buf, stdsizes.types.elf_xword); +} + +//---------------------------------------------------------------------------- +int reader_t::read_sxword(void *buf) const +{ + return safe_read(buf, stdsizes.types.elf_sxword); +} + +//---------------------------------------------------------------------------- +int reader_t::read_word(uint32 *buf) const +{ + return safe_read(buf, 4); +} + +//---------------------------------------------------------------------------- +int reader_t::read_half(uint16 *buf) const +{ + return safe_read(buf, 2); +} + +//---------------------------------------------------------------------------- +int reader_t::read_byte(uint8 *buf) const +{ + return safe_read(buf, 1); +} + +//------------------------------------------------------------------------- +int reader_t::read_symbol(elf_sym_t *buf) const +{ +#define _safe(expr) if ( (expr) < 0 ) goto FAILED_RS + if ( is_64() ) + { + _safe(read_word(&buf->st_name)); + _safe(read_byte(&buf->st_info)); + _safe(read_byte(&buf->st_other)); + _safe(read_half(&buf->st_shndx)); + _safe(read_addr(&buf->st_value)); + _safe(read_xword(&buf->st_size)); + } + else + { + _safe(read_word(&buf->st_name)); + _safe(read_addr(&buf->st_value)); + _safe(read_word((uint32 *) &buf->st_size)); + _safe(read_byte(&buf->st_info)); + _safe(read_byte(&buf->st_other)); + _safe(read_half(&buf->st_shndx)); + } + return 0; +FAILED_RS: + return -1; +#undef _safe +} + +#define IS_EXEC_OR_DYN(x) ((x) == ET_EXEC || (x) == ET_DYN) + +struct linuxcpu_t +{ + uint16 machine; + bool msb; + bool _64; +}; + +static const linuxcpu_t lincpus[] = +{ +// machine msb 64 + { EM_386, false, false }, + { EM_486, false, false }, + { EM_X86_64, false, true }, +}; + +//---------------------------------------------------------------------------- +// Linux kernel loader ignores class and endian fields for some(?) processors. +// check for such situation and set the effective endiannes/bitness +bool reader_t::check_ident() +{ + for ( unsigned i = 0; i < qnumber(lincpus); i++ ) + { + bool matched = false; + bool swap; + if ( eff_msb == lincpus[i].msb + && header.e_machine == lincpus[i].machine + && IS_EXEC_OR_DYN(header.e_type) ) + { + matched = true; + swap = false; + } + else if ( eff_msb != lincpus[i].msb + && swap16(header.e_machine) == lincpus[i].machine + && IS_EXEC_OR_DYN(swap16(header.e_type)) ) + { + matched = true; + swap = true; + } + if ( matched ) + { + if ( swap ) + { + header.e_machine = swap16(header.e_machine); + header.e_type = swap16(header.e_type); + if ( !handle_error(*this, BAD_ENDIANNESS, header.e_ident.bytesex) ) + return false; + eff_msb = lincpus[i].msb; + } + // segment bitness can be different from elf bitness: apparently there + // are some files like that in the wild (see pc_odd_bitness_64.elf) + seg_64 = lincpus[i]._64; + // assume elf32 for EM_386/EM_486 + if ( !seg_64 ) + eff_64 = false; + break; + } + } + return true; +} + +//---------------------------------------------------------------------------- +bool reader_t::read_header() +{ + // 32/64 + uint8 elf_class = get_ident().elf_class; + if ( elf_class != ELFCLASS32 + && elf_class != ELFCLASS64 ) + { + if ( !handle_error(*this, BAD_CLASS, elf_class) ) + return false; + } + // lsb/msb + uint8 elf_do = get_ident().bytesex; + if ( elf_do != ELFDATA2LSB + && elf_do != ELFDATA2MSB ) + { + if ( !handle_error(*this, BAD_ENDIANNESS, elf_do) ) + return false; + } + + input_status_t save_excursion(*this); + if ( save_excursion.seek(sizeof(elf_ident_t)) == -1 ) + return false; + + // set the default values from ident + eff_msb = elf_do == ELFDATA2MSB; + eff_64 = elf_class == ELFCLASS64; + seg_64 = eff_64; + + // Read the type and machine +#define _safe(expr) if ( (expr) < 0 ) goto FAILED + _safe(read_half(&header.e_type)); + _safe(read_half(&header.e_machine)); + + if ( !check_ident() ) + return false; + + // Define sizes + if ( !is_64() ) + { + stdsizes.ehdr = sizeof(Elf32_Ehdr); + stdsizes.phdr = sizeof(Elf32_Phdr); + stdsizes.shdr = sizeof(Elf32_Shdr); + stdsizes.entries.sym = sizeof(Elf32_Sym); + stdsizes.entries.dyn = sizeof(Elf32_Dyn); + stdsizes.entries.rel = sizeof(Elf32_Rel); + stdsizes.entries.rela = sizeof(Elf32_Rela); + stdsizes.types.elf_addr = 4; + stdsizes.types.elf_off = 4; + stdsizes.types.elf_xword= 4; + stdsizes.types.elf_sxword=4; + } + else + { + stdsizes.ehdr = sizeof(Elf64_Ehdr); + stdsizes.phdr = sizeof(Elf64_Phdr); + stdsizes.shdr = sizeof(Elf64_Shdr); + stdsizes.entries.sym = sizeof(Elf64_Sym); + stdsizes.entries.dyn = sizeof(Elf64_Dyn); + stdsizes.entries.rel = sizeof(Elf64_Rel); + stdsizes.entries.rela = sizeof(Elf64_Rela); + stdsizes.types.elf_addr = 8; + stdsizes.types.elf_off = 8; + stdsizes.types.elf_xword= 8; + stdsizes.types.elf_sxword=8; + } + stdsizes.dyn.sym = stdsizes.entries.sym; + stdsizes.dyn.rel = stdsizes.entries.rel; + stdsizes.dyn.rela = stdsizes.entries.rela; + + // Read the rest of the header + _safe(read_word(&header.e_version)); + _safe(read_addr(&header.e_entry)); + _safe(read_off (&header.e_phoff)); + _safe(read_off (&header.e_shoff)); + _safe(read_word(&header.e_flags)); + _safe(read_half(&header.e_ehsize)); + _safe(read_half(&header.e_phentsize)); + _safe(read_half(&header.e_phnum)); + _safe(read_half(&header.e_shentsize)); + _safe(read_half(&header.e_shnum)); + _safe(read_half(&header.e_shstrndx)); +#undef _safe + + if ( header.e_ehsize != stdsizes.ehdr ) + if ( !handle_error(*this, BAD_EHSIZE, header.e_ehsize, stdsizes.ehdr) ) + { +FAILED: + return false; + } + + // Sanitize PHT parameters + if ( (header.e_phnum == 0) != (header.e_phoff == 0) ) + { + if ( !handle_error(*this, BAD_PHLOC, header.e_phnum, header.e_phoff) ) + goto FAILED; + header.set_no_pht(); + } + if ( header.has_pht() && header.e_phentsize != stdsizes.phdr ) + { + if ( !handle_error(*this, BAD_PHENTSIZE, header.e_phentsize, stdsizes.phdr) + || header.e_phentsize < stdsizes.phdr ) + { + goto FAILED; + } + header.e_phentsize = stdsizes.phdr; + } + + // process large number of sections + // "System V Application Binary Interface - DRAFT - 19 October 2010" + // If the number of sections is greater than or equal to SHN_LORESERVE + // (0xff00), this member has the value zero and the actual number of + // section header table entries is contained in the sh_size field of the + // section header at index 0. (Otherwise, the sh_size member of the + // initial entry contains 0.) + elf_shdr_t sh0; + bool is_sh0_read; + if ( header.e_shnum == 0 + && header.e_shoff != 0 + && seek(header.e_shoff) != -1 + && read_section_header(&sh0) + && sh0.sh_type == SHT_NULL ) + { + is_sh0_read = true; + header.real_shnum = sh0.sh_size; + } + else + { + is_sh0_read = false; + header.real_shnum = header.e_shnum; + } + + // Sanitize SHT parameters + if ( (header.real_shnum == 0) != (header.e_shoff == 0) ) + { + if ( !handle_error(*this, BAD_SHLOC, header.real_shnum, header.e_shoff, size()) ) + goto FAILED; + header.set_no_sht(); // do not use sht + } + if ( header.has_sht() && header.e_shentsize != stdsizes.shdr ) + { + if ( !handle_error(*this, BAD_SHENTSIZE, header.e_shentsize, stdsizes.shdr) + || header.e_shentsize < stdsizes.shdr ) + { + header.set_no_sht(); // do not use sht + } + } + { + uint64 sections_start = header.e_shoff; + uint64 sections_finish = header.e_shoff + uint64(header.real_shnum) * header.e_shentsize; + if ( sections_start > sections_finish || sections_finish > size() ) + { + if ( !handle_error(*this, BAD_SHLOC, header.real_shnum, header.e_shoff, size()) ) + goto FAILED; + header.set_no_sht(); // do not use sht + } + } + + if ( header.has_sht() ) + { + // process large section name string table section index + // "System V Application Binary Interface - DRAFT - 19 October 2010" + // If the section name string table section index is greater than or equal + // to SHN_LORESERVE (0xff00), this member has the value SHN_XINDEX + // (0xffff) and the actual index of the section name string table section + // is contained in the sh_link field of the section header at index 0. + // (Otherwise, the sh_link member of the initial entry contains 0.) + if ( header.e_shstrndx == SHN_XINDEX && is_sh0_read && sh0.sh_link != 0 ) + header.real_shstrndx = sh0.sh_link; + else + header.real_shstrndx = header.e_shstrndx; + + // Sanitize SHT string table index + if ( header.real_shstrndx > 0 + && header.real_shstrndx >= header.real_shnum ) + { + if ( !handle_error(*this, BAD_SHSTRNDX, uint(header.real_shstrndx), uint(header.real_shnum)) ) + goto FAILED; + header.real_shstrndx = 0; + } + } + + // + if ( header.has_pht() && header.e_type == ET_REL ) + { + if ( !handle_error(*this, CONFLICTING_FILE_TYPE) ) + goto FAILED; + } + + // + switch ( header.e_machine ) + { + case EM_AARCH64: + // AARCH64 files must use 64-bit segments even for ELF32 (ILP32) + seg_64 = true; + // fallthrough + case EM_ARM: + delete arch_specific; + arch_specific = new arm_arch_specific_t; + break; + default: + arch_specific = new arch_specific_t; // Dummy + break; + } + return true; +} + +//---------------------------------------------------------------------------- +bool reader_t::read_section_header(elf_shdr_t *sh) +{ +#define _safe(expr) if ( expr < 0 ) return false; + _safe(read_word (&sh->sh_name)); + _safe(read_word (&sh->sh_type)); + _safe(read_xword(&sh->sh_flags)); + _safe(read_addr (&sh->sh_addr)); + _safe(read_off (&sh->sh_offset)); + _safe(read_xword(&sh->sh_size)); + _safe(read_word (&sh->sh_link)); + _safe(read_word (&sh->sh_info)); + _safe(read_xword(&sh->sh_addralign)); + _safe(read_xword(&sh->sh_entsize)); +#undef _safe + return true; +} + +//------------------------------------------------------------------------- +bool reader_t::read_compression_header(elf_chdr_t *out) +{ +#define _safe(expr) if ( expr < 0 ) return false; + _safe(read_word(&out->ch_type)); + if ( is_64() ) + _safe(read_word(&out->ch_reserved)); + _safe(read_xword(&out->ch_size)); + _safe(read_xword(&out->ch_addralign)); +#undef _safe + return true; +} + +//---------------------------------------------------------------------------- +bool reader_t::read_section_headers() +{ + if ( !header.has_sht() ) + return false; + input_status_t save_excursion(*this); + if ( save_excursion.seek(header.e_shoff) == -1 ) + return false; + + sections.resize(header.real_shnum); + + sections.initialized = true; + + for ( elf_shndx_t i = 0; i < header.real_shnum; i++ ) + { + if ( !seek_to_section_header(i) ) + return false; + + elf_shdr_t *sh = sections.getn(i); + if ( !read_section_header(sh) ) + return false; + } + + // in the first pass we store WKS_SYMTAB/WKS_DYNSYM to process sections + // of type SHT_SYMTAB_SHNDX in the second pass + typedef elf_shdrs_t::const_iterator const_iter; + const_iter it = sections.begin(); + const_iter end = sections.end(); + for ( elf_shndx_t i = 0; it != end; ++it, ++i ) + { + if ( i == 0 ) // Skip first header + continue; + const elf_shdr_t &sh = *it; + if ( sh.sh_size == 0 ) + continue; + + switch ( sh.sh_type ) + { + case SHT_SYMTAB: + { + sections.set_index(WKS_SYMTAB, i); + elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); + if ( strtab_sh == NULL ) + { + msg("Illegal link section %d of the string table " + "for symbols\n", + sh.sh_link); + } + else + { + set_sh_strtab(sym_strtab, *strtab_sh, true); + } + } + break; + + case SHT_DYNSYM: + { + sections.set_index(WKS_DYNSYM, i); + elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); + if ( strtab_sh == NULL ) + { + msg("Illegal link section %d of the string table " + "for dynamic linking symbols\n", + sh.sh_link); + } + else + { + set_sh_strtab(dyn_strtab, *strtab_sh, true); + } + } + break; + + case SHT_DYNAMIC: + { + elf_shdr_t *strtab_sh = sections.getn(sh.sh_link); + if ( strtab_sh == NULL ) + { + msg("Illegal link section %d of the dynamic linking " + "information section\n", + sh.sh_link); + } + else if ( strtab_sh->sh_type == SHT_DYNSYM ) + { + // OAT file: .dynamic section links to .dynsym section + strtab_sh->sh_link = 0; + } + else + { + set_sh_strtab(dyn_strtab, *strtab_sh, true); + } + } + break; + } + } + + // initialize the section name string table + if ( header.real_shstrndx != 0 ) + { + elf_shdr_t *shstrtab = sections.getn(header.real_shstrndx); + if ( shstrtab != NULL ) + { + // we do not check type of this section here + // (in some cases it may be not SHT_STRTAB) + sections.strtab.offset = shstrtab->sh_offset; + sections.strtab.addr = shstrtab->sh_addr; + sections.strtab.size = shstrtab->sh_size; + } + } + + qstring name; + it = sections.begin(); + for ( elf_shndx_t i = 0; it != end; ++it, ++i ) + { + if ( i == 0 ) // Skip first header + continue; + + const elf_shdr_t &sh = *it; + if ( sh.sh_size == 0 ) + continue; + + name.qclear(); + sections.get_name(&name, &sh); + switch ( sh.sh_type ) + { + case SHT_STRTAB: + // we specify replace = false as this section has less priority + // compared to the sh_link section + if ( name == ".strtab" ) + set_sh_strtab(sym_strtab, sh, false); + else if ( name == ".dynstr" ) + set_sh_strtab(dyn_strtab, sh, false); + break; + + case SHT_SYMTAB_SHNDX: + if ( sh.sh_link != 0 ) + { + if ( sh.sh_link == sections.get_index(WKS_SYMTAB) ) + sections.set_index(WKS_SYMTAB_SHNDX, i); + if ( sh.sh_link == sections.get_index(WKS_DYNSYM) ) + sections.set_index(WKS_DYNSYM_SHNDX, i); + } + break; + + case SHT_GNU_verdef: + sections.set_index(WKS_VERDEF, i); + break; + case SHT_GNU_verneed: + sections.set_index(WKS_VERNEED, i); + break; + case SHT_GNU_versym: + sections.set_index(WKS_VERSYM, i); + break; + + case SHT_PROGBITS: + if ( name == ".interp" ) + { + sections.set_index(WKS_INTERP, i); + break; + } + else if ( name == ".got" ) + { + sections.set_index(WKS_GOT, i); + sections.set_got_original(); + break; + } + else if ( name == ".got.plt" ) + { + sections.set_index(WKS_GOTPLT, i); + break; + } + else if ( name == ".plt.got" ) + { + sections.set_index(WKS_PLTGOT, i); + break; + } + else if ( name == ".plt.sec" ) + { + sections.set_index(WKS_PLTSEC, i); + break; + } + else if ( name == ".gnu_debugdata" ) + { + sections.set_index(WKS_GNU_DEBUGDATA, i); + break; + } + // function pointers for PPC64 (may be for IA64, HPPA64) + else if ( is_64() && name == ".opd" ) + { + sections.set_index(WKS_OPD, i); + break; + } + // no break + case SHT_NOBITS: + if ( name == ".plt" ) + sections.set_index(WKS_PLT, i); + break; + } + } + + if ( sections.get_index(WKS_GOTPLT) == 0 ) + sections.set_index(WKS_GOTPLT, sections.get_index(WKS_GOT)); + else if ( sections.get_index(WKS_GOT) == 0 ) + sections.set_index(WKS_GOTPLT, 0); // unsupported format + + return true; +} + +//---------------------------------------------------------------------------- +bool reader_t::read_program_headers() +{ + if ( !header.has_pht() ) + return false; + input_status_t save_excursion(*this); + if ( save_excursion.seek(header.e_phoff) == -1 ) + return false; + + int count = header.e_phnum; + validate_array_count_or_die(get_linput(), count, header.e_phentsize, "PHT entries"); + pheaders.resize(count); + + pheaders.initialized = true; + + elf_phdr_t *dyn_phdr = NULL; + for ( int i = 0; i < count; i++ ) + { + if ( !seek_to_program_header(i) ) + return false; + + elf_phdr_t *phdr = pheaders.get(i); +#define _safe(expr) \ + do \ + { \ + if ( expr < 0 ) \ + { \ + pheaders.resize(i == 0 ? 0 : i-1); \ + return false; \ + } \ + } while ( false ) + _safe(read_word(&phdr->p_type)); + if ( is_64() ) + _safe(read_word(&phdr->p_flags)); + _safe(read_off(&phdr->p_offset)); + _safe(read_addr(&phdr->p_vaddr)); + _safe(read_addr(&phdr->p_paddr)); + _safe(read_xword(&phdr->p_filesz)); + _safe(read_xword(&phdr->p_memsz)); + if ( !is_64() ) + _safe(read_word(&phdr->p_flags)); + _safe(read_xword(&phdr->p_align)); +#undef _safe + + switch ( phdr->p_type ) + { + case PT_LOAD: + add_mapping(*phdr); + + // ELF_Format.pdf page 2-4 + // The base address in ELF is "the lowest virtual address associated + // with the memory image of the program's object file". + if ( phdr->p_vaddr < pheaders.get_image_base() ) + { + // NOTE The default maximum page size is processor specific. + // The ELF standard vaguely mentions ("Program Loading") + // that 4 KB is the maximum page size for the SYSTEM V + // architecture, so we use this value. + const ea_t maximum_page_size = 0x1000; + // Truncate the memory address to the nearest multiple of the + // maximum page size. + ea_t image_base = phdr->p_vaddr & ~(maximum_page_size - 1); + pheaders.set_image_base(image_base); + } + + break; + case PT_DYNAMIC: + dyn_phdr = phdr; + break; + } + } + + if ( dyn_phdr != NULL ) + { + // in some files, p_filesz is 0, so take max of the two + // TODO: use the size of the surrounding PT_LOAD segment, + // since the dynamic loader does not use the size field + size_t dsize = qmax(dyn_phdr->p_filesz, dyn_phdr->p_memsz); + // p_offset may be wrong, always use p_vaddr + size_t fileoff = file_offset(dyn_phdr->p_vaddr); + pheaders.set_dynlink_table_info(fileoff, dyn_phdr->p_vaddr, dsize, -1); + } + + return true; +} + +//---------------------------------------------------------------------------- +void reader_t::set_sh_strtab( + dynamic_info_t::entry_t &strtab, + const elf_shdr_t &strtab_sh, + bool replace) +{ + // we don't check that type of section should be SHT_STRTAB, + // we just reject illegal section type + if ( strtab_sh.sh_type == SHT_NULL + || strtab_sh.sh_type == SHT_REL + || strtab_sh.sh_type == SHT_RELA + || strtab_sh.sh_type == SHT_DYNAMIC + || strtab_sh.sh_type == SHT_DYNSYM + || strtab_sh.sh_type == SHT_SYMTAB ) + { + msg("Illegal type %s of the string table section\n", + sections.sh_type_qstr(strtab_sh.sh_type).c_str()); + return; + } + if ( strtab_sh.sh_offset == 0 ) + { + msg("Illegal offset of the string table section\n"); + return; + } + // store the string table info + if ( strtab.is_valid() ) + { + if ( strtab.offset == strtab_sh.sh_offset ) + return; + warning("AUTOHIDE SESSION\n" + "More than one string table for %ssymbols, " + "using one at offset %08" FMT_64 "X", + &strtab == &dyn_strtab ? "dynamic linking " : "", + replace ? strtab_sh.sh_offset : strtab.offset); + if ( !replace ) + return; + } + strtab.offset = strtab_sh.sh_offset; + strtab.addr = strtab_sh.sh_addr; + strtab.size = strtab_sh.sh_size; +} + +//---------------------------------------------------------------------------- +void reader_t::set_di_strtab( + dynamic_info_t::entry_t &strtab, + const dynamic_info_t::entry_t &strtab_di) +{ + if ( !strtab_di.is_valid() ) + return; + if ( strtab.is_valid() ) + { + if ( strtab.offset == strtab_di.offset ) + return; + warning("The dynamic section string table " + "from section header (%08" FMT_64 "X) differs " + "from DT_STRTAB's one (%08" FMT_64 "X), " + "using the latter", + strtab.offset, + strtab_di.offset); + } + strtab = strtab_di; +} + +//---------------------------------------------------------------------------- +bool reader_t::read_notes(notes_t *notes) +{ + notes->clear(); + + if ( sections.initialized ) + { + for ( elf_shdrs_t::const_iterator p=sections.begin(); p != sections.end(); ++p ) + { + const elf_shdr_t &sh = *p; + if ( sh.sh_type != SHT_NOTE ) + continue; + bytevec_t buf; + sections.read_file_contents(&buf, sh); + notes->add(buf); + } + } + + if ( pheaders.initialized ) + { + for ( elf_phdrs_t::const_iterator q=pheaders.begin(); q != pheaders.end(); ++q ) + { + const elf_phdr_t &p = *q; + if ( p.p_type != PT_NOTE ) + continue; + bytevec_t buf; + pheaders.read_file_contents(&buf, p); + notes->add(buf); + } + } + + notes->initialized = true; + return true; +} + +//---------------------------------------------------------------------------- +elf_sym_idx_t reader_t::rel_info_index(const elf_rela_t &r) const +{ + if ( is_64() && !is_msb() && is_mips() ) + { + // MIPS64 does not use 64-bit r_info but always puts symbol index at low address + // so for LE we need to return low part of r_info + return uint32(r.r_info); + } + if ( is_64() ) + return ELF64_R_SYM(r.r_info); + else + return ELF32_R_SYM(r.r_info); +} + +//---------------------------------------------------------------------------- +uint32 reader_t::rel_info_type(const elf_rela_t &r) const +{ + if ( is_64() && !is_msb() && is_mips() ) + { + // MIPS64 does not use a 64-bit r_info but always puts symbol index at low address + // so in case of LE we need to return the high part of r_info + // we also need to convert it to BE + // so that macros like ELF64_MIPS_R_TYPE work properly + return swap32(r.r_info>>32); + } + if ( is_64() ) + return ELF64_R_TYPE(r.r_info); + else + return ELF32_R_TYPE(r.r_info); +} + +//---------------------------------------------------------------------------- +void reader_t::set_rel_info_index(elf_rela_t *r, uint32 symidx) const +{ + if ( !is_64() ) + { + r->r_info = ELF32_R_INFO(uint64(symidx), ELF32_R_TYPE(r->r_info)); + } + else if ( !is_msb() && is_mips() ) + { + // MIPS64 does not use the 64-bit r_info, but always puts the symbol + // index at the low address, so for LE we need to update the low part of + // r_info + r->r_info &= ~0xFFFFFFFF; + r->r_info |= uint64(symidx) << 32; + } + else + { + r->r_info &= 0xFFFFFFFF; + r->r_info |= symidx; + } +} + +//---------------------------------------------------------------------------- +void reader_t::set_rel_info_type(elf_rela_t *r, uint32 type) const +{ + if ( !is_64() ) + { + r->r_info = ELF32_R_INFO(ELF32_R_SYM(r->r_info), type); + } + else if ( !is_msb() && is_mips() ) + { + // MIPS64 does not use the 64-bit r_info, but always puts the symbol + // index at the low address, so for LE we need to update the high part + // of r_info. + // we also need to convert it to BE + r->r_info &= 0xFFFFFFFF; + r->r_info |= uint64(swap32(type)) << 32; + } + else + { + r->r_info &= ~0xFFFFFFFF; + r->r_info |= type; + } +} + +//---------------------------------------------------------------------------- +const char *reader_t::file_type_str() const +{ + const char *file_type = "Unknown"; + switch ( header.e_type ) + { + case ET_NONE: file_type = "None"; break; + case ET_REL: file_type = "Relocatable"; break; + case ET_EXEC: file_type = "Executable"; break; + case ET_DYN: file_type = "Shared object"; break; + case ET_CORE: file_type = "Core file"; break; + case ET_LOPROC: file_type = "Processor specific"; break; + case ET_HIPROC: file_type = "Processor specific"; break; + case ET_IRX: + if ( is_mips() ) + file_type = "PS2 IRX"; + break; + case ET_PSPEXEC: + if ( is_mips() ) + file_type = "PSP executable"; + break; + case ET_PS3PRX: + if ( header.e_machine == EM_PPC64 ) + file_type = "Sony PS3 PRX file"; + break; + } + return file_type; +} + +//---------------------------------------------------------------------------- +const char *reader_t::os_abi_str() const +{ + uint8 os_abi = get_ident().osabi; + const char *abi; + switch ( os_abi ) + { + case ELFOSABI_NONE: abi = "UNIX System V ABI"; break; + case ELFOSABI_HPUX: abi = "HP-UX operating system"; break; + case ELFOSABI_NETBSD: abi = "NetBSD"; break; + case ELFOSABI_LINUX: abi = "GNU/Linux"; break; + case ELFOSABI_HURD: abi = "GNU/Hurd"; break; + case ELFOSABI_SOLARIS: abi = "Solaris"; break; + case ELFOSABI_AIX: abi = "AIX"; break; + case ELFOSABI_IRIX: abi = "IRIX"; break; + case ELFOSABI_FREEBSD: abi = "FreeBSD"; break; + case ELFOSABI_TRU64: abi = "TRU64 UNIX"; break; + case ELFOSABI_MODESTO: abi = "Novell Modesto"; break; + case ELFOSABI_OPENBSD: abi = "OpenBSD"; break; + case ELFOSABI_OPENVMS: abi = "OpenVMS"; break; + case ELFOSABI_NSK: abi = "Hewlett-Packard Non-Stop Kernel"; break; + case ELFOSABI_AROS: abi = "Amiga Research OS"; break; + case ELFOSABI_ARM: abi = "ARM"; break; + case ELFOSABI_STANDALONE: abi = "Standalone (embedded) application"; break; + case ELFOSABI_CELLOSLV2: + if ( header.e_machine == EM_PPC64 ) + { + abi = "PS3 Cell OS lv2"; + break; + } + // fall through + default: + abi = "Unknown"; + break; + } + return abi; +} + +//---------------------------------------------------------------------------- +const char *reader_t::machine_name_str() const +{ + uint32 m = get_header().e_machine; + switch ( m ) + { + case EM_NONE: return "<No machine>"; + case EM_M32: return "AT & T WE 32100"; + case EM_SPARC: return "SPARC"; + case EM_386: return "Intel 386"; + case EM_68K: return "Motorola 68000"; + case EM_88K: return "Motorola 88000"; + case EM_486: return "Intel 486"; + case EM_860: return "Intel 860"; + case EM_MIPS: return "MIPS"; + case EM_S370: return "IBM System370"; + case EM_MIPS_RS3_BE: return "MIPS R3000 Big Endian"; + case EM_PARISC: return "PA-RISC"; + case EM_VPP550: return "Fujitsu VPP500"; + case EM_SPARC32PLUS: return "SPARC v8+"; + case EM_I960: return "Intel 960"; + case EM_PPC: return "PowerPC"; + case EM_PPC64: return "PowerPC 64"; + case EM_S390: return "IBM S/390"; + case EM_S390_OLD: return "IBM S/390 (old magic)"; + case EM_SPU: return "Cell BE SPU"; + case EM_CISCO7200: return "Cisco 7200 Series Router (MIPS)"; + case EM_CISCO3620: return "Cisco 3620/3640 Router (MIPS)"; + case EM_V800: return "NEC V800 or Renesas RH850"; + case EM_FR20: return "Fujitsu FR20"; + case EM_RH32: return "TRW RH-22"; + case EM_MCORE: return "Motorola M*Core"; + case EM_ARM: return "ARM"; + case EM_OLD_ALPHA: return "Digital Alpha"; + case EM_SH: return "SuperH"; + case EM_SPARC64: return "SPARC 64"; + case EM_TRICORE: return "Siemens Tricore"; + case EM_ARC: return "ARC"; + case EM_H8300: return "H8/300"; + case EM_H8300H: return "H8/300H"; + case EM_H8S: return "Hitachi H8S"; + case EM_H8500: return "H8/500"; + case EM_IA64: return "Itanium IA64"; + case EM_MIPS_X: return "Stanford MIPS-X"; + case EM_COLDFIRE: return "Coldfire"; + case EM_6812: return "MC68HC12"; + case EM_MMA: return "Fujitsu MMA"; + case EM_PCP: return "Siemens PCP"; + case EM_NCPU: return "Sony nCPU"; + case EM_NDR1: return "Denso NDR1"; + case EM_STARCORE: return "Star*Core"; + case EM_ME16: return "Toyota ME16"; + case EM_ST100: return "ST100"; + case EM_TINYJ: return "TinyJ"; + case EM_X86_64: return "x86-64"; + case EM_PDSP: return "PDSP"; + case EM_PDP10: return "DEC PDP-10"; + case EM_PDP11: return "DEC PDP-11"; + case EM_FX66: return "Siemens FX66"; + case EM_ST9: return "ST9+"; + case EM_ST7: return "ST7"; + case EM_68HC16: return "MC68HC16"; + case EM_6811: return "MC68HC11"; + case EM_68HC08: return "MC68HC08"; + case EM_68HC05: return "MC68HC05"; + case EM_SVX: return "Silicon Graphics SVx"; + case EM_ST19: return "ST19"; + case EM_VAX: return "VAX"; + case EM_CRIS: return "CRIS"; + case EM_JAVELIN: return "Infineon Javelin"; + case EM_FIREPATH: return "Element 14 Firepath"; + case EM_ZSP: return "ZSP"; + case EM_MMIX: return "MMIX"; + case EM_HUANY: return "Harvard HUANY"; + case EM_PRISM: return "SiTera Prism"; + case EM_AVR: return "Atmel"; + case EM_FR: return "Fujitsu FR"; + case EM_D10V: return "Mitsubishi D10V"; + case EM_D30V: return "Mitsubishi D30V"; + case EM_V850: // (GNU compiler) + case EM_CYGNUS_V850: + case EM_NECV850: return "NEC V850"; // (NEC compilers) + case EM_NECV850E: return "NEC v850E"; + case EM_NECV850E2: return "NEC v850E2"; + case EM_NECV850ES: return "NEC v850ES"; + case EM_NECV850E2R1: return "NEC v850E2R1"; + case EM_NECV850E2R2: return "NEC v850E2R2"; + case EM_NECV850E2R3: return "NEC v850E2R3"; + case EM_NECV850E2R4: return "NEC v850E2R4"; + case EM_NECV850E3V5: return "NEC v850E3V5"; + case EM_M32R: return "M32R"; + case EM_MN10300: return "MN10300"; + case EM_MN10200: return "MN10200"; + case EM_PJ: return "picoJava"; + case EM_OPENRISC : return "OpenRISC"; + case EM_ARCOMPACT: return "ARCompact"; + case EM_XTENSA: return "Xtensa"; + case EM_VIDEOCORE: return "VideoCore"; + case EM_TMM_GPP: return "Thompson GPP"; + case EM_NS32K: return "NS 32000"; + case EM_TPC: return "TPC"; + case EM_SNP1K: return "SNP 1000"; + case EM_ST200: return "ST200"; + case EM_IP2K: return "IP2022"; + case EM_MAX: return "MAX"; + case EM_CR: return "CompactRISC"; + case EM_F2MC16: return "F2MC16"; + case EM_MSP430: return "MSP430"; + case EM_BLACKFIN: return "ADI Blackfin"; + case EM_SE_C33: return "S1C33"; + case EM_SEP: return "SEP"; + case EM_ARCA: return "Arca"; + case EM_UNICORE: return "Unicore"; + case EM_EXCESS: return "eXcess"; + case EM_DXP: return "Icera DXP"; + case EM_ALTERA_NIOS2: return "Nios II"; + case EM_CRX: return "CRX"; + case EM_XGATE: return "XGATE"; + case EM_C166: return "C16x/XC16x/ST10"; + case EM_M16C: return "M16C"; + case EM_DSPIC30F: return "dsPIC30F"; + case EM_CE: return "Freescale Communication Engine"; + case EM_M32C: return "M32C"; + case EM_TSK3000: return "TSK3000"; + case EM_RS08: return "RS08"; + case EM_ECOG2: return "eCOG2"; + case EM_SCORE: return "Sunplus Score"; + case EM_DSP24: return "NJR DSP24"; + case EM_VIDEOCORE3: return "VideoCore III"; + case EM_LATTICEMICO32: return "Lattice Mico32"; + case EM_SE_C17: return "C17"; + case EM_MMDSP_PLUS: return "MMDSP"; + case EM_CYPRESS_M8C: return "M8C"; + case EM_R32C: return "R32C"; + case EM_TRIMEDIA: return "TriMedia"; + case EM_QDSP6: return "QDSP6"; + case EM_8051: return "i8051"; + case EM_STXP7X: return "STxP7x"; + case EM_NDS32: return "NDS32"; + case EM_ECOG1X: return "eCOG1X"; + case EM_MAXQ30: return "MAXQ30"; + case EM_XIMO16: return "NJR XIMO16"; + case EM_MANIK: return "M2000"; + case EM_CRAYNV2: return "Cray NV2"; + case EM_RX: return "RX"; + case EM_METAG: return "Imagination Technologies META"; + case EM_MCST_ELBRUS: return "MCST Elbrus"; + case EM_ECOG16: return "eCOG16"; + case EM_CR16: return "CompactRISC 16-bit"; + case EM_ETPU: return "Freescale ETPU"; + case EM_SLE9X: return "SLE9X"; + case EM_L1OM: return "Intel L1OM"; + case EM_K1OM: return "Intel K1OM"; + case EM_INTEL182: return "Intel Reserved (182)"; + case EM_AARCH64: return "ARM64"; + case EM_ARM184: return "ARM Reserved (184)"; + case EM_AVR32: return "AVR32"; + case EM_STM8: return "STM8"; + case EM_TILE64: return "Tilera TILE64"; + case EM_TILEPRO: return "Tilera TILEPro"; + case EM_MICROBLAZE: return "MicroBlaze"; + case EM_CUDA: return "CUDA"; + case EM_TILEGX: return "Tilera TILE-Gx"; + case EM_CLOUDSHIELD: return "CloudShield"; + case EM_COREA_1ST: return "Core-A 1st gen"; + case EM_COREA_2ND: return "Core-A 2nd gen"; + case EM_ARC_COMPACT2: return "ARCompactV2"; + case EM_OPEN8: return "Open8"; + case EM_RL78: return "RL78"; + case EM_VIDEOCORE5: return "VideoCore V"; + case EM_78K0R: return "78K0R"; + case EM_56800EX: return "Freescale 56800EX"; + case EM_BA1: return "Beyond BA1"; + case EM_BA2: return "Beyond BA2"; + case EM_XCORE: return "XMOS xCORE"; + case EM_CYGNUS_POWERPC: return "PowerPC"; + case EM_ALPHA: return "DEC Alpha"; + case EM_TI_C6000: return "TMS320C6"; + case EM_RISCV: return "Risc-V"; + default: return nullptr; + } +} + +//---------------------------------------------------------------------------- +qstring reader_t::get_machine_name() const +{ + qstring s = machine_name_str(); + if ( s.empty() ) + s.sprnt("Unknown CPU [%u]", get_header().e_machine); + return s; +} + +//---------------------------------------------------------------------------- +bool reader_t::read_prelink_base(uint32 *base) +{ + int64 fsize = size(); + input_status_t save_excursion(*this); + if ( save_excursion.seek(fsize - 4) == -1 ) + return false; + + char tag[4]; + bool ok = false; + if ( qlread(li, tag, 4) == 4 ) + { + if ( memcmp(tag, "PRE ", 4) == 0 ) + { + if ( qlseek(li, fsize - 8) != -1 && read_word(base) >= 0 ) + ok = true; + } + } + + return ok; +} + +//---------------------------------------------------------------------------- +bool reader_t::get_string_at(qstring *out, uint64 offset) const +{ + input_status_t save_excursion(*this); + if ( save_excursion.seek(offset) == -1 ) + { + out->sprnt("bad offset %08x", low(offset)); + return false; + } + + bool ret = true; + out->clear(); + char buffer[100]; + while ( true ) + { + int read = qlread(li, buffer, sizeof(buffer)); + if ( read < 0 ) + { + out->append("{truncated name}"); + ret = false; + break; + } + + // Find the position of the trailing zero + int pos; + for ( pos = 0; pos < read && buffer[pos] != '\0'; pos++ ) + ; + + out->append(buffer, pos); + if ( pos < sizeof(buffer) ) + break; + } + return ret; +} + +//---------------------------------------------------------------------------- +elf_shndx_t reader_t::get_shndx_at(uint64 offset) const +{ + input_status_t save_excursion(*this); + if ( save_excursion.seek(offset) == -1 ) + return 0; + CASSERT(sizeof(elf_shndx_t) == sizeof(uint32)); + uint32 res; + if ( read_word(&res) < 0 ) + return 0; + return res; +} + +//-------------------------------------------------------------------------- +// Fills 'out' with either a fake entry from the DHT or an entry from the SHT. +static bool get_versym_section( + elf_shdr_t *out, + slice_type_t *slice_type, + const reader_t &reader, + wks_t sht_idx, + const dynamic_info_t &di, + dynamic_info_type_t dht_idx, + bool use_pht) +{ + *slice_type = SLT_INVALID; + if ( use_pht ) + { + if ( di.fill_section_header(out, dht_idx) ) + *slice_type = SLT_DYNSYM; + } + else + { + const elf_shdr_t *sht_entry = reader.sections.get_wks(sht_idx); + if ( sht_entry != NULL ) + { + *out = *sht_entry; + if ( sht_entry->sh_link == reader.sections.get_index(WKS_SYMTAB) + && reader.symbols.slice_size(SLT_SYMTAB) != 0 ) + { + *slice_type = SLT_SYMTAB; + } + else if ( sht_entry->sh_link == reader.sections.get_index(WKS_DYNSYM) + && reader.symbols.slice_size(SLT_DYNSYM) != 0 ) + { + *slice_type = SLT_DYNSYM; + } + } + } + return *slice_type != SLT_INVALID; +} + +//---------------------------------------------------------------------------- +// Helper class for reading version info sections. DT_VERDEF and DT_VERNEED +// have similar structures for reading main and auxiliary entries. +template <class T_entry, class T_aux> +struct elf_ver_parser_t +{ + const reader_t &reader; + + elf_ver_parser_t(const reader_t &_reader) + : reader(_reader) + {} + + virtual void entry_cb(const T_entry &, int64, size_t) = 0; + virtual void aux_cb(const T_aux &, int64, size_t) = 0; + + void parse(int64 offset, size_t size) + { + int64 orig_offset = offset; + input_status_t save_excursion(reader); + int64 end = offset + size; + size_t entry_idx = 0; + std::set<int64> entry_seen; + while ( offset < end && entry_seen.insert(offset).second ) + { + T_entry entry; + if ( save_excursion.seek(offset) == -1 || !entry.read(reader) ) + break; + + entry_cb(entry, offset - orig_offset, entry_idx++); + + int64 aux_offset = offset + entry.aux(); + size_t aux_idx = 0; + std::set<int64> aux_seen; + while ( aux_offset < end + && aux_seen.insert(aux_offset).second + && aux_idx < entry.cnt() ) + { + T_aux aux; + if ( save_excursion.seek(aux_offset) == -1 || !aux.read(reader) ) + break; + + aux_cb(aux, aux_offset - orig_offset, aux_idx++); + + aux_offset += aux.next(); + } + + offset += entry.next(); + } + } +}; + +//---------------------------------------------------------------------------- +bool reader_t::read_symbol_versions( + elf_symbol_version_t *symver, + const dynamic_info_t &di, + bool use_pht) +{ + elf_shdr_t sh; + slice_type_t st; + + // Read version requirement entries from DT_VERNEED + struct elf_verneed_parser_t + : public elf_ver_parser_t<elf_verneed_t, elf_vernaux_t> + { + typedef elf_ver_parser_t<elf_verneed_t, elf_vernaux_t> inherited; + + elf_symbol_version_t &symver; + slice_type_t st; + elf_verneed_parser_t( + const reader_t &_reader, + elf_symbol_version_t &_symver, + slice_type_t _st) + : inherited(_reader), + symver(_symver), + st(_st) + { + } + + virtual void entry_cb(const elf_verneed_t &verneed, int64 offset, size_t) override + { + symbol_verneed_t &reqfile = symver.reqs.push_back(); + reqfile.offset = offset; + // TODO check verneed.vn_version + reqfile.name = symver.file_names.size(); + qstring &fname = symver.file_names.push_back(); + reader.get_name(&fname, st, verneed.vn_file); + } + + virtual void aux_cb(const elf_vernaux_t &vernaux, int64 offset, size_t) override + { + symbol_verneed_t &reqfile = symver.reqs.back(); + symbol_vernaux_t &reqver = reqfile.auxs.push_back(); + reqver.offset = offset; + + reqver.name = symver.version_names.size(); + qstring &vname = symver.version_names.push_back(); + reader.get_name(&vname, st, vernaux.vna_name); + + uint16 idx = vernaux.vna_other & ~0x8000; + if ( idx != 0 ) + { + vermap_item_t &vermap_item = symver.vermap[idx]; + vermap_item.fname_idx = reqfile.name; + vermap_item.vname_idx = reqver.name; + } + } + }; + + if ( get_versym_section(&sh, &st, *this, WKS_VERNEED, di, DIT_VERNEED, use_pht) ) + { + elf_verneed_parser_t parser(*this, *symver, st); + parser.parse(sh.sh_offset, sh.sh_size); + } + + // Read version definition entries from DT_VERDEF + struct elf_verdef_parser_t + : public elf_ver_parser_t<elf_verdef_t, elf_verdaux_t> + { + typedef elf_ver_parser_t<elf_verdef_t, elf_verdaux_t> inherited; + + elf_symbol_version_t &symver; + slice_type_t st; + elf_verdef_parser_t( + const reader_t &_reader, + elf_symbol_version_t &_symver, + slice_type_t _st) + : inherited(_reader), + symver(_symver), + st(_st) + { + } + + virtual void entry_cb(const elf_verdef_t &verdef, int64 offset, size_t) override + { + symbol_verdef_t &deffile = symver.defs.push_back(); + deffile.offset = offset; + // TODO check verdef.vd_version + deffile.flags = verdef.vd_flags; + deffile.ndx = verdef.vd_ndx; + } + + virtual void aux_cb(const elf_verdaux_t &verdaux, int64 offset, size_t) override + { + symbol_verdef_t &deffile = symver.defs.back(); + symbol_verdaux_t &defver = deffile.auxs.push_back(); + defver.offset = offset; + + if ( (deffile.flags & VER_FLG_BASE) != 0 ) + { + symver.def_base = symver.file_names.size(); + qstring &fname = symver.file_names.push_back(); + reader.get_name(&fname, st, verdaux.vda_name); + } + + defver.name = symver.version_names.size(); + qstring &vname = symver.version_names.push_back(); + reader.get_name(&vname, st, verdaux.vda_name); + + uint16 idx = deffile.ndx; + if ( idx != 0 && deffile.auxs.size() == 1 ) + { + vermap_item_t &vermap_item = symver.vermap[idx]; + vermap_item.fname_idx = symver.def_base; + vermap_item.vname_idx = defver.name; + } + } + }; + + if ( get_versym_section(&sh, &st, *this, WKS_VERDEF, di, DIT_VERDEF, use_pht) ) + { + elf_verdef_parser_t parser(*this, *symver, st); + parser.parse(sh.sh_offset, sh.sh_size); + } + + // Read version symbol entries from DT_VERSYM + if ( get_versym_section(&sh, &st, *this, WKS_VERSYM, di, DIT_VERSYM, use_pht) ) + { + input_status_t save_excursion(*this); + if ( save_excursion.seek(sh.sh_offset) != -1 ) + for ( size_t i = 0; i < sh.sh_size / sizeof(uint16); i++ ) + if ( read_half(&symver->symbols.push_back()) < 0 ) + break; + } + + return true; +} + +//---------------------------------------------------------------------------- +void reader_t::validate_section_size( + uint64 *count, + size_t *entsize, + const elf_shdr_t §ion, + const char *counter_name) +{ + *entsize = section.sh_entsize == 0 ? 1 : section.sh_entsize; + *count = section.sh_size / *entsize; + validate_array_count( + get_linput(), + count, + *entsize, + counter_name, + section.sh_offset); +} + +//---------------------------------------------------------------------------- +bool reader_t::read_dynamic_info_tags( + dyninfo_tags_t *dyninfo_tags, + const dynamic_linking_tables_t &dlt) +{ + // assert: dlt.is_valid() + if ( dlt.size == 0 ) + return false; + + // read all 'elf_dyn_t' entries + elf_dyn_t *d; + const size_t isize = stdsizes.entries.dyn; + elf_shdr_t fake_section; + fake_section.sh_type = SHT_DYNAMIC; + fake_section.sh_offset = dlt.offset; + fake_section.sh_size = dlt.size; + fake_section.sh_entsize = isize; + uint64 count; + size_t entsize; + validate_section_size(&count, &entsize, fake_section, "Dynamic info size"); + if ( count == 0 ) + return false; + buffered_input_t<elf_dyn_t> dyn_input(*this, fake_section.sh_offset, count, entsize); + while ( dyn_input.next(d) ) + { + dyninfo_tags->push_back(*d); + if ( d->d_tag == DT_NULL ) + break; + } + return true; +} + +//---------------------------------------------------------------------------- +bool reader_t::parse_dynamic_info( + dynamic_info_t *dyninfo, + const dyninfo_tags_t &dyninfo_tags) +{ + dyninfo->initialize(*this); + + sizevec_t offsets; + + // populate dyninfo structure + for ( dyninfo_tags_t::const_iterator dyn = dyninfo_tags.begin(); + dyn != dyninfo_tags.end(); + ++dyn ) + { + dynamic_info_type_t di_type = DIT_TYPE_COUNT; + switch ( dyn->d_tag ) + { + case DT_STRTAB: di_type = DIT_STRTAB; break; + case DT_SYMTAB: di_type = DIT_SYMTAB; break; + case DT_REL: di_type = DIT_REL; break; + case DT_RELA: di_type = DIT_RELA; break; + case DT_JMPREL: di_type = DIT_PLT; break; + case DT_HASH: di_type = DIT_HASH; break; + case DT_GNU_HASH: di_type = DIT_GNU_HASH; break; + case DT_PREINIT_ARRAY: di_type = DIT_PREINIT_ARRAY; break; + case DT_INIT_ARRAY: di_type = DIT_INIT_ARRAY; break; + case DT_FINI_ARRAY: di_type = DIT_FINI_ARRAY; break; + case DT_VERDEF: di_type = DIT_VERDEF; break; + case DT_VERNEED: di_type = DIT_VERNEED; break; + case DT_VERSYM: di_type = DIT_VERSYM; break; + case DT_ANDROID_REL: + if ( is_arm() ) + di_type = DIT_ANDROID_REL; + break; + case DT_ANDROID_RELA: + if ( is_arm() ) + di_type = DIT_ANDROID_RELA; + break; + } + if ( di_type != DIT_TYPE_COUNT ) + { + dynamic_info_t::entry_t &entry = dyninfo->entries[di_type]; + entry.offset = file_offset(dyn->d_un); + offsets.push_back(entry.offset); + entry.addr = dyn->d_un; + continue; + } + + switch ( dyn->d_tag ) + { + case DT_STRSZ: di_type = DIT_STRTAB; break; + case DT_RELSZ: di_type = DIT_REL; break; + case DT_RELASZ: di_type = DIT_RELA; break; + case DT_ANDROID_RELSZ: di_type = DIT_ANDROID_REL; break; + case DT_ANDROID_RELASZ: di_type = DIT_ANDROID_RELA; break; + case DT_PLTRELSZ: di_type = DIT_PLT; break; + case DT_PREINIT_ARRAYSZ: di_type = DIT_PREINIT_ARRAY; break; + case DT_INIT_ARRAYSZ: di_type = DIT_INIT_ARRAY; break; + case DT_FINI_ARRAYSZ: di_type = DIT_FINI_ARRAY; break; + } + if ( di_type != DIT_TYPE_COUNT ) + { + dyninfo->entries[di_type].size = dyn->d_un; + continue; + } + + switch ( dyn->d_tag ) + { + case DT_SYMENT: di_type = DIT_SYMTAB; break; + case DT_RELENT: di_type = DIT_REL; break; + case DT_RELAENT: di_type = DIT_RELA; break; + } + if ( di_type != DIT_TYPE_COUNT ) + { + dyninfo->entries[di_type].entsize = dyn->d_un; + continue; + } + + switch ( dyn->d_tag ) + { + case DT_VERDEFNUM: di_type = DIT_VERDEF; break; + case DT_VERNEEDNUM: di_type = DIT_VERNEED; break; + } + if ( di_type != DIT_TYPE_COUNT ) + { + dyninfo->entries[di_type].info = dyn->d_un; + continue; + } + + switch ( dyn->d_tag ) + { + case DT_PLTREL: + dyninfo->plt_rel_type = uint32(dyn->d_un); + if ( dyninfo->plt_rel_type != DT_REL && dyninfo->plt_rel_type != DT_RELA ) + { + if ( !handle_error(*this, BAD_DYN_PLT_TYPE, dyninfo->plt_rel_type) ) + return false; + } + continue; + + case DT_INIT: + case DT_FINI: + case DT_PLTGOT: + offsets.push_back(file_offset(dyn->d_un)); + continue; + + default: + continue; + + case DT_NULL: + break; // end of list + } + break; + } + + // Guess size of sections that don't have an explicit size + dyninfo->symtab().guess_size(offsets); + dyninfo->hash().guess_size(offsets); + dyninfo->gnu_hash().guess_size(offsets); + dyninfo->verdef().guess_size(offsets); + dyninfo->verneed().guess_size(offsets); + dyninfo->versym().guess_size(offsets); + + return true; +} + +//---------------------------------------------------------------------------- +void reader_t::add_mapping(const elf_phdr_t &p) +{ + mapping_t &m = mappings.push_back(); + m.offset = p.p_offset; + m.size = p.p_filesz; + m.ea = p.p_vaddr; +} + +//---------------------------------------------------------------------------- +int64 reader_t::file_offset(uint64 ea) const +{ + for ( int i=0; i < mappings.size(); i++ ) + { + const mapping_t &cur = mappings[i]; + if ( cur.ea <= ea && (cur.ea + cur.size) > ea ) + return low(ea - cur.ea) + cur.offset; + } + + return -1; +} + +//---------------------------------------------------------------------------- +ea_t reader_t::file_vaddr(uint64 offset) const +{ + for ( int i=0; i < mappings.size(); i++ ) + { + const mapping_t &cur = mappings[i]; + if ( cur.offset <= offset && (cur.offset + cur.size) > offset ) + return low(offset - cur.offset) + cur.ea; + } + + return BADADDR; +} + +//---------------------------------------------------------------------------- +elf_shndx_t section_headers_t::get_index(wks_t wks) const +{ + QASSERT(20054, wks >= WKS_BSS && wks < WKS_LAST); + return wks_lut[int(wks)]; +} + +//---------------------------------------------------------------------------- +void section_headers_t::set_index(wks_t wks, elf_shndx_t index) +{ + QASSERT(20055, wks >= WKS_BSS && wks < WKS_LAST); + wks_lut[int(wks)] = index; +} + +//---------------------------------------------------------------------------- +const elf_shdr_t *section_headers_t::getn(elf_shndx_t index) const +{ + assert_initialized(); + + if ( index >= headers.size() ) + return NULL; + else + return &headers[index]; +} + +//---------------------------------------------------------------------------- +const elf_shdr_t *section_headers_t::get(uint32 sh_type, const char *name) const +{ + assert_initialized(); + + qstring n2; + for ( qvector<elf_shdr_t>::const_iterator it=begin(); it != end(); it++ ) + { + const elf_shdr_t &cur = *it; + if ( cur.sh_type == sh_type ) + { + n2.qclear(); + get_name(&n2, &cur); + if ( n2 == name ) + return &cur; + } + } + return NULL; +} + +//---------------------------------------------------------------------------- +const elf_shdr_t *section_headers_t::get_rel_for(elf_shndx_t index, bool *is_rela) const +{ + assert_initialized(); + if ( is_rela != NULL ) + *is_rela = false; + + QASSERT(20056, index > 0); + for ( elf_shdrs_t::const_iterator it=begin(); it != end(); it++ ) + { + // for REL/RELA sections, sh_info contains the index to which the relocations apply + if ( it->sh_info == index + && (it->sh_type == SHT_RELA || it->sh_type == SHT_REL) ) + { + // found it + if ( is_rela != NULL ) + *is_rela = it->sh_type == SHT_RELA; + return it; + } + } + return NULL; +} + +//---------------------------------------------------------------------------- +int section_headers_t::add(const elf_shdr_t §ion) +{ + headers.push_back(section); + return headers.size() - 1; +} + +//---------------------------------------------------------------------------- +bool section_headers_t::get_name(qstring *out, elf_shndx_t index) const +{ + assert_initialized(); + + if ( index >= headers.size() ) + return false; + else + return get_name(out, &headers[index]); +} + +//---------------------------------------------------------------------------- +bool section_headers_t::get_name(qstring *out, const elf_shdr_t *sh) const +{ + if ( sh == NULL || !strtab.is_valid() ) + return false; + return reader->get_name(out, strtab, sh->sh_name); +} + +//---------------------------------------------------------------------------- +bool reader_t::get_name( + qstring *out, + const dynamic_info_t::entry_t &strtab, + uint32 name_idx) const +{ + if ( !strtab.is_valid() ) + *out = "{no string table}"; + // cisco ios files have size 0 for the string section + else if ( strtab.size != 0 && name_idx >= strtab.size ) + out->sprnt("bad offset %08x", low(strtab.offset + name_idx)); + else + return get_string_at(out, strtab.offset + name_idx); + return false; +} + +//---------------------------------------------------------------------------- +bool reader_t::get_name( + qstring *out, + slice_type_t slice_type, + uint32 name_idx) const +{ + const dynamic_info_t::entry_t *strtab; + switch ( slice_type ) + { + case SLT_SYMTAB: + strtab = &sym_strtab; + break; + case SLT_DYNSYM: + strtab = &dyn_strtab; + break; + default: + INTERR(20086); + } + return get_name(out, *strtab, name_idx); //-V614 Potentially uninitialized pointer 'strtab' used +} + +//---------------------------------------------------------------------------- +const char *section_headers_t::sh_type_str(uint32 sh_type) const +{ +#define NM(tp) case SHT_##tp: return #tp +#define NM2(tp, nm) case SHT_##tp: return #nm + + // OS-specific types + uint8 os_abi = reader->get_ident().osabi; + if ( os_abi == ELFOSABI_SOLARIS ) + { + switch ( sh_type ) + { + NM(SUNW_ancillary); + NM(SUNW_capchain); + NM(SUNW_capinfo); + NM(SUNW_symsort); + NM(SUNW_tlssort); + NM(SUNW_LDYNSYM); + NM(SUNW_dof); + NM(SUNW_cap); + NM(SUNW_SIGNATURE); + NM(SUNW_ANNOTATE); + NM(SUNW_DEBUGSTR); + NM(SUNW_DEBUG); + NM(SUNW_move); + NM(SUNW_COMDAT); + NM(SUNW_syminfo); + NM2(SUNW_verdef, VERDEF); + NM2(SUNW_verneed, VERNEEDED); + NM2(SUNW_versym, VERSYMBOL); + } + } + else + { + switch ( sh_type ) + { + NM(GNU_INCREMENTAL_INPUTS); + NM(GNU_INCREMENTAL_SYMTAB); + NM(GNU_INCREMENTAL_RELOCS); + NM(GNU_INCREMENTAL_GOT_PLT); + NM(GNU_ATTRIBUTES); + NM(GNU_HASH); + NM(GNU_LIBLIST); + NM2(GNU_verdef, VERDEF); + NM2(GNU_verneed, VERNEEDED); + NM2(GNU_versym, VERSYMBOL); + } + } + + switch ( sh_type ) + { + NM(NULL); + NM(PROGBITS); + NM(SYMTAB); + NM(STRTAB); + NM(RELA); + NM(HASH); + NM(DYNAMIC); + NM(NOTE); + NM(NOBITS); + NM(REL); + NM(SHLIB); + NM(DYNSYM); + NM(COMDAT); + NM(INIT_ARRAY); + NM(FINI_ARRAY); + NM(PREINIT_ARRAY); + NM(GROUP); + NM(SYMTAB_SHNDX); + default: + { + if ( reader->is_arm() ) + { + switch ( sh_type ) + { + NM(ARM_EXIDX); + NM(ARM_PREEMPTMAP); + NM(ARM_ATTRIBUTES); + NM(ARM_DEBUGOVERLAY); + NM(ARM_OVERLAYSECTION); + NM(ANDROID_REL); + NM(ANDROID_RELA); + } + } + else if ( reader->is_mips() ) + { + switch ( sh_type ) + { + NM(MIPS_LIBLIST); + NM(MIPS_MSYM); + NM(MIPS_CONFLICT); + NM(MIPS_GPTAB); + NM(MIPS_UCODE); + NM(MIPS_DEBUG); + NM(MIPS_REGINFO); + NM(MIPS_IFACE); + NM(MIPS_CONTENT); + NM(MIPS_OPTIONS); + NM(MIPS_DWARF); + NM(MIPS_SYMBOL_LIB); + NM(MIPS_EVENTS); + NM2(DVP_OVERLAY_TABLE, MIPS_DVP_OVERLAY_TABLE); + NM2(DVP_OVERLAY, MIPS_DVP_OVERLAY); + NM(MIPS_IOPMOD); + NM(MIPS_PSPREL); + } + } + else if ( reader->get_header().e_machine == EM_PPC64 ) + { + switch ( sh_type ) + { + NM2(PS3PRX_RELA, PRXRELA); + } + } + break; + } + } + return nullptr; +#undef NM2 +#undef NM +} + +//------------------------------------------------------------------------- +qstring section_headers_t::sh_type_qstr(uint32 sh_type) const +{ + qstring s = sh_type_str(sh_type); + if ( s.empty() ) + s.sprnt("%X", sh_type); + return s; +} + +//------------------------------------------------------------------------- +uint64 section_headers_t::get_size_in_file(const elf_shdr_t &sh) const +{ + if ( sh.sh_type == SHT_NOBITS ) + return 0; + uint64 next_boundary = reader->size(); + // It may happen that we receive a section header that is _not_ part + // of the list of original section headers. E.g., when we load symbols + // from the dynamic-provided information. + const elf_shdr_t *next_sh = &sh + 1; + if ( next_sh >= begin() + && next_sh < end() + && next_sh->sh_offset < next_boundary + && next_sh->sh_offset >= sh.sh_offset ) + { + next_boundary = next_sh->sh_offset; + } + if ( sh.sh_offset >= next_boundary ) + return 0; + return qmin(sh.sh_size, next_boundary - sh.sh_offset); +} + +//------------------------------------------------------------------------- +void section_headers_t::read_file_contents( + bytevec_t *out, + const elf_shdr_t &sh) const +{ + uint64 nbytes = sh.sh_size; + qstring hdrname = "?"; + get_name(&hdrname, sh); + qstring text; + text.sprnt("Size of %s", hdrname.c_str()); + validate_array_count( + reader->get_linput(), + &nbytes, + 1, + text.c_str(), + sh.sh_offset); + out->resize(nbytes); + reader->seek(sh.sh_offset); + reader->safe_read(out->begin(), nbytes, /*apply_endianness=*/ false); +} + +//------------------------------------------------------------------------- +bool section_headers_t::read_gnu_debuglink( + qstring *out_link, + uint32 *out_crc) const +{ + const elf_shdr_t *s = get(SHT_PROGBITS, ".gnu_debuglink"); + bool found = s != NULL; + if ( found ) + { + bytevec_t buf; + read_file_contents(&buf, *s); + size_t sz = buf.size(); + found = sz > 4; + if ( found ) + { + if ( out_crc != NULL ) + { + uint32 crc = *(uint32 *)(buf.begin() + (sz - 4)); + if ( reader->get_ident().bytesex == ELFDATA2MSB ) + crc = swap32(crc); + *out_crc = crc; + } + sz -= 4; + if ( out_link != NULL ) + { + out_link->reserve(sz); + for ( size_t i=0; i < sz; ++i ) + { + uchar ch = buf[i]; + if ( ch == 0 ) + break; + out_link->append(ch); + } + } + } + } + return found; +} + +//------------------------------------------------------------------------- +// program_headers_t +//---------------------------------------------------------------------------- +const char *program_headers_t::p_type_str(uint32 p_type) const +{ +#define NM(tp) case PT_##tp: return #tp +#define NM2(tp, nm) case PT_##tp: return #nm + + // OS-specific types + uint8 os_abi = reader->get_ident().osabi; + if ( os_abi == ELFOSABI_SOLARIS ) + { + switch ( p_type ) + { + NM2(SUNW_UNWIND, UNWIND); + NM2(SUNW_EH_FRAME, EH_FRAME); + NM(SUNWBSS); + NM2(SUNWSTACK, STACK); + NM2(SUNWDTRACE, DTRACE); + NM(SUNWCAP); + } + } + else + { + switch ( p_type ) + { + NM2(GNU_EH_FRAME, EH_FRAME); + NM2(GNU_STACK, STACK); + NM2(GNU_RELRO, RO-AFTER); + } + } + + switch ( p_type ) + { + NM(NULL); + NM(LOAD); + NM(DYNAMIC); + NM(INTERP); + NM(NOTE); + NM(SHLIB); + NM(PHDR); + NM(TLS); + + NM2(PAX_FLAGS, PAX-FLAG); + + default: + { + uint32 m = reader->get_header().e_machine; + if ( m == EM_ARM ) + { + switch ( p_type ) + { + NM2(ARM_ARCHEXT, ARCHEXT); + NM2(ARM_EXIDX, EXIDX); + } + } + else if ( m == EM_AARCH64 ) + { + switch ( p_type ) + { + NM2(AARCH64_ARCHEXT, ARCHEXT); + NM2(AARCH64_UNWIND, EXIDX); + } + } + else if ( m == EM_IA64 ) + { + switch ( p_type ) + { + NM(HP_TLS); + NM(HP_CORE_NONE); + NM(HP_CORE_VERSION); + NM(HP_CORE_KERNEL); + NM(HP_CORE_COMM); + NM(HP_CORE_PROC); + NM(HP_CORE_LOADABLE); + NM(HP_CORE_STACK); + NM(HP_CORE_SHM); + NM(HP_CORE_MMF); + NM(HP_PARALLEL); + NM(HP_FASTBIND); + NM(HP_OPT_ANNOT); + NM(HP_HSL_ANNOT); + NM(HP_STACK); + NM(HP_CORE_UTSNAME); + NM(HP_LINKER_FOOTPRINT); + NM(IA_64_ARCHEXT); + NM(IA_64_UNWIND); + } + } + else if ( m == EM_MIPS ) + { + switch ( p_type ) + { + NM2(MIPS_IOPMOD, IOPMOD); + NM2(MIPS_EEMOD, EEMOD); + NM2(MIPS_PSPREL, PSPREL); + NM2(MIPS_PSPREL2, PSPREL2); + NM2(MIPS_REGINFO, REGINFO); + NM2(MIPS_RTPROC, RTPROC); + NM2(MIPS_OPTIONS, OPTIONS); + NM2(MIPS_ABIFLAGS, ABIFLAGS); + } + } + else if ( m == EM_PPC64 ) + { + switch ( p_type ) + { + case PHT_PS3PRX_RELA : return "PRXRELA"; + } + } + return nullptr; + } + } +#undef NM2 +#undef NM +} + +//---------------------------------------------------------------------------- +qstring program_headers_t::p_type_qstr(uint32 p_type) const +{ + qstring s = p_type_str(p_type); + if ( s.empty() ) + s.sprnt("%08X", p_type); + return s; +} + +//---------------------------------------------------------------------------- +uint64 program_headers_t::get_size_in_file(const elf_phdr_t &p) const +{ + assert_initialized(); + if ( p.p_type != PT_LOAD + && p.p_type != PT_INTERP + && p.p_type != PT_NOTE + && p.p_type != PT_PHDR ) + { + return 0; + } + + uint64 next_boundary = reader->size(); + if ( p.p_offset >= next_boundary ) + return 0; + + int idx = &p - begin(); + if ( idx > -1 && (idx+1) < pheaders.size() ) + { + const elf_phdr_t *np = CONST_CAST(program_headers_t*)(this)->get(idx+1); + if ( np->p_offset >= p.p_offset ) + next_boundary = np->p_offset; + } + return qmin(p.p_filesz, next_boundary - p.p_offset); +} + +//---------------------------------------------------------------------------- +void program_headers_t::read_file_contents( + bytevec_t *out, + const elf_phdr_t &p) const +{ + assert_initialized(); + + uint64 nbytes = p.p_filesz; + qstring text; + text.sprnt("Size of %s", p_type_qstr(p.p_type).c_str()); + validate_array_count( + reader->get_linput(), + &nbytes, + 1, + text.c_str(), + p.p_offset); + out->resize(nbytes); + reader->seek(p.p_offset); + reader->safe_read(out->begin(), nbytes, /*apply_endianness=*/ false); +} + +//---------------------------------------------------------------------------- +// Note Section +// +bool elf_note_t::unpack_sz( + size_t *out, + size_t *pstart, + const bytevec_t &buf, + bool mf) +{ + const size_t start = *pstart; + const size_t szel = sizeof(uint32); + if ( !is_add_ok(start, szel) || start + szel > buf.size() ) + return false; + + if ( out != nullptr ) + { + uint32 res = *(uint32 *)&buf[start]; + if ( mf ) + res = swap32(res); + *out = res; + } + *pstart += szel; + return true; +} + +//---------------------------------------------------------------------------- +bool elf_note_t::unpack_mem( + qstring *out, + const bytevec_t &buf, + size_t start, + size_t len, + bool as_strz) +{ + if ( !is_add_ok(start, len) || start + len > buf.size() ) + return false; + out->qclear(); + if ( as_strz ) + { + out->reserve(len); + for ( int i=0; i < len; ++i ) + { + char ch = buf[start + i]; + if ( ch == '\0' ) + break; + out->append(ch); + } + } + else + { + out->resize(len, '\0'); + memcpy(out->begin(), &buf[start], len); + } + return true; +} + +//---------------------------------------------------------------------------- +bool elf_note_t::unpack_strz( + qstring *out, + const bytevec_t &buf, + size_t start, + size_t len) +{ + return unpack_mem(out, buf, start, len, /*as_strz=*/ true); +} + +//---------------------------------------------------------------------------- +bool elf_note_t::unpack( + elf_note_t *entry, + size_t *start, + const bytevec_t &buf, + bool mf) +{ + size_t end = *start; + size_t namesz; + size_t descsz; + size_t type; + if ( !elf_note_t::unpack_sz(&namesz, &end, buf, mf) + || !elf_note_t::unpack_sz(&descsz, &end, buf, mf) + || !elf_note_t::unpack_sz(&type, &end, buf, mf) ) + { + return false; + } + + qstring name; + if ( !elf_note_t::unpack_strz(&name, buf, end, namesz) ) + return false; + end += align_up(namesz, 4); + + qstring desc; + if ( !elf_note_t::unpack_mem(&desc, buf, end, descsz) ) + return false; + end += align_up(descsz, 4); + + if ( entry != NULL ) + { + entry->name = name; + entry->desc = desc; + entry->type = type; + } + *start = end; + return true; +} + +//---------------------------------------------------------------------------- +void notes_t::add(const bytevec_t &buf) +{ + bool mf = reader->is_msb(); + size_t start = 0; + while ( start < buf.size() ) + { + elf_note_t &n = notes.push_back(); + if ( !elf_note_t::unpack(&n, &start, buf, mf) ) + { + notes.pop_back(); + break; + } + } +} + +//---------------------------------------------------------------------------- +bool notes_t::get_build_id(qstring *out) const +{ + assert_initialized(); + + for ( elf_notes_t::const_iterator p=notes.begin(); p != notes.end(); ++p ) + { + const elf_note_t &en = *p; + if ( en.name == NT_NAME_GNU && en.type == NT_GNU_BUILD_ID ) + { + int sz = en.desc.length(); + out->qclear(); + out->reserve(2*sz); + for ( int i=0; i < sz; ++i ) + out->cat_sprnt("%02x", (unsigned char)en.desc[i]); + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +const char *d_note_gnu_type_str(uint64 type) +{ +#define NM(tp) case tp: return #tp + switch ( type ) + { + NM(NT_GNU_ABI_TAG); + NM(NT_GNU_HWCAP); + NM(NT_GNU_BUILD_ID); + NM(NT_GNU_GOLD_VERSION); + NM(NT_GNU_PROPERTY_TYPE_0); + } + return NULL; +#undef NM +} + +//---------------------------------------------------------------------------- +const char *d_note_linux_type_str(uint64 type) +{ +#define NM(tp) case tp: return #tp + switch ( type ) + { + NM(NT_PRXFPREG); + NM(NT_PPC_VMX); + NM(NT_PPC_VSX); + NM(NT_PPC_TAR); + NM(NT_PPC_PPR); + NM(NT_PPC_DSCR); + NM(NT_PPC_EBB); + NM(NT_PPC_PMU); + NM(NT_PPC_TM_CGPR); + NM(NT_PPC_TM_CFPR); + NM(NT_PPC_TM_CVMX); + NM(NT_PPC_TM_CVSX); + NM(NT_PPC_TM_SPR); + NM(NT_PPC_TM_CTAR); + NM(NT_PPC_TM_CPPR); + NM(NT_PPC_TM_CDSCR); + NM(NT_386_TLS); + NM(NT_386_IOPERM); + NM(NT_X86_XSTATE); + NM(NT_S390_HIGH_GPRS); + NM(NT_S390_TIMER); + NM(NT_S390_TODCMP); + NM(NT_S390_TODPREG); + NM(NT_S390_CTRS); + NM(NT_S390_PREFIX); + NM(NT_S390_LAST_BREAK); + NM(NT_S390_SYSTEM_CALL); + NM(NT_S390_TDB); + NM(NT_S390_VXRS_LOW); + NM(NT_S390_VXRS_HIGH); + NM(NT_S390_GS_CB); + NM(NT_S390_GS_BC); + NM(NT_ARM_VFP); + NM(NT_ARM_TLS); + NM(NT_ARM_HW_BREAK); + NM(NT_ARM_HW_WATCH); + NM(NT_ARM_SVE); + } + return NULL; +#undef NM +} + +//---------------------------------------------------------------------------- +const char *d_note_core_type_str(uint64 type) +{ +#define NM(tp) case tp: return #tp + switch ( type ) + { + NM(NT_PRSTATUS); + NM(NT_FPREGSET); + NM(NT_PRPSINFO); + NM(NT_TASKSTRUCT); + NM(NT_AUXV); + NM(NT_SIGINFO); + NM(NT_FILE); + NM(NT_PSTATUS); + NM(NT_FPREGS); + NM(NT_PSINFO); + NM(NT_LWPSTATUS); + NM(NT_LWPSINFO); + NM(NT_WIN32PSTATUS); + } + return NULL; +#undef NM +} + +//---------------------------------------------------------------------------- +template<> void buffered_input_t<sym_rel>::start_reading() +{ + reader.get_arch_specific()->on_start_symbols(reader); +} + +//---------------------------------------------------------------------------- +template<> bool buffered_input_t<sym_rel>::read_item(sym_rel &storage) +{ + storage = sym_rel(); + + elf_sym_t &orig = storage.original; +#define _safe(expr) \ + do \ + { \ + if ( expr < 0 ) \ + return false; \ + } while ( 0 ) + _safe(reader.read_symbol(&orig)); + + ushort bind = ELF_ST_BIND(orig.st_info); + // assert: bind <= STB_HIPROC + if ( bind > STB_WEAK ) + { + CASSERT(STB_LOCAL < STB_WEAK && STB_GLOBAL < STB_WEAK); //-V590 expression is excessive + if ( reader.get_header().e_machine == EM_ARM && bind == STB_LOPROC+1 ) + // codewarrior for arm seems to use this binding type similar to local or weak + bind = STB_WEAK; + else if ( bind < STB_LOOS ) + bind = STB_INVALID; + } + + storage.bind = (uchar) bind; + storage.sec = 0; + storage.type = ELF_ST_TYPE(orig.st_info); + storage.value = orig.st_value + reader.get_load_bias(); + storage.size = orig.st_size; + return true; +} + +//---------------------------------------------------------------------------- +static inline void swap_64_at(uint64 *ptr) +{ + *ptr = swap64(*ptr); +} + +//---------------------------------------------------------------------------- +static inline void swap_64_at(int64 *ptr) +{ + *ptr = swap64(*ptr); +} + +//---------------------------------------------------------------------------- +#define swap_addr(ptr) swap_64_at(ptr); +#define swap_xword(ptr) swap_64_at(ptr); +#define swap_sxword(ptr) swap_64_at(ptr); + +//---------------------------------------------------------------------------- +template<> ssize_t buffered_input_t<elf_rel_t>::read_items(size_t max) +{ + if ( isize != sizeof(Elf32_Rel) && isize != sizeof(Elf64_Rel) ) + return 0; + if ( !is_mul_ok<uint64>(read, isize) || !is_mul_ok(max, isize) ) + return 0; + input_status_t save_excursion(reader); + if ( save_excursion.seek(offset + (read * isize)) == -1 ) + return 0; + ssize_t bytes = max * isize; + if ( qlread(reader.get_linput(), buffer.begin(), bytes) != bytes ) + return 0; + +#if __MF__ + bool swap = !reader.is_msb(); +#else + bool swap = reader.is_msb(); +#endif + + if ( isize == sizeof(Elf32_Rel) ) + { + Elf32_Rel *rel32 = (Elf32_Rel *) buffer.begin(); + Elf64_Rel *rel64 = (Elf64_Rel *) buffer.begin(); + rel32 += max - 1; + rel64 += max - 1; + uint64 inf64, off64; + for ( size_t i = 0; i < max; i++, rel32--, rel64-- ) + { + if ( swap ) + { + inf64 = swap32(rel32->r_info); + off64 = swap32(rel32->r_offset); + } + else + { + inf64 = rel32->r_info; + off64 = rel32->r_offset; + } + rel64->r_info = inf64; + rel64->r_offset = off64; + } + } + else + { + if ( swap ) + { + elf_rel_t *rel64 = (elf_rel_t *)buffer.begin(); + for ( size_t i = 0; i < max; i++, rel64++ ) + { + swap_addr(&rel64->r_offset); + swap_xword(&rel64->r_info); + } + } + } + + return max; +} + +//---------------------------------------------------------------------------- +template<> ssize_t buffered_input_t<elf_rela_t>::read_items(size_t max) +{ + if ( isize != sizeof(Elf32_Rela) && isize != sizeof(Elf64_Rela) ) + return 0; + if ( !is_mul_ok<uint64>(read, isize) || !is_mul_ok(max, isize) ) + return 0; + input_status_t save_excursion(reader); + if ( save_excursion.seek(offset + (read * isize)) == -1 ) + return 0; + ssize_t bytes = max * isize; + if ( qlread(reader.get_linput(), buffer.begin(), bytes) != bytes ) + return 0; + +#if __MF__ + bool swap = !reader.is_msb(); +#else + bool swap = reader.is_msb(); +#endif + + if ( isize == sizeof(Elf32_Rela) ) + { + Elf32_Rela *rela32 = (Elf32_Rela *) buffer.begin(); + Elf64_Rela *rela64 = (Elf64_Rela *) buffer.begin(); + rela32 += max - 1; + rela64 += max - 1; + uint64 inf64, off64; + int64 addend; + for ( size_t i = 0; i < max; i++, rela32--, rela64-- ) + { + if ( swap ) + { + inf64 = swap32(rela32->r_info); + off64 = swap32(rela32->r_offset); + addend = swap32(rela32->r_addend); + } + else + { + inf64 = rela32->r_info; + off64 = rela32->r_offset; + addend = rela32->r_addend; + } + rela64->r_info = inf64; + rela64->r_offset = off64; + rela64->r_addend = addend; + } + } + else + { + if ( swap ) + { + elf_rela_t *rela64 = (elf_rela_t *)buffer.begin(); + for ( size_t i = 0; i < max; i++, rela64++ ) + { + swap_addr(&rela64->r_offset); + swap_xword(&rela64->r_info); + swap_sxword(&rela64->r_addend); + } + } + } + + return max; +} + +//-------------------------------------------------------------------------- +class aps2_unpacker_t +{ + enum + { + RELOCATION_GROUPED_BY_INFO_FLAG = 1, + RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG = 2, + RELOCATION_GROUPED_BY_ADDEND_FLAG = 4, + RELOCATION_GROUP_HAS_ADDEND_FLAG = 8 + }; + + const uchar *ptr; + const uchar *end; + int flags; + bool ok; + + bool grouped_by_offset_delta() const { return (flags & RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG) != 0; } + bool grouped_by_info() const { return (flags & RELOCATION_GROUPED_BY_INFO_FLAG) != 0; } + bool grouped_by_addend() const { return (flags & RELOCATION_GROUPED_BY_ADDEND_FLAG) != 0; } + bool group_has_addend() const { return (flags & RELOCATION_GROUP_HAS_ADDEND_FLAG) != 0; } + int64 getval() + { + int64 v; + if ( !unpack_sleb128(&v, &ptr, end) ) + ok = false; + return v; + } + +public: + aps2_unpacker_t(const uchar *p, const uchar *e) + : ptr(p), end(e), flags(0), ok(true) {} + + //-------------------------------------------------------------------------- + void unpack(elf_rela_vec_t *out, int64 nrelocs) + { + elf_rela_t rela; + rela.r_offset = getval(); + rela.r_addend = 0; + rela.r_info = 0; + + out->resize(nrelocs); + size_t n = 0; + + while ( ok ) // repeat for all groups + { + int64 nrels = getval(); // number of relocs in the group + flags = getval(); // flags for the group + + int64 offset_delta = 0; + if ( grouped_by_offset_delta() ) + offset_delta = getval(); + + if ( grouped_by_info() ) + rela.r_info = getval(); + + if ( grouped_by_addend() && group_has_addend() ) + rela.r_addend += getval(); + else if ( !group_has_addend() ) + rela.r_addend = 0; + + // unpack all relocs in the group + for ( int64 i=0; i < nrels; i++ ) + { + if ( !grouped_by_offset_delta() ) + offset_delta = getval(); + rela.r_offset += offset_delta; + + if ( !grouped_by_info() ) + rela.r_info = getval(); + + if ( group_has_addend() && !grouped_by_addend() ) + rela.r_addend += getval(); + + if ( !ok ) + { // some kind of error occurred, remove the uninitialized relocs + out->resize(n); + return; + } + if ( n == nrelocs ) + return; // safety check + out->at(n++) = rela; + } + } + } +}; + +//---------------------------------------------------------------------------- +bool buffered_rela_t::next(elf_rela_t *&storage) +{ + if ( !packed ) + return inherited::next(storage); + + if ( cur >= end ) + { + if ( end != 0 ) + return false; + + // read everything at once and unpack + bytevec_t bytes; + bytes.resize(count); + input_status_t save_excursion(reader); + if ( save_excursion.seek(offset) == -1 ) + return false; + ssize_t nread = qlread(reader.get_linput(), bytes.begin(), count); + if ( nread < count ) + { + msg("READ ERROR: read only %" FMT_ZS " bytes instead of %" FMT_64 "d bytes\n", + nread, count); + if ( nread <= 8 ) + return false; + bytes.resize(nread); + } + if ( bytes.size() < sizeof(uint32) ) + return false; + + const uchar *ptr = bytes.begin(); + const uchar *endp = bytes.end(); + uint32 magic = *(uint32*)ptr; + ptr += 4; + +#define PKREL_APR1 MC4('A','P','R','1') +#define PKREL_APA1 MC4('A','P','A','1') +#define PKREL_APS2 MC4('A','P','S','2') + + int64 n; + if ( !unpack_sleb128(&n, &ptr, endp) ) + return false; + if ( n <= 0 || n >= count ) // sanity check + return false; + + switch ( magic ) + { + default: // unknown magic +// case PKREL_APR1: +// case PKREL_APA1: + ask_for_feedback( + "The relocation packing method '%4.4s' is not supported yet.", + (const char *)bytes.begin()); + return false; + case PKREL_APS2: + aps2_unpacker_t unp(ptr, endp); + unp.unpack(&buffer, n); + break; + } + + end = n; + } + storage = &buffer[cur++]; + return true; +} + +//---------------------------------------------------------------------------- +template<> bool buffered_input_t<elf_dyn_t>::read_item(elf_dyn_t &storage) +{ + // FIXME: Load bias? + memset(&storage, 0, sizeof(storage)); + _safe(reader.read_sxword(&storage.d_tag)); + _safe(reader.read_addr(&storage.d_un)); +#undef _safe + return true; +} + +//------------------------------------------------------------------------- +void dynamic_info_t::initialize(const reader_t &reader) +{ + symtab().entsize = reader.stdsizes.entries.sym; + rel().entsize = reader.stdsizes.dyn.rel; + rela().entsize = reader.stdsizes.dyn.rela; + QASSERT(20037, symtab().entsize != 0 && rel().entsize != 0 && rela().entsize != 0); +} + +//---------------------------------------------------------------------------- +bool dynamic_info_t::fill_section_header( + elf_shdr_t *sh, + dynamic_info_type_t type) const +{ + int shtype; + switch ( type ) + { + case DIT_SYMTAB: shtype = SHT_DYNSYM; break; + case DIT_REL: shtype = SHT_REL; break; + case DIT_RELA: shtype = SHT_RELA; break; + case DIT_ANDROID_REL: shtype = SHT_REL; break; + case DIT_ANDROID_RELA: shtype = SHT_RELA; break; + case DIT_VERDEF: shtype = SHT_GNU_verdef; break; + case DIT_VERNEED: shtype = SHT_GNU_verneed; break; + case DIT_VERSYM: shtype = SHT_GNU_versym; break; + case DIT_PLT: + shtype = plt_rel_type == DT_RELA ? SHT_RELA : SHT_REL; + break; + default: + QASSERT(20101, false); + }; + const entry_t &entry = entries[type]; + if ( !entry.is_valid() ) + return false; + memset(sh, 0, sizeof(*sh)); + sh->sh_addr = entry.addr; + sh->sh_offset = entry.offset; + sh->sh_size = entry.size; + sh->sh_info = entry.info; + sh->sh_type = shtype; + if ( type != DIT_ANDROID_REL && type != DIT_ANDROID_RELA ) + { + sh->sh_entsize = sh->sh_type == SHT_DYNSYM ? entry.entsize + : sh->sh_type == SHT_RELA ? rela().entsize + : rel().entsize; + } + return true; +} + +//---------------------------------------------------------------------------- +qstring dynamic_info_t::d_tag_str_ext(const reader_t &reader, int64 d_tag) +{ + qstring buf = d_tag_str(reader, d_tag); + if ( buf.empty() ) + { + buf.sprnt("DT_???? Unknown (%08" FMT_64 "X)", d_tag); + return buf; + } + if ( buf.length() < 12 ) + buf.resize(12, ' '); + + uint16 e_machine = reader.get_header().e_machine; + const char *ext = NULL; + switch ( d_tag ) + { + case DT_NULL: + ext = "end of _DYNAMIC array"; + break; + case DT_NEEDED: + ext = "str-table offset name to needed library"; + break; + case DT_PLTRELSZ: + ext = "tot.size in bytes of relocation entries"; + break; + case DT_HASH: + ext = "addr. of symbol hash table"; + break; + case DT_STRTAB: + ext = "addr of string table"; + break; + case DT_SYMTAB: + ext = "addr of symbol table"; + break; + case DT_RELA: + ext = "addr of relocation table"; + break; + case DT_RELASZ: + ext = "size in bytes of DT_RELA table"; + break; + case DT_RELAENT: + ext = "size in bytes of DT_RELA entry"; + break; + case DT_STRSZ: + ext = "size in bytes of string table"; + break; + case DT_SYMENT: + ext = "size in bytes of symbol table entry"; + break; + case DT_INIT: + ext = "addr. of initialization function"; + break; + case DT_FINI: + ext = "addr. of termination function"; + break; + case DT_SONAME: + ext = "offs in str.-table - name of shared object"; + break; + case DT_RPATH: + ext = "offs in str-table - search path"; + break; + case DT_RUNPATH: + ext = "array of search pathes"; + break; + case DT_SYMBOLIC: + ext = "start search of shared object"; + break; + case DT_REL: + ext = "addr of relocation table"; + break; + case DT_RELSZ: + ext = "tot.size in bytes of DT_REL"; + break; + case DT_RELENT: + ext = "size in bytes of DT_REL entry"; + break; + case DT_PLTREL: + ext = "type of relocation (DT_REL or DT_RELA)"; + break; + case DT_DEBUG: + ext = "not specified"; + break; + case DT_TEXTREL: + ext = "segment permisson"; + break; + case DT_PLTGOT: + if ( e_machine == EM_PPC ) + ext = "addr of PLT"; + break; + case DT_JMPREL: + if ( e_machine == EM_PPC ) + ext = "addr of JMP_SLOT relocation table"; + else + ext = "addr of dlt procedure (if present)"; + break; + case DT_PPC_GOT: + if ( e_machine == EM_PPC ) + ext = "addr of _GLOBAL_OFFSET_TABLE_"; + break; + } + if ( ext == NULL && reader.is_arm() ) + { + switch ( d_tag ) + { + case DT_ANDROID_REL: + ext = " offset of packed REL data"; + break; + case DT_ANDROID_RELSZ: + ext = " size of DT_ANDROID_REL"; + break; + case DT_ANDROID_RELA: + ext = " offset of packed RELA data"; + break; + case DT_ANDROID_RELASZ: + ext = " size of DT_ANDROID_RELA"; + break; + } + } + buf.append(ext); + return buf; +} + +//---------------------------------------------------------------------------- +const char *dynamic_info_t::d_tag_str(const reader_t &reader, int64 d_tag) +{ + uint16 e_machine = reader.get_header().e_machine; +#define NM(tp) case tp: return #tp + + // OS-specific types + uint8 os_abi = reader.get_ident().osabi; + if ( os_abi == ELFOSABI_SOLARIS ) + { + switch ( d_tag ) + { + NM(DT_SUNW_AUXILIARY); +// NM(DT_SUNW_RTLDINF); + NM(DT_SUNW_FILTER); + NM(DT_SUNW_CAP); + NM(DT_SUNW_SYMTAB); + NM(DT_SUNW_SYMSZ); + NM(DT_SUNW_ENCODING); +// NM(DT_SUNW_SORTENT); + NM(DT_SUNW_SYMSORT); + NM(DT_SUNW_SYMSORTSZ); + NM(DT_SUNW_TLSSORT); + NM(DT_SUNW_TLSSORTSZ); + NM(DT_SUNW_CAPINFO); + NM(DT_SUNW_STRPAD); + NM(DT_SUNW_CAPCHAIN); + NM(DT_SUNW_LDMACH); + NM(DT_SUNW_CAPCHAINENT); + NM(DT_SUNW_CAPCHAINSZ); + NM(DT_SUNW_PARENT); + NM(DT_SUNW_ASLR); + NM(DT_SUNW_RELAX); + NM(DT_SUNW_NXHEAP); + NM(DT_SUNW_NXSTACK); + } + } + + switch ( d_tag ) + { + NM(DT_NULL); + NM(DT_NEEDED); + NM(DT_PLTRELSZ); + NM(DT_HASH); + NM(DT_STRTAB); + NM(DT_SYMTAB); + NM(DT_RELA); + NM(DT_RELASZ); + NM(DT_RELAENT); + NM(DT_STRSZ); + NM(DT_SYMENT); + NM(DT_INIT); + NM(DT_FINI); + NM(DT_SONAME); + NM(DT_RPATH); + NM(DT_RUNPATH); + NM(DT_SYMBOLIC); + NM(DT_REL); + NM(DT_RELSZ); + NM(DT_RELENT); + NM(DT_PLTREL); + NM(DT_DEBUG); + NM(DT_TEXTREL); + + NM(DT_PLTGOT); + NM(DT_JMPREL); + + NM(DT_BIND_NOW); + NM(DT_PREINIT_ARRAY); + NM(DT_INIT_ARRAY); + NM(DT_FINI_ARRAY); + NM(DT_INIT_ARRAYSZ); + NM(DT_FINI_ARRAYSZ); + NM(DT_PREINIT_ARRAYSZ); + NM(DT_FLAGS); + + NM(DT_VALRNGLO); + NM(DT_GNU_PRELINKED); + NM(DT_GNU_CONFLICTSZ); + NM(DT_GNU_LIBLISTSZ); + NM(DT_CHECKSUM); + NM(DT_PLTPADSZ); + NM(DT_MOVEENT); + NM(DT_MOVESZ); + NM(DT_FEATURE); + NM(DT_POSFLAG_1); + NM(DT_SYMINSZ); + NM(DT_SYMINENT); +// NM(DT_VALRNGHI); + NM(DT_ADDRRNGLO); + NM(DT_GNU_HASH); + NM(DT_TLSDESC_PLT); + NM(DT_TLSDESC_GOT); + NM(DT_GNU_CONFLICT); + NM(DT_GNU_LIBLIST); + NM(DT_CONFIG); + NM(DT_DEPAUDIT); + NM(DT_AUDIT); + NM(DT_PLTPAD); + NM(DT_MOVETAB); + NM(DT_SYMINFO); +// NM(DT_ADDRRNGHI); + NM(DT_RELACOUNT); + NM(DT_RELCOUNT); + NM(DT_FLAGS_1); + NM(DT_VERDEF); + NM(DT_VERDEFNUM); + NM(DT_VERNEED); + NM(DT_VERNEEDNUM); + NM(DT_VERSYM); + + NM(DT_AUXILIARY); + NM(DT_USED); + NM(DT_FILTER); + } + if ( reader.is_mips() ) + { + switch ( d_tag ) + { + NM(DT_MIPS_RLD_VERSION); + NM(DT_MIPS_TIME_STAMP); + NM(DT_MIPS_ICHECKSUM); + NM(DT_MIPS_IVERSION); + NM(DT_MIPS_FLAGS); + NM(DT_MIPS_BASE_ADDRESS); + NM(DT_MIPS_MSYM); + NM(DT_MIPS_CONFLICT); + NM(DT_MIPS_LIBLIST); + NM(DT_MIPS_LOCAL_GOTNO); + NM(DT_MIPS_CONFLICTNO); + NM(DT_MIPS_LIBLISTNO); + NM(DT_MIPS_SYMTABNO); + NM(DT_MIPS_UNREFEXTNO); + NM(DT_MIPS_GOTSYM); + NM(DT_MIPS_HIPAGENO); + NM(DT_MIPS_RLD_MAP); + NM(DT_MIPS_DELTA_CLASS); + NM(DT_MIPS_DELTA_CLASS_NO); + NM(DT_MIPS_DELTA_INSTANCE); + NM(DT_MIPS_DELTA_INSTANCE_NO); + NM(DT_MIPS_DELTA_RELOC); + NM(DT_MIPS_DELTA_RELOC_NO); + NM(DT_MIPS_DELTA_SYM); + NM(DT_MIPS_DELTA_SYM_NO); + NM(DT_MIPS_DELTA_CLASSSYM); + NM(DT_MIPS_DELTA_CLASSSYM_NO); + NM(DT_MIPS_CXX_FLAGS); + NM(DT_MIPS_PIXIE_INIT); + NM(DT_MIPS_SYMBOL_LIB); + NM(DT_MIPS_LOCALPAGE_GOTIDX); + NM(DT_MIPS_LOCAL_GOTIDX); + NM(DT_MIPS_HIDDEN_GOTIDX); + NM(DT_MIPS_PROTECTED_GOTIDX); + NM(DT_MIPS_OPTIONS); + NM(DT_MIPS_INTERFACE); + NM(DT_MIPS_DYNSTR_ALIGN); + NM(DT_MIPS_INTERFACE_SIZE); + NM(DT_MIPS_RLD_TEXT_RESOLVE_ADDR); + NM(DT_MIPS_PERF_SUFFIX); + NM(DT_MIPS_COMPACT_SIZE); + NM(DT_MIPS_GP_VALUE); + NM(DT_MIPS_AUX_DYNAMIC); + NM(DT_MIPS_PLTGOT); + NM(DT_MIPS_RWPLT); + } + } + else if ( e_machine == EM_IA64 ) + { + switch ( d_tag ) + { + NM(DT_HP_LOAD_MAP); + NM(DT_HP_DLD_FLAGS); + NM(DT_HP_DLD_HOOK); + NM(DT_HP_UX10_INIT); + NM(DT_HP_UX10_INITSZ); + NM(DT_HP_PREINIT); + NM(DT_HP_PREINITSZ); + NM(DT_HP_NEEDED); + NM(DT_HP_TIME_STAMP); + NM(DT_HP_CHECKSUM); + NM(DT_HP_GST_SIZE); + NM(DT_HP_GST_VERSION); + NM(DT_HP_GST_HASHVAL); + NM(DT_HP_EPLTREL); + NM(DT_HP_EPLTRELSZ); + NM(DT_HP_FILTERED); + NM(DT_HP_FILTER_TLS); + NM(DT_HP_COMPAT_FILTERED); + NM(DT_HP_LAZYLOAD); + NM(DT_HP_BIND_NOW_COUNT); + NM(DT_PLT); + NM(DT_PLT_SIZE); + NM(DT_DLT); + NM(DT_DLT_SIZE); + NM(DT_HP_SYM_CHECKSUM); + NM(DT_IA_64_PLT_RESERVE); + } + } + else if ( e_machine == EM_PPC ) + { + switch ( d_tag ) + { + NM(DT_PPC_GOT); + } + } + else if ( reader.is_arm() ) + { + switch ( d_tag ) + { + NM(DT_ANDROID_REL); + NM(DT_ANDROID_RELSZ); + NM(DT_ANDROID_RELA); + NM(DT_ANDROID_RELASZ); + } + } + +#undef NM + return NULL; +} + +//---------------------------------------------------------------------------- +qstring dynamic_info_t::d_un_str(const reader_t &reader, int64 d_tag, int64 d_un) +{ + qstring name; + switch ( d_tag ) + { + case DT_SONAME: + case DT_RPATH: + case DT_RUNPATH: + case DT_NEEDED: + case DT_AUXILIARY: + case DT_FILTER: + case DT_CONFIG: + case DT_DEPAUDIT: + case DT_AUDIT: + reader.get_name(&name, reader.dyn_strtab, uint32(d_un)); + break; + } + return name; +} + +//---------------------------------------------------------------------------- +size_t symrel_cache_t::slice_start(slice_type_t t) const +{ + check_type(t); + return t == SLT_DYNSYM ? dynsym_index : 0; +} + +//---------------------------------------------------------------------------- +size_t symrel_cache_t::slice_end(slice_type_t t) const +{ + check_type(t); + return t == SLT_SYMTAB ? dynsym_index : storage.size(); +} + +//---------------------------------------------------------------------------- +sym_rel &symrel_cache_t::append(slice_type_t t) +{ + check_type(t); + size_t idx = slice_end(t); + if ( t == SLT_SYMTAB ) + ++dynsym_index; + if ( idx == storage.size() ) + { + return storage.push_back(); + } + else + { + QASSERT(20133, idx <= storage.size()); + qvector<sym_rel>::iterator it = storage.begin() + idx; + storage.insert(it, sym_rel()); + return *it; + } +} + +// =========================================================================== +// ARM-specific code. +// =========================================================================== + +//---------------------------------------------------------------------------- +bool arm_arch_specific_t::is_mapping_symbol(const char *name) const +{ + if ( name == NULL ) + return false; + + if ( name[0] == '$' + && name[1] != '\0' + && (name[2] == '\0' || name[2] == '.') ) + { + switch ( name[1] ) + { + case 'a': // labels the first byte of a sequence of ARM instructions. Its type is STT_FUNC. + case 't': // labels the first byte of a sequence of Thumb instructions. Its type is STT_FUNC. + case 'b': // labels a Thumb BL instruction. Its type is STT_FUNC. + case 'd': // labels the first byte of a sequence of data items. Its type is STT_OBJECT. + case 'p': // labels the final, PC-modifying instruction of an + // indirect function call. Its type is STT_FUNC. + // (An indirect call is a call through a function pointer + // variable). $p does not label the PC-modifying + // instruction of a function return sequence. + case 'f': // labels a function pointer constant (static pointer to code). + // Its type is STT_OBJECT. + case 'x': // Start of a sequence of A64 instructions + return true; + } + } + return false; +} + +//---------------------------------------------------------------------------- +void arm_arch_specific_t::on_start_symbols(reader_t &) +{ + has_mapsym = false; +} + +//---------------------------------------------------------------------------- +void arm_arch_specific_t::on_symbol_read(reader_t &reader, sym_rel &sym) +{ + const char *name = sym.get_original_name(reader).c_str(); + if ( is_mapping_symbol(name) ) + { + has_mapsym = true; + + // assert: name != NULL + char name1 = name[1]; + if ( name1 == 'a' || name1 == 't' || name1 == 'x' ) + { + isa_t isa = name1 == 'a' || name1 == 'x' ? isa_arm : isa_thumb; + if ( name1 == 't' ) + sym.set_flag(thumb_function); + notify_isa(reader, sym, isa, true); + if ( is_mapping_symbols_tracking() ) + set_isa(sym, isa); + } + } + else + { + uchar bind = sym.bind; + + // Keep going _only_ if function + ushort orig_type = ELF_ST_TYPE(sym.original.st_info); + if ( (orig_type != STT_FUNC + && orig_type != STT_ARM_TFUNC + && orig_type != STT_ARM_16BIT ) + || (bind != STB_GLOBAL + && bind != STB_LOCAL + && bind != STB_WEAK) ) + { + return; + } + + sym.value &= ~1; + + // If original type is ARM_TFUNC, make it FUNC, + // so it gets treated as a regular FUNC by + // upstream code. + if ( orig_type == STT_ARM_TFUNC ) + sym.type = STT_FUNC; + + if ( (orig_type == STT_ARM_TFUNC + || orig_type == STT_ARM_16BIT + || (sym.original.st_value & 1) != 0) ) + { + sym.set_flag(thumb_function); + notify_isa(reader, sym, isa_thumb, false); + } + + if ( !sym.has_flag(thumb_function) + && is_mapping_symbols_tracking() + && get_isa(sym) == isa_thumb ) + { + sym.set_flag(thumb_function); + notify_isa(reader, sym, isa_thumb, false); + } + + if ( !sym.has_flag(thumb_function) ) + notify_isa(reader, sym, isa_arm, false); + } +} + +//---------------------------------------------------------------------------- +void arm_arch_specific_t::set_isa(const sym_rel &symbol, isa_t isa) +{ + isa_ranges_t::iterator it = isa_ranges.find(symbol.sec); + if ( it == isa_ranges.end() ) + { + isa_ranges[symbol.sec] = section_isa_ranges_t(); + it = isa_ranges.find(symbol.sec); + } + + section_isa_ranges_t §ion_isa_ranges = it->second; + section_isa_ranges[symbol.original.st_value] = isa; +} + +//---------------------------------------------------------------------------- +arm_arch_specific_t::isa_t arm_arch_specific_t::get_isa(const sym_rel &symbol) const +{ + isa_t current_isa = isa_arm; + isa_ranges_t::const_iterator it = isa_ranges.find(symbol.sec); + if ( it != isa_ranges.end() ) + { + const section_isa_ranges_t §ion_isa_ranges = it->second; + section_isa_ranges_t::const_iterator p; + section_isa_ranges_t::const_iterator end = section_isa_ranges.end(); + for ( p = section_isa_ranges.begin(); p != end; ++p ) + { + uint64 offset_in_section = p->first; + if ( offset_in_section > symbol.original.st_value ) + break; + + current_isa = p->second; + } + } + return current_isa; +} + +#endif // ELF_READER_CPP diff --git a/idasdk75/ldr/exports.def b/idasdk76/ldr/exports.def similarity index 100% rename from idasdk75/ldr/exports.def rename to idasdk76/ldr/exports.def diff --git a/idasdk75/ldr/geos/common.cpp b/idasdk76/ldr/geos/common.cpp similarity index 100% rename from idasdk75/ldr/geos/common.cpp rename to idasdk76/ldr/geos/common.cpp diff --git a/idasdk76/ldr/geos/geos.cpp b/idasdk76/ldr/geos/geos.cpp new file mode 100644 index 0000000..fcdad73 --- /dev/null +++ b/idasdk76/ldr/geos/geos.cpp @@ -0,0 +1,795 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2000 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + */ + +#include "../idaldr.h" +#include "geos2.h" +#include "common.cpp" +#include <struct.hpp> +#include <enum.hpp> +#include <typeinf.hpp> + +//-------------------------------------------------------------------------- +static int create_seg( + ea_t base, + ea_t start, + ea_t end, + const char *name, + const char *sclass) +{ + if ( start != BADADDR && end < start ) + return 0; + segment_t s; + s.sel = setup_selector(base); + s.start_ea = start; + s.end_ea = end; + s.align = saRelByte; + s.comb = (sclass != NULL && strcmp(sclass,"STACK") == 0) ? scStack : scPub; + s.bitness = 0; + return add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE); +} + +//-------------------------------------------------------------------------- +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + union + { + GEOSheader h1; + GEOS2header h2; + } h; + qlseek(li, 0); + if ( qlread(li, &h, sizeof(h)) != sizeof(h) ) + return 0; + + qoff64_t apppos; + int version; + if ( h.h1.ID == GEOS_ID && h.h1.fclass == 0 ) + { + apppos = 0xC8; + version = 1; + } + else if ( h.h2.ID == GEOS2_ID && h.h2.fclass == 1 ) + { + apppos = sizeof(GEOS2header); + version = 2; + } + else + { + return 0; + } + + GEOSappheader ah; + qlseek(li, apppos, SEEK_SET); + if ( qlread(li, &ah, sizeof(ah)) != sizeof(ah) ) + return 0; + const char *stype; + switch ( ah.type ) + { + case 1: stype = "Application"; break; + case 2: stype = "Library"; break; + case 3: stype = "Driver"; break; + default: stype = "Unknown type";break; + } + fileformatname->sprnt("GEOS%d %s", version, stype); + *processor = "metapc"; + return 1; +} + +//-------------------------------------------------------------------------- +static ea_t get_segea(const GEOSappheader &ah, const uint32 *segea, uint16 s) +{ + if ( s >= ah.numseg ) + { + ask_for_feedback("Bad segment number %d", s); + return BADADDR; + } + return segea[s] == uint32(BADADDR) ? BADADDR : segea[s]; +} + +//-------------------------------------------------------------------------- +static netnode get_node(const GEOSappheader &ah, const netnode *modnode, uint16 libn) +{ + if ( libn >= ah.numlib ) + { + ask_for_feedback("Bad library number %d", libn); + return BADNODE; + } + return modnode[libn]; +} + +//-------------------------------------------------------------------------- +static tid_t get_class_struct_flags_enum() +{ + static const char enum_name[] = "ClassFlags"; + enum_t id = get_enum(enum_name); + if ( id != BADNODE ) + return id; + id = add_enum(-1, enum_name, hex_flag()); + set_enum_bf(id, true); + add_enum_member(id, "CLASSF_HAS_DEFAULT", (1<<0), (1<<0)); + add_enum_member(id, "CLASSF_MASTER_CLASS", (1<<1), (1<<1)); + add_enum_member(id, "CLASSF_VARIANT_CLASS", (1<<2), (1<<2)); + add_enum_member(id, "CLASSF_DISCARD_ON_SAVE", (1<<3), (1<<3)); + add_enum_member(id, "CLASSF_NEVER_SAVED", (1<<4), (1<<4)); + add_enum_member(id, "CLASSF_HAS_RELOC", (1<<5), (1<<5)); + add_enum_member(id, "CLASSF_C_HANDLERS", (1<<6), (1<<6)); + return id; +} + +//-------------------------------------------------------------------------- +#if 0 +static void declare_parameter_types(ea_t ea, int count) +{ + static const char class_name[] = "CMethodDef"; + struc_t *sptr = get_struc(get_struc_id(class_name)); + if ( sptr == NULL ) + { + sptr = get_struc(add_struc(-1, class_name)); + if ( sptr == NULL ) + return; + add_struc_member(sptr, "methodParameterDef", -1, word_flag(), NULL, 2); + add_struc_member(sptr, "handlerTypeDef", -1, byte_flag(), NULL, 1); + } + size_t size = get_struc_size(sptr); + create_struct(ea, size*count, sptr->id); +} +#endif + +//-------------------------------------------------------------------------- +static void declare_class(ea_t ea, const char *entryname) +{ + static const char class_name[] = "ClassStruct"; + struc_t *sptr = get_struc(get_struc_id(class_name)); + if ( sptr == NULL ) + { + sptr = get_struc(add_struc(BADADDR, class_name)); + if ( sptr == NULL ) + return; + opinfo_t mt; + mt.ri.flags = REF_OFF32; + mt.ri.target = BADADDR; + mt.ri.base = 0; + mt.ri.tdelta = 0; + add_struc_member(sptr, "superClass", BADADDR, off_flag()|dword_flag(), &mt, 4); + add_struc_member(sptr, "masterOffset", BADADDR, word_flag(), NULL, 2); + add_struc_member(sptr, "methodCount", BADADDR, dec_flag()|word_flag(), NULL, 2); + add_struc_member(sptr, "instanceSize", BADADDR, dec_flag()|word_flag(), NULL, 2); + add_struc_member(sptr, "vdRelocTable", BADADDR, word_flag(), NULL, 2); + add_struc_member(sptr, "relocTable", BADADDR, word_flag(), NULL, 2); + mt.ec.tid = get_class_struct_flags_enum(); + mt.ec.serial = 0; + add_struc_member(sptr, "flags", BADADDR, enum_flag()|byte_flag(), &mt, 1); + add_struc_member(sptr, "masterMethods",BADADDR, byte_flag(), NULL, 1); + } + asize_t size = get_struc_size(sptr); + create_struct(ea, size, sptr->id); + + segment_t *s = getseg(ea); + if ( s == NULL ) + return; + int count = get_word(ea+6); +// bool c_handlers = get_byte(ea+14) & (1<<6); + ea += size; + if ( ea+2*count >= s->end_ea ) + return; + ea_t messages = ea; + create_word(ea, count*2); + op_dec(ea, 0); + ea += 2*count; + if ( ea+4*count > s->end_ea ) + return; + create_dword(ea, count*4); + op_plain_offset(ea, 0, 0); + for ( int i=0; i < count; i++ ) + { + ea_t idx = ea + 4*i; + ea_t pea = to_ea(get_word(idx+2), get_word(idx)); + auto_make_proc(pea); + char name[MAXSTR]; + qsnprintf(name, sizeof(name), "%s_%u", entryname, get_word(messages+2*i)); + add_entry(pea, pea, name, true, AEF_IDBENC); + } +// commented out because it doesn't work properly +// see geoplan.geo, entry number 1 for example +// if ( c_handlers ) +// declare_parameter_types(ea+count*4, count); +} + +//-------------------------------------------------------------------------- +static void describe_app(const GEOSappheader &ah, const uint32 *segea) +{ + char buf[MAXSTR]; + char *end = buf + sizeof(buf); + char *ptr = buf + qsnprintf(buf, sizeof(buf), "Pgm attrs :"); + if ( ah.attr & GA_PROCESS ) APPEND(ptr, end, " GA_PROCESS"); + if ( ah.attr & GA_LIBRARY ) APPEND(ptr, end, " GA_LIBRARY"); + if ( ah.attr & GA_DRIVER ) APPEND(ptr, end, " GA_DRIVER"); + if ( ah.attr & GA_KEEP_FILE_OPEN ) APPEND(ptr, end, " GA_KEEP_FILE_OPEN"); + if ( ah.attr & GA_SYSTEM ) APPEND(ptr, end, " GA_SYSTEM"); + if ( ah.attr & GA_MULTI_LAUNCHABLE ) APPEND(ptr, end, " GA_MULTI_LAUNCHABLE"); + if ( ah.attr & GA_APPLICATION ) APPEND(ptr, end, " GA_APPLICATION"); + if ( ah.attr & GA_DRIVER_INITIALIZED ) APPEND(ptr, end, " GA_DRIVER_INITIALIZED"); + if ( ah.attr & GA_LIBRARY_INITIALIZED ) APPEND(ptr, end, " GA_LIBRARY_INITIALIZED"); + if ( ah.attr & GA_GEODE_INITIALIZED ) APPEND(ptr, end, " GA_GEODE_INITIALIZED"); + if ( ah.attr & GA_USES_COPROC ) APPEND(ptr, end, " GA_USES_COPROC"); + if ( ah.attr & GA_REQUIRES_COPROC ) APPEND(ptr, end, " GA_REQUIRES_COPROC"); + if ( ah.attr & GA_HAS_GENERAL_CONSUMER_MODE ) APPEND(ptr, end, " GA_HAS_GENERAL_CONSUMER_MODE"); + if ( ah.attr & GA_ENTRY_POINTS_IN_C ) APPEND(ptr, end, " GA_ENTRY_POINTS_IN_C"); + add_pgm_cmt("%s", buf); + + if ( ah.attr & GA_PROCESS ) + { + ea_t entry = get_segea(ah, segea, ah.classptr_seg) + ah.classptr_ofs; + set_name(entry, "ProcessClass", SN_NOCHECK|SN_NOWARN); + declare_class(entry, "ProcessClass"); +// inf_set_start_cs(get_segea(ah,segea,ah.classptr_seg) >> 4); +// inf_set_start_ip (ah.classptr_ofs); + entry = get_segea(ah, segea, ah.tokenres_seg) + ah.tokenres_item; + set_name(entry, "ApplicationObject"); + add_pgm_cmt("ProcessClass: %d:%04X", ah.classptr_seg, ah.classptr_ofs); + add_pgm_cmt("App object : %d:%04X", ah.tokenres_seg, ah.tokenres_item); + } + if ( ah.attr & GA_LIBRARY && ah.initseg != 0 ) + { + inf_set_start_cs(get_segea(ah, segea, ah.initseg) >> 4); + inf_set_start_ip(ah.initofs); + add_pgm_cmt("Library init: %d:%04X", ah.initseg, ah.initofs); + } + if ( ah.attr & GA_DRIVER && ah.startseg != 0 ) + { + ea_t entry = get_segea(ah, segea, ah.startseg) + ah.startofs; + set_name(entry, "DriverTable"); +// inf_set_start_cs(get_segea(ah, segea, ah.startseg) >> 4); +// inf_set_start_ip (ah.startofs); + add_pgm_cmt("Driver Table: %d:%04X", ah.startseg, ah.startofs); +// add_jmplist(ah.startseg,ah.startofs,4,4); + // Add entry point as "jmplist" + } +} + +//-------------------------------------------------------------------------- +static void bad_lib_reloc(int i, uint16 off) +{ + ask_for_feedback("Strange library relocation at %d:%04X", i, off); +} + +//-------------------------------------------------------------------------- +static void create_fixup(ea_t ea, fixup_data_t &fd, ea_t target) +{ + segment_t *s = getseg(target); + if ( s != NULL ) + { + fd.sel = s->sel; + fd.off = target - get_segm_base(s); + } + else + { + fd.sel = sel_t(target >> 4); + fd.off = target & 0xF; + } + fd.displacement = 0; + fd.set(ea); + if ( fd.get_type() == FIXUP_PTR16 ) + { + put_word(ea, fd.off); + put_word(ea+2, fd.sel); + } + else if ( fd.get_type() == FIXUP_OFF16 ) + { + put_word(ea, fd.off); + } + else // SEG16 + { + put_word(ea, fd.sel); + } +} + +//-------------------------------------------------------------------------- +static void apply_relocations( + linput_t *li, + const GEOSappheader &ah, + const netnode *modnode, + const uint16 *seglen, + const int32 *segpos, + const uint16 *segfix, + const uint32 *segea) +{ + // apply relocation information + for ( int i=0; i < ah.numseg; i++ ) + { + if ( segfix[i] == 0 ) + continue; + GEOSfixup *fix = (GEOSfixup *)qalloc(segfix[i]); + if ( fix == NULL ) + nomem("fix"); + qlseek(li, segpos[i]+((seglen[i]+0xF)&~0xF)); + lread(li, fix, segfix[i]); + int n = segfix[i]/sizeof(GEOSfixup); + sel_t oldsel = BADSEL; + sel_t oldoff = BADSEL; + ea_t oldea = BADADDR; + for ( int j=0; j < n; j++ ) + { + ea_t ea = get_segea(ah, segea, (uint16)i) + fix[j].ofs; + int ftype = fix[j].type & 0xF0; + if ( ftype != 0x10 && ftype != 0x20 ) + ask_for_feedback("Unknown fixup type %02X", ftype); + netnode libnode = BADNODE; + if ( ftype == 0x10 ) + libnode = get_node(ah, modnode, fix[j].type>>8); + uint16 w1 = get_word(ea); + ea_t target = BADADDR; + fixup_data_t fd(FIXUP_SEG16); + switch ( fix[j].type & 0x0F ) + { + case 0x0: case 0x4: + fd.set_type_and_flags(FIXUP_PTR16); + if ( ftype == 0x20 ) // program + target = get_segea(ah, segea, w1) + get_word(ea+2); + else // library + { + target = node2ea(libnode.altval(w1+1)); + fd.set_extdef(); + } + break; + case 0x1: // off + if ( ftype == 0x20 ) // program + { + ask_for_feedback("Program offset relocation encountered"); + continue; + } + oldoff = w1; + if ( oldsel != BADSEL ) + { +LIB_PTR: + target = node2ea(libnode.altval(oldoff+1)); + if ( oldea == ea+2 ) + { + fd.set_type_and_flags(FIXUP_PTR16, FIXUPF_EXTDEF); + } + else + { + fd.set_type_and_flags(FIXUP_SEG16, FIXUPF_EXTDEF); + create_fixup(oldea, fd, target); + fd.set_type_and_flags(FIXUP_OFF16, FIXUPF_EXTDEF); + } + oldsel = BADSEL; + oldoff = BADSEL; + oldea = BADSEL; + break; + } + oldea = ea; + continue; + case 0x2: case 0x3: + if ( ftype == 0x20 ) // program + target = get_segea(ah, segea, w1); + else + { + oldsel = w1; + if ( oldoff != BADSEL ) + { + ea_t tmp = ea; + ea = oldea; + oldea = tmp; + goto LIB_PTR; + } + oldea = ea; + continue; + } + break; + default: + ask_for_feedback("Unknown relocation type %02X", fix[j].type); + } + create_fixup(ea, fd, target); + } + qfree(fix); + } +} + +//-------------------------------------------------------------------------- +static void find_imports_in_relocations( + linput_t *li, + const GEOSappheader &ah, + const netnode *modnode, + const uint16 *seglen, + const int32 *segpos, + const uint16 *segfix) +{ + for ( int i=0; i < ah.numseg; i++ ) + { + if ( segfix[i] == 0 ) + continue; + GEOSfixup *fix = (GEOSfixup *)qalloc(segfix[i]); + if ( fix == NULL ) + nomem("fix"); + qlseek(li, segpos[i]+((seglen[i]+0xF)&~0xF)); + lread(li, fix, segfix[i]); +// i don't understand why this should be done +// besides, if we uncomment it, the library fixups are +// not handled properly +// if ( fix[0].ofs == 0 ) +// fix[0].ofs = 0xFFFF; + int num = segfix[i]/sizeof(GEOSfixup); + sel_t oldseg = BADSEL; + sel_t oldoff = BADSEL; + sel_t oldlib = BADSEL; + for ( int j=0; j < num; j++ ) + { + if ( fix[j].ofs == 0xFFFF ) + continue; + if ( (fix[j].type & 0xF0) != 0x10 ) + continue; // only library! + int libn = fix[j].type>>8; + if ( libn >= ah.numlib ) + { + ask_for_feedback("Illegal library number in relocations"); + continue; + } + netnode n = modnode[libn]; + uint16 ofs = fix[j].ofs; + qlseek(li, segpos[i]+ofs); + uint16 w1; + lread(li, &w1, sizeof(w1)); + switch ( fix[j].type & 0x0F ) + { + case 0x0: case 0x4: // exported entry + n.altset(w1+1, 1); + oldseg = BADSEL; + oldoff = BADSEL; + oldlib = BADSEL; + break; + case 0x1: // off + if ( oldseg != BADSEL ) + { + if ( libn != oldlib || oldseg != w1 ) + bad_lib_reloc(i, ofs); + n.altset(w1+1, 1); + oldseg = BADSEL; + break; + } + oldoff = w1; + oldlib = libn; + break; + case 0x2: case 0x3: // seg # + if ( oldoff != BADSEL ) + { + if ( libn != oldlib || oldoff != w1 ) + bad_lib_reloc(i, ofs); + n.altset(w1+1, 1); + oldoff = BADSEL; + break; + } + oldseg = w1; + oldlib = libn; + break; + default: + ask_for_feedback("Unknown relocation type %02X", fix[j].type); + } + } + if ( oldseg != BADSEL && oldoff != BADSEL ) + ask_for_feedback("Some library relocations are strange"); + qfree(fix); + } +} + +//-------------------------------------------------------------------------- +static void create_extern_segments( + const GEOSappheader &ah, + const GEOSliblist *lib, + const netnode *modnode) +{ + inf_set_specsegs(inf_is_64bit() ? 8 : 4); + for ( int i=0; i < ah.numlib; i++ ) + { + char libname[8+1]; + qstrncpy(libname, lib[i].name, sizeof(libname)); + trim(libname); + netnode n = modnode[i]; + uval_t x; + int nimps = 0; + for ( x=n.altfirst(); x != BADNODE; x=n.altnext(x) ) + nimps++; + if ( nimps == 0 ) + continue; + + ea_t ea = free_chunk(inf_get_max_ea(), nimps*4, -15); + ea_t end = ea + nimps*4; + create_seg(ea>>4, ea, end, libname, "XTRN"); + for ( x=n.altfirst(); x != BADNODE; x=n.altnext(x),ea+=4 ) + { + char buf[MAXSTR]; + qsnprintf(buf, sizeof(buf), "%s_%u", libname, uint16(x)-1); + put_dword(ea, 0xCB); + create_insn(ea); + force_name(ea, buf, SN_IDBENC); + nodeidx_t ndx = ea2node(ea); + n.altset(x, ndx); + } + import_module(libname, NULL /*windir*/, n, NULL, "geos"); + } +} + +//-------------------------------------------------------------------------- +static void create_exports( + const GEOSappheader &ah, + const GEOSexplist *explist, + const uint32 *segea, + const char *modname) +{ + int i; + netnode n; + n.create(); + for ( i=0; i < ah.numexp; i++ ) + { + ea_t ea = get_segea(ah, segea, explist[i].seg) + explist[i].ofs; + add_extra_cmt(ea, true, "Exported entry %d", i); + nodeidx_t ndx = ea2node(ea); + n.altset(i+1, ndx); + } + import_module(modname, NULL /*windir*/, n, NULL, "geos"); + for ( i=0; i < ah.numexp; i++ ) + { + ea_t ea = get_segea(ah, segea, explist[i].seg) + explist[i].ofs; + qstring name; + if ( get_name(&name, ea, GN_NOT_DUMMY) <= 0 ) + name.sprnt("%s_%d", modname, i); + bool makecode = segtype(ea) == SEG_CODE; + add_entry(i, ea, name.begin(), makecode, AEF_IDBENC); + if ( !makecode ) + declare_class(ea, name.begin()); + } +} + +//-------------------------------------------------------------------------- +void load_application(linput_t *li, int32 fpos, int32 fdelta) +{ + GEOSappheader ah; + + qlseek(li, fpos); + lread(li, &ah, sizeof(ah)); + + // build our name + char modname[sizeof(ah.name)+1]; + qstrncpy(modname, ah.name, sizeof(ah.name)); + trim(modname); + + // read in library information + GEOSliblist *lib = NULL; + netnode *modnode = NULL; + validate_array_count(li, &ah.numlib, sizeof(GEOSliblist), "The library count"); + if ( ah.numlib != 0 ) + { + lib = qalloc_array<GEOSliblist>(ah.numlib); + if ( lib == NULL ) + nomem("libs"); + lread(li, lib, ah.numlib*sizeof(GEOSliblist)); + modnode = qalloc_array<netnode>(ah.numlib); + if ( modnode == NULL ) + nomem("libnode"); + for ( int i=0; i < ah.numlib; i++ ) + { + char libname[8+1]; + qstrncpy(libname, lib[i].name, sizeof(libname)); + trim(libname); + char buf[20]; + qsnprintf(buf, sizeof(buf), "$lib %.8s", libname); + modnode[i].create(buf); + } + } + + // read in export information + GEOSexplist *explist = NULL; + validate_array_count(li, &ah.numexp, sizeof(GEOSexplist), "Number of exports"); + if ( ah.numexp != 0 ) + { + explist = qalloc_array<GEOSexplist>(ah.numexp); + if ( explist == NULL ) + nomem("exp"); + lread(li, explist, ah.numexp*sizeof(GEOSexplist)); + } + + // read in segment information + void *segd = NULL; + uint16 *seglen = NULL; + int32 *segpos = NULL; + uint16 *segfix = NULL; + uint16 *segflg; + sel_t ds_sel = BADSEL; + uint32 *segea = NULL; + validate_array_count(li, &ah.numseg, 14, "Number of segments"); + if ( ah.numseg != 0 ) + { + if ( !is_mul_ok<ushort>(ah.numseg, 14) ) +NOMEM: + nomem("geos_segments"); + segd = qalloc(ah.numseg*14); + if ( segd == NULL ) + goto NOMEM; + lread(li, segd, ah.numseg*10); + seglen = (uint16 *)segd; + segpos = (int32 *)(seglen + ah.numseg); + segfix = (uint16 *)(segpos + ah.numseg); + segflg = (uint16 *)(segfix + ah.numseg); + segea = (uint32 *)(segflg + ah.numseg); + ea_t ea = to_ea(inf_get_baseaddr(), 0); + for ( int i=0; i < ah.numseg; i++ ) + { + uint16 f = segflg[i]; + segpos[i] += fdelta; + + segea[i] = uint32(BADADDR); + if ( seglen[i] == 0 ) + continue; + size_t bss_size = 0; + // if this is the data segment, increase its size by stacksize. + // i'm not aware of a reliable way to find it, so use heuristics + bool found_data_segment = false; + if ( ds_sel == BADSEL + && (f & (HF_READ_ONLY|HF_SHARABLE|HF_CODE)) == 0 + && (f & HF_FIXED) != 0 ) + { + found_data_segment = true; + bss_size = ah.stacksize; + } + ea = free_chunk(ea, bss_size + seglen[i], -15); + ea_t endea = ea + seglen[i] + bss_size; + if ( (f & HF_ZERO_INIT) == 0 ) + file2base(li, segpos[i], ea, endea - bss_size, FILEREG_PATCHABLE); + create_seg(ea>>4, ea, endea, NULL, (f & HF_CODE) ? "CODE" : "DATA"); + + if ( found_data_segment ) + ds_sel = find_selector(ea>>4); + + char buf[MAXSTR]; + char *end = buf + sizeof(buf); + char *ptr = buf + qsnprintf(buf, sizeof(buf), "Segm attrs :"); + if ( f & HF_ZERO_INIT ) APPEND(ptr, end, " ZEROINIT"); + if ( f & HF_LOCK ) APPEND(ptr, end, " LOCK"); + if ( f & HF_NO_ERR ) APPEND(ptr, end, " NO_ERR"); + if ( f & HF_UI ) APPEND(ptr, end, " UI"); + if ( f & HF_READ_ONLY ) APPEND(ptr, end, " RONLY"); + if ( f & HF_OBJECT_RESOURCE ) APPEND(ptr, end, " OBJ_RES"); + if ( f & HF_CODE ) APPEND(ptr, end, " CODE"); + if ( f & HF_CONFORMING ) APPEND(ptr, end, " CONFORMING"); + if ( f & HF_FIXED ) APPEND(ptr, end, " FIXED"); + if ( f & HF_SHARABLE ) APPEND(ptr, end, " SHARABLE"); + if ( f & HF_DISCARDABLE ) APPEND(ptr, end, " DISCARDABLE"); + if ( f & HF_SWAPABLE ) APPEND(ptr, end, " SWAPABLE"); + if ( f & HF_LMEM ) APPEND(ptr, end, " LMEM"); + if ( f & HF_DEBUG ) APPEND(ptr, end, " DEBUG"); + if ( f & HF_DISCARDED ) APPEND(ptr, end, " DISCARDED"); + if ( f & HF_SWAPPED ) APPEND(ptr, end, " SWAPPED"); + add_extra_cmt(ea, true, "%s", buf); + + segea[i] = (uint32)ea; + ea = endea; + } + } + + find_imports_in_relocations(li, ah, modnode, seglen, segpos, segfix); + create_extern_segments(ah, lib, modnode); + set_default_dataseg(ds_sel); + + if ( !qgetenv("IDA_NORELOC") ) + apply_relocations(li, ah, modnode, seglen, segpos, segfix, segea); + + create_exports(ah, explist, segea, modname); + + describe_app(ah, segea); + qfree(lib); + qfree(modnode); + qfree(explist); + qfree(segd); +} + +//-------------------------------------------------------------------------- +static void show_geos1(GEOSheader &h) +{ + char buf[MAXSTR]; + add_pgm_cmt("Name : %s", geos2ibm(buf, h.name, sizeof(h.name))); + add_pgm_cmt("Token : %s", token2str(buf, sizeof(buf), h.token)); + add_pgm_cmt("Creator : %s", token2str(buf, sizeof(buf), h.appl)); + add_pgm_cmt("Release : %u.%u.%u.%u", + h.release.versmaj, + h.release.versmin, + h.release.revmaj, + h.release.revmin); + add_pgm_cmt("Protocol : %u.%03u", + h.protocol.vers, + h.protocol.rev); + add_pgm_cmt("Flags : %04X", h.flags); + add_pgm_cmt("User info : %s", geos2ibm(buf, h.info, sizeof(h.info))); + add_pgm_cmt("Copyright : %s", geos2ibm(buf, h._copyright, sizeof(h._copyright))); +} + +//-------------------------------------------------------------------------- +static void show_geos2(GEOS2header &h) +{ + char buf[MAXSTR]; + add_pgm_cmt("Name : %s", geos2ibm(buf, h.name, sizeof(h.name))); + add_pgm_cmt("Token : %s", token2str(buf, sizeof(buf), h.token)); + add_pgm_cmt("Creator : %s", token2str(buf, sizeof(buf), h.appl)); + add_pgm_cmt("Release : %u.%u.%u.%u", + h.release.versmaj, + h.release.versmin, + h.release.revmaj, + h.release.revmin); + add_pgm_cmt("Protocol : %u.%03u", + h.protocol.vers, + h.protocol.rev); + add_pgm_cmt("Flags : %04X", h.flags); + add_pgm_cmt("Password : %.*s", int(sizeof(h.password)), h.password); + add_pgm_cmt("User info : %s", geos2ibm(buf, h.info, sizeof(h.info))); + add_pgm_cmt("Copyright : %s", geos2ibm(buf, h._copyright, sizeof(h._copyright))); +} + +//-------------------------------------------------------------------------- +void idaapi load_file(linput_t *li, uint16 /*neflag*/, const char * /*fileformatname*/) +{ + set_processor_type("metapc", SETPROC_LOADER); + + union + { + GEOSheader h1; + GEOS2header h2; + } h; + qlseek(li, 0); + lread(li, &h, sizeof(h)); + + int32 apppos; + int32 fdelta; + if ( h.h1.ID == GEOS_ID ) + { + apppos = 0xC8; + fdelta = 0; + } + else + { + apppos = sizeof(GEOS2header); + fdelta = apppos; + } + + load_application(li, apppos, fdelta); + + create_filename_cmt(); + if ( h.h1.ID == GEOS_ID ) + show_geos1(h.h1); + else + show_geos2(h.h2); + + inf_set_cc_cm(inf_get_cc_cm() | C_PC_LARGE); + add_til("geos", ADDTIL_DEFAULT); +} + +//-------------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk75/ldr/geos/geos.h b/idasdk76/ldr/geos/geos.h similarity index 100% rename from idasdk75/ldr/geos/geos.h rename to idasdk76/ldr/geos/geos.h diff --git a/idasdk75/ldr/geos/geos2.h b/idasdk76/ldr/geos/geos2.h similarity index 100% rename from idasdk75/ldr/geos/geos2.h rename to idasdk76/ldr/geos/geos2.h diff --git a/idasdk76/ldr/geos/makefile b/idasdk76/ldr/geos/makefile new file mode 100644 index 0000000..2171d40 --- /dev/null +++ b/idasdk76/ldr/geos/makefile @@ -0,0 +1,14 @@ +PROC=geos + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)geos$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)enum.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp \ + $(I)struct.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaldr.h common.cpp geos.cpp geos.h geos2.h diff --git a/idasdk76/ldr/hex/hex.cpp b/idasdk76/ldr/hex/hex.cpp new file mode 100644 index 0000000..22e6c47 --- /dev/null +++ b/idasdk76/ldr/hex/hex.cpp @@ -0,0 +1,624 @@ +#define BUFFSIZE ((255+6)*2+76) // buffer to read the string +#define MAX_BYTES 24 // Max number of bytes per line for write +#define SEGMENTGAP (1*1024*1024) // make new segment if gap between addresses + // is greater than this value +#define SPARSE_GAP (256*1024) // switch to sparse storage if the gap + // is greater than this value + +/* + * This Loader Module is written by Ilfak Guilfanov and + * rewriten by Yury Haron + * + */ + +/* + Interesting documentation: + + http://www.intel.com/design/zapcode/Intel_HEX_32_Format.doc + http://www.keil.com/support/docs/1584.htm + +*/ + +#include "../idaldr.h" + +//-------------------------------------------------------------------------- +static int idaapi accept_file( + qstring *fileformatname, + qstring *, + linput_t *li, + const char *) +{ + char str[80]; + if ( qlgets(str, sizeof(str), li) == NULL ) + return 0; + + const char *p = str; + while ( *p == ' ' ) + p++; + + int type = 0; + if ( qisxdigit((uchar)*(p+1)) && qisxdigit((uchar)*(p+2)) ) + { + switch ( *p ) + { + case ':': + p = "Intel Hex Object Format"; + type = f_HEX; + break; + + case ';': + p = "MOS Technology Hex Object Format"; + type = f_MEX; + break; + + case 'S': + p = "Motorola S-record Format"; + type = f_SREC; + default: + break; + + } + } + if ( type != 0 ) + *fileformatname = p; + return type; +} + +//-------------------------------------------------------------------------- +// this struct was created to save space in the data segment (yes, we were +// counting each byte at that time) +static struct local_data +{ + union + { + char *ptr; // load + int sz; // write + }; + union + { + uint32 ln; // load + int size; // write + }; + ushort sum; // load/write + uchar len; // load +} lc; + +//-------------------------------------------------------------------------- +NORETURN static void errfmt(void) +{ + loader_failure("Bad hex input file format, line %u", lc.ln); +} + +//-------------------------------------------------------------------------- +// reads the specified number of bytes from the input line +// if size==0, then initializes itself for a new line +static uint32 hexdata(int size) +{ + int i = size; + if ( i == 0 ) + { + i = 2; + } + else + { + if ( lc.len < i ) + errfmt(); + lc.len -= (uchar)i; + i <<= 1; + } + char n[10]; + char *p = n; + while ( i-- ) + *p++ = *lc.ptr++; + *p = '\0'; + char *endp; + uint32 data = strtoul(n, &endp, 16); + if ( endp != p ) + errfmt(); + switch ( size ) + { + case 0: + lc.len = (uchar)data; + lc.sum = lc.len; + break; + + case 4: + lc.sum += (uchar)(data >> 24); + case 3: + lc.sum += (uchar)(data >> 16); + case 2: + lc.sum += (uchar)(data >> 8); + default: // 1 + lc.sum += (uchar)data; + break; + } + return data; +} + +//-------------------------------------------------------------------------- +void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/) +{ + memset(&lc, 0, sizeof(local_data)); + inf_set_start_ip(BADADDR); // f_SREC without start record + + processor_t &ph = PH; + bool iscode = (neflag & NEF_CODE) != 0; + uint bs = iscode ? ph.cbsize() : ph.dbsize(); // number of bytes + ea_t start_ea = to_ea(inf_get_baseaddr(), 0); + sel_t sel = setup_selector(start_ea >> 4); + bool segment_created = false; + + bool cvt_to_bytes = false; + if ( ph.id == PLFM_PIC ) + { + // pic12xx and pic16xx use 12-bit and 14-bit words in program memory + // pic18xx uses 16-bit opcodes but byte addressing + if ( strncmp(inf_get_procname().c_str(), "PIC18", 5) != 0 ) + { + static const char *const form = +// "PIC HEX file addressing mode\n" +// "\n" + "There are two flavors of HEX files for PIC: with word addressing\n" + "and with byte addressing. It is not possible to recognize the\n" + "flavor automatically. Please specify what addressing mode should\n" + "be used to load the input file. If you don't know, try both and\n" + "choose the one which produces the more meaningful result\n"; + int code = ask_buttons("~B~yte addressing", + "~W~ord addressing", + "~C~ancel", + 1, + form); + switch ( code ) + { + case 1: + break; + case 0: + cvt_to_bytes = true; + break; + default: + loader_failure(); + } + } + } + + bool bs_addr_scale = true; + if ( ph.id == PLFM_TMS320C28 ) + bs_addr_scale = false; + + filetype_t ftype = inf_get_filetype(); + char rstart = (ftype == f_SREC) ? 'S' + : (ftype == f_HEX) ? ':' + : ';'; + ea_t addr; + ea_t end_ea = 0; + ea_t seg_start = 0; + ea_t subs_addr20 = 0; + ea_t subs_addr32 = 0; + bool bigaddr = false; + char line[BUFFSIZE]; + for ( lc.ln = 1; qlgets(line, BUFFSIZE, li); lc.ln++ ) + { + char *p = line; + while ( *p == ' ' ) + ++p; + if ( *p == '\n' || *p == '\r' ) + continue; + if ( *p++ != rstart ) + errfmt(); + + int sz = 2; + int mode = (ftype == f_SREC) ? (uchar)*p++ : 0x100; + lc.ptr = p; + hexdata(0); + if ( mode == 0x100 ) + { + if ( !lc.len ) + break; + lc.len += 2; + if ( ftype == f_HEX ) + ++lc.len; + } + else + { + switch ( mode ) + { + default: + errfmt(); + + case '0': + case '5': + continue; + + case '3': + case '7': + ++sz; + // fallthrough + case '2': + case '8': + ++sz; + // fallthrough + case '1': + case '9': + if ( mode > '3' ) + mode = 0; + --lc.len; + break; + } + } + addr = hexdata(sz); + if ( ftype != f_SREC && bs_addr_scale ) + addr = addr / bs; + if ( !mode ) + { + inf_set_start_ip(addr); + continue; + } + + if ( ftype == f_HEX ) + { + int type = hexdata(1); // record type + switch ( type ) + { + case 0xFF: // mitsubishi hex format + case 4: // Extended linear address record (bits 16..31 of the start address) + { + uint32 seg_addr = uint32(hexdata(2) << 16); + if ( bs_addr_scale ) + seg_addr /= bs; + subs_addr32 = seg_addr; + } + break; + case 2: // Extended segment address record (bits 4..19 of the start address) + { + uint32 seg_addr = uint32(hexdata(2) << 4); + if ( bs_addr_scale ) + seg_addr /= bs; + subs_addr20 = seg_addr; + } + break; + case 5: // start address (ARM) + { + uint32 start_addr = hexdata(4); + if ( ph.has_code16_bit() && (start_addr & 1) != 0 ) + { + processor_t::set_code16_mode(start_addr, true); + start_addr &= ~1; + } + inf_set_start_ip(start_addr); + inf_set_start_ea(start_addr); + } + break; + } + if ( type != 0 ) + { + if ( type == 1 ) + break; // end of file record + continue; // not a data record + } + } + // add the extended address bits + addr += subs_addr20; + addr += subs_addr32; + if ( lc.len ) + { + ea_t top = addr + lc.len / bs; + p = line; + while ( lc.len ) + { + *p++ = (uchar)hexdata(1); + if ( cvt_to_bytes ) // pic + *p++ = '\0'; + } + if ( top >= 0x10000 ) + bigaddr = true; + addr += start_ea; + show_addr(addr); + top += start_ea; + if ( top > end_ea || !segment_created ) + { + asize_t delta = addr - end_ea; + if ( delta >= SEGMENTGAP ) + segment_created = false; // force creation of new segment + + end_ea = top; + if ( neflag & NEF_SEGS ) + { + if ( !segment_created ) + { + if ( !add_segm(sel, addr, end_ea, NULL, iscode ? CLASS_CODE : CLASS_DATA) ) + loader_failure(); + segment_created = true; + seg_start = addr; + } + else + { + int flags = delta > SPARSE_GAP ? SEGMOD_SPARSE : 0; + set_segm_end(seg_start, end_ea, flags); + } + } + } + if ( seg_start > addr ) + { + if ( (neflag & NEF_SEGS) != 0 ) + { + int flags = seg_start-addr > SPARSE_GAP ? SEGMOD_SPARSE : 0; + set_segm_start(seg_start, addr, flags); + } + seg_start = addr; + } + mem2base(line, addr, top, -1); + } + { + ushort chi; // checksum + ++lc.len; + switch ( ftype ) + { + case f_SREC: + chi = (uchar)(~lc.sum); + chi ^= (uchar)hexdata(1); + break; + case f_HEX: + hexdata(1); + chi = (uchar)lc.sum; + break; + default: // MEX + ++lc.len; + chi = lc.sum; + chi -= (ushort)hexdata(2); + break; + } + if ( chi ) + { + static bool displayed = false; + if ( !displayed ) + { + displayed = true; + warning("Bad hex input file checksum, line %u. Ignore?", lc.ln); + } + } + } + } + + if ( (neflag & NEF_SEGS) != 0 ) + { + if ( bigaddr ) + { + set_segm_addressing(get_first_seg(), 1); + if ( ph.id == PLFM_386 ) + inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); + } + set_default_dataseg(sel); + inf_set_start_cs(sel); + } + else + { + enable_flags(start_ea, end_ea, STT_CUR); + } + inf_set_af(inf_get_af() & ~AF_FINAL); // behave as a binary file + + create_filename_cmt(); +} + +//-------------------------------------------------------------------------- +static int set_s_type(ea_t addr) +{ + int off = 0; + lc.sz = 4; + lc.size += 3; + if ( addr >= 0x10000 ) + { + ++off; + lc.sz += 2; + lc.sum += (uchar)(addr >> 16); + ++lc.size; + if ( addr >= 0x01000000 ) + { + ++off; + lc.sz += 2; + lc.sum += (uchar)(addr >> 24); + ++lc.size; + } + } + return off; +} + +//-------------------------------------------------------------------------- +GCC_DIAG_OFF(format-nonliteral); +int idaapi write_file(FILE *fp, const char * /*fileformatname*/) +{ +//#define TEST_COMPILATION +#ifdef TEST_COMPILATION +# define DECL_FMT(x, y) static const char *const x = y +#else +# define DECL_FMT(x, y) static char x[] = y +#endif + DECL_FMT(fmt0, "%02X%0*" FMT_EA "X%s%0?X\r\n"); + DECL_FMT(fmt1, "?00?00001FF\r\n"); + DECL_FMT(fone, "%02X"); + + ea_t base = to_ea(inf_get_baseaddr(), 0); + if ( inf_get_min_ea() < base ) + base = BADADDR; + + if ( fp == NULL ) + { + if ( inf_get_filetype() == f_SREC ) + return 1; + ea_t ea1 = inf_get_max_ea() - inf_get_min_ea(); + if ( ea1 <= 0x10000 ) + return 1; + ea_t strt = 0; + ea_t addr; + for ( addr = inf_get_min_ea(); addr < inf_get_max_ea(); ) + { + segment_t *ps = getseg(addr); + if ( ps == NULL || ps->type != SEG_IMEM ) + { + if ( is_loaded(addr) ) + break; + if ( base != BADADDR ) + { + if ( --ea1 <= 0x10000 ) + return 1; + } + else + { + ++strt; + } + ++addr; + continue; + } + if ( strt ) + { + ea1 -= strt; + if ( ea1 != 0x10000 ) + return 1; + strt = 0; + } + ea1 -= (ps->end_ea - addr); + if ( ea1 < 0x10000 ) + return 1; + ++ea1; + addr = ps->end_ea; + } + if ( base == BADADDR ) + { + segment_t *ps = getseg(addr); + ea1 -= (ps == NULL) ? addr : ps->start_ea; + if ( ea1 <= 0x10000 ) + return 1; + } + if ( addr == inf_get_max_ea() ) + return 0; + for ( base = inf_get_max_ea()-1; base > addr; ) + { + segment_t *ps = getseg(base); + if ( ps == NULL || ps->type != SEG_IMEM ) + { + if ( is_loaded(base) ) + break; + if ( --ea1 <= 0x10000 ) + return 1; + --base; + continue; + } + ea1 -= (base - ps->start_ea); + if ( ea1 < 0x10000 ) + return 1; + ++ea1; + base = ps->start_ea; + } + return 0; + } + + char ident; + const char *found = qstrrchr(fmt0, '?'); + QASSERT(20067, found != NULL); + int fmt0_marker = ((char *) found) - fmt0; + fmt0[fmt0_marker] = '2'; + switch ( inf_get_filetype() ) + { + case f_SREC: + ident = 'S'; + break; + case f_HEX: + ident = ':'; + fmt1[3] = '0'; + break; + default: + ident = ';'; + fmt0[fmt0_marker] = '4'; + fmt1[3] = '\0'; + break; + } + fmt1[0] = ident; + lc.sz = 4; + + ea_t strt = inf_get_start_ip(); + for ( ea_t ea1 = inf_get_min_ea(); ea1 < inf_get_max_ea(); ) + { + char str[(2 * MAX_BYTES) + 3]; + char *const end = str + sizeof(str); + if ( !is_loaded(ea1) || segtype(ea1) == SEG_IMEM ) + { + ++ea1; + continue; + } + if ( base == BADADDR ) + { + segment_t *ps = getseg(ea1); + base = ps == NULL ? ea1 : ps->start_ea; + if ( strt != BADADDR ) + strt += inf_get_min_ea() - base; + } + ea_t addr = ea1 - base; + lc.sum = (uchar)addr + (uchar)(addr >> 8); + char *p = str; + if ( inf_get_filetype() == f_HEX ) + { + *p++ = '0'; + *p++ = '0'; + } + lc.size = 0; + do + { + uchar b = get_byte(ea1++); + p += qsnprintf(p, end-p, fone, (unsigned)b); + lc.sum += b; + } while ( ++lc.size < MAX_BYTES + && ea1 < inf_get_max_ea() + && is_loaded(ea1) + && segtype(ea1) != SEG_IMEM ); + qfputc(ident, fp); + if ( inf_get_filetype() == f_SREC ) + { + char type = '1' + (char)set_s_type(addr); + qfputc(type, fp); + ++lc.sum; // correct to NOT + } // else addr = (ushort)addr; // force check + lc.sum += (ushort)lc.size; + if ( inf_get_filetype() != f_MEX ) + lc.sum = (uchar)(0-lc.sum); + qfprintf(fp, fmt0, lc.size, lc.sz, addr, str, lc.sum); + } + if ( inf_get_filetype() != f_SREC ) + { + qfprintf(fp, "%s", fmt1); + } + else if ( strt != BADADDR ) + { + qfputc(ident, fp); + lc.sum = 0; + lc.size = 0; + char type = '9' - (char)set_s_type(strt); + qfputc(type, fp); + lc.sum = (~(lc.size + lc.sum)) & 0xFF; + qfprintf(fp, fmt0, lc.size, lc.sz, strt, &fone[sizeof(fone)-1], lc.sum); + } + return 1; +} +GCC_DIAG_ON(format-nonliteral); + +//-------------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + LDRF_REQ_PROC, // requires the target processor to the set +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + write_file, + NULL, + NULL, +}; diff --git a/idasdk76/ldr/hex/makefile b/idasdk76/ldr/hex/makefile new file mode 100644 index 0000000..cfc810a --- /dev/null +++ b/idasdk76/ldr/hex/makefile @@ -0,0 +1,13 @@ +PROC=hex + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)hex$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h hex.cpp diff --git a/idasdk75/ldr/hpsom/common.cpp b/idasdk76/ldr/hpsom/common.cpp similarity index 100% rename from idasdk75/ldr/hpsom/common.cpp rename to idasdk76/ldr/hpsom/common.cpp diff --git a/idasdk75/ldr/hpsom/hpsom.cpp b/idasdk76/ldr/hpsom/hpsom.cpp similarity index 100% rename from idasdk75/ldr/hpsom/hpsom.cpp rename to idasdk76/ldr/hpsom/hpsom.cpp diff --git a/idasdk75/ldr/hpsom/hpsom.hpp b/idasdk76/ldr/hpsom/hpsom.hpp similarity index 100% rename from idasdk75/ldr/hpsom/hpsom.hpp rename to idasdk76/ldr/hpsom/hpsom.hpp diff --git a/idasdk76/ldr/hpsom/makefile b/idasdk76/ldr/hpsom/makefile new file mode 100644 index 0000000..2611ace --- /dev/null +++ b/idasdk76/ldr/hpsom/makefile @@ -0,0 +1,14 @@ +PROC=hpsom + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)hpsom$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ + common.cpp hpsom.cpp hpsom.hpp diff --git a/idasdk76/ldr/idaldr.h b/idasdk76/ldr/idaldr.h new file mode 100644 index 0000000..9735075 --- /dev/null +++ b/idasdk76/ldr/idaldr.h @@ -0,0 +1,212 @@ +#ifndef __IDALDR_H__ +#define __IDALDR_H__ + +#include <ida.hpp> +#include <fpro.h> +#include <idp.hpp> +#include <loader.hpp> +#include <name.hpp> +#include <bytes.hpp> +#include <offset.hpp> +#include <segment.hpp> +#include <segregs.hpp> +#include <fixup.hpp> +#include <entry.hpp> +#include <auto.hpp> +#include <diskio.hpp> +#include <kernwin.hpp> + +//---------------------------------- + +#define CLASS_CODE "CODE" +#define NAME_CODE ".text" +#define CLASS_DATA "DATA" +#define CLASS_CONST "CONST" +#define NAME_DATA ".data" +#define CLASS_BSS "BSS" +#define NAME_BSS ".bss" +#define NAME_EXTERN "extern" +#define NAME_COMMON "common" +#define NAME_ABS "abs" +#define NAME_UNDEF "UNDEF" +#define CLASS_STACK "STACK" +#define CLASS_RES16 "RESOURCE" +#define LDR_NODE "$ IDALDR node for ids loading $" +#define LDR_INFO_NODE "$ IDALDR node for unload $" + +//-------------------------------------------------------------------------- +template <class T> bool _validate_array_count( + linput_t *li, + T *p_cnt, + size_t elsize, + int64 current_offset=-1, + int64 max_offset=-1) +{ + if ( current_offset == -1 ) + current_offset = qltell(li); + if ( max_offset == -1 ) + max_offset = qlsize(li); + int64 rest = max_offset - current_offset; + T cnt = *p_cnt; + if ( current_offset >= 0 && rest >= 0 ) + { +#ifndef __X86__ + typedef size_t biggest_t; +#else + typedef ea_t biggest_t; +#endif + if ( is_mul_ok<biggest_t>(elsize, cnt) ) + { + biggest_t needed = elsize * cnt; +#ifdef __X86__ + if ( needed == size_t(needed) ) +#endif + if ( rest >= needed ) + return true; // all ok + } + cnt = rest / elsize; + } + else + { + cnt = 0; + } + *p_cnt = cnt; + return false; +} + +//-------------------------------------------------------------------------- +// Validate a counter taken from the input file. If there are not enough bytes +// in the input file, ask the user if we may continue and fix the counter. +template <class T> void validate_array_count( + linput_t *li, + T *p_cnt, + size_t elsize, + const char *counter_name, + int64 curoff=-1, + int64 maxoff=-1) +{ + T old = *p_cnt; + if ( !_validate_array_count(li, p_cnt, elsize, curoff, maxoff) ) + { + static const char *const format = + "AUTOHIDE SESSION\n" + "HIDECANCEL\n" + "%s %" FMT_64 "u is incorrect, maximum possible value is %" FMT_64 "u%s"; +#ifndef __KERNEL__ + if ( ask_yn(ASKBTN_YES, + format, + counter_name, + uint64(old), + uint64(*p_cnt), + ". Do you want to continue with the new value?") != ASKBTN_YES ) + { + loader_failure(NULL); + } +#else + warning(format, counter_name, uint64(old), uint64(*p_cnt), ""); +#endif + } +} + +//-------------------------------------------------------------------------- +// Validate a counter taken from the input file. If there are not enough bytes +// in the input file, die. +template <class T> void validate_array_count_or_die( + linput_t *li, + T cnt, + size_t elsize, + const char *counter_name, + int64 curoff=-1, + int64 maxoff=-1) +{ + if ( !_validate_array_count(li, &cnt, elsize, curoff, maxoff) ) + { + static const char *const format = + "%s is incorrect, maximum possible value is %u%s"; +#ifndef __KERNEL__ + loader_failure(format, counter_name, uint(cnt), ""); +#else + error(format, counter_name, uint(cnt), ""); +#endif + } +} + +//------------------------------------------------------------------------- +// Read a string table in COFF format. +inline bool read_string_table(qstring *out, linput_t *li, qoff64_t filepos=0, bool mf=false) +{ + if ( filepos != 0 && qlseek(li, filepos, SEEK_SET) != filepos ) + return false; + // read the string table length + uint32 strtsize; + if ( qlread(li, &strtsize, 4) != 4 ) + return false; + if ( mf ) + strtsize = swap32(strtsize); + + // it includes the length field itself, so should be greater than 4 + if ( strtsize <= 4 ) + return false; // too small table + + qlseek(li, -4, SEEK_CUR); +#ifdef LOADER_COMPILE + // Loaders display a message about the problematic size, to inform the user + // and give him a choice. + validate_array_count(li, &strtsize, 1, "String table size"); +#else + // Other modules silently fail. + if ( !_validate_array_count(li, &strtsize, 1) ) + return false; +#endif + + char *stable = (char *)qalloc(strtsize + 1); + if ( stable == NULL ) + return false; // out of memory?! + + bool ok; + if ( qlread(li, stable, strtsize) == strtsize ) + { + stable[strtsize] = '\0'; + out->clear(); + out->inject(stable, strtsize + 1); + ok = true; + } + else + { + qfree(stable); + ok = false; + } + return ok; +} + +//------------------------------------------------------------------------- +inline uchar readchar(linput_t *li) +{ + uchar x; + lread(li, &x, sizeof(x)); + return x; +} + +//------------------------------------------------------------------------- +inline uint16 readshort(linput_t *li) +{ + uint16 x; + lread(li, &x, sizeof(x)); + return x; +} + +//------------------------------------------------------------------------- +inline uint32 readlong(linput_t *li) +{ + uint32 x; + lread(li, &x, sizeof(x)); + return x; +} + +inline uint32 mf_readlong(linput_t *li) { return swap32(readlong(li)); } +inline uint16 mf_readshort(linput_t *li) { return swap16(readshort(li)); } + +// each loader must declare and export this symbol: +idaman loader_t ida_module_data LDSC; + +#endif // __IDALDR_H__ diff --git a/idasdk75/ldr/intelomf/common.cpp b/idasdk76/ldr/intelomf/common.cpp similarity index 100% rename from idasdk75/ldr/intelomf/common.cpp rename to idasdk76/ldr/intelomf/common.cpp diff --git a/idasdk75/ldr/intelomf/intelomf.cpp b/idasdk76/ldr/intelomf/intelomf.cpp similarity index 100% rename from idasdk75/ldr/intelomf/intelomf.cpp rename to idasdk76/ldr/intelomf/intelomf.cpp diff --git a/idasdk75/ldr/intelomf/intelomf.hpp b/idasdk76/ldr/intelomf/intelomf.hpp similarity index 100% rename from idasdk75/ldr/intelomf/intelomf.hpp rename to idasdk76/ldr/intelomf/intelomf.hpp diff --git a/idasdk76/ldr/intelomf/makefile b/idasdk76/ldr/intelomf/makefile new file mode 100644 index 0000000..145723b --- /dev/null +++ b/idasdk76/ldr/intelomf/makefile @@ -0,0 +1,14 @@ +PROC=intelomf + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)intelomf$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h common.cpp intelomf.cpp \ + intelomf.hpp diff --git a/idasdk75/ldr/javaldr/javaldr.cpp b/idasdk76/ldr/javaldr/javaldr.cpp similarity index 100% rename from idasdk75/ldr/javaldr/javaldr.cpp rename to idasdk76/ldr/javaldr/javaldr.cpp diff --git a/idasdk76/ldr/javaldr/makefile b/idasdk76/ldr/javaldr/makefile new file mode 100644 index 0000000..31f8f88 --- /dev/null +++ b/idasdk76/ldr/javaldr/makefile @@ -0,0 +1,15 @@ +PROC=javaldr + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)javaldr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../../module/java/classfil.hpp \ + ../../module/java/notify_codes.hpp ../idaldr.h \ + javaldr.cpp diff --git a/idasdk76/ldr/loader.mak b/idasdk76/ldr/loader.mak new file mode 100644 index 0000000..eb486e8 --- /dev/null +++ b/idasdk76/ldr/loader.mak @@ -0,0 +1,15 @@ + +__FUZZ_LOADERS__=1 + +SRC_PATH = $(IDA)ldr/ +BIN_PATH = $(R)loaders/ + +BASE_OBJS += $(F)$(PROC)$(O) + +ifdef __NT__ + DLLFLAGS += /BASE:0x140000000 +endif + +CC_DEFS += LOADER_COMPILE + +include ../../module.mak diff --git a/idasdk75/ldr/makefile b/idasdk76/ldr/makefile similarity index 100% rename from idasdk75/ldr/makefile rename to idasdk76/ldr/makefile diff --git a/idasdk76/ldr/mas/makefile b/idasdk76/ldr/mas/makefile new file mode 100644 index 0000000..00dffb8 --- /dev/null +++ b/idasdk76/ldr/mas/makefile @@ -0,0 +1,13 @@ +PROC=mas + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)mas$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h mas.cpp mas.hpp diff --git a/idasdk76/ldr/mas/mas.cpp b/idasdk76/ldr/mas/mas.cpp new file mode 100644 index 0000000..e544f11 --- /dev/null +++ b/idasdk76/ldr/mas/mas.cpp @@ -0,0 +1,407 @@ + +// Loader for the Macro-assembler-related binary format + +#include "../idaldr.h" +#include "mas.hpp" + +// undefine this to print some debugging information +// in the IDA console. +//#define DEBUG + +//----------------------------------------------------------------------------- +struct gas_family +{ + uchar code; + const char *processor; //lint !e958 padding is required to align members +}; + +static const struct gas_family families[] = +{ + { 0x01, "68k" }, + // 0x03 : M*Core + { 0x05, "ppc" }, + { 0x09, "dsp56k" }, + { 0x11, "m740" }, + // 0x12 : MELPS-4500 + // 0x13 : M16 + // 0x14 : M16C + // 0x15 : F2MC8L + { 0x16, "f2mc16l" }, + { 0x19, "m7700" }, + // 0x21 : MCS-48 + // 0x25 : SYM53C8xx + // 0x29 : 29xxx + { 0x2A, "i960b" }, // little or big endian ???? + // 0x31 : MCS-51 + { 0x32, "st9" }, + { 0x33, "st7" }, + // 0x38 : 1802/1805 + // 0x39 : MCS-96/196/296 + // 0x3A : 8X30x + { 0x3B, "avr" }, + // 0x3C : XA + // 0x3F : 4004/4040 + { 0x41, "8085" }, + { 0x42, "8086" }, + { 0x47, "tms320c6" }, + // 0x48 : TMS9900 + // 0x49 : TMS370xxx + // 0x4A : MSP430 + { 0x4B, "tms32054" }, + { 0x4C, "c166" }, + { 0x51, "z80" }, + // 0x52 : TLCS-900 + // 0x53 : TLCS-90 + // 0x54 : TLCS-870 + // 0x55 : TLCS-47 + // 0x56 : TLCS-9000 + { 0x61, "6800" }, + { 0x62, "6805" }, + { 0x63, "6809" }, + // 0x64 : 6804 + // 0x65 : 68HC16 + // 0x66 : 68HC12 + // 0x67 : ACE + { 0x68, "h8300" }, + { 0x69, "h8500" }, + // 0x6C : SH7000 + // 0x6C : SC14xxx + // 0x6C : SC/MP + // 0x6C : COP8 + { 0x70, "pic16cxx" }, + { 0x71, "pic16cxx" }, + // 0x72 : PIC17C4x + // 0x73 : TMS-7000 + // 0x74 : TSM3201x + // 0x75 : TSM320C2x + // 0x76 : TSM320C3x + { 0x77, "tms320c2" }, + // 0x78 : ST6uPD772 + { 0x79, "z8" } + // 0x7A : uPD78(C)10 + // 0x7B : 75K0 + // 0x7C : 78K0 + // 0x7D : uPD7720 + // 0x7E : uPD7725 + // 0x7F : uPD77230 +}; + +static char creator[MAXSTR]; // program name which created the binary +static int entry_point; // address of the entry point +static const char *set_proc = NULL; + +//----------------------------------------------------------------------------- +// output an error and exit loader. +AS_PRINTF(1, 2) NORETURN static void mas_error(const char *format, ...) +{ + char b[MAXSTR]; + va_list va; + + va_start(va, format); + qvsnprintf(b, sizeof(b), format, va); + va_end(va); + loader_failure("mas loader critical error: %s", b); +} + +//----------------------------------------------------------------------------- +// set the current processor type according to "cpu_type". +static bool mas_set_cpu(uchar cpu_type) +{ + for ( int i = 0; i < qnumber(families); i++ ) + { + if ( families[i].code != cpu_type ) + continue; + + const char *proc = families[i].processor; + if ( set_proc != NULL && !streq(proc, set_proc) ) + mas_error("only one processor record is allowed"); + + set_proc = proc; + set_processor_type(proc, SETPROC_LOADER); +#if defined(DEBUG) + msg("MAS: detected processor %s\n", proc); +#endif + return true; + } + return false; +} + +//----------------------------------------------------------------------------- +// return a segment name according to its "segment_type". +static const char *mas_get_segname(uchar segment_type) +{ + switch ( segment_type ) + { + case 0x00: return "UNDEFINED"; + case 0x01: return "CODE"; + case 0x02: return "DATA"; + case 0x03: return "IDATA"; + case 0x04: return "XDATA"; + case 0x05: return "YDATA"; + case 0x06: return "BDATA"; + case 0x07: return "IO"; + case 0x08: return "REG"; + case 0x09: return "ROMDATA"; + } + return NULL; +} + +//----------------------------------------------------------------------------- +// write comments. +static void mas_write_comments(void) +{ + create_filename_cmt(); + + char entry_point_str[20]; + if ( entry_point == -1 ) + qstrncpy(entry_point_str, "NOT DETECTED", sizeof(entry_point_str)); + else + qsnprintf(entry_point_str, sizeof(entry_point_str), "0x%X", entry_point); + + // write name of the creator program + add_pgm_cmt("Creator program : %s", creator); + // write address of the entry point + add_pgm_cmt("Entry point : %s", entry_point_str); +} + +//----------------------------------------------------------------------------- +// detect macro assembler files using the start sequence. +static int idaapi accept_file( + qstring *fileformatname, + qstring *, // too difficult to determine the processor + linput_t *li, + const char *) +{ + // read the first word + uint16 word = 0; + if ( qlread(li, &word, 2) != 2 ) + return 0; + +#if defined(DEBUG) + msg("MAS: 2 first bytes : 0x%X\n", word); +#endif + + // first word must match the start_sequence + if ( word != START_SEQUENCE ) + return 0; + + *fileformatname = "Macro Assembler by Alfred Arnold"; +#if defined(DEBUG) + msg("MAS: detected mas binary file !\n"); +#endif + return 1; +} + +//----------------------------------------------------------------------------- +static void load_bytes(linput_t *li, ea_t ea, asize_t size, const char *segname) +{ + // validate the segment size + ea_t end = ea + size; + qoff64_t curpos = qltell(li); + qoff64_t endpos = curpos + size; + if ( ea == BADADDR || end < ea || endpos < curpos || endpos > qlsize(li) ) + mas_error("wrong or too big segment %a..%a", ea, end); + + // send code in the database + file2base(li, curpos, ea, end, FILEREG_PATCHABLE); + + // set selector + sel_t selector = allocate_selector(0); + + // create data segment + add_segm(selector, ea, end, segname, segname, ADDSEG_SPARSE); +} + +//----------------------------------------------------------------------------- +static void check_target_processor() +{ + if ( PH.id == -1 ) + loader_failure("Failed to determine the target processor, please specify it manually"); +} + +//----------------------------------------------------------------------------- +// process a file record according to its "record_type". +// return true if there is no more records to process. +static bool process_record(linput_t *li, const uchar record_type, bool load) +{ + bool finished = false; + + switch ( record_type ) + { + // A record with a header byte of $81 is a record that may contain code or + // data from arbitrary segments. + // + // header : 1 byte + // segment : 1 byte + // gran : 1 byte + // start_addr : 4 bytes (entry point) + // length : 2 bytes + // data : length bytes + case 0x81: + { + mas_header_t header; + memset(&header, 0, sizeof(header)); + + // read the header + if ( qlread(li, &header, sizeof(header)) != sizeof(header) ) + mas_error("unable to read header (%" FMT_Z " bytes)", sizeof(header)); + + // granularities that differ from 1 are rare and mostly appear + // in DSP CPU's that are not designed for byte processing. + if ( header.gran != 1 ) + mas_error("unsupported granularity (%d)", header.gran); + + // set processor + if ( !mas_set_cpu(header.header) ) + mas_error("processor type '0x%X' is currently unsupported", header.header); + if ( !load ) // we have the processor, nothing else to do + { + finished = true; + break; + } + + // get segment name + const char *segname = mas_get_segname(header.segment); + if ( segname == NULL ) + mas_error("invalid segment '0x%X'", header.segment); + +#if defined(DEBUG) + msg("MAS: ready to read %d bytes (0x%X -> 0x%X)\n", + header.length, header.start_addr, header.start_addr + header.length); +#endif + load_bytes(li, header.start_addr, header.length, segname); + } + break; + + // The last record in a file bears the Header $00 and has only a string as + // data field. This string does not have an explicit length specification; + // its end is equal to the file's end. + // + // The string contains only the name of the program that created the file + // and has no further meaning. + // + // creator : x bytes + case 0x00: + { + uint32 length = qlsize(li) - qltell(li); +#if defined(DEBUG) + msg("MAS: creator length : %ld bytes\n", length); +#endif + if ( length >= sizeof(creator) ) + mas_error("creator length is too large (%u >= %" FMT_Z, + length, sizeof(creator)); + ssize_t tmp = qlread(li, creator, length); + if ( tmp != length ) + mas_error("unable to read creator string (i read %" FMT_ZS")", tmp); + creator[length] = '\0'; + } + finished = true; + break; + + // entry_point : 4 bytes + case 0x80: + { + if ( qlread(li, &entry_point, 4) != 4 ) + mas_error("unable to read entry_point"); + if ( load ) + { +#if defined(DEBUG) + msg("MAS: detected entry point : 0x%X\n", entry_point); +#endif + inf_set_start_ip(entry_point); // entry point + segment_t *s = getseg(entry_point); + inf_set_start_cs(s ? s->sel : 0); // selector of code + } + } + break; + + default: + // start_addr : 4 bytes + // length : 2 bytes + // data : length bytes + if ( record_type >= 0x01 && record_type <= 0x7F ) + { + check_target_processor(); + + struct + { + int start_addr; + short length; + } header; + + memset(&header, 0, sizeof(header)); + + // read the header + if ( qlread(li, &header, sizeof(header)) != sizeof(header) ) + mas_error("unable to read header (%" FMT_Z " bytes)", sizeof(header)); + + if ( load ) + load_bytes(li, header.start_addr, header.length, "DATA"); + else + qlseek(li, qltell(li)+header.length); + } + else + { + mas_error("invalid record type '0x%X'\n", record_type); + } + } + return finished; +} + +//----------------------------------------------------------------------------- +// load a macro assembler file in IDA. +void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) +{ + // already read the 2 first bytes + qlseek(li, 2); + + // initialize static variables + qstrncpy(creator, "UNKNOWN", sizeof(creator)); + entry_point = -1; + + bool finished = false; + while ( !finished ) + { + uchar record_type = 0; + + // read the record type + if ( qlread(li, &record_type, 1) != 1 ) + mas_error("unable to read the record type"); + + finished = process_record(li, record_type, true); + } + +#if defined(DEBUG) + msg("MAS: reading complete\n"); +#endif + + check_target_processor(); + + mas_write_comments(); +} + +//----------------------------------------------------------------------------- +// Loader description block +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk75/ldr/mas/mas.hpp b/idasdk76/ldr/mas/mas.hpp similarity index 100% rename from idasdk75/ldr/mas/mas.hpp rename to idasdk76/ldr/mas/mas.hpp diff --git a/idasdk76/ldr/nlm/makefile b/idasdk76/ldr/nlm/makefile new file mode 100644 index 0000000..6089eba --- /dev/null +++ b/idasdk76/ldr/nlm/makefile @@ -0,0 +1,14 @@ +PROC=nlm + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)nlm$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ + nlm.cpp nlm.h diff --git a/idasdk76/ldr/nlm/nlm.cpp b/idasdk76/ldr/nlm/nlm.cpp new file mode 100644 index 0000000..fa97893 --- /dev/null +++ b/idasdk76/ldr/nlm/nlm.cpp @@ -0,0 +1,1023 @@ +/* + * This Loader Module is written by Ilfak Guilfanov and + * rewriten by Yury Haron + * + */ +/* + L O A D E R for Netware Loadable Module (NLM) +*/ + +#include <stddef.h> +#include "../idaldr.h" +#include "nlm.h" +#include <typeinf.hpp> + +#pragma pack(push, 1) + +//-------------------------------------------------------------------------- +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + char magic[NLM_MAGIC_SIZE]; + + if ( qlread(li, magic, sizeof(magic)) != sizeof(magic ) + || memcmp(magic, NLM_MAGIC, sizeof(magic)) != 0 ) + { + return 0; + } + + *fileformatname = "Netware Loadable Module (NLM)"; + *processor = "metapc"; + return f_NLM; +} + +//-------------------------------------------------------------------------- +NORETURN static void _errstruct(int lnnum) +{ + loader_failure("Bad file structure or read error (line %d)", lnnum); +} +#define errstruct() _errstruct(__LINE__) + +//-------------------------------------------------------------------------- +//lint -e{958} padding needed +static struct local_data +{ + struct unp_data + { + FILE *fo; + uint32 pos, size; + uchar *buff; + ushort b_pos, b_val; + }; + + linput_t *li; + nlmexe_t nlm; + union + { + char buf[MAXSTR]; + unp_data unp; + }; //lint !e958 padding is required to align members + ea_t start, cbase, csize, dbase, dsize; + netnode impnode; +} lc; + +//-------------------------------------------------------------------------- +static int mread(void *buf, size_t size) +{ + if ( qlread(lc.li, buf, size) == size ) + return 0; + if ( ask_yn(ASKBTN_NO, + "HIDECANCEL\n" + "Read error or bad file structure. Continue loading?") <= ASKBTN_NO ) + { + loader_failure(); + } + return 1; +} + +//-------------------------------------------------------------------------- +static int getstr(void) +{ + uchar len; +#if MAXSTR < 256 +#error +#endif + + if ( mread(&len, sizeof(len)) || (len && mread(lc.buf, len)) ) + return 1; + lc.buf[len] = '\0'; + return 0; +} + +//---------------------------------------------------------------------- +static void set_reloc(ushort sel, ea_t fixaddr, ea_t toea, bool self_flag) +{ + sval_t displ = int32(get_dword(fixaddr)); + + fixup_data_t fd(FIXUP_OFF32); + fd.off = toea; + fd.sel = sel; + if ( sel == 3 ) + { + fd.set_extdef(); + fd.displacement = displ; + } + if ( self_flag ) + toea -= fixaddr; + put_dword(fixaddr, uint32(toea + displ)); + fd.set(fixaddr); +} + +//---------------------------------------------------------------------- +static void add_imports(void) +{ + if ( lc.nlm.impoff == 0 || lc.nlm.impnum == 0 ) + return; + uint32 i = lc.nlm.impnum; + msg("Creating imported names and relocating it...\n"); + lc.impnode.create(LDR_NODE); + qlseek(lc.li, lc.nlm.impoff, SEEK_SET); + ea_t ebase = lc.start; + ea_t eend = ebase + (i * sizeof(int32)); + uint64 fsize = qlsize(lc.li); + if ( lc.nlm.impoff >= fsize ) + loader_failure("Bad import offset"); + uint64 rest = fsize - lc.nlm.impoff; + if ( !is_mul_ok<uint32>(i, sizeof(int32)) + || eend <= ebase + || qoff64_t(i)*2 > rest ) // each name requires at least 2 bytes + { + loader_failure("Bad import count"); + } + + set_selector(3, 0); + if ( add_segm(3, ebase, eend, NAME_EXTERN, NULL) ) + { + segment_t *ps = getseg(ebase); + ps->type = SEG_XTRN; + ps->update(); + } + else + { + loader_failure(); + } + + uchar ss = inf_get_specsegs(); + for ( ; i; i--, ebase += ss ) + { + if ( getstr() ) + break; + show_addr(ebase); + set_name(ebase, lc.buf, SN_NOCHECK | SN_PUBLIC | SN_IDBENC); + if ( ss == 8 ) + put_qword(ebase, 0); + else + put_dword(ebase, 0); + if ( lc.impnode ) + netnode(lc.impnode).supset_ea(ebase, lc.buf); + uint32 fnum; + if ( mread(&fnum, sizeof(fnum)) ) + { +FORCE_END: + if ( (ebase += ss) < eend ) + set_segm_end(ebase, ebase, SEGMOD_KILL); + return; + } + int sff = 0; + while ( fnum-- ) + { + uint32 ent; + if ( mread(&ent, sizeof(ent)) ) + goto FORCE_END; + ea_t ea, sz; + bool self = (ent & 0x80000000) == 0; + if ( ent & 0x40000000 ) + { + ea = lc.cbase; + sz = lc.csize; + } + else + { + ea = lc.dbase; + sz = lc.dsize; + } + ent &= ~0xC0000000; + if ( ent >= sz ) + { + msg("Skip reference to extern '%s' with illegal offset 0x%X\n", + lc.buf, ent); + } + else + { + set_reloc(3, ea + ent, ebase, self); + if ( sff == 0 && self ) + { + ++sff; + add_func(ebase, ebase+ss-1); + } + } + } + } +} + +//-------------------------------------------------------------------------- +static void add_fixups(void) +{ + if ( lc.nlm.fixupoff == 0 || lc.nlm.fixupnum == 0 ) + return; + uint32 i = lc.nlm.fixupnum; + msg("Applying internal fixup records...\n"); + qlseek(lc.li, lc.nlm.fixupoff, SEEK_SET); + + validate_array_count_or_die(lc.li, i, 4, "Number of fixups", lc.nlm.fixupoff); + while ( i-- != 0 ) + { + uint32 ent; + if ( mread(&ent, sizeof(ent)) ) + break; + ea_t base, toea; + asize_t size; + if ( ent & 0x40000000 ) + { + base = lc.cbase; + size = lc.csize; + } + else + { + base = lc.dbase; + size = lc.dsize; + } + ushort sel; + if ( ent & 0x80000000 ) + { + toea = lc.cbase; + sel = 1; + } + else + { + toea = lc.dbase; + sel = 2; + } + ent &= ~0xC0000000; + if ( ent >= size || !toea ) + msg("Skip invalid relocation for offset 0x%X (to base %a)\n", ent, toea); + else + set_reloc(sel, ent + base, toea, 0); + } +} + +//-------------------------------------------------------------------------- +static void add_exports_and_publics(void) +{ + uint32 i, foff; + int pfl; + + for ( pfl = 0, foff = lc.nlm.expoff, i = lc.nlm.expnum; + pfl < 2; + pfl++, foff = lc.nlm.puboff, i = lc.nlm.pubnum ) + { + if ( foff == 0 || i == 0 ) + continue; + msg("Applying %s names...\n", pfl ? "public" : "exported"); + qlseek(lc.li, foff, SEEK_SET); + validate_array_count_or_die(lc.li, i, 4, + pfl ? "Number of publics" : "Number of exports", + foff); + while ( i-- != 0 ) + { + bool flag; + ea_t ea; + CASSERT(sizeof(flag) == 1); + if ( !pfl ) + { + if ( getstr() || mread(&ea, sizeof(uint32)) ) + break; + flag = (ea & 0x80000000) != 0; + } + else if ( mread(&flag, sizeof(flag)) + || mread(&ea, sizeof(uint32)) + || getstr() ) + { + break; + } + ea &= ~0xC0000000L; + ea_t base; + asize_t size; + if ( flag ) + { + base = lc.cbase; + size = lc.csize; + } + else + { + base = lc.dbase; + size = lc.dsize; + } + if ( ea >= size ) + { + msg("Skip name '%s' with illegal offset (0x%a)\n", lc.buf, ea); + } + else + { + ea += base; + add_entry(ea, ea, lc.buf, flag, AEF_IDBENC); + } + } + } +} + +//-------------------------------------------------------------------------- +static int LoadMsgString(void) +{ + int c, i; + for ( i = 0; i < sizeof(lc.buf)-1; i++ ) + { + if ( (c = qlgetc(lc.li)) == EOF ) + return 0; + if ( !c ) + break; + if ( c == 0xFF ) + { + c = '.'; + } + else if ( c < ' ' ) + { + static const char rpts[] = "\t\n\r\a\v\f"; + static const char rptc[] = "tnravf"; + const char *p = strchr(rpts, c); + if ( p ) + { + if ( i == sizeof(lc.buf)-2 ) + break; + lc.buf[i++] = '\\'; + c = (int)(uchar)rptc[(int)(p-rpts)]; + } + } + lc.buf[i] = (char)c; + } + lc.buf[i] = '\0'; + return 1; +} + +//-------------------------------------------------------------------------- +static uint32 addSpecialComment(void) +{ + uchar vp = 0, cp = 0; + uint32 mp = 0; + qoff64_t pos = qltell(lc.li); + ea_t loadbase = lc.nlm.codeoff; + if ( lc.nlm.datalen && loadbase > lc.nlm.dataoff ) + loadbase = lc.nlm.dataoff; + if ( loadbase > 0x1000 ) + loadbase = 0x1000; + + while ( pos + 12 < loadbase ) + { + if ( mread(lc.buf, 12) ) + break; + if ( !mp && !memcmp(lc.buf, "MeSsAgEs", 8) ) + { + mp = pos + 8; + pos += 0x7C; + goto repos; + } + if ( !vp && !memcmp(lc.buf, "VeRsIoN#", 8) ) + { + if ( mread(&lc.buf[12], 32-12) ) + break; + ++vp; + pos += 32 - 1; + qsnprintf(&lc.buf[32], sizeof(lc.buf)-32, "%u.%02u%c (%02u.%02u.%04u)", + *(uint32 *)&lc.buf[8], (uchar)lc.buf[8+4], + *(uint32 *)&lc.buf[8+8] ? (char)(lc.buf[8+8] + ('A'-1)) : ' ', + (uchar)lc.buf[8+20], (uchar)lc.buf[8+16], + *(ushort *)&lc.buf[8+12]); + add_pgm_cmt("Version : %s", &lc.buf[32]); + goto check; + } + if ( !cp && !memcmp(lc.buf, "CoPyRiGhT=", 10) ) + { + pos += 10; + pos += (uchar)lc.buf[10]; + qlseek(lc.li, -2L, SEEK_CUR); + if ( getstr() ) + break; + add_pgm_cmt("Copyright : %s", lc.buf); + ++cp; + goto check; + } + if ( !memcmp(lc.buf, "CuStHeAd", 8) ) + { + pos += 8; + pos += *(uint32 *)&lc.buf[8]; + goto repos; + } +check: + if ( mp && vp && cp ) + break; + ++pos; +repos: + qlseek(lc.li, pos, SEEK_SET); + } + return mp; +} + +//-------------------------------------------------------------------------- +static void addComments(int flg) +{ + uint32 clst = (uint32)-1, msgpos = 0; + char *cl1 = NULL; + char *cl2 = NULL; + + create_filename_cmt(); + qlseek(lc.li, NLM_MODNAMOFF, SEEK_SET); + if ( lc.nlm.fname[0] ) + add_pgm_cmt("Module Name : %.12s", lc.nlm.fname); + if ( !getstr() ) + { + add_pgm_cmt("Description : %s", lc.buf); + qlseek(lc.li, 1, SEEK_CUR); + if ( mread(&clst, sizeof(clst)) ) + { + clst = (uint32)-1; + } + else + { + qlseek(lc.li, 0xD-sizeof(clst), SEEK_CUR); + if ( !getstr() ) + { + cl1 = qstrdup(lc.buf); + qlseek(lc.li, 1, SEEK_CUR); + if ( !getstr() ) + { + cl2 = qstrdup(lc.buf); + msgpos = addSpecialComment(); + } + } + } + } + add_pgm_cmt("File Format Version : %08Xh%s", lc.nlm.version, + (lc.nlm.version & NLM_COMPRESSED) ? " (compressed)" : ""); + { + static const char *const tt[15] = + { + "Generic", + "LAN Driver", + "Disk Driver", + "Name Space", + "Patch/Utility", + "Mirrored Server Link", + "OS", + "High OS", + "Host Adapter", + "Custom Device", + "FS Engine", + "Real Mode", + "OS", // duplicate 6 + "Platform Support", + "Unknown" + }; + int type = (int)lc.nlm.modType; + if ( lc.nlm.modType > 14 ) + type = 14; + add_pgm_cmt("Module type : %s (%d)", tt[type], type); + } + if ( lc.nlm.bssSize ) + add_pgm_cmt("Unitialized data size : %08Xh", lc.nlm.bssSize); + if ( lc.nlm.custoff && lc.nlm.custlen ) + add_pgm_cmt("Custom data : off=%08Xh len=%08Xh", + lc.nlm.custoff, lc.nlm.custlen); + lc.buf[0]= '\0'; + if ( lc.nlm.flags ) + { + static const char *const ff[4] = + { + "reentrant", + "multiply loadable", + "synchronize", + "pseudo-preemptable" + }; + char *ptr = lc.buf; + char *end = lc.buf + sizeof(lc.buf); + int cn = 0; + APPCHAR(ptr, end, ' '); + APPCHAR(ptr, end, '('); + for ( int i = 0; i < 4; i++ ) + { + if ( lc.nlm.flags & (1 << i) ) + { + if ( cn ) + { + APPCHAR(ptr, end, ','); + APPCHAR(ptr, end, ' '); + } + ++cn; + APPEND(ptr, end, ff[i]); + } + } + if ( cn ) + APPCHAR(ptr, end, ')'); + else + ptr = lc.buf; + APPZERO(ptr, end); + } + add_pgm_cmt("Flags : %08Xh%s", lc.nlm.flags, lc.buf); + if ( clst != (uint32)-1 ) + add_pgm_cmt("CLIB Stack Size : %08Xh", clst); + if ( cl1 ) + { + if ( *cl1 ) + add_pgm_cmt("CLIB Screen Name : %s", cl1); + qfree(cl1); + } + if ( cl2 ) + { + if ( *cl2 ) + add_pgm_cmt("CLIB Thread Name : %s", cl2); + qfree(cl2); + } + if ( lc.nlm.autoliboff && lc.nlm.autolibnum ) + { + qlseek(lc.li, lc.nlm.autoliboff, SEEK_SET); + for ( uint i = 0; i < lc.nlm.autolibnum; i++ ) + { + if ( getstr() ) + break; + add_pgm_cmt("Referenced Modules : '%s'", lc.buf); + if ( lc.impnode ) + { + char *p1, *p2; + for ( p1 = lc.buf; p1 && *trim(p1); p1 = p2 ) + { + if ( (p2 = strchr(p1, '|')) != NULL ) + { + *p2++ = '\0'; + if ( !*trim(p1) ) + continue; + } + import_module(p1, NULL, lc.impnode, NULL, "netware"); + } + } + } + } + + if ( !msgpos ) + return; + + qlseek(lc.li, msgpos, SEEK_SET); + if ( mread(lc.buf, 0x7C-8) ) + return; + + uint32 id = *(uint32 *)&lc.buf[0x60-8]; + if ( id ) + add_pgm_cmt("Product ID : %08Xh", id); + id = *(uint32 *)&lc.buf[0]; + if ( id ) + add_pgm_cmt("Language ID : %u", id); + id = *(uint32 *)&lc.buf[0x34-8]; + if ( id ) + add_pgm_cmt("Shared Data : off=%08Xh, size=%08Xh", + *(uint32 *)&lc.buf[0x30-8], id); + id = *(uint32 *)&lc.buf[0x2C-8]; + if ( id ) + { + add_pgm_cmt("Shared Code : off=%08Xh, size=%08Xh", + *(uint32 *)&lc.buf[0x28-8], id); + add_pgm_cmt("Shared Start Procedure : off=%08Xh", + *(uint32 *)&lc.buf[0x58-8]); + add_pgm_cmt("Shared Exit Procedure : off=%08Xh", + *(uint32 *)&lc.buf[0x5C-8]); + } + id = *(uint32 *)&lc.buf[0x1C-8]; + if ( id ) + add_pgm_cmt("Help : off=%08Xh, size=%08Xh", + *(uint32 *)&lc.buf[0x18-8], id); + id = *(uint32 *)&lc.buf[0x24-8]; + if ( id ) + add_pgm_cmt("RPC & BAG : off=%08Xh, size=%08Xh", + *(uint32 *)&lc.buf[0x20-8], id); + id = *(uint32 *)&lc.buf[0x10-8]; + + if ( id ) + { + add_pgm_cmt("Message : off=%08Xh, size=%08Xh", + msgpos = *(uint32 *)&lc.buf[0xC-8], id); + + if ( !flg ) + return; + + uint32 mlng, mcnt; + qlseek(lc.li, msgpos + 0x6A, SEEK_SET); + if ( mread(&mlng, sizeof(mlng)) || mread(&mcnt, sizeof(mcnt)) ) + return; + + add_pgm_cmt("Message Language : %08Xh", mlng); + msgpos += 0x76; + for ( clst = 0; clst < mcnt; clst++ ) + { + qlseek(lc.li, msgpos + qoff64_t(clst)*4, SEEK_SET); + if ( mread(&mlng, sizeof(mlng)) ) + break; + qlseek(lc.li, msgpos + mlng, SEEK_SET); + if ( !LoadMsgString() ) + break; + add_pgm_cmt(" %08X : %s", clst, lc.buf); + } +// 4C - Shared Exported Symbols +// 44 - Shared Imported Symbols +// 3C - Shared Fixups +// 54 - Shared Debug Records + } +} + +//-------------------------------------------------------------------------- +static void load_image(void) +{ + uint32 lend = 0; + uint32 addbss = 0; + + qoff64_t off = lc.nlm.codeoff; + if ( off != 0 ) + { + lend = lc.nlm.codelen; + if ( lend != 0 ) + { + lc.csize = lend; + lc.cbase = lc.start; + } + } + for ( int i = 1; ; ) + { + const char *pn, *pc; + segment_t s; + s.start_ea = lc.start; + s.end_ea = lc.start; + s.align = saRel4K; + s.bitness = 1; + s.comb = scPub; + s.sel = i; + if ( i == 1 ) + { + s.type = SEG_CODE; + pn = NAME_BSS; + pc = CLASS_CODE; + } + else + { + if ( lend == 0 ) + { + pn = NAME_BSS; + pc = CLASS_BSS; + } + else + { + pn = NAME_DATA; + pc = CLASS_DATA; + } + if ( lend != 0 || addbss ) + { + s.type = SEG_DATA; + lc.dbase = lc.start; + lc.dsize = lend; + } + } + if ( lend == 0 && !addbss ) + { + s.type = SEG_NULL; + lc.start += 0x1000; + } + else + { + if ( lend != 0 ) + { + s.end_ea += lend; + uint64 fsize = qlsize(lc.li); + if ( s.end_ea < s.start_ea || off > fsize || s.size() > fsize-off ) + loader_failure("Truncated input file"); + file2base(lc.li, off, s.start_ea, s.end_ea, FILEREG_PATCHABLE); + } + s.end_ea += addbss; + lc.start = (s.end_ea + 0xFFF) & ~0xFFF; + } + set_selector(s.sel, 0); + if ( !add_segm_ex(&s, pn, pc, ADDSEG_NOSREG | ADDSEG_SPARSE) ) + loader_failure(); +//- + if ( ++i > 2 ) + break; + addbss = lc.nlm.bssSize; + lend = ((off = lc.nlm.dataoff) == 0) ? 0 : lc.nlm.datalen; + } +} + +//-------------------------------------------------------------------------- +static void Unpack(void); +//-------------------------------------------------------------------------- +// +// load file into the database. +// +void idaapi load_file(linput_t *li, ushort neflag, const char * /*fileformatname*/) +{ + set_processor_type("metapc", SETPROC_LOADER); + add_til("nlm", ADDTIL_DEFAULT); + inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); + + if ( qlread(lc.li = li, &lc.nlm, sizeof(lc.nlm)) != sizeof(lc.nlm) ) + errstruct(); + if ( lc.nlm.version & NLM_COMPRESSED ) + Unpack(); + + lc.start = to_ea(inf_get_baseaddr(), 0); + memset(&lc.cbase, 0, sizeof(local_data) - qoffsetof(local_data, cbase)); + + load_image(); + set_default_dataseg(2); + + if ( lc.nlm.startIP < lc.csize ) + { + uval_t bip = lc.cbase + lc.nlm.startIP; + inf_set_start_cs(1); + inf_set_start_ip(bip); + add_entry(bip, bip, "nlm_start", 1); + } + if ( (lc.nlm.endIP || lc.nlm.startIP) && lc.nlm.endIP < lc.csize ) + { + uval_t eip = lc.cbase + lc.nlm.endIP; + add_entry(eip, eip, "nlm_terminate", 1); + } + if ( lc.nlm.auxIP && lc.nlm.auxIP < lc.csize ) + { + uval_t aip = lc.cbase + lc.nlm.auxIP; + add_entry(aip, aip, "nlm_check_unload", 1); + } + +// inf.nametype = NM_EA; +// inf.s_prefflag &= ~PREF_SEGADR; +// inf.start_ss = BADSEL; +// inf.start_sp = BADADDR; + inf_set_specsegs(inf_is_64bit() ? 8 : 4); + + add_imports(); + add_exports_and_publics(); + add_fixups(); + addComments(neflag & NEF_RSCS); + if ( lc.impnode ) + import_module("nlm_root", NULL, lc.impnode, NULL, "netware"); + inf_set_lowoff(inf_get_min_ea()); + + if ( lc.li != li ) + close_linput(lc.li); // close & delete tmp (unpack) file + + split_sreg_range(inf_get_start_ea(), PH.reg_data_sreg, 2, SR_autostart, true); +} + +//---------------------------------------------------------------------- +// +// LOADER DESCRIPTION BLOCK +// +//---------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; + +//===============unpack===================================================== +NORETURN static void memerr(void) +{ + nomem("NLM-loader (for unpacking)"); +} + +//========================================================================== +#define OUTSIZE 8192 // 2**13 + +static void unp_process(void); + +static void Unpack(void) +{ + uint32 fsize; + FILE *fo; + + CASSERT(sizeof(lc) - qoffsetof(local_data, nlm) > 0x196); //-V658 value is being subtracted from the unsigned + CASSERT(qoffsetof(local_data,buf) == qoffsetof(local_data,nlm)+sizeof(lc.nlm)); + + if ( qlread(lc.li, lc.buf, 0x196-sizeof(lc.nlm)) != (0x196-sizeof(lc.nlm)) ) + errstruct(); + if ( lc.buf[0x190 - sizeof(lc.nlm )] != 1 + || lc.buf[0x191 - sizeof(lc.nlm)] != 10 ) + { + loader_failure("Unknown compressing method"); + } + if ( (fsize = *((uint32 *)&lc.buf[0x192 - sizeof(lc.nlm)])) <= 0x190 ) + errstruct(); + + if ( (fo = qtmpfile()) == NULL ) + loader_failure("Cannot create temporary file for decompressing"); + qfwrite(fo, &lc.nlm, 0x190); //lint !e426 + + lc.unp.buff = (uchar *)qalloc(OUTSIZE); + if ( lc.unp.buff == NULL ) + memerr(); + lc.unp.b_pos = 0x190; + lc.unp.pos = 0x190; + lc.unp.b_val = 0; + lc.unp.fo = fo; + lc.unp.size = fsize; + + msg("Decompressing module..."); + unp_process(); + + qfree(lc.unp.buff); + if ( qflush(lc.unp.fo) || ferror(lc.unp.fo) || feof(lc.unp.fo) ) + loader_failure("disk full or cannot write temporary file"); +// qlseek(fo, sizeof(nlm), SEEK_SET); + msg("Ok\n"); + lc.li = make_linput(lc.unp.fo); +} + +//========================================================================= +struct record +{ + record *left; + union + { + record *right; + uchar data; + }; +}; + +//===================================================================== +static void putUnpByte(uchar data) +{ + qfputc(data, lc.unp.fo); + ++lc.unp.pos; + lc.unp.buff[lc.unp.b_pos] = data; + if ( ++lc.unp.b_pos == OUTSIZE ) + lc.unp.b_pos = 0; +} + +//===================================================================== +static void putUnpRepeatBlk(ushort off, ushort sizeBlk) +{ + if ( !off || !sizeBlk || (uint32)off >= lc.unp.pos ) + errstruct(); + int pos = lc.unp.b_pos - off; + if ( pos < 0 ) + pos += OUTSIZE; + while ( true ) + { + putUnpByte(lc.unp.buff[pos]); + if ( --sizeBlk == 0 ) + break; + if ( ++pos == OUTSIZE ) + pos = 0; + } +} + +//===================================================================== +inline ushort nextbyte(void) +{ + uchar i; + if ( qlread(lc.li, &i, sizeof(i)) != sizeof(i) ) + errstruct(); + return i; +} + +//===================================================================== +ushort getNbit(int cnt) +{ + ushort res = 0; + ushort val = lc.unp.b_val; + int i = cnt; + do + { + if ( val <= 0xFF ) + val = nextbyte() | 0x8000; + res >>= 1; + if ( val & 1 ) + res |= 0x8000; + val >>= 1; + } while ( --i != 0 ); + lc.unp.b_val = val; + return res >> (16-cnt); +} + +//===================================================================== +static int getbit(void) +{ + if ( lc.unp.b_val <= 0xFF ) + lc.unp.b_val = nextbyte() | 0x8000; + int i = lc.unp.b_val & 1; + lc.unp.b_val >>= 1; + return i; +} + +//===================================================================== +inline uchar getbyte(void) +{ + if ( lc.unp.b_val <= 0xFF ) + return (uchar)nextbyte(); + return (uchar)getNbit(8); +} + +//===================================================================== +static uchar extractByte(const record *p) +{ + while ( p->left ) + p = getbit() ? p->right : p->left; + return p->data; +} + +//===================================================================== +static void free_record(record *p) +{ + if ( p->left ) + { + free_record(p->left); + free_record(p->right); + } + qfree(p); +} + +//===================================================================== +static record *load_record(void) +{ + record *p = (record *)qalloc(sizeof(record)); + if ( p == NULL ) + memerr(); + if ( getbit() ) + { + p->left = NULL; + p->data = getbyte(); + } + else + { + p->left = load_record(); + p->right = load_record(); + } + return p; +} + +//===================================================================== +static void unp_process(void) +{ + record *rOne = load_record(); + record *rKey = load_record(); + record *rPos = load_record(); + + while ( lc.unp.pos < lc.unp.size ) + { + if ( getbit() ) + { + putUnpByte(extractByte(rOne)); + continue; + } + ushort data = extractByte(rKey); + switch ( data ) + { + case 255: + { + uint32 cnt = 0; + lc.unp.b_val = 0; + int i = 8; + do + putUnpByte((uchar)nextbyte()); + while ( --i != 0 ); + do + { + uchar c; + putUnpByte(c = (uchar)nextbyte()); + cnt |= ((uint32)c << (i*8)); + } while ( ++i < 4 ); + while ( cnt-- ) + putUnpByte((uchar)nextbyte()); + } + break; + + case 254: + data = getNbit(13); + // fallthrough + default: + { + ushort off = getNbit(5); + off |=((ushort)extractByte(rPos) << 5); + putUnpRepeatBlk(off, data); + } + break; + } + } // while + if ( lc.unp.pos != lc.unp.size ) + errstruct(); + + free_record(rOne); + free_record(rKey); + free_record(rPos); +} + +#pragma pack(pop) diff --git a/idasdk75/ldr/nlm/nlm.h b/idasdk76/ldr/nlm/nlm.h similarity index 100% rename from idasdk75/ldr/nlm/nlm.h rename to idasdk76/ldr/nlm/nlm.h diff --git a/idasdk76/ldr/os9/makefile b/idasdk76/ldr/os9/makefile new file mode 100644 index 0000000..5b944c4 --- /dev/null +++ b/idasdk76/ldr/os9/makefile @@ -0,0 +1,14 @@ +PROC=os9 + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)os9$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../../module/mc68xx/notify_codes.hpp \ + ../idaldr.h os9.cpp os9.hpp diff --git a/idasdk75/ldr/os9/os9.cpp b/idasdk76/ldr/os9/os9.cpp similarity index 100% rename from idasdk75/ldr/os9/os9.cpp rename to idasdk76/ldr/os9/os9.cpp diff --git a/idasdk75/ldr/os9/os9.hpp b/idasdk76/ldr/os9/os9.hpp similarity index 100% rename from idasdk75/ldr/os9/os9.hpp rename to idasdk76/ldr/os9/os9.hpp diff --git a/idasdk76/ldr/pe/common.cpp b/idasdk76/ldr/pe/common.cpp new file mode 100644 index 0000000..60bc94f --- /dev/null +++ b/idasdk76/ldr/pe/common.cpp @@ -0,0 +1,701 @@ + +#include <auto.hpp> +#include "common.h" +#include "../idaldr.h" + +//------------------------------------------------------------------------ +#ifdef LOADER_SOURCE // building a loader? +AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...) +{ + va_list va; + va_start(va, format); + qstring question("AUTOHIDE REGISTRY\n"); + question.cat_vsprnt(format, va); + question.append("\nDo you wish to continue?"); + if ( ask_yn(ASKBTN_YES, "%s", question.c_str()) != ASKBTN_YES ) + { + loader_failure(NULL); + } + va_end(va); +} +#else +// for other purposes: just print the error message and continue +AS_PRINTF(1, 2) inline void pe_failure(const char *format, ...) +{ + va_list va; + va_start(va, format); + qvprintf(format, va); + qprintf("\n"); + va_end(va); +} +#endif + +//------------------------------------------------------------------------ +inline bool pe64_to_pe(peheader_t &pe, const peheader64_t &pe64, bool silent, bool zero_bad_data) +{ + bool ok = true; + switch ( pe64.magic ) + { + default: + if ( !silent ) + { + ask_for_feedback("The input file has non-standard magic number (%x)", + pe64.magic); + } + ok = false; + /* no break */ + case MAGIC_P32: + case MAGIC_ROM: + case 0: + memcpy(&pe, &pe64, sizeof(pe)); + break; + case MAGIC_P32_PLUS: + // Copy the constant part + memcpy(&pe, &pe64, offsetof(peheader_t, stackres)); + + // Copy after the changed part + memcpy(&pe.loaderflags, &pe64.loaderflags, + sizeof(pe) - qoffsetof(peheader_t, loaderflags)); + + // Truncate the 64bit to 32bit + pe.stackres = low(pe64.stackres); + pe.stackcom = low(pe64.stackcom); + pe.heapres = low(pe64.heapres); + pe.heapcom = low(pe64.heapcom); + break; + } + // Do various checks + if ( !pe.is_efi() + && (pe.objalign < pe.filealign + || pe.filealign != 0 && (pe.filealign & (pe.filealign-1)) != 0 // check for power of 2 + || pe.objalign != 0 && (pe.objalign & (pe.objalign -1)) != 0) ) // check for power of 2 + { + if ( !silent ) + pe_failure("Invalid file: bad alignment value specified (section alignment: %08X, file alignment: %08X)", pe.objalign, pe.filealign); + } + if ( pe.imagesize > 0x77000000 || pe.imagesize < pe.allhdrsize ) + { + if ( !silent ) + pe_failure("Invalid file: bad ImageSize value %x", pe.imagesize); + } + + if ( zero_bad_data ) + { + if ( pe.nrvas != 0 && pe.nrvas < total_rvatab_count ) + memset(&pe.expdir + pe.nrvas, 0, total_rvatab_size - pe.nrvas * sizeof(petab_t)); + size_t fullhdrsize = pe.is_pe_plus() ? sizeof(pe64) : sizeof(pe); + size_t sectblstart = pe.first_section_pos(0); + // clear items covered by section table + if ( sectblstart < fullhdrsize + && total_rvatab_size < fullhdrsize + && sectblstart >= fullhdrsize - total_rvatab_size ) + { + if ( !silent ) + msg("Warning: image directories are covered by the section table, some entries will be ignored\n"); + size_t clearcount = (fullhdrsize - sectblstart + sizeof(petab_t) -1 )/ sizeof(petab_t); + memset(&pe.expdir + (total_rvatab_count- clearcount), 0, clearcount * sizeof(petab_t)); + } + } + return ok; +} + +//------------------------------------------------------------------------ +inline bool te_to_pe(peheader_t &pe, const teheader_t &te) +{ + bool ok = true; + memset(&pe, 0, sizeof(pe)); + pe.signature = te.signature; + pe.machine = te.machine; + pe.nobjs = te.nobjs; + pe.magic = pe.is_64bit_cpu() ? MAGIC_P32_PLUS : MAGIC_P32; + pe.entry = te.entry; + pe.text_start = te.text_start; + pe.allhdrsize = te.text_start + te.te_adjust(); + if ( pe.is_pe_plus() ) + pe.imagebase64 = te.imagebase64; + else + pe.imagebase32 = te.imagebase64; + pe.subsys = te.subsys; + pe.reltab = te.reltab; + pe.debdir = te.debdir; + pe.objalign = 1; + pe.filealign = 1; + return ok; +} + +//------------------------------------------------------------------------ +inline bool pe_loader_t::read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data) +{ + peoff = _peoff; + qlseek(li, peoff); + memset(&pe64, 0, sizeof(pe64)); + qlseek(li, peoff); + size_t size = qlread(li, &pe64, sizeof(pe64)); + size_t minsize = pe64.magic == MAGIC_P32_PLUS + ? qoffsetof(peheader64_t, subsys) + : qoffsetof(peheader_t, subsys); + bool ok = size > minsize + && size <= sizeof(pe64) + && (pe64.signature == PEEXE_ID || pe64.signature == BPEEXE_ID || pe64.signature == PLEXE_ID) + && pe64_to_pe(pe, pe64, silent, zero_bad_data); + if ( ok ) + { + // initialize imagebase for loading + set_imagebase((ea_t)pe.imagebase()); + } + return ok; +} + +//------------------------------------------------------------------------ +inline bool pe_loader_t::read_header(linput_t *li, bool silent, bool zero_bad_data) +{ + uint32 hdroff = 0; + link_ulink = false; + + qlseek(li, hdroff); + if ( qlread(li, &exe, sizeof(exe)) != sizeof(exe) ) + return false; + if ( exe.exe_ident != PEEXE_ID ) + { + if ( exe.exe_ident == TEEXE_ID ) + { + qlseek(li, hdroff); + if ( qlread(li, &te, sizeof(te)) != sizeof(te) ) + return false; + bool ok = te_to_pe(pe, te); + if ( ok ) + { + // initialize imagebase for loading + set_imagebase((ea_t)pe.imagebase()); + peoff = hdroff; + } + return ok; + } + if ( exe.exe_ident == EXE_ID || exe.exe_ident == EXE_ID2 ) + { + char tmp[8]; + if ( qlread(li, tmp, sizeof(tmp)) == sizeof(tmp) + && memcmp(tmp, "UniLink", 8) == 0 ) + { + link_ulink = true; + } + qlseek(li, PE_PTROFF); + if ( qlread(li, &hdroff, sizeof(hdroff)) != sizeof(hdroff) ) + return false; + } + } + return read_header(li, hdroff, silent, zero_bad_data); +} + +//------------------------------------------------------------------------ +inline bool pe_loader_t::vseek(linput_t *li, uint32 rva) +{ + ea_t fpos = get_linput_type(li) == LINPUT_PROCMEM ? rva : map_ea(rva); + if ( fpos != BADADDR ) + { + qlseek(li, fpos); + return true; + } + qlseek(li, rva, SEEK_SET); + return false; +} + +//------------------------------------------------------------------------ +inline char *pe_loader_t::asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok) +{ + vseek(li, rva); + buf[0] = '\0'; + char *ret = qlgetz(li, -1, buf, bufsize); + *ok = buf[0] != '\0'; + return ret; +} + +//------------------------------------------------------------------------ +// same as asciiz() but don't set ok to false for successfully read empty strings +inline char *pe_loader_t::asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok) +{ + vseek(li, rva); + buf[0] = '\0'; + // do not use qlgetz() here because we won't distinguish empty strings from read errors + ssize_t readsize = qlread(li, buf, bufsize-1); + if ( readsize < 0 || readsize >= bufsize ) + *ok = false; + else + buf[readsize] = '\0'; + return buf; +} + +//------------------------------------------------------------------------ +inline int pe_loader_t::process_sections( + linput_t *li, + off_t first_sec_pos, + int nobjs, + pe_section_visitor_t &psv) +{ + transvec.qclear(); + qvector<pesection_t> sec_headers; + // does the file layout match memory layout? + bool alt_align = pe.objalign == pe.filealign && pe.objalign < PAGE_SIZE; + qlseek(li, first_sec_pos); + validate_array_count(li, &nobjs, sizeof(pesection_t), "Number of sections", first_sec_pos); + for ( int i=0; i < nobjs; i++ ) + { + pesection_t &sh = sec_headers.push_back(); + if ( qlread(li, &sh, sizeof(sh)) != sizeof(sh) ) + return -1; + if ( sh.s_vaddr != uint32(sh.s_scnptr) || sh.s_vsize > sh.s_psize ) + alt_align = false; + } + if ( alt_align || pe.is_te() ) + { + // according to Ivan Teblin from AVERT Labs, such files are + // mapped by Windows as-is and not section by section + // we mimic that behaviour + int code = psv.load_all(); + if ( code != 0 ) + return code; + } + + int off_align = alt_align ? pe.filealign : FILEALIGN; + if ( pe.is_efi() || pe.is_te() ) + off_align = 1; + + uint32 max_va = 0; + for ( int i=0; i < nobjs; i++ ) + { + pesection_t &sh = sec_headers[i]; + uint32 scnptr = align_down(sh.s_scnptr, off_align); + transl_t &tr = transvec.push_back(); + tr.start = sh.s_vaddr; + tr.psize = sh.get_psize(pe); + tr.end = pe.align_up_in_file(uint32(sh.s_vaddr + tr.psize)); + tr.pos = scnptr; + if ( pe.is_te() ) + tr.pos += te.te_adjust(); + int code = psv.visit_section(sh, scnptr); + if ( code != 0 ) + return code; + if ( max_va < sh.s_vaddr + sh.s_vsize ) + max_va = sh.s_vaddr + sh.s_vsize; + } + if ( pe.is_te() ) + pe.imagesize = max_va; + if ( nobjs == 0 || alt_align ) + { + // add mapping for the header + transl_t tr; + tr.start = 0; + tr.psize = qlsize(li); + tr.end = pe.align_up_in_file(pe.imagesize); + tr.pos = 0; + // insert at the front so that it's always consulted last + transvec.insert(transvec.begin(), tr); + } + return 0; +} + +//------------------------------------------------------------------------ +inline int pe_loader_t::process_sections(linput_t *li, pe_section_visitor_t &psv) +{ + off_t first_sec_pos = pe.is_te() ? te.first_section_pos(peoff) : pe.first_section_pos(peoff); + return process_sections(li, first_sec_pos, pe.nobjs, psv); +} + +//------------------------------------------------------------------------ +inline int pe_loader_t::process_sections(linput_t *li) +{ + pe_section_visitor_t v; + return process_sections(li, v); +} + +//------------------------------------------------------------------------- +inline void to_utf8(char *buf, size_t bufsz, bool force=false) +{ + if ( force || !is_valid_utf8(buf) ) + { + qstring qbuf; + if ( idb_utf8(&qbuf, buf) ) + qstrncpy(buf, qbuf.c_str(), bufsz); + } +} + +//------------------------------------------------------------------------ +// process import table for one dll +inline int pe_loader_t::process_import_table( + linput_t *li, + ea_t atable, + ea_t ltable, + pe_import_visitor_t &piv) +{ + bool is_pe_plus = pe.is_pe_plus(); + uint32 elsize = piv.elsize = is_pe_plus ? 8 : 4; + const uint64 mask = is_pe_plus ? IMP_BY_ORD64 : IMP_BY_ORD32; + bool ok = true; + uint32 i; + for ( i=0; ok; i++, atable += elsize ) + { + char buf[MAXSTR]; + if ( !is_mul_ok(i, elsize) ) + return 1; + uval_t rva_off = i * elsize; + if ( !is_add_ok(ltable, rva_off) ) + return 1; + ea_t rva = ltable + rva_off; + if ( piv.withbase ) + rva -= (uval_t)pe.imagebase(); + uint32 fof = uint32(rva); + uint64 entry = is_pe_plus ? vaint64(li, fof, &ok) : valong(li, fof, &ok); + if ( entry == 0 ) + break; + show_addr(atable); + + int code; + if ( (entry & mask) == 0 ) // by name + { + ea_t nrva = (uval_t)entry + sizeof(short); + if ( piv.withbase ) + nrva -= (uval_t)pe.imagebase(); + fof = uint32(nrva); + asciiz2(li, fof, buf, sizeof(buf), &ok); + to_utf8(buf, sizeof(buf)); + code = piv.visit_import(atable, entry, buf); + } + else + { + // ordinals are always 32bit, even in pe64 + uint32 ord = entry & ~mask; + code = piv.visit_import(atable, ord, NULL); + } + if ( code != 0 ) + return code; + } + return piv.leave_module(i); +} + +//------------------------------------------------------------------------ +// this function tries to read from a file as if it was reading from memory +// if translation not found for the given RVA then ZEROs are returned +// in addition, if it tries to read beyond a translation physical size +// the additional bytes will be returned as zeros +inline bool pe_loader_t::vmread(linput_t *li, uint32 rva, void *buf, size_t sz) +{ + // clear whole user buffer + memset(buf, 0, sz); + + size_t may_read = sz; + if ( get_linput_type(li) == LINPUT_PROCMEM ) + { + qlseek(li, rva, SEEK_SET); + } + else + { + const transl_t *tr; + ea_t fpos = map_ea(rva, &tr); + + // cannot find translation? + if ( fpos == BADADDR ) + { + qlseek(li, int32(rva), SEEK_SET); + return true; + } + uint32 sectend = tr->pos + tr->psize; // section end + if ( fpos >= sectend ) + return false; // data not present in the input file + qlseek(li, fpos); + + // reading beyond section's limit? + uint32 after_read_pos = fpos + sz; + if ( after_read_pos < fpos ) + return false; // integer overflow + if ( after_read_pos >= sectend ) + { + // check if position belongs to the header and if reading beyond the limit + if ( uint32(fpos) < pe.allhdrsize && after_read_pos > pe.allhdrsize ) + may_read = pe.allhdrsize - size_t(fpos); + else + may_read = sectend - fpos; // just read as much as section limit allows + } + } + QASSERT(20045, ssize_t(may_read) >= 0); + return qlread(li, buf, may_read) == (ssize_t)may_read; +} + +//------------------------------------------------------------------------ +// process all imports of a pe file +// returns: -1:could not read an impdir; 0-ok; +// other values can be returned by the visitor +inline int pe_loader_t::process_imports(linput_t *li, pe_import_visitor_t &piv) +{ + if ( pe.impdir.rva == 0 ) + return 0; + + if ( transvec.empty() ) + process_sections(li); + + int code = 0; + for ( int ni=0; ; ni++ ) + { + off_t off = pe.impdir.rva + ni*sizeof(peimpdir_t); + peimpdir_t &id = piv.id; + + if ( !vmread(li, off, &id, sizeof(id)) ) + { + memset(&id, 0, sizeof(id)); + // we continue if the import descriptor is within the page belonging + // to the program + if ( map_ea(off) == BADADDR || map_ea(off+sizeof(id)-1) == BADADDR ) + { + code = piv.impdesc_error(off); + if ( code != 0 ) + break; + } + } + if ( id.dllname == 0 || id.looktab == 0 ) + break; + ea_t ltable = id.table1; // OriginalFirstThunk + ea_t atable = id.looktab; // FirstThunk + bool ok = true; + char dll[MAXSTR]; + asciiz(li, id.dllname, dll, sizeof(dll), &ok); + if ( !ok ) + break; + to_utf8(dll, sizeof(dll), /*force=*/ true); + if ( map_ea(ltable) == BADADDR + || ltable < pe.allhdrsize + || pe.imagesize != 0 && ltable >= pe.imagesize ) + { + ltable = atable; + } + atable += get_imagebase(); + code = piv.visit_module(dll, atable, ltable); + if ( code != 0 ) + break; + code = process_import_table(li, atable, ltable, piv); + if ( code != 0 ) + break; + } + return code; +} + +//------------------------------------------------------------------------ +inline int pe_loader_t::process_delayed_imports(linput_t *li, pe_import_visitor_t &il) +{ + if ( pe.didtab.rva == 0 ) + return 0; + + if ( transvec.empty() ) + process_sections(li); + + int code = 0; + uint32 ni = 0; + bool ok = true; + while ( true ) + { + uint32 table = pe.didtab.rva + ni*uint32(sizeof(dimpdir_t)); + if ( !vseek(li, table) ) + break; + dimpdir_t &id = il.did; + if ( qlread(li, &id, sizeof(id)) != sizeof(id) ) + return -1; + if ( !id.dllname ) + break; + il.withbase = (id.attrs & DIMP_NOBASE) == 0; + uval_t base = il.withbase ? 0 : uval_t(get_imagebase()); + ea_t atable = id.diat + base; + ea_t ltable = id.dint; + char dll[MAXSTR]; + uint32 off = uint32(il.withbase ? id.dllname - (ea_t)pe.imagebase() : id.dllname); + asciiz(li, off, dll, sizeof(dll), &ok); + if ( !ok ) + break; + to_utf8(dll, sizeof(dll), /*force=*/ true); + code = il.visit_module(dll, atable, ltable); + if ( code != 0 ) + break; + code = process_import_table(li, atable, ltable, il); + if ( code != 0 ) + break; + ni++; + } + return ok || code != 0 ? code : -1; +} + +//------------------------------------------------------------------------ +// process all exports of a pe file +// returns -2: could not read expdir, -1: other read errors, 0-ok, +// other values can be returned by the visitor +inline int pe_loader_t::process_exports(linput_t *li, pe_export_visitor_t &pev) +{ + if ( pe.expdir.rva == 0 ) + return 0; + if ( transvec.empty() ) + process_sections(li); + if ( !vseek(li, pe.expdir.rva) ) + return -2; + + // process export directory + bool fok = true; + char buf[MAXSTR]; + peexpdir_t ed; + if ( qlread(li, &ed, sizeof(ed)) != sizeof(ed) ) + return -1; + asciiz2(li, ed.dllname, buf, sizeof(buf), &fok); + to_utf8(buf, sizeof(buf), /*force=*/ true); + int code = pev.visit_expdir(ed, buf); + if ( code != 0 ) + return code; + + // I'd like to have a better validation + uint64 maxsize = qlsize(li) + 4096; + if ( maxsize > pe.expdir.size && pe.expdir.size != 0 ) + maxsize = pe.expdir.size; + validate_array_count(NULL, &ed.nnames, 6, "Number of exported names", + pe.expdir.rva, pe.expdir.rva+maxsize); + validate_array_count(NULL, &ed.naddrs, 4, "Number of exported addresses", + pe.expdir.rva, pe.expdir.rva+maxsize); + + // gather name information + typedef std::map<int, qstring> names_t; + names_t names; + int rcode = fok ? 0 : -1; + for ( uint32 i=0; i < ed.nnames; i++ ) + { + fok = true; + uint32 ordidx = vashort(li, ed.ordtab + i*sizeof(ushort), &fok); + if ( !fok ) + { + if ( rcode == 0 ) + rcode = -1; + continue; + } + ushort ord = ushort(ordidx + ed.ordbase); + uint32 rva = valong(li, ed.namtab + i*sizeof(uint32), &fok); + if ( !fok ) + { + if ( rcode == 0 ) + rcode = -1; + continue; + } + asciiz2(li, rva, buf, sizeof(buf), &fok); + if ( !fok ) + { + if ( rcode == 0 ) + rcode = -1; + continue; + } + to_utf8(buf, sizeof(buf)); + names[ord] = buf; + } + + // visit all exports + uint32 expdir_start_rva = pe.expdir.rva; + uint32 expdir_end_rva = pe.expdir.rva + maxsize; + + for ( uint32 i = 0; i < ed.naddrs; i++ ) + { + fok = true; + uint32 rva = valong(li, ed.adrtab + i*sizeof(uint32), &fok); + if ( rva != 0 && fok ) + { + uint32 ord = i + ed.ordbase; + names_t::iterator p = names.find(ord); + const char *name = p != names.end() ? p->second.c_str() : ""; + const char *forwarder = NULL; + if ( rva >= expdir_start_rva && rva < expdir_end_rva ) + { + // string inside export directory: this is a forwarded export + asciiz(li, rva, buf, sizeof(buf), &fok); + if ( !fok ) + { + if ( rcode == 0 ) + rcode = -1; + continue; + } + char *dot = strrchr(buf, '.'); + if ( dot != NULL ) + { + char before_dot[MAXSTR]; + char after_dot[MAXSTR]; + *dot = '\0'; + qstrncpy(before_dot, buf, sizeof(before_dot)); + qstrncpy(after_dot, dot+1, sizeof(after_dot)); + to_utf8(before_dot, sizeof(before_dot), /*force=*/ true); + to_utf8(after_dot, sizeof(after_dot), /*force=*/ false); + qsnprintf(buf, sizeof(buf), "%s.%s", before_dot, after_dot); + } + else + { + to_utf8(buf, sizeof(buf), /*force=*/ true); + } + forwarder = buf; + } + code = pev.visit_export(rva, ord, name, forwarder); + if ( code != 0 ) + { + if ( rcode == 0 ) + rcode = code; + } + } + else if ( !fok ) + rcode = -1; + } + + return rcode; +} + +//------------------------------------------------------------------------ +inline const char *get_pe_machine_name(uint16 machine) +{ + switch ( machine ) + { + case PECPU_80386: return "80386"; + case PECPU_80486: return "80486"; + case PECPU_80586: return "80586"; + case PECPU_SH3: return "SH3"; + case PECPU_SH3DSP: return "SH3DSP"; + case PECPU_SH3E: return "SH3E"; + case PECPU_SH4: return "SH4"; + case PECPU_SH5: return "SH5"; + case PECPU_ARM: return "ARM"; + case PECPU_ARMI: return "ARMI"; + case PECPU_ARMV7: return "ARMv7"; + case PECPU_EPOC: return "ARM EPOC"; + case PECPU_PPC: return "PPC"; + case PECPU_PPCFP: return "PPC FP"; + case PECPU_PPCBE: return "PPC BE"; + case PECPU_IA64: return "IA64"; + case PECPU_R3000: return "MIPS R3000"; + case PECPU_R4000: return "MIPS R4000"; + case PECPU_R6000: return "MIPS R6000"; + case PECPU_R10000: return "MIPS R10000"; + case PECPU_MIPS16: return "MIPS16"; + case PECPU_WCEMIPSV2: return "MIPS WCEv2"; + case PECPU_ALPHA: return "ALPHA"; + case PECPU_ALPHA64: return "ALPHA 64"; + case PECPU_AMD64: return "AMD64"; + case PECPU_ARM64: return "ARM64"; + case PECPU_M68K: return "M68K"; + case PECPU_MIPSFPU: return "MIPS FPU"; + case PECPU_MIPSFPU16: return "MIPS16 FPU"; + case PECPU_EBC: return "EFI Bytecode"; + case PECPU_AM33: return "AM33"; + case PECPU_M32R: return "M32R"; + case PECPU_CEF: return "CEF"; + case PECPU_CEE: return "CEE"; + case PECPU_TRICORE: return "TRICORE"; + } + return NULL; +} + +//------------------------------------------------------------------------- +inline bool pe_loader_t::read_strtable(qstring *out, linput_t *li) +{ + bool ok = false; + if ( pe.symtof != 0 ) + { + qoff64_t strtoff = qoff64_t(pe.symtof) + pe.nsyms * 18; + ok = read_string_table(out, li, strtoff); + } + return ok; +} + diff --git a/idasdk76/ldr/pe/common.h b/idasdk76/ldr/pe/common.h new file mode 100644 index 0000000..c753814 --- /dev/null +++ b/idasdk76/ldr/pe/common.h @@ -0,0 +1,306 @@ +#ifndef _PE_LDR_COMMON_H_ +#define _PE_LDR_COMMON_H_ + +#include <netnode.hpp> +#include <idp.hpp> +#include <loader.hpp> +#include <diskio.hpp> + +#define PAGE_SIZE 0x1000 +//------------------------------------------------------------------------ +struct pe_section_visitor_t +{ + virtual int idaapi visit_section(const pesection_t &, off_t /*file_offset*/) { return 0; } + virtual int idaapi load_all() { return 0; } + virtual ~pe_section_visitor_t(void) {} +}; + +//------------------------------------------------------------------------ +//-V:pe_import_visitor_t:730 not all members of a class are initialized inside the constructor +struct pe_import_visitor_t +{ + bool withbase; + int elsize; // initialized by process_import_table() + peimpdir_t id; + dimpdir_t did; + + pe_import_visitor_t(void) : withbase(false) {} + virtual int idaapi visit_module(const char * /*dll*/, ea_t /*iat_start*/, ea_t /*int_rva*/) { return 0; } + virtual int idaapi leave_module(uint32 /*nprocessed_imports*/) { return 0; } + // buf==NULL:by ordinal + virtual int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) = 0; + virtual int idaapi impdesc_error(off_t /*file_offset*/) { return 0; } + virtual ~pe_import_visitor_t(void) {} +}; + +//------------------------------------------------------------------------ +struct pe_export_visitor_t +{ + // this function will be called once at the start. + // it must return 0 to continue + virtual int idaapi visit_expdir(const peexpdir_t & /*ed*/, const char * /*modname*/) { return 0; } + // this function is called for each export. name is never NULL, forwarder may point to the forwarder function + // it must return 0 to continue + virtual int idaapi visit_export(uint32 rva, uint32 ord, const char *name, const char *forwarder) = 0; + virtual ~pe_export_visitor_t(void) {} +}; + +//------------------------------------------------------------------------ +class pe_loader_t +{ + int process_import_table( + linput_t *li, + ea_t atable, + ea_t ltable, + pe_import_visitor_t &piv); + template <class T> + T varead(linput_t *li, uint32 rva, bool *ok) + { + T x = 0; + bool _ok = vseek(li, rva) && qlread(li, &x, sizeof(x)) == sizeof(x); + if ( ok != NULL ) + *ok = _ok; + return x; + } +public: + struct transl_t + { + ea_t start; + ea_t end; + off_t pos; + size_t psize; + }; + typedef qvector<transl_t> transvec_t; + transvec_t transvec; + union + { + exehdr exe; + teheader_t te; + }; + peheader_t pe; + peheader64_t pe64; // original 64bit header, should not be used + // because all fields are copied to pe + // nb: imagebase is truncated during the copy! + ea_t load_imagebase; // imagebase used during loading; initialized from the PE header but can be changed by the user + off_t peoff; // offset to pe header + bool link_ulink; // linked with unilink? + + // low level functions + +//------------------------------------------------------------------------ +// NB! We need to walk the mapping backwards, because +// the later sections take priority over earlier ones +// +// e.g. consider +// section 0: start=1000, end=5000, pos=1000 +// section 1: start=3000, end=4000, pos=5000 +// for byte at RVA 3500: +// section 0 maps it from the file offset 3500 +// but section 1 overrides it with the byte from file offset 5500! +// + inline ea_t map_ea(ea_t rva, const transl_t **tl=NULL) + { + for ( ssize_t i=transvec.size()-1; i >= 0; i-- ) + { + const transl_t &trans = transvec[i]; + if ( trans.start <= rva && trans.end > rva ) + { + if ( tl != NULL ) + *tl = &trans; + return rva-trans.start + trans.pos; + } + } + return BADADDR; + } + ea_t get_imagebase(void) const { return load_imagebase; } + void set_imagebase(ea_t newimagebase) { load_imagebase=newimagebase; } + virtual bool vseek(linput_t *li, uint32 rva); + inline uint16 vashort(linput_t *li, uint32 addr, bool *ok) { return varead<uint16>(li, addr, ok); } + inline uint32 valong(linput_t *li, uint32 addr, bool *ok) { return varead<uint32>(li, addr, ok); } + inline uint64 vaint64(linput_t *li, uint32 addr, bool *ok) { return varead<uint64>(li, addr, ok); } + char *asciiz(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok); + char *asciiz2(linput_t *li, uint32 rva, char *buf, size_t bufsize, bool *ok); + int process_sections(linput_t *li, off_t fist_sec_pos, int nojbs, pe_section_visitor_t &psv); + int process_sections(linput_t *li, pe_section_visitor_t &psv); + // If 'zero_bad_data==true' (i.e., the default), extra 'directories' + // in the pe/pe64 headers will be set to zero. + bool read_header(linput_t *li, off_t _peoff, bool silent, bool zero_bad_data = true); + + // high level functions + bool read_header(linput_t *li, bool silent=false, bool zero_bad_data = true); + int process_sections(linput_t *li); + + int process_delayed_imports(linput_t *li, pe_import_visitor_t &il); + int process_imports(linput_t *li, pe_import_visitor_t &piv); + int process_exports(linput_t *li, pe_export_visitor_t &pev); + bool vmread(linput_t *li, uint32 rva, void *buf, size_t sz); + + bool read_strtable(qstring *out, linput_t *li); + + virtual ~pe_loader_t(void) {} +}; + +//------------------------------------------------------------------------ +struct import_loader_t : public pe_import_visitor_t +{ + struct dllinfo_t + { + qstring orig_name; + qstring name; + netnode node; // will be used by import_module() + bool imported_module; + + dllinfo_t() + : imported_module(false) + {} + }; + typedef qvector<dllinfo_t> dllinfo_vec_t; + + processor_t &ph; + peheader_t &pe; + dllinfo_vec_t dlls; // visited modules + range_t imprange; + ea_t astart; + ea_t last_imp; + ea_t int_rva; + int ndid; // number of delayed import dirs + bool displayed; + bool got_new_imports; + bool delayed_imports; + + inline void preprocess(void); + inline bool has_module(const char *mod) const + { + size_t ndlls = dlls.size(); + for ( size_t i = 0; i < ndlls; i++ ) + if ( !stricmp(dlls[i].orig_name.c_str(), mod) ) + return true; + return false; + } + int idaapi visit_module(const char *dll, ea_t iat_start, ea_t _int_rva) override; + int idaapi visit_import(ea_t impea, uint32 ordinal, const char *buf) override; + int idaapi leave_module(uint32 nprocessed_imports) override; + int idaapi impdesc_error(off_t off) override; + inline void postprocess(void); + + import_loader_t(processor_t &_ph, peheader_t &_pe, bool di) + : ph(_ph), pe(_pe), astart(BADADDR), last_imp(BADADDR), int_rva(0), + ndid(0), + displayed(false), got_new_imports(false), delayed_imports(di) + { + imprange.start_ea = BADADDR; + imprange.end_ea = 0; + } +}; + +#ifdef __EA64__ + +struct function_entry_x64 +{ + uint32 BeginAddress; + uint32 EndAddress; + uint32 UnwindData; + bool operator<(const function_entry_x64 &r) const { return BeginAddress < r.BeginAddress; } + bool operator!=(const function_entry_x64 &r) const + { + return BeginAddress != r.BeginAddress + || EndAddress != r.EndAddress + || UnwindData != r.UnwindData; + } +}; + +struct unwind_info_x64 +{ + uint8 Version_Flags; + uint8 SizeOfProlog; //lint -e754 local structure member not referenced + uint8 CountOfCodes; + uint8 FrameRegister_Offset; +}; + +#endif + +//------------------------------------------------------------------------ +struct ida_loader_t : public pe_loader_t +{ + processor_t &ph; + eavec_t asked_eas; + import_loader_t imploader; // used in load_imports() + import_loader_t didloader; // used in load_delayed_imports() + eavec_t imp_fixups; // fixups to the import tables, + // they will be updated after a creation of + // the .idata segment + bool loaded_header = false; + bool vseek_asked = false; + bool has_embedded_pdb = false; + + virtual bool vseek(linput_t *li, uint32 rva) override + { + ea_t fpos; + if ( get_linput_type(li) == LINPUT_PROCMEM ) + { + fpos = rva; + } + else + { + fpos = map_ea(rva); + if ( fpos == BADADDR && rva < peoff+pe.allhdrsize ) + fpos = rva; + } + if ( fpos != BADADDR ) + { + qoff64_t p2 = qlseek(li, qoff64_t(fpos)); + return p2 != -1; + } + if ( !vseek_asked + && ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "Can't find translation for relative virtual address %08X, continue?", + rva) <= ASKBTN_NO ) + { + loader_failure(); + } + vseek_asked = true; + qlseek(li, rva, SEEK_SET); + return false; + } + ida_loader_t(void) //lint !e1401 non-static data member 'pe_loader_t::*' not initialized by constructor + : ph(PH), + imploader(ph, pe, false), + didloader(ph, pe, true) {} + + void setup_entry_and_dgroup(linput_t *li, sel_t dgroup); + bool make_beginning_loaded(linput_t *li, ea_t begin); + sel_t load_sections(linput_t *li, bool aux, const qstring *strtable=nullptr); + void load_tls(linput_t *li); + void load_exports(linput_t *li); + void load_imports(linput_t *li); + void load_delayed_imports(linput_t *li); + void read_and_save_fixups(linput_t *li); + bool has_imports_by_ordinal(linput_t *li); + void load_cli_module(linput_t *_li); + void load_pdata(linput_t *li); + void pe_convert_idata(); + void comment_impexp(linput_t *li); + void load_loadconfig(linput_t *li); + void load_header_section(linput_t *li, bool visible); + void load_debug_info(linput_t *li); + void remember_imp_fixup(ea_t fixup_ea, ea_t target) + { + for ( const auto &impldr : { imploader, didloader } ) + { + if ( impldr.imprange.contains(target) ) + { + imp_fixups.add(fixup_ea); + break; + } + } + } + bool has_ntdll() const { return imploader.has_module("ntdll.dll"); } +#ifdef __EA64__ + int check_chained_uw(linput_t *li, uint32 rva, function_entry_x64 *chained, int nest_count = 0); + void load_pdata_x64(linput_t *li, uint32 pdata_rva, asize_t psize); + bool has_bad_uwopcodes(linput_t *li, uint32 uw_rva, ea_t funcstart); +#endif +}; + +#endif diff --git a/idasdk75/ldr/pe/cor.h b/idasdk76/ldr/pe/cor.h similarity index 100% rename from idasdk75/ldr/pe/cor.h rename to idasdk76/ldr/pe/cor.h diff --git a/idasdk75/ldr/pe/corhdr.h b/idasdk76/ldr/pe/corhdr.h similarity index 100% rename from idasdk75/ldr/pe/corhdr.h rename to idasdk76/ldr/pe/corhdr.h diff --git a/idasdk75/ldr/pe/mycor.h b/idasdk76/ldr/pe/mycor.h similarity index 100% rename from idasdk75/ldr/pe/mycor.h rename to idasdk76/ldr/pe/mycor.h diff --git a/idasdk76/ldr/pe/pe.h b/idasdk76/ldr/pe/pe.h new file mode 100644 index 0000000..59bd170 --- /dev/null +++ b/idasdk76/ldr/pe/pe.h @@ -0,0 +1,1174 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. (2:5020/209@fidonet) + * ALL RIGHTS RESERVED. + * + */ + +// +// Portable Executable file format (MS Windows 95, MS Windows NT) +// + +#ifndef _PE_H_ +#define _PE_H_ + +#include <time.h> +#include <stddef.h> + +#pragma pack(push, 1) +//----------------------------------------------------------------------- +// +// 32-bit Portable EXE Header +// +//----------------------------------------------------------------------- +struct petab_t +{ + uint32 rva; // relative virtual address + uint32 size; // size +}; // PE va/size array element + +template <class pointer_t> +struct peheader_tpl +{ + int32 signature; // 00 Current value is "PE/0/0". + +#define PEEXE_ID 0x4550 // 'PE' followed by two zeroes +#define BPEEXE_ID 0x455042 // Borland's extenson for DPMI'host +#define PLEXE_ID 0x4C50 // 'PL', PharLap TNT DOS-Extender Lite file that uses real mode APIs +#define TEEXE_ID 0x5A56 // 'VZ', EFI Terse Executable + uint16 machine; // 04 This field specifies the type of CPU + // compatibility required by this image to run. + // The values are: +#define PECPU_UNKNOWN 0x0000 // unknown + +#define PECPU_80386 0x014C // 80386 +#define PECPU_80486 0x014D // 80486 +#define PECPU_80586 0x014E // 80586 + +#define PECPU_R3000 0x0162 // MIPS Mark I (R2000, R3000) +#define PECPU_R6000 0x0163 // MIPS Mark II (R6000) +#define PECPU_R4000 0x0166 // MIPS Mark III (R4000) +#define PECPU_R10000 0x0168 // MIPS Mark IV (R10000) +#define PECPU_WCEMIPSV2 0x0169 // MIPS little-endian WCE v2 +#define PECPU_MIPS16 0x0266 // MIPS16 +#define PECPU_MIPSFPU 0x0366 // MIPS with FPU +#define PECPU_MIPSFPU16 0x0466 // MIPS16 with FPU + +#define PECPU_ALPHA 0x0184 // DEC Alpha +#define PECPU_ALPHA64 0x0284 // Dec Alpha 64-bit + +#define PECPU_SH3 0x01A2 // SH3 +#define PECPU_SH3DSP 0x01A3 // SH3DSP +#define PECPU_SH3E 0x01A4 // SH3E +#define PECPU_SH4 0x01A6 // SH4 +#define PECPU_SH5 0x01A8 // SH5 + +#define PECPU_ARM 0x01C0 // ARM +#define PECPU_ARMI 0x01C2 // ARM with Thumb +#define PECPU_ARMV7 0x01C4 // ARMv7 (or higher) Thumb mode only + +#define PECPU_AM33 0x01D3 // Matsushita (Panasonic) AM33/MN10300 + +#define PECPU_PPC 0x01F0 // PowerPC +#define PECPU_PPCFP 0x01F1 // PowerPC with floating-point +#define PECPU_PPCBE 0x01F2 // PowerPC Big-Endian + +#define PECPU_M32R 0x9041 // M32R little-endian + +#define PECPU_IA64 0x0200 // Intel Itanium IA64 +#define PECPU_EPOC 0x0A00 // ARM EPOC +#define PECPU_AMD64 0x8664 // AMD64 (x64) +#define PECPU_ARM64 0xaa64 // ARMv8 in 64-bit mode +#define PECPU_M68K 0x0268 // Motorola 68000 series +#define PECPU_EBC 0x0EBC // EFI Bytecode +#define PECPU_CEF 0x0CEF // ? +#define PECPU_CEE 0xC0EE // ? +#define PECPU_TRICORE 0x0520 // TRICORE (Infineon) + + bool is_64bit_cpu(void) const + { + return machine == PECPU_AMD64 + || machine == PECPU_IA64 + || machine == PECPU_ARM64; + } + bool is_pc(void) const + { + return machine == PECPU_80386 + || machine == PECPU_80486 + || machine == PECPU_80586 + || machine == PECPU_AMD64; + } + bool is_mips(void) const + { + return machine == PECPU_R3000 + || machine == PECPU_R6000 + || machine == PECPU_R4000 + || machine == PECPU_R10000 + || machine == PECPU_WCEMIPSV2 + || machine == PECPU_MIPS16 + || machine == PECPU_MIPSFPU + || machine == PECPU_MIPSFPU16; + } + + bool is_arm(void) const + { + return machine == PECPU_ARM + || machine == PECPU_ARMI + || machine == PECPU_ARMV7; + } + + bool has_code16_bit(void) const + { + return is_arm() || is_mips(); + } + + uint16 nobjs; // 06 This field specifies the number of entries + // in the Object Table. + qtime32_t datetime; // 08 Used to store the time and date the file was + // created or modified by the linker. + uint32 symtof; // 0C Symbol Table Offset + uint32 nsyms; // 10 Number of Symbols in Symbol Table + uint16 hdrsize; // 14 This is the number of remaining bytes in the NT + // header that follow the FLAGS field. + uint16 flags; // 16 Flag bits for the image. 0000h Program image. +#define PEF_BRVHI 0x8000 // Big endian: MSB precedes LSB in memory +#define PEF_UP 0x4000 // File should be run only on a UP machine +#define PEF_DLL 0x2000 // Dynamic Link Library (DLL) +#define PEF_SYS 0x1000 // System file +#define PEF_NSWAP 0x0800 // If the image is on network media, fully load it and copy it to the swap file. +#define PEF_SWAP 0x0400 // If image is on removable media, + // copy and run from swap file +#define PEF_NODEB 0x0200 // Debugging info stripped +#define PEF_32BIT 0x0100 // 32-bit word machine +#define PEF_BRVLO 0x0080 // Little endian: LSB precedes MSB in memory +#define PEF_16BIT 0x0040 // 16-bit word machine +#define PEF_2GB 0x0020 // App can handle > 2gb addresses +#define PEF_TMWKS 0x0010 // Aggressively trim working set +#define PEF_NOSYM 0x0008 // Local symbols stripped +#define PEF_NOLIN 0x0004 // Line numbers stripped +#define PEF_EXEC 0x0002 // Image is executable +#define PEF_NOFIX 0x0001 // Relocation info stripped + + int32 first_section_pos(int32 peoff) const + { return peoff + offsetof(peheader_tpl, magic) + hdrsize; } + + // COFF fields: + + uint16 magic; // 18 Magic +#define MAGIC_ROM 0x107 // ROM image +#define MAGIC_P32 0x10B // Normal PE file +#define MAGIC_P32_PLUS 0x20B // 64-bit image + bool is_pe_plus(void) const { return magic == MAGIC_P32_PLUS; } + uchar vstamp_major; // 1A Major Linker Version + uchar vstamp_minor; // 1B Minor Linker Version + uint32 tsize; // 1C TEXT size (padded) + uint32 dsize; // 20 DATA size (padded) + uint32 bsize; // 24 BSS size (padded) + uint32 entry; // 28 Entry point + uint32 text_start; // 2C Base of text + union + { + struct + { + uint32 data_start; // 30 Base of data + + // Win32/NT extensions: + + uint32 imagebase32; // 34 Virtual base of the image. + }; + uint64 imagebase64; + }; + uint64 imagebase() const + { + if ( is_pe_plus() ) + return imagebase64; + else + return imagebase32; + } + // This will be the virtual address of the first + // byte of the file (Dos Header). This must be + // a multiple of 64K. + uint32 objalign; // 38 The alignment of the objects. This must be a power + // of 2 between 512 and 256M inclusive. The default + // is 64K. + uint32 filealign; // 3C Alignment factor used to align image pages. + // The alignment factor (in bytes) used to align the + // base of the image pages and to determine the + // granularity of per-object trailing zero pad. + // Larger alignment factors will cost more file space; + // smaller alignment factors will impact demand load + // performance, perhaps significantly. Of the two, + // wasting file space is preferable. This value + // should be a power of 2 between 512 and 64K inclusive. + // Get the file position aligned: +#define FILEALIGN 512 // IDA5.1: it seems that for standard object alignment (if 4096) + // the Windows kernel does not use filealign + // (just checks that it is in the valid range) but uses 512 + uint32 get_align_mask(void) const { return ((objalign == 4096 || filealign == 0) ? FILEALIGN : filealign) - 1; } + uint32 align_up_in_file(uint32 pos) const + { + if ( is_efi() ) // apparently EFI images are not aligned + return pos; + uint32 mask = get_align_mask(); + return (pos+mask) & ~mask; + } + uint32 align_down_in_file(uint32 pos) const + { + return is_efi() ? pos : (pos & ~get_align_mask()); + } + uint16 osmajor; // 40 OS version number required to run this image. + uint16 osminor; // 42 OS version number required to run this image. + uint16 imagemajor; // 44 User major version number. + uint16 imageminor; // 46 User minor version number. + uint16 subsysmajor; // 48 Subsystem major version number. + uint16 subsysminor; // 4A Subsystem minor version number. + + uint32 subsystem_version(void) const + { + return (subsysmajor << 16) | subsysminor; + } + + uint32 reserved; // 4C + uint32 imagesize; // 50 The virtual size (in bytes) of the image. + // This includes all headers. The total image size + // must be a multiple of Object Align. + uint32 allhdrsize; // 54 Total header size. The combined size of the Dos + // Header, PE Header and Object Table. + uint32 checksum; // 58 Checksum for entire file. Set to 0 by the linker. + uint16 subsys; // 5C NT Subsystem required to run this image. +#define PES_UNKNOWN 0x0000 // Unknown +#define PES_NATIVE 0x0001 // Native +#define PES_WINGUI 0x0002 // Windows GUI +#define PES_WINCHAR 0x0003 // Windows Character +#define PES_OS2CHAR 0x0005 // OS/2 Character +#define PES_POSIX 0x0007 // Posix Character +#define PES_NAT9x 0x0008 // image is a native Win9x driver +#define PES_WINCE 0x0009 // Runs on Windows CE. +#define PES_EFI_APP 0x000A // EFI application. +#define PES_EFI_BDV 0x000B // EFI driver that provides boot services. +#define PES_EFI_RDV 0x000C // EFI driver that provides runtime services. +#define PES_EFI_ROM 0x000D // EFI ROM image +#define PES_XBOX 0x000E // Xbox system +#define PES_BOOTAPP 0x0010 // Windows Boot Application + + bool is_efi(void) const + { + return subsys == PES_EFI_APP + || subsys == PES_EFI_BDV + || subsys == PES_EFI_RDV + || subsys == PES_EFI_ROM; + } + bool is_console_app(void) const + { + return subsys == PES_WINCHAR + || subsys == PES_OS2CHAR + || subsys == PES_POSIX; + } + bool is_userland(void) const + { + return subsys == PES_WINGUI + || subsys == PES_WINCHAR + || subsys == PES_OS2CHAR + || subsys == PES_POSIX + || subsys == PES_WINCE; + } + uint16 dllflags; // 5E Indicates special loader requirements. +#define PEL_PINIT 0x0001 // Per-Process Library Initialization. +#define PEL_PTERM 0x0002 // Per-Process Library Termination. +#define PEL_TINIT 0x0004 // Per-Thread Library Initialization. +#define PEL_TTERM 0x0008 // Per-Thread Library Termination. +#define PEL_HIGH_ENT 0x0020 // Image can handle a high entropy 64-bit virtual address space. +#define PEL_DYNAMIC_BASE 0x0040 // The DLL can be relocated at load time. +#define PEL_FORCE_INTEGRITY 0x0080 // Code integrity checks are forced. +#define PEF_NX 0x0100 // The image is compatible with data execution prevention (DEP). +#define PEF_NO_ISOLATION 0x0200 // The image is isolation aware, but should not be isolated. +#define PEF_NO_SEH 0x0400 // The image does not use structured exception handling (SEH). No handlers can be called in this image. +#define PEL_NO_BIND 0x0800 // Do not bind image +#define PEL_APPCONTAINER 0x1000 // Image should execute in an AppContainer +#define PEL_WDM_DRV 0x2000 // Driver is a WDM Driver +#define PEL_GUARDCF 0x4000 // Image supports Control Flow Guard checking +#define PEL_TSRVAWA 0x8000 // Image is Terminal Server aware + + pointer_t stackres; // 60 Stack size needed for image. The memory is + // reserved, but only the STACK COMMIT SIZE is + // committed. The next page of the stack is a + // 'guarded page'. When the application hits the + // guarded page, the guarded page becomes valid, + // and the next page becomes the guarded page. + // This continues until the RESERVE SIZE is reached. + pointer_t stackcom; // 64 Stack commit size. + pointer_t heapres; // 68 Size of local heap to reserve. + pointer_t heapcom; // 6C Amount to commit in local heap. + uint32 loaderflags; // 70 ? + uint32 nrvas; // 74 Indicates the size of the VA/SIZE array + // that follows. + petab_t expdir; // 0 78 Export Directory + petab_t impdir; // 1 80 Import Directory + petab_t resdir; // 2 88 Resource Directory + petab_t excdir; // 3 90 Exception Directory + petab_t secdir; // 4 98 Security Directory + // The Certificate Table entry points to a table of + // attribute certificates. These certificates are not + // loaded into memory as part of the image. As such, + // the first field of this entry, which is normally + // an RVA, is a File Pointer instead + petab_t reltab; // 5 A0 Relocation Table + petab_t debdir; // 6 A8 Debug Directory + petab_t desstr; // 7 B0 Description String + petab_t cputab; // 8 B8 Machine Value + petab_t tlsdir; // 9 C0 TLS Directory + petab_t loddir; // 10 Load Configuration Directory + petab_t bimtab; // 11 Bound Import Table address and size. + petab_t iat; // 12 Import Address Table address and size. + petab_t didtab; // 13 Address and size of the Delay Import Descriptor. + petab_t comhdr; // 14 COM+ Runtime Header address and size + petab_t x00tab; // 15 Reserved + + bool is_te() const + { return signature == TEEXE_ID; } + inline bool has_debdir() const; +}; + +typedef peheader_tpl<uint32> peheader_t; +typedef peheader_tpl<uint64> peheader64_t; + +constexpr size_t total_rvatab_size = sizeof(peheader_t) - offsetof(peheader_t, expdir); +constexpr size_t total_rvatab_count = total_rvatab_size / sizeof(petab_t); + +//----------------------------------------------------------------------- +struct diheader_t +{ + uint16 signature; // 00 Current value is "DI" +#define DBG_ID 0x4944 + uint16 flags2; // 02 ?? pedump mentions about this + // I've never seen something other than 0 + uint16 machine; // 04 This field specifies the type of CPU + // compatibility required by this image to run. + uint16 flags; // 06 Flag bits for the image. + qtime32_t datetime; // 08 Used to store the time and date the file was + // created or modified by the linker. + uint32 checksum; // 12 Checksum + uint32 imagebase; // 16 Virtual base of the image. + // This will be the virtual address of the first + // byte of the file (Dos Header). This must be + // a multiple of 64K. + uint32 imagesize; // 20 The virtual size (in bytes) of the image. + // This includes all headers. The total image size + // must be a multiple of Object Align. + uint32 n_secs; // 24 Number of sections + uint32 exp_name_size; // 28 Exported Names Size + uint32 dbg_dir_size; // 32 Debug Directory Size + uint32 reserved[3]; // 36 Reserved fields +}; + +//------------------------------------------------------------------------- +// +// S E C T I O N S +// +struct pesection_t +{ + char s_name[8]; /* section name */ + uint32 s_vsize; /* virtual size */ + uint32 s_vaddr; /* virtual address */ + uint32 s_psize; /* physical size */ + int32 s_scnptr; /* file ptr to raw data for section */ + int32 s_relptr; /* file ptr to relocation */ + int32 s_lnnoptr; /* file ptr to line numbers */ + uint16 s_nreloc; /* number of relocation entries */ + uint16 s_nlnno; /* number of line number entries */ + int32 s_flags; /* flags */ +#define PEST_REG 0x00000000 // obsolete: regular: allocated, relocated, loaded +#define PEST_DUMMY 0x00000001 // obsolete: dummy: not allocated, relocated, not loaded +#define PEST_NOLOAD 0x00000002 // obsolete: noload: allocated, relocated, not loaded +#define PEST_GROUP 0x00000004 // obsolete: grouped: formed of input sections +#define PEST_PAD 0x00000008 // obsolete: padding: not allocated, not relocated, loaded +#define PEST_COPY 0x00000010 // obsolete: copy: for decision function used + // by field update; not + // allocated, not relocated, + // loaded; reloc & lineno + // entries processed normally */ +#define PEST_TEXT 0x00000020L// section contains text only +#define PEST_DATA 0x00000040L// section contains data only +#define PEST_BSS 0x00000080L// section contains bss only +#define PEST_EXCEPT 0x00000100L// obsolete: Exception section +#define PEST_INFO 0x00000200L// Comment: not allocated, not relocated, not loaded +#define PEST_OVER 0x00000400L// obsolete: Overlay: not allocated, relocated, not loaded +#define PEST_LIB 0x00000800L// ".lib" section: treated like PEST_INFO + +#define PEST_LOADER 0x00001000L// Loader section: COMDAT +#define PEST_DEBUG 0x00002000L// Debug section: +#define PEST_TYPCHK 0x00004000L// Type check section: +#define PEST_OVRFLO 0x00008000L// obsolete: RLD and line number overflow sec hdr +#define PEST_F0000 0x000F0000L// Unknown +#define PEST_ALIGN 0x00F00000L// Alignment 2^(x-1): + uint32 get_sect_alignment(void) const + { + int align = ((s_flags >> 20) & 15); + return align == 0 ? 0 : (1 << (align-1)); + } + + asize_t get_vsize(const peheader_t &pe) const + { + return align_up(s_vsize ? s_vsize : s_psize, pe.objalign ? pe.objalign : 1); + } + + asize_t get_psize(const peheader_t &pe) const + { + return qmin(s_psize, get_vsize(pe)); + } + +#define PEST_1000000 0x01000000L// Unknown +#define PEST_DISCARD 0x02000000L// Discardable +#define PEST_NOCACHE 0x04000000L// Not cachable +#define PEST_NOPAGE 0x08000000L// Not pageable +#define PEST_SHARED 0x10000000L// Shareable +#define PEST_EXEC 0x20000000L// Executable +#define PEST_READ 0x40000000L// Readable +#define PEST_WRITE 0x80000000L// Writable +}; + +//------------------------------------------------------------------------- +// +// E X P O R T S +// +struct peexpdir_t +{ + uint32 flags; // Currently set to zero. + qtime32_t datetime; // Time/Date the export data was created. + uint16 major; // A user settable major/minor version number. + uint16 minor; + uint32 dllname; // Relative Virtual Address of the Dll asciiz Name. + // This is the address relative to the Image Base. + uint32 ordbase; // First valid exported ordinal. This field specifies + // the starting ordinal number for the export + // address table for this image. Normally set to 1. + uint32 naddrs; // Indicates number of entries in the Export Address + // Table. + uint32 nnames; // This indicates the number of entries in the Name + // Ptr Table (and parallel Ordinal Table). + uint32 adrtab; // Relative Virtual Address of the Export Address + // Table. This address is relative to the Image Base. + uint32 namtab; // Relative Virtual Address of the Export Name Table + // Pointers. This address is relative to the + // beginning of the Image Base. This table is an + // array of RVA's with # NAMES entries. + uint32 ordtab; // Relative Virtual Address of Export Ordinals + // Table Entry. This address is relative to the + // beginning of the Image Base. +}; + +//------------------------------------------------------------------------- +// +// I M P O R T S +// +struct peimpdir_t +{ + uint32 table1; // aka OriginalFirstThunk + qtime32_t datetime; // Time/Date the import data was pre-snapped or + // zero if not pre-snapped. + uint32 fchain; // Forwarder chain + uint32 dllname; // Relative Virtual Address of the Dll asciiz Name. + // This is the address relative to the Image Base. + uint32 looktab; // aka FirstThunk + // This field contains the address of the start of + // the import lookup table for this image. The address + // is relative to the beginning of the Image Base. +#define hibit(type) ((type(-1)>>1) ^ type(-1)) +#define IMP_BY_ORD32 hibit(uint32) // Import by ordinal, otherwise by name +#define IMP_BY_ORD64 hibit(uint64) // Import by ordinal, otherwise by name + + peimpdir_t(void) { memset(this, 0, sizeof(peimpdir_t)); } +}; + +struct dimpdir_t // delayed load import table +{ + uint32 attrs; // Attributes. +#define DIMP_NOBASE 0x0001 // pe.imagebase was not added to addresses + uint32 dllname; // Relative virtual address of the name of the DLL + // to be loaded. The name resides in the read-only + // data section of the image. + uint32 handle; // Relative virtual address of the module handle + // (in the data section of the image) of the DLL to + // be delay-loaded. Used for storage by the routine + // supplied to manage delay-loading. + uint32 diat; // Relative virtual address of the delay-load import + // address table. See below for further details. + uint32 dint; // Relative virtual address of the delay-load name + // table, which contains the names of the imports + // that may need to be loaded. Matches the layout of + // the Import Name Table, Section 6.4.3. Hint/Name Table. + uint32 dbiat; // Bound Delay Import Table. Relative virtual address + // of the bound delay-load address table, if it exists. + uint32 duiat; // Unload Delay Import Table. Relative virtual address + // of the unload delay-load address table, if it exists. + // This is an exact copy of the Delay Import Address + // Table. In the event that the caller unloads the DLL, + // this table should be copied back over the Delay IAT + // such that subsequent calls to the DLL continue to + // use the thunking mechanism correctly. + qtime32_t datetime; // Time stamp of DLL to which this image has been bound. +}; + + +// Bound Import Table format: + +struct BOUND_IMPORT_DESCRIPTOR +{ + qtime32_t TimeDateStamp; + uint16 OffsetModuleName; + uint16 NumberOfModuleForwarderRefs; +// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows +}; + +struct BOUND_FORWARDER_REF +{ + qtime32_t TimeDateStamp; + uint16 OffsetModuleName; + uint16 Reserved; +}; + + +//------------------------------------------------------------------------- +// +// T H R E A D L O C A L D A T A +// + +struct image_tls_directory64 +{ + uint64 StartAddressOfRawData; + uint64 EndAddressOfRawData; + uint64 AddressOfIndex; // PDWORD + uint64 AddressOfCallBacks; // PIMAGE_TLS_CALLBACK *; + uint32 SizeOfZeroFill; + uint32 Characteristics; +}; + +struct image_tls_directory32 +{ + uint32 StartAddressOfRawData; + uint32 EndAddressOfRawData; + uint32 AddressOfIndex; // PDWORD + uint32 AddressOfCallBacks; // PIMAGE_TLS_CALLBACK * + uint32 SizeOfZeroFill; + uint32 Characteristics; +}; + +//------------------------------------------------------------------------- +// +// Exception Tables (.pdata) +// + +// ARM, PowerPC, SH3 and SH4 WindowsCE platforms +struct function_entry_ce +{ + uint32 FuncStart; // Virtual address of the corresponding function. + uint32 PrologLen : 8; // Number of instructions in the function's prolog. + uint32 FuncLen : 22; // Number of instructions in the function. + uint32 ThirtyTwoBit : 1; // Set if the function is comprised of 32-bit instructions, cleared for a 16-bit function. + uint32 ExceptionFlag : 1; // Set if an exception handler exists for the function. +}; + +// ARMv7, ARM64 +struct function_entry_arm_pdata +{ + uint32 BeginAddress; // The RVA of the corresponding function + uint32 UnwindInfo; // The RVA of the unwind information, including function length. + // If the low 2 bits are non-zero, then this word represents a + // compacted inline form of the unwind information, + // including function length. +}; + +// for MIPS and 32-bit Alpha +struct function_entry_alpha +{ + uint32 BeginAddress; // Virtual address of the corresponding function. + uint32 EndAddress; // Virtual address of the end of the function. + uint32 ExceptionHandler; // Pointer to the exception handler to be executed. + uint32 HandlerData; // Pointer to additional information to be passed to the handler. + uint32 PrologEndAddress; // Virtual address of the end of the function's prolog. +}; + +// x64 +typedef enum _UNWIND_OP_CODES +{ + UWOP_PUSH_NONVOL = 0, // info == register number + UWOP_ALLOC_LARGE =1, // alloc size/8 in next 1(info=0) or 2(info=1) slots + UWOP_ALLOC_SMALL =2, // info == size of allocation / 8 - 1 + UWOP_SET_FPREG = 3, // FP = RSP + UNWIND_INFO.FPRegOffset*16 + UWOP_SAVE_NONVOL = 4, // info == register number, offset/8 in next slot + UWOP_SAVE_NONVOL_FAR=5,// info == register number, offset/8 in next 2 slots + UWOP_SAVE_XMM = 6, // Version 1: info == XMM reg number, offset/8 in next slot + UWOP_EPILOG = 6, // Version 2; code offset is epilog size; + UWOP_SAVE_XMM_FAR=7, // version 1:info == XMM reg number, offset/8 in next 2 slots + UWOP_SPARE_CODE = 7, // unused ("previously 64-bit UWOP_SAVE_XMM_FAR"); skip 2 slots + UWOP_SAVE_XMM128 = 8, // info == XMM reg number, offset/16 in next slot + UWOP_SAVE_XMM128_FAR = 9,// info == XMM reg number, offset/16 in next 2 slots + UWOP_PUSH_MACHFRAME = 10,// info == 0: no error-code, 1: with error code +} UNWIND_CODE_OPS; + +enum // ARM64_UNWIND_OP_CODES; +{ + // 1 byte long + ARM64_UWOP_BAD = 0, + ARM64_UWOP_UNNAMED, + ARM64_UWOP_ALLOC_S, // allocate small stack with size < 512 (2^5 * 16). + ARM64_UWOP_SAVE_R19R20_X, // save <x19,x20> pair at [sp-#Z*8]!, pre-indexed offset >= -248 + ARM64_UWOP_SAVE_FPLR, // save <x29,lr> pair at [sp+#Z*8], offset <= 504 + ARM64_UWOP_SAVE_FPLR_X, // save <x29,lr> pair at [sp-(#Z+1)*8]!, pre-indexed offset >= -512 + ARM64_UWOP_SET_FP, // set up x29: with: mov x29,sp + ARM64_UWOP_ADD_FP, // set up x29 with: add x29,sp,#x*8 + ARM64_UWOP_NOP, // no unwind operation is required + ARM64_UWOP_END, // end of unwind code. Implies ret in epilog + ARM64_UWOP_END_C, // end of unwind code in current chained scope + ARM64_UWOP_SAVE_NEXT, // save next non-volatile Int or FP register pair + + // 2 bytes long + ARM64_UWOP_ALLOC_M, // allocate large stack with size < 16k (2^11 * 16) + ARM64_UWOP_SAVE_REGP, // save x(19+#X) pair at [sp+#Z*8], offset <= 504 + ARM64_UWOP_SAVE_REGP_X, // save pair x(19+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -512 + ARM64_UWOP_SAVE_REG, // save reg x(19+#X) at [sp+#Z*8], offset <= 504 + ARM64_UWOP_SAVE_REG_X, // save reg x(19+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -256 + ARM64_UWOP_SAVE_LRPAIR, // save pair <x(19+2*#X),lr> at [sp+#Z*8], offset <= 504 + ARM64_UWOP_SAVE_FREGP, // save pair d(8+#X) at [sp+#Z*8], offset <= 504 + ARM64_UWOP_SAVE_FREGP_X, // save pair d(8+#X), at [sp-(#Z+1)*8]!, pre-indexed offset >= -512 + ARM64_UWOP_SAVE_FREG, // save reg d(8+#X) at [sp+#Z*8], offset <= 504 + ARM64_UWOP_SAVE_FREG_X, // save reg d(8+#X) at [sp-(#Z+1)*8]!, pre-indexed offset >= -256 + // 4 bytes long + ARM64_UWOP_ALLOC_L, // allocate large stack with size < 256M (2^24 *16) +}; + +enum // ARM_UNWIND_OP_CODES; +{ + // 1 byte long + ARM_UWOP_ALLOC = 0, // add sp,sp, #X where X = (Code & 0x7F) * 4) + ARM_UWOP_SAVE_SP, // mov sp,rX where X is Code & 0x0F + ARM_UWOP_POP, // pop {r4-rX,lr} where X is (Code & 0x03) + 4 and LR is popped if Code & 0x04 + ARM_UWOP_POP2, // pop {r4-rX,lr} where X is (Code & 0x03) + 8 and LR is popped if Code & 0x04 + ARM_UWOP_VPOP, // vpop {d8-dX} where X is (Code & 0x07) + 8 + ARM_UWOP_RESERVED, // Available (no opsize) + ARM_UWOP_END, // end + ARM_UWOP_END32, // end (+32bit nop in epilogue) + ARM_UWOP_NOP32, // nop (32bit) + ARM_UWOP_END16, // end (+16bit nop in epilogue) + ARM_UWOP_NOP16, // nop (16bit) + + // 2 bytes long + ARM_UWOP_POP3, // pop {r0-r12, lr} where LR is popped if Code & 0x2000 and r0-r12 are popped + // if the corresponding bit is set in Code & 0x1FFF + ARM_UWOP_ALLOC2, // addw sp,sp,#X where X is (Code & 0x03FF) * 4 + ARM_UWOP_POP4, // pop {r0-r7,lr} where LR is popped if Code & 0x0100 and r0-r7 are popped + // if the corresponding bit is set in Code & 0x00FF + ARM_UWOP_MS_SPECIFIC, // Microsoft specific + ARM_UWOP_RESERVED_W, // Available (16bit opsize) + ARM_UWOP_LD_PC_UPD_SP, // ldr lr,[sp],#X where X is (Code & 0x000F) * 4 + ARM_UWOP_RESERVED_DW, // Available (32bit opsize) + ARM_UWOP_VPOP2, // vpop {dS-dE} where S is (Code & 0x00F0) >> 4 and E is Code & 0x000F + ARM_UWOP_VPOP3, // vpop {dS-dE} where S is ((Code & 0x00F0) >> 4) + 16 and E is (Code & 0x000F) + 16 + + // 3 bytes long + ARM_UWOP_ALLOC3, // add sp,sp,#X where X is (Code & 0x00FFFF) * 4 + ARM_UWOP_ALLOC4, // add sp,sp,#X where X is (Code & 0x00FFFF) * 4 + + // 4 bytes long + ARM_UWOP_ALLOC5, // add sp,sp,#X where X is (Code & 0x00FFFFFF) * 4 + ARM_UWOP_ALLOC6, // add sp,sp,#X where X is (Code & 0x00FFFFFF) * 4 +}; + +// Define unwind information flags. +// + +#define UNW_FLAG_NHANDLER 0x0 +#define UNW_FLAG_EHANDLER 0x1 +#define UNW_FLAG_UHANDLER 0x2 +#define UNW_FLAG_CHAININFO 0x4 + +//------------------------------------------------------------------------- +// +// F I X U P S +// +struct pefixup_t +{ + uint32 page;// The image base plus the page rva is added to each offset + // to create the virtual address of where the fixup needs to + // be applied. + uint32 size;// Number of bytes in the fixup block. This includes the + // PAGE RVA and SIZE fields. +}; + +#define PER_OFF 0x0FFF +#define PER_TYPE 0xF000 +#define PER_ABS 0x0000 // This is a NOP. The fixup is skipped. +#define PER_HIGH 0x1000 // Add the high 16-bits of the delta to the + // 16-bit field at Offset. The 16-bit field + // represents the high value of a 32-bit word. +#define PER_LOW 0x2000 // Add the low 16-bits of the delta to the + // 16-bit field at Offset. The 16-bit field + // represents the low half value of a + // 32-bit word. This fixup will only be + // emitted for a RISC machine when the image + // Object Align isn't the default of 64K. +#define PER_HIGHLOW 0x3000 // Apply the 32-bit delta to the 32-bit field + // at Offset. +#define PER_HIGHADJUST 0x4000 // This fixup requires a full 32-bit value. + // The high 16-bits is located at Offset, and + // the low 16-bits is located in the next + // Offset array element (this array element + // is included in the SIZE field). The two + // need to be combined into a signed variable. + // Add the 32-bit delta. Then add 0x8000 and + // store the high 16-bits of the signed + // variable to the 16-bit field at Offset. +#define PER_REL5000 0x5000 // Machine-specific +#define PER_SECTION 0x6000 // Reserved for future use +#define PER_REL32 0x7000 // Relative intrasection +#define PER_REL7000 0x7000 // Machine-specific +#define PER_REL8000 0x8000 // Machine-specific +#define PER_REL9000 0x9000 // Machine-specific +#define PER_DIR64 0xA000 // This fixup applies the delta to the 64-bit + // field at Offset +#define PER_HIGH3ADJ 0xB000 // The fixup adds the high 16 bits of the delta + // to the 16-bit field at Offset. The 16-bit + // field represents the high value of a 48-bit + // word. The low 32 bits of the 48-bit value are + // stored in the 32-bit word that follows this + // base relocation. This means that this base + // relocation occupies three slots. + +// Platform-specific based relocation types. + +#define PER_IA64_IMM64 0x9000 + +#define PER_MIPS_JMPADDR 0x5000 // base relocation applies to a MIPS jump instruction. +#define PER_MIPS_JMPADDR16 0x9000 // base relocation applies to a MIPS16 jump instruction. + +#define PER_ARM_MOV32A 0x5000 // base relocation applies the difference to the + // 32-bit value encoded in the immediate fields of + // a contiguous MOVW+MOVT pair in ARM mode at offset. +#define PER_ARM_MOV32T 0x7000 // base relocation applies the difference to the + // 32-bit value encoded in the immediate fields of + // a contiguous MOVW+MOVT pair in Thumb mode at offset. + + +//------------------------------------------------------------------------- +// +// DBG file debug entry format +// +struct debug_entry_t +{ + uint32 flags; // usually zero + qtime32_t datetime; + uint16 major; + uint16 minor; + int32 type; +#define DBG_COFF 1 +#define DBG_CV 2 +#define DBG_FPO 3 +#define DBG_MISC 4 +#define DBG_EXCEPTION 5 +#define DBG_FIXUP 6 +#define DBG_OMAP_TO_SRC 7 +#define DBG_OMAP_FROM_SRC 8 +#define DBG_BORLAND 9 +#define DBG_RES10 10 +#define DBG_CLSID 11 +#define DBG_VCFEATURE 12 +#define DBG_POGO 13 +#define DBG_ILTCG 14 +#define DBG_MPX 15 + uint32 size; + uint32 rva; // virtual address + uint32 seek; // ptr to data in the file +}; + +// now we can define has_debdir() because we have debug_entry_t defined +template<> +inline bool peheader_t::has_debdir() const + { return debdir.size >= sizeof(debug_entry_t) && debdir.rva != 0; } + +//------------------------------------------------------------------------- +// +// DBG file COFF debug information header +// +struct coff_debug_t +{ + uint32 NumberOfSymbols; + uint32 LvaToFirstSymbol; + uint32 NumberOfLinenumbers; + uint32 LvaToFirstLinenumber; + uint32 RvaToFirstByteOfCode; + uint32 RvaToLastByteOfCode; + uint32 RvaToFirstByteOfData; + uint32 RvaToLastByteOfData; +}; + +//------------------------------------------------------------------------- +// +// DBG file FPO debug information +// +struct fpo_t +{ + uint32 address; + uint32 size; + uint32 locals; + uint16 params; + uchar prolog; + uchar regs; +#define FPO_REGS 0x07 // register number +#define FPO_SEH 0x08 // +#define FPO_BP 0x10 // has BP frame? +#define FPO_TYPE 0xC0 +#define FPO_T_FPO 0x00 +#define FPO_T_TRAP 0x40 +#define FPO_T_TSS 0x80 +#define FPO_T_NONFPO 0xC0 +}; + + +// DBG file OMAP debug information + +struct omap_t +{ + uint32 a1; + uint32 a2; +}; + +// misc entry format +struct misc_debug_t +{ + uint32 type; // type of misc data, see defines +#define MISC_EXENAME 1 + uint32 length; // total length of record, rounded to four + // byte multiple. + uchar unicode; // TRUE if data is unicode string + uchar reserved[3]; // padding + uchar data[1]; // Actual data +}; + +//---------------------------------------------------------------------- +// Resource information +struct rsc_dir_t +{ + uint32 Characteristics; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint16 NumberOfNamedEntries; + uint16 NumberOfIdEntries; +}; + +struct rsc_dir_entry_t +{ + union + { + struct + { + uint32 NameOffset:31; + uint32 NameIsString:1; + }; + uint32 Name; + uint16 Id; + }; + union + { + uint32 OffsetToData; + struct + { + uint32 OffsetToDirectory:31; + uint32 DataIsDirectory:1; + }; + }; +}; + +struct rsc_data_entry_t +{ + uint32 OffsetToData; + uint32 Size; + uint32 CodePage; + uint32 Reserved; +}; + + +// Resource types +#define PE_RT_CURSOR 1 +#define PE_RT_BITMAP 2 +#define PE_RT_ICON 3 +#define PE_RT_MENU 4 +#define PE_RT_DIALOG 5 +#define PE_RT_STRING 6 +#define PE_RT_FONTDIR 7 +#define PE_RT_FONT 8 +#define PE_RT_ACCELERATOR 9 +#define PE_RT_RCDATA 10 +#define PE_RT_MESSAGETABLE 11 +#define PE_RT_GROUP_CURSOR 12 +#define PE_RT_GROUP_ICON 14 +#define PE_RT_VERSION 16 +#define PE_RT_DLGINCLUDE 17 +#define PE_RT_PLUGPLAY 19 +#define PE_RT_VXD 20 +#define PE_RT_ANICURSOR 21 +#define PE_RT_ANIICON 22 +#define PE_RT_HTML 23 +#define PE_RT_MANIFEST 24 + +// Language codes +#define PE_LANG_NEUTRAL 0x00 +#define PE_LANG_INVARIANT 0x7f + +#define PE_LANG_AFRIKAANS 0x36 +#define PE_LANG_ALBANIAN 0x1c +#define PE_LANG_ARABIC 0x01 +#define PE_LANG_ARMENIAN 0x2b +#define PE_LANG_ASSAMESE 0x4d +#define PE_LANG_AZERI 0x2c +#define PE_LANG_BASQUE 0x2d +#define PE_LANG_BELARUSIAN 0x23 +#define PE_LANG_BENGALI 0x45 +#define PE_LANG_BULGARIAN 0x02 +#define PE_LANG_CATALAN 0x03 +#define PE_LANG_CHINESE 0x04 +#define PE_LANG_CROATIAN 0x1a +#define PE_LANG_CZECH 0x05 +#define PE_LANG_DANISH 0x06 +#define PE_LANG_DIVEHI 0x65 +#define PE_LANG_DUTCH 0x13 +#define PE_LANG_ENGLISH 0x09 +#define PE_LANG_ESTONIAN 0x25 +#define PE_LANG_FAEROESE 0x38 +#define PE_LANG_FARSI 0x29 +#define PE_LANG_FINNISH 0x0b +#define PE_LANG_FRENCH 0x0c +#define PE_LANG_GALICIAN 0x56 +#define PE_LANG_GEORGIAN 0x37 +#define PE_LANG_GERMAN 0x07 +#define PE_LANG_GREEK 0x08 +#define PE_LANG_GUJARATI 0x47 +#define PE_LANG_HEBREW 0x0d +#define PE_LANG_HINDI 0x39 +#define PE_LANG_HUNGARIAN 0x0e +#define PE_LANG_ICELANDIC 0x0f +#define PE_LANG_INDONESIAN 0x21 +#define PE_LANG_ITALIAN 0x10 +#define PE_LANG_JAPANESE 0x11 +#define PE_LANG_KANNADA 0x4b +#define PE_LANG_KASHMIRI 0x60 +#define PE_LANG_KAZAK 0x3f +#define PE_LANG_KONKANI 0x57 +#define PE_LANG_KOREAN 0x12 +#define PE_LANG_KYRGYZ 0x40 +#define PE_LANG_LATVIAN 0x26 +#define PE_LANG_LITHUANIAN 0x27 +#define PE_LANG_MACEDONIAN 0x2f // the Former Yugoslav Republic of Macedonia +#define PE_LANG_MALAY 0x3e +#define PE_LANG_MALAYALAM 0x4c +#define PE_LANG_MANIPURI 0x58 +#define PE_LANG_MARATHI 0x4e +#define PE_LANG_MONGOLIAN 0x50 +#define PE_LANG_NEPALI 0x61 +#define PE_LANG_NORWEGIAN 0x14 +#define PE_LANG_ORIYA 0x48 +#define PE_LANG_POLISH 0x15 +#define PE_LANG_PORTUGUESE 0x16 +#define PE_LANG_PUNJABI 0x46 +#define PE_LANG_ROMANIAN 0x18 +#define PE_LANG_RUSSIAN 0x19 +#define PE_LANG_SANSKRIT 0x4f +#define PE_LANG_SINDHI 0x59 +#define PE_LANG_SLOVAK 0x1b +#define PE_LANG_SLOVENIAN 0x24 +#define PE_LANG_SPANISH 0x0a +#define PE_LANG_SWAHILI 0x41 +#define PE_LANG_SWEDISH 0x1d +#define PE_LANG_SYRIAC 0x5a +#define PE_LANG_TAMIL 0x49 +#define PE_LANG_TATAR 0x44 +#define PE_LANG_TELUGU 0x4a +#define PE_LANG_THAI 0x1e +#define PE_LANG_TURKISH 0x1f +#define PE_LANG_UKRAINIAN 0x22 +#define PE_LANG_URDU 0x20 +#define PE_LANG_UZBEK 0x43 +#define PE_LANG_VIETNAMESE 0x2a + +//---------------------------------------------------------------------- + +#define PE_NODE "$ PE header" // netnode name for PE header + // value() -> peheader_t + // altval(segnum) -> s->start_ea +#define PE_ALT_DBG_FPOS nodeidx_t(-1) // altval() -> translated fpos of debuginfo +#define PE_ALT_IMAGEBASE nodeidx_t(-2) // altval() -> loading address (usually pe.imagebase) +#define PE_ALT_PEHDR_OFF nodeidx_t(-3) // altval() -> offset of PE header +#define PE_ALT_NEFLAGS nodeidx_t(-4) // altval() -> neflags +#define PE_ALT_TDS_LOADED nodeidx_t(-5) // altval() -> tds already loaded(1) or invalid(-1) +#define PE_ALT_PSXDLL nodeidx_t(-6) // altval() -> if POSIX(x86) imports from PSXDLL netnode +#define PE_ALT_OVRVA nodeidx_t(-7) // altval() -> overlay rva (if present) +#define PE_ALT_OVRSZ nodeidx_t(-8) // altval() -> overlay size (if present) +#define PE_SUPSTR_PDBNM nodeidx_t(-9) // supstr() -> pdb file name + // supval(segnum) -> pesection_t + // blob(0, PE_NODE_RELOC) -> relocation info + // blob(0, RSDS_TAG) -> rsds_t structure + // blob(0, NB10_TAG) -> cv_info_pdb20_t structure +#define PE_ALT_NTAPI nodeidx_t(-10) // altval() -> uses Native API +#define PE_EMBED_PDB_OFF nodeidx_t(-11) // altval() -> offset of embedded PDB file +#define PE_NODE_RELOC 'r' +#define RSDS_TAG 's' +#define NB10_TAG 'n' +#define UTDS_TAG 't' + +struct load_config_t +{ + uint32 Size; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint32 GlobalFlagsClear; + uint32 GlobalFlagsSet; + uint32 CriticalSectionDefaultTimeout; + uint32 DeCommitFreeBlockThreshold; + uint32 DeCommitTotalFreeThreshold; + uint32 LockPrefixTable; // VA + uint32 MaximumAllocationSize; + uint32 VirtualMemoryThreshold; + uint32 ProcessHeapFlags; + uint32 ProcessAffinityMask; + uint16 CSDVersion; + uint16 Reserved1; + uint32 EditList; // VA + uint32 SecurityCookie; // VA + // Version 2 + uint32 SEHandlerTable; // VA + uint32 SEHandlerCount; + // Version 3 + uint32 GuardCFCheckFunctionPointer; // VA + uint32 GuardCFDispatchFunctionPointer; // VA + uint32 GuardCFFunctionTable; // VA + uint32 GuardCFFunctionCount; + uint32 GuardFlags; +}; + +struct load_config64_t +{ + uint32 Size; + uint32 TimeDateStamp; + uint16 MajorVersion; + uint16 MinorVersion; + uint32 GlobalFlagsClear; + uint32 GlobalFlagsSet; + uint32 CriticalSectionDefaultTimeout; + uint64 DeCommitFreeBlockThreshold; + uint64 DeCommitTotalFreeThreshold; + uint64 LockPrefixTable; // VA + uint64 MaximumAllocationSize; + uint64 VirtualMemoryThreshold; + uint64 ProcessAffinityMask; + uint32 ProcessHeapFlags; + uint16 CSDVersion; + uint16 Reserved1; + uint64 EditList; // VA + uint64 SecurityCookie; // VA + // Version 2 + uint64 SEHandlerTable; // VA + uint64 SEHandlerCount; + // Version 3 + uint64 GuardCFCheckFunctionPointer; // VA + uint64 GuardCFDispatchFunctionPointer; // VA + uint64 GuardCFFunctionTable; // VA + uint64 GuardCFFunctionCount; + uint32 GuardFlags; +}; + +#ifndef IMAGE_GUARD_CF_INSTRUMENTED +#define IMAGE_GUARD_CF_INSTRUMENTED 0x000000100 // Module performs control flow integrity checks using system-supplied support +#define IMAGE_GUARD_CFW_INSTRUMENTED 0x000000200 // Module performs control flow and write integrity checks +#define IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT 0x000000400 // Module contains valid control flow target metadata +#define IMAGE_GUARD_SECURITY_COOKIE_UNUSED 0x000000800 // Module does not make use of the /GS security cookie +#define IMAGE_GUARD_PROTECT_DELAYLOAD_IAT 0x00001000 // Module supports read only delay load IAT +#define IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION 0x00002000 // Delayload import table in its own .didat section (with nothing else in it) that can be freely reprotected +#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK 0xF0000000 // Stride of Guard CF function table encoded in these bits (additional count of bytes per element) +#define IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT 28 // Shift to right-justify Guard CF function table stride +#endif + +//---------------------------------------------------------------------- +// MS Windows CLSID, GUID +struct clsid_t +{ + uint32 id1; + uint16 id2; + uint16 id3; + uchar id4[8]; + bool operator == (const struct clsid_t &r) const + { return memcmp(this, &r, sizeof(r)) == 0; } +}; + +//---------------------------------------------------------------------- +// RSDS debug information +struct rsds_t +{ + uint32 magic; +#define RSDS_MAGIC MC4('R','S','D','S') +#define UTDS_MAGIC MC4('u','T','D','S') + clsid_t guid; + uint32 age; +// char name[]; // followed by a zero-terminated UTF8 file name +}; + +//---------------------------------------------------------------------- +// NB10 debug information +struct cv_info_pdb20_t +{ + uint32 magic; // 'NB10' +#define NB10_MAGIC MC4('N', 'B', '1', '0') + uint32 offset; + uint32 signature; + uint32 age; + // char pdb_file_name[]; +}; + +//---------------------------------------------------------------------- +// MTOC debug information. +// denotes EFI binaries that were built on OSX as Mach-O, then converted to PE by the 'mtoc' utility. +// see https://opensource.apple.com/source/cctools/cctools-921/efitools/mtoc.c.auto.html +struct mtoc_info_t +{ + uint32 magic; // 'MTOC' +#define MTOC_MAGIC MC4('M', 'T', 'O', 'C') + uchar uuid[16]; // UUID of original Mach-O file + // char debug_filename[]; +}; + +// TE (Terse Executable) +struct teheader_t +{ + uint16 signature; // 00 + uint16 machine; // 02 same as in PE + + bool is_64bit_cpu(void) const { return machine == PECPU_AMD64 || machine == PECPU_IA64 || machine == PECPU_ARM64; } + + uint8 nobjs; // 04 number of sections + uint8 subsys; // 05 target subsystem + uint16 strippedsize; // 06 number of bytes removed from the base of the original image + + int32 first_section_pos(int32 peoff) const + { return peoff + sizeof(teheader_t); } + + // value which should be added to the sections' file offsets and RVAs + int32 te_adjust() const + { return sizeof(teheader_t) - strippedsize; } + + uint32 entry; // 08 Entry point + uint32 text_start; // 0C Base of code + uint64 imagebase64; // 10 Virtual base of the image. + uint64 imagebase() const + { + return imagebase64; + } + petab_t reltab; // 18 Relocation Table + petab_t debdir; // 20 Debug Directory +}; + +const char *get_pe_machine_name(uint16 machine); +void print_pe_flags(uint16 flags); + +#pragma pack(pop) +#endif diff --git a/idasdk75/ldr/pef/common.cpp b/idasdk76/ldr/pef/common.cpp similarity index 100% rename from idasdk75/ldr/pef/common.cpp rename to idasdk76/ldr/pef/common.cpp diff --git a/idasdk76/ldr/pef/makefile b/idasdk76/ldr/pef/makefile new file mode 100644 index 0000000..64e217e --- /dev/null +++ b/idasdk76/ldr/pef/makefile @@ -0,0 +1,16 @@ +PROC=pef + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)pef$(O) : $(I)../ldr/coff/dbxstcla.h $(I)../ldr/coff/storclas.h \ + $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../module/ppc/notify_codes.hpp ../coff/syms.h \ + ../idaldr.h common.cpp pef.cpp pef.hpp diff --git a/idasdk76/ldr/pef/pef.cpp b/idasdk76/ldr/pef/pef.cpp new file mode 100644 index 0000000..0c182bf --- /dev/null +++ b/idasdk76/ldr/pef/pef.cpp @@ -0,0 +1,766 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * FIDO: 2:5020/209 + * + * PEF Loader + * ---------- + * + */ + +#include "../idaldr.h" +#include <typeinf.hpp> +#include "pef.hpp" +#include "../coff/syms.h" +#include "../../module/ppc/notify_codes.hpp" +#include "common.cpp" + +static ea_t toc_ea; +static netnode toc; +//---------------------------------------------------------------------- +static const char *get_sec_share_name(uint8 share, char *buf, size_t bufsize) +{ + switch ( share ) + { + case PEF_SH_PROCESS: return "Shared within process"; + case PEF_SH_GLOBAL : return "Shared between all processes"; + case PEF_SH_PROTECT: return "Shared between all processes but protected"; + default: + qsnprintf(buf, bufsize, "Unknown code %d", share); + return buf; + } +} + +//---------------------------------------------------------------------- +static void process_vector(uint32 ea, const char *name) +{ + op_plain_offset(ea, 0, 0); + op_plain_offset(ea+4, 0, 0); + uint32 mintoc = get_dword(ea+4); + if ( segtype(mintoc) == SEG_DATA && mintoc < toc_ea ) + { + toc_ea = mintoc; + ppc_module_t::set_toc(toc_ea); + } + set_name(ea, name, SN_IDBENC); + char buf[MAXSTR]; + qsnprintf(buf, sizeof(buf), ".%s", name); + uint32 code = get_dword(ea); + add_entry(code, code, buf, true, AEF_IDBENC); + make_name_auto(code); +} + +//---------------------------------------------------------------------- +static void process_symbol_class(uint32 ea, uchar sclass, const char *name) +{ + switch ( sclass ) + { + case kPEFCodeSymbol: + case kPEFGlueSymbol: + add_entry(ea, ea, name, true, AEF_IDBENC); + break; + case kPEFTVectSymbol: + process_vector(ea, name); + break; + case kPEFTOCSymbol: + if ( segtype(ea) == SEG_DATA && ea < toc_ea ) + { + toc_ea = ea; + ppc_module_t::set_toc(toc_ea); + } + toc.charset_ea(ea, XMC_TD+1, 1); + /* fall thru */ + case kPEFDataSymbol: + set_name(ea, name, SN_IDBENC); + break; + } +} + +//---------------------------------------------------------------------- +static void fixup(uint32 ea, uint32 delta, int extdef) +{ + fixup_data_t fd(FIXUP_OFF32); + if ( extdef ) + fd.set_extdef(); + segment_t *s = getseg(delta); + fd.displacement = get_dword(ea); + if ( s == NULL ) + { + fd.off = delta; + } + else + { + fd.sel = s->sel; + fd.off = delta - get_segm_base(s); + } + fd.set(ea); + uint32 target = get_dword(ea) + delta; + put_dword(ea, target); + op_plain_offset(ea, 0, 0); + //cmd.ea = ea; ua_add_dref(0, target, dr_O); cmd.ea = BADADDR; + if ( target != toc_ea + && !has_name(get_flags(ea)) + && has_name(get_flags(target)) ) + { + qstring buf; + if ( get_name(&buf, target) > 0 ) + { + buf.insert("TC_"); + force_name(ea, buf.begin()); + make_name_auto(ea); + } + } +// toc.charset_ea(ea, XMC_TC+1, 1); +} + +//---------------------------------------------------------------------- +static NORETURN void bad_loader_data(void) +{ + loader_failure("Bad loader data"); +} + +//---------------------------------------------------------------------- +static NORETURN void bad_reloc_data(void) +{ + loader_failure("Bad relocation info"); +} + +//---------------------------------------------------------------------- +inline bool good_string(const char *begin, const uchar *end, const char *p) +{ + if ( p >= begin ) + { + while ( p < (const char *)end ) + { + if ( *p == '\0' ) + return true; + ++p; + } + } + return false; +} + +//---------------------------------------------------------------------- +static void process_loader_data(bytevec_t &ldrdata, const qvector<pef_section_t> &sec) +{ + pef_loader_data_t pd; + elderr_t errcode = extract_loader_data(&pd, ldrdata, sec); + if ( errcode != ELDERR_OK ) + bad_loader_data(); + + pef_loader_t &pl = pd.pl; + if ( pl.totalImportedSymbolCount != 0 ) + { + uint32 size = pl.totalImportedSymbolCount*4; + ea_t undef = free_chunk(inf_get_max_ea(), size, -0xF); + ea_t end = undef + size; + set_selector(sec.size()+1, 0); + if ( !add_segm(sec.size()+1, undef, end, "IMPORT", "XTRN") ) + loader_failure(); + + for ( int i=0; i < pl.importLibraryCount; i++ ) + { + const pef_library_t &pil = pd.pil[i]; + ea_t ea = undef + 4 * pil.firstImportedSymbol; + const char *libname = pd.stable + pil.nameOffset; + if ( !good_string(pd.stable, ldrdata.end(), libname) ) + bad_loader_data(); + add_extra_cmt(ea, true, "Imports from library %s", libname); + if ( (pil.options & PEF_LIB_WEAK) != 0 ) + add_extra_cmt(ea, true, "Library is weak"); + } + + inf_set_specsegs(inf_is_64bit() ? 8 : 4); + for ( int i=0; i < pl.totalImportedSymbolCount; i++ ) + { + uint32 sym = mflong(pd.impsym[i]); + uchar sclass = uchar(sym >> 24); + ea_t ea = undef + 4*i; + const char *iname = get_impsym_name(pd.stable, ldrdata.end(), pd.impsym, i); + if ( iname == NULL ) + bad_loader_data(); + set_name(ea, iname, SN_IDBENC); + if ( (sclass & kPEFWeak) != 0 ) + make_name_weak(ea); + create_dword(ea, 4); + put_dword(ea, 0); + pd.impsym[i] = (uint32)ea; + } + } + + if ( pl.mainSection != -1 ) + { + uint32 ea = sec[pl.mainSection].defaultAddress + pl.mainOffset; + toc_ea = sec[1].defaultAddress + get_dword(ea+4); + ppc_module_t::set_toc(toc_ea); + } + else if ( pl.initSection != -1 ) + { + uint32 ea = sec[pl.initSection].defaultAddress + pl.initOffset; + toc_ea = sec[1].defaultAddress + get_dword(ea+4); + ppc_module_t::set_toc(toc_ea); + } + + if ( qgetenv("IDA_NORELOC") ) + goto EXPORTS; + + msg("Processing relocation information... "); + for ( int i=0; i < pl.relocSectionCount; i++ ) + { + const pef_reloc_header_t &prh = pd.prh[i]; + int sidx = prh.sectionIndex; + if ( sidx >= sec.size() ) + bad_reloc_data(); + uint32 sea = sec[sidx].defaultAddress; + const uint16 *ptr = pd.relptr + prh.firstRelocOffset; + if ( !inside(ldrdata, ptr, prh.relocCount, sizeof(*ptr)) ) + bad_reloc_data(); + uint32 reladdr = sea; + uint32 import = 0; + uint32 code = sec.size() > 0 ? sec[0].defaultAddress : 0; + uint32 data = sec.size() > 1 ? sec[1].defaultAddress : 0; + int32 repeat = -1; + for ( int j=0; j < prh.relocCount; ) + { + uint16 insn = mfshort(ptr[j++]); + uint16 cnt = insn & 0x1FF; + switch ( insn >> 9 ) + { + default: // kPEFRelocBySectDWithSkip= 0x00,/* binary: 00xxxxx */ + if ( (insn & 0xC000) == 0 ) + { + int skipCount = (insn >> 6) & 0xFF; + int relocCount = insn & 0x3F; + reladdr += skipCount * 4; + while ( relocCount > 0 ) + { + relocCount--; + fixup(reladdr, data, 0); + reladdr += 4; + } + break; + } + bad_reloc_data(); + + case kPEFRelocBySectC: // = 0x20, /* binary: 0100000 */ + cnt++; + while ( cnt > 0 ) + { + cnt--; + fixup(reladdr, code, 0); + reladdr += 4; + } + break; + case kPEFRelocBySectD: + cnt++; + while ( cnt > 0 ) + { + cnt--; + fixup(reladdr, data, 0); + reladdr += 4; + } + break; + case kPEFRelocTVector12: + cnt++; + while ( cnt > 0 ) + { + cnt--; + fixup(reladdr, code, 0); + reladdr += 4; + fixup(reladdr, data, 0); + reladdr += 4; + reladdr += 4; + } + break; + case kPEFRelocTVector8: + cnt++; + while ( cnt > 0 ) + { + cnt--; + fixup(reladdr, code, 0); + reladdr += 4; + fixup(reladdr, data, 0); + reladdr += 4; + } + break; + case kPEFRelocVTable8: + cnt++; + while ( cnt > 0 ) + { + cnt--; + fixup(reladdr, data, 0); + reladdr += 4; + reladdr += 4; + } + break; + case kPEFRelocImportRun: + cnt++; + if ( import+cnt > pl.totalImportedSymbolCount ) + bad_reloc_data(); + while ( cnt > 0 ) + { + cnt--; + fixup(reladdr, pd.impsym[import], 1); + import++; + reladdr += 4; + } + break; + case kPEFRelocSmByImport: + if ( cnt >= pl.totalImportedSymbolCount ) + bad_reloc_data(); + fixup(reladdr, pd.impsym[cnt], 1); + reladdr += 4; + import = cnt + 1; + break; + case kPEFRelocSmSetSectC: + if ( cnt >= sec.size() ) + bad_reloc_data(); + code = sec[cnt].defaultAddress; + break; + case kPEFRelocSmSetSectD: + if ( cnt >= sec.size() ) + bad_reloc_data(); + data = sec[cnt].defaultAddress; + break; + case kPEFRelocSmBySection: + if ( cnt >= sec.size() ) + bad_reloc_data(); + fixup(reladdr, sec[cnt].defaultAddress, 0); + reladdr += 4; + break; + + case kPEFRelocIncrPosition: /* binary: 1000xxx */ + case kPEFRelocIncrPosition+1: + case kPEFRelocIncrPosition+2: + case kPEFRelocIncrPosition+3: + case kPEFRelocIncrPosition+4: + case kPEFRelocIncrPosition+5: + case kPEFRelocIncrPosition+6: + case kPEFRelocIncrPosition+7: + reladdr += (insn & 0x0FFF)+1; + break; + + case kPEFRelocSmRepeat: /* binary: 1001xxx */ + case kPEFRelocSmRepeat+1: + case kPEFRelocSmRepeat+2: + case kPEFRelocSmRepeat+3: + case kPEFRelocSmRepeat+4: + case kPEFRelocSmRepeat+5: + case kPEFRelocSmRepeat+6: + case kPEFRelocSmRepeat+7: + if ( repeat == -1 ) + repeat = (insn & 0xFF)+1; + repeat--; + if ( repeat != -1 ) + j -= ((insn>>8) & 15)+1 + 1; + break; + + case kPEFRelocSetPosition: /* binary: 101000x */ + case kPEFRelocSetPosition+1: + { + ushort next = mfshort(ptr[j++]); + uint32 offset = next | (uint32(insn & 0x3FF) << 16); + reladdr = sea + offset; + } + break; + + case kPEFRelocLgByImport: /* binary: 101001x */ + case kPEFRelocLgByImport+1: + { + ushort next = mfshort(ptr[j++]); + uint32 index = next | (uint32(insn & 0x3FF) << 16); + if ( index >= pl.totalImportedSymbolCount ) + bad_reloc_data(); + fixup(reladdr, pd.impsym[index], 1); + reladdr += 4; + import = index + 1; + } + break; + + case kPEFRelocLgRepeat: /* binary: 101100x */ + case kPEFRelocLgRepeat+1: + { + ushort next = mfshort(ptr[j++]); + if ( repeat == -1 ) + repeat = next | (uint32(insn & 0x3F) << 16); + repeat--; + if ( repeat != -1 ) + j -= ((insn >> 6) & 15) + 1 + 2; + } + break; + + case kPEFRelocLgSetOrBySection: /* binary: 101101x */ + case kPEFRelocLgSetOrBySection+1: + { + ushort next = mfshort(ptr[j++]); + uint32 index = next | (uint32(insn & 0x3F) << 16); + if ( index >= sec.size() ) + bad_reloc_data(); + int subcode = (insn >> 6) & 15; + switch ( subcode ) + { + case 0: + fixup(reladdr, sec[index].defaultAddress, 0); + reladdr += 4; + break; + case 1: + code = sec[index].defaultAddress; + break; + case 2: + data = sec[index].defaultAddress; + break; + } + } + break; + } + } + } + +EXPORTS: + for ( int i=0; i < pl.exportedSymbolCount; i++ ) + { + const pef_export_t &pe = pd.pe[i]; + uchar sclass = uchar(pe.classAndName >> 24); + char name[MAXSTR]; + uint32 ea; + switch ( pe.sectionIndex ) + { + case -3: + { + uint symidx = pe.symbolValue; + if ( symidx >= pl.totalImportedSymbolCount ) + bad_reloc_data(); + ea = pd.impsym[symidx]; + } + break; + case -2: // absolute symbol + ask_for_feedback("Absolute symbols are not implemented"); + continue; + default: + { + uint secidx = pe.sectionIndex; + if ( secidx >= sec.size() ) + bad_reloc_data(); + ea = sec[secidx].defaultAddress + pe.symbolValue; + } + break; + } + if ( !get_expsym_name(pd.stable, pd.keytable, pd.pe, i, ldrdata.end(), name, sizeof(name)) ) + bad_loader_data(); + process_symbol_class(ea, sclass & 0xF, name); + } + msg("done.\n"); + + if ( pl.mainSection >= 0 && pl.mainSection < sec.size() ) + { + uint32 ea = sec[pl.mainSection].defaultAddress + pl.mainOffset; + process_vector(ea, "start"); + inf_set_start_cs(0); + inf_set_start_ip(get_dword(ea)); + } + if ( pl.initSection >= 0 && pl.initSection < sec.size() ) + { + uint32 ea = sec[pl.initSection].defaultAddress + pl.initOffset; + process_vector(ea, "INIT_VECTOR"); + } + if ( pl.termSection >= 0 && pl.termSection < sec.size() ) + { + uint32 ea = sec[pl.termSection].defaultAddress + pl.termOffset; + process_vector(ea, "TERM_VECTOR"); + } + + if ( toc_ea != BADADDR ) + set_name(toc_ea, "TOC"); +} + +//-------------------------------------------------------------------------- +static NORETURN void bad_packed_data(void) +{ + loader_failure("Illegal compressed data"); +} + +//-------------------------------------------------------------------------- +static uint32 read_number(const uchar *&packed, const uchar *end) +{ + uint32 arg = 0; + for ( int i=0; ; i++ ) + { + if ( packed >= end ) + bad_packed_data(); + uchar b = *packed++; + arg <<= 7; + arg |= (b & 0x7F); + if ( (b & 0x80) == 0 ) + break; + if ( i > 4 ) + bad_packed_data(); + } + return arg; +} + +//-------------------------------------------------------------------------- +static void unpack_section( + const bytevec_t &packedvec, + ea_t start, + uint32 usize) +{ + bytevec_t unpacked; + const uchar *packed = packedvec.begin(); + const uchar *pckend = packedvec.begin() + packedvec.size(); + while ( packed < pckend ) + { + uchar code = *packed++; + uint32 arg = code & 0x1F; + if ( arg == 0 ) + arg = read_number(packed, pckend); + switch ( code >> 5 ) + { + case 0: // Zero + unpacked.growfill(arg); + break; + + case 1: // blockCopy + { + const uchar *end = packed + arg; + if ( end < packed || end > pckend ) + bad_packed_data(); + unpacked.append(packed, arg); + packed += arg; + } + break; + + case 2: // repeatedBlock + { + int32 repeat = read_number(packed, pckend) + 1; + const uchar *end = packed + arg; + if ( end < packed || end > pckend ) + bad_packed_data(); + while ( --repeat >= 0 ) + unpacked.append(packed, arg); + packed += arg; + } + break; + + case 3: // interleaveRepeatBlockWithBlockCopy + { + int32 commonSize = arg; + int32 customSize = read_number(packed, pckend); + int32 repeatCount = read_number(packed, pckend); + const uchar *common = packed; + packed += commonSize; + if ( packed < common || packed > pckend ) + bad_packed_data(); + while ( --repeatCount >= 0 ) + { + const uchar *end = packed + customSize; + if ( end < packed || end > pckend ) + bad_packed_data(); + unpacked.append(common, commonSize); + unpacked.append(packed, customSize); + packed += customSize; + } + unpacked.append(common, commonSize); + } + break; + + case 4: // interleaveRepeatBlockWithZero + { + int32 commonSize = arg; + int32 customSize = read_number(packed, pckend); + int32 repeatCount = read_number(packed, pckend); + while ( --repeatCount >= 0 ) + { + const uchar *end = packed + customSize; + if ( end < packed || end > pckend ) + bad_packed_data(); + unpacked.growfill(commonSize); + unpacked.append(packed, customSize); + packed += customSize; + } + unpacked.growfill(commonSize); + } + break; + + default: + bad_packed_data(); + } + } + if ( unpacked.size() < usize ) + unpacked.growfill(usize-unpacked.size()); + if ( unpacked.size() != usize ) + bad_packed_data(); + mem2base(unpacked.begin(), start, start+unpacked.size(), FILEREG_NOTPATCHABLE); +} + +//-------------------------------------------------------------------------- +static void load_section( + int i, + linput_t *li, + pef_section_t &ps, + const char *sname, + const char *classname, + int is_packed) +{ + uint32 size = ps.totalSize; + ea_t base = ps.defaultAddress ? ps.defaultAddress : to_ea(inf_get_baseaddr(), 0); + ea_t start = free_chunk(base, size, 1-(1 << ps.alignment)); + ea_t end = start + size; + if ( is_packed ) + { + bytevec_t packed; + packed.resize(ps.packedSize); + qlseek(li, ps.containerOffset); + lread(li, packed.begin(), packed.size()); + unpack_section(packed, start, ps.unpackedSize); + } + else + { + file2base(li, ps.containerOffset, + start, start+ps.unpackedSize, FILEREG_PATCHABLE); + } + set_selector(i+1, 0); + if ( !add_segm(i+1, start, end, sname, classname, ADDSEG_SPARSE) ) + loader_failure(); + ps.defaultAddress = start; + if ( start < inf_get_lowoff() ) + inf_set_lowoff(start); +} + +//-------------------------------------------------------------------------- +// +// load file into the database. +// +void idaapi load_file(linput_t *li, ushort /*neflag*/, const char * /*fileformatname*/) +{ + pef_t pef; + toc_ea = BADADDR; + toc.create("$ toc"); + qlseek(li, 0); + lread(li, &pef, sizeof(pef_t)); + swap_pef(pef); + + const char *proc = get_pef_processor(pef); + if ( proc != NULL ) + { + set_processor_type(proc, SETPROC_LOADER); + if ( PH.id == PLFM_PPC ) + { + // Mac OS Runtime Architecture for the PowerPC is very similar to AIX + set_abi_name("aix"); + } + } + + // read section headers + qvector<pef_section_t> sec; + if ( pef.sectionCount != 0 ) + { + sec.resize(pef.sectionCount); + lread(li, sec.begin(), sec.size()*sizeof(pef_section_t)); + } + + // swap section headers and find the loader section + pef_section_t *loader = NULL; + for ( int i=0; i < sec.size(); i++ ) + { + swap_pef_section(sec[i]); + if ( sec[i].sectionKind == PEF_SEC_LOADER ) + loader = &sec[i]; + } + + int32 snames_table = sizeof(pef_t) + sizeof(pef_section_t)*sec.size(); + for ( int i=0; i < sec.size(); i++ ) + { + char buf[MAXSTR]; + char *secname = get_string(li, snames_table, sec[i].nameOffset, buf, sizeof(buf)); + switch ( sec[i].sectionKind ) + { + case PEF_SEC_PDATA : // Pattern initialized data segment + load_section(i, li, sec[i], secname, CLASS_DATA, 1); + break; + case PEF_SEC_CODE : // Code segment + case PEF_SEC_EDATA : // Executable data segment + load_section(i, li, sec[i], secname, CLASS_CODE, 0); + break; + case PEF_SEC_DATA: // Unpacked data segment + load_section(i, li, sec[i], secname, + sec[i].unpackedSize != 0 ? CLASS_DATA : CLASS_BSS, 0); + break; + case PEF_SEC_CONST: // Read only data + load_section(i, li, sec[i], secname, CLASS_CONST, 0); + break; + case PEF_SEC_LOADER: // Loader section + case PEF_SEC_DEBUG : // Reserved for future use + case PEF_SEC_EXCEPT: // Reserved for future use + case PEF_SEC_TRACEB: // Reserved for future use + continue; + default: + ask_for_feedback("Unknown section type"); + continue; + } + if ( i == 0 ) + create_filename_cmt(); + add_extra_cmt(sec[i].defaultAddress, true, "Segment share type: %s\n", + get_sec_share_name(sec[i].shareKind, buf, sizeof(buf))); + } + if ( loader != NULL ) + { + bytevec_t ldrdata; + ldrdata.resize(loader->packedSize); + qlseek(li, loader->containerOffset); + lread(li, ldrdata.begin(), ldrdata.size()); + process_loader_data(ldrdata, sec); + } +} + + +//-------------------------------------------------------------------------- +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + const char *proc = get_pef_processor(li); + if ( proc == NULL ) + return 0; + + *fileformatname = "PEF (Mac OS or Be OS executable)"; + *processor = proc; + return 1; +} + +//---------------------------------------------------------------------- +// +// LOADER DESCRIPTION BLOCK +// +//---------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk75/ldr/pef/pef.hpp b/idasdk76/ldr/pef/pef.hpp similarity index 100% rename from idasdk75/ldr/pef/pef.hpp rename to idasdk76/ldr/pef/pef.hpp diff --git a/idasdk76/ldr/pilot/common.cpp b/idasdk76/ldr/pilot/common.cpp new file mode 100644 index 0000000..6121bda --- /dev/null +++ b/idasdk76/ldr/pilot/common.cpp @@ -0,0 +1,144 @@ + +//------------------------------------------------------------------------- +static void swap_prc(DatabaseHdrType &h) +{ + h.attributes = swap16(h.attributes); + h.version = swap16(h.version); + h.creationDate = swap32(h.creationDate); + h.modificationDate = swap32(h.modificationDate); + h.lastBackupDate = swap32(h.lastBackupDate); + h.modificationNumber = swap32(h.modificationNumber); + h.appInfoID = swap32(h.appInfoID); + h.sortInfoID = swap32(h.sortInfoID); +// h.type = swap32(h.type); +// h.id = swap32(h.id); + h.uniqueIDSeed = swap32(h.uniqueIDSeed); + h.nextRecordListID = swap32(h.nextRecordListID); + h.numRecords = swap16(h.numRecords); +} + +//------------------------------------------------------------------------- +static void swap_resource_map_entry(ResourceMapEntry &re) +{ + re.id = swap16(re.id); + re.ulOffset = swap32(re.ulOffset); +} + +//------------------------------------------------------------------------- +void swap_bitmap(pilot_bitmap_t *b) +{ + b->cx = swap16(b->cx); + b->cy = swap16(b->cy); + b->cbRow = swap16(b->cbRow); + b->ausUnk[0] = swap16(b->ausUnk[0]); + b->ausUnk[1] = swap16(b->ausUnk[1]); + b->ausUnk[2] = swap16(b->ausUnk[2]); + b->ausUnk[3] = swap16(b->ausUnk[3]); +} + +//------------------------------------------------------------------------- +void swap_code0000(code0000_t *cp) +{ + cp->nBytesAboveA5 = swap32(cp->nBytesAboveA5); + cp->nBytesBelowA5 = swap32(cp->nBytesBelowA5); +} + +//------------------------------------------------------------------------- +void swap_pref0000(pref0000_t *pp) +{ + pp->flags = swap16(pp->flags); + pp->stack_size = swap32(pp->stack_size); + pp->heap_size = swap32(pp->heap_size); +} + +//------------------------------------------------------------------------- +// Since the Palm Pilot programs are really poorly recognized by usual +// methods, we are forced to read the resource tablee to determine +// if everying is ok +// return 0 if not a PRC, 2 if has ARM code segments, 1 otherwise +int is_prc_file(linput_t *li) +{ + DatabaseHdrType h; + if ( qlread(li,&h,sizeof(h)) != sizeof(h) ) + return 0; + swap_prc(h); + if ( (h.attributes & dmHdrAttrResDB) == 0 ) + return 0; + if ( short(h.numRecords) <= 0 ) + return 0; + const uint64 filesize = qlsize(li); + const uint64 lowestpos = uint64(h.numRecords)*sizeof(ResourceMapEntry) + sizeof(h); + if ( lowestpos > filesize ) + return 0; + + // the dates can be plain wrong, so don't check them: + // uint32 now = time(NULL); + // && uint32(h.lastBackupDate) <= now // use unsigned comparition! + // && uint32(h.creationDate) <= now // use unsigned comparition! + // && uint32(h.modificationDate) <= now // use unsigned comparition! + + qvector<ResourceMapEntry> re; + re.resize(h.numRecords); + size_t size = sizeof(ResourceMapEntry) * h.numRecords; + if ( qlread(li, re.begin(), size) != size ) + return 0; + + bool hasArmCode = false; + for ( int i=0; i < h.numRecords; i++ ) + { + swap_resource_map_entry(re[i]); + if ( re[i].ulOffset >= filesize || re[i].ulOffset < lowestpos ) + return 0; + if ( re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL ) + hasArmCode = true; + } + return hasArmCode ? 2 : 1; +} + +bool isKnownResource(uint32 resId) +{ + switch ( resId ) + { + case MC4('t', 'F', 'R', 'M'): + case MC4('t', 'B', 'T', 'N'): + case MC4('t', 'C', 'B', 'X'): + case MC4('t', 'F', 'B', 'M'): + case MC4('t', 'F', 'L', 'D'): + case MC4('t', 'g', 'b', 'n'): + case MC4('t', 'G', 'D', 'T'): + case MC4('t', 'g', 'p', 'b'): + case MC4('t', 'g', 'r', 'b'): + case MC4('t', 'G', 'S', 'I'): + case MC4('t', 'L', 'B', 'L'): + case MC4('t', 'L', 'S', 'T'): + case MC4('t', 'P', 'B', 'N'): + case MC4('t', 'P', 'U', 'L'): + case MC4('t', 'P', 'U', 'T'): + case MC4('t', 'R', 'E', 'P'): + case MC4('t', 'S', 'C', 'L'): + case MC4('t', 's', 'l', 'd'): + case MC4('t', 's', 'l', 'f'): + case MC4('t', 'S', 'L', 'T'): + case MC4('t', 'T', 'B', 'L'): + case MC4('T', 'a', 'l', 't'): + case MC4('M', 'B', 'A', 'R'): + case MC4('M', 'E', 'N', 'U'): + case MC4('t', 'S', 'T', 'R'): + case MC4('t', 'S', 'T', 'L'): + case MC4('T', 'b', 'm', 'p'): + case MC4('t', 'b', 'm', 'f'): + case MC4('P', 'I', 'C', 'T'): + case MC4('t', 'v', 'e', 'r'): + case MC4('t', 'A', 'I', 'N'): + case MC4('t', 'a', 'i', 'c'): + case MC4('t', 'A', 'I', 'S'): + case MC4('t', 'A', 'I', 'B'): + case MC4('t', 'a', 'i', 'f'): + case MC4('I', 'C', 'O', 'N'): + case MC4('c', 'i', 'c', 'n'): + case MC4('p', 'r', 'e', 'f'): + case MC4('x', 'p', 'r', 'f'): + return true; + } + return false; +} diff --git a/idasdk76/ldr/pilot/makefile b/idasdk76/ldr/pilot/makefile new file mode 100644 index 0000000..a889966 --- /dev/null +++ b/idasdk76/ldr/pilot/makefile @@ -0,0 +1,14 @@ +PROC=pilot +IDCS=pilot.idc + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)pilot$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)expr.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h common.cpp pilot.cpp pilot.hpp diff --git a/idasdk76/ldr/pilot/pilot.cpp b/idasdk76/ldr/pilot/pilot.cpp new file mode 100644 index 0000000..8140bb3 --- /dev/null +++ b/idasdk76/ldr/pilot/pilot.cpp @@ -0,0 +1,912 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + */ + +#include "../idaldr.h" +#include <expr.hpp> +#include "pilot.hpp" + +#include "common.cpp" +//------------------------------------------------------------------------ +static void describe_all(DatabaseHdrType &h) +{ + create_filename_cmt(); + add_pgm_cmt("Version : %04X",h.version); + add_pgm_cmt("DatabaseType: %4.4s",(char*)&h.type); + add_pgm_cmt("\n appl \"%s\", '%4.4s'", h.name, (char*)&h.id); +} + +//------------------------------------------------------------------------ +// +// Structure of the DATA 0 resource: +// +// +--------------------------------------------+ +// | long: offset of CODE 1 xrefs? |- -+ +// +--------------------------------------------+ | +// | char[]: Initialized near data (below A5) | | +// +--------------------------------------------+ | +// | char[]: Uninitialized near data (below A5) | | +// +--------------------------------------------+ | +// | char[]: Initialized far data (above A5) | | +// +--------------------------------------------+ | +// | char[]: DATA 0 xrefs | | +// +--------------------------------------------+ | +// | char[]: CODE 1 xrefs |<--+ +// +--------------------------------------------+ +// + +static uchar *apply_relocs(uchar *packed, size_t &packlen, ea_t relocbase, ea_t targetbase, bool code=false) +{ + if ( packlen < 4 ) + { +BADDATA: + warning("Bad packed data"); + return NULL; + } + uint32 nrelocs = swap32(*(uint32*)packed); + packed += 4; + packlen -= 4; + ea_t offset = relocbase; + fixup_data_t fd(FIXUP_OFF32); + if ( code ) + fd.set_sel(getseg(targetbase)); + //msg("%d relocations\n", nrelocs); + for ( uint i=0; i < nrelocs; i++ ) + { + if ( packlen < 1 ) + goto BADDATA; + uchar c = *packed; + if ( c&0x80 ) + { + // signed 8-bit delta + offset+=(char)(c<<1); + packed++; + packlen--; + } + else if ( c&0x40 ) + { + if ( packlen < 2 ) + goto BADDATA; + // 15-bit unsigned(?) delta + // comment in PalmOS_Startup.cpp says "unsigned" but they cast it to a signed short... + uint32 o1 = swap16(*(ushort*)packed); + packed += 2; + packlen -= 2; + offset += (short)(o1<<2)>>1; + } + else + { + if ( packlen < 4 ) + goto BADDATA; + // direct signed 31-bit offset + offset = relocbase+(int32(swap32(*(int32*)packed)<<2)>>1); + packed += 4; + packlen -= 4; + } + for ( int j=0; j < 4; j++ ) + if ( !is_loaded(offset+j) ) + put_byte(offset+j, 0); + fd.off = get_dword(offset); + if ( code ) + { + fd.set(offset); + auto_make_proc(targetbase+fd.off); + if ( get_word(offset-2) == 0x4EF9 ) // jump opcode? + auto_make_proc(offset-2); + } + else + { + fd.set_base(targetbase); + fd.set(offset); + } +// msg("Relocation %d at %08X: %08X -> %08X\n", i, offset-relocbase, fd.off, targetbase+fd.off); + } + return packed; +} + +//------------------------------------------------------------------------ +// unpack rle data from the buffer packed at file position fpos to ea cea +// return new position in the buffer and update cea +static uchar *unpack_rle(uchar *packed, size_t &packlen, ea_t &cea, qoff64_t fpos) +{ + const uchar *packed_sav = packed; + while ( 1 ) + { + if ( packlen < 1 ) + { +BADDATA: + warning("Bad packed data"); + return NULL; + } + uchar buf[256]; + buf[0] = '\0'; // shutup lint + uchar cnt = *packed++; + packlen--; + if ( cnt == 0 ) + break; + if ( cnt & 0x80 ) + { + cnt = (cnt & 0x7F) + 1; + if ( packlen < cnt ) + goto BADDATA; + mem2base(packed, cea, cea+cnt, fpos+(packed-packed_sav)); + packed += cnt; + packlen -= cnt; + cea += cnt; + continue; + } + if ( cnt & 0x40 ) + { + cnt = (cnt & 0x3F) + 1; + memset(buf, 0, cnt); + } + else if ( cnt & 0x20 ) + { + if ( packlen < 1 ) + goto BADDATA; + cnt = (cnt & 0x1F) + 2; + memset(buf, *packed++, cnt); + packlen--; + } + else if ( cnt & 0x10 ) + { + cnt = (cnt & 0x0F) + 1; + memset(buf, 0xFF, cnt); + } + else if ( cnt == 1 ) + { + if ( packlen < 2 ) + goto BADDATA; + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0xFF; + buf[5] = 0xFF; + buf[6] = *packed++; + buf[7] = *packed++; + packlen -= 2; + cnt = 8; + } + else if ( cnt == 2 ) + { + if ( packlen < 3 ) + goto BADDATA; + buf[0] = 0x00; + buf[1] = 0x00; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0xFF; + buf[5] = *packed++; + buf[6] = *packed++; + buf[7] = *packed++; + cnt = 8; + packlen -= 3; + } + else if ( cnt == 3 ) + { + if ( packlen < 3 ) + goto BADDATA; + buf[0] = 0xA9; + buf[1] = 0xF0; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = *packed++; + buf[5] = *packed++; + buf[6] = 0x00; + buf[7] = *packed++; + cnt = 8; + packlen -= 3; + } + else if ( cnt == 4 ) + { + if ( packlen < 4 ) + goto BADDATA; + buf[0] = 0xA9; + buf[1] = 0xF0; + buf[2] = 0x00; + buf[3] = *packed++; + buf[4] = *packed++; + buf[5] = *packed++; + buf[6] = 0x00; + buf[7] = *packed++; + cnt = 8; + packlen -= 4; + } + mem2base(buf, cea, cea+cnt, -1); + cea += cnt; + } + return packed; +} + +//------------------------------------------------------------------------ +static size_t unpack_data0000( + linput_t *li, + qoff64_t fpos, + size_t size, + ea_t ea, + const code0000_t &code0000, + ea_t code1ea, + ea_t &a5) +{ + if ( size < 4 ) + { +BADDATA: + warning("Bad packed data"); + return 0; + } + bytevec_t packed_buf; + packed_buf.resize(size); + uchar *packed = packed_buf.begin(); + qlseek(li, fpos); + lread(li, packed, size); + size_t usize = code0000.nBytesAboveA5 + code0000.nBytesBelowA5; // total data size + enable_flags(ea, ea+usize, STT_CUR); + + packed += sizeof(uint32); // skip initializers size + size -= sizeof(uint32); + + a5 = ea+code0000.nBytesBelowA5; + ea_t cea; + for ( int i=0; i < 3; i++ ) + { + if ( size < 4 ) + goto BADDATA; + int32 offset = swap32(*(uint32*)packed); // offset from A5 + packed += sizeof(uint32); + size -= sizeof(uint32); + cea = a5 + offset; + if ( cea < ea ) + { + // can happen when code 0 resource is not present (e.g. prc-tools GLib-type shared libs) + if ( i != 0 ) + loader_failure("Error while decompressing data 0"); + cea = ea; + a5 = ea-offset; + } + if ( size > 0 ) + { + packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); + if ( packed == NULL ) + return 0; + } + if ( usize < cea-ea ) + usize = size_t(cea-ea); + } + + if ( a5 > ea + usize - 1 ) + { + // allocate one extra byte for A5 + enable_flags(ea+usize, ea+usize+1, STT_CUR); + usize++; + } + create_byte(a5,1); + if ( a5 != ea ) + add_pgm_cmt("A5 register does not point to the start of the data segment\n" + "The file should not be recompiled using Pila\n"); + set_name(a5,"A5BASE",SN_NOCHECK|SN_AUTO); + set_cmt(a5,"A5 points here",0); + // TODO: find undefined bytes and set them to zero + // this is done by Palm OS loader and some programs depend on it + + // process relocations + if ( size > 0 ) + { + // a5 to a5 + // msg("Relocations: data to data\n"); + packed = apply_relocs(packed, size, a5, a5); + if ( packed == NULL ) + return 0; + // packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); + } + if ( size > 0 ) + { + // a5 to code + // msg("Relocations: data to code1\n"); + packed = apply_relocs(packed, size, a5, code1ea, true); + if ( packed == NULL ) + return 0; + // packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); + } + return usize; +} + +//------------------------------------------------------------------------ +// CodeWarrior A4 data layout: +// +// 0..3: 0x00000000 +// 4..7: size of "above A4" region +// 8..11: size of "below A4" region +// 12..N-1: compressed "below A4" data +// N..N+3: size of "near above A4" region +// N+4..O-1: compressed "near above A4" data +// O..O+3: size of "far above A4" region +// O+4..P-1: compressed "far above A4" data +// then the relocations: +// 1) A4 -> A4 +// 2) A4 -> A5 +// 3) A4 -> code0001 +// 4) A5 -> A4 + +static size_t unpack_data0001(linput_t *li, qoff64_t fpos, size_t size, ea_t ea, ea_t a5, ea_t code1ea, ea_t &a4) +{ + if ( size < 3 * sizeof(uint32) ) + { +BADDATA: + warning("Bad packed data"); + return 0; + } + bytevec_t packed_buf; + packed_buf.resize(size); + uchar *packed = packed_buf.begin(); + qlseek(li, fpos); + lread(li, packed, size); + packed += sizeof(uint32); // skip the 0 + size -= sizeof(uint32); + + int32 above = swap32(*(int32*)packed); + packed += sizeof(int32); + size -= sizeof(uint32); + int32 below = swap32(*(int32*)packed); + packed += sizeof(int32); + size -= sizeof(uint32); + size_t usize = above - below; // unpacked size + if ( below & 1 ) + usize++; + + ea_t cea = ea; + a4 = ea-below; + if ( below & 1 ) + a4++; + enable_flags(ea, ea+usize, STT_CUR); + create_byte(a4,1); + set_name(a4,"A4BASE",SN_NOCHECK|SN_AUTO); + set_cmt(a4,"A4 points here",0); + + // unpack below a4 + packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); + if ( packed == NULL ) + return 0; + + // unpack near above a4 + if ( size < sizeof(int32) ) + goto BADDATA; + cea = a4 + swap32(*(int32*)packed); + packed += sizeof(int32); + size -= sizeof(uint32); + packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); + if ( packed == NULL ) + return 0; + + // unpack far above a4 + if ( size < sizeof(int32) ) + goto BADDATA; + cea = a4 + swap32(*(int32*)packed); + packed += sizeof(int32); + size -= sizeof(uint32); + packed = unpack_rle(packed, size, cea, fpos+(packed-packed_buf.begin())); + if ( packed == NULL ) + return 0; + + cea -= ea; + if ( usize < cea ) + usize = (size_t)cea; + + // process relocations + if ( size > 0 ) + { + // a4 to a4 + // msg("Relocations: a4 to a4\n"); + packed = apply_relocs(packed, size, a4, a4); + if ( packed == NULL ) + return 0; + // packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); + } + if ( size > 0 ) + { + // a4 to a5 + // msg("Relocations: a4 to a5\n"); + packed = apply_relocs(packed, size, a4, a5); + if ( packed == NULL ) + return 0; + // packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); + } + if ( size > 0 ) + { + // a4 to code1 + // msg("Relocations: a4 to code1\n"); + packed = apply_relocs(packed, size, a4, code1ea, true); + if ( packed == NULL ) + return 0; + // packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); + } + if ( size > 0 ) + { + // a5 to a4 + // msg("Relocations: a5 to a4\n"); + packed = apply_relocs(packed, size, a5, a4); + if ( packed == NULL ) + return 0; + // packed = (uchar*)__Relocate__((Int8*)packed, 0, 0); + } + return usize; +} + +//------------------------------------------------------------------------ +void fix_jumptables(ea_t ea1, ea_t /*ea2*/, sel_t sel, ea_t a5, ea_t a4) +{ + // msg("Fixing additional code segment at %08X\n",ea1); + // from PalmOS_Startup.cpp + /* + struct SegmentHeader { // the structure of a segment header + short jtsoffset; // A5 relative offset of this segments jump table (short version) + short jtentries; // number of entries in this segments jump table + int32 jtloffset; // A5 relative offset of this segments jump table (long version) + int32 xrefoffset; // offset of xref data in this CODE resource + char code[]; // the code + }; + struct JumpTableEntry { // the structure of a jumptable entry + short jumpinstruction; // instruction: jmp routine + int32 jumpaddress; // absolute or relative address of rountine + };*/ + + short jtsoffset = get_word(ea1); + int32 jtloffset = get_dword(ea1+4); + if ( jtsoffset != jtloffset ) + { + // msg("Doesn't look like a CodeWarrior code segment\n"); + return; + } + // find the jumptable + ea_t jt_start; + if ( a4 != BADADDR && get_word(a4+jtloffset) == 0x4EF9 ) // jmp opcode + { + jt_start = a4+jtloffset; + create_word(ea1,2); + create_dword(ea1+4,4); + op_offset(ea1, 0, REF_OFF16, BADADDR, a4); + op_offset(ea1+4, 0, REF_OFF32, BADADDR, a4); + } + else if ( get_word(a5+jtloffset) == 0x4EF9 ) // jmp opcode + { + jt_start = a5+jtloffset; + create_word(ea1,2); + create_dword(ea1+4,4); + op_offset(ea1, 0, REF_OFF16, BADADDR, a5); + op_offset(ea1+4, 0, REF_OFF32, BADADDR, a5); + } + else + { + // msg("Could not find the jump table!\n"); + return; + } + + create_word(ea1+2,2); + create_dword(ea1+8,4); + op_offset(ea1+8, 0, REF_OFF32, BADADDR, ea1); + set_cmt(ea1, "Short jump table offset", 0); + set_cmt(ea1+2, "Number of jump table entries", 0); + set_cmt(ea1+4, "Long jump table offset", 0); + set_cmt(ea1+8, "Offset to xref data", 0); + + fixup_data_t fd(FIXUP_OFF32); + fd.sel = sel; + ea_t jt_addr=jt_start; + short jtentries = get_word(ea1+2); + while ( jtentries-- ) + { + fd.off = get_dword(jt_addr+2); + fd.set(jt_addr+2); + // a little heuristic: does the jump point to code? + if ( get_word(ea1+fd.off) == 0x4E56 // link a6,x + || get_word(ea1+fd.off) == 0x06AF ) // addi.l x, 4(sp) + { + auto_make_proc(ea1+fd.off); + auto_make_proc(jt_addr); + } + jt_addr+=6; + } + // TODO: hide the table? + // add_hidden_range(jt_start, jt_addr, "Jumptable for segment NNN", "", "", 0); +} + +//------------------------------------------------------------------------ +void doCodeOffset(ea_t ea, ea_t base) +{ + create_dword(ea,4); + uint32 off = get_dword(ea); + op_offset(ea, 0, REF_OFF32, BADADDR, base, off&1); + ea_t target = base+off; + if ( off&1 )// last bit set: offset to thumb code + { + target &= (~1); // remove last bit + // set_sreg_at_next_code(target,BADADDR,str2reg("T"),1); + split_sreg_range(target,str2reg("T"),1,SR_auto,true); + } + auto_make_proc(target); +} + +//------------------------------------------------------------------------ +void fixArmCW(ea_t start_ea, ea_t end_ea) +{ + // check for codewarrior relocation info + /* + typedef struct PnoHeaderType { + 00 UInt32 startupCode[8]; // changes based on the instruction count in startup code + 20 UInt32 pnoMain; // offset to ARMletMain routine + 24 UInt32 signature; // special PNO signature value + 28 UInt32 dataStart; // offset to start of initialized data + 2C UInt32 roDataStart; // offset to start of read-only initialized data + 30 UInt32 bssStart; // offset to start of uninitialized data + 34 UInt32 bssEnd; // offset to end of uninitialized data + 38 UInt32 codeRelocsStart; // offset to start of data-to-code relocation list + 3C UInt32 codeRelocsEnd; // offset to end of data-to-code relocation list + 40 UInt32 dataRelocsStart; // offset to start of data-to-data relocation list + 44 UInt32 dataRelocsEnd; // offset to end of data-to-data relocation list + 48 UInt32 altEntryCode[8]; // changes based on the instruction count in alternate entry code + 68 + } PnoHeaderType; + */ + const char *const comments[] = + { + "offset to ARMletMain routine", + "special PNO signature value", + "offset to start of initialized data", + "offset to start of read-only initialized data", + "offset to start of uninitialized data", + "offset to end of uninitialized data", + "offset to start of data-to-code relocation list", + "offset to end of data-to-code relocation list", + "offset to start of data-to-data relocation list", + "offset to end of data-to-data relocation list", + }; + + if ( end_ea-start_ea < 0x68 ) + return; + for ( int i=0x20; i < 0x48; i+=4 ) + { + create_dword(start_ea+i,4); + if ( i == 0x24 ) + op_chr(start_ea+i, 0); + else + op_offset(start_ea+i, 0, REF_OFF32, BADADDR, start_ea); + set_cmt(start_ea+i, comments[(i-0x20)/4],0); + } + auto_make_proc(start_ea); + auto_make_proc(start_ea+0x48); + doCodeOffset(start_ea+0x20,start_ea); + + // do relocs + ea_t cur = start_ea+get_dword(start_ea+0x38); + ea_t end = start_ea+get_dword(start_ea+0x3C); + for ( ; cur < end; cur+=4 ) + { + create_dword(cur,4); + op_offset(cur, 0, REF_OFF32, BADADDR, start_ea); + doCodeOffset(start_ea+get_dword(cur), start_ea); + } + cur = start_ea+get_dword(start_ea+0x40); + end = start_ea+get_dword(start_ea+0x44); + for ( ; cur < end; cur+=4 ) + { + create_dword(cur,4); + op_offset(cur, 0, REF_OFF32, BADADDR, start_ea); + ea_t o = start_ea+get_dword(cur); + create_dword(o,4); + op_offset(o, 0, REF_OFF32, BADADDR, start_ea); + } +} + +//------------------------------------------------------------------------ +// check for 'cdwr' signature +bool isCWseg(linput_t *li, uint32 offset) +{ + qlseek(li, offset + 0x24); + uchar sig[4]; + qlread(li, sig, 4); + return sig[0] == 'r' + && sig[1] == 'w' + && sig[2] == 'd' + && sig[3] == 'c'; +} + +//------------------------------------------------------------------------ +void idaapi load_file(linput_t *li, ushort neflags, const char * fileformatname) +{ + int i; + bool armCode = strcmp(fileformatname, PRC_ARM) == 0; + bool manualMode = (neflags & NEF_MAN) != 0; // don't do any extra processing if set + sel_t dgroup = BADSEL; + + set_processor_type(armCode ? "ARM" : "68K", SETPROC_LOADER); + set_target_assembler(armCode ? 0 : 2); // Generic ARM assembler/PalmPilot assembler Pila + DatabaseHdrType h; + lread(li,&h,sizeof(h)); + swap_prc(h); + + qvector<ResourceMapEntry> re; + re.resize(h.numRecords); + lread(li, re.begin(), sizeof(ResourceMapEntry) * h.numRecords); + for ( i=0; i < h.numRecords; i++ ) + swap_resource_map_entry(re[i]); + + code0000_t code0000 = { 0, 0 }; + if ( !armCode ) + { + // sortResources(re, h.numRecords); + // determine the bss size + for ( i=0; i < h.numRecords; i++ ) + { + if ( re[i].fcType == PILOT_RSC_CODE && re[i].id == 0 ) // code0000 + { + qlseek(li, re[i].ulOffset); + lread(li, &code0000, sizeof(code0000)); + swap_code0000(&code0000); + break; + } + } + } + + ea_t a5 = BADADDR, a4 = BADADDR, code1ea = BADADDR; + ea_t datastart = BADADDR; + + // load the segments + for ( i=0; i < h.numRecords; i++ ) + { + // don't load known UI resources when asked not to + if ( !(NEF_RSCS & neflags) && isKnownResource(re[i].fcType) ) + continue; + // skip ARM chunks in 68K mode + if ( !armCode && (re[i].fcType == PILOT_RSC_ARMC || re[i].fcType == PILOT_RSC_ARMCL) ) + continue; + + uint64 size; + if ( i == (h.numRecords-1) ) + size = qlsize(li); + else + size = re[i+1].ulOffset; + if ( size < re[i].ulOffset ) + loader_failure("Invalid file structure"); + size -= re[i].ulOffset; + ea_t ea1 = (inf_get_max_ea() + 0xF) & ~0xF; + ea_t ea2 = ea1 + size; + + char segname[10]; + qsnprintf(segname, sizeof(segname), "%4.4s%04X", (char*)&re[i].fcType, re[i].id); + const char *sclass = "RSC"; + + if ( armCode ) + { + // load only ARM segments in ARM mode + if ( re[i].fcType != PILOT_RSC_ARMC && re[i].fcType != PILOT_RSC_ARMCL ) + continue; + + bool bCodeWarrior = isCWseg(li, re[i].ulOffset); + + ea_t start_ea=ea1; + file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE); + int sel = i+1; + if ( bCodeWarrior && !manualMode ) + { + // load all sequential chunks as one segment + while ( i < h.numRecords-1 && re[i].fcType == re[i+1].fcType && re[i].id + 1 == re[i+1].id && !isCWseg(li, re[i+1].ulOffset) ) + { + i++; + if ( i == (h.numRecords-1) ) + size = qlsize(li); + else + size = re[i+1].ulOffset; + if ( size < re[i].ulOffset ) + loader_failure("Invalid file structure"); + size -= re[i].ulOffset; + ea1 = ea2; // TODO: check if pnoloader.c does alignment + ea2 = ea1 + size; + file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE); + } + } + set_selector(sel, start_ea >> 4); + if ( !add_segm(sel, start_ea, ea2, segname, CLASS_CODE, ADDSEG_SPARSE) ) + loader_failure(); + + // set DS for the segment to itself + set_default_sreg_value(get_segm_by_sel(sel), str2reg("DS"), sel); + if ( bCodeWarrior ) + fixArmCW(start_ea, ea2); + continue; + } + + if ( re[i].fcType == PILOT_RSC_CODE ) + { + if ( re[i].id == 0 && !manualMode ) + continue; // skip code0000 resource + sclass = CLASS_CODE; + if ( re[i].id == 1 ) + { + inf_set_start_cs(i + 1); + inf_set_start_ip(0); + code1ea = ea1; + } + } + else if ( re[i].fcType == PILOT_RSC_LIBR || re[i].fcType == PILOT_RSC_GLIB ) + { + sclass = CLASS_CODE; + if ( re[i].id == 0 ) + { + inf_set_start_cs(i + 1); + inf_set_start_ip(0); + code1ea = ea1; + } + } + + // check if we need to decompress stuff + if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 0 ) + { + sclass = CLASS_DATA; + dgroup = i + 1; + size_t usize = unpack_data0000(li, re[i].ulOffset, size, ea1, code0000, code1ea, a5); + ea2 = ea1 + usize; + datastart = ea1; + } + else if ( re[i].fcType == PILOT_RSC_DATA && re[i].id == 1 && !manualMode ) + { + sclass = CLASS_DATA; + size_t usize = unpack_data0001(li, re[i].ulOffset, size, ea1, a5, code1ea, a4); + ea2 = ea1 + usize; + } + else + { + // otherwise just load it as-is + file2base(li, re[i].ulOffset, ea1, ea2, FILEREG_PATCHABLE); + } + + { + segment_t s; + s.start_ea = ea1; + s.end_ea = ea2; + s.sel = i+1; + s.bitness = 1; // 32bit + set_selector(i+1, ea1 >> 4); + if ( !add_segm_ex(&s, segname, sclass, ADDSEG_FILLGAP|ADDSEG_OR_DIE|ADDSEG_SPARSE) ) + loader_failure(); + } + } + + if ( !manualMode && !armCode ) + { + // check if first dword is 1; if so, skip it + if ( get_dword(code1ea) == 1 ) + { + // codewarrior startup + static const uchar pattern[] = + { + 0x00, 0x00, 0x00, 0x01, // dc.l 1 + 0x48, 0x7A, 0x00, 0x04, // pea $A + 0x06, 0x97, 0xFF, 0xFF, 0xFF, 0xFF, // addi.l #(__Startup__-$A),(sp) + 0x4E, 0x75, // rts + }; + if ( equal_bytes(code1ea, pattern, SKIP_FF_MASK, sizeof(pattern), true) ) + { + plan_to_apply_idasgn("cwpalm.sig"); + } + create_dword(code1ea, 4); + inf_set_start_ip(4); + } + // is main code segment GLib? + if ( inf_get_start_cs() > 0 + && re[int(inf_get_start_cs()-1)].fcType == PILOT_RSC_GLIB + && a4 == BADADDR + && datastart != BADADDR ) + { + // GLib's a4 points at the start of data segment + a4 = datastart; + create_byte(a4, 1); + set_name(a4, "A4BASE", SN_NOCHECK|SN_AUTO); + set_cmt(a4, "A4 points here", 0); + } + // check for CodeWarrior's jumptables in additional code segments and fix them up + for ( i=0; i < h.numRecords; i++ ) + { + if ( re[i].fcType == PILOT_RSC_CODE && re[i].id > 1 ) + { + segment_t *seg = get_segm_by_sel(i+1); + if ( seg != NULL ) + fix_jumptables(seg->start_ea, seg->end_ea, i+1, a5, a4); + } + } + // TODO: handle prc-tools and multilink's 'rloc' segments + } + + if ( dgroup != BADSEL ) + set_default_dataseg(dgroup); // input: selector + describe_all(h); + exec_system_script("pilot.idc"); +} + +//-------------------------------------------------------------------------- +// it is impossible to use ph.id, +// the processor module is not loaded yet +inline bool is_arm_specified(void) +{ + return strnieq(inf_get_procname().c_str(), "ARM", 3); +} + +inline bool is_68k_specified(void) +{ + char pname[IDAINFO_PROCNAME_SIZE]; + inf_get_procname(pname, sizeof(pname)); + return strnieq(pname, "68K", 3) + || strnieq(pname, "68000", 5) + || strnieq(pname, "68010", 5) + || strnieq(pname, "68020", 5) + || strnieq(pname, "68030", 5) + || strnieq(pname, "68040", 5) + || strnieq(pname, "68330", 5) + || strnieq(pname, "68882", 5) + || strnieq(pname, "68851", 5) + || strnieq(pname, "ColdFire", 8); +} + +//-------------------------------------------------------------------------- +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + static int n = 0; + int k = is_prc_file(li); + if ( k == 0 ) + return 0; + int ftype = 0; + if ( n == 1 ) + { + if ( k == 2 ) // has ARM segments? + { + *fileformatname = PRC_ARM; + *processor = "ARM"; + ftype = f_PRC; + if ( is_arm_specified() ) + ftype |= ACCEPT_FIRST; + } + } + else + { + n++; + *fileformatname = PRC_68K; + *processor = "68K"; + ftype = f_PRC|ACCEPT_CONTINUE; + if ( is_68k_specified() ) + ftype |= ACCEPT_FIRST; + } + return ftype; +} + +//-------------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk76/ldr/pilot/pilot.hpp b/idasdk76/ldr/pilot/pilot.hpp new file mode 100644 index 0000000..66c7f47 --- /dev/null +++ b/idasdk76/ldr/pilot/pilot.hpp @@ -0,0 +1,148 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + */ + +#ifndef __PILOT_H +#define __PILOT_H +#pragma pack(push, 1) + +#include <time.h> + +#define PRC_68K "PalmPilot program file (68K)" +#define PRC_ARM "PalmPilot program file (ARM)" + +// Regular resources: + +#define PILOT_RSC_CODE 0x65646F63L // "code\0\0\0\1" program code +#define PILOT_RSC_PREF 0x66657270L // "pref\0\0\0\0" preferences (not used yet) +#define PILOT_RSC_DATA 0x61746164L // "data\0\0\0\0" image of global data +#define PILOT_RSC_LIBR 0x7262696CL // "libr" SysLib-type shared library code +#define PILOT_RSC_GLIB 0x62694C47L // "GLib" PRC-Tools GLib-type shared library code +#define PILOT_RSC_RLOC 0x636F6C72L // "rloc" PRC-Tools and Multilink relocations +#define PILOT_RSC_ARMC 0x434D5241L // "ARMC" ARM native code +#define PILOT_RSC_ARMCL 0x636D7261L // "armc" ARM native code + +// UI resources: + +#define PILOT_RSC_MBAR 0x5241424DL // "MBAR" Menu bar +#define PILOT_RSC_MENU 0x554E454DL // "MENU" Menu options +#define PILOT_RSC_ICON 0x4E494174L // "tAIN" Application icon name +#define PILOT_RSC_AIB 0x42494174L // "tAIB" Application icon bitmap +#define PILOT_RSC_AIS 0x53494174L // "tAIS" Application information string +#define PILOT_RSC_ALERT 0x746C6154L // "Talt" Alert +#define PILOT_RSC_BITMAP 0x706D6254L // "Tbmp" Bitmap +#define PILOT_RSC_BUTTON 0x4E544274L // "tBTN" Button +#define PILOT_RSC_CHECK 0x58424374L // "tCBX" Check box +#define PILOT_RSC_FBM 0x4D424674L // "tFBM" Form bitmap +#define PILOT_RSC_FIELD 0x444C4674L // "tFLD" Field +#define PILOT_RSC_FORM 0x4D524674L // "tFRM" Form +#define PILOT_RSC_GADGET 0x54444774L // "tGDT" Gadget +#define PILOT_RSC_GRAFF 0x49534774L // "tGSI" Graffiti Shift +#define PILOT_RSC_LABEL 0x4C424C74L // "tLBL" Label +#define PILOT_RSC_LIST 0x54534C74L // "tLST" List box +#define PILOT_RSC_PUSH 0x4E425074L // "tPBN" Push button +#define PILOT_RSC_POPUPL 0x4C555074L // "tPUL" Popup list +#define PILOT_RSC_POPUPT 0x54555074L // "tPUT" Popup trigger +#define PILOT_RSC_REPEAT 0x50455274L // "tREP" Repeating control +#define PILOT_RSC_SELECT 0x544C5374L // "tSLT" Selector trigger +#define PILOT_RSC_STRING 0x52545374L // "tSTR" String +#define PILOT_RSC_TABLE 0x4C425474L // "tTBL" Table +#define PILOT_RSC_TITLE 0x4C545474L // "tTTL" Title +#define PILOT_RSC_VER 0x72657674L // "tver" Version number string + + +typedef uchar Byte; +typedef ushort Word; +typedef uint32 DWord; +typedef DWord LocalID; + +// +// Header of PRC file: +// + +struct DatabaseHdrType +{ + Byte name[32]; // name of database +#define PILOT_CREATOR_PILA 0x616C6950L // "Pila" + Word attributes; // database attributes +#define dmHdrAttrResDB 0x0001 // Resource database +#define dmHdrAttrReadOnly 0x0002 // Read Only database +#define dmHdrAttrAppInfoDirty 0x0004 // Set if Application Info block is dirty + // Optionally supported by an App's conduit +#define dmHdrAttrBackup 0x0008 // Set if database should be backed up to PC if + // no app-specific synchronization conduit has + // been supplied. +#define dmHdrAttrOpen 0x8000 // Database not closed properly + Word version; // version of database + DWord creationDate; // creation date of database + DWord modificationDate; // latest modification date + DWord lastBackupDate; // latest backup date + DWord modificationNumber; // modification number of database + LocalID appInfoID; // application specific info + LocalID sortInfoID; // app specific sorting info + DWord type; // database type +#define PILOT_TYPE_APPL 0x6C707061L // "appl" + DWord id; // program id + DWord uniqueIDSeed; // used to generate unique IDs. + // Note that only the low order + // 3 bytes of this is used (in + // RecordEntryType.uniqueID). + // We are keeping 4 bytes for + // alignment purposes. + LocalID nextRecordListID; // local chunkID of next list + Word numRecords; // number of records in this list +}; + +// +// Each resource has the following entry: +// +struct ResourceMapEntry +{ + uint32 fcType; + ushort id; + uint32 ulOffset; +}; + + +// Pilot bitmap format (also format of icon) +struct pilot_bitmap_t +{ + ushort cx; + ushort cy; + ushort cbRow; + ushort ff; + ushort ausUnk[4]; +}; + + +/* + * code0000[long 0] nBytesAboveA5 + * code0000[long 1] nBytesBelowA5 + */ +struct code0000_t +{ + uint32 nBytesAboveA5; + uint32 nBytesBelowA5; +}; + +// pref0000 + +struct pref0000_t +{ + ushort flags; +#define sysAppLaunchFlagNewThread 0x0001 +#define sysAppLaunchFlagNewStack 0x0002 +#define sysAppLaunchFlagNewGlobals 0x0004 +#define sysAppLaunchFlagUIApp 0x0008 +#define sysAppLaunchFlagSubCall 0x0010 + uint32 stack_size; + uint32 heap_size; +}; + +#pragma pack(pop) +#endif // __PILOT_H diff --git a/idasdk75/ldr/pilot/pilot.idc b/idasdk76/ldr/pilot/pilot.idc similarity index 100% rename from idasdk75/ldr/pilot/pilot.idc rename to idasdk76/ldr/pilot/pilot.idc diff --git a/idasdk75/ldr/qnx/lmf.h b/idasdk76/ldr/qnx/lmf.h similarity index 100% rename from idasdk75/ldr/qnx/lmf.h rename to idasdk76/ldr/qnx/lmf.h diff --git a/idasdk76/ldr/qnx/makefile b/idasdk76/ldr/qnx/makefile new file mode 100644 index 0000000..8656fac --- /dev/null +++ b/idasdk76/ldr/qnx/makefile @@ -0,0 +1,13 @@ +PROC=qnx + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)qnx$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h lmf.h qnx.cpp diff --git a/idasdk75/ldr/qnx/qnx.cpp b/idasdk76/ldr/qnx/qnx.cpp similarity index 100% rename from idasdk75/ldr/qnx/qnx.cpp rename to idasdk76/ldr/qnx/qnx.cpp diff --git a/idasdk75/ldr/readme.txt b/idasdk76/ldr/readme.txt similarity index 100% rename from idasdk75/ldr/readme.txt rename to idasdk76/ldr/readme.txt diff --git a/idasdk76/ldr/rt11/makefile b/idasdk76/ldr/rt11/makefile new file mode 100644 index 0000000..d7295e0 --- /dev/null +++ b/idasdk76/ldr/rt11/makefile @@ -0,0 +1,14 @@ +PROC=rt11 + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)rt11$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../../module/pdp11/pdp_ml.h ../idaldr.h \ + rt11.cpp diff --git a/idasdk75/ldr/rt11/rt11.cpp b/idasdk76/ldr/rt11/rt11.cpp similarity index 100% rename from idasdk75/ldr/rt11/rt11.cpp rename to idasdk76/ldr/rt11/rt11.cpp diff --git a/idasdk75/ldr/script_ldrs/archldr_tar.py b/idasdk76/ldr/script_ldrs/archldr_tar.py similarity index 100% rename from idasdk75/ldr/script_ldrs/archldr_tar.py rename to idasdk76/ldr/script_ldrs/archldr_tar.py diff --git a/idasdk75/ldr/script_ldrs/bios_image.idc b/idasdk76/ldr/script_ldrs/bios_image.idc similarity index 100% rename from idasdk75/ldr/script_ldrs/bios_image.idc rename to idasdk76/ldr/script_ldrs/bios_image.idc diff --git a/idasdk75/ldr/script_ldrs/bios_image.py b/idasdk76/ldr/script_ldrs/bios_image.py similarity index 100% rename from idasdk75/ldr/script_ldrs/bios_image.py rename to idasdk76/ldr/script_ldrs/bios_image.py diff --git a/idasdk75/ldr/script_ldrs/hppacore.idc b/idasdk76/ldr/script_ldrs/hppacore.idc similarity index 100% rename from idasdk75/ldr/script_ldrs/hppacore.idc rename to idasdk76/ldr/script_ldrs/hppacore.idc diff --git a/idasdk75/ldr/script_ldrs/makefile b/idasdk76/ldr/script_ldrs/makefile similarity index 100% rename from idasdk75/ldr/script_ldrs/makefile rename to idasdk76/ldr/script_ldrs/makefile diff --git a/idasdk76/ldr/script_ldrs/pdfldr.py b/idasdk76/ldr/script_ldrs/pdfldr.py new file mode 100644 index 0000000..d8aa0df --- /dev/null +++ b/idasdk76/ldr/script_ldrs/pdfldr.py @@ -0,0 +1,319 @@ +""" +A script that extracts shellcode from PDF files + +The script uses very basic shellcode extraction algorithm + +Copyright (c) 1990-2021 Hex-Rays +ALL RIGHTS RESERVED. + +Revision history +========================= +v1.0 - initial version + + +Possible enhancements: +========================= +1. From Didier: +----------------- +FYI: the regex you use to match /JavaScript /JS will fail to match +name obfuscation. Name obuscation use a feature of the PDF language +that allows a character in a name (like /JavaScript) to be replaced +with its hexcode. Example: /#4AavaScript +http://blog.didierstevens.com/2008/04/29/pdf-let-me-count-the-ways/ + +It's something that's used in-the-wild. + +I've updated your regex to support name obfuscation. The JavaScript +itself is now captured in group 13. + +\/S\s*\/(J|#4A|#4a)(a|#61)(v|#76)(a|#61)(S|#53)(c|#63)(r|#72)(i|#69)(p|#70)(t|#74)\s*\/(J|#4A|#4a)(S|#53) +\((.+?)>> + +2. +--------------- + +""" + +import sys +import re +import zlib + +SAMPLE1 = 'malware1.pdf.vir' +SAMPLE2 = 'heapspray-simpler-calc.pdf.vir' + +try: + import idaapi + import idc + import ida_idp + ida = True +except: + ida = False + +# ----------------------------------------------------------------------- +# Tries to find shellcode inside JavaScript statements +# The seach algorithm is simple: it searchs for anything between unescape() +# if it encounters %u or %x it correctly decodes them to characters +def extract_shellcode(lines): + p = 0 + shellcode = [] # accumulate shellcode + while True: + p = lines.find(b'unescape("', p) + if p == -1: + break + e = lines.find(b')', p) + if e == -1: + break + expr = lines[p+9:e] + data = [] + def put_byte(b): + if sys.version_info.major >= 3: + data.append(b) + else: + data.append(chr(b)) + + for i in range(0, len(expr)): + if expr[i:i+2] == b"%u": + i += 2 + put_byte(int(expr[i+2:i+4], 16)) + put_byte(int(expr[i:i+2], 16)) + i += 4 + elif expr[i] == b"%": + i += 1 + put_byte(int(expr[i:i+2], 16)) + i += 2 + # advance the match pos + p += 8 + if sys.version_info.major >= 3: + shellcode.append(bytes(data)) + else: + shellcode.append("".join(data)) + + # That's it + return shellcode + +# ----------------------------------------------------------------------- +# Given a PDF object id and version, we return the object declaration +def find_obj(buf, id, ver): + stream = re.search(b'%d %d obj(.*?)endobj' % (id, ver), buf, re.MULTILINE | re.DOTALL) + if not stream: + return None + return buf[stream.start(1):stream.end(1)] + +# ----------------------------------------------------------------------- +# Find JavaScript objects and extract the referenced script object id/ver +def find_js_ref_streams(buf): + o = [] + js_ref_streams = re.finditer(r'\/S\s*\/JavaScript\/JS (\d+) (\d+) R'.encode("UTF-8"), buf) + for g in js_ref_streams: + id = int(g.group(1)) + ver = int(g.group(2)) + o.append([id, ver]) + return o + +# ----------------------------------------------------------------------- +# Find JavaScript objects and extract the embedded script +def find_embedded_js(buf): + r = re.finditer(r'\/S\s*\/JavaScript\s*\/JS \((.+?)>>'.encode("UTF-8"), buf, re.MULTILINE | re.DOTALL) + if not r: + return None + + ret = [] + for js in r: + p = buf.rfind(b'obj', 0, js.start(1)) + if p == -1: + return None + + scs = extract_shellcode(js.group(1)) + if not scs: + return None + + t = buf[p - min(20, len(buf)): p + 3] + obj = re.search('(\d+) (\d+) obj'.encode("UTF-8"), t) + if not obj: + id, ver = 0 + else: + id = int(obj.group(1)) + ver = int(obj.group(2)) + n = 0 + for sc in scs: + n += 1 + ret.append([id, ver, n, sc]) + return ret + +# ----------------------------------------------------------------------- +# Given a gzipped stream object, it returns the decompressed contents +def decompress_stream(buf): + if buf.find(b'Filter[/FlateDecode]') == -1: + return None + m = re.search(b'stream\s*(.+?)\s*endstream', buf, re.DOTALL | re.MULTILINE) + if not m: + return None + # Decompress and return + return zlib.decompress(m.group(1)) + + +# ----------------------------------------------------------------------- +def read_whole_file(li): + li.seek(0) + return li.read(li.size()) + +# ----------------------------------------------------------------------- +def extract_pdf_shellcode(buf): + ret = [] + + # find all JS stream references + r = find_js_ref_streams(buf) + for id, ver in r: + # extract the JS stream object + obj = find_obj(buf, id, ver) + + # decode the stream + stream = decompress_stream(obj) + + # extract shell code + scs = extract_shellcode(stream) + i = 0 + for sc in scs: + i += 1 + ret.append([id, ver, i, sc]) + + # find all embedded JS + r = find_embedded_js(buf) + if r: + ret.extend(r) + + return ret + +# ----------------------------------------------------------------------- +def accept_file(li, filename): + """ + Check if the file is of supported format + + @param li: a file-like object which can be used to access the input data + @param filename: name of the file, if it is an archive member name then the actual file doesn't exist + @return: 0 - no more supported formats + string "name" - format name to display in the chooser dialog + dictionary { 'format': "name", 'options': integer } + options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000) + to indicate preferred format + """ + + # we support only one format per file + li.seek(0) + if li.read(5) != b'%PDF-': + return 0 + + buf = read_whole_file(li) + r = extract_pdf_shellcode(buf) + if not r: + return 0 + + return {'format': 'PDF with shellcode', 'processor': 'metapc'} + +# ----------------------------------------------------------------------- +def load_file(li, neflags, format): + + """ + Load the file into database + + @param li: a file-like object which can be used to access the input data + @param neflags: options selected by the user, see loader.hpp + @return: 0-failure, 1-ok + """ + + # Select the PC processor module + idaapi.set_processor_type("metapc", ida_idp.SETPROC_LOADER) + + buf = read_whole_file(li) + r = extract_pdf_shellcode(buf) + if not r: + return 0 + + # Load all shellcode into different segments + start = 0x10000 + seg = idaapi.segment_t() + for id, ver, n, sc in r: + size = len(sc) + end = start + size + + # Create the segment + seg.start_ea = start + seg.end_ea = end + seg.bitness = 1 # 32-bit + idaapi.add_segm_ex(seg, "obj_%d_%d_%d" % (id, ver, n), "CODE", 0) + + # Copy the bytes + idaapi.mem2base(sc, start, end) + + # Mark for analysis + idc.AutoMark(start, idc.AU_CODE) + + # Compute next loading address + start = ((end // 0x1000) + 1) * 0x1000 + + # Select the bochs debugger + idc.load_debugger("bochs", 0) + + return 1 + +# ----------------------------------------------------------------------- +def test1(sample = SAMPLE1): + # open the file + f = file(sample, 'rb') + buf = f.read() + f.close() + + # find all JS stream references + r = find_js_ref_streams(buf) + if not r: + return + + for id, ver in r: + obj = find_obj(buf, id, ver) + + # extract the JS stream object + f = file('obj_%d_%d.bin' % (id, ver), 'wb') + f.write(obj) + f.close() + + # decode the stream + stream = decompress_stream(obj) + f = file('dec_%d_%d.bin' % (id, ver), 'wb') + f.write(stream) + f.close() + + # extract shell code + scs = extract_shellcode(stream) + i = 0 + for sc in scs: + i += 1 + f = file('sh_%d_%d_%d.bin' % (id, ver, i), 'wb') + f.write(sc) + f.close() + +# ----------------------------------------------------------------------- +def test2(sample = SAMPLE1): + # open the file + f = file(sample, 'rb') + buf = f.read() + f.close() + + r = extract_pdf_shellcode(buf) + for id, ver, n, sc in r: + print("sc %d.%d[%d]=%d" % (id, ver, n, len(sc))) + +# ----------------------------------------------------------------------- +def test3(sample = SAMPLE2): + # open the file + f = file(sample, 'rb') + buf = f.read() + f.close() + t = find_embedded_js(buf) + print(t) + +# ----------------------------------------------------------------------- +def main(): + test1(SAMPLE1) + +if not ida: + main() diff --git a/idasdk76/ldr/script_ldrs/uimage.py b/idasdk76/ldr/script_ldrs/uimage.py new file mode 100644 index 0000000..da569d1 --- /dev/null +++ b/idasdk76/ldr/script_ldrs/uimage.py @@ -0,0 +1,218 @@ +# a file loader for U-Boot "uImage" flash images +# Copyright (c) 2011-2021 Hex-Rays +# ALL RIGHTS RESERVED. + +import idaapi +import idc +import zlib +import ida_idp +import ida_typeinf + +IH_TYPE_INVALID = 0 # /* Invalid Image */ +IH_TYPE_STANDALONE = 1 # /* Standalone Program */ +IH_TYPE_KERNEL = 2 # /* OS Kernel Image */ +IH_TYPE_RAMDISK = 3 # /* RAMDisk Image */ +IH_TYPE_MULTI = 4 # /* Multi-File Image */ +IH_TYPE_FIRMWARE = 5 # /* Firmware Image */ +IH_TYPE_SCRIPT = 6 # /* Script file */ +IH_TYPE_FILESYSTEM = 7 # /* Filesystem Image (any type) */ + +ImageTypeNames = [ "Invalid", "Standalone Program", "OS Kernel", "RAMDisk", + "Multi-File", "Firmware", "Script file", "Filesystem" ] + +IH_ARCH_INVALID = 0 # /* Invalid CPU */ +IH_ARCH_ALPHA = 1 # /* Alpha */ +IH_ARCH_ARM = 2 # /* ARM */ +IH_ARCH_I386 = 3 # /* Intel x86 */ +IH_ARCH_IA64 = 4 # /* IA64 */ +IH_ARCH_MIPS = 5 # /* MIPS */ +IH_ARCH_MIPS64 = 6 # /* MIPS 64 Bit */ +IH_ARCH_PPC = 7 # /* PowerPC */ +IH_ARCH_S390 = 8 # /* IBM S390 */ +IH_ARCH_SH = 9 # /* SuperH */ +IH_ARCH_SPARC = 10 # /* Sparc */ +IH_ARCH_SPARC64 = 11 # /* Sparc 64 Bit */ +IH_ARCH_M68K = 12 # /* M68K */ +IH_ARCH_NIOS = 13 # /* Nios-32 */ +IH_ARCH_MICROBLAZE = 14 # /* MicroBlaze */ +IH_ARCH_NIOS2 = 15 # /* Nios-II */ +IH_ARCH_BLACKFIN = 16 # /* */ +IH_ARCH_AVR32 = 17 # /* */ +IH_ARCH_ST200 = 18 # /* */ +IH_ARCH_SANDBOX = 19 # /* */ +IH_ARCH_NDS32 = 20 # /* */ +IH_ARCH_OPENRISC = 21 # /* */ +IH_ARCH_ARM64 = 22 # /* */ +IH_ARCH_ARC = 23 # /* */ + +CPUNames = [ "Invalid", "Alpha", "ARM", "x86", "IA64", "MIPS", "MIPS64", "PowerPC", + "IBM S390", "SuperH", "Sparc", "Sparc64", "M68K", "Nios-32", "MicroBlaze", "Nios-II", + "Blackfin", "AVR32", "ST200","Sandbox","NDS32", "OpenRISC", "ARM64", "ARC" ] + +IDACPUNames = { IH_ARCH_ALPHA: "alphab", + IH_ARCH_ARM:"ARM", + IH_ARCH_I386: "metapc", + IH_ARCH_IA64: "ia64b", + IH_ARCH_MIPS:"mipsl", + IH_ARCH_MIPS64:"mipsl", + IH_ARCH_PPC: "ppc", + IH_ARCH_SH: "SH4", + IH_ARCH_SPARC: "sparcb", + IH_ARCH_SPARC64:"sparcb", + IH_ARCH_M68K:"68K", + IH_ARCH_ARM64:"ARM", + IH_ARCH_ARC: "arcmpct" } + +IDAABINames = { IH_ARCH_MIPS:"n32", + IH_ARCH_MIPS64:"n64" } + +IH_COMP_NONE = 0 # /* No Compression Used */ +IH_COMP_GZIP = 1 # /* gzip Compression Used */ +IH_COMP_BZIP2 = 2 # /* bzip2 Compression Used */ +IH_COMP_LZMA = 3 # /* lzma Compression Used */ +IH_COMP_LZO = 4 # /* lzo Compression Used */ +CompTypeNames = [ "", "gzip", "bzip2", "lzma", "lzo" ] + +IH_MAGIC = 0x27051956 # Image Magic Number +IH_NMLEN = 32 # Image Name Length + +import ctypes + +uint8_t = ctypes.c_byte +uint32_t = ctypes.c_uint + +class image_header(ctypes.BigEndianStructure): + _fields_ = [ + ("ih_magic", uint32_t), # Image Header Magic Number + ("ih_hcrc", uint32_t), # Image Header CRC Checksum + ("ih_time", uint32_t), # Image Creation Timestamp + ("ih_size", uint32_t), # Image Data Size + ("ih_load", uint32_t), # Data Load Address + ("ih_ep", uint32_t), # Entry Point Address + ("ih_dcrc", uint32_t), # Image Data CRC Checksum + ("ih_os", uint8_t), # Operating System + ("ih_arch", uint8_t), # CPU architecture + ("ih_type", uint8_t), # Image Type + ("ih_comp", uint8_t), # Compression Type + ("ih_name", uint8_t * IH_NMLEN), # Image Name + ] +RomFormatName = "U-Boot image" + +# ----------------------------------------------------------------------- +def dwordAt(li, off): + li.seek(off) + s = li.read(4) + if len(s) < 4: + return 0 + return struct.unpack('<I', s)[0] + +def read_struct(li, struct): + s = struct() + s.ih_magic = 0 + slen = ctypes.sizeof(s) + if li.size() >= slen: + bytes = li.read(slen) + fit = min(len(bytes), slen) + ctypes.memmove(ctypes.addressof(s), bytes, fit) + return s + +# ----------------------------------------------------------------------- +def accept_file(li, filename): + """ + Check if the file is of supported format + + @param li: a file-like object which can be used to access the input data + @param filename: name of the file, if it is an archive member name then the actual file doesn't exist + @return: 0 - no more supported formats + string "name" - format name to display in the chooser dialog + dictionary { 'format': "name", 'options': integer } + options: should be 1, possibly ORed with ACCEPT_FIRST (0x8000) + to indicate preferred format + """ + + header = read_struct(li, image_header) + # check the signature + if header.ih_magic == IH_MAGIC: + # accept the file + t = header.ih_type + c = header.ih_arch + if t >= len(ImageTypeNames): + t = "unknown type(%d)" % t + else: + t = ImageTypeNames[t] + + if c >= len(CPUNames): + cname = "unknown CPU(%d)" % c + else: + cname = CPUNames[c] + + fmt = "%s (%s for %s)" % (RomFormatName, t, cname) + comp = header.ih_comp + if comp != IH_COMP_NONE: + if comp >= len (CompTypeNames): + cmpname = "unknown compression(%d)" + else: + cmpname = "%s compressed" % CompTypeNames[comp] + fmt += " [%s]" % cmpname + + proc = '' + if c in IDACPUNames: + proc = IDACPUNames[c] + + return {'format': fmt, 'processor': proc} + + # unrecognized format + return 0 + +# ----------------------------------------------------------------------- +def load_file(li, neflags, format): + + """ + Load the file into database + + @param li: a file-like object which can be used to access the input data + @param neflags: options selected by the user, see loader.hpp + @return: 0-failure, 1-ok + """ + + if format.startswith(RomFormatName): + li.seek(0) + header = read_struct(li, image_header) + c = header.ih_arch + cname = IDACPUNames.get(c) + if not cname: + idc.warning("Unsupported CPU") + #return + + if not header.ih_comp in (IH_COMP_NONE, IH_COMP_GZIP): + idc.warning("Can only handle uncompressed or gzip-compressed images") + return + + if cname: + idaapi.set_processor_type(cname, ida_idp.SETPROC_LOADER) + + idc.AddSeg(header.ih_load, header.ih_load + header.ih_size, 0, 1, idaapi.saRelPara, idaapi.scPub) + + # copy bytes to the database + + if header.ih_comp == IH_COMP_NONE: + li.file2base(ctypes.sizeof(header), header.ih_load, header.ih_load + header.ih_size, 0) + else: + cdata = li.read(header.ih_size) + d = zlib.decompressobj(zlib.MAX_WBITS|32) + udata = d.decompress(cdata) + udata += d.flush() + # expand segment to fit uncompressed data + idc.set_segment_bounds(header.ih_load, header.ih_load, header.ih_load+len(udata), idc.SEGMOD_KEEP) + idaapi.put_bytes(header.ih_load, udata) + + if cname == "ARM" and (header.ih_ep & 1) != 0: + # Thumb entry point + header.ih_ep -= 1 + split_sreg_range(header.ih_ep, "T", 1) + idaapi.add_entry(header.ih_ep, header.ih_ep, "start", 1) + aname = IDAABINames.get(header.ih_arch) + if aname: + ida_typeinf.set_abi_name(aname) + print("Load OK") + return 1 diff --git a/idasdk75/ldr/script_ldrs/wince.py b/idasdk76/ldr/script_ldrs/wince.py similarity index 100% rename from idasdk75/ldr/script_ldrs/wince.py rename to idasdk76/ldr/script_ldrs/wince.py diff --git a/idasdk75/ldr/snes/addr.cpp b/idasdk76/ldr/snes/addr.cpp similarity index 100% rename from idasdk75/ldr/snes/addr.cpp rename to idasdk76/ldr/snes/addr.cpp diff --git a/idasdk76/ldr/snes/makefile b/idasdk76/ldr/snes/makefile new file mode 100644 index 0000000..5037a81 --- /dev/null +++ b/idasdk76/ldr/snes/makefile @@ -0,0 +1,14 @@ +PROC=snes + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)snes$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp \ + $(I)xref.hpp ../idaldr.h addr.cpp snes.cpp \ + super-famicom.hpp diff --git a/idasdk76/ldr/snes/snes.cpp b/idasdk76/ldr/snes/snes.cpp new file mode 100644 index 0000000..ae4c4e4 --- /dev/null +++ b/idasdk76/ldr/snes/snes.cpp @@ -0,0 +1,716 @@ + +#include "../idaldr.h" +#include "addr.cpp" + +//---------------------------------------------------------------------------- +static void map_io_seg(ea_t start, ea_t end, const char *const name) +{ + segment_t s; + s.start_ea = start; + s.end_ea = end; + s.type = SEG_IMEM; + s.sel = allocate_selector(start >> 4); + if ( !add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", name); +} + + +//---------------------------------------------------------------------------- +static void map_hwregs() +{ + map_io_seg(0x2100, 0x2140, "ppu"); + map_io_seg(0x2140, 0x2144, "apu"); + map_io_seg(0x2180, 0x2184, "wramrw"); + map_io_seg(0x4016, 0x4018, "joypad"); + map_io_seg(0x4200, 0x4220, "misc"); + map_io_seg(0x4300, 0x4380, "dma"); +} + + +//---------------------------------------------------------------------------- +static void map_wram() +{ + segment_t s; + s.start_ea = 0x7e0000; + s.end_ea = 0x800000; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), "wram"); + if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); +} + +//---------------------------------------------------------------------------- +static void map_lorom_sram_offset(uint32 ram_size, uint8 start_bank) +{ + // Usually, the lower half of bank (0x8000 bytes) is SRAM, and the upper half is ROM mirror. + // However, some cartridges maps the whole of bank (0x10000 bytes) to SRAM. + // In that case, the upper half is probably mirrored as same as the lower half. + + // create ram banks + const uint32 bank_size = 0x8000; + uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; + for ( uint32 mapped = 0, bank = start_bank; mapped < ram_chunks; bank++, mapped++ ) + { + if ( bank == 0x7e ) + bank = 0xfe; + + segment_t s; + s.start_ea = uint32(bank << 16); + s.end_ea = s.start_ea + bank_size; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); + if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); + } +} + +//---------------------------------------------------------------------------- +static void map_hirom_sram_offset(uint32 ram_size, uint8 start_bank) +{ + // create ram banks + const uint32 bank_size = 0x2000; + uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; + for ( uint32 mapped = 0, bank = start_bank; mapped < ram_chunks; bank++, mapped++ ) + { + segment_t s; + s.start_ea = uint32((bank << 16) + 0x6000); + s.end_ea = s.start_ea + bank_size; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); + if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); + } +} + +//---------------------------------------------------------------------------- +static void map_lorom_sram(uint32 ram_size) +{ + // create ram banks 70-7d (and fe-ff) + map_lorom_sram_offset(ram_size, 0x70); +} + +//---------------------------------------------------------------------------- +static void map_hirom_sram(uint32 ram_size) +{ + // create ram banks 20-3f + map_hirom_sram_offset(ram_size, 0x20); +} + +//---------------------------------------------------------------------------- +static void map_superfx_sram(uint32 ram_size) +{ + // create ram banks 70-71 + const uint32 bank_size = 0x10000; + uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; + for ( uint32 mapped = 0, bank = 0x70; mapped < ram_chunks; bank++, mapped++ ) + { + segment_t s; + s.start_ea = uint32(bank << 16); + s.end_ea = s.start_ea + bank_size; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); + if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); + } +} + +//---------------------------------------------------------------------------- +static void map_superfx_workram() +{ + segment_t s; + s.start_ea = 0x6000; + s.end_ea = 0x8000; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), "sfxram"); + if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); +} + +//---------------------------------------------------------------------------- +static void map_superfx_hwregs() +{ + map_io_seg(0x3000, 0x3500, "superfx"); +} + +//---------------------------------------------------------------------------- +static void map_sa1_bwram(uint32 ram_size) +{ + // create ram banks 40-41 + const uint32 bank_size = 0x10000; + uint32 ram_chunks = (ram_size + bank_size - 1) / bank_size; + for ( uint32 mapped = 0, bank = 0x40; mapped < ram_chunks; bank++, mapped++ ) + { + segment_t s; + s.start_ea = uint32(bank << 16); + s.end_ea = s.start_ea + bank_size; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); + if ( !add_segm_ex(&s, seg_name, "BANK_RAM", ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); + } +} + +//---------------------------------------------------------------------------- +static void map_sa1_iram() +{ + segment_t s; + s.start_ea = 0x3000; + s.end_ea = 0x3800; + s.type = SEG_IMEM; + s.sel = allocate_selector(s.start_ea >> 4); + + char seg_name[0x10]; + qsnprintf(seg_name, sizeof(seg_name), "iram"); + if ( !add_segm_ex(&s, seg_name, NULL, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure("Failed adding %s segment\n", seg_name); +} + +//---------------------------------------------------------------------------- +static void map_sa1_hwregs() +{ + map_io_seg(0x2200, 0x2400, "sa1"); +} + +//---------------------------------------------------------------------------- +static void map_cx4_hwregs() +{ + map_io_seg(0x6000, 0x8000, "cx4"); +} + +//---------------------------------------------------------------------------- +static void map_spc7110_hwregs() +{ + map_io_seg(0x4800, 0x4840, "spc7110"); + map_io_seg(0x500000, 0x600000, "decomprom"); +} + +//---------------------------------------------------------------------------- +static void map_sdd1_hwregs() +{ + map_io_seg(0x4800, 0x4808, "sdd1"); +} + +//---------------------------------------------------------------------------- +static sel_t map_lorom_offset(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint8 start_bank, uint32 offset) +{ + // 32KB chunks count + uint32 chunks = (rom_size + 0x8000 - 1) / 0x8000; + + // map rom to banks + sel_t start_sel = 0; + for ( uint32 mapped = 0, bank = start_bank; mapped < chunks; bank++, mapped++ ) + { + if ( bank == 0x7e || bank == 0x7f ) + continue; + + uint32 map_size = qmin(0x8000, rom_size - (0x8000 * mapped)); + + ea_t start = uint32((bank << 16) + 0x8000); + ea_t end = start + 0x8000; + uint32 off_in_file = rom_start_in_file + offset + (mapped << 15); + + if ( !file2base(li, off_in_file, start, start + map_size, FILEREG_PATCHABLE) ) + loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", off_in_file, start, end); + + char seg_name[0x10]; + sel_t selector = allocate_selector((start - 0x8000) >> 4); + qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); + if ( !add_segm(selector, start, end, seg_name, "BANK_ROM") ) + loader_failure("Failed adding .BANK segment\n"); + + if ( bank == start_bank ) + start_sel = selector; + } + + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_hirom_offset(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint8 start_bank, uint32 offset) +{ + sel_t start_sel = 0; + + // map rom to banks + uint32 chunks = (rom_size + 0x10000 - 1) / 0x10000; + for ( uint32 mapped = 0, bank = start_bank; mapped < chunks; bank++, mapped++ ) + { + if ( bank == 0x7e || bank == 0x7f ) + continue; + + uint32 map_size = qmin(0x10000, rom_size - (0x10000 * mapped)); + + ea_t start = uint32(bank << 16); + ea_t end = start + 0x10000; + uint32 off_in_file = rom_start_in_file + offset + (mapped << 16); + if ( !file2base(li, off_in_file, start, start + map_size, FILEREG_PATCHABLE) ) + loader_failure("Failed mapping 0x%x -> [0x%a, 0x%a)\n", off_in_file, start, end); + + char seg_name[0x10]; + sel_t selector = allocate_selector((start) >> 4); + qsnprintf(seg_name, sizeof(seg_name), ".%02X", bank); + if ( !add_segm(selector, start, end, seg_name, "BANK_ROM") ) + loader_failure("Failed adding .BANK segment\n"); + + if ( bank == start_bank ) + start_sel = selector; + } + + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_lorom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) +{ + // map rom to banks 80-ff + return map_lorom_offset(li, rom_start_in_file, rom_size, 0x80, 0); +} + +//---------------------------------------------------------------------------- +static sel_t map_hirom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) +{ + // map rom to banks c0-ff + return map_hirom_offset(li, rom_start_in_file, rom_size, 0xc0, 0); +} + +//---------------------------------------------------------------------------- +static sel_t map_exhirom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) +{ + if ( rom_size <= 0x400000 ) + return BADSEL; + + // map rom to banks 40-7f + sel_t start_sel = map_hirom_offset(li, rom_start_in_file, rom_size - 0x400000, 0x40, 0x400000); + + // map rom to banks c0-ff + map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0xc0, 0); + + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_superfx(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) +{ + // map rom to banks 00-3f (LoROM layout) + sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x00, 0); + + // map rom to banks c0-df (HiROM layout) + map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0xc0, 0); + + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_sa1(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) +{ + // map rom to banks 00-3f (LoROM layout) + sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x00, 0); + + // map rom to banks c0-ff (HiROM layout) + map_hirom_offset(li, rom_start_in_file, rom_size, 0xc0, 0); + + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_sdd1rom(linput_t *li, uint32 rom_start_in_file, uint32 rom_size) +{ + // map rom to banks 80-bf (LoROM layout) + sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x80, 0); + + // map rom to banks c0-ff (HiROM layout) + map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0xc0, 0); + + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_lorom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_lorom(li, rom_start_in_file, qmin(rom_size, 0x400000)); + map_lorom_sram(ram_size); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_hirom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_hirom(li, rom_start_in_file, qmin(rom_size, 0x400000)); + map_hirom_sram(ram_size); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_exlorom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + // S-DD1 cartridge should be handled by map_sdd1_cartridge + sel_t start_sel = map_lorom_offset(li, rom_start_in_file, qmin(rom_size, 0x200000), 0x80, 0); + map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x400000), 0x40, 0); + map_lorom_sram(ram_size); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_exhirom_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_exhirom(li, rom_start_in_file, rom_size); + map_hirom_sram(ram_size); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_superfx_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_superfx(li, rom_start_in_file, rom_size); + map_superfx_sram(ram_size); + map_superfx_workram(); + map_superfx_hwregs(); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_sa1_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_sa1(li, rom_start_in_file, rom_size); + map_sa1_bwram(ram_size); + map_sa1_iram(); + map_sa1_hwregs(); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_cx4_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_lorom(li, rom_start_in_file, qmin(rom_size, 0x400000)); + map_lorom_sram(ram_size); + map_cx4_hwregs(); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_spc7110_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_hirom_offset(li, rom_start_in_file, qmin(rom_size, 0x100000), 0xc0, 0); + // create ram banks 00-3f + map_hirom_sram_offset(ram_size, 0x00); + map_spc7110_hwregs(); + return start_sel; +} + +//---------------------------------------------------------------------------- +static sel_t map_sdd1_cartridge(linput_t *li, uint32 rom_start_in_file, uint32 rom_size, uint32 ram_size) +{ + sel_t start_sel = map_sdd1rom(li, rom_start_in_file, rom_size); + map_lorom_sram(ram_size); + map_sdd1_hwregs(); + return start_sel; +} + +//---------------------------------------------------------------------------- +static void map_sharprtc() +{ + map_io_seg(0x2800, 0x2802, "sharprtc"); +} + +//---------------------------------------------------------------------------- +static void map_epsonrtc() +{ + map_io_seg(0x4840, 0x4843, "epsonrtc"); +} + +//---------------------------------------------------------------------------- +static void map_obc1() +{ + // TODO: Add OBC-1 registers +} + +//---------------------------------------------------------------------------- +static void map_dsp1(SuperFamicomCartridge::DSP1MemoryMapper /*dsp1_mapper*/) +{ + // TODO: Add DSP-1 registers +} + +//---------------------------------------------------------------------------- +static void map_dsp2() +{ + // TODO: Add DSP-2 registers +} + +//---------------------------------------------------------------------------- +static void map_dsp3() +{ + // TODO: Add DSP-3 registers +} + +//---------------------------------------------------------------------------- +static void map_dsp4() +{ + // TODO: Add DSP-4 registers +} + +//---------------------------------------------------------------------------- +static void map_st010() +{ + // TODO: Add ST-010 registers +} + +//---------------------------------------------------------------------------- +static void map_st011() +{ + // TODO: Add ST-011 registers +} + +//---------------------------------------------------------------------------- +static void map_st018() +{ + // TODO: Add ST-018 registers +} + +//---------------------------------------------------------------------------- +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + SuperFamicomCartridge cartridge(li); + unsigned score = SuperFamicomCartridge::score_header(li, cartridge.header_offset); + + // It is enough to have the first byte of the supposed 'reset vector' match + // one of 6 values, to have a treshold of 8. arm_eep0.bin has such a byte. + // Thus a treshold of 9 (or more) seems in order. Here are some scores: + // - m65816_ffVI.snes: 20 + // - m65816_pacman.snes: 14 + // - m65816_z2ybd.snes: 14 + const int ACCEPTABLE_SCORE_TRESHOLD = 9; + if ( score >= ACCEPTABLE_SCORE_TRESHOLD + && cartridge.type != SuperFamicomCartridge::TypeUnknown ) + { + *fileformatname = "SNES ROM"; + *processor = "m65816"; + return 1; + } + + return 0; +} + +//---------------------------------------------------------------------------- +static void add_interrupt_vector(snes_addr_t &sa, uint16 addr, const char *name, bool make_code) +{ + // Set 'addr' as dword + ea_t real_ea = sa.xlat(addr); + create_word(real_ea, 2); + + ea_t orig_vector_addr = get_word(real_ea); + ea_t vector_addr = sa.xlat(orig_vector_addr); + if ( orig_vector_addr != 0 && orig_vector_addr != 0xffff ) + { + // Set 'vector_addr' name to be 'name' + if ( !has_user_name(get_flags(vector_addr)) ) + set_name(vector_addr, name, SN_NOCHECK); + + // Push the vector_addr into the autoanalysis queue. + // Do not make use of auto_make_proc(), because some + // interrupt handler functions are ``overlaid''. Thus, + // we'd break a procedure w/ inserting another + // procedure right into the previous procedure's code. + if ( make_code ) + auto_make_code(vector_addr); + + // Set 'real_ea' as offset + refinfo_t ri; + ri.init(REF_OFF16, vector_addr - orig_vector_addr); + op_offset_ex(real_ea, OPND_MASK, &ri); + + set_cmt(real_ea, name, false); + } +} + +//---------------------------------------------------------------------------- +void idaapi load_file(linput_t *li, ushort /*neflags*/, const char * /*ffn*/) +{ + // One should always set the processor type + // as early as possible: IDA will draw some + // informations from it; e.g., the size of segments. + // + // Should this instruction be placed after the calls to + // map_mode_2x(), IDA would create 32-bits segments, + // because, until the processor type is specified, IDA + // assumes x86. + set_processor_type("m65816", SETPROC_LOADER); + + SuperFamicomCartridge cartridge(li); + + // Determine whether ROM has a header + int32 start = cartridge.has_copier_header ? 512 : 0; + + // Store information for the cpu module + netnode node; + node.create("$ m65816"); + node.hashset("device", "snes"); + cartridge.write_hash(node); + + snes_addr_t sa; + sa.addr_init(cartridge); + + sel_t start_cs; + + if ( cartridge.has_cx4 ) + { + start_cs = map_cx4_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + } + else if ( cartridge.has_spc7110 ) + { + start_cs = map_spc7110_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + } + else if ( cartridge.has_sdd1 ) + { + start_cs = map_sdd1_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + } + else + { + switch ( cartridge.mapper ) + { + case SuperFamicomCartridge::LoROM: + start_cs = map_lorom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + break; + case SuperFamicomCartridge::HiROM: + start_cs = map_hirom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + break; + case SuperFamicomCartridge::ExLoROM: + start_cs = map_exlorom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + break; + case SuperFamicomCartridge::ExHiROM: + start_cs = map_exhirom_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + break; + case SuperFamicomCartridge::SuperFXROM: + start_cs = map_superfx_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + break; + case SuperFamicomCartridge::SA1ROM: + start_cs = map_sa1_cartridge(li, start, cartridge.rom_size, cartridge.ram_size); + break; + default: + loader_failure("Unsupported mapper: %s", cartridge.mapper_string()); + } + } + inf_set_start_cs(start_cs); + + // Hardware registers + map_hwregs(); + + // WRAM + map_wram(); + + if ( cartridge.has_sharprtc ) + map_sharprtc(); + + if ( cartridge.has_epsonrtc ) + map_epsonrtc(); + + if ( cartridge.has_obc1 ) + map_obc1(); + + if ( cartridge.has_dsp1 ) + map_dsp1(cartridge.dsp1_mapper); + + if ( cartridge.has_dsp2 ) + map_dsp2(); + + if ( cartridge.has_dsp3 ) + map_dsp3(); + + if ( cartridge.has_dsp4 ) + map_dsp4(); + + if ( cartridge.has_st010 ) + map_st010(); + + if ( cartridge.has_st011 ) + map_st011(); + + if ( cartridge.has_st018 ) + map_st018(); + + ea_t reset_vector_loc = sa.xlat(0xfffc); + uint16 start_pc = get_word(reset_vector_loc); + ea_t start_address = sa.xlat(start_pc); + inf_set_start_ip(start_address & 0xffff); + + // ------- Most important vectors + // http://en.wikibooks.org/wiki/Super_NES_Programming/SNES_memory_map + add_interrupt_vector(sa, 0xfffc, "Emulation-mode RESET", true); + add_interrupt_vector(sa, 0xffea, "Native-mode NMI", true); + add_interrupt_vector(sa, 0xffee, "Native-mode IRQ", true); + add_interrupt_vector(sa, 0xfffe, "Emulation-mode IRQ", true); + + // ------- Native-mode vectors + add_interrupt_vector(sa, 0xffe4, "Native-mode COP", false); + add_interrupt_vector(sa, 0xffe6, "Native-mode BRK", false); + add_interrupt_vector(sa, 0xffe8, "Native-mode ABORT", false); + add_interrupt_vector(sa, 0xffec, "Native-mode RESET", false); + + // ------- Emulation-mode vectors + add_interrupt_vector(sa, 0xfff4, "Emulation-mode COP", false); + add_interrupt_vector(sa, 0xfff8, "Emulation-mode ABORT", false); + add_interrupt_vector(sa, 0xfffa, "Emulation-mode NMI", false); + + // ------- Undefined vectors + create_word(sa.xlat(0xffe0), 2); + create_word(sa.xlat(0xffe2), 2); + create_word(sa.xlat(0xfff0), 2); + create_word(sa.xlat(0xfff2), 2); + create_word(sa.xlat(0xfff6), 2); + + // Header info + ea_t header = sa.xlat(0xffc0); + set_name(header, "snes_header"); + create_strlit(header, 21, STRTYPE_C); + set_cmt(header, "Game Title", false); + create_byte(header + 0x15, 1); + set_cmt(header + 0x15, "ROM Makeup / ROM Speed and Map Mode", false); + create_byte(header + 0x16, 1); + set_cmt(header + 0x16, "Chipset", false); + create_byte(header + 0x17, 1); + set_cmt(header + 0x17, "ROM Size", false); + create_byte(header + 0x18, 1); + set_cmt(header + 0x18, "RAM Size", false); + create_byte(header + 0x19, 1); + set_cmt(header + 0x19, "Country", false); + create_byte(header + 0x1a, 1); + set_cmt(header + 0x1a, "Developer ID", false); + create_byte(header + 0x1b, 1); + set_cmt(header + 0x1b, "ROM Version", false); + create_word(header + 0x1c, 2); + set_cmt(header + 0x1c, "Checksum Complement", false); + create_word(header + 0x1e, 2); + set_cmt(header + 0x1e, "Checksum", false); +} + +//---------------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + LDRF_RELOAD, + accept_file, + load_file, + NULL, + NULL, + NULL, +}; diff --git a/idasdk75/ldr/snes/super-famicom.hpp b/idasdk76/ldr/snes/super-famicom.hpp similarity index 100% rename from idasdk75/ldr/snes/super-famicom.hpp rename to idasdk76/ldr/snes/super-famicom.hpp diff --git a/idasdk76/ldr/w32run/makefile b/idasdk76/ldr/w32run/makefile new file mode 100644 index 0000000..83dc2b1 --- /dev/null +++ b/idasdk76/ldr/w32run/makefile @@ -0,0 +1,14 @@ +PROC=w32run + +include ../loader.mak + +# MAKEDEP dependency list ------------------ +$(F)w32run$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)entry.hpp $(I)exehdr.h \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaldr.h \ + w32run.cpp w32run.h diff --git a/idasdk76/ldr/w32run/w32run.cpp b/idasdk76/ldr/w32run/w32run.cpp new file mode 100644 index 0000000..1f84be5 --- /dev/null +++ b/idasdk76/ldr/w32run/w32run.cpp @@ -0,0 +1,284 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * Watcom DosExtender loader. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +/* + L O A D E R for Watcom W32RUN DOS32-extender +*/ + +#include "../idaldr.h" +#include <exehdr.h> +#include <problems.hpp> +#include "w32run.h" +//lint !e451 header file 'stddef.h' repeatedly included but has no header guard +#include <stddef.h> // offsetof + +//-------------------------------------------------------------------------- +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// +static int idaapi accept_file( + qstring *fileformatname, + qstring *processor, + linput_t *li, + const char *) +{ + union + { + exehdr ex; + w32_hdr wh; + }; + uint32 pos; + + if ( qlread(li, &ex, sizeof(ex)) != sizeof(ex) + || ex.exe_ident != EXE_ID + || (pos = ex.HdrSize) == 0 ) + { + return 0; + } + uint64 fsize = qlsize(li); + qlseek(li, pos *= 16, SEEK_SET); + if ( qlread(li, &wh, sizeof(wh)) != sizeof(wh) ) + return 0; + if ( wh.ident != W32_ID || wh.beg_fileoff < pos+sizeof(wh) +// || ph->memsize >= MAXLOADMEM + || wh.read_size > wh.mem_size + || wh.start_offset >= wh.reltbl_offset + || wh.beg_fileoff > fsize + || wh.read_size > fsize - wh.beg_fileoff + || wh.reltbl_offset > wh.read_size - 2 ) + { + return 0; + } + *fileformatname = "Watcom DOS32-extender file"; + *processor = "metapc"; + return f_W32RUN; +} + +//-------------------------------------------------------------------------- +static w32_hdr wh; +static uint32 minea, topea; +static linput_t *li; + +//------------------------------------------------------------------------- +static int mread(void *buf, size_t size) +{ + if ( qlread(li, buf, size) == size ) + return 0; + if ( ask_yn(ASKBTN_NO, + "HIDECANCEL\n" + "Read error or bad file structure. Continue loading?") <= ASKBTN_NO ) + { + loader_failure(); + } + return 1; +} + +//------------------------------------------------------------------------- +static void realize_relocation(void) +{ + char first = 0; + ushort cnt, tmp; + uint32 offset; + uint32 curv, maxv = 0, ost = wh.read_size - wh.reltbl_offset; + + fixup_data_t fd(FIXUP_OFF32); + + msg("Reading relocation table...\n"); + + for ( ; ; ) + { + if ( ost < sizeof(short) ) + { + first = -1; + break; + } + ost -= sizeof(short); + if ( mread(&cnt, sizeof(cnt)) ) + return; + if ( cnt == 0 ) + break; + if ( ost < sizeof(int32) ) + { + first = -1; + break; + } + ost -= sizeof(int32); + if ( mread(&tmp, sizeof(tmp)) ) + return; + offset = (uint32)tmp << 16; + if ( mread(&tmp, sizeof(tmp)) ) + return; + offset |= tmp; + while ( true ) + { + if ( offset > wh.reltbl_offset - 4 ) + { + if ( !first ) + { + ++first; + warning("Bad value(s) in relocation table!"); + } + } + else + { + uint32 ea = minea + offset; + show_addr(ea); + curv = get_dword(ea); + if ( curv >= wh.mem_size ) + { + msg("Doubtful value after relocation! (%x=>%x)\n", ea, curv + minea); + remember_problem(PR_ATTN, ea); + } + else if ( curv > maxv ) + { + maxv = curv; + } + curv += minea; + put_dword(ea, curv); + fd.off = offset; + fd.sel = curv >= topea ? 2 : 1; + fd.set(ea); + } + if ( --cnt == 0 ) + break; + if ( ost < sizeof(short) ) + { + first = -1; + break; + } + ost -= sizeof(short); + if ( mread(&tmp, sizeof(tmp)) ) + return; + offset += tmp; + } + } + if ( first < 0 ) + warning("Truncated relocation table!"); + if ( !first && ost ) + warning("Information after relocation table!"); + if ( ost == 0 + && !first + && maxv > wh.start_offset + && (maxv += minea) < topea ) + { + set_segm_end(topea, maxv, SEGMOD_KILL); + } +} + +//-------------------------------------------------------------------------- +static void add_all_comments(void) +{ + create_filename_cmt(); + add_pgm_cmt("Full size of allocation memory: %08Xh", wh.mem_size); + add_pgm_cmt("Calling convention for W32RUN\n\n" + " ah - OS type\n" + " ecx - low stack limit\n" + " bx:edx - int 21h interface\n" + " edi - struct {"); + add_pgm_cmt(" char * ModuleFileName;\n" + " char * CommandLine;\n" + " char * Environment;"); + add_pgm_cmt(" char * ExeTrademarkString;\n" + " long SystemDepenced_1;\n" + " long SystemDepenced_2;"); + add_pgm_cmt(" }"); + + set_cmt(inf_get_start_ip(), "Calling convention declared in file header", 1); +} + +//-------------------------------------------------------------------------- +static void create32( + sel_t sel, + ea_t start_ea, + ea_t end_ea, + const char *name, + const char *sclass) +{ + set_selector(sel, 0); + + segment_t s; + s.sel = sel; + s.start_ea = start_ea; + s.end_ea = end_ea; + s.align = saRelByte; + s.comb = scPub; + s.bitness = 1; // 32-bit + + if ( !add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_SPARSE) ) + loader_failure(); +} + +//-------------------------------------------------------------------------- +// +// load file into the database. +// +void idaapi load_file(linput_t *_li, ushort /*neflag*/, const char * /*fileformatname*/) +{ + ushort pos; + + set_processor_type("metapc", SETPROC_LOADER); + + li = _li; + qlseek(li, offsetof(exehdr, HdrSize)); + lread(li, &pos, sizeof(pos)); + qlseek(li, (uint32)pos * 16); + lread(li, &wh, sizeof(wh)); + + inf_set_baseaddr(0); +// inf.s_prefflag &= ~PREF_SEGADR; +// inf.nametype = NM_EA4; + inf_set_lflags(inf_get_lflags() | LFLG_PC_FLAT); + minea = (uint32)to_ea(W32_DOS_LOAD_BASE, 0); + inf_set_start_ip(minea + wh.start_offset); + inf_set_start_cs(1); // selector of code + topea = minea + wh.reltbl_offset; + uint64 fsize = qlsize(li); + if ( wh.beg_fileoff > fsize || topea-minea > fsize-wh.beg_fileoff ) + loader_failure("Corrupted file"); + file2base(li, wh.beg_fileoff, minea, topea, FILEREG_PATCHABLE); + create32(1, minea, topea, NAME_CODE, CLASS_CODE); + create32(2, topea, minea+wh.mem_size, NAME_BSS, CLASS_BSS); + set_default_dataseg(1); + realize_relocation(); + add_all_comments(); +} + +//---------------------------------------------------------------------- +// +// LOADER DESCRIPTION BLOCK +// +//---------------------------------------------------------------------- +loader_t LDSC = +{ + IDP_INTERFACE_VERSION, + 0, // loader flags +// +// check input file format. if recognized, then return 1 +// and fill 'fileformatname'. +// otherwise return 0 +// + accept_file, +// +// load file into the database. +// + load_file, +// +// create output file from the database. +// this function may be absent. +// + NULL, +// take care of a moved segment (fix up relocations, for example) + NULL, + NULL, +}; diff --git a/idasdk75/ldr/w32run/w32run.h b/idasdk76/ldr/w32run/w32run.h similarity index 100% rename from idasdk75/ldr/w32run/w32run.h rename to idasdk76/ldr/w32run/w32run.h diff --git a/idasdk75/ldr/windmp/common.h b/idasdk76/ldr/windmp/common.h similarity index 100% rename from idasdk75/ldr/windmp/common.h rename to idasdk76/ldr/windmp/common.h diff --git a/idasdk76/lib/arm64_mac_clang_32/libida.dylib b/idasdk76/lib/arm64_mac_clang_32/libida.dylib new file mode 100644 index 0000000..6b1ac83 Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_32/libida.dylib differ diff --git a/idasdk76/lib/arm64_mac_clang_32/network.a b/idasdk76/lib/arm64_mac_clang_32/network.a new file mode 100644 index 0000000..52fb2a7 Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_32/network.a differ diff --git a/idasdk76/lib/arm64_mac_clang_64/compress.a b/idasdk76/lib/arm64_mac_clang_64/compress.a new file mode 100644 index 0000000..c98cf2e Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_64/compress.a differ diff --git a/idasdk76/lib/arm64_mac_clang_64/dumb.o b/idasdk76/lib/arm64_mac_clang_64/dumb.o new file mode 100644 index 0000000..0ce784f Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_64/dumb.o differ diff --git a/idasdk76/lib/arm64_mac_clang_64/libida64.dylib b/idasdk76/lib/arm64_mac_clang_64/libida64.dylib new file mode 100644 index 0000000..fdd2dfd Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_64/libida64.dylib differ diff --git a/idasdk76/lib/arm64_mac_clang_64/network.a b/idasdk76/lib/arm64_mac_clang_64/network.a new file mode 100644 index 0000000..b5f460c Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_64/network.a differ diff --git a/idasdk76/lib/arm64_mac_clang_64/pro.a b/idasdk76/lib/arm64_mac_clang_64/pro.a new file mode 100644 index 0000000..f963f8a Binary files /dev/null and b/idasdk76/lib/arm64_mac_clang_64/pro.a differ diff --git a/idasdk76/lib/arm_mac_clang_32/libida.dylib b/idasdk76/lib/arm_mac_clang_32/libida.dylib new file mode 100644 index 0000000..6c6ff54 Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_32/libida.dylib differ diff --git a/idasdk76/lib/arm_mac_clang_32/network.a b/idasdk76/lib/arm_mac_clang_32/network.a new file mode 100644 index 0000000..111434d Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_32/network.a differ diff --git a/idasdk76/lib/arm_mac_clang_64/compress.a b/idasdk76/lib/arm_mac_clang_64/compress.a new file mode 100644 index 0000000..d323eef Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_64/compress.a differ diff --git a/idasdk76/lib/arm_mac_clang_64/dumb.o b/idasdk76/lib/arm_mac_clang_64/dumb.o new file mode 100644 index 0000000..43d1bdc Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_64/dumb.o differ diff --git a/idasdk76/lib/arm_mac_clang_64/libida64.dylib b/idasdk76/lib/arm_mac_clang_64/libida64.dylib new file mode 100644 index 0000000..d5d234e Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_64/libida64.dylib differ diff --git a/idasdk76/lib/arm_mac_clang_64/network.a b/idasdk76/lib/arm_mac_clang_64/network.a new file mode 100644 index 0000000..9488371 Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_64/network.a differ diff --git a/idasdk76/lib/arm_mac_clang_64/pro.a b/idasdk76/lib/arm_mac_clang_64/pro.a new file mode 100644 index 0000000..5ec0635 Binary files /dev/null and b/idasdk76/lib/arm_mac_clang_64/pro.a differ diff --git a/idasdk76/lib/x64_linux_gcc_32/libida.so b/idasdk76/lib/x64_linux_gcc_32/libida.so new file mode 100644 index 0000000..8562966 Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_32/libida.so differ diff --git a/idasdk76/lib/x64_linux_gcc_32/network.a b/idasdk76/lib/x64_linux_gcc_32/network.a new file mode 100644 index 0000000..689109d Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_32/network.a differ diff --git a/idasdk76/lib/x64_linux_gcc_64/compress.a b/idasdk76/lib/x64_linux_gcc_64/compress.a new file mode 100644 index 0000000..e01b061 Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_64/compress.a differ diff --git a/idasdk76/lib/x64_linux_gcc_64/dumb.o b/idasdk76/lib/x64_linux_gcc_64/dumb.o new file mode 100644 index 0000000..ceb5ddb Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_64/dumb.o differ diff --git a/idasdk76/lib/x64_linux_gcc_64/libida64.so b/idasdk76/lib/x64_linux_gcc_64/libida64.so new file mode 100644 index 0000000..e44d960 Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_64/libida64.so differ diff --git a/idasdk76/lib/x64_linux_gcc_64/network.a b/idasdk76/lib/x64_linux_gcc_64/network.a new file mode 100644 index 0000000..ff76a66 Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_64/network.a differ diff --git a/idasdk76/lib/x64_linux_gcc_64/pro.a b/idasdk76/lib/x64_linux_gcc_64/pro.a new file mode 100644 index 0000000..f2db581 Binary files /dev/null and b/idasdk76/lib/x64_linux_gcc_64/pro.a differ diff --git a/idasdk76/lib/x64_mac_clang_32/libida.dylib b/idasdk76/lib/x64_mac_clang_32/libida.dylib new file mode 100644 index 0000000..37f7070 Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_32/libida.dylib differ diff --git a/idasdk76/lib/x64_mac_clang_32/network.a b/idasdk76/lib/x64_mac_clang_32/network.a new file mode 100644 index 0000000..2a82e8c Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_32/network.a differ diff --git a/idasdk76/lib/x64_mac_clang_64/compress.a b/idasdk76/lib/x64_mac_clang_64/compress.a new file mode 100644 index 0000000..5d2ca91 Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_64/compress.a differ diff --git a/idasdk76/lib/x64_mac_clang_64/dumb.o b/idasdk76/lib/x64_mac_clang_64/dumb.o new file mode 100644 index 0000000..69394b7 Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_64/dumb.o differ diff --git a/idasdk76/lib/x64_mac_clang_64/libida64.dylib b/idasdk76/lib/x64_mac_clang_64/libida64.dylib new file mode 100644 index 0000000..e5e030e Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_64/libida64.dylib differ diff --git a/idasdk76/lib/x64_mac_clang_64/network.a b/idasdk76/lib/x64_mac_clang_64/network.a new file mode 100644 index 0000000..2ed23a3 Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_64/network.a differ diff --git a/idasdk76/lib/x64_mac_clang_64/pro.a b/idasdk76/lib/x64_mac_clang_64/pro.a new file mode 100644 index 0000000..236d016 Binary files /dev/null and b/idasdk76/lib/x64_mac_clang_64/pro.a differ diff --git a/idasdk76/lib/x86_linux_gcc_32/compress.a b/idasdk76/lib/x86_linux_gcc_32/compress.a new file mode 100644 index 0000000..7d447f9 Binary files /dev/null and b/idasdk76/lib/x86_linux_gcc_32/compress.a differ diff --git a/idasdk76/lib/x86_linux_gcc_32/dumb.o b/idasdk76/lib/x86_linux_gcc_32/dumb.o new file mode 100644 index 0000000..697e88a Binary files /dev/null and b/idasdk76/lib/x86_linux_gcc_32/dumb.o differ diff --git a/idasdk76/lib/x86_linux_gcc_32/network.a b/idasdk76/lib/x86_linux_gcc_32/network.a new file mode 100644 index 0000000..7cdc018 Binary files /dev/null and b/idasdk76/lib/x86_linux_gcc_32/network.a differ diff --git a/idasdk76/lib/x86_linux_gcc_32/pro.a b/idasdk76/lib/x86_linux_gcc_32/pro.a new file mode 100644 index 0000000..480d429 Binary files /dev/null and b/idasdk76/lib/x86_linux_gcc_32/pro.a differ diff --git a/idasdk76/lib/x86_mac_clang_32/compress.a b/idasdk76/lib/x86_mac_clang_32/compress.a new file mode 100644 index 0000000..e2739da Binary files /dev/null and b/idasdk76/lib/x86_mac_clang_32/compress.a differ diff --git a/idasdk76/lib/x86_mac_clang_32/dumb.o b/idasdk76/lib/x86_mac_clang_32/dumb.o new file mode 100644 index 0000000..4c77a6a Binary files /dev/null and b/idasdk76/lib/x86_mac_clang_32/dumb.o differ diff --git a/idasdk76/lib/x86_mac_clang_32/network.a b/idasdk76/lib/x86_mac_clang_32/network.a new file mode 100644 index 0000000..3b4f310 Binary files /dev/null and b/idasdk76/lib/x86_mac_clang_32/network.a differ diff --git a/idasdk76/lib/x86_mac_clang_32/pro.a b/idasdk76/lib/x86_mac_clang_32/pro.a new file mode 100644 index 0000000..eedd8cf Binary files /dev/null and b/idasdk76/lib/x86_mac_clang_32/pro.a differ diff --git a/idasdk76/makeenv_vc.mak b/idasdk76/makeenv_vc.mak new file mode 100644 index 0000000..5a3da8f --- /dev/null +++ b/idasdk76/makeenv_vc.mak @@ -0,0 +1,290 @@ + +# Create configuration files + +include allmake.mak + +define CFG0 # Common flags +/I$(shell cygpath -am $(IDA)include) +/DMAXSTR=1024 +/DNO_TV_STREAMS +/D__NT__ +# Directory for PDB files +/Fd$(F) +endef + +############################################################################ +# Visual Studio for Intel +define CFG1 +# Merge duplicate strings +/GF +# Exception handling (try/catch can handle only C++ exceptions; use __except for SEH) +/EHs +# Separate functions for linker +/Gy +# show full paths +/FC +# All warnings on +/Wall +# warning C4018: >= : signed/unsigned mismatch +/wd4018 +# warning C4061: enumerator xxx in switch of enum yyy is not explicitly handled by a case label +/wd4061 +# warning C4121: xxx: alignment of a member was sensitive to packing +/wd4121 +# warning C4127: conditional expression is constant +/wd4127 +# warning C4146: unary minus operator applied to unsigned type, result still unsigned +/wd4146 +# warning C4200: nonstandard extension used: zero-sized array in struct/union +/wd4200 +# warning C4201: nonstandard extension used : nameless struct/union +/wd4201 +# warning C4239: nonstandard extension used : non-const refernece=>lvalue +/wd4239 +# warning C4242: initializing : conversion from a to b, possible loss of data +/wd4242 +# warning C4244: xxx : conversion from a to b, possible loss of data +/wd4244 +# warning C4245: xxx : conversion from a to b, signed/unsigned mismatch +/wd4245 +# warning C4267: xxx : conversion from size_t to b, possible loss of data +/wd4267 +# warning C4310: cast truncates constant value +/wd4310 +# warning C4324: xxx : structure was padded due to __declspec(align()) +/wd4324 +# warning C4350: behavior change: '' called instead of '' +# for some reason vc11 started to complain about it and i do not see +# how to shut it up +/wd4350 +# warning C4355: this : used in base member initializer list +/wd4355 +# warning C4365: xx : signed/unsigned mismatch (= or return) +/wd4365 +endef +define CFG1a +# warning C4366: The result of the unary & operator may be unaligned +/wd4366 +# warning C4371: xxx : layout of class may have changed from a previous version of the compiler due to better packing of member xxx +/wd4371 +# warning C4388: != : signed/unsigned mismatch +/wd4388 +# warning C4389: != : signed/unsigned mismatch +/wd4389 +# warning C4458: declaration of '' hides class member +/wd4458 +# warning C4480: != : nonstandard extension used: .... +/wd4480 +# warning C4512: xxx : assignment operator could not be generated +/wd4512 +# warning C4514: xxx : unreferenced inline function has been removed +/wd4514 +# warning C4548: expression before comma has no effect; expected expression with side-effect +/wd4548 +# warning C4571: Informational: catch(...) semantics changed since Visual C++ 7.1; structured exceptions (SEH) are no longer caught +/wd4571 +# warning C4574: yvals.h(vc10): '_SECURE_SCL' is defined to be '0': did you mean to use '#if _SECURE_SCL'? +# warning C4574: ws2tcpicp.h(vc14): 'INCL_WINSOCK_API_TYPEDEFS' is defined to be '0': did you mean to use '#if INCL_WINSOCK_API_TYPEDEFS'? +/wd4574 +# warning C4611: interaction between _setjmp and C++ object destruction is non-portable +/wd4611 +# warning C4619: pragma warning : there is no warning number xxx +/wd4619 +# warning C4623: xxx : default constructor was implicitly defined as deleted +/wd4623 +# warning C4625: xxx : copy constructor could not be generated because a base class copy constructor is inaccessible +/wd4625 +# warning C4626: xxx : assignment operator could not be generated because a base class assignment operator is inaccessible +/wd4626 +# warning C4640: p : construction of local static object is not thread-safe +/wd4640 +# warning C4668: xxx is not defined as a preprocessor macro, replacing with 0 for #if/#elif +/wd4668 +# warning C4686: xxx : possible change in behavior, change in UDT return calling convention +/wd4686 +# warning C4701: xxx : potentially uninitialized local variable +/wd4701 +# warning C4710: xxx : function not inlined +/wd4710 +# warning C4711: xxx : function select for automatic inline expansion +/wd4711 +# warning C4738: storing 32-bit float result in memory, possible loss of performance +/wd4738 +# warning C4820: xxx : x bytes padding added after member xxx +/wd4820 +# warning C4917: xxx : a GUID can only be associated with a class, interface or namespace +/wd4917 +# warning C4986: operator new[]: exception specification does not match previous declaration entered the game. +/wd4986 +# warning C4987: setjmp.h(vc10) nonstandard extension used: throw(...) +/wd4987 +# +# treat as errors: +# warning C4541: 'dynamic_cast' used on polymorphic type 'xxx' with /GR-; unpredictable behavior may result +/we4541 +# warning C4715: 'function' : not all control paths return a value +/we4715 +# warning C4296: '' : expression is always false +/we4296 +# warning C4315: 'class' : 'this' pointer for member 'class::member' may not be aligned 8 as expected by the constructor +/we4315 +# warning C4805: 'operation' : unsafe mix of type 'type' and type 'type' in operation +/we4805 +# +endef + +define CFG2 +# Separate data for linker +/Gw +# warning C4091: 'typedef ': ignored on left of '' when no variable is declared +# skd.../um/dbghelp/h +/wd4091 +# warning C4435: Object layout under /vd2 will change due to virtual base '' +/wd4435 +# warning C4456: declaration of '' hides previous local declaration +/wd4456 +# warning C4457: declaration of '' hides function parameter +/wd4457 +# warning C4459: declaration of '' hides global declaration +/wd4459 +# warning C4464: relative include path contains '..' +/wd4464 +# warning C4774: '' : format string expected in argument 1 is not a string literal +# this warning cannot handle cnd ? "fmt1" : "fmt2" while gcc can +/wd4774 +# warning C4589: Constructor of abstract class '' ignores initializer for virtual base class +# completely wrong warning +/wd4589 +# warning C5025: move assignment operator was implicitly defined as deleted +/wd5025 +# warning C5026: move constructor was implicitly defined as deleted because a base class move constructor is inaccessible or deleted +/wd5026 +# warning C5027: move assignment operator was implicitly defined as deleted because a base class move assignment operator is inaccessible or deleted +/wd5027 +# warning C5039: '': pointer or reference to potentially throwing function passed to extern C function under -EHc. Undefined behavior may occur if this function throws an exception. +/wd5039 +# warning C5045: Compiler will insert Spectre mitigation for memory load if /Qspectre switch specified +/wd5045 +# warning C6323: Use of arithmetic operator on Boolean type(s). +/wd5204 +# warning C5204: class has virtual functions, but its trivial destructor is not virtual; instances of objects derived from this class may not be destructed correctly +/wd6323 +# warning C5038: data member '' will be initialized after data member '' +/wd5038 +# warning C6340: Mismatch on sign: '' passed as '' when some signed type is required in call to '' +/wd6340 +endef + +ifdef NDEBUG # Optimization flags +define CFG3 +/DNDEBUG +# Do not use checked iterators +/D_SECURE_SCL=0 +# Maximum optimization +/Ox +# Enable intrinsic functions +/Oi +endef +else # Debug flags +define CFG3 +/D_DEBUG +# Enable security checks +/GS +# Disable optimizations +/Od +endef +endif + +ifdef USE_VS15 + VSCFG = vs15paths.cfg +else + ifdef __XPCOMPAT__ + VSCFG = vs17paths_xp.cfg + else + VSCFG = vs17paths.cfg + endif +endif + +all: $(SYSDIR).cfg $(VSCFG) +$(SYSDIR).cfg: makeenv_vc.mak allmake.mak defaults.mk makefile + @echo -e '$(subst $(newline),\n,${CFG0})' | grep -v '^#' >$@ + @echo -e '$(subst $(newline),\n,${CFG1})' | grep -v '^#' >>$@ + @echo -e '$(subst $(newline),\n,${CFG1a})'| grep -v '^#' >>$@ + @echo -e '$(subst $(newline),\n,${CFG2})' | grep -v '^#' >>$@ + @echo -e '$(subst $(newline),\n,${CFG3})' | grep -v '^#' >>$@ +ifdef __EA64__ + @echo /D__EA64__ >>$@ +endif +ifdef __X86__ + @echo /D__X86__ >>$@ +endif +ifdef USE_STATIC_RUNTIME + @echo /D__NOEXPORT__ >>$@ +endif +ifdef __XPCOMPAT__ + @echo /D_USING_V110_SDK71_ >>$@ + @echo /Zc:threadSafeInit- >>$@ +endif + +# these cfg files speed up the build process by caching compiler/sdk paths. +# this allows the build system to avoid calling cygpath multiple times on every run. + +define VS15PATHS_CFG +export MSVC_PATH = $(MSVC_PATH) +export MSVC_INCLUDE = $(MSVC_INCLUDE) +export MSVC_BIN-X86 = $(MSVC_BIN-X86) +export MSVC_BIN-X64 = $(MSVC_BIN-X64) +export WSDK_PATH = $(WSDK_PATH) +export WSDK_VER = $(WSDK_VER) +export INCLUDE_UCRT_PATH = $(INCLUDE_UCRT_PATH) +export LIB_UCRT_PATH = $(LIB_UCRT_PATH) +export INCLUDE_UCRT = $(INCLUDE_UCRT) +export LIB_UCRT = $(LIB_UCRT) +endef +vs15paths.cfg: + @echo -e '$(subst $(newline),\n,$(VS15PATHS_CFG))' >$@ + +define VS17PATHS_CFG +export MSVC_ROOT = $(MSVC_ROOT) +export MSVC_TOOLSVER = $(MSVC_TOOLSVER) +export MSVC_PATH = $(MSVC_PATH) +export MSVC_INCLUDE = $(MSVC_INCLUDE) +export MSVC_BIN-X86 = $(MSVC_BIN-X86) +export MSVC_BIN-X64 = $(MSVC_BIN-X64) +export WSDK_PATH = $(WSDK_PATH) +export WSDK_VER = $(WSDK_VER) +export INCLUDE_UCRT_PATH = $(INCLUDE_UCRT_PATH) +export LIB_UCRT_PATH = $(LIB_UCRT_PATH) +export INCLUDE_UCRT = $(INCLUDE_UCRT) +export LIB_UCRT = $(LIB_UCRT) +export INCLUDE_SHARED_PATH = $(INCLUDE_SHARED_PATH) +export INCLUDE_UM_PATH = $(INCLUDE_UM_PATH) +export LIB_UM_PATH = $(LIB_UM_PATH) +export SDK_BIN_PATH = $(SDK_BIN_PATH) +export INCLUDE_SHARED = $(INCLUDE_SHARED) +export INCLUDE_UM = $(INCLUDE_UM) +export LIB_UM = $(LIB_UM) +export SDK_BIN = $(SDK_BIN) +endef +vs17paths.cfg: + @echo -e '$(subst $(newline),\n,$(VS17PATHS_CFG))' >$@ + +define VS17PATHS_XP_CFG +export MSVC_ROOT = $(MSVC_ROOT) +export MSVC_TOOLSVER = $(MSVC_TOOLSVER) +export MSVC_PATH = $(MSVC_PATH) +export MSVC_INCLUDE = $(MSVC_INCLUDE) +export MSVC_BIN-X86 = $(MSVC_BIN-X86) +export MSVC_BIN-X64 = $(MSVC_BIN-X64) +export WSDK_PATH = $(WSDK_PATH) +export WSDK_VER = $(WSDK_VER) +export INCLUDE_UCRT_PATH = $(INCLUDE_UCRT_PATH) +export LIB_UCRT_PATH = $(LIB_UCRT_PATH) +export INCLUDE_UCRT = $(INCLUDE_UCRT) +export LIB_UCRT = $(LIB_UCRT) +export INCLUDE_MSSDK71 = $(INCLUDE_MSSDK71) +export LIB_MSSDK71 = $(LIB_MSSDK71) +export SDK_BIN = $(SDK_BIN) +endef +vs17paths_xp.cfg: + @echo -e '$(subst $(newline),\n,$(VS17PATHS_XP_CFG))' >$@ diff --git a/idasdk75/makefile b/idasdk76/makefile similarity index 100% rename from idasdk75/makefile rename to idasdk76/makefile diff --git a/idasdk76/module.mak b/idasdk76/module.mak new file mode 100644 index 0000000..d78a045 --- /dev/null +++ b/idasdk76/module.mak @@ -0,0 +1,86 @@ + +# This file is included by: +# - ldr/loader.mak +# - module/module.mak +# - plugins/plugin.mak + +ifdef __LINT__ + # Info 785 Too few initializers for aggregate + CFLAGS += -e785 +endif + +#---------------------------------------------------------------------- +# include allmake.mak and prepare default goal if needed +ifndef NO_DEFAULT_TARGETS + include ../../allmake.mak + + # prepare targets + GOALS += modules + GOALS += $(addprefix $(RI),$(IDCS)) + GOALS += configs + all: $(GOALS) + + # create default target and add it to the list of targets + ifdef BUILD_STATIC_LIBRARY + DEFAULT_TARGET = $(L)$(PROC)$(A) + STATIC_LIBS += $(DEFAULT_TARGET) + else + DEFAULT_TARGET = $(call module_dll,$(PROC)) + MODULES += $(DEFAULT_TARGET) + endif + + # create lists of object files for default target (shared or static) + OBJS += $(BASE_OBJS) + OBJS += $(call objs,$(foreach n,1 2 3 4 5 6 7 8 9 10,$(O$(n)))) + $(DEFAULT_TARGET): MODULE_OBJS += $(OBJS) + # object file dependencies must be explicitly added to each module + $(DEFAULT_TARGET): $(OBJS) +endif + +#---------------------------------------------------------------------- +# prepare ldflags for all modules +MODULE_LDFLAGS += $(OUTMAP)$(F)$(@F).map +ifdef __LINUX__ + DEFFILE ?= $(SRC_PATH)exports.def + MODULE_LDFLAGS += -Wl,--version-script=$(DEFFILE) +else ifdef __MAC__ + INSTALL_NAME ?= $(@F) + MODULE_LDFLAGS += -Wl,-install_name,$(INSTALL_NAME) +endif + +#---------------------------------------------------------------------- +# main rule for modules +.PHONY: modules +modules: $(MODULES) $(STATIC_LIBS) + +# shared libraries +$(MODULES): LDFLAGS += $(MODULE_LDFLAGS) +$(MODULES): $(LIBS) $(IDALIB) $(MAKEFILE_DEP) $(DEFFILE) + $(call link_dll, $(MODULE_OBJS), $(LIBS) $(LINKIDA)) +ifdef __NT__ + ifndef DONT_ERASE_LIB + $(Q)$(RM) $(@:$(DLLEXT)=.exp) $(@:$(DLLEXT)=.lib) + endif +endif + $(CHECKSYMS_CMD) + $(POSTACTION) + +# static libraries +$(STATIC_LIBS): $(call lib, $(MODULE_OBJS)) + +#---------------------------------------------------------------------- +# auxiliary rules +CFG_CONFIGS = $(addprefix $(C),$(CONFIGS)) +configs: $(CFG_CONFIGS) + +$(RI)%.idc: %.idc + $(CP) $? $@ + +#---------------------------------------------------------------------- +# removes installed binaries from the $(BIN_PATH)/ directory +.PHONY: uninstall +uninstall:: + rm -rf $(MODULES) $(STATIC_LIBS) + +#---------------------------------------------------------------------- +include $(IDA)objdir.mak diff --git a/idasdk76/module/6502/ana.cpp b/idasdk76/module/6502/ana.cpp new file mode 100644 index 0000000..ccaafbd --- /dev/null +++ b/idasdk76/module/6502/ana.cpp @@ -0,0 +1,284 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "m65.hpp" + +static const uchar nmos[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F +/* 00 */ M65_brk, M65_ora, M65_null,M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, M65_php, M65_ora, M65_asl, M65_anc, M65_nop, M65_ora, M65_asl, M65_slo, /* 00 */ +/* 10 */ M65_bpl, M65_ora, M65_null,M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, M65_clc, M65_ora, M65_nop, M65_slo, M65_nop, M65_ora, M65_asl, M65_slo, /* 10 */ +/* 20 */ M65_jsr, M65_and, M65_null,M65_rla, M65_bit, M65_and, M65_rol, M65_rla, M65_plp, M65_and, M65_rol, M65_anc, M65_bit, M65_and, M65_rol, M65_rla, /* 20 */ +/* 30 */ M65_bmi, M65_and, M65_null,M65_rla, M65_nop, M65_and, M65_rol, M65_rla, M65_sec, M65_and, M65_nop, M65_rla, M65_nop, M65_and, M65_rol, M65_rla, /* 30 */ +/* 40 */ M65_rti, M65_eor, M65_null,M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, M65_pha, M65_eor, M65_lsr, M65_asr, M65_jmp, M65_eor, M65_lsr, M65_sre, /* 40 */ +/* 50 */ M65_bvc, M65_eor, M65_null,M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, M65_cli, M65_eor, M65_nop, M65_sre, M65_nop, M65_eor, M65_lsr, M65_sre, /* 50 */ +/* 60 */ M65_rts, M65_adc, M65_null,M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, M65_pla, M65_adc, M65_ror, M65_arr, M65_jmpi,M65_adc, M65_ror, M65_rra, /* 60 */ +/* 70 */ M65_bvs, M65_adc, M65_null,M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, M65_sei, M65_adc, M65_nop, M65_rra, M65_nop, M65_adc, M65_ror, M65_rra, /* 70 */ +/* 80 */ M65_nop, M65_sta, M65_nop, M65_sax, M65_sty, M65_sta, M65_stx, M65_sax, M65_dey, M65_nop, M65_txa, M65_ane, M65_sty, M65_sta, M65_stx, M65_sax, /* 80 */ +/* 90 */ M65_bcc, M65_sta, M65_null,M65_sha, M65_sty, M65_sta, M65_stx, M65_sax, M65_tya, M65_sta, M65_txs, M65_shs, M65_shy, M65_sta, M65_shx, M65_sha, /* 90 */ +/* A0 */ M65_ldy, M65_lda, M65_ldx, M65_lax, M65_ldy, M65_lda, M65_ldx, M65_lax, M65_tay, M65_lda, M65_tax, M65_lxa, M65_ldy, M65_lda, M65_ldx, M65_lax, /* A0 */ +/* B0 */ M65_bcs, M65_lda, M65_null,M65_lax, M65_ldy, M65_lda, M65_ldx, M65_lax, M65_clv, M65_lda, M65_tsx, M65_lae, M65_ldy, M65_lda, M65_ldx, M65_lax, /* B0 */ +/* C0 */ M65_cpy, M65_cmp, M65_nop, M65_dcp, M65_cpy, M65_cmp, M65_dec, M65_dcp, M65_iny, M65_cmp, M65_dex, M65_sbx, M65_cpy, M65_cmp, M65_dec, M65_dcp, /* C0 */ +/* D0 */ M65_bne, M65_cmp, M65_null,M65_dcp, M65_nop, M65_cmp, M65_dec, M65_dcp, M65_cld, M65_cmp, M65_nop, M65_dcp, M65_nop, M65_cmp, M65_dec, M65_dcp, /* D0 */ +/* E0 */ M65_cpx, M65_sbc, M65_nop, M65_isb, M65_cpx, M65_sbc, M65_inc, M65_isb, M65_inx, M65_sbc, M65_nop, M65_sbc, M65_cpx, M65_sbc, M65_inc, M65_isb, /* E0 */ +/* F0 */ M65_beq, M65_sbc, M65_null,M65_isb, M65_nop, M65_sbc, M65_inc, M65_isb, M65_sed, M65_sbc, M65_nop, M65_isb, M65_nop, M65_sbc, M65_inc, M65_isb /* F0 */ +}; + +static const uchar cmos[256] = +{ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F +/* 00 */ M65_brk, M65_ora, M65_null,M65_null,M65_tsb, M65_ora, M65_asl, M65_rmb0,M65_php, M65_ora, M65_asl, M65_null,M65_tsb, M65_ora, M65_asl, M65_bbr0, /* 00 */ +/* 10 */ M65_bpl, M65_ora, M65_ora, M65_null,M65_trb, M65_ora, M65_asl, M65_rmb1,M65_clc, M65_ora, M65_inc, M65_null,M65_trb, M65_ora, M65_asl, M65_bbr1, /* 10 */ +/* 20 */ M65_jsr, M65_and, M65_null,M65_null,M65_bit, M65_and, M65_rol, M65_rmb2,M65_plp, M65_and, M65_rol, M65_null,M65_bit, M65_and, M65_rol, M65_bbr2, /* 20 */ +/* 30 */ M65_bmi, M65_and, M65_and, M65_null,M65_bit, M65_and, M65_rol, M65_rmb3,M65_sec, M65_and, M65_dec, M65_null,M65_bit, M65_and, M65_rol, M65_bbr3, /* 30 */ +/* 40 */ M65_rti, M65_eor, M65_null,M65_null,M65_null,M65_eor, M65_lsr, M65_rmb4,M65_pha, M65_eor, M65_lsr, M65_null,M65_jmp, M65_eor, M65_lsr, M65_bbr4, /* 40 */ +/* 50 */ M65_bvc, M65_eor, M65_eor, M65_null,M65_null,M65_eor, M65_lsr, M65_rmb5,M65_cli, M65_eor, M65_phy, M65_null,M65_null,M65_eor, M65_lsr, M65_bbr5, /* 50 */ +/* 60 */ M65_rts, M65_adc, M65_null,M65_null,M65_stz, M65_adc, M65_ror, M65_rmb6,M65_pla, M65_adc, M65_ror, M65_null,M65_jmpi,M65_adc, M65_ror, M65_bbr6, /* 60 */ +/* 70 */ M65_bvs, M65_adc, M65_adc, M65_null,M65_stz, M65_adc, M65_ror, M65_rmb7,M65_sei, M65_adc, M65_ply, M65_null,M65_jmpi,M65_adc, M65_ror, M65_bbr7, /* 70 */ +/* 80 */ M65_bra, M65_sta, M65_null,M65_null,M65_sty, M65_sta, M65_stx, M65_smb0,M65_dey, M65_bit, M65_txa, M65_null,M65_sty, M65_sta, M65_stx, M65_bbs0, /* 80 */ +/* 90 */ M65_bcc, M65_sta, M65_sta, M65_null,M65_sty, M65_sta, M65_stx, M65_smb1,M65_tya, M65_sta, M65_txs, M65_null,M65_stz, M65_sta, M65_stz, M65_bbs1, /* 90 */ +/* A0 */ M65_ldy, M65_lda, M65_ldx, M65_null,M65_ldy, M65_lda, M65_ldx, M65_smb2,M65_tay, M65_lda, M65_tax, M65_null,M65_ldy, M65_lda, M65_ldx, M65_bbs2, /* A0 */ +/* B0 */ M65_bcs, M65_lda, M65_lda, M65_null,M65_ldy, M65_lda, M65_ldx, M65_smb3,M65_clv, M65_lda, M65_tsx, M65_null,M65_ldy, M65_lda, M65_ldx, M65_bbs3, /* B0 */ +/* C0 */ M65_cpy, M65_cmp, M65_null,M65_null,M65_cpy, M65_cmp, M65_dec, M65_smb4,M65_iny, M65_cmp, M65_dex, M65_wai,M65_cpy, M65_cmp, M65_dec, M65_bbs4, /* C0 */ +/* D0 */ M65_bne, M65_cmp, M65_cmp, M65_null,M65_null,M65_cmp, M65_dec, M65_smb5,M65_cld, M65_cmp, M65_phx, M65_stp,M65_null,M65_cmp, M65_dec, M65_bbs5, /* D0 */ +/* E0 */ M65_cpx, M65_sbc, M65_null,M65_null,M65_cpx, M65_sbc, M65_inc, M65_smb6,M65_inx, M65_sbc, M65_nop, M65_null,M65_cpx, M65_sbc, M65_inc, M65_bbs6, /* E0 */ +/* F0 */ M65_beq, M65_sbc, M65_sbc, M65_null,M65_null,M65_sbc, M65_inc, M65_smb7,M65_sed, M65_sbc, M65_plx, M65_null,M65_null,M65_sbc, M65_inc, M65_bbs7 /* F0 */ +// 0 1 2 3 4 5 6 7 8 9 A B C D E F +}; + +//---------------------------------------------------------------------- +int m6502_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + insn.Op1.dtype = dt_byte; + uchar code = insn.get_next_byte(); + insn.itype = (is_cmos ? cmos : nmos)[code]; + if ( insn.itype == M65_null ) + return 0; + + switch ( code & 0x1F ) + { +// +08 PHP PLP PHA PLA DEY TAY INY INX Implied +// +18 CLC SEC CLI SEI TYA CLV CLD SED Implied +// +1a NOP* NOP* NOP* NOP* TXS TSX NOP* NOP* Implied +// +1a inc dec phy ply txs tsx phx ply + case 0x1A: + case 0x08: + case 0x18: + switch ( insn.itype ) + { + case M65_inc: + case M65_dec: + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + } + break; +// +0a ASL ROL LSR ROR TXA TAX DEX NOP Accu/impl + case 0x0A: + switch ( insn.itype ) + { + case M65_asl: + case M65_rol: + case M65_lsr: + case M65_ror: + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + } + break; +// +00 BRK JSR RTI RTS NOP*/bra LDY CPY CPX Impl/immed +// +02 t t t t NOP*t LDX NOP*t NOP*t ? /immed +// +09 ORA AND EOR ADC NOP* LDA CMP SBC Immediate +// +0b ANC** ANC** ASR** ARR** ANE** LXA** SBX** SBC* Immediate + case 0x00: + case 0x02: + case 0x09: + case 0x0B: + switch ( insn.itype ) + { + case M65_jsr: + insn.Op1.dtype = dt_code; + insn.Op1.type = o_near; + insn.Op1.addr = insn.get_next_word(); + break; + case M65_brk: + case M65_rti: + case M65_rts: + case M65_wai: + + // no operands + break; + case M65_bra: + goto M65_RELATIVE; + default: + insn.Op1.type = o_imm; + insn.Op1.value = insn.get_next_byte(); + break; + } + break; +// +0c NOP*/tsb BIT JMP JMP () STY LDY CPY CPX Absolute +// +0d ORA AND EOR ADC STA LDA CMP SBC Absolute +// +0e ASL ROL LSR ROR STX LDX DEC INC Absolute +// +0f SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Absolute +// +0f bbr0 bbr2 bbr4 bbr6 bbs0 bbs2 bbs4 bbs6 Zero page relative + case 0x0F: + if ( is_cmos ) + goto ZP_RELATIVE; + case 0x0C: + case 0x0D: + case 0x0E: +M65_ABSOLUTE: + switch ( insn.itype ) + { + case M65_jmp: + insn.Op1.dtype = dt_code; + insn.Op1.type = o_near; + break; + case M65_jmpi: + insn.Op1.dtype = dt_word; + insn.indirect = 1; + /* no break */ + default: + insn.Op1.type = o_mem; + break; + } + insn.Op1.addr = insn.get_next_word(); + break; +// +1c NOP*/trb NOP*/bit NOP* NOP*/jmp SHY**/stz LDY NOP* NOP* Absolute, x +// +1d ORA AND EOR ADC STA LDA CMP SBC Absolute, x +// +1e ASL ROL LSR ROR SHX**y) LDX y) DEC INC Absolute, x +// +1f SLO* RLA* SRE* RRA* SHA**y) LAX* y) DCP ISB Absolute, x +// +0f bbr1 bbr3 bbr5 bbr7 bbs1 bbs3 bbs5 bbs7 Zero page relative + case 0x1F: + if ( is_cmos ) + { +ZP_RELATIVE: + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + insn.Op2.dtype = dt_code; + insn.Op2.type = o_near; + char x = insn.get_next_byte(); + insn.Op2.addr = insn.ip + insn.size + x; + break; + } + /* fall thru */ + case 0x1C: + case 0x1D: + case 0x1E: + insn.Op1.type = o_displ; + insn.Op1.phrase = rX; + switch ( insn.itype ) + { + case M65_stz: + if ( code == 0x9E ) + break; + // no break + case M65_trb: + goto M65_ABSOLUTE; + case M65_shx: + case M65_sha: + case M65_ldx: + case M65_lax: + insn.Op1.phrase = rY; + break; + case M65_jmpi: + insn.Op1.phrase = riX; + break; + } + insn.Op1.addr = insn.get_next_word(); + break; +// +19 ORA AND EOR ADC STA LDA CMP SBC Absolute, y +// +1b SLO* RLA* SRE* RRA* SHS** LAS** DCP* ISB* Absolute, y + case 0x19: + case 0x1B: + if ( insn.itype == M65_stp ) + // no operands + break; + insn.Op1.type = o_displ; + insn.Op1.phrase = rY; + insn.Op1.addr = insn.get_next_word(); + break; +// +10 BPL BMI BVC BVS BCC BCS BNE BEQ Relative + case 0x10: +M65_RELATIVE: + insn.Op1.dtype = dt_code; + insn.Op1.type = o_near; + { + char x = insn.get_next_byte(); + insn.Op1.addr = insn.ip + insn.size + x; + } + break; +// +01 ORA AND EOR ADC STA LDA CMP SBC (indir, x) +// +03 SLO* RLA* SRE* RRA* SAX* LAX* y) DCP* ISB* (indir, x) + case 0x01: + case 0x03: + insn.Op1.type = o_displ; + insn.Op1.phrase = uint16((insn.itype == M65_lax) ? riY : riX); + insn.Op1.addr = insn.get_next_byte(); // what about LAX? + break; +// +11 ORA AND EOR ADC STA LDA CMP SBC (indir), y +// +13 SLO* RLA* SRE* RRA* SHA** LAX* DCP* ISB* (indir), y + case 0x11: + case 0x13: + insn.Op1.type = o_displ; + insn.Op1.phrase = riY; + insn.Op1.addr = insn.get_next_byte(); + break; +// +04 NOP*/tsb BIT NOP* NOP*/stz STY LDY CPY CPX Zeropage +// +05 ORA AND EOR ADC STA LDA CMP SBC Zeropage +// +06 ASL ROL LSR ROR STX LDX DEC INC Zeropage +// +07 SLO* RLA* SRE* RRA* SAX* LAX* DCP* ISB* Zeropage +// +07 rmb0 rmb2 rmb4 rmb6 smb0 smb2 smb4 smb6 Zeropage + case 0x04: + case 0x05: + case 0x06: + case 0x07: +ZEROPAGE: + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + break; +// +14 NOP*/trb NOP*/bit NOP* NOP*/stz STY LDY NOP* NOP* Zeropage, x +// +15 ORA AND EOR ADC STA LDA CMP SBC Zeropage, x +// +16 ASL ROL LSR ROR STX y) LDX y) DEC INC Zeropage, x +// +17 SLO* RLA* SRE* RRA* SAX* y) LAX* y) DCP ISB Zeropage, x +// +17 rmb1 rmb3 rmb5 rmb7 smb1 smb3 smb5 smb7 Zeropage + case 0x17: + if ( is_cmos ) + goto ZEROPAGE; + /* fall thru */ + case 0x14: + case 0x15: + case 0x16: + insn.Op1.type = o_displ; + insn.Op1.phrase = zX; + switch ( insn.itype ) + { + case M65_trb: + goto ZEROPAGE; + case M65_stx: + case M65_sax: + case M65_ldx: + case M65_lax: + insn.Op1.phrase = zY; + break; + } + insn.Op1.addr = insn.get_next_byte(); + break; +// +12 ora and eor adc sta lda cmp sbc Zeropage, indirect + case 0x12: + insn.indirect = 1; + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + break; + default: + error("ana: bad code %x",code); + } + if ( insn.itype == M65_nop ) + insn.Op1.type = o_void; + return insn.size; +} diff --git a/idasdk76/module/6502/emu.cpp b/idasdk76/module/6502/emu.cpp new file mode 100644 index 0000000..8c9794c --- /dev/null +++ b/idasdk76/module/6502/emu.cpp @@ -0,0 +1,94 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "m65.hpp" + +//---------------------------------------------------------------------- +void m6502_t::handle_operand( + const op_t &x, + bool isload, + const insn_t &insn, + bool *flow) const +{ + ea_t ea; + dref_t xreftype; + switch ( x.type ) + { + case o_reg: + break; + case o_imm: + if ( !isload ) + goto badTouch; + xreftype = dr_O; + goto MAKE_IMMD; + case o_displ: + xreftype = isload ? dr_R : dr_W; +MAKE_IMMD: + set_immd(insn.ea); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, xreftype, m65_opflags(x)); + break; + case o_mem: + ea = map_data_ea(insn, x); + insn.create_op_data(ea, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + // add xref to the target address + if ( insn.itype == M65_jmpi && x.dtype == dt_word && is_loaded(ea) ) + { + ea_t callee = get_word(ea); + if ( callee > 32 && is_mapped(callee) ) // is good address? + { + add_cref(insn.ea, callee, fl_JN); + if ( !is_defarg0(get_flags(ea)) ) + op_plain_offset(ea, 0, 0); + } + } + break; + case o_near: + { + ea = map_code_ea(insn, x); + ea_t segbase = (ea - x.addr) >> 4; + ea_t thisseg = insn.cs; + bool iscall = has_insn_feature(insn.itype, CF_CALL); + insn.add_cref( + ea, + x.offb, + iscall ? (segbase == thisseg ? fl_CN : fl_CF) + : (segbase == thisseg ? fl_JN : fl_JF)); + if ( iscall && *flow ) + *flow = func_does_return(ea); + } + break; + default: +badTouch: + const char *mnem = insn.get_canon_mnem(ph); + warning("%a: %s,%d: bad optype %d", insn.ea, mnem, x.n, x.type); + break; + } +} + +//---------------------------------------------------------------------- +int m6502_t::emu(const insn_t &insn) const +{ + uint32 Feature = insn.get_canon_feature(ph); + bool flow = ((Feature & CF_STOP) == 0); + + if ( Feature & CF_USE1 ) handle_operand(insn.Op1, 1, insn, &flow); + if ( Feature & CF_USE2 ) handle_operand(insn.Op2, 1, insn, &flow); + if ( Feature & CF_CHG1 ) handle_operand(insn.Op1, 0, insn, &flow); + if ( Feature & CF_CHG2 ) handle_operand(insn.Op2, 0, insn, &flow); + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + return 1; +} diff --git a/idasdk76/module/6502/ins.cpp b/idasdk76/module/6502/ins.cpp new file mode 100644 index 0000000..c64d1de --- /dev/null +++ b/idasdk76/module/6502/ins.cpp @@ -0,0 +1,140 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "m65.hpp" + +const instruc_t Instructions[] = +{ + { "", 0 }, + { "ADC", CF_USE1 }, // A <- (A) + M + C + { "ANC", CF_USE1 }, // A <- A /\ M, C <- ~A7 + { "AND", CF_USE1 }, // A <- (A) /\ M + { "ANE", CF_USE1 }, // M <-[(A)\/$EE] /\ (X)/\(M) + { "ARR", CF_USE1 }, // A <- [(A /\ M) >> 1] + { "ASL", CF_CHG1 }, // C <- A7, A <- (A) << 1 + { "ASR", CF_USE1 }, // A <- [(A /\ M) >> 1] + { "BCC", CF_USE1 }, // if C=0, PC = PC + offset + { "BCS", CF_USE1 }, // if C=1, PC = PC + offset + { "BEQ", CF_USE1 }, // if Z=1, PC = PC + offset + { "BIT", CF_USE1 }, // Z <- ~(A /\ M) N<-M7 V<-M6 + { "BMI", CF_USE1 }, // if N=1, PC = PC + offset + { "BNE", CF_USE1 }, // if Z=0, PC = PC + offset + { "BPL", CF_USE1 }, // if N=0, PC = PC + offset + { "BRK", CF_STOP }, // Stack <- PC, PC <- ($fffe) + { "BVC", CF_USE1 }, // if V=0, PC = PC + offset + { "BVS", CF_USE1 }, // if V=1, PC = PC + offset + { "CLC", 0 }, // C <- 0 + { "CLD", 0 }, // D <- 0 + { "CLI", 0 }, // I <- 0 + { "CLV", 0 }, // V <- 0 + { "CMP", CF_USE1 }, // (A - M) -> NZC + { "CPX", CF_USE1 }, // (X - M) -> NZC + { "CPY", CF_USE1 }, // (Y - M) -> NZC + { "DCP", CF_USE1|CF_CHG1 }, // M <- (M)-1, (A-M) -> NZC + { "DEC", CF_USE1|CF_CHG1 }, // M <- (M) - 1 + { "DEX", 0 }, // X <- (X) - 1 + { "DEY", 0 }, // Y <- (Y) - 1 + { "EOR", CF_USE1 }, // A <- (A) \-/ M + { "INC", CF_USE1|CF_CHG1 }, // M <- (M) + 1 + { "INX", 0 }, // X <- (X) +1 + { "INY", 0 }, // Y <- (Y) + 1 + { "ISB", CF_USE1|CF_CHG1 }, // M <- (M) - 1,A <- (A)-M-~C + { "JMP", CF_USE1|CF_STOP }, // PC <- Address + { "JMP", CF_USE1|CF_JUMP|CF_STOP }, // PC <- (Address) + { "JSR", CF_USE1|CF_CALL }, // Stack <- PC, PC <- Address + { "LAE", CF_USE1 }, // X,S,A <- (S /\ M) + { "LAX", CF_USE1 }, // A <- M, X <- M + { "LDA", CF_USE1 }, // A <- M + { "LDX", CF_USE1 }, // X <- M + { "LDY", CF_USE1 }, // Y <- M + { "LSR", CF_CHG1 }, // C <- A0, A <- (A) >> 1 + { "LXA", CF_USE1 }, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04 + { "NOP", 0 }, // [no operation] + { "ORA", CF_USE1 }, // A <- (A) V M + { "PHA", 0 }, // Stack <- (A) + { "PHP", 0 }, // Stack <- (P) + { "PLA", 0 }, // A <- (Stack) + { "PLP", 0 }, // A <- (Stack) + { "RLA", CF_USE1|CF_CHG1 }, // M <- (M << 1) /\ (A) + { "ROL", CF_CHG1 }, // C <- A7 & A <- A << 1 + C + { "ROR", CF_CHG1 }, // C<-A0 & A<- (A7=C + A>>1) + { "RRA", CF_USE1|CF_CHG1 }, // M <- (M >> 1) + (A) + C + { "RTI", CF_STOP }, // P <- (Stack), PC <-(Stack) + { "RTS", CF_STOP }, // PC <- (Stack) + { "SAX", CF_CHG1 }, // M <- (A) /\ (X) + { "SBC", CF_USE1 }, // A <- (A) - M - ~C + { "SBX", CF_USE1 }, // X <- (X)/\(A) - M + { "SEC", 0 }, // C <- 1 + { "SED", 0 }, // D <- 1 + { "SEI", 0 }, // I <- 1 + { "SHA", CF_CHG1 }, // M <- (A) /\ (X) /\ (PCH+1) + { "SHS", CF_CHG1 }, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1) + { "SHX", CF_CHG1 }, // M <- (X) /\ (PCH+1) + { "SHY", CF_CHG1 }, // M <- (Y) /\ (PCH+1) + { "SLO", CF_USE1|CF_CHG1 }, // M <- (M >> 1) + A + C + { "SRE", CF_USE1|CF_CHG1 }, // M <- (M >> 1) \-/ A + { "STA", CF_CHG1 }, // M <- (A) + { "STX", CF_CHG1 }, // M <- (X) + { "STY", CF_CHG1 }, // M <- (Y) + { "TAX", 0 }, // X <- (A) + { "TAY", 0 }, // Y <- (A) + { "TSX", 0 }, // X <- (S) + { "TXA", 0 }, // A <- (X) + { "TXS", 0 }, // S <- (X) + { "TYA", 0 }, // A <- (Y) + + + // CMOS instructions + + { "BBR0", CF_USE1|CF_USE2 }, // Branch if bit 0 reset + { "BBR1", CF_USE1|CF_USE2 }, // Branch if bit 1 reset + { "BBR2", CF_USE1|CF_USE2 }, // Branch if bit 2 reset + { "BBR3", CF_USE1|CF_USE2 }, // Branch if bit 3 reset + { "BBR4", CF_USE1|CF_USE2 }, // Branch if bit 4 reset + { "BBR5", CF_USE1|CF_USE2 }, // Branch if bit 5 reset + { "BBR6", CF_USE1|CF_USE2 }, // Branch if bit 6 reset + { "BBR7", CF_USE1|CF_USE2 }, // Branch if bit 7 reset + { "BBS0", CF_USE1|CF_USE2 }, // Branch if bit 0 set + { "BBS1", CF_USE1|CF_USE2 }, // Branch if bit 1 set + { "BBS2", CF_USE1|CF_USE2 }, // Branch if bit 2 set + { "BBS3", CF_USE1|CF_USE2 }, // Branch if bit 3 set + { "BBS4", CF_USE1|CF_USE2 }, // Branch if bit 4 set + { "BBS5", CF_USE1|CF_USE2 }, // Branch if bit 5 set + { "BBS6", CF_USE1|CF_USE2 }, // Branch if bit 6 set + { "BBS7", CF_USE1|CF_USE2 }, // Branch if bit 7 set + { "RMB0", CF_CHG1 }, // Reset memory bit 0 + { "RMB1", CF_CHG1 }, // Reset memory bit 1 + { "RMB2", CF_CHG1 }, // Reset memory bit 2 + { "RMB3", CF_CHG1 }, // Reset memory bit 3 + { "RMB4", CF_CHG1 }, // Reset memory bit 4 + { "RMB5", CF_CHG1 }, // Reset memory bit 5 + { "RMB6", CF_CHG1 }, // Reset memory bit 6 + { "RMB7", CF_CHG1 }, // Reset memory bit 7 + { "SMB0", CF_CHG1 }, // Set memory bit 0 + { "SMB1", CF_CHG1 }, // Set memory bit 1 + { "SMB2", CF_CHG1 }, // Set memory bit 2 + { "SMB3", CF_CHG1 }, // Set memory bit 3 + { "SMB4", CF_CHG1 }, // Set memory bit 4 + { "SMB5", CF_CHG1 }, // Set memory bit 5 + { "SMB6", CF_CHG1 }, // Set memory bit 6 + { "SMB7", CF_CHG1 }, // Set memory bit 7 + { "STZ", CF_CHG1 }, // Store zero + { "TSB", CF_USE1|CF_CHG1 }, // Test and set bits + { "TRB", CF_USE1|CF_CHG1 }, // Test and reset bits + { "PHY", 0 }, // Push Y register + { "PLY", 0 }, // Pull Y register + { "PHX", 0 }, // Push X register + { "PLX", 0 }, // Pull X register + { "BRA", CF_USE1|CF_STOP }, // Branch always + { "WAI", 0 }, // Wait for interrupt + { "STP", CF_STOP }, // Stop processor +}; + +CASSERT(qnumber(Instructions) == M65_last); diff --git a/idasdk76/module/6502/ins.hpp b/idasdk76/module/6502/ins.hpp new file mode 100644 index 0000000..64f564a --- /dev/null +++ b/idasdk76/module/6502/ins.hpp @@ -0,0 +1,144 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + M65_null = 0, // Unknown Operation + + // NMOS instructions + + M65_adc, // A <- (A) + M + C + M65_anc, // A <- A /\ M, C <- ~A7 + M65_and, // A <- (A) /\ M + M65_ane, // M <-[(A)\/$EE] /\ (X)/\(M) + M65_arr, // A <- [(A /\ M) >> 1] + M65_asl, // C <- A7, A <- (A) << 1 + M65_asr, // A <- [(A /\ M) >> 1] + M65_bcc, // if C=0, PC = PC + offset + M65_bcs, // if C=1, PC = PC + offset + M65_beq, // if Z=1, PC = PC + offset + M65_bit, // Z <- ~(A /\ M) N<-M7 V<-M6 + M65_bmi, // if N=1, PC = PC + offset + M65_bne, // if Z=0, PC = PC + offset + M65_bpl, // if N=0, PC = PC + offset + M65_brk, // Stack <- PC, PC <- ($fffe) + M65_bvc, // if V=0, PC = PC + offset + M65_bvs, // if V=1, PC = PC + offset + M65_clc, // C <- 0 + M65_cld, // D <- 0 + M65_cli, // I <- 0 + M65_clv, // V <- 0 + M65_cmp, // (A - M) -> NZC + M65_cpx, // (X - M) -> NZC + M65_cpy, // (Y - M) -> NZC + M65_dcp, // M <- (M)-1, (A-M) -> NZC + M65_dec, // M <- (M) - 1 + M65_dex, // X <- (X) - 1 + M65_dey, // Y <- (Y) - 1 + M65_eor, // A <- (A) \-/ M + M65_inc, // M <- (M) + 1 + M65_inx, // X <- (X) +1 + M65_iny, // Y <- (Y) + 1 + M65_isb, // M <- (M) - 1,A <- (A)-M-~C + M65_jmp, // PC <- Address + M65_jmpi, // (PC <- Address) + M65_jsr, // Stack <- PC, PC <- Address + M65_lae, // X,S,A <- (S /\ M) + M65_lax, // A <- M, X <- M + M65_lda, // A <- M + M65_ldx, // X <- M + M65_ldy, // Y <- M + M65_lsr, // C <- A0, A <- (A) >> 1 + M65_lxa, // X04 <- (X04) /\ M04, A04 <- (A04) /\ M04 + M65_nop, // [no operation] + M65_ora, // A <- (A) V M + M65_pha, // Stack <- (A) + M65_php, // Stack <- (P) + M65_pla, // A <- (Stack) + M65_plp, // A <- (Stack) + M65_rla, // M <- (M << 1) /\ (A) + M65_rol, // C <- A7 & A <- A << 1 + C + M65_ror, // C<-A0 & A<- (A7=C + A>>1) + M65_rra, // M <- (M >> 1) + (A) + C + M65_rti, // P <- (Stack), PC <-(Stack) + M65_rts, // PC <- (Stack) + M65_sax, // M <- (A) /\ (X) + M65_sbc, // A <- (A) - M - ~C + M65_sbx, // X <- (X)/\(A) - M + M65_sec, // C <- 1 + M65_sed, // D <- 1 + M65_sei, // I <- 1 + M65_sha, // M <- (A) /\ (X) /\ (PCH+1) + M65_shs, // X <- (A) /\ (X), S <- (X), M <- (X) /\ (PCH+1) + M65_shx, // M <- (X) /\ (PCH+1) + M65_shy, // M <- (Y) /\ (PCH+1) + M65_slo, // M <- (M >> 1) + A + C + M65_sre, // M <- (M >> 1) \-/ A + M65_sta, // M <- (A) + M65_stx, // M <- (X) + M65_sty, // M <- (Y) + M65_tax, // X <- (A) + M65_tay, // Y <- (A) + M65_tsx, // X <- (S) + M65_txa, // A <- (X) + M65_txs, // S <- (X) + M65_tya, // A <- (Y) + + // CMOS instructions + + M65_bbr0, // Branch if bit 0 reset + M65_bbr1, // Branch if bit 1 reset + M65_bbr2, // Branch if bit 2 reset + M65_bbr3, // Branch if bit 3 reset + M65_bbr4, // Branch if bit 4 reset + M65_bbr5, // Branch if bit 5 reset + M65_bbr6, // Branch if bit 6 reset + M65_bbr7, // Branch if bit 7 reset + M65_bbs0, // Branch if bit 0 set + M65_bbs1, // Branch if bit 1 set + M65_bbs2, // Branch if bit 2 set + M65_bbs3, // Branch if bit 3 set + M65_bbs4, // Branch if bit 4 set + M65_bbs5, // Branch if bit 5 set + M65_bbs6, // Branch if bit 6 set + M65_bbs7, // Branch if bit 7 set + M65_rmb0, // Reset memory bit 0 + M65_rmb1, // Reset memory bit 1 + M65_rmb2, // Reset memory bit 2 + M65_rmb3, // Reset memory bit 3 + M65_rmb4, // Reset memory bit 4 + M65_rmb5, // Reset memory bit 5 + M65_rmb6, // Reset memory bit 6 + M65_rmb7, // Reset memory bit 7 + M65_smb0, // Set memory bit 0 + M65_smb1, // Set memory bit 1 + M65_smb2, // Set memory bit 2 + M65_smb3, // Set memory bit 3 + M65_smb4, // Set memory bit 4 + M65_smb5, // Set memory bit 5 + M65_smb6, // Set memory bit 6 + M65_smb7, // Set memory bit 7 + M65_stz, // Store zero + M65_tsb, // Test and set bits + M65_trb, // Test and reset bits + M65_phy, // Push Y register + M65_ply, // Pull Y register + M65_phx, // Push X register + M65_plx, // Pull X register + M65_bra, // Branch always + M65_wai, // Wait for interrupt + M65_stp, // Stop processor + + M65_last, +}; + +#endif diff --git a/idasdk75/module/6502/m65.hpp b/idasdk76/module/6502/m65.hpp similarity index 100% rename from idasdk75/module/6502/m65.hpp rename to idasdk76/module/6502/m65.hpp diff --git a/idasdk76/module/6502/makefile b/idasdk76/module/6502/makefile new file mode 100644 index 0000000..2a3f3e9 --- /dev/null +++ b/idasdk76/module/6502/makefile @@ -0,0 +1,50 @@ +PROC=m65 + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + m65.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \ + m65.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ + m65.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp m65.hpp \ + out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp m65.hpp \ + reg.cpp diff --git a/idasdk75/module/6502/out.cpp b/idasdk76/module/6502/out.cpp similarity index 100% rename from idasdk75/module/6502/out.cpp rename to idasdk76/module/6502/out.cpp diff --git a/idasdk76/module/6502/reg.cpp b/idasdk76/module/6502/reg.cpp new file mode 100644 index 0000000..d3860f5 --- /dev/null +++ b/idasdk76/module/6502/reg.cpp @@ -0,0 +1,319 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "m65.hpp" + +//-------------------------------------------------------------------------- +static const char *const regnames[] = +{ + "A", "X", "Y", "cs", "ds" +}; + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(new m6502_t); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi m6502_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_ending_undo: + is_cmos = static_cast<bool>(ph.get_proc_index()); + break; + + case processor_t::ev_newprc: + is_cmos = va_arg(va, int) != 0; + break; + + case processor_t::ev_creating_segm: + { // default DS is equal to CS + segment_t *sptr = va_arg(va, segment_t *); + sptr->defsr[rVds-ph.reg_first_sreg] = sptr->sel; + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const char *const ps_headers[] = +{ + ".code", + NULL +}; + +static const asm_t pseudosam = +{ + AS_COLON | ASH_HEXF1 | AS_N2CHR | AS_NOXRF, + UAS_SELSG, + "PseudoSam by PseudoCode", + 0, + ps_headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".rs %s", // uninited arrays + ".equ", // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//----------------------------------------------------------------------- +// SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988 +//----------------------------------------------------------------------- +static const asm_t svasm = +{ + AS_COLON | ASH_HEXF4, + UAS_NOSEG, + "SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988", + 0, + NULL, // headers + "* = ", + ".END", + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "\\'", // special symbols in char and string constants + + ".BYTE", // ascii string directive + ".BYTE", // byte directive + ".WORD", // word directive +}; + +//----------------------------------------------------------------------- +// TASM assembler definiton +//----------------------------------------------------------------------- +static const asm_t tasm = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_NOENS | UAS_NOSEG, + "Table Driven Assembler (TASM) by Speech Technology Inc.", + 0, + NULL, // headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".text", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".block %s", // uninited arrays + ".equ", + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + "and", // and + "or", // or + NULL, // xor + "not", // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//----------------------------------------------------------------------- +// Avocet assembler definiton +//----------------------------------------------------------------------- +static const asm_t avocet = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_NOENS | UAS_NOSEG, + "Avocet Systems 2500AD 6502 Assembler", + 0, + NULL, // headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".fcc", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".ds %s", // uninited arrays +}; + +static const asm_t *const asms[] = { &svasm, &tasm, &pseudosam, &avocet, NULL }; +//----------------------------------------------------------------------- +#define FAMILY "MOS Technology 65xx series:" +static const char *const shnames[] = { "M6502", "M65C02", NULL }; +static const char *const lnames[] = { FAMILY"MOS Technology 6502", "MOS Technology 65C02", NULL }; + +//-------------------------------------------------------------------------- +static const uchar retcode_1[] = { 0x60 }; +static const uchar retcode_2[] = { 0x40 }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_6502, // id + PR_SEGS // flag + | PR_SEGTRANS, + 0, // flag2 + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + regnames, // Register names + qnumber(regnames), // Number of registers + + rVcs, // first + rVds, // last + 0, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0, M65_last, + Instructions, // instruc +}; diff --git a/idasdk75/module/65816/ana.cpp b/idasdk76/module/65816/ana.cpp similarity index 100% rename from idasdk75/module/65816/ana.cpp rename to idasdk76/module/65816/ana.cpp diff --git a/idasdk75/module/65816/bt.cpp b/idasdk76/module/65816/bt.cpp similarity index 100% rename from idasdk75/module/65816/bt.cpp rename to idasdk76/module/65816/bt.cpp diff --git a/idasdk75/module/65816/bt.hpp b/idasdk76/module/65816/bt.hpp similarity index 100% rename from idasdk75/module/65816/bt.hpp rename to idasdk76/module/65816/bt.hpp diff --git a/idasdk75/module/65816/emu.cpp b/idasdk76/module/65816/emu.cpp similarity index 100% rename from idasdk75/module/65816/emu.cpp rename to idasdk76/module/65816/emu.cpp diff --git a/idasdk75/module/65816/ins.cpp b/idasdk76/module/65816/ins.cpp similarity index 100% rename from idasdk75/module/65816/ins.cpp rename to idasdk76/module/65816/ins.cpp diff --git a/idasdk75/module/65816/ins.hpp b/idasdk76/module/65816/ins.hpp similarity index 100% rename from idasdk75/module/65816/ins.hpp rename to idasdk76/module/65816/ins.hpp diff --git a/idasdk75/module/65816/m65816.cfg b/idasdk76/module/65816/m65816.cfg similarity index 100% rename from idasdk75/module/65816/m65816.cfg rename to idasdk76/module/65816/m65816.cfg diff --git a/idasdk76/module/65816/m65816.hpp b/idasdk76/module/65816/m65816.hpp new file mode 100644 index 0000000..4fb8535 --- /dev/null +++ b/idasdk76/module/65816/m65816.hpp @@ -0,0 +1,263 @@ + +#ifndef __M65816_HPP__ +#define __M65816_HPP__ + +#include "../../module/idaidp.hpp" +#include <segregs.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" +#define PROCMOD_NAME m65816 +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + +// Direct Memory Reference with full-length address +#define o_mem_far o_idpspec0 + +// If there is an address in 'Op[N].full_target_ea', +// it means the target address of a branch/jump +// is already known. That's there to help the 'emu' +// module propagate M&X flags & status. +#define full_target_ea specval + + +// Is indirect memory reference? +#define indirect segpref + +// These defines are used by some 6502 asm_t descriptors. +// Although this is primarily a 65816 module, they'll +// remain here since at some point, this CPU module /might/ +// supersede the 6502 one. +// Should that happen, we wouldn't want to waste the +// set of asm_t's that are defined for 6502. +#define UAS_SECT 0x0002 // Segments are named .SECTION +#define UAS_NOSEG 0x0004 // No 'segment' directives +#define UAS_SELSG 0x0010 // Segment should be selected by its name +#define UAS_CDSEG 0x0080 // Only DSEG,CSEG,XSEG +#define UAS_NOENS 0x0200 // don't specify start addr in the .end directive + + +enum M65816_registers +{ + rA, // Accumulator + rX, // X index + rY, // Y index + rS, // Stack + rCs, // code segment + rDs, // data segment + + // This will hold the value of B, the + // data bank register. We won't make use of Ds + // directly, as it is typically used, in computation, + // as a 16-byte paragraph register, while B is a + // 64KB pages register. Also, by having a dedicated + // B, the user will be able to modify it more + // easily (without having to manually shift the value by + // 12 bits). + // Note: Also, we won't have this register ``mapped'' to a sel_t. + // We'll stuff the B value in there directly, which allows + // it to be more versatile, and access banks where there's + // no ROM loaded (such as [S|W]RAM bank(s)). + rB, + + // Direct page register. Same note as that of rB applies. + rD, + + // These will be considered segment + // registers by IDA (just as rCs, rDs, rB and rD), + // but we'll actually use them to keep information + // about the 'm', 'x' and 'e' flags, determining + // what's the accumulator & indices mode, and whether + // we run in 6502 emulation or 65816 native mode. + rFm, + rFx, + rFe, + + // program bank register + rPB +}; + + +// Addressing modes +enum m65_addrmode_t +{ + ABS = 0, + ABS_IX, + ABS_IY, + ABS_IX_INDIR, + ABS_INDIR, + ABS_INDIR_LONG, + ABS_LONG, + ABS_LONG_IX, + ACC, + BLK_MOV, + DP, + DP_IX, + DP_IY, + DP_IX_INDIR, + DP_INDIR, + DP_INDIR_LONG, + DP_INDIR_IY, + DP_INDIR_LONG_IY, + IMM, + IMPLIED, + PC_REL, + PC_REL_LONG, + STACK_ABS, + STACK_DP_INDIR, + STACK_INT, + STACK_PC_REL, + STACK_PULL, + STACK_PUSH, + STACK_RTI, + STACK_RTL, + STACK_RTS, + STACK_REL, + STACK_REL_INDIR_IY, + ADDRMODE_last +}; + +// The various phrases that can be used in case +// an operand is of type 'o_displ'. +enum odispl_phrases_t +{ + rDX = 100, // "dp, X" DP_IX + rDY, // "dp, Y" DP_IY + riDX, // "(dp, X)" DP_IX_INDIR + rAbsi, // "(abs)" ABS_INDIR + rAbsiL, // "long(abs)" ABS_INDIR_LONG + rAbsX, // "abs, X" ABS_IX + rAbsY, // "abs, Y" ABS_IY + rAbsLX, // "long abs, X" ABS_LONG_IX + rAbsXi, // "(abs,X)" ABS_IX_INDIR + rDi, // "(dp,n)" DP_INDIR + rDiL, // "long(dp,n)" DP_INDIR_LONG + rDiY, // "(dp,n), Y" DP_INDIR_IY + rDiLY, // "long(dp,n), Y" DP_INDIR_LONG_IY + rSiY, // (s,n),Y STACK_REL_INDIR_IY + rSDi // "(dp,n)" STACK_DP_INDIR +}; + + +// Information about addressing modes. +struct addrmode_info_t +{ + const char *name; +}; + +extern const struct addrmode_info_t AddressingModes[]; + + +// The type of m65* processors. Used +// to declare availability of certain opcodes depending +// on the processor. +enum m65_variant_t +{ + M6502 = 1, + M65C02 = 2, + M65802 = 4, + M65816 = 8, + M6X = 1 | 2 | 4 | 8 +}; + + +// Special flags, for certain opcodes +enum opcode_flags_t +{ + // Increment instruction's byte count + // if accumulator is in 16-bits mode. + ACC16_INCBC = 1, + + // Increment instruction's byte count + // if X/Y registers are in 16-bits mode. + XY16_INCBC = 2 +}; + +// Information about an opcode +struct opcode_info_t +{ + m65_itype_t itype; + m65_addrmode_t addr; + uint8 cpu_variants; // OR'd m65_variant_t + uint16 flags; // OR'd opcode_flags_t +}; + +inline bool is_acc_16_bits(ea_t ea) { return (get_sreg(ea, rFm) == 0); } +inline bool is_xy_16_bits(ea_t ea) { return (get_sreg(ea, rFx) == 0); } +inline bool is_acc_16_bits(const insn_t &insn) { return is_acc_16_bits(insn.ea); } +inline bool is_xy_16_bits(const insn_t &insn) { return is_xy_16_bits(insn.ea); } + +const struct opcode_info_t &get_opcode_info(uint8 opcode); + +// Determines whether an m65_itype_t is of type 'push' +#define M65_ITYPE_PUSH(op) \ + (((op) == M65816_pea) \ + || ((op) == M65816_pei) \ + || ((op) == M65816_per) \ + || ((op) == M65816_pha) \ + || ((op) == M65816_phb) \ + || ((op) == M65816_phd) \ + || ((op) == M65816_phk) \ + || ((op) == M65816_php) \ + || ((op) == M65816_phx) \ + || ((op) == M65816_phy)) + +// Determines whether an m65_itype_t is of type 'pull' +#define M65_ITYPE_PULL(op) \ + (((op) == M65816_pla) \ + || ((op) == M65816_plb) \ + || ((op) == M65816_pld) \ + || ((op) == M65816_plp) \ + || ((op) == M65816_plx) \ + || ((op) == M65816_ply)) + +//------------------------------------------------------------------------ +int idaapi ana(insn_t *_insn); +int idaapi emu(const insn_t &insn); + +//------------------------------------------------------------------------ +class snes_addr_t; + +struct m65816_iohandler_t : public iohandler_t +{ + m65816_iohandler_t(netnode &nn) : iohandler_t(nn) {} + + virtual bool check_ioresp() const override + { + if ( inf_like_binary() ) + return true; + else + return get_segm_by_name("ppu") != NULL; + } +}; + +DECLARE_PROC_LISTENER(idb_listener_t, struct m65816_t); + +struct m65816_t : public procmod_t +{ + netnode helper; + m65816_iohandler_t ioh = m65816_iohandler_t(helper); + idb_listener_t idb_listener = idb_listener_t(*this); + struct SuperFamicomCartridge *cartridge = nullptr; + snes_addr_t *sa = nullptr; + bool flow = false; + + m65816_t(); + ~m65816_t(); + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + ea_t xlat(ea_t address); + + void handle_operand(const op_t &x, bool read_access, const insn_t &insn); + int emu(const insn_t &insn); + + void m65816_assumes(outctx_t &ctx); + ea_t calc_addr(const op_t &x, ea_t *orig_ea, const insn_t &insn); + void m65816_header(outctx_t &ctx) const; + void m65816_segstart(outctx_t &ctx, segment_t *Srange) const; + void m65816_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; + +#endif diff --git a/idasdk76/module/65816/makefile b/idasdk76/module/65816/makefile new file mode 100644 index 0000000..023e84c --- /dev/null +++ b/idasdk76/module/65816/makefile @@ -0,0 +1,75 @@ +PROC=m65816 +CONFIGS=m65816.cfg +O1=bt + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../module/idaidp.hpp ../iohandler.hpp ana.cpp ins.hpp \ + m65816.hpp +$(F)bt$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../module/idaidp.hpp ../iohandler.hpp bt.cpp bt.hpp \ + ins.hpp m65816.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../module/idaidp.hpp ../iohandler.hpp bt.hpp emu.cpp \ + ins.hpp m65816.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../module/idaidp.hpp ../iohandler.hpp ins.cpp ins.hpp \ + m65816.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../module/idaidp.hpp ../iohandler.hpp bt.hpp ins.hpp \ + m65816.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/snes/addr.cpp ../../ldr/snes/super-famicom.hpp \ + ../../module/idaidp.hpp ../iohandler.hpp ins.hpp \ + m65816.hpp reg.cpp diff --git a/idasdk76/module/65816/out.cpp b/idasdk76/module/65816/out.cpp new file mode 100644 index 0000000..73dcc1b --- /dev/null +++ b/idasdk76/module/65816/out.cpp @@ -0,0 +1,473 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "m65816.hpp" +#include "bt.hpp" + +//---------------------------------------------------------------------- +class out_m65816_t : public outctx_t +{ + out_m65816_t(void) = delete; // not used + m65816_t &pm() { return *static_cast<m65816_t *>(procmod); } +public: + void out_dp(const op_t &x); + void out_addr_near_b(const op_t &x); + void out_addr_near(const op_t &x); + void out_addr_far(const op_t &x); + void print_orig_ea(const op_t &x); + + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_m65816_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_m65816_t) + +//---------------------------------------------------------------------- +void out_m65816_t::out_dp(const op_t &x) +{ + sel_t dp = get_sreg(insn.ea, rD); + if ( dp != BADSEL ) + { + ea_t orig_ea = dp + x.addr; + ea_t ea = pm().xlat(orig_ea); + + if ( !out_name_expr(x, ea, BADADDR) ) + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + } + else + { + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); + } +} + +//---------------------------------------------------------------------- +void out_m65816_t::out_addr_near_b(const op_t &x) +{ + sel_t db = get_sreg(insn.ea, rB); + if ( db != BADSEL ) + { + ea_t orig_ea = (db << 16) + x.addr; + ea_t ea = pm().xlat(orig_ea); + + if ( !out_name_expr(x, ea, BADADDR) ) + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + } + else + { + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_16); + } +} + +//------------------------------------------------------------------------- +void out_m65816_t::out_addr_near(const op_t &x) +{ + ea_t orig_ea = map_code_ea(insn, x); + ea_t ea = pm().xlat(orig_ea); + if ( !out_name_expr(x, ea, BADADDR) ) + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } +} + +//---------------------------------------------------------------------- +void out_m65816_t::out_addr_far(const op_t &x) +{ + ea_t orig_ea = x.addr; + ea_t ea = pm().xlat(orig_ea); + + if ( !out_name_expr(x, ea, BADADDR) ) + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_24); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } +} + +//---------------------------------------------------------------------- +void out_m65816_t::print_orig_ea(const op_t &x) +{ + if ( !has_cmt(F) ) + { + char buf[64]; + qsnprintf(buf, sizeof(buf), + COLSTR(" %s orig=0x%0*a", SCOLOR_AUTOCMT), + ash.cmnt, + (x.type == o_far || x.type == o_mem_far) ? 6 : 4, + x.addr); + out_line(buf); + } +} + +//---------------------------------------------------------------------- +ea_t m65816_t::calc_addr(const op_t &x, ea_t *orig_ea, const insn_t &insn) +{ + ea_t ea; + switch ( x.type ) + { + case o_near: + ea = map_code_ea(insn, x); + goto XLAT_ADDR; + case o_far: + case o_mem_far: + ea = x.addr; + goto XLAT_ADDR; + case o_mem: + ea = map_data_ea(insn, x); +XLAT_ADDR: + if ( orig_ea != NULL ) + *orig_ea = ea; + return xlat(ea); + default: + INTERR(559); + } +} + +//---------------------------------------------------------------------- +bool out_m65816_t::out_operand(const op_t &x) +{ + ea_t ea, orig_ea; + switch ( x.type ) + { + case o_reg: + out_register(ph.reg_names[x.reg]); + break; + case o_imm: + out_symbol('#'); + out_value(x, 0); + break; + case o_near: + case o_far: + if ( insn.indirect ) + out_symbol('('); + ea = pm().calc_addr(x, &orig_ea, insn); + if ( !out_name_expr(x, ea, BADADDR) ) + { + uint32 v = x.addr; + if ( x.type == o_far ) + v &= 0xFFFFFF; + else + v &= 0xFFFF; + out_tagon(COLOR_ERROR); + out_btoa(v, 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + if ( insn.indirect ) + out_symbol(')'); + if ( orig_ea != ea ) + print_orig_ea(x); + break; + case o_mem: + case o_mem_far: + { + if ( insn.indirect ) + out_symbol('('); + + if ( x.type == o_mem_far ) + { + ea = pm().calc_addr(x, &orig_ea, insn); + out_addr_far(x); + } + else + { + sel_t db = get_sreg(insn.ea, rB); + if ( db == BADSEL ) + ea = orig_ea = x.addr; + else + ea = pm().calc_addr(x, &orig_ea, insn); + out_addr_near_b(x); + } + + if ( insn.indirect ) + out_symbol(')'); + + if ( orig_ea != ea ) + print_orig_ea(x); + } + break; + case o_displ: + switch ( x.phrase ) + { + case rS: + out_register(ph.reg_names[x.phrase]); + out_symbol(','); + out_char(' '); + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); + break; + case rD: + out_register(ph.reg_names[x.phrase]); + out_symbol(','); + out_char(' '); + out_dp(x); + break; + case rSiY: + out_symbol('('); + out_register("S"); + out_symbol(','); + out_char(' '); + out_value(x, OOF_ADDR|OOFS_NOSIGN|OOFW_8); + out_symbol(','); + out_char(' '); + out_register("Y"); + out_symbol(')'); + break; + case rDi: + case rSDi: + out_symbol('('); + out_register("D"); + out_symbol(','); + out_char(' '); + out_dp(x); + out_symbol(')'); + break; + case rDiL: + out_symbol('['); + out_register("D"); + out_symbol(','); + out_char(' '); + out_dp(x); + out_symbol(']'); + break; + case rDX: + case rDY: + out_register("D"); + out_symbol(','); + out_char(' '); + out_dp(x); + out_symbol(','); + out_char(' '); + out_register((x.phrase == rDX) ? "X" : "Y"); + break; + case riDX: + out_symbol('('); + out_register("D"); + out_symbol(','); + out_char(' '); + out_dp(x); + out_symbol(','); + out_char(' '); + out_register("X"); + out_symbol(')'); + break; + case rDiY: + case rDiLY: + out_symbol(x.phrase == rDiLY ? '[' : '('); + out_register("D"); + out_symbol(','); + out_char(' '); + out_dp(x); + out_symbol(x.phrase == rDiLY ? ']' : ')'); + out_symbol(','); + out_char(' '); + out_register("Y"); + break; + case rAbsi: + out_symbol('('); + out_addr_near_b(x); + out_symbol(')'); + break; + case rAbsiL: + out_symbol('['); + out_addr_near_b(x); + out_symbol(']'); + break; + case rAbsX: + case rAbsY: + out_addr_near_b(x); + out_symbol(','); + out_char(' '); + out_register(x.phrase == rAbsY ? "Y" : "X"); + break; + case rAbsLX: + { + ea_t lorig_ea = x.addr; + ea_t lea = pm().xlat(lorig_ea); + + out_addr_far(x); + out_symbol(','); + out_char(' '); + out_register("X"); + + if ( lorig_ea != lea ) + print_orig_ea(x); + } + break; + case rAbsXi: + out_symbol('('); + out_addr_near(x); // jmp, jsr + out_symbol(','); + out_char(' '); + out_register("X"); + out_symbol(')'); + break; + default: + goto err; + } + break; + case o_void: + return 0; + default: + err: + warning("out: %a: bad optype %d", insn.ea, x.type); + break; + } + return 1; +} + + +//---------------------------------------------------------------------- +static bool forced_print(flags_t F, int reg) +{ + return (reg == rFm || reg == rFx) && is_func(F); +} + +//---------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +void m65816_t::m65816_assumes(outctx_t &ctx) +{ + ea_t ea = ctx.insn_ea; + char buf[MAXSTR]; + char *ptr = buf; + char *end = buf + sizeof(buf); + segment_t *seg = getseg(ea); + bool seg_started = (ea == seg->start_ea); + for ( int reg=ph.reg_first_sreg; reg <= ph.reg_last_sreg; reg++ ) + { + if ( reg == rCs ) + continue; + sreg_range_t srrange; + if ( !get_sreg_range(&srrange, ea, reg) ) + continue; + sel_t curval = srrange.val; + if ( seg_started || srrange.start_ea == ea ) + { + sreg_range_t prev; + bool prev_exists = get_sreg_range(&prev, ea - 1, reg); + if ( seg_started + || (prev_exists && prev.val != curval) + || forced_print(ctx.F, reg) ) + { + if ( reg == rFm || reg == rFx ) + { + ctx.gen_printf(0, ".%c%d", reg == rFm ? 'A' : 'I', curval > 0 ? 8 : 16); + } + else + { + if ( ptr != buf ) + APPCHAR(ptr, end, ' '); + ptr += qsnprintf(ptr, end-ptr, "%s=%a", ph.reg_names[reg], curval); + } + } + } + } + if ( ptr != buf ) + ctx.gen_cmt_line("%s", buf); +} + +//---------------------------------------------------------------------- +void out_m65816_t::out_insn(void) +{ + out_mnemonic(); + out_one_operand(0); + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void m65816_t::m65816_header(outctx_t &ctx) const +{ + ctx.gen_cmt_line("%s Processor: %s", ash.cmnt, inf_get_procname().c_str()); + ctx.gen_cmt_line("%s Target assembler: %s", ash.cmnt, ash.name); + if ( ash.header != NULL ) + for ( const char *const *ptr=ash.header; *ptr != NULL; ptr++ ) + ctx.flush_buf(*ptr,0); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Srange) could be made const +void m65816_t::m65816_segstart(outctx_t &ctx, segment_t *Srange) const +{ + qstring name; + get_visible_segm_name(&name, Srange); + if ( ash.uflag & UAS_SECT ) + { + ctx.gen_printf(0, COLSTR("%s: .section",SCOLOR_ASMDIR), name.c_str()); + } + else + { + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s.segment %s",SCOLOR_ASMDIR), + (ash.uflag & UAS_NOSEG) ? ash.cmnt : "", + name.c_str()); + if ( ash.uflag & UAS_SELSG ) + ctx.flush_buf(name.c_str(), DEFAULT_INDENT); + if ( ash.uflag & UAS_CDSEG ) + ctx.flush_buf(COLSTR("CSEG",SCOLOR_ASMDIR), DEFAULT_INDENT); // XSEG - eXternal memory + } + if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) + { + ea_t org = ctx.insn_ea - get_segm_base(Srange); + if ( org != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), org); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s",SCOLOR_ASMDIR), ash.origin, buf); + } + } +} + +//-------------------------------------------------------------------------- +void m65816_t::m65816_footer(outctx_t &ctx) const +{ + char buf[MAXSTR]; + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + char *ptr = buf; + char *end = buf + sizeof(buf); + APPEND(ptr, end, ash.end); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + if ( ash.uflag & UAS_NOENS ) + APPEND(ptr, end, ash.cmnt); + APPCHAR(ptr, end, ' '); + APPEND(ptr, end, name.begin()); + } + ctx.flush_buf(buf, DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} diff --git a/idasdk76/module/65816/reg.cpp b/idasdk76/module/65816/reg.cpp new file mode 100644 index 0000000..111e96c --- /dev/null +++ b/idasdk76/module/65816/reg.cpp @@ -0,0 +1,705 @@ + +#include <ida.hpp> +#include <idp.hpp> +#include <segregs.hpp> +#include <diskio.hpp> + +#include "m65816.hpp" +int data_id; + +#include "../../ldr/snes/addr.cpp" +//-------------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "A", // Accumulator + "X", // Index + "Y", // Index + "S", // Stack register (used?) + "cs", + "ds", + + "B", // Data bank + "D", // Direct page register (used?) + + "m", // Holds accumulator-is-8-bits flag + "x", // Holds indices-are-8-bits flag + "e", // Holds emulation mode flag + + "PB" // Program bank +}; + + +// --------------------------------------------------------------------------- +ea_t m65816_t::xlat(ea_t address) +{ + return sa->xlat(address); +} + +// --------------------------------------------------------------------------- +m65816_t::m65816_t() +{ + cartridge = new SuperFamicomCartridge; + sa = new snes_addr_t; +} + +// --------------------------------------------------------------------------- +m65816_t::~m65816_t() +{ + delete cartridge; + cartridge = nullptr; + delete sa; + sa = nullptr; +} + +// --------------------------------------------------------------------------- +// Handler for: get_autocmt. +// Will possibly store a comment in 'buf', +// depending on whether an autocmt is deemed necessary +// for the current line. +// +// For the moment this will just print, in a user-friendly +// way, information about the addressing mode, if needed. +static bool make_insn_cmt(qstring *buf, const insn_t &insn) +{ + uint8 opcode = get_byte(insn.ea); + const struct opcode_info_t &opcode_info = get_opcode_info(opcode); + static const bool addressing_info_required[] = + { + false, // ABS + false, // ABS_IX, + false, // ABS_IY, + false, // ABS_IX_INDIR, + false, // ABS_INDIR, + false, // ABS_INDIR_LONG, + false, // ABS_LONG, + false, // ABS_LONG_IX, + false, // ACC, + true, // BLK_MOV, + false, // DP, + false, // DP_IX, + false, // DP_IY, + false, // DP_IX_INDIR, + false, // DP_INDIR, + false, // DP_INDIR_LONG, + false, // DP_INDIR_IY, + false, // DP_INDIR_LONG_IY, + false, // IMM, + false, // IMPLIED, + true, // PC_REL, + true, // PC_REL_LONG, + false, // STACK_ABS, + false, // STACK_DP_INDIR, + false, // STACK_INT, + false, // STACK_PC_REL, + false, // STACK_PULL, + false, // STACK_PUSH, + false, // STACK_RTI, + false, // STACK_RTL, + false, // STACK_RTS, + false, // STACK_REL, + false // STACK_REL_INDIR_IY, + }; + + if ( !addressing_info_required[opcode_info.addr] ) + return false; + + const struct addrmode_info_t &addrmode_info = AddressingModes[opcode_info.addr]; + *buf = addrmode_info.name; + return true; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case idb_event::sgr_changed: + { + ea_t start_ea = va_arg(va, ea_t); + ea_t dummy = va_arg(va, ea_t); qnotused(dummy); + int regnum = va_arg(va, int); + sel_t value = va_arg(va, sel_t); + if ( regnum == rB ) + { +// sel_t d2 = va_arg(va, sel_t); qnotused(d2); + if ( value == BADSEL ) + split_sreg_range(start_ea, rDs, BADSEL, SR_auto); + else + split_sreg_range(start_ea, rDs, value << 12, SR_auto); + } + else if ( regnum == rPB ) + { + uint16 offset = start_ea & 0xffff; + ea_t newEA = pm.xlat((value << 16) + offset); + if ( start_ea != newEA ) + warning("Inconsistent program bank number ($%02X:%04X != $%02X:%04X)", + uint32(start_ea >> 16), + offset, + uint8(value), + offset); + } + } + break; + } + return 0; +} + +//---------------------------------------------------------------------- +void m65816_t::load_from_idb() +{ + cartridge->read_hash(helper); + //cartridge.print(); + if ( !sa->addr_init(*cartridge) ) + warning("Unsupported mapper: %s", cartridge->mapper_string()); + ioh.restore_device(IORESP_NONE); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(m65816_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi m65816_t::on_event(ssize_t msgid, va_list va) +{ + int retcode = 1; + switch ( msgid ) + { + case processor_t::ev_init: + hook_event_listener(HT_IDB, &idb_listener, &LPH); + helper.create(PROCMOD_NODE_NAME); + break; + case processor_t::ev_term: + unhook_event_listener(HT_IDB, &idb_listener); + clr_module_data(data_id); + break; + case processor_t::ev_newprc: + break; + case processor_t::ev_creating_segm: + { + segment_t *sptr = va_arg(va, segment_t *); + + // default DS is equal to CS + sptr->defsr[rDs - ph.reg_first_sreg] = sptr->sel; + + // detect SNES bank 0 + if ( xlat(0) == (sptr->start_ea & 0xff0000) ) + { + // initial bank must be $00 (especially important on HiROM) + // Example: Donkey Kong Country 2 - Emulation_mode_RESET + sptr->defsr[rB - ph.reg_first_sreg] = 0; + sptr->defsr[rPB - ph.reg_first_sreg] = 0; + } + else + { + // otherwise, set the default bank number from EA + uint8 pb = sptr->start_ea >> 16; + sptr->defsr[rB - ph.reg_first_sreg] = pb; + sptr->defsr[rPB - ph.reg_first_sreg] = pb; + } + } + break; + case processor_t::ev_newfile: + { + cartridge->read_hash(helper); + //cartridge.print(); + if ( !sa->addr_init(*cartridge) ) + warning("Unsupported mapper: %s", cartridge->mapper_string()); + + const char *device_ptr = nullptr; + if ( cartridge->has_superfx ) + device_ptr = "superfx"; + else if ( cartridge->has_sa1 ) + device_ptr = "sa1"; + else if ( cartridge->has_cx4 ) + device_ptr = "cx4"; + else if ( cartridge->has_spc7110 ) + device_ptr = "spc7110"; + else if ( cartridge->has_sdd1 ) + device_ptr = "sdd1"; + else if ( cartridge->has_sharprtc ) + device_ptr = "sharprtc"; + else if ( cartridge->has_epsonrtc ) + device_ptr = "epsonrtc"; + else if ( cartridge->has_obc1 ) + device_ptr = "obc1"; + else if ( cartridge->has_dsp1 ) + device_ptr = "dsp1"; + else if ( cartridge->has_dsp2 ) + device_ptr = "dsp2"; + else if ( cartridge->has_dsp3 ) + device_ptr = "dsp3"; + else if ( cartridge->has_dsp4 ) + device_ptr = "dsp4"; + else if ( cartridge->has_st010 ) + device_ptr = "st010"; + else if ( cartridge->has_st011 ) + device_ptr = "st011"; + else if ( cartridge->has_st018 ) + device_ptr = "st018"; + qstring loader_device; + if ( device_ptr == nullptr ) + { + ssize_t len = helper.hashstr(&loader_device, "device"); + if ( len <= 0 ) + device_ptr = "65816"; + else + device_ptr = loader_device.c_str(); + } + ioh.set_device_name(device_ptr, IORESP_ALL); + + set_default_sreg_value(NULL, rFm, 1); + set_default_sreg_value(NULL, rFx, 1); + set_default_sreg_value(NULL, rFe, 1); + set_default_sreg_value(NULL, rD, 0); + + // see processor_t::ev_creating_segm for the following registers + //set_default_sreg_value(NULL, rPB, 0); + //set_default_sreg_value(NULL, rB, 0); + //set_default_sreg_value(NULL, rDs, 0); + + if ( inf_get_start_ip() != BADADDR ) + { + ea_t reset_ea = xlat(inf_get_start_ip()); + ea_t sea = getseg(reset_ea)->start_ea; + split_sreg_range(reset_ea, rFm, get_sreg(sea, rFm), SR_auto); + split_sreg_range(reset_ea, rFx, get_sreg(sea, rFx), SR_auto); + split_sreg_range(reset_ea, rFe, get_sreg(sea, rFe), SR_auto); + split_sreg_range(reset_ea, rPB, 0, SR_auto); + split_sreg_range(reset_ea, rB, 0, SR_auto); + split_sreg_range(reset_ea, rD, get_sreg(sea, rD), SR_auto); + } + } + break; + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + { + load_from_idb(); + if ( msgid == processor_t::ev_oldfile ) + { // read rommode_t for backward compatibility + nodeidx_t mode = helper.hashval_long("rommode_t"); + if ( mode != 0 ) + { + switch ( mode ) + { + case 0x20: + cartridge->mapper = SuperFamicomCartridge::LoROM; + break; + + case 0x21: + cartridge->mapper = SuperFamicomCartridge::HiROM; + break; + } + helper.hashdel("rommode_t"); + cartridge->write_hash(helper); + } + } + } + break; + case processor_t::ev_get_autocmt: + { + qstring *buf = va_arg(va, qstring *); + const insn_t *insn = va_arg(va, insn_t *); + if ( make_insn_cmt(buf, *insn) ) + retcode = 1; + } + break; + case processor_t::ev_may_be_func: + { + const insn_t *insn = va_arg(va, insn_t *); + retcode = 0; + ea_t cref_addr; + for ( cref_addr = get_first_cref_to(insn->ea); + cref_addr != BADADDR; + cref_addr = get_next_cref_to(insn->ea, cref_addr) ) + { + uint8 opcode = get_byte(cref_addr); + const struct opcode_info_t &opinfo = get_opcode_info(opcode); + if ( opinfo.itype == M65816_jsl + || opinfo.itype == M65816_jsr + || opinfo.itype == M65816_jml ) + { + retcode = 100; + break; + } + } + } + break; + case processor_t::ev_is_call_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + const struct opcode_info_t &opinfo = get_opcode_info(get_byte(insn->ea)); + if ( opinfo.itype == M65816_jsr + || opinfo.itype == M65816_jsl ) + retcode = 1; + else + retcode = -1; + } + break; + case processor_t::ev_is_ret_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + const struct opcode_info_t &opinfo = get_opcode_info(get_byte(insn->ea)); + if ( opinfo.itype == M65816_rti + || opinfo.itype == M65816_rtl + || opinfo.itype == M65816_rts ) + retcode = 1; + else + retcode = -1; + } + break; + case processor_t::ev_is_indirect_jump: + { + const insn_t *insn = va_arg(va, insn_t *); + const struct opcode_info_t &opinfo = get_opcode_info(get_byte(insn->ea)); + if ( opinfo.itype == M65816_jmp + || opinfo.itype == M65816_jml ) + { + if ( opinfo.addr == ABS_INDIR + || opinfo.addr == ABS_IX_INDIR + || opinfo.addr == ABS_INDIR_LONG ) + retcode = 2; + else + retcode = 1; + } + else + retcode = 0; + } + break; + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m65816_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m65816_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + m65816_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m65816_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + + default: + retcode = 0; + break; + } + return retcode; +} + + +//----------------------------------------------------------------------- +// CA65 ASSEMBLER +// +// http://www.cc65.org/doc/ca65-4.html#ss4.1 +//----------------------------------------------------------------------- +static const asm_t ca65asm = +{ + AS_COLON | ASH_HEXF4, // Assembler features + 0, // User-defined flags + "CA65 ASSEMBLER", // Name + 0, + NULL, // headers + ".ORG", // origin directive + ".END", // end directive + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "\\'", // special symbols in char and string constants + + ".BYTE", // ascii string directive + ".BYTE", // byte directive + ".WORD", // word directive +}; + +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const char *const ps_headers[] = +{ + ".code", + NULL +}; + +static const asm_t pseudosam = +{ + AS_COLON | ASH_HEXF1 | AS_N2CHR | AS_NOXRF, + UAS_SELSG, + "PseudoSam by PseudoCode", + 0, + ps_headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".rs %s", // uninited arrays + ".equ", // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988 +//----------------------------------------------------------------------- +static const asm_t svasm = +{ + AS_COLON | ASH_HEXF4, + UAS_NOSEG, + "SVENSON ELECTRONICS 6502/65C02 ASSEMBLER - V.1.0 - MAY, 1988", + 0, + NULL, // headers + "* = ", + ".END", + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "\\'", // special symbols in char and string constants + + ".BYTE", // ascii string directive + ".BYTE", // byte directive + ".WORD", // word directive +}; + +//----------------------------------------------------------------------- +// TASM assembler definiton +//----------------------------------------------------------------------- +static const asm_t tasm = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_NOENS | UAS_NOSEG, + "Table Driven Assembler (TASM) by Speech Technology Inc.", + 0, + NULL, // headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".text", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".block %s", // uninited arrays + ".equ", + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + "and", // and + "or", // or + NULL, // xor + "not", // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//----------------------------------------------------------------------- +// Avocet assembler definiton +//----------------------------------------------------------------------- +static const asm_t avocet = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_NOENS | UAS_NOSEG, + "Avocet Systems 2500AD 6502 Assembler", + 0, + NULL, // headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".fcc", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".ds %s", // uninited arrays +}; + +static const asm_t *const asms[] = +{ + &ca65asm, + + // 6502 asm_t; imported from the 6502 CPU module. + &svasm, + &tasm, + &pseudosam, + &avocet, + NULL +}; + +//----------------------------------------------------------------------- +#define FAMILY "MOS Technology 658xx series:" +static const char *const shnames[] = { "m65816", "m65c816", NULL }; +static const char *const lnames[] = { FAMILY"MOS Technology 65816", "MOS Technology 65C816", NULL }; + +static const uchar retcode_1[] = { 0x60 }; // RTS +static const uchar retcode_2[] = { 0x40 }; // RTI +static const uchar retcode_3[] = { 0x6b }; // RTL + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- + +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_65C816, // id + // flag + PR_SEGS + | PR_SEGTRANS, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Register names + qnumber(RegNames), // Number of registers + + rCs, // first segreg + rPB, // last segreg + 0, // size of a segment register + rCs, // number of CS register + rDs, // number of DS register + + NULL, // No known code start sequences + retcodes, + + 0, + M65816_last, + Instructions, // instruc + 3, // int tbyte_size; -- doesn't exist + + { 0, 0, 0, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + M65816_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; + diff --git a/idasdk75/module/78k0/78k0.cfg b/idasdk76/module/78k0/78k0.cfg similarity index 100% rename from idasdk75/module/78k0/78k0.cfg rename to idasdk76/module/78k0/78k0.cfg diff --git a/idasdk76/module/78k0/78k0.hpp b/idasdk76/module/78k0/78k0.hpp new file mode 100644 index 0000000..9149010 --- /dev/null +++ b/idasdk76/module/78k0/78k0.hpp @@ -0,0 +1,72 @@ +/* + * NEC 78K0 processor module for IDA. + * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#ifndef _78K0_HPP +#define _78K0_HPP + +#include <ida.hpp> +#include <idp.hpp> + +#include "../idaidp.hpp" +#include "ins.hpp" +#include "../iohandler.hpp" + +struct nec78k0_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool flow = false; // stop flag + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit); + void N78K_header(outctx_t &ctx); + int N78K_emu(const insn_t &insn); + void handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn); + void N78K_segstart(outctx_t &ctx, segment_t *Sarea) const; + void N78K_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +bool idaapi out_opnd(outctx_t &ctx, const op_t &x); + +extern int data_id; +#define PROCMOD_NODE_NAME "$ 78k0" +#define PROCMOD_NAME nec78k0 + +// subtype of out format +#define FormOut specflag1 +// o_mem, o_near +#define FORM_OUT_VSK (0x01) +// o_mem, o_reg, o_near +#define FORM_OUT_SKOBA (0x02) +// o_reg +#define FORM_OUT_PLUS (0x04) +#define FORM_OUT_DISP (0x08) +#define FORM_OUT_REG (0x10) +// o_bit +#define FORM_OUT_HL (0x04) +#define FORM_OUT_PSW (0x08) +#define FORM_OUT_A (0x10) +#define FORM_OUT_SFR (0x20) +#define FORM_OUT_S_ADDR (0x40) +// o_reg +#define SecondReg specflag2 + +// bit operand +#define o_bit o_idpspec0 + +//------------------------------------------------------------------------ +enum N78K_registers { rX, rA, rC, rB, rE, rD, rL, rH, rAX, rBC, rDE, rHL, + rPSW, rSP, bCY, rRB0, rRB1, rRB2, rRB3, + rVcs, rVds }; + +//------------------------------------------------------------------------ +int idaapi N78K_ana(insn_t *_insn); +int idaapi N78K_emu(const insn_t &insn); + +#endif + diff --git a/idasdk76/module/78k0/ana.cpp b/idasdk76/module/78k0/ana.cpp new file mode 100644 index 0000000..d2be1f6 --- /dev/null +++ b/idasdk76/module/78k0/ana.cpp @@ -0,0 +1,1491 @@ +/* + * NEC 78K0 processor module for IDA. + * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "78k0.hpp" + +//---------------------------------------------------------------------- +inline uint32 Get_Data_16bits(insn_t &insn) +{ + uint32 low = insn.get_next_byte(); + uint32 high = insn.get_next_byte(); + return low | (high << 8); +} + +//---------------------------------------------------------------------- +inline void Operand_Sfr(insn_t &insn, op_t &x) +{ + x.type = o_mem; + x.dtype = dt_byte; + x.offb = (uchar)insn.size; + x.value = + x.addr = 0xFF00 + insn.get_next_byte(); +} + +//---------------------------------------------------------------------- +inline void Operand_Registr(op_t &x, int rReg, uchar Flags) +{ + x.type = o_reg; + x.reg = (uint16)rReg; + x.FormOut = Flags; +} + +//---------------------------------------------------------------------- +inline void Operand_Bit(op_t &x, uchar TypeOrd, int Bit) +{ + x.type = o_bit; + x.FormOut = TypeOrd; + x.value = Bit & 7; + x.offb = 0; +} + +//---------------------------------------------------------------------- +// convert short address to full address +inline uint32 GetFullAddress(uchar addr) +{ + if ( addr < 0x20 ) + return 0xFF00 + addr; + return 0xFE00 + addr; +} + +//---------------------------------------------------------------------- +inline void Operand_Saddr(op_t &x, uchar addr, const insn_t &insn) +{ + x.type = o_mem; + x.dtype = dt_byte; + x.offb = uchar(insn.size - 1); + x.addr = GetFullAddress(addr); + x.value = x.addr; +} + +//---------------------------------------------------------------------- +inline void Operand_Saddr1(insn_t &insn, op_t &x) +{ + Operand_Saddr(x, insn.get_next_byte(), insn); +} + +//---------------------------------------------------------------------- +inline void Operand_SaddrSP(insn_t &insn, op_t &x) +{ + uchar bt = insn.get_next_byte(); + if ( bt == 0x1C ) + { + Operand_Registr(x, rSP, 0); + } + else + { + Operand_Saddr(x, bt, insn); + x.dtype = dt_word; + } +} + +//---------------------------------------------------------------------- +inline void Operand_SaddrPSW(insn_t &insn, op_t &x) +{ + uchar bt = insn.get_next_byte(); + if ( bt == 0x1E ) + Operand_Registr(x, rPSW, 0); + else + Operand_Saddr(x, bt, insn); +} + +//---------------------------------------------------------------------- +inline void Operand_SA_Bit(insn_t &insn, op_t &x, uchar Bit) +{ + uchar bt; + x.offb = (uchar)insn.size; + x.type = o_bit; + x.dtype = dt_byte; + bt = insn.get_next_byte(); + if ( bt == 0x1E ) + { + x.FormOut = FORM_OUT_PSW; + } + else + { + x.addr = GetFullAddress(bt); + x.FormOut = FORM_OUT_S_ADDR; + } + x.value = Bit & 7; +} + +//---------------------------------------------------------------------- +inline void Operand_SFR_Bit(insn_t &insn, op_t &x, uchar Bit) +{ + x.offb = (uchar)insn.size; + x.addr = 0xFF00 + insn.get_next_byte(); + x.type = o_bit; + x.FormOut = FORM_OUT_SFR; + x.value = Bit & 7; +} + +//---------------------------------------------------------------------- +inline void Operand_Data_8bits(op_t &x, uchar Data) +{ + x.type = o_imm; + x.addr = Data; + x.value = Data; + x.dtype = dt_byte; +} + +//---------------------------------------------------------------------- +inline void Operand_Data_8bitsI(insn_t &insn, op_t &x) +{ + x.offb = (uchar)insn.size; + Operand_Data_8bits(x, insn.get_next_byte()); +} + +//---------------------------------------------------------------------- +inline void Operand_Data_16bitsI(insn_t &insn, op_t &x) +{ + x.type = o_imm; + x.dtype = dt_word; + x.offb = (uchar)insn.size; + x.value = Get_Data_16bits(insn); + x.addr = x.value; +} + +//---------------------------------------------------------------------- +inline void Operand_Addr16(op_t &x, uint32 Res, char Target_data_type) +{ + x.type = o_mem; + x.value = Res; + x.addr = Res; + x.dtype = Target_data_type; + x.FormOut = FORM_OUT_VSK; +} + +//---------------------------------------------------------------------- +inline void Operand_Addr16I(insn_t &insn, op_t &x, char Target_data_type) +{ + x.offb = (uchar)insn.size; + Operand_Addr16(x, Get_Data_16bits(insn),Target_data_type); +} + +//---------------------------------------------------------------------- +// [HL+XXX] +inline void Operand_HL_OffI(insn_t &insn, op_t &x) +{ + Operand_Registr(x, rHL, FORM_OUT_SKOBA | FORM_OUT_PLUS | FORM_OUT_DISP); + x.offb = (uchar)insn.size; + x.addr = x.value = insn.get_next_byte(); +} + +//---------------------------------------------------------------------- +// [HL+Reg] +inline void Operand_HL_OffReg(op_t &x, int rReg) +{ + Operand_Registr(x, rHL, FORM_OUT_SKOBA | FORM_OUT_PLUS | FORM_OUT_REG); + x.SecondReg = (uchar)rReg; +} + +//---------------------------------------------------------------------- +inline void Operand_NearByteI(insn_t &insn, op_t &x) +{ + x.type = o_near; + x.offb = (uchar)insn.size; + x.addr = insn.ip + (signed char)insn.get_next_byte(); + x.addr += insn.size; + x.value = x.addr; +} + +//---------------------------------------------------------------------- +static const uchar icode[16] = +{ + NEC_78K_0_add, NEC_78K_0_sub, NEC_78K_0_addc, + NEC_78K_0_subc, NEC_78K_0_cmp, NEC_78K_0_and, + NEC_78K_0_or, NEC_78K_0_xor, NEC_78K_0_xch +}; + +//---------------------------------------------------------------------- +static int Opcode_61(insn_t &insn) +{ + uchar code = insn.get_next_byte(); + uchar nib = (code >> 4) & 0xF; + uchar cd = code & 0xF; + + // sel RBx + // 11R1 R000 + if ( (code & 0xD7) == 0xD0 ) + { + insn.itype = NEC_78K_0_sel; + Operand_Registr(insn.Op1, + (rRB0 + ((code >>4) & 0x2)) | ((code>>3) & 0x1), + 0); + return insn.size; + } + if ( (code & 0x80) == 0 ) + { + // add A, r ( 0000 1RRR ) + // add r, A ( 0000 0RRR ) + // sub A, r ( 0001 1RRR ) + // sub r, A ( 0001 0RRR ) + // addc A, r ( 0010 1RRR ) + // addc r, A ( 0010 0RRR ) + // subc A, r ( 0011 1RRR ) + // subc r, A ( 0011 0RRR ) + // cmp A, r ( 0100 1RRR ) + // cmp r, A ( 0100 0RRR ) + // and A, r ( 0101 1RRR ) + // and r, A ( 0101 0RRR ) + // or A, r ( 0110 1RRR ) + // or r, A ( 0110 0RRR ) + // xor A, r ( 0111 1RRR ) + // xor r, A ( 0111 0RRR ) + insn.itype = icode[nib]; + if ( code & 0x8 ) + { + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, code & 0x7, 0); + } + else + { + Operand_Registr(insn.Op1, code & 0x7, 0); + Operand_Registr(insn.Op2, rA, 0); + } + return insn.size; + } + + switch ( code ) + { + // adjba ( 0110 0001 1000 0000 ) + case 0x80: + insn.itype = NEC_78K_0_adjba; + break; + // adjbs ( 0110 0001 1000 0000 ) + case 0x90: + insn.itype = NEC_78K_0_adjbs; + break; + default: + switch ( cd ) + { + // mov1 A.bit, CY + case 0x9: + insn.itype = NEC_78K_0_mov1; + Operand_Bit(insn.Op1, FORM_OUT_A, nib); + Operand_Registr(insn.Op2, bCY, 0); + break; + + case 0xA: + insn.itype = NEC_78K_0_set1; + Operand_Bit(insn.Op1, FORM_OUT_A, nib); + break; + + case 0xB: + insn.itype = NEC_78K_0_clr1; + Operand_Bit(insn.Op1, FORM_OUT_A, nib); + break; + + // mov1 CY, A.bit + case 0xC: + insn.itype = NEC_78K_0_mov1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_A, nib); + break; + case 0xD: + insn.itype = NEC_78K_0_and1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_A, nib); + break; + case 0xE: + insn.itype = NEC_78K_0_or1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_A, nib); + break; + case 0xF: + insn.itype = NEC_78K_0_xor1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_A, nib); + break; + default: + return 0; + } + } + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_71(insn_t &insn) +{ + uchar code = insn.get_next_byte(); + uchar nib = code >> 4; + // analyze the high bit by 1 + switch ( code & 0x8F ) + { + // mov1 [HL].bit, CY + case 0x81: + insn.itype = NEC_78K_0_mov1; + Operand_Bit(insn.Op1, FORM_OUT_HL, nib); + Operand_Registr(insn.Op2, bCY, 0); + break; + // set1 [HL].bit + case 0x82: + insn.itype = NEC_78K_0_set1; + Operand_Bit(insn.Op1, FORM_OUT_HL, nib); + break; + // clr1 [HL].bit + case 0x83: + insn.itype = NEC_78K_0_clr1; + Operand_Bit(insn.Op1, FORM_OUT_HL, nib); + break; + // mov1 CY,[HL].bit + case 0x84: + insn.itype = NEC_78K_0_mov1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_HL, nib); + break; + // and1 CY,[HL].bit + case 0x85: + insn.itype = NEC_78K_0_and1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_HL, nib); + break; + // or1 CY,[HL].bit + case 0x86: + insn.itype = NEC_78K_0_or1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_HL, nib); + break; + // xor1 CY,[HL].bit + case 0x87: + insn.itype = NEC_78K_0_xor1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_HL, nib); + break; + + // mov1 CY, A.bit + case 0x8C: + insn.itype = NEC_78K_0_mov1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_Bit(insn.Op2, FORM_OUT_A, nib); + break; + + case 0x0: + switch ( nib & 7 ) + { + case 0: insn.itype = NEC_78K_0_STOP; break; + case 1: insn.itype = NEC_78K_0_HALT; break; + default: return 0; + } + break; + // mov1 PSW.bit, CY + // mov1 saddr.bit, CY + case 0x1: + insn.itype = NEC_78K_0_mov1; + Operand_SA_Bit(insn, insn.Op1, nib); + Operand_Registr(insn.Op2, bCY, 0); + break; + // mov1 CY, saddr.bit + // mov1 CY, PSW.bit + case 0x4: + insn.itype = NEC_78K_0_mov1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_SA_Bit(insn, insn.Op2, nib); + break; + // and1 CY, saddr.bit + // and1 CY, PSW.bit + case 0x5: + insn.itype = NEC_78K_0_and1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_SA_Bit(insn, insn.Op2, nib); + break; + // or1 CY, addr.bit + // or1 CY, PSW.bit + case 0x6: + insn.itype = NEC_78K_0_or1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_SA_Bit(insn, insn.Op2, nib); + break; + // xor1 CY, addr.bit + // xor1 CY, PSW.bit + case 0x7: + insn.itype = NEC_78K_0_xor1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_SA_Bit(insn, insn.Op2, nib); + break; +//????? +// case 0x8: +// insn.itype = NEC_78K_0_EI; +// insn.get_next_byte(); +// break; + + // mov1 sfr.bit, CY + case 0x9: + insn.itype = NEC_78K_0_mov1; + Operand_SFR_Bit(insn, insn.Op1, nib); + Operand_Registr(insn.Op2, bCY, 0); + break; + // set1 sfr.bit + case 0xA: + insn.itype = NEC_78K_0_set1; + Operand_SFR_Bit(insn, insn.Op1, nib); + break; + // clr1 sfr.bit + case 0xB: + insn.itype = NEC_78K_0_clr1; + Operand_SFR_Bit(insn, insn.Op1, nib); + break; + + // and1 CY, sfr.bit + case 0xD: + insn.itype = NEC_78K_0_and1; + Operand_Registr(insn.Op1, bCY, 0); + Operand_SFR_Bit(insn, insn.Op2, nib); + break; + // bad instruction + default: + return 0; + } + return insn.size; +} +//---------------------------------------------------------------------- +static int Opcode_31(insn_t &insn) +{ + uchar code = insn.get_next_byte(); + uchar nib = (code >> 4) & 0xF; + switch ( code ) + { + case 0x0B:// add A,[HL+B] ( 0000 1011 ) + case 0x1B:// sub A,[HL+B] ( 0001 1011 ) + case 0x2B:// addc A,[HL+B] ( 0010 1011 ) + case 0x3B:// subc A,[HL+B] ( 0011 1011 ) + case 0x4B:// cmp A,[HL+B] ( 0100 1011 ) + case 0x5B:// and A,[HL+B] ( 0101 1011 ) + case 0x6B:// or A,[HL+B] ( 0110 1011 ) + case 0x7B:// xor A,[HL+B] ( 0111 1011 ) + case 0x8B:// xch A,[HL+B] ( 1000 1011 ) + insn.itype = icode[nib]; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffReg(insn.Op2, rB); + break; + + case 0x0A:// add A,[HL+C] ( 0000 1010 ) + case 0x1A:// sub A,[HL+C] ( 0001 1010 ) + case 0x2A:// addc A,[HL+C] ( 0010 1010 ) + case 0x3A:// subc A,[HL+C] ( 0011 1010 ) + case 0x4A:// cmp A,[HL+C] ( 0100 1010 ) + case 0x5A:// and A,[HL+C] ( 0101 1010 ) + case 0x6A:// or A,[HL+C] ( 0110 1010 ) + case 0x7A:// xor A,[HL+C] ( 0111 1010 ) + case 0x8A:// xch A,[HL+C] ( 1000 1010 ) + insn.itype = icode[nib]; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffReg(insn.Op2, rC); + break; + + case 0x98:// br AX (0011 0001 1001 1000) + insn.itype = NEC_78K_0_br; + Operand_Registr(insn.Op1, rAX, 0); + break; + + case 0x88:// mulu X ( 0011 0001 1000 1000) + insn.itype = NEC_78K_0_mulu; + Operand_Registr(insn.Op1, rX, 0); + break; + + case 0x82:// divuw X ( 0011 0001 1000 0010) + insn.itype = NEC_78K_0_divuw; + Operand_Registr(insn.Op1, rC, 0); + break; + + case 0x90:// ror4 [HL] ( 0011 0001 1001 0000) + insn.itype = NEC_78K_0_ror4; + Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); + break; + + case 0x80:// rol4 [HL] ( 0011 0001 1000 0000) + insn.itype = NEC_78K_0_rol4; + Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); + break; + + default: + switch ( code & 0x8F ) + { + // sfr.bit, $addr16 + // A.bit, $addr16 + // PSW.bit,$addr16 + // 0xxx 0001 + case 0x1: + insn.itype = NEC_78K_0_btclr; + Operand_SA_Bit(insn, insn.Op1, nib); + Operand_NearByteI(insn, insn.Op2); + break; + + // 0xxx 0011 + case 0x3: + insn.itype = NEC_78K_0_bf; + Operand_SA_Bit(insn, insn.Op1, nib); + Operand_NearByteI(insn, insn.Op2); + break; + + // 0xxx 0101 + case 0x5: + insn.itype = NEC_78K_0_btclr; + Operand_SFR_Bit(insn, insn.Op1, nib); + Operand_NearByteI(insn, insn.Op2); + break; + // 0xxx 0110 + case 0x6: + insn.itype = NEC_78K_0_bt; + Operand_SFR_Bit(insn, insn.Op1, nib); + Operand_NearByteI(insn, insn.Op2); + break; + // 0xxx 0111 + case 0x7: + insn.itype = NEC_78K_0_bf; + Operand_SFR_Bit(insn, insn.Op1, nib); + Operand_NearByteI(insn, insn.Op2); + break; + + // 0xxx 1101 + case 0xD: + insn.itype = NEC_78K_0_btclr; + Operand_Bit(insn.Op1, FORM_OUT_A, nib); + Operand_NearByteI(insn, insn.Op2); + break; + + // 0xxx 1110 + case 0xE: + insn.itype = NEC_78K_0_bt; + Operand_Bit(insn.Op1, FORM_OUT_A, nib); + Operand_NearByteI(insn, insn.Op2); + break; + + // 0xxx 1111 - bf + case 0xF: + insn.itype = NEC_78K_0_bf; + Operand_Bit(insn.Op1, FORM_OUT_A, nib); + Operand_NearByteI(insn, insn.Op2); + break; + // 1xxx 01xx + // btclr + case 0x85: + insn.itype = NEC_78K_0_btclr; + Operand_Bit(insn.Op1, FORM_OUT_HL, nib); + Operand_NearByteI(insn, insn.Op2); + break; + // bt + case 0x86: + insn.itype = NEC_78K_0_bt; + Operand_Bit(insn.Op1, FORM_OUT_HL, nib); + Operand_NearByteI(insn, insn.Op2); + break; + // bf + case 0x87: + insn.itype = NEC_78K_0_bf; + Operand_Bit(insn.Op1, FORM_OUT_HL, nib); + Operand_NearByteI(insn, insn.Op2); + break; + + default: + return 0; + } + } + return insn.size; +} + +//---------------------------------------------------------------------- +int idaapi N78K_ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + uchar code = insn.get_next_byte(); + switch ( code ) + { + // nop ( 0000 0000 ) + case 0x00: + insn.itype = NEC_78K_0_nop; + break; + // not1 CY ( 0000 0001 ) + case 0x01: + insn.itype = NEC_78K_0_not1; + Operand_Registr(insn.Op1, bCY, 0); + break; + // movw AX,!addr16 ( 0000 0010) + case 0x02: + insn.itype = NEC_78K_0_movw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Addr16I(insn, insn.Op2, dt_word); + break; + // movw !addr16, AX ( 0000 0011) + case 0x03: + insn.itype = NEC_78K_0_movw; + Operand_Addr16I(insn, insn.Op1, dt_word); + Operand_Registr(insn.Op2, rAX, 0); + break; + // dbnz saddr,$addr16 (0000 0100) + case 0x04: + insn.itype = NEC_78K_0_dbnz; + Operand_Saddr1(insn, insn.Op1); + Operand_NearByteI(insn, insn.Op2); + break; + // xch A,[DE] ( 0000 0101 ) + case 0x05: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op1, rDE, FORM_OUT_SKOBA); + break; + // Bad command + case 0x06: + return 0; + // xch A,[HL] ( 0000 0111 ) + case 0x07: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); + break; + // add A, addr16 + case 0x08: + insn.itype = NEC_78K_0_add; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // add A, [HL+off] + case 0x09: + insn.itype = NEC_78K_0_add; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // set1 saddr.bit (0xxx 1010) + // set1 PSW.bit (0xxx 1010) + case 0x0A: + case 0x1A: + case 0x2A: + case 0x3A: + case 0x4A: + case 0x5A: + case 0x6A: + case 0x7A: + insn.itype = NEC_78K_0_set1; + Operand_SA_Bit(insn, insn.Op1, code >> 4); + // convert set PSW.EI to EI + if ( code == 0x7A && insn.Op1.FormOut == FORM_OUT_PSW ) + { + insn.itype = NEC_78K_0_EI; + insn.Op1.type = o_void; + } + break; + // clr1 saddr.bit (0BBB 1011) + // clr1 PSW.bit (0BBB 1011) + case 0x0B: + case 0x1B: + case 0x2B: + case 0x3B: + case 0x4B: + case 0x5B: + case 0x6B: + case 0x7B: + insn.itype = NEC_78K_0_clr1; + Operand_SA_Bit(insn, insn.Op1, code >> 4); + // convert clr PSW.EI to DI + if ( code == 0x7B && insn.Op1.FormOut == FORM_OUT_PSW ) + { + insn.itype = NEC_78K_0_DI; + insn.Op1.type = o_void; + } + break; + // call11 (0x800-0xFFF) + case 0x0C: + case 0x1C: + case 0x2C: + case 0x3C: + case 0x4C: + case 0x5C: + case 0x6C: + case 0x7C: + insn.itype = NEC_78K_0_callf; + insn.Op1.type = o_near; + insn.Op1.addr = (uint32(( code & 0xF0 )<<8) | (uint32)insn.get_next_byte()) + 0x800; + insn.Op1.FormOut = FORM_OUT_VSK; + break; + // add A, #byte + case 0x0D: + insn.itype = NEC_78K_0_add; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // add A, saddr + case 0x0E: + insn.itype = NEC_78K_0_add; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // add A, [HL] + case 0x0F: + insn.itype = NEC_78K_0_add; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // movw rp,#word + case 0x10: + case 0x12: + case 0x14: + case 0x16: + insn.itype = NEC_78K_0_movw; + Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); + Operand_Data_16bitsI(insn, insn.Op2); + break; + // mov saddr,#byte ( 0001 0001 SADDR DATA) + // mov PSW,#byte ( 0001 0001 SADDR DATA) + case 0x11: + insn.itype = NEC_78K_0_mov; + Operand_SaddrPSW(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // case 0x12 - movw rp,#word + // mov sfr,#byte ( 0001 0011 SFR DATA) + case 0x13: + insn.itype = NEC_78K_0_mov; + Operand_Sfr(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // case 0x14 - movw rp,#word + // Bad Opcode + case 0x15: + return 0; + // case 0x16 - movw rp,#word + // Bad Opcode + case 0x17: + return 0; + // sub A, addr16 + case 0x18: + insn.itype = NEC_78K_0_sub; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // sub A, [HL+off] + case 0x19: + insn.itype = NEC_78K_0_sub; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // sub A, #byte + case 0x1D: + insn.itype = NEC_78K_0_sub; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // sub A, saddr + case 0x1E: + insn.itype = NEC_78K_0_sub; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // sub A, [HL] + case 0x1F: + insn.itype = NEC_78K_0_sub; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // set1 CY ( 0010 0000 ) + case 0x20: + insn.itype = NEC_78K_0_set1; + Operand_Registr(insn.Op1, bCY, 0); + break; + // clr1 CY ( 0010 0001 ) + case 0x21: + insn.itype = NEC_78K_0_clr1; + Operand_Registr(insn.Op1, bCY, 0); + break; + // push PSW ( 0010 0010 ) + case 0x22: + insn.itype = NEC_78K_0_push; + Operand_Registr(insn.Op1, rPSW, 0); + break; + // pop PSW ( 0010 0011 ) + case 0x23: + insn.itype = NEC_78K_0_pop; + Operand_Registr(insn.Op1, rPSW, 0); + break; + // ror A,1 ( 0010 0100 ) + case 0x24: + insn.itype = NEC_78K_0_ror; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bits(insn.Op2, 1); + break; + // rorc A,1 ( 0010 0101 ) + case 0x25: + insn.itype = NEC_78K_0_rorc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bits(insn.Op2, 1); + break; + // rol A,1 ( 0010 0110 ) + case 0x26: + insn.itype = NEC_78K_0_rol; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bits(insn.Op2, 1); + break; + // rolc A,1 ( 0010 0111 ) + case 0x27: + insn.itype = NEC_78K_0_rolc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bits(insn.Op2, 1); + break; + // addc A, addr16 + case 0x28: + insn.itype = NEC_78K_0_addc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // addc A, [HL+off] + case 0x29: + insn.itype = NEC_78K_0_addc; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // addc A, #byte + case 0x2D: + insn.itype = NEC_78K_0_addc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // addc A, saddr + case 0x2E: + insn.itype = NEC_78K_0_addc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // addc A, [HL] + case 0x2F: + insn.itype = NEC_78K_0_addc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // xch A, r (0011 0RRR) + case 0x30: + case 0x32: + case 0x33: + case 0x34: + case 0x35: + case 0x36: + case 0x37: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, code & 7, 0); + break; + // xxx A,[HL+B], xxx A,[HL+C] + case 0x31: + return Opcode_31(insn); + // subc A, addr16 + case 0x38: + insn.itype = NEC_78K_0_subc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // subc A, [HL+off] + case 0x39: + insn.itype = NEC_78K_0_subc; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // subc A, #byte + case 0x3D: + insn.itype = NEC_78K_0_subc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // subc A, saddr + case 0x3E: + insn.itype = NEC_78K_0_subc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // subc A, [HL] + case 0x3F: + insn.itype = NEC_78K_0_subc; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // inc r (0100 0RRR) + case 0x40: + case 0x41: + case 0x42: + case 0x43: + case 0x44: + case 0x45: + case 0x46: + case 0x47: + insn.itype = NEC_78K_0_inc; + Operand_Registr(insn.Op1, code & 7, 0); + break; + // cmp A, addr16 + case 0x48: + insn.itype = NEC_78K_0_cmp; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // cmp A, [HL+off] + case 0x49: + insn.itype = NEC_78K_0_cmp; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // cmp A, #byte + case 0x4D: + insn.itype = NEC_78K_0_cmp; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // cmp A, saddr + case 0x4E: + insn.itype = NEC_78K_0_cmp; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // cmp A, [HL] + case 0x4F: + insn.itype = NEC_78K_0_cmp; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // dec r (0101 0RRR) + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + insn.itype = NEC_78K_0_dec; + Operand_Registr(insn.Op1, code & 7, 0); + break; + // and A, addr16 + case 0x58: + insn.itype = NEC_78K_0_and; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // and A, [HL+off] + case 0x59: + insn.itype = NEC_78K_0_and; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // and A, #byte + case 0x5D: + insn.itype = NEC_78K_0_and; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // and A, saddr + case 0x5E: + insn.itype = NEC_78K_0_and; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // and A, [HL] + case 0x5F: + insn.itype = NEC_78K_0_and; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // mov A, r (0110 0RRR) + case 0x60: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, code & 7, 0); + break; + case 0x61: + return Opcode_61(insn); + // or A, addr16 + case 0x68: + insn.itype = NEC_78K_0_or; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // or A, [HL+off] + case 0x69: + insn.itype = NEC_78K_0_or; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // or A, #byte + case 0x6D: + insn.itype = NEC_78K_0_or; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // or A, saddr + case 0x6E: + insn.itype = NEC_78K_0_or; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // or A, [HL] + case 0x6F: + insn.itype = NEC_78K_0_or; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // mov r, A (0111 0RRR) + case 0x70: + case 0x72: + case 0x73: + case 0x74: + case 0x75: + case 0x76: + case 0x77: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, code & 7, 0); + Operand_Registr(insn.Op2, rA, 0); + break; + case 0x71: + return Opcode_71(insn); + // xor A, addr16 + case 0x78: + insn.itype = NEC_78K_0_xor; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // xor A, [HL+off] + case 0x79: + insn.itype = NEC_78K_0_xor; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // xor A, #byte + case 0x7D: + insn.itype = NEC_78K_0_xor; + Operand_Registr(insn.Op1, rA, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // xor A, saddr + case 0x7E: + insn.itype = NEC_78K_0_xor; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // xor A, [HL] + case 0x7F: + insn.itype = NEC_78K_0_xor; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // incw rp (1000 0PP0) + case 0x80: + case 0x82: + case 0x84: + case 0x86: + insn.itype = NEC_78K_0_incw; + Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); + break; + // inc saddr ( 1000 0001 SADDR) + case 0x81: + insn.itype = NEC_78K_0_inc; + Operand_Saddr1(insn, insn.Op1); + break; + // xch A, saddr ( 1000 0011 SADDR ) + case 0x83: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_Saddr1(insn, insn.Op2); + break; + // mov A,[DE] ( 1000 0101) + case 0x85: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rDE, FORM_OUT_SKOBA); + break; + // mov A,[HL] ( 1000 0111) + case 0x87: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_Registr(insn.Op2, rHL, FORM_OUT_SKOBA); + break; + // add saddr, #byte + case 0x88: + insn.itype = NEC_78K_0_add; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // movw AX, SP ( 1000 1001 0001 1100 ) + // movw AX, SADDRP ( 1000 1001 SADDRP ) + case 0x89: + insn.itype = NEC_78K_0_movw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_SaddrSP(insn, insn.Op2); + break; + // dbnz C,$addr16 (1000 1010 JDISP ) + case 0x8A: + insn.itype = NEC_78K_0_dbnz; + Operand_Registr(insn.Op1, rC, 0); + Operand_NearByteI(insn, insn.Op2); + break; + // dbnz B,$addr16 (1000 1011 JDISP ) + case 0x8B: + insn.itype = NEC_78K_0_dbnz; + Operand_Registr(insn.Op1, rB, 0); + Operand_NearByteI(insn, insn.Op2); + break; + // bt xxxxxxxx + case 0x8C: + case 0x9C: + case 0xAC: + case 0xBC: + case 0xCC: + case 0xDC: + case 0xEC: + case 0xFC: + insn.itype = NEC_78K_0_bt; + Operand_SA_Bit(insn, insn.Op1, code >> 4); + Operand_NearByteI(insn, insn.Op2); + break; + // bc $addr16 (1000 1101 JDISP ) + case 0x8D: + insn.itype = NEC_78K_0_bc; + Operand_NearByteI(insn, insn.Op1); + break; + // mov A,!addr16 ( 1000 1110 LOW HIGH) + case 0x8E: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // ret ( 1000 1111 ) + case 0x8F: + insn.itype = NEC_78K_0_reti; + break; + // decw + case 0x90: + case 0x92: + case 0x94: + case 0x96: + insn.itype = NEC_78K_0_decw; + Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); + break; + // dec saddr ( 1001 0001 SADDR) + case 0x91: + insn.itype = NEC_78K_0_dec; + Operand_Saddr1(insn, insn.Op1); + break; + // xch A, sfr ( 1001 0011 SFR ) + case 0x93: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_Sfr(insn, insn.Op2); + break; + // mov [DE], A ( 1001 0101) + case 0x95: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rDE, FORM_OUT_SKOBA); + Operand_Registr(insn.Op2, rA, 0); + break; + + // mov [HL], A ( 1001 0111) + case 0x97: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rHL, FORM_OUT_SKOBA); + Operand_Registr(insn.Op2, rA, 0); + break; + // sub saddr, #byte + case 0x98: + insn.itype = NEC_78K_0_sub; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // movw SP, AX ( 1001 1001 0001 1100 ) + // movw SADDRP, AX ( 1001 1001 SADDRP ) + case 0x99: + insn.itype = NEC_78K_0_movw; + Operand_SaddrSP(insn, insn.Op1); + Operand_Registr(insn.Op2, rAX, 0); + break; + // call !addr16 ( 1001 1010 LOW HIGH ) + case 0x9A: + insn.itype = NEC_78K_0_call; + insn.Op1.FormOut = FORM_OUT_VSK;// outputting char '!' + insn.Op1.type = o_near; + insn.Op1.dtype = dt_word; + insn.Op1.offb = (uchar)insn.size; + insn.Op1.addr = Get_Data_16bits(insn); + break; + // br !addr16 (1111 1011 LOW HIGH) + case 0x9B: + insn.itype = NEC_78K_0_br; + insn.Op1.FormOut = FORM_OUT_VSK; + insn.Op1.type = o_near; + insn.Op1.dtype = dt_word; + insn.Op1.offb = (uchar)insn.size; + insn.Op1.value = + insn.Op1.addr = Get_Data_16bits(insn); + break; + // case 9C - bt + // bnc $addr16 (1001 1101 JDISP ) + case 0x9D: + insn.itype = NEC_78K_0_bnc; + Operand_NearByteI(insn, insn.Op1); + break; + // mov !addr16, A ( 1001 1110 LOW HIGH) + case 0x9E: + insn.itype = NEC_78K_0_mov; + Operand_Addr16I(insn, insn.Op1, dt_byte); + Operand_Registr(insn.Op2, rA, 0); + break; + // retb ( 1001 1111 ) + case 0x9F: + insn.itype = NEC_78K_0_retb; + break; + // mov r,#byte (1010 0RRR) + case 0xA0: + case 0xA1: + case 0xA2: + case 0xA3: + case 0xA4: + case 0xA5: + case 0xA6: + case 0xA7: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, code & 7, 0); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // addc saddr, #byte + case 0xA8: + insn.itype = NEC_78K_0_addc; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // movw AX, SFR ( 1010 1001 SFR ) + case 0xA9: + insn.itype = NEC_78K_0_movw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Sfr(insn, insn.Op2); + break; + // mov A,[HL+C] ( 1010 1010) + case 0xAA: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffReg(insn.Op2, rC); + break; + // mov A,[HL+B] ( 1010 1011) + case 0xAB: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffReg(insn.Op2, rB); + break; + // case 0xAC - bt + // bz $addr16 (1010 1101 JDISP ) + case 0xAD: + insn.itype = NEC_78K_0_bz; + Operand_NearByteI(insn, insn.Op1); + break; + // mov A,[HL+byte] ( 1010 1110) + case 0xAE: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // ret ( 1010 1111 ) + case 0xAF: + insn.itype = NEC_78K_0_ret; + break; + // pop + case 0xB0: + case 0xB2: + case 0xB4: + case 0xB6: + insn.itype=NEC_78K_0_pop; + Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); + break; + // Push + case 0xB1: + case 0xB3: + case 0xB5: + case 0xB7: + insn.itype=NEC_78K_0_push; + Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); + break; + // subc saddr, #byte + case 0xB8: + insn.itype = NEC_78K_0_subc; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // movw SFR, AX ( 1011 1001 SFR ) + case 0xB9: + insn.itype = NEC_78K_0_movw; + Operand_Sfr(insn, insn.Op1); + Operand_Registr(insn.Op2, rAX, 0); + break; + // mov [HL+B], A ( 1011 1010) + case 0xBA: + insn.itype = NEC_78K_0_mov; + Operand_HL_OffReg(insn.Op1, rC); + Operand_Registr(insn.Op2, rA, 0); + break; + // mov [HL+B], A ( 1011 1011) + case 0xBB: + insn.itype = NEC_78K_0_mov; + Operand_HL_OffReg(insn.Op1, rB); + Operand_Registr(insn.Op2, rA, 0); + break; + // case 0xBC - bt + // bnz $addr16 (1011 1101 JDISP ) + case 0xBD: + insn.itype = NEC_78K_0_bnz; + Operand_NearByteI(insn, insn.Op1); + break; + // mov [HL+byte], A ( 1011 1110) + case 0xBE: + insn.itype = NEC_78K_0_mov; + Operand_HL_OffI(insn, insn.Op1); + Operand_Registr(insn.Op2, rA, 0); + break; + // brk ( 1011 1111 ) + case 0xBF: + insn.itype = NEC_78K_0_brk; + break; + // movw AX, rp (1100 0PP0) + case 0xC0: + case 0xC2: + case 0xC4: + case 0xC6: + insn.itype = NEC_78K_0_movw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Registr(insn.Op2, rAX+((code>>1)&7), 0); + break; + // cmp saddr, #byte + case 0xC8: + insn.itype = NEC_78K_0_cmp; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // addw AX,#word ( 1100 1010 LOW HIGH) + case 0xCA: + insn.itype = NEC_78K_0_addw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Data_16bitsI(insn, insn.Op2); + break; + // case 0xCC - bt + // xch A,!addr ( 1100 1110 LOW HIGH ) + case 0xCE: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_Addr16I(insn, insn.Op2, dt_byte); + break; + // movw rp, AX (1101 0PP0) + case 0xD0: + case 0xD2: + case 0xD4: + case 0xD6: + insn.itype = NEC_78K_0_movw; + Operand_Registr(insn.Op1, rAX+((code>>1)&7), 0); + Operand_Registr(insn.Op2, rAX, 0); + break; + // and saddr, #byte + case 0xD8: + insn.itype = NEC_78K_0_and; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // subw AX,#word ( 1101 1010 LOW HIGH) + case 0xDA: + insn.itype = NEC_78K_0_subw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Data_16bitsI(insn, insn.Op2); + break; + // case 0xDC - bt + // xch A,[HL+byte] ( 1101 1110 DATA ) + case 0xDE: + insn.itype = NEC_78K_0_xch; + Operand_Registr(insn.Op1, rA, 0); + Operand_HL_OffI(insn, insn.Op2); + break; + // xchw AX, rp (1101 0PP0) + case 0xE0: + case 0xE2: + case 0xE4: + case 0xE6: + insn.itype = NEC_78K_0_xchw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Registr(insn.Op2, rAX+((code>>1)&7), 0); + break; + // or saddr, #byte + case 0xE8: + insn.itype = NEC_78K_0_or; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // cmpw AX,#word ( 1110 1010 LOW HIGH) + case 0xEA: + insn.itype = NEC_78K_0_cmpw; + Operand_Registr(insn.Op1, rAX, 0); + Operand_Data_16bitsI(insn, insn.Op2); + break; + // case 0xEC - bt + // movw SP,#word ( 1110 1110 0001 1100 LOW HIGH) + // movw saddrp,#word ( 1110 1110 SADDR LOW HIGH) + case 0xEE: + insn.itype = NEC_78K_0_movw; + Operand_SaddrSP(insn, insn.Op1); + Operand_Data_16bitsI(insn, insn.Op2); + break; + // mov A, saddr ( 1111 0000 A SADDRR ) + // mov A, PSW ( 1111 0000 A PSW ) + case 0xF0: + insn.itype = NEC_78K_0_mov; + Operand_SaddrPSW(insn, insn.Op2); + Operand_Registr(insn.Op1, rA, 0); + break; + // mov saddr, A ( 1111 0010 SADDRR A) + // mov PSW, A ( 1111 0010 SADDRR A) + case 0xF2: + insn.itype = NEC_78K_0_mov; + Operand_SaddrPSW(insn, insn.Op1); + Operand_Registr(insn.Op2, rA, 0); + break; + // mov A, sfr ( 1111 0100 A SFR ) + case 0xF4: + insn.itype = NEC_78K_0_mov; + Operand_Registr(insn.Op1, rA, 0); + Operand_Sfr(insn, insn.Op2); + break; + // mov saddr, A ( 1111 0110 SFR A) + case 0xF6: + insn.itype = NEC_78K_0_mov; + Operand_Sfr(insn, insn.Op1); + Operand_Registr(insn.Op2, rA, 0); + break; + // xor saddr, #byte + case 0xF8: + insn.itype = NEC_78K_0_xor; + Operand_Saddr1(insn, insn.Op1); + Operand_Data_8bitsI(insn, insn.Op2); + break; + // br $addr16 (1111 01010 JDISP) + case 0xFA: + insn.itype = NEC_78K_0_br; + Operand_NearByteI(insn, insn.Op1); + break; + // case 0xFC - bt + // movw sfr,#word ( 1111 1110 SFR LOW HIGH) + case 0xFE: + insn.itype = NEC_78K_0_movw; + Operand_Sfr(insn, insn.Op1); + Operand_Data_16bitsI(insn, insn.Op2); + break; + // callt + case 0xC1:case 0xC3:case 0xC5:case 0xC7:case 0xC9:case 0xCB:case 0xCD:case 0xCF: + case 0xD1:case 0xD3:case 0xD5:case 0xD7:case 0xD9:case 0xDB:case 0xDD:case 0xDF: + case 0xE1:case 0xE3:case 0xE5:case 0xE7:case 0xE9:case 0xEB:case 0xED:case 0xEF: + case 0xF1:case 0xF3:case 0xF5:case 0xF7:case 0xF9:case 0xFB:case 0xFD:case 0xFF: + insn.itype = NEC_78K_0_callt; + Operand_Addr16(insn.Op1,0x40 + (code & 0x3E), dt_word); + // change format + insn.Op1.FormOut = FORM_OUT_SKOBA; + break; + // unknown code - return error + default: + return 0; + } + return insn.size; +} diff --git a/idasdk76/module/78k0/emu.cpp b/idasdk76/module/78k0/emu.cpp new file mode 100644 index 0000000..9d7aa3f --- /dev/null +++ b/idasdk76/module/78k0/emu.cpp @@ -0,0 +1,106 @@ +/* + * NEC 78K0 processor module for IDA. + * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "78k0.hpp" + +//---------------------------------------------------------------------- +// usage/change of operands +void nec78k0_t::handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn) +{ + ea_t ea = map_code_ea(insn, x.addr, x.n); + ea_t ev = map_code_ea(insn, x.value, x.n); + switch ( x.type ) + { + // unused! + case o_void: + break; + + case o_reg: + if ( forced_op ) + break; + if ( is_off(get_flags(insn.ea), x.n) ) + insn.add_dref(ev, x.n, dr_O); + break; + + case o_imm: // immediate can't be changed + if ( !isload ) + goto badTouch; + // set immediate flag + set_immd(insn.ea); + // if not forced and not offset + if ( !forced_op && is_off(get_flags(insn.ea), x.n) ) + insn.add_dref(ev, x.offb, dr_O); // it's an offset! + break; + + case o_mem: + insn.create_op_data(ea, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + break; + + + case o_near:// a call or jump + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + // add a code xref + insn.add_cref(ea, x.offb, fl_CN); + flow = func_does_return(ea); + } + else + { + insn.add_cref(ea, x.offb, fl_JN); + } + break; + + case o_bit: + switch ( x.FormOut ) + { + case FORM_OUT_S_ADDR: + case FORM_OUT_SFR: + insn.create_op_data(ea, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + break; + } + break; + // other - show a warning + default: +badTouch: + warning("%a %s,%d: bad optype %d", + insn.ea, insn.get_canon_mnem(ph), + x.n, x.type); + break; + } +} + + +//---------------------------------------------------------------------- +// emulator +int nec78k0_t::N78K_emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + // get operand types + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + + flow = (Feature & CF_STOP) == 0; + + // handle xrefs for the two operands + if ( Feature & CF_USE1 ) + handle_operand(insn.Op1, flag1, 1, insn); + if ( Feature & CF_USE2 ) + handle_operand(insn.Op2, flag2, 1, insn); + // add xref to the queue + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + // handle changing operands + if ( Feature & CF_CHG1 ) + handle_operand(insn.Op1, flag1, 0, insn); + if ( Feature & CF_CHG2 ) + handle_operand(insn.Op2, flag2, 0, insn); + // if not stop, continue with the next instruction + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + return 1; +} diff --git a/idasdk75/module/78k0/ins.cpp b/idasdk76/module/78k0/ins.cpp similarity index 100% rename from idasdk75/module/78k0/ins.cpp rename to idasdk76/module/78k0/ins.cpp diff --git a/idasdk75/module/78k0/ins.hpp b/idasdk76/module/78k0/ins.hpp similarity index 100% rename from idasdk75/module/78k0/ins.hpp rename to idasdk76/module/78k0/ins.hpp diff --git a/idasdk76/module/78k0/makefile b/idasdk76/module/78k0/makefile new file mode 100644 index 0000000..144f855 --- /dev/null +++ b/idasdk76/module/78k0/makefile @@ -0,0 +1,57 @@ +PROC=78k0 +CONFIGS=78k0.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k0.hpp ana.cpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k0.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k0.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k0.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp 78k0.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/78k0/out.cpp b/idasdk76/module/78k0/out.cpp similarity index 100% rename from idasdk75/module/78k0/out.cpp rename to idasdk76/module/78k0/out.cpp diff --git a/idasdk76/module/78k0/reg.cpp b/idasdk76/module/78k0/reg.cpp new file mode 100644 index 0000000..5ce7fe3 --- /dev/null +++ b/idasdk76/module/78k0/reg.cpp @@ -0,0 +1,288 @@ +/* + * NEC 78K0 processor module for IDA. + * Copyright (c) 2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "78k0.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//---------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "X", "A", "C", "B", "E", "D", "L", "H", "AX", "BC", "DE","HL", + "PSW", "SP", "CY", "RB0", "RB1", "RB2", "RB3", + "cs", "ds" +}; + +//---------------------------------------------------------------------- +static const asm_t nec78k0 = +{ + AS_COLON | ASB_BINF4 | AS_N2CHR, + 0, + "NEC 78K0 Assembler", + 0, + NULL, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".dw", // word directive + ".dd", // no double words + NULL, // no qwords + NULL, // oword (16 bytes) + NULL, // no float + NULL, // no double + NULL, // no tbytes + NULL, // no packreal + "#d dup(#v)", //".db.#s(b,w) #d,#v", // #h - header(.byte,.word) + // #d - size of array + // #v - value of array elements + // #s - size specifier + ".rs %s",// uninited data (reserve space) + ".equ", + NULL, // seg prefix + "$", // a_curip + + NULL, // returns function header line + NULL, // returns function footer line + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + + '(', ')',// lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//---------------------------------------------------------------------- +#define FAMILY "NEC series:" +static const char *const shnames[] = +{ + "78k0", + NULL +}; +static const char *const lnames[] = +{ + FAMILY"NEC 78K0", + NULL +}; + +static const asm_t *const asms[] = +{ + &nec78k0, + NULL +}; + +//-------------------------------------------------------------------------- +static const uchar retcNEC78K0_0[] = { 0xAF }; // ret +static const uchar retcNEC78K0_1[] = { 0x9F }; // retb +static const uchar retcNEC78K0_2[] = { 0x8F }; // reti +static const uchar retcNEC78K0_3[] = { 0xBF }; // brk +static const bytes_t retcodes[] = +{ + { sizeof(retcNEC78K0_0), retcNEC78K0_0 }, + { sizeof(retcNEC78K0_1), retcNEC78K0_1 }, + { sizeof(retcNEC78K0_2), retcNEC78K0_2 }, + { sizeof(retcNEC78K0_3), retcNEC78K0_3 }, + { 0, NULL } +}; + + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(nec78k0_t)); + return 0; +} + +//------------------------------------------------------------------ +bool nec78k0_t::nec_find_ioport_bit(outctx_t &ctx, int port, int bit) +{ + + const ioport_bit_t *b = find_ioport_bit(ioh.ports, port, bit); + if ( b != NULL && !b->name.empty() ) + { + ctx.out_line(b->name.c_str(), COLOR_IMPNAME); + return true; + } + return false; +} + +//---------------------------------------------------------------------- + +void set_dopolnit_info(void) +{ + for ( int banknum = 0; banknum < 4; banknum++ ) + { + for ( int Regs = 0; Regs < 8; Regs++ ) + { + char temp[100]; + qsnprintf(temp, sizeof(temp), "Bank%d_%s", banknum, RegNames[Regs]); + ushort Addr = ushort(0xFEE0+((banknum*8)+Regs)); + set_name(Addr, temp); + qsnprintf(temp, sizeof(temp), "Internal high-speed RAM (Bank %d registr %s)", banknum, RegNames[Regs]); + set_cmt(Addr, temp, true); + } + } +} + +//---------------------------------------------------------------------- +void nec78k0_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +ssize_t idaapi nec78k0_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_be(false); + inf_set_gen_lzero(true); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + set_dopolnit_info(); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + N78K_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + N78K_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + N78K_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return N78K_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return N78K_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_NEC_78K0, + // flag + PRN_HEX + | PR_SEGTRANS + | PR_SEGS, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs, rVds, + 2, // size of a segment register + rVcs, rVds, + NULL, + retcodes, + 0, NEC_78K_0_last, + Instructions, // instruc + 3, + { 0,0,0,0 }, + 0, + NULL, // micro virtual mashine +}; diff --git a/idasdk75/module/78k0s/78k0s.cfg b/idasdk76/module/78k0s/78k0s.cfg similarity index 100% rename from idasdk75/module/78k0s/78k0s.cfg rename to idasdk76/module/78k0s/78k0s.cfg diff --git a/idasdk76/module/78k0s/78k_0s.hpp b/idasdk76/module/78k0s/78k_0s.hpp new file mode 100644 index 0000000..6c13f28 --- /dev/null +++ b/idasdk76/module/78k0s/78k_0s.hpp @@ -0,0 +1,94 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _NEC78K0S_HPP +#define _NEC78K0S_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include "../iohandler.hpp" + +struct nec78k0s_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit); + void nec78k0s_header(outctx_t &ctx); + int emu(const insn_t &insn); + void handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn); + void nec78k0s_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +bool idaapi out_opnd(outctx_t &ctx, const op_t &x); + +extern int data_id; +#define PROCMOD_NODE_NAME "$ 78k0s" +#define PROCMOD_NAME nec78k0s + +#define UAS_NOSPA 0x0001 // no space after comma +//#define UAS_ZVBIT 0x0002 // '*' prefixes name in bit command +//#define UAS_AREAS 0x0004 // '.area' segment directive +//#define UAS_CCR 0x0008 // "ccr" register is named "cc" +// // "dpr" register is named "dp" +// // "pcr" register is named "pc" +//#define UAS_ORA 0x0010 // ORAA is named ORA +// // ORAB is named ORB +//#define UAS_CODE 0x0020 // "code", "data", "bss" directives +//#define UAS_AUTOPC 0x0040 // Automatic relative addressing by PC +// // (no need to substract PC value) +//#define UAS_ALL 0x0080 // "all" keyword is recognized as +// // a synonim for all registers +//#define UAS_OS9 0x0100 // has OS9 directive +//---------------------------------------------------------------------- +// Redefine temporary names +// +#define exten segpref +#define xmode specflag1 +#define prepost specflag2 +#define addr16 specflag3 + +// bit operand +#define regmode specflag1 +#define regdata specflag2 + +// callt +#define form specflag1 + +#define o_bit o_idpspec0 +//------------------------------------------------------------------------ +enum nec_registers { rX, rA, rC, rB, rE, rD, rL, rH, rAX, rBC, rDE, rHL, + rPSW, rSP, rS, rCC, rDPR, + bCY, + Rcs, Rds }; + +enum bitOper { SADDR=0, SFR, A, PSW, HL, CY }; +//------------------------------------------------------------------------ +extern qstring deviceparams; +extern qstring device; + +struct ioport_bit_t; +bool nec_find_ioport_bit(outctx_t &ctx, int port, int bit); +uint32 Get_Data_16bits(); +//------------------------------------------------------------------------ +void idaapi nec78k0s_header(outctx_t &ctx); +void idaapi nec78k0s_footer(outctx_t &ctx); + +void idaapi nec78k0s_segstart(outctx_t &ctx, segment_t *seg); + +int idaapi ana(insn_t *_insn); +int idaapi emu(const insn_t &insn); + + +#endif + diff --git a/idasdk76/module/78k0s/ana.cpp b/idasdk76/module/78k0s/ana.cpp new file mode 100644 index 0000000..4c44eed --- /dev/null +++ b/idasdk76/module/78k0s/ana.cpp @@ -0,0 +1,1710 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "78k_0s.hpp" + +//---------------------------------------------------------------------- +inline uint32 sfr(uchar sfr_offset) +{ + return 0xFF00 + sfr_offset; +} +//---------------------------------------------------------------------- +inline uint32 saddr(uchar Saddr_offset) +{ + if ( Saddr_offset < 0x20 ) + return 0xFF00 + Saddr_offset; + else + return 0xFE00 + Saddr_offset; +} + +//---------------------------------------------------------------------- +inline void addr16(insn_t &insn, op_t &x) +{ + // x.offb = insn.size; + uint32 low = insn.get_next_byte(); + uint32 high = insn.get_next_byte(); + + // x.type = o_near; + x.addr = low | (high << 8); + x.addr16 = 1; +} + +//---------------------------------------------------------------------- +inline void jdisp(op_t &x, uchar addr, int previons_len, const insn_t &insn) +{ + x.type = o_near; + x.addr = insn.ip + (signed char)addr + previons_len; + // x.offb = insn.size - 1; +} + +//---------------------------------------------------------------------- +inline void imm16(insn_t &insn, op_t &x) +{ + x.type = o_imm; + x.dtype = dt_word; + uchar b1 = insn.get_next_byte(); + uchar b2 = insn.get_next_byte(); + x.value = b1 | (b2<<8); +} + +//---------------------------------------------------------------------- +int idaapi ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + + // get one byte + uchar code = insn.get_next_byte(); + + switch ( code ) + { + // Mnemonic Operand Instruction Code + // B1 B2 B3 B4 + case 0x00: + // ROR A, 1 0000 0000 + insn.itype = NEC_78K_0S_ror; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = 1; + insn.Op2.regmode = 1; + break; + + case 0x02: + // RORC A, 1 0000 0010 + insn.itype = NEC_78K_0S_rorc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = 1; + insn.Op2.regmode = 1; + break; + + case 0x04: + // CLR1 CY 0000 0100 + insn.itype = NEC_78K_0S_clr1; + insn.Op1.type = o_phrase; + insn.Op1.reg = bCY; + break; + + case 0x05: + // XCH A, saddr 0000 0101 Saddr-offset + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x06: + // NOT1 CY 0000 0110 + insn.itype = NEC_78K_0S_not1; + insn.Op1.type = o_phrase; + insn.Op1.reg = bCY; + break; + + case 0x07: + // XCH A, sfr 0000 0111 Sfr-offset + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = sfr(insn.get_next_byte()); + break; + + case 0x08: + // NOP 0000 1000 + insn.itype = NEC_78K_0S_nop; + break; + + case 0x0A: // All 0x0A commands + { + uchar code2 = insn.get_next_byte(); + switch ( code2 ) + { + case 0x88: + case 0x98: + case 0xA8: + case 0xB8: + case 0xC8: + case 0xD8: + case 0xE8: + case 0xF8: + // BT saddr.bit, $addr16 0000 1010 1 B2 B1 B0 1000 Saddr-offset jdisp + insn.itype = NEC_78K_0S_bt; + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op1.value = (code2>>4) & 0x07; + jdisp(insn.Op2, insn.get_next_byte(), 4, insn); + break; + + case 0x84: + case 0x94: + case 0xA4: + case 0xB4: + case 0xC4: + case 0xD4: + case 0xE4: + case 0xF4: + { + // BT sfr.bit, $addr16 0000 1010 1 B2 B1 B0 0100 Sfr-offset jdisp + // BT PSW.bit, $addr16 0000 1010 1 B2 B1 B0 1000 0001 1110 jdisp + insn.itype = NEC_78K_0S_bt; + uchar code3 = insn.get_next_byte(); + if ( code3 == 0x1E ) + { + insn.Op1.type = o_bit; + insn.Op1.reg = rPSW; + insn.Op1.value = (code2>>4)&0x07; + jdisp(insn.Op2, code3, 4, insn); + } + else + { + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = sfr(code3); + insn.Op1.value = (code2>>4) & 0x07; + jdisp(insn.Op2, insn.get_next_byte(), 4, insn); + } + } + break; + + case 0x08: + case 0x18: + case 0x28: + case 0x38: + case 0x48: + case 0x58: + case 0x68: + case 0x78: + { + // BF saddr.bit, $addr16 0000 1010 0 B2 B1 B0 1000 Saddr-offset jdisp + // BF PSW.bit, $addr16 0000 1010 0 B2 B1 B0 1000 0001 1110 jdisp + insn.itype = NEC_78K_0S_bf; + uchar code3=insn.get_next_byte(); + if ( code3 == 0x1E ) + { + insn.Op1.type = o_bit; + insn.Op1.reg = rPSW; + insn.Op1.value = (code2>>4)&0x07; + jdisp(insn.Op2, insn.get_next_byte(), 4, insn); + } + else + { + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(code3); + insn.Op1.value = (code2>>4) & 0x07; + jdisp(insn.Op2, insn.get_next_byte(), 4, insn); + } + } + break; + + case 0x04: + case 0x14: + case 0x24: + case 0x34: + case 0x44: + case 0x54: + case 0x64: + case 0x74: + // BF sfr.bit, $addr16 0000 1010 0 B2 B1 B0 0100 Sfr-offset jdisp + insn.itype = NEC_78K_0S_bf; + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = sfr(insn.get_next_byte()); + insn.Op1.value = (code2>>4) & 0x07; + jdisp(insn.Op2, insn.get_next_byte(), 4, insn); + break; + + case 0x00: + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + // BF A.bit, $addr16 0000 1010 0 B2 B1 B0 0000 jdisp + insn.itype = NEC_78K_0S_bf; + insn.Op1.type = o_bit; + insn.Op1.reg = rA; + insn.Op1.value = (code2>>4) & 0x07; + jdisp(insn.Op2, insn.get_next_byte(), 3, insn); + break; + + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + case 0xC0: + case 0xD0: + case 0xE0: + case 0xF0: + // BT A.bit, $addr16 0000 1010 1 B2 B1 B0 0000 jdisp + insn.itype = NEC_78K_0S_bt; + insn.Op1.type = o_bit; + insn.Op1.reg = rA; + insn.Op1.value = (code2>>4) & 0x07; + jdisp(insn.Op2, insn.get_next_byte(), 3, insn); + break; + + case 0x0A: + case 0x1A: + case 0x2A: + case 0x3A: + case 0x4A: + case 0x5A: + case 0x6A: + case 0x7A: + { + // SET1 saddr.bit 0000 1010 0 B2 B1 B0 1010 Saddr-offset + // SET1 PSW.bit 0000 1010 0 B2 B1 B0 1010 0001 1110 + // EI 0000 1010 0 1 1 1 1010 0001 1110 + uchar code3 = insn.get_next_byte(); + if ( code3 == 0x1E ) + { + if ( code2 == 0x7A ) // EI + { + insn.itype = NEC_78K_0S_EI; + } + else // SET1 PSW.bit + { + insn.itype = NEC_78K_0S_set1; + insn.Op1.type = o_bit; + insn.Op1.reg = rPSW; + insn.Op1.value = (code2>>4)&0x07; + } + } + else // SET1 saddr.bit + { + insn.itype = NEC_78K_0S_set1; + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(code3); + insn.Op1.value = (code2>>4)&0x07; + } + } + break; + + case 0x06: + case 0x16: + case 0x26: + case 0x36: + case 0x46: + case 0x56: + case 0x66: + case 0x76: + // SET1 sfr.bit 0000 1010 0 B2 B1 B0 0110 Sfr-offset + insn.itype = NEC_78K_0S_set1; + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = sfr(insn.get_next_byte()); + insn.Op1.value = (code2>>4)&0x07; + break; + + case 0x02: + case 0x12: + case 0x22: + case 0x32: + case 0x42: + case 0x52: + case 0x62: + case 0x72: + // SET1 A.bit 0000 1010 0 B2 B1 B0 0010 + insn.itype = NEC_78K_0S_set1; + insn.Op1.type = o_bit; + insn.Op1.reg = rA; + insn.Op1.value = (code2>>4)&0x07; + break; + + case 0x0E: + case 0x1E: + case 0x2E: + case 0x3E: + case 0x4E: + case 0x5E: + case 0x6E: + case 0x7E: + // SET1 [HL].bit 0000 1010 0 B2 B1 B0 1110 + insn.itype = NEC_78K_0S_set1; + insn.Op1.type = o_bit; + insn.Op1.reg = rHL; + insn.Op1.prepost = 1; + insn.Op1.value = (code2>>4)&0x07; + break; + + case 0x8A: + case 0x9A: + case 0xAA: + case 0xBA: + case 0xCA: + case 0xDA: + case 0xEA: + case 0xFA: + { + // CLR1 saddr.bit 0000 1010 1 B2 B1 B0 1010 Saddr-offset + // CLR1 PSW.bit 0000 1010 1 B2 B1 B0 1010 0001 1110 + // DI 0000 1010 1 1 1 1 1010 0001 1110 + uchar code3 = insn.get_next_byte(); + if ( code3 == 0x1E ) + { + if ( code2 == 0xFA ) // DI + { + insn.itype = NEC_78K_0S_DI; + } + else // CLR1 PSW.bit + { + insn.itype = NEC_78K_0S_clr1; + insn.Op1.type = o_bit; + insn.Op1.reg = rPSW; + insn.Op1.value = (code2>>4)&0x07; + } + } + else // CLR1 saddr.bit + { + insn.itype = NEC_78K_0S_clr1; + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(code3); + insn.Op1.value = (code2>>4)&0x07; + } + } + break; + + case 0x86: + case 0x96: + case 0xA6: + case 0xB6: + case 0xC6: + case 0xD6: + case 0xE6: + case 0xF6: + // CLR1 sfr.bit 0000 1010 1 B2 B1 B0 0110 Sfr-offset + insn.itype = NEC_78K_0S_clr1; + insn.Op1.type = o_bit; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = sfr(insn.get_next_byte()); + insn.Op1.value = (code2>>4)&0x07; + break; + + case 0x82: + case 0x92: + case 0xA2: + case 0xB2: + case 0xC2: + case 0xD2: + case 0xE2: + case 0xF2: + // CLR1 A.bit 0000 1010 1 B2 B1 B0 0010 + insn.itype = NEC_78K_0S_clr1; + insn.Op1.type = o_bit; + insn.Op1.reg = rA; + insn.Op1.value = (code2>>4)&0x07; + break; + + case 0x8E: + case 0x9E: + case 0xAE: + case 0xBE: + case 0xCE: + case 0xDE: + case 0xEE: + case 0xFE: + // CLR1 [HL].bit 0000 1010 1 B2 B1 B0 1110 + insn.itype = NEC_78K_0S_clr1; + insn.Op1.type = o_bit; + insn.Op1.reg = rHL; + insn.Op1.prepost = 1; + insn.Op1.value = (code2>>4)&0x07; + break; + + case 0xF1: + case 0xF3: + case 0xF5: + case 0xF7: + case 0xF9: + case 0xFB: + case 0xFD: + case 0xFF: + // MOV r, #byte 0000 1010 1111 R2R1R0 1 Data + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code2>>1)&0x07)+rX; + insn.Op2.type = o_imm; + insn.Op2.dtype = dt_byte; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x21: + case 0x25: + case 0x27: + case 0x29: + case 0x2B: + case 0x2D: + case 0x2F: + // MOV A, r 0000 1010 0010 R2R1R0 1 Except r = A. + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0xE1: + case 0xE5: + case 0xE7: + case 0xE9: + case 0xEB: + case 0xED: + case 0xEF: + // MOV r, A 0000 1010 1110 R2R1R0 1 Except r = A. + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code2>>1)&0x07)+rX; + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + break; + + case 0x05: + case 0x07: + case 0x09: + case 0x0B: + case 0x0D: + case 0x0F: + // XCH A, r 0000 1010 0000 R2R1R0 1 Except r = A, X. + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0x81: + case 0x83: + case 0x85: + case 0x87: + case 0x89: + case 0x8B: + case 0x8D: + case 0x8F: + // ADD A, r 0000 1010 1000 R2R1R0 1 + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0xA1: + case 0xA3: + case 0xA5: + case 0xA7: + case 0xA9: + case 0xAB: + case 0xAD: + case 0xAF: + // ADDC A, r 0000 1010 1010 R2R1R0 1 + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0x91: + case 0x93: + case 0x95: + case 0x97: + case 0x99: + case 0x9B: + case 0x9D: + case 0x9F: + // SUB A, r 0000 1010 1001 R2R1R0 1 + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0xB1: + case 0xB3: + case 0xB5: + case 0xB7: + case 0xB9: + case 0xBB: + case 0xBD: + case 0xBF: + // SUBC A, r 0000 1010 1011 R2R1R0 1 + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0x61: + case 0x63: + case 0x65: + case 0x67: + case 0x69: + case 0x6B: + case 0x6D: + case 0x6F: + // AND A, r 0000 1010 0110 R2R1R0 1 + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0x71: + case 0x73: + case 0x75: + case 0x77: + case 0x79: + case 0x7B: + case 0x7D: + case 0x7F: + // OR A, r 0000 1010 0111 R2R1R0 1 + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0x41: + case 0x43: + case 0x45: + case 0x47: + case 0x49: + case 0x4B: + case 0x4D: + case 0x4F: + // XOR A, r 0000 1010 0100 R2R1R0 1 + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0x11: + case 0x13: + case 0x15: + case 0x17: + case 0x19: + case 0x1B: + case 0x1D: + case 0x1F: + // CMP A, r 0000 1010 0001 R2R1R0 1 + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code2>>1)&0x07)+rX; + break; + + case 0xC1: + case 0xC3: + case 0xC5: + case 0xC7: + case 0xC9: + case 0xCB: + case 0xCD: + case 0xCF: + // INC r 0000 1010 1100 R2R1R0 1 + insn.itype = NEC_78K_0S_inc; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code2>>1)&0x07)+rX; + break; + + case 0xD1: + case 0xD3: + case 0xD5: + case 0xD7: + case 0xD9: + case 0xDB: + case 0xDD: + case 0xDF: + // DEC r 0000 1010 1101 R2R1R0 1 + insn.itype = NEC_78K_0S_dec; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code2>>1)&0x07)+rX; + break; + + default: + // return with the error ERROR + return 0; + } // END switch 0x0A commands + } + break; // END case 0x0A + + case 0x0B: + // XCH A, [DE] 0000 1011 + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rDE; + insn.Op2.prepost =1; + break; + + case 0x0C: + // HALT 0000 1100 + insn.itype = NEC_78K_0S_HALT; + break; + + case 0x0D: + // XCH A, [HL+byte] 0000 1101 Data + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x0E: + // STOP 0000 1110 + insn.itype = NEC_78K_0S_STOP; + break; + + case 0x0F: + // XCH A, [HL] 0000 1111 + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x10: + // ROL A, 1 0001 0000 + insn.itype = NEC_78K_0S_rol; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = 1; + insn.Op2.regmode = 1; + break; + + case 0x11: + // CMP saddr, #byte 0001 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x12: + // ROLC A, 1 0001 0010 + insn.itype = NEC_78K_0S_rolc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = 1; + insn.Op2.regmode = 1; + break; + + case 0x13: + // CMP A, #byte 0001 0011 Data + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x14: + // SET1 CY 0001 0100 + insn.itype = NEC_78K_0S_set1; + insn.Op1.type = o_phrase; + insn.Op1.reg = bCY; + break; + + case 0x15: + // CMP A, saddr 0001 0101 Saddr-offset + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x19: + // CMP A, !addr16 0001 1001 Low addr High addr + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0x1D: + // CMP A, [HL+byte] 0001 1101 Data + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x1F: + // CMP A, [HL] 0001 1111 + insn.itype = NEC_78K_0S_cmp; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x20: + // RET 0010 0000 + insn.itype = NEC_78K_0S_ret; + break; + + case 0x22: + // CALL !addr16 0010 0010 Low addr High addr + insn.itype = NEC_78K_0S_call; + // insn.Op1.offb = insn.size; + insn.Op1.type = o_near; + insn.Op1.addr16 = 1; + addr16(insn, insn.Op1); + break; + + case 0x24: + // RETI 0010 0100 + insn.itype = NEC_78K_0S_reti; + break; + + case 0x25: + { + // MOV A, PSW 0010 0101 00011110 + // MOV A, saddr 0010 0101 Saddr-offset + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + uchar tst = insn.get_next_byte(); + if ( tst == 0x1E ) + { + insn.Op2.type = o_reg; + insn.Op2.reg = rPSW; + } + else + { + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(tst); + } + } + break; + + case 0x27: + // MOV A, sfr 0010 0111 Sfr-offset + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = sfr(insn.get_next_byte()); + break; + + case 0x29: + // MOV A, !addr16 0010 1001 Low addr High addr + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0x2B: + // MOV A, [DE] 0010 1011 + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rDE; + insn.Op2.prepost = 1; + break; + + case 0x2C: + // POP PSW 0010 1100 + insn.itype = NEC_78K_0S_pop; + insn.Op1.type = o_phrase; + insn.Op1.reg = rPSW; + break; + + case 0x2D: + // MOV A, [HL+byte] 0010 1101 Data + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x2E: + // PUSH PSW 0010 1110 + insn.itype = NEC_78K_0S_push; + insn.Op1.type = o_phrase; + insn.Op1.reg = rPSW; + break; + + case 0x2F: + // MOV A, [HL] 0010 1111 + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x30: + // BR $addr16 0011 0000 jdisp + insn.itype = NEC_78K_0S_br; + jdisp(insn.Op1, insn.get_next_byte(), 2, insn); + break; + + case 0x32: + // DBNZ saddr, $addr16 0011 0010 Saddr-offset jdisp + insn.itype = NEC_78K_0S_dbnz; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + jdisp(insn.Op2, insn.get_next_byte(), 3, insn); + break; + + case 0x34: + // DBNZ C, $addr16 0011 0100 jdisp + insn.itype = NEC_78K_0S_dbnz; + insn.Op1.type = o_reg; + insn.Op1.reg = rC; + jdisp(insn.Op2, insn.get_next_byte(), 2, insn); + break; + + case 0x36: + // DBNZ B, $addr16 0011 0110 jdisp + insn.itype = NEC_78K_0S_dbnz; + insn.Op1.type = o_reg; + insn.Op1.reg = rB; + jdisp(insn.Op2, insn.get_next_byte(), 2, insn); + break; + + case 0x38: + // BC $addr16 0011 1000 jdisp + insn.itype = NEC_78K_0S_bc; + jdisp(insn.Op1, insn.get_next_byte(), 2, insn); + break; + + case 0x3A: + // BNC $addr16 0011 1010 jdisp + insn.itype = NEC_78K_0S_bnc; + jdisp(insn.Op1, insn.get_next_byte(), 2, insn); + break; + + case 0x3C: + // BZ $addr16 0011 1100 jdisp + insn.itype = NEC_78K_0S_bz; + jdisp(insn.Op1, insn.get_next_byte(), 2, insn); + break; + + case 0x3E: + // BNZ $addr16 0011 1110 jdisp + insn.itype = NEC_78K_0S_bnz; + jdisp(insn.Op1, insn.get_next_byte(), 2, insn); + break; + + case 0x41: + // XOR saddr, #byte 0100 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x43: + // XOR A, #byte 0100 0011 Data + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x45: + // XOR A, saddr 0100 0101 Saddr-offset + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x49: + // XOR A, !addr16 0100 1001 Low addr High addr + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0x4D: + // XOR A, [HL+byte] 0100 1101 Data + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x4F: + // XOR A, [HL] 0100 1111 + insn.itype = NEC_78K_0S_xor; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x61: + // AND saddr, #byte 0110 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x63: + // AND A, #byte 0110 0011 Data + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x65: + // AND A, saddr 0110 0101 Saddr-offset + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x69: + // AND A, !addr16 0110 1001 Low addr High addr + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0x6D: + // AND A, [HL+byte] 0110 1101 Data + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x6F: + // AND A, [HL] 0110 1111 + insn.itype = NEC_78K_0S_and; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x71: + // OR saddr, #byte 0111 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_mem; + insn.Op1.dtype = o_mem; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x73: + // OR A, #byte 0111 0011 Data + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x75: + // OR A, saddr 0111 0101 Saddr-offset + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x79: + // OR A, !addr16 0111 1001 Low addr High addr + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + addr16(insn, insn.Op2); + break; + + case 0x7D: + // OR A, [HL+byte] 0111 1101 Data + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x7F: + // OR A, [HL] 0111 1111 + insn.itype = NEC_78K_0S_or; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x81: + // ADD saddr, #byte 1000 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x83: + // ADD A, #byte 1000 0011 Data + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x85: + // ADD A, saddr 1000 0101 Saddr-offset + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x89: + // ADD A, !addr16 1000 1001 Low addr High addr + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0x8D: + // ADD A, [HL+byte] 1000 1101 Data + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x8F: + // ADD A, [HL] 1000 1111 + insn.itype = NEC_78K_0S_add; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x80: + case 0x84: + case 0x88: + case 0x8C: + // INCW rp 1000 P1 P0 00 + insn.itype = NEC_78K_0S_incw; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code>>2)&0x03)+rAX; + break; + + case 0x91: + // SUB saddr, #byte 1001 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x93: + // SUB A, #byte 1001 0011 Data + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0x95: + // SUB A, saddr 1001 0101 Saddr-offset + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0x99: + // SUB A, !addr16 1001 1001 Low addr High addr + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0x9D: + // SUB A, [HL+byte] 1001 1101 Data + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0x9F: + // SUB A, [HL] 1001 1111 + insn.itype = NEC_78K_0S_sub; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0x90: + case 0x94: + case 0x98: + case 0x9C: + // DECW rp 1001 P1 P0 00 + insn.itype = NEC_78K_0S_decw; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code>>2)&0x03)+rAX; + break; + + case 0xA1: + // ADDC saddr,#byte 1010 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0xA3: + // ADDC A, #byte 1010 0011 Data + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0xA5: + // ADDC A, saddr 1010 0101 Saddr-offset + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0xA9: + // ADDC A, !addr16 1010 1001 Low addr High addr + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0xAD: + // ADDC A,[HL+byte] 1010 1101 Data + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost = 1; + insn.Op2.xmode = 1; + break; + + case 0xAF: + // ADDC A,[HL] 1010 1111 + insn.itype = NEC_78K_0S_addc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost = 1; + break; + + case 0xA0: + case 0xA4: + case 0xA8: + case 0xAC: + // POP rp 1010 P1 P0 00 + insn.itype = NEC_78K_0S_pop; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX + ((code>>2)&0x03); + break; + + case 0xA2: + case 0xA6: + case 0xAA: + case 0xAE: + // PUSH rp 1010 P1 P0 10 + insn.itype = NEC_78K_0S_push; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX + ((code>>2)&0x03); + break; + + case 0xB0: + // BR AX 1011 0000 + insn.itype = NEC_78K_0S_br; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + break; + + case 0xB1: + // SUBC saddr,#byte 1011 0001 Saddr-offset Data + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0xB2: + // BR !addr16 1011 0010 Low addr High addr + insn.itype = NEC_78K_0S_br; + insn.Op1.type = o_near; + insn.Op1.addr16 = 1; + addr16(insn, insn.Op1); + break; + + case 0xB3: + // SUBC A, #byte 1011 0011 Data + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0xB5: + // SUBC A, saddr 1011 0101 Saddr-offset + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = saddr(insn.get_next_byte()); + break; + + case 0xB9: + // SUBC A, !addr16 1011 1001 Low addr High addr + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr16 = 1; + addr16(insn, insn.Op2); + break; + + case 0xBD: + // SUBC A, [HL+byte] 1011 1101 Data + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.addr = insn.get_next_byte(); + insn.Op2.prepost =1; + insn.Op2.xmode =1; + break; + + case 0xBF: + // SUBC A, [HL] 1011 1111 + insn.itype = NEC_78K_0S_subc; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rHL; + insn.Op2.prepost =1; + break; + + + case 0xC0: + // XCH A, X 1100 0000 + insn.itype = NEC_78K_0S_xch; + insn.Op1.type = o_reg; + insn.Op1.reg = rA; + insn.Op2.type = o_reg; + insn.Op2.reg = rX; + break; + + case 0xC2: + // SUBW AX, #word 1100 0010 Low byte High byte + insn.itype = NEC_78K_0S_subw; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + imm16(insn, insn.Op2); + break; + + case 0xC5: + // INC saddr 1100 0101 Saddr-offset + insn.itype = NEC_78K_0S_inc; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + break; + + case 0xC4: + case 0xC8: + case 0xCC: + // XCHW AX, rp 1100 P1 P0 00 Only when rp = BC, DE, or HL. + insn.itype = NEC_78K_0S_xchw; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code>>2)&0x03)+rAX; + break; + + case 0xD2: + // ADDW AX, #word 1101 0010 Low byte High byte + insn.itype = NEC_78K_0S_addw; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + imm16(insn, insn.Op2); + break; + + case 0xD5: + // DEC saddr 1101 0101 Saddr-offset + insn.itype = NEC_78K_0S_dec; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(insn.get_next_byte()); + break; + + case 0xD6: + { + // MOVW AX, saddrp 1101 0110 Saddr-offset + // MOVW AX, SP 1101 0110 0001 1100 + insn.itype = NEC_78K_0S_movw; + uchar tst = insn.get_next_byte(); + if ( tst == 0x1C ) + { + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + insn.Op2.type = o_reg; + insn.Op2.reg = rSP; + } + else + { + if ( (tst & 0x01) != 0 ) // return with the error ERROR + return 0; + // movw AX,saddrp + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_word; + insn.Op2.addr = saddr(tst); + } + } + break; + + case 0xD4: + case 0xD8: + case 0xDC: + // MOVW AX, rp 1101 P1 P0 00 Only when rp = BC, DE, or HL. + insn.itype = NEC_78K_0S_movw; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + insn.Op2.type = o_reg; + insn.Op2.reg = ((code>>2)&0x03)+rAX; + break; + + case 0xE2: + // CMPW AX, #word 1110 0010 Low byte High byte + insn.itype = NEC_78K_0S_cmpw; + insn.Op1.type = o_reg; + insn.Op1.reg = rAX; + insn.Op2.type = o_imm; + imm16(insn, insn.Op2); + break; + + case 0xEB: + // MOV [DE], A 1110 1011 + insn.itype = NEC_78K_0S_mov; + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + insn.Op1.type = o_reg; + insn.Op1.reg = rDE; + insn.Op1.prepost = 1; + break; + + case 0xEF: + // MOV [HL], A 1110 1111 + insn.itype = NEC_78K_0S_mov; + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + insn.Op1.type = o_reg; + insn.Op1.reg = rHL; + insn.Op1.prepost = 1; + break; + + case 0xE9: + // MOV !addr16, A 1110 1001 Low addr High addr + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr16 = 1; + addr16(insn, insn.Op1); + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + break; + + case 0xE5: + { + // MOV saddr, A 1110 0101 Saddr-offset + // MOV PSW, A 1110 0101 00011110 + insn.itype = NEC_78K_0S_mov; + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + uchar tst = insn.get_next_byte(); + if ( tst == 0x1E ) + { + insn.Op1.type = o_reg; + insn.Op1.reg = rPSW; + } + else + { + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(tst); + } + } + break; + + case 0xE6: + { + // MOVW saddrp, AX 1110 0110 Saddr-offset + // MOVW SP, AX 1110 0110 0001 1100 + insn.itype = NEC_78K_0S_movw; + uchar byte2 = insn.get_next_byte(); + if ( byte2 == 0x1C ) + { + insn.Op1.type = o_reg; + insn.Op1.reg = rSP; + insn.Op2.type = o_reg; + insn.Op2.reg = rAX; + } + else + { + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_word; + insn.Op1.addr = saddr(byte2); + insn.Op2.type = o_reg; + insn.Op2.reg = rAX; + } + } + break; + + case 0xED: + // MOV [HL+byte], A 1110 1101 Data + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_reg; + insn.Op1.reg = rHL; + insn.Op1.addr = insn.get_next_byte(); + insn.Op1.prepost = 1; + insn.Op1.xmode = 1; + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + break; + + case 0xE7: + // MOV sfr, A 1110 0111 Sfr-offset + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = sfr(insn.get_next_byte()); + insn.Op2.type = o_reg; + insn.Op2.reg = rA; + break; + + case 0xE4: + case 0xE8: + case 0xEC: + // MOVW rp, AX 1110 P1 P0 00 Only when rp = BC, DE, or HL. + insn.itype = NEC_78K_0S_movw; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code>>2)&0x03)+rAX; + insn.Op2.type = o_reg; + insn.Op2.reg = rAX; + break; + + case 0xF5: + { + // MOV saddr, #byte 1111 0101 Saddr-offset Data + // MOV PSW, #byte 1111 0101 00011110 Data + insn.itype = NEC_78K_0S_mov; + uchar tst = insn.get_next_byte(); + if ( tst != 0x1E ) + { + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = saddr(tst); + } + else + { + insn.Op1.type = o_reg; + insn.Op1.reg = rPSW; + } + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + } + break; + + case 0xF7: + // MOV sfr, #byte 1111 0111 Sfr-offset Data + insn.itype = NEC_78K_0S_mov; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = sfr(insn.get_next_byte()); + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + + case 0xF0: + case 0xF4: + case 0xF8: + case 0xFC: + // MOVW rp, #word 1111 P1 P0 00 Low byte High byte + insn.itype = NEC_78K_0S_movw; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code>>2)&0x03)+rAX; + insn.Op2.type = o_imm; + imm16(insn, insn.Op2); + break; + + default: + if ( (code&0xC1) == 0x40 ) + { + // CALLT [addr5] 01 ta4 to 0 0 + insn.itype = NEC_78K_0S_callt; + uint32 addr = (code&0x3E)+0x40; + insn.Op1.type = o_near; + insn.Op1.form = 1; + insn.Op1.addr = get_byte(addr)|(get_byte(addr+1)<<8); + } + else + { + // return with the error ERROR + return 0; + } + break; + } // END main switch + return insn.size; +} diff --git a/idasdk76/module/78k0s/emu.cpp b/idasdk76/module/78k0s/emu.cpp new file mode 100644 index 0000000..9887421 --- /dev/null +++ b/idasdk76/module/78k0s/emu.cpp @@ -0,0 +1,99 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "78k_0s.hpp" + +//------------------------------------------------------------------------ +void DataSet(const insn_t &insn, const op_t &x, ea_t EA, int isload) +{ + insn.create_op_data(EA, x); + insn.add_dref(EA, x.offb, isload ? dr_R : dr_W); +} + +//---------------------------------------------------------------------- +void nec78k0s_t::handle_operand(const op_t &x, bool forced_op, bool isload, const insn_t &insn) +{ + switch ( x.type ) + { + case o_phrase: + case o_void: + case o_reg: + break; + + case o_imm: + case o_displ: + set_immd(insn.ea); + if ( !forced_op ) + { + ushort addr = ushort(x.addr); + if ( x.type == o_displ ) + { + addr += (ushort)insn.ip; + addr += insn.size; + uint32 offb = map_code_ea(insn, addr, x.n); + DataSet(insn, x, offb, isload); + } + else if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + { + insn.add_off_drefs(x, dr_O, 0); + } + } + break; + + case o_bit: + case o_mem: + DataSet(insn, x, map_code_ea(insn, x), isload); + break; + + case o_near: + { + ea_t ea = to_ea(insn.cs, x.addr); + int iscall = has_insn_feature(insn.itype, CF_CALL); + insn.add_cref(ea, x.offb, iscall ? fl_CN : fl_JN); + if ( iscall ) + flow = func_does_return(ea); + } + break; + + default: + warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); + break; + } +} +//---------------------------------------------------------------------- +int nec78k0s_t::emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + flow = (Feature & CF_STOP) == 0; + + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + bool flag3 = is_forced_operand(insn.ea, 2); + + if ( Feature & CF_USE1 ) + handle_operand(insn.Op1, flag1, 1, insn); + if ( Feature & CF_USE2 ) + handle_operand(insn.Op2, flag2, 1, insn); + if ( Feature & CF_USE3 ) + handle_operand(insn.Op3, flag3, 1, insn); + if ( Feature & CF_CHG1 ) + handle_operand(insn.Op1, flag1, 0, insn); + if ( Feature & CF_CHG2 ) + handle_operand(insn.Op2, flag2, 0, insn); + if ( Feature & CF_CHG3 ) + handle_operand(insn.Op3, flag3, 0, insn); + + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + return 1; +} diff --git a/idasdk75/module/78k0s/ins.cpp b/idasdk76/module/78k0s/ins.cpp similarity index 100% rename from idasdk75/module/78k0s/ins.cpp rename to idasdk76/module/78k0s/ins.cpp diff --git a/idasdk76/module/78k0s/ins.hpp b/idasdk76/module/78k0s/ins.hpp new file mode 100644 index 0000000..2473eaa --- /dev/null +++ b/idasdk76/module/78k0s/ins.hpp @@ -0,0 +1,64 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + NEC_78K_0S_null = 0, // Unknown Operation + NEC_78K_0S_cmp, // Compare Byte Data Comparison + NEC_78K_0S_xor, // Exclusive Or Exclusive Logical Sum of Byte Data + NEC_78K_0S_and, // AND Logical Product of Byte Data + NEC_78K_0S_or, // OR Logical Sum of Byte Data + NEC_78K_0S_add, // ADD Byte Data Addition + NEC_78K_0S_sub, // Subtract Byte Data Subtraction + NEC_78K_0S_addc, // Add with Carry Addition of Byte Data with Carry + NEC_78K_0S_subc, // Subtract with Carry Subtraction of Byte Data with Carry + NEC_78K_0S_subw, // Subtract Word Data Subtraction + NEC_78K_0S_addw, // Add Word Data Addition + NEC_78K_0S_cmpw, // Compare Word Data Comparison + NEC_78K_0S_inc, // Increment Byte Data Increment + NEC_78K_0S_dec, // Decrement Byte Data Decrement + NEC_78K_0S_incw, // Increment Word Data Increment + NEC_78K_0S_decw, // Decrement Word Data Decrement + NEC_78K_0S_ror, // Rotate Right Byte Data Rotation to the Right + NEC_78K_0S_rol, // Rotate Left Byte Data Rotation to the Left + NEC_78K_0S_rorc, // Rotate Right with Carry Byte Data Rotation to the Right with Carry + NEC_78K_0S_rolc, // Rotate Left with Carry Byte Data Rotation to the Left with Carry + NEC_78K_0S_call, // CALL Subroutine Call (16 Bit Direct) + NEC_78K_0S_callt, // Call Table Subroutine Call (Call Table Reference) + NEC_78K_0S_ret, // Return from Subroutine + NEC_78K_0S_reti, // Return from Interrupt / Return from Hardware Vectored Interrupt + NEC_78K_0S_mov, // Move Byte Data Transfer + NEC_78K_0S_xch, // Exchange Byte Data Exchange + NEC_78K_0S_xchw, // Exchange Word Data Exchange + NEC_78K_0S_set1, // Set Single Bit (Carry Flag) 1 Bit Data Set + NEC_78K_0S_clr1, // Clear Single Bit (Carry Flag) 1 Bit Data Clear + NEC_78K_0S_not1, // Not Single Bit (Carry Flag) 1 Bit Data Logical Negation + NEC_78K_0S_push, // Push + NEC_78K_0S_pop, // Pop + NEC_78K_0S_movw, // Move Word Data Transfer / Word Data Transfer with Stack Pointer + NEC_78K_0S_br, // Unconditional Branch + NEC_78K_0S_bc, // Branch if Carry Conditional Branch with Carry Flag (CY = 1) + NEC_78K_0S_bnc, // Branch if Not Carry Conditional Branch with Carry Flag (CY = 0) + NEC_78K_0S_bz, // Branch if Zero Conditional Branch with Zero Flag (Z = 1) + NEC_78K_0S_bnz, // Branch if Not Zero Conditional Branch with Zero Flag (Z = 0) + NEC_78K_0S_bt, // Branch if True Conditional Branch by Bit Test (Byte Data Bit = 1) + NEC_78K_0S_bf, // Branch if False Conditional Branch by Bit Test (Byte Data Bit = 0) + NEC_78K_0S_dbnz, // Decrement and Branch if Not Zero Conditional Loop (R1 != 0) + NEC_78K_0S_nop, // No Operation + NEC_78K_0S_EI, // Enable Interrupt + NEC_78K_0S_DI, // Disable Interrupt + NEC_78K_0S_HALT, // HALT Mode Set + NEC_78K_0S_STOP, // Stop Mode Set + NEC_78K_0S_last +}; + +#endif diff --git a/idasdk76/module/78k0s/makefile b/idasdk76/module/78k0s/makefile new file mode 100644 index 0000000..a75668c --- /dev/null +++ b/idasdk76/module/78k0s/makefile @@ -0,0 +1,52 @@ +PROC=78k0s +CONFIGS=78k0s.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k_0s.hpp ana.cpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k_0s.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + 78k_0s.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp 78k_0s.hpp ins.hpp reg.cpp diff --git a/idasdk76/module/78k0s/out.cpp b/idasdk76/module/78k0s/out.cpp new file mode 100644 index 0000000..98053d4 --- /dev/null +++ b/idasdk76/module/78k0s/out.cpp @@ -0,0 +1,232 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "78k_0s.hpp" + +//---------------------------------------------------------------------- +class out_nec78k0s_t : public outctx_t +{ + out_nec78k0s_t(void) = delete; // not used +public: + void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); } + int OutVarName(const op_t &x, bool iscode); + + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_nec78k0s_t) == sizeof(outctx_t)); + +//---------------------------------------------------------------------- +void idaapi out_insn(outctx_t &ctx) +{ + out_nec78k0s_t *p = (out_nec78k0s_t *)&ctx; + p->out_insn(); +} + +bool idaapi out_opnd(outctx_t &ctx, const op_t &x) +{ + out_nec78k0s_t *p = (out_nec78k0s_t *)&ctx; + return p->out_operand(x); +} + +//---------------------------------------------------------------------- +int out_nec78k0s_t::OutVarName(const op_t &x, bool iscode) +{ + ushort addr = ushort(x.addr); + // get linear address + ea_t toea = map_ea(insn, addr, x.n, iscode); + // get its string representation + return out_name_expr(x, toea, x.addr); +} + +//---------------------------------------------------------------------- +bool out_nec78k0s_t::out_operand(const op_t &x) +{ + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + if ( x.prepost ) + out_symbol('['); + OutReg(x.reg); + if ( x.xmode ) + { + out_symbol('+'); + out_value(x, OOF_ADDR | OOF_NUMBER | OOFW_8); + } + if ( x.prepost ) + out_symbol(']'); + break; + + case o_phrase: + out_line(ph.reg_names[x.reg]); + break; + + case o_bit: + switch ( x.reg ) + { + case rPSW: + out_line("PSW."); + switch ( x.value ) + { + case 0: + out_line("CY"); + break; + case 4: + out_line("AC"); + break; + case 6: + out_line("Z"); + break; + case 7: + out_line("IE"); + break; + default: + out_value(x, OOFW_IMM); + break; + } + break; + + case rA: + out_line("A."); + out_char(char('0'+x.value)); + break; + + default: + if ( !OutVarName(x, true) ) + out_value(x, OOF_ADDR | OOFW_16); + out_symbol('.'); + // Look for a bit using its address + nec78k0s_t &pm = *static_cast<nec78k0s_t *>(procmod); + if ( !pm.nec_find_ioport_bit(*this, (int)x.addr, (int)x.value) ) + out_char(char('0'+x.value)); // output data as immediate + break; + } + break; + + case o_imm: + if ( !x.regmode ) + { + out_symbol('#'); + out_value(x, OOFW_IMM); + } + else + { + out_symbol('1'); + } + break; + + case o_mem: + // output a memory address (e.g. byte_98) + if ( x.addr16 ) + out_symbol('!'); + // output a name + if ( !OutVarName(x, false) ) + out_value(x, OOF_ADDR | OOFW_16); // output just an address + break; + + case o_near: + { + if ( x.addr16 ) + out_symbol('!'); + if ( x.form ) + out_symbol('['); + // get linear address + ea_t v = to_ea(insn.cs,x.addr); + if ( !out_name_expr(x, v, x.addr) ) + { + // print its value + out_value(x, OOF_ADDR | OOF_NUMBER | OOFW_16); + remember_problem(PR_NONAME, insn.ea); + } + if ( x.form ) + out_symbol(']'); + } + break; + + default: + warning("out: %a: bad optype %d", insn.ip, x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +void out_nec78k0s_t::out_insn(void) +{ + out_mnemonic(); + + out_one_operand(0); + + // more operands? + if ( insn.Op2.type != o_void ) + { + out_symbol(',');// print delimiter + // unless UAS_NOSPA is set, add a space + if ( !(ash.uflag & UAS_NOSPA) ) + out_char(' '); + out_one_operand(1); + } + + if ( insn.Op3.type != o_void ) + { + out_symbol(','); + if ( !(ash.uflag & UAS_NOSPA) ) + out_char(' '); + out_one_operand(2); + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void nec78k0s_t::nec78k0s_header(outctx_t &ctx) +{ + ctx.gen_cmt_line("Processor: %s [%s]", + !ioh.device.empty() + ? ioh.device.c_str() + : inf_get_procname().c_str(), + ioh.deviceparams.c_str()); + ctx.gen_cmt_line("Target assebler: %s", ash.name); + if ( ash.header != NULL ) + for ( const char *const *ptr=ash.header; *ptr != NULL; ptr++ ) + ctx.flush_buf(*ptr, 0); +} + +//-------------------------------------------------------------------------- +void idaapi nec78k0s_segstart(outctx_t &, segment_t *) +{ +} + +//-------------------------------------------------------------------------- +void nec78k0s_t::nec78k0s_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + size_t i = strlen(ash.end); + do + ctx.out_char(' '); + while ( ++i < 8 ); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} diff --git a/idasdk76/module/78k0s/reg.cpp b/idasdk76/module/78k0s/reg.cpp new file mode 100644 index 0000000..06d1418 --- /dev/null +++ b/idasdk76/module/78k0s/reg.cpp @@ -0,0 +1,262 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "78k_0s.hpp" +#include <segregs.hpp> +#include <diskio.hpp> +int data_id; + +//---------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "X", "A", "C", "B", "E", "D", "L", "H", "AX", "BC", "DE","HL", + "PSW", "SP", "s", "cc", "dpr", + "CY", + "cs", "ds" +}; +//---------------------------------------------------------------------- +static const asm_t nec78k0s = +{ + AS_COLON | ASH_HEXF0 | ASD_DECF0 | ASO_OCTF0 | ASB_BINF4 | AS_N2CHR | AS_ONEDUP | AS_NOXRF, + UAS_NOSPA, + "NEC _78K_0S Assembler", + 0, + NULL, // header + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // no double words + NULL, // no qwords + NULL, // oword (16 bytes) + NULL, // no float + NULL, // no double + NULL, // no tbytes + NULL, // no packreal + NULL, //".db.#s(b,w) #d,#v", // #h - header(.byte,.word) + // #d - size of array + // #v - value of array elements + // #s - size specifier + ".rs %s", // uninited data (reserve space) + ".equ", + NULL, // seg prefix + "*", // a_curip + NULL, // returns function header line + NULL, // returns function footer line + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; +//---------------------------------------------------------------------- +#define FAMILY "NEC series:" +static const char *const shnames[] = +{ + "78k0s", + NULL +}; +static const char *const lnames[] = +{ + FAMILY"NEC 78K/0S", + NULL +}; +static const asm_t *const asms[] = +{ + &nec78k0s, + NULL +}; +//-------------------------------------------------------------------------- +// return opcodes +static const uchar retcNEC78K0S_0[] = { 0x24 }; // reti +static const uchar retcNEC78K0S_1[] = { 0x20 }; // ret + +static const bytes_t retcodes[] = +{ + { sizeof(retcNEC78K0S_0), retcNEC78K0S_0 }, + { sizeof(retcNEC78K0S_1), retcNEC78K0S_1 }, + { 0, NULL } +}; + +//------------------------------------------------------------------ +bool nec78k0s_t::nec_find_ioport_bit(outctx_t &ctx, int port, int bit) +{ + // find bit register in the ports list + const ioport_bit_t *b = find_ioport_bit(ioh.ports, port, bit); + if ( b != NULL && !b->name.empty() ) + { + // output bit register name + ctx.out_line(b->name.c_str(), COLOR_IMPNAME); + return true; + } + return false; +} + +//---------------------------------------------------------------------- +void nec78k0s_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(nec78k0s_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi nec78k0s_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_be(false); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + inf_set_gen_lzero(true); + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: // new segment + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + nec78k0s_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + nec78k0s_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + nec78k0s_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_NEC_78K0S, // id + // flag + PRN_HEX + | PR_SEGTRANS, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + Rcs,Rds, + 0, // size of a segment register + Rcs,Rds, + + NULL, // No known code start sequences + retcodes, + + 0, + NEC_78K_0S_last, + Instructions, // instruc +}; diff --git a/idasdk76/module/80196/ana.cpp b/idasdk76/module/80196/ana.cpp new file mode 100644 index 0000000..bf5d310 --- /dev/null +++ b/idasdk76/module/80196/ana.cpp @@ -0,0 +1,597 @@ +/* + * Interactive disassembler (IDA). + * Intel 80196 module + * + */ + +#include "i196.hpp" +#include "ins.hpp" + +//---------------------------------------------------------------------- +struct wsr_mapping_t +{ + ushort base; + uchar wsr; + uchar wsrbase; + uchar wsr1base; +}; + +static const wsr_mapping_t mappings[] = +{ + { 0x0000, 0x10, 0x80, 0xFF }, // 0080-00FF + { 0x0080, 0x11, 0x80, 0xFF }, + { 0x0100, 0x12, 0x80, 0xFF }, + { 0x0180, 0x13, 0x80, 0xFF }, + { 0x0200, 0x14, 0x80, 0xFF }, + { 0x0280, 0x15, 0x80, 0xFF }, + { 0x0300, 0x16, 0x80, 0xFF }, + { 0x0380, 0x17, 0x80, 0xFF }, + { 0x1F00, 0x1E, 0x80, 0xFF }, + { 0x1F80, 0x1F, 0x80, 0xFF }, + { 0x0000, 0x20, 0xC0, 0x40 }, // 00C0-00FF or 0040-007F + { 0x0040, 0x21, 0xC0, 0x40 }, + { 0x0080, 0x22, 0xC0, 0x40 }, + { 0x00C0, 0x23, 0xC0, 0x40 }, + { 0x0100, 0x24, 0xC0, 0x40 }, + { 0x0140, 0x25, 0xC0, 0x40 }, + { 0x0180, 0x26, 0xC0, 0x40 }, + { 0x01C0, 0x27, 0xC0, 0x40 }, + { 0x0200, 0x28, 0xC0, 0x40 }, + { 0x0240, 0x29, 0xC0, 0x40 }, + { 0x0280, 0x2A, 0xC0, 0x40 }, + { 0x02C0, 0x2B, 0xC0, 0x40 }, + { 0x0300, 0x2C, 0xC0, 0x40 }, + { 0x0340, 0x2D, 0xC0, 0x40 }, + { 0x0380, 0x2E, 0xC0, 0x40 }, + { 0x03C0, 0x2F, 0xC0, 0x40 }, + { 0x1F00, 0x3C, 0xC0, 0x40 }, + { 0x1F40, 0x3D, 0xC0, 0x40 }, + { 0x1F80, 0x3E, 0xC0, 0x40 }, + { 0x1FC0, 0x3F, 0xC0, 0x40 }, + { 0x0000, 0x40, 0xE0, 0x60 }, // 00E0-00FF or 0060-007F + { 0x0020, 0x41, 0xE0, 0x60 }, + { 0x0040, 0x42, 0xE0, 0x60 }, + { 0x0060, 0x43, 0xE0, 0x60 }, + { 0x0080, 0x44, 0xE0, 0x60 }, + { 0x00A0, 0x45, 0xE0, 0x60 }, + { 0x00C0, 0x46, 0xE0, 0x60 }, + { 0x00E0, 0x47, 0xE0, 0x60 }, + { 0x0100, 0x48, 0xE0, 0x60 }, + { 0x0120, 0x49, 0xE0, 0x60 }, + { 0x0140, 0x4A, 0xE0, 0x60 }, + { 0x0160, 0x4B, 0xE0, 0x60 }, + { 0x0180, 0x4C, 0xE0, 0x60 }, + { 0x01A0, 0x4D, 0xE0, 0x60 }, + { 0x01C0, 0x4E, 0xE0, 0x60 }, + { 0x01E0, 0x4F, 0xE0, 0x60 }, + { 0x0200, 0x50, 0xE0, 0x60 }, + { 0x0220, 0x51, 0xE0, 0x60 }, + { 0x0240, 0x52, 0xE0, 0x60 }, + { 0x0260, 0x53, 0xE0, 0x60 }, + { 0x0280, 0x54, 0xE0, 0x60 }, + { 0x02A0, 0x55, 0xE0, 0x60 }, + { 0x02C0, 0x56, 0xE0, 0x60 }, + { 0x02E0, 0x57, 0xE0, 0x60 }, + { 0x0300, 0x58, 0xE0, 0x60 }, + { 0x0320, 0x59, 0xE0, 0x60 }, + { 0x0340, 0x5A, 0xE0, 0x60 }, + { 0x0360, 0x5B, 0xE0, 0x60 }, + { 0x0380, 0x5C, 0xE0, 0x60 }, + { 0x03A0, 0x5D, 0xE0, 0x60 }, + { 0x03C0, 0x5E, 0xE0, 0x60 }, + { 0x03E0, 0x5F, 0xE0, 0x60 }, + { 0x1F00, 0x78, 0xE0, 0x60 }, + { 0x1F20, 0x79, 0xE0, 0x60 }, + { 0x1F40, 0x7A, 0xE0, 0x60 }, + { 0x1F60, 0x7B, 0xE0, 0x60 }, + { 0x1F80, 0x7C, 0xE0, 0x60 }, + { 0x1FA0, 0x7D, 0xE0, 0x60 }, + { 0x1FC0, 0x7E, 0xE0, 0x60 }, + { 0x1FE0, 0x7F, 0xE0, 0x60 }, +}; + +static int NT_CDECL cmp(const void *x, const void *y) +{ + const wsr_mapping_t *a = (const wsr_mapping_t *)x; + const wsr_mapping_t *b = (const wsr_mapping_t *)y; + return a->wsr - b->wsr; +} + +//---------------------------------------------------------------------- +// perform WSR/WSR1 mapping +ea_t i196_t::map(ea_t iea, ea_t v) const +{ + if ( !extended ) + return v; + if ( v < 0x40 ) + return v; + sel_t wsr = get_sreg(iea, v < 0x80 ? WSR1 : WSR) & 0x7F; + if ( wsr < 0x10 ) + return v; + + wsr_mapping_t key; + key.wsr = (char)wsr; + wsr_mapping_t *p = (wsr_mapping_t *) + bsearch(&key, mappings, qnumber(mappings), sizeof(key), cmp); + if ( p == NULL ) + return v; + + int delta = v < 0x80 ? p->wsr1base : p->wsrbase; + if ( v < delta ) + return v; + return v - delta + p->base; +} + +//---------------------------------------------------------------------- +void i196_t::aop(insn_t &insn, uint code, op_t &op) +{ + switch ( code & 3 ) + { + case 0: // direct + op.type = o_mem; + op.addr = map(insn.ea, insn.get_next_byte()); + break; + + case 1: // immediate + op.type = o_imm; + if ( (code & 0x10) == 0 && (code & 0xFC) != 0xAC ) // ldbze always baop + { + op.dtype = dt_word; + op.value = insn.get_next_word(); + } + else + { + op.value = insn.get_next_byte(); + } + break; + + case 2: // indirect + op.dtype = dt_word; + op.addr = insn.get_next_byte(); + op.type = (op.addr & 1) ? o_indirect_inc : o_indirect; + op.addr = map(insn.ea, op.addr & ~1); + break; + + case 3: // indexed + op.dtype = dt_word; + op.type = o_indexed; + op.value = insn.get_next_byte(); // short (reg file) + op.addr = (op.value & 1) ? insn.get_next_word() : insn.get_next_byte(); + op.value = map(insn.ea, op.value & ~1); + } +} + +//---------------------------------------------------------------------- +int i196_t::ld_st(insn_t &insn, ushort itype, char dtype, bool indirect, op_t ®, op_t &mem) +{ + if ( !extended ) + return 0; + insn.itype = itype; + reg.dtype = dtype; + mem.dtype = dtype; + mem.addr = insn.get_next_byte(); + if ( indirect ) // indirect + { + mem.type = (mem.addr & 1) ? o_indirect_inc : o_indirect; + mem.addr = map(insn.ea, mem.addr & ~1); + } + else + { + mem.type = o_indexed; + mem.value = map(insn.ea, mem.addr); + mem.addr = insn.get_next_word(); + mem.addr |= insn.get_next_byte() << 16; + } + reg.type = o_mem; + reg.addr = map(insn.ea, insn.get_next_byte()); + return insn.size; +} + +//---------------------------------------------------------------------- +int i196_t::ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + + insn.Op1.dtype = dt_byte; + insn.Op2.dtype = dt_byte; + insn.Op3.dtype = dt_byte; + + uint code = insn.get_next_byte(); + + uint nibble0 = (code & 0xF); + uint nibble1 = (code >> 4); + + char offc; + int32 off; + uint tmp; + + if ( nibble1 < 2 ) // 0,1 + { + static const char cmd01[] = + { + I196_skip, I196_clr, I196_not, I196_neg, + I196_xch, I196_dec, I196_ext, I196_inc, + I196_shr, I196_shl, I196_shra, I196_xch, + I196_shrl, I196_shll, I196_shral, I196_norml, + I196_null, I196_clrb, I196_notb, I196_negb, + I196_xchb, I196_decb, I196_extb, I196_incb, + I196_shrb, I196_shlb, I196_shrab, I196_xchb, + I196_est, I196_est, I196_estb, I196_estb + }; + + insn.itype = cmd01[code & 0x1F]; + + if ( insn.itype == I196_null ) + return 0; // unknown instruction + + switch ( code ) + { + case 0x4: case 0x14: // xch reg,aop direct + case 0xB: case 0x1B: // xch reg,aop indexed + if ( (code & 0x10) == 0 ) + insn.Op2.dtype = dt_word; + aop(insn, code, insn.Op2); + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + break; + + case 0xF: // norml lreg,breg + insn.Op2.addr = map(insn.ea, insn.get_next_byte()); + insn.Op2.type = o_mem; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + break; + + case 0x1C: // est.indirect + case 0x1D: // est.indexed + return ld_st(insn, I196_est, dt_word, code == 0x1C, insn.Op1, insn.Op2); + + case 0x1E: // estb.indirect + case 0x1F: // estb.indexed + return ld_st(insn, I196_estb, dt_byte, code == 0x1E, insn.Op1, insn.Op2); + + default: // shifts + tmp = insn.get_next_byte(); + if ( tmp < 16 ) + { + insn.Op2.value = tmp; + insn.Op2.type = o_imm; + } + else + { + insn.Op2.addr = map(insn.ea, tmp); + insn.Op2.type = o_mem; + } + // fallthrough + + case 0x0: case 0x1: case 0x2: case 0x3: + case 0x5: case 0x6: case 0x7: case 0x11: + case 0x12: case 0x13: case 0x15: case 0x16: case 0x17: + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + } + + switch ( code ) + { + case 0x1: case 0x2: case 0x3: case 0x4: case 0x5: + case 0x7: case 0x8: case 0x9: case 0xA: case 0xB: case 0x16: + insn.Op1.dtype = dt_word; + break; + + case 0x6: case 0xC: case 0xD: case 0xE: case 0xF: + insn.Op1.dtype = dt_dword; + break; + } + } + else if ( nibble1 < 4 ) // 2,3 + { + static const char cmd23[] = { I196_sjmp, I196_scall, I196_jbc, I196_jbs }; + + insn.itype = cmd23[ ((code - 0x20) >> 3) & 3 ]; + + if ( nibble1 == 2 ) // sjmp/scall + { + insn.Op1.type = o_near; + off = insn.get_next_byte() + ((code & 7) << 8); + if ( off & 0x400 ) + off |= ~0x7FF; + else + off &= 0x7FF; // make signed + insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition +// insn.Op1.dtype = dt_word; + } + else // jbc/jbs + { + insn.Op2.type = o_bit; + insn.Op2.reg = code & 7; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + insn.Op3.type = o_near; + offc = insn.get_next_byte(); + insn.Op3.addr = truncate(insn.ip + insn.size + offc); // signed addition +// insn.Op3.dtype = dt_word; + } + } + else if ( nibble1 < 6 ) // 4,5 + { + static const char cmd45[] = + { + I196_and3, I196_add3, I196_sub3, I196_mulu3, + I196_andb3, I196_addb3, I196_subb3, I196_mulub3 + }; + + insn.itype = cmd45[ ((code - 0x40) >> 2) & 7 ]; + + if ( (code & 0x10) == 0 ) + insn.Op1.dtype = insn.Op2.dtype = insn.Op3.dtype = dt_word; + + if ( (code & 0xc) == 0xc ) // mulu/mulub + insn.Op1.dtype++; // word->dword/byte->word + + aop(insn, code, insn.Op3); + insn.Op2.addr = map(insn.ea, insn.get_next_byte()); + insn.Op2.type = o_mem; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + } + else if ( nibble1 < 0xD ) // 6,7,8,9,A,B,C + { + static const char cmd6c[] = + { + I196_and2, I196_add2, I196_sub2, I196_mulu2, + I196_andb2, I196_addb2, I196_subb2, I196_mulub2, + I196_or, I196_xor, I196_cmp, I196_divu, + I196_orb, I196_xorb, I196_cmpb, I196_divub, + I196_ld, I196_addc, I196_subc, I196_ldbze, + I196_ldb, I196_addcb, I196_subcb, I196_ldbse, + I196_st, I196_stb, I196_push, I196_pop, + I196_null, I196_null, I196_null, I196_null, + }; + + insn.itype = cmd6c[ ((code - 0x60) >> 2) & 31 ]; + + switch ( nibble1 ) + { + case 6: // and/add/sub/mulu + case 8: // or/xor/cmp/duvu + insn.Op1.dtype = insn.Op2.dtype = dt_word; + if ( (nibble0 & 0xC) == 0xC ) + insn.Op1.dtype++; // mulu/divu + break; + + case 0xA: // ld/addc/subc/ldbze + insn.Op1.dtype = insn.Op2.dtype = dt_word; + if ( (nibble0 & 0xC) == 0xC ) + insn.Op2.dtype = dt_byte; // ldbze + break; + } + + switch ( code & 0xFC ) + { + case 0xC0: // st + insn.Op2.dtype = dt_word; + + case 0x7C: case 0x9C: case 0xBC: case 0xC8: case 0xCC: + insn.Op1.dtype = dt_word; + } + + switch ( code ) + { + case 0xC1: + insn.itype = I196_bmov; + goto cont1; + + case 0xC5: + insn.itype = I196_cmpl; + insn.Op2.dtype = dt_dword; + goto cont2; + + case 0xCD: + insn.itype = I196_bmovi; +cont1: + insn.Op2.dtype = dt_word; +cont2: + insn.Op2.addr = map(insn.ea, insn.get_next_byte()); + insn.Op2.type = o_mem; + insn.Op1.dtype = dt_dword; +// insn.Op1.addr = insn.get_next_byte(); +// insn.Op1.type = o_mem; + goto cont3; + + default: + if ( code > 0xC7 ) + { + aop(insn, code, insn.Op1); + } + else + { + aop(insn, code, insn.Op2); +cont3: + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + } + } + } + else if ( nibble1 == 0xD ) // jcc + { + static const char cmdd[] = + { + I196_jnst, I196_jnh, I196_jgt, I196_jnc, + I196_jnvt, I196_jnv, I196_jge, I196_jne, + I196_jst, I196_jh, I196_jle, I196_jc, + I196_jvt, I196_jv, I196_jlt, I196_je + }; + + insn.itype = cmdd[nibble0]; + + insn.Op1.type = o_near; + offc = insn.get_next_byte(); + insn.Op1.addr = truncate(insn.ip + insn.size + offc); // signed addition +// insn.Op1.dtype = dt_word; + } + else if ( nibble1 == 0xE ) // Ex + { + switch ( nibble0 ) + { + case 0x0: case 0x1: // djnz, djnzw + if ( nibble0 & 1 ) + { + insn.itype = I196_djnzw; + insn.Op1.dtype = dt_word; + } + else + { + insn.itype = I196_djnz; + } + insn.Op1.type = o_mem; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + offc = insn.get_next_byte(); + insn.Op2.type = o_near; + insn.Op2.addr = truncate(insn.ip + insn.size + offc); // signed addition + break; + + case 0x2: // tijmp + insn.itype = I196_tijmp; + insn.Op1.dtype = insn.Op2.dtype = dt_word; + insn.Op2.type = o_indirect; + insn.Op2.addr = map(insn.ea, insn.get_next_byte()); + insn.Op3.type = o_imm; + insn.Op3.value = insn.get_next_byte(); + insn.Op1.type = o_mem; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + break; + + case 0x3: // br + insn.itype = extended ? I196_ebr : I196_br; + aop(insn, 2, insn.Op1); + break; + + case 0x4: // ebmovi + if ( !extended ) + return 0; + insn.itype = I196_ebmovi; + insn.Op1.type = o_mem; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op2.type = o_mem; + insn.Op2.addr = map(insn.ea, insn.get_next_byte()); + break; + + case 0x6: // ejmp + if ( !extended ) + return 0; + insn.itype = I196_ejmp; + insn.Op1.type = o_near; + off = insn.get_next_word(); + off |= int32(insn.get_next_byte()) << 16; + insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition + break; + + case 0x8: // eld.indirect + case 0x9: // eld.indexed + return ld_st(insn, I196_eld, dt_word, nibble0 == 0x8, insn.Op1, insn.Op2); + + case 0xA: // eldb.indirect + case 0xB: // eldb.indexed + return ld_st(insn, I196_eldb, dt_byte, nibble0 == 0xA, insn.Op1, insn.Op2); + + case 0xC: // dpts + insn.itype = I196_dpts; + break; + + case 0xD: // epts + insn.itype = I196_epts; + break; + + case 0x7: case 0xF: // ljmp, lcall + insn.itype = (nibble0 & 8) ? I196_lcall : I196_ljmp; + insn.Op1.type = o_near; + off = short(insn.get_next_word()); + insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition + insn.Op1.dtype = dt_word; + break; + + default: + return 0; + } + } + else + { + static const char cmdf[] = + { + I196_ret, I196_ecall,I196_pushf, I196_popf, + I196_pusha, I196_popa, I196_idlpd, I196_trap, + I196_clrc, I196_setc, I196_di, I196_ei, + I196_clrvt, I196_nop, I196_null, I196_rst + }; + + insn.itype = cmdf[nibble0]; + if ( nibble0 == 1 ) // ecall + { + if ( !extended ) + return 0; + off = insn.get_next_word(); + off |= int32(insn.get_next_byte()) << 16; + insn.Op1.type = o_near; + insn.Op1.addr = truncate(insn.ip + insn.size + off); + } + else if ( nibble0 == 6 ) // idlpd + { + insn.Op1.type = o_imm; + insn.Op1.value = insn.get_next_byte(); + } + else if ( nibble0 == 0xE ) // prefix + { + code = insn.get_next_byte(); + + switch ( code & 0xFC ) + { + case 0x4C: case 0x5C: + if ( code & 0x10 ) + { + insn.itype = I196_mulb3; + insn.Op1.dtype = dt_word; + } + else + { + insn.itype = I196_mul3; + insn.Op3.dtype = insn.Op2.dtype = dt_word; + insn.Op1.dtype = dt_dword; + } + + aop(insn, code, insn.Op3); + insn.Op2.addr = map(insn.ea, insn.get_next_byte()); + insn.Op2.type = o_mem; + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + break; + + case 0x6C: case 0x7C: case 0x8C: case 0x9C: + insn.itype = (code & 0x80) + ? (code & 0x10) ? I196_divb : I196_div + : (code & 0x10) ? I196_mulb2 : I196_mul2; + + if ( code & 0x10 ) + { + insn.Op1.dtype = dt_word; + } + else + { + insn.Op1.dtype = dt_dword; + insn.Op2.dtype = dt_word; + } + + aop(insn, code, insn.Op2); + insn.Op1.addr = map(insn.ea, insn.get_next_byte()); + insn.Op1.type = o_mem; + break; + + default: + return 0; + } + } + } + + return insn.size; +} diff --git a/idasdk75/module/80196/emu.cpp b/idasdk76/module/80196/emu.cpp similarity index 100% rename from idasdk75/module/80196/emu.cpp rename to idasdk76/module/80196/emu.cpp diff --git a/idasdk75/module/80196/i196.hpp b/idasdk76/module/80196/i196.hpp similarity index 100% rename from idasdk75/module/80196/i196.hpp rename to idasdk76/module/80196/i196.hpp diff --git a/idasdk75/module/80196/ins.cpp b/idasdk76/module/80196/ins.cpp similarity index 100% rename from idasdk75/module/80196/ins.cpp rename to idasdk76/module/80196/ins.cpp diff --git a/idasdk75/module/80196/ins.hpp b/idasdk76/module/80196/ins.hpp similarity index 100% rename from idasdk75/module/80196/ins.hpp rename to idasdk76/module/80196/ins.hpp diff --git a/idasdk76/module/80196/makefile b/idasdk76/module/80196/makefile new file mode 100644 index 0000000..65f08de --- /dev/null +++ b/idasdk76/module/80196/makefile @@ -0,0 +1,50 @@ +PROC=i196 + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ana.cpp i196.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + emu.cpp i196.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + i196.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + i196.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + i196.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/80196/out.cpp b/idasdk76/module/80196/out.cpp similarity index 100% rename from idasdk75/module/80196/out.cpp rename to idasdk76/module/80196/out.cpp diff --git a/idasdk75/module/80196/reg.cpp b/idasdk76/module/80196/reg.cpp similarity index 100% rename from idasdk75/module/80196/reg.cpp rename to idasdk76/module/80196/reg.cpp diff --git a/idasdk76/module/arc/ana.cpp b/idasdk76/module/arc/ana.cpp new file mode 100644 index 0000000..96f7fe9 --- /dev/null +++ b/idasdk76/module/arc/ana.cpp @@ -0,0 +1,2776 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 2012-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * ARC (Argonaut RISC Core) processor module + * + * Based on code contributed by by Felix Domke <tmbinc@gmx.net> + */ + +#include "arc.hpp" +#include <frame.hpp> + +/* +doRegisterOperand converts the 6 bit field 'code' to an IDA-"op_t"-operand. + +'d' is the maybe-used (signed) immediate in the lowest 9 bits, li is the +long-immediate which is loaded in the instruction decoding, since it's +loaded only once, even if an instructions uses multiple times a long immediate + +when it's all about a branch (isbranch is true), we have to multiply the absolute +address by 4, since it's granularity are words then (and not bytes) + +FYI: +register code 61 means "short immediate with .f-flag set", 63 "short immediate +without .f-flag" and 62 means "long immediate (4 bytes following the instruction, +making the instruction 8 bytes long (insn.size)). +*/ + +//---------------------------------------------------------------------- +void doRegisterOperand(int code, op_t &op, int d, int li, int isbranch) +{ + /* we always deal with double words, exceptions are load/stores + with 8 or 16 bits. these are covered by the instruction decoding */ + + op.dtype = dt_dword; + if ( code == SHIMM_F || code == SHIMM ) // short immediate with/wo flags + { + if ( isbranch ) + { + op.type = o_near; + op.addr = d * 4; + } + else + { + op.type = o_imm; + op.value = d; + } + } + else if ( code == LIMM ) // long immediate + { + if ( isbranch ) + { + op.type = o_near; + /* the upper 7 bits containing processor flags to set */ + /* they are handled in the instruction decoding, since */ + /* they produce a second (ida-)operand */ + op.addr = (li & 0x1FFFFFF) * 4; + } + else + { + op.type = o_imm; + op.value = li; + } + op.offb = 4; + } + else /* just a register */ + { + op.type = o_reg; + op.reg = uint16(code); + } +} + +//---------------------------------------------------------------------- +// make indirect [b,c] operand +// b c +// imm imm mem: [imm1+imm2] +// reg imm displ: [reg, imm] +// imm reg displ: [imm, reg] (membase=1) +// reg reg phrase: [reg, reg] +void arc_t::doIndirectOperand(const insn_t &insn, int b, int c, op_t &op, int d, int li, bool special) +{ + if ( is_imm(b) && is_imm(c) ) + { + // [#imm, #imm] + int imm1 = b == LIMM ? li : d; + int imm2 = c == LIMM ? li : d; + if ( special ) + { + // use a simple immediate for AUX reg numbers + op.type = o_imm; + op.value = imm1; + } + else + { + op.type = o_mem; + op.immdisp = is_a4() ? 0 : imm2; + op.addr = imm1 + imm2 * get_scale_factor(insn); + } + } + else if ( !is_imm(b) && !is_imm(c) ) + { + // [reg, reg] + op.type = o_phrase; + op.reg = b; + op.secreg = c; + } + else + { + op.type = o_displ; + if ( is_imm(c) ) + { + // [reg, #imm] + op.reg = b; + op.addr = c == LIMM ? li : d; + if ( special ) + op.addr = 0; + op.membase = 0; + } + else + { + // [#imm, reg] + op.reg = c; + op.addr = b == LIMM ? li : d; + op.membase = 1; + } + } + switch ( insn.auxpref & aux_zmask ) + { + default: + op.dtype = dt_dword; + break; + case aux_b: + op.dtype = dt_byte; + break; + case aux_w: + op.dtype = dt_word; + break; + } +} + +//---------------------------------------------------------------------- +// doBranchOperand handles pc-relative word offsets. +// nothing special here. +void doBranchOperand(const insn_t &insn, op_t &op, int l) +{ + op.dtype = dt_dword; + op.type = o_near; + op.addr = insn.ip + l * 4 + 4; + op.offb = 0; +} + +//---------------------------------------------------------------------- +void arc_t::doRegisterInstruction(insn_t &insn, uint32 code) +{ + + int i = (code >> 27) & 31; + int a = (code >> 21) & 63; + int b = (code >> 15) & 63; + int c = (code >> 9) & 63; + + /* the (maybe used?) short immediate value */ + uint32 d = code & 0x1FF; + + // sign-extend + if ( d >= 0x100 ) + d -= 0x200; + + /* store the flags. if there are actually no flags at that place, they */ + /* will be reconstructed later */ + insn.auxpref = code & (aux_cmask|aux_f); + + switch ( i ) + { + case 0: // LD register+register + insn.itype = ARC_ld; + insn.auxpref |= (code & aux_di); + break; + case 1: // LD register+offset, LR + if ( code & (1 << 13) ) + insn.itype = ARC_lr; + else + insn.itype = ARC_ld; + break; + case 2: // ST, SR + if ( code & (1 << 25) ) + { + insn.itype = ARC_sr; + } + else + { + insn.itype = ARC_st; + // 26 = Di + // 24 = A + // 23..22 = ZZ + insn.auxpref = (code >> 20) & (aux_di|aux_amask|aux_zmask); + } + break; + case 3: // single operand instructions + switch ( c ) + { + case 0: + insn.itype = ARC_flag; + a = b; // flag has no 'a' operand, so we're moving the b-operand to a. + break; + case 1: + insn.itype = ARC_asr; + break; + case 2: + insn.itype = ARC_lsr; + break; + case 3: + insn.itype = ARC_ror; + break; + case 4: + insn.itype = ARC_rrc; + break; + case 5: + insn.itype = ARC_sexb; + break; + case 6: + insn.itype = ARC_sexw; + break; + case 7: + insn.itype = ARC_extb; + break; + case 8: + insn.itype = ARC_extw; + break; + case 9: + insn.itype = ARC_swap; + break; + case 10: + insn.itype = ARC_norm; + break; + case 0x3F: + switch ( d ) + { + case 0: + insn.itype = ARC_brk; + break; + case 1: + insn.itype = ARC_sleep; + break; + case 2: + insn.itype = ARC_swi; + break; + default: + return; + } + a = b = -1; + insn.auxpref = 0; + break; + } + c = -1; // c operand is no real operand, so don't try to convert it. + break; + case 7: // Jcc, JLcc + insn.itype = ARC_j; + if ( code & (1<<9) ) + insn.itype = ARC_jl; + else + insn.itype = ARC_j; + // copy the NN bits + insn.auxpref |= (code & aux_nmask); + break; + case 8: // ADD + insn.itype = ARC_add; + break; + case 9: // ADC + insn.itype = ARC_adc; + break; + case 10: // SUB + insn.itype = ARC_sub; + break; + case 11: // SBC + insn.itype = ARC_sbc; + break; + case 12: // AND + insn.itype = ARC_and; + break; + case 13: // OR + insn.itype = ARC_or; + break; + case 14: // BIC + insn.itype = ARC_bic; + break; + case 15: // XOR + insn.itype = ARC_xor; + break; + case 0x10: + insn.itype = ARC_asl; + break; + case 0x11: + insn.itype = ARC_lsr; + break; + case 0x12: + insn.itype = ARC_asr; + break; + case 0x13: + insn.itype = ARC_ror; + break; + case 0x14: + insn.itype = ARC_mul64; + break; + case 0x15: + insn.itype = ARC_mulu64; + break; + case 0x1E: + insn.itype = ARC_max; + break; + case 0x1F: + insn.itype = ARC_min; + break; + } + + uint32 immediate = 0; + int noop3 = 0, isnop = 0; + + if ( a == SHIMM_F || b == SHIMM_F || c == SHIMM_F ) + insn.auxpref = aux_f; // .f + + if ( b == SHIMM || c == SHIMM ) + insn.auxpref = 0; + + if ( b == LIMM || c == LIMM ) + immediate = insn.get_next_dword(); + + /* + pseudo instruction heuristic: + + we have some types of pseudo-instructions: + + (rS might be an immediate) + insn will be coded as + move rD, rS and rD, rS, rS + asl rD, rS add rD, rS, rS + lsl rD, rS add rD, rS, rS (the same as asl, of course...) + rlc rD, rS adc.f rD, rS, rS + rol rD, rS add.f rD, rS, rS; adc rD, rD, 0 + nop xxx 0, 0, 0 + */ + + switch ( insn.itype ) + { + case ARC_flag: + // special handling for flag, since its a-operand is a source here + b = -1; + break; + + case ARC_and: + case ARC_or: + if ( b == c ) + { + noop3 = 1; + insn.itype = ARC_mov; + } + break; + + case ARC_add: + if ( b == c ) + { + noop3 = 1; + if ( b >= SHIMM_F ) + { + // add rD, imm, imm -> move rD, imm*2 + insn.itype = ARC_mov; + d <<= 1; + immediate <<= 1; + } + else + { + insn.itype = ARC_lsl; + } + } + break; + + case ARC_adc: + if ( b == c ) + { + noop3 = 1; + insn.itype = ARC_rlc; + } + break; + + case ARC_xor: + if ( code == 0x7FFFFFFF ) // XOR 0x1FF, 0x1FF, 0x1FF + isnop = 1; + break; + } + + if ( !isnop ) + { + if ( i == 0 ) + { + // ld a, [b,c] + doRegisterOperand(a, insn.Op1, d, immediate, 0); + doIndirectOperand(insn, b, c, insn.Op2, d, immediate, false); + } + else if ( i == 1 || i == 2 ) + { + /* fetch the flag-bits from the right location */ + if ( insn.itype == ARC_ld ) + insn.auxpref = (code >> 9) & 0x3F; + else if ( insn.itype == ARC_st ) + insn.auxpref = (code >> 21) & 0x3F; + else + insn.auxpref = 0; + if ( insn.itype == ARC_st || insn.itype == ARC_sr ) + { + /* in a move to special register or load from special register, + we have the target operand somewhere else */ + a = c; + /* c=-1; not used anyway */ + } + doRegisterOperand(a, insn.Op1, d, immediate, 0); + doIndirectOperand(insn, b, SHIMM, insn.Op2, d, immediate, insn.itype == ARC_lr || insn.itype == ARC_sr); + } + else if ( i == 7 ) + { + /* the jump (absolute) instruction, with a special imm-encoding */ + doRegisterOperand(b, insn.Op1, d, immediate, 1); + } + else + { + if ( a != -1 ) + doRegisterOperand(a, insn.Op1, 0, immediate, 0); + /* this is a bugfix for the gnu-as: long immediate must be equal, while short */ + /* immediates don't have to. */ + if ( b != -1 ) + doRegisterOperand(b, insn.Op2, d, immediate, 0); + if ( c != -1 && !noop3 ) + doRegisterOperand(c, insn.Op3, d, immediate, 0); + } + } + else + { + insn.itype = ARC_nop; + insn.auxpref = 0; + } +} + +//---------------------------------------------------------------------- +void doBranchInstruction(insn_t &insn, uint32 code) +{ + int i = (code >> 27) & 31; + + int l = (code >> 7) & 0xFFFFF; // note: bits 21..2, so it's in WORDS + + if ( l >= 0x80000 ) // sign-extend + l = l - 0x100000; + + doBranchOperand(insn, insn.Op1, l); + + switch ( i ) + { + case 4: // Bcc + insn.itype = ARC_b; + break; + case 5: // BLcc + insn.itype = ARC_bl; + break; + case 6: // LPcc + insn.itype = ARC_lp; + break; + } + insn.auxpref = code & (aux_cmask | aux_nmask); +} + +//---------------------------------------------------------------------- +// analyze ARCTangent-A4 (32-bit) instruction +int arc_t::ana_old(insn_t &insn) +{ + if ( insn.ea & 3 ) + return 0; + + insn.Op1.dtype = dt_dword; + insn.Op2.dtype = dt_dword; + insn.Op3.dtype = dt_dword; + + uint32 code = insn.get_next_dword(); + + int i = (code >> 27) & 31; + + insn.itype = 0; + + switch ( i ) + { + case 0: // LD register+register + case 1: // LD register+offset, LR + case 2: // ST, SR + case 3: // single operand instructions + doRegisterInstruction(insn, code); + break; + case 4: // Bcc + case 5: // BLcc + case 6: // LPcc + doBranchInstruction(insn, code); + break; + case 7: // Jcc, JLcc + case 8: // ADD + case 9: // ADC + case 10: // SUB + case 11: // ADC + case 12: // AND + case 13: // OR + case 14: // BIC + case 15: // XOR + default: + doRegisterInstruction(insn, code); + break; + } + + return insn.size; +} + +#define SUBTABLE(high, low, name) (0x80000000 | (high << 8) | low), 0, { 0,0,0 }, name +#define SUBTABLE2(high1, low1, high2, low2, name) (0x80000000 | (high1 << 24) | (low1 << 16) | (high2 << 8) | low2), 0, { 0,0,0 }, name + +//---------------------------------------------------------------------- +struct arcompact_opcode_t +{ + uint32 mnem; // instruction itype, or indicator of sub-field decoding + uint32 aux; // auxpref and other flags + uint32 ops[3]; // description of operands + const arcompact_opcode_t *subtable; //lint !e958 padding is required to align members +}; + +enum aux_flags_t ENUM_SIZE(uint32) +{ + AUX_B = 1, // implicit byte size access + AUX_W = 2, // implicit word size access + Q_4_0 = 4, // 4..0 QQQQQ condition code + AAZZXD_23_15 = 8, // 23..22,18..15 aa, ZZ, X, D flags (load reg+reg) + DAAZZX_11_6 = 0x10, // 11..6 Di, aa, ZZ, X flags (load) + DAAZZ_5_1 = 0x20, // 5..0 Di, aa, ZZ, R flags (store) + AUX_D = 0x40, // implicit delay slot (.d) + AUX_X = 0x80, // implicit sign extend (.x) + AUX_CND = 0x100, // implicit condition (in low 5 bits) + N_5 = 0x200, // 5..5 N delay slot bit + AUX_GEN = 0x400, // 4..0 = Q if 23..22=0x3, bit 15 = F + AUX_GEN2 = 0x800, // 4..0 = Q if 23..22=0x3 + AUX_GEN3 = + AUX_GEN|AUX_GEN2, // 4..0 = Q if 23..22=0x3, bit 15 = Di + AUX_V2 = 0x1000, // only available on ARCv2 + AUX_F = 0x2000, // use alternative instruction when F = 1 + AUX_AS = 0x8000, // implicit scaled access + Q_5_0 = 0x10000, // 5..0 0QQQQQ condition code + Y_3 = 0x20000, // 3 Y static branch prediction bit +}; + +enum op_fields_t ENUM_SIZE(uint32) +{ + fA32=1, // 5..0 a register operand (6 bits, r0-r63) + fA16, // 2..0 a register operand (3 bits, r0-r3, r12-r15) + fB32, // 14..12 & 26..24 b register operand (6 bits) + fB16, // 10..8 b register operand (3 bits) + fC32, // 11..6 c register operand (6 bits) + fC32_w6, // 11..6 & 0 c/w6 register/immediate operand (6 bits) + fC16, // 7..5 c register operand (3 bits) + fH16, // 2..0 & 7..5 h register operand (6 bits) + fH16v2, // 1..0 & 7..5 h register operand (5 bits) + fH16v2_U5, // 1..0 & 7..5, 10&4..3 [h, u5] (u5=u3*4) + fG16, // 4..3 & 10..8 g register operand (5 bits) + fR16_2, // 9..8 R register operand (2 bits) + fR16_1, // 7 R register operand (1 bit) + S25, // 15..6 & 26..17 & 0..3 s25 signed branch displacement + S21, // 15..6 & 26..17 s21 signed branch displacement + S25L, // 15..6 & 26..18 & 0..3 s25 signed branch displacement for branch and link + S21L, // 15..6 & 26..18 s21 signed branch displacement for branch and link + S10, // 8..0 s10 signed branch displacement + S9, // 15..15 & 23..17 s9 signed branch displacement + S8, // 6..0 s8 signed branch displacement + S7, // 5..0 s7 signed branch displacement + S13, // 10..0 s13 signed branch displacement + U3, // 2..0 u2 unsigned immediate + U5, // 4..0 u5 unsigned immediate + U6, // 11..6 u6 unsigned immediate + U6_SWI, // 10..5 u6 unsigned immediate + U7, // 6..0 u7 unsigned immediate + U7L, // 4..0 u7 unsigned immediate (u5*4) + U8, // 7..0 u8 unsigned immediate + U6_16, // 6..4 & 2..0 u6 unsigned immediate + U7_16, // 7..4 & 2..0 u7 unsigned immediate + U10_16, // 9..0 u10 unsigned immediate + SP_U7, // 4..0 [SP, u7] stack + offset (u7 = u5*4) + PCL_U10, // 7..0 [PCL, u10] PCL + offset (u8*4) + fB_U5, // 10..8 & 4..0 [b, u5] + fB_U6, // 10..8 & 4..0 [b, u6] (u6=u5*2) + fB_U7, // 10..8 & 4..0 [b, u7] (u6=u5*4) + fB_S9, // 14..12&26..26, 15&23..16 [b, s9] + GENA, // 5..0 + GENB, // 14..12 & 26..24 + GENC, // 11..6 or 5..0 & 11..6 + GENC_PCREL, // 11..6 or 5..0 & 11..6 + fBC_IND, // 14..12 & 26..24, 11..6 [b, c] + fBC16_IND, // 10..8, 7..5 [b, c] + R_SP, // implicit SP + R_BLINK, // implicit BLINK + O_ZERO, // implicit immediate 0 + R_R0, // implicit R0 + R_R1, // implicit R1 + R_GP, // implicit GP + GP_S9, // 8..0 [GP, s9] GP + offset + GP_S10, // 8..0 [GP, s10] GP + offset (s10 = s9*2) + GP_S11, // 8..0 [GP, s11] GP + offset (s11 = s9*4) + S11, // 8..0 s11 signed immediate (s11 = s9*4) + GP_S11_16, // 10..5 & 4..2 [GP, s11] GP + offset (s11 = s9*4) + S3, // 10..8 s3 signed immediate + EL, // 4..1 & 10..8 enter / leave register set + + O_IND = 0x80000000, // [reg], [imm] (jumps: only [reg]) + O_WIDE = 0x40000000, // register pair rNrN+1 with N even + O_IDX = 0x20000000, // instruction specific index + + O_FLAGS = O_IND|O_WIDE|O_IDX, +}; + +// indexed by bit 16 (maj = 0) +static const arcompact_opcode_t arcompact_maj0[2] = +{ + { ARC_b, Q_4_0 | N_5, {S21, 0, 0}, NULL }, // 0 + { ARC_b, N_5, {S25, 0, 0}, NULL }, // 1 +}; + +// indexed by bit 17 (maj = 1, b16 = 0) +static const arcompact_opcode_t arcompact_bl[2] = +{ + { ARC_bl, Q_4_0 | N_5, {S21L, 0, 0}, NULL }, // 0 + { ARC_bl, N_5, {S25L, 0, 0}, NULL }, // 1 +}; + +// indexed by bits 3..0 (maj = 1, b16 = 1, b4 = 0) +static const arcompact_opcode_t arcompact_br_regreg[0x10] = +{ + { ARC_br, AUX_CND|cEQ|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x00 + { ARC_br, AUX_CND|cNE|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x01 + { ARC_br, AUX_CND|cLT|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x02 + { ARC_br, AUX_CND|cGE|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x03 + { ARC_br, AUX_CND|cLO|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x04 + { ARC_br, AUX_CND|cHS|N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x05 + { ARC_bbit0, N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x06 + { ARC_bbit1, N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x07 + { ARC_br, AUX_CND|cEQ|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x08 + { ARC_br, AUX_CND|cNE|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x09 + { ARC_br, AUX_CND|cLT|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0A + { ARC_br, AUX_CND|cGE|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0B + { ARC_br, AUX_CND|cLO|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0C + { ARC_br, AUX_CND|cHS|N_5|Y_3|AUX_V2, {fB32, fC32, S9}, NULL }, // 0x0D + { ARC_bbit0, N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x0E + { ARC_bbit1, N_5|Y_3, {fB32, fC32, S9}, NULL }, // 0x0F +}; + +// indexed by bits 3..0 (maj = 1, b16 = 1, b4 = 1) +static const arcompact_opcode_t arcompact_br_regimm[0x10] = +{ + { ARC_br, AUX_CND|cEQ|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x00 + { ARC_br, AUX_CND|cNE|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x01 + { ARC_br, AUX_CND|cLT|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x02 + { ARC_br, AUX_CND|cGE|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x03 + { ARC_br, AUX_CND|cLO|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x04 + { ARC_br, AUX_CND|cHS|N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x05 + { ARC_bbit0, N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x06 + { ARC_bbit1, N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x07 + { ARC_br, AUX_CND|cEQ|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x08 + { ARC_br, AUX_CND|cNE|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x09 + { ARC_br, AUX_CND|cLT|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0A + { ARC_br, AUX_CND|cGE|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0B + { ARC_br, AUX_CND|cLO|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0C + { ARC_br, AUX_CND|cHS|N_5|Y_3|AUX_V2, {fB32, U6, S9}, NULL }, // 0x0D + { ARC_bbit0, N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x0E + { ARC_bbit1, N_5|Y_3, {fB32, U6, S9}, NULL }, // 0x0F +}; + +// indexed by bit 4 (maj = 1, b16 = 1) +static const arcompact_opcode_t arcompact_br[4] = +{ + { SUBTABLE( 3, 0, arcompact_br_regreg) }, // 0 + { SUBTABLE( 3, 0, arcompact_br_regimm) }, // 1 +}; + +// indexed by bit 16 (maj = 1) +static const arcompact_opcode_t arcompact_maj1[0x40] = +{ + { SUBTABLE(17, 17, arcompact_bl) }, // 0 + { SUBTABLE( 4, 4, arcompact_br) }, // 1 +}; + +// indexed by bits 14..12 & 26..24 (maj = 4, 21..16=0x2F, 5..0=0x3F) +static const arcompact_opcode_t arcompact_zop[0x40] = +{ + { 0 }, // 0x00 + { ARC_sleep, 0, {GENC, 0, 0}, NULL }, // 0x01 + { ARC_swi, 0, { 0, 0, 0}, NULL }, // 0x02 + { ARC_sync, 0, { 0, 0, 0}, NULL }, // 0x03 + { ARC_rtie, 0, { 0, 0, 0}, NULL }, // 0x04 + { ARC_brk, 0, { 0, 0, 0}, NULL }, // 0x05 + { ARC_seti,AUX_V2,{GENC, 0, 0}, NULL }, // 0x06 + { ARC_clri,AUX_V2,{GENC, 0, 0}, NULL }, // 0x07 + { ARC_wevt, 0, {GENC, 0, 0}, NULL }, // 0x08 + { 0 }, // 0x09 + { 0 }, // 0x0A + { 0 }, // 0x0B + { 0 }, // 0x0C + { 0 }, // 0x0D + { 0 }, // 0x0E + { 0 }, // 0x0F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { 0 }, // 0x28 + { 0 }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { 0 }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F +}; + +// indexed by bits 5..0 (maj = 4, 21..16=0x2F) +static const arcompact_opcode_t arcompact_sop[0x40] = +{ + { ARC_asl, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x00 + { ARC_asr, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x01 + { ARC_lsr, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x02 + { ARC_ror, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x03 + { ARC_rrc, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x04 + { ARC_sexb, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x05 + { ARC_sexw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x06 + { ARC_extb, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x07 + { ARC_extw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x08 + { ARC_abs, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x09 + { ARC_not, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0A + { ARC_rlc, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0B + { ARC_ex, AUX_GEN, {GENB, GENC|O_IND,0},NULL}, // 0x0C + { ARC_rol, AUX_V2|AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0D + { 0 }, // 0x0E + { 0 }, // 0x0F + { ARC_llock,AUX_GEN, {GENB, GENC|O_IND, 0}, NULL }, // 0x10 + { ARC_scond,AUX_GEN, {GENB, GENC|O_IND, 0}, NULL }, // 0x11 + { 0 }, // 0x12 + { 0 }, // 0x13 + { 0 }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { 0 }, // 0x18 + { 0 }, // 0x19 + { 0 }, // 0x1A + { 0 }, // 0x1B + { 0 }, // 0x1C + { 0 }, // 0x1D + { 0 }, // 0x1E + { 0 }, // 0x1F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { 0 }, // 0x28 + { 0 }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { 0 }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { SUBTABLE2(14, 12, 26, 24, arcompact_zop) },// 0x3F +}; + +// indexed by bits 21..16 (maj = 4) +static const arcompact_opcode_t arcompact_maj4[0x40] = +{ + { ARC_add, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00 + { ARC_adc, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01 + { ARC_sub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02 + { ARC_sbc, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03 + { ARC_and, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x04 + { ARC_or, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x05 + { ARC_bic, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06 + { ARC_xor, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07 + { ARC_max, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08 + { ARC_min, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x09 + { ARC_mov, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0A + { ARC_tst, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x0B + { ARC_cmp, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x0C + { ARC_rcmp, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x0D + { ARC_rsub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E + { ARC_bset, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F + { ARC_bclr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10 + { ARC_btst, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x11 + { ARC_bxor, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x12 + { ARC_bmsk, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x13 + { ARC_add1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x14 + { ARC_add2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x15 + { ARC_add3, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x16 + { ARC_sub1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x17 + { ARC_sub2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x18 + { ARC_sub3, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x19 + { ARC_mpy, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1A + { ARC_mpyh, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1B + { ARC_mpyhu,AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C + { ARC_mpyu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D + { ARC_mpyw, AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1E + { ARC_mpyuw,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1F + { ARC_j, AUX_GEN, {GENC|O_IND, 0, 0}, NULL }, // 0x20 + { ARC_j, AUX_GEN|AUX_D, {GENC|O_IND, 0, 0}, NULL }, // 0x21 + { ARC_jl, AUX_GEN, {GENC|O_IND, 0, 0}, NULL }, // 0x22 + { ARC_jl, AUX_GEN|AUX_D, {GENC|O_IND, 0, 0}, NULL }, // 0x23 + { ARC_bi, AUX_V2, {fC32|O_IDX, 0, 0}, NULL }, // 0x24 + { ARC_bih, AUX_V2, {fC32|O_IDX, 0, 0}, NULL }, // 0x25 + { ARC_ldi, AUX_V2|Q_5_0, {GENB, GENC|O_IDX, 0}, NULL }, // 0x26 + { ARC_aex, AUX_V2|AUX_GEN2, {fB32, GENC|O_IND, 0}, NULL }, // 0x27 + { ARC_lp, AUX_GEN2, {GENC_PCREL, 0, 0}, NULL }, // 0x28 + { ARC_flag, AUX_GEN2, {GENC, 0, 0}, NULL }, // 0x29 + { ARC_lr, 0, {GENB, GENC|O_IND, 0}, NULL }, // 0x2A + { ARC_sr, 0, {GENB, GENC|O_IND, 0}, NULL }, // 0x2B + { ARC_bmskn,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C + { ARC_null, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C + { ARC_null, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D + { SUBTABLE(5, 0, arcompact_sop) }, // 0x2F + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x30 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x31 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x32 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x33 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x34 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x35 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x36 + { ARC_ld, AAZZXD_23_15, {fA32, fBC_IND, 0}, NULL }, // 0x37 + { ARC_seteq,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x38 + { ARC_setne,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x39 + { ARC_setlt,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3A + { ARC_setge,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3B + { ARC_setlo,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3C + { ARC_seths,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3D + { ARC_setle,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3E + { ARC_setgt,AUX_V2|AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3F +}; + +// indexed by bits 14..12 & 26..24 (maj = 5, 21..16=0x2F, 5..0=0x3F) +static const arcompact_opcode_t arcompact_zop5[0x40 * 2] = +{ + { ARC_aslacc, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x00 + { ARC_aslsacc, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x01 + { 0 }, // 0x02 + { 0 }, // 0x03 + { 0, AUX_F, {0, 0, 0}, NULL }, // 0x04(F=0) + { ARC_modif, AUX_V2|AUX_F, {GENC, 0, 0}, NULL }, // 0x05 + { 0 }, // 0x06 + { 0 }, // 0x07 + { 0 }, // 0x08 + { 0 }, // 0x09 + { 0 }, // 0x0A + { 0 }, // 0x0B + { 0 }, // 0x0C + { 0 }, // 0x0D + { 0 }, // 0x0E + { 0 }, // 0x0F + { 0 }, // 0x10 + { 0 }, // 0x11 + { 0 }, // 0x12 + { 0 }, // 0x13 + { 0 }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { 0 }, // 0x18 + { 0 }, // 0x19 + { 0 }, // 0x1A + { 0 }, // 0x1B + { 0 }, // 0x1C + { 0 }, // 0x1D + { 0 }, // 0x1E + { 0 }, // 0x1F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { 0 }, // 0x28 + { 0 }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { 0 }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F + + { 0 }, // 0x00 + { 0 }, // 0x01 + { 0 }, // 0x02 + { 0 }, // 0x03 + { ARC_flagacc, AUX_V2, {GENC, 0, 0}, NULL }, // 0x04(F=1) + { 0 }, // 0x05 + { 0 }, // 0x06 + { 0 }, // 0x07 + { 0 }, // 0x08 + { 0 }, // 0x09 + { 0 }, // 0x0A + { 0 }, // 0x0B + { 0 }, // 0x0C + { 0 }, // 0x0D + { 0 }, // 0x0E + { 0 }, // 0x0F + { 0 }, // 0x10 + { 0 }, // 0x11 + { 0 }, // 0x12 + { 0 }, // 0x13 + { 0 }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { 0 }, // 0x18 + { 0 }, // 0x19 + { 0 }, // 0x1A + { 0 }, // 0x1B + { 0 }, // 0x1C + { 0 }, // 0x1D + { 0 }, // 0x1E + { 0 }, // 0x1F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { 0 }, // 0x28 + { 0 }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { 0 }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F +}; + +// indexed by bits 5..0 (maj = 5, 21..16=0x2F) +static const arcompact_opcode_t arcompact_sop5[0x40] = +{ + { ARC_swap, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x00 + { ARC_norm, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x01 + { ARC_sat16, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x02 + { ARC_rnd16, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x03 + { ARC_abssw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x04 + { ARC_abss, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x05 + { ARC_negsw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x06 + { ARC_negs, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x07 + { ARC_normw, AUX_GEN, {GENB, GENC, 0}, NULL }, // 0x08 + { ARC_swape, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x09 + { ARC_lsl16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0A + { ARC_lsr16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0B + { ARC_asr16, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0C + { ARC_asr8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0D + { ARC_lsr8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0E + { ARC_lsl8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x0F + { ARC_rol8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x10 + { ARC_ror8, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x11 + { ARC_ffs, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x12 + { ARC_fls, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x13 + { 0 }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { ARC_getacc, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x18 + { ARC_normacc, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x19 + { ARC_satf, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1A + { 0 }, // 0x1B + { ARC_vpack2hbl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1C + { ARC_vpack2hbm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1D + { ARC_vpack2hblf,AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1E + { ARC_vpack2hbmf,AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x1F + { ARC_vext2bhlf, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x20 + { ARC_vext2bhmf, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x21 + { ARC_vrep2hl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x22 + { ARC_vrep2hm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x23 + { ARC_vext2bhl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x24 + { ARC_vext2bhm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x25 + { ARC_vsext2bhl, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x26 + { ARC_vsext2bhm, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x27 + { ARC_vabs2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x28 + { ARC_vabss2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x29 + { ARC_vneg2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2A + { ARC_vnegs2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2B + { ARC_vnorm2h, AUX_GEN2|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2C + { 0 }, // 0x2D + { ARC_bspeek, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2E + { ARC_bspop, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x2F + { ARC_sqrt, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x30 + { ARC_sqrtf, AUX_GEN|AUX_V2, {GENB, GENC, 0}, NULL }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { SUBTABLE2(14, 12, 26, 24, arcompact_zop5) }, // 0x3F +}; + +// indexed by bits 21..16 (maj = 5) +static const arcompact_opcode_t arcompact_maj5[0x40] = +{ + { ARC_asl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00 + { ARC_lsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01 + { ARC_asr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02 + { ARC_ror, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03 + { ARC_mul64, AUX_GEN, {O_ZERO,GENB,GENC}, NULL }, // 0x04 + { ARC_mulu64, AUX_GEN, {O_ZERO,GENB,GENC}, NULL }, // 0x05 + { ARC_adds, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06 + { ARC_subs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07 + { ARC_divaw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08 + { 0 }, // 0x09 + { ARC_asls, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A + { ARC_asrs, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0B + { ARC_muldw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0C + { ARC_muludw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0D + { ARC_mulrdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x0E + { 0 }, // 0x0F + { ARC_macdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x10 + { ARC_macudw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x11 + { ARC_macrdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x12 + { 0 }, // 0x13 + { ARC_msubdw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { 0 }, // 0x18 + { 0 }, // 0x19 + { 0 }, // 0x1A + { 0 }, // 0x1B + { 0 }, // 0x1C + { 0 }, // 0x1D + { 0 }, // 0x1E + { 0 }, // 0x1F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { ARC_addsdw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28 + { ARC_subsdw, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { SUBTABLE(5, 0, arcompact_sop5) }, // 0x2F + { ARC_mululw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x30 + { ARC_mullw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x31 + { ARC_mulflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x32 + { ARC_maclw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x33 + { ARC_macflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x34 + { ARC_machulw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x35 + { ARC_machlw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x36 + { ARC_machflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x37 + { ARC_mulhlw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x38 + { ARC_mulhflw, AUX_GEN, {GENB, GENC, GENC}, NULL }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F +}; + +// indexed by bits 21..16 (maj = 5) +static const arcompact_opcode_t arcv2_maj5[0x40 * 2] = +{ + { ARC_asl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x00 + { ARC_lsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x01 + { ARC_asr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x02 + { ARC_ror, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x03 + { ARC_div, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x04 + { ARC_divu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x05 + { ARC_adds, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x06 + { ARC_subs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x07 + { ARC_rem, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x08 + { ARC_remu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x09 + { ARC_asls, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A + { ARC_asrs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0B + { ARC_asrsr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0C + { ARC_valgn2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x0D(F=0) + { ARC_mac, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E + { ARC_macu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F + { ARC_dmpyh, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10 + { ARC_dmpyhu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x11 + { ARC_dmach, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x12 + { ARC_dmachu, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x13 + { ARC_vadd2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x14(F=0) + { ARC_vsub2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x15(F=0) + { ARC_vaddsub2h,AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x16(F=0) + { ARC_vsubadd2h,AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x17(F=0) + { ARC_mpyd, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x18 + { ARC_mpydu, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x19 + { ARC_macd, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1A + { ARC_macdu, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1B + { ARC_vmpy2h, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1C(F=0) + { ARC_vmpy2hu, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1D(F=0) + { ARC_vmac2h, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1E(F=0) + { ARC_vmac2hu, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x1F(F=0) + { ARC_vmpy2hwf, AUX_GEN|AUX_F, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x20(F=0) + { ARC_vasl2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x21(F=0) + { ARC_vasr2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x22(F=0) + { ARC_vlsr2h, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x23(F=0) + { ARC_vadd4b, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x24(F=0) + { ARC_vsub4b, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x25(F=0) + { ARC_adcs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x26 + { ARC_sbcs, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x27 + { ARC_dmpyhwf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28 + { ARC_vpack2hl, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x29(F=0) + { ARC_dmpyhf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2A + { ARC_dmpyhfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2B + { ARC_dmachf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C + { ARC_dmachfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2D + { ARC_vperm, AUX_GEN|AUX_F, {GENA, GENB, GENC}, NULL }, // 0x2E + { SUBTABLE(5, 0, arcompact_sop5) }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F + + { 0 }, // 0x00(F=1) + { 0 }, // 0x01(F=1) + { 0 }, // 0x02(F=1) + { 0 }, // 0x03(F=1) + { 0 }, // 0x04(F=1) + { 0 }, // 0x05(F=1) + { 0 }, // 0x06(F=1) + { 0 }, // 0x07(F=1) + { 0 }, // 0x08(F=1) + { 0 }, // 0x09(F=1) + { 0 }, // 0x0A(F=1) + { 0 }, // 0x0B(F=1) + { 0 }, // 0x0C(F=1) + { ARC_setacc, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x0D(F=1) + { 0 }, // 0x0E(F=1) + { 0 }, // 0x0F(F=1) + { 0 }, // 0x10(F=1) + { 0 }, // 0x11(F=1) + { 0 }, // 0x12(F=1) + { 0 }, // 0x13(F=1) + { ARC_vadds2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x14(F=1) + { ARC_vsubs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x15(F=1) + { ARC_vaddsubs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x16(F=1) + { ARC_vsubadds2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x17(F=1) + { 0 }, // 0x18(F=1) + { 0 }, // 0x19(F=1) + { 0 }, // 0x1A(F=1) + { 0 }, // 0x1B(F=1) + { ARC_vmpy2hf, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1C(F=1) + { ARC_vmpy2hfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1D(F=1) + { ARC_vmac2hf, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1E(F=1) + { ARC_vmac2hfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1F(F=1) + { 0 }, // 0x20(F=1) + { ARC_vasls2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x21(F=1) + { ARC_vasrs2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x22(F=1) + { ARC_vasrsr2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x23(F=1) + { ARC_vmax2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x24(F=1) + { ARC_vmin2h, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x25(F=1) + { 0 }, // 0x26(F=1) + { 0 }, // 0x27(F=1) + { 0 }, // 0x28(F=1) + { ARC_vpack2hm, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x29(F=1) + { 0 }, // 0x2A(F=1) + { 0 }, // 0x2B(F=1) + { 0 }, // 0x2C(F=1) + { 0 }, // 0x2D(F=1) + { ARC_bspush, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x2E(F=1) + { 0 }, // 0x2F(F=1) + { 0 }, // 0x30(F=1) + { 0 }, // 0x31(F=1) + { 0 }, // 0x32(F=1) + { 0 }, // 0x33(F=1) + { 0 }, // 0x34(F=1) + { 0 }, // 0x35(F=1) + { 0 }, // 0x36(F=1) + { 0 }, // 0x37(F=1) + { 0 }, // 0x38(F=1) + { 0 }, // 0x39(F=1) + { 0 }, // 0x3A(F=1) + { 0 }, // 0x3B(F=1) + { 0 }, // 0x3C(F=1) + { 0 }, // 0x3D(F=1) + { 0 }, // 0x3E(F=1) + { 0 }, // 0x3F(F=1) +}; + +// indexed by bits 21..16 +static const arcompact_opcode_t arcompact_maj6_1[0x40] = +{ + { ARC_fmul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 00 + { ARC_fadd, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 01 + { ARC_fsub, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 02 + { 0 }, // 03 + { 0 }, // 04 + { 0 }, // 05 + { 0 }, // 06 + { 0 }, // 07 + { ARC_dmulh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 08 + { ARC_dmulh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 09 + { ARC_dmulh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0a + { ARC_dmulh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0b + { ARC_daddh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0c + { ARC_daddh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0d + { ARC_daddh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0e + { ARC_daddh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0f + { ARC_dsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 10 + { ARC_dsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 11 + { ARC_dsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 12 + { ARC_dsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 13 + { ARC_drsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 14 + { ARC_drsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 15 + { ARC_drsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 16 + { ARC_drsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 17 + { ARC_dexcl1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 18 + { ARC_dexcl2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 19 + { 0 }, // 1a + { 0 }, // 1b + { 0 }, // 1c + { 0 }, // 1d + { 0 }, // 1e + { 0 }, // 1f + { ARC_pkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 20 + { ARC_upkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 21 + { ARC_xpkqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 22 + { ARC_avgqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 23 + { ARC_addqbs, AUX_GEN, {GENA, GENB, GENC}, NULL },// 24 + { ARC_mpyqb, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 25 + { ARC_fxtr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 26 + { ARC_iaddr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 27 + { ARC_acm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 28 + { ARC_sfxtr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 29 + { ARC_clamp, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 2a + { 0 }, // 2b + { 0 }, // 2c + { 0 }, // 2d + { 0 }, // 2e + { 0 }, // 2f + { 0 }, // 30 + { 0 }, // 31 + { 0 }, // 32 + { 0 }, // 33 + { 0 }, // 34 + { 0 }, // 35 + { 0 }, // 36 + { 0 }, // 37 + { 0 }, // 38 + { 0 }, // 39 + { 0 }, // 3a + { 0 }, // 3b + { 0 }, // 3c + { 0 }, // 3d + { 0 }, // 3e + { 0 } // 3f +}; + +// indexed by bits 23..22 +static const arcompact_opcode_t arcompact_maj6[4] = +{ + { SUBTABLE(21, 16, arcompact_maj6_1) }, // 00 + { SUBTABLE(21, 16, arcompact_maj6_1) }, // 01 + { SUBTABLE(21, 16, arcompact_maj6_1) }, // 02 + { 0 } // to be implemented +}; + +// indexed by bits 5..0 (maj = 6, 21..16=0x2F) +static const arcompact_opcode_t arcv2_sop6[0x40] = +{ + { ARC_fssqrt, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x00(F=0) reference doesn't specify minor opcode + { 0 }, // 0x01 + { 0 }, // 0x02 + { 0 }, // 0x03 + { 0 }, // 0x04 + { 0 }, // 0x05 + { 0 }, // 0x06 + { 0 }, // 0x07 + { 0 }, // 0x08 + { 0 }, // 0x09 + { 0 }, // 0x0A + { 0 }, // 0x0B + { 0 }, // 0x0C + { 0 }, // 0x0D + { 0 }, // 0x0E + { 0 }, // 0x0F + { 0 }, // 0x10 + { 0 }, // 0x11 + { 0 }, // 0x12 + { 0 }, // 0x13 + { 0 }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { 0 }, // 0x18 + { 0 }, // 0x18 + { 0 }, // 0x1A + { ARC_cbflyhf1r, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x1B(F=0) according to reference + { 0 }, // 0x1C + { 0 }, // 0x1D + { 0 }, // 0x1E + { 0 }, // 0x1F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { 0 }, // 0x28 + { 0 }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { 0 }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { ARC_cbflyhf1r, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x39(F=0) as encoded by the toolchain + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F +}; + +static const arcompact_opcode_t arcv2_maj6[0x40 * 2] = +{ + { ARC_fmul, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x00(F=0) + { ARC_fadd, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x01(F=0) + { ARC_fsub, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x02(F=0) + { ARC_vmsub2hfr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x03(F=0) + { ARC_vmsub2hf, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x04(F=0) + { ARC_fsmadd, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x05(F=0) + { ARC_fsmsub, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x06(F=0) + { ARC_fsdiv, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x07(F=0) + { ARC_fcvt32, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x08(F=0) + { 0, AUX_F, {0, 0, 0}, NULL }, // 0x09(F=0) + { ARC_mpyf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0A + { ARC_mpyfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0B + { ARC_macf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0C + { ARC_macfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0D + { ARC_msubf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0E + { ARC_msubfr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x0F + { ARC_divf, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x10 + { ARC_vmac2hnfr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x11 + { ARC_mpydf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x12 + { ARC_macdf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x13 + { ARC_msubwhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x14 + { ARC_msubdf, AUX_GEN, {GENA|O_WIDE, GENB, GENC}, NULL }, // 0x15 + { ARC_dmpyhbl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x16 + { ARC_dmpyhbm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x17 + { ARC_dmachbl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x18 + { ARC_dmachbm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x19 + { ARC_msubwhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1A + { ARC_cmpyhfmr, AUX_GEN|AUX_F,{GENA, GENB, GENC}, NULL }, // 0x1B + { ARC_mpywhl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1C + { ARC_macwhl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1D + { ARC_mpywhul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1E + { ARC_macwhul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x1F + { ARC_mpywhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x20 + { ARC_mpywhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x21 + { ARC_macwhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x22 + { ARC_macwhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x23 + { ARC_mpywhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x24 + { ARC_mpywhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x25 + { ARC_macwhfl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x26 + { ARC_macwhflr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x27 + { ARC_macwhkl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x28 + { ARC_macwhkul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x29 + { ARC_mpywhkl, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2A + { ARC_mpywhkul, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2B + { ARC_msubwhfm, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2C + { ARC_msubwhfmr, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x2D + { 0 }, // 0x2E + { SUBTABLE(5, 0, arcv2_sop6) }, // 0x2F + { ARC_dmulh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x30 + { ARC_dmulh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x31 + { ARC_dmulh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x32 + { ARC_dmulh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x33 + { ARC_daddh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x34 + { ARC_daddh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x35 + { ARC_daddh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x36 + { ARC_daddh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x37 + { ARC_dsubh11, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x38 + { ARC_dsubh12, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x39 + { ARC_dsubh21, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3A + { ARC_dsubh22, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3B + { ARC_dexcl1, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3C + { ARC_dexcl2, AUX_GEN, {GENA, GENB, GENC}, NULL }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F + + { ARC_cmpyhnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x00 + { ARC_cmpyhfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x01 + { ARC_cmpychnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x02 + { ARC_fscmp, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x03 + { ARC_fscmpf, AUX_GEN2, {GENB, GENC, 0}, NULL }, // 0x04 + { ARC_cmpychfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x05 + { ARC_cmachnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x06 + { ARC_cmachfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x07 + { ARC_cmacchnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x08 + { ARC_cmacchfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x09 + { 0 }, // 0x0A + { 0 }, // 0x0B + { 0 }, // 0x0C + { 0 }, // 0x0D + { 0 }, // 0x0E + { 0 }, // 0x0F + { 0 }, // 0x10 + { ARC_vmsub2hnfr, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x11 + { 0 }, // 0x12 + { 0 }, // 0x13 + { 0 }, // 0x14 + { 0 }, // 0x15 + { 0 }, // 0x16 + { 0 }, // 0x17 + { 0 }, // 0x18 + { 0 }, // 0x19 + { 0 }, // 0x1A + { ARC_cbflyhf0r, AUX_GEN2, {GENA, GENB, GENC}, NULL }, // 0x1B + { 0 }, // 0x1C + { 0 }, // 0x1D + { 0 }, // 0x1E + { 0 }, // 0x1F + { 0 }, // 0x20 + { 0 }, // 0x21 + { 0 }, // 0x22 + { 0 }, // 0x23 + { 0 }, // 0x24 + { 0 }, // 0x25 + { 0 }, // 0x26 + { 0 }, // 0x27 + { 0 }, // 0x28 + { 0 }, // 0x29 + { 0 }, // 0x2A + { 0 }, // 0x2B + { 0 }, // 0x2C + { 0 }, // 0x2D + { 0 }, // 0x2E + { 0 }, // 0x2F + { 0 }, // 0x30 + { 0 }, // 0x31 + { 0 }, // 0x32 + { 0 }, // 0x33 + { 0 }, // 0x34 + { 0 }, // 0x35 + { 0 }, // 0x36 + { 0 }, // 0x37 + { 0 }, // 0x38 + { 0 }, // 0x39 + { 0 }, // 0x3A + { 0 }, // 0x3B + { 0 }, // 0x3C + { 0 }, // 0x3D + { 0 }, // 0x3E + { 0 }, // 0x3F +}; + +// indexed by bits 4..3 (maj = 0xC) +static const arcompact_opcode_t arcompact_maj0C[4] = +{ + { ARC_ld, 0, { fA16, fBC16_IND, 0}, NULL }, // 0x0 + { ARC_ld, AUX_B, { fA16, fBC16_IND, 0}, NULL }, // 0x1 + { ARC_ld, AUX_W, { fA16, fBC16_IND, 0}, NULL }, // 0x2 + { ARC_add, 0, { fA16, fB16, fC16 }, NULL }, // 0x3 +}; + +// indexed by bits 4..3 (maj = 0xD) +static const arcompact_opcode_t arcompact_maj0D[4] = +{ + { ARC_add, 0, {fC16, fB16, U3 }, NULL }, // 0x00 + { ARC_sub, 0, {fC16, fB16, U3 }, NULL }, // 0x01 + { ARC_asl, 0, {fC16, fB16, U3 }, NULL }, // 0x02 + { ARC_asr, 0, {fC16, fB16, U3 }, NULL }, // 0x03 +}; + +// indexed by bits 4..3 (maj = 0xE) +static const arcompact_opcode_t arcompact_maj0E[4] = +{ + { ARC_add, 0, {fB16, fB16, fH16}, NULL }, // 0x00 + { ARC_mov, 0, {fB16, fH16, 0 }, NULL }, // 0x01 + { ARC_cmp, 0, {fB16, fH16, 0 }, NULL }, // 0x02 + { ARC_mov, 0, {fH16, fB16, 0 }, NULL }, // 0x03 +}; + +// indexed by bits 4..3 (maj = 0xE) +static const arcompact_opcode_t arcv2_maj0E[8] = +{ + { ARC_add, 0, {fB16, fB16, fH16v2}, NULL }, // 0x00 + { ARC_add, 0, {fH16v2, fH16v2, S3 }, NULL }, // 0x01 + { 0 }, // 0x02 + { ARC_mov, 0, {fH16v2, S3, 0 }, NULL }, // 0x03 + { ARC_cmp, 0, {fB16, fH16v2, 0 }, NULL }, // 0x04 + { ARC_cmp, 0, {fH16v2, S3, 0 }, NULL }, // 0x05 + { 0 }, // 0x06 + { ARC_mov, AUX_CND|cNE, {fB16, fH16v2, 0 }, NULL }, // 0x07 +}; + +// indexed by bits 10..8 (maj = 0xF, 4..0 = 0x0, 7..5=0x7) +// 01111 iii 111 00000 +static const arcompact_opcode_t arcompact_zop16[8] = +{ + { ARC_nop, 0, { 0, 0, 0}, NULL }, // 0x00 + { ARC_unimp, 0, { 0, 0, 0}, NULL }, // 0x01 + { ARC_swi, 0, { 0, 0, 0}, NULL }, // 0x02 + { 0 }, // 0x03 + { ARC_j, AUX_CND|cEQ, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x04 + { ARC_j, AUX_CND|cNE, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x05 + { ARC_j, 0, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x06 + { ARC_j, AUX_D, {R_BLINK|O_IND, 0, 0}, NULL }, // 0x07 +}; + +// indexed by bits 7..5 (maj = 0xF, 4..0 = 0x0) +// 01111 bbb iii 00000 +static const arcompact_opcode_t arcompact_sop16[8] = +{ + { ARC_j, 0, {fB16|O_IND, 0, 0}, NULL }, // 0x00 + { ARC_j, AUX_D, {fB16|O_IND, 0, 0}, NULL }, // 0x01 + { ARC_jl, 0, {fB16|O_IND, 0, 0}, NULL }, // 0x02 + { ARC_jl, AUX_D, {fB16|O_IND, 0, 0}, NULL }, // 0x03 + { 0 }, // 0x04 + { 0 }, // 0x05 + { ARC_sub, AUX_CND|cNE, {fB16, fB16, fB16}, NULL }, // 0x06 + { SUBTABLE(10, 8, arcompact_zop16) }, // 0x07 +}; + +// indexed by bits 4..0 (maj = 0xF) +// 01111 bbb ccc iiiii +static const arcompact_opcode_t arcompact_maj0F[0x20] = +{ + { SUBTABLE(7, 5, arcompact_sop16) }, // 0x00 + { 0 }, // 0x01 + { ARC_sub, 0, {fB16, fB16, fC16}, NULL }, // 0x02 + { 0 }, // 0x03 + { ARC_and, 0, {fB16, fB16, fC16}, NULL }, // 0x04 + { ARC_or, 0, {fB16, fB16, fC16}, NULL }, // 0x05 + { ARC_bic, 0, {fB16, fB16, fC16}, NULL }, // 0x06 + { ARC_xor, 0, {fB16, fB16, fC16}, NULL }, // 0x05 + { 0 }, // 0x08 + { 0 }, // 0x09 + { 0 }, // 0x0A + { ARC_tst, 0, {fB16, fC16, 0 }, NULL }, // 0x0B + { ARC_mul64, 0, {fB16, fC16, 0 }, NULL }, // 0x0C + { ARC_sexb, 0, {fB16, fC16, 0 }, NULL }, // 0x0D + { ARC_sexw, 0, {fB16, fC16, 0 }, NULL }, // 0x0E + { ARC_extb, 0, {fB16, fC16, 0 }, NULL }, // 0x0F + { ARC_extw, 0, {fB16, fC16, 0 }, NULL }, // 0x10 + { ARC_abs, 0, {fB16, fC16, 0 }, NULL }, // 0x11 + { ARC_not, 0, {fB16, fC16, 0 }, NULL }, // 0x12 + { ARC_neg, 0, {fB16, fC16, 0 }, NULL }, // 0x13 + { ARC_add1, 0, {fB16, fB16, fC16}, NULL }, // 0x14 + { ARC_add2, 0, {fB16, fB16, fC16}, NULL }, // 0x15 + { ARC_add3, 0, {fB16, fB16, fC16}, NULL }, // 0x16 + { 0 }, // 0x17 + { ARC_asl, 0, {fB16, fB16, fC16}, NULL }, // 0x18 + { ARC_lsr, 0, {fB16, fB16, fC16}, NULL }, // 0x19 + { ARC_asr, 0, {fB16, fB16, fC16}, NULL }, // 0x1A + { ARC_asl, 0, {fB16, fC16, 0 }, NULL }, // 0x1B + { ARC_asr, 0, {fB16, fC16, 0 }, NULL }, // 0x1C + { ARC_lsr, 0, {fB16, fC16, 0 }, NULL }, // 0x1D + { ARC_trap, 0, { 0, 0, 0 }, NULL }, // 0x1E + { ARC_brk, 0, { 0, 0, 0 }, NULL }, // 0x1F +}; + +// indexed by bits 4..0 (maj = 0xF) +// 01111 bbb ccc iiiii +static const arcompact_opcode_t arcv2_maj0F[0x20] = +{ + { SUBTABLE(7, 5, arcompact_sop16) }, // 0x00 + { 0 }, // 0x01 + { ARC_sub, 0, {fB16, fB16, fC16}, NULL }, // 0x02 + { 0 }, // 0x03 + { ARC_and, 0, {fB16, fB16, fC16}, NULL }, // 0x04 + { ARC_or, 0, {fB16, fB16, fC16}, NULL }, // 0x05 + { ARC_bic, 0, {fB16, fB16, fC16}, NULL }, // 0x06 + { ARC_xor, 0, {fB16, fB16, fC16}, NULL }, // 0x05 + { 0 }, // 0x08 + { ARC_mpyw, 0, {fB16, fB16, fC16}, NULL }, // 0x09 + { ARC_mpyuw, 0, {fB16, fB16, fC16}, NULL }, // 0x0A + { ARC_tst, 0, {fB16, fC16, 0 }, NULL }, // 0x0B + { ARC_mpy, 0, {fB16, fB16, fC16}, NULL }, // 0x0C breaking change + { ARC_sexb, 0, {fB16, fC16, 0 }, NULL }, // 0x0D + { ARC_sexw, 0, {fB16, fC16, 0 }, NULL }, // 0x0E + { ARC_extb, 0, {fB16, fC16, 0 }, NULL }, // 0x0F + { ARC_extw, 0, {fB16, fC16, 0 }, NULL }, // 0x10 + { ARC_abs, 0, {fB16, fC16, 0 }, NULL }, // 0x11 + { ARC_not, 0, {fB16, fC16, 0 }, NULL }, // 0x12 + { ARC_neg, 0, {fB16, fC16, 0 }, NULL }, // 0x13 + { ARC_add1, 0, {fB16, fB16, fC16}, NULL }, // 0x14 + { ARC_add2, 0, {fB16, fB16, fC16}, NULL }, // 0x15 + { ARC_add3, 0, {fB16, fB16, fC16}, NULL }, // 0x16 + { 0 }, // 0x17 + { ARC_asl, 0, {fB16, fB16, fC16}, NULL }, // 0x18 + { ARC_lsr, 0, {fB16, fB16, fC16}, NULL }, // 0x19 + { ARC_asr, 0, {fB16, fB16, fC16}, NULL }, // 0x1A + { ARC_asl, 0, {fB16, fC16, 0 }, NULL }, // 0x1B + { ARC_asr, 0, {fB16, fC16, 0 }, NULL }, // 0x1C + { ARC_lsr, 0, {fB16, fC16, 0 }, NULL }, // 0x1D + { ARC_trap, 0, {U6_SWI, 0, 0 }, NULL }, // 0x1E + { ARC_swi, 0, {U6_SWI, 0, 0 }, NULL }, // 0x1F +}; + +// indexed by bits 7..5 (maj = 0x17) +static const arcompact_opcode_t arcompact_maj17[8] = +{ + { ARC_asl, 0, {fB16, fB16, U5}, NULL }, // 0x00 + { ARC_lsr, 0, {fB16, fB16, U5}, NULL }, // 0x01 + { ARC_asr, 0, {fB16, fB16, U5}, NULL }, // 0x02 + { ARC_sub, 0, {fB16, fB16, U5}, NULL }, // 0x03 + { ARC_bset, 0, {fB16, fB16, U5}, NULL }, // 0x04 + { ARC_bclr, 0, {fB16, fB16, U5}, NULL }, // 0x05 + { ARC_bmsk, 0, {fB16, fB16, U5}, NULL }, // 0x06 + { ARC_btst, 0, {fB16, U5, 0}, NULL }, // 0x07 +}; + +// indexed by bits 10..8 (maj = 0x18, i=5) +static const arcompact_opcode_t arcompact_sp_addsub[8] = +{ + { ARC_add, 0, {R_SP, R_SP, U7L }, NULL }, // 0x00 + { ARC_sub, 0, {R_SP, R_SP, U7L }, NULL }, // 0x01 + { 0 }, // 0x02 + { 0 }, // 0x03 + { 0 }, // 0x04 + { 0 }, // 0x05 + { 0 }, // 0x06 + { 0 }, // 0x07 +}; + +// indexed by bits 4..0 (maj = 0x18, i=6) +static const arcompact_opcode_t arcompact_sp_pops[0x20] = +{ + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x00 + { ARC_pop, 0, {fB16, 0, 0}, NULL }, // 0x01 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x02 + { 0 }, // 0x03 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x04 + { 0 }, // 0x05 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x06 + { 0 }, // 0x07 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x08 + { 0 }, // 0x09 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0A + { 0 }, // 0x0B + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0C + { 0 }, // 0x0D + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x0E + { 0 }, // 0x0F + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x10 + { ARC_pop, 0, {R_BLINK, 0, 0}, NULL }, // 0x11 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x12 + { 0 }, // 0x13 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x14 + { 0 }, // 0x15 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x16 + { 0 }, // 0x17 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x18 + { 0 }, // 0x19 + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1A + { 0 }, // 0x1B + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1C + { 0 }, // 0x1D + { ARC_leave, AUX_V2, {EL, 0, 0}, NULL }, // 0x1E + { 0 }, // 0x1F +}; + +// indexed by bits 4..0 (maj = 0x18, i=7) +static const arcompact_opcode_t arcompact_sp_pushs[0x20] = +{ + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x00 + { ARC_push, 0, {fB16, 0, 0}, NULL }, // 0x01 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x02 + { 0 }, // 0x03 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x04 + { 0 }, // 0x05 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x06 + { 0 }, // 0x07 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x08 + { 0 }, // 0x09 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0A + { 0 }, // 0x0B + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0C + { 0 }, // 0x0D + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x0E + { 0 }, // 0x0F + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x10 + { ARC_push, 0, {R_BLINK, 0, 0}, NULL }, // 0x11 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x12 + { 0 }, // 0x13 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x14 + { 0 }, // 0x15 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x16 + { 0 }, // 0x17 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x18 + { 0 }, // 0x19 + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1A + { 0 }, // 0x1B + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1C + { 0 }, // 0x1D + { ARC_enter, AUX_V2, {EL, 0, 0}, NULL }, // 0x1E + { 0 }, // 0x1F +}; + +// indexed by bits 7..5 (maj = 0x18) +// sp-based instructions +static const arcompact_opcode_t arcompact_maj18[8] = +{ + { ARC_ld, 0, {fB16, SP_U7, 0 }, NULL }, // 0x00 + { ARC_ld, AUX_B, {fB16, SP_U7, 0 }, NULL }, // 0x01 + { ARC_st, 0, {fB16, SP_U7, 0 }, NULL }, // 0x02 + { ARC_st, AUX_B, {fB16, SP_U7, 0 }, NULL }, // 0x03 + { ARC_add, 0, {fB16, R_SP, U7L }, NULL }, // 0x04 + { SUBTABLE( 10, 8, arcompact_sp_addsub) }, // 0x05 + { SUBTABLE( 4, 0, arcompact_sp_pops) }, // 0x06 + { SUBTABLE( 4, 0, arcompact_sp_pushs) }, // 0x07 +}; + +// indexed by bits 10..9 (maj = 0x19) +// gp-based ld/add (data aligned offset) +static const arcompact_opcode_t arcompact_maj19[4] = +{ + { ARC_ld, 0, {R_R0, GP_S11, 0 }, NULL }, // 0x00 + { ARC_ld, AUX_B, {R_R0, GP_S9, 0 }, NULL }, // 0x01 + { ARC_ld, AUX_W, {R_R0, GP_S10, 0 }, NULL }, // 0x02 + { ARC_add, 0, {R_R0, R_GP, S11 }, NULL }, // 0x03 +}; + +// indexed by bits 7..7 (maj = 0x1C) +static const arcompact_opcode_t arcompact_maj1C[2] = +{ + { ARC_add, 0, { fB16, fB16, U7}, NULL }, // 0x00 + { ARC_cmp, 0, { fB16, U7, 0}, NULL }, // 0x01 +}; + +// indexed by bits 7..7 (maj = 0x1D) +static const arcompact_opcode_t arcompact_maj1D[2] = +{ + { ARC_br, AUX_CND|cEQ, { fB16, O_ZERO, S8}, NULL }, // 0x00 + { ARC_br, AUX_CND|cNE, { fB16, O_ZERO, S8}, NULL }, // 0x01 +}; + +// indexed by bits 8..6 (maj = 0x1E, 10..9=0x3) +static const arcompact_opcode_t arcompact_bcc16[8] = +{ + { ARC_b, AUX_CND|cGT, { S7, 0, 0}, NULL }, // 0x00 + { ARC_b, AUX_CND|cGE, { S7, 0, 0}, NULL }, // 0x01 + { ARC_b, AUX_CND|cLT, { S7, 0, 0}, NULL }, // 0x02 + { ARC_b, AUX_CND|cLE, { S7, 0, 0}, NULL }, // 0x03 + { ARC_b, AUX_CND|cHI, { S7, 0, 0}, NULL }, // 0x04 + { ARC_b, AUX_CND|cHS, { S7, 0, 0}, NULL }, // 0x05 + { ARC_b, AUX_CND|cLO, { S7, 0, 0}, NULL }, // 0x06 + { ARC_b, AUX_CND|cLS, { S7, 0, 0}, NULL }, // 0x07 +}; + +// indexed by bits 10..9 (maj = 0x1E) +static const arcompact_opcode_t arcompact_maj1E[4] = +{ + { ARC_b, 0, { S10, 0, 0}, NULL }, // 0x00 + { ARC_b, AUX_CND|cEQ, { S10, 0, 0}, NULL }, // 0x01 + { ARC_b, AUX_CND|cNE, { S10, 0, 0}, NULL }, // 0x02 + { SUBTABLE(8, 6, arcompact_bcc16) }, // 0x03 +}; + +// indexed by major opcode (bits 15..11) +static const arcompact_opcode_t arcompact_major[0x20] = +{ + { SUBTABLE(16, 16, arcompact_maj0) }, // 0x00 + { SUBTABLE(16, 16, arcompact_maj1) }, // 0x01 + { ARC_ld, DAAZZX_11_6, {fA32, fB_S9, 0}, NULL},// 0x02 + { ARC_st, DAAZZ_5_1, {fC32, fB_S9, 0}, NULL},// 0x03 + { SUBTABLE(21, 16, arcompact_maj4) }, // 0x04 + { SUBTABLE(21, 16, arcompact_maj5) }, // 0x05 + { SUBTABLE(23, 22, arcompact_maj6) }, // 0x06 + { 0 }, // 0x07 + { 0 }, // 0x08 + { 0 }, // 0x09 + { 0 }, // 0x0A + { 0 }, // 0x0B + { SUBTABLE( 4, 3, arcompact_maj0C) }, // 0x0C + { SUBTABLE( 4, 3, arcompact_maj0D) }, // 0x0D + { SUBTABLE( 4, 3, arcompact_maj0E) }, // 0x0E + { SUBTABLE( 4, 0, arcompact_maj0F) }, // 0x0F + { ARC_ld, 0, { fC16, fB_U7, 0}, NULL }, // 0x10 + { ARC_ld, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x11 + { ARC_ld, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x12 + { ARC_ld, AUX_W|AUX_X, { fC16, fB_U6, 0}, NULL },// 0x13 + { ARC_st, 0, { fC16, fB_U7, 0}, NULL }, // 0x14 + { ARC_st, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x15 + { ARC_st, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x16 + { SUBTABLE( 7, 5, arcompact_maj17) }, // 0x17 + { SUBTABLE( 7, 5, arcompact_maj18) }, // 0x18 + { SUBTABLE(10, 9, arcompact_maj19) }, // 0x19 + { ARC_ld, 0, { fB16, PCL_U10, 0}, NULL }, // 0x1A + { ARC_mov, 0, { fB16, U8, 0}, NULL }, // 0x1B + { SUBTABLE( 7, 7, arcompact_maj1C) }, // 0x1C + { SUBTABLE( 7, 7, arcompact_maj1D) }, // 0x1D + { SUBTABLE(10, 9, arcompact_maj1E) }, // 0x1E + { ARC_bl, 0, { S13, 0, 0}, NULL }, // 0x1F +}; + +// indexed by bit 2 (maj = 8) +static const arcompact_opcode_t arcv2_maj8[2] = +{ + { ARC_mov, 0, {fG16, fH16v2, 0}, NULL }, // 0x00 + { ARC_ld, 0, {fR16_2, fH16v2_U5, 0}, NULL }, // 0x01 +}; + +// indexed by bits 4..3 (maj = 8) +static const arcompact_opcode_t arcv2_maj9[4] = +{ + { ARC_ld, AUX_AS, {fA16, fBC16_IND, 0}, NULL }, // 0x00 + { ARC_add, 0, {fR16_1, fB16, U6_16}, NULL }, // 0x01 + { ARC_sub, 0, {fA16, fB16, fC16}, NULL }, // 0x02 + { ARC_add, 0, {fR16_1, fB16, U6_16}, NULL }, // 0x03 +}; + +// indexed by bits 4..3 (maj = 0x0A) +static const arcompact_opcode_t arcv2_maj0A[4] = +{ + { ARC_ld, 0, {R_R1, GP_S11_16, 0}, NULL }, // 0x00 + { ARC_ldi, 0, {fB16, U7_16|O_IDX, 0}, NULL }, // 0x01 + { ARC_st, 0, {R_R0, GP_S11_16, 0}, NULL }, // 0x02 + { ARC_ldi, 0, {fB16, U7_16|O_IDX, 0}, NULL }, // 0x03 +}; + +// indexed by bit 10 (maj = 0x0B) +static const arcompact_opcode_t arcv2_maj0B[2] = +{ + { ARC_jli, 0, {U10_16|O_IDX, 0, 0}, NULL }, // 0x00 + { ARC_ei, 0, {U10_16|O_IDX, 0, 0}, NULL }, // 0x01 +}; + + +// indexed by major opcode (bits 15..11) +static const arcompact_opcode_t arcv2_major[0x20] = +{ + { SUBTABLE(16, 16, arcompact_maj0) }, // 0x00 + { SUBTABLE(16, 16, arcompact_maj1) }, // 0x01 + { ARC_ld, DAAZZX_11_6, {fA32, fB_S9, 0}, NULL},// 0x02 + { ARC_st, DAAZZ_5_1, {fC32_w6, fB_S9, 0}, NULL},// 0x03 + { SUBTABLE(21, 16, arcompact_maj4) }, // 0x04 + { SUBTABLE(21, 16, arcv2_maj5) }, // 0x05 + { SUBTABLE(21, 16, arcv2_maj6) }, // 0x06 + { 0 }, // 0x07 + { SUBTABLE( 2, 2, arcv2_maj8) }, // 0x08 + { SUBTABLE( 4, 3, arcv2_maj9) }, // 0x09 + { SUBTABLE( 4, 3, arcv2_maj0A) }, // 0x0A + { SUBTABLE(10, 10, arcv2_maj0B) }, // 0x0B + { SUBTABLE( 4, 3, arcompact_maj0C) }, // 0x0C + { SUBTABLE( 4, 3, arcompact_maj0D) }, // 0x0D + { SUBTABLE( 4, 2, arcv2_maj0E) }, // 0x0E + { SUBTABLE( 4, 0, arcv2_maj0F) }, // 0x0F + { ARC_ld, 0, { fC16, fB_U7, 0}, NULL }, // 0x10 + { ARC_ld, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x11 + { ARC_ld, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x12 + { ARC_ld, AUX_W|AUX_X, { fC16, fB_U6, 0}, NULL }, // 0x13 + { ARC_st, 0, { fC16, fB_U7, 0}, NULL }, // 0x14 + { ARC_st, AUX_B, { fC16, fB_U5, 0}, NULL }, // 0x15 + { ARC_st, AUX_W, { fC16, fB_U6, 0}, NULL }, // 0x16 + { SUBTABLE( 7, 5, arcompact_maj17) }, // 0x17 + { SUBTABLE( 7, 5, arcompact_maj18) }, // 0x18 + { SUBTABLE(10, 9, arcompact_maj19) }, // 0x19 + { ARC_ld, 0, { fB16, PCL_U10, 0}, NULL }, // 0x1A + { ARC_mov, 0, { fB16, U8, 0}, NULL }, // 0x1B + { SUBTABLE( 7, 7, arcompact_maj1C) }, // 0x1C + { SUBTABLE( 7, 7, arcompact_maj1D) }, // 0x1D + { SUBTABLE(10, 9, arcompact_maj1E) }, // 0x1E + { ARC_bl, 0, { S13, 0, 0}, NULL }, // 0x1F +}; + +// extract bit numbers high..low from val (inclusive, start from 0) +#define BITS(val, high, low) ( ((val)>>low) & ( (1<<(high-low+1))-1) ) +// sign extend b low bits in x +// from "Bit Twiddling Hacks" +static sval_t SIGNEXT(sval_t x, int b) +{ + uint32 m = 1 << (b - 1); + x &= ((sval_t(1) << b) - 1); + return (x ^ m) - m; +} + +// extract bitfield with sign extension +#define SBITS(val, high, low) SIGNEXT(BITS(val, high, low), high-low+1) + +//---------------------------------------------------------------------- +int arc_t::get_limm(insn_t &insn) +{ + if ( !got_limm ) + { + g_limm = (insn.get_next_word() << 16); + g_limm |= insn.get_next_word(); + got_limm = true; + } + return g_limm; +} + +//---------------------------------------------------------------------- +// register, or a reference to long immediate (r62) +inline void arc_t::opreg(insn_t &insn, op_t &x, int rgnum, int limm) +{ + if ( rgnum != limm ) + { + x.reg = uint16(rgnum); + x.type = o_reg; + } + else + { + x.type = o_imm; + // limm as destination is not used + // so check for instructions where first operand is source + if ( x.n == 0 && (insn.get_canon_feature(ph) & CF_CHG1) != 0 ) + x.value = 0; + else + x.value = get_limm(insn); + } + x.dtype = dt_dword; +} + +//---------------------------------------------------------------------- +inline void opimm(op_t &x, uval_t val) +{ + x.value = val; + x.type = o_imm; + x.dtype = dt_dword; +} + +//---------------------------------------------------------------------- +inline void arc_t::opdisp(insn_t &insn, op_t &x, int rgnum, ea_t disp) +{ + if ( rgnum != LIMM ) + { + x.type = o_displ; + x.addr = disp; + x.reg = rgnum; + } + else + { + x.type = o_mem; + x.immdisp = disp; + x.addr = get_limm(insn) + disp * get_scale_factor(insn); + } + x.dtype = dt_dword; +} + +//---------------------------------------------------------------------- +inline int reg16(int rgnum) +{ + // 0..3 r0-r3 + // 4..7 r12-r15 + return ( rgnum > 3 ) ? (rgnum + 8) : rgnum; +} + +//---------------------------------------------------------------------- +inline void opbranch(const insn_t &insn, op_t &x, sval_t delta) +{ + // cPC <- (cPCL+delta) + // PCL is current instruction address with 2 low bits set to 0 + ea_t pcl = insn.ip & ~3ul; + x.type = o_near; + x.dtype = dt_code; + x.addr = pcl + delta; +} + +//---------------------------------------------------------------------- +void arc_t::decode_operand( + insn_t &insn, + uint32 code, + int &op_pos, + uint32 opkind) +{ + op_t &x = insn.ops[op_pos]; + ++op_pos; + if ( opkind == 0 ) + { + x.type = o_void; + return; + } + int reg, p; + sval_t displ; + switch ( opkind & ~O_FLAGS ) + { + case fA16: + opreg(insn, x, reg16(BITS(code, 2, 0))); + break; + case fB16: + opreg(insn, x, reg16(BITS(code, 10, 8))); + break; + case fC16: + opreg(insn, x, reg16(BITS(code, 7, 5))); + break; + + case fA32: // 5..0 a register operand (6 bits, r0-r63) + opreg(insn, x, BITS(code, 5, 0)); + break; + case fB32: // 14..12 & 26..24 b register operand (6 bits) + opreg(insn, x, (BITS(code, 14, 12)<<3) | BITS(code, 26, 24)); + break; + case fC32: // 11..6 c register operand (6 bits) + opreg(insn, x, BITS(code, 11, 6)); + break; + case fC32_w6: // 11..6 & 0 c/w6 register/immediate operand (6 bits) + if ( BITS(code, 0, 0) != 0 ) + opimm(x, SBITS(code, 11, 6)); + else + opreg(insn, x, BITS(code, 11, 6)); + break; + case fH16: // 2..0 & 7..5 h register operand (6 bits) + reg = (BITS(code, 2, 0) << 3) | BITS(code, 7, 5); + opreg(insn, x, reg); + break; + case fH16v2: // 1..0 & 7..5 h register operand (5 bits) + reg = (BITS(code, 1, 0) << 3) | BITS(code, 7, 5); + opreg(insn, x, reg, LIMM5); + break; + case fH16v2_U5: // 1..0 & 7..5, 10&4..3 [h, u5] (u5=u3*4) + displ = ((BITS(code, 10, 10) << 2) | BITS(code, 4, 3)) * 4; + reg = (BITS(code, 1, 0) << 3) | BITS(code, 7, 5); + opdisp(insn, x, reg, displ); + break; + case fG16: // 4..3 & 10..8 g register operand (5 bits) + reg = (BITS(code, 4, 3) << 3) | BITS(code, 10, 8); + opreg(insn, x, reg, LIMM5); + break; + case fR16_2: // 9..8 R register operand (2 bits) + opreg(insn, x, BITS(code, 9, 8)); + break; + case fR16_1: // 7 R register operand (1 bits) + opreg(insn, x, BITS(code, 7, 7)); + break; + + case S25L: // 15..6 & 26..18 & 0..3 s25 signed branch displacement for branch and link + case S21L: // 15..6 & 26..18 s21 signed branch displacement for branch and link + case S25: // 15..6 & 26..17 & 3..0 s25 signed branch displacement + case S21: // 15..6 & 26..17 s21 signed branch displacement + displ = (BITS(code, 15, 6) << 10) | BITS(code, 26, 17); + if ( opkind == S25 || opkind == S25L ) + { + displ |= BITS(code, 3, 0) << 20; + if ( displ & (1ul<<23) ) + displ -= (1ul<<24); + } + else + { + if ( displ & (1ul<<19) ) + displ -= (1ul<<20); + } + if ( opkind == S25L || opkind == S21L ) + { + // branch-and-link uses 32-bit aligned target + displ &= ~1ul; + } + opbranch(insn, x, displ * 2); + break; + + case S9: // 15&23..17 s9 signed branch displacement (16-bit aligned) + displ = BITS(code, 23, 17); + if ( BITS(code, 15, 15) ) // sign bit + displ -= (1ul<<7); + opbranch(insn, x, displ * 2); + break; + + case S7: // 5..0 s7 signed branch displacement (16-bit aligned) + displ = SBITS(code, 5, 0); + opbranch(insn, x, displ * 2); + break; + + case S8: // 6..0 s8 signed branch displacement (16-bit aligned) + displ = SBITS(code, 6, 0); + opbranch(insn, x, displ * 2); + break; + + case S10: // 8..0 s10 signed branch displacement (16-bit aligned) + displ = SBITS(code, 8, 0); + opbranch(insn, x, displ * 2); + break; + + case S13: // 10..0 s13 signed branch displacement (32-bit aligned) + displ = SBITS(code, 10, 0); + opbranch(insn, x, displ * 4); + break; + + case PCL_U10: + displ = BITS(code, 7, 0); + opdisp(insn, x, PCL, displ*4); + break; + + case SP_U7: // 4..0 [SP, u7] stack + offset (u7 = u5*4) + displ = BITS(code, 4, 0); + opdisp(insn, x, SP, displ*4); + break; + + case S3: // 10..8 s3 signed immediate + p = BITS(code, 10, 8); + opimm(x, p == 7 ? -1 : p); + break; + + case U3: // 2..0 u2 unsigned immediate + opimm(x, BITS(code, 2, 0)); + break; + + case U7: + opimm(x, BITS(code, 6, 0)); + break; + + case U6: + opimm(x, BITS(code, 11, 6)); + break; + + case U6_SWI: + opimm(x, BITS(code, 10, 5)); + break; + + case U5: + case U7L: + displ = BITS(code, 4, 0); + if ( opkind == U7L ) + displ *= 4; + opimm(x, displ); + break; + + case U8: + opimm(x, BITS(code, 7, 0)); + break; + + case U6_16: // 6..4 & 2..0 u6 unsigned immediate + opimm(x, (BITS(code, 6, 4) << 3) | BITS(code, 2, 0)); + break; + + case U7_16: // 7..4 & 2..0 u7 unsigned immediate + opimm(x, (BITS(code, 7, 4) << 3) | BITS(code, 2, 0)); + break; + + case U10_16: + opimm(x, BITS(code, 9, 0)); + break; + + case fB_U5: // 10..8 & 4..0 [b, u5] + case fB_U6: // 10..8 & 4..0 [b, u6] (u6=u5*2) + case fB_U7: // 10..8 & 4..0 [b, u7] (u6=u5*4) + displ = BITS(code, 4, 0); + if ( opkind == fB_U6 ) + displ *= 2; + else if ( opkind == fB_U7 ) + displ *= 4; + reg = reg16(BITS(code, 10, 8)); + opdisp(insn, x, reg, displ); + break; + + case fB_S9: // 14..12&26..26, 15&23..16 [b, s9] + displ = BITS(code, 23, 16); + if ( BITS(code, 15, 15) ) // sign bit + displ -= (1ul<<8); + reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); + opdisp(insn, x, reg, displ); + break; + + // handing of the "gen" format: + // P M + // REG_REG 00 N/A Destination and both sources are registers + // REG_U6IMM 01 N/A Source 2 is a 6-bit unsigned immediate + // REG_S12IMM 10 N/A Source 2 is a 12-bit signed immediate + // COND_REG 11 0 Conditional instruction. Destination (if any) is source 1. Source 2 is a register + // COND_REG_U6IMM 11 1 Conditional instruction. Destination (if any) is source 1. Source 2 is a 6-bit unsigned immediate + // P=23..22, M=5 + // 0x04, [0x00 - 0x3F] + // 00100 bbb 00 iiiiii F BBB CCCCCC AAAAAA reg-reg op<.f> a,b,c + // 00100 bbb 01 iiiiii F BBB UUUUUU AAAAAA reg-u6imm op<.f> a,b,u6 + // 00100 bbb 10 iiiiii F BBB ssssss SSSSSS reg-s12imm op<.f> b,b,s12 + // 00100 bbb 11 iiiiii F BBB CCCCCC 0 QQQQQ cond reg-reg op<.cc><.f> b,b,c + // 00100 bbb 11 iiiiii F BBB UUUUUU 1 QQQQQ cond reg-u6 op<.cc><.f> b,b,u6 + // 0x04, [0x30 - 0x37] + // 00100 bbb aa 110 ZZ X D BBB CCCCCC AAAAAA LD<zz><.x><.aa><.di> a,[b,c] + + case GENA: // 5..0 + p = BITS(code, 23, 22); + if ( p <= 1 ) + reg = BITS(code, 5, 0); + else + reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); + opreg(insn, x, reg); + break; + + case GENB: // 14..12 & 26..24 + reg = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); + opreg(insn, x, reg); + break; + + case GENC: // 11..6 reg/u6 or 0..5&11..6 s12 + case GENC_PCREL: // 11..6 u6 or 0..5&11..6 s12 pc-relative displacement + p = BITS(code, 23, 22); + if ( p != 2 ) + { + reg = BITS(code, 11, 6); + if ( p == 0 || (p == 3 && BITS(code, 5, 5) == 0) ) + opreg(insn, x, reg); + else + opimm(x, reg); + } + else + { + // s12 + reg = (BITS(code, 5, 0) << 6) | BITS(code, 11, 6); + reg = SIGNEXT(reg, 12); + opimm(x, reg); + } + if ( (opkind & ~O_IND) == GENC_PCREL && x.type == o_imm ) + opbranch(insn, x, reg * 2); + break; + + case fBC_IND: + { + int b = (BITS(code, 14, 12)<<3) | BITS(code, 26, 24); + int c = BITS(code, 11, 6); + int li = 0; + if ( b == LIMM || c == LIMM ) + li = get_limm(insn); + doIndirectOperand(insn, b, c, x, 0, li, false); + } + break; + + case fBC16_IND: + { + int b = BITS(code, 10, 8); + int c = BITS(code, 7, 5); + doIndirectOperand(insn, reg16(b), reg16(c), x, 0, 0, false); + } + break; + + case O_ZERO: + opimm(x, 0); + break; + + case R_SP: // implicit SP + opreg(insn, x, SP); + break; + + case R_BLINK: // implicit BLINK + opreg(insn, x, BLINK); + break; + + case R_R0: // implicit R0 + opreg(insn, x, R0); + break; + + case R_R1: // implicit R1 + opreg(insn, x, R1); + break; + + case R_GP: // implicit GP + opreg(insn, x, GP); + break; + + case GP_S9: // 8..0 [GP, s9] GP + offset + case GP_S10: // 8..0 [GP, s10] GP + offset (s10 = s9*2) + case GP_S11: // 8..0 [GP, s11] GP + offset (s11 = s9*4) + case S11: // 8..0 s11 signed immediate (s11 = s9*4) + displ = SBITS(code, 8, 0); + if ( opkind == GP_S10 ) + displ *= 2; + else if ( opkind != GP_S9 ) + displ *= 4; + if ( opkind == S11 ) + opimm(x, displ); + else + opdisp(insn, x, GP, displ); + break; + + case GP_S11_16: + displ = (SBITS(code, 10, 5) << 5) | (BITS(code, 2, 0) << 2); + opdisp(insn, x, GP, displ); + break; + + case EL: // 4..1 & 10..8 enter / leave register set + x.type = o_reglist; + x.reglist = BITS(code, 4, 1) | (BITS(code, 10, 8) << 4); + x.dtype = dt_dword; + break; + + default: + msg("%a: cannot decode operand %d (opkind=%u)\n", insn.ea, x.n, opkind); + return; + } + if ( opkind & O_IND ) + { + // indirect access + if ( x.type == o_reg ) + { + x.type = o_displ; + x.addr = 0; + } + else if ( x.type == o_imm && insn.itype != ARC_lr && insn.itype != ARC_sr ) + { + if ( insn.itype == ARC_j || insn.itype == ARC_jl ) + x.type = o_near; + else + x.type = o_mem; + x.addr = x.value; + x.immdisp = 0; + } + } + if ( opkind & O_WIDE ) + { + // register pair for 64-bit values + op_t &y = insn.ops[op_pos]; + ++op_pos; + if ( x.type == o_reg && (x.reg & 1) == 0 && x.reg <= R58 ) + { + y.type = o_reg; + y.reg = x.reg + 1; + y.regpair = true; + } + else + { + y.type = o_void; + } + } + if ( opkind & O_IDX ) + { + int base; + switch ( insn.itype ) + { + case ARC_bi: + case ARC_bih: + base = NEXT_PC; + break; + + case ARC_ldi: + base = LDI_BASE; + break; + + case ARC_jli: + base = JLI_BASE; + break; + + case ARC_ei: + base = EI_BASE; + break; + + default: + msg("%a: unknown implicit base for indexed access\n", insn.ea); + return; + } + if ( x.type == o_reg ) + { + x.type = o_phrase; + x.secreg = x.reg; + x.reg = base; + } + else if ( x.type == o_imm ) + { + x.type = o_displ; + x.addr = x.value; + x.reg = base; + } + else + { + msg("%a: unknown operand type for indexed access\n", insn.ea); + } + } +} + +//---------------------------------------------------------------------- +// decode non-operand bits of the instruction +static void decode_aux(insn_t &insn, uint32 code, uint32 aux) +{ + aux &= ~AUX_V2 & ~AUX_F; + if ( aux & AUX_CND ) + { + // condition in low bits of 'aux' + insn.auxpref = (insn.auxpref & ~aux_cmask) | (aux & aux_cmask); + aux &= ~(AUX_CND | aux_cmask); + } + if ( aux & Q_4_0 ) + { + // condition in low bits of instruction + insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask); + aux &= ~Q_4_0; + } + if ( aux & Q_5_0 ) + { + // condition in low bits of instruction if the next higer bit is 1 + if ( BITS(code, 5, 5) == 1 ) + insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask); + aux &= ~Q_5_0; + } + if ( aux & AUX_GEN3 ) + { + // bit 15 = F/Di, 4..0 = Q if 23..22=0x3 + if ( BITS(code, 15, 15) ) + { + if ( (aux & AUX_GEN3) == AUX_GEN ) + insn.auxpref |= aux_f; + else if ( (aux & AUX_GEN3) == AUX_GEN3 ) + insn.auxpref |= aux_di; + } + if ( BITS(code, 23, 22) == 3 ) + insn.auxpref = (insn.auxpref & ~aux_cmask) | (code & aux_cmask); + aux &= ~AUX_GEN3; + } + if ( aux & N_5 ) + { + insn.auxpref = (insn.auxpref & ~aux_d) | (code & aux_d); + aux &= ~N_5; + } + if ( aux & AUX_W ) + { + insn.auxpref = (insn.auxpref & ~aux_zmask) | aux_w; + aux &= ~AUX_W; + } + if ( aux & AUX_B ) + { + insn.auxpref = (insn.auxpref & ~aux_zmask) | aux_b; + aux &= ~AUX_B; + } + if ( aux & AUX_X ) + { + insn.auxpref |= aux_x; + aux &= ~AUX_X; + } + if ( aux & AUX_D ) + { + insn.auxpref = (insn.auxpref & ~aux_nmask) | aux_d; + aux &= ~AUX_D; + } + if ( aux & DAAZZX_11_6 ) // 11..6 Di, aa, ZZ, X flags (load) + { + insn.auxpref = (insn.auxpref & ~0x3F) | (BITS(code, 11, 6)); + aux &= ~DAAZZX_11_6; + } + if ( aux & DAAZZ_5_1 ) // 5..1 Di, aa, ZZ (store) + { + insn.auxpref = (insn.auxpref & ~0x3F) | (BITS(code, 5, 1) << 1); + aux &= ~DAAZZ_5_1; + } + if ( aux & AAZZXD_23_15 ) // 23..22,18..15 aa, ZZ, X, D flags (load reg+reg) + { + // load instructions flags: Di.AA.ZZ.X + insn.auxpref &= ~0x3F; + insn.auxpref |= BITS(code, 15, 15) << 5; // Di + insn.auxpref |= BITS(code, 23, 22) << 3; // aa + insn.auxpref |= BITS(code, 18, 17) << 1; // ZZ + insn.auxpref |= BITS(code, 16, 16) << 0; // X + aux &= ~AAZZXD_23_15; + } + if ( aux & AUX_AS ) + { + insn.auxpref |= aux_as; + aux &= ~AUX_AS; + } + if ( aux & Y_3 ) + { + // static prediction bit Y is bit 3 + // in default case (no hint specified) it's 0 for BRcc and 1 for BBITn + if ( (BITS(code, 3, 3) == 0) != (insn.itype == ARC_br) ) + { + insn.auxpref |= aux_bhint; + } + aux &= ~Y_3; + } + if ( aux != 0 ) + msg("%a: unhandled aux bits: %08X\n", insn.ea, aux); +} + +//---------------------------------------------------------------------- +int arc_t::analyze_compact(insn_t &insn, uint32 code, int idx, const arcompact_opcode_t *table) +{ + const arcompact_opcode_t *line = &table[idx]; + while ( (line->mnem & 0x80000000) != 0 ) + { + // it's a pointer into subtable + // indexed by some of the instruction's bits + int high1 = (line->mnem >> 24) & 0x1F; + int low1 = (line->mnem >> 16) & 0x1F; + int high2 = (line->mnem >> 8) & 0x1F; + int low2 = (line->mnem >> 0) & 0x1F; + idx = BITS(code, high2, low2); + if ( high1 != 0 && low1 != 0 ) + idx |= BITS(code, high1, low1) << (high2-low2+1); + line = &(line->subtable[idx]); + } + if ( line->aux & AUX_F && BITS(code, 15, 15) ) + line += 0x40; + if ( (line->mnem == 0 && line->aux == 0) || !is_arcv2() && line->aux & AUX_V2 ) + { + return 0; + } + + insn.itype = line->mnem; + decode_aux(insn, code, line->aux); + + if ( is_arcv2() && insn.itype == ARC_flag && BITS(code, 15, 15) ) + insn.itype = ARC_kflag; + + int j = 0; + for ( int i = 0; i < 3; i++ ) + decode_operand(insn, code, j, line->ops[i]); + for ( ; j < PROC_MAXOP; ++j ) + insn.ops[j].type = o_void; + + if ( insn.itype == ARC_swi + && insn.Op1.type == o_imm + && insn.Op1.value == 0x3f ) + { + insn.itype = ARC_brk; + insn.Op1.type = o_void; + } + + return insn.size; +} + +//---------------------------------------------------------------------- +// analyze ARCompact instruction +int arc_t::ana_compact(insn_t &insn) +{ + // must be 16-bit aligned + if ( insn.ea & 1 ) + return 0; + uint32 code = insn.get_next_word(); + got_limm = false; + // first 5 bits is the major opcode + int i = (code >> 11) & 0x1F; + if ( i < 0x8 ) + { + // this is a 32-bit instruction + // get the full word + code = (code << 16) | insn.get_next_word(); + } + else + { + insn.auxpref |= aux_s; + } + return analyze_compact(insn, code, i, + is_arcv2() ? arcv2_major : arcompact_major); +} + +//---------------------------------------------------------------------- +static void simplify(insn_t &insn) +{ + for ( int i = 0; i < PROC_MAXOP; ++i ) + { + if ( insn.ops[i].type == o_mem ) + insn.ops[i].immdisp = 0; + } + + switch ( insn.itype ) + { + case ARC_st: + case ARC_ld: + // ld.as r1, [r2, delta] -> ld r1, [r2, delta*size] + if ( insn.Op2.type == o_displ + && insn.Op2.membase == 0 + && (insn.auxpref & aux_amask) == aux_as ) + { + insn.Op2.addr *= get_scale_factor(insn); + insn.auxpref &= ~aux_amask; + } + else if ( insn.Op2.type == o_mem + && (insn.auxpref & aux_amask) == aux_as ) + { + insn.Op2.immdisp = 0; + insn.auxpref &= ~aux_amask; + } + break; + case ARC_add1: + case ARC_add2: + case ARC_add3: + case ARC_sub1: + case ARC_sub2: + case ARC_sub3: + // addN a, b, c -> add a, b, c<<N + if ( insn.Op3.type == o_imm ) + { + switch ( insn.itype ) + { + case ARC_add1: + case ARC_sub1: + insn.Op3.value *= 2; + break; + case ARC_add2: + case ARC_sub2: + insn.Op3.value *= 4; + break; + case ARC_add3: + case ARC_sub3: + insn.Op3.value *= 8; + break; + } + switch ( insn.itype ) + { + case ARC_add1: + case ARC_add2: + case ARC_add3: + insn.itype = ARC_add; + break; + case ARC_sub3: + case ARC_sub2: + case ARC_sub1: + insn.itype = ARC_sub; + break; + } + } + break; + case ARC_sub: + // sub.f 0, a, b -> cmp a, b + if ( insn.Op1.is_imm(0) && (insn.auxpref & aux_f) != 0 ) + { + insn.auxpref &= ~aux_f; + insn.itype = ARC_cmp; + insn.Op1 = insn.Op2; + insn.Op2 = insn.Op3; + insn.Op3.type = o_void; + } + break; + } +} + +//---------------------------------------------------------------------- +// fix operand size for byte or word loads/stores +inline void fix_ldst(insn_t &insn) +{ + if ( insn.itype == ARC_ld || insn.itype == ARC_st ) + { + switch ( insn.auxpref & aux_zmask ) + { + case aux_b: + insn.Op2.dtype = dt_byte; + break; + case aux_w: + insn.Op2.dtype = dt_word; + break; + } + } +} + +//---------------------------------------------------------------------- +// convert pc-relative loads +// ld r1, [pc,#delta] -> ld r1, [memaddr] +static void inline_const(insn_t &insn) +{ + if ( insn.itype == ARC_ld + && insn.Op2.type == o_displ + && insn.Op2.reg == PCL + && (insn.auxpref & (aux_a|aux_zmask)) == 0 ) // no .a and 32-bit access + { + ea_t val_ea = (insn.ea & ~3ul) + insn.Op2.addr; + if ( is_mapped(val_ea) ) + { + insn.Op2.type = o_mem; + insn.Op2.addr = val_ea; + insn.Op2.immdisp = 0; + insn.auxpref |= aux_pcload; + } + } +} + +//---------------------------------------------------------------------- +// analyze an instruction +int arc_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + int sz = is_a4() ? ana_old(insn) : ana_compact(insn); + if ( sz != 0 ) + { + fix_ldst(insn); + if ( (idpflags & ARC_SIMPLIFY) != 0 ) + simplify(insn); + if ( (idpflags & ARC_INLINECONST) != 0 ) + inline_const(insn); + } + return insn.size; +} diff --git a/idasdk76/module/arc/arc.hpp b/idasdk76/module/arc/arc.hpp new file mode 100644 index 0000000..42c79eb --- /dev/null +++ b/idasdk76/module/arc/arc.hpp @@ -0,0 +1,502 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 2012-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * ARC (Argonaut RISC Core) processor module + * + * Based on code contributed by by Felix Domke <tmbinc@gmx.net> + */ + +#ifndef _ARC_HPP +#define _ARC_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <typeinf.hpp> +#include <diskio.hpp> +#include "../iohandler.hpp" + +#define PROCMOD_NAME arc +#define PROCMOD_NODE_NAME "$ arc" + +//------------------------------------------------------------------------ +// customization of the 'cmd' structure: + +enum processor_subtype_t +{ + prc_arc = 0, // ARCTangent-A4 (old 32-bit ISA) + prc_arcompact = 1, // ARCtangent-A5 and later (32/16-bit mixed) + prc_arcv2 = 2, // ARC EM (ARCompact successor) +}; + +//------------------------------------------------------------------------ +enum RegNo +{ + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, R11, R12, R13, R14, R15, + R16, R17, R18, R19, R20, R21, R22, R23, + R24, R25, R26, R27, R28, R29, R30, R31, + + R32, R33, R34, R35, R36, R37, R38, R39, + R40, R41, R42, R43, R44, R45, R46, R47, + R48, R49, R50, R51, R52, R53, R54, R55, + R56, R57, R58, R59, R60, R61, R62, R63, + + CF, ZF, NF, VF, + + // registers used for indexed instructions + // keep these consecutive + NEXT_PC, + LDI_BASE, JLI_BASE, EI_BASE, + + GP_SEG, // virtual segment register for global pointer value + + rVcs, rVds, // virtual registers for code and data segments + + // aliases + + GP = R26, // Global Pointer + FP = R27, // Frame Pointer + SP = R28, // Stack Pointer + ILINK1 = R29, // Level 1 interrupt link register + ILINK2 = R30, // Level 2 interrupt link register + BLINK = R31, // Branch link register + LP_COUNT = R60, // Loop count register + PCL = R63, // 32-bit aligned PC value (ARCompact) + + // optional extension + MLO = R57, // Multiply low 32 bits, read only + MMID = R58, // Multiply middle 32 bits, read only + MHI = R59, // Multiply high 32 bits, read only +}; + +#define SHIMM_F 61 // Short immediate data indicator setting flags +#define LIMM 62 // Long immediate data indicator +#define SHIMM 63 // Short immediate data indicator not setting flags (NB: not used in ARCompact) +#define LIMM5 30 // 5-bit long immediate data indicator (used in ARCv2) + +//------------------------------------------------------------------------ +const ioport_t *find_port(ea_t address); + +#define PROC_MAXOP 4 // max number of operands +CASSERT(PROC_MAXOP <= UA_MAXOP); + +//--------------------------------- + +inline int getreg(const op_t &x) +{ + return x.type == o_reg ? x.reg : -1; +} + +inline bool isreg(const op_t &x, int reg) +{ + return getreg(x) == reg; +} + +inline bool issp(const op_t &x) { return isreg(x, SP); } + +//--------------------------------- +// cmd.auxpref bits +// instructions that use condition flags (Bcc, Jcc) +#define aux_f 0x0100 // Flags set field (.f postfix) +#define aux_nmask 0x0060 // Jump/Call nullify instruction mode +#define aux_nd 0x00 // No Delayed instruction slot (only execute next instruction when not jumping) +#define aux_d 0x20 // Delayed instruction slot (always execute next instruction) +#define aux_jd 0x40 // Jump Delayed instruction slot (only execute next instruction when jumping) +#define aux_cmask 0x001F // condition code mask +// load/store instructions flags (Di.AA.ZZ.X) +#define aux_di 0x0020 // direct to memory (cache bypass) (.di suffix) +#define aux_amask 0x0018 // Address write-back +#define aux_anone 0x00 // no writeback +#define aux_a 0x08 // pre-increment (.a or .aw) +#define aux_ab 0x10 // post-increment (.ab) +#define aux_as 0x18 // scaled access (.as) +#define aux_zmask 0x0006 // size mask +#define aux_l 0x0 // long size (no suffix) +#define aux_w 0x4 // word size (.w suffix) +#define aux_b 0x2 // byte size (.b suffix) +#define aux_x 0x0001 // Sign extend field (.x suffix) + +#define aux_pcload 0x0200 // converted pc-relative to memory load (used when ARC_INLINECONST is set) +#define aux_bhint 0x0400 // non-default static branch prediction hint (.t or .nt suffix) +#define aux_s 0x0800 // 16-bit encoded instruction + +// Operand types: +#define o_reglist o_idpspec0 // register list for enter/leave + +#define reglist specval // o_reglist: registers to save/restore +#define REGLIST_REGS 0x0F // number of core registers to save/restore +#define REGLISTR_MAX 0x0E // max number of core registers to save/restore +#define REGLIST_FP 0x10 // save/restore stack frame +#define REGLIST_BLINK 0x20 // save/restore blink register +#define REGLIST_PCL 0x40 // jump to blink register after restore (leave only) + +// o_phrase +#define secreg specflag1 // o_phrase: the second register is here: [op.phrase, op.secreg] + +// o_displ +#define membase specflag1 // o_displ: if set, displacement is the base value: [op.addr, op.reg] + // this is important for scaled loads, e.g. ld.as r1, [0x23445, r2] +// o_reg +#define regpair specflag1 // o_reg: if set, this operand is the second register of a register pair + // the previous operand contains the other register of the pair +// o_mem +#define immdisp specval // o_mem: immediate displacement to immediate address. + // addr contains the already displaced address. + // addr - get_scale_factor(insn) * immdisp is the base address for immdisp + +//------------------------------------------------------------------ +// Condition codes: +enum cond_t +{ + cAL=0, cRA=0, // Always 1 0x00 + cEQ=1, cZ=1, // Zero Z 0x01 + cNE=2, cNZ=2, // Non-Zero /Z 0x02 + cPL=3, cP=3, // Positive /N 0x03 + cMI=4, cN=4, // Negative N 0x04 + cCS=5, cC=5, cLO=5, // Carry set, lower than (unsigned) C 0x05 + cCC=6, cNC=6, cHS=6, // Carry clear, higher or same (unsigned) /C 0x06 + cVS=7, cV=7, // Over-flow set V 0x07 + cVC=8, cNV=8, // Over-flow clear /V 0x08 + cGT=9, // Greater than (signed) (N and V and /Z) or (/N and /V and /Z) 0x09 + cGE=0x0A, // Greater than or equal to (signed) (N and V) or (/N and /V) 0x0A + cLT=0x0B, // Less than (signed) (N and /V) or (/N and V) 0x0B + cLE=0x0C, // Less than or equal to (signed) Z or (N and /V) or (/N and V) 0x0C + cHI=0x0D, // Higher than (unsigned) /C and /Z 0x0D + cLS=0x0E, // Lower than or same (unsigned) C or Z 0x0E + cPNZ=0x0F, // Positive non-zero /N and /Z 0x0F + cLAST +}; +inline uint8 get_cond(const insn_t &insn) +{ + if ( insn.itype <= ARC_store_instructions ) + return cAL; + return uint8(insn.auxpref & aux_cmask); +} +inline bool has_cond(const insn_t &insn) +{ + if ( insn.itype <= ARC_store_instructions ) + return false; + return (insn.auxpref & aux_cmask) != cAL; +} +inline cond_t get_core_cond(const insn_t &insn) +{ + if ( insn.itype <= ARC_store_instructions ) + return cAL; + uint8 cond = insn.auxpref & aux_cmask; + if ( cond >= cLAST ) + return cLAST; + return cond_t(cond); +} +inline bool has_core_cond(const insn_t &insn) +{ + if ( insn.itype <= ARC_store_instructions ) + return false; + uint8 cond = insn.auxpref & aux_cmask; + return cond != cAL && cond < cLAST; +} +inline cond_t invert_cond(cond_t cond) +{ + switch ( cond ) + { + case cNE: return cEQ; + case cEQ: return cNE; + case cCC: return cCS; + case cCS: return cCC; + case cPL: return cMI; + case cMI: return cPL; + case cVC: return cVS; + case cVS: return cVC; + case cHI: return cLS; + case cLS: return cHI; + case cGE: return cLT; + case cLT: return cGE; + case cGT: return cLE; + case cLE: return cGT; + default: return cLAST; + } +} + +// ARC ABI conventions from gdb/arc-tdep.h +#define ARC_ABI_GLOBAL_POINTER 26 +#define ARC_ABI_FRAME_POINTER 27 +#define ARC_ABI_STACK_POINTER 28 + +#define ARC_ABI_FIRST_CALLEE_SAVED_REGISTER 13 +#define ARC_ABI_LAST_CALLEE_SAVED_REGISTER 26 + +#define ARC_ABI_FIRST_ARGUMENT_REGISTER 0 +#define ARC_ABI_LAST_ARGUMENT_REGISTER 7 + +#define ARC_ABI_RETURN_REGNUM 0 +#define ARC_ABI_RETURN_LOW_REGNUM 0 +#define ARC_ABI_RETURN_HIGH_REGNUM 1 + +//------------------------------------------------------------------------ +// does 'ins' have a delay slot? (next instruction is executed before branch/jump) +inline bool has_dslot(const insn_t &ins) +{ + // EXCEPTION: jl.jd <addr> uses delay slot to + // hide the long immediate used for the address + if ( ins.itype == ARC_jl + && (ins.auxpref & aux_nmask) == aux_jd + && ins.Op1.type == o_near ) + return false; + return ins.itype > ARC_store_instructions && (ins.auxpref & aux_nmask) != 0; +} + +//------------------------------------------------------------------------ +// Scale factor for indexed memory access +inline int get_scale_factor(const insn_t &ins) +{ + switch ( ins.itype ) + { + case ARC_st: + case ARC_ld: + if ( (ins.auxpref & aux_amask) == aux_as ) + { + if ( (ins.auxpref & aux_zmask) == aux_w ) + return 2; + if ( (ins.auxpref & aux_zmask) == aux_l ) + return 4; + } + break; + + case ARC_bih: + return 2; + + case ARC_bi: + case ARC_ldi: + case ARC_jli: + case ARC_ei: + return 4; + } + return 1; +} + +//------------------------------------------------------------------------ +// Should the register be hidden when used as base in o_displ/o_phrase? +// +// 0 output normally +// 1 hide base reg +// -1 hide base reg and output as immediate +inline int is_hidden_base_reg(int reg) +{ + if ( reg >= NEXT_PC && reg <= EI_BASE ) + { + return reg == JLI_BASE || reg == EI_BASE ? -1 : 1; + } + return 0; +} + +//------------------------------------------------------------------------ +// The sreg that contains the current value for the given register +// +// Returns -1 if there is no such sreg +inline int get_base_sreg(int reg) +{ + if ( reg == GP ) + return GP_SEG; + else if ( reg >= LDI_BASE && reg <= GP_SEG ) + return reg; + return -1; +} + +//------------------------------------------------------------------------ +void idaapi arc_header(outctx_t &ctx); +void idaapi arc_footer(outctx_t &ctx); + +int idaapi is_sp_based(const insn_t &insn, const op_t & x); +bool idaapi create_func_frame(func_t * pfn); +int idaapi arc_get_frame_retsize(const func_t * pfn); +bool is_arc_return_insn(const insn_t &insn); +bool arc_is_switch(switch_info_t *si, const insn_t &insn); +inline bool is_arc_simple_branch(uint16 itype) +{ + return itype == ARC_bl + || itype == ARC_jl + || itype == ARC_b + || itype == ARC_j; +} + +int get_arc_fastcall_regs(const int **regs); +bool calc_arc_arglocs(func_type_data_t *fti); +bool calc_arc_varglocs( + func_type_data_t *fti, + regobjs_t *regargs, + int nfixed); +bool calc_arc_retloc(argloc_t *retloc, const tinfo_t &tif, cm_t cc); +void use_arc_arg_types( + ea_t ea, + func_type_data_t *fti, + funcargvec_t *rargs); + +//------------------------------------------------------------------------ +struct arc_iohandler_t : public iohandler_t +{ + struct arc_t ± + arc_iohandler_t(arc_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual const char *iocallback(const ioports_t &iop, const char *line) override; + virtual void get_cfg_filename(char *buf, size_t bufsize) override; +}; + +DECLARE_PROC_LISTENER(pm_idb_listener_t, struct arc_t); + +struct arc_t : public procmod_t +{ + netnode helper; // altval(-1): idp flags +#define CALLEE_TAG 'A' // altval(ea): callee address for indirect calls +#define DXREF_TAG 'd' // altval(ea): resolved address for complex calculation (e.g. ADD R1, PC) +#define DSLOT_TAG 's' // altval(ea): 1: delay slot of an unconditional jump/branch + // 2: delay slot of a conditional jump/branch + // 3: delay slot of a jl/bl + inline void set_callee(ea_t ea, ea_t callee) { helper.easet(ea, callee, CALLEE_TAG); } + inline ea_t get_callee(ea_t ea) { return helper.eaget(ea, CALLEE_TAG); } + inline void del_callee(ea_t ea) { helper.eadel(ea, CALLEE_TAG); } + + inline void set_dxref(ea_t ea, ea_t dxref) { helper.easet(ea, dxref, DXREF_TAG); } + inline ea_t get_dxref(ea_t ea) { return helper.eaget(ea, DXREF_TAG); } + inline void del_dxref(ea_t ea) { helper.eadel(ea, DXREF_TAG); } + + instruc_t Instructions[ARC_last]; + + ioports_t auxregs; + arc_iohandler_t ioh = arc_iohandler_t(*this, helper); + pm_idb_listener_t idb_listener = pm_idb_listener_t(*this); + + processor_subtype_t ptype = prc_arc; + inline bool is_a4() { return ptype == prc_arc; } + inline bool is_arcv2() { return ptype == prc_arcv2; } + + int arc_respect_info = IORESP_ALL; + + int ref_arcsoh_id = 0; + int ref_arcsol_id = 0; + +#define ARC_SIMPLIFY 0x01 +#define ARC_INLINECONST 0x02 +#define ARC_TRACKREGS 0x04 + ushort idpflags = ARC_SIMPLIFY | ARC_INLINECONST | ARC_TRACKREGS; + + int g_limm = 0; + bool got_limm = false; + + std::set<ea_t> renamed; + int islast = 0; + + // is 'ea' in a delay slot of a branch/jump? + inline bool is_dslot(ea_t ea, bool including_calls = true) + { + nodeidx_t v = helper.altval_ea(ea, DSLOT_TAG); + if ( including_calls ) + return v != 0; + else + return v == 1 || v == 2; + } + + inline bool is_imm(int regno) + { + if ( regno == LIMM ) + return true; + if ( regno == SHIMM_F || regno == SHIMM ) + return is_a4(); + return false; + } + + arc_t(); + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); + + bool select_device(int resp_info); + inline void add_dxref(const insn_t &insn, ea_t target); + int emu(const insn_t &insn); + bool is_arc_basic_block_end( + const insn_t &insn, + bool call_insn_stops_block); + void del_insn_info(ea_t ea); + const char *set_idp_options( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded); + void set_codeseqs() const; + void set_instruc_names(); + void ptype_changed(); + void doIndirectOperand(const insn_t &insn, int b, int c, op_t &op, int d, int li, bool special); + void doRegisterInstruction(insn_t &insn, uint32 code); + int ana_old(insn_t &insn); + void decode_operand( + insn_t &insn, + uint32 code, + int &op_pos, + uint32 opkind); + int analyze_compact(insn_t &insn, uint32 code, int idx, const struct arcompact_opcode_t *table); + int ana_compact(insn_t &insn); + int ana(insn_t *_insn); + int is_align_insn(ea_t ea) const; + bool good_target(const insn_t &insn, ea_t target) const; + bool copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, void *value = NULL, bool force = false) const; + void handle_operand(const insn_t &insn, const op_t & x, bool loading); + int get_limm(insn_t &insn); + inline void opreg(insn_t &insn, op_t &x, int rgnum, int limm=LIMM); + inline void opdisp(insn_t &insn, op_t &x, int rgnum, ea_t disp); + void rename_if_not_set(ea_t ea, const char *name); + bool check_ac_pop_chain(int *regno, ea_t ea); + bool detect_millicode(qstring *mname, ea_t ea); + bool is_millicode(ea_t ea, sval_t *spdelta=nullptr); + sval_t calc_sp_delta(const insn_t &insn); + void trace_sp(const insn_t &insn); + bool arc_calc_spdelta(sval_t *spdelta, const insn_t &insn); + int arc_may_be_func(const insn_t &insn, int state); + void force_offset( + ea_t ea, + int n, + ea_t base, + bool issub = false, + int scale = 1); + bool spoils(const insn_t &insn, int reg) const; + int spoils(const insn_t &insn, const uint32 *regs, int n) const; + bool is_arc_call_insn(const insn_t &insn); + bool find_op_value_ex( + const insn_t &insn, + const op_t &x, + struct ldr_value_info_t *lvi, + bool /*check_fbase_reg*/); + bool find_ldr_value_ex( + const insn_t &insn, + ea_t ea, + int reg, + struct ldr_value_info_t *lvi, + bool /*check_fbase_reg*/); + bool find_op_value( + const insn_t &insn, + const op_t &x, + uval_t *p_val, + ea_t *p_val_ea=NULL, + bool check_fbase_reg=true, + bool *was_const_load=NULL); + bool find_ldr_value( + const insn_t &insn, + ea_t ea, + int reg, + uval_t *p_val, + ea_t *p_val_ea=NULL, + bool check_fbase_reg=true, + bool *was_const_load=NULL); + int use_arc_regarg_type(ea_t ea, const funcargvec_t &rargs); + bool arc_set_op_type( + const insn_t &insn, + const op_t &x, + const tinfo_t &tif, + const char *name, + eavec_t *visited); + void use_arc_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs); + + void arc_segstart(outctx_t &ctx, segment_t *Sarea) const; +}; +extern int data_id; + +#endif diff --git a/idasdk76/module/arc/emu.cpp b/idasdk76/module/arc/emu.cpp new file mode 100644 index 0000000..f49e563 --- /dev/null +++ b/idasdk76/module/arc/emu.cpp @@ -0,0 +1,2887 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su, ig@datarescue.com + * FIDO: 2:5020/209 + * + */ + +#include "arc.hpp" +#include <frame.hpp> +#include <xref.hpp> +#include <jumptable.hpp> +#include <segregs.hpp> + +//#define DEBUG_ARGLOC + +//---------------------------------------------------------------------- +#ifdef DEBUG_ARGLOC +static void debug_print_argloc(int i, const argloc_t &argloc, const tinfo_t &type) +{ + qstring typestr; + type.print(&typestr); + char varstr[MAXSTR]; + if ( argloc.is_stkoff() ) + qsnprintf(varstr, sizeof(varstr), "STK_%x", int(argloc.stkoff())); + else + print_argloc(varstr, sizeof(varstr), argloc, type.get_size()); + if ( i == -1 ) + msg("RET: %s %s\n", typestr.c_str(), varstr); + else + msg("%d: %s %s\n", i, typestr.c_str(), varstr); +} +#else +inline void debug_print_argloc(int, const argloc_t &, const tinfo_t &) {} +#endif + +// does the expression [reg, xxx] point to the stack? +static bool is_stkptr(const insn_t &insn, int reg) +{ + if ( reg == SP ) + return true; + if ( reg == FP ) + { + func_t *pfn = get_func(insn.ea); + + if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) + return true; + } + return false; +} + +void arc_t::handle_operand(const insn_t &insn, const op_t & x, bool loading) +{ + flags_t F; + switch ( x.type ) + { + case o_reg: + break; + case o_imm: + set_immd(insn.ea); + F = get_flags(insn.ea); + if ( op_adds_xrefs(F, x.n) ) + { + insn.add_off_drefs(x, dr_O, OOFS_IFSIGN); + } + else if ( x.n == 2 && may_create_stkvars() && !is_defarg(F, x.n) + && insn.itype == ARC_add && !insn.Op1.is_reg(SP) && !insn.Op1.is_reg(FP) + && (insn.Op2.is_reg(SP) || insn.Op2.is_reg(FP)) ) + { + // add rx, sp, #imm + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL ) + { + adiff_t sp_off = x.value; + if ( insn.create_stkvar(x, sp_off, 0) ) + op_stkvar(insn.ea, x.n); + } + } + break; + case o_mem: + if ( insn.itype != ARC_lr && insn.itype != ARC_sr ) + { + ea_t ea = to_ea(insn.cs, x.addr); + insn.create_op_data(ea, x); // create the data item of the correct size + insn.add_dref(ea, x.offb, loading ? dr_R : dr_W); + if ( (idpflags & ARC_INLINECONST) != 0 && insn.itype == ARC_ld ) + copy_insn_optype(insn, x, ea); + } + break; + case o_near: + { + int iscall = has_insn_feature(insn.itype, CF_CALL); + + insn.add_cref(to_ea(insn.cs, x.addr), x.offb, iscall ? fl_CN : fl_JN); + if ( !islast && iscall ) + { + if ( !func_does_return(x.addr) ) // delay slot?! + islast = 1; + } + } + break; + case o_displ: + set_immd(insn.ea); + F = get_flags(insn.ea); + if ( !is_defarg(F, x.n) ) + { + ea_t base = BADADDR; + if ( x.reg == PCL ) + base = insn.ea & (~3ul); + else if ( x.reg == NEXT_PC ) + base = insn.ea + insn.size; + int sreg = get_base_sreg(x.reg); + if ( sreg > 0 ) + base = get_sreg(insn.ea, sreg); + if ( base != BADADDR ) + { + int scale = get_scale_factor(insn); + reftype_t reftype = REF_OFF32; + if ( scale == 2 ) + reftype = ref_arcsoh_id | REFINFO_CUSTOM; + else if ( scale == 4 ) + reftype = ref_arcsol_id | REFINFO_CUSTOM; + op_offset(insn.ea, x.n, reftype | REFINFO_NOBASE, BADADDR, base); + } + } + if ( op_adds_xrefs(F, x.n) ) // create an xref for offset expressions + { + if ( insn.itype == ARC_jli ) + { + // for jli the reference target is called, not read + ea_t base = get_sreg(insn.ea, JLI_BASE); + insn.add_cref(base + 4 * x.addr, 0, fl_CF); + } + else if ( insn.itype == ARC_bi || insn.itype == ARC_bih ) + { + // for bi/bih the reference target is jumped to, not read + ea_t next_pc = insn.ea + insn.size; + int scale = insn.itype == ARC_bi ? 4 : 2; + insn.add_cref(next_pc + scale * x.addr, 0, fl_JN); + } + else + { + ea_t target = insn.add_off_drefs(x, loading ? dr_R : dr_W, OOF_ADDR|OOF_SIGNED|OOFW_32); + if ( target != BADADDR ) + insn.create_op_data(target, x); // create the data item of the correct size + } + } + else if ( is_stkptr(insn, x.phrase) && may_create_stkvars() && !is_defarg(F, x.n) ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL ) + { + // if it's [sp, xxx] we make a stackvar out of it + adiff_t sp_off = x.addr; + if ( insn.create_stkvar(x, sp_off, STKVAR_VALID_SIZE) ) + op_stkvar(insn.ea, x.n); + } + } + break; + } +} + +//---------------------------------------------------------------------- +inline bool is_callee_saved(int reg) +{ + return reg >= ARC_ABI_FIRST_CALLEE_SAVED_REGISTER + && reg <= ARC_ABI_LAST_CALLEE_SAVED_REGISTER; +} + +//---------------------------------------------------------------------- +// Is register 'reg' spoiled by the current instruction? +#define PROC_MAXCHGOP 2 +bool arc_t::spoils(const insn_t &insn, int reg) const +{ + switch ( insn.itype ) + { + case ARC_pop: + case ARC_push: + if ( reg == SP ) + return true; + break;// otherwise check flags + + case ARC_ld: // ld Rx, [reg, #imm] + case ARC_st: // st.a R1, [R2, #imm] + if ( insn.Op2.reg == reg && ((insn.auxpref & aux_amask) == aux_a || (insn.auxpref & aux_amask) == aux_ab) ) + return true; + break;// otherwise check flags + + case ARC_bl: + case ARC_jl: + return !is_callee_saved(reg); + + case ARC_enter: + case ARC_leave: + { + if ( insn.Op1.reglist == 0 ) + return false; + if ( reg == SP ) + return true; + // FP is set to SP on enter and restored on leave + if ( (insn.Op1.reglist & REGLIST_FP) != 0 && reg == FP ) + return true; + if ( insn.itype == ARC_enter ) + return false; + int regs = insn.Op1.reglist & REGLIST_REGS; + return (insn.Op1.reglist & REGLIST_BLINK) != 0 && reg == BLINK + || reg >= R13 && reg < R13 + regs; + } + } + + uint32 feature = insn.get_canon_feature(ph); + if ( feature != 0 ) + { + for ( int i = 0; i < PROC_MAXOP; ++i ) + { + if ( has_cf_chg(feature, i) && insn.ops[i].is_reg(reg) ) + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------- +// does the instruction spoil the flags? +static bool spoils_flags(const insn_t &insn) +{ + return insn.itype == ARC_cmp + || insn.itype == ARC_flag + || insn.itype == ARC_modif + || insn.itype == ARC_fscmp + || insn.itype == ARC_fscmpf + || (insn.auxpref & aux_f) != 0; +} + +// info about a single register +struct ldr_value_info_t +{ + uval_t value; // value loaded into the register + ea_t val_ea; // where the value comes from (for constant pool or immediate loads) + eavec_t insn_eas; // insns that were involved in calculating the value + char n; // operand number + char state; +#define LVI_STATE 0x03 // state mask +#define LVI_UNKNOWN 0x00 // unknown state +#define LVI_VALID 0x01 // value known to be valid +#define LVI_INVALID 0x02 // value known to be invalid +#define LVI_CONST 0x04 // is the value constant? (e.g. immediate or const pool) + + ldr_value_info_t(void) + : value(0), val_ea(BADADDR), n(0), state(LVI_UNKNOWN) + {} + bool is_const(void) const { return (state & LVI_CONST) != 0; } + bool is_valid(void) const { return (state & LVI_STATE) == LVI_VALID; } + bool is_known(void) const { return (state & LVI_STATE) != LVI_UNKNOWN; } + void set_valid(bool valid) + { + state &= ~LVI_STATE; + state |= valid ? LVI_VALID : LVI_INVALID; + } + void set_const(void) { state |= LVI_CONST; } +}; + +//---------------------------------------------------------------------- +// helper class for find_op_value/find_ldr_value +// we keep a cache of discovered register values to avoid unnecessary recursion +struct reg_tracker_t +{ + // map cannot store an array directly, so wrap it in a class + struct reg_values_t + { + ldr_value_info_t regs[R60+1]; // values for registers R0 to R60 for a specific ea + }; + + typedef std::map<ea_t, reg_values_t> reg_values_cache_t; + + arc_t ± + // we save both valid and invalid values into in the cache. + reg_values_cache_t regcache; + + reg_tracker_t(arc_t *p) : pm(*p) {} + // recursive functions; they can call each other, so we limit the nesting level + bool do_find_op_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level); + bool do_find_ldr_value(const insn_t &insn, ea_t ea, int reg, ldr_value_info_t *p_lvi, int nest_level); + bool do_calc_complex_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level); + + bool is_call_insn(const insn_t &insn) const; +}; + +//---------------------------------------------------------------------- +bool reg_tracker_t::is_call_insn(const insn_t &insn) const +{ + switch ( insn.itype ) + { + case ARC_bl: + case ARC_jli: + return true; + + case ARC_jl: + if ( insn.Op1.reg != BLINK && insn.Op1.reg != ILINK1 && insn.Op1.reg != ILINK2 ) + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool arc_t::is_arc_call_insn(const insn_t &insn) +{ + reg_tracker_t tr(this); + return tr.is_call_insn(insn); +} + +//---------------------------------------------------------------------- +bool reg_tracker_t::do_find_op_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level) +{ + switch ( x.type ) + { + case o_reg: + return do_find_ldr_value(insn, insn.ea, x.reg, lvi, nest_level); + case o_imm: + if ( lvi != NULL ) + { + lvi->value = x.value & 0xFFFFFFFF; + lvi->set_const(); + lvi->set_valid(true); + lvi->insn_eas.push_back(insn.ea); + } + return true; + case o_displ: + case o_phrase: + { + ldr_value_info_t val2; + if ( do_calc_complex_value(insn, x, &val2, nest_level+1) && val2.is_valid() ) + { + if ( lvi != NULL ) + { + *lvi = val2; + if ( lvi->is_valid() ) + lvi->insn_eas.push_back(insn.ea); + } + return true; + } + } + break; + case o_mem: + if ( lvi != NULL ) + { + ea_t value = to_ea(insn.cs, x.addr); + ea_t val_ea = BADADDR; + if ( insn.itype == ARC_ld && insn.Op2.dtype == dt_dword ) + { + val_ea = value; + value = BADADDR; + if ( is_loaded(val_ea) ) + { + value = get_dword(val_ea); + lvi->set_const(); + lvi->set_valid(true); + lvi->insn_eas.push_back(insn.ea); + } + } + lvi->val_ea = uint32(val_ea); + lvi->value = uint32(value); + } + return true; + } + return false; +} + +//---------------------------------------------------------------------- +// check if ea is in a const segment, and so we can use the pointer value +static bool is_const_seg(ea_t ea) +{ + if ( !is_loaded(ea) ) + return false; + + const char *const *names = NULL; + int ncnt = 0; + if ( inf_get_filetype() == f_MACHO ) + { + static const char *const macho_segs[] = + { + "__const", "__const_coal", + "__text", "__dyld", + "__la_symbol_ptr", "__nl_symbol_ptr", + "__class", "__cls_refs", "__message_refs", + "__inst_meth", "__cat_inst_meth", "__cat_cls_meth", + "__constructor", "__destructor", "__pointers", + "__objc_protorefs", + "__objc_selrefs", + "__objc_classrefs", + "__objc_superrefs", + "__objc_const", + }; + names = macho_segs; + ncnt = qnumber(macho_segs); + } + else if ( inf_get_filetype() == f_ELF ) + { + static const char *const elf_segs[] = + { + ".got", ".text", ".rodata", + ".got.plt", ".plt", + ".init", ".fini" + }; + names = elf_segs; + ncnt = qnumber(elf_segs); + } + if ( names != NULL ) + { + segment_t *seg = getseg(ea); + if ( seg != NULL ) + { + qstring segname; + if ( get_segm_name(&segname, seg) > 0 ) + { + for ( size_t i = 0; i < ncnt; i++ ) + if ( segname == names[i] ) + return true; + } + } + } + + if ( segtype(ea) == SEG_CODE ) + return true; + + segment_t *seg = getseg(ea); + if ( seg != NULL && (seg->perm & (SEGPERM_WRITE|SEGPERM_READ)) == SEGPERM_READ ) + return true; + + return false; +} + +//---------------------------------------------------------------------- +// calculate value of a complex operand +// ld [<Rn>, #+/-<offset>] +// ld [<Rn>, <Rm>] +// ld.a [<Rn>, #+/-<offset>] +// ld.ab [<Rn>, #+/-<offset>] (post-increment) +// val_ea is always calculated, val only for dword accesses to const segments +// returns true is val_ea is ok; value may be still wrong! set is_valid() for the value +bool reg_tracker_t::do_calc_complex_value(const insn_t &insn, const op_t &x, ldr_value_info_t *lvi, int nest_level) +{ + ldr_value_info_t val1; + ea_t val_ea = BADADDR; + uval_t value = BADADDR; + bool ok = false; + if ( do_find_ldr_value(insn, insn.ea, x.reg, &val1, nest_level+1) ) + { + ldr_value_info_t val2; + if ( (insn.auxpref & aux_amask) == aux_ab ) // post-increment + { + ok = true; + val2.value = 0; + } + else + { + if ( x.type == o_phrase ) + { + ok = do_find_ldr_value(insn, insn.ea, x.secreg, &val2, nest_level+1); + } + else if ( x.type == o_displ ) + { + ok = true; + val2.value = (int32)x.addr; + } + if ( !ok ) + return false; + } + int scale1 = 1; + int scale2 = 1; + if ( x.membase ) + scale1 = get_scale_factor(insn); + else + scale2 = get_scale_factor(insn); + val_ea = to_ea(insn.cs, scale1 * val1.value + scale2 * val2.value); + if ( x.dtype == dt_dword && is_const_seg(val_ea) ) + value = get_dword(val_ea); + } + if ( ok && lvi != NULL ) + { + lvi->value = uint32(value); + if ( value != BADADDR ) + lvi->set_valid(true); + lvi->val_ea = uint32(val_ea); + lvi->n = x.n; + } + return ok; +} + +//---------------------------------------------------------------------- +bool reg_tracker_t::do_find_ldr_value( + const insn_t &insn, + ea_t ea, + int reg, + ldr_value_info_t *p_lvi, + int nest_level) +{ + if ( nest_level > 200 ) + return false; + bool ok = false; + ldr_value_info_t lvi; + do + { + if ( reg == PCL || reg == NEXT_PC ) + { + lvi.value = reg == PCL ? insn.ip & ~3ul : insn.ip + insn.size; + lvi.value &= 0xFFFFFFFF; + lvi.set_valid(true); + lvi.set_const(); + lvi.insn_eas.push_back(insn.ea); + ok = true; + break; + } + + int sreg = get_base_sreg(reg); + if ( sreg >= 0 ) + { + lvi.value = get_sreg(ea, sreg); + if ( lvi.value != BADADDR ) + { + lvi.set_valid(true); + lvi.set_const(); + ok = true; + break; + } + } + + if ( reg >= R60 || reg < 0 ) + { + // not handled + break; + } + + // check if it's in the cache + reg_values_cache_t::iterator regs_it = regcache.find(ea); + if ( regs_it != regcache.end() ) + { + const ldr_value_info_t &cached = regs_it->second.regs[reg]; + if ( cached.is_known() ) + { + ok = lvi.is_valid(); + if ( ok ) + lvi = cached; + break; + } + } + + /* + ushort fbase_reg; + if ( check_fbase_reg && get_fbase_info(&lvi.value, &fbase_reg) && fbase_reg == reg ) + { + lvi.value -= to_ea(insn.cs, 0); + ok = true; + } + */ + + const insn_t *pinsn = &insn; + insn_t curr_insn; + while ( !ok ) + { + flags_t F = get_flags(pinsn->ea); + if ( has_xref(F) || !is_flow(F) ) + { + // count xrefs to the current instruction + xrefblk_t xb; + int numxrefs = 0; + ea_t xref_from = BADADDR; + for ( bool ok2 = xb.first_to(pinsn->ea, XREF_ALL); + ok2 && numxrefs < 2; + ok2 = xb.next_to() ) + { + if ( xb.iscode && xb.from < pinsn->ea ) // count only xrefs from above + { + // call xref => bad + if ( xb.type == fl_CN || xb.type == fl_CF ) + { + numxrefs = 0; + break; + } + xref_from = xb.from; + numxrefs++; + } + } + // if we have a single xref, use it + if ( numxrefs != 1 || xref_from == BADADDR || decode_insn(&curr_insn, xref_from) == 0 ) + break; + + } + else + { + if ( decode_prev_insn(&curr_insn, pinsn->ea) == BADADDR ) + break; + } + pinsn = &curr_insn; + + // we started with a conditional instruction? + // (BR.cc does not actually use a condition code) + if ( has_cond(insn) && insn.itype != ARC_br ) + { + // ignore instructions which belong to different condition branches + if ( !has_cond(*pinsn) || pinsn->itype == ARC_br ) + continue; + if ( get_cond(*pinsn) != get_cond(insn) ) + continue; + // if current instruction changes flags, stop tracking + if ( spoils_flags(*pinsn) ) + break; + } + + if ( pinsn->Op1.is_reg(reg) ) + { + switch ( pinsn->itype ) + { + case ARC_ld: + if ( pinsn->Op2.type == o_mem && pinsn->Op2.dtype == dt_dword ) + { + lvi.val_ea = to_ea(pinsn->cs, pinsn->Op2.addr); + if ( is_loaded(lvi.val_ea) && is_const_seg(lvi.val_ea) ) + { + lvi.value = get_dword(lvi.val_ea); + lvi.set_const(); + ok = true; + } + } + else if ( pinsn->Op2.type == o_displ || pinsn->Op2.type == o_phrase ) + { + ok = do_calc_complex_value(*pinsn, pinsn->Op2, &lvi, nest_level+1) && lvi.is_valid(); + } + if ( ok ) + lvi.insn_eas.push_back(pinsn->ea); + break; + case ARC_mov: + ok = do_find_op_value(*pinsn, pinsn->Op2, &lvi, nest_level+1); + if ( ok ) + { + if ( pinsn->itype == ARC_mov && pinsn->Op2.type == o_imm ) + { + // MOV Rx, #ABCD + lvi.val_ea = pinsn->ea; + lvi.n = 1; + } + } + break; + case ARC_asr: + case ARC_lsl: + case ARC_lsr: + case ARC_ror: + case ARC_and: + case ARC_xor: + case ARC_add: + case ARC_sub: + case ARC_rsub: + case ARC_or: + case ARC_bic: + { + ldr_value_info_t v1; + ldr_value_info_t v2; + const op_t *op1 = &pinsn->Op1; + const op_t *op2 = &pinsn->Op2; + if ( pinsn->Op3.type != o_void ) + { // arm mode + op1++; // points to pinsn->Op2 + op2++; // points to pinsn->Op3 + } + if ( !do_find_op_value(*pinsn, *op1, &v1, nest_level+1) ) + break; + if ( !do_find_op_value(*pinsn, *op2, &v2, nest_level+1) ) + break; + switch ( pinsn->itype ) + { + case ARC_add: + lvi.value = v1.value + v2.value; + break; + case ARC_sub: + lvi.value = v1.value - v2.value; + break; + case ARC_rsub: + lvi.value = v2.value - v1.value; + break; + case ARC_or: + lvi.value = v1.value | v2.value; + break; + case ARC_asr: + lvi.value = ((int32)v1.value) >> v2.value; + break; + case ARC_lsl: + lvi.value = v1.value << v2.value; + break; + case ARC_lsr: + lvi.value = ((uint32)v1.value) >> v2.value; + break; + case ARC_ror: + v2.value %= 32; + lvi.value = (v1.value >> v2.value) | left_shift(v1.value, 32-v2.value); + break; + case ARC_and: + lvi.value = v1.value & v2.value; + break; + case ARC_xor: + lvi.value = v1.value ^ v2.value; + break; + case ARC_bic: + lvi.value = v1.value & ~v2.value; + break; + } + ok = true; + if ( v1.is_const() && v2.is_const() ) + lvi.set_const(); + // we do not take into account the insns that calculate .got + /* + if ( got_ea == BADADDR || v1.value != got_ea ) + add_eavec(&lvi.insn_eas, v1.insn_eas); + if ( got_ea == BADADDR || v2.value != got_ea ) + add_eavec(&lvi.insn_eas, v2.insn_eas);*/ + lvi.insn_eas.push_back(pinsn->ea); + } + break; + } + } + else if ( (pinsn->itype == ARC_ld || pinsn->itype == ARC_st) + && pinsn->Op2.type == o_displ && pinsn->Op2.reg == reg + && ((pinsn->auxpref & aux_amask) == aux_a || (pinsn->auxpref & aux_amask) == aux_ab) ) + { + // writeback of the base reg + // find the previous value + op_t x = pinsn->Op2; + x.type = o_reg; + ok = do_find_op_value(*pinsn, x, &lvi, nest_level+1); + if ( ok ) + { + // add the immediate + lvi.value += pinsn->Op2.addr; + lvi.insn_eas.push_back(pinsn->ea); + } + } + if ( pm.spoils(*pinsn, reg) ) + break; + } +#ifdef __EA64__ + lvi.value &= 0xFFFFFFFF; +#endif + lvi.set_valid(ok); + regcache[ea].regs[reg] = lvi; + } + while ( false ); + + if ( ok && p_lvi != NULL ) + *p_lvi = lvi; + return ok; +} + +//---------------------------------------------------------------------- +bool arc_t::find_op_value_ex( + const insn_t &insn, + const op_t &x, + struct ldr_value_info_t *lvi, + bool /*check_fbase_reg*/) +{ + reg_tracker_t tr(this); + return tr.do_find_op_value(insn, x, lvi, 0); +} + +//---------------------------------------------------------------------- +// find the value loaded into reg +bool arc_t::find_ldr_value_ex( + const insn_t &insn, + ea_t ea, + int reg, + struct ldr_value_info_t *lvi, + bool /*check_fbase_reg*/) +{ + reg_tracker_t tr(this); + return tr.do_find_ldr_value(insn, ea, reg, lvi, 0); +} + +//---------------------------------------------------------------------- +bool arc_t::find_op_value( + const insn_t &insn, + const op_t &x, + uval_t *p_val, + ea_t *p_val_ea, + bool check_fbase_reg, + bool *was_const_load) +{ + ldr_value_info_t tmp; + if ( find_op_value_ex(insn, x, &tmp, check_fbase_reg) ) + { + if ( p_val != NULL ) + *p_val = tmp.value; + if ( p_val_ea != NULL ) + *p_val_ea = tmp.val_ea; + if ( was_const_load != NULL ) + *was_const_load = tmp.is_const(); + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool arc_t::find_ldr_value( + const insn_t &insn, + ea_t ea, + int reg, + uval_t *p_val, + ea_t *p_val_ea, + bool check_fbase_reg, + bool *was_const_load) +{ + ldr_value_info_t tmp; + if ( find_ldr_value_ex(insn, ea, reg, &tmp, check_fbase_reg) ) + { + if ( p_val != NULL ) + *p_val = tmp.value; + if ( p_val_ea != NULL ) + *p_val_ea = tmp.val_ea; + if ( was_const_load != NULL ) + *was_const_load = tmp.is_const(); + return true; + } + return false; +} + +//------------------------------------------------------------------------- +// 4 sub rA, rA', #minv (optional) +// 3 cmp rA, #size | brhs rA, #size, default +// bhi default or | +// bls body with optional 'b default' +// body: +// 2 ldb.x rA, [rJumps,rA'] | ld.as rA, [#jumps,rA'] (if not using bi/bih) +// 1 add1 rA, rElbase, rA' (optional) +// 0 j [rA] | bi [rA] | bih [rA] + +static const char arc_depends[][4] = +{ + { 1 | JPT_OPT }, // 0 + { 2 }, // 1 optional + { 3 }, // 2 if and only if not using bi/bih + { 4 | JPT_OPT | JPT_NEAR }, // 3 + { 0 }, // 4 optional +}; + +struct arc_jump_pattern_t : public jump_pattern_t +{ +protected: + enum { rA, rC }; + enum + { + BODY_NJPI = 2, // ldb.x rA, [rJumps,rA'] + ELBASE_NJPI = 1, // add1 rA, rElbase, rA' + }; + arc_t ± + ea_t jumps_offset_ea; + int jumps_offset_n; + ea_t elbase_offset_ea; //lint !e958 padding is required + int elbase_offset_n; + +public: + arc_jump_pattern_t(procmod_t *_pm, switch_info_t *_si) + : jump_pattern_t(_si, arc_depends, rC), + pm(*(arc_t *)_pm), + jumps_offset_ea(BADADDR), + jumps_offset_n(-1), + elbase_offset_ea(BADADDR), + elbase_offset_n(-1) + { + modifying_r32_spoils_r64 = false; + si->flags |= SWI_HXNOLOWCASE; + non_spoiled_reg = rA; + } + + virtual void process_delay_slot(ea_t &ea, bool branch) const override; + virtual bool equal_ops(const op_t &x, const op_t &y) const override; + virtual bool handle_mov(tracked_regs_t &_regs) override; + virtual void check_spoiled(tracked_regs_t *_regs) const override; + + bool jpi4() override; // sub rA, rA', #minv + bool jpi3() override; // cmp followed by the conditional jump or 'brhi/lo' + bool jpi2() override; // ldb.x rA, [rJumps,rA'] + bool jpi1() override; // add1 rA, rElbase, rA' + bool jpi0() override; // j [rA] | bi [rA] | bih [rA] + + //lint -esym(1762, arc_jump_pattern_t::finish) member function could be made const + bool finish(); + +protected: + static inline bool optype_supported(const op_t &x); + + // helpers + // brhs rA, #size, default | brlo rA, #size, body + bool jpi_cmp_jump(const op_t **op_var); + // bhi default | bls body with optional 'b default' + bool jpi_condjump(); + // cmp rA, #size + bool jpi_cmp_ncases(const op_t **op_var); + + // prepare and track rC + bool analyze_cond(cond_t cond, ea_t jump); +}; + +//------------------------------------------------------------------------- +void arc_jump_pattern_t::process_delay_slot(ea_t &ea, bool branch) const +{ + flags_t F = get_flags(ea); + if ( !is_code(F) ) + return; + insn_t insn2; + if ( branch ) + { + if ( decode_insn(&insn2, ea) != 0 && has_dslot(insn2) ) + ea += insn2.size; + } + /*else + { + return; // no 'likely' insn in ARC + }*/ +} + +//------------------------------------------------------------------------- +bool arc_jump_pattern_t::equal_ops(const op_t &x, const op_t &y) const +{ + if ( x.type != y.type ) + return false; + // ignore difference in the data size of registers + switch ( x.type ) + { + case o_void: + // consider spoiled values as not equal + return false; + case o_reg: + return x.reg == y.reg; + case o_displ: + return x.phrase == y.phrase && x.addr == y.addr; + case o_condjump: + // we do not track the condition flags + return true; + } + return false; +} + +//------------------------------------------------------------------------- +inline bool arc_jump_pattern_t::optype_supported(const op_t &x) +{ + // we can work with the following types only + return x.type == o_reg && x.reg <= R63 + || x.type == o_displ; +} + +//------------------------------------------------------------------------- +bool arc_jump_pattern_t::handle_mov(tracked_regs_t &_regs) +{ + const op_t *src = &insn.Op2; + const op_t *dst = &insn.Op1; + switch ( insn.itype ) + { + case ARC_add: + case ARC_lsl: + case ARC_lsr: + case ARC_sub: + case ARC_xor: + case ARC_or: + if ( insn.Op3.type != o_imm || insn.Op3.value != 0 ) + return false; + // no break + case ARC_ld: + case ARC_mov: + break; + case ARC_st: + std::swap(src, dst); + break; + default: + return false; + } + if ( !optype_supported(*src) || optype_supported(*dst) ) + return false; + return set_moved(*dst, *src, _regs); +} + +//------------------------------------------------------------------------- +void arc_jump_pattern_t::check_spoiled(tracked_regs_t *__regs) const +{ + tracked_regs_t &_regs = *__regs; + for ( uint i = 0; i < _regs.size(); ++i ) + { + const op_t &x = _regs[i]; + if ( x.type == o_reg && pm.spoils(insn, x.reg) + || x.type == o_condjump && spoils_flags(insn) ) + { + set_spoiled(&_regs, x); + } + } + check_spoiled_not_reg(&_regs, PROC_MAXCHGOP); +} + +//---------------------------------------------------------------------- +// j [rA] +bool arc_jump_pattern_t::jpi0() +{ + if ( insn.itype == ARC_bi || insn.itype == ARC_bih ) + { + si->jumps = insn.ea + insn.size; + si->flags |= SWI_JMPINSN; + si->set_jtable_element_size(insn.itype == ARC_bi ? 4 : 2); + + skip[1] = true; // no jpi2 + skip[2] = true; // no jpi2 + track(insn.Op1.secreg, rA, dt_dword); + return true; + } + + if ( insn.itype != ARC_j + || insn.Op1.type != o_displ + || insn.Op1.addr != 0 + || has_cond(insn) ) + { + return false; + } + track(insn.Op1.phrase, rA, dt_dword); + return true; +} + +//---------------------------------------------------------------------- +// add1 rA, rElbase, rA' +bool arc_jump_pattern_t::jpi1() +{ + if ( insn.itype != ARC_add1 + && insn.itype != ARC_add2 + && insn.itype != ARC_add + || has_cond(insn) + || !is_equal(insn.Op1, rA) ) + { + return false; + } + + ea_t elbase; + const op_t *op_var; + if ( insn.Op2.type == o_imm && optype_supported(insn.Op3) ) + { + elbase = insn.Op2.value; + elbase_offset_ea = insn.ea; + elbase_offset_n = 1; + op_var = &insn.Op3; + } + else if ( insn.itype == ARC_add + && insn.Op3.type == o_imm + && optype_supported(insn.Op2) ) + { + elbase = insn.Op3.value; + elbase_offset_ea = insn.ea; + elbase_offset_n = 2; + op_var = &insn.Op2; + } + else + { + ldr_value_info_t lvi; + if ( insn.Op2.type == o_reg + && optype_supported(insn.Op3) + && pm.find_ldr_value_ex(insn, insn.ea, insn.Op2.reg, &lvi, true) ) + { + op_var = &insn.Op3; + } + else if ( insn.itype == ARC_add + && insn.Op3.type == o_reg + && optype_supported(insn.Op2) + && pm.find_ldr_value_ex(insn, insn.ea, insn.Op3.reg, &lvi, true) ) + { + op_var = &insn.Op2; + } + else + { + return false; + } + elbase = lvi.value; + elbase_offset_ea = lvi.val_ea; + elbase_offset_n = lvi.n; + } + + si->set_elbase(elbase); + if ( insn.itype == ARC_add1 ) + si->set_shift(1); + else if ( insn.itype == ARC_add2 ) + si->set_shift(2); + trackop(*op_var, rA); + return true; +} + +//---------------------------------------------------------------------- +// ldb.x rA, [rJumps,rA'] +// ldb.x rA, [rA',rJumps] +// ldw.as rA, [rJumps,rA'] +// ldw.x rA, [rA',rJumps] +// ld.x.as rA, [#jumps,rA'] +// ldb rA, [rA',#jumps] +bool arc_jump_pattern_t::jpi2() +{ + if ( insn.itype != ARC_ld + || insn.Op2.type != o_displ && insn.Op2.type != o_phrase + || !is_equal(insn.Op1, rA) ) + { + return false; + } + + int elsize; + switch ( insn.auxpref & aux_zmask ) + { + case aux_b: + elsize = 1; + break; + case aux_w: + elsize = 2; + break; + case aux_l: + elsize = 4; + break; + default: + return false; + } + + int reg_var = -1; + + // do we have scaled load? + switch ( insn.auxpref & aux_amask ) + { + case aux_anone: + if ( elsize != 1 ) + { + // check for preceding scale instruction + // 2: asl r12, r1 (shift by one) + // 4: asl r12, r1, 2 + insn_t prev; + if ( decode_prev_insn(&prev, insn.ea) != BADADDR + && prev.itype == ARC_asl + && is_equal(prev.Op1, rA) ) + { + if ( elsize == 2 && prev.Op3.type == o_void + || elsize == 2 && prev.Op3.type == o_imm && prev.Op3.value == 2 ) + { + reg_var = prev.Op2.reg; + break; + } + } + return false; + + } + break; + case aux_as: + // nothing to do, index is scaled during load + break; + default: + // writeback or pre-increment: not valid here + return false; + } + + const op_t &x = insn.Op2; + ea_t jumps; + if ( x.type == o_phrase ) + { + ldr_value_info_t lvi; + if ( reg_var == -1 ) + { + if ( pm.find_ldr_value_ex(insn, insn.ea, x.phrase, &lvi, true) ) + { + reg_var = x.secreg; + } + else if ( elsize == 1 + && pm.find_ldr_value_ex(insn, insn.ea, x.secreg, &lvi, true) ) + { + reg_var = x.phrase; + } + else + { + return false; + } + } + jumps = lvi.value; + jumps_offset_ea = lvi.val_ea; + jumps_offset_n = lvi.n; + } + // x.type == o_displ + else if ( x.type == o_displ ) + { + if ( reg_var == -1 ) + { + if ( x.membase != 1 && elsize != 1 ) + return false; + reg_var = x.phrase; + } + jumps = x.addr; + jumps_offset_ea = insn.ea; + jumps_offset_n = 1; + } + else + { + return false; + } + + si->jumps = jumps; + si->set_jtable_element_size(elsize); + if ( (insn.auxpref & aux_x) != 0 ) + si->flags |= SWI_SIGNED; + track(reg_var, rA, dt_dword); + return true; +} + +//---------------------------------------------------------------------- +// cmp followed by the conditional jump or 'brhi/lo' +bool arc_jump_pattern_t::jpi3() +{ + // var should not be spoiled + QASSERT(10312, !is_spoiled(rA)); + + const op_t *op_var; + if ( !jpi_cmp_jump(&op_var) + && (jpi_condjump() // continue matching if found + || is_spoiled(rC) + || !jpi_cmp_ncases(&op_var)) ) + { + return false; + } + op_t &op = regs[rC]; + // assert: op.type == o_condjump + if ( (op.value & cc_inc_ncases) != 0 ) + ++si->ncases; + si->defjump = op.specval; + si->set_expr(op_var->reg, op_var->dtype); + return true; +} + +//---------------------------------------------------------------------- +// sub rA, rA', #minv +bool arc_jump_pattern_t::jpi4() +{ + if ( insn.itype != ARC_sub + || has_cond(insn) + || insn.Op3.type != o_imm + || !is_equal(insn.Op1, rA) ) + { + return false; + } + si->lowcase = insn.Op3.value; + return true; +} + +//------------------------------------------------------------------------- +bool arc_jump_pattern_t::finish() +{ + if ( !skip[2] ) + { + if ( eas[ELBASE_NJPI] != BADADDR && elbase_offset_ea != BADADDR ) + op_offset(elbase_offset_ea, elbase_offset_n, REF_OFF32); + if ( jumps_offset_ea != BADADDR ) + op_offset(jumps_offset_ea, jumps_offset_n, REF_OFF32); + } + return true; +} + +//------------------------------------------------------------------------- +// brhs rA, #size, default +// brlo #size, rA, default +// brlo rA, #size, body +// brhs #size, rA, body +bool arc_jump_pattern_t::jpi_cmp_jump(const op_t **op_var) +{ + if ( insn.itype != ARC_br + || insn.Op3.type != o_near + || !has_core_cond(insn) ) + { + return false; + } + cond_t cond = get_core_cond(insn); + if ( cond != cLO && cond != cHS ) + return false; + uval_t size; + if ( insn.Op1.type == o_reg && insn.Op2.type == o_imm ) + { + *op_var = &insn.Op1; + size = insn.Op2.value; + } + else if ( insn.Op1.type == o_imm && insn.Op2.type == o_reg ) + { + cond = invert_cond(cond); + *op_var = &insn.Op2; + size = insn.Op1.value; + } + else + { + return false; + } + if ( !analyze_cond(cond, to_ea(insn.cs, insn.Op3.addr)) ) + return false; + si->ncases = ushort(size); + trackop(**op_var, rA); + return true; +} + +//------------------------------------------------------------------------- +// bhi default | bls body with optional 'b default' +bool arc_jump_pattern_t::jpi_condjump() +{ + if ( insn.itype != ARC_b + || insn.Op1.type != o_near + || !has_core_cond(insn) ) + { + return false; + } + return analyze_cond(get_core_cond(insn), to_ea(insn.cs, insn.Op1.addr)); +} + +//------------------------------------------------------------------------- +// cmp rA, #size +bool arc_jump_pattern_t::jpi_cmp_ncases(const op_t **op_var) +{ + // assert: !is_spoiled(rA) because rA is non spoiled register + if ( insn.itype != ARC_cmp + || has_cond(insn) + || insn.Op2.type != o_imm + || !same_value(insn.Op1, rA) ) + { + return false; + } + si->ncases = ushort(insn.Op2.value); + // continue to track rA + *op_var = &insn.Op1; + return true; +} + +//------------------------------------------------------------------------- +// prepare and track rC +bool arc_jump_pattern_t::analyze_cond(cond_t cond, ea_t jump) +{ + op_t op; + op.type = o_condjump; + op.value = 0; + switch ( cond ) + { + case cHI: // higher + case cLS: // lower or same + case cGT: + case cLE: + op.value |= cc_inc_ncases; + break; + case cLO: // lower + case cHS: // higher or same + case cLT: + case cGE: + break; + default: + return false; + } + + switch ( cond ) + { + case cHI: // higher + case cHS: // higher or same + case cGT: + case cGE: + op.specval = jump; + break; + case cLO: // lower + case cLS: // lower or same + case cLT: + case cLE: + // we have conditional jump to the switch body + { + ea_t body = eas[BODY_NJPI]; + // assert: body != BADADDR + if ( jump > body ) + return false; + op.specval = insn.ea + insn.size; + + // possibly followed by 'b default' + insn_t dflt; + if ( decode_insn(&dflt, op.specval) > 0 + && dflt.itype == ARC_b + && !has_cond(insn) + && !has_dslot(insn) + && dflt.Op1.type == o_near ) + { + op.specval = to_ea(dflt.cs, dflt.Op1.addr); + } + } + break; + default: + return false; + } + op.addr = insn.ea; + trackop(op, rC); + return true; +} + +//---------------------------------------------------------------------- +static int is_jump_pattern(switch_info_t *si, const insn_t &insn, procmod_t *pm) +{ + arc_jump_pattern_t jp(pm, si); + if ( !jp.match(insn) || !jp.finish() ) + return JT_NONE; + return JT_SWITCH; +} + +//---------------------------------------------------------------------- +bool arc_is_switch(switch_info_t *si, const insn_t &insn) +{ + if ( insn.itype != ARC_j + && insn.itype != ARC_bi + && insn.itype != ARC_bih ) + return false; + + static is_pattern_t *const patterns[] = + { + is_jump_pattern, + }; + return check_for_table_jump(si, insn, patterns, qnumber(patterns)); +} + +//---------------------------------------------------------------------- +// Trace the value of the SP and create an SP change point if the current +// instruction modifies the SP. +sval_t arc_t::calc_sp_delta(const insn_t &insn) +{ + if ( has_cond(insn) ) // trace only unconditional instructions + return 0; // conditional instructions may be + // corrected manually + switch ( insn.itype ) + { + case ARC_add: + case ARC_sub: + if ( insn.Op1.is_reg(SP) && insn.Op2.is_reg(SP) ) + { + // add sp, sp, #imm + // add sp, sp, r1 + uval_t spofs; + if ( find_op_value(insn, insn.Op3, &spofs, NULL, false) && (spofs & 3) == 0 ) + return insn.itype == ARC_sub ? -spofs : spofs; + } + break; + case ARC_push: // push [reg] + return -4; + case ARC_pop: // pop [reg] + return +4; + case ARC_ld: // ld.ab fp, [sp,4] + case ARC_st: // st.a fp, [sp,-4] + if ( insn.Op2.type == o_displ + && insn.Op2.reg == SP + && ((insn.auxpref & aux_amask) == aux_a || (insn.auxpref & aux_amask) == aux_ab) ) + { + if ( (insn.Op2.addr & 3) == 0 ) + return insn.Op2.addr; + } + break; + case ARC_bl: // bl __ac_push_13_to_NN: push 13..NN + case ARC_b: // b __ac_pop_13_to_NN: pop 13..NN,blink + { + ea_t call_ea = to_ea(insn.cs, insn.Op1.addr); + sval_t delta; + if ( is_millicode(call_ea, &delta) ) + { + if ( delta == BADADDR ) + break; + return delta; + } + } + break; + case ARC_enter: + case ARC_leave: + { + sval_t nregs = insn.Op1.reglist & REGLIST_REGS; + nregs += (insn.Op1.reglist & REGLIST_FP) != 0; + nregs += (insn.Op1.reglist & REGLIST_BLINK) != 0; + + return 4 * (insn.itype == ARC_enter ? -nregs : nregs); + } + default: + if ( insn.Op1.is_reg(SP) && insn.itype != ARC_mov ) + { + // msg("??? illegal access mode sp @ %a\n", insn.ea); + } + break; + } + return 0; +} + +//---------------------------------------------------------------------- +// Add a SP change point. We assume that SP is always divisible by 4 +inline void add_stkpnt(const insn_t &insn, func_t *pfn, sval_t v) +{ + add_auto_stkpnt(pfn, insn.ea+insn.size, v); +} + +//---------------------------------------------------------------------- +// Trace the value of the SP and create an SP change point if the current +// instruction modifies the SP. +void arc_t::trace_sp(const insn_t &insn) +{ + func_t *pfn = get_func(insn.ea); + if ( pfn == NULL ) + return; // no function -> we don't care about SP + + sval_t delta = calc_sp_delta(insn); + if ( delta != 0 ) + add_stkpnt(insn, pfn, delta); +} + +//---------------------------------------------------------------------- +bool arc_t::arc_calc_spdelta(sval_t *spdelta, const insn_t &insn) +{ + *spdelta = calc_sp_delta(insn); + return true; +} + +//-------------------------------------------------------------------------- +// is the input file object file? +// in such files, the references will be fixed up by the linker +static bool is_object_file(void) +{ + // Currently we know only about ELF relocatable files + if ( inf_get_filetype() == f_ELF ) + { + char buf[MAXSTR]; + if ( get_file_type_name(buf, sizeof(buf)) > 0 + && stristr(buf, "reloc") != NULL ) // ELF (Relocatable) + { + return true; + } + } + + return false; +} + +//-------------------------------------------------------------------------- +// force the offset by the calculated base +void arc_t::force_offset( + ea_t ea, + int n, + ea_t base, + bool issub, + int scale) +{ + if ( !is_off(get_flags(ea), n) + || !is_object_file() && get_offbase(ea, n) != base ) + { + refinfo_t ri; + + reftype_t reftype = REF_OFF32; + if ( scale == 2 ) + reftype = ref_arcsoh_id | REFINFO_CUSTOM; + else if ( scale == 4 ) + reftype = ref_arcsol_id | REFINFO_CUSTOM; + + ri.init(reftype|REFINFO_NOBASE|(issub ? REFINFO_SUBTRACT : 0), base); + op_offset_ex(ea, n, &ri); + } +} + +//-------------------------------------------------------------------------- +// add resolved target address, to be displayed as a comment +inline void arc_t::add_dxref(const insn_t &insn, ea_t target) +{ + // only add it if the comment would not be displayed otherwise + // ASCII xrefs show up as comments + if ( (inf_get_strlit_flags() & STRF_COMMENT) && is_strlit(get_flags(target)) ) + return; + + // repeatable comments follow xrefs + if ( get_cmt(NULL, target, true) > 0 ) + return; + + // demangled names show as comments + // FIXME: get rid of GN_INSNLOC +#define MY_GN_INSNLOC 0x0080 + if ( get_demangled_name(NULL, target, inf_get_short_demnames(), + DEMNAM_CMNT, GN_STRICT|MY_GN_INSNLOC) > 0 ) + return; + + set_dxref(insn.ea, target); +} + +//---------------------------------------------------------------------- +static bool is_good_target(ea_t ea) +{ + // address must exist + if ( !is_mapped(ea) ) + return false; + + flags_t F = get_flags(ea); + if ( !is_code(F) ) + return true; + + // don't point into middle of instructions + return !is_tail(F); +} + +//---------------------------------------------------------------------- +// Emulate an instruction +int arc_t::emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + + islast = Feature & CF_STOP; + + ea_t cmdend = insn.ea + insn.size; + + if ( helper.altval_ea(insn.ea, DSLOT_TAG) == 1 ) + islast = 1; // previous instruction was an unconditional jump/branch + + // you may emulate selected instructions with a greater care: + switch ( insn.itype ) + { + case ARC_j: + case ARC_b: + if ( !has_cond(insn) ) // branch always + islast = 1; + break; + case ARC_bi: + case ARC_bih: + islast = 1; + break; + case ARC_leave: + if ( (insn.Op1.reglist & REGLIST_PCL) != 0 ) // branch to blink + islast = 1; + break; + case ARC_add: // add r1, r2, #imm + case ARC_sub: // sub r1, r2, #imm + if ( (idpflags & ARC_TRACKREGS) != 0 + && insn.Op1.type == o_reg + && !is_stkptr(insn, insn.Op2.reg) + && !is_defarg(get_flags(insn.ea), 2) ) + { + bool issub = insn.itype == ARC_sub; + ea_t val1 = BADADDR; + if ( find_op_value(insn, insn.Op2, &val1) && val1 != 0 ) + { + if ( insn.Op3.type == o_imm && insn.Op3.value > 3 && is_good_target(val1 + insn.Op3.value) ) + { + force_offset(insn.ea, 2, val1, issub); + } + else if ( insn.Op2.reg != insn.Op3.reg ) + { + // mov r12, #imm + // sub r3, r15, r12 + ldr_value_info_t lvi; + if ( find_op_value_ex(insn, insn.Op3, &lvi, false) && lvi.value > 3 ) + { + ea_t target = issub ? (val1 - lvi.value) : (val1 + lvi.value); + if ( is_good_target(target) ) + { + force_offset(lvi.val_ea, lvi.n, val1, issub); + add_dxref(insn, target & 0xFFFFFFFF); + } + } + } + } + } + break; + case ARC_ld: // ld r1, [r2, #imm] + case ARC_st: // st r1, [r2, #imm] + if ( (idpflags & ARC_TRACKREGS) != 0 + && insn.Op2.type == o_displ + && !is_stkptr(insn, insn.Op2.reg) + && !is_defarg(get_flags(insn.ea), 1) ) + { + ea_t val1 = BADADDR; + if ( insn.Op2.addr > 3 && find_ldr_value(insn, insn.ea, insn.Op2.reg, &val1) && val1 != 0 ) + { + if ( (insn.auxpref & aux_amask) == aux_ab ) // post-increment + val1 -= insn.Op2.addr; + if ( is_good_target(val1 + insn.Op2.addr) ) + force_offset(insn.ea, 1, val1, false, get_scale_factor(insn)); + } + } + break; + } + + // trace the stack pointer if: + // - it is the second analysis pass + // - the stack pointer tracing is allowed + if ( may_trace_sp() ) + { + if ( !islast ) + trace_sp(insn); // trace modification of SP register + else + recalc_spd(insn.ea); // recalculate SP register for the next insn + } + + for ( int i = 0; i < PROC_MAXOP; ++i ) + { + if ( has_cf_use(Feature, i) ) + handle_operand(insn, insn.ops[i], true); + } + + for ( int i = 0; i < PROC_MAXOP; ++i ) + { + if ( has_cf_chg(Feature, i) ) + handle_operand(insn, insn.ops[i], false); + } + + // if the execution flow is not stopped here, then create + // a xref to the next instruction. + // Thus we plan to analyze the next instruction. + + if ( !islast || has_dslot(insn) ) + add_cref(insn.ea, cmdend, fl_F); + else if ( get_auto_state() == AU_USED ) + recalc_spd(insn.ea); + + if ( has_dslot(insn) ) + { + // mark the following address as a delay slot + int slotkind; + if ( insn.itype == ARC_bl || insn.itype == ARC_jl ) + slotkind = 3; + else + slotkind = islast ? 1 : 2; + helper.altset_ea(cmdend, slotkind, DSLOT_TAG); + } + else + { + helper.altdel_ea(cmdend, DSLOT_TAG); + } + return 1; // actually the return value is unimportant, but let's it be so +} + +//---------------------------------------------------------------------- +bool idaapi create_func_frame(func_t * pfn) +{ + ea_t ea = pfn->start_ea; + + insn_t insn; + for ( int i = 0; i < 10 && ea < pfn->end_ea; i++ ) + { + if ( !decode_insn(&insn, ea) ) + break; + // move fp, sp + // enter_s [...,fp,...] + if ( insn.itype == ARC_mov + && insn.Op1.is_reg(FP) + && insn.Op2.is_reg(SP) + || insn.itype == ARC_enter + && (insn.Op1.reglist & REGLIST_FP) != 0 ) + { + pfn->flags |= FUNC_FRAME; + update_func(pfn); + } + // sub sp, sp + if ( insn.itype == ARC_sub + && insn.Op1.is_reg(SP) + && insn.Op2.is_reg(SP) + && insn.Op3.type == o_imm ) + { + return add_frame(pfn, insn.Op3.value, 0, 0); + } + ea += insn.size; + } + return 0; +} + +//---------------------------------------------------------------------- +int idaapi is_sp_based(const insn_t &insn, const op_t & x) +{ + int flag = OP_FP_BASED; + if ( x.type == o_displ && x.reg == SP + || (x.type == o_imm && x.n == 2 && insn.itype == ARC_add && !insn.Op2.is_reg(FP)) ) + { + // add rx, sp, #imm + flag = OP_SP_BASED; + } + return OP_SP_ADD | flag; +} + +//---------------------------------------------------------------------- +int idaapi arc_get_frame_retsize(const func_t * /*pfn */ ) +{ + return 0; +} + +// #processor_t.is_align_insn +//---------------------------------------------------------------------- +// Is the instruction created only for alignment purposes? +// returns: number of bytes in the instruction +int arc_t::is_align_insn(ea_t ea) const +{ + if ( ptype == prc_arcompact ) + { + if ( (ea & 3) != 0 ) + return 0; + if ( get_word(ea) == 0x78E0 ) // nop_s + return 2; + if ( get_word(ea) == 0x264A && get_word(ea+2) == 0x7000 ) // mov 0, 0 + return 4; + } + return 0; +} + +//---------------------------------------------------------------------- +static bool can_be_data(ea_t target) +{ + if ( (target & 3) == 0 ) + { + segment_t *seg = getseg(target); + if ( seg == NULL ) + return false; + if ( seg->start_ea == target ) + return true; + ea_t prev = prev_head(target, seg->start_ea); + if ( prev != BADADDR && is_data(get_flags(prev)) ) + return true; + } + return false; +} + +//---------------------------------------------------------------------- +// we have a possible reference from current instruction to 'target' +// check if we should make it an offset +bool arc_t::good_target(const insn_t &insn, ea_t target) const +{ + if ( target <= ' ' ) + return false; + + // check if it points to code + flags_t F = get_flags(target&~1); + if ( is_code(F) ) + { + // arcompact code references should have bit 0 set + if ( ptype == prc_arcompact && ((target & 1) == 0) ) + return false; + + // arc4 should be word-aligned + if ( ptype == prc_arc && ((target & 3) != 0) ) + return false; + + if ( !is_head(F) ) // middle of instruction? + return false; + + // if we're referencing middle of a function, it should be the same function + func_t *pfn = get_func(target); + if ( pfn == NULL && is_flow(F) ) + return false; + if ( pfn != NULL && pfn->start_ea != target && !func_contains(pfn, insn.ea) ) + return false; + + return true; + } + else if ( is_data(F) || segtype(target) == SEG_DATA || can_be_data(target) ) + { + return true; + } + return false; +} + +//---------------------------------------------------------------------- +// returns target address +bool arc_t::copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, void *value, bool force) const +{ + flags_t F = get_flags(ea); + flags_t iflag = get_flags(insn.ea); + if ( is_dword(F) && x.dtype == dt_dword + || is_word(F) && x.dtype == dt_word + || is_byte(F) && x.dtype == dt_byte + || is_float(F) && x.dtype == dt_float + || is_double(F) && x.dtype == dt_double ) + { + if ( force || is_defarg(F, 0) && is_defarg(iflag, x.n) ) + { + // both are defined - check that the data types are the same + // if not, copy insntype -> dwordtype + flags_t fd = get_optype_flags0(F); + flags_t fi = get_optype_flags0(x.n ? (iflag>>4) : iflag); + if ( fd != fi ) + { + F = (F ^ fd) | fi; + opinfo_t ti; + get_opinfo(&ti, insn.ea, x.n, iflag); + set_opinfo(ea, 0, F, &ti); + set_op_type(ea, F, 0); + plan_ea(insn.ea); + plan_ea(ea); + } + } + if ( x.dtype == dt_dword ) + { + if ( !is_defarg(F, 0) || (is_off(F, 0) && get_offbase(ea, 0) == to_ea(insn.cs, 0)) ) + { + uint32 pcval = get_dword(ea); + ea_t target = to_ea(insn.cs, pcval); + // if the data is a 32-bit value which can be interpreted as an address + // then convert it to an offset expression + if ( get_auto_state() == AU_USED + // && (inf.af & AF_DATOFF) != 0 + // && target > ' ' + && good_target(insn, target) ) + { + if ( !is_defarg(F, 0) ) + op_plain_offset(ea, 0, to_ea(insn.cs, 0)); + if ( !is_defarg(get_flags(insn.ea), x.n) ) + { + op_plain_offset(insn.ea, x.n, to_ea(insn.cs, 0)); + } + } + // add xref from "LDR Rx,=addr" to addr. + if ( is_off(F, 0) ) + { + // NB: insn_t::add_dref uses insn.ea to calculate the target + // of a reloc so we can't use it here + ea_t newto = get_name_base_ea(ea, target); + dref_t type = dr_O; + if ( newto != target ) + { + type = dref_t(type | XREF_TAIL); + target = newto; + } + add_dref(insn.ea, target, type); + // helper.altdel_ea(ea, DELAY_TAG); + } + else + { + // analyze later for a possible offset + // helper.altset_ea(ea, 1, DELAY_TAG); + } + } + } + if ( value != NULL ) + { + switch ( x.dtype ) + { + case dt_dword: + *(uint32*)value = get_dword(ea); + break; + case dt_word: + *(uint16*)value = get_word(ea); + break; + case dt_byte: + *(uint8*)value = get_byte(ea); + break; + case dt_float: + *(uint32*)value = 0; + get_bytes(value, 4, ea); + break; + case dt_double: + *(uint64*)value = 0; + get_bytes(value, 8, ea); + break; + } + } + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +// Is the current instruction "return"? (conditional or not) +bool is_arc_return_insn(const insn_t &insn) +{ + switch ( insn.itype ) + { + case ARC_j: + // j blink (A4) or j [blink] (compact) is a return + return insn.Op1.reg == BLINK; + case ARC_leave: + // leave [..,pcl,...] is a return + return insn.Op1.reglist & REGLIST_PCL; + } + return false; +} + +//-------------------------------------------------------------------------- +static const int rv_arc[] = { R0, R1, R2, R3, R4, R5, R6, R7, -1 }; + +int get_arc_fastcall_regs(const int **regs) +{ + *regs = rv_arc; + return qnumber(rv_arc) - 1; +} + +//---------------------------------------------------------------------- +static void add_argregs(argloc_t *argloc, int r, int nregs, int size, bool force_scattered) +{ + QASSERT(10306, size > (nregs-1) * 4); + QASSERT(10307, r + nregs < qnumber(rv_arc)); + if ( force_scattered || nregs >= 2 && size != 8 ) + { + scattered_aloc_t *scloc = new scattered_aloc_t; + int off = 0; + for ( int i = 0; i < nregs; ++i, ++r, off += 4 ) + { + argpart_t ®loc = scloc->push_back(); + regloc.off = off; + regloc.set_reg1(rv_arc[r]); + regloc.size = qmin(size, 4); + size -= 4; + } + argloc->consume_scattered(scloc); + } + else if ( size == 8 ) + { + argloc->set_reg2(rv_arc[r], rv_arc[r+1]); + } + else + { + argloc->set_reg1(rv_arc[r]); + } +} + +//------------------------------------------------------------------------- +bool calc_arc_retloc(argloc_t *retloc, const tinfo_t &tif, cm_t /*cc*/) +{ + if ( !tif.is_void() ) + { + int size = tif.get_size(); + int nregs = (size + 3) / 4; + if ( nregs >= qnumber(rv_arc) ) + return false; + add_argregs(retloc, 0, nregs, size, false); + } + debug_print_argloc(-1, *retloc, tif); + return true; +} + +//---------------------------------------------------------------------- +// note: currently we do not support partial allocation (when part of +// the argument is in a register and another part is on the stack) +// fixme, but how? we need a means of telling the kernel about partial allocations +static bool alloc_args(func_type_data_t *fti, int nfixed) +{ + if ( !calc_arc_retloc(&fti->retloc, fti->rettype, 0 /*fti->get_cc()*/) ) + return false; + + int r = 0; + int fr = 0; + const int NUMREGARGS = 8; + + // if function returns its value in the memory + size_t retsize = fti->rettype.get_size(); + if ( retsize != BADSIZE && retsize > 8 && !fti->rettype.is_floating() ) + r++; // R0 is used to point to the result + + sval_t spoff = 0; + for ( int i=0; i < fti->size(); i++ ) + { + size_t size; + uint32 align; + funcarg_t &fa = fti->at(i); + const tinfo_t &type = fa.type; + if ( type.empty() && i >= nfixed ) + { + size = fa.argloc.stkoff(); + align = size; + } + else + { + size = type.get_size(&align); + } + if ( size == BADSIZE ) + return false; + // XXX: does ARC ABI align 64-bit params? so far doesn't look like it + if ( size == 8 && align > 4 ) + align = 4; +#ifndef FP_ABI_HARD + qnotused(fr); +#else + // currently we support only soft fpu abi + // todo: add config option to switch between abis + if ( (size == 4 || size == 8 || size == 16) + && type.is_floating() ) + { + // use floating point registers + int fpr; + switch ( size ) + { + case 4: + fpr = S0 + fr; + fr++; + break; + case 8: + case 16: // we do not have Q.. registers yet + fr = align_up(fr, 2); + fpr = D0 + fr/2; + fr += 2; + break; + } + if ( fr > 16 ) + goto ALLOC_ON_STACK; // no more fpregs + fa.argloc.set_reg1(fpr); + debug_print_argloc(i, fa.argloc, fa.type); + continue; + } +#endif + size = align_up(size, 4); + // XXX: align regs to even pairs? + /*if ( align > 4 && r < NUMREGARGS ) + r = align_up(r, 2);*/ + if ( r < NUMREGARGS && size <= 16 ) + { + int nregs = (size+3) / 4; + int start_reg = r; + r += nregs; + if ( nregs == 1 ) + { + fa.argloc.set_reg1(rv_arc[start_reg]); + } + else if ( r <= NUMREGARGS ) + { + add_argregs(&fa.argloc, start_reg, nregs, size, false); + } + else + { // part of the argument is passed on the stack: mixed scattered + int nr = NUMREGARGS - start_reg; + add_argregs(&fa.argloc, start_reg, nr, nr * 4, true); + scattered_aloc_t &scloc = fa.argloc.scattered(); + argpart_t &stkloc = scloc.push_back(); + stkloc.off = nr * 4; + stkloc.size = size - stkloc.off; + stkloc.set_stkoff(0); + spoff += align_up(stkloc.size, 4); + } + } + else + { +// ALLOC_ON_STACK: + if ( align > 4 ) + spoff = align_up(spoff, 8); + fa.argloc.set_stkoff(spoff); + spoff += size; + } + debug_print_argloc(i, fa.argloc, fa.type); + } + fti->stkargs = spoff; + return true; +} + +//---------------------------------------------------------------------- +bool calc_arc_arglocs(func_type_data_t *fti) +{ + return alloc_args(fti, fti->size()); +} + +//------------------------------------------------------------------------- +bool calc_arc_varglocs( + func_type_data_t *fti, + regobjs_t * /*regargs*/, + int nfixed) +{ + return alloc_args(fti, nfixed); +} + +//------------------------------------------------------------------------- +// returns: +// -1: doesn't spoil anything +// -2: spoils everything +// >=0: the number of the spoiled register +int arc_t::spoils(const insn_t &insn, const uint32 *regs, int n) const +{ + if ( is_call_insn(insn) ) + return -2; + + for ( int i=0; i < n; i++ ) + if ( spoils(insn, regs[i]) ) + return i; + + return -1; +} + +//------------------------------------------------------------------------- +bool arc_t::arc_set_op_type( + const insn_t &insn, + const op_t &x, + const tinfo_t &tif, + const char *name, + eavec_t *visited) +{ + tinfo_t type = tif; + switch ( x.type ) + { + case o_imm: + if ( type.is_ptr() + && x.value != 0 + && !is_defarg(get_flags(insn.ea), x.n) ) + { + op_plain_offset(insn.ea, x.n, to_ea(insn.cs, 0)); + return true; + } + break; + case o_mem: + { + ea_t dea = to_ea(insn.cs, x.addr); + return apply_once_tinfo_and_name(dea, type, name); + } + case o_displ: + return apply_tinfo_to_stkarg(insn, x, x.addr, type, name); + case o_reg: + { + uint32 r = x.reg; + func_t *pfn = get_func(insn.ea); + if ( pfn == NULL ) + return false; + bool ok; + bool farref; + func_item_iterator_t fii; + insn_t insn1; + for ( ok=fii.set(pfn, insn.ea); + ok && (ok=fii.decode_preceding_insn(visited, &farref, &insn1)) != false; + ) + { + if ( visited->size() > 4096 ) + break; // decoded enough of it, abandon + if ( farref ) + continue; + switch ( insn1.itype ) + { + case ARC_mov: + case ARC_ld: + if ( insn1.Op1.reg != r ) + continue; + return arc_set_op_type(insn, insn1.Op2, type, name, visited); + case ARC_add: + case ARC_sub: + // SUB R3, R11, #-var_12C + // ADD R1, SP, #var_1C + if ( insn1.Op1.reg != r ) + continue; + if ( (issp(insn1.Op2) /*|| isfp(insn1.Op2)*/ ) + && insn1.Op3.type != o_void ) + { + if ( remove_tinfo_pointer(&type, &name) ) + return apply_tinfo_to_stkarg(insn, insn1.Op3, insn1.Op3.value, type, name); + } + // no break + default: + { + int code = spoils(insn, &r, 1); + if ( code == -1 ) + continue; + } + break; + } + break; + } + } + break; + } + return false; +} + +//------------------------------------------------------------------------- +int arc_t::use_arc_regarg_type(ea_t ea, const funcargvec_t &rargs) +{ + int idx = -1; + insn_t insn; + if ( decode_insn(&insn, ea) ) + { + qvector<uint32> regs; + int n = rargs.size(); + regs.resize(n); + for ( int i=0; i < n; i++ ) + regs[i] = rargs[i].argloc.reg1(); + + idx = spoils(insn, regs.begin(), n); + if ( idx >= 0 ) + { + tinfo_t type = rargs[idx].type; + const char *name = rargs[idx].name.begin(); + switch ( insn.itype ) + { + + case ARC_add: // add r1, sp, #stkvar + case ARC_sub: // sub r1, r11, #0x15C + if ( (issp(insn.Op2) /*|| isfp(insn.Op2)*/) + && insn.Op3.type != o_void ) + if ( remove_tinfo_pointer(&type, &name) ) + apply_tinfo_to_stkarg(insn, insn.Op3, insn.Op3.value, type, name); + break; + case ARC_mov: + case ARC_ld: + { + eavec_t visited; + arc_set_op_type(insn, insn.Op2, type, name, &visited); + } + break; + default: // unknown instruction changed the register, stop tracing it + idx |= REG_SPOIL; + break; + } + } + } + return idx; +} + +//------------------------------------------------------------------------- +struct arc_argtinfo_helper_t : public argtinfo_helper_t +{ + arc_t ± + arc_argtinfo_helper_t(arc_t &_pm) : pm(_pm) {} + bool idaapi set_op_tinfo( + const insn_t &insn, + const op_t &x, + const tinfo_t &tif, + const char *name) override + { + eavec_t visited; + return pm.arc_set_op_type(insn, x, tif, name, &visited); + } + + // does the current instruction prepare a stack argument? + bool idaapi is_stkarg_load(const insn_t &insn, int *src, int *dst) override + { + if ( insn.itype == ARC_st && is_sp_based(insn, insn.Op2) ) + { + *src = 0; + *dst = 1; + return true; + } + return false; + } + + bool idaapi has_delay_slot(ea_t caller) override + { + insn_t insn; + return decode_insn(&insn, caller) != 0 + && pm.is_dslot(insn.ea+insn.size, true); + } +}; + +//------------------------------------------------------------------------- +void arc_t::use_arc_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs) +{ + arc_argtinfo_helper_t argtypes_helper(*this); + argtypes_helper.use_arg_tinfos(ea, fti, rargs); +} + +//---------------------------------------------------------------------- +// does the current instruction end a basic block? +bool arc_t::is_arc_basic_block_end( + const insn_t &insn, + bool call_insn_stops_block) +{ + // is this a delay slot of a branch? + if ( is_dslot(insn.ea, false) ) + return true; + + // do we flow into next instruction? + if ( !is_flow(get_flags(insn.ea+insn.size)) ) + return true; + + if ( is_call_insn(insn) ) + return call_insn_stops_block; + + // are there jump xrefs from here? + xrefblk_t xb; + bool has_jumps = false; + for ( bool ok=xb.first_from(insn.ea, XREF_FAR); ok && xb.iscode; ok=xb.next_from() ) + { + if ( xb.type == fl_JF || xb.type == fl_JN ) + { + has_jumps = true; + break; + } + } + + if ( has_jumps ) + { + // delayed jump does not end a basic block + return !has_dslot(insn); + } + return false; +} + +//---------------------------------------------------------------------- +void arc_t::del_insn_info(ea_t ea) +{ + // delete delay slot info + // NB: may not clobber cmd here! + nodeidx_t ndx = ea2node(ea); + helper.altdel(ndx, DSLOT_TAG); + if ( is_code(get_flags(ea)) ) + helper.altdel(ndx + get_item_size(ea), DSLOT_TAG); + del_callee(ea); + del_dxref(ea); +} + +//---------------------------------------------------------------------- +///< \param insn (const ::insn_t*) the instruction +///< \param state (int) autoanalysis phase +///< 0: creating functions +///< 1: creating chunks +///< \return probability 0..100 +int arc_t::arc_may_be_func(const insn_t &insn, int state) +{ + // don't add millicode thunks as chunks + if ( state == 1 && is_millicode(insn.ea) ) + return 100; + return 0; +} + +//====================================================================== +// millicode handling +//====================================================================== + +//---------------------------------------------------------------------- +void arc_t::rename_if_not_set(ea_t ea, const char *name) +{ + if ( renamed.find(ea) != renamed.end() ) + return; + + qstring curname; + if ( get_name(&curname, ea, GN_NOT_DUMMY) > 0 + && (is_uname(curname.c_str()) || curname.find(name) != qstring::npos) ) + return; + force_name(ea, name); +} + +//---------------------------------------------------------------------- +static int match_ac_pop_ld(const insn_t &insn) +{ + // ld rNN, [sp, #mm] + // mm = (NN-13)*4 + if ( ( insn.auxpref & aux_amask ) == aux_anone + && insn.Op1.type == o_reg + && insn.Op2.type == o_displ + && insn.Op2.reg == SP + && insn.Op2.membase == 0 + && ( insn.Op2.addr % 4 ) == 0 ) + { + int reg = insn.Op1.reg; + if ( reg == 13 + insn.Op2.addr / 4 ) + { + return reg; + } + } + // ld.ab r13, [sp, r13] + if ( ( insn.auxpref & aux_amask ) == aux_ab + && insn.Op1.is_reg(R13) + && insn.Op2.type == o_phrase + && insn.Op2.reg == SP + && insn.Op2.secreg == R13 ) + { + return 13; + } + // ld.ab blink, [sp, r12] + if ( ( insn.auxpref & aux_amask ) == aux_ab + && insn.Op1.is_reg(BLINK) + && insn.Op2.type == o_phrase + && insn.Op2.reg == SP + && insn.Op2.secreg == R12 ) + { + return BLINK; + } + return -1; + +} + +//---------------------------------------------------------------------- +bool arc_t::check_ac_pop_chain(int *regno, ea_t ea) +{ + // __ac_pop_26: + // ld gp, [sp, 0x34] + // __ac_pop_25: + // ld r25, [sp, 0x30] + // [..] + // __ac_pop_14: + // ld r14, [sp, 4] + // __ac_pop_13: + // ld.ab r13, [sp, r13] + // __ac_pop_blink: + // ld.ab blink, [sp, r12] + // j [blink] + insn_t insn; + bool ok = false; + if ( decode_insn(&insn, ea) > 0 ) + { + int reg = match_ac_pop_ld(insn); + if ( reg == BLINK ) + { + // j [blink] should follow + if ( decode_insn(&insn, insn.ea + insn.size) > 0 + && insn.itype == ARC_j + && insn.Op1.type == o_displ + && insn.Op1.reg == BLINK + && insn.Op1.addr == 0 ) + { + ok = true; + } + } + else if ( reg == R13 ) + { + int r2; + ok = check_ac_pop_chain(&r2, insn.ea + insn.size) && r2 == BLINK; + } + else if ( reg > R13 && reg <= R26 ) + { + // recurse to the lower addresses + int r2; + ok = check_ac_pop_chain(&r2, insn.ea + insn.size) && r2 == reg - 1; + } + if ( ok ) + { + qstring tmp; + if ( reg == BLINK ) + tmp = "__ac_pop_blink"; + else + tmp.sprnt("__ac_pop_%d", reg); + rename_if_not_set(ea, tmp.c_str()); + *regno = reg; + } + } + return ok; +} + +//---------------------------------------------------------------------- +static int match_ac_push_st(const insn_t &insn) +{ + // st.a rN, [sp,-4] + if ( insn.itype == ARC_st + && insn.auxpref == aux_a + && insn.Op2.type == o_displ + && insn.Op2.reg == SP + && insn.Op2.membase == 0 + && insn.Op2.addr == ea_t(-4) ) + { + return insn.Op1.reg; + } + return -1; +} + +//---------------------------------------------------------------------- +// __ac_mc_va: +// FC 1C 88 B1 st.a r6, [sp,-4] +// FC 1C 48 B1 st.a r5, [sp,-4] +// FC 1C 08 B1 st.a r4, [sp,-4] +// E1 C3 push r3 +// E1 C2 push r2 +// E1 C1 push r1 +// E1 C0 push r0 +// 07 C0 ld r0, [sp,0x1C] +// 1C 1C C0 31 st r7, [sp,0x1C] +// E1 C0 push r0 +// 01 C0 ld r0, [sp,4] | E0 7F j.d [blink] +// E0 7E j [blink] | 01 C0 ld r0, [sp,4] +static bool check_ac_mc_va(ea_t ea) +{ + // version with j.d + static const uchar sig_d[] = + { + 0xFC, 0x1C, 0x88, 0xB1, 0xFC, 0x1C, 0x48, 0xB1, 0xFC, 0x1C, + 0x08, 0xB1, 0xE1, 0xC3, 0xE1, 0xC2, 0xE1, 0xC1, 0xE1, 0xC0, + 0x07, 0xC0, 0x1C, 0x1C, 0xC0, 0x31, 0xE1, 0xC0, 0xE0, 0x7F, + 0x01, 0xC0 + }; + + // version with non-delayed j + static const uchar sig_nd[] = + { + 0xFC, 0x1C, 0x88, 0xB1, 0xFC, 0x1C, 0x48, 0xB1, 0xFC, 0x1C, + 0x08, 0xB1, 0xE1, 0xC3, 0xE1, 0xC2, 0xE1, 0xC1, 0xE1, 0xC0, + 0x07, 0xC0, 0x1C, 0x1C, 0xC0, 0x31, 0xE1, 0xC0, 0x01, 0xC0, + 0xE0, 0x7E + }; + + CASSERT(sizeof(sig_d) == sizeof(sig_nd)); + const int patlen = sizeof(sig_d); + uint8 buf[patlen]; + if ( get_bytes(buf, patlen, ea, GMB_READALL) == patlen ) + { + return memcmp(buf,sig_d, patlen) == 0 + || memcmp(buf,sig_nd, patlen) == 0; + } + return false; + +} +//---------------------------------------------------------------------- +static bool check_ac_push_chain(int *regno, ea_t ea) +{ + // __ac_push_13_to_26: + // st.a gp, [sp,-4] + // __ac_push_13_to_25: + // st.a r25, [sp,-4] + // [..] + // __ac_push_13_to_14: + // st.a r14, [sp,-4] + // __ac_push_13_to_13: + // j.d [blink] + // st.a r13, [sp,-4] + // VARIATION: + // __ac_push_13_to_13: + // st.a r13, [sp,-4] + // j [blink] + + insn_t insn; + bool ok = false; + int reg; + if ( decode_insn(&insn, ea) > 0 ) + { + if ( insn.itype == ARC_j + && insn.auxpref == aux_d + && insn.Op1.type == o_displ + && insn.Op1.reg == BLINK + && insn.Op1.addr == 0 ) + { + // j.d [blink] + // must be followed by st.a r13, [sp,-4] + if ( decode_insn(&insn, insn.ea + insn.size) > 0 + && match_ac_push_st(insn) == 13 ) + { + reg = 13; + ok = true; + } + } + else + { + // st.a rN, [sp,-4] + reg = match_ac_push_st(insn); + if ( reg == R13 ) + { + // j [blink] should follow + if ( decode_insn(&insn, insn.ea + insn.size) > 0 + && insn.itype == ARC_j + && insn.auxpref == 0 + && insn.Op1.type == o_displ + && insn.Op1.reg == BLINK + && insn.Op1.addr == 0 ) + { + ok = true; + } + } + if ( reg > R13 && reg <= R26 ) + { + // recurse to the lower addresses + int r2; + ok = check_ac_push_chain(&r2, insn.ea + insn.size) && r2 == reg - 1; + } + } + if ( ok ) + { + *regno = reg; + } + } + return ok; +} + +//---------------------------------------------------------------------- +bool arc_t::detect_millicode(qstring *mname, ea_t ea) +{ + // MetaWare arcompact millicode + // __ac_pop_13_to_26: + // mov r12, 4 + // __ac_pop_13_to_26v: + // mov r13, 0x38 + // b __ac_pop_26 + // [...] + // __ac_pop_13_to_13: + // mov r12, 4 + // __ac_pop_13_to_13v: + // mov r13, 4 + // b __ac_pop_13 + // __ac_pop_none: + // mov r12, 4 + // __ac_pop_nonev: + // b __ac_pop_blink + insn_t insn; + bool ok = false; + if ( decode_insn(&insn, ea) > 0 ) + { + if ( insn.itype == ARC_mov ) + { + if ( insn.Op1.is_reg(R13) && insn.Op2.type == o_imm && (insn.Op2.value % 4) == 0 ) + { + // mov r13, 0x38 + int regno = 12 + insn.Op2.value / 4; + if ( decode_insn(&insn, insn.ea + insn.size) > 0 && insn.itype == ARC_b && insn.Op1.type == o_near ) + { + // b __ac_pop_N + ea_t dest = insn.Op1.addr; + int regno2; + if ( check_ac_pop_chain(®no2, dest) && regno == regno2 ) + { + mname->sprnt("__ac_pop_13_to_%dv", regno); + ok = true; + } + } + } + else if ( insn.Op1.is_reg(R12) && insn.Op2.type == o_imm && insn.Op2.value == 4 ) + { + // mov r12, 4 + // check for fall through into __ac_pop_13_to_NNv + if ( detect_millicode(mname, insn.ea + insn.size) && mname->last() == 'v' ) + { + // erase the last 'v' + mname->resize(mname->length() - 1); + ok = true; + } + } + } + else if ( insn.itype == ARC_b && insn.Op1.type == o_near ) + { + // b __ac_pop_blink ? + int regno2; + if ( check_ac_pop_chain(®no2, insn.Op1.addr) && regno2 == BLINK ) + { + *mname = "__ac_pop_nonev"; + ok = true; + } + } + else if ( insn.itype == ARC_st ) + { + int reg; + if ( check_ac_push_chain(®, ea) ) + { + mname->sprnt("__ac_push_13_to_%d", reg); + ok = true; + } + else if ( check_ac_mc_va(ea) ) + { + *mname = "__ac_mc_va"; + ok = true; + } + } + } + if ( ok ) + { + rename_if_not_set(ea, mname->c_str()); + } + return ok; +} + +//---------------------------------------------------------------------- +static bool check_millicode_name(const qstring &name, ea_t ea, sval_t *spdelta) +{ + qstring cname; + if ( cleanup_name(&cname, ea, name.c_str(), CN_KEEP_TRAILING__DIGITS) ) + { + const char *p = cname.c_str(); + if ( streq(p, "ac_push_none") + || streq(p, "ac_pop_none") ) + { + *spdelta = 0; + return true; + } + else if ( streq(p, "ac_mc_va") ) + { + // pushes r0-r7 + *spdelta = -4*8; + return true; + } + else if ( streq(p, "ac_push_nonev") ) + { + // adjusts sp by r12 + *spdelta = BADADDR; + return true; + } + +#define SKIP_PREFIX(x) (strneq(p, x, strlen(x)) && (p+=strlen(x), true)) + if ( SKIP_PREFIX("ac_push_13_to_") ) + { + int reg = atoi(p); + if ( reg >= 13 && reg <= 26 ) + { + // pushes 13..reg + *spdelta = -4 * (reg-13+1); + return true; + } + } + else if ( SKIP_PREFIX("ac_pop_13_to_") ) + { + char *p2; + uint64 reg = strtoull(p, &p2, 10); + if ( reg >= 13 && reg <= 26 + && ( *p2 == '\0' || *p2 == 'v' || *p2 == '_' ) ) + { + // pops 13..reg + *spdelta = 4 * (reg - 12); + return true; + } + } + else if ( SKIP_PREFIX("prolog_save") ) + { + char *p2; + uint64 reg = strtoull(p, &p2, 10); + if ( ( reg == 0 || reg >= 13 && reg <= 26 ) + && ( *p2 == '\0' || strneq(p2, "_sub4", 5) || strneq(p2, "sp", 2) || strneq(p2, "sp_sub4", 7) ) ) + { + // different suffixes affect the fp value but sp remains unchanged + *spdelta = 0; + return true; + } + } + else if ( SKIP_PREFIX("epilog_load") + || SKIP_PREFIX("epilog_restore") ) + { + char *p2; + uint64 reg = strtoull(p, &p2, 10); + if ( ( reg == 0 || reg >= 13 && reg <= 26 ) + && ( *p2 == '\0' || strneq(p2, "_add4", 5) ) ) + { + // sp delta depends on r12 value + *spdelta = BADADDR; + return true; + } + } + else if ( SKIP_PREFIX("st_r13_to_r") ) + { + char *p2; + uint64 reg = strtoull(p, &p2, 10); + if ( reg >= 13 && reg <= 26 ) + { + *spdelta = 0; + return true; + } + } + else if ( SKIP_PREFIX("ld_r13_to_r") ) + { + char *p2; + uint64 reg = strtoull(p, &p2, 10); + if ( reg >= 13 && reg <= 26 ) + { + if ( *p2 == '\0' ) + { + *spdelta = 0; + return true; + } + else if ( strneq(p2, "_ret", 4) ) + { + // sp delta depends on r12 value + *spdelta = BADADDR; + return true; + } + } + } + } + return false; +} + +//---------------------------------------------------------------------- +bool arc_t::is_millicode(ea_t ea, sval_t *spdelta) +{ + // MetaWare arcompact names (N=13..26): + // __ac_push_13_to_N + // __ac_push_none + // __ac_pop_13_to_N + // __ac_pop_13_to_Nv + // __ac_pop_none + // __ac_pop_nonev + // __ac_mc_va + // MetaWare ARC4 names (N=0,13..26) + // __prolog_saveNsp_sub4 + // __prolog_saveN_sub4 + // __prolog_saveN + // __prolog_saveNsp + // __epilog_loadN + // __epilog_restoreN + // __epilog_loadN_add4 + // __epilog_restoreN_add4 + // __store_va + // GCC names (N=15..26) + // __st_r13_to_rN + // __ld_r13_to_rN + // N=14..26 + // __ld_r13_to_rN_ret + bool detected = false; + qstring name; + if ( get_name(&name, ea, GN_NOT_DUMMY) > 0 ) + { +CHECK_NAME: + sval_t tmp; + if ( check_millicode_name(name, ea, &tmp) ) + { + if ( spdelta != NULL ) + *spdelta = tmp; + return true; + } + if ( !detected ) + return false; + } + qstring mname; + if ( detect_millicode(&mname, ea) ) + { + if ( name.empty() ) + { + msg("%a: detected millicode thunk %s\n", ea, mname.c_str()); + force_name(ea, mname.c_str()); + } + else if ( is_uname(name.c_str()) && name.find(mname) == qstring::npos ) + { + msg("%a: detected millicode thunk %s but current name is %s, rename for better analysis\n", ea, mname.c_str(), name.c_str()); + } + name = mname; + detected = true; + goto CHECK_NAME; + } + return false; +} diff --git a/idasdk75/module/arc/ins.cpp b/idasdk76/module/arc/ins.cpp similarity index 100% rename from idasdk75/module/arc/ins.cpp rename to idasdk76/module/arc/ins.cpp diff --git a/idasdk76/module/arc/ins.hpp b/idasdk76/module/arc/ins.hpp new file mode 100644 index 0000000..85e6919 --- /dev/null +++ b/idasdk76/module/arc/ins.hpp @@ -0,0 +1,387 @@ + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INS_HPP +#define __INS_HPP + +extern instruc_t Instructions[]; + +enum nameNum +{ + + ARC_null = 0, // Unknown Operation + + ARC_ld, // Load + ARC_lr, // Load from auxiliary register + ARC_st, // Store + ARC_sr, // Store to auxiliary register + ARC_store_instructions = ARC_sr, + ARC_flag, // Set flags + ARC_asr, // Arithmetic shift right + ARC_lsr, // Logical shift right + ARC_sexb, // Sign extend byte + ARC_sexw, // Sign extend word + ARC_sexh = ARC_sexw, + ARC_extb, // Zero extend byte + ARC_extw, // Zero extend word + ARC_exth = ARC_extw, + ARC_ror, // Rotate right + ARC_rrc, // Rotate right through carry + ARC_b, // Branch + ARC_bl, // Branch and link + ARC_lp, // Zero-overhead loop setup + ARC_j, // Jump + ARC_jl, // Jump and link + ARC_add, // Add + ARC_adc, // Add with carry + ARC_sub, // Subtract + ARC_sbc, // Subtract with carry + ARC_and, // Logical bitwise AND + ARC_or, // Logical bitwise OR + ARC_bic, // Logical bitwise AND with invert + ARC_xor, // Logical bitwise exclusive-OR + + // pseudo instructions + ARC_mov, // Move + ARC_nop, // No operation + ARC_lsl, // Logical shift left + ARC_rlc, // Rotate left through carry + + // arc7 + ARC_brk, // Breakpoint + ARC_sleep, // Sleep until interrupt or restart + + // arc8 + ARC_swi, // Software interrupt + + // extra optional instrutions + ARC_asl, // Arithmetic shift left + ARC_mul64, // Signed 32x32 multiply + ARC_mulu64, // Unsigned 32x32 multiply + ARC_max, // Maximum of two signed integers + ARC_min, // Minimum of two signed integers + ARC_swap, // Exchange upper and lower 16 bits + ARC_norm, // Normalize (find-first-bit) + + // ARCompact instructions + ARC_bbit0, // Branch if bit cleared to 0 + ARC_bbit1, // Branch if bit set to 1 + ARC_br, // Branch on compare + ARC_pop, // Restore register value from stack + ARC_push, // Store register value on stack + + ARC_abs, // Absolute value + ARC_add1, // Add with left shift by 1 bit + ARC_add2, // Add with left shift by 2 bits + ARC_add3, // Add with left shift by 3 bits + ARC_bclr, // Clear specified bit (to 0) + ARC_bmsk, // Bit Mask + ARC_bset, // Set specified bit (to 1) + ARC_btst, // Test value of specified bit + ARC_bxor, // Bit XOR + ARC_cmp, // Compare + ARC_ex, // Atomic Exchange + ARC_mpy, // Signed 32x32 multiply (low) + ARC_mpyh, // Signed 32x32 multiply (high) + ARC_mpym = ARC_mpyh, + ARC_mpyhu, // Unsigned 32x32 multiply (high) + ARC_mpyhm = ARC_mpyhu, + ARC_mpyu, // Unsigned 32x32 multiply (low) + ARC_neg, // Negate + ARC_not, // Logical bit inversion + ARC_rcmp, // Reverse Compare + ARC_rsub, // Reverse Subtraction + ARC_rtie, // Return from Interrupt/Exception + ARC_sub1, // Subtract with left shift by 1 bit + ARC_sub2, // Subtract with left shift by 2 bits + ARC_sub3, // Subtract with left shift by 3 bits + ARC_sync, // Synchronize + ARC_trap, // Raise an exception + ARC_tst, // Test + ARC_unimp, // Unimplemented instruction + + ARC_abss, // Absolute and saturate + ARC_abssw, // Absolute and saturate of word + ARC_abssh = ARC_abssw, + ARC_adds, // Add and saturate + ARC_addsdw, // Add and saturate dual word + ARC_asls, // Arithmetic shift left and saturate + ARC_asrs, // Arithmetic shift right and saturate + ARC_divaw, // Division assist + ARC_negs, // Negate and saturate + ARC_negsw, // Negate and saturate of word + ARC_negsh = ARC_negsw, + ARC_normw, // Normalize to 16 bits + ARC_normh = ARC_normw, + ARC_rnd16, // Round to word + ARC_rndh = ARC_rnd16, + ARC_sat16, // Saturate to word + ARC_sath = ARC_sat16, + ARC_subs, // Subtract and saturate + ARC_subsdw, // Subtract and saturate dual word + + // mac d16 + ARC_muldw, + ARC_muludw, + ARC_mulrdw, + ARC_macdw, + ARC_macudw, + ARC_macrdw, + ARC_msubdw, + + // 32x16 MUL/MAC + ARC_mululw, + ARC_mullw, + ARC_mulflw, + ARC_maclw, + ARC_macflw, + ARC_machulw, + ARC_machlw, + ARC_machflw, + ARC_mulhlw, + ARC_mulhflw, + + // Major 6 compact insns + ARC_acm, + ARC_addqbs, + ARC_avgqb, + ARC_clamp, + ARC_daddh11, + ARC_daddh12, + ARC_daddh21, + ARC_daddh22, + ARC_dexcl1, + ARC_dexcl2, + ARC_dmulh11, + ARC_dmulh12, + ARC_dmulh21, + ARC_dmulh22, + ARC_dsubh11, + ARC_dsubh12, + ARC_dsubh21, + ARC_dsubh22, + ARC_drsubh11, + ARC_drsubh12, + ARC_drsubh21, + ARC_drsubh22, + ARC_fadd, + ARC_fsadd = ARC_fadd, + ARC_fmul, + ARC_fsmul = ARC_fmul, + ARC_fsub, + ARC_fssub = ARC_fsub, + ARC_fxtr, + ARC_iaddr, + ARC_mpyqb, + ARC_sfxtr, + ARC_pkqb, + ARC_upkqb, + ARC_xpkqb, + + // ARCv2 only major 4 instructions + ARC_mpyw, // Signed 16x16 multiply + ARC_mpyuw, // Unsigned 16x16 multiply + ARC_bi, // Branch indexed + ARC_bih, // Branch indexed half-word + ARC_ldi, // Load indexed + ARC_aex, // Exchange with auxiliary register + ARC_bmskn, // Bit mask negated + ARC_seteq, // Set if equal + ARC_setne, // Set if not equal + ARC_setlt, // Set if less than + ARC_setge, // Set if greater or equal + ARC_setlo, // Set if lower than + ARC_seths, // Set if higher or same + ARC_setle, // Set if less than or equal + ARC_setgt, // Set if greater than + + ARC_rol, // Rotate left + ARC_llock, // Load locked + ARC_scond, // Store conditional + + ARC_seti, // Set interrupt enable and priority level + ARC_clri, // Cler and get interrupt enable and priority level + + // ARCv2 compact prolog / epilog instructions + ARC_enter, // Function prologue sequence + ARC_leave, // Function epilogue sequence + + // ARCv2 32-bit extension major 5 DOP instructions + ARC_div, // Signed integer divsion + ARC_divu, // Unsigned integer divsion + ARC_rem, // Signed integer remainder + ARC_remu, // Unsigned integer remainder + ARC_asrsr, // Shift right rounding and saturating + ARC_valgn2h, // Two-way 16-bit vector align + ARC_setacc, // Set the accumulator + ARC_mac, // Signed 32x32 multiply accumulate + ARC_macu, // Unsigned 32x32 multiply accumulate + ARC_dmpyh, // Sum of dual signed 16x16 multiplication + ARC_dmpyhu, // Sum of dual unsigned 16x16 multiplication + ARC_dmach, // Dual signed 16x16 multiply accumulate + ARC_dmachu, // Dual unsigned 16x16 multiply accumulate + ARC_vadd2h, // Dual 16-bit addition + ARC_vadds2h, // Dual 16-bit saturating addition + ARC_vsub2h, // Dual 16-bit subtraction + ARC_vsubs2h, // Dual 16-bit saturating subtraction + ARC_vaddsub2h, // Dual 16-bit addition/subtraction + ARC_vaddsubs2h, // Dual 16-bit saturating addition/subtraction + ARC_vsubadd2h, // Dual 16-bit subtraction/addition + ARC_vsubadds2h, // Dual 16-bit saturating subtraction/addition + ARC_mpyd, // Signed 32x32 multiply (wide) + ARC_mpydu, // Unsigned 32x32 multiply (wide) + ARC_macd, // Signed 32x32 multiply accumulate (wide) + ARC_macdu, // Unsigned 32x32 multiply accumulate (wide) + ARC_vmpy2h, // Dual signed 16x16 multiply (wide) + ARC_vmpy2hf, // Dual 16x16 saturating fractional multiply + ARC_vmpy2hu, // Dual unsigned 16x16 multiply (wide) + ARC_vmpy2hfr, // Dual 16x16 saturating rounded fractional multiply + ARC_vmac2h, // Dual signed 16x16 multiply (wide) + ARC_vmac2hf, // Dual 16x16 saturating fractional multiply + ARC_vmac2hu, // Dual unsigned 16x16 multiply (wide) + ARC_vmac2hfr, // Dual 16x16 saturating rounded fractional multiply + ARC_vmpy2hwf, // Dual 16x16 saturating fractional multiply (wide) + ARC_vasl2h, // Dual 16-bit arithmetic shift left + ARC_vasls2h, // Dual 16-bit saturating arithmetic shift left + ARC_vasr2h, // Dual 16-bit arithmetic shift right + ARC_vasrs2h, // Dual 16-bit saturating arithmetic shift right + ARC_vlsr2h, // Dual 16-bit logical shift right + ARC_vasrsr2h, // Dual 16-bit saturating rounded arithmetic shift right + ARC_vadd4b, // Quad 8-bit addition + ARC_vmax2h, // Dual 16-bit maximum + ARC_vsub4b, // Quad 8-bit subtraction + ARC_vmin2h, // Dual 16-bit minimum + ARC_adcs, // Signed saturating addition with carry in + ARC_sbcs, // Signed saturating subtraction with carry in + ARC_dmpyhwf, // Fractional saturating sum of dual 16x16 signed fractional multiply + ARC_vpack2hl, // Compose lower 16-bits + ARC_vpack2hm, // Compose upper 16-bits + ARC_dmpyhf, // Saturating sum of dual 16x16 signed fractional multiply + ARC_dmpyhfr, // Saturating rounded sum of dual 16x16 signed fractional multiply + ARC_dmachf, // Saturating sum of dual 16x16 signed fractional multiply accumulate + ARC_dmachfr, // Saturating rounded sum of dual 16x16 signed fractional multiply accumulate + ARC_vperm, // Byte permutation with zero or sign extension + ARC_bspush, // Bitstream push + + // ARCv2 32-bit extension major 5 SOP instructions + ARC_swape, // Swap byte ordering + ARC_lsl16, // Logical shift left by 16 bits + ARC_lsr16, // Logical shift right by 16 bits + ARC_asr16, // Arithmetic shift right by 16 bits + ARC_asr8, // Arithmetic shift right by 8 bits + ARC_lsr8, // Logical shift right by 8 bits + ARC_lsl8, // Logical shift left by 8 bits + ARC_rol8, // Rotate left by 8 bits + ARC_ror8, // Rotate right by 8 bits + ARC_ffs, // Find first set bit + ARC_fls, // Find last set bit + + ARC_getacc, // Get accumulator + ARC_normacc, // Normalize accumulator + ARC_satf, // Saturate according to flags + ARC_vpack2hbl, // Pack lower bytes into lower 16 bits + ARC_vpack2hbm, // Pack upper bytes into upper 16 bits + ARC_vpack2hblf, // Pack upper bytes into lower 16 bits + ARC_vpack2hbmf, // Pack lower bytes into upper 16 bits + ARC_vext2bhlf, // Pack lower 2 bytes into upper byte of 16 bits each + ARC_vext2bhmf, // Pack upper 2 bytes into upper byte of 16 bits each + ARC_vrep2hl, // Repeat lower 16 bits + ARC_vrep2hm, // Repeat upper 16 bits + ARC_vext2bhl, // Pack lower 2 bytes into zero extended 16 bits + ARC_vext2bhm, // Pack upper 2 bytes into zero extended 16 bits + ARC_vsext2bhl, // Pack lower 2 bytes into sign extended 16 bits + ARC_vsext2bhm, // Pack upper 2 bytes into sign extended 16 bits + ARC_vabs2h, // Dual 16-bit absolute value + ARC_vabss2h, // Dual saturating 16-bit absolute value + ARC_vneg2h, // Dual 16-bit negation + ARC_vnegs2h, // Dual saturating 16-bit negation + ARC_vnorm2h, // Dual 16-bit normalization + ARC_bspeek, // Bitstream peek + ARC_bspop, // Bitstream pop + ARC_sqrt, // Integer square root + ARC_sqrtf, // Fractional square root + + // ARCv2 32-bit extension major 5 ZOP instructions + ARC_aslacc, // Arithmetic shift of accumulator + ARC_aslsacc, // Saturating arithmetic shift of accumulator + ARC_flagacc, // Copy accumulator flags to status32 register + ARC_modif, // Update address pointer + + // ARCv2 32-bit extension major 6 DOP instructions + ARC_cmpyhnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply + ARC_cmpyhfr, // Fractional 16+16 bit complex saturating rounded multiply + ARC_cmpychfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply + ARC_vmsub2hf, // Dual 16x16 saturating fractional multiply subtract + ARC_vmsub2hfr, // Dual 16x16 saturating rounded fractional multiply subtract + ARC_cmpychnfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply + ARC_cmachnfr, // Fractional 16+16 bit complex saturating rounded unshifted multiply accumulate + ARC_cmachfr, // Fractional 16+16 bit complex saturating rounded unshifted accumulate + ARC_cmacchnfr, // Fractional 16+16 bit complex saturating rounded conjugated multiply accumulate + ARC_cmacchfr, // Fractional 16+16 bit complex saturating rounded unshifted conjugated multiply accumulate + ARC_mpyf, // Signed 32-bit fractional saturating multiply + ARC_mpyfr, // Signed 32-bit fractional saturating rounded multiply + ARC_macf, // Signed 32-bit fractional saturating multiply accumulate + ARC_macfr, // Signed 32-bit fractional saturating rounded multiply accumulate + ARC_msubf, // Signed 32-bit fractional saturating multiply subtract + ARC_msubfr, // Signed 32-bit fractional saturating rounded multiply subtract + ARC_divf, // Signed 32-bit fractional division + ARC_vmac2hnfr, // Dual signed 16-bit fractional saturating rounded multiply accumulate + ARC_vmsub2hnfr, // Dual signed 16-bit fractional saturating rounded multiply subtract + ARC_mpydf, // Signed 32-bit fractional multiply (wide) + ARC_macdf, // Signed 32-bit fractional multiply accumulate (wide) + ARC_msubwhfl, // Signed 32 x 16 (lower) fractional saturating multiply subtract + ARC_msubdf, // Signed 32-bit fractional multiply subtract (wide) + ARC_dmpyhbl, // Dual 16x8 signed multiply with lower two bytes + ARC_dmpyhbm, // Dual 16x8 signed multiply with upper two bytes + ARC_dmachbl, // Dual 16x8 signed multiply accumulate with lower two bytes + ARC_dmachbm, // Dual 16x8 signed multiply accumulate with upper two bytes + ARC_msubwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply subtract + ARC_cmpyhfmr, // Fractional 16+16 bit complex x 16bit real (upper) saturating rounded multiply + ARC_cbflyhf0r, // Fractional 16+16 bit complex FFT butterfly, first half + ARC_mpywhl, // Signed 32 x 16 (lower) multiply + ARC_macwhl, // Signed 32 x 16 (lower) multiply accumulate + ARC_mpywhul, // Unsigned 32 x 16 (lower) multiply + ARC_macwhul, // Unsigned 32 x 16 (lower) multiply accumulate + ARC_mpywhfm, // Signed 32 x 16 (upper) fractional saturating multiply + ARC_mpywhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply + ARC_macwhfm, // Signed 32 x 16 (upper) fractional saturating multiply accumulate + ARC_macwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply accumulate + ARC_mpywhfl, // Signed 32 x 16 (lower) fractional saturating multiply + ARC_mpywhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply + ARC_macwhfl, // Signed 32 x 16 (lower) fractional saturating multiply accumulate + ARC_macwhflr, // Signed 32 x 16 (lower) fractional saturating rounded multiply accumulate + ARC_macwhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply accumulate + ARC_macwhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply accumulate + ARC_mpywhkl, // Signed 32 x 16 (lower) 16-bit shifted multiply + ARC_mpywhkul, // Unsigned 32 x 16 (lower) 16-bit shifted multiply + ARC_msubwhfm, // Signed 32 x 16 (upper) fractional saturating multiply subtract + ARC_msubwhfmr, // Signed 32 x 16 (upper) fractional saturating rounded multiply subtract + + // ARCv2 32-bit extension major 6 SOP instructions + ARC_cbflyhf1r, // Fractional 16+16 bit complex FFT butterfly, second half + + // ARCv2 FPU instructions + ARC_fscmp, // Single precision floating point compare + ARC_fscmpf, // Single precision floating point compare (IEEE 754 flag generation) + ARC_fsmadd, // Single precision floating point fused multiply add + ARC_fsmsub, // Single precision floating point fused multiply subtract + ARC_fsdiv, // Single precision floating point division + ARC_fcvt32, // Single precision floating point / integer conversion + ARC_fssqrt, // Single precision floating point square root + + // ARCv2 jump / execute indexed instructions + ARC_jli, // Jump and link indexed + ARC_ei, // Execute indexed + + ARC_kflag, // Set kernel flags + ARC_wevt, // Enter sleep state + + ARC_last, +}; + +#endif diff --git a/idasdk76/module/arc/makefile b/idasdk76/module/arc/makefile new file mode 100644 index 0000000..8ed8309 --- /dev/null +++ b/idasdk76/module/arc/makefile @@ -0,0 +1,57 @@ +PROC=arc +CONFIGS=arc.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp arc.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)jumptable.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp arc.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp arc.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp arc.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp arc.hpp ins.hpp reg.cpp diff --git a/idasdk76/module/arc/out.cpp b/idasdk76/module/arc/out.cpp new file mode 100644 index 0000000..29e8b84 --- /dev/null +++ b/idasdk76/module/arc/out.cpp @@ -0,0 +1,539 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su, ig@datarescue.com + * FIDO: 2:5020/209 + * + */ + +#include "arc.hpp" + +// generic condition codes +static const char *const ccode[] = +{ + "", ".z", ".nz", ".p", + ".n", ".c", ".nc", ".v", + ".nv", ".gt", ".ge", ".lt", + ".le", ".hi", ".ls", ".pnz", + ".ss", ".sc", ".c0x12", ".c0x13", + ".c0x14", ".c0x15", ".c0x16", ".c0x17", + ".c0x18", ".c0x19", ".c0x1A", ".c0x1B", + ".c0x1C", ".c0x1D", ".c0x1E", ".c0x1F", +}; + +// generic condition codes for ARCv2 +static const char *const ccode_v2[] = +{ + "", ".eq", ".ne", ".p", + ".n", ".c", ".nc", ".v", + ".nv", ".gt", ".ge", ".lt", + ".le", ".hi", ".ls", ".pnz", + ".c0x10", ".c0x11", ".c0x12", ".c0x13", + ".c0x14", ".c0x15", ".c0x16", ".c0x17", + ".c0x18", ".c0x19", ".c0x1A", ".c0x1B", + ".c0x1C", ".c0x1D", ".c0x1E", ".c0x1F", +}; + + +// condition codes for branches +static const char *const ccode_b[] = +{ + "", "eq", "ne", "pl", + "mi", "lo", "hs", "vs", + "vc", "gt", "ge", "lt", + "le", "hi", "ls", "pnz", + "ss", "sc", "c0x12", "c0x13", + "c0x14", "c0x15", "c0x16", "c0x17", + "c0x18", "c0x19", "c0x1A", "c0x1B", + "c0x1C", "c0x1D", "c0x1E", "c0x1F", +}; + +// condition codes for ARCv2 branches +static const char *const ccode_b_v2[] = +{ + "", "eq", "ne", "p", + "n", "lo", "hs", "v", + "nv", "gt", "ge", "lt", + "le", "hi", "ls", "pnz", + "c0x10", "c0x11", "c0x12", "c0x13", + "c0x14", "c0x15", "c0x16", "c0x17", + "c0x18", "c0x19", "c0x1A", "c0x1B", + "c0x1C", "c0x1D", "c0x1E", "c0x1F", +}; + + +/* jump delay slot codes */ +static const char ncode[][4] = { "", ".d", ".jd", ".d?" }; + +//---------------------------------------------------------------------- +class out_arc_t : public outctx_t +{ + out_arc_t(void) = delete; // not used + void set_gr_cmt(const char *cmt) { user_data = (void *)cmt; } + const char *get_gr_cmt(void) const { return (const char *)user_data; } +public: + void outreg(int rn); + + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); + void out_specreg(const ioports_t &table, const op_t &x); + void out_aux(const op_t &x) + { + arc_t &pm = *static_cast<arc_t *>(procmod); + out_specreg(pm.auxregs, x); + } +}; +CASSERT(sizeof(out_arc_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_arc_t) + +//---------------------------------------------------------------------- +void out_arc_t::outreg(int rn) +{ + const char *regname = (rn < ph.regs_num) ? ph.reg_names[rn] : "<bad register>"; + out_register(regname); +} + +//---------------------------------------------------------------------- +void out_arc_t::out_specreg(const ioports_t &table, const op_t &x) +{ + const ioport_t *reg = find_ioport(table, x.value); + if ( reg == NULL ) + { + out_symbol('['); + out_value(x, OOFS_IFSIGN | OOFW_32); + out_symbol(']'); + } + else + { + out_register(reg->name.c_str()); + if ( !reg->cmt.empty() && !has_cmt(F) ) + set_gr_cmt(reg->cmt.c_str()); + } +} + +//---------------------------------------------------------------------- +/* outputs an operand 'x' */ +bool out_arc_t::out_operand(const op_t & x) +{ + arc_t &pm = *static_cast<arc_t *>(procmod); + ea_t v; + switch ( x.type ) + { + case o_reg: + outreg(x.reg); + break; + + case o_phrase: + { + int hidden_base = is_hidden_base_reg(x.reg); + if ( hidden_base != -1 ) + out_symbol('['); + if ( hidden_base == 0 ) + { + outreg(x.reg); + out_symbol(','); + } + outreg(x.secreg); + if ( hidden_base != -1 ) + out_symbol(']'); + } + break; + + case o_imm: + // check for: LR <dest>, [aux] + // SR <src>, [aux] + if ( x.n == 1 + && !is_defarg(F, x.n) // don't use aux register if op type is set + && (insn.itype == ARC_lr || insn.itype == ARC_sr) ) + out_aux(x); + else + out_value(x, OOFS_IFSIGN | OOFW_IMM); + break; + + case o_mem: + { + ea_t ea = to_ea(insn.cs, x.addr); + if ( (insn.auxpref & aux_pcload) != 0 ) + { + // A little hack to make the output + // more readable... + op_t y; + if ( pm.copy_insn_optype(insn, x, ea, &y.value) ) + { + y.dtype = x.dtype; + y.flags = OF_SHOW; + out_symbol('='); + set_dlbind_opnd(); + ea_t insn_ea_sav = insn_ea; + flags_t savedF = F; + insn_ea = ea; // change context + F = get_flags(ea); + out_value(y, OOFS_IFSIGN|OOFW_IMM); + insn_ea = insn_ea_sav; // restore context + F = savedF; + break; + } + } + out_symbol('['); + if ( insn.itype != ARC_lr && insn.itype != ARC_sr ) + { + if ( !out_name_expr(x, ea, x.addr) ) + { + out_tagon(COLOR_ERROR); + out_btoa(uint32(x.addr), 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + } + else + { + out_btoa(uint32(x.addr), 16); + } + if ( x.immdisp != 0 ) + { + out_symbol('-'); + out_btoa(uint32(x.immdisp * get_scale_factor(insn)), 16); + out_symbol(','); + out_btoa(uint32(x.immdisp), 16); + } + out_symbol(']'); + } + break; + + case o_near: + v = to_ea(insn.cs, x.addr); + if ( !out_name_expr(x, v, x.addr) ) + { + out_value(x, OOF_ADDR|OOF_NUMBER|OOFS_NOSIGN|OOFW_32); + remember_problem(PR_NONAME, insn.ea); + break; + } + break; + + case o_displ: + { + // membase=0: [reg, #addr] + // membase=1: [#addr, reg] + int hidden_base = is_hidden_base_reg(x.reg); + if ( hidden_base != -1 ) + out_symbol('['); + if ( x.membase == 0 && hidden_base == 0 ) + outreg(x.reg); + if ( x.addr != 0 + || hidden_base != 0 + || is_off(F, x.n) + || is_stkvar(F, x.n) + || is_enum(F, x.n) + || is_stroff(F, x.n) ) + { + if ( x.membase == 0 && hidden_base == 0 ) + out_symbol(','); + out_value(x, OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED|OOFW_32); + if ( x.membase != 0 ) + out_symbol(','); + } + if ( x.membase != 0 ) + outreg(x.reg); + if ( hidden_base != -1 ) + out_symbol(']'); + } + break; + + case o_reglist: + { + out_symbol('{'); + bool need_comma = false; + int regs = x.reglist & REGLIST_REGS; + if ( regs > REGLISTR_MAX ) + { + out_tagon(COLOR_ERROR); + out_btoa(regs, 16); + out_tagoff(COLOR_ERROR); + need_comma = true; + } + else if ( regs > 0 ) + { + outreg(R13); + if ( regs > 1 ) + { + out_symbol('-'); + outreg(R13 + regs - 1); + } + need_comma = true; + } + if ( (x.reglist & REGLIST_FP) != 0 ) + { + if ( need_comma ) + out_symbol(','); + outreg(FP); + need_comma = true; + } + if ( (x.reglist & REGLIST_BLINK) != 0 ) + { + if ( need_comma ) + out_symbol(','); + outreg(BLINK); + need_comma = true; + } + if ( (x.reglist & REGLIST_PCL) != 0 ) + { + if ( need_comma ) + out_symbol(','); + outreg(PCL); + need_comma = true; + } + out_symbol('}'); + } + break; + + default: + out_symbol('?'); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +inline bool is_branch(const insn_t &insn) +{ + switch ( insn.itype ) + { + case ARC_b: + case ARC_lp: + case ARC_bl: + case ARC_j: + case ARC_jl: + case ARC_br: + case ARC_bbit0: + case ARC_bbit1: + return true; + } +#ifndef NDEBUG + // delay slot bits must be only set for branches + QASSERT(10184, !has_dslot(insn)); +#endif + return false; +} + +//---------------------------------------------------------------------- +void out_arc_t::out_proc_mnem(void) +{ + arc_t &pm = *static_cast<arc_t *>(procmod); + char postfix[MAXSTR]; + postfix[0] = '\0'; + if ( insn.itype == ARC_null ) + { + uint32 code = get_dword(insn.ea); + + int i = (code>>27)&31; + if ( i == 3 ) + { + int c = (code>>9)&63; + qsnprintf(postfix, sizeof(postfix), "ext%02X_%02X", i, c); + } + else + { + qsnprintf(postfix, sizeof(postfix), "ext%02X", i); + } + } + + /* if we have a load or store instruction, flags are used a bit different */ + if ( insn.itype <= ARC_store_instructions ) + { + switch ( insn.auxpref & aux_zmask ) + { + case 0: + break; + case aux_b: + qstrncat(postfix, "b", sizeof(postfix)); + break; + case aux_w: + qstrncat(postfix, pm.is_arcv2() ? "h" : "w", sizeof(postfix)); + break; + default: + qstrncat(postfix, "?", sizeof(postfix)); + break; + } + if ( (insn.auxpref & aux_s) != 0 ) + qstrncat(postfix, "_s", sizeof(postfix)); + if ( insn.auxpref & aux_x ) + qstrncat(postfix, ".x", sizeof(postfix)); + switch ( insn.auxpref & aux_amask ) + { + case 0: + break; + case aux_a: + qstrncat(postfix, ".a", sizeof(postfix)); + break; + case aux_as: + qstrncat(postfix, ".as", sizeof(postfix)); + break; + case aux_ab: + qstrncat(postfix, ".ab", sizeof(postfix)); + break; + default: + qstrncat(postfix, "?", sizeof(postfix)); + break; + } + if ( insn.auxpref & aux_di ) + qstrncat(postfix, ".di", sizeof(postfix)); + } + else + { + uint8 cond = insn.auxpref & aux_cmask; + if ( cond != cAL && is_branch(insn) ) + { + if ( pm.is_arcv2() ) + qstrncat(postfix, ccode_b_v2[cond], sizeof(postfix)); + else + qstrncat(postfix, ccode_b[cond], sizeof(postfix)); + } + + if ( (insn.auxpref & aux_s) != 0 ) + qstrncat(postfix, "_s", sizeof(postfix)); + + if ( cond != cAL && !is_branch(insn) ) + { + if ( pm.is_arcv2() ) + qstrncat(postfix, ccode_v2[cond], sizeof(postfix)); + else + qstrncat(postfix, ccode[cond], sizeof(postfix)); + } + } + if ( is_branch(insn) ) // delay slot code + qstrncat(postfix, ncode[(insn.auxpref >> 5) & 3], sizeof(postfix)); + else if ( (insn.auxpref & aux_f) != 0 ) + { + // for these load/store like instructions, the f bit is used for the .di + if ( insn.itype == ARC_ex + || insn.itype == ARC_llock + || insn.itype == ARC_scond ) + { + qstrncat(postfix, ".di", sizeof(postfix)); + } + else if ( insn.itype != ARC_flag // flag implicitly sets this bit + && insn.itype != ARC_rcmp ) // rcmp implicitly sets this bit + { + qstrncat(postfix, ".f", sizeof(postfix)); + } + } + + if ( pm.is_arcv2() && ( insn.auxpref & aux_bhint ) != 0 ) + { + // print static prediction hint + /* + from "Assembler Syntax for Static Branch Predictions" + The default static prediction, in the absence of any <.T> syntax, is always BTFN (Backwards Taken, Forwards Not Taken). + Therefore, a BRcc instruction always has the Y bit set to 0 by default, whereas a BBITn instruction always has the Y bit set to 1 + by default. + */ + bool backwards = insn.Op3.addr <= insn.ea; + const char *suf = NULL; + if ( insn.itype == ARC_br ) + suf = backwards ? ".t" : ".nt"; + else + suf = backwards ? ".nt" : ".t"; + qstrncat(postfix, suf, sizeof(postfix)); + } + + out_mnem(8, postfix); // output instruction mnemonics +} + +//---------------------------------------------------------------------- +void out_arc_t::out_insn(void) +{ + arc_t &pm = *static_cast<arc_t *>(procmod); + out_mnemonic(); + if ( insn.Op1.type != o_void ) + out_one_operand(0); // output the first operand + + for ( int i = 1; i < PROC_MAXOP; ++i ) + { + if ( insn.ops[i].type != o_void ) + { + if ( !(insn.ops[i].type == o_reg && insn.ops[i].regpair) ) + { + out_symbol(','); + out_char(' '); + } + out_one_operand(i); // output the current operand + } + } + + // output a character representation of the immediate values + // embedded in the instruction as comments + out_immchar_cmts(); + + // add comments for indirect calls or calculated data xrefs + nodeidx_t callee = pm.get_callee(insn.ea); + if ( callee == BADADDR ) + callee = pm.get_dxref(insn.ea); + if ( callee != BADADDR ) + set_comment_addr(callee & ~1); + const char *gr_cmt = get_gr_cmt(); + if ( gr_cmt != NULL ) + { + out_char(' '); + out_line(ash.cmnt, COLOR_AUTOCMT); + out_char(' '); + + out_line(gr_cmt, COLOR_AUTOCMT); + if ( ash.cmnt2 != NULL ) + { + out_char(' '); + out_line(ash.cmnt2, COLOR_AUTOCMT); + } + } + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +// generate start of the disassembly + +void idaapi arc_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX); +} + +//-------------------------------------------------------------------------- +// generate start of a segment +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Sarea) could be made const +void arc_t::arc_segstart(outctx_t &ctx, segment_t *Sarea) const +{ + qstring name; + get_visible_segm_name(&name, Sarea); + ctx.gen_printf(0, COLSTR(".section %s", SCOLOR_ASMDIR), name.c_str()); + if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) + { + adiff_t org = ctx.insn_ea - get_segm_base(Sarea); + + if ( org != 0 ) + { + char buf[MAX_NUMBUF]; + + btoa(buf, sizeof(buf), org); + ctx.gen_printf(0, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } + } +} + +//-------------------------------------------------------------------------- +// generate end of the disassembly +void idaapi arc_footer(outctx_t &ctx) +{ + ctx.gen_empty_line(); + + ctx.out_line(".end", COLOR_ASMDIR); + + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + ctx.out_line(" #"); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); +} diff --git a/idasdk76/module/arc/reg.cpp b/idasdk76/module/arc/reg.cpp new file mode 100644 index 0000000..106e864 --- /dev/null +++ b/idasdk76/module/arc/reg.cpp @@ -0,0 +1,908 @@ + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * + * E-mail: ig@estar.msk.su, ig@datarescue.com + * FIDO: 2:5020/209 + * + */ + +#include "arc.hpp" +int data_id; + +//-------------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // 0 .. 7 + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", // 8 .. 15 + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", // 16 .. 23 + "r24", "r25", "gp", "fp", "sp", "ilink1", "ilink2", "blink", // 23 .. 31 + + "r32", "r33", "r34", "r35", "r36", "r37", "r38", "r39", // 31 .. 39 + "r40", "r41", "r42", "r43", "r44", "r45", "r46", "r47", // 40 .. 47 + "r48", "r49", "r50", "r51", "r52", "r53", "r54", "r55", // 48 .. 55 + "r56", "mlo", "mmid", "mhi","lp_count", "r61", "<limm>", "pcl", // 56 .. 63 + // condition codes + "CF", "ZF", "NF", "VF", + + // registers used for indexed instructions + "next_pc", + "ldi_base", "jli_base", "ei_base", + + "gp_base", + + "cs", "ds" +}; + +static const uchar codeseq_arcompact[] = { 0xF1, 0xC0 }; // push blink +static const uchar codeseq_arctg4[] = { 0x04, 0x3E, 0x0E, 0x10 }; // st blink, [sp,4] + +static const bytes_t codestart_arcompact[] = +{ + { sizeof(codeseq_arcompact), codeseq_arcompact }, + { 0, NULL } +}; + +static const bytes_t codestart_arctg4[] = +{ + { sizeof(codeseq_arctg4), codeseq_arctg4 }, + { 0, NULL } +}; + +//---------------------------------------------------------------------- +void arc_t::set_codeseqs() const +{ + switch ( ptype ) + { + case prc_arc: + ph.codestart = codestart_arctg4; + break; + case prc_arcompact: + case prc_arcv2: + ph.codestart = codestart_arcompact; + break; + } +} + +//----------------------------------------------------------------------- +// new names for old instructions in ARCv2 +//lint -e{958} padding of 6 bytes needed to align member on a 8 byte boundary +struct instruc_alt_name_t +{ + uint16 itype; + const char *old_name; // ARCompact name + const char *new_name; // ARCv2 name +}; + +static const instruc_alt_name_t InstructionNamesARCv2[] = +{ + { ARC_mpyh, "mpyh", "mpym" }, + { ARC_mpyhu, "mpyhu", "mpymu" }, + { ARC_sexw, "sexw", "sexh" }, + { ARC_extw, "extw", "exth" }, + { ARC_sat16, "sat16", "sath" }, + { ARC_rnd16, "rnd16", "rndh" }, + { ARC_abssw, "abssw", "abssh" }, + { ARC_negsw, "negsw", "negsh" }, + { ARC_normw, "normw", "normh" }, + { ARC_fadd, "fadd", "fsadd" }, + { ARC_fmul, "fmul", "fsmul" }, + { ARC_fsub, "fsub", "fssub" }, +}; + +//---------------------------------------------------------------------- +arc_t::arc_t() +{ + memcpy(Instructions, ::Instructions, sizeof(Instructions)); + ph.instruc = Instructions; +} + +//---------------------------------------------------------------------- +// updates names in Instruction array to match the subtype +void arc_t::set_instruc_names() +{ + for ( int i = 0; i < qnumber(InstructionNamesARCv2); ++i ) + { + const instruc_alt_name_t &name = InstructionNamesARCv2[i]; + Instructions[name.itype].name = is_arcv2() ? name.new_name : name.old_name; + } +} + +//---------------------------------------------------------------------- +// updates affected global state after a ptype change +void arc_t::ptype_changed() +{ + set_codeseqs(); + set_instruc_names(); +} + +//-------------------------------------------------------------------------- +// handler for some IDB events +ssize_t idaapi pm_idb_listener_t::on_event(ssize_t notification_code, va_list va) +{ + switch ( notification_code ) + { + case idb_event::op_type_changed: + // An operand type (offset, hex, etc...) has been set or deleted + { + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + if ( n >= 0 && n < UA_MAXOP && is_code(get_flags(ea)) ) + { + insn_t insn; + decode_insn(&insn, ea); + op_t &x = insn.ops[n]; + if ( x.type == o_mem ) + { + ea = to_ea(insn.cs, x.addr); + pm.copy_insn_optype(insn, x, ea, NULL, true); + } + } + } + break; + } + return 0; +} + +//----------------------------------------------------------------------- +// ASMI +//----------------------------------------------------------------------- +static const asm_t gnuas = +{ + AS_COLON | AS_N2CHR | AS_1TEXT | ASH_HEXF3 | ASO_OCTF1 | ASB_BINF3 + |AS_ONEDUP | AS_ASCIIC, + 0, + "GNU assembler", + 0, + NULL, // no headers + ".org", // org directive + 0, // end directive + "#", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".long", // dword (4 bytes) + ".quad", // qword (8 bytes) + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // seg prefix + ".", // curent ip + NULL, // func_header + NULL, // func_footer + ".global", // public + NULL, // weak + ".extern", // extrn + ".comm", // comm + NULL, // get_type_name + ".align", // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + + +static const asm_t *const asms[] = { &gnuas, NULL }; + +static int idaapi choose_device(int, form_actions_t &); + +//----------------------------------------------------------------------- +const char *arc_t::set_idp_options( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded) +{ + if ( keyword == NULL ) + { + static const char form[] = + "HELP\n" + "ARC specific options\n" + "\n" + " Simplify instructions\n" + "\n" + " If this option is on, IDA will simplify instructions and replace\n" + " them by more natural pseudo-instructions or alternative mnemonics.\n" + " For example,\n" + "\n" + " sub.f 0, a, b\n" + "\n" + " will be replaced by\n" + "\n" + " cmp a, b\n" + "\n" + "\n" + " Inline constant pool loads\n" + "\n" + " If this option is on, IDA will use =label syntax for\n" + " pc-relative loads (commonly used to load constants)\n" + " For example,\n" + "\n" + " ld r1, [pcl,0x1C]\n" + " ...\n" + " .long 0x2051D1C8\n" + "\n" + " will be replaced by\n" + "\n" + " ld r1, =0x2051D1C8\n" + "\n" + "\n" + " Track register accesses\n" + "\n" + " This option tells IDA to track values loaded\n" + " into registers and use it to improve the listing.\n" + " For example,\n" + "\n" + " mov r13, 0x172C\n" + " ...\n" + " add r0, r13, 0x98\n" + "\n" + " will be replaced by\n" + "\n" + " add r0, r13, (dword_17C4 - 0x172C)\n" + "\n" + "\n" + "ENDHELP\n" + "ARC specific options\n" + "%*\n" + " <~S~implify instructions:C>\n" + " <~I~nline constant pool loads:C>\n" + " <Track ~r~egister accesses:C>>\n" + " <~C~hoose core variant:B:0::>\n" + "\n"; + CASSERT(sizeof(idpflags) == sizeof(ushort)); + ask_form(form, this, &idpflags, choose_device); + goto SAVE; + } + else + { + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + if ( strcmp(keyword, "ARC_SIMPLIFY") == 0 ) + { + setflag(idpflags, ARC_SIMPLIFY, *(int*)value != 0); + } + else if ( strcmp(keyword, "ARC_INLINECONST") == 0 ) + { + setflag(idpflags, ARC_INLINECONST, *(int*)value != 0); + } + else if ( strcmp(keyword, "ARC_TRACKREGS") == 0 ) + { + setflag(idpflags, ARC_TRACKREGS, *(int*)value != 0); + } + else + { + return IDPOPT_BADKEY; + } +SAVE: + if ( idb_loaded ) + save_idpflags(); + return IDPOPT_OK; + } +} + +//----------------------------------------------------------------------- +// The short and long names of the supported processors +#define FAMILY "Argonaut RISC Core:" + +static const char *const shnames[] = +{ + "arc", + "arcmpct", + "arcv2", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Argonaut RISC Core ARCtangent-A4", + "Argonaut RISC Core ARCompact", + "Argonaut RISC Core ARCv2", + NULL +}; + +//-------------------------------------------------------------------------- +// Opcodes of "return" instructions. This information will be used in 2 ways: +// - if an instruction has the "return" opcode, its autogenerated label +// will be "locret" rather than "loc". +// - IDA will use the first "return" opcode to create empty subroutines. + +static const bytes_t retcodes[] = +{ + { 0, NULL } // NULL terminated array +}; + +//-------------------------------------------------------------------------- +void arc_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) +{ + qstrncpy(buf, "arc.cfg", bufsize); +} + +//-------------------------------------------------------------------------- +const char *arc_iohandler_t::iocallback(const ioports_t &iop, const char *line) +{ + int len; + sval_t ea1; + char word[MAXSTR]; + word[MAXSTR-1] = '\0'; + CASSERT(MAXSTR == 1024); + if ( qsscanf(line, "aux %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) + { + const char *cmt = &line[len]; + cmt = skip_spaces(cmt); + ioport_t &port = pm.auxregs.push_back(); + port.address = ea1; + port.name = word; + if ( cmt[0] != '\0' ) + port.cmt = cmt; + return NULL; + } + return standard_callback(iop, line); +} + +//-------------------------------------------------------------------------- +bool arc_t::select_device(int resp_info) +{ + char cfgfile[QMAXFILE]; + arc_respect_info = resp_info; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( !choose_ioport_device(&ioh.device, cfgfile) ) + { + ioh.device = NONEPROC; + return false; + } + + if ( !ioh.display_infotype_dialog(IORESP_ALL, &arc_respect_info, cfgfile) ) + return false; + + ioh.set_device_name(ioh.device.c_str(), arc_respect_info); + return true; +} + + +//-------------------------------------------------------------------------- +static int idaapi choose_device(int, form_actions_t &fa) +{ + arc_t &pm = *(arc_t *)fa.get_ud(); + if ( pm.select_device(IORESP_ALL) ) + { + // load_symbols(IORESP_ALL); + // apply_symbols(); + } + return 0; +} + +//-------------------------------------------------------------------------- +static int idaapi arcso_gen_scaled_expr( + qstring * /*buf*/, + qstring *format, + ea_t /*ea*/, + int /*numop*/, + const refinfo_t &ri, + ea_t /*from*/, + adiff_t * /*opval*/, + ea_t * /*target*/, + ea_t * /*fullvalue*/, + int /*getn_flags*/) +{ + arc_t &pm = *GET_MODULE_DATA(arc_t); + int scale = ri.type() == pm.ref_arcsoh_id ? 2 : 4; + format->sprnt("%%s " COLSTR("/", SCOLOR_SYMBOL) " %i", scale); + return 4; // normal processing with custom format +} + +//-------------------------------------------------------------------------- +static bool idaapi arcso_calc_reference_data( + ea_t *target, + ea_t *base, + ea_t from, + const refinfo_t &ri, + adiff_t opval) +{ + arc_t &pm = *GET_MODULE_DATA(arc_t); + qnotused(from); + if ( ri.base == BADADDR || ri.is_subtract() ) + return false; + + int scale = ri.type() == pm.ref_arcsoh_id ? 2 : 4; + + *base = ri.base; + *target = ri.base + scale * opval; + + if ( ri.target != BADADDR && ri.target != *target ) + return false; + + return true; +} + +//-------------------------------------------------------------------------- +static const custom_refinfo_handler_t ref_arcsoh = +{ + sizeof(custom_refinfo_handler_t), + "ARCSOH", + "ARC 16-bit scaled offset", + RHF_TGTOPT, // properties: target be calculated using operand value + arcso_gen_scaled_expr, // gen_expr + arcso_calc_reference_data, // calc_reference_data + NULL, // get_format +}; + +//-------------------------------------------------------------------------- +static const custom_refinfo_handler_t ref_arcsol = +{ + sizeof(custom_refinfo_handler_t), + "ARCSOL", + "ARC 32-bit scaled offset", + RHF_TGTOPT, // properties: target be calculated using operand value + arcso_gen_scaled_expr, // gen_expr + arcso_calc_reference_data, // calc_reference_data + NULL, // get_format +}; + + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(arc_t)); + return 0; +} + +//---------------------------------------------------------------------- +void arc_t::load_from_idb() +{ + ptype = processor_subtype_t(ph.get_proc_index()); + ptype_changed(); + idpflags = (ushort)helper.altval(-1); + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +ssize_t idaapi arc_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(false); // Set little-endian mode of the IDA kernel + set_codeseqs(); + hook_event_listener(HT_IDB, &idb_listener, &LPH); + ref_arcsol_id = register_custom_refinfo(&ref_arcsol); + ref_arcsoh_id = register_custom_refinfo(&ref_arcsoh); + break; + + case processor_t::ev_term: + unregister_custom_refinfo(ref_arcsoh_id); + unregister_custom_refinfo(ref_arcsol_id); + unhook_event_listener(HT_IDB, &idb_listener); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + save_idpflags(); + set_codeseqs(); + if ( inf_like_binary() ) + { + // ask the user + select_device(IORESP_ALL); + } + else + { + // load the default AUX regs + ioh.set_device_name(is_a4() ? "ARC4": "ARCompact", IORESP_NONE); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + break; + + case processor_t::ev_newprc: + ptype = va_argi(va, processor_subtype_t); + // bool keep_cfg = va_argi(va, bool); + if ( uint(ptype) > prc_arcv2 ) //lint !e685 //-V547 is always false + { + code = -1; + break; + } + ptype_changed(); + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_is_call_insn: + // Is the instruction a "call"? + // ea_t ea - instruction address + // returns: 1-unknown, 0-no, 2-yes + { + const insn_t *insn = va_arg(va, insn_t *); + code = is_arc_call_insn(*insn) ? 1 : -1; + return code; + } + + case processor_t::ev_is_ret_insn: + { + const insn_t *insn = va_arg(va, insn_t *); +// bool strict = va_argi(va, bool); + code = is_arc_return_insn(*insn) ? 1 : -1; + return code; + } + + case processor_t::ev_is_basic_block_end: + { + const insn_t *insn = va_arg(va, insn_t *); + bool call_insn_stops_block = va_argi(va, bool); + return is_arc_basic_block_end(*insn, call_insn_stops_block) ? 1 : -1; + } + + case processor_t::ev_delay_slot_insn: + // Get delay slot instruction + // ea_t *ea in: instruction address in question, + // it may point to the instruction with a + // delay slot or to the delay slot + // instruction itself + // out: (if the answer is positive) + // if the delay slot contains valid insn: + // the address of the delay slot insn + // else: + // BADADDR (invalid insn, e.g. a branch) + // bool *bexec execute slot if jumping + // bool *fexec execute slot if not jumping + // returns: 1 positive answer + // <=0 ordinary insn + { + ea_t *ea = va_arg(va, ea_t *); + bool *bexec = va_arg(va, bool *); + bool *fexec = va_arg(va, bool *); + insn_t insn; + if ( decode_insn(&insn, *ea) == 0 ) + return -1; + if ( has_dslot(insn) ) + { + // the current instruction is a delayed slot instruction + // set EA to the address of the delay slot + *ea = insn.ea + insn.size; + // check the insn in the delay slot + // doc: "The Illegal Instruction Sequence type also occurs when + // any of the following instructions are attempted in an executed + // delay slot of a jump or branch: + // * Another jump or branch instruction (Bcc, BLcc, Jcc, JLcc) + // * Conditional loop instruction (LPcc) + // * Return from interrupt (RTIE) + // * Any instruction with long-immediate data as a source operand" + insn_t dslot_insn; + if ( decode_insn(&dslot_insn, *ea) == 0 + || is_arc_simple_branch(dslot_insn.itype) + || dslot_insn.itype == ARC_lp + || dslot_insn.itype == ARC_rtie + || dslot_insn.size > 4 + || dslot_insn.itype == ARC_br // ARCompact instructions + || dslot_insn.itype == ARC_bbit0 + || dslot_insn.itype == ARC_bbit1 ) + { + *ea = BADADDR; + } + } + else + { + if ( !is_flow(get_flags(*ea)) + || decode_prev_insn(&insn, *ea) == BADADDR + || !has_dslot(insn) ) + { + return -1; + } + // the previous instruction is a delayed slot instruction + // EA already has the address of the delay slot + } + *bexec = true; + *fexec = (insn.auxpref & aux_nmask) != aux_jd; + return 1; + } + + case processor_t::ev_is_switch: + { + switch_info_t *si = va_arg(va, switch_info_t *); + const insn_t *insn = va_arg(va, const insn_t *); + return arc_is_switch(si, *insn) ? 1 : -1; + } + + case processor_t::ev_may_be_func: + // can a function start here? + ///< \param insn (const ::insn_t*) the instruction + ///< \param state (int) autoanalysis phase + ///< 0: creating functions + ///< 1: creating chunks + ///< \return probability 0..100 + { + const insn_t *insn = va_arg(va, insn_t *); + int state = va_arg(va, int); + return arc_may_be_func(*insn, state); + } + + case processor_t::ev_undefine: + { + // an item is being undefined; delete data attached to it + ea_t ea = va_arg(va, ea_t); + del_insn_info(ea); + } + return 1; + +// +++ TYPE CALLBACKS + case processor_t::ev_decorate_name: + { + qstring *outbuf = va_arg(va, qstring *); + const char *name = va_arg(va, const char *); + bool mangle = va_argi(va, bool); + cm_t cc = va_argi(va, cm_t); + tinfo_t *type = va_arg(va, tinfo_t *); + return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; + } + + case processor_t::ev_max_ptr_size: + return 4; + + case processor_t::ev_calc_arglocs: + { + func_type_data_t *fti = va_arg(va, func_type_data_t *); + return calc_arc_arglocs(fti) ? 1 : -1; + } + + case processor_t::ev_calc_varglocs: + { + func_type_data_t *fti = va_arg(va, func_type_data_t *); + regobjs_t *regargs = va_arg(va, regobjs_t *); + /*relobj_t *stkargs =*/ va_arg(va, relobj_t *); + int nfixed = va_arg(va, int); + return calc_arc_varglocs(fti, regargs, nfixed) ? 1 : -1; + } + + case processor_t::ev_calc_retloc: + { + argloc_t *retloc = va_arg(va, argloc_t *); + const tinfo_t *type = va_arg(va, const tinfo_t *); + cm_t cc = va_argi(va, cm_t); + return calc_arc_retloc(retloc, *type, cc) ? 1 : -1; + } + + case processor_t::ev_use_stkarg_type: + return 0; + + case processor_t::ev_use_regarg_type: + { + int *used = va_arg(va, int *); + ea_t ea = va_arg(va, ea_t); + const funcargvec_t *rargs = va_arg(va, const funcargvec_t *); + *used = use_arc_regarg_type(ea, *rargs); + return 1; + } + + case processor_t::ev_use_arg_types: + { + ea_t ea = va_arg(va, ea_t); + func_type_data_t *fti = va_arg(va, func_type_data_t *); + funcargvec_t *rargs = va_arg(va, funcargvec_t *); + use_arc_arg_types(ea, fti, rargs); + return 1; + } + + case processor_t::ev_get_cc_regs: + { + callregs_t *callregs = va_arg(va, callregs_t *); + cm_t cc = va_argi(va, cm_t); + if ( cc == CM_CC_FASTCALL || cc == CM_CC_ELLIPSIS ) + { + const int *regs; + get_arc_fastcall_regs(®s); + callregs->set(ARGREGS_INDEPENDENT, regs, NULL); + return 1; + } + else if ( cc == CM_CC_THISCALL ) + { + callregs->reset(); + return 1; + } + } + break; + + case processor_t::ev_calc_cdecl_purged_bytes: + // calculate number of purged bytes after call + { + // ea_t ea = va_arg(va, ea_t); + return 0; + } + + case processor_t::ev_get_stkarg_offset: + // get offset from SP to the first stack argument + // args: none + // returns: the offset+2 + return 0; + + +// --- TYPE CALLBACKS + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + arc_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + arc_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + arc_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_calc_spdelta: + { + sval_t *spdelta = va_arg(va, sval_t *); + const insn_t *insn = va_arg(va, const insn_t *); + return arc_calc_spdelta(spdelta, *insn); + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = arc_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_ARC, // id + // flag + PR_USE32 // 32-bit processor + | PR_DEFSEG32 // create 32-bit segments by default + | PRN_HEX // Values are hexadecimal by default + | PR_TYPEINFO // Support the type system notifications + | PR_CNDINSNS // Has conditional instructions + | PR_DELAYED // Has delay slots + | PR_USE_ARG_TYPES // use ph.use_arg_types callback + | PR_RNAMESOK // register names can be reused for location names + | PR_SEGS // has segment registers + | PR_SGROTHER, // the segment registers don't contain the segment selectors. + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + RegNames, // Register names + qnumber(RegNames), // Number of registers + + LDI_BASE, // first + rVds, // last + 4, // size of a segment register + rVcs, rVds, + + codestart_arcompact, // code start sequences + retcodes, + + 0, ARC_last, + Instructions, // instruc + 0, // size of tbyte + {0}, // real width + 0, // Icode of a return instruction + NULL, // Micro virtual machine description +}; diff --git a/idasdk76/module/arm/arm.hpp b/idasdk76/module/arm/arm.hpp new file mode 100644 index 0000000..509d400 --- /dev/null +++ b/idasdk76/module/arm/arm.hpp @@ -0,0 +1,1745 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2002 by Ilfak Guilfanov, Datarescue. + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _ARM_HPP +#define _ARM_HPP + +#include "../idaidp.hpp" +#include <idd.hpp> +#include <dbg.hpp> +#include <segregs.hpp> +#include <typeinf.hpp> +#include <fixup.hpp> +#include "../calcrel_common.hpp" +struct arm_t; + +#define PROCMOD_NAME arm +#define PROCMOD_NODE_NAME " $arm" + +//------------------------------------------------------------------ +struct fptr_info_t +{ + ea_t addr; // address where the fp register is set + ushort reg; // frame pointer for current function (usually R11 or R7) +}; + +//--------------------------------- +// ARM insn.auxpref bits +#define aux_cond 0x0001 // set condition codes (S postfix is required) +#define aux_byte 0x0002 // byte transfer (B postfix is required) +#define aux_npriv 0x0004 // non-privileged transfer (T postfix is required) +#define aux_regsh 0x0008 // shift count is held in a register (see o_shreg) +#define aux_negoff 0x0010 // memory offset is negated in LDR,STR +#define aux_immcarry 0x0010 // carry flag is set to bit 31 of the immediate operand (see may_set_carry) +#define aux_wback 0x0020 // write back (! postfix is required) +#define aux_wbackldm 0x0040 // write back for LDM/STM (! postfix is required) +#define aux_postidx 0x0080 // post-indexed mode in LDR,STR +#define aux_ltrans 0x0100 // long transfer in LDC/STC (L postfix is required) +#define aux_wimm 0x0200 // thumb32 wide encoding of immediate constant (MOVW) +#define aux_sb 0x0400 // signed byte (SB postfix) +#define aux_sh 0x0800 // signed halfword (SH postfix) +#define aux_sw (aux_sb|aux_sh) // signed word (SW postfix) +#define aux_h 0x1000 // halfword (H postfix) +#define aux_x (aux_h|aux_byte) // doubleword (X postfix in A64) +#define aux_d aux_x // dual (D postfix in A32/T32) +#define aux_p 0x2000 // priviledged (P postfix) +#define aux_coproc 0x4000 // coprocessor instruction +#define aux_wide 0x8000 // wide (32-bit) thumb instruction (.W suffix) +#define aux_pac 0x10000 // Pointer Authentication Code instruction (see PAC_ flags) +#define aux_ns 0x20000 // non-secure branch (NS suffix) +#define aux_thumb32 0x40000 // (aux_wide is sometimes turned off for pretty-printing) + +// assembler flags +#define UAS_GNU 0x0001 // GNU assembler +#define UAS_LEGACY 0x0002 // Legacy (pre-UAL) assembler + +//--------------------------------- + +#define it_mask insnpref // mask field of IT-insn + +// data type of NEON and vector VFP instructions (for the suffix) +enum neon_datatype_t ENUM_SIZE(char) +{ + DT_NONE = 0, + DT_8, + DT_16, + DT_32, + DT_64, + DT_S8, + DT_S16, + DT_S32, + DT_S64, + DT_U8, + DT_U16, + DT_U32, + DT_U64, + DT_I8, + DT_I16, + DT_I32, + DT_I64, + DT_P8, + DT_P16, + DT_F16, + DT_F32, + DT_F64, + DT_P32, // unused? + DT_P64, // for 128-bit form of PMULL instruction +}; + +//------------------------------------------------------------------------- +// we will store the suffix in insnpref, since it's used only by the IT instruction +// if we need two suffixes (VCVTxx), we'll store the second one in Op1.specflag1 +inline void set_neon_suffix(insn_t &insn, neon_datatype_t suf1, neon_datatype_t suf2 = DT_NONE) +{ + if ( suf1 != DT_NONE ) + { + insn.insnpref = char(0x80 | suf1); + if ( suf2 != DT_NONE ) + insn.Op1.specflag1 = suf2; + } +} + +//------------------------------------------------------------------------- +inline neon_datatype_t get_neon_suffix(const insn_t &insn) +{ + if ( insn.insnpref & 0x80 ) + return neon_datatype_t(insn.insnpref & 0x7F); + else + return DT_NONE; +} + +//------------------------------------------------------------------------- +inline neon_datatype_t get_neon_suffix2(const insn_t &insn) +{ + return neon_datatype_t(insn.Op1.specflag1); +} + +//---------------------------------------------------------------------- +inline char dtype_from_dt(neon_datatype_t dt) +{ + switch ( dt ) + { + case DT_8: + case DT_S8: + case DT_U8: + case DT_I8: + case DT_P8: + return dt_byte; + case DT_16: + case DT_S16: + case DT_U16: + case DT_I16: + case DT_P16: + return dt_word; + case DT_32: + case DT_S32: + case DT_U32: + case DT_I32: + return dt_dword; + case DT_64: + case DT_S64: + case DT_U64: + case DT_I64: + case DT_NONE: + default: + return dt_qword; + case DT_F16: + return dt_half; + case DT_F32: + return dt_float; + case DT_F64: + return dt_double; + } +} + +#define PROC_MAXOP 5 +CASSERT(PROC_MAXOP <= UA_MAXOP); + +// Operand types: +#define o_shreg o_idpspec0 // Shifted register + // op.reg - register +#define shtype specflag2 // op.shtype - shift type +#define shreg(x) uchar(x.specflag1) // op.shreg - shift register +#define shcnt value // op.shcnt - shift counter + +#define ishtype specflag2 // o_imm - shift type +#define ishcnt specval // o_imm - shift counter + +#define secreg(x) uchar(x.specflag1) // o_phrase: the second register is here +#define ralign specflag3 // o_phrase, o_displ: NEON alignment (power-of-two bytes, i.e. 8*(1<<a)) + // minimal alignment is 16 (a==1) + +#define simd_sz specflag1 // o_reg: SIMD vector element size + // 0=scalar, 1=8 bits, 2=16 bits, 3=32 bits, 4=64 bits, 5=128 bits) + // number of lanes is derived from the vector size (dtype) +#define simd_idx specflag3 // o_reg: SIMD scalar index plus 1 (Vn.H[i]) + +// o_phrase: the second register is held in secreg (specflag1) +// the shift type is in shtype (specflag2) +// the shift counter is in shcnt (value) + +#define o_reglist o_idpspec1 // Register list (for LDM/STM) +#define reglist specval // The list is in op.specval +#define uforce specflag1 // PSR & force user bit (^ suffix) + +#define o_creglist o_idpspec2 // Coprocessor register list (for CDP) +#define CRd reg // +#define CRn specflag1 // +#define CRm specflag2 // + +#define o_creg o_idpspec3 // Coprocessor register (for LDC/STC) + +#define o_fpreglist o_idpspec4 // Floating point register list +#define fpregstart reg // First register +#define fpregcnt value // number of registers; 0: single register (NEON scalar) +#define fpregstep specflag2 // register spacing (0: {Dd, Dd+1,... }, 1: {Dd, Dd+2, ...} etc) +#define fpregindex specflag3 // NEON scalar index plus 1 (Dd[x]) +#define NOINDEX (char)254 // no index - all lanes (Dd[]) + +#define o_text o_idpspec5 // Arbitrary text stored in the operand + // structure starting at the 'value' field + // up to 16 bytes (with terminating zero) +#define o_cond o_idpspec5+1 // ARM condition as an operand + // condition is stored in 'value' field + +// The processor number of coprocessor instructions is held in cmd.Op1.specflag1: +#define procnum specflag1 + +// bits stored in specflag1 for APSR register +#define APSR_nzcv 0x01 +#define APSR_q 0x02 +#define APSR_g 0x04 +// for SPSR/CPSR +#define CPSR_c 0x01 +#define CPSR_x 0x02 +#define CPSR_s 0x04 +#define CPSR_f 0x08 +// for banked registers (R8-R12, SP, LR/ELR, SPSR), this flag is set +#define BANKED_MODE 0x80 // the mode is in low 5 bits (arm_mode_t) + +//------------------------------------------------------------------ +// Shift types: +enum shift_t +{ + LSL, // logical left LSL #0 - don't shift + LSR, // logical right LSR #0 means LSR #32 + ASR, // arithmetic right ASR #0 means ASR #32 + ROR, // rotate right ROR #0 means RRX + RRX, // extended rotate right + + // ARMv8 shifts + MSL, // masked shift left (ones are shifted in from the right) + + // extending register operations + UXTB, + UXTH, + UXTW, + UXTX, // alias for LSL + SXTB, + SXTH, + SXTW, + SXTX, +}; + +//------------------------------------------------------------------ +// Bit definitions. Just for convenience: +#define BIT0 0x00000001L +#define BIT1 0x00000002L +#define BIT2 0x00000004L +#define BIT3 0x00000008L +#define BIT4 0x00000010L +#define BIT5 0x00000020L +#define BIT6 0x00000040L +#define BIT7 0x00000080L +#define BIT8 0x00000100L +#define BIT9 0x00000200L +#define BIT10 0x00000400L +#define BIT11 0x00000800L +#define BIT12 0x00001000L +#define BIT13 0x00002000L +#define BIT14 0x00004000L +#define BIT15 0x00008000L +#define BIT16 0x00010000L +#define BIT17 0x00020000L +#define BIT18 0x00040000L +#define BIT19 0x00080000L +#define BIT20 0x00100000L +#define BIT21 0x00200000L +#define BIT22 0x00400000L +#define BIT23 0x00800000L +#define BIT24 0x01000000L +#define BIT25 0x02000000L +#define BIT26 0x04000000L +#define BIT27 0x08000000L +#define BIT28 0x10000000L +#define BIT29 0x20000000L +#define BIT30 0x40000000L +#define BIT31 0x80000000L + +#define HEX__(n) 0x##n##LU + +/* 8-bit conversion function */ +#define B8__(x) ((x&0x0000000FLU)?1:0) \ ++((x&0x000000F0LU)?2:0) \ ++((x&0x00000F00LU)?4:0) \ ++((x&0x0000F000LU)?8:0) \ ++((x&0x000F0000LU)?16:0) \ ++((x&0x00F00000LU)?32:0) \ ++((x&0x0F000000LU)?64:0) \ ++((x&0xF0000000LU)?128:0) + +// for upto 8-bit binary constants +#define B8(d) ((unsigned char)B8__(HEX__(d))) + +// for upto 16-bit binary constants, MSB first +#define B16(dmsb,dlsb) (((uint16)B8(dmsb)<< 8) | (uint16)B8(dlsb)) + +// for upto 32-bit binary constants, MSB first +#define B32(dmsb,db2,db3,dlsb) (((uint32)B8(dmsb)<<24) \ + | ((uint32)B8(db2 )<<16) \ + | ((uint32)B8(db3 )<< 8) \ + | (uint32)B8(dlsb)) + +// extract bit numbers high..low from val (inclusive, start from 0) +#define BITS(val, high, low) ( ((val)>>low) & ( (1<<(high-low+1))-1) ) + +// extract one bit +#define BIT(val, bit) ( ((val)>>bit) & 1 ) + +// return if mask matches the value +// mask has 1s for important bits and 0s for don't-care bits +// match has actual values for important bits +// e.g. : xx0x0 means mask is 11010 and match is aa0a0 +#define MATCH(value, mask, match) ( ((value) & (mask)) == (match) ) + +//------------------------------------------------------------------ +// The condition code of instruction will be kept in cmd.segpref: + +#define cond segpref + +//--------------------------------- +// PAC (Pointer Authentication Code) instruction suffix flags are stored in insnpref +// NB: we have only 8 bits! +#define pac_flags insnpref + +// bits 0..2: key used +// The Pointer Authentication specification defines five keys. Four +// keys for PAC* and AUT* instructions (combination of instruction/data +// and A/B keys), and a fifth key for use with the general purpose PACGA +// instruction +#define PAC_KEYMASK 0x07 +#define PAC_KEY_IA 0x00 // Instruction address, using key A +#define PAC_KEY_IB 0x01 // Instruction address, using key B +#define PAC_KEY_DA 0x02 // Data address, using key A +#define PAC_KEY_DB 0x03 // Data address, using key B +#define PAC_KEY_GA 0x04 // Generic key (PACGA) +#define PAC_KEY_RES5 0x05 // reserved for future +#define PAC_KEY_RES6 0x06 // reserved for future +// bits 3..4: address used +#define PAC_ADRMASK (3<<3) // address is: +#define PAC_ADR_GPR (0<<3) // in general-purpose register that is specified by <Xd> +#define PAC_ADR_X17 (1<<3) // in X17 +#define PAC_ADR_X30 (2<<3) // in X30(XLR) +// bits 5..7: modifier used +#define PAC_MODMASK (3<<5) // modifier is : +#define PAC_MOD_GPR (0<<5) // in general-purpose register or stack pointer that is specified by <Xn|SP> +#define PAC_MOD_ZR (1<<5) // zero +#define PAC_MOD_X16 (2<<5) // in X16 +#define PAC_MOD_SP (3<<5) // in SP + +//---------------------------------------------------------------------- +// build a suffix for a PAC instruction +static inline bool get_pac_suffix(qstring *suf, const insn_t &insn) +{ +// + int key = insn.pac_flags & PAC_KEYMASK; + const char *id = NULL, *ab = NULL; + switch ( key ) + { + case PAC_KEY_IA: id= "I"; ab="A"; break; + case PAC_KEY_IB: id= "I"; ab="B"; break; + case PAC_KEY_DA: id= "D"; ab="A"; break; + case PAC_KEY_DB: id= "D"; ab="B"; break; + case PAC_KEY_GA: id= "G"; ab="A"; break; + default: return false; + } + int adr = insn.pac_flags & PAC_ADRMASK; + int mod = insn.pac_flags & PAC_MODMASK; + bool pre_ab = adr == PAC_ADR_X30 || adr == PAC_ADR_X17; + switch ( insn.itype ) + { + case ARM_pac: + case ARM_aut: + suf->append(id); + if ( pre_ab ) + suf->append(ab); + + if ( adr == PAC_ADR_X17 ) + suf->append("17"); + else if ( adr != PAC_ADR_X30 && adr != PAC_ADR_GPR ) + return false; + + if ( mod == PAC_MOD_SP ) + suf->append("SP"); + else if ( mod == PAC_MOD_ZR ) + suf->append("Z"); + else if ( mod == PAC_MOD_X16 ) + suf->append("16"); + else if ( mod != PAC_MOD_GPR ) + return false; + if ( !pre_ab ) + suf->append(ab); + break; + case ARM_xpac: + if ( adr == PAC_ADR_X30 ) + suf->append("LR");// XPACLRI + else if ( adr != PAC_ADR_GPR ) + return 0; + suf->append(id); // XPACD, XPACI, + break; + default: + // AA, AB, AAZ, ABZ + suf->append("A"); + suf->append(ab); + if ( mod == PAC_MOD_ZR ) + suf->append("Z"); + break; + } + return true; +} + +//------------------------------------------------------------------ +// is insn PACIASP or PACIBSP ? +static inline bool is_paci_sp(const insn_t &insn) +{ + if ( insn.itype != ARM_pac ) + return false; + int adr = insn.pac_flags & PAC_ADRMASK; + int mod = insn.pac_flags & PAC_MODMASK; + int key = insn.pac_flags & PAC_KEYMASK; + if ( adr != PAC_ADR_X30 + || mod != PAC_MOD_SP ) + return false; + return key == PAC_KEY_IA || key == PAC_KEY_IB; +} + + +//------------------------------------------------------------------ +enum RegNo +{ + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, R11, R12, R13, R14, R15, + CPSR, CPSR_flg, + SPSR, SPSR_flg, + T, rVcs, rVds, // virtual registers for code and data segments + Racc0, // Intel xScale coprocessor accumulator + FPSID, FPSCR, FPEXC, // VFP system registers + FPINST, FPINST2, MVFR0, MVFR1, + // msr system registers + SYSM_APSR, + SYSM_IAPSR, + SYSM_EAPSR, + SYSM_XPSR, + SYSM_IPSR, + SYSM_EPSR, + SYSM_IEPSR, + SYSM_MSP, + SYSM_PSP, + SYSM_PRIMASK, + SYSM_BASEPRI, + SYSM_BASEPRI_MAX, + SYSM_FAULTMASK, + SYSM_CONTROL, + Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, + Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, + D0, D1, D2, D3, D4, D5, D6, D7, + D8, D9, D10, D11, D12, D13, D14, D15, + D16, D17, D18, D19, D20, D21, D22, D23, + D24, D25, D26, D27, D28, D29, D30, D31, + S0, S1, S2, S3, S4, S5, S6, S7, + S8, S9, S10, S11, S12, S13, S14, S15, + S16, S17, S18, S19, S20, S21, S22, S23, + S24, S25, S26, S27, S28, S29, S30, S31, + FIRST_FPREG=Q0, + LAST_FPREG=S31, + CF, ZF, NF, VF, + + // AArch64 registers + // general-purpose registers + X0, X1, X2, X3, X4, X5, X6, X7, + X8, X9, X10, X11, X12, X13, X14, X15, + X16, X17, X18, X19, X20, X21, X22, X23, + X24, X25, X26, X27, X28, + X29, XFP = X29, // frame pointer + X30, XLR = X30, // link register + + XZR, // zero register (special case of GPR=31) + + XSP, // stack pointer (special case of GPR=31) + + XPC, // PC (not available as actual register) + + // 128-bit SIMD registers + V0, V1, V2, V3, V4, V5, V6, V7, + V8, V9, V10, V11, V12, V13, V14, V15, + V16, V17, V18, V19, V20, V21, V22, V23, + V24, V25, V26, V27, V28, V29, V30, V31, + + ARM_MAXREG, // must be the last entry +}; + +// we use specflag1 to store register values +// so they must fit into a byte +CASSERT(ARM_MAXREG < 0x100); + +extern const char *const arm_regnames[]; + +//------------------------------------------------------------------ +// r0 * argument word/integer result +// r1-r3 argument word +// +// r4-r8 S register variable +// r9 S (rfp) register variable (real frame pointer) +// +// r10 F S (sl) stack limit (used by -mapcs-stack-check) +// r11 F S (fp) argument pointer +// r12 (ip) temp workspace +// r13 F S (sp) lower end of current stack frame +// r14 (lr) link address/workspace +// r15 F (pc) program counter +// +// f0 floating point result +// f1-f3 floating point scratch +// +// f4-f7 S floating point variable + +#define PC R15 +#define LR R14 +#define SP R13 +#define FP R11 +#define FP2 R7 // in thumb mode + +inline int getreg(const op_t &x) +{ + return x.type == o_reg + || x.type == o_shreg + && x.shtype == LSL + && x.shcnt == 0 ? x.reg : -1; +} + +inline bool isreg(const op_t &x, int reg) +{ + return getreg(x) == reg; +} + +// is it simply [Rx, Ry]? +// no shift, no negation, no post-index, no writeback +inline bool is_simple_phrase(const insn_t &insn, const op_t &x) +{ + return x.type == o_phrase + && x.shtype == LSL + && x.shcnt == 0 + && (insn.auxpref & (aux_negoff|aux_postidx|aux_wback)) == 0; +} + +inline bool issp(const op_t &x) { return isreg(x, SP) || isreg(x, XSP); } +inline bool issp(int reg) { return reg == SP || reg == XSP; } + +#define is_a64reg(reg) ((reg) >= X0 && (reg) < ARM_MAXREG) + +inline bool is_gr(int reg) +{ + return reg >= R0 && reg <= R14 + || reg >= X0 && reg <= X30; +} + +inline bool is_thread_id_sysreg(const insn_t &insn, int op) +{ + // assert: insn.ops[op+0].type == o_imm + // && insn.ops[op+1].type == o_creg + // && insn.ops[op+2].type == o_creg + // && insn.ops[op+3].type == o_imm + // TPIDR_EL0 + return insn.ops[op+0].value == 3 + && insn.ops[op+1].reg == 13 + && insn.ops[op+2].reg == 0 + && insn.ops[op+3].value == 2; +} + +// is callee-saved (preserved) register? (according to Procedure Call Standard) +/* Procedure Call Standard for the ARM Architecture: +5.1.1. A subroutine must preserve the contents of the registers r4-r8, +r10, r11 and SP (and r9 in PCS variants that designate r9 as v6). +Procedure Call Standard for the ARM 64-bit Architecture: +5.1.1. A subroutine invocation must preserve the contents of the +registers r19-r29 and SP. +*/ +inline bool is_callee_saved_gr(int reg) +{ + return reg >= R4 && reg <= R11 + || reg >= X19 && reg <= X29; +} +/* Procedure Call Standard for the ARM Architecture: +5.1.2.1 Registers s16-s31 (d8-d15, q4-q7) must be preserved across +subroutine calls; registers s0-s15 (d0-d7, q0-q3) do not need to be +preserved (and can be used for passing arguments or returning results in +standard procedure-call variants) +Procedure Call Standard for the ARM 64-bit Architecture: +5.1.2. Registers v8-v15 must be preserved by a callee across subroutine +calls. +*/ +inline bool is_callee_saved_vr(int reg) +{ + return reg >= S16 && reg <= S31 + || reg >= D8 && reg <= D15 + || reg >= Q4 && reg <= Q7 + || reg >= V8 && reg <= V15; +} + +//---------------------------------------------------------------------- +// get full value of the immediate operand +// (performing optional shift operator) +inline uval_t get_immfull(const op_t &x) +{ + // FIXME support other types of shift + return x.type != o_imm ? 0 + : x.value == 0 ? 0 + : x.ishcnt == 0 ? x.value + : x.ishtype == LSL ? x.value << x.ishcnt + : x.ishtype == MSL ? ((x.value + 1) << x.ishcnt) - 1 + : 0; +} +//---------------------------------------------------------------------- +// check if 'reg' is present in 'reglist' (only ARM32 GPRs supported!) +inline bool in_reglist(uint32 reglist, int reg) +{ + return (reg <= R15) && (reglist & (1u << reg)) != 0; +} +//---------------------------------------------------------------------- +// calculate the total number of bytes represented by a register list +inline uval_t calc_reglist_size(uint32 reglist) +{ + return uval_t(4) * bitcount(reglist & 0xFFFF); +} + +//---------------------------------------------------------------------- +// find out pre- or post-indexed addressing mode of given operand <op>; +// if <delta> arg is specified than we check o_displ operand only and +// return register offset in <delta>; +// returns base register or -1 +inline int get_pre_post_delta(const insn_t &insn, const op_t &op, sval_t *delta = NULL) +{ + if ( (insn.auxpref & (aux_wback | aux_postidx)) != 0 + && (op.type == o_displ && op.addr != 0 + || op.type == o_phrase && delta == NULL) ) + { + if ( delta != NULL ) + *delta = op.addr; + return op.reg; + } + return -1; +} + +//------------------------------------------------------------------ +// PSR format: +// bit name description +// 0 M0 M4..M0 are mode bits: +// 1 M1 10000 User +// 2 M2 10001 FIQ (fast interrupt request) +// 3 M3 10010 IRQ (interrupt request) +// 4 M4 10011 Supervisor +// 10110 Monitor (security extensions) +// 10111 Abort +// 11010 Hyp (Hypervisor; virtualization extensions) +// 11011 Undefined +// 11111 System +// 5 T Thumb state +// 6 F FIQ disable +// 7 I IRQ disable +// 8 A Asynchronous abort disable +// 9 E Endianness (0=little endian, 1=big endian) +// 10 IT2 IT7...IT0 If-Then execution state bits (ITSTATE) +// 11 IT3 +// 12 IT4 +// 13 IT5 +// 14 IT6 +// 15 IT7 +// 16 GE0 GE3..GE0 Greater than or Equal flags (for SIMD instructions) +// 17 GE1 +// 18 GE2 +// 19 GE3 +// 24 J Jazelle state +// 25 IT0 +// 26 IT1 +// 27 Q Cumulative saturation flag +// 28 V Overflow +// 29 C Carry/Borrow/Extend +// 30 Z Zero +// 31 N Negative/Less Than + +enum arm_mode_t +{ + M_usr = B8(10000), + M_fiq = B8(10001), + M_irq = B8(10010), + M_svc = B8(10011), + M_mon = B8(10110), + M_abt = B8(10111), + M_hyp = B8(11010), + M_und = B8(11011), + M_sys = B8(11111), +}; + +//------------------------------------------------------------------ +// Vector summary: +// Address Exception Mode on Entry +// ------- --------- ------------- +// 0000 Reset Supervisor +// 0004 Undefined instruction Undefined +// 0008 Software interrupt Supervisor +// 000C Abort (prefetch) Abort +// 0010 Abort (data) Abort +// 0014 Hypervisor trap Hyp +// 0018 IRQ IRQ +// 001C FIQ FIQ + +//------------------------------------------------------------------ +// Condition codes: +enum cond_t +{ + cEQ, // 0000 Z Equal + cNE, // 0001 !Z Not equal + cCS, // 0010 C Unsigned higher or same + cCC, // 0011 !C Unsigned lower + cMI, // 0100 N Negative + cPL, // 0101 !N Positive or Zero + cVS, // 0110 V Overflow + cVC, // 0111 !V No overflow + cHI, // 1000 C & !Z Unsigned higher + cLS, // 1001 !C | Z Unsigned lower or same + cGE, // 1010 (N & V) | (!N & !V) Greater or equal + cLT, // 1011 (N & !V) | (!N & V) Less than + cGT, // 1100 !Z & ((N & V)|(!N & !V)) Greater than + cLE, // 1101 Z | (N & !V) | (!N & V) Less than or equal + cAL, // 1110 Always + cNV, // 1111 Never + cLAST +}; +inline cond_t get_cond(const insn_t &insn) +{ + return cond_t(insn.cond); +} +inline bool has_cond(const insn_t &insn) +{ + return insn.cond != cAL; +} +inline bool is_negated_cond(cond_t cond) +{ + return (cond & 1) != 0; +} +inline cond_t invert_cond(cond_t cond) +{ + if ( cond < cLAST ) + return cond_t(cond ^ 1); + return cLAST; +} +inline cond_t get_op_cond(const op_t &x) +{ + // assert: x.type == o_cond + return cond_t(x.value & 0xF); +} + +//---------------------------------------------------------------------- +// see ARMExpandImm_C/ThumbExpandImm_C in ARM ARM +inline bool may_set_carry(ushort itype) +{ + switch ( itype ) + { + case ARM_and: + case ARM_bic: + case ARM_eor: + case ARM_mov: + case ARM_mvn: + case ARM_orn: + case ARM_orr: + case ARM_teq: + case ARM_tst: + return true; + } + return false; +} + +//---------------------------------------------------------------------- +// if true, then ASPR.C is set to bit 31 of the immediate constant +inline bool imm_sets_carry(const insn_t &insn) +{ + switch ( insn.itype ) + { + case ARM_and: + case ARM_bic: + case ARM_eor: + case ARM_mov: + case ARM_mvn: + case ARM_orn: + case ARM_orr: + // flags are updated if S suffix is used + return (insn.auxpref & (aux_immcarry|aux_cond)) == (aux_immcarry|aux_cond); + case ARM_teq: + case ARM_tst: + // these two always update flags + return (insn.auxpref & aux_immcarry) != 0; + } + return false; +} + + +//---------------------------------------------------------------------- +struct pushreg_t +{ + ea_t ea; // instruction ea + uval_t off; // offset from the frame top (sp delta) + uval_t width; // size of allocated area in bytes + int reg; // register number (-1 means stack space allocation) + DECLARE_COMPARISONS(pushreg_t); +}; +typedef qvector<pushreg_t> pushregs_t; + +struct pushinfo_t : public pushregs_t +{ + enum { PUSHINFO_VERSION = 2 }; + uint32 flags; +#define APSI_VARARG 0x01 // is vararg function? +#define APSI_FIRST_VARG_MASK 0x06 // index of the first register in push {rx..r3} +#define APSI_HAVE_SSIZE 0x08 // pushinfo_t structure contains its own size (field 'cb') +#define APSI_OFFSET_WO_DELTA 0x10 // do not use delta-coding for <off> + inline int get_first_vararg_reg(void) { return (flags & APSI_FIRST_VARG_MASK) >> 1; } + uval_t savedregs; // size of the 'saved regs' area + eavec_t prolog_insns; // additional prolog instruction addresses + // (in addition to instructions from pushregs_t) + uval_t fpd; // frame pointer delta + + int cb; // size of this structure (it would be better if + // this field was the first one) + + // vararg info + uval_t gr_top; // offset from the frame top general registers + // vararg save area + uval_t vr_top; // offset from the frame top FP/SIMD registers + // vararg save area + uval_t gr_width; // size of general registers vararg save area + uval_t vr_width; // size of FP/SIMD registers vararg save area + + pushinfo_t(void) + : flags(APSI_HAVE_SSIZE), + savedregs(0), fpd(0), + cb(sizeof(pushinfo_t)), + gr_top(0), vr_top(0), gr_width(0), vr_width(0) + {} + DECLARE_COMPARISONS(pushinfo_t); + + void serialize(bytevec_t *packed, ea_t ea) const; + bool deserialize(memory_deserializer_t *mmdsr, ea_t ea); + + void save_to_idb(arm_t &pm, ea_t ea) const; + bool restore_from_idb(arm_t &pm, ea_t ea); + + void mark_prolog_insns(arm_t &pm); +}; + +//---------------------------------------------------------------------- +enum arm_base_arch_t +{ + // values taken from ARM IHI 0045C, Tag_CPU_arch + arch_ARM_old = 0, // Pre-v4 + arch_ARMv4 = 1, // e.g. SA110 + arch_ARMv4T = 2, // e.g. ARM7TDMI + arch_ARMv5T = 3, // e.g. ARM9TDMI + arch_ARMv5TE = 4, // e.g. ARM946E-S + arch_ARMv5TEJ = 5, // e.g. ARM926EJ-S + arch_ARMv6 = 6, // e.g. ARM1136J-S + arch_ARMv6KZ = 7, // e.g. ARM1176JZ-S + arch_ARMv6T2 = 8, // e.g. ARM1156T2F-S + arch_ARMv6K = 9, // e.g. ARM1136J-S + arch_ARMv7 = 10, // e.g. Cortex A8, Cortex M3 + arch_ARMv6M = 11, // e.g. Cortex M1 + arch_ARMv6SM = 12, // v6-M with the System extensions + arch_ARMv7EM = 13, // v7-M with DSP extensions + arch_ARMv8 = 14, // v8 + arch_curr_max = arch_ARMv8, + arch_ARM_meta = 9999, // decode everything +}; + +enum arm_arch_profile_t +{ + arch_profile_unkn = 0, // Architecture profile is not applicable (e.g. pre v7, or cross-profile code) + arch_profile_A = 'A', // The application profile (e.g. for Cortex A8) + arch_profile_R = 'R', // The real-time profile (e.g. for Cortex R4) + arch_profile_M = 'M', // The microcontroller profile (e.g. for Cortex M3) + arch_profile_S = 'S', // Application or real-time profile (i.e. the 'classic' programmer's model) +}; + +enum fp_arch_t +{ + fp_arch_none = 0, // The user did not permit this entity to use instructions requiring FP hardware + fp_arch_v1 = 1, // The user permitted use of instructions from v1 of the floating point (FP) ISA + fp_arch_v2 = 2, // Use of the v2 FP ISA was permitted (implies use of the v1 FP ISA) + fp_arch_v3 = 3, // Use of the v3 FP ISA was permitted (implies use of the v2 FP ISA) + fp_arch_v3_16 = 4, // Use of the v3 FP ISA was permitted, but only citing registers D0-D15, S0-S31 + fp_arch_v4 = 5, // Use of the v4 FP ISA was permitted (implies use of the non-vector v3 FP ISA) + fp_arch_v4_16 = 6, // Use of the v4 FP ISA was permitted, but only citing registers D0-D15, S0-S31 + fp_arch_v8 = 7, // Use of the ARM v8-A FP ISA was permitted + fp_arch_v8_16 = 8, // Use of the ARM v8-A FP ISA was permitted, but only citing registers D0-D15, S0-S31 +}; + +enum adv_simd_arch_t +{ + adv_simd_arch_none = 0, // The user did not permit this entity to use the Advanced SIMD Architecture (Neon) + adv_simd_arch_base = 1, // Use of the Advanced SIMD Architecture (Neon) was permitted + adv_simd_arch_fma = 2, // Use of Advanced SIMD Architecture (Neon) with fused MAC operations was permitted + adv_simd_arch_v8 = 3, // Use of the ARM v8-A Advanced SIMD Architecture (Neon) was permitted +}; + +struct arm_arch_t +{ + arm_base_arch_t base_arch; + arm_arch_profile_t profile; + fp_arch_t fp_arch; + adv_simd_arch_t neon_arch; + + int arm_isa_use; // 0 = no ARM instructions (e.g. v7-M) + // 1 = allow ARM instructions + int thumb_isa_use; // 0 = no Thumb instructions + // 1 = 16-bit Thumb instructions + BL + // 2 = plus 32-bit Thumb instructions + int xscale_arch; // 0 = no XScale extension + // 1 = XScale extension (MAR/MRA etc) + int wmmx_arch; // 0 = no WMMX + // 1 = WMMX v1 + // 2 = WMMX v2 + int hp_ext; // 0 = no half-precision extension + // 1 = VFPv3/Advanced SIMD optional half-precision extension + int t2_ee; // 0 = no Thumb2-EE extension + // 1 = Thumb2-EE extension (ENTERX and LEAVEX) + qstring arch_name; // e.g. ARMv7-M + qstring core_name; // e.g. ARM1176JZF-S + + bool be8; // image is BE-8, i.e. little-endian code but big-endian data + bool arm64_32; // 32-bit address space, ARM64 instructions + + static const char *get_canonical_name(unsigned archno); + bool set_from_name(const char *name); // arch name or core name + bool set_options(const char *opts); // semicolon-delimited option string + void save_to_idb(arm_t &pm) const; + bool restore_from_idb(arm_t &pm); + qstring to_string() const; + arm_arch_t(void) + : base_arch(arch_ARM_old), + profile(arch_profile_unkn), + fp_arch(fp_arch_none), + neon_arch(adv_simd_arch_none), + arm_isa_use(0), + thumb_isa_use(0), + xscale_arch(0), + wmmx_arch(0), + hp_ext(0), + t2_ee(0), + be8(false), + arm64_32(false) + {} + + bool is_mprofile() + { + if ( profile == arch_profile_unkn ) + { + return base_arch >= arch_ARMv6M && base_arch <= arch_ARMv7EM; + } + return profile == arch_profile_M; + } +}; + +//------------------------------------------------------------------ +struct mmtype_t +{ + const char *name; + const type_t *type; + const type_t *fields; + tinfo_t tif; +}; + +//------------------------------------------------------------------ +void term_ana(void); +void move_it_blocks(ea_t from, ea_t to, asize_t size); +int get_it_size(const insn_t &insn); + +uint64 expand_imm_vfp(uint8 imm8, int sz); +bool idaapi equal_ops(const op_t &x, const op_t &y); + +int may_be_func(const insn_t &insn); +bool is_branch_insn(const insn_t &insn); +bool is_push_insn(const insn_t &insn, uint32 *reglist=NULL); +bool is_pop_insn(const insn_t &insn, uint32 *reglist=NULL, bool allow_ed=false); +int arm_create_switch_xrefs(ea_t insn_ea, const switch_info_t &si); +void mark_arm_codeseqs(void); +bool can_resolve_seg(ea_t ea); +#if defined(NALT_HPP) && defined(_XREF_HPP) +int arm_calc_switch_cases(casevec_t *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si); +#endif + +bool create_func_frame64(func_t *pfn, bool reanalyze); +int arm_get_frame_retsize(const func_t *pfn); +bool get_insn_op_literal(const insn_t &insn, const op_t &x, ea_t ea, void *value, bool force=false); + +void use_arm_arg_types( + ea_t ea, + func_type_data_t *fti, + funcargvec_t *rargs); + +//---------------------------------------------------------------------- +typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); + +ea_t arm_calc_step_over(ea_t ip); +ea_t arm_get_macro_insn_head(ea_t ip); +int arm_get_dbr_opnum(const insn_t &insn); +ssize_t arm_get_reg_name(qstring *buf, int _reg, size_t width, int reghi); +ssize_t arm_get_one_reg_name(qstring *buf, int _reg, size_t width); +bool ana_neon(insn_t &insn, uint32 code, bool thumb); +void opimm_vfp(op_t &x, uint32 imm8, int sz); +void ana_hint(insn_t &insn, int hint); +int get_it_info(ea_t ea); +int arm_get_reg_index(const char *name, bool as_mainreg, bitrange_t *pbitrange, bool is_a64); + +//====================================================================== +// common inline functions used by analyzer +//---------------------------------------------------------------------- +inline void oreglist(op_t &x, int regs) +{ + x.type = o_reglist; + x.dtype = dt_dword; + x.reglist = regs; +} + +//---------------------------------------------------------------------- +inline void onear(op_t &x, uval_t target, bool arm64=false) +{ + x.type = o_near; + x.dtype = dt_code; + x.addr = arm64 ? target : uint32(target); +} + +//---------------------------------------------------------------------- +inline void otext(op_t &x, const char *txt) +{ + x.type = o_text; + qstrncpy((char *)&x.value, txt, sizeof(x) - qoffsetof(op_t, value)); +} + +//---------------------------------------------------------------------- +// Get register number +inline uchar getreg(uint32 code, int lbit) +{ + return uchar((code >> lbit) & 0xF); +} + +//---------------------------------------------------------------------- +// Create operand of register type +inline void fillreg(op_t &x, uint32 code, int lbit) +{ + x.reg = getreg(code, lbit); + x.type = o_reg; + x.dtype = dt_dword; +} + +//---------------------------------------------------------------------- +inline void opreg(op_t &x, int rgnum) +{ + x.reg = uint16(rgnum); + x.type = o_reg; + x.dtype = dt_dword; +} + +struct reg_mode_t +{ + uint16 reg; + uchar mode; +}; + +//---------------------------------------------------------------------- +// Create operand of banked_reg type +extern const reg_mode_t banked0[32]; +extern const reg_mode_t banked1[32]; +inline bool opbanked(op_t &x, int R, uchar sysm) +{ + const reg_mode_t &rm = R ? banked1[sysm] : banked0[sysm]; + if ( rm.reg == 0xFFFF ) + return false; + x.reg = rm.reg; + x.specflag1 = rm.mode | BANKED_MODE; + x.type = o_reg; + x.dtype = dt_dword; + return true; +} + +//---------------------------------------------------------------------- +// Create operand of immediate type +inline void op_imm(op_t &x, uval_t value) +{ + x.type = o_imm; + x.dtype = dt_dword; + x.value = value; + x.ishtype = LSL; + x.ishcnt = 0; +} + +//---------------------------------------------------------------------- +// Create operand of immediate type (4 bits) +inline void op_imm4(op_t &x, uint32 code, int lbit) +{ + op_imm(x, getreg(code, lbit)); +} + +//---------------------------------------------------------------------- +inline void barrier_op(op_t &x, int code) +{ + const char *op = NULL; + switch ( code ) + { + case B8(0001): op = "OSHLD"; break; + case B8(0010): op = "OSHST"; break; + case B8(0011): op = "OSH"; break; + case B8(0101): op = "NSHLD"; break; + case B8(0110): op = "NSHST"; break; + case B8(0111): op = "NSH"; break; + case B8(1001): op = "ISHLD"; break; + case B8(1010): op = "ISHST"; break; + case B8(1011): op = "ISH"; break; + case B8(1101): op = "LD"; break; + case B8(1110): op = "ST"; break; + case B8(1111): op = "SY"; break; + } + if ( op != NULL ) + otext(x, op); + else + op_imm(x, code & 0xF); +} + +// is the current insn inside an it-block? +inline bool inside_itblock(int itcnd) +{ + return itcnd != -1; +} + +//====================================================================== +// common data sructures and functions for emulator +//---------------------------------------------------------------------- + +// since these is a lot of recursion in this module, we will keep +// all data as local as possible. no static data since we will have +// to save/restore it a lot +struct arm_saver_t +{ + arm_t ± + insn_t insn; // current instruction + bool flow; + + arm_saver_t(arm_t &_pm) : pm(_pm), insn(), flow(true) {} + arm_saver_t(arm_t &_pm, const insn_t &insn_) : pm(_pm), insn(insn_), flow(true) {} + + void handle_operand(const op_t &x, bool isload); + void emulate(void); + void handle_code_ref(const op_t &x, ea_t ea, bool iscall); + ea_t match_arm64_glue(void); + bool detect_glue_code( + ea_t ea, + int flags, +#define DGC_HANDLE 0x0001 // create offsets and names +#define DGC_FIND 0x0002 // ea points to the end of the glue code + ea_t *p_target = NULL, + ea_t *p_fptr = NULL, + size_t *p_glue_size = NULL); + bool detect_glue_code( + int flags, + ea_t *p_target = NULL, + ea_t *p_fptr = NULL, + size_t *p_glue_size = NULL); + bool arm_is_switch(void); + // try to decode instruction at ea as arm or thumb + //-V:try_decode:501 identical sub-expressions + bool try_decode(ea_t ea, bool is_thumb, bool check_sane = true); +}; + +// SPD value for security_push_cookie/security_pop_cookie +inline sval_t security_cookie_spd() +{ + return inf_is_64bit() ? 0x10 : 0x4; +} + +// SPD value for a special function +inline sval_t special_func_spd(special_func_t spf) +{ + return spf == SPF_GNU_MCOUNT_NC ? 4 + : spf == SPF_SECURITY_POP_COOKIE ? security_cookie_spd() + : spf == SPF_SECURITY_PUSH_COOKIE ? -security_cookie_spd() + : 0; +} + +int calc_fpreglist_size(const insn_t &ins); +int calc_advsimdlist_size(const insn_t &ins); + +// return true if 'x' is 'const' in LDR Rd, =const +inline bool is_ldr_literal(const insn_t &insn, const op_t &x) +{ + return x.type == o_mem + && (insn.itype == ARM_ldr || insn.itype == ARM_ldrpc + || insn.itype == ARM_ldur || insn.itype == ARM_ldxr + || insn.itype == ARM_fldd || insn.itype == ARM_flds + || insn.itype == ARM_vldr); +} + +//---------------------------------------------------------------------- +inline bool creglist_is_crd_cref(const insn_t &insn) +{ + return insn.itype == ARM_cdp || insn.itype == ARM_cdp2; +} +inline bool creglist_is_crn_cref(const insn_t &insn) +{ + return insn.itype != ARM_mcrr + && insn.itype != ARM_mrrc + && insn.itype != ARM_mcrr2 + && insn.itype != ARM_mrrc2; +} + +//---------------------------------------------------------------------- +// tuning parameters for reg_tracker_t +struct regtrack_info_t +{ + uint16 vals_size; // max number of possible values returned by + // find_op_values, find_reg_values; + // 0 - no limit; + uint16 op_recursion; // max level of recursion when calculating + // operands of the emulated instruction, e.g. + // LDR R0, =addr + // LDR R0, [R0,#4] + // ADD R0, #4 + // needs 2 levels (one for addressing, one for + // addition); + // 0 - no limit; + uint16 bblk_recursion; // max level of recursion when reconstructing + // the execution flow; + // 0 - no limit; + uint16 cache_size; // max size of the cache for one register; + // 0 - no limit; + uint16 max_xrefs; // max number of xrefs to analyze + // 0 - no limit; +}; + +//---------------------------------------------------------------------- +// Since we have to know if an instruction belongs to an IT-block or not, +// we keep all this information in a map +struct it_info_t +{ + uint8 size; + uint8 cond; + uint8 mask; + it_info_t(void) : size(0), cond(0), mask(0) {} + it_info_t(uval_t x) : + size(x&0xFF), + cond((x >> 8)&0xFF), + mask((x >> 16)&0xFF) + { + } + it_info_t(uint8 s, uint8 c, uint8 m) : size(s), cond(c), mask(m) {} + operator uval_t(void) const { return size | (cond << 8) | (mask << 16); } +}; +using it_blocks_t = std::map<ea_t, it_info_t>; // first_it_block_ea -> info + +//------------------------------------------------------------------ +#if defined(__LINUX__) && defined(__ARM__) || defined(ENABLE_LOWCNDS) +inline bool is_arm64_ea(ea_t ea) +{ + qnotused(ea); +#if defined(__EA64__) + return true; +#else + return false; +#endif +} +#endif + +//------------------------------------------------------------------ +#define BL_FORCE_JUMP 0 +#define BL_FORCE_CALL 1 +bool idaapi arm_bl_force(ea_t ea, int option, bool hide_errors); + +struct bl_force_flow_ah_t : public action_handler_t +{ + bool is_jump; + bl_force_flow_ah_t(bool _is_jump) : is_jump(_is_jump) {} + virtual int idaapi activate(action_activation_ctx_t *) override + { + return arm_bl_force( + get_screen_ea(), + is_jump ? BL_FORCE_JUMP : BL_FORCE_CALL, + false); + } + + virtual action_state_t idaapi update(action_update_ctx_t *) override + { + return AST_ENABLE_ALWAYS; + } +}; + +//------------------------------------------------------------------ +struct reg_tracker_t; +struct opinfo_helpers_t; +struct cfh_t; +struct rvi_vec_t; + +DECLARE_PROC_LISTENER(pm_idb_listener_t, struct arm_t); + +#define PROCMOD_T arm_t +struct arm_t : public procmod_t +{ + arm_t(); + ~arm_t(); + + pm_idb_listener_t idb_listener = pm_idb_listener_t(*this); + struct eh_parse_t *eh_parse = nullptr; + + //---------------------------------------------------------------------- + netnode helper; // altval(-1): idp flags +#define CALLEE_TAG 'A' // altval(ea): callee address for indirect calls +#define DXREF_TAG 'd' // altval(ea): resolved address for complex calculation (e.g. ADD R1, PC) +#define DELAY_TAG 'D' // altval(ea) == DELAY_MARK: analyze ea for a possible offset +#define ITBLOCK_TAG 'I' // altval(ea): packed it_info_t +#define FPTR_REG_TAG 'F' // supval(ea): frame pointer info fptr_info_t +#define FIXED_STKPNT 'x' // charval(ea): may not modify sp value at this address +#define PUSHINFO_TAG 's' // blob(ea): packed pushinfo_t +#define ARCHINFO_TAG 'a' // blob(0): packed arm_arch_t +#define LITERAL_EA 'L' // charval(insn_ea): =const operand number of load literal instruction +#define MAYBE_STKVAR 't' // charval(ea) == opno+1: may create stkvar for the operand + +#define DELAY_MARK 1 // possible offset marked for reanalysis +#define DELAY_DONE 2 // reanalysis completed, don't mark again to prevent endless loops + + inline void set_callee(ea_t ea, ea_t callee) { helper.easet(ea, callee, CALLEE_TAG); } + inline ea_t get_callee(ea_t ea) { return helper.eaget(ea, CALLEE_TAG); } + inline void del_callee(ea_t ea) { helper.eadel(ea, CALLEE_TAG); } + + inline void set_dxref(ea_t ea, ea_t dxref) { helper.easet(ea, dxref, DXREF_TAG); } + inline ea_t get_dxref(ea_t ea) { return helper.eaget(ea, DXREF_TAG); } + inline void del_dxref(ea_t ea) { helper.eadel(ea, DXREF_TAG); } + + // literal intsruction + inline void set_lit_opnum(ea_t insn_ea, uchar nop) { helper.charset_ea(insn_ea, nop, LITERAL_EA); } + inline uchar get_lit_opnum(ea_t insn_ea) { return helper.charval_ea(insn_ea, LITERAL_EA); } + inline void del_lit_opnum(ea_t insn_ea) { helper.chardel_ea(insn_ea, LITERAL_EA); } + + // possible stkvar + inline void set_possible_stkvar(ea_t insn_ea, int nop) { helper.charset_ea(insn_ea, uchar(nop + 1), MAYBE_STKVAR); } + inline int get_possible_stkvar(ea_t insn_ea) { return helper.charval_ea(insn_ea, MAYBE_STKVAR) - 1; } + inline void del_possible_stkvar(ea_t insn_ea) { helper.chardel_ea(insn_ea, MAYBE_STKVAR); } + + //---------------------------------------------------------------------- +#define IDP_SIMPLIFY 0x0001 +#define IDP_NO_PTR_DEREF 0x0002 +// 0x0004 // reserved, see reg.cpp +#define IDP_ARM5 0x0008 +#define IDP_NO_SETSGR 0x0010 +#define IDP_NO_BL_JUMPS 0x0020 +#define IDP_MOVT_MASK 0x0F00 // handling of MOV(W)/MOVT pairs +#define IDP_MOVT_SHIFT 8 // see MOVT_ +// MOVT pair handling options +#define MOVT_NONE 0 // do nothing (old behavior) +#define MOVT_ADDR 1 // only convert if resulting value is valid address +#define MOVT_ALL 2 // convert all pairs regardless of the value + + // - simplify instructions and replace them by pseudo-instructions + // - disable detection of BL instructions used for long jumps (not calls) + // in Thumb mode + // - convert valid addresses + ushort idpflags = IDP_SIMPLIFY + | IDP_ARM5 + | IDP_NO_BL_JUMPS + | (MOVT_ADDR<<IDP_MOVT_SHIFT); + + inline bool simplify(void) { return (idpflags & IDP_SIMPLIFY) != 0; } + inline bool deref_ptrs(void) { return (idpflags & IDP_NO_PTR_DEREF) == 0; } + inline bool may_setsgr(void) { return (idpflags & IDP_NO_SETSGR) == 0; } + inline bool no_bl_jumps(void) { return (idpflags & IDP_NO_BL_JUMPS) != 0; } + inline uint8 arm_movt_convert(void) { return (idpflags & IDP_MOVT_MASK) >> 8; } + + bool convert_movw_movt(const insn_t &_insn, ea_t ea_movt, ea_t ea_movw, ea_t base); + + //---------------------------------------------------------------------- + arm_arch_t arch; + arm_arch_t tarch; // temporary (unsaved) arch info that's being changed by the user + qstring default_arch; + qstring arm_arch; + + inline bool has_arm() { return arch.arm_isa_use != 0; } + inline bool has_thumb() { return arch.thumb_isa_use != 0; } + inline bool has_thumb2() { return arch.thumb_isa_use >= 2; } + inline bool has_xscale() { return arch.xscale_arch != 0; } + inline bool has_vfp() { return arch.fp_arch != fp_arch_none; } + inline bool has_neon() { return arch.neon_arch != adv_simd_arch_none; } +#ifndef ENABLE_LOWCNDS + inline bool has_armv5() { return arch.base_arch >= arch_ARMv5T; } + inline bool has_armv7a() { return arch.base_arch == arch_ARMv7 || arch.base_arch > arch_ARMv7EM; } + inline bool has_armv8() { return arch.base_arch >= arch_ARMv8; } + inline bool is_mprofile() { return arch.is_mprofile(); } +#endif + inline bool is_be8() { return arch.be8 != 0; } + inline bool is_thumb_ea(ea_t ea) + { + if ( !has_arm() ) + return true; + sel_t t = get_sreg(ea, T); + return t != BADSEL && t != 0; + } + + intvec_t custom_format_fids; + bl_force_flow_ah_t bl_force_jump = bl_force_flow_ah_t(true); + bl_force_flow_ah_t bl_force_call = bl_force_flow_ah_t(false); + ea_t got_ea = BADADDR; // .got start address + int mnem_width = 0; + bool file_loaded = 0; + bool initing = false; + bool warn_about_max_xrefs = true; + bool recursing = false; + + it_blocks_t it_blocks; + + //---------------------------------------------------------------------- + // tuning parameters for reg_tracker_t (set from configuration file by + // set_idp_options) + regtrack_info_t regtrack_inf = + { + 100, // vals_size + 100, // op_recursion + 2000, // bblk_recursion + 5000, // cache_size + 256, // max_xrefs + }; + reg_tracker_t *reg_tracker = nullptr; + + //---------------------------------------------------------------------- + // clear the cache of calculated register values from <ea> until the + // next function; + // if <ea> is BADADDR the clear the whole cache + void clear_reg_cache(ea_t ea, int msgid); + // clear all + void term_reg_cache(); + // find all values loaded into register + void find_reg_values(rvi_vec_t *ret, ea_t ea, int reg); + + //---------------------------------------------------------------------- + mmtype_t *mmtypes = nullptr; + size_t mmtypes_cnt = 0; + mmtype_t *mm_array_types = nullptr; + size_t mm_array_types_cnt = 0; + + int get_arm_simd_types( + simd_info_vec_t *outtypes, + const simd_info_t *pattern, + const argloc_t *argloc, + bool do_create); + void term_arm_simdtypes(); + void register_custom_formats(void); + void unregister_custom_formats(void); + + //---------------------------------------------------------------------- + cfh_t *cfh = nullptr; +#ifdef __EA64__ + fixup_type_t cfh_pg21_id = 0; // ids of fixup handlers + fixup_type_t cfh_hi12_id = 0; + fixup_type_t cfh_lo12_id = 0; + fixup_type_t cfh_lo21_id = 0; + fixup_type_t cfh_b14_id = 0; + fixup_type_t cfh_b19_id = 0; + fixup_type_t cfh_b26_id = 0; + int ref_pg21_id = 0; // ids of refinfo handlers + int ref_hi12_id = 0; + int ref_lo12_id = 0; + int ref_lo21_id = 0; + + bool emulate_ldr_str_add_operand(const insn_t &insn, const op_t &op); +#else + // ids of fixup handlers + fixup_type_t cfh_prel31_id = 0; + // ids of refinfo handlers + int ref_prel31_id = 0; +#endif + + void init_custom_refs(); + void term_custom_refs(); + + //---------------------------------------------------------------------- +#include "../msvc_common.hpp" + + //---------------------------------------------------------------------- + inline bool is_gas(void) const + { + return (ash.uflag & UAS_GNU) != 0; + } + inline bool is_ual(void) const + { + return (ash.uflag & UAS_LEGACY) == 0; + } + + //---------------------------------------------------------------------- + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void restore_arch(); + void load_from_idb(); + void arm_set_gotea(ea_t ea); + void arm_get_abi_info(qstrvec_t *abi_names, qstrvec_t *abi_opts, comp_t); + void arm_set_compiler(bool init_abibits); + void header(outctx_t &ctx); + void assumes(outctx_t &ctx); + void segstart(outctx_t &ctx, segment_t *seg); + void segend(outctx_t &ctx, segment_t *seg); + void del_function_marks(const func_t *pfn); + const char *get_regname(int rn); + + void init_ana(void); + void term_ana(void); + int ana64(insn_t &insn, calcrel_helper_t *crh); + int ana_arm(insn_t &insn, calcrel_helper_t *crh=nullptr); + int ana_thumb(insn_t &insn, calcrel_helper_t *crh=nullptr); + bool ana_coproc(insn_t &insn, uint32 code); + bool ana_vfp_insns(insn_t &insn, uint32 code); + bool ana_neon(insn_t &insn, uint32 code, bool thumb); + inline bool is_undef_vfp(uint32 code, bool thumb); + inline bool supported_vfp_neon_insn(uint32 code); + void check_displ(const insn_t &insn, op_t &x, bool alignPC=false); + void addressing_mode( + insn_t &insn, + op_t &x, + uint32 code, + calcrel_helper_t *crh); + bool thumb32(insn_t &insn, int code1, int code2, calcrel_helper_t *crh); + int do_ana(insn_t &insn, calcrel_helper_t *crh); + int ana(insn_t *out_ins); + int get_it_info(ea_t ea, ea_t *it_insn_ea=nullptr); + void move_it_blocks(ea_t from, ea_t to, asize_t size); + bool build_movl_macro(insn_t *s, const insn_t &insn); + bool build_adrl_macro(insn_t *s, const insn_t &insn); + bool simplify_to_mov(insn_t *s); + bool build_macro(insn_t &insn, bool may_go_forward); + bool is_arm64(const insn_t &insn) const; + bool is_arm64(void) const; +#if defined(__LINUX__) && defined(__ARM__) + // see above, global def +#else + bool is_arm64_ea(ea_t ea) const; +#endif + bool check_for_t_changes(ea_t start, size_t size); + int a64_branch(insn_t &insn, uint32 code, calcrel_helper_t *crh); + int decode64(insn_t &insn, calcrel_helper_t *crh); + + int emu(const insn_t &insn); + void add_it_block(const insn_t &insn); + void del_it_block(ea_t ea); + void del_insn_info(ea_t ea); + bool copy_insn_optype(const insn_t &insn, const op_t &x, ea_t ea, bool force=false); + inline void fix_stkpnt(ea_t ea); + inline bool is_fixed_stkpnt(ea_t ea) const; + inline void add_stkpnt(const insn_t &insn, func_t *pfn, sval_t v) const; + void trace_sp(const insn_t &insn); + bool verify_sp(func_t *pfn); + inline void save_idpflags() { helper.altset(-1, idpflags); } + void add_dxref(ea_t from, ea_t target); + ea_t find_callee(const insn_t &insn, const op_t &x); + void emulate_ldr_str_base_offset( + const insn_t &insn, + ea_t base, + const struct rvi_vec_t &offs, + char op_dtyp, + bool swap_base_off, + bool only_dxref = false); + bool emulate_ldr_str_reg_based(const insn_t &insn, const op_t &op); + bool emulate_ldr_str_with_displ(const insn_t &insn, const op_t &op); + bool emulate_add_reg_based(const insn_t &insn, int reg1, int reg2); + void arm_splitSRrange1(ea_t from, ea_t to, sel_t v, uchar tag); + bool is_arm_call_insn(const insn_t &insn); + bool range_uses_lr(ea_t ea1, ea_t ea2); + bool is_bl_call(const insn_t &_insn, ea_t ea); + void propagate_t_bit_to(const insn_t &insn, ea_t ea, bool use_low_bit); + bool same_reg_value( + ea_t ea, + const op_t &op, + int r1, + const op_t *r1_moved, + bool ignore_r1_changes = false); + void set_arch_from_loader_arch_info(); + bool is_sp_alias(ea_t ea, int reg); + int arm_calc_next_eas(eavec_t *res, const insn_t &insn, bool over); + bool is_return_insn(const insn_t &insn, bool only_lr=false); + bool try_code_start(ea_t ea, bool respect_low_bit); + int try_offset(ea_t ea); + ea_t calc_next_exec_insn( + const insn_t &ins, + const regval_t *regvalues, + const opinfo_helpers_t &oh, + bool is_mprofile); + bool try_switch_branch_stmt2(switch_info_t *_si, const insn_t &strt); + bool try_switch_branch_stmt3(switch_info_t *_si, const insn_t &strt); + + //---------------------------------------------------------------------- + // Is register 'reg' spoiled by the current instruction? + // If flag <use_pcs> is set then it is assumed that call instruction + // doesn't spoil callee-saved registers (according to Procedure Call + // Standard the are r4-r8, r10, r11, SP for AArch32, r19-r29, SP for + // AArch64). If this flag is not set then this function assumes that + // call instruction spoils LR and r0 (return value). + bool spoils(const insn_t &insn, int reg, bool use_pcs = false); + // If flag <use_pcs> is set then it is assumed that call instruction + // doesn't spoil callee-saved registers else this function assumes that + // call instruction spoils everything (why?). + int spoils(const insn_t &insn, const uint32 *regs, int n, bool use_pcs = false); + // is PSR (Program Status Register) spoiled by the instruction ? + bool spoils_psr(const insn_t &insn) const; + + + bool get_fptr_info(fptr_info_t *fpi, ea_t func_ea) const; + inline ushort get_fptr_reg(ea_t func_ea) + { + fptr_info_t fpi; + return get_fptr_info(&fpi, func_ea) ? fpi.reg : ushort(-1); + } + inline ea_t get_fp_ea(ea_t func_ea) + { + fptr_info_t fpi; + return get_fptr_info(&fpi, func_ea) ? fpi.addr : BADADDR; + } + void set_fptr_info(ea_t func_ea, ushort reg, ea_t addr); + + bool is_sub_rn_fp(const insn_t &insn); + sval_t calc_sp_delta(func_t *pfn, const insn_t &insn); + bool arm_calc_spdelta(sval_t *spdelta, const insn_t &insn); + inline bool isfp(const insn_t &insn, const op_t &x); + inline bool is_sp_based(const insn_t &insn, const op_t &x); + static bool is_start_func_hint(const insn_t &_insn); + void try_delay_offset(ea_t ea); + int sp_based(const insn_t &insn, const op_t &x); + bool uses(const insn_t &insn, int reg) const; + bool arm_set_op_type( + const insn_t &insn, + const op_t &x, + const tinfo_t &tif, + const char *name); + bool arm_set_op_type( + const insn_t &insn, + const op_t &x, + const tinfo_t &tif, + const char *name, + eavec_t *visited); + int use_arm_regarg_type(ea_t ea, const funcargvec_t &rargs); + void use_arm_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs); + bool is_glue_adr_insn(const insn_t &insn); + flags_t set_immd_bit(const insn_t &insn, int n, flags_t F); + bool good_target(ea_t from, ea_t target); + ea_t get_thumb_glue_target(ea_t ea); + bool handle_thunk(const insn_t &insn); + void handle_pc_offset(ea_t ea, int reg); + int is_jump_func(func_t *pfn, ea_t *jump_target, ea_t *function_pointer); + int is_arm_sane_insn(const insn_t &insn, int asn_flags); +#define ASN_NOCREFS 0x01 // there are no crefs to the insn +#define ASN_THUMB 0x02 // use thumb mode +#define ASN_CHECK_MODE 0x04 // check thumb/arm mode of the next insn + int arm_is_align_insn(ea_t ea); + bool is_rt_switch8(switch_info_t *_si, const insn_t &insn); + bool lr_points_to_next_insn(const insn_t &insn, ea_t *value=nullptr); + bool arm_get_operand_info( + idd_opinfo_t *opinf, + ea_t ea, + int n, + int tid, + getreg_t *getreg, + const regval_t *rv); + ea_t arm_next_exec_insn( + ea_t ea, + int tid, + getreg_t *getreg, + const regval_t *regvalues); + bool arm_update_call_stack(call_stack_t *stack, int tid, getreg_t *getreg, const regval_t *rv); + bool get_call_addr(call_stack_info_t *si, ea_t pc, bool is_a64); + void force_offset(ea_t ea, int n, ea_t base) const; + int may_be_func(const insn_t &_insn); + void get_reg_accesses(reg_accesses_t *accvec, const insn_t &insn) const; + void test_get_reg_accesses() const; + bool find_reg_diff(sval_t *delta, const insn_t &insn); + bool get_arm_callregs(callregs_t *callregs, cm_t cc); + bool is_big_udt(const tinfo_t &tif, bool as_retval); + bool alloc_args(func_type_data_t *fti, int nfixed); + bool calc_arm_arglocs(func_type_data_t *fti); + bool calc_arm_varglocs(func_type_data_t *fti, regobjs_t *regargs, int nfixed); + bool calc_arm_retloc(argloc_t *retloc, const tinfo_t &rettype, cm_t cc); + bool adjust_arm_argloc(argloc_t *argloc, const tinfo_t *tif, int size); + bool alloc_args64(func_type_data_t *fti, int nfixed); + void arm_lower_func_arg_types(intvec_t *argnums, const func_type_data_t &fti); + bool arm_get_reg_info(const char **main_name, bitrange_t *pbitrange, const char *name); + bool create_func_frame32(func_t *pfn, bool reanalyze); + bool create_func_frame64(func_t *pfn, bool reanalyze); + bool create_func_frame(func_t *pfn, bool reanalyze = false); + sval_t find_subsp_ofs(const insn_t &insn); + sval_t check_fp_changes(const insn_t &strt, int fpreg, int *finalreg); + bool adjust_frame_size( + func_t *pfn, + const insn_t &insn, + int reg, + sval_t spoff); + int is_cfguard_reg(int *reg, ea_t ea, bool is_indirect) const; + int is_cfguard_thunk(const insn_t &insn, int *p_reg); + + void arm_move_segm(ea_t from, const segment_t *s, bool changed_netmap); + void arm_erase_info(ea_t ea1, ea_t ea2); + const char *set_idp_options( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded); + void correct_code_sequences(void); + bool is_be_proc() const; + + ushort basearch_to_field() const; + ushort vfp_to_field() const; + + void arm_upgrade_fbase_to700(); + void arm_upgrade_fptr_to700(); + + const char *cond2str(cond_t cond) const; + void footer(outctx_t &ctx) const; + bool outspec(outctx_t &ctx, uchar stype) const; +}; +extern int data_id; + +//---------------------------------------------------------------------- +class reg_formatter_t +{ + const processor_t &ph; + qstring outbuf; + + const char *regname(int rn) const; + void format_with_suffix(int rn, int fields); + +public: + reg_formatter_t(const processor_t &_ph) : ph(_ph) {} + void format_a64(int regnum, char dtype, int elsize = 0, int index = -1); + void format_with_index(int rn, int index=-1); + void format_any_reg(int rn, const op_t &x, bool ignore_suffix=false); + op_dtype_t format_phreg(const op_t &x, int regidx); + const qstring &get_regname() const { return outbuf; } +}; + +//------------------------------------------------------------------ +reg_tracker_t *alloc_reg_tracker(arm_t &pm); +void free_reg_tracker(reg_tracker_t *rt); +cfh_t *alloc_cfh(); +void free_cfh(cfh_t *ptr); + +#endif // _ARM_HPP diff --git a/idasdk76/module/arm/notify_codes.hpp b/idasdk76/module/arm/notify_codes.hpp new file mode 100644 index 0000000..c8a5de7 --- /dev/null +++ b/idasdk76/module/arm/notify_codes.hpp @@ -0,0 +1,142 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __ARM_NOTIFY_CODES_HPP +#define __ARM_NOTIFY_CODES_HPP + +struct pushinfo_t; +struct arm_arch_t; +//---------------------------------------------------------------------- +// The following events are supported by the ARM module in the ph.notify() function +namespace arm_module_t +{ + enum event_codes_t + { + // obsolete, use processor_t::set_code16_mode() + ev_set_thumb_mode = processor_t::ev_loader, + ev_set_arm_mode, + // obsolete, use processor_t::get_code16_mode() + ev_get_thumb_mode, + ev_restore_pushinfo, // Restore function prolog info from the database + // in: pushinfo_t *pi + // ea_t func_start + // Returns: 1-ok, otherwise-failed + ev_save_pushinfo, // Save function prolog info to the database + // in: ea_t func_start + // const pushinfo_t *pi + // Returns: 1-ok, otherwise-failed + ev_is_push_insn, // Is push instruction? + // in: uint32 *reglist + // const insn_t* insn + // Returns: 1-yes, -1-no + ev_is_pop_insn, // Is pop instruction? + // in: uint32 *reglist + // const insn_t* insn + // bool allow_ldmed + // Returns: 1-yes, -1-no + ev_is_gnu_mcount_nc, // Is __gnu_mcount_nc function? + // in: ea_t ea + // Returns: 1-yes, -1-no + ev_is_special_func, // Is special function? + // in: ea_t ea + // Returns: special_func_t + ev_get_arch_settings, // in: arm_arch_t *arch to be filled in + // size_t strucsize;(init to sizeof(arm_arch_t) + // Returns: 1-ok, otherwise-failed + ev_get_fptr_info, // Get frame pointer info for given function + // in: ushort *reg (out) FP register number + // ea_t *addr (out) address where the fp register is set + // ea_t func_start + // Returns: 1-ok, 0-no FP register + ev_serialize_pushinfo, // Save function prolog info to the buffer + // in: bytevec_t *buf + // ea_t func_start + // const pushinfo_t *pi + // int flags (reserved) + // Returns: 1-ok, otherwise-failed + ev_deserialize_pushinfo, + // Restore function prolog info from the buffer + // in: pushinfo_t *pi + // memory_deserializer_t *buf + // ea_t func_start + // int flags (reserved) + // Returns: 1-ok, otherwise-failed + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline bool restore_pushinfo(pushinfo_t *pi, ea_t func_start) + { + return processor_t::notify(idp_ev(ev_restore_pushinfo), pi, func_start) == 1; + } + + inline bool save_pushinfo(ea_t func_start, const pushinfo_t &pi) + { + return processor_t::notify(idp_ev(ev_save_pushinfo), func_start, &pi) == 1; + } + + inline bool is_push_insn(uint32 *reglist, const insn_t &insn) + { + return processor_t::notify(idp_ev(ev_is_push_insn), reglist, &insn) == 1; + } + + inline bool is_pop_insn(uint32 *reglist, const insn_t &insn, bool allow_ldmed) + { + return processor_t::notify(idp_ev(ev_is_pop_insn), reglist, &insn, allow_ldmed) == 1; + } + + inline bool is_gnu_mcount_nc(ea_t ea) + { + return processor_t::notify(idp_ev(ev_is_gnu_mcount_nc), ea) == 1; + } + + inline int is_special_func(ea_t ea) + { + return processor_t::notify(idp_ev(ev_is_special_func), ea); + } + + inline bool get_arch_settings(arm_arch_t *arch) + { + return processor_t::notify(idp_ev(ev_get_arch_settings), arch) == 1; + } + + inline bool get_fptr_info(ushort *reg, ea_t *addr, ea_t func_start) + { + return processor_t::notify(idp_ev(ev_get_fptr_info), reg, addr, func_start) == 1; + } + + inline bool serialize_pushinfo( + bytevec_t *buf, + ea_t func_start, + const pushinfo_t &pi, + int flags = 0) + { + return processor_t::notify(idp_ev(ev_serialize_pushinfo), + buf, + func_start, + &pi, + flags) == 1; + } + + inline bool deserialize_pushinfo( + pushinfo_t *pi, + memory_deserializer_t *buf, + ea_t func_start, + int flags = 0) + { + return processor_t::notify(idp_ev(ev_deserialize_pushinfo), + pi, + buf, + func_start, + flags) == 1; + } +} + +#endif // __NOTIFY_CODES_HPP diff --git a/idasdk76/module/avr/ana.cpp b/idasdk76/module/avr/ana.cpp new file mode 100644 index 0000000..930e645 --- /dev/null +++ b/idasdk76/module/avr/ana.cpp @@ -0,0 +1,819 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#include "avr.hpp" +#include <fixup.hpp> + +//-------------------------------------------------------------------------- +/* + +0000 0000 0000 0000 nop +0000 0001 dddd rrrr movw Rd,Rr +0000 0010 dddd rrrr muls Rd,Rr +0000 0011 0ddd 0rrr mulsu Rd,Rr +0000 0011 0ddd 1rrr fmul Rd,Rr +0000 0011 1ddd 0rrr fmuls Rd,Rr +0000 0011 1ddd 1rrr fmulsu Rd,Rr +0000 01rd dddd rrrr cpc rd, rr +0000 10rd dddd rrrr sbc rd, rr +0000 11rd dddd rrrr add rd, rr lsl rd if rd==rr +0001 00rd dddd rrrr cpse rd, rr +0001 01rd dddd rrrr cp rd, rr +0001 10rd dddd rrrr sub rd, rr +0001 11rd dddd rrrr adc rd, rr rol rd if rd==rr +0010 00rd dddd rrrr and rd, rr tst rd if rd==rr +0010 01rd dddd rrrr eor rd, rr clr rd if rd==rr +0010 10rd dddd rrrr or rd, rr +0010 11rd dddd rrrr mov rd, rr +0011 kkkk dddd kkkk cpi rd, k (16<=d<=31) +0100 kkkk dddd kkkk sbci rd, k (16<=d<=31) +0101 kkkk dddd kkkk subi rd, k (16<=d<=31) +0110 kkkk dddd kkkk ori/sbr rd, k (16<=d<=31) +0111 kkkk dddd kkkk andi rd, k (16<=d<=31) cbr rd, k if op2 is bitwise negated +1000 000d dddd 0000 ld rd, Z +1000 000d dddd 1000 ld rd, Y +1000 001r rrrr 0000 st Z, rr +1000 001r rrrr 1000 st Y, rr +1001 000d dddd 0000(1*k)lds rd, k +1001 000d dddd 0001 ld rd, Z+ +1001 000d dddd 0010 ld rd, -Z +1001 000d dddd 0100 lpm Rd, Z +1001 000d dddd 0101 lpm Rd, Z+ +1001 000d dddd 0110 elpm Rd, Z +1001 000d dddd 0111 elpm Rd, Z+ +1001 000d dddd 1001 ld rd, Y+ +1001 000d dddd 1010 ld rd, -Y +1001 000d dddd 1100 ld rd, X +1001 000d dddd 1101 ld rd, X+ +1001 000d dddd 1110 ld rd, -X +1001 000d dddd 1111 pop rd +1001 001d dddd 0000(1*k)sts k, rd +1001 001d dddd 1111 push rd +1001 001r rrrr 0001 st Z+, rr +1001 001r rrrr 0010 st -Z, rr +1001 001r rrrr 0100 xch Z, rr +1001 001r rrrr 0101 las Z, rr +1001 001r rrrr 0110 lac Z, rr +1001 001r rrrr 0111 lat Z, rr +1001 001r rrrr 1001 st Y+, rr +1001 001r rrrr 1010 st -Y, rr +1001 001r rrrr 1100 st X, rr +1001 001r rrrr 1101 st X+, rr +1001 001r rrrr 1110 st -X, rr +1001 0100 0000 1000 sec +1001 0100 0001 1000 sez +1001 0100 0010 1000 sen +1001 0100 0011 1000 sev +1001 0100 0100 1000 ses +1001 0100 0101 1000 seh +1001 0100 0110 1000 set +1001 0100 0111 1000 sei +1001 0100 0sss 1000 bset s +1001 0100 1000 1000 clc +1001 0100 1001 1000 clz +1001 0100 1010 1000 cln +1001 0100 1011 1000 clv +1001 0100 1100 1000 cls +1001 0100 1101 1000 clh +1001 0100 1110 1000 clt +1001 0100 1111 1000 cli +1001 0100 1sss 1000 bclr s +1001 0100 0000 1001 ijmp +1001 0100 0001 1001 eijmp +1001 0100 KKKK 1011 des K +1001 0101 0xx0 1000 ret +1001 0101 0xx1 1000 reti +1001 0101 100x 1000 sleep +1001 0101 101x 1000 wdr +1001 0101 110x 1000 lpm +1001 0101 1101 1000 elpm +1001 0101 1110 1000 spm +1001 0101 1111 1000 espm +1001 0101 0000 1001 icall +1001 0101 0001 1001 eicall +1001 010d dddd 0000 com rd +1001 010d dddd 0001 neg rd +1001 010d dddd 0010 swap rd +1001 010d dddd 0011 inc rd +1001 010d dddd 0101 asr rd +1001 010d dddd 0110 lsr rd +1001 010d dddd 0111 ror rd +1001 010d dddd 1010 dec rd +1001 010k kkkk 110k(1*k)jmp k +1001 010k kkkk 111k(1*k)call k +1001 0110 kkdd kkkk adiw rd, k (d=24,26,28,30) +1001 0111 kkdd kkkk sbiw rd, k (d=24,26,28,30) +1001 1000 pppp pbbb cbi p, b +1001 1001 pppp pbbb sbic p, b +1001 1010 pppp pbbb sbi p, b +1001 1011 pppp pbbb sbis p, b +1001 11rd dddd rrrr mul rd, rr +1011 0ppd dddd pppp in rd, p +1011 1ppr rrrr pppp out p, rr +10q0 qq0d dddd 0qqq ldd rd, Z+q +10q0 qq0d dddd 1qqq ldd rd, Y+q +10q0 qq1r rrrr 0qqq std Z+d, rr +10q0 qq1r rrrr 1qqq std Y+d, rr +1100 kkkk kkkk kkkk rjmp k +1101 kkkk kkkk kkkk rcall k +1110 1111 dddd 1111 ser rd (16<=d<=31) +1110 kkkk dddd kkkk ldi rd, k +1111 00kk kkkk k000 brcs/brlo k +1111 00kk kkkk k001 brne k +1111 00kk kkkk k010 brmi k +1111 00kk kkkk k011 brvs k +1111 00kk kkkk k100 brlt k +1111 00kk kkkk k101 brhs k +1111 00kk kkkk k110 brts k +1111 00kk kkkk k111 brie k +1111 00kk kkkk ksss brbs s, k +1111 01kk kkkk k000 brcc/brsh k +1111 01kk kkkk k001 breq k +1111 01kk kkkk k010 brpl k +1111 01kk kkkk k011 brvc k +1111 01kk kkkk k100 brge k +1111 01kk kkkk k101 brhc k +1111 01kk kkkk k110 brtc k +1111 01kk kkkk k111 brid k +1111 01kk kkkk ksss brbc s, k +1111 100d dddd 0bbb bld rd, b +1111 101d dddd Xbbb bst rd, b +1111 110r rrrr xbbb sbrc rr, b +1111 111r rrrr xbbb sbrs rr, b +*/ + +// handle wraparound jumps +inline uint32 avr_t::code_address(const insn_t &insn, signed int delta) const +{ + ea_t newip = insn.ip + 1 + delta; + uint32 size = romsize != 0 ? romsize : 0x10000; + if ( insn.ip > size ) + return newip; + else + return newip % size; +} + +//------------------------------------------------------------------------ +inline ushort ua_next_full_byte(insn_t &insn) +{ + return (ushort)get_wide_byte(insn.ea + insn.size++); +} + +//-------------------------------------------------------------------------- +inline void opreg(op_t &x, uint16 n, bool rpair = false) +{ + x.type = o_reg; + x.dtype = dt_byte; + x.reg = n; + if ( rpair ) + x.reg_pair = 1; +} + +//-------------------------------------------------------------------------- +inline void avr_t::opimm(const insn_t &insn, op_t &x, int value) const +{ + x.type = o_imm; + x.dtype = dt_byte; + x.value = value; + x.specflag1 = uchar(helper.charval_ea(insn.ea, ELF_AVR_TAG) == ELF_AVR_LDI_NEG); +} + +//-------------------------------------------------------------------------- +inline void opnear(op_t &x, ea_t addr) +{ + x.type = o_near; + x.dtype = dt_code; + x.addr = addr; +} + +//-------------------------------------------------------------------------- +inline void opmem(insn_t &insn, op_t &x) +{ + x.type = o_mem; + x.dtype = dt_byte; + x.offb = (char)insn.size; + x.addr = ua_next_full_byte(insn); +} + +//-------------------------------------------------------------------------- +// 0001 10rd dddd rrrr sub rd, rr 6 +static void tworegs(insn_t &insn, int code) +{ + opreg(insn.Op1, (code >> 4) & 31); + opreg(insn.Op2, (code & 15) | ((code >> 5) & 16)); +} + +//-------------------------------------------------------------------------- +// 1000 000d dddd 1000 ld rd, Y +inline void opregd(op_t &x, int code) +{ + opreg(x, (code >> 4) & 31); +} + +//-------------------------------------------------------------------------- +inline void opphr(op_t &x, phrase_t phrase) +{ + x.type = o_phrase; + x.phrase = phrase; + x.dtype = dt_byte; +} + +//-------------------------------------------------------------------------- +inline void opport(op_t &x, int portnum) +{ + x.type = o_port; + x.addr = portnum; + x.dtype = dt_byte; +} + +//-------------------------------------------------------------------------- +inline void opdisp(op_t &x, phrase_t phrase, int delta) +{ + if ( delta ) + { + x.type = o_displ; + x.phrase = phrase; + x.addr = delta; + x.dtype = dt_byte; + } + else + { + opphr(x, phrase); + } +} + +//-------------------------------------------------------------------------- +int avr_t::ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + // if ( insn.ip & 1 ) return 0; // alignment error + int code = ua_next_full_byte(insn); + switch ( code >> 12 ) + { + case 0: + case 1: + case 2: +// 0000 0000 0000 0000 nop 0 +// 0000 0001 dddd rrrr movw Rd, Rr 0 +// 0000 0010 dddd rrrr muls Rd, Rr 0 +// 0000 0011 0ddd 0rrr mulsu Rd, Rr 0 +// 0000 0011 0ddd 1rrr fmul Rd, Rr 0 +// 0000 0011 1ddd 0rrr fmuls Rd, Rr 0 +// 0000 0011 1ddd 1rrr fmulsu Rd, Rr 0 +// 0000 01rd dddd rrrr cpc rd, rr 1 +// 0000 10rd dddd rrrr sbc rd, rr 2 +// 0000 11rd dddd rrrr add rd, rr 3 lsl rd if rd==rr +// 0001 00rd dddd rrrr cpse rd, rr 4 +// 0001 01rd dddd rrrr cp rd, rr 5 +// 0001 10rd dddd rrrr sub rd, rr 6 +// 0001 11rd dddd rrrr adc rd, rr 7 rol rd if rd==rr +// 0010 00rd dddd rrrr and rd, rr 8 tst rd if rd==rr +// 0010 01rd dddd rrrr eor rd, rr 9 clr rd if rd==rr +// 0010 10rd dddd rrrr or rd, rr A +// 0010 11rd dddd rrrr mov rd, rr B + { + static const uchar itypes[] = + { + AVR_nop, // 0 + AVR_cpc, // 1 + AVR_sbc, // 2 + AVR_add, // 3 + AVR_cpse, // 4 + AVR_cp, // 5 + AVR_sub, // 6 + AVR_adc, // 7 + AVR_and, // 8 + AVR_eor, // 9 + AVR_or, // A + AVR_mov // B + }; + int idx = (code >> 10) & 15; + insn.itype = itypes[idx]; + tworegs(insn, code); + switch ( idx ) + { + case 0: + switch ( (code>>8) & 3 ) + { + case 0: // nop + if ( code != 0 ) + return 0; + insn.Op1.type = insn.Op2.type = o_void; + break; + case 1: // movw + insn.itype = AVR_movw; + opreg(insn.Op1, ((code >> 3) & 30), true); + opreg(insn.Op2, ((code << 1) & 30), true); + break; + case 2: // muls + insn.itype = AVR_muls; + opreg(insn.Op1, 16 + (((code >> 4) & 15))); + opreg(insn.Op2, 16 + (((code >> 0) & 15))); + break; +// 0000 0011 0ddd 0rrr mulsu Rd, Rr 0 +// 0000 0011 0ddd 1rrr fmul Rd, Rr 0 +// 0000 0011 1ddd 0rrr fmuls Rd, Rr 0 +// 0000 0011 1ddd 1rrr fmulsu Rd, Rr 0 + case 3: // mulsu, fmul, fmuls, fmulsu + { + idx = ((code >> 6) & 2) | ((code>>3) & 1); + static const uchar subtypes[] = + { AVR_mulsu, AVR_fmul, AVR_fmuls, AVR_fmulsu }; + insn.itype = subtypes[idx]; + } + opreg(insn.Op1, 16 + (((code >> 4) & 7))); + opreg(insn.Op2, 16 + (((code >> 0) & 7))); + break; + } + break; + case 3: // lsl + if ( insn.Op1.reg == insn.Op2.reg ) + { + insn.itype = AVR_lsl; + insn.Op2.type = o_void; + } + break; + case 7: // rol + if ( insn.Op1.reg == insn.Op2.reg ) + { + insn.itype = AVR_rol; + insn.Op2.type = o_void; + } + break; + case 8: // tst + if ( insn.Op1.reg == insn.Op2.reg ) + { + insn.itype = AVR_tst; + insn.Op2.type = o_void; + } + break; + case 9: // clr + if ( insn.Op1.reg == insn.Op2.reg ) + { + insn.itype = AVR_clr; + insn.Op2.type = o_void; + } + break; + } + } + break; + + case 3: + case 4: + case 5: + case 6: + case 7: +// 0011 kkkk dddd kkkk cpi rd, k (16<=d<=31) +// 0100 kkkk dddd kkkk sbci rd, k (16<=d<=31) +// 0101 kkkk dddd kkkk subi rd, k (16<=d<=31) +// 0110 kkkk dddd kkkk ori/sbr rd, k (16<=d<=31) +// 0111 kkkk dddd kkkk andi rd, k (16<=d<=31) cbr rd, k if op2 is bitwise negated + { + static const uchar itypes[] = + { + AVR_cpi, + AVR_sbci, + AVR_subi, + AVR_ori, + AVR_andi, + }; + insn.itype = itypes[(code >> 12) - 3]; + opreg(insn.Op1, ((code >> 4) & 15) + 16); + opimm(insn, insn.Op2, (code & 0x0F) | ((code >> 4) & 0xF0)); + } + break; + + case 8: + case 10: +// 10q0 qq0d dddd 0qqq ldd rd, Z+q +// 10q0 qq0d dddd 1qqq ldd rd, Y+q +// 10q0 qq1r rrrr 0qqq std Z+d, rr +// 10q0 qq1r rrrr 1qqq std Y+d, rr +// 1000 000d dddd 0000 ld rd, Z +// 1000 000d dddd 1000 ld rd, Y +// 1000 001r rrrr 0000 st Z, rr +// 1000 001r rrrr 1000 st Y, rr + { + int delta = ((code & 0x2000) >> 8) + | ((code & 0x0C00) >> 7) + | (code & 0x0007); + if ( code & 0x200 ) + { + insn.itype = delta ? AVR_std : AVR_st; + opdisp(insn.Op1, (code & 8) ? PH_Y : PH_Z, delta); + opregd(insn.Op2, code); + } + else + { + insn.itype = delta ? AVR_ldd : AVR_ld; + opregd(insn.Op1, code); + opdisp(insn.Op2, (code & 8) ? PH_Y : PH_Z, delta); + } + } + break; + + case 9: + switch ( (code >> 8) & 15 ) + { + case 0: + case 1: + case 2: + case 3: +// 1001 000d dddd 0000(8*k)lds rd, k 0 +// 1001 000d dddd 0001 ld rd, Z+ 1 +// 1001 000d dddd 0010 ld rd, -Z 2 +// 1001 000d dddd 0100 lpm Rd, Z 4 +// 1001 000d dddd 0101 lpm Rd, Z+ 5 +// 1001 000d dddd 0110 elpm Rd, Z 6 +// 1001 000d dddd 0111 elpm Rd, Z+ 7 +// 1001 000d dddd 1001 ld rd, Y+ 9 +// 1001 000d dddd 1010 ld rd, -Y A +// 1001 000d dddd 1100 ld rd, X C +// 1001 000d dddd 1101 ld rd, X+ D +// 1001 000d dddd 1110 ld rd, -X E +// 1001 000d dddd 1111 pop rd F + +// 1001 001d dddd 0000(8*k)sts k, rd 0 +// 1001 001r rrrr 0001 st Z+, rr 1 +// 1001 001r rrrr 0010 st -Z, rr 2 +// 1001 001r rrrr 0011 <unallocated> 3 +// 1001 001r rrrr 0100 xch Z, rr 4 +// 1001 001r rrrr 0101 las Z, rr 5 +// 1001 001r rrrr 0110 lac Z, rr 6 +// 1001 001r rrrr 0111 lat Z, rr 7 +// 1001 001r rrrr 1000 <unallocated> 8 +// 1001 001r rrrr 1001 st Y+, rr 9 +// 1001 001r rrrr 1010 st -Y, rr A +// 1001 001r rrrr 1100 st X, rr C +// 1001 001r rrrr 1101 st X+, rr D +// 1001 001r rrrr 1110 st -X, rr E +// 1001 001d dddd 1111 push rd F + { + static const uchar itypes[] = + { + AVR_lds, AVR_ld, AVR_ld, 0, + AVR_lpm, AVR_lpm, AVR_elpm, AVR_elpm, + 0, AVR_ld, AVR_ld, 0, + AVR_ld, AVR_ld, AVR_ld, AVR_pop + }; + insn.itype = itypes[code & 15]; + opregd(insn.Op1, code); + switch ( code & 15 ) + { + case 0x0: + opmem(insn, insn.Op2); + switch ( helper.charval_ea(insn.ea+1, ELF_AVR_TAG) ) + { + case ELF_AVR_EEP_OFF: + insn.Op2.addr += ELF_AVR_EEPROMBASE-ELF_AVR_RAMBASE; + case ELF_AVR_RAM_OFF: + insn.Op2.addr += ELF_AVR_RAMBASE; + default: + break; + } + break; + case 0x1: opphr(insn.Op2, PH_ZPLUS); break; + case 0x2: opphr(insn.Op2, PH_MINUSZ); break; + case 0x4: opphr(insn.Op2, PH_Z); break; + case 0x5: opphr(insn.Op2, PH_ZPLUS); break; + case 0x6: opphr(insn.Op2, PH_Z); break; + case 0x7: opphr(insn.Op2, PH_ZPLUS); break; + case 0x9: opphr(insn.Op2, PH_YPLUS); break; + case 0xA: opphr(insn.Op2, PH_MINUSY); break; + case 0xC: opphr(insn.Op2, PH_X); break; + case 0xD: opphr(insn.Op2, PH_XPLUS); break; + case 0xE: opphr(insn.Op2, PH_MINUSX); break; + case 0xF: break; + default: + return 0; + } + if ( code & 0x200 ) + { + switch ( insn.itype ) + { + case AVR_pop: + insn.itype = AVR_push; + break; + case AVR_lds: + insn.itype = AVR_sts; + goto SWAP_OPERANDS; + case AVR_ld: + insn.itype = AVR_st; +SWAP_OPERANDS: + { + op_t tmp = insn.Op1; + insn.Op1 = insn.Op2; + insn.Op2 = tmp; + } + break; + case AVR_lpm: + case AVR_elpm: +// 1001 001r rrrr 0100 xch Z, rr 4 +// 1001 001r rrrr 0101 las Z, rr 5 +// 1001 001r rrrr 0110 lac Z, rr 6 +// 1001 001r rrrr 0111 lat Z, rr 7 + { + static const uchar itypes2[] = + { + AVR_xch, AVR_las, AVR_lac, AVR_lat, + }; + insn.itype = itypes2[code & 3]; + opphr(insn.Op1, PH_Z); + opregd(insn.Op2, code); + } + break; + } + } + } + break; + + case 4: + case 5: + switch ( code & 0xF ) + { + case 11: +// 1001 0100 KKKK 1011 des K + switch ( code & 0x0F00 ) + { + case 0x0400: + insn.itype = AVR_des; + opimm(insn, insn.Op1, (code >> 4) & 0xF); + break; + default: return 0; + } + break; + case 9: +// 1001 0100 0000 1001 ijmp +// 1001 0100 0001 1001 eijmp +// 1001 0101 0000 1001 icall +// 1001 0101 0001 1001 eicall + switch ( code & 0xFF0 ) + { + case 0x400: insn.itype = AVR_ijmp; break; + case 0x410: insn.itype = AVR_eijmp; break; + case 0x500: insn.itype = AVR_icall; break; + case 0x510: insn.itype = AVR_eicall; break; + default: return 0; + } + break; + case 8: +// 1001 0101 0xx0 1000 ret +// 1001 0101 0xx1 1000 reti +// 1001 0101 100x 1000 sleep +// 1001 0101 101x 1000 wdr +// 1001 0101 1100 1000 lpm +// 1001 0101 1101 1000 elpm +// 1001 0101 1110 1000 spm +// 1001 0101 1111 1000 espm + if ( (code & 0x0F00) == 0x0500 ) + { + if ( (code & 0x0090) == 0x0000 ) + insn.itype = AVR_ret; + else if ( (code & 0x0090) == 0x0010 ) + insn.itype = AVR_reti; + else if ( (code & 0x00E0) == 0x0080 ) + insn.itype = AVR_sleep; + else if ( (code & 0x00E0) == 0x00A0 ) + insn.itype = AVR_wdr; + else if ( (code & 0x00F0) == 0x00C0 ) + insn.itype = AVR_lpm; + else if ( (code & 0x00F0) == 0x00D0 ) + insn.itype = AVR_elpm; + else if ( (code & 0x00F0) == 0x00E0 ) + insn.itype = AVR_spm; + else if ( (code & 0x00F0) == 0x00F0 ) + insn.itype = AVR_espm; + break; + } +// 1001 0100 0000 1000 sec 0 +// 1001 0100 0001 1000 sez 1 +// 1001 0100 0010 1000 sen 2 +// 1001 0100 0011 1000 sev 3 +// 1001 0100 0100 1000 ses 4 +// 1001 0100 0101 1000 seh 5 +// 1001 0100 0110 1000 set 6 +// 1001 0100 0111 1000 sei 7 +// 1001 0100 0sss 1000 bset s +// 1001 0100 1000 1000 clc 8 +// 1001 0100 1001 1000 clz 9 +// 1001 0100 1010 1000 cln a +// 1001 0100 1011 1000 clv b +// 1001 0100 1100 1000 cls c +// 1001 0100 1101 1000 clh d +// 1001 0100 1110 1000 clt e +// 1001 0100 1111 1000 cli f +// 1001 0100 1sss 1000 bclr s + { + static const uchar itypes[] = + { + AVR_sec, AVR_sez, AVR_sen, AVR_sev, + AVR_ses, AVR_seh, AVR_set, AVR_sei, + AVR_clc, AVR_clz, AVR_cln, AVR_clv, + AVR_cls, AVR_clh, AVR_clt, AVR_cli, + }; + insn.itype = itypes[(code >> 4) & 15]; + } + break; // case 8 + + case 0: + case 1: + case 2: + case 3: + case 5: + case 6: + case 7: + case 10: +// 1001 010d dddd 0000 com rd 0 +// 1001 010d dddd 0001 neg rd 1 +// 1001 010d dddd 0010 swap rd 2 +// 1001 010d dddd 0011 inc rd 3 +// 1001 010d dddd 0101 asr rd 5 +// 1001 010d dddd 0110 lsr rd 6 +// 1001 010d dddd 0111 ror rd 7 +// 1001 010d dddd 1010 dec rd 10 + { + static const uchar itypes[] = + { + AVR_com, AVR_neg, AVR_swap, AVR_inc, + 0, AVR_asr, AVR_lsr, AVR_ror, + 0, 0, AVR_dec, + }; + insn.itype = itypes[code & 15]; + opregd(insn.Op1, code); + } + break; // case 8 + + case 12: + case 13: + case 14: + case 15: +// 1001 010k kkkk 110k(1*k)jmp k +// 1001 010k kkkk 111k(1*k)call k + insn.itype = (code & 2) ? AVR_call : AVR_jmp; + opnear(insn.Op1, (ea_t((code & 1) | ((code >> 3) & 0x3E)) << 16) + | ua_next_full_byte(insn)); + if ( helper.charval_ea(insn.ea+1, ELF_AVR_TAG) == ELF_AVR_ABS_OFF ) + insn.Op1.addr += ELF_AVR_ABSBASE; + break; + } + break; + + case 6: + case 7: +// 1001 0110 kkdd kkkk adiw rd, k (d=24,26,28,30) +// 1001 0111 kkdd kkkk sbiw rd, k (d=24,26,28,30) + insn.itype = (code & 0x100) ? AVR_sbiw : AVR_adiw; + opreg(insn.Op1, R24 + ((code >> 3) & 6), true); + opimm(insn, insn.Op2, ((code >> 2) & 0x30) | (code & 0x0F)); + break; + + case 8: + case 9: + case 10: + case 11: +// 1001 1000 pppp pbbb cbi p, b +// 1001 1001 pppp pbbb sbic p, b +// 1001 1010 pppp pbbb sbi p, b +// 1001 1011 pppp pbbb sbis p, b + { + static const uchar itypes[] = { AVR_cbi, AVR_sbic, AVR_sbi, AVR_sbis }; + insn.itype = itypes[(code >> 8) & 3]; + opport(insn.Op1, (code >> 3) & 0x1F); + opimm(insn, insn.Op2, code & 7); + } + break; + + case 12: + case 13: + case 14: + case 15: +// 1001 11rd dddd rrrr mul rd, rr + insn.itype = AVR_mul; + tworegs(insn, code); + break; + } + break; + + case 11: +// 1011 0ppd dddd pppp in rd, p +// 1011 1ppr rrrr pppp out p, rr + if ( code & 0x800 ) + { + insn.itype = AVR_out; + opport(insn.Op1, ((code & 0x0600) >> 5) | (code & 15)); + opregd(insn.Op2, code); + } + else + { + insn.itype = AVR_in; + opregd(insn.Op1, code); + opport(insn.Op2, ((code & 0x0600) >> 5) | (code & 15)); + } + break; + + case 12: + case 13: +// 1100 kkkk kkkk kkkk rjmp k +// 1101 kkkk kkkk kkkk rcall k + { + insn.itype = (code & 0x1000) ? AVR_rcall : AVR_rjmp; + signed int delta = (code & 0xFFF); + if ( delta & 0x800 ) + delta |= ~0xFFF; + opnear(insn.Op1, code_address(insn, delta)); + } + break; + + case 14: +// 1110 1111 dddd 1111 ser rd (16<=d<=31) +// 1110 kkkk dddd kkkk ldi rd, k + { + insn.itype = AVR_ldi; + opreg(insn.Op1, ((code >> 4) & 15) + 16); + int x = ((code >> 4) & 0xF0) | (code & 0x0F); + if ( x == 0xFF && !exists_fixup(insn.ea) ) + { + insn.itype = AVR_ser; + break; + } + opimm(insn, insn.Op2, x); + } + break; + + case 15: + switch ( (code >> 9) & 7 ) + { + case 0: + case 1: + case 2: + case 3: +// 1111 00kk kkkk k000 brcs/brlo k +// 1111 00kk kkkk k001 breq k +// 1111 00kk kkkk k010 brmi k +// 1111 00kk kkkk k011 brvs k +// 1111 00kk kkkk k100 brlt k +// 1111 00kk kkkk k101 brhs k +// 1111 00kk kkkk k110 brts k +// 1111 00kk kkkk k111 brie k +// 1111 00kk kkkk ksss brbs s, k +// 1111 01kk kkkk k000 brcc/brsh k +// 1111 01kk kkkk k001 brne k +// 1111 01kk kkkk k010 brpl k +// 1111 01kk kkkk k011 brvc k +// 1111 01kk kkkk k100 brge k +// 1111 01kk kkkk k101 brhc k +// 1111 01kk kkkk k110 brtc k +// 1111 01kk kkkk k111 brid k +// 1111 01kk kkkk ksss brbc s, k + { + static const uchar itypes[] = + { + AVR_brcs, AVR_breq, AVR_brmi, AVR_brvs, + AVR_brlt, AVR_brhs, AVR_brts, AVR_brie, + AVR_brcc, AVR_brne, AVR_brpl, AVR_brvc, + AVR_brge, AVR_brhc, AVR_brtc, AVR_brid, + }; + insn.itype = itypes[((code >> 7) & 8) | (code & 7)]; + signed int delta = (code >> 3) & 0x7F; + if ( delta & 0x40 ) + delta |= ~0x7F; + opnear(insn.Op1, code_address(insn, delta)); + } + break; + case 4: +// 1111 100d dddd 0bbb bld rd, b + if ( code & 8 ) + return 0; + insn.itype = AVR_bld; + goto REGBIT; + case 5: +// 1111 101d dddd Xbbb bst rd, b + insn.itype = AVR_bst; + goto REGBIT; + case 6: +// 1111 110r rrrr xbbb sbrc rr, b + insn.itype = AVR_sbrc; + goto REGBIT; + case 7: + insn.itype = AVR_sbrs; +// 1111 111r rrrr xbbb sbrs rr, b +REGBIT: + opregd(insn.Op1, code); + opimm(insn, insn.Op2, code & 7); + break; + } + break; + } + if ( insn.itype == AVR_null ) + return 0; + return insn.size; +} diff --git a/idasdk76/module/avr/avr.cfg b/idasdk76/module/avr/avr.cfg new file mode 100644 index 0000000..70d7f60 --- /dev/null +++ b/idasdk76/module/avr/avr.cfg @@ -0,0 +1,17813 @@ +; +; New directives: +; +; RAM=xxxx ;Maximum # bytes of RAM for this part +; ROM=xxxx ;# 8-bit bytes of ROM for this part +; EEPROM=xxxx ;# 8-bit bytes of EEPROM for this part +; +; Please note that the ROM size must be declared as the double of the addressable +; size because it is in bytes +; +; Information in this file came from the August, 1999 Atmel AVR databook +; Information was updated based on GCC/binutils information in Jan 2021 +; + +; +; this file defines the i/o port definitions for amtel's avr processors. +; the i/o port definitions are provided for each avr device +; each device definition begins with a line like this: +; +; .devicename +; +; after it go the port definitions in this format: +; +; portname address +; +; lines beginning with a space are ignored. +; comment lines should be started with ';' character. +; +; the default device is specified at the start of the file +; +; SUBARCH corresponds to the __AVR_ARCH__ value used in GCC toolchain +; +; Last update 2021-01-27: +; gcc - https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=gcc/config/avr/avr-devices.c;hb=HEAD +; gcc-doc - https://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html +; binutils - https://sourceware.org/git/?p=binutils-gdb.git;a=blob;f=gas/config/tc-avr.c;hb=HEAD) +; +; The following values are defined (Check latest GCC/binutils if your chip is missing): +; +; 1: avr1 - classic AVR core without data RAM +; MCU types: attiny11, attiny12, attiny15, attiny28, at90s1200 +; +; 2: avr2 - classic AVR core with up to 8K program memory +; MCU types: attiny22, attiny26, at90s2313, at90s2323, at90s2333, at90s2343, +; at90s4414, at90s4433, at90s4434, at90c8534, at90s8515, at90s8535 +; +; 25: avr25 - classic AVR core with up to 8K program memory plus the MOVW instruction +; MCU types: attiny13, attiny13a, attiny24, attiny24a, attiny25, attiny261, attiny261a, +; attiny2313, attiny2313a, attiny43u, attiny44, attiny44a, attiny45, attiny48, +; attiny441, attiny461, attiny461a, attiny4313, attiny84, attiny84a, attiny85, +; attiny87, attiny88, attiny828, attiny841, attiny861, attiny861a, ata5272, +; ata6616c, at86rf401 +; +; 3: avr3 - classic AVR core with up to 64K program memory +; MCU types: at76c711, at43usb355 +; +; 31: avr31 - classic AVR core with up to 128K program memory +; MCU types: atmega103, at43usb320 +; +; 35: avr35 - classic AVR core with up to 64K program memory plus MOVW, CALL, and JMP instructions +; MCU types: attiny167, attiny1634, atmega8u2, atmega16u2, atmega32u2, ata5505, ata6617c, +; ata664251, at90usb82, at90usb162 +; +; 4: avr4 - enhanced AVR core with up to 8K program memory +; MCU types: atmega48, atmega48a, atmega48p, atmega48pa, atmega48pb, atmega8, atmega8a, +; atmega8hva, atmega88, atmega88a, atmega88p, atmega88pa, atmega88pb, atmega8515, +; atmega8535, ata6285, ata6286, ata6289, ata6612c, at90pwm1, at90pwm2, at90pwm2b, +; at90pwm3, at90pwm3b, at90pwm81 +; +; 5: avr5 - enhanced AVR core with up to 64K program memory +; MCU types: atmega16, atmega16a, atmega16hva, atmega16hva2, atmega16hvb, atmega16hvbrevb, +; atmega16m1, atmega16u4, atmega161, atmega162, atmega163, atmega164a, atmega164p, +; atmega164pa, atmega165, atmega165a, atmega165p, atmega165pa, atmega168, atmega168a, +; atmega168p, atmega168pa, atmega168pb, atmega169, atmega169a, atmega169p, atmega169pa, +; atmega32, atmega32a, atmega32c1, atmega32hvb, atmega32hvbrevb, atmega32m1, atmega32u4, +; atmega32u6, atmega323, atmega324a, atmega324p, atmega324pa, atmega325, atmega325a, +; atmega325p, atmega325pa, atmega328, atmega328p, atmega328pb, atmega329, atmega329a, +; atmega329p, atmega329pa, atmega3250, atmega3250a, atmega3250p, atmega3250pa, atmega3290, +; atmega3290a, atmega3290p, atmega3290pa, atmega406, atmega64, atmega64a, atmega64c1, +; atmega64hve, atmega64hve2, atmega64m1, atmega64rfr2, atmega640, atmega644, atmega644a, +; atmega644p, atmega644pa, atmega644rfr2, atmega645, atmega645a, atmega645p, atmega649, +; atmega649a, atmega649p, atmega6450, atmega6450a, atmega6450p, atmega6490, atmega6490a, +; atmega6490p, ata5795, ata5790, ata5790n, ata5791, ata6613c, ata6614q, ata5782, ata5831, +; ata8210, ata8510, ata5702m322, at90pwm161, at90pwm216, at90pwm316, at90can32, at90can64, +; at90scr100, at90usb646, at90usb647, at94k, m3000 +; +; 51: avr51 - enhanced AVR core with up to 128K program memory +; MCU types: atmega128, atmega128a, atmega128rfa1, atmega128rfr2, atmega1280, atmega1281, +; atmega1284, atmega1284p, atmega1284rfr2, at90can128, at90usb1286, at90usb1287 +; +; 6: avr6 - enhanced AVR core with up to 256K program memory and a 3-byte PC +; MCU types: atmega256rfr2, atmega2560, atmega2561, atmega2564rfr2 +; +; 100: avrtiny - Tiny core with 512B up to 4K of program memory and 16 gp registers +; MCU types: attiny4, attiny5, attiny9, attiny10, attiny20, attiny40 +; 101: avrxmega1 - XMega core with up to 8K program memory +; MCU types: currently none(?) +; 102: avrxmega2 - XMega core with 8K to 64K program memory and less than 64K RAM +; MCU types: atxmega8e5, atxmega16a4, atxmega16a4u, atxmega16c4, atxmega16d4, atxmega16e5, +; atxmega32a4, atxmega32a4u, atxmega32c3, atxmega32c4, atxmega32d3, atxmega32d4, +; atxmega32e5 +; +; 103: avrxmega3 - XMega core with 8K to 64K program memory and more than 64K RAM +; MCU types: attiny202, attiny204, attiny212, attiny214, attiny402, attiny404, attiny406, +; attiny412, attiny414, attiny416, attiny417, attiny804, attiny806, attiny807, +; attiny814, attiny816, attiny817, attiny1604, attiny1606, attiny1607, attiny1614, +; attiny1616, attiny1617, attiny3214, attiny3216, attiny3217, atmega808, atmega809, +; atmega1608, atmega1609, atmega3208, atmega3209, atmega4808, atmega4809 +; +; 104: avrxmega4 - XMega core with 64K to 128K program memory and less than 64K RAM +; MCU types: atxmega64a3, atxmega64a3u, atxmega64a4u, atxmega64b1, atxmega64b3, atxmega64c3, +; atxmega64d3, atxmega64d4 +; +; 105: avrxmega5 - XMega core with 64K to 128K program memory and more than 64K RAM +; MCU types: atxmega64a1, atxmega64a1u +; +; 106: avrxmega6 - XMega core with 128K to 256K program memory and less than 64K RAM +; MCU types: atxmega128a3, atxmega128a3u, atxmega128b1, atxmega128b3, atxmega128c3, atxmega128d3, +; atxmega128d4, atxmega192a3, atxmega192a3u, atxmega192c3, atxmega192d3, atxmega256a3, +; atxmega256a3b, atxmega256a3bu, atxmega256a3u, atxmega256c3, atxmega256d3, atxmega384c3, +; atxmega384d3 +; +; 107: avrxmega7 - XMega core with 128K to 256K program memory and more than 64K RAM +; MCU types: atxmega128a1, atxmega128a1u, atxmega128a4u + +.default AT90S8515 + +.AT90C8534 +SUBARCH=2 +; doc1229.pdf +; + +RAM=256 +ROM=8192 +EEPROM=512 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0060 I/O registers +area DATA I_SRAM 0x0060:0x0160 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_OVF 0x0003 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0004 Timer/Counter0 Overflow +entry ADC_ 0x0005 ADC Conversion Complete +entry EE_RDY 0x0006 EEPROM Ready + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +ADCL 0x0004 ADC Data Register Low +ADCH 0x0005 ADC Data Register High +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Run Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Select Register +ADMUX.MUX2 2 Analog Channel Select Bit 2 +ADMUX.MUX1 1 Analog Channel Select Bit 1 +ADMUX.MUX0 0 Analog Channel Select Bit 0 +RESERVED0008 0x0008 RESERVED +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +GIPR 0x0010 General Interrupt Pin Register +GIPR.IPIN1 3 External Interrupt Pin 1 +GIPR.IPIN0 2 External Interrupt Pin 0 +RESERVED0011 0x0011 RESERVED +RESERVED0012 0x0012 RESERVED +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +RESERVED0016 0x0016 RESERVED +RESERVED0017 0x0017 RESERVED +RESERVED0018 0x0018 RESERVED +RESERVED0019 0x0019 RESERVED +DDRA 0x001A Port A Data Direction Register +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 +EEARL.EEAR6 6 +EEARL.EEAR5 5 +EEARL.EEAR4 4 +EEARL.EEAR3 3 +EEARL.EEAR2 2 +EEARL.EEAR1 1 +EEARL.EEAR0 0 +EEARH 0x001F EEPROM Address Register High +RESERVED0020 0x0020 RESERVED +RESERVED0021 0x0021 RESERVED +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +TCNT1L 0x002C Timer/Counter1 Low +TCNT1H 0x002D Timer/Counter1 High +TCCR1 0x002E Timer/Counter1 Control Register +TCCR1.CS12 2 Clock Select1, Bit 2 +TCCR1.CS11 1 Clock Select1, Bit 1 +TCCR1.CS10 0 Clock Select1, Bit 0 +RESERVED002F 0x002F RESERVED +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +RESERVED0034 0x0034 RESERVED +MCUCR 0x0035 MCU Control Register +MCUCR.SE 6 Sleep Enable +MCUCR.SM 5 Sleep Mode +MCUCR.ISC1 2 Interrupt Sense Control 1 +MCUCR.ISC0 0 Interrupt Sense Control 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer Low +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; RESERVED0023 0x0023 RESERVED +; ADCL 0x0024 ADC Data Register Low +; ADCH 0x0025 ADC Data Register High +; ADCSR 0x0026 ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADFR 5 ADC Free Run Select +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Select Register +; ADMUX.MUX2 2 Analog Channel Select Bit 2 +; ADMUX.MUX1 1 Analog Channel Select Bit 1 +; ADMUX.MUX0 0 Analog Channel Select Bit 0 +; RESERVED0028 0x0028 RESERVED +; RESERVED0029 0x0029 RESERVED +; RESERVED002A 0x002A RESERVED +; RESERVED002B 0x002B RESERVED +; RESERVED002C 0x002C RESERVED +; RESERVED002D 0x002D RESERVED +; RESERVED002E 0x002E RESERVED +; RESERVED002F 0x002F RESERVED +; GIPR 0x0030 General Interrupt Pin Register +; GIPR.IPIN1 3 External Interrupt Pin 1 +; GIPR.IPIN0 2 External Interrupt Pin 0 +; RESERVED0031 0x0031 RESERVED +; RESERVED0032 0x0032 RESERVED +; RESERVED0033 0x0033 RESERVED +; RESERVED0034 0x0034 RESERVED +; RESERVED0035 0x0035 RESERVED +; RESERVED0036 0x0036 RESERVED +; RESERVED0037 0x0037 RESERVED +; RESERVED0038 0x0038 RESERVED +; RESERVED0039 0x0039 RESERVED +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 +; EEARL.EEAR6 6 +; EEARL.EEAR5 5 +; EEARL.EEAR4 4 +; EEARL.EEAR3 3 +; EEARL.EEAR2 2 +; EEARL.EEAR1 1 +; EEARL.EEAR0 0 +; EEARH 0x003F EEPROM Address Register High +; RESERVED0040 0x0040 RESERVED +; RESERVED0041 0x0041 RESERVED +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; RESERVED0044 0x0044 RESERVED +; RESERVED0045 0x0045 RESERVED +; RESERVED0046 0x0046 RESERVED +; RESERVED0047 0x0047 RESERVED +; RESERVED0048 0x0048 RESERVED +; RESERVED0049 0x0049 RESERVED +; RESERVED004A 0x004A RESERVED +; RESERVED004B 0x004B RESERVED +; TCNT1L 0x004C Timer/Counter1 Low +; TCNT1H 0x004D Timer/Counter1 High +; TCCR1 0x004E Timer/Counter1 Control Register +; TCCR1.CS12 2 Clock Select1, Bit 2 +; TCCR1.CS11 1 Clock Select1, Bit 1 +; TCCR1.CS10 0 Clock Select1, Bit 0 +; RESERVED004F 0x004F RESERVED +; RESERVED0050 0x0050 RESERVED +; RESERVED0051 0x0051 RESERVED +; TCNT0 0x0052 Timer Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; RESERVED0054 0x0054 RESERVED +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 6 Sleep Enable +; MCUCR.SM 5 Sleep Mode +; MCUCR.ISC1 2 Interrupt Sense Control 1 +; MCUCR.ISC0 0 Interrupt Sense Control 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED005C 0x005C RESERVED +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer Low +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.AT90S1200 +SUBARCH=1 +; doc0838.pdf +; + +RAM=0 +ROM=1024 +EEPROM=64 + + +; MEMORY MAP + + +; Interrupt and reset vector assignments + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +PIND 0x0010 Port D Input Pins Address +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pin Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.MSB 7 +EEDR.LSB 0 +EEAR 0x001E EEPROM Address Register +EEAR.EEAR5 5 EEPROM Address 5 +EEAR.EEAR4 4 EEPROM Address 4 +EEAR.EEAR3 3 EEPROM Address 3 +EEAR.EEAR2 2 EEPROM Address 2 +EEAR.EEAR1 1 EEPROM Address 1 +EEAR.EEAR0 0 EEPROM Address 0 +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +RESERVED002C 0x002C RESERVED +RESERVED002D 0x002D RESERVED +RESERVED002E 0x002E RESERVED +RESERVED002F 0x002F RESERVED +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer/Counter0 +TCNT0.MSB 7 +TCNT0.LSB 0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +RESERVED0034 0x0034 RESERVED +MCUCR 0x0035 MCU Control Register +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC01 1 Interrupt Sense Control Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt FLAG Register +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +RESERVED003A 0x003A RESERVED +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +RESERVED003D 0x003D RESERVED +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + + +.AT90S2313 +SUBARCH=2 +; doc0839.pdf +; + +RAM=128 +ROM=2048 +EEPROM=128 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0080 I/O registers +area DATA SRAM_ 0x0080:0x00E0 SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Processor reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_CAPT1 0x0003 Timer/Counter1 Capture Event +entry TIMER1_COMP1 0x0004 Timer/Counter1 Compare Match +entry TIMER1_OVF1 0x0005 Timer/Counter1 Overflow +entry TIMER0_OVF0 0x0006 Timer/Counter0 Overflow +entry UART_RX 0x0007 UART, RX Complete +entry UART_UDRE 0x0008 UART Data Register Empty +entry UART_TX 0x0009 UART, TX Complete +entry ANA_COMP 0x000A Analog Comparator + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR 0x0009 UART Baud Rate Register +UCR 0x000A UART Control Register +UCR.RXCIE 7 RX Complete Interrupt Enable +UCR.TXCIE 6 TX Complete Interrupt Enable +UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +UCR.RXEN 4 Receiver Enable +UCR.TXEN 3 Transmitter Enable +UCR.CHR9 2 9 Bit Characters +UCR.RXB8 1 Receive Data Bit 8 +UCR.TXB8 0 Transmit Data Bit 8 +USR 0x000B UART Status Register +USR.RXC 7 UART Receive Complete +USR.TXC 6 UART Transmit Complete +USR.UDRE 5 UART Data Register Empty +USR.FE 4 Framing Error +USR.OR 3 OverRun +UDR 0x000C The UART I/O Data Register +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +PIND 0x0010 Port D Input Pins Address +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEAR 0x001E EEPROM Address Register +EEAR.EEAR6 6 EEPROM Address 6 +EEAR.EEAR5 5 EEPROM Address 5 +EEAR.EEAR4 4 EEPROM Address 4 +EEAR.EEAR3 3 EEPROM Address 3 +EEAR.EEAR2 2 EEPROM Address 2 +EEAR.EEAR1 1 EEPROM Address 1 +EEAR.EEAR0 0 EEPROM Address 0 +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +ICR1L 0x0024 Timer/Counter1 Input Capture Register low +ICR1H 0x0025 Timer/Counter1 Input Capture Register high +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +OCR1AL 0x002A Timer/Counter1 Output Compare Register A low +OCR1AH 0x002B Timer/Counter1 Output Compare Register A high +TCNT1L 0x002C Timer/Counter1 low +TCNT1H 0x002D Timer/Counter1 high +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1 Bit 2 +TCCR1B.CS11 1 Clock Select1 Bit 1 +TCCR1B.CS10 0 Clock Select1 Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1, Bits 1 +TCCR1A.COM1A0 6 Compare Output Mode1, Bits 0 +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 11 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 10 +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +RESERVED0034 0x0034 RESERVED +MCUCR 0x0035 MCU Control Register +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC11 3 InterruptSense Control 1 Bit 1 +MCUCR.ISC10 2 InterruptSense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt FLAG Register +TIFR.TOV1 7 Timer/Counter1 Overflow Flag +TIFR.OCF1A 6 Output Compare Flag 1A +TIFR.ICF1 3 Input Capture Flag 1 +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Match Interrupt Enable +TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt FLAG Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; RESERVED0023 0x0023 RESERVED +; RESERVED0024 0x0024 RESERVED +; RESERVED0025 0x0025 RESERVED +; RESERVED0026 0x0026 RESERVED +; RESERVED0027 0x0027 RESERVED +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR 0x0029 UART Baud Rate Register +; UCR 0x002A UART Control Register +; UCR.RXCIE 7 RX Complete Interrupt Enable +; UCR.TXCIE 6 TX Complete Interrupt Enable +; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +; UCR.RXEN 4 Receiver Enable +; UCR.TXEN 3 Transmitter Enable +; UCR.CHR9 2 9 Bit Characters +; UCR.RXB8 1 Receive Data Bit 8 +; UCR.TXB8 0 Transmit Data Bit 8 +; USR 0x002B UART Status Register +; USR.RXC 7 UART Receive Complete +; USR.TXC 6 UART Transmit Complete +; USR.UDRE 5 UART Data Register Empty +; USR.FE 4 Framing Error +; USR.OR 3 OverRun +; UDR 0x002C The UART I/O Data Register +; RESERVED002D 0x002D RESERVED +; RESERVED002E 0x002E RESERVED +; RESERVED002F 0x002F RESERVED +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; RESERVED0033 0x0033 RESERVED +; RESERVED0034 0x0034 RESERVED +; RESERVED0035 0x0035 RESERVED +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; RESERVED0039 0x0039 RESERVED +; RESERVED003A 0x003A RESERVED +; RESERVED003B 0x003B RESERVED +; EECR 0x003C EEPROM Control Register +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEAR 0x003E EEPROM Address Register +; EEAR.EEAR6 6 EEPROM Address 6 +; EEAR.EEAR5 5 EEPROM Address 5 +; EEAR.EEAR4 4 EEPROM Address 4 +; EEAR.EEAR3 3 EEPROM Address 3 +; EEAR.EEAR2 2 EEPROM Address 2 +; EEAR.EEAR1 1 EEPROM Address 1 +; EEAR.EEAR0 0 EEPROM Address 0 +; RESERVED003F 0x003F RESERVED +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; ICR1L 0x0044 Timer/Counter1 Input Capture Register low +; ICR1H 0x0045 Timer/Counter1 Input Capture Register high +; RESERVED0046 0x0046 RESERVED +; RESERVED0047 0x0047 RESERVED +; RESERVED0048 0x0048 RESERVED +; RESERVED0049 0x0049 RESERVED +; OCR1AL 0x004A Timer/Counter1 Output Compare Register A low +; OCR1AH 0x004B Timer/Counter1 Output Compare Register A high +; TCNT1L 0x004C Timer/Counter1 low +; TCNT1H 0x004D Timer/Counter1 high +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1 Bit 2 +; TCCR1B.CS11 1 Clock Select1 Bit 1 +; TCCR1B.CS10 0 Clock Select1 Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1, Bits 1 +; TCCR1A.COM1A0 6 Compare Output Mode1, Bits 0 +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 11 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 10 +; RESERVED0050 0x0050 RESERVED +; RESERVED0051 0x0051 RESERVED +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; RESERVED0054 0x0054 RESERVED +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM 4 Sleep Mode +; MCUCR.ISC11 3 InterruptSense Control 1 Bit 1 +; MCUCR.ISC10 2 InterruptSense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt FLAG Register +; TIFR.TOV1 7 Timer/Counter1 Overflow Flag +; TIFR.OCF1A 6 Output Compare Flag 1A +; TIFR.ICF1 3 Input Capture Flag 1 +; TIFR.TOV0 1 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Match Interrupt Enable +; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt FLAG Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED005C 0x005C RESERVED +; SPL 0x005D Stack Pointer +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; RESERVED005E 0x005E RESERVED +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.AT90S2323_43 +SUBARCH=2 +; doc1004.pdf +; + +RAM=128 +ROM=2048 +EEPROM=128 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0080 I/O registers +area DATA SRAM_ 0x0080:0x00E0 SRAM + + +; Interrupt and reset vector assignments + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +RESERVED0008 0x0008 RESERVED +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +RESERVED0010 0x0010 RESERVED +RESERVED0011 0x0011 RESERVED +RESERVED0012 0x0012 RESERVED +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEAR 0x001E EEPROM Address Register +EEAR.EEAR6 6 EEPROM Address 6 +EEAR.EEAR5 5 EEPROM Address 5 +EEAR.EEAR4 4 EEPROM Address 4 +EEAR.EEAR3 3 EEPROM Address 3 +EEAR.EEAR2 2 EEPROM Address 2 +EEAR.EEAR1 1 EEPROM Address 1 +EEAR.EEAR0 0 EEPROM Address 0 +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +RESERVED002C 0x002C RESERVED +RESERVED002D 0x002D RESERVED +RESERVED002E 0x002E RESERVED +RESERVED002F 0x002F RESERVED +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0 Bit 2 +TCCR0.CS01 1 Clock Select0 Bit 1 +TCCR0.CS00 0 Clock Select0 Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt FLAG Register +TIFR.TOV0 1 Timer/Counter 0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE0 1 Timer/Counter 0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF0 6 External Interrupt Flag 0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; RESERVED0023 0x0023 RESERVED +; RESERVED0024 0x0024 RESERVED +; RESERVED0025 0x0025 RESERVED +; RESERVED0026 0x0026 RESERVED +; RESERVED0027 0x0027 RESERVED +; RESERVED0028 0x0028 RESERVED +; RESERVED0029 0x0029 RESERVED +; RESERVED002A 0x002A RESERVED +; RESERVED002B 0x002B RESERVED +; RESERVED002C 0x002C RESERVED +; RESERVED002D 0x002D RESERVED +; RESERVED002E 0x002E RESERVED +; RESERVED002F 0x002F RESERVED +; RESERVED0030 0x0010 RESERVED +; RESERVED0031 0x0031 RESERVED +; RESERVED0032 0x0032 RESERVED +; RESERVED0033 0x0033 RESERVED +; RESERVED0034 0x0034 RESERVED +; RESERVED0035 0x0035 RESERVED +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; RESERVED0039 0x0039 RESERVED +; RESERVED003A 0x003A RESERVED +; RESERVED003B 0x003B RESERVED +; EECR 0x003C EEPROM Control Register +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEAR 0x003E EEPROM Address Register +; EEAR.EEAR6 6 EEPROM Address 6 +; EEAR.EEAR5 5 EEPROM Address 5 +; EEAR.EEAR4 4 EEPROM Address 4 +; EEAR.EEAR3 3 EEPROM Address 3 +; EEAR.EEAR2 2 EEPROM Address 2 +; EEAR.EEAR1 1 EEPROM Address 1 +; EEAR.EEAR0 0 EEPROM Address 0 +; RESERVED003F 0x003F RESERVED +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; RESERVED0044 0x0044 RESERVED +; RESERVED0045 0x0045 RESERVED +; RESERVED0046 0x0046 RESERVED +; RESERVED0047 0x0047 RESERVED +; RESERVED0048 0x0048 RESERVED +; RESERVED0049 0x0049 RESERVED +; RESERVED004A 0x004A RESERVED +; RESERVED004B 0x004B RESERVED +; RESERVED004C 0x004C RESERVED +; RESERVED004D 0x004D RESERVED +; RESERVED004E 0x004E RESERVED +; RESERVED004F 0x004F RESERVED +; RESERVED0050 0x0050 RESERVED +; RESERVED0051 0x0051 RESERVED +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.CS02 2 Clock Select0 Bit 2 +; TCCR0.CS01 1 Clock Select0 Bit 1 +; TCCR0.CS00 0 Clock Select0 Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM 4 Sleep Mode +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt FLAG Register +; TIFR.TOV0 1 Timer/Counter 0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE0 1 Timer/Counter 0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED005C 0x005C RESERVED +; SPL 0x005D Stack Pointer +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; RESERVED005E 0x005E RESERVED +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.AT90S8515 +SUBARCH=2 +; doc0841.pdf +; + +RAM=512 +ROM=8192 +EEPROM=512 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0060 I/O registers +area DATA I_SRAM 0x0060:0x0260 Internal SRAM +area DATA E_SRAM 0x0260:0x10000 External SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Reset, Power-on Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0005 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0006 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0007 Timer/Counter0 Overflow +entry SPI_STC 0x0008 Serial Transfer Complete +entry UART_RX 0x0009 UART, Rx Complete +entry UART_UDRE 0x000A UART Data Register Empty +entry UART_TX 0x000B UART, Tx Complete +entry ANA_COMP 0x000C Analog Comparator + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR 0x0009 UART BAUD Rate Register +UCR 0x000A UART Control Register +UCR.RXCIE 7 RX Complete Interrupt Enable +UCR.TXCIE 6 TX Complete Interrupt Enable +UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +UCR.RXEN 4 Receiver Enable +UCR.TXEN 3 Transmitter Enable +UCR.CHR9 2 9-bit Characters +UCR.RXB8 1 Receive Data Bit 8 +UCR.TXB8 0 Transmit Data Bit 8 +USR 0x000B UART Status Register +USR.RXC 7 UART Receive Complete +USR.TXC 6 UART Transmit Complete +USR.UDRE 5 UART Data Register Empty +USR.FE 4 Framing Error +USR.OR 3 Overrun +UDR 0x000C UART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write Collision Flag +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 +EEARL.EEAR6 6 +EEARL.EEAR5 5 +EEARL.EEAR4 4 +EEARL.EEAR3 3 +EEARL.EEAR2 2 +EEARL.EEAR1 1 +EEARL.EEAR0 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR8 8 +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +ICR1L 0x0024 Timer/Counter1 Input Capture Register Low +ICR1H 0x0025 Timer/Counter1 Input Capture Register High +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +OCR1BL 0x0028 Timer/Counter1 Output Compare Register Low +OCR1BH 0x0029 Timer/Counter1 Output Compare Register High +OCR1AL 0x002A Timer/Counter1 Output Compare Register Low +OCR1AH 0x002B Timer/Counter1 Output Compare Register High +TCNT1L 0x002C Timer/Counter1 Low +TCNT1H 0x002D Timer/Counter1 High +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1, Bit 2 +TCCR1B.CS11 1 Clock Select1, Bit 1 +TCCR1B.CS10 0 Clock Select1, Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +RESERVED0034 0x0034 RESERVED +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM Enable +MCUCR.SRW 6 External SRAM Wait State +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC11 3 Interrupt Sense Control 1, Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1, Bit +MCUCR.ISC01 1 Interrupt Sense Control 0, Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0, Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter1 Overflow Flag +TIFR.OCF1A 6 Output Compare Flag 1A +TIFR.OCIFB 5 Output Compare Flag 1B +TIFR.ICF1 3 Input Capture Flag 1 +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable +TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag1 +GIFR.INTF0 6 External Interrupt Flag0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; RESERVED0023 0x0023 RESERVED +; RESERVED0024 0x0024 RESERVED +; RESERVED0025 0x0025 RESERVED +; RESERVED0026 0x0026 RESERVED +; RESERVED0027 0x0027 RESERVED +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR 0x0029 UART BAUD Rate Register +; UCR 0x002A UART Control Register +; UCR.RXCIE 7 RX Complete Interrupt Enable +; UCR.TXCIE 6 TX Complete Interrupt Enable +; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +; UCR.RXEN 4 Receiver Enable +; UCR.TXEN 3 Transmitter Enable +; UCR.CHR9 2 9-bit Characters +; UCR.RXB8 1 Receive Data Bit 8 +; UCR.TXB8 0 Transmit Data Bit 8 +; USR 0x002B UART Status Register +; USR.RXC 7 UART Receive Complete +; USR.TXC 6 UART Transmit Complete +; USR.UDRE 5 UART Data Register Empty +; USR.FE 4 Framing Error +; USR.OR 3 Overrun +; UDR 0x002C UART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write Collision Flag +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 +; EEARL.EEAR6 6 +; EEARL.EEAR5 5 +; EEARL.EEAR4 4 +; EEARL.EEAR3 3 +; EEARL.EEAR2 2 +; EEARL.EEAR1 1 +; EEARL.EEAR0 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR8 8 +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; ICR1L 0x0044 Timer/Counter1 Input Capture Register Low +; ICR1H 0x0045 Timer/Counter1 Input Capture Register High +; RESERVED0046 0x0046 RESERVED +; RESERVED0047 0x0047 RESERVED +; OCR1BL 0x0048 Timer/Counter1 Output Compare Register Low +; OCR1BH 0x0049 Timer/Counter1 Output Compare Register High +; OCR1AL 0x004A Timer/Counter1 Output Compare Register Low +; OCR1AH 0x004B Timer/Counter1 Output Compare Register High +; TCNT1L 0x004C Timer/Counter1 Low +; TCNT1H 0x004D Timer/Counter1 High +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1, Bit 2 +; TCCR1B.CS11 1 Clock Select1, Bit 1 +; TCCR1B.CS10 0 Clock Select1, Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; RESERVED0050 0x0050 RESERVED +; RESERVED0051 0x0051 RESERVED +; TCNT0 0x0052 Timer Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; RESERVED0054 0x0054 RESERVED +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM Enable +; MCUCR.SRW 6 External SRAM Wait State +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM 4 Sleep Mode +; MCUCR.ISC11 3 Interrupt Sense Control 1, Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1, Bit +; MCUCR.ISC01 1 Interrupt Sense Control 0, Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0, Bit 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.TOV1 7 Timer/Counter1 Overflow Flag +; TIFR.OCF1A 6 Output Compare Flag 1A +; TIFR.OCIFB 5 Output Compare Flag 1B +; TIFR.ICF1 3 Input Capture Flag 1 +; TIFR.TOV0 1 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable +; TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable +; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag1 +; GIFR.INTF0 6 External Interrupt Flag0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED005C 0x005C RESERVED +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.AT90S_L4433 +SUBARCH=2 +; doc1042.pdf +; + +RAM=128 +ROM=4096 +EEPROM=256 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0080 I/O registers +area DATA SRAM_ 0x0080:0x00E0 SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event +entry TIMER1_COMP 0x0004 Timer/Counter1 Compare Match +entry TIMER1_OVF 0x0005 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0006 Timer/Counter0 Overflow +entry SPI_STC 0x0007 Serial Transfer Complete +entry UART_RX 0x0008 UART, Rx Complete +entry UART_UDRE 0x0009 UART Data Register Empty +entry UART_TX 0x000A UART, Tx Complete +entry ADC_ 0x000B ADC Conversion Complete +entry EE_RDY 0x000C EEPROM Ready +entry ANA_COMP 0x000D Analog Comparator + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +UBRRHI 0x0003 UART Baud Rate Register High +ADCL 0x0004 ADC Data Register low +ADCL.ADC7 7 +ADCL.ADC6 6 +ADCL.ADC5 5 +ADCL.ADC4 4 +ADCL.ADC3 3 +ADCL.ADC2 2 +ADCL.ADC1 1 +ADCL.ADC0 0 +ADCH 0x0005 ADC Data Register high +ADCH.ADC9 9 +ADCH.ADC8 8 +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Run Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Select Register +ADMUX.ADCBG 6 ADC Bandgap Select +ADMUX.MUX2 2 Analog Channel Select Bit 2 +ADMUX.MUX1 1 Analog Channel Select Bit 1 +ADMUX.MUX0 0 Analog Channel Select Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.AINBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR 0x0009 UART Baud Rate Register Low +UCSRB 0x000A UART Control and Status Register +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.CHR9 2 9-bit Characters +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B UART Control and Status Register A +UCSRA.RXC 7 UART Receive Complete +UCSRA.TXC 6 UART Transmit Complete +UCSRA.UDRE 5 UART Data Register Empty +UCSRA.FE 4 Framing Error +UCSRA.OR 3 OverRun +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C UART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write Collision Flag +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEAR 0x001E EEPROM Address Register +EEAR.EEAR7 7 +EEAR.EEAR6 6 +EEAR.EEAR5 5 +EEAR.EEAR4 4 +EEAR.EEAR3 3 +EEAR.EEAR2 2 +EEAR.EEAR1 1 +EEAR.EEAR0 0 +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +ICR1L 0x0026 Timer/Counter1 Input Capture Register Low +ICR1H 0x0027 Timer/Counter1 Input Capture Register High +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +OCR1L 0x002A Timer/Counter1 Output Compare Register Low +OCR1H 0x002B Timer/Counter1 Output Compare Register High +TCNT1L 0x002C Timer/Counter1 Low +TCNT1H 0x002D Timer/Counter1 High +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1 Bit 2 +TCCR1B.CS11 1 Clock Select1 Bit 1 +TCCR1B.CS10 0 Clock Select1 Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM11 7 Compare Output Mode1, Bit 1 +TCCR1A.COM10 6 Compare Output Mode1, Bit 0 +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer Counter 0 +TCCR0 0x0033 Timer/Counter 0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.WDRF 3 Watchdog Reset Flag +MCUSR.BORF 2 Brown-out Reset Flag +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter 1 Overflow Flag +TIFR.OCF1 6 Output Compare Flag 1 +TIFR.ICF1 3 Input Capture Flag 1 +TIFR.TOV0 1 Timer/Counter 0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +TIMSK.OCIE1 6 Timer/Counter1 Output Compare Match Interrupt Enable +TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SP 0x003D Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; UBRRHI 0x0023 UART Baud Rate Register High +; ADCL 0x0024 ADC Data Register low +; ADCL.ADC7 7 +; ADCL.ADC6 6 +; ADCL.ADC5 5 +; ADCL.ADC4 4 +; ADCL.ADC3 3 +; ADCL.ADC2 2 +; ADCL.ADC1 1 +; ADCL.ADC0 0 +; ADCH 0x0025 ADC Data Register high +; ADCH.ADC8 8 +; ADCH.ADC9 9 +; ADCSR 0x0026 ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADFR 5 ADC Free Run Select +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Select Register +; ADMUX.ADCBG 6 ADC Bandgap Select +; ADMUX.MUX2 2 Analog Channel Select Bit 2 +; ADMUX.MUX1 1 Analog Channel Select Bit 1 +; ADMUX.MUX0 0 Analog Channel Select Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.AINBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR 0x0029 UART Baud Rate Register Low +; UCSRB 0x002A UART Control and Status Register +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.CHR9 2 9-bit Characters +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B UART Control and Status Register A +; UCSRA.RXC 7 UART Receive Complete +; UCSRA.TXC 6 UART Transmit Complete +; UCSRA.UDRE 5 UART Data Register Empty +; UCSRA.FE 4 Framing Error +; UCSRA.OR 3 OverRun +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C UART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write Collision Flag +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; RESERVED0039 0x0039 RESERVED +; RESERVED003A 0x003A RESERVED +; RESERVED003B 0x003B RESERVED +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEAR 0x003E EEPROM Address Register +; EEAR.EEAR7 7 +; EEAR.EEAR6 6 +; EEAR.EEAR5 5 +; EEAR.EEAR4 4 +; EEAR.EEAR3 3 +; EEAR.EEAR2 2 +; EEAR.EEAR1 1 +; EEAR.EEAR0 0 +; RESERVED003F 0x003F RESERVED +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; RESERVED0044 0x0044 RESERVED +; RESERVED0045 0x0045 RESERVED +; ICR1L 0x0046 Timer/Counter1 Input Capture Register Low +; ICR1H 0x0047 Timer/Counter1 Input Capture Register High +; RESERVED0048 0x0048 RESERVED +; RESERVED0049 0x0049 RESERVED +; OCR1L 0x004A Timer/Counter1 Output Compare Register Low +; OCR1H 0x004B Timer/Counter1 Output Compare Register High +; TCNT1L 0x004C Timer/Counter1 Low +; TCNT1H 0x004D Timer/Counter1 High +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1 Bit 2 +; TCCR1B.CS11 1 Clock Select1 Bit 1 +; TCCR1B.CS10 0 Clock Select1 Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM11 7 Compare Output Mode1, Bit 1 +; TCCR1A.COM10 6 Compare Output Mode1, Bit 0 +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; RESERVED0050 0x0050 RESERVED +; RESERVED0051 0x0051 RESERVED +; TCNT0 0x0052 Timer Counter 0 +; TCCR0 0x0053 Timer/Counter 0 Control Register +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.WDRF 3 Watchdog Reset Flag +; MCUSR.BORF 2 Brown-out Reset Flag +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM 4 Sleep Mode +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.TOV1 7 Timer/Counter 1 Overflow Flag +; TIFR.OCF1 6 Output Compare Flag 1 +; TIFR.ICF1 3 Input Capture Flag 1 +; TIFR.TOV0 1 Timer/Counter 0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.OCIE1 6 Timer/Counter1 Output Compare Match Interrupt Enable +; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED005C 0x005C RESERVED +; SP 0x005D Stack Pointer +; SP.SP7 7 +; SP.SP6 6 +; SP.SP5 5 +; SP.SP4 4 +; SP.SP3 3 +; SP.SP2 2 +; SP.SP1 1 +; SP.SP0 0 +; RESERVED005E 0x005E RESERVED +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.AT90S_LS8535 +SUBARCH=2 +; doc1041.pdf +; + +RAM=512 +ROM=8192 +EEPROM=512 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0060 I/O registers +area DATA SRAM_ 0x0060:0x0260 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER2_COMP 0x0003 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0004 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0005 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0006 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0007 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0008 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0009 Timer/Counter0 Overflow +entry SPI_STC 0x000A SPI Serial Transfer Complete +entry UART_RX 0x000B UART, Rx Complete + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +ADCL 0x0004 ADC Data Register Low +ADCL.ADC7 7 Conversion result 7 +ADCL.ADC6 6 Conversion result 6 +ADCL.ADC5 5 Conversion result 5 +ADCL.ADC4 4 Conversion result 4 +ADCL.ADC3 3 Conversion result 3 +ADCL.ADC2 2 Conversion result 2 +ADCL.ADC1 1 Conversion result 1 +ADCL.ADC0 0 Conversion result 0 +ADCH 0x0005 ADC Data Register High +ADCH.ADC8 8 Conversion result 8 +ADCH.ADC9 9 Conversion result 9 +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Running Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Select Register +ADMUX.MUX2 2 Analog Channel Select Bit 2 +ADMUX.MUX1 1 Analog Channel Select Bit 1 +ADMUX.MUX0 0 Analog Channel Select Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR 0x0009 UART Baud Rate Register +UCR 0x000A UART Control Register +UCR.RXCIE 7 RX Complete Interrupt Enable +UCR.TXCIE 6 TX Complete Interrupt Enable +UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +UCR.RXEN 4 Receiver Enable +UCR.TXEN 3 Transmitter Enable +UCR.CHR9 2 9 Bit Characters +UCR.RXB8 1 Receive Data Bit 8 +UCR.TXB8 0 Transmit Data Bit 8 +USR 0x000B UART Status Register +USR.RXC 7 UART Receive Complete +USR.TXC 6 UART Transmit Complete +USR.UDRE 5 UART Data Register Empty +USR.FE 4 Framing Error +USR.OR 3 OverRun +UDR 0x000C UART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write Collision flag +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARH 0x001F EEPROM Address Register High +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +OCR2 0x0023 Timer/Counter2 Output Compare Register +TCNT2 0x0024 Timer/Counter2 +TCCR2 0x0025 Timer/Counter2 Control Register +TCCR2.PWM2 6 Pulse Width Modulator Enable +TCCR2.COM21 5 Compare Output Mode, Bits 1 +TCCR2.COM20 4 Compare Output Mode, Bits 0 +TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +TCCR2.CS22 2 Clock Select Bit 2 +TCCR2.CS21 1 Clock Select Bit 1 +TCCR2.CS20 0 Clock Select Bit 0 +ICR1L 0x0026 Timer/Counter1 Input Capture Register Low +ICR1H 0x0027 Timer/Counter1 Input Capture Register High +OCR1BL 0x0028 Timer/Counter1 Output Compare Register Low +OCR1BH 0x0029 Timer/Counter1 Output Compare Register High +OCR1AL 0x002A Timer/Counter1 Output Compare Register Low +OCR1AH 0x002B Timer/Counter1 Output Compare Register High +TCNT1L 0x002C Timer/Counter1 Low +TCNT1H 0x002D Timer/Counter1 High +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1, Bit 2 +TCCR1B.CS11 1 Clock Select1, Bit 1 +TCCR1B.CS10 0 Clock Select1, Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer Counter 0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 6 Sleep Enable +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Input Capture Flag 1 +TIFR.OCF1A 4 Output Compare Flag 1A +TIFR.OCF1B 3 Output Compare Flag 1B +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag1 +GIFR.INTF0 6 External Interrupt Flag0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; RESERVED0023 0x0023 RESERVED +; ADCL 0x0024 ADC Data Register Low +; ADCL.ADC7 7 Conversion result 7 +; ADCL.ADC6 6 Conversion result 6 +; ADCL.ADC5 5 Conversion result 5 +; ADCL.ADC4 4 Conversion result 4 +; ADCL.ADC3 3 Conversion result 3 +; ADCL.ADC2 2 Conversion result 2 +; ADCL.ADC1 1 Conversion result 1 +; ADCL.ADC0 0 Conversion result 0 +; ADCH 0x0025 ADC Data Register High +; ADCH.ADC8 8 Conversion result 8 +; ADCH.ADC9 9 Conversion result 9 +; ADCSR 0x0026 ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADFR 5 ADC Free Running Select +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Select Register +; ADMUX.MUX2 2 Analog Channel Select Bit 2 +; ADMUX.MUX1 1 Analog Channel Select Bit 1 +; ADMUX.MUX0 0 Analog Channel Select Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR 0x0029 UART Baud Rate Register +; UCR 0x002A UART Control Register +; UCR.RXCIE 7 RX Complete Interrupt Enable +; UCR.TXCIE 6 TX Complete Interrupt Enable +; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +; UCR.RXEN 4 Receiver Enable +; UCR.TXEN 3 Transmitter Enable +; UCR.CHR9 2 9 Bit Characters +; UCR.RXB8 1 Receive Data Bit 8 +; UCR.TXB8 0 Transmit Data Bit 8 +; USR 0x002B UART Status Register +; USR.RXC 7 UART Receive Complete +; USR.TXC 6 UART Transmit Complete +; USR.UDRE 5 UART Data Register Empty +; USR.FE 4 Framing Error +; USR.OR 3 OverRun +; UDR 0x002C UART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write Collision flag +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARH 0x003F EEPROM Address Register High +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; OCR2 0x0043 Timer/Counter2 Output Compare Register +; TCNT2 0x0044 Timer/Counter2 +; TCCR2 0x0045 Timer/Counter2 Control Register +; TCCR2.PWM2 6 Pulse Width Modulator Enable +; TCCR2.COM21 5 Compare Output Mode, Bits 1 +; TCCR2.COM20 4 Compare Output Mode, Bits 0 +; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +; TCCR2.CS22 2 Clock Select Bit 2 +; TCCR2.CS21 1 Clock Select Bit 1 +; TCCR2.CS20 0 Clock Select Bit 0 +; ICR1L 0x0046 Timer/Counter1 Input Capture Register Low +; ICR1H 0x0047 Timer/Counter1 Input Capture Register High +; OCR1BL 0x0048 Timer/Counter1 Output Compare Register Low +; OCR1BH 0x0049 Timer/Counter1 Output Compare Register High +; OCR1AL 0x004A Timer/Counter1 Output Compare Register Low +; OCR1AH 0x004B Timer/Counter1 Output Compare Register High +; TCNT1L 0x004C Timer/Counter1 Low +; TCNT1H 0x004D Timer/Counter1 High +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1, Bit 2 +; TCCR1B.CS11 1 Clock Select1, Bit 1 +; TCCR1B.CS10 0 Clock Select1, Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; RESERVED0050 0x0050 RESERVED +; RESERVED0051 0x0051 RESERVED +; TCNT0 0x0052 Timer Counter 0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 6 Sleep Enable +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Input Capture Flag 1 +; TIFR.OCF1A 4 Output Compare Flag 1A +; TIFR.OCF1B 3 Output Compare Flag 1B +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag1 +; GIFR.INTF0 6 External Interrupt Flag0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED003C 0x005C RESERVED +; SPL 0x005D Stack Pointer +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega103_L +SUBARCH=31 +; doc0945.pdf +; + +RAM=4096 +ROM=131072 +EEPROM=4096 + + +; MEMORY MAP +; Memory Configuration A +area DATA FSR_ 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x1000 Internal SRAM +; Memory Configuration B +; area DATA FSR_ 0x0000:0x0060 +; area DATA I_SRAM 0x0060:0x1000 Internal SRAM +; area DATA E_SRAM 0x1000:0x10000 External SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry INT3_ 0x0008 External Interrupt Request 3 +entry INT4_ 0x000A External Interrupt Request 4 +entry INT5_ 0x000C External Interrupt Request 5 +entry INT6_ 0x000E External Interrupt Request 6 +entry INT7_ 0x0010 External Interrupt Request 7 +entry TIMER2_COMP 0x0012 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0014 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0016 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0018 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x001A Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x001C Timer/Counter1 Overflow +entry TIMER0_COMP 0x001E Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow +entry SPI_STC 0x0022 SPI Serial Transfer Complete +entry UART_RX 0x0024 UART, Rx Complete +entry UART_UDRE 0x0026 UART Data Register Empty +entry UART_TX 0x0028 UART, Tx Complete +entry ADC_ 0x002A ADC Conversion Complete +entry EE_READY 0x002C EEPROM Ready +entry ANALOG_COMP 0x002E Analog Comparator + + +; INPUT/OUTPUT PORTS +PINF 0x0000 Port F Input Pins Address +PINF.PINF7 7 +PINF.PINF6 6 +PINF.PINF5 5 +PINF.PINF4 4 +PINF.PINF3 3 +PINF.PINF2 2 +PINF.PINF1 1 +PINF.PINF0 0 +PINE 0x0001 Port E Input Pins Address +PINE.PINE7 7 +PINE.PINE6 6 +PINE.PINE5 5 +PINE.PINE4 4 +PINE.PINE3 3 +PINE.PINE2 2 +PINE.PINE1 1 +PINE.PINE0 0 +DDRE 0x0002 Port E Data Direction Register +DDRE.DDE7 7 Port E Data Direction Register bit 7 +DDRE.DDE6 6 Port E Data Direction Register bit 6 +DDRE.DDE5 5 Port E Data Direction Register bit 5 +DDRE.DDE4 4 Port E Data Direction Register bit 4 +DDRE.DDE3 3 Port E Data Direction Register bit 3 +DDRE.DDE2 2 Port E Data Direction Register bit 2 +DDRE.DDE1 1 Port E Data Direction Register bit 1 +DDRE.DDE0 0 Port E Data Direction Register bit 0 +PORTE 0x0003 Port E Data Register +PORTE.PORTE7 7 Port E Data Register bit 7 +PORTE.PORTE6 6 Port E Data Register bit 6 +PORTE.PORTE5 5 Port E Data Register bit 5 +PORTE.PORTE4 4 Port E Data Register bit 4 +PORTE.PORTE3 3 Port E Data Register bit 3 +PORTE.PORTE2 2 Port E Data Register bit 2 +PORTE.PORTE1 1 Port E Data Register bit 1 +PORTE.PORTE0 0 Port E Data Register bit 0 +ADCL 0x0004 ADC Data Register Low +ADCL.ADC7 7 +ADCL.ADC6 6 +ADCL.ADC5 5 +ADCL.ADC4 4 +ADCL.ADC3 3 +ADCL.ADC2 2 +ADCL.ADC1 1 +ADCL.ADC0 0 +ADCH 0x0005 ADC Data Register High +ADCH.ADC9 9 +ADCH.ADC8 8 +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Select Register +ADMUX.MUX2 2 Analog Channel Select Bit 2 +ADMUX.MUX1 1 Analog Channel Select Bit 1 +ADMUX.MUX0 0 Analog Channel Select Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 6 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR 0x0009 UART Baud Rate Register +UCR 0x000A UART Control Register +UCR.RXCIE 7 RX Complete Interrupt Enable +UCR.TXCIE 6 TX Complete Interrupt Enable +UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +UCR.RXEN 4 Receiver Enable +UCR.TXEN 3 Transmitter Enable +UCR.CHR9 2 9-bit Characters +UCR.RXB8 1 Receive Data Bit 8 +UCR.TXB8 0 Transmit Data Bit 8 +USR 0x000B UART Status Register +USR.RXC 7 UART Receive Complete +USR.TXC 6 UART Transmit Complete +USR.UDRE 5 UART Data Register Empty +USR.FE 4 Framing Error +USR.OR 3 OverRun +UDR 0x000C UART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write Collision Flag +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +PORTC 0x0015 The Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 +EEARL.EEAR6 6 +EEARL.EEAR5 5 +EEARL.EEAR4 4 +EEARL.EEAR3 3 +EEARL.EEAR2 2 +EEARL.EEAR1 1 +EEARL.EEAR0 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR11 11 +EEARH.EEAR10 10 +EEARH.EEAR9 9 +EEARH.EEAR8 8 +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +OCR2 0x0023 Timer/Counter2 Output Compare Register +TCNT2 0x0024 Timer/Counter2 +TCCR2 0x0025 Timer/Counter2 Control Register +TCCR2.PWM2 6 Pulse Width Modulator Enable +TCCR2.COM21 5 Compare Output Mode, Bit 1 +TCCR2.COM20 4 Compare Output Mode, Bits0 +TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +TCCR2.CS22 2 Clock Select Bit 2 +TCCR2.CS21 1 Clock Select Bit 1 +TCCR2.CS20 0 Clock Select Bit 0 +ICR1L 0x0026 Timer/Counter1 Input Capture Register Low +ICR1H 0x0027 Timer/Counter1 Input Capture Register High +OCR1BL 0x0028 Timer/Counter1 Output Compare Register Low +OCR1BH 0x0029 Timer/Counter1 Output Compare Register High +OCR1AL 0x002A Timer/Counter1 Output Compare Register Low +OCR1AH 0x002B Timer/Counter1 Output Compare Register High +TCNT1L 0x002C Timer/Counter1 Low +TCNT1H 0x002D Timer/Counter1 High +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1, Bit 2 +TCCR1B.CS11 1 Clock Select1, Bit 1 +TCCR1B.CS10 0 Clock Select1, Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +ASSR 0x0030 Asynchronous Status Register +ASSR.AS0 3 Asynchronous Timer/Counter0 +ASSR.TCN0UB 2 Timer/Counter0 Update Busy +ASSR.OCR0UB 1 Output Compare Register0 Update Busy +ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy +OCR0 0x0031 Timer/Counter0 Output Compare Register +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.PWM0 6 Pulse Width Modulator Enable +TCCR0.COM01 5 Compare Output Mode, Bit 1 +TCCR0.COM00 4 Compare Output Mode, Bit 0 +TCCR0.CTC0 3 Clear Timer/Counter on Compare Match +TCCR0.CS02 2 Clock Select Bit 2 +TCCR0.CS01 1 Clock Select Bit 1 +TCCR0.CS00 0 Clock Select Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM Enable +MCUCR.SRW 6 External SRAM Wait State +MCUCR.SE 5 Sleep Enable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.SM0 3 Sleep Mode Select Bit 0 +TIFR 0x0036 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Input Capture Flag 1 +TIFR.OCF1A 4 Output Compare Flag 1A +TIFR.OCF1B 3 Output Compare Flag 1B +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0037 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +TIMSK.OCIE0 1 Timer/Counter0 Output Compare Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +EIFR 0x0038 External Interrupt Flag Register +EIFR.INTF7 7 External Interrupt 7 Flag +EIFR.INTF6 6 External Interrupt 6 Flag +EIFR.INTF5 5 External Interrupt 5 Flag +EIFR.INTF4 4 External Interrupt 4 Flag +EIMSK 0x0039 External Interrupt Mask Register +EIMSK.INT7 7 External Interrupt Request 7 Enable +EIMSK.INT6 6 External Interrupt Request 6 Enable +EIMSK.INT5 5 External Interrupt Request 5 Enable +EIMSK.INT4 4 External Interrupt Request 4 Enable +EIMSK.INT3 3 External Interrupt Request 3 Enable +EIMSK.INT2 2 External Interrupt Request 2 Enable +EIMSK.INT1 1 External Interrupt Request 1 Enable +EIMSK.INT0 0 External Interrupt Request 0 Enable +EICR 0x003A External Interrupt Control Register +EICR.ISC71 7 External Interrupt 7 Sense Control Bit 1 +EICR.ISC70 6 External Interrupt 7 Sense Control Bit 0 +EICR.ISC61 5 External Interrupt 6 Sense Control Bit 1 +EICR.ISC60 4 External Interrupt 6 Sense Control Bit 0 +EICR.ISC51 3 External Interrupt 5 Sense Control Bit 1 +EICR.ISC50 2 External Interrupt 5 Sense Control Bit 0 +EICR.ISC41 1 External Interrupt 4 Sense Control Bit 1 +EICR.ISC40 0 External Interrupt 4 Sense Control Bit 0 +RAMPZ 0x003B RAM Page Z Select Register +RAMPZ.RAMPZ0 0 +XDIV 0x003C XTAL Divide Control Register +XDIV.XDIVEN 7 XTAL Divide Enable +XDIV.XDIV6 6 XTAL Divide Select Bit 6 +XDIV.XDIV5 5 XTAL Divide Select Bit 5 +XDIV.XDIV4 4 XTAL Divide Select Bit 4 +XDIV.XDIV3 3 XTAL Divide Select Bit 3 +XDIV.XDIV2 2 XTAL Divide Select Bit 2 +XDIV.XDIV1 1 XTAL Divide Select Bit 1 +XDIV.XDIV0 0 XTAL Divide Select Bit 0 +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half-carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; PINF 0x0020 Port F Input Pins Address +; PINF.PINF7 7 +; PINF.PINF6 6 +; PINF.PINF5 5 +; PINF.PINF4 4 +; PINF.PINF3 3 +; PINF.PINF2 2 +; PINF.PINF1 1 +; PINF.PINF0 0 +; PINE 0x0021 Port E Input Pins Address +; PINE.PINE7 7 +; PINE.PINE6 6 +; PINE.PINE5 5 +; PINE.PINE4 4 +; PINE.PINE3 3 +; PINE.PINE2 2 +; PINE.PINE1 1 +; PINE.PINE0 0 +; DDRE 0x0022 Port E Data Direction Register +; DDRE.DDE7 7 Port E Data Direction Register bit 7 +; DDRE.DDE6 6 Port E Data Direction Register bit 6 +; DDRE.DDE5 5 Port E Data Direction Register bit 5 +; DDRE.DDE4 4 Port E Data Direction Register bit 4 +; DDRE.DDE3 3 Port E Data Direction Register bit 3 +; DDRE.DDE2 2 Port E Data Direction Register bit 2 +; DDRE.DDE1 1 Port E Data Direction Register bit 1 +; DDRE.DDE0 0 Port E Data Direction Register bit 0 +; PORTE 0x0023 Port E Data Register +; PORTE.PORTE7 7 Port E Data Register bit 7 +; PORTE.PORTE6 6 Port E Data Register bit 6 +; PORTE.PORTE5 5 Port E Data Register bit 5 +; PORTE.PORTE4 4 Port E Data Register bit 4 +; PORTE.PORTE3 3 Port E Data Register bit 3 +; PORTE.PORTE2 2 Port E Data Register bit 2 +; PORTE.PORTE1 1 Port E Data Register bit 1 +; PORTE.PORTE0 0 Port E Data Register bit 0 +; ADCL 0x0024 ADC Data Register Low +; ADCL.ADC7 7 +; ADCL.ADC6 6 +; ADCL.ADC5 5 +; ADCL.ADC4 4 +; ADCL.ADC3 3 +; ADCL.ADC2 2 +; ADCL.ADC1 1 +; ADCL.ADC0 0 +; ADCH 0x0025 ADC Data Register High +; ADCH.ADC9 9 +; ADCH.ADC8 8 +; ADCSR 0x0026 ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Select Register +; ADMUX.MUX2 2 Analog Channel Select Bit 2 +; ADMUX.MUX1 1 Analog Channel Select Bit 1 +; ADMUX.MUX0 0 Analog Channel Select Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACO 6 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR 0x0029 UART Baud Rate Register +; UCR 0x002A UART Control Register +; UCR.RXCIE 7 RX Complete Interrupt Enable +; UCR.TXCIE 6 TX Complete Interrupt Enable +; UCR.UDRIE 5 UART Data Register Empty Interrupt Enable +; UCR.RXEN 4 Receiver Enable +; UCR.TXEN 3 Transmitter Enable +; UCR.CHR9 2 9-bit Characters +; UCR.RXB8 1 Receive Data Bit 8 +; UCR.TXB8 0 Transmit Data Bit 8 +; USR 0x002B UART Status Register +; USR.RXC 7 UART Receive Complete +; USR.TXC 6 UART Transmit Complete +; USR.UDRE 5 UART Data Register Empty +; USR.FE 4 Framing Error +; USR.OR 3 OverRun +; UDR 0x002C UART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write Collision Flag +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; RESERVED0033 0x0033 RESERVED +; RESERVED0034 0x0034 RESERVED +; PORTC 0x0035 The Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 +; EEARL.EEAR6 6 +; EEARL.EEAR5 5 +; EEARL.EEAR4 4 +; EEARL.EEAR3 3 +; EEARL.EEAR2 2 +; EEARL.EEAR1 1 +; EEARL.EEAR0 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR11 11 +; EEARH.EEAR10 10 +; EEARH.EEAR9 9 +; EEARH.EEAR8 8 +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; OCR2 0x0043 Timer/Counter2 Output Compare Register +; TCNT2 0x0044 Timer/Counter2 +; TCCR2 0x0045 Timer/Counter2 Control Register +; TCCR2.PWM2 6 Pulse Width Modulator Enable +; TCCR2.COM21 5 Compare Output Mode, Bit 1 +; TCCR2.COM20 4 Compare Output Mode, Bits0 +; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +; TCCR2.CS22 2 Clock Select Bit 2 +; TCCR2.CS21 1 Clock Select Bit 1 +; TCCR2.CS20 0 Clock Select Bit 0 +; ICR1L 0x0046 Timer/Counter1 Input Capture Register Low +; ICR1H 0x0047 Timer/Counter1 Input Capture Register High +; OCR1BL 0x0048 Timer/Counter1 Output Compare Register Low +; OCR1BH 0x0049 Timer/Counter1 Output Compare Register High +; OCR1AL 0x004A Timer/Counter1 Output Compare Register Low +; OCR1AH 0x004B Timer/Counter1 Output Compare Register High +; TCNT1L 0x004C Timer/Counter1 Low +; TCNT1H 0x004D Timer/Counter1 High +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1, Bit 2 +; TCCR1B.CS11 1 Clock Select1, Bit 1 +; TCCR1B.CS10 0 Clock Select1, Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; ASSR 0x0050 Asynchronous Status Register +; ASSR.AS0 3 Asynchronous Timer/Counter0 +; ASSR.TCN0UB 2 Timer/Counter0 Update Busy +; ASSR.OCR0UB 1 Output Compare Register0 Update Busy +; ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy +; OCR0 0x0051 Timer/Counter0 Output Compare Register +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.PWM0 6 Pulse Width Modulator Enable +; TCCR0.COM01 5 Compare Output Mode, Bit 1 +; TCCR0.COM00 4 Compare Output Mode, Bit 0 +; TCCR0.CTC0 3 Clear Timer/Counter on Compare Match +; TCCR0.CS02 2 Clock Select Bit 2 +; TCCR0.CS01 1 Clock Select Bit 1 +; TCCR0.CS00 0 Clock Select Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM Enable +; MCUCR.SRW 6 External SRAM Wait State +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.SM0 3 Sleep Mode Select Bit 0 +; TIFR 0x0056 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Input Capture Flag 1 +; TIFR.OCF1A 4 Output Compare Flag 1A +; TIFR.OCF1B 3 Output Compare Flag 1B +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0057 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; EIFR 0x0058 External Interrupt Flag Register +; EIFR.INTF7 7 External Interrupt 7 Flag +; EIFR.INTF6 6 External Interrupt 6 Flag +; EIFR.INTF5 5 External Interrupt 5 Flag +; EIFR.INTF4 4 External Interrupt 4 Flag +; EIMSK 0x0059 External Interrupt Mask Register +; EIMSK.INT7 7 External Interrupt Request 7 Enable +; EIMSK.INT6 6 External Interrupt Request 6 Enable +; EIMSK.INT5 5 External Interrupt Request 5 Enable +; EIMSK.INT4 4 External Interrupt Request 4 Enable +; EIMSK.INT3 3 External Interrupt Request 3 Enable +; EIMSK.INT2 2 External Interrupt Request 2 Enable +; EIMSK.INT1 1 External Interrupt Request 1 Enable +; EIMSK.INT0 0 External Interrupt Request 0 Enable +; EICR 0x005A External Interrupt Control Register +; EICR.ISC71 7 External Interrupt 7 Sense Control Bit 1 +; EICR.ISC70 6 External Interrupt 7 Sense Control Bit 0 +; EICR.ISC61 5 External Interrupt 6 Sense Control Bit 1 +; EICR.ISC60 4 External Interrupt 6 Sense Control Bit 0 +; EICR.ISC51 3 External Interrupt 5 Sense Control Bit 1 +; EICR.ISC50 2 External Interrupt 5 Sense Control Bit 0 +; EICR.ISC41 1 External Interrupt 4 Sense Control Bit 1 +; EICR.ISC40 0 External Interrupt 4 Sense Control Bit 0 +; RAMPZ 0x005B RAM Page Z Select Register +; RAMPZ.RAMPZ0 0 +; XDIV 0x005C XTAL Divide Control Register +; XDIV.XDIVEN 7 XTAL Divide Enable +; XDIV.XDIV6 6 XTAL Divide Select Bit 6 +; XDIV.XDIV5 5 XTAL Divide Select Bit 5 +; XDIV.XDIV4 4 XTAL Divide Select Bit 4 +; XDIV.XDIV3 3 XTAL Divide Select Bit 3 +; XDIV.XDIV2 2 XTAL Divide Select Bit 2 +; XDIV.XDIV1 1 XTAL Divide Select Bit 1 +; XDIV.XDIV0 0 XTAL Divide Select Bit 0 +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half-carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega128_L +SUBARCH=51 +; doc2467.pdf +; + +ROM=131072 +RAM=4096 +EEPROM=4096 + +; MEMORY MAP +; Memory Configuration A +area DATA FSR_1 0x0000:0x0020 32 Registers +area DATA FSR_2 0x0020:0x0060 64 I/O Registers +area DATA FSR_3 0x0060:0x00A0 160 Ext I/O Reg. +area BSS RESERVED 0x00A0:0x0100 +area DATA I_SRAM 0x0100:0x1100 Internal SRAM +area DATA E_SRAM 0x1100:0x10000 External SRAM +; Memory Configuration B +; area DATA FSR_1 0x0000:0x0020 32 Registers +; area DATA FSR_2 0x0020:0x0060 64 I/O Registers +; area DATA I_SRAM 0x0060:0x1000 Internal SRAM +; area DATA E_SRAM 0x1000:0x10000 External SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry INT3_ 0x0008 External Interrupt Request 3 +entry INT4_ 0x000A External Interrupt Request 4 +entry INT5_ 0x000C External Interrupt Request 5 +entry INT6_ 0x000E External Interrupt Request 6 +entry INT7_ 0x0010 External Interrupt Request 7 +entry TIMER2_COMP 0x0012 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0014 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0016 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0018 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x001A Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x001C Timer/Counter1 Overflow +entry TIMER0_COMP 0x001E Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow +entry SPI_STC 0x0022 SPI Serial Transfer Complete +entry USART0_RX 0x0024 USART0, Rx Complete +entry USART0_UDRE 0x0026 USART0 Data Register Empty +entry USART0_TX 0x0028 USART0, Tx Complete +entry ADC_ 0x002A ADC Conversion Complete +entry EE_READY 0x002C EEPROM Ready +entry ANALOG_COMP 0x002E Analog Comparator +entry TIMER1_COMPC 0x0030 Timer/Countre1 Compare Match C +entry TIMER3_CAPT 0x0032 Timer/Counter3 Capture Event +entry TIMER3_COMPA 0x0034 Timer/Counter3 Compare Match A +entry TIMER3_COMPB 0x0036 Timer/Counter3 Compare Match B +entry TIMER3_COMPC 0x0038 Timer/Counter3 Compare Match C +entry TIMER3_OVF 0x003A Timer/Counter3 Overflow +entry USART1_RX 0x003C USART1, Rx Complete +entry USART1_UDRE 0x003E USART1 Data Register Empty +entry USART1_TX 0x0040 USART1, Tx Complete +entry TWI_ 0x0042 Two-wire Serial Interface +entry SPM_READY 0x0044 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +PINF 0x0000 Port F Input Pins Address +PINF.PINF7 7 +PINF.PINF6 6 +PINF.PINF5 5 +PINF.PINF4 4 +PINF.PINF3 3 +PINF.PINF2 2 +PINF.PINF1 1 +PINF.PINF0 0 +PINE 0x0001 Port E Input Pins Address +PINE.PINE7 7 +PINE.PINE6 6 +PINE.PINE5 5 +PINE.PINE4 4 +PINE.PINE3 3 +PINE.PINE2 2 +PINE.PINE1 1 +PINE.PINE0 0 +DDRE 0x0002 Port E Data Direction Register +DDRE.DDE7 7 Port E Data Direction Register bit 7 +DDRE.DDE6 6 Port E Data Direction Register bit 6 +DDRE.DDE5 5 Port E Data Direction Register bit 5 +DDRE.DDE4 4 Port E Data Direction Register bit 4 +DDRE.DDE3 3 Port E Data Direction Register bit 3 +DDRE.DDE2 2 Port E Data Direction Register bit 2 +DDRE.DDE1 1 Port E Data Direction Register bit 1 +DDRE.DDE0 0 Port E Data Direction Register bit 0 +PORTE 0x0003 Port E Data Register +PORTE.PORTE7 7 Port E Data Register bit 7 +PORTE.PORTE6 6 Port E Data Register bit 6 +PORTE.PORTE5 5 Port E Data Register bit 5 +PORTE.PORTE4 4 Port E Data Register bit 4 +PORTE.PORTE3 3 Port E Data Register bit 3 +PORTE.PORTE2 2 Port E Data Register bit 2 +PORTE.PORTE1 1 Port E Data Register bit 1 +PORTE.PORTE0 0 Port E Data Register bit 0 +ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 +ADCL.ADC6 6 +ADCL.ADC5 5 +ADCL.ADC4 4 +ADCL.ADC3 3 +ADCL.ADC2 2 +ADCL.ADC1 1 +ADCL.ADC0 0 +ADCH 0x0005 The ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 +ADCH.ADC8 8 +; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 +; ADCL.ADC0 6 +; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 +; ADCH.ADC8 14 +; ADCH.ADC7 13 +; ADCH.ADC6 12 +; ADCH.ADC5 11 +; ADCH.ADC4 10 +; ADCH.ADC3 9 +; ADCH.ADC2 8 +ADCSRA 0x0006 ADC Control and Status Register A +ADCSRA.ADEN 7 ADC Enable +ADCSRA.ADSC 6 ADC Start Conversion +ADCSRA.ADFR 5 ADC Free Running Select +ADCSRA.ADIF 4 ADC Interrupt Flag +ADCSRA.ADIE 3 ADC Interrupt Enable +ADCSRA.ADPS2 2 ADC Prescaler Select Bit +ADCSRA.ADPS1 1 ADC Prescaler Select Bit +ADCSRA.ADPS0 0 ADC Prescaler Select Bit +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR0L 0x0009 USART Baud Rate Register +UBRR0L.UBRR7 7 +UBRR0L.UBRR6 6 +UBRR0L.UBRR5 5 +UBRR0L.UBRR4 4 +UBRR0L.UBRR3 3 +UBRR0L.UBRR2 2 +UBRR0L.UBRR1 1 +UBRR0L.UBRR0 0 +UCSR0B 0x000A USART Control and Status Register +UCSR0B.RXCIE 7 RX Complete Interrupt Enable +UCSR0B.TXCIE 6 TX Complete Interrupt Enable +UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSR0B.RXEN 4 Receiver Enable +UCSR0B.TXEN 3 Transmitter Enable +UCSR0B.UCSZ2 2 Character Size +UCSR0B.RXB8 1 Receive Data Bit 8 +UCSR0B.TXB8 0 Transmit Data Bit8 +UCSR0A 0x000B USART Control and Status Register +UCSR0A.RXC 7 USART Receive Complete +UCSR0A.TXC 6 USART Transmit Complete +UCSR0A.UDRE 5 USART Data Register Empty +UCSR0A.FE 4 Frame Error +UCSR0A.DOR 3 Data OverRun +UCSR0A.UPE 2 Parity Error +UCSR0A.U2X 1 Double the USART Transmission Speed +UCSR0A.MPCM 0 Multi-Processor Communication Mode +UDR0 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 +EEARL.EEAR6 6 +EEARL.EEAR5 5 +EEARL.EEAR4 4 +EEARL.EEAR3 3 +EEARL.EEAR2 2 +EEARL.EEAR1 1 +EEARL.EEAR0 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR11 11 +EEARH.EEAR10 10 +EEARH.EEAR9 9 +EEARH.EEAR8 8 +SFIOR 0x0020 Special Function IO Register +SFIOR.TSM 7 Timer/Counter Synchronization Mode +SFIOR.ADHSM 4 ADC High Speed Mode +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up disable +SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 +SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +OCDR 0x0022 On-chip Debug Register +OCDR.IDRD_OCDR7 7 +OCDR.OCDR6 6 +OCDR.OCDR5 5 +OCDR.OCDR4 4 +OCDR.OCDR3 3 +OCDR.OCDR2 2 +OCDR.OCDR1 1 +OCDR.OCDR0 0 +OCR2 0x0023 Output Compare Register +OCR2.OCR2_7 7 +OCR2.OCR2_6 6 +OCR2.OCR2_5 5 +OCR2.OCR2_4 4 +OCR2.OCR2_3 3 +OCR2.OCR2_2 2 +OCR2.OCR2_1 1 +OCR2.OCR2_0 0 +TCNT2 0x0024 Timer/Counter Register +TCNT2.TCNT2_7 7 +TCNT2.TCNT2_6 6 +TCNT2.TCNT2_5 5 +TCNT2.TCNT2_4 4 +TCNT2.TCNT2_3 3 +TCNT2.TCNT2_2 2 +TCNT2.TCNT2_1 1 +TCNT2.TCNT2_0 0 +TCCR2 0x0025 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Compare Match Output Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Waveform Generation Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +ICR1L 0x0026 Input Capture Register Low Byte +ICR1H 0x0027 Input Capture Register High Byte +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input CaptureEdgeSelect +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 +TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +ASSR 0x0030 Asynchronous Status Register +ASSR.AS0 3 Asynchronous Timer/Counter0 +ASSR.TCN0UB 2 Timer/Counter0 Update Busy +ASSR.OCR0UB 1 Output Compare Register0 Update Busy +ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy +OCR0 0x0031 Timer/Counter0 Output Compare Register +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.JTD 7 JTAG Interface Disable +MCUCSR.JTRF 4 JTAG Reset Flag +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-On Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM/XMEM Enable +MCUCR.SRW10 6 Wait-state Select Bit +MCUCR.SE 5 Sleep Enable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.SM0 3 Sleep Mode Select Bit 0 +MCUCR.SM2 2 Sleep Mode Select Bit 2 +MCUCR.IVSEL 1 Interrupt Vector Select +MCUCR.IVCE 0 Interrupt Vector Change Enable +TIFR 0x0036 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0037 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +EIFR 0x0038 External Interrupt Flag Register +EIFR.INTF7 7 External Interrupt Flag 7 +EIFR.INTF6 6 External Interrupt Flag 6 +EIFR.INTF5 5 External Interrupt Flag 5 +EIFR.INTF4 4 External Interrupt Flag 4 +EIFR.INTF3 3 External Interrupt Flag 3 +EIFR.INTF2 2 External Interrupt Flag 2 +EIFR.INTF1 1 External Interrupt Flag 1 +EIFR.INTF0 0 External Interrupt Flag 0 +EIMSK 0x0039 External Interrupt Mask Register +EIMSK.INT7 7 External Interrupt Request 7 Enable +EIMSK.INT6 6 External Interrupt Request 6 Enable +EIMSK.INT5 5 External Interrupt Request 5 Enable +EIMSK.INT4 4 External Interrupt Request 4 Enable +EIMSK.INT3 3 External Interrupt Request 3 Enable +EIMSK.INT2 2 External Interrupt Request 2 Enable +EIMSK.INT1 1 External Interrupt Request 1 Enable +EIMSK.INT0 0 External Interrupt Request 0 Enable +EICRB 0x003A External Interrupt Control Register B +EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 +EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 +EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 +EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 +EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 +EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 +EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 +EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 +RAMPZ 0x003B RAM Page Z Select Register +RAMPZ.RAMPZ0 0 Extended RAM Page Z-pointer +XDIV 0x003C XTAL Divide Control Register +XDIV.XDIVEN 7 XTAL Divide Enable +XDIV.XDIV6 6 XTAL Divide Select Bit 6 +XDIV.XDIV5 5 XTAL Divide Select Bit 5 +XDIV.XDIV4 4 XTAL Divide Select Bit 4 +XDIV.XDIV3 3 XTAL Divide Select Bit 3 +XDIV.XDIV2 2 XTAL Divide Select Bit 2 +XDIV.XDIV1 1 XTAL Divide Select Bit 1 +XDIV.XDIV0 0 XTAL Divide Select Bit 0 +SPL 0x003D Stack Pointer Register Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer Register High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 CarryFlag + +; PINF 0x0020 Port F Input Pins Address +; PINF.PINF7 7 +; PINF.PINF6 6 +; PINF.PINF5 5 +; PINF.PINF4 4 +; PINF.PINF3 3 +; PINF.PINF2 2 +; PINF.PINF1 1 +; PINF.PINF0 0 +; PINE 0x0021 Port E Input Pins Address +; PINE.PINE7 7 +; PINE.PINE6 6 +; PINE.PINE5 5 +; PINE.PINE4 4 +; PINE.PINE3 3 +; PINE.PINE2 2 +; PINE.PINE1 1 +; PINE.PINE0 0 +; DDRE 0x0022 Port E Data Direction Register +; DDRE.DDE7 7 Port E Data Direction Register bit 7 +; DDRE.DDE6 6 Port E Data Direction Register bit 6 +; DDRE.DDE5 5 Port E Data Direction Register bit 5 +; DDRE.DDE4 4 Port E Data Direction Register bit 4 +; DDRE.DDE3 3 Port E Data Direction Register bit 3 +; DDRE.DDE2 2 Port E Data Direction Register bit 2 +; DDRE.DDE1 1 Port E Data Direction Register bit 1 +; DDRE.DDE0 0 Port E Data Direction Register bit 0 +; PORTE 0x0023 Port E Data Register +; PORTE.PORTE7 7 Port E Data Register bit 7 +; PORTE.PORTE6 6 Port E Data Register bit 6 +; PORTE.PORTE5 5 Port E Data Register bit 5 +; PORTE.PORTE4 4 Port E Data Register bit 4 +; PORTE.PORTE3 3 Port E Data Register bit 3 +; PORTE.PORTE2 2 Port E Data Register bit 2 +; PORTE.PORTE1 1 Port E Data Register bit 1 +; PORTE.PORTE0 0 Port E Data Register bit 0 +; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 +; ADCL.ADC6 6 +; ADCL.ADC5 5 +; ADCL.ADC4 4 +; ADCL.ADC3 3 +; ADCL.ADC2 2 +; ADCL.ADC1 1 +; ADCL.ADC0 0 +; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 +; ADCH.ADC8 8 +; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 +; ; ADCL.ADC0 6 +; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 +; ; ADCH.ADC8 14 +; ; ADCH.ADC7 13 +; ; ADCH.ADC6 12 +; ; ADCH.ADC5 11 +; ; ADCH.ADC4 10 +; ; ADCH.ADC3 9 +; ; ADCH.ADC2 8 +; ADCSRA 0x0026 ADC Control and Status Register A +; ADCSRA.ADEN 7 ADC Enable +; ADCSRA.ADSC 6 ADC Start Conversion +; ADCSRA.ADFR 5 ADC Free Running Select +; ADCSRA.ADIF 4 ADC Interrupt Flag +; ADCSRA.ADIE 3 ADC Interrupt Enable +; ADCSRA.ADPS2 2 ADC Prescaler Select Bit +; ADCSRA.ADPS1 1 ADC Prescaler Select Bit +; ADCSRA.ADPS0 0 ADC Prescaler Select Bit +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR0L 0x0029 USART Baud Rate Register +; UBRR0L.UBRR7 7 +; UBRR0L.UBRR6 6 +; UBRR0L.UBRR5 5 +; UBRR0L.UBRR4 4 +; UBRR0L.UBRR3 3 +; UBRR0L.UBRR2 2 +; UBRR0L.UBRR1 1 +; UBRR0L.UBRR0 0 +; UCSR0B 0x002A USART Control and Status Register +; UCSR0B.RXCIE 7 RX Complete Interrupt Enable +; UCSR0B.TXCIE 6 TX Complete Interrupt Enable +; UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSR0B.RXEN 4 Receiver Enable +; UCSR0B.TXEN 3 Transmitter Enable +; UCSR0B.UCSZ2 2 Character Size +; UCSR0B.RXB8 1 Receive Data Bit 8 +; UCSR0B.TXB8 0 Transmit Data Bit8 +; UCSR0A 0x002B USART Control and Status Register +; UCSR0A.RXC 7 USART Receive Complete +; UCSR0A.TXC 6 USART Transmit Complete +; UCSR0A.UDRE 5 USART Data Register Empty +; UCSR0A.FE 4 Frame Error +; UCSR0A.DOR 3 Data OverRun +; UCSR0A.UPE 2 Parity Error +; UCSR0A.U2X 1 Double the USART Transmission Speed +; UCSR0A.MPCM 0 Multi-Processor Communication Mode +; UDR0 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 +; EEARL.EEAR6 6 +; EEARL.EEAR5 5 +; EEARL.EEAR4 4 +; EEARL.EEAR3 3 +; EEARL.EEAR2 2 +; EEARL.EEAR1 1 +; EEARL.EEAR0 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR11 11 +; EEARH.EEAR10 10 +; EEARH.EEAR9 9 +; EEARH.EEAR8 8 +; SFIOR 0x0040 Special Function IO Register +; SFIOR.TSM 7 Timer/Counter Synchronization Mode +; SFIOR.ADHSM 4 ADC High Speed Mode +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up disable +; SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 +; SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; OCDR 0x0042 On-chip Debug Register +; OCDR.IDRD_OCDR7 7 +; OCDR.OCDR6 6 +; OCDR.OCDR5 5 +; OCDR.OCDR4 4 +; OCDR.OCDR3 3 +; OCDR.OCDR2 2 +; OCDR.OCDR1 1 +; OCDR.OCDR0 0 +; OCR2 0x0043 Output Compare Register +; OCR2.OCR2_7 7 +; OCR2.OCR2_6 6 +; OCR2.OCR2_5 5 +; OCR2.OCR2_4 4 +; OCR2.OCR2_3 3 +; OCR2.OCR2_2 2 +; OCR2.OCR2_1 1 +; OCR2.OCR2_0 0 +; TCNT2 0x0044 Timer/Counter Register +; TCNT2.TCNT2_7 7 +; TCNT2.TCNT2_6 6 +; TCNT2.TCNT2_5 5 +; TCNT2.TCNT2_4 4 +; TCNT2.TCNT2_3 3 +; TCNT2.TCNT2_2 2 +; TCNT2.TCNT2_1 1 +; TCNT2.TCNT2_0 0 +; TCCR2 0x0045 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Compare Match Output Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Waveform Generation Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; ICR1L 0x0046 Input Capture Register Low Byte +; ICR1H 0x0047 Input Capture Register High Byte +; OCR1BL 0x0048 Output Compare Register B Low Byte +; OCR1BH 0x0049 Output Compare Register B High Byte +; OCR1AL 0x004A Output Compare Register A Low Byte +; OCR1AH 0x004B Output Compare Register A High Byte +; TCNT1L 0x004C Counter Register Low Byte +; TCNT1H 0x004D Counter Register High Byte +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input CaptureEdgeSelect +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +; TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 +; TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; ASSR 0x0050 Asynchronous Status Register +; ASSR.AS0 3 Asynchronous Timer/Counter0 +; ASSR.TCN0UB 2 Timer/Counter0 Update Busy +; ASSR.OCR0UB 1 Output Compare Register0 Update Busy +; ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy +; OCR0 0x0051 Timer/Counter0 Output Compare Register +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.JTD 7 JTAG Interface Disable +; MCUCSR.JTRF 4 JTAG Reset Flag +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-On Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM/XMEM Enable +; MCUCR.SRW10 6 Wait-state Select Bit +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.SM0 3 Sleep Mode Select Bit 0 +; MCUCR.SM2 2 Sleep Mode Select Bit 2 +; MCUCR.IVSEL 1 Interrupt Vector Select +; MCUCR.IVCE 0 Interrupt Vector Change Enable +; TIFR 0x0056 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0057 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; EIFR 0x0058 External Interrupt Flag Register +; EIFR.INTF7 7 External Interrupt Flag 7 +; EIFR.INTF6 6 External Interrupt Flag 6 +; EIFR.INTF5 5 External Interrupt Flag 5 +; EIFR.INTF4 4 External Interrupt Flag 4 +; EIFR.INTF3 3 External Interrupt Flag 3 +; EIFR.INTF2 2 External Interrupt Flag 2 +; EIFR.INTF1 1 External Interrupt Flag 1 +; EIFR.INTF0 0 External Interrupt Flag 0 +; EIMSK 0x0059 External Interrupt Mask Register +; EIMSK.INT7 7 External Interrupt Request 7 Enable +; EIMSK.INT6 6 External Interrupt Request 6 Enable +; EIMSK.INT5 5 External Interrupt Request 5 Enable +; EIMSK.INT4 4 External Interrupt Request 4 Enable +; EIMSK.INT3 3 External Interrupt Request 3 Enable +; EIMSK.INT2 2 External Interrupt Request 2 Enable +; EIMSK.INT1 1 External Interrupt Request 1 Enable +; EIMSK.INT0 0 External Interrupt Request 0 Enable +; EICRB 0x005A External Interrupt Control Register B +; EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 +; EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 +; EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 +; EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 +; EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 +; EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 +; EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 +; EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 +; RAMPZ 0x005B RAM Page Z Select Register +; RAMPZ.RAMPZ0 0 Extended RAM Page Z-pointer +; XDIV 0x005C XTAL Divide Control Register +; XDIV.XDIVEN 7 XTAL Divide Enable +; XDIV.XDIV6 6 XTAL Divide Select Bit 6 +; XDIV.XDIV5 5 XTAL Divide Select Bit 5 +; XDIV.XDIV4 4 XTAL Divide Select Bit 4 +; XDIV.XDIV3 3 XTAL Divide Select Bit 3 +; XDIV.XDIV2 2 XTAL Divide Select Bit 2 +; XDIV.XDIV1 1 XTAL Divide Select Bit 1 +; XDIV.XDIV0 0 XTAL Divide Select Bit 0 +; SPL 0x005D Stack Pointer Register Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer Register High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 CarryFlag +; RESERVED0060 0x0060 RESERVED +; DDRF 0x0061 Port F Data Direction Register +; DDRF.DDF7 7 Port F Data Direction Register bit 7 +; DDRF.DDF6 6 Port F Data Direction Register bit 6 +; DDRF.DDF5 5 Port F Data Direction Register bit 5 +; DDRF.DDF4 4 Port F Data Direction Register bit 4 +; DDRF.DDF3 3 Port F Data Direction Register bit 3 +; DDRF.DDF2 2 Port F Data Direction Register bit 2 +; DDRF.DDF1 1 Port F Data Direction Register bit 1 +; DDRF.DDF0 0 Port F Data Direction Register bit 0 +; PORTF 0x0062 Port F Data Register +; PORTF.PORTF7 7 Port F Data Register bit 7 +; PORTF.PORTF6 6 Port F Data Register bit 6 +; PORTF.PORTF5 5 Port F Data Register bit 5 +; PORTF.PORTF4 4 Port F Data Register bit 4 +; PORTF.PORTF3 3 Port F Data Register bit 3 +; PORTF.PORTF2 2 Port F Data Register bit 2 +; PORTF.PORTF1 1 Port F Data Register bit 1 +; PORTF.PORTF0 0 Port F Data Register bit 0 +; PING 0x0063 Port G Input Pins Address +; PING.PING4 4 +; PING.PING3 3 +; PING.PING2 2 +; PING.PING1 1 +; PING.PING0 0 +; DDRG 0x0064 Port G Data Direction Register +; DDRG.DDG4 4 Port G Data Direction Register bit 4 +; DDRG.DDG3 3 Port G Data Direction Register bit 3 +; DDRG.DDG2 2 Port G Data Direction Register bit 2 +; DDRG.DDG1 1 Port G Data Direction Register bit 1 +; DDRG.DDG0 0 Port G Data Direction Register bit 0 +; PORTG 0x0065 Port G Data Register +; PORTG.PORTG4 4 Port G Data Register bit 4 +; PORTG.PORTG3 3 Port G Data Register bit 3 +; PORTG.PORTG2 2 Port G Data Register bit 2 +; PORTG.PORTG1 1 Port G Data Register bit 1 +; PORTG.PORTG0 0 Port G Data Register bit 0 +; RESERVED0066 0x0066 RESERVED +; RESERVED0067 0x0067 RESERVED +; SPMCSR 0x0068 Store Program Memory Control Register +; SPMCSR.SPMIE 7 SPM Interrupt Enable +; SPMCSR.RWWSB 6 Read-While-Write Section Busy +; SPMCSR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCSR.BLBSET 3 Boot Lock Bit Set +; SPMCSR.PGWRT 2 Page Write +; SPMCSR.PGERS 1 Page Erase +; SPMCSR.SPMEN 0 Store Program Memory Enable +; RESERVED0069 0x0069 RESERVED +; EICRA 0x006A External Interrupt Control Register A +; EICRA.ISC31 7 External Interrupt 3 Sense Control Bit 1 +; EICRA.ISC30 6 External Interrupt 3 Sense Control Bit 0 +; EICRA.ISC21 5 External Interrupt 2 Sense Control Bit 1 +; EICRA.ISC20 4 External Interrupt 2 Sense Control Bit 0 +; EICRA.ISC11 3 External Interrupt 1 Sense Control Bit 1 +; EICRA.ISC10 2 External Interrupt 1 Sense Control Bit 0 +; EICRA.ISC01 1 External Interrupt 0 Sense Control Bit 1 +; EICRA.ISC00 0 External Interrupt 0 Sense Control Bit 0 +; RESERVED006B 0x006B RESERVED +; XMCRB 0x006C External Memory Control Register B +; XMCRB.XMBK 7 External Memory Bus-keeper Enable +; XMCRB.XMM2 2 External Memory High Mask 2 +; XMCRB.XMM1 1 External Memory High Mask 1 +; XMCRB.XMM0 0 External Memory High Mask 0 +; RESERVED006D 0x006D RESERVED +; OSCCAL 0x006F Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TWBR 0x0070 TWI Bit Rate Register +; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +; TWSR 0x0071 TWI Status Register +; TWSR.TWS7 7 TWI Status 7 +; TWSR.TWS6 6 TWI Status 6 +; TWSR.TWS5 5 TWI Status 5 +; TWSR.TWS4 4 TWI Status 4 +; TWSR.TWS3 3 TWI Status 3 +; TWSR.TWS1 1 TWI Status 1 +; TWSR.TWS0 0 TWI Status 0 +; TWAR 0x0072 TWI (Slave) Address Register +; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +; TWDR 0x0073 TWI Data Register +; TWDR.TWD7 7 TWI Data Register bit 7 +; TWDR.TWD6 6 TWI Data Register bit 6 +; TWDR.TWD5 5 TWI Data Register bit 5 +; TWDR.TWD4 4 TWI Data Register bit 4 +; TWDR.TWD3 3 TWI Data Register bit 3 +; TWDR.TWD2 2 TWI Data Register bit 2 +; TWDR.TWD1 1 TWI Data Register bit 1 +; TWDR.TWD0 0 TWI Data Register bit 0 +; TWCR 0x0074 TWI Control Register +; TWCR.TWINT 7 TWI Interrupt Flag +; TWCR.TWEA 6 TWI Enable Acknowledge Bit +; TWCR.TWSTA 5 TWI START Condition Bit +; TWCR.TWSTO 4 TWI STOP Condition Bit +; TWCR.TWWC 3 TWI Write Collision Flag +; TWCR.TWEN 2 TWI Enable Bit +; TWCR.TWIE 0 TWI Interrupt Enable +; RESERVED0075 0x0075 RESERVED +; RESERVED0076 0x0076 RESERVED +; RESERVED0077 0x0077 RESERVED +; OCR1CL 0x0078 Output Compare Register C Low Byte +; OCR1CH 0x0079 Output Compare Register C High Byte +; TCCR1C 0x007A Timer/Counter1 Control Register C +; TCCR1C.FOC1A 7 Force Output Compare for Channel A +; TCCR1C.FOC1B 6 Force Output Compare for Channel B +; TCCR1C.FOC1C 5 Force Output Compare for Channel C +; RESERVED007B 0x007B RESERVED +; ETIFR 0x007C Extended Timer/Counter Interrupt Flag Register +; ETIFR.ICF3 5 Timer/Counter3, Input Capture Flag +; ETIFR.OCF3A 4 Timer/Counter3, Output Compare A Match Flag +; ETIFR.OCF3B 3 Timer/Counter3, Output Compare B Match Flag +; ETIFR.TOV3 2 Timer/Counter3, Overflow Flag +; ETIFR.OCF3C 1 Timer/Counter3, Output Compare C Match Flag +; ETIFR.OCF1C 0 Timer/Counter1, Output Compare C Match Flag +; ETIMSK 0x007D Extended Timer/Counter Interrupt Mask Register +; ETIMSK.TICIE3 5 Timer/Counter3, Input Capture Interrupt Enable +; ETIMSK.OCIE3A 4 Timer/Counter3, Output Compare A Match Interrupt Enable +; ETIMSK.OCIE3B 3 Timer/Counter3, Output Compare B Match Interrupt Enable +; ETIMSK.TOIE3 2 Timer/Counter3, Overflow Interrupt Enable +; ETIMSK.OCIE3C 1 Timer/Counter3, Output Compare C Match Interrupt Enable +; ETIMSK.OCIE1C 0 Timer/Counter1, Output Compare C Match Interrupt Enable +; RESERVED007E 0x007E RESERVED +; RESERVED007F 0x007F RESERVED +; ICR3L 0x0080 Input Capture Register Low Byte +; ICR3H 0x0081 Input Capture Register High Byte +; OCR3CL 0x0082 Output Compare Register C Low Byte +; OCR3CH 0x0083 Output Compare Register C High Byte +; OCR3BL 0x0084 Output Compare Register B Low Byte +; OCR3BH 0x0085 Output Compare Register B High Byte +; OCR3AL 0x0086 Output Compare Register A Low Byte +; OCR3AH 0x0087 Output Compare Register A High Byte +; TCNT3L 0x0088 Counter Register Low Byte +; TCNT3H 0x0089 Counter Register High Byte +; TCCR3B 0x008A Timer/Counter3 Control Register B +; TCCR3B.ICNC3 7 Input Capture Noise Canceler +; TCCR3B.ICES3 6 Input CaptureEdgeSelect +; TCCR3B.WGM33 4 Waveform Generation Mode 3 +; TCCR3B.WGM32 3 Waveform Generation Mode 2 +; TCCR3B.CS32 2 Clock Select 2 +; TCCR3B.CS31 1 Clock Select 1 +; TCCR3B.CS30 0 Clock Select 0 +; TCCR3A 0x008B Timer/Counter3 Control Register A +; TCCR3A.COM3A1 7 Compare Output Mode for Channel A 1 +; TCCR3A.COM3A0 6 Compare Output Mode for Channel A 0 +; TCCR3A.COM3B1 5 Compare Output Mode for Channel B 1 +; TCCR3A.COM3B0 4 Compare Output Mode for Channel B 0 +; TCCR3A.COM3C1 3 Compare Output Mode for Channel C 1 +; TCCR3A.COM3C0 2 Compare Output Mode for Channel C 0 +; TCCR3A.WGM31 1 Waveform Generation Mode 1 +; TCCR3A.WGM30 0 Waveform Generation Mode 0 +; TCCR3C 0x008C Timer/Counter3 Control Register C +; TCCR3C.FOC3A 7 Force Output Compare for Channel A +; TCCR3C.FOC3B 6 Force Output Compare for Channel B +; TCCR3C.FOC3C 5 Force Output Compare for Channel C +; RESERVED008D 0x008D RESERVED +; RESERVED008E 0x008E RESERVED +; RESERVED008F 0x008F RESERVED +; UBRR0H 0x0090 USART0 Baud Rate Register High +; RESERVED0091 0x0091 RESERVED +; RESERVED0092 0x0092 RESERVED +; RESERVED0093 0x0093 RESERVED +; RESERVED0094 0x0094 RESERVED +; UCSR0C 0x0095 USART Control and Status Register C +; UCSR0C.UMSEL 6 USART Mode Select +; UCSR0C.UPM1 5 Parity Mode 1 +; UCSR0C.UPM0 4 Parity Mode 0 +; UCSR0C.USBS 3 Stop Bit Select +; UCSR0C.UCSZ1 2 Character Size 1 +; UCSR0C.UCSZ0 1 Character Size 0 +; UCSR0C.UCPOL 0 Clock Polarity +; RESERVED0096 0x0096 RESERVED +; RESERVED0097 0x0097 RESERVED +; UBRR1H 0x0098 USART1 Baud Rate Register High +; UBRR1L 0x0099 USART1 Baud Rate Register Low +; UCSR1B 0x009A USART Control and Status Register B +; UCSR1B.RXCIE 7 RX Complete Interrupt Enable +; UCSR1B.TXCIE 6 TX Complete Interrupt Enable +; UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSR1B.RXEN 4 Receiver Enable +; UCSR1B.TXEN 3 Transmitter Enable +; UCSR1B.UCSZ2 2 Character Size +; UCSR1B.RXB8 1 Receive Data Bit 8 +; UCSR1B.TXB8 0 Transmit Data Bit8 +; UCSR1A 0x009B USART Control and Status Register A +; UCSR1A.RXC 7 USART Receive Complete +; UCSR1A.TXC 6 USART Transmit Complete +; UCSR1A.UDRE 5 USART Data Register Empty +; UCSR1A.FE 4 Frame Error +; UCSR1A.DOR 3 Data OverRun +; UCSR1A.UPE 2 Parity Error +; UCSR1A.U2X 1 Double the USART Transmission Speed +; UCSR1A.MPCM 0 Multi-Processor Communication Mode +; UDR1 0x009C USART1 I/O Data Register +; UCSR1C 0x009D USART Control and Status Register C +; UCSR1C.UMSEL 6 USART Mode Select +; UCSR1C.UPM1 5 Parity Mode 1 +; UCSR1C.UPM0 4 Parity Mode 0 +; UCSR1C.USBS 3 Stop Bit Select +; UCSR1C.UCSZ1 2 Character Size 1 +; UCSR1C.UCSZ0 1 Character Size 0 +; UCSR1C.UCPOL 0 Clock Polarity +; RESERVED009E 0x009E RESERVED +; RESERVED009F 0x009F RESERVED + + +.ATmega161_L +SUBARCH=5 +; doc1228.pdf +; + +RAM=1024 +ROM=16384 +EEPROM=512 + + +; MEMORY MAP +area DATA FSR 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x0460 Internal SRAM +area DATA E_SRAM 0x0460:0x10000 External SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x000A Timer/Counter2 Overflow +entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow +entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow +entry SPI_STC 0x0018 Serial Transfer Complete +entry UART0_RX 0x001A UART0, Rx Complete +entry UART1_RX 0x001C UART1, Rx Complete +entry UART0_UDRE 0x001E UART0 Data Register Empty +entry UART1_UDRE 0x0020 UART1 Data Register Empty +entry UART0_TX 0x0022 UART0, Tx Complete +entry UART1_TX 0x0024 UART1, Tx Complete +entry EE_RDY 0x0026 EEPROM Ready +entry ANA_COMP 0x0028 Analog Comparator + + +; INPUT/OUTPUT PORTS +UBRR1 0x0000 UART1 Baud Rate Register Low Byte +UCSR1B 0x0001 UART1 Control and Status Register +UCSR1B.RXCIE1 7 RX Complete Interrupt Enable +UCSR1B.TXCIE1 6 TX Complete Interrupt Enable +UCSR1B.UDRIE1 5 UART Data Register Empty Interrupt Enable +UCSR1B.RXEN1 4 Receiver Enable +UCSR1B.TXEN1 3 Transmitter Enable +UCSR1B.CHR91 2 9-bit Characters +UCSR1B.RXB81 1 Receive Data Bit 8 +UCSR1B.TXB81 0 Transmit Data Bit 8 +UCSR1A 0x0002 UART1 Control and Status Register +UCSR1A.RXC1 7 UART Receive Complete +UCSR1A.TXC1 6 UART Transmit Complete +UCSR1A.UDRE1 5 UART Data Register Empty +UCSR1A.FE1 4 Framing Error +UCSR1A.OR1 3 OverRun +UCSR1A.U2X1 1 Double the UART Transmission Speed +UCSR1A.MPCM1 0 Multi-processor Communication Mode +UDR1 0x0003 UART1 I/O Data Register +RESERVED0004 0x0004 RESERVED +PINE 0x0005 Port E Input Pins Address +PINE.PINE2 2 +PINE.PINE1 1 +PINE.PINE0 0 +DDRE 0x0006 Port E Data Direction Register +DDRE.DDE2 2 Port E Data Direction Register bit 2 +DDRE.DDE1 1 Port E Data Direction Register bit 1 +DDRE.DDE0 0 Port E Data Direction Register bit 0 +PORTE 0x0007 Port E Data Register +PORTE.PORTE2 2 Port E Data Register bit 2 +PORTE.PORTE1 1 Port E Data Register bit 1 +PORTE.PORTE0 0 Port E Data Register bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.AINBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR0 0x0009 UART0 Baud Rate Register Low Byte +UCSR0B 0x000A UART0 Control and StatusRegister +UCSR0B.RXCIE0 7 RX Complete Interrupt Enable +UCSR0B.TXCIE0 6 TX Complete Interrupt Enable +UCSR0B.UDRIE0 5 UART Data Register Empty Interrupt Enable +UCSR0B.RXEN0 4 Receiver Enable +UCSR0B.TXEN0 3 Transmitter Enable +UCSR0B.CHR90 2 9-bit Characters +UCSR0B.RXB80 1 Receive Data Bit 8 +UCSR0B.TXB80 0 Transmit Data Bit 8 +UCSR0A 0x000B UART0 Control and Status Register +UCSR0A.RXC0 7 UART Receive Complete +UCSR0A.TXC0 6 UART Transmit Complete +UCSR0A.UDRE0 5 UART Data Register Empty +UCSR0A.FE0 4 Framing Error +UCSR0A.OR0 3 OverRun +UCSR0A.U2X0 1 Double the UART Transmission Speed +UCSR0A.MPCM0 0 Multi-processor Communication Mode +UDR0 0x000C UART0 I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write Collision Flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low Byte +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High Byte +UBRRHI 0x0020 UART0 and UART1 High Byte Baud Rate Register +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +OCR2 0x0022 Timer/Counter2 Output Compare Register +TCNT2 0x0023 Timer/Counter2 Counter Register +ICR1L 0x0024 Input Capture Register Low Byte +ICR1H 0x0025 Input Capture Register High Byte +ASSR 0x0026 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 Mode +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +TCCR2 0x0027 Timer/Counter2 Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.PWM2 6 Pulse Width Modulator Enable +TCCR2.COM21 5 Compare Output Mode, Bit 1 +TCCR2.COM20 4 Compare Output Mode, Bit 0 +TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +TCCR2.CS22 2 Clock Select Bit 2 +TCCR2.CS21 1 Clock Select Bit 1 +TCCR2.CS20 0 Clock Select Bit 0 +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1, Bit 2 +TCCR1B.CS11 1 Clock Select1, Bit 1 +TCCR1B.CS10 0 Clock Select1, Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +TCCR1A.FOC1A 3 Force Output Compare1A +TCCR1A.FOC1B 2 Force Output Compare1B +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +SFIOR 0x0030 Special Function IO Register +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OCR0 0x0031 Timer/Counter0 Output Compare Register +TCNT0 0x0032 Timer/Counter0 Counter Register +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.PWM0 6 Pulse Width Modulator Enable +TCCR0.COM01 5 Compare Output Mode, Bit 1 +TCCR0.COM00 4 Compare Output Mode, Bit 0 +TCCR0.CTC0 3 Clear Timer/Counter on Compare Match +TCCR0.CS02 2 Clock Select Bit 2 +TCCR0.CS01 1 Clock Select Bit 1 +TCCR0.CS00 0 Clock Select Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.WDRF 3 Watchdog Reset Flag +MCUSR.BORF 2 Brown-out Reset Flag +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM Enable +MCUCR.SRW10 6 External SRAM Wait State +MCUCR.SE 5 Sleep Enable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +EMCUCR 0x0036 Extended MCU Control Register +EMCUCR.SM0 7 Sleep Mode Bit 0 +EMCUCR.SRL2 6 External SRAM Limit 2 +EMCUCR.SRL1 5 External SRAM Limit 1 +EMCUCR.SRL0 4 External SRAM Limit 0 +EMCUCR.SRW01 3 External SRAM Wait State Select Bit 01 +EMCUCR.SRW00 2 External SRAM Wait State Select Bit 00 +EMCUCR.SRW11 1 External SRAM Wait State Select Bit 11 +EMCUCR.ISC2 0 Interrupt Sense Control 2 +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter1 Overflow Flag +TIFR.OCF1A 6 Output Compare Flag 1A +TIFR.OCIFB 5 Output Compare Flag 1B +TIFR.TOV2 4 Timer/Counter2 Overflow Flag +TIFR.ICF1 3 Input Capture Flag 1 +TIFR.OCF2 2 Output Compare Flag 2 +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIFR.OCF0 0 Output Compare Flag 0 +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable +TIMSK.TOIE2 4 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.OCIE2 2 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable +GIFR 0x003A General Interrupt Flag +GIFR.INTF1 7 External Interrupt Flag1 +GIFR.INTF0 6 External Interrupt Flag0 +GIFR.INTF2 5 External Interrupt Flag2 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.INT2 5 External Interrupt Request 2 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 CarryFlag + +; UBRR1 0x0020 UART1 Baud Rate Register Low Byte +; UCSR1B 0x0021 UART1 Control and Status Register +; UCSR1B.RXCIE1 7 RX Complete Interrupt Enable +; UCSR1B.TXCIE1 6 TX Complete Interrupt Enable +; UCSR1B.UDRIE1 5 UART Data Register Empty Interrupt Enable +; UCSR1B.RXEN1 4 Receiver Enable +; UCSR1B.TXEN1 3 Transmitter Enable +; UCSR1B.CHR91 2 9-bit Characters +; UCSR1B.RXB81 1 Receive Data Bit 8 +; UCSR1B.TXB81 0 Transmit Data Bit 8 +; UCSR1A 0x0022 UART1 Control and Status Register +; UCSR1A.RXC1 7 UART Receive Complete +; UCSR1A.TXC1 6 UART Transmit Complete +; UCSR1A.UDRE1 5 UART Data Register Empty +; UCSR1A.FE1 4 Framing Error +; UCSR1A.OR1 3 OverRun +; UCSR1A.U2X1 1 Double the UART Transmission Speed +; UCSR1A.MPCM1 0 Multi-processor Communication Mode +; UDR1 0x0023 UART1 I/O Data Register +; RESERVED0024 0x0024 RESERVED +; PINE 0x0025 Port E Input Pins Address +; PINE.PINE2 2 +; PINE.PINE1 1 +; PINE.PINE0 0 +; DDRE 0x0026 Port E Data Direction Register +; DDRE.DDE2 2 Port E Data Direction Register bit 2 +; DDRE.DDE1 1 Port E Data Direction Register bit 1 +; DDRE.DDE0 0 Port E Data Direction Register bit 0 +; PORTE 0x0027 Port E Data Register +; PORTE.PORTE2 2 Port E Data Register bit 2 +; PORTE.PORTE1 1 Port E Data Register bit 1 +; PORTE.PORTE0 0 Port E Data Register bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.AINBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR0 0x0029 UART0 Baud Rate Register Low Byte +; UCSR0B 0x002A UART0 Control and StatusRegister +; UCSR0B.RXCIE0 7 RX Complete Interrupt Enable +; UCSR0B.TXCIE0 6 TX Complete Interrupt Enable +; UCSR0B.UDRIE0 5 UART Data Register Empty Interrupt Enable +; UCSR0B.RXEN0 4 Receiver Enable +; UCSR0B.TXEN0 3 Transmitter Enable +; UCSR0B.CHR90 2 9-bit Characters +; UCSR0B.RXB80 1 Receive Data Bit 8 +; UCSR0B.TXB80 0 Transmit Data Bit 8 +; UCSR0A 0x002B UART0 Control and Status Register +; UCSR0A.RXC0 7 UART Receive Complete +; UCSR0A.TXC0 6 UART Transmit Complete +; UCSR0A.UDRE0 5 UART Data Register Empty +; UCSR0A.FE0 4 Framing Error +; UCSR0A.OR0 3 OverRun +; UCSR0A.U2X0 1 Double the UART Transmission Speed +; UCSR0A.MPCM0 0 Multi-processor Communication Mode +; UDR0 0x002C UART0 I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write Collision Flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low Byte +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High Byte +; UBRRHI 0x0040 UART0 and UART1 High Byte Baud Rate Register +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; OCR2 0x0042 Timer/Counter2 Output Compare Register +; TCNT2 0x0043 Timer/Counter2 Counter Register +; ICR1L 0x0044 Input Capture Register Low Byte +; ICR1H 0x0045 Input Capture Register High Byte +; ASSR 0x0046 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 Mode +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; TCCR2 0x0047 Timer/Counter2 Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.PWM2 6 Pulse Width Modulator Enable +; TCCR2.COM21 5 Compare Output Mode, Bit 1 +; TCCR2.COM20 4 Compare Output Mode, Bit 0 +; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +; TCCR2.CS22 2 Clock Select Bit 2 +; TCCR2.CS21 1 Clock Select Bit 1 +; TCCR2.CS20 0 Clock Select Bit 0 +; OCR1BL 0x0048 Output Compare Register B Low Byte +; OCR1BH 0x0049 Output Compare Register B High Byte +; OCR1AL 0x004A Output Compare Register A Low Byte +; OCR1AH 0x004B Output Compare Register A High Byte +; TCNT1L 0x004C Counter Register Low Byte +; TCNT1H 0x004D Counter Register High Byte +; TCCR1B 0x004E Timer/Counter1 Control Register +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1, Bit 2 +; TCCR1B.CS11 1 Clock Select1, Bit 1 +; TCCR1B.CS10 0 Clock Select1, Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +; TCCR1A.FOC1A 3 Force Output Compare1A +; TCCR1A.FOC1B 2 Force Output Compare1B +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; SFIOR 0x0050 Special Function IO Register +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OCR0 0x0051 Timer/Counter0 Output Compare Register +; TCNT0 0x0052 Timer/Counter0 Counter Register +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.PWM0 6 Pulse Width Modulator Enable +; TCCR0.COM01 5 Compare Output Mode, Bit 1 +; TCCR0.COM00 4 Compare Output Mode, Bit 0 +; TCCR0.CTC0 3 Clear Timer/Counter on Compare Match +; TCCR0.CS02 2 Clock Select Bit 2 +; TCCR0.CS01 1 Clock Select Bit 1 +; TCCR0.CS00 0 Clock Select Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.WDRF 3 Watchdog Reset Flag +; MCUSR.BORF 2 Brown-out Reset Flag +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM Enable +; MCUCR.SRW10 6 External SRAM Wait State +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; EMCUCR 0x0056 Extended MCU Control Register +; EMCUCR.SM0 7 Sleep Mode Bit 0 +; EMCUCR.SRL2 6 External SRAM Limit 2 +; EMCUCR.SRL1 5 External SRAM Limit 1 +; EMCUCR.SRL0 4 External SRAM Limit 0 +; EMCUCR.SRW01 3 External SRAM Wait State Select Bit 01 +; EMCUCR.SRW00 2 External SRAM Wait State Select Bit 00 +; EMCUCR.SRW11 1 External SRAM Wait State Select Bit 11 +; EMCUCR.ISC2 0 Interrupt Sense Control 2 +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.TOV1 7 Timer/Counter1 Overflow Flag +; TIFR.OCF1A 6 Output Compare Flag 1A +; TIFR.OCIFB 5 Output Compare Flag 1B +; TIFR.TOV2 4 Timer/Counter2 Overflow Flag +; TIFR.ICF1 3 Input Capture Flag 1 +; TIFR.OCF2 2 Output Compare Flag 2 +; TIFR.TOV0 1 Timer/Counter0 Overflow Flag +; TIFR.OCF0 0 Output Compare Flag 0 +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 7 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.OCIE1A 6 Timer/Counter1 Output CompareA Match Interrupt Enable +; TIMSK.OCIE1B 5 Timer/Counter1 Output CompareB Match Interrupt Enable +; TIMSK.TOIE2 4 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 3 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.OCIE2 2 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable +; GIFR 0x005A General Interrupt Flag +; GIFR.INTF1 7 External Interrupt Flag1 +; GIFR.INTF0 6 External Interrupt Flag0 +; GIFR.INTF2 5 External Interrupt Flag2 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; GIMSK.INT2 5 External Interrupt Request 2 Enable +; RESERVED003C 0x005C RESERVED +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 CarryFlag + + +.ATmega162_L_V +SUBARCH=5 +; doc2513.pdf +; + +RAM=1024 +ROM=16384 +EEPROM=512 + +; MEMORY MAP +; Memory configuration A +area DATA FSR1 0x0000:0x0060 +area DATA FSR2 0x0060:0x008C Ext I/O Reg. +area BSS RESERVED 0x008C:0x0100 +area DATA I_SRAM 0x0100:0x0500 Internal SRAM +area DATA E_SRAM 0x0500:0x10000 External SRAM +; Memory configuration B +; area DATA FSR 0x0000:0x0060 +; area DATA I_SRAM 0x0060:0x0460 Internal SRAM +; area DATA E_SRAM 0x0460:0x10000 External SRAM + + +; Interrupt and reset vector assignments +; if M161C is unprogrammed +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry PCINT0_ 0x0008 Pin Change Interrupt Request 0 +entry PCINT1_ 0x000A Pin Change Interrupt Request 1 +entry TIMER3_CAPT 0x000C Timer/Counter3 Capture Event +entry TIMER3_COMPA 0x000E Timer/Counter3 Compare Match A +entry TIMER3_COMPB 0x0010 Timer/Counter3 Compare Match B +entry TIMER3_OVF 0x0012 Timer/Counter3 Overflow +entry TIMER2_COMP 0x0014 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0016 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0018 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x001A Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x001C Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x001E Timer/Counter1 Overflow +entry TIMER0_COMP 0x0020 Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0022 Timer/Counter0 Overflow +entry SPI_STC 0x0024 Serial Transfer Complete +entry USART0_RXC 0x0026 USART0, Rx Complete +entry USART1_RXC 0x0028 USART1, Rx Complete +entry USART0_UDRE 0x002A USART0 Data Register Empty +entry USART1_UDRE 0x002C USART1 Data Register Empty +entry USART0_TXC 0x002E USART0, Tx Complete +entry USART1_TXC 0x0030 USART1, Tx Complete +entry EE_RDY 0x0032 EEPROM Ready +entry ANA_COMP 0x0034 Analog Comparator +entry SPM_RDY 0x0036 Store Program Memory Ready + +; if M161C is programmed +; entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset +; entry INT0_ 0x0002 External Interrupt Request 0 +; entry INT1_ 0x0004 External Interrupt Request 1 +; entry INT2_ 0x0006 External Interrupt Request 2 +; entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match +; entry TIMER2_OVF 0x000A Timer/Counter2 Overflow +; entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event +; entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A +; entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B +; entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow +; entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match +; entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow +; entry SPI_STC 0x0018 Serial Transfer Complete +; entry USART0_RXC 0x001A USART0, Rx Complete +; entry USART1_RXC 0x001C USART1, Rx Complete +; entry USART0_UDRE 0x001E USART0 Data Register Empty +; entry USART1_UDRE 0x0020 USART1 Data Register Empty +; entry USART0_TXC 0x0022 USART0, Tx Complete +; entry USART1_TXC 0x0024 USART1, Tx Complete +; entry EE_RDY 0x0026 EEPROM Ready +; entry ANA_COMP 0x0028 Analog Comparator +; entry SPM_RDY 0x002A Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +UBRR1L 0x0000 USART1 Baud Rate Register Low Byte +UCSR1B 0x0001 USART Control and Status Register B +UCSR1B.RXCIE 7 RX Complete Interrupt Enable +UCSR1B.TXCIE 6 TX Complete Interrupt Enable +UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSR1B.RXEN 4 Receiver Enable +UCSR1B.TXEN 3 Transmitter Enable +UCSR1B.UCSZ2 2 Character Size +UCSR1B.RXB8 1 Receive Data Bit 8 +UCSR1B.TXB8 0 Transmit Data Bit8 +UCSR1A 0x0002 USART Control and Status Register A +UCSR1A.RXC 7 USART Receive Complete +UCSR1A.TXC 6 USART Transmit Complete +UCSR1A.UDRE 5 USART Data Register Empty +UCSR1A.FE 4 Frame Error +UCSR1A.DOR 3 Data OverRun +UCSR1A.PE 2 Parity Error +UCSR1A.U2X 1 Double the USART Transmission Speed +UCSR1A.MPCM 0 Multi-processor Communication Mode +UDR1 0x0003 USART I/O Data Register +OCDR 0x0004 On-chip Debug Register +; OSCCAL 0x0004 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +PINE 0x0005 Port E Input Pins Address +PINE.PINE2 2 +PINE.PINE1 1 +PINE.PINE0 0 +DDRE 0x0006 Port E Data Direction Register +DDRE.DDE2 2 Port E Data Direction Register bit 2 +DDRE.DDE1 1 Port E Data Direction Register bit 1 +DDRE.DDE0 0 Port E Data Direction Register bit 0 +PORTE 0x0007 Port E Data Register +PORTE.PORTE2 2 Port E Data Register bit 2 +PORTE.PORTE1 1 Port E Data Register bit 1 +PORTE.PORTE0 0 Port E Data Register bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR0L 0x0009 USART0 Baud Rate Register Low Byte +UCSR0B 0x000A USART Control and Status Register B +UCSR0B.RXCIE 7 RX Complete Interrupt Enable +UCSR0B.TXCIE 6 TX Complete Interrupt Enable +UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSR0B.RXEN 4 Receiver Enable +UCSR0B.TXEN 3 Transmitter Enable +UCSR0B.UCSZ2 2 Character Size +UCSR0B.RXB8 1 Receive Data Bit 8 +UCSR0B.TXB8 0 Transmit Data Bit8 +UCSR0A 0x000B USART Control and Status Register A +UCSR0A.RXC 7 USART Receive Complete +UCSR0A.TXC 6 USART Transmit Complete +UCSR0A.UDRE 5 USART Data Register Empty +UCSR0A.FE 4 Frame Error +UCSR0A.DOR 3 Data OverRun +UCSR0A.PE 2 Parity Error +UCSR0A.U2X 1 Double the USART Transmission Speed +UCSR0A.MPCM 0 Multi-processor Communication Mode +UDR0 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register- +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision Flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C The EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low Byte +EEARH 0x001F The EEPROM Address Register High +EEARH.EEAR8 8 EEPROM Address 8 +UCSR0C 0x0020 USART Control and Status Register C (page 180) +UCSR0C.URSEL 7 Register Select +UCSR0C.UMSEL 6 USART Mode Select +UCSR0C.UPM1 5 Parity Mode 1 +UCSR0C.UPM0 4 Parity Mode 0 +UCSR0C.USBS 3 Stop Bit Select +UCSR0C.UCSZ1 2 Character Size 1 +UCSR0C.UCSZ0 1 Character Size 0 +UCSR0C.UCPOL 0 Clock Polarity +; UBRR0H 0x0020 USART Baud Rate Register High +; UBRR0H.URSEL 15 Register Select +; UBRR0H.UBRR11 11 USART Baud Rate Register bit 11 +; UBRR0H.UBRR10 10 USART Baud Rate Register bit 10 +; UBRR0H.UBRR9 9 USART Baud Rate Register bit 9 +; UBRR0H.UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +OCR2 0x0022 Output Compare Register +TCNT2 0x0023 Timer/Counter2 +ICR1L 0x0024 Input Capture Register Low Byte +ICR1H 0x0025 Input Capture Register High Byte +ASSR 0x0026 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +TCCR2 0x0027 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Compare Match Output Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Waveform Generation Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input CaptureEdgeSelect +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 +TCCR1A.FOC1A 3 Force Output Compare for channel A +TCCR1A.FOC1B 2 Force Output Compare for channel B +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +SFIOR 0x0030 Special Function IO Register +SFIOR.TSM 7 Timer/Counter Synchronization Mode +SFIOR.XMBK 6 External Memory Bus Keeper Enable +SFIOR.XMM2 5 External Memory High Mask 2 +SFIOR.XMM1 4 External Memory High Mask 1 +SFIOR.XMM0 3 External Memory High Mask 0 +SFIOR.PUD 2 Pull-up Disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR310 0 Prescaler Reset Timer/Counter3, Timer/Counter1, and Timer/Counter0 +OCR0 0x0031 Timer/Counter0 Output Compare Register +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.JTD 7 JTAG Interface Disable +MCUCSR.SM2 5 Sleep Mode Select Bit 2 +MCUCSR.JTRF 4 JTAG Reset Flag +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM/XMEM Enable +MCUCR.SRW10 6 Wait State Select Bit +MCUCR.SE 5 Sleep Enable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +EMCUCR 0x0036 Extended MCU Control Register +EMCUCR.SM0 7 Sleep Mode Select Bit 0 +EMCUCR.SRL2 6 Wait State Sector Limit 2 +EMCUCR.SRL1 5 Wait State Sector Limit 1 +EMCUCR.SRL0 4 Wait State Sector Limit 0 +EMCUCR.SRW01 3 Wait-state Select Bits for Lower Sector 1 +EMCUCR.SRW00 2 Wait-state Select Bits for Lower Sector 0 +EMCUCR.SRW11 1 Wait-state Select Bits for Upper Sector +EMCUCR.ISC2 0 Interrupt Sense Control 2 +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.SPMIE 7 SPM Interrupt Enable +SPMCR.RWWSB 6 Read-While-Write Section Busy +SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter1, Overflow Flag +TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag +TIFR.OCF2 4 Output Compare Flag 2 +TIFR.ICF1 3 Timer/Counter1, Input Capture Flag +TIFR.TOV2 2 Timer/Counter2 Overflow Flag +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIFR.OCF0 0 Output Compare Flag 0 +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.OCIE2 4 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.TOIE2 2 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +TIMSK.OCIE0 0 Timer/Counter0 Overflow Flag +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIFR.INTF2 5 External Interrupt Flag 2 +GIFR.PCIF1 4 Pin Change Interrupt Flag 1 +GIFR.PCIF0 3 Pin Change Interrupt Flag 0 +GICR 0x003B General Interrupt Control Register +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.INT2 5 External Interrupt Request 2 Enable +GICR.PCIE1 4 Pin Change Interrupt Enable 1 +GICR.PCIE0 3 Pin Change Interrupt Enable 0 +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +UCSR1C 0x003C USART Control and Status Register C (page 180) +UCSR1C.URSEL 7 Register Select +UCSR1C.UMSEL 6 USART Mode Select +UCSR1C.UPM1 5 Parity Mode 1 +UCSR1C.UPM0 4 Parity Mode 0 +UCSR1C.USBS 3 Stop Bit Select +UCSR1C.UCSZ1 2 Character Size 1 +UCSR1C.UCSZ0 1 Character Size 0 +UCSR1C.UCPOL 0 Clock Polarity +; UBRR1H 0x003C USART Baud Rate Register High +; UBRR1H.URSEL 15 Register Select +; UBRR1H.UBRR11 11 USART Baud Rate Register 11 +; UBRR1H.UBRR10 10 USART Baud Rate Register 10 +; UBRR1H.UBRR9 9 USART Baud Rate Register 9 +; UBRR1H.UBRR8 8 USART Baud Rate Register 8 +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 CarryFlag + +; UBRR1L 0x0020 USART1 Baud Rate Register Low Byte +; UCSR1B 0x0021 USART Control and Status Register B +; UCSR1B.RXCIE 7 RX Complete Interrupt Enable +; UCSR1B.TXCIE 6 TX Complete Interrupt Enable +; UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSR1B.RXEN 4 Receiver Enable +; UCSR1B.TXEN 3 Transmitter Enable +; UCSR1B.UCSZ2 2 Character Size +; UCSR1B.RXB8 1 Receive Data Bit 8 +; UCSR1B.TXB8 0 Transmit Data Bit8 +; UCSR1A 0x0022 USART Control and Status Register A +; UCSR1A.RXC 7 USART Receive Complete +; UCSR1A.TXC 6 USART Transmit Complete +; UCSR1A.UDRE 5 USART Data Register Empty +; UCSR1A.FE 4 Frame Error +; UCSR1A.DOR 3 Data OverRun +; UCSR1A.PE 2 Parity Error +; UCSR1A.U2X 1 Double the USART Transmission Speed +; UCSR1A.MPCM 0 Multi-processor Communication Mode +; UDR1 0x0023 USART I/O Data Register +; OCDR 0x0024 On-chip Debug Register +; ; OSCCAL 0x0024 Oscillator Calibration Register +; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; PINE 0x0025 Port E Input Pins Address +; PINE.PINE2 2 +; PINE.PINE1 1 +; PINE.PINE0 0 +; DDRE 0x0026 Port E Data Direction Register +; DDRE.DDE2 2 Port E Data Direction Register bit 2 +; DDRE.DDE1 1 Port E Data Direction Register bit 1 +; DDRE.DDE0 0 Port E Data Direction Register bit 0 +; PORTE 0x0027 Port E Data Register +; PORTE.PORTE2 2 Port E Data Register bit 2 +; PORTE.PORTE1 1 Port E Data Register bit 1 +; PORTE.PORTE0 0 Port E Data Register bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR0L 0x0029 USART0 Baud Rate Register Low Byte +; UCSR0B 0x002A USART Control and Status Register B +; UCSR0B.RXCIE 7 RX Complete Interrupt Enable +; UCSR0B.TXCIE 6 TX Complete Interrupt Enable +; UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSR0B.RXEN 4 Receiver Enable +; UCSR0B.TXEN 3 Transmitter Enable +; UCSR0B.UCSZ2 2 Character Size +; UCSR0B.RXB8 1 Receive Data Bit 8 +; UCSR0B.TXB8 0 Transmit Data Bit8 +; UCSR0A 0x002B USART Control and Status Register A +; UCSR0A.RXC 7 USART Receive Complete +; UCSR0A.TXC 6 USART Transmit Complete +; UCSR0A.UDRE 5 USART Data Register Empty +; UCSR0A.FE 4 Frame Error +; UCSR0A.DOR 3 Data OverRun +; UCSR0A.PE 2 Parity Error +; UCSR0A.U2X 1 Double the USART Transmission Speed +; UCSR0A.MPCM 0 Multi-processor Communication Mode +; UDR0 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register- +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision Flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C The EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low Byte +; EEARH 0x003F The EEPROM Address Register High +; EEARH.EEAR8 8 EEPROM Address 8 +; UCSR0C 0x0040 USART Control and Status Register C (page 180) +; UCSR0C.URSEL 7 Register Select +; UCSR0C.UMSEL 6 USART Mode Select +; UCSR0C.UPM1 5 Parity Mode 1 +; UCSR0C.UPM0 4 Parity Mode 0 +; UCSR0C.USBS 3 Stop Bit Select +; UCSR0C.UCSZ1 2 Character Size 1 +; UCSR0C.UCSZ0 1 Character Size 0 +; UCSR0C.UCPOL 0 Clock Polarity +; ; UBRR0H 0x0040 USART Baud Rate Register High +; ; UBRR0H.URSEL 15 Register Select +; ; UBRR0H.UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRR0H.UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRR0H.UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRR0H.UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; OCR2 0x0042 Output Compare Register +; TCNT2 0x0043 Timer/Counter2 +; ICR1L 0x0044 Input Capture Register Low Byte +; ICR1H 0x0045 Input Capture Register High Byte +; ASSR 0x0046 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; TCCR2 0x0047 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Compare Match Output Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Waveform Generation Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; OCR1BL 0x0048 Output Compare Register B Low Byte +; OCR1BH 0x0049 Output Compare Register B High Byte +; OCR1AL 0x004A Output Compare Register A Low Byte +; OCR1AH 0x004B Output Compare Register A High Byte +; TCNT1L 0x004C Counter Register Low Byte +; TCNT1H 0x004D Counter Register High Byte +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input CaptureEdgeSelect +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 +; TCCR1A.FOC1A 3 Force Output Compare for channel A +; TCCR1A.FOC1B 2 Force Output Compare for channel B +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; SFIOR 0x0050 Special Function IO Register +; SFIOR.TSM 7 Timer/Counter Synchronization Mode +; SFIOR.XMBK 6 External Memory Bus Keeper Enable +; SFIOR.XMM2 5 External Memory High Mask 2 +; SFIOR.XMM1 4 External Memory High Mask 1 +; SFIOR.XMM0 3 External Memory High Mask 0 +; SFIOR.PUD 2 Pull-up Disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR310 0 Prescaler Reset Timer/Counter3, Timer/Counter1, and Timer/Counter0 +; OCR0 0x0051 Timer/Counter0 Output Compare Register +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.JTD 7 JTAG Interface Disable +; MCUCSR.SM2 5 Sleep Mode Select Bit 2 +; MCUCSR.JTRF 4 JTAG Reset Flag +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM/XMEM Enable +; MCUCR.SRW10 6 Wait State Select Bit +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; EMCUCR 0x0056 Extended MCU Control Register +; EMCUCR.SM0 7 Sleep Mode Select Bit 0 +; EMCUCR.SRL2 6 Wait State Sector Limit 2 +; EMCUCR.SRL1 5 Wait State Sector Limit 1 +; EMCUCR.SRL0 4 Wait State Sector Limit 0 +; EMCUCR.SRW01 3 Wait-state Select Bits for Lower Sector 1 +; EMCUCR.SRW00 2 Wait-state Select Bits for Lower Sector 0 +; EMCUCR.SRW11 1 Wait-state Select Bits for Upper Sector +; EMCUCR.ISC2 0 Interrupt Sense Control 2 +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.TOV1 7 Timer/Counter1, Overflow Flag +; TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag +; TIFR.OCF2 4 Output Compare Flag 2 +; TIFR.ICF1 3 Timer/Counter1, Input Capture Flag +; TIFR.TOV2 2 Timer/Counter2 Overflow Flag +; TIFR.TOV0 1 Timer/Counter0 Overflow Flag +; TIFR.OCF0 0 Output Compare Flag 0 +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.OCIE2 4 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.TOIE2 2 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; TIMSK.OCIE0 0 Timer/Counter0 Overflow Flag +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIFR.INTF2 5 External Interrupt Flag 2 +; GIFR.PCIF1 4 Pin Change Interrupt Flag 1 +; GIFR.PCIF0 3 Pin Change Interrupt Flag 0 +; GICR 0x005B General Interrupt Control Register +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.INT2 5 External Interrupt Request 2 Enable +; GICR.PCIE1 4 Pin Change Interrupt Enable 1 +; GICR.PCIE0 3 Pin Change Interrupt Enable 0 +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; UCSR1C 0x005C USART Control and Status Register C (page 180) +; UCSR1C.URSEL 7 Register Select +; UCSR1C.UMSEL 6 USART Mode Select +; UCSR1C.UPM1 5 Parity Mode 1 +; UCSR1C.UPM0 4 Parity Mode 0 +; UCSR1C.USBS 3 Stop Bit Select +; UCSR1C.UCSZ1 2 Character Size 1 +; UCSR1C.UCSZ0 1 Character Size 0 +; UCSR1C.UCPOL 0 Clock Polarity +; ; UBRR1H 0x005C USART Baud Rate Register High +; ; UBRR1H.URSEL 15 Register Select +; ; UBRR1H.UBRR11 11 USART Baud Rate Register 11 +; ; UBRR1H.UBRR10 10 USART Baud Rate Register 10 +; ; UBRR1H.UBRR9 9 USART Baud Rate Register 9 +; ; UBRR1H.UBRR8 8 USART Baud Rate Register 8 +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 CarryFlag +; RESERVED0060 0x0060 RESERVED +; CLKPR 0x0061 Clock Prescale Register +; CLKPR.CPCE 7 Clock Prescaler Change Enable +; CLKPR.CLKPS3 3 Clock Prescaler Select Bit 3 +; CLKPR.CLKPS2 2 Clock Prescaler Select Bit 2 +; CLKPR.CLKPS1 1 Clock Prescaler Select Bit 1 +; CLKPR.CLKPS0 0 Clock Prescaler Select Bit 0 +; RESERVED0062 0x0062 RESERVED +; RESERVED0063 0x0063 RESERVED +; RESERVED0064 0x0064 RESERVED +; RESERVED0065 0x0065 RESERVED +; RESERVED0066 0x0066 RESERVED +; RESERVED0067 0x0067 RESERVED +; RESERVED0068 0x0068 RESERVED +; RESERVED0069 0x0069 RESERVED +; RESERVED006A 0x006A RESERVED +; PCMSK0 0x006B Pin Change Mask Register 0 +; PCMSK0.PCINT7 7 Pin Change Enable Mask 7 +; PCMSK0.PCINT6 6 Pin Change Enable Mask 6 +; PCMSK0.PCINT5 5 Pin Change Enable Mask 5 +; PCMSK0.PCINT4 4 Pin Change Enable Mask 4 +; PCMSK0.PCINT3 3 Pin Change Enable Mask 3 +; PCMSK0.PCINT2 2 Pin Change Enable Mask 2 +; PCMSK0.PCINT1 1 Pin Change Enable Mask 1 +; PCMSK0.PCINT0 0 Pin Change Enable Mask 0 +; PCMSK1 0x006C Pin Change Mask Register 1 +; PCMSK1.PCINT15 15 Pin Change Enable Mask 15 +; PCMSK1.PCINT14 14 Pin Change Enable Mask 14 +; PCMSK1.PCINT13 13 Pin Change Enable Mask 13 +; PCMSK1.PCINT12 12 Pin Change Enable Mask 12 +; PCMSK1.PCINT11 11 Pin Change Enable Mask 11 +; PCMSK1.PCINT10 10 Pin Change Enable Mask 10 +; PCMSK1.PCINT9 9 Pin Change Enable Mask 9 +; PCMSK1.PCINT8 8 Pin Change Enable Mask 8 +; RESERVED006D 0x006D RESERVED +; RESERVED006E 0x006E RESERVED +; RESERVED006F 0x006F RESERVED +; RESERVED0070 0x0070 RESERVED +; RESERVED0071 0x0071 RESERVED +; RESERVED0072 0x0072 RESERVED +; RESERVED0073 0x0073 RESERVED +; RESERVED0074 0x0074 RESERVED +; RESERVED0075 0x0075 RESERVED +; RESERVED0076 0x0076 RESERVED +; RESERVED0077 0x0077 RESERVED +; RESERVED0078 0x0078 RESERVED +; RESERVED0079 0x0079 RESERVED +; RESERVED007A 0x007A RESERVED +; RESERVED007B 0x007B RESERVED +; ETIFR 0x007C Extended Timer/Counter Interrupt Flag Register +; ETIFR.ICF3 5 Timer/Counter3, Input Capture Flag +; ETIFR.OCF3A 4 Timer/Counter3, Output Compare A Match Flag +; ETIFR.OC3FB 3 Timer/Counter3, Output Compare B Match Flag +; ETIFR.TOV3 2 Timer/Counter3, Overflow Flag +; ETIMSK 0x007D Extended Timer/Counter Interrupt Mask Register +; ETIMSK.TICIE3 5 Timer/Counter3, Input Capture Interrupt Enable +; ETIMSK.OCIE3A 4 Timer/Counter3, Output Compare A Match Interrupt Enable +; ETIMSK.OCIE3B 3 Timer/Counter3, Output Compare B Match Interrupt Enable +; ETIMSK.TOIE3 2 Timer/Counter3, Overflow Interrupt Enable +; RESERVED007E 0x007E RESERVED +; RESERVED007F 0x007F RESERVED +; ICR3L 0x0080 Input Capture Register Low Byte +; ICR3H 0x0081 Input Capture Register High Byte +; RESERVED0082 0x0082 RESERVED +; RESERVED0083 0x0083 RESERVED +; OCR3BL 0x0084 Output Compare Register B Low Byte +; OCR3BH 0x0085 Output Compare Register B High Byte +; OCR3AL 0x0086 Output Compare Register A Low Byte +; OCR3AH 0x0087 Output Compare Register A High Byte +; TCNT3L 0x0088 Counter Register Low Byte +; TCNT3H 0x0089 Counter Register High Byte +; TCCR3B 0x008A Timer/Counter3 Control Register A +; TCCR3B.COM3A1 7 Compare Output Mode for channel A 1 +; TCCR3B.COM3A0 6 Compare Output Mode for channel A 0 +; TCCR3B.COM3B1 5 Compare Output Mode for channel B 1 +; TCCR3B.COM3B0 4 Compare Output Mode for channel B 0 +; TCCR3B.FOC3A 3 Force Output Compare for channel A +; TCCR3B.FOC3B 2 Force Output Compare for channel B +; TCCR3B.WGM31 1 Waveform Generation Mode 1 +; TCCR3B.WGM30 0 Waveform Generation Mode 0 +; TCCR3A 0x008B Timer/Counter3 Control Register B +; TCCR3A.ICNC3 7 Input Capture Noise Canceler +; TCCR3A.ICES3 6 Input CaptureEdgeSelect +; TCCR3A.WGM33 4 Waveform Generation Mode 3 +; TCCR3A.WGM32 3 Waveform Generation Mode 2 +; TCCR3A.CS32 2 Clock Select 2 +; TCCR3A.CS31 1 Clock Select 1 +; TCCR3A.CS30 0 Clock Select 0 + + +.ATmega163_L +SUBARCH=5 +; doc1142.pdf +; + +RAM=1024 +ROM=16384 +EEPROM=512 + +; MEMORY MAP + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry TIMER2_COMP 0x0006 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0008 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x000A Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x000C Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x000E Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0010 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0012 Timer/Counter0 Overflow +entry SPI_STC 0x0014 Serial Transfer Complete +entry UART_RXC 0x0016 UART, Rx Complete +entry UART_UDRE 0x0018 UART Data Register Empty +entry UART_TXC 0x001A UART, Tx Complete +entry ADC_ 0x001C ADC Conversion Complete +entry EE_RDY 0x001E EEPROM Ready +entry ANA_COMP 0x0020 Analog Comparator +entry TWI_ 0x0022 2-wire Serial Interface + + +; INPUT/OUTPUT PORTS +TWBR 0x0000 The 2-wire Serial Interface Bit Rate Register +TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 +TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 +TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 +TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 +TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 +TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 +TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 +TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 +TWSR 0x0001 The 2-wire Serial Interface Status Register +TWSR.TWS7 7 2-wire Serial Interface Status bit 7 +TWSR.TWS6 6 2-wire Serial Interface Status bit 6 +TWSR.TWS5 5 2-wire Serial Interface Status bit 5 +TWSR.TWS4 4 2-wire Serial Interface Status bit 4 +TWSR.TWS3 3 2-wire Serial Interface Status bit 3 +TWAR 0x0002 The 2-wire Serial Interface (Slave) Address Register +TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 +TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 +TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 +TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 +TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 +TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 +TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 +TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable Bit +TWDR 0x0003 The 2-wire Serial Interface Data Register +TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 +TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 +TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 +TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 +TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 +TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 +TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 +TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 +ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion result 7 +ADCL.ADC6 6 ADC Conversion result 6 +ADCL.ADC5 5 ADC Conversion result 5 +ADCL.ADC4 4 ADC Conversion result 4 +ADCL.ADC3 3 ADC Conversion result 3 +ADCL.ADC2 2 ADC Conversion result 2 +ADCL.ADC1 1 ADC Conversion result 1 +ADCL.ADC0 0 ADC Conversion result 0 +ADCH 0x0005 The ADC Data Register High (ADLAR = 0) +ADCH.SIGN 15 +ADCH.ADC9 9 ADC Conversion result 9 +ADCH.ADC8 8 ADC Conversion result 8 +; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion result 1 +; ADCL.ADC0 6 ADC Conversion result 0 +; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion result 9 +; ADCH.ADC8 14 ADC Conversion result 8 +; ADCH.ADC7 13 ADC Conversion result 7 +; ADCH.ADC6 12 ADC Conversion result 6 +; ADCH.ADC5 11 ADC Conversion result 5 +; ADCH.ADC4 10 ADC Conversion result 4 +; ADCH.ADC3 9 ADC Conversion result 3 +; ADCH.ADC2 8 ADC Conversion result 2 +ADCSR 0x0006 The ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Running Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 The ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control And Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR 0x0009 UART Baud Rate Register +UCSRB 0x000A UART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.CHR9 2 9 Bit Characters +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B UART Control and Status Register A +UCSRA.RXC 7 UART Receive Complete +UCSRA.TXC 6 UART Transmit Complete +UCSRA.UDRE 5 UART Data Register Empty +UCSRA.FE 4 Framing Error +UCSRA.OR 3 OverRun +UCSRA.U2X 1 Double the UART Transmission Speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C UART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E The SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision Flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C The EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Address 7 +EEARL.EEAR6 6 EEPROM Address 6 +EEARL.EEAR5 5 EEPROM Address 5 +EEARL.EEAR4 4 EEPROM Address 4 +EEARL.EEAR3 3 EEPROM Address 3 +EEARL.EEAR2 2 EEPROM Address 2 +EEARL.EEAR1 1 EEPROM Address 1 +EEARL.EEAR0 0 EEPROM Address 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR8 8 EEPROM Address 8 +UBRRHI 0x0020 UART Baud Rate Register +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +OCR2 0x0023 Timer/Counter2 Output Compare Register +TCNT2 0x0024 Timer/Counter2 +TCCR2 0x0025 Timer/Counter2 Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.PWM2 6 Pulse Width Modulator Enable +TCCR2.COM21 5 Compare Output Mode, bit 1 +TCCR2.COM20 4 Compare Output Mode, bit 0 +TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +TCCR2.CS22 2 Clock Select Bit 2 +TCCR2.CS21 1 Clock Select Bit 1 +TCCR2.CS20 0 Clock Select Bit 0 +ICR1L 0x0026 Input Capture Register Low Byte +ICR1H 0x0027 Input Capture Register High Byte +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1, Bit 2 +TCCR1B.CS11 1 Clock Select1, Bit 1 +TCCR1B.CS10 0 Clock Select1, Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +TCCR1A.FOC1A 3 Force Output Compare1A +TCCR1A.FOC1B 2 Force Output Compare1B +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +SFIOR 0x0030 Special Function I/O Register +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up Disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter 0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.WDRF 3 Watchdog Reset Flag +MCUSR.BORF 2 Brown-out Reset Flag +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 6 Sleep Enable +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +TWCR 0x0036 2-wire Serial Interface Control Register +TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag +TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag +TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag +TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag +TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag +TWCR.TWEN 2 2-wire Serial Interface Enable Bit +TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.ASB 6 Application Section Busy +SPMCR.ASRE 4 Application Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Input Capture Flag 1 +TIFR.OCF1A 4 Output Compare Flag 1A +TIFR.OCF1B 3 Output Compare Flag 1B +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag1 +GIFR.INTF0 6 External Interrupt Flag0 +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; TWBR 0x0020 The 2-wire Serial Interface Bit Rate Register +; TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 +; TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 +; TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 +; TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 +; TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 +; TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 +; TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 +; TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 +; TWSR 0x0021 The 2-wire Serial Interface Status Register +; TWSR.TWS7 7 2-wire Serial Interface Status bit 7 +; TWSR.TWS6 6 2-wire Serial Interface Status bit 6 +; TWSR.TWS5 5 2-wire Serial Interface Status bit 5 +; TWSR.TWS4 4 2-wire Serial Interface Status bit 4 +; TWSR.TWS3 3 2-wire Serial Interface Status bit 3 +; TWAR 0x0022 The 2-wire Serial Interface (Slave) Address Register +; TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 +; TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 +; TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 +; TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 +; TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 +; TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 +; TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 +; TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable Bit +; TWDR 0x0023 The 2-wire Serial Interface Data Register +; TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 +; TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 +; TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 +; TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 +; TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 +; TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 +; TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 +; TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 +; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion result 7 +; ADCL.ADC6 6 ADC Conversion result 6 +; ADCL.ADC5 5 ADC Conversion result 5 +; ADCL.ADC4 4 ADC Conversion result 4 +; ADCL.ADC3 3 ADC Conversion result 3 +; ADCL.ADC2 2 ADC Conversion result 2 +; ADCL.ADC1 1 ADC Conversion result 1 +; ADCL.ADC0 0 ADC Conversion result 0 +; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) +; ADCH.SIGN 15 +; ADCH.ADC9 9 ADC Conversion result 9 +; ADCH.ADC8 8 ADC Conversion result 8 +; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion result 1 +; ; ADCL.ADC0 6 ADC Conversion result 0 +; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion result 9 +; ; ADCH.ADC8 14 ADC Conversion result 8 +; ; ADCH.ADC7 13 ADC Conversion result 7 +; ; ADCH.ADC6 12 ADC Conversion result 6 +; ; ADCH.ADC5 11 ADC Conversion result 5 +; ; ADCH.ADC4 10 ADC Conversion result 4 +; ; ADCH.ADC3 9 ADC Conversion result 3 +; ; ADCH.ADC2 8 ADC Conversion result 2 +; ADCSR 0x0026 The ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADFR 5 ADC Free Running Select +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 The ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control And Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR 0x0029 UART Baud Rate Register +; UCSRB 0x002A UART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 UART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.CHR9 2 9 Bit Characters +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B UART Control and Status Register A +; UCSRA.RXC 7 UART Receive Complete +; UCSRA.TXC 6 UART Transmit Complete +; UCSRA.UDRE 5 UART Data Register Empty +; UCSRA.FE 4 Framing Error +; UCSRA.OR 3 OverRun +; UCSRA.U2X 1 Double the UART Transmission Speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C UART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E The SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision Flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C The EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Address 7 +; EEARL.EEAR6 6 EEPROM Address 6 +; EEARL.EEAR5 5 EEPROM Address 5 +; EEARL.EEAR4 4 EEPROM Address 4 +; EEARL.EEAR3 3 EEPROM Address 3 +; EEARL.EEAR2 2 EEPROM Address 2 +; EEARL.EEAR1 1 EEPROM Address 1 +; EEARL.EEAR0 0 EEPROM Address 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR8 8 EEPROM Address 8 +; UBRRHI 0x0040 UART Baud Rate Register +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; OCR2 0x0043 Timer/Counter2 Output Compare Register +; TCNT2 0x0044 Timer/Counter2 +; TCCR2 0x0045 Timer/Counter2 Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.PWM2 6 Pulse Width Modulator Enable +; TCCR2.COM21 5 Compare Output Mode, bit 1 +; TCCR2.COM20 4 Compare Output Mode, bit 0 +; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +; TCCR2.CS22 2 Clock Select Bit 2 +; TCCR2.CS21 1 Clock Select Bit 1 +; TCCR2.CS20 0 Clock Select Bit 0 +; ICR1L 0x0046 Input Capture Register Low Byte +; ICR1H 0x0047 Input Capture Register High Byte +; OCR1BL 0x0048 Output Compare Register B Low Byte +; OCR1BH 0x0049 Output Compare Register B High Byte +; OCR1AL 0x004A Output Compare Register A Low Byte +; OCR1AH 0x004B Output Compare Register A High Byte +; TCNT1L 0x004C Counter Register Low Byte +; TCNT1H 0x004D Counter Register High Byte +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1, Bit 2 +; TCCR1B.CS11 1 Clock Select1, Bit 1 +; TCCR1B.CS10 0 Clock Select1, Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1A, Bit 1 +; TCCR1A.COM1A0 6 Compare Output Mode1A, Bit 0 +; TCCR1A.COM1B1 5 Compare Output Mode1B, Bit 1 +; TCCR1A.COM1B0 4 Compare Output Mode1B, Bit 0 +; TCCR1A.FOC1A 3 Force Output Compare1A +; TCCR1A.FOC1B 2 Force Output Compare1B +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; SFIOR 0x0050 Special Function I/O Register +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up Disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OSCCAL 0x0051 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter 0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.WDRF 3 Watchdog Reset Flag +; MCUSR.BORF 2 Brown-out Reset Flag +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 6 Sleep Enable +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; TWCR 0x0056 2-wire Serial Interface Control Register +; TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag +; TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag +; TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag +; TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag +; TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag +; TWCR.TWEN 2 2-wire Serial Interface Enable Bit +; TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.ASB 6 Application Section Busy +; SPMCR.ASRE 4 Application Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Input Capture Flag 1 +; TIFR.OCF1A 4 Output Compare Flag 1A +; TIFR.OCF1B 3 Output Compare Flag 1B +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1 Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1 Output CompareA Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1 Output CompareB Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag1 +; GIFR.INTF0 6 External Interrupt Flag0 +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT1 7 External Interrupt Request 1 Enable +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; RESERVED003C 0x005C RESERVED +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega16_L +SUBARCH=5 +; doc2466.pdf +; + +RAM=1024 +ROM=16384 +EEPROM=512 + +; MEMORY MAP +area DATA FSR 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x0460 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry TIMER2_COMP 0x0006 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0008 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x000A Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x000C Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x000E Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0010 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0012 Timer/Counter0 Overflow +entry SPI_STC 0x0014 Serial Transfer Complete +entry USART_RXC 0x0016 USART, Rx Complete +entry USART_UDRE 0x0018 USART Data Register Empty +entry USART_TXC 0x001A USART, Tx Complete +entry ADC_ 0x001C ADC Conversion Complete +entry EE_RDY 0x001E EEPROM Ready +entry ANA_COMP 0x0020 Analog Comparator +entry TWI_ 0x0022 Two-wire Serial Interface +entry INT2 0x0024 External Interrupt Request 2 +entry TIMER0_COMP 0x0026 Timer/Counter0 Compare Match +entry SPM_RDY 0x0028 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +TWBR 0x0000 TWI Bit Rate Register +TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +TWSR 0x0001 TWI Status Register +TWSR.TWS7 7 TWI Status 7 +TWSR.TWS6 6 TWI Status 6 +TWSR.TWS5 5 TWI Status 5 +TWSR.TWS4 4 TWI Status 4 +TWSR.TWS3 3 TWI Status 3 +TWSR.TWS1 1 TWI Status 1 +TWSR.TWS0 0 TWI Status 0 +TWAR 0x0002 TWI (Slave) Address Register +TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +TWDR 0x0003 TWI Data Register +TWDR.TWD7 7 TWI Data Register bit 7 +TWDR.TWD6 6 TWI Data Register bit 6 +TWDR.TWD5 5 TWI Data Register bit 5 +TWDR.TWD4 4 TWI Data Register bit 4 +TWDR.TWD3 3 TWI Data Register bit 3 +TWDR.TWD2 2 TWI Data Register bit 2 +TWDR.TWD1 1 TWI Data Register bit 1 +TWDR.TWD0 0 TWI Data Register bit 0 +ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 +ADCL.ADC6 6 +ADCL.ADC5 5 +ADCL.ADC4 4 +ADCL.ADC3 3 +ADCL.ADC2 2 +ADCL.ADC1 1 +ADCL.ADC0 0 +ADCH 0x0005 The ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 +ADCH.ADC8 8 +; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 +; ADCL.ADC0 6 +; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 7 +; ADCH.ADC8 6 +; ADCH.ADC7 5 +; ADCH.ADC6 4 +; ADCH.ADC5 3 +; ADCH.ADC4 2 +; ADCH.ADC3 1 +; ADCH.ADC2 0 +ADCSRA 0x0006 ADC Control and Status Register A +ADCSRA.ADEN 7 ADC Enable +ADCSRA.ADSC 6 ADC Start Conversion +ADCSRA.ADATE 5 ADC Auto Trigger Enable +ADCSRA.ADIF 4 ADC Interrupt Flag +ADCSRA.ADIE 3 ADC Interrupt Enable +ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register Low Byte +UCSRB 0x000A USART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B USART Control and Status Register A +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.PE 2 Parity Error +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR8 8 EEPROM Addres 8 +UCSRC 0x0020 USART Control and Status Register C (page 155) +UCSRC.URSEL 7 Register Select +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +; UBRRH 0x0020 USART Baud Rate Register High (page 155) +; UBRRH.URSEL 15 Register Select +; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +OCR2 0x0023 Output Compare Register +TCNT2 0x0024 Timer/Counter Register +TCCR2 0x0025 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Waveform Generation Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Compare Match Output Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +ICR1L 0x0026 Input Capture Register Low Byte +ICR1H 0x0027 Input Capture Register High Byte +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input Capture Edge Select +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.FOC1A 3 Force Output Compare for Channel A +TCCR1A.FOC1B 2 Force Output Compare for Channel B +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +SFIOR 0x0030 Special Function I/O Register +SFIOR.ADTS2 7 ADC Auto Trigger Source 2 +SFIOR.ADTS1 6 ADC Auto Trigger Source 1 +SFIOR.ADTS0 5 ADC Auto Trigger Source 0 +SFIOR.ADHSM 4 ADC High Speed Mode +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OCDR 0x0031 On-chip Debug Register +; OSCCAL 0x0031 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter Register +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.JTD 7 JTAG Interface Disable +MCUCSR.ISC2 6 Interrupt Sense Control 2 +MCUCSR.JTRF 4 JTAG Reset Flag +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SM2 7 Sleep Mode Select Bit 2 +MCUCR.SE 6 Sleep Enable +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +TWCR 0x0036 TWI Control Register +TWCR.TWINT 7 TWI Interrupt Flag +TWCR.TWEA 6 TWI Enable Acknowledge Bit +TWCR.TWSTA 5 TWI START Condition Bit +TWCR.TWSTO 4 TWI STOP Condition Bit +TWCR.TWWC 3 TWI Write Collision Flag +TWCR.TWEN 2 TWI Enable Bit +TWCR.TWIE 0 TWI Interrupt Enable +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.SPMIE 7 SPM Interrupt Enable +SPMCR.RWWSB 6 Read-While-Write Section Busy +SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter0 Overflow Flag 2 +TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +TIFR.TOV1 2 Timer/Counter0 Overflow Flag 1 +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag 0 +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIFR.INTF2 5 External Interrupt Flag 2 +GICR 0x003B General Interrupt Control Register +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.INT2 5 External Interrupt Request 2 Enable +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +OCR0 0x003C Output Compare Register +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 CarryFlag + +; TWBR 0x0020 TWI Bit Rate Register +; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +; TWSR 0x0021 TWI Status Register +; TWSR.TWS7 7 TWI Status 7 +; TWSR.TWS6 6 TWI Status 6 +; TWSR.TWS5 5 TWI Status 5 +; TWSR.TWS4 4 TWI Status 4 +; TWSR.TWS3 3 TWI Status 3 +; TWSR.TWS1 1 TWI Status 1 +; TWSR.TWS0 0 TWI Status 0 +; TWAR 0x0022 TWI (Slave) Address Register +; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +; TWDR 0x0023 TWI Data Register +; TWDR.TWD7 7 TWI Data Register bit 7 +; TWDR.TWD6 6 TWI Data Register bit 6 +; TWDR.TWD5 5 TWI Data Register bit 5 +; TWDR.TWD4 4 TWI Data Register bit 4 +; TWDR.TWD3 3 TWI Data Register bit 3 +; TWDR.TWD2 2 TWI Data Register bit 2 +; TWDR.TWD1 1 TWI Data Register bit 1 +; TWDR.TWD0 0 TWI Data Register bit 0 +; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 +; ADCL.ADC6 6 +; ADCL.ADC5 5 +; ADCL.ADC4 4 +; ADCL.ADC3 3 +; ADCL.ADC2 2 +; ADCL.ADC1 1 +; ADCL.ADC0 0 +; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 +; ADCH.ADC8 8 +; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 +; ; ADCL.ADC0 6 +; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 7 +; ; ADCH.ADC8 6 +; ; ADCH.ADC7 5 +; ; ADCH.ADC6 4 +; ; ADCH.ADC5 3 +; ; ADCH.ADC4 2 +; ; ADCH.ADC3 1 +; ; ADCH.ADC2 0 +; ADCSRA 0x0026 ADC Control and Status Register A +; ADCSRA.ADEN 7 ADC Enable +; ADCSRA.ADSC 6 ADC Start Conversion +; ADCSRA.ADATE 5 ADC Auto Trigger Enable +; ADCSRA.ADIF 4 ADC Interrupt Flag +; ADCSRA.ADIE 3 ADC Interrupt Enable +; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRRL 0x0029 USART Baud Rate Register Low Byte +; UCSRB 0x002A USART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.UCSZ2 2 Character Size +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B USART Control and Status Register A +; UCSRA.RXC 7 USART Receive Complete +; UCSRA.TXC 6 USART Transmit Complete +; UCSRA.UDRE 5 USART Data Register Empty +; UCSRA.FE 4 Frame Error +; UCSRA.DOR 3 Data OverRun +; UCSRA.PE 2 Parity Error +; UCSRA.U2X 1 Double the USART Transmission Speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR8 8 EEPROM Addres 8 +; UCSRC 0x0040 USART Control and Status Register C (page 155) +; UCSRC.URSEL 7 Register Select +; UCSRC.UMSEL 6 USART Mode Select +; UCSRC.UPM1 5 Parity Mode 1 +; UCSRC.UPM0 4 Parity Mode 0 +; UCSRC.USBS 3 Stop Bit Select +; UCSRC.UCSZ1 2 Character Size 1 +; UCSRC.UCSZ0 1 Character Size 0 +; UCSRC.UCPOL 0 Clock Polarity +; ; UBRRH 0x0040 USART Baud Rate Register High (page 155) +; ; UBRRH.URSEL 15 Register Select +; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; OCR2 0x0043 Output Compare Register +; TCNT2 0x0044 Timer/Counter Register +; TCCR2 0x0045 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Waveform Generation Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Compare Match Output Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; ICR1L 0x0046 Input Capture Register Low Byte +; ICR1H 0x0047 Input Capture Register High Byte +; OCR1BL 0x0048 Output Compare Register B Low Byte +; OCR1BH 0x0049 Output Compare Register B High Byte +; OCR1AL 0x004A Output Compare Register A Low Byte +; OCR1AH 0x004B Output Compare Register A High Byte +; TCNT1L 0x004C Counter Register Low Byte +; TCNT1H 0x004D Counter Register High Byte +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input Capture Edge Select +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +; TCCR1A.FOC1A 3 Force Output Compare for Channel A +; TCCR1A.FOC1B 2 Force Output Compare for Channel B +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; SFIOR 0x0050 Special Function I/O Register +; SFIOR.ADTS2 7 ADC Auto Trigger Source 2 +; SFIOR.ADTS1 6 ADC Auto Trigger Source 1 +; SFIOR.ADTS0 5 ADC Auto Trigger Source 0 +; SFIOR.ADHSM 4 ADC High Speed Mode +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OCDR 0x0051 On-chip Debug Register +; ; OSCCAL 0x0051 Oscillator Calibration Register +; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter Register +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.JTD 7 JTAG Interface Disable +; MCUCSR.ISC2 6 Interrupt Sense Control 2 +; MCUCSR.JTRF 4 JTAG Reset Flag +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SM2 7 Sleep Mode Select Bit 2 +; MCUCR.SE 6 Sleep Enable +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; TWCR 0x0056 TWI Control Register +; TWCR.TWINT 7 TWI Interrupt Flag +; TWCR.TWEA 6 TWI Enable Acknowledge Bit +; TWCR.TWSTA 5 TWI START Condition Bit +; TWCR.TWSTO 4 TWI STOP Condition Bit +; TWCR.TWWC 3 TWI Write Collision Flag +; TWCR.TWEN 2 TWI Enable Bit +; TWCR.TWIE 0 TWI Interrupt Enable +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter0 Overflow Flag 2 +; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +; TIFR.TOV1 2 Timer/Counter0 Overflow Flag 1 +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag 0 +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIFR.INTF2 5 External Interrupt Flag 2 +; GICR 0x005B General Interrupt Control Register +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.INT2 5 External Interrupt Request 2 Enable +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; OCR0 0x005C Output Compare Register +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 CarryFlag + + +.ATmega323_L +SUBARCH=5 +; doc1457.pdf +; + +RAM=2048 +ROM=32768 +EEPROM=1024 + + +; MEMORY MAP + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x000A Timer/Counter2 Overflow +entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow +entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow +entry SPI_STC 0x0018 Serial Transfer Complete +entry USART_RXC 0x001A USART, Rx Complete +entry USART_UDRE 0x001C USART Data Register Empty +entry USART_TXC 0x001E USART, Tx Complete +entry ADC_ 0x0020 ADC Conversion Complete +entry EE_RDY 0x0022 EEPROM Ready +entry ANA_COMP 0x0024 Analog Comparator +entry TWSI_ 0x0026 2-wire Serial Interface + + +; INPUT/OUTPUT PORTS +TWBR 0x0000 2-wire Serial Interface Bit vRate Register +TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 +TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 +TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 +TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 +TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 +TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 +TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 +TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 +TWSR 0x0001 2-wire Serial Interface Status Register +TWSR.TWS7 7 2-wire Serial Interface Status bit 7 +TWSR.TWS6 6 2-wire Serial Interface Status bit 6 +TWSR.TWS5 5 2-wire Serial Interface Status bit 5 +TWSR.TWS4 4 2-wire Serial Interface Status bit 4 +TWSR.TWS3 3 2-wire Serial Interface Status bit 3 +TWAR 0x0002 2-wire Serial Interface (Slave) Address Register +TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 +TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 +TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 +TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 +TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 +TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 +TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 +TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable bit +TWDR 0x0003 2-wire Serial Interface Data Register +TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 +TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 +TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 +TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 +TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 +TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 +TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 +TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 +ADCL 0x0004 ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion Result 7 +ADCL.ADC6 6 ADC Conversion Result 6 +ADCL.ADC5 5 ADC Conversion Result 5 +ADCL.ADC4 4 ADC Conversion Result 4 +ADCL.ADC3 3 ADC Conversion Result 3 +ADCL.ADC2 2 ADC Conversion Result 2 +ADCL.ADC1 1 ADC Conversion Result 1 +ADCL.ADC0 0 ADC Conversion Result 0 +ADCH 0x0005 ADC Data Register High (ADLAR = 0) +ADCH.SIGN 15 +ADCH.ADC9 9 ADC Conversion Result 9 +ADCH.ADC8 8 ADC Conversion Result 8 +; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion Result 1 +; ADCL.ADC0 6 ADC Conversion Result 0 +; ADCH 0x0005 ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion Result 9 +; ADCH.ADC8 14 ADC Conversion Result 8 +; ADCH.ADC7 13 ADC Conversion Result 7 +; ADCH.ADC6 12 ADC Conversion Result 6 +; ADCH.ADC5 11 ADC Conversion Result 5 +; ADCH.ADC4 10 ADC Conversion Result 4 +; ADCH.ADC3 9 ADC Conversion Result 3 +; ADCH.ADC2 8 ADC Conversion Result 2 +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Running Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel Selection Bit 4 +ADMUX.MUX3 3 Analog Channel Selection Bit 3 +ADMUX.MUX2 2 Analog Channel Selection Bit 2 +ADMUX.MUX1 1 Analog Channel Selection Bit 1 +ADMUX.MUX0 0 Analog Channel Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register Low +UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +UCSRB 0x000A USART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B USART Control and Status Register A +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.PE 2 Parity Error +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR9 9 EEPROM Addres 9 +EEARH.EEAR8 8 EEPROM Addres 8 +UCSRC 0x0020 USART Control and Status Register (page 91) +UCSRC.URSEL 7 Register Select +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +; UBRRH 0x0020 USART Baud Rate Register High (page 91) +; UBRRH.URSEL 15 Register Select +; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watch Dog Turn-off Enable +WDTCR.WDE 3 Watch Dog Enable +WDTCR.WDP2 2 Watch Dog Timer Prescaler 2 +WDTCR.WDP1 1 Watch Dog Timer Prescaler 1 +WDTCR.WDP0 0 Watch Dog Timer Prescaler 0 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +OCR2 0x0023 Timer/Counter2 Output Compare Register +TCNT2 0x0024 Timer/Counter2 +TCCR2 0x0025 Timer/Counter2 Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.PWM2 6 Pulse Width Modulator Enable +TCCR2.COM21 5 Compare Output Mode, Bit 1 +TCCR2.COM20 4 Compare Output Mode, Bit 0 +TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +TCCR2.CS22 2 Clock Select bit 2 +TCCR2.CS21 1 Clock Select bit 1 +TCCR2.CS20 0 Clock Select bit 0 +ICR1L 0x0026 Input Capture Register Low Byte +ICR1H 0x0027 Input Capture Register High Byte +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +TCCR1B.ICES1 6 Input Capture1 Edge Select +TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +TCCR1B.CS12 2 Clock Select1, Bit 2 +TCCR1B.CS11 1 Clock Select1, Bit 1 +TCCR1B.CS10 0 Clock Select1, Bit 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode1A, bit 1 +TCCR1A.COM1A0 6 Compare Output Mode1A, bit 0 +TCCR1A.COM1B1 5 Compare Output Mode1B, bit 1 +TCCR1A.COM1B0 4 Compare Output Mode1B, bit 0 +TCCR1A.FOC1A 3 Force Output Compare1A +TCCR1A.FOC1B 2 Force Output Compare1B +TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +SFIOR 0x0030 Special Function IO Register +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up Disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OCRD 0x0031 On-chip Debug Register +; OSCCAL 0x0031 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.PWM0 6 Pulse Width Modulator Enable +TCCR0.COM01 5 Compare Output Mode, Bit 1 +TCCR0.COM00 4 Compare Output Mode, Bit 0 +TCCR0.CTC0 3 Clear Timer/Counter on Compare Match +TCCR0.CS02 2 Clock Select bit 2 +TCCR0.CS01 1 Clock Select bit 1 +TCCR0.CS00 0 Clock Select bit 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.JTD 7 JTAG interface disable +MCUCSR.ISC2 6 Interrupt Sense Control 2 +MCUCSR.JTRF 4 JTAG Reset Flag +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 7 Sleep Enable +MCUCR.SM2 6 Sleep Mode Select Bit 2 +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +TWCR 0x0036 2-wire Serial Interface Control Register +TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag +TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag +TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag +TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag +TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag +TWCR.TWEN 2 2-wire Serial Interface Enable Bit +TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.ASB 6 Application Section Busy +SPMCR.ASRE 4 Application Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Input Capture Flag 1 +TIFR.OCF1A 4 Output Compare Flag 1A +TIFR.OCF1B 3 Output Compare Flag 1B +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Flag Register +TIMSK.OCF2 7 Output Compare Flag 2 +TIMSK.TOV2 6 Timer/Counter2 Overflow Flag +TIMSK.ICF1 5 Input Capture Flag 1 +TIMSK.OCF1A 4 Output Compare Flag 1A +TIMSK.OCF1B 3 Output Compare Flag 1B +TIMSK.TOV1 2 Timer/Counter1 Overflow Flag +TIMSK.OCF0 1 Output Compare Flag 0 +TIMSK.TOV0 0 Timer/Counter0 Overflow Flag +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag1 +GIFR.INTF0 6 External Interrupt Flag0 +GIFR.INTF2 5 External Interrupt Flag2 +GICR 0x003B General Interrupt Control Register +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.INT2 5 External Interrupt Request 2 Enable +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +OCR0 0x003C Timer/Counter0 Output Compare Register +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; TWBR 0x0020 2-wire Serial Interface Bit vRate Register +; TWBR.TWBR7 7 2-wire Serial Interface Bit Rate Register bit 7 +; TWBR.TWBR6 6 2-wire Serial Interface Bit Rate Register bit 6 +; TWBR.TWBR5 5 2-wire Serial Interface Bit Rate Register bit 5 +; TWBR.TWBR4 4 2-wire Serial Interface Bit Rate Register bit 4 +; TWBR.TWBR3 3 2-wire Serial Interface Bit Rate Register bit 3 +; TWBR.TWBR2 2 2-wire Serial Interface Bit Rate Register bit 2 +; TWBR.TWBR1 1 2-wire Serial Interface Bit Rate Register bit 1 +; TWBR.TWBR0 0 2-wire Serial Interface Bit Rate Register bit 0 +; TWSR 0x0021 2-wire Serial Interface Status Register +; TWSR.TWS7 7 2-wire Serial Interface Status bit 7 +; TWSR.TWS6 6 2-wire Serial Interface Status bit 6 +; TWSR.TWS5 5 2-wire Serial Interface Status bit 5 +; TWSR.TWS4 4 2-wire Serial Interface Status bit 4 +; TWSR.TWS3 3 2-wire Serial Interface Status bit 3 +; TWAR 0x0022 2-wire Serial Interface (Slave) Address Register +; TWAR.TWA6 7 2-wire Serial Interface (Slave) Address Register bit 6 +; TWAR.TWA5 6 2-wire Serial Interface (Slave) Address Register bit 5 +; TWAR.TWA4 5 2-wire Serial Interface (Slave) Address Register bit 4 +; TWAR.TWA3 4 2-wire Serial Interface (Slave) Address Register bit 3 +; TWAR.TWA2 3 2-wire Serial Interface (Slave) Address Register bit 2 +; TWAR.TWA1 2 2-wire Serial Interface (Slave) Address Register bit 1 +; TWAR.TWA0 1 2-wire Serial Interface (Slave) Address Register bit 0 +; TWAR.TWGCE 0 2-wire Serial Interface General Call Recognition Enable bit +; TWDR 0x0023 2-wire Serial Interface Data Register +; TWDR.TWD7 7 2-wire Serial Interface Data Register bit 7 +; TWDR.TWD6 6 2-wire Serial Interface Data Register bit 6 +; TWDR.TWD5 5 2-wire Serial Interface Data Register bit 5 +; TWDR.TWD4 4 2-wire Serial Interface Data Register bit 4 +; TWDR.TWD3 3 2-wire Serial Interface Data Register bit 3 +; TWDR.TWD2 2 2-wire Serial Interface Data Register bit 2 +; TWDR.TWD1 1 2-wire Serial Interface Data Register bit 1 +; TWDR.TWD0 0 2-wire Serial Interface Data Register bit 0 +; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion Result 7 +; ADCL.ADC6 6 ADC Conversion Result 6 +; ADCL.ADC5 5 ADC Conversion Result 5 +; ADCL.ADC4 4 ADC Conversion Result 4 +; ADCL.ADC3 3 ADC Conversion Result 3 +; ADCL.ADC2 2 ADC Conversion Result 2 +; ADCL.ADC1 1 ADC Conversion Result 1 +; ADCL.ADC0 0 ADC Conversion Result 0 +; ADCH 0x0025 ADC Data Register High (ADLAR = 0) +; ADCH.SIGN 15 +; ADCH.ADC9 9 ADC Conversion Result 9 +; ADCH.ADC8 8 ADC Conversion Result 8 +; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion Result 1 +; ; ADCL.ADC0 6 ADC Conversion Result 0 +; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion Result 9 +; ; ADCH.ADC8 14 ADC Conversion Result 8 +; ; ADCH.ADC7 13 ADC Conversion Result 7 +; ; ADCH.ADC6 12 ADC Conversion Result 6 +; ; ADCH.ADC5 11 ADC Conversion Result 5 +; ; ADCH.ADC4 10 ADC Conversion Result 4 +; ; ADCH.ADC3 9 ADC Conversion Result 3 +; ; ADCH.ADC2 8 ADC Conversion Result 2 +; ADCSR 0x0026 ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADFR 5 ADC Free Running Select +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRRL 0x0029 USART Baud Rate Register Low +; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +; UCSRB 0x002A USART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.UCSZ2 2 Character Size +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B USART Control and Status Register A +; UCSRA.RXC 7 USART Receive Complete +; UCSRA.TXC 6 USART Transmit Complete +; UCSRA.UDRE 5 USART Data Register Empty +; UCSRA.FE 4 Frame Error +; UCSRA.DOR 3 Data OverRun +; UCSRA.PE 2 Parity Error +; UCSRA.U2X 1 Double the USART Transmission Speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEDR.EEDR7 7 EEPROM Data 7 +; EEDR.EEDR6 6 EEPROM Data 6 +; EEDR.EEDR5 5 EEPROM Data 5 +; EEDR.EEDR4 4 EEPROM Data 4 +; EEDR.EEDR3 3 EEPROM Data 3 +; EEDR.EEDR2 2 EEPROM Data 2 +; EEDR.EEDR1 1 EEPROM Data 1 +; EEDR.EEDR0 0 EEPROM Data 0 +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR9 9 EEPROM Addres 9 +; EEARH.EEAR8 8 EEPROM Addres 8 +; UCSRC 0x0040 USART Control and Status Register (page 91) +; UCSRC.URSEL 7 Register Select +; UCSRC.UMSEL 6 USART Mode Select +; UCSRC.UPM1 5 Parity Mode 1 +; UCSRC.UPM0 4 Parity Mode 0 +; UCSRC.USBS 3 Stop Bit Select +; UCSRC.UCSZ1 2 Character Size 1 +; UCSRC.UCSZ0 1 Character Size 0 +; UCSRC.UCPOL 0 Clock Polarity +; ; UBRRH 0x0040 USART Baud Rate Register High (page 91) +; ; UBRRH.URSEL 15 Register Select +; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watch Dog Turn-off Enable +; WDTCR.WDE 3 Watch Dog Enable +; WDTCR.WDP2 2 Watch Dog Timer Prescaler 2 +; WDTCR.WDP1 1 Watch Dog Timer Prescaler 1 +; WDTCR.WDP0 0 Watch Dog Timer Prescaler 0 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; OCR2 0x0043 Timer/Counter2 Output Compare Register +; TCNT2 0x0044 Timer/Counter2 +; TCCR2 0x0045 Timer/Counter2 Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.PWM2 6 Pulse Width Modulator Enable +; TCCR2.COM21 5 Compare Output Mode, Bit 1 +; TCCR2.COM20 4 Compare Output Mode, Bit 0 +; TCCR2.CTC2 3 Clear Timer/Counter on Compare Match +; TCCR2.CS22 2 Clock Select bit 2 +; TCCR2.CS21 1 Clock Select bit 1 +; TCCR2.CS20 0 Clock Select bit 0 +; ICR1L 0x0026 Input Capture Register Low Byte +; ICR1H 0x0027 Input Capture Register High Byte +; OCR1BL 0x0028 Output Compare Register B Low Byte +; OCR1BH 0x0029 Output Compare Register B High Byte +; OCR1AL 0x002A Output Compare Register A Low Byte +; OCR1AH 0x002B Output Compare Register A High Byte +; TCNT1L 0x002C Counter Register Low Byte +; TCNT1H 0x002D Counter Register High Byte +; TCCR1B 0x002E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture1 Noise Canceler (4 CKs) +; TCCR1B.ICES1 6 Input Capture1 Edge Select +; TCCR1B.CTC1 3 Clear Timer/Counter1 on Compare Match +; TCCR1B.CS12 2 Clock Select1, Bit 2 +; TCCR1B.CS11 1 Clock Select1, Bit 1 +; TCCR1B.CS10 0 Clock Select1, Bit 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode1A, bit 1 +; TCCR1A.COM1A0 6 Compare Output Mode1A, bit 0 +; TCCR1A.COM1B1 5 Compare Output Mode1B, bit 1 +; TCCR1A.COM1B0 4 Compare Output Mode1B, bit 0 +; TCCR1A.FOC1A 3 Force Output Compare1A +; TCCR1A.FOC1B 2 Force Output Compare1B +; TCCR1A.PWM11 1 Pulse Width Modulator Select Bit 1 +; TCCR1A.PWM10 0 Pulse Width Modulator Select Bit 0 +; SFIOR 0x0050 Special Function IO Register +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up Disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OCRD 0x0051 On-chip Debug Register +; ; OSCCAL 0x0051 Oscillator Calibration Register +; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.PWM0 6 Pulse Width Modulator Enable +; TCCR0.COM01 5 Compare Output Mode, Bit 1 +; TCCR0.COM00 4 Compare Output Mode, Bit 0 +; TCCR0.CTC0 3 Clear Timer/Counter on Compare Match +; TCCR0.CS02 2 Clock Select bit 2 +; TCCR0.CS01 1 Clock Select bit 1 +; TCCR0.CS00 0 Clock Select bit 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.JTD 7 JTAG interface disable +; MCUCSR.ISC2 6 Interrupt Sense Control 2 +; MCUCSR.JTRF 4 JTAG Reset Flag +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 7 Sleep Enable +; MCUCR.SM2 6 Sleep Mode Select Bit 2 +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; TWCR 0x0056 2-wire Serial Interface Control Register +; TWCR.TWINT 7 2-wire Serial Interface Interrupt Flag +; TWCR.TWEA 6 2-wire Serial Interface Enable Acknowledge Flag +; TWCR.TWSTA 5 2-wire Serial Bus START Condition Flag +; TWCR.TWSTO 4 2-wire Serial Bus STOP Condition Flag +; TWCR.TWWC 3 2-wire Serial Bus Write Collision Flag +; TWCR.TWEN 2 2-wire Serial Interface Enable Bit +; TWCR.TWIE 0 2-wire Serial Interface Interrupt Enable +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.ASB 6 Application Section Busy +; SPMCR.ASRE 4 Application Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Input Capture Flag 1 +; TIFR.OCF1A 4 Output Compare Flag 1A +; TIFR.OCF1B 3 Output Compare Flag 1B +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Flag Register +; TIMSK.OCF2 7 Output Compare Flag 2 +; TIMSK.TOV2 6 Timer/Counter2 Overflow Flag +; TIMSK.ICF1 5 Input Capture Flag 1 +; TIMSK.OCF1A 4 Output Compare Flag 1A +; TIMSK.OCF1B 3 Output Compare Flag 1B +; TIMSK.TOV1 2 Timer/Counter1 Overflow Flag +; TIMSK.OCF0 1 Output Compare Flag 0 +; TIMSK.TOV0 0 Timer/Counter0 Overflow Flag +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag1 +; GIFR.INTF0 6 External Interrupt Flag0 +; GIFR.INTF2 5 External Interrupt Flag2 +; GICR 0x005B General Interrupt Control Register +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.INT2 5 External Interrupt Request 2 Enable +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; OCR0 0x005C Timer/Counter0 Output Compare Register +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega32_L +SUBARCH=5 +; doc2503.pdf +; + +RAM=2048 +ROM=32768 +EEPROM=1024 + +; MEMORY MAP + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry TIMER2_COMP 0x0008 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x000A Timer/Counter2 Overflow +entry TIMER1_CAPT 0x000C Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x000E Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0010 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0012 Timer/Counter1 Overflow +entry TIMER0_COMP 0x0014 Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0016 Timer/Counter0 Overflow +entry SPI_STC 0x0018 Serial Transfer Complete +entry USART_RXC 0x001A USART, Rx Complete +entry USART_UDRE 0x001C USART Data Register Empty +entry USART_TXC 0x001E USART, Tx Complete +entry ADC_ 0x0020 ADC Conversion Complete +entry EE_RDY 0x0022 EEPROM Ready +entry ANA_COMP 0x0024 Analog Comparator +entry TWI_ 0x0026 Two-wire Serial Interface +entry SPM_RDY 0x0028 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +TWBR 0x0000 Two-wire Serial Interface Bit Rate Register +TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +TWSR 0x0001 TWI Status Register +TWSR.TWS7 7 TWI Status 7 +TWSR.TWS6 6 TWI Status 6 +TWSR.TWS5 5 TWI Status 5 +TWSR.TWS4 4 TWI Status 4 +TWSR.TWS3 3 TWI Status 3 +TWSR.TWS1 1 TWI Prescaler Bit 1 +TWSR.TWS0 0 TWI Prescaler Bit 0 +TWAR 0x0002 TWI (Slave) Address Register +TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +TWDR 0x0003 TWI Data Register +TWDR.TWD7 7 TWI Data Register bit 7 +TWDR.TWD6 6 TWI Data Register bit 6 +TWDR.TWD5 5 TWI Data Register bit 5 +TWDR.TWD4 4 TWI Data Register bit 4 +TWDR.TWD3 3 TWI Data Register bit 3 +TWDR.TWD2 2 TWI Data Register bit 2 +TWDR.TWD1 1 TWI Data Register bit 1 +TWDR.TWD0 0 TWI Data Register bit 0 +ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion result 7 +ADCL.ADC6 6 ADC Conversion result 6 +ADCL.ADC5 5 ADC Conversion result 5 +ADCL.ADC4 4 ADC Conversion result 4 +ADCL.ADC3 3 ADC Conversion result 3 +ADCL.ADC2 2 ADC Conversion result 2 +ADCL.ADC1 1 ADC Conversion result 1 +ADCL.ADC0 0 ADC Conversion result 0 +ADCH 0x0005 The ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 ADC Conversion result 9 +ADCH.ADC8 8 ADC Conversion result 8 +; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion result 1 +; ADCL.ADC0 6 ADC Conversion result 0 +; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion result 9 +; ADCH.ADC8 14 ADC Conversion result 8 +; ADCH.ADC7 13 ADC Conversion result 7 +; ADCH.ADC6 12 ADC Conversion result 6 +; ADCH.ADC5 11 ADC Conversion result 5 +; ADCH.ADC4 10 ADC Conversion result 4 +; ADCH.ADC3 9 ADC Conversion result 3 +; ADCH.ADC2 8 ADC Conversion result 2 +ADCSRA 0x0006 ADC Control and Status Register A +ADCSRA.ADEN 7 ADC Enable +ADCSRA.ADSC 6 ADC Start Conversion +ADCSRA.ADATE 5 ADC Auto Trigger Enable +ADCSRA.ADIF 4 ADC Interrupt Flag +ADCSRA.ADIE 3 ADC Interrupt Enable +ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit +ADMUX.REFS0 6 Reference Selection Bit +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register Low +UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +UCSRB 0x000A USART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B USART Control and Status Register A +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.PE 2 Parity Error +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C The EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D The EEPROM Data Register +SPSR 0x001E SPI Status Register +;SPSR.SPIF 7 SPI Interrupt Flag +;SPSR.WCOL 6 Write COLlision flag +;SPSR.SPI2X 0 Double SPI Speed Bit +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR9 9 EEPROM Addres 9 +EEARH.EEAR8 8 EEPROM Addres 8 +UCSRC 0x0020 USART Control and Status Register C (page 155) +UCSRC.URSEL 7 Register Select +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +; UBRRH 0x0020 USART Baud Rate Register (page 155) +; URSEL 15 Register Select +; UBRR11 11 USART Baud Rate Register bit 11 +; UBRR10 10 USART Baud Rate Register bit 10 +; UBRR9 9 USART Baud Rate Register bit 9 +; UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 9 Watchdog Timer Prescaler 9 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +OCR2 0x0023 Timer/Counter2 Output Compare Register +TCNT2 0x0024 Timer/Counter Register +TCNT2.TCNT2_7 7 +TCNT2.TCNT2_6 6 +TCNT2.TCNT2_5 5 +TCNT2.TCNT2_4 4 +TCNT2.TCNT2_3 3 +TCNT2.TCNT2_2 2 +TCNT2.TCNT2_1 1 +TCNT2.TCNT2_0 0 +TCCR2 0x0025 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Compare Match Output Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Waveform Generation Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +ICR1L 0x0026 Input Capture Register Low Byte +ICR1H 0x0027 Input Capture Register High Byte +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input Capture Edge Select +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.FOC1A 3 Force Output Compare for Channel A +TCCR1A.FOC1B 2 Force Output Compare for Channel B +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +SFIOR 0x0030 Special Function I/O Register +SFIOR.ADTS2 7 ADC Auto Trigger Source 2 +SFIOR.ADTS1 6 ADC Auto Trigger Source 1 +SFIOR.ADTS0 5 ADC Auto Trigger Source 0 +SFIOR.ADHSM 4 ADC High Speed Mode +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OCDR 0x0031 On-Chip Debug Register +; OSCCAL 0x0031 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter Register +TCNT0.TCNT0_7 7 +TCNT0.TCNT0_6 6 +TCNT0.TCNT0_5 5 +TCNT0.TCNT0_4 4 +TCNT0.TCNT0_3 3 +TCNT0.TCNT0_2 2 +TCNT0.TCNT0_1 1 +TCNT0.TCNT0_0 0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.JTD 7 JTAG Interface Disable +MCUCSR.ISC2 6 Interrupt Sense Control 2 +MCUCSR.JTRF 4 JTAG Reset Flag +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 7 Sleep Enable +MCUCR.SM2 6 Sleep Mode Select Bit 2 +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 CInterrupt Sense Control 0 Bit 0 +TWCR 0x0036 TWI Control Register +TWCR.TWINT 7 TWI Interrupt Flag +TWCR.TWEA 6 TWI Enable Acknowledge Bit +TWCR.TWSTA 5 TWI START Condition Bit +TWCR.TWSTO 4 TWI STOP Condition Bit +TWCR.TWWC 3 TWI Write Collision Flag +TWCR.TWEN 2 TWI Enable Bit +TWCR.TWIE 0 TWI Interrupt Enable +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.SPMIE 7 SPM Interrupt Enable +SPMCR.RWWSB 6 Read-While-Write Section Busy +SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +TIFR.TOV1 2 Timer/Counter1, Overflow Flag +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIFR.INTF2 5 External Interrupt Flag 2 +GICR 0x003B General Interrupt Control +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.INT2 5 External Interrupt Request 2 Enable +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +OCR0 0x003C Timer/Counter0 Output Compare Register +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; TWBR 0x0020 Two-wire Serial Interface Bit Rate Register +; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +; TWSR 0x0021 TWI Status Register +; TWSR.TWS7 7 TWI Status 7 +; TWSR.TWS6 6 TWI Status 6 +; TWSR.TWS5 5 TWI Status 5 +; TWSR.TWS4 4 TWI Status 4 +; TWSR.TWS3 3 TWI Status 3 +; TWSR.TWS1 1 TWI Prescaler Bit 1 +; TWSR.TWS0 0 TWI Prescaler Bit 0 +; TWAR 0x0022 TWI (Slave) Address Register +; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +; TWDR 0x0023 TWI Data Register +; TWDR.TWD7 7 TWI Data Register bit 7 +; TWDR.TWD6 6 TWI Data Register bit 6 +; TWDR.TWD5 5 TWI Data Register bit 5 +; TWDR.TWD4 4 TWI Data Register bit 4 +; TWDR.TWD3 3 TWI Data Register bit 3 +; TWDR.TWD2 2 TWI Data Register bit 2 +; TWDR.TWD1 1 TWI Data Register bit 1 +; TWDR.TWD0 0 TWI Data Register bit 0 +; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion result 7 +; ADCL.ADC6 6 ADC Conversion result 6 +; ADCL.ADC5 5 ADC Conversion result 5 +; ADCL.ADC4 4 ADC Conversion result 4 +; ADCL.ADC3 3 ADC Conversion result 3 +; ADCL.ADC2 2 ADC Conversion result 2 +; ADCL.ADC1 1 ADC Conversion result 1 +; ADCL.ADC0 0 ADC Conversion result 0 +; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 ADC Conversion result 9 +; ADCH.ADC8 8 ADC Conversion result 8 +; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion result 1 +; ; ADCL.ADC0 6 ADC Conversion result 0 +; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion result 9 +; ; ADCH.ADC8 14 ADC Conversion result 8 +; ; ADCH.ADC7 13 ADC Conversion result 7 +; ; ADCH.ADC6 12 ADC Conversion result 6 +; ; ADCH.ADC5 11 ADC Conversion result 5 +; ; ADCH.ADC4 10 ADC Conversion result 4 +; ; ADCH.ADC3 9 ADC Conversion result 3 +; ; ADCH.ADC2 8 ADC Conversion result 2 +; ADCSRA 0x0026 ADC Control and Status Register A +; ADCSRA.ADEN 7 ADC Enable +; ADCSRA.ADSC 6 ADC Start Conversion +; ADCSRA.ADATE 5 ADC Auto Trigger Enable +; ADCSRA.ADIF 4 ADC Interrupt Flag +; ADCSRA.ADIE 3 ADC Interrupt Enable +; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit +; ADMUX.REFS0 6 Reference Selection Bit +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRRL 0x0029 USART Baud Rate Register Low +; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +; UCSRB 0x002A USART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.UCSZ2 2 Character Size +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B USART Control and Status Register A +; UCSRA.RXC 7 USART Receive Complete +; UCSRA.TXC 6 USART Transmit Complete +; UCSRA.UDRE 5 USART Data Register Empty +; UCSRA.FE 4 Frame Error +; UCSRA.DOR 3 Data OverRun +; UCSRA.PE 2 Parity Error +; UCSRA.U2X 1 Double the USART Transmission Speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C The EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D The EEPROM Data Register +; SPSR 0x003E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR9 9 EEPROM Addres 9 +; EEARH.EEAR8 8 EEPROM Addres 8 +; UCSRC 0x0040 USART Control and Status Register C (page 155) +; UCSRC.URSEL 7 Register Select +; UCSRC.UMSEL 6 USART Mode Select +; UCSRC.UPM1 5 Parity Mode 1 +; UCSRC.UPM0 4 Parity Mode 0 +; UCSRC.USBS 3 Stop Bit Select +; UCSRC.UCSZ1 2 Character Size 1 +; UCSRC.UCSZ0 1 Character Size 0 +; UCSRC.UCPOL 0 Clock Polarity +; ; UBRRH 0x0040 USART Baud Rate Register (page 155) +; ; URSEL 15 Register Select +; ; UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDTOE 4 Watchdog Turn-off Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 9 Watchdog Timer Prescaler 9 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; OCR2 0x0043 Timer/Counter2 Output Compare Register +; TCNT2 0x0044 Timer/Counter Register +; TCNT2.TCNT2_7 7 +; TCNT2.TCNT2_6 6 +; TCNT2.TCNT2_5 5 +; TCNT2.TCNT2_4 4 +; TCNT2.TCNT2_3 3 +; TCNT2.TCNT2_2 2 +; TCNT2.TCNT2_1 1 +; TCNT2.TCNT2_0 0 +; TCCR2 0x0045 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Compare Match Output Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Waveform Generation Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; ICR1L 0x0046 Input Capture Register Low Byte +; ICR1H 0x0047 Input Capture Register High Byte +; OCR1BL 0x0048 Output Compare Register B Low Byte +; OCR1BH 0x0049 Output Compare Register B High Byte +; OCR1AL 0x004A Output Compare Register A Low Byte +; OCR1AH 0x004B Output Compare Register A High Byte +; TCNT1L 0x004C Counter Register Low Byte +; TCNT1H 0x004D Counter Register High Byte +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input Capture Edge Select +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +; TCCR1A.FOC1A 3 Force Output Compare for Channel A +; TCCR1A.FOC1B 2 Force Output Compare for Channel B +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; SFIOR 0x0050 Special Function I/O Register +; SFIOR.ADTS2 7 ADC Auto Trigger Source 2 +; SFIOR.ADTS1 6 ADC Auto Trigger Source 1 +; SFIOR.ADTS0 5 ADC Auto Trigger Source 0 +; SFIOR.ADHSM 4 ADC High Speed Mode +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OCDR 0x0051 On-Chip Debug Register +; ; OSCCAL 0x0051 Oscillator Calibration Register +; ; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; ; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; ; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; ; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; ; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; ; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; ; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; ; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter Register +; TCNT0.TCNT0_7 7 +; TCNT0.TCNT0_6 6 +; TCNT0.TCNT0_5 5 +; TCNT0.TCNT0_4 4 +; TCNT0.TCNT0_3 3 +; TCNT0.TCNT0_2 2 +; TCNT0.TCNT0_1 1 +; TCNT0.TCNT0_0 0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.JTD 7 JTAG Interface Disable +; MCUCSR.ISC2 6 Interrupt Sense Control 2 +; MCUCSR.JTRF 4 JTAG Reset Flag +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 7 Sleep Enable +; MCUCR.SM2 6 Sleep Mode Select Bit 2 +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 CInterrupt Sense Control 0 Bit 0 +; TWCR 0x0056 TWI Control Register +; TWCR.TWINT 7 TWI Interrupt Flag +; TWCR.TWEA 6 TWI Enable Acknowledge Bit +; TWCR.TWSTA 5 TWI START Condition Bit +; TWCR.TWSTO 4 TWI STOP Condition Bit +; TWCR.TWWC 3 TWI Write Collision Flag +; TWCR.TWEN 2 TWI Enable Bit +; TWCR.TWIE 0 TWI Interrupt Enable +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +; TIFR.TOV1 2 Timer/Counter1, Overflow Flag +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIFR.INTF2 5 External Interrupt Flag 2 +; GICR 0x005B General Interrupt Control +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.INT2 5 External Interrupt Request 2 Enable +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; OCR0 0x005C Timer/Counter0 Output Compare Register +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega64_L +SUBARCH=5 +; doc2490.pdf +; +RAM=4096 +ROM=65536 +EEPROM=2048 + +; MEMORY MAP +; Memory configuration A +area DATA FSR1 0x0000:0x0060 +area DATA FSR2 0x0060:0x009E Ext I/O Reg. +area BSS RESERVED 0x009E:0x0100 +area DATA I_SRAM 0x0100:0x1100 Internal SRAM +area DATA E_SRAM 0x1100:0x10000 External SRAM +; Memory configuration B +; area DATA FSR 0x0000:0x0060 +; area DATA I_SRAM 0x0060:0x1000 Internal SRAM +; area DATA E_SRAM 0x1000:0x10000 External SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry INT3_ 0x0008 External Interrupt Request 3 +entry INT4_ 0x000A External Interrupt Request 4 +entry INT5_ 0x000C External Interrupt Request 5 +entry INT6_ 0x000E External Interrupt Request 6 +entry INT7_ 0x0010 External Interrupt Request 7 +entry TIMER2_COMP 0x0012 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0014 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0016 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0018 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x001A Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x001C Timer/Counter1 Overflow +entry TIMER0_COMP 0x001E Timer/Counter0 Compare Match +entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow +entry SPI_STC 0x0022 SPI Serial Transfer Complete +entry USART0_RX 0x0024 USART0, Rx Complete +entry USART0_UDRE 0x0026 USART0 Data Register Empty +entry USART0_TX 0x0028 USART0, Tx Complete +entry ADC_ 0x002A ADC Conversion Complete +entry EE_READY 0x002C EEPROM Ready +entry ANALOG_COMP 0x002E Analog Comparator +entry TIMER1_COMPC 0x0030 Timer/Countre1 Compare Match C +entry TIMER3_CAPT 0x0032 Timer/Counter3 Capture Event +entry TIMER3_COMPA 0x0034 Timer/Counter3 Compare Match A +entry TIMER3_COMPB 0x0036 Timer/Counter3 Compare Match B +entry TIMER3_COMPC 0x0038 Timer/Counter3 Compare Match C +entry TIMER3_OVF 0x003A Timer/Counter3 Overflow +entry USART1_RX 0x003C USART1, Rx Complete +entry USART1_UDRE 0x003E USART1 Data Register Empty +entry USART1_TX 0x0040 USART1, Tx Complete +entry TWI_ 0x0042 2-wire Serial Interface +entry SPM_READY 0x0044 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +PINF 0x0000 Port F Input Pins Address +PINF.PINF7 7 +PINF.PINF6 6 +PINF.PINF5 5 +PINF.PINF4 4 +PINF.PINF3 3 +PINF.PINF2 2 +PINF.PINF1 1 +PINF.PINF0 0 +PINE 0x0001 Port E Input Pins Address +PINE.PINE7 7 +PINE.PINE6 6 +PINE.PINE5 5 +PINE.PINE4 4 +PINE.PINE3 3 +PINE.PINE2 2 +PINE.PINE1 1 +PINE.PINE0 0 +DDRE 0x0002 Port E Data Direction Register +DDRE.DDE7 7 Port E Data Direction Register bit 7 +DDRE.DDE6 6 Port E Data Direction Register bit 6 +DDRE.DDE5 5 Port E Data Direction Register bit 5 +DDRE.DDE4 4 Port E Data Direction Register bit 4 +DDRE.DDE3 3 Port E Data Direction Register bit 3 +DDRE.DDE2 2 Port E Data Direction Register bit 2 +DDRE.DDE1 1 Port E Data Direction Register bit 1 +DDRE.DDE0 0 Port E Data Direction Register bit 0 +PORTE 0x0003 Port E Data Register +PORTE.PORTE7 7 Port E Data Register bit 7 +PORTE.PORTE6 6 Port E Data Register bit 6 +PORTE.PORTE5 5 Port E Data Register bit 5 +PORTE.PORTE4 4 Port E Data Register bit 4 +PORTE.PORTE3 3 Port E Data Register bit 3 +PORTE.PORTE2 2 Port E Data Register bit 2 +PORTE.PORTE1 1 Port E Data Register bit 1 +PORTE.PORTE0 0 Port E Data Register bit 0 +ADCL 0x0004 ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion Result 7 +ADCL.ADC6 6 ADC Conversion Result 6 +ADCL.ADC5 5 ADC Conversion Result 5 +ADCL.ADC4 4 ADC Conversion Result 4 +ADCL.ADC3 3 ADC Conversion Result 3 +ADCL.ADC2 2 ADC Conversion Result 2 +ADCL.ADC1 1 ADC Conversion Result 1 +ADCL.ADC0 0 ADC Conversion Result 0 +ADCH 0x0005 ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 ADC Conversion Result 9 +ADCH.ADC8 8 ADC Conversion Result 8 +; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion Result 1 +; ADCL.ADC0 6 ADC Conversion Result 0 +; ADCH 0x0005 ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion Result 9 +; ADCH.ADC8 14 ADC Conversion Result 8 +; ADCH.ADC7 13 ADC Conversion Result 7 +; ADCH.ADC6 12 ADC Conversion Result 6 +; ADCH.ADC5 11 ADC Conversion Result 5 +; ADCH.ADC4 10 ADC Conversion Result 4 +; ADCH.ADC3 9 ADC Conversion Result 3 +; ADCH.ADC2 8 ADC Conversion Result 2 +ADCSRA 0x0006 ADC Control and Status Register A +ADCSRA.ADEN 7 ADC Enable +ADCSRA.ADSC 6 ADC Start Conversion +ADCSRA.ADATE 5 ADC Auto Trigger Enable +ADCSRA.ADIF 4 ADC Interrupt Flag +ADCSRA.ADIE 3 ADC Interrupt Enable +ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRR0L 0x0009 USART Baud Rate Register +UBRR0L.UBRR7 7 USART Baud Rate Register bit 7 +UBRR0L.UBRR6 6 USART Baud Rate Register bit 6 +UBRR0L.UBRR5 5 USART Baud Rate Register bit 5 +UBRR0L.UBRR4 4 USART Baud Rate Register bit 4 +UBRR0L.UBRR3 3 USART Baud Rate Register bit 3 +UBRR0L.UBRR2 2 USART Baud Rate Register bit 2 +UBRR0L.UBRR1 1 USART Baud Rate Register bit 1 +UBRR0L.UBRR0 0 USART Baud Rate Register bit 0 +UCSR0B 0x000A USART Control and Status Register B +UCSR0B.RXCIE 7 RX Complete Interrupt Enable +UCSR0B.TXCIE 6 TX Complete Interrupt Enable +UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSR0B.RXEN 4 Receiver Enable +UCSR0B.TXEN 3 Transmitter Enable +UCSR0B.UCSZ2 2 Character Size +UCSR0B.RXB8 1 Receive Data Bit 8 +UCSR0B.TXB8 0 Transmit Data Bit 8 +UCSR0A 0x000B USART Control and Status Register A +UCSR0A.RXC 7 USART Receive Complete +UCSR0A.TXC 6 USART Transmit Complete +UCSR0A.UDRE 5 USART Data Register Empty +UCSR0A.FE 4 Frame Error +UCSR0A.DOR 3 Data OverRun +UCSR0A.UPE 2 USART Parity Error +UCSR0A.U2X 1 Double the USART Transmission Speed +UCSR0A.MPCM 0 Multi-processor Communication Mode +UDR0 0x000C USART0 I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision Flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR10 10 EEPROM Addres 10 +EEARH.EEAR9 9 EEPROM Addres 9 +EEARH.EEAR8 8 EEPROM Addres 8 +SFIOR 0x0020 Special Function IO Register +SFIOR.TSM 7 Timer/Counter Synchronization Mode +SFIOR.ADHSM 4 ADC High Speed Mode +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up disable +SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 +SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +OCDR 0x0022 On-chip Debug Register +OCDR.IDRD_OCDR7 7 +OCDR.OCDR6 6 +OCDR.OCDR5 5 +OCDR.OCDR4 4 +OCDR.OCDR3 3 +OCDR.OCDR2 2 +OCDR.OCDR1 1 +OCDR.OCDR0 0 +OCR2 0x0023 Output Compare Register +OCR2.OCR2_7 7 +OCR2.OCR2_6 6 +OCR2.OCR2_5 5 +OCR2.OCR2_4 4 +OCR2.OCR2_3 3 +OCR2.OCR2_2 2 +OCR2.OCR2_1 1 +OCR2.OCR2_0 0 +TCNT2 0x0024 Timer/Counter Register +TCNT2.TCNT2_7 7 +TCNT2.TCNT2_6 6 +TCNT2.TCNT2_5 5 +TCNT2.TCNT2_4 4 +TCNT2.TCNT2_3 3 +TCNT2.TCNT2_2 2 +TCNT2.TCNT2_1 1 +TCNT2.TCNT2_0 0 +TCCR2 0x0025 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Compare Match Output Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Waveform Generation Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +ICR1L 0x0026 Input Capture Register 1 Low +ICR1L.ICR1_7 7 +ICR1L.ICR1_6 6 +ICR1L.ICR1_5 5 +ICR1L.ICR1_4 4 +ICR1L.ICR1_3 3 +ICR1L.ICR1_2 2 +ICR1L.ICR1_1 1 +ICR1L.ICR1_0 0 +ICR1H 0x0027 Input Capture Register 1 High +ICR1H.ICR1_15 15 +ICR1H.ICR1_14 14 +ICR1H.ICR1_13 13 +ICR1H.ICR1_12 12 +ICR1H.ICR1_11 11 +ICR1H.ICR1_10 10 +ICR1H.ICR1_9 9 +ICR1H.ICR1_8 8 +OCR1BL 0x0028 Output Compare Register 1 B Low +OCR1BL.OCR1B_7 7 +OCR1BL.OCR1B_6 6 +OCR1BL.OCR1B_5 5 +OCR1BL.OCR1B_4 4 +OCR1BL.OCR1B_3 3 +OCR1BL.OCR1B_2 2 +OCR1BL.OCR1B_1 1 +OCR1BL.OCR1B_0 0 +OCR1BH 0x0029 Output Compare Register 1 B High +OCR1BH.OCR1B_15 15 +OCR1BH.OCR1B_14 14 +OCR1BH.OCR1B_13 13 +OCR1BH.OCR1B_12 12 +OCR1BH.OCR1B_11 11 +OCR1BH.OCR1B_10 10 +OCR1BH.OCR1B_9 9 +OCR1BH.OCR1B_8 8 +OCR1AL 0x002A Output Compare Register 1 A Low +OCR1AL.OCR1A_7 7 +OCR1AL.OCR1A_6 6 +OCR1AL.OCR1A_5 5 +OCR1AL.OCR1A_4 4 +OCR1AL.OCR1A_3 3 +OCR1AL.OCR1A_2 2 +OCR1AL.OCR1A_1 1 +OCR1AL.OCR1A_0 0 +OCR1AH 0x002B Output Compare Register 1 A High +OCR1AH.OCR1A_15 15 +OCR1AH.OCR1A_14 14 +OCR1AH.OCR1A_13 13 +OCR1AH.OCR1A_12 12 +OCR1AH.OCR1A_11 11 +OCR1AH.OCR1A_10 10 +OCR1AH.OCR1A_9 9 +OCR1AH.OCR1A_8 8 +TCNT1L 0x002C Timer/Counter 1 Low +TCNT1L.TCNT1_7 7 +TCNT1L.TCNT1_6 6 +TCNT1L.TCNT1_5 5 +TCNT1L.TCNT1_4 4 +TCNT1L.TCNT1_3 3 +TCNT1L.TCNT1_2 2 +TCNT1L.TCNT1_1 1 +TCNT1L.TCNT1_0 0 +TCNT1H 0x002D Timer/Counter 1 High +TCNT1H.TCNT1_15 15 +TCNT1H.TCNT1_14 14 +TCNT1H.TCNT1_13 13 +TCNT1H.TCNT1_12 12 +TCNT1H.TCNT1_11 11 +TCNT1H.TCNT1_10 10 +TCNT1H.TCNT1_9 9 +TCNT1H.TCNT1_8 8 +TCCR1B 0x002E Timer/Counter 1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input Capture Edge Select +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter 1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 +TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +ASSR 0x0030 Asynchronous Status Register +ASSR.AS0 3 Asynchronous Timer/Counter0 +ASSR.TCN0UB 2 Timer/Counter0 Update Busy +ASSR.OCR0UB 1 Output Compare Register0 Update Busy +ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy +OCR0 0x0031 Output Compare Register +OCR0.OCR0_7 7 +OCR0.OCR0_6 6 +OCR0.OCR0_5 5 +OCR0.OCR0_4 4 +OCR0.OCR0_3 3 +OCR0.OCR0_2 2 +OCR0.OCR0_1 1 +OCR0.OCR0_0 0 +TCNT0 0x0032 Timer/Counter Register +TCNT0.TCNT0_7 7 +TCNT0.TCNT0_6 6 +TCNT0.TCNT0_5 5 +TCNT0.TCNT0_4 4 +TCNT0.TCNT0_3 3 +TCNT0.TCNT0_2 2 +TCNT0.TCNT0_1 1 +TCNT0.TCNT0_0 0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.JTD 7 JTAG interface disable +MCUCSR.JTRF 4 JTAG Reset Flag +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM/XMEM Enable +MCUCR.SRW10 6 Wait State Select Bit +MCUCR.SE 5 Sleep Enable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.SM0 3 Sleep Mode Select Bit 0 +MCUCR.SM2 2 Sleep Mode Select Bit 2 +MCUCR.IVSEL 1 Interrupt Vector Select +MCUCR.IVCE 0 Interrupt Vector Change Enable +TIFR 0x0036 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +TIFR.TOV1 2 Timer/Counter1, Overflow Flag +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0037 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +EIFR 0x0038 External Interrupt Flag Register +EIFR.INTF7 7 External Interrupt Flag 7 +EIFR.INTF6 6 External Interrupt Flag 6 +EIFR.INTF5 5 External Interrupt Flag 5 +EIFR.INTF4 4 External Interrupt Flag 4 +EIFR.INTF3 3 External Interrupt Flag 3 +EIFR.INTF2 2 External Interrupt Flag 2 +EIFR.INTF1 1 External Interrupt Flag 1 +EIFR.INTF0 0 External Interrupt Flag 0 +EIMSK 0x0039 External Interrupt Mask Register +EIMSK.INT7 7 External Interrupt Request 7 Enable +EIMSK.INT6 6 External Interrupt Request 6 Enable +EIMSK.INT5 5 External Interrupt Request 5 Enable +EIMSK.INT4 4 External Interrupt Request 4 Enable +EIMSK.INT3 3 External Interrupt Request 3 Enable +EIMSK.INT2 2 External Interrupt Request 2 Enable +EIMSK.INT1 1 External Interrupt Request 1 Enable +EIMSK.INT0 0 External Interrupt Request 0 Enable +EICRB 0x003A External Interrupt Control Register B +EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 +EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 +EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 +EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 +EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 +EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 +EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 +EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 +RESERVED003B 0x003B RESERVED +XDIV 0x003C XTAL Divide Control Register +XDIV.XDIVEN 7 XTAL Divide Enable +XDIV.XDIV6 6 XTAL Divide Select Bit 6 +XDIV.XDIV5 5 XTAL Divide Select Bit 5 +XDIV.XDIV4 4 XTAL Divide Select Bit 4 +XDIV.XDIV3 3 XTAL Divide Select Bit 3 +XDIV.XDIV2 2 XTAL Divide Select Bit 2 +XDIV.XDIV1 1 XTAL Divide Select Bit 1 +XDIV.XDIV0 0 XTAL Divide Select Bit 0 +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; PINF 0x0020 Port F Input Pins Address +; PINF.PINF7 7 +; PINF.PINF6 6 +; PINF.PINF5 5 +; PINF.PINF4 4 +; PINF.PINF3 3 +; PINF.PINF2 2 +; PINF.PINF1 1 +; PINF.PINF0 0 +; PINE 0x0021 Port E Input Pins Address +; PINE.PINE7 7 +; PINE.PINE6 6 +; PINE.PINE5 5 +; PINE.PINE4 4 +; PINE.PINE3 3 +; PINE.PINE2 2 +; PINE.PINE1 1 +; PINE.PINE0 0 +; DDRE 0x0022 Port E Data Direction Register +; DDRE.DDE7 7 Port E Data Direction Register bit 7 +; DDRE.DDE6 6 Port E Data Direction Register bit 6 +; DDRE.DDE5 5 Port E Data Direction Register bit 5 +; DDRE.DDE4 4 Port E Data Direction Register bit 4 +; DDRE.DDE3 3 Port E Data Direction Register bit 3 +; DDRE.DDE2 2 Port E Data Direction Register bit 2 +; DDRE.DDE1 1 Port E Data Direction Register bit 1 +; DDRE.DDE0 0 Port E Data Direction Register bit 0 +; PORTE 0x0023 Port E Data Register +; PORTE.PORTE7 7 Port E Data Register bit 7 +; PORTE.PORTE6 6 Port E Data Register bit 6 +; PORTE.PORTE5 5 Port E Data Register bit 5 +; PORTE.PORTE4 4 Port E Data Register bit 4 +; PORTE.PORTE3 3 Port E Data Register bit 3 +; PORTE.PORTE2 2 Port E Data Register bit 2 +; PORTE.PORTE1 1 Port E Data Register bit 1 +; PORTE.PORTE0 0 Port E Data Register bit 0 +; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion Result 7 +; ADCL.ADC6 6 ADC Conversion Result 6 +; ADCL.ADC5 5 ADC Conversion Result 5 +; ADCL.ADC4 4 ADC Conversion Result 4 +; ADCL.ADC3 3 ADC Conversion Result 3 +; ADCL.ADC2 2 ADC Conversion Result 2 +; ADCL.ADC1 1 ADC Conversion Result 1 +; ADCL.ADC0 0 ADC Conversion Result 0 +; ADCH 0x0025 ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 ADC Conversion Result 9 +; ADCH.ADC8 8 ADC Conversion Result 8 +; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion Result 1 +; ; ADCL.ADC0 6 ADC Conversion Result 0 +; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion Result 9 +; ; ADCH.ADC8 14 ADC Conversion Result 8 +; ; ADCH.ADC7 13 ADC Conversion Result 7 +; ; ADCH.ADC6 12 ADC Conversion Result 6 +; ; ADCH.ADC5 11 ADC Conversion Result 5 +; ; ADCH.ADC4 10 ADC Conversion Result 4 +; ; ADCH.ADC3 9 ADC Conversion Result 3 +; ; ADCH.ADC2 8 ADC Conversion Result 2 +; ADCSRA 0x0026 ADC Control and Status Register A +; ADCSRA.ADEN 7 ADC Enable +; ADCSRA.ADSC 6 ADC Start Conversion +; ADCSRA.ADATE 5 ADC Auto Trigger Enable +; ADCSRA.ADIF 4 ADC Interrupt Flag +; ADCSRA.ADIE 3 ADC Interrupt Enable +; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRR0L 0x0029 USART Baud Rate Register +; UBRR0L.UBRR7 7 USART Baud Rate Register bit 7 +; UBRR0L.UBRR6 6 USART Baud Rate Register bit 6 +; UBRR0L.UBRR5 5 USART Baud Rate Register bit 5 +; UBRR0L.UBRR4 4 USART Baud Rate Register bit 4 +; UBRR0L.UBRR3 3 USART Baud Rate Register bit 3 +; UBRR0L.UBRR2 2 USART Baud Rate Register bit 2 +; UBRR0L.UBRR1 1 USART Baud Rate Register bit 1 +; UBRR0L.UBRR0 0 USART Baud Rate Register bit 0 +; UCSR0B 0x002A USART Control and Status Register B +; UCSR0B.RXCIE 7 RX Complete Interrupt Enable +; UCSR0B.TXCIE 6 TX Complete Interrupt Enable +; UCSR0B.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSR0B.RXEN 4 Receiver Enable +; UCSR0B.TXEN 3 Transmitter Enable +; UCSR0B.UCSZ2 2 Character Size +; UCSR0B.RXB8 1 Receive Data Bit 8 +; UCSR0B.TXB8 0 Transmit Data Bit 8 +; UCSR0A 0x002B USART Control and Status Register A +; UCSR0A.RXC 7 USART Receive Complete +; UCSR0A.TXC 6 USART Transmit Complete +; UCSR0A.UDRE 5 USART Data Register Empty +; UCSR0A.FE 4 Frame Error +; UCSR0A.DOR 3 Data OverRun +; UCSR0A.UPE 2 USART Parity Error +; UCSR0A.U2X 1 Double the USART Transmission Speed +; UCSR0A.MPCM 0 Multi-processor Communication Mode +; UDR0 0x002C USART0 I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision Flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEDR.EEDR7 7 EEPROM Data 7 +; EEDR.EEDR6 6 EEPROM Data 6 +; EEDR.EEDR5 5 EEPROM Data 5 +; EEDR.EEDR4 4 EEPROM Data 4 +; EEDR.EEDR3 3 EEPROM Data 3 +; EEDR.EEDR2 2 EEPROM Data 2 +; EEDR.EEDR1 1 EEPROM Data 1 +; EEDR.EEDR0 0 EEPROM Data 0 +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR10 10 EEPROM Addres 10 +; EEARH.EEAR9 9 EEPROM Addres 9 +; EEARH.EEAR8 8 EEPROM Addres 8 +; SFIOR 0x0040 Special Function IO Register +; SFIOR.TSM 7 Timer/Counter Synchronization Mode +; SFIOR.ADHSM 4 ADC High Speed Mode +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up disable +; SFIOR.PSR0 1 Prescaler Reset Timer/Counter0 +; SFIOR.PSR321 0 Prescaler Reset Timer/Counter3, Timer/Counter2, and Timer/Counter1 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; OCDR 0x0042 On-chip Debug Register +; OCDR.IDRD_OCDR7 7 +; OCDR.OCDR6 6 +; OCDR.OCDR5 5 +; OCDR.OCDR4 4 +; OCDR.OCDR3 3 +; OCDR.OCDR2 2 +; OCDR.OCDR1 1 +; OCDR.OCDR0 0 +; OCR2 0x0043 Output Compare Register +; OCR2.OCR2_7 7 +; OCR2.OCR2_6 6 +; OCR2.OCR2_5 5 +; OCR2.OCR2_4 4 +; OCR2.OCR2_3 3 +; OCR2.OCR2_2 2 +; OCR2.OCR2_1 1 +; OCR2.OCR2_0 0 +; TCNT2 0x0044 Timer/Counter Register +; TCNT2.TCNT2_7 7 +; TCNT2.TCNT2_6 6 +; TCNT2.TCNT2_5 5 +; TCNT2.TCNT2_4 4 +; TCNT2.TCNT2_3 3 +; TCNT2.TCNT2_2 2 +; TCNT2.TCNT2_1 1 +; TCNT2.TCNT2_0 0 +; TCCR2 0x0045 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Compare Match Output Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Waveform Generation Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; ICR1L 0x0046 Input Capture Register 1 Low +; ICR1L.ICR1_7 7 +; ICR1L.ICR1_6 6 +; ICR1L.ICR1_5 5 +; ICR1L.ICR1_4 4 +; ICR1L.ICR1_3 3 +; ICR1L.ICR1_2 2 +; ICR1L.ICR1_1 1 +; ICR1L.ICR1_0 0 +; ICR1H 0x0047 Input Capture Register 1 High +; ICR1H.ICR1_15 15 +; ICR1H.ICR1_14 14 +; ICR1H.ICR1_13 13 +; ICR1H.ICR1_12 12 +; ICR1H.ICR1_11 11 +; ICR1H.ICR1_10 10 +; ICR1H.ICR1_9 9 +; ICR1H.ICR1_8 8 +; OCR1BL 0x0048 Output Compare Register 1 B Low +; OCR1BL.OCR1B_7 7 +; OCR1BL.OCR1B_6 6 +; OCR1BL.OCR1B_5 5 +; OCR1BL.OCR1B_4 4 +; OCR1BL.OCR1B_3 3 +; OCR1BL.OCR1B_2 2 +; OCR1BL.OCR1B_1 1 +; OCR1BL.OCR1B_0 0 +; OCR1BH 0x0049 Output Compare Register 1 B High +; OCR1BH.OCR1B_15 15 +; OCR1BH.OCR1B_14 14 +; OCR1BH.OCR1B_13 13 +; OCR1BH.OCR1B_12 12 +; OCR1BH.OCR1B_11 11 +; OCR1BH.OCR1B_10 10 +; OCR1BH.OCR1B_9 9 +; OCR1BH.OCR1B_8 8 +; OCR1AL 0x004A Output Compare Register 1 A Low +; OCR1AL.OCR1A_7 7 +; OCR1AL.OCR1A_6 6 +; OCR1AL.OCR1A_5 5 +; OCR1AL.OCR1A_4 4 +; OCR1AL.OCR1A_3 3 +; OCR1AL.OCR1A_2 2 +; OCR1AL.OCR1A_1 1 +; OCR1AL.OCR1A_0 0 +; OCR1AH 0x004B Output Compare Register 1 A High +; OCR1AH.OCR1A_15 15 +; OCR1AH.OCR1A_14 14 +; OCR1AH.OCR1A_13 13 +; OCR1AH.OCR1A_12 12 +; OCR1AH.OCR1A_11 11 +; OCR1AH.OCR1A_10 10 +; OCR1AH.OCR1A_9 9 +; OCR1AH.OCR1A_8 8 +; TCNT1L 0x004C Timer/Counter 1 Low +; TCNT1L.TCNT1_7 7 +; TCNT1L.TCNT1_6 6 +; TCNT1L.TCNT1_5 5 +; TCNT1L.TCNT1_4 4 +; TCNT1L.TCNT1_3 3 +; TCNT1L.TCNT1_2 2 +; TCNT1L.TCNT1_1 1 +; TCNT1L.TCNT1_0 0 +; TCNT1H 0x004D Timer/Counter 1 High +; TCNT1H.TCNT1_15 15 +; TCNT1H.TCNT1_14 14 +; TCNT1H.TCNT1_13 13 +; TCNT1H.TCNT1_12 12 +; TCNT1H.TCNT1_11 11 +; TCNT1H.TCNT1_10 10 +; TCNT1H.TCNT1_9 9 +; TCNT1H.TCNT1_8 8 +; TCCR1B 0x004E Timer/Counter 1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input Capture Edge Select +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter 1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +; TCCR1A.COM1C1 3 Compare Output Mode for Channel C 1 +; TCCR1A.COM1C0 2 Compare Output Mode for Channel C 0 +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; ASSR 0x0050 Asynchronous Status Register +; ASSR.AS0 3 Asynchronous Timer/Counter0 +; ASSR.TCN0UB 2 Timer/Counter0 Update Busy +; ASSR.OCR0UB 1 Output Compare Register0 Update Busy +; ASSR.TCR0UB 0 Timer/Counter Control Register0 Update Busy +; OCR0 0x0051 Output Compare Register +; OCR0.OCR0_7 7 +; OCR0.OCR0_6 6 +; OCR0.OCR0_5 5 +; OCR0.OCR0_4 4 +; OCR0.OCR0_3 3 +; OCR0.OCR0_2 2 +; OCR0.OCR0_1 1 +; OCR0.OCR0_0 0 +; TCNT0 0x0052 Timer/Counter Register +; TCNT0.TCNT0_7 7 +; TCNT0.TCNT0_6 6 +; TCNT0.TCNT0_5 5 +; TCNT0.TCNT0_4 4 +; TCNT0.TCNT0_3 3 +; TCNT0.TCNT0_2 2 +; TCNT0.TCNT0_1 1 +; TCNT0.TCNT0_0 0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.JTD 7 JTAG interface disable +; MCUCSR.JTRF 4 JTAG Reset Flag +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM/XMEM Enable +; MCUCR.SRW10 6 Wait State Select Bit +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.SM0 3 Sleep Mode Select Bit 0 +; MCUCR.SM2 2 Sleep Mode Select Bit 2 +; MCUCR.IVSEL 1 Interrupt Vector Select +; MCUCR.IVCE 0 Interrupt Vector Change Enable +; TIFR 0x0056 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +; TIFR.TOV1 2 Timer/Counter1, Overflow Flag +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0057 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; EIFR 0x0058 External Interrupt Flag Register +; EIFR.INTF7 7 External Interrupt Flag 7 +; EIFR.INTF6 6 External Interrupt Flag 6 +; EIFR.INTF5 5 External Interrupt Flag 5 +; EIFR.INTF4 4 External Interrupt Flag 4 +; EIFR.INTF3 3 External Interrupt Flag 3 +; EIFR.INTF2 2 External Interrupt Flag 2 +; EIFR.INTF1 1 External Interrupt Flag 1 +; EIFR.INTF0 0 External Interrupt Flag 0 +; EIMSK 0x0059 External Interrupt Mask Register +; EIMSK.INT7 7 External Interrupt Request 7 Enable +; EIMSK.INT6 6 External Interrupt Request 6 Enable +; EIMSK.INT5 5 External Interrupt Request 5 Enable +; EIMSK.INT4 4 External Interrupt Request 4 Enable +; EIMSK.INT3 3 External Interrupt Request 3 Enable +; EIMSK.INT2 2 External Interrupt Request 2 Enable +; EIMSK.INT1 1 External Interrupt Request 1 Enable +; EIMSK.INT0 0 External Interrupt Request 0 Enable +; EICRB 0x005A External Interrupt Control Register B +; EICRB.ISC71 7 External Interrupt 7 Sense Control Bit 1 +; EICRB.ISC70 6 External Interrupt 7 Sense Control Bit 0 +; EICRB.ISC61 5 External Interrupt 6 Sense Control Bit 1 +; EICRB.ISC60 4 External Interrupt 6 Sense Control Bit 0 +; EICRB.ISC51 3 External Interrupt 5 Sense Control Bit 1 +; EICRB.ISC50 2 External Interrupt 5 Sense Control Bit 0 +; EICRB.ISC41 1 External Interrupt 4 Sense Control Bit 1 +; EICRB.ISC40 0 External Interrupt 4 Sense Control Bit 0 +; RESERVED005B 0x005B RESERVED +; XDIV 0x005C XTAL Divide Control Register +; XDIV.XDIVEN 7 XTAL Divide Enable +; XDIV.XDIV6 6 XTAL Divide Select Bit 6 +; XDIV.XDIV5 5 XTAL Divide Select Bit 5 +; XDIV.XDIV4 4 XTAL Divide Select Bit 4 +; XDIV.XDIV3 3 XTAL Divide Select Bit 3 +; XDIV.XDIV2 2 XTAL Divide Select Bit 2 +; XDIV.XDIV1 1 XTAL Divide Select Bit 1 +; XDIV.XDIV0 0 XTAL Divide Select Bit 0 +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag +; RESERVED0060 0x0060 RESERVED +; DDRF 0x0061 Port F Data Direction Register +; DDRF.DDF7 7 Port F Data Direction Register bit 7 +; DDRF.DDF6 6 Port F Data Direction Register bit 6 +; DDRF.DDF5 5 Port F Data Direction Register bit 5 +; DDRF.DDF4 4 Port F Data Direction Register bit 4 +; DDRF.DDF3 3 Port F Data Direction Register bit 3 +; DDRF.DDF2 2 Port F Data Direction Register bit 2 +; DDRF.DDF1 1 Port F Data Direction Register bit 1 +; DDRF.DDF0 0 Port F Data Direction Register bit 0 +; PORTF 0x0062 Port F Data Register +; PORTF.PORTF 7 Port F Data Register bit 7 +; PORTF.PORTF 6 Port F Data Register bit 6 +; PORTF.PORTF 5 Port F Data Register bit 5 +; PORTF.PORTF 4 Port F Data Register bit 4 +; PORTF.PORTF 3 Port F Data Register bit 3 +; PORTF.PORTF 2 Port F Data Register bit 2 +; PORTF.PORTF 1 Port F Data Register bit 1 +; PORTF.PORTF 0 Port F Data Register bit 0 +; PING 0x0063 Port G Input Pins Address +; PING.PING4 4 +; PING.PING3 3 +; PING.PING2 2 +; PING.PING1 1 +; PING.PING0 0 +; DDRG 0x0064 Port G Data Direction Register +; DDRG.DDG4 4 Port G Data Direction Register bit 4 +; DDRG.DDG3 3 Port G Data Direction Register bit 3 +; DDRG.DDG2 2 Port G Data Direction Register bit 2 +; DDRG.DDG1 1 Port G Data Direction Register bit 1 +; DDRG.DDG0 0 Port G Data Direction Register bit 0 +; PORTG 0x0065 Port G Data Register +; PORTG.PORTG4 4 Port G Data Register bit 4 +; PORTG.PORTG3 3 Port G Data Register bit 3 +; PORTG.PORTG2 2 Port G Data Register bit 2 +; PORTG.PORTG1 1 Port G Data Register bit 1 +; PORTG.PORTG0 0 Port G Data Register bit 0 +; RESERVED0066 0x0066 RESERVED +; RESERVED0067 0x0067 RESERVED +; SPMCR 0x0068 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; RESERVED0069 0x0069 RESERVED +; EICRA 0x006A External Interrupt Control Register A +; EICRA.ISC31 7 External Interrupt 3 Sense Control Bit 1 +; EICRA.ISC30 6 External Interrupt 3 Sense Control Bit 0 +; EICRA.ISC21 5 External Interrupt 2 Sense Control Bit 1 +; EICRA.ISC20 4 External Interrupt 2 Sense Control Bit 0 +; EICRA.ISC11 3 External Interrupt 1 Sense Control Bit 1 +; EICRA.ISC10 2 External Interrupt 1 Sense Control Bit 0 +; EICRA.ISC01 1 External Interrupt 0 Sense Control Bit 1 +; EICRA.ISC00 0 External Interrupt 0 Sense Control Bit 0 +; RESERVED006B 0x006B RESERVED +; XMCRB 0x006C External Memory Control Register B +; XMCRB.XMBK 7 External Memory Bus-keeper Enable +; XMCRB.XMM2 2 External Memory High Mask 2 +; XMCRB.XMM1 1 External Memory High Mask 1 +; XMCRB.XMM0 0 External Memory High Mask 0 +; XMCRA 0x006D External Memory Control Register A +; XMCRA.SRL2 6 Wait State Sector Limit 2 +; XMCRA.SRL1 5 Wait State Sector Limit 1 +; XMCRA.SRL0 4 Wait State Sector Limit 0 +; XMCRA.SRW01 3 Wait State Select Bits for Lower Sector +; XMCRA.SRW00 2 Wait State Select Bits for Lower Sector +; XMCRA.SRW11 1 Wait State Select Bits for Upper Sector +; RESERVED006E 0x006E RESERVED +; OSCCAL 0x006F Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TWBR 0x0070 TWI Bit Rate Register +; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +; TWSR 0x0071 TWI Status Register +; TWSR.TWS7 7 TWI Status bit 7 +; TWSR.TWS6 6 TWI Status bit 6 +; TWSR.TWS5 5 TWI Status bit 5 +; TWSR.TWS4 4 TWI Status bit 4 +; TWSR.TWS3 3 TWI Status bit 3 +; TWSR.TWS1 1 TWI Status bit 1 +; TWSR.TWS0 0 TWI Status bit 0 +; TWAR 0x0072 TWI (Slave) Address Register +; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +; TWDR 0x0073 TWI Data Register +; TWDR.TWD7 7 TWI Data Register bit 7 +; TWDR.TWD6 6 TWI Data Register bit 6 +; TWDR.TWD5 5 TWI Data Register bit 5 +; TWDR.TWD4 4 TWI Data Register bit 4 +; TWDR.TWD3 3 TWI Data Register bit 3 +; TWDR.TWD2 2 TWI Data Register bit 2 +; TWDR.TWD1 1 TWI Data Register bit 1 +; TWDR.TWD0 0 TWI Data Register bit 0 +; TWCR 0x0074 TWI Control Register +; TWCR.TWINT 7 TWI Interrupt Flag +; TWCR.TWEA 6 TWI Enable Acknowledge Bit +; TWCR.TWSTA 5 TWI START Condition Bit +; TWCR.TWSTO 4 TWI STOP Condition Bit +; TWCR.TWWC 3 TWI Write Collision Flag +; TWCR.TWEN 2 TWI Enable Bit +; TWCR.TWIE 0 TWI Interrupt Enable +; RESERVED0075 0x0075 RESERVED +; RESERVED0076 0x0076 RESERVED +; RESERVED0077 0x0077 RESERVED +; OCR1CL 0x0078 Output Compare Register 1 C Low +; OCR1CL.OCR1C7 7 +; OCR1CL.OCR1C6 6 +; OCR1CL.OCR1C5 5 +; OCR1CL.OCR1C4 4 +; OCR1CL.OCR1C3 3 +; OCR1CL.OCR1C2 2 +; OCR1CL.OCR1C1 1 +; OCR1CL.OCR1C0 0 +; OCR1CH 0x0079 Output Compare Register 1 C High +; OCR1CH.OCR1C15 15 +; OCR1CH.OCR1C14 14 +; OCR1CH.OCR1C13 13 +; OCR1CH.OCR1C12 12 +; OCR1CH.OCR1C11 11 +; OCR1CH.OCR1C10 10 +; OCR1CH.OCR1C9 9 +; OCR1CH.OCR1C8 8 +; TCCR1C 0x007A Timer/Counter 1 Control Register C +; TCCR1C.FOC1A 7 Force Output Compare for Channel A +; TCCR1C.FOC1B 6 Force Output Compare for Channel B +; TCCR1C.FOC1C 5 Force Output Compare for Channel C +; RESERVED007B 0x007B RESERVED +; ETIFR 0x007C Extended Timer/Counter Interrupt Flag Register +; ETIFR.ICF3 5 Timer/Counter3, Input Capture Flag +; ETIFR.OCF3A 4 Timer/Counter3, Output Compare A Match Flag +; ETIFR.OCF3B 3 Timer/Counter3, Output Compare B Match Flag +; ETIFR.TOV3 2 Timer/Counter3, Overflow Flag +; ETIFR.OCF3C 1 Timer/Counter3, Output Compare C Match Flag +; ETIFR.OCF1C 0 Timer/Counter1, Output Compare C Match Flag +; ETIMSK 0x007D Extended Timer/Counter Interrupt Mask Register +; ETIMSK.TICIE3 5 Timer/Counter3, Input Capture Interrupt Enable +; ETIMSK.OCIE3A 4 Timer/Counter3, Output Compare A Match Interrupt Enable +; ETIMSK.OCIE3B 3 Timer/Counter3, Output Compare B Match Interrupt Enable +; ETIMSK.TOIE3 2 Timer/Counter3, Overflow Interrupt Enable +; ETIMSK.OCIE3C 1 Timer/Counter3, Output Compare C Match Interrupt Enable +; ETIMSK.OCIE1C 0 Timer/Counter1, Output Compare C Match Interrupt Enable +; RESERVED007E 0x007E RESERVED +; RESERVED007F 0x007F RESERVED +; ICR3L 0x0080 Input Capture Register 3 Low +; ICR3L.ICR3_7 7 +; ICR3L.ICR3_6 6 +; ICR3L.ICR3_5 5 +; ICR3L.ICR3_4 4 +; ICR3L.ICR3_3 3 +; ICR3L.ICR3_2 2 +; ICR3L.ICR3_1 1 +; ICR3L.ICR3_0 0 +; ICR3H 0x0081 Input Capture Register 3 High +; ICR3H.ICR3_15 15 +; ICR3H.ICR3_14 14 +; ICR3H.ICR3_13 13 +; ICR3H.ICR3_12 12 +; ICR3H.ICR3_11 11 +; ICR3H.ICR3_10 10 +; ICR3H.ICR3_9 9 +; ICR3H.ICR3_8 8 +; OCR3CL 0x0082 Output Compare Register 3 C Low +; OCR3CL.OCR3C_7 7 +; OCR3CL.OCR3C_6 6 +; OCR3CL.OCR3C_5 5 +; OCR3CL.OCR3C_4 4 +; OCR3CL.OCR3C_3 3 +; OCR3CL.OCR3C_2 2 +; OCR3CL.OCR3C_1 1 +; OCR3CL.OCR3C_0 0 +; OCR3CH 0x0083 Output Compare Register 3 C High +; OCR3CH.OCR3C_15 15 +; OCR3CH.OCR3C_14 14 +; OCR3CH.OCR3C_13 13 +; OCR3CH.OCR3C_12 12 +; OCR3CH.OCR3C_11 11 +; OCR3CH.OCR3C_10 10 +; OCR3CH.OCR3C_9 9 +; OCR3CH.OCR3C_8 8 +; OCR3BL 0x0084 Output Compare Register 3 B Low +; OCR3BL.OCR3B_7 7 +; OCR3BL.OCR3B_6 6 +; OCR3BL.OCR3B_5 5 +; OCR3BL.OCR3B_4 4 +; OCR3BL.OCR3B_3 3 +; OCR3BL.OCR3B_2 2 +; OCR3BL.OCR3B_1 1 +; OCR3BL.OCR3B_0 0 +; OCR3BH 0x0085 Output Compare Register 3 B High +; OCR3BH.OCR3B_15 15 +; OCR3BH.OCR3B_14 14 +; OCR3BH.OCR3B_13 13 +; OCR3BH.OCR3B_12 12 +; OCR3BH.OCR3B_11 11 +; OCR3BH.OCR3B_10 10 +; OCR3BH.OCR3B_9 9 +; OCR3BH.OCR3B_8 8 +; OCR3AL 0x0086 Output Compare Register 3 A Low +; OCR3AL.OCR3A_7 7 +; OCR3AL.OCR3A_6 6 +; OCR3AL.OCR3A_5 5 +; OCR3AL.OCR3A_4 4 +; OCR3AL.OCR3A_3 3 +; OCR3AL.OCR3A_2 2 +; OCR3AL.OCR3A_1 1 +; OCR3AL.OCR3A_0 0 +; OCR3AH 0x0087 Output Compare Register 3 A High +; OCR3AH.OCR3A_15 15 +; OCR3AH.OCR3A_14 14 +; OCR3AH.OCR3A_13 13 +; OCR3AH.OCR3A_12 12 +; OCR3AH.OCR3A_11 11 +; OCR3AH.OCR3A_10 10 +; OCR3AH.OCR3A_9 9 +; OCR3AH.OCR3A_8 8 +; TCNT3L 0x0088 Timer/Counter 3 Low +; TCNT3L.TCNT3_7 7 +; TCNT3L.TCNT3_6 6 +; TCNT3L.TCNT3_5 5 +; TCNT3L.TCNT3_4 4 +; TCNT3L.TCNT3_3 3 +; TCNT3L.TCNT3_2 2 +; TCNT3L.TCNT3_1 1 +; TCNT3L.TCNT3_0 0 +; TCNT3H 0x0089 Timer/Counter 3 High +; TCNT3H.TCNT3_15 15 +; TCNT3H.TCNT3_14 14 +; TCNT3H.TCNT3_13 13 +; TCNT3H.TCNT3_12 12 +; TCNT3H.TCNT3_11 11 +; TCNT3H.TCNT3_10 10 +; TCNT3H.TCNT3_9 9 +; TCNT3H.TCNT3_8 8 +; TCCR3B 0x008A Timer/Counter 3 Control Register B +; TCCR3B.ICNC3 7 Input Capture Noise Canceler +; TCCR3B.ICES3 6 Input Capture Edge Select +; TCCR3B.WGM33 4 Waveform Generation Mode 3 +; TCCR3B.WGM32 3 Waveform Generation Mode 2 +; TCCR3B.CS32 2 Clock Select 2 +; TCCR3B.CS31 1 Clock Select 1 +; TCCR3B.CS30 0 Clock Select 0 +; TCCR3A 0x008B Timer/Counter 3 Control Register A +; TCCR3A.COM3A1 7 Compare Output Mode for Channel A 1 +; TCCR3A.COM3A0 6 Compare Output Mode for Channel A 0 +; TCCR3A.COM3B1 5 Compare Output Mode for Channel B 1 +; TCCR3A.COM3B0 4 Compare Output Mode for Channel B 0 +; TCCR3A.COM3C1 3 Compare Output Mode for Channel C 1 +; TCCR3A.COM3C0 2 Compare Output Mode for Channel C 0 +; TCCR3A.WGM31 1 Waveform Generation Mode 1 +; TCCR3A.WGM30 0 Waveform Generation Mode 0 +; TCCR3C 0x008C Timer/Counter 3 Control Register C +; TCCR3C.FOC3A 7 Force Output Compare for Channel A +; TCCR3C.FOC3B 6 Force Output Compare for Channel B +; TCCR3C.FOC3C 5 Force Output Compare for Channel C +; RESERVED008D 0x008D RESERVED +; ADCSRB 0x008E ADC Control and Status Register B +; ADCSRB.ADTS2 2 ADC Auto Trigger Source 2 +; ADCSRB.ADTS1 1 ADC Auto Trigger Source 1 +; ADCSRB.ADTS0 0 ADC Auto Trigger Source 0 +; RESERVED008F 0x008F RESERVED +; UBRR0H 0x0090 USART Baud Rate Register High +; UBRR0H.UBRR11 11 USART Baud Rate Register bit 11 +; UBRR0H.UBRR10 10 USART Baud Rate Register bit 10 +; UBRR0H.UBRR9 9 USART Baud Rate Register bit 9 +; UBRR0H.UBRR8 8 USART Baud Rate Register bit 8 +; RESERVED0091 0x0091 RESERVED +; RESERVED0092 0x0092 RESERVED +; RESERVED0093 0x0093 RESERVED +; RESERVED0094 0x0094 RESERVED +; UCSR0C 0x0095 USART Control and Status Register C +; UCSR0C.UMSEL 6 USART Mode Select +; UCSR0C.UPM1 5 Parity Mode 1 +; UCSR0C.UPM0 4 Parity Mode 0 +; UCSR0C.USBS 3 Stop Bit Select +; UCSR0C.UCSZ1 2 Character Size 1 +; UCSR0C.UCSZ0 1 Character Size 0 +; UCSR0C.UCPOL 0 Clock Polarity +; RESERVED0096 0x0096 RESERVED +; RESERVED0097 0x0097 RESERVED +; UBRR1H 0x0098 USART Baud Rate Register High +; UBRR1H.UBRR11 11 USART Baud Rate Register bit 11 +; UBRR1H.UBRR10 10 USART Baud Rate Register bit 10 +; UBRR1H.UBRR9 9 USART Baud Rate Register bit 9 +; UBRR1H.UBRR8 8 USART Baud Rate Register bit 8 +; UBRR1L 0x0099 USART Baud Rate Register Low +; UBRR1L.UBRR7 7 USART Baud Rate Register bit 7 +; UBRR1L.UBRR6 6 USART Baud Rate Register bit 6 +; UBRR1L.UBRR5 5 USART Baud Rate Register bit 5 +; UBRR1L.UBRR4 4 USART Baud Rate Register bit 4 +; UBRR1L.UBRR3 3 USART Baud Rate Register bit 3 +; UBRR1L.UBRR2 2 USART Baud Rate Register bit 2 +; UBRR1L.UBRR1 1 USART Baud Rate Register bit 1 +; UBRR1L.UBRR0 0 USART Baud Rate Register bit 0 +; UCSR1B 0x009A USART Control and Status Register B +; UCSR1B.RXCIE 7 RX Complete Interrupt Enable +; UCSR1B.TXCIE 6 TX Complete Interrupt Enable +; UCSR1B.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSR1B.RXEN 4 Receiver Enable +; UCSR1B.TXEN 3 Transmitter Enable +; UCSR1B.UCSZ2 2 Character Size +; UCSR1B.RXB8 1 Receive Data Bit 8 +; UCSR1B.TXB8 0 Transmit Data Bit 8 +; UCSR1A 0x009B USART Control and Status Register A +; UCSR1A.RXC 7 USART Receive Complete +; UCSR1A.TXC 6 USART Transmit Complete +; UCSR1A.UDRE 5 USART Data Register Empty +; UCSR1A.FE 4 Frame Error +; UCSR1A.DOR 3 Data OverRun +; UCSR1A.UPE 2 USART Parity Error +; UCSR1A.U2X 1 Double the USART Transmission Speed +; UCSR1A.MPCM 0 Multi-processor Communication Mode +; UDR1 0x009C USART1 I/O Data Register +; UCSR1C 0x009D USART Control and Status Register C +; UCSR1C.UMSEL 6 USART Mode Select +; UCSR1C.UPM1 5 Parity Mode 1 +; UCSR1C.UPM0 4 Parity Mode 0 +; UCSR1C.USBS 3 Stop Bit Select +; UCSR1C.UCSZ1 2 Character Size 1 +; UCSR1C.UCSZ0 1 Character Size 0 +; UCSR1C.UCPOL 0 Clock Polarity + +.ATmega644P +SUBARCH=5 + +RAM=4096 +ROM=65536 +EEPROM=2048 + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 32 General Purpose Working Registers +area DATA FSR1 0x0020:0x0060 64 I/O registers +area DATA FSR2 0x0060:0x0100 160 Ext I/O Reg. +area DATA I_SRAM 0x0100:0x1100 Internal SRAM + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset, Watchdog Reset, and JTAG AVR Reset +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry INT2_ 0x0006 External Interrupt Request 2 +entry PCINT0 0x0008 Pin Change Interrupt Request 0 +entry PCINT1 0x000A Pin Change Interrupt Request 1 +entry PCINT2 0x000C Pin Change Interrupt Request 2 +entry PCINT3 0x000E Pin Change Interrupt Request 3 +entry WDT 0x0010 Watchdog Time-out Interrupt +entry TIMER2_COMPA 0x0012 Timer/Counter2 Comapare Match A +entry TIMER2_COMPB 0x0014 Timer/Counter2 Comapare Match B +entry TIMER2_OVF 0x0016 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0018 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x001A Timer/Counter1 Comapare Match A +entry TIMER1_COMPB 0x001C Timer/Counter1 Comapare Match B +entry TIMER1_OVF 0x001E Timer/Counter1 Overflow +entry TIMER0_COMPA 0x0020 Timer/Counter0 Comapare Match A +entry TIMER0_COMPB 0x0022 Timer/Counter0 Comapare Match B +entry TIMER0_OVF 0x0024 Timer/Counter0 Overflow +entry SPI_STC 0x0026 SPI Serial Transfer Complete +entry USART0_RX 0x0028 USART0 RX Complete +entry USART0_UDRE 0x002A USART0 Data register empty +entry USART0_TX 0x002C USART0 TX Complete +entry ANALOG_COMP 0x002E Analog Comparator +entry ADC_ 0x0030 ADC Conversion Complete +entry EEREADY 0x0032 EEPROM Ready +entry TWI_ 0x0034 2-wire Serial Interface +entry SPM_READY 0x0036 Store Program Memory Ready +entry USART1_RX 0x0038 USART1 RX Complete +entry USART1_UDRE 0x003A USART1 Data register empty +entry USART1_TX 0x003C USART1 TX Complete + + +; INPUT/OUTPUT PORTS +; CHECK ALL REGISTERS FROM REGISTERS SUMMARY + +UDR1 0x00AE USART1 I/O Data Register +UBRR1H 0x00AD USART1 Baud Rate Register High Byte +UBRR1L 0x00AC USART1 Baud Rate Register Low Byte + +UCSR1C 0x00AA +UCSR1C.UMSEL11 7 +UCSR1C.UMSEL10 6 +UCSR1C.UCORD1 2 +UCSR1C.UCPHA1 1 +UCSR1C.UCPOL1 0 + +UCSR1B 0x00A9 +UCSR1B.RXCIE1 7 +UCSR1B.TXCIE1 6 +UCSR1B.UDRIE1 5 +UCSR1B.RXEN1 4 +UCSR1B.TXEN1 3 +UCSR1B.UCSZ12 2 +UCSR1B.RXB81 1 +UCSR1B.TXB81 0 + +UCSR1A 0x00A8 +UCSR1A.RXC1 7 +UCSR1A.TXC1 6 +UCSR1A.UDRE1 5 +UCSR1A.FE1 4 +UCSR1A.DOR1 3 +UCSR1A.UPE1 2 +UCSR1A.U2X1 1 +UCSR1A.MPCM1 0 + +UDR0 0x00A6 USART0 I/O Data Register +UBRR0H 0x00A5 USART0 Baud Rate Register High Byte +UBRR0L 0x00A4 USART0 Baud Rate Register Low Byte + +UCSR0C 0x00A2 +UCSR0C.UMSEL01 7 +UCSR0C.UMSEL00 6 +UCSR0C.UDORD0 2 +UCSR0C.UCPHA0 1 +UCSR0C.UCPOL0 0 + +UCSR0B 0x00A1 +UCSR0B.RXCIE0 7 +UCSR0B.TXCIE0 6 +UCSR0B.UDRIE0 5 +UCSR0B.RXEN0 4 +UCSR0B.TXEN0 3 +UCSR0B.UCSZ02 2 +UCSR0B.RXB80 1 +UCSR0B.TXB80 0 + +UCSR0A 0x00A0 +UCSR0A.RXC0 7 +UCSR0A.TXC0 6 +UCSR0A.UDRE0 5 +UCSR0A.FE0 4 +UCSR0A.DOR0 3 +UCSR0A.UPE0 2 +UCSR0A.U2X0 1 +UCSR0A.MPCM0 0 + +TWAMR 0x009D TWI (Slave) Address Mask Register +TWAMR.TWAM6 7 TWAM: TWI Address Mask bit 6 +TWAMR.TWAM5 6 TWAM: TWI Address Mask bit 5 +TWAMR.TWAM4 5 TWAM: TWI Address Mask bit 4 +TWAMR.TWAM3 4 TWAM: TWI Address Mask bit 3 +TWAMR.TWAM2 3 TWAM: TWI Address Mask bit 2 +TWAMR.TWAM1 2 TWAM: TWI Address Mask bit 1 +TWAMR.TWAM0 1 TWAM: TWI Address Mask bit 0 + +TWCR 0x009C TWI Control Register +TWCR.TWINT 7 TWINT: TWI Interrupt Flag +TWCR.TWEA 6 TWEA: TWI Enable Acknowledge Bit +TWCR.TWSTA 5 TWSTA: TWI START Condition Bit +TWCR.TWSTO 4 TWSTO: TWI STOP Condition Bit +TWCR.TWWC 3 TWWC: TWI Write Collision Flag +TWCR.TWEN 2 TWEN: TWI Enable Bit +TWCR.TWIE 0 TWIE: TWI Interrupt Enable + +TWDR 0x009B 2-wire Serial Interface Data Register + +TWAR 0x009A TWI (Slave) Address Register +TWAR.TWA6 7 TWA: TWI (Slave) Address Register bit 6 +TWAR.TWA5 6 TWA: TWI (Slave) Address Register bit 5 +TWAR.TWA4 5 TWA: TWI (Slave) Address Register bit 4 +TWAR.TWA3 4 TWA: TWI (Slave) Address Register bit 3 +TWAR.TWA2 3 TWA: TWI (Slave) Address Register bit 2 +TWAR.TWA1 2 TWA: TWI (Slave) Address Register bit 1 +TWAR.TWA0 1 TWA: TWI (Slave) Address Register bit 0 +TWAR.TWGCE 0 TWGCE: TWI General Call Recognition Enable Bit + +TWSR 0x0099 TWI Status Register +TWSR.TWS7 7 TWS: TWI Status bit 4 +TWSR.TWS6 6 TWS: TWI Status bit 3 +TWSR.TWS5 5 TWS: TWI Status bit 2 +TWSR.TWS4 4 TWS: TWI Status bit 1 +TWSR.TWS3 3 TWS: TWI Status bit 0 +TWSR.TWPS1 1 TWPS: TWI Prescaler bit 1 +TWSR.TWPS0 0 TWPS: TWI Prescaler bit 0 + +TWBR 0x0098 2-wire Serial Interface Bit Rate Register + +ASSR 0x0096 Asynchronous Status Register +ASSR.EXCLK 6 EXCLK: Enable External Clock Input +ASSR.AS2 5 AS2: Asynchronous Timer/Counter2 +ASSR.TCN2UB 4 TCN2UB: Timer/Counter2 Update Busy +ASSR.OCR2AUB 3 OCR2AUB: Output Compare Register2 Update Busy +ASSR.OCR2BUB 2 OCR2BUB: Output Compare Register2 Update Busy +ASSR.TCR2AUB 1 TCR2AUB: Timer/Counter Control Register2 Update Busy +ASSR.TCR2BUB 0 TCR2BUB: Timer/Counter Control Register2 Update Busy + +OCR2B 0x0094 Timer/Counter2 Output Compare Register B + +OCR2A 0x0093 Timer/Counter2 Output Compare Register A + +TCNT2 0x0092 Timer/Counter2 (8 Bit) + +TCCR2B 0x0091 Timer/Counter Control Register B +TCCR2B.FOC2A 7 FOC2A: Force Output Compare A +TCCR2B.FOC2B 6 FOC2B: Force Output Compare B +TCCR2B.WGM22 3 WGM22: Waveform Generation Mode +TCCR2B.CS22 2 CS22 Clock Select +TCCR2B.CS21 1 CS21 Clock Select +TCCR2B.CS20 0 CS20 Clock Select + +TCCR2A 0x0090 Timer/Counter Control Register A +TCCR2A.COM2A1 7 COM2A1 Compare Match Output A Mode +TCCR2A.COM2A0 6 COM2A0 Compare Match Output A Mode +TCCR2A.COM2B1 5 COM2B1 Compare Match Output B Mode +TCCR2A.COM2B0 4 COM2B0 Compare Match Output B Mode +TCCR2A.WGM21 1 WGM21 Waveform Generation Mode +TCCR2A.WGM20 0 WGM20 Waveform Generation Mode + +OCR1BH 0x006B Timer/Counter1 - Output Compare Register B High Byte +OCR1BH.Timer_Counter1 7 +OCR1BH.Output 5 +OCR1BH.Compare 4 +OCR1BH.Register 3 +OCR1BH.B 2 +OCR1BH.High 1 +OCR1BH.Byte 0 + +OCR1BL 0x006A Timer/Counter1 - Output Compare Register B Low Byte +OCR1BL.Timer_Counter1 7 +OCR1BL.Output 5 +OCR1BL.Compare 4 +OCR1BL.Register 3 +OCR1BL.B 2 +OCR1BL.Low 1 +OCR1BL.Byte 0 + +OCR1AH 0x0069 Timer/Counter1 - Output Compare Register A High Byte +OCR1AH.Timer_Counter1 7 +OCR1AH.Output 5 +OCR1AH.Compare 4 +OCR1AH.Register 3 +OCR1AH.A 2 +OCR1AH.High 1 +OCR1AH.Byte 0 + +OCR1AL 0x0068 Timer/Counter1 - Output Compare Register A Low Byte +OCR1AL.Timer_Counter1 7 +OCR1AL.Output 5 +OCR1AL.Compare 4 +OCR1AL.Register 3 +OCR1AL.A 2 +OCR1AL.Low 1 +OCR1AL.Byte 0 + +ICR1H 0x0067 Timer/Counter1 - Input Capture Register High Byte +ICR1H.Timer_Counter1 7 +ICR1H.Input 5 +ICR1H.Capture 4 +ICR1H.Register 3 +ICR1H.High 2 +ICR1H.Byte 1 +ICR1H.136 0 + +ICR1L 0x0066 Timer/Counter1 - Input Capture Register Low Byte +ICR1L.Timer_Counter1 7 +ICR1L.Input 5 +ICR1L.Capture 4 +ICR1L.Register 3 +ICR1L.Low 2 +ICR1L.Byte 1 +ICR1L.136 0 + +TCNT1H 0x0065 Timer/Counter1 - Counter Register High Byte + +TCNT1L 0x0064 Timer/Counter1 - Counter Register Low Byte + +TCCR1C 0x0062 Timer/Counter1 Control Register C +TCCR1C.FOC1A 7 FOC1A: Force Output Compare for Channel A +TCCR1C.FOC1B 6 FOC1B: Force Output Compare for Channel B + +TCCR1B 0x0061 Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 ICNC1: Input Capture Noise Canceler +TCCR1B.ICES1 6 ICES1: Input Capture Edge Select +TCCR1B.WGM13 4 WGM13 Waveform Generation Mode +TCCR1B.WGM12 3 WGM12 Waveform Generation Mode +TCCR1B.CS12 2 CS12 Clock Select +TCCR1B.CS11 1 CS11 Clock Select +TCCR1B.CS10 0 CS10 Clock Select + +TCCR1A 0x0060 Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 COM1A1 Compare Output Mode for Channel A +TCCR1A.COM1A0 6 COM1A0 Compare Output Mode for Channel A +TCCR1A.COM1B1 5 COM1B1 Compare Output Mode for Channel B +TCCR1A.COM1B0 4 COM1B0 Compare Output Mode for Channel B +TCCR1A.WGM11 1 WGM11 Waveform Generation Mode +TCCR1A.WGM10 0 WGM10 Waveform Generation Mode + +DIDR1 0x005F Digital Input Disable Register 1 +DIDR1.AIN1D 1 AIN1D: AIN1 Digital Input Disable +DIDR1.AIN0D 0 AIN0D: AIN0 Digital Input Disable + +DIDR0 0x005E Digital Input Disable Register 0 +DIDR0.ADC7D 7 ADC7D: ADC7 Digital Input Disable +DIDR0.ADC6D 6 ADC6D: ADC6 Digital Input Disable +DIDR0.ADC5D 5 ADC5D: ADC5 Digital Input Disable +DIDR0.ADC4D 4 ADC4D: ADC4 Digital Input Disable +DIDR0.ADC3D 3 ADC3D: ADC3 Digital Input Disable +DIDR0.ADC2D 2 ADC2D: ADC2 Digital Input Disable +DIDR0.ADC1D 1 ADC1D: ADC1 Digital Input Disable +DIDR0.ADC0D 0 ADC0D: ADC0 Digital Input Disable + +ADMUX 0x005C ADC Multiplexer Selection Register +ADMUX.REFS1 7 REFS1 Reference Selection Bits +ADMUX.REFS0 6 REFS0 Reference Selection Bits +ADMUX.ADLAR 5 ADLAR: ADC Left Adjust Result +ADMUX.MUX4 4 MUX4 Analog Channel and Gain Selection bit 4 +ADMUX.MUX3 3 MUX3 Analog Channel and Gain Selection bit 3 +ADMUX.MUX2 2 MUX2 Analog Channel and Gain Selection bit 2 +ADMUX.MUX1 1 MUX1 Analog Channel and Gain Selection bit 1 +ADMUX.MUX0 0 MUX0 Analog Channel and Gain Selection bit 0 + +ADCSRB 0x005B ADC Control and Status Register B +ADCSRB.ACME 6 +ADCSRB.ADTS2 2 +ADCSRB.ADTS1 1 +ADCSRB.ADTS0 0 + +ADCSRA 0x005A ADC Control and Status Register A +ADCSRA.ADEN 7 ADEN: ADC Enable +ADCSRA.ADSC 6 ADSC: ADC Start Conversion +ADCSRA.ADATE 5 ADATE: ADC Auto Trigger Enable +ADCSRA.ADIF 4 ADIF: ADC Interrupt Flag +ADCSRA.ADIE 3 ADIE: ADC Interrupt Enable +ADCSRA.ADPS2 2 ADPS2 ADC Prescaler Select bit 2 +ADCSRA.ADPS1 1 ADPS1 ADC Prescaler Select bit 1 +ADCSRA.ADPS0 0 ADPS0 ADC Prescaler Select bit 0 + +ADCH 0x0059 ADC Data Register High byte + +ADCL 0x0058 ADC Data Register Low byte + +PCMSK3 0x0053 Pin Change Mask Register 3 +PCMSK3.PCINT31 7 PCINT31 Pin Change Enable Mask +PCMSK3.PCINT30 6 PCINT30 Pin Change Enable Mask +PCMSK3.PCINT29 5 PCINT29 Pin Change Enable Mask +PCMSK3.PCINT28 4 PCINT28 Pin Change Enable Mask +PCMSK3.PCINT27 3 PCINT27 Pin Change Enable Mask +PCMSK3.PCINT26 2 PCINT26 Pin Change Enable Mask +PCMSK3.PCINT25 1 PCINT25 Pin Change Enable Mask +PCMSK3.PCINT24 0 PCINT24 Pin Change Enable Mask + +TIMSK2 0x0050 Timer/Counter2 Interrupt Mask Register +TIMSK2.OCIE2B 2 OCIE2B: Timer/Counter2 Output Compare Match B Interrupt Enable +TIMSK2.OCIE2A 1 OCIE2A: Timer/Counter2 Output Compare Match A Interrupt Enable +TIMSK2.TOIE2 0 TOIE2: Timer/Counter2 Overflow Interrupt Enable + +TIMSK1 0x004F Timer/Counter1 Interrupt Mask Register +TIMSK1.ICIE1 5 ICIE1: Timer/Counter1, Input Capture Interrupt Enable +TIMSK1.OCIE1B 2 OCIE1B: Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK1.OCIE1A 1 OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK1.TOIE1 0 TOIE1: Timer/Counter1, Overflow Interrupt Enable + +TIMSK0 0x004E Timer/Counter Interrupt Mask Register +TIMSK0.OCIE0B 2 OCIE0B: Timer/Counter Output Compare Match B Interrupt Enable +TIMSK0.OCIE0A 1 OCIE0A: Timer/Counter0 Output Compare Match A Interrupt Enable +TIMSK0.TOIE0 0 TOIE0: Timer/Counter0 Overflow Interrupt Enable + +PCMSK2 0x004D Pin Change Mask Register 2 +PCMSK2.PCINT23 7 PCINT23 Pin Change Enable Mask +PCMSK2.PCINT22 6 PCINT22 Pin Change Enable Mask +PCMSK2.PCINT21 5 PCINT21 Pin Change Enable Mask +PCMSK2.PCINT20 4 PCINT20 Pin Change Enable Mask +PCMSK2.PCINT19 3 PCINT19 Pin Change Enable Mask +PCMSK2.PCINT18 2 PCINT18 Pin Change Enable Mask +PCMSK2.PCINT17 1 PCINT17 Pin Change Enable Mask +PCMSK2.PCINT16 0 PCINT16 Pin Change Enable Mask + +PCMSK1 0x004C Pin Change Mask Register 1 +PCMSK1.PCINT15 7 PCINT15 Pin Change Enable Mask +PCMSK1.PCINT14 6 PCINT14 Pin Change Enable Mask +PCMSK1.PCINT13 5 PCINT13 Pin Change Enable Mask +PCMSK1.PCINT12 4 PCINT12 Pin Change Enable Mask +PCMSK1.PCINT11 3 PCINT11 Pin Change Enable Mask +PCMSK1.PCINT10 2 PCINT10 Pin Change Enable Mask +PCMSK1.PCINT9 1 PCINT9 Pin Change Enable Mask +PCMSK1.PCINT8 0 PCINT8 Pin Change Enable Mask + +PCMSK0 0x004B Pin Change Mask Register 0 +PCMSK0.PCINT7 7 PCINT7 Pin Change Enable Mask +PCMSK0.PCINT6 6 PCINT6 Pin Change Enable Mask +PCMSK0.PCINT5 5 PCINT5 Pin Change Enable Mask +PCMSK0.PCINT4 4 PCINT4 Pin Change Enable Mask +PCMSK0.PCINT3 3 PCINT3 Pin Change Enable Mask +PCMSK0.PCINT2 2 PCINT2 Pin Change Enable Mask +PCMSK0.PCINT1 1 PCINT1 Pin Change Enable Mask +PCMSK0.PCINT0 0 PCINT0 Pin Change Enable Mask + +EICRA 0x0049 External Interrupt Control Register A +EICRA.ISC21 5 ISC21: External Interrupt Sense Control Bits +EICRA.ISC20 4 ISC20: External Interrupt Sense Control Bits +EICRA.ISC11 3 ISC11: External Interrupt Sense Control Bits +EICRA.ISC10 2 ISC10: External Interrupt Sense Control Bits +EICRA.ISC01 1 ISC01: External Interrupt Sense Control Bits +EICRA.ISC00 0 ISC00: External Interrupt Sense Control Bits + +PCICR 0x0048 Pin Change Interrupt Control Register +PCICR.PCIE3 3 PCIE3: Pin Change Interrupt Enable 3 +PCICR.PCIE2 2 PCIE2: Pin Change Interrupt Enable 2 +PCICR.PCIE1 1 PCIE1: Pin Change Interrupt Enable 1 +PCICR.PCIE0 0 PCIE0: Pin Change Interrupt Enable 0 + +OSCCAL 0x0046 Oscillator Calibration Register + +PRR 0x0044 Power Reduction Register +PRR.PRTWI 7 PRTWI: Power Reduction TWI +PRR.PRTIM2 6 PRTIM2: Power Reduction Timer/Counter2 +PRR.PRTIM0 5 PRTIM0: Power Reduction Timer/Counter0 +PRR.PRUSART1 4 PRUSART1: Power Reduction USART1 +PRR.PRTIM1 3 PRTIM1: Power Reduction Timer/Counter1 +PRR.PRSPI 2 PRSPI: Power Reduction Serial Peripheral Interface +PRR.PRUSART0 1 PRUSART0: Power Reduction USART0 +PRR.PRADC 0 PRADC: Power Reduction ADC + +CLKPR 0x0041 Clock Prescale Register +CLKPR.CLKPCE 7 CLKPCE: Clock Prescaler Change Enable +CLKPR.CLKPS3 3 CLKPS3 Clock Prescaler Select bit 3 +CLKPR.CLKPS2 2 CLKPS2 Clock Prescaler Select bit 2 +CLKPR.CLKPS1 1 CLKPS1 Clock Prescaler Select bit 1 +CLKPR.CLKPS0 0 CLKPS0 Clock Prescaler Select bit 0 + +WDTCSR 0x0040 Watchdog Timer Control Register +WDTCSR.WDIF 7 WDIF: Watchdog Interrupt Flag +WDTCSR.WDIE 6 WDIE: Watchdog Interrupt Enable +WDTCSR.WDP3 5 WDP3: Watchdog Timer Prescaler 3 +WDTCSR.WDCE 4 WDCE: Watchdog Change Enable +WDTCSR.WDE 3 WDCE: Watchdog Change Enable +WDTCSR.WDP2 2 WDP2: Watchdog Timer Prescaler 3 +WDTCSR.WDP1 1 WDP1: Watchdog Timer Prescaler 3 +WDTCSR.WDP0 0 WDP0: Watchdog Timer Prescaler 3 + +SREG 0x003F Status Register +SREG.I 7 I: Global Interrupt Enable +SREG.T 6 T: Bit Copy Storage +SREG.H 5 H: Half Carry Flag +SREG.S 4 S: Sign Bit +SREG.V 3 V: Two’s Complement Overflow Flag +SREG.N 2 N: Negative Flag +SREG.Z 1 Z: Zero Flag +SREG.C 0 C: Carry Flag + +SPH 0x003E Stack Pointer High +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 + +SPL 0x003D Stack pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 + +SPMCSR 0x0037 Store Program Memory Control and Status Register +SPMCSR.SPMIE 7 SPMIE: SPM Interrupt Enable +SPMCSR.RWWSB 6 RWWSB: Read-While-Write Section Busy +SPMCSR.SIGRD 5 SIGRD: Signature Row Read +SPMCSR.RWWSRE 4 RWWSRE: Read-While-Write Section Read Enable +SPMCSR.BLBSET 3 BLBSET: Boot Lock Bit Set +SPMCSR.PGWRT 2 PGWRT: Page Write +SPMCSR.PGERS 1 PGERS: Page Erase +SPMCSR.SPMEN 0 SPMEN: Store Program Memory Enable + +MCUCR 0x0035 MCU Control Register +MCUCR.JTD 7 +MCUCR.BODS 6 BODS: BOD Sleep +MCUCR.BODSE 5 BODSE: BOD Sleep Enable +MCUCR.PUD 4 +MCUCR.IVSEL 1 +MCUCR.IVCE 0 + +MCUSR 0x0034 MCU Status Register +MCUSR.JTRF 4 JTRF: JTAG Reset Flag +MCUSR.WDRF 3 WDRF: Watchdog Reset Flag +MCUSR.BORF 2 BORF: Brown-out Reset Flag +MCUSR.EXTRF 1 EXTRF: External Reset Flag +MCUSR.PORF 0 PORF: Power-on Reset Flag + +SMCR 0x0033 Sleep Mode Control Register +SMCR.SM2 3 SM2 Sleep Mode Select bit 2 +SMCR.SM1 2 SM1 Sleep Mode Select bit 1 +SMCR.SM0 1 SM0 Sleep Mode Select bit 0 +SMCR.SE 0 SE: Sleep Enable + +OCDR 0x0031 On-Chip Debug Register + +ACSR 0x0030 Analog Comparator Control and Status Register +ACSR.ACD 7 ACD: Analog Comparator Disable +ACSR.ACBG 6 ACBG: Analog Comparator Bandgap Select +ACSR.ACO 5 ACO: Analog Comparator Output +ACSR.ACI 4 ACI: Analog Comparator Interrupt Flag +ACSR.ACIE 3 ACIE: Analog Comparator Interrupt Enable +ACSR.ACIC 2 ACIC: Analog Comparator Input Capture Enable +ACSR.ACIS1 1 ACIS1: Analog Comparator Interrupt Mode Select +ACSR.ACIS0 0 ACIS0: Analog Comparator Interrupt Mode Select + +SPDR 0x002E SPI Data Register + +SPSR 0x002D SPI Status Register +SPSR.SPIF 7 SPIF: SPI Interrupt Flag +SPSR.WCOL 6 WCOL: Write COLlision Flag +SPSR.SPI2X 0 SPI2X: Double SPI Speed Bit + +SPCR 0x002C SPI Control Register +SPCR.SPIE 7 SPIE: SPI Interrupt Enable +SPCR.SPE 6 SPE: SPI Enable +SPCR.DORD 5 DORD: Data Order +SPCR.MSTR 4 MSTR: Master/Slave Select +SPCR.CPOL 3 CPOL: Clock Polarity +SPCR.CPHA 2 CPHA: Clock Phase +SPCR.SPR1 1 SPR1: SPI Clock Rate Select 1 +SPCR.SPR0 0 SPR0: SPI Clock Rate Select 0 + +GPIOR2 0x002B General Purpose I/O Register 2 + +GPIOR1 0x002A General Purpose I/O Register 1 + +OCR0B 0x0028 Timer/Counter0 Output Compare Register B + +OCR0A 0x0027 Timer/Counter0 Output Compare Register A + +TCNT0 0x0026 Timer/Counter0 (8 Bit) + +TCCR0B 0x0025 Timer/Counter Control Register B +TCCR0B.FOC0A 7 FOC0A: Force Output Compare A +TCCR0B.FOC0B 6 FOC0B: Force Output Compare B +TCCR0B.WGM02 3 WGM02: Waveform Generation Mode +TCCR0B.CS02 2 CS02: Clock Select +TCCR0B.CS01 1 CS01: Clock Select +TCCR0B.CS00 0 CS00: Clock Select + +TCCR0A 0x0024 Timer/Counter Control Register A +TCCR0A.COM0A1 7 COM0A1: Compare Match Output A Mode +TCCR0A.COM0A0 6 COM0A0: Compare Match Output A Mode +TCCR0A.COM0B1 5 COM0B1: Compare Match Output B Mode +TCCR0A.COM0B0 4 COM0B0: Compare Match Output B Mode +TCCR0A.WGM01 1 WGM01: Waveform Generation Mode +TCCR0A.WGM00 0 WGM00: Waveform Generation Mode + +GTCCR 0x0023 General Timer/Counter Control Register +GTCCR.TSM 7 TSM: Timer/Counter Synchronization mode +GTCCR.PSRASY 1 PSRASY: Prescaler Reset Timer/Counter2 +GTCCR.PSRSYNC 0 PSRSYNC: Prescaler Reset + +EEARH 0x0022 EEPROM Address Register High Byte +EEARL 0x0021 EEPROM Address Register Low Byte +EEDR 0x0020 EEPROM Data Register + +EECR 0x001F The EEPROM Control Register +EECR.EEPM1 5 EEPM1: EEPROM Programming Mode Bits +EECR.EEPM0 4 EEPM0: EEPROM Programming Mode Bits +EECR.EERIE 3 EERIE: EEPROM Ready Interrupt Enable +EECR.EEMPE 2 EEMPE: EEPROM Master Programming Enable +EECR.EEPE 1 EEPE: EEPROM Programming Enable +EECR.EERE 0 EERE: EEPROM Read Enable + +GPIOR0 0x001E General Purpose I/O Register 0 + +EIMSK 0x001D External Interrupt Mask Register +EIMSK.INT2 2 INT2 External Interrupt Request 2 +EIMSK.INT1 1 INT1 External Interrupt Request 1 +EIMSK.INT0 0 INT0 External Interrupt Request 0 + +EIFR 0x001C External Interrupt Flag Register +EIFR.INTF2 2 INTF2 External Interrupt Flags 2 +EIFR.INTF1 1 INTF1 External Interrupt Flags 1 +EIFR.INTF0 0 INTF0 External Interrupt Flags 0 + +PCIFR 0x001B Pin Change Interrupt Flag Register +PCIFR.PCIF3 3 PCIF3: Pin Change Interrupt Flag 3 +PCIFR.PCIF2 2 PCIF2: Pin Change Interrupt Flag 2 +PCIFR.PCIF1 1 PCIF1: Pin Change Interrupt Flag 1 +PCIFR.PCIF0 0 PCIF0: Pin Change Interrupt Flag 0 + +TIFR2 0x0017 Timer/Counter2 Interrupt Flag Register +TIFR2.OCF2B 2 OCF2B: Output Compare Flag 2 B +TIFR2.OCF2A 1 OCF2A: Output Compare Flag 2 A +TIFR2.TOV2 0 TOV2: Timer/Counter2 Overflow Flag + +TIFR1 0x0016 Timer/Counter1 Interrupt Flag Register +TIFR1.ICF1 5 ICF1: Timer/Counter1, Input Capture Flag +TIFR1.OCF1B 2 OCF1B: Timer/Counter1, Output Compare B Match Flag +TIFR1.OCF1A 1 OCF1A: Timer/Counter1, Output Compare A Match Flag +TIFR1.TOV1 0 TOV1: Timer/Counter1, Overflow Flag + +TIFR0 0x0015 Timer/Counter 0 Interrupt Flag Register +TIFR0.OCF0B 2 OCF0B: Timer/Counter 0 Output Compare B Match Flag +TIFR0.OCF0A 1 OCF0A: Timer/Counter 0 Output Compare A Match Flag +TIFR0.TOV0 0 TOV0: Timer/Counter0 Overflow Flag + +PORTD 0x000B Port D Data Register +PORTD.PORTD7 7 PORT D7 +PORTD.PORTD6 6 PORT D6 +PORTD.PORTD5 5 PORT D5 +PORTD.PORTD4 4 PORT D4 +PORTD.PORTD3 3 PORT D3 +PORTD.PORTD2 2 PORT D2 +PORTD.PORTD1 1 PORT D1 +PORTD.PORTD0 0 PORT D0 + +DDRD 0x000A Port D Data Direction Register +DDRD.DDD7 7 +DDRD.DDD6 6 +DDRD.DDD5 5 +DDRD.DDD4 4 +DDRD.DDD3 3 +DDRD.DDD2 2 +DDRD.DDD1 1 +DDRD.DDD0 0 + +PIND 0x0009 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 + +PORTC 0x0008 Port C Data Register +PORTC.PORTC7 7 +PORTC.PORTC6 6 +PORTC.PORTC5 5 +PORTC.PORTC4 4 +PORTC.PORTC3 3 +PORTC.PORTC2 2 +PORTC.PORTC1 1 +PORTC.PORTC0 0 + +DDRC 0x0007 Port C Data Direction Register +DDRC.DDC7 7 +DDRC.DDC6 6 +DDRC.DDC5 5 +DDRC.DDC4 4 +DDRC.DDC3 3 +DDRC.DDC2 2 +DDRC.DDC1 1 +DDRC.DDC0 0 + +PINC 0x0006 Port C Input Pins Address +PINC.PINC6 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 + +PORTB 0x0005 Port B Data Register +PORTB.PORTB7 7 +PORTB.PORTB6 6 +PORTB.PORTB5 5 +PORTB.PORTB4 4 +PORTB.PORTB3 3 +PORTB.PORTB2 2 +PORTB.PORTB1 1 +PORTB.PORTB0 0 + +DDRB 0x0004 Port B Data Direction Register +DDRB.DDB7 7 +DDRB.DDB6 6 +DDRB.DDB5 5 +DDRB.DDB4 4 +DDRB.DDB3 3 +DDRB.DDB2 2 +DDRB.DDB1 1 +DDRB.DDB0 0 + +PINB 0x0003 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 + +PORTA 0x0002 Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 + +DDRA 0x0001 Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 + +PINA 0x0000 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 + +.ATmega8515_L +SUBARCH=2 +; doc2512.pdf +; + +RAM=512 +ROM=8192 +EEPROM=512 + +; MEMORY MAP +area DATA FSR_ 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x0260 Internal SRAM +area DATA E_SRAM 0x0260:0x10000 External SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset,Brown-out Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0005 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0006 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0007 Timer/Counter0 Overflow +entry SPI_STC 0x0008 Serial Transfer Complete +entry USART_RXC 0x0009 USART, Rx Complete +entry USART_UDRE 0x000A USART Data Register Empty +entry USART_TXC 0x000B USART, Tx Complete +entry ANA_COMP 0x000C Analog Comparator +entry INT2_ 0x000D External Interrupt Request 2 +entry TIMER0_COMP 0x000E Timer/Counter0 Compare Match +entry EE_RDY 0x000F EEPROM Ready +entry SPM_RDY 0x0010 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +OSCCAL 0x0004 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +PINE 0x0005 Port E Input Pins Address +PINE.PINE2 2 +PINE.PINE1 1 +PINE.PINE0 0 +DDRE 0x0006 Port E Data Direction Register +DDRE.DDE2 2 Port E Data Direction Register bit 2 +DDRE.DDE1 1 Port E Data Direction Register bit 1 +DDRE.DDE0 0 Port E Data Direction Register bit 0 +PORTE 0x0007 Port E Data Register +PORTE.PORTE2 2 Port E Data Register bit 2 +PORTE.PORTE1 1 Port E Data Register bit 1 +PORTE.PORTE0 0 Port E Data Register bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register Low +UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +UCSRB 0x000A USART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit8 +UCSRA 0x000B USART Control and Status Register A +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.PE 2 ParityError +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision Flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR9 9 EEPROM Addres 9 +UCSRC 0x0020 USART Control and Status Register C +UCSRC.URSEL 7 Register Select +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +; UBRRH 0x0020 USART Baud Rate Register High +; UBRRH.URSEL 15 Register Select +; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +ICR1L 0x0024 Input Capture Register 1 Low +ICR1L.ICR1_7 7 +ICR1L.ICR1_6 6 +ICR1L.ICR1_5 5 +ICR1L.ICR1_4 4 +ICR1L.ICR1_3 3 +ICR1L.ICR1_2 2 +ICR1L.ICR1_1 1 +ICR1L.ICR1_0 0 +ICR1H 0x0025 Input Capture Register 1 High +ICR1H.ICR1_15 15 +ICR1H.ICR1_14 14 +ICR1H.ICR1_13 13 +ICR1H.ICR1_12 12 +ICR1H.ICR1_11 11 +ICR1H.ICR1_10 10 +ICR1H.ICR1_9 9 +ICR1H.ICR1_8 8 +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +OCR1BL 0x0028 Output Compare Register 1 B Low +OCR1BL.OCR1B_7 7 +OCR1BL.OCR1B_6 6 +OCR1BL.OCR1B_5 5 +OCR1BL.OCR1B_4 4 +OCR1BL.OCR1B_3 3 +OCR1BL.OCR1B_2 2 +OCR1BL.OCR1B_1 1 +OCR1BL.OCR1B_0 0 +OCR1BH 0x0029 Output Compare Register 1 B High +OCR1BH.OCR1B_15 15 +OCR1BH.OCR1B_14 14 +OCR1BH.OCR1B_13 13 +OCR1BH.OCR1B_12 12 +OCR1BH.OCR1B_11 11 +OCR1BH.OCR1B_10 10 +OCR1BH.OCR1B_9 9 +OCR1BH.OCR1B_8 8 +OCR1AL 0x002A Output Compare Register 1 A Low +OCR1AL.OCR1A_7 7 +OCR1AL.OCR1A_6 6 +OCR1AL.OCR1A_5 5 +OCR1AL.OCR1A_4 4 +OCR1AL.OCR1A_3 3 +OCR1AL.OCR1A_2 2 +OCR1AL.OCR1A_1 1 +OCR1AL.OCR1A_0 0 +OCR1AH 0x002B Output Compare Register 1 A High +OCR1AH.OCR1A_15 15 +OCR1AH.OCR1A_14 14 +OCR1AH.OCR1A_13 13 +OCR1AH.OCR1A_12 12 +OCR1AH.OCR1A_11 11 +OCR1AH.OCR1A_10 10 +OCR1AH.OCR1A_9 9 +OCR1AH.OCR1A_8 8 +TCNT1L 0x002C Timer/Counter 1 Low +TCNT1L.TCNT1_7 7 +TCNT1L.TCNT1_6 6 +TCNT1L.TCNT1_5 5 +TCNT1L.TCNT1_4 4 +TCNT1L.TCNT1_3 3 +TCNT1L.TCNT1_2 2 +TCNT1L.TCNT1_1 1 +TCNT1L.TCNT1_0 0 +TCNT1H 0x002D Timer/Counter 1 High +TCNT1H.TCNT1_15 15 +TCNT1H.TCNT1_14 14 +TCNT1H.TCNT1_13 13 +TCNT1H.TCNT1_12 12 +TCNT1H.TCNT1_11 11 +TCNT1H.TCNT1_10 10 +TCNT1H.TCNT1_9 9 +TCNT1H.TCNT1_8 8 +TCCR1B 0x002E Timer/Counter 1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input Capture Edge Select +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter 1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 +TCCR1A.FOC1A 3 Force Output Compare for channel A +TCCR1A.FOC1B 2 Force Output Compare for channel B +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +SFIOR 0x0030 Special Function IO Register +SFIOR.XMBK 6 External Memory Bus Keeper Enable +SFIOR.XMM2 5 External Memory High Mask 2 +SFIOR.XMM1 4 External Memory High Mask 1 +SFIOR.XMM0 3 External Memory High Mask 0 +SFIOR.PUD 2 Pull-up Disable +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OCR0 0x0031 Output Compare Register +OCR0.OCR0_7 7 +OCR0.OCR0_6 6 +OCR0.OCR0_5 5 +OCR0.OCR0_4 4 +OCR0.OCR0_3 3 +OCR0.OCR0_2 2 +OCR0.OCR0_1 1 +OCR0.OCR0_0 0 +TCNT0 0x0032 Timer/Counter Register +TCNT0.TCNT0_7 7 +TCNT0.TCNT0_6 6 +TCNT0.TCNT0_5 5 +TCNT0.TCNT0_4 4 +TCNT0.TCNT0_3 3 +TCNT0.TCNT0_2 2 +TCNT0.TCNT0_1 1 +TCNT0.TCNT0_0 0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.SM2 5 Sleep Mode Select Bit 2 +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SRE 7 External SRAM/XMEM Enable +MCUCR.SRW10 6 Wait State Select Bit +MCUCR.SE 5 SleepEnable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +EMCUCR 0x0036 Extended MCU Control Register +EMCUCR.SM0 7 Sleep Mode Select Bit 0 +EMCUCR.SRL2 6 Wait State Sector Limit 2 +EMCUCR.SRL1 5 Wait State Sector Limit 1 +EMCUCR.SRL0 4 Wait State Sector Limit 0 +EMCUCR.SRW01 3 Wait State Select Bits for Lower Sector 1 +EMCUCR.SRW00 2 Wait State Select Bits for Lower Sector 0 +EMCUCR.SRW11 1 Wait State Select Bits for Upper 1 +EMCUCR.ISC2 0 Interrupt Sense Control 2 +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.SPMIE 7 SPM Interrupt Enable +SPMCR.RWWSB 6 Read-While-Write Section Busy +SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +SPMCR.BLBSET 3 Boot Lock BitSet +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter1, Overflow Flag +TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag +TIFR.ICF1 3 Timer/Counter1, Input Capture Flag +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIFR.OCF0 0 OutputCompare Flag0 +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIFR.INTF2 5 External Interrupt Flag 2 +GICR 0x003B General Interrupt Control Register +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.INT2 5 External Interrupt Request 2 Enable +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP15 15 +SPH.SP14 14 +SPH.SP13 13 +SPH.SP12 12 +SPH.SP11 11 +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; OSCCAL 0x0024 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; PINE 0x0025 Port E Input Pins Address +; PINE.PINE2 2 +; PINE.PINE1 1 +; PINE.PINE0 0 +; DDRE 0x0026 Port E Data Direction Register +; DDRE.DDE2 2 Port E Data Direction Register bit 2 +; DDRE.DDE1 1 Port E Data Direction Register bit 1 +; DDRE.DDE0 0 Port E Data Direction Register bit 0 +; PORTE 0x0027 Port E Data Register +; PORTE.PORTE2 2 Port E Data Register bit 2 +; PORTE.PORTE1 1 Port E Data Register bit 1 +; PORTE.PORTE0 0 Port E Data Register bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRRL 0x0029 USART Baud Rate Register Low +; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +; UCSRB 0x002A USART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.UCSZ2 2 Character Size +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit8 +; UCSRA 0x002B USART Control and Status Register A +; UCSRA.RXC 7 USART Receive Complete +; UCSRA.TXC 6 USART Transmit Complete +; UCSRA.UDRE 5 USART Data Register Empty +; UCSRA.FE 4 Frame Error +; UCSRA.DOR 3 Data OverRun +; UCSRA.PE 2 ParityError +; UCSRA.U2X 1 Double the USART Transmission Speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision Flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEDR.EEDR7 7 EEPROM Data 7 +; EEDR.EEDR6 6 EEPROM Data 6 +; EEDR.EEDR5 5 EEPROM Data 5 +; EEDR.EEDR4 4 EEPROM Data 4 +; EEDR.EEDR3 3 EEPROM Data 3 +; EEDR.EEDR2 2 EEPROM Data 2 +; EEDR.EEDR1 1 EEPROM Data 1 +; EEDR.EEDR0 0 EEPROM Data 0 +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR9 9 EEPROM Addres 9 +; UCSRC 0x0040 USART Control and Status Register C +; UCSRC.URSEL 7 Register Select +; UCSRC.UMSEL 6 USART Mode Select +; UCSRC.UPM1 5 Parity Mode 1 +; UCSRC.UPM0 4 Parity Mode 0 +; UCSRC.USBS 3 Stop Bit Select +; UCSRC.UCSZ1 2 Character Size 1 +; UCSRC.UCSZ0 1 Character Size 0 +; UCSRC.UCPOL 0 Clock Polarity +; ; UBRRH 0x0040 USART Baud Rate Register High +; ; UBRRH.URSEL 15 Register Select +; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; ICR1L 0x0044 Input Capture Register 1 Low +; ICR1L.ICR1_7 7 +; ICR1L.ICR1_6 6 +; ICR1L.ICR1_5 5 +; ICR1L.ICR1_4 4 +; ICR1L.ICR1_3 3 +; ICR1L.ICR1_2 2 +; ICR1L.ICR1_1 1 +; ICR1L.ICR1_0 0 +; ICR1H 0x0045 Input Capture Register 1 High +; ICR1H.ICR1_15 15 +; ICR1H.ICR1_14 14 +; ICR1H.ICR1_13 13 +; ICR1H.ICR1_12 12 +; ICR1H.ICR1_11 11 +; ICR1H.ICR1_10 10 +; ICR1H.ICR1_9 9 +; ICR1H.ICR1_8 8 +; RESERVED0046 0x0046 RESERVED +; RESERVED0047 0x0047 RESERVED +; OCR1BL 0x0048 Output Compare Register 1 B Low +; OCR1BL.OCR1B_7 7 +; OCR1BL.OCR1B_6 6 +; OCR1BL.OCR1B_5 5 +; OCR1BL.OCR1B_4 4 +; OCR1BL.OCR1B_3 3 +; OCR1BL.OCR1B_2 2 +; OCR1BL.OCR1B_1 1 +; OCR1BL.OCR1B_0 0 +; OCR1BH 0x0049 Output Compare Register 1 B High +; OCR1BH.OCR1B_15 15 +; OCR1BH.OCR1B_14 14 +; OCR1BH.OCR1B_13 13 +; OCR1BH.OCR1B_12 12 +; OCR1BH.OCR1B_11 11 +; OCR1BH.OCR1B_10 10 +; OCR1BH.OCR1B_9 9 +; OCR1BH.OCR1B_8 8 +; OCR1AL 0x004A Output Compare Register 1 A Low +; OCR1AL.OCR1A_7 7 +; OCR1AL.OCR1A_6 6 +; OCR1AL.OCR1A_5 5 +; OCR1AL.OCR1A_4 4 +; OCR1AL.OCR1A_3 3 +; OCR1AL.OCR1A_2 2 +; OCR1AL.OCR1A_1 1 +; OCR1AL.OCR1A_0 0 +; OCR1AH 0x004B Output Compare Register 1 A High +; OCR1AH.OCR1A_15 15 +; OCR1AH.OCR1A_14 14 +; OCR1AH.OCR1A_13 13 +; OCR1AH.OCR1A_12 12 +; OCR1AH.OCR1A_11 11 +; OCR1AH.OCR1A_10 10 +; OCR1AH.OCR1A_9 9 +; OCR1AH.OCR1A_8 8 +; TCNT1L 0x004C Timer/Counter 1 Low +; TCNT1L.TCNT1_7 7 +; TCNT1L.TCNT1_6 6 +; TCNT1L.TCNT1_5 5 +; TCNT1L.TCNT1_4 4 +; TCNT1L.TCNT1_3 3 +; TCNT1L.TCNT1_2 2 +; TCNT1L.TCNT1_1 1 +; TCNT1L.TCNT1_0 0 +; TCNT1H 0x004D Timer/Counter 1 High +; TCNT1H.TCNT1_15 15 +; TCNT1H.TCNT1_14 14 +; TCNT1H.TCNT1_13 13 +; TCNT1H.TCNT1_12 12 +; TCNT1H.TCNT1_11 11 +; TCNT1H.TCNT1_10 10 +; TCNT1H.TCNT1_9 9 +; TCNT1H.TCNT1_8 8 +; TCCR1B 0x004E Timer/Counter 1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input Capture Edge Select +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter 1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 +; TCCR1A.FOC1A 3 Force Output Compare for channel A +; TCCR1A.FOC1B 2 Force Output Compare for channel B +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; SFIOR 0x0050 Special Function IO Register +; SFIOR.XMBK 6 External Memory Bus Keeper Enable +; SFIOR.XMM2 5 External Memory High Mask 2 +; SFIOR.XMM1 4 External Memory High Mask 1 +; SFIOR.XMM0 3 External Memory High Mask 0 +; SFIOR.PUD 2 Pull-up Disable +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OCR0 0x0051 Output Compare Register +; OCR0.OCR0_7 7 +; OCR0.OCR0_6 6 +; OCR0.OCR0_5 5 +; OCR0.OCR0_4 4 +; OCR0.OCR0_3 3 +; OCR0.OCR0_2 2 +; OCR0.OCR0_1 1 +; OCR0.OCR0_0 0 +; TCNT0 0x0052 Timer/Counter Register +; TCNT0.TCNT0_7 7 +; TCNT0.TCNT0_6 6 +; TCNT0.TCNT0_5 5 +; TCNT0.TCNT0_4 4 +; TCNT0.TCNT0_3 3 +; TCNT0.TCNT0_2 2 +; TCNT0.TCNT0_1 1 +; TCNT0.TCNT0_0 0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.SM2 5 Sleep Mode Select Bit 2 +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SRE 7 External SRAM/XMEM Enable +; MCUCR.SRW10 6 Wait State Select Bit +; MCUCR.SE 5 SleepEnable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; EMCUCR 0x0056 Extended MCU Control Register +; EMCUCR.SM0 7 Sleep Mode Select Bit 0 +; EMCUCR.SRL2 6 Wait State Sector Limit 2 +; EMCUCR.SRL1 5 Wait State Sector Limit 1 +; EMCUCR.SRL0 4 Wait State Sector Limit 0 +; EMCUCR.SRW01 3 Wait State Select Bits for Lower Sector 1 +; EMCUCR.SRW00 2 Wait State Select Bits for Lower Sector 0 +; EMCUCR.SRW11 1 Wait State Select Bits for Upper 1 +; EMCUCR.ISC2 0 Interrupt Sense Control 2 +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock BitSet +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.TOV1 7 Timer/Counter1, Overflow Flag +; TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag +; TIFR.ICF1 3 Timer/Counter1, Input Capture Flag +; TIFR.TOV0 1 Timer/Counter0 Overflow Flag +; TIFR.OCF0 0 OutputCompare Flag0 +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TICIE1 3 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; TIMSK.OCIE0 0 Timer/Counter0 Output Compare Match Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIFR.INTF2 5 External Interrupt Flag 2 +; GICR 0x005B General Interrupt Control Register +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.INT2 5 External Interrupt Request 2 Enable +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; RESERVED005C 0x005C RESERVED +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP15 15 +; SPH.SP14 14 +; SPH.SP13 13 +; SPH.SP12 12 +; SPH.SP11 11 +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega8535_L +SUBARCH=2 +; doc2502.pdf +; + +RAM=512 +ROM=8192 +EEPROM=512 + +; MEMORY MAP +area DATA FSR 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x0260 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER2_COMP 0x0003 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0004 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0005 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0006 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0007 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0008 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0009 Timer/Counter0 Overflow +entry SPI_STC 0x000A Serial Transfer Complete +entry USART_RXC 0x000B USART, Rx Complete +entry USART_UDRE 0x000C USART Data Register Empty +entry USART_TXC 0x000D USART, Tx Complete +entry ADC_ 0x000E ADC Conversion Complete +entry EE_RDY 0x000F EEPROM Ready +entry ANA_COMP 0x0010 Analog Comparator +entry TWI_ 0x0011 Two-wire Serial Interface +entry INT2_ 0x0012 External Interrupt Request 2 +entry TIMER0_COMP 0x0013 Timer/Counter0 Compare Match +entry SPM_RDY 0x0014 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +TWBR 0x0000 TWI Bit Rate Register +TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +TWSR 0x0001 TWI Status Register +TWSR.TWS7 7 TWI Status +TWSR.TWS6 6 TWI Status +TWSR.TWS5 5 TWI Status +TWSR.TWS4 4 TWI Status +TWSR.TWS3 3 TWI Status +TWSR.TWPS1 1 TWI Prescaler Bit 1 +TWSR.TWPS0 0 TWI Prescaler Bit 0 +TWAR 0x0002 TWI (Slave) Address Register +TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +TWDR 0x0003 TWI Data Register +TWDR.TWD7 7 TWI Data Register bit 7 +TWDR.TWD6 6 TWI Data Register bit 6 +TWDR.TWD5 5 TWI Data Register bit 5 +TWDR.TWD4 4 TWI Data Register bit 4 +TWDR.TWD3 3 TWI Data Register bit 3 +TWDR.TWD2 2 TWI Data Register bit 2 +TWDR.TWD1 1 TWI Data Register bit 1 +TWDR.TWD0 0 TWI Data Register bit 0 +ADCL 0x0004 ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion Result 7 +ADCL.ADC6 6 ADC Conversion Result 6 +ADCL.ADC5 5 ADC Conversion Result 5 +ADCL.ADC4 4 ADC Conversion Result 4 +ADCL.ADC3 3 ADC Conversion Result 3 +ADCL.ADC2 2 ADC Conversion Result 2 +ADCL.ADC1 1 ADC Conversion Result 1 +ADCL.ADC0 0 ADC Conversion Result 0 +ADCH 0x0005 ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 ADC Conversion Result 9 +ADCH.ADC8 8 ADC Conversion Result 8 +; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion Result 1 +; ADCL.ADC0 6 ADC Conversion Result 0 +; ADCH 0x0005 ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion Result 9 +; ADCH.ADC8 14 ADC Conversion Result 8 +; ADCH.ADC7 13 ADC Conversion Result 7 +; ADCH.ADC6 12 ADC Conversion Result 6 +; ADCH.ADC5 11 ADC Conversion Result 5 +; ADCH.ADC4 10 ADC Conversion Result 4 +; ADCH.ADC3 9 ADC Conversion Result 3 +; ADCH.ADC2 8 ADC Conversion Result 2 +ADCSRA 0x0006 ADC Control and Status Register A +ADCSRA.ADEN 7 ADC Enable +ADCSRA.ADSC 6 ADC Start Conversion +ADCSRA.ADATE 5 ADC Auto Trigger Enable +ADCSRA.ADIF 4 ADC Interrupt Flag +ADCSRA.ADIE 3 ADC Interrupt Enable +ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register Low +UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +UCSRB 0x000A USART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B USART Control and Status Register A +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.PE 2 Parity Error +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC7 7 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC7 7 Port C Data Direction Register bit 7 +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC7 7 Port C Data Register bit 7 +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR8 8 EEPROM Addres 8 +UCSRC 0x0020 USART Control and Status Register (page 159) +UCSRC.URSEL 7 Register Select +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +; UBRRH 0x0020 USART Baud Rate Register High (page 159) +; UBRRH.URSEL 15 Register Select +; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register 2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register 2 Update Busy +OCR2 0x0023 Output Compare Register +OCR2.OCR2_7 7 +OCR2.OCR2_6 6 +OCR2.OCR2_5 5 +OCR2.OCR2_4 4 +OCR2.OCR2_3 3 +OCR2.OCR2_2 2 +OCR2.OCR2_1 1 +OCR2.OCR2_0 0 +TCNT2 0x0024 Timer/Counter Register +TCNT2.TCNT2_7 7 +TCNT2.TCNT2_6 6 +TCNT2.TCNT2_5 5 +TCNT2.TCNT2_4 4 +TCNT2.TCNT2_3 3 +TCNT2.TCNT2_2 2 +TCNT2.TCNT2_1 1 +TCNT2.TCNT2_0 0 +TCCR2 0x0025 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Compare Match Output Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Waveform Generation Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +ICR1L 0x0026 Input Capture Register 1 Low +ICR1L.ICR1_7 7 +ICR1L.ICR1_6 6 +ICR1L.ICR1_5 5 +ICR1L.ICR1_4 4 +ICR1L.ICR1_3 3 +ICR1L.ICR1_2 2 +ICR1L.ICR1_1 1 +ICR1L.ICR1_0 0 +ICR1H 0x0027 Input Capture Register 1 High +ICR1H.ICR1_15 15 +ICR1H.ICR1_14 14 +ICR1H.ICR1_13 13 +ICR1H.ICR1_12 12 +ICR1H.ICR1_11 11 +ICR1H.ICR1_10 10 +ICR1H.ICR1_9 9 +ICR1H.ICR1_8 8 +OCR1BL 0x0028 Output Compare Register 1 B Low +OCR1BL.OCR1B_7 7 +OCR1BL.OCR1B_6 6 +OCR1BL.OCR1B_5 5 +OCR1BL.OCR1B_4 4 +OCR1BL.OCR1B_3 3 +OCR1BL.OCR1B_2 2 +OCR1BL.OCR1B_1 1 +OCR1BL.OCR1B_0 0 +OCR1BH 0x0029 Output Compare Register 1 B High +OCR1BH.OCR1B_15 15 +OCR1BH.OCR1B_14 14 +OCR1BH.OCR1B_13 13 +OCR1BH.OCR1B_12 12 +OCR1BH.OCR1B_11 11 +OCR1BH.OCR1B_10 10 +OCR1BH.OCR1B_9 9 +OCR1BH.OCR1B_8 8 +OCR1AL 0x002A Output Compare Register 1 A Low +OCR1AL.OCR1A_7 7 +OCR1AL.OCR1A_6 6 +OCR1AL.OCR1A_5 5 +OCR1AL.OCR1A_4 4 +OCR1AL.OCR1A_3 3 +OCR1AL.OCR1A_2 2 +OCR1AL.OCR1A_1 1 +OCR1AL.OCR1A_0 0 +OCR1AH 0x002B Output Compare Register 1 A High +OCR1AH.OCR1A_15 15 +OCR1AH.OCR1A_14 14 +OCR1AH.OCR1A_13 13 +OCR1AH.OCR1A_12 12 +OCR1AH.OCR1A_11 11 +OCR1AH.OCR1A_10 10 +OCR1AH.OCR1A_9 9 +OCR1AH.OCR1A_8 8 +TCNT1L 0x002C Timer/Counter 1 Low +TCNT1L.TCNT1_7 7 +TCNT1L.TCNT1_6 6 +TCNT1L.TCNT1_5 5 +TCNT1L.TCNT1_4 4 +TCNT1L.TCNT1_3 3 +TCNT1L.TCNT1_2 2 +TCNT1L.TCNT1_1 1 +TCNT1L.TCNT1_0 0 +TCNT1H 0x002D Timer/Counter 1 High +TCNT1H.TCNT1_15 15 +TCNT1H.TCNT1_14 14 +TCNT1H.TCNT1_13 13 +TCNT1H.TCNT1_12 12 +TCNT1H.TCNT1_11 11 +TCNT1H.TCNT1_10 10 +TCNT1H.TCNT1_9 9 +TCNT1H.TCNT1_8 8 +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input Capture Edge Select +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.FOC1A 3 Force Output Compare for Channel A +TCCR1A.FOC1B 2 Force Output Compare for Channel B +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +SFIOR 0x0030 Special Function IO Register +SFIOR.ADTS2 7 ADC Auto Trigger Source 2 +SFIOR.ADTS1 6 ADC Auto Trigger Source 1 +SFIOR.ADTS0 5 ADC Auto Trigger Source 0 +SFIOR.ADHSM 4 ADC High Speed Mode +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter Register +TCNT0.TCNT0_7 7 +TCNT0.TCNT0_6 6 +TCNT0.TCNT0_5 5 +TCNT0.TCNT0_4 4 +TCNT0.TCNT0_3 3 +TCNT0.TCNT0_2 2 +TCNT0.TCNT0_1 1 +TCNT0.TCNT0_0 0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.FOC0 7 Force Output Compare +TCCR0.WGM00 6 Waveform Generation Mode 0 +TCCR0.COM01 5 Compare Match Output Mode 1 +TCCR0.COM00 4 Compare Match Output Mode 0 +TCCR0.WGM01 3 Waveform Generation Mode 1 +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.ISC2 6 Interrupt Sense Control 2 +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SM2 7 Sleep Mode Select Bit 2 +MCUCR.SE 6 Sleep Enable +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +TWCR 0x0036 TWI Control Register +TWCR.TWINT 7 TWI Interrupt Flag +TWCR.TWEA 6 TWI Enable Acknowledge Bit +TWCR.TWSTA 5 TWI START Condition Bit +TWCR.TWSTO 4 TWI STOP Condition Bit +TWCR.TWWC 3 TWI Write Collision Flag +TWCR.TWEN 2 TWI Enable Bit +TWCR.TWIE 0 TWI Interrupt Enable +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.SPMIE 7 SPM Interrupt Enable +SPMCR.RWWSB 6 Read-While-Write Section Busy +SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +TIFR.TOV1 2 Timer/Counter1, Overflow Flag +TIFR.OCF0 1 Output Compare Flag 0 +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GIFR.INTF2 5 External Interrupt Flag 2 +GICR 0x003B General Interrupt Control Register +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.INT2 5 External Interrupt Request 2 Enable +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +OCR0 0x003C Output Compare Register +OCR0.OCR0_7 7 +OCR0.OCR0_6 6 +OCR0.OCR0_5 5 +OCR0.OCR0_4 4 +OCR0.OCR0_3 3 +OCR0.OCR0_2 2 +OCR0.OCR0_1 1 +OCR0.OCR0_0 0 +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; TWBR 0x0020 TWI Bit Rate Register +; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +; TWSR 0x0021 TWI Status Register +; TWSR.TWS7 7 TWI Status +; TWSR.TWS6 6 TWI Status +; TWSR.TWS5 5 TWI Status +; TWSR.TWS4 4 TWI Status +; TWSR.TWS3 3 TWI Status +; TWSR.TWPS1 1 TWI Prescaler Bit 1 +; TWSR.TWPS0 0 TWI Prescaler Bit 0 +; TWAR 0x0022 TWI (Slave) Address Register +; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +; TWDR 0x0023 TWI Data Register +; TWDR.TWD7 7 TWI Data Register bit 7 +; TWDR.TWD6 6 TWI Data Register bit 6 +; TWDR.TWD5 5 TWI Data Register bit 5 +; TWDR.TWD4 4 TWI Data Register bit 4 +; TWDR.TWD3 3 TWI Data Register bit 3 +; TWDR.TWD2 2 TWI Data Register bit 2 +; TWDR.TWD1 1 TWI Data Register bit 1 +; TWDR.TWD0 0 TWI Data Register bit 0 +; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion Result 7 +; ADCL.ADC6 6 ADC Conversion Result 6 +; ADCL.ADC5 5 ADC Conversion Result 5 +; ADCL.ADC4 4 ADC Conversion Result 4 +; ADCL.ADC3 3 ADC Conversion Result 3 +; ADCL.ADC2 2 ADC Conversion Result 2 +; ADCL.ADC1 1 ADC Conversion Result 1 +; ADCL.ADC0 0 ADC Conversion Result 0 +; ADCH 0x0025 ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 ADC Conversion Result 9 +; ADCH.ADC8 8 ADC Conversion Result 8 +; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion Result 1 +; ; ADCL.ADC0 6 ADC Conversion Result 0 +; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion Result 9 +; ; ADCH.ADC8 14 ADC Conversion Result 8 +; ; ADCH.ADC7 13 ADC Conversion Result 7 +; ; ADCH.ADC6 12 ADC Conversion Result 6 +; ; ADCH.ADC5 11 ADC Conversion Result 5 +; ; ADCH.ADC4 10 ADC Conversion Result 4 +; ; ADCH.ADC3 9 ADC Conversion Result 3 +; ; ADCH.ADC2 8 ADC Conversion Result 2 +; ADCSRA 0x0026 ADC Control and Status Register A +; ADCSRA.ADEN 7 ADC Enable +; ADCSRA.ADSC 6 ADC Start Conversion +; ADCSRA.ADATE 5 ADC Auto Trigger Enable +; ADCSRA.ADIF 4 ADC Interrupt Flag +; ADCSRA.ADIE 3 ADC Interrupt Enable +; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRRL 0x0029 USART Baud Rate Register Low +; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +; UCSRB 0x002A USART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.UCSZ2 2 Character Size +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B USART Control and Status Register A +; UCSRA.RXC 7 USART Receive Complete +; UCSRA.TXC 6 USART Transmit Complete +; UCSRA.UDRE 5 USART Data Register Empty +; UCSRA.FE 4 Frame Error +; UCSRA.DOR 3 Data OverRun +; UCSRA.PE 2 Parity Error +; UCSRA.U2X 1 Double the USART Transmission Speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC7 7 +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC7 7 Port C Data Direction Register bit 7 +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC7 7 Port C Data Register bit 7 +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEDR.EEDR7 7 EEPROM Data 7 +; EEDR.EEDR6 6 EEPROM Data 6 +; EEDR.EEDR5 5 EEPROM Data 5 +; EEDR.EEDR4 4 EEPROM Data 4 +; EEDR.EEDR3 3 EEPROM Data 3 +; EEDR.EEDR2 2 EEPROM Data 2 +; EEDR.EEDR1 1 EEPROM Data 1 +; EEDR.EEDR0 0 EEPROM Data 0 +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR8 8 EEPROM Addres 8 +; UCSRC 0x0040 USART Control and Status Register (page 159) +; UCSRC.URSEL 7 Register Select +; UCSRC.UMSEL 6 USART Mode Select +; UCSRC.UPM1 5 Parity Mode 1 +; UCSRC.UPM0 4 Parity Mode 0 +; UCSRC.USBS 3 Stop Bit Select +; UCSRC.UCSZ1 2 Character Size 1 +; UCSRC.UCSZ0 1 Character Size 0 +; UCSRC.UCPOL 0 Clock Polarity +; ; UBRRH 0x0040 USART Baud Rate Register High (page 159) +; ; UBRRH.URSEL 15 Register Select +; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register 2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register 2 Update Busy +; OCR2 0x0043 Output Compare Register +; OCR2.OCR2_7 7 +; OCR2.OCR2_6 6 +; OCR2.OCR2_5 5 +; OCR2.OCR2_4 4 +; OCR2.OCR2_3 3 +; OCR2.OCR2_2 2 +; OCR2.OCR2_1 1 +; OCR2.OCR2_0 0 +; TCNT2 0x0044 Timer/Counter Register +; TCNT2.TCNT2_7 7 +; TCNT2.TCNT2_6 6 +; TCNT2.TCNT2_5 5 +; TCNT2.TCNT2_4 4 +; TCNT2.TCNT2_3 3 +; TCNT2.TCNT2_2 2 +; TCNT2.TCNT2_1 1 +; TCNT2.TCNT2_0 0 +; TCCR2 0x0045 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Compare Match Output Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Waveform Generation Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; ICR1L 0x0046 Input Capture Register 1 Low +; ICR1L.ICR1_7 7 +; ICR1L.ICR1_6 6 +; ICR1L.ICR1_5 5 +; ICR1L.ICR1_4 4 +; ICR1L.ICR1_3 3 +; ICR1L.ICR1_2 2 +; ICR1L.ICR1_1 1 +; ICR1L.ICR1_0 0 +; ICR1H 0x0047 Input Capture Register 1 High +; ICR1H.ICR1_15 15 +; ICR1H.ICR1_14 14 +; ICR1H.ICR1_13 13 +; ICR1H.ICR1_12 12 +; ICR1H.ICR1_11 11 +; ICR1H.ICR1_10 10 +; ICR1H.ICR1_9 9 +; ICR1H.ICR1_8 8 +; OCR1BL 0x0048 Output Compare Register 1 B Low +; OCR1BL.OCR1B_7 7 +; OCR1BL.OCR1B_6 6 +; OCR1BL.OCR1B_5 5 +; OCR1BL.OCR1B_4 4 +; OCR1BL.OCR1B_3 3 +; OCR1BL.OCR1B_2 2 +; OCR1BL.OCR1B_1 1 +; OCR1BL.OCR1B_0 0 +; OCR1BH 0x0049 Output Compare Register 1 B High +; OCR1BH.OCR1B_15 15 +; OCR1BH.OCR1B_14 14 +; OCR1BH.OCR1B_13 13 +; OCR1BH.OCR1B_12 12 +; OCR1BH.OCR1B_11 11 +; OCR1BH.OCR1B_10 10 +; OCR1BH.OCR1B_9 9 +; OCR1BH.OCR1B_8 8 +; OCR1AL 0x004A Output Compare Register 1 A Low +; OCR1AL.OCR1A_7 7 +; OCR1AL.OCR1A_6 6 +; OCR1AL.OCR1A_5 5 +; OCR1AL.OCR1A_4 4 +; OCR1AL.OCR1A_3 3 +; OCR1AL.OCR1A_2 2 +; OCR1AL.OCR1A_1 1 +; OCR1AL.OCR1A_0 0 +; OCR1AH 0x004B Output Compare Register 1 A High +; OCR1AH.OCR1A_15 15 +; OCR1AH.OCR1A_14 14 +; OCR1AH.OCR1A_13 13 +; OCR1AH.OCR1A_12 12 +; OCR1AH.OCR1A_11 11 +; OCR1AH.OCR1A_10 10 +; OCR1AH.OCR1A_9 9 +; OCR1AH.OCR1A_8 8 +; TCNT1L 0x004C Timer/Counter 1 Low +; TCNT1L.TCNT1_7 7 +; TCNT1L.TCNT1_6 6 +; TCNT1L.TCNT1_5 5 +; TCNT1L.TCNT1_4 4 +; TCNT1L.TCNT1_3 3 +; TCNT1L.TCNT1_2 2 +; TCNT1L.TCNT1_1 1 +; TCNT1L.TCNT1_0 0 +; TCNT1H 0x004D Timer/Counter 1 High +; TCNT1H.TCNT1_15 15 +; TCNT1H.TCNT1_14 14 +; TCNT1H.TCNT1_13 13 +; TCNT1H.TCNT1_12 12 +; TCNT1H.TCNT1_11 11 +; TCNT1H.TCNT1_10 10 +; TCNT1H.TCNT1_9 9 +; TCNT1H.TCNT1_8 8 +; TCCR1B 0x004E Timer/Counter1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input Capture Edge Select +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +; TCCR1A.FOC1A 3 Force Output Compare for Channel A +; TCCR1A.FOC1B 2 Force Output Compare for Channel B +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; SFIOR 0x0050 Special Function IO Register +; SFIOR.ADTS2 7 ADC Auto Trigger Source 2 +; SFIOR.ADTS1 6 ADC Auto Trigger Source 1 +; SFIOR.ADTS0 5 ADC Auto Trigger Source 0 +; SFIOR.ADHSM 4 ADC High Speed Mode +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OSCCAL 0x0051 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter Register +; TCNT0.TCNT0_7 7 +; TCNT0.TCNT0_6 6 +; TCNT0.TCNT0_5 5 +; TCNT0.TCNT0_4 4 +; TCNT0.TCNT0_3 3 +; TCNT0.TCNT0_2 2 +; TCNT0.TCNT0_1 1 +; TCNT0.TCNT0_0 0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.FOC0 7 Force Output Compare +; TCCR0.WGM00 6 Waveform Generation Mode 0 +; TCCR0.COM01 5 Compare Match Output Mode 1 +; TCCR0.COM00 4 Compare Match Output Mode 0 +; TCCR0.WGM01 3 Waveform Generation Mode 1 +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.ISC2 6 Interrupt Sense Control 2 +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SM2 7 Sleep Mode Select Bit 2 +; MCUCR.SE 6 Sleep Enable +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; TWCR 0x0056 TWI Control Register +; TWCR.TWINT 7 TWI Interrupt Flag +; TWCR.TWEA 6 TWI Enable Acknowledge Bit +; TWCR.TWSTA 5 TWI START Condition Bit +; TWCR.TWSTO 4 TWI STOP Condition Bit +; TWCR.TWWC 3 TWI Write Collision Flag +; TWCR.TWEN 2 TWI Enable Bit +; TWCR.TWIE 0 TWI Interrupt Enable +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +; TIFR.TOV1 2 Timer/Counter1, Overflow Flag +; TIFR.OCF0 1 Output Compare Flag 0 +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.OCIE0 1 Timer/Counter0 Output Compare Match Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GIFR.INTF2 5 External Interrupt Flag 2 +; GICR 0x005B General Interrupt Control Register +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.INT2 5 External Interrupt Request 2 Enable +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; OCR0 0x005C Output Compare Register +; OCR0.OCR0_7 7 +; OCR0.OCR0_6 6 +; OCR0.OCR0_5 5 +; OCR0.OCR0_4 4 +; OCR0.OCR0_3 3 +; OCR0.OCR0_2 2 +; OCR0.OCR0_1 1 +; OCR0.OCR0_0 0 +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATmega8_L +SUBARCH=4 +; doc2486.pdf +; + +RAM=1024 +ROM=8192 +EEPROM=512 + +; MEMORY MAP +area DATA FSR 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x0460 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER2_COMP 0x0003 Timer/Counter2 Compare Match +entry TIMER2_OVF 0x0004 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0005 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0006 Timer/Counter1 Compare Match A +entry TIMER1_COMPB 0x0007 Timer/Counter1 Compare Match B +entry TIMER1_OVF 0x0008 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0009 Timer/Counter0 Overflow +entry SPI_STC 0x000A Serial Transfer Complete +entry USART_RXC 0x000B USART, Rx Complete +entry USART_UDRE 0x000C USART Data Register Empty +entry USART_TXC 0x000D USART, Tx Complete +entry ADC_ 0x000E ADC Conversion Complete +entry EE_RDY 0x000F EEPROM Ready +entry ANA_COMP 0x0010 Analog Comparator +entry TWI_ 0x0011 Two-wire Serial Interface +entry SPM_RDY 0x0012 Store Program Memory Ready + + +; INPUT/OUTPUT PORTS +TWBR 0x0000 Two-wire Serial Interface Bit Rate Register +TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +TWSR 0x0001 TWI Status Register +TWSR.TWS7 7 TWI Status 7 +TWSR.TWS6 6 TWI Status 6 +TWSR.TWS5 5 TWI Status 5 +TWSR.TWS4 4 TWI Status 4 +TWSR.TWS3 3 TWI Status 3 +TWSR.TWS1 1 TWI Status 1 +TWSR.TWS0 0 TWI Status 0 +TWAR 0x0002 TWI (Slave) Address Register +TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +TWDR 0x0003 TWI Data Register +TWDR.TWD7 7 TWI Data Register bit 7 +TWDR.TWD6 6 TWI Data Register bit 6 +TWDR.TWD5 5 TWI Data Register bit 5 +TWDR.TWD4 4 TWI Data Register bit 4 +TWDR.TWD3 3 TWI Data Register bit 3 +TWDR.TWD2 2 TWI Data Register bit 2 +TWDR.TWD1 1 TWI Data Register bit 1 +TWDR.TWD0 0 TWI Data Register bit 0 +ADCL 0x0004 ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion Result 7 +ADCL.ADC6 6 ADC Conversion Result 6 +ADCL.ADC5 5 ADC Conversion Result 5 +ADCL.ADC4 4 ADC Conversion Result 4 +ADCL.ADC3 3 ADC Conversion Result 3 +ADCL.ADC2 2 ADC Conversion Result 2 +ADCL.ADC1 1 ADC Conversion Result 1 +ADCL.ADC0 0 ADC Conversion Result 0 +ADCH 0x0005 ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 ADC Conversion Result 9 +ADCH.ADC8 8 ADC Conversion Result 8 +; ADCL 0x0004 ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion Result 1 +; ADCL.ADC0 6 ADC Conversion Result 0 +; ADCH 0x0005 ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion Result 9 +; ADCH.ADC8 14 ADC Conversion Result 8 +; ADCH.ADC7 13 ADC Conversion Result 7 +; ADCH.ADC6 12 ADC Conversion Result 6 +; ADCH.ADC5 11 ADC Conversion Result 5 +; ADCH.ADC4 10 ADC Conversion Result 4 +; ADCH.ADC3 9 ADC Conversion Result 3 +; ADCH.ADC2 8 ADC Conversion Result 2 +ADCSRA 0x0006 ADC Control and Status Register A +ADCSRA.ADEN 7 ADC Enable +ADCSRA.ADSC 6 ADC Start Conversion +ADCSRA.ADFR 5 ADC Free Running Select +ADCSRA.ADIF 4 ADC Interrupt Flag +ADCSRA.ADIE 3 ADC Interrupt Enable +ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX3 3 Analog Channel Selection Bit 3 +ADMUX.MUX2 2 Analog Channel Selection Bit 2 +ADMUX.MUX1 1 Analog Channel Selection Bit 1 +ADMUX.MUX0 0 Analog Channel Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register Low +UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +UCSRB 0x000A USART Control and Status Register B +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit 8 +UCSRA 0x000B USART Control and Status Register A +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.PE 2 Parity Error +UCSRA.U2X 1 Double the USART transmission speed +UCSRA.MPCM 0 Multi-processor Communication Mode +UDR 0x000C USART I/O Data Register +SPCR 0x000D SPI Control Register +SPCR.SPIE 7 SPI Interrupt Enable +SPCR.SPE 6 SPI Enable +SPCR.DORD 5 Data Order +SPCR.MSTR 4 Master/Slave Select +SPCR.CPOL 3 Clock Polarity +SPCR.CPHA 2 Clock Phase +SPCR.SPR1 1 SPI Clock Rate Select 1 +SPCR.SPR0 0 SPI Clock Rate Select 0 +SPSR 0x000E SPI Status Register +SPSR.SPIF 7 SPI Interrupt Flag +SPSR.WCOL 6 Write COLlision flag +SPSR.SPI2X 0 Double SPI Speed Bit +SPDR 0x000F SPI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +PINC 0x0013 Port C Input Pins Address +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +DDRC 0x0014 Port C Data Direction Register +DDRC.DDC6 6 Port C Data Direction Register bit 6 +DDRC.DDC5 5 Port C Data Direction Register bit 5 +DDRC.DDC4 4 Port C Data Direction Register bit 4 +DDRC.DDC3 3 Port C Data Direction Register bit 3 +DDRC.DDC2 2 Port C Data Direction Register bit 2 +DDRC.DDC1 1 Port C Data Direction Register bit 1 +DDRC.DDC0 0 Port C Data Direction Register bit 0 +PORTC 0x0015 Port C Data Register +PORTC.PORTC6 6 Port C Data Register bit 6 +PORTC.PORTC5 5 Port C Data Register bit 5 +PORTC.PORTC4 4 Port C Data Register bit 4 +PORTC.PORTC3 3 Port C Data Register bit 3 +PORTC.PORTC2 2 Port C Data Register bit 2 +PORTC.PORTC1 1 Port C Data Register bit 1 +PORTC.PORTC0 0 Port C Data Register bit 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEARL 0x001E EEPROM Address Register Low +EEARL.EEAR7 7 EEPROM Addres 7 +EEARL.EEAR6 6 EEPROM Addres 6 +EEARL.EEAR5 5 EEPROM Addres 5 +EEARL.EEAR4 4 EEPROM Addres 4 +EEARL.EEAR3 3 EEPROM Addres 3 +EEARL.EEAR2 2 EEPROM Addres 2 +EEARL.EEAR1 1 EEPROM Addres 1 +EEARL.EEAR0 0 EEPROM Addres 0 +EEARH 0x001F EEPROM Address Register High +EEARH.EEAR8 8 EEPROM Addres 8 +UCSRC 0x0020 USART Control and Status Register (page 148) +UCSRC.URSEL 7 Register Select +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +; UBRRH 0x0020 USART Baud Rate Register High (page 148) +; UBRRH.URSEL 15 Register Select +; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +ASSR 0x0022 Asynchronous Status Register +ASSR.AS2 3 Asynchronous Timer/Counter2 +ASSR.TCN2UB 2 Timer/Counter2 Update Busy +ASSR.OCR2UB 1 Output Compare Register2 Update Busy +ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +OCR2 0x0023 Output Compare Register +OCR2.OCR2_7 7 +OCR2.OCR2_6 6 +OCR2.OCR2_5 5 +OCR2.OCR2_4 4 +OCR2.OCR2_3 3 +OCR2.OCR2_2 2 +OCR2.OCR2_1 1 +OCR2.OCR2_0 0 +TCNT2 0x0024 Timer/Counter Register +TCNT2.TCNT2_7 7 +TCNT2.TCNT2_6 6 +TCNT2.TCNT2_5 5 +TCNT2.TCNT2_4 4 +TCNT2.TCNT2_3 3 +TCNT2.TCNT2_2 2 +TCNT2.TCNT2_1 1 +TCNT2.TCNT2_0 0 +TCCR2 0x0025 Timer/Counter Control Register +TCCR2.FOC2 7 Force Output Compare +TCCR2.WGM20 6 Waveform Generation Mode 0 +TCCR2.COM21 5 Compare Match Output Mode 1 +TCCR2.COM20 4 Compare Match Output Mode 0 +TCCR2.WGM21 3 Waveform Generation Mode 1 +TCCR2.CS22 2 Clock Select 2 +TCCR2.CS21 1 Clock Select 1 +TCCR2.CS20 0 Clock Select 0 +ICR1L 0x0026 Input Capture Register 1 Low +ICR1L.ICR1_7 7 +ICR1L.ICR1_6 6 +ICR1L.ICR1_5 5 +ICR1L.ICR1_4 4 +ICR1L.ICR1_3 3 +ICR1L.ICR1_2 2 +ICR1L.ICR1_1 1 +ICR1L.ICR1_0 0 +ICR1H 0x0027 Input Capture Register 1 High +ICR1H.ICR1_15 15 +ICR1H.ICR1_14 14 +ICR1H.ICR1_13 13 +ICR1H.ICR1_12 12 +ICR1H.ICR1_11 11 +ICR1H.ICR1_10 10 +ICR1H.ICR1_9 9 +ICR1H.ICR1_8 8 +OCR1BL 0x0028 Output Compare Register 1 B Low +OCR1BL.OCR1B_7 7 +OCR1BL.OCR1B_6 6 +OCR1BL.OCR1B_5 5 +OCR1BL.OCR1B_4 4 +OCR1BL.OCR1B_3 3 +OCR1BL.OCR1B_2 2 +OCR1BL.OCR1B_1 1 +OCR1BL.OCR1B_0 0 +OCR1BH 0x0029 Output Compare Register 1 B High +OCR1BH.OCR1B_15 15 +OCR1BH.OCR1B_14 14 +OCR1BH.OCR1B_13 13 +OCR1BH.OCR1B_12 12 +OCR1BH.OCR1B_11 11 +OCR1BH.OCR1B_10 10 +OCR1BH.OCR1B_9 9 +OCR1BH.OCR1B_8 8 +OCR1AL 0x002A Output Compare Register 1 A Low +OCR1AL.OCR1A_7 7 +OCR1AL.OCR1A_6 6 +OCR1AL.OCR1A_5 5 +OCR1AL.OCR1A_4 4 +OCR1AL.OCR1A_3 3 +OCR1AL.OCR1A_2 2 +OCR1AL.OCR1A_1 1 +OCR1AL.OCR1A_0 0 +OCR1AH 0x002B Output Compare Register 1 A High +OCR1AH.OCR1A_15 15 +OCR1AH.OCR1A_14 14 +OCR1AH.OCR1A_13 13 +OCR1AH.OCR1A_12 12 +OCR1AH.OCR1A_11 11 +OCR1AH.OCR1A_10 10 +OCR1AH.OCR1A_9 9 +OCR1AH.OCR1A_8 8 +TCNT1L 0x002C Timer/Counter 1 Low +TCNT1L.TCNT1_7 7 +TCNT1L.TCNT1_6 6 +TCNT1L.TCNT1_5 5 +TCNT1L.TCNT1_4 4 +TCNT1L.TCNT1_3 3 +TCNT1L.TCNT1_2 2 +TCNT1L.TCNT1_1 1 +TCNT1L.TCNT1_0 0 +TCNT1H 0x002D Timer/Counter 1 High +TCNT1H.TCNT1_15 15 +TCNT1H.TCNT1_14 14 +TCNT1H.TCNT1_13 13 +TCNT1H.TCNT1_12 12 +TCNT1H.TCNT1_11 11 +TCNT1H.TCNT1_10 10 +TCNT1H.TCNT1_9 9 +TCNT1H.TCNT1_8 8 +TCCR1B 0x002E Timer/Counter 1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input Capture Edge Select +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter 1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 +TCCR1A.FOC1A 3 Force Output Compare for channel A +TCCR1A.FOC1B 2 Force Output Compare for channel B +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +SFIOR 0x0030 Special Function IO Register +SFIOR.ADHSM 4 ADC High Speed Mode +SFIOR.ACME 3 Analog Comparator Multiplexer Enable +SFIOR.PUD 2 Pull-up Disable +SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter Register +TCNT0.TCNT0_7 7 +TCNT0.TCNT0_6 6 +TCNT0.TCNT0_5 5 +TCNT0.TCNT0_4 4 +TCNT0.TCNT0_3 3 +TCNT0.TCNT0_2 2 +TCNT0.TCNT0_1 1 +TCNT0.TCNT0_0 0 +TCCR0 0x0033 Timer/Counter Control Register +TCCR0.CS02 2 Clock Select 2 +TCCR0.CS01 1 Clock Select 1 +TCCR0.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 7 Sleep Enable +MCUCR.SM2 6 Sleep Mode Select Bit 2 +MCUCR.SM1 5 Sleep Mode Select Bit 1 +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +TWCR 0x0036 TWI Control Register +TWCR.TWINT 7 TWI Interrupt Flag +TWCR.TWEA 6 TWI Enable Acknowledge Bit +TWCR.TWSTA 5 TWI START Condition Bit +TWCR.TWSTO 4 TWI STOP Condition Bit +TWCR.TWWC 3 TWI Write Collision Flag +TWCR.TWEN 2 TWI Enable Bit +TWCR.TWIE 0 TWI Interrupt Enable +SPMCR 0x0037 Store Program Memory Control Register +SPMCR.SPMIE 7 SPM Interrupt Enable +SPMCR.RWWSB 6 Read-While-Write Section Busy +SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +SPMCR.BLBSET 3 Boot Lock Bit Set +SPMCR.PGWRT 2 Page Write +SPMCR.PGERS 1 Page Erase +SPMCR.SPMEN 0 Store Program Memory Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF2 7 Output Compare Flag 2 +TIFR.TOV2 6 Timer/Counter2 Overflow Flag +TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +TIFR.TOV1 2 Timer/Counter1, Overflow Flag +TIFR.TOV0 0 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF1 7 External Interrupt Flag 1 +GIFR.INTF0 6 External Interrupt Flag 0 +GICR 0x003B General Interrupt Control Register +GICR.INT1 7 External Interrupt Request 1 Enable +GICR.INT0 6 External Interrupt Request 0 Enable +GICR.IVSEL 1 Interrupt Vector Select +GICR.IVCE 0 Interrupt Vector Change Enable +RESERVED003C 0x003C RESERVED +SPL 0x003D Stack Pointer Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPH 0x003E Stack Pointer High +SPH.SP10 10 +SPH.SP9 9 +SPH.SP8 8 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; TWBR 0x0020 Two-wire Serial Interface Bit Rate Register +; TWBR.TWBR7 7 TWI Bit Rate Register bit 7 +; TWBR.TWBR6 6 TWI Bit Rate Register bit 6 +; TWBR.TWBR5 5 TWI Bit Rate Register bit 5 +; TWBR.TWBR4 4 TWI Bit Rate Register bit 4 +; TWBR.TWBR3 3 TWI Bit Rate Register bit 3 +; TWBR.TWBR2 2 TWI Bit Rate Register bit 2 +; TWBR.TWBR1 1 TWI Bit Rate Register bit 1 +; TWBR.TWBR0 0 TWI Bit Rate Register bit 0 +; TWSR 0x0021 TWI Status Register +; TWSR.TWS7 7 TWI Status 7 +; TWSR.TWS6 6 TWI Status 6 +; TWSR.TWS5 5 TWI Status 5 +; TWSR.TWS4 4 TWI Status 4 +; TWSR.TWS3 3 TWI Status 3 +; TWSR.TWS1 1 TWI Status 1 +; TWSR.TWS0 0 TWI Status 0 +; TWAR 0x0022 TWI (Slave) Address Register +; TWAR.TWA6 7 TWI (Slave) Address Register bit 6 +; TWAR.TWA5 6 TWI (Slave) Address Register bit 5 +; TWAR.TWA4 5 TWI (Slave) Address Register bit 4 +; TWAR.TWA3 4 TWI (Slave) Address Register bit 3 +; TWAR.TWA2 3 TWI (Slave) Address Register bit 2 +; TWAR.TWA1 2 TWI (Slave) Address Register bit 1 +; TWAR.TWA0 1 TWI (Slave) Address Register bit 0 +; TWAR.TWGCE 0 TWI General Call Recognition Enable Bit +; TWDR 0x0023 TWI Data Register +; TWDR.TWD7 7 TWI Data Register bit 7 +; TWDR.TWD6 6 TWI Data Register bit 6 +; TWDR.TWD5 5 TWI Data Register bit 5 +; TWDR.TWD4 4 TWI Data Register bit 4 +; TWDR.TWD3 3 TWI Data Register bit 3 +; TWDR.TWD2 2 TWI Data Register bit 2 +; TWDR.TWD1 1 TWI Data Register bit 1 +; TWDR.TWD0 0 TWI Data Register bit 0 +; ADCL 0x0024 ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion Result 7 +; ADCL.ADC6 6 ADC Conversion Result 6 +; ADCL.ADC5 5 ADC Conversion Result 5 +; ADCL.ADC4 4 ADC Conversion Result 4 +; ADCL.ADC3 3 ADC Conversion Result 3 +; ADCL.ADC2 2 ADC Conversion Result 2 +; ADCL.ADC1 1 ADC Conversion Result 1 +; ADCL.ADC0 0 ADC Conversion Result 0 +; ADCH 0x0025 ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 ADC Conversion Result 9 +; ADCH.ADC8 8 ADC Conversion Result 8 +; ; ADCL 0x0024 ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion Result 1 +; ; ADCL.ADC0 6 ADC Conversion Result 0 +; ; ADCH 0x0025 ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion Result 9 +; ; ADCH.ADC8 14 ADC Conversion Result 8 +; ; ADCH.ADC7 13 ADC Conversion Result 7 +; ; ADCH.ADC6 12 ADC Conversion Result 6 +; ; ADCH.ADC5 11 ADC Conversion Result 5 +; ; ADCH.ADC4 10 ADC Conversion Result 4 +; ; ADCH.ADC3 9 ADC Conversion Result 3 +; ; ADCH.ADC2 8 ADC Conversion Result 2 +; ADCSRA 0x0026 ADC Control and Status Register A +; ADCSRA.ADEN 7 ADC Enable +; ADCSRA.ADSC 6 ADC Start Conversion +; ADCSRA.ADFR 5 ADC Free Running Select +; ADCSRA.ADIF 4 ADC Interrupt Flag +; ADCSRA.ADIE 3 ADC Interrupt Enable +; ADCSRA.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSRA.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSRA.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX3 3 Analog Channel Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACIC 2 Analog Comparator Input Capture Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; UBRRL 0x0029 USART Baud Rate Register Low +; UBRRL.UBRR7 7 USART Baud Rate Register bit 7 +; UBRRL.UBRR6 6 USART Baud Rate Register bit 6 +; UBRRL.UBRR5 5 USART Baud Rate Register bit 5 +; UBRRL.UBRR4 4 USART Baud Rate Register bit 4 +; UBRRL.UBRR3 3 USART Baud Rate Register bit 3 +; UBRRL.UBRR2 2 USART Baud Rate Register bit 2 +; UBRRL.UBRR1 1 USART Baud Rate Register bit 1 +; UBRRL.UBRR0 0 USART Baud Rate Register bit 0 +; UCSRB 0x002A USART Control and Status Register B +; UCSRB.RXCIE 7 RX Complete Interrupt Enable +; UCSRB.TXCIE 6 TX Complete Interrupt Enable +; UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +; UCSRB.RXEN 4 Receiver Enable +; UCSRB.TXEN 3 Transmitter Enable +; UCSRB.UCSZ2 2 Character Size +; UCSRB.RXB8 1 Receive Data Bit 8 +; UCSRB.TXB8 0 Transmit Data Bit 8 +; UCSRA 0x002B USART Control and Status Register A +; UCSRA.RXC 7 USART Receive Complete +; UCSRA.TXC 6 USART Transmit Complete +; UCSRA.UDRE 5 USART Data Register Empty +; UCSRA.FE 4 Frame Error +; UCSRA.DOR 3 Data OverRun +; UCSRA.PE 2 Parity Error +; UCSRA.U2X 1 Double the USART transmission speed +; UCSRA.MPCM 0 Multi-processor Communication Mode +; UDR 0x002C USART I/O Data Register +; SPCR 0x002D SPI Control Register +; SPCR.SPIE 7 SPI Interrupt Enable +; SPCR.SPE 6 SPI Enable +; SPCR.DORD 5 Data Order +; SPCR.MSTR 4 Master/Slave Select +; SPCR.CPOL 3 Clock Polarity +; SPCR.CPHA 2 Clock Phase +; SPCR.SPR1 1 SPI Clock Rate Select 1 +; SPCR.SPR0 0 SPI Clock Rate Select 0 +; SPSR 0x002E SPI Status Register +; SPSR.SPIF 7 SPI Interrupt Flag +; SPSR.WCOL 6 Write COLlision flag +; SPSR.SPI2X 0 Double SPI Speed Bit +; SPDR 0x002F SPI Data Register +; PIND 0x0030 Port D Input Pins Address +; PIND.PIND7 7 +; PIND.PIND6 6 +; PIND.PIND5 5 +; PIND.PIND4 4 +; PIND.PIND3 3 +; PIND.PIND2 2 +; PIND.PIND1 1 +; PIND.PIND0 0 +; DDRD 0x0031 Port D Data Direction Register +; DDRD.DDD7 7 Port D Data Direction Register bit 7 +; DDRD.DDD6 6 Port D Data Direction Register bit 6 +; DDRD.DDD5 5 Port D Data Direction Register bit 5 +; DDRD.DDD4 4 Port D Data Direction Register bit 4 +; DDRD.DDD3 3 Port D Data Direction Register bit 3 +; DDRD.DDD2 2 Port D Data Direction Register bit 2 +; DDRD.DDD1 1 Port D Data Direction Register bit 1 +; DDRD.DDD0 0 Port D Data Direction Register bit 0 +; PORTD 0x0032 Port D Data Register +; PORTD.PORTD7 7 Port D Data Register bit 7 +; PORTD.PORTD6 6 Port D Data Register bit 6 +; PORTD.PORTD5 5 Port D Data Register bit 5 +; PORTD.PORTD4 4 Port D Data Register bit 4 +; PORTD.PORTD3 3 Port D Data Register bit 3 +; PORTD.PORTD2 2 Port D Data Register bit 2 +; PORTD.PORTD1 1 Port D Data Register bit 1 +; PORTD.PORTD0 0 Port D Data Register bit 0 +; PINC 0x0033 Port C Input Pins Address +; PINC.PINC6 6 +; PINC.PINC5 5 +; PINC.PINC4 4 +; PINC.PINC3 3 +; PINC.PINC2 2 +; PINC.PINC1 1 +; PINC.PINC0 0 +; DDRC 0x0034 Port C Data Direction Register +; DDRC.DDC6 6 Port C Data Direction Register bit 6 +; DDRC.DDC5 5 Port C Data Direction Register bit 5 +; DDRC.DDC4 4 Port C Data Direction Register bit 4 +; DDRC.DDC3 3 Port C Data Direction Register bit 3 +; DDRC.DDC2 2 Port C Data Direction Register bit 2 +; DDRC.DDC1 1 Port C Data Direction Register bit 1 +; DDRC.DDC0 0 Port C Data Direction Register bit 0 +; PORTC 0x0035 Port C Data Register +; PORTC.PORTC6 6 Port C Data Register bit 6 +; PORTC.PORTC5 5 Port C Data Register bit 5 +; PORTC.PORTC4 4 Port C Data Register bit 4 +; PORTC.PORTC3 3 Port C Data Register bit 3 +; PORTC.PORTC2 2 Port C Data Register bit 2 +; PORTC.PORTC1 1 Port C Data Register bit 1 +; PORTC.PORTC0 0 Port C Data Register bit 0 +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; RESERVED0039 0x0039 RESERVED +; RESERVED003A 0x003A RESERVED +; RESERVED003B 0x003B RESERVED +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEDR.EEDR7 7 EEPROM Data 7 +; EEDR.EEDR6 6 EEPROM Data 6 +; EEDR.EEDR5 5 EEPROM Data 5 +; EEDR.EEDR4 4 EEPROM Data 4 +; EEDR.EEDR3 3 EEPROM Data 3 +; EEDR.EEDR2 2 EEPROM Data 2 +; EEDR.EEDR1 1 EEPROM Data 1 +; EEDR.EEDR0 0 EEPROM Data 0 +; EEARL 0x003E EEPROM Address Register Low +; EEARL.EEAR7 7 EEPROM Addres 7 +; EEARL.EEAR6 6 EEPROM Addres 6 +; EEARL.EEAR5 5 EEPROM Addres 5 +; EEARL.EEAR4 4 EEPROM Addres 4 +; EEARL.EEAR3 3 EEPROM Addres 3 +; EEARL.EEAR2 2 EEPROM Addres 2 +; EEARL.EEAR1 1 EEPROM Addres 1 +; EEARL.EEAR0 0 EEPROM Addres 0 +; EEARH 0x003F EEPROM Address Register High +; EEARH.EEAR8 8 EEPROM Addres 8 +; UCSRC 0x0040 USART Control and Status Register (page 148) +; UCSRC.URSEL 7 Register Select +; UCSRC.UMSEL 6 USART Mode Select +; UCSRC.UPM1 5 Parity Mode 1 +; UCSRC.UPM0 4 Parity Mode 0 +; UCSRC.USBS 3 Stop Bit Select +; UCSRC.UCSZ1 2 Character Size 1 +; UCSRC.UCSZ0 1 Character Size 0 +; UCSRC.UCPOL 0 Clock Polarity +; ; UBRRH 0x0040 USART Baud Rate Register High (page 148) +; ; UBRRH.URSEL 15 Register Select +; ; UBRRH.UBRR11 11 USART Baud Rate Register bit 11 +; ; UBRRH.UBRR10 10 USART Baud Rate Register bit 10 +; ; UBRRH.UBRR9 9 USART Baud Rate Register bit 9 +; ; UBRRH.UBRR8 8 USART Baud Rate Register bit 8 +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; ASSR 0x0042 Asynchronous Status Register +; ASSR.AS2 3 Asynchronous Timer/Counter2 +; ASSR.TCN2UB 2 Timer/Counter2 Update Busy +; ASSR.OCR2UB 1 Output Compare Register2 Update Busy +; ASSR.TCR2UB 0 Timer/Counter Control Register2 Update Busy +; OCR2 0x0043 Output Compare Register +; OCR2.OCR2_7 7 +; OCR2.OCR2_6 6 +; OCR2.OCR2_5 5 +; OCR2.OCR2_4 4 +; OCR2.OCR2_3 3 +; OCR2.OCR2_2 2 +; OCR2.OCR2_1 1 +; OCR2.OCR2_0 0 +; TCNT2 0x0044 Timer/Counter Register +; TCNT2.TCNT2_7 7 +; TCNT2.TCNT2_6 6 +; TCNT2.TCNT2_5 5 +; TCNT2.TCNT2_4 4 +; TCNT2.TCNT2_3 3 +; TCNT2.TCNT2_2 2 +; TCNT2.TCNT2_1 1 +; TCNT2.TCNT2_0 0 +; TCCR2 0x0045 Timer/Counter Control Register +; TCCR2.FOC2 7 Force Output Compare +; TCCR2.WGM20 6 Waveform Generation Mode 0 +; TCCR2.COM21 5 Compare Match Output Mode 1 +; TCCR2.COM20 4 Compare Match Output Mode 0 +; TCCR2.WGM21 3 Waveform Generation Mode 1 +; TCCR2.CS22 2 Clock Select 2 +; TCCR2.CS21 1 Clock Select 1 +; TCCR2.CS20 0 Clock Select 0 +; ICR1L 0x0046 Input Capture Register 1 Low +; ICR1L.ICR1_7 7 +; ICR1L.ICR1_6 6 +; ICR1L.ICR1_5 5 +; ICR1L.ICR1_4 4 +; ICR1L.ICR1_3 3 +; ICR1L.ICR1_2 2 +; ICR1L.ICR1_1 1 +; ICR1L.ICR1_0 0 +; ICR1H 0x0047 Input Capture Register 1 High +; ICR1H.ICR1_15 15 +; ICR1H.ICR1_14 14 +; ICR1H.ICR1_13 13 +; ICR1H.ICR1_12 12 +; ICR1H.ICR1_11 11 +; ICR1H.ICR1_10 10 +; ICR1H.ICR1_9 9 +; ICR1H.ICR1_8 8 +; OCR1BL 0x0048 Output Compare Register 1 B Low +; OCR1BL.OCR1B_7 7 +; OCR1BL.OCR1B_6 6 +; OCR1BL.OCR1B_5 5 +; OCR1BL.OCR1B_4 4 +; OCR1BL.OCR1B_3 3 +; OCR1BL.OCR1B_2 2 +; OCR1BL.OCR1B_1 1 +; OCR1BL.OCR1B_0 0 +; OCR1BH 0x0049 Output Compare Register 1 B High +; OCR1BH.OCR1B_15 15 +; OCR1BH.OCR1B_14 14 +; OCR1BH.OCR1B_13 13 +; OCR1BH.OCR1B_12 12 +; OCR1BH.OCR1B_11 11 +; OCR1BH.OCR1B_10 10 +; OCR1BH.OCR1B_9 9 +; OCR1BH.OCR1B_8 8 +; OCR1AL 0x004A Output Compare Register 1 A Low +; OCR1AL.OCR1A_7 7 +; OCR1AL.OCR1A_6 6 +; OCR1AL.OCR1A_5 5 +; OCR1AL.OCR1A_4 4 +; OCR1AL.OCR1A_3 3 +; OCR1AL.OCR1A_2 2 +; OCR1AL.OCR1A_1 1 +; OCR1AL.OCR1A_0 0 +; OCR1AH 0x004B Output Compare Register 1 A High +; OCR1AH.OCR1A_15 15 +; OCR1AH.OCR1A_14 14 +; OCR1AH.OCR1A_13 13 +; OCR1AH.OCR1A_12 12 +; OCR1AH.OCR1A_11 11 +; OCR1AH.OCR1A_10 10 +; OCR1AH.OCR1A_9 9 +; OCR1AH.OCR1A_8 8 +; TCNT1L 0x004C Timer/Counter 1 Low +; TCNT1L.TCNT1_7 7 +; TCNT1L.TCNT1_6 6 +; TCNT1L.TCNT1_5 5 +; TCNT1L.TCNT1_4 4 +; TCNT1L.TCNT1_3 3 +; TCNT1L.TCNT1_2 2 +; TCNT1L.TCNT1_1 1 +; TCNT1L.TCNT1_0 0 +; TCNT1H 0x004D Timer/Counter 1 High +; TCNT1H.TCNT1_15 15 +; TCNT1H.TCNT1_14 14 +; TCNT1H.TCNT1_13 13 +; TCNT1H.TCNT1_12 12 +; TCNT1H.TCNT1_11 11 +; TCNT1H.TCNT1_10 10 +; TCNT1H.TCNT1_9 9 +; TCNT1H.TCNT1_8 8 +; TCCR1B 0x004E Timer/Counter 1 Control Register B +; TCCR1B.ICNC1 7 Input Capture Noise Canceler +; TCCR1B.ICES1 6 Input Capture Edge Select +; TCCR1B.WGM13 4 Waveform Generation Mode 3 +; TCCR1B.WGM12 3 Waveform Generation Mode 2 +; TCCR1B.CS12 2 Clock Select 2 +; TCCR1B.CS11 1 Clock Select 1 +; TCCR1B.CS10 0 Clock Select 0 +; TCCR1A 0x004F Timer/Counter 1 Control Register A +; TCCR1A.COM1A1 7 Compare Output Mode for channel A 1 +; TCCR1A.COM1A0 6 Compare Output Mode for channel A 0 +; TCCR1A.COM1B1 5 Compare Output Mode for channel B 1 +; TCCR1A.COM1B0 4 Compare Output Mode for channel B 0 +; TCCR1A.FOC1A 3 Force Output Compare for channel A +; TCCR1A.FOC1B 2 Force Output Compare for channel B +; TCCR1A.WGM11 1 Waveform Generation Mode 1 +; TCCR1A.WGM10 0 Waveform Generation Mode 0 +; SFIOR 0x0050 Special Function IO Register +; SFIOR.ADHSM 4 ADC High Speed Mode +; SFIOR.ACME 3 Analog Comparator Multiplexer Enable +; SFIOR.PUD 2 Pull-up Disable +; SFIOR.PSR2 1 Prescaler Reset Timer/Counter2 +; SFIOR.PSR10 0 Prescaler Reset Timer/Counter1 and Timer/Counter0 +; OSCCAL 0x0051 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter Register +; TCNT0.TCNT0_7 7 +; TCNT0.TCNT0_6 6 +; TCNT0.TCNT0_5 5 +; TCNT0.TCNT0_4 4 +; TCNT0.TCNT0_3 3 +; TCNT0.TCNT0_2 2 +; TCNT0.TCNT0_1 1 +; TCNT0.TCNT0_0 0 +; TCCR0 0x0053 Timer/Counter Control Register +; TCCR0.CS02 2 Clock Select 2 +; TCCR0.CS01 1 Clock Select 1 +; TCCR0.CS00 0 Clock Select 0 +; MCUCSR 0x0054 MCU Control and Status Register +; MCUCSR.WDRF 3 Watchdog Reset Flag +; MCUCSR.BORF 2 Brown-out Reset Flag +; MCUCSR.EXTRF 1 External Reset Flag +; MCUCSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.SE 7 Sleep Enable +; MCUCR.SM2 6 Sleep Mode Select Bit 2 +; MCUCR.SM1 5 Sleep Mode Select Bit 1 +; MCUCR.SM0 4 Sleep Mode Select Bit 0 +; MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +; MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; TWCR 0x0056 TWI Control Register +; TWCR.TWINT 7 TWI Interrupt Flag +; TWCR.TWEA 6 TWI Enable Acknowledge Bit +; TWCR.TWSTA 5 TWI START Condition Bit +; TWCR.TWSTO 4 TWI STOP Condition Bit +; TWCR.TWWC 3 TWI Write Collision Flag +; TWCR.TWEN 2 TWI Enable Bit +; TWCR.TWIE 0 TWI Interrupt Enable +; SPMCR 0x0057 Store Program Memory Control Register +; SPMCR.SPMIE 7 SPM Interrupt Enable +; SPMCR.RWWSB 6 Read-While-Write Section Busy +; SPMCR.RWWSRE 4 Read-While-Write Section Read Enable +; SPMCR.BLBSET 3 Boot Lock Bit Set +; SPMCR.PGWRT 2 Page Write +; SPMCR.PGERS 1 Page Erase +; SPMCR.SPMEN 0 Store Program Memory Enable +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF2 7 Output Compare Flag 2 +; TIFR.TOV2 6 Timer/Counter2 Overflow Flag +; TIFR.ICF1 5 Timer/Counter1, Input Capture Flag +; TIFR.OCF1A 4 Timer/Counter1, Output Compare A Match Flag +; TIFR.OCF1B 3 Timer/Counter1, Output Compare B Match Flag +; TIFR.TOV1 2 Timer/Counter1, Overflow Flag +; TIFR.TOV0 0 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE2 7 Timer/Counter2 Output Compare Match Interrupt Enable +; TIMSK.TOIE2 6 Timer/Counter2 Overflow Interrupt Enable +; TIMSK.TICIE1 5 Timer/Counter1, Input Capture Interrupt Enable +; TIMSK.OCIE1A 4 Timer/Counter1, Output Compare A Match Interrupt Enable +; TIMSK.OCIE1B 3 Timer/Counter1, Output Compare B Match Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1, Overflow Interrupt Enable +; TIMSK.TOIE0 0 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF1 7 External Interrupt Flag 1 +; GIFR.INTF0 6 External Interrupt Flag 0 +; GICR 0x005B General Interrupt Control Register +; GICR.INT1 7 External Interrupt Request 1 Enable +; GICR.INT0 6 External Interrupt Request 0 Enable +; GICR.IVSEL 1 Interrupt Vector Select +; GICR.IVCE 0 Interrupt Vector Change Enable +; RESERVED005C 0x005C RESERVED +; SPL 0x005D Stack Pointer Low +; SPL.SP7 7 +; SPL.SP6 6 +; SPL.SP5 5 +; SPL.SP4 4 +; SPL.SP3 3 +; SPL.SP2 2 +; SPL.SP1 1 +; SPL.SP0 0 +; SPH 0x005E Stack Pointer High +; SPH.SP10 10 +; SPH.SP9 9 +; SPH.SP8 8 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATtiny15L +SUBARCH=1 +; doc1187.pdf +; + +RAM=0 +ROM=1024 +EEPROM=64 + +; MEMORY MAP + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Reset, Power-on Reset, Brown-out Reset, and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry I_O_Pins 0x0002 Pin Change Interrupt +entry TIMER1_COMPA 0x0003 Timer/Counter1 Compare Match A +entry TIMER1_OVF 0x0004 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0005 Timer/Counter0 Overflow +entry EE_RDY 0x0006 EEPROM Ready +entry ANA_COMP 0x0007 Analog Comparator +entry ADC_ 0x0008 ADC Conversion Complete + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion result 7 +ADCL.ADC6 6 ADC Conversion result 6 +ADCL.ADC5 5 ADC Conversion result 5 +ADCL.ADC4 4 ADC Conversion result 4 +ADCL.ADC3 3 ADC Conversion result 3 +ADCL.ADC2 2 ADC Conversion result 2 +ADCL.ADC1 1 ADC Conversion result 1 +ADCL.ADC0 0 ADC Conversion result 0 +ADCH 0x0005 The ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 ADC Conversion result 9 +ADCH.ADC8 8 ADC Conversion result 8 +; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion result 1 +; ADCL.ADC0 6 ADC Conversion result 0 +; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion result 9 +; ADCH.ADC8 14 ADC Conversion result 8 +; ADCH.ADC7 13 ADC Conversion result 7 +; ADCH.ADC6 12 ADC Conversion result 6 +; ADCH.ADC5 11 ADC Conversion result 5 +; ADCH.ADC4 10 ADC Conversion result 4 +; ADCH.ADC3 9 ADC Conversion result 3 +; ADCH.ADC2 8 ADC Conversion result 2 +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Running Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +RESERVED0010 0x0010 RESERVED +RESERVED0011 0x0011 RESERVED +RESERVED0012 0x0012 RESERVED +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEAR 0x001E EEPROM Address Register +EEAR.EEAR5 5 EEPROM Addres 5 +EEAR.EEAR4 4 EEPROM Addres 4 +EEAR.EEAR3 3 EEPROM Addres 3 +EEAR.EEAR2 2 EEPROM Addres 2 +EEAR.EEAR1 1 EEPROM Addres 1 +EEAR.EEAR0 0 EEPROM Addres 0 +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +SFIOR 0x002C Special Function IO Register +SFIOR.FOC1A 2 Force Output Compare 1A +SFIOR.PSR1 1 Prescaler Reset Timer/Counter1 +SFIOR.PSR0 0 Prescaler Reset Timer/Counter0 +OCR1B 0x002D Timer/Counter1 Output Compare RegisterB +OCR1A 0x002E Timer/Counter1 Output Compare Register A +TCNT1 0x002F Timer/Counter1 +TCCR1 0x0030 Timer/Counter1 Control Register +TCCR1.CTC1 7 Clear Timer/Counter on Compare Match +TCCR1.PWM1 6 Pulse Width Modulator Enable +TCCR1.COM1A1 5 Compare Output Mode, Bit 1 +TCCR1.COM1A0 4 Compare Output Mode, Bit 0 +TCCR1.CS13 3 Clock Select Bit 3 +TCCR1.CS12 2 Clock Select Bit 2 +TCCR1.CS11 1 Clock Select Bit 1 +TCCR1.CS10 0 Clock Select Bit 0 +OSCCAL 0x0031 System Clock Oscillator Calibration Register +OSCCAL.CAL7 7 +OSCCAL.CAL6 6 +OSCCAL.CAL5 5 +OSCCAL.CAL4 4 +OSCCAL.CAL3 3 +OSCCAL.CAL2 2 +OSCCAL.CAL1 1 +OSCCAL.CAL0 0 +TCNT0 0x0032 Timer Counter 0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.WDRF 3 Watchdog Reset Flag +MCUSR.BORF 2 Brown-out Reset Flag +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.PUD 6 Pull-up Disable +MCUCR.SE 5 SleepEnable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.SM0 3 Sleep Mode Select Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF1A 6 Output Compare Flag 1A +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF0 6 External Interrupt Flag0 +GIFR.PCIF 5 Pin Change Interrupt Flag +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.PCIE 5 PinChange InterruptEnable +RESERVED003C 0x003C RESERVED +RESERVED003D 0x003D RESERVED +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + + +.ATtiny26L +SUBARCH=2 +; doc1477.pdf +; + +RAM=128 +ROM=2048 +EEPROM=128 + +; MEMORY MAP +area DATA FSR_ 0x0000:0x0060 +area DATA I_SRAM 0x0060:0x00E0 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry I_O_Pins 0x0002 Pin Change Interrupt +entry TIMER1_CMPA 0x0003 Timer/Counter1 Compare Match 1A +entry TIMER1_CMPB 0x0004 Timer/Counter1 Compare Match 1B +entry TIMER1_OVF1 0x0005 Timer/Counter1 Overflow +entry TIMER0_OVF0 0x0006 Timer/Counter0 Overflow +entry USI_STRT 0x0007 USI Start +entry USI_OVF 0x0008 USI Overflow +entry EE_RDY 0x0009 EEPROM Ready +entry ANA_COMP 0x000A Analog Comparator +entry ADC_ 0x000B ADC Conversion Complete + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +ADCL 0x0004 The ADC Data Register Low (ADLAR = 0) +ADCL.ADC7 7 ADC Conversion result 7 +ADCL.ADC6 6 ADC Conversion result 6 +ADCL.ADC5 5 ADC Conversion result 5 +ADCL.ADC4 4 ADC Conversion result 4 +ADCL.ADC3 3 ADC Conversion result 3 +ADCL.ADC2 2 ADC Conversion result 2 +ADCL.ADC1 1 ADC Conversion result 1 +ADCL.ADC0 0 ADC Conversion result 0 +ADCH 0x0005 The ADC Data Register High (ADLAR = 0) +ADCH.ADC9 9 ADC Conversion result 9 +ADCH.ADC8 8 ADC Conversion result 8 +; ADCL 0x0004 The ADC Data Register Low (ADLAR = 1) +; ADCL.ADC1 7 ADC Conversion result 1 +; ADCL.ADC0 6 ADC Conversion result 0 +; ADCH 0x0005 The ADC Data Register High (ADLAR = 1) +; ADCH.ADC9 15 ADC Conversion result 9 +; ADCH.ADC8 14 ADC Conversion result 8 +; ADCH.ADC7 13 ADC Conversion result 7 +; ADCH.ADC6 12 ADC Conversion result 6 +; ADCH.ADC5 11 ADC Conversion result 5 +; ADCH.ADC4 10 ADC Conversion result 4 +; ADCH.ADC3 9 ADC Conversion result 3 +; ADCH.ADC2 8 ADC Conversion result 2 +ADCSR 0x0006 ADC Control and Status Register +ADCSR.ADEN 7 ADC Enable +ADCSR.ADSC 6 ADC Start Conversion +ADCSR.ADFR 5 ADC Free Running Select +ADCSR.ADIF 4 ADC Interrupt Flag +ADCSR.ADIE 3 ADC Interrupt Enable +ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +ADMUX 0x0007 ADC Multiplexer Selection Register +ADMUX.REFS1 7 Reference Selection Bit 1 +ADMUX.REFS0 6 Reference Selection Bit 0 +ADMUX.ADLAR 5 ADC Left Adjust Result +ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACME 2 Analog Comparator Multiplexer Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +USICR 0x000D USI Control Register +USICR.USISIE 7 Start Condition Interrupt Enable +USICR.USIOIE 6 Counter Overflow Interrupt Enable +USICR.USIWM1 5 Wire Mode 1 +USICR.USIWM0 4 Wire Mode 0 +USICR.USICS1 3 Clock Source Select 1 +USICR.USICS0 2 Clock Source Select 0 +USICR.USICLK 1 Clock Strobe +USICR.USITC 0 Toggle Clock Port Pin +USISR 0x000E USI Status Register +USISR.USISIF 7 Start Condition Interrupt Flag +USISR.USIOIF 6 Counter Overflow Interrupt Flag +USISR.USIPF 5 Stop Condition Flag +USISR.USIDC 4 Data Output Collision +USISR.USICNT3 3 Counter Value 3 +USISR.USICNT2 2 Counter Value 2 +USISR.USICNT1 1 Counter Value 1 +USISR.USICNT0 0 Counter Value 0 +USIDR 0x000F USI Data Register +RESERVED0010 0x0010 RESERVED +RESERVED0011 0x0011 RESERVED +RESERVED0012 0x0012 RESERVED +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEAR 0x001E EEPROM Address Register +EEAR.EEAR6 6 EEPROM Addres 6 +EEAR.EEAR5 5 EEPROM Addres 5 +EEAR.EEAR4 4 EEPROM Addres 4 +EEAR.EEAR3 3 EEPROM Addres 3 +EEAR.EEAR2 2 EEPROM Addres 2 +EEAR.EEAR1 1 EEPROM Addres 1 +EEAR.EEAR0 0 EEPROM Addres 0 +RESERVED0001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDCE 4 Watchdog Change Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +PLLCSR 0x0029 PLL Control and Status Register +PLLCSR.PCKE 2 PCK Enable +PLLCSR.PLLE 1 PLL Enable +PLLCSR.PLOCK 0 PLL Lock Detector +RESERVED002A 0x002A RESERVED +OCR1C 0x002B Timer/Counter1 Output Compare Register C +OCR1B 0x002C Timer/Counter1 Output Compare Register B +OCR1A 0x002D Timer/Counter1 Output Compare Register A +TCNT1 0x002E Timer/Counter1 +TCCR1B 0x002F Timer/Counter1 Control Register B +TCCR1B.CTC1 7 Clear Timer/Counter on Compare Match +TCCR1B.PSR1 6 Prescaler Reset Timer/Counter1 +TCCR1B.CS13 3 Clock Select Bit 3 +TCCR1B.CS12 2 Clock Select Bit 2 +TCCR1B.CS11 1 Clock Select Bit 1 +TCCR1B.CS10 0 Clock Select Bit 0 +TCCR1A 0x0030 Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Comparator A Output Mode, Bit 1 +TCCR1A.COM1A0 6 Comparator A Output Mode, Bit 0 +TCCR1A.COM1B1 5 Comparator B Output Mode, Bit 1 +TCCR1A.COM1B0 4 Comparator B Output Mode, Bit 0 +TCCR1A.FOC1A 3 Force Output Compare Match 1A +TCCR1A.FOC1B 2 Force Output Compare Match 1B +TCCR1A.PWM1A 1 Pulse Width Modulator A Enable +TCCR1A.PWM1B 0 Pulse Width Modulator B Enable +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.PSR0 3 Prescaler Reset Timer/Counter0 +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.WDRF 3 Watchdog Reset Flag +MCUSR.BORF 2 Brown-out Reset Flag +MCUSR.EXTRF 1 External Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.PUD 6 Pull-up Disable +MCUCR.SE 5 Sleep Enable +MCUCR.SM1 4 Sleep Mode Select Bit 1 +MCUCR.SM0 3 Sleep Mode Select Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.OCF1A 6 Output Compare Flag 1A +TIFR.OCF1B 5 Output Compare Flag 1B +TIFR.TOV1 2 Timer/Counter1 Overflow Flag +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1 Output Compare Interrupt Enable +TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF0 6 External Interrupt Flag0 +GIFR.PCIF 5 Pin Change Interrupt Flag +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.PCIE1 5 Pin Change Interrupt Enable1 +GIMSK.PCIE0 4 Pin Change Interrupt Enable0 +RESERVED003C 0x003C RESERVED +SP 0x003D Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +; RESERVED0020 0x0020 RESERVED +; RESERVED0021 0x0021 RESERVED +; RESERVED0022 0x0022 RESERVED +; RESERVED0023 0x0023 RESERVED +; ADCL 0x0024 The ADC Data Register Low (ADLAR = 0) +; ADCL.ADC7 7 ADC Conversion result 7 +; ADCL.ADC6 6 ADC Conversion result 6 +; ADCL.ADC5 5 ADC Conversion result 5 +; ADCL.ADC4 4 ADC Conversion result 4 +; ADCL.ADC3 3 ADC Conversion result 3 +; ADCL.ADC2 2 ADC Conversion result 2 +; ADCL.ADC1 1 ADC Conversion result 1 +; ADCL.ADC0 0 ADC Conversion result 0 +; ADCH 0x0025 The ADC Data Register High (ADLAR = 0) +; ADCH.ADC9 9 ADC Conversion result 9 +; ADCH.ADC8 8 ADC Conversion result 8 +; ; ADCL 0x0024 The ADC Data Register Low (ADLAR = 1) +; ; ADCL.ADC1 7 ADC Conversion result 1 +; ; ADCL.ADC0 6 ADC Conversion result 0 +; ; ADCH 0x0025 The ADC Data Register High (ADLAR = 1) +; ; ADCH.ADC9 15 ADC Conversion result 9 +; ; ADCH.ADC8 14 ADC Conversion result 8 +; ; ADCH.ADC7 13 ADC Conversion result 7 +; ; ADCH.ADC6 12 ADC Conversion result 6 +; ; ADCH.ADC5 11 ADC Conversion result 5 +; ; ADCH.ADC4 10 ADC Conversion result 4 +; ; ADCH.ADC3 9 ADC Conversion result 3 +; ; ADCH.ADC2 8 ADC Conversion result 2 +; ADCSR 0x0026 ADC Control and Status Register +; ADCSR.ADEN 7 ADC Enable +; ADCSR.ADSC 6 ADC Start Conversion +; ADCSR.ADFR 5 ADC Free Running Select +; ADCSR.ADIF 4 ADC Interrupt Flag +; ADCSR.ADIE 3 ADC Interrupt Enable +; ADCSR.ADPS2 2 ADC Prescaler Select Bit 2 +; ADCSR.ADPS1 1 ADC Prescaler Select Bit 1 +; ADCSR.ADPS0 0 ADC Prescaler Select Bit 0 +; ADMUX 0x0027 ADC Multiplexer Selection Register +; ADMUX.REFS1 7 Reference Selection Bit 1 +; ADMUX.REFS0 6 Reference Selection Bit 0 +; ADMUX.ADLAR 5 ADC Left Adjust Result +; ADMUX.MUX4 4 Analog Channel and Gain Selection Bit 4 +; ADMUX.MUX3 3 Analog Channel and Gain Selection Bit 3 +; ADMUX.MUX2 2 Analog Channel and Gain Selection Bit 2 +; ADMUX.MUX1 1 Analog Channel and Gain Selection Bit 1 +; ADMUX.MUX0 0 Analog Channel and Gain Selection Bit 0 +; ACSR 0x0028 Analog Comparator Control and Status Register +; ACSR.ACD 7 Analog Comparator Disable +; ACSR.ACBG 6 Analog Comparator Bandgap Select +; ACSR.ACO 5 Analog Comparator Output +; ACSR.ACI 4 Analog Comparator Interrupt Flag +; ACSR.ACIE 3 Analog Comparator Interrupt Enable +; ACSR.ACME 2 Analog Comparator Multiplexer Enable +; ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +; ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +; RESERVED0029 0x0029 RESERVED +; RESERVED002A 0x002A RESERVED +; RESERVED002B 0x002B RESERVED +; RESERVED002C 0x002C RESERVED +; USICR 0x002D USI Control Register +; USICR.USISIE 7 Start Condition Interrupt Enable +; USICR.USIOIE 6 Counter Overflow Interrupt Enable +; USICR.USIWM1 5 Wire Mode 1 +; USICR.USIWM0 4 Wire Mode 0 +; USICR.USICS1 3 Clock Source Select 1 +; USICR.USICS0 2 Clock Source Select 0 +; USICR.USICLK 1 Clock Strobe +; USICR.USITC 0 Toggle Clock Port Pin +; USISR 0x002E USI Status Register +; USISR.USISIF 7 Start Condition Interrupt Flag +; USISR.USIOIF 6 Counter Overflow Interrupt Flag +; USISR.USIPF 5 Stop Condition Flag +; USISR.USIDC 4 Data Output Collision +; USISR.USICNT3 3 Counter Value 3 +; USISR.USICNT2 2 Counter Value 2 +; USISR.USICNT1 1 Counter Value 1 +; USISR.USICNT0 0 Counter Value 0 +; USIDR 0x002F USI Data Register +; RESERVED0030 0x0030 RESERVED +; RESERVED0031 0x0031 RESERVED +; RESERVED0032 0x0032 RESERVED +; RESERVED0033 0x0033 RESERVED +; RESERVED0034 0x0034 RESERVED +; RESERVED0035 0x0035 RESERVED +; PINB 0x0036 Port B Input Pins Address +; PINB.PINB7 7 +; PINB.PINB6 6 +; PINB.PINB5 5 +; PINB.PINB4 4 +; PINB.PINB3 3 +; PINB.PINB2 2 +; PINB.PINB1 1 +; PINB.PINB0 0 +; DDRB 0x0037 Port B Data Direction Register +; DDRB.DDB7 7 Port B Data Direction Register bit 7 +; DDRB.DDB6 6 Port B Data Direction Register bit 6 +; DDRB.DDB5 5 Port B Data Direction Register bit 5 +; DDRB.DDB4 4 Port B Data Direction Register bit 4 +; DDRB.DDB3 3 Port B Data Direction Register bit 3 +; DDRB.DDB2 2 Port B Data Direction Register bit 2 +; DDRB.DDB1 1 Port B Data Direction Register bit 1 +; DDRB.DDB0 0 Port B Data Direction Register bit 0 +; PORTB 0x0038 Port B Data Register +; PORTB.PORTB7 7 Port B Data Register bit 7 +; PORTB.PORTB6 6 Port B Data Register bit 6 +; PORTB.PORTB5 5 Port B Data Register bit 5 +; PORTB.PORTB4 4 Port B Data Register bit 4 +; PORTB.PORTB3 3 Port B Data Register bit 3 +; PORTB.PORTB2 2 Port B Data Register bit 2 +; PORTB.PORTB1 1 Port B Data Register bit 1 +; PORTB.PORTB0 0 Port B Data Register bit 0 +; PINA 0x0039 Port A Input Pins Address +; PINA.PINA7 7 +; PINA.PINA6 6 +; PINA.PINA5 5 +; PINA.PINA4 4 +; PINA.PINA3 3 +; PINA.PINA2 2 +; PINA.PINA1 1 +; PINA.PINA0 0 +; DDRA 0x003A Port A Data Direction Register +; DDRA.DDA7 7 Port A Data Direction Register bit 7 +; DDRA.DDA6 6 Port A Data Direction Register bit 6 +; DDRA.DDA5 5 Port A Data Direction Register bit 5 +; DDRA.DDA4 4 Port A Data Direction Register bit 4 +; DDRA.DDA3 3 Port A Data Direction Register bit 3 +; DDRA.DDA2 2 Port A Data Direction Register bit 2 +; DDRA.DDA1 1 Port A Data Direction Register bit 1 +; DDRA.DDA0 0 Port A Data Direction Register bit 0 +; PORTA 0x003B Port A Data Register +; PORTA.PORTA7 7 Port A Data Register bit 7 +; PORTA.PORTA6 6 Port A Data Register bit 6 +; PORTA.PORTA5 5 Port A Data Register bit 5 +; PORTA.PORTA4 4 Port A Data Register bit 4 +; PORTA.PORTA3 3 Port A Data Register bit 3 +; PORTA.PORTA2 2 Port A Data Register bit 2 +; PORTA.PORTA1 1 Port A Data Register bit 1 +; PORTA.PORTA0 0 Port A Data Register bit 0 +; EECR 0x003C EEPROM Control Register +; EECR.EERIE 3 EEPROM Ready Interrupt Enable +; EECR.EEMWE 2 EEPROM Master Write Enable +; EECR.EEWE 1 EEPROM Write Enable +; EECR.EERE 0 EEPROM Read Enable +; EEDR 0x003D EEPROM Data Register +; EEDR.EEDR7 7 EEPROM Data 7 +; EEDR.EEDR6 6 EEPROM Data 6 +; EEDR.EEDR5 5 EEPROM Data 5 +; EEDR.EEDR4 4 EEPROM Data 4 +; EEDR.EEDR3 3 EEPROM Data 3 +; EEDR.EEDR2 2 EEPROM Data 2 +; EEDR.EEDR1 1 EEPROM Data 1 +; EEDR.EEDR0 0 EEPROM Data 0 +; EEAR 0x003E EEPROM Address Register +; EEAR.EEAR6 6 EEPROM Addres 6 +; EEAR.EEAR5 5 EEPROM Addres 5 +; EEAR.EEAR4 4 EEPROM Addres 4 +; EEAR.EEAR3 3 EEPROM Addres 3 +; EEAR.EEAR2 2 EEPROM Addres 2 +; EEAR.EEAR1 1 EEPROM Addres 1 +; EEAR.EEAR0 0 EEPROM Addres 0 +; RESERVED003F 0x003F RESERVED +; RESERVED0040 0x0040 RESERVED +; WDTCR 0x0041 Watchdog Timer Control Register +; WDTCR.WDCE 4 Watchdog Change Enable +; WDTCR.WDE 3 Watchdog Enable +; WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +; WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +; WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +; RESERVED0042 0x0042 RESERVED +; RESERVED0043 0x0043 RESERVED +; RESERVED0044 0x0044 RESERVED +; RESERVED0045 0x0045 RESERVED +; RESERVED0046 0x0046 RESERVED +; RESERVED0047 0x0047 RESERVED +; RESERVED0048 0x0048 RESERVED +; PLLCSR 0x0049 PLL Control and Status Register +; PLLCSR.PCKE 2 PCK Enable +; PLLCSR.PLLE 1 PLL Enable +; PLLCSR.PLOCK 0 PLL Lock Detector +; RESERVED004A 0x004A RESERVED +; OCR1C 0x004B Timer/Counter1 Output Compare Register C +; OCR1B 0x004C Timer/Counter1 Output Compare Register B +; OCR1A 0x004D Timer/Counter1 Output Compare Register A +; TCNT1 0x004E Timer/Counter1 +; TCCR1B 0x004F Timer/Counter1 Control Register B +; TCCR1B.CTC1 7 Clear Timer/Counter on Compare Match +; TCCR1B.PSR1 6 Prescaler Reset Timer/Counter1 +; TCCR1B.CS13 3 Clock Select Bit 3 +; TCCR1B.CS12 2 Clock Select Bit 2 +; TCCR1B.CS11 1 Clock Select Bit 1 +; TCCR1B.CS10 0 Clock Select Bit 0 +; TCCR1A 0x0050 Timer/Counter1 Control Register A +; TCCR1A.COM1A1 7 Comparator A Output Mode, Bit 1 +; TCCR1A.COM1A0 6 Comparator A Output Mode, Bit 0 +; TCCR1A.COM1B1 5 Comparator B Output Mode, Bit 1 +; TCCR1A.COM1B0 4 Comparator B Output Mode, Bit 0 +; TCCR1A.FOC1A 3 Force Output Compare Match 1A +; TCCR1A.FOC1B 2 Force Output Compare Match 1B +; TCCR1A.PWM1A 1 Pulse Width Modulator A Enable +; TCCR1A.PWM1B 0 Pulse Width Modulator B Enable +; OSCCAL 0x0051 Oscillator Calibration Register +; OSCCAL.CAL7 7 Oscillator Calibration Value 7 +; OSCCAL.CAL6 6 Oscillator Calibration Value 6 +; OSCCAL.CAL5 5 Oscillator Calibration Value 5 +; OSCCAL.CAL4 4 Oscillator Calibration Value 4 +; OSCCAL.CAL3 3 Oscillator Calibration Value 3 +; OSCCAL.CAL2 2 Oscillator Calibration Value 2 +; OSCCAL.CAL1 1 Oscillator Calibration Value 1 +; OSCCAL.CAL0 0 Oscillator Calibration Value 0 +; TCNT0 0x0052 Timer/Counter0 +; TCCR0 0x0053 Timer/Counter0 Control Register +; TCCR0.PSR0 3 Prescaler Reset Timer/Counter0 +; TCCR0.CS02 2 Clock Select0, Bit 2 +; TCCR0.CS01 1 Clock Select0, Bit 1 +; TCCR0.CS00 0 Clock Select0, Bit 0 +; MCUSR 0x0054 MCU Status Register +; MCUSR.WDRF 3 Watchdog Reset Flag +; MCUSR.BORF 2 Brown-out Reset Flag +; MCUSR.EXTRF 1 External Reset Flag +; MCUSR.PORF 0 Power-on Reset Flag +; MCUCR 0x0055 MCU Control Register +; MCUCR.PUD 6 Pull-up Disable +; MCUCR.SE 5 Sleep Enable +; MCUCR.SM1 4 Sleep Mode Select Bit 1 +; MCUCR.SM0 3 Sleep Mode Select Bit 0 +; MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +; MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +; RESERVED0056 0x0056 RESERVED +; RESERVED0057 0x0057 RESERVED +; TIFR 0x0058 Timer/Counter Interrupt Flag Register +; TIFR.OCF1A 6 Output Compare Flag 1A +; TIFR.OCF1B 5 Output Compare Flag 1B +; TIFR.TOV1 2 Timer/Counter1 Overflow Flag +; TIFR.TOV0 1 Timer/Counter0 Overflow Flag +; TIMSK 0x0059 Timer/Counter Interrupt Mask Register +; TIMSK.OCIE1A 6 Timer/Counter1 Output Compare Interrupt Enable +; TIMSK.OCIE1B 5 Timer/Counter1 Output Compare Interrupt Enable +; TIMSK.TOIE1 2 Timer/Counter1 Overflow Interrupt Enable +; TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +; GIFR 0x005A General Interrupt Flag Register +; GIFR.INTF0 6 External Interrupt Flag0 +; GIFR.PCIF 5 Pin Change Interrupt Flag +; GIMSK 0x005B General Interrupt Mask Register +; GIMSK.INT0 6 External Interrupt Request 0 Enable +; GIMSK.PCIE1 5 Pin Change Interrupt Enable1 +; GIMSK.PCIE0 4 Pin Change Interrupt Enable0 +; RESERVED005C 0x005C RESERVED +; SP 0x005D Stack Pointer +; SP.SP7 7 +; SP.SP6 6 +; SP.SP5 5 +; SP.SP4 4 +; SP.SP3 3 +; SP.SP2 2 +; SP.SP1 1 +; SP.SP0 0 +; SREG 0x005F Status Register +; SREG.I 7 Global Interrupt Enable +; SREG.T 6 Bit Copy Storage +; SREG.H 5 Half Carry Flag +; SREG.S 4 Sign Bit +; SREG.V 3 Two's Complement Overflow Flag +; SREG.N 2 Negative Flag +; SREG.Z 1 Zero Flag +; SREG.C 0 Carry Flag + + +.ATtiny28L_V +SUBARCH=1 +; doc1062.pdf +; + +RAM=0 +ROM=2048 +EEPROM=0 + +; MEMORY MAP + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin, Power-on Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry Input_Pins 0x0003 Low-level Input on Port B +entry TIMER0_OVF0 0x0004 Timer/Counter0 Overflow +entry ANA_COMP 0x0005 Analog Comparator + + +; INPUT/OUTPUT PORTS +OSCCAL 0x0000 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +WDTCR 0x0001 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +MODCR 0x0002 Modulation Control Register +MODCR.ONTIM4 7 Modulation On-time 4 +MODCR.ONTIM3 6 Modulation On-time 3 +MODCR.ONTIM2 5 Modulation On-time 2 +MODCR.ONTIM1 4 Modulation On-time 1 +MODCR.ONTIM0 3 Modulation On-time 0 +MODCR.MCONF2 2 Modulation Configuration Bit 2 +MODCR.MCONF1 1 Modulation Configuration Bit 1 +MODCR.MCONF0 0 Modulation Configuration Bit 0 +TCNT0 0x0003 Timer Counter 0 +TCCR0 0x0004 Timer/Counter0 Control Register +TCCR0.FOV0 7 Force Overflow +TCCR0.OOM01 4 Overflow Output Mode, Bit 1 +TCCR0.OOM00 3 Overflow Output Mode, Bit 0 +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +IFR 0x0005 Interrupt Flag Register +IFR.INTF1 7 External Interrupt Flag1 +IFR.INTF0 6 External Interrupt Flag0 +IFR.TOV0 4 Timer/Counter0 Overflow Flag +ICR 0x0006 Interrupt Control Register +ICR.INT1 7 External Interrupt Request 1 Enable +ICR.INT0 6 External Interrupt Request 0 Enable +ICR.LLIE 5 Low-level Input Interrupt Enable +ICR.TOIE0 4 Timer/Counter0 Overflow Interrupt Enable +ICR.ISC11 3 Interrupt Sense Control 1 Bit 1 +ICR.ISC10 2 Interrupt Sense Control 1 Bit 0 +ICR.ISC01 1 Interrupt Sense Control 0 Bit 1 +ICR.ISC00 0 Interrupt Sense Control 0 Bit 0 +MCUCS 0x0007 MCU Control and Status Register +MCUCS.PLUPB 7 Pull-up Enable Port B +MCUCS.SE 5 Sleep Enable +MCUCS.SM 4 Sleep Mode +MCUCS.WDRF 3 Watchdog Reset Flag +MCUCS.EXTRF 1 External Reset Flag +MCUCS.PORF 0 Power-on Reset Flag +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +RESERVED0017 0x0017 RESERVED +RESERVED0018 0x0018 RESERVED +PINA 0x0019 Port A Input Pins Address +PINA.PINA3 3 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +RESERVED001C 0x001C RESERVED +RESERVED001D 0x001D RESERVED +RESERVED001E 0x001E RESERVED +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +RESERVED0021 0x0021 RESERVED +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +RESERVED002C 0x002C RESERVED +RESERVED002D 0x002D RESERVED +RESERVED002E 0x002E RESERVED +RESERVED002F 0x002F RESERVED +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +RESERVED0032 0x0032 RESERVED +RESERVED0033 0x0033 RESERVED +RESERVED0034 0x0034 RESERVED +RESERVED0035 0x0035 RESERVED +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +RESERVED0038 0x0038 RESERVED +RESERVED0039 0x0039 RESERVED +RESERVED003A 0x003A RESERVED +RESERVED003B 0x003B RESERVED +RESERVED003C 0x003C RESERVED +RESERVED003D 0x003D RESERVED +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + + +.ATtiny_11 +SUBARCH=1 +; doc1006.pdf +; + +RAM=0 +ROM=1024 +EEPROM=0 + +; MEMORY MAP + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry I_O_Pins 0x0002 Pin Change Interrupt +entry TIMER0_OVF0 0x0003 Timer/Counter0 Overflow +entry ANA_COMP 0x0004 Analog Comparator + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +RESERVED0010 0x0010 RESERVED +RESERVED0011 0x0011 RESERVED +RESERVED0012 0x0012 RESERVED +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +RESERVED001C 0x001C RESERVED +RESERVED001D 0x001D RESERVED +RESERVED001E 0x001E RESERVED +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +RESERVED002C 0x002C RESERVED +RESERVED002D 0x002D RESERVED +RESERVED002E 0x002E RESERVED +RESERVED002F 0x002F RESERVED +RESERVED0030 0x0030 RESERVED +RESERVED0031 0x0031 RESERVED +TCNT0 0x0032 Timer Counter 0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.EXTRF 1 EXTernal Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC01 1 Interrupt Sense Control0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF0 6 External Interrupt Flag0 +GIFR.PCIF 5 Pin Change Interrupt Flag +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.PCIE 5 Pin Change Interrupt Enable +RESERVED003C 0x003C RESERVED +RESERVED003D 0x003D RESERVED +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + + +.ATtiny_11_12 +SUBARCH=1 +; doc1006.pdf +; + +RAM=0 +ROM=1024 +EEPROM=64 + +; MEMORY MAP + +; Interrupt and reset vector assignments +entry __RESET 0x0000 External Pin, Power-on Reset, Brown-out Reset and Watchdog Reset +entry INT0_ 0x0001 External Interrupt Request 0 +entry I_O_Pins 0x0002 Pin Change Interrupt +entry TIMER0_OVF0 0x0003 Timer/Counter0 Overflow +entry EE_RDY 0x0004 EEPROM Ready +entry ANA_COMP 0x0005 Analog Comparator + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +RESERVED0001 0x0001 RESERVED +RESERVED0002 0x0002 RESERVED +RESERVED0003 0x0003 RESERVED +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.AINBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +RESERVED0009 0x0009 RESERVED +RESERVED000A 0x000A RESERVED +RESERVED000B 0x000B RESERVED +RESERVED000C 0x000C RESERVED +RESERVED000D 0x000D RESERVED +RESERVED000E 0x000E RESERVED +RESERVED000F 0x000F RESERVED +RESERVED0010 0x0010 RESERVED +RESERVED0011 0x0011 RESERVED +RESERVED0012 0x0012 RESERVED +RESERVED0013 0x0013 RESERVED +RESERVED0014 0x0014 RESERVED +RESERVED0015 0x0015 RESERVED +PINB 0x0016 Port B Input Pins Address +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +RESERVED0019 0x0019 RESERVED +RESERVED001A 0x001A RESERVED +RESERVED001B 0x001B RESERVED +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEDR.EEDR7 7 EEPROM Data 7 +EEDR.EEDR6 6 EEPROM Data 6 +EEDR.EEDR5 5 EEPROM Data 5 +EEDR.EEDR4 4 EEPROM Data 4 +EEDR.EEDR3 3 EEPROM Data 3 +EEDR.EEDR2 2 EEPROM Data 2 +EEDR.EEDR1 1 EEPROM Data 1 +EEDR.EEDR0 0 EEPROM Data 0 +EEAR 0x001E EEPROM Address Register +EEAR.EEAR5 5 +EEAR.EEAR4 4 +EEAR.EEAR3 3 +EEAR.EEAR2 2 +EEAR.EEAR1 1 +EEAR.EEAR0 0 +RESERVED001F 0x001F RESERVED +RESERVED0020 0x0020 RESERVED +WDTCR 0x0021 Watchdog Timer Control Register +WDTCR.WDTOE 4 Watchdog Turn-off Enable +WDTCR.WDE 3 Watchdog Enable +WDTCR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCR.WDP0 0 Watchdog Timer Prescaler 0 +RESERVED0022 0x0022 RESERVED +RESERVED0023 0x0023 RESERVED +RESERVED0024 0x0024 RESERVED +RESERVED0025 0x0025 RESERVED +RESERVED0026 0x0026 RESERVED +RESERVED0027 0x0027 RESERVED +RESERVED0028 0x0028 RESERVED +RESERVED0029 0x0029 RESERVED +RESERVED002A 0x002A RESERVED +RESERVED002B 0x002B RESERVED +RESERVED002C 0x002C RESERVED +RESERVED002D 0x002D RESERVED +RESERVED002E 0x002E RESERVED +RESERVED002F 0x002F RESERVED +RESERVED0030 0x0030 RESERVED +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL7 7 Oscillator Calibration Value 7 +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer Counter 0 +TCCR0 0x0033 Timer/Counter0 Control Register +TCCR0.CS02 2 Clock Select0, Bit 2 +TCCR0.CS01 1 Clock Select0, Bit 1 +TCCR0.CS00 0 Clock Select0, Bit 0 +MCUSR 0x0034 MCU Status Register +MCUSR.WDRF 3 Watchdog Reset Flag +MCUSR.BORF 2 Brown-out Reset Flag +MCUSR.EXTRF 1 EXTernal Reset Flag +MCUSR.PORF 0 Power-on Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.PUD 6 Pull-up Disable +MCUCR.SE 5 Sleep Enable +MCUCR.SM 4 Sleep Mode +MCUCR.ISC01 1 Interrupt Sense Control0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control0 Bit 0 +RESERVED0036 0x0036 RESERVED +RESERVED0037 0x0037 RESERVED +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +GIFR 0x003A General Interrupt Flag Register +GIFR.INTF0 6 External Interrupt Flag0 +GIFR.PCIF 5 Pin Change Interrupt Flag +GIMSK 0x003B General Interrupt Mask Register +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.PCIE 5 Pin Change Interrupt Enable +RESERVED003C 0x003C RESERVED +RESERVED003D 0x003D RESERVED +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 Carry Flag + +.ATmega168P +; doc8025.pdf +; + +RAM=1024 +ROM=16384 +EEPROM=512 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0060 I/O registers +area DATA I_SRAM 0x0060:0x0160 Internal SRAM + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin +entry INT0_ 0x0002 External Interrupt Request 0 +entry INT1_ 0x0004 External Interrupt Request 1 +entry PCINT0 0x0006 Pin Change Interrupt Request 0 +entry PCINT1 0x0008 Pin Change Interrupt Request 1 +entry PCINT2 0x000A Pin Change Interrupt Request 2 +entry WDT 0x000C Watchdog Time-out +entry TIMER2_COMPA 0x000E Timer/Counter2 Comapare Match A +entry TIMER2_COMPB 0x0010 Timer/Counter2 Comapare Match B +entry TIMER2_OVF 0x0012 Timer/Counter2 Overflow +entry TIMER1_CAPT 0x0014 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0016 Timer/Counter1 Comapare Match A +entry TIMER1_COMPB 0x0018 Timer/Counter1 Comapare Match B +entry TIMER1_OVF 0x001A Timer/Counter1 Overflow +entry TIMER0_COMPA 0x001C Timer/Counter0 Comapare Match A +entry TIMER0_COMPB 0x001E Timer/Counter0 Comapare Match B +entry TIMER0_OVF 0x0020 Timer/Counter0 Overflow +entry SPI_STC 0x0022 SPI Serial Transfer Complete +entry USART_RX 0x0024 USART RX Complete +entry USART_UDRE 0x0026 USART Data register empty +entry USART_TX 0x0028 USART TX Complete +entry ADC 0x002A ADC Conversion Complete +entry EEREADY 0x002C EEPROM Ready + +; INPUT/OUTPUT PORTS +UDR0 0x00A6 +UBRR0H 0x00A5 +UBRR0L 0x00A4 +UCSR0C 0x00A2 +UCSR0C.UMSEL01 7 +UCSR0C.UMSEL00 6 +UCSR0C.UPM01 5 +UCSR0C.UPM00 4 +UCSR0C.USBS0 3 +UCSR0C.UCSZ01 2 +UCSR0C._UDORD0 1 +UCSR0C.UCSZ00 0 +UCSR0B 0x00A1 +UCSR0B.RXCIE0 7 +UCSR0B.TXCIE0 6 +UCSR0B.UDRIE0 5 +UCSR0B.RXEN0 4 +UCSR0B.TXEN0 3 +UCSR0B.UCSZ02 2 +UCSR0B.RXB80 1 +UCSR0B.TXB80 0 +UCSR0A 0x00A0 +UCSR0A.RXC0 7 +UCSR0A.TXC0 6 +UCSR0A.UDRE0 5 +UCSR0A.FE0 4 +UCSR0A.DOR0 3 +UCSR0A.UPE0 2 +UCSR0A.U2X0 1 +UCSR0A.MPCM0 0 +TWAMR 0x009D +TWAMR.TWAM6 7 +TWAMR.TWAM5 6 +TWAMR.TWAM4 5 +TWAMR.TWAM3 4 +TWAMR.TWAM2 3 +TWAMR.TWAM1 2 +TWAMR.TWAM0 1 +TWCR 0x009C +TWCR.TWINT 7 +TWCR.TWEA 6 +TWCR.TWSTA 5 +TWCR.TWSTO 4 +TWCR.TWWC 3 +TWCR.TWEN 2 +TWCR.TWIE 0 +TWDR 0x009B +TWAR 0x009A +TWAR.TWA6 7 +TWAR.TWA5 6 +TWAR.TWA4 5 +TWAR.TWA3 4 +TWAR.TWA2 3 +TWAR.TWA1 2 +TWAR.TWA0 1 +TWAR.TWGCE 0 +TWSR 0x0099 +TWSR.TWS7 7 +TWSR.TWS6 6 +TWSR.TWS5 5 +TWSR.TWS4 4 +TWSR.TWS3 3 +TWSR.TWPS1 1 +TWSR.TWPS0 0 +TWBR 0x0098 +ASSR 0x0096 +ASSR.EXCLK 6 +ASSR.AS2 5 +ASSR.TCN2UB 4 +ASSR.OCR2AUB 3 +ASSR.OCR2BUB 2 +ASSR.TCR2AUB 1 +ASSR.TCR2BUB 0 +OCR2B 0x0094 +OCR2A 0x0093 +TCNT2 0x0092 +TCCR2B 0x0091 +TCCR2B.FOC2A 7 +TCCR2B.FOC2B 6 +TCCR2B.WGM22 3 +TCCR2B.CS22 2 +TCCR2B.CS21 1 +TCCR2B.CS20 0 +TCCR2A 0x0090 +TCCR2A.COM2A1 7 +TCCR2A.COM2A0 6 +TCCR2A.COM2B1 5 +TCCR2A.COM2B0 4 +TCCR2A.WGM21 1 +TCCR2A.WGM20 0 +OCR1BH 0x006B +OCR1BH.Timer_Counter1 7 +OCR1BH.Output 5 +OCR1BH.Compare 4 +OCR1BH.Register 3 +OCR1BH.B 2 +OCR1BH.High 1 +OCR1BH.Byte 0 +OCR1BL 0x006A +OCR1BL.Timer_Counter1 7 +OCR1BL.Output 5 +OCR1BL.Compare 4 +OCR1BL.Register 3 +OCR1BL.B 2 +OCR1BL.Low 1 +OCR1BL.Byte 0 +OCR1AH 0x0069 +OCR1AH.Timer_Counter1 7 +OCR1AH.Output 5 +OCR1AH.Compare 4 +OCR1AH.Register 3 +OCR1AH.A 2 +OCR1AH.High 1 +OCR1AH.Byte 0 +OCR1AL 0x0068 +OCR1AL.Timer_Counter1 7 +OCR1AL.Output 5 +OCR1AL.Compare 4 +OCR1AL.Register 3 +OCR1AL.A 2 +OCR1AL.Low 1 +OCR1AL.Byte 0 +ICR1H 0x0067 +ICR1H.Timer_Counter1 7 +ICR1H.Input 5 +ICR1H.Capture 4 +ICR1H.Register 3 +ICR1H.High 2 +ICR1H.Byte 1 +ICR1H.136 0 +ICR1L 0x0066 +ICR1L.Timer_Counter1 7 +ICR1L.Input 5 +ICR1L.Capture 4 +ICR1L.Register 3 +ICR1L.Low 2 +ICR1L.Byte 1 +ICR1L.136 0 +TCNT1H 0x0065 +TCNT1L 0x0064 +TCCR1C 0x0062 +TCCR1C.FOC1A 7 +TCCR1C.FOC1B 6 +TCCR1B 0x0061 +TCCR1B.ICNC1 7 +TCCR1B.ICES1 6 +TCCR1B.WGM13 4 +TCCR1B.WGM12 3 +TCCR1B.CS12 2 +TCCR1B.CS11 1 +TCCR1B.CS10 0 +TCCR1A 0x0060 +TCCR1A.COM1A1 7 +TCCR1A.COM1A0 6 +TCCR1A.COM1B1 5 +TCCR1A.COM1B0 4 +TCCR1A.WGM11 1 +TCCR1A.WGM10 0 +DIDR1 0x005F +DIDR1.AIN1D 1 +DIDR1.AIN0D 0 +DIDR0 0x005E +DIDR0.ADC5D 5 +DIDR0.ADC4D 4 +DIDR0.ADC3D 3 +DIDR0.ADC2D 2 +DIDR0.ADC1D 1 +DIDR0.ADC0D 0 +ADMUX 0x005C +ADMUX.REFS1 7 +ADMUX.REFS0 6 +ADMUX.ADLAR 5 +ADMUX.MUX3 3 +ADMUX.MUX2 2 +ADMUX.MUX1 1 +ADMUX.MUX0 0 +ADCSRB 0x005B +ADCSRB.ACME 6 +ADCSRB.ADTS2 2 +ADCSRB.ADTS1 1 +ADCSRB.ADTS0 0 +ADCSRA 0x005A +ADCSRA.ADEN 7 +ADCSRA.ADSC 6 +ADCSRA.ADATE 5 +ADCSRA.ADIF 4 +ADCSRA.ADIE 3 +ADCSRA.ADPS2 2 +ADCSRA.ADPS1 1 +ADCSRA.ADPS0 0 +ADCH 0x0059 +ADCL 0x0058 +TIMSK2 0x0050 +TIMSK2.OCIE2B 2 +TIMSK2.OCIE2A 1 +TIMSK2.TOIE2 0 +TIMSK1 0x004F +TIMSK1.ICIE1 5 +TIMSK1.OCIE1B 2 +TIMSK1.OCIE1A 1 +TIMSK1.TOIE1 0 +TIMSK0 0x004E +TIMSK0.OCIE0B 2 +TIMSK0.OCIE0A 1 +TIMSK0.TOIE0 0 +PCMSK2 0x004D +PCMSK2.PCINT23 7 +PCMSK2.PCINT22 6 +PCMSK2.PCINT21 5 +PCMSK2.PCINT20 4 +PCMSK2.PCINT19 3 +PCMSK2.PCINT18 2 +PCMSK2.PCINT17 1 +PCMSK2.PCINT16 0 +PCMSK1 0x004C +PCMSK1.PCINT14 6 +PCMSK1.PCINT13 5 +PCMSK1.PCINT12 4 +PCMSK1.PCINT11 3 +PCMSK1.PCINT10 2 +PCMSK1.PCINT9 1 +PCMSK1.PCINT8 0 +PCMSK0 0x004B +PCMSK0.PCINT7 7 +PCMSK0.PCINT6 6 +PCMSK0.PCINT5 5 +PCMSK0.PCINT4 4 +PCMSK0.PCINT3 3 +PCMSK0.PCINT2 2 +PCMSK0.PCINT1 1 +PCMSK0.PCINT0 0 +EICRA 0x0049 +EICRA.ISC11 3 +EICRA.ISC10 2 +EICRA.ISC01 1 +EICRA.ISC00 0 +PCICR 0x0048 +PCICR.PCIE2 2 +PCICR.PCIE1 1 +PCICR.PCIE0 0 +OSCCAL 0x0046 +PRR 0x0044 +PRR.PRTWI 7 +PRR.PRTIM2 6 +PRR.PRTIM0 5 +PRR.PRTIM1 3 +PRR.PRSPI 2 +PRR.PRUSART0 1 +PRR.PRADC 0 +CLKPR 0x0041 +CLKPR.CLKPCE 7 +CLKPR.CLKPS3 3 +CLKPR.CLKPS2 2 +CLKPR.CLKPS1 1 +CLKPR.CLKPS0 0 +WDTCSR 0x0040 +WDTCSR.WDIF 7 +WDTCSR.WDIE 6 +WDTCSR.WDP3 5 +WDTCSR.WDCE 4 +WDTCSR.WDE 3 +WDTCSR.WDP2 2 +WDTCSR.WDP1 1 +WDTCSR.WDP0 0 +SREG 0x003F +SREG.I 7 +SREG.T 6 +SREG.H 5 +SREG.S 4 +SREG.V 3 +SREG.N 2 +SREG.Z 1 +SREG.C 0 +SPH 0x003E +SPH.(SP10) 2 +SPH.5. 1 +SPH.SP9 0 +SPL 0x003D +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +SPMCSR 0x0037 +SPMCSR.SPMIE 7 +SPMCSR.(RWWSB)5. 6 +SPMCSR.(RWWSRE)5. 4 +SPMCSR.BLBSET 3 +SPMCSR.PGWRT 2 +SPMCSR.PGERS 1 +SPMCSR.SELFPRGEN 0 +MCUCR 0x0035 +MCUCR.BODS 6 +MCUCR.BODSE 5 +MCUCR.PUD 4 +MCUCR.IVSEL 1 +MCUCR.IVCE 0 +MCUSR 0x0034 +MCUSR.WDRF 3 +MCUSR.BORF 2 +MCUSR.EXTRF 1 +MCUSR.PORF 0 +SMCR 0x0033 +SMCR.SM2 3 +SMCR.SM1 2 +SMCR.SM0 1 +SMCR.SE 0 +ACSR 0x0030 +ACSR.ACD 7 +ACSR.ACBG 6 +ACSR.ACO 5 +ACSR.ACI 4 +ACSR.ACIE 3 +ACSR.ACIC 2 +ACSR.ACIS1 1 +ACSR.ACIS0 0 +SPDR 0x002E +SPSR 0x002D +SPSR.SPIF 7 +SPSR.WCOL 6 +SPSR.SPI2X 0 +SPCR 0x002C +SPCR.SPIE 7 +SPCR.SPE 6 +SPCR.DORD 5 +SPCR.MSTR 4 +SPCR.CPOL 3 +SPCR.CPHA 2 +SPCR.SPR1 1 +SPCR.SPR0 0 +GPIOR2 0x002B +GPIOR1 0x002A +OCR0B 0x0028 +OCR0A 0x0027 +TCNT0 0x0026 +TCCR0B 0x0025 +TCCR0B.FOC0A 7 +TCCR0B.FOC0B 6 +TCCR0B.WGM02 3 +TCCR0B.CS02 2 +TCCR0B.CS01 1 +TCCR0B.CS00 0 +TCCR0A 0x0024 +TCCR0A.COM0A1 7 +TCCR0A.COM0A0 6 +TCCR0A.COM0B1 5 +TCCR0A.COM0B0 4 +TCCR0A.WGM01 1 +TCCR0A.WGM00 0 +GTCCR 0x0023 +GTCCR.TSM 7 +GTCCR.PSRASY 1 +GTCCR.PSRSYNC 0 +EEARH 0x0022 +EEARL 0x0021 +EEDR 0x0020 +EECR 0x001F +EECR.EEPM1 5 +EECR.EEPM0 4 +EECR.EERIE 3 +EECR.EEMPE 2 +EECR.EEPE 1 +EECR.EERE 0 +GPIOR0 0x001E +EIMSK 0x001D +EIMSK.INT1 1 +EIMSK.INT0 0 +EIFR 0x001C +EIFR.INTF1 1 +EIFR.INTF0 0 +PCIFR 0x001B +PCIFR.PCIF2 2 +PCIFR.PCIF1 1 +PCIFR.PCIF0 0 +TIFR2 0x0017 +TIFR2.OCF2B 2 +TIFR2.OCF2A 1 +TIFR2.TOV2 0 +TIFR1 0x0016 +TIFR1.ICF1 5 +TIFR1.OCF1B 2 +TIFR1.OCF1A 1 +TIFR1.TOV1 0 +TIFR0 0x0015 +TIFR0.OCF0B 2 +TIFR0.OCF0A 1 +TIFR0.TOV0 0 +PORTD 0x000B +PORTD.PORTD7 7 +PORTD.PORTD6 6 +PORTD.PORTD5 5 +PORTD.PORTD4 4 +PORTD.PORTD3 3 +PORTD.PORTD2 2 +PORTD.PORTD1 1 +PORTD.PORTD0 0 +DDRD 0x000A +DDRD.DDD7 7 +DDRD.DDD6 6 +DDRD.DDD5 5 +DDRD.DDD4 4 +DDRD.DDD3 3 +DDRD.DDD2 2 +DDRD.DDD1 1 +DDRD.DDD0 0 +PIND 0x0009 +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +PORTC 0x0008 +PORTC.PORTC6 6 +PORTC.PORTC5 5 +PORTC.PORTC4 4 +PORTC.PORTC3 3 +PORTC.PORTC2 2 +PORTC.PORTC1 1 +PORTC.PORTC0 0 +DDRC 0x0007 +DDRC.DDC6 6 +DDRC.DDC5 5 +DDRC.DDC4 4 +DDRC.DDC3 3 +DDRC.DDC2 2 +DDRC.DDC1 1 +DDRC.DDC0 0 +PINC 0x0006 +PINC.PINC6 6 +PINC.PINC5 5 +PINC.PINC4 4 +PINC.PINC3 3 +PINC.PINC2 2 +PINC.PINC1 1 +PINC.PINC0 0 +PORTB 0x0005 +PORTB.PORTB7 7 +PORTB.PORTB6 6 +PORTB.PORTB5 5 +PORTB.PORTB4 4 +PORTB.PORTB3 3 +PORTB.PORTB2 2 +PORTB.PORTB1 1 +PORTB.PORTB0 0 +DDRB 0x0004 +DDRB.DDB7 7 +DDRB.DDB6 6 +DDRB.DDB5 5 +DDRB.DDB4 4 +DDRB.DDB3 3 +DDRB.DDB2 2 +DDRB.DDB1 1 +DDRB.DDB0 0 +PINB 0x0003 +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 + +.ATtiny2313 +SUBARCH=25 +; doc2543.pdf +; + +RAM=128 +ROM=2048 +EEPROM=128 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0060 I/O registers +area DATA I_SRAM 0x0060:0x00E0 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A +entry TIMER1_OVF 0x0005 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0006 Timer/Counter0 Overflow +entry USART0_RX 0x0007 USART0, Rx Complete +entry USART0_UDRE 0x0008 USART0 Data Register Empty +entry USART0_TX 0x0009 USART0, Tx Complete +entry ANALOG_COMP 0x000A Analog Comparator +entry PCINT0 0x000B Pin Change Interrupt Request 0 +entry TIMER1_COMPB 0x000C Timer/Counter1 Compare Match B +entry TIMER0_COMPA 0x000D Timer/Counter0 Compare Match A +entry TIMER0_COMPB 0x000E Timer/Counter0 Compare Match B +entry USI_START 0x000F USI Start Condition +entry USI_OVERFLOW 0x0010 USI Overflow +entry EE_READY 0x0011 EEPROM Ready +entry WDT_OVERFLOW 0x0012 Watchdog Timer Overflow + + +; INPUT/OUTPUT PORTS +RESERVED0000 0x0000 RESERVED +DIDR 0x0001 Digital Input Disable Register +DIDR.AIND0 1 AIN0 Digital Input Disable +DIDR.AIND1 2 AIN1 Digital Input Disable +UBRRH 0x0002 USART Baud Rate Registers High +UCSRC 0x0003 USART Control and Status Register C +UCSRC.UMSEL 6 USART Mode Select +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +RESERVED0004 0x0004 RESERVED +RESERVED0005 0x0005 RESERVED +RESERVED0006 0x0006 RESERVED +RESERVED0007 0x0007 RESERVED +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register +UBRRL.UBRR7 7 +UBRRL.UBRR6 6 +UBRRL.UBRR5 5 +UBRRL.UBRR4 4 +UBRRL.UBRR3 3 +UBRRL.UBRR2 2 +UBRRL.UBRR1 1 +UBRRL.UBRR0 0 +UCSRB 0x000A USART Control and Status Register +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit8 +UCSRA 0x000B USART Control and Status Register +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.UPE 2 Parity Error +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-Processor Communication Mode +UDR 0x000C USART I/O Data Register +USICR 0x000D USI Control Register +USICR.USISIE 7 Start Condition Interrupt Enable +USICR.USIOIE 6 Counter Overflow Interrupt Enable +USICR.USIWM1 5 Wire Mode 1 +USICR.USIWM0 4 Wire Mode 0 +USICR.USICS1 3 Clock Source Select 1 +USICR.USICS0 2 Clock Source Select 0 +USICR.USICLK 1 Clock Strobe +USICR.USITC 0 Toggle Clock Port Pin +USISR 0x000E USI Status Register +USISR.USISIF 7 Start Condition Interrupt Flag +USISR.USIOIF 6 Counter Overflow Interrupt Flag +USISR.USIPF 5 Stop Condition Flag +USISR.USIDC 4 Data Output Collision +USISR.USICNT3 3 Counter Value 3 +USISR.USICNT2 2 Counter Value 2 +USISR.USICNT1 1 Counter Value 1 +USISR.USICNT0 0 Counter Value 0 +USIDR 0x000F USI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +GPIOR0 0x0013 General Purpose I/O Register 0 +GPIOR1 0x0014 General Purpose I/O Register 0 +GPIOR2 0x0015 General Purpose I/O Register 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEAR 0x001E EEPROM Address Register +EEAR.EEAR7 7 +EEAR.EEAR6 6 +EEAR.EEAR5 5 +EEAR.EEAR4 4 +EEAR.EEAR3 3 +EEAR.EEAR2 2 +EEAR.EEAR1 1 +EEAR.EEAR0 0 +RESERVED001F 0x001F RESERVED +PCMSK 0x0020 Pin Change Mask Register 0 +PCMSK.PCINT7 7 Pin Change Enable Mask 7 +PCMSK.PCINT6 6 Pin Change Enable Mask 6 +PCMSK.PCINT5 5 Pin Change Enable Mask 5 +PCMSK.PCINT4 4 Pin Change Enable Mask 4 +PCMSK.PCINT3 3 Pin Change Enable Mask 3 +PCMSK.PCINT2 2 Pin Change Enable Mask 2 +PCMSK.PCINT1 1 Pin Change Enable Mask 1 +PCMSK.PCINT0 0 Pin Change Enable Mask 0 +WDTCSR 0x0021 Watchdog Timer Control Register +WDTCSR.WDIF 7 Watchdog Interrupt Flag +WDTCSR.WDIE 6 Watchdog Interrupt Enable +WDTCSR.WDP3 5 Watchdog Timer Prescaler 3 +WDTCSR.WDCE 4 Watchdog Change Enable +WDTCSR.WDE 3 Watchdog Enable +WDTCSR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCSR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCSR.WDP0 0 Watchdog Timer Prescaler 0 +TCCR1C 0x0022 Timer/Counter1 Control Register C +TCCR1C.FOC1A 7 Force Output Compare for Channel A +TCCR1C.FOC1B 6 Force Output Compare for Channel B +GTCCR 0x0023 General Timer/Counter Control Register +GTCCR.PSR10 1 Prescaler Reset Timer/Counter1 and Timer/Counter0 +ICR1L 0x0024 Input Capture Register Low Byte +ICR1H 0x0025 Input Capture Register High Byte +CLKPR 0x0026 Clock Prescale Register +CLKPR.CPCE 7 Clock Prescaler Change Enable +CLKPR.CLKPS3 3 Clock Prescaler Select Bit 3 +CLKPR.CLKPS2 2 Clock Prescaler Select Bit 2 +CLKPR.CLKPS1 1 Clock Prescaler Select Bit 1 +CLKPR.CLKPS0 0 Clock Prescaler Select Bit 0 +RESERVED0027 0x0027 RESERVED +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input CaptureEdgeSelect +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +TCCR0A 0x0030 Timer/Counter0 Control Register A +TCCR0A.COM0A1 7 Compare Output Mode for Channel A 1 +TCCR0A.COM0A0 6 Compare Output Mode for Channel A 0 +TCCR0A.COM0B1 5 Compare Output Mode for Channel B 1 +TCCR0A.COM0B0 4 Compare Output Mode for Channel B 0 +TCCR0A.WGM01 1 Waveform Generation Mode 1 +TCCR0A.WGM00 0 Waveform Generation Mode 0 +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter0 +TCCR0B 0x0033 Timer/Counter Control Register +TCCR0B.FOC0A 7 Force Output Compare A +TCCR0B.FOC0B 6 Force Output Compare B +TCCR0B.WGM02 3 Waveform Generation Mode +TCCR0B.CS02 2 Clock Select 2 +TCCR0B.CS01 1 Clock Select 1 +TCCR0B.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-On Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.PUD 7 Pull-up Disable +MCUCR.SM1 6 Sleep Mode Select Bit 1 +MCUCR.SE 5 SleepEnable +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +OCR0A 0x0036 Timer/Counter0 Compare Register A +SPMCSR 0x0037 Store Program Memory Control Register +SPMCSR.CTPB 4 Clear Temporary Page Buffer +SPMCSR.RFLB 3 Read Fuse and Lock Bits +SPMCSR.PGWRT 2 Page Write +SPMCSR.PGERS 1 Page Erase +SPMCSR.SELFPRGEN 0 Self Programming Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter1 Overflow Flag +TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag +TIFR.ICF1 3 Timer/Counter1, Input Capture Flag +TIFR.OCF0B 2 Timer/Counter0, Output Compare B Match Flag +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIFR.OCF0A 0 Timer/Counter0, Output Compare A Match Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.ICIE1 3 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE0A 2 Timer/Counter0, Output Compare A Match Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +TIMSK.OCIE0B 0 Timer/Counter0, Output Compare B Match Interrupt Enable +EIFR 0x003A External Interrupt Flag Register +EIFR.INTF1 7 External Interrupt Flag 1 +EIFR.INTF0 6 External Interrupt Flag 0 +EIFR.PCIF 5 Pin Change Interrupt Flag +GIMSK 0x003B External Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.PCIE 5 Pin Change Interrupt Request Enable +OCR0B 0x003C Output Compare Register B Low Byte +SPL 0x003D Stack Pointer Register Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 CarryFlag + + +.ATtiny2313A +SUBARCH=25 +; doc8246.pdf +; + +RAM=128 +ROM=2048 +EEPROM=128 + + +; MEMORY MAP +area DATA GPWR_ 0x0000:0x0020 General Purpose Working Registers +area DATA FSR_ 0x0020:0x0060 I/O registers +area DATA I_SRAM 0x0060:0x00E0 Internal SRAM + + +; Interrupt and reset vector assignments +entry __RESET 0x0000 Hardware Pin +entry INT0_ 0x0001 External Interrupt Request 0 +entry INT1_ 0x0002 External Interrupt Request 1 +entry TIMER1_CAPT 0x0003 Timer/Counter1 Capture Event +entry TIMER1_COMPA 0x0004 Timer/Counter1 Compare Match A +entry TIMER1_OVF 0x0005 Timer/Counter1 Overflow +entry TIMER0_OVF 0x0006 Timer/Counter0 Overflow +entry USART0_RX 0x0007 USART0, Rx Complete +entry USART0_UDRE 0x0008 USART0 Data Register Empty +entry USART0_TX 0x0009 USART0, Tx Complete +entry ANALOG_COMP 0x000A Analog Comparator +entry PCINT0 0x000B Pin Change Interrupt Request 0 +entry TIMER1_COMPB 0x000C Timer/Counter1 Compare Match B +entry TIMER0_COMPA 0x000D Timer/Counter0 Compare Match A +entry TIMER0_COMPB 0x000E Timer/Counter0 Compare Match B +entry USI_START 0x000F USI Start Condition +entry USI_OVERFLOW 0x0010 USI Overflow +entry EE_READY 0x0011 EEPROM Ready +entry WDT_OVERFLOW 0x0012 Watchdog Timer Overflow +entry PCINT1 0x0013 Pin Change Interrupt Request 1 +entry PCINT2 0x0014 Pin Change Interrupt Request 2 + + +; INPUT/OUTPUT PORTS +USIBR 0x0000 USI Buffer Register +DIDR 0x0001 Digital Input Disable Register +DIDR.AIND0 1 AIN0 Digital Input Disable +DIDR.AIND1 2 AIN1 Digital Input Disable +UBRRH 0x0002 USART Baud Rate Registers High +UCSRC 0x0003 USART Control and Status Register C +UCSRC.UMSEL1 7 USART Mode Select 1 +UCSRC.UMSEL0 6 USART Mode Select 0 +UCSRC.UPM1 5 Parity Mode 1 +UCSRC.UPM0 4 Parity Mode 0 +UCSRC.USBS 3 Stop Bit Select +UCSRC.UCSZ1 2 Character Size 1 +UCSRC.UCSZ0 1 Character Size 0 +UCSRC.UCPOL 0 Clock Polarity +PCMSK1 0x0004 Pin Change Mask Register 1 +PCMSK1.PCINT10 2 Pin Change Enable Mask 10 +PCMSK1.PCINT9 1 Pin Change Enable Mask 9 +PCMSK1.PCINT8 0 Pin Change Enable Mask 8 +PCMSK2 0x0005 Pin Change Mask Register 2 +PCMSK2.PCINT17 6 Pin Change Enable Mask 17 +PCMSK2.PCINT16 5 Pin Change Enable Mask 16 +PCMSK2.PCINT15 4 Pin Change Enable Mask 15 +PCMSK2.PCINT14 3 Pin Change Enable Mask 14 +PCMSK2.PCINT13 2 Pin Change Enable Mask 13 +PCMSK2.PCINT12 1 Pin Change Enable Mask 12 +PCMSK2.PCINT11 0 Pin Change Enable Mask 11 +PRR 0x0006 Power Reduction Register +PRR.PRTIM1 3 Power Reduction Timer/Counter1 +PRR.PRTIM0 2 Power Reduction Timer/Counter0 +PRR.PRUSI 1 Power Reduction USI +PRR.PRUSART 0 Power Reduction USART +BODCR 0x0007 Brown-Out Detector Control Register +BODCR.BODS 1 BOD Sleep +BODCR.BODSE 0 BOD Sleep Enable +ACSR 0x0008 Analog Comparator Control and Status Register +ACSR.ACD 7 Analog Comparator Disable +ACSR.ACBG 6 Analog Comparator Bandgap Select +ACSR.ACO 5 Analog Comparator Output +ACSR.ACI 4 Analog Comparator Interrupt Flag +ACSR.ACIE 3 Analog Comparator Interrupt Enable +ACSR.ACIC 2 Analog Comparator Input Capture Enable +ACSR.ACIS1 1 Analog Comparator Interrupt Mode Select 1 +ACSR.ACIS0 0 Analog Comparator Interrupt Mode Select 0 +UBRRL 0x0009 USART Baud Rate Register +UBRRL.UBRR7 7 +UBRRL.UBRR6 6 +UBRRL.UBRR5 5 +UBRRL.UBRR4 4 +UBRRL.UBRR3 3 +UBRRL.UBRR2 2 +UBRRL.UBRR1 1 +UBRRL.UBRR0 0 +UCSRB 0x000A USART Control and Status Register +UCSRB.RXCIE 7 RX Complete Interrupt Enable +UCSRB.TXCIE 6 TX Complete Interrupt Enable +UCSRB.UDRIE 5 USART Data Register Empty Interrupt Enable +UCSRB.RXEN 4 Receiver Enable +UCSRB.TXEN 3 Transmitter Enable +UCSRB.UCSZ2 2 Character Size +UCSRB.RXB8 1 Receive Data Bit 8 +UCSRB.TXB8 0 Transmit Data Bit8 +UCSRA 0x000B USART Control and Status Register +UCSRA.RXC 7 USART Receive Complete +UCSRA.TXC 6 USART Transmit Complete +UCSRA.UDRE 5 USART Data Register Empty +UCSRA.FE 4 Frame Error +UCSRA.DOR 3 Data OverRun +UCSRA.UPE 2 Parity Error +UCSRA.U2X 1 Double the USART Transmission Speed +UCSRA.MPCM 0 Multi-Processor Communication Mode +UDR 0x000C USART I/O Data Register +USICR 0x000D USI Control Register +USICR.USISIE 7 Start Condition Interrupt Enable +USICR.USIOIE 6 Counter Overflow Interrupt Enable +USICR.USIWM1 5 Wire Mode 1 +USICR.USIWM0 4 Wire Mode 0 +USICR.USICS1 3 Clock Source Select 1 +USICR.USICS0 2 Clock Source Select 0 +USICR.USICLK 1 Clock Strobe +USICR.USITC 0 Toggle Clock Port Pin +USISR 0x000E USI Status Register +USISR.USISIF 7 Start Condition Interrupt Flag +USISR.USIOIF 6 Counter Overflow Interrupt Flag +USISR.USIPF 5 Stop Condition Flag +USISR.USIDC 4 Data Output Collision +USISR.USICNT3 3 Counter Value 3 +USISR.USICNT2 2 Counter Value 2 +USISR.USICNT1 1 Counter Value 1 +USISR.USICNT0 0 Counter Value 0 +USIDR 0x000F USI Data Register +PIND 0x0010 Port D Input Pins Address +PIND.PIND7 7 +PIND.PIND6 6 +PIND.PIND5 5 +PIND.PIND4 4 +PIND.PIND3 3 +PIND.PIND2 2 +PIND.PIND1 1 +PIND.PIND0 0 +DDRD 0x0011 Port D Data Direction Register +DDRD.DDD7 7 Port D Data Direction Register bit 7 +DDRD.DDD6 6 Port D Data Direction Register bit 6 +DDRD.DDD5 5 Port D Data Direction Register bit 5 +DDRD.DDD4 4 Port D Data Direction Register bit 4 +DDRD.DDD3 3 Port D Data Direction Register bit 3 +DDRD.DDD2 2 Port D Data Direction Register bit 2 +DDRD.DDD1 1 Port D Data Direction Register bit 1 +DDRD.DDD0 0 Port D Data Direction Register bit 0 +PORTD 0x0012 Port D Data Register +PORTD.PORTD7 7 Port D Data Register bit 7 +PORTD.PORTD6 6 Port D Data Register bit 6 +PORTD.PORTD5 5 Port D Data Register bit 5 +PORTD.PORTD4 4 Port D Data Register bit 4 +PORTD.PORTD3 3 Port D Data Register bit 3 +PORTD.PORTD2 2 Port D Data Register bit 2 +PORTD.PORTD1 1 Port D Data Register bit 1 +PORTD.PORTD0 0 Port D Data Register bit 0 +GPIOR0 0x0013 General Purpose I/O Register 0 +GPIOR1 0x0014 General Purpose I/O Register 0 +GPIOR2 0x0015 General Purpose I/O Register 0 +PINB 0x0016 Port B Input Pins Address +PINB.PINB7 7 +PINB.PINB6 6 +PINB.PINB5 5 +PINB.PINB4 4 +PINB.PINB3 3 +PINB.PINB2 2 +PINB.PINB1 1 +PINB.PINB0 0 +DDRB 0x0017 Port B Data Direction Register +DDRB.DDB7 7 Port B Data Direction Register bit 7 +DDRB.DDB6 6 Port B Data Direction Register bit 6 +DDRB.DDB5 5 Port B Data Direction Register bit 5 +DDRB.DDB4 4 Port B Data Direction Register bit 4 +DDRB.DDB3 3 Port B Data Direction Register bit 3 +DDRB.DDB2 2 Port B Data Direction Register bit 2 +DDRB.DDB1 1 Port B Data Direction Register bit 1 +DDRB.DDB0 0 Port B Data Direction Register bit 0 +PORTB 0x0018 Port B Data Register +PORTB.PORTB7 7 Port B Data Register bit 7 +PORTB.PORTB6 6 Port B Data Register bit 6 +PORTB.PORTB5 5 Port B Data Register bit 5 +PORTB.PORTB4 4 Port B Data Register bit 4 +PORTB.PORTB3 3 Port B Data Register bit 3 +PORTB.PORTB2 2 Port B Data Register bit 2 +PORTB.PORTB1 1 Port B Data Register bit 1 +PORTB.PORTB0 0 Port B Data Register bit 0 +PINA 0x0019 Port A Input Pins Address +PINA.PINA7 7 +PINA.PINA6 6 +PINA.PINA5 5 +PINA.PINA4 4 +PINA.PINA3 3 +PINA.PINA2 2 +PINA.PINA1 1 +PINA.PINA0 0 +DDRA 0x001A Port A Data Direction Register +DDRA.DDA7 7 Port A Data Direction Register bit 7 +DDRA.DDA6 6 Port A Data Direction Register bit 6 +DDRA.DDA5 5 Port A Data Direction Register bit 5 +DDRA.DDA4 4 Port A Data Direction Register bit 4 +DDRA.DDA3 3 Port A Data Direction Register bit 3 +DDRA.DDA2 2 Port A Data Direction Register bit 2 +DDRA.DDA1 1 Port A Data Direction Register bit 1 +DDRA.DDA0 0 Port A Data Direction Register bit 0 +PORTA 0x001B Port A Data Register +PORTA.PORTA7 7 Port A Data Register bit 7 +PORTA.PORTA6 6 Port A Data Register bit 6 +PORTA.PORTA5 5 Port A Data Register bit 5 +PORTA.PORTA4 4 Port A Data Register bit 4 +PORTA.PORTA3 3 Port A Data Register bit 3 +PORTA.PORTA2 2 Port A Data Register bit 2 +PORTA.PORTA1 1 Port A Data Register bit 1 +PORTA.PORTA0 0 Port A Data Register bit 0 +EECR 0x001C EEPROM Control Register +EECR.EERIE 3 EEPROM Ready Interrupt Enable +EECR.EEMWE 2 EEPROM Master Write Enable +EECR.EEWE 1 EEPROM Write Enable +EECR.EERE 0 EEPROM Read Enable +EEDR 0x001D EEPROM Data Register +EEAR 0x001E EEPROM Address Register +EEAR.EEAR7 7 +EEAR.EEAR6 6 +EEAR.EEAR5 5 +EEAR.EEAR4 4 +EEAR.EEAR3 3 +EEAR.EEAR2 2 +EEAR.EEAR1 1 +EEAR.EEAR0 0 +RESERVED001F 0x001F RESERVED +PCMSK0 0x0020 Pin Change Mask Register 0 +PCMSK0.PCINT7 7 Pin Change Enable Mask 7 +PCMSK0.PCINT6 6 Pin Change Enable Mask 6 +PCMSK0.PCINT5 5 Pin Change Enable Mask 5 +PCMSK0.PCINT4 4 Pin Change Enable Mask 4 +PCMSK0.PCINT3 3 Pin Change Enable Mask 3 +PCMSK0.PCINT2 2 Pin Change Enable Mask 2 +PCMSK0.PCINT1 1 Pin Change Enable Mask 1 +PCMSK0.PCINT0 0 Pin Change Enable Mask 0 +WDTCSR 0x0021 Watchdog Timer Control Register +WDTCSR.WDIF 7 Watchdog Interrupt Flag +WDTCSR.WDIE 6 Watchdog Interrupt Enable +WDTCSR.WDP3 5 Watchdog Timer Prescaler 3 +WDTCSR.WDCE 4 Watchdog Change Enable +WDTCSR.WDE 3 Watchdog Enable +WDTCSR.WDP2 2 Watchdog Timer Prescaler 2 +WDTCSR.WDP1 1 Watchdog Timer Prescaler 1 +WDTCSR.WDP0 0 Watchdog Timer Prescaler 0 +TCCR1C 0x0022 Timer/Counter1 Control Register C +TCCR1C.FOC1A 7 Force Output Compare for Channel A +TCCR1C.FOC1B 6 Force Output Compare for Channel B +GTCCR 0x0023 General Timer/Counter Control Register +GTCCR.PSR10 1 Prescaler Reset Timer/Counter1 and Timer/Counter0 +ICR1L 0x0024 Input Capture Register Low Byte +ICR1H 0x0025 Input Capture Register High Byte +CLKPR 0x0026 Clock Prescale Register +CLKPR.CPCE 7 Clock Prescaler Change Enable +CLKPR.CLKPS3 3 Clock Prescaler Select Bit 3 +CLKPR.CLKPS2 2 Clock Prescaler Select Bit 2 +CLKPR.CLKPS1 1 Clock Prescaler Select Bit 1 +CLKPR.CLKPS0 0 Clock Prescaler Select Bit 0 +RESERVED0027 0x0027 RESERVED +OCR1BL 0x0028 Output Compare Register B Low Byte +OCR1BH 0x0029 Output Compare Register B High Byte +OCR1AL 0x002A Output Compare Register A Low Byte +OCR1AH 0x002B Output Compare Register A High Byte +TCNT1L 0x002C Counter Register Low Byte +TCNT1H 0x002D Counter Register High Byte +TCCR1B 0x002E Timer/Counter1 Control Register B +TCCR1B.ICNC1 7 Input Capture Noise Canceler +TCCR1B.ICES1 6 Input CaptureEdgeSelect +TCCR1B.WGM13 4 Waveform Generation Mode 3 +TCCR1B.WGM12 3 Waveform Generation Mode 2 +TCCR1B.CS12 2 Clock Select 2 +TCCR1B.CS11 1 Clock Select 1 +TCCR1B.CS10 0 Clock Select 0 +TCCR1A 0x002F Timer/Counter1 Control Register A +TCCR1A.COM1A1 7 Compare Output Mode for Channel A 1 +TCCR1A.COM1A0 6 Compare Output Mode for Channel A 0 +TCCR1A.COM1B1 5 Compare Output Mode for Channel B 1 +TCCR1A.COM1B0 4 Compare Output Mode for Channel B 0 +TCCR1A.WGM11 1 Waveform Generation Mode 1 +TCCR1A.WGM10 0 Waveform Generation Mode 0 +TCCR0A 0x0030 Timer/Counter0 Control Register A +TCCR0A.COM0A1 7 Compare Output Mode for Channel A 1 +TCCR0A.COM0A0 6 Compare Output Mode for Channel A 0 +TCCR0A.COM0B1 5 Compare Output Mode for Channel B 1 +TCCR0A.COM0B0 4 Compare Output Mode for Channel B 0 +TCCR0A.WGM01 1 Waveform Generation Mode 1 +TCCR0A.WGM00 0 Waveform Generation Mode 0 +OSCCAL 0x0031 Oscillator Calibration Register +OSCCAL.CAL6 6 Oscillator Calibration Value 6 +OSCCAL.CAL5 5 Oscillator Calibration Value 5 +OSCCAL.CAL4 4 Oscillator Calibration Value 4 +OSCCAL.CAL3 3 Oscillator Calibration Value 3 +OSCCAL.CAL2 2 Oscillator Calibration Value 2 +OSCCAL.CAL1 1 Oscillator Calibration Value 1 +OSCCAL.CAL0 0 Oscillator Calibration Value 0 +TCNT0 0x0032 Timer/Counter0 +TCCR0B 0x0033 Timer/Counter Control Register +TCCR0B.FOC0A 7 Force Output Compare A +TCCR0B.FOC0B 6 Force Output Compare B +TCCR0B.WGM02 3 Waveform Generation Mode +TCCR0B.CS02 2 Clock Select 2 +TCCR0B.CS01 1 Clock Select 1 +TCCR0B.CS00 0 Clock Select 0 +MCUCSR 0x0034 MCU Control and Status Register +MCUCSR.WDRF 3 Watchdog Reset Flag +MCUCSR.BORF 2 Brown-out Reset Flag +MCUCSR.EXTRF 1 External Reset Flag +MCUCSR.PORF 0 Power-On Reset Flag +MCUCR 0x0035 MCU Control Register +MCUCR.PUD 7 Pull-up Disable +MCUCR.SM1 6 Sleep Mode Select Bit 1 +MCUCR.SE 5 SleepEnable +MCUCR.SM0 4 Sleep Mode Select Bit 0 +MCUCR.ISC11 3 Interrupt Sense Control 1 Bit 1 +MCUCR.ISC10 2 Interrupt Sense Control 1 Bit 0 +MCUCR.ISC01 1 Interrupt Sense Control 0 Bit 1 +MCUCR.ISC00 0 Interrupt Sense Control 0 Bit 0 +OCR0A 0x0036 Timer/Counter0 Compare Register A +SPMCSR 0x0037 Store Program Memory Control Register +SPMCSR.RSIG 5 Read Device Signature Imprint Table +SPMCSR.CTPB 4 Clear Temporary Page Buffer +SPMCSR.RFLB 3 Read Fuse and Lock Bits +SPMCSR.PGWRT 2 Page Write +SPMCSR.PGERS 1 Page Erase +SPMCSR.SPMEN 0 Self Programming Enable +TIFR 0x0038 Timer/Counter Interrupt Flag Register +TIFR.TOV1 7 Timer/Counter1 Overflow Flag +TIFR.OCF1A 6 Timer/Counter1, Output Compare A Match Flag +TIFR.OCF1B 5 Timer/Counter1, Output Compare B Match Flag +TIFR.ICF1 3 Timer/Counter1, Input Capture Flag +TIFR.OCF0B 2 Timer/Counter0, Output Compare B Match Flag +TIFR.TOV0 1 Timer/Counter0 Overflow Flag +TIFR.OCF0A 0 Timer/Counter0, Output Compare A Match Flag +TIMSK 0x0039 Timer/Counter Interrupt Mask Register +TIMSK.TOIE1 7 Timer/Counter1, Overflow Interrupt Enable +TIMSK.OCIE1A 6 Timer/Counter1, Output Compare A Match Interrupt Enable +TIMSK.OCIE1B 5 Timer/Counter1, Output Compare B Match Interrupt Enable +TIMSK.ICIE1 3 Timer/Counter1, Input Capture Interrupt Enable +TIMSK.OCIE0A 2 Timer/Counter0, Output Compare A Match Interrupt Enable +TIMSK.TOIE0 1 Timer/Counter0 Overflow Interrupt Enable +TIMSK.OCIE0B 0 Timer/Counter0, Output Compare B Match Interrupt Enable +EIFR 0x003A External Interrupt Flag Register +EIFR.INTF1 7 External Interrupt Flag 1 +EIFR.INTF0 6 External Interrupt Flag 0 +EIFR.PCIF0 5 Pin Change Interrupt Flag 0 +EIFR.PCIF2 4 Pin Change Interrupt Flag 2 +EIFR.PCIF1 3 Pin Change Interrupt Flag 1 +GIMSK 0x003B External Interrupt Mask Register +GIMSK.INT1 7 External Interrupt Request 1 Enable +GIMSK.INT0 6 External Interrupt Request 0 Enable +GIMSK.PCIE0 5 Pin Change Interrupt Request Enable 0 +GIMSL.PCIE2 4 Pin Change Interrupt Request Enable 2 +GIMSL.PCIE1 3 Pin Change Interrupt Request Enable 1 +OCR0B 0x003C Output Compare Register B Low Byte +SPL 0x003D Stack Pointer Register Low +SPL.SP7 7 +SPL.SP6 6 +SPL.SP5 5 +SPL.SP4 4 +SPL.SP3 3 +SPL.SP2 2 +SPL.SP1 1 +SPL.SP0 0 +RESERVED003E 0x003E RESERVED +SREG 0x003F Status Register +SREG.I 7 Global Interrupt Enable +SREG.T 6 Bit Copy Storage +SREG.H 5 Half Carry Flag +SREG.S 4 Sign Bit +SREG.V 3 Two's Complement Overflow Flag +SREG.N 2 Negative Flag +SREG.Z 1 Zero Flag +SREG.C 0 CarryFlag diff --git a/idasdk76/module/avr/avr.hpp b/idasdk76/module/avr/avr.hpp new file mode 100644 index 0000000..5150b12 --- /dev/null +++ b/idasdk76/module/avr/avr.hpp @@ -0,0 +1,136 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#ifndef _AVR_HPP +#define _AVR_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include <fixup.hpp> +#include "../iohandler.hpp" +#include "../../ldr/elf/elfr_avr.h" +extern int data_id; + +#define PROCMOD_NAME avr +#define PROCMOD_NODE_NAME AVR_INFO_NODENAME + +//--------------------------------- +// Operand types: + +enum phrase_t ENUM_SIZE(uint16) +{ + PH_X, // X + PH_XPLUS, // X+ + PH_MINUSX, // -X + PH_Y, // Y + PH_YPLUS, // Y+ + PH_MINUSY, // -Y + PH_Z, // Z + PH_ZPLUS, // Z+ + PH_MINUSZ, // -Z +}; + + +#define reg_pair specflag1 // o_reg: operand is 16bit a register pair (even register is in op.reg) +#define o_port o_idpspec0 // port number in x.addr + +//------------------------------------------------------------------ +enum RegNo +{ + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, R11, R12, R13, R14, R15, + R16, R17, R18, R19, R20, R21, R22, R23, + R24, R25, R26, R27, R28, R29, R30, R31, + rVcs, rVds, // virtual registers for code and data segments +}; + +//------------------------------------------------------------------ +void idaapi avr_segend(outctx_t &ctx, segment_t *seg); +void idaapi avr_assumes(outctx_t &ctx); // function to produce assume directives + +int idaapi is_align_insn(ea_t ea); + +//------------------------------------------------------------------ +struct avr_iohandler_t : public iohandler_t +{ + struct avr_t ± + avr_iohandler_t(avr_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual const char *iocallback(const ioports_t &iop, const char *line) override; + virtual bool entry_processing(ea_t &, const char * /*word*/, const char * /*cmt*/) override; + virtual bool check_ioresp() const override; +}; + +DECLARE_PROC_LISTENER(idb_listener_t, struct avr_t); + +struct avr_t : public procmod_t +{ + netnode helper; + avr_iohandler_t ioh = avr_iohandler_t(*this, helper); + idb_listener_t idb_listener = idb_listener_t(*this); + + //-------------------------------------------------------------------------- + // not tested + fixup_handler_t cfh_avr16 = + { + sizeof(fixup_handler_t), + "AVR16", // Format name, must be unique + 0, // props + 2, 16, 0, 0, // size, width, shift + REFINFO_CUSTOM, // reftype + nullptr, // apply, will be inited in processor_t::ev_init + NULL, // get_value + NULL, // patch_value + }; + fixup_type_t cfh_avr16_id = 0; + int ref_avr16_id = 0; + + int subarch = 0; + + // memory configuration + ea_t ram = BADADDR; + uint32 ramsize = 0; + uint32 romsize = 0; + uint32 eepromsize = 0; + + bool imageFile = false; + bool nonBinary = false; + + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const ioport_t *find_port(ea_t address); + const char *find_bit(ea_t address, size_t bit); + void setup_avr_device(int resp_info); + const char *set_idp_options( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded); + bool set_param_by_arch(void); + bool is_possible_subarch(int addr) const; + + void handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload); + int emu(const insn_t &insn); + + void avr_header(outctx_t &ctx); + + inline void opimm(const insn_t &insn, op_t &x, int value) const; + inline uint32 code_address(const insn_t &insn, signed int delta) const; + int ana(insn_t *_insn); + + void avr_segstart(outctx_t &ctx, segment_t *Sarea) const; + void avr_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; + +#endif // _AVR_HPP diff --git a/idasdk76/module/avr/emu.cpp b/idasdk76/module/avr/emu.cpp new file mode 100644 index 0000000..9b71381 --- /dev/null +++ b/idasdk76/module/avr/emu.cpp @@ -0,0 +1,170 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#include "avr.hpp" +#include "../../ldr/elf/elfr_avr.h" + +//------------------------------------------------------------------------ +static void set_immd_bit(const insn_t &insn, int n) +{ + set_immd(insn.ea); + if ( is_defarg(get_flags(insn.ea), n) ) + return; + switch ( insn.itype ) + { + case AVR_andi: + case AVR_ori: + op_num(insn.ea, n); + } +} + +//---------------------------------------------------------------------- +void avr_t::handle_operand(const insn_t &insn, const op_t &x, bool isforced, bool isload) +{ + switch ( x.type ) + { + case o_reg: + case o_phrase: + break; + case o_imm: + if ( !isload ) + goto WRONG_CALL; + set_immd_bit(insn, x.n); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, dr_O, OOF_SIGNED); + break; + case o_displ: + set_immd_bit(insn, x.n); + if ( !isforced && op_adds_xrefs(get_flags(insn.ea), x.n) ) + { + int outf = OOF_ADDR|OOFS_NEEDSIGN|OOFW_32; + ea_t ea = insn.add_off_drefs(x, isload ? dr_R : dr_W, outf); + if ( ea != BADADDR ) + insn.create_op_data(ea, x); + } + break; + case o_near: + { + cref_t ftype = fl_JN; + ea_t ea = to_ea(insn.cs, x.addr); + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + if ( !func_does_return(ea) ) + flow = false; + ftype = fl_CN; + } + insn.add_cref(ea, x.offb, ftype); + } + break; + case o_port: + if ( ram != BADADDR ) + { + ea_t ea = ram + x.addr; + if ( subarch < E_AVR_MACH_TINY ) + ea += 0x20; // skip 32 mapped GPRs for legacy archs + if ( x.type == o_port ) + { // verify that the calculated address corresponds to the register name + const ioport_t *port = find_port(x.addr); + if ( port == NULL || port->name.empty() ) + break; + ea_t rev = get_name_ea(BADADDR, port->name.c_str()); + if ( rev != ea ) + break; + } + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + } + break; + case o_mem: + { + ea_t ea = map_data_ea(insn, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + } + break; + default: +WRONG_CALL: + if ( insn.itype != AVR_lpm && insn.itype != AVR_elpm ) + warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); + break; + } +} + +//---------------------------------------------------------------------- +static bool may_be_skipped(const insn_t &insn) +{ + ea_t ea = insn.ea - 1; + if ( is_code(get_flags(ea)) ) + { + int code = get_wide_byte(ea); + switch ( code & 0xFC00 ) + { +// 0001 00rd dddd rrrr cpse rd, rr 4 Compare, Skip if Equal + case 0x1000: +// 1111 110r rrrr xbbb sbrc rr, b Skip if Bit in I/O Register Cleared +// 1111 111r rrrr xbbb sbrs rr, b Skip if Bit in I/O Register Set + case 0xFC00: + return true; +// 1001 1001 pppp pbbb sbic p, b Skip if Bit in Register Cleared +// 1001 1011 pppp pbbb sbis p, b Skip if Bit in Register Set + case 0x9800: + return (code & 0x0100) != 0; + } + } + return false; +} + +//---------------------------------------------------------------------- + +int avr_t::emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + bool flag3 = is_forced_operand(insn.ea, 2); + + flow = (Feature & CF_STOP) == 0; + + if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true); + if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true); + if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true); + + if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false); + if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false); + if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false); + +// +// Determine if the next instruction should be executed +// + if ( !flow ) + flow = may_be_skipped(insn); + if ( segtype(insn.ea) == SEG_XTRN ) + flow = false; + if ( flow ) + add_cref(insn.ea,insn.ea+insn.size, fl_F); + + return 1; +} + +//---------------------------------------------------------------------- +int idaapi is_align_insn(ea_t ea) +{ + insn_t insn; + decode_insn(&insn, ea); + switch ( insn.itype ) + { + case AVR_mov: + if ( insn.Op1.reg == insn.Op2.reg ) + break; + default: + return 0; + case AVR_nop: + break; + } + return insn.size; +} diff --git a/idasdk76/module/avr/ins.cpp b/idasdk76/module/avr/ins.cpp new file mode 100644 index 0000000..8681b5c --- /dev/null +++ b/idasdk76/module/avr/ins.cpp @@ -0,0 +1,150 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#include "avr.hpp" + +const instruc_t Instructions[] = +{ + + { "", 0 }, // Unknown Operation + + // ARITHMETIC AND LOGIC INSTRUCTIONS + { "add", CF_USE1|CF_USE2|CF_CHG1 }, // Add without Carry + { "adc", CF_USE1|CF_USE2|CF_CHG1 }, // Add with Carry + { "adiw", CF_USE1|CF_USE2|CF_CHG1 }, // Add Immediate to Word + { "sub", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract without Carry + { "subi", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract Immediate + { "sbc", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract with Carry + { "sbci", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract Immediate with Carry + { "sbiw", CF_USE1|CF_USE2|CF_CHG1 }, // Subtract Immediate from Word + { "and", CF_USE1|CF_USE2|CF_CHG1 }, // Logical AND + { "andi", CF_USE1|CF_USE2|CF_CHG1 }, // Logical AND with Immediate + { "or", CF_USE1|CF_USE2|CF_CHG1 }, // Logical OR + { "ori", CF_USE1|CF_USE2|CF_CHG1 }, // Logical OR with Immediate + { "eor", CF_USE1|CF_USE2|CF_CHG1 }, // Exclusive OR + { "com", CF_USE1| CF_CHG1 }, // One's Complement + { "neg", CF_USE1| CF_CHG1 }, // Two's Complement + { "sbr", CF_USE1|CF_USE2|CF_CHG1 }, // Set Bit(s) in Register + { "cbr", CF_USE1|CF_USE2|CF_CHG1 }, // Clear Bit(s) in Register + { "inc", CF_USE1| CF_CHG1 }, // Increment + { "dec", CF_USE1| CF_CHG1 }, // Decrement + { "tst", CF_USE1| CF_CHG1 }, // Test for Zero or Minus + { "clr", CF_CHG1 }, // Clear Register + { "ser", CF_CHG1 }, // Set Register + { "cp", CF_USE1|CF_USE2 }, // Compare + { "cpc", CF_USE1|CF_USE2 }, // Compare with Carry + { "cpi", CF_USE1|CF_USE2 }, // Compare with Immediate + { "mul", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply + + // BRANCH INSTRUCTIONS + { "rjmp", CF_USE1|CF_STOP }, // Relative Jump + { "ijmp", CF_STOP|CF_JUMP }, // Indirect Jump to (Z) + { "jmp", CF_USE1|CF_STOP }, // Jump + { "rcall", CF_USE1 |CF_CALL }, // Relative Call Subroutine + { "icall", CF_JUMP|CF_CALL }, // Indirect Call to (Z) + { "call", CF_USE1 |CF_CALL }, // Call Subroutine + { "ret", CF_STOP }, // Subroutine Return + { "reti", CF_STOP }, // Interrupt Return + { "cpse", CF_USE1|CF_USE2 }, // Compare", Skip if Equal + { "sbrc", CF_USE1|CF_USE2 }, // Skip if Bit in Register Cleared + { "sbrs", CF_USE1|CF_USE2 }, // Skip if Bit in Register Set + { "sbic", CF_USE1|CF_USE2 }, // Skip if Bit in I/O Register Cleared + { "sbis", CF_USE1|CF_USE2 }, // Skip if Bit in I/O Register Set + { "brbs", CF_USE1|CF_USE2 }, // Branch if Status Flag Set + { "brbc", CF_USE1|CF_USE2 }, // Branch if Status Flag Cleared + { "breq", CF_USE1 }, // Branch if Equal + { "brne", CF_USE1 }, // Branch if Not Equal + { "brcs", CF_USE1 }, // Branch if Carry Set + { "brcc", CF_USE1 }, // Branch if Carry Cleared + { "brsh", CF_USE1 }, // Branch if Same or Higher + { "brlo", CF_USE1 }, // Branch if Lower + { "brmi", CF_USE1 }, // Branch if Minus + { "brpl", CF_USE1 }, // Branch if Plus + { "brge", CF_USE1 }, // Branch if Greater or Equal + { "brlt", CF_USE1 }, // Branch if Less Than + { "brhs", CF_USE1 }, // Branch if Half Carry Flag Set + { "brhc", CF_USE1 }, // Branch if Half Carry Flag Cleared + { "brts", CF_USE1 }, // Branch if T Flag Set + { "brtc", CF_USE1 }, // Branch if T Flag Cleared + { "brvs", CF_USE1 }, // Branch if Overflow Flag is Set + { "brvc", CF_USE1 }, // Branch if Overflow Flag is Cleared + { "brie", CF_USE1 }, // Branch if Interrupt Enabled + { "brid", CF_USE1 }, // Branch if Interrupt Disabled + + // DATA TRANSFER INSTRUCTIONS + { "mov", CF_CHG1|CF_USE2 }, // Copy Register + { "ldi", CF_CHG1|CF_USE2 }, // Load Immediate + { "lds", CF_CHG1|CF_USE2 }, // Load Direct + { "ld", CF_CHG1|CF_USE2 }, // Load Indirect + { "ldd", CF_CHG1|CF_USE2 }, // Load Indirect with Displacement + { "sts", CF_CHG1|CF_USE2 }, // Store Direct to SRAM + { "st", CF_USE1|CF_USE2 }, // Store Indirect + { "std", CF_USE1|CF_USE2 }, // Store Indirect with Displacement + { "lpm", CF_USE1|CF_USE2|CF_CHG1 }, // Load Program Memory + { "in", CF_CHG1|CF_USE2 }, // In Port + { "out", CF_USE1|CF_USE2 }, // Out Port + { "push", CF_USE1 }, // Push Register on Stack + { "pop", CF_CHG1 }, // Pop Register from Stack + + // BIT AND BIT-TEST INSTRUCTIONS + { "lsl", CF_USE1|CF_CHG1 }, // Logical Shift Left + { "lsr", CF_USE1|CF_CHG1 }, // Logical Shift Right + { "rol", CF_USE1|CF_CHG1 }, // Rotate Left Through Carry + { "ror", CF_USE1|CF_CHG1 }, // Rotate Right Through Carry + { "asr", CF_USE1|CF_CHG1 }, // Arithmetic Shift Right + { "swap", CF_USE1|CF_CHG1 }, // Swap Nibbles + { "bset", CF_USE1 }, // Flag Set + { "bclr", CF_USE1 }, // Flag Clear + { "sbi", CF_USE1|CF_USE2 }, // Set Bit in I/O Register + { "cbi", CF_USE1|CF_USE2 }, // Clear Bit in I/O Register + { "bst", CF_USE1|CF_USE2 }, // Bit Store from Register to T + { "bld", CF_USE1|CF_USE2 }, // Bit load from T to Register + { "sec", 0 }, // Set Carry + { "clc", 0 }, // Clear Carry + { "sen", 0 }, // Set Negative Flag + { "cln", 0 }, // Clear Negative Flag + { "sez", 0 }, // Set Zero Flag + { "clz", 0 }, // Clear Zero Flag + { "sei", 0 }, // Global Interrupt Enable + { "cli", 0 }, // Global Interrupt Disable + { "ses", 0 }, // Set Signed Test Flag + { "cls", 0 }, // Clear Signed Test Flag + { "sev", 0 }, // Set Two's Complement Overflow + { "clv", 0 }, // Clear Two's Complement Overflow + { "set", 0 }, // Set T in SREG + { "clt", 0 }, // Clear T in SREG + { "seh", 0 }, // Set Half Carry Flag in SREG + { "clh", 0 }, // Clear Half Carry Flag in SREG + { "nop", 0 }, // No Operation + { "sleep", 0 }, // Sleep + { "wdr", 0 }, // Watchdog Reset + + // New MegaAVR instructions + { "elpm", CF_USE2|CF_CHG1 }, // Extended Load Program Memory + { "espm", 0 }, // Extended Store Program Memory + { "fmul", CF_USE1|CF_USE2|CF_CHG1 }, // Fractional Multiply Unsigned + { "fmuls", CF_USE1|CF_USE2|CF_CHG1 }, // Fractional Multiply Signed + { "fmulsu", CF_USE1|CF_USE2|CF_CHG1 }, // Fractional Multiply Signed with Unsigned + { "movw", CF_USE1|CF_USE2|CF_CHG1 }, // Copy Register Word + { "muls", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply Signed + { "mulsu", CF_USE1|CF_USE2|CF_CHG1 }, // Multiply Signed with Unsigned + { "spm", 0 }, // Store Program Memory + { "eicall", 0 }, // Extended Indirect Call to Subroutine + { "eijmp", 0 }, // Extended Indirect Jump + + // New XMega instructions + { "des", CF_USE1 }, // Data Encryption Standard + { "lac", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Load And Clear + { "las", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Load And Set + { "lat", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Load And Toggle + { "xch", CF_USE1|CF_USE2|CF_CHG1|CF_CHG2 }, // Exchange +}; + +CASSERT(qnumber(Instructions) == AVR_last); diff --git a/idasdk76/module/avr/ins.hpp b/idasdk76/module/avr/ins.hpp new file mode 100644 index 0000000..0566394 --- /dev/null +++ b/idasdk76/module/avr/ins.hpp @@ -0,0 +1,157 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + +AVR_null = 0, // Unknown Operation + +// ARITHMETIC AND LOGIC INSTRUCTIONS +AVR_add, // Add without Carry +AVR_adc, // Add with Carry +AVR_adiw, // Add Immediate to Word +AVR_sub, // Subtract without Carry +AVR_subi, // Subtract Immediate +AVR_sbc, // Subtract with Carry +AVR_sbci, // Subtract Immediate with Carry +AVR_sbiw, // Subtract Immediate from Word +AVR_and, // Logical AND +AVR_andi, // Logical AND with Immediate +AVR_or, // Logical OR +AVR_ori, // Logical OR with Immediate +AVR_eor, // Exclusive OR +AVR_com, // One's Complement +AVR_neg, // Two's Complement +AVR_sbr, // Set Bit(s) in Register +AVR_cbr, // Clear Bit(s) in Register +AVR_inc, // Increment +AVR_dec, // Decrement +AVR_tst, // Test for Zero or Minus +AVR_clr, // Clear Register +AVR_ser, // Set Register +AVR_cp, // Compare +AVR_cpc, // Compare with Carry +AVR_cpi, // Compare with Immediate +AVR_mul, // Multiply + +// BRANCH INSTRUCTIONS +AVR_rjmp, // Relative Jump +AVR_ijmp, // Indirect Jump to (Z) +AVR_jmp, // Jump +AVR_rcall, // Relative Call Subroutine +AVR_icall, // Indirect Call to (Z) +AVR_call, // Call Subroutine +AVR_ret, // Subroutine Return +AVR_reti, // Interrupt Return +AVR_cpse, // Compare, Skip if Equal +AVR_sbrc, // Skip if Bit in Register Cleared +AVR_sbrs, // Skip if Bit in Register Set +AVR_sbic, // Skip if Bit in I/O Register Cleared +AVR_sbis, // Skip if Bit in I/O Register Set +AVR_brbs, // Branch if Status Flag Set +AVR_brbc, // Branch if Status Flag Cleared +AVR_breq, // Branch if Equal +AVR_brne, // Branch if Not Equal +AVR_brcs, // Branch if Carry Set +AVR_brcc, // Branch if Carry Cleared +AVR_brsh, // Branch if Same or Higher +AVR_brlo, // Branch if Lower +AVR_brmi, // Branch if Minus +AVR_brpl, // Branch if Plus +AVR_brge, // Branch if Greater or Equal +AVR_brlt, // Branch if Less Than +AVR_brhs, // Branch if Half Carry Flag Set +AVR_brhc, // Branch if Half Carry Flag Cleared +AVR_brts, // Branch if T Flag Set +AVR_brtc, // Branch if T Flag Cleared +AVR_brvs, // Branch if Overflow Flag is Set +AVR_brvc, // Branch if Overflow Flag is Cleared +AVR_brie, // Branch if Interrupt Enabled +AVR_brid, // Branch if Interrupt Disabled + +// DATA TRANSFER INSTRUCTIONS +AVR_mov, // Copy Register +AVR_ldi, // Load Immediate +AVR_lds, // Load Direct +AVR_ld, // Load Indirect +AVR_ldd, // Load Indirect with Displacement +AVR_sts, // Store Direct to SRAM +AVR_st, // Store Indirect +AVR_std, // Store Indirect with Displacement +AVR_lpm, // Load Program Memory +AVR_in, // In Port +AVR_out, // Out Port +AVR_push, // Push Register on Stack +AVR_pop, // Pop Register from Stack + +// BIT AND BIT-TEST INSTRUCTIONS +AVR_lsl, // Logical Shift Left +AVR_lsr, // Logical Shift Right +AVR_rol, // Rotate Left Through Carry +AVR_ror, // Rotate Right Through Carry +AVR_asr, // Arithmetic Shift Right +AVR_swap, // Swap Nibbles +AVR_bset, // Flag Set +AVR_bclr, // Flag Clear +AVR_sbi, // Set Bit in I/O Register +AVR_cbi, // Clear Bit in I/O Register +AVR_bst, // Bit Store from Register to T +AVR_bld, // Bit load from T to Register +AVR_sec, // Set Carry +AVR_clc, // Clear Carry +AVR_sen, // Set Negative Flag +AVR_cln, // Clear Negative Flag +AVR_sez, // Set Zero Flag +AVR_clz, // Clear Zero Flag +AVR_sei, // Global Interrupt Enable +AVR_cli, // Global Interrupt Disable +AVR_ses, // Set Signed Test Flag +AVR_cls, // Clear Signed Test Flag +AVR_sev, // Set Two's Complement Overflow +AVR_clv, // Clear Two's Complement Overflow +AVR_set, // Set T in SREG +AVR_clt, // Clear T in SREG +AVR_seh, // Set Half Carry Flag in SREG +AVR_clh, // Clear Half Carry Flag in SREG +AVR_nop, // No Operation +AVR_sleep, // Sleep +AVR_wdr, // Watchdog Reset + +// New MegaAVR instructions + +AVR_elpm, // Extended Load Program Memory +AVR_espm, // Extended Store Program Memory +AVR_fmul, // Fractional Multiply Unsigned +AVR_fmuls, // Fractional Multiply Signed +AVR_fmulsu, // Fractional Multiply Signed with Unsigned +AVR_movw, // Copy Register Word +AVR_muls, // Multiply Signed +AVR_mulsu, // Multiply Signed with Unsigned +AVR_spm, // Store Program Memory +AVR_eicall, // Extended Indirect Call to Subroutine +AVR_eijmp, // Extended Indirect Jump + +// New XMega instructions + +AVR_des, // Data Encryption Standard +AVR_lac, // Load And Clear +AVR_las, // Load And Set +AVR_lat, // Load And Toggle +AVR_xch, // Exchange + +AVR_last, + + }; + +#endif diff --git a/idasdk76/module/avr/makefile b/idasdk76/module/avr/makefile new file mode 100644 index 0000000..daf55f7 --- /dev/null +++ b/idasdk76/module/avr/makefile @@ -0,0 +1,63 @@ +PROC=avr +CONFIGS=avr.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../../ldr/elf/elfbase.h \ + ../idaidp.hpp ../iohandler.hpp \ + ana.cpp avr.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../../ldr/elf/elfbase.h \ + ../idaidp.hpp ../iohandler.hpp \ + avr.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../../ldr/elf/elfbase.h \ + ../idaidp.hpp ../iohandler.hpp \ + avr.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../../ldr/elf/elfbase.h \ + ../idaidp.hpp ../iohandler.hpp \ + avr.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \ + ../../ldr/elf/elfbase.h \ + ../idaidp.hpp ../iohandler.hpp avr.hpp ins.hpp \ + notify_codes.hpp reg.cpp diff --git a/idasdk76/module/avr/notify_codes.hpp b/idasdk76/module/avr/notify_codes.hpp new file mode 100644 index 0000000..3f7829d --- /dev/null +++ b/idasdk76/module/avr/notify_codes.hpp @@ -0,0 +1,34 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __AVR_NOTIFY_CODES_HPP +#define __AVR_NOTIFY_CODES_HPP + +#include <idp.hpp> + +//---------------------------------------------------------------------- +// The following events are supported by the AVR module in the ph.notify() function +namespace avr_module_t +{ + enum event_codes_t + { + ev_set_machine_type = processor_t::ev_loader, + // elf-loader 'set machine type' and file type + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline void set_machine_type(int subarch, bool image_file) + { + processor_t::notify(idp_ev(ev_set_machine_type), subarch, image_file); + } +} + +#endif // __AVR_NOTIFY_CODES_HPP diff --git a/idasdk76/module/avr/out.cpp b/idasdk76/module/avr/out.cpp new file mode 100644 index 0000000..eb62067 --- /dev/null +++ b/idasdk76/module/avr/out.cpp @@ -0,0 +1,257 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#include "avr.hpp" +#include "../../ldr/elf/elfr_avr.h" + +//---------------------------------------------------------------------- +class out_avr_t : public outctx_t +{ + void out_regop(const op_t &x); + out_avr_t(void) = delete; // not used +public: + void out_phrase(int phn); + void out_bad_address(ea_t addr); + + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_avr_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_avr_t) + +//---------------------------------------------------------------------- +void out_avr_t::out_phrase(int phn) +{ + switch ( phn ) + { + case PH_XPLUS: // X+ + out_register("X"); + out_symbol('+'); + break; + case PH_MINUSX: // -X + out_symbol('-'); + case PH_X: // X + out_register("X"); + break; + case PH_YPLUS: // Y+ + out_register("Y"); + out_symbol('+'); + break; + case PH_MINUSY: // -Y + out_symbol('-'); + case PH_Y: // Y + out_register("Y"); + break; + case PH_ZPLUS: // Z+ + out_register("Z"); + out_symbol('+'); + break; + case PH_MINUSZ: // -Z + out_symbol('-'); + case PH_Z: // Z + out_register("Z"); + break; + default: + error("%a: bad phrase number", insn.ea); + } +} + +//---------------------------------------------------------------------- +void out_avr_t::out_bad_address(ea_t addr) +{ + out_tagon(COLOR_ERROR); + out_btoa(addr, 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); +} + +void out_avr_t::out_regop(const op_t &x) +{ + avr_t &pm = *static_cast<avr_t *>(procmod); + qstring name; + // for legacy architectures, try to get SRAM name if available + if ( x.reg_pair + || pm.ram == BADADDR || pm.subarch >= E_AVR_MACH_TINY + || get_visible_name(&name, pm.ram+x.reg) <= 0 ) + { + // no name or reg pair: use standard reg name + name = ph.reg_names[x.reg]; + if ( x.reg_pair ) + { + switch ( x.reg ) + { + case R26: name = "X"; break; + case R28: name = "Y"; break; + case R30: name = "Z"; break; + default: + // r1:r2 + out_register(name.begin()); + out_symbol(':'); + name = ph.reg_names[x.reg+1]; + break; + } + } + } + out_register(name.begin()); +} +//---------------------------------------------------------------------- +bool out_avr_t::out_operand(const op_t &x) +{ + avr_t &pm = *static_cast<avr_t *>(procmod); + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + out_regop(x); + break; + + case o_imm: + { + if ( insn.itype == AVR_cbi + || insn.itype == AVR_sbic + || insn.itype == AVR_sbi + || insn.itype == AVR_sbis ) + { + const char *bit = pm.find_bit(insn.Op1.addr, (size_t)x.value); + if ( bit != NULL && bit[0] != '\0' ) + { + out_line(bit, COLOR_REG); + break; + } + } + if ( x.specflag1 && is_off1(F) && !is_invsign(insn.ea, F, 1) ) + out_symbol('-'); + int flags = OOFS_IFSIGN|OOFW_8; + if ( insn.itype == AVR_subi || insn.itype == AVR_sbci ) + flags |= OOF_SIGNED; + out_value(x, flags); + } + break; + + case o_near: + { + ea_t ea = to_ea(insn.cs, x.addr); + if ( !out_name_expr(x, ea, x.addr) ) + out_bad_address(x.addr); + } + break; + + case o_mem: + { + ea_t ea = map_data_ea(insn, x); + if ( !out_name_expr(x, ea, x.addr) ) + out_bad_address(x.addr); + } + break; + + case o_phrase: + out_phrase(x.phrase); + break; + + case o_displ: + out_phrase(x.phrase); + out_value(x, OOF_ADDR|OOFS_NEEDSIGN|OOFW_32); + break; + + case o_port: + { + const ioport_t *port = pm.find_port(x.addr); + if ( port != NULL && !port->name.empty() ) + out_register(port->name.c_str()); + else + out_bad_address(x.addr); + } + break; + + default: + warning("out: %a: bad optype %d", insn.ea, x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +void out_avr_t::out_insn(void) +{ + avr_t &pm = *static_cast<avr_t *>(procmod); + // output .org for enties without any labels + if ( !has_any_name(F) && pm.helper.altval_ea(insn.ea) ) + { + char buf[MAXSTR]; + btoa(buf, sizeof(buf), insn.ip); + int saved_flags = forbid_annotations(); + gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + restore_ctxflags(saved_flags); + } + + out_mnemonic(); + + out_one_operand(0); + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Sarea) could be made const +void avr_t::avr_segstart(outctx_t &ctx, segment_t *Sarea) const +{ + if ( is_spec_segm(Sarea->type) ) + return; + qstring sname; + qstring sclas; + get_visible_segm_name(&sname, Sarea); + get_segm_class(&sclas, Sarea); + ctx.gen_printf(0, + COLSTR("%s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), + sclas == "CODE" + ? ".CSEG" + : sclas == "DATA" + ? ".DSEG" + : ".ESEG", + ash.cmnt, + sname.c_str()); + if ( Sarea->orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), Sarea->orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +void idaapi avr_segend(outctx_t &, segment_t *) +{ +} + +//-------------------------------------------------------------------------- +void avr_t::avr_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); +} + +//-------------------------------------------------------------------------- +void avr_t::avr_footer(outctx_t &ctx) const +{ + qstring name = get_visible_name(inf_get_start_ea()); + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), + ash.end, ash.cmnt, name.c_str()); +} diff --git a/idasdk76/module/avr/reg.cpp b/idasdk76/module/avr/reg.cpp new file mode 100644 index 0000000..d5087c9 --- /dev/null +++ b/idasdk76/module/avr/reg.cpp @@ -0,0 +1,803 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Atmel AVR - 8-bit RISC processor + * + */ + +#include "avr.hpp" +#include <segregs.hpp> +#include <diskio.hpp> +#include <loader.hpp> +#include <fixup.hpp> +#include "notify_codes.hpp" +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "XL", "XH", "YL", "YH", "ZL", "ZH", + "cs","ds", // virtual registers for code and data segments +}; + +//----------------------------------------------------------------------- +// AVR assembler +//----------------------------------------------------------------------- +static const char *const avr_header[] = +{ + ".equ XL, 26", + ".equ XH, 27", + ".equ YL, 28", + ".equ YH, 29", + ".equ ZL, 30", + ".equ ZH, 31", + NULL +}; + +static const asm_t avrasm = +{ + AS_COLON|AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF0|AS_ONEDUP, + 0, + "AVR Assembler", + 0, + avr_header, // header lines + ".org", // org + ".exit", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".dw", // word directive + ".dd", // double words + NULL, // no qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".byte %s", // uninited arrays + ".equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + NULL, // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + NULL, // "public" name keyword + NULL, // "weak" name keyword + NULL, // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + NULL, // "align" keyword + '(', ')', // lbrace, rbrace + NULL, // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &avrasm, NULL }; + +//-------------------------------------------------------------------------- +static const char cfgname[] = "avr.cfg"; + +//-------------------------------------------------------------------------- +bool avr_iohandler_t::entry_processing(ea_t &ea1, const char * /*word*/, const char * /*cmt*/) +{ + pm.helper.altset_ea(ea1, 1); + create_insn(ea1); + ea_t ea = get_first_fcref_from(ea1); + if ( ea != BADADDR ) + ea1 = ea; + return false; // continue processing +} + +//-------------------------------------------------------------------------- +bool avr_iohandler_t::check_ioresp() const +{ + return inf_like_binary() || pm.imageFile; +} + +//-------------------------------------------------------------------------- +bool avr_t::is_possible_subarch(int addr) const +{ + // old version of gcc-arm don't use 31/51/etc subarches - only 3/5/... :( + // maybe make option? + return subarch == 0 || subarch == addr || (addr/10 == subarch); +} + +//-------------------------------------------------------------------------- +const char *avr_iohandler_t::iocallback(const ioports_t &_ports, const char *line) +{ + int addr; + char word[MAXSTR]; + word[MAXSTR-1] = '\0'; + CASSERT(MAXSTR == 1024); + if ( qsscanf(line, "%1023[^=] = %d", word, &addr) == 2 ) + { + if ( streq(word, "RAM") ) + { + pm.ramsize = addr; + return NULL; + } + if ( streq(word, "ROM") ) + { + pm.romsize = addr >> 1; + return NULL; + } + if ( streq(word, "EEPROM") ) + { + pm.eepromsize = addr; + return NULL; + } + if ( streq(word, "SUBARCH") ) + { + // set pm.subarch based on SUBARCH in the config file + // it is needed to do XMEGA specific things for non-elf files + pm.subarch = addr; + return pm.is_possible_subarch(addr) ? NULL : IOPORT_SKIP_DEVICE; + } + } + return standard_callback(_ports, line); +} + +//-------------------------------------------------------------------------- +struct avr_ioport_parser_t : public choose_ioport_parser_t +{ + avr_t ± + + avr_ioport_parser_t(avr_t &_pm) : pm(_pm) {} + virtual bool parse(qstring *, const char *line) override + { + int addr; + char word[MAXSTR]; + word[MAXSTR-1] = '\0'; + CASSERT(MAXSTR == 1024); + bool skip = qsscanf(line, "%1023[^=] = %d", word, &addr) == 2 + && strcmp(word, "SUBARCH") == 0 + && !pm.is_possible_subarch(addr); + return !skip; + } +}; + +//-------------------------------------------------------------------------- +const ioport_t *avr_t::find_port(ea_t address) +{ + return find_ioport(ioh.ports, address); +} + +//-------------------------------------------------------------------------- +const char *avr_t::find_bit(ea_t address, size_t bit) +{ + const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit); + return b ? b->name.c_str() : NULL; +} + +//-------------------------------------------------------------------------- +void avr_t::setup_avr_device(int resp_info) +{ + if ( !choose_ioport_device(&ioh.device, cfgname) ) + return; + + ioh.set_device_name(ioh.device.c_str(), resp_info); + if ( get_first_seg() == NULL ) // set processor options before load file + return; + plan_range(0, BADADDR); // reanalyze program + + // resize the ROM segment + { + segment_t *s = getseg(node2ea(helper.altval(-1))); + if ( s == NULL ) + s = get_first_seg(); // for the old databases + if ( s != NULL ) //-V547 's != 0' is always true + { + if ( s->size() > romsize ) + warning("The input file is bigger than the ROM size of the current device"); + set_segm_end(s->start_ea, s->start_ea+romsize, SEGMOD_KILL); + } + } + // resize the RAM segment + { + segment_t *s = get_segm_by_name("RAM"); + if ( s == NULL && ramsize != 0 ) + { + ea_t start = (inf_get_max_ea() + 0xFFFFF) & ~0xFFFFF; + add_segm(start>>4, start, start+ramsize, "RAM", "DATA"); + s = getseg(start); + } + ram = BADADDR; + if ( s != NULL ) + { + int i; + // offset added to I/O port address to get RAM address + int ram_offset = 0; + ram = s->start_ea; + set_segm_end(ram, ram+ramsize, SEGMOD_KILL); + + if ( subarch < E_AVR_MACH_TINY ) + { + // legacy devices start with 32 GPRs + // 0x20 needs to be added to the port address + ram_offset = 0x20; + // set register names for aliases in data memory + for ( i=0; i < 32; i++ ) + if ( !has_any_name(get_flags(ram+i)) ) + set_name(ram+i, register_names[i], SN_NODUMMY); + } + + // set I/O port names + for ( i=0; i < ioh.ports.size(); i++ ) + { + const ioport_t &p = ioh.ports[i]; + set_name(ram+p.address+ram_offset, p.name.c_str(), SN_NODUMMY); + set_cmt(ram+p.address+ram_offset, p.cmt.c_str(), true); + } + } + } +} + +//-------------------------------------------------------------------------- +const char *avr_t::set_idp_options( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded) +{ + if ( keyword == NULL ) + { + setup_avr_device(IORESP_INT); + return IDPOPT_OK; + } + else if ( strcmp(keyword, "AVR_MCPU") == 0 ) + { + if ( value_type != IDPOPT_STR ) + return IDPOPT_BADTYPE; + + ioh.device = (const char *) value; + if ( idb_loaded ) + ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); + return IDPOPT_OK; + } + + return IDPOPT_BADKEY; +} + +//-------------------------------------------------------------------------- +bool avr_t::set_param_by_arch(void) +{ + int max_rom, max_ram, max_eeprom; + // preset MAXIMUM's of memory size's by mcpu subtype + switch ( subarch ) + { + default: + subarch = 0; + return false; // LOGICAL ERROR? + + // at90s1200, attiny10, attiny11, attiny12, attiny15, attiny28 + case E_AVR_MACH_AVR1: // ROM<=1k + max_rom = 1024; + max_ram = 32; + max_eeprom = 64; + break; + // at90s2313, at90s2323, at90s2333, at90s2343, attiny22, attiny26, + // at90s4414 /* XXX -> 8515 */, at90s4433, at90s4434 /* XXX -> 8535 */, + // at90s8515, at90c8534, at90s8535 + case E_AVR_MACH_AVR2: // ROM<=8k + // attiny13, attiny13a, attiny2313, attiny24, attiny44, attiny84, + // attiny25, attiny45, attiny85, attiny261, attiny461, attiny861, + // attiny43u, attiny48, attiny88, at86rf401 + // PASS THRU + case E_AVR_MACH_AVR25: // ROM<=8k + max_rom = 8*1024; + max_ram = 512; + max_eeprom = 512; + break; + // at43usb355, at76c711 + case E_AVR_MACH_AVR3: // ROM>=8k<=64k + max_rom = 64*1024; + max_ram = 1024; + max_eeprom = 0; + break; + // atmega103, at43usb320, + case E_AVR_MACH_AVR31: // ROM>=65k&&<=128k, (RAM=65k, EEPROM=4k) + max_rom = 128*1024; + max_ram = 4*1024; + max_eeprom = 4*1024; + break; + // attiny167, at90usb82, at90usb162 + case E_AVR_MACH_AVR35: // ROM>=8k&&<=64k, + max_rom = 64*1024; + max_ram = 512; + max_eeprom = 512; + break; + // atmega8, atmega48, atmega48p, atmega88, atmega88p, atmega8515, + // atmega8535, atmega8hva, at90pwm1, at90pwm2, at90pwm2b, at90pwm3, + // at90pwm3b + case E_AVR_MACH_AVR4: // ROM<=8k + max_rom = 8*1024; + max_ram = 1024; + max_eeprom = 512; + break; + // atmega16, atmega161, atmega162, atmega163, atmega164p, atmega165, + // atmega165p, atmega168, atmega168p, atmega169, atmega169p, atmega32, + // atmega323, atmega324p, atmega325, atmega325p, atmega3250, atmega3250p, + // atmega328p, atmega329, atmega329p, atmega3290, atmega3290p, atmega406, + // atmega64, atmega640, atmega644, atmega644p, atmega645, atmega649, + // atmega6450, atmega6490, atmega16hva, at90can32, at90can64, at90pwm216, + // at90pwm316, atmega32c1, atmega32m1, atmega32u4, at90usb646, at90usb647, + // at94k + case E_AVR_MACH_AVR5: // ROM>=8k&&<=64k + max_rom = 64*1024; + max_ram = 4*1024; + max_eeprom = 2*1024; + break; + // atmega128, atmega1280, atmega1281, atmega1284p, + // at90can128, at90usb1286, at90usb1287 + case E_AVR_MACH_AVR51: // ROM=128k + max_rom = 128*1024; + max_ram = 16*1024; + max_eeprom = 4*1024; + break; + // atmega2560, atmega2561 + case E_AVR_MACH_AVR6: // ROM=256k (3-byte pc -- is supported?) + max_rom = 256*1024; + max_ram = 8*1024; + max_eeprom = 4*1024; + break; + case E_AVR_MACH_XMEGA1: // ROM < 8K, ram=? + max_rom = 8*1024; + max_ram = 1024; + max_eeprom = 512; + break; + // ATxmega16A4, ATxmega16D4, ATxmega32D4 + case E_AVR_MACH_XMEGA2: // 8K < FLASH <= 64K, RAM <= 64K + max_rom = 64*1024; + max_ram = 64*1024; + max_eeprom = 1024; + break; + // ATxmega32A4 + case E_AVR_MACH_XMEGA3: // 8K < FLASH <= 64K, RAM > 64K + max_rom = 64*1024; + max_ram = 128*1024; // ? + max_eeprom = 1024; + break; + // ATxmega64A3, ATxmega64D3 + case E_AVR_MACH_XMEGA4: // 64K < FLASH <= 128K, RAM <= 64K + max_rom = 128*1024; + max_ram = 64*1024; + max_eeprom = 2048; + break; + // ATxmega64A1 + case E_AVR_MACH_XMEGA5: // 64K < FLASH <= 128K, RAM > 64K + max_rom = 128*1024; + max_ram = 128*1024; + max_eeprom = 2048; + break; + // ATxmega128A3, ATxmega128D3, ATxmega192A3, ATxmega192D3, + // ATxmega256A3B, ATxmega256A3, ATxmega256D3 + case E_AVR_MACH_XMEGA6: // 128K < FLASH <= 256K, RAM <= 64K + max_rom = 256*1024; + max_ram = 64*1024; + max_eeprom = 4096; + break; + // ATxmega128A1 + case E_AVR_MACH_XMEGA7: // 128K < FLASH <= 256K, RAM > 64K + max_rom = 256*1024; + max_ram = 128*1024; + max_eeprom = 4096; + break; + } + avr_ioport_parser_t parser(*this); + if ( !choose_ioport_device2(&ioh.device, cfgname, &parser) ) + { + ioh.device.sprnt("avr%d", subarch); + ioh.device[sizeof("avrX")-1] = '\0'; + romsize = max_rom >> 1; + ramsize = max_ram; + eepromsize = max_eeprom; + } + else + { + ioh.set_device_name(ioh.device.c_str(), IORESP_INT); + plan_range(0, BADADDR); // reanalyze program + } + return true; +} + +//-------------------------------------------------------------------------- +static inline ea_t get16bit(ea_t ea) +{ + if ( segtype(ea) == SEG_CODE ) + return get_wide_byte(ea); + + return get_word(ea); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case idb_event::segm_added: + { + segment_t *s = va_arg(va, segment_t *); + qstring sclass; + if ( get_segm_class(&sclass, s) > 0 && sclass == "DATA" ) + set_default_dataseg(s->sel); + } + break; + + case idb_event::segm_moved: // A segment is moved + // Fix processor dependent address sensitive information + { + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + asize_t size = va_arg(va, asize_t); + //bool changed_netmap = va_argi(va, bool); + + nodeidx_t ndx1 = ea2node(from); + nodeidx_t ndx2 = ea2node(to); + pm.helper.altshift(ndx1, ndx2, size); // move address information + } + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +static bool idaapi avr16_apply( + const fixup_handler_t *fh, + ea_t item_ea, + ea_t fixup_ea, + int opnum, + bool /*is_macro*/, + const fixup_data_t &fd) +{ + avr_t &pm = *GET_MODULE_DATA(avr_t); + if ( !pm.nonBinary + || fd.has_base() + || fd.is_unused() + || fd.displacement != 0 ) + { + msg("%a: Unexpected or incorrect CUSTOM_FIXUP\n", fixup_ea); + return false; + } + + if ( is_unknown(get_flags(item_ea)) ) + create_16bit_data(item_ea, 2); + + refinfo_t ri; + ri.flags = fh->reftype; + ri.base = fd.get_base(); + ri.target = ri.base + fd.off; + ri.tdelta = fd.displacement; + op_offset_ex(item_ea, opnum, &ri); + return true; +} + +//-------------------------------------------------------------------------- +//lint -e{818} could be declared const +static int idaapi avr16_gen_expr( + qstring * /*buf*/, + qstring * /*format*/, + ea_t ea, + int numop, + const refinfo_t &ri, + ea_t /*from*/, + adiff_t *opval, + ea_t * /*target*/, + ea_t * /*fullvalue*/, + int /*getn_flags*/) +{ + avr_t &pm = *GET_MODULE_DATA(avr_t); + if ( !pm.nonBinary + || numop != 0 + || ri.type() == (pm.ref_avr16_id | REFINFO_CUSTOM) + || ri.tdelta != 0 + || ri.target == BADADDR + || *opval != get16bit(ea) ) + { + msg("%a: Unexpected or incorrect CUSTOM offset\n", ea); + return 0; + } + return 3; // process as a regular fixup +} + +//-------------------------------------------------------------------------- +static const custom_refinfo_handler_t ref_avr16 = +{ + sizeof(custom_refinfo_handler_t), + "AVR16", + "AVR 16-bit offset", + 0, // properties (currently 0) + avr16_gen_expr, // gen_expr + NULL, // calc_reference_data + NULL, // get_format +}; + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(avr_t)); + return 0; +} + +//---------------------------------------------------------------------- +void avr_t::load_from_idb() +{ + ioh.restore_device(); + segment_t *s = get_segm_by_name("RAM"); + if ( s != NULL ) + ram = s->start_ea; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi avr_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + hook_event_listener(HT_IDB, &idb_listener, &LPH); + cfh_avr16.apply = avr16_apply; + cfh_avr16_id = register_custom_fixup(&cfh_avr16); + ref_avr16_id = register_custom_refinfo(&ref_avr16); + cfh_avr16.reftype = REFINFO_CUSTOM | ref_avr16_id; + break; + + case processor_t::ev_term: + cfh_avr16.reftype = REFINFO_CUSTOM; + unregister_custom_refinfo(ref_avr16_id); + unregister_custom_fixup(cfh_avr16_id); + unhook_event_listener(HT_IDB, &idb_listener); + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case avr_module_t::ev_set_machine_type: // elf-loader 'set machine type' and file type + subarch = va_arg(va, int); + imageFile = va_argi(va, bool); + nonBinary = true; + break; + + case processor_t::ev_newfile: // new file loaded + // remember the ROM segment + { + segment_t *s = get_first_seg(); + if ( s != NULL ) + { + if ( subarch == 0 ) + set_segm_name(s, "ROM"); + helper.altset(-1, ea2node(s->start_ea)); + } + } + if ( subarch != 0 && set_param_by_arch() ) + break; + setup_avr_device(/*IORESP_AREA|*/IORESP_INT); // allow the user to select the device + if ( subarch != 0 ) + break; + // create additional segments + { + ea_t start = (inf_get_max_ea() + 0xFFFFF) & ~0xFFFFF; + if ( eepromsize != 0 ) + { + char *file = ask_file(false, "*.bin", "Please enter the binary EEPROM image file"); + if ( file != NULL ) + { + add_segm(start>>4, start, start+eepromsize, "EEPROM", "DATA"); + linput_t *li = open_linput(file, false); + if ( li != NULL ) + { + uint64 size = qlsize(li); + if ( size > eepromsize ) + size = eepromsize; + file2base(li, 0, start, start+size, FILEREG_NOTPATCHABLE); + close_linput(li); + } + } + } + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + break; + + case processor_t::ev_newasm: // new assembler type + break; + + case processor_t::ev_out_label: // The kernel is going to generate an instruction + // label line or a function header + { + outctx_t *ctx = va_arg(va, outctx_t *); + if ( helper.altval_ea(ctx->insn_ea) ) // if entry point + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), ctx->insn_ea); + ctx->gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + avr_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + avr_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + avr_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + avr_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +// 1001 0101 0xx0 1000 ret +// 1001 0101 0xx1 1000 reti +static const uchar retcode_1[] = { 0x08, 0x95 }; // ret +static const uchar retcode_2[] = { 0x18, 0x95 }; // reti +static const uchar retcode_3[] = { 0x28, 0x95 }; // ret +static const uchar retcode_4[] = { 0x38, 0x95 }; // reti +static const uchar retcode_5[] = { 0x48, 0x95 }; // ret +static const uchar retcode_6[] = { 0x58, 0x95 }; // reti +static const uchar retcode_7[] = { 0x68, 0x95 }; // ret +static const uchar retcode_8[] = { 0x78, 0x95 }; // reti + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { sizeof(retcode_4), retcode_4 }, + { sizeof(retcode_5), retcode_5 }, + { sizeof(retcode_6), retcode_6 }, + { sizeof(retcode_7), retcode_7 }, + { sizeof(retcode_8), retcode_8 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +#define FAMILY "Atmel AVR series:" + +static const char *const shnames[] = +{ + "AVR", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Atmel AVR", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_AVR, // id + // flag + PRN_HEX + | PR_RNAMESOK, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 16, // 16 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + rVcs, // first + rVds, // last + 0, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + AVR_null, + AVR_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + AVR_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/c39/ana.cpp b/idasdk76/module/c39/ana.cpp new file mode 100644 index 0000000..0ca11bb --- /dev/null +++ b/idasdk76/module/c39/ana.cpp @@ -0,0 +1,442 @@ +/* + * Rockwell C39 processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "c39.hpp" + +/* +Operand types: +1) none +2) Register a, x, y +3) address $xx address may be 8 or 16 bits +4) indirect address ($xx) address of the cell with the target address +5) immediate #$xx constant +6) label Label target label of the jump +*/ + +//---------------------------------------------------------------------- +// current byte(s) is immediate data, 1 byte +static void SetImmData(op_t &op, uchar code) +{ + op.type = o_imm; + // always in the second byte + op.offb = 1; + // element size + op.dtype = dt_byte; + // value + op.addr = op.value = code; + // it can't be an offset! + op.flags |= OF_NUMBER; // only number +} + +//---------------------------------------------------------------------- +// registres are considered byte-sized +static void SetReg(op_t &op, uchar reg_n) +{ + op.type = o_reg; // only register + op.reg = reg_n; // register number + op.dtype = dt_byte; // size is always 8 bits +} + +//---------------------------------------------------------------------- +// memory cell +static void SetMemVar(op_t &op, ushort addr) +{ + op.type = o_mem; + op.addr = op.value = addr; + op.dtype = dt_word; +} + +//---------------------------------------------------------------------- +// memory cell with an address +static void SetMemVarI(op_t &op, ushort addr) +{ + op.type = o_mem; + op.specflag1 |= URR_IND; + op.addr = op.value = addr; + op.dtype = dt_word; +} + +//---------------------------------------------------------------------- +// relative branch +static void SetRelative(const insn_t &insn, op_t &op, signed char disp) +{ + op.type = o_near; + op.dtype = dt_word; + op.offb = 1; // in fact, not always... + // calculate indirect value + op.addr = op.value = insn.ip + insn.size + (int32)disp; +} + +//---------------------------------------------------------------------- +// absolute branch +static void SetAbs(op_t &op, unsigned short disp) +{ + op.type = o_near; + op.dtype = dt_word; + op.offb = 1; // in fact, not always... + // calculate final value + op.addr = op.value = disp; +} + +//---------------------------------------------------------------------- +// analyzer +int idaapi C39_ana(insn_t *_insn) +{ + static const uchar Dt[] = + { + C39_brk, C39_ora, C39_mpy, C39_tip, 0, C39_ora, C39_asl, C39_rmb, // 00 + C39_php, C39_ora, C39_asl, C39_jsb, C39_jpi, C39_ora, C39_asl, C39_bbr, // 08 + + C39_bpl, C39_ora, C39_mpa, C39_lab, 0, C39_ora, C39_asl, C39_rmb, // 10 + C39_clc, C39_ora, C39_neg, C39_jsb, 0, C39_ora, C39_asl, C39_bbr, // 18 + + C39_jsr, C39_and, C39_psh, C39_phw, C39_bit, C39_and, C39_rol, C39_rmb, // 20 + C39_plp, C39_and, C39_rol, C39_jsb, C39_bit, C39_and, C39_rol, C39_bbr, // 28 + + C39_bmi, C39_and, C39_pul, C39_plw, 0, C39_and, C39_rol, C39_rmb, // 30 + C39_sec, C39_and, C39_asr, C39_jsb, 0, C39_and, C39_rol, C39_bbr, // 38 + + C39_rti, C39_eor, C39_rnd, 0, 0, C39_eor, C39_lsr, C39_rmb, // 40 + C39_pha, C39_eor, C39_lsr, C39_jsb, C39_jmp, C39_eor, C39_lsr, C39_bbr, // 48 + + C39_bvc, C39_eor, C39_clw, 0, 0, C39_eor, C39_lsr, C39_rmb, // 50 + C39_cli, C39_eor, C39_phy, C39_jsb, 0, C39_eor, C39_lsr, C39_bbr, // 58 + + C39_rts, C39_adc, C39_taw, 0, C39_add, C39_adc, C39_ror, C39_rmb, // 60 + C39_pla, C39_adc, C39_ror, C39_jsb, C39_jmp, C39_adc, C39_ror, C39_bbr, // 68 + + C39_bvs, C39_adc, C39_twa, 0, C39_add, C39_adc, C39_ror, C39_rmb, // 70 + C39_sei, C39_adc, C39_ply, C39_jsb, C39_jmp, C39_adc, C39_ror, C39_bbr, // 78 + + C39_bra, C39_sta, 0, 0, C39_sty, C39_sta, C39_stx, C39_smb, // 80 + C39_dey, C39_add, C39_txa, C39_nxt, C39_sty, C39_sta, C39_stx, C39_bbs, // 88 + + C39_bcc, C39_sta, 0, 0, C39_sty, C39_sta, C39_stx, C39_smb, // 90 + C39_tya, C39_sta, C39_txs, C39_lii, 0, C39_sta, 0, C39_bbs, // 98 + + C39_ldy, C39_lda, C39_ldx, 0, C39_ldy, C39_lda, C39_ldx, C39_smb, // A0 + C39_tay, C39_lda, C39_tax, C39_lan, C39_ldy, C39_lda, C39_ldx, C39_bbs, // A8 + + C39_bcs, C39_lda, C39_sti, 0, C39_ldy, C39_lda, C39_ldx, C39_smb, // B0 + C39_clv, C39_lda, C39_tsx, C39_ini, C39_ldy, C39_lda, C39_ldx, C39_bbs, // B8 + + + C39_cpy, C39_cmp, C39_rba, 0, C39_cpy, C39_cmp, C39_dec, C39_smb, // C0 + C39_iny, C39_cmp, C39_dex, C39_phi, C39_cpy, C39_cmp, C39_dec, C39_bbs, // C8 + + C39_bne, C39_cmp, C39_sba, 0, C39_exc, C39_cmp, C39_dec, C39_smb, // D0 + C39_cld, C39_cmp, C39_phx, C39_pli, 0, C39_cmp, C39_dec, C39_bbs, // D8 + + C39_cpx, C39_sbc, C39_bar, 0, C39_cpx, C39_sbc, C39_inc, C39_smb, // E0 + C39_inx, C39_sbc, C39_nop, C39_lai, C39_cpx, C39_sbc, C39_inc, C39_bbs, // E8 + + C39_beq, C39_sbc, C39_bas, 0, 0, C39_sbc, C39_inc, C39_smb, // F0 + C39_sed, C39_sbc, C39_plx, C39_pia, 0, C39_sbc, C39_inc, C39_bbs // F8 + }; + + // get instruction byte + insn_t &insn = *_insn; + uchar code = insn.get_next_byte(); + // get instruction code + insn.itype = Dt[code]; + // analyze instruction type + switch ( insn.itype ) + { + // unknown instruction + case 0: + return 0; + // smb/rmb + case C39_smb: + case C39_rmb: + SetImmData(insn.Op1, (code>>4) & 7); + SetMemVar(insn.Op2, insn.get_next_byte()); + break; + // bbs/bbr + case C39_bbs: + case C39_bbr: + SetImmData(insn.Op1, (code>>4)&7); + SetMemVar(insn.Op2, insn.get_next_byte()); + SetRelative(insn, insn.Op3, insn.get_next_byte()); + break; + + // bpl/bmi/bvc/bvs/bra/bcc/bcs/bne/beq + case C39_beq: + case C39_bne: + case C39_bcs: + case C39_bcc: + case C39_bra: + case C39_bvs: + case C39_bvc: + case C39_bmi: + case C39_bpl: + SetRelative(insn, insn.Op1, insn.get_next_byte()); + break; + + // jsb + case C39_jsb: + SetMemVar(insn.Op1,0xFFE0+((code>>4) & 7)*2); + break; + + // ora, and, eor, adc, sta, lda, cmp, sbc + case C39_sbc: + case C39_cmp: + case C39_lda: + case C39_sta: + case C39_adc: + case C39_eor: + case C39_and: + case C39_ora: + switch ( code&0x1E ) + { + // 01 - xxx ($b) + case 0x00: + SetMemVarI(insn.Op1, insn.get_next_byte()); + break; + // 05 - xxx $b + case 0x04: + SetMemVar(insn.Op1, insn.get_next_byte()); + break; + // 09 - xxx #$b + case 0x08: + SetImmData(insn.Op1, insn.get_next_byte()); + break; + // 0D - xxx $w + case 0x0C: + SetMemVar(insn.Op1, insn.get_next_word()); + break; + // 11 - xxx ($b), x + case 0x10: + SetMemVarI(insn.Op1, insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + // 15 - xxx $b, x + case 0x14: + SetMemVar(insn.Op1, insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + // 19 - xxx $w, y + case 0x18: + SetMemVar(insn.Op1, insn.get_next_word()); + SetReg(insn.Op2,rY); + break; + // 1d - xxx $w, x + case 0x1C: + SetMemVar(insn.Op1, insn.get_next_word()); + SetReg(insn.Op2,rX); + break; + } + break; + + // asl, rol, lsr, ror, asr + case C39_asr: // this one has a single variant (asr a) + case C39_ror: + case C39_lsr: + case C39_rol: + case C39_asl: + switch ( code & 0x1C ) + { + // 6 - xxx $b + case 0x04: + SetMemVar(insn.Op1, insn.get_next_byte()); + break; + // A - xxx a + case 0x08: + SetReg(insn.Op1,rA); + break; + // E - xxx $w + case 0x0C: + SetMemVar(insn.Op1, insn.get_next_word()); + break; + // 16 - xxx $b, x + case 0x14: + SetMemVar(insn.Op1, insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + // 1E - xxx $w, x + case 0x1C: + SetMemVar(insn.Op1, insn.get_next_word()); + SetReg(insn.Op2,rX); + break; + } + break; + + // inc, dec + case C39_dec: + case C39_inc: + switch ( code&0x18 ) + { + // e6 - xxx $b + case 0x00: + SetMemVar(insn.Op1, insn.get_next_byte()); + break; + // ee - xxx $w + case 0x08: + SetMemVar(insn.Op1, insn.get_next_word()); + break; + // f6 - xxx $b, x + case 0x10: + SetMemVar(insn.Op1, insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + // fe - xxx $w, x + case 0x18: + SetMemVar(insn.Op1, insn.get_next_word()); + SetReg(insn.Op2,rX); + break; + } + break; + + // rba/sba $b, $w + case C39_rba: + case C39_sba: + SetImmData(insn.Op1, insn.get_next_byte()); + SetMemVar(insn.Op2, insn.get_next_word()); + break; + + // cpy/cpx + case C39_cpx: + case C39_cpy: + switch ( code & 0x1C ) + { + // a0 - xxx #$b + case 0x00: + SetImmData(insn.Op1, insn.get_next_byte()); + break; + // a4 - xxx $b + case 0x04: + SetMemVar(insn.Op1, insn.get_next_byte()); + break; + // ac - xxx $w + case 0x0C: + SetMemVar(insn.Op1, insn.get_next_word()); + break; + // 14 - xxx $b, x + case 0x14: + SetMemVar(insn.Op1, insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + // 1C - xxx $w, x + case 0x1C: + SetMemVar(insn.Op1, insn.get_next_word()); + SetReg(insn.Op2,rX); + break; + } + break; + + // lab/neg + case C39_neg: + case C39_lab: + SetReg(insn.Op1,rA); + break; + + // jpi ($w) + case C39_jpi: + SetMemVarI(insn.Op1, insn.get_next_word()); + break; + + // jsr $w + case C39_jsr: + SetAbs(insn.Op1, insn.get_next_word()); + break; + + // bar/bas $w, $b ,$rel + case C39_bar: + case C39_bas: + SetMemVar(insn.Op1, insn.get_next_word()); + SetImmData(insn.Op2, insn.get_next_byte()); + SetRelative(insn, insn.Op3, insn.get_next_byte()); + break; + + // bit + case C39_bit: + if ( code & 8 ) + SetMemVar(insn.Op1, insn.get_next_word()); // bit $w + else + SetMemVar(insn.Op1, insn.get_next_byte()); // bit $b + break; + + // jmp + case C39_jmp: + switch ( code ) + { + case 0x4C: + SetAbs(insn.Op1, insn.get_next_word()); + break; + case 0x6C: + SetMemVarI(insn.Op1, insn.get_next_word()); + break; + case 0x7C: + SetMemVarI(insn.Op1, insn.get_next_word()); + SetReg(insn.Op2, rX); + break; + } + break; + + // sti + case C39_sti: + SetImmData(insn.Op1,insn.get_next_byte()); + SetMemVar(insn.Op2,insn.get_next_byte()); + break; + + // exc + case C39_exc: + SetMemVar(insn.Op1,insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + + // add + case C39_add: + switch ( code ) + { + case 0x64: + SetMemVar(insn.Op1,insn.get_next_byte()); + break; + case 0x74: + SetMemVar(insn.Op1,insn.get_next_byte()); + SetReg(insn.Op2,rX); + break; + case 0x89: + SetImmData(insn.Op1,insn.get_next_byte()); + break; + } + break; + + // sty + case C39_stx: + case C39_ldx: + case C39_ldy: + case C39_sty: + switch ( code & 0x1C ) + { + // A0 xxx #$b + case 0x00: + SetImmData(insn.Op1,insn.get_next_byte()); + break; + // A4 xxx $b + case 0x04: + SetMemVar(insn.Op1,insn.get_next_byte()); + break; + // AC xxx $w + case 0x0C: + SetMemVar(insn.Op1,insn.get_next_word()); + break; + // B4 xxx $b, x + case 0x14: + SetMemVar(insn.Op1,insn.get_next_byte()); + SetReg(insn.Op2, + insn.itype == C39_sty || insn.itype == C39_ldy ? rX : rY); + break; + // BC xxx $w, x + case 0x1C: + SetMemVar(insn.Op1,insn.get_next_word()); + SetReg(insn.Op2, + insn.itype == C39_sty || insn.itype == C39_ldy ? rX : rY); + break; + } + break; + } + return insn.size; +} diff --git a/idasdk75/module/c39/c39.cfg b/idasdk76/module/c39/c39.cfg similarity index 100% rename from idasdk75/module/c39/c39.cfg rename to idasdk76/module/c39/c39.cfg diff --git a/idasdk76/module/c39/c39.hpp b/idasdk76/module/c39/c39.hpp new file mode 100644 index 0000000..9c33691 --- /dev/null +++ b/idasdk76/module/c39/c39.hpp @@ -0,0 +1,72 @@ +/* + * Rockwell C39 processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#ifndef _C39_HPP +#define _C39_HPP + +#include <ida.hpp> +#include <idp.hpp> + +#include "../idaidp.hpp" +#define near +#define far +#include "ins.hpp" +#include "../iohandler.hpp" + +// ============================================================ +// aditional bits for specflags1 (specflag2 not used) +//----------------------------------------------- +// additional bits for memory access +#define URR_IND (0x01) // indirect via a register + +//------------------------------------------------------------------------ +// list of processor registers +#ifdef _MSC_VER +#define ENUM8BIT : uint8 +#else +#define ENUM8BIT +#endif +enum C39_registers ENUM8BIT +{ + rNULLReg, + rA, + rX, rY, + rVcs, rVds +}; + +//------------------------------------------------------------------------ +int idaapi C39_ana(insn_t *insn); +int idaapi C39_emu(const insn_t &insn); +void idaapi C39_data(outctx_t &ctx, bool analyze_only); + +//------------------------------------------------------------------------ +struct c39_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool flow = false; // stop flag + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void C39_header(outctx_t &ctx); + void handle_operand( + const insn_t &insn, + const op_t &x, + bool is_forced, + bool isload); + int C39_emu(const insn_t &insn); + + void C39_segstart(outctx_t &ctx, segment_t *Sarea) const; + void C39_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ C39" +#define PROCMOD_NAME c39 + +#endif diff --git a/idasdk76/module/c39/emu.cpp b/idasdk76/module/c39/emu.cpp new file mode 100644 index 0000000..bdc39f4 --- /dev/null +++ b/idasdk76/module/c39/emu.cpp @@ -0,0 +1,98 @@ +/* + * Rockwell C39 processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "c39.hpp" + +//---------------------------------------------------------------------- +// use/change of operands +void c39_t::handle_operand( + const insn_t &insn, + const op_t &x, + bool is_forced, + bool isload) +{ + ea_t ea = map_code_ea(insn, x); + switch ( x.type ) + { + case o_void: + break; + // nothing to do here + case o_reg: + break; + + case o_imm: + if ( !isload ) + goto badTouch; + set_immd(insn.ea); + if ( !is_forced && is_off(get_flags(insn.ea), x.n) ) + insn.add_dref(ea, x.offb, dr_O); // offset! + break; + + // jump or call + case o_near: + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + // add xref to code + insn.add_cref(ea, x.offb, fl_CN); + // is nonreturning function? + flow = func_does_return(ea); + } + else + { + insn.add_cref(ea, x.offb, fl_JN); + } + break; + + // memory reference + case o_mem: + insn.create_op_data(ea, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + // add xref to the target address + if ( insn.itype == C39_jmp && x.dtype == dt_word && is_loaded(ea) ) + { + ea_t callee = get_word(ea); + if ( callee > 32 && is_mapped(callee) ) // is good address? + { + add_cref(insn.ea, callee, fl_JN); + if ( !is_defarg0(get_flags(ea)) ) + op_plain_offset(ea, 0, 0); + } + } + break; + + default: +badTouch: + warning("%a %s,%d: bad optype %d", + insn.ea, insn.get_canon_mnem(ph), + x.n, x.type); + break; + } +} + +//---------------------------------------------------------------------- +int c39_t::C39_emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + bool flag3 = is_forced_operand(insn.ea, 2); + + flow = ((Feature & CF_STOP) == 0); + + if ( Feature & CF_USE1) handle_operand(insn, insn.Op1, flag1, true); + if ( Feature & CF_USE2) handle_operand(insn, insn.Op2, flag2, true); + if ( Feature & CF_USE3) handle_operand(insn, insn.Op3, flag3, true); + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP,insn.ea); + + if ( Feature & CF_CHG1) handle_operand(insn, insn.Op1, flag1, false); + if ( Feature & CF_CHG2) handle_operand(insn, insn.Op2, flag2, false); + if ( Feature & CF_CHG3) handle_operand(insn, insn.Op3, flag3, false); + if ( flow ) + add_cref(insn.ea, insn.ea+insn.size, fl_F); + + return 1; +} diff --git a/idasdk75/module/c39/ins.cpp b/idasdk76/module/c39/ins.cpp similarity index 100% rename from idasdk75/module/c39/ins.cpp rename to idasdk76/module/c39/ins.cpp diff --git a/idasdk75/module/c39/ins.hpp b/idasdk76/module/c39/ins.hpp similarity index 100% rename from idasdk75/module/c39/ins.hpp rename to idasdk76/module/c39/ins.hpp diff --git a/idasdk76/module/c39/makefile b/idasdk76/module/c39/makefile new file mode 100644 index 0000000..15ced7d --- /dev/null +++ b/idasdk76/module/c39/makefile @@ -0,0 +1,57 @@ +PROC=c39 +CONFIGS=c39.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp c39.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + c39.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + c39.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + c39.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp c39.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/c39/out.cpp b/idasdk76/module/c39/out.cpp similarity index 100% rename from idasdk75/module/c39/out.cpp rename to idasdk76/module/c39/out.cpp diff --git a/idasdk76/module/c39/reg.cpp b/idasdk76/module/c39/reg.cpp new file mode 100644 index 0000000..6dd2be4 --- /dev/null +++ b/idasdk76/module/c39/reg.cpp @@ -0,0 +1,242 @@ +/* + * Rockwell C39 processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "c39.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const RegNames[] = +{ + // empty place + "", + // general registers + "A","X","Y", + // pseudo-segment registers + "cs","ds" +}; + +//---------------------------------------------------------------------- +void c39_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(c39_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi c39_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_gen_lzero(true); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + C39_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + C39_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + C39_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return C39_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return C39_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + C39_data(*ctx, analyze_only); + return 1; + } + + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const asm_t pseudosam = +{ + AS_COLON | AS_UDATA | ASH_HEXF3 | ASD_DECF0, + 0, + "Generic C39 assembler", // Assembler name + 0, // Help screen number, 0 - no help + NULL, // array of automatically generated header lines + "org", // ORG + "end", // end + + ";", // comment + '"', // string literal delimiter + '\'', // char constant delimiter + "\\\"'", // special chars that cannot appear + + "db", // ascii string directive + ".DATA.B", // byte directive + ".DATA.W", // word directive + ".DATA.L", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "#d dup(#v)", // arrays (#h,#d,#v,#s(...) + "db ?", // uninited arrays + ".equ", // equ + NULL, // seg prefix + "$", // current IP + NULL, // Generate function header lines + NULL, // Generate function footer lines + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // Get name of type of item at ea or id + ".ALIGN", // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &pseudosam, NULL }; +//----------------------------------------------------------------------- +#define FAMILY "Rockwell C39:" +static const char *const shnames[] = { "C39", NULL }; +static const char *const lnames[] = { FAMILY"Rockwell C39", NULL }; + +//-------------------------------------------------------------------------- +static const uchar retcode_1[] = { 0x00, 0x0B }; // RTS +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_C39, // processor's id + // flag + PR_USE32 + | PR_BINMEM + | PR_SEGTRANS, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte + + shnames, // short processor names + lnames, // long processor names + + asms, // assembler definitions + + notify, // Event notification handler + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 2, // size of a segment register + rVcs,rVds, + NULL, // typical code start sequences + retcodes, // 'return' instruction opcodes + 0,C39_last, // icode of the first and the last instruction + Instructions, // instruc + 3, // Size of long double (tbyte) - 24 bits + {0,0,0,0}, // Number of digits in floating numbers after the decimal point + 0, // Icode of return instruction + NULL, // Reserved, currently equals to NULL +}; diff --git a/idasdk76/module/cfh_ha16.cpp b/idasdk76/module/cfh_ha16.cpp new file mode 100644 index 0000000..4d65c22 --- /dev/null +++ b/idasdk76/module/cfh_ha16.cpp @@ -0,0 +1,127 @@ + +// This file contains a custom fixup handler for the HA16 fixup type. +// It is used by PPC, MIPS, and similar processors. +// Also thie file contains a custom refinfo handler for the HA16 type. + +#include <fixup.hpp> + +//-------------------------------------------------------------------------- +// 'apply' a fixup: take it into account while analyzing the file +// usually it consists of converting the operand into an offset expression +static bool idaapi ha16_apply( + const fixup_handler_t *fh, + ea_t item_ea, + ea_t fixup_ea, + int opnum, + bool is_macro, + const fixup_data_t &fd) +{ + if ( is_unknown(get_flags(item_ea)) ) + create_16bit_data(fixup_ea, 2); + + refinfo_t ri; + ri.flags = fh->reftype; + ri.base = fd.get_base(); + ri.target = ri.base + fd.off; + ri.tdelta = fd.displacement; + + // check for the second fixup within a macro instruction + if ( is_macro ) + handle_fixups_in_macro(&ri, item_ea, FIXUP_LOW16, REF_OFF32); + if ( processor_t::adjust_refinfo(&ri, fixup_ea, opnum, fd) < 0 ) + return false; + op_offset_ex(item_ea, opnum, &ri); + return true; +} + +//-------------------------------------------------------------------------- +static uval_t idaapi ha16_get_value(const fixup_handler_t * /*fh*/, ea_t ea) +{ + // we can't get the exact value of this fixup as it depends on the low + // part + return get_word(ea) << 16; +} + +//---------------------------------------------------------------------------- +static bool idaapi ha16_patch_value( + const fixup_handler_t * /*fh*/, + ea_t ea, + const fixup_data_t &fd) +{ + // compensate signed low part + ea_t expr = fd.off + fd.displacement + 0x8000; +#ifdef __EA64__ + // in the case of 32-bit reloc we have to check overflow, + // for simplicity we don't do. + // overflow = is32bit_reloc && expr > UINT_MAX; +#endif + put_word(ea, expr >> 16); + return true; +} + +//-------------------------------------------------------------------------- +static const fixup_handler_t cfh_ha16 = +{ + sizeof(fixup_handler_t), + "HIGHA16", /* name */ + 0, /* props */ + 2, 0, 0, 0, /* size, width, shift */ + REFINFO_CUSTOM, /* reftype */ + ha16_apply, /* apply */ + ha16_get_value, /* get_value */ + ha16_patch_value, /* patch_value */ +}; + +//-------------------------------------------------------------------------- +inline bool was_displacement_generated(const char *buf) +{ + const char *ptr = strchr(buf, COLOR_SYMBOL); // is there a displacement? + return ptr != NULL && (ptr[1] == '+' || ptr[1] == '-'); +} + +//-------------------------------------------------------------------------- +// get reference data from ri, +// check compliance of opval and the full value +static bool idaapi ha16_calc_reference_data( + ea_t *target, + ea_t *base, + ea_t /*from*/, + const refinfo_t &ri, + adiff_t opval) +{ + if ( ri.target == BADADDR + || ri.base == BADADDR + || ri.is_subtract() ) + { + return false; + } + ea_t fullvalue = ri.target + ri.tdelta - ri.base; + int16 calc_opval = (fullvalue >> 16) & 0xFFFF; + if ( (fullvalue & 0x8000) != 0 ) + calc_opval += 1; + if ( calc_opval != int16(opval) ) + return false; + + *target = ri.target; + *base = ri.base; + return true; +} + +//-------------------------------------------------------------------------- +// simple format +static void idaapi ha16_get_format(qstring *format) +{ + *format = COLSTR("%s@ha", SCOLOR_KEYWORD); +} + +//-------------------------------------------------------------------------- +static const custom_refinfo_handler_t ref_ha16 = +{ + sizeof(custom_refinfo_handler_t), + "HIGHA16", + "high adjusted 16 bits of 32-bit offset", + 0, // properties (currently 0) + NULL, // gen_expr + ha16_calc_reference_data, // calc_reference_data + ha16_get_format, // get_format +}; diff --git a/idasdk75/module/cr16/ana.cpp b/idasdk76/module/cr16/ana.cpp similarity index 100% rename from idasdk75/module/cr16/ana.cpp rename to idasdk76/module/cr16/ana.cpp diff --git a/idasdk75/module/cr16/cr16.cfg b/idasdk76/module/cr16/cr16.cfg similarity index 100% rename from idasdk75/module/cr16/cr16.cfg rename to idasdk76/module/cr16/cr16.cfg diff --git a/idasdk76/module/cr16/cr16.hpp b/idasdk76/module/cr16/cr16.hpp new file mode 100644 index 0000000..a662999 --- /dev/null +++ b/idasdk76/module/cr16/cr16.hpp @@ -0,0 +1,64 @@ +/* + * National Semiconductor Corporation CR16 processor module for IDA. + * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#ifndef _CR16_HPP +#define _CR16_HPP + +#include <ida.hpp> +#include <idp.hpp> + +#include "../idaidp.hpp" +#define near +#define far +#include "ins.hpp" +#include "../iohandler.hpp" + +// ============================================================ +// specflags1 bits +//----------------------------------------------- +#define URR_PAIR (0x01) // indirect reference via reg pair + +//------------------------------------------------------------------------ +// processor registers +enum CR16_registers +{ + rNULLReg, + rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7, + rR8, rR9, rR10, rR11, rR12, rR13, rRA, rSP, + // special registers + rPC, rISP, rINTBASE, rPSR, rCFG, rDSR, rDCR, + rCARL, rCARH, rINTBASEL, rINTBASEH, + rVcs, rVds +}; + +//------------------------------------------------------------------------ +int idaapi CR16_ana(insn_t *_insn); +int idaapi CR16_emu(const insn_t &insn); + +//------------------------------------------------------------------------ +struct cr16_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool flow = false; // flow stop flag + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void CR16_header(outctx_t &ctx); + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + int CR16_emu(const insn_t &insn); + + void CR16_segstart(outctx_t &ctx, segment_t *Sarea) const; + void CR16_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ CR16" +#define PROCMOD_NAME cr16 + +#endif diff --git a/idasdk76/module/cr16/emu.cpp b/idasdk76/module/cr16/emu.cpp new file mode 100644 index 0000000..b517142 --- /dev/null +++ b/idasdk76/module/cr16/emu.cpp @@ -0,0 +1,100 @@ +/* + * National Semiconductor Corporation CR16 processor module for IDA. + * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "cr16.hpp" + +//---------------------------------------------------------------------- +// handle using/changing of operands +void cr16_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) +{ + ea_t ea; + switch ( x.type ) + { + case o_void: + case o_reg: + break; + + case o_imm: + if ( !isload ) + goto badTouch; + set_immd(insn.ea); + // no break + case o_displ: + if ( !is_forced && op_adds_xrefs(get_flags(insn.ea), x.n) ) + { + int outf = (x.type == o_displ ? OOF_ADDR : 0) + | OOF_SIGNED + | (x.dtype == dt_word ? OOFW_16 : OOFW_8); + dref_t dt = x.type == o_imm ? dr_O : isload ? dr_R : dr_W; + ea = insn.add_off_drefs(x, dt, outf); + if ( ea != BADADDR ) + insn.create_op_data(ea, x); + } + break; + + // jump or call + case o_near: + ea = map_code_ea(insn, x); + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + // add cross-reference + insn.add_cref(ea, x.offb, fl_CN); + // doesn't return? + flow = func_does_return(ea); + } + else + { + insn.add_cref(ea, x.offb, fl_JN); + } + break; + + // memory reference + case o_mem: + ea = map_data_ea(insn, x); + insn.create_op_data(ea, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + break; + + // other - report error + default: + badTouch: + warning("%a %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); + break; + } +} + +//---------------------------------------------------------------------- +// emulator +int cr16_t::CR16_emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + + // get operand types + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + + flow = ((Feature & CF_STOP) == 0); + + // handle reads + if ( Feature & CF_USE1 ) + handle_operand(insn, insn.Op1, flag1, true); + if ( Feature & CF_USE2 ) + handle_operand(insn, insn.Op2, flag2, true); + + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + // handle writes + if ( Feature & CF_CHG1 ) + handle_operand(insn, insn.Op1, flag1, false); + if ( Feature & CF_CHG2 ) + handle_operand(insn, insn.Op2, flag2, false); + // if not stopping, add flow xref + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + return 1; +} diff --git a/idasdk75/module/cr16/ins.cpp b/idasdk76/module/cr16/ins.cpp similarity index 100% rename from idasdk75/module/cr16/ins.cpp rename to idasdk76/module/cr16/ins.cpp diff --git a/idasdk75/module/cr16/ins.hpp b/idasdk76/module/cr16/ins.hpp similarity index 100% rename from idasdk75/module/cr16/ins.hpp rename to idasdk76/module/cr16/ins.hpp diff --git a/idasdk76/module/cr16/makefile b/idasdk76/module/cr16/makefile new file mode 100644 index 0000000..3ea1a63 --- /dev/null +++ b/idasdk76/module/cr16/makefile @@ -0,0 +1,57 @@ +PROC=cr16 +CONFIGS=cr16.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp cr16.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + cr16.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + cr16.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + cr16.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp cr16.hpp ins.hpp reg.cpp diff --git a/idasdk76/module/cr16/out.cpp b/idasdk76/module/cr16/out.cpp new file mode 100644 index 0000000..8687992 --- /dev/null +++ b/idasdk76/module/cr16/out.cpp @@ -0,0 +1,195 @@ + +/* + * National Semiconductor Corporation CR16 processor module for IDA. + * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "cr16.hpp" + +//---------------------------------------------------------------------- +class out_CR16_t : public outctx_t +{ + out_CR16_t(void) = delete; // not used +public: + void OutVarName(const op_t &x); + + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_CR16_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_CR16_t) + +//---------------------------------------------------------------------- +void out_CR16_t::OutVarName(const op_t &x) +{ + ea_t toea = map_code_ea(insn, x); + + if ( !out_name_expr(x, toea, x.addr) ) + { + out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); + remember_problem(PR_NONAME, insn.ea); + } +} + +//---------------------------------------------------------------------- +// output one operand +bool out_CR16_t::out_operand(const op_t &x) +{ + int flags; + switch ( x.type ) + { + case o_displ: + flags = OOF_ADDR | OOF_SIGNED | (x.dtype == dt_word ? OOFW_16 : OOFW_8); + out_value(x, flags); + out_symbol('('); + if ( x.specflag1 & URR_PAIR ) + { + out_register(ph.reg_names[x.reg + 1]); + out_symbol(','); + out_register(ph.reg_names[x.reg]); + } + else + { + out_register(ph.reg_names[x.reg]); + } + out_symbol(')'); + break; + + case o_reg: + if ( x.specflag1 & URR_PAIR ) + { + out_symbol('('); + out_register(ph.reg_names[x.reg + 1]); + out_symbol(','); + out_register(ph.reg_names[x.reg]); + out_symbol(')'); + } + else + { + out_register(ph.reg_names[x.reg]); + } + break; + + case o_imm: + out_symbol('$'); + flags = /*OOFS_NOSIGN | OOF_SIGNED | */OOFW_IMM; + switch ( insn.itype ) + { + case CR16_addb: + case CR16_addw: + case CR16_addub: + case CR16_adduw: + case CR16_addcb: + case CR16_addcw: + case CR16_ashub: + case CR16_ashuw: + case CR16_lshb: + case CR16_lshw: + flags |= OOF_SIGNED; + break; + } + out_value(x, flags); + break; + + case o_near: + OutVarName(x); + break; + + case o_mem: + OutVarName(x); + break; + + case o_void: + return 0; + + default: + warning("out: %a: bad optype %d", insn.ea, x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +// main output function +void out_CR16_t::out_insn(void) +{ + // print mnemonic + out_mnemonic(); + + // print first operand + if ( insn.Op1.type != o_void ) + out_one_operand(0); + + // print second operand + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +// header of the listing +void cr16_t::CR16_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, ioh.device.c_str(), ioh.deviceparams.c_str()); +} + +//-------------------------------------------------------------------------- +// segment start +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Sarea) could be made const +void cr16_t::CR16_segstart(outctx_t &ctx, segment_t *Sarea) const +{ + const char *SegType = Sarea->type == SEG_CODE ? "CSEG" + : Sarea->type == SEG_DATA ? "DSEG" + : "RSEG"; + // print RSEG <NAME> + qstring sn; + + get_visible_segm_name(&sn, Sarea); + ctx.gen_printf(-1, "%s %s ", SegType, sn.c_str()); + // if offset not zero, print it (ORG XXXX) + if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) + { + ea_t org = ctx.insn_ea - get_segm_base(Sarea); + + if ( org != 0 ) + { + char bufn[MAX_NUMBUF]; + btoa(bufn, sizeof(bufn), org); + ctx.gen_printf(-1, "%s %s", ash.origin, bufn); + } + } +} + +//-------------------------------------------------------------------------- +// end of listing +void cr16_t::CR16_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + size_t i = strlen(ash.end); + do + ctx.out_char(' '); + while ( ++i < 8 ); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} diff --git a/idasdk76/module/cr16/reg.cpp b/idasdk76/module/cr16/reg.cpp new file mode 100644 index 0000000..cf5b68a --- /dev/null +++ b/idasdk76/module/cr16/reg.cpp @@ -0,0 +1,254 @@ + +/* + * National Semiconductor Corporation CR16 processor module for IDA. + * Copyright (c) 2002-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "cr16.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +// list of registers +static const char *const RegNames[] = +{ + // empty + "", + // general purpose + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "ra", "sp", + // special + "pc", "isp", "intbase", "psr", "cfg", "dsr", "dcr", "carl", "carh", + "intbaseh", "intbasel", + + // pseudo segments + "cs", "ds" +}; + +//---------------------------------------------------------------------- +void cr16_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(cr16_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi cr16_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_be(false); + inf_set_gen_lzero(true); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + // ask for a processor from the config file + // use it to handle ports and registers + { + char cfgfile[QMAXFILE]; + + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + CR16_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + CR16_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + CR16_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return CR16_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return CR16_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const asm_t pseudosam = +{ + AS_COLON | AS_UDATA | ASH_HEXF3 | ASD_DECF0, + // user flags + 0, + "Generic CR16 assembler", // title + 0, // help id + NULL, // header + "org", // ORG directive + "end", // end directive + + ";", // comment + '"', // string delimiter + '\'', // character constant + "\\\"'", // special characters + + "db", // ascii string directive + ".byte", // byte directive + ".word", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "#d dup(#v)", // arrays (#h,#d,#v,#s(...) + "db ?", // uninited arrays + ".equ", // equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + NULL, // Generate function header lines + NULL, // Generate function footer lines + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // Get name of type of item at ea or id + ".ALIGN", // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +// list of assemblers +static const asm_t *const asms[] = { &pseudosam, NULL }; + +//----------------------------------------------------------------------- +#define FAMILY "NSC CR16:" + +// short names +static const char *const shnames[] = { "CR16", NULL }; + +// long names +static const char *const lnames[] = { FAMILY"NSC CR16", NULL }; + +//-------------------------------------------------------------------------- +// return instructions +static const uchar retcode_1[] = { 0x00, 0x0B }; // RTS + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_CR16, // processor ID + // flag + PR_USE32 + | PR_BINMEM + | PR_SEGTRANS, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for data segments + + shnames, // short processor names (NULL terminated) + lnames, // long processor names (NULL terminated) + + asms, // assemblers + + notify, // Event notification handler + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs, rVds, + 2, // size of a segment register + rVcs, rVds, + NULL, // Array of typical code start sequences + retcodes, // Array of 'return' instruction opcodes + 0, CR16_last, // icode of the first and the last instruction + Instructions, // instruc + 3, // Size of long double (tbyte) for this processor - 24 bits + {0, 0, 0, 0}, // Number of digits in floating numbers after the decimal point + 0, // Icode of return instruction + NULL, // micro virtual mashine +}; diff --git a/idasdk76/module/dsp56k/ana.cpp b/idasdk76/module/dsp56k/ana.cpp new file mode 100644 index 0000000..a609910 --- /dev/null +++ b/idasdk76/module/dsp56k/ana.cpp @@ -0,0 +1,2945 @@ +/* + Motorola DSP56K processor module for IDA. + The instruction decoder of this processor module is based on the disassembler + for DSP5600x processor by Miloslaw Smyk. + + The source code was modified to conform IDA by Ilfak Guilfanov. + Support for DSP 563xx was added by Ivan Litvin <ltv@microset.ru> (December 2003) + Support for DSP 561xx was added by Ivan Litvin <ltv@microset.ru> (January 2004) + +*/ + +/* + * Copyright (c) 1998 Miloslaw Smyk + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Miloslaw Smyk + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "dsp56k.hpp" + +#define FUNCS_COUNT 5 +#define F_SWITCH nullptr +//lint -e1762 member function 'dsp56k_t::' could be made const + + +struct funcdesc_t +{ + bool (dsp56k_t:: *func)(insn_t &, int); + uint32 mask; + uint32 shift; +}; + +struct opcode_t +{ + ushort proc; +#define p5600x 0x01 // valid for 5600x +#define p561xx 0x02 // valid for 561xx +#define p563xx 0x04 // valid for 563xx +#define p566xx 0x08 // valid for 566xx + +#define pall (p5600x|p561xx|p563xx|p566xx) +#define p_1 p561xx +#define p_0_3 (p5600x|p563xx) +#define p_3_6 (p563xx|p566xx) + + ushort itype; + const char *recog; //lint !e958 padding is required to align members + char pmov_cl; // class of acceptable parallel movs for the instruction + funcdesc_t funcs[FUNCS_COUNT]; //lint !e958 padding is required to align members + uint32 mask; + uint32 value; +}; + +struct par_move +{ + ushort proc; + const char *recog; //lint !e958 padding is required to align members + funcdesc_t funcs[FUNCS_COUNT]; + ushort mask; + ushort value; +}; + +//---------------------------------------------------------------------- +static uint32 ua_next_24bits(insn_t &insn) +{ + uint32 x = get_wide_byte(insn.ea+insn.size); + insn.size++; + return x; +} + +//---------------------------------------------------------------------- +static uint32 ua_32bits(const insn_t &insn) +{ + + uint32 x = ((get_wide_byte(insn.ea) ) & 0x0000FFFF) + | ((get_wide_byte(insn.ea+1) << 16) & 0xFFFF0000); + return x; +} + + +//---------------------------------------------------------------------- +// make sure that the additional args are good +void dsp56k_t::fill_additional_args(const insn_t &insn) const +{ + if ( aa.ea != insn.ea ) + { + insn_t tmp; + decode_insn(&tmp, insn.ea); + } +} + +//---------------------------------------------------------------------- +void dsp56k_t::switch_to_additional_args(insn_t &) +{ + op = aa.args[aa.nargs++]; + op[0].flags = OF_SHOW; + op[1].flags = OF_SHOW; + op[0].n = 1; // just something else than 0 + op[1].n = 1; // just something else than 0 +} + +//---------------------------------------------------------------------- +inline void dsp56k_t::opreg(insn_t &, int reg) +{ + op->type = o_reg; + op->reg = (uint16)reg; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_EE(insn_t &insn, int value) +{ + uchar reg; + if ( is561xx() ) + { + static const char regs[] = { -1, MR, CCR, OMR }; + + if ( value < 1 ) + return false; + + reg = regs[value]; + } + else + { + static const char regs[] = { MR, CCR, OMR }; + + if ( value == 3 ) + return false; + + reg = regs[value]; + } + opreg(insn, reg); + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_DDDDD(insn_t &insn, int value) +{ + if ( is561xx() ) + { + static const uchar regs[] = + { + X0, Y0, X1, Y1, A, B, A0, B0, + uchar(-1), SR, OMR,SP, A1, B1, A2, B2, + R0, R1, R2, R3, M0, M1, M2, M3, + SSH,SSL,LA, LC, N0, N1, N2, N3 + }; + + if ( value >= qnumber(regs) ) + return false; + opreg(insn, regs[value]); + if ( op->reg == uchar(-1) ) + return false; + } + else + { + static const uchar regs[] = { 0, SR, OMR, SP, SSH, SSL, LA, LC }; + if ( value < 8 ) + { + opreg(insn, M0 + (value & 7)); + } + else + { + value &= 7; + if ( value == 0 ) + return false; + opreg(insn, regs[value & 7]); + } + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_ff(const insn_t &insn, int value, int reg_bank) +{ + op->type = o_reg; + switch ( value ) + { + case 0: + op->reg = reg_bank ? Y0 : X0; + break; + case 1: + op->reg = reg_bank ? Y1 : X1; + break; + case 2: + op->reg = A; + break; + case 3: + op->reg = B; + break; + default: + interr(&insn, "D_ff"); + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_df(insn_t &insn, int value, int reg_bank) +{ + opreg(insn, value & 0x02 ? B : A); + op++; + opreg(insn, reg_bank + ? (value & 1) ? X1 : X0 + : (value & 1) ? Y1 : Y0); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_xi(insn_t &, int value) +{ + op->type = o_imm; + op->value = is561xx() ? (value & 0xFF) : value; + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_ximm(insn_t &insn, int /*value*/) +{ + op->type = o_imm; + op->value = ua_next_24bits(insn); + if ( is566xx() ) + op->value &= 0xffff; + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_ximm(insn_t &insn, int value) +{ + if ( D_ximm(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_sssss(insn_t &, int value) +{ + static const int vals[] = + { + 0x800000, 0x400000, 0x200000, 0x100000, + 0x080000, 0x040000, 0x020000, 0x010000, + 0x008000, 0x004000, 0x002000, 0x001000, + 0x000800, 0x000400, 0x000200, 0x000100, + 0x000080, 0x000040, 0x000020, 0x000010, + 0x000008, 0x000004, 0x000002, 0x000001, + 0x000000, 0x000000, 0x000000, 0x000000, + 0x000000, 0x000000, 0x000000, 0x000000, + }; + + op->type = o_imm; + op->value = vals[value & 0x1f]; + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_ssss(insn_t &, int value) +{ + static const int vals[] = + { + 0x8000, 0x4000, 0x2000, 0x1000, + 0x0800, 0x0400, 0x0200, 0x0100, + 0x0080, 0x0040, 0x0020, 0x0010, + 0x0008, 0x0004, 0x0002, 0x0001 + }; + + op->type = o_imm; + op->value = vals[value & 0xf]; + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_xih(insn_t &, int value) +{ + op->type = o_imm; + op->value = (value & 0xF) << 8; + op->value |= (value >> 8) & 0xFF; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_xih(insn_t &insn, int value) +{ + if ( D_xih(insn, value) ) + { + op++; + return true; + } + return false; +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_d(insn_t &insn, int value) +{ + if ( value ) + { + opreg(insn, A); + op++; + opreg(insn, B); + } + else + { + opreg(insn, B); + op++; + opreg(insn, A); + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::SS_JJJd(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + + if ( value > 1 && value < 8 ) + return false; + + switch ( value >> 1 ) + { + case 0: + return SD_d(insn, value & 0x01); + + default: + opreg(insn, regs[(value >> 1) - 4]); + op++; + break; + } + opreg(insn, value & 0x01 ? B : A); + return true; +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_JJJd(insn_t &insn, int value) +{ + static const uchar regs[] = { X, Y, X0, Y0, X1, Y1 }; + switch ( value >> 1 ) + { + case 0: + return false; + + case 1: + return SD_d(insn, value & 0x01); + + default: + opreg(insn, regs[(value >> 1) - 2]); + op++; + break; + } + opreg(insn, value & 0x01 ? B : A); + return true; +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_Jd(insn_t &insn, int value) +{ + opreg(insn, (value & 2) ? Y : X); + op++; + opreg(insn, (value & 1) ? B : A); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_d(insn_t &insn, int value) +{ + opreg(insn, value ? B : A); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_S(insn_t &insn, int value) +{ + if ( D_d(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_JJd(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + opreg(insn, regs[value>>1]); + op++; + return D_d(insn, value & 0x01); +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_dddd(insn_t &insn, int value) +{ + opreg(insn, ((value & 8) ? N0 : R0) + (value & 0xF)); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_ddddd(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, X1, Y0, Y1, A0, B0, A2, B2, A1, B1, A, B }; + + if ( value >= 4 ) + { + if ( value < 16 ) + opreg(insn, regs[value - 4]); + else + opreg(insn, ((value < 24) ? R0 : N0) + (value & 7)); + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_ddddd(insn_t &insn, int value) +{ + if ( D_ddddd(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_LLL(insn_t &insn, int value) +{ + static const uchar regs[] = { A10, B10, X, Y, A, B, AB, BA }; + opreg(insn, regs[value]); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_sss(insn_t &insn, int value) +{ + static const char regs[] = { -1, -1, A1, B1, X0, Y0, X1, Y1 }; + + if ( value > 1 ) + { + opreg(insn, regs[value]); + return true; + } + else + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_sss(insn_t &insn, int value) +{ + if ( D_sss(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_qqq(insn_t &insn, int value) +{ + static const char regs[] = { -1, -1, A0, B0, X0, Y0, X1, Y1 }; + + if ( value > 1 ) + { + opreg(insn, regs[value]); + return true; + } + else + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_qqq(insn_t &insn, int value) +{ + if ( D_qqq(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_qq(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + + opreg(insn, regs[value & 0x03]); + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_QQ(insn_t &insn, int value) +{ + int idx = value & 0x03; + if ( is561xx() ) + { + static const uchar regs1[] = { X0, X0, X1, X1 }; + static const uchar regs2[] = { Y0, Y1, Y0, Y1 }; + opreg(insn, regs1[idx]); + op++; + opreg(insn, regs2[idx]); + } + else + { + static const uchar regs[] = { Y1, X0, Y0, X1 }; + opreg(insn, regs[idx]); + } + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_gggd(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + + if ( value < 2 ) + { + opreg(insn, value == 0 ? B : A); + } + else + { + opreg(insn, regs[(value>>1) & 0x03]); + } + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_MMRRR(insn_t &, int value) +{ + op->type = o_phrase; + op->phrase = value & 0x07; + op->phtype = uchar(value >> 3); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_MMRRR(insn_t &insn, int value) +{ + if ( D_MMRRR(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_MMRRR_XY(insn_t &, int value) +{ + static const char phtypes[] = + { + 4, // (Rn) + 1, // (Rn)+Nn + 2, // (Rn)- + 3 // (Rn)+ + }; + op->type = o_phrase; + op->phrase = value & 0x07; + op->phtype = phtypes[value >> 3]; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_pppppp(insn_t &, int value) +{ + int base = is563xx() ? 0xFFFFC0 : 0xFFC0; + + value += base; + + op->amode |= amode_ioshort; + op->type = o_mem; + op->addr = value; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_pppppp(insn_t &insn, int value) +{ + if ( D_pppppp(insn, value) ) + { + op++; + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_qqqqqq(insn_t &, int value) +{ + int base = is563xx() ? 0xFFFF80 : 0xFF80; + + value += base; + + op->amode |= amode_ioshort; + op->type = o_mem; + op->addr = value; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_qqqqqq(insn_t &insn, int value) +{ + if ( D_qqqqqq(insn, value) ) + { + op++; + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_qXqqqqq(insn_t &insn, int value) +{ + return D_qqqqqq(insn, (value & 0x1f) + ((value & 0x40)>>1)); +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_DDDDDD(insn_t &insn, int value) +{ + static const char regs[] = + { + -1, -1, -1, -1, X0, X1, Y0, Y1, + A0, B0, A2, B2, A1, B1, A, B, + R0, R1, R2, R3, R4, R5, R6, R7, + N0, N1, N2, N3, N4, N5, N6, N7, + M0, M1, M2, M3, M4, M5, M6, M7, + -1, -1, EP, -1, -1, -1, -1, -1, + VBA, SC, -1,-1, -1, -1, -1, -1, + SZ, SR, OMR,SP, SSH,SSL,LA, LC + }; + + if ( value >= qnumber(regs) ) + return false; + char r = regs[value]; + if ( r == -1 ) + return false; + opreg(insn, r); + // if ( op->reg >= SZ && !is563xx() ) return false; + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_DDDDDD(insn_t &insn, int value) +{ + if ( D_DDDDDD(insn, value) ) + { + op++; + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_DDDD(insn_t &insn, int value) +{ + if ( D_DDDDDD(insn, value & 0x0f) ) + return true; + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_RRR(insn_t &insn, int value) +{ + opreg(insn, R0 + value); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_RRR(insn_t &insn, int value) +{ + opreg(insn, R0 + value); + op++; + return true; +} + +//---------------------------------------------------------------------- +//lint -e{1764} insn could be const +void dsp56k_t::make_o_mem(insn_t &insn) +{ + if ( !(op->amode & (amode_x|amode_y)) ) switch ( insn.itype ) + { + case DSP56_do: + case DSP56_do_f: + case DSP56_dor: + case DSP56_dor_f: + if ( !is561xx() ) + op->addr++; + // no break + case DSP56_jcc: + case DSP56_jclr: + case DSP56_jmp: + case DSP56_jscc: + case DSP56_jsclr: + case DSP56_jsr: + case DSP56_jsset: + case DSP56_jset: + + case DSP56_bcc: + case DSP56_bra: + case DSP56_brclr: + case DSP56_brset: + case DSP56_bscc: + case DSP56_bsclr: + case DSP56_bsr: + case DSP56_bsset: + op->type = o_near; + op->dtype = dt_code; + return; + } + op->type = o_mem; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_mMMMRRR(insn_t &insn, int value) +{ + if ( !(value & 0x40) ) + { + op->amode |= amode_short; // < + op->addr = value & 0x3F; + make_o_mem(insn); + return true; + } + + value &= ~0x40; + + D_MMRRR(insn, value); // phrase + if ( op->phtype == 6 ) + { + if ( value & 0x4 ) + { + op->type = o_imm; + op->value = ua_next_24bits(insn); + if ( is566xx() ) + op->value &= 0xffff; + } + else + { + op->addr = ua_next_24bits(insn); + if ( is566xx() ) + op->addr &= 0xffff; + make_o_mem(insn); + } + } + return true; +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::S_mMMMRRR(insn_t &insn, int value) +{ + if ( D_mMMMRRR(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_aaaaaa(insn_t &insn, int value) +{ + if ( D_mMMMRRR(insn, value & 0x3f) == true ) + { + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_aaaaaa(insn_t &insn, int value) +{ + if ( D_aaaaaa(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_MMMRRR(insn_t &insn, int value) +{ + if ( D_mMMMRRR(insn, value | 0x40) == true ) + { + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_MMMRRR(insn_t &insn, int value) +{ + if ( D_MMMRRR(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::P_type(insn_t &, int) +{ + op->amode |= amode_p; + return true; +} + +//------------------------------------------------------------------ +bool dsp56k_t::X_type(insn_t &, int) +{ + op->amode |= amode_x; + return true; +} + +//------------------------------------------------------------------ +bool dsp56k_t::Y_type(insn_t &, int) +{ + op->amode |= amode_y; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::mem_type(insn_t &, int value) +{ + if ( value == 1 ) + op->amode |= amode_y; + else + op->amode |= amode_x; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::space(insn_t &insn, int) +{ + switch_to_additional_args(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::sign(insn_t &, int value) +{ + if ( value == 1 ) + op->amode |= amode_neg; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::AAE(insn_t &insn, int) +{ + op->addr = ushort(ua_next_24bits(insn)); + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_PC_dispL(insn_t &insn, int value) +{ + if ( is561xx() ) + { + op->addr = insn.ea + short(value) + 2; // +2 - PC should point to next instruction + } + else + { + value = ua_next_24bits(insn); + if ( is566xx() ) + { + op->addr = insn.ea + short(value); + } + else + { + if ( value & 0x00800000 ) + value |= ~0x007FFFFF; + op->addr = insn.ea + value; + } + } + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_PC_dispL(insn_t &insn, int value) +{ + if ( D_PC_dispL(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_PC_dispS(insn_t &insn, int value) +{ + value = (value & 0x1f) + ((value & 0x3c0) >> 1); + + if ( value & 0x100 ) + { + value = (value^0x1ff) + 1; + op->addr = insn.ea - value; + } + else + { + op->addr = insn.ea + value; + } + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_PC_RRR(insn_t &, int value) +{ + op->type = o_phrase; + op->phrase = (uint16)value; + op->phtype = 8; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_RRR_dispL(insn_t &insn, int value) +{ + op->type = o_displ; + op->reg = value & 0x07; + op->phtype = 0; // "R + displ" + + value = ua_next_24bits(insn); + if ( is566xx() ) + op->value &= 0xffff; + + if ( is566xx() ) + { + if ( value & 0x8000 ) + { + value = (value^0xffff) + 1; + op->phtype = 1; // "R - displ" + } + } + else + { + if ( value & 0x800000 ) + { + value = (value^0xffffff) + 1; + op->phtype = 1; // "R - displ" + } + } + + + op->addr = value; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_RRR_dispS(insn_t &, int value) +{ + op->type = o_displ; + op->reg = (value >> 2) & 0x07; + op->phtype = 0; // "R + displ" + + value = (value & 0x1) + ((value & 0x7e0) >> 4); + + if ( value & 0x40 ) + { + op->phtype = 1; // "R - displ" + value = (value^0x7f) + 1; + } + + op->addr = value; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_RR_dispS(insn_t &, int value) +{ + + op->type = o_displ; + op->reg = (value >> 4) & 0x07; + op->phtype = 0; // "R + displ" + + value = (value & 0x0f) + ((value & 0x380) >> 3); + + if ( value & 0x40 ) + { + op->phtype = 1; // "R - displ" + value = (value^0x7f) + 1; + } + + op->addr = value; + op++; + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::AA(insn_t &, int value) +{ + op->amode |= amode_short; + + op->type = o_near; + op->dtype = dt_code; + op->addr = value; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_F(insn_t &insn, int value) +{ + opreg(insn, value ? B : A); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_F(insn_t &insn, int value) +{ + if ( D_F(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::CCCC(insn_t &insn, int value) +{ + insn.auxpref |= value & 0xF; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::s(insn_t &insn, int value) +{ + static const char s_u[] = { s_SU, s_UU }; + + insn.auxpref |= s_u[value & 0x01]; + return true; +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::ss(insn_t &insn, int value) +{ + static const char s_u[] = { s_SS, s_SS, s_SU, s_UU }; + + int idx = is561xx() + ? ((value & 0x08)>>2) + (value & 0x01) + : ((value & 0x04)>>1) + (value & 0x01); + insn.auxpref |= s_u[idx]; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_IIII(insn_t &insn, int value) +{ + // 0100IIII----F--- + static const char regs1[] = + { + X0, Y0, X1, Y1, + A, B, A0, B0, + -1, -1, -1, -1, + A, B, A0, B0 + }; + + static const char regs2[] = + { + -1, -1, -1, -1, + X0, Y0, X0, Y0, + -1, -1, -1, -1, + X1, Y1, X1, Y1 + }; + + unsigned idx = ((value >> 8) & 0x0f); + + if ( idx < 4 ) + { + op->type = o_reg; + op->reg = regs1[idx]; + op++; + D_F(insn, ((value & 0x08)>>3) ^ 0x01); + return true; + } + + if ( ( idx == 8 ) || ( idx == 9 ) ) + { + S_F(insn, ((value & 0x08)>>3)); + D_F(insn, ((value & 0x08)>>3) ^ 0x01); + return true; + } + + + if ( ( idx == 0x0a ) || ( idx == 0x0b ) ) + return false; + + op->type = o_reg; + op->reg = regs1[idx]; + if ( regs1[idx] == -1 ) + return false; + op++; + op->type = o_reg; + op->reg = regs2[idx]; + if ( regs2[idx] == -1 ) + return false; + + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_zRR(insn_t &, int value) +{ + // 00110zRR----F--- + + op->type = o_phrase; + op->phrase = (value >> 8) & 0x03; + if ( ((value >> 10) & 0x01) == 1 ) + op->phtype = 1; + else + op->phtype = 2; + + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_mRR(insn_t &, int value) +{ + op->type = o_phrase; + op->phrase = value & 0x03; + + if ( (value >> 2) & 0x01 ) + op->phtype = 1; + else + op->phtype = 3; + + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_RRm(insn_t &insn, int value) +{ + return D_mRR(insn, ((value & 0x06)>>1) + ((value & 0x01)<<2)); +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_RR11m(insn_t &insn, int value) +{ + return D_mRR(insn, ((value & 0x18)>>3) + (value <<2)); +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_MMRR(insn_t &, int value) +{ + op->type = o_phrase; + op->phrase = value & 0x03; + + switch ( (value & 0x0c)>>2 ) + { + case 0: + op->phtype = 4; + break; + case 1: + op->phtype = 3; + break; + case 2: + op->phtype = 2; + break; + case 3: + op->phtype = 1; + break; + } + + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::S_MMRR(insn_t &insn, int value) +{ + if ( D_MMRR(insn, value) ) + { + op++; + return true; + } + return false; +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_RR0MM(insn_t &insn, int value) +{ + return D_MMRR(insn, ((value & 0x18)>>3) + ((value & 0x03)<<2)); +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_qRR(insn_t &, int value) +{ + op->type = o_phrase; + op->phrase = value & 0x03; + + switch ( (value & 0x08)>>3 ) + { + case 0: + op->phtype = 1; + break; + case 1: + op->phtype = 7; + break; + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_HHH(insn_t &, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1, A, B, A0, B0 }; + + int idx = value & 0x07; + + op->type = o_reg; + op->reg = regs[idx]; + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_HH(insn_t &, int value) +{ + static const uchar regs[] = { X0, Y0, A, B }; + + int idx = value & 0x03; + + op->type = o_reg; + op->reg = regs[idx]; + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_mWRRHHH(insn_t &insn, int value) +// 001001mWRRDDFHHH +{ + if ( value & 0x0100 ) + { + X_type(insn, 0); + D_mRR(insn, ((value & 0xc0)>>6) + ((value & 0x200)>>7)); + op++; + D_HHH(insn, value & 0x07); + } + else + { + D_HHH(insn, value & 0x07); + op++; + X_type(insn, 0); + D_mRR(insn, ((value & 0xc0)>>6) + ((value & 0x200)>>7)); + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_FJJJ(insn_t &insn, int value) +{ + static const char regs[] = { -1, -1, X, Y, X0, Y0, X1, Y1 }; + + int idx = value & 0x07; + + if ( idx != 0x01 ) + { + if ( idx ) + { + op->type = o_reg; + op->reg = regs[idx]; + } + else + { + opreg(insn, (value & 0x08) ? A : B); + } + op++; + return true; + } + else + { + return false; + } +} +//---------------------------------------------------------------------- +bool dsp56k_t::S_QQQ(insn_t &, int value) +{ + int idx = value & 0x07; + + if ( is561xx() ) + { + static const uchar regs1_61[] = { X0, X1, A1, B1, Y0, Y1, Y0, Y1 }; + static const uchar regs2_61[] = { X0, X0, Y0, X0, X0, X0, X1, X1 }; + op->type = o_reg; + op->reg = regs1_61[idx]; + op++; + op->type = o_reg; + op->reg = regs2_61[idx]; + op++; + } + else + { + static const uchar regs1_6x[] = { X0, Y0, X1, Y1, X0, Y0, X1, Y1 }; + static const uchar regs2_6x[] = { X0, Y0, X0, Y0, Y1, X0, Y0, X1 }; + op->type = o_reg; + op->reg = regs1_6x[idx]; + op++; + op->type = o_reg; + op->reg = regs2_6x[idx]; + op++; + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_QQ2(insn_t &, int value) +{ + static const uchar regs1[] = { Y0, Y1, Y0, Y1 }; + static const uchar regs2[] = { X0, X0, X1, X1 }; + + int idx = value & 0x03; + + op->type = o_reg; + op->reg = regs1[idx]; + op++; + op->type = o_reg; + op->reg = regs2[idx]; + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_QQQQ(insn_t &, int value) +{ + static const uchar regs1[] = { X0, Y0, X1, Y1, X0, Y0, X1, Y1, + X1, Y1, X0, Y0, Y1, X0, Y0, X1 }; + static const uchar regs2[] = { X0, Y0, X0, Y0, Y1, X0, Y0, X1, + X1, Y1, X1, Y1, X0, Y0, X1, Y1 }; + + int idx = value & 0xf; + op->type = o_reg; + op->reg = regs1[idx]; + op++; + op->type = o_reg; + op->reg = regs2[idx]; + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_Fh0h(insn_t &insn, int value) +{ + // 000100ccccTTFh0h + static const char regs[] = { -1, -1, X0, Y0 }; + + if ( (((value & 0x04)>>1) + (value & 0x01)) > 1 ) + opreg(insn, regs[(((value & 0x04)>>1) + (value & 0x01))]); + else + opreg(insn, ((value & 0x08)>>3) == (value & 0x01) ? B : A); + + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_uFuuu_add(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + + if ( ((value & 0x07) + ((value & 0x10)>>1)) == 0x0c ) + { + opreg(insn, (value & 0x08) ? A : B); + op++; + return true; + } + if ( ((value & 0x07) + ((value & 0x10)>>1)) > 0x03 ) + return false; + + opreg(insn, regs[value & 0x03]); + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_uFuuu_sub(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + + if ( ((value & 0x07) + ((value & 0x10)>>1)) == 0x0d ) + { + opreg(insn, (value & 0x08) ? A : B); + op++; + return true; + } + if ( ((value & 0x07) + ((value & 0x10)>>1)) < 0x04 ) + return false; + + opreg(insn, regs[value & 0x03]); + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_RR(insn_t &insn, int value) +{ + opreg(insn, R0 + (value & 0x03)); + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::D_NN(insn_t &insn, int value) +{ + opreg(insn, N0 + (value & 0x03)); + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::DB_RR(insn_t &, int value) +{ + // P_type(0); + op->type = o_phrase; + op->phrase = (uint16)value; + op->phtype = 4; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_PC_RR(insn_t &, int value) +{ + // P_type(0); + op->type = o_phrase; + op->phrase = (uint16)value; + op->phtype = 8; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::DX_RR(insn_t &insn, int value) +{ + X_type(insn, 0); + op->type = o_phrase; + op->phrase = (uint16)value; + op->phtype = 4; + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_RR(insn_t &insn, int value) +{ + if ( D_RR(insn, value) ) + { + op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::m_A_B(insn_t &, int /*value*/) +{ + op->type = o_reg; + op->reg = A; + op++; + op->type = o_reg; + op->reg = B; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::IF(insn_t &, int /*value*/) +{ + op->type = o_iftype; + op->imode = imode_if; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::IFU(insn_t &, int /*value*/) +{ + op->type = o_iftype; + op->imode = imode_ifu; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_i(insn_t &insn, int value) +{ + op->type = o_vsltype; + insn.auxpref |= (value & 0x01); + op++; + op->amode |= amode_l; // set L type for last operand + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_TT(insn_t &insn, int value) +{ + // 000100ccccTTFh0h >> 4 + + if ( (value & 0x03) == 0 ) // exclude bogus transfer R0 -> R0 + return true; + + opreg(insn, R0); + op++; + + if ( D_RR(insn, value & 0x03) ) + return true; + + return false; +} +//---------------------------------------------------------------------- +bool dsp56k_t::S_BBBiiiiiiii(insn_t &, int value) +{ + // BBB10010iiiiiiii0001010011Pppppp >> 16 + op->type = o_imm; + op->value = uint32((value & 0xff) << (((value & 0xe000) >> 14) * 4)); + op++; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_Pppppp(insn_t &insn, int value) +{ + X_type(insn, 0); + if ( value & 0x20 ) + { + op->amode |= amode_ioshort; // << + value = 0xffe0 + (value & 0x1f); + } + else + { + value = value & 0x1f; + } + + op->addr = value; + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_ppppp(insn_t &insn, int value) +{ + return D_Pppppp(insn, (value & 0x1f) + 0x20); +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_aaaaa(insn_t &insn, int value) +{ + return D_Pppppp(insn, value & 0x1f); +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_DDDDD(insn_t &insn, int value) +{ + if ( D_DDDDD(insn, value) ) + { + op++; + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_xi(insn_t &, int value) +{ + op->type = o_imm; + op->value = value & 0xff; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_xi16(insn_t &, int value) +{ + op->type = o_imm; + op->value = value & 0xffff; + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_xi_adr_16(insn_t &insn, int value) +{ + op->addr = value & 0xffff; + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_DD(insn_t &insn, int value) +{ + static const uchar regs[] = { X0, Y0, X1, Y1 }; + opreg(insn, regs[value & 0x03]); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::S_DD(insn_t &insn, int value) +{ + if ( D_DD(insn, value) ) + { + op++; + return true; + } + + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_Z(insn_t &, int value) +{ + op->type = o_phrase; + op->phrase = 0; + op->phtype = (value ? 9 : 10); + return true; +} + +//---------------------------------------------------------------------- +// new +bool dsp56k_t::D_t(insn_t &insn, int value) +{ + // xxxxxxxxxxxxxxxx00111WDDDDD1t10- >>3 + if ( value & 0x01 ) + { + D_xi16(insn, (value >> 13) & 0xffff); + } + else + { + X_type(insn, 0); + op->addr = (value >> 13) & 0xffff; + make_o_mem(insn); + } + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::SD_F00J(insn_t &insn, int value) +{ + opreg(insn, (value & 0x08) ? B : A); + op++; + opreg(insn, (value & 0x01) ? Y : X); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_PC_eeeeee(insn_t &insn, int value) +{ + if ( value & 0x20 ) + { + value = (value^0x3f) + 1; + op->addr = insn.ea - value + 1; // +1 - PC should point to next instruction + } + else + { + op->addr = insn.ea + value + 1; + } + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_PC_aaaaaaaa(insn_t &insn, int value) +{ + if ( value & 0x80 ) + { + value = (value^0xff) + 1; + op->addr = insn.ea - value + 1;// +1 - PC should point to next instruction + } + else + { + op->addr = insn.ea + value + 1; + } + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::D_BBBBBBBB(insn_t &, int value) +{ + op->type = o_displ; + op->reg = 2; + op->phtype = 0; // "R + displ" + + if ( value & 0x80 ) + { + value = ((value & 0xff) ^ 0xff) + 1; + op->phtype = 1; // "R - displ" + } + else + { + value = value & 0xff; + } + + op->addr = value; + return true; +} + +//---------------------------------------------------------------------- +static par_move pmoves_6x[] = +{ + { pall, "0010000000000000", },// no movement + { pall, "001dddddiiiiiiii", {{ &dsp56k_t::S_xi, 0x00ff }, { &dsp56k_t::D_ddddd, 0x1f00 }}, },// imm short move + { pall, "001000eeeeeddddd", {{ &dsp56k_t::S_ddddd, 0x03e0 }, { &dsp56k_t::D_ddddd, 0x001f }}, },// regto reg move + { pall, "00100000010MMRRR", {{ &dsp56k_t::D_MMRRR, 0x001f } }, },// Register update + { p563xx, "001000000010CCCC", {{ &dsp56k_t::IF, 0x0000 }, { &dsp56k_t::CCCC, 0x000f }}, },// Execute conditionally without CCR Update + { p563xx, "001000000011CCCC", {{ &dsp56k_t::IFU, 0x0000 }, { &dsp56k_t::CCCC, 0x000f }}, },// Execute conditionally with CCR Update +}; + +static opcode_t table_6x_24[] = +{ +// No Parallel move +// A + { p_3_6, DSP56_add, "0000000101iiiiii1000d000", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_add, "00000001010000001100d000", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_and, "0000000101iiiiii1000d110", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_and, "00000001010000001100d110", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_andi, "00000000iiiiiiii101110EE", 0, {{ &dsp56k_t::S_xi, 0x00ff00 }, { &dsp56k_t::D_EE, 0x000003 }, }}, + { p_3_6, DSP56_asl, "0000110000011101SiiiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00007e }, { &dsp56k_t::S_S, 0x000080 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_asl, "0000110000011110010SsssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_asr, "0000110000011100SiiiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00007e }, { &dsp56k_t::S_S, 0x000080 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_asr, "0000110000011110011SsssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, +// B + { p563xx, DSP56_bcc, "00001101000100000100CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, + { p_3_6, DSP56_bcc, "00000101CCCC01aaaa0aaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::D_PC_dispS, 0x03ff }, }}, + { p_3_6, DSP56_bcc, "0000110100011RRR0100CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_RRR, 0x000700 }, }}, + { p_0_3, DSP56_bchg, "000010110mMMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p566xx, DSP56_bchg, "000010110mMMMRRR0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p_0_3, DSP56_bchg, "0000101110pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p566xx, DSP56_bchg, "0000101110pppppp0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p563xx, DSP56_bchg, "0000000101qqqqqq0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p566xx, DSP56_bchg, "0000000101qqqqqq0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p_0_3, DSP56_bchg, "0000101111DDDDDD010bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p566xx, DSP56_bchg, "0000101111DDDDDD0100bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p_0_3, DSP56_bclr, "0000101011DDDDDD010bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p566xx, DSP56_bclr, "0000101011DDDDDD0100bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p_0_3, DSP56_bclr, "000010100mMMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p566xx, DSP56_bclr, "000010100mMMMRRR0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p563xx, DSP56_bclr, "0000000100qqqqqq0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p566xx, DSP56_bclr, "0000000100qqqqqq0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p_0_3, DSP56_bclr, "0000101010pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p566xx, DSP56_bclr, "0000101010pppppp0S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p563xx, DSP56_bra, "000011010001000011000000", 0, {{ &dsp56k_t::D_PC_dispL,0x000000}, }}, + { p_3_6, DSP56_bra, "00000101000011aaaa0aaaaa", 0, {{ &dsp56k_t::D_PC_dispS,0x0003df}, }}, + { p_3_6, DSP56_bra, "0000110100011RRR11000000", 0, {{ &dsp56k_t::D_PC_RRR, 0x000700 }, }}, + { p563xx, DSP56_brclr, "0000110010MMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brclr, "0000110010aaaaaa1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brclr, "0000110011pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brclr, "0000010010qqqqqq0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brclr, "0000110011DDDDDD100bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x000 }, }}, + { p_3_6, DSP56_brkcc, "00000000000000100001CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, }}, + { p563xx, DSP56_brset, "0000110010MMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brset, "0000110010aaaaaa1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brset, "0000110011pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brset, "0000010010qqqqqq0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_brset, "0000110011DDDDDD101bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x001 }, }}, + { p563xx, DSP56_bscc, "00001101000100000000CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, + { p_3_6, DSP56_bscc, "00000101CCCC00aaaa0aaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::D_PC_dispS, 0x03df }, }}, + { p_3_6, DSP56_bscc, "0000110100011RRR0000CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_PC_RRR, 0x0700 }, }}, + { p563xx, DSP56_bsclr, "0000110110MMMRRR0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsclr, "0000110110aaaaaa1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsclr, "0000110111pppppp0S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsclr, "0000010010qqqqqq1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsclr, "0000110111DDDDDD100bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p_0_3, DSP56_bset, "0000101011DDDDDD011bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p566xx, DSP56_bset, "0000101011DDDDDD0110bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p_0_3, DSP56_bset, "000010100mMMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p566xx, DSP56_bset, "000010100mMMMRRR0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p563xx, DSP56_bset, "0000000100qqqqqq0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p566xx, DSP56_bset, "0000000100qqqqqq0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p_0_3, DSP56_bset, "0000101010pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p566xx, DSP56_bset, "0000101010pppppp0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p563xx, DSP56_bsr, "000011010001000010000000", 0, {{ &dsp56k_t::D_PC_dispL,0x000000}, }}, + { p_3_6, DSP56_bsr, "00000101000010aaaa0aaaaa", 0, {{ &dsp56k_t::D_PC_dispS,0x0003df}, }}, + { p_3_6, DSP56_bsr, "0000110100011RRR10000000", 0, {{ &dsp56k_t::D_PC_RRR, 0x000700 }, }}, + { p563xx, DSP56_bsset, "0000110110MMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_MMMRRR, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsset, "0000110110aaaaaa1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_aaaaaa, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsset, "0000110111pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsset, "0000010010qqqqqq1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p563xx, DSP56_bsset, "0000110111DDDDDD101bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x00 }, }}, + { p_0_3, DSP56_btst, "000010110mMMMRRR0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p566xx, DSP56_btst, "000010110mMMMRRR0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, }}, + { p_0_3, DSP56_btst, "0000101110pppppp0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p566xx, DSP56_btst, "0000101110pppppp0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_pppppp, 0x3f00 }, }}, + { p563xx, DSP56_btst, "0000000101qqqqqq0S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p566xx, DSP56_btst, "0000000101qqqqqq0S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_qqqqqq, 0x3f00 }, }}, + { p_0_3, DSP56_btst, "0000101111DDDDDD011bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { p566xx, DSP56_btst, "0000101111DDDDDD0110bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, +// C + { p_3_6, DSP56_clb, "0000110000011110000000SD", 0, {{ &dsp56k_t::S_S, 0x000002 }, { &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_cmp, "0000000101iiiiii1000d101", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_cmp, "00000001010000001100d101", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_cmpu, "00001100000111111111gggd", 0, {{ &dsp56k_t::S_gggd, 0x00000f }, { &dsp56k_t::D_d, 0x000001 }, }}, +// D + { pall, DSP56_debug, "000000000000001000000000", 0, {{ 0 } }}, + { pall, DSP56_debugcc, "00000000000000110000CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, }}, + { pall, DSP56_dec, "00000000000000000000101d", 0, {{ &dsp56k_t::D_d, 0x000001 }, }}, + { pall, DSP56_div, "000000011000000001JJd000", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, + { p_3_6, DSP56_dmac, "000000010010010s1sdkQQQQ", 0, {{ &dsp56k_t::ss, 0x000140 }, { &dsp56k_t::sign, 0x000010 }, { &dsp56k_t::S_QQQQ, 0x000f }, { &dsp56k_t::D_d, 0x00020 }, }}, + { pall, DSP56_do, "000001100mMMMRRR0S000000", 0, {{ &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR,0x007f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { pall, DSP56_do, "00000110iiiiiiii1000hhhh", 0, {{ &dsp56k_t::S_xih, 0x00ff0f }, { &dsp56k_t::AAE, 0x000000 }, }}, + { pall, DSP56_do, "0000011011DDDDDD00000000", 0, {{ &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x000000 }, }}, + { p_3_6, DSP56_do_f, "000000000000001000000011", 0, {{ &dsp56k_t::AAE, 0x000000 }, }}, + { p563xx, DSP56_dor, "000001100mMMMRRR0S010000", 0, {{ &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR,0x007f00 }, { &dsp56k_t::D_PC_dispL,0x0000 }, }}, + { p563xx, DSP56_dor, "00000110iiiiiiii1001hhhh", 0, {{ &dsp56k_t::S_xih, 0x00ff0f }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, + { p563xx, DSP56_dor, "0000011011DDDDDD00010000", 0, {{ &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::D_PC_dispL, 0x0000 }, }}, + { p563xx, DSP56_dor_f, "000000000000001000000010", 0, {{ &dsp56k_t::D_PC_dispL,0x00000 }, }}, +// E + { pall, DSP56_enddo, "000000000000000010001100", 0, {{ 0 } }}, + { p_3_6, DSP56_eor, "0000000101iiiiii1000d011", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_eor, "00000001010000001100d011", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_extract, "0000110000011010000sSSSD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_extract, "0000110000011000000s000D", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_extractu,"0000110000011010100sSSSD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_extractu,"0000110000011000100s000D", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_S, 0x000010 }, { &dsp56k_t::D_d, 0x0001 }, }}, +// I + { pall, DSP56_ill, "000000000000000000000101", 0, {{ 0 } }}, + { pall, DSP56_inc, "00000000000000000000100d", 0, {{ &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_insert, "00001100000110110qqqSSSD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::S_qqq, 0x000070 }, { &dsp56k_t::D_d, 0x0001 }, }}, + { p_3_6, DSP56_insert, "00001100000110010qqq000D", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_qqq, 0x000070 }, { &dsp56k_t::D_d, 0x0001 }, }}, +// J + { pall, DSP56_jcc, "0000101011MMMRRR1010CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, + { pall, DSP56_jcc, "00001110CCCCaaaaaaaaaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::AA, 0x000fff }, }}, +// exception is possible, it should be moved lower, after move +// { DSP56_jclr, "000010100mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, + { p_0_3, DSP56_jclr, "0000101010pppppp1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jclr, "0000101010pppppp1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p563xx, DSP56_jclr, "0000000110qqqqqq1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jclr, "0000000110qqqqqq1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jclr, "0000101011DDDDDD000bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { p566xx, DSP56_jclr, "0000101011DDDDDD0000bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { pall, DSP56_jmp, "0000101011MMMRRR10000000", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, + { pall, DSP56_jmp, "000011000000aaaaaaaaaaaa", 0, {{ &dsp56k_t::AA, 0x000fff }, }}, + { pall, DSP56_jscc, "0000101111MMMRRR1010CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, { &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, + { pall, DSP56_jscc, "00001111CCCCaaaaaaaaaaaa", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::AA, 0x000fff }, }}, +// exception is possible, it should be moved lower, after move +// { DSP56_jsclr, "000010110mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, + { p_0_3, DSP56_jsclr, "0000101110pppppp1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jsclr, "0000101110pppppp1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p563xx, DSP56_jsclr, "0000000111qqqqqq1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jsclr, "0000000111qqqqqq1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jsclr, "0000101111DDDDDD000bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { p566xx, DSP56_jsclr, "0000101111DDDDDD0000bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, +// exception is possible, it should be moved lower, after move +// { DSP56_jset, "000010100mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, + { p_0_3, DSP56_jset, "0000101010pppppp1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jset, "0000101010pppppp1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p563xx, DSP56_jset, "0000000110qqqqqq1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jset, "0000000110qqqqqq1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jset, "0000101011DDDDDD001bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { p566xx, DSP56_jset, "0000101011DDDDDD0010bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { pall, DSP56_jsr, "0000101111MMMRRR10000000", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, + { pall, DSP56_jsr, "000011010000aaaaaaaaaaaa", 0, {{ &dsp56k_t::AA, 0x000fff }, }}, +// exception is possible, it should be moved lower, after move +// { DSP56_jsset, "000010110mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, + { p_0_3, DSP56_jsset, "0000101110pppppp1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jsset, "0000101110pppppp1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_pppppp, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p563xx, DSP56_jsset, "0000000111qqqqqq1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jsset, "0000000111qqqqqq1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_qqqqqq, 0x3f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jsset, "0000101111DDDDDD001bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, + { p566xx, DSP56_jsset, "0000101111DDDDDD0010bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::S_DDDDDD, 0x003f00 }, { &dsp56k_t::AAE, 0x0000 }, }}, +// L + { p_3_6, DSP56_lra, "0000010011000RRR000ddddd", 0, {{ &dsp56k_t::S_RRR, 0x000700 }, { &dsp56k_t::D_ddddd, 0x00001f }, }}, + { p_3_6, DSP56_lra, "0000010001000000010ddddd", 0, {{ &dsp56k_t::S_PC_dispL,0x000000}, { &dsp56k_t::D_ddddd, 0x00001f }, }}, + { p_3_6, DSP56_lsl, "000011000001111010iiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00003e }, { &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_lsl, "00001100000111100001sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_lsr, "000011000001111011iiiiiD", 0, {{ &dsp56k_t::S_xi, 0x00003e }, { &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_lsr, "00001100000111100011sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_lua, "0000010000aaaRRRaaaadddd", 0, {{ &dsp56k_t::S_RR_dispS,0x003ff0}, { &dsp56k_t::D_dddd, 0x00000f }, }}, + { p_3_6, DSP56_lua, "00000100010MMRRR000ddddd", 0, {{ &dsp56k_t::S_MMRRR, 0x001f00 }, { &dsp56k_t::D_ddddd, 0x00001f }, }}, + { p5600x, DSP56_lua, "00000100010MMRRR0001dddd", 0, {{ &dsp56k_t::S_MMRRR, 0x001f00 }, { &dsp56k_t::D_dddd, 0x00000f }, }}, +// M + { p_0_3, DSP56_mac, "00000001000sssss11QQdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p566xx, DSP56_mac, "000000010000ssss11QQdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_3_6, DSP56_maci, "000000010100000111qqdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_3_6, DSP56_mac_s_u, "00000001001001101sdkQQQQ", 0, {{ &dsp56k_t::s, 0x000040 }, { &dsp56k_t::sign, 0x000010 }, { &dsp56k_t::S_QQQQ, 0x000f }, { &dsp56k_t::D_d, 0x00020 }, }}, + { p_0_3, DSP56_macr, "00000001000sssss11QQdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p566xx, DSP56_macr, "000000010000ssss11QQdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030 }, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_3_6, DSP56_macri, "000000010100000111qqdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_3_6, DSP56_merge, "00001100000110111000sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, + { p_3_6, DSP56_move, "0000101s01110RRR1Wdddddd", 0, {{ F_SWITCH, 0x000040 }, { &dsp56k_t::mem_type, 0x010000 }, { &dsp56k_t::D_RRR_dispL, 0x000700 }, { &dsp56k_t::D_DDDDDD,0x3f }, }}, + { p_3_6, DSP56_move, "0000001aaaaaaRRR1asWdddd", 0, {{ F_SWITCH, 0x000010 }, { &dsp56k_t::mem_type, 0x000020 }, { &dsp56k_t::D_RRR_dispS, 0x01ff40 }, { &dsp56k_t::D_DDDD, 0x0f }, }}, +// moved lower due to potential opcode overlap + { p_0_3, DSP56_jclr, "000010100mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jclr, "000010100mMMMRRR1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jsclr, "000010110mMMMRRR1S0bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jsclr, "000010110mMMMRRR1S00bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jset, "000010100mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jset, "000010100mMMMRRR1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p_0_3, DSP56_jsset, "000010110mMMMRRR1S1bbbbb", 0, {{ &dsp56k_t::S_xi, 0x00001f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { p566xx, DSP56_jsset, "000010110mMMMRRR1S10bbbb", 0, {{ &dsp56k_t::S_xi, 0x00000f }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::S_mMMMRRR, 0x7f00 }, { &dsp56k_t::AAE, 0x00000 }, }}, + { pall, DSP56_movec, "00000100W1eeeeee101ddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::D_DDDDD, 0x0001f }, }}, + { pall, DSP56_movec, "00000101WmMMMRRR0s1ddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, { &dsp56k_t::D_DDDDD, 0x0001f }, }}, + { pall, DSP56_movec, "00000101iiiiiiii101ddddd", 0, {{ &dsp56k_t::S_xi, 0x00ff00 }, { &dsp56k_t::D_DDDDD, 0x00001f }, }}, + { pall, DSP56_movem, "00000111WmMMMRRR10dddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_mMMMRRR, 0x7f00 }, { &dsp56k_t::D_DDDDDD, 0x0003f }, }}, + { pall, DSP56_movem, "00000111W0aaaaaa00dddddd", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_aaaaaa, 0x3f00 }, { &dsp56k_t::D_DDDDDD, 0x0003f }, }}, + { pall, DSP56_movep, "0000100SW1MMMRRR01pppppp", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::mem_type, 0x10000 }, { &dsp56k_t::D_pppppp, 0x3f }}}, + { pall, DSP56_movep, "0000100SW1dddddd00pppppp", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::mem_type, 0x10000 }, { &dsp56k_t::D_pppppp, 0x3f }}}, + { pall, DSP56_movep, "0000100sW1MMMRRR1spppppp", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::mem_type, 0x10000 }, { &dsp56k_t::D_pppppp, 0x3f }}}, + { p_3_6, DSP56_movep, "00000111W1MMMRRR0sqqqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::X_type, 0x00000 }, { &dsp56k_t::D_qqqqqq, 0x3f }}}, + { p_3_6, DSP56_movep, "00000111W0MMMRRR1sqqqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::Y_type, 0x00000 }, { &dsp56k_t::D_qqqqqq, 0x3f }}}, + { p_3_6, DSP56_movep, "00000100W1dddddd1q0qqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::X_type, 0x00000 }, { &dsp56k_t::D_qXqqqqq,0x5f }}}, + { p_3_6, DSP56_movep, "00000100W1dddddd0q1qqqqq", 0, {{ F_SWITCH, 0x008000 }, { &dsp56k_t::D_DDDDDD, 0x003f00 }, { NULL, 0x0000 }, { &dsp56k_t::Y_type, 0x00000 }, { &dsp56k_t::D_qXqqqqq,0x5f }}}, + { p_3_6, DSP56_movep, "000000001WMMMRRR0sqqqqqq", 0, {{ F_SWITCH, 0x004000 }, { &dsp56k_t::P_type, 0x000000 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, { &dsp56k_t::mem_type, 0x00040 }, { &dsp56k_t::D_qqqqqq, 0x3f }}}, + { p_0_3, DSP56_mpy, "00000001000sssss11QQdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p566xx, DSP56_mpy, "000000010000ssss11QQdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_3_6, DSP56_mpy_s_u, "00000001001001111sdkQQQQ", 0, {{ &dsp56k_t::s, 0x000040 }, { &dsp56k_t::sign, 0x000010,}, { &dsp56k_t::S_QQQQ, 0x000f }, { &dsp56k_t::D_d, 0x00020 }, }}, + { p_3_6, DSP56_mpyi, "000000010100000111qqdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000,}, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_0_3, DSP56_mpyr, "00000001000sssss11QQdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_sssss, 0x1f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p566xx, DSP56_mpyr, "000000010000ssss11QQdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQ, 0x000030,}, { &dsp56k_t::S_ssss, 0x0f00 }, { &dsp56k_t::D_d, 0x00008 }, }}, + { p_3_6, DSP56_mpyri, "000000010100000111qqdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_ximm, 0x000000,}, { &dsp56k_t::S_qq, 0x0030 }, { &dsp56k_t::D_d, 0x00008 }, }}, +// N + { pall, DSP56_nop, "000000000000000000000000", 0, {{ 0 } }}, + { pall, DSP56_norm, "0000000111011RRR0001d101", 0, {{ &dsp56k_t::S_RRR, 0x000700 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_normf, "00001100000111100010sssD", 0, {{ &dsp56k_t::S_sss, 0x00000e }, { &dsp56k_t::D_d, 0x000001 }, }}, +// O + { p_3_6, DSP56_or, "0000000101iiiiii1000d010", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_or, "00000001010000001100d010", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_ori, "00000000iiiiiiii111110EE", 0, {{ &dsp56k_t::S_xi, 0x00ff00 }, { &dsp56k_t::D_EE, 0x000003 }, }}, +// P + { p563xx, DSP56_pflush, "000000000000000000000011", 0, {{ 0 } }}, + { p563xx, DSP56_pflushun,"000000000000000000000001", 0, {{ 0 } }}, + { p563xx, DSP56_pfree, "000000000000000000000010", 0, {{ 0 } }}, + { p563xx, DSP56_plock, "0000101111MMMRRR10000001", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, + { p563xx, DSP56_plockr, "000000000000000000001111", 0, {{ &dsp56k_t::D_PC_dispL,0x00000 }, }}, + { p563xx, DSP56_punlock, "0000101011MMMRRR10000001", 0, {{ &dsp56k_t::D_MMMRRR, 0x003f00 }, }}, + { p563xx, DSP56_punlockr,"000000000000000000001110", 0, {{ &dsp56k_t::D_PC_dispL,0x00000 }, }}, +// R + { pall, DSP56_rep, "000001100mMMMRRR0S100000", 0, {{ &dsp56k_t::mem_type, 0x000040 }, { &dsp56k_t::D_mMMMRRR,0x007f00 }, }}, + { pall, DSP56_rep, "0000011011dddddd00100000", 0, {{ &dsp56k_t::D_DDDDDD, 0x003f00 }, }}, + { pall, DSP56_rep, "00000110iiiiiiii1010hhhh", 0, {{ &dsp56k_t::D_xih, 0x00ff0f }, }}, + { pall, DSP56_reset, "000000000000000010000100", 0, {{ 0 } }}, + { pall, DSP56_rti, "000000000000000000000100", 0, {{ 0 } }}, + { pall, DSP56_rts, "000000000000000000001100", 0, {{ 0 } }}, +// S + { pall, DSP56_stop, "000000000000000010000111", 0, {{ 0 } }}, + { p_3_6, DSP56_sub, "0000000101iiiiii1000d100", 0, {{ &dsp56k_t::S_xi, 0x003f00 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p_3_6, DSP56_sub, "00000001010000001100d100", 0, {{ &dsp56k_t::S_ximm, 0x000000 }, { &dsp56k_t::D_d, 0x000008 }, }}, + { p5600x, DSP56_swi, "000000000000000000000110", 0, {{ 0 } }}, +// T + { pall, DSP56_tcc, "00000010CCCC00000JJJD000", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::SS_JJJd, 0x000078 }, }}, + { pall, DSP56_tcc, "00000011CCCC0ttt0JJJDTTT", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::SS_JJJd, 0x000078 }, { &dsp56k_t::space, 0x0000 }, { &dsp56k_t::S_RRR, 0x00700 }, { &dsp56k_t::D_RRR, 0x07 }}}, + { p_3_6, DSP56_tcc, "00000010CCCC1ttt00000TTT", 0, {{ &dsp56k_t::CCCC, 0x00f000 }, { &dsp56k_t::S_RRR, 0x000700 }, { &dsp56k_t::D_RRR, 0x0007 }, }}, + { p_3_6, DSP56_trap, "000000000000000000000110", 0, {{ 0 } }}, + { p_3_6, DSP56_trapcc, "00000000000000000001CCCC", 0, {{ &dsp56k_t::CCCC, 0x00000f }, }}, +// V + { p_3_6, DSP56_vsl, "0000101S11MMMRRR110i0000", 0, {{ &dsp56k_t::S_S, 0x010000 }, { &dsp56k_t::S_i, 0x000010 }, { &dsp56k_t::D_MMMRRR, 0x3f00 }, }}, +// W + { pall, DSP56_wait, "000000000000000010000110", 0, {{ 0 } }}, + +// Parallel move + + { pall, DSP56_move, "00000000", 0, {{ 0 } }}, + { p_3_6, DSP56_max, "00011101", 0, {{ &dsp56k_t::m_A_B, 0x000001 }, }}, + { p_3_6, DSP56_maxm, "00010101", 0, {{ &dsp56k_t::m_A_B, 0x000001 }, }}, + { pall, DSP56_addr, "0000d010", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, + { pall, DSP56_tst, "0000d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_subr, "0000d110", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, + { pall, DSP56_rnd, "0001d001", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_addl, "0001d010", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, + { pall, DSP56_clr, "0001d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_subl, "0001d110", 0, {{ &dsp56k_t::SD_d, 0x000008 }, }}, + { pall, DSP56_not, "0001d111", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_asr, "0010d010", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_lsr, "0010d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_abs, "0010d110", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_ror, "0010d111", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_asl, "0011d010", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_lsl, "0011d011", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_neg, "0011d110", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_rol, "0011d111", 0, {{ &dsp56k_t::D_d, 0x000008 }, }}, + { pall, DSP56_adc, "001Jd001", 0, {{ &dsp56k_t::SD_Jd, 0x000018 }, }}, + { pall, DSP56_sbc, "001Jd101", 0, {{ &dsp56k_t::SD_Jd, 0x000018 }, }}, + { pall, DSP56_or, "01JJd010", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, + { pall, DSP56_eor, "01JJd011", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, + { pall, DSP56_and, "01JJd110", 0, {{ &dsp56k_t::SD_JJd, 0x000038 }, }}, + { pall, DSP56_add, "0JJJd000", 0, {{ &dsp56k_t::SD_JJJd, 0x000078 }, }}, + { pall, DSP56_tfr, "0JJJd001", 0, {{ &dsp56k_t::SS_JJJd, 0x000078 }, }}, + { pall, DSP56_sub, "0JJJd100", 0, {{ &dsp56k_t::SD_JJJd, 0x000078 }, }}, + { pall, DSP56_cmp, "0JJJd101", 0, {{ &dsp56k_t::SS_JJJd, 0x000078 }, }}, + { pall, DSP56_cmpm, "0JJJd111", 0, {{ &dsp56k_t::SS_JJJd, 0x000078 }, }}, + { pall, DSP56_mpy, "1QQQdk00", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, + { pall, DSP56_mpyr, "1QQQdk01", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, + { pall, DSP56_mac, "1QQQdk10", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, + { pall, DSP56_macr, "1QQQdk11", 0, {{ &dsp56k_t::sign, 0x000004 }, { &dsp56k_t::S_QQQ, 0x000070 }, { &dsp56k_t::D_d, 0x0008 }, }}, +}; +static opcode_t table_6x_32[qnumber(table_6x_24)]; + +//---------------------------------------------------------------------- +static par_move pmoves_61[] = +{ + { p_1, "01001010----F---" },// No Parallel Data Move + { p_1, "0100IIII----F---", {{&dsp56k_t::SD_IIII, 0x0fff }}, },// Register to Register Data Move + { p_1, "00110zRR----F---", {{&dsp56k_t::D_zRR, 0x07ff }}, },// Address Register Update +}; + +//---------------------------------------------------------------------- +static opcode_t table_61_24[] = +{ +// Warning! All 32-masks have swapped halves (compared to the documentation) +// Cmd with No Parallel move + { p_1, DSP56_bfchg, "BBB10010iiiiiiii0001010011Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}}, + { p_1, DSP56_bfchg, "BBB10010iiiiiiii00010100101---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}}, + { p_1, DSP56_bfchg, "BBB10010iiiiiiii00010100100DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}}, + { p_1, DSP56_bfclr, "BBB00100iiiiiiii0001010011Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}}, + { p_1, DSP56_bfclr, "BBB00100iiiiiiii00010100101---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}}, + { p_1, DSP56_bfclr, "BBB00100iiiiiiii00010100100DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}}, + { p_1, DSP56_bfset, "BBB11000iiiiiiii0001010011Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}}, + { p_1, DSP56_bfset, "BBB11000iiiiiiii00010100101---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}}, + { p_1, DSP56_bfset, "BBB11000iiiiiiii00010100100DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}}, + { p_1, DSP56_bftsth, "BBB10000iiiiiiii0001010001Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}}, + { p_1, DSP56_bftsth, "BBB10000iiiiiiii00010100001---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}}, + { p_1, DSP56_bftsth, "BBB10000iiiiiiii00010100000DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}}, + { p_1, DSP56_bftstl, "BBB00000iiiiiiii0001010001Pppppp", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_Pppppp, 0x3f}}}, + { p_1, DSP56_bftstl, "BBB00000iiiiiiii00010100001---RR", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::DX_RR, 0x03}}}, + { p_1, DSP56_bftstl, "BBB00000iiiiiiii00010100000DDDDD", cl_0, {{&dsp56k_t::S_BBBiiiiiiii, 0xe0ff0000}, {&dsp56k_t::D_DDDDD, 0x1f}}}, + { p_1, DSP56_movec, "00111WDDDDD0----00000101BBBBBBBB", cl_0, {{F_SWITCH, 0x04000000}, {&dsp56k_t::X_type, 0 },{&dsp56k_t::D_BBBBBBBB, 0xff}, {&dsp56k_t::D_DDDDD, 0x03e00000 }}}, + { p_1, DSP56_movem, "0000001W--0--HHH00000101BBBBBBBB", cl_0, {{F_SWITCH, 0x01000000}, {&dsp56k_t::P_type, 0 },{&dsp56k_t::D_BBBBBBBB, 0xff}, {&dsp56k_t::D_HHH, 0x00070000 }}}, + { p_1, DSP56_adc, "000101010000F01J", cl_0, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_asl4, "000101010011F001", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_asr4, "000101010011F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_asr16, "000101010111F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_asr16, "000101010111F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_bcc, "xxxxxxxxxxxxxxxx00000111--11cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_bcc, "001011cccceeeeee", cl_0, {{&dsp56k_t::CCCC, 0x000003c0}, {&dsp56k_t::D_PC_eeeeee, 0x3f}}}, + { p_1, DSP56_bcc, "00000111RR10cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_RR, 0xc0}}}, + { p_1, DSP56_bra, "xxxxxxxxxxxxxxxx00000001001111--", cl_0, {{&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_bra, "00001011aaaaaaaa", cl_0, {{&dsp56k_t::D_PC_aaaaaaaa, 0x000000ff}}}, + { p_1, DSP56_bra, "00000001001011RR", cl_0, {{&dsp56k_t::D_PC_RR, 0x00000003}}}, + { p_1, DSP56_brkcc, "000000010001cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}}}, + { p_1, DSP56_bscc, "xxxxxxxxxxxxxxxx00000111--01cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_bscc, "00000111RR00cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_PC_RR, 0xc0}}}, + { p_1, DSP56_bsr, "xxxxxxxxxxxxxxxx00000001001110--", cl_0, {{&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_bsr, "00000001001010RR", cl_0, {{&dsp56k_t::D_PC_RR, 0x00000003}}}, + { p_1, DSP56_chkaau, "0000000000000100", cl_0}, + { p_1, DSP56_debug, "0000000000000001", cl_0}, + { p_1, DSP56_debugcc, "000000000101cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}}}, + { p_1, DSP56_div, "000101010--0F1DD", cl_0, {{&dsp56k_t::S_DD, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_dmac, "0001010110s1FsQQ", cl_0, {{&dsp56k_t::ss, 0x00000024}, {&dsp56k_t::S_QQ2, 0x03}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_do, "xxxxxxxxxxxxxxxx00000000110---RR", cl_0, {{&dsp56k_t::D_RR, 0x00000003}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_do, "xxxxxxxxxxxxxxxx00001110iiiiiiii", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_do, "xxxxxxxxxxxxxxxx00000100000DDDDD", cl_0, {{&dsp56k_t::S_DDDDD, 0x0000001f}, {&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_do_f, "xxxxxxxxxxxxxxxx0000000000000010", cl_0, {{&dsp56k_t::D_PC_dispL, 0xffff0000}}}, + { p_1, DSP56_enddo, "0000000000001001", cl_0}, + { p_1, DSP56_ext, "000101010101F010", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_ill, "0000000000001111", cl_0}, + { p_1, DSP56_imac, "000101011010FQQQ", cl_0, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_impy, "000101011000FQQQ", cl_0, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_jcc, "xxxxxxxxxxxxxxxx00000110--11cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_xi_adr_16, 0xffff0000}}}, + { p_1, DSP56_jcc, "00000110RR10cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::DB_RR, 0xc0}}}, + { p_1, DSP56_jmp, "xxxxxxxxxxxxxxxx00000001001101--", cl_0, {{&dsp56k_t::D_xi_adr_16, 0xffff0000}}}, + { p_1, DSP56_jmp, "00000001001001RR", cl_0, {{&dsp56k_t::DB_RR, 0x00000003}}}, + { p_1, DSP56_jscc, "xxxxxxxxxxxxxxxx00000110--01cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::D_xi_adr_16, 0xffff0000}}}, + { p_1, DSP56_jscc, "00000110RR00cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}, {&dsp56k_t::DB_RR, 0xc0}}}, + { p_1, DSP56_jsr, "xxxxxxxxxxxxxxxx00000001001100--", cl_0, {{&dsp56k_t::D_xi_adr_16, 0xffff0000}}}, + { p_1, DSP56_jsr, "00001010AAAAAAAA", cl_0, {{&dsp56k_t::D_xi, 0x000000ff}}}, + { p_1, DSP56_jsr, "00000001001000RR", cl_0, {{&dsp56k_t::DB_RR, 0x00000003}}}, + { p_1, DSP56_lea, "0000000111TTMMRR", cl_0, {{&dsp56k_t::S_MMRR, 0x0000000f}, {&dsp56k_t::D_RR, 0x30}}}, + { p_1, DSP56_lea, "0000000110NNMMRR", cl_0, {{&dsp56k_t::S_MMRR, 0x0000000f}, {&dsp56k_t::D_NN, 0x30}}}, + { p_1, DSP56_mac_s_u, "000101011110FsQQ", cl_0, {{&dsp56k_t::s, 0x00000004}, {&dsp56k_t::S_QQ2, 0x03}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_movec, "00111WDDDDD0MMRR", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::X_type, 0}, {&dsp56k_t::D_MMRR,0x0f}, {&dsp56k_t::D_DDDDD, 0x3e0}}}, + { p_1, DSP56_movec, "00111WDDDDD1q0RR", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::X_type, 0}, {&dsp56k_t::D_qRR, 0x0b}, {&dsp56k_t::D_DDDDD, 0x3e0}}}, + { p_1, DSP56_movec, "00111WDDDDD1Z11-", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::X_type, 0}, {&dsp56k_t::D_Z, 0x08}, {&dsp56k_t::D_DDDDD, 0x3e0}}}, + { p_1, DSP56_movec, "xxxxxxxxxxxxxxxx00111WDDDDD1t10-", cl_0, {{F_SWITCH, 0x00000400}, {&dsp56k_t::D_t, 0xffff0008}, {0,0}, {&dsp56k_t::D_DDDDD, 0x3e0}}}, + { p_1, DSP56_movec, "001010dddddDDDDD", cl_0, {{&dsp56k_t::S_DDDDD, 0x000003e0}, {&dsp56k_t::D_DDDDD, 0x1f}}}, + { p_1, DSP56_movei, "001000DDBBBBBBBB", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_DD, 0x300}}}, + { p_1, DSP56_movem, "0000001WRR0MMHHH", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::P_type, 0}, {&dsp56k_t::D_RR0MM, 0xd8}, {&dsp56k_t::D_HHH, 0x07}}}, + { p_1, DSP56_movem, "0000001WRR11mmRR", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::P_type, 0}, {&dsp56k_t::D_RR11m, 0xc8}, {&dsp56k_t::X_type,0}, {&dsp56k_t::D_mRR, 0x07}}}, + { p_1, DSP56_movep, "0001100WHH1ppppp", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::D_ppppp, 0x1f}, {0, 0}, {&dsp56k_t::D_HH, 0xc0}}}, + { p_1, DSP56_movep, "0000110WRRmppppp", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::D_ppppp, 0x1f}, {0, 0}, {&dsp56k_t::D_RRm, 0xe0}}}, + { p_1, DSP56_moves, "0001100WHH0aaaaa", cl_0, {{F_SWITCH, 0x00000100}, {&dsp56k_t::D_aaaaa, 0x1f}, {0, 0}, {&dsp56k_t::D_HH, 0xc0}}}, + { p_1, DSP56_mpy_s_u, "000101011100FsQQ", cl_0, {{&dsp56k_t::s, 0x00000004}, {&dsp56k_t::S_QQ2, 0x03}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_negc, "000101010110F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_nop, "0000000000000000", cl_0}, + { p_1, DSP56_norm, "000101010010F0RR", cl_0, {{&dsp56k_t::S_RR, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_andi, "00011EE0iiiiiiii", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_EE, 0x0600}}}, + { p_1, DSP56_ori, "00011EE1iiiiiiii", cl_0, {{&dsp56k_t::S_xi, 0x000000ff}, {&dsp56k_t::D_EE, 0x0600}}}, + { p_1, DSP56_rep, "00000000111---RR", cl_0, {{&dsp56k_t::D_RR, 0x00000003}}}, + { p_1, DSP56_rep, "00001111iiiiiiii", cl_0, {{&dsp56k_t::D_xi, 0x000000ff}}}, + { p_1, DSP56_rep, "00000100001DDDDD", cl_0, {{&dsp56k_t::D_DDDDD, 0x0000001f}}}, + { p_1, DSP56_repcc, "000000010101cccc", cl_0, {{&dsp56k_t::CCCC, 0x0000000f}}}, + { p_1, DSP56_reset, "0000000000001000", cl_0}, + { p_1, DSP56_rti, "0000000000000111", cl_0}, + { p_1, DSP56_rts, "0000000000000110", cl_0}, + { p_1, DSP56_stop, "0000000000001010", cl_0}, + { p_1, DSP56_swap, "000101010111F001", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_swi, "0000000000000101", cl_0}, + { p_1, DSP56_tcc, "000100ccccTTFh0h", cl_0, {{&dsp56k_t::CCCC, 0x000003c0}, {&dsp56k_t::S_Fh0h, 0x0d}, {&dsp56k_t::D_F, 0x08}, {&dsp56k_t::space, 0}, {&dsp56k_t::SD_TT, 0x30}}}, + { p_1, DSP56_tfr2, "000101010000F00J", cl_0, {{&dsp56k_t::SD_F00J, 0x00000009}}}, + { p_1, DSP56_tfr3, "001001mWRRDDFHHH", cl_0, {{&dsp56k_t::S_F, 0x00000008}, {&dsp56k_t::D_DD, 0x30}, {&dsp56k_t::space, 0}, {&dsp56k_t::SD_mWRRHHH, 0x03ff}}}, + { p_1, DSP56_tst2, "000101010001-1DD", cl_0, {{&dsp56k_t::D_DD, 0x00000003}}}, + { p_1, DSP56_wait, "0000000000001011", cl_0}, + { p_1, DSP56_zero, "000101010101F000", cl_0, {{&dsp56k_t::D_F, 0x00000008}}}, +// Cmd with Parallel move +// 32-bit mask + { p_1, DSP56_pmov, "----HHHW--------00000101BBBBBBBB", cl_1_3 },// X Memory Data Move with short displacement +// 16-bit mask + { p_1, DSP56_mac, "00010111RRDDFQQQ", cl_3, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mpy, "00010110RRDDFQQQ", cl_3, {{&dsp56k_t::S_QQQ, 0x00000007}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mpy, "011mmKKK1--0F0QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mpyr, "011mmKKK1--1F0QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mac, "011mmKKK1--0F1QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_macr, "011mmKKK1--1F1QQ", cl_2, {{&dsp56k_t::S_QQ, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_move, "011mmKKK0rr10000", cl_2 }, + { p_1, DSP56_tfr, "011mmKKK0rr1F0DD", cl_2, {{&dsp56k_t::S_DD, 0x00000003}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_sub, "011mmKKK0rruF1uu", cl_2, {{&dsp56k_t::S_uFuuu_sub, 0x0000001f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_add, "011mmKKK0rruFuuu", cl_2, {{&dsp56k_t::S_uFuuu_add, 0x0000001f}, {&dsp56k_t::D_F, 0x08}}}, +// 8-bit mask + { p_1, DSP56_clr, "0000F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_add, "0000FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_move, "00010001", cl_1 }, + { p_1, DSP56_tfr, "0001FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_rnd, "0010F000", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_tst, "0010F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_inc, "0010F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_inc24, "0010F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_inc, "0010F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_or, "0010F1JJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_asr, "0011F000", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_asl, "0011F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_lsr, "0011F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_lsl, "0011F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_eor, "0011F1JJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_subl, "0100F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_sub, "0100FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_clr24, "0101F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_sbc, "0101F01J", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_cmp, "0101FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_neg, "0110F000", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_not, "0110F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_dec, "0110F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_dec24, "0110F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_and, "0110F1JJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_abs, "0111F001", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_ror, "0111F010", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_rol, "0111F011", cl_1, {{&dsp56k_t::D_F, 0x00000008}}}, + { p_1, DSP56_cmpm, "0111FJJJ", cl_1, {{&dsp56k_t::S_FJJJ, 0x0000000f}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mpy, "1k00FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mpyr, "1k01FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_mac, "1k10FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}}, + { p_1, DSP56_macr, "1k11FQQQ", cl_1, {{&dsp56k_t::sign, 0x00000040}, {&dsp56k_t::S_QQQ, 0x07}, {&dsp56k_t::D_F, 0x08}}}, +}; +static opcode_t table_61_32[qnumber(table_61_24)]; + +static void make_masks(opcode_t *table, int qty, int n_bits) +{ + for ( int i = 0; i < qty; i++ ) + { + for ( int b = 0; b < strlen(table[i].recog); b++ ) + { + table[i].value <<= 1; + table[i].mask <<= 1; + + if ( table[i].recog[b] == '1' || table[i].recog[b] == '0' ) + table[i].mask++; + + if ( table[i].recog[b] == '1' ) + table[i].value++; + } + + // int n_bits = is561xx() ? 32 : 24; + for ( int j = 0; j < FUNCS_COUNT; j++ ) + { + if ( table[i].funcs[j].func ) + { + for ( int b = 0; b < n_bits; b++ ) + { + if ( table[i].funcs[j].mask & (1 << b) ) + break; + table[i].funcs[j].shift++; + } + } + } + } +} + +//---------------------------------------------------------------------- +static void make_masks2(par_move *pmoves, int qty) +{ + for ( int i = 0; i < qty; i++ ) + { + for ( int b = 0; b < 16; b++ ) + { + pmoves[i].value <<= 1; + pmoves[i].mask <<= 1; + + if ( pmoves[i].recog[b] == '1' || pmoves[i].recog[b] == '0' ) + pmoves[i].mask++; + + if ( pmoves[i].recog[b] == '1' ) + pmoves[i].value++; + } + + for ( int j = 0; j < FUNCS_COUNT; j++ ) + { + if ( pmoves[i].funcs[j].func ) + { + for ( int b = 0; b < 16; b++ ) + { + if ( pmoves[i].funcs[j].mask & (1 << b) ) + break; + pmoves[i].funcs[j].shift++; + } + } + } + } +} + + +//---------------------------------------------------------------------- +// singletons to init tables thread-aware +struct table_61_24_t +{ + static const opcode_t *get() + { + static table_61_24_t instance; //lint !e1788 only by its constructor/destructor + return table_61_24; + } +private: + table_61_24_t() + { + make_masks(table_61_24, qnumber(table_61_24), 24); + } + ~table_61_24_t() = default; + table_61_24_t(const table_61_24_t&) = delete; + table_61_24_t &operator=(const table_61_24_t&) = delete; +}; + +struct table_61_32_t +{ + static const opcode_t *get() + { + static table_61_32_t instance; //lint !e1788 only by its constructor/destructor + return table_61_32; + } +private: + table_61_32_t() + { + memcpy(table_61_32, table_61_24, sizeof(table_61_24)); + make_masks(table_61_32, qnumber(table_61_32), 32); + } + ~table_61_32_t() = default; + table_61_32_t(const table_61_32_t&) = delete; + table_61_32_t &operator=(const table_61_32_t&) = delete; +}; + +struct table_6x_24_t +{ + static const opcode_t *get() + { + static table_6x_24_t instance; //lint !e1788 only by its constructor/destructor + return table_6x_24; + } +private: + table_6x_24_t() + { + make_masks(table_6x_24, qnumber(table_6x_24), 24); + } + ~table_6x_24_t() = default; + table_6x_24_t(const table_6x_24_t&) = delete; + table_6x_24_t &operator=(const table_6x_24_t&) = delete; +}; + +struct table_6x_32_t +{ + static const opcode_t *get() + { + static table_6x_32_t instance; //lint !e1788 only by its constructor/destructor + return table_6x_32; + } +private: + table_6x_32_t() + { + memcpy(table_6x_32, table_6x_24, sizeof(table_6x_24)); + make_masks(table_6x_32, qnumber(table_6x_32), 32); + } + ~table_6x_32_t() = default; + table_6x_32_t(const table_6x_32_t&) = delete; + table_6x_32_t &operator=(const table_6x_32_t&) = delete; +}; + +struct pmoves_61_t +{ + static const par_move *get() + { + static pmoves_61_t instance; //lint !e1788 only by its constructor/destructor + return pmoves_61; + } +private: + pmoves_61_t() + { + make_masks2(pmoves_61, qnumber(pmoves_61)); + } + ~pmoves_61_t() = default; + pmoves_61_t(const pmoves_61_t&) = delete; + pmoves_61_t &operator=(const pmoves_61_t&) = delete; +}; + +struct pmoves_6x_t +{ + static const par_move *get() + { + static pmoves_6x_t instance; //lint !e1788 only by its constructor/destructor + return pmoves_6x; + } +private: + pmoves_6x_t() + { + make_masks2(pmoves_6x, qnumber(pmoves_6x)); + } + ~pmoves_6x_t() = default; + pmoves_6x_t(const pmoves_6x_t&) = delete; + pmoves_6x_t &operator=(const pmoves_6x_t&) = delete; +}; + +//---------------------------------------------------------------------- +// check if the instruction may be disassembled for the current processor +bool dsp56k_t::is_valid_insn(ushort proc) +{ + if ( is566xx() ) + { + if ( (proc & p566xx) == 0 ) + return false; + } + else if ( is563xx() ) + { + if ( (proc & p563xx) == 0 ) + return false; + } + else if ( is561xx() ) + { + if ( (proc & p561xx) == 0 ) + return false; + } + else + { + if ( (proc & p5600x) == 0 ) + return false; + } + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::disassemble_parallel_move(insn_t &insn, int i, int value) +{ + switch_to_additional_args(insn); + + const par_move *pmoves = is561xx() ? pmoves_61_t::get() : pmoves_6x_t::get(); + const par_move &ptr = pmoves[i]; + if ( !is_valid_insn(ptr.proc) ) + return false; + for ( int j = 0; j < FUNCS_COUNT; j++ ) + { + if ( ptr.funcs[j].func != NULL ) + { + int v = (value & ptr.funcs[j].mask) >> ptr.funcs[j].shift; + (this->*ptr.funcs[j].func)(insn, v); + } + } + return true; +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::decode_XY_R_mem(insn_t &insn, int value) +{ + /* order of operands depends on whether we are writing or reading */ + + if ( value & 0x0080 ) + { + mem_type(insn, (value >> 6) & 0x01); + + D_mMMMRRR(insn, (value & 0x3f) | 0x40); + op++; + + if ( value & 0x40 ) + D_ff(insn, (value >> 8) & 0x03, value & 0x40); + else + D_ff(insn, (value >> 10) & 0x03, value & 0x40); + } + else + { + if ( value & 0x40 ) + D_ff(insn, (value >> 8) & 0x03, value & 0x40); + else + D_ff(insn, (value >> 10) & 0x03, value & 0x40); + op++; + + mem_type(insn, (value >> 6) & 0x01); + + D_mMMMRRR(insn, (value & 0x3f) | 0x40); + } + + return true; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::recognize_parallel_move_class1(insn_t &insn, int value) +{ + int index = -1; + + if ( (value & 0xff00) == 0x4a00 ) + { + index = 0; // No Parallel Data Move 01001010----F--- + } + else if ( (value & 0xf000) == 0x4000 ) + { + index = 1; // Register to Register Data Move 0100IIII----F--- + } + else if ( (value & 0xf800) == 0x3000 ) + { + index = 2; // Address Register Update 00110zRR----F--- + } + else if ( (value & 0x8000) == 0x8000 ) // X Memory Data Move 1 1mRRHHHW----F--- + { + switch_to_additional_args(insn); + + if ( value & 0x0100 ) + { + X_type(insn, 0); + D_mRR(insn, (value >>12) & 0x07); + op++; + D_HHH(insn, (value >>9) & 0x07); + } + else + { + D_HHH(insn, (value >>9) & 0x07); + op++; + X_type(insn, 0); + D_mRR(insn, (value >>12) & 0x07); + } + return true; + } + else if ( (value & 0xf000) == 0x5000 ) // X Memory Data Move 2 0101HHHW----F--- + { + switch_to_additional_args(insn); + + if ( value & 0x0100 ) + { + X_type(insn, 0); + op->type = o_phrase; + op->phrase = 0; + op->phtype = ((value & 0x08) ? 9 : 10); + op++; + D_HHH(insn, (value >>9) & 0x07); + } + else + { + D_HHH(insn, (value >>9) & 0x07); + op++; + X_type(insn, 0); + op->type = o_phrase; + op->phrase = 0; + op->phtype = ((value & 0x08) ? 9 : 10); + } + return true; + } + + if ( index != -1 ) + return disassemble_parallel_move(insn, index, value); + return false; +} +//---------------------------------------------------------------------- +bool dsp56k_t::recognize_parallel_move_class1_3(insn_t &insn, int value) +{ + // X Memory Data Move with short displacement + //----HHHW--------00000101BBBBBBBB + + switch_to_additional_args(insn); + if ( (value >> 24) & 0x01 ) + { + X_type(insn, 0); + D_BBBBBBBB(insn, value & 0x0ff); + op++; + D_HHH(insn, (value >> 25 ) & 0x07); + } + else + { + D_HHH(insn, (value >> 25 ) & 0x07); + op++; + X_type(insn, 0); + D_BBBBBBBB(insn, value & 0x0ff); + } + return true; +} +//---------------------------------------------------------------------- +bool dsp56k_t::recognize_parallel_move_class2(insn_t &insn, int value) +{ + // Dual X Memory Data Read + // 011mmKKKXrrXXXXX + + static const char regs1[] = { -1, Y0, X1, Y1, X0, Y0, -1, Y1 }; + static const char regs2[] = { X0, X0, X0, X0, X1, X1, Y0, X1 }; + + switch_to_additional_args(insn); + + X_type(insn, 0); + D_mRR(insn, ((value >> 10) & 0x04) + ((value >> 5) & 0x03)); + op++; + char r = regs1[(value >>8) & 0x07]; + if ( r != -1 ) + opreg(insn, r); + else + D_F(insn, ((value & 0x08)>>3) ^ 0x01); + + + switch_to_additional_args(insn); + + X_type(insn, 0); + op->type = o_phrase; + op->phrase = 3; + + if ( (value >> 11) & 0x01 ) + op->phtype = 1; + else + op->phtype = 3; + + op++; + opreg(insn, regs2[(value >>8) & 0x07]); + + return true; + +} +//---------------------------------------------------------------------- +bool dsp56k_t::recognize_parallel_move_class3(insn_t &insn, int value) +{ + // X Memory Data Write and Register Data Move + // 0001011kRRDDXXXX + + + switch_to_additional_args(insn); + opreg(insn, ((value >>8) & 0x01) == 1 ? A : B); + op++; + X_type(insn, 0); + D_mRR(insn, 0x04 + ((value >> 6) & 0x03)); + + + switch_to_additional_args(insn); + S_DD(insn, (value >>4) & 0x03); + opreg(insn, ((value >>8) & 0x01) == 1 ? A : B); + + return true; + +} + + +//---------------------------------------------------------------------- +bool dsp56k_t::is_parallel_move(insn_t &insn, int value) +{ + int index = -1; + + if ( value == 0x2000 ) + index = 0; /* NOP */ + else if ( ((value & 0xe000) == 0x2000) && (((value >> 8) & 0x1f) >= 4) ) + index = 1; /* I */ + else if ( ((value >> 10) == 0x08) && (((value >> 5) & 0x1f) >= 4) && ((value & 0x1f) >= 4) ) + index = 2; /* R */ + else if ( (value >> 5) == 0x102 ) + index = 3; /* U */ + else if ( (value >> 4) == 0x202 ) + index = 4; /* IF */ + else if ( (value >> 4) == 0x203 ) + index = 5; /* IF.U */ + else if ( ((value & 0xc000) == 0x4000) && (((value >> 8) & 0x37) >= 4) ) + { + switch_to_additional_args(insn); + + if ( value & 0x0080 ) + { + mem_type(insn, (value >> 11) & 0x01); + D_mMMMRRR(insn, value & 0x7f); + op++; + D_ddddd(insn, ((value >> 8) & 0x07) | ((value >> 9) & 0x18)); + } + else + { + D_ddddd(insn, ((value >> 8) & 0x07) | ((value >> 9) & 0x18)); + op++; + mem_type(insn, (value >> 11) & 0x01); + D_mMMMRRR(insn, value & 0x7f); + } + + return true; + } + else if ( (value & 0xf000) == 0x1000 ) /* class I */ + { + switch_to_additional_args(insn); + + if ( value & 0x40 ) /* Y:R */ + { + D_df(insn, (value >> 10) & 0x03, value & 0x40); + switch_to_additional_args(insn); + decode_XY_R_mem(insn, value); + } + else /* X:R */ + { + decode_XY_R_mem(insn, value); + switch_to_additional_args(insn); + D_df(insn, (value >> 8) & 0x03, value & 0x40); + } + + return true; + } + else if ( (value & 0xfe40) == 0x0800 ) /* class II */ + { + switch_to_additional_args(insn); + + if ( value & 0x0080 ) /* Y:R */ + { + opreg(insn, Y0); + op++; + opreg(insn, (value & 0x0100) ? B : A); + + switch_to_additional_args(insn); + + D_d(insn, (value >> 8) & 0x01); + op++; + op->amode |= amode_y; + D_mMMMRRR(insn, (value & 0x3f) | 0x40); + } + else /* X:R */ + { + D_d(insn, (value >> 8) & 0x01); + op++; + op->amode |= amode_x; + D_mMMMRRR(insn, (value & 0x3f) | 0x40); + + switch_to_additional_args(insn); + + opreg(insn, X0); + op++; + opreg(insn, (value & 0x0100) ? B : A); + } + + return true; + } + else if ( (value & 0xf400) == 0x4000 ) /* L: */ + { + switch_to_additional_args(insn); + + if ( value & 0x0080 ) + { + op->amode |= amode_l; + D_mMMMRRR(insn, value & 0x7f); + op++; + D_LLL(insn, ((value & 0x0800) >> 9) | ((value & 0x0300) >> 8)); + } + else + { + D_LLL(insn, ((value & 0x0800) >> 9) | ((value & 0x0300) >> 8)); + op++; + op->amode |= amode_l; + D_mMMMRRR(insn, value & 0x7f); + } + + return true; + } + else if ( value & 0x8000 ) /* X: Y: */ + { + switch_to_additional_args(insn); + + /* X: */ + if ( value & 0x0080 ) + { + op->amode |= amode_x; + D_MMRRR_XY(insn, value & 0x1f); + op++; + D_ff(insn, (value >> 10) & 0x3, false); + } + else + { + D_ff(insn, (value >> 10) & 0x3, false); + op++; + op->amode |= amode_x; + D_MMRRR_XY(insn, value & 0x1f); + } + + switch_to_additional_args(insn); + + /* Y: */ + if ( value & 0x4000 ) + { + op->amode |= amode_y; + D_MMRRR_XY(insn, ((value >> 5) & 0x03) | (~value & 0x04) | ((value >> 9) & 0x18)); + op++; + D_ff(insn, (value >> 8) & 0x3, true); + } + else + { + D_ff(insn, (value >> 8) & 0x3, true); + op++; + op->amode |= amode_y; + D_MMRRR_XY(insn, ((value >> 5) & 0x03) | (~value & 0x04) | ((value >> 9) & 0x18)); + } + + return true; + } + + if ( index != -1 ) + return disassemble_parallel_move(insn, index, value); + return false; +} + +//---------------------------------------------------------------------- +bool dsp56k_t::use_table( + insn_t &insn, + const opcode_t *table, + uint32 code, + int entry, + int start, + int end) +{ + const opcode_t &ptr = table[entry]; + for ( int j = start; j <= end; j++ ) + { + if ( ptr.funcs[j].func == NULL ) + break; + int value = (code & ptr.funcs[j].mask) >> ptr.funcs[j].shift; + if ( !(this->*ptr.funcs[j].func)(insn, value) ) + return false; + } + return true; +} + +//---------------------------------------------------------------------- +void dsp56k_t::reset_ops(insn_t &insn) +{ + op = &insn.Op1; + for ( int i=0; i < UA_MAXOP; i++ ) + insn.ops[i].type = o_void; + memset(&aa, 0, sizeof(aa)); +} + +//---------------------------------------------------------------------- +int dsp56k_t::ana_61(insn_t &insn) +{ + int prev_insn_p_class = cl_0; + int insn_p_class; + uint code = ua_32bits(insn); + op = &insn.Op1; + memset(&aa, 0, sizeof(aa)); + aa.ea = insn.ea; + + const opcode_t *table_61_xx = is561xx() ? table_61_32_t::get() : table_61_24_t::get(); + for ( int i = 0; i < qnumber(table_61_24); i++ ) + { + const auto &te = table_61_xx[i]; + if ( (code & te.mask) == te.value ) + { + insn.itype = te.itype; + insn.size = 1; + insn_p_class = te.pmov_cl; + if ( strlen(te.recog) > 16 ) + insn.size = 2; + + // X Memory Data Move with short displacement + if ( prev_insn_p_class == cl_1_3 ) + { + insn.size = 2; + insn_p_class = cl_1_3; + } + else if ( insn_p_class == cl_1_3 ) + { + prev_insn_p_class = insn_p_class; + code >>= 16; + continue; + } + + + if ( te.funcs[0].func == F_SWITCH ) + { + int first, second; + if ( (code & te.funcs[0].mask) >> te.funcs[0].shift ) + { + first = 1; + second = 3; + } + else + { + first = 3; + second = 1; + } + if ( !use_table(insn, table_61_xx, code, i, first, first + 1) ) + { + reset_ops(insn); + continue; + } + op++; + if ( !use_table(insn, table_61_xx, code, i, second, second + 1) ) + { + reset_ops(insn); + continue; + } + } + else + { + if ( !use_table(insn, table_61_xx, code, i, 0, FUNCS_COUNT - 1) ) + { + reset_ops(insn); + continue; + } + } + + // analyze additional operands of parallel moves + switch ( insn_p_class ) + { + case cl_0:// No Parallel move + break; + case cl_1:// X Memory Data Move (common) + code = ushort(code & 0xffff); + recognize_parallel_move_class1(insn, code); + break; + case cl_1_3:// X Memory Data Move with short displacement + code = ua_32bits(insn); + recognize_parallel_move_class1_3(insn, code); + break; + case cl_2:// Dual X Memory Data Read + code = ushort(code & 0xffff); + recognize_parallel_move_class2(insn, code); + break; + case cl_3:// X Memory Data Write and Register Data Move + code = ushort(code & 0xffff); + recognize_parallel_move_class3(insn, code); + break; + } + + if ( insn.Op1.type == o_void && aa.nargs != 0 ) + { + insn.Op1 = aa.args[0][0]; + insn.Op2 = aa.args[0][1]; + aa.args[0][0].type = o_void; + aa.args[0][1].type = o_void; + } + return insn.size; + } + } + return 0; +} + +//---------------------------------------------------------------------- +int dsp56k_t::ana_6x(insn_t &insn) +{ + uint32 code = ua_next_24bits(insn); + op = &insn.Op1; + memset(&aa, 0, sizeof(aa)); + aa.ea = insn.ea; + + const opcode_t *table_6x_xx = is561xx() ? table_6x_32_t::get() : table_6x_24_t::get(); + for ( int i = 0; i < qnumber(table_6x_24); i++ ) + { + const auto &te = table_6x_xx[i]; + if ( (code & te.mask) == te.value + && is_valid_insn(te.proc) ) + { + insn.itype = te.itype; + if ( te.funcs[0].func == F_SWITCH ) + { + int first, second; + if ( (code & te.funcs[0].mask) >> te.funcs[0].shift ) + { + first = 1; + second = 3; + } + else + { + first = 3; + second = 1; + } + if ( !use_table(insn, table_6x_xx, code, i, first, first + 1) ) + { + reset_ops(insn); + continue; + } + op++; + if ( !use_table(insn, table_6x_xx, code, i, second, second + 1) ) + { + reset_ops(insn); + continue; + } + } + else + { + if ( !use_table(insn, table_6x_xx, code, i, 0, FUNCS_COUNT - 1) ) + { + reset_ops(insn); + continue; + } + } + + if ( te.recog[8] == '\0' ) + { + code = ushort(code>>8); + is_parallel_move(insn, code); + } + if ( insn.Op1.type == o_void && aa.nargs != 0 ) + { + insn.Op1 = aa.args[0][0]; + insn.Op2 = aa.args[0][1]; + aa.args[0][0].type = o_void; + aa.args[0][1].type = o_void; + } + return insn.size; + } + } + return 0; +} + +//-------------------------------------------------------------------------- +int dsp56k_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + return is561xx() ? ana_61(insn) : ana_6x(insn); +} + +//-------------------------------------------------------------------------- +void interr(const insn_t *insn, const char *module) +{ + const char *name = NULL; + if ( insn->itype < DSP56_last ) + name = Instructions[insn->itype].name; + warning("%a(%s): internal error in %s", insn->ea, name, module); +} diff --git a/idasdk75/module/dsp56k/dsp561xx.cfg b/idasdk76/module/dsp56k/dsp561xx.cfg similarity index 100% rename from idasdk75/module/dsp56k/dsp561xx.cfg rename to idasdk76/module/dsp56k/dsp561xx.cfg diff --git a/idasdk75/module/dsp56k/dsp563xx.cfg b/idasdk76/module/dsp56k/dsp563xx.cfg similarity index 100% rename from idasdk75/module/dsp56k/dsp563xx.cfg rename to idasdk76/module/dsp56k/dsp563xx.cfg diff --git a/idasdk75/module/dsp56k/dsp566xx.cfg b/idasdk76/module/dsp56k/dsp566xx.cfg similarity index 100% rename from idasdk75/module/dsp56k/dsp566xx.cfg rename to idasdk76/module/dsp56k/dsp566xx.cfg diff --git a/idasdk75/module/dsp56k/dsp56k.cfg b/idasdk76/module/dsp56k/dsp56k.cfg similarity index 100% rename from idasdk75/module/dsp56k/dsp56k.cfg rename to idasdk76/module/dsp56k/dsp56k.cfg diff --git a/idasdk76/module/dsp56k/dsp56k.hpp b/idasdk76/module/dsp56k/dsp56k.hpp new file mode 100644 index 0000000..909ec32 --- /dev/null +++ b/idasdk76/module/dsp56k/dsp56k.hpp @@ -0,0 +1,348 @@ + +#ifndef _DSP56K_HPP +#define _DSP56K_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include "../iohandler.hpp" +#define PROCMOD_NAME dsp56k +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + +//------------------------------------------------------------------ +// DSP56K instruction may have many operands. We keep them separately +// in the following structure. + +struct addargs_t +{ + ea_t ea; + int nargs; + op_t args[4][2]; + + addargs_t() : ea(BADADDR), nargs(0) { memset(args, 0, sizeof(args)); } +}; + +//------------------------------------------------------------------ +struct dsp56k_iohandler_t : public iohandler_t +{ + struct dsp56k_t ± + dsp56k_iohandler_t(dsp56k_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual const char *iocallback(const ioports_t &iop, const char *line) override; +}; + +struct dsp56k_t : public procmod_t +{ + netnode helper; + dsp56k_iohandler_t ioh = dsp56k_iohandler_t(*this, helper); + ea_t xmem = BADADDR; + ea_t ymem = BADADDR; + op_t *op = nullptr; // current operand + addargs_t aa; + int xmemsize = 0x10000; + int ymemsize = 0x10000; + int procnum = -1; // 0 - dsp56k, 1 - dsp561xx, 2 - dsp563xx, 3 - dsp566xx + bool flow = false; + + inline bool is561xx(void) const { return procnum == 1; } + inline bool is563xx(void) const { return procnum == 2; } + inline bool is566xx(void) const { return procnum == 3; } + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + const ioport_t *find_port(ea_t address); + void create_xmem_ymem(void); + void select_device(const char *dname, int resp_info); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + ea_t calc_mem(const insn_t &insn, const op_t &x) const; + ea_t AdditionalSegment(asize_t size, int offset, const char *name) const; + void handle_operand( + const insn_t &insn, + const op_t &x, + flags_t F, + bool is_forced, + bool isload); + int emu(const insn_t &insn); + void header(outctx_t &ctx); + void set_cpu(int procno); + bool D_EE(insn_t &insn, int value); + bool D_DDDDD(insn_t &insn, int value); + bool D_ff(const insn_t &insn, int value, int reg_bank); + bool D_df(insn_t &insn, int value, int reg_bank); + bool S_xi(insn_t &, int value); + bool D_ximm(insn_t &insn, int /*value*/); + bool S_ximm(insn_t &insn, int value); + bool S_sssss(insn_t &, int value); + bool S_ssss(insn_t &, int value); + bool D_xih(insn_t &, int value); + bool S_xih(insn_t &insn, int value); + bool SD_d(insn_t &insn, int value); + bool SS_JJJd(insn_t &insn, int value); + bool SD_JJJd(insn_t &insn, int value); + bool SD_Jd(insn_t &insn, int value); + bool D_d(insn_t &insn, int value); + bool S_S(insn_t &insn, int value); + bool SD_JJd(insn_t &insn, int value); + bool D_dddd(insn_t &insn, int value); + bool D_ddddd(insn_t &insn, int value); + bool S_ddddd(insn_t &insn, int value); + bool D_LLL(insn_t &insn, int value); + bool D_sss(insn_t &insn, int value); + bool S_sss(insn_t &insn, int value); + bool D_qqq(insn_t &insn, int value); + bool S_qqq(insn_t &insn, int value); + bool S_qq(insn_t &insn, int value); + bool S_QQ(insn_t &insn, int value); + bool S_gggd(insn_t &insn, int value); + bool D_MMRRR(insn_t &, int value); + bool S_MMRRR(insn_t &insn, int value); + bool D_MMRRR_XY(insn_t &, int value); + bool D_pppppp(insn_t &, int value); + bool S_pppppp(insn_t &insn, int value); + bool D_qqqqqq(insn_t &, int value); + bool S_qqqqqq(insn_t &insn, int value); + bool D_qXqqqqq(insn_t &insn, int value); + bool D_DDDDDD(insn_t &insn, int value); + bool S_DDDDDD(insn_t &insn, int value); + bool D_DDDD(insn_t &insn, int value); + bool D_RRR(insn_t &insn, int value); + bool S_RRR(insn_t &insn, int value); + void make_o_mem(insn_t &insn); + bool D_mMMMRRR(insn_t &insn, int value); + bool S_mMMMRRR(insn_t &insn, int value); + bool D_aaaaaa(insn_t &insn, int value); + bool S_aaaaaa(insn_t &insn, int value); + bool D_MMMRRR(insn_t &insn, int value); + bool S_MMMRRR(insn_t &insn, int value); + bool P_type(insn_t &, int); + bool AAE(insn_t &insn, int); + bool D_PC_dispL(insn_t &insn, int value); + bool S_PC_dispL(insn_t &insn, int value); + bool D_PC_dispS(insn_t &insn, int value); + bool D_PC_RRR(insn_t &, int value); + bool D_RRR_dispL(insn_t &insn, int value); + bool D_RRR_dispS(insn_t &, int value); + bool S_RR_dispS(insn_t &, int value); + bool AA(insn_t &, int value); + bool D_F(insn_t &insn, int value); + bool S_F(insn_t &insn, int value); + bool CCCC(insn_t &insn, int value); + bool s(insn_t &insn, int value); + bool ss(insn_t &insn, int value); + bool SD_IIII(insn_t &insn, int value); + bool D_zRR(insn_t &, int value); + bool D_mRR(insn_t &, int value); + bool D_RRm(insn_t &insn, int value); + bool D_RR11m(insn_t &insn, int value); + bool D_MMRR(insn_t &, int value); + bool S_MMRR(insn_t &insn, int value); + bool D_RR0MM(insn_t &insn, int value); + bool D_qRR(insn_t &, int value); + bool D_HHH(insn_t &, int value); + bool D_HH(insn_t &, int value); + bool SD_mWRRHHH(insn_t &insn, int value); + bool S_FJJJ(insn_t &insn, int value); + bool S_QQQ(insn_t &, int value); + bool S_QQ2(insn_t &, int value); + bool S_QQQQ(insn_t &, int value); + bool S_Fh0h(insn_t &insn, int value); + bool S_uFuuu_add(insn_t &insn, int value); + bool S_uFuuu_sub(insn_t &insn, int value); + bool D_RR(insn_t &insn, int value); + bool D_NN(insn_t &insn, int value); + bool DB_RR(insn_t &, int value); + bool D_PC_RR(insn_t &, int value); + bool DX_RR(insn_t &insn, int value); + bool S_RR(insn_t &insn, int value); + bool m_A_B(insn_t &, int /*value*/); + bool IF(insn_t &, int /*value*/); + bool IFU(insn_t &, int /*value*/); + bool S_i(insn_t &insn, int value); + bool SD_TT(insn_t &insn, int value); + bool S_BBBiiiiiiii(insn_t &, int value); + bool D_Pppppp(insn_t &insn, int value); + bool D_ppppp(insn_t &insn, int value); + bool D_aaaaa(insn_t &insn, int value); + bool S_DDDDD(insn_t &insn, int value); + bool D_xi(insn_t &, int value); + bool D_xi16(insn_t &, int value); + bool D_xi_adr_16(insn_t &insn, int value); + bool D_DD(insn_t &insn, int value); + bool S_DD(insn_t &insn, int value); + bool D_Z(insn_t &, int value); + bool D_t(insn_t &insn, int value); + bool SD_F00J(insn_t &insn, int value); + bool D_PC_eeeeee(insn_t &insn, int value); + bool D_PC_aaaaaaaa(insn_t &insn, int value); + bool D_BBBBBBBB(insn_t &, int value); + bool is_valid_insn(ushort proc); + bool disassemble_parallel_move(insn_t &insn, int i, int value); + bool decode_XY_R_mem(insn_t &insn, int value); + bool recognize_parallel_move_class1(insn_t &insn, int value); + bool recognize_parallel_move_class1_3(insn_t &insn, int value); + bool recognize_parallel_move_class2(insn_t &insn, int value); + bool recognize_parallel_move_class3(insn_t &insn, int value); + bool is_parallel_move(insn_t &insn, int value); + bool use_table( + insn_t &insn, + const struct opcode_t *table, + uint32 code, + int entry, + int start, + int end); + int ana_61(insn_t &insn); + int ana_6x(insn_t &insn); + int ana(insn_t *_insn); + bool X_type(insn_t &, int); + bool Y_type(insn_t &, int); + bool mem_type(insn_t &, int value); + bool space(insn_t &insn, int); + bool sign(insn_t &, int value); + int is_sane_insn(const insn_t &insn, int /*nocrefs*/) const; + void fill_additional_args(const insn_t &insn) const; + void switch_to_additional_args(insn_t &); + inline void opreg(insn_t &, int reg); + void reset_ops(insn_t &insn); + void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); + + void segstart(outctx_t &ctx, segment_t *seg) const; + void segend(outctx_t &ctx, segment_t *seg) const; + void footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; + +//------------------------------------------------------------------ + +#define aux_cc 0x000F // condition code +#define aux_su 0x0003 // sign/unsing code + +#define phtype specflag1 // o_phrase: phrase type +// 0 (Rn)-n +// 1 (Rn)+Nn +// 2 (Rn)- +// 3 (Rn)+ +// 4 (Rn) +// 5 (Rn+Nn) +// 7 -(Rn) +// 8 $+Rn +// 9 (a1) +// 10 (b1) + +#define amode specflag2 // addressing mode +#define amode_ioshort 0x01 // << +#define amode_short 0x02 // < +#define amode_long 0x04 // > +#define amode_neg 0x08 // - +#define amode_x 0x10 // X: +#define amode_y 0x20 // Y: +#define amode_p 0x40 // P: +#define amode_l 0x80 // L: + +#define imode specflag3 // IF mode +#define imode_if 0x01 // IFcc +#define imode_ifu 0x02 // IFUcc + +#define o_iftype o_idpspec0 // IF type + +#define o_vsltype o_idpspec1 // VSL 2-nd operand type + +//------------------------------------------------------------------ +#define UAS_GNU 0x0001 // GNU assembler +//------------------------------------------------------------------ +enum RegNo ENUM_SIZE(uint16) +{ + // data arithmetic logic unit + X, X0, X1, + Y, Y0, Y1, + // accumulator registers + A, A0, A1, A2, + B, B0, B1, B2, + AB, // a1:b1 + BA, // b1:a1 + A10, // a1:a0 + B10, // b1:b0 + // address generation unit (AGU) + R0, R1, R2, R3, R4, R5, R6, R7, // pointers + N0, N1, N2, N3, N4, N5, N6, N7, // offsets + M0, M1, M2, M3, M4, M5, M6, M7, // modifiers + // Program Control Unit + PC, // Program Counter (16 Bits) + MR, // Mode Register (8 Bits) + CCR, // Condition Code Register (8 Bits) + SR, // Status Register (MR:CCR, 16 Bits) + OMR, // Operating Mode Register (8 Bits) + LA, // Hardware Loop Address Register (16 Bits) + LC, // Hardware Loop Counter (16 Bits) + SP, // System Stack Pointer (6 Bits) + SS, // System Stack RAM (15X32 Bits) + SSH, // Upper 16 Bits of the Contents of the Current Top of Stack + SSL, // Lower 16 Bits of the Contents of the Current Top of Stack + SZ, // Stack Size register + SC, // Stack Counter register + EP, // Extension Pointer register + VBA, // Vector Base Address Register + + vCS, vDS, // virtual registers for code and data segments + +}; + + +//------------------------------------------------------------------ +// condition codes +enum cc_t +{ + cc_CC, // carry clear (higher or same) C=0 + cc_GE, // greater than or equal N xor V=0 + cc_NE, // not equal Z=0 + cc_PL, // plus N=0 + cc_NN, // not normalized Z+(^U&^E)=0 + cc_EC, // extension clear E=0 + cc_LC, // limit clear L=0 + cc_GT, // greater than Z+(N xor V)=0 + cc_CS, // carry set (lower) C=1 + cc_LT, // less than N xor V=1 + cc_EQ, // equal Z=1 + cc_MI, // minus N=1 + cc_NR, // normalized Z+(^U&^E)=1 + cc_ES, // extension set E=1 + cc_LS, // limit set L=1 + cc_LE, // less than or equal Z+(N xor V)=1 +}; + +//------------------------------------------------------------------ + +enum PMoveClass +{ + cl_0 = 0, // No Parallel move + cl_1, // X Memory Data Move (common) + cl_1_3, // X Memory Data Move with short displacement + cl_2, // Dual X Memory Data Read + cl_3, // X Memory Data Write and Register Data Move +}; + +//------------------------------------------------------------------ +// signed/unsigned codes +enum su_t +{ + s_SS, // signed * signed + s_SU, // signed * unsigned + s_UU, // unsigned * unsigned +}; + +// Make sure that the 'aa' structure is up to date. +void fill_additional_args(const insn_t &insn); + +//------------------------------------------------------------------ +void interr(const insn_t *insn, const char *module); + +int idaapi ana(insn_t *insn); +int idaapi emu(const insn_t &insn); + +int idaapi is_align_insn(ea_t ea); +int idaapi is_sp_based(const insn_t &insn, const op_t &x); + +#endif // _DSP56K_HPP diff --git a/idasdk75/module/dsp56k/emu.cpp b/idasdk76/module/dsp56k/emu.cpp similarity index 100% rename from idasdk75/module/dsp56k/emu.cpp rename to idasdk76/module/dsp56k/emu.cpp diff --git a/idasdk75/module/dsp56k/ins.cpp b/idasdk76/module/dsp56k/ins.cpp similarity index 100% rename from idasdk75/module/dsp56k/ins.cpp rename to idasdk76/module/dsp56k/ins.cpp diff --git a/idasdk75/module/dsp56k/ins.hpp b/idasdk76/module/dsp56k/ins.hpp similarity index 100% rename from idasdk75/module/dsp56k/ins.hpp rename to idasdk76/module/dsp56k/ins.hpp diff --git a/idasdk76/module/dsp56k/makefile b/idasdk76/module/dsp56k/makefile new file mode 100644 index 0000000..5e388e9 --- /dev/null +++ b/idasdk76/module/dsp56k/makefile @@ -0,0 +1,57 @@ +PROC=dsp56k +CONFIGS=dsp56k.cfg dsp563xx.cfg dsp566xx.cfg dsp561xx.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp dsp56k.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + dsp56k.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + dsp56k.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + dsp56k.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + dsp56k.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/dsp56k/out.cpp b/idasdk76/module/dsp56k/out.cpp similarity index 100% rename from idasdk75/module/dsp56k/out.cpp rename to idasdk76/module/dsp56k/out.cpp diff --git a/idasdk76/module/dsp56k/reg.cpp b/idasdk76/module/dsp56k/reg.cpp new file mode 100644 index 0000000..a78b545 --- /dev/null +++ b/idasdk76/module/dsp56k/reg.cpp @@ -0,0 +1,559 @@ + +#include "dsp56k.hpp" +#include <diskio.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + // data arithmetic logic unit + "x", "x0", "x1", + "y", "y0", "y1", + // accumulator registers + "a", "a0", "a1", "a2", + "b", "b0", "b1", "b2", + "ab", // a1:b1 + "ba", // b1:a1 + "a10", // a1:a0 + "b10", // b1:b0 + // address generation unit (AGU) + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // pointers + "n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", // offsets + "m0", "m1", "m2", "m3", "m4", "m5", "m6", "m7", // modifiers + // Program Control Unit + "pc", // Program Counter (16 Bits) + "mr", // Mode Register (8 Bits) + "ccr", // Condition Code Register (8 Bits) + "sr", // Status Register (MR:CCR, 16 Bits) + "omr", // Operating Mode Register (8 Bits) + "la", // Hardware Loop Address Register (16 Bits) + "lc", // Hardware Loop Counter (16 Bits) + "sp", // System Stack Pointer (6 Bits) + "ss", // System Stack RAM (15X32 Bits) + "ssh", // Upper 16 Bits of the Contents of the Current Top of Stack + "ssl", // Lower 16 Bits of the Contents of the Current Top of Stack + "sz", // Stack Size register + "sc", // Stack Counter register + "ep", // Extension Pointer register + "vba", // Vector Base Address Register + + "cs","ds", // virtual registers for code and data segments +}; + +//-------------------------------------------------------------------------- +// 6x +static const uchar retcode_0[] = { 0x0C, 0x00, 0x00 }; +static const uchar retcode_1[] = { 0x04, 0x00, 0x00 }; +// 61 +static const uchar retcode_2[] = { 0x06, 0x00 }; +static const uchar retcode_3[] = { 0x07, 0x00 }; + +static const bytes_t retcodes6x[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +static const bytes_t retcodes61[] = +{ + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Motorola DSP56000 Assembler +//----------------------------------------------------------------------- +static const asm_t motasm = +{ +// AS_ASCIIC + ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASB_BINF2 // %01010 + |ASO_OCTF1 // 0123 + |AS_COLON + |AS_N2CHR + |AS_NCMAS + |AS_ONEDUP, + 0, + "Motorola DSP56K Assembler", + 0, + NULL, // header lines + "org", // org + "end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + "dc", // ascii string directive + "dcb", // byte directive + "dc", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "*", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + "global", // "public" name keyword + NULL, // "weak" name keyword + "xref", // "extrn" name keyword + // .extern directive requires an explicit object size + NULL, // "comm" (communal variable) + NULL, // get_type_name + NULL, // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_BYTE1CHAR,// One symbol per processor byte +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gas = +{ + AS_ASCIIC + |ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASB_BINF3 // 0b01010 + |ASO_OCTF1 // 0123 + |AS_COLON + |AS_N2CHR + |AS_NCMAS + |AS_ONEDUP, + UAS_GNU, + "GNU-like hypothetical assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".long", // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + ".", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "mod", // mod + "and", // and + "or", // or + "xor", // xor + "not", // not + "shl", // shl + "shr", // shr + NULL, // sizeof + AS2_BYTE1CHAR,// One symbol per processor byte + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt +}; + +static const asm_t *const asms[] = { &motasm, &gas, NULL }; + +//---------------------------------------------------------------------- +ea_t dsp56k_t::AdditionalSegment(asize_t size, int offset, const char *name) const +{ + segment_t s; + int step = is561xx() ? 0xF : 0x1000000-1; + s.start_ea = free_chunk(0x1000000, size, step); + s.end_ea = s.start_ea + size; + s.sel = allocate_selector((s.start_ea-offset) >> 4); + s.type = SEG_DATA; + s.bitness = ph.dnbits > 16; + add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE); + return s.start_ea - offset; +} + +inline ea_t get_start(const segment_t *s) +{ + return s ? s->start_ea : BADADDR; +} + +//-------------------------------------------------------------------------- +const char *dsp56k_iohandler_t::iocallback(const ioports_t &iop, const char *line) +{ + int size; + if ( qsscanf(line, "XMEMSIZE = %i", &size) == 1 ) + { + pm.xmemsize = size; +RETOK: + pm.ioh.deviceparams.sprnt("XMEM=0x%X YMEM=0x%X", pm.xmemsize, pm.ymemsize); + return NULL; + } + if ( !pm.is561xx() && qsscanf(line, "YMEMSIZE = %i", &size) == 1 ) + { + pm.ymemsize = size; + goto RETOK; + } + return pm.ioh.standard_callback(iop, line); +} + +const ioport_t *dsp56k_t::find_port(ea_t address) +{ + return find_ioport(ioh.ports, address); +} + +//-------------------------------------------------------------------------- +void dsp56k_t::create_xmem_ymem(void) +{ + if ( xmem == BADADDR ) + { + xmem = AdditionalSegment(xmemsize, 0, "XMEM"); + + if ( !is561xx() ) + ymem = AdditionalSegment(ymemsize, 0, "YMEM"); + } +} + +//-------------------------------------------------------------------------- +void dsp56k_t::select_device(const char *dname, int resp_info) +{ + ioh.set_device_name(dname, resp_info); + + create_xmem_ymem(); + + for ( int i=0; i < ioh.ports.size(); i++ ) + { + const ioport_t &p = ioh.ports[i]; + ea_t ea = xmem + p.address; + const char *name = p.name.c_str(); + ea_t nameea = get_name_ea(BADADDR, name); + if ( nameea != ea ) + { + set_name(nameea, ""); + if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) + set_cmt(ea, name, 0); + } + } +} + +//-------------------------------------------------------------------------- +const char *dsp56k_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( choose_ioport_device(&ioh.device, cfgfile) ) + select_device(ioh.device.c_str(), IORESP_INT); + return IDPOPT_OK; +} + +//----------------------------------------------------------------------- +// We always return "yes" because of the messy problem that +// there are additional operands with a wrong operand number (always 1) +static bool idaapi can_have_type(const op_t &) +{ + return true; +} + +//-------------------------------------------------------------------------- +void dsp56k_t::set_cpu(int procno) +{ + procnum = procno; + ph.cnbits = (is561xx() ) ? 16 : 24; + ph.dnbits = (is561xx() || is566xx()) ? 16 : 24; + ph.retcodes = (is561xx() ) ? retcodes61 : retcodes6x; +} + +//---------------------------------------------------------------------- +void dsp56k_t::load_from_idb() +{ + xmem = get_start(get_segm_by_name("XMEM")); + if ( !is561xx() ) + ymem = get_start(get_segm_by_name("YMEM")); + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(dsp56k_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi dsp56k_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + { + // data memory could already be present, check it + xmem = get_start(get_segm_by_name("XMEM")); + if ( !is561xx() ) + ymem = get_start(get_segm_by_name("YMEM")); + + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + select_device(ioh.device.c_str(), IORESP_AREA|IORESP_INT); + else + create_xmem_ymem(); + } + break; + + case processor_t::ev_ending_undo: + // restore ptype + set_cpu(ph.get_proc_index()); + //fall through + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + { + int n = va_arg(va, int); + // bool keep_cfg = va_argi(va, bool); + if ( procnum == -1 ) + { + set_cpu(n); + } + else if ( procnum != n ) // can't change the processor type + { // after the initial set up + warning("Sorry, processor type cannot be changed after loading"); + code = -1; + break; + } + } + break; + + case processor_t::ev_is_sane_insn: + { + const insn_t &insn = *va_arg(va, const insn_t *); + int nocrefs = va_arg(va, int); + return is_sane_insn(insn, nocrefs) == 1 ? 1 : -1; + } + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *_op = va_arg(va, const op_t *); + return out_opnd(*ctx, *_op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *_op = va_arg(va, const op_t *); + return can_have_type(*_op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *_op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *_op); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "Motorola DSP 5600x:" + +static const char *const shnames[] = +{ + "dsp56k", + "dsp561xx", + "dsp563xx", + "dsp566xx", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Motorola DSP 5600x", + "Motorola DSP 561xx", + "Motorola DSP 563xx", + "Motorola DSP 566xx", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_DSP56K, // id + // flag + PRN_HEX + | PR_ALIGN + | PR_BINMEM, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 24, // 24 bits in a byte for code segments + 24, // 24 bits in a byte for other segments + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + vCS, // first + vDS, // last + 0, // size of a segment register + vCS, vDS, + + NULL, // No known code start sequences + retcodes6x, + + DSP56_null, + DSP56_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + DSP56_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/exports.def b/idasdk76/module/exports.def similarity index 100% rename from idasdk75/module/exports.def rename to idasdk76/module/exports.def diff --git a/idasdk76/module/f2mc/ana.cpp b/idasdk76/module/f2mc/ana.cpp new file mode 100644 index 0000000..13a759c --- /dev/null +++ b/idasdk76/module/f2mc/ana.cpp @@ -0,0 +1,1217 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Fujitsu's F2MC + * + */ + +#include "f2mc.hpp" +#include <segregs.hpp> + +//-------------------------------------------------------------------------- +// function to generate an operand +typedef void (*func_op_t)(const struct map_t *, int offset, op_t &op, insn_t &insn); + +struct map_t +{ + const map_t *next; // map for next opcode byte + int code; // first opcode of instruction range + ushort itype; // itype of instruction + func_op_t op1; //lint !e958 padding is required to align members + // function to set Op1 + func_op_t op2; // function to set Op2 + func_op_t op3; // function to set Op3 + char priority1; // first operand to inc (1..3) + char size1; // maximum size of the first operand + char priority2; + char size2; + char priority3; + char size3; +}; +// operands increments priority (OP_first_second_...) +#define OP_NULL 0, 0, 0, 0, 0, 0 +#define OP_1_2(SIZE1) 1, SIZE1, 2, 0, 0, 0 +#define OP_2_1(SIZE2) 2, SIZE2, 1, 0, 0, 0 +#define OP_3_1(SIZE3) 3, SIZE3, 1, 0, 0, 0 +#define OP_3_2(SIZE3) 3, SIZE3, 2, 0, 0, 0 + + +//-------------------------------------------------------------------------- +// analyze code by processing map + +static const map_t *process_map(insn_t &insn, int code, const map_t *map, int itype_null) +{ + // search for the good opcode range + const map_t *p = map; + while ( ((p+1)->code != 0 || (p+1)->itype != 0) + && code >= (p+1)->code ) + { + p++; // loop until p->code <= code < (p+1)->code + } + if ( insn.itype == itype_null ) + insn.itype = p->itype; // define itype if not already defined + + // compute operand offsets + int offset = code - p->code, offsets[3]; + for ( int i=0; i < 3; i++ ) + offsets[i] = offset; + if ( p->priority1 ) + { + if ( p->size1 ) + offsets[p->priority1 - 1] = offset % p->size1; + if ( p->priority2 ) + { + offset /= p->size1; + offsets[p->priority2 - 1] = offset; + if ( p->size2 ) + offsets[p->priority2 - 1] = offset % p->size2; + if ( p->priority3 ) + { + offset /= p->size2; + offsets[p->priority3 - 1] = offset; + if ( p->size3 ) + offsets[p->priority3 - 1] = offset % p->size3; + } + } + } + + // process operands + if ( p->op1 != NULL ) + p->op1(p, offsets[0], insn.Op1, insn); + if ( p->op2 != NULL ) + p->op2(p, offsets[1], insn.Op2, insn); + if ( p->op3 != NULL ) + p->op3(p, offsets[2], insn.Op3, insn); + return p->next; +} + +//-------------------------------------------------------------------------- +// analyze code by processing all necessary maps +static void process_maps(insn_t &insn, const map_t *map,uint16 itype_null) +{ + insn.itype = itype_null; + insn.size = 0; + while ( map ) // while we must analyze a new map + { + int code = insn.get_next_byte(); + map = process_map(insn, code, map, itype_null); // analyze this byte + } +} + +//-------------------------------------------------------------------------- +// class to store an instructions cache +#define CMDS_SIZE 3 // maximum cache size (maximum number of instructions) +class cmds_t +{ +private: + insn_t insns[CMDS_SIZE]; + int size; + int i; +public: + void reset(void) { i = 0; } + //lint -sem(cmds_t::reload,initializer) + void reload(const insn_t &insn) { insns[0] = insn; size = 1; reset(); } + cmds_t(const insn_t &insn) { reload(insn); } //lint !e1566 'cmds_t::i' may have been initialized in a separate method + const insn_t *get_next(void); + const insn_t *get(int j) const; +}; + +// get the next instruction +const insn_t *cmds_t::get_next(void) +{ + if ( i == size ) + { + // if ( size >= CACHE_SIZE ) return NULL; + // load a new instruction into the cache + if ( size <= 0 ) + return NULL; + ea_t ea = insns[size-1].ea + insns[size-1].size; + if ( decode_insn(&insns[size], ea) < 1 ) + return NULL; + size++; + } + return &insns[i++]; +} + +//-------------------------------------------------------------------------- +// get an instruction already in the cache +const insn_t *cmds_t::get(int j) const +{ + // if ( j >= size ) return NULL; + return &insns[j]; +} + +// function to check the validity of an operand +typedef bool (*func_is_op_t)(const insn_t *insn, const op_t &op); + +struct macro_insn_t +{ + func_is_op_t op1; // function to check Op1 + func_is_op_t op2; // function to check Op2 + func_is_op_t op3; // function to check Op3 + ushort itype; // itype of instruction +}; + +struct macro_t +{ + const macro_insn_t *insns; // array of instructions + ushort itype; // itype of macro + char cmd; // indice (1..n) of the "base" cmd + char op1_cmd; // indice (1..n) of the cmd containing the 1st operand + char op1_cmd_op; // indice of the operand from the cmd containing the 1st operand + char op2_cmd; + char op2_cmd_op; + char op3_cmd; + char op3_cmd_op; +}; +#define OP_VOID 0, 0 +#define OP_CMD(CMD,OP) CMD, OP + + +//-------------------------------------------------------------------------- +// build a macro and return true, or return cmd and return false +static bool build_macro(const macro_t *macros, int itype_null, insn_t &build, const insn_t &insn) +{ + build = insn; + cmds_t cmds(insn); + const macro_t *macro = macros; + while ( macro->itype != itype_null ) // loop into macros array + { + const macro_insn_t *mdef = macro->insns; + cmds.reset(); + int size = 0; + while ( mdef->itype != itype_null ) // loop into instructions of the macro + { + const insn_t *pcmds = cmds.get_next(); // get the instruction + if ( pcmds == NULL ) + break; + size += pcmds->size; + // check if instructions and operands correspond + if ( pcmds->itype != mdef->itype ) + break; + if ( mdef->op1 && !mdef->op1(pcmds, pcmds->Op1) ) + break; + if ( mdef->op2 && !mdef->op2(pcmds, pcmds->Op2) ) + break; + if ( mdef->op3 && !mdef->op2(pcmds, pcmds->Op3) ) + break; + if ( (mdef+1)->itype == itype_null ) // macro founded + { + ea_t ea = cmds.get(0)->ea; + // check if an external Xrefs exists + xrefblk_t xb; + for ( ea_t i = ea; i < ea+size; i++ ) + for ( int ok = xb.first_to(i,XREF_FAR); ok; ok=xb.next_to() ) + if ( xb.from < ea || xb.from >= ea+size ) + return false; // external Xref founded + + // fill resulting insn_t + build = *cmds.get(macro->cmd-1); + build.ea = ea; + build.size = (uint16)size; + build.itype = macro->itype; + if ( macro->op1_cmd ) + build.Op1 = cmds.get(macro->op1_cmd-1)->ops[macro->op1_cmd_op-1]; + else + build.Op1.type = o_void; + build.Op1.n = 1; + if ( macro->op2_cmd ) + build.Op2 = cmds.get(macro->op2_cmd-1)->ops[macro->op2_cmd_op-1]; + else + build.Op2.type = o_void; + build.Op2.n = 2; + if ( macro->op3_cmd ) + build.Op3 = cmds.get(macro->op3_cmd-1)->ops[macro->op3_cmd_op-1]; + else + build.Op3.type = o_void; + build.Op3.n = 3; + return true; + } + mdef++; + } + macro++; + } + return false; +} + +//-------------------------------------------------------------------------- +// analyze cmd and next instructions to eventually detect a macro and update database +static void process_macros(insn_t &insn, const macro_t *macros, int itype_null, bool macro_on) +{ + if ( macro_on ) // try to build a macro + { + insn_t macro; + if ( build_macro(macros, itype_null, macro, insn) ) + insn = macro; // a macro can be built + } + if ( is_head(get_flags(insn.ea)) // if not the first analyze + && insn.size != get_item_size(insn.ea) ) // and the size of the instruction just changed + { + // reanalyze + del_items(insn.ea, DELIT_SIMPLE, insn.size); // undefine preceding instructions + auto_make_code(insn.ea); + } +} + +//-------------------------------------------------------------------------- +// get the value of a bank +static sel_t get_bank_value(const insn_t &insn, int bank) +{ + sel_t sel; + if ( bank != PCB ) + { + if ( bank == SPB ) + { + sel_t ccr = get_sreg(insn.ea, CCR); + if ( ccr == BADSEL ) + ccr = 0; + if ( ccr & 0x20 ) + bank = SSB; + else + bank = USB; + } + + sel = get_sreg(insn.ea, bank); + if ( sel == BADSEL ) + sel = 0; + } + else + { + sel = insn.cs; + } + return sel & 0xFF; +} + +//-------------------------------------------------------------------------- +// get the value of the bank used by the instruction (eventually with a prefix) +static sel_t get_insn_bank_value(const insn_t &insn) +{ + int bank = 0; + if ( insn.prefix_bank ) + bank = insn.prefix_bank; + else if ( insn.default_bank ) + bank = insn.default_bank; + else + error("interr: emu: get_insn_bank_value()"); + return get_bank_value(insn, bank); +} + +//-------------------------------------------------------------------------- +#define op_reg(REG,DTYP) \ + static void op_##REG(const map_t *, int, op_t &op, insn_t &) \ + { \ + op.type = o_reg; \ + op.reg = REG; \ + op.dtype = dt_##DTYP; \ + } +op_reg(A,dword) // op_A +op_reg(AH,word) // op_AH +op_reg(AL,word) // op_AL +op_reg(SP,word) // op_SP +op_reg(PC,word) // op_PC +op_reg(PCB,byte) // op_PCB +op_reg(DTB,byte) // op_DTB +op_reg(ADB,byte) // op_ADB +op_reg(SPB,byte) // op_SPB +op_reg(SSB,byte) // op_SSB +op_reg(USB,byte) // op_USB +op_reg(DPR,byte) // op_DPR +op_reg(PS,word) // op_PS +op_reg(ILM,byte) // op_ILM +op_reg(RP,byte) // op_RP +op_reg(CCR,byte) // op_CCR + +#define op_regi(NAME,REG,DTYP) \ + static void op_##NAME(const map_t *, int offset, op_t &op, insn_t &) \ + { \ + op.type = o_reg; \ + op.reg = uint16(REG + offset); \ + op.dtype = dt_##DTYP; \ + } +op_regi(Ri,R0,byte) // op_Ri +op_regi(RWi,RW0,word) // op_RWi +op_regi(RLi,RL0,dword) // op_RLi +// special for EA RLi adressing mode + +static void op_RLi2(const map_t *, int offset, op_t &op, insn_t &) +{ + op.type = o_reg; + op.reg = uint16(RL0 + (offset>>1)); + op.dtype = dt_dword; +} + +#define op_at(OP,DEFAULT_BANK,DTYP) \ + static void op_##DTYP##_at_##OP(const map_t *map, int offset, op_t &op, insn_t &insn) \ + { \ + op_##OP(map,offset,op,insn); \ + insn.default_bank = DEFAULT_BANK; \ + insn.op_bank = op.n; \ + op.type = o_phrase; \ + op.at++; \ + op.dtype = dt_##DTYP; \ + } +op_at(A,DTB,byte) // op_byte_at_A +op_at(A,DTB,word) // op_word_at_A +op_at(A,DTB,code) // op_code_at_A +op_at(AL,DTB,byte) // op_byte_at_AL +op_at(AL,DTB,word) // op_word_at_AL +// op_DTYP_at_RWi +op_at(RLi,0,byte) // op_byte_at_RLi +op_at(RLi,0,word) // op_word_at_RLi +// op_at(RLi,0,dword) // op_dword_at_RLi +op_at(PC,PCB,byte) // op_byte_at_PC +op_at(PC,PCB,word) // op_word_at_PC +op_at(PC,PCB,dword) // op_dword_at_PC + +#define op_at_RWi(DTYP) \ + static void op_##DTYP##_at_RWi(const map_t *map, int offset, op_t &op, insn_t &insn) \ + { \ + op_RWi(map,offset,op,insn); \ + op.type = o_phrase; \ + op.at++; \ + op.dtype = dt_##DTYP; \ + switch ( offset ) \ + { \ + case 0: \ + case 1: \ + case 4: \ + case 5: \ + insn.default_bank = DTB; \ + break; \ + case 3: \ + case 7: \ + insn.default_bank = SPB; \ + break; \ + case 2: \ + case 6: \ + insn.default_bank = ADB; \ + break; \ + } \ + insn.op_bank = op.n; \ + } +op_at_RWi(byte) +op_at_RWi(word) +op_at_RWi(dword) + +#define op_imm(NAME,VALUE,DTYP,IN) \ + static void op_##NAME(const map_t *, int offset, op_t &op, insn_t &IN) \ + { \ + op.type = o_imm; \ + op.value = VALUE; \ + op.dtype = dt_##DTYP; \ + } +op_imm(imm4,offset,byte, /*insn*/) // op_imm4 +#define offset +op_imm(imm8,insn.get_next_byte(),byte,insn) // op_imm8 +op_imm(imm16,insn.get_next_word(),word,insn) // op_imm16 +op_imm(imm32,insn.get_next_dword(),dword,insn) // op_imm32 +#undef offset + +#define op_dir(DTYP) \ + static void op_dir_##DTYP(const map_t *, int, op_t &op, insn_t &insn) \ + { \ + insn.default_bank = DTB; \ + insn.op_bank = op.n; \ + op.type = o_mem; \ + op.dtype = dt_##DTYP; \ + sel_t dpr = get_sreg(insn.ea, DPR); \ + if ( dpr == BADSEL ) \ + dpr = 0; \ + op.addr = (get_insn_bank_value(insn) << 16) | ((dpr&0xFF) << 8) | insn.get_next_byte(); \ + op.addr_dtyp = 's'; \ + } +op_dir(byte) // op_dir_byte +op_dir(word) // op_dir_word +// op_dir(dword) // op_dir_dword + +#define op_io(DTYP) \ + static void op_io_##DTYP(const map_t *, int, op_t &op, insn_t &insn) \ + { \ + op.type = o_mem; \ + op.dtype = dt_##DTYP; \ + op.addr = insn.get_next_byte(); \ + op.addr_dtyp = 'i'; \ + } +op_io(byte) // op_io_byte +op_io(word) // op_io_word +// op_io(dword) // op_io_dword + +#define op_addr16(DEFAULT_BANK,TYPE,DTYP) \ + static void op_addr16_##DTYP(const map_t *, int, op_t &op, insn_t &insn) \ + { \ + insn.default_bank = DEFAULT_BANK; \ + insn.op_bank = op.n; \ + op.type = o_##TYPE; \ + op.addr = (get_insn_bank_value(insn) << 16) | insn.get_next_word(); \ + op.dtype = dt_##DTYP; \ + } +op_addr16(PCB, near, code) // op_addr16_code +op_addr16(DTB, mem, byte) // op_addr16_byte +op_addr16(DTB, mem, word) // op_addr16_word +op_addr16(DTB, mem, dword) // op_addr16_dword + +#define op_bp(NAME,OP) \ + static void op_bp_##NAME(const map_t *map, int offset, op_t &op, insn_t &insn) \ + { \ + op_##OP(map,offset,op,insn); \ + op.special_mode = MODE_BIT; \ + op.byte_bit = uchar(offset); \ + } +op_bp(io,io_byte) // op_bp_io +op_bp(dir,dir_byte) // op_bp_dir +op_bp(addr16,addr16_byte) // op_bp_addr16 + +#define op_at_RWi_inc(DTYP) \ + static void op_##DTYP##_at_RWi_inc(const map_t *map, int offset, op_t &op, insn_t &insn) \ + { \ + op_##DTYP##_at_RWi(map, offset, op, insn); \ + op.special_mode = MODE_INC; \ + } +op_at_RWi_inc(byte) // op_byte_at_RWi_inc +op_at_RWi_inc(word) // op_word_at_RWi_inc +op_at_RWi_inc(dword) // op_dword_at_RWi_inc + +#define op_at_reg_displ(NAME,REG,VALUE,VALUE_DTYP,DTYP) \ + static void op_##DTYP##_at_##REG##_##NAME(const map_t *map, int offset, op_t &op, insn_t &insn) \ + { \ + op_##DTYP##_at_##REG(map,offset,op,insn); \ + op.type = o_displ; \ + op.addr = VALUE; \ + op.addr_dtyp = dt_##VALUE_DTYP; \ + } +op_at_reg_displ(disp8,RWi,get_signed(insn.get_next_byte(),0xFF),byte,byte) // op_byte_at_RWi_disp8 +op_at_reg_displ(disp8,RWi,get_signed(insn.get_next_byte(),0xFF),byte,word) // op_word_at_RWi_disp8 +op_at_reg_displ(disp8,RWi,get_signed(insn.get_next_byte(),0xFF),byte,dword) // op_dword_at_RWi_disp8 +op_at_reg_displ(disp16,RWi,get_signed(insn.get_next_word(),0xFFFF),word,byte) // op_byte_at_RWi_disp16 +op_at_reg_displ(disp16,RWi,get_signed(insn.get_next_word(),0xFFFF),word,word) // op_word_at_RWi_disp16 +op_at_reg_displ(disp16,RWi,get_signed(insn.get_next_word(),0xFFFF),word,dword) // op_dword_at_RWi_disp16 +op_at_reg_displ(disp8,RLi,get_signed(insn.get_next_byte(),0xFF),byte,byte) // op_byte_at_RLi_disp8 +op_at_reg_displ(disp8,RLi,get_signed(insn.get_next_byte(),0xFF),byte,word) // op_word_at_RLi_disp8 +// op_at_reg_displ(disp8,RLi,get_signed(insn.get_next_byte(),0xFF),byte,dword) // op_dword_at_RLi_disp8 +op_at_reg_displ(disp16,PC,get_signed(insn.get_next_word(),0xFFFF),word,byte) // op_byte_at_PC_disp16 +op_at_reg_displ(disp16,PC,get_signed(insn.get_next_word(),0xFFFF),word,word) // op_word_at_PC_disp16 +op_at_reg_displ(disp16,PC,get_signed(insn.get_next_word(),0xFFFF),word,dword) // op_dword_at_PC_disp16 + +#define op_ea(REG,DTYP) \ +static void op_ea_##DTYP(const map_t *map, int offset, op_t &op, insn_t &insn) \ +{ \ + if ( offset < 8 ) \ + op_##REG(map, offset, op, insn); \ + else if ( offset < 0x0C ) \ + op_##DTYP##_at_RWi(map, offset-0x08, op, insn); \ + else if ( offset < 0x10 ) \ + op_##DTYP##_at_RWi_inc(map, offset-0x0C, op, insn); \ + else if ( offset < 0x18 ) \ + op_##DTYP##_at_RWi_disp8(map, offset-0x10, op, insn); \ + else if ( offset < 0x1C ) \ + op_##DTYP##_at_RWi_disp16(map, offset-0x18, op, insn); \ + else if ( offset < 0x1E ) \ + { \ + op_##DTYP##_at_RWi(map, offset-0x1C, op, insn); \ + op.special_mode = MODE_INDEX; \ + op.f2mc_index = RW7; \ + } \ + else if ( offset == 0x1E ) \ + op_##DTYP##_at_PC_disp16(map, offset-0x18, op, insn); \ + else \ + op_addr16_##DTYP(map, offset-0x1F, op, insn); \ +} + +op_ea(Ri,byte) // op_ea_byte +op_ea(RWi,word) // op_ea_word +op_ea(RLi2,dword) // op_ea_dword + +#define op_code_at_ea(DEFAULT_BANK,DTYP) \ + static void op_code_at_ea_##DTYP(const map_t *map, int offset, op_t &op, insn_t &insn) \ + { \ + op_ea_##DTYP(map,offset,op, insn); \ + insn.default_bank = DEFAULT_BANK; \ + insn.op_bank = op.n; \ + op.at++; \ + op.dtype = dt_code; \ + } +op_code_at_ea(PCB,word) // op_code_at_ea_word +op_code_at_ea(0,dword) // op_code_at_ea_dword + + +//-------------------------------------------------------------------------- +static void op_addr24(const map_t *, int, op_t &op, insn_t &insn) +{ + op.type = o_far; + op.addr = insn.get_next_word(); + op.addr |= insn.get_next_byte() << 16; + op.dtype = dt_code; +} + +//-------------------------------------------------------------------------- +static void op_rel(const map_t *, int, op_t &op, insn_t &insn) +{ + int offset = get_signed(insn.get_next_byte(), 0xFF); + op.type = o_near; + op.addr = (insn.ip & ~0xFFFF) | ((insn.ip + insn.size + offset) & 0xFFFF); + op.dtype = dt_code; +} + +//------------------------------------------------------------------------- +static void op_rlst(const map_t *, int, op_t &op, insn_t &insn) +{ + op.type = o_reglist; + op.reg = insn.get_next_byte(); + op.dtype = dt_byte; +} + +//-------------------------------------------------------------------------- +// used for string instructions +static void op_PCB_DTB_ADB_SPB(const map_t *map, int offset, op_t &op, insn_t &insn) +{ + static const func_op_t banks[4] = { op_PCB, op_DTB, op_ADB, op_SPB }; + banks[offset&3](map, offset, op, insn); +} + +//-------------------------------------------------------------------------- +// used for writing/reading values to/from bank registers +static void op_DTB_ADB_SSB_USB_DPR(const map_t *map, int offset, op_t &op, insn_t &insn) +{ + static const func_op_t banks[5] = { op_DTB, op_ADB, op_SSB, op_USB, op_DPR }; + banks[offset%5](map, offset, op, insn); +} + +//-------------------------------------------------------------------------- +static const map_t bitop_map[] = // bit operations +{ + { NULL, 0x00, F2MC_movb, op_A, op_bp_io, 0, OP_NULL }, + { NULL, 0x08, F2MC_movb, op_A, op_bp_dir, 0, OP_NULL }, + { NULL, 0x10, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x18, F2MC_movb, op_A, op_bp_addr16, 0, OP_NULL }, + { NULL, 0x20, F2MC_movb, op_bp_io, op_A, 0, OP_NULL }, + { NULL, 0x28, F2MC_movb, op_bp_dir, op_A, 0, OP_NULL }, + { NULL, 0x30, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x38, F2MC_movb, op_bp_addr16, op_A, 0, OP_NULL }, + { NULL, 0x40, F2MC_clrb, op_bp_io, 0, 0, OP_NULL }, + { NULL, 0x48, F2MC_clrb, op_bp_dir, 0, 0, OP_NULL }, + { NULL, 0x50, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x58, F2MC_clrb, op_bp_addr16, 0, 0, OP_NULL }, + { NULL, 0x60, F2MC_setb, op_bp_io, 0, 0, OP_NULL }, + { NULL, 0x68, F2MC_setb, op_bp_dir, 0, 0, OP_NULL }, + { NULL, 0x70, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x78, F2MC_setb, op_bp_addr16, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_bbc, op_bp_io, op_rel, 0, OP_NULL }, + { NULL, 0x88, F2MC_bbc, op_bp_dir, op_rel, 0, OP_NULL }, + { NULL, 0x90, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x98, F2MC_bbc, op_bp_addr16, op_rel, 0, OP_NULL }, + { NULL, 0xA0, F2MC_bbs, op_bp_io, op_rel, 0, OP_NULL }, + { NULL, 0xA8, F2MC_bbs, op_bp_dir, op_rel, 0, OP_NULL }, + { NULL, 0xB0, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xB8, F2MC_bbs, op_bp_addr16, op_rel, 0, OP_NULL }, + { NULL, 0xC0, F2MC_wbts, op_bp_io, 0, 0, OP_NULL }, + { NULL, 0xC8, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xE0, F2MC_wbtc, op_bp_io, 0, 0, OP_NULL }, + { NULL, 0xE8, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xF8, F2MC_sbbs, op_bp_addr16, op_rel, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t strop_map[] = // string operations +{ + { NULL, 0x00, F2MC_movsi, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, + { NULL, 0x10, F2MC_movsd, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, + { NULL, 0x20, F2MC_movswi, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, + { NULL, 0x30, F2MC_movswd, op_PCB_DTB_ADB_SPB, op_PCB_DTB_ADB_SPB, 0, OP_2_1(4) }, + { NULL, 0x40, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_sceqi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, + { NULL, 0x84, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x90, F2MC_sceqd, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, + { NULL, 0x94, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xA0, F2MC_scweqi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, + { NULL, 0xA4, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xB0, F2MC_scweqd, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, + { NULL, 0xB4, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xC0, F2MC_filsi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, + { NULL, 0xC4, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0xE0, F2MC_filswi, op_PCB_DTB_ADB_SPB, 0, 0, OP_NULL }, + { NULL, 0xE4, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t twobyte_map[] = +{ + { NULL, 0x00, F2MC_mov, op_A, op_DTB_ADB_SSB_USB_DPR, 0, OP_NULL }, + { NULL, 0x05, F2MC_mov, op_A, op_byte_at_A, 0, OP_NULL }, + { NULL, 0x06, F2MC_mov, op_A, op_PCB, 0, OP_NULL }, + { NULL, 0x07, F2MC_rolc, op_A, 0, 0, OP_NULL }, + { NULL, 0x08, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x0C, F2MC_lslw2, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x0D, F2MC_movw, op_A, op_word_at_A, 0, OP_NULL }, + { NULL, 0x0E, F2MC_asrw2, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x0F, F2MC_lsrw2, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x10, F2MC_mov, op_DTB_ADB_SSB_USB_DPR, op_A, 0, OP_NULL }, + { NULL, 0x15, F2MC_mov, op_byte_at_AL, op_AH, 0, OP_NULL }, + { NULL, 0x16, F2MC_movx, op_A, op_byte_at_A, 0, OP_NULL }, + { NULL, 0x17, F2MC_rorc, op_A, 0, 0, OP_NULL }, + { NULL, 0x18, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x1C, F2MC_lsll, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x1D, F2MC_movw, op_word_at_AL, op_AH, 0, OP_NULL }, + { NULL, 0x1E, F2MC_asrl, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x1F, F2MC_lsrl, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x20, F2MC_movx, op_A, op_byte_at_RLi_disp8, 0, OP_3_2(2) }, + { NULL, 0x27, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x2C, F2MC_lsl, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x2D, F2MC_nrml, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x2E, F2MC_asr, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x2F, F2MC_lsr, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x30, F2MC_mov, op_byte_at_RLi_disp8, op_A, 0, OP_3_1(2) }, + { NULL, 0x38, F2MC_movw, op_word_at_RLi_disp8, op_A, 0, OP_3_1(2) }, + { NULL, 0x40, F2MC_mov, op_A, op_byte_at_RLi_disp8, 0, OP_3_2(2) }, + { NULL, 0x48, F2MC_movw, op_A, op_word_at_RLi_disp8, 0, OP_3_2(2) }, + { NULL, 0x50, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x78, F2MC_mul1, op_A, 0, 0, OP_NULL }, + { NULL, 0x79, F2MC_mulw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x7A, F2MC_div1, op_A, 0, 0, OP_NULL }, + { NULL, 0x7B, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_1_map[] = +{ + { NULL, 0x00, F2MC_addl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0x20, F2MC_subl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0x40, F2MC_cwbne, op_ea_word, op_imm16, op_rel, OP_NULL }, + { NULL, 0x60, F2MC_cmpl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0x80, F2MC_andl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0xA0, F2MC_orl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0xC0, F2MC_xorl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0xE0, F2MC_cbne, op_ea_byte, op_imm8, op_rel, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_2_map[] = +{ + { NULL, 0x00, F2MC_jmpp, op_code_at_ea_dword, 0, 0, OP_NULL }, + { NULL, 0x20, F2MC_callp, op_code_at_ea_dword, 0, 0, OP_NULL }, + { NULL, 0x40, F2MC_incl, op_ea_dword, 0, 0, OP_NULL }, + { NULL, 0x60, F2MC_decl, op_ea_dword, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_movl, op_A, op_ea_dword, 0, OP_NULL }, + { NULL, 0xA0, F2MC_movl, op_ea_dword, op_A, 0, OP_NULL }, + { NULL, 0xC0, F2MC_mov, op_ea_byte, op_imm8, 0, OP_NULL }, + { NULL, 0xE0, F2MC_movea, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_3_map[] = +{ + { NULL, 0x00, F2MC_rolc, op_ea_byte, 0, 0, OP_NULL }, + { NULL, 0x20, F2MC_rorc, op_ea_byte, 0, 0, OP_NULL }, + { NULL, 0x40, F2MC_inc, op_ea_byte, 0, 0, OP_NULL }, + { NULL, 0x60, F2MC_dec, op_ea_byte, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_mov, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xA0, F2MC_mov, op_ea_byte, op_A, 0, OP_NULL }, + { NULL, 0xC0, F2MC_movx, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xE0, F2MC_xch, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_4_map[] = +{ + { NULL, 0x00, F2MC_jmp, op_code_at_ea_word, 0, 0, OP_NULL }, + { NULL, 0x20, F2MC_call, op_code_at_ea_word, 0, 0, OP_NULL }, + { NULL, 0x40, F2MC_incw, op_ea_word, 0, 0, OP_NULL }, + { NULL, 0x60, F2MC_decw, op_ea_word, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_movw, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0xA0, F2MC_movw, op_ea_word, op_A, 0, OP_NULL }, + { NULL, 0xC0, F2MC_movw, op_ea_word, op_imm16, 0, OP_NULL }, + { NULL, 0xE0, F2MC_xchw, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_5_map[] = +{ + { NULL, 0x00, F2MC_add, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x20, F2MC_sub, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x40, F2MC_addc2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x60, F2MC_cmp2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x80, F2MC_and, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xA0, F2MC_or, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xC0, F2MC_xor, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xE0, F2MC_dbnz, op_ea_byte, op_rel, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_6_map[] = +{ + { NULL, 0x00, F2MC_add, op_ea_byte, op_A, 0, OP_NULL }, + { NULL, 0x20, F2MC_sub, op_ea_byte, op_A, 0, OP_NULL }, + { NULL, 0x40, F2MC_subc2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x60, F2MC_neg, op_ea_byte, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_and, op_ea_byte, op_A, 0, OP_NULL }, + { NULL, 0xA0, F2MC_or, op_ea_byte, op_A, 0, OP_NULL }, + { NULL, 0xC0, F2MC_xor, op_ea_byte, op_A, 0, OP_NULL }, + { NULL, 0xE0, F2MC_not, op_ea_byte, 0, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_7_map[] = +{ + { NULL, 0x00, F2MC_addw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x20, F2MC_subw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x40, F2MC_addcw, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x60, F2MC_cmpw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x80, F2MC_andw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0xA0, F2MC_orw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0xC0, F2MC_xorw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0xE0, F2MC_dwbnz, op_ea_word, op_rel, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_8_map[] = +{ + { NULL, 0x00, F2MC_addw2, op_ea_word, op_A, 0, OP_NULL }, + { NULL, 0x20, F2MC_subw2, op_ea_word, op_A, 0, OP_NULL }, + { NULL, 0x40, F2MC_subcw, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x60, F2MC_negw, op_ea_word, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_andw2, op_ea_word, op_A, 0, OP_NULL }, + { NULL, 0xA0, F2MC_orw2, op_ea_word, op_A, 0, OP_NULL }, + { NULL, 0xC0, F2MC_xorw2, op_ea_word, op_A, 0, OP_NULL }, + { NULL, 0xE0, F2MC_notw, op_ea_word, 0, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_9_map[] = +{ + { NULL, 0x00, F2MC_mulu2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x20, F2MC_muluw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x40, F2MC_mul2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0x60, F2MC_mulw2, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0x80, F2MC_divu2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xA0, F2MC_divuw, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0xC0, F2MC_div2, op_A, op_ea_byte, 0, OP_NULL }, + { NULL, 0xE0, F2MC_divw, op_A, op_ea_word, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t RWi_ea_map[] = +{ + { NULL, 0x00, F2MC_null, op_RWi, op_ea_word, 0, OP_2_1(32) }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t Ri_ea_map[] = +{ + { NULL, 0x00, F2MC_null, op_Ri, op_ea_byte, 0, OP_2_1(32) }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_Ri_map[] = +{ + { NULL, 0x00, F2MC_null, op_ea_byte, op_Ri, 0, OP_1_2(32) }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t ea_RWi_map[] = +{ + { NULL, 0x00, F2MC_null, op_ea_word, op_RWi, 0, OP_1_2(32) }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +static const map_t basic_map[] = +{ + { NULL, 0x00, F2MC_nop, 0, 0, 0, OP_NULL }, + { NULL, 0x01, F2MC_int9, 0, 0, 0, OP_NULL }, + { NULL, 0x02, F2MC_adddc, op_A, 0, 0, OP_NULL }, + { NULL, 0x03, F2MC_neg, op_A, 0, 0, OP_NULL }, + { NULL, 0x04, F2MC_pcb, 0, 0, 0, OP_NULL }, + { NULL, 0x05, F2MC_dtb, 0, 0, 0, OP_NULL }, + { NULL, 0x06, F2MC_adb, 0, 0, 0, OP_NULL }, + { NULL, 0x07, F2MC_spb, 0, 0, 0, OP_NULL }, + { NULL, 0x08, F2MC_link, op_imm8, 0, 0, OP_NULL }, + { NULL, 0x09, F2MC_unlink, 0, 0, 0, OP_NULL }, + { NULL, 0x0A, F2MC_mov, op_RP, op_imm8, 0, OP_NULL }, + { NULL, 0x0B, F2MC_negw, op_A, 0, 0, OP_NULL }, + { NULL, 0x0C, F2MC_lslw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x0D, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x0E, F2MC_asrw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x0F, F2MC_lsrw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x10, F2MC_cmr, 0, 0, 0, OP_NULL }, + { NULL, 0x11, F2MC_ncc, 0, 0, 0, OP_NULL }, + { NULL, 0x12, F2MC_subdc, op_A, 0, 0, OP_NULL }, + { NULL, 0x13, F2MC_jctx, op_byte_at_A, 0, 0, OP_NULL }, + { NULL, 0x14, F2MC_ext, 0, 0, 0, OP_NULL }, + { NULL, 0x15, F2MC_zext, 0, 0, 0, OP_NULL }, + { NULL, 0x16, F2MC_swap, 0, 0, 0, OP_NULL }, + { NULL, 0x17, F2MC_addsp, op_imm8, 0, 0, OP_NULL }, + { NULL, 0x18, F2MC_addl, op_A, op_imm32, 0, OP_NULL }, + { NULL, 0x19, F2MC_subl, op_A, op_imm32, 0, OP_NULL }, + { NULL, 0x1A, F2MC_mov, op_ILM, op_imm8, 0, OP_NULL }, + { NULL, 0x1B, F2MC_cmpl, op_A, op_imm32, 0, OP_NULL }, + { NULL, 0x1C, F2MC_extw, 0, 0, 0, OP_NULL }, + { NULL, 0x1D, F2MC_zextw, 0, 0, 0, OP_NULL }, + { NULL, 0x1E, F2MC_swapw, 0, 0, 0, OP_NULL }, + { NULL, 0x1F, F2MC_addsp, op_imm16, 0, 0, OP_NULL }, + { NULL, 0x20, F2MC_add, op_A, op_dir_byte, 0, OP_NULL }, + { NULL, 0x21, F2MC_sub, op_A, op_dir_byte, 0, OP_NULL }, + { NULL, 0x22, F2MC_addc1, op_A, 0, 0, OP_NULL }, + { NULL, 0x23, F2MC_cmp1, op_A, 0, 0, OP_NULL }, + { NULL, 0x24, F2MC_and, op_CCR, op_imm8, 0, OP_NULL }, + { NULL, 0x25, F2MC_or, op_CCR, op_imm8, 0, OP_NULL }, + { NULL, 0x26, F2MC_divu1, op_A, 0, 0, OP_NULL }, + { NULL, 0x27, F2MC_mulu1, op_A, 0, 0, OP_NULL }, + { NULL, 0x28, F2MC_addw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x29, F2MC_subw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x29, F2MC_subw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x2A, F2MC_cbne, op_A, op_imm8, op_rel, OP_NULL }, + { NULL, 0x2B, F2MC_cmpw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x2C, F2MC_andw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x2D, F2MC_orw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x2E, F2MC_xorw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x2F, F2MC_muluw1, op_A, 0, 0, OP_NULL }, + { NULL, 0x30, F2MC_add, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x31, F2MC_sub, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x32, F2MC_subc1, op_A, 0, 0, OP_NULL }, + { NULL, 0x33, F2MC_cmp2, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x34, F2MC_and, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x35, F2MC_or, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x36, F2MC_xor, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x37, F2MC_not, op_A, 0, 0, OP_NULL }, + { NULL, 0x38, F2MC_addw2, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x39, F2MC_subw2, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x3A, F2MC_cwbne, op_A, op_imm16, op_rel, OP_NULL }, + { NULL, 0x3B, F2MC_cmpw2, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x3C, F2MC_andw2, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x3D, F2MC_orw2, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x3E, F2MC_xorw2, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x3F, F2MC_notw, op_A, 0, 0, OP_NULL }, + { NULL, 0x40, F2MC_mov, op_A, op_dir_byte, 0, OP_NULL }, + { NULL, 0x41, F2MC_mov, op_dir_byte, op_A, 0, OP_NULL }, + { NULL, 0x42, F2MC_mov, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x43, F2MC_movx, op_A, op_imm8, 0, OP_NULL }, + { NULL, 0x44, F2MC_mov, op_dir_byte, op_imm8, 0, OP_NULL }, + { NULL, 0x45, F2MC_movx, op_A, op_dir_byte, 0, OP_NULL }, + { NULL, 0x46, F2MC_movw, op_A, op_SP, 0, OP_NULL }, + { NULL, 0x47, F2MC_movw, op_SP, op_A, 0, OP_NULL }, + { NULL, 0x48, F2MC_movw, op_A, op_dir_word, 0, OP_NULL }, + { NULL, 0x49, F2MC_movw, op_dir_word, op_A, 0, OP_NULL }, + { NULL, 0x4A, F2MC_movw, op_A, op_imm16, 0, OP_NULL }, + { NULL, 0x4B, F2MC_movl, op_A, op_imm32, 0, OP_NULL }, + { NULL, 0x4C, F2MC_pushw, op_A, 0, 0, OP_NULL }, + { NULL, 0x4D, F2MC_pushw, op_AH, 0, 0, OP_NULL }, + { NULL, 0x4E, F2MC_pushw, op_PS, 0, 0, OP_NULL }, + { NULL, 0x4F, F2MC_pushw, op_rlst, 0, 0, OP_NULL }, + { NULL, 0x50, F2MC_mov, op_A, op_io_byte, 0, OP_NULL }, + { NULL, 0x51, F2MC_mov, op_io_byte, op_A, 0, OP_NULL }, + { NULL, 0x52, F2MC_mov, op_A, op_addr16_byte, 0, OP_NULL }, + { NULL, 0x53, F2MC_mov, op_addr16_byte, op_A, 0, OP_NULL }, + { NULL, 0x54, F2MC_mov, op_io_byte, op_imm8, 0, OP_NULL }, + { NULL, 0x55, F2MC_movx, op_A, op_io_byte, 0, OP_NULL }, + { NULL, 0x56, F2MC_movw, op_io_word, op_imm16, 0, OP_NULL }, + { NULL, 0x57, F2MC_movx, op_A, op_addr16_byte, 0, OP_NULL }, + { NULL, 0x58, F2MC_movw, op_A, op_io_word, 0, OP_NULL }, + { NULL, 0x59, F2MC_movw, op_io_word, op_A, 0, OP_NULL }, + { NULL, 0x5A, F2MC_movw, op_A, op_addr16_word, 0, OP_NULL }, + { NULL, 0x5B, F2MC_movw, op_addr16_word, op_A, 0, OP_NULL }, + { NULL, 0x5C, F2MC_popw, op_A, 0, 0, OP_NULL }, + { NULL, 0x5D, F2MC_popw, op_AH, 0, 0, OP_NULL }, + { NULL, 0x5E, F2MC_popw, op_PS, 0, 0, OP_NULL }, + { NULL, 0x5F, F2MC_popw, op_rlst, 0, 0, OP_NULL }, + { NULL, 0x60, F2MC_bra, op_rel, 0, 0, OP_NULL }, + { NULL, 0x61, F2MC_jmp, op_code_at_A, 0, 0, OP_NULL }, + { NULL, 0x62, F2MC_jmp, op_addr16_code, 0, 0, OP_NULL }, + { NULL, 0x63, F2MC_jmpp, op_addr24, 0, 0, OP_NULL }, + { NULL, 0x64, F2MC_call, op_addr16_code, 0, 0, OP_NULL }, + { NULL, 0x65, F2MC_callp, op_addr24, 0, 0, OP_NULL }, + { NULL, 0x66, F2MC_retp, 0, 0, 0, OP_NULL }, + { NULL, 0x67, F2MC_ret, 0, 0, 0, OP_NULL }, + { NULL, 0x68, F2MC_int, op_imm8, 0, 0, OP_NULL }, + { NULL, 0x69, F2MC_int, op_addr16_code, 0, 0, OP_NULL }, + { NULL, 0x6A, F2MC_intp, op_addr24, 0, 0, OP_NULL }, + { NULL, 0x6B, F2MC_reti, 0, 0, 0, OP_NULL }, + { bitop_map, 0x6C, F2MC_null, 0, 0, 0, OP_NULL }, + { NULL, 0x6D, F2MC_null, 0, 0, 0, OP_NULL }, + { strop_map, 0x6E, F2MC_null, 0, 0, 0, OP_NULL }, + { twobyte_map,0x6F, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_1_map, 0x70, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_2_map, 0x71, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_3_map, 0x72, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_4_map, 0x73, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_5_map, 0x74, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_6_map, 0x75, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_7_map, 0x76, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_8_map, 0x77, F2MC_null, 0, 0, 0, OP_NULL }, + { ea_9_map, 0x78, F2MC_null, 0, 0, 0, OP_NULL }, + { RWi_ea_map, 0x79, F2MC_movea, 0, 0, 0, OP_NULL }, + { Ri_ea_map, 0x7A, F2MC_mov, 0, 0, 0, OP_NULL }, + { RWi_ea_map, 0x7B, F2MC_movw, 0, 0, 0, OP_NULL }, + { ea_Ri_map, 0x7C, F2MC_mov, 0, 0, 0, OP_NULL }, + { ea_RWi_map, 0x7D, F2MC_movw, 0, 0, 0, OP_NULL }, + { Ri_ea_map, 0x7E, F2MC_xch, 0, 0, 0, OP_NULL }, + { RWi_ea_map, 0x7F, F2MC_xchw, 0, 0, 0, OP_NULL }, + { NULL, 0x80, F2MC_mov, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0x88, F2MC_movw, op_A, op_RWi, 0, OP_NULL }, + { NULL, 0x90, F2MC_mov, op_Ri, op_A, 0, OP_NULL }, + { NULL, 0x98, F2MC_movw, op_RWi, op_A, 0, OP_NULL }, + { NULL, 0xA0, F2MC_mov, op_Ri, op_imm8, 0, OP_NULL }, + { NULL, 0xA8, F2MC_movw, op_RWi, op_imm16, 0, OP_NULL }, + { NULL, 0xB0, F2MC_movx, op_A, op_Ri, 0, OP_NULL }, + { NULL, 0xB8, F2MC_movw, op_A, op_word_at_RWi_disp8, 0, OP_NULL }, + { NULL, 0xC0, F2MC_movx, op_A, op_byte_at_RWi_disp8, 0, OP_NULL }, + { NULL, 0xC8, F2MC_movw, op_word_at_RWi_disp8, op_A, 0, OP_NULL }, + { NULL, 0xD0, F2MC_movn, op_A, op_imm4, 0, OP_NULL }, + { NULL, 0xE0, F2MC_callv, op_imm4, 0, 0, OP_NULL }, + { NULL, 0xF0, F2MC_bz, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF1, F2MC_bnz, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF2, F2MC_bc, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF3, F2MC_bnc, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF4, F2MC_bn, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF5, F2MC_bp, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF6, F2MC_bv, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF7, F2MC_bnv, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF8, F2MC_bt, op_rel, 0, 0, OP_NULL }, + { NULL, 0xF9, F2MC_bnt, op_rel, 0, 0, OP_NULL }, + { NULL, 0xFA, F2MC_blt, op_rel, 0, 0, OP_NULL }, + { NULL, 0xFB, F2MC_bge, op_rel, 0, 0, OP_NULL }, + { NULL, 0xFC, F2MC_ble, op_rel, 0, 0, OP_NULL }, + { NULL, 0xFD, F2MC_bgt, op_rel, 0, 0, OP_NULL }, + { NULL, 0xFE, F2MC_bls, op_rel, 0, 0, OP_NULL }, + { NULL, 0xFF, F2MC_bhi, op_rel, 0, 0, OP_NULL }, + { NULL, 0, 0, 0, 0, 0, OP_NULL } +}; + +//-------------------------------------------------------------------------- +static bool is_A(const insn_t *, const op_t &op) +{ + return op.type == o_reg && op.reg == A; +} + +//-------------------------------------------------------------------------- +static bool is_1(const insn_t *, const op_t &op) +{ + return op.type == o_imm && op.value == 1; +} + +//-------------------------------------------------------------------------- +#define is_rel(REL) \ +static bool is_rel##REL(const insn_t *insn, const op_t &op) \ +{ \ + return op.type == o_near && op.addr == insn->ea + REL; \ +} +is_rel(5) // is_rel5 +is_rel(7) // is_rel7 + +//-------------------------------------------------------------------------- +static bool is_imm(const insn_t *, const op_t &op) +{ + return op.type == o_imm; +} + +//-------------------------------------------------------------------------- +// can't be A (if A then this is a dec/decw MACRO) +static bool is_ea_and_not_A(const insn_t *, const op_t &op) +{ + return op.type != o_reg || op.reg != A; +} + +//-------------------------------------------------------------------------- +static bool is_bp(const insn_t *, const op_t &op) +{ + return op.special_mode == MODE_BIT; +} + +//-------------------------------------------------------------------------- +static bool is_bp_addr16(const insn_t *insn, const op_t &op) +{ + return op.type == o_mem && op.dtype == dt_byte && is_bp(insn, op); +} + +//-------------------------------------------------------------------------- +#define macro_incdec(ITYPE) \ + static const macro_insn_t macro_##ITYPE[] = \ + { \ + { is_A, is_1, 0, F2MC_##ITYPE }, \ + { 0, 0, 0, F2MC_null } \ + } +macro_incdec(add); // macro_add +macro_incdec(addw2); // macro_addw2 +macro_incdec(addl); // macro_addl +macro_incdec(sub); // macro_sub +macro_incdec(subw2); // macro_subw2 +macro_incdec(subl); // macro_subl + +#define macro_bXX16(ITYPE) \ + static const macro_insn_t macro_##ITYPE##_jmp[] = \ + { \ + { is_rel5, 0, 0, F2MC_##ITYPE }, \ + { 0, 0, 0, F2MC_jmp }, \ + { 0, 0, 0, F2MC_null } \ + } +macro_bXX16(bnz); // macro_bnz_jmp +macro_bXX16(bz); // macro_bz_jmp +macro_bXX16(bnc); // macro_bnc_jmp +macro_bXX16(bc); // macro_bc_jmp +macro_bXX16(bp); // macro_bp_jmp +macro_bXX16(bn); // macro_bn_jmp +macro_bXX16(bnv); // macro_bnv_jmp +macro_bXX16(bv); // macro_bv_jmp +macro_bXX16(bnt); // macro_bnt_jmp +macro_bXX16(bt); // macro_bt_jmp +macro_bXX16(bge); // macro_bge_jmp +macro_bXX16(blt); // macro_blt_jmp +macro_bXX16(bgt); // macro_bgt_jmp +macro_bXX16(ble); // macro_ble_jmp +macro_bXX16(bhi); // macro_bhi_jmp +macro_bXX16(bls); // macro_bls_jmp + +#define macro_cXbne16(ITYPE) \ + static const macro_insn_t macro_##ITYPE##_bnz16[] = \ + { \ + { is_A, is_imm, 0, F2MC_##ITYPE }, \ + { 0, 0, 0, F2MC_bnz16 }, \ + { 0, 0, 0, F2MC_null } \ + } +macro_cXbne16(cmp2); // macro_cmp2_bnz16 +macro_cXbne16(cmpw2); // macro_cmpw2_bnz16 + +#define macro_dXbnz16(ITYPE) \ + static const macro_insn_t macro_##ITYPE##_bnz16[] = \ + { \ + { is_ea_and_not_A, 0, 0, F2MC_##ITYPE }, \ + { 0, 0, 0, F2MC_bnz16 }, \ + { 0, 0, 0, F2MC_null } \ + } +macro_dXbnz16(dec); // macro_dec_bnz16 +macro_dXbnz16(decw); // macro_decw_bnz16 + +#define macro_bbX16(ITYPE) \ + static const macro_insn_t macro_##ITYPE##_jmp[] = \ + { \ + { is_bp, is_rel7, 0, F2MC_##ITYPE }, \ + { 0, 0, 0, F2MC_jmp }, \ + { 0, 0, 0, F2MC_null } \ + } +macro_bbX16(bbc); // macro_bbc_jmp +macro_bbX16(bbs); // macro_bbs_jmp + +static const macro_insn_t macro_sbbs_bra_jmp[] = +{ + { is_bp_addr16, is_rel7, 0, F2MC_sbbs }, + { is_rel5, 0, 0, F2MC_bra }, + { 0, 0, 0, F2MC_jmp }, + { 0, 0, 0, F2MC_null } +}; + + +static const macro_t macros[] = +{ + { macro_add, F2MC_inc, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, + { macro_addw2, F2MC_incw, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, + { macro_addl, F2MC_incl, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, + { macro_sub, F2MC_dec, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, + { macro_subw2, F2MC_decw, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, + { macro_subl, F2MC_decl, 1, OP_CMD(1,1), OP_VOID, OP_VOID }, + { macro_bnz_jmp, F2MC_bz16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bz_jmp, F2MC_bnz16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bnc_jmp, F2MC_bc16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bc_jmp, F2MC_bnc16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bp_jmp, F2MC_bn16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bn_jmp, F2MC_bp16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bnv_jmp, F2MC_bv16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bv_jmp, F2MC_bnv16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bnt_jmp, F2MC_bt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bt_jmp, F2MC_bnt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bge_jmp, F2MC_blt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_blt_jmp, F2MC_bge16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bgt_jmp, F2MC_ble16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_ble_jmp, F2MC_bgt16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bhi_jmp, F2MC_bls16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_bls_jmp, F2MC_bhi16, 1, OP_CMD(2,1), OP_VOID, OP_VOID }, + { macro_cmp2_bnz16, F2MC_cbne16, 1, OP_CMD(1,1), OP_CMD(1,2), OP_CMD(2,1) }, + { macro_cmpw2_bnz16, F2MC_cwbne16, 1, OP_CMD(1,1), OP_CMD(1,2), OP_CMD(2,1) }, + { macro_dec_bnz16, F2MC_dbnz16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, + { macro_decw_bnz16, F2MC_dwbnz16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, + { macro_bbs_jmp, F2MC_bbc16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, + { macro_bbc_jmp, F2MC_bbs16, 1, OP_CMD(1,1), OP_CMD(2,1), OP_VOID }, + { macro_sbbs_bra_jmp, F2MC_sbbs16, 1, OP_CMD(1,1), OP_CMD(3,1), OP_VOID }, + { NULL, F2MC_null, OP_VOID, OP_VOID, OP_VOID, 0 } +}; + +//-------------------------------------------------------------------------- +void f2mc_t::ana_F2MC16LX(insn_t &insn) +{ + process_maps(insn, basic_map, F2MC_null); // analyze opcode + + // analyze prefix + char prefix; + switch ( insn.itype ) + { + case F2MC_pcb: prefix = PCB; break; + case F2MC_dtb: prefix = DTB; break; + case F2MC_adb: prefix = ADB; break; + case F2MC_spb: prefix = SPB; break; + default: prefix = 0; break; + } + if ( prefix ) + { + insn_t next; + if ( decode_insn(&next, insn.ea + insn.size) > 0 && next.default_bank + && (prefix != next.default_bank) ) // if next instruction need prefix + { + next.ea = insn.ea; + next.size += insn.size; + next.prefix_bank = prefix; + insn = next; + } + } + + process_macros(insn, macros, F2MC_null, (idpflags & F2MC_MACRO) != 0); +} + +//-------------------------------------------------------------------------- +int f2mc_t::ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + + switch ( ptype ) + { + case F2MC16L: + ana_F2MC16LX(insn); + switch ( insn.itype ) + { + case F2MC_div1: + case F2MC_div2: + case F2MC_divw: + case F2MC_mul1: + case F2MC_mul2: + case F2MC_mulw1: + case F2MC_mulw2: + insn.itype = F2MC_null; + break; + } + break; + case F2MC16LX: + ana_F2MC16LX(insn); + break; + default: + error("interr: ana: ana()"); + } + if ( insn.itype == F2MC_null ) + return 0; + return insn.size; +} + +//-------------------------------------------------------------------------- +int get_signed(int byte, int mask) +{ + int bits = mask >> 1; + int sign = bits + 1; + if ( byte & sign ) // offset < 0 + { + byte = ( byte & bits ) - sign; + } + else // offset >= 0 + { + byte = byte & mask; + } + return byte; +} diff --git a/idasdk76/module/f2mc/emu.cpp b/idasdk76/module/f2mc/emu.cpp new file mode 100644 index 0000000..8378d67 --- /dev/null +++ b/idasdk76/module/f2mc/emu.cpp @@ -0,0 +1,297 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "f2mc.hpp" +#include <segregs.hpp> +#include <frame.hpp> + +//------------------------------------------------------------------------ +static int get_reglist_size(ushort reglist) +{ + int size = 0; + for ( int i = 0; i < 8; i++ ) + if ( (reglist >> i) & 1 ) + size++; + return size; +} + +//------------------------------------------------------------------------ +static bool is_bank(const op_t &op) +{ + if ( op.type != o_reg ) + return false; + + return op.reg == DTB + || op.reg == ADB + || op.reg == SSB + || op.reg == USB + || op.reg == DPR + || op.reg == PCB; +} + +//---------------------------------------------------------------------- +static void process_imm(const insn_t &insn, const op_t &x) +{ + set_immd(insn.ea); + + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, dr_O, calc_outf(x)); + + if ( is_defarg(get_flags(insn.ea), x.n) ) + return; // if already defined by user + + switch ( insn.itype ) + { + case F2MC_add: + case F2MC_addl: + case F2MC_addsp: + case F2MC_addw2: + case F2MC_and: + case F2MC_andw2: + case F2MC_callv: + case F2MC_cbne: + case F2MC_cmp2: + case F2MC_cmpl: + case F2MC_cmpw2: + case F2MC_cwbne: + case F2MC_int: + case F2MC_link: + case F2MC_mov: + case F2MC_movl: + case F2MC_movn: + case F2MC_movw: + case F2MC_movx: + case F2MC_or: + case F2MC_orw2: + case F2MC_sub: + case F2MC_subl: + case F2MC_subw2: + case F2MC_xor: + case F2MC_xorw2: + op_num(insn.ea, x.n); + } +} + +//---------------------------------------------------------------------- +void f2mc_t::handle_operand(const insn_t &insn, const op_t &x, bool use) +{ + switch ( x.type ) + { + case o_reg: + case o_phrase: + case o_reglist: + return; + + case o_near: + case o_far: + { + cref_t ftype = fl_JN; + ea_t ea = x.addr; + // 24-bit (far) operands store the full address. + // so this calculation is needed only for near jumps/calls + if ( x.type == o_near ) + ea = calc_code_mem(insn, x.addr); + + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + if ( !func_does_return(ea) ) + flow = false; + ftype = fl_CN; + } + insn.add_cref(ea, x.offb, ftype); + } + break; + + case o_imm: + QASSERT(10102, use); + process_imm(insn, x); + break; + + case o_mem: + { + ea_t ea = calc_data_mem(x.addr); + insn.add_dref(ea, x.offb, use ? dr_R : dr_W); + insn.create_op_data(ea, x); + } + break; + case o_displ: + process_imm(insn, x); + if ( may_create_stkvars() && x.reg == RW3 ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL + && (pfn->flags & FUNC_FRAME) != 0 + && insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) ) + { + op_stkvar(insn.ea, x.n); + } + } + break; + + default: + warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); + } +} + +//---------------------------------------------------------------------- +inline bool add_stkpnt(func_t *pfn, sval_t delta, const insn_t &insn) +{ + return add_auto_stkpnt(pfn, insn.ea + insn.size, delta); +} + +//---------------------------------------------------------------------- +static void trace_sp(const insn_t &insn) +{ + func_t *pfn = get_func(insn.ea); + if ( pfn == NULL ) + return; + + switch ( insn.itype ) + { + case F2MC_int: + case F2MC_intp: + case F2MC_int9: + add_stkpnt(pfn, -6*2, insn); + break; + case F2MC_reti: + add_stkpnt(pfn, 6*2, insn); + break; + case F2MC_link: + add_stkpnt(pfn, -2-insn.Op1.value, insn); + break; + case F2MC_unlink: + add_stkpnt(pfn, -get_spd(pfn, insn.ea), insn); + break; + case F2MC_ret: + add_stkpnt(pfn, 2, insn); + break; + case F2MC_retp: + add_stkpnt(pfn, 2*2, insn); + break; + case F2MC_pushw: + if ( insn.Op1.type == o_reglist ) + add_stkpnt(pfn, -get_reglist_size(insn.Op1.reg)*2, insn); + else + add_stkpnt(pfn, -2, insn); + break; + case F2MC_popw: + if ( insn.Op1.type == o_reglist ) + add_stkpnt(pfn, get_reglist_size(insn.Op1.reg)*2, insn); + else + add_stkpnt(pfn, 2, insn); + break; + case F2MC_addsp: + add_stkpnt(pfn, insn.Op1.value, insn); + break; + } +} + +//---------------------------------------------------------------------- + +int f2mc_t::emu(const insn_t &insn) +{ + uint32 feature = insn.get_canon_feature(ph); + flow = (feature & CF_STOP) == 0; + + if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, true); + if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, true); + if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, true); + + if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false); + if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false); + if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, false); + + // check for CCR changes + if ( insn.Op1.type == o_reg && insn.Op1.reg == CCR ) + { + op_bin(insn.ea, 1); + + sel_t ccr = get_sreg(insn.ea, CCR); + if ( ccr == BADSEL ) + ccr = 0; + + if ( insn.itype == F2MC_and ) + ccr &= insn.Op2.value; // and ccr,imm8 + else if ( insn.itype == F2MC_or ) + ccr |= insn.Op2.value; // or ccr,imm8 + split_sreg_range(get_item_end(insn.ea), CCR, ccr, SR_auto); + } + + + // check for DTB,ADB,SSB,USB,DPR changes + if ( insn.itype == F2MC_mov && is_bank(insn.Op1) + && insn.Op2.type == o_reg && insn.Op2.reg == A ) // mov dtb|adb|ssb|usb|dpr,a + { + sel_t bank = BADSEL; + insn_t l; + if ( decode_prev_insn(&l, insn.ea) != BADADDR && l.itype == F2MC_mov + && l.Op1.type == o_reg && l.Op1.reg == A ) + { + if ( l.Op2.type == o_imm ) // mov a,imm8 + bank = l.Op2.value; + else if ( is_bank(l.Op2) ) // mov a,dtb|adb|ssb|usb|dpr|pcb + { + bank = get_sreg(l.ea, l.Op2.reg); + if ( bank == BADSEL ) + bank = 0; + } + } + if ( bank != BADSEL ) + split_sreg_range(get_item_end(insn.ea), insn.Op1.reg, bank, SR_auto); + } + + + // determine if the next instruction should be executed + if ( segtype(insn.ea) == SEG_XTRN ) + flow = false; + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + if ( may_trace_sp() ) + { + if ( !flow ) + recalc_spd(insn.ea); // recalculate SP register for the next insn + else + trace_sp(insn); + } + + return 1; +} + +//---------------------------------------------------------------------- +bool idaapi create_func_frame(func_t *pfn) +{ + if ( pfn != NULL ) + { + if ( pfn->frame == BADNODE ) + { + ea_t ea = pfn->start_ea; + if ( ea + 4 < pfn->end_ea ) // minimum 2+1+1 bytes needed + { + insn_t insn; + decode_insn(&insn, ea); + if ( insn.itype == F2MC_link ) + { + size_t localsize = (size_t)insn.Op1.value; + ushort regsize = 2; + decode_insn(&insn, ea + 2); + pfn->flags |= FUNC_FRAME; + return add_frame(pfn, localsize, regsize, 0); + } + } + } + } + return 0; +} + +//---------------------------------------------------------------------- +int idaapi is_sp_based(const insn_t &, const op_t &) +{ + return OP_SP_ADD | OP_FP_BASED; +} diff --git a/idasdk76/module/f2mc/f2mc.hpp b/idasdk76/module/f2mc/f2mc.hpp new file mode 100644 index 0000000..21bd09f --- /dev/null +++ b/idasdk76/module/f2mc/f2mc.hpp @@ -0,0 +1,159 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _F2MC_HPP +#define _F2MC_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + +//------------------------------------------------------------------ +enum regnum_t +{ + A, // accumulator + AL, // accumulator + AH, // accumulator + PC, // program counter + SP, // stack pointer + R0, + R1, + R2, + R3, + R4, + R5, + R6, + R7, + RW0, + RW1, + RW2, + RW3, + RW4, + RW5, + RW6, + RW7, + RL0, + RL1, + RL2, + RL3, + + PCB, // program bank register + DTB, // data bank register + ADB, // additional data bank register + SSB, // system stack bank register + USB, // user stack bank register + CCR, // condition code register + DPR, // direct page register + rVcs, rVds, // virtual registers for code and data segments + + SPB, // stack pointer bank register + PS, // processor status + ILM, // interrupt level mask register + RP // register bank pointer +}; + +//------------------------------------------------------------------ +// specific processor records + +#define default_bank segpref +#define prefix_bank auxpref_u8[1] +#define op_bank auxpref_u8[0] +// o_phrase = @reg+(f2mc_index) (f2mc_index if PHRASE_INDEX) + #define at specflag1 // number of @ indirections (dtype @ = op.dtype) + #define special_mode specflag2 + #define MODE_INC 1 + #define MODE_INDEX 2 + #define f2mc_index specval_shorts.high +#define o_reglist o_idpspec0 +// o_disp = @reg+value +#define addr_dtyp specflag3 + #define MODE_BIT 1 + #define byte_bit specflag4 + +//------------------------------------------------------------------ +// processor types + +typedef uchar proctype_t; + +const proctype_t F2MC16L = 0; +const proctype_t F2MC16LX = 1; + +extern ea_t dataseg; +//------------------------------------------------------------------ +#define F2MC_MACRO 0x0001 // use instruction macros +inline ea_t calc_code_mem(const insn_t &insn, ea_t ea) { return to_ea(insn.cs, ea); } +inline ea_t calc_data_mem(ea_t ea) { return (get_sreg(ea, DTB) << 16) | ea; } + +int get_signed(int byte,int mask); + +ea_t map_port(ea_t from); +int calc_outf(const op_t &x); +//------------------------------------------------------------------ +void idaapi f2mc_segend(outctx_t &ctx, segment_t *seg); + +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_sp_based(const insn_t &insn, const op_t &x); + +//------------------------------------------------------------------ +struct f2mc_iohandler_t : public iohandler_t +{ + struct f2mc_t ± + f2mc_iohandler_t(f2mc_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual const char *aux_segm() const override { return "FSR"; } + virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override; + virtual const char *iocallback(const ioports_t &iop, const char *line) override; +}; + +struct f2mc_t : public procmod_t +{ + netnode helper; + f2mc_iohandler_t ioh = f2mc_iohandler_t(*this, helper); + const char *cfgname = nullptr; + proctype_t ptype = F2MC16LX; // contains processor type + ushort idpflags = F2MC_MACRO; + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void load_symbols(int _respect_info); + const char *find_sym(ea_t address); + const char *find_bit(ea_t address, int bit); + bool exist_bits(ea_t ea, int bitl, int bith); + void f2mc_set_device_name(int _respect_info); + void choose_and_set_device(int flags); + inline void choose_device(); + const char *set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + void adjust_ea_bit(ea_t &ea, int &bit); + void handle_operand(const insn_t &insn, const op_t &x, bool use); + int emu(const insn_t &insn); + + void ana_F2MC16LX(insn_t &insn); + int ana(insn_t *_insn); + + void f2mc_header(outctx_t &ctx); + void f2mc_assumes(outctx_t &ctx); + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void f2mc_segstart(outctx_t &ctx, segment_t *Srange) const; + void f2mc_footer(outctx_t &ctx) const; + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ f2mc" +#define PROCMOD_NAME f2mc + +#endif // _F2MC_HPP diff --git a/idasdk75/module/f2mc/f2mc16l.cfg b/idasdk76/module/f2mc/f2mc16l.cfg similarity index 100% rename from idasdk75/module/f2mc/f2mc16l.cfg rename to idasdk76/module/f2mc/f2mc16l.cfg diff --git a/idasdk75/module/f2mc/f2mc16lx.cfg b/idasdk76/module/f2mc/f2mc16lx.cfg similarity index 100% rename from idasdk75/module/f2mc/f2mc16lx.cfg rename to idasdk76/module/f2mc/f2mc16lx.cfg diff --git a/idasdk75/module/f2mc/ins.cpp b/idasdk76/module/f2mc/ins.cpp similarity index 100% rename from idasdk75/module/f2mc/ins.cpp rename to idasdk76/module/f2mc/ins.cpp diff --git a/idasdk76/module/f2mc/ins.hpp b/idasdk76/module/f2mc/ins.hpp new file mode 100644 index 0000000..deef447 --- /dev/null +++ b/idasdk76/module/f2mc/ins.hpp @@ -0,0 +1,222 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ + +F2MC_null = 0, // Unknown Operation + +// TRANSFER INSTRUCTIONS + +F2MC_mov, // Move byte data from source to destination +F2MC_movn, // Move immediate nibble data to A +F2MC_movx, // Move byte data with sign extension from source to A +F2MC_xch, // Exchange byte data of source to destination +F2MC_movw, // Move word data from source to destination +F2MC_xchw, // Exchange word data of source to destination +F2MC_movl, // Move long word data from source to destination + +// NUMERIC DATA OPERATIONS INSTRUCTIONS + +F2MC_add, // Add byte data of destination and source to destination +F2MC_addc1, // Add byte data of AL and AH with Carry to AL +F2MC_addc2, // Add byte data of A and effective address with Carry to A +F2MC_adddc, // Add decimal data of AL and AH with Carry to AL +F2MC_sub, // Subtract byte data of source from festination to destination +F2MC_subc1, // Subtract byte data of AL from AH with Carry to AL +F2MC_subc2, // Subtract byte data of effective address from A with Carry to A +F2MC_subdc, // Subtract decimal data of AL from AH with Carry to AL +F2MC_addw1, // Add word data of AH and AL to AL +F2MC_addw2, // Add word data of destination and source to destination +F2MC_addcw, // Add word data of A and effective address from A with Carry to A +F2MC_subw1, // Subtract word data of AL from AH to AL +F2MC_subw2, // Subtract word data of source from festination to destination +F2MC_subcw, // Subtract word data of A and effective address from A with carry to A +F2MC_addl, // Add long word data of destination and source to destination +F2MC_subl, // Subtract long word data of source from festination to destination +F2MC_inc, // Increment byte data +F2MC_dec, // Decrement byte data +F2MC_incw, // Increment word data +F2MC_decw, // Decrement word data +F2MC_incl, // Increment long word data +F2MC_decl, // Decrement long word data +F2MC_cmp1, // Compare byte data of AH and AL +F2MC_cmp2, // Compare byte data of destination and source +F2MC_cmpw1, // Compare word data of AH and AL +F2MC_cmpw2, // Compare word data of destination and source +F2MC_cmpl, // Compare long word data of destination and source +F2MC_divu1, // Divide unsigned AH by AL +F2MC_divu2, // Divide unsigned word data by unsigned byte data +F2MC_divuw, // Divide unsigned long word data by unsigned word data +F2MC_mulu1, // Multiply unsigned byte AH by AL +F2MC_mulu2, // Multiply unsigned byte data +F2MC_muluw1, // Multiply unsigned word AH by AL +F2MC_muluw2, // Multiply unsigned word data +F2MC_div1, // Divide AH by AL +F2MC_div2, // Divide word data by byte data +F2MC_divw, // Divide long word data by word data +F2MC_mul1, // Multiply byte AH by AL +F2MC_mul2, // Multiply byte data +F2MC_mulw1, // Multiply word AH by AL +F2MC_mulw2, // Multiply word data + +// LOGICAL DATA OPERATION INSTRUCTIONS + +F2MC_and, // And byte data of destination and source to destination +F2MC_or, // Or byte data of destination and source to destination +F2MC_xor, // Exclusive or byte data of destination and source to destination +F2MC_not, // Not byte data of destination +F2MC_andw1, // And word data of AH and AL to AL +F2MC_andw2, // And word data of destination and source to destination +F2MC_orw1, // Or word data of AH and AL to AL +F2MC_orw2, // Or word data of destination and source to destination +F2MC_xorw1, // Exclusive or word data of AH and AL to AL +F2MC_xorw2, // Exclusive or word data of destination and source to destination +F2MC_notw, // Not word data of destination +F2MC_andl, // And long word data of destination and source to destination +F2MC_orl, // Or long word data of destination and source to destination +F2MC_xorl, // Exclusive or long word data of destination and source to destination +F2MC_neg, // Negate byte data of destination +F2MC_negw, // Negate word data of destination +F2MC_nrml, // Normalize long word + +// SHIFT INSTRUCTIONS + +F2MC_rorc, // Rotate byte data of A with Carry to right +F2MC_rolc, // Rotate byte data of A with Carry to left +F2MC_asr, // Arithmetic shift byte data of A to right +F2MC_lsr, // Logical shift byte data of A to right +F2MC_lsl, // Logical shift byte data of A to left +F2MC_asrw1, // Arithmetic shift word data of A to right +F2MC_asrw2, // Arithmetic shift word data of A to right +F2MC_lsrw1, // Logical shift word data of A to right +F2MC_lsrw2, // Logical shift word data of A to right +F2MC_lslw1, // Logical shift word data of A to left +F2MC_lslw2, // Logical shift word data of A to left +F2MC_asrl, // Arithmetic shift long word data of A to right +F2MC_lsrl, // Logical shift long word data of A to right +F2MC_lsll, // Logical shift long word data of A to left + +// BRANCH INSTRUCTIONS + +F2MC_bz, // Branch if Zero +F2MC_bnz, // Branch if Not Zero +F2MC_bc, // Branch if Carry +F2MC_bnc, // Branch if Not Carry +F2MC_bn, // Branch if Negative +F2MC_bp, // Branch if Not Negative +F2MC_bv, // Branch if Overflow +F2MC_bnv, // Branch if Not Overflow +F2MC_bt, // Branch if Sticky +F2MC_bnt, // Branch if Not Sticky +F2MC_blt, // Branch if Overflow or Negative +F2MC_bge, // Branch if Not (Overflow or Negative) +F2MC_ble, // Branch if (Overflow xor Negative) or Zero +F2MC_bgt, // Branch if Not ((Overflow xor Negative) or Zero) +F2MC_bls, // Branch if Carry or Zero +F2MC_bhi, // Branch if Not (Carry or Zero) +F2MC_bra, // Branch unconditionally +F2MC_jmp, // Jump destination address +F2MC_jmpp, // Jump destination physical address +F2MC_call, // Call subroutine +F2MC_callv, // Call vectored subroutine +F2MC_callp, // Call physical address +F2MC_cbne, // Compare byte data and branch if not Equal +F2MC_cwbne, // Compare word data and branch if not Equal +F2MC_dbnz, // Decrement byte data and branch if not Zero +F2MC_dwbnz, // Decrement word data and branch if not Zero +F2MC_int, // Software interrupt +F2MC_intp, // Software interrupt +F2MC_int9, // Software interrupt +F2MC_reti, // Return from interrupt +F2MC_link, // Link and create new stack frame +F2MC_unlink, // Unlink and create new stack frame +F2MC_ret, // Return from subroutine +F2MC_retp, // Return from physical address + +// OTHER INSTRUCTIONS + +F2MC_pushw, // Push to stack memory +F2MC_popw, // Pop from stack memory +F2MC_jctx, // Jump context +// F2MC_and, +// F2MC_or, +// F2MC_mov, +F2MC_movea, // Move effective address to destination +F2MC_addsp, // Add word data of SP and immediate data to SP +// F2MC_mov, +F2MC_nop, // No operation +F2MC_adb, // ADB register +F2MC_dtb, // DTB register +F2MC_pcb, // PCB register +F2MC_spb, // SPB register +F2MC_ncc, // Flag change inhibit +F2MC_cmr, // Common register bank +F2MC_movb, // Move bit data +F2MC_setb, // Set bit +F2MC_clrb, // Clear bit +F2MC_bbc, // Branch if bit condition satisfied +F2MC_bbs, // Branch if bit condition satisfied +F2MC_sbbs, // Set bit and branch if bit set +F2MC_wbts, // Wait until bit condition satisfied +F2MC_wbtc, // Wait until bit condition satisfied +F2MC_swap, // Swap byte data of A +F2MC_swapw, // Swap word data of A +F2MC_ext, // Sign extend from byte data to word data +F2MC_extw, // Sign extend from word data to long word data +F2MC_zext, // Zero extendfrom byte data to word data +F2MC_zextw, // Zero extendfrom word data to long word data +F2MC_movsi, // Move string byte with addresses incremented +F2MC_movsd, // Move string byte with addresses decremented +F2MC_sceqi, // Scan string byte until Equal with address incremented +F2MC_sceqd, // Scan string byte until Equal with address decremented +F2MC_filsi, // Fill string byte +F2MC_movswi, // Move string word with address incremented +F2MC_movswd, // Move string word with address decremented +F2MC_scweqi, // Scan string word until Equal with address incremented +F2MC_scweqd, // Scan string word until Equal with address decremented +F2MC_filswi, // Fill string word + +// MACROS + +F2MC_bz16, // Branch if Zero +F2MC_bnz16, // Branch if Not Zero +F2MC_bc16, // Branch if Carry +F2MC_bnc16, // Branch if Not Carry +F2MC_bn16, // Branch if Negative +F2MC_bp16, // Branch if Not Negative +F2MC_bv16, // Branch if Overflow +F2MC_bnv16, // Branch if Not Overflow +F2MC_bt16, // Branch if Sticky +F2MC_bnt16, // Branch if Not Sticky +F2MC_blt16, // Branch if Overflow or Negative +F2MC_bge16, // Branch if Not (Overflow or Negative) +F2MC_ble16, // Branch if (Overflow xor Negative) or Zero +F2MC_bgt16, // Branch if Not ((Overflow xor Negative) or Zero) +F2MC_bls16, // Branch if Carry or Zero +F2MC_bhi16, // Branch if Not (Carry or Zero) + +F2MC_cbne16, // Compare byte data and branch if not Equal +F2MC_cwbne16, // Compare word data and branch if not Equal + +F2MC_dbnz16, // Decrement byte data and branch if not Zero +F2MC_dwbnz16, // Decrement word data and branch if not Zero + +F2MC_bbc16, // Branch if bit condition satisfied +F2MC_bbs16, // Branch if bit condition satisfied +F2MC_sbbs16, // Set bit and branch if bit set + +F2MC_last, + +}; + +#endif diff --git a/idasdk76/module/f2mc/makefile b/idasdk76/module/f2mc/makefile new file mode 100644 index 0000000..7e8101b --- /dev/null +++ b/idasdk76/module/f2mc/makefile @@ -0,0 +1,57 @@ +PROC=f2mc +CONFIGS=f2mc16l.cfg f2mc16lx.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp f2mc.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp f2mc.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp f2mc.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp f2mc.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp f2mc.hpp ins.hpp reg.cpp diff --git a/idasdk76/module/f2mc/out.cpp b/idasdk76/module/f2mc/out.cpp new file mode 100644 index 0000000..3811b99 --- /dev/null +++ b/idasdk76/module/f2mc/out.cpp @@ -0,0 +1,358 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "f2mc.hpp" +#include <frame.hpp> +#include <segregs.hpp> + +//---------------------------------------------------------------------- +class out_f2mc_t : public outctx_t +{ + out_f2mc_t(void) = delete; // not used +public: + void out_address(ea_t ea, const op_t &x); + void out_reglist(ushort reglist); + + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_f2mc_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_f2mc_t) + +//---------------------------------------------------------------------- +void out_f2mc_t::out_address(ea_t ea, const op_t &x) +{ + if ( !out_name_expr(x, ea, x.addr & 0xffff) ) + { + out_tagon(COLOR_ERROR); + out_btoa(x.addr, 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } +} + +//---------------------------------------------------------------------- +void out_f2mc_t::out_reglist(ushort reglist) +{ + out_symbol('('); + bool first = true; + int i = 0; + while ( i < 8 ) + { + int size = 1; + if ( (reglist>>i) & 1 ) + { + while ( (i + size < 8) && ((reglist>>(i+size)) & 1 ) ) + size++; + if ( first ) + first = false; + else + out_symbol(','); + out_register(ph.reg_names[RW0+i]); + if ( size > 1 ) + { + out_symbol('-'); + out_register(ph.reg_names[RW0+i+size-1]); + } + } + i+=size; + } + out_symbol(')'); +} + +//---------------------------------------------------------------------- +bool f2mc_t::exist_bits(ea_t ea, int bitl, int bith) +{ + for ( int i = bitl; i <= bith; i++ ) + { + const char *name = find_bit(ea, i); + if ( name != NULL && name[0] != '\0' ) + return true; + } + return false; +} + +// adjust to respect 16 bits an 32 bits definitions +void f2mc_t::adjust_ea_bit(ea_t &ea, int &bit) +{ + const char *name = find_sym(ea); + if ( name != NULL && name[0] != '\0' ) + return; + name = find_sym(ea-1); + if ( name != NULL && name[0] != '\0' && exist_bits(ea-1, 8, 15) ) + { + ea--; + bit+=8; + return; + } + name = find_sym(ea-2); + if ( name != NULL && name[0] != '\0' && exist_bits(ea-2, 16, 31) ) + { + ea-=2; + bit+=16; + return; + } + name = find_sym(ea-3); + if ( name != NULL && name[0] != '\0' && exist_bits(ea-3, 16, 31) ) + { + ea-=3; + bit+=24; + return; + } +} + +//---------------------------------------------------------------------- +int calc_outf(const op_t &x) +{ + if ( x.type == o_imm ) + return OOFS_IFSIGN|OOFW_IMM; + + QASSERT(10103, x.type == o_displ); + if ( x.addr_dtyp == dt_byte ) + return OOF_ADDR|OOFS_NEEDSIGN|OOF_SIGNED|OOFW_8; + if ( x.addr_dtyp == dt_word ) + return OOF_ADDR|OOFS_NEEDSIGN|OOF_SIGNED|OOFW_16; + INTERR(10104); +} + +//---------------------------------------------------------------------- +bool out_f2mc_t::out_operand(const op_t &x) +{ + f2mc_t &pm = *static_cast<f2mc_t *>(procmod); + ea_t ea; + + if ( insn.prefix_bank && (insn.op_bank == x.n) + && (insn.prefix_bank != insn.default_bank) ) + { + out_register(ph.reg_names[insn.prefix_bank]); + out_symbol(':'); + } + + for ( int i = 0; i < x.at; i++ ) + out_symbol('@'); + + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + out_register(ph.reg_names[x.reg]); + break; + + case o_near: + case o_far: + { + ea_t addr = x.addr; + if ( x.type == o_near ) + addr = calc_code_mem(insn, addr); + out_address(addr, x); + } + break; + + case o_imm: + out_symbol('#'); + out_value(x, calc_outf(x)); + break; + + case o_mem: + { + ea = calc_data_mem(x.addr); + if ( x.addr_dtyp != 'i' ) // data address + { + if ( x.addr_dtyp ) + { + out_symbol(x.addr_dtyp); + out_symbol(':'); + } + out_address(ea, x); + if ( x.special_mode == MODE_BIT ) + { + out_symbol(':'); + out_symbol('0' + x.byte_bit); + } + } + else // IO address + { + int bit = x.byte_bit; + out_symbol('i'); out_symbol(':'); + if ( x.special_mode == MODE_BIT ) + pm.adjust_ea_bit(ea, bit); + const char *name = pm.find_sym(ea); + if ( name != NULL && name[0] != '\0' ) + { + out_addr_tag(ea); + out_line(name, COLOR_IMPNAME); + } + else + { + out_address(ea, x); + } + if ( x.special_mode == MODE_BIT ) + { + name = pm.find_bit(ea,bit); + if ( name != NULL && name[0] != '\0' ) + { + out_symbol('_'); + out_line(name, COLOR_IMPNAME); + } + else + { + out_symbol(':'); + out_tagon(COLOR_SYMBOL); + out_btoa(bit, 10); + out_tagoff(COLOR_SYMBOL); + } + } + } + } + break; + + case o_phrase: + out_register(ph.reg_names[x.reg]); + switch ( x.special_mode ) + { + case MODE_INC: + out_symbol('+'); + break; + case MODE_INDEX: + out_symbol('+'); + out_register(ph.reg_names[x.f2mc_index]); + break; + } + break; + + case o_displ: + out_register(ph.reg_names[x.reg]); + out_value(x, calc_outf(x)); + break; + + case o_reglist: + out_reglist(x.reg); + break; + + default: + error("interr: out"); + } + return 1; +} + +//---------------------------------------------------------------------- +void out_f2mc_t::out_insn(void) +{ + out_mnemonic(); + out_one_operand(0); + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + if ( insn.Op3.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(2); + } + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void f2mc_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) +{ + if ( reg == ph.reg_data_sreg ) + return; + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), value); + ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); +} + +//-------------------------------------------------------------------------- +// function to produce assume directives +//lint -esym(1764, ctx) could be made const +void f2mc_t::f2mc_assumes(outctx_t &ctx) +{ + ea_t ea = ctx.insn_ea; + segment_t *seg = getseg(ea); + if ( seg == NULL || (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 ) + return; + + for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) + { + if ( i == ph.reg_code_sreg ) + continue; + sreg_range_t sra; + if ( !get_sreg_range(&sra, ea, i) ) + continue; + sel_t now = get_sreg(ea, i); + bool seg_started = (ea == seg->start_ea); + if ( seg_started || sra.start_ea == ea ) + { + sreg_range_t prev_sra; + bool prev_exists = get_sreg_range(&prev_sra, ea - 1, i); + if ( seg_started || (prev_exists && get_sreg(prev_sra.start_ea, i) != now) ) + print_segment_register(ctx, i, now); + } + } +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Srange) could be made const +void f2mc_t::f2mc_segstart(outctx_t &ctx, segment_t *Srange) const +{ + if ( is_spec_segm(Srange->type) ) + return; + + qstring sname; + qstring sclas; + get_visible_segm_name(&sname, Srange); + get_segm_class(&sclas, Srange); + + ctx.gen_printf(DEFAULT_INDENT, + COLSTR(".section %s, %s", SCOLOR_ASMDIR), + sname.c_str(), + sclas == "CODE" ? "code" + : sclas == "BSS" ? "data" + : "const"); + if ( Srange->orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), Srange->orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +void idaapi f2mc_segend(outctx_t &, segment_t *) {} + +//-------------------------------------------------------------------------- +void f2mc_t::f2mc_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_PROC_AND_ASM, ioh.device.c_str(), ioh.deviceparams.c_str()); + ctx.gen_printf(0, ""); + ctx.gen_printf(0, COLSTR("#include <_ffmc16_a.asm>", SCOLOR_ASMDIR)); + ctx.gen_header_extra(); + ctx.gen_empty_line(); +} + +//-------------------------------------------------------------------------- +void f2mc_t::f2mc_footer(outctx_t &ctx) const +{ + qstring nbuf = get_colored_name(inf_get_start_ea()); + const char *name = nbuf.c_str(); + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), + ash.end, + ash.cmnt, + name); +} diff --git a/idasdk76/module/f2mc/reg.cpp b/idasdk76/module/f2mc/reg.cpp new file mode 100644 index 0000000..2306140 --- /dev/null +++ b/idasdk76/module/f2mc/reg.cpp @@ -0,0 +1,553 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include <ctype.h> +#include "f2mc.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +static const proctype_t ptypes[] = +{ + F2MC16L, + F2MC16LX +}; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "A", // accumulator + "AL", // accumulator + "AH", // accumulator + "PC", // program counter + "SP", // stack pointer + "R0", + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + "RW0", + "RW1", + "RW2", + "RW3", + "RW4", + "RW5", + "RW6", + "RW7", + "RL0", + "RL1", + "RL2", + "RL3", + + "PCB", // program bank register + "DTB", // data bank register + "ADB", // additional data bank register + "SSB", // system stack bank register + "USB", // user stack bank register + "CCR", // condition code register + "DPR", // direct page register + "cs","ds", // virtual registers for code and data segments + + "SPB", // stack pointer bank register + "PS", // processor status + "ILM", // interrupt level mask register + "RP" // register bank pointer +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0x66 }; // retp +static const uchar retcode_1[] = { 0x67 }; // ret +static const uchar retcode_2[] = { 0x6B }; // reti + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Fujitsu FASM +//----------------------------------------------------------------------- +static const asm_t fasm = +{ + AS_N2CHR|AS_NCMAS|ASH_HEXF3|ASD_DECF0|ASO_OCTF1|ASB_BINF3|AS_ONEDUP, + 0, + "Fujitsu FASM", + 0, + NULL, // header lines + ".org", // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".data.b", // byte directive + ".data.w", // word directive + ".data.l", // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".res.b %s", // uninited arrays + ".equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + NULL, // "public" name keyword + NULL, // "weak" name keyword + NULL, // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &fasm, NULL }; + +//-------------------------------------------------------------------------- +bool f2mc_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass) +{ + const bool split = end > start && (end - start) > 0x10000; + for ( ea_t chunk_ea = start; chunk_ea < end; chunk_ea += 0x10000 ) + { + ea_t segbase = (chunk_ea >> 16) << 12; + sel_t sel = allocate_selector(segbase); + qstring nm(name); + if ( split ) + nm.cat_sprnt("_%02X", uint32((chunk_ea >> 16) & 0xFF)); + ea_t chunk_end = chunk_ea + 0x10000; + if ( chunk_end > end ) + chunk_end = end; + add_segm(sel, chunk_ea, chunk_end, nm.c_str(), aclass); + } + return true; +} + +//------------------------------------------------------------------------- +const char *f2mc_iohandler_t::iocallback(const ioports_t &iop, const char *line) +{ + const char *ret = NULL; + bool handled = false; + int len; + ea_t ea1; + char word[MAXSTR]; + word[MAXSTR-1] = '\0'; + CASSERT(MAXSTR == 1024); + if ( qsscanf(line, "interrupt %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) //lint !e706 nominally inconsistent format + { + if ( (respect_info & IORESP_INT) != 0 ) + { + segment_t *s = getseg(ea1); + ea_t proc; + if ( s != NULL ) + { + create_dword(ea1, 4); + proc = get_dword(ea1); + if ( proc != 0xFFFFFFFF ) + { + op_plain_offset(ea1, 0, 0); + add_entry(proc, proc, word, true); + + const char *ptr = &line[len]; + ptr = skip_spaces(ptr); + if ( ptr[0] != '\0' ) + set_cmt(ea1, ptr, true); + + handled = true; + } + } + } + } + if ( !handled ) + ret = standard_callback(iop, line); + return ret; +} + +//------------------------------------------------------------------------- +void f2mc_t::load_symbols(int _respect_info) +{ + if ( cfgname != NULL ) + { + ioh.deviceparams.qclear(); + ioh.respect_info = _respect_info; + if ( !inf_like_binary() ) + ioh.respect_info &= ~2; + ioh.ports.clear(); + iohandler_t::ioports_loader_t ldr(&ioh); + read_ioports2(&ioh.ports, &ioh.device, cfgname, &ldr); + if ( ioh.respect_info ) + { + for ( int i=0; i < ioh.ports.size(); i++ ) + { + ea_t ea = ioh.ports[i].address; + create_byte(ea, 1); + const char *name = ioh.ports[i].name.c_str(); + if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) + set_cmt(ea, name, 0); + else + set_cmt(ea, ioh.ports[i].cmt.c_str(), true); + } + } + } +} + +const char *f2mc_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? port->name.c_str() : NULL; +} + +const char *f2mc_t::find_bit(ea_t address, int bit) +{ + const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit); + return b ? b->name.c_str() : NULL; +} + +//-------------------------------------------------------------------------- +void f2mc_t::f2mc_set_device_name(int _respect_info) +{ + helper.supset(-1, ioh.device.c_str()); + load_symbols(_respect_info); +} + +//------------------------------------------------------------------------- +void f2mc_t::choose_and_set_device(int flags) +{ + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) + f2mc_set_device_name(flags); +} + +//-------------------------------------------------------------------------- +inline void f2mc_t::choose_device() +{ + choose_and_set_device(IORESP_PORT|IORESP_INT); +} + +//-------------------------------------------------------------------------- +static int idaapi choose_device_cb(int, form_actions_t &fa) +{ + f2mc_t &pm = *(f2mc_t *)fa.get_ud(); + pm.choose_device(); + return 0; +} + +//-------------------------------------------------------------------------- +const char *f2mc_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + if ( keyword == NULL ) + { + static const char form[] = + "HELP\n" + "F2MC specific options\n" + "\n" + " Use macro instructions\n" + "\n" + " If this option is on, IDA will try to combine several instructions\n" + " into a macro instruction\n" + " For example,\n" + "\n" + " sbbs data:7, $1\n" + " bra $2\n" + " $1:\n" + " jmp LABEL\n" + " $2:\n" + "\n" + " will be replaced by\n" + "\n" + " sbbs16 data:7, LABEL\n" + "\n" + "ENDHELP\n" + "F2MC specific options\n" + "%*\n" + " <Use ~m~acro instructions:C>>\n" + "\n" + " <~C~hoose device name:B:0::>\n" + "\n" + "\n"; + CASSERT(sizeof(idpflags) == sizeof(ushort)); + ask_form(form, this, &idpflags, choose_device_cb); +OK: + if ( idb_loaded ) + save_idpflags(); + return IDPOPT_OK; + } + else + { + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + if ( streq(keyword, "F2MC_MACRO") ) + { + setflag(idpflags, F2MC_MACRO, *(int*)value != 0); + goto OK; + } + return IDPOPT_BADKEY; + } +} + +//---------------------------------------------------------------------- +void f2mc_t::load_from_idb() +{ + idpflags = (ushort)helper.altval(-1); + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(f2mc_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi f2mc_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_wide_high_byte_first(true); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + set_segm_name(get_first_seg(), "CODE"); + choose_and_set_device(IORESP_ALL); + for ( int i = DTB; i <= rVds; i++ ) + { + for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) + set_default_sreg_value(s, i, 0); + } + save_idpflags(); + break; + + case processor_t::ev_ending_undo: + // restore ptype + ptype = ptypes[ph.get_proc_index()]; + //fall through + case processor_t::ev_oldfile: // old file loaded + ioh.upgrade_device_index(); + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + { + ptype = ptypes[va_arg(va, int)]; + // bool keep_cfg = va_argi(va, bool); + switch ( ptype ) + { + case F2MC16L: + cfgname = "f2mc16l.cfg"; + break; + case F2MC16LX: + cfgname = "f2mc16lx.cfg"; + break; + default: + error("interr: setprc"); + } + ioh.device.qclear(); + if ( get_first_seg() != NULL ) + choose_device(); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + f2mc_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + f2mc_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + f2mc_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + f2mc_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + f2mc_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +#define FAMILY "Fujitsu F2MC:" + +static const char *const shnames[] = +{ "F2MC16L", + "F2MC16LX", + NULL +}; +static const char *const lnames[] = +{ FAMILY"Fujitsu F2MC 16L", + "Fujitsu F2MC 16LX", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_F2MC, // id + // flag + PRN_HEX + | PR_SEGS + | PR_SGROTHER, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + DTB, // first. We don't start at PCB, because + // PCB == cs, and the way to get addresses + // right is not to modify PCB, but rather + // create the segmentation correctly. + rVds, // last + 1, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + F2MC_null, + F2MC_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 0, 0, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + F2MC_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/fr/ana.cpp b/idasdk76/module/fr/ana.cpp similarity index 100% rename from idasdk75/module/fr/ana.cpp rename to idasdk76/module/fr/ana.cpp diff --git a/idasdk75/module/fr/emu.cpp b/idasdk76/module/fr/emu.cpp similarity index 100% rename from idasdk75/module/fr/emu.cpp rename to idasdk76/module/fr/emu.cpp diff --git a/idasdk75/module/fr/fr.cfg b/idasdk76/module/fr/fr.cfg similarity index 100% rename from idasdk75/module/fr/fr.cfg rename to idasdk76/module/fr/fr.cfg diff --git a/idasdk76/module/fr/fr.hpp b/idasdk76/module/fr/fr.hpp new file mode 100644 index 0000000..4989482 --- /dev/null +++ b/idasdk76/module/fr/fr.hpp @@ -0,0 +1,144 @@ + +#ifndef __FR_HPP +#define __FR_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include <frame.hpp> +#include "../iohandler.hpp" + +// uncomment this for the final release +//#define __DEBUG__ + +// FR registers +enum fr_registers +{ + // general purpose registers : + + rR0, + rR1, + rR2, + rR3, + rR4, + rR5, + rR6, + rR7, + rR8, + rR9, + rR10, + rR11, + rR12, + rR13, + rR14, + rR15, + + // coprocessor registers : + + rCR0, + rCR1, + rCR2, + rCR3, + rCR4, + rCR5, + rCR6, + rCR7, + rCR8, + rCR9, + rCR10, + rCR11, + rCR12, + rCR13, + rCR14, + rCR15, + + // dedicated registers : + + rPC, // program counter + rPS, // program status + rTBR, // table base register + rRP, // return pointer + rSSP, // system stack pointer + rUSP, // user stack pointer + rMDL, // multiplication/division register (LOW) + rMDH, // multiplication/division register (HIGH) + + // system use dedicated registers + rReserved6, + rReserved7, + rReserved8, + rReserved9, + rReserved10, + rReserved11, + rReserved12, + rReserved13, + rReserved14, + rReserved15, + + // these 2 registers are required by the IDA kernel : + + rVcs, + rVds +}; + +enum fr_phrases +{ + fIGR, // indirect general register + fIRA, // indirect relative address + fIGRP, // indirect general register with post-increment + fIGRM, // indirect general register with pre-decrement + fR13RI, // indirect displacement between R13 and a general register +}; + +// shortcut for a new operand type +#define o_reglist o_idpspec0 + +// flags for insn.auxpref +#define INSN_DELAY_SHOT 0x00000001 // postfix insn mnem by ":D" + +// flags for opt.specflag1 +#define OP_DISPL_IMM_R14 0x00000001 // @(R14, #i) +#define OP_DISPL_IMM_R15 0x00000002 // @(R15, #i) +#define OP_ADDR_R 0x00000010 // read-access to memory +#define OP_ADDR_W 0x00000012 // write-access to memory + +inline bool op_displ_imm_r14(const op_t &op) { return (op.specflag1 & OP_DISPL_IMM_R14) != 0; } +inline bool op_displ_imm_r15(const op_t &op) { return (op.specflag1 & OP_DISPL_IMM_R15) != 0; } + +// exporting our routines +int idaapi ana(insn_t *_insn); +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_sp_based(const insn_t &, const op_t &x); +int idaapi is_align_insn(ea_t ea); + +struct fr_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool print_comma = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + int choose_device(); + const ioport_t *find_sym(ea_t address); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + void fr_header(outctx_t &ctx); + + int emu(const insn_t &insn) const; + bool is_stop(const insn_t &insn) const; + + void fr_footer(outctx_t &ctx) const; + void fr_segstart(outctx_t &ctx, segment_t *Sarea) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ fr" +#define PROCMOD_NAME fr + +#endif /* __FR_HPP */ diff --git a/idasdk75/module/fr/ins.cpp b/idasdk76/module/fr/ins.cpp similarity index 100% rename from idasdk75/module/fr/ins.cpp rename to idasdk76/module/fr/ins.cpp diff --git a/idasdk75/module/fr/ins.hpp b/idasdk76/module/fr/ins.hpp similarity index 100% rename from idasdk75/module/fr/ins.hpp rename to idasdk76/module/fr/ins.hpp diff --git a/idasdk76/module/fr/makefile b/idasdk76/module/fr/makefile new file mode 100644 index 0000000..258c628 --- /dev/null +++ b/idasdk76/module/fr/makefile @@ -0,0 +1,57 @@ +PROC=fr +CONFIGS=fr.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp fr.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp fr.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + fr.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + fr.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp fr.hpp ins.hpp reg.cpp diff --git a/idasdk76/module/fr/out.cpp b/idasdk76/module/fr/out.cpp new file mode 100644 index 0000000..3b5e17a --- /dev/null +++ b/idasdk76/module/fr/out.cpp @@ -0,0 +1,298 @@ + +#include "fr.hpp" + +//---------------------------------------------------------------------- +class out_fr_t : public outctx_t +{ + out_fr_t(void) = delete; // not used +public: + void out_reg(ushort reg) { out_register(ph.reg_names[reg]); } + void out_reg(const op_t &op) { out_reg(op.reg); } + void out_imm(const op_t &op, bool no_sharp = false); + void out_addr(const op_t &op); + void out_reglist(const op_t &op); + + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); +private: + void out_reg_if_bit(ushort reg, uval_t value, int bit); +}; +CASSERT(sizeof(out_fr_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_fr_t) + +//---------------------------------------------------------------------- +// Output an operand as an immediate value +void out_fr_t::out_imm(const op_t &op, bool no_sharp) +{ + if ( !no_sharp ) + out_symbol('#'); + out_value(op, OOFW_IMM); +} + +//---------------------------------------------------------------------- +// Output an operand as an address +void out_fr_t::out_addr(const op_t &op) +{ + if ( !out_name_expr(op, to_ea(insn.cs, op.addr), op.addr) ) + out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_32); +} + +//---------------------------------------------------------------------- +void out_fr_t::out_reg_if_bit(ushort reg, uval_t value, int bit) +{ + fr_t &pm = *static_cast<fr_t *>(procmod); + if ( (value & bit) == bit ) + { + if ( pm.print_comma ) + { + out_symbol(','); + out_char(' '); + } + out_reg(reg); + pm.print_comma = true; + } +} + +void out_fr_t::out_reglist(const op_t &op) +{ + static const uint16 regs_ldm0[] = { rR7, rR6, rR5, rR4, rR3, rR2, rR1, rR0 }; + static const uint16 regs_stm0[] = { rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7 }; + static const uint16 regs_ldm1[] = { rR15, rR14, rR13, rR12, rR11, rR10, rR9, rR8 }; + static const uint16 regs_stm1[] = { rR8, rR9, rR10, rR11, rR12, rR13, rR14, rR15 }; + fr_t &pm = *static_cast<fr_t *>(procmod); + const uint16 *regs; + bool left; + + switch ( insn.itype ) + { + case fr_ldm0: regs = regs_ldm0; left = false; break; + case fr_stm0: regs = regs_stm0; left = true; break; + case fr_ldm1: regs = regs_ldm1; left = false; break; + case fr_stm1: regs = regs_stm1; left = true; break; + default: + INTERR(10018); + } + + pm.print_comma = false; + + out_symbol('('); + if ( left ) //-V614 uninitialized variable 'left' + { + for ( int i = 0, bit = 128; bit != 0; bit >>= 1, i++ ) + out_reg_if_bit(regs[i], op.value, bit); + } + else + { + for ( int i = 7, bit = 1; bit <= 128; bit <<= 1, i-- ) + out_reg_if_bit(regs[i], op.value, bit); + } + out_symbol(')'); +} + +//---------------------------------------------------------------------- +// Generate disassembly header +void fr_t::fr_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); +} + +//---------------------------------------------------------------------- +// Generate disassembly footer +void fr_t::fr_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + ctx.out_char(' '); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} + +//---------------------------------------------------------------------- +// Generate a segment header +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Sarea) could be made const +void fr_t::fr_segstart(outctx_t &ctx, segment_t *Sarea) const +{ + qstring sname; + if ( get_visible_segm_name(&sname, Sarea) <= 0 ) + return; + + const char *segname = sname.c_str(); + if ( *segname == '_' ) + segname++; + + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".section .%s", SCOLOR_ASMDIR), segname); + + ea_t orgbase = ctx.insn_ea - get_segm_para(Sarea); + + if ( orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//---------------------------------------------------------------------- +// Output an operand. +bool out_fr_t::out_operand(const op_t & op) +{ + fr_t &pm = *static_cast<fr_t *>(procmod); + switch ( op.type ) + { + case o_near: + case o_mem: + out_addr(op); + break; + + // immediate value + case o_imm: + { + const ioport_t *port = pm.find_sym(op.value); + + // this immediate is represented in the .cfg file + // output the port name instead of the numeric value + if ( port != NULL ) + out_line(port->name.c_str(), COLOR_IMPNAME); + else // otherwise, simply print the value + out_imm(op); + } + break; + + // register + case o_reg: + out_reg(op); + break; + + // phrase + case o_phrase: + out_symbol('@'); + switch ( op.specflag2 ) + { + case fIGR: // indirect general register + out_reg(op); + break; + + case fIRA: // indirect relative address + out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_32); + break; + + case fIGRP: // indirect general register with post-increment + out_reg(op); + out_symbol('+'); + break; + + case fIGRM: // indirect general register with pre-decrement + out_symbol('-'); + out_reg(op); + break; + + case fR13RI: // indirect displacement between R13 and a general register + out_symbol('('); + out_reg(rR13); + out_symbol(','); + out_char(' '); + out_reg(op); + out_symbol(')'); + break; + + default: + INTERR(10019); + } + break; + + // displacement + case o_displ: + out_symbol('@'); + out_symbol('('); + + // @(R14, #i) + if ( op_displ_imm_r14(op) ) + { + out_reg(rR14); + out_symbol(','); + out_char(' '); + out_imm(op, true); + } + // @(R15, #i) + else if ( op_displ_imm_r15(op) ) + { + out_reg(rR15); + out_symbol(','); + out_char(' '); + out_imm(op, true); + } + else + INTERR(10020); + + out_symbol(')'); + break; + + // reglist + case o_reglist: + out_reglist(op); + break; + + // void operand + case o_void: + break; + + default: + INTERR(10021); + } + return 1; +} + + +//---------------------------------------------------------------------- +void out_fr_t::out_proc_mnem(void) +{ + char postfix[5]; + postfix[0] = '\0'; + + if ( insn.auxpref & INSN_DELAY_SHOT ) + qstrncpy(postfix, ":D", sizeof(postfix)); + out_mnem(8, postfix); +} + +//---------------------------------------------------------------------- +// Output an instruction +void out_fr_t::out_insn(void) +{ + + // + // print insn mnemonic + // + out_mnemonic(); + + for ( int i=0; i < 4; i++ ) + { + if ( insn.ops[i].type != o_void ) + { + if ( i != 0 ) + { + out_symbol(','); + out_char(' '); + } + out_one_operand(i); + } + } + + // output a character representation of the immediate values + // embedded in the instruction as comments + out_immchar_cmts(); + flush_outbuf(); +} diff --git a/idasdk76/module/fr/reg.cpp b/idasdk76/module/fr/reg.cpp new file mode 100644 index 0000000..d471134 --- /dev/null +++ b/idasdk76/module/fr/reg.cpp @@ -0,0 +1,439 @@ +#include "fr.hpp" +#include <segregs.hpp> +int data_id; + +// FR registers names +static const char *const RegNames[] = +{ + // general purpose registers : + + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + + // coprocessor registers : + + "cr0", + "cr1", + "cr2", + "cr3", + "cr4", + "cr5", + "cr6", + "cr7", + "cr8", + "cr9", + "cr10", + "cr11", + "cr12", + "cr13", + "cr14", + "cr15", + + // dedicated registers : + + "pc", // program counter + "ps", // program status + "tbr", // table base register + "rp", // return pointer + "ssp", // system stack pointer + "usp", // user stack pointer + "mdl", // multiplication/division register (LOW) + "mdh", // multiplication/division register (HIGH) + + // system use dedicated registers + "reserved6", + "reserved7", + "reserved8", + "reserved9", + "reserved10", + "reserved11", + "reserved12", + "reserved13", + "reserved14", + "reserved15", + + // these 2 registers are required by the IDA kernel : + + "cs", + "ds" +}; + +int fr_t::choose_device() +{ + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( choose_ioport_device(&ioh.device, cfgfile) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); + return 0; +} + +// returns a pointer to a ioport_t object if address was found in the config file. +// otherwise, returns NULL. +const ioport_t *fr_t::find_sym(ea_t address) +{ + return find_ioport(ioh.ports, address); +} + +const char *fr_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( !choose_ioport_device(&ioh.device, cfgfile) + && ioh.device == NONEPROC ) + { + warning("No devices are defined in the configuration file %s", cfgfile); + } + else + { + ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); + } + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +void fr_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(fr_t)); + return 0; +} + +ssize_t idaapi fr_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_be(true); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + choose_device(); + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + fr_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + fr_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + fr_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + default: + break; + } + return 0; +} + +// +// GNU assembler for fujitsu FR +// + +//----------------------------------------------------------------------- +// gets a function's name +//lint -e{818} could be declared const +static bool fr_get_func_name(qstring *name, func_t *pfn) +{ + ea_t ea = pfn->start_ea; + if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 ) + return false; + + tag_addr(name, ea, true); + return true; +} + +//----------------------------------------------------------------------- +// prints function header +static void idaapi gnu_func_header(outctx_t &ctx, func_t *pfn) +{ + ctx.gen_func_header(pfn); + + qstring namebuf; + if ( fr_get_func_name(&namebuf, pfn) ) + { + const char *name = namebuf.begin(); + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".type %s, @function", SCOLOR_ASMDIR), name); + ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name); + ctx.ctxflags |= CTXF_LABEL_OK; + } +} + +//----------------------------------------------------------------------- +// prints function footer +static void idaapi gnu_func_footer(outctx_t &ctx, func_t *pfn) +{ + qstring namebuf; + if ( fr_get_func_name(&namebuf, pfn) ) + { + const char *name = namebuf.begin(); + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".size %s, .-%s", SCOLOR_ASMDIR), name, name); + } +} + +//----------------------------------------------------------------------- +static const asm_t gnu_asm = +{ + AS_COLON + |ASH_HEXF3 // hex 0x123 format + |ASB_BINF0 // bin 0110b format + |ASO_OCTF1 // oct 012345 format + // don't display the final 0 in string declarations + |/*AS_1TEXT |*/ AS_NCMAS, + 0, + "GNU Assembler for the Fujitsu FR Family", + 0, + NULL, // no headers + ".org", // origin directive + NULL, // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + ".ascii", // ascii string directive + ".byte", // byte directive + ".word", // word directive + ".long", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + gnu_func_header, // func_header + gnu_func_footer, // func_footer + ".globl", // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + ".align", // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +// +// Supported assemblers : +// + +static const asm_t *const asms[] = { &gnu_asm, NULL }; + +// +// Short and long name for our module +// +#define FAMILY "Fujitsu FR 32-Bit Family:" + +static const char *const shnames[] = +{ + "fr", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Fujitsu FR 32-Bit Family", + NULL +}; + +static const uchar retcode_1[] = { 0x97, 0x20 }; // ret +static const uchar retcode_2[] = { 0x9F, 0x20 }; // ret with delay shot +static const uchar retcode_3[] = { 0x9F, 0x30 }; // reti + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } // NULL terminated array +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_FR, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_USE32 // supports 32-bit addressing + | PR_DEFSEG32 // segments are 32-bit by default + | PR_BINMEM, // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs, rVds, + 0, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + 0, fr_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + fr_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/h8/ana.cpp b/idasdk76/module/h8/ana.cpp similarity index 100% rename from idasdk75/module/h8/ana.cpp rename to idasdk76/module/h8/ana.cpp diff --git a/idasdk75/module/h8/emu.cpp b/idasdk76/module/h8/emu.cpp similarity index 100% rename from idasdk75/module/h8/emu.cpp rename to idasdk76/module/h8/emu.cpp diff --git a/idasdk75/module/h8/h8.cfg b/idasdk76/module/h8/h8.cfg similarity index 100% rename from idasdk75/module/h8/h8.cfg rename to idasdk76/module/h8/h8.cfg diff --git a/idasdk76/module/h8/h8.hpp b/idasdk76/module/h8/h8.hpp new file mode 100644 index 0000000..6f40fd8 --- /dev/null +++ b/idasdk76/module/h8/h8.hpp @@ -0,0 +1,305 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _H8_HPP +#define _H8_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + +#define PROCMOD_NAME h8 +#define PROCMOD_NODE_NAME "$ h8" + +//------------------------------------------------------------------ +// processor types + +typedef uint16 proctype_t; + +static const proctype_t none = 0; +static const proctype_t P300 = 0x0001; // H8/300, H8/300H +static const proctype_t P2000 = 0x0002; // H8S/2000 +static const proctype_t P2600 = 0x0004; // H8S/2600 +static const proctype_t PSX = 0x0008; // H8SX + +// assume 'Normal mode' as the default +static const proctype_t MODE_MASK= 0xF000; +static const proctype_t MODE_MID = 0x1000; // H8SX +static const proctype_t MODE_ADV = 0x2000; // H8/300H (!), H8S, H8SX +static const proctype_t MODE_MAX = 0x3000; // H8SX + +// submodel +static const proctype_t SUBM_MASK= 0x0F00; +static const proctype_t SUBM_TINY= 0x0100; // H8/300H Tiny model + // full insn set and normal mode + +static const proctype_t P30A = P300 | MODE_ADV; +static const proctype_t P26A = P2600 | MODE_ADV; + +//------------------------------------------------------------------ +#ifdef _MSC_VER +#define ENUM8BIT : uint8 +#else +#define ENUM8BIT +#endif +enum regnum_t ENUM8BIT +{ + R0, R1, R2, R3, R4, R5, R6, R7, SP=R7, + E0, E1, E2, E3, E4, E5, E6, E7, + R0H, R1H, R2H, R3H, R4H, R5H, R6H, R7H, + R0L, R1L, R2L, R3L, R4L, R5L, R6L, R7L, + ER0, ER1, ER2, ER3, ER4, ER5, ER6, ER7, + // don't change registers order above this line + MACL, MACH, + PC, + CCR, EXR, + rVcs, rVds, // virtual registers for code and data segments + VBR, SBR, // base or segment registers +}; + +//--------------------------------- +// Operand types: + +/* +o_reg 1 Register direct + Rn + x.reg +o_phrase 2 Register indirect + @ERn + x.phrase contains register number + x.phtype contains phrase type (normal, post, pre) +o_displ 3 Register indirect with displacement + @(d:2,ERn)/@(d:16,ERn)/@(d:32,ERn) + x.reg, x.addr, disp_16, disp_32, disp_2 +o_displ 4 Index register indirect with displacement + @(d:16, RnL.B)/@(d:16,Rn.W)/@(d:16,ERn.L) + @(d:32, RnL.B)/@(d:32,Rn.W)/@(d:32,ERn.L) + x.displtype = dt_regidx, + x.reg, + x.addr - disp_16, disp_32, idx_byte/word/long +o_phrase 5 Register indirect with post-inc/pre-dec/pre-inc/post-dec + @ERn+/@-ERn/@+ERn/@ERn- +o_mem 6 Absolute address + @aa:8/@aa:16/@aa:24/@aa:32 + x.memtype = @aa:8 ? mem_sbr : mem_direct + x.addr +o_imm 7 Immediate + #x:2/#xx:3/#xx:4/#xx:5/#xx:8/#xx:16/#xx:32 + #1/#2/#4/#8/#16 + x.value +o_near 8 Program-counter relative + @(d:8,PC)/@(d:16,PC) +o_pcidx 9 Program-counter relative with index register + @(RnL.B,PC)/@(Rn.W,PC)/@(ERn.L,PC) + x.reg +o_mem 10 Memory indirect + @@aa:8 + x.memtype = mem_ind + x.addr +o_mem 11 Extended memory indirect + @@vec:7 + x.memtype = mem_vec7 + x.addr +o_reglist Register list + x.reg, x.nregs +o_displ first operand of MOVA insn + @(d16,<EA>.[BW])/@(d32:<EA>.[BW]) + x.displtype = dt_movaop1, + x.addr, + x.szfl - disp_16/disp_32/idx_byte/idx_word + x.idxt - <EA> type + <EA> type: + o_reg - x.reg EQ to o_regidx + o_phrase - x.phrase,x.idxdt + o_displ - x.reg,x.value,x.idxsz,x.idxdt + o_regidx - x.reg,x.value,x.idxsz,x.idxdt + o_mem - x.value,x.idsz,x.idxdt +*/ + +#define o_reglist o_idpspec0 +#define o_pcidx o_idpspec1 + +#define phtype specflag1 // phrase type: +const int ph_normal = 0; // just simple indirection +const int ph_pre_dec = 0x10; // -@Rn ^ 3 -> @Rn+ +const int ph_post_inc = 0x13; // @Rn+ +const int ph_pre_inc = 0x11; // +@ERn +const int ph_post_dec = 0x12; // @ERn- + +#define displtype specflag1 // displ type: +const int dt_normal = 0; // Register indirect with displacement +const int dt_regidx = 1; // Index register indirect with displacement +const int dt_movaop1 = 2; // first operand of MOVA insn + +#define szfl specflag2 // various operand size flags + // index target +const int idx_byte = 0x01; // .b +const int idx_word = 0x02; // .w +const int idx_long = 0x04; // .l + // size of operand displ +const int disp_16 = 0x10; // 16bit displacement +const int disp_24 = 0x20; // 24bit displacement +const int disp_32 = 0x40; // 32bit displacement +const int disp_2 = 0x80; // 2bit displacement + +#define memtype specflag1 // mem type: +const int mem_direct = 0; // x.addr - direct memory ref +const int mem_sbr = 1; // SBR based @aa:8 +const int mem_vec7 = 2; // @@vec:7 +const int mem_ind = 3; // @@aa:8 + +#define nregs specflag1 // o_reglist: number of registers + +// MOVA Op1 store +#define idxt specflag3 // MOVA: optype_t of index +#define idxsz specflag4 // MOVA: size of index +#define idxdt specval // MOVA: index phtype,displtype,memtype + +//------------------------------------------------------------------ +const uint16 aux_none = 0; // no postfix +const uint16 aux_byte = 1; // .b postfix +const uint16 aux_word = 2; // .w postfix +const uint16 aux_long = 3; // .l postfix + +//------------------------------------------------------------------ +#define UAS_HEW 0x0001 // HEW assembler + +//------------------------------------------------------------------ +ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea +ea_t calc_mem_sbr_based(const insn_t &insn, ea_t ea); // map virtual @aa:8 physical ea + +void idaapi h8_segend(outctx_t &ctx, segment_t *seg); + +int idaapi h8_is_align_insn(ea_t ea); +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_sp_based(const insn_t &insn, const op_t &x); +bool idaapi is_return_insn(const insn_t &insn); + +int is_jump_func(const func_t *pfn, ea_t *jump_target); +int may_be_func(const insn_t &insn); // can a function start here? +int is_sane_insn(const insn_t &insn, int nocrefs); +bool idaapi h8_is_switch(switch_info_t *si, const insn_t &insn); + +//------------------------------------------------------------------ +struct h8_iohandler_t : public iohandler_t +{ + h8_iohandler_t(netnode &nn) : iohandler_t(nn) {} + virtual void get_cfg_filename(char *buf, size_t bufsize) override; +}; + +struct h8_t : public procmod_t +{ + netnode helper; + h8_iohandler_t ioh = h8_iohandler_t(helper); + proctype_t ptype = none; // contains all bits which correspond + // to the supported processors set + char show_sizer = -1; + uchar code = 0; + uchar code3 = 0; + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + inline bool advanced(void) { return (ptype & MODE_MASK) != 0; } + inline bool is_h8s(void) { return (ptype & (P2000|P2600)) != 0; } + inline bool is_h8sx(void) { return (ptype & PSX) != 0; } + inline bool is_tiny(void) { return (ptype & SUBM_TINY) != 0; } + + inline regnum_t r0(void) { return advanced() ? ER0 : R0; } + + inline bool is_hew_asm(void) const + { + return (ash.uflag & UAS_HEW) != 0; + } + + void load_symbols(void); + const char *find_sym(ea_t address); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + void set_cpu(int cpuno); + int get_displ_outf(const op_t &x, flags_t F); + ea_t trim_ea_branch(ea_t ea) const; // trim address according to proc mode + void h8_header(outctx_t &ctx); + void trimaddr(op_t &x); + void opatHL(op_t &x, op_dtype_t dtyp); + void opdsp16(insn_t &insn, op_t &x, op_dtype_t dtyp); + void opdsp32(insn_t &insn, op_t &x, op_dtype_t dtyp); + bool read_operand(insn_t &insn, op_t &x, ushort flags); + bool map014(insn_t &insn); + bool map4(insn_t &insn); + int ana(insn_t *pinsn); + int exit_40(insn_t &insn); + int exit_54_56(insn_t &insn, uint8 rts, uint8 rtsl); + int exit_59_5D(insn_t &insn, uint16 jump, uint16 branch); + int exit_7B(insn_t &insn); + int h8sx_03(insn_t &insn); + int h8sx_0A(insn_t &insn); + int h8sx_1A(insn_t &insn); + int h8sx_6A(insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + int h8sx_6B(insn_t &insn); + int h8sx_78(insn_t &insn); + int h8sx_79(insn_t &insn); + int h8sx_7A(insn_t &insn); + bool h8sx_010D(insn_t &insn); + bool h8sx_010E(insn_t &insn); + bool insn_ldc(insn_t &insn, uint8 byte2, regnum_t reg); + bool h8sx_01_exr(insn_t &insn); + bool insn_mova(insn_t &insn); + int insn_mova_reg(insn_t &insn, uint8 opcode, uint8 rs, bool is_reg_equal); + bool h8sx_01_other(insn_t &insn); + bool insn_addx_imm(insn_t &insn, op_t &x, uint8 byte2, uint8 byte3, uint16 mask, bool check_byte3); + bool insn_bra(insn_t &insn, uint8 byte2, uint8 byte3); + bool insn_bfld_bfst(insn_t &insn, uint8 byte2, uint8 byte3, bool is_bfld); + bool use_leaf_map(insn_t &insn, const struct map_t *m, uint8 idx); + bool op_from_byte(insn_t &insn, op_t &x, uint8 byte2); + bool read_1st_op(insn_t &insn, uint8 byte2, uint8 byte3_hiNi); + bool op_phrase(const insn_t &insn, op_t &x, uint8 reg, int pht, op_dtype_t dtype=dt_byte); + bool op_displ_regidx(insn_t &insn, op_t &x, uint8 selector, bool is_32, uint8 reg); + int emu(const insn_t &insn); + int h8_get_frame_retsize(const func_t *); + int h8sx_7C(insn_t &insn); + int h8sx_7D(insn_t &insn); + bool h8sx_010_01dd(insn_t &insn, uint16 postfix); + bool h8sx_ldm(insn_t &insn); + bool insn_mac(insn_t &insn); + bool insn_tas(insn_t &insn); + bool op_phrase_prepost(const insn_t &insn, op_t &x, uint8 reg, uint8 selector); + bool op_phrase_displ2(const insn_t &insn, op_t &x, uint8 reg, uint8 displ); + int h8sx_01(insn_t &insn); + bool h8sx_010_00dd(insn_t &insn); + int h8sx_7E(insn_t &insn); + int h8sx_7F(insn_t &insn); + int unpack_8bit_shift(const map_t *m, insn_t &insn, uint16 itype, uint16 itype2); + int h8sx_10(insn_t &insn); + int h8sx_11(insn_t &insn); + bool h8sx_0108(insn_t &insn); + bool h8sx_0109_010A(insn_t &insn,op_t ®op, op_t &genop); + int h8sx_0F(insn_t &insn); + int h8sx_1F(insn_t &insn); + void add_code_xref(const insn_t &insn, const op_t &x, ea_t ea); + + void h8_assumes(outctx_t &ctx); + void trace_sp(const insn_t &insn) const; + bool get_op_value(uval_t *value, const insn_t &_insn, const op_t &x) const; + bool spoils(const insn_t &insn, int reg) const; + void check_base_reg_change_value(const insn_t &insn) const; + void h8_segstart(outctx_t &ctx, segment_t *Srange) const; + void h8_gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; + void h8_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; + +#endif // _H8_HPP diff --git a/idasdk75/module/h8/ins.cpp b/idasdk76/module/h8/ins.cpp similarity index 100% rename from idasdk75/module/h8/ins.cpp rename to idasdk76/module/h8/ins.cpp diff --git a/idasdk76/module/h8/ins.hpp b/idasdk76/module/h8/ins.hpp new file mode 100644 index 0000000..29b5f68 --- /dev/null +++ b/idasdk76/module/h8/ins.hpp @@ -0,0 +1,137 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + +H8_null = 0, // Unknown Operation + +H8_add, // Add binary +H8_adds, // Add with sign extension +H8_addx, // Add with extend carry +H8_and, // Logical AND +H8_andc, // Logical AND with control register +H8_band, // Bit AND +H8_bra, // Branch always +H8_brn, // Branch never +H8_bhi, // Branch if higher +H8_bls, // Branch if lower or same +H8_bcc, // Branch if carry clear (higher or same) +H8_bcs, // Branch if carry set (lower) +H8_bne, // Branch if not equal +H8_beq, // Branch if equal +H8_bvc, // Branch if overflow clear +H8_bvs, // Branch if overflow set +H8_bpl, // Branch if plus +H8_bmi, // Branch if minus +H8_bge, // Branch if greates or equal +H8_blt, // Branch if less +H8_bgt, // Branch if greater +H8_ble, // Branch if less or equal +H8_bclr, // Bit clear +H8_biand, // Bit invert AND +H8_bild, // Bit invert load +H8_bior, // Bit invert OR +H8_bist, // Bit invert store +H8_bixor, // Bit invert XOR +H8_bld, // Bit load +H8_bnot, // Bit NOT +H8_bor, // Bit OR +H8_bset, // Bit set +H8_bsr, // Branch to subroutine +H8_bst, // Bit store +H8_btst, // Bit test +H8_bxor, // Bit XOR +H8_clrmac, // Clear MAC register +H8_cmp, // Compare +H8_daa, // Decimal adjust add +H8_das, // Decimal adjust subtract +H8_dec, // Decrement +H8_divxs, // Divide extended as signed +H8_divxu, // Divide extended as unsigned +H8_eepmov, // Move data to EEPROM +H8_exts, // Extend as signed +H8_extu, // Extend as unsigned +H8_inc, // Increment +H8_jmp, // Jump +H8_jsr, // Jump to subroutine +H8_ldc, // Load to control register +H8_ldm, // Load to multiple registers +H8_ldmac, // Load to MAC register +H8_mac, // Multiply and accumulate +H8_mov, // Move data +H8_movfpe, // Move from peripheral with E clock +H8_movtpe, // Move to peripheral with E clock +H8_mulxs, // Multiply extend as signed +H8_mulxu, // Multiply extend as unsigned +H8_neg, // Negate +H8_nop, // No operation +H8_not, // Logical complement +H8_or, // Logical OR +H8_orc, // Logical OR with control register +H8_pop, // Pop data from stack +H8_push, // Push data on stack +H8_rotl, // Rotate left +H8_rotr, // Rotate right +H8_rotxl, // Rotate with extend carry left +H8_rotxr, // Rotate with extend carry right +H8_rte, // Return from exception +H8_rts, // Return from subroutine +H8_shal, // Shift arithmetic left +H8_shar, // Shift arithmetic right +H8_shll, // Shift logical left +H8_shlr, // Shift logical right +H8_sleep, // Power down mode +H8_stc, // Store from control register +H8_stm, // Store from multiple registers +H8_stmac, // Store from MAC register +H8_sub, // Subtract binary +H8_subs, // Subtract with sign extension +H8_subx, // Subtract with extend carry +H8_tas, // Test and set +H8_trapa, // Trap always +H8_xor, // Logical XOR +H8_xorc, // Logical XOR with control register + +// H8SX +H8_rtel, // Returns from an exception, restoring data to multiple general registers +H8_rtsl, // Returns from a subroutine, restoring data to multiple general registers +H8_movmd, // Transfers a data block +H8_movsd, // Transfers a data block with zero detection +H8_bras, // Branch always after the next instruction (delay slot) +H8_movab, // MOVe effective Address/B +H8_movaw, // MOVe effective Address/W +H8_moval, // MOVe effective Address/L +H8_bsetne, // Bit SET if Not Equal +H8_bseteq, // Bit SET if EQual +H8_bclrne, // Bit CLeaR if Not Equal +H8_bclreq, // Bit CLeaR if Equal +H8_bstz, // Bit STore Zero flag +H8_bistz, // Bit Invert STore Zero flag +H8_bfld, // Bit Field LoaD +H8_bfst, // Bit Field STore +H8_muls, // MULtiply as Signed +H8_divs, // DIVide as Signed +H8_mulu, // MULtiply as Unsigned +H8_divu, // DIVide as Unsigned +H8_mulsu, // MULtiply as Signed +H8_muluu, // MULtiply as Unsigned +H8_brabc, // BRAnch if Bit Cleared +H8_brabs, // BRAnch if Bit Set +H8_bsrbc, // Branch to SubRoutine if Bit Cleared +H8_bsrbs, // Branch to SubRoutine if Bit Set + +H8_last, + +}; + +#endif diff --git a/idasdk76/module/h8/makefile b/idasdk76/module/h8/makefile new file mode 100644 index 0000000..77513bf --- /dev/null +++ b/idasdk76/module/h8/makefile @@ -0,0 +1,57 @@ +PROC=h8 +CONFIGS=h8.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp h8.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)jumptable.hpp \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp h8.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + h8.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp h8.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp h8.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/h8/out.cpp b/idasdk76/module/h8/out.cpp similarity index 100% rename from idasdk75/module/h8/out.cpp rename to idasdk76/module/h8/out.cpp diff --git a/idasdk76/module/h8/reg.cpp b/idasdk76/module/h8/reg.cpp new file mode 100644 index 0000000..ce7bf70 --- /dev/null +++ b/idasdk76/module/h8/reg.cpp @@ -0,0 +1,588 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@datarescue.com + * + */ + +#include "h8.hpp" +#include <diskio.hpp> +#include <frame.hpp> +#include <segregs.hpp> + +#include <ieee.h> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", + "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", + "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", + "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7", + "macl", "mach", + "pc", + "ccr", "exr", + "cs","ds", // virtual registers for code and data segments + "vbr", "sbr", +}; + +//-------------------------------------------------------------------------- +static const char *const register_names_sp_er7[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "sp", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", + "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", + "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", + "er0", "er1", "er2", "er3", "er4", "er5", "er6", "er7", + "macl", "mach", + "pc", + "ccr", "exr", + "cs","ds", // virtual registers for code and data segments + "vbr", "sbr", +}; + +//-------------------------------------------------------------------------- +static const char *const register_names_r7_sp[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", + "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", + "r0h", "r1h", "r2h", "r3h", "r4h", "r5h", "r6h", "r7h", + "r0l", "r1l", "r2l", "r3l", "r4l", "r5l", "r6l", "r7l", + "er0", "er1", "er2", "er3", "er4", "er5", "er6", "sp", + "macl", "mach", + "pc", + "ccr", "exr", + "cs","ds", // virtual registers for code and data segments + "vbr", "sbr", +}; + +//-------------------------------------------------------------------------- +static const uchar startcode_0[] = { 0x01, 0x00, 0x6D, 0xF3 }; // push.l er3 +static const uchar startcode_1[] = { 0x6D, 0xF3 }; // push.w r3 + +static const bytes_t startcodes[] = +{ + { sizeof(startcode_0), startcode_0 }, + { sizeof(startcode_1), startcode_1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gas = +{ + AS_ASCIIC|AS_ALIGN2|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, + 0, + "GNU assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + ";", // comment string + '"', // string delimiter + '"', // char delimiter + "\"", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".byte", // byte directive + ".word", // word directive + ".long", // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + NULL, // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".globl", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof_fmt + 0, // flag2 + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt + NULL, // a_vstruc_fmt + NULL, // a_rva + NULL, // a_yword +}; + +//----------------------------------------------------------------------- +// HEW ASM +//----------------------------------------------------------------------- +const asm_t hew = +{ + AS_ASCIIC|AS_ALIGN2|ASH_HEXF1|ASD_DECF0|ASO_OCTF7|ASB_BINF4|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, + UAS_HEW, + "HEW assembler", + 0, + NULL, // header lines + ".org", // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '"', // char delimiter + "\"", // special symbols in char and string constants + + ".sdata", // ascii string directive + ".data.b", // byte directive + ".data.w", // word directive + ".data.l", // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".res %s", // uninited arrays + ": .assign", // equ that allows set/reset values +//": .equ", // equ (does not allow for reuse) +//": .reg (%s)",// equ for regs (does not allow for reuse) +//": .bequ", // equ for bits (does not allow for reuse) + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".global", // "extrn" name keyword + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "~", // xor + "~", // not + "<<", // shl + ">>", // shr + "sizeof", // sizeof_fmt + 0, // flag2 + NULL, // cmnt2 + "low", // low8 + "high", // high8 + "lword", // low16 + "hword", // high16 + ".include \"%s\"", // a_include_fmt + NULL, // a_vstruc_fmt + NULL, // a_rva + NULL, // a_yword +}; + +static const asm_t *const asms[] = { &gas, &hew, NULL }; + +//-------------------------------------------------------------------------- +static const char cfgname[] = "h8.cfg"; + +void h8_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) +{ + qstrncpy(buf, cfgname, bufsize); +} + +//-------------------------------------------------------------------------- +const char *h8_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? port->name.c_str() : NULL; +} + +//------------------------------------------------------------------------- +void h8_t::load_from_idb() +{ + ioh.restore_device(); +} + +//-------------------------------------------------------------------------- +const char *h8_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + if ( choose_ioport_device(&ioh.device, cfgname) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); + return IDPOPT_OK; +} + +//-------------------------------------------------------------------------- +static const proctype_t ptypes[] = +{ + P300, // h8300 + P300 | MODE_ADV, // h8300a + P300 | P2000 | P2600, // h8s300 + P300 | MODE_ADV | P2000 | P2600, // h8s300a + P300 | P2000 | P2600 | PSX, // h8sxn + P300 | MODE_MID | P2000 | P2600 | PSX, // h8sxm + P300 | MODE_ADV | P2000 | P2600 | PSX, // h8sxa + P300 | MODE_MAX | P2000 | P2600 | PSX, // h8sx + P300 | MODE_ADV | SUBM_TINY, // h8368 +}; + +//-------------------------------------------------------------------------- +void h8_t::set_cpu(int cpuno) +{ + ptype = ptypes[cpuno]; + // bool keep_cfg = va_argi(va, bool); + if ( advanced() && !is_tiny() ) + { + ph.flag |= PR_DEFSEG32; + } + if ( is_h8sx() ) + { + ph.flag |= PR_SEGS; + ph.reg_last_sreg = SBR; + ph.segreg_size = 4; + } +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(h8_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi h8_t::on_event(ssize_t msgid, va_list va) +{ + int ret = 0; + switch ( msgid ) + { + case processor_t::ev_init: +// __emit__(0xCC); // debugger trap + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newasm: // new assembler type selected + { + int asmnum = va_arg(va, int); + bool hew_asm = asmnum == 1; + if ( advanced() ) + ph.reg_names = hew_asm ? register_names : register_names_r7_sp; + else + ph.reg_names = hew_asm ? register_names : register_names_sp_er7; + } + break; + + case processor_t::ev_newfile: // new file loaded + if ( choose_ioport_device(&ioh.device, cfgname) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); + if ( is_h8sx() ) + { + set_default_sreg_value(NULL, VBR, 0); + set_default_sreg_value(NULL, SBR, 0xFFFFFF00); + } + break; + + case processor_t::ev_ending_undo: + // restore ptype + set_cpu(ph.get_proc_index()); + //fall through + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + set_cpu(va_arg(va, int)); + break; + + case processor_t::ev_creating_segm: // new segment + break; + + case processor_t::ev_is_jump_func: + { + const func_t *pfn = va_arg(va, const func_t *); + ea_t *jump_target = va_arg(va, ea_t *); + ret = is_jump_func(pfn, jump_target); + } + break; + + case processor_t::ev_is_sane_insn: + { + const insn_t &insn = *va_arg(va, insn_t *); + int no_crefs = va_arg(va, int); + ret = is_sane_insn(insn, no_crefs) == 1 ? 1 : -1; + } + break; + + case processor_t::ev_may_be_func: + // can a function start here? + // arg: none, the instruction is in 'cmd' + // returns: probability 0..100 + // 'cmd' structure is filled upon the entrace + // the idp module is allowed to modify 'cmd' + { + const insn_t &insn = *va_arg(va, insn_t *); + ret = may_be_func(insn); + } + break; + + case processor_t::ev_gen_regvar_def: + { + outctx_t *ctx = va_arg(va, outctx_t *); + regvar_t *v = va_arg(va, regvar_t*); + if ( is_hew_asm() ) + { + ctx->gen_printf(0, + COLSTR("%s", SCOLOR_REG) + COLSTR(": .reg (", SCOLOR_SYMBOL) + COLSTR("%s", SCOLOR_REG) + COLSTR(")", SCOLOR_SYMBOL), + v->user, v->canon); + ret = 1; + } + } + break; + + case processor_t::ev_is_ret_insn: + { + const insn_t &insn = *va_arg(va, insn_t *); + ret = is_return_insn(insn) ? 1 : -1; + } + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + h8_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + h8_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + h8_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + h8_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + h8_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_is_switch: + { + switch_info_t *si = va_arg(va, switch_info_t *); + const insn_t *insn = va_arg(va, const insn_t *); + return h8_is_switch(si, *insn) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = h8_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_gen_stkvar_def: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const member_t *mptr = va_arg(va, const member_t *); + sval_t v = va_arg(va, sval_t); + h8_gen_stkvar_def(*ctx, mptr, v); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *retstr = set_idp_options(keyword, value_type, value, idb_loaded); + if ( retstr == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = retstr; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return h8_is_align_insn(ea); + } + + + default: + break; + } + return ret; +} + +//----------------------------------------------------------------------- +#define FAMILY "Hitachi H8:" +static const char *const shnames[] = +{ + "h8300", "h8300a", "h8s300", "h8s300a", + "h8sxn", "h8sxm", "h8sxa", "h8sx", "h8368", NULL +}; +static const char *const lnames[] = +{ + FAMILY"Hitachi H8/300H normal", + "Hitachi H8/300H advanced", + "Hitachi H8S normal", + "Hitachi H8S advanced", + "Hitachi H8SX normal", + "Hitachi H8SX middle", + "Hitachi H8SX advanced", + "Hitachi H8SX maximum", + "Renesas H8/3687 Group", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_H8, // id + // flag + PRN_HEX + | PR_USE32 + | PR_WORD_INS, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + rVcs, // first + rVds, // last + 0, // size of a segment register + rVcs, rVds, + + startcodes, // start sequences + NULL, // see is_ret_insn callback in the notify() function + + H8_null, + H8_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + H8_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/h8500/ana.cpp b/idasdk76/module/h8500/ana.cpp new file mode 100644 index 0000000..78c3bb8 --- /dev/null +++ b/idasdk76/module/h8500/ana.cpp @@ -0,0 +1,650 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Hitchi H8 + * + */ + +#include "h8500.hpp" + +//-------------------------------------------------------------------------- +#define MAP3 ushort(-3) +#define MAP4 ushort(-4) +#define MAP5 ushort(-5) +#define MAP6 ushort(-6) + +static const ushort A2[] = +{ +/* 00 */ H8500_nop, MAP6, H8500_ldm, H8500_pjsr, MAP5, MAP4, MAP6, MAP6, +/* 08 */ H8500_trapa, H8500_trap_vs, H8500_rte, H8500_bpt, MAP5, MAP4, H8500_bsr, H8500_unlk, +/* 10 */ H8500_jmp, MAP6, H8500_stm, H8500_pjmp, H8500_rtd, MAP4, H8500_null, H8500_link, +/* 18 */ H8500_jsr, H8500_rts, H8500_sleep, H8500_null, H8500_rtd, MAP4, H8500_bsr, H8500_link, +/* 20 */ H8500_bra, H8500_brn, H8500_bhi, H8500_bls, H8500_bcc, H8500_bcs, H8500_bne, H8500_beq, +/* 28 */ H8500_bvc, H8500_bvs, H8500_bpl, H8500_bmi, H8500_bge, H8500_blt, H8500_bgt, H8500_ble, +/* 30 */ H8500_bra, H8500_brn, H8500_bhi, H8500_bls, H8500_bcc, H8500_bcs, H8500_bne, H8500_beq, +/* 38 */ H8500_bvc, H8500_bvs, H8500_bpl, H8500_bmi, H8500_bge, H8500_blt, H8500_bgt, H8500_ble, +/* 40 */ H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, H8500_cmp_e, +/* 48 */ H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, H8500_cmp_i, +/* 50 */ H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, H8500_mov_e, +/* 58 */ H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, H8500_mov_i, +}; + +static const ushort A2tail[] = +{ +/* 60 */ H8500_mov_l, +/* 70 */ H8500_mov_s, +/* 80 */ H8500_mov_f, +/* 90 */ H8500_mov_f, +/* A0 */ MAP3, +/* B0 */ MAP4, +/* C0 */ MAP4, +/* D0 */ MAP4, +/* E0 */ MAP4, +/* F0 */ MAP4, +}; + +static const ushort A3[] = +{ +/* 00 */ MAP6, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +/* 08 */ H8500_add_q, H8500_add_q, H8500_null, H8500_null, H8500_add_q, H8500_add_q, H8500_null, H8500_null, +/* 10 */ H8500_swap, H8500_exts, H8500_extu, H8500_clr, H8500_neg, H8500_not, H8500_tst, H8500_tas, +/* 18 */ H8500_shal, H8500_shar, H8500_shll, H8500_shlr, H8500_rotl, H8500_rotr, H8500_rotxl, H8500_rotxr, +}; + +static const ushort A3tail[] = +{ +/* 20 */ H8500_add_g, H8500_adds, +/* 30 */ H8500_sub, H8500_subs, +/* 40 */ H8500_or, H8500_bset, +/* 50 */ H8500_and, H8500_bclr, +/* 60 */ H8500_xor, H8500_bnot, +/* 70 */ H8500_cmp_g, H8500_btst, +/* 80 */ H8500_mov_g, H8500_ldc, +/* 90 */ H8500_xch, H8500_stc, +/* A0 */ H8500_addx, H8500_mulxu, +/* B0 */ H8500_subx, H8500_divxu, +/* C0 */ H8500_bset, H8500_bset, +/* D0 */ H8500_bclr, H8500_bclr, +/* E0 */ H8500_bnot, H8500_bnot, +/* F0 */ H8500_btst, H8500_btst, +}; + +static const ushort A4[] = +{ +/* 00 */ MAP6, H8500_null, H8500_null, H8500_null, H8500_cmp_g, H8500_cmp_g, H8500_mov_g, H8500_mov_g, +/* 08 */ H8500_add_q, H8500_add_q, H8500_null, H8500_null, H8500_add_q, H8500_add_q, H8500_null, H8500_null, +/* 10 */ H8500_null, H8500_null, H8500_null, H8500_clr, H8500_neg, H8500_not, H8500_tst, H8500_tas, +/* 18 */ H8500_shal, H8500_shar, H8500_shll, H8500_shlr, H8500_rotl, H8500_rotr, H8500_rotxl, H8500_rotxr, +}; + +static const ushort A4tail[] = +{ +/* 20 */ H8500_add_g, H8500_adds, +/* 30 */ H8500_sub, H8500_subs, +/* 40 */ H8500_or, H8500_bset, +/* 50 */ H8500_and, H8500_bclr, +/* 60 */ H8500_xor, H8500_bnot, +/* 70 */ H8500_cmp_g, H8500_btst, +/* 80 */ H8500_mov_g, H8500_ldc, +/* 90 */ H8500_mov_g, H8500_stc, +/* A0 */ H8500_addx, H8500_mulxu, +/* B0 */ H8500_subx, H8500_divxu, +/* C0 */ H8500_bset, H8500_bset, +/* D0 */ H8500_bclr, H8500_bclr, +/* E0 */ H8500_bnot, H8500_bnot, +/* F0 */ H8500_btst, H8500_btst, +}; + +static const ushort A5[] = +{ +/* 00 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +/* 08 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +/* 10 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +/* 18 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +}; + +static const ushort A5tail[] = +{ +/* 20 */ H8500_add_g, H8500_adds, +/* 30 */ H8500_sub, H8500_subs, +/* 40 */ H8500_or, H8500_orc, +/* 50 */ H8500_and, H8500_andc, +/* 60 */ H8500_xor, H8500_xorc, +/* 70 */ H8500_cmp_g, H8500_null, +/* 80 */ H8500_mov_g, H8500_ldc, +/* 90 */ H8500_null, H8500_null, +/* A0 */ H8500_addx, H8500_mulxu, +/* B0 */ H8500_subx, H8500_divxu, +/* C0 */ H8500_null, H8500_null, +/* D0 */ H8500_null, H8500_null, +/* E0 */ H8500_null, H8500_null, +/* F0 */ H8500_null, H8500_null, +}; + +static const ushort A6[] = +{ +/* 00 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +/* 08 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, H8500_null, +/* 10 */ H8500_null, H8500_null, H8500_null, H8500_null, H8500_prtd, H8500_null, H8500_null, H8500_null, +/* 18 */ H8500_null, H8500_prts, H8500_null, H8500_null, H8500_prtd, H8500_null, H8500_null, H8500_null, +}; + +static const ushort A6tail[] = +{ +/* 20 */ H8500_null, H8500_null, +/* 30 */ H8500_null, H8500_null, +/* 40 */ H8500_null, H8500_null, +/* 50 */ H8500_null, H8500_null, +/* 60 */ H8500_null, H8500_null, +/* 70 */ H8500_null, H8500_null, +/* 80 */ H8500_movfpe, H8500_null, +/* 90 */ H8500_movtpe, H8500_null, +/* A0 */ H8500_dadd, H8500_null, +/* B0 */ H8500_dsub, H8500_scb, +/* C0 */ H8500_pjmp, H8500_pjsr, +/* D0 */ H8500_jmp, H8500_jsr, +/* E0 */ H8500_jmp, H8500_jsr, +/* F0 */ H8500_jmp, H8500_jsr, +}; + +struct tables_t +{ + const ushort *head; + const ushort *tail; +}; + +static const tables_t tables[] = +{ + { A3, A3tail }, + { A4, A4tail }, + { A5, A5tail }, + { A6, A6tail }, +}; + +//-------------------------------------------------------------------------- +inline void immv(op_t &x, int v) +{ + x.type = o_imm; + x.dtype = dt_dword; + x.value = v; +} + +//-------------------------------------------------------------------------- +inline void imm8(insn_t &insn, op_t &x) +{ + insn.auxpref |= aux_disp8; + x.type = o_imm; + x.dtype = dt_byte; + x.value = insn.get_next_byte(); +} + +//-------------------------------------------------------------------------- +inline void imm16(insn_t &insn, op_t &x) +{ + insn.auxpref |= aux_disp16; + x.type = o_imm; + x.dtype = dt_word; + x.value = insn.get_next_word(); +} + +//-------------------------------------------------------------------------- +inline void opreg(op_t &x, int code, char dtype) +{ + x.type = o_reg; + x.dtype = dtype; + x.reg = code & 7; +} + +//-------------------------------------------------------------------------- +inline void aa8(insn_t &insn, op_t &x, char dtype) +{ + insn.auxpref |= aux_page|aux_disp8; + x.type = o_mem; + x.dtype = dtype; + x.addr = insn.get_next_byte(); +} + +//-------------------------------------------------------------------------- +inline void aa16(insn_t &insn, op_t &x, char dtype) +{ + insn.auxpref |= aux_disp16; + x.type = o_mem; + x.dtype = dtype; + x.addr = insn.get_next_word(); +} + +//-------------------------------------------------------------------------- +inline void ds8(insn_t &insn, op_t &x, int reg, char dtype) +{ + insn.auxpref |= aux_disp8; + x.type = o_displ; + x.dtype = dtype; + x.reg = reg & 7; + x.addr = insn.get_next_byte(); +} + +//-------------------------------------------------------------------------- +inline void ds16(insn_t &insn, op_t &x, int reg, char dtype) +{ + insn.auxpref |= aux_disp16; + x.type = o_displ; + x.dtype = dtype; + x.reg = reg & 7; + x.addr = insn.get_next_word(); +} + +//-------------------------------------------------------------------------- +inline void phrase(op_t &x, int code, uchar pht, char dtype) +{ + x.type = o_phrase; + x.dtype = dtype; + x.phrase = code & 7; + x.phtype = pht; +} + +//-------------------------------------------------------------------------- +inline void d8(insn_t &insn, op_t &x) +{ + insn.auxpref |= aux_disp8; + int32 disp = char(insn.get_next_byte()); + x.type = o_near; + x.dtype = dt_code; + x.addr = insn.ip + insn.size + disp; +} + +//-------------------------------------------------------------------------- +int h8500_t::h8500_ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + uint8 code = insn.get_next_byte(); + uint8 saved_code = code; + char dtype = dt_byte; + if ( code < 0x60 ) + { + insn.itype = A2[code]; + } + else + { + if ( code & 8 ) + { + insn.auxpref |= aux_word; + dtype = dt_word; + } + else + { + insn.auxpref |= aux_byte; + dtype = dt_byte; + } + insn.itype = A2tail[(code>>4)-6]; + } + if ( insn.itype == H8500_null ) + return 0; + switch ( code ) + { + case 0x02: // ldm.w @sp+, <reglist> +// insn.auxpref |= aux_word; + phrase(insn.Op1, SP, ph_post, dt_word); + insn.Op2.type = o_reglist; + insn.Op2.reg = insn.get_next_byte(); + if ( !insn.Op2.reg ) + return 0; + break; + case 0x12: // stm.w <reglist>, @-sp +// insn.auxpref |= aux_word; + insn.Op1.type = o_reglist; + insn.Op1.reg = insn.get_next_byte(); + if ( !insn.Op1.reg ) + return 0; + phrase(insn.Op2, SP, ph_pre, dt_word); + break; + case 0x01: // scb/f + insn.auxpref |= aux_f; + break; + case 0x06: // scb/ne + insn.auxpref |= aux_ne; + break; + case 0x07: // scb/eq + insn.auxpref |= aux_eq; + break; + case 0x08: // trapa #xx + code = insn.get_next_byte(); + if ( (code & 0xF0) != 0x10 ) + return 0; + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_byte; + insn.Op1.value = code & 15; + break; + case 0x0F: // unlk + opreg(insn.Op1, FP, dt_word); + break; + case 0x10: // jmp @aa:16 + case 0x18: // jsr @aa:16 + aa16(insn, insn.Op1, dt_code); + insn.Op1.type = o_near; + insn.Op1.addr += insn.ea & ~0xFFFF; + break; + case 0x17: // link #xx:8 + opreg(insn.Op1, FP, dt_word); + imm8(insn, insn.Op2); + break; + case 0x1F: // link #xx:16 + opreg(insn.Op1, FP, dt_word); + imm16(insn, insn.Op2); + break; + case 0x03: // pjsr @aa:24 + case 0x13: // pjmp @aa:24 + { + insn.auxpref |= aux_disp24; + uint32 page = insn.get_next_byte(); + insn.Op1.type = o_far; + insn.Op1.dtype = dt_code; + insn.Op1.addr = (page<<16) | insn.get_next_word(); + } + break; + case 0x04: // #xx:8 + insn.auxpref |= aux_byte; + // fallthrough + case 0x14: // #xx:8 + imm8(insn, insn.Op1); + break; + case 0x05: // #aa:8.B + insn.auxpref |= aux_byte; + aa8(insn, insn.Op1, dt_byte); + break; + case 0x15: // #aa:16.B + insn.auxpref |= aux_byte; + aa16(insn, insn.Op1, dt_byte); + break; + case 0x0C: // #xx:16 + insn.auxpref |= aux_word; + // fallthrough + case 0x1C: // #xx:16 + imm16(insn, insn.Op1); + break; + case 0x0D: // #aa:8.W + insn.auxpref |= aux_word; + aa8(insn, insn.Op1, dt_word); + dtype = dt_word; + break; + case 0x1D: // #aa:16.W + insn.auxpref |= aux_word; + aa16(insn, insn.Op1, dt_word); + dtype = dt_word; + break; + case 0x0E: // bsr d:8 + case 0x20: case 0x21: case 0x22: case 0x23: // d:8 + case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2A: case 0x2B: + case 0x2C: case 0x2D: case 0x2E: case 0x2F: + d8(insn, insn.Op1); + break; + case 0x1E: // bsr d:16 + case 0x30: case 0x31: case 0x32: case 0x33: // d:16 + case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3A: case 0x3B: + case 0x3C: case 0x3D: case 0x3E: case 0x3F: + { + insn.auxpref |= aux_disp16; + int32 disp = short(insn.get_next_word()); + insn.Op1.type = o_near; + insn.Op1.dtype = dt_code; + insn.Op1.addr = insn.ip + insn.size + disp; + } + break; + case 0x40: case 0x41: case 0x42: case 0x43: // cmp:e #xx:8, Rn + case 0x44: case 0x45: case 0x46: case 0x47: + case 0x50: case 0x51: case 0x52: case 0x53: // mov:e #xx:8, Rn + case 0x54: case 0x55: case 0x56: case 0x57: + insn.auxpref |= aux_byte; + imm8(insn, insn.Op1); + opreg(insn.Op2, code, dtype); + break; + case 0x48: case 0x49: case 0x4A: case 0x4B: // cmp:i #xx:16, Rn + case 0x4C: case 0x4D: case 0x4E: case 0x4F: + case 0x58: case 0x59: case 0x5A: case 0x5B: // mov:i #xx:16, Rn + case 0x5C: case 0x5D: case 0x5E: case 0x5F: + insn.auxpref |= aux_word; + imm16(insn, insn.Op1); + opreg(insn.Op2, code, dtype); + break; + case 0x60: case 0x61: case 0x62: case 0x63: // @aa:8, Rn + case 0x64: case 0x65: case 0x66: case 0x67: + case 0x68: case 0x69: case 0x6A: case 0x6B: + case 0x6C: case 0x6D: case 0x6E: case 0x6F: + aa8(insn, insn.Op1, dtype); + opreg(insn.Op2, code, dtype); + break; + case 0x70: case 0x71: case 0x72: case 0x73: // Rn, @aa:8 + case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7A: case 0x7B: + case 0x7C: case 0x7D: case 0x7E: case 0x7F: + opreg(insn.Op1, code, dtype); + aa8(insn, insn.Op2, dtype); + break; + case 0x80: case 0x81: case 0x82: case 0x83: // mov:f @(d:8, R6), Rn + case 0x84: case 0x85: case 0x86: case 0x87: + case 0x88: case 0x89: case 0x8A: case 0x8B: + case 0x8C: case 0x8D: case 0x8E: case 0x8F: + ds8(insn, insn.Op1, R6, dtype); + opreg(insn.Op2, code, dtype); + break; + case 0x90: case 0x91: case 0x92: case 0x93: // mov:f Rn, @(d:8, R6) + case 0x94: case 0x95: case 0x96: case 0x97: + case 0x98: case 0x99: case 0x9A: case 0x9B: + case 0x9C: case 0x9D: case 0x9E: case 0x9F: + opreg(insn.Op1, code, dtype); + ds8(insn, insn.Op2, R6, dtype); + break; + case 0xA0: case 0xA1: case 0xA2: case 0xA3: // Rn, Rn + case 0xA4: case 0xA5: case 0xA6: case 0xA7: + case 0xA8: case 0xA9: case 0xAA: case 0xAB: + case 0xAC: case 0xAD: case 0xAE: case 0xAF: + opreg(insn.Op1, code, dtype); + break; + case 0xB0: case 0xB1: case 0xB2: case 0xB3: // @-Rn, Rn + case 0xB4: case 0xB5: case 0xB6: case 0xB7: + case 0xB8: case 0xB9: case 0xBA: case 0xBB: + case 0xBC: case 0xBD: case 0xBE: case 0xBF: + phrase(insn.Op1, code, ph_pre, dtype); + break; + case 0xC0: case 0xC1: case 0xC2: case 0xC3: // @Rn+, Rn + case 0xC4: case 0xC5: case 0xC6: case 0xC7: + case 0xC8: case 0xC9: case 0xCA: case 0xCB: + case 0xCC: case 0xCD: case 0xCE: case 0xCF: + phrase(insn.Op1, code, ph_post, dtype); + break; + case 0xD0: case 0xD1: case 0xD2: case 0xD3: // @Rn, Rn + case 0xD4: case 0xD5: case 0xD6: case 0xD7: + case 0xD8: case 0xD9: case 0xDA: case 0xDB: + case 0xDC: case 0xDD: case 0xDE: case 0xDF: + phrase(insn.Op1, code, ph_normal, dtype); + break; + case 0xE0: case 0xE1: case 0xE2: case 0xE3: // @(d:8,Rn), Rn + case 0xE4: case 0xE5: case 0xE6: case 0xE7: + case 0xE8: case 0xE9: case 0xEA: case 0xEB: + case 0xEC: case 0xED: case 0xEE: case 0xEF: + ds8(insn, insn.Op1, code, dtype); + break; + case 0xF0: case 0xF1: case 0xF2: case 0xF3: // @(d:16,Rn), Rn + case 0xF4: case 0xF5: case 0xF6: case 0xF7: + case 0xF8: case 0xF9: case 0xFA: case 0xFB: + case 0xFC: case 0xFD: case 0xFE: case 0xFF: + ds16(insn, insn.Op1, code, dtype); + break; + } + while ( insn.itype > H8500_last ) // while MAPs are not resolved + { + int index = -(3+short(insn.itype)); + if ( index < 0 || index >= qnumber(tables) ) + INTERR(10089); + code = insn.get_next_byte(); + if ( code < 0x20 ) + { + insn.itype = tables[index].head[code]; + } + else + { + insn.itype = tables[index].tail[(code>>3)-4]; + opreg(insn.Op2, code, dtype); + } + if ( index == 3 ) switch ( saved_code ) // MAP6 + { + case 0x01: + case 0x06: + case 0x07: + if ( insn.itype != H8500_scb ) + return 0; + break; + case 0x11: + if ( insn.itype != H8500_prts + && insn.itype != H8500_prtd + && insn.itype != H8500_jmp + && insn.itype != H8500_pjmp + && insn.itype != H8500_jsr + && insn.itype != H8500_pjsr ) + { + return 0; + } + break; + default: + if ( insn.itype != H8500_movfpe + && insn.itype != H8500_movtpe + && insn.itype != H8500_dadd + && insn.itype != H8500_dsub ) + { + return 0; + } + } + switch ( insn.itype ) + { + case H8500_null: + return 0; + case H8500_add_q: + insn.Op2 = insn.Op1; + switch ( code ) + { + case 0x08: immv(insn.Op1, 1); break; + case 0x09: immv(insn.Op1, 2); break; + case 0x0C: immv(insn.Op1, -1); break; + case 0x0D: immv(insn.Op1, -2); break; + } + break; + case H8500_bset: + case H8500_bclr: + case H8500_bnot: + case H8500_btst: + insn.Op2 = insn.Op1; + if ( code < 0xC0 ) + opreg(insn.Op1, code, dtype); + else + immv(insn.Op1, code & 15); + break; + case H8500_mov_g: + if ( (code & 0xF8) == 0x80 ) + break; + insn.Op2 = insn.Op1; + if ( code == 0x06 ) + { + if ( (insn.auxpref & aux_word) == 0 ) + insn.auxpref |= aux_byte; + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_byte; + insn.Op1.value = insn.get_next_byte(); + } + else if ( code == 0x07 ) + { + if ( (insn.auxpref & aux_byte) == 0 ) + insn.auxpref |= aux_word; + insn.auxpref |= aux_mov16; + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_word; + insn.Op1.value = insn.get_next_word(); + } + else + opreg(insn.Op1, code, dtype); + break; + case H8500_cmp_g: + if ( code > 5 ) + break; + insn.Op2 = insn.Op1; + if ( code == 0x04 ) + { + insn.auxpref |= aux_byte; + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_byte; + insn.Op1.value = insn.get_next_byte(); + } + else + { + insn.auxpref |= aux_word; + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_word; + insn.Op1.value = insn.get_next_word(); + } + break; + case H8500_andc: + case H8500_orc: + case H8500_xorc: + case H8500_ldc: + case H8500_stc: + insn.Op2.reg += SR; + if ( insn.Op2.reg == RES1 || insn.Op2.reg == CP ) + return 0; + if ( ((insn.auxpref & aux_word) != 0) != (insn.Op2.reg == SR) ) + return 0; + if ( insn.itype != H8500_stc ) + break; + // no break + case H8500_movtpe: + { + op_t x = insn.Op1; + insn.Op1 = insn.Op2; + insn.Op2 = x; + } + break; + case H8500_pjmp: + case H8500_pjsr: + case H8500_jmp: + case H8500_jsr: + insn.Op2.type = o_void; + switch ( code & 0xF0 ) + { + case 0xC0: + case 0xD0: phrase(insn.Op1, code, ph_normal, dt_code); break; + case 0xE0: ds8(insn, insn.Op1, code, dt_code); break; + case 0xF0: ds16(insn, insn.Op1, code, dt_code); break; + } + break; + case H8500_rtd: + case H8500_prtd: + if ( code == 0x14 ) + imm8(insn, insn.Op1); + else + imm16(insn, insn.Op1); + break; + case H8500_scb: + insn.Op1 = insn.Op2; + d8(insn, insn.Op2); + break; + case H8500_dadd: + case H8500_dsub: + if ( (insn.auxpref & aux_byte) == 0 ) + return 0; + insn.auxpref &= ~aux_byte; + break; + } + } + if ( !is_mixed_size_insns() ) + { + if ( (insn.auxpref & aux_word) && insn.Op1.dtype == dt_byte + || (insn.auxpref & aux_byte) && insn.Op1.dtype == dt_word ) + { + if ( insn.itype != H8500_mov_g ) + return 0; + } + } + return insn.size; +} diff --git a/idasdk75/module/h8500/emu.cpp b/idasdk76/module/h8500/emu.cpp similarity index 100% rename from idasdk75/module/h8500/emu.cpp rename to idasdk76/module/h8500/emu.cpp diff --git a/idasdk76/module/h8500/h8500.hpp b/idasdk76/module/h8500/h8500.hpp new file mode 100644 index 0000000..352107e --- /dev/null +++ b/idasdk76/module/h8500/h8500.hpp @@ -0,0 +1,122 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _H8500_HPP +#define _H8500_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <segregs.hpp> +#include <diskio.hpp> + +#define PROCMOD_NAME h8500 +#define PROCMOD_NODE_NAME "$ h8/500" + +//--------------------------------- +// Operand types: + +/* +o_reg 1 Register direct Rn + x.reg +o_phrase 2 Register indirect @Rn + x.phrase contains register number + x.phtype contains phrase type (normal, post, pre) +o_displ 3 Register indirect with displacement @(d:8,Rn)/@(d:16,Rn) + x.reg, x.addr, aux_disp16, aux_disp32 +o_mem 5 Absolute address @aa:8/@aa:16/@aa:24 + x.page, x.addr +o_imm 6 Immediate #xx:8/#xx:16/#xx:32 + x.value +o_displ 7 Program-counter relative @(d:8,PC)/@(d:16,PC) +o_reglist Register list + x.reg +*/ + +#define o_reglist o_idpspec0 + +#define phtype specflag1 // phrase type: +const int ph_normal = 0; // just simple indirection +const int ph_pre = 1; // predecrement +const int ph_post = 2; // postincrement + +#define page specflag1 // o_mem, page number if aux_page +//------------------------------------------------------------------ +#define aux_byte 0x0001 // .b postfix +#define aux_word 0x0002 // .w postfix +#define aux_disp8 0x0004 // 8bit displacement +#define aux_disp16 0x0008 // 16bit displacement +#define aux_disp24 0x0010 // 24bit displacement +#define aux_page 0x0020 // implicit page using BR +#define aux_f 0x0040 // /f postfix +#define aux_ne 0x0080 // /ne postfix +#define aux_eq 0x0100 // /eq postfix +#define aux_mov16 0x0200 // mov #xx:16, ... + +//------------------------------------------------------------------ +enum regnum_t +{ + R0, R1, R2, R3, R4, R5, R6, FP=R6, R7, SP=R7, + SR, CCR, RES1, BR, EP, DP, CP, TP, // RES1 is forbidden +}; + + +ea_t calc_mem(const insn_t &insn, const op_t &x); // map virtual to physical ea +//------------------------------------------------------------------ +int calc_opimm_flags(const insn_t &insn); +int calc_opdispl_flags(const insn_t &insn); + +void idaapi h8500_header(outctx_t &ctx); + +void idaapi h8500_segend(outctx_t &ctx, segment_t *seg); + +int idaapi is_align_insn(ea_t ea); +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_sp_based(const insn_t &insn, const op_t &x); + +int idaapi h8500_get_frame_retsize(const func_t *); +int is_jump_func(const func_t *pfn, ea_t *jump_target); +int is_sane_insn(const insn_t &insn, int nocrefs); +int may_be_func(const insn_t &insn); // can a function start here? + +//------------------------------------------------------------------ +struct h8500_t : public procmod_t +{ + netnode helper; + ioports_t ports; +#define IDP_SAMESIZE 0x0001 // do not disassemble mixed size insns + ushort idpflags = 0; + bool is_mixed_size_insns() const { return (idpflags & IDP_SAMESIZE) == 0; } + bool flow = false; + char show_sizer = -1; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void load_symbols(const char *file); + const char *find_sym(int address); + const char *set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + + int h8500_ana(insn_t *_insn); + + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + int h8500_emu(const insn_t &insn); + + void h8500_assume(outctx_t &ctx); + void h8500_segstart(outctx_t &ctx, segment_t *Srange) const; + void h8500_footer(outctx_t &ctx) const; + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); +}; +extern int data_id; + +#endif // _H8500_HPP diff --git a/idasdk75/module/h8500/ins.cpp b/idasdk76/module/h8500/ins.cpp similarity index 100% rename from idasdk75/module/h8500/ins.cpp rename to idasdk76/module/h8500/ins.cpp diff --git a/idasdk76/module/h8500/ins.hpp b/idasdk76/module/h8500/ins.hpp new file mode 100644 index 0000000..c7dd970 --- /dev/null +++ b/idasdk76/module/h8500/ins.hpp @@ -0,0 +1,130 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ + +H8500_null = 0, // Unknown Operation + +// Data transfer + +H8500_mov_g, // B/W Move data +H8500_mov_e, // B Move data +H8500_mov_i, // W Move data +H8500_mov_f, // B/W Move data +H8500_mov_l, // B/W Move data +H8500_mov_s, // B/W Move data +H8500_ldm, // W Pop data from the stack to one or more registers +H8500_stm, // W Push data from one or more registers onto the stack +H8500_xch, // W Exchange data between two general registers +H8500_swap, // B Exchange the upper and lower bytes in a general register +H8500_movtpe, // B Transfer data from a general register to memory +H8500_movfpe, // B Transfer data from memory to a general register + +// Arithmetic operations + +H8500_add_g, // B/W Addition +H8500_add_q, // B/W Addition +H8500_sub, // B/W Subtraction +H8500_adds, // B/W Addition +H8500_subs, // B/W Subtraction +H8500_addx, // B/W Addition with carry +H8500_subx, // B/W Subtraction with borrow +H8500_dadd, // B Decimal addition +H8500_dsub, // B Decimal subtraction +H8500_mulxu, // B/W Unsigned multiplication +H8500_divxu, // B/W Unsigned division +H8500_cmp_g, // B/W Compare data +H8500_cmp_e, // B Compare data +H8500_cmp_i, // W Compare data +H8500_exts, // B Convert byte to word by extending the sign bit +H8500_extu, // B Convert byte to word data by padding with zero bits +H8500_tst, // B/W Compare with 0 +H8500_neg, // B/W Negate +H8500_clr, // B/W Make zero +H8500_tas, // B Test and set + +// Logic Operations + +H8500_and, // B/W Logical AND +H8500_or, // B/W Logical OR +H8500_xor, // B/W Exclusive OR +H8500_not, // B/W Bitwise NOT + +// Shift Operations + +H8500_shal, // B/W Arithmetic shift left +H8500_shar, // B/W Arithmetic shift right +H8500_shll, // B/W Logical shift left +H8500_shlr, // B/W Logical shift right +H8500_rotl, // B/W Rotate left +H8500_rotr, // B/W Rotate right +H8500_rotxl, // B/W Rotate through carry left +H8500_rotxr, // B/W Rotate through carry right + +// Bit Manipulations + +H8500_bset, // B/W Test bit and set +H8500_bclr, // B/W Test bit and clear +H8500_bnot, // B/W Test bit and invert +H8500_btst, // B/W Test bit + +// Branching Instructions + +H8500_bra, // Branch Always +H8500_brn, // Branch Never +H8500_bhi, // Branch if High (C|Z = 0) +H8500_bls, // Branch if Low or Same (C|Z = 1) +H8500_bcc, // Branch if Carry Clear (C = 0) +H8500_bcs, // Branch if Carry Set (C = 1) +H8500_bne, // Branch if Not Equal (Z = 0) +H8500_beq, // Branch if Equal (Z = 1) +H8500_bvc, // Branch if Overflow Clear (V = 0) +H8500_bvs, // Branch if Overflow Set (V = 1) +H8500_bpl, // Branch if Plus (N = 0) +H8500_bmi, // Branch if Minus (N = 1) +H8500_bge, // Branch if Greater or Equal (N^V = 0) +H8500_blt, // Branch if Less Than (N^V = 1) +H8500_bgt, // Branch if Greater Than (Z|(N^V) = 0) +H8500_ble, // Branch if Less or Equal (Z|(N^V) = 1) +H8500_jmp, // Branch unconditionally (same page) +H8500_pjmp, // Branch unconditionally (specified page) +H8500_bsr, // Branch to subroutine (same page) +H8500_jsr, // Branch to subroutine (same page) +H8500_pjsr, // Branch to subroutine (specified page) +H8500_rts, // Return from subroutine (same page) +H8500_prts, // Return from subroutine (different page) +H8500_rtd, // Return from subroutine (same page) and adjust SP +H8500_prtd, // Return from subroutine (different page) and adjust SP +H8500_scb, // Control loop + +// System Control Instructions + +H8500_trapa, // Generate trap exception +H8500_trap_vs, // Generate trap exception if the V bit is set +H8500_rte, // Return from exception-handling routine +H8500_link, // Create stack frame +H8500_unlk, // Deallocate stack frame +H8500_sleep, // Go to power-down state +H8500_ldc, // B/W Move to control register +H8500_stc, // B/W Move from control register +H8500_andc, // B/W Logically AND control register +H8500_orc, // B/W Logically OR control register +H8500_xorc, // B/W Logically exclusive-OR control register +H8500_nop, // No operation +H8500_bpt, // + +H8500_last, + + }; + +#endif diff --git a/idasdk76/module/h8500/makefile b/idasdk76/module/h8500/makefile new file mode 100644 index 0000000..c99e2ff --- /dev/null +++ b/idasdk76/module/h8500/makefile @@ -0,0 +1,51 @@ +PROC=h8500 + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ana.cpp h8500.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + emu.cpp h8500.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + h8500.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + h8500.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + h8500.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/h8500/out.cpp b/idasdk76/module/h8500/out.cpp similarity index 100% rename from idasdk75/module/h8500/out.cpp rename to idasdk76/module/h8500/out.cpp diff --git a/idasdk76/module/h8500/reg.cpp b/idasdk76/module/h8500/reg.cpp new file mode 100644 index 0000000..d067a76 --- /dev/null +++ b/idasdk76/module/h8500/reg.cpp @@ -0,0 +1,506 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "h8500.hpp" +#include <fpro.h> +#include <diskio.hpp> + +#include <ieee.h> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", "fp", "sp", + "sr", "ccr", "?", "br", "ep", "dp", "cp", "tp", +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0x56, 0x70 }; // rte +static const uchar retcode_1[] = { 0x54, 0x70 }; // rts + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//------------------------------------------------------------------ +static void idaapi func_header(outctx_t &ctx, func_t *pfn) +{ + ctx.gen_func_header(pfn); + + if ( ctx.curlabel.empty() ) + return; + + ctx.gen_printf(0, "%s" COLSTR(":", SCOLOR_SYMBOL) " " + SCOLOR_ON SCOLOR_AUTOCMT + "%s %s" + SCOLOR_OFF SCOLOR_AUTOCMT, + ctx.curlabel.begin(), + ASH.cmnt, + (pfn->flags & FUNC_FAR) != 0 ? "far" : "near"); + ctx.ctxflags |= CTXF_LABEL_OK; +} + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gas = +{ + AS_ASCIIC|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, + 0, + "GNU assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + "!", // comment string + '"', // string delimiter + '"', // char delimiter + "\"", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".byte", // byte directive + ".word", // word directive + ".long", // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + NULL, // current IP (instruction pointer) + func_header, // func_header + NULL, // func_footer + ".globl", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_COLONSUF, // flag2 + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt +}; + +static const asm_t *const asms[] = { &gas, NULL }; + +//-------------------------------------------------------------------------- +void h8500_t::load_symbols(const char *file) +{ + ports.clear(); + + // KLUDGE: read_ioports() will complain if the file is + // not present, but we don't want that. + char cfgpath[QMAXPATH]; + const char *rfile = getsysfile(cfgpath, sizeof(cfgpath), file, CFG_SUBDIR); + if ( rfile != NULL ) + read_ioports(&ports, NULL, file); +} + +//-------------------------------------------------------------------------- +const char *h8500_t::find_sym(int address) +{ + const ioport_t *port = find_ioport(ports, address); + return port != NULL ? port->name.c_str() : NULL; +} + +//------------------------------------------------------------------------- +void h8500_t::load_from_idb() +{ + // in old databases we store 0 for the "mixed size" flag and -1 for the + // "same size" flag. Now we store 1 for the latter. + uval_t flags = helper.altval(-1); + idpflags = flags == 0 ? 0 : IDP_SAMESIZE; +} + +//------------------------------------------------------------------ +const char *h8500_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + static const char form[] = + "HELP\n" + "H8/500 specific analyzer options\n" + "\n" + "Disassemble mixed size instructions\n" + "\n" + " According to the documentation, instructions like\n" + "\n" + " cmp:g.b #1:16, @0x222:16\n" + "\n" + " are not allowed. The correct instruction is:\n" + "\n" + " cmp:g.b #1:8, @0x222:16\n" + "\n" + " The size of the first operand should agree with the size\n" + " of the instruction. (exception mov:g)\n" + "\n" + "ENDHELP\n" + "H8/500 specific analyzer options\n" + "\n" + // m + " <Disassemble ~m~ixed size instructions:C>>\n" + "\n" + "\n"; + + if ( keyword != nullptr ) + { + if ( streq(keyword, "H8500_MIXED_SIZE") ) + { + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + // we store in IDPFLAGS the negation of the mixed size flag + setflag(idpflags, IDP_SAMESIZE, *(int*)value == 0); + } + else + { + return IDPOPT_BADKEY; + } + } + else + { + // we store in IDPFLAGS the negation of the mixed size flag + ushort flags = 0; + if ( is_mixed_size_insns() ) + flags |= 1; + ask_form(form, &flags); + idpflags = 0; + if ( (flags & 1) == 0 ) + idpflags |= IDP_SAMESIZE; + } + if ( idb_loaded ) + save_idpflags(); + return IDPOPT_OK; + +} + +//----------------------------------------------------------------------- +#define FAMILY "Hitachi H8/500:" +static const char *const shnames[] = { "h8500", NULL }; +static const char *const lnames[] = +{ + FAMILY"Hitachi H8/500", + NULL +}; + +//----------------------------------------------------------------------- +// temporary solution for v4.7 +static ea_t idaapi h8_extract_address(ea_t screen_ea, const char *string, size_t x) +{ + size_t len = strlen(string); + if ( len == 0 || x > len ) + return BADADDR; + if ( x == len ) + x--; + const char *ptr = string + x; + while ( ptr > string && qisxdigit(ptr[-1]) ) + ptr--; + const char *start = ptr; + while ( qisxdigit(ptr[0]) ) + ptr++; + len = ptr - start; + char buf[MAXSTR]; + memcpy(buf, start, len); + buf[len] = '\0'; + ea_t ea = BADADDR; + str2ea(&ea, buf, screen_ea); + return ea; +} + +//------------------------------------------------------------------------ +static bool idaapi can_have_type(const op_t &x) // returns 1 - operand can have +{ + switch ( x.type ) + { + case o_void: + case o_reg: + case o_reglist: + return false; + case o_phrase: + return x.phtype == ph_normal; + } + return true; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(h8500_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi h8500_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); + load_symbols("h8500.cfg"); + break; + + case processor_t::ev_term: + ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + save_idpflags(); + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_creating_segm: // new segment + { + segment_t *sptr = va_arg(va, segment_t *); + sptr->defsr[BR-ph.reg_first_sreg] = 0; + sptr->defsr[DP-ph.reg_first_sreg] = 0; + } + break; + + case processor_t::ev_is_jump_func: + { + const func_t *pfn = va_arg(va, const func_t *); + ea_t *jump_target = va_arg(va, ea_t *); + return is_jump_func(pfn, jump_target); + } + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + int no_crefs = va_arg(va, int); + return is_sane_insn(*insn, no_crefs) == 1 ? 1 : -1; + } + + case processor_t::ev_may_be_func: + { + const insn_t *insn = va_arg(va, insn_t *); + return may_be_func(*insn); + } + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + h8500_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + h8500_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + h8500_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + h8500_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + h8500_assume(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return h8500_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return h8500_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *op = va_arg(va, const op_t *); + return can_have_type(*op) ? 1 : -1; + } + + case processor_t::ev_extract_address: + { + ea_t *out_ea = va_arg(va, ea_t *); + ea_t screen_ea = va_arg(va, ea_t); + const char *str = va_arg(va, const char *); + size_t pos = va_arg(va, size_t); + ea_t ea = h8_extract_address(screen_ea, str, pos); + if ( ea == BADADDR ) + return -1; + if ( ea == (BADADDR-1) ) + return 0; + *out_ea = ea; + return 1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = h8500_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_H8500, // id + // flag + PRN_HEX + | PR_SEGS + | PR_SGROTHER, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + BR, // first + TP, // last + 1, // size of a segment register + CP, DP, + + NULL, // No known code start sequences + retcodes, + + H8500_null, + H8500_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + H8500_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/hppa/ana.cpp b/idasdk76/module/hppa/ana.cpp new file mode 100644 index 0000000..ca062bd --- /dev/null +++ b/idasdk76/module/hppa/ana.cpp @@ -0,0 +1,1334 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + */ + +#include "hppa.hpp" + +//-------------------------------------------------------------------------- +static void simplify(insn_t &insn, uint32 code) +{ + switch ( insn.itype ) + { + // B,L,n target, %r0 => B,n target + // B,L,n target, %r2 => CALL,n target + case HPPA_b: + { + int sub = (code>>13) & 7; + if ( sub == 1 || sub == 4 ) + break; // ,gate or ,push + switch ( insn.Op2.reg ) + { + case R0: + insn.Op2.type = o_void; + break; + case R2: + insn.itype = HPPA_call; + insn.Op2.type = o_void; + break; + } + } + break; + + // BVE,L,n (b), %r2 => CALL,n (b) + // BVE,n (%r2) => RET,n + case HPPA_bve: + if ( code & BIT31 ) + break; // ,push or ,pop + if ( insn.Op2.type == o_reg ) + { + insn.itype = HPPA_call; + insn.Op1.type = o_void; + break; + } + if ( insn.Op1.phrase == R2 ) + { + insn.itype = HPPA_ret; + insn.Op1.type = o_void; + } + break; + + // DEPD,Z,cond r,63-sa,64-sa,t => SHLD,cond r,sa,t + // DEPW,Z,cond r,31-sa,32-sa,t => SHLW,cond r,sa,t + case HPPA_depd: + case HPPA_depw: + if ( code & BIT21 ) + break; // no Z flag + if ( insn.Op2.type == o_imm + && insn.Op3.type == o_imm + && (insn.Op2.value+1) == insn.Op3.value ) + { + insn.itype += (HPPA_shld-HPPA_depd); + insn.Op2.value = (insn.itype == HPPA_shld ? 63 : 31) - insn.Op2.value; + insn.Op3 = insn.Op4; + insn.Op4.type = o_void; + } + break; + + // DEPWI,Z,cond -1,31,x,t => LDI,cond (1<<x)-1,t + case HPPA_depwi: + if ( code & BIT21 ) + break; // no Z flag + if ( insn.Op2.type == o_imm && insn.Op2.value == 31 + && insn.Op3.type == o_imm && insn.Op3.value <= 16 ) + { + insn.itype = HPPA_ldi; + insn.Op1.value = (uval_t(1) << insn.Op3.value) - 1; + insn.Op2 = insn.Op4; + insn.Op3.type = o_void; + insn.Op4.type = o_void; + } + break; + // EXTRD,S,cond r,63-sa,64-sa,t => SHRD,S,cond r,sa,t + // EXTRD,U,cond r,63-sa,64-sa,t => SHRD,U,cond r,sa,t + // EXTRW,S,cond r,31-sa,32-sa,t => SHRW,S,cond r,sa,t + // EXTRW,U,cond r,31-sa,32-sa,t => SHRW,U,cond r,sa,t + case HPPA_extrd: + case HPPA_extrw: + if ( insn.Op2.type == o_imm + && insn.Op3.type == o_imm + && (insn.Op2.value+1) == insn.Op3.value ) + { + insn.itype += HPPA_shrd - HPPA_extrd; + insn.Op2.value = (insn.itype == HPPA_shrd ? 63 : 31) - insn.Op2.value; + insn.Op3 = insn.Op4; + insn.Op4.type = o_void; + } + break; + + // LDO i(%r0), t => LDI i, t + // LDO 0(r), t => COPY r, t + case HPPA_ldo: + if ( insn.Op1.reg == R0 ) + { + insn.itype = HPPA_ldi; + insn.Op1.type = o_imm; + insn.Op1.value = insn.Op1.addr; + break; + } + if ( insn.Op1.addr == 0 ) + { + insn.itype = HPPA_copy; + insn.Op1.type = o_reg; + } + break; + + // MTCTL r, %sar => MTSAR r + case HPPA_mtctl: + if ( insn.Op2.reg == CR11 ) + { + insn.itype = HPPA_mtsar; + insn.Op2.type = o_void; + } + break; + + // OR %r0, %r0, %r0 => NOP + // OR %r, %r0, %t => COPY r, t + // OR %r0, %r, %t => COPY r, t + case HPPA_or: + if ( ((code>>13) & 7) ) + break; // condition codes not zero + if ( insn.Op1.reg == R0 ) + { + if ( insn.Op2.reg == R0 && insn.Op3.reg == R0 ) + { + insn.itype = HPPA_nop; + insn.Op1.type = o_void; + insn.Op2.type = o_void; + insn.Op3.type = o_void; + break; + } + insn.itype = HPPA_copy; + insn.Op1 = insn.Op2; + insn.Op2 = insn.Op3; + insn.Op3.type = o_void; + break; + } + if ( insn.Op2.reg == R0 ) + { + insn.itype = HPPA_copy; + insn.Op2 = insn.Op3; + insn.Op3.type = o_void; + } + break; + } +} + +//-------------------------------------------------------------------------- +struct table1_t +{ + ushort itype; + char dtype; +}; + +static const table1_t C1[] = +{ + { 0, dt_qword }, // 00 + { 0, dt_qword }, // 01 + { 0, dt_qword }, // 02 + { 0, dt_qword }, // 03 + { 0, dt_qword }, // 04 + { HPPA_diag, dt_qword }, // 05 + { HPPA_fmpyadd, dt_qword }, // 06 + { HPPA_null, dt_qword }, // 07 + { HPPA_ldil, dt_qword }, // 08 + { 0, dt_qword }, // 09 + { HPPA_addil, dt_qword }, // 0A + { 0, dt_qword }, // 0B + { HPPA_copr, dt_qword }, // 0C + { HPPA_ldo, dt_dword }, // 0D + { 0, dt_qword }, // 0E + { HPPA_null, dt_qword }, // 0F + { HPPA_ldb, dt_byte }, // 10 + { HPPA_ldh, dt_word }, // 11 + { HPPA_ldw, dt_dword }, // 12 + { HPPA_ldw, dt_dword }, // 13 + { 0, dt_qword }, // 14 + { HPPA_null, dt_dword }, // 15 + { HPPA_fldw, dt_dword }, // 16 + { 0, dt_dword }, // 17 + { HPPA_stb, dt_byte }, // 18 + { HPPA_sth, dt_word }, // 19 + { HPPA_stw, dt_dword }, // 1A + { HPPA_stw, dt_dword }, // 1B + { 0, dt_qword }, // 1C + { HPPA_null, dt_dword }, // 1D + { HPPA_fstw, dt_dword }, // 1E + { 0, dt_dword }, // 1F + { HPPA_cmpb, dt_byte }, // 20 + { HPPA_cmpib, dt_byte }, // 21 + { HPPA_cmpb, dt_byte }, // 22 + { HPPA_cmpib, dt_dword }, // 23 + { HPPA_cmpiclr, dt_qword }, // 24 + { HPPA_subi, dt_dword }, // 25 + { HPPA_fmpysub, dt_dword }, // 26 + { HPPA_cmpb, dt_byte }, // 27 + { HPPA_addb, dt_byte }, // 28 + { HPPA_addib, dt_byte }, // 29 + { HPPA_addb, dt_byte }, // 2A + { HPPA_addib, dt_byte }, // 2B + { HPPA_addi, dt_dword }, // 2C + { HPPA_addi, dt_dword }, // 2D + { 0, dt_dword }, // 2E + { HPPA_cmpb, dt_byte }, // 2F + { HPPA_bb, dt_dword }, // 30 + { HPPA_bb, dt_dword }, // 31 + { HPPA_movb, dt_byte }, // 32 + { HPPA_movib, dt_byte }, // 33 + { 0, dt_dword }, // 34 + { 0, dt_dword }, // 35 + { HPPA_extrd, dt_qword }, // 36 + { HPPA_null, dt_dword }, // 37 + { HPPA_be, dt_dword }, // 38 + { HPPA_be, dt_dword }, // 39 + { 0, dt_dword }, // 3A + { HPPA_cmpib, dt_byte }, // 3B + { 0, dt_dword }, // 3C + { 0, dt_dword }, // 3D + { 0, dt_dword }, // 3E + { HPPA_null, dt_dword }, // 3F +}; + +struct ldst_t +{ + ushort itype; + char dtype; +}; + +static const ldst_t C6[] = +{ + { HPPA_ldb, dt_byte }, // 0 + { HPPA_ldh, dt_word }, // 1 + { HPPA_ldw, dt_dword }, // 2 + { HPPA_ldd, dt_qword }, // 3 + { HPPA_ldda, dt_qword }, // 4 + { HPPA_ldcd, dt_qword }, // 5 + { HPPA_ldwa, dt_dword }, // 6 + { HPPA_ldcw, dt_dword }, // 7 + { HPPA_stb, dt_byte }, // 8 + { HPPA_sth, dt_word }, // 9 + { HPPA_stw, dt_dword }, // A + { HPPA_std, dt_qword }, // B + { HPPA_stby, dt_byte }, // C + { HPPA_stdby, dt_qword }, // D + { HPPA_stwa, dt_dword }, // E + { HPPA_stda, dt_qword }, // F +}; + +//-------------------------------------------------------------------------- +static void opr(op_t &x, uint32 rgnum) +{ + x.reg = (uint16)rgnum; +/* if ( rgnum == 0 ) + { + x.type = o_imm; + x.value = 0; + x.dtype = dt_dword; + } + else*/ + { + x.type = o_reg; + x.dtype = dt_qword; + } +} + +//-------------------------------------------------------------------------- +inline void opi(op_t &x, uval_t v) +{ + x.type = o_imm; + x.value = v; + x.dtype = dt_dword; +} + +//-------------------------------------------------------------------------- +inline void opb(op_t &x, int r) +{ + x.type = o_based; + x.phrase = (uint16)r; + x.dtype = dt_dword; +} + +//-------------------------------------------------------------------------- +inline void opbs(insn_t &insn, op_t &x, int sr, int r) +{ + opb(x, r); + x.sid = uchar(SR0+sr); + if ( sr != 0 ) + insn.auxpref |= aux_space; +} + +//-------------------------------------------------------------------------- +inline void opx(op_t &x, int b, int xx, char dtype) +{ + x.type = o_phrase; + x.phrase = uint16(b); + x.secreg = uchar(xx); + x.dtype = dtype; +} + +//-------------------------------------------------------------------------- +inline void opxs(insn_t &insn, op_t &x, int sr, int b, int xx, char dtype) +{ + opx(x, b, xx, dtype); + x.sid = uchar(SR0+sr); + if ( sr != 0 ) + insn.auxpref |= aux_space; +} + +//-------------------------------------------------------------------------- +inline void opd(op_t &x, int b, uval_t value, char dtype) +{ + x.type = o_displ; + x.phrase = uint16(b); + x.addr = value; + x.dtype = dtype; +} + +//-------------------------------------------------------------------------- +inline void opds(insn_t &insn, op_t &x, int sr, int b, uval_t value, char dtype) +{ + opd(x, b, value, dtype); + x.sid = uchar(SR0+sr); + if ( sr != 0 ) + insn.auxpref |= aux_space; +} + +//-------------------------------------------------------------------------- +struct table_t +{ + char code; + ushort itype; //lint !e958 padding is required to align members +}; + +static const table_t C5[] = +{ + { 0x18, HPPA_add }, + { 0x28, HPPA_add }, + { 0x38, HPPA_add }, + { 0x1C, HPPA_add }, + { 0x3C, HPPA_add }, + { 0x19, HPPA_shladd }, + { 0x29, HPPA_shladd }, + { 0x39, HPPA_shladd }, + { 0x1A, HPPA_shladd }, + { 0x2A, HPPA_shladd }, + { 0x3A, HPPA_shladd }, + { 0x1B, HPPA_shladd }, + { 0x2B, HPPA_shladd }, + { 0x3B, HPPA_shladd }, + { 0x10, HPPA_sub }, + { 0x30, HPPA_sub }, + { 0x13, HPPA_sub }, + { 0x33, HPPA_sub }, + { 0x14, HPPA_sub }, + { 0x34, HPPA_sub }, + { 0x11, HPPA_ds }, + { 0x00, HPPA_andcm }, + { 0x08, HPPA_and }, + { 0x09, HPPA_or }, + { 0x0A, HPPA_xor }, + { 0x0E, HPPA_uxor }, + { 0x22, HPPA_cmpclr }, + { 0x26, HPPA_uaddcm }, + { 0x27, HPPA_uaddcm }, + { 0x2E, HPPA_dcor }, + { 0x2F, HPPA_dcor }, + { 0x0F, HPPA_hadd }, + { 0x0D, HPPA_hadd }, + { 0x0C, HPPA_hadd }, + { 0x07, HPPA_hsub }, + { 0x05, HPPA_hsub }, + { 0x04, HPPA_hsub }, + { 0x0B, HPPA_havg }, + { 0x1D, HPPA_hshladd }, + { 0x1E, HPPA_hshladd }, + { 0x1F, HPPA_hshladd }, + { 0x15, HPPA_hshladd }, + { 0x16, HPPA_hshladd }, + { 0x17, HPPA_hshladd }, + { 0, HPPA_null }, +}; + +static ushort find_itype(const table_t *table, int code) +{ + while ( table->itype ) + { + if ( table->code == code ) + return table->itype; + table++; + } + return HPPA_null; +} + +//-------------------------------------------------------------------------- +inline sval_t ls5(int i5) { return (( i5>>1)&15) | (( i5 & 1) ? ~sval_t(15) : 0); } +inline sval_t ls11(int i11) { return ((i11>>1)&0x3FF) | ((i11 & 1) ? ~sval_t(0x1FF) : 0); } +inline sval_t s12(int imm12) { return (imm12 & 0x0800) ? (imm12 | ~sval_t(0x0FFF)) : imm12; } +inline sval_t s16(int imm16) { return (imm16 & 0x8000) ? (imm16 | ~sval_t(0xFFFF)) : imm16; } +inline sval_t s17(uint32 i17) { return (i17 & 0x10000) ? (i17 | ~sval_t(0x1FFFF)) : i17; } +inline sval_t s22(uint32 i22) { return (i22 & 0x200000) ? (i22 | ~sval_t(0x3FFFFF)) : i22; } +inline int mfr(int r, bool d) { return (d ? F0 : F16L) + r; } +inline int as3(int s) +{ + return ((s>>1) & 3) | ((s&1) << 2); +} +inline int fr(int r, int y) +{ + return F0 + r + ((y&1)<<5); +} + +//-------------------------------------------------------------------------- +static void handle_float_0C(insn_t &insn, uint32 code) +{ + int uid = (code>> 6) & 7; + if ( uid == 2 ) // performance coprocessor + { + int sub = (code>>9) & 0x1F; + switch ( sub ) + { + case 1: + insn.itype = HPPA_pmdis; + break; + case 3: + insn.itype = (code & BIT26) ? HPPA_null : HPPA_pmenb; + break; + default: + insn.itype = HPPA_null; + break; + } + return; + } + if ( uid != 0 ) + return; // other coprocessors + + // floating-point coprocessor + int cls = (code>>9) & 3; + switch ( cls ) + { + case 0: + { + static const ushort itypes[] = + { + HPPA_fid, HPPA_null, HPPA_fcpy, HPPA_fabs, + HPPA_fsqrt, HPPA_frnd, HPPA_fneg, HPPA_fnegabs + }; + insn.itype = itypes[(code>>13)&7]; + if ( insn.itype != HPPA_fid ) + { + opr(insn.Op1, F0 + r06(code)); + opr(insn.Op2, F0 + r27(code)); + } + } + break; + case 1: + insn.itype = HPPA_fcnv; + opr(insn.Op1, F0 + r06(code)); + opr(insn.Op2, F0 + r27(code)); + break; + case 2: + if ( code & BIT26 ) + { + insn.itype = HPPA_ftest; + int y = (code>>13) & 7; + if ( y != 1 ) + opr(insn.Op1, CA0+(y^1)-1); + } + else + { + insn.itype = HPPA_fcmp; + opr(insn.Op1, F0 + r06(code)); + opr(insn.Op2, F0 + r11(code)); + int y = (code>>13) & 7; + if ( y ) + opr(insn.Op3, CA0+y-1); + } + break; + case 3: + { + static const ushort itypes[] = + { + HPPA_fadd, HPPA_fsub, HPPA_fmpy, HPPA_fdiv, + HPPA_frem, HPPA_null, HPPA_null, HPPA_null + }; + int sub = (code>>13) & 7; + insn.itype = (code & BIT26) ? HPPA_null : itypes[sub]; + opr(insn.Op1, F0 + r06(code)); + opr(insn.Op2, F0 + r11(code)); + opr(insn.Op3, F0 + r27(code)); + } + break; + } +} + +//-------------------------------------------------------------------------- +static void handle_float_0E(insn_t &insn, uint32 code) +{ + int cls = (code>>9) & 3; + switch ( cls ) + { + case 0: + { + static const ushort itypes[] = + { + HPPA_null, HPPA_null, HPPA_fcpy, HPPA_fabs, + HPPA_fsqrt, HPPA_frnd, HPPA_fneg, HPPA_fnegabs + }; + insn.itype = itypes[(code>>13)&7]; + opr(insn.Op1, fr(r06(code), (code>>7)&1)); + opr(insn.Op2, fr(r27(code), (code>>6)&1)); + } + break; + case 1: + insn.itype = HPPA_fcnv; + opr(insn.Op1, fr(r06(code), (code>>7)&1)); + opr(insn.Op2, fr(r27(code), (code>>6)&1)); + break; + case 2: + { + insn.itype = HPPA_fcmp; + opr(insn.Op1, fr(r06(code), (code>>7)&1)); + opr(insn.Op2, fr(r11(code), (code>>12)&1)); + int y = (code>>13) & 7; + if ( y ) + opr(insn.Op3, CA0+y-1); + } + break; + case 3: + { + static const ushort itypes[] = + { + HPPA_fadd, HPPA_fsub, HPPA_fmpy, HPPA_fdiv, + HPPA_null, HPPA_null, HPPA_null, HPPA_null + }; + int sub = (code>>13) & 7; + insn.itype = itypes[sub]; + if ( code & BIT23 ) + { + insn.itype = (sub == 2) ? HPPA_xmpyu : HPPA_null; + } + opr(insn.Op1, fr(r06(code), (code>>7)&1)); + opr(insn.Op2, fr(r11(code), (code>>12)&1)); + opr(insn.Op3, fr(r27(code), (code>>6)&1)); + } + break; + } +} + +//-------------------------------------------------------------------------- +inline void opn(op_t &x, sval_t disp, ea_t ip) +{ + disp <<= 2; + x.type = o_near; + x.addr = ip + 8 + disp; +} + +//-------------------------------------------------------------------------- +int hppa_t::ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + if ( insn.ip & 3 ) + return 0; // alignment error + + uint32 code = insn.get_next_dword(); + + int op = opcode(code); + insn.itype = C1[op].itype; + char dtype = C1[op].dtype; + switch ( op ) + { + case 0x00: + switch ( (code>>5) & 0xFF ) + { + case 0x00: + insn.itype = HPPA_break; + opi(insn.Op1, r27(code)); + opi(insn.Op2, (code>>13) & 0x1FFF); + break; + case 0x20: + insn.itype = (code & BIT11) ? HPPA_syncdma : HPPA_sync; + break; + case 0x60: + case 0x65: + insn.itype = HPPA_rfi; + break; + case 0x6B: + insn.itype = HPPA_ssm; +RSM_SSM: + opi(insn.Op1, (code>>16)&0x3FF); + opr(insn.Op2, r27(code)); + break; + case 0x73: + insn.itype = HPPA_rsm; + goto RSM_SSM; + case 0xC3: + insn.itype = HPPA_mtsm; + opr(insn.Op1, r11(code)); + break; + case 0x85: + insn.itype = HPPA_ldsid; + opbs(insn, insn.Op1, (code>>14)&3, r06(code)); + opr(insn.Op2, r27(code)); + break; + case 0xC1: + insn.itype = HPPA_mtsp; + opr(insn.Op1, r11(code)); + opr(insn.Op2, SR0+((code>>13)&7)); + break; + case 0x25: + insn.itype = HPPA_mfsp; + opr(insn.Op1, SR0+((code>>13)&7)); + opr(insn.Op2, r27(code)); + break; + case 0xA5: + insn.itype = HPPA_mfia; + opr(insn.Op1, r27(code)); + break; + case 0xC2: + insn.itype = HPPA_mtctl; + opr(insn.Op1, r11(code)); + opr(insn.Op2, CR0+r06(code)); + break; + case 0xC6: + if ( r06(code) != 0xB ) + return 0; + insn.itype = HPPA_mtsarcm; + opr(insn.Op1, r11(code)); + break; + case 0x45: + insn.itype = HPPA_mfctl; + opr(insn.Op1, CR0+r06(code)); + opr(insn.Op2, r27(code)); + break; + default: + return 0; + } + break; + + case 0x01: + if ( code & BIT19 ) + { + switch ( (code>>6) & 0xFF ) + { + case 0x60: + insn.itype = HPPA_idtlbt; + opr(insn.Op1, CR0+r06(code)); + opr(insn.Op2, r27(code)); + break; + case 0x48: + case 0x58: + insn.itype = HPPA_pdtlb; + goto PDT; + case 0x49: + insn.itype = HPPA_pdtlbe; +PDT: + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); + break; + case 0x4A: + insn.itype = HPPA_fdc; + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); + break; + case 0xCA: + insn.itype = HPPA_fdc; + opds(insn, insn.Op1, (code>>14)&3, r06(code), ls5(r11(code)), dt_dword); + if ( code & BIT26 ) + return 0; + break; + case 0x4B: + insn.itype = HPPA_fdce; + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); + break; + case 0x4E: + insn.itype = HPPA_pdc; + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); + break; + case 0x4F: + insn.itype = HPPA_fic; + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); + break; + case 0x46: + case 0x47: + insn.itype = HPPA_probe; + opbs(insn, insn.Op1, (code>>14)&3, r06(code)); + opr(insn.Op2, r11(code)); + opr(insn.Op3, r27(code)); + break; + case 0xC6: + case 0xC7: + insn.itype = HPPA_probei; + opbs(insn, insn.Op1, (code>>14)&3, r06(code)); + opi(insn.Op2, r11(code)); + opr(insn.Op3, r27(code)); + break; + case 0x4D: + insn.itype = HPPA_lpa; +MAKE_LPA: + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dt_dword); + opr(insn.Op2, r27(code)); + break; + case 0x4C: + insn.itype = HPPA_lci; + if ( code & BIT26 ) + return 0; + goto MAKE_LPA; + default: + return 0; + } + } + else + { + switch ( (code>>6) & 0x7F ) + { + case 0x20: + insn.itype = HPPA_iitlbt; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + break; + case 0x18: + case 0x08: + insn.itype = HPPA_pitlb; +PIT: + opxs(insn, insn.Op1, as3((code>>13)&7), r06(code), r11(code), dt_dword); + insn.auxpref |= aux_space; + break; + case 0x09: + insn.itype = HPPA_pitlbe; + goto PIT; + case 0x0A: + insn.itype = HPPA_fic; + goto PIT; + case 0x0B: + insn.itype = HPPA_fice; + goto PIT; + default: + return 0; + } + } + break; + + case 0x02: + insn.auxpref = (code>>13) & aux_cndc; // condition + insn.itype = find_itype(C5, (code>>6)&0x3F); + switch ( insn.itype ) + { + default: + // case HPPA_add: + // case HPPA_sub: + // case HPPA_ds: + // case HPPA_and: + // case HPPA_andcm: + // case HPPA_or: + // case HPPA_xor: + // case HPPA_uxor: + // case HPPA_cmpclr: + // case HPPA_uaddcm: + // case HPPA_hadd: + // case HPPA_hsub: + // case HPPA_havg: + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + opr(insn.Op3, r27(code)); + break; + case HPPA_dcor: + opr(insn.Op1, r06(code)); + opr(insn.Op2, r27(code)); + break; + case HPPA_shladd: + opr(insn.Op1, r11(code)); + opi(insn.Op2, (code>>6)&3); + if ( ((code>>6) & 3) == 0 ) + return 0; + opr(insn.Op3, r06(code)); + opr(insn.Op4, r27(code)); + break; + case HPPA_hshladd: + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + if ( ((code>>6) & 3) == 0 ) + return 0; + if ( insn.auxpref ) + return 0; // condition should be never + opi(insn.Op3, (code>>6)&3); + opr(insn.Op4, r27(code)); + break; + } + break; + + case 0x03: + { + int idx = (code>>6) & 0xF; + if ( (code & BIT19) == 0 && idx > 7 ) + return 0; + insn.itype = C6[idx].itype; + dtype = C6[idx].dtype; + if ( code & BIT19 ) // short + { + if ( idx > 7 ) // store + { + opr(insn.Op1, r11(code)); + opds(insn, insn.Op2, (code>>14)&3, r06(code), ls5(r27(code)), dtype); + } + else // load + { + opds(insn, insn.Op1, (code>>14)&3, r06(code), ls5(r11(code)), dtype); + opr(insn.Op2, r27(code)); + } + } + else // index + { + opxs(insn, insn.Op1, (code>>14)&3, r06(code), r11(code), dtype); + opr(insn.Op2, r27(code)); + } + if ( (idx & 7) == 6 ) + insn.auxpref &= ~aux_space; // ldwa, stwa + } + break; + + case 0x04: + switch ( (code>>9) & 3 ) + { + case 0: + insn.itype = HPPA_spop0; + break; + case 1: + insn.itype = HPPA_spop1; + opr(insn.Op1, r27(code)); + break; + case 2: + insn.itype = HPPA_spop2; + opr(insn.Op1, r06(code)); + break; + case 3: + insn.itype = HPPA_spop3; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + break; + } + break; + + case 0x05: // diag + opi(insn.Op1, code & 0x3FFFFFF); + break; + + case 0x06: // fmpyadd + case 0x26: // fmpysub + { + bool d = !((code>>5) & 1); + opr(insn.Op1, mfr(r06(code),d)); + opr(insn.Op2, mfr(r11(code),d)); + opr(insn.Op3, mfr(r27(code),d)); + opr(insn.Op4, mfr((code>>6)&0x1F,d)); + opr(insn.Op5, mfr((code>>11)&0x1F,d)); + } + break; + + case 0x07: + return 0; + + case 0x08: // ldil + opi(insn.Op1, as21(code & 0x1FFFFF)); + opr(insn.Op2, r06(code)); + break; + + case 0x09: // cldw, cstw, fstd, fstw + case 0x0B: // cldd, cstd, fldd, fldw + { + op_t *x; + int uid = (code>> 6) & 7; + if ( code & BIT22 ) + { + insn.itype = HPPA_cstd; + opr(insn.Op1, r27(code)); + x = &insn.Op2; + if ( uid < 2 ) + { + insn.itype = HPPA_fstd; + insn.Op1.reg += F0 + ((code>>1)&0x20); + } + } + else + { + insn.itype = HPPA_cldd; + opr(insn.Op2, r27(code)); + x = &insn.Op1; + if ( uid < 2 ) + { + insn.itype = HPPA_fldd; + insn.Op2.reg += F0 + ((code>>1)&0x20); + } + } + dtype = dt_qword; + if ( op == 0x09 ) + { + insn.itype++; // cldw, cstw + dtype = dt_dword; + } + if ( code & BIT19 ) + opds(insn, *x, (code>>14)&3, r06(code), ls5(r11(code)), dtype); + else + opxs(insn, *x, (code>>14)&3, r06(code), r11(code), dtype); + } + break; + + case 0x0A: // addil + opi(insn.Op1, as21(code & 0x1FFFFF)); + opr(insn.Op2, r06(code)); + opr(insn.Op3, R1); + break; + + case 0x0C: // copr + handle_float_0C(insn, code); + break; + + case 0x0D: // ldo + if ( getseg(insn.ea)->is_64bit() ) + dtype = dt_qword; + opd(insn.Op1, r06(code), s16(get_ldo(code)), dtype); + opr(insn.Op2, r11(code)); + break; + + case 0x0E: + handle_float_0E(insn, code); + break; + + case 0x0F: + return 0; + + case 0x10: // ldb + case 0x11: // ldh + case 0x12: // ldw + case 0x13: // ldw (mod) + { + int s = (code>>14) & 3; + opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,code & 0x3FFF)), dtype); + opr(insn.Op2, r11(code)); + } + break; + + case 0x14: + { + int s = (code>>14) & 3; + insn.itype = (code & BIT30) ? HPPA_fldd : HPPA_ldd; + int im10a = ((code>>3) & 0x7FE) | (code & 1); + opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,im10a)), dtype); + opr(insn.Op2, r11(code)); + if ( code & BIT30 ) + insn.Op2.reg += F0; + } + break; + + case 0x1C: + { + int s = (code>>14) & 3; + insn.itype = (code & BIT30) ? HPPA_fstd : HPPA_std; + int im10a = ((code>>3) & 0x7FE) | (code & 1); + opr(insn.Op1, r11(code)); + if ( code & BIT30 ) + insn.Op1.reg += F0; + opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,im10a)), dtype); + } + break; + + case 0x16: + case 0x17: + { + int s = (code>>14) & 3; + insn.itype = op & 1 && (code & BIT29) ? HPPA_ldw : HPPA_fldw; + int im11a = ((code>>3) & 0xFFE) | (code & 1); + opds(insn, insn.Op1, s, r06(code), s16(assemble_16(s,im11a)), dtype); + opr(insn.Op2, r11(code)); + if ( code & BIT29 ) + insn.Op2.reg += F0 + ((code<<4) & 0x20); + } + break; + + case 0x1E: + case 0x1F: + { + int s = (code>>14) & 3; + insn.itype = op & 1 && (code & BIT29) ? HPPA_stw : HPPA_fstw; + int im11a = ((code>>3) & 0xFFE) | (code & 1); + opr(insn.Op1, r11(code)); + if ( code & BIT29 ) + insn.Op1.reg += F0 + ((code<<4) & 0x20); + opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,im11a)), dtype); + } + break; + + case 0x18: // stb + case 0x19: // sth + case 0x1A: // stw + case 0x1B: // stw (mod) + { + int s = (code>>14) & 3; + opr(insn.Op1, r11(code)); + opds(insn, insn.Op2, s, r06(code), s16(assemble_16(s,code & 0x3FFF)), dtype); + } + break; + + case 0x15: + case 0x1D: + return 0; + + case 0x20: // cmpb + case 0x22: // cmpb + case 0x27: // cmpb + case 0x2F: // cmpb + case 0x28: // addb + case 0x2A: // addb + case 0x32: // movb + insn.auxpref = (code>>13) & aux_cndc; // condition + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip); + break; + + case 0x21: // cmpib + case 0x23: // cmpib + case 0x3B: // cmpib + case 0x29: // addib + case 0x2B: // addib + case 0x33: // movib + insn.auxpref = (code>>13) & aux_cndc; // condition + opi(insn.Op1, ls5(r11(code))); + opr(insn.Op2, r06(code)); + opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip); + break; + + case 0x24: // cmpiclr + case 0x25: // subi + case 0x2C: // addi + case 0x2D: // addi + insn.auxpref = (code>>13) & aux_cndc; // condition + opi(insn.Op1, ls11(code & 0x7FF)); + opr(insn.Op2, r06(code)); + opr(insn.Op3, r11(code)); + break; + + case 0x2E: + { + insn.itype = (code & BIT26) ? HPPA_fmpynfadd : HPPA_fmpyfadd; + bool d = (code>>11) & 1; + opr(insn.Op1, mfr(r06(code),d)); + opr(insn.Op2, mfr(r11(code),d)); + int ra = ((code>>10) & 0x38) | ((code>>8) & 0x7); + opr(insn.Op3, F0+ra); + opr(insn.Op4, mfr(r27(code),d)); + } + break; + + case 0x30: // bb + case 0x31: + opr(insn.Op1, r11(code)); + if ( op & 1 ) + { + int pos = r06(code) | ((code>>8) & 0x20); + opi(insn.Op2, pos); + } + else + { + opr(insn.Op2, CR11); + } + opn(insn.Op3, s12(get11(code)|((code&1)<<11)), insn.ip); + break; + + case 0x34: + insn.auxpref = (code>>13) & aux_cndc; // condition + switch ( (code>>11) & 3 ) // bits 19, 20 + { + case 0: + if ( (code & BIT21) == 0 ) // format 11 + { + insn.itype = (code & BIT22) ? HPPA_shrpd : HPPA_shrpw; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + opr(insn.Op3, CR11); + opr(insn.Op4, r27(code)); + break; + } + // no break + case 1: // format 14 + { + insn.itype = (code & BIT21) ? HPPA_shrpd : HPPA_shrpw; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + int sa = (insn.itype == HPPA_shrpd ? 63 : 31) - (r22(code)|((code>>10)&1)); + opi(insn.Op3, sa); + opr(insn.Op4, r27(code)); + } + break; + case 2: // format 12 + { + insn.itype = (code & BIT22) ? HPPA_extrd : HPPA_extrw; + opr(insn.Op1, r06(code)); + opr(insn.Op2, CR11); + int cl = (code>>3) & 0x20; + if ( (code & BIT22) == 0 && cl ) + return 0; + opi(insn.Op3, (32-r27(code))|cl); + opr(insn.Op4, r11(code)); + } + break; + case 3: // format 15 + insn.itype = HPPA_extrw; + opr(insn.Op1, r06(code)); + opi(insn.Op2, r22(code)); + opi(insn.Op3, 32-r27(code)); + opr(insn.Op4, r11(code)); + break; + } + break; + + case 0x35: + insn.auxpref = (code>>13) & aux_cndc; // condition + if ( code & BIT20 ) // format 16 + { + if ( code & BIT19 ) + { + insn.itype = HPPA_depwi; + opi(insn.Op1, ls5(r11(code))); + } + else + { + insn.itype = HPPA_depw; + opr(insn.Op1, r11(code)); + } + opi(insn.Op2, 31-r22(code)); + opi(insn.Op3, 32-r27(code)); + opr(insn.Op4, r06(code)); + } + else // format 13 + { + if ( code & BIT19 ) + { + insn.itype = (code & BIT22) ? HPPA_depdi : HPPA_depwi; + opi(insn.Op1, ls5(r11(code))); + opr(insn.Op2, CR11); + } + else + { + insn.itype = (code & BIT22) ? HPPA_depd : HPPA_depw; + opr(insn.Op1, r11(code)); + opr(insn.Op2, CR11); + } + int cl = (code>>3) & 0x20; + if ( (code & BIT22) == 0 && cl ) + return 0; + opi(insn.Op3, (32-r27(code))|cl); + opr(insn.Op4, r06(code)); + } + break; + + case 0x36: // extrd + { + insn.auxpref = (code>>13) & aux_cndc; // condition + opr(insn.Op1, r06(code)); + opi(insn.Op2, ((code>>6)&0x20)|r22(code)); + int cl = (code>>7) & 0x20; + opi(insn.Op3, (32-r27(code))|cl); + opr(insn.Op4, r11(code)); + } + break; + + case 0x37: + return 0; + + case 0x38: // be + case 0x39: // be + { + int32 w = get17(code); + opds(insn, insn.Op1, as3((code>>13)&7), r06(code), s17(w)<<2, dt_code); + insn.auxpref |= aux_space; + if ( op & 1 ) + { + opr(insn.Op2, SR0); + opr(insn.Op3, R31); + } + } + break; + + case 0x3A: + { + int sub = (code>>13) & 7; + switch ( sub ) + { + case 0x2: + if ( code & BIT19 ) + return 0; + insn.itype = HPPA_blr; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + break; + case 0x6: + insn.itype = (code & BIT19) ? HPPA_bve : HPPA_bv; + if ( insn.itype == HPPA_bv ) + opx(insn.Op1, r06(code), r11(code), dt_code); + else + opb(insn.Op1, r06(code)); + break; + case 0x7: + if ( !(code & BIT19) ) + return 0; + insn.itype = HPPA_bve; + opb(insn.Op1, r06(code)); + opr(insn.Op1, R2); + break; + case 0x0: + case 0x1: + { + insn.itype = HPPA_b; + int32 w = get17(code); + opn(insn.Op1, s17(w), insn.ip); + opr(insn.Op2, r06(code)); + } + break; + case 0x4: + case 0x5: + { + insn.itype = HPPA_b; + int32 w = ((code&1) << 21) + | (r06(code) << 16) + | (r11(code) << 11) + | get11(code); + opn(insn.Op1, s22(w), insn.ip); + opr(insn.Op2, R2); + } + break; + } + } + break; + + case 0x3C: + insn.itype = HPPA_depd; + opr(insn.Op1, r11(code)); +DEPD: + opi(insn.Op2, (32-r22(code))|((code>>7)&0x20)); + opi(insn.Op3, r27(code)); + opr(insn.Op4, r06(code)); + insn.auxpref = (code>>13) & aux_cndc; // condition + break; + + case 0x3D: + insn.itype = HPPA_depdi; + opi(insn.Op1, ls5(r11(code))); + goto DEPD; + + case 0x3E: + if ( code & BIT16 ) + { + switch ( (code>>10) & 3 ) + { + case 0: + insn.itype = HPPA_mixw; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + opr(insn.Op3, r27(code)); + break; + case 1: + insn.itype = HPPA_mixh; + opr(insn.Op1, r11(code)); + opr(insn.Op2, r06(code)); + opr(insn.Op3, r27(code)); + break; + case 2: + if ( ((code>>13)&3) == 0 ) + { + insn.itype = HPPA_hshl; + opr(insn.Op1, r11(code)); + opi(insn.Op2, (code>>6) & 0xF); + opr(insn.Op3, r27(code)); + break; + } + // no break; + case 3: + insn.itype = HPPA_hshr; + opr(insn.Op1, r06(code)); + opi(insn.Op2, (code>>6) & 0xF); + opr(insn.Op3, r27(code)); + break; + default: + return 0; + } + } + else + { + insn.itype = HPPA_permh; + if ( r06(code) != r11(code) ) + return 0; + opr(insn.Op1, r06(code)); + opr(insn.Op2, r27(code)); + } + break; + + case 0x3F: + return 0; + + default: + interr(insn, "ana"); + } + if ( insn.itype == 0 ) + return 0; + + if ( dosimple() ) + simplify(insn, code); + + char buf[80]; + if ( !build_insn_completer(insn, code, buf, sizeof(buf)) ) + return 0; + + return insn.size; +} + +//-------------------------------------------------------------------------- +void interr(const insn_t &insn, const char *module) +{ + const char *name = NULL; + if ( insn.itype < HPPA_last ) + name = Instructions[insn.itype].name; + warning("%a(%s): internal error in %s", insn.ea, name, module); +} + diff --git a/idasdk75/module/hppa/emu.cpp b/idasdk76/module/hppa/emu.cpp similarity index 100% rename from idasdk75/module/hppa/emu.cpp rename to idasdk76/module/hppa/emu.cpp diff --git a/idasdk76/module/hppa/hppa.hpp b/idasdk76/module/hppa/hppa.hpp new file mode 100644 index 0000000..37a6999 --- /dev/null +++ b/idasdk76/module/hppa/hppa.hpp @@ -0,0 +1,241 @@ + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _HPPA_HPP +#define _HPPA_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <segregs.hpp> +#include <typeinf.hpp> +#include <diskio.hpp> +#include <fixup.hpp> + +#define PROCMOD_NAME hppa +#define PROCMOD_NODE_NAME "$ hppa" + +//------------------------------------------------------------------ +#define PROC_MAXOP 5 // max number of operands +CASSERT(PROC_MAXOP <= UA_MAXOP); + +#define aux_cndc 0x0007 // condition bits c +#define aux_cndf 0x0008 // condition bits f +#define aux_cndd 0x0010 // condition bits d +#define aux_space 0x0020 // space register present + +#define o_based o_idpspec2 // (%r5) + // o_phrase: %r4(%r5) + // o_displ: 55(%r5) +#define sid specflag1 +#define secreg specflag2 // for o_phrase, the index register +//------------------------------------------------------------------ +enum RegNo +{ + // general registers + R0, R1, R2, R3, R4, R5, R6, R7, + R8, R9, R10, R11, R12, R13, R14, R15, + R16, R17, R18, R19, R20, R21, R22, R23, + R24, R25, R26, DP, R28, R29, SP, R31, + // space registers + SR0, SR1, SR2, SR3, SR4, SR5, SR6, SR7, + // control registers + CR0, CR1, CR2, CR3, CR4, CR5, CR6, CR7, + CR8, CR9, CR10, CR11, CR12, CR13, CR14, CR15, + CR16, CR17, CR18, CR19, CR20, CR21, CR22, CR23, + CR24, CR25, CR26, CR27, CR28, CR29, CR30, CR31, + // floating-point registers + F0, F1, F2, F3, F4, F5, F6, F7, + F8, F9, F10, F11, F12, F13, F14, F15, + F16, F17, F18, F19, F20, F21, F22, F23, + F24, F25, F26, F27, F28, F29, F30, F31, + // register halves (valid only for fmpyadd/sub) + F16L, F17L, F18L, F19L, F20L, F21L, F22L, F23L, + F24L, F25L, F26L, F27L, F28L, F29L, F30L, F31L, + F16R, F17R, F18R, F19R, F20R, F21R, F22R, F23R, + F24R, F25R, F26R, F27R, F28R, F29R, F30R, F31R, + // condition bits + CA0, CA1, CA2, CA3, CA4, CA5, CA6, + + DPSEG, rVcs, rVds, // virtual registers for code and data segments +}; + +//------------------------------------------------------------------ +// Bit definitions. +// Note that the bit order is unusual: the LSB is BIT31 +// This is a so-called big-endian bit order. +#define BIT31 0x00000001L +#define BIT30 0x00000002L +#define BIT29 0x00000004L +#define BIT28 0x00000008L +#define BIT27 0x00000010L +#define BIT26 0x00000020L +#define BIT25 0x00000040L +#define BIT24 0x00000080L +#define BIT23 0x00000100L +#define BIT22 0x00000200L +#define BIT21 0x00000400L +#define BIT20 0x00000800L +#define BIT19 0x00001000L +#define BIT18 0x00002000L +#define BIT17 0x00004000L +#define BIT16 0x00008000L +#define BIT15 0x00010000L +#define BIT14 0x00020000L +#define BIT13 0x00040000L +#define BIT12 0x00080000L +#define BIT11 0x00100000L +#define BIT10 0x00200000L +#define BIT9 0x00400000L +#define BIT8 0x00800000L +#define BIT7 0x01000000L +#define BIT6 0x02000000L +#define BIT5 0x04000000L +#define BIT4 0x08000000L +#define BIT3 0x10000000L +#define BIT2 0x20000000L +#define BIT1 0x40000000L +#define BIT0 0x80000000L + +//------------------------------------------------------------------ +ea_t calc_mem(ea_t ea); // map virtual to phisycal ea + +typedef int proc_t; +const proc_t PROC_HPPA = 0; // HPPA big endian + +//------------------------------------------------------------------ +void interr(const insn_t &insn, const char *module); + +void idaapi hppa_header(outctx_t &ctx); + +void idaapi hppa_segend(outctx_t &ctx, segment_t *seg); + +int idaapi is_align_insn(ea_t ea); +int idaapi hppa_get_frame_retsize(const func_t *); + +int idaapi is_sp_based(const insn_t &insn, const op_t &x); +int is_sane_insn(const insn_t &insn, int nocrefs); +int may_be_func(const insn_t &insn); // can a function start here? +bool is_basic_block_end(const insn_t &insn); + +//-------------------------------------------------------------------------- +// functions to get various fields from the instruction code +inline int opcode(uint32 code) { return (code>>26) & 0x3F; } +inline int r06(uint32 code) { return (code>>21) & 0x1F; } +inline int r11(uint32 code) { return (code>>16) & 0x1F; } +inline int r22(uint32 code) { return (code>> 5) & 0x1F; } +inline int r27(uint32 code) { return (code>> 0) & 0x1F; } +inline int get11(uint32 code) // 11bit field for branches +{ + return ((code>>3) & 0x3FF) | ((code&4)<<(10-2)); +} +inline int32 get17(uint32 code) +{ + return ((code&1) << 16) + | (r11(code) << 11) + | get11(code); +} +inline sval_t as21(uint32 x) +{ + // 1 2 + // 012345678901234567890 bit number + // 2 1 + // 098765432109876543210 shift amount + x = (((x>>12) & 0x003) << 0) // 2: x{7..8} + | (((x>>16) & 0x01F) << 2) // 5: x{0..4} + | (((x>>14) & 0x003) << 7) // 2: x{5..6} + | (((x>> 1) & 0x7FF) << 9) // 11: x{9..19} + | (((x>> 0) & 0x001) <<20); // 1: x{20} + return int32(x << 11); +} +//-------------------------------------------------------------------------- +// type system functions +bool calc_hppa_arglocs(func_type_data_t *fti); +int use_hppa_regarg_type(ea_t ea, const funcargvec_t &rargs); +void use_hppa_arg_types( + ea_t ea, + func_type_data_t *fti, + funcargvec_t *rargs); + +//-------------------------------------------------------------------------- +struct hppa_cf_t; +struct hppa_t : public procmod_t +{ + // altval(-1) -> idpflags + // altval(ea) -> function frame register or 0 + netnode helper; + + ioports_t syscalls; + +#define IDP_SIMPLIFY 0x0001 // simplify instructions +#define IDP_PSW_W 0x0002 // W-bit in PSW is set +#define IDP_MNEMONIC 0x0004 // use mnemonic register names + ushort idpflags = IDP_SIMPLIFY; + inline bool dosimple(void) { return (idpflags & IDP_SIMPLIFY) != 0; } + inline bool psw_w(void) { return (idpflags & IDP_PSW_W) != 0; } + inline bool mnemonic(void) { return (idpflags & IDP_MNEMONIC) != 0; } + inline int assemble_16(int x, int y) + { + if ( psw_w() ) + { + int r = 0; + if ( y & 1 ) + { + x ^= 3; + r = 0x8000; + } + return ((y>>1) & 0x1FFF) | (x<<13) | r; + } + return ((y>>1) & 0x1FFF) | ((y&1) ? 0xE000 : 0); + } + inline int get_ldo(uint32 code) { return assemble_16((code>>14)&3,code & 0x3FFF); } + + int ptype = 0; // processor type + ea_t got = BADADDR; + // custom fixups and refinfo + hppa_cf_t *hppa_cf = nullptr; + + bool flow = false; + ea_t oldea = BADADDR; + int oldreg = -1; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *get_syscall_name(int syscall); + const char *set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + void handle_new_flags(bool save=true); + void init_custom_refs(); + void term_custom_refs(); + void setup_got(void); + int ana(insn_t *_insn); + int emu(const insn_t &insn); + bool is_frreg(const insn_t &insn, int reg); + void process_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload); + void trace_sp(const insn_t &insn); + bool create_func_frame(func_t *pfn); + void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); + ea_t get_dp(const insn_t &insn) const; + ea_t calc_possible_memref(const insn_t &insn, const op_t &x); + uval_t idaapi r11_get_value(const fixup_handler_t * /*fh*/, ea_t ea); + char *build_insn_completer(const insn_t &insn, uint32 code, char *buf, size_t bufsize); + void hppa_assumes(outctx_t &ctx); // function to produce assume directives + void hppa_segstart(outctx_t &ctx, segment_t *Srange) const; + void hppa_footer(outctx_t &ctx) const; + void use_hppa_arg_types(ea_t ea, func_type_data_t *fti, funcargvec_t *rargs); + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); +}; +extern int data_id; + +#endif // _HPPA_HPP diff --git a/idasdk76/module/hppa/hppa_cfh.cpp b/idasdk76/module/hppa/hppa_cfh.cpp new file mode 100644 index 0000000..e7c005a --- /dev/null +++ b/idasdk76/module/hppa/hppa_cfh.cpp @@ -0,0 +1,248 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +// This file contains custom fixup handlers for simplified fixups with high +// and low parts. The word "simplified" means that we don't use LR and RR +// rounding modes as prescribed in the documentation. We replace them by " +// and R rounding modes. +// They are used for the relocations: +// - R_PARISC_DIR21L, R_PARISC_DPREL21L +// - R_PARISC_DIR14R, R_PARISC_DPREL14R + +#include <fixup.hpp> + +//-------------------------------------------------------------------------- +static uval_t idaapi l21_get_value(const fixup_handler_t * /*fh*/, ea_t ea) +{ + uint32 insn = get_dword(ea); + // extract `im21' from "Long immediate" instruction + return as21(insn); +} + +//---------------------------------------------------------------------------- +static bool idaapi l21_patch_value( + const fixup_handler_t * /*fh*/, + ea_t ea, + const fixup_data_t &fd) +{ + uint32 insn = get_dword(ea); + ea_t expr = fd.off + fd.displacement; + // 33222222222211111111110000000000 + // 10987654321098765432109876543210 + // abbbbbbbbbbbccdddddee___________ expr + // ___________dddddcceebbbbbbbbbbba insn + // 10987654321098765432109876543210 + uint32 im21 = (((expr >> 31) & 0x001) << 0) // a + | (((expr >> 20) & 0x7FF) << 1) // b + | (((expr >> 18) & 0x003) << 14) // c + | (((expr >> 13) & 0x01F) << 16) // d + | (((expr >> 11) & 0x003) << 12); // e + put_dword(ea, (insn & 0xFFE00000) | im21); + return true; +} + +//-------------------------------------------------------------------------- +static bool idaapi l21_calc_reference_data( + ea_t *target, + ea_t *base, + ea_t /*from*/, + const refinfo_t &ri, + adiff_t opval) +{ + if ( ri.target == BADADDR + || ri.base == BADADDR + || ri.is_subtract() ) + { + return false; + } + ea_t fullvalue = ri.target + ri.tdelta - ri.base; + uint32 calc_opval = fullvalue & 0xFFFFF800; + if ( calc_opval != uint32(opval) ) + return false; + + *target = ri.target; + *base = ri.base; + return true; +} + +//-------------------------------------------------------------------------- +static void idaapi l21_get_format(qstring *format) +{ + *format = COLSTR("l%%%s", SCOLOR_KEYWORD); +} + +//-------------------------------------------------------------------------- +static const custom_refinfo_handler_t ref_l21 = +{ + sizeof(custom_refinfo_handler_t), + "L21", + "right-justified, high-order 21 bits", + 0, // properties (currently 0) + NULL, // gen_expr + l21_calc_reference_data, // calc_reference_data + l21_get_format, // get_format +}; + + +//-------------------------------------------------------------------------- +// we use the R rounding mode (11-bit) in this fixup +// but here we return the full immediated value (14-bit or 16-bit) +static uval_t idaapi r11_get_value(const fixup_handler_t * /*fh*/, ea_t ea) +{ + hppa_t &pm = *GET_MODULE_DATA(hppa_t); + uint32 insn = get_dword(ea); + // extract `im14' from "Load/Store" instruction + return sval_t(int16(pm.get_ldo(insn))); +} + +//---------------------------------------------------------------------------- +static bool idaapi r11_patch_value( + const fixup_handler_t * /*fh*/, + ea_t ea, + const fixup_data_t &fd) +{ + hppa_t &pm = *GET_MODULE_DATA(hppa_t); + uint32 insn = get_dword(ea); + // we use the R rounding mode (11-bit) in this fixup + ea_t expr = (fd.off + fd.displacement) & 0x7FF; + if ( pm.psw_w() ) + { + // 33222222222211111111110000000000 + // 10987654321098765432109876543210 + // ________________abbccccccccccccc expr + // ________________BBccccccccccccca insn + // 10987654321098765432109876543210 + // B = a == 0 ? b : ~b; + uint32 a = (expr >> 15) & 0x0001; + uint32 b = (expr >> 13) & 0x0003; + if ( a != 0 ) //-V547 'a != 0' is always false + b = ~b; + uint32 c = expr & 0x1FFF; + uint32 im16 = a | (b << 14) | (c << 1); + put_dword(ea, (insn & 0xFFFF0000) | im16); + } + else + { + // 33222222222211111111110000000000 + // 10987654321098765432109876543210 + // __________________abbbbbbbbbbbbb expr + // __________________bbbbbbbbbbbbba insn + // 10987654321098765432109876543210 + uint32 im14 = (((expr >> 13) & 0x0001) << 0) // a + | ((expr & 0x1FFF) << 1); // b + put_dword(ea, (insn & 0xFFFFC000) | im14); + } + return true; +} + +//-------------------------------------------------------------------------- +static bool idaapi r11_calc_reference_data( + ea_t *target, + ea_t *base, + ea_t /*from*/, + const refinfo_t &ri, + adiff_t opval) +{ + if ( ri.target == BADADDR + || ri.base == BADADDR + || ri.is_subtract() ) + { + return false; + } + ea_t fullvalue = ri.target + ri.tdelta - ri.base; + uint32 calc_opval = fullvalue & 0x7FF; + if ( calc_opval != uint32(opval) ) + return false; + + *target = ri.target; + *base = ri.base; + return true; +} + +//-------------------------------------------------------------------------- +static void idaapi r11_get_format(qstring *format) +{ + *format = COLSTR("r%%%s", SCOLOR_KEYWORD); +} + +//-------------------------------------------------------------------------- +static const custom_refinfo_handler_t ref_r11 = +{ + sizeof(custom_refinfo_handler_t), + "R11", + "low-order 11 bits", + 0, // properties (currently 0) + NULL, // gen_expr + r11_calc_reference_data, // calc_reference_data + r11_get_format, // get_format +}; + +//-------------------------------------------------------------------------- +struct hppa_cf_t +{ + fixup_handler_t cfh_l21 = + { + sizeof(fixup_handler_t), + "L21", // name + FHF_CODE // verify that fixup points to code + | FHF_FORCE_CODE, // convert unknonw item to code + 4, 0, 0, 0, // size, width, shift + REFINFO_CUSTOM, // reftype + NULL, // apply + l21_get_value, // get_value + l21_patch_value, // patch_value + }; + + fixup_handler_t cfh_r11 = + { + sizeof(fixup_handler_t), + "R11", // name + FHF_CODE // verify that fixup points to code + | FHF_FORCE_CODE, // convert unknonw item to code + 4, 0, 0, 0, // size, width, shift + REFINFO_CUSTOM, // reftype + NULL, // apply + r11_get_value, // get_value + r11_patch_value, // patch_value + }; + + fixup_type_t cfh_l21_id = 0; // ids of fixup handlers + fixup_type_t cfh_r11_id = 0; + int ref_l21_id = 0; // ids of refinfo handlers + int ref_r11_id = 0; +}; + +//-------------------------------------------------------------------------- +void hppa_t::init_custom_refs() +{ + if ( hppa_cf == nullptr ) + { + hppa_cf = new hppa_cf_t; + hppa_cf->cfh_l21_id = register_custom_fixup(&hppa_cf->cfh_l21); + hppa_cf->cfh_r11_id = register_custom_fixup(&hppa_cf->cfh_r11); + hppa_cf->ref_l21_id = register_custom_refinfo(&ref_l21); + hppa_cf->ref_r11_id = register_custom_refinfo(&ref_r11); + hppa_cf->cfh_l21.reftype = REFINFO_CUSTOM | hppa_cf->ref_l21_id; + hppa_cf->cfh_r11.reftype = REFINFO_CUSTOM | hppa_cf->ref_r11_id; + } +} + +//-------------------------------------------------------------------------- +void hppa_t::term_custom_refs() +{ + if ( hppa_cf != nullptr ) + { + hppa_cf->cfh_l21.reftype = REFINFO_CUSTOM; + hppa_cf->cfh_r11.reftype = REFINFO_CUSTOM; + unregister_custom_refinfo(hppa_cf->ref_r11_id); + unregister_custom_refinfo(hppa_cf->ref_l21_id); + unregister_custom_fixup(hppa_cf->cfh_r11_id); + unregister_custom_fixup(hppa_cf->cfh_l21_id); + delete hppa_cf; + hppa_cf = nullptr; + } +} diff --git a/idasdk75/module/hppa/hpux.cfg b/idasdk76/module/hppa/hpux.cfg similarity index 100% rename from idasdk75/module/hppa/hpux.cfg rename to idasdk76/module/hppa/hpux.cfg diff --git a/idasdk75/module/hppa/ins.cpp b/idasdk76/module/hppa/ins.cpp similarity index 100% rename from idasdk75/module/hppa/ins.cpp rename to idasdk76/module/hppa/ins.cpp diff --git a/idasdk76/module/hppa/ins.hpp b/idasdk76/module/hppa/ins.hpp new file mode 100644 index 0000000..45e032f --- /dev/null +++ b/idasdk76/module/hppa/ins.hpp @@ -0,0 +1,174 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ +HPPA_null = 0, // Unknown Operation + +HPPA_add, // Add +HPPA_addb, // Add and Branch +HPPA_addi, // Add to Immediate +HPPA_addib, // Add Immediate and Branch +HPPA_addil, // Add to Immediate Left +HPPA_and, // AND +HPPA_andcm, // AND complement +HPPA_b, // Branch +HPPA_bb, // Branch on Bit +HPPA_be, // Branch External +HPPA_blr, // Branch and Link Register +HPPA_break, // Break +HPPA_bv, // Branch Vectored +HPPA_bve, // Branch Vectored External +HPPA_cldd, // Coprocessor Load Doubleword +HPPA_cldw, // Coprocessor Load Word +HPPA_clrbts, // Clear Branch Target Stack +HPPA_cmpb, // Compare and Branch +HPPA_cmpclr, // Compare and Clear +HPPA_cmpib, // Compare Immediate and Branch +HPPA_cmpiclr, // Compare Immediate and Clear +HPPA_copr, // Coprocessor Operation +HPPA_cstd, // Coprocessor Store Doubleword +HPPA_cstw, // Coprocessor Store Word +HPPA_dcor, // Decimal Correct +HPPA_depd, // Deposit Doubleword +HPPA_depdi, // Deposit Doubleword Immediate +HPPA_depw, // Deposit Word +HPPA_depwi, // Deposit Word Immediate +HPPA_diag, // Diagnose +HPPA_ds, // Divide Step +HPPA_extrd, // Extract Doubleword +HPPA_extrw, // Extract Word +HPPA_fdc, // Flush Data Cache +HPPA_fdce, // Flush Data Cache Entry +HPPA_fic, // Flush Instruction Cache +HPPA_fice, // Flush Instruction Cache Entry +HPPA_hadd, // Halfword Parallel Add +HPPA_havg, // Halfword Parallel Average +HPPA_hshl, // Halfword Parallel Shift Left +HPPA_hshladd, // Halfword Parallel Shift Left and Add +HPPA_hshr, // Halfword Parallel Shift Right +HPPA_hshradd, // Halfword Parallel Shift Right and Add +HPPA_hsub, // Halfword Parallel Subtract +HPPA_idtlbt, // Insert Data TLB Translation +HPPA_iitlbt, // Insert Instruction TLB Translation +HPPA_lci, // Load Coherence Index +HPPA_ldb, // Load Byte +HPPA_ldcd, // Load and Clear Doubleword +HPPA_ldcw, // Load and Clear Word +HPPA_ldd, // Load Doubleword +HPPA_ldda, // Load Doubleword Absolute +HPPA_ldh, // Load Halfword +HPPA_ldil, // Load Immediate Left +HPPA_ldo, // Load Offset +HPPA_ldsid, // Load Space Identifier +HPPA_ldw, // Load Word +HPPA_ldwa, // Load Word Absolute +HPPA_lpa, // Load Physical Address +HPPA_mfctl, // Move From Control Register +HPPA_mfia, // Move From Instruction Address +HPPA_mfsp, // Move From Space Register +HPPA_mixh, // Mix Halfwords +HPPA_mixw, // Mix Words +HPPA_movb, // Move and Branch +HPPA_movib, // Move Immediate and Branch +HPPA_mtctl, // Move To Control Register +HPPA_mtsarcm, // Move To Shift Amount Register Complement +HPPA_mtsm, // Move To System Mask +HPPA_mtsp, // Move To Space Register +HPPA_or, // Inclusive OR +HPPA_pdc, // Purge Data Cache +HPPA_pdtlb, // Purge Data TLB +HPPA_pdtlbe, // Purge Data TLB Entry +HPPA_permh, // Permute Halfwords +HPPA_pitlb, // Purge Instruction TLB +HPPA_pitlbe, // Purge Instruction TLB Entry +HPPA_popbts, // Pop Branch Target Stack +HPPA_probe, // Probe Access +HPPA_probei, // Probe Access Immediate +HPPA_pushbts, // Push Branch Target Stack +HPPA_pushnom, // Push Nominated +HPPA_rfi, // Return From Interruption +HPPA_rsm, // Reset System Mask +HPPA_shladd, // Shift Left and Add +HPPA_shrpd, // Sihft Right Pair Doubleword +HPPA_shrpw, // Sihft Right Pair Word +HPPA_spop0, // Special Operation Zero +HPPA_spop1, // Special Operation One +HPPA_spop2, // Special Operation Two +HPPA_spop3, // Special Operation Three +HPPA_ssm, // Set System Mask +HPPA_stb, // Store Byte +HPPA_stby, // Store Bytes +HPPA_std, // Store Doubleword +HPPA_stda, // Store Doubleword Absolute +HPPA_stdby, // Store Doubleword Bytes +HPPA_sth, // Store Halfword +HPPA_stw, // Store Word +HPPA_stwa, // Store Word Absolute +HPPA_sub, // Subtract +HPPA_subi, // Subtract from Immediate +HPPA_sync, // Synchronize Caches +HPPA_syncdma, // Synchronize DMA +HPPA_uaddcm, // Unit Add Complement +HPPA_uxor, // Unit XOR +HPPA_xor, // Exclusive OR + +// Floating point instructions + +HPPA_fabs, // Floating-Point Absolute Value +HPPA_fadd, // Floating-Point Add +HPPA_fcmp, // Floating-Point Compare +HPPA_fcnv, // Floating-Point Convert +HPPA_fcpy, // Floating-Point Copy +HPPA_fdiv, // Floating-Point Divide +HPPA_fid, // Floating-Point Identity +HPPA_fldd, // Floating-Point Load Doubleword +HPPA_fldw, // Floating-Point Load Word +HPPA_fmpy, // Floating-Point Multiply +HPPA_fmpyadd, // Floating-Point Multiply/Add +HPPA_fmpyfadd, // Floating-Point Multiply Fused Add +HPPA_fmpynfadd, // Floating-Point Multiply Negate Fused Add +HPPA_fmpysub, // Floating-Point Multiply/Subtract +HPPA_fneg, // Floating-Point Negate +HPPA_fnegabs, // Floating-Point Negate Absolute Value +HPPA_frem, // Floating-Point Remainder +HPPA_frnd, // Floating-Point Round to Integer +HPPA_fsqrt, // Floating-Point Square Root +HPPA_fstd, // Floating-Point Store Doubleword +HPPA_fstw, // Floating-Point Store Word +HPPA_fsub, // Floating-Point Subtract +HPPA_ftest, // Floating-Point Test +HPPA_xmpyu, // Fixed-Point Multiply Unsigned + +// Performance Monitor Coprocessor + +HPPA_pmdis, // Performance Monitor Disable +HPPA_pmenb, // Performance Monitor Enable + +// Macros + +HPPA_call, // Call Subroutine +HPPA_ret, // Return From Subroutine +HPPA_shld, // Shift Left Doubleword +HPPA_shlw, // Shift Left Word +HPPA_shrd, // Shift Right Doubleword +HPPA_shrw, // Shift Right Word +HPPA_ldi, // Load Immediate +HPPA_copy, // Copy Register +HPPA_mtsar, // Move To %SAR +HPPA_nop, // No Operation + +HPPA_last, + +}; + +#endif diff --git a/idasdk76/module/hppa/makefile b/idasdk76/module/hppa/makefile new file mode 100644 index 0000000..7e1e5e3 --- /dev/null +++ b/idasdk76/module/hppa/makefile @@ -0,0 +1,59 @@ +PROC=hppa +CONFIGS=hpux.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ana.cpp hppa.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)typeinf.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp hppa.hpp \ + ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp hppa.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp hppa.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp hppa.hpp hppa_cfh.cpp ins.hpp \ + notify_codes.hpp reg.cpp diff --git a/idasdk76/module/hppa/notify_codes.hpp b/idasdk76/module/hppa/notify_codes.hpp new file mode 100644 index 0000000..7300369 --- /dev/null +++ b/idasdk76/module/hppa/notify_codes.hpp @@ -0,0 +1,31 @@ + +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ +#pragma once + +#include <idp.hpp> + +//---------------------------------------------------------------------- +// The following events are supported by the PPC module in the ph.notify() function +namespace hppa_module_t +{ + enum event_codes_t + { + ev_dummy = processor_t::ev_loader, // was used before + ev_is_psw_w, // W-bit in PSW is set + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline bool is_psw_w() + { + return processor_t::notify(idp_ev(ev_is_psw_w)) == 1; + } +} diff --git a/idasdk76/module/hppa/out.cpp b/idasdk76/module/hppa/out.cpp new file mode 100644 index 0000000..b70c657 --- /dev/null +++ b/idasdk76/module/hppa/out.cpp @@ -0,0 +1,1304 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "hppa.hpp" + +//-------------------------------------------------------------------------- +struct cond_text_t +{ + const char *text; + char c; // -1 means any value + char f; // -1 means any value +}; + +static const cond_text_t D3[] = // and D4 combined +{ // c f + { "", 0, 0 }, // never + { "=", 1, 0 }, // op1 is equal to op2 (word) + { "<", 2, 0 }, // op1 is less than op2 (signed word) + { "<=", 3, 0 }, // op1 is less than or equal to op2 (signed word) + { "<<", 4, 0 }, // op1 is less than op2 (unsigned word) + { "<<=", 5, 0 }, // op1 is less than or equal to op2 (unsigned word) + { "sv", 6, 0 }, // op1 minus op2 overflows (signed word) + { "od", 7, 0 }, // op1 minus op2 is odd + { "tr", 0, 1 }, // always + { "<>", 1, 1 }, // op1 is not equal to op2 (word) + { ">=", 2, 1 }, // op1 is greater than or equal to op2 (signed word) + { ">", 3, 1 }, // op1 is greater than op2 (signed word) + { ">>=", 4, 1 }, // op1 is greater than or equal to op2 (unsigned word) + { ">>", 5, 1 }, // op1 is greater than op2 (unsigned word) + { "nsv", 6, 1 }, // op1 minus op2 does not overflow (signed word) + { "ev", 7, 1 }, // op1 minus op2 is even + { NULL }, +}; + +static const cond_text_t D5[] = // f should be 0! +{ // c f + { "*<<", 0, 0 }, // op1 is less than op2 (unsigned doubleword) + { "*=", 1, 0 }, // op1 is equal to op2 (doubleword) + { "*<", 2, 0 }, // op1 is less than op2 (signed doubleword) + { "*<=", 3, 0 }, // op1 is less than or equal to op2 (signed doubleword) + { "*>>=", 4, 0 }, // op1 is greater than or equal to op2 (unsigned doubleword) + { "*<>", 5, 0 }, // op1 is not equal to op2 (doubleword) + { "*>=", 6, 0 }, // op1 is greater than or equal to op2 (signed doubleword) + { "*>", 7, 0 }, // op1 is greater than op2 (signed doubleword) + { NULL }, +}; + +static const cond_text_t D6[] = // and D7 combined +{ // c f + { "", 0, 0 }, // never + { "=", 1, 0 }, // op1 is equal to negative of op2 (word) + { "<", 2, 0 }, // op1 is less than negative of op2 (signed word) + { "<=", 3, 0 }, // op1 is less than or equal to negative of op2 (signed word) + { "nuv", 4, 0 }, // op1 plus op2 does not overflow (unsigned word) + { "znv", 5, 0 }, // op1 plus op2 is zero or no overflow (unsigned word) + { "sv", 6, 0 }, // op1 plus op2 overflows (signed word) + { "od", 7, 0 }, // op1 plus op2 is odd + { "tr", 0, 1 }, // always + { "<>", 1, 1 }, // op1 is not equal to negative of op2 (word) + { ">=", 2, 1 }, // op1 is greater than or equal to negative of op2 (signed word) + { ">", 3, 1 }, // op1 is greater than negative of op2 (signed word) + { "uv", 4, 1 }, // op1 plus op2 overflows (unsigned word) + { "vnz", 5, 1 }, // op1 plus op2 is nonzero and overflows (unsigned word) + { "nsv", 6, 1 }, // op1 minus op2 does not overflow (signed word) + { "ev", 7, 1 }, // op1 minus op2 is even + { NULL }, +}; + +static const cond_text_t D8[] = // d should be 0! +{ // c f + { "", 0, 0 }, // never + { "=", 1, 0 }, // op1 is equal to negative of op2 (word) + { "<", 2, 0 }, // op1 is less than negative of op2 (signed word) + { "<=", 3, 0 }, // op1 is less than or equal to negative of op2 (signed word) + { "nuv", 4, 0 }, // op1 plus op2 does not overflow (unsigned word) + { "*=", 5, 0 }, // op1 is equal to negative of op2 (doubleword) + { "*<", 6, 0 }, // op1 is less than negative of op2 (signed doubleword) + { "*<=", 7, 0 }, // op1 is less than or equal to negative of op2 (signed doubleword) + { "tr", 0, 1 }, // always + { "<>", 1, 1 }, // op1 is not equal to negative of op2 (word) + { ">=", 2, 1 }, // op1 is greater than or equal to negative of op2 (signed word) + { ">", 3, 1 }, // op1 is greater than negative of op2 (signed word) + { "uv", 4, 1 }, // op1 plus op2 overflows (unsigned word) + { "*<>", 5, 1 }, // op1 is not equal to negative of op2 (doubleword) + { "*>=", 6, 1 }, // op1 is greater than or equal to negative of op2 (signed doubleword) + { "*>", 7, 1 }, // op1 is greater than negative of op2 (signed doubleword) + { NULL }, +}; + +static const cond_text_t D9[] = // and D10 combined +{ // c f + { "", 0, 0 }, // never + { "=", 1, 0 }, // all bits in word are 0 + { "<", 2, 0 }, // leftmost bit in word is 1 + { "<=", 3, 0 }, // leftmost bit in word is 1 or all bits in word are 0 + { "od", 7, 0 }, // rightmost bit is 1 + { "tr", 0, 1 }, // always + { "<>", 1, 1 }, // some bits in word are 1 + { ">=", 2, 1 }, // leftmost bit in word is 0 + { ">", 3, 1 }, // leftmost bit in word is 0 and some bits in word are 1 + { "ev", 7, 1 }, // rightmost bit is 0 +}; + + +static const cond_text_t D11[] = // and D12 combined +{ // c f + { "", 0, 0 }, // never + { "swz", 1, 0 }, // 64! some word zero + { "sbz", 2, 0 }, // some byte zero + { "shz", 3, 0 }, // some halfword zero + { "sdc", 4, 0 }, // some digit carry + { "swc", 5, 0 }, // 64! some word carry + { "sbc", 6, 0 }, // some byte carry + { "shc", 7, 0 }, // some halfword carry + { "tr", 0, 1 }, // always + { "nwz", 1, 1 }, // 64! no word zero + { "nbz", 2, 1 }, // no byte zero + { "nhz", 3, 1 }, // no halfword zero + { "ndc", 4, 1 }, // no digit carry + { "nwc", 5, 1 }, // 64! no word carry + { "nbc", 6, 1 }, // no byte carry + { "nhc", 7, 1 }, // no halfword carry +}; + + +static const cond_text_t D13[] = // and D14 combined (f should be 0) +{ // c f + { "", 0, 0 }, // never + { "=", 1, 0 }, // all bits in word are 0 + { "<", 2, 0 }, // leftmost bit in word is 1 + { "od", 3, 0 }, // rightmost bit is 1 + { "tr", 4, 0 }, // always + { "<>", 5, 0 }, // some bits in word are 1 + { ">=", 6, 0 }, // leftmost bit in word is 0 + { "ev", 7, 0 }, // rightmost bit is 0 +}; + +static const cond_text_t D15[] = // (f should be 0) +{ // c f + { "<", 0, 0 }, // leftmost bit in word is 1 + { ">=", 1, 0 }, // leftmost bit in word is 0 +}; + +static char *append_conds( + const cond_text_t *table, + int c, + int f, + int d, + char *ptr, + char *end) +{ + if ( !d && table == D11 && (c == 1 || c == 5) ) + return NULL; + while ( table->text != NULL ) + { + if ( table->c == c && table->f == f ) + { + if ( table->text[0] != '\0' ) + { + APPCHAR(ptr, end, ','); + if ( d != 0 ) + APPCHAR(ptr, end, '*'); + APPEND(ptr, end, table->text); + } + return ptr; + } + table++; + } + return NULL; +} + +//-------------------------------------------------------------------------- +// short displacement load and store instruction completers +static const char *h1_comp(int a, int m, int im5) +{ + if ( m ) + { + if ( a ) + return ",mb"; // a=1 m=1 + return im5 + ? ",ma" // a=0 m=1 im5 != 0 + : ",o"; // a=0 m=1 im5 == 0 + } + return ""; // m=0 +} + +//-------------------------------------------------------------------------- +// store bytes instruction completers +static const char *h2_comp(int a, int m) +{ + static const char *const suffixes[] = + { + "", // beginning case, don't modify base register + ",b,m", // beginning case, modify base register + ",e", // ending case, don't modify base register + ",e,m" // ending case, modify base register + }; + int idx = (a<<1) | m; + return suffixes[idx & 3]; +} + +//-------------------------------------------------------------------------- +// indexed instruction completers +static const char *h3_comp(int u, int m) +{ + static const char *const suffixes[] = + { + "", // no index shift, don't modify base register + ",m", // no index shift, modify base register + ",s", // shift index by data size, don't modify base register + ",sm" // shift index by data size, modify base register + }; + int idx = (u<<1) | m; + return suffixes[idx & 3]; +} + +//-------------------------------------------------------------------------- +static char *append_cc(char *ptr, const char *end, int cc, bool isload) +{ + static const char *const ld_suffixes[] = { "", NULL, ",sl", NULL }; + static const char *const st_suffixes[] = { "", ",bc", ",sl", NULL }; + const char *comp = (isload ? ld_suffixes : st_suffixes)[cc]; + if ( comp == NULL ) + return NULL; + APPEND(ptr, end, comp); + return ptr; +} + +//-------------------------------------------------------------------------- +static char *ldst_short(const insn_t &insn, uint32 code, char *ptr, const char *end) +{ + int cc = (code>>10) & 3; + int m = (code & BIT26) ? 1 : 0; + int a = (code & BIT18) ? 1 : 0; + const char *comp; + if ( code & BIT19 ) + { + int im5 = (code>>16) & 0x1F; + comp = h1_comp(a, m, im5); + } + else + { + int u = a; + comp = h3_comp(u, m); + } + bool isload; + switch ( insn.itype ) + { + default: + INTERR(10125); //-V796 no break + case HPPA_cldd: + case HPPA_cldw: + case HPPA_ldb: + case HPPA_ldcd: + case HPPA_ldcw: + case HPPA_ldd: + case HPPA_ldda: + case HPPA_ldh: + case HPPA_ldw: + case HPPA_ldwa: + case HPPA_fldd: + case HPPA_fldw: + isload = true; + break; + case HPPA_stby: + case HPPA_stdby: + comp = h2_comp(a, m); + // no break + case HPPA_cstd: + case HPPA_cstw: + case HPPA_stb: + case HPPA_std: + case HPPA_stda: + case HPPA_sth: + case HPPA_stw: + case HPPA_stwa: + case HPPA_fstd: + case HPPA_fstw: + isload = false; + break; + } + APPEND(ptr, end, comp); + ptr = append_cc(ptr, end, cc, isload); + return ptr; +} + +//-------------------------------------------------------------------------- +static const char *const fpp_comp[] = +{ + "false?", // 0 + "false", // 1 + "?", // 2 + "!<=>", // 3 + "=", // 4 + "=T", // 5 + "?=", // 6 + "!<>", // 7 + "!?>=", // 8 + "<", // 9 + "?<", // 10 + "!>=", // 11 + "!?>", // 12 + "<=", // 13 + "?<=", // 14 + "!>", // 15 + "!?<=", // 16 + ">", // 17 + "?>", // 18 + "!<=", // 19 + "!?<", // 20 + ">=", // 21 + "?>=", // 22 + "!<", // 23 + "!?=", // 24 + "<>", // 25 + "!=", // 26 + "!=T", // 27 + "!?", // 28 + "<=>", // 29 + "true?", // 30 + "true", // 31 +}; + +static const char *const fpp_test[] = +{ + "", // 0 + "acc", // 1 + ",rej", // 2 + NULL, // 3 + NULL, // 4 + ",acc8", // 5 + ",rej8", // 6 + NULL, // 7 + NULL, // 8 + ",acc6", // 9 + NULL, // 10 + NULL, // 11 + NULL, // 12 + ",acc4", // 13 + NULL, // 14 + NULL, // 15 + NULL, // 16 + ",acc2", // 17 + NULL, // 18 + NULL, // 19 + NULL, // 20 + NULL, // 21 + NULL, // 22 + NULL, // 23 + NULL, // 24 + NULL, // 25 + NULL, // 26 + NULL, // 27 + NULL, // 28 + NULL, // 29 + NULL, // 30 + NULL, // 31 +}; + +static const char *const fpp_sngop[] = +{ + "", // 0 or sgl + ",dbl", // 1 + NULL, // 2 + ",quad", // 3 +}; + +//-------------------------------------------------------------------------- +inline char *append_fmt(int fmt, char *ptr, const char *end) +{ + if ( fmt == 2 || fmt > 3 ) + return NULL; + APPEND(ptr, end, fpp_sngop[fmt]); + return ptr; +} + +//-------------------------------------------------------------------------- +char *hppa_t::build_insn_completer(const insn_t &insn, uint32 code, char *buf, size_t bufsize) +{ + char *ptr = buf; + char *const end = buf + bufsize; + switch ( insn.itype ) + { + case HPPA_ldo: // format 1 (special case) + case HPPA_ldi: // pseudo-op + case HPPA_nop: // pseudo-op + case HPPA_copy: // pseudo-op (ldo or or) + break; + + case HPPA_ldb: // formats 1-5 + case HPPA_ldcd: + case HPPA_ldcw: + case HPPA_ldd: + case HPPA_ldda: + case HPPA_ldh: + case HPPA_ldw: + case HPPA_ldwa: + case HPPA_stb: + case HPPA_stby: + case HPPA_std: + case HPPA_stda: + case HPPA_stdby: + case HPPA_sth: + case HPPA_stw: + case HPPA_stwa: + case HPPA_fldd: + case HPPA_fldw: + case HPPA_fstd: + case HPPA_fstw: + switch ( opcode(code) ) + { + case 0x10: // format 1 + case 0x11: + case 0x12: + case 0x18: + case 0x19: + case 0x1A: + case 0x17: // format 2 + case 0x1F: + // nothing to do + break; + case 0x13: // ldw (mod) + case 0x1B: // stw (mod) + { + sval_t off = insn.itype == HPPA_ldw ? insn.Op1.addr : insn.Op2.addr; + APPEND(ptr, end, off < 0 ? ",mb" : ",ma"); + } + break; + case 0x14: // format 3 + case 0x1C: + { + int m = (code & BIT28) ? 1 : 0; + int a = (code & BIT29) ? 1 : 0; + int im10a = ((code >> 3) & 0x7FE) | (code & 1); + APPEND(ptr, end, h1_comp(a, m, im10a)); + } + break; + case 0x16: // format 44 (fldw) + case 0x1E: // format 44 (fstw) + { + int m = 0; + int a = (code & BIT29) ? 1 : 0; + int im11a = ((code >> 2) & 0xFFE) | (code & 1); + APPEND(ptr, end, h1_comp(a, m, im11a)); + } + break; + case 0x03: // formats 4 & 5 + case 0x09: // formats 39 & 41 + case 0x0B: // formats 39 & 41 + ptr = ldst_short(insn, code, ptr, end); + break; + default: + interr(insn, "format1"); + } + break; + + case HPPA_addil: // format 7 + case HPPA_ldil: + break; + + case HPPA_hadd: // format 8 (special case) + case HPPA_hsub: + { + int sat = (code>>6) & 3; + static const char *const suffixes[4] = { ",us", ",ss", NULL, "" }; + if ( sat == 2 ) + return NULL; + APPEND(ptr, end, suffixes[sat]); + } + case HPPA_havg: // format 8 (special case2) + case HPPA_hshladd: + case HPPA_hshradd: + break; + + case HPPA_add: // format 8 + case HPPA_and: + case HPPA_andcm: + case HPPA_cmpclr: + case HPPA_dcor: + case HPPA_ds: + case HPPA_or: + case HPPA_shladd: + case HPPA_sub: + case HPPA_uaddcm: + case HPPA_uxor: + case HPPA_xor: + { + int c = (code>>13) & aux_cndc; + int f = (code & BIT19) ? 1 : 0; // aux_cndf + int d = (code & BIT26) ? 1 : 0; // aux_cndd + const cond_text_t *table = NULL; + switch ( insn.itype ) + { + case HPPA_cmpclr: + case HPPA_ds: + table = D3; + break; + case HPPA_add: + case HPPA_shladd: + { + int e1 = (code>>10) & 3; + int e2 = (code & BIT23) ? 1 : 0; + if ( !e1 ) + return NULL; + if ( e1 == 2 && e2 ) + return NULL; // not defined + if ( e2 ) + APPEND(ptr, end, d ? ",dc" : ",c"); + static const char *const suffixes[4] = { "", "", ",l", ",tsv" }; + APPEND(ptr, end, suffixes[e1]); + } + table = D6; + break; + case HPPA_sub: + { + int e1 = (code>>10) & 3; + int e2 = (code & BIT23) ? 1 : 0; + int e3 = (code>> 6) & 3; + if ( e1 != 1 && e1 != 3 ) + return NULL; + if ( e3 != 0 && e3 != 3 ) + return NULL; + if ( e2 && e3 ) + return NULL; + if ( e2 ) + APPEND(ptr, end, d ? ",db" : ",b"); + if ( e3 ) + APPEND(ptr, end, ",tc"); + if ( e1 == 3 ) + APPEND(ptr, end, ",tsv"); + } + table = D3; + break; + case HPPA_or: + case HPPA_and: + case HPPA_andcm: + case HPPA_xor: + table = D9; + break; + case HPPA_uaddcm: + { + int e1 = (code>>6) & 3; + if ( e1 != 2 && e1 != 3 ) + return NULL; + if ( e1 == 3 ) + APPEND(ptr, end, ",tc"); + } + table = D11; + break; + case HPPA_dcor: + { + int e1 = (code>>6) & 3; + if ( e1 != 2 && e1 != 3 ) + return NULL; + if ( e1 == 3 ) + APPEND(ptr, end, ",i"); + } + table = D11; + break; + case HPPA_uxor: + table = D11; + if ( c > 3 ) + return NULL; // disable carry conditions + break; + default: + interr(insn, "format8"); + } + ptr = append_conds(table, c, f, d, ptr, end); + } + break; + + case HPPA_addi: // format 9 (special case) + case HPPA_subi: + { + if ( (code & BIT20) != 0 ) + APPEND(ptr, end, ",tsv"); + if ( opcode(code) == 0x2C ) + APPEND(ptr, end, ",tc"); + int c = (code>>13) & 7; + int f = (code & BIT19) ? 1 : 0; + ptr = append_conds(insn.itype == HPPA_subi ? D3 : D6, c, f, 0, ptr, end); + } + break; + + case HPPA_cmpiclr: // format 9 + { + int c = (code>>13) & 7; + int f = (code & BIT19) ? 1 : 0; + int d = (code & BIT20) ? 1 : 0; + ptr = append_conds(D3, c, f, d, ptr, end); + } + break; + + case HPPA_permh: // format 10 + { + int c0 = (code>>13) & 3; + int c1 = (code>>10) & 3; + int c2 = (code>> 8) & 3; + int c3 = (code>> 6) & 3; + ptr += qsnprintf(ptr, end-ptr, ",%d%d%d%d", c0, c1, c2, c3); + } + break; + + case HPPA_mixh: // format 10 + case HPPA_mixw: + { + int ea = (code>>13) & 3; + if ( ea & 1 ) + return NULL; + APPEND(ptr, end, ea ? ",r" : ",l"); + } + break; + + case HPPA_hshr: // format 10 + { + int se = (code>>10) & 3; + if ( se < 2 ) + return NULL; + if ( se == 2 ) + APPEND(ptr, end, ",u"); + } + case HPPA_hshl: // format 10 (special case) + break; + + case HPPA_shrpd: // formats 11 & 14 + case HPPA_shrpw: + ptr = append_conds(D13, (code>>13) & 7, 0, insn.itype == HPPA_shrpd, ptr, end); + break; + + case HPPA_extrd: // formats 12 & 15 + case HPPA_extrw: + case HPPA_shrd: // pseudo-op + case HPPA_shrw: // pseudo-op + if ( (code & BIT21) == 0 ) + APPEND(ptr, end, ",u"); + ptr = append_conds(D13, (code>>13) & 7, 0, insn.itype == HPPA_extrd, ptr, end); + break; + + case HPPA_depd: // formats 13 & 16 + case HPPA_depdi: + case HPPA_depw: + case HPPA_depwi: + case HPPA_shld: // pseudo-op + case HPPA_shlw: // pseudo-op + { + int nz = (code & BIT21) ? 1 : 0; + int c = (code>>13) & 7; + int d = 0; + switch ( insn.itype ) + { + case HPPA_depd: + case HPPA_depdi: + ++d; + case HPPA_depw: + case HPPA_depwi: + break; + default: + interr(insn, "format13"); + } + if ( !nz && insn.itype < HPPA_call ) + APPEND(ptr, end, ",z"); + ptr = append_conds(D13, c, 0, d, ptr, end); + } + break; + + case HPPA_addb: // format 17 + case HPPA_addib: + case HPPA_cmpb: + case HPPA_cmpib: + case HPPA_movb: + case HPPA_movib: + { + int c = (code>>13) & 7; + int f = 0; + const cond_text_t *table = psw_w() ? D8 : D6; + switch ( opcode(code) ) + { + case 0x20: // cmpb + case 0x21: // cmpib + case 0x27: // cmpb + table = D3; + case 0x28: // addb + case 0x29: // addib + break; + case 0x22: // cmpb + case 0x23: // cmpib + case 0x2F: // cmpb + table = D3; + // fallthrough + case 0x2A: // addb + case 0x2B: // addib + ++f; + break; + case 0x32: // movb + case 0x33: // movib + table = D13; + break; + case 0x3B: // cmpib 64 bit + table = D5; + break; + default: + interr(insn, "format17"); + } + ptr = append_conds(table, c, f, 0, ptr, end); + if ( ptr == NULL ) + return NULL; + } + goto NULLIFY; + + case HPPA_bb: // format 18 + { + int c = (code & BIT16) ? 1 : 0; + int d = (code & BIT18) ? 1 : 0; + ptr = append_conds(D15, c, 0, d, ptr, end); + } + goto NULLIFY; + + case HPPA_be: // format 19 + if ( opcode(code) == 0x39 ) + APPEND(ptr, end, ",l"); + goto NULLIFY; + + case HPPA_b: // format 20 + if ( insn.Op2.type != o_void ) + { + int subopcode = (code>>13) & 7; + if ( subopcode >= 6 ) + goto BVE; + static const char *const suffixes[8] = + { + ",l", ",gate", NULL, NULL, + ",push", ",l", NULL, NULL + }; + const char *s = suffixes[subopcode]; + if ( s == NULL ) + return NULL; + APPEND(ptr, end, s); + } + goto NULLIFY; + + case HPPA_blr: // format 21 + case HPPA_bv: + case HPPA_call: // pseudo-op +NULLIFY: + if ( (code & BIT30) != 0 ) + APPEND(ptr, end, ",n"); + break; + + case HPPA_bve: // format 22 + case HPPA_ret: // pseudo-op +BVE: + { + int subopcode = (code>>13) & 7; + if ( subopcode != 6 && subopcode != 7 ) + return NULL; + if ( subopcode == 7 && insn.itype == HPPA_bve ) + APPEND(ptr, end, ",l"); + if ( (code & BIT31) != 0 ) + APPEND(ptr, end, (subopcode == 7) ? ",push" : ",pop"); + } + goto NULLIFY; + + case HPPA_clrbts: // format 23 + case HPPA_popbts: + case HPPA_pushbts: + case HPPA_pushnom: + break; + + case HPPA_pdtlb: // formats 24 & 25 & 26 + case HPPA_pitlb: + if ( (code & BIT21) != 0 ) + APPEND(ptr, end, ",l"); + // no break + case HPPA_fdc: + case HPPA_fdce: + case HPPA_fic: + case HPPA_fice: + case HPPA_lpa: + case HPPA_pdc: + case HPPA_pdtlbe: + case HPPA_pitlbe: + if ( (code & BIT26) != 0 ) + APPEND(ptr, end, ",m"); + case HPPA_lci: // format 24 (special case) + break; + + case HPPA_probe: // format 24 (special case) + case HPPA_probei: + APPEND(ptr, end, (code & BIT25) != 0 ? ",w" : ",r"); + break; + + case HPPA_idtlbt: // format 26 + case HPPA_iitlbt: + break; + + case HPPA_break: // format 27 + break; + + case HPPA_diag: // format 28 + break; + + case HPPA_mfsp: // format 29 + case HPPA_mtsp: + break; + + case HPPA_ldsid: // format 30 + break; + + case HPPA_mtctl: // format 31 + case HPPA_mtsar: // pseudo-op + case HPPA_mtsarcm: + break; + + case HPPA_mfctl: // format 32 + if ( (code & BIT17) != 0 ) + APPEND(ptr, end, ",w"); + case HPPA_mfia: // format 32 (special case) + break; + + case HPPA_rfi: // format 33 + { + int e1 = (code>>5) & 0xF; + if ( e1 != 0 && e1 != 5 ) + return NULL; + if ( e1 == 5 ) + APPEND(ptr, end, ",r"); + } + case HPPA_mtsm: // format 33 + case HPPA_rsm: + case HPPA_ssm: + case HPPA_sync: + case HPPA_syncdma: + break; + + case HPPA_spop0: // format 34 + { + int sfu = (code>> 6) & 7; + int sop1 = (code>>11) & 0x7FFF; + int sop2 = (code>> 0) & 0x1F; + uint32 sop = (sop1 << 5) | sop2; + ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); + ptr += btoa(ptr, end-ptr, sop); + } + goto NULLIFY2; + + case HPPA_spop1: // format 35 + { + int sfu = (code>> 6) & 7; + uint32 sop = (code>>11) & 0x7FFF; + ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); + ptr += btoa(ptr, end-ptr, sop); + } + goto NULLIFY2; + + case HPPA_spop2: // format 36 + { + int sfu = (code>> 6) & 7; + int sop1 = (code>>11) & 0x3FF; + int sop2 = (code>> 0) & 0x1F; + uint32 sop = (sop1 << 5) | sop2; + ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); + ptr += btoa(ptr, end-ptr, sop); + } + goto NULLIFY2; + + case HPPA_spop3: // format 37 + { + int sfu = (code>> 6) & 7; + int sop1 = (code>>11) & 0x1F; + int sop2 = (code>> 0) & 0x1F; + uint32 sop = (sop1 << 5) | sop2; + ptr += qsnprintf(ptr, end-ptr, ",%d,", sfu); + ptr += btoa(ptr, end-ptr, sop); + } + goto NULLIFY2; + + case HPPA_copr: // format 38 + { + int uid = (code>> 6) & 7; + uint32 sop = (code & 0x1F) | ((code>>4)&(0x1FFFF<<5)); + ptr += qsnprintf(ptr, end-ptr, ",%d,", uid); + ptr += btoa(ptr, end-ptr, sop); + } + goto NULLIFY2; + + case HPPA_pmdis: // format 55 +NULLIFY2: + { + int n = (code & BIT26) ? 1 : 0; + if ( n != 0 ) + APPEND(ptr, end, ",n"); + } + break; + + case HPPA_cldd: // formats 39 & 41 + case HPPA_cldw: + case HPPA_cstd: // formats 40 & 42 + case HPPA_cstw: + { + int uid = (code>> 6) & 7; + ptr += qsnprintf(ptr, end-ptr, ",%d", uid); + ptr = ldst_short(insn, code, ptr, end); + } + break; + + case HPPA_fabs: // formats 45 & 49 + case HPPA_fcpy: + case HPPA_fneg: + case HPPA_fnegabs: + case HPPA_frem: + case HPPA_frnd: + case HPPA_fsqrt: + case HPPA_fadd: // formats 48 & 52 + case HPPA_fdiv: + case HPPA_fmpy: + case HPPA_fsub: + { + int fmt = 0; + switch ( opcode(code) ) + { + case 0x0E: // formats 49 & 52 + fmt = (code>>11) & 1; + break; + case 0x0C: // formats 45 & 48 + fmt = (code>>11) & 3; + break; + default: + INTERR(10126); + } + ptr = append_fmt(fmt, ptr, end); + } + break; + case HPPA_fid: // format 45 + break; + + case HPPA_fcnv: // formats 46 & 50 + { + int sub = (code>>15) & 7; + int df, sf; + if ( opcode(code) == 0x0E ) // format 50 + { + df = (code>>13) & 1; + sf = (code>>11) & 1; + } + else // format 46 + { + df = (code>>13) & 3; + sf = (code>>11) & 3; + } + if ( sf == 2 || df == 2 ) + return NULL; + if ( (sub & 3) == 3 ) + APPEND(ptr, end, ",t"); // with explicit round to zero + static const char *const cnv_fpp[] = { ",sgl", ",dbl", NULL, ",quad" }; + static const char *const cnv_sfx[] = { ",w", ",dw", NULL, ",qw" }; + static const char *const cnv_ufx[] = { ",uw", ",udw", NULL, ",uqw" }; + const char *const *s1 = NULL; + const char *const *s2 = NULL; + switch ( sub ) + { + case 0: // fpp->fpp + s1 = cnv_fpp; + s2 = cnv_fpp; + break; + case 2: // fpp->fix + case 3: // fpp->fix with explicit round to zero + s1 = cnv_fpp; + s2 = cnv_sfx; + break; + case 6: // fpp->unsigned fix + case 7: // fpp->unsigned fix with explicit round to zero + s1 = cnv_fpp; + s2 = cnv_ufx; + break; + case 4: // undefined + return NULL; + case 1: // fix->fpp + s1 = cnv_sfx; + s2 = cnv_fpp; + break; + case 5: // unsigned fix->fpp + s1 = cnv_ufx; + s2 = cnv_fpp; + break; + } + APPEND(ptr, end, s1[sf]); + APPEND(ptr, end, s2[df]); + } + break; + + case HPPA_fcmp: // formats 47 & 51 + if ( opcode(code) == 0x0C ) + { + int fmt = (code>>11) & 3; + ptr = append_fmt(fmt, ptr, end); + if ( ptr == NULL ) + return NULL; + } + { + int c = code & 0x1F; + APPCHAR(ptr, end, ','); + APPEND(ptr, end, fpp_comp[c]); + } + break; + + case HPPA_ftest: // format 47 + { + int y = (code>>13) & 7; + if ( y == 1 ) // queue test + { + int c = code & 0x1F; + const char *s = fpp_test[c]; + if ( s == NULL ) + return NULL; + APPEND(ptr, end, s); + } + } + break; + + case HPPA_xmpyu: // format 52 + break; + + case HPPA_fmpyadd: // format 53 + case HPPA_fmpysub: + { + int f = (code>>5) & 1; + if ( f == 0 ) + APPEND(ptr, end, ",dbl"); + } + break; + + case HPPA_fmpyfadd: // format 54 + case HPPA_fmpynfadd: + { + int f = (code>>11) & 1; + if ( f != 0 ) + APPEND(ptr, end, ",dbl"); + } + break; + + default: + interr(insn, "build_insn_completer"); + } + if ( ptr == NULL ) + return NULL; + APPZERO(ptr, end); + return buf; +} + +//---------------------------------------------------------------------- +class out_hppa_t : public outctx_t +{ + out_hppa_t(void) = delete; // not used +public: + void out_bad_address(ea_t addr); + void outreg(int r); + void out_ip_rel(int displ); + void out_memref(ea_t ea); + void resolve_possible_memref(const op_t &x); + + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); +}; +CASSERT(sizeof(out_hppa_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_hppa_t) + +//---------------------------------------------------------------------- +void out_hppa_t::out_bad_address(ea_t addr) +{ + out_tagon(COLOR_ERROR); + out_btoa(addr, 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); +} + +//---------------------------------------------------------------------- +void out_hppa_t::outreg(int r) +{ + bool right = false; + out_tagon(COLOR_REG); + if ( r >= F0+32 && r < F0+64 // fpp register half + && insn.itype != HPPA_fmpyadd + && insn.itype != HPPA_fmpysub ) + { + r -= 32; + right = true; + } + out_line(ph.reg_names[r]); + if ( right ) + out_char('r'); + out_tagoff(COLOR_REG); +} + +//---------------------------------------------------------------------- +void out_hppa_t::out_ip_rel(int displ) +{ + out_printf(COLSTR("%s+", SCOLOR_SYMBOL) COLSTR("%d", SCOLOR_NUMBER), + ash.a_curip, displ); +} + +//---------------------------------------------------------------------- +bool out_hppa_t::out_operand(const op_t &x) +{ + switch ( x.type ) + { + case o_void: + return 0; + + case o_imm: + out_value(x, OOF_SIGNED|OOFS_IFSIGN|OOFW_IMM); + break; + + case o_reg: + outreg(x.reg); + break; + + case o_near: + { + ea_t ea = calc_mem(x.addr); + if ( ea == insn.ea+4 ) + out_ip_rel(4); + else if ( !out_name_expr(x, ea, ea) ) + out_bad_address(x.addr); + } + break; + + case o_displ: + out_value(x, OOF_ADDR|OOFS_IFSIGN|OOF_SIGNED|OOFW_32); + // no break + case o_based: +OUT_PHRASE: + out_symbol('('); + if ( insn.auxpref & aux_space ) + { + outreg(x.sid); + out_symbol(','); + } + outreg(x.phrase); + out_symbol(')'); + break; + + case o_phrase: + outreg(x.secreg); + goto OUT_PHRASE; + + default: + interr(insn, "out"); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +void out_hppa_t::out_memref(ea_t ea) +{ + out_char(' '); + out_line(ash.cmnt, COLOR_AUTOCMT); + out_char(' '); + if ( has_any_name(get_flags(ea)) ) + { + qstring nbuf = get_colored_name(ea); + out_line(nbuf.c_str()); + } + else + { + // do not sign extend values that fit 32 bits +#ifdef __EA64__ + if ( int32(ea) == ea ) + ea = uint32(ea); +#endif + out_printf("%0*a", 8, ea); + } +} + +//---------------------------------------------------------------------- +void out_hppa_t::resolve_possible_memref(const op_t &x) +{ + hppa_t &pm = *static_cast<hppa_t *>(procmod); + ea_t ea = pm.calc_possible_memref(insn, x); + if ( ea != BADADDR ) + out_memref(ea); +} + +//---------------------------------------------------------------------- +void out_hppa_t::out_proc_mnem(void) +{ + hppa_t &pm = *static_cast<hppa_t *>(procmod); + char postfix[80]; + uint32 code = get_dword(insn.ea); + char *pfx = pm.build_insn_completer(insn, code, postfix, sizeof(postfix)); + out_mnem(16, pfx); +} + +//---------------------------------------------------------------------- +void out_hppa_t::out_insn(void) +{ + // output instruction mnemonics + out_mnemonic(); + + int i; + bool comma = false; + for ( i=0; i < PROC_MAXOP; i++ ) + { + if ( insn.ops[i].type == o_void ) + continue; + if ( comma ) + { + out_symbol(','); + out_char(' '); + } + comma = out_one_operand(i); + } + + out_immchar_cmts(); + + if ( insn.Op1.type == o_displ ) + resolve_possible_memref(insn.Op1); + if ( insn.Op2.type == o_displ ) + resolve_possible_memref(insn.Op2); + + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +//lint -esym(818, Srange) could be made const +void hppa_t::hppa_segstart(outctx_t &ctx, segment_t *Srange) const +{ + const char *const predefined[] = + { + ".text", // Text section + ".data", // Data sections + ".rdata", + ".comm", + }; + + if ( is_spec_segm(Srange->type) ) + return; + + qstring sname; + qstring sclas; + get_segm_name(&sname, Srange); + get_segm_class(&sclas, Srange); + + if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) ) + ctx.gen_printf(DEFAULT_INDENT, + COLSTR(".section %s", SCOLOR_ASMDIR) "" COLSTR("%s %s", SCOLOR_AUTOCMT), + sname.c_str(), + ash.cmnt, + sclas.c_str()); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +void hppa_t::hppa_assumes(outctx_t &ctx) // function to produce assume directives +{ + ea_t ea = ctx.insn_ea; + if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || got == BADADDR ) + return; + sreg_range_t sra; + if ( !get_sreg_range(&sra, ea, DPSEG) || sra.start_ea != ea ) + return; + + if ( sra.val == BADSEL ) + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s %s is unknown", SCOLOR_ASMDIR), + ash.cmnt, ph.reg_names[DPSEG]); + else + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s %s = %0*a", SCOLOR_ASMDIR), + ash.cmnt, ph.reg_names[DPSEG], 8, got + sra.val); +} + +//-------------------------------------------------------------------------- +void idaapi hppa_segend(outctx_t &, segment_t *) +{ +} + +//-------------------------------------------------------------------------- +void idaapi hppa_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL); +} + +//-------------------------------------------------------------------------- +void hppa_t::hppa_footer(outctx_t &ctx) const +{ + qstring nbuf = get_colored_name(inf_get_start_ea()); + const char *name = nbuf.c_str(); + const char *end = ash.end; + if ( end == NULL ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name); + else + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), + ash.end, ash.cmnt, name); +} diff --git a/idasdk76/module/hppa/reg.cpp b/idasdk76/module/hppa/reg.cpp new file mode 100644 index 0000000..cda836e --- /dev/null +++ b/idasdk76/module/hppa/reg.cpp @@ -0,0 +1,606 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "hppa.hpp" +#include "hppa_cfh.cpp" +#include <diskio.hpp> +#include <typeinf.hpp> +#include "notify_codes.hpp" + +#include <ieee.h> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names_plain[] = +{ + // general registers (r0 is always 0) + // r31 is for BLE instruction + "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", + "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", + "%r24", "%r25", "%r26", "%dp", "%r28", "%r29", "%sp", "%r31", + // space registers + "%sr0", "%sr1", "%sr2", "%sr3", "%sr4", "%sr5", "%sr6", "%sr7", + // control registers + "%rctr", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7", + "%pidr1","%pidr2", "%ccr", "%sar", "%pidr3", "%pidr4","%iva", "%eiem", + "%itmr", "%pcsq", "pcoq", "%iir", "%isr", "%ior", "%ipsw", "%eirr", + "%tr0", "%tr1", "%tr2", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", + // floating-point registers + "%fpsr", "%fr1", "%fr2", "%fr3", "%fr4", "%fr5", "%fr6", "%fr7", + "%fr8", "%fr9", "%fr10", "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", + "%fr16", "%fr17", "%fr18", "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", + "%fr24", "%fr25", "%fr26", "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", + // register halves + "%fr16l", "%fr17l", "%fr18l", "%fr19l", "%fr20l", "%fr21l", "%fr22l", "%fr23l", + "%fr24l", "%fr25l", "%fr26l", "%fr27l", "%fr28l", "%fr29l", "%fr30l", "%fr31l", + "%fr16r", "%fr17r", "%fr18r", "%fr19r", "%fr20r", "%fr21r", "%fr22r", "%fr23r", + "%fr24r", "%fr25r", "%fr26r", "%fr27r", "%fr28r", "%fr29r", "%fr30r", "%fr31r", + // condition bits + "%ca0", "%ca1", "%ca2", "%ca3", "%ca4", "%ca5", "%ca6", + + "dp", // segment register to represent DP + "cs","ds", // virtual registers for code and data segments +}; + +static const char *const register_names_mnemonic[] = +{ + // general registers (r0 is always 0) + // r31 is for BLE instruction + "%r0", "%r1", "%rp", "%r3", "%r4", "%r5", "%r6", "%r7", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", + "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%arg3", + "%arg2", "%arg1", "%arg0", "%dp", "%ret0", "%r29", "%sp", "%r31", + // space registers + "%sr0", "%sr1", "%sr2", "%sr3", "%sr4", "%sr5", "%sr6", "%sr7", + // control registers + "%rctr", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7", + "%pidr1","%pidr2", "%ccr", "%sar", "%pidr3", "%pidr4","%iva", "%eiem", + "%itmr", "%pcsq", "pcoq", "%iir", "%isr", "%ior", "%ipsw", "%eirr", + "%tr0", "%tr1", "%tr2", "%tr3", "%tr4", "%tr5", "%tr6", "%tr7", + // floating-point registers + "%fpsr", "%fr1", "%fr2", "%fr3", "%fr4", "%fr5", "%fr6", "%fr7", + "%fr8", "%fr9", "%fr10", "%fr11", "%fr12", "%fr13", "%fr14", "%fr15", + "%fr16", "%fr17", "%fr18", "%fr19", "%fr20", "%fr21", "%fr22", "%fr23", + "%fr24", "%fr25", "%fr26", "%fr27", "%fr28", "%fr29", "%fr30", "%fr31", + // register halves + "%fr16l", "%fr17l", "%fr18l", "%fr19l", "%fr20l", "%fr21l", "%fr22l", "%fr23l", + "%fr24l", "%fr25l", "%fr26l", "%fr27l", "%fr28l", "%fr29l", "%fr30l", "%fr31l", + "%fr16r", "%fr17r", "%fr18r", "%fr19r", "%fr20r", "%fr21r", "%fr22r", "%fr23r", + "%fr24r", "%fr25r", "%fr26r", "%fr27r", "%fr28r", "%fr29r", "%fr30r", "%fr31r", + // condition bits + "%ca0", "%ca1", "%ca2", "%ca3", "%ca4", "%ca5", "%ca6", + + "dp", // segment register to represent DP + "cs","ds", // virtual registers for code and data segments +}; +CASSERT(qnumber(register_names_plain) == qnumber(register_names_mnemonic)); + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0xE8, 0x40, 0xC0, 0x00 }; // bv %r0(%rp) + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gas = +{ + AS_ASCIIC|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, + 0, + "GNU-like hypothetical assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + "#", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".long", // double words + ".quad", // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + ".", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "mod", // mod + "and", // and + "or", // or + "xor", // xor + "not", // not + "shl", // shl + "shr", // shr + NULL, // sizeof + 0, // flag2 + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt + NULL, // vstruc_fmt + NULL, // rva +}; + +static const asm_t *const asms[] = { &gas, NULL }; + +//------------------------------------------------------------------ +// read all procmod data from the idb +void hppa_t::load_from_idb() +{ + idpflags = (ushort)helper.altval(-1); + handle_new_flags(/*save*/ false); +} + +//-------------------------------------------------------------------------- +void hppa_t::setup_got(void) +{ + got = get_gotea(); + if ( got == BADADDR ) + got = get_name_ea(BADADDR, "_GLOBAL_OFFSET_TABLE_"); + if ( got == BADADDR ) + { + segment_t *s = get_segm_by_name(".got"); + if ( s != NULL ) + got = s->start_ea; + } + msg("DP is assumed to be %08a\n", got); +} + +//-------------------------------------------------------------------------- +void hppa_t::handle_new_flags(bool save) +{ + if ( mnemonic() ) + ph.reg_names = register_names_mnemonic; + else + ph.reg_names = register_names_plain; + if ( save ) + save_idpflags(); +} + +//-------------------------------------------------------------------------- +const char *hppa_t::get_syscall_name(int syscall) +{ + const ioport_t *p = find_ioport(syscalls, syscall); + return p == NULL ? NULL : p->name.c_str(); +} + +//-------------------------------------------------------------------------- +const char *hppa_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + static const char form[] = + "HELP\n" + "HP PA-RISC specific options\n" + "\n" + " Simplify instructions\n" + "\n" + " If this option is on, IDA will simplify instructions and replace\n" + " them by clearer pseudo-instructions\n" + " For example,\n" + "\n" + " or 0, 0, 0\n" + "\n" + " will be replaced by\n" + "\n" + " nop\n" + "\n" + " PSW bit W is on\n" + "\n" + " If this option is on, IDA will disassemble instructions as if\n" + " PSW W bit is on, i.e. addresses are treated as 64bit. In fact,\n" + " IDA still will truncate them to 32 bit, but this option changes\n" + " disassembly of load/store instructions.\n" + "\n" + " Use mnemonic register names\n" + "\n" + " If checked, IDA will use mnemonic names of the registers:\n" + " %r26: %arg0\n" + " %r25: %arg1\n" + " %r24: %arg2\n" + " %r23: %arg3\n" + " %r28: %ret0\n" + "\n" + "\n" + "ENDHELP\n" + "HPPA specific options\n" + "\n" + " <~S~implify instructions:C>\n" + " <PSW bit W is on (for 64-bit):C>\n" + " <Use ~m~nemonic register names:C>>\n" + "\n" + "\n"; + + if ( keyword == NULL ) + { + CASSERT(sizeof(idpflags) == sizeof(ushort)); + ask_form(form, &idpflags); +OK: + handle_new_flags(idb_loaded); + return IDPOPT_OK; + } + else + { + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + if ( strcmp(keyword, "HPPA_SIMPLIFY") == 0 ) + { + setflag(idpflags, IDP_SIMPLIFY, *(int*)value != 0); + goto OK; + } + if ( strcmp(keyword, "HPPA_MNEMONIC") == 0 ) + { + setflag(idpflags, IDP_MNEMONIC, *(int*)value != 0); + goto OK; + } + if ( strcmp(keyword, "HPPA_PSW_W") == 0 ) + { + setflag(idpflags, IDP_PSW_W, *(int*)value != 0); + goto OK; + } + return IDPOPT_BADKEY; + } +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(hppa_t)); + return 0; +} + +ssize_t idaapi hppa_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: +// __emit__(0xCC); // debugger trap + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); // always big endian + read_ioports(&syscalls, NULL, "hpux.cfg"); + init_custom_refs(); + break; + + case processor_t::ev_term: + term_custom_refs(); + syscalls.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + handle_new_flags(); + setup_got(); + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + setup_got(); + break; + + case processor_t::ev_newprc: // new processor type + break; + + case processor_t::ev_newasm: // new assembler type + break; + + case processor_t::ev_creating_segm: // new segment + { + segment_t *sptr = va_arg(va, segment_t *); + sptr->defsr[ rVds-ph.reg_first_sreg] = find_selector(sptr->sel); + sptr->defsr[DPSEG-ph.reg_first_sreg] = 0; + } + break; + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + int nocrefs = va_arg(va, int); + return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1; + } + + case processor_t::ev_may_be_func: + { + const insn_t *insn = va_arg(va, insn_t *); + return may_be_func(*insn); + } + + case processor_t::ev_is_basic_block_end: + { + const insn_t *insn = va_arg(va, insn_t *); + return is_basic_block_end(*insn) ? 1 : -1; + } + +// +++ TYPE CALLBACKS (only 32-bit programs for the moment) + case processor_t::ev_decorate_name: + { + qstring *outbuf = va_arg(va, qstring *); + const char *name = va_arg(va, const char *); + bool mangle = va_argi(va, bool); + cm_t cc = va_argi(va, cm_t); + tinfo_t *type = va_arg(va, tinfo_t *); + return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; + } + + case processor_t::ev_max_ptr_size: + return 4; + + case processor_t::ev_calc_arglocs: + { + func_type_data_t *fti = va_arg(va, func_type_data_t *); + return calc_hppa_arglocs(fti) ? 1 : -1; + } + + case processor_t::ev_use_stkarg_type: + return 0; + + case processor_t::ev_use_regarg_type: + { + int *used = va_arg(va, int *); + ea_t ea = va_arg(va, ea_t); + const funcargvec_t *rargs = va_arg(va, const funcargvec_t *); + *used = use_hppa_regarg_type(ea, *rargs); + return 1; + } + + case processor_t::ev_use_arg_types: + { + ea_t ea = va_arg(va, ea_t); + func_type_data_t *fti = va_arg(va, func_type_data_t *); + funcargvec_t *rargs = va_arg(va, funcargvec_t *); + use_hppa_arg_types(ea, fti, rargs); + return 1; + } + + case processor_t::ev_get_cc_regs: + { + callregs_t *callregs = va_arg(va, callregs_t *); + cm_t cc = va_argi(va, cm_t); + static const int fastcall_regs[] = { R26, R25, R24, R23, -1 }; + if ( cc == CM_CC_FASTCALL ) + callregs->set(ARGREGS_INDEPENDENT, fastcall_regs, NULL); + else if ( cc == CM_CC_THISCALL ) + callregs->reset(); + else + break; + return 1; + } + + case processor_t::ev_calc_cdecl_purged_bytes: + // calculate number of purged bytes after call + { + // ea_t ea = va_arg(va, ea_t); + return 0; + } + + case processor_t::ev_get_stkarg_offset: + // get offset from SP to the first stack argument + // args: none + // returns: the offset+2 + return -0x34; + +// --- TYPE CALLBACKS + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + hppa_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + hppa_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + hppa_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + hppa_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + hppa_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = hppa_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + case hppa_module_t::ev_is_psw_w: + return psw_w() ? 1 : -1; + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +static const char *const shnames[] = { "hppa", NULL }; +static const char *const lnames[] = +{ + "PA-RISC", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_HPPA, // id + // flag + PRN_HEX // hex numbers + | PR_ALIGN // data items should be aligned + | PR_DEFSEG32 // 32-bit segments by default + | PR_SEGS // has segment registers + | PR_SGROTHER // segment register mean something unknown to the kernel + | PR_STACK_UP // stack grows up + | PR_TYPEINFO // type system is supported + | PR_USE_ARG_TYPES // use ph.use_arg_types() + | PR_DELAYED, // has delayed jumps and calls + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names_plain, // Register names + qnumber(register_names_plain), // Number of registers + + DPSEG, // first + rVds, // last + 8, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + HPPA_null, + HPPA_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + HPPA_rfi, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/i51/ana.cpp b/idasdk76/module/i51/ana.cpp new file mode 100644 index 0000000..3bd6d50 --- /dev/null +++ b/idasdk76/module/i51/ana.cpp @@ -0,0 +1,1083 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su, ig@datarescue.com + * FIDO: 2:5020/209 + * + */ + +#include "i51.hpp" + +//---------------------------------------------------------------------- +inline uint32 get_next_24bits(insn_t &insn) +{ + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_word(); + return low | (high<<16); +} + +//---------------------------------------------------------------------- +static void operand1(insn_t &insn, int nibble) +{ + switch ( nibble ) + { + case 4: + insn.Op1.type = o_reg; + insn.Op1.reg = rAcc; + break; + case 5: + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + break; + case 6: + insn.Op1.type = o_phrase; + insn.Op1.phrase = fR0; + break; + case 7: + insn.Op1.type = o_phrase; + insn.Op1.phrase = fR1; + break; + default: + insn.Op1.type = o_reg; + insn.Op1.phrase = uint16(rR0 + (nibble-8)); + break; + } +} + +//---------------------------------------------------------------------- +static void operand2(insn_t &insn, ushort nibble) +{ + switch ( nibble ) + { + case 4: + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + case 5: + insn.Op2.type = o_mem; + insn.Op2.addr = insn.get_next_byte(); + break; + case 6: + insn.Op2.type = o_phrase; + insn.Op2.phrase = fR0; + break; + case 7: + insn.Op2.type = o_phrase; + insn.Op2.phrase = fR1; + break; + default: + insn.Op2.type = o_reg; + insn.Op2.phrase = rR0 + (nibble-8); + break; + } +} + +//---------------------------------------------------------------------- +inline void opAcc(op_t &op) +{ + op.type = o_reg; + op.reg = rAcc; +} + +//---------------------------------------------------------------------- +inline void opC(op_t &op) +{ + op.type = o_reg; + op.reg = rC; +} + +//---------------------------------------------------------------------- +// register direct +static int op_rd(op_t &x, uint16 reg, uchar dtyp) +{ + if ( reg >= rDR32 && reg <= rDR52 ) + return 0; + x.type = o_reg; + x.dtype = dtyp; + x.reg = reg; + return 1; +} + +//---------------------------------------------------------------------- +// register indirect (fRi registers) +static int op_ph(op_t &x, int reg, uchar dtyp) +{ + if ( reg >= rDR32 && reg <= rDR52 ) + return 0; + x.type = o_phrase; + x.dtype = dtyp; + x.reg = fRi; + x.indreg = uchar(reg); + return 1; +} + +//---------------------------------------------------------------------- +// register indirect +static int op_ph(op_t &op, i51_phrases phr, uchar dtyp, uval_t disp = 0) +{ + op.type = o_phrase; + op.dtype = dtyp; + op.phrase = phr; + if ( disp > 0 ) + { + op.imm_disp = 1; + op.value = disp; + } + return 1; +} + + +//---------------------------------------------------------------------- +// register indirect with displacement +static int op_ds(op_t &x, uint16 phrase, uval_t disp, uchar dtyp) +{ + if ( phrase >= rDR32 && phrase <= rDR52 ) + return 0; + x.type = o_displ; + x.dtype = dtyp; + x.phrase = phrase; + x.addr = disp; + return 1; +} + +//---------------------------------------------------------------------- +inline void op_mm(op_t &x, uval_t addr, uchar dtyp) +{ + x.type = o_mem; + x.dtype = dtyp; + x.addr = addr; +} + +//---------------------------------------------------------------------- +inline void op_near(op_t &x, uval_t addr) +{ + x.type = o_near; + x.dtype = dt_word; + x.addr = addr; +} + +//---------------------------------------------------------------------- +inline void op_im(op_t &x, uval_t value, uchar dtyp) +{ + x.type = o_imm; + x.dtype = dtyp; + x.value = value; +} + +//---------------------------------------------------------------------- +uint32 i51_t::truncate(uval_t addr) const +{ + if ( ptype == prc_51 ) + return addr & 0xFFFF; + else + return addr & 0xFFFFFF; +} + +//---------------------------------------------------------------------- +static int make_short(insn_t &insn, uint16 itype, uchar b) +{ + insn.itype = itype; + static const uchar bregs[] = { rR0, rWR0, 0, rDR0 }; + static const uchar dtyps[] = { dt_byte, dt_word, dt_dword }; + int idx = (b >> 2) & 3; + if ( !op_rd(insn.Op1, bregs[idx] + (b>>4), dtyps[idx]) ) + return 0; + b &= 3; + if ( b == 3 ) + return 0; + op_im(insn.Op2, uval_t(1)<<b, dt_byte); + return insn.size; +} + +//---------------------------------------------------------------------- +// analyze extended instruction set + +int i51_t::ana_extended(insn_t &insn) +{ + int code = insn.get_next_byte(); + if ( (code & 8) == 0 ) + return 0; + if ( (code & 0xF0) >= 0xE0 ) + return 0; + + static const uchar itypes[] = + { +/* 8 9 A B C D E F */ +/* 0 */ I51_jsle, I51_mov, I51_movz, I51_mov, I51_null, I51_null, I51_sra, I51_null, +/* 1 */ I51_jsg, I51_mov, I51_movs, I51_mov, I51_null, I51_null, I51_srl, I51_null, +/* 2 */ I51_jle, I51_mov, I51_null, I51_null, I51_add, I51_add, I51_add, I51_add, +/* 3 */ I51_jg, I51_mov, I51_null, I51_null, I51_null, I51_null, I51_sll, I51_null, +/* 4 */ I51_jsl, I51_mov, I51_null, I51_null, I51_orl, I51_orl, I51_orl, I51_null, +/* 5 */ I51_jsge, I51_mov, I51_null, I51_null, I51_anl, I51_anl, I51_anl, I51_null, +/* 6 */ I51_je, I51_mov, I51_null, I51_null, I51_xrl, I51_xrl, I51_xrl, I51_null, +/* 7 */ I51_jne, I51_mov, I51_mov, I51_null, I51_mov, I51_mov, I51_mov, I51_mov, +/* 8 */ I51_null, I51_ljmp, I51_ejmp, I51_null, I51_div, I51_div, I51_null, I51_null, +/* 9 */ I51_null, I51_lcall, I51_ecall, I51_null, I51_sub, I51_sub, I51_sub, I51_sub, +/* A */ I51_null, I51_last, I51_eret, I51_null, I51_mul, I51_mul, I51_null, I51_null, +/* B */ I51_null, I51_trap, I51_null, I51_null, I51_cmp, I51_cmp, I51_cmp, I51_cmp, +/* C */ I51_null, I51_null, I51_push, I51_null, I51_null, I51_null, I51_null, I51_null, +/* D */ I51_null, I51_null, I51_pop, I51_null, I51_null, I51_null, I51_null, I51_null, + }; + insn.itype = itypes[ ((code&0xF0)>>1) | (code & 7) ]; + if ( insn.itype == I51_null ) + return 0; + + uchar b1, b2; + int oax = 0; + switch ( code ) + { + case 0x08: // rel + case 0x18: + case 0x28: + case 0x38: + case 0x48: + case 0x58: + case 0x68: + case 0x78: + { + insn.Op1.type = o_near; + insn.Op1.dtype = dt_word; + signed char off = insn.get_next_byte(); + insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition + } + break; + + case 0x09: // mov Rm, @WRj+dis + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rR0 +(b1>>4), dt_byte); + insn.Op2.offb = (uchar)insn.size; + op_ds(insn.Op2, rWR0+(b1&15), insn.get_next_word(), dt_byte); + break; + + case 0x49: // mov WRk, @WRj+dis + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + insn.Op2.offb = (uchar)insn.size; + op_ds(insn.Op2, rWR0+(b1&15), insn.get_next_word(), dt_word); + break; + + case 0x29: // mov Rm, @DRj+dis + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rR0 +(b1>>4), dt_byte); + insn.Op2.offb = (uchar)insn.size; + if ( !op_ds(insn.Op2, rDR0+(b1&15), insn.get_next_word(), dt_byte) ) + return 0; + break; + + case 0x69: // mov WRj, @DRk+dis + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + insn.Op2.offb = (uchar)insn.size; + if ( !op_ds(insn.Op2, rDR0+(b1&15), insn.get_next_word(), dt_word) ) + return 0; + break; + + case 0x19: // mov @WRj+dis, Rm + b1 = insn.get_next_byte(); + insn.Op1.offb = (uchar)insn.size; + op_ds(insn.Op1, rWR0+(b1&15), insn.get_next_word(), dt_byte); + op_rd(insn.Op2, rR0 +(b1>>4), dt_byte); + break; + + case 0x59: // mov @WRj+dis, WRk + b1 = insn.get_next_byte(); + insn.Op1.offb = (uchar)insn.size; + op_ds(insn.Op1, rWR0+(b1&15), insn.get_next_word(), dt_word); + op_rd(insn.Op2, rWR0+(b1>>4), dt_word); + break; + + case 0x39: // mov @DRj+dis, Rm + b1 = insn.get_next_byte(); + insn.Op1.offb = (uchar)insn.size; + if ( !op_ds(insn.Op1, rDR0+(b1&15), insn.get_next_word(), dt_byte) ) + return 0; + op_rd(insn.Op2, rR0 +(b1>>4), dt_byte); + break; + + case 0x79: // mov @DRk+dis, WRj + b1 = insn.get_next_byte(); + insn.Op1.offb = (uchar)insn.size; + if ( !op_ds(insn.Op1, rDR0+(b1&15), insn.get_next_word(), dt_word) ) + return 0; + op_rd(insn.Op2, rWR0+(b1>>4), dt_word); + break; + + case 0x0A: // movz WRj, Rm + case 0x1A: // movs WRj, Rm + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + op_rd(insn.Op2, rR0 +(b1&15), dt_byte); + break; + + case 0x0B: // 1000 mov WRj, @WRj + // 1010 mov WRj, @DRk + { + b1 = insn.get_next_byte(); + int ri; + switch ( b1 & 15 ) + { + case 0x8: ri = rWR0; break; + case 0xA: ri = rDR0; break; + case 0x9: return 0; + case 0xB: return 0; + default: return make_short(insn, I51_inc, b1); + } + b2 = insn.get_next_byte(); + if ( b2 & 15 ) + return 0; + op_rd(insn.Op1, rWR0+(b2>>4), dt_word); + if ( !op_ph(insn.Op2, ri + (b1>>4), dt_word) ) + return 0; + } + break; + + case 0x1B: // 1000 mov @WRj, WRj + // 1010 mov @DRk, WRj + { + b1 = insn.get_next_byte(); + int ri; + switch ( b1 & 15 ) + { + case 0x8: ri = rWR0; break; + case 0xA: ri = rDR0; break; + case 0x9: return 0; + case 0xB: return 0; + default: return make_short(insn, I51_dec, b1); + } + b2 = insn.get_next_byte(); + if ( b2 & 15 ) + return 0; + if ( !op_ph(insn.Op1, ri + (b1>>4), dt_word) ) + return 0; + op_rd(insn.Op2, rWR0+(b2>>4), dt_word); + } + break; + + case 0x7A: + { + b1 = insn.get_next_byte(); + switch ( b1&15 ) + { + case 9: // 1001 mov @WRj, Rm + case 0xB: // 1011 mov @DRk, Rm + b2 = insn.get_next_byte(); + if ( b2 & 15 ) + return 0; + if ( !op_ph(insn.Op1, ((b1&2) ? rDR0 : rWR0) + (b1>>4), dt_byte) ) + return 0; + op_rd(insn.Op2, rR0+(b2>>4), dt_byte); + break; + case 0xC: // movh DRk, #data16 + insn.itype = I51_movh; + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + insn.Op2.offb = (uchar)insn.size; + op_im(insn.Op2, insn.get_next_word(), dt_word); + break; + default: + goto CONT; + } + break; +CONT: + uval_t addr = (b1&2) ? insn.get_next_word() : insn.get_next_byte(); + switch ( b1&15 ) + { + case 0x1: // mov dir8, Rm + case 0x3: // mov dir16, Rm + op_mm(insn.Op1, addr, dt_byte); + op_rd(insn.Op2, rR0+(b1>>4), dt_byte); + break; + case 0x5: // mov dir8, WRj + case 0x7: // mov dir16, WRj + op_mm(insn.Op1, addr, dt_word); + op_rd(insn.Op2, rWR0+(b1>>4), dt_word); + break; + case 0xD: // mov dir8, DRj + case 0xF: // mov dir16, DRj + op_mm(insn.Op1, addr, dt_dword); + if ( !op_rd(insn.Op2, rDR0+(b1>>4), dt_dword) ) + return 0; + break; + default: return 0; + } + } + break; + + case 0x89: // ljmp @WRj or @DRj + case 0x99: // lcall @WRj or @DRj + { + int r; + uchar dt; + b1 = insn.get_next_byte(); + switch ( b1 & 15 ) + { + case 4: + r = rWR0; + dt = dt_word; + break; + case 8: + r = rDR0; + dt = dt_dword; + insn.itype = (insn.itype == I51_ljmp) ? I51_ejmp : I51_ecall; + break; + default: + return 0; + } + if ( !op_ph(insn.Op1, r+(b1>>4), dt) ) + return 0; + } + break; + + case 0x8A: // ejmp addr24 + case 0x9A: // ecall addr24 + op_near(insn.Op1, get_next_24bits(insn)); + break; + + case 0xAA: // eret + case 0xB9: // trap + break; + + case 0xCA: // push + case 0xDA: // pop + b1 = insn.get_next_byte(); + switch ( b1 & 15 ) + { + case 0x1: // mov DRk, PC + if ( code != 0xCA ) + return 0; + insn.itype = I51_mov; + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + op_rd(insn.Op2, rPC, dt_dword); + break; + case 0x2: // #data8 + insn.Op1.offb = (uchar)insn.size; + op_im(insn.Op1, insn.get_next_byte(), dt_byte); + break; + case 0x6: // #data16 + insn.Op1.offb = (uchar)insn.size; + op_im(insn.Op1, insn.get_next_word(), dt_word); + break; + case 0x8: // Rm + op_rd(insn.Op1, rR0+(b1>>4), dt_byte); + break; + case 0x9: // WRj + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + break; + case 0xB: // DRj + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + break; + default: + return 0; + } + break; + + case 0xA9: // bit instructions + { + static const uchar subtypes[] = + { + I51_null, I51_jbc, I51_jb, I51_jnb, + I51_null, I51_null, I51_null, I51_orl, + I51_anl, I51_mov, I51_mov, I51_cpl, + I51_clr, I51_setb, I51_orl, I51_anl + }; + b1 = insn.get_next_byte(); + if ( b1 & 8 ) + return 0; + insn.itype = subtypes[ b1 >> 4]; + if ( insn.itype == I51_null ) + return 0; + insn.Op1.type = o_bit251; + insn.Op1.dtype = dt_byte; + insn.Op1.b251_bit = b1 & 7; + insn.Op1.addr = insn.get_next_byte(); + insn.Op1.b251_bitneg = 0; + switch ( b1 >> 4 ) + { + case 0x1: // jbc bit, rel + case 0x2: // jb bit, rel + case 0x3: // jnb bit, rel + { + signed char rel = insn.get_next_byte(); + op_near(insn.Op2, truncate(insn.ip + insn.size + rel)); + } + break; + case 0xE: // orl cy, /bit + case 0xF: // anl cy, /bit + insn.Op1.b251_bitneg = 1; + /* no break */ + case 0x7: // orl cy, bit + case 0x8: // anl cy, bit + case 0xA: // mov cy, bit + insn.Op2 = insn.Op1; + opC(insn.Op1); + break; + case 0x9: // mov bit, cy + opC(insn.Op2); + break; + case 0xB: // cpl bit + case 0xC: // clr bit + case 0xD: // setb bit + break; + } + } + break; + + case 0x0E: // sra + case 0x1E: // srl + case 0x3E: // sll + b1 = insn.get_next_byte(); + switch ( b1 & 15 ) + { + case 0: + op_rd(insn.Op1, rR0 +(b1>>4), dt_byte); + break; + case 4: + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + break; + default: + return 0; + } + break; + + case 0x2C: // add Rm, Rm + case 0x4C: // orl Rm, Rm + case 0x5C: // anl Rm, Rm + case 0x6C: // xrl Rm, Rm + case 0x7C: // mov Rm, Rm + case 0x8C: // div Rm, Rm + case 0x9C: // sub Rm, Rm + case 0xAC: // mul Rm, Rm + case 0xBC: // cmp Rm, Rm + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rR0+(b1>>4), dt_byte); + op_rd(insn.Op2, rR0+(b1&15), dt_byte); + break; + + case 0x2D: // add WRj, WRj + case 0x4D: // orl WRj, WRj + case 0x5D: // anl WRj, WRj + case 0x6D: // xrl WRj, WRj + case 0x7D: // mov WRj, WRj + case 0x8D: // div WRj, WRj + case 0x9D: // sub WRj, WRj + case 0xAD: // mul WRj, WRj + case 0xBD: // cmp WRj, WRj + b1 = insn.get_next_byte(); + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + op_rd(insn.Op2, rWR0+(b1&15), dt_word); + break; + + case 0x2F: // add DRj, DRj + case 0x7F: // mov DRj, DRj + case 0x9F: // sub DRj, DRj + case 0xBF: // cmp DRj, DRj + b1 = insn.get_next_byte(); + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + if ( !op_rd(insn.Op2, rDR0+(b1&15), dt_dword) ) + return 0; + break; + + case 0x4E: // orl reg, op2 + case 0x5E: // anl reg, op2 + case 0x6E: // xrl reg, op2 + oax = 1; // orl, anl, xrl + /* no break */ + case 0x2E: // add reg, op2 + case 0x7E: // mov reg, op2 + case 0x8E: // div reg, op2 + case 0x9E: // sub reg, op2 + case 0xAE: // mul reg, op2 + case 0xBE: // cmp reg, op2 + b1 = insn.get_next_byte(); + switch ( b1 & 15 ) + { + case 0x0: // Rm, #8 + op_rd(insn.Op1, rR0+(b1>>4), dt_byte); + insn.Op2.offb = (uchar)insn.size; + op_im(insn.Op2, insn.get_next_byte(), dt_byte); + break; + case 0x4: // WRj, #16 + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + insn.Op2.offb = (uchar)insn.size; + op_im(insn.Op2, insn.get_next_word(), dt_word); + break; + case 0x8: // DRk, #16 + if ( oax ) + return 0; + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + insn.Op2.offb = (uchar)insn.size; + op_im(insn.Op2, insn.get_next_word(), dt_word); + break; + case 0xC: // DRk, #(1)16 + if ( oax ) + return 0; + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + insn.Op2.offb = (uchar)insn.size; + op_im(insn.Op2, insn.get_next_word(), dt_word); + insn.auxpref |= aux_1ext; + break; + case 0x1: // Rm, dir8 + op_rd(insn.Op1, rR0+(b1>>4), dt_byte); + op_mm(insn.Op2, insn.get_next_byte(), dt_byte); + break; + case 0x5: // WRj, dir8 + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + op_mm(insn.Op2, insn.get_next_byte(), dt_word); + break; + case 0xD: // DRk, dir8 + if ( oax ) + return 0; + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + op_mm(insn.Op2, insn.get_next_byte(), dt_word); + break; + case 0x3: // Rm, dir16 + op_rd(insn.Op1, rR0+(b1>>4), dt_byte); + op_mm(insn.Op2, insn.get_next_word(), dt_byte); + break; + case 0x7: // WRj, dir16 + op_rd(insn.Op1, rWR0+(b1>>4), dt_word); + op_mm(insn.Op2, insn.get_next_word(), dt_word); + break; + case 0xF: // DRk, dir16 + if ( code != 0x7E ) + return 0; // only mov works + if ( !op_rd(insn.Op1, rDR0+(b1>>4), dt_dword) ) + return 0; + op_mm(insn.Op2, insn.get_next_word(), dt_word); + break; + case 0x9: // Rm, @WRj + b2 = insn.get_next_byte(); + if ( b2 & 15 ) + return 0; + op_rd(insn.Op1, rR0 +(b2>>4), dt_byte); + op_ph(insn.Op2, rWR0+(b1>>4), dt_byte); + break; + case 0xB: // Rm, @DRk + b2 = insn.get_next_byte(); + if ( b2 & 15 ) + return 0; + op_rd(insn.Op1, rR0 +(b2>>4), dt_byte); + if ( !op_ph(insn.Op2, rDR0+(b1>>4), dt_byte) ) + return 0; + break; + default: + return 0; + } + break; + + default: + error("%a: internal ana_extended() error, code=%x", insn.ea, code); + } + + return insn.size; +} + +//---------------------------------------------------------------------- +// analyze an basic instruction +int i51_t::ana_basic(insn_t &insn) +{ + ushort code = insn.get_next_byte(); + bool mx_a5 = false; + if ( code == 0xA5 && ptype == prc_51mx ) + { + code = insn.get_next_byte(); + mx_a5 = true; + } + + ushort nibble0 = (code & 0xF); + ushort nibble1 = (code >> 4); + char off; + if ( mx_a5 ) + { + if ( nibble1 == 0x6 && nibble0 >= 0x8 ) // ADD PRi,#data2 (0 1 1 0 1 i d1 d2) + { + insn.itype = I51_add; + op_rd(insn.Op1, (nibble0 & 4) == 0 ? rPR0 : rPR1, dt_dword); + int val = nibble0 & 3; + op_im(insn.Op2, val == 0 ? 4 : val, dt_byte); + return insn.size; + } + if ( nibble1 == 0x4 && nibble0 >= 0x8 ) // EMOVE A, @PRi+#data2 + { + insn.itype = I51_emov; + opAcc(insn.Op1); + int val = nibble0 & 3; + op_ph(insn.Op2, (nibble0 & 4) == 0 ? fPr0 : fPr1, dt_dword, val == 0 ? 4 : val); + return insn.size; + } + if ( nibble1 == 0x5 && nibble0 >= 0x8 ) // EMOVE @PRi+#data2, A + { + insn.itype = I51_emov; + int val = nibble0 & 3; + op_ph(insn.Op1, (nibble0 & 4) == 0 ? fPr0 : fPr1, dt_dword, val == 0 ? 4 : val); + opAcc(insn.Op2); + return insn.size; + } + } + if ( nibble0 < 4 ) // complex coding, misc instructions + { + switch ( nibble0 ) + { + case 0: + { + static const uchar misc0[16] = + { + I51_nop, I51_jbc, I51_jb, I51_jnb, + I51_jc, I51_jnc, I51_jz, I51_jnz, + I51_sjmp,I51_mov, I51_orl, I51_anl, + I51_push,I51_pop, I51_movx,I51_movx + }; + insn.itype = misc0[nibble1]; + } + switch ( nibble1 ) + { + case 0x1: case 0x2: case 0x3: // jbc, jb, jnb + insn.Op1.type = o_bit; + insn.Op1.reg = insn.get_next_byte(); + insn.Op2.type = o_near; + off = insn.get_next_byte(); + insn.Op2.addr = truncate(insn.ip + insn.size + off); // signed addition + insn.Op2.dtype = dt_word; + break; + case 0x4: case 0x5: case 0x6: case 0x7: case 0x8: // jc, jnc, jz, jnz, sjmp + insn.Op1.type = o_near; + off = insn.get_next_byte(); + insn.Op1.addr = truncate(insn.ip + insn.size + off); // signed addition + insn.Op1.dtype = dt_word; + break; + case 0x9: // mov + insn.Op1.type = o_reg; + insn.Op1.reg = mx_a5 ? rEptr : rDptr; + insn.Op1.dtype = mx_a5 ? dt_dword : dt_word; + insn.Op2.type = o_imm; + insn.Op2.offb = (uchar)insn.size; + if ( mx_a5 ) + { + insn.Op2.value = (((ea_t)insn.get_next_word()) << 8) + insn.get_next_byte(); + insn.Op2.dtype = dt_dword; + } + else + { + insn.Op2.value = insn.get_next_word(); + insn.Op2.dtype = dt_word; + } + break; + case 0xA: case 0xB: // orl, anl + opC(insn.Op1); + insn.Op2.type = o_bitnot; + insn.Op2.reg = insn.get_next_byte(); + break; + case 0xC: case 0xD: // push, pop + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + break; + case 0xE: // movx + opAcc(insn.Op1); + insn.Op2.type = o_phrase; + insn.Op2.phrase = mx_a5 ? fEptr : fDptr; + break; + case 0xF: // movx + opAcc(insn.Op2); + insn.Op1.type = o_phrase; + insn.Op1.phrase = mx_a5 ? fEptr : fDptr; + break; + } + break; + case 1: // acall, ajmp + { + ushort lowbits = insn.get_next_byte(); + insn.Op1.type = o_near; + insn.Op1.addr = truncate((code&0xE0)<<3) + lowbits + ((insn.ip+insn.size) & ~0x7FF); + insn.Op1.dtype = dt_word; + insn.itype = (nibble1 & 1) ? I51_acall : I51_ajmp; + } + break; + case 2: + { + static const uchar misc2[16] = + { + I51_ljmp,I51_lcall,I51_ret,I51_reti, + I51_orl, I51_anl, I51_xrl, I51_orl, + I51_anl, I51_mov, I51_mov, I51_cpl, + I51_clr, I51_setb,I51_movx,I51_movx + }; + insn.itype = misc2[nibble1]; + } + switch ( nibble1 ) + { + case 0x0: case 0x1: // ljump (ejmp), lcall (ecall) + insn.Op1.type = o_near; + if ( mx_a5 ) // ecall + { + insn.itype = nibble1 == 0 ? I51_ejmp : I51_ecall; + insn.Op1.addr = (((ea_t)insn.get_next_word()) << 8) + insn.get_next_byte(); + if ( insn.Op1.addr >= 0x800000 ) + insn.Op1.addr -= 0x800000; + } + else + { + insn.Op1.addr = insn.get_next_word(); + } + insn.Op1.addr|= (insn.ip+insn.size) & ~0xFFFF; + insn.Op1.dtype = mx_a5 ? dt_dword : dt_word; + break; + case 0x2: // ret (eret); + if ( mx_a5 ) + insn.itype = I51_eret; + break; + case 0x4: case 0x5: case 0x6: // orl, anl, xrl, + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + opAcc(insn.Op2); + break; + case 0x7: case 0x8: case 0xA: // orl, anl, mov + opC(insn.Op1); + insn.Op2.type = o_bit; + insn.Op2.reg = insn.get_next_byte(); + break; + case 0x9: // mov + opC(insn.Op2); + /* no break */ + case 0xB: case 0xC: case 0xD: // cpl, clr, setb + insn.Op1.type = o_bit; + insn.Op1.reg = insn.get_next_byte(); + break; + case 0xE: // movx + opAcc(insn.Op1); + insn.Op2.type = o_phrase; + insn.Op2.phrase = fR0; + break; + case 0xF: // movx + insn.Op1.type = o_phrase; + insn.Op1.phrase = fR0; + opAcc(insn.Op2); + break; + } + break; + case 3: + { + static const uchar misc3[16] = + { + I51_rr, I51_rrc, I51_rl, I51_rlc, + I51_orl, I51_anl, I51_xrl, I51_jmp, + I51_movc,I51_movc,I51_inc, I51_cpl, + I51_clr, I51_setb,I51_movx,I51_movx + }; + insn.itype = misc3[nibble1]; + } + switch ( nibble1 ) + { + case 0x0: case 0x1: case 0x2: case 0x3: // rr, rrc, rl, rlc + opAcc(insn.Op1); + break; + case 0x4: case 0x5: case 0x6: // orl, anl, xrl + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + insn.Op2.offb = (uchar)insn.size; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + case 0x7: // jmp + insn.Op1.type = o_phrase; + insn.Op1.phrase = mx_a5 ? fAeptr : fAdptr; + break; + case 0x8: case 0x9: // movc + opAcc(insn.Op1); + insn.Op2.type = o_phrase; + insn.Op2.phrase = nibble1 == 0x8 ? fApc : (mx_a5 ? fAeptr : fAdptr); + break; + case 0xA: // inc + insn.Op1.type = o_reg; + insn.Op1.reg = mx_a5 ? rEptr : rDptr; + insn.Op1.dtype = mx_a5 ? dt_dword : dt_word; + break; + case 0xB: case 0xC: case 0xD: // cpl, clr, setb + opC(insn.Op1); + break; + case 0xE: // movx + opAcc(insn.Op1); + insn.Op2.type = o_phrase; + insn.Op2.phrase = fR1; + break; + case 0xF: // movx + insn.Op1.type = o_phrase; + insn.Op1.phrase = fR1; + opAcc(insn.Op2); + break; + } + break; + } + } + else + { // i.e. nibble0 >= 4 + static const uchar regulars[16] = + { + I51_inc, I51_dec, I51_add, I51_addc, + I51_orl, I51_anl, I51_xrl, I51_mov, + I51_mov, I51_subb,I51_mov, I51_cjne, + I51_xch, I51_djnz,I51_mov, I51_mov + }; + insn.itype = regulars[nibble1]; + switch ( nibble1 ) + { + case 0x00: case 0x01: // inc, dec + operand1(insn, nibble0); + break; + case 0x0C: // xch + if ( nibble0 == 4 ) + { + insn.itype = I51_swap; + opAcc(insn.Op1); + break; + } + // fallthrough + case 0x02: case 0x03: case 0x04: // add, addc, orl + case 0x05: case 0x06: case 0x09: // anl, xrl, subb + operand2(insn, nibble0); + opAcc(insn.Op1); + break; + case 0x07: // mov + operand1(insn, nibble0); + insn.Op2.offb = (uchar)insn.size; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + break; + case 0x08: // mov + if ( nibble0 == 4 ) + { + insn.itype = I51_div; + insn.Op1.type = o_reg; + insn.Op1.reg = rAB; + break; + } + operand2(insn, nibble0); + insn.Op1.type = o_mem; + insn.Op1.addr = insn.get_next_byte(); + break; + case 0x0A: // mov + if ( nibble0 == 4 ) + { + insn.itype = I51_mul; + insn.Op1.type = o_reg; + insn.Op1.reg = rAB; + break; + } + if ( nibble0 == 5 ) + return 0; // mov to imm - no sense (0xA5) + operand1(insn, nibble0); + insn.Op2.type = o_mem; + insn.Op2.addr = insn.get_next_byte(); + break; + case 0x0B: // cjne + if ( nibble0 == 5 ) + { + opAcc(insn.Op1); + insn.Op2.type = o_mem; + insn.Op2.addr = insn.get_next_byte(); + } + else + { + operand1(insn, nibble0); + insn.Op2.offb = (uchar)insn.size; + insn.Op2.type = o_imm; + insn.Op2.value = insn.get_next_byte(); + } + insn.Op3.type = o_near; + off = insn.get_next_byte(); + insn.Op3.addr = truncate(insn.ip + insn.size + off); // signed addition + insn.Op3.dtype = dt_word; + break; + case 0x0D: // djnz + switch ( nibble0 ) + { + case 4: + insn.itype = I51_da; + opAcc(insn.Op1); + break; + case 6: case 7: + insn.itype = I51_xchd; + opAcc(insn.Op1); + operand2(insn, nibble0); + break; + default: + operand1(insn, nibble0); + off = insn.get_next_byte(); + insn.Op2.type = o_near; + insn.Op2.addr = truncate(insn.ip + insn.size + off); // signed addition + insn.Op2.dtype = dt_word; + break; + } + break; + case 0x0E: // mov + opAcc(insn.Op1); + if ( nibble0 == 4 ) + { + insn.itype = I51_clr; + break; + } + operand2(insn, nibble0); + break; + case 0x0F: // mov + if ( nibble0 == 4 ) + { + insn.itype = I51_cpl; + opAcc(insn.Op1); + break; + } + operand1(insn, nibble0); + insn.Op2.type = o_reg; + insn.Op2.reg = rAcc; + break; + } + } + return insn.size; +} + +//---------------------------------------------------------------------- +// analyze an instruction +int i51_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + insn.Op1.dtype = dt_byte; + insn.Op2.dtype = dt_byte; + insn.Op3.dtype = dt_byte; + + uchar code = get_byte(insn.ea); + switch ( ptype ) + { + case prc_51: + case prc_51mx: + return ana_basic(insn); + + case prc_251_src: + case prc_930_src: + if ( code == 0xA5 ) + { + insn.size++; // skip A5 + code = get_byte(insn.ea+1); + if ( (code & 15) < 6 ) + return 0; + return ana_basic(insn); + } + if ( (code & 15) < 6 ) + return ana_basic(insn); + return ana_extended(insn); + + case prc_251_bin: + case prc_930_bin: + if ( code == 0xA5 ) + { + insn.size++; // skip A5 + return ana_extended(insn); + } + return ana_basic(insn); + } + return 0; //lint !e527 statement is unreachable +} diff --git a/idasdk75/module/i51/emu.cpp b/idasdk76/module/i51/emu.cpp similarity index 100% rename from idasdk75/module/i51/emu.cpp rename to idasdk76/module/i51/emu.cpp diff --git a/idasdk76/module/i51/i51.cfg b/idasdk76/module/i51/i51.cfg new file mode 100644 index 0000000..1809387 --- /dev/null +++ b/idasdk76/module/i51/i51.cfg @@ -0,0 +1,17356 @@ +; The format of the input file: +; each device definition begins with a line like this: +; +; .devicename +; +; after it go the port definitions in this format: +; +; portname address +; +; the bit definitions (optional) are represented like this: +; +; portname.bitname bitnumber +; +; lines beginning with a space are ignored. +; comment lines should be started with ';' character. +; +; the default device is specified at the start of the file +; +; .default device_name +; +; all lines non conforming to the format are passed to the callback function +; +; MOTOROLA SPECIFIC LINES +;------------------------ +; +; the processor definition may include the memory configuration. +; the line format is: + +; area CLASS AREA-NAME START:END +; +; where CLASS is anything, but please use one of CODE, DATA, BSS +; START and END are addresses, the end address is not included + +; Interrupt vectors are declared in the following way: + +; interrupt NAME ADDRESS COMMENT + +.default C517 + +.C501 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8006&parent_oid=13727 +; d501.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 interrupt +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 interrupt +entry RI_TI 0x0023 Serial port interrupt +entry TF2_EXF2 0x002B Timer 2 interrupt + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +RESERVED0086 0x0086 RESERVED +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.P17 7 +P1.P16 6 +P1.P15 5 +P1.P14 4 +P1.P13 3 +P1.P12 2 +P1.P11 1 +P1.P10 0 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IE 0x00A8 Interrupt Enable Register +IE.EA 7 +IE.ET2 5 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 +RESERVED00A9 0x00A9 RESERVED +RESERVED00AA 0x00AA RESERVED +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +RESERVED00B1 0x00B1 RESERVED +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IP 0x00B8 Interrupt Priority Register +IP.PT2 5 +IP.PS 4 +IP.PT1 3 +IP.PX1 2 +IP.PT0 1 +IP.PX0 0 +RESERVED00B9 0x00B9 RESERVED +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +RESERVED00C0 0x00C0 RESERVED +RESERVED00C1 0x00C1 RESERVED +RESERVED00C2 0x00C2 RESERVED +RESERVED00C3 0x00C3 RESERVED +RESERVED00C4 0x00C4 RESERVED +RESERVED00C5 0x00C5 RESERVED +RESERVED00C6 0x00C6 RESERVED +RESERVED00C7 0x00C7 RESERVED +T2CON 0x00C8 Timer 2 Control Register +T2CON.TF2 7 +T2CON.EXF2 6 +T2CON.RCLK 5 +T2CON.TCLK 4 +T2CON.EXEN2 3 +T2CON.TR2 2 +T2CON.C_T2 1 +T2CON.CP_RL2 0 +T2MOD 0x00C9 Timer 2 Mode Register +T2MOD.DCEN 0 +RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte +RC2L.RC2L7 7 +RC2L.RC2L6 6 +RC2L.RC2L5 5 +RC2L.RC2L4 4 +RC2L.RC2L3 3 +RC2L.RC2L2 2 +RC2L.RC2L1 1 +RC2L.RC2L0 0 +RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte +RC2H.RC2H7 7 +RC2H.RC2H6 6 +RC2H.RC2H5 5 +RC2H.RC2H4 4 +RC2H.RC2H3 3 +RC2H.RC2H2 2 +RC2H.RC2H1 1 +RC2H.RC2H0 0 +TL2 0x00CC Timer 2 Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2 High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +RESERVED00D8 0x00D8 RESERVED +RESERVED00D9 0x00D9 RESERVED +RESERVED00DA 0x00DA RESERVED +RESERVED00DB 0x00DB RESERVED +RESERVED00DC 0x00DC RESERVED +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +RESERVED00E8 0x00E8 RESERVED +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C504 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=28993&parent_oid=12032 +; SAF-C504-2E40M.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xFF00 +area DATA XRAM 0xFF00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 interrupt +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 interrupt +entry RI_TI 0x0023 Serial port interrupt +entry TF2_EXF2 0x002B Timer 2 interrupt +entry IE2 0x004B External interrupt 2 +entry TRF_BCERR 0x0053 CAPCOM emergency interrupt +entry CT2P 0x005B Compare timer 2 interrupt +entry CC0F_R_CC2F_R 0x0063 Capture/compare match interrupt +entry CT1FP_CT1FC 0x006B Compare timer 1 interrupt +entry PDINT 0x007B Power-down interrupt + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.P17 7 +P1.P16 6 +P1.P15 5 +P1.P14 4 +P1.P13 3 +P1.P12 2 +P1.T2EX 1 +P1.T2 0 +; P1ANA 0x0090 Port 1 Analog Input Selection Register +; P1ANA.EAN3 3 +; P1ANA.EAN2 2 +; P1ANA.EAN1 1 +; P1ANA.EAN0 0 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +ITCON 0x009A Interrupt Trigger Condition Register +ITCON.IT2 7 +ITCON.IE2 6 +ITCON.I2ETF 5 +ITCON.I2ETR 4 +ITCON.I1ETF 3 +ITCON.I1ETR 2 +ITCON.I0ETF 1 +ITCON.I0ETR 0 +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IEN1 0x00A9 Interrupt Enable Register 1 +IEN1.ECT1 5 +IEN1.ECCM 4 +IEN1.ECT2 3 +IEN1.ECEM 2 +IEN1.EX2 1 +IEN1.EADC 0 +RESERVED00AA 0x00AA RESERVED +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +; P3ANA 0x00B0 Port 3 Analog Input Selection Register +; P3ANA.EAN7 5 +; P3ANA.EAN6 4 +; P3ANA.EAN5 3 +; P3ANA.EAN4 2 +SYSCON 0x00B1 System Control Register +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.XMAP 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IP0 0x00B8 Interrupt Priority Register 0 +IP0.PT2 5 +IP0.PS 4 +IP0.PT1 3 +IP0.PX1 2 +IP0.PT0 1 +IP0.PX0 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.PCT1 5 +IP1.PCCM 4 +IP1.PCT2 3 +IP1.PCEM 2 +IP1.PX2 1 +IP1.PADC 0 +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +WDCON 0x00C0 Watchdog Timer Control Register +WDCON.OWDS 3 +WDCON.WDTS 2 +WDCON.WDT 1 +WDCON.SWDT 0 +CT2CON 0x00C1 Compare timer 2 control register +CT2CON.CT2P 7 +CT2CON.ECT2O 6 +CT2CON.STE2 5 +CT2CON.CT2RES 4 +CT2CON.CT2R 3 +CT2CON.CLK2 2 +CT2CON.CLK1 1 +CT2CON.CLK0 0 +CCL0 0x00C2 Capture/compare register 0, low byte +CCL0.CCL07 7 +CCL0.CCL06 6 +CCL0.CCL05 5 +CCL0.CCL04 4 +CCL0.CCL03 3 +CCL0.CCL02 2 +CCL0.CCL01 1 +CCL0.CCL00 0 +CCH0 0x00C3 Capture/compare register 0, high byte +CCH0.CCH07 7 +CCH0.CCH06 6 +CCH0.CCH05 5 +CCH0.CCH04 4 +CCH0.CCH03 3 +CCH0.CCH02 2 +CCH0.CCH01 1 +CCH0.CCH00 0 +CCL1 0x00C4 Capture/compare register 1, low byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C5 Capture/compare register 1, high byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C6 Capture/compare register 2, low byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C7 Capture/compare register 2, high byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.TF2 7 +T2CON.EXF2 6 +T2CON.RCLK 5 +T2CON.TCLK 4 +T2CON.EXEN2 3 +T2CON.TR2 2 +T2CON.C_T2 1 +T2CON.CP_RL2 0 +T2MOD 0x00C9 Timer 2 Mode Register +T2MOD.DCEN 0 +RC2L 0x00CA Timer 2 Reload Capture Register, Low Byte +RC2L.RC2L7 7 +RC2L.RC2L6 6 +RC2L.RC2L5 5 +RC2L.RC2L4 4 +RC2L.RC2L3 3 +RC2L.RC2L2 2 +RC2L.RC2L1 1 +RC2L.RC2L0 0 +RC2H 0x00CB Timer 2 Reload Capture Register, High Byte +RC2H.RC2H7 7 +RC2H.RC2H6 6 +RC2H.RC2H5 5 +RC2H.RC2H4 4 +RC2H.RC2H3 3 +RC2H.RC2H2 2 +RC2H.RC2H1 1 +RC2H.RC2H0 0 +TL2 0x00CC Timer 2 Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2 High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +TRCON 0x00CF Trap enable control register +TRCON.TRPEN 7 +TRCON.TRF 6 +TRCON.TREN5 5 +TRCON.TREN4 4 +TRCON.TREN3 3 +TRCON.TREN2 2 +TRCON.TREN1 1 +TRCON.TREN0 0 +PSW 0x00D0 Program Status Word Register +PSW.CY 7 Carry Flag +PSW.AC 6 Auxiliary Carry Flag +PSW.F0 5 General Purpose Flag 0 +PSW.RS1 4 Register Bank Select Control bit 1 +PSW.RS0 3 Register Bank Select Control bit 2 +PSW.OV 2 Overflow Flag +PSW.F1 1 General Purpose Flag 1 +PSW.P 0 Parity Flag +RESERVED00D1 0x00D1 RESERVED +CP2L 0x00D2 Compare timer 2 period register, low byte +CP2L.CP2L7 7 +CP2L.CP2L6 6 +CP2L.CP2L5 5 +CP2L.CP2L4 4 +CP2L.CP2L3 3 +CP2L.CP2L2 2 +CP2L.CP2L1 1 +CP2L.CP2L0 0 +CP2H 0x00D3 Compare timer 2 period register, high byte +CP2H.CP2H1 1 +CP2H.CP2H0 0 +CMP2L 0x00D4 Compare timer 2 compare register, low byte +CMP2L.CMP2L7 7 +CMP2L.CMP2L6 6 +CMP2L.CMP2L5 5 +CMP2L.CMP2L4 4 +CMP2L.CMP2L3 3 +CMP2L.CMP2L2 2 +CMP2L.CMP2L1 1 +CMP2L.CMP2L0 0 +CMP2H 0x00D5 Compare timer 2 compare register, high byte +CMP2H.CMP2H1 1 +CMP2H.CMP2H0 0 +CCIE 0x00D6 Capture/Compare Interrupt Enable Reg. +CCIE.ECTP 7 +CCIE.ECTC 6 +CCIE.CC2FEN 5 +CCIE.CC2REN 4 +CCIE.CC1FEN 3 +CCIE.CC1REN 2 +CCIE.CC0FEN 1 +CCIE.CC0REN 0 +BCON 0x00D7 Block commutation control register +BCON.BCMPBCEM 7 +BCON.PWM1 6 +BCON.PWM0 5 +BCON.EBCE 4 +BCON.BCERR 3 +BCON.BCEN 2 +BCON.BCM1 1 +BCON.BCM0 0 +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.IADC 5 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register High Byte +ADDATH.ADDATH9 7 +ADDATH.ADDATH8 6 +ADDATH.ADDATH7 5 +ADDATH.ADDATH6 4 +ADDATH.ADDATH5 3 +ADDATH.ADDATH4 2 +ADDATH.ADDATH3 1 +ADDATH.ADDATH2 0 +ADDATL 0x00DA A/D Converter Data Register Low Byte +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +RESERVED00DB 0x00DB RESERVED +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +CCPL 0x00DE Compare timer 1 period register, low byte +CCPL.CCPL7 7 +CCPL.CCPL6 6 +CCPL.CCPL5 5 +CCPL.CCPL4 4 +CCPL.CCPL3 3 +CCPL.CCPL2 2 +CCPL.CCPL1 1 +CCPL.CCPL0 0 +CCPH 0x00DF Compare timer 1 period register, high byte +CCPH.CCPH7 7 +CCPH.CCPH6 6 +CCPH.CCPH5 5 +CCPH.CCPH4 4 +CCPH.CCPH3 3 +CCPH.CCPH2 2 +CCPH.CCPH1 1 +CCPH.CCPH0 0 +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +CT1CON 0x00E1 Compare timer 1 control register +CT1CON.CTM 7 +CT1CON.ETRP 6 +CT1CON.STE1 5 +CT1CON.CT1RES 4 +CT1CON.CT1R 3 +CT1CON.CLK2 2 +CT1CON.CLK1 1 +CT1CON.CLK0 0 +COINI 0x00E2 Compare output initialization register +COINI.COUT3I 7 +COINI.COUTXI 6 +COINI.COUT2I 5 +COINI.CC2I 4 +COINI.COUT1I 3 +COINI.CC1I 2 +COINI.COUT0I 1 +COINI.CC0I 0 +CMSEL0 0x00E3 Capture/compare mode select register 0 +CMSEL0.CMSEL13 7 +CMSEL0.CMSEL12 6 +CMSEL0.CMSEL11 5 +CMSEL0.CMSEL10 4 +CMSEL0.CMSEL03 3 +CMSEL0.CMSEL02 2 +CMSEL0.CMSEL01 1 +CMSEL0.CMSEL00 0 +CMSEL1 0x00E4 Capture/compare mode select register 1 +CMSEL1.CMSEL23 3 +CMSEL1.CMSEL22 2 +CMSEL1.CMSEL21 1 +CMSEL1.CMSEL20 0 +CCIR 0x00E5 Capture/compare interrupt request flag reg. +CCIR.CT1FP 7 +CCIR.CT1FC 6 +CCIR.CC2F 5 +CCIR.CC2R 4 +CCIR.CC1F 3 +CCIR.CC1R 2 +CCIR.CC0F 1 +CCIR.CC0R 0 +CT1OFL 0x00E6 Compare timer 1 offset register, low byte +CT1OFL.CT1OFL7 7 +CT1OFL.CT1OFL6 6 +CT1OFL.CT1OFL5 5 +CT1OFL.CT1OFL4 4 +CT1OFL.CT1OFL3 3 +CT1OFL.CT1OFL2 2 +CT1OFL.CT1OFL1 1 +CT1OFL.CT1OFL0 0 +; alex - this was cause for error message "duplicate address 0xe6 at line 950" +;CT1OFH 0x00E6 Compare timer 1 offset register, high byte +;CT1OFH.CT1OFH7 7 +;CT1OFH.CT1OFH6 6 +;CT1OFH.CT1OFH5 5 +;CT1OFH.CT1OFH4 4 +;CT1OFH.CT1OFH3 3 +;CT1OFH.CT1OFH2 2 +;CT1OFH.CT1OFH1 1 +;CT1OFH.CT1OFH0 0 +RESERVED00E7 0x00E7 RESERVED +RESERVED00E8 0x00E8 RESERVED +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C505 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 +; C505C.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xF700 +area BSS RESERVED 0xF700:0xFF00 +area DATA XRAM 0xFF00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry CAN_SWI 0x004B CAN Controller / Software Interrupt +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry IRTC 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.P14 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +; P1ANA 0x0090 Port 1 Analog Input Selection Register +; P1ANA.EAN7 7 +; P1ANA.EAN6 6 +; P1ANA.EAN5 5 +; P1ANA.EAN4 4 +; P1ANA.EAN3 3 +; P1ANA.EAN2 2 +; P1ANA.EAN1 1 +; P1ANA.EAN0 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register (C505/C505C/C505A only) +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.CMOD 3 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.ECAN 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.SWI 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Reload Register Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Reload Register High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDAT 0x00D9 A/D Converter Data Reg. (C505 / C505C only) +ADDAT.ADDAT7 7 +ADDAT.ADDAT6 6 +ADDAT.ADDAT5 5 +ADDAT.ADDAT4 4 +ADDAT.ADDAT3 3 +ADDAT.ADDAT2 2 +ADDAT.ADDAT1 1 +ADDAT.ADDAT0 0 +ADST 0x00DA A/D Converter Start Reg. (C505 / C505C only) +RESERVED00DB 0x00DB RESERVED +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.RXDC 1 +P4.TXDC 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +VR2.VR27 7 +VR2.VR26 6 +VR2.VR25 5 +VR2.VR24 4 +VR2.VR23 3 +VR2.VR22 2 +VR2.VR21 1 +VR2.VR20 0 +RESERVED00FF 0x00FF RESERVED + + +.C505A +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 +; C505C.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xF700 +area BSS RESERVED 0xF700:0xFC00 +area DATA XRAM 0xFC00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry CAN_SWI 0x004B CAN Controller / Software Interrupt +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry IRTC 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.P14 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +; P1ANA 0x0090 Port 1 Analog Input Selection Register +; P1ANA.EAN7 7 +; P1ANA.EAN6 6 +; P1ANA.EAN5 5 +; P1ANA.EAN4 4 +; P1ANA.EAN3 3 +; P1ANA.EAN2 2 +; P1ANA.EAN1 1 +; P1ANA.EAN0 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register (C505/C505C/C505A only) +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.CMOD 3 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.ECAN 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.SWI 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Reload Register Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Reload Register High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter High Byte Data Register (C505A / C505CA only) +ADDATH.ADDATH7 7 +ADDATH.ADDATH6 6 +ADDATH.ADDATH5 5 +ADDATH.ADDATH4 4 +ADDATH.ADDATH3 3 +ADDATH.ADDATH2 2 +ADDATH.ADDATH1 1 +ADDATH.ADDATH0 0 +ADDATL 0x00DA A/D Converter Low Byte Data Register (C505A / C505CA only) +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +RESERVED00DB 0x00DB RESERVED +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.RXDC 1 +P4.TXDC 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +VR2.VR27 7 +VR2.VR26 6 +VR2.VR25 5 +VR2.VR24 4 +VR2.VR23 3 +VR2.VR22 2 +VR2.VR21 1 +VR2.VR20 0 +RESERVED00FF 0x00FF RESERVED + + +.C505C +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 +; C505C.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xF700 +area DATA CAN 0xF700:0xF800 +area BSS RESERVED 0xF800:0xFF00 +area DATA XRAM 0xFF00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry CAN_SWI 0x004B CAN Controller / Software Interrupt +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry IRTC 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.P14 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +; P1ANA 0x0090 Port 1 Analog Input Selection Register +; P1ANA.EAN7 7 +; P1ANA.EAN6 6 +; P1ANA.EAN5 5 +; P1ANA.EAN4 4 +; P1ANA.EAN3 3 +; P1ANA.EAN2 2 +; P1ANA.EAN1 1 +; P1ANA.EAN0 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register (C505/C505C/C505A only) +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.CMOD 3 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.ECAN 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.SWI 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Reload Register Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Reload Register High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDAT 0x00D9 A/D Converter Data Reg. (C505 / C505C only) +ADDAT.ADDAT7 7 +ADDAT.ADDAT6 6 +ADDAT.ADDAT5 5 +ADDAT.ADDAT4 4 +ADDAT.ADDAT3 3 +ADDAT.ADDAT2 2 +ADDAT.ADDAT1 1 +ADDAT.ADDAT0 0 +ADST 0x00DA A/D Converter Start Reg. (C505 / C505C only) +RESERVED00DB 0x00DB RESERVED +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.RXDC 1 +P4.TXDC 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +VR2.VR27 7 +VR2.VR26 6 +VR2.VR25 5 +VR2.VR24 4 +VR2.VR23 3 +VR2.VR22 2 +VR2.VR21 1 +VR2.VR20 0 +RESERVED00FF 0x00FF RESERVED +; -------------------------------------- CAN -------------------------------- +CR 0xF700 Control Register +CR.TEST 7 +CR.CCE 6 +CR.EIE 3 +CR.SIE 2 +CR.IE 1 +CR.INIT 0 +SR 0xF701 Status Register +SR.BOFF 7 +SR.EWRN 6 +SR.RXOK 4 +SR.TXOK 3 +SR.LEC2 2 +SR.LEC1 1 +SR.LEC0 0 +IR 0xF702 Interrupt Register +IR.INTID7 7 +IR.INTID6 6 +IR.INTID5 5 +IR.INTID4 4 +IR.INTID3 3 +IR.INTID2 2 +IR.INTID1 1 +IR.INTID0 0 +RESERVEDF703 0xF703 RESERVED +BTR0 0xF704 Bit Timing Register Low +BTR0.SJW7 7 +BTR0.SJW6 6 +BTR0.BRP5 5 +BTR0.BRP4 4 +BTR0.BRP3 3 +BTR0.BRP2 2 +BTR0.BRP1 1 +BTR0.BRP0 0 +BTR1 0xF705 Bit Timing Register High +BTR1.TSEG26 6 +BTR1.TSEG25 5 +BTR1.TSEG24 4 +BTR1.TSEG13 3 +BTR1.TSEG12 2 +BTR1.TSEG11 1 +BTR1.TSEG10 0 +GMS0 0xF706 Global Mask Short Register Low +GMS0.ID28 7 +GMS0.ID27 6 +GMS0.ID26 5 +GMS0.ID25 4 +GMS0.ID24 3 +GMS0.ID23 2 +GMS0.ID22 1 +GMS0.ID21 0 +GMS1 0xF707 Global Mask Short Register High +GMS1.ID20 7 +GMS1.ID19 6 +GMS1.ID18 5 +UGML0 0xF708 Upper Global Mask Long Register Low +UGML0.ID28 7 +UGML0.ID27 6 +UGML0.ID26 5 +UGML0.ID25 4 +UGML0.ID24 3 +UGML0.ID23 2 +UGML0.ID22 1 +UGML0.ID21 0 +UGML1 0xF709 Upper Global Mask Long Register High +UGML1.ID20 7 +UGML1.ID19 6 +UGML1.ID18 5 +UGML1.ID17 4 +UGML1.ID16 3 +UGML1.ID15 2 +UGML1.ID14 1 +UGML1.ID13 0 +LGML0 0xF70A Lower Global Mask Long Register Low +LGML0.ID12 7 +LGML0.ID11 6 +LGML0.ID10 5 +LGML0.ID9 4 +LGML0.ID8 3 +LGML0.ID7 2 +LGML0.ID6 1 +LGML0.ID5 0 +LGML1 0xF70B Lower Global Mask Long Register High +LGML1.ID4 7 +LGML1.ID3 6 +LGML1.ID2 5 +LGML1.ID1 4 +LGML1.ID0 3 +UMLM0 0xF70C Upper Mask of Last Message Register Low +UMLM0.ID28 7 +UMLM0.ID27 6 +UMLM0.ID26 5 +UMLM0.ID25 4 +UMLM0.ID24 3 +UMLM0.ID23 2 +UMLM0.ID22 1 +UMLM0.ID21 0 +UMLM1 0xF70D Upper Mask of Last Message Register High +UMLM1.ID20 7 +UMLM1.ID19 6 +UMLM1.ID18 5 +UMLM1.ID17 4 +UMLM1.ID16 3 +UMLM1.ID15 2 +UMLM1.ID14 1 +UMLM1.ID13 0 +LMLM0 0xF70E Lower Mask of Last Message Register Low +LMLM0.ID12 7 +LMLM0.ID11 6 +LMLM0.ID10 5 +LMLM0.ID9 4 +LMLM0.ID8 3 +LMLM0.ID7 2 +LMLM0.ID6 1 +LMLM0.ID5 0 +LMLM1 0xF70F Lower Mask of Last Message Register High +LMLM1.ID4 7 +LMLM1.ID3 6 +LMLM1.ID2 5 +LMLM1.ID1 4 +LMLM1.ID0 3 +; -------------------------------------- CAN_1 -------------------------------- +MCR0_1 0xF710 Message Control Register Low +MCR0_1.MSGVAL1 7 +MCR0_1.MSGVAL0 6 +MCR0_1.TXIE1 5 +MCR0_1.TXIE0 4 +MCR0_1.RXIE1 3 +MCR0_1.RXIE0 2 +MCR0_1.INTPND1 1 +MCR0_1.INTPND0 0 +MCR1_1 0xF711 Message Control Register High +MCR1_1.RMTPND1 7 +MCR1_1.RMTPND0 6 +MCR1_1.TXRQ1 5 +MCR1_1.TXRQ0 4 +MCR1_1.MSGLSTCPUUPD1 3 +MCR1_1.MSGLSTCPUUPD0 2 +MCR1_1.NEWDAT1 1 +MCR1_1.NEWDAT0 0 +UAR0_1 0xF712 Upper Arbitration Register Low +UAR0_1.ID28 7 +UAR0_1.ID27 6 +UAR0_1.ID26 5 +UAR0_1.ID25 4 +UAR0_1.ID24 3 +UAR0_1.ID23 2 +UAR0_1.ID22 1 +UAR0_1.ID21 0 +UAR1_1 0xF713 Upper Arbitration Register High +UAR1_1.ID20 7 +UAR1_1.ID19 6 +UAR1_1.ID18 5 +UAR1_1.ID17 4 +UAR1_1.ID16 3 +UAR1_1.ID15 2 +UAR1_1.ID14 1 +UAR1_1.ID13 0 +LAR0_1 0xF714 Lower Arbitration Register Low +LAR0_1.ID12 7 +LAR0_1.ID11 6 +LAR0_1.ID10 5 +LAR0_1.ID9 4 +LAR0_1.ID8 3 +LAR0_1.ID7 2 +LAR0_1.ID6 1 +LAR0_1.ID5 0 +LAR1_1 0xF715 Lower Arbitration Register High +LAR1_1.ID4 7 +LAR1_1.ID3 6 +LAR1_1.ID2 5 +LAR1_1.ID1 4 +LAR1_1.ID0 3 +MCFG_1 0xF716 Message Configuration Register +MCFG_1.DLC7 7 +MCFG_1.DLC6 6 +MCFG_1.DLC5 5 +MCFG_1.DLC4 4 +MCFG_1.DIR 3 +MCFG_1.XTD 2 +DB0_1 0xF717 Message Data Byte 0 +DB0_1.DB07 7 +DB0_1.DB06 6 +DB0_1.DB05 5 +DB0_1.DB04 4 +DB0_1.DB03 3 +DB0_1.DB02 2 +DB0_1.DB01 1 +DB0_1.DB00 0 +DB1_1 0xF718 Message Data Byte 1 +DB1_1.DB17 7 +DB1_1.DB16 6 +DB1_1.DB15 5 +DB1_1.DB14 4 +DB1_1.DB13 3 +DB1_1.DB12 2 +DB1_1.DB11 1 +DB1_1.DB10 0 +DB2_1 0xF719 Message Data Byte 2 +DB2_1.DB27 7 +DB2_1.DB26 6 +DB2_1.DB25 5 +DB2_1.DB24 4 +DB2_1.DB23 3 +DB2_1.DB22 2 +DB2_1.DB21 1 +DB2_1.DB20 0 +DB3_1 0xF71A Message Data Byte 3 +DB3_1.DB37 7 +DB3_1.DB36 6 +DB3_1.DB35 5 +DB3_1.DB34 4 +DB3_1.DB33 3 +DB3_1.DB32 2 +DB3_1.DB31 1 +DB3_1.DB30 0 +DB4_1 0xF71B Message Data Byte 4 +DB4_1.DB47 7 +DB4_1.DB46 6 +DB4_1.DB45 5 +DB4_1.DB44 4 +DB4_1.DB43 3 +DB4_1.DB42 2 +DB4_1.DB41 1 +DB4_1.DB40 0 +DB5_1 0xF71C Message Data Byte 5 +DB5_1.DB57 7 +DB5_1.DB56 6 +DB5_1.DB55 5 +DB5_1.DB54 4 +DB5_1.DB53 3 +DB5_1.DB52 2 +DB5_1.DB51 1 +DB5_1.DB50 0 +DB6_1 0xF71D Message Data Byte 6 +DB6_1.DB67 7 +DB6_1.DB66 6 +DB6_1.DB65 5 +DB6_1.DB64 4 +DB6_1.DB63 3 +DB6_1.DB62 2 +DB6_1.DB61 1 +DB6_1.DB60 0 +DB7_1 0xF71E Message Data Byte 7 +DB7_1.DB77 7 +DB7_1.DB76 6 +DB7_1.DB75 5 +DB7_1.DB74 4 +DB7_1.DB73 3 +DB7_1.DB72 2 +DB7_1.DB71 1 +DB7_1.DB70 0 +RESERVEDF71F 0xF71F RESERVED +; -------------------------------------- CAN_2 -------------------------------- +MCR0_2 0xF720 Message Control Register Low +MCR0_2.MSGVAL1 7 +MCR0_2.MSGVAL0 6 +MCR0_2.TXIE1 5 +MCR0_2.TXIE0 4 +MCR0_2.RXIE1 3 +MCR0_2.RXIE0 2 +MCR0_2.INTPND1 1 +MCR0_2.INTPND0 0 +MCR1_2 0xF721 Message Control Register High +MCR1_2.RMTPND1 7 +MCR1_2.RMTPND0 6 +MCR1_2.TXRQ1 5 +MCR1_2.TXRQ0 4 +MCR1_2.MSGLSTCPUUPD1 3 +MCR1_2.MSGLSTCPUUPD0 2 +MCR1_2.NEWDAT1 1 +MCR1_2.NEWDAT0 0 +UAR0_2 0xF722 Upper Arbitration Register Low +UAR0_2.ID28 7 +UAR0_2.ID27 6 +UAR0_2.ID26 5 +UAR0_2.ID25 4 +UAR0_2.ID24 3 +UAR0_2.ID23 2 +UAR0_2.ID22 1 +UAR0_2.ID21 0 +UAR1_2 0xF723 Upper Arbitration Register High +UAR1_2.ID20 7 +UAR1_2.ID19 6 +UAR1_2.ID18 5 +UAR1_2.ID17 4 +UAR1_2.ID16 3 +UAR1_2.ID15 2 +UAR1_2.ID14 1 +UAR1_2.ID13 0 +LAR0_2 0xF724 Lower Arbitration Register Low +LAR0_2.ID12 7 +LAR0_2.ID11 6 +LAR0_2.ID10 5 +LAR0_2.ID9 4 +LAR0_2.ID8 3 +LAR0_2.ID7 2 +LAR0_2.ID6 1 +LAR0_2.ID5 0 +LAR1_2 0xF725 Lower Arbitration Register High +LAR1_2.ID4 7 +LAR1_2.ID3 6 +LAR1_2.ID2 5 +LAR1_2.ID1 4 +LAR1_2.ID0 3 +MCFG_2 0xF726 Message Configuration Register +MCFG_2.DLC7 7 +MCFG_2.DLC6 6 +MCFG_2.DLC5 5 +MCFG_2.DLC4 4 +MCFG_2.DIR 3 +MCFG_2.XTD 2 +DB0_2 0xF727 Message Data Byte 0 +DB0_2.DB07 7 +DB0_2.DB06 6 +DB0_2.DB05 5 +DB0_2.DB04 4 +DB0_2.DB03 3 +DB0_2.DB02 2 +DB0_2.DB01 1 +DB0_2.DB00 0 +DB1_2 0xF728 Message Data Byte 1 +DB1_2.DB17 7 +DB1_2.DB16 6 +DB1_2.DB15 5 +DB1_2.DB14 4 +DB1_2.DB13 3 +DB1_2.DB12 2 +DB1_2.DB11 1 +DB1_2.DB10 0 +DB2_2 0xF729 Message Data Byte 2 +DB2_2.DB27 7 +DB2_2.DB26 6 +DB2_2.DB25 5 +DB2_2.DB24 4 +DB2_2.DB23 3 +DB2_2.DB22 2 +DB2_2.DB21 1 +DB2_2.DB20 0 +DB3_2 0xF72A Message Data Byte 3 +DB3_2.DB37 7 +DB3_2.DB36 6 +DB3_2.DB35 5 +DB3_2.DB34 4 +DB3_2.DB33 3 +DB3_2.DB32 2 +DB3_2.DB31 1 +DB3_2.DB30 0 +DB4_2 0xF72B Message Data Byte 4 +DB4_2.DB47 7 +DB4_2.DB46 6 +DB4_2.DB45 5 +DB4_2.DB44 4 +DB4_2.DB43 3 +DB4_2.DB42 2 +DB4_2.DB41 1 +DB4_2.DB40 0 +DB5_2 0xF72C Message Data Byte 5 +DB5_2.DB57 7 +DB5_2.DB56 6 +DB5_2.DB55 5 +DB5_2.DB54 4 +DB5_2.DB53 3 +DB5_2.DB52 2 +DB5_2.DB51 1 +DB5_2.DB50 0 +DB6_2 0xF72D Message Data Byte 6 +DB6_2.DB67 7 +DB6_2.DB66 6 +DB6_2.DB65 5 +DB6_2.DB64 4 +DB6_2.DB63 3 +DB6_2.DB62 2 +DB6_2.DB61 1 +DB6_2.DB60 0 +DB7_2 0xF72E Message Data Byte 7 +DB7_2.DB77 7 +DB7_2.DB76 6 +DB7_2.DB75 5 +DB7_2.DB74 4 +DB7_2.DB73 3 +DB7_2.DB72 2 +DB7_2.DB71 1 +DB7_2.DB70 0 +RESERVEDF72F 0xF72F RESERVED +; -------------------------------------- CAN_3 -------------------------------- +MCR0_3 0xF730 Message Control Register Low +MCR0_3.MSGVAL1 7 +MCR0_3.MSGVAL0 6 +MCR0_3.TXIE1 5 +MCR0_3.TXIE0 4 +MCR0_3.RXIE1 3 +MCR0_3.RXIE0 2 +MCR0_3.INTPND1 1 +MCR0_3.INTPND0 0 +MCR1_3 0xF731 Message Control Register High +MCR1_3.RMTPND1 7 +MCR1_3.RMTPND0 6 +MCR1_3.TXRQ1 5 +MCR1_3.TXRQ0 4 +MCR1_3.MSGLSTCPUUPD1 3 +MCR1_3.MSGLSTCPUUPD0 2 +MCR1_3.NEWDAT1 1 +MCR1_3.NEWDAT0 0 +UAR0_3 0xF732 Upper Arbitration Register Low +UAR0_3.ID28 7 +UAR0_3.ID27 6 +UAR0_3.ID26 5 +UAR0_3.ID25 4 +UAR0_3.ID24 3 +UAR0_3.ID23 2 +UAR0_3.ID22 1 +UAR0_3.ID21 0 +UAR1_3 0xF733 Upper Arbitration Register High +UAR1_3.ID20 7 +UAR1_3.ID19 6 +UAR1_3.ID18 5 +UAR1_3.ID17 4 +UAR1_3.ID16 3 +UAR1_3.ID15 2 +UAR1_3.ID14 1 +UAR1_3.ID13 0 +LAR0_3 0xF734 Lower Arbitration Register Low +LAR0_3.ID12 7 +LAR0_3.ID11 6 +LAR0_3.ID10 5 +LAR0_3.ID9 4 +LAR0_3.ID8 3 +LAR0_3.ID7 2 +LAR0_3.ID6 1 +LAR0_3.ID5 0 +LAR1_3 0xF735 Lower Arbitration Register High +LAR1_3.ID4 7 +LAR1_3.ID3 6 +LAR1_3.ID2 5 +LAR1_3.ID1 4 +LAR1_3.ID0 3 +MCFG_3 0xF736 Message Configuration Register +MCFG_3.DLC7 7 +MCFG_3.DLC6 6 +MCFG_3.DLC5 5 +MCFG_3.DLC4 4 +MCFG_3.DIR 3 +MCFG_3.XTD 2 +DB0_3 0xF737 Message Data Byte 0 +DB0_3.DB07 7 +DB0_3.DB06 6 +DB0_3.DB05 5 +DB0_3.DB04 4 +DB0_3.DB03 3 +DB0_3.DB02 2 +DB0_3.DB01 1 +DB0_3.DB00 0 +DB1_3 0xF738 Message Data Byte 1 +DB1_3.DB17 7 +DB1_3.DB16 6 +DB1_3.DB15 5 +DB1_3.DB14 4 +DB1_3.DB13 3 +DB1_3.DB12 2 +DB1_3.DB11 1 +DB1_3.DB10 0 +DB2_3 0xF739 Message Data Byte 2 +DB2_3.DB27 7 +DB2_3.DB26 6 +DB2_3.DB25 5 +DB2_3.DB24 4 +DB2_3.DB23 3 +DB2_3.DB22 2 +DB2_3.DB21 1 +DB2_3.DB20 0 +DB3_3 0xF73A Message Data Byte 3 +DB3_3.DB37 7 +DB3_3.DB36 6 +DB3_3.DB35 5 +DB3_3.DB34 4 +DB3_3.DB33 3 +DB3_3.DB32 2 +DB3_3.DB31 1 +DB3_3.DB30 0 +DB4_3 0xF73B Message Data Byte 4 +DB4_3.DB47 7 +DB4_3.DB46 6 +DB4_3.DB45 5 +DB4_3.DB44 4 +DB4_3.DB43 3 +DB4_3.DB42 2 +DB4_3.DB41 1 +DB4_3.DB40 0 +DB5_3 0xF73C Message Data Byte 5 +DB5_3.DB57 7 +DB5_3.DB56 6 +DB5_3.DB55 5 +DB5_3.DB54 4 +DB5_3.DB53 3 +DB5_3.DB52 2 +DB5_3.DB51 1 +DB5_3.DB50 0 +DB6_3 0xF73D Message Data Byte 6 +DB6_3.DB67 7 +DB6_3.DB66 6 +DB6_3.DB65 5 +DB6_3.DB64 4 +DB6_3.DB63 3 +DB6_3.DB62 2 +DB6_3.DB61 1 +DB6_3.DB60 0 +DB7_3 0xF73E Message Data Byte 7 +DB7_3.DB77 7 +DB7_3.DB76 6 +DB7_3.DB75 5 +DB7_3.DB74 4 +DB7_3.DB73 3 +DB7_3.DB72 2 +DB7_3.DB71 1 +DB7_3.DB70 0 +RESERVEDF73F 0xF73F RESERVED +; -------------------------------------- CAN_4 -------------------------------- +MCR0_4 0xF740 Message Control Register Low +MCR0_4.MSGVAL1 7 +MCR0_4.MSGVAL0 6 +MCR0_4.TXIE1 5 +MCR0_4.TXIE0 4 +MCR0_4.RXIE1 3 +MCR0_4.RXIE0 2 +MCR0_4.INTPND1 1 +MCR0_4.INTPND0 0 +MCR1_4 0xF741 Message Control Register High +MCR1_4.RMTPND1 7 +MCR1_4.RMTPND0 6 +MCR1_4.TXRQ1 5 +MCR1_4.TXRQ0 4 +MCR1_4.MSGLSTCPUUPD1 3 +MCR1_4.MSGLSTCPUUPD0 2 +MCR1_4.NEWDAT1 1 +MCR1_4.NEWDAT0 0 +UAR0_4 0xF742 Upper Arbitration Register Low +UAR0_4.ID28 7 +UAR0_4.ID27 6 +UAR0_4.ID26 5 +UAR0_4.ID25 4 +UAR0_4.ID24 3 +UAR0_4.ID23 2 +UAR0_4.ID22 1 +UAR0_4.ID21 0 +UAR1_4 0xF743 Upper Arbitration Register High +UAR1_4.ID20 7 +UAR1_4.ID19 6 +UAR1_4.ID18 5 +UAR1_4.ID17 4 +UAR1_4.ID16 3 +UAR1_4.ID15 2 +UAR1_4.ID14 1 +UAR1_4.ID13 0 +LAR0_4 0xF744 Lower Arbitration Register Low +LAR0_4.ID12 7 +LAR0_4.ID11 6 +LAR0_4.ID10 5 +LAR0_4.ID9 4 +LAR0_4.ID8 3 +LAR0_4.ID7 2 +LAR0_4.ID6 1 +LAR0_4.ID5 0 +LAR1_4 0xF745 Lower Arbitration Register High +LAR1_4.ID4 7 +LAR1_4.ID3 6 +LAR1_4.ID2 5 +LAR1_4.ID1 4 +LAR1_4.ID0 3 +MCFG_4 0xF746 Message Configuration Register +MCFG_4.DLC7 7 +MCFG_4.DLC6 6 +MCFG_4.DLC5 5 +MCFG_4.DLC4 4 +MCFG_4.DIR 3 +MCFG_4.XTD 2 +DB0_4 0xF747 Message Data Byte 0 +DB0_4.DB07 7 +DB0_4.DB06 6 +DB0_4.DB05 5 +DB0_4.DB04 4 +DB0_4.DB03 3 +DB0_4.DB02 2 +DB0_4.DB01 1 +DB0_4.DB00 0 +DB1_4 0xF748 Message Data Byte 1 +DB1_4.DB17 7 +DB1_4.DB16 6 +DB1_4.DB15 5 +DB1_4.DB14 4 +DB1_4.DB13 3 +DB1_4.DB12 2 +DB1_4.DB11 1 +DB1_4.DB10 0 +DB2_4 0xF749 Message Data Byte 2 +DB2_4.DB27 7 +DB2_4.DB26 6 +DB2_4.DB25 5 +DB2_4.DB24 4 +DB2_4.DB23 3 +DB2_4.DB22 2 +DB2_4.DB21 1 +DB2_4.DB20 0 +DB3_4 0xF74A Message Data Byte 3 +DB3_4.DB37 7 +DB3_4.DB36 6 +DB3_4.DB35 5 +DB3_4.DB34 4 +DB3_4.DB33 3 +DB3_4.DB32 2 +DB3_4.DB31 1 +DB3_4.DB30 0 +DB4_4 0xF74B Message Data Byte 4 +DB4_4.DB47 7 +DB4_4.DB46 6 +DB4_4.DB45 5 +DB4_4.DB44 4 +DB4_4.DB43 3 +DB4_4.DB42 2 +DB4_4.DB41 1 +DB4_4.DB40 0 +DB5_4 0xF74C Message Data Byte 5 +DB5_4.DB57 7 +DB5_4.DB56 6 +DB5_4.DB55 5 +DB5_4.DB54 4 +DB5_4.DB53 3 +DB5_4.DB52 2 +DB5_4.DB51 1 +DB5_4.DB50 0 +DB6_4 0xF74D Message Data Byte 6 +DB6_4.DB67 7 +DB6_4.DB66 6 +DB6_4.DB65 5 +DB6_4.DB64 4 +DB6_4.DB63 3 +DB6_4.DB62 2 +DB6_4.DB61 1 +DB6_4.DB60 0 +DB7_4 0xF74E Message Data Byte 7 +DB7_4.DB77 7 +DB7_4.DB76 6 +DB7_4.DB75 5 +DB7_4.DB74 4 +DB7_4.DB73 3 +DB7_4.DB72 2 +DB7_4.DB71 1 +DB7_4.DB70 0 +RESERVEDF74F 0xF74F RESERVED +; -------------------------------------- CAN_5 -------------------------------- +MCR0_5 0xF750 Message Control Register Low +MCR0_5.MSGVAL1 7 +MCR0_5.MSGVAL0 6 +MCR0_5.TXIE1 5 +MCR0_5.TXIE0 4 +MCR0_5.RXIE1 3 +MCR0_5.RXIE0 2 +MCR0_5.INTPND1 1 +MCR0_5.INTPND0 0 +MCR1_5 0xF751 Message Control Register High +MCR1_5.RMTPND1 7 +MCR1_5.RMTPND0 6 +MCR1_5.TXRQ1 5 +MCR1_5.TXRQ0 4 +MCR1_5.MSGLSTCPUUPD1 3 +MCR1_5.MSGLSTCPUUPD0 2 +MCR1_5.NEWDAT1 1 +MCR1_5.NEWDAT0 0 +UAR0_5 0xF752 Upper Arbitration Register Low +UAR0_5.ID28 7 +UAR0_5.ID27 6 +UAR0_5.ID26 5 +UAR0_5.ID25 4 +UAR0_5.ID24 3 +UAR0_5.ID23 2 +UAR0_5.ID22 1 +UAR0_5.ID21 0 +UAR1_5 0xF753 Upper Arbitration Register High +UAR1_5.ID20 7 +UAR1_5.ID19 6 +UAR1_5.ID18 5 +UAR1_5.ID17 4 +UAR1_5.ID16 3 +UAR1_5.ID15 2 +UAR1_5.ID14 1 +UAR1_5.ID13 0 +LAR0_5 0xF754 Lower Arbitration Register Low +LAR0_5.ID12 7 +LAR0_5.ID11 6 +LAR0_5.ID10 5 +LAR0_5.ID9 4 +LAR0_5.ID8 3 +LAR0_5.ID7 2 +LAR0_5.ID6 1 +LAR0_5.ID5 0 +LAR1_5 0xF755 Lower Arbitration Register High +LAR1_5.ID4 7 +LAR1_5.ID3 6 +LAR1_5.ID2 5 +LAR1_5.ID1 4 +LAR1_5.ID0 3 +MCFG_5 0xF756 Message Configuration Register +MCFG_5.DLC7 7 +MCFG_5.DLC6 6 +MCFG_5.DLC5 5 +MCFG_5.DLC4 4 +MCFG_5.DIR 3 +MCFG_5.XTD 2 +DB0_5 0xF757 Message Data Byte 0 +DB0_5.DB07 7 +DB0_5.DB06 6 +DB0_5.DB05 5 +DB0_5.DB04 4 +DB0_5.DB03 3 +DB0_5.DB02 2 +DB0_5.DB01 1 +DB0_5.DB00 0 +DB1_5 0xF758 Message Data Byte 1 +DB1_5.DB17 7 +DB1_5.DB16 6 +DB1_5.DB15 5 +DB1_5.DB14 4 +DB1_5.DB13 3 +DB1_5.DB12 2 +DB1_5.DB11 1 +DB1_5.DB10 0 +DB2_5 0xF759 Message Data Byte 2 +DB2_5.DB27 7 +DB2_5.DB26 6 +DB2_5.DB25 5 +DB2_5.DB24 4 +DB2_5.DB23 3 +DB2_5.DB22 2 +DB2_5.DB21 1 +DB2_5.DB20 0 +DB3_5 0xF75A Message Data Byte 3 +DB3_5.DB37 7 +DB3_5.DB36 6 +DB3_5.DB35 5 +DB3_5.DB34 4 +DB3_5.DB33 3 +DB3_5.DB32 2 +DB3_5.DB31 1 +DB3_5.DB30 0 +DB4_5 0xF75B Message Data Byte 4 +DB4_5.DB47 7 +DB4_5.DB46 6 +DB4_5.DB45 5 +DB4_5.DB44 4 +DB4_5.DB43 3 +DB4_5.DB42 2 +DB4_5.DB41 1 +DB4_5.DB40 0 +DB5_5 0xF75C Message Data Byte 5 +DB5_5.DB57 7 +DB5_5.DB56 6 +DB5_5.DB55 5 +DB5_5.DB54 4 +DB5_5.DB53 3 +DB5_5.DB52 2 +DB5_5.DB51 1 +DB5_5.DB50 0 +DB6_5 0xF75D Message Data Byte 6 +DB6_5.DB67 7 +DB6_5.DB66 6 +DB6_5.DB65 5 +DB6_5.DB64 4 +DB6_5.DB63 3 +DB6_5.DB62 2 +DB6_5.DB61 1 +DB6_5.DB60 0 +DB7_5 0xF75E Message Data Byte 7 +DB7_5.DB77 7 +DB7_5.DB76 6 +DB7_5.DB75 5 +DB7_5.DB74 4 +DB7_5.DB73 3 +DB7_5.DB72 2 +DB7_5.DB71 1 +DB7_5.DB70 0 +RESERVEDF75F 0xF75F RESERVED +; -------------------------------------- CAN_6 -------------------------------- +MCR0_6 0xF760 Message Control Register Low +MCR0_6.MSGVAL1 7 +MCR0_6.MSGVAL0 6 +MCR0_6.TXIE1 5 +MCR0_6.TXIE0 4 +MCR0_6.RXIE1 3 +MCR0_6.RXIE0 2 +MCR0_6.INTPND1 1 +MCR0_6.INTPND0 0 +MCR1_6 0xF761 Message Control Register High +MCR1_6.RMTPND1 7 +MCR1_6.RMTPND0 6 +MCR1_6.TXRQ1 5 +MCR1_6.TXRQ0 4 +MCR1_6.MSGLSTCPUUPD1 3 +MCR1_6.MSGLSTCPUUPD0 2 +MCR1_6.NEWDAT1 1 +MCR1_6.NEWDAT0 0 +UAR0_6 0xF762 Upper Arbitration Register Low +UAR0_6.ID28 7 +UAR0_6.ID27 6 +UAR0_6.ID26 5 +UAR0_6.ID25 4 +UAR0_6.ID24 3 +UAR0_6.ID23 2 +UAR0_6.ID22 1 +UAR0_6.ID21 0 +UAR1_6 0xF763 Upper Arbitration Register High +UAR1_6.ID20 7 +UAR1_6.ID19 6 +UAR1_6.ID18 5 +UAR1_6.ID17 4 +UAR1_6.ID16 3 +UAR1_6.ID15 2 +UAR1_6.ID14 1 +UAR1_6.ID13 0 +LAR0_6 0xF764 Lower Arbitration Register Low +LAR0_6.ID12 7 +LAR0_6.ID11 6 +LAR0_6.ID10 5 +LAR0_6.ID9 4 +LAR0_6.ID8 3 +LAR0_6.ID7 2 +LAR0_6.ID6 1 +LAR0_6.ID5 0 +LAR1_6 0xF765 Lower Arbitration Register High +LAR1_6.ID4 7 +LAR1_6.ID3 6 +LAR1_6.ID2 5 +LAR1_6.ID1 4 +LAR1_6.ID0 3 +MCFG_6 0xF766 Message Configuration Register +MCFG_6.DLC7 7 +MCFG_6.DLC6 6 +MCFG_6.DLC5 5 +MCFG_6.DLC4 4 +MCFG_6.DIR 3 +MCFG_6.XTD 2 +DB0_6 0xF767 Message Data Byte 0 +DB0_6.DB07 7 +DB0_6.DB06 6 +DB0_6.DB05 5 +DB0_6.DB04 4 +DB0_6.DB03 3 +DB0_6.DB02 2 +DB0_6.DB01 1 +DB0_6.DB00 0 +DB1_6 0xF768 Message Data Byte 1 +DB1_6.DB17 7 +DB1_6.DB16 6 +DB1_6.DB15 5 +DB1_6.DB14 4 +DB1_6.DB13 3 +DB1_6.DB12 2 +DB1_6.DB11 1 +DB1_6.DB10 0 +DB2_6 0xF769 Message Data Byte 2 +DB2_6.DB27 7 +DB2_6.DB26 6 +DB2_6.DB25 5 +DB2_6.DB24 4 +DB2_6.DB23 3 +DB2_6.DB22 2 +DB2_6.DB21 1 +DB2_6.DB20 0 +DB3_6 0xF76A Message Data Byte 3 +DB3_6.DB37 7 +DB3_6.DB36 6 +DB3_6.DB35 5 +DB3_6.DB34 4 +DB3_6.DB33 3 +DB3_6.DB32 2 +DB3_6.DB31 1 +DB3_6.DB30 0 +DB4_6 0xF76B Message Data Byte 4 +DB4_6.DB47 7 +DB4_6.DB46 6 +DB4_6.DB45 5 +DB4_6.DB44 4 +DB4_6.DB43 3 +DB4_6.DB42 2 +DB4_6.DB41 1 +DB4_6.DB40 0 +DB5_6 0xF76C Message Data Byte 5 +DB5_6.DB57 7 +DB5_6.DB56 6 +DB5_6.DB55 5 +DB5_6.DB54 4 +DB5_6.DB53 3 +DB5_6.DB52 2 +DB5_6.DB51 1 +DB5_6.DB50 0 +DB6_6 0xF76D Message Data Byte 6 +DB6_6.DB67 7 +DB6_6.DB66 6 +DB6_6.DB65 5 +DB6_6.DB64 4 +DB6_6.DB63 3 +DB6_6.DB62 2 +DB6_6.DB61 1 +DB6_6.DB60 0 +DB7_6 0xF76E Message Data Byte 7 +DB7_6.DB77 7 +DB7_6.DB76 6 +DB7_6.DB75 5 +DB7_6.DB74 4 +DB7_6.DB73 3 +DB7_6.DB72 2 +DB7_6.DB71 1 +DB7_6.DB70 0 +RESERVEDF76F 0xF76F RESERVED +; -------------------------------------- CAN_7 -------------------------------- +MCR0_7 0xF770 Message Control Register Low +MCR0_7.MSGVAL1 7 +MCR0_7.MSGVAL0 6 +MCR0_7.TXIE1 5 +MCR0_7.TXIE0 4 +MCR0_7.RXIE1 3 +MCR0_7.RXIE0 2 +MCR0_7.INTPND1 1 +MCR0_7.INTPND0 0 +MCR1_7 0xF771 Message Control Register High +MCR1_7.RMTPND1 7 +MCR1_7.RMTPND0 6 +MCR1_7.TXRQ1 5 +MCR1_7.TXRQ0 4 +MCR1_7.MSGLSTCPUUPD1 3 +MCR1_7.MSGLSTCPUUPD0 2 +MCR1_7.NEWDAT1 1 +MCR1_7.NEWDAT0 0 +UAR0_7 0xF772 Upper Arbitration Register Low +UAR0_7.ID28 7 +UAR0_7.ID27 6 +UAR0_7.ID26 5 +UAR0_7.ID25 4 +UAR0_7.ID24 3 +UAR0_7.ID23 2 +UAR0_7.ID22 1 +UAR0_7.ID21 0 +UAR1_7 0xF773 Upper Arbitration Register High +UAR1_7.ID20 7 +UAR1_7.ID19 6 +UAR1_7.ID18 5 +UAR1_7.ID17 4 +UAR1_7.ID16 3 +UAR1_7.ID15 2 +UAR1_7.ID14 1 +UAR1_7.ID13 0 +LAR0_7 0xF774 Lower Arbitration Register Low +LAR0_7.ID12 7 +LAR0_7.ID11 6 +LAR0_7.ID10 5 +LAR0_7.ID9 4 +LAR0_7.ID8 3 +LAR0_7.ID7 2 +LAR0_7.ID6 1 +LAR0_7.ID5 0 +LAR1_7 0xF775 Lower Arbitration Register High +LAR1_7.ID4 7 +LAR1_7.ID3 6 +LAR1_7.ID2 5 +LAR1_7.ID1 4 +LAR1_7.ID0 3 +MCFG_7 0xF776 Message Configuration Register +MCFG_7.DLC7 7 +MCFG_7.DLC6 6 +MCFG_7.DLC5 5 +MCFG_7.DLC4 4 +MCFG_7.DIR 3 +MCFG_7.XTD 2 +DB0_7 0xF777 Message Data Byte 0 +DB0_7.DB07 7 +DB0_7.DB06 6 +DB0_7.DB05 5 +DB0_7.DB04 4 +DB0_7.DB03 3 +DB0_7.DB02 2 +DB0_7.DB01 1 +DB0_7.DB00 0 +DB1_7 0xF778 Message Data Byte 1 +DB1_7.DB17 7 +DB1_7.DB16 6 +DB1_7.DB15 5 +DB1_7.DB14 4 +DB1_7.DB13 3 +DB1_7.DB12 2 +DB1_7.DB11 1 +DB1_7.DB10 0 +DB2_7 0xF779 Message Data Byte 2 +DB2_7.DB27 7 +DB2_7.DB26 6 +DB2_7.DB25 5 +DB2_7.DB24 4 +DB2_7.DB23 3 +DB2_7.DB22 2 +DB2_7.DB21 1 +DB2_7.DB20 0 +DB3_7 0xF77A Message Data Byte 3 +DB3_7.DB37 7 +DB3_7.DB36 6 +DB3_7.DB35 5 +DB3_7.DB34 4 +DB3_7.DB33 3 +DB3_7.DB32 2 +DB3_7.DB31 1 +DB3_7.DB30 0 +DB4_7 0xF77B Message Data Byte 4 +DB4_7.DB47 7 +DB4_7.DB46 6 +DB4_7.DB45 5 +DB4_7.DB44 4 +DB4_7.DB43 3 +DB4_7.DB42 2 +DB4_7.DB41 1 +DB4_7.DB40 0 +DB5_7 0xF77C Message Data Byte 5 +DB5_7.DB57 7 +DB5_7.DB56 6 +DB5_7.DB55 5 +DB5_7.DB54 4 +DB5_7.DB53 3 +DB5_7.DB52 2 +DB5_7.DB51 1 +DB5_7.DB50 0 +DB6_7 0xF77D Message Data Byte 6 +DB6_7.DB67 7 +DB6_7.DB66 6 +DB6_7.DB65 5 +DB6_7.DB64 4 +DB6_7.DB63 3 +DB6_7.DB62 2 +DB6_7.DB61 1 +DB6_7.DB60 0 +DB7_7 0xF77E Message Data Byte 7 +DB7_7.DB77 7 +DB7_7.DB76 6 +DB7_7.DB75 5 +DB7_7.DB74 4 +DB7_7.DB73 3 +DB7_7.DB72 2 +DB7_7.DB71 1 +DB7_7.DB70 0 +RESERVEDF77F 0xF77F RESERVED +; -------------------------------------- CAN_8 -------------------------------- +MCR0_8 0xF780 Message Control Register Low +MCR0_8.MSGVAL1 7 +MCR0_8.MSGVAL0 6 +MCR0_8.TXIE1 5 +MCR0_8.TXIE0 4 +MCR0_8.RXIE1 3 +MCR0_8.RXIE0 2 +MCR0_8.INTPND1 1 +MCR0_8.INTPND0 0 +MCR1_8 0xF781 Message Control Register High +MCR1_8.RMTPND1 7 +MCR1_8.RMTPND0 6 +MCR1_8.TXRQ1 5 +MCR1_8.TXRQ0 4 +MCR1_8.MSGLSTCPUUPD1 3 +MCR1_8.MSGLSTCPUUPD0 2 +MCR1_8.NEWDAT1 1 +MCR1_8.NEWDAT0 0 +UAR0_8 0xF782 Upper Arbitration Register Low +UAR0_8.ID28 7 +UAR0_8.ID27 6 +UAR0_8.ID26 5 +UAR0_8.ID25 4 +UAR0_8.ID24 3 +UAR0_8.ID23 2 +UAR0_8.ID22 1 +UAR0_8.ID21 0 +UAR1_8 0xF783 Upper Arbitration Register High +UAR1_8.ID20 7 +UAR1_8.ID19 6 +UAR1_8.ID18 5 +UAR1_8.ID17 4 +UAR1_8.ID16 3 +UAR1_8.ID15 2 +UAR1_8.ID14 1 +UAR1_8.ID13 0 +LAR0_8 0xF784 Lower Arbitration Register Low +LAR0_8.ID12 7 +LAR0_8.ID11 6 +LAR0_8.ID10 5 +LAR0_8.ID9 4 +LAR0_8.ID8 3 +LAR0_8.ID7 2 +LAR0_8.ID6 1 +LAR0_8.ID5 0 +LAR1_8 0xF785 Lower Arbitration Register High +LAR1_8.ID4 7 +LAR1_8.ID3 6 +LAR1_8.ID2 5 +LAR1_8.ID1 4 +LAR1_8.ID0 3 +MCFG_8 0xF786 Message Configuration Register +MCFG_8.DLC7 7 +MCFG_8.DLC6 6 +MCFG_8.DLC5 5 +MCFG_8.DLC4 4 +MCFG_8.DIR 3 +MCFG_8.XTD 2 +DB0_8 0xF787 Message Data Byte 0 +DB0_8.DB07 7 +DB0_8.DB06 6 +DB0_8.DB05 5 +DB0_8.DB04 4 +DB0_8.DB03 3 +DB0_8.DB02 2 +DB0_8.DB01 1 +DB0_8.DB00 0 +DB1_8 0xF788 Message Data Byte 1 +DB1_8.DB17 7 +DB1_8.DB16 6 +DB1_8.DB15 5 +DB1_8.DB14 4 +DB1_8.DB13 3 +DB1_8.DB12 2 +DB1_8.DB11 1 +DB1_8.DB10 0 +DB2_8 0xF789 Message Data Byte 2 +DB2_8.DB27 7 +DB2_8.DB26 6 +DB2_8.DB25 5 +DB2_8.DB24 4 +DB2_8.DB23 3 +DB2_8.DB22 2 +DB2_8.DB21 1 +DB2_8.DB20 0 +DB3_8 0xF78A Message Data Byte 3 +DB3_8.DB37 7 +DB3_8.DB36 6 +DB3_8.DB35 5 +DB3_8.DB34 4 +DB3_8.DB33 3 +DB3_8.DB32 2 +DB3_8.DB31 1 +DB3_8.DB30 0 +DB4_8 0xF78B Message Data Byte 4 +DB4_8.DB47 7 +DB4_8.DB46 6 +DB4_8.DB45 5 +DB4_8.DB44 4 +DB4_8.DB43 3 +DB4_8.DB42 2 +DB4_8.DB41 1 +DB4_8.DB40 0 +DB5_8 0xF78C Message Data Byte 5 +DB5_8.DB57 7 +DB5_8.DB56 6 +DB5_8.DB55 5 +DB5_8.DB54 4 +DB5_8.DB53 3 +DB5_8.DB52 2 +DB5_8.DB51 1 +DB5_8.DB50 0 +DB6_8 0xF78D Message Data Byte 6 +DB6_8.DB67 7 +DB6_8.DB66 6 +DB6_8.DB65 5 +DB6_8.DB64 4 +DB6_8.DB63 3 +DB6_8.DB62 2 +DB6_8.DB61 1 +DB6_8.DB60 0 +DB7_8 0xF78E Message Data Byte 7 +DB7_8.DB77 7 +DB7_8.DB76 6 +DB7_8.DB75 5 +DB7_8.DB74 4 +DB7_8.DB73 3 +DB7_8.DB72 2 +DB7_8.DB71 1 +DB7_8.DB70 0 +RESERVEDF78F 0xF78F RESERVED +; -------------------------------------- CAN_9 -------------------------------- +MCR0_9 0xF790 Message Control Register Low +MCR0_9.MSGVAL1 7 +MCR0_9.MSGVAL0 6 +MCR0_9.TXIE1 5 +MCR0_9.TXIE0 4 +MCR0_9.RXIE1 3 +MCR0_9.RXIE0 2 +MCR0_9.INTPND1 1 +MCR0_9.INTPND0 0 +MCR1_9 0xF791 Message Control Register High +MCR1_9.RMTPND1 7 +MCR1_9.RMTPND0 6 +MCR1_9.TXRQ1 5 +MCR1_9.TXRQ0 4 +MCR1_9.MSGLSTCPUUPD1 3 +MCR1_9.MSGLSTCPUUPD0 2 +MCR1_9.NEWDAT1 1 +MCR1_9.NEWDAT0 0 +UAR0_9 0xF792 Upper Arbitration Register Low +UAR0_9.ID28 7 +UAR0_9.ID27 6 +UAR0_9.ID26 5 +UAR0_9.ID25 4 +UAR0_9.ID24 3 +UAR0_9.ID23 2 +UAR0_9.ID22 1 +UAR0_9.ID21 0 +UAR1_9 0xF793 Upper Arbitration Register High +UAR1_9.ID20 7 +UAR1_9.ID19 6 +UAR1_9.ID18 5 +UAR1_9.ID17 4 +UAR1_9.ID16 3 +UAR1_9.ID15 2 +UAR1_9.ID14 1 +UAR1_9.ID13 0 +LAR0_9 0xF794 Lower Arbitration Register Low +LAR0_9.ID12 7 +LAR0_9.ID11 6 +LAR0_9.ID10 5 +LAR0_9.ID9 4 +LAR0_9.ID8 3 +LAR0_9.ID7 2 +LAR0_9.ID6 1 +LAR0_9.ID5 0 +LAR1_9 0xF795 Lower Arbitration Register High +LAR1_9.ID4 7 +LAR1_9.ID3 6 +LAR1_9.ID2 5 +LAR1_9.ID1 4 +LAR1_9.ID0 3 +MCFG_9 0xF796 Message Configuration Register +MCFG_9.DLC7 7 +MCFG_9.DLC6 6 +MCFG_9.DLC5 5 +MCFG_9.DLC4 4 +MCFG_9.DIR 3 +MCFG_9.XTD 2 +DB0_9 0xF797 Message Data Byte 0 +DB0_9.DB07 7 +DB0_9.DB06 6 +DB0_9.DB05 5 +DB0_9.DB04 4 +DB0_9.DB03 3 +DB0_9.DB02 2 +DB0_9.DB01 1 +DB0_9.DB00 0 +DB1_9 0xF798 Message Data Byte 1 +DB1_9.DB17 7 +DB1_9.DB16 6 +DB1_9.DB15 5 +DB1_9.DB14 4 +DB1_9.DB13 3 +DB1_9.DB12 2 +DB1_9.DB11 1 +DB1_9.DB10 0 +DB2_9 0xF799 Message Data Byte 2 +DB2_9.DB27 7 +DB2_9.DB26 6 +DB2_9.DB25 5 +DB2_9.DB24 4 +DB2_9.DB23 3 +DB2_9.DB22 2 +DB2_9.DB21 1 +DB2_9.DB20 0 +DB3_9 0xF79A Message Data Byte 3 +DB3_9.DB37 7 +DB3_9.DB36 6 +DB3_9.DB35 5 +DB3_9.DB34 4 +DB3_9.DB33 3 +DB3_9.DB32 2 +DB3_9.DB31 1 +DB3_9.DB30 0 +DB4_9 0xF79B Message Data Byte 4 +DB4_9.DB47 7 +DB4_9.DB46 6 +DB4_9.DB45 5 +DB4_9.DB44 4 +DB4_9.DB43 3 +DB4_9.DB42 2 +DB4_9.DB41 1 +DB4_9.DB40 0 +DB5_9 0xF79C Message Data Byte 5 +DB5_9.DB57 7 +DB5_9.DB56 6 +DB5_9.DB55 5 +DB5_9.DB54 4 +DB5_9.DB53 3 +DB5_9.DB52 2 +DB5_9.DB51 1 +DB5_9.DB50 0 +DB6_9 0xF79D Message Data Byte 6 +DB6_9.DB67 7 +DB6_9.DB66 6 +DB6_9.DB65 5 +DB6_9.DB64 4 +DB6_9.DB63 3 +DB6_9.DB62 2 +DB6_9.DB61 1 +DB6_9.DB60 0 +DB7_9 0xF79E Message Data Byte 7 +DB7_9.DB77 7 +DB7_9.DB76 6 +DB7_9.DB75 5 +DB7_9.DB74 4 +DB7_9.DB73 3 +DB7_9.DB72 2 +DB7_9.DB71 1 +DB7_9.DB70 0 +RESERVEDF79F 0xF79F RESERVED +; -------------------------------------- CAN_A -------------------------------- +MCR0_A 0xF7A0 Message Control Register Low +MCR0_A.MSGVAL1 7 +MCR0_A.MSGVAL0 6 +MCR0_A.TXIE1 5 +MCR0_A.TXIE0 4 +MCR0_A.RXIE1 3 +MCR0_A.RXIE0 2 +MCR0_A.INTPND1 1 +MCR0_A.INTPND0 0 +MCR1_A 0xF7A1 Message Control Register High +MCR1_A.RMTPND1 7 +MCR1_A.RMTPND0 6 +MCR1_A.TXRQ1 5 +MCR1_A.TXRQ0 4 +MCR1_A.MSGLSTCPUUPD1 3 +MCR1_A.MSGLSTCPUUPD0 2 +MCR1_A.NEWDAT1 1 +MCR1_A.NEWDAT0 0 +UAR0_A 0xF7A2 Upper Arbitration Register Low +UAR0_A.ID28 7 +UAR0_A.ID27 6 +UAR0_A.ID26 5 +UAR0_A.ID25 4 +UAR0_A.ID24 3 +UAR0_A.ID23 2 +UAR0_A.ID22 1 +UAR0_A.ID21 0 +UAR1_A 0xF7A3 Upper Arbitration Register High +UAR1_A.ID20 7 +UAR1_A.ID19 6 +UAR1_A.ID18 5 +UAR1_A.ID17 4 +UAR1_A.ID16 3 +UAR1_A.ID15 2 +UAR1_A.ID14 1 +UAR1_A.ID13 0 +LAR0_A 0xF7A4 Lower Arbitration Register Low +LAR0_A.ID12 7 +LAR0_A.ID11 6 +LAR0_A.ID10 5 +LAR0_A.ID9 4 +LAR0_A.ID8 3 +LAR0_A.ID7 2 +LAR0_A.ID6 1 +LAR0_A.ID5 0 +LAR1_A 0xF7A5 Lower Arbitration Register High +LAR1_A.ID4 7 +LAR1_A.ID3 6 +LAR1_A.ID2 5 +LAR1_A.ID1 4 +LAR1_A.ID0 3 +MCFG_A 0xF7A6 Message Configuration Register +MCFG_A.DLC7 7 +MCFG_A.DLC6 6 +MCFG_A.DLC5 5 +MCFG_A.DLC4 4 +MCFG_A.DIR 3 +MCFG_A.XTD 2 +DB0_A 0xF7A7 Message Data Byte 0 +DB0_A.DB07 7 +DB0_A.DB06 6 +DB0_A.DB05 5 +DB0_A.DB04 4 +DB0_A.DB03 3 +DB0_A.DB02 2 +DB0_A.DB01 1 +DB0_A.DB00 0 +DB1_A 0xF7A8 Message Data Byte 1 +DB1_A.DB17 7 +DB1_A.DB16 6 +DB1_A.DB15 5 +DB1_A.DB14 4 +DB1_A.DB13 3 +DB1_A.DB12 2 +DB1_A.DB11 1 +DB1_A.DB10 0 +DB2_A 0xF7A9 Message Data Byte 2 +DB2_A.DB27 7 +DB2_A.DB26 6 +DB2_A.DB25 5 +DB2_A.DB24 4 +DB2_A.DB23 3 +DB2_A.DB22 2 +DB2_A.DB21 1 +DB2_A.DB20 0 +DB3_A 0xF7AA Message Data Byte 3 +DB3_A.DB37 7 +DB3_A.DB36 6 +DB3_A.DB35 5 +DB3_A.DB34 4 +DB3_A.DB33 3 +DB3_A.DB32 2 +DB3_A.DB31 1 +DB3_A.DB30 0 +DB4_A 0xF7AB Message Data Byte 4 +DB4_A.DB47 7 +DB4_A.DB46 6 +DB4_A.DB45 5 +DB4_A.DB44 4 +DB4_A.DB43 3 +DB4_A.DB42 2 +DB4_A.DB41 1 +DB4_A.DB40 0 +DB5_A 0xF7AC Message Data Byte 5 +DB5_A.DB57 7 +DB5_A.DB56 6 +DB5_A.DB55 5 +DB5_A.DB54 4 +DB5_A.DB53 3 +DB5_A.DB52 2 +DB5_A.DB51 1 +DB5_A.DB50 0 +DB6_A 0xF7AD Message Data Byte 6 +DB6_A.DB67 7 +DB6_A.DB66 6 +DB6_A.DB65 5 +DB6_A.DB64 4 +DB6_A.DB63 3 +DB6_A.DB62 2 +DB6_A.DB61 1 +DB6_A.DB60 0 +DB7_A 0xF7AE Message Data Byte 7 +DB7_A.DB77 7 +DB7_A.DB76 6 +DB7_A.DB75 5 +DB7_A.DB74 4 +DB7_A.DB73 3 +DB7_A.DB72 2 +DB7_A.DB71 1 +DB7_A.DB70 0 +RESERVEDF7AF 0xF7AF RESERVED +; -------------------------------------- CAN_B -------------------------------- +MCR0_B 0xF7B0 Message Control Register Low +MCR0_B.MSGVAL1 7 +MCR0_B.MSGVAL0 6 +MCR0_B.TXIE1 5 +MCR0_B.TXIE0 4 +MCR0_B.RXIE1 3 +MCR0_B.RXIE0 2 +MCR0_B.INTPND1 1 +MCR0_B.INTPND0 0 +MCR1_B 0xF7B1 Message Control Register High +MCR1_B.RMTPND1 7 +MCR1_B.RMTPND0 6 +MCR1_B.TXRQ1 5 +MCR1_B.TXRQ0 4 +MCR1_B.MSGLSTCPUUPD1 3 +MCR1_B.MSGLSTCPUUPD0 2 +MCR1_B.NEWDAT1 1 +MCR1_B.NEWDAT0 0 +UAR0_B 0xF7B2 Upper Arbitration Register Low +UAR0_B.ID28 7 +UAR0_B.ID27 6 +UAR0_B.ID26 5 +UAR0_B.ID25 4 +UAR0_B.ID24 3 +UAR0_B.ID23 2 +UAR0_B.ID22 1 +UAR0_B.ID21 0 +UAR1_B 0xF7B3 Upper Arbitration Register High +UAR1_B.ID20 7 +UAR1_B.ID19 6 +UAR1_B.ID18 5 +UAR1_B.ID17 4 +UAR1_B.ID16 3 +UAR1_B.ID15 2 +UAR1_B.ID14 1 +UAR1_B.ID13 0 +LAR0_B 0xF7B4 Lower Arbitration Register Low +LAR0_B.ID12 7 +LAR0_B.ID11 6 +LAR0_B.ID10 5 +LAR0_B.ID9 4 +LAR0_B.ID8 3 +LAR0_B.ID7 2 +LAR0_B.ID6 1 +LAR0_B.ID5 0 +LAR1_B 0xF7B5 Lower Arbitration Register High +LAR1_B.ID4 7 +LAR1_B.ID3 6 +LAR1_B.ID2 5 +LAR1_B.ID1 4 +LAR1_B.ID0 3 +MCFG_B 0xF7B6 Message Configuration Register +MCFG_B.DLC7 7 +MCFG_B.DLC6 6 +MCFG_B.DLC5 5 +MCFG_B.DLC4 4 +MCFG_B.DIR 3 +MCFG_B.XTD 2 +DB0_B 0xF7B7 Message Data Byte 0 +DB0_B.DB07 7 +DB0_B.DB06 6 +DB0_B.DB05 5 +DB0_B.DB04 4 +DB0_B.DB03 3 +DB0_B.DB02 2 +DB0_B.DB01 1 +DB0_B.DB00 0 +DB1_B 0xF7B8 Message Data Byte 1 +DB1_B.DB17 7 +DB1_B.DB16 6 +DB1_B.DB15 5 +DB1_B.DB14 4 +DB1_B.DB13 3 +DB1_B.DB12 2 +DB1_B.DB11 1 +DB1_B.DB10 0 +DB2_B 0xF7B9 Message Data Byte 2 +DB2_B.DB27 7 +DB2_B.DB26 6 +DB2_B.DB25 5 +DB2_B.DB24 4 +DB2_B.DB23 3 +DB2_B.DB22 2 +DB2_B.DB21 1 +DB2_B.DB20 0 +DB3_B 0xF7BA Message Data Byte 3 +DB3_B.DB37 7 +DB3_B.DB36 6 +DB3_B.DB35 5 +DB3_B.DB34 4 +DB3_B.DB33 3 +DB3_B.DB32 2 +DB3_B.DB31 1 +DB3_B.DB30 0 +DB4_B 0xF7BB Message Data Byte 4 +DB4_B.DB47 7 +DB4_B.DB46 6 +DB4_B.DB45 5 +DB4_B.DB44 4 +DB4_B.DB43 3 +DB4_B.DB42 2 +DB4_B.DB41 1 +DB4_B.DB40 0 +DB5_B 0xF7BC Message Data Byte 5 +DB5_B.DB57 7 +DB5_B.DB56 6 +DB5_B.DB55 5 +DB5_B.DB54 4 +DB5_B.DB53 3 +DB5_B.DB52 2 +DB5_B.DB51 1 +DB5_B.DB50 0 +DB6_B 0xF7BD Message Data Byte 6 +DB6_B.DB67 7 +DB6_B.DB66 6 +DB6_B.DB65 5 +DB6_B.DB64 4 +DB6_B.DB63 3 +DB6_B.DB62 2 +DB6_B.DB61 1 +DB6_B.DB60 0 +DB7_B 0xF7BE Message Data Byte 7 +DB7_B.DB77 7 +DB7_B.DB76 6 +DB7_B.DB75 5 +DB7_B.DB74 4 +DB7_B.DB73 3 +DB7_B.DB72 2 +DB7_B.DB71 1 +DB7_B.DB70 0 +RESERVEDF7BF 0xF7BF RESERVED +; -------------------------------------- CAN_C -------------------------------- +MCR0_C 0xF7C0 Message Control Register Low +MCR0_C.MSGVAL1 7 +MCR0_C.MSGVAL0 6 +MCR0_C.TXIE1 5 +MCR0_C.TXIE0 4 +MCR0_C.RXIE1 3 +MCR0_C.RXIE0 2 +MCR0_C.INTPND1 1 +MCR0_C.INTPND0 0 +MCR1_C 0xF7C1 Message Control Register High +MCR1_C.RMTPND1 7 +MCR1_C.RMTPND0 6 +MCR1_C.TXRQ1 5 +MCR1_C.TXRQ0 4 +MCR1_C.MSGLSTCPUUPD1 3 +MCR1_C.MSGLSTCPUUPD0 2 +MCR1_C.NEWDAT1 1 +MCR1_C.NEWDAT0 0 +UAR0_C 0xF7C2 Upper Arbitration Register Low +UAR0_C.ID28 7 +UAR0_C.ID27 6 +UAR0_C.ID26 5 +UAR0_C.ID25 4 +UAR0_C.ID24 3 +UAR0_C.ID23 2 +UAR0_C.ID22 1 +UAR0_C.ID21 0 +UAR1_C 0xF7C3 Upper Arbitration Register High +UAR1_C.ID20 7 +UAR1_C.ID19 6 +UAR1_C.ID18 5 +UAR1_C.ID17 4 +UAR1_C.ID16 3 +UAR1_C.ID15 2 +UAR1_C.ID14 1 +UAR1_C.ID13 0 +LAR0_C 0xF7C4 Lower Arbitration Register Low +LAR0_C.ID12 7 +LAR0_C.ID11 6 +LAR0_C.ID10 5 +LAR0_C.ID9 4 +LAR0_C.ID8 3 +LAR0_C.ID7 2 +LAR0_C.ID6 1 +LAR0_C.ID5 0 +LAR1_C 0xF7C5 Lower Arbitration Register High +LAR1_C.ID4 7 +LAR1_C.ID3 6 +LAR1_C.ID2 5 +LAR1_C.ID1 4 +LAR1_C.ID0 3 +MCFG_C 0xF7C6 Message Configuration Register +MCFG_C.DLC7 7 +MCFG_C.DLC6 6 +MCFG_C.DLC5 5 +MCFG_C.DLC4 4 +MCFG_C.DIR 3 +MCFG_C.XTD 2 +DB0_C 0xF7C7 Message Data Byte 0 +DB0_C.DB07 7 +DB0_C.DB06 6 +DB0_C.DB05 5 +DB0_C.DB04 4 +DB0_C.DB03 3 +DB0_C.DB02 2 +DB0_C.DB01 1 +DB0_C.DB00 0 +DB1_C 0xF7C8 Message Data Byte 1 +DB1_C.DB17 7 +DB1_C.DB16 6 +DB1_C.DB15 5 +DB1_C.DB14 4 +DB1_C.DB13 3 +DB1_C.DB12 2 +DB1_C.DB11 1 +DB1_C.DB10 0 +DB2_C 0xF7C9 Message Data Byte 2 +DB2_C.DB27 7 +DB2_C.DB26 6 +DB2_C.DB25 5 +DB2_C.DB24 4 +DB2_C.DB23 3 +DB2_C.DB22 2 +DB2_C.DB21 1 +DB2_C.DB20 0 +DB3_C 0xF7CA Message Data Byte 3 +DB3_C.DB37 7 +DB3_C.DB36 6 +DB3_C.DB35 5 +DB3_C.DB34 4 +DB3_C.DB33 3 +DB3_C.DB32 2 +DB3_C.DB31 1 +DB3_C.DB30 0 +DB4_C 0xF7CB Message Data Byte 4 +DB4_C.DB47 7 +DB4_C.DB46 6 +DB4_C.DB45 5 +DB4_C.DB44 4 +DB4_C.DB43 3 +DB4_C.DB42 2 +DB4_C.DB41 1 +DB4_C.DB40 0 +DB5_C 0xF7CC Message Data Byte 5 +DB5_C.DB57 7 +DB5_C.DB56 6 +DB5_C.DB55 5 +DB5_C.DB54 4 +DB5_C.DB53 3 +DB5_C.DB52 2 +DB5_C.DB51 1 +DB5_C.DB50 0 +DB6_C 0xF7CD Message Data Byte 6 +DB6_C.DB67 7 +DB6_C.DB66 6 +DB6_C.DB65 5 +DB6_C.DB64 4 +DB6_C.DB63 3 +DB6_C.DB62 2 +DB6_C.DB61 1 +DB6_C.DB60 0 +DB7_C 0xF7CE Message Data Byte 7 +DB7_C.DB77 7 +DB7_C.DB76 6 +DB7_C.DB75 5 +DB7_C.DB74 4 +DB7_C.DB73 3 +DB7_C.DB72 2 +DB7_C.DB71 1 +DB7_C.DB70 0 +RESERVEDF7CF 0xF7CF RESERVED +; -------------------------------------- CAN_D -------------------------------- +MCR0_D 0xF7D0 Message Control Register Low +MCR0_D.MSGVAL1 7 +MCR0_D.MSGVAL0 6 +MCR0_D.TXIE1 5 +MCR0_D.TXIE0 4 +MCR0_D.RXIE1 3 +MCR0_D.RXIE0 2 +MCR0_D.INTPND1 1 +MCR0_D.INTPND0 0 +MCR1_D 0xF7D1 Message Control Register High +MCR1_D.RMTPND1 7 +MCR1_D.RMTPND0 6 +MCR1_D.TXRQ1 5 +MCR1_D.TXRQ0 4 +MCR1_D.MSGLSTCPUUPD1 3 +MCR1_D.MSGLSTCPUUPD0 2 +MCR1_D.NEWDAT1 1 +MCR1_D.NEWDAT0 0 +UAR0_D 0xF7D2 Upper Arbitration Register Low +UAR0_D.ID28 7 +UAR0_D.ID27 6 +UAR0_D.ID26 5 +UAR0_D.ID25 4 +UAR0_D.ID24 3 +UAR0_D.ID23 2 +UAR0_D.ID22 1 +UAR0_D.ID21 0 +UAR1_D 0xF7D3 Upper Arbitration Register High +UAR1_D.ID20 7 +UAR1_D.ID19 6 +UAR1_D.ID18 5 +UAR1_D.ID17 4 +UAR1_D.ID16 3 +UAR1_D.ID15 2 +UAR1_D.ID14 1 +UAR1_D.ID13 0 +LAR0_D 0xF7D4 Lower Arbitration Register Low +LAR0_D.ID12 7 +LAR0_D.ID11 6 +LAR0_D.ID10 5 +LAR0_D.ID9 4 +LAR0_D.ID8 3 +LAR0_D.ID7 2 +LAR0_D.ID6 1 +LAR0_D.ID5 0 +LAR1_D 0xF7D5 Lower Arbitration Register High +LAR1_D.ID4 7 +LAR1_D.ID3 6 +LAR1_D.ID2 5 +LAR1_D.ID1 4 +LAR1_D.ID0 3 +MCFG_D 0xF7D6 Message Configuration Register +MCFG_D.DLC7 7 +MCFG_D.DLC6 6 +MCFG_D.DLC5 5 +MCFG_D.DLC4 4 +MCFG_D.DIR 3 +MCFG_D.XTD 2 +DB0_D 0xF7D7 Message Data Byte 0 +DB0_D.DB07 7 +DB0_D.DB06 6 +DB0_D.DB05 5 +DB0_D.DB04 4 +DB0_D.DB03 3 +DB0_D.DB02 2 +DB0_D.DB01 1 +DB0_D.DB00 0 +DB1_D 0xF7D8 Message Data Byte 1 +DB1_D.DB17 7 +DB1_D.DB16 6 +DB1_D.DB15 5 +DB1_D.DB14 4 +DB1_D.DB13 3 +DB1_D.DB12 2 +DB1_D.DB11 1 +DB1_D.DB10 0 +DB2_D 0xF7D9 Message Data Byte 2 +DB2_D.DB27 7 +DB2_D.DB26 6 +DB2_D.DB25 5 +DB2_D.DB24 4 +DB2_D.DB23 3 +DB2_D.DB22 2 +DB2_D.DB21 1 +DB2_D.DB20 0 +DB3_D 0xF7DA Message Data Byte 3 +DB3_D.DB37 7 +DB3_D.DB36 6 +DB3_D.DB35 5 +DB3_D.DB34 4 +DB3_D.DB33 3 +DB3_D.DB32 2 +DB3_D.DB31 1 +DB3_D.DB30 0 +DB4_D 0xF7DB Message Data Byte 4 +DB4_D.DB47 7 +DB4_D.DB46 6 +DB4_D.DB45 5 +DB4_D.DB44 4 +DB4_D.DB43 3 +DB4_D.DB42 2 +DB4_D.DB41 1 +DB4_D.DB40 0 +DB5_D 0xF7DC Message Data Byte 5 +DB5_D.DB57 7 +DB5_D.DB56 6 +DB5_D.DB55 5 +DB5_D.DB54 4 +DB5_D.DB53 3 +DB5_D.DB52 2 +DB5_D.DB51 1 +DB5_D.DB50 0 +DB6_D 0xF7DD Message Data Byte 6 +DB6_D.DB67 7 +DB6_D.DB66 6 +DB6_D.DB65 5 +DB6_D.DB64 4 +DB6_D.DB63 3 +DB6_D.DB62 2 +DB6_D.DB61 1 +DB6_D.DB60 0 +DB7_D 0xF7DE Message Data Byte 7 +DB7_D.DB77 7 +DB7_D.DB76 6 +DB7_D.DB75 5 +DB7_D.DB74 4 +DB7_D.DB73 3 +DB7_D.DB72 2 +DB7_D.DB71 1 +DB7_D.DB70 0 +RESERVEDF7DF 0xF7DF RESERVED +; -------------------------------------- CAN_E -------------------------------- +MCR0_E 0xF7E0 Message Control Register Low +MCR0_E.MSGVAL1 7 +MCR0_E.MSGVAL0 6 +MCR0_E.TXIE1 5 +MCR0_E.TXIE0 4 +MCR0_E.RXIE1 3 +MCR0_E.RXIE0 2 +MCR0_E.INTPND1 1 +MCR0_E.INTPND0 0 +MCR1_E 0xF7E1 Message Control Register High +MCR1_E.RMTPND1 7 +MCR1_E.RMTPND0 6 +MCR1_E.TXRQ1 5 +MCR1_E.TXRQ0 4 +MCR1_E.MSGLSTCPUUPD1 3 +MCR1_E.MSGLSTCPUUPD0 2 +MCR1_E.NEWDAT1 1 +MCR1_E.NEWDAT0 0 +UAR0_E 0xF7E2 Upper Arbitration Register Low +UAR0_E.ID28 7 +UAR0_E.ID27 6 +UAR0_E.ID26 5 +UAR0_E.ID25 4 +UAR0_E.ID24 3 +UAR0_E.ID23 2 +UAR0_E.ID22 1 +UAR0_E.ID21 0 +UAR1_E 0xF7E3 Upper Arbitration Register High +UAR1_E.ID20 7 +UAR1_E.ID19 6 +UAR1_E.ID18 5 +UAR1_E.ID17 4 +UAR1_E.ID16 3 +UAR1_E.ID15 2 +UAR1_E.ID14 1 +UAR1_E.ID13 0 +LAR0_E 0xF7E4 Lower Arbitration Register Low +LAR0_E.ID12 7 +LAR0_E.ID11 6 +LAR0_E.ID10 5 +LAR0_E.ID9 4 +LAR0_E.ID8 3 +LAR0_E.ID7 2 +LAR0_E.ID6 1 +LAR0_E.ID5 0 +LAR1_E 0xF7E5 Lower Arbitration Register High +LAR1_E.ID4 7 +LAR1_E.ID3 6 +LAR1_E.ID2 5 +LAR1_E.ID1 4 +LAR1_E.ID0 3 +MCFG_E 0xF7E6 Message Configuration Register +MCFG_E.DLC7 7 +MCFG_E.DLC6 6 +MCFG_E.DLC5 5 +MCFG_E.DLC4 4 +MCFG_E.DIR 3 +MCFG_E.XTD 2 +DB0_E 0xF7E7 Message Data Byte 0 +DB0_E.DB07 7 +DB0_E.DB06 6 +DB0_E.DB05 5 +DB0_E.DB04 4 +DB0_E.DB03 3 +DB0_E.DB02 2 +DB0_E.DB01 1 +DB0_E.DB00 0 +DB1_E 0xF7E8 Message Data Byte 1 +DB1_E.DB17 7 +DB1_E.DB16 6 +DB1_E.DB15 5 +DB1_E.DB14 4 +DB1_E.DB13 3 +DB1_E.DB12 2 +DB1_E.DB11 1 +DB1_E.DB10 0 +DB2_E 0xF7E9 Message Data Byte 2 +DB2_E.DB27 7 +DB2_E.DB26 6 +DB2_E.DB25 5 +DB2_E.DB24 4 +DB2_E.DB23 3 +DB2_E.DB22 2 +DB2_E.DB21 1 +DB2_E.DB20 0 +DB3_E 0xF7EA Message Data Byte 3 +DB3_E.DB37 7 +DB3_E.DB36 6 +DB3_E.DB35 5 +DB3_E.DB34 4 +DB3_E.DB33 3 +DB3_E.DB32 2 +DB3_E.DB31 1 +DB3_E.DB30 0 +DB4_E 0xF7EB Message Data Byte 4 +DB4_E.DB47 7 +DB4_E.DB46 6 +DB4_E.DB45 5 +DB4_E.DB44 4 +DB4_E.DB43 3 +DB4_E.DB42 2 +DB4_E.DB41 1 +DB4_E.DB40 0 +DB5_E 0xF7EC Message Data Byte 5 +DB5_E.DB57 7 +DB5_E.DB56 6 +DB5_E.DB55 5 +DB5_E.DB54 4 +DB5_E.DB53 3 +DB5_E.DB52 2 +DB5_E.DB51 1 +DB5_E.DB50 0 +DB6_E 0xF7ED Message Data Byte 6 +DB6_E.DB67 7 +DB6_E.DB66 6 +DB6_E.DB65 5 +DB6_E.DB64 4 +DB6_E.DB63 3 +DB6_E.DB62 2 +DB6_E.DB61 1 +DB6_E.DB60 0 +DB7_E 0xF7DE Message Data Byte 7 +DB7_E.DB77 7 +DB7_E.DB76 6 +DB7_E.DB75 5 +DB7_E.DB74 4 +DB7_E.DB73 3 +DB7_E.DB72 2 +DB7_E.DB71 1 +DB7_E.DB70 0 +RESERVEDF7EF 0xF7EF RESERVED +; -------------------------------------- CAN_F -------------------------------- +MCR0_F 0xF7F0 Message Control Register Low +MCR0_F.MSGVAL1 7 +MCR0_F.MSGVAL0 6 +MCR0_F.TXIE1 5 +MCR0_F.TXIE0 4 +MCR0_F.RXIE1 3 +MCR0_F.RXIE0 2 +MCR0_F.INTPND1 1 +MCR0_F.INTPND0 0 +MCR1_F 0xF7F1 Message Control Register High +MCR1_F.RMTPND1 7 +MCR1_F.RMTPND0 6 +MCR1_F.TXRQ1 5 +MCR1_F.TXRQ0 4 +MCR1_F.MSGLSTCPUUPD1 3 +MCR1_F.MSGLSTCPUUPD0 2 +MCR1_F.NEWDAT1 1 +MCR1_F.NEWDAT0 0 +UAR0_F 0xF7F2 Upper Arbitration Register Low +UAR0_F.ID28 7 +UAR0_F.ID27 6 +UAR0_F.ID26 5 +UAR0_F.ID25 4 +UAR0_F.ID24 3 +UAR0_F.ID23 2 +UAR0_F.ID22 1 +UAR0_F.ID21 0 +UAR1_F 0xF7F3 Upper Arbitration Register High +UAR1_F.ID20 7 +UAR1_F.ID19 6 +UAR1_F.ID18 5 +UAR1_F.ID17 4 +UAR1_F.ID16 3 +UAR1_F.ID15 2 +UAR1_F.ID14 1 +UAR1_F.ID13 0 +LAR0_F 0xF7F4 Lower Arbitration Register Low +LAR0_F.ID12 7 +LAR0_F.ID11 6 +LAR0_F.ID10 5 +LAR0_F.ID9 4 +LAR0_F.ID8 3 +LAR0_F.ID7 2 +LAR0_F.ID6 1 +LAR0_F.ID5 0 +LAR1_F 0xF7F5 Lower Arbitration Register High +LAR1_F.ID4 7 +LAR1_F.ID3 6 +LAR1_F.ID2 5 +LAR1_F.ID1 4 +LAR1_F.ID0 3 +MCFG_F 0xF7F6 Message Configuration Register +MCFG_F.DLC7 7 +MCFG_F.DLC6 6 +MCFG_F.DLC5 5 +MCFG_F.DLC4 4 +MCFG_F.DIR 3 +MCFG_F.XTD 2 +DB0_F 0xF7F7 Message Data Byte 0 +DB0_F.DB07 7 +DB0_F.DB06 6 +DB0_F.DB05 5 +DB0_F.DB04 4 +DB0_F.DB03 3 +DB0_F.DB02 2 +DB0_F.DB01 1 +DB0_F.DB00 0 +DB1_F 0xF7F8 Message Data Byte 1 +DB1_F.DB17 7 +DB1_F.DB16 6 +DB1_F.DB15 5 +DB1_F.DB14 4 +DB1_F.DB13 3 +DB1_F.DB12 2 +DB1_F.DB11 1 +DB1_F.DB10 0 +DB2_F 0xF7F9 Message Data Byte 2 +DB2_F.DB27 7 +DB2_F.DB26 6 +DB2_F.DB25 5 +DB2_F.DB24 4 +DB2_F.DB23 3 +DB2_F.DB22 2 +DB2_F.DB21 1 +DB2_F.DB20 0 +DB3_F 0xF7FA Message Data Byte 3 +DB3_F.DB37 7 +DB3_F.DB36 6 +DB3_F.DB35 5 +DB3_F.DB34 4 +DB3_F.DB33 3 +DB3_F.DB32 2 +DB3_F.DB31 1 +DB3_F.DB30 0 +DB4_F 0xF7FB Message Data Byte 4 +DB4_F.DB47 7 +DB4_F.DB46 6 +DB4_F.DB45 5 +DB4_F.DB44 4 +DB4_F.DB43 3 +DB4_F.DB42 2 +DB4_F.DB41 1 +DB4_F.DB40 0 +DB5_F 0xF7FC Message Data Byte 5 +DB5_F.DB57 7 +DB5_F.DB56 6 +DB5_F.DB55 5 +DB5_F.DB54 4 +DB5_F.DB53 3 +DB5_F.DB52 2 +DB5_F.DB51 1 +DB5_F.DB50 0 +DB6_F 0xF7FD Message Data Byte 6 +DB6_F.DB67 7 +DB6_F.DB66 6 +DB6_F.DB65 5 +DB6_F.DB64 4 +DB6_F.DB63 3 +DB6_F.DB62 2 +DB6_F.DB61 1 +DB6_F.DB60 0 +DB7_F 0xF7FE Message Data Byte 7 +DB7_F.DB77 7 +DB7_F.DB76 6 +DB7_F.DB75 5 +DB7_F.DB74 4 +DB7_F.DB73 3 +DB7_F.DB72 2 +DB7_F.DB71 1 +DB7_F.DB70 0 +RESERVEDF7FF 0xF7FF RESERVED + + +.C505CA +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=11843&parent_oid=8088 +; C505C.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xF700 +area DATA CAN 0xF700:0xF800 +area BSS RESERVED 0xF800:0xFC00 +area DATA XRAM 0xFC00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry CAN_SWI 0x004B CAN Controller / Software Interrupt +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry IRTC 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.P14 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +; P1ANA 0x0090 Port 1 Analog Input Selection Register +; P1ANA.EAN7 7 +; P1ANA.EAN6 6 +; P1ANA.EAN5 5 +; P1ANA.EAN4 4 +; P1ANA.EAN3 3 +; P1ANA.EAN2 2 +; P1ANA.EAN1 1 +; P1ANA.EAN0 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register (C505CA only) +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.CMOD 3 +SYSCON.CSWO 2 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.ECAN 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.SWI 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Reload Register Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Reload Register High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter High Byte Data Register (C505A / C505CA only) +ADDATH.ADDATH7 7 +ADDATH.ADDATH6 6 +ADDATH.ADDATH5 5 +ADDATH.ADDATH4 4 +ADDATH.ADDATH3 3 +ADDATH.ADDATH2 2 +ADDATH.ADDATH1 1 +ADDATH.ADDATH0 0 +ADDATL 0x00DA A/D Converter Low Byte Data Register (C505A / C505CA only) +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +RESERVED00DB 0x00DB RESERVED +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.RXDC 1 +P4.TXDC 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +VR2.VR27 7 +VR2.VR26 6 +VR2.VR25 5 +VR2.VR24 4 +VR2.VR23 3 +VR2.VR22 2 +VR2.VR21 1 +VR2.VR20 0 +RESERVED00FF 0x00FF RESERVED +; -------------------------------------- CAN -------------------------------- +CR 0xF700 Control Register +CR.TEST 7 +CR.CCE 6 +CR.EIE 3 +CR.SIE 2 +CR.IE 1 +CR.INIT 0 +SR 0xF701 Status Register +SR.BOFF 7 +SR.EWRN 6 +SR.RXOK 4 +SR.TXOK 3 +SR.LEC2 2 +SR.LEC1 1 +SR.LEC0 0 +IR 0xF702 Interrupt Register +IR.INTID7 7 +IR.INTID6 6 +IR.INTID5 5 +IR.INTID4 4 +IR.INTID3 3 +IR.INTID2 2 +IR.INTID1 1 +IR.INTID0 0 +RESERVEDF703 0xF703 RESERVED +BTR0 0xF704 Bit Timing Register Low +BTR0.SJW7 7 +BTR0.SJW6 6 +BTR0.BRP5 5 +BTR0.BRP4 4 +BTR0.BRP3 3 +BTR0.BRP2 2 +BTR0.BRP1 1 +BTR0.BRP0 0 +BTR1 0xF705 Bit Timing Register High +BTR1.TSEG26 6 +BTR1.TSEG25 5 +BTR1.TSEG24 4 +BTR1.TSEG13 3 +BTR1.TSEG12 2 +BTR1.TSEG11 1 +BTR1.TSEG10 0 +GMS0 0xF706 Global Mask Short Register Low +GMS0.ID28 7 +GMS0.ID27 6 +GMS0.ID26 5 +GMS0.ID25 4 +GMS0.ID24 3 +GMS0.ID23 2 +GMS0.ID22 1 +GMS0.ID21 0 +GMS1 0xF707 Global Mask Short Register High +GMS1.ID20 7 +GMS1.ID19 6 +GMS1.ID18 5 +UGML0 0xF708 Upper Global Mask Long Register Low +UGML0.ID28 7 +UGML0.ID27 6 +UGML0.ID26 5 +UGML0.ID25 4 +UGML0.ID24 3 +UGML0.ID23 2 +UGML0.ID22 1 +UGML0.ID21 0 +UGML1 0xF709 Upper Global Mask Long Register High +UGML1.ID20 7 +UGML1.ID19 6 +UGML1.ID18 5 +UGML1.ID17 4 +UGML1.ID16 3 +UGML1.ID15 2 +UGML1.ID14 1 +UGML1.ID13 0 +LGML0 0xF70A Lower Global Mask Long Register Low +LGML0.ID12 7 +LGML0.ID11 6 +LGML0.ID10 5 +LGML0.ID9 4 +LGML0.ID8 3 +LGML0.ID7 2 +LGML0.ID6 1 +LGML0.ID5 0 +LGML1 0xF70B Lower Global Mask Long Register High +LGML1.ID4 7 +LGML1.ID3 6 +LGML1.ID2 5 +LGML1.ID1 4 +LGML1.ID0 3 +UMLM0 0xF70C Upper Mask of Last Message Register Low +UMLM0.ID28 7 +UMLM0.ID27 6 +UMLM0.ID26 5 +UMLM0.ID25 4 +UMLM0.ID24 3 +UMLM0.ID23 2 +UMLM0.ID22 1 +UMLM0.ID21 0 +UMLM1 0xF70D Upper Mask of Last Message Register High +UMLM1.ID20 7 +UMLM1.ID19 6 +UMLM1.ID18 5 +UMLM1.ID17 4 +UMLM1.ID16 3 +UMLM1.ID15 2 +UMLM1.ID14 1 +UMLM1.ID13 0 +LMLM0 0xF70E Lower Mask of Last Message Register Low +LMLM0.ID12 7 +LMLM0.ID11 6 +LMLM0.ID10 5 +LMLM0.ID9 4 +LMLM0.ID8 3 +LMLM0.ID7 2 +LMLM0.ID6 1 +LMLM0.ID5 0 +LMLM1 0xF70F Lower Mask of Last Message Register High +LMLM1.ID4 7 +LMLM1.ID3 6 +LMLM1.ID2 5 +LMLM1.ID1 4 +LMLM1.ID0 3 +; -------------------------------------- CAN_1 -------------------------------- +MCR0_1 0xF710 Message Control Register Low +MCR0_1.MSGVAL1 7 +MCR0_1.MSGVAL0 6 +MCR0_1.TXIE1 5 +MCR0_1.TXIE0 4 +MCR0_1.RXIE1 3 +MCR0_1.RXIE0 2 +MCR0_1.INTPND1 1 +MCR0_1.INTPND0 0 +MCR1_1 0xF711 Message Control Register High +MCR1_1.RMTPND1 7 +MCR1_1.RMTPND0 6 +MCR1_1.TXRQ1 5 +MCR1_1.TXRQ0 4 +MCR1_1.MSGLSTCPUUPD1 3 +MCR1_1.MSGLSTCPUUPD0 2 +MCR1_1.NEWDAT1 1 +MCR1_1.NEWDAT0 0 +UAR0_1 0xF712 Upper Arbitration Register Low +UAR0_1.ID28 7 +UAR0_1.ID27 6 +UAR0_1.ID26 5 +UAR0_1.ID25 4 +UAR0_1.ID24 3 +UAR0_1.ID23 2 +UAR0_1.ID22 1 +UAR0_1.ID21 0 +UAR1_1 0xF713 Upper Arbitration Register High +UAR1_1.ID20 7 +UAR1_1.ID19 6 +UAR1_1.ID18 5 +UAR1_1.ID17 4 +UAR1_1.ID16 3 +UAR1_1.ID15 2 +UAR1_1.ID14 1 +UAR1_1.ID13 0 +LAR0_1 0xF714 Lower Arbitration Register Low +LAR0_1.ID12 7 +LAR0_1.ID11 6 +LAR0_1.ID10 5 +LAR0_1.ID9 4 +LAR0_1.ID8 3 +LAR0_1.ID7 2 +LAR0_1.ID6 1 +LAR0_1.ID5 0 +LAR1_1 0xF715 Lower Arbitration Register High +LAR1_1.ID4 7 +LAR1_1.ID3 6 +LAR1_1.ID2 5 +LAR1_1.ID1 4 +LAR1_1.ID0 3 +MCFG_1 0xF716 Message Configuration Register +MCFG_1.DLC7 7 +MCFG_1.DLC6 6 +MCFG_1.DLC5 5 +MCFG_1.DLC4 4 +MCFG_1.DIR 3 +MCFG_1.XTD 2 +DB0_1 0xF717 Message Data Byte 0 +DB0_1.DB07 7 +DB0_1.DB06 6 +DB0_1.DB05 5 +DB0_1.DB04 4 +DB0_1.DB03 3 +DB0_1.DB02 2 +DB0_1.DB01 1 +DB0_1.DB00 0 +DB1_1 0xF718 Message Data Byte 1 +DB1_1.DB17 7 +DB1_1.DB16 6 +DB1_1.DB15 5 +DB1_1.DB14 4 +DB1_1.DB13 3 +DB1_1.DB12 2 +DB1_1.DB11 1 +DB1_1.DB10 0 +DB2_1 0xF719 Message Data Byte 2 +DB2_1.DB27 7 +DB2_1.DB26 6 +DB2_1.DB25 5 +DB2_1.DB24 4 +DB2_1.DB23 3 +DB2_1.DB22 2 +DB2_1.DB21 1 +DB2_1.DB20 0 +DB3_1 0xF71A Message Data Byte 3 +DB3_1.DB37 7 +DB3_1.DB36 6 +DB3_1.DB35 5 +DB3_1.DB34 4 +DB3_1.DB33 3 +DB3_1.DB32 2 +DB3_1.DB31 1 +DB3_1.DB30 0 +DB4_1 0xF71B Message Data Byte 4 +DB4_1.DB47 7 +DB4_1.DB46 6 +DB4_1.DB45 5 +DB4_1.DB44 4 +DB4_1.DB43 3 +DB4_1.DB42 2 +DB4_1.DB41 1 +DB4_1.DB40 0 +DB5_1 0xF71C Message Data Byte 5 +DB5_1.DB57 7 +DB5_1.DB56 6 +DB5_1.DB55 5 +DB5_1.DB54 4 +DB5_1.DB53 3 +DB5_1.DB52 2 +DB5_1.DB51 1 +DB5_1.DB50 0 +DB6_1 0xF71D Message Data Byte 6 +DB6_1.DB67 7 +DB6_1.DB66 6 +DB6_1.DB65 5 +DB6_1.DB64 4 +DB6_1.DB63 3 +DB6_1.DB62 2 +DB6_1.DB61 1 +DB6_1.DB60 0 +DB7_1 0xF71E Message Data Byte 7 +DB7_1.DB77 7 +DB7_1.DB76 6 +DB7_1.DB75 5 +DB7_1.DB74 4 +DB7_1.DB73 3 +DB7_1.DB72 2 +DB7_1.DB71 1 +DB7_1.DB70 0 +RESERVEDF71F 0xF71F RESERVED +; -------------------------------------- CAN_2 -------------------------------- +MCR0_2 0xF720 Message Control Register Low +MCR0_2.MSGVAL1 7 +MCR0_2.MSGVAL0 6 +MCR0_2.TXIE1 5 +MCR0_2.TXIE0 4 +MCR0_2.RXIE1 3 +MCR0_2.RXIE0 2 +MCR0_2.INTPND1 1 +MCR0_2.INTPND0 0 +MCR1_2 0xF721 Message Control Register High +MCR1_2.RMTPND1 7 +MCR1_2.RMTPND0 6 +MCR1_2.TXRQ1 5 +MCR1_2.TXRQ0 4 +MCR1_2.MSGLSTCPUUPD1 3 +MCR1_2.MSGLSTCPUUPD0 2 +MCR1_2.NEWDAT1 1 +MCR1_2.NEWDAT0 0 +UAR0_2 0xF722 Upper Arbitration Register Low +UAR0_2.ID28 7 +UAR0_2.ID27 6 +UAR0_2.ID26 5 +UAR0_2.ID25 4 +UAR0_2.ID24 3 +UAR0_2.ID23 2 +UAR0_2.ID22 1 +UAR0_2.ID21 0 +UAR1_2 0xF723 Upper Arbitration Register High +UAR1_2.ID20 7 +UAR1_2.ID19 6 +UAR1_2.ID18 5 +UAR1_2.ID17 4 +UAR1_2.ID16 3 +UAR1_2.ID15 2 +UAR1_2.ID14 1 +UAR1_2.ID13 0 +LAR0_2 0xF724 Lower Arbitration Register Low +LAR0_2.ID12 7 +LAR0_2.ID11 6 +LAR0_2.ID10 5 +LAR0_2.ID9 4 +LAR0_2.ID8 3 +LAR0_2.ID7 2 +LAR0_2.ID6 1 +LAR0_2.ID5 0 +LAR1_2 0xF725 Lower Arbitration Register High +LAR1_2.ID4 7 +LAR1_2.ID3 6 +LAR1_2.ID2 5 +LAR1_2.ID1 4 +LAR1_2.ID0 3 +MCFG_2 0xF726 Message Configuration Register +MCFG_2.DLC7 7 +MCFG_2.DLC6 6 +MCFG_2.DLC5 5 +MCFG_2.DLC4 4 +MCFG_2.DIR 3 +MCFG_2.XTD 2 +DB0_2 0xF727 Message Data Byte 0 +DB0_2.DB07 7 +DB0_2.DB06 6 +DB0_2.DB05 5 +DB0_2.DB04 4 +DB0_2.DB03 3 +DB0_2.DB02 2 +DB0_2.DB01 1 +DB0_2.DB00 0 +DB1_2 0xF728 Message Data Byte 1 +DB1_2.DB17 7 +DB1_2.DB16 6 +DB1_2.DB15 5 +DB1_2.DB14 4 +DB1_2.DB13 3 +DB1_2.DB12 2 +DB1_2.DB11 1 +DB1_2.DB10 0 +DB2_2 0xF729 Message Data Byte 2 +DB2_2.DB27 7 +DB2_2.DB26 6 +DB2_2.DB25 5 +DB2_2.DB24 4 +DB2_2.DB23 3 +DB2_2.DB22 2 +DB2_2.DB21 1 +DB2_2.DB20 0 +DB3_2 0xF72A Message Data Byte 3 +DB3_2.DB37 7 +DB3_2.DB36 6 +DB3_2.DB35 5 +DB3_2.DB34 4 +DB3_2.DB33 3 +DB3_2.DB32 2 +DB3_2.DB31 1 +DB3_2.DB30 0 +DB4_2 0xF72B Message Data Byte 4 +DB4_2.DB47 7 +DB4_2.DB46 6 +DB4_2.DB45 5 +DB4_2.DB44 4 +DB4_2.DB43 3 +DB4_2.DB42 2 +DB4_2.DB41 1 +DB4_2.DB40 0 +DB5_2 0xF72C Message Data Byte 5 +DB5_2.DB57 7 +DB5_2.DB56 6 +DB5_2.DB55 5 +DB5_2.DB54 4 +DB5_2.DB53 3 +DB5_2.DB52 2 +DB5_2.DB51 1 +DB5_2.DB50 0 +DB6_2 0xF72D Message Data Byte 6 +DB6_2.DB67 7 +DB6_2.DB66 6 +DB6_2.DB65 5 +DB6_2.DB64 4 +DB6_2.DB63 3 +DB6_2.DB62 2 +DB6_2.DB61 1 +DB6_2.DB60 0 +DB7_2 0xF72E Message Data Byte 7 +DB7_2.DB77 7 +DB7_2.DB76 6 +DB7_2.DB75 5 +DB7_2.DB74 4 +DB7_2.DB73 3 +DB7_2.DB72 2 +DB7_2.DB71 1 +DB7_2.DB70 0 +RESERVEDF72F 0xF72F RESERVED +; -------------------------------------- CAN_3 -------------------------------- +MCR0_3 0xF730 Message Control Register Low +MCR0_3.MSGVAL1 7 +MCR0_3.MSGVAL0 6 +MCR0_3.TXIE1 5 +MCR0_3.TXIE0 4 +MCR0_3.RXIE1 3 +MCR0_3.RXIE0 2 +MCR0_3.INTPND1 1 +MCR0_3.INTPND0 0 +MCR1_3 0xF731 Message Control Register High +MCR1_3.RMTPND1 7 +MCR1_3.RMTPND0 6 +MCR1_3.TXRQ1 5 +MCR1_3.TXRQ0 4 +MCR1_3.MSGLSTCPUUPD1 3 +MCR1_3.MSGLSTCPUUPD0 2 +MCR1_3.NEWDAT1 1 +MCR1_3.NEWDAT0 0 +UAR0_3 0xF732 Upper Arbitration Register Low +UAR0_3.ID28 7 +UAR0_3.ID27 6 +UAR0_3.ID26 5 +UAR0_3.ID25 4 +UAR0_3.ID24 3 +UAR0_3.ID23 2 +UAR0_3.ID22 1 +UAR0_3.ID21 0 +UAR1_3 0xF733 Upper Arbitration Register High +UAR1_3.ID20 7 +UAR1_3.ID19 6 +UAR1_3.ID18 5 +UAR1_3.ID17 4 +UAR1_3.ID16 3 +UAR1_3.ID15 2 +UAR1_3.ID14 1 +UAR1_3.ID13 0 +LAR0_3 0xF734 Lower Arbitration Register Low +LAR0_3.ID12 7 +LAR0_3.ID11 6 +LAR0_3.ID10 5 +LAR0_3.ID9 4 +LAR0_3.ID8 3 +LAR0_3.ID7 2 +LAR0_3.ID6 1 +LAR0_3.ID5 0 +LAR1_3 0xF735 Lower Arbitration Register High +LAR1_3.ID4 7 +LAR1_3.ID3 6 +LAR1_3.ID2 5 +LAR1_3.ID1 4 +LAR1_3.ID0 3 +MCFG_3 0xF736 Message Configuration Register +MCFG_3.DLC7 7 +MCFG_3.DLC6 6 +MCFG_3.DLC5 5 +MCFG_3.DLC4 4 +MCFG_3.DIR 3 +MCFG_3.XTD 2 +DB0_3 0xF737 Message Data Byte 0 +DB0_3.DB07 7 +DB0_3.DB06 6 +DB0_3.DB05 5 +DB0_3.DB04 4 +DB0_3.DB03 3 +DB0_3.DB02 2 +DB0_3.DB01 1 +DB0_3.DB00 0 +DB1_3 0xF738 Message Data Byte 1 +DB1_3.DB17 7 +DB1_3.DB16 6 +DB1_3.DB15 5 +DB1_3.DB14 4 +DB1_3.DB13 3 +DB1_3.DB12 2 +DB1_3.DB11 1 +DB1_3.DB10 0 +DB2_3 0xF739 Message Data Byte 2 +DB2_3.DB27 7 +DB2_3.DB26 6 +DB2_3.DB25 5 +DB2_3.DB24 4 +DB2_3.DB23 3 +DB2_3.DB22 2 +DB2_3.DB21 1 +DB2_3.DB20 0 +DB3_3 0xF73A Message Data Byte 3 +DB3_3.DB37 7 +DB3_3.DB36 6 +DB3_3.DB35 5 +DB3_3.DB34 4 +DB3_3.DB33 3 +DB3_3.DB32 2 +DB3_3.DB31 1 +DB3_3.DB30 0 +DB4_3 0xF73B Message Data Byte 4 +DB4_3.DB47 7 +DB4_3.DB46 6 +DB4_3.DB45 5 +DB4_3.DB44 4 +DB4_3.DB43 3 +DB4_3.DB42 2 +DB4_3.DB41 1 +DB4_3.DB40 0 +DB5_3 0xF73C Message Data Byte 5 +DB5_3.DB57 7 +DB5_3.DB56 6 +DB5_3.DB55 5 +DB5_3.DB54 4 +DB5_3.DB53 3 +DB5_3.DB52 2 +DB5_3.DB51 1 +DB5_3.DB50 0 +DB6_3 0xF73D Message Data Byte 6 +DB6_3.DB67 7 +DB6_3.DB66 6 +DB6_3.DB65 5 +DB6_3.DB64 4 +DB6_3.DB63 3 +DB6_3.DB62 2 +DB6_3.DB61 1 +DB6_3.DB60 0 +DB7_3 0xF73E Message Data Byte 7 +DB7_3.DB77 7 +DB7_3.DB76 6 +DB7_3.DB75 5 +DB7_3.DB74 4 +DB7_3.DB73 3 +DB7_3.DB72 2 +DB7_3.DB71 1 +DB7_3.DB70 0 +RESERVEDF73F 0xF73F RESERVED +; -------------------------------------- CAN_4 -------------------------------- +MCR0_4 0xF740 Message Control Register Low +MCR0_4.MSGVAL1 7 +MCR0_4.MSGVAL0 6 +MCR0_4.TXIE1 5 +MCR0_4.TXIE0 4 +MCR0_4.RXIE1 3 +MCR0_4.RXIE0 2 +MCR0_4.INTPND1 1 +MCR0_4.INTPND0 0 +MCR1_4 0xF741 Message Control Register High +MCR1_4.RMTPND1 7 +MCR1_4.RMTPND0 6 +MCR1_4.TXRQ1 5 +MCR1_4.TXRQ0 4 +MCR1_4.MSGLSTCPUUPD1 3 +MCR1_4.MSGLSTCPUUPD0 2 +MCR1_4.NEWDAT1 1 +MCR1_4.NEWDAT0 0 +UAR0_4 0xF742 Upper Arbitration Register Low +UAR0_4.ID28 7 +UAR0_4.ID27 6 +UAR0_4.ID26 5 +UAR0_4.ID25 4 +UAR0_4.ID24 3 +UAR0_4.ID23 2 +UAR0_4.ID22 1 +UAR0_4.ID21 0 +UAR1_4 0xF743 Upper Arbitration Register High +UAR1_4.ID20 7 +UAR1_4.ID19 6 +UAR1_4.ID18 5 +UAR1_4.ID17 4 +UAR1_4.ID16 3 +UAR1_4.ID15 2 +UAR1_4.ID14 1 +UAR1_4.ID13 0 +LAR0_4 0xF744 Lower Arbitration Register Low +LAR0_4.ID12 7 +LAR0_4.ID11 6 +LAR0_4.ID10 5 +LAR0_4.ID9 4 +LAR0_4.ID8 3 +LAR0_4.ID7 2 +LAR0_4.ID6 1 +LAR0_4.ID5 0 +LAR1_4 0xF745 Lower Arbitration Register High +LAR1_4.ID4 7 +LAR1_4.ID3 6 +LAR1_4.ID2 5 +LAR1_4.ID1 4 +LAR1_4.ID0 3 +MCFG_4 0xF746 Message Configuration Register +MCFG_4.DLC7 7 +MCFG_4.DLC6 6 +MCFG_4.DLC5 5 +MCFG_4.DLC4 4 +MCFG_4.DIR 3 +MCFG_4.XTD 2 +DB0_4 0xF747 Message Data Byte 0 +DB0_4.DB07 7 +DB0_4.DB06 6 +DB0_4.DB05 5 +DB0_4.DB04 4 +DB0_4.DB03 3 +DB0_4.DB02 2 +DB0_4.DB01 1 +DB0_4.DB00 0 +DB1_4 0xF748 Message Data Byte 1 +DB1_4.DB17 7 +DB1_4.DB16 6 +DB1_4.DB15 5 +DB1_4.DB14 4 +DB1_4.DB13 3 +DB1_4.DB12 2 +DB1_4.DB11 1 +DB1_4.DB10 0 +DB2_4 0xF749 Message Data Byte 2 +DB2_4.DB27 7 +DB2_4.DB26 6 +DB2_4.DB25 5 +DB2_4.DB24 4 +DB2_4.DB23 3 +DB2_4.DB22 2 +DB2_4.DB21 1 +DB2_4.DB20 0 +DB3_4 0xF74A Message Data Byte 3 +DB3_4.DB37 7 +DB3_4.DB36 6 +DB3_4.DB35 5 +DB3_4.DB34 4 +DB3_4.DB33 3 +DB3_4.DB32 2 +DB3_4.DB31 1 +DB3_4.DB30 0 +DB4_4 0xF74B Message Data Byte 4 +DB4_4.DB47 7 +DB4_4.DB46 6 +DB4_4.DB45 5 +DB4_4.DB44 4 +DB4_4.DB43 3 +DB4_4.DB42 2 +DB4_4.DB41 1 +DB4_4.DB40 0 +DB5_4 0xF74C Message Data Byte 5 +DB5_4.DB57 7 +DB5_4.DB56 6 +DB5_4.DB55 5 +DB5_4.DB54 4 +DB5_4.DB53 3 +DB5_4.DB52 2 +DB5_4.DB51 1 +DB5_4.DB50 0 +DB6_4 0xF74D Message Data Byte 6 +DB6_4.DB67 7 +DB6_4.DB66 6 +DB6_4.DB65 5 +DB6_4.DB64 4 +DB6_4.DB63 3 +DB6_4.DB62 2 +DB6_4.DB61 1 +DB6_4.DB60 0 +DB7_4 0xF74E Message Data Byte 7 +DB7_4.DB77 7 +DB7_4.DB76 6 +DB7_4.DB75 5 +DB7_4.DB74 4 +DB7_4.DB73 3 +DB7_4.DB72 2 +DB7_4.DB71 1 +DB7_4.DB70 0 +RESERVEDF74F 0xF74F RESERVED +; -------------------------------------- CAN_5 -------------------------------- +MCR0_5 0xF750 Message Control Register Low +MCR0_5.MSGVAL1 7 +MCR0_5.MSGVAL0 6 +MCR0_5.TXIE1 5 +MCR0_5.TXIE0 4 +MCR0_5.RXIE1 3 +MCR0_5.RXIE0 2 +MCR0_5.INTPND1 1 +MCR0_5.INTPND0 0 +MCR1_5 0xF751 Message Control Register High +MCR1_5.RMTPND1 7 +MCR1_5.RMTPND0 6 +MCR1_5.TXRQ1 5 +MCR1_5.TXRQ0 4 +MCR1_5.MSGLSTCPUUPD1 3 +MCR1_5.MSGLSTCPUUPD0 2 +MCR1_5.NEWDAT1 1 +MCR1_5.NEWDAT0 0 +UAR0_5 0xF752 Upper Arbitration Register Low +UAR0_5.ID28 7 +UAR0_5.ID27 6 +UAR0_5.ID26 5 +UAR0_5.ID25 4 +UAR0_5.ID24 3 +UAR0_5.ID23 2 +UAR0_5.ID22 1 +UAR0_5.ID21 0 +UAR1_5 0xF753 Upper Arbitration Register High +UAR1_5.ID20 7 +UAR1_5.ID19 6 +UAR1_5.ID18 5 +UAR1_5.ID17 4 +UAR1_5.ID16 3 +UAR1_5.ID15 2 +UAR1_5.ID14 1 +UAR1_5.ID13 0 +LAR0_5 0xF754 Lower Arbitration Register Low +LAR0_5.ID12 7 +LAR0_5.ID11 6 +LAR0_5.ID10 5 +LAR0_5.ID9 4 +LAR0_5.ID8 3 +LAR0_5.ID7 2 +LAR0_5.ID6 1 +LAR0_5.ID5 0 +LAR1_5 0xF755 Lower Arbitration Register High +LAR1_5.ID4 7 +LAR1_5.ID3 6 +LAR1_5.ID2 5 +LAR1_5.ID1 4 +LAR1_5.ID0 3 +MCFG_5 0xF756 Message Configuration Register +MCFG_5.DLC7 7 +MCFG_5.DLC6 6 +MCFG_5.DLC5 5 +MCFG_5.DLC4 4 +MCFG_5.DIR 3 +MCFG_5.XTD 2 +DB0_5 0xF757 Message Data Byte 0 +DB0_5.DB07 7 +DB0_5.DB06 6 +DB0_5.DB05 5 +DB0_5.DB04 4 +DB0_5.DB03 3 +DB0_5.DB02 2 +DB0_5.DB01 1 +DB0_5.DB00 0 +DB1_5 0xF758 Message Data Byte 1 +DB1_5.DB17 7 +DB1_5.DB16 6 +DB1_5.DB15 5 +DB1_5.DB14 4 +DB1_5.DB13 3 +DB1_5.DB12 2 +DB1_5.DB11 1 +DB1_5.DB10 0 +DB2_5 0xF759 Message Data Byte 2 +DB2_5.DB27 7 +DB2_5.DB26 6 +DB2_5.DB25 5 +DB2_5.DB24 4 +DB2_5.DB23 3 +DB2_5.DB22 2 +DB2_5.DB21 1 +DB2_5.DB20 0 +DB3_5 0xF75A Message Data Byte 3 +DB3_5.DB37 7 +DB3_5.DB36 6 +DB3_5.DB35 5 +DB3_5.DB34 4 +DB3_5.DB33 3 +DB3_5.DB32 2 +DB3_5.DB31 1 +DB3_5.DB30 0 +DB4_5 0xF75B Message Data Byte 4 +DB4_5.DB47 7 +DB4_5.DB46 6 +DB4_5.DB45 5 +DB4_5.DB44 4 +DB4_5.DB43 3 +DB4_5.DB42 2 +DB4_5.DB41 1 +DB4_5.DB40 0 +DB5_5 0xF75C Message Data Byte 5 +DB5_5.DB57 7 +DB5_5.DB56 6 +DB5_5.DB55 5 +DB5_5.DB54 4 +DB5_5.DB53 3 +DB5_5.DB52 2 +DB5_5.DB51 1 +DB5_5.DB50 0 +DB6_5 0xF75D Message Data Byte 6 +DB6_5.DB67 7 +DB6_5.DB66 6 +DB6_5.DB65 5 +DB6_5.DB64 4 +DB6_5.DB63 3 +DB6_5.DB62 2 +DB6_5.DB61 1 +DB6_5.DB60 0 +DB7_5 0xF75E Message Data Byte 7 +DB7_5.DB77 7 +DB7_5.DB76 6 +DB7_5.DB75 5 +DB7_5.DB74 4 +DB7_5.DB73 3 +DB7_5.DB72 2 +DB7_5.DB71 1 +DB7_5.DB70 0 +RESERVEDF75F 0xF75F RESERVED +; -------------------------------------- CAN_6 -------------------------------- +MCR0_6 0xF760 Message Control Register Low +MCR0_6.MSGVAL1 7 +MCR0_6.MSGVAL0 6 +MCR0_6.TXIE1 5 +MCR0_6.TXIE0 4 +MCR0_6.RXIE1 3 +MCR0_6.RXIE0 2 +MCR0_6.INTPND1 1 +MCR0_6.INTPND0 0 +MCR1_6 0xF761 Message Control Register High +MCR1_6.RMTPND1 7 +MCR1_6.RMTPND0 6 +MCR1_6.TXRQ1 5 +MCR1_6.TXRQ0 4 +MCR1_6.MSGLSTCPUUPD1 3 +MCR1_6.MSGLSTCPUUPD0 2 +MCR1_6.NEWDAT1 1 +MCR1_6.NEWDAT0 0 +UAR0_6 0xF762 Upper Arbitration Register Low +UAR0_6.ID28 7 +UAR0_6.ID27 6 +UAR0_6.ID26 5 +UAR0_6.ID25 4 +UAR0_6.ID24 3 +UAR0_6.ID23 2 +UAR0_6.ID22 1 +UAR0_6.ID21 0 +UAR1_6 0xF763 Upper Arbitration Register High +UAR1_6.ID20 7 +UAR1_6.ID19 6 +UAR1_6.ID18 5 +UAR1_6.ID17 4 +UAR1_6.ID16 3 +UAR1_6.ID15 2 +UAR1_6.ID14 1 +UAR1_6.ID13 0 +LAR0_6 0xF764 Lower Arbitration Register Low +LAR0_6.ID12 7 +LAR0_6.ID11 6 +LAR0_6.ID10 5 +LAR0_6.ID9 4 +LAR0_6.ID8 3 +LAR0_6.ID7 2 +LAR0_6.ID6 1 +LAR0_6.ID5 0 +LAR1_6 0xF765 Lower Arbitration Register High +LAR1_6.ID4 7 +LAR1_6.ID3 6 +LAR1_6.ID2 5 +LAR1_6.ID1 4 +LAR1_6.ID0 3 +MCFG_6 0xF766 Message Configuration Register +MCFG_6.DLC7 7 +MCFG_6.DLC6 6 +MCFG_6.DLC5 5 +MCFG_6.DLC4 4 +MCFG_6.DIR 3 +MCFG_6.XTD 2 +DB0_6 0xF767 Message Data Byte 0 +DB0_6.DB07 7 +DB0_6.DB06 6 +DB0_6.DB05 5 +DB0_6.DB04 4 +DB0_6.DB03 3 +DB0_6.DB02 2 +DB0_6.DB01 1 +DB0_6.DB00 0 +DB1_6 0xF768 Message Data Byte 1 +DB1_6.DB17 7 +DB1_6.DB16 6 +DB1_6.DB15 5 +DB1_6.DB14 4 +DB1_6.DB13 3 +DB1_6.DB12 2 +DB1_6.DB11 1 +DB1_6.DB10 0 +DB2_6 0xF769 Message Data Byte 2 +DB2_6.DB27 7 +DB2_6.DB26 6 +DB2_6.DB25 5 +DB2_6.DB24 4 +DB2_6.DB23 3 +DB2_6.DB22 2 +DB2_6.DB21 1 +DB2_6.DB20 0 +DB3_6 0xF76A Message Data Byte 3 +DB3_6.DB37 7 +DB3_6.DB36 6 +DB3_6.DB35 5 +DB3_6.DB34 4 +DB3_6.DB33 3 +DB3_6.DB32 2 +DB3_6.DB31 1 +DB3_6.DB30 0 +DB4_6 0xF76B Message Data Byte 4 +DB4_6.DB47 7 +DB4_6.DB46 6 +DB4_6.DB45 5 +DB4_6.DB44 4 +DB4_6.DB43 3 +DB4_6.DB42 2 +DB4_6.DB41 1 +DB4_6.DB40 0 +DB5_6 0xF76C Message Data Byte 5 +DB5_6.DB57 7 +DB5_6.DB56 6 +DB5_6.DB55 5 +DB5_6.DB54 4 +DB5_6.DB53 3 +DB5_6.DB52 2 +DB5_6.DB51 1 +DB5_6.DB50 0 +DB6_6 0xF76D Message Data Byte 6 +DB6_6.DB67 7 +DB6_6.DB66 6 +DB6_6.DB65 5 +DB6_6.DB64 4 +DB6_6.DB63 3 +DB6_6.DB62 2 +DB6_6.DB61 1 +DB6_6.DB60 0 +DB7_6 0xF76E Message Data Byte 7 +DB7_6.DB77 7 +DB7_6.DB76 6 +DB7_6.DB75 5 +DB7_6.DB74 4 +DB7_6.DB73 3 +DB7_6.DB72 2 +DB7_6.DB71 1 +DB7_6.DB70 0 +RESERVEDF76F 0xF76F RESERVED +; -------------------------------------- CAN_7 -------------------------------- +MCR0_7 0xF770 Message Control Register Low +MCR0_7.MSGVAL1 7 +MCR0_7.MSGVAL0 6 +MCR0_7.TXIE1 5 +MCR0_7.TXIE0 4 +MCR0_7.RXIE1 3 +MCR0_7.RXIE0 2 +MCR0_7.INTPND1 1 +MCR0_7.INTPND0 0 +MCR1_7 0xF771 Message Control Register High +MCR1_7.RMTPND1 7 +MCR1_7.RMTPND0 6 +MCR1_7.TXRQ1 5 +MCR1_7.TXRQ0 4 +MCR1_7.MSGLSTCPUUPD1 3 +MCR1_7.MSGLSTCPUUPD0 2 +MCR1_7.NEWDAT1 1 +MCR1_7.NEWDAT0 0 +UAR0_7 0xF772 Upper Arbitration Register Low +UAR0_7.ID28 7 +UAR0_7.ID27 6 +UAR0_7.ID26 5 +UAR0_7.ID25 4 +UAR0_7.ID24 3 +UAR0_7.ID23 2 +UAR0_7.ID22 1 +UAR0_7.ID21 0 +UAR1_7 0xF773 Upper Arbitration Register High +UAR1_7.ID20 7 +UAR1_7.ID19 6 +UAR1_7.ID18 5 +UAR1_7.ID17 4 +UAR1_7.ID16 3 +UAR1_7.ID15 2 +UAR1_7.ID14 1 +UAR1_7.ID13 0 +LAR0_7 0xF774 Lower Arbitration Register Low +LAR0_7.ID12 7 +LAR0_7.ID11 6 +LAR0_7.ID10 5 +LAR0_7.ID9 4 +LAR0_7.ID8 3 +LAR0_7.ID7 2 +LAR0_7.ID6 1 +LAR0_7.ID5 0 +LAR1_7 0xF775 Lower Arbitration Register High +LAR1_7.ID4 7 +LAR1_7.ID3 6 +LAR1_7.ID2 5 +LAR1_7.ID1 4 +LAR1_7.ID0 3 +MCFG_7 0xF776 Message Configuration Register +MCFG_7.DLC7 7 +MCFG_7.DLC6 6 +MCFG_7.DLC5 5 +MCFG_7.DLC4 4 +MCFG_7.DIR 3 +MCFG_7.XTD 2 +DB0_7 0xF777 Message Data Byte 0 +DB0_7.DB07 7 +DB0_7.DB06 6 +DB0_7.DB05 5 +DB0_7.DB04 4 +DB0_7.DB03 3 +DB0_7.DB02 2 +DB0_7.DB01 1 +DB0_7.DB00 0 +DB1_7 0xF778 Message Data Byte 1 +DB1_7.DB17 7 +DB1_7.DB16 6 +DB1_7.DB15 5 +DB1_7.DB14 4 +DB1_7.DB13 3 +DB1_7.DB12 2 +DB1_7.DB11 1 +DB1_7.DB10 0 +DB2_7 0xF779 Message Data Byte 2 +DB2_7.DB27 7 +DB2_7.DB26 6 +DB2_7.DB25 5 +DB2_7.DB24 4 +DB2_7.DB23 3 +DB2_7.DB22 2 +DB2_7.DB21 1 +DB2_7.DB20 0 +DB3_7 0xF77A Message Data Byte 3 +DB3_7.DB37 7 +DB3_7.DB36 6 +DB3_7.DB35 5 +DB3_7.DB34 4 +DB3_7.DB33 3 +DB3_7.DB32 2 +DB3_7.DB31 1 +DB3_7.DB30 0 +DB4_7 0xF77B Message Data Byte 4 +DB4_7.DB47 7 +DB4_7.DB46 6 +DB4_7.DB45 5 +DB4_7.DB44 4 +DB4_7.DB43 3 +DB4_7.DB42 2 +DB4_7.DB41 1 +DB4_7.DB40 0 +DB5_7 0xF77C Message Data Byte 5 +DB5_7.DB57 7 +DB5_7.DB56 6 +DB5_7.DB55 5 +DB5_7.DB54 4 +DB5_7.DB53 3 +DB5_7.DB52 2 +DB5_7.DB51 1 +DB5_7.DB50 0 +DB6_7 0xF77D Message Data Byte 6 +DB6_7.DB67 7 +DB6_7.DB66 6 +DB6_7.DB65 5 +DB6_7.DB64 4 +DB6_7.DB63 3 +DB6_7.DB62 2 +DB6_7.DB61 1 +DB6_7.DB60 0 +DB7_7 0xF77E Message Data Byte 7 +DB7_7.DB77 7 +DB7_7.DB76 6 +DB7_7.DB75 5 +DB7_7.DB74 4 +DB7_7.DB73 3 +DB7_7.DB72 2 +DB7_7.DB71 1 +DB7_7.DB70 0 +RESERVEDF77F 0xF77F RESERVED +; -------------------------------------- CAN_8 -------------------------------- +MCR0_8 0xF780 Message Control Register Low +MCR0_8.MSGVAL1 7 +MCR0_8.MSGVAL0 6 +MCR0_8.TXIE1 5 +MCR0_8.TXIE0 4 +MCR0_8.RXIE1 3 +MCR0_8.RXIE0 2 +MCR0_8.INTPND1 1 +MCR0_8.INTPND0 0 +MCR1_8 0xF781 Message Control Register High +MCR1_8.RMTPND1 7 +MCR1_8.RMTPND0 6 +MCR1_8.TXRQ1 5 +MCR1_8.TXRQ0 4 +MCR1_8.MSGLSTCPUUPD1 3 +MCR1_8.MSGLSTCPUUPD0 2 +MCR1_8.NEWDAT1 1 +MCR1_8.NEWDAT0 0 +UAR0_8 0xF782 Upper Arbitration Register Low +UAR0_8.ID28 7 +UAR0_8.ID27 6 +UAR0_8.ID26 5 +UAR0_8.ID25 4 +UAR0_8.ID24 3 +UAR0_8.ID23 2 +UAR0_8.ID22 1 +UAR0_8.ID21 0 +UAR1_8 0xF783 Upper Arbitration Register High +UAR1_8.ID20 7 +UAR1_8.ID19 6 +UAR1_8.ID18 5 +UAR1_8.ID17 4 +UAR1_8.ID16 3 +UAR1_8.ID15 2 +UAR1_8.ID14 1 +UAR1_8.ID13 0 +LAR0_8 0xF784 Lower Arbitration Register Low +LAR0_8.ID12 7 +LAR0_8.ID11 6 +LAR0_8.ID10 5 +LAR0_8.ID9 4 +LAR0_8.ID8 3 +LAR0_8.ID7 2 +LAR0_8.ID6 1 +LAR0_8.ID5 0 +LAR1_8 0xF785 Lower Arbitration Register High +LAR1_8.ID4 7 +LAR1_8.ID3 6 +LAR1_8.ID2 5 +LAR1_8.ID1 4 +LAR1_8.ID0 3 +MCFG_8 0xF786 Message Configuration Register +MCFG_8.DLC7 7 +MCFG_8.DLC6 6 +MCFG_8.DLC5 5 +MCFG_8.DLC4 4 +MCFG_8.DIR 3 +MCFG_8.XTD 2 +DB0_8 0xF787 Message Data Byte 0 +DB0_8.DB07 7 +DB0_8.DB06 6 +DB0_8.DB05 5 +DB0_8.DB04 4 +DB0_8.DB03 3 +DB0_8.DB02 2 +DB0_8.DB01 1 +DB0_8.DB00 0 +DB1_8 0xF788 Message Data Byte 1 +DB1_8.DB17 7 +DB1_8.DB16 6 +DB1_8.DB15 5 +DB1_8.DB14 4 +DB1_8.DB13 3 +DB1_8.DB12 2 +DB1_8.DB11 1 +DB1_8.DB10 0 +DB2_8 0xF789 Message Data Byte 2 +DB2_8.DB27 7 +DB2_8.DB26 6 +DB2_8.DB25 5 +DB2_8.DB24 4 +DB2_8.DB23 3 +DB2_8.DB22 2 +DB2_8.DB21 1 +DB2_8.DB20 0 +DB3_8 0xF78A Message Data Byte 3 +DB3_8.DB37 7 +DB3_8.DB36 6 +DB3_8.DB35 5 +DB3_8.DB34 4 +DB3_8.DB33 3 +DB3_8.DB32 2 +DB3_8.DB31 1 +DB3_8.DB30 0 +DB4_8 0xF78B Message Data Byte 4 +DB4_8.DB47 7 +DB4_8.DB46 6 +DB4_8.DB45 5 +DB4_8.DB44 4 +DB4_8.DB43 3 +DB4_8.DB42 2 +DB4_8.DB41 1 +DB4_8.DB40 0 +DB5_8 0xF78C Message Data Byte 5 +DB5_8.DB57 7 +DB5_8.DB56 6 +DB5_8.DB55 5 +DB5_8.DB54 4 +DB5_8.DB53 3 +DB5_8.DB52 2 +DB5_8.DB51 1 +DB5_8.DB50 0 +DB6_8 0xF78D Message Data Byte 6 +DB6_8.DB67 7 +DB6_8.DB66 6 +DB6_8.DB65 5 +DB6_8.DB64 4 +DB6_8.DB63 3 +DB6_8.DB62 2 +DB6_8.DB61 1 +DB6_8.DB60 0 +DB7_8 0xF78E Message Data Byte 7 +DB7_8.DB77 7 +DB7_8.DB76 6 +DB7_8.DB75 5 +DB7_8.DB74 4 +DB7_8.DB73 3 +DB7_8.DB72 2 +DB7_8.DB71 1 +DB7_8.DB70 0 +RESERVEDF78F 0xF78F RESERVED +; -------------------------------------- CAN_9 -------------------------------- +MCR0_9 0xF790 Message Control Register Low +MCR0_9.MSGVAL1 7 +MCR0_9.MSGVAL0 6 +MCR0_9.TXIE1 5 +MCR0_9.TXIE0 4 +MCR0_9.RXIE1 3 +MCR0_9.RXIE0 2 +MCR0_9.INTPND1 1 +MCR0_9.INTPND0 0 +MCR1_9 0xF791 Message Control Register High +MCR1_9.RMTPND1 7 +MCR1_9.RMTPND0 6 +MCR1_9.TXRQ1 5 +MCR1_9.TXRQ0 4 +MCR1_9.MSGLSTCPUUPD1 3 +MCR1_9.MSGLSTCPUUPD0 2 +MCR1_9.NEWDAT1 1 +MCR1_9.NEWDAT0 0 +UAR0_9 0xF792 Upper Arbitration Register Low +UAR0_9.ID28 7 +UAR0_9.ID27 6 +UAR0_9.ID26 5 +UAR0_9.ID25 4 +UAR0_9.ID24 3 +UAR0_9.ID23 2 +UAR0_9.ID22 1 +UAR0_9.ID21 0 +UAR1_9 0xF793 Upper Arbitration Register High +UAR1_9.ID20 7 +UAR1_9.ID19 6 +UAR1_9.ID18 5 +UAR1_9.ID17 4 +UAR1_9.ID16 3 +UAR1_9.ID15 2 +UAR1_9.ID14 1 +UAR1_9.ID13 0 +LAR0_9 0xF794 Lower Arbitration Register Low +LAR0_9.ID12 7 +LAR0_9.ID11 6 +LAR0_9.ID10 5 +LAR0_9.ID9 4 +LAR0_9.ID8 3 +LAR0_9.ID7 2 +LAR0_9.ID6 1 +LAR0_9.ID5 0 +LAR1_9 0xF795 Lower Arbitration Register High +LAR1_9.ID4 7 +LAR1_9.ID3 6 +LAR1_9.ID2 5 +LAR1_9.ID1 4 +LAR1_9.ID0 3 +MCFG_9 0xF796 Message Configuration Register +MCFG_9.DLC7 7 +MCFG_9.DLC6 6 +MCFG_9.DLC5 5 +MCFG_9.DLC4 4 +MCFG_9.DIR 3 +MCFG_9.XTD 2 +DB0_9 0xF797 Message Data Byte 0 +DB0_9.DB07 7 +DB0_9.DB06 6 +DB0_9.DB05 5 +DB0_9.DB04 4 +DB0_9.DB03 3 +DB0_9.DB02 2 +DB0_9.DB01 1 +DB0_9.DB00 0 +DB1_9 0xF798 Message Data Byte 1 +DB1_9.DB17 7 +DB1_9.DB16 6 +DB1_9.DB15 5 +DB1_9.DB14 4 +DB1_9.DB13 3 +DB1_9.DB12 2 +DB1_9.DB11 1 +DB1_9.DB10 0 +DB2_9 0xF799 Message Data Byte 2 +DB2_9.DB27 7 +DB2_9.DB26 6 +DB2_9.DB25 5 +DB2_9.DB24 4 +DB2_9.DB23 3 +DB2_9.DB22 2 +DB2_9.DB21 1 +DB2_9.DB20 0 +DB3_9 0xF79A Message Data Byte 3 +DB3_9.DB37 7 +DB3_9.DB36 6 +DB3_9.DB35 5 +DB3_9.DB34 4 +DB3_9.DB33 3 +DB3_9.DB32 2 +DB3_9.DB31 1 +DB3_9.DB30 0 +DB4_9 0xF79B Message Data Byte 4 +DB4_9.DB47 7 +DB4_9.DB46 6 +DB4_9.DB45 5 +DB4_9.DB44 4 +DB4_9.DB43 3 +DB4_9.DB42 2 +DB4_9.DB41 1 +DB4_9.DB40 0 +DB5_9 0xF79C Message Data Byte 5 +DB5_9.DB57 7 +DB5_9.DB56 6 +DB5_9.DB55 5 +DB5_9.DB54 4 +DB5_9.DB53 3 +DB5_9.DB52 2 +DB5_9.DB51 1 +DB5_9.DB50 0 +DB6_9 0xF79D Message Data Byte 6 +DB6_9.DB67 7 +DB6_9.DB66 6 +DB6_9.DB65 5 +DB6_9.DB64 4 +DB6_9.DB63 3 +DB6_9.DB62 2 +DB6_9.DB61 1 +DB6_9.DB60 0 +DB7_9 0xF79E Message Data Byte 7 +DB7_9.DB77 7 +DB7_9.DB76 6 +DB7_9.DB75 5 +DB7_9.DB74 4 +DB7_9.DB73 3 +DB7_9.DB72 2 +DB7_9.DB71 1 +DB7_9.DB70 0 +RESERVEDF79F 0xF79F RESERVED +; -------------------------------------- CAN_A -------------------------------- +MCR0_A 0xF7A0 Message Control Register Low +MCR0_A.MSGVAL1 7 +MCR0_A.MSGVAL0 6 +MCR0_A.TXIE1 5 +MCR0_A.TXIE0 4 +MCR0_A.RXIE1 3 +MCR0_A.RXIE0 2 +MCR0_A.INTPND1 1 +MCR0_A.INTPND0 0 +MCR1_A 0xF7A1 Message Control Register High +MCR1_A.RMTPND1 7 +MCR1_A.RMTPND0 6 +MCR1_A.TXRQ1 5 +MCR1_A.TXRQ0 4 +MCR1_A.MSGLSTCPUUPD1 3 +MCR1_A.MSGLSTCPUUPD0 2 +MCR1_A.NEWDAT1 1 +MCR1_A.NEWDAT0 0 +UAR0_A 0xF7A2 Upper Arbitration Register Low +UAR0_A.ID28 7 +UAR0_A.ID27 6 +UAR0_A.ID26 5 +UAR0_A.ID25 4 +UAR0_A.ID24 3 +UAR0_A.ID23 2 +UAR0_A.ID22 1 +UAR0_A.ID21 0 +UAR1_A 0xF7A3 Upper Arbitration Register High +UAR1_A.ID20 7 +UAR1_A.ID19 6 +UAR1_A.ID18 5 +UAR1_A.ID17 4 +UAR1_A.ID16 3 +UAR1_A.ID15 2 +UAR1_A.ID14 1 +UAR1_A.ID13 0 +LAR0_A 0xF7A4 Lower Arbitration Register Low +LAR0_A.ID12 7 +LAR0_A.ID11 6 +LAR0_A.ID10 5 +LAR0_A.ID9 4 +LAR0_A.ID8 3 +LAR0_A.ID7 2 +LAR0_A.ID6 1 +LAR0_A.ID5 0 +LAR1_A 0xF7A5 Lower Arbitration Register High +LAR1_A.ID4 7 +LAR1_A.ID3 6 +LAR1_A.ID2 5 +LAR1_A.ID1 4 +LAR1_A.ID0 3 +MCFG_A 0xF7A6 Message Configuration Register +MCFG_A.DLC7 7 +MCFG_A.DLC6 6 +MCFG_A.DLC5 5 +MCFG_A.DLC4 4 +MCFG_A.DIR 3 +MCFG_A.XTD 2 +DB0_A 0xF7A7 Message Data Byte 0 +DB0_A.DB07 7 +DB0_A.DB06 6 +DB0_A.DB05 5 +DB0_A.DB04 4 +DB0_A.DB03 3 +DB0_A.DB02 2 +DB0_A.DB01 1 +DB0_A.DB00 0 +DB1_A 0xF7A8 Message Data Byte 1 +DB1_A.DB17 7 +DB1_A.DB16 6 +DB1_A.DB15 5 +DB1_A.DB14 4 +DB1_A.DB13 3 +DB1_A.DB12 2 +DB1_A.DB11 1 +DB1_A.DB10 0 +DB2_A 0xF7A9 Message Data Byte 2 +DB2_A.DB27 7 +DB2_A.DB26 6 +DB2_A.DB25 5 +DB2_A.DB24 4 +DB2_A.DB23 3 +DB2_A.DB22 2 +DB2_A.DB21 1 +DB2_A.DB20 0 +DB3_A 0xF7AA Message Data Byte 3 +DB3_A.DB37 7 +DB3_A.DB36 6 +DB3_A.DB35 5 +DB3_A.DB34 4 +DB3_A.DB33 3 +DB3_A.DB32 2 +DB3_A.DB31 1 +DB3_A.DB30 0 +DB4_A 0xF7AB Message Data Byte 4 +DB4_A.DB47 7 +DB4_A.DB46 6 +DB4_A.DB45 5 +DB4_A.DB44 4 +DB4_A.DB43 3 +DB4_A.DB42 2 +DB4_A.DB41 1 +DB4_A.DB40 0 +DB5_A 0xF7AC Message Data Byte 5 +DB5_A.DB57 7 +DB5_A.DB56 6 +DB5_A.DB55 5 +DB5_A.DB54 4 +DB5_A.DB53 3 +DB5_A.DB52 2 +DB5_A.DB51 1 +DB5_A.DB50 0 +DB6_A 0xF7AD Message Data Byte 6 +DB6_A.DB67 7 +DB6_A.DB66 6 +DB6_A.DB65 5 +DB6_A.DB64 4 +DB6_A.DB63 3 +DB6_A.DB62 2 +DB6_A.DB61 1 +DB6_A.DB60 0 +DB7_A 0xF7AE Message Data Byte 7 +DB7_A.DB77 7 +DB7_A.DB76 6 +DB7_A.DB75 5 +DB7_A.DB74 4 +DB7_A.DB73 3 +DB7_A.DB72 2 +DB7_A.DB71 1 +DB7_A.DB70 0 +RESERVEDF7AF 0xF7AF RESERVED +; -------------------------------------- CAN_B -------------------------------- +MCR0_B 0xF7B0 Message Control Register Low +MCR0_B.MSGVAL1 7 +MCR0_B.MSGVAL0 6 +MCR0_B.TXIE1 5 +MCR0_B.TXIE0 4 +MCR0_B.RXIE1 3 +MCR0_B.RXIE0 2 +MCR0_B.INTPND1 1 +MCR0_B.INTPND0 0 +MCR1_B 0xF7B1 Message Control Register High +MCR1_B.RMTPND1 7 +MCR1_B.RMTPND0 6 +MCR1_B.TXRQ1 5 +MCR1_B.TXRQ0 4 +MCR1_B.MSGLSTCPUUPD1 3 +MCR1_B.MSGLSTCPUUPD0 2 +MCR1_B.NEWDAT1 1 +MCR1_B.NEWDAT0 0 +UAR0_B 0xF7B2 Upper Arbitration Register Low +UAR0_B.ID28 7 +UAR0_B.ID27 6 +UAR0_B.ID26 5 +UAR0_B.ID25 4 +UAR0_B.ID24 3 +UAR0_B.ID23 2 +UAR0_B.ID22 1 +UAR0_B.ID21 0 +UAR1_B 0xF7B3 Upper Arbitration Register High +UAR1_B.ID20 7 +UAR1_B.ID19 6 +UAR1_B.ID18 5 +UAR1_B.ID17 4 +UAR1_B.ID16 3 +UAR1_B.ID15 2 +UAR1_B.ID14 1 +UAR1_B.ID13 0 +LAR0_B 0xF7B4 Lower Arbitration Register Low +LAR0_B.ID12 7 +LAR0_B.ID11 6 +LAR0_B.ID10 5 +LAR0_B.ID9 4 +LAR0_B.ID8 3 +LAR0_B.ID7 2 +LAR0_B.ID6 1 +LAR0_B.ID5 0 +LAR1_B 0xF7B5 Lower Arbitration Register High +LAR1_B.ID4 7 +LAR1_B.ID3 6 +LAR1_B.ID2 5 +LAR1_B.ID1 4 +LAR1_B.ID0 3 +MCFG_B 0xF7B6 Message Configuration Register +MCFG_B.DLC7 7 +MCFG_B.DLC6 6 +MCFG_B.DLC5 5 +MCFG_B.DLC4 4 +MCFG_B.DIR 3 +MCFG_B.XTD 2 +DB0_B 0xF7B7 Message Data Byte 0 +DB0_B.DB07 7 +DB0_B.DB06 6 +DB0_B.DB05 5 +DB0_B.DB04 4 +DB0_B.DB03 3 +DB0_B.DB02 2 +DB0_B.DB01 1 +DB0_B.DB00 0 +DB1_B 0xF7B8 Message Data Byte 1 +DB1_B.DB17 7 +DB1_B.DB16 6 +DB1_B.DB15 5 +DB1_B.DB14 4 +DB1_B.DB13 3 +DB1_B.DB12 2 +DB1_B.DB11 1 +DB1_B.DB10 0 +DB2_B 0xF7B9 Message Data Byte 2 +DB2_B.DB27 7 +DB2_B.DB26 6 +DB2_B.DB25 5 +DB2_B.DB24 4 +DB2_B.DB23 3 +DB2_B.DB22 2 +DB2_B.DB21 1 +DB2_B.DB20 0 +DB3_B 0xF7BA Message Data Byte 3 +DB3_B.DB37 7 +DB3_B.DB36 6 +DB3_B.DB35 5 +DB3_B.DB34 4 +DB3_B.DB33 3 +DB3_B.DB32 2 +DB3_B.DB31 1 +DB3_B.DB30 0 +DB4_B 0xF7BB Message Data Byte 4 +DB4_B.DB47 7 +DB4_B.DB46 6 +DB4_B.DB45 5 +DB4_B.DB44 4 +DB4_B.DB43 3 +DB4_B.DB42 2 +DB4_B.DB41 1 +DB4_B.DB40 0 +DB5_B 0xF7BC Message Data Byte 5 +DB5_B.DB57 7 +DB5_B.DB56 6 +DB5_B.DB55 5 +DB5_B.DB54 4 +DB5_B.DB53 3 +DB5_B.DB52 2 +DB5_B.DB51 1 +DB5_B.DB50 0 +DB6_B 0xF7BD Message Data Byte 6 +DB6_B.DB67 7 +DB6_B.DB66 6 +DB6_B.DB65 5 +DB6_B.DB64 4 +DB6_B.DB63 3 +DB6_B.DB62 2 +DB6_B.DB61 1 +DB6_B.DB60 0 +DB7_B 0xF7BE Message Data Byte 7 +DB7_B.DB77 7 +DB7_B.DB76 6 +DB7_B.DB75 5 +DB7_B.DB74 4 +DB7_B.DB73 3 +DB7_B.DB72 2 +DB7_B.DB71 1 +DB7_B.DB70 0 +RESERVEDF7BF 0xF7BF RESERVED +; -------------------------------------- CAN_C -------------------------------- +MCR0_C 0xF7C0 Message Control Register Low +MCR0_C.MSGVAL1 7 +MCR0_C.MSGVAL0 6 +MCR0_C.TXIE1 5 +MCR0_C.TXIE0 4 +MCR0_C.RXIE1 3 +MCR0_C.RXIE0 2 +MCR0_C.INTPND1 1 +MCR0_C.INTPND0 0 +MCR1_C 0xF7C1 Message Control Register High +MCR1_C.RMTPND1 7 +MCR1_C.RMTPND0 6 +MCR1_C.TXRQ1 5 +MCR1_C.TXRQ0 4 +MCR1_C.MSGLSTCPUUPD1 3 +MCR1_C.MSGLSTCPUUPD0 2 +MCR1_C.NEWDAT1 1 +MCR1_C.NEWDAT0 0 +UAR0_C 0xF7C2 Upper Arbitration Register Low +UAR0_C.ID28 7 +UAR0_C.ID27 6 +UAR0_C.ID26 5 +UAR0_C.ID25 4 +UAR0_C.ID24 3 +UAR0_C.ID23 2 +UAR0_C.ID22 1 +UAR0_C.ID21 0 +UAR1_C 0xF7C3 Upper Arbitration Register High +UAR1_C.ID20 7 +UAR1_C.ID19 6 +UAR1_C.ID18 5 +UAR1_C.ID17 4 +UAR1_C.ID16 3 +UAR1_C.ID15 2 +UAR1_C.ID14 1 +UAR1_C.ID13 0 +LAR0_C 0xF7C4 Lower Arbitration Register Low +LAR0_C.ID12 7 +LAR0_C.ID11 6 +LAR0_C.ID10 5 +LAR0_C.ID9 4 +LAR0_C.ID8 3 +LAR0_C.ID7 2 +LAR0_C.ID6 1 +LAR0_C.ID5 0 +LAR1_C 0xF7C5 Lower Arbitration Register High +LAR1_C.ID4 7 +LAR1_C.ID3 6 +LAR1_C.ID2 5 +LAR1_C.ID1 4 +LAR1_C.ID0 3 +MCFG_C 0xF7C6 Message Configuration Register +MCFG_C.DLC7 7 +MCFG_C.DLC6 6 +MCFG_C.DLC5 5 +MCFG_C.DLC4 4 +MCFG_C.DIR 3 +MCFG_C.XTD 2 +DB0_C 0xF7C7 Message Data Byte 0 +DB0_C.DB07 7 +DB0_C.DB06 6 +DB0_C.DB05 5 +DB0_C.DB04 4 +DB0_C.DB03 3 +DB0_C.DB02 2 +DB0_C.DB01 1 +DB0_C.DB00 0 +DB1_C 0xF7C8 Message Data Byte 1 +DB1_C.DB17 7 +DB1_C.DB16 6 +DB1_C.DB15 5 +DB1_C.DB14 4 +DB1_C.DB13 3 +DB1_C.DB12 2 +DB1_C.DB11 1 +DB1_C.DB10 0 +DB2_C 0xF7C9 Message Data Byte 2 +DB2_C.DB27 7 +DB2_C.DB26 6 +DB2_C.DB25 5 +DB2_C.DB24 4 +DB2_C.DB23 3 +DB2_C.DB22 2 +DB2_C.DB21 1 +DB2_C.DB20 0 +DB3_C 0xF7CA Message Data Byte 3 +DB3_C.DB37 7 +DB3_C.DB36 6 +DB3_C.DB35 5 +DB3_C.DB34 4 +DB3_C.DB33 3 +DB3_C.DB32 2 +DB3_C.DB31 1 +DB3_C.DB30 0 +DB4_C 0xF7CB Message Data Byte 4 +DB4_C.DB47 7 +DB4_C.DB46 6 +DB4_C.DB45 5 +DB4_C.DB44 4 +DB4_C.DB43 3 +DB4_C.DB42 2 +DB4_C.DB41 1 +DB4_C.DB40 0 +DB5_C 0xF7CC Message Data Byte 5 +DB5_C.DB57 7 +DB5_C.DB56 6 +DB5_C.DB55 5 +DB5_C.DB54 4 +DB5_C.DB53 3 +DB5_C.DB52 2 +DB5_C.DB51 1 +DB5_C.DB50 0 +DB6_C 0xF7CD Message Data Byte 6 +DB6_C.DB67 7 +DB6_C.DB66 6 +DB6_C.DB65 5 +DB6_C.DB64 4 +DB6_C.DB63 3 +DB6_C.DB62 2 +DB6_C.DB61 1 +DB6_C.DB60 0 +DB7_C 0xF7CE Message Data Byte 7 +DB7_C.DB77 7 +DB7_C.DB76 6 +DB7_C.DB75 5 +DB7_C.DB74 4 +DB7_C.DB73 3 +DB7_C.DB72 2 +DB7_C.DB71 1 +DB7_C.DB70 0 +RESERVEDF7CF 0xF7CF RESERVED +; -------------------------------------- CAN_D -------------------------------- +MCR0_D 0xF7D0 Message Control Register Low +MCR0_D.MSGVAL1 7 +MCR0_D.MSGVAL0 6 +MCR0_D.TXIE1 5 +MCR0_D.TXIE0 4 +MCR0_D.RXIE1 3 +MCR0_D.RXIE0 2 +MCR0_D.INTPND1 1 +MCR0_D.INTPND0 0 +MCR1_D 0xF7D1 Message Control Register High +MCR1_D.RMTPND1 7 +MCR1_D.RMTPND0 6 +MCR1_D.TXRQ1 5 +MCR1_D.TXRQ0 4 +MCR1_D.MSGLSTCPUUPD1 3 +MCR1_D.MSGLSTCPUUPD0 2 +MCR1_D.NEWDAT1 1 +MCR1_D.NEWDAT0 0 +UAR0_D 0xF7D2 Upper Arbitration Register Low +UAR0_D.ID28 7 +UAR0_D.ID27 6 +UAR0_D.ID26 5 +UAR0_D.ID25 4 +UAR0_D.ID24 3 +UAR0_D.ID23 2 +UAR0_D.ID22 1 +UAR0_D.ID21 0 +UAR1_D 0xF7D3 Upper Arbitration Register High +UAR1_D.ID20 7 +UAR1_D.ID19 6 +UAR1_D.ID18 5 +UAR1_D.ID17 4 +UAR1_D.ID16 3 +UAR1_D.ID15 2 +UAR1_D.ID14 1 +UAR1_D.ID13 0 +LAR0_D 0xF7D4 Lower Arbitration Register Low +LAR0_D.ID12 7 +LAR0_D.ID11 6 +LAR0_D.ID10 5 +LAR0_D.ID9 4 +LAR0_D.ID8 3 +LAR0_D.ID7 2 +LAR0_D.ID6 1 +LAR0_D.ID5 0 +LAR1_D 0xF7D5 Lower Arbitration Register High +LAR1_D.ID4 7 +LAR1_D.ID3 6 +LAR1_D.ID2 5 +LAR1_D.ID1 4 +LAR1_D.ID0 3 +MCFG_D 0xF7D6 Message Configuration Register +MCFG_D.DLC7 7 +MCFG_D.DLC6 6 +MCFG_D.DLC5 5 +MCFG_D.DLC4 4 +MCFG_D.DIR 3 +MCFG_D.XTD 2 +DB0_D 0xF7D7 Message Data Byte 0 +DB0_D.DB07 7 +DB0_D.DB06 6 +DB0_D.DB05 5 +DB0_D.DB04 4 +DB0_D.DB03 3 +DB0_D.DB02 2 +DB0_D.DB01 1 +DB0_D.DB00 0 +DB1_D 0xF7D8 Message Data Byte 1 +DB1_D.DB17 7 +DB1_D.DB16 6 +DB1_D.DB15 5 +DB1_D.DB14 4 +DB1_D.DB13 3 +DB1_D.DB12 2 +DB1_D.DB11 1 +DB1_D.DB10 0 +DB2_D 0xF7D9 Message Data Byte 2 +DB2_D.DB27 7 +DB2_D.DB26 6 +DB2_D.DB25 5 +DB2_D.DB24 4 +DB2_D.DB23 3 +DB2_D.DB22 2 +DB2_D.DB21 1 +DB2_D.DB20 0 +DB3_D 0xF7DA Message Data Byte 3 +DB3_D.DB37 7 +DB3_D.DB36 6 +DB3_D.DB35 5 +DB3_D.DB34 4 +DB3_D.DB33 3 +DB3_D.DB32 2 +DB3_D.DB31 1 +DB3_D.DB30 0 +DB4_D 0xF7DB Message Data Byte 4 +DB4_D.DB47 7 +DB4_D.DB46 6 +DB4_D.DB45 5 +DB4_D.DB44 4 +DB4_D.DB43 3 +DB4_D.DB42 2 +DB4_D.DB41 1 +DB4_D.DB40 0 +DB5_D 0xF7DC Message Data Byte 5 +DB5_D.DB57 7 +DB5_D.DB56 6 +DB5_D.DB55 5 +DB5_D.DB54 4 +DB5_D.DB53 3 +DB5_D.DB52 2 +DB5_D.DB51 1 +DB5_D.DB50 0 +DB6_D 0xF7DD Message Data Byte 6 +DB6_D.DB67 7 +DB6_D.DB66 6 +DB6_D.DB65 5 +DB6_D.DB64 4 +DB6_D.DB63 3 +DB6_D.DB62 2 +DB6_D.DB61 1 +DB6_D.DB60 0 +DB7_D 0xF7DE Message Data Byte 7 +DB7_D.DB77 7 +DB7_D.DB76 6 +DB7_D.DB75 5 +DB7_D.DB74 4 +DB7_D.DB73 3 +DB7_D.DB72 2 +DB7_D.DB71 1 +DB7_D.DB70 0 +RESERVEDF7DF 0xF7DF RESERVED +; -------------------------------------- CAN_E -------------------------------- +MCR0_E 0xF7E0 Message Control Register Low +MCR0_E.MSGVAL1 7 +MCR0_E.MSGVAL0 6 +MCR0_E.TXIE1 5 +MCR0_E.TXIE0 4 +MCR0_E.RXIE1 3 +MCR0_E.RXIE0 2 +MCR0_E.INTPND1 1 +MCR0_E.INTPND0 0 +MCR1_E 0xF7E1 Message Control Register High +MCR1_E.RMTPND1 7 +MCR1_E.RMTPND0 6 +MCR1_E.TXRQ1 5 +MCR1_E.TXRQ0 4 +MCR1_E.MSGLSTCPUUPD1 3 +MCR1_E.MSGLSTCPUUPD0 2 +MCR1_E.NEWDAT1 1 +MCR1_E.NEWDAT0 0 +UAR0_E 0xF7E2 Upper Arbitration Register Low +UAR0_E.ID28 7 +UAR0_E.ID27 6 +UAR0_E.ID26 5 +UAR0_E.ID25 4 +UAR0_E.ID24 3 +UAR0_E.ID23 2 +UAR0_E.ID22 1 +UAR0_E.ID21 0 +UAR1_E 0xF7E3 Upper Arbitration Register High +UAR1_E.ID20 7 +UAR1_E.ID19 6 +UAR1_E.ID18 5 +UAR1_E.ID17 4 +UAR1_E.ID16 3 +UAR1_E.ID15 2 +UAR1_E.ID14 1 +UAR1_E.ID13 0 +LAR0_E 0xF7E4 Lower Arbitration Register Low +LAR0_E.ID12 7 +LAR0_E.ID11 6 +LAR0_E.ID10 5 +LAR0_E.ID9 4 +LAR0_E.ID8 3 +LAR0_E.ID7 2 +LAR0_E.ID6 1 +LAR0_E.ID5 0 +LAR1_E 0xF7E5 Lower Arbitration Register High +LAR1_E.ID4 7 +LAR1_E.ID3 6 +LAR1_E.ID2 5 +LAR1_E.ID1 4 +LAR1_E.ID0 3 +MCFG_E 0xF7E6 Message Configuration Register +MCFG_E.DLC7 7 +MCFG_E.DLC6 6 +MCFG_E.DLC5 5 +MCFG_E.DLC4 4 +MCFG_E.DIR 3 +MCFG_E.XTD 2 +DB0_E 0xF7E7 Message Data Byte 0 +DB0_E.DB07 7 +DB0_E.DB06 6 +DB0_E.DB05 5 +DB0_E.DB04 4 +DB0_E.DB03 3 +DB0_E.DB02 2 +DB0_E.DB01 1 +DB0_E.DB00 0 +DB1_E 0xF7E8 Message Data Byte 1 +DB1_E.DB17 7 +DB1_E.DB16 6 +DB1_E.DB15 5 +DB1_E.DB14 4 +DB1_E.DB13 3 +DB1_E.DB12 2 +DB1_E.DB11 1 +DB1_E.DB10 0 +DB2_E 0xF7E9 Message Data Byte 2 +DB2_E.DB27 7 +DB2_E.DB26 6 +DB2_E.DB25 5 +DB2_E.DB24 4 +DB2_E.DB23 3 +DB2_E.DB22 2 +DB2_E.DB21 1 +DB2_E.DB20 0 +DB3_E 0xF7EA Message Data Byte 3 +DB3_E.DB37 7 +DB3_E.DB36 6 +DB3_E.DB35 5 +DB3_E.DB34 4 +DB3_E.DB33 3 +DB3_E.DB32 2 +DB3_E.DB31 1 +DB3_E.DB30 0 +DB4_E 0xF7EB Message Data Byte 4 +DB4_E.DB47 7 +DB4_E.DB46 6 +DB4_E.DB45 5 +DB4_E.DB44 4 +DB4_E.DB43 3 +DB4_E.DB42 2 +DB4_E.DB41 1 +DB4_E.DB40 0 +DB5_E 0xF7EC Message Data Byte 5 +DB5_E.DB57 7 +DB5_E.DB56 6 +DB5_E.DB55 5 +DB5_E.DB54 4 +DB5_E.DB53 3 +DB5_E.DB52 2 +DB5_E.DB51 1 +DB5_E.DB50 0 +DB6_E 0xF7ED Message Data Byte 6 +DB6_E.DB67 7 +DB6_E.DB66 6 +DB6_E.DB65 5 +DB6_E.DB64 4 +DB6_E.DB63 3 +DB6_E.DB62 2 +DB6_E.DB61 1 +DB6_E.DB60 0 +DB7_E 0xF7EE Message Data Byte 7 +DB7_E.DB77 7 +DB7_E.DB76 6 +DB7_E.DB75 5 +DB7_E.DB74 4 +DB7_E.DB73 3 +DB7_E.DB72 2 +DB7_E.DB71 1 +DB7_E.DB70 0 +RESERVEDF7EF 0xF7EF RESERVED +; -------------------------------------- CAN_F -------------------------------- +MCR0_F 0xF7F0 Message Control Register Low +MCR0_F.MSGVAL1 7 +MCR0_F.MSGVAL0 6 +MCR0_F.TXIE1 5 +MCR0_F.TXIE0 4 +MCR0_F.RXIE1 3 +MCR0_F.RXIE0 2 +MCR0_F.INTPND1 1 +MCR0_F.INTPND0 0 +MCR1_F 0xF7F1 Message Control Register High +MCR1_F.RMTPND1 7 +MCR1_F.RMTPND0 6 +MCR1_F.TXRQ1 5 +MCR1_F.TXRQ0 4 +MCR1_F.MSGLSTCPUUPD1 3 +MCR1_F.MSGLSTCPUUPD0 2 +MCR1_F.NEWDAT1 1 +MCR1_F.NEWDAT0 0 +UAR0_F 0xF7F2 Upper Arbitration Register Low +UAR0_F.ID28 7 +UAR0_F.ID27 6 +UAR0_F.ID26 5 +UAR0_F.ID25 4 +UAR0_F.ID24 3 +UAR0_F.ID23 2 +UAR0_F.ID22 1 +UAR0_F.ID21 0 +UAR1_F 0xF7F3 Upper Arbitration Register High +UAR1_F.ID20 7 +UAR1_F.ID19 6 +UAR1_F.ID18 5 +UAR1_F.ID17 4 +UAR1_F.ID16 3 +UAR1_F.ID15 2 +UAR1_F.ID14 1 +UAR1_F.ID13 0 +LAR0_F 0xF7F4 Lower Arbitration Register Low +LAR0_F.ID12 7 +LAR0_F.ID11 6 +LAR0_F.ID10 5 +LAR0_F.ID9 4 +LAR0_F.ID8 3 +LAR0_F.ID7 2 +LAR0_F.ID6 1 +LAR0_F.ID5 0 +LAR1_F 0xF7F5 Lower Arbitration Register High +LAR1_F.ID4 7 +LAR1_F.ID3 6 +LAR1_F.ID2 5 +LAR1_F.ID1 4 +LAR1_F.ID0 3 +MCFG_F 0xF7F6 Message Configuration Register +MCFG_F.DLC7 7 +MCFG_F.DLC6 6 +MCFG_F.DLC5 5 +MCFG_F.DLC4 4 +MCFG_F.DIR 3 +MCFG_F.XTD 2 +DB0_F 0xF7F7 Message Data Byte 0 +DB0_F.DB07 7 +DB0_F.DB06 6 +DB0_F.DB05 5 +DB0_F.DB04 4 +DB0_F.DB03 3 +DB0_F.DB02 2 +DB0_F.DB01 1 +DB0_F.DB00 0 +DB1_F 0xF7F8 Message Data Byte 1 +DB1_F.DB17 7 +DB1_F.DB16 6 +DB1_F.DB15 5 +DB1_F.DB14 4 +DB1_F.DB13 3 +DB1_F.DB12 2 +DB1_F.DB11 1 +DB1_F.DB10 0 +DB2_F 0xF7F9 Message Data Byte 2 +DB2_F.DB27 7 +DB2_F.DB26 6 +DB2_F.DB25 5 +DB2_F.DB24 4 +DB2_F.DB23 3 +DB2_F.DB22 2 +DB2_F.DB21 1 +DB2_F.DB20 0 +DB3_F 0xF7FA Message Data Byte 3 +DB3_F.DB37 7 +DB3_F.DB36 6 +DB3_F.DB35 5 +DB3_F.DB34 4 +DB3_F.DB33 3 +DB3_F.DB32 2 +DB3_F.DB31 1 +DB3_F.DB30 0 +DB4_F 0xF7FB Message Data Byte 4 +DB4_F.DB47 7 +DB4_F.DB46 6 +DB4_F.DB45 5 +DB4_F.DB44 4 +DB4_F.DB43 3 +DB4_F.DB42 2 +DB4_F.DB41 1 +DB4_F.DB40 0 +DB5_F 0xF7FC Message Data Byte 5 +DB5_F.DB57 7 +DB5_F.DB56 6 +DB5_F.DB55 5 +DB5_F.DB54 4 +DB5_F.DB53 3 +DB5_F.DB52 2 +DB5_F.DB51 1 +DB5_F.DB50 0 +DB6_F 0xF7FD Message Data Byte 6 +DB6_F.DB67 7 +DB6_F.DB66 6 +DB6_F.DB65 5 +DB6_F.DB64 4 +DB6_F.DB63 3 +DB6_F.DB62 2 +DB6_F.DB61 1 +DB6_F.DB60 0 +DB7_F 0xF7FE Message Data Byte 7 +DB7_F.DB77 7 +DB7_F.DB76 6 +DB7_F.DB75 5 +DB7_F.DB74 4 +DB7_F.DB73 3 +DB7_F.DB72 2 +DB7_F.DB71 1 +DB7_F.DB70 0 +RESERVEDF7FF 0xF7FF RESERVED + + +.C505L +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=29187&parent_oid=29275 +; SAF-C505L-4EM.pdf + + +; up to 64 Kbytes of program memory (32K on-chip OTP memory) +; up to 64 Kbytes of external data memory +; 256 bytes of internal data memory +; 256 bytes of internal XRAM data memory +; 20 bytes of LCD Controller registers +; 16 bytes of Real-Time Clock (RTC) registers +; A 128-byte Special Function Register (SFR) area + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry SWI 0x004B Software Interrupt +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry IRTC 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.P14 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +; P1ANA 0x0090 Port 1 Analog Input Selection Register +; P1ANA.EAN7 7 +; P1ANA.EAN6 6 +; P1ANA.EAN5 5 +; P1ANA.EAN4 4 +; P1ANA.EAN3 3 +; P1ANA.EAN2 2 +; P1ANA.EAN1 1 +; P1ANA.EAN0 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM, LCD Controller and RTC +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register +SYSCON.EALE 5 +SYSCON.RMAP 4 SFR map bit +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.ESWI 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.SWI 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Reload Register Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Reload Register High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 Carry Flag +PSW.AC 6 Auxiliary Carry Flag +PSW.F0 5 General Purpose Flag +PSW.RS1 4 Register Bank select control bit 1 +PSW.RS0 3 Register Bank select control bit 0 +PSW.OV 2 Overflow Flag +PSW.F1 1 General Purpose Flag +PSW.P 0 Parity Flag +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register High Byte +ADDATH.ADDATH9 7 +ADDATH.ADDATH8 6 +ADDATH.ADDATH7 5 +ADDATH.ADDATH6 4 +ADDATH.ADDATH5 3 +ADDATH.ADDATH4 2 +ADDATH.ADDATH3 1 +ADDATH.ADDATH2 0 +ADDATL 0x00DA A/D Converter Data Register Low Byte +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +RESERVED00DB 0x00DB RESERVED +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.P47 7 +P4.P46 6 +P4.P45 5 +P4.P44 4 +P4.P43 3 +P4.P42 2 +P4.P41 1 +P4.P40 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +P5 0x00F8 Port 5 +P5.P55 5 +P5.P54 4 +P5.P53 3 +P5.P52 2 +P5.P51 1 +P5.P50 0 +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +VR2.VR27 7 +VR2.VR26 6 +VR2.VR25 5 +VR2.VR24 4 +VR2.VR23 3 +VR2.VR22 2 +VR2.VR21 1 +VR2.VR20 0 +RESERVED00FF 0x00FF RESERVED +DAC0 0xF3DC D/A Conversion Register +DAC0.S7 7 +DAC0.S6 6 +DAC0.S5 5 +DAC0.S4 4 +DAC0.S3 3 +DAC0.S2 2 +DAC0.S1 1 +DAC0.S0 0 +LCON 0xF3DD LCD Control Register +LCON.DSB1 7 +LCON.DSB0 6 +LCON.CSEL 1 +LCON.LCEN 0 +LCRL 0xF3DE LCD Timer Reload Low Register +LCRL.LCRL7 7 +LCRL.LCRL6 6 +LCRL.LCRL5 5 +LCRL.LCRL4 4 +LCRL.LCRL3 3 +LCRL.LCRL2 2 +LCRL.LCRL1 1 +LCRL.LCRL0 0 +LCRH 0xF3DF LCD Timer Reload High Register +LCRH.SLT 7 +LCRH.LCRH14 6 +LCRH.LCRH13 5 +LCRH.LCRH12 4 +LCRH.LCRH11 3 +LCRH.LCRH10 2 +LCRH.LCRH9 1 +LCRH.LCRH8 0 +DIG0 0xF3E0 LCD Digit Register 0 +DIG0.SEGF 7 +DIG0.SEGA 6 +DIG0.SEGG 5 +DIG0.SEGB 4 +DIG0.SEGE 3 +DIG0.SEGC 2 +DIG0.SEGH 1 +DIG0.SEGD 0 +DIG1 0xF3E1 LCD Digit Register 1 +DIG1.SEGF 7 +DIG1.SEGA 6 +DIG1.SEGG 5 +DIG1.SEGB 4 +DIG1.SEGE 3 +DIG1.SEGC 2 +DIG1.SEGH 1 +DIG1.SEGD 0 +DIG2 0xF3E2 LCD Digit Register 2 +DIG2.SEGF 7 +DIG2.SEGA 6 +DIG2.SEGG 5 +DIG2.SEGB 4 +DIG2.SEGE 3 +DIG2.SEGC 2 +DIG2.SEGH 1 +DIG2.SEGD 0 +DIG3 0xF3E3 LCD Digit Register 3 +DIG3.SEGF 7 +DIG3.SEGA 6 +DIG3.SEGG 5 +DIG3.SEGB 4 +DIG3.SEGE 3 +DIG3.SEGC 2 +DIG3.SEGH 1 +DIG3.SEGD 0 +DIG4 0xF3E4 LCD Digit Register 4 +DIG4.SEGF 7 +DIG4.SEGA 6 +DIG4.SEGG 5 +DIG4.SEGB 4 +DIG4.SEGE 3 +DIG4.SEGC 2 +DIG4.SEGH 1 +DIG4.SEGD 0 +DIG5 0xF3E5 LCD Digit Register 5 +DIG5.SEGF 7 +DIG5.SEGA 6 +DIG5.SEGG 5 +DIG5.SEGB 4 +DIG5.SEGE 3 +DIG5.SEGC 2 +DIG5.SEGH 1 +DIG5.SEGD 0 +DIG6 0xF3E6 LCD Digit Register 6 +DIG6.SEGF 7 +DIG6.SEGA 6 +DIG6.SEGG 5 +DIG6.SEGB 4 +DIG6.SEGE 3 +DIG6.SEGC 2 +DIG6.SEGH 1 +DIG6.SEGD 0 +DIG7 0xF3E7 LCD Digit Register 7 +DIG7.SEGF 7 +DIG7.SEGA 6 +DIG7.SEGG 5 +DIG7.SEGB 4 +DIG7.SEGE 3 +DIG7.SEGC 2 +DIG7.SEGH 1 +DIG7.SEGD 0 +DIG8 0xF3E8 LCD Digit Register 8 +DIG8.SEGF 7 +DIG8.SEGA 6 +DIG8.SEGG 5 +DIG8.SEGB 4 +DIG8.SEGE 3 +DIG8.SEGC 2 +DIG8.SEGH 1 +DIG8.SEGD 0 +DIG9 0xF3E9 LCD Digit Register 9 +DIG9.SEGF 7 +DIG9.SEGA 6 +DIG9.SEGG 5 +DIG9.SEGB 4 +DIG9.SEGE 3 +DIG9.SEGC 2 +DIG9.SEGH 1 +DIG9.SEGD 0 +DIGA 0xF3EA LCD Digit Register A +DIGA.SEGF 7 +DIGA.SEGA 6 +DIGA.SEGG 5 +DIGA.SEGB 4 +DIGA.SEGE 3 +DIGA.SEGC 2 +DIGA.SEGH 1 +DIGA.SEGD 0 +DIGB 0xF3EB LCD Digit Register B +DIGB.SEGF 7 +DIGB.SEGA 6 +DIGB.SEGG 5 +DIGB.SEGB 4 +DIGB.SEGE 3 +DIGB.SEGC 2 +DIGB.SEGH 1 +DIGB.SEGD 0 +DIGC 0xF3EC LCD Digit Register C +DIGC.SEGF 7 +DIGC.SEGA 6 +DIGC.SEGG 5 +DIGC.SEGB 4 +DIGC.SEGE 3 +DIGC.SEGC 2 +DIGC.SEGH 1 +DIGC.SEGD 0 +DIGD 0xF3ED LCD Digit Register D +DIGD.SEGF 7 +DIGD.SEGA 6 +DIGD.SEGG 5 +DIGD.SEGB 4 +DIGD.SEGE 3 +DIGD.SEGC 2 +DIGD.SEGH 1 +DIGD.SEGD 0 +DIGE 0xF3EE LCD Digit Register E +DIGE.SEGF 7 +DIGE.SEGA 6 +DIGE.SEGG 5 +DIGE.SEGB 4 +DIGE.SEGE 3 +DIGE.SEGC 2 +DIGE.SEGH 1 +DIGE.SEGD 0 +DIGF 0xF3EF LCD Digit Register F +DIGF.SEGF 7 +DIGF.SEGA 6 +DIGF.SEGG 5 +DIGF.SEGB 4 +DIGF.SEGE 3 +DIGF.SEGC 2 +DIGF.SEGH 1 +DIGF.SEGD 0 +RTCON 0xF3F0 Real-Time Clock Control Register +RTCON.RTPD 3 +RTCON.IRTC 2 +RTCON.ERTC 1 +RTCON.RTCS 0 +RTCR0 0xF3F1 Real-Time Clock Initialization Register 0 +RTCR0.RTCR07 7 +RTCR0.RTCR06 6 +RTCR0.RTCR05 5 +RTCR0.RTCR04 4 +RTCR0.RTCR03 3 +RTCR0.RTCR02 2 +RTCR0.RTCR01 1 +RTCR0.RTCR00 0 +RTCR1 0xF3F2 Real-Time Clock Initialization Register 1 +RTCR1.RTCR17 7 +RTCR1.RTCR16 6 +RTCR1.RTCR15 5 +RTCR1.RTCR14 4 +RTCR1.RTCR13 3 +RTCR1.RTCR12 2 +RTCR1.RTCR11 1 +RTCR1.RTCR10 0 +RTCR2 0xF3F3 Real-Time Clock Initialization Register 2 +RTCR2.RTCR27 7 +RTCR2.RTCR26 6 +RTCR2.RTCR25 5 +RTCR2.RTCR24 4 +RTCR2.RTCR23 3 +RTCR2.RTCR22 2 +RTCR2.RTCR21 1 +RTCR2.RTCR20 0 +RTCR3 0xF3F4 Real-Time Clock Initialization Register 3 +RTCR3.RTCR37 7 +RTCR3.RTCR36 6 +RTCR3.RTCR35 5 +RTCR3.RTCR34 4 +RTCR3.RTCR33 3 +RTCR3.RTCR32 2 +RTCR3.RTCR31 1 +RTCR3.RTCR30 0 +RTCR4 0xF3F5 Real-Time Clock Initialization Register 4 +RTCR4.RTCR47 7 +RTCR4.RTCR46 6 +RTCR4.RTCR45 5 +RTCR4.RTCR44 4 +RTCR4.RTCR43 3 +RTCR4.RTCR42 2 +RTCR4.RTCR41 1 +RTCR4.RTCR40 0 +CLREG0 0xF3F6 Clock Count Register 0 +CLREG0.CLREG07 7 +CLREG0.CLREG06 6 +CLREG0.CLREG05 5 +CLREG0.CLREG04 4 +CLREG0.CLREG03 3 +CLREG0.CLREG02 2 +CLREG0.CLREG01 1 +CLREG0.CLREG00 0 +CLREG1 0xF3F7 Clock Count Register 1 +CLREG1.CLREG17 7 +CLREG1.CLREG16 6 +CLREG1.CLREG15 5 +CLREG1.CLREG14 4 +CLREG1.CLREG13 3 +CLREG1.CLREG12 2 +CLREG1.CLREG11 1 +CLREG1.CLREG10 0 +CLREG2 0xF3F8 Clock Count Register 2 +CLREG2.CLREG27 7 +CLREG2.CLREG26 6 +CLREG2.CLREG25 5 +CLREG2.CLREG24 4 +CLREG2.CLREG23 3 +CLREG2.CLREG22 2 +CLREG2.CLREG21 1 +CLREG2.CLREG20 0 +CLREG3 0xF3F9 Clock Count Register 3 +CLREG3.CLREG37 7 +CLREG3.CLREG36 6 +CLREG3.CLREG35 5 +CLREG3.CLREG34 4 +CLREG3.CLREG33 3 +CLREG3.CLREG32 2 +CLREG3.CLREG31 1 +CLREG3.CLREG30 0 +CLREG4 0xF3FA Clock Count Register 4 +CLREG4.CLREG47 7 +CLREG4.CLREG46 6 +CLREG4.CLREG45 5 +CLREG4.CLREG44 4 +CLREG4.CLREG43 3 +CLREG4.CLREG42 2 +CLREG4.CLREG41 1 +CLREG4.CLREG40 0 +RTINT0 0xF3FB Real-Time Clock Interrupt Register 0 +RTINT0.RTINT07 7 +RTINT0.RTINT06 6 +RTINT0.RTINT05 5 +RTINT0.RTINT04 4 +RTINT0.RTINT03 3 +RTINT0.RTINT02 2 +RTINT0.RTINT01 1 +RTINT0.RTINT00 0 +RTINT1 0xF3FC Real-Time Clock Interrupt Register 1 +RTINT1.RTINT17 7 +RTINT1.RTINT16 6 +RTINT1.RTINT15 5 +RTINT1.RTINT14 4 +RTINT1.RTINT13 3 +RTINT1.RTINT12 2 +RTINT1.RTINT11 1 +RTINT1.RTINT10 0 +RTINT2 0xF3FD Real-Time Clock Interrupt Register 2 +RTINT2.RTINT27 7 +RTINT2.RTINT26 6 +RTINT2.RTINT25 5 +RTINT2.RTINT24 4 +RTINT2.RTINT23 3 +RTINT2.RTINT22 2 +RTINT2.RTINT21 1 +RTINT2.RTINT20 0 +RTINT3 0xF3FE Real-Time Clock Interrupt Register 3 +RTINT3.RTINT37 7 +RTINT3.RTINT36 6 +RTINT3.RTINT35 5 +RTINT3.RTINT34 4 +RTINT3.RTINT33 3 +RTINT3.RTINT32 2 +RTINT3.RTINT31 1 +RTINT3.RTINT30 0 +RTINT4 0xF3FF Real-Time Clock Interrupt Register 4 +RTINT4.RTINT47 7 +RTINT4.RTINT46 6 +RTINT4.RTINT45 5 +RTINT4.RTINT44 4 +RTINT4.RTINT43 3 +RTINT4.RTINT42 2 +RTINT4.RTINT41 1 +RTINT4.RTINT40 0 + + +.C508 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=19575&parent_oid=12110 +; SAF-C508-4EM.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xFC00 +area DATA RAM2 0xFC00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External Interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External Interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2 0x002B Timer 2 Overflow +entry IADC 0x0043 A/D Converter +entry IEX2 0x004B External Interrupt 2 +entry IEX3 0x0053 External Interrupt 3 +entry IEX4 0x005B External Interrupt 4 +entry IEX5 0x0063 External Interrupt 5 +entry IEX6 0x006B External Interrupt 6 +entry TRF_BCERR 0x0093 CAPCOM Emergency Interrupt +entry CT2P 0x009B Compare Timer 2 Interrupt +entry CCxF_CCxF 0x00A3 Capture/Compare Match Interrupt +entry CT1FP_CT1FC 0x00AB Compare Timer 1 Interrupt +entry IEX7 0x00D3 External Interrupt 7 +entry IEX8 0x00DB External Interrupt 8 +entry IEX9 0x00E3 External Interrupt 9 +entry WAKE_UP 0x00EB Wake-up from power-down + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +WDTL 0x0084 Watchdog Timer Register, low byte +WDTL.WDTL7 7 +WDTL.WDTL6 6 +WDTL.WDTL5 5 +WDTL.WDTL4 4 +WDTL.WDTL3 3 +WDTL.WDTL2 2 +WDTL.WDTL1 1 +WDTL.WDTL0 0 +WDTH 0x0085 Watchdog Timer Register, high byte +WDTH.WDTH7 7 +WDTH.WDTH6 6 +WDTH.WDTH5 5 +WDTH.WDTH4 4 +WDTH.WDTH3 3 +WDTH.WDTH2 2 +WDTH.WDTH1 1 +WDTH.WDTH0 0 +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.P17 7 +P1.P16 6 +P1.P15 5 +P1.P14 4 +P1.P13 3 +P1.P12 2 +P1.P11 1 +P1.P10 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +IEN2 0x009A Interrupt Enable Register 2 +IEN2.ECT1 5 +IEN2.ECCM 4 +IEN2.ECT2 3 +IEN2.ECEM 2 +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EA 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.EX2 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +IEN3 0x00BE Interrupt Enable Register 3 +IEN3.EX9 4 +IEN3.EX8 3 +IEN3.EX7 2 +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.IEX2 1 +IRCON.IADC 0 +CCEN 0x00C1 Compare/Capture Enable Register +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +T2CCL1 0x00C2 Compare/Capture Register 1, Low Byte +T2CCL1.T2CCL17 7 +T2CCL1.T2CCL16 6 +T2CCL1.T2CCL15 5 +T2CCL1.T2CCL14 4 +T2CCL1.T2CCL13 3 +T2CCL1.T2CCL12 2 +T2CCL1.T2CCL11 1 +T2CCL1.T2CCL10 0 +T2CCH1 0x00C3 Compare/Capture Register 1, High Byte +T2CCH1.T2CCH17 7 +T2CCH1.T2CCH16 6 +T2CCH1.T2CCH15 5 +T2CCH1.T2CCH14 4 +T2CCH1.T2CCH13 3 +T2CCH1.T2CCH12 2 +T2CCH1.T2CCH11 1 +T2CCH1.T2CCH10 0 +T2CCL2 0x00C4 Compare/Capture Register 2, Low Byte +T2CCL2.T2CCL27 7 +T2CCL2.T2CCL26 6 +T2CCL2.T2CCL25 5 +T2CCL2.T2CCL24 4 +T2CCL2.T2CCL23 3 +T2CCL2.T2CCL22 2 +T2CCL2.T2CCL21 1 +T2CCL2.T2CCL20 0 +T2CCH2 0x00C5 Compare/Capture Register 2, High Byte +T2CCH2.T2CCH27 7 +T2CCH2.T2CCH26 6 +T2CCH2.T2CCH25 5 +T2CCH2.T2CCH24 4 +T2CCH2.T2CCH23 3 +T2CCH2.T2CCH22 2 +T2CCH2.T2CCH21 1 +T2CCH2.T2CCH20 0 +T2CCL3 0x00C6 Compare/Capture Register 3, Low Byte +T2CCL3.T2CCL37 7 +T2CCL3.T2CCL36 6 +T2CCL3.T2CCL35 5 +T2CCL3.T2CCL34 4 +T2CCL3.T2CCL33 3 +T2CCL3.T2CCL32 2 +T2CCL3.T2CCL31 1 +T2CCL3.T2CCL30 0 +T2CCH3 0x00C7 Compare/Capture Register 3, High Byte +T2CCH3.T2CCH37 7 +T2CCH3.T2CCH36 6 +T2CCH3.T2CCH35 5 +T2CCH3.T2CCH34 4 +T2CCH3.T2CCH33 3 +T2CCH3.T2CCH32 2 +T2CCH3.T2CCH31 1 +T2CCH3.T2CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.I2FR 5 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Comp./Rel./Capt. Register, Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Comp./Rel./Capt. Register, High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 Carry Flag +PSW.AC 6 Auxiliary Carry Flag +PSW.F0 5 General Purpose Flag 0 +PSW.RS1 4 Register Bank select control bit 1 +PSW.RS0 3 Register Bank select control bit 0 +PSW.OV 2 Overflow Flag +PSW.F1 1 General Purpose Flag 1 +PSW.P 0 Parity Flag +RESERVED00D1 0x00D1 RESERVED +CP2L 0x00D2 Compare timer 2 period register, low byte +CP2L.CP2L7 7 +CP2L.CP2L6 6 +CP2L.CP2L5 5 +CP2L.CP2L4 4 +CP2L.CP2L3 3 +CP2L.CP2L2 2 +CP2L.CP2L1 1 +CP2L.CP2L0 0 +CP2H 0x00D3 Compare timer 2 period register, high byte +CP2H.CP2H1 1 +CP2H.CP2H0 0 +CMP2L 0x00D4 Compare timer 2 compare register, low byte +CMP2L.CMP2L7 7 +CMP2L.CMP2L6 6 +CMP2L.CMP2L5 5 +CMP2L.CMP2L4 4 +CMP2L.CMP2L3 3 +CMP2L.CMP2L2 2 +CMP2L.CMP2L1 1 +CMP2L.CMP2L0 0 +CMP2H 0x00D5 Compare timer 2 compare register, high byte +CMP2H.CMP2H1 1 +CMP2H.CMP2H0 0 +CCIE 0x00D6 Capture/compare interrupt enable register +CCIE.ECTP 7 +CCIE.ECTC 6 +CCIE.CC2FEN 5 +CCIE.CC2REN 4 +CCIE.CC1FEN 3 +CCIE.CC1REN 2 +CCIE.CC0FEN 1 +CCIE.CC0REN 0 +BCON 0x00D7 Block commutation control register +BCON.BCMPBCEM 7 +BCON.PWM1 6 +BCON.PWM0 5 +BCON.EBCE 4 +BCON.BCERR 3 +BCON.BCEN 2 +BCON.BCM1 1 +BCON.BCM0 0 +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.BD 6 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register High Byte +ADDATH.ADDATH9 7 +ADDATH.ADDATH8 6 +ADDATH.ADDATH7 5 +ADDATH.ADDATH6 4 +ADDATH.ADDATH5 3 +ADDATH.ADDATH4 2 +ADDATH.ADDATH3 1 +ADDATH.ADDATH2 0 +ADDATL 0x00DA A/D Converter Start Register Low Byte +ADDATL.1 7 +ADDATL.0 6 +P4 0x00DB Port 4, Analog/Digital Input +P4.P47 7 +P4.P46 6 +P4.P45 5 +P4.P44 4 +P4.P43 3 +P4.P42 2 +P4.P41 1 +P4.P40 0 +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +CCPL 0x00DE Compare timer 1 period register, low byte +CCPL.CCPL7 7 +CCPL.CCPL6 6 +CCPL.CCPL5 5 +CCPL.CCPL4 4 +CCPL.CCPL3 3 +CCPL.CCPL2 2 +CCPL.CCPL1 1 +CCPL.CCPL0 0 +CCPH 0x00DF Compare timer 1 period register, high byte +CCPH.CCPH7 7 +CCPH.CCPH6 6 +CCPH.CCPH5 5 +CCPH.CCPH4 4 +CCPH.CCPH3 3 +CCPH.CCPH2 2 +CCPH.CCPH1 1 +CCPH.CCPH0 0 +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +CT1CON 0x00E1 Compare timer 1 control register +CT1CON.CTM 7 +CT1CON.ETRP 6 +CT1CON.STE1 5 +CT1CON.CT1RES 4 +CT1CON.CT1R 3 +CT1CON.CLK2 2 +CT1CON.CLK1 1 +CT1CON.CLK0 0 +COINI 0x00E2 Compare output initialization register +COINI.COUT3I 7 +COINI.COUTXI 6 +COINI.COUT2I 5 +COINI.CC2I 4 +COINI.COUT1I 3 +COINI.CC1I 2 +COINI.COUT0I 1 +COINI.CC0I 0 +CMSEL0 0x00E3 Capture/compare mode select register 0 +CMSEL0.CMSEL13 7 +CMSEL0.CMSEL12 6 +CMSEL0.CMSEL11 5 +CMSEL0.CMSEL10 4 +CMSEL0.CMSEL03 3 +CMSEL0.CMSEL02 2 +CMSEL0.CMSEL01 1 +CMSEL0.CMSEL00 0 +CMSEL1 0x00E4 Capture/compare mode select register 1 +CMSEL1.ESMC 7 +CMSEL1.NMCS 6 +CMSEL1.CMSEL23 3 +CMSEL1.CMSEL22 2 +CMSEL1.CMSEL21 1 +CMSEL1.CMSEL20 0 +CCIR 0x00E5 Capture/compare interrupt request flag reg. +CCIR.CT1FP 7 +CCIR.CT1FC 6 +CCIR.CC2F 5 +CCIR.CC2R 4 +CCIR.CC1F 3 +CCIR.CC1R 2 +CCIR.CC0F 1 +CCIR.CC0R 0 +CT1OFL 0x00E6 Compare timer 1 offset register, low byte +CT1OFL.CT1OFL7 7 +CT1OFL.CT1OFL6 6 +CT1OFL.CT1OFL5 5 +CT1OFL.CT1OFL4 4 +CT1OFL.CT1OFL3 3 +CT1OFL.CT1OFL2 2 +CT1OFL.CT1OFL1 1 +CT1OFL.CT1OFL0 0 +CT1OFH 0x00E7 Compare timer 1 offset register, high byte +CT1OFH.CT1OFH7 7 +CT1OFH.CT1OFH6 6 +CT1OFH.CT1OFH5 5 +CT1OFH.CT1OFH4 4 +CT1OFH.CT1OFH3 3 +CT1OFH.CT1OFH2 2 +CT1OFH.CT1OFH1 1 +CT1OFH.CT1OFH0 0 +RESERVED00E8 0x00E8 RESERVED +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +CT2CON 0x00F1 Compare timer 2 control register +CT2CON.CT2P 7 +CT2CON.ECT2O 6 +CT2CON.STE2 5 +CT2CON.CT2RES 4 +CT2CON.CT2R 3 +CT2CON.CLK2 2 +CT2CON.CLK1 1 +CT2CON.CLK0 0 +CCL0 0x00F2 Capture/compare register 0, low byte +CCL0.CCL07 7 +CCL0.CCL06 6 +CCL0.CCL05 5 +CCL0.CCL04 4 +CCL0.CCL03 3 +CCL0.CCL02 2 +CCL0.CCL01 1 +CCL0.CCL00 0 +CCH0 0x00F3 Capture/compare register 0, high byte +CCH0.CCH07 7 +CCH0.CCH06 6 +CCH0.CCH05 5 +CCH0.CCH04 4 +CCH0.CCH03 3 +CCH0.CCH02 2 +CCH0.CCH01 1 +CCH0.CCH00 0 +CCL1 0x00F4 Capture/compare register 1, low byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00F5 Capture/compare register 1, high byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00F6 Capture/compare register 2, low byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00F7 Capture/compare register 2, high byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +P5 0x00F8 Port 5 +P5.P57 7 +P5.P56 6 +P5.P55 5 +P5.P54 4 +P5.P53 3 +P5.P52 2 +P5.P51 1 +P5.P50 0 +COTRAP 0x00F9 Compare output in trap state register +COTRAP.BCTSEL 7 +COTRAP.PDTEN 6 +COTRAP.COUT2T 5 +COTRAP.CC2T 4 +COTRAP.COUT1T 3 +COTRAP.CC1T 2 +COTRAP.COUT0T 1 +COTRAP.CC0T 0 +RESERVED00EF 0x00FA RESERVED +EINT 0x00FB External Interrupt Control Register +EINT.IEX9 5 +EINT.I9FR 4 +EINT.IEX8 3 +EINT.I8FR 2 +EINT.IEX7 1 +EINT.I7FR 0 +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +TRCON 0x00FF Trap enable control register +TRCON.TRPEN 7 +TRCON.TRF 6 +TRCON.TREN5 5 +TRCON.TREN4 4 +TRCON.TREN3 3 +TRCON.TREN2 2 +TRCON.TREN1 1 +TRCON.TREN0 0 + + +.C509 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8022&parent_oid=8090 +; C509-L.pdf + + +; up to 64 Kbyte of external program memory +; up to 64 Kbyte of external data memory +; 512 byte of internal Boot ROM (program memory) +; 256 bytes of internal data memory +; 3 Kbyte of external XRAM data memory +; a 128 byte special function register area + + +; MEMORY MAP +area CODE code 0x0000:0xF400 +area DATA XRAM 0xF400:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External Interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External Interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI0_TI0 0x0023 Serial Channel 0 +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry IEX2 0x004B External Interrupt 2 +entry IEX3 0x0053 External Interrupt 3 +entry IEX4 0x005B External Interrupt 4 +entry IEX5 0x0063 External Interrupt 5 +entry IEX6 0x006B External Interrupt 6 +entry RI1_TI1 0x0083 Serial Channel 1 +entry ICMP0_ICMP7 0x0093 Compare Match Interupt of Compare Registers assigned to Timer 2 CM0-CM7 +entry CTF 0x009B Compare Timer Overflow +entry ICS 0x00A3 Compare Match Interupt of Compare Register COMSET +entry ICR 0x00AB Compare Match Interupt of Compare Register COMCLR +entry ICC10_ICC17 0x00D3 Compare / Capture Event interrupt +entry CT1F 0x00DB Compare Timer 1 Overflow + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 (PDIR=0) +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +; DIR0 0x0080 Direction Register Port 0 (PDIR=1) +; DIR0.DIR07 7 +; DIR0.DIR06 6 +; DIR0.DIR05 5 +; DIR0.DIR04 4 +; DIR0.DIR03 3 +; DIR0.DIR02 2 +; DIR0.DIR01 1 +; DIR0.DIR00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +WDTL 0x0084 Watchdog Timer Register, Low Byte +WDTL.WDTL7 7 +WDTL.WDTL6 6 +WDTL.WDTL5 5 +WDTL.WDTL4 4 +WDTL.WDTL3 3 +WDTL.WDTL2 2 +WDTL.WDTL1 1 +WDTL.WDTL0 0 +WDTH 0x0085 Watchdog Timer Register, High Byte +WDTH.WDTH7 7 +WDTH.WDTH6 6 +WDTH.WDTH5 5 +WDTH.WDTH4 4 +WDTH.WDTH3 3 +WDTH.WDTH2 2 +WDTH.WDTH1 1 +WDTH.WDTH0 0 +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 (PDIR=0) +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.INT2 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +; DIR1 0x0090 Direction Register Port 1 (PDIR=1) +; DIR1.DIR17 7 +; DIR1.DIR16 6 +; DIR1.DIR15 5 +; DIR1.DIR14 4 +; DIR1.DIR13 3 +; DIR1.DIR12 2 +; DIR1.DIR11 1 +; DIR1.DIR10 0 +XPAGE 0x0091 Page Address Register for XRAM +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +S0CON 0x0098 Serial Channel 0 Control Register +S0CON.SM0 7 +S0CON.SM1 6 +S0CON.SM20 5 +S0CON.REN0 4 +S0CON.TB80 3 +S0CON.RB80 2 +S0CON.TI0 1 +S0CON.RI0 0 +S0BUF 0x0099 Serial Channel 0 Buffer Register +S0BUF.S0BUF7 7 +S0BUF.S0BUF6 6 +S0BUF.S0BUF5 5 +S0BUF.S0BUF4 4 +S0BUF.S0BUF3 3 +S0BUF.S0BUF2 2 +S0BUF.S0BUF1 1 +S0BUF.S0BUF0 0 +IEN2 0x009A Interrupt Enable Register 2 +IEN2.ECR 5 +IEN2.ECS 4 +IEN2.ECT 3 +IEN2.ECMP 2 +IEN2.ES1 0 +S1CON 0x009B Serial Channel 1 Control Register +S1CON.SM 7 +S1CON.S1P 6 +S1CON.SM21 5 +S1CON.REN1 4 +S1CON.TB81 3 +S1CON.RB81 2 +S1CON.TI1 1 +S1CON.RI1 0 +S1BUF 0x009C Serial Channel 1 Buffer Register +S1BUF.S1BUF7 7 +S1BUF.S1BUF6 6 +S1BUF.S1BUF5 5 +S1BUF.S1BUF4 4 +S1BUF.S1BUF3 3 +S1BUF.S1BUF2 2 +S1BUF.S1BUF1 1 +S1BUF.S1BUF0 0 +S1RELL 0x009D Serial Channel 1 Reload Reg., Low Byte +S1RELL.S1RELL7 7 +S1RELL.S1RELL6 6 +S1RELL.S1RELL5 5 +S1RELL.S1RELL4 4 +S1RELL.S1RELL3 3 +S1RELL.S1RELL2 2 +S1RELL.S1RELL1 1 +S1RELL.S1RELL0 0 +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 (PDIR=0) +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +; DIR2 0x00A0 Direction Register Port 2 (PDIR=1) +; DIR2.DIR27 7 +; DIR2.DIR26 6 +; DIR2.DIR25 5 +; DIR2.DIR24 4 +; DIR2.DIR23 3 +; DIR2.DIR22 2 +; DIR2.DIR21 1 +; DIR2.DIR20 0 +COMSETL 0x00A1 Compare Set Register, Low Byte +COMSETL.COMSETL7 7 +COMSETL.COMSETL6 6 +COMSETL.COMSETL5 5 +COMSETL.COMSETL4 4 +COMSETL.COMSETL3 3 +COMSETL.COMSETL2 2 +COMSETL.COMSETL1 1 +COMSETL.COMSETL0 0 +COMSETH 0x00A2 Compare Set Register, High Byte +COMSETH.COMSETH7 7 +COMSETH.COMSETH6 6 +COMSETH.COMSETH5 5 +COMSETH.COMSETH4 4 +COMSETH.COMSETH3 3 +COMSETH.COMSETH2 2 +COMSETH.COMSETH1 1 +COMSETH.COMSETH0 0 +COMCLRL 0x00A3 Compare Clear Register, Low Byte +COMCLRL.COMCLRL7 7 +COMCLRL.COMCLRL6 6 +COMCLRL.COMCLRL5 5 +COMCLRL.COMCLRL4 4 +COMCLRL.COMCLRL3 3 +COMCLRL.COMCLRL2 2 +COMCLRL.COMCLRL1 1 +COMCLRL.COMCLRL0 0 +COMCLRH 0x00A4 Compare Clear Register, High Byte +COMCLRH.COMCLRH7 7 +COMCLRH.COMCLRH6 6 +COMCLRH.COMCLRH5 5 +COMCLRH.COMCLRH4 4 +COMCLRH.COMCLRH3 3 +COMCLRH.COMCLRH2 2 +COMCLRH.COMCLRH1 1 +COMCLRH.COMCLRH0 0 +SETMSK 0x00A5 Compare Set Mask Register +SETMSK.SETMSK7 7 +SETMSK.SETMSK6 6 +SETMSK.SETMSK5 5 +SETMSK.SETMSK4 4 +SETMSK.SETMSK3 3 +SETMSK.SETMSK2 2 +SETMSK.SETMSK1 1 +SETMSK.SETMSK0 0 +CLRMSK 0x00A6 Compare Clear Mask Register +CLRMSK.CLRMSK7 7 +CLRMSK.CLRMSK6 6 +CLRMSK.CLRMSK5 5 +CLRMSK.CLRMSK4 4 +CLRMSK.CLRMSK3 3 +CLRMSK.CLRMSK2 2 +CLRMSK.CLRMSK1 1 +CLRMSK.CLRMSK0 0 +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EAL 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES0 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +S0RELL 0x00AA Serial Channel 0 Reload Reg., Low Byte +S0RELL.S0RELL7 7 +S0RELL.S0RELL6 6 +S0RELL.S0RELL5 5 +S0RELL.S0RELL4 4 +S0RELL.S0RELL3 3 +S0RELL.S0RELL2 2 +S0RELL.S0RELL1 1 +S0RELL.S0RELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 (PDIR=0) +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T1 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD0 1 +P3.RxD0 0 +; DIR3 0x00B0 Direction Register Port 3 (PDIR=1) +; DIR3.DIR37 7 +; DIR3.DIR36 6 +; DIR3.DIR35 5 +; DIR3.DIR34 4 +; DIR3.DIR33 3 +; DIR3.DIR32 2 +; DIR3.DIR31 1 +; DIR3.DIR30 0 +SYSCON 0x00B1 System Control Register +SYSCON.CLKP 7 +SYSCON.PMOD 6 +SYSCON.RMAP 4 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +SYSCON1 0x00B2 System Control Register 1 +SYSCON1.ESWC 7 +SYSCON1.SWC 6 +SYSCON1.EA1 4 +SYSCON1.EA0 3 +SYSCON1.PRGEN1 2 +SYSCON1.PRGEN0 1 +SYSCON1.SWAP 0 +RESERVED00B3 0x00B3 RESERVED +PRSC 0x00B4 Prescaler Control Register +PRSC.WDTP 7 +PRSC.S0P 6 +PRSC.T2P1 5 +PRSC.T2P0 4 +PRSC.T1P1 3 +PRSC.T1P0 2 +PRSC.T0P1 1 +PRSC.T0P0 0 +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.EX2 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.PDIR 7 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +S0RELH 0x00BA Serial Channel 0 Reload Reg., High Byte +S0RELH.S0RELH1 1 +S0RELH.S0RELH0 0 +S1RELH 0x00BB Serial Channel 1 Reload Reg., High Byte +S1RELH.S1RELH1 1 +S1RELH.S1RELH0 0 +CT1CON 0x00BC Compare Timer 1 Control Register +CT1CON.CT1P 6 +CT1CON.CT1F 3 +CT1CON.CLK12 2 +CT1CON.CLK11 1 +CT1CON.CLK10 0 +RESERVED00BD 0x00BD RESERVED +IEN3 0x00BE Interrupt Enable Register 3 +IEN3.ECT1 3 +IEN3.ECC1 2 +IRCON2 0x00BF Interrupt Request Control Register 2 (PDIR=0) +IRCON2.ICC17 7 +IRCON2.ICC16 6 +IRCON2.ICC15 5 +IRCON2.ICC14 4 +IRCON2.ICC13 3 +IRCON2.ICC12 2 +IRCON2.ICC11 1 +IRCON2.ICC10 0 +; EICC1 0x00BF Interrupt Request Enable Register for CT1 (PDIR=1) +; EICC1.EICC17 7 +; EICC1.EICC16 6 +; EICC1.EICC15 5 +; EICC1.EICC14 4 +; EICC1.EICC13 3 +; EICC1.EICC12 2 +; EICC1.EICC11 1 +; EICC1.EICC10 0 +IRCON0 0x00C0 Interrupt Request Control Register 0 +IRCON0.EXF2 7 +IRCON0.TF2 6 +IRCON0.IEX6 5 +IRCON0.IEX5 4 +IRCON0.IEX4 3 +IRCON0.IEX3 2 +IRCON0.IEX2 1 +IRCON0.IADC 0 +CCEN 0x00C1 Compare/Capture Enable Register +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Compare/Capture Register 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Compare/Capture Register 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Compare/Capture Register 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Compare/Capture Register 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Compare/Capture Register 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Compare/Capture Register 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.I2FR 5 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +CC4EN 0x00C9 Compare/Capture 4 Enable Register +CC4EN.COCOEN1 7 +CC4EN.COCON2 6 +CC4EN.COCON1 5 +CC4EN.COCON0 4 +CC4EN.COCOEN0 3 +CC4EN.COCAH4 2 +CC4EN.COCAL4 1 +CC4EN.COM0 0 +CRCL 0x00CA Comp./Rel./Capt. Reg. Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Comp./Rel./Capt. Reg. High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +CCL4 0x00CE Compare/Capture Register 4, Low Byte +CCL4.CCL47 7 +CCL4.CCL46 6 +CCL4.CCL45 5 +CCL4.CCL44 4 +CCL4.CCL43 3 +CCL4.CCL42 2 +CCL4.CCL41 1 +CCL4.CCL40 0 +CCH4 0x00CF Compare/Capture Register 4, High Byte +CCH4.CCH47 7 +CCH4.CCH46 6 +CCH4.CCH45 5 +CCH4.CCH44 4 +CCH4.CCH43 3 +CCH4.CCH42 2 +CCH4.CCH41 1 +CCH4.CCH40 0 +PSW 0x00D0 Program Status Word +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +IRCON1 0x00D1 Interrupt Request Control Register 1 +IRCON1.ICMP7 7 +IRCON1.ICMP6 6 +IRCON1.ICMP5 5 +IRCON1.ICMP4 4 +IRCON1.ICMP3 3 +IRCON1.ICMP2 2 +IRCON1.ICMP1 1 +IRCON1.ICMP0 0 +CML0 0x00D2 Compare Register 0, Low Byte (RMAP=0) +CML0.CML07 7 +CML0.CML06 6 +CML0.CML05 5 +CML0.CML04 4 +CML0.CML03 3 +CML0.CML02 2 +CML0.CML01 1 +CML0.CML00 0 +; CC1L0 0x00D2 Compare/Capture 1 Register 0, Low Byte (RMAP=1) +; CC1L0.CC1L07 7 +; CC1L0.CC1L06 6 +; CC1L0.CC1L05 5 +; CC1L0.CC1L04 4 +; CC1L0.CC1L03 3 +; CC1L0.CC1L02 2 +; CC1L0.CC1L01 1 +; CC1L0.CC1L00 0 +CMH0 0x00D3 Compare Register 0, High Byte (RMAP=0) +CMH0.CMH07 7 +CMH0.CMH06 6 +CMH0.CMH05 5 +CMH0.CMH04 4 +CMH0.CMH03 3 +CMH0.CMH02 2 +CMH0.CMH01 1 +CMH0.CMH00 0 +; CC1H0 0x00D3 Compare/Capture 1 Register 0, High Byte (RMAP=1) +; CC1H0.CC1H07 7 +; CC1H0.CC1H06 6 +; CC1H0.CC1H05 5 +; CC1H0.CC1H04 4 +; CC1H0.CC1H03 3 +; CC1H0.CC1H02 2 +; CC1H0.CC1H01 1 +; CC1H0.CC1H00 0 +CML1 0x00D4 Compare Register 1, Low Byte (RMAP=0) +CML1.CML17 7 +CML1.CML16 6 +CML1.CML15 5 +CML1.CML14 4 +CML1.CML13 3 +CML1.CML12 2 +CML1.CML11 1 +CML1.CML10 0 +; CC1L1 0x00D4 Compare/Capture 1 Register 1, Low Byte (RMAP=1) +; CC1L1.CC1L17 7 +; CC1L1.CC1L16 6 +; CC1L1.CC1L15 5 +; CC1L1.CC1L14 4 +; CC1L1.CC1L13 3 +; CC1L1.CC1L12 2 +; CC1L1.CC1L11 1 +; CC1L1.CC1L10 0 +CMH1 0x00D5 Compare Register 1, High Byte (RMAP=0) +CMH1.CMH17 7 +CMH1.CMH16 6 +CMH1.CMH15 5 +CMH1.CMH14 4 +CMH1.CMH13 3 +CMH1.CMH12 2 +CMH1.CMH11 1 +CMH1.CMH10 0 +; CC1H1 0x00D5 Compare/Capture 1 Register 1, High Byte (RMAP=1) +; CC1H1.CC1H17 7 +; CC1H1.CC1H16 6 +; CC1H1.CC1H15 5 +; CC1H1.CC1H14 4 +; CC1H1.CC1H13 3 +; CC1H1.CC1H12 2 +; CC1H1.CC1H11 1 +; CC1H1.CC1H10 0 +CML2 0x00D6 Compare Register 2, Low Byte (RMAP=0) +CML2.CML27 7 +CML2.CML26 6 +CML2.CML25 5 +CML2.CML24 4 +CML2.CML23 3 +CML2.CML22 2 +CML2.CML21 1 +CML2.CML20 0 +; CC1L2 0x00D6 Compare/Capture 1 Register 2, Low Byte (RMAP=1) +; CC1L2.CC1L27 7 +; CC1L2.CC1L26 6 +; CC1L2.CC1L25 5 +; CC1L2.CC1L24 4 +; CC1L2.CC1L23 3 +; CC1L2.CC1L22 2 +; CC1L2.CC1L21 1 +; CC1L2.CC1L20 0 +CMH2 0x00D7 Compare Register 2, High Byte (RMAP=0) +CMH2.CMH27 7 +CMH2.CMH26 6 +CMH2.CMH25 5 +CMH2.CMH24 4 +CMH2.CMH23 3 +CMH2.CMH22 2 +CMH2.CMH21 1 +CMH2.CMH20 0 +; CC1H2 0x00D7 Compare/Capture 1 Register 2, High Byte (RMAP=1) +; CC1H2.CC1H27 7 +; CC1H2.CC1H26 6 +; CC1H2.CC1H25 5 +; CC1H2.CC1H24 4 +; CC1H2.CC1H23 3 +; CC1H2.CC1H22 2 +; CC1H2.CC1H21 1 +; CC1H2.CC1H20 0 +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.ADEX 5 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register, High Byte +ADDATH.ADDATH7 7 +ADDATH.ADDATH6 6 +ADDATH.ADDATH5 5 +ADDATH.ADDATH4 4 +ADDATH.ADDATH3 3 +ADDATH.ADDATH2 2 +ADDATH.ADDATH1 1 +ADDATH.ADDATH0 0 +ADDATL 0x00DA A/D Converter Data Register, Low Byte +ADDATL.ADDATL7 7 +ADDATL.ADDATL6 6 +P7 0x00DB Port 7, Analog/Digital Input +P7.P77 7 +P7.P76 6 +P7.P75 5 +P7.P74 4 +P7.P73 3 +P7.P72 2 +P7.P71 1 +P7.P70 0 +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL1 7 +ADCON1.ADCL0 6 +ADCON1.ADST1 5 +ADCON1.ADST0 4 +ADCON1.MX3 3 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +P8 0x00DD Port 8, Analog/Digital Input +P8.P86 6 +P8.P85 5 +P8.P84 4 +P8.P83 3 +P8.P82 2 +P8.P81 1 +P8.P80 0 +CTRELL 0x00DE Compare Timer Rel. Reg., Low Byte (RMAP=0) +CTRELL.CTRELL7 7 +CTRELL.CTRELL6 6 +CTRELL.CTRELL5 5 +CTRELL.CTRELL4 4 +CTRELL.CTRELL3 3 +CTRELL.CTRELL2 2 +CTRELL.CTRELL1 1 +CTRELL.CTRELL0 0 +; CT1RELL 0x00DE Compare Timer 1 Rel. Reg., Low Byte (RMAP=1) +; CT1RELL.CT1RELL7 7 +; CT1RELL.CT1RELL6 6 +; CT1RELL.CT1RELL5 5 +; CT1RELL.CT1RELL4 4 +; CT1RELL.CT1RELL3 3 +; CT1RELL.CT1RELL2 2 +; CT1RELL.CT1RELL1 1 +; CT1RELL.CT1RELL0 0 +CTRELH 0x00DF Compare Timer Rel. Reg., High Byte (RMAP=0) +CTRELH.CTRELH7 7 +CTRELH.CTRELH6 6 +CTRELH.CTRELH5 5 +CTRELH.CTRELH4 4 +CTRELH.CTRELH3 3 +CTRELH.CTRELH2 2 +CTRELH.CTRELH1 1 +CTRELH.CTRELH0 0 +; CT1RELH 0x00DF Compare Timer 1 Rel. Reg., High Byte (RMAP=1) +; CT1RELH.CT1RELH7 7 +; CT1RELH.CT1RELH6 6 +; CT1RELH.CT1RELH5 5 +; CT1RELH.CT1RELH4 4 +; CT1RELH.CT1RELH3 3 +; CT1RELH.CT1RELH2 2 +; CT1RELH.CT1RELH1 1 +; CT1RELH.CT1RELH0 0 +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +CTCON 0x00E1 Compare Timer Control Register +CTCON.T2PS1 7 +CTCON.CTP 6 +CTCON.ICR 5 +CTCON.ICS 4 +CTCON.CTF 3 +CTCON.CLK2 2 +CTCON.CLK1 1 +CTCON.CLK0 0 +CML3 0x00E2 Compare Register 3, Low Byte (RMAP=0) +CML3.CML37 7 +CML3.CML36 6 +CML3.CML35 5 +CML3.CML34 4 +CML3.CML33 3 +CML3.CML32 2 +CML3.CML31 1 +CML3.CML30 0 +; CC1L3 0x00E2 Compare/Capture 1 Register 3, Low Byte (RMAP=1) +; CC1L3.CC1L37 7 +; CC1L3.CC1L36 6 +; CC1L3.CC1L35 5 +; CC1L3.CC1L34 4 +; CC1L3.CC1L33 3 +; CC1L3.CC1L32 2 +; CC1L3.CC1L31 1 +; CC1L3.CC1L30 0 +CMH3 0x00E3 Compare Register 3, High Byte (RMAP=0) +CMH3.CMH37 7 +CMH3.CMH36 6 +CMH3.CMH35 5 +CMH3.CMH34 4 +CMH3.CMH33 3 +CMH3.CMH32 2 +CMH3.CMH31 1 +CMH3.CMH30 0 +; CC1H3 0x00E3 Compare/Capture 1 Register 3, High Byte (RMAP=1) +; CC1H3.CC1H37 7 +; CC1H3.CC1H36 6 +; CC1H3.CC1H35 5 +; CC1H3.CC1H34 4 +; CC1H3.CC1H33 3 +; CC1H3.CC1H32 2 +; CC1H3.CC1H31 1 +; CC1H3.CC1H30 0 +CML4 0x00E4 Compare Register 4, Low Byte (RMAP=0) +CML4.CML47 7 +CML4.CML46 6 +CML4.CML45 5 +CML4.CML44 4 +CML4.CML43 3 +CML4.CML42 2 +CML4.CML41 1 +CML4.CML40 0 +; CC1L4 0x00E4 Compare/Capture 1 Register 4, Low Byte (RMAP=1) +; CC1L4.CC1L47 7 +; CC1L4.CC1L46 6 +; CC1L4.CC1L45 5 +; CC1L4.CC1L44 4 +; CC1L4.CC1L43 3 +; CC1L4.CC1L42 2 +; CC1L4.CC1L41 1 +; CC1L4.CC1L40 0 +CMH4 0x00E5 Compare Register 4, High Byte (RMAP=0) +CMH4.CMH47 7 +CMH4.CMH46 6 +CMH4.CMH45 5 +CMH4.CMH44 4 +CMH4.CMH43 3 +CMH4.CMH42 2 +CMH4.CMH41 1 +CMH4.CMH40 0 +; CC1H4 0x00E5 Compare/Capture 1 Register 4, High Byte (RMAP=1) +; CC1H4.CC1H47 7 +; CC1H4.CC1H46 6 +; CC1H4.CC1H45 5 +; CC1H4.CC1H44 4 +; CC1H4.CC1H43 3 +; CC1H4.CC1H42 2 +; CC1H4.CC1H41 1 +; CC1H4.CC1H40 0 +CML5 0x00E6 Compare Register 5, Low Byte (RMAP=0) +CML5.CML57 7 +CML5.CML56 6 +CML5.CML55 5 +CML5.CML54 4 +CML5.CML53 3 +CML5.CML52 2 +CML5.CML51 1 +CML5.CML50 0 +; CC1L5 0x00E6 Compare/Capture 1 Register 5, Low Byte (RMAP=1) +; CC1L5.CC1L57 7 +; CC1L5.CC1L56 6 +; CC1L5.CC1L55 5 +; CC1L5.CC1L54 4 +; CC1L5.CC1L53 3 +; CC1L5.CC1L52 2 +; CC1L5.CC1L51 1 +; CC1L5.CC1L50 0 +CMH5 0x00E7 Compare Register 5, High Byte (RMAP=0) +CMH5.CMH57 7 +CMH5.CMH56 6 +CMH5.CMH55 5 +CMH5.CMH54 4 +CMH5.CMH53 3 +CMH5.CMH52 2 +CMH5.CMH51 1 +CMH5.CMH50 0 +; CC1H5 0x00E7 Compare/Capture 1 Register 5, High Byte (RMAP=1) +; CC1H5.CC1H57 7 +; CC1H5.CC1H56 6 +; CC1H5.CC1H55 5 +; CC1H5.CC1H54 4 +; CC1H5.CC1H53 3 +; CC1H5.CC1H52 2 +; CC1H5.CC1H51 1 +; CC1H5.CC1H50 0 +P4 0x00E8 Port 4 (PDIR=0) +P4.CM7 7 +P4.CM6 6 +P4.CM5 5 +P4.CM4 4 +P4.CM3 3 +P4.CM2 2 +P4.CM1 1 +P4.CM0 0 +; DIR4 0x00E8 Direction Register Port 4 (PDIR=1) +; DIR4.DIR47 7 +; DIR4.DIR46 6 +; DIR4.DIR45 5 +; DIR4.DIR44 4 +; DIR4.DIR43 3 +; DIR4.DIR42 2 +; DIR4.DIR41 1 +; DIR4.DIR40 0 +MD0 0x00E9 Multiplication/Division Register 0 +MD0.MD07 7 +MD0.MD06 6 +MD0.MD05 5 +MD0.MD04 4 +MD0.MD03 3 +MD0.MD02 2 +MD0.MD01 1 +MD0.MD00 0 +MD1 0x00EA Multiplication/Division Register 1 +MD1.MD17 7 +MD1.MD16 6 +MD1.MD15 5 +MD1.MD14 4 +MD1.MD13 3 +MD1.MD12 2 +MD1.MD11 1 +MD1.MD10 0 +MD2 0x00EB Multiplication/Division Register 2 +MD2.MD27 7 +MD2.MD26 6 +MD2.MD25 5 +MD2.MD24 4 +MD2.MD23 3 +MD2.MD22 2 +MD2.MD21 1 +MD2.MD20 0 +MD3 0x00EC Multiplication/Division Register 3 +MD3.MD37 7 +MD3.MD36 6 +MD3.MD35 5 +MD3.MD34 4 +MD3.MD33 3 +MD3.MD32 2 +MD3.MD31 1 +MD3.MD30 0 +MD4 0x00ED Multiplication/Division Register 4 +MD4.MD47 7 +MD4.MD46 6 +MD4.MD45 5 +MD4.MD44 4 +MD4.MD43 3 +MD4.MD42 2 +MD4.MD41 1 +MD4.MD40 0 +MD5 0x00EE Multiplication/Division Register 5 +MD5.MD57 7 +MD5.MD56 6 +MD5.MD55 5 +MD5.MD54 4 +MD5.MD53 3 +MD5.MD52 2 +MD5.MD51 1 +MD5.MD50 0 +ARCON 0x00EF Arithmetic Control Register +ARCON.MDEF 7 +ARCON.MDOV 6 +ARCON.SLR 5 +ARCON.SC4 4 +ARCON.SC3 3 +ARCON.SC2 2 +ARCON.SC1 1 +ARCON.SC0 0 +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +CML6 0x00F2 Compare Register 6, Low Byte (RMAP=0) +CML6.CML67 7 +CML6.CML66 6 +CML6.CML65 5 +CML6.CML64 4 +CML6.CML63 3 +CML6.CML62 2 +CML6.CML61 1 +CML6.CML60 0 +; CC1L6 0x00F2 Compare/Capture 1 Register 6, Low Byte (RMAP=1) +; CC1L6.CC1L67 7 +; CC1L6.CC1L66 6 +; CC1L6.CC1L65 5 +; CC1L6.CC1L64 4 +; CC1L6.CC1L63 3 +; CC1L6.CC1L62 2 +; CC1L6.CC1L61 1 +; CC1L6.CC1L60 0 +CMH6 0x00F3 Compare Register 6, High Byte (RMAP=0) +CMH6.CMH67 7 +CMH6.CMH66 6 +CMH6.CMH65 5 +CMH6.CMH64 4 +CMH6.CMH63 3 +CMH6.CMH62 2 +CMH6.CMH61 1 +CMH6.CMH60 0 +; CC1H6 0x00F3 Compare/Capture 1 Register 6, High Byte (RMAP=1) +; CC1H6.CC1H67 7 +; CC1H6.CC1H66 6 +; CC1H6.CC1H65 5 +; CC1H6.CC1H64 4 +; CC1H6.CC1H63 3 +; CC1H6.CC1H62 2 +; CC1H6.CC1H61 1 +; CC1H6.CC1H60 0 +CML7 0x00F4 Compare Register 7, Low Byte (RMAP=0) +CML7.CML77 7 +CML7.CML76 6 +CML7.CML75 5 +CML7.CML74 4 +CML7.CML73 3 +CML7.CML72 2 +CML7.CML71 1 +CML7.CML70 0 +; CC1L7 0x00F4 Compare/Capture 1 Register 7, Low Byte (RMAP=1) +; CC1L7.CC1L77 7 +; CC1L7.CC1L76 6 +; CC1L7.CC1L75 5 +; CC1L7.CC1L74 4 +; CC1L7.CC1L73 3 +; CC1L7.CC1L72 2 +; CC1L7.CC1L71 1 +; CC1L7.CC1L70 0 +CMH7 0x00F5 Compare Register 7, High Byte (RMAP=0) +CMH7.CMH77 7 +CMH7.CMH76 6 +CMH7.CMH75 5 +CMH7.CMH74 4 +CMH7.CMH73 3 +CMH7.CMH72 2 +CMH7.CMH71 1 +CMH7.CMH70 0 +; CC1H7 0x00F5 Compare/Capture 1 Register 7, High Byte (RMAP=1) +; CC1H7.CC1H77 7 +; CC1H7.CC1H76 6 +; CC1H7.CC1H75 5 +; CC1H7.CC1H74 4 +; CC1H7.CC1H73 3 +; CC1H7.CC1H72 2 +; CC1H7.CC1H71 1 +; CC1H7.CC1H70 0 +CMEN 0x00F6 Compare Enable Register (RMAP=0) +CMEN.CMEN7 7 +CMEN.CMEN6 6 +CMEN.CMEN5 5 +CMEN.CMEN4 4 +CMEN.CMEN3 3 +CMEN.CMEN2 2 +CMEN.CMEN1 1 +CMEN.CMEN0 0 +; CC1EN 0x00F6 Compare/Capture Enable Register (RMAP=1) +; CC1EN.CC1EN7 7 +; CC1EN.CC1EN6 6 +; CC1EN.CC1EN5 5 +; CC1EN.CC1EN4 4 +; CC1EN.CC1EN3 3 +; CC1EN.CC1EN2 2 +; CC1EN.CC1EN1 1 +; CC1EN.CC1EN0 0 +CMSEL 0x00F7 Compare Input Select (RMAP=0) +CMSEL.CMSEL7 7 +CMSEL.CMSEL6 6 +CMSEL.CMSEL5 5 +CMSEL.CMSEL4 4 +CMSEL.CMSEL3 3 +CMSEL.CMSEL2 2 +CMSEL.CMSEL1 1 +CMSEL.CMSEL0 0 +; CAFR 0x00F7 Capture 1, Falling/Rising Edge Register (RMAP=1) +; CAFR.CAFR7 7 +; CAFR.CAFR6 6 +; CAFR.CAFR5 5 +; CAFR.CAFR4 4 +; CAFR.CAFR3 3 +; CAFR.CAFR2 2 +; CAFR.CAFR1 1 +; CAFR.CAFR0 0 +P5 0x00F8 Port 5 (PDIR=0) +P5.CCM7 7 +P5.CCM6 6 +P5.CCM5 5 +P5.CCM4 4 +P5.CCM3 3 +P5.CCM2 2 +P5.CCM1 1 +P5.CCM0 0 +; DIR5 0x00F8 Direction Register Port 5 (PDIR=1) +; DIR5.DIR57 7 +; DIR5.DIR56 6 +; DIR5.DIR55 5 +; DIR5.DIR54 4 +; DIR5.DIR53 3 +; DIR5.DIR52 2 +; DIR5.DIR51 1 +; DIR5.DIR50 0 +P9 0x00F9 Port 9 (PDIR=0) +P9.CC17 7 +P9.CC16 6 +P9.CC15 5 +P9.CC14 4 +P9.CC13 3 +P9.CC12 2 +P9.CC11 1 +P9.CC10 0 +; DIR9 0x00F9 Direction Register Port 9 (PDIR=1) +; DIR9.DIR97 7 +; DIR9.DIR96 6 +; DIR9.DIR95 5 +; DIR9.DIR94 4 +; DIR9.DIR93 3 +; DIR9.DIR92 2 +; DIR9.DIR91 1 +; DIR9.DIR90 0 +P6 0x00FA Port 6 (PDIR=0) +P6.P67 7 +P6.P66 6 +P6.P65 5 +P6.P64 4 +P6.P63 3 +P6.TxD1 2 +P6.RxD1 1 +P6.ADST 0 +; DIR6 0x00FA Direction Register Port 6 (PDIR=1) +; DIR6.DIR67 7 +; DIR6.DIR66 6 +; DIR6.DIR65 5 +; DIR6.DIR64 4 +; DIR6.DIR63 3 +; DIR6.DIR62 2 +; DIR6.DIR61 1 +; DIR6.DIR60 0 +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C513AO +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8025&parent_oid=16713 +; SAF-C513AO-LN.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xFF00 +area DATA XRAM 0xFF00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External Interrupt 0 +entry TF0 0x000B Timer 0 interrupt +entry IE1 0x0013 External Interrupt 1 +entry TF1 0x001B Timer 1 interrupt +entry RI_TI 0x0023 USART serial port interrupt +entry TF2_EXF2 0x002B Timer 2 interrupt +entry WCOL_TC 0x0043 Synchronous Serial Channel interrupt (SSC) +entry WA_PDM 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.SLS 5 +P1.STO 4 +P1.SRI 3 +P1.SCLK 2 +P1.T2EX 1 +P1.T2 0 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IE 0x00A8 Interrupt Enable Register +IE.EA 7 +IE.ESSC 6 +IE.ET2 5 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 +RESERVED00A9 0x00A9 RESERVED +RESERVED00AA 0x00AA RESERVED +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.XMAP 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IP 0x00B8 Interrupt Priority Register +IP.PSSC 6 +IP.PT2 5 +IP.PS 4 +IP.PT1 3 +IP.PX1 2 +IP.PT0 1 +IP.PX0 0 +RESERVED00B9 0x00B9 RESERVED +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +WDCON 0x00C0 Watchdog Timer Control Register +WDCON.OWDS 3 +WDCON.WDTS 2 +WDCON.WDT 1 +WDCON.SWDT 0 +RESERVED00C1 0x00C1 RESERVED +RESERVED00C2 0x00C2 RESERVED +RESERVED00C3 0x00C3 RESERVED +RESERVED00C4 0x00C4 RESERVED +RESERVED00C5 0x00C5 RESERVED +RESERVED00C6 0x00C6 RESERVED +RESERVED00C7 0x00C7 RESERVED +T2CON 0x00C8 Timer 2 Control Register +T2CON.TF2 7 +T2CON.EXF2 6 +T2CON.RCLK 5 +T2CON.TCLK 4 +T2CON.EXEN2 3 +T2CON.TR2 2 +T2CON.C_T2 1 +T2CON.CP_RL2 0 +T2MOD 0x00C9 Timer 2 Mode Register +T2MOD.DCEN 0 +RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte +RC2L.RC2L7 7 +RC2L.RC2L6 6 +RC2L.RC2L5 5 +RC2L.RC2L4 4 +RC2L.RC2L3 3 +RC2L.RC2L2 2 +RC2L.RC2L1 1 +RC2L.RC2L0 0 +RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte +RC2H.RC2H7 7 +RC2H.RC2H6 6 +RC2H.RC2H5 5 +RC2H.RC2H4 4 +RC2H.RC2H3 3 +RC2H.RC2H2 2 +RC2H.RC2H1 1 +RC2H.RC2H0 0 +TL2 0x00CC Timer 2 Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2 High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +RESERVED00D8 0x00D8 RESERVED +RESERVED00D9 0x00D9 RESERVED +RESERVED00DA 0x00DA RESERVED +RESERVED00DB 0x00DB RESERVED +RESERVED00DC 0x00DC RESERVED +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +SSCCON 0x00E8 SSC Control Register +SSCCON.SCEN 7 +SSCCON.TEN 6 +SSCCON.MSTR 5 +SSCCON.CPOL 4 +SSCCON.CPHA 3 +SSCCON.BRS2 2 +SSCCON.BRS1 1 +SSCCON.BRS0 0 +STB 0x00E9 SSC Transmit Register +STB.STB7 7 +STB.STB6 6 +STB.STB5 5 +STB.STB4 4 +STB.STB3 3 +STB.STB2 2 +STB.STB1 1 +STB.STB0 0 +SRB 0x00EA SSC Receive Register +SRB.SRB7 7 +SRB.SRB6 6 +SRB.SRB5 5 +SRB.SRB4 4 +SRB.SRB3 3 +SRB.SRB2 2 +SRB.SRB1 1 +SRB.SRB0 0 +SSCMOD 0x00EB SSC Mode Test Register +SSCMOD.LOOPB 7 +SSCMOD.TRIO 6 +SSCMOD.LSBSM 0 +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +SCF 0x00F8 SSC Flag Register +SCF.WCOL 1 +SCF.TC 0 +SCIEN 0x00F9 SSC Interrupt Enable Register +SCIEN.WCEN 1 +SCIEN.TCEN 0 +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR0.VR07 7 +VR0.VR06 6 +VR0.VR05 5 +VR0.VR04 4 +VR0.VR03 3 +VR0.VR02 2 +VR0.VR01 1 +VR0.VR00 0 +VR1 0x00FD Version Register 1 +VR1.VR17 7 +VR1.VR16 6 +VR1.VR15 5 +VR1.VR14 4 +VR1.VR13 3 +VR1.VR12 2 +VR1.VR11 1 +VR1.VR10 0 +VR2 0x00FE Version Register 2 +VR2.VR27 7 +VR2.VR26 6 +VR2.VR25 5 +VR2.VR24 4 +VR2.VR23 3 +VR2.VR22 2 +VR2.VR21 1 +VR2.VR20 0 +RESERVED00FF 0x00FF RESERVED + + +.C515 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8032&parent_oid=16670 +; SAF-C515-L24N.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI_TI 0x0023 Serial channel +entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload +entry IADC 0x0043 A/D converter +entry IEX2 0x004B External interrupt 2 +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +RESERVED0086 0x0086 RESERVED +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_0 7 +TMOD.C_T_0 6 +TMOD.M1_0 5 +TMOD.M0_0 4 +TMOD.GATE_1 3 +TMOD.C_T_1 2 +TMOD.M1_1 1 +TMOD.M0_1 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.INT2 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EAL 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +RESERVED00AA 0x00AA RESERVED +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register +SYSCON.EALE 5 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.EX2 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.IEX2 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.I2FR 5 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Com./Rel./Capt. Reg. High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON 0x00D8 A/D Converter Control Register +ADCON.BD 7 +ADCON.CLK 6 +ADCON.BSY 4 +ADCON.ADM 3 +ADCON.MX2 2 +ADCON.MX1 1 +ADCON.MX0 0 +ADDAT 0x00D9 A/D Converter Data Register +ADDAT.ADDAT7 7 +ADDAT.ADDAT6 6 +ADDAT.ADDAT5 5 +ADDAT.ADDAT4 4 +ADDAT.ADDAT3 3 +ADDAT.ADDAT2 2 +ADDAT.ADDAT1 1 +ADDAT.ADDAT0 0 +DAPR 0x00DA A/D Converter Program Register +DAPR.DAPR7 7 +DAPR.DAPR6 6 +DAPR.DAPR5 5 +DAPR.DAPR4 4 +DAPR.DAPR3 3 +DAPR.DAPR2 2 +DAPR.DAPR1 1 +DAPR.DAPR0 0 +P6 0x00DB Port 6, Analog/Digital Input +P6.P67 7 +P6.P66 6 +P6.P65 5 +P6.P64 4 +P6.P63 3 +P6.P62 2 +P6.P61 1 +P6.P60 0 +RESERVED00DC 0x00DC RESERVED +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 +P4.P47 7 +P4.P46 6 +P4.P45 5 +P4.P44 4 +P4.P43 3 +P4.P42 2 +P4.P41 1 +P4.P40 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +P5 0x00F8 +P5.P57 7 +P5.P56 6 +P5.P55 5 +P5.P54 4 +P5.P53 3 +P5.P52 2 +P5.P51 1 +P5.P50 0 +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C515A +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8033&parent_oid=12122 +; SAF_C515A-4R24M.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xFC00 +area DATA XRAM 0xFC00:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI_TI 0x0023 Serial channel +entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload +entry IADC 0x0043 A/D converter +entry IEX2 0x004B External interrupt 2 +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry WAKE_UP 0x007B Wake-up from power-down mode + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.INT2 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +XPAGE 0x0091 Page Address Register for Extended On-Chip RAM +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EAL 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, Low Byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System/XRAM Control Register +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.EX2 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, High Byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.IEX2 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.I2FR 5 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Com./Rel./Capt. Reg. High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.ADEX 5 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register, High Byte +ADDATH.ADDATH9 7 +ADDATH.ADDATH8 6 +ADDATH.ADDATH7 5 +ADDATH.ADDATH6 4 +ADDATH.ADDATH5 3 +ADDATH.ADDATH4 2 +ADDATH.ADDATH3 1 +ADDATH.ADDATH2 0 +ADDATL 0x00DA A/D Converter Data Register, low Byte +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +P6 0x00DB Port 6, Analog/Digital Input +P6.P67 7 +P6.P66 6 +P6.P65 5 +P6.P64 4 +P6.P63 3 +P6.P62 2 +P6.P61 1 +P6.P60 0 +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL 7 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.P47 7 +P4.P46 6 +P4.P45 5 +P4.P44 4 +P4.P43 3 +P4.P42 2 +P4.P41 1 +P4.P40 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +P5 0x00F8 Port 5 +P5.P57 7 +P5.P56 6 +P5.P55 5 +P5.P54 4 +P5.P53 3 +P5.P52 2 +P5.P51 1 +P5.P50 0 +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C515C +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=31042&parent_oid=12126 +; SAF_C515C-8EM.pdf + + +; MEMORY MAP +area CODE code 0x0000:0xF700 +area DATA CAN 0xF700:0xF800 +area DATA XRAM 0xF800:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External Interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External Interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial Channel +entry TF2_EXF2 0x002B Timer 2 Overflow / Ext. Reload +entry IADC 0x0043 A/D Converter +entry IEX2 0x004B External Interrupt 2 +entry IEX3 0x0053 External Interrupt 3 +entry IEX4 0x005B External Interrupt 4 +entry IEX5 0x0063 External Interrupt 5 +entry IEX6 0x006B External Interrupt 6 +entry WUPPDM 0x007B Wake-up from power-down mode +entry CANC 0x008B CAN controller +entry IEX7 0x00A3 External Interrupt 7 +entry IEX8 0x00AB External Interrupt 8 +entry SSCI 0x0093 SSC interface + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_0 7 +TMOD.C_T_0 6 +TMOD.M1_0 5 +TMOD.M0_0 4 +TMOD.GATE_1 3 +TMOD.C_T_1 2 +TMOD.M1_1 1 +TMOD.M0_1 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.INT2 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +XPAGE 0x0091 Page Address Register for Extended on-chip XRAM and CAN Controller +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +SSCCON 0x0093 SSC Control Register +SSCCON.SCEN 7 +SSCCON.TEN 6 +SSCCON.MSTR 5 +SSCCON.CPOL 4 +SSCCON.CPHA 3 +SSCCON.BRS2 2 +SSCCON.BRS1 1 +SSCCON.BRS0 0 +STB 0x0094 SSC Transmit Buffer +STB.STB7 7 +STB.STB6 6 +STB.STB5 5 +STB.STB4 4 +STB.STB3 3 +STB.STB2 2 +STB.STB1 1 +STB.STB0 0 +SRB 0x0095 SSC Receive Register +SRB.SRB7 7 +SRB.SRB6 6 +SRB.SRB5 5 +SRB.SRB4 4 +SRB.SRB3 3 +SRB.SRB2 2 +SRB.SRB1 1 +SRB.SRB0 0 +SSCMOD 0x0096 SSC Mode Test Register +SSCMOD.LOOPB 7 +SSCMOD.TRIO 6 +SSCMOD.LSBSM 0 +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +IEN2 0x009A Interrupt Enable Register 2 +IEN2.EX8 5 +IEN2.EX7 4 +IEN2.ESSC 2 +IEN2.ECAN 1 +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EAL 7 +IEN0.WDT 6 +IEN0.ET2 5 +IEN0.ES 4 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +SRELL 0x00AA Serial Channel Reload Register, low byte +SRELL.SRELL7 7 +SRELL.SRELL6 6 +SRELL.SRELL5 5 +SRELL.SRELL4 4 +SRELL.SRELL3 3 +SRELL.SRELL2 2 +SRELL.SRELL1 1 +SRELL.SRELL0 0 +SCF 0x00AB SSC Flag Register +SCF.WCOL 1 +SCF.TC 0 +SCIEN 0x00AC SSC Interrupt Enable Register +SCIEN.WCEN 1 +SCIEN.TCEN 0 +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD 1 +P3.RxD 0 +SYSCON 0x00B1 System Control Register +SYSCON.PMOD 6 +SYSCON.EALE 5 +SYSCON.RMAP 4 +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +; SYSCON 0x00B1 System Control Register (available in the C515C-8E) +; SYSCON.PMOD 6 +; SYSCON.EALE 5 +; SYSCON.RMAP 4 +; SYSCON.CSWO 2 +; SYSCON.XMAP1 1 +; SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.EX2 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.PDIR 7 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +SRELH 0x00BA Serial Channel Reload Register, high byte +SRELH.SRELH1 1 +SRELH.SRELH0 0 +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +IRCON.EXF2 7 +IRCON.TF2 6 +IRCON.IEX6 5 +IRCON.IEX5 4 +IRCON.IEX4 3 +IRCON.IEX3 2 +IRCON.IEX2 1 +IRCON.IADC 0 +CCEN 0x00C1 Comp./Capture Enable Reg. +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.I2FR 5 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Com./Rel./Capt. Reg. High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.ADEX 5 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register High Byte +ADDATH.ADDATH9 7 +ADDATH.ADDATH8 6 +ADDATH.ADDATH7 5 +ADDATH.ADDATH6 4 +ADDATH.ADDATH5 3 +ADDATH.ADDATH4 2 +ADDATH.ADDATH3 1 +ADDATH.ADDATH2 0 +ADDATL 0x00DA A/D Converter Data Register Low Byte +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +P6 0x00DB Port 6, Analog/Digital Input +P6.P67 7 +P6.P66 6 +P6.P65 5 +P6.P64 4 +P6.P63 3 +P6.P62 2 +P6.P61 1 +P6.P60 0 +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL 7 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +P4.RXDC 7 +P4.TXDC 6 +P4.INT8 5 +P4.SLS 4 +P4.STO 3 +P4.SRI 2 +P4.SCLK 1 +P4.ADST 0 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +P5 0x00F8 Port 5 +P5.P57 7 +P5.P56 6 +P5.P55 5 +P5.P54 4 +P5.P53 3 +P5.P52 2 +P5.P51 1 +P5.P50 0 +; DIR5 0x00F8 Port 5 Direction Register +; DIR5.DIR57 7 +; DIR5.DIR56 6 +; DIR5.DIR55 5 +; DIR5.DIR54 4 +; DIR5.DIR53 3 +; DIR5.DIR52 2 +; DIR5.DIR51 1 +; DIR5.DIR50 0 +RESERVED00F9 0x00F9 RESERVED +P7 0x00FA Port 7 +P7.INT7 0 +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC (C515C-8E only) +VR1 0x00FD (C515C-8E only) +VR2 0x00FE (C515C-8E only) +RESERVED00FF 0x00FF RESERVED +CR 0xF700 Control Register +CR.TEST 7 +CR.CCE 6 +CR.EIE 3 +CR.SIE 2 +CR.IE 1 +CR.INIT 0 +SR 0xF701 Status Register +SR.BOFF 7 +SR.EWRN 6 +SR.RXOK 4 +SR.TXOK 3 +SR.LEC2 2 +SR.LEC1 1 +SR.LEC0 0 +IR 0xF702 Interrupt Register +IR.INTID7 7 +IR.INTID6 6 +IR.INTID5 5 +IR.INTID4 4 +IR.INTID3 3 +IR.INTID2 2 +IR.INTID1 1 +IR.INTID0 0 +RESERVEDF703 0xF703 RESERVED +BTR0 0xF704 Bit Timing Register Low +BTR0.SJW7 7 +BTR0.SJW6 6 +BTR0.BRP5 5 +BTR0.BRP4 4 +BTR0.BRP3 3 +BTR0.BRP2 2 +BTR0.BRP1 1 +BTR0.BRP0 0 +BTR1 0xF705 Bit Timing Register High +BTR1.TSEG27 7 +BTR1.TSEG26 6 +BTR1.TSEG25 5 +BTR1.TSEG24 4 +BTR1.TSEG13 3 +BTR1.TSEG12 2 +BTR1.TSEG11 1 +BTR1.TSEG10 0 +GMS0 0xF706 Global Mask Short Register Low +GMS0.ID28 7 +GMS0.ID27 6 +GMS0.ID26 5 +GMS0.ID25 4 +GMS0.ID24 3 +GMS0.ID23 2 +GMS0.ID22 1 +GMS0.ID21 0 +GMS1 0xF707 Global Mask Short Register High +GMS1.ID20 7 +GMS1.ID19 6 +GMS1.ID18 5 +UGML0 0xF708 Upper Global Mask Long Register Low +UGML0.ID28 7 +UGML0.ID27 6 +UGML0.ID26 5 +UGML0.ID25 4 +UGML0.ID24 3 +UGML0.ID23 2 +UGML0.ID22 1 +UGML0.ID21 0 +UGML1 0xF709 Upper Global Mask Long Register High +UGML1.ID20 7 +UGML1.ID19 6 +UGML1.ID18 5 +UGML1.ID17 4 +UGML1.ID16 3 +UGML1.ID15 2 +UGML1.ID14 1 +UGML1.ID13 0 +LGML0 0xF70A Lower Global Mask Long Register Low +LGML0.ID12 7 +LGML0.ID11 6 +LGML0.ID10 5 +LGML0.ID9 4 +LGML0.ID8 3 +LGML0.ID7 2 +LGML0.ID6 1 +LGML0.ID5 0 +LGML1 0xF70B Lower Global Mask Long Register High +LGML1.ID4 7 +LGML1.ID3 6 +LGML1.ID2 5 +LGML1.ID1 4 +LGML1.ID0 3 +UMLM0 0xF70C Upper Mask of Last Message Register Low +UMLM0.ID28 7 +UMLM0.ID27 6 +UMLM0.ID26 5 +UMLM0.ID25 4 +UMLM0.ID24 3 +UMLM0.ID23 2 +UMLM0.ID22 1 +UMLM0.ID21 0 +UMLM1 0xF70D Upper Mask of Last Message Register High +UMLM1.ID20 7 +UMLM1.ID19 6 +UMLM1.ID18 5 +UMLM1.ID17 4 +UMLM1.ID16 3 +UMLM1.ID15 2 +UMLM1.ID14 1 +UMLM1.ID13 0 +LMLM0 0xF70E Lower Mask of Last Message Register Low +LMLM0.ID12 7 +LMLM0.ID11 6 +LMLM0.ID10 5 +LMLM0.ID9 4 +LMLM0.ID8 3 +LMLM0.ID7 2 +LMLM0.ID6 1 +LMLM0.ID5 0 +LMLM1 0xF70F Lower Mask of Last Message Register High +LMLM1.ID4 7 +LMLM1.ID3 6 +LMLM1.ID2 5 +LMLM1.ID1 4 +LMLM1.ID0 3 +; -------------------------------------- CAN_1 -------------------------------- +MCR0_1 0xF710 Message Control Register Low +MCR0_1.MSGVAL1 7 +MCR0_1.MSGVAL0 6 +MCR0_1.TXIE1 5 +MCR0_1.TXIE0 4 +MCR0_1.RXIE1 3 +MCR0_1.RXIE0 2 +MCR0_1.INTPND1 1 +MCR0_1.INTPND0 0 +MCR1_1 0xF711 Message Control Register High +MCR1_1.RMTPND1 7 +MCR1_1.RMTPND0 6 +MCR1_1.TXRQ1 5 +MCR1_1.TXRQ0 4 +MCR1_1.MSGLSTCPUUPD1 3 +MCR1_1.MSGLSTCPUUPD0 2 +MCR1_1.NEWDAT1 1 +MCR1_1.NEWDAT0 0 +UAR0_1 0xF712 Upper Arbitration Register Low +UAR0_1.ID28 7 +UAR0_1.ID27 6 +UAR0_1.ID26 5 +UAR0_1.ID25 4 +UAR0_1.ID24 3 +UAR0_1.ID23 2 +UAR0_1.ID22 1 +UAR0_1.ID21 0 +UAR1_1 0xF713 Upper Arbitration Register High +UAR1_1.ID20 7 +UAR1_1.ID19 6 +UAR1_1.ID18 5 +UAR1_1.ID17 4 +UAR1_1.ID16 3 +UAR1_1.ID15 2 +UAR1_1.ID14 1 +UAR1_1.ID13 0 +LAR0_1 0xF714 Lower Arbitration Register Low +LAR0_1.ID12 7 +LAR0_1.ID11 6 +LAR0_1.ID10 5 +LAR0_1.ID9 4 +LAR0_1.ID8 3 +LAR0_1.ID7 2 +LAR0_1.ID6 1 +LAR0_1.ID5 0 +LAR1_1 0xF715 Lower Arbitration Register High +LAR1_1.ID4 7 +LAR1_1.ID3 6 +LAR1_1.ID2 5 +LAR1_1.ID1 4 +LAR1_1.ID0 3 +MCFG_1 0xF716 Message Configuration Register +MCFG_1.DLC7 7 +MCFG_1.DLC6 6 +MCFG_1.DLC5 5 +MCFG_1.DLC4 4 +MCFG_1.DIR 3 +MCFG_1.XTD 2 +DB0_1 0xF717 Message Data Byte 0 +DB0_1.DB07 7 +DB0_1.DB06 6 +DB0_1.DB05 5 +DB0_1.DB04 4 +DB0_1.DB03 3 +DB0_1.DB02 2 +DB0_1.DB01 1 +DB0_1.DB00 0 +DB1_1 0xF718 Message Data Byte 1 +DB1_1.DB17 7 +DB1_1.DB16 6 +DB1_1.DB15 5 +DB1_1.DB14 4 +DB1_1.DB13 3 +DB1_1.DB12 2 +DB1_1.DB11 1 +DB1_1.DB10 0 +DB2_1 0xF719 Message Data Byte 2 +DB2_1.DB27 7 +DB2_1.DB26 6 +DB2_1.DB25 5 +DB2_1.DB24 4 +DB2_1.DB23 3 +DB2_1.DB22 2 +DB2_1.DB21 1 +DB2_1.DB20 0 +DB3_1 0xF71A Message Data Byte 3 +DB3_1.DB37 7 +DB3_1.DB36 6 +DB3_1.DB35 5 +DB3_1.DB34 4 +DB3_1.DB33 3 +DB3_1.DB32 2 +DB3_1.DB31 1 +DB3_1.DB30 0 +DB4_1 0xF71B Message Data Byte 4 +DB4_1.DB47 7 +DB4_1.DB46 6 +DB4_1.DB45 5 +DB4_1.DB44 4 +DB4_1.DB43 3 +DB4_1.DB42 2 +DB4_1.DB41 1 +DB4_1.DB40 0 +DB5_1 0xF71C Message Data Byte 5 +DB5_1.DB57 7 +DB5_1.DB56 6 +DB5_1.DB55 5 +DB5_1.DB54 4 +DB5_1.DB53 3 +DB5_1.DB52 2 +DB5_1.DB51 1 +DB5_1.DB50 0 +DB6_1 0xF71D Message Data Byte 6 +DB6_1.DB67 7 +DB6_1.DB66 6 +DB6_1.DB65 5 +DB6_1.DB64 4 +DB6_1.DB63 3 +DB6_1.DB62 2 +DB6_1.DB61 1 +DB6_1.DB60 0 +DB7_1 0xF71E Message Data Byte 7 +DB7_1.DB77 7 +DB7_1.DB76 6 +DB7_1.DB75 5 +DB7_1.DB74 4 +DB7_1.DB73 3 +DB7_1.DB72 2 +DB7_1.DB71 1 +DB7_1.DB70 0 +RESERVEDF71F 0xF71F RESERVED +; -------------------------------------- CAN_2 -------------------------------- +MCR0_2 0xF720 Message Control Register Low +MCR0_2.MSGVAL1 7 +MCR0_2.MSGVAL0 6 +MCR0_2.TXIE1 5 +MCR0_2.TXIE0 4 +MCR0_2.RXIE1 3 +MCR0_2.RXIE0 2 +MCR0_2.INTPND1 1 +MCR0_2.INTPND0 0 +MCR1_2 0xF721 Message Control Register High +MCR1_2.RMTPND1 7 +MCR1_2.RMTPND0 6 +MCR1_2.TXRQ1 5 +MCR1_2.TXRQ0 4 +MCR1_2.MSGLSTCPUUPD1 3 +MCR1_2.MSGLSTCPUUPD0 2 +MCR1_2.NEWDAT1 1 +MCR1_2.NEWDAT0 0 +UAR0_2 0xF722 Upper Arbitration Register Low +UAR0_2.ID28 7 +UAR0_2.ID27 6 +UAR0_2.ID26 5 +UAR0_2.ID25 4 +UAR0_2.ID24 3 +UAR0_2.ID23 2 +UAR0_2.ID22 1 +UAR0_2.ID21 0 +UAR1_2 0xF723 Upper Arbitration Register High +UAR1_2.ID20 7 +UAR1_2.ID19 6 +UAR1_2.ID18 5 +UAR1_2.ID17 4 +UAR1_2.ID16 3 +UAR1_2.ID15 2 +UAR1_2.ID14 1 +UAR1_2.ID13 0 +LAR0_2 0xF724 Lower Arbitration Register Low +LAR0_2.ID12 7 +LAR0_2.ID11 6 +LAR0_2.ID10 5 +LAR0_2.ID9 4 +LAR0_2.ID8 3 +LAR0_2.ID7 2 +LAR0_2.ID6 1 +LAR0_2.ID5 0 +LAR1_2 0xF725 Lower Arbitration Register High +LAR1_2.ID4 7 +LAR1_2.ID3 6 +LAR1_2.ID2 5 +LAR1_2.ID1 4 +LAR1_2.ID0 3 +MCFG_2 0xF726 Message Configuration Register +MCFG_2.DLC7 7 +MCFG_2.DLC6 6 +MCFG_2.DLC5 5 +MCFG_2.DLC4 4 +MCFG_2.DIR 3 +MCFG_2.XTD 2 +DB0_2 0xF727 Message Data Byte 0 +DB0_2.DB07 7 +DB0_2.DB06 6 +DB0_2.DB05 5 +DB0_2.DB04 4 +DB0_2.DB03 3 +DB0_2.DB02 2 +DB0_2.DB01 1 +DB0_2.DB00 0 +DB1_2 0xF728 Message Data Byte 1 +DB1_2.DB17 7 +DB1_2.DB16 6 +DB1_2.DB15 5 +DB1_2.DB14 4 +DB1_2.DB13 3 +DB1_2.DB12 2 +DB1_2.DB11 1 +DB1_2.DB10 0 +DB2_2 0xF729 Message Data Byte 2 +DB2_2.DB27 7 +DB2_2.DB26 6 +DB2_2.DB25 5 +DB2_2.DB24 4 +DB2_2.DB23 3 +DB2_2.DB22 2 +DB2_2.DB21 1 +DB2_2.DB20 0 +DB3_2 0xF72A Message Data Byte 3 +DB3_2.DB37 7 +DB3_2.DB36 6 +DB3_2.DB35 5 +DB3_2.DB34 4 +DB3_2.DB33 3 +DB3_2.DB32 2 +DB3_2.DB31 1 +DB3_2.DB30 0 +DB4_2 0xF72B Message Data Byte 4 +DB4_2.DB47 7 +DB4_2.DB46 6 +DB4_2.DB45 5 +DB4_2.DB44 4 +DB4_2.DB43 3 +DB4_2.DB42 2 +DB4_2.DB41 1 +DB4_2.DB40 0 +DB5_2 0xF72C Message Data Byte 5 +DB5_2.DB57 7 +DB5_2.DB56 6 +DB5_2.DB55 5 +DB5_2.DB54 4 +DB5_2.DB53 3 +DB5_2.DB52 2 +DB5_2.DB51 1 +DB5_2.DB50 0 +DB6_2 0xF72D Message Data Byte 6 +DB6_2.DB67 7 +DB6_2.DB66 6 +DB6_2.DB65 5 +DB6_2.DB64 4 +DB6_2.DB63 3 +DB6_2.DB62 2 +DB6_2.DB61 1 +DB6_2.DB60 0 +DB7_2 0xF72E Message Data Byte 7 +DB7_2.DB77 7 +DB7_2.DB76 6 +DB7_2.DB75 5 +DB7_2.DB74 4 +DB7_2.DB73 3 +DB7_2.DB72 2 +DB7_2.DB71 1 +DB7_2.DB70 0 +RESERVEDF72F 0xF72F RESERVED +; -------------------------------------- CAN_3 -------------------------------- +MCR0_3 0xF730 Message Control Register Low +MCR0_3.MSGVAL1 7 +MCR0_3.MSGVAL0 6 +MCR0_3.TXIE1 5 +MCR0_3.TXIE0 4 +MCR0_3.RXIE1 3 +MCR0_3.RXIE0 2 +MCR0_3.INTPND1 1 +MCR0_3.INTPND0 0 +MCR1_3 0xF731 Message Control Register High +MCR1_3.RMTPND1 7 +MCR1_3.RMTPND0 6 +MCR1_3.TXRQ1 5 +MCR1_3.TXRQ0 4 +MCR1_3.MSGLSTCPUUPD1 3 +MCR1_3.MSGLSTCPUUPD0 2 +MCR1_3.NEWDAT1 1 +MCR1_3.NEWDAT0 0 +UAR0_3 0xF732 Upper Arbitration Register Low +UAR0_3.ID28 7 +UAR0_3.ID27 6 +UAR0_3.ID26 5 +UAR0_3.ID25 4 +UAR0_3.ID24 3 +UAR0_3.ID23 2 +UAR0_3.ID22 1 +UAR0_3.ID21 0 +UAR1_3 0xF733 Upper Arbitration Register High +UAR1_3.ID20 7 +UAR1_3.ID19 6 +UAR1_3.ID18 5 +UAR1_3.ID17 4 +UAR1_3.ID16 3 +UAR1_3.ID15 2 +UAR1_3.ID14 1 +UAR1_3.ID13 0 +LAR0_3 0xF734 Lower Arbitration Register Low +LAR0_3.ID12 7 +LAR0_3.ID11 6 +LAR0_3.ID10 5 +LAR0_3.ID9 4 +LAR0_3.ID8 3 +LAR0_3.ID7 2 +LAR0_3.ID6 1 +LAR0_3.ID5 0 +LAR1_3 0xF735 Lower Arbitration Register High +LAR1_3.ID4 7 +LAR1_3.ID3 6 +LAR1_3.ID2 5 +LAR1_3.ID1 4 +LAR1_3.ID0 3 +MCFG_3 0xF736 Message Configuration Register +MCFG_3.DLC7 7 +MCFG_3.DLC6 6 +MCFG_3.DLC5 5 +MCFG_3.DLC4 4 +MCFG_3.DIR 3 +MCFG_3.XTD 2 +DB0_3 0xF737 Message Data Byte 0 +DB0_3.DB07 7 +DB0_3.DB06 6 +DB0_3.DB05 5 +DB0_3.DB04 4 +DB0_3.DB03 3 +DB0_3.DB02 2 +DB0_3.DB01 1 +DB0_3.DB00 0 +DB1_3 0xF738 Message Data Byte 1 +DB1_3.DB17 7 +DB1_3.DB16 6 +DB1_3.DB15 5 +DB1_3.DB14 4 +DB1_3.DB13 3 +DB1_3.DB12 2 +DB1_3.DB11 1 +DB1_3.DB10 0 +DB2_3 0xF739 Message Data Byte 2 +DB2_3.DB27 7 +DB2_3.DB26 6 +DB2_3.DB25 5 +DB2_3.DB24 4 +DB2_3.DB23 3 +DB2_3.DB22 2 +DB2_3.DB21 1 +DB2_3.DB20 0 +DB3_3 0xF73A Message Data Byte 3 +DB3_3.DB37 7 +DB3_3.DB36 6 +DB3_3.DB35 5 +DB3_3.DB34 4 +DB3_3.DB33 3 +DB3_3.DB32 2 +DB3_3.DB31 1 +DB3_3.DB30 0 +DB4_3 0xF73B Message Data Byte 4 +DB4_3.DB47 7 +DB4_3.DB46 6 +DB4_3.DB45 5 +DB4_3.DB44 4 +DB4_3.DB43 3 +DB4_3.DB42 2 +DB4_3.DB41 1 +DB4_3.DB40 0 +DB5_3 0xF73C Message Data Byte 5 +DB5_3.DB57 7 +DB5_3.DB56 6 +DB5_3.DB55 5 +DB5_3.DB54 4 +DB5_3.DB53 3 +DB5_3.DB52 2 +DB5_3.DB51 1 +DB5_3.DB50 0 +DB6_3 0xF73D Message Data Byte 6 +DB6_3.DB67 7 +DB6_3.DB66 6 +DB6_3.DB65 5 +DB6_3.DB64 4 +DB6_3.DB63 3 +DB6_3.DB62 2 +DB6_3.DB61 1 +DB6_3.DB60 0 +DB7_3 0xF73E Message Data Byte 7 +DB7_3.DB77 7 +DB7_3.DB76 6 +DB7_3.DB75 5 +DB7_3.DB74 4 +DB7_3.DB73 3 +DB7_3.DB72 2 +DB7_3.DB71 1 +DB7_3.DB70 0 +RESERVEDF73F 0xF73F RESERVED +; -------------------------------------- CAN_4 -------------------------------- +MCR0_4 0xF740 Message Control Register Low +MCR0_4.MSGVAL1 7 +MCR0_4.MSGVAL0 6 +MCR0_4.TXIE1 5 +MCR0_4.TXIE0 4 +MCR0_4.RXIE1 3 +MCR0_4.RXIE0 2 +MCR0_4.INTPND1 1 +MCR0_4.INTPND0 0 +MCR1_4 0xF741 Message Control Register High +MCR1_4.RMTPND1 7 +MCR1_4.RMTPND0 6 +MCR1_4.TXRQ1 5 +MCR1_4.TXRQ0 4 +MCR1_4.MSGLSTCPUUPD1 3 +MCR1_4.MSGLSTCPUUPD0 2 +MCR1_4.NEWDAT1 1 +MCR1_4.NEWDAT0 0 +UAR0_4 0xF742 Upper Arbitration Register Low +UAR0_4.ID28 7 +UAR0_4.ID27 6 +UAR0_4.ID26 5 +UAR0_4.ID25 4 +UAR0_4.ID24 3 +UAR0_4.ID23 2 +UAR0_4.ID22 1 +UAR0_4.ID21 0 +UAR1_4 0xF743 Upper Arbitration Register High +UAR1_4.ID20 7 +UAR1_4.ID19 6 +UAR1_4.ID18 5 +UAR1_4.ID17 4 +UAR1_4.ID16 3 +UAR1_4.ID15 2 +UAR1_4.ID14 1 +UAR1_4.ID13 0 +LAR0_4 0xF744 Lower Arbitration Register Low +LAR0_4.ID12 7 +LAR0_4.ID11 6 +LAR0_4.ID10 5 +LAR0_4.ID9 4 +LAR0_4.ID8 3 +LAR0_4.ID7 2 +LAR0_4.ID6 1 +LAR0_4.ID5 0 +LAR1_4 0xF745 Lower Arbitration Register High +LAR1_4.ID4 7 +LAR1_4.ID3 6 +LAR1_4.ID2 5 +LAR1_4.ID1 4 +LAR1_4.ID0 3 +MCFG_4 0xF746 Message Configuration Register +MCFG_4.DLC7 7 +MCFG_4.DLC6 6 +MCFG_4.DLC5 5 +MCFG_4.DLC4 4 +MCFG_4.DIR 3 +MCFG_4.XTD 2 +DB0_4 0xF747 Message Data Byte 0 +DB0_4.DB07 7 +DB0_4.DB06 6 +DB0_4.DB05 5 +DB0_4.DB04 4 +DB0_4.DB03 3 +DB0_4.DB02 2 +DB0_4.DB01 1 +DB0_4.DB00 0 +DB1_4 0xF748 Message Data Byte 1 +DB1_4.DB17 7 +DB1_4.DB16 6 +DB1_4.DB15 5 +DB1_4.DB14 4 +DB1_4.DB13 3 +DB1_4.DB12 2 +DB1_4.DB11 1 +DB1_4.DB10 0 +DB2_4 0xF749 Message Data Byte 2 +DB2_4.DB27 7 +DB2_4.DB26 6 +DB2_4.DB25 5 +DB2_4.DB24 4 +DB2_4.DB23 3 +DB2_4.DB22 2 +DB2_4.DB21 1 +DB2_4.DB20 0 +DB3_4 0xF74A Message Data Byte 3 +DB3_4.DB37 7 +DB3_4.DB36 6 +DB3_4.DB35 5 +DB3_4.DB34 4 +DB3_4.DB33 3 +DB3_4.DB32 2 +DB3_4.DB31 1 +DB3_4.DB30 0 +DB4_4 0xF74B Message Data Byte 4 +DB4_4.DB47 7 +DB4_4.DB46 6 +DB4_4.DB45 5 +DB4_4.DB44 4 +DB4_4.DB43 3 +DB4_4.DB42 2 +DB4_4.DB41 1 +DB4_4.DB40 0 +DB5_4 0xF74C Message Data Byte 5 +DB5_4.DB57 7 +DB5_4.DB56 6 +DB5_4.DB55 5 +DB5_4.DB54 4 +DB5_4.DB53 3 +DB5_4.DB52 2 +DB5_4.DB51 1 +DB5_4.DB50 0 +DB6_4 0xF74D Message Data Byte 6 +DB6_4.DB67 7 +DB6_4.DB66 6 +DB6_4.DB65 5 +DB6_4.DB64 4 +DB6_4.DB63 3 +DB6_4.DB62 2 +DB6_4.DB61 1 +DB6_4.DB60 0 +DB7_4 0xF74E Message Data Byte 7 +DB7_4.DB77 7 +DB7_4.DB76 6 +DB7_4.DB75 5 +DB7_4.DB74 4 +DB7_4.DB73 3 +DB7_4.DB72 2 +DB7_4.DB71 1 +DB7_4.DB70 0 +RESERVEDF74F 0xF74F RESERVED +; -------------------------------------- CAN_5 -------------------------------- +MCR0_5 0xF750 Message Control Register Low +MCR0_5.MSGVAL1 7 +MCR0_5.MSGVAL0 6 +MCR0_5.TXIE1 5 +MCR0_5.TXIE0 4 +MCR0_5.RXIE1 3 +MCR0_5.RXIE0 2 +MCR0_5.INTPND1 1 +MCR0_5.INTPND0 0 +MCR1_5 0xF751 Message Control Register High +MCR1_5.RMTPND1 7 +MCR1_5.RMTPND0 6 +MCR1_5.TXRQ1 5 +MCR1_5.TXRQ0 4 +MCR1_5.MSGLSTCPUUPD1 3 +MCR1_5.MSGLSTCPUUPD0 2 +MCR1_5.NEWDAT1 1 +MCR1_5.NEWDAT0 0 +UAR0_5 0xF752 Upper Arbitration Register Low +UAR0_5.ID28 7 +UAR0_5.ID27 6 +UAR0_5.ID26 5 +UAR0_5.ID25 4 +UAR0_5.ID24 3 +UAR0_5.ID23 2 +UAR0_5.ID22 1 +UAR0_5.ID21 0 +UAR1_5 0xF753 Upper Arbitration Register High +UAR1_5.ID20 7 +UAR1_5.ID19 6 +UAR1_5.ID18 5 +UAR1_5.ID17 4 +UAR1_5.ID16 3 +UAR1_5.ID15 2 +UAR1_5.ID14 1 +UAR1_5.ID13 0 +LAR0_5 0xF754 Lower Arbitration Register Low +LAR0_5.ID12 7 +LAR0_5.ID11 6 +LAR0_5.ID10 5 +LAR0_5.ID9 4 +LAR0_5.ID8 3 +LAR0_5.ID7 2 +LAR0_5.ID6 1 +LAR0_5.ID5 0 +LAR1_5 0xF755 Lower Arbitration Register High +LAR1_5.ID4 7 +LAR1_5.ID3 6 +LAR1_5.ID2 5 +LAR1_5.ID1 4 +LAR1_5.ID0 3 +MCFG_5 0xF756 Message Configuration Register +MCFG_5.DLC7 7 +MCFG_5.DLC6 6 +MCFG_5.DLC5 5 +MCFG_5.DLC4 4 +MCFG_5.DIR 3 +MCFG_5.XTD 2 +DB0_5 0xF757 Message Data Byte 0 +DB0_5.DB07 7 +DB0_5.DB06 6 +DB0_5.DB05 5 +DB0_5.DB04 4 +DB0_5.DB03 3 +DB0_5.DB02 2 +DB0_5.DB01 1 +DB0_5.DB00 0 +DB1_5 0xF758 Message Data Byte 1 +DB1_5.DB17 7 +DB1_5.DB16 6 +DB1_5.DB15 5 +DB1_5.DB14 4 +DB1_5.DB13 3 +DB1_5.DB12 2 +DB1_5.DB11 1 +DB1_5.DB10 0 +DB2_5 0xF759 Message Data Byte 2 +DB2_5.DB27 7 +DB2_5.DB26 6 +DB2_5.DB25 5 +DB2_5.DB24 4 +DB2_5.DB23 3 +DB2_5.DB22 2 +DB2_5.DB21 1 +DB2_5.DB20 0 +DB3_5 0xF75A Message Data Byte 3 +DB3_5.DB37 7 +DB3_5.DB36 6 +DB3_5.DB35 5 +DB3_5.DB34 4 +DB3_5.DB33 3 +DB3_5.DB32 2 +DB3_5.DB31 1 +DB3_5.DB30 0 +DB4_5 0xF75B Message Data Byte 4 +DB4_5.DB47 7 +DB4_5.DB46 6 +DB4_5.DB45 5 +DB4_5.DB44 4 +DB4_5.DB43 3 +DB4_5.DB42 2 +DB4_5.DB41 1 +DB4_5.DB40 0 +DB5_5 0xF75C Message Data Byte 5 +DB5_5.DB57 7 +DB5_5.DB56 6 +DB5_5.DB55 5 +DB5_5.DB54 4 +DB5_5.DB53 3 +DB5_5.DB52 2 +DB5_5.DB51 1 +DB5_5.DB50 0 +DB6_5 0xF75D Message Data Byte 6 +DB6_5.DB67 7 +DB6_5.DB66 6 +DB6_5.DB65 5 +DB6_5.DB64 4 +DB6_5.DB63 3 +DB6_5.DB62 2 +DB6_5.DB61 1 +DB6_5.DB60 0 +DB7_5 0xF75E Message Data Byte 7 +DB7_5.DB77 7 +DB7_5.DB76 6 +DB7_5.DB75 5 +DB7_5.DB74 4 +DB7_5.DB73 3 +DB7_5.DB72 2 +DB7_5.DB71 1 +DB7_5.DB70 0 +RESERVEDF75F 0xF75F RESERVED +; -------------------------------------- CAN_6 -------------------------------- +MCR0_6 0xF760 Message Control Register Low +MCR0_6.MSGVAL1 7 +MCR0_6.MSGVAL0 6 +MCR0_6.TXIE1 5 +MCR0_6.TXIE0 4 +MCR0_6.RXIE1 3 +MCR0_6.RXIE0 2 +MCR0_6.INTPND1 1 +MCR0_6.INTPND0 0 +MCR1_6 0xF761 Message Control Register High +MCR1_6.RMTPND1 7 +MCR1_6.RMTPND0 6 +MCR1_6.TXRQ1 5 +MCR1_6.TXRQ0 4 +MCR1_6.MSGLSTCPUUPD1 3 +MCR1_6.MSGLSTCPUUPD0 2 +MCR1_6.NEWDAT1 1 +MCR1_6.NEWDAT0 0 +UAR0_6 0xF762 Upper Arbitration Register Low +UAR0_6.ID28 7 +UAR0_6.ID27 6 +UAR0_6.ID26 5 +UAR0_6.ID25 4 +UAR0_6.ID24 3 +UAR0_6.ID23 2 +UAR0_6.ID22 1 +UAR0_6.ID21 0 +UAR1_6 0xF763 Upper Arbitration Register High +UAR1_6.ID20 7 +UAR1_6.ID19 6 +UAR1_6.ID18 5 +UAR1_6.ID17 4 +UAR1_6.ID16 3 +UAR1_6.ID15 2 +UAR1_6.ID14 1 +UAR1_6.ID13 0 +LAR0_6 0xF764 Lower Arbitration Register Low +LAR0_6.ID12 7 +LAR0_6.ID11 6 +LAR0_6.ID10 5 +LAR0_6.ID9 4 +LAR0_6.ID8 3 +LAR0_6.ID7 2 +LAR0_6.ID6 1 +LAR0_6.ID5 0 +LAR1_6 0xF765 Lower Arbitration Register High +LAR1_6.ID4 7 +LAR1_6.ID3 6 +LAR1_6.ID2 5 +LAR1_6.ID1 4 +LAR1_6.ID0 3 +MCFG_6 0xF766 Message Configuration Register +MCFG_6.DLC7 7 +MCFG_6.DLC6 6 +MCFG_6.DLC5 5 +MCFG_6.DLC4 4 +MCFG_6.DIR 3 +MCFG_6.XTD 2 +DB0_6 0xF767 Message Data Byte 0 +DB0_6.DB07 7 +DB0_6.DB06 6 +DB0_6.DB05 5 +DB0_6.DB04 4 +DB0_6.DB03 3 +DB0_6.DB02 2 +DB0_6.DB01 1 +DB0_6.DB00 0 +DB1_6 0xF768 Message Data Byte 1 +DB1_6.DB17 7 +DB1_6.DB16 6 +DB1_6.DB15 5 +DB1_6.DB14 4 +DB1_6.DB13 3 +DB1_6.DB12 2 +DB1_6.DB11 1 +DB1_6.DB10 0 +DB2_6 0xF769 Message Data Byte 2 +DB2_6.DB27 7 +DB2_6.DB26 6 +DB2_6.DB25 5 +DB2_6.DB24 4 +DB2_6.DB23 3 +DB2_6.DB22 2 +DB2_6.DB21 1 +DB2_6.DB20 0 +DB3_6 0xF76A Message Data Byte 3 +DB3_6.DB37 7 +DB3_6.DB36 6 +DB3_6.DB35 5 +DB3_6.DB34 4 +DB3_6.DB33 3 +DB3_6.DB32 2 +DB3_6.DB31 1 +DB3_6.DB30 0 +DB4_6 0xF76B Message Data Byte 4 +DB4_6.DB47 7 +DB4_6.DB46 6 +DB4_6.DB45 5 +DB4_6.DB44 4 +DB4_6.DB43 3 +DB4_6.DB42 2 +DB4_6.DB41 1 +DB4_6.DB40 0 +DB5_6 0xF76C Message Data Byte 5 +DB5_6.DB57 7 +DB5_6.DB56 6 +DB5_6.DB55 5 +DB5_6.DB54 4 +DB5_6.DB53 3 +DB5_6.DB52 2 +DB5_6.DB51 1 +DB5_6.DB50 0 +DB6_6 0xF76D Message Data Byte 6 +DB6_6.DB67 7 +DB6_6.DB66 6 +DB6_6.DB65 5 +DB6_6.DB64 4 +DB6_6.DB63 3 +DB6_6.DB62 2 +DB6_6.DB61 1 +DB6_6.DB60 0 +DB7_6 0xF76E Message Data Byte 7 +DB7_6.DB77 7 +DB7_6.DB76 6 +DB7_6.DB75 5 +DB7_6.DB74 4 +DB7_6.DB73 3 +DB7_6.DB72 2 +DB7_6.DB71 1 +DB7_6.DB70 0 +RESERVEDF76F 0xF76F RESERVED +; -------------------------------------- CAN_7 -------------------------------- +MCR0_7 0xF770 Message Control Register Low +MCR0_7.MSGVAL1 7 +MCR0_7.MSGVAL0 6 +MCR0_7.TXIE1 5 +MCR0_7.TXIE0 4 +MCR0_7.RXIE1 3 +MCR0_7.RXIE0 2 +MCR0_7.INTPND1 1 +MCR0_7.INTPND0 0 +MCR1_7 0xF771 Message Control Register High +MCR1_7.RMTPND1 7 +MCR1_7.RMTPND0 6 +MCR1_7.TXRQ1 5 +MCR1_7.TXRQ0 4 +MCR1_7.MSGLSTCPUUPD1 3 +MCR1_7.MSGLSTCPUUPD0 2 +MCR1_7.NEWDAT1 1 +MCR1_7.NEWDAT0 0 +UAR0_7 0xF772 Upper Arbitration Register Low +UAR0_7.ID28 7 +UAR0_7.ID27 6 +UAR0_7.ID26 5 +UAR0_7.ID25 4 +UAR0_7.ID24 3 +UAR0_7.ID23 2 +UAR0_7.ID22 1 +UAR0_7.ID21 0 +UAR1_7 0xF773 Upper Arbitration Register High +UAR1_7.ID20 7 +UAR1_7.ID19 6 +UAR1_7.ID18 5 +UAR1_7.ID17 4 +UAR1_7.ID16 3 +UAR1_7.ID15 2 +UAR1_7.ID14 1 +UAR1_7.ID13 0 +LAR0_7 0xF774 Lower Arbitration Register Low +LAR0_7.ID12 7 +LAR0_7.ID11 6 +LAR0_7.ID10 5 +LAR0_7.ID9 4 +LAR0_7.ID8 3 +LAR0_7.ID7 2 +LAR0_7.ID6 1 +LAR0_7.ID5 0 +LAR1_7 0xF775 Lower Arbitration Register High +LAR1_7.ID4 7 +LAR1_7.ID3 6 +LAR1_7.ID2 5 +LAR1_7.ID1 4 +LAR1_7.ID0 3 +MCFG_7 0xF776 Message Configuration Register +MCFG_7.DLC7 7 +MCFG_7.DLC6 6 +MCFG_7.DLC5 5 +MCFG_7.DLC4 4 +MCFG_7.DIR 3 +MCFG_7.XTD 2 +DB0_7 0xF777 Message Data Byte 0 +DB0_7.DB07 7 +DB0_7.DB06 6 +DB0_7.DB05 5 +DB0_7.DB04 4 +DB0_7.DB03 3 +DB0_7.DB02 2 +DB0_7.DB01 1 +DB0_7.DB00 0 +DB1_7 0xF778 Message Data Byte 1 +DB1_7.DB17 7 +DB1_7.DB16 6 +DB1_7.DB15 5 +DB1_7.DB14 4 +DB1_7.DB13 3 +DB1_7.DB12 2 +DB1_7.DB11 1 +DB1_7.DB10 0 +DB2_7 0xF779 Message Data Byte 2 +DB2_7.DB27 7 +DB2_7.DB26 6 +DB2_7.DB25 5 +DB2_7.DB24 4 +DB2_7.DB23 3 +DB2_7.DB22 2 +DB2_7.DB21 1 +DB2_7.DB20 0 +DB3_7 0xF77A Message Data Byte 3 +DB3_7.DB37 7 +DB3_7.DB36 6 +DB3_7.DB35 5 +DB3_7.DB34 4 +DB3_7.DB33 3 +DB3_7.DB32 2 +DB3_7.DB31 1 +DB3_7.DB30 0 +DB4_7 0xF77B Message Data Byte 4 +DB4_7.DB47 7 +DB4_7.DB46 6 +DB4_7.DB45 5 +DB4_7.DB44 4 +DB4_7.DB43 3 +DB4_7.DB42 2 +DB4_7.DB41 1 +DB4_7.DB40 0 +DB5_7 0xF77C Message Data Byte 5 +DB5_7.DB57 7 +DB5_7.DB56 6 +DB5_7.DB55 5 +DB5_7.DB54 4 +DB5_7.DB53 3 +DB5_7.DB52 2 +DB5_7.DB51 1 +DB5_7.DB50 0 +DB6_7 0xF77D Message Data Byte 6 +DB6_7.DB67 7 +DB6_7.DB66 6 +DB6_7.DB65 5 +DB6_7.DB64 4 +DB6_7.DB63 3 +DB6_7.DB62 2 +DB6_7.DB61 1 +DB6_7.DB60 0 +DB7_7 0xF77E Message Data Byte 7 +DB7_7.DB77 7 +DB7_7.DB76 6 +DB7_7.DB75 5 +DB7_7.DB74 4 +DB7_7.DB73 3 +DB7_7.DB72 2 +DB7_7.DB71 1 +DB7_7.DB70 0 +RESERVEDF77F 0xF77F RESERVED +; -------------------------------------- CAN_8 -------------------------------- +MCR0_8 0xF780 Message Control Register Low +MCR0_8.MSGVAL1 7 +MCR0_8.MSGVAL0 6 +MCR0_8.TXIE1 5 +MCR0_8.TXIE0 4 +MCR0_8.RXIE1 3 +MCR0_8.RXIE0 2 +MCR0_8.INTPND1 1 +MCR0_8.INTPND0 0 +MCR1_8 0xF781 Message Control Register High +MCR1_8.RMTPND1 7 +MCR1_8.RMTPND0 6 +MCR1_8.TXRQ1 5 +MCR1_8.TXRQ0 4 +MCR1_8.MSGLSTCPUUPD1 3 +MCR1_8.MSGLSTCPUUPD0 2 +MCR1_8.NEWDAT1 1 +MCR1_8.NEWDAT0 0 +UAR0_8 0xF782 Upper Arbitration Register Low +UAR0_8.ID28 7 +UAR0_8.ID27 6 +UAR0_8.ID26 5 +UAR0_8.ID25 4 +UAR0_8.ID24 3 +UAR0_8.ID23 2 +UAR0_8.ID22 1 +UAR0_8.ID21 0 +UAR1_8 0xF783 Upper Arbitration Register High +UAR1_8.ID20 7 +UAR1_8.ID19 6 +UAR1_8.ID18 5 +UAR1_8.ID17 4 +UAR1_8.ID16 3 +UAR1_8.ID15 2 +UAR1_8.ID14 1 +UAR1_8.ID13 0 +LAR0_8 0xF784 Lower Arbitration Register Low +LAR0_8.ID12 7 +LAR0_8.ID11 6 +LAR0_8.ID10 5 +LAR0_8.ID9 4 +LAR0_8.ID8 3 +LAR0_8.ID7 2 +LAR0_8.ID6 1 +LAR0_8.ID5 0 +LAR1_8 0xF785 Lower Arbitration Register High +LAR1_8.ID4 7 +LAR1_8.ID3 6 +LAR1_8.ID2 5 +LAR1_8.ID1 4 +LAR1_8.ID0 3 +MCFG_8 0xF786 Message Configuration Register +MCFG_8.DLC7 7 +MCFG_8.DLC6 6 +MCFG_8.DLC5 5 +MCFG_8.DLC4 4 +MCFG_8.DIR 3 +MCFG_8.XTD 2 +DB0_8 0xF787 Message Data Byte 0 +DB0_8.DB07 7 +DB0_8.DB06 6 +DB0_8.DB05 5 +DB0_8.DB04 4 +DB0_8.DB03 3 +DB0_8.DB02 2 +DB0_8.DB01 1 +DB0_8.DB00 0 +DB1_8 0xF788 Message Data Byte 1 +DB1_8.DB17 7 +DB1_8.DB16 6 +DB1_8.DB15 5 +DB1_8.DB14 4 +DB1_8.DB13 3 +DB1_8.DB12 2 +DB1_8.DB11 1 +DB1_8.DB10 0 +DB2_8 0xF789 Message Data Byte 2 +DB2_8.DB27 7 +DB2_8.DB26 6 +DB2_8.DB25 5 +DB2_8.DB24 4 +DB2_8.DB23 3 +DB2_8.DB22 2 +DB2_8.DB21 1 +DB2_8.DB20 0 +DB3_8 0xF78A Message Data Byte 3 +DB3_8.DB37 7 +DB3_8.DB36 6 +DB3_8.DB35 5 +DB3_8.DB34 4 +DB3_8.DB33 3 +DB3_8.DB32 2 +DB3_8.DB31 1 +DB3_8.DB30 0 +DB4_8 0xF78B Message Data Byte 4 +DB4_8.DB47 7 +DB4_8.DB46 6 +DB4_8.DB45 5 +DB4_8.DB44 4 +DB4_8.DB43 3 +DB4_8.DB42 2 +DB4_8.DB41 1 +DB4_8.DB40 0 +DB5_8 0xF78C Message Data Byte 5 +DB5_8.DB57 7 +DB5_8.DB56 6 +DB5_8.DB55 5 +DB5_8.DB54 4 +DB5_8.DB53 3 +DB5_8.DB52 2 +DB5_8.DB51 1 +DB5_8.DB50 0 +DB6_8 0xF78D Message Data Byte 6 +DB6_8.DB67 7 +DB6_8.DB66 6 +DB6_8.DB65 5 +DB6_8.DB64 4 +DB6_8.DB63 3 +DB6_8.DB62 2 +DB6_8.DB61 1 +DB6_8.DB60 0 +DB7_8 0xF78E Message Data Byte 7 +DB7_8.DB77 7 +DB7_8.DB76 6 +DB7_8.DB75 5 +DB7_8.DB74 4 +DB7_8.DB73 3 +DB7_8.DB72 2 +DB7_8.DB71 1 +DB7_8.DB70 0 +RESERVEDF78F 0xF78F RESERVED +; -------------------------------------- CAN_9 -------------------------------- +MCR0_9 0xF790 Message Control Register Low +MCR0_9.MSGVAL1 7 +MCR0_9.MSGVAL0 6 +MCR0_9.TXIE1 5 +MCR0_9.TXIE0 4 +MCR0_9.RXIE1 3 +MCR0_9.RXIE0 2 +MCR0_9.INTPND1 1 +MCR0_9.INTPND0 0 +MCR1_9 0xF791 Message Control Register High +MCR1_9.RMTPND1 7 +MCR1_9.RMTPND0 6 +MCR1_9.TXRQ1 5 +MCR1_9.TXRQ0 4 +MCR1_9.MSGLSTCPUUPD1 3 +MCR1_9.MSGLSTCPUUPD0 2 +MCR1_9.NEWDAT1 1 +MCR1_9.NEWDAT0 0 +UAR0_9 0xF792 Upper Arbitration Register Low +UAR0_9.ID28 7 +UAR0_9.ID27 6 +UAR0_9.ID26 5 +UAR0_9.ID25 4 +UAR0_9.ID24 3 +UAR0_9.ID23 2 +UAR0_9.ID22 1 +UAR0_9.ID21 0 +UAR1_9 0xF793 Upper Arbitration Register High +UAR1_9.ID20 7 +UAR1_9.ID19 6 +UAR1_9.ID18 5 +UAR1_9.ID17 4 +UAR1_9.ID16 3 +UAR1_9.ID15 2 +UAR1_9.ID14 1 +UAR1_9.ID13 0 +LAR0_9 0xF794 Lower Arbitration Register Low +LAR0_9.ID12 7 +LAR0_9.ID11 6 +LAR0_9.ID10 5 +LAR0_9.ID9 4 +LAR0_9.ID8 3 +LAR0_9.ID7 2 +LAR0_9.ID6 1 +LAR0_9.ID5 0 +LAR1_9 0xF795 Lower Arbitration Register High +LAR1_9.ID4 7 +LAR1_9.ID3 6 +LAR1_9.ID2 5 +LAR1_9.ID1 4 +LAR1_9.ID0 3 +MCFG_9 0xF796 Message Configuration Register +MCFG_9.DLC7 7 +MCFG_9.DLC6 6 +MCFG_9.DLC5 5 +MCFG_9.DLC4 4 +MCFG_9.DIR 3 +MCFG_9.XTD 2 +DB0_9 0xF797 Message Data Byte 0 +DB0_9.DB07 7 +DB0_9.DB06 6 +DB0_9.DB05 5 +DB0_9.DB04 4 +DB0_9.DB03 3 +DB0_9.DB02 2 +DB0_9.DB01 1 +DB0_9.DB00 0 +DB1_9 0xF798 Message Data Byte 1 +DB1_9.DB17 7 +DB1_9.DB16 6 +DB1_9.DB15 5 +DB1_9.DB14 4 +DB1_9.DB13 3 +DB1_9.DB12 2 +DB1_9.DB11 1 +DB1_9.DB10 0 +DB2_9 0xF799 Message Data Byte 2 +DB2_9.DB27 7 +DB2_9.DB26 6 +DB2_9.DB25 5 +DB2_9.DB24 4 +DB2_9.DB23 3 +DB2_9.DB22 2 +DB2_9.DB21 1 +DB2_9.DB20 0 +DB3_9 0xF79A Message Data Byte 3 +DB3_9.DB37 7 +DB3_9.DB36 6 +DB3_9.DB35 5 +DB3_9.DB34 4 +DB3_9.DB33 3 +DB3_9.DB32 2 +DB3_9.DB31 1 +DB3_9.DB30 0 +DB4_9 0xF79B Message Data Byte 4 +DB4_9.DB47 7 +DB4_9.DB46 6 +DB4_9.DB45 5 +DB4_9.DB44 4 +DB4_9.DB43 3 +DB4_9.DB42 2 +DB4_9.DB41 1 +DB4_9.DB40 0 +DB5_9 0xF79C Message Data Byte 5 +DB5_9.DB57 7 +DB5_9.DB56 6 +DB5_9.DB55 5 +DB5_9.DB54 4 +DB5_9.DB53 3 +DB5_9.DB52 2 +DB5_9.DB51 1 +DB5_9.DB50 0 +DB6_9 0xF79D Message Data Byte 6 +DB6_9.DB67 7 +DB6_9.DB66 6 +DB6_9.DB65 5 +DB6_9.DB64 4 +DB6_9.DB63 3 +DB6_9.DB62 2 +DB6_9.DB61 1 +DB6_9.DB60 0 +DB7_9 0xF79E Message Data Byte 7 +DB7_9.DB77 7 +DB7_9.DB76 6 +DB7_9.DB75 5 +DB7_9.DB74 4 +DB7_9.DB73 3 +DB7_9.DB72 2 +DB7_9.DB71 1 +DB7_9.DB70 0 +RESERVEDF79F 0xF79F RESERVED +; -------------------------------------- CAN_A -------------------------------- +MCR0_A 0xF7A0 Message Control Register Low +MCR0_A.MSGVAL1 7 +MCR0_A.MSGVAL0 6 +MCR0_A.TXIE1 5 +MCR0_A.TXIE0 4 +MCR0_A.RXIE1 3 +MCR0_A.RXIE0 2 +MCR0_A.INTPND1 1 +MCR0_A.INTPND0 0 +MCR1_A 0xF7A1 Message Control Register High +MCR1_A.RMTPND1 7 +MCR1_A.RMTPND0 6 +MCR1_A.TXRQ1 5 +MCR1_A.TXRQ0 4 +MCR1_A.MSGLSTCPUUPD1 3 +MCR1_A.MSGLSTCPUUPD0 2 +MCR1_A.NEWDAT1 1 +MCR1_A.NEWDAT0 0 +UAR0_A 0xF7A2 Upper Arbitration Register Low +UAR0_A.ID28 7 +UAR0_A.ID27 6 +UAR0_A.ID26 5 +UAR0_A.ID25 4 +UAR0_A.ID24 3 +UAR0_A.ID23 2 +UAR0_A.ID22 1 +UAR0_A.ID21 0 +UAR1_A 0xF7A3 Upper Arbitration Register High +UAR1_A.ID20 7 +UAR1_A.ID19 6 +UAR1_A.ID18 5 +UAR1_A.ID17 4 +UAR1_A.ID16 3 +UAR1_A.ID15 2 +UAR1_A.ID14 1 +UAR1_A.ID13 0 +LAR0_A 0xF7A4 Lower Arbitration Register Low +LAR0_A.ID12 7 +LAR0_A.ID11 6 +LAR0_A.ID10 5 +LAR0_A.ID9 4 +LAR0_A.ID8 3 +LAR0_A.ID7 2 +LAR0_A.ID6 1 +LAR0_A.ID5 0 +LAR1_A 0xF7A5 Lower Arbitration Register High +LAR1_A.ID4 7 +LAR1_A.ID3 6 +LAR1_A.ID2 5 +LAR1_A.ID1 4 +LAR1_A.ID0 3 +MCFG_A 0xF7A6 Message Configuration Register +MCFG_A.DLC7 7 +MCFG_A.DLC6 6 +MCFG_A.DLC5 5 +MCFG_A.DLC4 4 +MCFG_A.DIR 3 +MCFG_A.XTD 2 +DB0_A 0xF7A7 Message Data Byte 0 +DB0_A.DB07 7 +DB0_A.DB06 6 +DB0_A.DB05 5 +DB0_A.DB04 4 +DB0_A.DB03 3 +DB0_A.DB02 2 +DB0_A.DB01 1 +DB0_A.DB00 0 +DB1_A 0xF7A8 Message Data Byte 1 +DB1_A.DB17 7 +DB1_A.DB16 6 +DB1_A.DB15 5 +DB1_A.DB14 4 +DB1_A.DB13 3 +DB1_A.DB12 2 +DB1_A.DB11 1 +DB1_A.DB10 0 +DB2_A 0xF7A9 Message Data Byte 2 +DB2_A.DB27 7 +DB2_A.DB26 6 +DB2_A.DB25 5 +DB2_A.DB24 4 +DB2_A.DB23 3 +DB2_A.DB22 2 +DB2_A.DB21 1 +DB2_A.DB20 0 +DB3_A 0xF7AA Message Data Byte 3 +DB3_A.DB37 7 +DB3_A.DB36 6 +DB3_A.DB35 5 +DB3_A.DB34 4 +DB3_A.DB33 3 +DB3_A.DB32 2 +DB3_A.DB31 1 +DB3_A.DB30 0 +DB4_A 0xF7AB Message Data Byte 4 +DB4_A.DB47 7 +DB4_A.DB46 6 +DB4_A.DB45 5 +DB4_A.DB44 4 +DB4_A.DB43 3 +DB4_A.DB42 2 +DB4_A.DB41 1 +DB4_A.DB40 0 +DB5_A 0xF7AC Message Data Byte 5 +DB5_A.DB57 7 +DB5_A.DB56 6 +DB5_A.DB55 5 +DB5_A.DB54 4 +DB5_A.DB53 3 +DB5_A.DB52 2 +DB5_A.DB51 1 +DB5_A.DB50 0 +DB6_A 0xF7AD Message Data Byte 6 +DB6_A.DB67 7 +DB6_A.DB66 6 +DB6_A.DB65 5 +DB6_A.DB64 4 +DB6_A.DB63 3 +DB6_A.DB62 2 +DB6_A.DB61 1 +DB6_A.DB60 0 +DB7_A 0xF7AE Message Data Byte 7 +DB7_A.DB77 7 +DB7_A.DB76 6 +DB7_A.DB75 5 +DB7_A.DB74 4 +DB7_A.DB73 3 +DB7_A.DB72 2 +DB7_A.DB71 1 +DB7_A.DB70 0 +RESERVEDF7AF 0xF7AF RESERVED +; -------------------------------------- CAN_B -------------------------------- +MCR0_B 0xF7B0 Message Control Register Low +MCR0_B.MSGVAL1 7 +MCR0_B.MSGVAL0 6 +MCR0_B.TXIE1 5 +MCR0_B.TXIE0 4 +MCR0_B.RXIE1 3 +MCR0_B.RXIE0 2 +MCR0_B.INTPND1 1 +MCR0_B.INTPND0 0 +MCR1_B 0xF7B1 Message Control Register High +MCR1_B.RMTPND1 7 +MCR1_B.RMTPND0 6 +MCR1_B.TXRQ1 5 +MCR1_B.TXRQ0 4 +MCR1_B.MSGLSTCPUUPD1 3 +MCR1_B.MSGLSTCPUUPD0 2 +MCR1_B.NEWDAT1 1 +MCR1_B.NEWDAT0 0 +UAR0_B 0xF7B2 Upper Arbitration Register Low +UAR0_B.ID28 7 +UAR0_B.ID27 6 +UAR0_B.ID26 5 +UAR0_B.ID25 4 +UAR0_B.ID24 3 +UAR0_B.ID23 2 +UAR0_B.ID22 1 +UAR0_B.ID21 0 +UAR1_B 0xF7B3 Upper Arbitration Register High +UAR1_B.ID20 7 +UAR1_B.ID19 6 +UAR1_B.ID18 5 +UAR1_B.ID17 4 +UAR1_B.ID16 3 +UAR1_B.ID15 2 +UAR1_B.ID14 1 +UAR1_B.ID13 0 +LAR0_B 0xF7B4 Lower Arbitration Register Low +LAR0_B.ID12 7 +LAR0_B.ID11 6 +LAR0_B.ID10 5 +LAR0_B.ID9 4 +LAR0_B.ID8 3 +LAR0_B.ID7 2 +LAR0_B.ID6 1 +LAR0_B.ID5 0 +LAR1_B 0xF7B5 Lower Arbitration Register High +LAR1_B.ID4 7 +LAR1_B.ID3 6 +LAR1_B.ID2 5 +LAR1_B.ID1 4 +LAR1_B.ID0 3 +MCFG_B 0xF7B6 Message Configuration Register +MCFG_B.DLC7 7 +MCFG_B.DLC6 6 +MCFG_B.DLC5 5 +MCFG_B.DLC4 4 +MCFG_B.DIR 3 +MCFG_B.XTD 2 +DB0_B 0xF7B7 Message Data Byte 0 +DB0_B.DB07 7 +DB0_B.DB06 6 +DB0_B.DB05 5 +DB0_B.DB04 4 +DB0_B.DB03 3 +DB0_B.DB02 2 +DB0_B.DB01 1 +DB0_B.DB00 0 +DB1_B 0xF7B8 Message Data Byte 1 +DB1_B.DB17 7 +DB1_B.DB16 6 +DB1_B.DB15 5 +DB1_B.DB14 4 +DB1_B.DB13 3 +DB1_B.DB12 2 +DB1_B.DB11 1 +DB1_B.DB10 0 +DB2_B 0xF7B9 Message Data Byte 2 +DB2_B.DB27 7 +DB2_B.DB26 6 +DB2_B.DB25 5 +DB2_B.DB24 4 +DB2_B.DB23 3 +DB2_B.DB22 2 +DB2_B.DB21 1 +DB2_B.DB20 0 +DB3_B 0xF7BA Message Data Byte 3 +DB3_B.DB37 7 +DB3_B.DB36 6 +DB3_B.DB35 5 +DB3_B.DB34 4 +DB3_B.DB33 3 +DB3_B.DB32 2 +DB3_B.DB31 1 +DB3_B.DB30 0 +DB4_B 0xF7BB Message Data Byte 4 +DB4_B.DB47 7 +DB4_B.DB46 6 +DB4_B.DB45 5 +DB4_B.DB44 4 +DB4_B.DB43 3 +DB4_B.DB42 2 +DB4_B.DB41 1 +DB4_B.DB40 0 +DB5_B 0xF7BC Message Data Byte 5 +DB5_B.DB57 7 +DB5_B.DB56 6 +DB5_B.DB55 5 +DB5_B.DB54 4 +DB5_B.DB53 3 +DB5_B.DB52 2 +DB5_B.DB51 1 +DB5_B.DB50 0 +DB6_B 0xF7BD Message Data Byte 6 +DB6_B.DB67 7 +DB6_B.DB66 6 +DB6_B.DB65 5 +DB6_B.DB64 4 +DB6_B.DB63 3 +DB6_B.DB62 2 +DB6_B.DB61 1 +DB6_B.DB60 0 +DB7_B 0xF7BE Message Data Byte 7 +DB7_B.DB77 7 +DB7_B.DB76 6 +DB7_B.DB75 5 +DB7_B.DB74 4 +DB7_B.DB73 3 +DB7_B.DB72 2 +DB7_B.DB71 1 +DB7_B.DB70 0 +RESERVEDF7BF 0xF7BF RESERVED +; -------------------------------------- CAN_C -------------------------------- +MCR0_C 0xF7C0 Message Control Register Low +MCR0_C.MSGVAL1 7 +MCR0_C.MSGVAL0 6 +MCR0_C.TXIE1 5 +MCR0_C.TXIE0 4 +MCR0_C.RXIE1 3 +MCR0_C.RXIE0 2 +MCR0_C.INTPND1 1 +MCR0_C.INTPND0 0 +MCR1_C 0xF7C1 Message Control Register High +MCR1_C.RMTPND1 7 +MCR1_C.RMTPND0 6 +MCR1_C.TXRQ1 5 +MCR1_C.TXRQ0 4 +MCR1_C.MSGLSTCPUUPD1 3 +MCR1_C.MSGLSTCPUUPD0 2 +MCR1_C.NEWDAT1 1 +MCR1_C.NEWDAT0 0 +UAR0_C 0xF7C2 Upper Arbitration Register Low +UAR0_C.ID28 7 +UAR0_C.ID27 6 +UAR0_C.ID26 5 +UAR0_C.ID25 4 +UAR0_C.ID24 3 +UAR0_C.ID23 2 +UAR0_C.ID22 1 +UAR0_C.ID21 0 +UAR1_C 0xF7C3 Upper Arbitration Register High +UAR1_C.ID20 7 +UAR1_C.ID19 6 +UAR1_C.ID18 5 +UAR1_C.ID17 4 +UAR1_C.ID16 3 +UAR1_C.ID15 2 +UAR1_C.ID14 1 +UAR1_C.ID13 0 +LAR0_C 0xF7C4 Lower Arbitration Register Low +LAR0_C.ID12 7 +LAR0_C.ID11 6 +LAR0_C.ID10 5 +LAR0_C.ID9 4 +LAR0_C.ID8 3 +LAR0_C.ID7 2 +LAR0_C.ID6 1 +LAR0_C.ID5 0 +LAR1_C 0xF7C5 Lower Arbitration Register High +LAR1_C.ID4 7 +LAR1_C.ID3 6 +LAR1_C.ID2 5 +LAR1_C.ID1 4 +LAR1_C.ID0 3 +MCFG_C 0xF7C6 Message Configuration Register +MCFG_C.DLC7 7 +MCFG_C.DLC6 6 +MCFG_C.DLC5 5 +MCFG_C.DLC4 4 +MCFG_C.DIR 3 +MCFG_C.XTD 2 +DB0_C 0xF7C7 Message Data Byte 0 +DB0_C.DB07 7 +DB0_C.DB06 6 +DB0_C.DB05 5 +DB0_C.DB04 4 +DB0_C.DB03 3 +DB0_C.DB02 2 +DB0_C.DB01 1 +DB0_C.DB00 0 +DB1_C 0xF7C8 Message Data Byte 1 +DB1_C.DB17 7 +DB1_C.DB16 6 +DB1_C.DB15 5 +DB1_C.DB14 4 +DB1_C.DB13 3 +DB1_C.DB12 2 +DB1_C.DB11 1 +DB1_C.DB10 0 +DB2_C 0xF7C9 Message Data Byte 2 +DB2_C.DB27 7 +DB2_C.DB26 6 +DB2_C.DB25 5 +DB2_C.DB24 4 +DB2_C.DB23 3 +DB2_C.DB22 2 +DB2_C.DB21 1 +DB2_C.DB20 0 +DB3_C 0xF7CA Message Data Byte 3 +DB3_C.DB37 7 +DB3_C.DB36 6 +DB3_C.DB35 5 +DB3_C.DB34 4 +DB3_C.DB33 3 +DB3_C.DB32 2 +DB3_C.DB31 1 +DB3_C.DB30 0 +DB4_C 0xF7CB Message Data Byte 4 +DB4_C.DB47 7 +DB4_C.DB46 6 +DB4_C.DB45 5 +DB4_C.DB44 4 +DB4_C.DB43 3 +DB4_C.DB42 2 +DB4_C.DB41 1 +DB4_C.DB40 0 +DB5_C 0xF7CC Message Data Byte 5 +DB5_C.DB57 7 +DB5_C.DB56 6 +DB5_C.DB55 5 +DB5_C.DB54 4 +DB5_C.DB53 3 +DB5_C.DB52 2 +DB5_C.DB51 1 +DB5_C.DB50 0 +DB6_C 0xF7CD Message Data Byte 6 +DB6_C.DB67 7 +DB6_C.DB66 6 +DB6_C.DB65 5 +DB6_C.DB64 4 +DB6_C.DB63 3 +DB6_C.DB62 2 +DB6_C.DB61 1 +DB6_C.DB60 0 +DB7_C 0xF7CE Message Data Byte 7 +DB7_C.DB77 7 +DB7_C.DB76 6 +DB7_C.DB75 5 +DB7_C.DB74 4 +DB7_C.DB73 3 +DB7_C.DB72 2 +DB7_C.DB71 1 +DB7_C.DB70 0 +RESERVEDF7CF 0xF7CF RESERVED +; -------------------------------------- CAN_D -------------------------------- +MCR0_D 0xF7D0 Message Control Register Low +MCR0_D.MSGVAL1 7 +MCR0_D.MSGVAL0 6 +MCR0_D.TXIE1 5 +MCR0_D.TXIE0 4 +MCR0_D.RXIE1 3 +MCR0_D.RXIE0 2 +MCR0_D.INTPND1 1 +MCR0_D.INTPND0 0 +MCR1_D 0xF7D1 Message Control Register High +MCR1_D.RMTPND1 7 +MCR1_D.RMTPND0 6 +MCR1_D.TXRQ1 5 +MCR1_D.TXRQ0 4 +MCR1_D.MSGLSTCPUUPD1 3 +MCR1_D.MSGLSTCPUUPD0 2 +MCR1_D.NEWDAT1 1 +MCR1_D.NEWDAT0 0 +UAR0_D 0xF7D2 Upper Arbitration Register Low +UAR0_D.ID28 7 +UAR0_D.ID27 6 +UAR0_D.ID26 5 +UAR0_D.ID25 4 +UAR0_D.ID24 3 +UAR0_D.ID23 2 +UAR0_D.ID22 1 +UAR0_D.ID21 0 +UAR1_D 0xF7D3 Upper Arbitration Register High +UAR1_D.ID20 7 +UAR1_D.ID19 6 +UAR1_D.ID18 5 +UAR1_D.ID17 4 +UAR1_D.ID16 3 +UAR1_D.ID15 2 +UAR1_D.ID14 1 +UAR1_D.ID13 0 +LAR0_D 0xF7D4 Lower Arbitration Register Low +LAR0_D.ID12 7 +LAR0_D.ID11 6 +LAR0_D.ID10 5 +LAR0_D.ID9 4 +LAR0_D.ID8 3 +LAR0_D.ID7 2 +LAR0_D.ID6 1 +LAR0_D.ID5 0 +LAR1_D 0xF7D5 Lower Arbitration Register High +LAR1_D.ID4 7 +LAR1_D.ID3 6 +LAR1_D.ID2 5 +LAR1_D.ID1 4 +LAR1_D.ID0 3 +MCFG_D 0xF7D6 Message Configuration Register +MCFG_D.DLC7 7 +MCFG_D.DLC6 6 +MCFG_D.DLC5 5 +MCFG_D.DLC4 4 +MCFG_D.DIR 3 +MCFG_D.XTD 2 +DB0_D 0xF7D7 Message Data Byte 0 +DB0_D.DB07 7 +DB0_D.DB06 6 +DB0_D.DB05 5 +DB0_D.DB04 4 +DB0_D.DB03 3 +DB0_D.DB02 2 +DB0_D.DB01 1 +DB0_D.DB00 0 +DB1_D 0xF7D8 Message Data Byte 1 +DB1_D.DB17 7 +DB1_D.DB16 6 +DB1_D.DB15 5 +DB1_D.DB14 4 +DB1_D.DB13 3 +DB1_D.DB12 2 +DB1_D.DB11 1 +DB1_D.DB10 0 +DB2_D 0xF7D9 Message Data Byte 2 +DB2_D.DB27 7 +DB2_D.DB26 6 +DB2_D.DB25 5 +DB2_D.DB24 4 +DB2_D.DB23 3 +DB2_D.DB22 2 +DB2_D.DB21 1 +DB2_D.DB20 0 +DB3_D 0xF7DA Message Data Byte 3 +DB3_D.DB37 7 +DB3_D.DB36 6 +DB3_D.DB35 5 +DB3_D.DB34 4 +DB3_D.DB33 3 +DB3_D.DB32 2 +DB3_D.DB31 1 +DB3_D.DB30 0 +DB4_D 0xF7DB Message Data Byte 4 +DB4_D.DB47 7 +DB4_D.DB46 6 +DB4_D.DB45 5 +DB4_D.DB44 4 +DB4_D.DB43 3 +DB4_D.DB42 2 +DB4_D.DB41 1 +DB4_D.DB40 0 +DB5_D 0xF7DC Message Data Byte 5 +DB5_D.DB57 7 +DB5_D.DB56 6 +DB5_D.DB55 5 +DB5_D.DB54 4 +DB5_D.DB53 3 +DB5_D.DB52 2 +DB5_D.DB51 1 +DB5_D.DB50 0 +DB6_D 0xF7DD Message Data Byte 6 +DB6_D.DB67 7 +DB6_D.DB66 6 +DB6_D.DB65 5 +DB6_D.DB64 4 +DB6_D.DB63 3 +DB6_D.DB62 2 +DB6_D.DB61 1 +DB6_D.DB60 0 +DB7_D 0xF7DE Message Data Byte 7 +DB7_D.DB77 7 +DB7_D.DB76 6 +DB7_D.DB75 5 +DB7_D.DB74 4 +DB7_D.DB73 3 +DB7_D.DB72 2 +DB7_D.DB71 1 +DB7_D.DB70 0 +RESERVEDF7DF 0xF7DF RESERVED +; -------------------------------------- CAN_E -------------------------------- +MCR0_E 0xF7E0 Message Control Register Low +MCR0_E.MSGVAL1 7 +MCR0_E.MSGVAL0 6 +MCR0_E.TXIE1 5 +MCR0_E.TXIE0 4 +MCR0_E.RXIE1 3 +MCR0_E.RXIE0 2 +MCR0_E.INTPND1 1 +MCR0_E.INTPND0 0 +MCR1_E 0xF7E1 Message Control Register High +MCR1_E.RMTPND1 7 +MCR1_E.RMTPND0 6 +MCR1_E.TXRQ1 5 +MCR1_E.TXRQ0 4 +MCR1_E.MSGLSTCPUUPD1 3 +MCR1_E.MSGLSTCPUUPD0 2 +MCR1_E.NEWDAT1 1 +MCR1_E.NEWDAT0 0 +UAR0_E 0xF7E2 Upper Arbitration Register Low +UAR0_E.ID28 7 +UAR0_E.ID27 6 +UAR0_E.ID26 5 +UAR0_E.ID25 4 +UAR0_E.ID24 3 +UAR0_E.ID23 2 +UAR0_E.ID22 1 +UAR0_E.ID21 0 +UAR1_E 0xF7E3 Upper Arbitration Register High +UAR1_E.ID20 7 +UAR1_E.ID19 6 +UAR1_E.ID18 5 +UAR1_E.ID17 4 +UAR1_E.ID16 3 +UAR1_E.ID15 2 +UAR1_E.ID14 1 +UAR1_E.ID13 0 +LAR0_E 0xF7E4 Lower Arbitration Register Low +LAR0_E.ID12 7 +LAR0_E.ID11 6 +LAR0_E.ID10 5 +LAR0_E.ID9 4 +LAR0_E.ID8 3 +LAR0_E.ID7 2 +LAR0_E.ID6 1 +LAR0_E.ID5 0 +LAR1_E 0xF7E5 Lower Arbitration Register High +LAR1_E.ID4 7 +LAR1_E.ID3 6 +LAR1_E.ID2 5 +LAR1_E.ID1 4 +LAR1_E.ID0 3 +MCFG_E 0xF7E6 Message Configuration Register +MCFG_E.DLC7 7 +MCFG_E.DLC6 6 +MCFG_E.DLC5 5 +MCFG_E.DLC4 4 +MCFG_E.DIR 3 +MCFG_E.XTD 2 +DB0_E 0xF7E7 Message Data Byte 0 +DB0_E.DB07 7 +DB0_E.DB06 6 +DB0_E.DB05 5 +DB0_E.DB04 4 +DB0_E.DB03 3 +DB0_E.DB02 2 +DB0_E.DB01 1 +DB0_E.DB00 0 +DB1_E 0xF7E8 Message Data Byte 1 +DB1_E.DB17 7 +DB1_E.DB16 6 +DB1_E.DB15 5 +DB1_E.DB14 4 +DB1_E.DB13 3 +DB1_E.DB12 2 +DB1_E.DB11 1 +DB1_E.DB10 0 +DB2_E 0xF7E9 Message Data Byte 2 +DB2_E.DB27 7 +DB2_E.DB26 6 +DB2_E.DB25 5 +DB2_E.DB24 4 +DB2_E.DB23 3 +DB2_E.DB22 2 +DB2_E.DB21 1 +DB2_E.DB20 0 +DB3_E 0xF7EA Message Data Byte 3 +DB3_E.DB37 7 +DB3_E.DB36 6 +DB3_E.DB35 5 +DB3_E.DB34 4 +DB3_E.DB33 3 +DB3_E.DB32 2 +DB3_E.DB31 1 +DB3_E.DB30 0 +DB4_E 0xF7EB Message Data Byte 4 +DB4_E.DB47 7 +DB4_E.DB46 6 +DB4_E.DB45 5 +DB4_E.DB44 4 +DB4_E.DB43 3 +DB4_E.DB42 2 +DB4_E.DB41 1 +DB4_E.DB40 0 +DB5_E 0xF7EC Message Data Byte 5 +DB5_E.DB57 7 +DB5_E.DB56 6 +DB5_E.DB55 5 +DB5_E.DB54 4 +DB5_E.DB53 3 +DB5_E.DB52 2 +DB5_E.DB51 1 +DB5_E.DB50 0 +DB6_E 0xF7ED Message Data Byte 6 +DB6_E.DB67 7 +DB6_E.DB66 6 +DB6_E.DB65 5 +DB6_E.DB64 4 +DB6_E.DB63 3 +DB6_E.DB62 2 +DB6_E.DB61 1 +DB6_E.DB60 0 +DB7_E 0xF7DE Message Data Byte 7 +DB7_E.DB77 7 +DB7_E.DB76 6 +DB7_E.DB75 5 +DB7_E.DB74 4 +DB7_E.DB73 3 +DB7_E.DB72 2 +DB7_E.DB71 1 +DB7_E.DB70 0 +RESERVEDF7EF 0xF7EF RESERVED +; -------------------------------------- CAN_F -------------------------------- +MCR0_F 0xF7F0 Message Control Register Low +MCR0_F.MSGVAL1 7 +MCR0_F.MSGVAL0 6 +MCR0_F.TXIE1 5 +MCR0_F.TXIE0 4 +MCR0_F.RXIE1 3 +MCR0_F.RXIE0 2 +MCR0_F.INTPND1 1 +MCR0_F.INTPND0 0 +MCR1_F 0xF7F1 Message Control Register High +MCR1_F.RMTPND1 7 +MCR1_F.RMTPND0 6 +MCR1_F.TXRQ1 5 +MCR1_F.TXRQ0 4 +MCR1_F.MSGLSTCPUUPD1 3 +MCR1_F.MSGLSTCPUUPD0 2 +MCR1_F.NEWDAT1 1 +MCR1_F.NEWDAT0 0 +UAR0_F 0xF7F2 Upper Arbitration Register Low +UAR0_F.ID28 7 +UAR0_F.ID27 6 +UAR0_F.ID26 5 +UAR0_F.ID25 4 +UAR0_F.ID24 3 +UAR0_F.ID23 2 +UAR0_F.ID22 1 +UAR0_F.ID21 0 +UAR1_F 0xF7F3 Upper Arbitration Register High +UAR1_F.ID20 7 +UAR1_F.ID19 6 +UAR1_F.ID18 5 +UAR1_F.ID17 4 +UAR1_F.ID16 3 +UAR1_F.ID15 2 +UAR1_F.ID14 1 +UAR1_F.ID13 0 +LAR0_F 0xF7F4 Lower Arbitration Register Low +LAR0_F.ID12 7 +LAR0_F.ID11 6 +LAR0_F.ID10 5 +LAR0_F.ID9 4 +LAR0_F.ID8 3 +LAR0_F.ID7 2 +LAR0_F.ID6 1 +LAR0_F.ID5 0 +LAR1_F 0xF7F5 Lower Arbitration Register High +LAR1_F.ID4 7 +LAR1_F.ID3 6 +LAR1_F.ID2 5 +LAR1_F.ID1 4 +LAR1_F.ID0 3 +MCFG_F 0xF7F6 Message Configuration Register +MCFG_F.DLC7 7 +MCFG_F.DLC6 6 +MCFG_F.DLC5 5 +MCFG_F.DLC4 4 +MCFG_F.DIR 3 +MCFG_F.XTD 2 +DB0_F 0xF7F7 Message Data Byte 0 +DB0_F.DB07 7 +DB0_F.DB06 6 +DB0_F.DB05 5 +DB0_F.DB04 4 +DB0_F.DB03 3 +DB0_F.DB02 2 +DB0_F.DB01 1 +DB0_F.DB00 0 +DB1_F 0xF7F8 Message Data Byte 1 +DB1_F.DB17 7 +DB1_F.DB16 6 +DB1_F.DB15 5 +DB1_F.DB14 4 +DB1_F.DB13 3 +DB1_F.DB12 2 +DB1_F.DB11 1 +DB1_F.DB10 0 +DB2_F 0xF7F9 Message Data Byte 2 +DB2_F.DB27 7 +DB2_F.DB26 6 +DB2_F.DB25 5 +DB2_F.DB24 4 +DB2_F.DB23 3 +DB2_F.DB22 2 +DB2_F.DB21 1 +DB2_F.DB20 0 +DB3_F 0xF7FA Message Data Byte 3 +DB3_F.DB37 7 +DB3_F.DB36 6 +DB3_F.DB35 5 +DB3_F.DB34 4 +DB3_F.DB33 3 +DB3_F.DB32 2 +DB3_F.DB31 1 +DB3_F.DB30 0 +DB4_F 0xF7FB Message Data Byte 4 +DB4_F.DB47 7 +DB4_F.DB46 6 +DB4_F.DB45 5 +DB4_F.DB44 4 +DB4_F.DB43 3 +DB4_F.DB42 2 +DB4_F.DB41 1 +DB4_F.DB40 0 +DB5_F 0xF7FC Message Data Byte 5 +DB5_F.DB57 7 +DB5_F.DB56 6 +DB5_F.DB55 5 +DB5_F.DB54 4 +DB5_F.DB53 3 +DB5_F.DB52 2 +DB5_F.DB51 1 +DB5_F.DB50 0 +DB6_F 0xF7FD Message Data Byte 6 +DB6_F.DB67 7 +DB6_F.DB66 6 +DB6_F.DB65 5 +DB6_F.DB64 4 +DB6_F.DB63 3 +DB6_F.DB62 2 +DB6_F.DB61 1 +DB6_F.DB60 0 +DB7_F 0xF7FE Message Data Byte 7 +DB7_F.DB77 7 +DB7_F.DB76 6 +DB7_F.DB75 5 +DB7_F.DB74 4 +DB7_F.DB73 3 +DB7_F.DB72 2 +DB7_F.DB71 1 +DB7_F.DB70 0 +RESERVEDF7FF 0xF7FF RESERVED + + +.C517 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=10484&parent_oid=13739 +; SAB_80C537.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI0_TI0 0x0023 Serial channel 0 +entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload +entry IADC 0x0043 A/D converter +entry IEX2 0x004B External interrupt 2 +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry RI1_TI1 0x0083 Serial channel 1 +entry CTF 0x009B Compare timer overflow + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +SP 0x0081 Stack Pointer +DPL 0x0082 Data Pointer, Low Byte +DPH 0x0083 Data Pointer, High Byte +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Reg. +PCON 0x0087 Power Control Register +TCON 0x0088 Timer Control Register +TMOD 0x0089 Timer Mode Register +TL0 0x008A Timer 0, Low Byte +TL1 0x008B Timer 1, Low Byte +TH0 0x008C Timer 0, High Byte +TH1 0x008D Timer 1, High Byte +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +RESERVED0091 0x0091 RESERVED +DPSEL 0x0092 Data Pointer Select Register +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +S0CON 0x0098 Serial Channel 0 Control Reg. +S0BUF 0x0099 Serial Channel 0 Buffer Reg. +IEN2 0x009A Interrupt Enable Register 2 +S1CON 0x009B Serial Channel 1 Control Reg. +S1BUF 0x009C Serial Channel 1 Buffer Reg., +S1REL 0x009D Serial Channel 1 Reload Reg., low byte +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IP0 0x00A9 Interrupt Priority Register 0 +S0RELL 0x00AA Serial Channel 0, Reload Reg., low byte +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +RESERVED00B1 0x00B1 RESERVED +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IP1 0x00B9 Interrupt Priority Register 1 +S0RELH 0x00BA Serial Channel 0, Reload Reg., high byte +S1RELH 0x00BB Serial Channel 1, Reload Reg.,high byte +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +CCEN 0x00C1 Comp./Capture Enable Reg. +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +T2CON 0x00C8 Timer 2 Control Register +CC4EN 0x00C9 Comp./Capture Enable 4 Reg. +CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte +CRCH 0x00CB Com./Rel./Capt. Reg. High Byte +TL2 0x00CC Timer 2, Low Byte +TH2 0x00CD Timer 2, High Byte +CCL4 0x00CE Comp./Capture Reg. 4, Low Byte +CCH4 0x00CF Comp./Capture Reg. 4, High Byte +PSW 0x00D0 Program Status Word Register +RESERVED00D1 0x00D1 RESERVED +CML0 0x00D2 Compare Register 0, Low Byte +CMH0 0x00D3 Compare Register 0, High Byte +CML1 0x00D4 Compare Register 1, Low Byte +CMH1 0x00D5 Compare Register 1, High Byte +CML2 0x00D6 Compare Register 2, Low Byte +CMH2 0x00D7 Compare Register 2, High Byte +ADCON0 0x00D8 A/D Converter Control Register 0 +ADDAT 0x00D9 A/D Converter Data Register +DAPR 0x00DA D/AConverter Program Register +P7 0x00DB Port 7, Analog/Digital Input +ADCON1 0x00DC A/D Converter Control Register 1 +P8 0x00DD Port 8, Analog/Digital Input, 4-bit 0DD +CTRELL 0x00DE Com. Timer Rel. Reg., Low Byte +CTRELH 0x00DF Com. Timer Rel. Reg., High Byte +ACC 0x00E0 Accumulator +CTCON 0x00E1 Com. Timer Control Register +CML3 0x00E2 Compare Register 3, Low Byte +CMH3 0x00E3 Compare Register 3, High Byte +CML4 0x00E4 Compare Register 4, Low Byte +CMH4 0x00E5 Compare Register 4, High Byte +CML5 0x00E6 Compare Register 5, Low Byte +CMH5 0x00E7 Compare Register 5, High Byte +P4 0x00E8 Port 4 +MD0 0x00E9 Multiplication/Division Register 0 +MD1 0x00EA Multiplication/Division Register 1 +MD2 0x00EB Multiplication/Division Register 2 +MD3 0x00EC Multiplication/Division Register 3 +MD4 0x00ED Multiplication/Division Register 4 +MD5 0x00EE Multiplication/Division Register 5 +ARCON 0x00EF Arithmetic Control Register +B 0x00F0 B-Register +RESERVED00F1 0x00F1 RESERVED +CML6 0x00F2 Compare Register 6, Low Byte +CMH6 0x00F3 Compare Register 6, High Byte +CML7 0x00F4 Compare Register 7, Low Byte +CMH7 0x00F5 Compare Register 7, High Byte +CMEN 0x00F6 Compare Enable Register +CMSEL 0x00F7 Compare Input Select +P5 0x00F8 Port 5 +RESERVED00F9 0x00F9 RESERVED +P6 0x00FA Port 6 +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C517A +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=8041&parent_oid=14402 +; SAF-C517A-LN.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI0_TI0 0x0023 Serial channel 0 +entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload +entry IADC 0x0043 A/D converter +entry IEX2 0x004B External interrupt 2 +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry RI1_TI1 0x0083 Serial channel 1 +entry ICMP0_ICMP7 0x0093 Compare Match Interupt of Compare Registers CM0-CM7 assigned to Timer 2 +entry CTF 0x009B Compare timer overflow +entry ICS 0x00A3 Compare Match Interupt of Compare Register COMSET +entry ICR 0x00AB Compare Match Interupt of Compare Register COMCLR + + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +; WDTREL 0x0083 Watchdog Timer Reload Register +; WDTREL.WDTPSEL 7 +; WDTREL.WDTREL6 6 +; WDTREL.WDTREL5 5 +; WDTREL.WDTREL4 4 +; WDTREL.WDTREL3 3 +; WDTREL.WDTREL2 2 +; WDTREL.WDTREL1 1 +; WDTREL.WDTREL0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +RESERVED0086 0x0086 RESERVED +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_0 7 +TMOD.C_T_0 6 +TMOD.M1_0 5 +TMOD.M0_0 4 +TMOD.GATE_1 3 +TMOD.C_T_1 2 +TMOD.M1_1 1 +TMOD.M0_1 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.T2 7 +P1.CLKOUT 6 +P1.T2EX 5 +P1.INT2 4 +P1.INT6 3 +P1.INT5 2 +P1.INT4 1 +P1.INT3 0 +XPAGE 0x0091 Page Address Register for Extended On-Chip RAM +XPAGE.XPAGE7 7 +XPAGE.XPAGE6 6 +XPAGE.XPAGE5 5 +XPAGE.XPAGE4 4 +XPAGE.XPAGE3 3 +XPAGE.XPAGE2 2 +XPAGE.XPAGE1 1 +XPAGE.XPAGE0 0 +DPSEL 0x0092 Data Pointer Select Register +DPSEL.DPSEL2 2 +DPSEL.DPSEL1 1 +DPSEL.DPSEL0 0 +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +S0CON 0x0098 Serial Channel 0 Control Register +S0CON.SM0 7 +S0CON.SM1 6 +S0CON.SM20 5 +S0CON.REN0 4 +S0CON.TB80 3 +S0CON.RB80 2 +S0CON.TI0 1 +S0CON.RI0 0 +S0BUF 0x0099 Serial Channel 0 Buffer Register +S0BUF.S0BUF7 7 +S0BUF.S0BUF6 6 +S0BUF.S0BUF5 5 +S0BUF.S0BUF4 4 +S0BUF.S0BUF3 3 +S0BUF.S0BUF2 2 +S0BUF.S0BUF1 1 +S0BUF.S0BUF0 0 +IEN2 0x009A Interrupt Enable Register 2 +IEN2.ECR 5 +IEN2.ECS 4 +IEN2.ECT 3 +IEN2.ECMP 2 +IEN2.ES1 0 +S1CON 0x009B Serial Channel 1 Control Register +S1CON.SM 7 +S1CON.SM21 5 +S1CON.REN1 4 +S1CON.TB81 3 +S1CON.RB81 2 +S1CON.TI1 1 +S1CON.RI1 0 +S1BUF 0x009C Serial Channel 1 Buffer Register +S1BUF.S1BUF7 7 +S1BUF.S1BUF6 6 +S1BUF.S1BUF5 5 +S1BUF.S1BUF4 4 +S1BUF.S1BUF3 3 +S1BUF.S1BUF2 2 +S1BUF.S1BUF1 1 +S1BUF.S1BUF0 0 +S1RELL 0x009D Serial Channel 1 Reload Reg., Low Byte +S1RELL.S1RELL7 7 +S1RELL.S1RELL6 6 +S1RELL.S1RELL5 5 +S1RELL.S1RELL4 4 +S1RELL.S1RELL3 3 +S1RELL.S1RELL2 2 +S1RELL.S1RELL1 1 +S1RELL.S1RELL0 0 +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +COMSETL 0x00A1 Compare Set Register Low Byte +COMSETL.COMSETL7 7 +COMSETL.COMSETL6 6 +COMSETL.COMSETL5 5 +COMSETL.COMSETL4 4 +COMSETL.COMSETL3 3 +COMSETL.COMSETL2 2 +COMSETL.COMSETL1 1 +COMSETL.COMSETL0 0 +COMSETH 0x00A2 Compare Set Register, High Byte +COMSETH.COMSETH7 7 +COMSETH.COMSETH6 6 +COMSETH.COMSETH5 5 +COMSETH.COMSETH4 4 +COMSETH.COMSETH3 3 +COMSETH.COMSETH2 2 +COMSETH.COMSETH1 1 +COMSETH.COMSETH0 0 +COMCLRL 0x00A3 Compare Clear Register, Low Byte +COMCLRL.COMCLRL7 7 +COMCLRL.COMCLRL6 6 +COMCLRL.COMCLRL5 5 +COMCLRL.COMCLRL4 4 +COMCLRL.COMCLRL3 3 +COMCLRL.COMCLRL2 2 +COMCLRL.COMCLRL1 1 +COMCLRL.COMCLRL0 0 +COMCLRH 0x00A4 Compare Clear Register, High Byte +COMCLRH.COMCLRH7 7 +COMCLRH.COMCLRH6 6 +COMCLRH.COMCLRH5 5 +COMCLRH.COMCLRH4 4 +COMCLRH.COMCLRH3 3 +COMCLRH.COMCLRH2 2 +COMCLRH.COMCLRH1 1 +COMCLRH.COMCLRH0 0 +SETMSK 0x00A5 Compare Set Mask Register +SETMSK.SETMSK7 7 +SETMSK.SETMSK6 6 +SETMSK.SETMSK5 5 +SETMSK.SETMSK4 4 +SETMSK.SETMSK3 3 +SETMSK.SETMSK2 2 +SETMSK.SETMSK1 1 +SETMSK.SETMSK0 0 +CLRMSK 0x00A6 Compare Clear Mask Register +CLRMSK.CLRMSK7 7 +CLRMSK.CLRMSK6 6 +CLRMSK.CLRMSK5 5 +CLRMSK.CLRMSK4 4 +CLRMSK.CLRMSK3 3 +CLRMSK.CLRMSK2 2 +CLRMSK.CLRMSK1 1 +CLRMSK.CLRMSK0 0 +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.EAL7 7 +IEN0.WDT6 6 +IEN0.ET25 5 +IEN0.ES04 4 +IEN0.ET13 3 +IEN0.EX12 2 +IEN0.ET01 1 +IEN0.EX00 0 +IP0 0x00A9 Interrupt Priority Register 0 +IP0.OWDS 7 +IP0.WDTS 6 +IP0.IP05 5 +IP0.IP04 4 +IP0.IP03 3 +IP0.IP02 2 +IP0.IP01 1 +IP0.IP00 0 +S0RELL 0x00AA Serial Channel 0 Reload Reg., Low Byte +S0RELL.S0RELL7 7 +S0RELL.S0RELL6 6 +S0RELL.S0RELL5 5 +S0RELL.S0RELL4 4 +S0RELL.S0RELL3 3 +S0RELL.S0RELL2 2 +S0RELL.S0RELL1 1 +S0RELL.S0RELL0 0 +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD0 1 +P3.RxD0 0 +SYSCON 0x00B1 System/XRAM Control Register +SYSCON.XMAP1 1 +SYSCON.XMAP0 0 +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IEN1.EXEN2 7 +IEN1.SWDT 6 +IEN1.EX6 5 +IEN1.EX5 4 +IEN1.EX4 3 +IEN1.EX3 2 +IEN1.EX2 1 +IEN1.EADC 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.IP15 5 +IP1.IP14 4 +IP1.IP13 3 +IP1.IP12 2 +IP1.IP11 1 +IP1.IP10 0 +S0RELH 0x00BA Serial Channel 0 Reload Reg., High Byte +S0RELH.S0RELH1 1 +S0RELH.S0RELH0 0 +S1RELH 0x00BB Serial Channel 1 Reload Reg., High Byte +S1RELH.S1RELH1 1 +S1RELH.S1RELH0 0 +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON0 0x00C0 Interrupt Request Control Register 0 +IRCON0.EXF2 7 +IRCON0.TF2 6 +IRCON0.IEX6 5 +IRCON0.IEX5 4 +IRCON0.IEX4 3 +IRCON0.IEX3 2 +IRCON0.IEX2 1 +IRCON0.IADC 0 +CCEN 0x00C1 Compare/Capture Enable Register +CCEN.COCAH3 7 +CCEN.COCAL3 6 +CCEN.COCAH2 5 +CCEN.COCAL2 4 +CCEN.COCAH1 3 +CCEN.COCAL1 2 +CCEN.COCAH0 1 +CCEN.COCAL0 0 +CCL1 0x00C2 Compare/Capture Register 1, Low Byte +CCL1.CCL17 7 +CCL1.CCL16 6 +CCL1.CCL15 5 +CCL1.CCL14 4 +CCL1.CCL13 3 +CCL1.CCL12 2 +CCL1.CCL11 1 +CCL1.CCL10 0 +CCH1 0x00C3 Compare/Capture Register 1, High Byte +CCH1.CCH17 7 +CCH1.CCH16 6 +CCH1.CCH15 5 +CCH1.CCH14 4 +CCH1.CCH13 3 +CCH1.CCH12 2 +CCH1.CCH11 1 +CCH1.CCH10 0 +CCL2 0x00C4 Compare/Capture Register 2, Low Byte +CCL2.CCL27 7 +CCL2.CCL26 6 +CCL2.CCL25 5 +CCL2.CCL24 4 +CCL2.CCL23 3 +CCL2.CCL22 2 +CCL2.CCL21 1 +CCL2.CCL20 0 +CCH2 0x00C5 Compare/Capture Register 2, High Byte +CCH2.CCH27 7 +CCH2.CCH26 6 +CCH2.CCH25 5 +CCH2.CCH24 4 +CCH2.CCH23 3 +CCH2.CCH22 2 +CCH2.CCH21 1 +CCH2.CCH20 0 +CCL3 0x00C6 Compare/Capture Register 1, Low Byte +CCL3.CCL37 7 +CCL3.CCL36 6 +CCL3.CCL35 5 +CCL3.CCL34 4 +CCL3.CCL33 3 +CCL3.CCL32 2 +CCL3.CCL31 1 +CCL3.CCL30 0 +CCH3 0x00C7 Compare/Capture Register 3, High Byte +CCH3.CCH37 7 +CCH3.CCH36 6 +CCH3.CCH35 5 +CCH3.CCH34 4 +CCH3.CCH33 3 +CCH3.CCH32 2 +CCH3.CCH31 1 +CCH3.CCH30 0 +T2CON 0x00C8 Timer 2 Control Register +T2CON.T2PS 7 +T2CON.I3FR 6 +T2CON.I2FR 5 +T2CON.T2R1 4 +T2CON.T2R0 3 +T2CON.T2CM 2 +T2CON.T2I1 1 +T2CON.T2I0 0 +CC4EN 0x00C9 Compare/Capture 4 Enable Register +CC4EN.COCOEN1 7 +CC4EN.COCON2 6 +CC4EN.COCON1 5 +CC4EN.COCON0 4 +CC4EN.COCOEN0 3 +CC4EN.COCAH4 2 +CC4EN.COCAL4 1 +CC4EN.COMO 0 +CRCL 0x00CA Comp./Rel./Capt. Register Low Byte +CRCL.CRCL7 7 +CRCL.CRCL6 6 +CRCL.CRCL5 5 +CRCL.CRCL4 4 +CRCL.CRCL3 3 +CRCL.CRCL2 2 +CRCL.CRCL1 1 +CRCL.CRCL0 0 +CRCH 0x00CB Comp./Rel./Capt. Register High Byte +CRCH.CRCH7 7 +CRCH.CRCH6 6 +CRCH.CRCH5 5 +CRCH.CRCH4 4 +CRCH.CRCH3 3 +CRCH.CRCH2 2 +CRCH.CRCH1 1 +CRCH.CRCH0 0 +TL2 0x00CC Timer 2, Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2, High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +CCL4 0x00CE Compare/Capture Register 4, Low Byte +CCL4.CCL47 7 +CCL4.CCL46 6 +CCL4.CCL45 5 +CCL4.CCL44 4 +CCL4.CCL43 3 +CCL4.CCL42 2 +CCL4.CCL41 1 +CCL4.CCL40 0 +CCH4 0x00CF Compare/Capture Register 4, High Byte +CCH4.CCH47 7 +CCH4.CCH46 6 +CCH4.CCH45 5 +CCH4.CCH44 4 +CCH4.CCH43 3 +CCH4.CCH42 2 +CCH4.CCH41 1 +CCH4.CCH40 0 +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +IRCON1 0x00D1 Interrupt Request Control Register 1 +IRCON1.ICMP7 7 +IRCON1.ICMP6 6 +IRCON1.ICMP5 5 +IRCON1.ICMP4 4 +IRCON1.ICMP3 3 +IRCON1.ICMP2 2 +IRCON1.ICMP1 1 +IRCON1.ICMP0 0 +CML0 0x00D2 Compare Register 0, Low Byte +CML0.CML07 7 +CML0.CML06 6 +CML0.CML05 5 +CML0.CML04 4 +CML0.CML03 3 +CML0.CML02 2 +CML0.CML01 1 +CML0.CML00 0 +CMH0 0x00D3 Compare Register 0, High Byte +CMH0.CMH07 7 +CMH0.CMH06 6 +CMH0.CMH05 5 +CMH0.CMH04 4 +CMH0.CMH03 3 +CMH0.CMH02 2 +CMH0.CMH01 1 +CMH0.CMH00 0 +CML1 0x00D4 Compare Register 1, Low Byte +CML1.CML17 7 +CML1.CML16 6 +CML1.CML15 5 +CML1.CML14 4 +CML1.CML13 3 +CML1.CML12 2 +CML1.CML11 1 +CML1.CML10 0 +CMH1 0x00D5 Compare Register 1, High Byte +CMH1.CMH17 7 +CMH1.CMH16 6 +CMH1.CMH15 5 +CMH1.CMH14 4 +CMH1.CMH13 3 +CMH1.CMH12 2 +CMH1.CMH11 1 +CMH1.CMH10 0 +CML2 0x00D6 Compare Register 2, Low Byte +CML2.CML27 7 +CML2.CML26 6 +CML2.CML25 5 +CML2.CML24 4 +CML2.CML23 3 +CML2.CML22 2 +CML2.CML21 1 +CML2.CML20 0 +CMH2 0x00D7 Compare Register 2, High Byte +CMH2.CMH27 7 +CMH2.CMH26 6 +CMH2.CMH25 5 +CMH2.CMH24 4 +CMH2.CMH23 3 +CMH2.CMH22 2 +CMH2.CMH21 1 +CMH2.CMH20 0 +ADCON0 0x00D8 A/D Converter Control Register 0 +ADCON0.BD 7 +ADCON0.CLK 6 +ADCON0.ADEX 5 +ADCON0.BSY 4 +ADCON0.ADM 3 +ADCON0.MX2 2 +ADCON0.MX1 1 +ADCON0.MX0 0 +ADDATH 0x00D9 A/D Converter Data Register, High Byte +ADDATH.ADDATH9 7 +ADDATH.ADDATH8 6 +ADDATH.ADDATH7 5 +ADDATH.ADDATH6 4 +ADDATH.ADDATH5 3 +ADDATH.ADDATH4 2 +ADDATH.ADDATH3 1 +ADDATH.ADDATH2 0 +ADDATL 0x00DA A/D Converter Data Register, Low Byte +ADDATL.ADDATL1 7 +ADDATL.ADDATL0 6 +P7 0x00DB Port 7, Analog/Digital Input +P7.P77 7 +P7.P76 6 +P7.P75 5 +P7.P74 4 +P7.P73 3 +P7.P72 2 +P7.P71 1 +P7.P70 0 +ADCON1 0x00DC A/D Converter Control Register 1 +ADCON1.ADCL 7 +ADCON1.MX3 3 +ADCON1.MX2 2 +ADCON1.MX1 1 +ADCON1.MX0 0 +P8 0x00DD Port 8, Analog/Digital Input +P8.P83 3 +P8.P82 2 +P8.P81 1 +P8.P80 0 +CTRELL 0x00DE Compare Timer Rel. Register, Low Byte +CTRELL.CTRELL7 7 +CTRELL.CTRELL6 6 +CTRELL.CTRELL5 5 +CTRELL.CTRELL4 4 +CTRELL.CTRELL3 3 +CTRELL.CTRELL2 2 +CTRELL.CTRELL1 1 +CTRELL.CTRELL0 0 +CTRELH 0x00DF Compare Timer Rel. Register, High Byte +CTRELH.CTRELH7 7 +CTRELH.CTRELH6 6 +CTRELH.CTRELH5 5 +CTRELH.CTRELH4 4 +CTRELH.CTRELH3 3 +CTRELH.CTRELH2 2 +CTRELH.CTRELH1 1 +CTRELH.CTRELH0 0 +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +CTCON 0x00E1 Compare Timer Control Register +CTCON.T2PS1 7 +CTCON.ICR 5 +CTCON.ICS 4 +CTCON.CTF 3 +CTCON.CLK2 2 +CTCON.CLK1 1 +CTCON.CLK0 0 +CML3 0x00E2 Compare Register 3, Low Byte +CML3.CML37 7 +CML3.CML36 6 +CML3.CML35 5 +CML3.CML34 4 +CML3.CML33 3 +CML3.CML32 2 +CML3.CML31 1 +CML3.CML30 0 +CMH3 0x00E3 Compare Register 3, High Byte +CMH3.CMH37 7 +CMH3.CMH36 6 +CMH3.CMH35 5 +CMH3.CMH34 4 +CMH3.CMH33 3 +CMH3.CMH32 2 +CMH3.CMH31 1 +CMH3.CMH30 0 +CML4 0x00E4 Compare Register 4, Low Byte +CML4.CML47 7 +CML4.CML46 6 +CML4.CML45 5 +CML4.CML44 4 +CML4.CML43 3 +CML4.CML42 2 +CML4.CML41 1 +CML4.CML40 0 +CMH4 0x00E5 Compare Register 4, High Byte +CMH4.CMH47 7 +CMH4.CMH46 6 +CMH4.CMH45 5 +CMH4.CMH44 4 +CMH4.CMH43 3 +CMH4.CMH42 2 +CMH4.CMH41 1 +CMH4.CMH40 0 +CML5 0x00E6 Compare Register 5, Low Byte +CML5.CML57 7 +CML5.CML56 6 +CML5.CML55 5 +CML5.CML54 4 +CML5.CML53 3 +CML5.CML52 2 +CML5.CML51 1 +CML5.CML50 0 +CMH5 0x00E7 Compare Register 5, High Byte +CMH5.CMH57 7 +CMH5.CMH56 6 +CMH5.CMH55 5 +CMH5.CMH54 4 +CMH5.CMH53 3 +CMH5.CMH52 2 +CMH5.CMH51 1 +CMH5.CMH50 0 +P4 0x00E8 Port 4 +P4.CM7 7 +P4.CM6 6 +P4.CM5 5 +P4.CM4 4 +P4.CM3 3 +P4.CM2 2 +P4.CM1 1 +P4.CM0 0 +MD0 0x00E9 Multiplication/Division Register 0 +MD0.MD07 7 +MD0.MD06 6 +MD0.MD05 5 +MD0.MD04 4 +MD0.MD03 3 +MD0.MD02 2 +MD0.MD01 1 +MD0.MD00 0 +MD1 0x00EA Multiplication/Division Register 1 +MD1.MD17 7 +MD1.MD16 6 +MD1.MD15 5 +MD1.MD14 4 +MD1.MD13 3 +MD1.MD12 2 +MD1.MD11 1 +MD1.MD10 0 +MD2 0x00EB Multiplication/Division Register 2 +MD2.MD27 7 +MD2.MD26 6 +MD2.MD25 5 +MD2.MD24 4 +MD2.MD23 3 +MD2.MD22 2 +MD2.MD21 1 +MD2.MD20 0 +MD3 0x00EC Multiplication/Division Register 3 +MD3.MD37 7 +MD3.MD36 6 +MD3.MD35 5 +MD3.MD34 4 +MD3.MD33 3 +MD3.MD32 2 +MD3.MD31 1 +MD3.MD30 0 +MD4 0x00ED Multiplication/Division Register 4 +MD4.MD47 7 +MD4.MD46 6 +MD4.MD45 5 +MD4.MD44 4 +MD4.MD43 3 +MD4.MD42 2 +MD4.MD41 1 +MD4.MD40 0 +MD5 0x00EE Multiplication/Division Register 5 +MD5.MD57 7 +MD5.MD56 6 +MD5.MD55 5 +MD5.MD54 4 +MD5.MD53 3 +MD5.MD52 2 +MD5.MD51 1 +MD5.MD50 0 +ARCON 0x00EF Arithmetic Control Register +ARCON.MDEF 7 +ARCON.MDOV 6 +ARCON.SLR 5 +ARCON.SC4 4 +ARCON.SC3 3 +ARCON.SC2 2 +ARCON.SC1 1 +ARCON.SC0 0 +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +CML6 0x00F2 Compare Register 6, Low Byte +CML6.CML67 7 +CML6.CML66 6 +CML6.CML65 5 +CML6.CML64 4 +CML6.CML63 3 +CML6.CML62 2 +CML6.CML61 1 +CML6.CML60 0 +CMH6 0x00F3 Compare Register 6, High Byte +CMH6.CMH67 7 +CMH6.CMH66 6 +CMH6.CMH65 5 +CMH6.CMH64 4 +CMH6.CMH63 3 +CMH6.CMH62 2 +CMH6.CMH61 1 +CMH6.CMH60 0 +CML7 0x00F4 Compare Register 7, Low Byte +CML7.CML77 7 +CML7.CML76 6 +CML7.CML75 5 +CML7.CML74 4 +CML7.CML73 3 +CML7.CML72 2 +CML7.CML71 1 +CML7.CML70 0 +CMH7 0x00F5 Compare Register 7, High Byte +CMH7.CMH77 7 +CMH7.CMH76 6 +CMH7.CMH75 5 +CMH7.CMH74 4 +CMH7.CMH73 3 +CMH7.CMH72 2 +CMH7.CMH71 1 +CMH7.CMH70 0 +CMEN 0x00F6 Compare Enable Register +CMEN.CMEN7 7 +CMEN.CMEN6 6 +CMEN.CMEN5 5 +CMEN.CMEN4 4 +CMEN.CMEN3 3 +CMEN.CMEN2 2 +CMEN.CMEN1 1 +CMEN.CMEN0 0 +CMSEL 0x00F7 Compare Input Select +CMSEL.CMSEL7 7 +CMSEL.CMSEL6 6 +CMSEL.CMSEL5 5 +CMSEL.CMSEL4 4 +CMSEL.CMSEL3 3 +CMSEL.CMSEL2 2 +CMSEL.CMSEL1 1 +CMSEL.CMSEL0 0 +P5 0x00F8 Port 5 +P5.CCM7 7 +P5.CCM6 6 +P5.CCM5 5 +P5.CCM4 4 +P5.CCM3 3 +P5.CCM2 2 +P5.CCM1 1 +P5.CCM0 0 +RESERVED00F9 0x00F9 RESERVED +P6 0x00FA Port 6 +P6.P67 7 +P6.P66 6 +P6.P65 5 +P6.P64 4 +P6.P63 3 +P6.TxD1 2 +P6.RxD1 1 +P6.ADST 0 +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C535 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=10483&parent_oid=13738 +; SAB_80C535.pdf +; SAB 80C535: ROM-less version, identical to the SAB 80C515 + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI_TI 0x0023 Serial channel +entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload +entry IADC 0x0043 A/D converter +entry IEX2 0x004B External interrupt 2 +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +SP 0x0081 Stack Pointer +DPL 0x0082 Data Pointer, Low Byte +DPH 0x0083 Data Pointer, High Byte +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +RESERVED0086 0x0086 RESERVED +PCON 0x0087 Power Control Register +TCON 0x0088 Timer Control Register +TMOD 0x0089 Timer Mode Register +TL0 0x008A Timer 0, Low Byte +TL1 0x008B Timer 1, Low Byte +TH0 0x008C Timer 0, High Byte +TH1 0x008D Timer 1, High Byte +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Reg. +SBUF 0x0099 Serial Channel Buffer Reg. +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IP0 0x00A9 Interrupt Priority Register 0 +RESERVED00AA 0x00AA RESERVED +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +RESERVED00B1 0x00B1 RESERVED +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IP1 0x00B9 Interrupt Priority Register 1 +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +CCEN 0x00C1 Comp./Capture Enable Reg. +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +T2CON 0x00C8 Timer 2 Control Register +RESERVED00C9 0x00C9 RESERVED +CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte +CRCH 0x00CB Com./Rel./Capt. Reg. High Byte +TL2 0x00CC Timer 2, Low Byte +TH2 0x00CD Timer 2, High Byte +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +ADCON1 0x00D8 A/D Converter Control Register 1 +ADDAT 0x00D9 A/D Converter Data Register +DAPR 0x00DA D/A Converter Program Register +P6 0x00DB Port 6, Analog/Digital Input +RESERVED00DC 0x00DC RESERVED +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +P4 0x00E8 Port 4 +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B-Register +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +P5 0x00F8 Port 5 +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C537 +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=10484&parent_oid=13739 +; SAB_80C537.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI0_TI0 0x0023 Serial channel 0 +entry TF2_EXF2 0x002B Timer 2 overflow/ext. reload +entry IADC 0x0043 A/D converter +entry IEX2 0x004B External interrupt 2 +entry IEX3 0x0053 External interrupt 3 +entry IEX4 0x005B External interrupt 4 +entry IEX5 0x0063 External interrupt 5 +entry IEX6 0x006B External interrupt 6 +entry RI1_TI1 0x0083 Serial channel 1 +entry CTF 0x009B Compare timer overflow + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +SP 0x0081 Stack Pointer +DPL 0x0082 Data Pointer, Low Byte +DPH 0x0083 Data Pointer, High Byte +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Reg. +PCON 0x0087 Power Control Register +TCON 0x0088 Timer Control Register +TMOD 0x0089 Timer Mode Register +TL0 0x008A Timer 0, Low Byte +TL1 0x008B Timer 1, Low Byte +TH0 0x008C Timer 0, High Byte +TH1 0x008D Timer 1, High Byte +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +RESERVED0091 0x0091 RESERVED +DPSEL 0x0092 Data Pointer Select Register +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +S0CON 0x0098 Serial Channel 0 Control Reg. +S0BUF 0x0099 Serial Channel 0 Buffer Reg. +IEN2 0x009A Interrupt Enable Register 2 +S1CON 0x009B Serial Channel 1 Control Reg. +S1BUF 0x009C Serial Channel 1 Buffer Reg., +S1REL 0x009D Serial Channel 1 Reload Reg., low byte +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IP0 0x00A9 Interrupt Priority Register 0 +S0RELL 0x00AA Serial Channel 0, Reload Reg., low byte +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +RESERVED00B1 0x00B1 RESERVED +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IEN1 0x00B8 Interrupt Enable Register 1 +IP1 0x00B9 Interrupt Priority Register 1 +S0RELH 0x00BA Serial Channel 0, Reload Reg., high byte +S1RELH 0x00BB Serial Channel 1, Reload Reg.,high byte +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +IRCON 0x00C0 Interrupt Request Control Register +CCEN 0x00C1 Comp./Capture Enable Reg. +CCL1 0x00C2 Comp./Capture Reg. 1, Low Byte +CCH1 0x00C3 Comp./Capture Reg. 1, High Byte +CCL2 0x00C4 Comp./Capture Reg. 2, Low Byte +CCH2 0x00C5 Comp./Capture Reg. 2, High Byte +CCL3 0x00C6 Comp./Capture Reg. 3, Low Byte +CCH3 0x00C7 Comp./Capture Reg. 3, High Byte +T2CON 0x00C8 Timer 2 Control Register +CC4EN 0x00C9 Comp./Capture Enable 4 Reg. +CRCL 0x00CA Com./Rel./Capt. Reg. Low Byte +CRCH 0x00CB Com./Rel./Capt. Reg. High Byte +TL2 0x00CC Timer 2, Low Byte +TH2 0x00CD Timer 2, High Byte +CCL4 0x00CE Comp./Capture Reg. 4, Low Byte +CCH4 0x00CF Comp./Capture Reg. 4, High Byte +PSW 0x00D0 Program Status Word Register +RESERVED00D1 0x00D1 RESERVED +CML0 0x00D2 Compare Register 0, Low Byte +CMH0 0x00D3 Compare Register 0, High Byte +CML1 0x00D4 Compare Register 1, Low Byte +CMH1 0x00D5 Compare Register 1, High Byte +CML2 0x00D6 Compare Register 2, Low Byte +CMH2 0x00D7 Compare Register 2, High Byte +ADCON0 0x00D8 A/D Converter Control Register 0 +ADDAT 0x00D9 A/D Converter Data Register +DAPR 0x00DA D/AConverter Program Register +P7 0x00DB Port 7, Analog/Digital Input +ADCON1 0x00DC A/D Converter Control Register 1 +P8 0x00DD Port 8, Analog/Digital Input, 4-bit 0DD +CTRELL 0x00DE Com. Timer Rel. Reg., Low Byte +CTRELH 0x00DF Com. Timer Rel. Reg., High Byte +ACC 0x00E0 Accumulator +CTCON 0x00E1 Com. Timer Control Register +CML3 0x00E2 Compare Register 3, Low Byte +CMH3 0x00E3 Compare Register 3, High Byte +CML4 0x00E4 Compare Register 4, Low Byte +CMH4 0x00E5 Compare Register 4, High Byte +CML5 0x00E6 Compare Register 5, Low Byte +CMH5 0x00E7 Compare Register 5, High Byte +P4 0x00E8 Port 4 +MD0 0x00E9 Multiplication/Division Register 0 +MD1 0x00EA Multiplication/Division Register 1 +MD2 0x00EB Multiplication/Division Register 2 +MD3 0x00EC Multiplication/Division Register 3 +MD4 0x00ED Multiplication/Division Register 4 +MD5 0x00EE Multiplication/Division Register 5 +ARCON 0x00EF Arithmetic Control Register +B 0x00F0 B-Register +RESERVED00F1 0x00F1 RESERVED +CML6 0x00F2 Compare Register 6, Low Byte +CMH6 0x00F3 Compare Register 6, High Byte +CML7 0x00F4 Compare Register 7, Low Byte +CMH7 0x00F5 Compare Register 7, High Byte +CMEN 0x00F6 Compare Enable Register +CMSEL 0x00F7 Compare Input Select +P5 0x00F8 Port 5 +RESERVED00F9 0x00F9 RESERVED +P6 0x00FA Port 6 +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FE 0x00FE RESERVED +RESERVED00FF 0x00FF RESERVED + + +.C541U +; http://www.infineon.com/cgi/ecrm.dll/ecrm/scripts/public_download.jsp?oid=28987&parent_oid=12071 +; SAB-C541U-1EN.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External Interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External Interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry TC_WCOL 0x0043 SSC Interrupt +entry EPIR0_4 0x004B USB Endpoint Interrupt +entry DIRR 0x0053 USB Device Interrupt +entry WAKE_UP 0x007B Wake-up from power down + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +WDTREL 0x0086 Watchdog Timer Reload Register +WDTREL.WDTPSEL 7 +WDTREL.WDTREL6 6 +WDTREL.WDTREL5 5 +WDTREL.WDTREL4 4 +WDTREL.WDTREL3 3 +WDTREL.WDTREL2 2 +WDTREL.WDTREL1 1 +WDTREL.WDTREL0 0 +PCON 0x0087 Power Control Register +PCON.PDS 6 +PCON.IDLS 5 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +; PCON1 0x0088 Power Control Register 1 +; PCON1.EWPD 7 +; PCON1.WS 4 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.P17 7 +P1.P16 6 +P1.SLS 5 +P1.STO 4 +P1.SRI 3 +P1.SCLK 2 +P1.LED1 1 +P1.LED0 0 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +SSCCON 0x0093 SSC Control Register +SSCCON.SCEN 7 +SSCCON.TEN 6 +SSCCON.MSTR 5 +SSCCON.CPOL 4 +SSCCON.CPHA 3 +SSCCON.BRS2 2 +SSCCON.BRS1 1 +SSCCON.BRS0 0 +STB 0x0094 SSC Transmit Buffer +STB.STB7 7 +STB.STB6 6 +STB.STB5 5 +STB.STB4 4 +STB.STB3 3 +STB.STB2 2 +STB.STB1 1 +STB.STB0 0 +SRB 0x0095 SSC Receive Register +SRB.SRB7 7 +SRB.SRB6 6 +SRB.SRB5 5 +SRB.SRB4 4 +SRB.SRB3 3 +SRB.SRB2 2 +SRB.SRB1 1 +SRB.SRB0 0 +SSCMOD 0x0096 SSC Mode Test Register +SSCMOD.LOOPB 7 +SSCMOD.TRIO 6 +SSCMOD.LSBSM 0 +RESERVED0097 0x0097 RESERVED +RESERVED0098 0x0098 RESERVED +RESERVED0099 0x0099 RESERVED +ITCON 0x009A External Interrupt Trigger Condition Register +ITCON.I1ETF 3 +ITCON.I1ETR 2 +ITCON.I0ETF 1 +ITCON.I0ETR 0 +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IEN0 0x00A8 Interrupt Enable Register 0 +IEN0.ET1 3 +IEN0.EX1 2 +IEN0.ET0 1 +IEN0.EX0 0 +IEN1 0x00A9 Interrupt Enable Register 1 +IEN1.EUDI 2 +IEN1.EUEI 1 +IEN1.ESSC 0 +RESERVED00AA 0x00AA RESERVED +SCF 0x00AB SSC Flag Register +SCF.WCOL 1 +SCF.TC 0 +SCIEN 0x00AC SSC Interrupt Enable Register +SCIEN.WCEN 1 +SCIEN.TCEN 0 +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.DADD 1 +P3.LED2 0 +SYSCON 0x00B1 System Control Register +SYSCON.EALE 5 +SYSCON.RMAP 4 Special function register map bit +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IP0 0x00B8 Interrupt Priority Register 0 +IP0.PT1 3 +IP0.PX1 2 +IP0.PT0 1 +IP0.PX0 0 +IP1 0x00B9 Interrupt Priority Register 1 +IP1.PUDI 2 +IP1.PUEI 1 +IP1.PSSC 0 +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +WDCON 0x00C0 Watchdog Timer Control Register +WDCON.OWDS 3 +WDCON.WDTS 2 +WDCON.WDT 1 +WDCON.SWDT 0 +; FOR EPSEL = 1XXX.XXXX B Device Registers +DCR 0x00C1 USB Device Control Register +DCR.SPEED 7 +DCR.DA 6 +DCR.SWR 5 +DCR.SUSP 4 +DCR.DINIT 3 +DCR.RSM 2 +DCR.UCLK 1 +DCR.PCLK 0 +DPWDR 0x00C2 USB Device Power Down Register +DPWDR.DRVIE 7 +DPWDR.XVREG 6 +DPWDR.TPWD 1 +DPWDR.RPWD 0 +DIER 0x00C3 USB Device Interrupt Control Register +DIER.SE0IE 7 +DIER.DAIE 6 +DIER.DDIE 5 +DIER.SBIE 4 +DIER.SEIE 3 +DIER.STIE 2 +DIER.SUIE 1 +DIER.SOFIE 0 +DIRR 0x00C4 USB Device Interrupt Request Register +DIRR.SE0I 7 +DIRR.DAI 6 +DIRR.DDI 5 +DIRR.SBI 4 +DIRR.SEI 3 +DIRR.STI 2 +DIRR.SUI 1 +DIRR.SOFI 0 +RESERVED00C5 0x00C5 RESERVED +FNRL 0x00C6 USB Frame Number Register, Low Byte +FNRL.FNR7 7 +FNRL.FNR6 6 +FNRL.FNR5 5 +FNRL.FNR4 4 +FNRL.FNR3 3 +FNRL.FNR2 2 +FNRL.FNR1 1 +FNRL.FNR0 0 +FNRH 0x00C7 USB Frame Number Register, High Byte +FNRH.FNR10 2 +FNRH.FNR9 1 +FNRH.FNR8 0 +; FOR EPSEL = 0XXX.X000 B Endpoint 0 Registers +; EPBC0 0x00C1 USB Endpoint 0 Buffer Control Register +; EPBC0.STALL0 7 +; EPBC0.GEPIE0 4 +; EPBC0.SOFDE0 3 +; EPBC0.INCE0 2 +; EPBC0.DBM0 0 +; EPBS0 0x00C2 USB Endpoint 0 Buffer Status Register +; EPBS0.UBF0 7 +; EPBS0.CBF0 6 +; EPBS0.DIR0 5 +; EPBS0.ESP0 4 +; EPBS0.SETRD0 3 +; EPBS0.SETWR0 2 +; EPBS0.CLREP0 1 +; EPBS0.DONE0 0 +; EPIE0 0x00C3 USB Endpoint 0 Interrupt Enable Register +; EPIE0.AIE0 7 +; EPIE0.NAIE0 6 +; EPIE0.RLEIE0 5 +; EPIE0.DNRIE0 3 +; EPIE0.NODIE0 2 +; EPIE0.EODIE0 1 +; EPIE0.SODIE0 0 +; EPIR0 0x00C4 USB Endpoint 0 Interrupt Request Register +; EPIR0.ACK0 7 +; EPIR0.NACK0 6 +; EPIR0.RLE0 5 +; EPIR0.DNR0 3 +; EPIR0.NOD0 2 +; EPIR0.EOD0 1 +; EPIR0.SOD0 0 +; EPBA0 0x00C5 USB Endpoint 0 Base Address Register +; EPBA0.PAGE0 7 +; EPBA0.A06 3 +; EPBA0.A05 2 +; EPBA0.A04 1 +; EPBA0.A03 0 +; EPLEN0 0x00C6 USB Endpoint 0 Buffer Length Register +; EPLEN0.L06 6 +; EPLEN0.L05 5 +; EPLEN0.L04 4 +; EPLEN0.L03 3 +; EPLEN0.L02 2 +; EPLEN0.L01 1 +; EPLEN0.L00 0 +; RESERVED00C7 0x00C7 RESERVED +; FOR EPSEL = 0XXX.X001 B Endpoint 1 Registers +; EPBC1 0x00C1 USB Endpoint 1 Buffer Control Register +; EPBC1.STALL1 7 +; EPBC1.GEPIE1 4 +; EPBC1.SOFDE1 3 +; EPBC1.INCE1 2 +; EPBC1.DBM1 0 +; EPBS1 0x00C2 USB Endpoint 1 Buffer Status Register +; EPBS1.UBF1 7 +; EPBS1.CBF1 6 +; EPBS1.DIR1 5 +; EPBS1.ESP1 4 +; EPBS1.SETRD1 3 +; EPBS1.SETWR1 2 +; EPBS1.CLREP1 1 +; EPBS1.DONE1 0 +; EPIE1 0x00C3 USB Endpoint 1 Interrupt Enable Register +; EPIE1.AIE1 7 +; EPIE1.NAIE1 6 +; EPIE1.RLEIE1 5 +; EPIE1.DNRIE1 3 +; EPIE1.NODIE1 2 +; EPIE1.EODIE1 1 +; EPIE1.SODIE1 0 +; EPIR1 0x00C4 USB Endpoint 1 Interrupt Request Register +; EPIR1.ACK1 7 +; EPIR1.NACK1 6 +; EPIR1.RLE1 5 +; EPIR1.DNR1 3 +; EPIR1.NOD1 2 +; EPIR1.EOD1 1 +; EPIR1.SOD1 0 +; EPBA1 0x00C5 USB Endpoint 1 Base Address Register +; EPBA1.PAGE1 7 +; EPBA1.A16 3 +; EPBA1.A15 2 +; EPBA1.A14 1 +; EPBA1.A13 0 +; EPLEN1 0x00C6 USB Endpoint 1 Buffer Length Register +; EPLEN1.L16 6 +; EPLEN1.L15 5 +; EPLEN1.L14 4 +; EPLEN1.L13 3 +; EPLEN1.L12 2 +; EPLEN1.L11 1 +; EPLEN1.L10 0 +; RESERVED00C7 0x00C7 RESERVED +; FOR EPSEL = 0XXX.X010 B Endpoint 2 Registers +; EPBC2 0x00C1 USB Endpoint 2 Buffer Control Register +; EPBC2.STALL2 7 +; EPBC2.GEPIE2 4 +; EPBC2.SOFDE2 3 +; EPBC2.INCE2 2 +; EPBC2.DBM2 0 +; EPBS2 0x00C2 USB Endpoint 2 Buffer Status Register +; EPBS2.UBF2 7 +; EPBS2.CBF2 6 +; EPBS2.DIR2 5 +; EPBS2.ESP2 4 +; EPBS2.SETRD2 3 +; EPBS2.SETWR2 2 +; EPBS2.CLREP2 1 +; EPBS2.DONE2 0 +; EPIE2 0x00C3 USB Endpoint 2 Interrupt Enable Register +; EPIE2.AIE2 7 +; EPIE2.NAIE2 6 +; EPIE2.RLEIE2 5 +; EPIE2.DNRIE2 3 +; EPIE2.NODIE2 2 +; EPIE2.EODIE2 1 +; EPIE2.SODIE2 0 +; EPIR2 0x00C4 USB Endpoint 2 Interrupt Request Register +; EPIR2.ACK2 7 +; EPIR2.NACK2 6 +; EPIR2.NACK2 5 +; EPIR2.DNR2 3 +; EPIR2.NOD2 2 +; EPIR2.EOD2 1 +; EPIR2.SOD2 0 +; EPBA2 0x00C5 USB Endpoint 2 Base Address Register +; EPBA2.PAGE2 7 +; EPBA2.A62 3 +; EPBA2.A52 2 +; EPBA2.A42 1 +; EPBA2.A32 0 +; EPLEN2 0x00C6 USB Endpoint 2 Buffer Length Register +; EPLEN2.L62 6 +; EPLEN2.L52 5 +; EPLEN2.L42 4 +; EPLEN2.L32 3 +; EPLEN2.L22 2 +; EPLEN2.L12 1 +; EPLEN2.L02 0 +; RESERVED00C7 0x00C7 RESERVED +; FOR EPSEL = 0XXX.X011 B Endpoint 3 Registers +; EPBC3 0x00C1 USB Endpoint 3 Buffer Control Register +; EPBC3.STALL3 7 +; EPBC3.GEPIE3 4 +; EPBC3.SOFDE3 3 +; EPBC3.INCE3 2 +; EPBC3.DBM3 0 +; EPBS3 0x00C2 USB Endpoint 3 Buffer Status Register +; EPBS3.UBF3 7 +; EPBS3.CBF3 6 +; EPBS3.DIR3 5 +; EPBS3.ESP3 4 +; EPBS3.SETRD3 3 +; EPBS3.SETWR3 2 +; EPBS3.CLREP3 1 +; EPBS3.DONE3 0 +; EPIE3 0x00C3 USB Endpoint 3 Interrupt Enable Register +; EPIE3.AIE3 7 +; EPIE3.NAIE3 6 +; EPIE3.RLEIE3 5 +; EPIE3.DNRIE3 3 +; EPIE3.NODIE3 2 +; EPIE3.EODIE3 1 +; EPIE3.SODIE3 0 +; EPIR3 0x00C4 USB Endpoint 3 Interrupt Request Register +; EPIR3.ACK3 7 +; EPIR3.NACK3 6 +; EPIR3.RLE3 5 +; EPIR3.DNR3 3 +; EPIR3.NOD3 2 +; EPIR3.EOD3 1 +; EPIR3.SOD3 0 +; EPBA3 0x00C5 USB Endpoint 3 Base Address Register +; EPBA3.PAGE3 7 +; EPBA3.A63 3 +; EPBA3.A52 2 +; EPBA3.A43 1 +; EPBA3.A33 0 +; EPLEN3 0x00C6 USB Endpoint 3 Buffer Length Register +; EPLEN3.L63 6 +; EPLEN3.L53 5 +; EPLEN3.L43 4 +; EPLEN3.L33 3 +; EPLEN3.L23 2 +; EPLEN3.L13 1 +; EPLEN3.L03 0 +; RESERVED00C7 0x00C7 RESERVED +; FOR EPSEL = 0XXX.X100 B Endpoint 4 Registers +; EPBC4 0x00C1 USB Endpoint 4 Buffer Control Register +; EPBC4.STALL4 7 +; EPBC4.GEPIE4 4 +; EPBC4.SOFDE4 3 +; EPBC4.INCE4 2 +; EPBC4.DBM4 0 +; EPBS4 0x00C2 USB Endpoint 4 Buffer Status Register +; EPBS4.UBF4 7 +; EPBS4.CBF4 6 +; EPBS4.DIR4 5 +; EPBS4.ESP4 4 +; EPBS4.SETRD4 3 +; EPBS4.SETWR4 2 +; EPBS4.CLREP4 1 +; EPBS4.DONE4 0 +; EPIE4 0x00C3 USB Endpoint 4 Interrupt Enable Register +; EPIE4.AIE4 7 +; EPIE4.NAIE4 6 +; EPIE4.RLEIE4 5 +; EPIE4.DNRIE4 3 +; EPIE4.NODIE4 2 +; EPIE4.EODIE4 1 +; EPIE4.SODIE4 0 +; EPIR4 0x00C4 USB Endpoint 4 Interrupt Request Register +; EPIR4.ACK4 7 +; EPIR4.NACK4 6 +; EPIR4.RLE4 5 +; EPIR4.DNR4 3 +; EPIR4.NOD4 2 +; EPIR4.EOD4 1 +; EPIR4.SOD4 0 +; EPBA4 0x00C5 USB Endpoint 4 Base Address Register +; EPBA4.PAGE4 7 +; EPBA4.A64 3 +; EPBA4.A54 2 +; EPBA4.A44 1 +; EPBA4.A34 0 +; EPLEN4 0x00C6 USB Endpoint 4 Buffer Length Register +; EPLEN4.L64 6 +; EPLEN4.L54 5 +; EPLEN4.L44 4 +; EPLEN4.L34 3 +; EPLEN4.L24 2 +; EPLEN4.L14 1 +; EPLEN4.L04 0 +; RESERVED00C7 0x00C7 RESERVED +RESERVED00C8 0x00C8 RESERVED +RESERVED00C9 0x00C9 RESERVED +RESERVED00CA 0x00CA RESERVED +RESERVED00CB 0x00CB RESERVED +RESERVED00CC 0x00CC RESERVED +RESERVED00CD 0x00CD RESERVED +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 Carry Flag +PSW.AC 6 Auxiliary Carry Flag +PSW.F0 5 General Purpose Flag +PSW.RS1 4 Register Bank Select Control Bit 1 +PSW.RS0 3 Register Bank Select Control Bit 0 +PSW.OV 2 Overflow Flag +PSW.F1 1 General Purpose Flag +PSW.P 0 Parity Flag +RESERVED00D1 0x00D1 RESERVED +EPSEL 0x00D2 USB Endpoint Select Register +EPSEL.EPS7 7 +EPSEL.EPS2 2 +EPSEL.EPS1 1 +EPSEL.EPS0 0 +USBVAL 0x00D3 USB Data Register +USBVAL.USBVAL7 7 +USBVAL.USBVAL6 6 +USBVAL.USBVAL5 5 +USBVAL.USBVAL4 4 +USBVAL.USBVAL3 3 +USBVAL.USBVAL2 2 +USBVAL.USBVAL1 1 +USBVAL.USBVAL0 0 +ADROFF 0x00D4 USB Address Offset Register +ADROFF.AO5 5 +ADROFF.AO4 4 +ADROFF.AO3 3 +ADROFF.AO2 2 +ADROFF.AO1 1 +ADROFF.AO0 0 +RESERVED00D5 0x00D5 RESERVED +GEPIR 0x00D6 USB Global Endpoint Interrupt Request Reg. +GEPIR.DRVI 7 +GEPIR.EPI4 4 +GEPIR.EPI3 3 +GEPIR.EPI2 2 +GEPIR.EPI1 1 +GEPIR.EPI0 0 +RESERVED00D7 0x00D7 RESERVED +RESERVED00D8 0x00D8 RESERVED +RESERVED00D9 0x00D9 RESERVED +RESERVED00DA 0x00DA RESERVED +RESERVED00DB 0x00DB RESERVED +RESERVED00DC 0x00DC RESERVED +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +USBPWD 0x00E6 USB Power Down Register +USBPWD.SUSPIE 5 +USBPWD.DADDIE 4 +USBPWD.SUSP 3 +USBPWD.DADD 2 +USBPWD.TPWD 1 +USBPWD.RPWD 0 +USBDCR 0x00E7 USB Control Register +USBDCR.TYPE3 7 +USBDCR.TYPE2 6 +USBDCR.TYPE1 5 +USBDCR.TYPE0 4 +USBDCR.LEN3 3 +USBDCR.LEN2 2 +USBDCR.LEN1 1 +USBDCR.LEN0 0 +USBDR0 0x00E8 USB Data Register 0 +USBDR0.USBDR07 7 +USBDR0.USBDR06 6 +USBDR0.USBDR05 5 +USBDR0.USBDR04 4 +USBDR0.USBDR03 3 +USBDR0.USBDR02 2 +USBDR0.USBDR01 1 +USBDR0.USBDR00 0 +USBDR1 0x00E9 USB Data Register 1 +USBDR1.USBDR17 7 +USBDR1.USBDR16 6 +USBDR1.USBDR15 5 +USBDR1.USBDR14 4 +USBDR1.USBDR13 3 +USBDR1.USBDR12 2 +USBDR1.USBDR11 1 +USBDR1.USBDR10 0 +USBDR2 0x00EA USB Data Register 2 +USBDR2.USBDR27 7 +USBDR2.USBDR26 6 +USBDR2.USBDR25 5 +USBDR2.USBDR24 4 +USBDR2.USBDR23 3 +USBDR2.USBDR22 2 +USBDR2.USBDR21 1 +USBDR2.USBDR20 0 +USBDR3 0x00EB USB Data Register 3 +USBDR3.USBDR37 7 +USBDR3.USBDR36 6 +USBDR3.USBDR35 5 +USBDR3.USBDR34 4 +USBDR3.USBDR33 3 +USBDR3.USBDR32 2 +USBDR3.USBDR31 1 +USBDR3.USBDR30 0 +USBDR4 0x00EC USB Data Register 4 +USBDR4.USBDR47 7 +USBDR4.USBDR46 6 +USBDR4.USBDR45 5 +USBDR4.USBDR44 4 +USBDR4.USBDR43 3 +USBDR4.USBDR42 2 +USBDR4.USBDR41 1 +USBDR4.USBDR40 0 +USBDR5 0x00ED USB Data Register 5 +USBDR5.USBDR57 7 +USBDR5.USBDR56 6 +USBDR5.USBDR55 5 +USBDR5.USBDR54 4 +USBDR5.USBDR53 3 +USBDR5.USBDR52 2 +USBDR5.USBDR51 1 +USBDR5.USBDR50 0 +USBDR6 0x00EE USB Data Register 6 +USBDR6.USBDR67 7 +USBDR6.USBDR66 6 +USBDR6.USBDR65 5 +USBDR6.USBDR64 4 +USBDR6.USBDR63 3 +USBDR6.USBDR62 2 +USBDR6.USBDR61 1 +USBDR6.USBDR60 0 +USBDR7 0x00EF USB Data Register 7 +USBDR7.USBDR77 7 +USBDR7.USBDR76 6 +USBDR7.USBDR75 5 +USBDR7.USBDR74 4 +USBDR7.USBDR73 3 +USBDR7.USBDR72 2 +USBDR7.USBDR71 1 +USBDR7.USBDR70 0 +B 0x00F0 B Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +VR0 0x00FC Version Register 0 +VR1 0x00FD Version Register 1 +VR2 0x00FE Version Register 2 +RESERVED00FF 0x00FF RESERVED + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.AT89S8252 +; http://www.atmel.com/atmel/acrobat/doc0401.pdf +; + +; MEMORY MAP +area CODE code 0x0000:0x2000 +area DATA RAM 0x0000:0x0100 +area DATA FSR 0x0080:0x0100 + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DP0L 0x0082 Data Pointer Low Byte +DP0H 0x0083 Data Pointer High Byte +DP1L 0x0084 Data Pointer 1 Low Byte +DP1H 0x0085 Data Pointer 1 High Byte +SPDR 0x0086 SPI Data Register +PCON 0x0087 Power Control Register +PCON.PDS 6 +PCON.IDLS 5 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Control Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0 Low Byte +TL1 0x008B Timer 1 Low Byte +TH0 0x008c Timer 0 High Byte +TH1 0x008D Timer 1 High Byte + +P1 0x0090 Port 1 +WMCON 0x0096 Watchdog and Memory Control Register +SCON 0x0098 Serial Port Control +SBUF 0x0099 Serial Port Buffer + +P2 0x00A0 Port 2 +IE 0x00A8 Interrupt Enable Register 0 +IE.EA 7 +IE.ET2 5 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 +SPSR 0x00AA SPI Status Register , different to AT89C52 + +P3 0x00B0 Port 3 +IP 0x00B8 Interrupt Priority Register + +T2CON 0x00C8 Timer 2 Control +T2MOD 0x00C9 Timer 2 Mode +RCAP2L 0x00CA Timer 2 Capture Low Byte +RCAP2H 0x00CB Timer 2 Capture High Byte +TL2 0x00CC Timer 2 Low Byte +TH2 0x00CD Timer 2 High Byte + +PSW 0x00D0 Program Status Word +SPCR 0x00D5 SPI Control Register + +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +B 0x00F0 B Register + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +.AT89C2051 +; http://www.atmel.com/atmel/acrobat/doc0368.pdf +; + +; MEMORY MAP +area CODE code 0x0000:0x0800 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 interrupt +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 interrupt +entry RI_TI 0x0023 Serial port interrupt +entry TF2_EXF2 0x002B Timer 2 interrupt + +; INPUT/OUTPUT PORTS + +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 + +DPL 0x0082 Data Pointer Low Byte +DPH 0x0083 Data Pointer High Byte + +PCON 0x0087 Power Control Register +PCON.PDS 6 +PCON.IDLS 5 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 + +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 + +TMOD 0x0089 Timer Mode Control Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 + +TL0 0x008A Timer 0 Low Byte +TL1 0x008B Timer 1 Low Byte +TH0 0x008c Timer 0 High Byte +TH1 0x008D Timer 1 High Byte + +P1 0x0090 Port 1 +P1.P17 7 +P1.P16 6 +P1.P15 5 +P1.P14 4 +P1.P13 3 +P1.P12 2 +P1.P11 1 +P1.P10 0 + +SCON 0x0098 Serial Port Control +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 + +SBUF 0x0099 Serial Port Buffer + +IE 0x00A8 Interrupt Enable Register 0 +IE.EA 7 +IE.ET2 5 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 + +P3 0x00B0 Port 3 +P3.P37 7 +P3.P36 6 +P3.P35 5 +P3.P34 4 +P3.P33 3 +P3.P32 2 +P3.P31 1 +P3.P30 0 + +IP 0x00B8 Interrupt Priority Register +IP.PS 4 +IP.PT1 3 +IP.PX1 2 +IP.PT0 1 +IP.PX0 0 + +PSW 0x00D0 Program Status Word +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.P 0 + +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 + +B 0x00F0 B Register + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +.8032 +; http://www.keil.com/dd/docs/c51/reg52.h + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0100 +area DATA FSR 0x0080:0x0100 + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External Interrupt 0 +entry TF0 0x000B Timer 0 Overflow +entry IE1 0x0013 External Interrupt 1 +entry TF1 0x001B Timer 1 Overflow +entry RI_TI 0x0023 Serial port interrupt +entry TF2_EXF2 0x002B Timer 2 Overflow or TX2 Pin + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +SP.SP7 7 +SP.SP6 6 +SP.SP5 5 +SP.SP4 4 +SP.SP3 3 +SP.SP2 2 +SP.SP1 1 +SP.SP0 0 +DPL 0x0082 Data Pointer, Low Byte +DPL.DPL7 7 +DPL.DPL6 6 +DPL.DPL5 5 +DPL.DPL4 4 +DPL.DPL3 3 +DPL.DPL2 2 +DPL.DPL1 1 +DPL.DPL0 0 +DPH 0x0083 Data Pointer, High Byte +DPH.DPH7 7 +DPH.DPH6 6 +DPH.DPH5 5 +DPH.DPH4 4 +DPH.DPH3 3 +DPH.DPH2 2 +DPH.DPH1 1 +DPH.DPH0 0 +RESERVED0084 0x0084 RESERVED +RESERVED0085 0x0085 RESERVED +RESERVED0086 0x0086 RESERVED +PCON 0x0087 Power Control Register +PCON.PDS 6 +PCON.IDLS 5 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0, Low Byte +TL0.TL07 7 +TL0.TL06 6 +TL0.TL05 5 +TL0.TL04 4 +TL0.TL03 3 +TL0.TL02 2 +TL0.TL01 1 +TL0.TL00 0 +TL1 0x008B Timer 1, Low Byte +TL1.TL17 7 +TL1.TL16 6 +TL1.TL15 5 +TL1.TL14 4 +TL1.TL13 3 +TL1.TL12 2 +TL1.TL11 1 +TL1.TL10 0 +TH0 0x008C Timer 0, High Byte +TH0.TH07 7 +TH0.TH06 6 +TH0.TH05 5 +TH0.TH04 4 +TH0.TH03 3 +TH0.TH02 2 +TH0.TH01 1 +TH0.TH00 0 +TH1 0x008D Timer 1, High Byte +TH1.TH17 7 +TH1.TH16 6 +TH1.TH15 5 +TH1.TH14 4 +TH1.TH13 3 +TH1.TH12 2 +TH1.TH11 1 +TH1.TH10 0 +RESERVED008E 0x008E RESERVED +RESERVED008F 0x008F RESERVED +P1 0x0090 Port 1 +P1.P17 7 +P1.P16 6 +P1.SLS 5 +P1.STO 4 +P1.SRI 3 +P1.SCLK 2 +P1.T2EX 1 +P1.T2 0 +RESERVED0091 0x0091 RESERVED +RESERVED0092 0x0092 RESERVED +RESERVED0093 0x0093 RESERVED +RESERVED0094 0x0094 RESERVED +RESERVED0095 0x0095 RESERVED +RESERVED0096 0x0096 RESERVED +RESERVED0097 0x0097 RESERVED +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM2 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +SBUF.SBUF7 7 +SBUF.SBUF6 6 +SBUF.SBUF5 5 +SBUF.SBUF4 4 +SBUF.SBUF3 3 +SBUF.SBUF2 2 +SBUF.SBUF1 1 +SBUF.SBUF0 0 +RESERVED009A 0x009A RESERVED +RESERVED009B 0x009B RESERVED +RESERVED009C 0x009C RESERVED +RESERVED009D 0x009D RESERVED +RESERVED009E 0x009E RESERVED +RESERVED009F 0x009F RESERVED +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +RESERVED00A1 0x00A1 RESERVED +RESERVED00A2 0x00A2 RESERVED +RESERVED00A3 0x00A3 RESERVED +RESERVED00A4 0x00A4 RESERVED +RESERVED00A5 0x00A5 RESERVED +RESERVED00A6 0x00A6 RESERVED +RESERVED00A7 0x00A7 RESERVED +IE 0x00A8 +IE.EA 7 +IE.ET2 5 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 +RESERVED00A9 0x00A9 RESERVED +RESERVED00AA 0x00AA RESERVED +RESERVED00AB 0x00AB RESERVED +RESERVED00AC 0x00AC RESERVED +RESERVED00AD 0x00AD RESERVED +RESERVED00AE 0x00AE RESERVED +RESERVED00AF 0x00AF RESERVED +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TXD 1 +P3.RXD 0 +RESERVED00B1 0x00B1 RESERVED +RESERVED00B2 0x00B2 RESERVED +RESERVED00B3 0x00B3 RESERVED +RESERVED00B4 0x00B4 RESERVED +RESERVED00B5 0x00B5 RESERVED +RESERVED00B6 0x00B6 RESERVED +RESERVED00B7 0x00B7 RESERVED +IP 0x00B8 Interrupt Priority Register 0 +IP.PT2 5 +IP.PS0 4 +IP.PT1 3 +IP.PX1 2 +IP.PT0 1 +IP.PX0 0 +RESERVED00B9 0x00B9 RESERVED +RESERVED00BA 0x00BA RESERVED +RESERVED00BB 0x00BB RESERVED +RESERVED00BC 0x00BC RESERVED +RESERVED00BD 0x00BD RESERVED +RESERVED00BE 0x00BE RESERVED +RESERVED00BF 0x00BF RESERVED +RESERVED00C0 0x00C0 RESERVED +RESERVED00C1 0x00C1 RESERVED +RESERVED00C2 0x00C2 RESERVED +RESERVED00C3 0x00C3 RESERVED +RESERVED00C4 0x00C4 RESERVED +RESERVED00C5 0x00C5 RESERVED +RESERVED00C6 0x00C6 RESERVED +RESERVED00C7 0x00C7 RESERVED +T2CON 0x00C8 Timer 2 Control Register +T2CON.TF2 7 +T2CON.EXF2 6 +T2CON.RCLK 5 +T2CON.TCLK 4 +T2CON.EXEN2 3 +T2CON.TR2 2 +T2CON.C_T2 1 +T2CON.CP_RL2 0 +RESERVED00C9 0x00C9 RESERVED +RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte +RC2L.RC2L7 7 +RC2L.RC2L6 6 +RC2L.RC2L5 5 +RC2L.RC2L4 4 +RC2L.RC2L3 3 +RC2L.RC2L2 2 +RC2L.RC2L1 1 +RC2L.RC2L0 0 +RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte +RC2H.RC2H7 7 +RC2H.RC2H6 6 +RC2H.RC2H5 5 +RC2H.RC2H4 4 +RC2H.RC2H3 3 +RC2H.RC2H2 2 +RC2H.RC2H1 1 +RC2H.RC2H0 0 +TL2 0x00CC Timer 2 Low Byte +TL2.TL27 7 +TL2.TL26 6 +TL2.TL25 5 +TL2.TL24 4 +TL2.TL23 3 +TL2.TL22 2 +TL2.TL21 1 +TL2.TL20 0 +TH2 0x00CD Timer 2 High Byte +TH2.TH27 7 +TH2.TH26 6 +TH2.TH25 5 +TH2.TH24 4 +TH2.TH23 3 +TH2.TH22 2 +TH2.TH21 1 +TH2.TH20 0 +RESERVED00CE 0x00CE RESERVED +RESERVED00CF 0x00CF RESERVED +PSW 0x00D0 Program Status Word Register +PSW.CY 7 Carry Flag +PSW.AC 6 Auxiliary Carry Flag +PSW.F0 5 General Purpose Flag +PSW.RS1 4 Register Bank Select Control Bit 1 +PSW.RS0 3 Register Bank Select Control Bit 0 +PSW.OV 2 Overflow Flag +PSW.F1 1 General Purpose Flag +PSW.P 0 Parity Flag +RESERVED00D1 0x00D1 RESERVED +RESERVED00D2 0x00D2 RESERVED +RESERVED00D3 0x00D3 RESERVED +RESERVED00D4 0x00D4 RESERVED +RESERVED00D5 0x00D5 RESERVED +RESERVED00D6 0x00D6 RESERVED +RESERVED00D7 0x00D7 RESERVED +RESERVED00D8 0x00D8 RESERVED +RESERVED00D9 0x00D9 RESERVED +RESERVED00DA 0x00DA RESERVED +RESERVED00DB 0x00DB RESERVED +RESERVED00DC 0x00DC RESERVED +RESERVED00DD 0x00DD RESERVED +RESERVED00DE 0x00DE RESERVED +RESERVED00DF 0x00DF RESERVED +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +RESERVED00E1 0x00E1 RESERVED +RESERVED00E2 0x00E2 RESERVED +RESERVED00E3 0x00E3 RESERVED +RESERVED00E4 0x00E4 RESERVED +RESERVED00E5 0x00E5 RESERVED +RESERVED00E6 0x00E6 RESERVED +RESERVED00E7 0x00E7 RESERVED +RESERVED00E8 0x00E8 RESERVED +RESERVED00E9 0x00E9 RESERVED +RESERVED00EA 0x00EA RESERVED +RESERVED00EB 0x00EB RESERVED +RESERVED00EC 0x00EC RESERVED +RESERVED00ED 0x00ED RESERVED +RESERVED00EE 0x00EE RESERVED +RESERVED00EF 0x00EF RESERVED +B 0x00F0 B Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +RESERVED00F1 0x00F1 RESERVED +RESERVED00F2 0x00F2 RESERVED +RESERVED00F3 0x00F3 RESERVED +RESERVED00F4 0x00F4 RESERVED +RESERVED00F5 0x00F5 RESERVED +RESERVED00F6 0x00F6 RESERVED +RESERVED00F7 0x00F7 RESERVED +RESERVED00F8 0x00F8 RESERVED +RESERVED00F9 0x00F9 RESERVED +RESERVED00FA 0x00FA RESERVED +RESERVED00FB 0x00FB RESERVED +RESERVED00FC 0x00FC RESERVED +RESERVED00FD 0x00FD RESERVED +RESERVED00FF 0x00FF RESERVED + +.FX2 +; Cypress EZ-USB FX2 +; http://www.keil.com/dd/docs/datashts/cypress/cy7c68xxx_ds.pdf +; http://www.keil.com/dd/docs/datashts/cypress/fx2_trm.pdf + +; MEMORY MAP +;area CODE code 0x0000:0x10000 +;area DATA RAM 0x0000:0x0080 +;area DATA FSR 0x0080:0x0100 +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0080 +area DATA FSR 0x0080:0x0100 +area DATA FSR 0xe200:0x10000 + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 overflow +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 overflow +entry RI_TI_0 0x0023 USART0 Rx & Tx +entry TF2 0x002B Timer 2 overflow +entry RESUME 0x0033 USB Resume +entry RI_TI_1 0x003B USART1 Rx & Tx +entry USBINT 0x0043 USB +entry I2CINT 0x004B I2C-Compatible Bus +entry IE4 0x0053 GPIF / FIFOs / INT4 Pin +entry IE5 0x005B INT5 Pin +entry IE6 0x0063 INT6 Pin + +; INPUT/OUTPUT PORTS + +IOA 0x0080 Port A +IOA.D7 7 +IOA.D6 6 +IOA.D5 5 +IOA.D4 4 +IOA.D3 3 +IOA.D2 2 +IOA.D1 1 +IOA.D0 0 + +SP 0x0081 Stack Pointer + +DPL0 0x0082 DPTR0 Low Byte +DPH0 0x0083 DPTR0 High Byte +DPL1 0x0084 DPTR1 Low Byte +DPH1 0x0085 DPTR1 High Byte +DPS 0x0086 DPTR Select (bit 0) +PCON 0x0087 Power Control Register +PCON.SMOD0 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Control Register +TMOD.GATE_1 7 +TMOD.C_T_1 6 +TMOD.M1_1 5 +TMOD.M0_1 4 +TMOD.GATE_0 3 +TMOD.C_T_0 2 +TMOD.M1_0 1 +TMOD.M0_0 0 +TL0 0x008A Timer 0 Reload L +TL1 0x008B Timer 1 Reload L +TH0 0x008C Timer 0 Reload H +TH1 0x008D Timer 1 Reload H +CKCON 0x008E Clock Control + +IOB 0x0090 Port B +IOB.D7 7 +IOB.D6 6 +IOB.D5 5 +IOB.D4 4 +IOB.D3 3 +IOB.D2 2 +IOB.D1 1 +IOB.D0 0 + +EXIF 0x0091 External Interrupt Flag(s) +MPAGE 0x0092 Upper Addr Byte of MOVX using @R0/@R1 +SCON0 0x0098 Serial Port 0 Control +SCON0.SM0 7 +SCON0.SM1 6 +SCON0.SM2 5 +SCON0.REN 4 +SCON0.TB8 3 +SCON0.RB8 2 +SCON0.TI 1 +SCON0.RI 0 + +SBUF0 0x0099 Serial Port 0 Data Buffer +AUTOPTRH1 0x009A Autopointer 1 Address HIGH +AUTOPTRL1 0x009B Autopointer 1 Address LOW +AUTOPTRH2 0x009D Autopointer 1 Address HIGH +AUTOPTRL2 0x009E Autopointer 1 Address LOW + +IOC 0x00A0 Port C +IOC.D7 7 +IOC.D6 6 +IOC.D5 5 +IOC.D4 4 +IOC.D3 3 +IOC.D2 2 +IOC.D1 1 +IOC.D0 0 + +INT2CLR 0x00A1 Interrupt 2 clear +INT4CLR 0x00A2 Interrupt 4 clear + +IE 0x00A8 Interrupt Enable +IE.EA 7 +IE.ET2 5 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 + +EP2468STAT 0x00AA Endpoint 2,4,6,8 status flags +EP2468STAT.EP8F 7 +EP2468STAT.EP8E 6 +EP2468STAT.EP6F 5 +EP2468STAT.EP6E 4 +EP2468STAT.EP4F 3 +EP2468STAT.EP4E 2 +EP2468STAT.EP2F 1 +EP2468STAT.EP2E 0 + +EP24FIFOFLGS 0x00AB Endpoint 2,4 slave FIFO status flags +EP24FIFOFLGS.EP4PF 6 +EP24FIFOFLGS.EP4EF 5 +EP24FIFOFLGS.EP4FF 4 +EP24FIFOFLGS.EP2PF 2 +EP24FIFOFLGS.EP2EF 1 +EP24FIFOFLGS.EP2FF 0 + +EP68FIFOFLGS 0x00AC Endpoint 6,8 slave FIFO status flags +EP68FIFOFLGS.EP8PF 6 +EP68FIFOFLGS.EP8EF 5 +EP68FIFOFLGS.EP8FF 4 +EP68FIFOFLGS.EP6PF 2 +EP68FIFOFLGS.EP6EF 1 +EP68FIFOFLGS.EP6FF 0 + +AUTOPTRSETUP 0x00AF Autopointer 1&2 Setup + +IOD 0x00B0 Port D +IOD.D7 7 +IOD.D6 6 +IOD.D5 5 +IOD.D4 4 +IOD.D3 3 +IOD.D2 2 +IOD.D1 1 +IOD.D0 0 + +; port E is not bit-addressable +IOE 0x00B1 Port E + +OEA 0x00B2 Port A Output Enable +OEB 0x00B3 Port B Output Enable +OEC 0x00B4 Port C Output Enable +OED 0x00B5 Port D Output Enable +OEE 0x00B6 Port E Output Enable + +IP 0x00B8 Interrupt Priority Register +IP.PS1 6 +IP.PT2 5 +IP.PS0 4 +IP.PT1 3 +IP.PX1 2 +IP.PT0 1 +IP.PX0 0 + +EP01STAT 0x00ba Endpoint 0 and 1 Status +EP01STAT.EP1INBSY 2 +EP01STAT.EP1OUTBSY 1 +EP01STAT.EP0BSY 0 +GPIFTRIG 0x00bb Endpoint 2, 4, 6, 8 GPIF slave FIFO trigger +GPIFTRIG.DONE 7 +GPIFTRIG.RW 2 +GPIFTRIG.EP1 1 +GPIFTRIG.EP0 0 +GPIFSGLDATH 0x00bd GPIF Data H +GPIFSGLDATL 0x00be GPIF Data L with Trigger +GPIFSGLDATLNOX 0x00bf GPIF Data L with No Trigger + +SCON1 0x00C0 Serial Port 1 Control +SCON1.SM0 7 +SCON1.SM1 6 +SCON1.SM2 5 +SCON1.REN 4 +SCON1.TB8 3 +SCON1.RB8 2 +SCON1.TI 1 +SCON1.RI 0 + +SBUF1 0x00c1 Serial Port 1 Data Buffer +T2CON 0x00c8 Timer/Counter 2 Control +T2CON.TF2 7 +T2CON.EXF2 6 +T2CON.RCLK 5 +T2CON.TCLK 4 +T2CON.EXEN2 3 +T2CON.TR2 2 +T2CON.CT2 1 +T2CON.CPRL2 0 + +RCAP2L 0x00ca Capture for Timer 2, auto-reload, up-counter +RCAP2H 0x00cb Capture for Timer 2, auto-reload, up-counter +TL2 0x00cc Timer 2 reload L +TH2 0x00cd Timer 2 reload H +PSW 0x00d0 Program Status Word +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +EICON 0x00d8 External Interrupt Control +EICON.SMOD1 7 +EICON.ERESI 5 +EICON.RESI 4 +EICON.INT6 3 +ACC 0x00e0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 + +EIE 0x00e8 External Interrupt Enables + +B 0x00F0 B Register +B.D7 7 +B.D6 6 +B.D5 5 +B.D4 4 +B.D3 3 +B.D2 2 +B.D1 1 +B.D0 0 + +EIP 0x00f8 External Interrupt Priority Control + + +.SM5964 +; SyncMOS SM5964 +; http://www.keil.com/dd/chip/3767.htm +; http://www.keil.com/dd/docs/datashts/syncmos/sm5964.pdf + + +; MEMORY MAP +area CODE code 0x0000:0x10000 +area DATA RAM 0x0000:0x0300 +area DATA FSR 0x0080:0x0100 + + +; Interrupt and reset vector assignments +entry RESET 0x0000 RESET +entry IE0 0x0003 External interrupt 0 +entry TF0 0x000B Timer 0 interrupt +entry IE1 0x0013 External interrupt 1 +entry TF1 0x001B Timer 1 interrupt +entry RI_TI 0x0023 Serial port interrupt +entry TF2_EXF2 0x002B Timer 2 interrupt + + +; INPUT/OUTPUT PORTS +P0 0x0080 Port 0 +P0.P07 7 +P0.P06 6 +P0.P05 5 +P0.P04 4 +P0.P03 3 +P0.P02 2 +P0.P01 1 +P0.P00 0 +SP 0x0081 Stack Pointer +DPL 0x0082 Data Pointer, Low Byte +DPH 0x0083 Data Pointer, High Byte +RCON 0x0085 Internal RAM Control Register +RCON.RAMS0 0 +RCON.RAMS1 1 +DBANK 0x0086 Data Bank Control Register +DBANK.BSE 7 +DBANK.BS3 3 +DBANK.BS2 2 +DBANK.BS1 1 +DBANK.BS0 0 +PCON 0x0087 Power Control Register +PCON.SMOD 7 +PCON.PDS 6 +PCON.IDLS 5 +PCON.SD 4 +PCON.GF1 3 +PCON.GF0 2 +PCON.PDE 1 +PCON.IDLE 0 +TCON 0x0088 Timer 0/1 Control Register +TCON.TF1 7 +TCON.TR1 6 +TCON.TF0 5 +TCON.TR0 4 +TCON.IE1 3 +TCON.IT1 2 +TCON.IE0 1 +TCON.IT0 0 +TMOD 0x0089 Timer Mode Register +TMOD.GATE_0 7 +TMOD.C_T_0 6 +TMOD.M1_0 5 +TMOD.M0_0 4 +TMOD.GATE_1 3 +TMOD.C_T_1 2 +TMOD.M1_1 1 +TMOD.M0_1 0 +TL0 0x008A Timer 0, Low Byte +TL1 0x008B Timer 1, Low Byte +TH0 0x008C Timer 0, High Byte +TH1 0x008D Timer 1, High Byte +P1 0x0090 Port 1 +P1.SPWM4 7 +P1.SPWM3 6 +P1.SPWM2 5 +P1.SPWM1 4 +P1.SPWM0 3 +P1.T2EX 1 +P1.T2 0 +SCON 0x0098 Serial Channel Control Register +SCON.SM0 7 +SCON.SM1 6 +SCON.SM3 5 +SCON.REN 4 +SCON.TB8 3 +SCON.RB8 2 +SCON.TI 1 +SCON.RI 0 +SBUF 0x0099 Serial Channel Buffer Register +P1CON 0x009B Port 1 Configuration Register +P1CON.SPWM4E 7 SPWM function for pin SPWM4 +P1CON.SPWM3E 6 SPWM function for pin SPWM3 +P1CON.SPWM2E 5 SPWM function for pin SPWM2 +P1CON.SPWM1E 4 SPWM function for pin SPWM1 +P1CON.SPWM0E 3 SPWM function for pin SPWM0 +WDTC 0x009F Watch Dog Timer Control +WDTC.WDTE 7 Watch Dog Timer enable +WDTC.CLEAR 5 Watch Dog Timer counter clear +WDTC.PS2 2 Watch Dog Timer clock source divider bit 2 +WDTC.PS1 1 Watch Dog Timer clock source divider bit 1 +WDTC.PS0 0 Watch Dog Timer clock source divider bit 0 +P2 0x00A0 Port 2 +P2.P27 7 +P2.P26 6 +P2.P25 5 +P2.P24 4 +P2.P23 3 +P2.P22 2 +P2.P21 1 +P2.P20 0 +SPWMC 0x00A3 +SPWMC.FPDIV1 1 +SPWMC.FPDIV1 0 +SPWMD0 0x00A4 +SPWMD1 0x00A5 +SPWMD2 0x00A6 +SPWMD3 0x00A7 +IE 0x00A8 Interrupt Enable Register +IE.EA 7 +IE.ES 4 +IE.ET1 3 +IE.EX1 2 +IE.ET0 1 +IE.EX0 0 +SPWMD4 0x00AC +P3 0x00B0 Port 3 +P3.RD 7 +P3.WR 6 +P3.T1 5 +P3.T0 4 +P3.INT1 3 +P3.INT0 2 +P3.TxD0 1 +P3.RxD0 0 +IP 0x00B8 Interrupt Priority Register +IP.PS 4 +IP.PT1 3 +IP.PX1 2 +IP.PT0 1 +IP.PX0 0 +SCONF 0x00BF System Control Register +SCONF.WDR 7 Watch Dog Timer Reset. +SCONF.ISPE 2 ISP function enable bit +SCONF.OME 1 768 byte on-chip RAM enable bit +SCONF.ALEI 0 ALE output inhibit bit +T2CON 0x00C8 Timer 2 Control Register +T2CON.TF2 7 +T2CON.EXF2 6 +T2CON.RCLK 5 +T2CON.TCLK 4 +T2CON.EXEN2 3 +T2CON.TR2 2 +T2CON.C_T2 1 +T2CON.CP_RL2 0 +T2MOD 0x00C9 Timer 2 Mode Register +T2MOD.DCEN 0 +T2MOD.T2OE 1 +RC2L 0x00CA Timer 2 Reload/Capture Register, Low Byte +RC2H 0x00CB Timer 2 Reload/Capture Register, High Byte +TL2 0x00CC Timer 2 Low Byte +TH2 0x00CD Timer 2 High Byte +PSW 0x00D0 Program Status Word Register +PSW.CY 7 +PSW.AC 6 +PSW.F0 5 +PSW.RS1 4 +PSW.RS0 3 +PSW.OV 2 +PSW.F1 1 +PSW.P 0 +P4 0x00D8 Port 4 +P4.P47 7 +P4.P46 6 +P4.P45 5 +P4.P44 4 +P4.P43 3 +P4.P42 2 +P4.P41 1 +P4.P40 0 +ACC 0x00E0 Accumulator +ACC.ACC7 7 +ACC.ACC6 6 +ACC.ACC5 5 +ACC.ACC4 4 +ACC.ACC3 3 +ACC.ACC2 2 +ACC.ACC1 1 +ACC.ACC0 0 +B 0x00F0 B-Register +B.B7 7 +B.B6 6 +B.B5 5 +B.B4 4 +B.B3 3 +B.B2 2 +B.B1 1 +B.B0 0 +ISPFAH 0x00F4 ISP Flash Address High Register +ISPFAL 0x00F5 ISP Flash Address Low Register +ISPFD 0x00F6 ISP Flash Data Register +ISPC 0x00F7 ISP Flash Control Register +ISPC.START 7 ISP function start bit +ISPC.F1 1 ISP function select bit 1 +ISPC.F0 0 ISP function select bit 0 diff --git a/idasdk76/module/i51/i51.hpp b/idasdk76/module/i51/i51.hpp new file mode 100644 index 0000000..dadf2bf --- /dev/null +++ b/idasdk76/module/i51/i51.hpp @@ -0,0 +1,166 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su, ig@datarescue.com + * FIDO: 2:5020/209 + * + */ + +#ifndef _I51_HPP +#define _I51_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include "../iohandler.hpp" + +//------------------------------------------------------------------ +enum processor_subtype_t +{ + // odd types are binary mode + // even types are source modes + prc_51 = 0, // plain 8051 + prc_251_bin, // 80251 in binary mode + prc_251 = prc_251_bin, // the same... (a shortcut) + prc_251_src, // 80251 in source mode + prc_930_bin, // 8x930 in source mode + prc_930 = prc_930_bin, // the same... (a shortcut) + prc_930_src, // 8x930 in source mode + prc_51mx, +}; + +//------------------------------------------------------------------------ +// customization of the 'cmd' structure: + +// 8051 bit references: + +#define o_bit o_idpspec0 +#define o_bitnot o_idpspec1 + +// fRi indirect register number (for o_phrase): +#define indreg specflag1 + +// displacement is an immediate number (print #) (for o_displ): +#define imm_disp specflag1 + +// 80251 bit references (bit address in x.addr): + +#define o_bit251 o_idpspec2 +#define b251_bit specflag1 // bit number +#define b251_bitneg specflag2 // negate? + + +// cmd.auxpref bits: + +#define aux_0ext 0x0001 // high bit 0-extension immediate value +#define aux_1ext 0x0002 // high bit 1-extension immediate value + + +// ash.uflag bit meanings: + +#define UAS_PSAM 0x0001 // PseudoSam: use funny form of + // equ for intmem +#define UAS_SECT 0x0002 // Segments are named .SECTION +#define UAS_NOSEG 0x0004 // No 'segment' directives +#define UAS_NOBIT 0x0008 // No bit.# names, use bit_# +#define UAS_SELSG 0x0010 // Segment should be selected by its name +#define UAS_EQCLN 0x0020 // ':' in EQU directives +#define UAS_AUBIT 0x0040 // Don't use BIT directives - + // assembler generates bit names itself +#define UAS_CDSEG 0x0080 // Only DSEG,CSEG,XSEG +#define UAS_NODS 0x0100 // No .DS directives in Code segment +#define UAS_NOENS 0x0200 // don't specify start addr in the .end directive +#define UAS_PBIT 0x0400 // assembler knows about predefined bits +#define UAS_PBYTNODEF 0x0800 // do not define predefined byte names + +//------------------------------------------------------------------------ +// Registers +enum i51_registers +{ + rAcc, rAB, rB, + rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7, + rR8, rR9, r10, r11, rR12, rR13, rR14, rR15, + rWR0, rWR2, rWR4, rWR6, rWR8, rWR10, rWR12, rWR14, + rWR16, rWR18, rWR20, rWR22, rWR24, rWR26, rWR28, rWR30, + rDR0, rDR4, rDR8, rDR12, rDR16, rDR20, rDR24, rDR28, + rDR32, rDR36, rDR40, rDR44, rDR48, rDR52, rDR56, rDR60, + rDptr, rC, rPC, + rEptr, rPR0, rPR1, // 51mx registers + rVcs, rVds // these 2 registers are required by the IDA kernel +}; + +// Indirect addressing modes without a displacement: +enum i51_phrases +{ + fR0, // @R0 + fR1, // @R1 + fDptr, // @DPTR + fAdptr, // @A+DPTR + fApc, // @A+PC + fRi, // @WRj or @DRj, reg number in indreg + fEptr, // @EPTR + fAeptr, // @A+EPTR + fPr0, // @PR0 + fPr1, // @PR1 +}; + +//------------------------------------------------------------------------ +bool is_sane_insn(const insn_t &insn, int reason); + +//------------------------------------------------------------------ +struct i51_iohandler_t : public iohandler_t +{ + struct i51_t ± + i51_iohandler_t(i51_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual void apply_io_port(ea_t ea, const char *name, const char *cmt) override; + virtual void get_cfg_filename(char *buf, size_t bufsize) override; + virtual bool segment_created(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override; +}; + +DECLARE_PROC_LISTENER(idb_listener_t, struct i51_t); + +struct i51_t : public procmod_t +{ + netnode helper; + i51_iohandler_t ioh = i51_iohandler_t(*this, helper); + idb_listener_t idb_listener = idb_listener_t(*this); + processor_subtype_t ptype = prc_51; + ea_t intmem = 0; // address of the internal memory + ea_t sfrmem = 0; // address of SFR memory + bool flow = false; + bool first_time = true; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + const ioport_bit_t *find_bit(ea_t address, int bit); + bool IsPredefined(const char *name); + ea_t AdditionalSegment(size_t size, size_t offset, const char *name) const; + uint32 truncate(uval_t addr) const; + int ana_extended(insn_t &insn); + void attach_bit_comment(const insn_t &insn, ea_t addr, int bit); + void setup_data_segment_pointers(void); + void i51_header(outctx_t &ctx); + int out_equ(outctx_t &ctx); + void i51_data(outctx_t &ctx, bool analyze_only); + ea_t i51_map_data_ea(const insn_t &insn, ea_t addr, int opnum) const; + void handle_operand(const insn_t &insn, const op_t &x, bool loading); + int emu(const insn_t &insn); + int ana_basic(insn_t &insn); + int ana(insn_t *_insn); + void i51_segstart(outctx_t &ctx, segment_t *Sarea) const; + void i51_footer(outctx_t &ctx) const; + void do_out_equ(outctx_t &ctx, const char *name, const char *equ, uchar off) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ intel 8051" +#define PROCMOD_NAME i51 +#endif diff --git a/idasdk75/module/i51/ins.cpp b/idasdk76/module/i51/ins.cpp similarity index 100% rename from idasdk75/module/i51/ins.cpp rename to idasdk76/module/i51/ins.cpp diff --git a/idasdk76/module/i51/ins.hpp b/idasdk76/module/i51/ins.hpp new file mode 100644 index 0000000..60c6ef0 --- /dev/null +++ b/idasdk76/module/i51/ins.hpp @@ -0,0 +1,92 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint8) +{ +I51_null = 0, // Unknown Operation + +I51_acall, // Absolute Call +I51_add, // Add Second Operand to Acc +I51_addc, // Add Second Operand to Acc with carry +I51_ajmp, // Absolute Jump +I51_anl, // Logical AND (op1 &= op2) +I51_cjne, // Compare Operands and JNE +I51_clr, // Clear Operand (0) +I51_cpl, // Complement Operand +I51_da, // Decimal Adjust Accumulator +I51_dec, // Decrement Operand +I51_div, // Divide Acc by B +I51_djnz, // Decrement Operand and JNZ +I51_inc, // Increment Operand +I51_jb, // Jump if Bit is set +I51_jbc, // Jump if Bit is set & clear Bit +I51_jc, // Jump if Carry is set +I51_jmp, // Jump indirect relative to Data Pointer +I51_jnb, // Jump if Bit is clear +I51_jnc, // Jump if Carry is clear +I51_jnz, // Jump if Acc is not zero +I51_jz, // Jump if Acc is zero +I51_lcall, // Long Subroutine Call +I51_ljmp, // Long Jump +I51_mov, // Move (Op1 <- Op2) +I51_movc, // Move code byte relative to second op to Acc +I51_movx, // Move from/to external RAM +I51_mul, // Multiply Acc by B +I51_nop, // No operation +I51_orl, // Logical OR (op1 |= op2) +I51_pop, // Pop from Stack and put in Direct RAM +I51_push, // Push from Direct RAM to Stack +I51_ret, // Return from subroutine +I51_reti, // Return from Interrupt +I51_rl, // Rotate Acc left +I51_rlc, // Rotate Acc left through Carry +I51_rr, // Rotate Acc right +I51_rrc, // Rotate Acc right through Carry +I51_setb, // Set Direct Bit +I51_sjmp, // Short jump +I51_subb, // Subtract Second Operand from Acc with Borrow +I51_swap, // Swap nibbles of Acc +I51_xch, // Exchange Operands +I51_xchd, // Exchange Digit in Acc with Indirect RAM +I51_xrl, // Exclusive OR (op1 ^= op2) + +// 80251 instructions + +I51_jsle, // Jump if less than or equal (signed) +I51_jsg, // Jump if greater than (signed) +I51_jle, // Jump if less than or equal +I51_jg, // Jump if greater than +I51_jsl, // Jump if less than (signed) +I51_jsge, // Jump if greater than or equal (signed) +I51_je, // Jump if equal +I51_jne, // Jump if not equal +I51_trap, // Trap +I51_ejmp, // Extended jump +I51_ecall, // Extended call +I51_eret, // Extended return +I51_movh, // Move immediate 16-bit data to the high word of a dword (double-word) register +I51_movz, // Move 8-bit register to 16-bit register with zero extension +I51_movs, // Move 8-bit register to 16-bit register with sign extension +I51_srl, // Shift logical right by 1 bit +I51_sra, // Shift arithmetic right by 1 bit +I51_sll, // Shift logical left by 1 bit +I51_sub, // Subtract +I51_cmp, // Compare + +// 51mx instructions +I51_emov, // Move (A <- @PRi+disp) or (@PRi+disp <- A) + +I51_last, + + }; + +#endif diff --git a/idasdk76/module/i51/makefile b/idasdk76/module/i51/makefile new file mode 100644 index 0000000..cdebf28 --- /dev/null +++ b/idasdk76/module/i51/makefile @@ -0,0 +1,57 @@ +PROC=i51 +CONFIGS=i51.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp i51.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp i51.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + i51.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + i51.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp i51.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/i51/out.cpp b/idasdk76/module/i51/out.cpp similarity index 100% rename from idasdk75/module/i51/out.cpp rename to idasdk76/module/i51/out.cpp diff --git a/idasdk76/module/i51/reg.cpp b/idasdk76/module/i51/reg.cpp new file mode 100644 index 0000000..096cdef --- /dev/null +++ b/idasdk76/module/i51/reg.cpp @@ -0,0 +1,900 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su, ig@datarescue.com + * FIDO: 2:50620/209 + * + */ + +#include "i51.hpp" +#include <entry.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "A", "AB", "B", + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", + "WR0", "WR2", "WR4", "WR6", "WR8", "WR10", "WR12", "WR14", + "WR16", "WR18", "WR20", "WR22", "WR24", "WR26", "WR28", "WR30", + "DR0", "DR4", "DR8", "DR12", "DR16", "DR20", "DR24", "DR28", + "DR32", "DR36", "DR40", "DR44", "DR48", "DR52", "DPX", "SPX", + "DPTR","C", "PC", + "EPTR", "PR0", "PR1", + "cs","ds" +}; + +//---------------------------------------------------------------------- +static const char cfgname[] = "i51.cfg"; + +void i51_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) +{ + qstrncpy(buf, cfgname, bufsize); +} + +void i51_iohandler_t::apply_io_port(ea_t ea, const char *name, const char *cmt) +{ + if ( ea >= 0x80 && ea < 0x100 ) + { + // specail mapping alg for i51 FSR regs + segment_t *s = get_segm_by_name("FSR"); + if ( s != NULL ) + { + ea_t map = ea + s->start_ea - 0x80; + if ( is_mapped(map) ) + ea = map; + } + } + set_name(ea, name, SN_NODUMMY); + set_cmt(ea, cmt, true); +} + +bool i51_iohandler_t::segment_created(ea_t start, ea_t end, const char *word, const char *) +{ + if ( stristr(word, "FSR") != NULL || stristr(word, "RAM") != NULL ) + { + pm.AdditionalSegment(end-start, start, word); + return true; + } + return false; +} + +//------------------------------------------------------------------ +const char *i51_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT); + return IDPOPT_OK; +} + +//------------------------------------------------------------------ +const ioport_bit_t *i51_t::find_bit(ea_t address, int bit) +{ + return find_ioport_bit(ioh.ports, address, bit); +} + +//---------------------------------------------------------------------- +bool i51_t::IsPredefined(const char *name) +{ + for ( int i=0; i < ioh.ports.size(); i++ ) + { + const ioport_t &p = ioh.ports[i]; + if ( p.name == name ) + return true; + for ( int j=0; j < p.bits.size(); j++ ) + if ( p.bits[j].name == name ) + return true; + } + return false; +} + +//---------------------------------------------------------------------- +struct entry_t +{ + char proc; + char off; + const char *name; //lint !e958 padding is required to align members + const char *cmt; +}; + +static const entry_t entries[] = +{ + { prc_51, 0x03, "extint0", "External interrupt 0 (INT0 / EX0)" }, + { prc_51, 0x0B, "timint0", "Timer interrupt 0 (TIM0)" }, + { prc_51, 0x13, "extint1", "External interrupt 1 (INT1 / EX1)" }, + { prc_51, 0x1B, "timint1", "Timer interrupt 1 (TIM1)" }, + { prc_51, 0x23, "serint", "Serial port interrupt (SERIAL)" }, + { prc_51, 0x2B, "timint2", "Timer interrupt 2 (TIM2) (52 or higher)" }, + { prc_51, 0x33, "pcaint", "PCA (programmable counter array) interrupt\n(only 51f or higher)" }, + { prc_930, 0x43, "usbhub", "USB Hub/SOF (isochronous end point) (only 930)" }, + { prc_930, 0x4B, "usbfun", "USB Function (non-isochronous end point) (only 930)" }, + { prc_930, 0x53, "usbglb", "USB Global Suspend/Resume and USB Reset (only 930)" }, + { prc_251, 0x7B, "trapint", "TRAP (program interrupt) (only 251 or 930)" } +}; + +//---------------------------------------------------------------------- +// Get linear address of a special segment +// sel - selector of the segment +static ea_t specialSeg(segment_t *s) +{ + if ( s->type != SEG_IMEM ) // is the segment type correct? - no + { + s->type = SEG_IMEM; // fix it + s->update(); + } + return s->start_ea; +} + +//---------------------------------------------------------------------- +ea_t i51_t::AdditionalSegment(size_t size, size_t offset, const char *name) const +{ + segment_t s; + s.start_ea = (ptype > prc_51) + ? (inf_get_max_ea() + 0xF) & ~0xF + : free_chunk(0, size, 0xF); + s.end_ea = s.start_ea + size; + s.sel = allocate_selector((s.start_ea-offset) >> 4); + s.type = SEG_IMEM; // internal memory + add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_OR_DIE); + return s.start_ea - offset; +} + +//---------------------------------------------------------------------- +void i51_t::setup_data_segment_pointers(void) +{ + segment_t *s = get_segm_by_name("INTMEM"); + if ( s == NULL ) + s = get_segm_by_name("RAM"); + if ( s != NULL ) + intmem = specialSeg(s); + + s = get_segm_by_name("SFR"); + if ( s == NULL ) + s = get_segm_by_name("FSR"); + if ( s != NULL ) + sfrmem = specialSeg(s) - 0x80; +} + +//-------------------------------------------------------------------------- +void i51_t::load_from_idb() +{ + ioh.restore_device(); + // restore ptype + ptype = processor_subtype_t(ph.get_proc_index()); + setup_data_segment_pointers(); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) +{ + switch ( code ) + { + case idb_event::segm_moved: // A segment is moved + // Fix processor dependent address sensitive information + { + // ea_t from = va_arg(va, ea_t); + // ea_t to = va_arg(va, ea_t); + // asize_t size = va_arg(va, asize_t); + // bool changed_netmap = va_argi(va, bool); + + // Add commands to adjust your internal variables here + // Most of the time this callback will be empty + // + // If you keep information in a netnode's altval array, you can use + // node.altshift(from, s->start_ea, s->end_ea - s->start_ea); + // + // If you have a variables pointing to somewhere in the disassembled program memory, + // you can adjust it like this: + // + // if ( var >= from && var < from+size ) + // var += to - from; + } + break; + } + return 0; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(i51_t)); + return 0; +} + +ssize_t idaapi i51_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + hook_event_listener(HT_IDB, &idb_listener, &LPH); + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); // Set a big endian mode of the IDA kernel + break; + + case processor_t::ev_term: + ioh.ports.clear(); + unhook_event_listener(HT_IDB, &idb_listener); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + segment_t *sptr = get_first_seg(); + if ( sptr != NULL ) + { + if ( sptr->start_ea-get_segm_base(sptr) == 0 ) + { + inf_set_start_ea(sptr->start_ea); + inf_set_start_ip(0); + for ( int i=0; i < qnumber(entries); i++ ) + { + if ( entries[i].proc > ptype ) + continue; + ea_t ea = inf_get_start_ea()+entries[i].off; + if ( is_mapped(ea) && get_byte(ea) != 0xFF ) + { + add_entry(ea, ea, entries[i].name, 1); + set_cmt(ea, entries[i].cmt, 1); + } + } + } + } + segment_t *scode = get_first_seg(); + set_segm_class(scode, "CODE"); + + if ( ptype > prc_51 ) + { + AdditionalSegment(0x10000-256-128, 256+128, "RAM"); + if ( scode != NULL ) + { + ea_t align = (scode->end_ea + 0xFFF) & ~0xFFF; + if ( getseg(align-7) == scode ) // the code segment size is + { // multiple of 4K or near it + uchar b0 = get_byte(align-8); + // 251: + // 0 : 1-source, 0-binary mode + // 6,7: must be 1s + // 82930: + // 0 : 1-source, 0-binary mode + // 7 : must be 1s +// uchar b1 = get_byte(align-7); + // 251 + // 0: eprommap 0 - FE2000..FE4000 is mapped into 00E000..100000 + // 1 - .............. is not mapped ............... + // 1: must be 1 + // 3: + // 2: must be 1 + // 4: intr 1 - upon interrupt PC,PSW are pushed into stack + // 0 - upon interrupt only PC is pushed into stack + // 5: must be 1 + // 6: must be 1 + // 7: must be 1 + // 82930: + // 3: must be 1 + // 5: must be 1 + // 6: must be 1 + // 7: must be 1 +// msg("b0=%x b1=%x\n", b0, b1); +// if ( (b0 & 0x80) == 0x80 && (b1 & 0xEA) == 0xEA ) + { // the init bits are correct + char pname[IDAINFO_PROCNAME_SIZE]; + inf_get_procname(pname, sizeof(pname)); + char ntype = (b0 & 1) ? 's' : 'b'; + char *ptr = tail(pname)-1; + if ( ntype != *ptr + && ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "The input file seems to be for the %s mode of the processor.\n" + "Do you want to change the current processor type?", + ntype == 's' ? "source" : "binary") > 0 ) + { + *ptr = ntype; + first_time = true; + set_processor_type(pname, SETPROC_USER); + } + } + } + } + } + + // the default data segment will be INTMEM + { + segment_t *s = getseg(intmem); + if ( s != NULL ) + set_default_dataseg(s->sel); + } + + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + + if ( get_segm_by_name("RAM") == NULL ) + AdditionalSegment(256, 0, "RAM"); + if ( get_segm_by_name("FSR") == NULL ) + AdditionalSegment(128, 128, "FSR"); + setup_data_segment_pointers(); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + // make the default DS point to INTMEM + // (8051 specific issue) + { + segment_t *newseg = va_arg(va, segment_t *); + segment_t *intseg = getseg(intmem); + if ( intseg != NULL ) + newseg->defsr[rVds-ph.reg_first_sreg] = intseg->sel; + } + break; + + case processor_t::ev_newprc: + { + processor_subtype_t prcnum = processor_subtype_t(va_arg(va, int)); + // bool keep_cfg = va_argi(va, bool); + if ( !first_time && prcnum != ptype ) + { + warning("Sorry, it is not possible to change" // (this is 8051 specific) + " the processor mode on the fly." + " Please reload the input file" + " if you want to change the processor."); + code = -1; + break; + } + first_time = false; + ptype = prcnum; + } + break; + + case processor_t::ev_newasm: // new assembler type + ioh.restore_device(); + break; + + case processor_t::ev_is_sane_insn: + // is the instruction sane for the current file type? + // arg: int no_crefs + // 1: the instruction has no code refs to it. + // ida just tries to convert unexplored bytes + // to an instruction (but there is no other + // reason to convert them into an instruction) + // -1: the instruction is created because + // of some coderef, user request or another + // weighty reason. + // The instruction is in 'cmd' + // returns: 1-ok, <=0-no, the instruction isn't + // likely to appear in the program + { + const insn_t *insn = va_arg(va, insn_t *); + int reason = va_arg(va, int); + return is_sane_insn(*insn, reason) == 1 ? 1 : -1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + i51_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + i51_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + i51_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + i51_data(*ctx, analyze_only); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// ASMI +//----------------------------------------------------------------------- +static const asm_t asmi = +{ + AS_COLON | ASH_HEXF3 | AS_1TEXT | AS_NCHRE | ASO_OCTF1 | AS_RELSUP, + UAS_PSAM | UAS_NOSEG | UAS_AUBIT | UAS_PBIT | UAS_NOENS, + "ASMI", + 0, + NULL, // no headers + ".equ $, ", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".text", // ascii string directive + ".byte", // byte directive + ".word", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".byte 0xFF;(array %s)", // uninited arrays + ".equ", // equ + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// 8051 Macro Assembler - Version 4.02a +// Copyright (C) 1985 by 2500 A.D. Software, Inc. +//----------------------------------------------------------------------- +static const asm_t adasm = +{ + AS_COLON | ASH_HEXF0, + UAS_PBIT | UAS_SECT, + "8051 Macro Assembler by 2500 A.D. Software", + 0, + NULL, // no headers + "org", + "end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + "long", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "reg", // equ + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof + 0, // flag2 + NULL, // close comment + COLSTR("<", SCOLOR_SYMBOL) "%s", // low8 + COLSTR(">", SCOLOR_SYMBOL) "%s", // high8 + NULL, // low16 + NULL, // high16 +}; + +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const char *const ps_headers[] = +{ + ".code", + NULL +}; + +static const asm_t pseudosam = +{ + AS_COLON | ASH_HEXF1 | AS_N2CHR, + UAS_PBIT | UAS_PSAM | UAS_SELSG, + "PseudoSam by PseudoCode", + 0, + ps_headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".rs %s", // uninited arrays + ".equ", // equ + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// Cross-16 assembler definiton +//----------------------------------------------------------------------- +static const char *const cross16_headers[] = +{ + "cpu \"8051.tbl\"", + NULL +}; + +static const asm_t cross16 = +{ + AS_COLON | ASH_HEXF0 | AS_NHIAS, + UAS_PBIT | UAS_NOSEG | UAS_NOBIT | UAS_EQCLN, + "Cross-16 by Universal Cross-Assemblers", + 0, + cross16_headers, + "org", + "end", + + ";", // comment string + '"', // string delimiter + '\0', // char delimiter (no char consts) + "\\\"'", // special symbols in char and string constants + + "dfb", // ascii string directive + "dfb", // byte directive + "dwm", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// 8051 Cross-Assembler by MetaLink Corporation +//----------------------------------------------------------------------- +static const asm_t mcross = +{ + AS_COLON | ASH_HEXF0 | AS_NHIAS, + UAS_NOSEG | UAS_CDSEG | UAS_AUBIT | UAS_NODS | UAS_NOENS, + "8051 Cross-Assembler by MetaLink Corporation", + 0, + NULL, + "org", + "end", + + ";", // comment string + '\'', // string delimiter + '\0', // char delimiter (no char consts) + "\\\"'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// TASM assembler definiton +//----------------------------------------------------------------------- +static const char *const tasm_headers[] = +{ + ".msfirst", + NULL +}; + +static const asm_t tasm = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_PBIT | UAS_NOENS | UAS_EQCLN | UAS_NOSEG, + "Table Driven Assembler (TASM) by Speech Technology Inc.", + 0, + tasm_headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".text", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".block %s", // uninited arrays + ".equ", + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + "and", // and + "or", // or + NULL, // xor + "not", // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = +{ + &asmi, &adasm, &pseudosam, &cross16, &mcross, &tasm, NULL +}; + +//----------------------------------------------------------------------- +// The short and long names of the supported processors +#define FAMILY "Intel 51 series:" + +static const char *const shnames[] = +{ + "8051", + "80251b", + "80251s", + "80930b", + "80930s", + "8051mx", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Intel 8051", + "Intel 80251 in binary mode", + "Intel 80251 in source mode", + "Intel 80930 in binary mode", + "Intel 80930 in source mode", + "Intel 8051MX", + NULL +}; + +//-------------------------------------------------------------------------- +// Opcodes of "return" instructions. This information will be used in 2 ways: +// - if an instruction has the "return" opcode, its autogenerated label +// will be "locret" rather than "loc". +// - IDA will use the first "return" opcode to create empty subroutines. + +static const uchar retcode_1[] = { 0x22 }; +static const uchar retcode_2[] = { 0x32 }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } // NULL terminated array +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_8051, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_SEGTRANS // segment translation is supported (map_code_ea) + | PR_BINMEM, // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 0, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0,I51_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + I51_ret, // Icode of return instruction. It is ok to give any of possible return instructions + +}; diff --git a/idasdk75/module/i860/ana.cpp b/idasdk76/module/i860/ana.cpp similarity index 100% rename from idasdk75/module/i860/ana.cpp rename to idasdk76/module/i860/ana.cpp diff --git a/idasdk76/module/i860/emu.cpp b/idasdk76/module/i860/emu.cpp new file mode 100644 index 0000000..7f4decf --- /dev/null +++ b/idasdk76/module/i860/emu.cpp @@ -0,0 +1,147 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "i860.hpp" + +//------------------------------------------------------------------------ +static void set_immd_bit(const insn_t &insn) +{ + set_immd(insn.ea); + if ( is_defarg(get_flags(insn.ea), 1) ) + return; + switch ( insn.itype ) + { + case I860_and: + case I860_andh: + case I860_andnot: + case I860_andnoth: + case I860_xor: + case I860_xorh: + op_num(insn.ea, 1); + break; + } +} + +//---------------------------------------------------------------------- +bool i860_t::handle_operand(const insn_t &insn, const op_t &x, bool isload) const +{ + dref_t xreftype; + uchar outf; + switch ( x.type ) + { + case o_phrase: // 2 registers + case o_reg: + break; + case o_imm: + if ( !isload ) + goto badTouch; + xreftype = dr_O; + outf = OOF_SIGNED; + goto makeImm; + case o_displ: + xreftype = isload ? dr_R : dr_W; + outf = OOF_SIGNED|OOF_ADDR; +makeImm: + set_immd_bit(insn); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, xreftype, outf); + break; + case o_mem: + insn.create_op_data(x.addr, x); + insn.add_dref(x.addr, x.offb, isload ? dr_R : dr_W); + break; + case o_near: + { + int iscall = has_insn_feature(insn.itype,CF_CALL); + insn.add_cref(x.addr, x.offb, iscall ? fl_CN : fl_JN); + if ( iscall && !func_does_return(x.addr) ) + return false; + } + break; + default: +badTouch: + warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); + break; + } + return true; +} + +//---------------------------------------------------------------------- +static bool isDual(uint32 code) +{ + return int(code>>26) == 0x12 && (code & Dbit) != 0; +} + +//---------------------------------------------------------------------- +static int isDelayedStop(uint32 code) +{ + // br bri + int opcode = int(code >> 26); + switch ( opcode ) + { + case 0x10: // bri + case 0x1A: // br + return 1; + } + return 0; +} + +//---------------------------------------------------------------------- +static bool canFlow(const insn_t &insn) +{ + if ( !is_flow(get_flags(insn.ea)) ) + return 1; // no previous instructions + ea_t ea = insn.ea - 4; + flags_t F = get_flags(ea); + if ( is_flow(F) && is_code(F) ) + { + if ( isDelayedStop(get_dword(ea)) ) // now or later + { + ea -= 4; + if ( !is_code(get_flags(ea)) || !isDual(get_dword(ea)) ) + return 0; + return 1; + } + if ( is_flow(F) ) + { + ea -= 4; + return !is_code(get_flags(ea)) || !isDelayedStop(get_dword(ea)); + } + } + return 1; +} + +//---------------------------------------------------------------------- +int i860_t::i860_emu(const insn_t &insn) const +{ + bool flow = true; + + uint32 Feature = insn.get_canon_feature(ph); + + if ( Feature & CF_USE1 && !handle_operand(insn, insn.Op1, true) ) + flow = false; + if ( Feature & CF_USE2 && !handle_operand(insn, insn.Op2, true) ) + flow = false; + if ( Feature & CF_USE3 && !handle_operand(insn, insn.Op3, true) ) + flow = false; + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( Feature & CF_CHG1 && !handle_operand(insn, insn.Op1, false) ) + flow = false; + if ( Feature & CF_CHG2 && !handle_operand(insn, insn.Op2, false) ) + flow = false; + if ( Feature & CF_CHG3 && !handle_operand(insn, insn.Op3, false) ) + flow = false; + + if ( flow && canFlow(insn) ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + return 1; +} diff --git a/idasdk75/module/i860/i860.hpp b/idasdk76/module/i860/i860.hpp similarity index 100% rename from idasdk75/module/i860/i860.hpp rename to idasdk76/module/i860/i860.hpp diff --git a/idasdk75/module/i860/ins.cpp b/idasdk76/module/i860/ins.cpp similarity index 100% rename from idasdk75/module/i860/ins.cpp rename to idasdk76/module/i860/ins.cpp diff --git a/idasdk76/module/i860/ins.hpp b/idasdk76/module/i860/ins.hpp new file mode 100644 index 0000000..187ce58 --- /dev/null +++ b/idasdk76/module/i860/ins.hpp @@ -0,0 +1,171 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + +I860_null = 0, // Unknown Operation + +// +// Intel 860 XP instructions +// + +I860_adds, +I860_addu, +I860_and, +I860_andh, +I860_andnot, +I860_andnoth, +I860_bc, +I860_bc_t, +I860_bla, +I860_bnc, +I860_bnc_t, +I860_br, +I860_bri, +I860_bte, +I860_btne, +I860_call, +I860_calli, +I860_fadd, +I860_faddp, +I860_faddz, +I860_famov, +I860_fiadd, +I860_fisub, +I860_fix, +I860_fld, +I860_flush, +I860_fmlow_dd, +I860_fmul, +I860_form, +I860_frcp, +I860_frsqr, +I860_fst, +I860_fsub, +I860_ftrunc, +I860_fxfr, +I860_fzchkl, +I860_fzchks, +I860_introvr, +I860_ixfr, +I860_ld_c, +I860_ld, +I860_ldint, +I860_ldio, +I860_lock, +I860_or, +I860_orh, +I860_pfadd, +I860_pfaddp, +I860_pfaddz, +I860_pfamov, +I860_pfeq, +I860_pfgt, +I860_pfiadd, +I860_pfisub, +I860_pfix, +I860_pfld, +I860_pfle, +I860_pfmul, +I860_pfmul3_dd, +I860_pform, +I860_pfsub, +I860_pftrunc, +I860_pfzchkl, +I860_pfzchks, +I860_pst_d, +I860_scyc, +I860_shl, +I860_shr, +I860_shra, +I860_shrd, +I860_st_c, +I860_st, +I860_stio, +I860_subs, +I860_subu, +I860_trap, +I860_unlock, +I860_xor, +I860_xorh, +// +// iNTEL 860 XP Pipelined F-P instructions +// +I860_r2p1, +I860_r2pt, +I860_r2ap1, +I860_r2apt, +I860_i2p1, +I860_i2pt, +I860_i2ap1, +I860_i2apt, +I860_rat1p2, +I860_m12apm, +I860_ra1p2, +I860_m12ttpa, +I860_iat1p2, +I860_m12tpm, +I860_ia1p2, +I860_m12tpa, +I860_r2s1, +I860_r2st, +I860_r2as1, +I860_r2ast, +I860_i2s1, +I860_i2st, +I860_i2as1, +I860_i2ast, +I860_rat1s2, +I860_m12asm, +I860_ra1s2, +I860_m12ttsa, +I860_iat1s2, +I860_m12tsm, +I860_ia1s2, +I860_m12tsa, +I860_mr2p1, +I860_mr2pt, +I860_mr2mp1, +I860_mr2mpt, +I860_mi2p1, +I860_mi2pt, +I860_mi2mp1, +I860_mi2mpt, +I860_mrmt1p2, +I860_mm12mpm, +I860_mrm1p2, +I860_mm12ttpm, +I860_mimt1p2, +I860_mm12tpm, +I860_mim1p2, +I860_mr2s1, +I860_mr2st, +I860_mr2ms1, +I860_mr2mst, +I860_mi2s1, +I860_mi2st, +I860_mi2ms1, +I860_mi2mst, +I860_mrmt1s2, +I860_mm12msm, +I860_mrm1s2, +I860_mm12ttsm, +I860_mimt1s2, +I860_mm12tsm, +I860_mim1s2, + +I860_last, + + }; + +#endif diff --git a/idasdk76/module/i860/makefile b/idasdk76/module/i860/makefile new file mode 100644 index 0000000..fb53862 --- /dev/null +++ b/idasdk76/module/i860/makefile @@ -0,0 +1,50 @@ +PROC=i860 + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp i860.hpp \ + ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp i860.hpp \ + ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp i860.hpp ins.cpp \ + ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp i860.hpp ins.hpp \ + out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp i860.hpp ins.hpp \ + reg.cpp diff --git a/idasdk75/module/i860/out.cpp b/idasdk76/module/i860/out.cpp similarity index 100% rename from idasdk75/module/i860/out.cpp rename to idasdk76/module/i860/out.cpp diff --git a/idasdk75/module/i860/reg.cpp b/idasdk76/module/i860/reg.cpp similarity index 100% rename from idasdk75/module/i860/reg.cpp rename to idasdk76/module/i860/reg.cpp diff --git a/idasdk75/module/i960/ana.cpp b/idasdk76/module/i960/ana.cpp similarity index 100% rename from idasdk75/module/i960/ana.cpp rename to idasdk76/module/i960/ana.cpp diff --git a/idasdk75/module/i960/emu.cpp b/idasdk76/module/i960/emu.cpp similarity index 100% rename from idasdk75/module/i960/emu.cpp rename to idasdk76/module/i960/emu.cpp diff --git a/idasdk75/module/i960/i960.cfg b/idasdk76/module/i960/i960.cfg similarity index 100% rename from idasdk75/module/i960/i960.cfg rename to idasdk76/module/i960/i960.cfg diff --git a/idasdk76/module/i960/i960.hpp b/idasdk76/module/i960/i960.hpp new file mode 100644 index 0000000..969d442 --- /dev/null +++ b/idasdk76/module/i960/i960.hpp @@ -0,0 +1,127 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _I960_HPP +#define _I960_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + +// Absolute offset (<4096) offset exp MEMA o_imm +// Absolute displacement disp exp MEMB o_imm +// Register Indirect abase (reg) o_phrase, index=-1, scale=1 +// with offset abase+offset exp(reg) o_displ, index=-1,scale=1 +// with displacement abase+disp exp(reg) o_displ, index=-1,scale=1 +// with index abase+(index*scale) (reg)[reg*scale] o_phrase, index=index +// with index and displacement abase+(index*scale)+disp exp(reg)[reg*scale] o_displ +// Index with displacement (index*scale) + disp exp[reg*scale] o_displ, reg=index, index=-1 +// IP with displacement IP+disp+8 exp(IP) o_near + +#define index specflag1 // o_displ, o_phrase +#define scale specflag2 // o_displ, o_phrase + +#define aux_t 0x0001 // .t suffix +#define aux_f 0x0002 // .f suffix +#define aux_ip 0x0004 // ip relative addressing + +//------------------------------------------------------------------ +enum regnum_t +{ + LR0, LR1, LR2, LR3, LR4, LR5, LR6, LR7, + LR8, LR9, LR10, LR11, LR12, LR13, LR14, LR15, + GR0, GR1, GR2, GR3, GR4, GR5, GR6, GR7, + GR8, GR9, GR10, GR11, GR12, GR13, GR14, GR15, + SF0, SF31=SF0+31, + PC, AC, IP, TC, + FP0, FP1, FP2, FP3, + ds, cs, + MAXREG = cs, + PFP = LR0, + SP = LR1, + RIP = LR2, + FP = GR15, + IPND = SF0+0, + IMSK = SF0+1, + DMAC = SF0+2, +}; + +//------------------------------------------------------------------ +ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea +//------------------------------------------------------------------ +void idaapi i960_header(outctx_t &ctx); + +void idaapi i960_segend(outctx_t &ctx, segment_t *seg); +void idaapi i960_assumes(outctx_t &ctx); // function to produce assume directives + +int idaapi is_align_insn(ea_t ea); + +//------------------------------------------------------------------ +struct tabent_t +{ + ushort itype; + char opnum; + char dtype; +}; + +//------------------------------------------------------------------ +struct i960_iohandler_t : public iohandler_t +{ + struct i960_t ± + i960_iohandler_t(i960_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} +}; + +struct i960_t : public procmod_t +{ + netnode helper; + i960_iohandler_t ioh = i960_iohandler_t(*this, helper); + + ushort idpflags; +#define IDP_STRICT 0x0001 // Strictly adhere to instruction encodings + inline bool is_strict(void) { return (idpflags & IDP_STRICT) != 0; } + void save_idpflags() { helper.altset(-1, idpflags); } + +#define REG_MIN 0x580 +#define REG_MAX 0x7f4 + struct tabent_t reg_tab_buf[REG_MAX - REG_MIN + 1]; + struct tabent_t *reg_tab = nullptr; + + bool flow; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void load_symbols(void); + const char *find_sym(ea_t address); + void choose_device(); + const char *set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + bool ctrl(insn_t &insn, uint32 code); + bool opmemory(insn_t &insn, op_t &x, uint32 code, char dtype); + bool mem(insn_t &insn, uint32 code); + + int i960_ana(insn_t *_insn); + bool reg(insn_t &insn, uint32 code); + + void handle_operand(const insn_t &insn, const op_t &x, bool isload); + int i960_emu(const insn_t &insn); + + void i960_segstart(outctx_t &ctx, segment_t *Sarea) const; + void i960_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ i960" +#define PROCMOD_NAME i960 +#endif // _I960_HPP diff --git a/idasdk75/module/i960/ins.cpp b/idasdk76/module/i960/ins.cpp similarity index 100% rename from idasdk75/module/i960/ins.cpp rename to idasdk76/module/i960/ins.cpp diff --git a/idasdk76/module/i960/ins.hpp b/idasdk76/module/i960/ins.hpp new file mode 100644 index 0000000..9a1ca00 --- /dev/null +++ b/idasdk76/module/i960/ins.hpp @@ -0,0 +1,288 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ +I960_null = 0, // Unknown Operation + +I960_addc, // Add ordinal with carry +I960_addi, // Add integer +I960_addo, // Add ordinal +I960_alterbit, // Alter bit +I960_and, // Src2 AND src1 +I960_andnot, // Src2 AND (NOT src1) +I960_atadd, // Atomic add +I960_atmod, // Atomic modify +I960_b, // Branch +I960_bal, // Branch and Link +I960_balx, // Branch and Link Extended +I960_bbc, // Check bit and branch if clear +I960_bbs, // Check bit and branch if set +I960_bno, // Branch if unordered/false +I960_bg, // Branch if greater +I960_be, // Branch if equal/true +I960_bge, // Branch if greater or equal +I960_bl, // Branch if less +I960_bne, // Branch if not equal +I960_ble, // Branch if less or equal +I960_bo, // Branch if ordered +I960_bx, // Branch Extended +I960_call, // Call +I960_calls, // Call system +I960_callx, // Call extended +I960_chkbit, // Check bit +I960_clrbit, // Clear bit +I960_cmpdeci, // Compare and decrement integer +I960_cmpdeco, // Compare and decrement ordinal +I960_cmpi, // Compare integer +I960_cmpibno, // Compare integer and branch if unordered +I960_cmpibg, // Compare integer and branch if greater +I960_cmpibe, // Compare integer and branch if equal +I960_cmpibge, // Compare integer and branch if greater or equal +I960_cmpibl, // Compare integer and branch if less +I960_cmpibne, // Compare integer and branch if not equal +I960_cmpible, // Compare integer and branch if less or equal +I960_cmpibo, // Compare integer and branch if ordered +I960_cmpinci, // Compare and increment integer +I960_cmpinco, // Compare and increment ordinal +I960_cmpo, // Compare ordinal +I960_cmpobg, // Compare ordinal and branch if greater +I960_cmpobe, // Compare ordinal and branch if equal +I960_cmpobge, // Compare ordinal and branch if greater or equal +I960_cmpobl, // Compare ordinal and branch if less +I960_cmpobne, // Compare ordinal and branch if not equal +I960_cmpoble, // Compare ordinal and branch if less or equal +I960_concmpi, // Conditional compare integer +I960_concmpo, // Conditional compare ordinal +I960_divi, // Divide integer +I960_divo, // Divide ordinal +I960_ediv, // Extended divide +I960_emul, // Extended multiply +I960_eshro, // Extended shift right ordinal +I960_extract, // Extract +I960_faultno, // Fault if unordered +I960_faultg, // Fault if greater +I960_faulte, // Fault if equal +I960_faultge, // Fault if greater or equal +I960_faultl, // Fault if less +I960_faultne, // Fault if not equal +I960_faultle, // Fault if less or equal +I960_faulto, // Fault if ordered +I960_flushreg, // Flush cached local register sets to memory +I960_fmark, // Force mark +I960_ld, // Load word +I960_lda, // Load address +I960_ldib, // Load integer byte +I960_ldis, // Load integer short +I960_ldl, // Load long +I960_ldob, // Load ordinal byte +I960_ldos, // Load ordinal short +I960_ldq, // Load quad +I960_ldt, // Load triple +I960_mark, // Mark +I960_modac, // Modify the AC register +I960_modi, // Modulo integer +I960_modify, // Modify +I960_modpc, // Modify the process controls register +I960_modtc, // Modify trace controls +I960_mov, // Move word +I960_movl, // Move long word +I960_movq, // Move quad word +I960_movt, // Move triple word +I960_muli, // Multiply integer +I960_mulo, // Multiply ordinal +I960_nand, // NOT (src2 AND src1) +I960_nor, // NOT (src2 OR src1) +I960_not, // NOT src1 +I960_notand, // (NOT src2) AND src1 +I960_notbit, // Not bit +I960_notor, // (NOT src2) or src1 +I960_or, // Src2 OR src1 +I960_ornot, // Src2 or (NOT src1) +I960_remi, // Remainder integer +I960_remo, // Remainder ordinal +I960_ret, // Return +I960_rotate, // Rotate left +I960_scanbit, // Scan for bit +I960_scanbyte, // Scan byte equal +I960_setbit, // Set bit +I960_shli, // Shift left integer +I960_shlo, // Shift left ordinal +I960_shrdi, // Shift right dividing integer +I960_shri, // Shift right integer +I960_shro, // Shift right ordinal +I960_spanbit, // Span over bit +I960_st, // Store word +I960_stib, // Store integer byte +I960_stis, // Store integer short +I960_stl, // Store long +I960_stob, // Store ordinal byte +I960_stos, // Store ordinal short +I960_stq, // Store quad +I960_stt, // Store triple +I960_subc, // Subtract ordinal with carry +I960_subi, // Subtract integer +I960_subo, // Subtract ordinal +I960_syncf, // Synchronize faults +I960_testno, // Test for unordered +I960_testg, // Test for greater +I960_teste, // Test for equal +I960_testge, // Test for greater or equal +I960_testl, // Test for less +I960_testne, // Test for not equal +I960_testle, // Test for less or equal +I960_testo, // Test for ordered +I960_xnor, // Src2 XNOR src1 +I960_xor, // Src2 XOR src1 + +// Cx instructions + +I960_sdma, // Set up a DMA controller channel +I960_sysctl, // Perform system control function +I960_udma, // Copy current DMA pointers to internal data RAM + +// Unknown instructions + +I960_dcinva, +I960_cmpob, +I960_cmpib, +I960_cmpos, +I960_cmpis, +I960_bswap, +I960_intdis, +I960_inten, +I960_synmov, +I960_synmovl, +I960_synmovq, +I960_cmpstr, +I960_movqstr, +I960_movstr, +I960_inspacc, +I960_ldphy, +I960_synld, +I960_fill, +I960_daddc, +I960_dsubc, +I960_dmovt, +I960_condrec, +I960_receive, +I960_intctl, +I960_icctl, +I960_dcctl, +I960_halt, +I960_send, +I960_sendserv, +I960_resumprcs, +I960_schedprcs, +I960_saveprcs, +I960_condwait, +I960_wait, +I960_signal, +I960_ldtime, +I960_addono, +I960_addino, +I960_subono, +I960_subino, +I960_selno, +I960_addog, +I960_addig, +I960_subog, +I960_subig, +I960_selg, +I960_addoe, +I960_addie, +I960_suboe, +I960_subie, +I960_sele, +I960_addoge, +I960_addige, +I960_suboge, +I960_subige, +I960_selge, +I960_addol, +I960_addil, +I960_subol, +I960_subil, +I960_sell, +I960_addone, +I960_addine, +I960_subone, +I960_subine, +I960_selne, +I960_addole, +I960_addile, +I960_subole, +I960_subile, +I960_selle, +I960_addoo, +I960_addio, +I960_suboo, +I960_subio, +I960_selo, + +// Floating point instructions + +I960_faddr, I960_fp_first = I960_faddr, +I960_faddrl, +I960_fatanr, +I960_fatanrl, +I960_fclassr, +I960_fclassrl, +I960_fcmpor, +I960_fcmporl, +I960_fcmpr, +I960_fcmprl, +I960_fcosr, +I960_fcosrl, +I960_fcpyrsre, +I960_fcpysre, +I960_fcvtilr, +I960_fcvtir, +I960_fcvtri, +I960_fcvtril, +I960_fcvtzri, +I960_fcvtzril, +I960_fdivr, +I960_fdivrl, +I960_fexpr, +I960_fexprl, +I960_flogbnr, +I960_flogbnrl, +I960_flogepr, +I960_flogeprl, +I960_flogr, +I960_flogrl, +I960_fmovr, +I960_fmovre, +I960_fmovrl, +I960_fmulr, +I960_fmulrl, +I960_fremr, +I960_fremrl, +I960_froundr, +I960_froundrl, +I960_fscaler, +I960_fscalerl, +I960_fsinr, +I960_fsinrl, +I960_fsqrtr, +I960_fsqrtrl, +I960_fsubr, +I960_fsubrl, +I960_ftanr, +I960_ftanrl, I960_fp_last = I960_ftanrl, + +I960_last, + + }; + +#endif diff --git a/idasdk76/module/i960/makefile b/idasdk76/module/i960/makefile new file mode 100644 index 0000000..2b58f76 --- /dev/null +++ b/idasdk76/module/i960/makefile @@ -0,0 +1,57 @@ +PROC=i960 +CONFIGS=i960.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp i960.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp i960.hpp ins.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + i960.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + i960.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp i960.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/i960/out.cpp b/idasdk76/module/i960/out.cpp similarity index 100% rename from idasdk75/module/i960/out.cpp rename to idasdk76/module/i960/out.cpp diff --git a/idasdk76/module/i960/reg.cpp b/idasdk76/module/i960/reg.cpp new file mode 100644 index 0000000..3ff3bc6 --- /dev/null +++ b/idasdk76/module/i960/reg.cpp @@ -0,0 +1,440 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2001 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "i960.hpp" +#include <diskio.hpp> +#include <typeinf.hpp> +#include <ieee.h> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "pfp", "sp", "rip", "r3", "r4", "r5", "r6", "r7", + "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", + "g0", "g1", "g2", "g3", "g4", "g5", "g6", "g7", + "g8", "g9", "g10", "g11", "g12", "g13", "g14", "fp", + "sf0", "sf1", "sf2", "sf3", "sf4", "sf5", "sf6", "sf7", + "sf8", "sf9", "sf10", "sf11", "sf12", "sf13", "sf14", "sf15", + "sf16", "sf17","sf18", "sf19", "sf20", "sf21", "sf22", "sf23", + "sf24", "sf25","sf26", "sf27", "sf28", "sf29", "sf30", "sf31", + "pc", "ac", "ip", "tc", + "fp0", "fp1", "fp2", "fp3", + "ds", "cs", +}; + +//-------------------------------------------------------------------------- +static const bytes_t retcodes[] = +{ +// { sizeof(retcode0), retcode0 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// GNU assembler +//----------------------------------------------------------------------- +static const asm_t gnuasm = +{ + AS_ASCIIC|AS_ALIGN2|ASH_HEXF3|ASD_DECF0|ASB_BINF3|ASO_OCTF1|AS_COLON|AS_N2CHR|AS_NCMAS|AS_ONEDUP, + 0, + "GNU assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + "#", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".long", // double words + ".quad", // qwords + ".octa", // oword (16 bytes) + ".float", // float (4 bytes) + ".double", // double (8 bytes) + ".extended", // tbyte (10/12 bytes) + NULL, // packed decimal real + ".fill #d, #s(1,2,4,8), #v", // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + ".", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &gnuasm, NULL }; + +//-------------------------------------------------------------------------- +static const char *const cfgname = "i960.cfg"; + +void i960_t::load_symbols(void) +{ + ioh.ports.clear(); + read_ioports(&ioh.ports, &ioh.device, cfgname); +} + +const char *i960_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? port->name.c_str() : NULL; +} + +//-------------------------------------------------------------------------- +void i960_t::choose_device() +{ + if ( choose_ioport_device(&ioh.device, cfgname) ) + { + ioh.set_device_name(ioh.device.c_str(), IORESP_NONE); + load_symbols(); + } +} + +//-------------------------------------------------------------------------- +static int idaapi choose_device_cb(int, form_actions_t &fa) +{ + i960_t &pm = *(i960_t *)fa.get_ud(); + pm.choose_device(); + return 0; +} + +//-------------------------------------------------------------------------- +const char *i960_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + static const char form[] = + "HELP\n" + "Intel 960 specific options\n" + "\n" + " Choose device name\n" + " Here you may select a specific Intel 960 device\n" + " IDA will use the definitions in the I960.CFG file for\n" + " the i/o port names\n" + "\n" + " Strictly adhere to instruction encodings\n" + " If this option is on, IDA will check that unused fields\n" + " of instructions are filled by zeroes. If they are not,\n" + " it will refuse to disassemble the instruction.\n" + "\n" + "ENDHELP\n" + "Intel 960 specific options\n" + "%*\n" + " <~C~hoose device name:B:0:::>\n" + "\n" + " <~S~trictly adhere to instruction encodings:C>>\n" + "\n" + "\n"; + + if ( keyword == NULL ) + { + CASSERT(sizeof(idpflags) == sizeof(ushort)); + ask_form(form, this, choose_device_cb, &idpflags); +OK: + if ( idb_loaded ) + save_idpflags(); + return IDPOPT_OK; + } + else + { + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + if ( strcmp(keyword, "I960_STRICT") == 0 ) + { + setflag(idpflags, IDP_STRICT, *(int*)value != 0); + goto OK; + } + } + return IDPOPT_BADKEY; +} + +//-------------------------------------------------------------------------- +void i960_t::load_from_idb() +{ + // restore ptype + int n = ph.get_proc_index(); + inf_set_be((n > 1)); + idpflags = helper.altval(-1); + ioh.restore_device(); + load_symbols(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(i960_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi i960_t::on_event(ssize_t msgid, va_list va) +{ + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + choose_device(); + save_idpflags(); + break; + + case processor_t::ev_oldfile: // old file loaded + ioh.upgrade_device_index(); + // fall through + case processor_t::ev_ending_undo: + load_from_idb(); + break; + + case processor_t::ev_newprc: + { + int n = va_arg(va, int); + bool keep_cfg = va_argi(va, bool); + if ( !keep_cfg ) + inf_set_be((n > 1)); + } + break; + +// +++ TYPE CALLBACKS + case processor_t::ev_decorate_name: + { + qstring *outbuf = va_arg(va, qstring *); + const char *name = va_arg(va, const char *); + bool mangle = va_argi(va, bool); + cm_t cc = va_argi(va, cm_t); + tinfo_t *type = va_arg(va, tinfo_t *); + return gen_decorate_name(outbuf, name, mangle, cc, type) ? 1 : 0; + } + + case processor_t::ev_max_ptr_size: + return 4; + + case processor_t::ev_calc_arglocs: + return -1; + + case processor_t::ev_use_stkarg_type: + return 0; + + case processor_t::ev_use_regarg_type: + return -1; + + case processor_t::ev_get_cc_regs: + { + callregs_t *callregs = va_arg(va, callregs_t *); + cm_t cc = va_argi(va, cm_t); + if ( cc == CM_CC_FASTCALL || cc == CM_CC_THISCALL ) + { + callregs->reset(); + return 1; + } + } + break; + + case processor_t::ev_calc_cdecl_purged_bytes:// calculate number of purged bytes after call + { + // ea_t ea = va_arg(va, ea_t); + return 0; + } + + case processor_t::ev_get_stkarg_offset: // get offset from SP to the first stack argument + // args: none + // returns: the offset + return 0; + +// --- TYPE CALLBACKS + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + i960_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + i960_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + i960_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + i960_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return i960_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return i960_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return 0; +} + +//----------------------------------------------------------------------- +#define FAMILY "Intel 960:" + +static const char *const shnames[] = +{ + "i960", + "i960l", + "i960b", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Intel 960 little endian (default)", + "Intel 960 little endian", + "Intel 960 big endian", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_I960, // id + // flag + PRN_HEX + | PR_RNAMESOK + | PR_SEGS + | PR_USE32 + | PR_DEFSEG32 + | PR_TYPEINFO, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + ds, // first + cs, // last + 2, // size of a segment register + cs, ds, + + NULL, // No known code start sequences + retcodes, + + I960_null, + I960_last, + Instructions, // instruc + 10, // int tbyte_size (0-doesn't exist) + { 0, 7, 15, 19 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + I960_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/idaidp.hpp b/idasdk76/module/idaidp.hpp new file mode 100644 index 0000000..30c7aa7 --- /dev/null +++ b/idasdk76/module/idaidp.hpp @@ -0,0 +1,69 @@ + +// Common include files for IDP modules: + +#include <ida.hpp> +#include <idp.hpp> +#include <ua.hpp> +#include <name.hpp> +#include <auto.hpp> +#include <bytes.hpp> +#include <problems.hpp> +#include <lines.hpp> +#include <loader.hpp> +#include <offset.hpp> +#include <segment.hpp> +#include <kernwin.hpp> + + +#define DECLARE_PROC_LISTENER(listener_type, parent_type) \ + DECLARE_LISTENER(listener_type, parent_type, pm) + +// Current processor in the module +// It must be exported +idaman processor_t ida_module_data LPH; + +void idaapi out_insn(outctx_t &ctx); +void idaapi out_mnem(outctx_t &ctx); +bool idaapi out_opnd(outctx_t &ctx, const op_t &x); + +// use this define if the default out_mnem() is good enough +#define DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(CTXNAME) \ + void idaapi out_insn(outctx_t &ctx) \ + { \ + CTXNAME *p = (CTXNAME *)&ctx; \ + p->out_insn(); \ + } \ + bool idaapi out_opnd(outctx_t &ctx, const op_t &x) \ + { \ + CTXNAME *p = (CTXNAME *)&ctx; \ + return p->out_operand(x); \ + } + +// use this define if you want to print insn mnemonics yourself +#define DECLARE_OUT_FUNCS(CTXNAME) \ + DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(CTXNAME) \ + void idaapi out_mnem(outctx_t &ctx) \ + { \ + CTXNAME *p = (CTXNAME *)&ctx; \ + p->out_proc_mnem(); \ + } + +//-------------------------------------------------------------------------- +inline bool print_predefined_segname( + outctx_t &ctx, + qstring *sname, + const char *const predefined[], + size_t n) +{ + for ( size_t i=0; i < n; i++ ) + { + if ( *sname == predefined[i] ) + { + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR), sname->c_str()); + return true; + } + } + validate_name(sname, VNT_IDENT); + return false; +} + diff --git a/idasdk76/module/iohandler.hpp b/idasdk76/module/iohandler.hpp new file mode 100644 index 0000000..e0eceb2 --- /dev/null +++ b/idasdk76/module/iohandler.hpp @@ -0,0 +1,376 @@ +/* + + This file contains functions common to many processor modules + to manage configuration files. The following functions can be called: + + bool apply_config_file(int _respect_info); + Read and parse the config file + + void set_device_name(const char *dname, int respect_info); + Set a new device name and reread the config file + + bool display_infotype_dialog(int *respect_info, const char *cfgname); + Display a form and allow the user to clear some IORESP_ bits + +*/ +#pragma once + +#include <pro.h> +#include <ida.hpp> +#include <netnode.hpp> +#include <bytes.hpp> +#include <diskio.hpp> +#include <segment.hpp> +#include <entry.hpp> +#include <name.hpp> +#include <xref.hpp> +#include <offset.hpp> +#include <idp.hpp> + +struct iohandler_t +{ + qstring device; + ioports_t ports; + qstring deviceparams; +#define IORESP_PORT 1 // rename port names in memory +#define IORESP_AREA 2 // respect "area" directives +#define IORESP_INT 4 // respect interrupt information + +#define IORESP_ALL (IORESP_PORT|IORESP_AREA|IORESP_INT) +#define IORESP_NONE 0 + int respect_info = IORESP_NONE; + netnode &helper; + + iohandler_t(netnode &_helper) : helper(_helper) {} + virtual ~iohandler_t() {} + +#define NONEPROC "NONE" + + // Option: additional segment class to appear in the device description + // Default: EEPROM + virtual const char *aux_segm() const { return "EEPROM"; } + + // Option: respect configuration information for different file types? + // Default: only binary-like files use IORESP_PORT, AREA, INT + virtual bool check_ioresp() const { return inf_like_binary(); } + + // Option: a callback function to parse additional configuration file lines + // Default: "interrupt" and "entry" keywords are recognized + virtual const char *iocallback(const ioports_t &iop, const char *line) + { + return standard_callback(iop, line); + } + + // can be used as object handler for read_ioports2() + struct ioports_loader_t : public ioports_fallback_t + { + iohandler_t *_this; + ioports_loader_t(iohandler_t *_t) : _this(_t) {} + + virtual bool handle(qstring *errbuf, const ioports_t &_ports, const char *line) override + { + const char *errmsg = _this->iocallback(_ports, line); + if ( errmsg == nullptr ) + return true; + if ( errmsg == IOPORT_SKIP_DEVICE ) + errmsg = "SKIP device (logic error):"; + *errbuf = errmsg; + return false; + } + }; + + // Option: the function that will actually apply the IO port info into the IDB. + // Default: will simply set name & comment. + virtual void apply_io_port(ea_t ea, const char *name, const char *cmt) + { + set_name(ea, name, SN_NODUMMY); + set_cmt(ea, cmt, true); + } + + // Option: the function that will be called for unknown directives + // (e.g., "area", "mirror", ...) + // Default: standard_handle_unknown_directive + virtual const char *handle_unknown_directive(const char *line) + { + return parse_area_line(&deviceparams, line); + } + + // Option: function to handle entry points + // Default: create an entry point + //-V:entry_processing:669 + virtual bool entry_processing(ea_t &, const char * /*word*/, const char * /*cmt*/) { return false; } + + // Option: function to handle areas + // Default: create a segment + virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) { return false; } + + virtual bool segment_created(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) { return false; } + + // Option: define function get_cfg_path() + // Default: yes, it returns a file name using the current processor name + virtual void get_cfg_filename(char *buf, size_t bufsize) + { + inf_get_procname(buf, bufsize); + qstrlwr(buf); + qstrncat(buf, ".cfg", bufsize); + } + + GCC_DIAG_OFF(format-nonliteral); + //------------------------------------------------------------------ + const char *parse_area_line(qstring *buf, const char *line) + { + if ( line[0] != ';' ) + { + char word[MAXSTR]; + char aclass[MAXSTR]; + word[MAXSTR-1] = '\0'; + aclass[MAXSTR-1] = '\0'; + ea_t ea1, ea2; + CASSERT(MAXSTR == 1024); + if ( qsscanf(line, "area %1023s %1023s %a:%a", aclass, word, &ea1, &ea2) == 4 ) + { + size_t _ram = 0; + size_t _rom = 0; + size_t _eprom = 0; + size_t _eeprom = 0; + qstring format("RAM=%" FMT_Z " ROM=%" FMT_Z " EPROM=%" FMT_Z " "); + format.append(aux_segm()); + format.append("=%" FMT_Z); + qsscanf(buf->c_str(), format.c_str(), &_ram, &_rom, &_eprom, &_eeprom); + size_t size = size_t(ea2 - ea1); + if ( stristr(word, "RAM") != NULL ) + _ram += size; + else if ( stristr(word, aux_segm()) != NULL ) + _eeprom += size; + else if ( stristr(word, "EPROM") != NULL ) + _eprom += size; + else if ( stristr(word, "ROM") != NULL ) + _rom += size; + if ( _ram || _rom || _eprom || _eeprom ) + buf->sprnt(format.c_str(), _ram, _rom, _eprom, _eeprom); + else + buf->qclear(); + if ( (respect_info & IORESP_AREA) != 0 && get_first_seg() != NULL ) + { + if ( !area_processing(ea1, ea2, word, aclass) ) + { + if ( !segment_created(ea1, ea2, word, aclass) ) + { + segment_t s; + s.sel = setup_selector(0); + s.start_ea = ea1; + s.end_ea = ea2; + s.align = saRelByte; + s.comb = streq(aclass, "STACK") ? scStack : scPub; + s.bitness = PH.get_segm_bitness(); + if ( s.bitness == 0 && s.size() > 0xFFFF ) + s.bitness = 1; + int sfl = ADDSEG_NOSREG; + if ( !is_loaded(s.start_ea) ) + sfl |= ADDSEG_SPARSE; + add_segm_ex(&s, word, aclass, sfl); + } + } + } + return NULL; + } + } + return "syntax error"; + } + GCC_DIAG_ON(format-nonliteral); + + //------------------------------------------------------------------ + struct parse_area_line0_t : public choose_ioport_parser_t + { + iohandler_t &_this; + parse_area_line0_t(iohandler_t &_t) : _this(_t) {} + + virtual bool parse(qstring *param, const char *line) override + { + _this.respect_info = 0; + _this.parse_area_line(param, line); + return true; + } + }; + + //------------------------------------------------------------------ + const char *idaapi standard_callback(const ioports_t &, const char *line) + { + int len; + ea_t ea1; + char word[MAXSTR]; + word[MAXSTR-1] = '\0'; + CASSERT(MAXSTR == 1024); + if ( qsscanf(line, "interrupt %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) + { + if ( (respect_info & IORESP_INT) != 0 ) + { + ea_t proc, wrong; + segment_t *s = getseg(ea1); + if ( s == nullptr || s->is_16bit() ) + { + create_word(ea1, 2); + proc = get_word(ea1); + wrong = 0xFFFF; + } + else + { + create_dword(ea1, 4); + proc = get_dword(ea1); + wrong = 0xFFFFFFFF; + } + if ( proc != wrong && is_mapped(proc) ) + { + op_plain_offset(ea1, 0, 0); + add_entry(proc, proc, word, true); + } + else + { + set_name(ea1, word, SN_NODUMMY); + } + const char *ptr = &line[len]; + ptr = skip_spaces(ptr); + if ( ptr[0] != '\0' ) + set_cmt(ea1, ptr, true); + } + return NULL; + } + if ( qsscanf(line, "entry %1023s %" FMT_EA "i%n", word, &ea1, &len) == 2 ) + { + if ( (respect_info & IORESP_INT) != 0 ) + { + if ( is_mapped(ea1) ) + { + const char *ptr = &line[len]; + ptr = skip_spaces(ptr); + if ( !entry_processing(ea1, word, ptr) ) + { + add_entry(ea1, ea1, word, true); + if ( ptr[0] != '\0' ) + set_cmt(ea1, ptr, true); + } + } + } + return NULL; + } + return handle_unknown_directive(line); + } + + //------------------------------------------------------------------ + bool apply_config_file(int _respect_info) + { + if ( device == NONEPROC ) // processor not selected + return true; + + char cfgfile[QMAXFILE]; + get_cfg_filename(cfgfile, sizeof(cfgfile)); + deviceparams.qclear(); + if ( !check_ioresp() ) + _respect_info = 0; + respect_info = _respect_info; + ports.clear(); + ioports_loader_t ldr(this); + read_ioports2(&ports, &device, cfgfile, &ldr); + if ( respect_info & IORESP_PORT ) + { + for ( size_t i=0; i < ports.size(); i++ ) + { + const ioport_t &p = ports[i]; + ea_t ea = p.address; + apply_io_port(ea, p.name.c_str(), p.cmt.c_str()); + } + } + return true; + } + + //------------------------------------------------------------------ + void set_device_name(const char *dname, int respinfo) + { + if ( dname != NULL ) + { + device = dname; + helper.supset(-1, device.c_str()); + apply_config_file(respinfo); + } + } + + //------------------------------------------------------------------ + void restore_device(int respinfo = IORESP_NONE) + { + if ( helper.supstr(&device, -1) > 0 ) + apply_config_file(respinfo); + } + + //------------------------------------------------------------------ + // Some processor modules wrongly store device with index 0 (some store + // duplicate value with both indices 0 and -1). Upgrade IDB to use -1 + void upgrade_device_index() + { + qstring old_device; + if ( helper.supstr(&old_device, 0) >= 0 ) + { + helper.supset(-1, old_device.c_str()); + helper.supdel(0); + } + } + + //------------------------------------------------------------------ + // Display a dialog form with the information types + // Let the user to clear some checkboxes if he wants so + // Returns: true - the user clicked OK + bool display_infotype_dialog( + int display_info, + int *p_resp_info, + const char *cfg_filename) + { + if ( display_info == 0 ) + return false; + static const char *const form = + "Loaded information type\n" + "\n" + "Please specify what information should be loaded from\n" + "the configuration file %s to the database.\n" + "\n" + "If the input file does not contain parts corresponding to\n" + "the segmentation defined in the config file, you might want\n" + "to clear the 'memory layout' checkbox or even cancel this\n" + "dialog box.\n"; + char buf[MAXSTR]; + char *ptr = buf + qsnprintf(buf, sizeof(buf), form, cfg_filename); + char *const end = buf + sizeof(buf); + int B = 1; + ushort b = 0; + ushort r = (ushort)*p_resp_info; + #define ADD_FIELD(bit, desc) \ + if ( display_info & bit ) \ + { \ + if ( r & bit ) \ + b |= B; \ + B <<= 1; \ + APPEND(ptr, end, desc); \ + } + ADD_FIELD(IORESP_PORT, "\n<#Rename port and I/O registers#I/O ports:C>") + ADD_FIELD(IORESP_AREA, "\n<#Adjust the segments#Memory layout:C>") + ADD_FIELD(IORESP_INT, "\n<#Create interrupt vectors and/or entry points#Interrupts:C>") + #undef ADD_FIELD + qnotused(B); + APPEND(ptr, end, ">\n\n"); + if ( !ask_form(buf, &b) ) + return false; + B = 1; + if ( display_info & IORESP_PORT ) + { + setflag(r, IORESP_PORT, (B & b) != 0); + B <<= 1; + } + if ( display_info & IORESP_AREA ) + { + setflag(r, IORESP_AREA, (B & b) != 0); + B <<= 1; + } + if ( display_info & IORESP_INT ) + setflag(r, IORESP_INT, (B & b) != 0); + *p_resp_info = r; + return true; + } +}; diff --git a/idasdk76/module/java/ana.cpp b/idasdk76/module/java/ana.cpp new file mode 100644 index 0000000..78198ac --- /dev/null +++ b/idasdk76/module/java/ana.cpp @@ -0,0 +1,577 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "java.hpp" + +//---------------------------------------------------------------------- +int java_t::LoadIndex(insn_t &insn) +{ + ushort top; + + insn.Op1.type = o_mem; +// insn.Op1.ref = 0; + insn.Op1.offb = char(insn.size); + top = insn.wid ? insn.get_next_word() : insn.get_next_byte(); + insn.Op1.addr = top; + if ( ((insn.Op1.dtype == dt_qword || insn.Op1.dtype == dt_double) && !++top) + || top >= curSeg.DataSize ) + { + if ( !debugmode ) + return 0; + ++insn.Op1.ref; + } + return 1; +} + +//---------------------------------------------------------------------- +void copy_const_to_opnd(op_t &x, const const_desc_t &co) +{ + x.addr = co.value2; + x.value = co.value; +#ifdef __EA64__ + // in 64-bit version of IDA the 'value' field is 64bit, so copy the value + // there + x.value = make_ulonglong((uint32)x.value, (uint32)x.addr); +#endif +} + +//---------------------------------------------------------------------- +int java_t::ConstLoad(insn_t &insn, CIC_param ctype) +{ + const_desc_t cntopis; + + insn.Op1.type = o_cpool; +// insn.Op1.ref = 0; + + if ( !insn.Op1.cp_ind ) + goto dmpchk; // NULL Ptr + + if ( !LoadOpis(lm_normal, insn.Op1.cp_ind, 0, &cntopis) ) + goto dmpchk; + + CASSERT(offsetof(const_desc_t,flag) == (offsetof(const_desc_t,type) + sizeof(uchar) ) + && (sizeof(cntopis.type) == sizeof(uchar)) + && (sizeof(cntopis.flag) == sizeof(uchar)) + && (sizeof(insn.Op1.cp_type) >= (2*sizeof(uchar))) + && (sizeof(ushort) == sizeof(insn.Op1.cp_type))); + insn.Op1.cp_type = *((ushort *)&cntopis.type); + + switch ( ctype ) + { + case C_Class: + if ( cntopis.type != CONSTANT_Class ) + break; + // no break + case C_4byte: // ldc/ldcw + switch ( cntopis.type ) + { + case CONSTANT_Class: + if ( !(cntopis.flag & HAS_CLSNAME) ) + goto wrnret; + insn.Op1.addr = 0x10001ul * (ushort)fmt_fullname; +loadref1: + insn.xtrn_ip = cntopis.ref_ip; + // no break + case CONSTANT_Integer: + case CONSTANT_Float: + case CONSTANT_String: + insn.Op1.value = cntopis.value; // for string index to Utf8 + return 1; // or TWO index for other + default: + break; + } + break; + + case C_8byte: + if ( cntopis.type == CONSTANT_Long || cntopis.type == CONSTANT_Double ) + goto load2; + break; + + case C_Field: + if ( cntopis.type != CONSTANT_Fieldref ) + break; + if ( (cntopis.flag & NORM_FIELD) != NORM_FIELD ) + goto wrnret; +loadref2: + insn.xtrn_ip = cntopis.ref_ip; +load2: + copy_const_to_opnd(insn.Op1, cntopis); // for string index to Utf8 + return 1; + + case C_Interface: + if ( cntopis.type == CONSTANT_InterfaceMethodref ) + goto methodchk; + break; + case C_Method: + if ( cntopis.type != CONSTANT_Methodref ) + break; +methodchk: + if ( (cntopis.flag & NORM_METOD) == NORM_METOD ) + goto loadref2; // load 3 ind. & xtrn_ref + goto wrnret; + + case C_CallSite: + if ( cntopis.type != CONSTANT_InvokeDynamic ) + break; + goto wrnret; + + case C_Type: + if ( cntopis.type != CONSTANT_Class ) + break; + if ( !(cntopis.flag & HAS_TYPEDSCR) ) + goto wrnret; + insn.Op1.addr = ((uint32)fmt_FieldDescriptor << 16) | (ushort)fmt_ClassName; + goto loadref1; // load 1 ind. + + case C_TypeName: + if ( cntopis.type != CONSTANT_Class ) + break; + if ( !(cntopis.flag & (HAS_TYPEDSCR | HAS_CLSNAME)) ) + goto wrnret; + insn.Op1.addr = ((uint32)fmt_ClassName_or_Array << 16) + | (ushort)((cntopis.flag & HAS_CLSNAME) + ? fmt_fullname + : fmt_ClassName); + goto loadref1; // load 1 ind. + + default: + warning("Illegal CIC call (%x)", ctype); + return 0; + } +dmpchk: + if ( !debugmode ) + return 0; + ++insn.Op1.ref; +wrnret: + ++insn.Op1.ref; + insn.Op1.addr_shorts.low = insn.Op1.cp_ind; // for dmp out + return 1; +} + +//---------------------------------------------------------------------- +int java_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + + CIC_param ctype; + segment_t *s = getMySeg(insn.ea); // also set curSeg + + if ( s->type != SEG_CODE || insn.ip >= curSeg.CodeSize ) + { + warning("Can't decode non-code fragment!"); + return 0; + } + + insn.Op1.dtype = dt_void; + insn.wid = insn.swit = 0; + insn.Op1.ref = 0; + + insn.itype = insn.get_next_byte(); + if ( insn.itype == j_wide ) + { + insn.itype = insn.get_next_byte(); + if ( insn.itype == j_iinc + || (insn.itype >= j_iload && insn.itype <= j_aload) + || (insn.itype >= j_istore && insn.itype <= j_astore) + || insn.itype == j_ret ) + { + insn.wid = 1; // _w + } + else + { + if ( !debugmode ) + return 0; + insn.size = 1; + insn.itype = j_wide; + } + } + + if ( insn.itype >= j_lastnorm ) + { + if ( !debugmode ) + return 0; + if ( insn.itype < j_quick_last ) + { + static const uchar redefcmd[j_quick_last - j_lastnorm] = + { + j_ldc, // j_ldc_quick + j_ldcw, // j_ldcw_quick + j_ldc2w, // j_ldc2w_quick + j_getfield, // j_getfield_quick + j_putfield, // j_putfield_quick + j_getfield, // j_getfield2_quick + j_putfield, // j_putfield2_quick + j_getstatic, // j_getstatic_quick + j_putstatic, // j_putstatic_quick + j_getstatic, // j_getstatic2_quick + j_putstatic, // j_putstatic2_quick + j_invokevirtual, // j_invokevirtual_quick + j_invokespecial, // j_invokenonvirtual_quick + j_a_invokesuper, // j_invokesuper_quick + j_invokestatic, // j_invokestatic_quick + j_invokeinterface, // j_invokeinterface_quick + j_a_invokevirtualobject, // j_invokevirtualobject_quick + j_a_invokeignored, // j_invokeignored_quick + j_new, // j_new_quick + j_anewarray, // j_anewarray_quick + j_multianewarray, // j_multianewarray_quick + j_checkcast, // j_checkcast_quick + j_instanceof, // j_instanceof_quick + j_invokevirtual, // j_invokevirtual_quick_w + j_getfield, // j_getfield_quick_w + j_putfield // j_putfield_quick_w + }; + + insn.wid = 2; // _quick; + switch ( insn.itype ) + { + case j_getstatic2_quick: + case j_putstatic2_quick: + case j_getfield2_quick: + case j_putfield2_quick: + insn.wid = 3; // 2_quick + break; + case j_invokevirtual_quick_w: + case j_getfield_quick_w: + case j_putfield_quick_w: + insn.wid = 4; // _quick_w + break; + default: + break; + } + insn.itype = redefcmd[insn.itype - j_lastnorm]; + } + else if ( insn.itype < j_software ) + { + return 0; + } + else + { + insn.itype -= (j_software - j_a_software); + } + } +//--- + switch ( insn.itype ) + { + default: + { + uint refs, ref2f; + + if ( insn.itype >= j_iload_0 && insn.itype <= j_aload_3 ) + { + refs = (insn.itype - j_iload_0) % 4; + ref2f = (insn.itype - j_iload_0) / 4; + ref2f = ref2f == ((j_lload_0 - j_iload_0) / 4) + || ref2f == ((j_dload_0 - j_iload_0) / 4); + goto refer; + } + if ( insn.itype >= j_istore_0 && insn.itype <= j_astore_3 ) + { + refs = (insn.itype - j_istore_0) % 4; + ref2f = (insn.itype - j_istore_0) / 4; + ref2f = ref2f == ((j_lstore_0 - j_istore_0) / 4) + || ref2f == ((j_dstore_0 - j_istore_0) / 4); +refer: + insn.Op1.addr = curSeg.DataBase + (ushort)refs; + insn.Op1.ref = (uchar)(ref2f + 1); + if ( (ushort)(refs + ref2f) >= curSeg.DataSize ) + insn.Op1.ref |= 0x80; + break; + } + } // end refs/refx + if ( insn.itype < j_ifeq || insn.itype > j_jsr ) + break; + case j_ifnull: + case j_ifnonnull: + insn.Op1.addr = (short)insn.get_next_word(); +b_near: + insn.Op1.type = o_near; + insn.Op1.offb = 1; + insn.Op1.addr += insn.ip; + if ( insn.Op1.addr >= curSeg.CodeSize ) + goto set_bad_ref; + break; + + case j_goto_w: + case j_jsr_w: + insn.Op1.addr = insn.get_next_dword(); + goto b_near; + + case j_bipush: + insn.Op1.dtype = dt_byte; + insn.Op1.value = (char)insn.get_next_byte(); + goto setdat; + case j_sipush: + insn.Op1.dtype = dt_word; + insn.Op1.value = (short)insn.get_next_word(); +setdat: + insn.Op1.type = o_imm; + insn.Op1.offb = 1; + break; + + case j_ldc: + insn.Op1.cp_ind = insn.get_next_byte(); + ctype = C_4byte; + goto constchk; + case j_ldcw: + ctype = C_4byte; + goto const2w; + case j_ldc2w: + ctype = C_8byte; +const2w: + insn.Op1.cp_ind = insn.get_next_word(); +constchk: + if ( !ConstLoad(insn, ctype) ) + return 0; + break; + + case j_getstatic: + case j_putstatic: + case j_getfield: + case j_putfield: + if ( insn.wid > 1 ) // _quick form + { + insn.Op1.type = o_imm; + insn.Op1.ref = 2; // #data + insn.Op1.offb = 1; + if ( insn.wid == 4 ) + { + insn.Op1.dtype = dt_word; + insn.Op1.value = insn.get_next_word(); + } + else + { + insn.Op1.dtype = dt_byte; + insn.Op1.value = insn.get_next_byte(); + ++insn.size; // SKIP + } + break; + } + ctype = C_Field; + goto const2w; + + case j_new: + ctype = C_Class; + goto const2w; + + case j_anewarray: +//\\ ?/ + case j_checkcast: + case j_instanceof: + ctype = C_TypeName; + goto const2w; + + case j_a_invokesuper: + case j_a_invokeignored: + goto fictarg; + case j_invokevirtual: + case j_a_invokevirtualobject: + insn.Op2.dtype = dt_void; + if ( insn.wid > 1 ) + { + if ( insn.wid == 4 ) + { +fictarg: + insn.Op1.value = insn.get_next_word(); //??? + insn.Op1.dtype = dt_word; + } + else + { + insn.Op2.type = o_imm; + insn.Op1.ref = 2; // #data + insn.Op1.dtype = insn.Op2.dtype = dt_byte; + insn.Op1.value = insn.get_next_byte(); + insn.Op2.offb = 2; + insn.Op2.value = insn.get_next_byte(); + } + insn.Op1.offb = 1; + insn.Op1.type = o_imm; + insn.Op1.ref = 2; // #data + break; + } + // fallthrough + case j_invokespecial: + case j_invokestatic: + ctype = C_Method; + goto const2w; + case j_invokedynamic: + ctype = C_CallSite; + insn.Op1.cp_ind = insn.get_next_word(); + if ( !ConstLoad(insn, ctype) ) + return 0; + insn.get_next_word(); // eat two mandatory 0's + insn.Op1.ref = 0; + break; + case j_invokeinterface: + ctype = C_Interface; + insn.Op1.cp_ind = insn.get_next_word(); + insn.Op2.type = o_imm; + insn.Op2.ref = 1; // not descriptor + insn.Op2.dtype = dt_byte; + insn.Op2.value = insn.get_next_byte(); + if ( insn.wid > 1 ) + { + insn.Op3.type = o_imm; + insn.Op3.ref = 2; // #data + insn.Op3.value = insn.get_next_byte(); + insn.Op3.offb = 4; + insn.Op3.dtype = dt_byte; + } + else + { + ++insn.size; // reserved + insn.Op3.dtype = dt_void; + } + goto constchk; + + case j_multianewarray: + insn.Op1.cp_ind = insn.get_next_word(); + insn.Op2.type = o_imm; + insn.Op2.ref = 1; // not descriptor + insn.Op2.dtype = dt_byte; + insn.Op2.value = insn.get_next_byte(); + if ( insn.Op2.value == 0 && !debugmode ) + return 0; + ctype = C_Type; + goto constchk; + + case j_iinc: + case j_iload: + case j_istore: + insn.Op1.dtype = dt_dword; + goto memref; + case j_lload: + case j_lstore: + insn.Op1.dtype = dt_qword; + goto memref; + case j_fload: + case j_fstore: + insn.Op1.dtype = dt_float; + goto memref; + case j_dload: + case j_dstore: + insn.Op1.dtype = dt_double; + goto memref; + case j_aload: + case j_astore: + insn.Op1.dtype = dt_string; + goto memref; + case j_ret: + insn.Op1.dtype = dt_code; +memref: + if ( !LoadIndex(insn) ) + return 0; + if ( insn.itype == j_iinc ) + { + insn.Op2.type = o_imm; + insn.Op2.ref = 0; + insn.Op2.offb = (uchar)insn.size; + if ( insn.wid ) + { + insn.Op2.dtype = dt_word; + insn.Op2.value = (short)insn.get_next_word(); + } + else + { + insn.Op2.dtype = dt_byte; + insn.Op2.value = (char)insn.get_next_byte(); + } + } + break; + + case j_tableswitch: + case j_lookupswitch: + { + int32 count; + uint32 top; + + insn.swit = 1; + for ( top = (4 - uint32((insn.ip + insn.size) % 4)) & 3; top; top-- ) + { + if ( insn.get_next_byte() ) + { + if ( !debugmode ) + return 0; + insn.swit |= 0100; + } + } + insn.Op3.type = o_near; + insn.Op3.offb = (uchar)insn.size; + insn.Op3.addr = insn.get_next_dword(); + insn.Op3.addr += insn.ip; + insn.Op3.ref = 0; + + if ( insn.Op3.addr >= curSeg.CodeSize ) + { + if ( !debugmode ) + return 0; + ++insn.Op3.ref; + } + + insn.swit |= 2; // start out arguments + + count = insn.get_next_dword(); + if ( insn.itype == j_tableswitch ) + { + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_dword; + insn.Op1.value = count; // minimal value + insn.Op2.ref = 0; + insn.Op2.type = o_imm; + insn.Op2.dtype = dt_dword; + count = (uint32(insn.Op2.value = insn.get_next_dword()) - count + 1); + } + insn.Op3.value = count; + insn.Op2.addr = insn.ip + insn.size; + top = uint32(curSeg.CodeSize - insn.ip); + while ( count-- ) + { + if ( insn.itype == j_lookupswitch ) + insn.get_next_dword(); // skip pairs; + if ( (insn.ip + insn.get_next_dword()) >= curSeg.CodeSize ) + { + if ( !debugmode ) + return 0; + insn.swit |= 0200; + } + if ( (uint32)insn.size >= top ) + return 0; + } + } + break; + + case j_newarray: + insn.Op1.type = o_array; // type! + insn.Op1.offb = 1; + insn.Op1.cp_type = insn.get_next_byte(); + if ( insn.Op1.cp_type < T_BOOLEAN || (uchar)insn.Op1.cp_type > T_LONG ) + { +set_bad_ref: + if ( !debugmode ) + return 0; + ++insn.Op1.ref; + } + break; + } // switch ( insn.itype ) + + return insn.size; +} + +//---------------------------------------------------------------------- + +bool idaapi can_have_type(const op_t &x) +{ + if ( x.type == o_cpool ) + return (uchar)x.cp_type == CONSTANT_Integer + || (uchar)x.cp_type == CONSTANT_Long; + return x.type == o_imm; +} diff --git a/idasdk76/module/java/classfil.hpp b/idasdk76/module/java/classfil.hpp new file mode 100644 index 0000000..1fc86f0 --- /dev/null +++ b/idasdk76/module/java/classfil.hpp @@ -0,0 +1,212 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _CLASSFIL_HPP_ +#define _CLASSFIL_HPP_ +// +// Java File definition +// +#define MAGICNUMBER 0xcafebabeUL // magic number + +// Oracle's Java Virtual Machine implementation in JDK release 1.0.2 +// supports class file format versions 45.0 through 45.3 inclusive. JDK +// releases 1.1.* support class file format versions in the range 45.0 +// through 45.65535 inclusive. For k >= 2, JDK release 1.k supports class +// file format versions in the range 45.0 through 44+k.0 inclusive. + +#define JDK_1_02_MINOR 2 // (45.2) JDK1.0 +#define JDK_1_1_MINOR 3 // (45.3) JDK1.1 +#define JDK_MIN_MAJOR 45 // JDK1.0/JDK1.1 +#define JDK_MAX_MAJOR (44+11)// JDK1.11(JDK11): Java11? +// +// access_flags +// +#define ACC_PUBLIC 0x0001 // Visible to everyone +#define ACC_PRIVATE 0x0002 // Visible only to the defning +#define ACC_PROTECTED 0x0004 // Visible to subclasses +#define ACC_STATIC 0x0008 // Variable or method is static Method +#define ACC_FINAL 0x0010 // No further subclassing, overriding, or + // assignment after initialization +#define ACC_SYNCHRONIZED 0x0020 // Wrap use in monitor lock +#define ACC_SUPER 0x0020 // invoke by the 'invokespecial' (deprecated) +#define ACC_VOLATILE 0x0040 // Can't cache (field) +#define ACC_BRIDGE 0x0040 // Bridge method (java5) (generate by compiler) +#define ACC_TRANSIENT 0x0080 // Not to be written or read by + // a persistent object manager (field) +#define ACC_VARARGS 0x0080 // Method with variable number of arguments + // (java5) +#define ACC_NATIVE 0x0100 // Implemented in a language otherthan Java +#define ACC_INTERFACE 0x0200 // Is an interface +#define ACC_ABSTRACT 0x0400 // No body provided +#define ACC_STRICT 0x0800 // Delcared strictfp (floating-point mode + // is FP-strict) (method) +#define ACC_SYNTHETIC 0x1000 // Generate by compiler (no present in source) + // (java2) +#define ACC_ANNOTATION 0x2000 // only with INTERFACE (annotated) (java5) +#define ACC_ENUM 0x4000 // Class or BaseClass is enum (java5) +/* jdk1.5 +ACC_BRIDGE, ACC_VARARGS, ACC_STRICT, ACC_SYNTHETIC, ACC_ANNOTATION, ACC_ENUM +*/ +// +#define ACC_ACCESS_MASK (ACC_PUBLIC | ACC_PROTECTED | ACC_PRIVATE) +#define _ACC_ALLTP (ACC_ACCESS_MASK | ACC_STATIC | ACC_FINAL \ + | ACC_SYNTHETIC) + +#define ACC_THIS_MASK (ACC_PUBLIC | ACC_FINAL | ACC_SUPER | ACC_INTERFACE \ + | ACC_ABSTRACT | ACC_SYNTHETIC | ACC_ANNOTATION \ + | ACC_ENUM) +#define ACC_NESTED_MASK (_ACC_ALLTP | ACC_INTERFACE | ACC_ABSTRACT \ + | ACC_ANNOTATION | ACC_ENUM) +#define ACC_FIELD_MASK (_ACC_ALLTP | ACC_VOLATILE | ACC_TRANSIENT | ACC_ENUM) +#define ACC_METHOD_MASK (_ACC_ALLTP | ACC_SYNCHRONIZED | ACC_BRIDGE \ + | ACC_VARARGS | ACC_NATIVE | ACC_ABSTRACT \ + | ACC_STRICT) + +//----------------------------------- +// base type +// +#define j_byte 'B' // signed byte +#define j_char 'C' // unicode character +#define j_double 'D' // double precision IEEE float +#define j_float 'F' // single precision IEEE foat +#define j_int 'I' // integer +#define j_long 'J' // long integer +#define j_class 'L' // <fullclassname>; + // ... an object of the given class +#define j_endclass ';' // tag for end of classname +#define j_parm_list_start '(' // start of function parameters +#define j_parm_list_end ')' // end of function parameters +#define j_short 'S' // signed short +#define j_bool 'Z' // boolean true or false +#define j_array '[' // <length><field sig> ... array +#define j_void_ret 'V' // return no value +//----------- make as mnemonic in new version +#define j_field_dlm '.' // use as field delimiter +#define j_clspath_dlm '/' // use as classpath delimeter +//#define j_legacy_dlm '$' // mechanically generated & legacy systems +//----------- jdk1.5 +// signatures +#define j_typeref 'T' // TypeVariable signature +#define j_throw '^' // ThrowsSignature start +#define j_wild '*' // wildcard(unknown) <?> +#define j_wild_e '+' // wildcard(extends) <+name> +#define j_wild_s '-' // wildcard(super) <-name> +// type declaration syntax: <name:typesign> +// iface declaration syntax: <name:typesign:ifacesign> +// super declaration syntax: +#define j_sign '<' // formal type parameter start +#define j_endsign '>' // formal type parameter end +#define j_tag ':' // delimeter + +// annotation tags +// possible const types is: B, C, D, F, I, J, S, Z, [ +// additional annotation tag types +#define j_string 's' // constant string +#define j_enumconst 'e' // enum (type + name) +#define j_class_ret 'c' // return type descriptor +#define j_annotation '@' // nested annotation + +//----------------------------------------------------- +// Constant Pool +// +#define CONSTANT_Asciz 1 // jdk1.1 +#define CONSTANT_Utf8 1 // jdk1.x +#define CONSTANT_Unicode 2 // unused if jdk >= 1.0 (45.2) +#define CONSTANT_Integer 3 +#define CONSTANT_Float 4 +#define CONSTANT_Long 5 +#define CONSTANT_Double 6 +#define CONSTANT_Class 7 +#define CONSTANT_String 8 +#define CONSTANT_Fieldref 9 +#define CONSTANT_Methodref 10 +#define CONSTANT_InterfaceMethodref 11 +#define CONSTANT_NameAndType 12 +#define MAX_CONSTANT_TYPE 12 // Check in Loader flag +// JDK1.7 (JSR 292) -- dynamic for multiLanguage (python, ruby, etc) +#define CONSTANT_MethodHandle 15 +#define CONSTANT_MethodType 16 +// JDK 1.8 +#define CONSTANT_InvokeDynamic 18 +#define CONSTANT_LAST CONSTANT_InvokeDynamic + +// JVM_CONSTANT_MethodHandle subtypes +#define JVM_REF_getField 1 +#define JVM_REF_getStatic 2 +#define JVM_REF_putField 3 +#define JVM_REF_putStatic 4 +#define JVM_REF_invokeVirtual 5 +#define JVM_REF_invokeStatic 6 +#define JVM_REF_invokeSpecial 7 +#define JVM_REF_newInvokeSpecial 8 +#define JVM_REF_invokeInterface 9 + +//------------------------------------------------------- +// Array Type (newarray) +// +#define T_BOOLEAN 4 +#define T_CHAR 5 +#define T_FLOAT 6 +#define T_DOUBLE 7 +#define T_BYTE 8 +#define T_SHORT 9 +#define T_INT 10 +#define T_LONG 11 + +//-------------------------------------------------------- +// StackMapTable records +#define JDK_SMF_MAJOR_MIN 50 // minimal version (previous: CLDC) +// offset for record 0 == offset, else previous_offset + offset + 1; +#define SMT_SAME_FRM_S0_min 0 // off_dt=type, loc=prev, stack=empty +#define SMT_SAME_FRM_S0_max 63 +#define SMT_SAME_FRM_S1_min 64 // off_dt=type-min, loc=prev, stack=1 +#define SMT_SAME_FRM_S1_max 127 // [ + verinf[1] ] +#define SMT_reserved_min 128 +#define SMT_reserved_max 246 +#define SMT_SAME_FRM_S1 247 // loc=prev, stack=1 [ + off_d, verinf[1] ] +#define SMT_CHOP_FRM_S0_min 248 // stack=empty, loc=prev-((max+1)-type) +#define SMT_CHOP_FRM_S0_max 250 // [ + off_dt ] +#define SMT_SAME_FRM_S0 251 // stack=empty, loca=prev [ + off_dt ] +#define SMT_APPE_FRM_S0_min 252 // stack=empty, loc+=prev+(type-(min-1)) +#define SMT_APPE_FRM_S0_max 254 // [ + off_dt, { verinf[n] } ] +#define SMT_FULL_FRAME 255 // see below +/* +struct sm_full +{ + u1 type; // for JDK16 or higher + u2 off_dt; // for StackMap - off + u2 nloc; + verinf locs[nlocks]; + u2 nstk; + verinf stks[nstk]; +}; +*/ +// Initial stack map frame: off=0, stack is free, max_locals, max_stack; + +// StackMap types +enum SM_ITEM // u1 +{ + ITEM_Bogus = 0, // unused (unknown type -- can't used directly) + ITEM_Integer, + ITEM_Float, + ITEM_Double, + ITEM_Long, + ITEM_Null, + ITEM_UnitializedThis, + ITEM_Object, // +pool_index + ITEM_Uninitialized, // +offset (u2) + // additional for out + ITEM_BADOBJECT, + ITEM_CURCLASS +}; + +#endif diff --git a/idasdk76/module/java/emu.cpp b/idasdk76/module/java/emu.cpp new file mode 100644 index 0000000..8ebfd5a --- /dev/null +++ b/idasdk76/module/java/emu.cpp @@ -0,0 +1,316 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "java.hpp" + +static const char badlocvar[] = "Invalid local variable number"; + +//---------------------------------------------------------------------- +uval_t java_t::SearchFM(ushort name, ushort dscr, char *naprN) +{ + char buf[(qmax(sizeof(FieldInfo), sizeof(SegInfo))+1+3)&~3]; + sval_t pos = curClass.FieldCnt; + uint32 csz = sizeof(FieldInfo); + sval_t napr = *naprN; + + if ( napr != 1 ) + { + if ( napr != -1 ) + INTERNAL("SearchFM"); + pos = -(uval_t)curClass.MethodCnt; + csz = sizeof(SegInfo); + } + void *p = buf; + for ( ; pos; pos -= napr ) + { + if ( ClassNode.supval(pos, p, sizeof(buf)) != csz ) + DESTROYED("SearchFM"); + if ( ((_FMid_ *)p)->extflg & EFL_NAMETYPE + || CmpString(name, ((_FMid_ *)p)->name) + || CmpString(dscr, ((_FMid_ *)p)->dscr) ) + { + continue; + } + if ( napr >= 0 ) + return curClass.start_ea + ((FieldInfo *)p)->id.Number; + if ( ((SegInfo *)p)->CodeSize ) + *naprN = 0; + return ((SegInfo *)p)->start_ea; + } + return BADADDR; +} + +//------------------------------------------------------------------------ +void java_t::mark_and_comment(ea_t ea, const char *cmt) const +{ + remember_problem(PR_ATTN, ea); + if ( *cmt && (!has_cmt(get_flags(ea)) || ea == curClass.start_ea) ) + append_cmt(ea, cmt, false); +} + +//------------------------------------------------------------------------ +void java_t::TouchArg(const insn_t &insn, const op_t &x, bool isload) +{ + const char *p; + + switch ( x.type ) + { + case o_void: // not operand + break; + + case o_cpool: // ConstantPool reference (index) + if ( x.ref ) + { + p = x.ref == 1 + ? "Invalid string in constant pool" + : "Invalid index in constant pool"; + goto mark; + } + if ( x.cp_ind ) + { + ea_t ea; + char npr = -1; + + switch ( (uchar)x.cp_type ) + { + case CONSTANT_Fieldref: + npr = 1; + // fallthrough + case CONSTANT_InterfaceMethodref: + case CONSTANT_Methodref: + if ( !(x._subnam | x._name | x._class) ) + break; + if ( x._class == curClass.This.Dscr ) + { + ea = SearchFM(x._subnam, x._dscr, &npr); + if ( ea == BADADDR ) + break; + } + else + { + if ( !insn.xtrn_ip ) + break; + ea = insn.xtrn_ip == 0xFFFF + ? curClass.start_ea + : curClass.xtrnEA + insn.xtrn_ip; + if ( npr < 0 ) + npr = 0; + } + if ( npr <= 0 ) + { + insn.add_cref(ea, x.offb, fl_CF); + if ( !npr ) + auto_cancel(ea, ea+1); + } + else + { + dref_t type = insn.itype == j_putstatic || insn.itype == j_putfield + ? dr_W + : dr_R; + insn.add_dref(ea, x.offb, type); + } + break; + + case CONSTANT_Class: + if ( insn.xtrn_ip ) + { + ea_t target = insn.xtrn_ip == 0xFFFF + ? curClass.start_ea + : curClass.xtrnEA + insn.xtrn_ip; + insn.add_dref(target, x.offb, dr_I); + } + break; + default: + break; + } + } + break; + + case o_array: // type! + if ( x.ref ) + { + p = "Invalid array type"; + goto mark; + } + break; + + case o_imm: // const (& #data) + if ( x.ref < 2 ) + set_immd(insn.ea); + break; + + case o_mem: // local data pool + if ( x.ref ) + { + p = badlocvar; +mark: + mark_and_comment(insn.ea, p); + } + else + { + dref_t ref = isload ? dr_R : dr_W; + ea_t adr = curSeg.DataBase + x.addr; + insn.add_dref(adr, x.offb, ref); + if ( (x.dtype == dt_qword || x.dtype == dt_double) + && get_item_size(adr) <= 1 ) + { + insn.add_dref(adr + 1, x.offb, ref); + } + } + break; + + case o_near: + if ( x.ref ) + { + p = "Invalid jump address"; + goto mark; + } + insn.add_cref( + curSeg.start_ea + x.addr, + x.offb, + (Feature & CF_CALL) != 0 ? fl_CN : fl_JN); + break; + + default: + warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, + x.type); + break; + } +} + +//---------------------------------------------------------------------- +int java_t::emu(const insn_t &insn) +{ + Feature = insn.get_canon_feature(ph); + + if ( insn.wid > 1 ) + mark_and_comment(insn.ea, "Limited usage instruction"); + + if ( insn.itype >= j_a_software ) + mark_and_comment(insn.ea, "Undocumented instruction"); + + if ( insn.Op1.type == o_void && insn.Op1.ref ) + { + if ( (char)insn.Op1.ref < 0 ) + { + mark_and_comment(insn.ea, badlocvar); + } + else + { + dref_t ref = (insn.itype >= j_istore_0) ? dr_W : dr_R; + insn.add_dref(insn.Op1.addr, 0, ref); + if ( (insn.Op1.ref & 2) && get_item_size(insn.Op1.addr) <= 1 ) + insn.add_dref(insn.Op1.addr + 1, 0, ref); + } + } + + if ( Feature & CF_USE1 ) + TouchArg(insn, insn.Op1, true); + if ( Feature & CF_USE2 ) + TouchArg(insn, insn.Op2, true); + if ( Feature & CF_USE3 ) + TouchArg(insn, insn.Op3, true); + + if ( Feature & CF_CHG1 ) + TouchArg(insn, insn.Op1, false); + + if ( insn.swit ) // tableswitch OR lookupswitch + { + uval_t count, addr, rnum; + + if ( insn.swit & 0200 ) + mark_and_comment(insn.ea, badlocvar); + if ( insn.swit & 0100 ) + mark_and_comment(insn.ea, "Nonzero filler (warning)"); + + rnum = insn.Op2.value - 1; // for lookupswtitch + for ( addr=insn.Op2.addr, count=insn.Op3.value; count; addr +=4, count-- ) + { + uval_t refa; + + if ( insn.itype != j_lookupswitch ) + { + ++rnum; + } + else + { + rnum = get_dword(curSeg.start_ea + addr); // skip pairs + addr += 4; + } + refa = insn.ip + get_dword(curSeg.start_ea + addr); + + if ( refa < curSeg.CodeSize ) + { + add_cref(insn.ea, (refa += curSeg.start_ea), fl_JN); + if ( !has_cmt(get_flags(refa)) ) + { + char str[32]; + qsnprintf(str, sizeof(str), "case %" FMT_EA "u", rnum); + set_cmt(refa, str, false); + } + } + } + } + + if ( !(Feature&CF_STOP) && (!(Feature&CF_CALL) || func_does_return(insn.ea)) ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + return 1; +} + +//---------------------------------------------------------------------- +size_t java_t::make_locvar_cmt(qstring *buf, const insn_t &insn) +{ + LocVar lv; + + if ( curSeg.varNode ) + { + const char *p = NULL; + uval_t idx = insn.Op1.addr; + + if ( insn.Op1.type == o_mem ) + { + if ( !insn.Op1.ref ) + { + switch ( insn.itype ) + { + case j_ret: + p = "Return"; + break; + case j_iinc: + p = "Add 8-bit signed const to"; + break; + default: + p = "Push"; + if ( insn.get_canon_feature(ph) & CF_CHG1 ) + p = "Pop"; + break; + } + } + } + else if ( insn.Op1.type == o_void + && (char)insn.Op1.ref >= 0 + && (int32)(idx -= curSeg.DataBase) >= 0 ) + { + p = "Push"; + if ( insn.itype >= j_istore_0 ) + p = "Pop"; + } + + if ( p != NULL && netnode(curSeg.varNode).supval(idx,&lv,sizeof(lv)) == sizeof(lv) ) + { + if ( fmtName(lv.var.Name, tmp_name, sizeof(tmp_name), fmt_UnqualifiedName) ) + return buf->sprnt("%s %s", p, tmp_name).length(); + } + } + return 0; +} diff --git a/idasdk75/module/java/fmtstr.cpp b/idasdk76/module/java/fmtstr.cpp similarity index 100% rename from idasdk75/module/java/fmtstr.cpp rename to idasdk76/module/java/fmtstr.cpp diff --git a/idasdk76/module/java/ins.cpp b/idasdk76/module/java/ins.cpp new file mode 100644 index 0000000..90239bc --- /dev/null +++ b/idasdk76/module/java/ins.cpp @@ -0,0 +1,235 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include <ida.hpp> +#include <idp.hpp> +#include "ins.hpp" + +// ATTENTION: if change mnemonic(s) change version in 'jas_rw.cc' +const instruc_t Instructions[] = +{ + + { "nop", 0 }, // Do nothing + { "aconst_null", 0 }, // Push null object reference + { "iconst_m1", 0 }, // Push integer constant -1 + { "iconst_0", 0 }, // Push the integer 0 + { "iconst_1", 0 }, // Push the integer 1 + { "iconst_2", 0 }, // Push the integer 2 + { "iconst_3", 0 }, // Push the integer 3 + { "iconst_4", 0 }, // Push the integer 4 + { "iconst_5", 0 }, // Push the integer 5 + { "lconst_0", 0 }, // Push the long integer 0 + { "lconst_1", 0 }, // Push the long integer 1 + { "fconst_0", 0 }, // Push the single-precision foating point 0.0 + { "fconst_1", 0 }, // Push the single-precision foating point 1.0 + { "fconst_2", 0 }, // Push the single-precision foating point 2.0 + { "dconst_0", 0 }, // Push the double-precision foating point 0.0 + { "dconst_1", 0 }, // Push the double-precision foating point 1.0 + { "bipush", CF_USE1 }, // Push one-byte integer + { "sipush", CF_USE1 }, // Push two-byte integer + { "ldc", CF_USE1 }, // Push item from constant pool (i1) + { "ldc_w", CF_USE1 }, // Push item from constant pool (i2) + { "ldc2_w", CF_USE1 }, // Push long or double from constant pool + { "iload", CF_USE1 }, // Push integer value of the local variable + { "lload", CF_USE1 }, // Push long value of the local variable + { "fload", CF_USE1 }, // Push single-float. val. of the local variable + { "dload", CF_USE1 }, // Push double-float. val. of the local variable + { "aload", CF_USE1 }, // Push object reference from the local variable + { "iload_0", 0 }, // Push integer value of the local variable #0 + { "iload_1", 0 }, // Push integer value of the local variable #1 + { "iload_2", 0 }, // Push integer value of the local variable #2 + { "iload_3", 0 }, // Push integer value of the local variable #3 + { "lload_0", 0 }, // Push long value of the local variable #0 + { "lload_1", 0 }, // Push long value of the local variable #1 + { "lload_2", 0 }, // Push long value of the local variable #2 + { "lload_3", 0 }, // Push long value of the local variable #3 + { "fload_0", 0 }, // Push single-flt. val. of the local variable #0 + { "fload_1", 0 }, // Push single-flt. val. of the local variable #1 + { "fload_2", 0 }, // Push single-flt. val. of the local variable #2 + { "fload_3", 0 }, // Push single-flt. val. of the local variable #3 + { "dload_0", 0 }, // Push double-flt. val. of the local variable #0 + { "dload_1", 0 }, // Push double-flt. val. of the local variable #1 + { "dload_2", 0 }, // Push double-flt. val. of the local variable #2 + { "dload_3", 0 }, // Push double-flt. val. of the local variable #3 + { "aload_0", 0 }, // Push object reference from the local var. #0 + { "aload_1", 0 }, // Push object reference from the local var. #1 + { "aload_2", 0 }, // Push object reference from the local var. #2 + { "aload_3", 0 }, // Push object reference from the local var. #3 + { "iaload", 0 }, // Push integer from array + { "laload", 0 }, // Push long from array + { "faload", 0 }, // Push single float from array + { "daload", 0 }, // Push double float from array + { "aaload", 0 }, // Push object reference from array + { "baload", 0 }, // Push signed byte from array + { "caload", 0 }, // Push signed char from array + { "saload", 0 }, // Push short from array + { "istore", CF_CHG1 }, // Pop integer value into local variable + { "lstore", CF_CHG1 }, // Pop long value into local variable + { "fstore", CF_CHG1 }, // Pop single float value into local variable + { "dstore", CF_CHG1 }, // Pop double float value into local variable + { "astore", CF_CHG1 }, // Pop object refernce into local variable + { "istore_0", 0 }, // Pop integer value into local variable #0 + { "istore_1", 0 }, // Pop integer value into local variable #1 + { "istore_2", 0 }, // Pop integer value into local variable #2 + { "istore_3", 0 }, // Pop integer value into local variable #3 + { "lstore_0", 0 }, // Pop long value into local variable #0 + { "lstore_1", 0 }, // Pop long value into local variable #1 + { "lstore_2", 0 }, // Pop long value into local variable #2 + { "lstore_3", 0 }, // Pop long value into local variable #3 + { "fstore_0", 0 }, // Pop single float value into local variable #0 + { "fstore_1", 0 }, // Pop single float value into local variable #1 + { "fstore_2", 0 }, // Pop single float value into local variable #2 + { "fstore_3", 0 }, // Pop single float value into local variable #3 + { "dstore_0", 0 }, // Pop doublefloat value into local variable #0 + { "dstore_1", 0 }, // Pop doublefloat value into local variable #1 + { "dstore_2", 0 }, // Pop doublefloat value into local variable #2 + { "dstore_3", 0 }, // Pop doublefloat value into local variable #3 + { "astore_0", 0 }, // Pop object refernce into local variable #0 + { "astore_1", 0 }, // Pop object refernce into local variable #1 + { "astore_2", 0 }, // Pop object refernce into local variable #2 + { "astore_3", 0 }, // Pop object refernce into local variable #3 + { "iastore", 0 }, // Pop integer from array + { "lastore", 0 }, // Pop long from array + { "fastore", 0 }, // Pop single float from array + { "dastore", 0 }, // Pop double float from array + { "aastore", 0 }, // Pop object reference from array + { "bastore", 0 }, // Pop signed byte from array + { "castore", 0 }, // Pop signed char from array + { "sastore", 0 }, // Pop short from array + { "pop", 0 }, // Pop top stack word + { "pop2", 0 }, // Pop top two stack word + { "dup", 0 }, // Duplicate top stack word + { "dup_x1", 0 }, // Duplicate top stack word and put two down + { "dup_x2", 0 }, // Duplicate top stack word and put three down + { "dup2", 0 }, // Duplicate top two stack word + { "dup2_x1", 0 }, // Duplicate top two stack words and put two down + { "dup2_x2", 0 }, // Duplicate top two stack words and put three down + { "swap", 0 }, // Swap two top stack words + { "iadd", 0 }, // Integer add + { "ladd", 0 }, // Long add + { "fadd", 0 }, // Single float add + { "dadd", 0 }, // Double float add + { "isub", 0 }, // Integer subtract + { "lsub", 0 }, // Long subtract + { "fsub", 0 }, // Single float subtract + { "dsub", 0 }, // Double float subtract + { "imul", 0 }, // Integer multiply + { "lmul", 0 }, // Long multiply + { "fmul", 0 }, // Single float multiply + { "dmul", 0 }, // Double float multiply + { "idiv", 0 }, // Integer divide + { "ldiv", 0 }, // Long divide + { "fdiv", 0 }, // Single float divide + { "ddiv", 0 }, // Double float divide + { "irem", 0 }, // Integer remainder + { "lrem", 0 }, // Long remainder + { "frem", 0 }, // Single float remainder + { "drem", 0 }, // Double float remainder + { "ineg", 0 }, // Integer negate + { "lneg", 0 }, // Long negate + { "fneg", 0 }, // Single float negate + { "dneg", 0 }, // Double float negate + { "ishl", 0 }, // Integer shift left + { "lshl", 0 }, // Long shift left + { "ishr", 0 }, // Integer logical shift right + { "lshr", 0 }, // Long logical shift right + { "iushr", 0 }, // Integer arithmetic shift right + { "lushr", 0 }, // Long arithmeticshift right + { "iand", 0 }, // Integer boolean AND + { "land", 0 }, // Long boolean AND + { "ior", 0 }, // Integer boolean OR + { "lor", 0 }, // Long boolean OR + { "ixor", 0 }, // Integer boolean XOR + { "lxor", 0 }, // Long boolean XOR + { "iinc", CF_CHG1|CF_USE2 }, // Add 8-bit signed const to local variable + { "i2l", 0 }, // Integer to Long conversion + { "i2f", 0 }, // Integer to Single float conversion + { "i2d", 0 }, // Integer to Double float conversion + { "l2i", 0 }, // Long to Integer conversion + { "l2f", 0 }, // Long to Single float conversion + { "l2d", 0 }, // Long to Double float conversion + { "f2i", 0 }, // Single float to Integer conversion + { "f2l", 0 }, // Single float to Long conversion + { "f2d", 0 }, // Single float to Double float conversion + { "d2i", 0 }, // Double float to Integer conversion + { "d2l", 0 }, // Double float to Long conversion + { "d2f", 0 }, // Double float to Single float conversion + { "int2byte", 0 }, // Integer to signed byte conversion + { "int2char", 0 }, // Integer to unsigned short conversion + { "int2short", 0 }, // Integer to signed short conversion + { "lcmp", 0 }, // Long compare + { "fcmpl", 0 }, // Single float compare (-1 on NaN) + { "fcmpg", 0 }, // Single float compare (1 on NaN) + { "dcmpl", 0 }, // Double float compare (-1 on NaN) + { "dcmpg", 0 }, // Double float compare (1 on NaN) + { "ifeq", CF_USE1 }, // Branch if equal to 0 + { "ifne", CF_USE1 }, // Branch if not equal to 0 + { "iflt", CF_USE1 }, // Branch if less then 0 + { "ifge", CF_USE1 }, // Branch if greater than or equal to 0 + { "ifgt", CF_USE1 }, // Branch if greater than 0 + { "ifle", CF_USE1 }, // Branch if less than or equal to 0 + { "if_icmpeq", CF_USE1 }, // Branch if integers equal + { "if_icmpne", CF_USE1 }, // Branch if integers not equal + { "if_icmplt", CF_USE1 }, // Branch if integers less than + { "if_icmpge", CF_USE1 }, // Branch if integers grater than or equal to + { "if_icmpgt", CF_USE1 }, // Branch if integers grater than + { "if_icmple", CF_USE1 }, // Branch if integers less than or equal to + { "if_acmpeq", CF_USE1 }, // Branch if object references are equal + { "if_acmpne", CF_USE1 }, // Branch if object references not equal + { "goto", CF_USE1|CF_STOP }, // Branch always + { "jsr", CF_USE1|CF_CALL }, // Jump subroutine + { "ret", CF_USE1|CF_STOP }, // Return from subroutine + { "tableswitch", CF_USE1|CF_USE2|CF_USE3 }, // Access jump table by index and jump + { "lookupswitch", CF_USE1|CF_USE2 }, // Access jump table by key match and jump + { "ireturn", CF_STOP }, // Return integer from function + { "lreturn", CF_STOP }, // Return long from function + { "freturn", CF_STOP }, // Return single float from function + { "dreturn", CF_STOP }, // Return double float from function + { "areturn", CF_STOP }, // Return object reference from function + { "return", CF_STOP }, // Return (void) from procedure + { "getstatic", CF_USE1 }, // Set static field from class + { "putstatic", CF_USE1 }, // Set static field in class + { "getfield", CF_USE1 }, // Fetch field from object + { "putfield", CF_CHG1 }, // Set field in object + { "invokevirtual", CF_USE1|CF_USE2|CF_CALL }, // invoke instance method + { "invokespecial", CF_USE1|CF_CALL }, // invoke instance method (super/private/init) + { "invokestatic", CF_USE1|CF_CALL }, // invoke a class (static) method + { "invokeinterface", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // invoke interface method + { "invokedynamic", CF_USE1|CF_USE2|CF_CALL }, // + { "new", CF_USE1 }, // Create new object + { "newarray", CF_USE1 }, // Allocate new array + { "anewarray", CF_USE1 }, // Allocate new array of references to object + { "arraylength", 0 }, // Get length of array + { "athrow", CF_STOP }, // Throw exception or error + { "checkcast", CF_USE1 }, // Make sure object is of given type + { "instanceof", CF_USE1 }, // Determine if an object is of given type + { "monitorenter", 0 }, // Enter monitored region of code + { "monitorexit", 0 }, // Exit monitored region of code + { "wide", 0 }, // WIDE PREFIX of Command + { "multianewarray", CF_USE1|CF_USE2 }, // Allocate new multidimensional array + { "ifnull", CF_USE1 }, // Branch if NULL-ptr + { "ifnonnull", CF_USE1 }, // Branch if not NULL-ptr + { "goto_w", CF_USE1 }, // Branch always (wide index) + { "jsr_w", CF_USE1 }, // Jump subroutine (wide index) + { "breakpoint", 0 }, // Stop and pass control to breakpoint handler + //{ "ret_w", CF_USE1 }, // Return from subroutine (wide index) + // Pseudocode for quick + { "invokesuper", CF_USE1|CF_CALL }, + { "invokevirtualobject", CF_USE1|CF_USE2|CF_CALL }, + { "invokeignored", CF_USE1 }, + // SUN-dependet + { "software", 0 }, + { "hardware", 0 } + +}; + +CASSERT(qnumber(Instructions) == j_last); diff --git a/idasdk76/module/java/ins.hpp b/idasdk76/module/java/ins.hpp new file mode 100644 index 0000000..a96aa2b --- /dev/null +++ b/idasdk76/module/java/ins.hpp @@ -0,0 +1,267 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-2021 Hex-Rays + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + + +extern const instruc_t Instructions[]; +enum nameNum ENUM_SIZE(uint16) +{ + j_nop = 0, // 0 Do nothing + j_aconst_null, // 1 Push null object reference + j_iconst_m1, // 2 Push integer constant -1 + j_iconst_0, // 3 Push the integer 0 + j_iconst_1, // 4 Push the integer 1 + j_iconst_2, // 5 Push the integer 2 + j_iconst_3, // 6 Push the integer 3 + j_iconst_4, // 7 Push the integer 4 + j_iconst_5, // 8 Push the integer 5 + j_lconst_0, // 9 Push the long integer 0 + j_lconst_1, // 10 Push the long integer 1 + j_fconst_0, // 11 Push the single-precision foating point 0.0 + j_fconst_1, // 12 Push the single-precision foating point 1.0 + j_fconst_2, // 13 Push the single-precision foating point 2.0 + j_dconst_0, // 14 Push the double-precision foating point 2.0 + j_dconst_1, // 15 Push the double-precision foating point 2.0 + j_bipush, // 16 Push one byte signed integer + j_sipush, // 17 Push two-byte signed integer + j_ldc, // 18 Push item from constant pool (i1) + j_ldcw, // 19 Push item from constant pool (i2) + j_ldc2w, // 20 Push long or double from constant pool + j_iload, // 21 Push integer value of the local variable + j_lload, // 22 Push long value of the local variable + j_fload, // 23 Push single float value of the local variable + j_dload, // 24 Push double float value of the local variable + j_aload, // 25 Push object reference from the local variable + j_iload_0, // 26 Push integer value of the local variable #0 + j_iload_1, // 27 Push integer value of the local variable #1 + j_iload_2, // 28 Push integer value of the local variable #2 + j_iload_3, // 29 Push integer value of the local variable #3 + j_lload_0, // 30 Push long value of the local variable #0 + j_lload_1, // 31 Push long value of the local variable #1 + j_lload_2, // 32 Push long value of the local variable #2 + j_lload_3, // 33 Push long value of the local variable #3 + j_fload_0, // 34 Push single float value of the local variable #0 + j_fload_1, // 35 Push single float value of the local variable #1 + j_fload_2, // 36 Push single float value of the local variable #2 + j_fload_3, // 37 Push single float value of the local variable #3 + j_dload_0, // 38 Push double float value of the local variable #0 + j_dload_1, // 39 Push double float value of the local variable #1 + j_dload_2, // 40 Push double float value of the local variable #2 + j_dload_3, // 41 Push double float value of the local variable #3 + j_aload_0, // 42 Push object reference from the local variable #0 + j_aload_1, // 43 Push object reference from the local variable #1 + j_aload_2, // 44 Push object reference from the local variable #2 + j_aload_3, // 45 Push object reference from the local variable #3 + j_iaload, // 46 Push integer from array + j_laload, // 47 Push long from array + j_faload, // 48 Push single float from array + j_daload, // 49 Push double float from array + j_aaload, // 50 Push object refernce from array + j_baload, // 51 Push signed byte from array + j_caload, // 52 Push character from array + j_saload, // 53 Push short from array + j_istore, // 54 Pop integer value into local variable + j_lstore, // 55 Pop long value into local variable + j_fstore, // 56 Pop single float value into local variable + j_dstore, // 57 Pop double float value into local variable + j_astore, // 58 Pop object refernce into local variable + j_istore_0, // 59 Pop integer value into local variable #0 + j_istore_1, // 60 Pop integer value into local variable #1 + j_istore_2, // 61 Pop integer value into local variable #2 + j_istore_3, // 62 Pop integer value into local variable #3 + j_lstore_0, // 63 Pop long value into local variable #0 + j_lstore_1, // 64 Pop long value into local variable #1 + j_lstore_2, // 65 Pop long value into local variable #2 + j_lstore_3, // 66 Pop long value into local variable #3 + j_fstore_0, // 67 Pop single float value into local variable #0 + j_fstore_1, // 68 Pop single float value into local variable #1 + j_fstore_2, // 69 Pop single float value into local variable #2 + j_fstore_3, // 70 Pop single float value into local variable #3 + j_dstore_0, // 71 Pop double float value into local variable + j_dstore_1, // 72 Pop double float value into local variable #0 + j_dstore_2, // 73 Pop double float value into local variable #1 + j_dstore_3, // 74 Pop double float value into local variable #2 + j_astore_0, // 75 Pop object refernce into local variable #0 + j_astore_1, // 76 Pop object refernce into local variable #1 + j_astore_2, // 77 Pop object refernce into local variable #2 + j_astore_3, // 78 Pop object refernce into local variable #3 + j_iastore, // 79 Pop integer from array + j_lastore, // 80 Pop long from array + j_fastore, // 81 Pop single float from array + j_dastore, // 82 Pop double float from array + j_aastore, // 83 Pop object refernce from array + j_bastore, // 84 Pop signed byte from array + j_castore, // 85 Pop character from array + j_sastore, // 86 Pop short from array + j_pop, // 87 Pop top stack word + j_pop2, // 88 Pop top two stack word + j_dup, // 89 Duplicate top stack word + j_dup_x1, // 90 Duplicate top stack word and put two down + j_dup_x2, // 91 Duplicate top stack word and put three down + j_dup2, // 92 Duplicate top two stack word + j_dup2_x1, // 93 Duplicate top two stack words and put two down + j_dup2_x2, // 94 Duplicate top two stack words and put three down + j_swap, // 95 Swap two top stack words + j_iadd, // 96 Integer add + j_ladd, // 97 Long add + j_fadd, // 98 Single float add + j_dadd, // 99 Double float add + j_isub, // 100 Integer subtract + j_lsub, // 101 Long subtract + j_fsub, // 102 Single float subtract + j_dsub, // 103 Double Float subtract + j_imul, // 104 Integer multiply + j_lmul, // 105 Long multiply + j_fmul, // 106 Single float multiply + j_dmul, // 107 Double Float multiply + j_idiv, // 108 Integer divide + j_ldiv, // 109 Long divide + j_fdiv, // 110 Single float divide + j_ddiv, // 111 Double Float divide + j_irem, // 112 Integer reminder + j_lrem, // 113 Long reminder + j_frem, // 114 Single float reminder + j_drem, // 115 Double Float reminder + j_ineg, // 116 Integer negate + j_lneg, // 117 Long negate + j_fneg, // 118 Single float negate + j_dneg, // 119 Double Float negate + j_ishl, // 120 Integer shift left + j_lshl, // 121 Long shift left + j_ishr, // 122 Integer logical shift right + j_lshr, // 123 Long logical shift right + j_iushr, // 124 Integer arithmetic shift right + j_lushr, // 125 Long arithmeticshift right + j_iand, // 126 Integer boolean AND + j_land, // 127 Long boolean AND + j_ior, // 128 Integer boolean OR + j_lor, // 129 Long boolean OR + j_ixor, // 130 Integer boolean XOR + j_lxor, // 131 Long boolean XOR + j_iinc, // 132 Add 8-bit signed const to local variable + j_i2l, // 133 Integer to Long conversion + j_i2f, // 134 Integer to single float conversion + j_i2d, // 135 Integer to double float conversion + j_l2i, // 136 Long to Integer conversion + j_l2f, // 137 Long to single float conversion + j_l2d, // 138 Long to double float conversion + j_f2i, // 139 Single float to Integer conversion + j_f2l, // 140 Single float to Long conversion + j_f2d, // 141 Single float to double float conversion + j_d2i, // 142 Double float to Integer conversion + j_d2l, // 143 Double float to Long conversion + j_d2f, // 144 Double float to double float conversion + j_i2b, // 145 Integer to signed byte conversion + j_i2c, // 146 Integer to unsigned short conversion + j_i2s, // 147 Integer to signed short conversion + j_lcmp, // 148 Long compare + j_fcmpl, // 149 Single float compare (-1 on NaN) + j_fcmpg, // 150 Single float compare (1 on NaN) + j_dcmpl, // 151 Double float compare (-1 on NaN) + j_dcmpg, // 152 Double float compare (1 on NaN) + j_ifeq, // 153 Branch if equal to 0 + j_ifne, // 154 Branch if not equal to 0 + j_iflt, // 155 Branch if less then 0 + j_ifge, // 156 Branch if greater than or equal to 0 + j_ifgt, // 157 Branch if greater than 0 + j_ifle, // 158 Branch if less than or equal to 0 + j_if_icmpeq, // 159 Branch if integers equal + j_if_icmpne, // 160 Branch if integers not equal + j_if_icmplt, // 161 Branch if integers less than + j_if_icmpge, // 162 Branch if integers grater than or equal to + j_if_icmpgt, // 163 Branch if integers grater than + j_if_icmple, // 164 Branch if integers less than or equal to + j_if_acmpeq, // 165 Branch if object references are equal + j_if_acmpne, // 166 Branch if object references not equal + j_goto, // 167 Branch always + j_jsr, // 168 Jump subroutine + j_ret, // 169 Return from subroutine + j_tableswitch, // 170 Access jump table by index and jump + j_lookupswitch, // 171 Access jump table by key match and jump + j_ireturn, // 172 Return integer from function + j_lreturn, // 173 Return long from function + j_freturn, // 174 Return single floatr from function + j_dreturn, // 175 Return double float from function + j_areturn, // 176 Return object reference from function + j_return, // 177 Return (void) from procedure + j_getstatic, // 178 Set static field from class + j_putstatic, // 179 Set static field in class + j_getfield, // 180 Fetch field from object + j_putfield, // 181 Set field in object + j_invokevirtual, // 182 invoke instance method + j_invokespecial, // 183 invoke instance method (superclass/init/...) + j_invokestatic, // 184 invoke a class (static) method + j_invokeinterface,// 185 invoke interface method + j_invokedynamic, // 186 invoke instance method (select by paraneter) + j_new, // 187 Create new object + j_newarray, // 188 Allocate new array + j_anewarray, // 189 Allocate new array of refernces to object + j_arraylength, // 190 Get length of array + j_athrow, // 191 Throw exception or error + j_checkcast, // 192 Make sure object is of given type + j_instanceof, // 193 Determine if an object is of given type + j_monitorenter, // 194 Enter monitored region of code + j_monitorexit, // 195 Exit monitored region of code + j_wide, // 196 wide (prefix of command) + j_multianewarray, // 197 Allocate new multi-dimensional array + j_ifnull, // 198 Branch if NULL-ptr + j_ifnonnull, // 199 Branch if not NULL-ptr + j_goto_w, // 200 Branch always (wide index) + j_jsr_w, // 201 Jump subroutine (wide index) + j_breakpoint, // 202 Stop and pass control to breakpoint handler + // + j_lastnorm, + j_a_invokesuper = j_lastnorm, + j_a_invokevirtualobject, + j_a_invokeignored, + // bottom of table ! (emu) + j_a_software, + j_a_hardware, + // + j_last +}; + +enum name_quick +{ + j_ldc_quick = j_lastnorm, // 203 (18) + j_ldcw_quick, // 204 (19) + j_ldc2w_quick, // 205 (20) + j_getfield_quick, // 206 (180) + j_putfield_quick, // 207 (181) + j_getfield2_quick, // 208 + j_putfield2_quick, // 209 + j_getstatic_quick, // 210 (178) + j_putstatic_quick, // 211 (179) + j_getstatic2_quick, // 212 + j_putstatic2_quick, // 213 + j_invokevirtual_quick, // 214 (182) + j_invokenonvirtual_quick, // 215 (183) + j_invokesuper_quick, // 216 + j_invokestatic_quick, // 217 (184) + j_invokeinterface_quick, // 218 (185) + j_invokevirtualobject_quick, // 219 + j_invokeignored_quick, // 220 + j_new_quick, // 221 (187) + j_anewarray_quick, // 222 (189) + j_multianewarray_quick, // 223 (197) + j_checkcast_quick, // 224 (192) + j_instanceof_quick, // 225 (193) + j_invokevirtual_quick_w, // 226 + j_getfield_quick_w, // 227 + j_putfield_quick_w, // 228 + j_quick_last +}; + +#define j_software 254 +#define j_hardware 255 +#endif diff --git a/idasdk75/module/java/jas_rw.cc b/idasdk76/module/java/jas_rw.cc similarity index 100% rename from idasdk75/module/java/jas_rw.cc rename to idasdk76/module/java/jas_rw.cc diff --git a/idasdk76/module/java/java.hpp b/idasdk76/module/java/java.hpp new file mode 100644 index 0000000..fcdf59e --- /dev/null +++ b/idasdk76/module/java/java.hpp @@ -0,0 +1,651 @@ +//#define __debug__ + +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _JAVA_HPP +#define _JAVA_HPP + +#define VIEW_WITHOUT_TYPE // no show return/filed type in command if !jasmin() + +#include <pro.h> +#include "../idaidp.hpp" +#include <fpro.h> +#include <ieee.h> + +#include "classfil.hpp" +#include "ins.hpp" +struct java_t; + +#pragma pack(1) +//---------------------------------------------------------------------- +// Redefine temporary names +// +#define wid segpref +#define xtrn_ip auxpref + +#define swit Op1.specflag2 +#define ref specflag1 +#define _name value_shorts.low +#define _class value_shorts.high +#define _bmidx value_shorts.high +#define _mhr_kind value_shorts.low // MethodHandle reference_kind +#define _mhr_index value_shorts.high // MethodHandle reference_index +#define _mtd_index value_shorts.low // MethodType descriptor_index +#define _dscr addr_shorts.low +#define _subnam addr_shorts.high +#define cp_ind specval_shorts.low +#define cp_type specval_shorts.high +// nexts for Utf8 (on load) and _Ssize used in MAP only +#define _Ssize addr_shorts.low +#define _Sflags addr_shorts.high +#define _Sopstr value2 + +// command aliases +#define o_cpool o_idpspec0 +#define o_array o_idpspec1 + +//---------------------------------------------------------------------- +struct TXS +{ + const char *str; + uchar size; +}; +#define TXS_DECLARE(p) { p, (uchar)(sizeof(p)-1) } +#define TXS_EMPTY() { NULL, 0 } + +//---------------------------------------------------------------------- +struct const_desc_t +{ + uchar type; // CONSTANT_type + uchar flag; +#define _REF 0x01 // has reference +#define HAS_FLDNAME 0x02 // Utf8 is valid Field/Variable Name +#define HAS_TYPEDSCR 0x04 // Utf8 is valid Descriptor +#define HAS_CALLDSCR 0x08 // Utf8 is valid Descriptor for Method +#define HAS_CLSNAME 0x10 // Utf8 is valid as Class Name (Not FLD!) +#define SUB_FLDNAME 0x20 +#define SUB_TYPEDSCR 0x40 +#define SUB_CALLDSCR 0x80 +#define SUB_SHIFT 4 + CASSERT((HAS_FLDNAME << SUB_SHIFT) == SUB_FLDNAME + && (HAS_TYPEDSCR << SUB_SHIFT) == SUB_TYPEDSCR + && (HAS_CALLDSCR << SUB_SHIFT) == SUB_CALLDSCR); + + bool is_referenced() const { return (flag & _REF) != 0; } + void mark_referenced() { flag |= _REF; } + +#define NORM_FIELD (HAS_CLSNAME | SUB_FLDNAME | SUB_TYPEDSCR) +#define NORM_METOD (HAS_CLSNAME | SUB_FLDNAME | SUB_CALLDSCR) + + ushort ref_ip; // in xtrn-segment... + union + { + uint32 value; // low part of # value + struct + { + ushort low; // BegInd Utf8 (name) + ushort high; // index to _Class + } value_shorts; // unification + }; + union + { + uint32 value2; // hi part of # value + struct + { + ushort low; // TypeName + ushort high; // Descriptor + } addr_shorts; + }; +}; + +union Object +{ // in IDP_JDK12 format was in reverse order! + struct + { + ushort Name; // index to name + ushort Dscr; // index to descriptor + }; + uint32 Ref; // used in out +}; + +struct _FMid_ +{ + ushort name; // index to name + ushort dscr; // index to descriptor + ushort access; // access flag +// Number not needed for search/out + ushort Number; // Number of current Field or Method + uchar extflg; // for ERROR diagnostic and other flags +#define EFL_NAME 1 +#define EFL_TYPE 2 +#define EFL_NAMETYPE (EFL_NAME | EFL_TYPE) +//#define _OLD_EFL_ACCESS 4 +#define EFL__MASK (EFL_NAME | EFL_TYPE | 4) // for check on conversion +// next constant added in JDK15 store-format +// java-2 store format only +#define XFL_DEPRECATED 0x04 +#define XFL_UNICODENAME 0x08 // name contain unicode character +#define XFL_M_LABSTART 0x10 // for METHOD set label at entry +#define XFL_C_SUPEROBJ 0x10 // for THIS - parent(.super) == Object +#define XFL_M_LABEND 0x20 // for METHOD set label at exit +#define XFL_C_DEBEXT 0x20 // for THIS - have stored SourceDebugExtension +#define XFL_M_EMPTYSM 0x40 // for METHOD - have empty StackMap +#define XFL_C_ERRLOAD 0x40 // for THIS - have loadtime problems +#define XFL_C_DONE 0x80 // analisys pass complete +// next fields added in JDK15 store-format + uchar _UNUSED_ALING; // = 0 + ushort utsign; // index to signature attribute +}; + +struct FieldInfo +{ + _FMid_ id; // for search procedure + uval_t valNode; // init value's node +// next fields added in JDK15 store-format + uval_t annNodes[2]; // nodes for Vis/Invis annotation + uval_t genNode; // list of stored generic attributes +}; + +struct SegInfo +{ + _FMid_ id; // for search procedure + uint32 CodeSize; // CODE size + ea_t start_ea; // EA of Code (checker & slb) + ea_t DataBase; // EA of loc variable segment + ushort DataSize; // max locals (DATA size) + ushort stacks; // stack size + uval_t excNode; // Node for exception table + uval_t thrNode; // Node for throws (fmt change!) +// next fields added in JDK15 store-format + uval_t varNode; // LocVar descriptors + uval_t smNode; // StackMap descriptors + // Visible, Invisible, VisibleParam, InvisibleParam, Default + uval_t annNodes[5]; // nodes for all types of annotations + uval_t genNodes[2]; // list of stored generic attributes + code +}; + +struct ClassInfo +{ + ushort maxCPindex; // max valid index in ConstantPool + ushort MinVers; //-> of file + Object This; // class name/descriptor + Object super; // .super class (parent) + ushort AccessFlag; // access flags + ushort FieldCnt; // Field Declaration Counter + uval_t ClassNode; // Field (>0) & Method (<0) (0?) + ushort MethodCnt; // Method's Segment fot this Class + ushort SourceName; // Index of Utf8 Source File Name + uval_t impNode; // Node for Interfaces (fmt change!) + ea_t start_ea; // for SearchFM + uint32 maxSMsize; // optimize memory allocation (StackMap) + // ATT: JDK15 - previous errload + ea_t xtrnEA; // beg header segment + uval_t xtrnNode; // node for xtrn Segment + ushort xtrnCnt; // header size + ushort xtrnLQE; +// next fields added in JDK15 store-format + ushort MajVers; // -> of file + uchar extflg; // XFL_.... consts + uchar JDKsubver; // for speed/size ONLY + uval_t innerNode; // Node for Inner classes + ushort encClass; // EnclosingMethod class + ushort encMethod; // EnclosingMethod NameAndType + uval_t msgNode; // node for store loading messages + ushort utsign; // signature attribute index + ushort maxStrSz; // optimize memory allocation (string) + uval_t annNodes[2]; // nodes for Visible/Invisible + uint32 maxAnnSz; // optimize memory allocation (annotation) + uval_t genNode; // list of stored generic attributes +}; + +#define FOR_EACH_CONSTANT_POOL_INDEX(Binding) for ( ushort Binding = 1; Binding <= curClass.maxCPindex; ++Binding ) + + +struct Exception +{ + ushort start_pc; + ushort end_pc; + ushort handler_pc; + Object filter; +}; + +struct LocVar +{ + ushort ScopeBeg; // scope start + ushort ScopeTop; // scope end + Object var; // name & descriptor + ushort utsign; // signature attribute index +}; + +struct InnerClass +{ + ushort inner; + ushort outer; + ushort name; + ushort access; +}; + +//------------------------------------------------------------------------ +enum sm_node_t +{ + smn_aa_not_finished = -1, + smn_ok = 0, + smn_no_use = 1, +}; +#define CNS_SOURCE -2 +#define CNS_CLASS 0 +//>0 - opis[i] +//>=0x10000 - string blobs +#define CNA_VERSION -1 +#define CNA_KWRDVER -2 +#define CNA_IDPFLAGS -3 // idpflags value +#define CNA_LIMITER -4 // user_limiter state +//>=0x10000 - string info +#define UR_TAG 'r' + +//------------------------------------------------------------------------ +// !DO NOT CHANGE ORDER! +enum fmt_t +{ + fmt_debug = 0, // as fmt_string, but have prompting + fmt_string, // string as text + fmt_string_single_quotes, + fmt_FieldDescriptor, + + // MethodTypeSignature: + // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* + // ^ + fmt_method_FormalTypeParameters, + + // MethodTypeSignature: + // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* + // ^ + fmt_method_ReturnType, + + // MethodTypeSignature: + // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* + // ^ + fmt_method_TypeSignature, + + // MethodTypeSignature: + // FormalTypeParameters opt (TypeSignature*) ReturnType ThrowsSignature* + // ^ + fmt_method_ThrowsSignature, + + fmt_ClassSignature, // class signature (start width <...:...>) + fmt_FieldDescriptor_nospace, // signature (==dscr, without space) + fmt_ClassName_or_Array, // if have '[' desriptor, else fieldname + fmt_ClassName, // extract class from descriptor + fmt_fullname, // full qualified name + fmt_UnqualifiedName, + fmt__ENDENUM + }; +#define FMT_ENC_RESERVED (uchar)0x80 + +//------------------------------------------------------------------------- +inline bool fmt_expects_call_descriptor(fmt_t fmt) +{ + return fmt >= fmt_method_FormalTypeParameters && fmt <= fmt_ClassSignature; +} + +//------------------------------------------------------------------------- +struct SMinfo // for sm_getinfo +{ + const uchar *pb; + const uchar *pe; + uint fcnt; + ea_t ea; +}; + +enum load_mode_t +{ + lm_lenient = -1, // don't call remember_problem() + lm_no_set_ref = 0, // no set reference + lm_normal = 1, // Normal mode + lm_need_cr = 2, // needed CR +}; +ea_t extract_name_ea( + char buf[MAXSTR], + const char *name, + int pos, + uchar clv); +const TXS *get_base_typename(uchar tag, bool or_void=false); + +#if defined(__debug__) || defined(TEST_FMTSTR) +NORETURN extern void _destroyed(const char *from); +NORETURN extern void _faterr(uchar mode, const char *from); +#define UNCOMPAT(p) _faterr(1, p) +#define INTERNAL(p) _faterr(0, p) +#define DESTROYED(p) _destroyed(p) +#else +NORETURN extern void _destroyed(void); +NORETURN extern void _faterr(uchar mode); +#define UNCOMPAT(p) _faterr(1) +#define INTERNAL(p) _faterr(0) +#define DESTROYED(p) _destroyed() +#endif + +uchar javaIdent(ushort v, uchar *isStart = NULL); + +// information record of StackMap +struct sm_info_t +{ + uint32 noff; // start offset in blob + uint32 eoff; // end offset in blob + uint fcnt; // locals at entry +}; + +//------------------------------------------------------------------------ +#ifdef __debug__ +#define DEB_ASSERT(cond, text) if ( cond ) error(text) +#else +#define DEB_ASSERT(cond, text) +#endif + +//------------------------------------------------------------------------ +enum j_registers { Rvars=0, Roptop, Rframe, rVcs, rVds }; + +//------------------------------------------------------------------------ +void idaapi java_header(outctx_t &ctx); + +void idaapi java_segstart(outctx_t &ctx, segment_t *seg); +void idaapi java_segend(outctx_t &ctx, segment_t *seg); + +fpvalue_error_t idaapi j_realcvt(void *m, fpvalue_t *e, ushort swt); + +void idaapi java_data(outctx_t &ctx, bool analyze_only); + +int cmp_operands(op_t &op1, op_t &op2); +bool idaapi can_have_type(const op_t &op); +void copy_const_to_opnd(op_t &x, const const_desc_t &co); + + +//---------------------------------------------------------------------- +#define UAS_JASMIN 0x0001 // is jasmin assembler? + +//------------------------------------------------------------------------ +#define MLD_EXTREF 0x01 +#define MLD_VARREF 0x02 // if present EXTREF must be present +#define MLD_METHREF 0x04 // if present VARREF must be present + +#define MLD_EXTATR 0x08 // store additional attributes to file(s) +#define MLD_LOCVAR 0x10 // Rename local variables +#define MLD_STRIP 0x20 // Semantic error names show +#define MLD_FORCE 0x40 // Ignore 'additional error' on load + +#define MLD__DEFAULT ((MLD_EXTREF|MLD_VARREF) /* | MLD_LOCVAR */) + + +//------------------------------------------------------------------------ +#define IDF_MULTDEB 0x0001 // multiline debug +#define IDF_HIDESM 0x0002 // hide stackmap +#define IDF_AUTOSTR 0x0004 // fmt_string as fmt_debug (next string at \n) +#define IDF_CONVERT 0x0008 // convert (to jasmin) when write asm file +#define IDF_ENCODING 0x0010 // enable unicode-encoding (also see map) +#define IDF_NOPATH 0x0020 // .attribute's filename without path + +// not stored (in base) flags +#define IDM_BADIDXSTR 0x00010000 // show invalid indexes as string's + +// ... and used loader only +#define IDM_REQUNK 0x20000000 // make request of ;unknown attribute' +#define IDM_WARNUNK 0x40000000 // 'unknown attribute' produced warnings +// ... in module, but temporary +#define IDM_OUTASM 0x80000000 // currently write asm file + +#define IDM__REQMASK ((~(IDM_REQUNK | IDM_WARNUNK | IDM_OUTASM)) >> 16) + +// curent modes +#define IDFM__DEFAULT ((IDF_MULTDEB|IDF_CONVERT|IDF_ENCODING) | IDM_WARNUNK) + +#pragma pack() + +//------------------------------------------------------------------ +enum CIC_param +{ + C_4byte = 0, + C_8byte, + C_Field, + C_Method, + C_Interface, + C_Class, + C_Type, + C_TypeName, + C_CallSite, +}; + +enum attr_parent_kind_t +{ + attr_parent_kind_code = 0, + attr_parent_kind_field, + attr_parent_kind_method, + attr_parent_kind_class_file, + attr_parent_kind_CHECK, +}; + +class out_java_t; +typedef size_t _PRMPT_(java_t &pm, out_java_t *oj); +#define MAX_ATTR_NMSZ 128 + +//------------------------------------------------------------------ +DECLARE_PROC_LISTENER(idb_listener_t, struct java_t); + +struct java_t : public procmod_t +{ + idb_listener_t idb_listener = idb_listener_t(*this); + int start_asm_list = 0; + uint32 idpflags = IDFM__DEFAULT; +#ifdef TEST_FMTSTR + inline bool jasmin(void) const { return false; } + inline bool is_multiline_debug(void) const { return true; } // true by default, it seems + inline bool is_fmt_string_as_fmt_debug(void) const { return false; } // false by default, it seems +#else + inline bool jasmin(void) const { return (ash.uflag & UAS_JASMIN) != 0; } + inline bool is_multiline_debug(void) const { return (idpflags & IDF_MULTDEB) != 0; } + inline bool is_fmt_string_as_fmt_debug(void) const { return (idpflags & IDF_AUTOSTR) != 0; } +#endif + bool mode_changed = false; + bool displayed_nl = false; + + bool g_bufinited = false; + uint32 g_bufsize = 0; + uint32 maxpos = 0; + uint32 curpos = 0; + uchar user_limiter = 0; + // next fields are only for out + bool no_prim = false; + size_t outcnt = 0; + size_t ref_pos = 0; + uint32 Feature = 0; + // Normally static buffers of MAX_NODENAME_SIZE are forbidden but since + // 'tmp_name' is defined only in the java module, it is acceptable. To avoid + // warnings we define JAVA_BUFSIZE: +#define JAVA_BUFSIZE MAX_NODENAME_SIZE + char tmp_name[JAVA_BUFSIZE]; + + // map.cpp vars + char rfmt[23] = " %5u=> "; + char ind_fmt[8] = "%s=%-5u"; + char lft_fmt[16] = "%08lX %5u%c %s "; + + // npool.cpp vars + int32 savesize = -1; + uchar sde = 0; + + // npooluti.cpp vars + ClassInfo curClass; + SegInfo curSeg; + FieldInfo curField; + FILE *myFile = nullptr; + netnode ClassNode; + netnode XtrnNode; + netnode ConstantNode; + char debugmode = 0; + uchar SMF_mode = 0; + // only for npool + uchar loadMode = 0; + uint32 errload = 0; + ushort *tsPtr = nullptr; + uchar *smBuf = nullptr; + uchar *annBuf = nullptr; + uint32 FileSize = 0; + sm_node_t sm_node = smn_aa_not_finished; + uchar uni_chk = (uchar)-1; // unicode 'renaming' support + uchar name_chk = 0; + char tmpbuf[JAVA_BUFSIZE]; // see comment for TMP_NAME + netnode SMnode; + uint32 SMsize = 0; + uint endcls = 0; + uchar clunic = 0; // for unicode renaming + ea_t start_ea = 0; + ushort cursel = 1; + // jasmin reserved word support + std::set<qstring> ResW; + + java_t() + { + memset(&curClass, 0, sizeof(curClass)); + memset(&curSeg, 0, sizeof(curSeg)); + memset(&curField, 0, sizeof(curField)); + memset(tmp_name, 0, sizeof(tmp_name)); + memset(tmpbuf, 0, sizeof(tmpbuf)); + } + + inline void StoreOpis(uint index, const const_desc_t &opis) + { + ConstantNode.supset(index, &opis, sizeof(opis)); + } + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + void sm_validate(const SegInfo *si); + + uchar loadDialog(bool manual); + int32 gen_map_file(FILE *fp); + char *convert_clsname(char *buf) const; + void database_loaded(const char *file); + void make_new_name(ushort name, ushort subnam, uchar mode, uint ip); + int upgrade_db_format(int ver, netnode constnode); + void coagulate_unused_data(const SegInfo *ps); + + void java_footer(outctx_t &ctx); + + void load_attributes(attr_parent_kind_t apk); + void loader(FILE *fp, bool manual); + ea_t get_ref_addr(ea_t ea, const char *name, size_t pos); + void TouchArg(const insn_t &insn, const op_t &x, bool isload); + uval_t SearchFM(ushort name, ushort dscr, char *naprN); + void mark_and_comment(ea_t ea, const char *cmt) const; + int emu(const insn_t &insn); + + int format_utf16_string( + const ushort *_tp, + uint32 ostsz, + uint32 off_ReturnType, + uint32 off_ThrowsSignature_and_TypeSignature, + ssize_t size, + fmt_t mode, + out_java_t *oj, + _PRMPT_ putproc); + void xtrnSet( + uint cin, + const_desc_t *co, + uint xip, + char *str, + size_t strsize, + bool full, + uchar rmod=3); + void rename_uninames(int32 mode); + void setPoolReference(void); + void SetName(ushort name, ea_t ea, ushort access, uval_t number, uchar rmod=3); + int refput(ushort index); + bool fmtName(ushort index, char *buf, size_t bufsize, fmt_t fmt); + uchar set_parent_object(void); + uchar attribute_type_from_str(ushort index, attr_parent_kind_t apk, char str[MAX_ATTR_NMSZ]); + void CheckPoolReference(bool insns_created); + void set_lv_name(ushort name, ea_t ea, uchar rmod); + int is_locvar_name(const insn_t &insn, const char *name); + void ValidateStoreLocVar(ushort slot, LocVar & lv); + void dump_floating_constants( + const char *problem, + const char *what, + const intvec_t &ks); + ssize_t check_special_label(const char *buf, size_t len) const; + bool LoadOpis(load_mode_t load_mode, ushort index, uchar _op, const_desc_t *p); + void load_msg(const char *format, ...); + bool isSingleClass(ushort val); + const char *mk_diag(attr_parent_kind_t apk, char str[128]) const; + uint load_constants_pool(void); + inline void BadRefFile(const char *to, ushort id); + void BadRef(ea_t ea, const char *to, ushort id, attr_parent_kind_t apk); + void mark_access(ea_t ea, ushort acc) const; + uchar *sm_realloc(uint size); + uchar *annotation_realloc(uint size); + ushort *append_tmp_buffer(uint size); + bool getblob(uval_t ind, void *p, uval_t sz); + bool getstr(qstring *out, ushort index); + ushort read2(void); + uint32 read4(void); + uchar read1(void); + void readData(void *data, uint32 size); + void skipData(uint32 size); + const uchar *get_annotation(uval_t node, uint *plen); + bool sm_getinfo(const insn_t &insn, SMinfo *pinf); + uchar *annot_elm(uchar *ptr, uint32 *psize, uchar is_array=0); + uchar *annotation(uchar *p, uint32 *psize); + segment_t *getMySeg(ea_t ea, segment_t *seg = nullptr); + bool sm_chkargs(uchar **pptr, uint32 *pDopSize, ushort cnt); + int sm_load(ushort declcnt, uint32 *pDopSize); + NORETURN void loader_failure_bad_attr_decl_size(attr_parent_kind_t apk) const; + int CmpString(ushort index1, ushort index2); + int cmpDscrString(ushort index1, uchar met, ushort index2, uchar self); + ushort xtrnDscrSearch(ushort name, uchar met); + void mark_strange_name(ea_t ea) const; + void xtrnRef(ea_t ea, const const_desc_t &opis) const; + void xtrnRef_dscr(ea_t ea, const_desc_t *opis, uchar met=0); + void deltry(uint bg, uint ic, uint ui, const const_desc_t &pco); + segment_t *_add_seg(int caller); + void resizeLocVars(void) const; + const char *CopyAttrToFile(const char *astr, uint32 size, ushort id); + inline int strstrpos(const char *s1, const char *s2) + { + s2 = strstr(s1, s2); + return s2 == NULL ? -1 : s2 - s1; + } + bool is_valid_string_index(ushort index) const; + uchar LoadUtf8(ushort index, const_desc_t *co); + void parse_const_desc(ushort index, const_desc_t *co); + uchar CheckSignature(ushort index, attr_parent_kind_t apk); + + void ResW_init(void); + void ResW_newbase(void); + uchar ResW_oldbase(void); + void ResW_validate(uint32 *Flags, const ushort *pend); + uint32 upgrade_ResW(uint32 opstr); + void ResW_free(void); + + size_t make_locvar_cmt(qstring *buf, const insn_t &insn); + int32 print_loader_messages(char str[MAXSTR], const char *cmt, outctx_t *ctx); + + int LoadIndex(insn_t &insn); + int ConstLoad(insn_t &insn, CIC_param ctype); + int ana(insn_t *_insn); +}; +extern int data_id; +#endif + diff --git a/idasdk76/module/java/makefile b/idasdk76/module/java/makefile new file mode 100644 index 0000000..6df8bde --- /dev/null +++ b/idasdk76/module/java/makefile @@ -0,0 +1,131 @@ +PROC=java +O1=oututil +O2=map +O3=npool +O4=npooluti +O5=resword +O6=upgrade +O7=fmtstr + +include ../module.mak + +test_fmtstr: $(R)test_fmtstr$(B) + +TEST_FMTSTR_OBJS:=$(F)test_fmtstr_main$(O) +$(R)test_fmtstr$(B): $(call dumb_target, unicode pro, $(TEST_FMTSTR_OBJS)) + +$(F)test_fmtstr_main$(O): CFLAGS += -DTEST_FMTSTR=1 + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp \ + classfil.hpp ins.hpp java.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + emu.cpp ins.hpp java.hpp +$(F)fmtstr$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + fmtstr.cpp ins.hpp java.hpp oututil.hpp upgrade.hpp +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)map$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp java.hpp map.cpp oututil.hpp +$(F)npool$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + classfil.hpp ins.hpp java.hpp npool.cpp npooluti.hpp \ + oututil.hpp upgrade.hpp +$(F)npooluti$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp java.hpp npooluti.cpp npooluti.hpp oututil.hpp \ + upgrade.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp java.hpp npooluti.hpp out.cpp oututil.hpp \ + upgrade.hpp +$(F)oututil$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp java.hpp oututil.cpp oututil.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp java.hpp notify_codes.hpp npooluti.hpp reg.cpp \ + upgrade.hpp +$(F)resword$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp jas_rw.cc java.hpp npooluti.hpp resword.cpp \ + upgrade.hpp +$(F)test_fmtstr_main$(O): $(I)kernwin.hpp $(I)llong.hpp $(I)pro.h \ + fmtstr.cpp test_fmtstr_main.cpp +$(F)upgrade$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp classfil.hpp \ + ins.hpp java.hpp oututil.hpp upgrade.cpp upgrade.hpp diff --git a/idasdk75/module/java/map.cpp b/idasdk76/module/java/map.cpp similarity index 100% rename from idasdk75/module/java/map.cpp rename to idasdk76/module/java/map.cpp diff --git a/idasdk76/module/java/notify_codes.hpp b/idasdk76/module/java/notify_codes.hpp new file mode 100644 index 0000000..ca2496b --- /dev/null +++ b/idasdk76/module/java/notify_codes.hpp @@ -0,0 +1,37 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __JAVA_NOTIFY_CODES_HPP +#define __JAVA_NOTIFY_CODES_HPP + +#include <idp.hpp> + +//---------------------------------------------------------------------- +// The following events are supported by the JAVA module in the ph.notify() function +namespace java_module_t +{ + enum event_codes_t + { + ev_load_file = processor_t::ev_loader, + // load input file (see also function loader()) + // in: linput_t *li + // bool manual + // Returns: 0-ok, otherwise-failed + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline bool load_file(linput_t *li, bool manual) + { + return processor_t::notify(idp_ev(ev_load_file), li, manual) == 0; + } +} + +#endif // __JAVA_NOTIFY_CODES_HPP diff --git a/idasdk76/module/java/npool.cpp b/idasdk76/module/java/npool.cpp new file mode 100644 index 0000000..f5dbc80 --- /dev/null +++ b/idasdk76/module/java/npool.cpp @@ -0,0 +1,2499 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ +#include "java.hpp" +#include <loader.hpp> +#include <diskio.hpp> +#include <segregs.hpp> +#include "npooluti.hpp" +#include "oututil.hpp" + +#define _CUR_IDP_VER IDP_JDK16 + +static const char constant_pool[] = "$ Constant Pool ~"; + +//------------------------------------------------------------------------- +nodeidx_t bootstrap_methods_get_node(bool assert, bool can_create) +{ + // if ( curClass.bmNode != 0 ) + // return curClass.bmNode; + netnode n("$ BootstrapMethods ~"); + if ( can_create && !netnode_exist(n) ) + n.create("$ BootstrapMethods ~"); + if ( assert ) + QASSERT(10333, netnode_exist(n)); + return n; +} + +//------------------------------------------------------------------------- +nodeidx_t bootstrap_methods_get_count() +{ + return netnode(bootstrap_methods_get_node()).altval(0); +} + +//------------------------------------------------------------------------- +void bootstrap_methods_set_count(nodeidx_t cnt) +{ + netnode(bootstrap_methods_get_node()).altset(0, cnt); +} + +//------------------------------------------------------------------------- +bool bootstrap_methods_get_method( + bootstrap_method_def_t *out, + nodeidx_t idx) +{ + netnode n = bootstrap_methods_get_node(); + bytevec_t blob; + if ( n.getblob(&blob, idx, stag) < 2 ) + return false; + const uchar *p = blob.begin(); + out->method_ref = *(ushort *) p; + p += sizeof(ushort); + const size_t nargs = size_t(blob.end() - p) / sizeof(ushort); + out->args.resize(nargs); + if ( nargs > 0 ) + memcpy(out->args.begin(), p, nargs * sizeof(ushort)); + return true; +} + +//------------------------------------------------------------------------- +static bool bootstrap_methods_set_method( + const bootstrap_method_def_t &bmd, + nodeidx_t idx) +{ + netnode n = bootstrap_methods_get_node(); + bytevec_t blob; + blob.append(&bmd.method_ref, sizeof(bmd.method_ref)); + if ( !bmd.args.empty() ) + blob.append(bmd.args.begin(), bmd.args.size() * sizeof(ushort)); + return n.setblob(blob.begin(), blob.size(), idx, stag); +} + +//----------------------------------------------------------------------- +void java_t::database_loaded(const char *file) +{ + int i, v; + ssize_t size; + + if ( file == NULL ) // load old file + { + if ( ConstantNode.create(constant_pool) ) + goto BADIDB; + + i = sizeof(curClass); + v = (int)ConstantNode.altval(CNA_VERSION); + switch ( v ) + { + default: + error("Very old database format. Cannot convert it"); + + case IDP_JDK15: + error("Intermediate (developer) database format. Cannot convert it."); + + case IDP_JDK12: + i -= sizeof(curClass) - offsetof(ClassInfo, MajVers); + // no break + case _CUR_IDP_VER: // IDP_JDK16 + break; + } + + if ( i != (int)ConstantNode.supval(CNS_CLASS, NULL, (size_t)-1) ) + goto BADIDB; + size = ConstantNode.supval(CNS_CLASS, &curClass, sizeof(curClass)); + if ( size < (int32)offsetof(ClassInfo, MajVers) || !curClass.ClassNode ) + goto BADIDB; + if ( curClass.xtrnNode ) + { + if ( !curClass.xtrnCnt ) + goto BADIDB; + XtrnNode = curClass.xtrnNode; + } + else if ( curClass.xtrnCnt ) + { + goto BADIDB; + } + ClassNode = curClass.ClassNode; + + if ( v != IDP_JDK12 ) // current JDK format + { + if ( curClass.MajVers < JDK_MIN_MAJOR ) + goto BADIDB; + if ( curClass.MajVers > JDK_MAX_MAJOR ) + goto BADIDB; + if ( curClass.MajVers == JDK_MIN_MAJOR ) // JDK1.0/1.1 + { + if ( curClass.JDKsubver != (curClass.MinVers >= JDK_1_1_MINOR) ) + goto BADIDB; + } + else + { + if ( curClass.MinVers ) + goto BADIDB; + if ( curClass.MajVers - (JDK_MIN_MAJOR-1) != curClass.JDKsubver ) + goto BADIDB; + } + } + + make_NameChars(/*on_load=*/ false); // initialize and set enableExr_NameChar for upgrade + if ( v != _CUR_IDP_VER ) + { + ResW_init(); // prepare RW-find + v = upgrade_db_format(v, ConstantNode); + if ( v == 0 ) + { +BADIDB: + DESTROYED("database_loaded"); + } + QASSERT(10134, v == _CUR_IDP_VER); + ConstantNode.supset(CNS_CLASS, &curClass, sizeof(curClass)); + ConstantNode.altset(CNA_VERSION, _CUR_IDP_VER); + } + else + { + v = curClass.maxStrSz; + if ( v != 0 ) + tsPtr = (ushort*)myAlloc(sizeof(ushort)*(v+1)); + v = curClass.maxSMsize; + if ( v != 0 ) + smBuf = (uchar*)myAlloc(v+1); + v = curClass.maxAnnSz; + if ( v != 0 ) + annBuf = (uchar*)myAlloc(v+1); + idpflags = (ushort)ConstantNode.altval(CNA_IDPFLAGS); + user_limiter = (uchar)ConstantNode.altval(CNA_LIMITER); + + if ( !ResW_oldbase() ) + goto BADIDB; + } + // disableExt_NameChar(); // set standart extension + if ( curClass.extflg & XFL_C_DONE ) + sm_node = smn_ok; + if ( curClass.MajVers >= JDK_SMF_MAJOR_MIN ) + SMF_mode = 1; + } + else + { // new base + if ( !ConstantNode ) + INTERNAL("ConstantNode"); + + char str[MAXSPECSIZE]; + char *ps = str; + i = qstrlen((char *) file); + if ( i >= sizeof(str) ) + { + ps = (char *) file + i - (sizeof(str) - 3); + for ( i = sizeof(str) - 1 - 3; i; i-- ) + if ( *--ps == '/' ) + break; + if ( i == 0 ) + error("notify: illegal file name parameter"); + file = ps; + memcpy(str, "...", 3); + ps = &str[3]; + } + memcpy(ps, file, i); + if ( ps != str ) + i += 3; + ConstantNode.supset(CNS_SOURCE, str, i); + user_limiter = inf_get_limiter(); + ConstantNode.altset(CNA_LIMITER, user_limiter); + } + inf_set_limiter(0); +} + + +//------------------------------------------------------------------------- +void java_t::dump_floating_constants( + const char *problem, + const char *what, + const intvec_t &ks) +{ + const size_t kss = ks.size(); + if ( kss > 0 ) + { + static const char *const emc = "Number of %s CONSTANT_%s: %" FMT_Z "\n"; + load_msg(emc, problem, what, kss); + for ( size_t i = 0; i < kss; ++i ) + { + qstrvec_t lines; + + const_desc_t cd; + ushort cid = ks[i]; + if ( ConstantNode.supval(cid, &cd, sizeof(cd)) == sizeof(cd) ) + { + print_constant(&lines, cd, cid); + if ( lines.empty() ) + lines.push_back("<failed printing constant>"); + } + else + { + cd.type = 0; + lines.push_back("<failed retrieving constant>"); + } + for ( size_t lidx = 0, lcnt = lines.size(); lidx < lcnt; ++lidx ) + { + char sfxbuf[MAXSTR]; + if ( lcnt > 1 ) + qsnprintf(sfxbuf, sizeof(sfxbuf), ".%" FMT_Z, lidx); + else + sfxbuf[0] = '\0'; + load_msg(" #%" FMT_Z "%s, index=%d, type=%s: %s", + i, sfxbuf, cid, constant_type_to_str(cd.type), + lines[lidx].c_str()); + } + } + } +} + +//----------------------------------------------------------------------- +bool java_t::LoadOpis(load_mode_t load_mode, ushort index, uchar _op, const_desc_t *p) +{ + const uchar op = _op; +#define LoadAnyString(lmod, index) LoadOpis(lmod, index, CONSTANT_Utf8, NULL) + const_desc_t tmp; + if ( p == NULL ) + p = &tmp; + + if ( !index + || index > curClass.maxCPindex + || ConstantNode.supval(index, p, sizeof(*p)) != sizeof(*p) ) + { + return false; + } + + if ( load_mode == lm_lenient || load_mode == lm_no_set_ref ) + return true; + + if ( !p->is_referenced() ) + { + p->mark_referenced(); + StoreOpis(index, *p); + } + CASSERT(MAX_CONSTANT_TYPE < 0x20); + if ( op < 0x20 ) + return op == 0 || op == p->type; + +#define LoadNamedClass(lmod, index, p) LoadOpis(lmod, index, uchar(-1), p) + if ( op == uchar(-1) ) + return p->type == CONSTANT_Class && (p->flag & HAS_CLSNAME); + + if ( p->type != CONSTANT_Utf8 ) + return false; + +#define OP_TYPE_MASK 0x1F +#define OP_CHECK_SHIFT 5 + + const uchar _type = op & OP_TYPE_MASK; + const uchar _check = op >> OP_CHECK_SHIFT; + switch ( _type ) + { + default: + INTERNAL("LoadOpis"); + case 0: + case CONSTANT_Utf8: + break; + } + { + static const uchar chk[8] = + { + 0x00, // align + +#define CheckAnyDscr(lmod, index, p) LoadOpis(lmod, index, (1 << OP_CHECK_SHIFT), p) + (HAS_TYPEDSCR | HAS_CALLDSCR), + +#define CheckFieldDscr(lmod, index, p) LoadOpis(lmod, index, (2 << OP_CHECK_SHIFT), p) +#define LoadFieldDscr(lmod, index, p) LoadOpis(lmod, index, (2 << OP_CHECK_SHIFT) | CONSTANT_Utf8, p) + HAS_TYPEDSCR, + +#define CheckFieldName(lmod, index, p) LoadOpis(lmod, index, (3 << OP_CHECK_SHIFT), p) +#define LoadFieldName(lmod, index) LoadOpis(lmod, index, (3 << OP_CHECK_SHIFT) | CONSTANT_Utf8, NULL) + HAS_FLDNAME, + +//#define Check...(lmod, index, p) LoadOpis(lmod, index, (4 << OP_CHECK_SHIFT), p) + 0x00, + +#define CheckClass(lmod, index, p) LoadOpis(lmod, index, (5 << OP_CHECK_SHIFT), p) + (HAS_TYPEDSCR | HAS_CLSNAME), + +#define CheckCallDscr(lmod, index, p) LoadOpis(lmod, index, (6 << OP_CHECK_SHIFT), p) +#define LoadCallDscr(lmod, index) LoadOpis(lmod, index, (6 << OP_CHECK_SHIFT) | CONSTANT_Utf8, NULL) + HAS_CALLDSCR, + +#define CheckClassName(lmod, index, p) LoadOpis(lmod, index, (7 << OP_CHECK_SHIFT), p) + HAS_CLSNAME + }; + + if ( p->flag & chk[_check] ) + return true; + } + + if ( _type != 0 ) + return false; + + if ( load_mode == lm_need_cr ) + msg("\n"); + load_msg("Illegal reference type to Utf8#%u\n", index); + return lm_need_cr >= 2; // true when load_constants_pool, false after +} + +//----------------------------------------------------------------------- +// for annotation +bool java_t::isSingleClass(ushort val) +{ + const_desc_t co; + + return LoadFieldDscr(lm_normal, val, &co) + && (co._Sflags & (_OP_VALPOS | _OP_ONECLS)) == _OP_ONECLS; +} + +//----------------------------------------------------------------------- +uchar java_t::attribute_type_from_str(ushort index, attr_parent_kind_t apk, char str[MAX_ATTR_NMSZ]) +{ + static const char *const name[] = + { +#define attr_LineNumberTable 0 // 0x000001: code + "LineNumberTable", +#define attr_LocalVariableTable 1 // 0x000002: code + "LocalVariableTable", +#define attr_LocalVariableTypeTable 2 // 0x000004: code + "LocalVariableTypeTable", +#define attr_StackMap 3 // 0x000008: code (J2ME CLDC) + "StackMap", +#define attr_StackMapTable 4 // 0x000010: code (>=JDK1.6) + "StackMapTable", +#define attr_CODE_TOP 5 + +#define attr_ConstantValue 5 // 0x000020: fld + "ConstantValue", +#define attr_FLD_TOP 6 + +#define attr_Code 6 // 0x000040: met + "Code", +#define attr_Exceptions 7 // 0x000080: met + "Exceptions", +#define attr_RuntimeVisibleParameterAnnotations 8 // 0x000100: met + "RuntimeVisibleParameterAnnotations", +#define attr_RuntimeInvisibleParameterAnnotations 9 // 0x000200: met + "RuntimeInvisibleParameterAnnotations", +#define attr_AnnotationDefault 10 // 0x000400: met + "AnnotationDefault", +#define attr_MET_TOP 11 + +#define attr_SourceFile 11 // 0x000800: file + "SourceFile", +#define attr_InnerClasses 12 // 0x001000: file + "InnerClasses", +#define attr_EnclosingMethod 13 // 0x002000: file + "EnclosingMethod", +#define attr_SourceDebugExtension 14 // 0x004000: file + "SourceDebugExtension", +#define attr_BootstrapMethods 15 // 0x008000: file + "BootstrapMethods", +#define attr_FILE_TOP 16 + +#define attr_Signature 16 // 0x010000: all !code + "Signature", +#define attr_Synthetic 17 // 0x020000: all !code + "Synthetic", +#define attr_Deprecated 18 // 0x040000: all !code + "Deprecated", +#define attr_RuntimeVisibleAnnotations 19 // 0x080000: all !code + "RuntimeVisibleAnnotations", +#define attr_RuntimeInvisibleAnnotations 20 // 0x100000: all !code + "RuntimeInvisibleAnnotations", +// next field for check pool ONLY (must be in last position) +#define attr_LocalVariables 21 // 0x200000: obsolete + "LocalVariables" +#define attr_CHECK_MASK 0x3FFFFF + }; +#define attr_UNKNOWN 32 +#define attr_TRUNCATED 33 +#define attr_NONAME 34 +//#if sizeof("RuntimeInvisibleParameterAnnotations") > MAX_ATTR_NMSZ +//#error +//#endif + + str[0] = '\0'; + if ( !LoadFieldName(lm_normal, index) ) + return attr_NONAME; + if ( !fmtName(index, str, MAX_ATTR_NMSZ, fmt_UnqualifiedName) ) + return attr_TRUNCATED; + + uchar i = 0, top = (uchar)(qnumber(name) - 1); + switch ( apk ) + { + case attr_parent_kind_code: + top = attr_CODE_TOP; + break; + case attr_parent_kind_field: + i = attr_CODE_TOP; + top = attr_FLD_TOP; + break; + case attr_parent_kind_method: + i = attr_FLD_TOP; + top = attr_MET_TOP; + break; + case attr_parent_kind_class_file: + i = attr_MET_TOP; + top = attr_FILE_TOP; + break; + default: +// case ARQ_CHECK: + ++top; + break; + } + +repeat: + do + { + if ( !strcmp(name[i], str) ) + return i; + } while ( ++i < top ); + if ( apk != attr_parent_kind_code && i < (uchar)(qnumber(name)-1) ) + { + i = attr_FILE_TOP; + top = (uchar)(qnumber(name) - 1); + goto repeat; + } + return attr_UNKNOWN; +} + +//------------------------------------------------------------------------- +static NORETURN void badref_loader_failure(ushort i, ushort k) +{ + loader_failure("Bad reference (from %u to %u) in constant pool", i, k); +} + +//----------------------------------------------------------------------- +uint java_t::load_constants_pool(void) +{ + ushort k; + uint ui = 0; + const_desc_t cd; + + // prepare jasmin reserved word checking + ResW_init(); + + msg("\nLoading constant pool..."); + FOR_EACH_CONSTANT_POOL_INDEX(i) + { + memset(&cd, 0, sizeof(cd)); + cd.type = read1(); + switch ( cd.type ) + { + case CONSTANT_Long: + case CONSTANT_Double: + cd.value2 = read4(); + // fallthrough + case CONSTANT_Integer: + case CONSTANT_Float: + cd.value = read4(); + break; + + case CONSTANT_NameAndType: + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + case CONSTANT_InterfaceMethodref: + k = read2(); + if ( k == 0 || k > curClass.maxCPindex ) + { +badindex: + loader_failure("Bad record in constant pool.\n" + "Record %u have reference to %u\n" + "(maxnum %u, file offset after the read is 0x%" FMT_64 "X)", + i, k, curClass.maxCPindex, qftell(myFile)); + } + cd._class = k; // _subnam for name & type + // fallthrough. Yes, we will let 'name_and_type_index' be read by the CONSTANT_String block below... + case CONSTANT_Class: + cd.ref_ip = 0; + // fallthrough + case CONSTANT_String: + k = read2(); + if ( k == 0 || k > curClass.maxCPindex ) + goto badindex; + cd._name = k; // _dscr for name & type + break; + + case CONSTANT_Unicode: + loader_failure("File contains CONSTANT_Unicode, which was removed from " + "the standard in 1996, and is not supported by IDA"); + + case CONSTANT_Utf8: + cd._name = (ushort)i; // for xtrnRef_dscr + if ( LoadUtf8((ushort)i, &cd) ) + parse_const_desc((ushort)i, &cd); + break; + + case CONSTANT_MethodHandle: + cd._mhr_kind = read1(); + cd._mhr_index = read2(); + break; + + case CONSTANT_MethodType: + k = read2(); // descriptor_index + if ( k == 0 || k > curClass.maxCPindex ) + goto badindex; + cd._mtd_index = k; + break; + + case CONSTANT_InvokeDynamic: + { + cd._bmidx = read2(); // bootstrap_method_attr_index + k = read2(); // name_and_type_index + if ( k == 0 || k > curClass.maxCPindex ) + goto badindex; + cd._name = k; + } + break; + + default: + loader_failure("Bad constant type 0x%x (%u)", cd.type, i); + } // end switch + StoreOpis(i, cd); + if ( cd.type == CONSTANT_Long || cd.type == CONSTANT_Double ) + { + if ( curClass.maxCPindex == (ushort)i ) + loader_failure("Premature end of constant pool"); + ++i; + } + } // end for + ResW_free(); // free mem - this set not needed later + + msg("checking..."); + FOR_EACH_CONSTANT_POOL_INDEX(i) + { + const_desc_t cr; + ConstantNode.supval(i, &cd, sizeof(cd)); + switch ( cd.type ) + { + case CONSTANT_String: + if ( !LoadAnyString(lm_need_cr, cd._name) ) + badref_loader_failure(i, cd._name); + continue; + + case CONSTANT_Long: + case CONSTANT_Double: + ++i; + default: + continue; + + case CONSTANT_NameAndType: + if ( !CheckFieldName(lm_need_cr, cd._class, &cr) ) + badref_loader_failure(i, cd._class); + cd.flag |= ((cr.flag & HAS_FLDNAME) << SUB_SHIFT); + if ( !CheckAnyDscr(lm_need_cr, cd._name, &cr) ) + badref_loader_failure(i, cd._name); + cd.flag |= ((cr.flag<<SUB_SHIFT) & (SUB_TYPEDSCR | SUB_CALLDSCR)); + break; + + case CONSTANT_Class: + if ( !CheckClass(lm_need_cr, cd._name, &cr) ) + badref_loader_failure(i, cd._name); + cd.flag |= (cr.flag & (HAS_FLDNAME | HAS_TYPEDSCR | HAS_CLSNAME)); + cd._dscr = cd._subnam = 0; + break; + } // end switch + StoreOpis(i, cd); + if ( (loadMode & MLD_EXTREF) + && cd.type == CONSTANT_Class + && (cd.flag & HAS_CLSNAME) ) + { + ushort j; + + for ( j = 1; j <= curClass.xtrnCnt; j++ ) + { + uint32 rfc = (uint32)XtrnNode.altval(j); + if ( !CmpString(cd._name, (ushort)rfc) ) + { + cd._subnam = (ushort)(rfc >> 16); + goto found; + } + } + XtrnNode.altset(j, (i << 16) | cd._name); + ++curClass.xtrnCnt; + cd._subnam = (ushort)i; +found: + StoreOpis(i, cd); + } + } // end for + if ( loadMode & MLD_EXTREF ) + XtrnNode.altdel(); // delete all + + msg("referencing..."); + FOR_EACH_CONSTANT_POOL_INDEX(i) + { + const_desc_t cr; + uint32 sav; + + ConstantNode.supval(i, &cd, sizeof(cd)); + switch ( cd.type ) + { + case CONSTANT_Long: + case CONSTANT_Double: + ++i; + default: + continue; + + case CONSTANT_Class: + continue; + + case CONSTANT_InterfaceMethodref: + case CONSTANT_Fieldref: + case CONSTANT_Methodref: + if ( !LoadOpis(lm_need_cr, cd._class, CONSTANT_Class, &cr) ) + badref_loader_failure(i, cd._class); +//\\VALID NULL ??? go twos if any... (reorder cur ind to null) + cd.flag |= (cr.flag & HAS_CLSNAME); + k = cd._name; + sav = errload; + cd.ref_ip = cr._subnam; + CheckClassName(lm_need_cr, cd._name = cr._name, NULL); //lint !e530 likely using an uninitialized value + if ( !LoadOpis(lm_need_cr, k, CONSTANT_NameAndType, &cr) ) + { + badref_loader_failure(i, k); + } + cd._dscr = cr._name; + cd._subnam = cr._class; + cd.flag |=(cr.flag & (SUB_FLDNAME | SUB_TYPEDSCR | SUB_CALLDSCR)); + if ( cd.type != CONSTANT_Fieldref ) + CheckCallDscr(lm_need_cr, cd._dscr, NULL); + else + CheckFieldDscr(lm_need_cr, cd._dscr, NULL); + if ( !LoadFieldName(lm_need_cr, cd._subnam) ) + --sav; + if ( (loadMode & MLD_EXTREF) && errload == sav ) + { + XtrnNode.altset(++ui, i, '0'); + ++curClass.xtrnCnt; + } + else + { + cd.ref_ip = 0; + } + break; + + case CONSTANT_MethodHandle: + if ( !LoadOpis(lm_need_cr, cd._mhr_index, 0, &cr) ) + badref_loader_failure(i, cd._mhr_index); + break; + + case CONSTANT_MethodType: + if ( !LoadOpis(lm_need_cr, cd._mtd_index, CONSTANT_Utf8, &cr) ) + badref_loader_failure(i, cd._mtd_index); + break; + + case CONSTANT_InvokeDynamic: + // We can resolve the name_and_type_index, right away but the + // bootstrap_method_attr_index, will have to wait after the + // BootstrapMethods array has been loaded (in load_attributes()) + if ( !LoadOpis(lm_need_cr, cd._name, CONSTANT_NameAndType, &cr) ) + badref_loader_failure(i, cd._mtd_index); + break; + } // end switch + StoreOpis(i, cd); + } // end for + + msg("complete\n"); + + // { // debug + // intvec_t tmp; + // FOR_EACH_CONSTANT_POOL_INDEX(i) + // tmp.push_back(i); + // dump_floating_constants( + // "NO PROBLEM", + // "NOTHING", + // tmp); + // } + + return ui; +} + +//----------------------------------------------------------------------- +void java_t::setPoolReference(void) +{ + char str[MAXNAMELEN]; + const_desc_t co; + uint ic, ii, ui = 0; + + msg("Sorting external references..."); + for ( uint i = 1; (ushort)i <= curClass.xtrnCnt; i++ ) + { + uint j = (uint)XtrnNode.altval(i, '0'); + if ( j == 0 ) + continue; + show_addr(curClass.xtrnCnt - (ushort)i); + ConstantNode.supval(j, &co, sizeof(co)); + if ( co._class == curClass.This.Dscr ) + { + co.ref_ip = 0; + StoreOpis(j, co); + continue; + } + const_desc_t cr; + ConstantNode.supval(ic = co.ref_ip, &cr, sizeof(cr)); + xtrnSet(ic, &cr, ++ui, str, sizeof(str), true); + xtrnSet(j, &co, ++ui, str, sizeof(str), false); + deltry(ii = i + 1, ic, ui, co); + for ( ; (ushort)ii <= curClass.xtrnCnt; ii++ ) + { + j = (uint)XtrnNode.altval(ii, '0'); + if ( j == 0 ) + continue; + ConstantNode.supval(j, &cr, sizeof(cr)); + if ( cr.ref_ip != (ushort)ic ) + continue; + xtrnSet(j, &cr, ++ui, str, sizeof(str), false); + XtrnNode.altdel(ii, '0'); + deltry(ii + 1, ic, ui, co); + } + } + XtrnNode.altdel_all('0'); + + FOR_EACH_CONSTANT_POOL_INDEX(i) + { + ConstantNode.supval(i, &co, sizeof(co)); + switch ( co.type ) + { + case CONSTANT_Long: + case CONSTANT_Double: + ++i; + default: + break; + case CONSTANT_Class: + if ( co._subnam == (ushort)i + && (ushort)i != curClass.This.Dscr + && !co.ref_ip ) + { + xtrnSet(i, &co, ++ui, str, sizeof(str), true); + } + break; + } + } + + FOR_EACH_CONSTANT_POOL_INDEX(i) + { + ConstantNode.supval(i, &co, sizeof(co)); + switch ( co.type ) + { + case CONSTANT_Long: + case CONSTANT_Double: + ++i; + default: + continue; + case CONSTANT_Class: + break; + } + if ( co._subnam && co._subnam != (ushort)i ) + { + const_desc_t tmp; + ConstantNode.supval(co._subnam, &tmp, sizeof(tmp)); + co.ref_ip = tmp.ref_ip; + StoreOpis(i, co); + } + } + + curClass.xtrnCnt = (ushort)ui; + if ( curClass.xtrnCnt != 0 ) + { + set_segm_end(curClass.xtrnEA, curClass.xtrnEA + curClass.xtrnCnt + 1, SEGMOD_KILL); + create_byte(curClass.xtrnEA, 1); + } + else + { + XtrnNode.kill(); + curClass.xtrnNode = 0; + del_segm(curClass.xtrnEA, SEGMOD_KILL); + curClass.xtrnEA = 0; + } + msg("OK\n"); +} + +//----------------------------------------------------------------------- +void java_t::CheckPoolReference(bool insns_created) +{ + char str[MAX_ATTR_NMSZ]; + const_desc_t co; + intvec_t k1s; + intvec_t k2s; + intvec_t k3s; + uint mask = attr_CHECK_MASK; + + msg("Checking references, %s creating instructions...\n", insns_created ? "after" : "before"); + FOR_EACH_CONSTANT_POOL_INDEX(i) + { + ConstantNode.supval(i, &co, sizeof(co)); + if ( co.type == CONSTANT_Long || co.type == CONSTANT_Double ) + ++i; + if ( co.is_referenced() ) + continue; + switch ( co.type ) + { + case CONSTANT_Utf8: + if ( !insns_created ) + { + uchar j; + + k2s.push_back(i); + CASSERT((1 << (attr_LocalVariables+1)) - 1 == attr_CHECK_MASK); + if ( (co.flag & HAS_FLDNAME) + && mask + && (j = attribute_type_from_str((ushort)i, attr_parent_kind_CHECK, str)) <= attr_LocalVariables + && (mask & (1 << j)) ) + { + mask ^= (1 << j); + } + else if ( co._Ssize ) + { + k3s.push_back(i); // unnotify empty + } + } + break; + + case CONSTANT_NameAndType: + if ( !insns_created ) + k1s.push_back(i); + break; + + case CONSTANT_Class: + if ( insns_created ) + { + k2s.push_back(i); + if ( !(co.flag & HAS_CLSNAME) ) + k3s.push_back(i); + } + break; + + default: + if ( insns_created ) + k1s.push_back(i); + break; + } // switch + } // for + + if ( !k1s.empty() ) + { + dump_floating_constants( + "unused", + insns_created ? "(any except Class/Type/String)" : "NameAndType", + k1s); + } + if ( !k2s.empty() ) + { + if ( !k3s.empty() ) + { + dump_floating_constants( + insns_created ? "unnamed" : "unreferenced", + insns_created ? "Class" : "Utf8", + k3s); + for ( size_t i = 0, n = k3s.size(); i < n; ++i ) + k2s.del(k3s[i]); + } + if ( !k2s.empty() ) + dump_floating_constants("unused", insns_created ? "Class" : "Utf8", k2s); + } +} + +//----------------------------------------------------------------------- +void java_t::ValidateStoreLocVar(ushort slot, LocVar & lv) +{ + netnode temp; + uint32 cnt, id; + bool dble; + LocVar vals[(qmin(MAXSTR, MAXSPECSIZE)/sizeof(LocVar))]; + const char *txt = "Invalid declaration"; + + lv.ScopeTop = (ushort)(id = (uint32)lv.ScopeBeg + lv.ScopeTop); + + if ( slot >= curSeg.DataSize || id > curSeg.CodeSize ) + goto BADDECL; + + dble = false; + if ( curSeg.varNode ) + { + temp = curSeg.varNode; + cnt = (uint32)temp.altval(slot); + if ( cnt != 0 ) + { + if ( (int32)cnt < 0 ) + { + cnt = -(int32)cnt; + dble = true; + } + if ( (cnt % sizeof(LocVar)) + || cnt >= sizeof(vals) + || temp.supval(slot, vals, cnt+1) != cnt ) + { + goto interr; + } + cnt /= sizeof(LocVar); + } + } + else + { + temp.create(); + curSeg.varNode = temp; + cnt = 0; + } + + if ( !lv.utsign ) // base declaration + { + const_desc_t opis; + + CASSERT(offsetof(LocVar, utsign)+sizeof(lv.utsign) == sizeof(LocVar)); + //lint -esym(645, vals) Symbol may not have been initialized + for ( id = 0; id < cnt; id++ ) // skip full duplication + if ( memcmp(&lv, &vals[id], offsetof(LocVar, utsign)) == 0 ) + return; + + if ( !LoadFieldName(lm_normal, lv.var.Name) ) + goto BADDECL; + if ( !LoadFieldDscr(lm_normal, lv.var.Dscr, &opis) ) + goto BADDECL; + + CASSERT(offsetof(const_desc_t, _Sflags) - offsetof(const_desc_t, _Ssize) == 2); + if ( !dble && opis._Sopstr == (1 | (_OP_UTF8_ << 16)) ) + { + uchar tmp[sizeof(ushort)+1]; + if ( ConstantNode.supval((uint32)lv.var.Dscr << 16, tmp, sizeof(tmp), + BLOB_TAG) != sizeof(ushort) ) + goto interr; + switch ( tmp[0] ) + { + case j_double: + case j_long: + dble = true; + if ( slot+1 == curSeg.DataSize ) + goto BADDECL; + default: + break; + } + } + + txt = "Too many variants"; + if ( cnt == qnumber(vals)-1 ) + goto BADDECL; + + if ( !lv.ScopeBeg ) + curSeg.id.extflg |= XFL_M_LABSTART; // special label at entry + if ( lv.ScopeTop == curSeg.CodeSize ) + curSeg.id.extflg |= XFL_M_LABEND; // special label at end + + { + ea_t dea = curSeg.DataBase + slot; + add_dref(dea, curSeg.start_ea + lv.ScopeBeg, dr_I); + add_dref(dea, curSeg.start_ea + lv.ScopeTop, dr_I); + } + xtrnRef_dscr(curSeg.start_ea + lv.ScopeBeg, &opis); + if ( !cnt ) + set_lv_name(lv.var.Name, curSeg.DataBase + slot, + (loadMode & MLD_LOCVAR) ? 3 : 0); // if not rename_on_load ONLY mark + vals[cnt++] = lv; + } + else + { // signature declaration + CASSERT(offsetof(LocVar, var.Dscr)+sizeof(lv.var.Dscr)+sizeof(lv.utsign) == sizeof(LocVar)); + for ( id = 0; id < cnt; id++ ) + if ( memcmp(&lv, &vals[id], offsetof(LocVar, var.Dscr)) == 0 ) + { + if ( !vals[id].utsign ) + { + if ( !CheckSignature(lv.utsign, attr_parent_kind_code) ) + goto BADDECL; + vals[id].utsign = lv.utsign; + goto store; + } + if ( vals[id].utsign == lv.utsign ) + return; + txt = "Different signature"; + goto BADDECL; + } + txt = "Signature without type"; + goto BADDECL; + } +store: + cnt *= sizeof(LocVar); + temp.supset(slot, vals, cnt); + if ( !lv.utsign ) + { + if ( dble ) + cnt = -(int32)cnt; + temp.altset(slot, cnt); + } + return; + +BADDECL: + load_msg("%s LocVar#%u Method#%u (name#%u dsc#%u sgn#%u scope:%u-%u)\n", + txt, slot, curSeg.id.Number, + lv.var.Name, lv.var.Dscr, lv.utsign, lv.ScopeBeg, lv.ScopeTop); + return; + +interr: + INTERNAL("StoreLocVar"); +} + +//----------------------------------------------------------------------- +inline void java_t::BadRefFile(const char *to, ushort id) +{ + BadRef(BADADDR, to, id, attr_parent_kind_class_file); +} + +//----------------------------------------------------------------------- +uchar *java_t::annotation(uchar *p, uint32 *psize) +{ + if ( *psize < 2 ) + { +bad: + return NULL; + } + *psize -= 2; + uint pairs= read2(); + *(ushort *)p = (ushort)pairs; + p += sizeof(ushort); + if ( pairs ) + { + do + { + if ( *psize < 2 ) + goto bad; + *psize -= 2; + ushort id = read2(); + if ( !LoadFieldName(lm_normal, id) ) + goto bad; + *(ushort *)p = id; + p = annot_elm(p+sizeof(ushort), psize); + if ( p == NULL ) + goto bad; + } + while ( --pairs ); + } + return p; +} + +//--------------------------------------------------------------------------- +uchar *java_t::annot_elm(uchar *ptr, uint32 *psize, uchar is_array) +{ + if ( *psize < 1+2 ) + { +bad: + return NULL; + } + *psize -= 1+2; + union + { + uchar *p1; + ushort *p2; + }; + p1 = ptr; + uchar tag = read1(); + ushort val = read2(); + *p1++ = tag; + *p2++ = val; + switch ( tag ) + { + case j_annotation: + if ( isSingleClass(val) + && (p1 = annotation(p1, psize)) != NULL ) + { + goto done; + } + default: + goto bad; + + case j_array: + if ( val && !is_array ) // multidimensional array is not valid (javac ) + { + uchar *ps = p1; + tag = 0; + do + { + p1 = annot_elm(p1, psize, 1); + if ( p1 == NULL ) + goto bad; + if ( !tag ) + { + if ( val == 1 ) + break; + tag = *ps; + ps = p1; + } + else if ( tag != (uchar)-1 ) + { + if ( tag != *ps ) + goto bad; + tag = (uchar)-1; + } + } + while ( --val ); + goto done; + } + goto bad; + + case j_enumconst: + if ( LoadFieldDscr(lm_normal, val, NULL) ) + { + if ( *psize < 2 ) + goto bad; + *psize -= 2; + *p2++ = val = read2(); + if ( LoadFieldName(lm_normal, val) ) + goto done; + } + goto bad; + + case j_class_ret: + if ( isSingleClass(val) ) + goto done; + goto bad; //### in 'classfile.pdf' j_void_ret also remebemered? + + case j_string: + tag = CONSTANT_Utf8; + break; + case j_float: + tag = CONSTANT_Float; + break; + case j_long: + tag = CONSTANT_Long; + break; + case j_double: + tag = CONSTANT_Double; + break; + case j_int: + case j_byte: + case j_char: + case j_short: + case j_bool: + tag = CONSTANT_Integer; + break; + } + if ( !LoadOpis(lm_normal, val, tag, NULL) ) + goto bad; +done: + return p1; +} + +//----------------------------------------------------------------------- +bool java_t::sm_chkargs(uchar **pptr, uint32 *pDopSize, ushort cnt) +{ + union + { + uchar *p1; + ushort *p2; + }; + p1 = *pptr; + uint32 dopsize = *pDopSize; + bool result = false; + + do + { + if ( !dopsize ) + goto declerr_w; + --dopsize; + uchar tag = read1(); + if ( tag > ITEM_Uninitialized ) + goto declerr_w; + *p1++ = tag; + CASSERT(ITEM_Object+1 == ITEM_Uninitialized); + if ( tag >= ITEM_Object ) + { + if ( dopsize < 2 ) + goto declerr_w; + dopsize -= 2; + ushort var = read2(); + if ( tag == ITEM_Object ) + { + const_desc_t opis; + if ( var == curClass.This.Dscr ) + { + var = curClass.This.Name; + p1[-1] = ITEM_CURCLASS; + } + else if ( LoadNamedClass(lm_normal, var, &opis) ) + { + var = opis._name; + } + else + { + p1[-1] = ITEM_BADOBJECT; + } + } + else + { // Uninitialized (offset to new instruction) + if ( !var ) + curSeg.id.extflg |= XFL_M_LABSTART; // PARANOYA + else if ( var >= curSeg.CodeSize ) + goto declerr_w; + } + *p2++ = var; + } + } + while ( --cnt ); + result = true; + *pptr = p1; +declerr_w: + *pDopSize = dopsize; + return result; +} + +//----------------------------------------------------------------------- +int java_t::sm_load(ushort declcnt, uint32 *pDopSize) +{ + union + { + uchar *p1; + ushort *p2; + }; + sm_info_t smr; + uint32 dopsize = *pDopSize; + netnode temp(curSeg.smNode); + int result = 0; + uint prevoff = (uint)-1; + + p1 = sm_realloc(dopsize); + dopsize -= 2; // skip READED counter + *p2++ = declcnt; // counter + smr.noff = (uint32)(p1 - smBuf); + smr.fcnt = 0; + do + { + ea_t refea; + uint nxcnt; + uchar rectype = SMT_FULL_FRAME; + if ( SMF_mode ) // >=JDK6 + { + if ( !dopsize ) + goto declerr_w; + --dopsize; + rectype = read1(); + *p1++ = rectype; + } + { + uint off; + if ( rectype < SMT_SAME_FRM_S1 ) + { + if ( rectype > SMT_SAME_FRM_S1_max ) + goto declerr_w; // reserved + off = rectype; + if ( rectype >= SMT_SAME_FRM_S1_min ) + off -= SMT_SAME_FRM_S1_min; + } + else + { + if ( dopsize < 2 ) + goto declerr_w; + dopsize -= 2; + off = read2(); + *p2++ = (ushort)off; + } + if ( SMF_mode ) + off += (prevoff + 1); // >=JDK6 + if ( (uint32)off >= curSeg.CodeSize ) + goto declerr_w; + prevoff = off; + refea = curSeg.start_ea + off; + } + if ( temp.supval(refea, NULL, 0) != -1 ) // for CLDC only + { + --result; + goto declerr_w; + } + nxcnt = smr.fcnt; + if ( rectype == SMT_FULL_FRAME ) + { + for ( int pass = 0; pass < 2; pass++ ) + { + ushort cnt; + + if ( dopsize < 2 ) + goto declerr_w; + dopsize -= 2; + *p2++ = cnt = read2(); // number of locals / number of stacks + if ( !pass ) + nxcnt = cnt; + if ( cnt && !sm_chkargs(&p1, &dopsize, cnt) ) + goto declerr_w; + } + } + else if ( rectype > SMT_SAME_FRM_S0 ) + { + rectype -= SMT_SAME_FRM_S0; + if ( !sm_chkargs(&p1, &dopsize, rectype) ) + goto declerr_w; + nxcnt += rectype; + } + else if ( rectype >= SMT_SAME_FRM_S1 ) + { + rectype = (uchar)SMT_SAME_FRM_S0 - rectype; + nxcnt -= rectype; + if ( int(nxcnt) < 0 ) + goto declerr_w; + if ( rectype == 4 /*i.e., was: SMT_SAME_FRM_S1 */ ) + { + // same_locals_1_stack_item_frame_extended + // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.4 + if ( !sm_chkargs(&p1, &dopsize, 1) ) + goto declerr_w; + } + } + else if ( rectype >= SMT_SAME_FRM_S1_min ) + { + if ( !sm_chkargs(&p1, &dopsize, 1) ) + goto declerr_w; + } + smr.eoff = (uint32)(p1 - smBuf); + temp.supset(refea, &smr, sizeof(smr)); + smr.noff = smr.eoff; + smr.fcnt = nxcnt; + } + while ( --declcnt ); +// + temp.altset(-1, smr.noff); + temp.setblob(smBuf, smr.noff, 0, BLOB_TAG); + ++result; +declerr_w: + *pDopSize = dopsize; + return result; +} + +//------------------------------------------------------------------------- +NORETURN void java_t::loader_failure_bad_attr_decl_size(attr_parent_kind_t apk) const +{ + char diastr[128]; + loader_failure("Illegal declaration size%s", mk_diag(apk, diastr)); +} + +//----------------------------------------------------------------------- +void java_t::load_attributes(attr_parent_kind_t apk) +{ + char atrs[MAX_ATTR_NMSZ+2], diastr[128]; + // ushort k; + uint i, j, r; + netnode temp; + uval_t *pann; + uchar eflg, lvtb = 0, lntb = 0, fatal = (loadMode & MLD_FORCE) == 0; + const_desc_t opis; + opis._name = 0; // for vc + + j = read2(); + for ( i = 0; i < j; i++ ) + { + if ( savesize >= 0 && (savesize -= 6) < 0 ) + loader_failure_bad_attr_decl_size(apk); + const ushort attribute_name_index = read2(); + uint attribute_length = read4(); + if ( savesize >= 0 ) + { + if ( (uint)savesize < attribute_length ) + loader_failure_bad_attr_decl_size(apk); + savesize -= attribute_length; + } + eflg = 0; // flag(additional attributes/locvars/annotation/stackmap) + atrs[0] = ' '; // for additinal attibutes (mark SourceDebugExtension) + switch ( attribute_type_from_str(attribute_name_index, apk, &atrs[1]) ) + { + case attr_SourceDebugExtension: + if ( sde ) + goto duplerr_w; + ++sde; + if ( attribute_length < 0x10000 ) + { + if ( attribute_length == 0 ) + { + deb(IDA_DEBUG_LDR, + "Ignore zero length SourceDebugExtension attribute\n"); + break; + } + qoff64_t pos = qftell(myFile), ssz = FileSize; + if ( LoadUtf8((ushort)-1, (const_desc_t*)(size_t)attribute_length) ) + { + curClass.extflg |= XFL_C_DEBEXT; + break; + } + qfseek(myFile, pos, SEEK_SET); + FileSize = ssz; + } + if ( ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "SourceDebugExtension attribute have a non standard encoding\n" + "or large size and cannot be represented in assembler.\n\n" + "\3Do you want to store it in external file?") > ASKBTN_NO ) + goto attr2file; + goto skipAttr; + + case attr_BootstrapMethods: + { + if ( bootstrap_methods_get_node(/*assert=*/ false) != BADNODE ) + loader_failure("Duplicate 'BootstrapMethods' attribute definition"); + bootstrap_methods_get_node(/*assert=*/ true, /*can_create=*/ true); + if ( attribute_length < 2 ) + goto declerr_w; + const ushort num_bootstrap_methods = read2(); + bootstrap_methods_set_count(num_bootstrap_methods); + attribute_length -= 2; + const qoff64_t end = qftell(myFile) + attribute_length; + for ( ushort bmidx = 0; bmidx < num_bootstrap_methods; ++bmidx ) + { + if ( qftell(myFile) >= end ) + goto declerr_w; + const ushort bootstrap_method_ref = read2(); + + if ( qftell(myFile) >= end ) + goto declerr_w; + const ushort num_bootstrap_arguments = read2(); + + bootstrap_method_def_t mdef; + mdef.method_ref = bootstrap_method_ref; + for ( ushort baidx = 0; baidx < num_bootstrap_arguments; ++baidx ) + { + if ( qftell(myFile) >= end ) + goto declerr_w; + const ushort bootstrap_argument = read2(); + mdef.args.push_back(bootstrap_argument); + } + + bootstrap_methods_set_method(mdef, bmidx); + } + + // Now that all bootstrap methods are loaded, try and resolve + // the constant pool's references to it + FOR_EACH_CONSTANT_POOL_INDEX(cpidx) + { + const_desc_t cd; + cd.type = 0; + ConstantNode.supval(cpidx, &cd, sizeof(cd)); + if ( cd.type == CONSTANT_InvokeDynamic ) + { + bootstrap_method_def_t mdef; + if ( bootstrap_methods_get_method(&mdef, cd._bmidx) ) + LoadOpis(lm_normal, mdef.method_ref, CONSTANT_MethodHandle, NULL); + } + } + } + break; + + case attr_UNKNOWN: + atrs[0] = uchar(apk); + if ( loadMode & MLD_EXTATR ) + { +attr2file: + const char *p = CopyAttrToFile(atrs, attribute_length, attribute_name_index); + if ( p == NULL ) + break; + loader_failure("%s %sattribute '%s'%s", + p, + atrs[0] == ' ' ? "" : "additional ", + &atrs[1], + mk_diag(apk, diastr)); + } + if ( idpflags & IDM_REQUNK ) + { + idpflags &= ~IDM_REQUNK; + if ( ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "File contains unknown attribute(s).\n" + "Do you want store it in external files?\n\n") > ASKBTN_NO ) + { + loadMode |= MLD_EXTATR; + goto attr2file; + } + } + eflg = 1; + goto unkAttr; + case attr_NONAME: + qsnprintf(atrs, sizeof(atrs), "(with index %u)", attribute_name_index); + goto notify; + case attr_TRUNCATED: + qstrncat(atrs, "...", sizeof(atrs)); +unkAttr: + atrs[0] = '"'; + qstrncat(atrs, "\"", sizeof(atrs)); +notify: +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4191) +#endif + if ( eflg && !(idpflags & IDM_WARNUNK) ) + msg( + "Ignore%s %s attribute (size %u)%s\n", + (uchar)atrs[0] == ' ' ? "" : " unknown", + atrs, attribute_length, mk_diag(apk, diastr)); + else + load_msg( + "Ignore%s %s attribute (size %u)%s\n", + (uchar)atrs[0] == ' ' ? "" : " unknown", + atrs, attribute_length, mk_diag(apk, diastr)); +#ifdef _MSC_VER +#pragma warning(pop) +#endif +skipAttr: + if ( attribute_length ) + { +real_skipAttr: + skipData(attribute_length); + } + break; + + case attr_ConstantValue: + { + ushort constantvalue_index; + if ( attribute_length != 2 || !LoadOpis(lm_normal, constantvalue_index = read2(), 0, &opis) ) + { + declerr: + ++fatal; + declerr_w: + load_msg("Illegal declaration of %s%s\n", + &atrs[1], mk_diag(apk, diastr)); + goto skipAttr; + } + + temp = curField.valNode; + if ( !temp ) + { + temp.create(); + curField.valNode = temp; + r = 0; + } + else + { + r = (uint)temp.altval(0); + } + switch ( opis.type ) + { + case CONSTANT_Integer: + case CONSTANT_Long: + case CONSTANT_Float: + case CONSTANT_Double: + case CONSTANT_String: + temp.supset(++r, &opis, sizeof(opis)); + break; + default: + BadRef(curClass.start_ea + curField.id.Number, "value", constantvalue_index, apk); + temp.altset(++r, (((uint32) constantvalue_index) << 16) | 0xFFFF); + break; + } + temp.altset(0, r); + } + break; + + case attr_Code: + if ( curSeg.CodeSize ) + { +// duplerr: + ++fatal; +duplerr_w: + if ( fatal ) + loader_failure("Duplicate %s attribute declaration%s", &atrs[1], mk_diag(apk, diastr)); + else + load_msg("Duplicate %s attribute declaration%s", &atrs[1], mk_diag(apk, diastr)); + goto skipAttr; + } + r = curClass.JDKsubver ? 12 : 8; + if ( attribute_length < r ) + goto declerr; + attribute_length -= r; + r -= 8; + curSeg.stacks = r ? read2() : read1(); + curSeg.DataSize = r ? read2() : read1(); // max_locals + curSeg.CodeSize = r ? read4() : read2(); + if ( curSeg.CodeSize != 0 ) + { + if ( attribute_length < curSeg.CodeSize ) + goto declerr; + attribute_length -= curSeg.CodeSize; + if ( FileSize < curSeg.CodeSize ) + errtrunc(); + FileSize -= curSeg.CodeSize; + { + segment_t *S = _add_seg(-1); // expand size + if ( curSeg.DataSize ) + set_default_sreg_value(S, rVds, _add_seg(2)->sel); // create data segment + } + } + + { + const ushort exception_table_length = read2(); + if ( exception_table_length != 0 ) // except. table + { + if ( !curSeg.CodeSize ) + goto declerr; + + r = ((uint32) exception_table_length) * (2*4); + if ( attribute_length < r ) + goto declerr; + attribute_length -= r; + temp.create(); + curSeg.excNode = temp; + temp.altset(0, exception_table_length); + ea_t ea = curSeg.start_ea + curSeg.CodeSize; + r = 1; + uchar err = 0; + do + { + Exception exc; + + exc.start_pc = read2(); + exc.end_pc = read2(); + exc.handler_pc = read2(); + + exc.filter.Ref &= 0; // for 'finally' + exc.filter.Dscr = read2(); + if ( exc.filter.Dscr != 0 ) + { + if ( !LoadNamedClass(lm_normal, exc.filter.Dscr, &opis) ) + { + BadRef(ea, ".catch", exc.filter.Dscr, apk); + } + else + { + exc.filter.Name = opis._name; + xtrnRef(ea, opis); + } + } + temp.supset(r++, &exc, sizeof(exc)); + err |= set_exception_xref(&curSeg, exc, ea); // as procedure for base converter + } + while ( (ushort)r <= exception_table_length ); + if ( err ) + { + remember_problem(PR_ILLADDR, ea); + load_msg("Invalid address(es) in .catch%s\n", + mk_diag(apk, diastr)); + } + } + }// exception table + + savesize = attribute_length; + load_attributes(attr_parent_kind_code); // Additional attr + savesize = -1; + break; + + case attr_Exceptions: + if ( curSeg.thrNode ) + goto duplerr_w; + if ( attribute_length < (2+2) || (attribute_length % 2) ) + goto declerr_w; + attribute_length -= 2; + if ( (attribute_length / 2) != (uint32)read2() ) + goto declerr_w; + attribute_length /= 2; + temp.create(); + curSeg.thrNode = temp; + r = 0; + do + { + const ushort exception_index = read2(); + if ( exception_index == 0 ) + { + load_msg("Ignore zero exception index%s\n", mk_diag(apk, diastr)); + } + else + { + uint32 refd = (uint32)exception_index << 16; + if ( !LoadNamedClass(lm_normal, exception_index, &opis) ) + { + BadRef(curSeg.start_ea, ".throws", exception_index, apk); + } + else + { + refd |= opis._name; + xtrnRef(curSeg.start_ea, opis); + } + temp.altset(++r, refd); + } + } + while ( --attribute_length ); + temp.altset(0, r); + break; + + case attr_LineNumberTable: + if ( lntb ) + goto duplerr_w; + ++lntb; + r = attribute_length - 2; + if ( attribute_length < 2 || (r % 4) ) + goto declerr_w; + attribute_length -= 2; + if ( (r /= 4) != (uint32)read2() ) + goto declerr_w; + if ( attribute_length == 0 ) + { +// Symantec error (strip) #1 + deb(IDA_DEBUG_LDR, + "Stripped declaration of LineNumber table%s\n", + mk_diag(apk, diastr)); + } + while ( r-- ) + { + const ushort start_pc = read2(); + const ushort line_number = read2(); + if ( uint32(start_pc) < curSeg.CodeSize ) + set_source_linnum(curSeg.start_ea + start_pc, line_number); + else + load_msg("Illegal address (%u) of source line %u%s\n", start_pc, + line_number, mk_diag(apk, diastr)); + } + break; + + case attr_LocalVariableTypeTable: + if ( !(lvtb & 1) ) // ATT: my be can before LocalVariableTable? + { + if ( fatal ) + loader_failure("%s before LocalVariableTable%s", atrs, mk_diag(apk, diastr)); + else + load_msg("%s before LocalVariableTable%s", atrs, mk_diag(apk, diastr)); + goto skipAttr; + } + ++eflg; // 2 <= 1 + 1 + // no break + case attr_LocalVariableTable: + ++eflg; // 1 + if ( lvtb & eflg ) + goto duplerr_w; + lvtb |= eflg; + --eflg; // unification (0/1) + r = attribute_length - 2; + if ( attribute_length < 2 || (r % 10) ) + goto declerr_w; + attribute_length -= 2; + if ( (r /= 10) != (uint32)read2() ) + goto declerr_w; + while ( r-- ) + { + LocVar lv; + + lv.ScopeBeg = read2(); // start_pc + lv.ScopeTop = read2(); // length + lv.var.Name = read2(); // name_index + CASSERT(offsetof(LocVar,utsign) == offsetof(LocVar,var.Dscr)+sizeof(lv.var.Dscr) + && sizeof(lv.var.Dscr)*2 == sizeof(uint32)); + *(uint32 *)&lv.var.Dscr &= 0; + if ( eflg == 0 ) // LocalVariableTable/LocalVariableTypeTable + lv.var.Dscr = read2(); // descriptor_index + else + lv.utsign = read2(); // descriptor_index + const ushort index = read2(); // index + if ( !eflg ) // normal table + { + if ( index == 0 && !lv.var.Name && !lv.ScopeBeg && lv.ScopeTop <= 1 ) + { +// Symantec error (strip) #2 + deb(IDA_DEBUG_LDR, + "Stripped declaration of local variables%s\n", + mk_diag(apk, diastr)); + continue; + } + if ( (short)lv.ScopeBeg == -1 ) + { +// Microsoft VisualJ++ error (purge?) + LoadAnyString(lm_normal, lv.var.Name); + LoadAnyString(lm_normal, lv.var.Dscr); + deb(IDA_DEBUG_LDR, + "Purged declaration of LocVar#%u%s\n", index, + mk_diag(apk, diastr)); + continue; + } + } + ValidateStoreLocVar(index, lv); + } // while + break; + + case attr_SourceFile: + { + if ( attribute_length != 2 ) + goto declerr_w; + const ushort sourcefile_index = read2(); + if ( LoadAnyString(lm_normal, sourcefile_index) ) + curClass.SourceName = sourcefile_index; + else + BadRef(BADADDR, "source file name", sourcefile_index, apk); + } + break; + + case attr_InnerClasses: + r = attribute_length - 2; + if ( attribute_length < 2 || (r % 8) ) + goto declerr_w; + attribute_length -= 2; + if ( (r /= 8) != (uint32)read2() ) + goto declerr_w; + if ( !r ) + { + deb(IDA_DEBUG_LDR, "Stripped declaration of InnerClasses\n"); + break; + } + attribute_length = r; + { + ushort flags = 0; + while ( attribute_length-- ) + { + InnerClass ic; + + *(uchar *)&flags = 0; + ic.inner = read2(); // inner_class_info_index + if ( ic.inner && !LoadNamedClass(lm_normal, ic.inner, &opis) ) + flags |= 0x101; + else + ic.inner = opis._name; + ic.outer = read2(); // outer_class_info_index + if ( ic.outer && !LoadNamedClass(lm_normal, ic.outer, &opis) ) + flags |= 0x101; + else + ic.outer = opis._name; + ic.name = read2(); // inner_class_name_index + if ( ic.name && !LoadFieldName(lm_normal, ic.name) ) + flags |= 0x101; + ic.access = read2(); // inner_class_access_flags + r = ic.access & ACC_ACCESS_MASK; + if ( r & (r-1) ) + flags |= 0x101; + if ( uchar(flags) == 0 ) + { + temp = curClass.innerNode; + if ( !temp ) + { + temp.create(); + curClass.innerNode = temp; + r = 0; + } + else + { + r = (uint)temp.altval(0); + } + temp.supset(++r, &ic, sizeof(ic)); + temp.altset(0, r); + } + } + if ( flags != 0 ) + load_msg("Error declaration(s) in Inner Classes\n"); + } + break; + + case attr_EnclosingMethod: + if ( curClass.encClass ) + goto duplerr_w; + if ( attribute_length != 4 ) + goto declerr_w; + curClass.encClass = LoadNamedClass(lm_normal, read2(), &opis) + ? opis._name + : 0xFFFF; + { + const ushort method_index = read2(); + if ( curClass.encClass == 0xFFFF ) + { +bad_encl: + msg("Invalid EnclosingMethod description\n"); + } + else if ( method_index != 0 ) + { + if ( !LoadOpis(lm_normal, method_index, CONSTANT_NameAndType, &opis) + || !(opis.flag & SUB_FLDNAME) + || !LoadCallDscr(lm_normal, opis._name) ) + { + goto bad_encl; + } + curClass.encMethod = method_index; + } + } + break; + + case attr_Synthetic: + if ( attribute_length != 0 ) + goto declerr_w; + switch ( apk ) + { + default: // attr_parent_kind_code + goto declerr_w; // paranoya + case attr_parent_kind_field: + curField.id.access |= ACC_SYNTHETIC; + break; + case attr_parent_kind_method: + curSeg.id.access |= ACC_SYNTHETIC; + break; + case attr_parent_kind_class_file: + curClass.AccessFlag |= ACC_SYNTHETIC; + break; + } + break; + + case attr_Deprecated: + if ( attribute_length != 0 ) + goto declerr_w; + switch ( apk ) + { + default: // attr_parent_kind_code + goto declerr_w; // paranoya + case attr_parent_kind_field: + curField.id.extflg |= XFL_DEPRECATED; + break; + case attr_parent_kind_method: + curSeg.id.extflg |= XFL_DEPRECATED; + break; + case attr_parent_kind_class_file: + curClass.extflg |= XFL_DEPRECATED; + break; + } + break; + + case attr_Signature: + if ( attribute_length != 2 || apk == attr_parent_kind_code ) + goto declerr_w; + { + const ushort signature_index = read2(); + if ( CheckSignature(signature_index, apk) ) + { + switch ( apk ) + { + case attr_parent_kind_field: + curField.id.utsign = signature_index; + break; + case attr_parent_kind_method: + curSeg.id.utsign = signature_index; + break; + case attr_parent_kind_class_file: + curClass.utsign = signature_index; + break; + default: break; + } + } + } + break; + + case attr_StackMapTable: + ++eflg; + // fallthrough + case attr_StackMap: + if ( !eflg != (curClass.JDKsubver < 6) ) + { + if ( fatal ) + loader_failure("JDK1.%u incompatible with attribute%s%s", curClass.JDKsubver, atrs, mk_diag(apk, diastr)); + else + load_msg("JDK1.%u incompatible with attribute%s%s", curClass.JDKsubver, atrs, mk_diag(apk, diastr)); + goto skipAttr; + } + if ( curSeg.smNode ) + goto duplerr_w; + if ( attribute_length < 2 ) + goto declerr_w; + { + const ushort number_of_entries = read2(); + if ( number_of_entries == 0 ) + { + attribute_length -= 2; + curSeg.smNode = BADNODE; + deb(IDA_DEBUG_LDR, + "Empty%s attribute%s\n", atrs, mk_diag(apk, diastr)); + curSeg.id.extflg |= XFL_M_EMPTYSM; + } + else + { + temp.create(); + curSeg.smNode = temp; + r = sm_load(number_of_entries, &attribute_length); + if ( int(r) <= 0 ) + { + temp.kill(); + curSeg.smNode = BADNODE; + if ( !r ) + goto declerr_w; + if ( fatal ) + loader_failure("Inconsistent declaration of %s%s", &atrs[1], mk_diag(apk, diastr)); + else + load_msg("Inconsistent declaration of %s%s", &atrs[1], mk_diag(apk, diastr)); + goto skipAttr; //-V779 Unreachable code detected + } + } + } +skip_excess: + if ( attribute_length ) + { + deb(IDA_DEBUG_LDR, + "Excess %u bytes in%s attribute%s\n", attribute_length, atrs, + mk_diag(apk, diastr)); + goto real_skipAttr; + } + break; + + case attr_AnnotationDefault: + pann = &curSeg.annNodes[2]; + eflg = 4; // as flag + goto do_annot1; + case attr_RuntimeInvisibleParameterAnnotations: + ++eflg; + // no break + case attr_RuntimeVisibleParameterAnnotations: + pann = &curSeg.annNodes[3]; + eflg |= 2; // flag of secondary loop +do_annot1: + if ( apk != attr_parent_kind_method ) + goto declerr_w; // paranoya + goto do_annot; + case attr_RuntimeInvisibleAnnotations: + ++eflg; + // no break + case attr_RuntimeVisibleAnnotations: + switch ( apk ) + { + default: // attr_parent_kind_code + goto declerr_w; // paranoya + case attr_parent_kind_class_file: + pann = curClass.annNodes; + break; + case attr_parent_kind_field: + pann = curField.annNodes; + break; + case attr_parent_kind_method: + pann = curSeg.annNodes; + break; + } +do_annot: + if ( eflg & 1 ) + ++pann; // invisible + if ( *pann ) + goto duplerr_w; + temp.create(); + *pann = temp; + if ( attribute_length == 0 ) + goto declerr_w; + { + uchar *p = annotation_realloc(attribute_length); + r = 1; // no paramsloop + if ( eflg & 2 ) // Parameters + { + r = read1(); + *p++ = (uchar)r; + --attribute_length; + if ( !r ) + goto annot_err; + } + if ( eflg & 4 ) // defalut + { + p = annot_elm(p, &attribute_length); + if ( p != NULL ) + goto annot_done; +annot_err: + temp.kill(); + *pann = (uval_t)-1; // as flag for duplicates + goto declerr_w; + } + do // loop for Parameters + { + if ( attribute_length < 2 ) + goto annot_err; + uint cnt = read2(); + attribute_length -= 2; + *(ushort *)p = (ushort)cnt; + p += sizeof(ushort); + if ( !cnt ) + { + if ( !(eflg & 2) ) + goto annot_err; // no parameters + continue; + } + eflg |= 8; // flag for parameters + do + { + if ( attribute_length < 2 ) + goto annot_err; + attribute_length -= 2; + ushort id = read2(); + if ( !isSingleClass(id) ) + goto annot_err; + *(ushort*)p = id; + p = annotation(p + sizeof(ushort), &attribute_length); + if ( p == NULL ) + goto annot_err; + } + while ( --cnt ); + } + while ( --r ); // parameters loop + if ( eflg == 2 ) + goto annot_err; // empty Parameters annotation +annot_done: + r = (uint)(p - annBuf); + } // local variable block + temp.setblob(annBuf, r, 0, BLOB_TAG); + temp.altset(0, r); + goto skip_excess; + + default: + INTERNAL("load_attributes"); + } // switch + } // for +} + +//----------------------------------------------------------------------- +uchar java_t::CheckSignature(ushort index, attr_parent_kind_t apk) +{ + char diastr[128]; + const_desc_t opis; + + if ( !LoadOpis(lm_normal, index, CONSTANT_Utf8, &opis) ) + { +bad: + if ( apk != attr_parent_kind_code ) // not debug variable + load_msg("Invalid signature (#%u)%s\n", index, mk_diag(apk, diastr)); + return 0; + } + + CASSERT(HAS_TYPEDSCR < 0x100 && HAS_CALLDSCR < 0x100); //-V590 expression is excessive + if ( !((uchar)opis.flag & ((apk == attr_parent_kind_method ) ? HAS_CALLDSCR : HAS_TYPEDSCR)) ) + { + if ( !opis._Ssize ) + goto bad; // PARANOYA + if ( opis._Sflags & (_OP_EXTSYM_ | _OP_NOSIGN) ) + goto bad; + opis._Sflags &= (_OP_VALPOS | _OP_METSIGN | _OP_CLSSIGN); + switch ( apk ) + { + case attr_parent_kind_method: + if ( (opis._Sflags &= ~_OP_METSIGN) != _OP_VALPOS ) + goto bad; + break; + case attr_parent_kind_class_file: + opis._Sflags &= ~_OP_CLSSIGN; + // no break + default: // FIELD & .var + if ( opis._Sflags ) + goto bad; + break; + } + } + return 1; +} + +//----------------------------------------------------------------------- +// +// This function should read the input file (it is opened in binary mode) +// analyze it and: +// - loading segment and offset are in inf.BaseAddr & +// - load it into the database using file2base(),mem2base() +// or allocate addresses by enable_flags() and fill them +// with values using putByte(), putWord(), putLong() +// - (if createsegs) create segments using +// add_segm(segment_t *,const char *name,const char *sclass,int flags) +// or +// add_segm(uint short,ea_t,ea_t,char *,char *) +// see segment.hpp for explanations +// - set up inf_get_start_ip(),startCS to the starting address +// - set up inf_get_min_ea(),inf_get_max_ea() +// +// +void java_t::loader(FILE *fp, bool manual) +{ + ushort j; + const_desc_t opis; + + memset(&curClass, 0, sizeof(curClass)); + qfseek(fp, 0, SEEK_SET); // rewind + FileSize = qfsize(fp); + myFile = fp; + enableExt_NameChar(); + + if ( read4() != MAGICNUMBER ) + error("Illegal magic number"); + + curClass.MinVers = read2(); + curClass.MajVers = read2(); + + if ( curClass.MajVers <= JDK_MIN_MAJOR ) + { + if ( curClass.MajVers < JDK_MIN_MAJOR ) + goto BAD_VERSION; + curClass.JDKsubver = (uchar)(curClass.MinVers >= JDK_1_1_MINOR); + } + else if ( curClass.MajVers > JDK_MAX_MAJOR || curClass.MinVers ) + { +BAD_VERSION: + loader_failure("Unsupported file format (version %u.%u)", + curClass.MajVers, curClass.MinVers); + } + else + { + curClass.JDKsubver = (uchar)(curClass.MajVers - (JDK_MIN_MAJOR-1)); + } + + if ( curClass.MajVers >= JDK_SMF_MAJOR_MIN ) + { + SMF_mode = 1; + } + else if ( curClass.JDKsubver <= 1 ) + { + switch ( curClass.MinVers ) + { + default: + ask_for_feedback( + "Class file with version %u.%u (JDK1.%u?) is not tested!", + curClass.MajVers, curClass.MinVers, curClass.JDKsubver); + // no break + case JDK_1_02_MINOR: + case JDK_1_1_MINOR: + break; + } + } +//-- + curClass.maxCPindex = read2(); + if ( curClass.maxCPindex <= 2 ) + loader_failure("Empty constant pool"); + loadMode = loadDialog(manual); + ConstantNode.create(constant_pool); + --curClass.maxCPindex; // last valid number + XtrnNode.create(); + make_NameChars(/*on_load=*/ true); // initialize and set 'load extension' + const uint nconstants = load_constants_pool(); + if ( !_add_seg(0) ) + { + XtrnNode.kill(); + } + else + { + curClass.xtrnCnt = ushort(nconstants); + curClass.xtrnNode = XtrnNode; + } +//-- + curClass.AccessFlag = read2(); + if ( curClass.AccessFlag & ~ACC_THIS_MASK ) + load_msg("Illegal class access bits (0x%X)\n", curClass.AccessFlag); + curClass.This.Dscr = read2(); + if ( LoadNamedClass(lm_normal, curClass.This.Dscr, &opis) ) + { + curClass.This.Name = opis._name; + } + else + { + BadRefFile("'this' class", curClass.This.Dscr); + CASSERT(offsetof(ClassInfo, This.Ref)+2 == offsetof(ClassInfo, This.Dscr) + && offsetof(ClassInfo, This.Ref) == offsetof(ClassInfo, This.Name)); + curClass.This.Ref >>= 16; +// curClass.This.Name = curClass.This.Dscr; +// curClass.This.Dscr = 0; + } +//-- + if ( curClass.xtrnNode ) + setPoolReference(); + curClass.super.Dscr = read2(); + uint i = read2(); // interface counter + i *= 2; + if ( FileSize < i ) + errtrunc(); + qfseek(fp, i, SEEK_CUR); + curClass.FieldCnt = read2(); + qfseek(fp, -2 - qoff64_t(i), SEEK_CUR); + _add_seg(3); // class segment + enableExt_NameChar(); + if ( curClass.This.Dscr ) + { + curSeg.id.Number = 0; + SetName(curClass.This.Name, curClass.start_ea, curClass.AccessFlag, 0); + hide_name(curClass.start_ea); + } + + if ( curClass.super.Ref ) + { + if ( !LoadNamedClass(lm_normal, curClass.super.Dscr, &opis) ) + { + BadRefFile("parent class", curClass.super.Dscr); + } + else + { + curClass.super.Name = opis._name; + xtrnRef(curClass.start_ea, opis); + } + } +//-- + if ( (i /= 2) != 0 ) // InterfaceCount + { + netnode temp; + uint r = 0; + + do + { + j = read2(); + if ( j == 0 ) + { + load_msg("Ignore zero interface index\n"); + continue; + } + if ( !r ) + temp.create(); + + uint32 refd = (uint32)j << 16; + if ( !LoadNamedClass(lm_normal, j, &opis) ) + { + BadRefFile("interface", j); + } + else + { + xtrnRef(curClass.start_ea, opis); + refd |= opis._name; + } + temp.altset(++r, refd); + } + while ( --i ); + if ( r ) + { + temp.altset(0, r); + curClass.impNode = temp; + } + } +//--- + ClassNode.create(); + curClass.ClassNode = ClassNode; + qfseek(fp, 2, SEEK_CUR); + if ( errload ) + { + int f = (curClass.AccessFlag & ~ACC_THIS_MASK) ? curClass.AccessFlag : 0; + mark_access(curClass.start_ea, f); + } +//--- + for ( i = 1; (ushort)i <= curClass.FieldCnt; i++ ) + { + memset(&curField, 0, sizeof(curField)); + curField.id.Number = (ushort)i; + curField.id.access = read2(); + j = curField.id.access & ACC_ACCESS_MASK; + if ( (curField.id.access & ~ACC_FIELD_MASK) || (j & (j-1)) ) + { + load_msg("Illegal Field#%u Attribute 0x%04x\n", i, curField.id.access); +// curField.id.extflg |= EFL_ACCESS; + mark_access(curClass.start_ea + i, curField.id.access); + } + + curField.id.name = read2(); + if ( !CheckFieldName(lm_normal, curField.id.name, NULL) ) + curField.id.extflg |= EFL_NAME; + + curField.id.dscr = read2(); + if ( !CheckFieldDscr(lm_normal, curField.id.dscr, &opis) ) + curField.id.extflg |= EFL_TYPE; + else + xtrnRef_dscr(curClass.start_ea + curField.id.Number, &opis); + if ( curField.id.extflg & EFL_NAMETYPE ) + load_msg("Illegal NameAndType of field %u\n", i); + load_attributes(attr_parent_kind_field); + for ( int n = 0; n < qnumber(curField.annNodes); n++ ) + if ( curField.annNodes[n] == (uval_t)-1 ) + ++curField.annNodes[n]; + ClassNode.supset(i, &curField, sizeof(curField)); + if ( !(curField.id.extflg & EFL_NAME) ) + SetName(curField.id.name, curClass.start_ea + i, curField.id.access, i); + } +//-- + curClass.MethodCnt = read2(); + for ( i = 1; i <= curClass.MethodCnt; i++ ) + { + memset(&curSeg, 0, sizeof(curSeg)); + curSeg.id.Number = (ushort)i; + curSeg.id.access = read2(); + j = curSeg.id.access & ACC_ACCESS_MASK; + if ( !(j & ~ACC_METHOD_MASK) && !(j & (j-1)) ) + j = 0; + else + load_msg("Illegal Method#%u Attribute 0x%04x\n", i, curSeg.id.access); +// curSeg.id.extflg |= EFL_ACCESS; + + _add_seg(1); // create code segment // this for strnRef_dscr + curSeg.id.name = read2(); + if ( !CheckFieldName(lm_normal, curSeg.id.name, NULL) ) + curSeg.id.extflg |= EFL_NAME; + + curSeg.id.dscr = read2(); + if ( !CheckCallDscr(lm_normal, curSeg.id.dscr, &opis) ) + curSeg.id.extflg |= EFL_TYPE; + else + xtrnRef_dscr(curSeg.start_ea, &opis, 1); + if ( curSeg.id.extflg & EFL_NAMETYPE ) + load_msg("Illegal NameAndType of method %u\n", i); +// if ( curSeg.id.extflg & EFL_ACCESS ) + if ( j ) + mark_access(curSeg.start_ea, curSeg.id.access); + load_attributes(attr_parent_kind_method); + if ( curSeg.smNode == BADNODE ) + curSeg.smNode = 0; // remove 'flagged' value + for ( int n = 0; n < qnumber(curSeg.annNodes); n++ ) + if ( curSeg.annNodes[n] == (uval_t)-1 ) + ++curSeg.annNodes[n]; + if ( curSeg.varNode ) + resizeLocVars(); + if ( curSeg.thrNode ) + { + netnode tnode(curSeg.thrNode); + if ( !tnode.altval(0) ) + { + tnode.kill(); + curSeg.thrNode = 0; + } + } + ClassNode.supset(-(int)i, &curSeg, sizeof(curSeg)); + } +//-- + load_attributes(attr_parent_kind_class_file); // Source File + for ( int n = 0; n < qnumber(curClass.annNodes); n++ ) + if ( curClass.annNodes[n] == (uval_t)-1 ) + ++curClass.annNodes[n]; + myFile = NULL; + if ( curClass.encClass == 0xFFFF ) + ++curClass.encClass; // unification in out + if ( FileSize ) + warning("This file has extra information (pos=0x%" FMT_64 "x)", qftell(fp)); +//--- + CheckPoolReference(0); + endLoad_NameChar(); // set 'standart extension' + if ( !set_parent_object() && (curClass.AccessFlag & ACC_INTERFACE) ) + { + load_msg("This is interface, but superclass is not java.lang.Object!\n"); + mark_and_comment(curClass.start_ea, "Interface have nonstandart parent"); + } + if ( curClass.impNode && !curClass.super.Ref ) + { + load_msg("This have implements without superclass!\n"); + mark_and_comment(curClass.start_ea, "Empty supperclass not for Object"); + } + if ( errload ) + curClass.extflg |= XFL_C_ERRLOAD; + ConstantNode.supset(CNS_CLASS, &curClass, sizeof(curClass)); // load end! +//-- + debugmode = 1; // full pass... + for ( i = 1; i <= curClass.MethodCnt; i++ ) + { + msg("Analysing method %u...\n", i); + ClassNode.supval(-(int)i, &curSeg, sizeof(curSeg)); + ea_t ea = curSeg.start_ea; + show_addr(ea); + ea_t end = ea + curSeg.CodeSize; + segment_t *s = getseg(ea); + if ( s == NULL || end < ea || end > s->end_ea ) + loader_failure("Bad method %u code size 0x%X", i, curSeg.CodeSize); + if ( !curSeg.CodeSize ) + { + create_byte(ea, 0x10); + } + else + { + do + { + int sz = create_insn(ea); + if ( sz == 0 ) + ++sz; + ea += sz; + } + while ( ea < end ); + } + if ( (curSeg.id.extflg & EFL_NAME) == 0 ) + SetName(curSeg.id.name, curSeg.start_ea, curSeg.id.access, + curClass.FieldCnt + i); + add_func(curSeg.start_ea, end + 1); + } + debugmode = 0; // all references setting... + CheckPoolReference(1); + ConstantNode.altset(CNA_VERSION, _CUR_IDP_VER); + ResW_newbase(); + create_filename_cmt(); +} diff --git a/idasdk76/module/java/npooluti.cpp b/idasdk76/module/java/npooluti.cpp new file mode 100644 index 0000000..0085955 --- /dev/null +++ b/idasdk76/module/java/npooluti.cpp @@ -0,0 +1,2031 @@ +#include "java.hpp" +#include <diskio.hpp> +#include <entry.hpp> +#include "npooluti.hpp" +#include "oututil.hpp" + +#ifndef NCPS +#define NCPS 0x110000 +#endif + +//----------------------------------------------------------------------- +NORETURN void errtrunc(void) +{ + loader_failure("Premature end of file"); +} + +//----------------------------------------------------------------------- +GCC_DIAG_OFF(format-nonliteral); +void java_t::load_msg(const char *format, ...) +{ // this procedure prepares saving load-time message to base + char str[MAXSTR]; + va_list va; + + ++errload; + va_start(va, format); + int cnt = qvsnprintf(str, sizeof(str), format, va); + va_end(va); + msg("%s", str); + for ( int i = cnt; i; ) + { + if ( str[--i] <= ' ' ) // remove cr's + continue; + if ( ++i > MAXSPECSIZE ) + { + i = MAXSPECSIZE; + memcpy(&str[MAXSPECSIZE-3], "...", 3); + } + + netnode temp; + uval_t j; + if ( !curClass.msgNode ) + { + temp.create(); + curClass.msgNode = temp; + j = 0; + } + else + { + temp = curClass.msgNode; + j = temp.altval(0); + } + temp.supset(j, str, i); + temp.altset(0, j+1); + break; + } +} +GCC_DIAG_ON(format-nonliteral); + +//----------------------------------------------------------------------- +const char *java_t::mk_diag(attr_parent_kind_t apk, char str[128]) const +{ + static const char *const diag[] = { "Code in method", "Field", "Method" }; + str[0] = '\0'; + if ( apk < attr_parent_kind_class_file ) + qsnprintf(str, + 126, + " for %s#%u", diag[uchar(apk)], + apk == attr_parent_kind_field ? curField.id.Number : curSeg.id.Number); + return str; +} + +//----------------------------------------------------------------------- +void java_t::BadRef(ea_t ea, const char *to, ushort id, attr_parent_kind_t apk) +{ + if ( ea != BADADDR ) + remember_problem(PR_DISASM, ea); + + char diastr[128]; + load_msg("Illegal %s reference (%u)%s\n", to, id, mk_diag(apk, diastr)); +} + +//----------------------------------------------------------------------- +void java_t::mark_access(ea_t ea, ushort acc) const +{ + char str[60]; + + str[0] = 0; // for module + if ( acc ) + qsnprintf(str, sizeof(str), "Illegal access bits (0x%X)", acc); + mark_and_comment(ea, str); +} + +//------------------------------------------------------------------------- +static const char *_constant_strings[CONSTANT_LAST+1] = +{ + // 0 + "<UNKNOWN>", + "Utf8", + "Unicode", + "Integer", + "Float", + // 5 + "Long", + "Double", + "Class", + "String", + "Fieldref", + // 10 + "Methodref", + "InterfaceMethodref", + "NameAndType", + "<UNUSED_13>", + "<UNUSED_14>", + // 15 + "MethodHandle", + "MethodType", + "<UNUSED_17>", + "InvokeDynamic", +}; +const char *constant_type_to_str(uchar ctype) +{ + if ( ctype > CONSTANT_LAST ) + ctype = 0; + return _constant_strings[ctype]; +} + +//------------------------------------------------------------------------- +void print_constant( + qstrvec_t *out, + const const_desc_t &cd, + ushort index, + bool strip_tags) +{ + size_t anchor = out->size(); + + op_t x; + memset(&x, 0, sizeof(x)); + copy_const_to_opnd(x, cd); + x.ref = 0; // as flag + x.cp_type = cd.type; + x.cp_ind = index; + if ( x.cp_type == CONSTANT_Class ) + x.addr_shorts.high = (cd.flag & HAS_CLSNAME) != 0 ? fmt_fullname : fmt_ClassName; + out_java_t *ctx = (out_java_t *) create_outctx(BADADDR); + ctx->init_lines_array(out, 1000); + ctx->init_prompted_output(); + ctx->OutConstant(x, /*include_descriptor=*/ true); + ctx->flush_outbuf(); + + if ( strip_tags ) + { + for ( ; anchor < out->size(); ++anchor ) + tag_remove(&out->at(anchor)); + } + + delete ctx; +} + +//----------------------------------------------------------------------- +void *myAlloc(uint size) +{ + void *p = qalloc(size); + if ( p == NULL ) + nomem("JavaLoader"); + return p; +} + +//----------------------------------------------------------------------- +uchar *java_t::sm_realloc(uint size) +{ + if ( size > curClass.maxSMsize ) + { + curClass.maxSMsize = size; + qfree(smBuf); + smBuf = (uchar*)myAlloc(size+1); + } + return smBuf; +} + +//----------------------------------------------------------------------- +uchar *java_t::annotation_realloc(uint size) +{ + if ( size > curClass.maxAnnSz ) + { + curClass.maxAnnSz = size; + qfree(annBuf); + annBuf = (uchar*)myAlloc(size+1); + } + return annBuf; +} + +//----------------------------------------------------------------------- +// visible for converter only +ushort *java_t::append_tmp_buffer(uint size) +{ + if ( (ushort)size > curClass.maxStrSz ) + { + curClass.maxStrSz = (ushort)size; + qfree(tsPtr); + tsPtr = (ushort*)myAlloc(size*sizeof(ushort)*2+sizeof(ushort)); + } + return tsPtr; +} + +//----------------------------------------------------------------------- +bool java_t::getblob(uval_t ind, void *p, uval_t sz) +{ + if ( (ushort)sz > curClass.maxStrSz ) + return false; + + sz *= 2; + size_t ts = (size_t)sz + 1; + return ConstantNode.getblob(p, &ts, ind, BLOB_TAG) && (uint32)ts == sz; +} + +//------------------------------------------------------------------------- +bool java_t::getstr(qstring *out, ushort index) +{ + bool ok = is_valid_string_index(index); + if ( ok ) + { + // || !getblob(ind2, p2 = p1 + (size_t)siz1, siz2) ) + // uval_t i1 = ConstantNode.altval(ind1); + uint32 raw_idx = (uint32)index << 16; + nodeidx_t sz = ushort(ConstantNode.altval(raw_idx)); + ok = sz > 0; + if ( ok ) + { + qvector<ushort> raw; + raw.resize(sz, 0); + msg("Reading %u bytes\n", uint32(sz)); + ok = getblob(raw_idx, raw.begin(), sz); + if ( ok ) + out->append((const char *) raw.begin(), sz); + } + } + return ok; +} + +//---------------------------------------------------------------------- +NORETURN static void readerr(void) +{ + loader_failure("Input file read error"); +} + +//----------------------------------------------------------------------- +ushort java_t::read2(void) +{ + ushort data; + if ( FileSize < 2 ) + errtrunc(); + FileSize -= 2; + if ( fread2bytes(myFile, &data, 1) != 0 ) + readerr(); + return data; +} + +//----------------------------------------------------------------------- +uint32 java_t::read4(void) +{ + uint32 data; + if ( FileSize < 4 ) + errtrunc(); + FileSize -= 4; + if ( fread4bytes(myFile, &data, 1) != 0 ) + readerr(); + return data; +} + +//----------------------------------------------------------------------- +uchar java_t::read1(void) +{ + uchar data; + if ( !FileSize ) + errtrunc(); + --FileSize; + if ( qfread(myFile, &data, 1) != 1 ) + readerr(); + return data; +} + +//----------------------------------------------------------------------- +void java_t::readData(void *data, uint32 size) +{ + if ( FileSize < size ) + errtrunc(); + FileSize -= size; + if ( qfread(myFile, data, size) != size ) + readerr(); +} + +//----------------------------------------------------------------------- +void java_t::skipData(uint32 size) +{ + if ( FileSize < size ) + errtrunc(); + FileSize -= size; + qfseek(myFile, size, SEEK_CUR); +} + +//----------------------------------------------------------------------- +uchar java_t::set_parent_object(void) +{ + if ( curClass.super.Name ) + { + static const char object[] = "java.lang.Object"; + if ( fmtName(curClass.super.Name, tmpbuf, sizeof(tmpbuf), fmt_fullname) + && memcmp(tmpbuf, object, sizeof(object)) == 0 ) + { + curClass.extflg |= XFL_C_SUPEROBJ; + return 1; + } + } + return 0; +} + +//----------------------------------------------------------------------- +const uchar *java_t::get_annotation(uval_t node, uint *plen) +{ + netnode temp(node); + size_t len = (size_t)temp.altval(0); + if ( len && len <= curClass.maxAnnSz ) + { + *plen = (uint)len; + ++len; + if ( temp.getblob(annBuf, &len, 0, BLOB_TAG) && len == *plen ) + return annBuf; + } + return NULL; +} + +//----------------------------------------------------------------------- +bool java_t::sm_getinfo(const insn_t &insn, SMinfo *pinf) +{ // call ONLY when curSeg.smNode != 0 + sm_info_t smr; + ea_t ea; + + switch ( sm_node ) + { + case smn_aa_not_finished: + goto noinfo; + + case smn_ok: + sm_node = smn_no_use; + SMnode = curSeg.smNode; + { + size_t cnt = (size_t)SMnode.altval(-1); + if ( cnt < 2 || cnt > curClass.maxSMsize ) + goto destroyed; + SMsize = (uint32)cnt; + ++cnt; + if ( !SMnode.getblob(smBuf, &cnt, 0, BLOB_TAG) || cnt != SMsize ) + goto destroyed; + } + default: + break; + } + + ea = pinf->ea; + if ( ea == BADADDR ) + ea = insn.ea - 1; + ea = SMnode.supnext(ea); + if ( ea == BADNODE ) + goto noinfo; + if ( get_item_head(ea) != insn.ea ) + goto noinfo; + if ( SMnode.supval(ea, &smr, sizeof(smr)) != sizeof(smr) ) + goto destroyed; + if ( smr.noff >= 2 && smr.eoff > smr.noff && smr.eoff <= SMsize ) + { + pinf->ea = ea; + pinf->pb = smBuf + smr.noff; + pinf->pe = smBuf + smr.eoff; + pinf->fcnt = smr.fcnt; + return true; + } + +destroyed: + DESTROYED("sm_getinfo"); + +noinfo: + return false; +} + +//----------------------------------------------------------------------- +static const char special_sym[] = +{ + j_field_dlm, // classname (dot) ==> special point + j_clspath_dlm, // classname path (slash) + j_parm_list_start, j_parm_list_end, // function (for methods) + 0 +}; + +//------------------------------------------------------------------------- +void op_NameChars(namechar_op_t op) +{ + switch ( op ) + { + case ncop_disable: + for ( size_t i = 0; i < qnumber(special_sym); ++i ) + set_cp_validity(UCDR_NAME, special_sym[i], BADCP, false); + break; + case ncop_enable: + for ( size_t i = 0; i < qnumber(special_sym); ++i ) + set_cp_validity(UCDR_NAME, special_sym[i]); + break; + case ncop_enable_without_parens: + for ( size_t i = 0; i < 2; ++i ) + set_cp_validity(UCDR_NAME, special_sym[i]); + break; + default: INTERR(10267); + } +} + +//----------------------------------------------------------------------- +void make_NameChars(bool on_load) +{ + static const char special_char[] = + { + '$', '_', // MUST present (historical/special) + j_sign, j_endsign, // special case for <init>, <clinit> :( + }; + + set_cp_validity(UCDR_NAME, 0, NCPS, false); + // in names accepted ONLY english chars (temporary?) + set_cp_validity(UCDR_NAME, 'A', 'Z'+1); + set_cp_validity(UCDR_NAME, 'a', 'z'+1); + set_cp_validity(UCDR_NAME, '0', '9'+1); + for ( size_t i = 0; i < qnumber(special_char); ++i ) + set_cp_validity(UCDR_NAME, special_char[i]); + // fill national character's + set_cp_validity(UCDR_NAME, '\\'); // is valid for unicode escape sequnce only (special work) + // class/method path/call chars + op_NameChars(on_load ? ncop_enable : ncop_enable_without_parens); // for oldbase convertation +} + +//---------------------------------------------------------------------- +segment_t *java_t::getMySeg(ea_t ea, segment_t *seg) +{ + segment_t *s = seg != NULL ? seg : getseg(ea); + + if ( s == NULL ) + goto compat_err; + + if ( curSeg.start_ea != s->start_ea ) + { + if ( sm_node > smn_ok ) + sm_node = smn_ok; + if ( !s->orgbase ) + { + if ( s->type != SEG_IMP && s->type != SEG_XTRN ) + goto compat_err; + curSeg.start_ea = s->start_ea; + } + else + { + if ( ClassNode.supval(s->orgbase, &curSeg, sizeof(curSeg) ) != sizeof(curSeg) ) + DESTROYED("getMySeg"); + if ( -s->orgbase != curSeg.id.Number + || s->start_ea != (s->type == SEG_BSS ? curSeg.DataBase : curSeg.start_ea) ) + { +compat_err: + UNCOMPAT("getMySeg"); + } + } + } + return s; +} + +//----------------------------------------------------------------------- +// visible for converter only +GCC_DIAG_OFF(format-nonliteral); +void out_java_t::trunc_name(uint num, uchar type) +{ + static const char fnam[] = "...(Field_%u)"; + static const char metnam[] = "...(Method_%u)"; + static const char locnam[] = "...(locvar_%u)"; + static const char xtrn[] = "...(extern_%u)"; + static const char clsnam[] = "..."; + static const char *const add_nam[5] = { xtrn, fnam, metnam, locnam, clsnam }; + + enableExt_NameChar(); + size_t s = (sizeof(metnam) - 2 + 5 + 1); + size_t inplen = outbuf.length(); + outbuf.resize(inplen - s); + outbuf.cat_sprnt(add_nam[type], num); +} +GCC_DIAG_ON(format-nonliteral); + +//----------------------------------------------------------------------- +int java_t::CmpString(ushort index1, ushort index2) +{ + DEB_ASSERT((!index1 || !index2), "cs-ind"); + if ( index1 != index2 ) + { + size_t i; + uval_t ind1 = (uint32)index1 << 16; + uval_t ind2 = (uint32)index2 << 16; + + uval_t sz = ConstantNode.altval(ind1); + if ( sz == 0 || (i=(size_t)ConstantNode.altval(ind2)) == 0 ) + { +BADIDB: + DESTROYED("CmpString"); + } + + if ( sz != i ) + { +diff: + return 1; + } + + i = (ushort)i; + if ( i == 0 ) + return -1; + + sz = i; + i *= sizeof(ushort); + uchar *p1 = (uchar *)tsPtr, *p2 = p1 + i; + if ( !getblob(ind1, p1, sz) || !getblob(ind2, p2, sz) ) + goto BADIDB; + if ( memcmp(p1, p2, i) != 0 ) + goto diff; + } + return 0; +} + +//----------------------------------------------------------------------- +int java_t::cmpDscrString(ushort index1, uchar met, ushort index2, uchar self) +{ + uval_t siz1, siz2; + ushort *p1, *p2; + + uval_t ind1 = (uint32)index1 << 16; + uval_t ind2 = (uint32)index2 << 16; + uval_t i1 = ConstantNode.altval(ind1); + uval_t i2 = ConstantNode.altval(ind2); + if ( i1 == 0 + || i2 == 0 + || (siz1 = (ushort)i1) == 0 + || (siz2 = (ushort)i2) == 0 + || !getblob(ind1, p1 = tsPtr, siz1) + || !getblob(ind2, p2 = p1 + (size_t)siz1, siz2) ) + { + goto int_err; + } + + if ( met ) + { +#define _MCR ((_OP_ONECLS | _OP_VALPOS) << 16) + if ( (i1 & _MCR) != _MCR ) + goto diff; +#undef _MCR + i1 = ConstantNode.altval(ind1+1); + if ( !i1 || (int32)(siz1 -= i1) <= 0 ) + goto int_err; // never signature + p1 += (size_t)i1; + } + + if ( self && !(i1 & (_OP_NODSCR << 16)) ) + { + while ( *p1 == j_array ) + { + if ( !--siz1 ) + goto int_err; + ++p1; + } + } + + if ( (i1 ^ i2) & (_OP_NODSCR << 16) ) + { + if ( i2 & (_OP_NODSCR << 16) ) + { + if ( *p1 == j_class && p1[(size_t)siz1-1] == j_endclass ) + { + ++p1; + if ( (int)(siz1 -= 2) <= 0 ) + goto int_err; + } + } + else + { + if ( *p2 == j_class && p2[(size_t)siz2-1] == j_endclass ) + { + ++p2; + if ( (int)(siz2 -= 2) <= 0 ) + goto int_err; + } + } + } + + if ( siz1 != siz2 || memcmp(p1, p2, (size_t)siz1 * sizeof(ushort)) != 0 ) + goto diff; + return 0; +int_err: + INTERNAL("cmpDscrString"); +diff: + return 1; +} + +//----------------------------------------------------------------------- +ushort java_t::xtrnDscrSearch(ushort name, uchar met) +{ + const_desc_t cr; + + if ( curClass.This.Dscr + && !cmpDscrString(name, met, curClass.This.Name, 1) ) + { + return 0xFFFF; + } + + for ( ushort j = curClass.xtrnLQE; j; j = (ushort)(XtrnNode.altval(j) >> 16) ) + { + if ( ConstantNode.supval(j, &cr, sizeof(cr)) != sizeof(cr) + || cr.type != CONSTANT_Class + || (j = cr.ref_ip) == 0 ) + { + INTERNAL("xtrnDscrSearch"); + } + if ( !cmpDscrString(name, met, cr._name, 0) ) + return j; + } + return 0; +} + +//----------------------------------------------------------------------- +void java_t::mark_strange_name(ea_t ea) const +{ + mark_and_comment(ea, "Strange name"); +} + +//----------------------------------------------------------------------- +void java_t::xtrnSet( + uint cin, + const_desc_t *co, + uint xip, + char *str, + size_t strsize, + bool full, + uchar rmod) +{ + ea_t ea = curClass.xtrnEA + xip; + + if ( !(rmod & 4) ) + { + co->ref_ip = (ushort)xip; + StoreOpis(cin, *co); + uval_t rfa = cin; + if ( full ) + { + rfa |= ((uval_t)curClass.xtrnLQE << 16); + curClass.xtrnLQE = (ushort)cin; + } + XtrnNode.altset(xip, rfa); + create_byte(ea, 1); + } + + uint js = MAXNAMELEN - 1; + out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); + name_chk = 0; + if ( full ) // fmt_fullname + { + uni_chk = 0; + if ( pctx->fmtString(*this, co->_name, js, fmt_fullname) ) + { + endcls = MAXNAMELEN; +trnc: + pctx->trunc_name(xip); + pctx->outbuf.resize(MAXNAMELEN-1); + } + else + { + endcls = (uint)strlen(pctx->outbuf.c_str()); + } + clunic = uni_chk; + } + else + { + uni_chk = clunic; + if ( endcls >= MAXNAMELEN - 2 ) + { + pctx->outbuf.resize(MAXNAMELEN-1); + name_chk = 0; // no mark here + goto trnc; + } + pctx->outbuf.resize(pctx->outbuf.length() + (endcls + 1)); + pctx->outbuf[endcls] = '.'; + js -= (endcls + 1); + if ( pctx->fmtString(*this, co->_subnam, js, fmt_UnqualifiedName) ) + goto trnc; + } + qstrncpy(str, pctx->outbuf.c_str(), strsize); + delete pctx; + if ( rmod & 1 ) + { + // enableExt_NameChar(); + force_name(ea, convert_clsname(str)); + hide_name(ea); + // disableExt_NameChar(); + } + if ( (char)uni_chk > 0 && (rmod & 2) ) + ConstantNode.charset(ea, uni_chk, UR_TAG); + uni_chk = (uchar)-1; + if ( name_chk && !(rmod & 4) ) + mark_strange_name(ea); +} + +//----------------------------------------------------------------------- +void java_t::SetName(ushort name, ea_t ea, ushort access_mode, uval_t number, uchar rmod) +{ + uni_chk = name_chk = 0; + fmt_t fmt = number || curSeg.id.Number ? fmt_UnqualifiedName : fmt_fullname; + out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); + if ( pctx->fmtString(*this, name, sizeof(tmpbuf) - 1, fmt) ) + { + if ( !number ) + pctx->trunc_name(curSeg.id.Number, uchar(3 + !curSeg.id.Number)); + else if ( number <= (uval_t)curClass.FieldCnt ) + pctx->trunc_name((uint)number, 1); + else + pctx->trunc_name((uint)number - curClass.FieldCnt, 2); + } + qstrncpy(tmpbuf, pctx->outbuf.c_str(), sizeof(tmpbuf)); + delete pctx; + convert_clsname(tmpbuf); + + if ( rmod & 1 ) + { + switch ( access_mode & ACC_ACCESS_MASK ) + { + case ACC_PUBLIC: + if ( rmod & 4 ) + del_global_name(ea); + add_entry(number, ea, tmpbuf, 0); + break; + case 0: + if ( rmod & 4 ) + del_global_name(ea); + add_entry(ea, ea, tmpbuf, 0); + break; + default: + force_name(ea, tmpbuf); + break; + } + } + // disableExt_NameChar(); + if ( (char)uni_chk > 0 && (rmod & 2) ) + ConstantNode.charset(ea, uni_chk, UR_TAG); + uni_chk = (uchar)-1; + if ( name_chk && !(rmod & 4) ) + mark_strange_name(ea); +} + +//----------------------------------------------------------------------- +// as procedure for rename_unichars +void java_t::set_lv_name(ushort name, ea_t ea, uchar rmod) +{ + uni_chk = name_chk = 0; + if ( fmtName(name, tmpbuf, sizeof(tmpbuf), fmt_UnqualifiedName) ) + { + if ( rmod & 1 ) + force_name(ea, tmpbuf); + hide_name(ea); + if ( (char)uni_chk > 0 && (rmod & 2) ) + ConstantNode.charset(ea, uni_chk, UR_TAG); + if ( name_chk && !(rmod & 4) ) + mark_strange_name(ea); + } + uni_chk = (uchar)-1; +} + +//-------------------------------------------------------------------------- +void java_t::rename_uninames(int32 mode) +{ + nodeidx_t id = ConstantNode.charfirst(UR_TAG); + if ( id != BADNODE ) + { + char str[MAXNAMELEN]; // for imports + + show_wait_box("HIDECANCEL\nRenaming labels with national characters"); + + ushort lcls = 0; // for imports + uchar rmod = 7; // rename+save (+renamemode) + switch ( mode ) + { + case 0: // change table but renaming not needed (recreate records only) + rmod = 2; // save only + break; + case -1: // change processor flag only + rmod = 5; // rename only + // no break + default: // change table and renaming needed + break; + } + do + { + adiff_t dif; + ea_t ea = id; + uchar type = ConstantNode.charval(ea, UR_TAG); + show_addr(ea); + if ( !type || type > 3 ) + goto BADIDB; + if ( !(type & 2) && mode == -1 ) + continue; + switch ( getMySeg(ea)->type ) + { + default: +BADIDB: + DESTROYED("rename_uninames"); + + case SEG_BSS: + if ( !curSeg.varNode + || (dif = ea - curSeg.DataBase) < 0 + || dif >= curSeg.DataSize + || is_align(get_flags(ea)) ) + { + goto BADIDB; + } + { + netnode tmp(curSeg.varNode); + LocVar lv; + if ( tmp.supval((nodeidx_t)dif, &lv, sizeof(lv)) != sizeof(lv) ) + goto BADIDB; + set_lv_name(lv.var.Name, ea, rmod); + } + break; + + case SEG_CODE: + if ( ea != curSeg.start_ea ) + goto BADIDB; + SetName(curSeg.id.name, ea, curSeg.id.access, + curClass.FieldCnt + curSeg.id.Number, rmod); + break; + + case SEG_IMP: // class/fields + dif = ea - curClass.start_ea; + if ( dif < 0 ) + goto BADIDB; + if ( !dif ) // class + { + ushort sv = curSeg.id.Number; + curSeg.id.Number = 0; + SetName(curClass.This.Name, ea, curClass.AccessFlag, 0, rmod); + curSeg.id.Number = sv; + break; + } + if ( dif > curClass.FieldCnt ) + goto BADIDB; + if ( ClassNode.supval((nodeidx_t)dif, &curField, sizeof(curField) ) != sizeof(curField) ) + goto BADIDB; + SetName(curField.id.name, ea, curField.id.access, (int)dif, rmod); + break; + + case SEG_XTRN: + dif = ea - curClass.xtrnEA; + if ( dif <= 0 || dif > curClass.xtrnCnt ) + goto BADIDB; + { + uchar cmod = rmod; + const_desc_t co; + { + uint j = (uint)XtrnNode.altval((nodeidx_t)dif); + if ( j == 0 ) + goto BADIDB; + if ( !LoadOpis(lm_normal, (ushort)j, 0, &co) ) + goto BADIDB; + } + switch ( co.type ) + { + default: + goto BADIDB; + + case CONSTANT_Fieldref: + case CONSTANT_InterfaceMethodref: + case CONSTANT_Methodref: + if ( co._name != lcls ) + { + cmod = 4; // set internal static variables only +LCLASS: + lcls = co._name; + xtrnSet(-1, &co, (uint)dif, str, sizeof(str), true, cmod); + if ( co.type == CONSTANT_Class ) + break; + } + xtrnSet(-1, &co, (uint)dif, str, sizeof(str), false, rmod); + break; + case CONSTANT_Class: + goto LCLASS; + } + } + break; + } + } + while ( (id = ConstantNode.charnext(id, UR_TAG)) != BADNODE ); + hide_wait_box(); + } +} + +//----------------------------------------------------------------------- +void java_t::xtrnRef(ea_t ea, const const_desc_t &opis) const +{ + if ( (loadMode & MLD_EXTREF) && opis.ref_ip ) + { + ea_t target = opis.ref_ip == 0xFFFF + ? curClass.start_ea + : curClass.xtrnEA + opis.ref_ip; + add_dref(ea, target, dr_I); + } +} + +//----------------------------------------------------------------------- +void java_t::xtrnRef_dscr(ea_t ea, const_desc_t *opis, uchar met) +{ + if ( !met ) + { + if ( !(loadMode & MLD_VARREF) ) + return; + if ( (opis->flag & (HAS_CLSNAME | HAS_TYPEDSCR)) == HAS_CLSNAME ) + return; + } + else if ( !(loadMode & MLD_METHREF) ) + { + return; + } + + const_desc_t cr(*opis); + opis = &cr; + opis->ref_ip = xtrnDscrSearch(opis->_name, met); + xtrnRef(ea, *opis); +} + +//----------------------------------------------------------------------- +void java_t::deltry(uint bg, uint ic, uint ui, const const_desc_t &pco) +{ + for ( uint i = bg; (ushort)i <= curClass.xtrnCnt; i++ ) + { + uint j = (uint)XtrnNode.altval(i, '0'); + if ( j == 0 ) + continue; + const_desc_t co; + ConstantNode.supval(j, &co, sizeof(co)); + if ( co.type != pco.type + || co.flag != pco.flag + || co.ref_ip != (ushort)ic + || CmpString(co._subnam, pco._subnam) + || CmpString(co._dscr, pco._dscr) ) + { + continue; + } + co.ref_ip = (ushort)ui; + StoreOpis(j, co); + XtrnNode.altdel(i, '0'); + } +} + +//----------------------------------------------------------------------- +GCC_DIAG_OFF(format-nonliteral); +segment_t *java_t::_add_seg(int caller) +{ + static const char *const _cls[4] = { "xtrn", "met_", "_var", "head" }; + static const char *const fm[4] = { "import", "met%03u", "var%03u", "_Class" }; + + uval_t size; + uchar type; + + switch ( caller ) + { + default: + INTERNAL("_add_seg"); + + case 1: // method + curSeg.start_ea = start_ea; + // fallthrough + case -1: // code + start_ea = curSeg.start_ea; + type = SEG_CODE; + size = curSeg.CodeSize; + break; + + case 2: // data + curSeg.DataBase = start_ea; + size = curSeg.DataSize; + type = SEG_BSS; + break; + + case 3: // class + curClass.start_ea = start_ea; + size = curClass.FieldCnt + 1; + type = SEG_IMP; + break; + + case 0: // header + curClass.xtrnEA = start_ea = to_ea(inf_get_baseaddr(), 0); + if ( !curClass.xtrnCnt ) + return NULL; + size = curClass.xtrnCnt; + type = SEG_XTRN; + break; + } + ea_t top = start_ea + size; + ea_t end = (top + (0xF + 1)) & ~0xF; + if ( top < start_ea ) + loader_failure("Our of addressing space"); + + segment_t *S; + if ( caller < 0 ) + { + S = getseg(start_ea); + if ( S == NULL || !set_segm_end(curSeg.start_ea, end, SEGMOD_KILL) ) + qexit(1); + qoff64_t pos = qftell(myFile); + linput_t *li = make_linput(myFile); + file2base(li, pos, start_ea, top, FILEREG_PATCHABLE); + unmake_linput(li); + qfseek(myFile, pos + curSeg.CodeSize, SEEK_SET); + } + else + { + sel_t sel; + if ( start_ea > 0x100000 ) + { + sel = cursel++; + set_selector(sel, start_ea>>4); + } + else + { + sel = (ushort)(start_ea >> 4); + } + if ( !add_segm(sel, start_ea, end, NULL, _cls[caller]) ) + qexit(1); + S = getseg(start_ea); + S->orgbase = -(uval_t)curSeg.id.Number; + S->type = type; + if ( caller != 1 ) + S->set_hidden_segtype(true); // no out comment of segment type + char sname[32]; + qsnprintf(sname, sizeof(sname), fm[caller], curSeg.id.Number); + set_segm_name(S, sname); + if ( caller <= 1 ) + goto end_create; // method/header + for ( uval_t i = 0; start_ea < top; start_ea++, i++ ) // data & class + { + create_byte(start_ea, 1); + if ( caller == 2 ) // data + { + char str[MAXNAMELEN]; + qsnprintf(str, sizeof(str), "met%03u_slot%03" FMT_EA "u", curSeg.id.Number, i); + if ( force_name(start_ea, str) ) + make_name_auto(start_ea); + else + hide_name(start_ea); + } + } + } + + create_byte(top, end - top); // !header && !method +end_create: + start_ea = end; + return S; +} +GCC_DIAG_ON(format-nonliteral); + +//----------------------------------------------------------------------- +void java_t::resizeLocVars(void) const +{ + netnode temp(curSeg.varNode); + int slot = curSeg.DataSize; + + for ( int32 cur, prev = 1; --slot >= 0; prev = cur ) + { + cur = (int32)temp.altval(slot); + if ( cur < 0 && !prev ) + { + del_items(curSeg.DataBase + slot+1, DELIT_SIMPLE); + create_word(curSeg.DataBase + slot, 2); + } + } +} + +//----------------------------------------------------------------------- +const char *java_t::CopyAttrToFile(const char *astr, uint32 size, ushort id) +{ + if ( FileSize < size ) + errtrunc(); // here for alloc diagnostic + + char fname[QMAXPATH]; + qstrncpy(fname, get_path(PATH_TYPE_CMD), sizeof(fname)); + char *ptr = (char *)get_file_ext(fname); + if ( ptr == NULL ) + { + ptr = &fname[strlen(fname)]; + *ptr++ = '.'; + } + + uint32 sz = uint32(ptr - fname); + + uval_t *pnode = NULL; + if ( astr[0] == ' ' ) // SourceDebugExtension + { + if ( sz > sizeof(fname)-sizeof("SDE.utf8") ) + { +too_long: + return "PathName too long"; + } + memcpy(ptr, "SDE.utf8", sizeof("SDE.utf8")); + } + else + { + if ( sz > (sizeof(fname)-30) ) + goto too_long; + + switch ( (uchar)astr[0] ) + { + default: // ARQ_FILE: + pnode = &curClass.genNode; + break; + case attr_parent_kind_field: + ptr += qsnprintf(ptr, 30, "fld%03u_", curField.id.Number); + pnode = &curField.genNode; + break; + case attr_parent_kind_code: + case attr_parent_kind_method: + pnode = &curSeg.genNodes[astr[0] == attr_parent_kind_code]; + ptr += qsnprintf(ptr, 30, "%smet%03u.", + astr[0] == attr_parent_kind_code ? "code_" : "", + curSeg.id.Number); + break; + } + + uchar err = 0; + for ( sz = 1; ptr < &fname[sizeof(fname) - sizeof(".attr")]; sz++ ) //lint !e440 + { + uchar c = astr[sz]; + switch ( c ) + { + case 0: + goto full_copy; + default: + if ( c > CHP_MIN && c < CHP_MAX ) + { + *ptr++ = c; + break; + } + // no break + case '/': + case '\\': + case '>': + case '<': + case '?': + case '*': + case '=': + err = 1; + break; + } + } + ptr[-1] = '!'; // as marker of truncated name +full_copy: + memcpy(ptr, ".attr", sizeof(".attr")); + if ( err ) + msg("Convert unprintable filename for attribute '%s'\n", &astr[1]); + } + ptr = fname; + while ( (ptr=strchr(ptr, '\\')) != NULL ) + *ptr = '/'; + + ptr = (char *)myAlloc(size + 1); // +1 for zero_size extension! + readData(ptr, size); + + FILE *f = qfopen(fname, "wb"); + if ( f == NULL ) + { + qfree(ptr); + return "Can't create file for storing"; + } + + uchar err = 0; + if ( qfwrite(f, ptr, size) != size ) + ++err; + qfree(ptr); + if ( qfclose(f) && !err ) + { + qunlink(fname); + return "Error writing"; + } + if ( pnode ) + { + netnode temp; + uint32 pos = 0; + if ( *pnode ) + { + temp = *pnode; + } + else + { + temp.create(); + *pnode = temp; + pos = (uint32)temp.altval(0); + } + ++pos; + temp.altset(pos, id); + temp.supset(pos, fname, strlen(fname)); + temp.altset(0, pos); + } + return NULL; +} + +//----------------------------------------------------------------------- +bool java_t::fmtName(ushort index, char *buf, size_t bufsize, fmt_t fmt) +{ + out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); + int i = pctx->fmtString(*this, index, bufsize-1, fmt); + qstrncpy(buf, pctx->outbuf.c_str(), bufsize); + delete pctx; + return !i && buf[0]; +} + +//-------------------------------------------------------------------------- +// Procedures for "press Enter on any name" +int java_t::is_locvar_name(const insn_t &insn, const char *name) +{ + LocVar lv; + uint32 idx = (uint32)insn.Op1.addr; + + if ( insn.Op1.type == o_mem ) + { + if ( insn.Op1.ref ) + goto bad; + } + else if ( insn.Op1.type == o_void ) + { + if ( (char)insn.Op1.ref < 0 || (int32)(idx -= (uint32)curSeg.DataBase) < 0 ) + goto bad; + } + + if ( netnode(curSeg.varNode).supval(idx, &lv, sizeof(lv)) == sizeof(lv) + && fmtName(lv.var.Name, tmpbuf, sizeof(tmpbuf), fmt_UnqualifiedName) + && streq(name, tmpbuf) ) + { + return idx; + } +bad: + return -1; +} + +//------------------------------------------------------------------------- +static bool is_get_ref_addr_visible_cp(wchar32_t cp) +{ + return cp == j_field_dlm || cp == j_clspath_dlm || is_visible_cp(cp); +} + +//-------------------------------------------------------------------------- +ea_t java_t::get_ref_addr(ea_t ea, const char *name, size_t pos) +{ + if ( strlen(name) <= pos || getseg(ea) == NULL ) + { +NOT_FOUND: + return BADADDR; + } + + uchar clv = getMySeg(ea)->type; + switch ( clv ) // also set curSeg + { + case SEG_XTRN: + if ( !jasmin() ) + goto NOT_FOUND; // short form. Can't search by text + // no break + default: + break; + case SEG_CODE: + if ( strstrpos(name, ash.cmnt) <= pos ) + clv |= 0x80; // flag for 'modified autocomment' (see make_locvar_cmt) + break; + } + + ssize_t r = pos; + if ( !is_get_ref_addr_visible_cp(uchar(name[r])) ) + goto NOT_FOUND; + + while ( r > 0 && is_get_ref_addr_visible_cp(uchar(name[r-1])) ) + --r; + ssize_t start = r; + for ( r = pos+1; name[r]; r++ ) + if ( !is_get_ref_addr_visible_cp(uchar(name[r])) ) + break; + if ( name[r] == '\\' && !name[r+1] ) + goto NOT_FOUND; //\\+++ not work with prompt? + char buf[MAXSTR*2]; + memcpy(buf, &name[start], r); + buf[r] = '\0'; + switch ( clv & ~0x80 ) + { + case SEG_CODE: + case SEG_BSS: + r = check_special_label(buf, r); + if ( r >= 0 ) + return curSeg.start_ea + r; + // no break + default: + break; + } + insn_t insn; + decode_insn(&insn, ea); + if ( (clv&0x80) && curSeg.varNode && (start = is_locvar_name(insn, buf)) >= 0 ) + return curSeg.DataBase + start; +// append(new) + ea_t rea = get_name_ea(BADADDR, convert_clsname(buf)); + if ( rea == BADADDR && jasmin() && (clv&~0x80) == SEG_CODE ) // fieldnames + { + char *p = strrchr(buf, j_field_dlm); + if ( p ) + { + *p++ = '\0'; + if ( get_name_ea(BADADDR, buf) == curClass.start_ea ) + rea = get_name_ea(BADADDR, p); + } + } + return rea; +} + +//----------------------------------------------------------------------- +// for IDF_SHOWBADSTR (index my be not string :) +bool java_t::is_valid_string_index(ushort index) const +{ + return index > 0 + && index <= curClass.maxCPindex + && ConstantNode.altval(((uint32)index) << 16); +} + +//----------------------------------------------------------------------- +/* signatures encoding + * + * methodOrFieldSignature ::= type + * classSignature ::= [ typeparams ] supertype { interfacetype } + * + * type ::= ... | classtype | methodtype | typevar + * classtype ::= classsig { '.' classsig } + * classig ::= 'L' name [typeargs] ';' + * methodtype ::= [ typeparams ] '(' { type } ')' type + * typevar ::= 'T' name ';' + * typeargs ::= '<' type { type } '>' + * typeparams ::= '<' typeparam { typeparam } '>' + * typeparam ::= name ':' type +*/ + +//------------------------------------------------------------------------- +int out_java_t::fmtString(java_t &pm, ushort index, ssize_t size, fmt_t mode, _PRMPT_ putproc) +{ + ushort *tp = NULL; + + if ( size < 0 ) +FMTSTR_INTERR: + INTERNAL("fmtString"); + + if ( !index ) +BADIDB: + DESTROYED("fmtString"); + + uint32 strind = ((uint32)index) << 16; + uint32 ostsz = uint32(pm.ConstantNode.altval(strind)); + if ( ostsz == 0 ) + goto BADIDB; + CASSERT(offsetof(_STROP_, size) == 0 && sizeof(((_STROP_ *)0)->size) == sizeof(ushort)); + if ( !(pm.uni_chk & 1) && (ostsz & (_OP_UNICHARS<<16)) ) + ++pm.uni_chk; // rename unicode + if ( ostsz & (_OP_BADFIRST<<16) ) + pm.name_chk = 1; + if ( mode & FMT_ENC_RESERVED ) // support jasmin reserved words + { + CASSERT((fmt_fullname+1) == fmt_UnqualifiedName && (fmt_UnqualifiedName+1 ) == fmt__ENDENUM); + mode = (fmt_t)(mode ^ FMT_ENC_RESERVED); + if ( mode < fmt_fullname ) + goto FMTSTR_INTERR; + if ( (ostsz & (_OP_JSMRES_ << 16)) && (pm.idpflags & IDM_OUTASM) ) + mode = fmt_string_single_quotes; + } + ostsz = (ushort)ostsz; + if ( ostsz != 0 && !pm.getblob(strind, tp = pm.tsPtr, ostsz) ) + goto BADIDB; + + uint32 off_ReturnType = 0; + uint32 off_ThrowsSignature_and_TypeSignature = 0; + if ( fmt_expects_call_descriptor(mode) ) // method part out + { + off_ReturnType = (uint32)pm.ConstantNode.altval(strind+1); // offset to return type + off_ThrowsSignature_and_TypeSignature = (uint32)pm.ConstantNode.altval(strind+2); // lng of <...:...> + throw off + } + + return pm.format_utf16_string(tp, ostsz, off_ReturnType, off_ThrowsSignature_and_TypeSignature, size, mode, this, putproc); +} + +//----------------------------------------------------------------------- +//----------------------------------------------------------------------- +// this function is called only from the loader +uchar java_t::LoadUtf8(ushort index, const_desc_t *co) +{ + _STROP_ _opstr; + uint32 Flags = 0; + uint32 ind = ((uint32)index) << 16; + uchar result = 0, is_sde = 0, unicode = 0; + uint size; + + if ( index == (ushort)-1 ) // SourceDebugExtension + { + CASSERT(offsetof(_STROP_, size) == 0 && sizeof(_opstr.size) == sizeof(ushort)); + *(uint32*)&_opstr = (ushort)(size_t)co; + co = NULL; + is_sde = 1; + } + else + { + _opstr.flags = _OP_UTF8_; + _opstr.size = read2(); + } + size = _opstr.size; + if ( size != 0 ) + { + ushort *po = append_tmp_buffer(size); + union + { + ushort cw; + uchar cs; + }; + uchar c; + do + { + --size; + cw = (uchar)read1(); + if ( cw == 0 || cs >= 0xf0 ) + goto errcoding; + if ( (char)cs < 0 ) + { + if ( !size ) + goto errchar; + --size; + --_opstr.size; + c = cs; + cs &= 0x1F; + cw <<= 6; + { + uchar c2 = read1(); + if ( (c2 & 0xC0) != 0x80 ) + goto errchar; + cs |= (c2 & 0x3F); + } + if ( (c & 0xE0) != 0xC0 ) + { + if ( !size + || (c & 0xF0) != 0xE0 + || ((c = read1()) & 0xC0) != 0x80 ) + { +errchar: + if ( is_sde ) + goto done; + loader_failure("Illegal byte in CONSTANT_Utf8 (%u)", index); + } + --size; + --_opstr.size; + cw <<= 6; + cs |= (c & 0x3F); + if ( cw < 0x800 ) + goto errcoding; + } + else if ( cw < 0x80 && cs ) + { +errcoding: + if ( is_sde ) + goto done; + loader_failure("Illegal symbol encoding in CONSTANT_Utf8 (%u)", index); + } + } // end encoding + *po++ = cw; + if ( !is_sde ) + { + if ( cw >= CHP_MAX ) + { + if ( !javaIdent(cw) ) + goto extchar; + unicode = 1; + } + else if ( cs <= CHP_MIN ) + { +extchar: + Flags |= _OP_EXTSYM_; + unicode = (uchar)-1; + } + } + } + while ( size ); + + if ( !is_sde + && _opstr.size == 1 + && (loadMode & MLD_STRIP) + && (cw >= 0x80 || get_base_typename(cs) == NULL) ) + { +// Symantec error (strip) #3 + char str[16]; + uchar *ps = (uchar *)str; + + _opstr.size = (ushort)qsnprintf(str, sizeof(str), "_?_%04X", cw); + po = append_tmp_buffer(_opstr.size); + do + *po++ = *ps++; + while ( *ps ); + Flags |= _OP_NODSCR | _OP_NOSIGN; + co->flag = HAS_CLSNAME | HAS_FLDNAME; + unicode = 0; // PARANOYA + } + result = !Flags; + ConstantNode.setblob(tsPtr, (uchar *)po - (uchar *)tsPtr, ind, BLOB_TAG); + } + if ( !is_sde ) + { + if ( unicode == 1 ) + Flags |= _OP_UNICHARS; + _opstr.flags |= (ushort)Flags; + co->_Sopstr = *(int32 *)&_opstr; + } + ConstantNode.altset(ind, *(uint32 *)&_opstr); +done: + return result; +} + +//----------------------------------------------------------------------- +void java_t::parse_const_desc(ushort index, const_desc_t *co) +{ +// all nexts used only here (for parsing) +#define _op_PARAM_ 0x00010000 // start paramlist '(' +#define _op_PAREND_ 0x00020000 // last char is end of paramlist ')' +#define _op_RETTYPE_ 0x00040000 // have valid position for call return type +#define _op_FRSPRM_ 0x00080000 // not first descriptor (parameter) +#define _op_CLSBEG_ 0x00100000 // begin 'L...;' detected +#define _op_TYPBEG_ 0x00200000 // begin 'T...;' (signtype) detected +#define _op_NAME_ 0x00400000 // non empty class/typeref-name +#define _op_ARRAY_ 0x00800000 // previous char is '[' +// next needed for 'complex' classnames +#define _op_ISARRAY_ 0x01000000 // have any '[' in name +#define _op_PRIMSIG_ 0x02000000 // <...:...> signature presnt +#define _op_INPRSIG_ 0x04000000 // currently parse <...:...> signature +#define _op_MUSTNAM_ 0x08000000 // part must be name (before ':') + +#define _op_isTAG_ (_op_CLSBEG_ | _op_NAME_ | _op_TYPBEG_) + + uint Flags = 0; + uint size = co->_Ssize; + uint32 off_ReturnType = 0; + uint32 off_ThrowsSignature_and_TypeSignature = 0; + ushort *po = tsPtr; // ATT: call ONLY after LoadUtf8, size!=0 + uchar sgnlev = 0, prim = 0, *pprim = NULL; + uchar cs; // for prev + + if ( *po == j_sign ) // check <...:...> signature and <init>/<clinit> + { + while ( ++off_ReturnType < size ) + { + if ( !javaIdent(po[off_ReturnType]) ) + { + if ( off_ReturnType != 1 ) + { + size -= off_ReturnType+1; // +1 => balance for while, or align for <init> + switch ( po[off_ReturnType] ) + { + case j_tag: + if ( size < 7 ) + break; // Lx;>Lx; or Lx;>( )V => only_string + Flags |= _OP_FULLNM | _OP_NOFNM | _OP_NODSCR + | _op_PRIMSIG_ | _op_INPRSIG_; + po += off_ReturnType; + off_ReturnType &= 0; + ++sgnlev; + goto accept_tag; + + case j_endsign: + if ( !size ) // <init>/<clinit> + { + Flags |= _OP_NODSCR | _OP_NOSIGN; + goto SET_FLAGS; + } + // no break + default: + break; // only_string + } // switch + } // off_ReturnType != 1 + break; + } // special_char + } + goto only_string; + } // first '<' + + if ( *po == j_parm_list_start ) // check method descriptor/signature + { +to_func: + if ( --size < 2 ) + goto only_string; // )V + ++po; + Flags |= _op_PARAM_; + } + else + { + pprim = &prim; + } + do + { + --size; + cs = 0; // as flag (for wide characters) + CASSERT(CHP_MAX < 0x100); + if ( *po < CHP_MAX ) + cs = (uchar)*po; // for 'L', 'T'... + if ( javaIdent(*po, pprim) ) // letter/digit/$_ + { + if ( pprim ) + { + if ( !prim ) + Flags |= _OP_BADFIRST; + pprim = NULL; + } + goto norm_char; + } + pprim = NULL; // for speed + if ( cs <= CHP_MIN ) + goto only_string; // also >= CHP_MAX + + if ( Flags & _op_MUSTNAM_ ) // only in <...:...> signature (formal name) + { + if ( cs != j_tag ) + goto only_string; + Flags &= ~_op_MUSTNAM_; + if ( size < 7 ) + goto only_string; // Lx;>Lx; or Lx;>()V +accept_tag: + if ( po[1] == j_tag ) + { // iface + --size; + ++po; + } + goto only_tag; + } + switch ( cs ) // validate special chars + { + case j_parm_list_end: // always can be present in in name + if ( sgnlev ) + goto only_string; + if ( (Flags & (_op_PARAM_ | _op_ARRAY_ | _op_isTAG_)) != _op_PARAM_ ) + goto only_string; + Flags ^= (_op_PARAM_ | _op_PAREND_); + continue; + + case j_array: // class name can be full qualified array :( + if ( !sgnlev && !(Flags & (_op_isTAG_ | _OP_NOSIGN)) ) + { + Flags |= _OP_FULLNM; + break; + } + // no break + default: + goto only_string; + + case j_clspath_dlm: // '/' + case j_field_dlm: // '.' + Flags |= _OP_FULLNM; + continue; + + case j_sign: + if ( size < 3 // *>; + || (Flags & (_op_NAME_ | _OP_NOSIGN)) != _op_NAME_ + || ++sgnlev >= 30 ) + { + goto only_string; + } + CASSERT((int32)(2 << 30) < 0); // "fmtString check method" + Flags |= _OP_FULLNM | _OP_NOFNM | _OP_NODSCR; + Flags &= ~_op_isTAG_; + --size; + switch ( *++po ) + { + case j_wild: + if ( *++po != j_endsign ) + goto only_string; + --size; + goto end_signW; + + case j_wild_s: + case j_wild_e: + goto only_tag; + + default: + goto skipped_only_tag; + } + + case j_endsign: + if ( !size || !sgnlev ) + goto only_string; +end_signW: + // end of <...:...> signature must resolve in endclass + if ( !--sgnlev && (Flags & _op_INPRSIG_) ) + goto only_string; + if ( *++po != j_endclass ) + goto only_string; + --size; + Flags |= _op_NAME_; // restore + // no break + case j_endclass: + if ( (Flags & (_op_NAME_ | _op_PAREND_ | _op_ARRAY_)) != _op_NAME_ ) + goto only_string; + + if ( !size && (Flags & (_op_CLSBEG_ | _OP_NOSIGN)) == _op_CLSBEG_ ) + Flags |= _OP_ONECLS; + Flags &= ~_op_isTAG_; + + if ( sgnlev == 1 && (Flags & _op_INPRSIG_) ) // parse <...:...> + { + if ( size < 4 ) + goto only_string; // >Lx; or >( )V + switch ( po[1] ) + { + default: + Flags |= _op_MUSTNAM_; // next substitution + continue; + case j_tag: + goto only_string; + case j_endsign: // end of <...:...> + break; + } + ++po; // skip ';' + --size; // balance next '>' + sgnlev = 0; + Flags &= ~_op_INPRSIG_; + if ( po[1] != j_parm_list_start ) + goto only_tag; // superclass{ifaces} + ++po; // skip '>' (go=> before do-while) + off_ThrowsSignature_and_TypeSignature = (uint32)(po - tsPtr); + goto to_func; + } // end resolve end of <...:...> + + if ( sgnlev ) + { + if ( po[1] == j_endsign ) + continue; + if ( size > 2 ) + goto only_tag; // Lx; + goto only_string; + } + Flags |= _OP_FULLNM; + // class name can be full qualified array :( + if ( (Flags&(_op_ISARRAY_|_op_PARAM_|_op_RETTYPE_)) != _op_ISARRAY_ ) + { + if ( Flags & _OP_NOSIGN ) + goto only_string; // speed only + Flags |= _OP_NOFNM; + } + if ( Flags & (_op_RETTYPE_ | _op_PRIMSIG_) ) + { + Flags &= ~_op_FRSPRM_; + if ( Flags & _op_RETTYPE_ ) + goto check_throw; + } + continue; + } // switch ( specchar ) FULLNM +norm_char: + if ( Flags & (_OP_NOSIGN | _op_MUSTNAM_ | _op_NAME_) ) + continue; + + if ( Flags & _op_isTAG_ ) + { + Flags |= _op_NAME_; + continue; + } + if ( sgnlev ) + continue; + + if ( Flags & _op_PAREND_ ) + { + off_ReturnType = (uint32)(po - tsPtr); + Flags &= ~(_op_PAREND_ | _op_FRSPRM_); + Flags |= _op_RETTYPE_; + if ( cs == j_void_ret ) + goto check_throw; + } + +// chkdscr + if ( (Flags & (_op_PARAM_ | _op_FRSPRM_)) == _op_FRSPRM_ ) + goto nodscsg; + + if ( cs == j_array ) + { + Flags |= _op_ARRAY_ | _op_ISARRAY_; + continue; + } + + Flags = (Flags & ~_op_ARRAY_) | _op_FRSPRM_; + switch ( cs ) + { + case j_class: // 'L' + Flags |= _op_CLSBEG_; + continue; + case j_typeref: // 'T' + Flags |= _op_TYPBEG_; + continue; + default: + break; + } + if ( !cs || get_base_typename(cs) == NULL ) + { +nodscsg: + if ( Flags & (_OP_FULLNM | _op_RETTYPE_) ) + goto only_string; + Flags |= _OP_NODSCR | _OP_NOSIGN; + } + else if ( Flags & _op_RETTYPE_ ) + { +check_throw: + if ( !size ) + break; + if ( size < 4 || po[1] != j_throw ) + goto only_string; // ^Lx; + Flags |= _OP_FULLNM | _OP_NOFNM | _OP_NODSCR; + ++po; // skip rettype/previous-';' + --size; + if ( off_ThrowsSignature_and_TypeSignature < 0x10000 ) + off_ThrowsSignature_and_TypeSignature |= ((uint32)(po - tsPtr) << 16); +only_tag: + --size; + ++po; +skipped_only_tag: + switch ( *po ) + { + default: + goto only_string; + case j_class: // never set CLSBEG (no ONECLS) + case j_typeref: + Flags |= _op_TYPBEG_; + break; + } + } + } + while ( ++po, size ); + + if ( (Flags & (_op_PARAM_ | _op_PAREND_ | _op_ARRAY_)) || sgnlev ) + { +only_string: + Flags |= (_OP_NODSCR | _OP_NOSIGN | _OP_NOFNM | _OP_FULLNM); + } + else + { + if ( Flags & (_op_CLSBEG_ | _op_TYPBEG_) ) + { + Flags |= _OP_NODSCR | _OP_NOSIGN; + } + else if ( !(Flags & _OP_NOSIGN) ) + { + if ( off_ReturnType ) + { + Flags |= _OP_VALPOS; + if ( off_ThrowsSignature_and_TypeSignature ) + Flags |= _OP_METSIGN; + } + else if ( off_ThrowsSignature_and_TypeSignature ) + { + Flags |= _OP_CLSSIGN; + } + } + // check for reserved words + if ( !(Flags & _OP_NOWORD) ) + ResW_validate((uint32 *)&Flags, po); + } + if ( (ushort)Flags ) + { +SET_FLAGS: // <init>/<cinit>/V nor reserved :) + uint32 ind = ((uint32)index) << 16; + co->_Sflags |= (ushort)Flags; + ConstantNode.altset(ind, co->_Sopstr); + CASSERT(_OP_VALPOS < 0x10000u); + if ( Flags & _OP_VALPOS ) + { + ConstantNode.altset(ind+1, off_ReturnType); + if ( Flags & _OP_METSIGN ) + ConstantNode.altset(ind+2, off_ThrowsSignature_and_TypeSignature); + if ( !(Flags & _OP_NODSCR) ) + co->flag |= HAS_CALLDSCR; + return; + } + } + + cs = 0; + if ( !(Flags & _OP_NODSCR) ) + cs |= HAS_TYPEDSCR; + if ( !(Flags & _OP_NOFNM) ) + cs |= HAS_CLSNAME; + if ( !(Flags & _OP_FULLNM) ) + cs |= HAS_FLDNAME; + co->flag |= cs; +} + +//-------------------------------------------------------------------------- +//--------------------------------------------------------------------------- +// generated by JDK1.5 (checked with beta of 1.6) -- previously version have +// some 'skipped' letters(?). See 'addonces\jvunigen.cpp' (and move headers) +uchar javaIdent(ushort v, uchar *isStart) +{ + static const uchar cpchtb[256] = + { + 2, 3, 4, 5, 6, 7, 8, 9, 0, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 3, 22, 23, 24, 25, 0, 0, 0, 26, 27, 28, + 29, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 31, 32, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 33, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 34, + 3, 3, 3, 3, 35, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 36, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 37, 38, 3, 39, 40, 41 }; + + static const uchar idxtb[42][32] = + { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 0,192,215, 38, 26, 26, 49, 38, 26, 26, 86, + 0, 0, 0, 0, 2, 3,111, 3, 26, 26,110, 26, 26, 26,110, 26 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }, + { 26, 26, 26, 26, 26, 26,110, 0, 0, 0, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 28, 26, 37, 0, 40, 83, 0, 0 }, + { 192,192,192,192,192,192,192,192,192,192,192,222,192,192, 0, 3, + 83, 4, 26, 26, 65, 26, 26, 26, 26,110, 26, 26, 26, 26, 71, 55 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 155, 5, 26, 26, 26, 26, 26, 26, 26,110, 26, 26, 26, 26, 96, 37 }, + { 26, 26, 0, 0, 0, 0, 38, 26, 26, 26,110, 97, 38, 26, 26, 26, + 26, 0,217,192,193,192,192,194,195, 0, 26, 26, 26, 86, 86, 0 }, + { 0, 0,224, 0, 38, 26, 26, 86, 26,154,192,228,192,156,157, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26,158,196,159,160,192,191 }, + { 0, 0,190, 26, 26, 26,192,192,192,163, 0, 0, 0, 0, 0, 0, + 26, 26, 26, 26,164,192,165, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 166, 26, 26, 26, 26, 26, 26,189,192,224,168, 26,169,192, 0, 0, + 170, 63, 6, 26, 26, 32, 7,189,196,197,237, 8,169,192, 55, 0 }, + { 170, 49, 6, 26, 26, 32, 9,171,198,197, 0, 10,216,192,172, 0, + 170, 71, 65, 26, 26, 32, 11,189,199,200,100, 0,169,192, 97, 0 }, + { 170, 63, 6, 26, 26, 32, 11,189,201,197,216, 8,173,192, 97, 0, + 188, 74, 75, 12,108, 74, 71,173,202,203,237, 0,237,192, 0, 97 }, + { 170, 76, 32, 26, 26, 32, 30,173,204,203,219, 0,173,192, 0, 0, + 175, 76, 32, 26, 26, 32, 30,189,204,203,219, 83,173,192, 0, 0 }, + { 175, 76, 32, 26, 26, 32, 26,173,205,203,237, 0,173,192, 0, 0, + 175, 26,110, 5, 26, 26, 65, 90,110,206,207,192, 0, 0,208, 0 }, + { 38, 26, 26, 26, 26, 26,187,177,178,238,192,215, 0, 0, 0, 0, + 13, 14, 98, 38, 15, 47,187,179, 79,224,192,186, 0, 0, 0, 0 }, + { 100, 0, 0,215,192,215,221,209, 26, 38, 26, 26, 26, 86,217,192, + 204, 55,192,217,192,192,192,210,211, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 65,185,202,215,192,215,164,215, 0, 0, 0, 0, + 0, 0, 0, 0, 26, 26, 26, 26, 96, 0, 26, 26, 26, 26, 26,100 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 16, 26, 26, 26, 26, + 26, 26, 26, 26, 86, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 37 }, + { 110, 26, 26, 26, 26, 26, 26, 26,110, 75,110, 75, 26, 26, 26, 26, + 110, 75, 26, 26, 26,110, 75,110, 75,110,110, 26, 26,110, 26, 26 }, + { 26,110, 75,110, 26, 26, 26, 26,110, 26, 26, 86, 0,217,215, 0, + 0, 0, 0, 0, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 40, 0 }, + { 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 63,110, 0, + 38, 26, 26, 86, 26, 26, 26, 26, 26, 26, 26, 26, 26, 74,100, 0 }, + { 26, 76,182, 0, 26, 26,182, 0, 26, 26,183, 0, 26, 76,184, 0, + 26, 26, 26, 26, 26, 26,181,192,192,192,180,176,192,215, 0, 0 }, + { 0,212,192,215, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 0, + 26, 26, 26, 26, 26,174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 40,192,241,192,241,216,192, 26, 26, 26, 96, 40, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 55, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 55, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 37 }, + { 26, 26, 96, 96, 26, 26, 26, 26, 96, 96, 26, 17, 26, 26, 26, 96, + 26, 26, 26, 26, 26, 26, 76, 79, 18, 40, 41, 55, 26, 40, 18, 40 }, + { 0, 0, 0, 0, 0, 0, 0,109,100, 0, 1, 0, 0, 0, 97,109, + 0, 0, 0, 0, 26, 26, 37, 0, 0, 0,192,210,213,214, 0, 0 }, + { 78, 5, 90, 19, 20, 21, 65, 22, 33, 37, 0, 0, 26, 26, 26, 26, + 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 33, 0, 0, 0, 38,167, 19, 40, 38, 26, 26, 26, 26, 26, 26, 26, + 26, 26,110,162, 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26 }, + { 33, 26, 26, 26, 26, 40, 38, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26,110, 0, 0, 26, 26, 26, 0, 0, 0, 0, 0, 0, 0, 26, 26 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 55, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 26, 26, 26, 26, 26, 96, 26, 26, 26, 26, 26, 26, 26, 86, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 110, 0, 23,161, 26, 32,110, 79, 24, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 37, 0, 0, 0, 23, 26, 26, 26, 26, 26 }, + { 26, 26, 26, 26, 26, 26, 26, 96, 0, 0, 26, 26, 26, 26, 26, 26, + 26, 26, 5, 26, 26, 26, 26, 26, 26, 0, 0, 0, 0, 0, 26, 40 }, + { 192,192, 0, 0,241, 0,108, 0, 0, 33, 0, 0, 0, 97, 76, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 40 }, + { 1, 0,192,215, 38, 26, 26, 49, 38, 26, 26, 86, 33, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26,110, 5, 5, 5,104, 25, 0, 0, 0 } + }; + + static const uchar bittb[124] = + { + 0x00, 0x10, 0x3C, 0x04, 0xD7, 0xFC, 0xF9, 0xC5, 0xB0, 0x6D, 0x5E, 0xED, + 0xD6, 0x96, 0x25, 0xAE, 0x83, 0xAA, 0xDC, 0x3E, 0x50, 0xBD, 0xE3, 0xF8, + 0xDB, 0x63, 0xFF, 0x7B, 0xC3, 0xFF, 0xEF, 0xFF, 0xFD, 0xE0, 0xE6, 0xE7, + 0xFF, 0x03, 0xFE, 0xFF, 0x1F, 0xCF, 0xEE, 0xD3, 0x1F, 0xC3, 0x03, 0xEC, + 0x38, 0x87, 0xFF, 0x3B, 0x8F, 0xCF, 0x1F, 0x0F, 0x0D, 0xF6, 0x33, 0xFF, + 0xEC, 0xF3, 0xFF, 0x9F, 0xFF, 0xFB, 0xBB, 0x16, 0x9F, 0x39, 0x87, 0xBF, + 0x3B, 0x8F, 0xC7, 0x3D, 0xDF, 0xCF, 0x84, 0x5F, 0x0C, 0xC2, 0x1F, 0x40, + 0x38, 0xE2, 0x07, 0x03, 0xC0, 0xFE, 0x2F, 0x60, 0xC0, 0xA0, 0xE0, 0xE0, + 0x3F, 0x02, 0xF0, 0x03, 0x01, 0x03, 0xE0, 0x03, 0x1C, 0x03, 0x01, 0xE0, + 0x18, 0x80, 0x7F, 0x20, 0x80, 0x0F, 0x03, 0x03, 0x01, 0x06, 0x30, 0x0D, + 0xE8, 0x23, 0xFD, 0x9C + }; + + uint ind = idxtb[cpchtb[v >> 8]][(((uchar)v) >> 3) & 31]; + uchar bit = uchar(1 << (v & 7)); + + if ( !(bittb[ind & 0x7F] & bit) ) + return 0; + if ( isStart ) + *isStart = (!(ind & 0x80) + || (!(ind & 0x40) && (bittb[ind - 68] & bit))); + return 1; +} + diff --git a/idasdk76/module/java/npooluti.hpp b/idasdk76/module/java/npooluti.hpp new file mode 100644 index 0000000..fc9db64 --- /dev/null +++ b/idasdk76/module/java/npooluti.hpp @@ -0,0 +1,104 @@ +#ifndef _NPOOLUTI_HPP_ +#define _NPOOLUTI_HPP_ +#include "upgrade.hpp" + +const char *constant_type_to_str(uchar ctype); +void print_constant( + qstrvec_t *out, + const const_desc_t &cd, + ushort index, + bool strip_tags=false); + +void *myAlloc(uint size); + +NORETURN void errtrunc(void); + +//------------------------------------------------------------------------- +struct bootstrap_method_def_t +{ + ushort method_ref; + qvector<ushort> args; + + bootstrap_method_def_t() : method_ref(0) {} +}; + +nodeidx_t bootstrap_methods_get_node(bool assert=true, bool can_create=false); +nodeidx_t bootstrap_methods_get_count(); +void bootstrap_methods_set_count(nodeidx_t cnt); +bool bootstrap_methods_get_method( + bootstrap_method_def_t *out, + nodeidx_t idx); + +//----------------------------------------------------------------------------- +void make_NameChars(bool on_load); + +enum namechar_op_t +{ + ncop_disable, + ncop_enable, + ncop_enable_without_parens, +}; + +//------------------------------------------------------------------------- +void op_NameChars(namechar_op_t op); + +//------------------ +static void inline endLoad_NameChar(void) +{ + op_NameChars(ncop_enable_without_parens); // end load base (remove '()') +} + +//------------------ +static void inline enableExt_NameChar(void) +{ + op_NameChars(ncop_enable); //j_field_dlm; // (for searches) +} + +//------------------ +static void inline disableExt_NameChar(void) +{ + op_NameChars(ncop_disable); +} + +//----------------------------------------------------------------------- +struct _STROP_ +{ + ushort size; + ushort flags; +}; + +// new flags at VER15 +#define _OP_NOSIGN 0x0001 // not signature (always +_OP_NODSCR) +#define _OP_METSIGN 0x0002 // method signature: <:>(...)ret +#define _OP_CLSSIGN 0x0004 // class signature: <:>super{iface} +//#define _OP_ 0x0008 +//#define _OP_ 0x0010 +#define _OP_JSMRES_ 0x0020 // name reserved in jasmin (asm support) +// end of new flags +#define _OP_ONECLS 0x0040 // descriptor has class reference +#define _OP_FULLNM 0x0080 // field have '.', '/' or [ => no FM name +#define _OP_NOFNM 0x0100 // can only descriptor. Not name +#define _OP_VALPOS 0x0200 // has posit for call descriptor +#define _OP_NODSCR 0x0400 // not descriptor +//#define _OP_NULL_ 0x0800 // has simbols 0 +//#define _OP_NAT0_ 0x1000 // has simbols disabled in Xlat-table +//#define _OP_WIDE_ 0x2000 // has simbols >= 0x100 +#define _OP_BADFIRST 0x1000 // first char in string is badStart for ident +#define _OP_UNICHARS 0x2000 // have valid unicode characters +#define _OP_UTF8_ 0x4000 // Utf8 String +#define _OP_EXTSYM_ 0x8000 // contain (!qisprint(english) && !isJavaIdent()) +// ver12 bits +// #define _OP_UNICODE_ 0x8000 // Unicode String (removed? from standard) +// for jasmin reserved words checking +#define _OP_NOWORD uint32(0xFFFF & ~(_OP_NOSIGN|_OP_ONECLS|_OP_NODSCR|_OP_UTF8_)) + +// low bits used as temporary in VER12 + // _OP_NULL_ | _OP_NAT0_ | _OP_WIDE_ + +CASSERT((UPG12_EXTMASK >> 16) == 0x7000 + && (UPG12_CLRMASK >> 16) == 0xF03F + && (UPG12_BADMASK >> 16) == 0x8000 + && (UPG12_EXTSET >> 16) == _OP_EXTSYM_); + +//----------------------------------------------------------------------------- +#endif diff --git a/idasdk76/module/java/out.cpp b/idasdk76/module/java/out.cpp new file mode 100644 index 0000000..7af2015 --- /dev/null +++ b/idasdk76/module/java/out.cpp @@ -0,0 +1,2160 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "java.hpp" +#include "oututil.hpp" +#include "npooluti.hpp" +//lint -esym(666,qnumber) expression with side effects + +// support for jasmin reserved word's +#define QS(f) (fmt_t)(f | FMT_ENC_RESERVED) + +DECLARE_OUT_FUNCS(out_java_t) + +//---------------------------------------------------------------------- +bool out_java_t::out_sm_end(void) +{ + return block_close(4, "stack"); +} + +//---------------------------------------------------------------------- +bool out_java_t::out_deprecated(uchar pos) +{ + return flush_buf(COLSTR(".deprecated", SCOLOR_KEYWORD), pos); +} + +//---------------------------------------------------------------------- +//lint -e719 too many arguments for format +// no idea why lint complains, everything looks corrrect +bool out_java_t::out_sm_start(int same) +{ + char samestr[80]; + + samestr[0] = 0; + if ( same >= 0 ) + { + char tmp[32]; + tmp[0] = '\0'; + if ( same ) + qsnprintf(tmp, sizeof(tmp), COLSTR(" %d", SCOLOR_NUMBER), same); + qsnprintf(samestr, sizeof(samestr), " use%s locals", tmp); + } + + if ( jasmin() ) + return gen_printf(4, COLSTR(".stack%s", SCOLOR_KEYWORD), samestr); + + return gen_printf(4, + COLSTR("%s %s StackMap%s", SCOLOR_AUTOCMT), + COLSTR("{", SCOLOR_SYMBOL), + ash.cmnt, samestr); +} + +//---------------------------------------------------------------------- +bool out_java_t::out_stackmap(const SMinfo *pinf) +{ + static char const *const verif[ITEM_BADOBJECT] = + { + "Top", "Integer", "Float", "Double", "Long", "Null", "UninitializedThis", + "Object ", "Unititialized " + }; + static char const *const kwd[3] = { "locals", "stack", NULL }; + + union + { + const uchar *p1; + const ushort *p2; + }; + + char const *const *stage; + uchar rectype; + uint vcnt; + + p1 = pinf->pb; + rectype = SMT_FULL_FRAME; + if ( pm().SMF_mode ) + rectype = *p1++; // >=JDK6 + if ( rectype >= SMT_SAME_FRM_S1 ) + ++p2; // skip offset + if ( (rectype < SMT_SAME_FRM_S1 && rectype > SMT_SAME_FRM_S1_max) ) + goto BADIDB; + if ( p1 > pinf->pe ) + goto BADIDB; + + { + int hdr = -1; + + if ( rectype != SMT_FULL_FRAME ) + { + ++hdr; // 0 -- without args + if ( rectype >= SMT_CHOP_FRM_S0_min && rectype <= SMT_CHOP_FRM_S0_max ) + { + hdr = SMT_SAME_FRM_S0 - rectype; + if ( (uint)hdr > pinf->fcnt ) + goto BADIDB; + hdr = pinf->fcnt - hdr; + if ( hdr == 0 ) + --hdr; // nocopy + } + } + if ( out_sm_start(hdr) ) + goto STOP_NOW; + } + + if ( pinf->ea != insn.ea ) + if ( gen_printf(6, COLSTR("%s %u", SCOLOR_ERROR), + COLSTR("offset", SCOLOR_KEYWORD), + (uint)(pinf->ea - pm().curSeg.start_ea)) ) + goto STOP_NOW; + + + if ( rectype <= SMT_SAME_FRM_S0_max ) + goto done_block; + stage = &kwd[1]; + vcnt = 1; + if ( rectype > SMT_SAME_FRM_S1 ) + { + if ( rectype <= SMT_SAME_FRM_S0 ) + goto done_block; + --stage; + if ( rectype != SMT_FULL_FRAME ) + { + vcnt = rectype - SMT_SAME_FRM_S0; + } + else + { +repeat_stage: + vcnt = *p2++; + if ( p1 > pinf->pe ) + goto BADIDB; + } + } + if ( vcnt != 0 ) + { + do + { + uchar tag = *p1++; + if ( p1 > pinf->pe || tag > ITEM_CURCLASS ) + goto BADIDB; + pm().curpos = 6; + out_tagon(COLOR_KEYWORD); + size_t inplen = outbuf.length(); + out_printf("%s %s", *stage, + verif[tag < ITEM_BADOBJECT ? tag : ITEM_Object]); + pm().outcnt = outbuf.length() - inplen; + out_tagoff(COLOR_KEYWORD); + CASSERT((ITEM_Object+1) == ITEM_Uninitialized + && (ITEM_Uninitialized+1) == ITEM_BADOBJECT + && (ITEM_BADOBJECT+1) == ITEM_CURCLASS); + if ( tag >= ITEM_Object ) + { + ushort var = *p2++; + if ( p1 > pinf->pe ) + goto BADIDB; + switch ( tag ) + { + case ITEM_BADOBJECT: + if ( putShort(var) ) + goto STOP_NOW; + break; + case ITEM_CURCLASS: + case ITEM_Object: + if ( OutUtf8(var, + QS(fmt_fullname), + tag == ITEM_Object ? COLOR_IMPNAME : COLOR_DNAME) ) + goto STOP_NOW; + break; + case ITEM_Uninitialized: + if ( outOffName(var) ) + goto STOP_NOW; + break; + } + } + if ( change_line() ) + goto STOP_NOW; + } + while ( --vcnt ); + } + if ( rectype == SMT_FULL_FRAME && *++stage ) + goto repeat_stage; +done_block: + if ( p1 == pinf->pe ) + return out_sm_end(); +BADIDB: + DESTROYED("out_stackmap"); +STOP_NOW: + return true; +} + +//---------------------------------------------------------------------- +uchar out_java_t::OutModes(uint32 mode) +#define OA_THIS 0 +#define OA_FIELD 1 +#define OA_METHOD 2 +#define OA_NEST 4 // in this case low BYTE == OA_NEST, hi word == access +{ + static const TXS fn[] = + { + TXS_DECLARE("public "), + TXS_DECLARE("private "), + TXS_DECLARE("protected "), + TXS_DECLARE("static "), + TXS_DECLARE("final "), + TXS_DECLARE("synchronized "), // "super " (file) + TXS_DECLARE("volatile "), // "bridge " (method) + TXS_DECLARE("transient "), // "varargs " (method) + TXS_DECLARE("native "), + TXS_EMPTY(), // "interface " // special output mode + TXS_DECLARE("abstract "), + TXS_DECLARE("fpstrict "), // float-ing-point FP-stricted + TXS_DECLARE("synthetic "), // create by compiler (not present in source) + TXS_DECLARE("annotation "), + TXS_DECLARE("enum ") // class or it superclass is enum + }; + + static const TXS ex[2] = + { + TXS_DECLARE("bridge "), + TXS_DECLARE("varargs ") + }; + + static const TXS kwd[4] = + { + TXS_DECLARE(".class "), + TXS_DECLARE(".field "), + TXS_DECLARE(".method "), + TXS_DECLARE(".interface ") + }; + + ushort access_mode; + uchar off = 2, flg; + int kwdo; + + switch ( mode ) + { + case OA_FIELD: + flg = pm().curField.id.extflg; + access_mode = pm().curField.id.access & ACC_FIELD_MASK; + break; + case OA_METHOD: + flg = pm().curSeg.id.extflg; + access_mode = pm().curSeg.id.access & ACC_METHOD_MASK; + break; + case OA_THIS: + flg = pm().curClass.extflg; + access_mode = pm().curClass.AccessFlag & ACC_THIS_MASK; + off = 0; + break; + default: // OA_NEST + flg = 0; + access_mode = (ushort)(mode >> 16); + break; + } + + kwdo = mode & 3; + if ( kwdo == 0 && (access_mode & ACC_INTERFACE) ) + kwdo += 3; + + if ( !jasmin() && (flg & XFL_DEPRECATED) ) + { + out_commented("@Deprecated", COLOR_AUTOCMT); + if ( change_line() ) + { +BADIDB: + return 1; + } + pm().curpos = off; + } + + if ( mode >= OA_NEST && !jasmin() ) + { + pm().outcnt += out_commented("{Inner}: "); + } + else + { + out_tagon(COLOR_KEYWORD); + uint rc = 0; + if ( jasmin() ) + { + if ( mode >= OA_NEST ) + { + OUT_STR(".inner "); + ++rc; + } + outLine(&kwd[kwdo].str[rc], kwd[kwdo].size-rc); + } + } + for ( uint m, v = access_mode & ((1 << qnumber(fn)) - 1), i = 0; + (m = (1<<i)) <= v; + i++ ) //lint !e440 for clause irregularity + { + if ( (v & m) == 0 ) + continue; + + const TXS *pfn = &fn[i]; + + switch ( m ) + { + case ACC_SUPER: + if ( !(mode & 3) ) + continue; // OA_THIS, OA_NEST: 'super' is deprecated; + default: + break; + case ACC_BRIDGE: + case ACC_VARARGS: + if ( (uchar)mode == OA_METHOD ) + pfn = &ex[m == ACC_VARARGS]; + break; + } + if ( !pfn->size ) + continue; // special case + if ( chkOutLine(pfn->str, pfn->size) ) + goto BADIDB; + } + switch ( mode ) + { + default: // OA_NEST, OA_THIS + if ( !jasmin() + && chkOutLine(&kwd[kwdo].str[1], kwd[kwdo].size-1) ) + { + goto BADIDB; + } + if ( (uchar)mode != OA_THIS && !jasmin() ) + break; + // no break + case OA_FIELD: + case OA_METHOD: + out_tagoff(COLOR_KEYWORD); + break; + } + return 0; +} + +//---------------------------------------------------------------------- +uchar out_java_t::sign_out(ushort utsign, char mode) +{ + fmt_t fmt = fmt_string; + + if ( !jasmin() ) + { + out_tagon(COLOR_AUTOCMT); + pm().outcnt += out_commented("User type: "); + fmt = fmt_FieldDescriptor_nospace; // for field/locvar + if ( mode ) + { + fmt = fmt_method_FormalTypeParameters; + if ( mode > 0 ) + fmt = fmt_ClassSignature; // defer for check ONLY + } + } + else + { + static const TXS sgn = TXS_DECLARE(".signature "); + out_tagon(COLOR_KEYWORD); + if ( chkOutLine(sgn.str + !mode, sgn.size - !mode) ) + goto BADIDB; + } + if ( OutUtf8(utsign, fmt) ) + { +BADIDB: + return 1; + } + if ( fmt == fmt_method_FormalTypeParameters ) + { + if ( OutUtf8(utsign, fmt_method_ReturnType) + || chkOutSpace() + || OutUtf8(utsign, fmt_method_TypeSignature) + || OutUtf8(utsign, fmt_method_ThrowsSignature) ) + { + goto BADIDB; + } + } + out_tagoff(jasmin() ? COLOR_KEYWORD : COLOR_AUTOCMT); + if ( mode || !jasmin() ) + return change_line(); + return chkOutSpace(); +} + +//---------------------------------------------------------------------- +void out_java_t::out_switch(void) +{ + op_t x; + x.n = 0; + x.flags = OF_SHOW; + x.dtype = dt_dword; + x.type = o_imm; + + if ( !jasmin() && block_begin(4) ) + return; + + uchar nwarns = 0; + uval_t count; + ea_t addr; + for ( addr = insn.Op2.addr, count = insn.Op3.value; count; addr += 4, count-- ) + { + pm().curpos = 8; + if ( insn.itype == j_lookupswitch ) + { + x.value = get_dword(pm().curSeg.start_ea + addr); // pairs + addr += 4; + if ( !putVal(x, OOFW_IMM | OOF_NUMBER | OOF_SIGNED | OOFW_32, 0) + || chkOutSpace() + || chkOutSymSpace(':') ) + { + return; + } + if ( !checkLine(1 + 8 - ((pm().outcnt + 1) % 8)) ) + return; + int idx = pm().outcnt & 7; + if ( idx != 0 ) + { + static const char seven_spaces[] = " "; + out_line(&seven_spaces[idx-1]); + } + } + x.value = insn.ip + get_dword(pm().curSeg.start_ea + addr); + if ( x.value >= pm().curSeg.CodeSize ) + { + ++nwarns; + } + else + { + if ( outName(pm().curSeg.start_ea + addr, x.n, pm().curSeg.start_ea, x.value, &nwarns) ) + goto doneswitch; + if ( nwarns ) + return; + } + if ( !putVal(x, OOFW_IMM | OOF_NUMBER | OOFS_NOSIGN | OOFW_32, nwarns) ) + return; +doneswitch: + if ( change_line() ) + return; + } + pm().curpos = 6; + OUT_KEYWORD("default "); + if ( chkOutSymSpace(':') || !out_operand(insn.Op3) || change_line() ) + return; + if ( !jasmin() ) + block_end(4); +} + +//---------------------------------------------------------------------- +void out_java_t::out_proc_mnem(void) +{ + static const char *const addonce[] = { "", "_w", "_quick", "2_quick", "_quick_w" }; + out_mnem(2, addonce[uchar(insn.wid)]); +} + +//---------------------------------------------------------------------- +void out_java_t::out_insn(void) +{ + pm().getMySeg(insn.ea); // set curSeg (for special strings) + set_gen_xrefs(false); + + if ( pm().curSeg.smNode && !(pm().idpflags & IDF_HIDESM) ) + { + SMinfo smi; + smi.ea = BADADDR; + if ( pm().sm_getinfo(insn, &smi) ) + { + init_prompted_output(4); + do + if ( out_stackmap(&smi) ) + goto STOP_NOW; + while ( pm().sm_getinfo(insn, &smi) ); + } + } + + init_prompted_output(4); + out_mnemonic(); + pm().outcnt = tag_strlen(outbuf.c_str()); + + if ( insn.Op1.type != o_void ) + { + if ( !out_one_operand(0) ) + goto STOP_NOW; + } + else + { + if ( (char)insn.Op1.ref > 0 ) + { + qstring nbuf; + if ( get_visible_name(&nbuf, insn.Op1.addr) > 0 ) + pm().outcnt += out_commented(nbuf.begin(), COLOR_REGCMT); + } + } + + if ( insn.Op2.type != o_void ) + { + if ( chkOutSpace() ) + goto STOP_NOW; + if ( insn.itype == j_tableswitch && !jasmin() ) + { + if ( CHK_OUT_KEYWORD("to ") ) + goto STOP_NOW; + } + if ( !out_one_operand(1) ) + goto STOP_NOW; + } + + if ( insn.Op3.type != o_void && !insn.swit ) // ! lookupswitch/tablesswitch + { + if ( chkOutSpace() || !out_one_operand(2) ) + goto STOP_NOW; + } + + set_gen_xrefs(true); + set_gen_cmt(true); + if ( !change_line(true) ) + { + if ( insn.swit & 2 ) + out_switch(); // normal tableswitch/lookupswitch + } +STOP_NOW: + term_prompted_output(); +} + +//-------------------------------------------------------------------------- +bool out_java_t::close_annotation(uint32 pos) +{ + return block_close(pos, "annotation"); +} + +//-------------------------------------------------------------------------- +const ushort *out_java_t::annotation(const ushort *p, uint *plen, uint pos) +{ + if ( *plen < sizeof(ushort) ) + return NULL; + *plen -= sizeof(ushort); + uint pairs = *p++; + if ( pairs != 0 ) + { + do + { + pm().curpos = pos; + if ( *plen < sizeof(ushort) ) + return NULL; + *plen -= sizeof(ushort); + p = annotation_element(p+1, plen, pos, *p); + if ( p == NULL ) + break; + if ( change_line() ) + goto STOP_NOW; + } + while ( --pairs ); + } + return p; + +STOP_NOW: + *plen = (uint)-1; + return NULL; +} + +//-------------------------------------------------------------------------- +const ushort *out_java_t::annotation_element( + const ushort *p, + uint *plen, + uint pos, + ushort name) +{ + uchar tag = 0, type = 0; + ushort val, prev = 0; + int alev = 0; + color_t ecol = COLOR_IMPNAME; + const TXS *pt; + const_desc_t co; + + op_t x; + x.flags = 0; // output flags, will be used by out_value() + x.n = 0; // operand number, will be used by out_value() + do // array-values-loop + { +arentry: + if ( *plen < sizeof(uchar)+sizeof(ushort) ) + goto BADIDB; + *plen -= sizeof(uchar)+sizeof(ushort); + if ( alev > 0 && tag != *(uchar*)p ) + goto BADIDB; + tag = *(uchar *)p; + p = (ushort*)((uchar*)p+1); + val = *p++; + if ( tag == j_array ) + { + if ( !*plen || (alev= val) == 0 || (tag= *(uchar*)p) == j_array ) + goto BADIDB; + alev = -alev; + goto arentry; + } + + if ( alev > 0 ) // not first array element + { + switch ( tag ) + { + case j_enumconst: + case j_annotation: + if ( prev != val ) + goto BADIDB; + default: + break; + } + if ( !jasmin() ) + { + if ( chkOutSymSpace(',') ) + goto STOP_NOW; + } + else if ( tag != j_annotation ) + { + if ( chkOutSpace() ) + goto STOP_NOW; + } + else + { + if ( change_line() ) + goto STOP_NOW; + pm().curpos = pos; + } + goto do_value; + } + + switch ( tag ) + { + default: + goto BADIDB; + + case j_annotation: + case j_enumconst: + if ( val == pm().curClass.This.Dscr ) + ecol = COLOR_DNAME; + prev = val; + // no break + case j_class_ret: + case j_string: + break; + + case j_float: + type = CONSTANT_Float; + x.dtype = dt_float; + break; + case j_long: + type = CONSTANT_Long; + x.dtype = dt_qword; + break; + case j_double: + type = CONSTANT_Double; + x.dtype = dt_double; + break; + case j_bool: + case j_byte: + case j_char: + x.dtype = dt_byte; + goto do_int; + case j_short: + x.dtype = dt_word; + goto do_int; + case j_int: + x.dtype = dt_dword; +do_int: + type = CONSTANT_Integer; + break; + } + + if ( jasmin() ) + { + if ( name ) + { + if ( OutUtf8(name, fmt_UnqualifiedName, COLOR_DNAME) || chkOutSpace() ) + goto STOP_NOW; + } + out_tagon(COLOR_KEYWORD); + if ( alev ) + { + if ( !checkLine(2) ) + goto STOP_NOW; + out_char(j_array); + } + if ( chkOutChar(tag) ) + goto STOP_NOW; + out_tagoff(COLOR_KEYWORD); + switch ( tag ) + { + case j_enumconst: + case j_annotation: + if ( chkOutSpace() || OutUtf8(val, fmt_FieldDescriptor_nospace, ecol) ) + goto STOP_NOW; + default: + break; + } + } + else + { // jasmin + static const TXS doptype[] = + { + TXS_DECLARE("String"), + TXS_DECLARE("Enum"), + TXS_DECLARE("Class"), + TXS_DECLARE("Annotation") + }; + pt = doptype; + switch ( tag ) + { + case j_annotation: + ++pt; + // no break + case j_class_ret: + ++pt; + // no break + case j_enumconst: + ++pt; + // no break + case j_string: + break; + + default: + pt = get_base_typename(tag); + if ( pt == NULL ) + goto BADIDB; + break; + } + if ( chkOutKeyword(pt->str, pt->size) ) + goto STOP_NOW; + switch ( tag ) + { + case j_enumconst: + case j_annotation: + if ( chkOutSpace() || OutUtf8(val, fmt_FieldDescriptor_nospace, ecol) ) + goto STOP_NOW; + default: + break; + } + if ( alev && CHK_OUT_KEYWORD("[]") ) + goto STOP_NOW; + if ( name != 0 ) + { + if ( chkOutSpace() || OutUtf8(name, fmt_UnqualifiedName, COLOR_DNAME) ) + goto STOP_NOW; + } + } // jasmin + alev = -alev; // 0 = 0 +/* + if ( chkOutSpace(insn) ) + goto STOP_NOW; + if ( (name || jasmin()) && chkOutSymSpace(insn, '=') ) + goto STOP_NOW; +*/ + if ( chkOutSpace() || chkOutSymSpace('=') ) + goto STOP_NOW; +do_value: + switch ( tag ) + { + case j_annotation: + if ( jasmin() ) + { + if ( CHK_OUT_KEYWORD(".annotation") ) + goto STOP_NOW; + } + else + { + if ( chkOutSymbol('{') ) + goto STOP_NOW; + } + if ( change_line() ) + goto STOP_NOW; + p = annotation(p, plen, pos+2); + if ( p == NULL ) + goto done; + pm().curpos = pos; + if ( jasmin() ) + { + out_line(COLSTR(".end annotation", SCOLOR_KEYWORD)); + } + else + { + out_symbol('}'); + ++pm().outcnt; + } + continue; + + case j_class_ret: + if ( !OutUtf8(val, fmt_FieldDescriptor_nospace, // without space + val == pm().curClass.This.Dscr ? COLOR_DNAME : COLOR_IMPNAME) ) + continue; +STOP_NOW: + *plen = (uint)-1; +BADIDB: + return NULL; + + case j_enumconst: + if ( *plen < sizeof(ushort) ) + goto BADIDB; + *plen -= sizeof(ushort); + if ( OutUtf8(*p++, fmt_UnqualifiedName, ecol) ) + goto STOP_NOW; + continue; + + case j_string: + if ( OutUtf8(val, fmt_string, COLOR_STRING) ) + goto STOP_NOW; + continue; + + default: + break; + } + if ( !pm().LoadOpis(lm_normal, val, type, &co) ) + goto BADIDB; + if ( !jasmin() ) + { + switch ( tag ) + { + case j_bool: + { + static const TXS bt[2] = + { + TXS_DECLARE("true"), + TXS_DECLARE("false") + }; + pt = &bt[!co.value]; + if ( chkOutKeyword(pt->str, pt->size) ) + goto STOP_NOW; + } + continue; + + case j_char: + if ( co.value < ' ' || co.value >= 0x80 ) + break; + if ( !checkLine(3) ) + goto STOP_NOW; + out_printf(COLSTR("'%c'", SCOLOR_CHAR), char(co.value)); + pm().outcnt += 3; + continue; + + default: + break; + } + } + copy_const_to_opnd(x, co); + if ( !putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) ) + goto STOP_NOW; + } + while ( alev && --alev ); +done: + return p; +} + +//-------------------------------------------------------------------------- +uchar out_java_t::annotation_loop(const uval_t *pnodes, uint nodecnt) +{ + uchar result = 1; + uint32 pos = pm().curpos; + + if ( gen_empty_line() ) + goto STOP_NOW; + + for ( uint n = 0; n < nodecnt; n++ ) + { + if ( pnodes[n] ) + { + static char const *const jnames[5] = + { + "visible", "invisible", "default", "visibleparam", "invisibleparam" + }; + static char const *const lnames[5] = + { + "RuntimeVisible", "RuntimeInvisible", + "Default", + "RuntimeVisibleParameter", "RuntimeInvisibleParameter" + }; + char hdr[MAXSTR]; + uint hdrpos, hdrlen, len; + const ushort *p = (ushort*)pm().get_annotation(pnodes[n], &len); + if ( p == NULL ) + goto BADIDB; + + if ( jasmin() ) + { + hdrpos = qsnprintf(hdr, sizeof(hdr), + COLSTR(".annotation %s", SCOLOR_KEYWORD), + jnames[n]); + } + else + { + hdrpos = qsnprintf(hdr, sizeof(hdr), + COLSTR("%sAnnotation", SCOLOR_KEYWORD), + lnames[n]); + } + + if ( n == 2 ) // defalut + { + if ( !jasmin() ) + qstrncpy(&hdr[hdrpos], COLSTR(" {", SCOLOR_SYMBOL), sizeof(hdr)-hdrpos); + if ( flush_buf(hdr, pos) ) + goto STOP_NOW; + pm().curpos = pos + 2; + p = annotation_element(p, &len, pos+2, 0); + if ( p == NULL ) + { +checkans: + if ( len == (uint)-1 ) + goto STOP_NOW; + goto BADIDB; + } + if ( len ) + goto BADIDB; + if ( change_line() || close_annotation(pos) ) + goto STOP_NOW; + continue; + } + int nump = 0, ip = 1; + uchar present = 0; + if ( n > 2 ) // parameters + { + --len; + nump = *(uchar*)p; + if ( nump == 0 ) + goto BADIDB; + p = (ushort*)((uchar*)p+1); + if ( !jasmin() ) + hdrpos += qsnprintf(&hdr[hdrpos], sizeof(hdr)-hdrpos, + COLSTR(" for parameter", SCOLOR_KEYWORD)); + } + hdr[hdrpos++] = ' '; + hdr[hdrpos] = '\0'; + do // parameters loop + { + if ( len < sizeof(ushort) ) + goto BADIDB; + len -= sizeof(ushort); + uint cnt = *p++; + if ( !cnt ) + { + if ( !nump ) + goto BADIDB; + continue; + } + if ( nump ) + qsnprintf(&hdr[hdrpos], sizeof(hdr) - hdrpos, COLSTR("%d ", SCOLOR_NUMBER), ip); + present = 1; + hdrlen = (uint32)tag_strlen(hdr); + do // annotations loop + { + if ( len < sizeof(ushort) ) + goto BADIDB; + len -= sizeof(ushort); + pm().curpos = pos; + out_line(hdr); + pm().outcnt = hdrlen; + if ( OutUtf8(*p, jasmin() ? fmt_FieldDescriptor_nospace : fmt_FieldDescriptor) ) + goto STOP_NOW; + if ( !jasmin() ) + out_symbol('{'); + if ( change_line() ) + goto STOP_NOW; + p = annotation(p+1, &len, pos+2); + if ( p == NULL ) + goto checkans; + if ( close_annotation(pos) ) + goto STOP_NOW; + } + while ( --cnt ); + } + while ( ++ip <= nump ); + if ( nump && !present ) + goto BADIDB; + if ( len ) + goto BADIDB; + } + } // loop of annotation types + result = 0; +STOP_NOW: + return result; + +BADIDB: + DESTROYED("annotation"); +} + +//-------------------------------------------------------------------------- +void out_java_t::java_header(void) +{ + char str[MAXSTR*2]; + + if ( !jasmin() ) + flush_buf(COLSTR("/*", SCOLOR_AUTOCMT), 0); + const char *prefix = jasmin() ? ash.cmnt : ""; + +#ifdef __debug__ + gen_printf(0, COLSTR("%sDisassembler mode: %s", SCOLOR_AUTOCMT), + prefix, debugmode ? "DEBUG" : "Normal"); +#endif + gen_printf(0, + COLSTR("%sJava Virtual Machine (JDK 1.%u)", SCOLOR_AUTOCMT), + prefix, pm().curClass.JDKsubver); + { + char sv = inf_get_indent(); + inf_set_indent(0); + if ( !jasmin() ) + { + gen_printf(-1, + COLSTR("%sClassFile version: %u.%u", SCOLOR_AUTOCMT), + prefix, pm().curClass.MajVers, pm().curClass.MinVers); + } + else + { + if ( out_problems(str, prefix) ) + return; + gen_empty_line(); + gen_printf(-1, COLSTR("%s %u.%u", SCOLOR_NUMBER), + COLSTR(".bytecode", SCOLOR_KEYWORD), + pm().curClass.MajVers, pm().curClass.MinVers); + } + inf_set_indent(sv); + } + + if ( pm().curClass.SourceName ) + { + init_prompted_output(); + if ( jasmin() ) + { + OUT_KEYWORD(".source "); + out_tagon(COLOR_STRING); + } + else + { + out_tagon(COLOR_AUTOCMT); + OUT_STR("Source File : "); + } + uchar stp; + { + uint32 save = pm().idpflags; + pm().idpflags = (pm().idpflags & ~IDF_AUTOSTR) | IDF_ENCODING; // PARANOYA + stp = OutUtf8(pm().curClass.SourceName, fmt_string); + pm().idpflags = save; + } + if ( !stp ) + out_tagoff(jasmin() ? COLOR_STRING : COLOR_AUTOCMT); + if ( stp || flush_outbuf(0) ) + return; + } + else + { + gen_empty_line(); + } + + // + { + nodeidx_t bmnidx = bootstrap_methods_get_node(/*assert=*/ false, /*can_create=*/ true); + if ( bmnidx != BADNODE ) + { + const nodeidx_t bmcnt = bootstrap_methods_get_count(); + if ( bmcnt > 0 ) + { + gen_printf(0, COLSTR("%sBootstrapMethods : %u", SCOLOR_AUTOCMT), + prefix, uint(bmcnt)); + for ( nodeidx_t bmidx = 0; bmidx < bmcnt; ++bmidx ) + { + bootstrap_method_def_t bmd; + const char *bmerr = "error retrieving data"; + bool bmok = bootstrap_methods_get_method(&bmd, bmidx); + if ( bmok ) + { + bmok = bmd.method_ref != 0 && bmd.method_ref <= pm().curClass.maxCPindex; + if ( bmok ) + { + const_desc_t tmp; + bmok = pm().ConstantNode.supval(bmd.method_ref, &tmp, sizeof(tmp)) == sizeof(tmp); + if ( bmok ) + { + bmok = tmp.type == CONSTANT_MethodHandle; + if ( bmok ) + { + const_desc_t method_handle; + bmok = pm().ConstantNode.supval(bmd.method_ref, &method_handle, sizeof(method_handle)) == sizeof(method_handle); + if ( bmok ) + { + // qstring buf; + // buf.sprnt("MethodHandle{kind=%u, index=%u}", + // method_handle._mhr_kind, method_handle._mhr_index); + // flush_buf(buf.c_str()); + switch ( method_handle._mhr_kind ) + { + case JVM_REF_getField: + case JVM_REF_getStatic: + case JVM_REF_putField: + case JVM_REF_putStatic: + // points at CONSTANT_Fieldref + // (fallthrough) + case JVM_REF_invokeVirtual: + case JVM_REF_invokeStatic: + case JVM_REF_invokeSpecial: + case JVM_REF_newInvokeSpecial: + // points at CONSTANT_Methodref + { + qstrvec_t lines; + print_constant(&lines, method_handle, bmd.method_ref); + if ( lines.empty() ) + lines.push_back("<failed printing method handle>"); + for ( ssize_t lidx = 0; lidx < lines.size(); ++lidx ) + gen_printf(0, "%s", lines[lidx].c_str()); + flush_outbuf(); + for ( size_t argidx = 0, argcnt = bmd.args.size(); argidx < argcnt; ++argidx ) + { + const_desc_t arg; + const ushort argcid = bmd.args[argidx]; + if ( pm().ConstantNode.supval(argcid, &arg, sizeof(arg)) == sizeof(arg) ) + { + lines.qclear(); + print_constant(&lines, arg, argcid, /*strip_tags=*/ true); + if ( lines.empty() ) + lines.push_back("<failed printing constant>"); + for ( size_t lidx = 0; lidx < lines.size(); ++lidx ) + gen_printf(0, "Argument #%" FMT_Z ": %s", argidx, lines[lidx].c_str()); + } + else + { + gen_printf(0, COLSTR("Error retrieving argument #%" FMT_Z, SCOLOR_ERROR), argidx); + } + flush_outbuf(); + } + } + break; + case JVM_REF_invokeInterface: + // points at CONSTANT_InterfaceMethodref + bmok = false; + break; + } + } + else + { + bmerr = "Couldn't retrieve method handle"; + } + } + else + { + bmerr = "Bad constant type"; + } + } + else + { + bmerr = "Corrupted data"; + } + } + else + { + bmerr = "Bad constant pool index"; + } + } + if ( !bmok ) + gen_printf(0, COLSTR("Error retrieving bootstrap method %u (%s)", SCOLOR_ERROR), + uint(bmcnt), bmerr); + } + } + } + } + + if ( !jasmin() ) + { + if ( out_problems(str, prefix) ) + return; + close_comment(); + } + myBorder(); +} + +//-------------------------------------------------------------------------- +void idaapi java_header(outctx_t &ctx) +{ + out_java_t *pctx = (out_java_t *)&ctx; + pctx->java_header(); +} + +//-------------------------------------------------------------------------- +uchar out_java_t::enclose_out(void) +{ + if ( !jasmin() ) + { + out_tagon(COLOR_AUTOCMT); + size_t inplen = outbuf.length(); + out_printf("%sEnclosing %s: ", ash.cmnt, + pm().curClass.encMethod ? "method" : "class"); + pm().outcnt += outbuf.length() - inplen; + } + else + { + OUT_KEYWORD(".enclosing method "); + } + if ( !pm().curClass.encMethod ) + { + if ( OutUtf8(pm().curClass.encClass, QS(fmt_fullname)) ) + return 1; + } + else + { + const_desc_t op; + + if ( !pm().LoadOpis(lm_normal, pm().curClass.encMethod, CONSTANT_NameAndType, &op) ) + DESTROYED("out::enclose"); + if ( (!jasmin() && OutUtf8(op._name, fmt_method_ReturnType)) + || OutUtf8(pm().curClass.encClass, fmt_fullname) + || chkOutChar(jasmin() ? '/' : '.') + || OutUtf8(op._class, fmt_UnqualifiedName) + || OutUtf8(op._name, jasmin() ? fmt_FieldDescriptor : fmt_method_TypeSignature) ) + { + return 1; + } + } + if ( !jasmin() ) + out_tagoff(COLOR_AUTOCMT); + pm().curpos = 0; + return change_line(); +} + +//-------------------------------------------------------------------------- +// output the method return type +uchar out_java_t::out_seg_type(fmt_t fmt) +{ + return out_index(pm().curSeg.id.dscr, + fmt, + COLOR_KEYWORD, + pm().curSeg.id.extflg & EFL_TYPE); +} + +//-------------------------------------------------------------------------- +// output the field type +uchar out_java_t::out_field_type(void) +{ + return out_index(pm().curField.id.dscr, + fmt_FieldDescriptor, + COLOR_KEYWORD, + pm().curField.id.extflg & EFL_TYPE); +} + +//---------------------------------------------------------------------- +uchar out_java_t::out_includes(uval_t node, uchar pos) +{ + netnode temp(node); + uint32 len, vid, cnt = (uint32)temp.altval(0); + color_t color = jasmin() ? COLOR_KEYWORD : COLOR_AUTOCMT; + char fnm[qmin(QMAXPATH,MAXSPECSIZE)+4]; + + if ( !cnt ) + goto BADIDB; + fnm[0] = '"'; + do + { + pm().curpos = pos; + + len = (uint32)temp.supstr(cnt, &fnm[1], sizeof(fnm)-3); + if ( !len ) + goto BADIDB; + fnm[++len] = '"'; + fnm[++len] = '\0'; + char *pf = fnm; + if ( pm().idpflags & IDF_NOPATH ) + { + pf = strrchr(pf, '/'); + if ( pf != NULL ) + { + ++pf; + } + else + { +#ifndef __UNIX__ + pf = &fnm[1+1]; + if ( *pf != ':' ) + --pf; +#else + pf = &fnm[1]; +#endif + } + *--pf = '"'; + len -= uint32(pf - fnm); + } + vid = (uint32)temp.altval(cnt); + if ( vid == 0 || vid > pm().curClass.maxCPindex ) + goto BADIDB; + out_tagon(color); + if ( jasmin() ) + OUT_STR(".attribute "); + else + pm().outcnt = out_commented("GenericAttribute "); + if ( OutUtf8((ushort)vid, fmt_UnqualifiedName) + || chkOutSpace() + || chkOutLine(pf, len) ) + { + goto STOP_NOW; + } + out_tagoff(color); + if ( change_line() ) + goto STOP_NOW; + } + while ( --cnt ); + return 0; + +BADIDB: + DESTROYED("out_includes"); +STOP_NOW: + return 1; +} + +//---------------------------------------------------------------------- +void out_java_t::java_segstart(segment_t *) +{ + ea_t ea = insn_ea; + + init_prompted_output(2); + + set_gen_cmt(true); + switch ( pm().getMySeg(ea)->type ) // also set curSeg + { + case SEG_CODE: + { + func_t *pfn = get_func(ea); + if ( pfn != NULL ) + { + qstring qbuf; + if ( get_func_cmt(&qbuf, pfn, false) > 0 + || get_func_cmt(&qbuf, pfn, true) > 0 ) + { + if ( gen_block_cmt(qbuf.c_str(), COLOR_REGCMT) ) + break; + } + } + } + pm().no_prim = true; + if ( OutModes(OA_METHOD) ) + break; + if ( !(pm().curSeg.id.extflg & EFL_TYPE) + && !jasmin() + && out_seg_type(fmt_method_ReturnType) ) + { + break; + } + if ( out_index(pm().curSeg.id.name, fmt_UnqualifiedName, COLOR_CNAME, // Method Name + pm().curSeg.id.extflg & EFL_NAME) ) + break; + if ( pm().curSeg.id.extflg & EFL_TYPE ) + { + if ( chkOutSpace() ) + break; + goto do_dscid; + } + if ( jasmin() ) + { +do_dscid: + if ( out_seg_type(fmt_FieldDescriptor) ) + break; + } + else if ( OutUtf8(pm().curSeg.id.dscr, fmt_method_TypeSignature, COLOR_KEYWORD) ) + { + break; + } + if ( pm().curSeg.thrNode ) + { + const char *p = ".throws "; + if ( !jasmin() ) + { + if ( CHK_OUT_KEYWORD(" throws ") ) + break; + p = NULL; + } + if ( !out_nodelist(pm().curSeg.thrNode, 2, p) ) + break; + } + if ( change_line() ) + break; + if ( pm().curSeg.id.utsign ) + { + pm().curpos = 2; + if ( sign_out(pm().curSeg.id.utsign, -1) ) + break; + } + if ( jasmin() && (pm().curSeg.id.extflg & XFL_DEPRECATED) ) + { + if ( out_deprecated(2) ) + break; + } + if ( pm().curSeg.genNodes[0] && out_includes(pm().curSeg.genNodes[0], 2) ) + break; + + if ( pm().curSeg.stacks ) + { + int over = gen_printf(2, + jasmin() ? COLSTR(".limit stack %u", SCOLOR_ASMDIR) : + COLSTR("max_stack %u", SCOLOR_ASMDIR), + pm().curSeg.stacks); + if ( over ) + break; + } + + if ( pm().curSeg.DataSize ) + { + int over = gen_printf(2, + jasmin() ? COLSTR(".limit locals %u", SCOLOR_ASMDIR) : + COLSTR("max_locals %u", SCOLOR_ASMDIR), + pm().curSeg.DataSize); + if ( over ) + break; + } + if ( (pm().curSeg.id.extflg & XFL_M_EMPTYSM) && (out_sm_start(-1) || out_sm_end()) ) + break; + + if ( pm().curSeg.id.extflg & XFL_M_LABSTART ) + out_method_label(0); + if ( !jasmin() ) + block_begin(2); + break; + + case SEG_IMP: + pm().curpos = 0; + if ( OutModes(OA_THIS) ) + break; + if ( out_index(pm().curClass.This.Name, QS(fmt_fullname), COLOR_DNAME, + (uchar)!pm().curClass.This.Dscr) ) + break; + + if ( jasmin() ) + { + if ( !pm().curClass.super.Ref ) + goto nosuper; + if ( change_line(true) ) + break; + OUT_KEYWORD(".super "); + } + else + { + uchar sskip = 0; + if ( !pm().curClass.super.Ref ) + goto check_imps; + if ( (pm().curClass.AccessFlag & ACC_INTERFACE) + && (pm().curClass.extflg & XFL_C_SUPEROBJ) ) + { +check_imps: + if ( !pm().curClass.impNode ) + goto noparents; + sskip = 1; + } + + if ( CHK_OUT_KEYWORD(" extends ") ) + break; + if ( sskip ) + goto nosuper; + } + if ( out_alt_ind(pm().curClass.super.Ref) ) + break; +nosuper: + if ( pm().curClass.impNode ) + { + const char *p = ".implements "; + if ( !jasmin() ) + { + if ( pm().curClass.AccessFlag & ACC_INTERFACE ) + { + if ( pm().curClass.super.Ref + && !(pm().curClass.extflg&XFL_C_SUPEROBJ) + && chkOutSymSpace(',') ) + { + break; + } + } + else if ( CHK_OUT_KEYWORD(" implements ") ) + { + break; + } + p = NULL; + } + if ( !out_nodelist(pm().curClass.impNode, 0, p) ) + break; + } +noparents: + if ( change_line(!jasmin()) ) + break; + if ( pm().curClass.utsign && sign_out(pm().curClass.utsign, 1) ) + break; + if ( pm().curClass.encClass && enclose_out() ) + break; + if ( jasmin() && (pm().curClass.extflg & XFL_DEPRECATED) ) + { + if ( out_deprecated(0) ) + break; + } + if ( pm().curClass.genNode != 0 && out_includes(pm().curClass.genNode, 0) ) + break; + struct ida_local lambda_t + { + static size_t call_debLine(java_t &pm, out_java_t *oj) + { + return oj->debLine(pm); + } + }; + if ( (pm().curClass.extflg & XFL_C_DEBEXT) + && fmtString(pm(), (ushort)-1, putDeb(0), fmt_debug, lambda_t::call_debLine) >= 0 ) + { + out_tagoff(COLOR_STRING); + change_line(); + } + break; + + case SEG_XTRN: + case SEG_BSS: + if ( !jasmin() ) + flush_buf(COLSTR("/*", SCOLOR_AUTOCMT), 0); + default: + break; + } + term_prompted_output(); + pm().no_prim = false; +} + +//---------------------------------------------------------------------- +void idaapi java_segstart(outctx_t &ctx, segment_t *seg) +{ + out_java_t *pctx = (out_java_t *)&ctx; + pctx->java_segstart(seg); +} + +//-------------------------------------------------------------------------- +void out_java_t::java_segend(segment_t *seg) +{ + init_prompted_output(4); + uchar t = pm().getMySeg(BADADDR, seg)->type; // also set curSeg + switch ( t ) + { + case SEG_CODE: + clr_gen_label(); // for empty method's + if ( pm().curSeg.id.extflg & XFL_M_LABEND ) + out_method_label(1); + if ( pm().curSeg.excNode ) + { + netnode enode(pm().curSeg.excNode); + uint j = (uint32)enode.altval(0); + if ( j == 0 ) + DESTROYED("out::segend"); + + if ( !jasmin() ) + flush_buf(COLSTR("/*", SCOLOR_AUTOCMT), 0); /*"*/// makedep BUG!!! + else + gen_empty_line(); + uint i = 0; + do + { + Exception ex; + if ( enode.supval(++i, &ex, sizeof(ex)) != sizeof(ex) ) + DESTROYED("out::except"); + + pm().curpos = 4; // for loop with large lines + if ( !jasmin() ) + { + OUT_KEYWORD("try"); + } + else + { + OUT_KEYWORD(".catch "); + CASSERT(offsetof(Exception, filter.Ref) == offsetof(Exception, filter.Name) + && offsetof(Exception, filter.Dscr) == offsetof(Exception, filter.Name) + 2); + if ( !ex.filter.Ref ) + OUT_KEYWORD("all"); + else if ( out_alt_ind(ex.filter.Ref) ) + goto STOP_NOW; + } + { + static const TXS kw[3] = + { + TXS_DECLARE(" from "), + TXS_DECLARE(" to "), + TXS_DECLARE(" using ") + }; + int n = 0; + do + { + if ( n == 2 && !jasmin() ) + { + if ( ex.filter.Ref ) + { + if ( CHK_OUT_KEYWORD(" catch") + || chkOutSymbol('(') + || out_alt_ind(ex.filter.Ref) + || chkOutSymbol(')') ) + { + goto STOP_NOW; + } + } + else + { + if ( CHK_OUT_KEYWORD(" finally") ) + goto STOP_NOW; + } + if ( CHK_OUT_KEYWORD(" handler ") ) + goto STOP_NOW; + } + else + { + if ( chkOutKeyword(kw[n].str, kw[n].size) ) + goto STOP_NOW; + } + CASSERT(offsetof(Exception,end_pc)-offsetof(Exception,start_pc) == sizeof(ushort) + && offsetof(Exception,handler_pc)-offsetof(Exception,end_pc) == sizeof(ushort)); + ushort off = 0; + switch ( n ) + { + case 0: off = ex.start_pc; break; + case 1: off = ex.end_pc; break; + case 2: off = ex.handler_pc; break; + } + if ( outOffName(off) ) + goto STOP_NOW; + } + while ( ++n < 3 ); + } + if ( change_line() ) + goto STOP_NOW; + } + while ( i < j ); + if ( !jasmin() ) + close_comment(); + else + gen_empty_line(); + } + if ( pm().curSeg.genNodes[1] && out_includes(pm().curSeg.genNodes[1], 2) ) + goto STOP_NOW; + if ( pm().curSeg.DataSize ) + goto STOP_NOW; +close_method: + for ( int i = 0; i < qnumber(pm().curSeg.annNodes); i++ ) + { + if ( pm().curSeg.annNodes[i] ) + { + if ( annotation_loop(pm().curSeg.annNodes, qnumber(pm().curSeg.annNodes)) ) + goto STOP_NOW; + gen_empty_line(); + break; + } + } + block_close(2, "method"); + break; + +// case SEG_IMP: + default: // PARANOYA + break; + + case SEG_XTRN: + case SEG_BSS: + if ( !jasmin() ) + close_comment(); + if ( t == SEG_BSS ) + goto close_method; + break; + } + myBorder(); +STOP_NOW: + term_prompted_output(); +} + +//-------------------------------------------------------------------------- +void idaapi java_segend(outctx_t &ctx, segment_t *seg) +{ + out_java_t *pctx = (out_java_t *)&ctx; + pctx->java_segend(seg); +} + +//---------------------------------------------------------------------- +static void check_float_const(ea_t ea, void *m, char len) +{ + if ( !has_cmt(get_flags(ea)) && j_realcvt(m, NULL, (uchar)len) != REAL_ERROR_OK ) + { + char cmt[2+5*5+2], *p = cmt; + + *p++ = '0'; + *p++ = 'x'; + do + p += qsnprintf(p, 5, "%04X", ((ushort *)m)[uchar(len)]); + while ( --len >= 0 ); + remember_problem(PR_ATTN, ea); + append_cmt(ea, cmt, false); + } +} + +//-------------------------------------------------------------------------- +void out_java_t::java_data(bool /*analyze_only*/) +{ + char nbuf[MAXSTR]; + qstring name; + op_t x; + uint32 off; + uint32 lvc; + ea_t ea = insn_ea; + + init_prompted_output(); + char stype = pm().getMySeg(ea)->type; // also set curSeg + ea_t ip = ea - pm().curSeg.start_ea; + asize_t sz = get_item_size(ea) - 1; + switch ( stype ) + { + case SEG_CODE: + if ( ip >= pm().curSeg.CodeSize ) + goto STOP_NOW; + if ( get_name(NULL, ea) > 0 ) + flush_buf(" "); // for string delimeter + if ( sz != 0 ) + { +illcall: + out_line(COLSTR("!!!_UNSUPPORTED_OUTPUT_MODE_!!!", SCOLOR_ERROR)); + } + else + { + pm().curpos = 2; + uchar c = get_byte(ea); + out_printf(COLSTR("%3u %s 0x%02X", SCOLOR_ERROR), + c, ash.cmnt, c); + } + default: + break; + + case SEG_BSS: + if ( is_align(F) ) + { + clr_gen_label(); + set_gen_cmt(false); + set_gen_xrefs(false); + goto STOP_NOW; + } + lvc = 0; // unification + off = uint32(ea - pm().curSeg.DataBase); + if ( (uint32)off >= (uint32)pm().curSeg.DataSize ) + { + off = (uint32)-1; + } + else if ( pm().curSeg.varNode + && (lvc = (uint32)netnode(pm().curSeg.varNode).altval(off)) != 0 ) + { + if ( (int32)lvc < 0 ) + { + lvc = -(int32)lvc; + if ( sz ) // can be byte for 'overloaded' variables :( + { + if ( --sz ) + goto BADIDB; // must be word + } + } + if ( (lvc % sizeof(LocVar)) || lvc >= sizeof(nbuf) ) + goto BADIDB; + } + if ( jasmin() ) + out_line(ash.cmnt, COLOR_AUTOCMT); + clr_gen_label(); + if ( off == (uint32)-1 ) + goto STOP_NOW; + if ( sz ) + goto illcall; + if ( get_visible_name(&name, ea) > 0 ) + out_printf(COLSTR("%s", SCOLOR_AUTOCMT), name.begin()); + if ( lvc == 0 ) + break; + set_gen_cmt(true); + set_gen_xrefs(true); + if ( change_line(true) ) + goto STOP_NOW; + if ( netnode(pm().curSeg.varNode).supval(off, nbuf, lvc+1) != lvc ) + goto BADIDB; + lvc /= sizeof(LocVar); + for ( LocVar *plv = (LocVar*)nbuf; ; plv++ ) + { + if ( jasmin() ) + { + pm().curpos = 4; + OUT_KEYWORD(".var "); + out_tagon(COLOR_NUMBER); + size_t inplen = outbuf.length(); + out_printf("%u", off); + pm().outcnt += outbuf.length() - inplen; + out_tagoff(COLOR_NUMBER); + OUT_KEYWORD(" is "); + } + else + { + if ( plv->utsign && sign_out(plv->utsign, 0) ) + break; + if ( OutUtf8(plv->var.Dscr, fmt_FieldDescriptor, COLOR_KEYWORD) ) + break; + if ( chkOutSpace() ) + break; + } + if ( OutUtf8(plv->var.Name, QS(fmt_UnqualifiedName), COLOR_DNAME) ) + break; + if ( chkOutSpace() ) + break; + if ( jasmin() ) + { + if ( OutUtf8(plv->var.Dscr, fmt_FieldDescriptor, COLOR_KEYWORD) ) + break; + if ( plv->utsign && sign_out(plv->utsign, 0) ) + break; + if ( CHK_OUT_KEYWORD("from ") ) + break; + } + else + { + out_tagon(COLOR_AUTOCMT); + if ( !out_commented("Scope: ") ) + break; + } + if ( putScope(plv->ScopeBeg, off) ) + break; + if ( jasmin() ) + { + if ( CHK_OUT_KEYWORD(" to ") ) + break; + } + else + { + if ( CHK_OUT_STR(" / ") ) + break; + } + if ( putScope(plv->ScopeTop, off) ) + break; + if ( !jasmin() ) + out_tagoff(COLOR_AUTOCMT); + if ( change_line(pm().curpos != 0) || !--lvc ) + break; + } + goto STOP_NOW; + + case SEG_XTRN: + if ( ip > (uint32)pm().curClass.xtrnCnt ) + goto STOP_NOW; + if ( sz ) + goto illcall; + if ( !ip ) + { + gen_printf(0, COLSTR("%s Importing prototypes", SCOLOR_AUTOCMT), + jasmin() ? ash.cmnt : ""); + break; // equivalence - gen_empty_line(); with comment + } + + if ( jasmin() ) + { + out_printf(COLSTR("%s", SCOLOR_AUTOCMT), ash.cmnt); + pm().outcnt = strlen(ash.cmnt); + } + clr_gen_label(); + set_gen_cmt(false); + set_gen_xrefs(false); + { + const_desc_t co; + { + uint j = (uint32)pm().XtrnNode.altval(ip); + if ( j == 0 ) + goto BADIDB; + if ( !pm().LoadOpis(lm_normal, (ushort)j, 0, &co) ) + goto BADIDB; + } + copy_const_to_opnd(x, co); // name / class & dscr / subnam + x.ref = 0; // as flag + x.cp_type = co.type; + switch ( x.cp_type ) + { + default: + goto BADIDB; + + case CONSTANT_Class: + if ( !jasmin() ) + { + outbuf.qclear(); + pm().outcnt = 0; + } + { + static const TXS imp = TXS_DECLARE(".import "); + int of = !jasmin(); + OutKeyword(imp.str+of, imp.size-of); + } + + if ( !(co.flag & (HAS_TYPEDSCR | HAS_CLSNAME)) ) + goto do_idx_out; + x.addr_shorts.high = (co.flag & HAS_CLSNAME) != 0 + ? fmt_fullname + : fmt_ClassName; + goto no_space_check; + + case CONSTANT_Fieldref: + if ( (co.flag & NORM_FIELD) != NORM_FIELD ) + goto do_idx; + break; + case CONSTANT_InterfaceMethodref: + case CONSTANT_Methodref: + if ( (co.flag & NORM_METOD) != NORM_METOD ) + { +do_idx: + ++x.ref; + } + break; + } + } + if ( CHK_OUT_STR(" ") ) + goto STOP_NOW; + if ( x.ref ) + { +do_idx_out: + x.n = 2; + if ( !putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16, 1) ) + goto STOP_NOW; + } + else + { +no_space_check: + if ( !OutConstant(x, /*include_descriptor=*/ true) ) + goto STOP_NOW; + } +// if ( x.cp_type == CONSTANT_Class && !jasmin() ) +// out_line(".*", COLOR_SYMBOL); + break; + + case SEG_IMP: + if ( ip > (uint32)pm().curClass.FieldCnt ) + goto STOP_NOW; + if ( sz ) + goto illcall; + clr_gen_label(); + set_gen_cmt(false); + set_gen_xrefs(false); + if ( !ip ) + { + if ( pm().curClass.annNodes[0] | pm().curClass.annNodes[1] ) + { + if ( annotation_loop(pm().curClass.annNodes, qnumber(pm().curClass.annNodes)) ) + goto STOP_NOW; + } + if ( !jasmin() ) + block_begin(0); + else + gen_empty_line(); + + if ( pm().curClass.innerNode ) + { + netnode inode(pm().curClass.innerNode); + uint j = (uint32)inode.altval(0); + if ( j == 0 ) + goto BADIDB; + color_t ci = jasmin() ? COLOR_IMPNAME : COLOR_NONE; + uint i = 0; + do + { + InnerClass ic; + if ( inode.supval(++i, &ic, sizeof(ic)) != sizeof(ic) ) + goto BADIDB; + pm().curpos = 2; + if ( !jasmin() ) + out_tagon(COLOR_AUTOCMT); + if ( OutModes((((uint32)ic.access) << 16) | OA_NEST) ) + break; + if ( ic.name ) + { + if ( OutUtf8(ic.name, fmt_UnqualifiedName, ci) ) + break; + } + else if ( !jasmin() && CHK_OUT_STR("{anonymous}") ) + { + break; + } + if ( ic.inner ) + { + if ( jasmin() ) + { + if ( CHK_OUT_KEYWORD(" inner ") ) + break; + } + else if ( CHK_OUT_STR(" {is}: ") ) + { + break; + } + if ( OutUtf8(ic.inner, fmt_fullname, ci) ) + break; + } + if ( ic.outer ) + { + if ( jasmin() ) + { + if ( CHK_OUT_KEYWORD(" outer ") ) + break; + } + else if ( CHK_OUT_STR(" {from}: ") ) + { + break; + } + color_t co = ci; + if ( co != COLOR_NONE && ic.outer == pm().curClass.This.Name ) + co = COLOR_DNAME; + if ( OutUtf8(ic.outer, fmt_fullname, co) ) + break; + } + if ( !jasmin() ) + out_tagoff(COLOR_AUTOCMT); + if ( change_line() ) + break; + } + while ( i < j ); + if ( pm().curClass.FieldCnt ) + gen_empty_line(); + } + goto STOP_NOW; + } // first entry (zero offset) + + if ( pm().ClassNode.supval(ip, &pm().curField, sizeof(pm().curField)) != sizeof(pm().curField) ) + goto BADIDB; + pm().curpos = 2; + if ( !jasmin() && pm().curField.id.utsign ) + { + if ( sign_out(pm().curField.id.utsign, 0) ) + goto STOP_NOW; + pm().curpos = 2; + } + if ( OutModes(OA_FIELD) ) + goto STOP_NOW; + if ( !jasmin() && out_field_type() ) + goto STOP_NOW; + if ( out_index(pm().curField.id.name, QS(fmt_UnqualifiedName), COLOR_DNAME, pm().curField.id.extflg & EFL_NAME) ) + goto STOP_NOW; + if ( chkOutSpace() ) + goto STOP_NOW; + if ( jasmin() && out_field_type() ) + goto STOP_NOW; + + if ( pm().curField.valNode ) + { + netnode vnode(pm().curField.valNode); + + uint valcnt = (uint32)vnode.altval(0); + if ( valcnt == 0 ) + goto BADIDB; + x.n = 0; + x.flags = OF_SHOW; + x.type = o_imm; + + if ( chkOutSymSpace('=') ) + goto STOP_NOW; + for ( uint i = 1; ; i++ ) + { + uchar flen; + + const_desc_t co; + if ( vnode.supval(i, &co, sizeof(co)) != sizeof(co) ) + { + ip = netnode(pm().curField.valNode).altval(i); + if ( ushort(ip) != 0xFFFF ) + goto BADIDB; + if ( putShort(ushort(ip >> 16)) ) + goto STOP_NOW; + } + else + { + switch ( co.type ) + { + case CONSTANT_Long: + x.dtype = dt_qword; + copy_const_to_opnd(x, co); + flen = 3; + goto chk_flt; + case CONSTANT_Double: + x.dtype = dt_double; + check_float_const(ea, &co.value, 3); + copy_const_to_opnd(x, co); + goto one_w; + case CONSTANT_Float: + x.dtype = dt_float; + x.value = co.value; + flen = 1; +chk_flt: + check_float_const(ea, &x.value, flen); + goto one_w; + case CONSTANT_Integer: + x.dtype = dt_dword; + x.value = co.value; +one_w: + if ( !putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) ) + goto STOP_NOW; + break; + + case CONSTANT_String: + if ( !checkLine(2) ) + goto STOP_NOW; + if ( OutUtf8(co._name, fmt_string, COLOR_STRING) ) + goto STOP_NOW; + break; + + default: + UNCOMPAT("out::data"); + } + } + + if ( i >= valcnt ) + break; + if ( chkOutSymSpace(',') ) + goto STOP_NOW; + } // for(...) (value) + } // if ( valNode ) + set_gen_cmt(true); + set_gen_xrefs(true); + if ( !change_line(pm().curpos != 0) ) + { + uchar addonce = 0; + + if ( jasmin() ) + { + if ( pm().curField.id.utsign ) + { + pm().curpos = 4; + if ( sign_out(pm().curField.id.utsign, -1) ) + goto STOP_NOW; + addonce = 1; + } + if ( pm().curField.id.extflg & XFL_DEPRECATED ) + { + if ( out_deprecated(4) ) + goto STOP_NOW; + addonce = 1; + } + } + + if ( pm().curField.genNode | pm().curField.annNodes[0] | pm().curField.annNodes[1] ) + { + addonce = 1; + if ( !jasmin() ) + block_begin(2); + } + + if ( pm().curField.genNode && out_includes(pm().curField.genNode, 4) ) + goto STOP_NOW; + + if ( pm().curField.annNodes[0] | pm().curField.annNodes[1] ) + { + pm().curpos = 4; // prompted output (prefer to new syntax) + if ( annotation_loop(pm().curField.annNodes, qnumber(pm().curField.annNodes)) ) + goto STOP_NOW; + } + if ( addonce ) + block_close(2, "field"); + } + goto STOP_NOW; + } + + set_gen_cmt(true); + set_gen_xrefs(true); + change_line(pm().curpos != 0); +STOP_NOW: + term_prompted_output(); + return; + +BADIDB: + DESTROYED("out::data"); +} + +//-------------------------------------------------------------------------- +void idaapi java_data(outctx_t &ctx, bool analyze_only) +{ + out_java_t *pctx = (out_java_t *)&ctx; + pctx->java_data(analyze_only); +} diff --git a/idasdk76/module/java/oututil.cpp b/idasdk76/module/java/oututil.cpp new file mode 100644 index 0000000..ec7a7c6 --- /dev/null +++ b/idasdk76/module/java/oututil.cpp @@ -0,0 +1,813 @@ +#include "java.hpp" +#include "oututil.hpp" + +//-------------------------------------------------------------------------- +// returns number of positions advanced +int out_java_t::out_commented(const char *p, color_t color) +{ + if ( color != COLOR_NONE ) + out_tagon(color); + size_t inplen = outbuf.length(); + out_printf("%s %s", ash.cmnt, p); + int npos = outbuf.length() - inplen; + if ( color != COLOR_NONE ) + out_tagoff(color); + return npos; +} + +//---------------------------------------------------------------------- +bool out_java_t::change_line(bool main) +{ + bool overflow = false; + if ( pm().g_bufinited ) + { + pm().outcnt = 0; + uchar sv = inf_get_indent(); + inf_set_indent((uchar)pm().curpos); + overflow = flush_buf(outbuf.c_str(), main ? -1 : pm().curpos); + inf_set_indent(sv); + // for autocomment with call fmtName + outbuf.qclear(); + outbuf.reserve(pm().g_bufsize); + } + return overflow; +} + +//---------------------------------------------------------------------- +size_t out_java_t::putLine(java_t &pm) +{ + color_t color = COLOR_NONE; + + if ( pm.g_bufinited ) + { + const char *p = strrchr(outbuf.c_str(), COLOR_ON); + if ( p != NULL && p[1] && strchr(p+2, COLOR_OFF) == NULL ) // second - PARANOYA + { + color = (color_t)*(p + 1); + out_tagoff(color); + } + } + out_symbol('\\'); + if ( change_line(pm.curpos != 0 && !pm.no_prim) ) + return 0; + pm.curpos = 0; + if ( color != COLOR_NONE ) + out_tagon(color); + pm.ref_pos = outbuf.length(); + return pm.maxpos; +} + +//---------------------------------------------------------------------- +bool out_java_t::checkLine(size_t size) +{ + if ( !pm().g_bufinited ) + return true; + if ( pm().maxpos - pm().curpos > pm().outcnt + size ) + return true; + return putLine(pm()) != 0; +} + +//---------------------------------------------------------------------- +bool out_java_t::chkOutLine(const char *str, size_t len) +{ + if ( !checkLine(len) ) + return true; + pm().outcnt += len; + out_line(str); + return false; +} + +//---------------------------------------------------------------------- +bool out_java_t::chkOutKeyword(const char *str, uint len) +{ + if ( !checkLine(len) ) + return true; + OutKeyword(str, len); + return false; +} + +//---------------------------------------------------------------------- +bool out_java_t::chkOutSymbol(char c) +{ + if ( !checkLine(1) ) + return true; + ++pm().outcnt; + out_symbol(c); + return false; +} + +//---------------------------------------------------------------------- +bool out_java_t::chkOutChar(char c) +{ + if ( !checkLine(1) ) + return true; + ++pm().outcnt; + out_char(c); + return false; +} + +//---------------------------------------------------------------------- +bool out_java_t::chkOutSymSpace(char c) +{ + if ( !checkLine(2) ) + return true; + out_symbol(c); + out_char(' '); + pm().outcnt += 2; + return false; +} + +//---------------------------------------------------------------------- +uchar out_java_t::putShort(ushort value, uchar wsym) +{ + size_t inplen = outbuf.length(); + + out_tagon(COLOR_ERROR); + if ( wsym ) + out_char(wsym); + out_btoa(value, +#ifdef __debug__ + debugmode ? 16 : +#endif + 10); + out_tagoff(COLOR_ERROR); + + char tmpstr[32]; + size_t curlen = outbuf.length(); + size_t len = curlen - inplen; + qstrncpy(tmpstr, &outbuf[inplen], qmin(len+1, sizeof(tmpstr))); + outbuf.resize(inplen); + return chkOutLine(tmpstr, tag_strlen(tmpstr)); +} + +//---------------------------------------------------------------------- +char out_java_t::outName(ea_t from, int n, ea_t ea, uval_t off, uchar *rbad) +{ + qstring qbuf; + + if ( get_name_expr(&qbuf, from, n, ea + off, off) <= 0 ) + { + remember_problem(PR_NONAME, insn.ea); + return 0; + } + if ( chkOutLine(qbuf.begin(), tag_strlen(qbuf.begin())) ) + { + *rbad = 1; + return 0; + } + return 1; +} + +//--------------------------------------------------------------------------- +uchar out_java_t::putVal(const op_t &x, uchar mode, uchar warn) +{ + size_t inplen = outbuf.length(); + + { + flags_t saved = F; + F = 0; + out_value(x, mode); + F = saved; + } + + char str[MAXSTR]; + size_t curlen = outbuf.length(); + size_t len = curlen - inplen; + qstrncpy(str, &outbuf[inplen], qmin(len+1, sizeof(str))); + outbuf.resize(inplen); + + if ( warn ) + out_tagon(COLOR_ERROR); + + if ( warn ) + { + qstring qstr; + len = tag_remove(&qstr, str); + qstrncpy(str, qstr.c_str(), sizeof(str)); + } + else + { + len = tag_strlen(str); + } + + if ( chkOutLine(str, len) ) + return 0; + + if ( warn ) + out_tagoff(COLOR_ERROR); + return 1; +} + +//---------------------------------------------------------------------- +CASSERT(MIN_ARG_SIZE >= 2 && MIN_ARG_SIZE < 30); + +uchar out_java_t::OutUtf8(ushort index, fmt_t mode, color_t color) +{ + size_t size = (pm().maxpos - pm().curpos) - pm().outcnt; + + if ( (int)size <= MIN_ARG_SIZE ) + { + DEB_ASSERT(((int)size < 0), "OutUtf8"); + size = putLine(pm()); + if ( size == 0 ) + return 1; + } + + if ( color != COLOR_NONE ) + out_tagon(color); + pm().ref_pos = outbuf.length(); + struct ida_local lambda_t + { + static size_t call_putLine(java_t &pm, out_java_t *oj) + { + return oj->putLine(pm); + } + }; + if ( fmtString(pm(), index, size, mode, lambda_t::call_putLine) < 0 ) + return 1; + pm().outcnt += outbuf.length() - pm().ref_pos; + if ( color != COLOR_NONE ) + out_tagoff(color); + return 0; +} + +//--------------------------------------------------------------------------- +uchar out_java_t::out_index(ushort index, fmt_t mode, color_t color, uchar as_index) +{ + if ( as_index ) + { + if ( !(pm().idpflags & (IDM_BADIDXSTR | IDM_OUTASM)) // no store in file + || !pm().is_valid_string_index(index) ) + { + return putShort(index); + } + color = COLOR_ERROR; + mode = fmt_string; + } + return OutUtf8(index, mode, color); +} + +//-------------------------------------------------------------------------- +uchar out_java_t::out_alt_ind(uint32 val) +{ + if ( (ushort)val ) + return OutUtf8((ushort)val, fmt_fullname, COLOR_IMPNAME); + return putShort((ushort)(val >> 16)); +} + +//-------------------------------------------------------------------------- +// special label format/scan procedures +//-------------------------------------------------------------------------- +void out_java_t::out_method_label(uchar is_end) +{ + set_gen_cmt(true); + set_gen_xrefs(true); + gen_printf(0, COLSTR("met%03u_%s%s", SCOLOR_CODNAME), pm().curSeg.id.Number, + is_end ? "end" : "begin", COLSTR(":", SCOLOR_SYMBOL)); +} + +//--------------------------------------------------------------------------- +char out_java_t::putMethodLabel(ushort off) +{ + char str[32]; + int len = qsnprintf(str, sizeof(str), "met%03u_%s", pm().curSeg.id.Number, + off ? "end" : "begin"); + + if ( !checkLine(len) ) + return 1; + out_tagon(COLOR_CODNAME); + outLine(str, len); + out_tagoff(COLOR_CODNAME); + return 0; +} + +//-------------------------------------------------------------------------- +// procedure for get_ref_addr +ssize_t java_t::check_special_label(const char *buf, size_t len) const +{ + if ( len >= sizeof("met000_end")-1 + && (*(uint32*)buf & 0xFFFFFF) == ('m'|('e'<<8)|('t'<<16)) ) + { + + switch ( *(uint32*)&buf[len -= 4] ) + { + case ('_'|('e'<<8)|('n'<<16)|('d'<<24)): + break; + case ('e'|('g'<<8)|('i'<<16)|('n'<<24)): + if ( len >= sizeof("met000_begin")-1 - 4 + && *(ushort*)&buf[len -= 2] == ('_'|('b'<<8)) ) + { + break; + } + // no break + default: + len |= -1; // as flag + break; + } + if ( len <= sizeof("met00000")-1 ) + { + size_t off = curSeg.CodeSize; + if ( buf[len+1] == 'b' ) + off = 0; + size_t n = 0; + size_t j = sizeof("met")-1; + while ( true ) + { + if ( !qisdigit((uchar)buf[j]) ) + break; + n = n*10 + (buf[j] - '0'); + if ( ++j == len ) + { + if ( n >= 0x10000 || (ushort)n != curSeg.id.Number ) + break; + return off; + } + } + } + } + return -1; +} + +//-------------------------------------------------------------------------- +// end of special-label procedures +//---------------------------------------------------------------------- +uchar out_java_t::outOffName(ushort off) +{ + if ( !off || off == pm().curSeg.CodeSize ) + return putMethodLabel(off); + if ( off < pm().curSeg.CodeSize ) + { + uchar err = 0; + if ( outName(pm().curSeg.start_ea + pm().curSeg.CodeSize, 0, + pm().curSeg.start_ea, off, &err) ) + return 0; // good + if ( err ) + return 1; // bad + } + return putShort(off, 0); +} + +//---------------------------------------------------------------------- +bool out_java_t::block_begin(uchar off) +{ + return flush_buf(COLSTR("{", SCOLOR_SYMBOL), off); +} + +//---------------------------------------------------------------------- +bool out_java_t::block_end(uint32 off) +{ + return flush_buf(COLSTR("}", SCOLOR_SYMBOL), off); +} + +//---------------------------------------------------------------------- +bool out_java_t::block_close(uint32 off, const char *name) +{ + if ( !jasmin() ) + return block_end(off); + return gen_printf(off, COLSTR(".end %s", SCOLOR_KEYWORD), name); +} + +//---------------------------------------------------------------------- +bool out_java_t::close_comment(void) +{ + return flush_buf(COLSTR("*/", SCOLOR_AUTOCMT), 0); +} + +//--------------------------------------------------------------------------- +uchar out_java_t::out_nodelist(uval_t nodeid, uchar pos, const char *pref) +{ + netnode node(nodeid); + uval_t cnt = node.altval(0); + if ( cnt == 0 ) + DESTROYED("out::nodelist"); + + uval_t off = 0; + if ( pref ) // jasmin + { + if ( change_line() ) + { +bad: + return 0; + } + off = strlen(pref); + } + + uint i = 0; + while ( true ) + { + if ( pref ) // jasmin (single directive per line) + { + pm().curpos = pos; + out_keyword(pref); + pm().outcnt = off; + } + else if ( i && chkOutSymSpace(',') ) + { + goto bad; // prompted list + } + if ( out_alt_ind((uint32)node.altval(++i)) ) + goto bad; + if ( i >= cnt ) + return 1; + if ( pref && change_line() ) + goto bad; // jasmin + } +} + +//---------------------------------------------------------------------- +void out_java_t::init_prompted_output(uchar pos) +{ + pm().maxpos = inf_get_margin(); +// if ( maxpos < 32 ) +// maxpos = 32; +// if ( maxpos > MAXSTR - 4 ) +// maxpos = MAXSTR - 4; + +#ifdef __debug__ + if ( debugmode == -1 + && inf.show_line_pref() && inf_get_margin() == 77 && !inf.bin_prefix_size ) + { + maxpos -= gl_psize; + } +#endif + pm().g_bufsize = (MAXSTR*2) - STR_PRESERVED; + pm().g_bufinited = true; + outbuf.qclear(); + outbuf.reserve(pm().g_bufsize); + pm().curpos = pos; + pm().outcnt = 0; +} + +//---------------------------------------------------------------------- +void out_java_t::term_prompted_output(void) +{ + outbuf.qclear(); + pm().g_bufinited = false; + pm().g_bufsize = 0; + pm().maxpos = 0; + pm().curpos = -1; +} + +//---------------------------------------------------------------------- +uchar out_java_t::OutConstant(const op_t &_x, bool include_descriptor) +{ + op_t x = _x; + fmt_t fmt = fmt_FieldDescriptor; + color_t color; + + insn_t cur_insn; + decode_insn(&cur_insn, insn_ea); + switch ( (uchar)x.cp_type ) + { + default: + warning("OC: bad constant type %u", (uchar)x.cp_type); + break; + + case CONSTANT_Long: + x.dtype = dt_qword; + goto outNum; + case CONSTANT_Double: + x.dtype = dt_double; + goto outNum; + case CONSTANT_Integer: + x.dtype = dt_dword; + goto outNum; + case CONSTANT_Float: + x.dtype = dt_float; +outNum: + if ( putVal(x, OOF_NUMBER | OOF_SIGNED | OOFW_IMM, 0) ) + break; +badconst: + return 0; + + case CONSTANT_Utf8: + if ( OutUtf8(x.cp_ind, fmt_string, COLOR_STRING) ) + goto badconst; + break; + + case CONSTANT_String: + if ( OutUtf8(x._name, fmt_string, COLOR_STRING) ) + goto badconst; + break; + + case CONSTANT_NameAndType: +nameandtype: + if ( OutUtf8(x._class, fmt_fullname) + || OutUtf8(x._name, fmt_fullname) ) + { + goto badconst; + } + break; + + case CONSTANT_InvokeDynamic: + { + const_desc_t invdyn; + if ( pm().ConstantNode.supval(x.cp_ind, &invdyn, sizeof(invdyn)) != sizeof(invdyn) ) + goto badconst; + // Retrieve NameAndType + const_desc_t nat; + if ( pm().ConstantNode.supval(invdyn._name, &nat, sizeof(nat)) != sizeof(nat) ) + goto badconst; + memset(&x, 0, sizeof(x)); + copy_const_to_opnd(x, nat); + x.ref = 0; + x.cp_type = nat.type; + x.cp_ind = invdyn._name; + goto nameandtype; + } + break; + + case CONSTANT_MethodHandle: + { + const_desc_t tmp; + if ( pm().ConstantNode.supval(x._mhr_index, &tmp, sizeof(tmp)) != sizeof(tmp) ) + goto badconst; + op_t tmpop; + memset(&tmpop, 0, sizeof(tmpop)); + copy_const_to_opnd(tmpop, tmp); + tmpop.ref = 0; // as flag + tmpop.cp_type = tmp.type; + tmpop.cp_ind = x._mhr_index; + OutConstant(tmpop, include_descriptor); + } + break; + + case CONSTANT_MethodType: + if ( OutUtf8(x._mtd_index, fmt_fullname, COLOR_KEYWORD) ) + goto badconst; + break; + + case CONSTANT_Class: + CASSERT((fmt_ClassName_or_Array+1) == fmt_ClassName && (fmt_ClassName+1) == fmt_fullname); + { + fmt_t f2 = (fmt_t )x.addr_shorts.high; + color_t c2 = f2 < fmt_ClassName_or_Array || f2 > fmt_fullname ? COLOR_KEYWORD + : cur_insn.xtrn_ip == 0xFFFF ? COLOR_DNAME : COLOR_IMPNAME; + + if ( OutUtf8(x._name, f2, c2) ) + goto badconst; + } + break; + + case CONSTANT_InterfaceMethodref: + case CONSTANT_Methodref: + fmt = fmt_method_ReturnType; + // fallthrough + case CONSTANT_Fieldref: +#ifdef VIEW_WITHOUT_TYPE + if ( include_descriptor ) +#endif + if ( !jasmin() && OutUtf8(x._dscr, fmt, COLOR_KEYWORD) ) + goto badconst; + color = x._class == pm().curClass.This.Dscr ? COLOR_DNAME : COLOR_IMPNAME; + out_tagon(color); + if ( jasmin() || (color == COLOR_IMPNAME && !include_descriptor) ) // other class + { + if ( OutUtf8(x._name, fmt_ClassName) || chkOutDot() ) + goto badconst; + } + if ( OutUtf8(x._subnam, fmt_UnqualifiedName) ) + goto badconst; // Field + out_tagoff(color); + if ( jasmin() ) + { + if ( fmt == fmt_method_ReturnType ) + fmt = fmt_FieldDescriptor_nospace; // no space at end + else if ( chkOutSpace() ) + goto badconst; + } + else + { + if ( fmt != fmt_method_ReturnType ) + break; + fmt = fmt_method_TypeSignature; + } + if ( OutUtf8(x._dscr, fmt, COLOR_KEYWORD) ) + goto badconst; + break; + } + return 1; +} + +//-------------------------------------------------------------------------- +// FIXME: there should be a better way of suppressing borders in disassembly +void out_java_t::myBorder(void) +{ + gen_empty_line(); + if ( pm().user_limiter ) + { + inf_set_limiter(LMT_THIN); + gen_border_line(false); + } + inf_set_limiter(0); // do not output border between method & vars :( +} + +//-------------------------------------------------------------------------- +uchar out_java_t::out_problems(char str[MAXSTR], const char *prefix) +{ + if ( pm().curClass.extflg & XFL_C_ERRLOAD ) + { + myBorder(); + gen_printf(DEFAULT_INDENT, + COLSTR("%s This class has had loading time problem(s)", SCOLOR_ERROR), + prefix); + if ( pm().curClass.msgNode ) + { + gen_empty_line(); + if ( pm().print_loader_messages(str, prefix, this) == -1 ) + return 1; + } + myBorder(); + } + return 0; +} + +//-------------------------------------------------------------------------- +uchar out_java_t::putScope(ushort scope, uint32 doff) +{ + if ( !scope || scope == pm().curSeg.CodeSize ) + return putMethodLabel(scope); + + if ( scope < pm().curSeg.CodeSize ) + { + uchar err = 0; + if ( outName(pm().curSeg.DataBase + doff, 0, pm().curSeg.start_ea, scope, &err) ) + return 0; + if ( err ) + return 1; + } + + return putShort(scope, 0); +} + +//---------------------------------------------------------------------- +size_t out_java_t::debLine(java_t &) +{ + out_char('"'); + out_tagoff(COLOR_STRING); + if ( change_line() ) + return 0; + return putDeb(1); +} + +//---------------------------------------------------------------------- +void out_java_t::OutKeyword(const char *str, size_t len) +{ + pm().outcnt += len; + out_keyword(str); +} + +//---------------------------------------------------------------------- +void out_java_t::outLine(const char *str, uint len) +{ + pm().outcnt += len; + out_line(str); +} + +//---------------------------------------------------------------------- +uchar out_java_t::chkOutDot(void) +{ + return chkOutChar('.'); +} + +//---------------------------------------------------------------------- +void out_java_t::OutSpace(void) +{ + ++pm().outcnt; + out_char(' '); +} + +//---------------------------------------------------------------------- +uchar out_java_t::chkOutSpace(void) +{ + return chkOutChar(' '); +} + +//-------------------------------------------------------------------------- +size_t out_java_t::putDeb(uchar next) +{ + OUT_KEYWORD(".debug "); + out_tagon(COLOR_STRING); + if ( next ) + out_char('"'); + return pm().maxpos - pm().outcnt; +} + +//---------------------------------------------------------------------- +bool out_java_t::out_operand(const op_t &x) +{ + int outf; + uchar warn = 0; + + switch ( x.type ) + { + case o_near: + if ( x.ref ) + { + ++warn; + } + else + { + if ( outName(insn.ea + x.offb, x.n, pm().curSeg.start_ea, x.addr, &warn) ) + break; + if ( warn ) + goto badop; + } + if ( putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32, warn) ) + break; + // no break + case o_void: +badop: + return false; + + case o_imm: + if ( x.ref == 2 ) + ++warn; + outf = OOFW_IMM | OOF_NUMBER | (x.ref ? OOFS_NOSIGN : OOF_SIGNED); + if ( putVal(x, outf, warn) ) + break; + goto badop; + + case o_mem: + if ( jasmin() ) + goto putidcv_num; + if ( x.ref ) + { +putAddr: + ++warn; + } + else + { + if ( outName(insn.ea + x.offb, x.n, pm().curSeg.DataBase, x.addr, &warn) ) + break; + if ( warn ) + goto badop; + } +putidcv_num: + if ( putVal(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16, warn) ) + break; + goto badop; + + case o_cpool: + if ( !x.cp_ind ) + { + OUT_KEYWORD("NULL"); + } + else + { + if ( x.ref ) + goto putAddr; + if ( !OutConstant(x) ) + goto badop; + } + break; + + case o_array: + if ( !x.ref ) + { + uchar btype = 0; + switch ( uchar(x.cp_type) ) + { + case T_BOOLEAN: btype = j_bool; break; + case T_CHAR: btype = j_char; break; + case T_FLOAT: btype = j_float; break; + case T_DOUBLE: btype = j_double; break; + case T_BYTE: btype = j_byte; break; + case T_SHORT: btype = j_short; break; + case T_INT: btype = j_int; break; + case T_LONG: btype = j_long; break; + } + const TXS *tname = get_base_typename(btype); + if ( tname == 0 || chkOutKeyword(tname->str, tname->size) ) + goto badop; + } + else + { + static const char tt_bogust[] = "BOGUST_TYPE-"; + + if ( !checkLine(sizeof(tt_bogust) + 2) ) + goto badop; + out_tagon(COLOR_ERROR); + size_t inplen = outbuf.length(); + out_printf("%c%s%u", WARN_SYM, tt_bogust, (uchar)x.cp_type); + pm().outcnt += outbuf.length() - inplen; + out_tagoff(COLOR_ERROR); + } + break; + + default: + warning("out: %a: bad optype %d", insn.ip, x.type); + break; + } + return true; +} + +//-------------------------------------------------------------------------- +void java_t::java_footer(outctx_t &ctx) +{ + if ( !jasmin() ) + { + out_java_t *p = (out_java_t *)&ctx; + p->block_end(0); + } +} diff --git a/idasdk75/module/java/oututil.hpp b/idasdk76/module/java/oututil.hpp similarity index 100% rename from idasdk75/module/java/oututil.hpp rename to idasdk76/module/java/oututil.hpp diff --git a/idasdk76/module/java/reg.cpp b/idasdk76/module/java/reg.cpp new file mode 100644 index 0000000..1ea50db --- /dev/null +++ b/idasdk76/module/java/reg.cpp @@ -0,0 +1,822 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "java.hpp" +#include <diskio.hpp> +#include <ieee.h> +#include "npooluti.hpp" +#include "notify_codes.hpp" +int data_id; + +//----------------------------------------------------------------------- +#ifdef __debug__ +NORETURN void _destroyed(const char *from) +{ + error("Database is corrupted! [at: %s]", from); +} + +//----------------------------------------------------------------------- +NORETURN void _faterr(uchar mode, const char *from) +{ + error("Internal error (%s) [at: %s]", + mode ? "compatibility" : "idp", + from); +} +#else +//----------------------------------------------------------------------- +NORETURN void _destroyed(void) +{ + error("Database is corrupted!"); +} + +//----------------------------------------------------------------------- +NORETURN void _faterr(uchar mode) +{ + error("Internal error (%s)", mode ? "compatibility" : "idp"); +} +#endif + +//----------------------------------------------------------------------- +void java_t::sm_validate(const SegInfo *si) +{ + ea_t segTopEA = si->start_ea + si->CodeSize; + netnode temp(si->smNode); + nodeidx_t nid = temp.supfirst(); + + if ( (ea_t)nid < si->start_ea ) + goto destroyed; + + do + { + if ( (ea_t)nid >= segTopEA ) + goto destroyed; + if ( temp.supval(nid, NULL, 0) != sizeof(sm_info_t) ) + goto destroyed; + if ( !is_head(get_flags((ea_t)nid)) ) + { + remember_problem(PR_HEAD, (ea_t)nid); + if ( !displayed_nl ) + { + displayed_nl = true; + msg("\n"); + } + msg("StackMap refers to nonHead offset %X in Method#%u\n", + (uint32)((ea_t)nid - si->start_ea), si->id.Number); + } + nid = temp.supnext(nid); + } + while ( nid != BADNODE ); + return; + +destroyed: + DESTROYED("sm_validate"); +} + +//---------------------------------------------------------------------- +// visble for upgrade ONLY +void java_t::coagulate_unused_data(const SegInfo *ps) +{ + uint size = 0; + ea_t ea = ps->DataBase; + ea_t top = ea + ps->DataSize; + for ( ; ea < top; ea++ ) + { + if ( is_head(get_flags(ea)) + && get_first_dref_to(ea) == BADADDR ) + { + ConstantNode.chardel(ea, UR_TAG); // unicode renaming support + del_global_name(ea); + del_items(ea, DELIT_SIMPLE); + ++size; + ea_t to; + while ( (to=get_first_dref_from(ea)) != BADADDR ) + del_dref(ea, to); + } + else if ( size ) + { + create_data(ea-size, align_flag(), size, BADNODE); + size = 0; + } + } + if ( size ) + create_data(ea-size, align_flag(), size, BADNODE); +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +static int idaapi out_asm_file( + FILE *fp, + const qstring &line, + bgcolor_t, + bgcolor_t) +{ + qstring qbuf; + tag_remove(&qbuf, line); + size_t len = qbuf.length(); + size_t chk = len; + + if ( qbuf.last() == '\\' ) + --len; + if ( qfwrite(fp, qbuf.c_str(), len) != len ) + return 0; + if ( chk == len && qfputc('\n', fp) == EOF ) + return 0; + return 1; +} + +//---------------------------------------------------------------------- +static void idaapi func_header(outctx_t &ctx, func_t *) { ctx.ctxflags |= CTXF_LABEL_OK; } +static void idaapi func_footer(outctx_t &, func_t *) {} +static bool idaapi java_specseg(outctx_t &ctx, uchar) { java_data(ctx, false); return false; } + +//---------------------------------------------------------------------- +// floating point conversion +fpvalue_error_t idaapi j_realcvt(void *m, fpvalue_t *e, ushort swt) +{ + return ieee_realcvt(m, e, swt | 0x80); +} + +//---------------------------------------------------------------------- +// Set IDP options. Either from the configuration file either allow the user +// to specify them in a dialog box. +const char *java_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + static const char form[] = + "HELP\n" + "JAVA specific options\n" + "\n" + " Multiline .debug\n" + "\n" + " If this option is on, IDA forces new .debug directive at every\n" + " LR ('\\n') in the input string\n" + "\n" + " Hide StackMap(s)\n" + "\n" + " If this option is on, IDA hides .stack verification declarations\n" + "\n" + " Auto strings\n" + "\n" + " If this option is on, IDA makes 'prompt-string' after every CR in\n" + " the quoted-string operand\n" + "\n" + " Save to jasmin\n" + "\n" + " If this option is on, IDA creates asm-file in the jasmin-\n" + " compatibe form: concatenates 'prompted' string, reserved names\n" + " will be enclosed in quotes.\n" + " Also when this option is on IDA changes unicode-to-oem encoding to\n" + " unicode-to-ansi encoding because jasmin expects ansi encoding.\n" + "\n" + " Enable encoding\n" + "\n" + " If this option is on, IDA converts unicode characters which\n" + " can't be represented in current locale to ascii characters.\n" + "\n" + " Nopath .attribute\n" + " If this option is on, IDA prints filename in '.attribute'\n" + " directives without the path part.\n" + "\n" + "\n" + " Bad index as string\n" + " If this option is on, IDA will show invalid name/type references\n" + " as a quoted string.\n" + "ENDHELP\n" + "JAVA specific options\n" + "\n" + " <~M~ultilne .debug :C>\n" + " <~H~ide StackMap(s) :C>\n" + " <~A~uto strings :C>\n" + " <~S~ave to jasmin :C>\n" + " <~E~nable encoding :C>\n" + " <~N~opath .attribute :C>>\n" + "\n" + " <~B~ad index as string :C>>\n" + "\n" + "\n"; + + if ( !keyword ) + { + ushort tmp = (idpflags >> 16) & IDM__REQMASK; + ushort flags = idpflags; + if ( ask_form(form, &flags, &tmp) ) + { + int32 old = idpflags; + idpflags = (flags & ~(IDM__REQMASK << 16)) | (tmp << 16); + if ( (idpflags ^ old) & IDF_ENCODING ) + rename_uninames(-1); + } + goto SAVE; + } + + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + + struct keyword_info_t + { + const char *name; + int bit; + }; + static const keyword_info_t keywords[] = + { + { "JAVA_MULTILINE_DEBUG", IDF_MULTDEB }, + { "JAVA_HIDE_STACKMAP", IDF_HIDESM }, + { "JAVA_AUTO_STRING", IDF_AUTOSTR }, + { "JAVA_ASMFILE_CONVERT", IDF_CONVERT }, + { "JAVA_ENABLE_ENCODING", IDF_ENCODING }, + { "JAVA_NOPATH_ATTRIBUTE", IDF_NOPATH }, + { "JAVA_UNKATTR_REQUEST", IDM_REQUNK }, + { "JAVA_UNKATTR_WARNING", IDM_WARNUNK }, + }; + + for ( int i=0; i < qnumber(keywords); i++ ) + { + if ( strcmp(keywords[i].name, keyword) == 0 ) + { + setflag(idpflags, keywords[i].bit, *(int*)value != 0); + goto SAVE; + } + } + + if ( streq(keyword, "JAVA_STARTASM_LIST") ) + { + start_asm_list = *(int*)value; + return IDPOPT_OK; + } + else + { + return IDPOPT_BADKEY; + } +SAVE: + if ( idb_loaded ) + ConstantNode.altset(CNA_IDPFLAGS, (ushort)idpflags); + return IDPOPT_OK; + +} + +//---------------------------------------------------------------------- +static const asm_t jasmin_asm = +{ + AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3, + UAS_JASMIN, + "Jasmin assembler", + 0, // no help screen + NULL, // header + NULL, // origin + NULL, // end of file + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'\\", // special symbols in char and string constants + + "", // ascii string directive + "", // byte directive + NULL, // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float + NULL, // double + NULL, // no tbytes + NULL, // no packreal + NULL, // arrays: + // #h - header(.byte,.word) + // #d - size of array + // #v - value of array elements + NULL, //".reserv %s", // uninited data (reserve space) + " = ", // equ + NULL, // seg prefix + NULL, // a_curip + func_header, // func header + func_footer, // func footer + "", // public (disable ouput) + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + NULL, // a_include_fmt + NULL, // a_vstruc_fmt + NULL, // a_rva +}; + +//---------------------------------------------------------------------- +static const asm_t list_asm = +{ + AS_COLON | ASH_HEXF3 | ASO_OCTF1 | ASD_DECF0 | AS_ONEDUP | ASB_BINF3, + 0, + "User friendly listing", + 0, // no help screen + NULL, // header + NULL, // origin + NULL, // end of file + + "//", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'\\", // special symbols in char and string constants + + "", // ascii string directive + "", // byte directive + NULL, // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float + NULL, // double + NULL, // no tbytes + NULL, // no packreal + NULL, // arrays: + // #h - header(.byte,.word) + // #d - size of array + // #v - value of array elements + NULL, //".reserv %s", // uninited data (reserve space) + " = ", // equ + NULL, // seg prefix + NULL, // a_curip + func_header, // func header + func_footer, // func footer + "", // public (disable ouput) + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + NULL, // a_include_fmt + NULL, // a_vstruc_fmt + NULL, // a_rva +}; + +//----------------------------------------------------------------------- +static const asm_t *const asms[] = { &jasmin_asm, &list_asm, NULL }; + +static const char *const RegNames[] = { "vars", "optop", "frame", "cs", "ds" }; + +#define FAMILY "Java Virtual Machine:" + +static const char *const shnames[] = +{ + "java", +#ifdef __debug__ + "_javaPC", +#endif + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Java", +#ifdef __debug__ + "Java full (IBM PC, debug mode)", +#endif + NULL +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { j_ret }; +static const uchar retcode_1[] = { j_ireturn }; +static const uchar retcode_2[] = { j_lreturn }; +static const uchar retcode_3[] = { j_freturn }; +static const uchar retcode_4[] = { j_dreturn }; +static const uchar retcode_5[] = { j_areturn }; +static const uchar retcode_6[] = { j_return }; +static const uchar retcode_7[] = { j_wide, j_ret }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { sizeof(retcode_4), retcode_4 }, + { sizeof(retcode_5), retcode_5 }, + { sizeof(retcode_6), retcode_6 }, + { sizeof(retcode_7), retcode_7 }, + { 0, NULL } +}; + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) +{ + switch ( code ) + { + case idb_event::closebase: + memset(&pm.curClass, 0, sizeof(pm.curClass)); + // no break + case idb_event::savebase: + pm.ConstantNode.altset(CNA_IDPFLAGS, (ushort)pm.idpflags); + break; + + case idb_event::auto_empty: + if ( !(pm.curClass.extflg & XFL_C_DONE) ) // kernel BUGs + { + pm.curClass.extflg |= XFL_C_DONE; + msg("JavaLoader finalization stage..."); + for ( int n = pm.curClass.MethodCnt; n; n-- ) + { + SegInfo si; + if ( pm.ClassNode.supval(-n, &si, sizeof(si)) != sizeof(si) ) + DESTROYED("postprocess"); + if ( si.smNode || si.DataSize ) + { + show_addr(si.start_ea); + if ( si.smNode ) + pm.sm_validate(&si); + if ( si.DataSize ) + pm.coagulate_unused_data(&si); + } + } + pm.ConstantNode.supset(CNS_CLASS, &pm.curClass, sizeof(pm.curClass)); // all chgs + pm.sm_node = smn_ok; + msg("OK\n"); + } + break; + } + return 0; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(java_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi java_t::on_event(ssize_t msgid, va_list va) +{ + int retcode = 0; + switch ( msgid ) + { + case processor_t::ev_init: + hook_event_listener(HT_IDB, &idb_listener, &LPH); + inf_set_be(true); // reverse byte! + break; + + case processor_t::ev_rename: + va_arg(va, ea_t); + for ( char const *pn, *p = va_arg(va, const char *); + (pn = strchr(p, '\\')) != NULL; + p = pn+1 ) + { + if ( *++pn != 'u' ) + { +inv_name: + --retcode; // 0 + warning("Backslash is accepted only as a unicode escape sequence in names"); + break; + } + for ( int i = 0; i < 4; i++ ) + if ( !qisxdigit((uchar)*++pn) ) + goto inv_name; + } + break; + + case processor_t::ev_newfile: + if ( inf_get_filetype() != f_LOADER ) + { + set_database_flag(DBFL_KILL); // clean up the database files + error("The input file does not have a supported Java file format"); + } + database_loaded (va_arg(va, char *)); + inf_set_lowoff(BADADDR); + inf_set_highoff(BADADDR); + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + database_loaded(NULL); + break; + + case processor_t::ev_term: + unhook_event_listener(HT_IDB, &idb_listener); + qfree(tsPtr); + qfree(smBuf); + qfree(annBuf); + clr_module_data(data_id); + break; + +#ifdef __debug__ + case processor_t::ev_newprc: + { + int procnum = va_arg(va, int); + bool keep_cfg = va_argi(va, bool); + if ( procnum == 1 ) // debug mode + { + ph.flag &= ~(PR_DEFNUM | PR_NOCHANGE); + ph.flag |= PRN_HEX; + if ( inf_get_margin() == 77 && !inf.bin_prefix_size && !inf.show_line_pref() ) + { + if ( !keep_cfg ) + inf_set_show_line_pref(true); + --debugmode; + } + else + { + ++debugmode; + } + } + else // normal node + { + ph.flag &= ~PR_DEFNUM; + ph.flag |= PRN_DEC; + if ( debugmode == -1 + && inf.show_line_pref() + && !inf.bin_prefix_size + && inf_get_margin() == 77 + && !keep_cfg ) + { + inf.show_line_pref(false); + } + debugmode = 0; + } + } + break; +#endif + + case java_module_t::ev_load_file: + { + linput_t *li = va_arg(va, linput_t *); + FILE *f = qlfile(li); + QASSERT(10082, f != NULL); + bool manual = va_argi(va, bool); + loader(f, manual); + retcode = 0; + } + if ( start_asm_list ) + set_target_assembler(1); + break; + + case processor_t::ev_gen_src_file_lnnum: + if ( jasmin() ) + { + outctx_t *ctx = va_arg(va, outctx_t *); + va_arg(va, const char *); // skip file name + size_t lineno = va_arg(va, size_t); + ctx->gen_printf(2, COLSTR(".line %" FMT_Z, SCOLOR_ASMDIR), lineno); + retcode = 1; + } + break; + + case processor_t::ev_gen_asm_or_lst: + { + if ( va_argi(va, bool) ) // starting (else end of generation ) + { + va_arg(va, FILE *); // output file (skip) + bool isasm = va_argi(va, bool); // assembler-true, listing-false + if ( isasm && (idpflags & IDF_CONVERT) ) + { + va_arg(va, int); // flags of gen_file() (skip) + *va_arg(va, gen_outline_t**) = out_asm_file; + idpflags |= IDM_OUTASM; + } + if ( isasm == jasmin() ) + break; // need change mode? + } + else // end of generation. + { + idpflags &= ~IDM_OUTASM; + if ( !mode_changed ) + break; // mode changed? + } + mode_changed = !mode_changed; + set_target_assembler(!inf_get_asmtype()); + } + break; + + case processor_t::ev_get_autocmt: + { + qstring *buf = va_arg(va, qstring *); + const insn_t *insn = va_arg(va, insn_t *); + if ( make_locvar_cmt(buf, *insn) ) + retcode = 1; + } + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + java_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + java_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + java_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + java_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + java_data(*ctx, analyze_only); + return 1; + } + + case processor_t::ev_can_have_type: + { + const op_t *op = va_arg(va, const op_t *); + return can_have_type(*op) ? 1 : -1; + } + + case processor_t::ev_realcvt: + { + void *m = va_arg(va, void *); + fpvalue_t *e = va_arg(va, fpvalue_t *); + uint16 swt = va_argi(va, uint16); + fpvalue_error_t code = j_realcvt(m, e, swt); + return code == REAL_ERROR_OK ? 1 : code; + } + + case processor_t::ev_gen_map_file: + { + int *nlines = va_arg(va, int *); + FILE *fp = va_arg(va, FILE *); + int code = gen_map_file(fp); + if ( code == -1 ) + return -1; + *nlines = code; + return 1; + } + + case processor_t::ev_extract_address: + { + ea_t *out_ea = va_arg(va, ea_t *); + ea_t screen_ea = va_arg(va, ea_t); + const char *str = va_arg(va, const char *); + size_t pos = va_arg(va, size_t); + ea_t ea = get_ref_addr(screen_ea, str, pos); + if ( ea == BADADDR ) + return -1; + if ( ea == (BADADDR-1) ) + return 0; + *out_ea = ea; + return 1; + } + + case processor_t::ev_out_special_item: + { + outctx_t *ctx = va_arg(va, outctx_t *); + uchar seg_type = va_argi(va, uchar); + java_specseg(*ctx, seg_type); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + default: + break; + } + return retcode; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_JAVA, // id + // flag + PRN_DEC + | PR_RNAMESOK + | PR_NO_SEGMOVE, + // flag2 + PR2_REALCVT // the module has 'realcvt' event implementation + | PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 0, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0,j_last, + Instructions, // instruc + 0, // size of tbyte + {0,7,15,0}, // real width + j_ret, // icode_return + NULL, // Micro virtual machine description +}; diff --git a/idasdk75/module/java/resword.cpp b/idasdk76/module/java/resword.cpp similarity index 100% rename from idasdk75/module/java/resword.cpp rename to idasdk76/module/java/resword.cpp diff --git a/idasdk75/module/java/resword.hpp b/idasdk76/module/java/resword.hpp similarity index 100% rename from idasdk75/module/java/resword.hpp rename to idasdk76/module/java/resword.hpp diff --git a/idasdk76/module/java/upgrade.cpp b/idasdk76/module/java/upgrade.cpp new file mode 100644 index 0000000..86bbb0e --- /dev/null +++ b/idasdk76/module/java/upgrade.cpp @@ -0,0 +1,391 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * JVM module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "java.hpp" +#include "upgrade.hpp" +#include "oututil.hpp" + +//---------------------------------------------------------------------- +#define _TO_VERSION IDP_JDK16 + +//---------------------------------------------------------------------- +void java_t::make_new_name(ushort name, ushort subnam, uchar mode, uint ip) +{ + out_java_t *pctx = (out_java_t *)create_outctx(BADADDR); + if ( pctx->fmtString(*this, name, MAXNAMELEN-2, fmt_fullname) ) + { +trunc: + pctx->trunc_name(ip, mode & 4); + } + else if ( (char)mode > 0 ) + { + size_t len = pctx->outbuf.length(); + if ( len >= (MAXNAMELEN-3) ) + goto trunc; + pctx->out_char(' '); + if ( pctx->fmtString(*this, subnam, (MAXNAMELEN-2) - len, fmt_UnqualifiedName) ) + goto trunc; + } + force_name(ip, convert_clsname(pctx->outbuf.begin())); + delete pctx; + hide_name(ip); +} + +//---------------------------------------------------------------------- +int java_t::upgrade_db_format(int ver, netnode constnode) +{ + if ( ask_yn(ASKBTN_YES, + "AUTOHIDE REGISTRY\nHIDECANCEL\n" + "The database has an old java data format.\n" + "Do you want to upgrade it?") <= ASKBTN_NO ) + { + qexit(1); + } + + switch ( ver ) + { + default: + INTERNAL("upgrade::ver"); + case IDP_JDK12: + break; + } + + // change format: jdk-version + if ( curClass.MinVers > 0x8000u ) + { +BADIDB: + return 0; + } + + curClass.MajVers = JDK_MIN_MAJOR; + if ( curClass.MinVers >= 0x8000 ) + { + curClass.MinVers &= ~0; + ++curClass.MajVers; + curClass.JDKsubver = 2; + } + else if ( curClass.MinVers >= JDK_1_1_MINOR ) + { + ++curClass.JDKsubver; + } + +// change format: This + CASSERT(offsetof(ClassInfo, This.Ref) == offsetof(ClassInfo, This.Name) + && offsetof(ClassInfo, This.Dscr) == offsetof(ClassInfo, This.Name) + 2); + + curClass.This.Ref = (curClass.This.Ref << 16) | curClass.This.Dscr; + if ( !curClass.This.Name ) + goto BADIDB; + +// change format: Super + CASSERT(offsetof(ClassInfo, super.Ref) == offsetof(ClassInfo, super.Name) + && offsetof(ClassInfo, super.Dscr) == offsetof(ClassInfo, super.Name) + 2); + switch ( curClass.super.Name ) + { + case 0: // absent + curClass.super.Ref &= 0; + break; + case 0xFFFF: // bad index + ++curClass.super.Name; + break; + default: // reverse order + curClass.super.Ref = (curClass.super.Ref << 16) | curClass.super.Dscr; + break; + } + +// validate: impNode + if ( curClass.impNode && !netnode(curClass.impNode).altval(0) ) + goto BADIDB; + +// change variable 'errload' in previous version + if ( curClass.maxSMsize ) + { + curClass.extflg |= XFL_C_ERRLOAD; + curClass.maxSMsize &= 0; + } + +// set segments type type for special segments + segment_t *S = getseg(curClass.start_ea); + if ( S == NULL ) + goto BADIDB; + S->set_hidden_segtype(true); + S->update(); + if ( curClass.xtrnCnt ) + { + S = getseg(curClass.xtrnEA); + if ( S == NULL ) + goto BADIDB; + S->set_hidden_segtype(true); + S->update(); + } + + curClass.extflg |= XFL_C_DONE; // do not repeat datalabel destroyer :) +// change: method/fields format +#define SGEXPSZ (sizeof(SegInfo) - offsetof(SegInfo, varNode)) +#define FMEXPSZ (sizeof(_FMid_) - offsetof(_FMid_, _UNUSED_ALING)) +#define FLEXPSZ (sizeof(FieldInfo) - offsetof(FieldInfo, annNodes)) + uval_t oldsize = sizeof(SegInfo) - FMEXPSZ - SGEXPSZ; + + for ( int pos = -(int)curClass.MethodCnt; pos <= (int)curClass.FieldCnt; pos++ ) + { + union + { + SegInfo s; + FieldInfo f; + _FMid_ id; + uchar _space[qmax(sizeof(SegInfo), sizeof(FieldInfo)) + 1]; //lint !e754 not referenced + } u; + + if ( !pos ) // class node + { + oldsize += (sizeof(FieldInfo) - FLEXPSZ) - (sizeof(SegInfo) - SGEXPSZ); + continue; + } + + if ( ClassNode.supval(pos, &u, sizeof(u)) != oldsize ) + goto BADIDB; + + memmove((uchar *)&u.id + sizeof(u.id), &u.id._UNUSED_ALING, + (size_t)oldsize - offsetof(_FMid_, _UNUSED_ALING)); + u.id._UNUSED_ALING = 0; + u.id.utsign = 0; + + if ( u.id.extflg & ~EFL__MASK ) + goto BADIDB; + u.id.extflg &= (EFL_NAMETYPE); + + if ( pos > 0 ) // fields + { + memset(u.f.annNodes, 0, sizeof(u.f)-offsetof(FieldInfo, annNodes)); + ClassNode.supset(pos, &u.f, sizeof(u.f)); + continue; + } + + // segments + memset(&u.s.varNode, 0, sizeof(u.s) - offsetof(SegInfo, varNode)); + if ( u.s.thrNode && !netnode(u.s.thrNode).altval(0) ) + { + netnode(u.s.thrNode).kill(); // empty node (old format) + u.s.thrNode = 0; + } + + // have locvars? + if ( u.s.DataSize ) + { + S = getseg(u.s.DataBase); + if ( S == NULL ) + goto BADIDB; + S->type = SEG_BSS; + S->set_hidden_segtype(true); + S->update(); + } + + // change: Exception format + if ( u.s.excNode ) + { + netnode enode(u.s.excNode); + ushort j = (ushort)enode.altval(0); + if ( j == 0 ) + goto BADIDB; + ea_t ea = u.s.start_ea + u.s.CodeSize; + ushort i = 1; + do + { + Exception exc; + + if ( enode.supval(i, &exc, sizeof(exc)) != sizeof(exc) ) + goto BADIDB; + + CASSERT(offsetof(Exception, filter.Ref) == offsetof(Exception, filter.Name) + && offsetof(Exception, filter.Dscr) == offsetof(Exception, filter.Name) + 2); + if ( !exc.filter.Name != !exc.filter.Dscr ) + goto BADIDB; + exc.filter.Ref = (exc.filter.Ref << 16) | exc.filter.Dscr; // was reverse order + if ( exc.filter.Name == 0xFFFF ) + ++exc.filter.Name; + enode.supset(i, &exc, sizeof(exc)); + set_exception_xref(&u.s, exc, ea); + } + while ( ++i <= j ); + } + ClassNode.supset(pos, &u.s, sizeof(u.s)); + // rename local variables (for references) + if ( u.s.DataSize ) + { + int i = u.s.DataSize; + ea_t ea = u.s.DataBase + i; + do + { + char str[MAXNAMELEN]; + qsnprintf(str, sizeof(str), "met%03u_slot%03d", u.s.id.Number, --i); + --ea; + if ( force_name(ea, str) ) + make_name_auto(ea); + else + hide_name(ea); + } + while ( i > 0 ); + coagulate_unused_data(&u.s); + } + } // for + + // change format of string presentation in constant pool + FOR_EACH_CONSTANT_POOL_INDEX(pos) + { + const_desc_t co; + if ( constnode.supval(pos, &co, sizeof(co)) != sizeof(co) ) + goto BADIDB; + switch ( co.type ) + { + default: + continue; + + case CONSTANT_Unicode: + error("Base contain CONSTANT_Unicode, but it is removed from " + "the standard in 1996 year and never normal loaded in IDA"); + + case CONSTANT_Utf8: + break; + } + uint32 v, i = pos << 16; + uint32 n = (uint32)constnode.altval(i); + if ( (n & UPG12_BADMASK) != 0 || (v = n & ~UPG12_CLRMASK) == 0 ) + goto BADIDB; + if ( n & UPG12_EXTMASK ) + v |= UPG12_EXTSET; + n = ushort(v); + if ( n != 0 ) + { + uchar *po = (uchar*)append_tmp_buffer(v); + n *= sizeof(ushort); + uint32 idx = 0; + do + { + uint32 sz = n - idx; + if ( sz > MAXSPECSIZE ) + sz = MAXSPECSIZE; + if ( constnode.supval(++i, &po[idx], sz) != sz ) + goto BADIDB; + constnode.supdel(i); + idx += sz; + } + while ( idx < n ); + constnode.setblob(po, n, i & ~0xFFFF, BLOB_TAG); + if ( !(v & UPG12_EXTSET) ) + { + do + { + CASSERT((sizeof(ushort) % 2) == 0 && (MAXSPECSIZE % 2) == 0); + ushort cw = *(ushort *)&po[idx]; + if ( cw >= CHP_MAX ) + { + if ( !javaIdent(cw) ) + goto extchar; + } + else if ( (uchar)cw <= CHP_MIN ) + { +extchar: + v |= UPG12_EXTSET; + break; + } + } + while ( (idx -= sizeof(ushort)) != 0 ); + } + v = upgrade_ResW(v); + } + constnode.altset(i, v); + co._Sopstr = v; // my be not needed? (next also) + constnode.supset(pos, &co, sizeof(co)); + } + +// rename 'import' variables for refernces + for ( uint ip = 1; (ushort)ip <= curClass.xtrnCnt; ip++ ) + { + const_desc_t co; + { + uint j = (uint)XtrnNode.altval(ip); + if ( j == 0 || !LoadOpis(lm_lenient, (ushort)j, 0, &co) ) + goto BADIDB; + } + switch ( co.type ) + { + default: + goto BADIDB; + + case CONSTANT_Class: + if ( !(co.flag & HAS_CLSNAME) ) + continue; + break; + case CONSTANT_InterfaceMethodref: + case CONSTANT_Methodref: + if ( (co.flag & NORM_METOD) != NORM_METOD ) + continue; + break; + case CONSTANT_Fieldref: + if ( (co.flag & NORM_FIELD) != NORM_FIELD ) + continue; + break; + } + make_new_name(co._name, co._subnam, co.type != CONSTANT_Class, ip); + } + + if ( curClass.This.Dscr ) + make_new_name(curClass.This.Name, 0, (uchar)-1, (uint)curClass.start_ea); + + return _TO_VERSION; +} + +//----------------------------------------------------------------------- +//---------------------------------------------------------------------- +// some utilities (size of npool) +//---------------------------------------------------------------------- +// visible for converter only +char *java_t::convert_clsname(char *buf) const +{ + if ( jasmin() ) + for ( char *p = buf; (p = strchr(p, j_clspath_dlm)) != NULL; p++ ) + *p = j_field_dlm; + + return buf; +} + +//----------------------------------------------------------------------- +// visible for converter only +uchar set_exception_xref(SegInfo *ps, Exception const & exc, ea_t ea) +{ + uchar ans = 0; + + if ( exc.start_pc >= ps->CodeSize ) + { + ans = 1; + } + else + { + if ( !exc.start_pc ) + ps->id.extflg |= XFL_M_LABSTART; // special label at entry + add_dref(ea, ps->start_ea + exc.start_pc, dr_I); + } + if ( exc.end_pc > ps->CodeSize ) + { + ans = 1; + } + else + { + if ( exc.end_pc == ps->CodeSize ) + ps->id.extflg |= XFL_M_LABEND; // special label at end + add_dref(ea, ps->start_ea + exc.end_pc, dr_I); + } + if ( exc.handler_pc >= ps->CodeSize ) + return 1; + add_dref(ea, ps->start_ea + exc.handler_pc, dr_I); + return ans; +} diff --git a/idasdk75/module/java/upgrade.hpp b/idasdk76/module/java/upgrade.hpp similarity index 100% rename from idasdk75/module/java/upgrade.hpp rename to idasdk76/module/java/upgrade.hpp diff --git a/idasdk75/module/kr1878/ana.cpp b/idasdk76/module/kr1878/ana.cpp similarity index 100% rename from idasdk75/module/kr1878/ana.cpp rename to idasdk76/module/kr1878/ana.cpp diff --git a/idasdk75/module/kr1878/emu.cpp b/idasdk76/module/kr1878/emu.cpp similarity index 100% rename from idasdk75/module/kr1878/emu.cpp rename to idasdk76/module/kr1878/emu.cpp diff --git a/idasdk75/module/kr1878/ins.cpp b/idasdk76/module/kr1878/ins.cpp similarity index 100% rename from idasdk75/module/kr1878/ins.cpp rename to idasdk76/module/kr1878/ins.cpp diff --git a/idasdk75/module/kr1878/ins.hpp b/idasdk76/module/kr1878/ins.hpp similarity index 100% rename from idasdk75/module/kr1878/ins.hpp rename to idasdk76/module/kr1878/ins.hpp diff --git a/idasdk76/module/kr1878/kr1878.cfg b/idasdk76/module/kr1878/kr1878.cfg new file mode 100644 index 0000000..9350df8 --- /dev/null +++ b/idasdk76/module/kr1878/kr1878.cfg @@ -0,0 +1,19 @@ + +; This file describes the standard addresses for Angstrem KR1878 + +.default kr1878 + +.kr1878 + +ST 0x00 +PortA 0x01 +PortB 0x02 +TCtl 0x04 +Twrk 0x05 +PCtlA 0x19 +PCtlB 0x1A +WDCtl 0x1D +EEPCtl 0x38 +EEPLoA 0x39 +EEPHiA 0x3A +EEPData 0x3F diff --git a/idasdk76/module/kr1878/kr1878.hpp b/idasdk76/module/kr1878/kr1878.hpp new file mode 100644 index 0000000..230f070 --- /dev/null +++ b/idasdk76/module/kr1878/kr1878.hpp @@ -0,0 +1,124 @@ + +#ifndef _KR1878_HPP +#define _KR1878_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> + +//------------------------------------------------------------------ + +#define amode specflag2 // addressing mode +#define amode_x 0x10 // X: + +//------------------------------------------------------------------ +#define UAS_GNU 0x0001 // GNU assembler +//------------------------------------------------------------------ +enum RegNo +{ + SR0, + SR1, + SR2, + SR3, + SR4, + SR5, + SR6, + SR7, + DSP, + ISP, + as, + bs, + cs, + ds, + vCS, vDS, // virtual registers for code and data segments + +}; + + +//------------------------------------------------------------------ + +struct addargs_t +{ + ea_t ea; + int nargs; + op_t args[4][2]; +}; + + +//------------------------------------------------------------------ +#define IDP_SIMPLIFY 0x0001 // simplify instructions +#define IDP_PSW_W 0x0002 // W-bit in PSW is set + +extern ushort idpflags; + +inline bool dosimple(void) { return (idpflags & IDP_SIMPLIFY) != 0; } +inline bool psw_w(void) { return (idpflags & IDP_PSW_W) != 0; } + +ea_t calc_mem(const insn_t &insn, const op_t &x); + +//------------------------------------------------------------------ +void interr(const insn_t &insn, const char *module); + +void idaapi kr1878_header(outctx_t &ctx); + +void idaapi kr1878_segend(outctx_t &ctx, segment_t *seg); + +int idaapi is_align_insn(ea_t ea); +int idaapi is_sp_based(const insn_t &insn, const op_t &x); + +int is_jump_func(const func_t *pfn, ea_t *jump_target); +int is_sane_insn(const insn_t &insn, int nocrefs); +int may_be_func(const insn_t &insn); // can a function start here? + +void init_analyzer(void); + +//------------------------------------------------------------------ +struct kr1878_t : public procmod_t +{ + ioports_t ports; + qstring device; + netnode helper; + ea_t xmem = BADADDR; + op_t *op = nullptr; // current operand + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const ioport_t *find_port(ea_t address); + void read_kr1878_cfg(void); + void set_device_name(const char *dev); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + + ea_t calc_data_mem(const insn_t &insn, const op_t &x, ushort segreg) const; + void handle_operand(const insn_t &insn, const op_t &x, bool isAlt, bool isload); + void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); + int emu(const insn_t &insn); + + void opreg(uint16 reg); + void make_o_mem(const insn_t &insn); + bool D_ddddd(const insn_t &, int value); + bool S_ddddd(const insn_t &insn, int value); + bool D_SR(const insn_t &, int value); + bool S_SR(const insn_t &insn, int value); + bool D_Imm(const insn_t &, int value); + bool D_pImm(const insn_t &insn, int value); + bool D_EA(const insn_t &insn, int value); + bool use_table(const insn_t &insn, uint32 code, int entry, int start, int end); + int ana(insn_t *_insn); + + void kr1878_assumes(outctx_t &ctx); + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void kr1878_segstart(outctx_t &ctx, segment_t *Srange) const; + void kr1878_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ kr1878" +#define PROCMOD_NAME kr1878 +#endif // _KR1878_HPP diff --git a/idasdk76/module/kr1878/makefile b/idasdk76/module/kr1878/makefile new file mode 100644 index 0000000..1e21757 --- /dev/null +++ b/idasdk76/module/kr1878/makefile @@ -0,0 +1,53 @@ +PROC=kr1878 +CONFIGS=kr1878.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + kr1878.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)frame.hpp $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + emu.cpp ins.hpp kr1878.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ + kr1878.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp kr1878.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp kr1878.hpp reg.cpp diff --git a/idasdk75/module/kr1878/out.cpp b/idasdk76/module/kr1878/out.cpp similarity index 100% rename from idasdk75/module/kr1878/out.cpp rename to idasdk76/module/kr1878/out.cpp diff --git a/idasdk76/module/kr1878/reg.cpp b/idasdk76/module/kr1878/reg.cpp new file mode 100644 index 0000000..e82122a --- /dev/null +++ b/idasdk76/module/kr1878/reg.cpp @@ -0,0 +1,503 @@ + +#include <ctype.h> +#include "kr1878.hpp" +#include <diskio.hpp> +#include <entry.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + // data arithmetic logic unit + "SR0", "SR1", "SR2", "SR3", + "SR4", "SR5", "SR6", "SR7", + "DSP", "ISP", + "a", "b", "c", "d", + "cs","ds", // virtual registers for code and data segments +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0x0c, 0x00 }; +static const uchar retcode_1[] = { 0x0d, 0x00 }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//-------------------------------------------------------------------------- +struct interrupt_t +{ + int offset; + const char *name; //lint !e958 padding is required to align members +}; + +static const interrupt_t ints[] = +{ + { 0x0000, "HRESET" }, // Hardware RESET + { 0x0001, "WDOG" }, + { 0x0002, "STOVF" }, + { 0x0003, "TIMER" }, + { 0x0006, "PORTA" }, + { 0x0007, "PORTB" }, + { 0x000F, "EEPWr" }, +}; + +//----------------------------------------------------------------------- +// Angstrem KR1878VE1 Assembler +//----------------------------------------------------------------------- +static const asm_t motasm = +{ + ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASB_BINF2 // %01010 + |ASO_OCTF1 // 0123 + |AS_COLON + |AS_N2CHR + |AS_NCMAS + |AS_ONEDUP, + 0, + "Angstrem KR1878VE1 Assembler", + 0, + NULL, // header lines + "org", // org + "end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + "dc", // ascii string directive + "dcb", // byte directive + "dc", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "*", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + "global", // "public" name keyword + NULL, // "weak" name keyword + "xref", // "extrn" name keyword + // .extern directive requires an explicit object size + NULL, // "comm" (communal variable) + NULL, // get_type_name + NULL, // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gas = +{ + AS_ASCIIC + |ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASB_BINF3 // 0b01010 + |ASO_OCTF1 // 0123 + |AS_COLON + |AS_N2CHR + |AS_NCMAS + |AS_ONEDUP, + UAS_GNU, + "GNU-like hypothetical assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".long", // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + ".", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "mod", // mod + "and", // and + "or", // or + "xor", // xor + "not", // not + "shl", // shl + "shr", // shr + NULL, // sizeof + 0, // flag2 + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt +}; + +static const asm_t *const asms[] = { &motasm, &gas, NULL }; + +//---------------------------------------------------------------------- +static ea_t AdditionalSegment(int size, int offset, const char *name) +{ + segment_t s; + s.start_ea = free_chunk(0x100000, size, 0xF); + s.end_ea = s.start_ea + size; + s.sel = allocate_selector((s.start_ea-offset) >> 4); + s.type = SEG_DATA; + add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE); + return s.start_ea - offset; +} + +inline ea_t get_start(const segment_t *s) +{ + return s ? s->start_ea : BADADDR; +} + +//-------------------------------------------------------------------------- +const ioport_t *kr1878_t::find_port(ea_t address) +{ + return find_ioport(ports, address); +} + +void kr1878_t::read_kr1878_cfg(void) +{ + read_ioports(&ports, &device, "kr1878.cfg"); + for ( size_t i=0; i < ports.size(); i++ ) + { + const ioport_t &p = ports[i]; + ea_t ea = xmem + p.address; + const char *name = p.name.c_str(); + ea_t nameea = get_name_ea(BADADDR, name); + if ( nameea != ea ) + { + set_name(nameea, ""); + if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) + set_cmt(ea, name, 0); + } + } +} + +void kr1878_t::set_device_name(const char *dev) +{ + if ( dev ) + { + device = dev; + helper.supset(-1, dev); + read_kr1878_cfg(); + } +} + +const char *kr1878_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + if ( choose_ioport_device(&device, "kr1878.cfg") ) + set_device_name(device.c_str()); + return IDPOPT_OK; +} + +//----------------------------------------------------------------------- +// We always return "yes" because of the messy problem that +// there are additional operands with wrong operand number (always 1) +static bool idaapi can_have_type(const op_t &) +{ + return true; +} + +//---------------------------------------------------------------------- +void kr1878_t::load_from_idb() +{ + xmem = get_start(get_segm_by_name("MEM")); + if ( helper.supstr(&device, -1) > 0 ) + read_kr1878_cfg(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(kr1878_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi kr1878_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: +// __emit__(0xCC); // debugger trap + helper.create(PROCMOD_NODE_NAME); + init_analyzer(); + inf_set_gen_tryblks(true); + break; + + case processor_t::ev_term: + ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + { + for ( int i=0; i < qnumber(ints); i++ ) + { + ea_t ea = inf_get_min_ea() + ints[i].offset; + if ( !is_loaded(ea) ) + continue; + add_entry(ea, ea, ints[i].name, true); + } + + segment_t *s0 = get_first_seg(); + if ( s0 != NULL ) + { + segment_t *s1 = get_next_seg(s0->start_ea); + set_segm_name(s0, "CODE"); + for ( int i = as; i <= vDS; i++ ) + { + set_default_sreg_value(s0, i, BADSEL); + set_default_sreg_value(s1, i, BADSEL); + } + } + xmem = AdditionalSegment(0x100, 0, "MEM"); + } + read_kr1878_cfg(); + break; + + case processor_t::ev_oldfile: // old file loaded + { + qstring old_device; + if ( helper.supstr(&old_device, 0) >= 0 ) + { + helper.supset(-1, old_device.c_str()); + helper.supdel(0); + } + } + // fall through + case processor_t::ev_ending_undo: + load_from_idb(); + break; + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + int nocrefs = va_arg(va, int); + return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1; + } + + case processor_t::ev_may_be_func: + // can a function start here? + // arg: instruction + // returns: probability 0..100 + { + const insn_t *insn = va_arg(va, insn_t *); + return may_be_func(*insn); + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + kr1878_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + kr1878_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + kr1878_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + kr1878_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + kr1878_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *_op = va_arg(va, const op_t *); + return out_opnd(*ctx, *_op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *_op = va_arg(va, const op_t *); + return can_have_type(*_op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *_op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *_op); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "Angstrem KR1878:" +static const char *const shnames[] = { "kr1878", NULL }; +static const char *const lnames[] = +{ + FAMILY"Angstrem KR1878", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_KR1878, // id + // flag + PRN_HEX // hex numbers + | PR_ALIGN // data items must be aligned + | PR_BINMEM // segmentation is done by the processor mode + | PR_SEGS, // has segment registers + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 16, // 16 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + as, // first + vDS, // last + 1, // size of a segment register + vCS, vDS, + + NULL, // No known code start sequences + retcodes, + + KR1878_null, + KR1878_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + KR1878_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/m32r/ana.cpp b/idasdk76/module/m32r/ana.cpp similarity index 100% rename from idasdk75/module/m32r/ana.cpp rename to idasdk76/module/m32r/ana.cpp diff --git a/idasdk76/module/m32r/emu.cpp b/idasdk76/module/m32r/emu.cpp new file mode 100644 index 0000000..77160bf --- /dev/null +++ b/idasdk76/module/m32r/emu.cpp @@ -0,0 +1,393 @@ + +#include "m32r.hpp" + +// handle immediate values +static void handle_imm(const insn_t &insn) +{ + set_immd(insn.ea); +} + +//---------------------------------------------------------------------- +// handle the custom switch format +// .... +// bl.s next || nop <- insn_ea +// next: +// add lr, R0 +// jmp lr +// si.jumps: +// bra.s case0 || nop +// bra.l case1 +// ... +int m32r_create_switch_xrefs(ea_t insn_ea, const switch_info_t &si) +{ + if ( (si.flags & SWI_CUSTOM) != 0 ) + { + insn_t insn; + decode_insn(&insn, insn_ea); + ea_t ea = si.jumps; + for ( int i = 0; i < si.ncases; i++, ea += insn.size ) + { + add_cref(insn_ea, ea, fl_JN); + decode_insn(&insn, ea); + if ( insn.Op1.type == o_near ) + { + ea_t target = to_ea(insn.cs, insn.Op1.addr); + // xrefs are from "bl" -> branch target. + add_cref(insn_ea, target, fl_JN); + } + } + } + return 1; // ok +} + +//---------------------------------------------------------------------- +int m32r_calc_switch_cases(casevec_t *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si) +{ + if ( (si.flags & SWI_CUSTOM) == 0 ) + return 0; + + insn_t insn; + decode_insn(&insn, insn_ea); + + ea_t ea = si.jumps; + svalvec_t vals; + vals.push_back(0); // add one item + for ( int i=0; i < si.ncases; i++, ea += insn.size ) + { + decode_insn(&insn, ea); + if ( targets != NULL ) + { + if ( insn.itype == m32r_bra && insn.Op1.type == o_near ) + targets->push_back(insn.Op1.addr); + else + targets->push_back(insn.ea); + } + if ( casevec != NULL ) + { + vals[0] = i; + casevec->push_back(vals); + } + } + return 1; // ok +} + +//---------------------------------------------------------------------- +static bool handle_switch(const insn_t &insn) +{ + switch_info_t si; + bool was_switch = (get_flags(insn.ea) & FF_JUMP) != 0 + && get_switch_info(&si, insn.ea) > 0; + // do not overwrite the existing switch + // FIXME: reanalyze non user defined switches + if ( was_switch ) + return true; + + // ldi8 R1, #0x21 ; '!' + // cmpu R1, R0 + // bc.l loc_67F8C + // slli R0, #2 + // addi R0, #4 + // bl.s next || nop + // next: + // add lr, R0 + // jmp lr + // bra.s loc_67CDC || nop + // bra.s loc_67D34 || nop + // bra.l loc_67F8C + // ... + if ( insn.itype != m32r_bl ) + return false; + + // bl should be to next address + ea_t tgt = to_ea(insn.cs, insn.Op1.addr); + if ( tgt != insn.ea + insn.size ) + return false; + + insn_t insn2; + // check for add lr, R0; jmp lr + if ( decode_insn(&insn2, tgt) == 0 + || insn2.itype != m32r_add + || !insn2.Op1.is_reg(rLR) + || insn2.Op2.type != o_reg ) + { +BAD_MATCH: + return false; + } + + int switch_reg = insn2.Op2.reg; + + // jmp lr + if ( decode_insn(&insn2, insn2.ea + insn2.size) == 0 + || insn2.itype != m32r_jmp + || !insn2.Op1.is_reg(rLR) ) + { + goto BAD_MATCH; + } + + // addi R0, #4 + if ( decode_prev_insn(&insn2, insn.ea) == BADADDR + || insn2.itype != m32r_addi + || !insn2.Op1.is_reg(switch_reg) + || insn2.Op2.type != o_imm ) + { + goto BAD_MATCH; + } + + ea_t jumps = insn.ea + insn.size + insn2.Op2.value; + + // slli R0, #2 + if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR + || insn2.itype != m32r_slli + || !insn2.Op1.is_reg(switch_reg) + || !insn2.Op2.is_imm(2) ) + { + goto BAD_MATCH; + } + + // bc.l default + if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR + || insn2.itype != m32r_bc ) + { + goto BAD_MATCH; + } + + ea_t defea = to_ea(insn2.cs, insn2.Op1.addr); + + // cmpu R1, R0 + if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR + || insn2.itype != m32r_cmpu + || !insn2.Op2.is_reg(switch_reg) + || insn2.Op1.type != o_reg ) + { + goto BAD_MATCH; + } + + int cmpreg = insn2.Op1.reg; + + // ldi8 R1, #max + if ( decode_prev_insn(&insn2, insn2.ea) == BADADDR + || insn2.itype != m32r_ldi + || !insn2.Op1.is_reg(cmpreg) + || insn2.Op2.type != o_imm ) + { + goto BAD_MATCH; + } + + // looks good + + si.flags |= SWI_CUSTOM | SWI_J32; + si.ncases = insn2.Op2.value + 1; + si.jumps = jumps; + si.lowcase = 0; + si.startea = insn2.ea; + si.set_expr(switch_reg, dt_dword); + si.defjump = defea; + set_switch_info(insn.ea, si); + create_switch_table(insn.ea, si); + return true; +} + +//---------------------------------------------------------------------- +// emulate operand +void m32r_t::handle_operand(const insn_t &insn, const op_t &op, bool loading) +{ + flags_t F = get_flags(insn.ea); + switch ( op.type ) + { + // Address + case o_near: + // branch label - create code reference (call or jump + // according to the instruction) + { + ea_t ea = to_ea(insn.cs, op.addr); + cref_t ftype = fl_JN; + if ( insn.itype == m32r_bl && !handle_switch(insn) ) + { + if ( !func_does_return(ea) ) + flow = false; + ftype = fl_CN; + } + insn.add_cref(ea, op.offb, ftype); + } + break; + + // Immediate + case o_imm: + QASSERT(10135, loading); + handle_imm(insn); + // if the value was converted to an offset, then create a data xref: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, dr_O, OOFW_IMM|OOF_SIGNED); + + // create a comment if this immediate is represented in the .cfg file + { + const ioport_t *port = find_sym(op.value); + if ( port != NULL && !has_cmt(F) ) + set_cmt(insn.ea, port->cmt.c_str(), false); + } + break; + + // Displ + case o_displ: + handle_imm(insn); + // if the value was converted to an offset, then create a data xref: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, loading ? dr_R : dr_W, OOF_SIGNED|OOF_ADDR|OOFW_32); + + // create stack variables if required + if ( may_create_stkvars() && !is_defarg(F, op.n) ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL && (op.reg == rFP || op.reg == rSP) && pfn->flags & FUNC_FRAME ) + { + if ( insn.create_stkvar(op, op.addr, STKVAR_VALID_SIZE) ) + op_stkvar(insn.ea, op.n); + } + } + break; + + case o_phrase: + /* create stack variables if required */ + if ( op.specflag1 == fRI && may_create_stkvars() && !is_defarg(F, op.n) ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL + && (op.reg == rFP || op.reg == rSP) + && (pfn->flags & FUNC_FRAME) != 0 ) + { + if ( insn.create_stkvar(op, 0, STKVAR_VALID_SIZE) ) + op_stkvar(insn.ea, op.n); + } + } + break; + + // Phrase - register - void : do nothing + case o_reg: + case o_void: + break; + + // Others types should never be called + default: + INTERR(10136); + } +} + +//---------------------------------------------------------------------------- +// emulate an instruction +int m32r_t::emu(const insn_t &insn) +{ + uint32 feature = insn.get_canon_feature(ph); + flow = ((feature & CF_STOP) == 0); + + if ( feature & CF_USE1 ) handle_operand(insn, insn.Op1, true); + if ( feature & CF_USE2 ) handle_operand(insn, insn.Op2, true); + if ( feature & CF_USE3 ) handle_operand(insn, insn.Op3, true); + + if ( feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false); + if ( feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false); + if ( feature & CF_CHG3 ) handle_operand(insn, insn.Op3, false); + + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + return 1; +} + +//---------------------------------------------------------------------------- +bool idaapi create_func_frame(func_t *pfn) +{ + if ( pfn == NULL ) + return 0; + + ea_t ea = pfn->start_ea; + insn_t insn[4]; + int i; + + for ( i = 0; i < 4; i++ ) + { + decode_insn(&insn[i], ea); + ea += insn[i].size; + } + + i = 0; + ushort regsize = 0; // number of saved registers + + // first insn is not either push fp OR st fp, @-sp + if ( (insn[i].itype != m32r_push + || insn[i].Op1.reg != rFP) + && (insn[i].itype != m32r_st + || insn[i].Op1.reg != rFP + || insn[i].Op2.reg != rSP + || insn[i].Op2.specflag1 != fRIAS) ) + { + return 0; + } + + regsize += 4; + i++; + + // next insn is push lr OR st lr, @-sp + if ( (insn[i].itype == m32r_push + && insn[i].Op1.reg == rLR) + || (insn[i].itype == m32r_st + && insn[i].Op1.reg == rFP + && insn[i].Op2.reg == rLR + && insn[i].Op2.specflag1 != fRIAS) ) + { + regsize += 4; + i++; + } + + // next insn is not addi sp, #imm + if ( insn[i].itype != m32r_addi || insn[i].Op1.reg != rSP ) + return 0; + + sval_t offset = - (sval_t) insn[i].Op2.value; + + // toggle to the negative sign of the immediate operand of the addi insn + if ( !is_invsign(insn[i].ea, get_flags(insn[i].ea), 2) ) + toggle_sign(insn[i].ea, 2); + + i++; + + // next insn is not mv fp, sp + if ( insn[i].itype != m32r_mv || insn[i].Op1.reg != rFP || insn[i].Op2.reg != rSP ) + return 0; + + pfn->flags |= (FUNC_FRAME | FUNC_BOTTOMBP); + return add_frame(pfn, offset, regsize, 0); +} + +//---------------------------------------------------------------------------- +// should always returns 0 +int idaapi m32r_get_frame_retsize(const func_t *) +{ + return 0; +} + +//---------------------------------------------------------------------------- +// check is the specified operand is relative to the SP register +int idaapi is_sp_based(const insn_t &/*insn*/, const op_t &op) +{ + return OP_SP_ADD | (op.reg == rSP ? OP_SP_BASED : OP_FP_BASED); +} + +//---------------------------------------------------------------------------- +bool idaapi can_have_type(const op_t &x) +{ + switch ( x.type ) + { + case o_imm: + case o_displ: + return 1; + + case o_phrase: + if ( x.specflag1 == fRI ) + return 1; + break; + } + return 0; +} diff --git a/idasdk75/module/m32r/ins.cpp b/idasdk76/module/m32r/ins.cpp similarity index 100% rename from idasdk75/module/m32r/ins.cpp rename to idasdk76/module/m32r/ins.cpp diff --git a/idasdk75/module/m32r/ins.hpp b/idasdk76/module/m32r/ins.hpp similarity index 100% rename from idasdk75/module/m32r/ins.hpp rename to idasdk76/module/m32r/ins.hpp diff --git a/idasdk75/module/m32r/m32r.cfg b/idasdk76/module/m32r/m32r.cfg similarity index 100% rename from idasdk75/module/m32r/m32r.cfg rename to idasdk76/module/m32r/m32r.cfg diff --git a/idasdk76/module/m32r/m32r.hpp b/idasdk76/module/m32r/m32r.hpp new file mode 100644 index 0000000..fc2b25f --- /dev/null +++ b/idasdk76/module/m32r/m32r.hpp @@ -0,0 +1,190 @@ + +#ifndef _M32R_HPP +#define _M32R_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include <frame.hpp> +#include "../iohandler.hpp" + +#define PROCMOD_NAME m32r +#define PROCMOD_NODE_NAME "$ m32r" + +// Flags for operand specflag1 + +#define NEXT_INSN_PARALLEL_NOP 0x0001 // next insn is a // nop +#define NEXT_INSN_PARALLEL_DSP 0x0002 // next insn is a // dsp +#define NEXT_INSN_PARALLEL_OTHER 0x0004 // next insn is an other // insn + +#define SYNTHETIC_SHORT 0x0010 // insn is synthetic short (ex bc.s) +#define SYNTHETIC_LONG 0x0020 // insn is synthetic long (ex bc.l) + +#define HAS_MSB 0x0100 // insn _has_ its MSB to 1 + +// Synthetic instructions list: + +/* + m32r : + + bc.s label bc label [8-bit offset] + bc.l label bc label [24-bit offset] + bl.s label bl label [8-bit offset] + bl.l label bl label [24-bit offset] + bnc.s label bnc label [8-bit offset] + bnc.l label bnc label [24-bit offset] + bra.s label bra label [8-bit offset] + bra.l label bra label [24-bit offset] + ldi8 reg, #const ldi reg, #const [8-bit constant] + ldi16 reg, #const ldi reg, #const [16-bit constant] + push reg st reg, @-sp + pop reg ld reg, @sp+ + + m32rx : + + bcl.s label bcl label [8 bit offset] + bcl.l label bcl label [24 bit offset] + bncl.s label bncl label [8 bit offset] + bncl.l label bncl label [24 bit offset] +*/ + +// Register aliases list: + +/* + m32r : + + r13 fp + r14 lr + r15 sp + + cr0 psw + cr1 cbr + cr2 spi + cr3 spu + cr6 bpc + + m32rx : + + cr8 bbpsw + cr14 bbpc +*/ + +// define some shortcuts +#define rFP rR13 +#define rLR rR14 +#define rSP rR15 +#define rPSW rCR0 +#define rCBR rCR1 +#define rSPI rCR2 +#define rSPU rCR3 +#define rBPC rCR6 +#define rFPSR rCR7 + +// m32rx only +#define rBBPSW rCR8 +#define rBBPC rCR14 + +// m32r registers +enum m32r_registers +{ + // General-purpose registers + rR0, rR1, rR2, rR3, rR4, + rR5, rR6, rR7, rR8, rR9, + rR10, rR11, rR12, rR13, rR14, rR15, + + // Control registers + rCR0, rCR1, rCR2, rCR3, rCR6, + + // Program counter + rPC, + + // m32rx special registers + + rA0, rA1, // Accumulators + rCR4, rCR5, rCR7, rCR8, rCR9, // Add. control registers + rCR10, rCR11, rCR12, rCR13, rCR14, rCR15, + + rVcs, rVds // these 2 registers are required by the IDA kernel +}; + +// m32r indirect addressing mode +enum m32r_phrases +{ + fRI, // @R Register indirect + fRIBA, // @R+ Register indirect update before add + fRIAA, // @+R Register indirect update after add + fRIAS // @-R Register indirect update after sub +}; + +// this module supports 2 processors: m32r and m32rx +enum processor_subtype_t +{ + prc_m32r = 0, + prc_m32rx = 1 +}; + +// exporting our routines +void idaapi m32r_footer(outctx_t &ctx); +void idaapi m32r_segstart(outctx_t &ctx, segment_t *seg); +int idaapi emu(const insn_t &insn); +bool idaapi create_func_frame(func_t *pfn); +int idaapi m32r_get_frame_retsize(const func_t *pfn); +int idaapi is_sp_based(const insn_t &insn, const op_t &op); +bool idaapi can_have_type(const op_t &op); +int m32r_create_switch_xrefs(ea_t insn_ea, const switch_info_t &si); +int m32r_calc_switch_cases(casevec_t *casevec, eavec_t *targets, ea_t insn_ea, const switch_info_t &si); + +//------------------------------------------------------------------ +struct opcode; + +struct m32r_iohandler_t : public iohandler_t +{ + struct m32r_t ± + m32r_iohandler_t(m32r_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual void get_cfg_filename(char *buf, size_t bufsize) override; +}; + +struct m32r_t : public procmod_t +{ + // altval(-1) -> idpflags + // supstr(-1) -> device + netnode helper; + m32r_iohandler_t ioh = m32r_iohandler_t(*this, helper); + +#define IDP_SYNTHETIC 0x0001 // use synthetic instructions +#define IDP_REG_ALIASES 0x0002 // use register aliases + uint32 idpflags = IDP_SYNTHETIC | IDP_REG_ALIASES; + inline bool use_synthetic_insn(void) { return (idpflags & IDP_SYNTHETIC) != 0; } + inline bool use_reg_aliases(void) { return (idpflags & IDP_REG_ALIASES) != 0; } + + // Current processor type (prc_m32r or prc_m32rx) + processor_subtype_t ptype = prc_m32r; + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool idb_loaded); + void handle_new_flags(bool save=true); + const ioport_t *find_sym(ea_t address); + + int ana(insn_t *_insn); + const opcode *get_opcode(int word) const; + bool ana_special(insn_t &insn, int word, int *s) const; + int parse_fp_insn(insn_t &insn, int word); + + void m32r_header(outctx_t &ctx); + inline const char *ptype_str(void) const; + + void handle_operand(const insn_t &insn, const op_t &op, bool loading); + int emu(const insn_t &insn); + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); +}; +extern int data_id; + +#endif /* _M32R_HPP */ diff --git a/idasdk76/module/m32r/makefile b/idasdk76/module/m32r/makefile new file mode 100644 index 0000000..7c862e2 --- /dev/null +++ b/idasdk76/module/m32r/makefile @@ -0,0 +1,57 @@ +PROC=m32r +CONFIGS=m32r.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp m32r.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp ins.hpp m32r.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp m32r.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp m32r.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp m32r.hpp reg.cpp diff --git a/idasdk75/module/m32r/out.cpp b/idasdk76/module/m32r/out.cpp similarity index 100% rename from idasdk75/module/m32r/out.cpp rename to idasdk76/module/m32r/out.cpp diff --git a/idasdk76/module/m32r/reg.cpp b/idasdk76/module/m32r/reg.cpp new file mode 100644 index 0000000..0688fc7 --- /dev/null +++ b/idasdk76/module/m32r/reg.cpp @@ -0,0 +1,475 @@ + +#include "m32r.hpp" +#include <ieee.h> +int data_id; + +// m32r register names +static const char *const RegNames[] = +{ + "R0", "R1", "R2", "R3", "R4", + "R5", "R6", "R7", "R8", "R9", + "R10", "R11", "R12", "R13", "R14", "R15", + "CR0", "CR1", "CR2", "CR3", "CR6", + "PC", + "A0", "A1", + "CR4", "CR5", "CR7", "CR8", "CR9", + "CR10", "CR11", "CR12", "CR13", "CR14", "CR15", + "cs", "ds" // required by IDA kernel +}; +static const char *const RegNames_alias[] = +{ + "R0", "R1", "R2", "R3", "R4", + "R5", "R6", "R7", "R8", "R9", + "R10", "R11", "R12", "fp", "lr", "sp", + "psw", "cbr", "spi", "spu", "bpc", + "PC", + "A0", "A1", + "CR4", "CR5", "fpsr", "CR8", "CR9", + "CR10", "CR11", "CR12", "CR13", "CR14", "CR15", + "cs", "ds" // required by IDA kernel +}; + +static char const cfgname[] = "m32r.cfg"; + +void m32r_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) +{ + qstrncpy(buf, cfgname, bufsize); +} + +//---------------------------------------------------------------------------- +static int idaapi choose_device(int, form_actions_t &fa) +{ + m32r_t &pm = *(m32r_t *)fa.get_ud(); + // we do not respect the IDB_LOADED flag at this point + // should we fix it? + if ( choose_ioport_device(&pm.ioh.device, cfgname) ) + pm.ioh.set_device_name(pm.ioh.device.c_str(), IORESP_NONE); + return 0; +} + +//------------------------------------------------------------------------- +// read all procmod data from the idb +void m32r_t::load_from_idb() +{ + idpflags = (uint32)helper.altval(-1); + handle_new_flags(/*save*/ false); + ioh.restore_device(); +} + +//------------------------------------------------------------------------- +void m32r_t::handle_new_flags(bool save) +{ + // patch the RegNames[] array according to the use_reg_aliases parameter + if ( use_reg_aliases() ) + ph.reg_names = RegNames_alias; + else + ph.reg_names = RegNames; + if ( save ) + save_idpflags(); +} + +//---------------------------------------------------------------------------- +// This function (called when opening the module related configuration in +// the general options) will create a dialog box asking the end-user if he +// wants to use synthetic instructions and register aliases. +const char *m32r_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool idb_loaded) +{ + short opt_subs = 0; + + if ( keyword != NULL ) + return IDPOPT_BADKEY; + + if ( use_synthetic_insn() ) + opt_subs |= 1; + if ( use_reg_aliases() ) + opt_subs |= 2; + + static const char form[] = + "HELP\n" + "Mitsubishi 32-Bit (m32r) related options :\n" + "\n" + " Use synthetic instructions\n" + "\n" + " If this option is on, IDA will simplify instructions and replace\n" + " them by synthetic pseudo-instructions.\n" + "\n" + " For example,\n" + "\n" + " bc label1 ; 8 bits offset \n" + " bc label2 ; 24 bits offset \n" + " ldi r1, #0xF \n" + " ldi r2, #0x123456 \n" + " st r3, @-sp \n" + " ld r4, @sp+ \n" + "\n" + " will be replaced by\n" + "\n" + " bc.s label1 \n" + " bc.l label2 \n" + " ldi8 r1, #0xF \n" + " ldi24 r2, #0x123456 \n" + " push r3 \n" + " pop r4 \n" + "\n" + " Use registers aliases\n" + "\n" + " If checked, IDA will use aliases names for the following registers :\n" + "\n" + " r13 -> fp \n" + " r14 -> lr \n" + " r15 -> sp \n" + " cr0 -> psw \n" + " cr1 -> cbr \n" + " cr2 -> spi \n" + " cr3 -> spu \n" + " cr6 -> bpc \n" + "\n" + "ENDHELP\n" + "m32r related options\n" + "%*\n" + "<##Substitutions" + "#For example, use bc.s instead of 8-Bit bc instructions#Use ~s~ynthetic instructions:C>" + "<#For example, use fp instead or r14#Use registers ~a~liases:C>>\n\n\n\n" + "<~C~hoose device name:B:0::>" + "\n\n\n"; + + ask_form(form, this, &opt_subs, choose_device); + + idpflags = 0; // reset the configuration + if ( opt_subs & 1 ) + idpflags |= IDP_SYNTHETIC; + if ( opt_subs & 2 ) + idpflags |= IDP_REG_ALIASES; + + handle_new_flags(idb_loaded); + // DEVICE was saved in choose_device() + return IDPOPT_OK; +} + +// returns a pointer to a ioport_t object if address was found in the config file. +// otherwise, returns NULL. +const ioport_t *m32r_t::find_sym(ea_t address) +{ + return find_ioport(ioh.ports, address); +} + +// GNU Assembler description +static const asm_t gnu_asm = +{ + AS_COLON + |ASH_HEXF3 // hex 0x123 format + |ASB_BINF3 // bin 0b010 format + // don't display the final 0 in string declarations + |AS_ASCIIZ | AS_ASCIIC | AS_1TEXT, + 0, + "m32r GNU Assembler", + 0, + NULL, // no headers + NULL, + NULL, + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".word", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + + // Although the M32R/X/D has no hardware floating point, + // the '.float' and '.double' directives generate IEEE-format + // floating-point values for compatibility with other development tools. + + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + NULL, // func_header + NULL, // func_footer + ".global", // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + "LOW(%s)", // low16 op + "HIGH(%s)" // high16 op +}; + +// As this time, we only support the GNU assembler. +static const asm_t *const asms[] = { &gnu_asm, NULL }; + +// Short and long names for our module +#define FAMILY "Mitsubishi 32-BIT family:" +static const char *const shnames[] = +{ + "m32r", + "m32rx", + NULL +}; +static const char *const lnames[] = +{ + FAMILY"Mitsubishi 32-BIT family", + "Mitsubishi 32-BIT family (extended)", + NULL +}; + +// Opcodes of "return" instructions. This information will be used in 2 ways: +// - if an instruction has the "return" opcode, its autogenerated label +// will be "locret" rather than "loc". +// - IDA will use the first "return" opcode to create empty subroutines. + +static const uchar retcode_1[] = { 0x1F, 0xCE }; // jmp lr +static const uchar retcode_2[] = { 0x10, 0xD6 }; // rte + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } // NULL terminated array +}; + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(m32r_t)); + return 0; +} + +//---------------------------------------------------------------------------- +ssize_t idaapi m32r_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + // this processor is big endian + inf_set_be(true); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + if ( choose_ioport_device(&ioh.device, cfgname) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + handle_new_flags(); + break; + + case processor_t::ev_newprc: + ptype = processor_subtype_t(va_arg(va, int)); +// msg("ptype = %s\n", ptype == prc_m32r ? "m32r" : ptype == prc_m32rx ? "m32rx" : "???"); + break; + + case processor_t::ev_ending_undo: + // restore ptype + ptype = processor_subtype_t(ph.get_proc_index()); + //fall through + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_create_switch_xrefs: + { + ea_t insn_ea = va_arg(va, ea_t); + switch_info_t *si = va_arg(va, switch_info_t *); + return m32r_create_switch_xrefs(insn_ea, *si); + } + + case processor_t::ev_calc_switch_cases: + { + casevec_t *casevec = va_arg(va, casevec_t *); + eavec_t *targets = va_arg(va, eavec_t *); + ea_t insn_ea = va_arg(va, ea_t); + switch_info_t *si = va_arg(va, switch_info_t *); + return m32r_calc_switch_cases(casevec, targets, insn_ea, *si); + } + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m32r_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m32r_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + m32r_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *op = va_arg(va, const op_t *); + return can_have_type(*op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = m32r_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_M32R, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_BINMEM // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + | PR_USE32 + | PR_DEFSEG32, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 0, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0,m32r_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + m32r_rte, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/m740/ana.cpp b/idasdk76/module/m740/ana.cpp similarity index 100% rename from idasdk75/module/m740/ana.cpp rename to idasdk76/module/m740/ana.cpp diff --git a/idasdk76/module/m740/emu.cpp b/idasdk76/module/m740/emu.cpp new file mode 100644 index 0000000..1db57aa --- /dev/null +++ b/idasdk76/module/m740/emu.cpp @@ -0,0 +1,135 @@ + +#include "m740.hpp" + +static void handle_imm(const insn_t &insn, const op_t &op, flags_t F) +{ + set_immd(insn.ea); + if ( is_defarg(F, op.n) ) + return; + bool in_hex = false; + switch ( insn.itype ) + { + case m740_and: + case m740_ora: + in_hex = true; + break; + } + if ( in_hex ) + op_hex(insn.ea, op.n); +} + +void m740_t::handle_operand(const insn_t &insn, const op_t &op) +{ + flags_t F = get_flags(insn.ea); + switch ( op.type ) + { + // code address + case o_near: + { + ea_t ea = to_ea(insn.cs, op.addr); + cref_t mode = fl_JN; + if ( insn.itype == m740_jsr ) + { + if ( !func_does_return(ea) ) + flow = false; + mode = fl_CN; + } + insn.add_cref(ea, op.offb, mode); + } + break; + + // data address + case o_mem: + { + enum dref_t mode = dr_U; + + if ( is_addr_ind(op) ) + mode = dr_R; /* NOT dr_O */ + else if ( is_addr_read(op) ) + mode = dr_R; + else if ( is_addr_write(op) ) + mode = dr_W; + + insn.add_dref(to_ea(insn.cs, op.addr), op.offb, mode); + insn.create_op_data(op.addr, op); + } + break; + + // immediate + case o_imm: + handle_imm(insn, op, F); + // if the value was converted to an offset, then create a data xref: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, dr_O, 0); + break; + + // displ + case o_displ: + if ( op_adds_xrefs(F, op.n) ) + { + ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR); + insn.create_op_data(ea, op); + } + break; + + // reg - do nothing + case o_reg: + case o_void: + break; + + default: + INTERR(10022); + } +} + +// emulate an instruction +int m740_t::emu(const insn_t &insn) +{ + uint32 feature = insn.get_canon_feature(ph); + flow = ((feature & CF_STOP) == 0); + + if ( insn.Op1.type != o_void ) handle_operand(insn, insn.Op1); + if ( insn.Op2.type != o_void ) handle_operand(insn, insn.Op2); + if ( insn.Op3.type != o_void ) handle_operand(insn, insn.Op3); + +/* + we can't use this code + + if ( feature & CF_USE1) handle_operand(insn, insn.Op1, 1 ); + if ( feature & CF_USE2) handle_operand(insn, insn.Op2, 1 ); + if ( feature & CF_USE3) handle_operand(insn, insn.Op3, 1 ); +*/ + + // we don't use CF_JUMP + // if ( feature & CF_JUMP ) + switch ( insn.itype ) + { + case m740_jmp: + case m740_jsr: + if ( insn.Op1.type != o_void && is_addr_ind(insn.Op1) ) + remember_problem(PR_JUMP, insn.ea); + break; + } + +/* + if ( feature & CF_CHG1) handle_operand(insn, insn.Op1, 0 ); + if ( feature & CF_CHG2) handle_operand(insn, insn.Op2, 0 ); + if ( feature & CF_CHG3) handle_operand(insn, insn.Op3, 0 ); +*/ + + if ( flow ) + { + // skip the next byte if the current insn is brk + if ( insn.itype == m740_brk ) + { + add_cref(insn.ea, insn.ea + insn.size + 1, fl_JN); + create_byte(insn.ea + insn.size, 1); + } + else + { + add_cref(insn.ea, insn.ea + insn.size, fl_F); + } + } + + return 1; +} diff --git a/idasdk75/module/m740/ins.cpp b/idasdk76/module/m740/ins.cpp similarity index 100% rename from idasdk75/module/m740/ins.cpp rename to idasdk76/module/m740/ins.cpp diff --git a/idasdk75/module/m740/ins.hpp b/idasdk76/module/m740/ins.hpp similarity index 100% rename from idasdk75/module/m740/ins.hpp rename to idasdk76/module/m740/ins.hpp diff --git a/idasdk75/module/m740/m740.cfg b/idasdk76/module/m740/m740.cfg similarity index 100% rename from idasdk75/module/m740/m740.cfg rename to idasdk76/module/m740/m740.cfg diff --git a/idasdk76/module/m740/m740.hpp b/idasdk76/module/m740/m740.hpp new file mode 100644 index 0000000..bf544e1 --- /dev/null +++ b/idasdk76/module/m740/m740.hpp @@ -0,0 +1,88 @@ + +#ifndef __M740_HPP +#define __M740_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include <frame.hpp> +#include "../iohandler.hpp" +#define PROCMOD_NAME m740 +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + +// flags for insn.auxpref +#define INSN_DISPL_INDX 0x00000001 // indirect X +#define INSN_DISPL_INDY 0x00000002 // indirect Y +#define INSN_DISPL_ZPX 0x00000004 // zero page X +#define INSN_DISPL_ZPY 0x00000008 // zero page Y +#define INSN_DISPL_ABSX 0x00000010 // absolute X +#define INSN_DISPL_ABSY 0x00000020 // absolute Y + +inline bool is_displ_indx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_INDX) != 0; } +inline bool is_displ_indy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_INDY) != 0; } +inline bool is_displ_zpx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ZPX) != 0; } +inline bool is_displ_zpy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ZPY) != 0; } +inline bool is_displ_absx(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ABSX) != 0; } +inline bool is_displ_absy(const insn_t &insn) { return (insn.auxpref & INSN_DISPL_ABSY) != 0; } + +// flags for insn.Op[n].specflag1 +#define OP_ADDR_SP 0x00000001 // special page +#define OP_ADDR_IND 0x00000002 // indirect address +#define OP_ADDR_R 0x00000010 // read access +#define OP_ADDR_W 0x00000020 // write access +#define OP_IMM_BIT 0x00000004 // immediate bit index + +inline bool is_addr_sp(const op_t &op) { return (op.specflag1 & OP_ADDR_SP) != 0; } +inline bool is_addr_ind(const op_t &op) { return (op.specflag1 & OP_ADDR_IND) != 0; } +inline bool is_addr_read(const op_t &op) { return (op.specflag1 & OP_ADDR_R) != 0; } +inline bool is_addr_write(const op_t &op) { return (op.specflag1 & OP_ADDR_W) != 0; } + +// flags for ash.uflag +#define UAS_SEGM 0x0001 // segments are named "segment XXX" +#define UAS_RSEG 0x0002 // segments are named "rseg XXX" +#define UAS_INDX_NOSPACE 0x0004 // no spaces between operands in indirect X addressing mode + +// 740 registers +enum m740_registers +{ + rA, // accumulator + rX, // index register X + rY, // index register Y + rS, // stack pointer + rPS, // processor status register + rVcs, rVds // these 2 registers are required by the IDA kernel +}; + +// 740 phrases +enum m740_phrases {}; + +// exporting our routines +void idaapi m740_header(outctx_t &ctx); +int idaapi ana(insn_t *_insn); + +//------------------------------------------------------------------ +struct m740_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + + void handle_operand(const insn_t &insn, const op_t &op); + int emu(const insn_t &insn); + + void m740_header(outctx_t &ctx); + void m740_footer(outctx_t &ctx) const; + void m740_segstart(outctx_t &ctx, segment_t *Sarea) const; + + void load_from_idb(); +}; +extern int data_id; +#endif /* __M740_HPP */ diff --git a/idasdk76/module/m740/makefile b/idasdk76/module/m740/makefile new file mode 100644 index 0000000..808d9a4 --- /dev/null +++ b/idasdk76/module/m740/makefile @@ -0,0 +1,57 @@ +PROC=m740 +CONFIGS=m740.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp m740.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp ins.hpp m740.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp m740.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp m740.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp m740.hpp reg.cpp diff --git a/idasdk75/module/m740/out.cpp b/idasdk76/module/m740/out.cpp similarity index 100% rename from idasdk75/module/m740/out.cpp rename to idasdk76/module/m740/out.cpp diff --git a/idasdk76/module/m740/reg.cpp b/idasdk76/module/m740/reg.cpp new file mode 100644 index 0000000..7c9a08e --- /dev/null +++ b/idasdk76/module/m740/reg.cpp @@ -0,0 +1,338 @@ + +#include "m740.hpp" +int data_id; + +// 740 registers names +static const char *const RegNames[] = +{ + "A", // accumulator + "X", // index register X + "Y", // index register Y + "S", // stack pointer + "PS", // processor status register + "cs", "ds" // these 2 registers are required by the IDA kernel +}; + +const char *m740_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( !choose_ioport_device(&ioh.device, cfgfile) ) + { + if ( ioh.device == NONEPROC ) + warning("No devices are defined in the configuration file %s", cfgfile); + } + else + { + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +void m740_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(m740_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi m740_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + set_idp_options(NULL, 0, NULL, true); + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m740_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m740_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + m740_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +static const asm_t as_asm = +{ + AS_COLON + |ASH_HEXF4 // hex $123 format + |ASB_BINF3 // bin 0b010 format + |ASO_OCTF5 // oct 123q format + |AS_1TEXT, // 1 text per line, no bytes + UAS_SEGM|UAS_INDX_NOSPACE, + "Alfred Arnold's Macro Assembler", + 0, + NULL, // no headers + "ORG", // origin directive + "END", // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + "BYT", // ascii string directive + "BYT", // byte directive (alias: DB) + NULL, // word directive (alias: DW) + NULL, // dword (4 bytes, alias: DD) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +static const asm_t iar_asm = +{ + AS_COLON + |ASH_HEXF4 // hex $123 format + |ASB_BINF3 // bin 0b010 format + |ASO_OCTF5 // oct 123q format + |AS_1TEXT, // 1 text per line, no bytes + UAS_RSEG, + "IAR 740 Assembler", + 0, + NULL, // no headers + "ORG", // origin directive + "END", // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + "BYTE", // ascii string directive + "BYTE", // byte directive (alias: DB) + "WORD", // word directive (alias: DW) + "DWORD", // dword (4 bytes, alias: DD) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "BLKB %s", // uninited arrays + "EQU", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + NULL, // func_header + NULL, // func_footer + "PUBLIC", // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + "SIZEOF", // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +// Supported assemblers +static const asm_t *const asms[] = { &as_asm, &iar_asm, NULL }; + +// Short and long name for our module +#define FAMILY "Mitsubishi 8-BIT 740 family:" // MELPS 740, Renesas 740 + +static const char *const shnames[] = +{ + "m740", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY "Mitsubishi 8-BIT 740 family", + NULL +}; + +static const uchar retcode_1[] = { 0x40 }; // rti +static const uchar retcode_2[] = { 0x60 }; // rts + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } // NULL terminated array +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_M740, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_BINMEM, // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 0, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0, m740_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + m740_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/m7700/ana.cpp b/idasdk76/module/m7700/ana.cpp similarity index 100% rename from idasdk75/module/m7700/ana.cpp rename to idasdk76/module/m7700/ana.cpp diff --git a/idasdk76/module/m7700/emu.cpp b/idasdk76/module/m7700/emu.cpp new file mode 100644 index 0000000..e2ff663 --- /dev/null +++ b/idasdk76/module/m7700/emu.cpp @@ -0,0 +1,267 @@ + +#include "m7700.hpp" + +static void handle_imm(const insn_t &insn, const op_t &op, flags_t F) +{ + set_immd(insn.ea); + if ( is_defarg(F, op.n) ) + return; + bool in_hex = false; + switch ( insn.itype ) + { + case m7700_and: + case m7700_ora: + in_hex = true; + break; + } + if ( in_hex ) + op_hex(insn.ea, op.n); +} + +// propagate m and x to the jump target +static void propagate_bits_to(const insn_t &insn, ea_t ea) +{ + if ( !is_loaded(ea) ) + return; + split_sreg_range(ea, rfM, get_sreg(insn.ea, rfM), SR_auto); + split_sreg_range(ea, rfX, get_sreg(insn.ea, rfX), SR_auto); +} + +void m7700_t::handle_operand(const insn_t &insn, const op_t &op) +{ + flags_t F = get_flags(insn.ea); + switch ( op.type ) + { + // code address + case o_near: + { + ea_t ea = to_ea(insn.cs, op.addr); + cref_t mode; + if ( insn.itype == m7700_jsr ) + { + mode = is_insn_long_format(insn) ? fl_CF : fl_CN; + if ( !func_does_return(ea) ) + flow = false; + } + else + { + mode = is_insn_long_format(insn) ? fl_JF : fl_JN; + } + insn.add_cref(ea, op.offb, mode); + propagate_bits_to(insn, ea); + } + break; + + // data address + case o_mem: + // create xref for instructions with : + // - direct addressing mode if the value of DR is known + // (and therefore, computed by the analyzer) + // - other addressing modes + if ( !is_addr_dr_rel(op) || get_sreg(insn.ea, rDR) != BADSEL ) + { + enum dref_t mode = dr_U; + if ( is_addr_ind(op) ) + mode = dr_R; /* NOT dr_O */ + else if ( is_addr_read(op) ) + mode = dr_R; + else if ( is_addr_write(op) ) + mode = dr_W; + + insn.add_dref(to_ea(insn.cs, op.addr), op.offb, mode); + insn.create_op_data(op.addr, op); + } + break; + + // immediate + case o_imm: + handle_imm(insn, op, F); + // if the value was converted to an offset, then create a data xref: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, dr_O, 0); + break; + + // bit + case o_bit: + handle_imm(insn, op, F); + // create a comment if this immediate is represented in the .cfg file + if ( op.n == 0 && (insn.Op2.type == o_near || insn.Op2.type == o_mem) ) + { + const ioport_bit_t * port = find_bit(insn.Op2.addr, (size_t)op.value); + + if ( port != NULL && !port->name.empty() && !has_cmt(F) ) + set_cmt(insn.ea, port->cmt.c_str(), false); + } + // if the value was converted to an offset, then create a data xref: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, dr_O, 0); + break; + + // displ + case o_displ: + if ( op_adds_xrefs(F, op.n) ) + { + ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR | OOFW_32); + insn.create_op_data(ea, op); + } + break; + + // reg - do nothing + case o_reg: + case o_void: + break; + + default: + INTERR(10028); + } +} + +//------------------------------------------------------------------------- +// emulate an instruction +int m7700_t::emu(const insn_t &insn) +{ + uint32 feature = insn.get_canon_feature(ph); + flow = ((feature & CF_STOP) == 0); + + if ( insn.Op1.type != o_void ) handle_operand(insn, insn.Op1); + if ( insn.Op2.type != o_void ) handle_operand(insn, insn.Op2); + if ( insn.Op3.type != o_void ) handle_operand(insn, insn.Op3); + + switch ( insn.itype ) + { + case m7700_jmp: + case m7700_jsr: + if ( insn.Op1.type != o_void && is_addr_ind(insn.Op1) ) + remember_problem(PR_JUMP, insn.ea); + break; + } + + if ( flow ) + { + // skip the next byte if the current insn is brk + if ( insn.itype == m7700_brk ) + { + add_cref(insn.ea, insn.ea + insn.size + 1, fl_JN); + create_byte(insn.ea + insn.size, 1); + } + else + { + add_cref(insn.ea, insn.ea + insn.size, fl_F); + } + } + + switch ( insn.itype ) + { + // clear m flag + case m7700_clm: + split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); + break; + // set m flag + case m7700_sem: + split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); + break; + + // clear processor status + case m7700_clp: + // clear m flag + if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) + split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); + // clear x flag + if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) + split_sreg_range(insn.ea + insn.size, rfX, 0, SR_auto); + break; + + // set processor status + case m7700_sep: + // set m flag + if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) + split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); + // set x flag + if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) + split_sreg_range(insn.ea + insn.size, rfX, 1, SR_auto); + break; + + // pull processor status from stack + case m7700_plp: + split_sreg_range(insn.ea + insn.size, rfM, BADSEL, SR_auto); + split_sreg_range(insn.ea + insn.size, rfX, BADSEL, SR_auto); + break; + } + return 1; +} + +static bool is_func_far(ea_t ea) +{ + bool func_far = false; + insn_t insn; + while ( true ) + { + if ( decode_insn(&insn, ea) == 0 ) + break; + ea += insn.size; + + // rts = jsr + if ( insn.itype == m7700_rts ) + break; + + // rtl = jsrl + if ( insn.itype == m7700_rtl ) + { + func_far = true; + break; + } + } + return func_far; +} + +bool idaapi create_func_frame(func_t *pfn) +{ + // PC (2 bytes long) is always pushed + int context_size = 2; + + // detect phd + ea_t ea = pfn->start_ea; + + // if far, 1 byte more on the stack (PG register) + if ( is_func_far(ea) ) + { + pfn->flags |= FUNC_FAR; + context_size++; + } + + insn_t insn; + decode_insn(&insn, ea); + ea += insn.size; + if ( insn.itype != m7700_phd ) + return 0; + + // DR (2 bytes long) is pushed + context_size += 2; + + int auto_size = 0; + + while ( true ) + { + decode_insn(&insn, ea); + ea += insn.size; + + // A (2 bytes long) is pushed + if ( insn.itype != m7700_pha ) + break; + + auto_size += 2; + } + + // gen comment + char b[MAXSTR]; + qsnprintf(b, sizeof b, "Auto Size (%d) - Context Size (%d)", auto_size, context_size); + set_func_cmt(pfn, b, false); + + return add_frame(pfn, auto_size, 0, 0); +} + +//lint -e{818} +int idaapi idp_get_frame_retsize(const func_t *pfn) +{ + return is_func_far(pfn->start_ea) ? 2 : 3; +} diff --git a/idasdk75/module/m7700/ins.cpp b/idasdk76/module/m7700/ins.cpp similarity index 100% rename from idasdk75/module/m7700/ins.cpp rename to idasdk76/module/m7700/ins.cpp diff --git a/idasdk75/module/m7700/ins.hpp b/idasdk76/module/m7700/ins.hpp similarity index 100% rename from idasdk75/module/m7700/ins.hpp rename to idasdk76/module/m7700/ins.hpp diff --git a/idasdk75/module/m7700/m7700.cfg b/idasdk76/module/m7700/m7700.cfg similarity index 100% rename from idasdk75/module/m7700/m7700.cfg rename to idasdk76/module/m7700/m7700.cfg diff --git a/idasdk76/module/m7700/m7700.hpp b/idasdk76/module/m7700/m7700.hpp new file mode 100644 index 0000000..62cc163 --- /dev/null +++ b/idasdk76/module/m7700/m7700.hpp @@ -0,0 +1,165 @@ + +#ifndef __M7700_HPP +#define __M7700_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include <frame.hpp> +#include <segregs.hpp> // for get_sreg() +#include "../iohandler.hpp" +#define PROCMOD_NAME m7700 +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + +// flags for insn.op[n].specflag1 +#define OP_IMM_WITHOUT_SHARP 0x0001 // don't display the # for this immediate +#define OP_ADDR_IND 0x0002 // this address should be printed between '(' ')' +#define OP_DISPL_IND 0x0004 // this displacement should be printed between '(' ')' +#define OP_DISPL_IND_P1 0x0008 // only the first parameter of the displacement + // should be printed between '(' ')' +#define OP_ADDR_R 0x0010 // addr operand used in 'read' context +#define OP_ADDR_W 0x0020 // addr operand used in 'write' context +#define OP_ADDR_DR_REL 0x0040 // addr operand is relative to DR (direct page register) + +// specflag1 helpers +inline bool is_imm_without_sharp(const op_t &op) { return (op.specflag1 & OP_IMM_WITHOUT_SHARP) != 0; } +inline bool is_addr_ind(const op_t &op) { return (op.specflag1 & OP_ADDR_IND) != 0; } +inline bool is_addr_read(const op_t &op) { return (op.specflag1 & OP_ADDR_R) != 0; } +inline bool is_addr_write(const op_t &op) { return (op.specflag1 & OP_ADDR_W) != 0; } +inline bool is_displ_ind(const op_t &op) { return (op.specflag1 & OP_DISPL_IND) != 0; } +inline bool is_displ_ind_p1(const op_t &op) { return (op.specflag1 & OP_DISPL_IND_P1) != 0; } +inline bool is_addr_dr_rel(const op_t &op) { return (op.specflag1 & OP_ADDR_DR_REL) != 0; } + +// flags for insn.auxpref +#define INSN_LONG_FORMAT 0x0001 // we need to write an additionnal 'l' + // after the insn mnemonic. +// auxpref helpers +inline bool is_insn_long_format(const insn_t &insn) { return (insn.auxpref & INSN_LONG_FORMAT) != 0; } + +// flags for ash.uflag +#define UAS_SEGM 0x0001 // segments are named "segment XXX" +#define UAS_INDX_NOSPACE 0x0002 // no spaces between operands in indirect X addressing mode +#define UAS_END_WITHOUT_LABEL 0x0004 // do not print the entry point label after end directive +#define UAS_DEVICE_DIR 0x0008 // supports device declaration directives +#define UAS_BITMASK_LIST 0x0010 // supports list instead of bitmask for some special insn + // like clp, psh... + +// 7700 registers +enum m7700_registers +{ + rA, // accumulator A + rB, // accumulator B + rX, // index X + rY, // index Y + rS, // stack pointer + rPC, // program counter + rPG, // program bank register + rDT, // data bank register + rPS, // processor status register + rDR, // direct page register + rfM, // data length flag + rfX, // index register length flag + rVcs, rVds // these 2 registers are required by the IDA kernel +}; + +// this module supports 2 processors: m7700, m7750 +enum processor_subtype_t +{ + prc_m7700 = 0, + prc_m7750 = 1 +}; + +// shortcut for a new operand type +#define o_bit o_idpspec0 + +// exporting our routines +void idaapi m7700_assumes(outctx_t &ctx); +int idaapi ana(insn_t *_insn); +bool idaapi create_func_frame(func_t *pfn); +int idaapi idp_get_frame_retsize(const func_t *pfn); + +//------------------------------------------------------------------ +// 7700 addressing modes : +enum m7700_addr_mode_t +{ + A_IMPL, // implied + A_IMM, // immediate + A_ACC_A, // accumulator A + A_ACC_B, // accumulator B + A_DIR, // direct + A_DIR_BIT, // direct bit + A_DIR_IND_X, // direct indexed X + A_DIR_IND_Y, // direct indexed Y + A_DIR_INDI, // direct indirect + A_DIR_IND_X_INDI, // direct indexed X indirect + A_DIR_INDI_IND_Y, // direct indirect indexed Y + A_DIR_INDI_LONG, // direct indirect long + A_DIR_INDI_LONG_IND_Y, // direct indirect long indexed Y + A_ABS, // absolute + A_ABS_BIT, // absolute bit + A_ABS_IND_X, // absolute indexed X + A_ABS_IND_Y, // absolute indexed Y + A_ABS_LONG, // absolute long + A_ABS_LONG_IND_X, // absolute long indexed X + A_ABS_INDI, // absolute indirect + A_ABS_INDI_LONG, // absolute indirect long + A_ABS_IND_X_INDI, // absolute indexed X indirect + A_STACK, // stack + A_STACK_S, // stack short + A_STACK_L, // stack long + A_REL, // relative + A_REL_LONG, // relative long + A_DIR_BIT_REL, // direct bit relative + A_ABS_BIT_REL, // absolute bit relative + A_STACK_PTR_REL, // stack pointer relative + A_STACK_PTR_REL_IIY, // stack pointer relative indirect indexed Y + A_BT // block transfer +}; + +//------------------------------------------------------------------ +struct opcode; +struct m7700_iohandler_t : public iohandler_t +{ + struct m7700_t ± + m7700_iohandler_t(m7700_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual void get_cfg_filename(char *buf, size_t bufsize) override; +}; + +DECLARE_PROC_LISTENER(idb_listener_t, struct m7700_t); + +struct m7700_t : public procmod_t +{ + netnode helper; + m7700_iohandler_t ioh = m7700_iohandler_t(*this, helper); + idb_listener_t idb_listener = idb_listener_t(*this); + // Current processor type + processor_subtype_t ptype = prc_m7700; + bool with_acc_b = false; + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + bool choose_device(); + const ioport_bit_t *find_bit(ea_t address, size_t bit); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + + const struct opcode *get_opcode(uint16 code); + void fill_insn(insn_t &insn, m7700_addr_mode_t mode); + int ana(insn_t *_insn); + + void handle_operand(const insn_t &insn, const op_t &op); + int emu(const insn_t &insn); + + void m7700_header(outctx_t &ctx); + void m7700_footer(outctx_t &ctx) const; + void m7700_segstart(outctx_t &ctx, segment_t *Srange) const; + void m7700_assumes(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; +#endif // __M7700_HPP diff --git a/idasdk76/module/m7700/makefile b/idasdk76/module/m7700/makefile new file mode 100644 index 0000000..9604327 --- /dev/null +++ b/idasdk76/module/m7700/makefile @@ -0,0 +1,57 @@ +PROC=m7700 +CONFIGS=m7700.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp ins.hpp m7700.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp m7700.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.cpp ins.hpp m7700.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp m7700.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp m7700.hpp reg.cpp diff --git a/idasdk76/module/m7700/out.cpp b/idasdk76/module/m7700/out.cpp new file mode 100644 index 0000000..9345081 --- /dev/null +++ b/idasdk76/module/m7700/out.cpp @@ -0,0 +1,358 @@ + +#include "m7700.hpp" + +//---------------------------------------------------------------------- +class out_m7700_t : public outctx_t +{ + out_m7700_t(void) = delete; // not used + m7700_t &pm() { return *static_cast<m7700_t *>(procmod); } +public: + void outreg(const int n) { out_register(ph.reg_names[n]); } + void outaddr(const op_t &op, const bool replace_with_label = true); + void outdispl(const op_t &op); + bool bitmask2list(const op_t &op); + + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); +}; +CASSERT(sizeof(out_m7700_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_m7700_t) + +//-------------------------------------------------------------------------- +void out_m7700_t::outaddr(const op_t &op, const bool replace_with_label) +{ + bool ind = is_addr_ind(op); // is operand indirect ? + + if ( ind ) + out_symbol('('); + + // if addressing mode is direct and the value of DR is unknown, + // we have to print DR:x (where x is the "indexed" value) + if ( is_addr_dr_rel(op) && get_sreg(insn.ea, rDR) == BADSEL ) + { + outreg(rDR); + out_symbol(':'); + out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_32); + } + // otherwise ... + else if ( !replace_with_label + || !out_name_expr(op, to_ea(insn.cs, op.addr), op.addr) ) + { + if ( replace_with_label ) + out_tagon(COLOR_ERROR); + out_value(op, OOF_ADDR | OOFS_NOSIGN | OOFW_32); + if ( replace_with_label ) + out_tagoff(COLOR_ERROR); + } + + if ( ind ) + out_symbol(')'); +} + +//-------------------------------------------------------------------------- +void out_m7700_t::outdispl(const op_t &op) +{ + if ( is_displ_ind(op) ) + { + out_symbol('('); + outaddr(op, false); + out_symbol(','); + if ( !(ash.uflag & UAS_INDX_NOSPACE) ) + out_char(' '); + outreg(op.reg); + out_symbol(')'); + } + else if ( is_displ_ind_p1(op) ) + { + out_symbol('('); + outaddr(op, false); + out_symbol(')'); + out_symbol(','); + out_char(' '); + outreg(op.reg); + } + else + { + outaddr(op, false); + out_symbol(','); + out_char(' '); + outreg(op.reg); + } +} + +//-------------------------------------------------------------------------- +void m7700_t::m7700_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); + if ( ash.uflag & UAS_DEVICE_DIR ) + { + switch ( ptype ) + { + case prc_m7700: + ctx.gen_printf(DEFAULT_INDENT, ".MCU M37700"); + break; + case prc_m7750: + ctx.gen_printf(DEFAULT_INDENT, ".MCU M37750"); + break; + default: + INTERR(10029); + } + } +} + +//-------------------------------------------------------------------------- +void m7700_t::m7700_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + ctx.out_char(' '); + if ( ash.uflag & UAS_END_WITHOUT_LABEL ) + ctx.out_line("; "); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} + +//-------------------------------------------------------------------------- +bool out_m7700_t::bitmask2list(const op_t &op) +{ + static const char *const flags[] = + { + "N", "V", "m", "x", "D", "I", "Z", "C" + }; + static const int regs[] = + { + rPS, rPG, rDT, rDR, rY, rX, rB, rA + }; + + enum { bitFLAGS, bitREGS } t; + switch ( insn.itype ) + { + case m7700_psh: + case m7700_pul: + t = bitREGS; + break; + + case m7700_sep: + case m7700_clp: + t = bitFLAGS; + break; + + default: + return false; + } + + if ( op.value == 0 ) + return false; + + bool ok = false; + for ( int tmp = (int)op.value, i = 1, j = 0; j < 8; i *= 2, j++ ) + { + if ( ((tmp & i) >> j) != 1 ) + continue; + + if ( ok ) + { + out_symbol(','); + out_char(' '); + } + + switch ( t ) + { + case bitFLAGS: + out_register(flags[7 - j]); + break; + case bitREGS: + outreg(regs[7 - j]); + break; + } + ok = true; + } + return true; +} + +//-------------------------------------------------------------------------- +bool out_m7700_t::out_operand(const op_t &x) +{ + switch ( x.type ) + { + // register + case o_reg: + outreg(x.reg); + break; + + // immediate + case o_imm: + { + bool list_ok = false; + + if ( ash.uflag & UAS_BITMASK_LIST ) + list_ok = bitmask2list(x); + + if ( !list_ok ) + { + if ( !(is_imm_without_sharp(x)) ) + out_symbol('#'); + out_value(x, OOFW_IMM); + } + } + break; + + // bit + case o_bit: + { + const ioport_bit_t * port = NULL; + + if ( x.n == 0 && (insn.Op2.type == o_near || insn.Op2.type == o_mem) ) + port = pm().find_bit(insn.Op2.addr, (size_t)x.value); + + // this immediate is represented in the .cfg file + if ( port != NULL && !port->name.empty() ) + { + // output the port name instead of the numeric value + out_line(port->name.c_str(), COLOR_IMPNAME); + } + // otherwise, simply print the value + else + { + out_symbol('#'); + out_value(x, OOFW_IMM); + } + } + break; + + // data / code memory address + case o_near: + case o_mem: + outaddr(x); + break; + + // displ + case o_displ: + outdispl(x); + break; + + // ignore void operands + case o_void: + break; + + default: + INTERR(10030); + } + return 1; +} + +//-------------------------------------------------------------------------- +void out_m7700_t::out_proc_mnem(void) +{ + const char *pfx = is_insn_long_format(insn) ? "l" : NULL; + out_mnem(8, pfx); +} + +//-------------------------------------------------------------------------- +void out_m7700_t::out_insn(void) +{ + out_mnemonic(); + + // + // print insn operands + // + + out_one_operand(0); // output the first operand + + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + } + + if ( insn.Op3.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(2); + } + + // output a character representation of the immediate values + // embedded in the instruction as comments + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +// generate segment header +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Srange) could be made const +void m7700_t::m7700_segstart(outctx_t &ctx, segment_t *Srange) const +{ + qstring sname; + get_visible_segm_name(&sname, Srange); + + if ( ash.uflag & UAS_SEGM ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), sname.c_str()); + else + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".SECTION %s", SCOLOR_ASMDIR), sname.c_str()); + + ea_t orgbase = ctx.insn_ea - get_segm_para(Srange); + if ( orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +inline bool show_assume_line(const sreg_range_t *sra, ea_t ea, int segreg) +{ + bool show = false; + if ( sra->start_ea == ea ) + { + sreg_range_t prev_sra; + if ( get_prev_sreg_range(&prev_sra, ea, segreg) ) + show = sra->val != prev_sra.val; + } + return show; +} + +//-------------------------------------------------------------------------- +void m7700_t::m7700_assumes(outctx_t &ctx) const +{ + ea_t ea = ctx.insn_ea; + segment_t *seg = getseg(ea); + if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) + return; + bool seg_started = (ea == seg->start_ea); + + sreg_range_t sra; + if ( get_sreg_range(&sra, ea, rDR) ) + { + if ( (seg_started && sra.val != BADSEL) || show_assume_line(&sra, ea, rDR) ) + ctx.gen_printf(-1, COLSTR("%s DPR = %a", SCOLOR_REGCMT), ash.cmnt, sra.val); + } + + if ( get_sreg_range(&sra, ea, rfM) ) + { + if ( seg_started || show_assume_line(&sra, ea, rfM) ) + ctx.gen_printf(-1, COLSTR("%s m = %a", SCOLOR_REGCMT), ash.cmnt, sra.val); + } + + if ( get_sreg_range(&sra, ea, rfX) ) + { + if ( seg_started || show_assume_line(&sra, ea, rfX) ) + ctx.gen_printf(-1, COLSTR("%s x = %a", SCOLOR_REGCMT), ash.cmnt, sra.val); + } +} diff --git a/idasdk76/module/m7700/reg.cpp b/idasdk76/module/m7700/reg.cpp new file mode 100644 index 0000000..d1a5f2e --- /dev/null +++ b/idasdk76/module/m7700/reg.cpp @@ -0,0 +1,501 @@ + +#include "m7700.hpp" +#include <segregs.hpp> +int data_id; + +// 740 registers names +static const char *const RegNames[] = +{ + "A", // accumulator A + "B", // accumulator B + "X", // index register X + "Y", // index register Y + "S", // stack pointer + "PC", // program counter + "PG", // program bank register + "DT", // data bank register + "PS", // processor status register + "DPR", // direct page register + "fM", // data length flag + "fX", // index register length flag + "cs", "ds" // these 2 registers are required by the IDA kernel +}; + +static const char cfgname[] = "m7700.cfg"; + +void m7700_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) +{ + qstrncpy(buf, cfgname, bufsize); +} + +//-------------------------------------------------------------------------- +bool m7700_t::choose_device() +{ + bool ok = choose_ioport_device(&ioh.device, cfgname); + if ( !ok ) + ioh.device = NONEPROC; + return ok; +} + +//-------------------------------------------------------------------------- +const ioport_bit_t *m7700_t::find_bit(ea_t address, size_t bit) +{ + return find_ioport_bit(ioh.ports, address, bit); +} + +//-------------------------------------------------------------------------- +const char *m7700_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + + if ( !choose_ioport_device(&ioh.device, cfgname) + && ioh.device == NONEPROC ) + { + warning("No devices are defined in the configuration file %s", cfgname); + } + else + { + if ( ioh.device != NONEPROC ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + return IDPOPT_OK; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case idb_event::sgr_changed: + { + ea_t ea1 = va_arg(va, ea_t); + ea_t ea2 = va_arg(va, ea_t); + int reg = va_arg(va, int); + sel_t v = va_arg(va, sel_t); + sel_t ov = va_arg(va, sel_t); + if ( (reg == rfM || reg == rfX) && v != ov ) + set_sreg_at_next_code(ea1, ea2, reg, ov); + } + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +static const char *const m7700_help_message = + "AUTOHIDE REGISTRY\n" + "You have loaded a file for the Mitsubishi 7700 family processor.\n\n"\ + "This processor can be used in two different 'length modes' : 8-bit and 16-bit.\n"\ + "IDA allows to specify the encoding mode for every single instruction.\n"\ + "For this, IDA uses two virtual segment registers : \n"\ + " - fM, used to specify the data length;\n"\ + " - fX, used to specify the index register length.\n\n"\ + "Switching their state from 0 to 1 will switch the disassembly from 16-bit to 8-bit.\n"\ + "You can change their value using the 'change segment register value' command\n"\ + "(the canonical hotkey is Alt-G).\n\n"\ + "Note : in the real design, those registers are represented as flags in the\n"\ + "processor status register.\n"; + +//---------------------------------------------------------------------- +void m7700_t::load_from_idb() +{ + ioh.restore_device(IORESP_NONE); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(m7700_t)); + return 0; +} + +ssize_t idaapi m7700_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + hook_event_listener(HT_IDB, &idb_listener, &LPH); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + clr_module_data(data_id); + unhook_event_listener(HT_IDB, &idb_listener); + break; + + case processor_t::ev_newfile: + if ( choose_device() ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + else + ioh.set_device_name(NONEPROC, IORESP_NONE); + // Set the default segment register values : + // -1 (badsel) for DR + // 0 for fM and fX + for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) + { + set_default_sreg_value(s, rDR, BADSEL); + set_default_sreg_value(s, rfM, 0); + set_default_sreg_value(s, rfX, 0); + } + info(m7700_help_message); + break; + + case processor_t::ev_newprc: + ptype = processor_subtype_t(va_arg(va, int)); + break; + + case processor_t::ev_ending_undo: + // restore ptype + ptype = processor_subtype_t(ph.get_proc_index()); + //fall through + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m7700_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m7700_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + m7700_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m7700_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = idp_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +static const asm_t as_asm = +{ + AS_COLON + |ASH_HEXF4 // hex $123 format + |ASB_BINF3 // bin 0b010 format + |ASO_OCTF5 // oct 123q format + |AS_1TEXT, // 1 text per line, no bytes + UAS_SEGM|UAS_INDX_NOSPACE, + "Alfred Arnold's Macro Assembler", + 0, + NULL, // no headers + "ORG", // origin directive + "END", // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + "DB", // ascii string directive + "DB", // byte directive + "DW", // word directive + "DD", // dword (4 bytes) + "DQ", // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + "DT", // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +// +// Mitsubishi Macro Assembler for 7700 Family +// + +//-------------------------------------------------------------------------- +// gets a function name +//lint -e{818} could be declared const +static bool mits_get_func_name(qstring *name, func_t *pfn) +{ + ea_t ea = pfn->start_ea; + if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 ) + return false; + + tag_addr(name, ea, true); + return true; +} + +//-------------------------------------------------------------------------- +// prints function header +static void idaapi mits_func_header(outctx_t &ctx, func_t *pfn) +{ + ctx.gen_func_header(pfn); + + qstring name; + if ( mits_get_func_name(&name, pfn) ) + { + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".FUNC %s", SCOLOR_ASMDIR), name.begin()); + ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name.begin()); + ctx.ctxflags |= CTXF_LABEL_OK; + } +} + +//-------------------------------------------------------------------------- +// prints function footer +static void idaapi mits_func_footer(outctx_t &ctx, func_t *pfn) +{ + qstring name; + if ( mits_get_func_name(&name, pfn) ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".ENDFUNC %s", SCOLOR_ASMDIR), name.begin()); +} + +static const asm_t mitsubishi_asm = +{ + AS_COLON + |ASH_HEXF0 // hex 123h format + |ASB_BINF0 // bin 10100011b format + |ASO_OCTF0 // oct 123o format + |AS_1TEXT, // 1 text per line, no bytes + UAS_END_WITHOUT_LABEL|UAS_DEVICE_DIR|UAS_BITMASK_LIST, + "Mitsubishi Macro Assembler for 7700 Family", + 0, + NULL, // no headers + ".ORG", // origin directive + ".END", // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".BYTE", // ascii string directive + ".BYTE", // byte directive + ".WORD", // word directive + ".DWORD", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".BLKB %s", // uninited arrays + ".EQU", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + mits_func_header, // func_header + mits_func_footer, // func_footer + ".PUB", // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + "SIZEOF", // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +// Supported assemblers +static const asm_t *const asms[] = { &mitsubishi_asm, &as_asm, NULL }; + +// Short and long name for our module +#define FAMILY "Mitsubishi 16-BIT 7700 family:" + +static const char *const shnames[] = +{ + "m7700", + "m7750", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Mitsubishi 16-BIT 7700 family", + "Mitsubishi 16-BIT 7700 family (7750 series)", + NULL +}; + +static const uchar retcode_1[] = { 0x40 }; // rti +static const uchar retcode_2[] = { 0x60 }; // rts +static const uchar retcode_3[] = { 0x6B }; // rtl + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } // NULL terminated array +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_M7700, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_BINMEM // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + | PR_SEGS // has segment registers? + | PR_SGROTHER, // the segment registers don't contain + // the segment selectors, something else + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rDR, rVds, + 2, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + 0, m7700_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + m7700_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/m7900/7900.hpp b/idasdk76/module/m7900/7900.hpp new file mode 100644 index 0000000..3d8ab87 --- /dev/null +++ b/idasdk76/module/m7900/7900.hpp @@ -0,0 +1,251 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#ifndef _MITSUBISHI7900_HPP +#define _MITSUBISHI7900_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <segregs.hpp> +#include "../iohandler.hpp" +#define PROCMOD_NAME m7900 +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + +#define UAS_NOSPA 0x0001 // no space after comma +#define UAS_SEGM 0x0002 // segments are named "segment XXX" + + +// flags for insn.auxpref +// operand prefix +// 0x1 - .b +// 0x2 - .w +// 0x4 - .d + +#define INSN_PREF_U 0x0000 +#define INSN_PREF_B 0x0001 +#define INSN_PREF_W 0x0002 +#define INSN_PREF_D 0x0004 + +#define RAZOPER insn.auxpref + +// Detect status value +#define getFlag_M get_sreg(insn.ea, rfM) +#define getFlag_X get_sreg(insn.ea, rfX) + +#define getDT get_sreg(insn.ea, rDT) +#define getPG get_sreg(insn.ea, rPG) + +#define getDPReg get_sreg(insn.ea, rDPReg) + +#define getDPR0 get_sreg(insn.ea, rDPR0) +#define getDPR1 get_sreg(insn.ea, rDPR1) +#define getDPR2 get_sreg(insn.ea, rDPR2) +#define getDPR3 get_sreg(insn.ea, rDPR3) + + +//---------------------------------------------------------------------- +// Redefine temporary names +// + +#define xmode specflag1 +#define TypeOper specflag2 + +#define o_sr o_idpspec0 +#define o_ab o_idpspec1 +#define o_stk o_idpspec2 + + +// +// + +enum mitsubishi_bit_PUL { bPS, bb, bDT, bDPR0, bY, bX, bB, bA }; +// ======= mitsubishi_bit_CPU ======================================== +/* + __________________________ +|... |IPL|N|V|m|x|D|I|Z|C| + __________________________ +*/ + +// +// Bit 0: Carry flag (C) +// Bit 1: Zero flag (Z) +// Bit 2: Interrupt disable flag (I) +// Bit 3: Decimal mode flag (D) +// Bit 4: Index register length flag (x) +// Bit 5: Data length flag (m) +// Bit 6: Overflow flag (V) +// Bit 7: Negative flag (N) +// Bits 10 to 8: Processor interrupt priority level (IPL) +// +enum mitsubishi_bit_CPU { bIPL, bN, bV, bm, bx, bD, bI, bZ, bC }; + + +enum mitsubishi_registers { rA, rB, rE, rX, rY, rPC, + rPS, + rfIPL, rfN, rfV, rfD, rfI, rfZ, rfC, + rDT, rPG, rDPReg, rDPR0, rDPR1, rDPR2, rDPR3,rfM, rfX, + Rcs, Rds }; + + + + +/* + 15____________________0 + | Ah | AL | - Accumulator A + _____________________ +15____________________0 +| Bh | BL | - Accumulator B +| ____________________| + +31___________________________________________0 +| Eh | EL | - Accumulator E + _____________________________________________ + +15____________________0 +| Xh | XL | - Index registr X + _____________________ +15____________________0 +| Yh | YL | - Index registr Y + _____________________ + +15____________________0 +| Sh | SL | - Stack pointer S + _____________________ + +8_________0 +| DT | - Data bank registr(DT) + _________ + +23_________15___________________0 +| PG | PCh | PCl | - Program counter(PC) + _______________________________ + |_____________________________________________________ - Program bank registr()PG + +15____________________0 +| DPR0h | DPR0L | - Direct page registr 0(DPR0) + _____________________ +15____________________0 +| DPR1h | DPR1L | - Direct page registr 1(DPR1) + _____________________ +15____________________0 +| DPR2h | DPR2L | - Direct page registr 2(DPR2) + _____________________ +15____________________0 +| DPR3h | DPR3L | - Direct page registr 3(DPR3) + _____________________ +15____________________0 +| PSh | PS L | - Procesor status register(PS) + _____________________ +*/ + + + + + +enum eMode { IMM_8=0, IMM_16, IMM_32, DIR_32, DIR_16, DIR_8 }; + + +// TDIR_DIR - Direct addressing mode DIR +// TDIR_DIR_X - Direct index X addressing DIR,X +// TDIR_DIR_Y - Direct index Y addressing DIR,Y +// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR) +// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X) +// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y) +// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR) +// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y + +enum eTypeDIR { TDIR_DIR=0, TDIR_DIR_X, TDIR_DIR_Y, TDIR_INDIRECT_DIR, + TDIR_INDIRECT_DIR_X, TDIR_INDIRECT_DIR_Y, TDIR_L_INDIRECT_DIR, TDIR_L_INDIRECT_DIR_Y }; + + +// TSP_SP - Stack pointer relative addressing mode(SR) +// TSP_INDEX_SP_Y - Stack pointer relative indexed Y addressing mode((SR),Y) + +enum eTypeSP { TSP_SP=0, TSP_INDEX_SP_Y }; + + +// TAB_ABS - Absolute addressing mode(ABS) +// TAB_ABS_X - Absolute indexed X addressing mode(ABS,X) +// TAB_ABS_Y - Absolute indexed Y addressing mode(ABS,Y) +// TAB_ABL - Absolute long addressing mode(ABL) +// TAB_ABL_X - Absolute long indexed X addressing mode(ABS,X) +// TAB_INDIRECTED_ABS - Absolute indirect addressing mode((ABS)) +// TAB_L_INDIRECTED_ABS - Absolute indirect long addressing mode(L(ABS)) +// TAB_INDIRECTED_ABS_X - Absolute indexed X indirect addressing mode((ABS,X)) + +enum eTypeAB { TAB_ABS=0, TAB_ABS_X, TAB_ABS_Y, TAB_ABL, TAB_ABL_X, + TAB_INDIRECTED_ABS, TAB_L_INDIRECTED_ABS, TAB_INDIRECTED_ABS_X }; + + +//------------------------------------------------------------------------ +struct ioport_bit_t; +//------------------------------------------------------------------------ +int idaapi ana(insn_t *_insn); + +inline void TRACE1(const char *szStr) +{ + msg("%s\n", szStr); +} + + +inline void TRACE1(uint32 Data) +{ + msg("DATA - %X\n", Data); +} + + +inline void TRACE(const char * /*szStr*/) +{ +// msg("%s\n", szStr); +} + + +inline void TRACE(uint32 /*Data*/) +{ +// msg("DATA - %X\n", Data); +} + +inline int GETBIT(uval_t Data, int bit) +{ + uint32 TempByte = (uint32)Data; + return (TempByte>>bit)&0x01; +} + +//------------------------------------------------------------------ +DECLARE_PROC_LISTENER(idb_listener_t, struct m7900_t); + +struct m7900_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + idb_listener_t idb_listener = idb_listener_t(*this); + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + bool choose_device(); + + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + int emu(const insn_t &insn); + + void m7900_header(outctx_t &ctx); + void m7900_segstart(outctx_t &ctx, segment_t *Srange) const; + void m7900_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; +#endif + diff --git a/idasdk76/module/m7900/ana.cpp b/idasdk76/module/m7900/ana.cpp new file mode 100644 index 0000000..7802acd --- /dev/null +++ b/idasdk76/module/m7900/ana.cpp @@ -0,0 +1,10062 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "7900.hpp" + +#define SetTypeDataM (getFlag_M ? dt_byte : dt_word) +#define SetTypeDataX (getFlag_X ? dt_byte : dt_word) + +//---------------------------------------------------------------------- +// reg - register +// +inline void Operand_Registr(op_t &x, uint16 rReg) +{ + x.type = o_reg; + x.reg = rReg; + // x.dtype = dt_word; // For A and B, for E need dt_dword +} + +//---------------------------------------------------------------------- +static void Operand_Imm_32(insn_t &insn, op_t &x) +{ + uint32 L_L = insn.get_next_byte(); + uint32 L_H = insn.get_next_byte(); + uint32 H_L = insn.get_next_byte(); + uint32 H_H = insn.get_next_byte(); + + uint32 data = ((L_L | (H_H<<24)) | (H_L << 16)) | (L_H<<8); + + x.type = o_imm; + x.value = data; + x.dtype = dt_dword; + x.xmode = IMM_32; + +} + +//---------------------------------------------------------------------- +static void Operand_Imm_16(insn_t &insn, op_t &x) +{ + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + uint32 data = high | (low<<8); + + x.type = o_imm; + x.value = data; + x.dtype = dt_word; + x.xmode = IMM_16; +} + +//---------------------------------------------------------------------- +static void Operand_Imm_8(insn_t &insn, op_t &x) +{ + uint32 high = insn.get_next_byte(); + + x.type = o_imm; + x.value = high; + x.dtype = dt_byte; + x.xmode = IMM_8; +} + +//---------------------------------------------------------------------- +// Raz - instruction bitness (8, 16, 32) +//---------------------------------------------------------------------- +static void Operand_Imm(insn_t &insn, op_t &x, int Raz) +{ + switch ( Raz ) + { + case 8: Operand_Imm_8(insn, x); break; + case 16: Operand_Imm_16(insn, x); break; + case 32: Operand_Imm_32(insn, x); break; + } +} + +//---------------------------------------------------------------------- +static void Operand_Imm_Spesh(op_t &x, uchar dtype, uint32 data) +{ + uchar type = 0; + + x.type = o_imm; + x.value = data; + x.dtype = dtype; + + if ( dtype == dt_byte ) + type= IMM_8; + + if ( dtype == dt_word ) + type= IMM_16; + + x.xmode = type; +} + +sel_t getDPR(const insn_t &insn, int iDPR) +{ + switch ( iDPR ) + { + case 0x0: return getDPR0; + case 0x40: return getDPR1; + case 0x80: return getDPR2; + case 0xC0: return getDPR3; + } + return 0; +} + +//---------------------------------------------------------------------- +// TypeDIR +// TDIR_DIR - Direct addressing mode DIR +// TDIR_DIR_X - Direct index X addressing DIR,X +// TDIR_DIR_Y - Direct index Y addressing DIR,Y +// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR) +// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X) +// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y) +// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR) +// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y +// +//---------------------------------------------------------------------- +inline void DIR(insn_t &insn, op_t &x, uchar TypeDir, char dtype) +{ + uint32 higth = insn.get_next_byte(); + + uint32 Addr; + if ( getDPReg == 1 ) + { + sel_t ValDPR = getDPR(insn, higth & 0xC0); + Addr = uint32(ValDPR + higth); + } + else + { + Addr = uint32(getDPR0 + higth); + } + x.type = o_mem; + x.addr = Addr; + x.dtype = dtype; + x.TypeOper = TypeDir; +} + +static void LDIR(insn_t &insn, op_t &x, uchar TypeDir, char dtype) +{ + uint32 higth = insn.get_next_byte(); + uint32 Addr; + if ( getDPReg == 1 ) + { + sel_t ValDPR = getDPR(insn, higth & 0xC0); + Addr = uint32(ValDPR + higth); + } + else + { + Addr = uint32(getDPR0 + higth); + } + + x.type = o_mem; + x.addr = Addr; + x.dtype = dtype; + x.TypeOper = TypeDir; +} + +//---------------------------------------------------------------------- +// TypeDIR +// TDIR_DIR - Direct addressing mode DIR +// TDIR_DIR_X - Direct index X addressing DIR,X +// TDIR_DIR_Y - Direct index Y addressing DIR,Y +// TDIR_INDIRECT_DIR - Direct indirect addressing mode (DIR) +// TDIR_INDIRECT_DIR_X - Direct index X indirect addressing mode (DIR,X) +// TDIR_INDIRECT_DIR_Y - Direct index Y indirect addressing mode (DIR,Y) +// TDIR_L_INDIRECT_DIR - Direct indirect long addressing mode L(DIR) +// TDIR_L_INDIRECT_DIR_Y - Direct indirect long indexed Y addressing mode L(DIR),Y +// +// +// dtype - target data type for memory cell +//---------------------------------------------------------------------- +static void Operand_Dir(insn_t &insn, op_t &x, uchar TypeDir, char dtype = dt_word) +{ + switch ( TypeDir ) + { + case TDIR_DIR:// - Direct addressing mode DIR + DIR(insn, x, TypeDir, dtype); + break; + case TDIR_DIR_X:// - Direct index X addressing DIR,X + DIR(insn, x, TypeDir, dtype); + break; + case TDIR_DIR_Y:// - Direct index Y addressing DIR,Y + DIR(insn, x, TypeDir, dtype); + break; + case TDIR_INDIRECT_DIR:// - Direct indirect addressing mode (DIR) + LDIR(insn, x, TypeDir, dtype); + break; + case TDIR_INDIRECT_DIR_X:// - Direct index X indirect addressing mode (DIR,X) + LDIR(insn, x, TypeDir, dtype); + break; + case TDIR_INDIRECT_DIR_Y:// - Direct index Y indirect addressing mode (DIR,Y) + LDIR(insn, x, TypeDir, dtype); + break; + case TDIR_L_INDIRECT_DIR:// - Direct indirect long addressing mode L(DIR) + LDIR(insn, x, TypeDir, dtype); + break; + case TDIR_L_INDIRECT_DIR_Y:// - Direct indirect long indexed Y addressing mode L(DIR),Y + LDIR(insn, x, TypeDir, dtype); + break; + } +} + +//---------------------------------------------------------------------- +static void Operand_SR_16(insn_t &insn, op_t &x, uchar Type) +{ + uint32 data = insn.get_next_byte(); + + x.type = o_sr; + x.value = data; + x.dtype = dt_word; + x.TypeOper = Type; +} + +//---------------------------------------------------------------------- +static void Operand_SR_8(insn_t &insn, op_t &x, uchar Type) +{ + uint32 data = insn.get_next_byte(); + + x.type = o_sr; + x.value = data; + x.dtype = dt_byte; + x.TypeOper = Type; +} + +//---------------------------------------------------------------------- +static void Operand_SR(insn_t &insn, op_t &x, uchar TypeDir, int Raz) +{ + switch ( Raz ) + { + case 8: Operand_SR_8(insn, x, TypeDir); break; + case 16: Operand_SR_16(insn, x, TypeDir); break; + } +} + +//---------------------------------------------------------------------- +static void ABS(insn_t &insn, op_t &x, uchar Type, sel_t gDT, char dtype) +{ + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + uint32 data = high | (low<<8); + + data = uint32(data | (gDT<<16)); + + x.type = o_ab; + x.addr = data; + x.dtype = dtype; + x.TypeOper = Type; +} + +//---------------------------------------------------------------------- +static void ABL(insn_t &insn, op_t &x, uchar Type, char dtype) +{ + uint32 ll = insn.get_next_byte(); + uint32 mm = insn.get_next_byte(); + uint32 hh = insn.get_next_byte(); + + uint32 data = (ll | (hh<<16)) | (mm<<8); + + x.type = o_ab; + x.addr = data; + x.dtype = dtype; + x.TypeOper = Type; +} + +//---------------------------------------------------------------------- +static void Indirect_ABS(insn_t &insn, op_t &x, uchar Type, sel_t /*gPG*/, char dtype) +{ + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + + uint32 addr = high | (low<<8); + + // This looks like a bug, FIXME! + /*uint32 Addr =*/ get_word(addr); + // Addr = uint32(Addr | (gPG<<16)); + + x.type = o_ab; + x.addr = addr; + x.dtype = dtype; + x.TypeOper = Type; +} + +//---------------------------------------------------------------------- +static void Operand_AB(insn_t &insn, op_t &x, uchar TypeDir, int /*Raz*/, char dtype = dt_word) +{ + switch ( TypeDir ) + { + case TAB_ABS: // - Absolute addressing mode(ABS) + ABS(insn, x, TypeDir, getDT, dtype); + break; + + case TAB_ABS_X:// - Absolute indexed X addressing mode(ABS,X) + ABS(insn, x, TypeDir, getDT, dtype); + break; + + case TAB_ABS_Y:// - Absolute indexed Y addressing mode(ABS,Y) + ABS(insn, x, TypeDir, getDT, dtype); + break; + + case TAB_ABL: // - Absolute long addressing mode(ABL) + ABL(insn, x, TypeDir, dtype); + break; + case TAB_ABL_X:// - Absolute long indexed X addressing mode(ABS,X) + ABL(insn, x, TypeDir, dtype); + break; + + case TAB_INDIRECTED_ABS:// - Absolute indirect addressing mode((ABS)) + Indirect_ABS(insn, x, TypeDir, getPG, dtype);//??? + break; + + case TAB_L_INDIRECTED_ABS:// - Absolute indirect long addressing mode(L(ABS)) + Indirect_ABS(insn, x, TypeDir, getPG, dtype);//??? + break; + + case TAB_INDIRECTED_ABS_X:// - Absolute indexed X indirect addressing mode((ABS,X)) + Indirect_ABS(insn, x, TypeDir, getPG, dtype);//??? + break; + } +} + +//---------------------------------------------------------------------- +static void Bral(insn_t &insn, op_t &x, int del) +{ + x.type = o_near; + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + uint32 addr = high | (low<<8); + + x.addr = insn.ip + (signed short)addr + del; +} + +//---------------------------------------------------------------------- +inline void Operand_BSR(const insn_t &insn, op_t &x, uint32 addr, int del) +{ + x.type = o_near; + x.addr = insn.ip + (int32)addr + del; +} + +//---------------------------------------------------------------------- +inline void Operand_BBC(const insn_t &insn, op_t &x, uchar addr, int del) +{ + x.type = o_near; + x.addr = insn.ip + (signed char)addr + del; +} + +//---------------------------------------------------------------------- +inline void Operand_BBS(const insn_t &insn, op_t &x, uchar addr, int del) +{ + Operand_BBC(insn, x, addr, del); +} + +//---------------------------------------------------------------------- +inline void Operand_DEBNE(const insn_t &insn, op_t &x, uchar addr, int del) +{ + x.type = o_near; + x.addr = insn.ip + (signed char)addr + del; +} + +//---------------------------------------------------------------------- +inline void Operand_Near(const insn_t &insn, op_t &x, uchar addr, int del) +{ + x.type = o_near; + x.addr = insn.ip + (signed char)addr + del; +} + +//---------------------------------------------------------------------- +inline void Operand_IMP(op_t & /*x*/) +{ +} + +//---------------------------------------------------------------------- +static void Jsr_24(insn_t &insn, op_t &x) +{ + x.type = o_near; + + uint32 ll = insn.get_next_byte(); + uint32 mm = insn.get_next_byte(); + uint32 hh = insn.get_next_byte(); + + uint32 data = (ll | (hh<<16)) | (mm<<8); + + x.addr = data; + x.dtype = dt_dword; +} + +//---------------------------------------------------------------------- +static void Jsr_16(insn_t &insn, op_t &x, sel_t gPG) +{ + x.type = o_near; + + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + uint32 data = high | (low<<8); + data = uint32(data | (gPG<<16)); + + x.addr = data; + x.dtype = dt_word; +} + +//---------------------------------------------------------------------- +// dt_byte +// dt_word +// dt_dword +//---------------------------------------------------------------------- +static void Operand_STK_16(insn_t &insn, op_t &x, uchar dtype) +{ + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + uint32 data = high | (low<<8); + + x.type = o_stk; + x.value = data; + x.dtype = dtype; + x.xmode = IMM_16; +} + +//---------------------------------------------------------------------- +// dt_byte +// dt_word +// dt_dword +//---------------------------------------------------------------------- +inline void Operand_STK_8(insn_t &insn, op_t &x, uchar dt_type) +{ + uint32 high = insn.get_next_byte(); + + x.type = o_stk; + x.value = high; + x.dtype = dt_type; + x.xmode = IMM_8; +} + +//---------------------------------------------------------------------- +inline void Operand_STK(insn_t &insn, op_t &x, int Razr) +{ + switch ( Razr ) + { + case 8: Operand_STK_8(insn, x, dt_byte); break; + case 16: Operand_STK_16(insn, x, dt_word); break; + } +} + +//---------------------------------------------------------------------- +static void Branch(insn_t &insn, op_t &x, int cd) +{ + static const uchar icode[] = + { + 0, // 0 + m7900_bpl, // 1 + m7900_bra, // 2 + m7900_bmi, // 3 + m7900_bgtu, // 4 + m7900_bvc, // 5 + m7900_bleu, // 6 + m7900_bvs, // 7 + m7900_bgt, // 8 + m7900_bcc, // 9 + m7900_ble, // a + m7900_bcs, // b + m7900_bge, // c + m7900_bne, // d + m7900_blt, // e + m7900_beq // F + }; + insn.itype = icode[ cd ]; + Operand_Near(insn, x, insn.get_next_byte(), 2); +} + +//---------------------------------------------------------------------- +int Opcode_91(insn_t &insn) +{ + TRACE("Opcode_91"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + // ________________________ ADD________________________ + // 101 - ADd + // add B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 20 dd] + case 0x20: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 101 - ADd + // add B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 21 dd] + case 0x21: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 101 - ADd + // add B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [91 28 dd] + case 0x28: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 22 dd] + case 0x22: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 101 - ADd + // add B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 29 dd] + case 0x29: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + // Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, 8, SetTypeDataM); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 23 nn] + case 0x23: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 101 - ADd + // add B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 24 nn] + case 0x24: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 26 ll mm] + case 0x26: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [91 2C ll mm hh] + case 0x2C: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 101 - ADd + // add B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [91 2D ll mm hh] + case 0x2D: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // ______________________ END ADD _____________________ + // ________________________ CMP________________________ + // 161 - CoMPare + // cmp B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 40 dd] + case 0x40: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 41 dd] + case 0x41: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [91 48 dd] + case 0x48: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 42 dd] + case 0x42: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 161 - CoMPare + // cmp B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 49 dd] + case 0x49: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 43 nn] + case 0x43: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 161 - CoMPare + // cmp B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 44 nn] + case 0x44: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 46 ll mm] + case 0x46: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [91 4C ll mm hh] + case 0x4C: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [91 4D ll mm hh] + case 0x4D: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END CMP _____________________ + + // ________________________ AND________________________ + // 111 - logical AND + // and B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 60 dd] + case 0x60: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 111 - logical AND + // and B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 61 dd] + case 0x61: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 111 - logical AND + // and B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [91 68 dd] + case 0x68: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 62 dd] + case 0x62: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 111 - logical AND + // and B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 69 dd] + case 0x69: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 63 nn] + case 0x63: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 111 - logical AND + // and B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 64 nn] + case 0x64: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 66 ll mm] + case 0x66: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [91 6C ll mm hh] + case 0x6C: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 111 - logical AND + // and B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [91 6D ll mm hh] + case 0x6D: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END AND _____________________ + // ________________________ EOR________________________ + // 180 - Exclusive OR memory with accumulator + // eor B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 70 dd] + case 0x70: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 71 dd] + case 0x71: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [91 78 dd] + case 0x78: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 72 dd] + case 0x72: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 79 dd] + case 0x79: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 73 nn] + case 0x73: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 74 nn] + case 0x74: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 76 ll mm] + case 0x76: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [91 7C ll mm hh] + case 0x7C: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [91 7D ll mm hh] + case 0x7D: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END eor _____________________ + + // ___________________ LDA _________________________ + // 195 - LoaD Accumulator from memory + // lda B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 10 dd] + case 0x10: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 11 dd] + case 0x11: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 12 dd] + case 0x12: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 195 - LoaD Accumulator from memory + // lda B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 13 nn] + case 0x13: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 195 - LoaD Accumulator from memory + // lda B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 14 nn] + case 0x14: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 195 - LoaD Accumulator from memory + // lda B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 16 ll mm] + case 0x16: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END LDA ____________________ + + // ___________________ LDAB _________________________ + // 196 - LoaD Accumulator from memory at Byte + // ldab B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 00 dd] + case 0x00: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 01 dd] + case 0x01: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 02 dd] + case 0x02: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 03 nn] + case 0x03: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 04 nn] + case 0x04: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 06 ll mm] + case 0x06: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END LDAB ____________________ + + // ___________________ STA _________________________ + // 271 - STore Accumulator in memory + // sta B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 D0 dd] + case 0xD0: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 D1 dd] + case 0xD1: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 D2 dd] + case 0xD2: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_byte); + break; + + // 271 - STore Accumulator in memory + // sta B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 D3 nn] + case 0xD3: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 271 - STore Accumulator in memory + // sta B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 D4 nn] + case 0xD4: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 271 - STore Accumulator in memory + // sta B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 D6 ll mm] + case 0xD6: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END STA ____________________ + // _____________________ STAB ____________________ + // 272 - STore Accumulator in memory at Byte + // stab B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 C0 dd] + case 0xC0: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 C1 dd] + case 0xC1: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 C2 dd] + case 0xC2: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 C3 nn] + case 0xC3: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 C4 nn] + case 0xC4: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 C6 ll mm] + case 0xC6: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END STAB ____________________ + + // ________________________ ORA________________________ + // 220 - OR memory with Accumulator + // ora B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 50 dd] + case 0x50: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 51 dd] + case 0x51: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [91 58 dd] + case 0x58: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 52 dd] + case 0x52: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 220 - OR memory with Accumulator + // ora B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 59 dd] + case 0x59: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 53 nn] + case 0x53: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 220 - OR memory with Accumulator + // ora B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 54 nn] + case 0x54: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 56 ll mm] + case 0x56: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [91 5C ll mm hh] + case 0x5C: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // ora B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [91 5D ll mm hh] + case 0x5D: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END ora _____________________ + + // ________________________ SUB________________________ + // 278 - SUBtract + // sub B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [91 30 dd] + case 0x30: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 278 - SUBtract + // sub B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [91 31 dd] + case 0x31: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 278 - SUBtract + // sub B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [91 38 dd] + case 0x38: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 32 dd] + case 0x32: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 278 - SUBtract + // sub B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [91 39 dd] + case 0x39: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [91 33 nn] + case 0x33: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 278 - SUBtract + // sub B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [91 34 nn] + case 0x34: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [91 36 ll mm] + case 0x36: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [91 3C ll mm hh] + case 0x3C: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 278 - SUBtract + // sub B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [91 3D ll mm hh] + case 0x3D: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END SUB _____________________ + + default: + return 0; + + } + return insn.size; +} + +//-------------------------------------------------------------------------------------------- +static int Opcode_21(insn_t &insn) +{ + TRACE("Opcode_21"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + // ___________________ ADC _________________________ + // 96 - ADd with Carry + // adc A, dd + // Operation data length: 16 bits or 8 bits + // [21 8A dd] + case 0x8A: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 8B dd] + case 0x8B: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 96 - ADd with Carry + // adc A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 80 dd] + case 0x80: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 81 dd] + case 0x81: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 88 dd] + case 0x88: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 82 dd] + case 0x82: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 96 - ADd with Carry + // adc A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 89 dd] + case 0x89: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 83 nn] + case 0x83: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 96 - ADd with Carry + // adc A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 84 nn] + case 0x84: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 8E ll mm] + case 0x8E: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16,SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 8F ll mm] + case 0x8F: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 96 - ADd with Carry + // adc A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 86 ll mm] + case 0x86: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 8C ll mm hh] + case 0x8C: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 8D ll mm hh] + case 0x8D: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END ADC _________________________ + + // ___________________ LSR _________________________ + // 204 - Logical Shift Right + // lsr dd + // Operation data length: 16 bits or 8 bits + // [21 2A dd] + case 0x2A: + insn.itype = m7900_lsr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 204 - Logical Shift Right + // lsr dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 2B dd] + case 0x2B: + insn.itype = m7900_lsr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 204 - Logical Shift Right + // lsr mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 2E ll mm] + case 0x2E: + insn.itype = m7900_lsr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 204 - Logical Shift Right + // lsr mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 2F ll mm] + case 0x2F: + insn.itype = m7900_lsr; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END LSR _________________________ + + // ___________________ ROL _________________________ + // 254 - ROtate one bit Left + // rol dd + // Operation data length: 16 bits or 8 bits + // [21 1A dd] + case 0x1A: + insn.itype = m7900_rol; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 254 - ROtate one bit Left + // rol dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 1B dd] + case 0x1B: + insn.itype = m7900_rol; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 254 - ROtate one bit Left + // rol mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 1E ll mm] + case 0x1E: + insn.itype = m7900_rol; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 254 - ROtate one bit Left + // rol mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 1F ll mm] + case 0x1F: + insn.itype = m7900_rol; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END ROL _________________________ + // ___________________ ROR _________________________ + // 255 - ROtate one bit Right + // rol dd + // Operation data length: 16 bits or 8 bits + // [21 3A dd] + case 0x3A: + insn.itype = m7900_ror; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 255 - ROtate one bit Right + // rol dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 3B dd] + case 0x3B: + insn.itype = m7900_ror; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 255 - ROtate one bit Right + // ror mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 3E ll mm] + case 0x3E: + insn.itype = m7900_ror; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 255 - ROtate one bit Right + // ror mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 3F ll mm] + case 0x3F: + insn.itype = m7900_ror; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END ROR _________________________ + + // ___________________ ASL _________________________ + + // 116 - Arithmetic Shift to Left + // asl dd + // Operation data length: 16 bits or 8 bits + // [21 0A dd] + case 0x0A: + insn.itype = m7900_asl; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 116 - Arithmetic Shift to Left + // asl dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 0B dd] + case 0x0B: + insn.itype = m7900_asl; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 116 - Arithmetic Shift to Left + // asl mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 0E ll mm] + case 0x0E: + insn.itype = m7900_asl; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 116 - Arithmetic Shift to Left + // asl mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 0F ll mm] + case 0x0F: + insn.itype = m7900_asl; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END ASL _________________________ + + // ___________________ ASR _________________________ + + // 119 - Arithmetic Shift to Right + // asr dd + // Operation data length: 16 bits or 8 bits + // [21 4A dd] + case 0x4A: + insn.itype = m7900_asr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 119 - Arithmetic Shift to Right + // asr dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 4B dd] + case 0x4B: + insn.itype = m7900_asr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 119 - Arithmetic Shift to Right + // asr mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 4E ll mm] + case 0x4E: + insn.itype = m7900_asr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 119 - Arithmetic Shift to Right + // asr mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 4F ll mm] + case 0x4F: + insn.itype = m7900_asr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END ASR _________________________ + + // ___________________ ADCD _________________________ + + // 99 - ADd with Carry at Double-word + // adcd E, dd + // Operation data length: 32 bits + // [21 9A dd] + case 0x9A: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 32 + // [21 9B dd] + case 0x9B: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 32 bits + // [21 90 dd] + case 0x90: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 32 buts + // [21 91 dd] + case 0x91: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, (dd), Y () + // Operation data length: 32 bits + // [21 98 dd] + case 0x98: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [21 92 dd] + case 0x92: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + + // should collect 3 bytes, but collect as 2 bytes + // can use dt_tbyte + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [21 99 dd] + case 0x99: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + // should collect 3 bytes, but collect as 2 bytes + // can use dt_tbyte + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 32 bits + // [21 93 nn] + case 0x93: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 32 bits + // [21 94 nn] + case 0x94: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [21 9E ll mm] + case 0x9E: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [21 9F ll mm] + case 0x9F: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 32 bits + // [21 96 ll mm] + case 0x96: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 9C ll mm hh] + case 0x9C: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 99 - ADd with Carry at Double-word + // adcd A, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [21 9D ll mm hh] + case 0x9D: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END ADCD _________________________ + + // ___________________ DIV _________________________ + // 174 - DIVide unsigned + // div A, dd + // Operation data length: 16 bits or 8 bits + // [21 EA dd] + case 0xEA: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 174 - DIVide unsigned + // div A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 EB dd] + case 0xEB: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 174 - DIVide unsigned + // div A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 E0 dd] + case 0xE0: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 174 - DIVide unsigned + // div A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 E1 dd] + case 0xE1: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 174 - DIVide unsigned + // div A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 E8 dd] + case 0xE8: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 174 - DIVide unsigned + // div A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 E2 dd] + case 0xE2: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 174 - DIVide unsigned + // div A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 E9 dd] + case 0xE9: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op2, rY); + break; + + // 174 - DIVide unsigned + // div A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 E3 nn] + case 0xE3: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_SP, 8); + Operand_Registr(insn.Op2, rPS); + break; + + // 174 - DIVide unsigned + // div A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 E4 nn] + case 0xE4: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op2, rY); + break; + + // 174 - DIVide unsigned + // div A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 EE ll mm] + case 0xEE: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 174 - DIVide unsigned + // div A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 EF ll mm] + case 0xEF: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 174 - DIVide unsigned + // div A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 E6 ll mm] + case 0xE6: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 174 - DIVide unsigned + // div A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 EC ll mm hh] + case 0xEC: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); + break; + + // 174 - DIVide unsigned + // div A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 ED ll mm hh] + case 0xED: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END DIV _________________________ + // ___________________ DIVS _________________________ + // 176 - DIVide with Sign + // divs A, dd + // Operation data length: 16 bits or 8 bits + // [21 FA dd] + case 0xFA: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 176 - DIVide with Sign + // divs A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 FB dd] + case 0xFB: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 176 - DIVide with Sign + // divs A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 F0 dd] + case 0xF0: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 176 - DIVide with Sign + // divs A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 F1 dd] + case 0xF1: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 176 - DIVide with Sign + // divs A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 F8 dd] + case 0xF8: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 176 - DIVide with Sign + // divs A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 F2 dd] + case 0xF2: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 176 - DIVide with Sign + // divs A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 F9 dd] + case 0xF9: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op2, rY); + break; + + // 176 - DIVide with Sign + // divs A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 F3 nn] + case 0xF3: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_SP, 8); + Operand_Registr(insn.Op2, rPS); + break; + + // 176 - DIVide with Sign + // divs A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 F4 nn] + case 0xF4: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op2, rY); + break; + + // 176 - DIVide with Sign + // divs A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 FE ll mm] + case 0xFE: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 176 - DIVide with Sign + // divs A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 FF ll mm] + case 0xFF: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 176 - DIVide with Sign + // divs A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 F6 ll mm] + case 0xF6: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 176 - DIVide with Sign + // divs A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 FC ll mm hh] + case 0xFC: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); + break; + + // 176 - DIVide with Sign + // divs A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 FD ll mm hh] + case 0xFD: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END DIVS _________________________ + + // ___________________ MPY _________________________ + // 212 - MultiPlY + // Operation data length: 16 bits or 8 bits + // [21 CA dd] + case 0xCA: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 212 - MultiPlY + // mpy dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 CB dd] + case 0xCB: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 212 - MultiPlY + // mpy (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 C0 dd] + case 0xC0: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 212 - MultiPlY + // mpy (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 C1 dd] + case 0xC1: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 212 - MultiPlY + // mpy (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 C8 dd] + case 0xC8: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 212 - MultiPlY + // mpy L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 C2 dd] + case 0xC2: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 212 - MultiPlY + // mpy L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 C9 dd] + case 0xC9: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op2, rY); + break; + + // 212 - MultiPlY + // mpy nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 C3 nn] + case 0xC3: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_SP, 8); + Operand_Registr(insn.Op2, rPS); + break; + + // 212 - MultiPlY + // mpy (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 C4 nn] + case 0xC4: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op2, rY); + break; + + // 212 - MultiPlY + // mpy mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 CE ll mm] + case 0xCE: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 212 - MultiPlY + // mpy mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 CF ll mm] + case 0xCF: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 212 - MultiPlY + // mpy A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 C6 ll mm] + case 0xC6: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 212 - MultiPlY + // mpy hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 CC ll mm hh] + case 0xCC: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); + break; + + // 212 - MultiPlY + // mpy hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 CD ll mm hh] + case 0xCD: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END MPY _________________________ + // ___________________ MPYS _________________________ + // 213 - MultiPlY with Sign + // Operation data length: 16 bits or 8 bits + // [21 DA dd] + case 0xDA: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 213 - MultiPlY with Sign + // mpys dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 DB dd] + case 0xDB: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 213 - MultiPlY with Sign + // mpys (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 D0 dd] + case 0xD0: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 213 - MultiPlY with Sign + // mpys (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 D1 dd] + case 0xD1: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 213 - MultiPlY with Sign + // mpys (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 D8 dd] + case 0xD8: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 213 - MultiPlY with Sign + // mpys L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 D2 dd] + case 0xD2: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 213 - MultiPlY with Sign + // mpys L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 D9 dd] + case 0xD9: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op2, rY); + break; + + // 213 - MultiPlY with Sign + // mpys nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 D3 nn] + case 0xD3: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_SP, 8); + Operand_Registr(insn.Op2, rPS); + break; + + // 213 - MultiPlY with Sign + // mpys (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 D4 nn] + case 0xD4: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_SR(insn, insn.Op1, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op2, rY); + break; + + // 213 - MultiPlY with Sign + // mpys mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 DE ll mm] + case 0xDE: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // 213 - MultiPlY with Sign + // mpys mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 DF ll mm] + case 0xDF: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 213 - MultiPlY with Sign + // mpys A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 D6 ll mm] + case 0xD6: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + + // 213 - MultiPlY with Sign + // mpys hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 DC ll mm hh] + case 0xDC: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL, 24, SetTypeDataM); + break; + + // 213 - MultiPlY with Sign + // mpys hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 DD ll mm hh] + case 0xDD: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // ___________________ END MPYS _________________________ + + // ___________________ SBC _________________________ + // 264 - SuBtract with Carry + // sbc A, dd + // Operation data length: 16 bits or 8 bits + // [21 AA dd] + case 0xAA: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 AB dd] + case 0xAB: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 264 - SuBtract with Carry + // sbc A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 A0 dd] + case 0xA0: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 A1 dd] + case 0xA1: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 A8 dd] + case 0xA8: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 A2 dd] + case 0xA2: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 264 - SuBtract with Carry + // sbc A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 A9 dd] + case 0xA9: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 A3 nn] + case 0xA3: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 264 - SuBtract with Carry + // sbc A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 A4 nn] + case 0xA4: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 AE ll mm] + case 0xAE: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 AF ll mm] + case 0xAF: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 264 - SuBtract with Carry + // sbc A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 A6 ll mm] + case 0xA6: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 AC ll mm hh] + case 0xAC: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 AD ll mm hh] + case 0xAD: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END sbc _________________________ + + // ___________________ SBCD _________________________ + // 266 - SuBtract with Carry at Double-word + // sbcd E, dd + // Operation data length: 16 bits or 8 bits + // [21 BA dd] + case 0xBA: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 BB dd] + case 0xBB: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 B0 dd] + case 0xB0: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 B1 dd] + case 0xB1: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 B8 dd] + case 0xB8: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 B2 dd] + case 0xB2: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 B9 dd] + case 0xB9: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 B3 nn] + case 0xB3: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 B4 nn] + case 0xB4: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd BE mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 BE ll mm] + case 0xBE: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 BF ll mm] + case 0xBF: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 B6 ll mm] + case 0xB6: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 BC ll mm hh] + case 0xBC: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 BD ll mm hh] + case 0xBD: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END SBCD _________________________ + + default: + return 0; + } + + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_31(insn_t &insn) +{ + TRACE("Opcode_31"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + uchar nib = (code >> 4) & 0xF; + + switch ( code ) + { + + // _____________________ JMPJMPL ____________________ + // 192 - JuMP + // jmp (mmll) + // Operation data - + // [31 5C ll mm] + case 0x5C:// jmp (mmll) ((ABS)) + insn.itype = m7900_jmp; + Operand_AB(insn, insn.Op1, TAB_INDIRECTED_ABS, 16, dt_word); + break; + + // 192 - JuMP + // jmp L(mmll) + // Operation data - + // [31 5D ll mm] + case 0x5D:// jmp L(mmll) (L(ABS)) + insn.itype = m7900_jmp; + Operand_AB(insn, insn.Op1, TAB_L_INDIRECTED_ABS, 16, dt_tbyte); + break; + // _____________________ END JMP/JMPL ____________________ + + // 232 - PusH proGram bank register on stack + // phg + // Operation data length: 8 bits + // [31 60] + case 0x60: + insn.itype = m7900_phg; + RAZOPER = INSN_PREF_U; + break; + + // 235 - + // pht + // Operation data length: 8 bits + // [31 40] + case 0x40: + insn.itype = m7900_pht; + RAZOPER = INSN_PREF_U; + break; + + // 243 - PuLl daTa bank register from stack + // plt + // Operation data length: 8 bits + // [31 50] + case 0x50: + insn.itype = m7900_plt; + RAZOPER = INSN_PREF_U; + break; + + // 96 - ADd with Carry + // adc A, #imm + // Operation data length: 16 bits or 8 bits + // [31 87 imm] + case 0x87: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 274 - + // stp + // Operation data length: - + // [31 30] + case 0x30: + insn.itype = m7900_stp; + break; + + // 284 - SUBtract Stack pointer + // subs #imm + // Operation data length: 16 bits + // [31 0B imm] + case 0x0B: + insn.itype = m7900_subs; + RAZOPER = INSN_PREF_W; + Operand_Imm(insn, insn.Op1, 8); + break; + + // 288 - Transfer accumulator A to Stack pointer + // tas + // Operation data length: 16 bits + // [31 82] + case 0x82: + insn.itype = m7900_tas; + break; + + // 297 - Transfer Direct page register to Stack pointer + // tds + // Operation data length: 16 bits + // [31 73] + case 0x73: + insn.itype = m7900_tds; + break; + + // 298- Transfer Stack pointer to accumulator A + // tsa + // Operation data length: 16 bits or 8 bit + // [31 92] + case 0x92: + insn.itype = m7900_tsa; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + // 300- Transfer Stack pointer to Direct page register + // tsd + // Operation data length: 16 bits + // [31 70] + case 0x70: + insn.itype = m7900_tsd; + break; + + // 301- Transfer Stack pointer to index register X + // tsx + // Operation data length: 16 bits or 8 bits + // [31 F2] + case 0xF2: + insn.itype = m7900_tsx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + // 304- Transfer index register X to Stack pointer + // txs + // Operation data length: 16 bits or 8 bits + // [31 E2] + case 0xE2: + insn.itype = m7900_txs; + break; + + // 305- Transfer index register X to Y + // txy + // Operation data length: 16 bits or 8 bits + // [31 C2] + case 0xC2: + insn.itype = m7900_txy; + break; + + // 308- Transfer index register Y to X + // tyx + // Operation data length: 16 bits or 8 bits + // [31 D2] + case 0xD2: + insn.itype = m7900_tyx; + break; + + // 309- WaIT + // wit + // Operation data length: 16 bits or 8 bits + // [31 10] + case 0x10: + insn.itype = m7900_wit; + break; + + //---------------------------BYTE-------------------------------------// + // 98 - ADd with Carry at Byte + // adcb A, #imm + // Operation data length: 8 bits + // [31 1A imm] + case 0x1A: + insn.itype = m7900_adcb; + RAZOPER = 8; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 199 - LoaD immediate to DaTa bank register + // ldt A, #imm + // Operation data length: 8 bits + // [31 4A imm] + case 0x4A: + insn.itype = m7900_ldt; + RAZOPER = INSN_PREF_U; + Operand_Imm(insn, insn.Op1, 8); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb mmll, #imm + // Operation data length: 8 bits + // [3B imm ll mm] + case 0x3B: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Imm(insn, insn.Op3, 8); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Registr(insn.Op2, rX); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb dd, #imm + // Operation data length: 8 bits + // [3A imm dd] + case 0x3A: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op3, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + Operand_Registr(insn.Op2, rX); + break; + + // 265 - SuBtract with Carry at Byte + // sbcb A, #imm + // Operation data length: 8 bits + // [31 1B imm] + case 0x1B: + insn.itype = m7900_sbcb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + //---------------------------WORD------------------------------------// + + // 107 - ADD Stack pointer and immediate + // adds #imm + // Operation data length: 16 bits + // [31 0A imm] + case 0x0A: + insn.itype = m7900_adds; + RAZOPER = INSN_PREF_W; + Operand_Imm(insn, insn.Op1, 8); + break; + + //---------------------------DWORD------------------------------------// + + // 95 - ABSolute at Double-word + // absd E + // Operation data length: 32 bits + // [31 90] + case 0x90: + insn.itype = m7900_absd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + break; + + // 186 - EXTension Sign at Double-word + // extsd E + // Operation data length: 32 bits + // [31 B0] + case 0xB0:// extsd + insn.itype = m7900_extsd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + break; + + // 188 - EXTension Zero at Double-word + // extzd E + // Operation data length: 32 bits + // [31 A0] + case 0xA0:// extsd + insn.itype = m7900_extzd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + break; + + // 99 - ADd with Carry at Double-word + // adcd E, #imm + // Operation data length: 32 bits + // [31 1C imm imm imm imm] + case 0x1C: + insn.itype = m7900_adcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 217 - NEGative at Double-word + // negd E + // Operation data length: 32 bits + // [31 80] + case 0x80: + insn.itype = m7900_negd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + break; + + // 266 - SuBtract with Carry at Double-word + // sbcd E + // Operation data length: 32 bits + // [31 1D] + case 0x1D: + insn.itype = m7900_sbcd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm(insn, insn.Op2, 32); + break; + + //---------------------------WORD/byte------------------------------------// + + // 174 - DIVide unsigned + // div #imm + // Operation data length: 16 bits or 8 bits + // [31 E7 imm] + case 0xE7: + insn.itype = m7900_div; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + break; + + // 174 - DIVide with Sign + // divs #imm + // Operation data length: 16 bits or 8 bits + // [31 F7 imm] + case 0xF7: + insn.itype = m7900_divs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + break; + + // 207 - MOVe Memory to memory + // movm mmll, X, #imm + // Operation data length: 16 bits or 8 bits + // [31 57 imm] + case 0x57: + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op3, getFlag_M ? 8 : 16); + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // 207 - MOVe Memory to memory + // movm #imm dd + // Operation data length: 16 bits or 8 bits + // [31 47 imm] + case 0x47: + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op3, getFlag_M ? 8 : 16); + Operand_Dir(insn, insn.Op1, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + // _____________________ MPY ____________________ + // 212 - MultiPlY + // MPY #imm + // Operation data - 16 bits or 8 bits + // [31 C7 imm] + case 0xC7: + insn.itype = m7900_mpy; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + break; + // _____________________ END MPY ____________________ + + // _____________________ MPYS ____________________ + // 213 - MultiPlY + // MPYS #imm + // Operation data - 16 bits or 8 bits + // [31 D7 imm] + case 0xD7: + insn.itype = m7900_mpys; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + break; + // _____________________ END MPY ____________________ + // _____________________ MVN ____________________ + // 214 - MoVe Negative + // mvn hh1 hh2 + // Operation data - 16 bits or 8 bits + // [31 2B hh1 hh2] + case 0x2B: + insn.itype = m7900_mvn; + Operand_Dir(insn, insn.Op1, TDIR_DIR); + Operand_Dir(insn, insn.Op2, TDIR_DIR); + break; + // _____________________ END MVN ____________________ + + // _____________________ MVP ____________________ + // 215 - MoVe Positive + // mvp hh1 hh2 + // Operation data - 16 bits or 8 bits + // [31 2A hh1 hh2] + case 0x2A: + insn.itype = m7900_mvp; + Operand_Dir(insn, insn.Op1, TDIR_DIR); + Operand_Dir(insn, insn.Op2, TDIR_DIR); + break; + // _____________________ END MVP ____________________ + + case 0x4B:// pei + insn.itype = m7900_pei; + RAZOPER = INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR); + break; + + case 0x4C:// pea + insn.itype = m7900_pea; + RAZOPER = INSN_PREF_W; + Operand_STK(insn, insn.Op1, 16); + break; + + case 0x4D:// per + insn.itype = m7900_per; + RAZOPER = INSN_PREF_W; + Operand_STK(insn, insn.Op1, 16); + break; + + // _____________________ RLA ____________________ + // 250 - Rotate Left accumulator A + // RLA #imm + // Operation data - 16 bits or 8 bits + // [31 07 imm] + case 0x07: + insn.itype = m7900_rla; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + break; + // _____________________ END RLA ____________________ + + // _____________________ RMPA ____________________ + // 250 - Repeat Multiply and Accumulate + // RMPA #imm + // Operation data - 16 bits or 8 bits + // [31 5A imm] + case 0x5A: + insn.itype = m7900_rmpa; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END RMPA ____________________ + // _____________________ SBC ____________________ + // 264 - SuBtract with Carry + // sbc A,#imm + // Operation data - 16 bits or 8 bits + // [31 A7 imm] + case 0xA7: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _____________________ END SBC ____________________ + + default: + { + uchar cm = code & 0x40; + if ( cm == 0x40 ) + { + insn.itype = m7900_tdan; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, (((code-0x40) >> 4) & 0xF)+0x1); + } + else + { + insn.itype = m7900_tadn; + Operand_Imm_Spesh(insn.Op1, dt_byte, nib); + } + } + break; + } + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_41(insn_t &insn) +{ + TRACE("Opcode_41"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + // ________________________ BBC________________________ + + // 122 -Branch on Bit Clear + // bbc #imm dd rr (DIR) + // Operation data length: 16 bits or 8 bits + // [41 5A dd imm rr] + case 0x5A: + insn.itype = m7900_bbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + Operand_BBC(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); + break; + + // 122 -Branch on Bit Clear + // bbc #imm mmll rr (ABS) + // Operation data length: 16 bits or 8 bits + // [41 5E ll mm imm rr] + case 0x5E: + insn.itype = m7900_bbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + Operand_BBC(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 6 : 7); + break; + + // ________________________ END BBC________________________ + // ________________________ BBS________________________ + + // 124 - Branch on Bit Set + // bbs #imm dd rr (DIR) + // Operation data length: 16 bits or 8 bits + // [41 4A dd imm rr] + case 0x4A: + insn.itype = m7900_bbs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + Operand_BBS(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); + break; + + // 124 - Branch on Bit Set + // bbs #imm mmll rr (ABS) + // Operation data length: 16 bits or 8 bits + // [41 4E ll mm imm rr] + case 0x4E: + insn.itype = m7900_bbs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_Imm(insn, insn.Op1, getFlag_M ? 8 : 16); + Operand_BBS(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 6 : 7); + break; + // ________________________ END BBS________________________ + + // _____________________ CBEQ ____________________ + + // 145 - Compare immediate and Branch on EQual + // cbeq dd, #imm, rr + // Operation data length: 16 bits or 8 bits + // [41 6A dd imm rr] + case 0x6A: + insn.itype = m7900_cbeq; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); + break; + // _____________________ END CBEQ ____________________ + + // _____________________ CBNE ____________________ + + // 147 - Compare immediate and Branch on Not Equal + // cbne dd, #imm, rr + // Operation data length: 16 bits or 8 bits + // [7A dd imm rr] + case 0x7A: + insn.itype = m7900_cbne; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 5 : 6); + break; + // _____________________ END CBNE ____________________ + // _____________________ CPX ____________________ + // 167 - ComPare memory and index register X + // cpx mmll + // Operation data length: 16 bits or 8 bits + // [41 2E ll mm] + case 0x2E: + insn.itype = m7900_cpx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_X ? 8 : 16, SetTypeDataX); + break; + // _____________________ END CPX ____________________ + // 168 - ComPare memory and index register Y + // cpy mmll + // Operation data length: 16 bits or 8 bits + // [41 3E ll mm] + case 0x3E:// cpy + insn.itype = m7900_cpy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataX); + break; + + // _____________________ DEC ____________________ + // 170 - DECrement by one + // dec dd, X + // Operation data - 16 bits or 8 bits + // [41 9B dd] + case 0x9B: + insn.itype = m7900_dec; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + case 0x9F:// dec + insn.itype = m7900_dec; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // _____________________ END DEC ____________________ + + // _____________________ INC ____________________ + // 189 - INCrement by one + // inc dd, X + // Operation data - 16 bits or 8 bits + // [41 8B dd] + case 0x8B: + insn.itype = m7900_inc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + + case 0x8F:// inc + insn.itype = m7900_inc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rX); + break; + // _____________________ END INC ____________________ + + // _____________________ DEX ____________________ + // 171 - DEcrement index register X by one + // dex + // Operation data - 16 bits or 8 bits + // [E3] + case 0xE3: + insn.itype = m7900_dex; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + // _____________________ END DEX ____________________ + // _____________________ DEY ____________________ + // 172 - DEcrement index register Y by one + // dex + // Operation data - 16 bits or 8 bits + // [F3] + case 0xF3: + insn.itype = m7900_dey; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + // _____________________ END DEY ____________________ + + + // _____________________ LDX ____________________ + // 200 - Load + // ldx dd, Y + // Operation data - 16 bits or 8 bits + // [41 05 dd] + case 0x05: + insn.itype = m7900_ldx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + Operand_Registr(insn.Op2, rY); + break; + + case 0x06: + insn.itype = m7900_ldx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op2, rY); + break; + // _____________________ END LDX ____________________ + + // _____________________ LDY ____________________ + // 202 - LoaD index register Y from memory + // ldy dd, X + // Operation data - 16 bits or 8 bits + // [41 1B dd] + case 0x1B: + insn.itype = m7900_ldy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + Operand_Registr(insn.Op2, rX); + break; + + case 0x1F: + insn.itype = m7900_ldy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS_X, 16); + Operand_Registr(insn.Op2, rX); + break; + // _____________________ END INC ____________________ + // _____________________ STX ____________________ + // 275 - STore index register X in memory + // stx dd, Y + // Operation data - 16 bits or 8 bits + // [41 E5 dd] + case 0xE5:// stx dd,Y (DIR,Y) + insn.itype = m7900_stx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_Y, SetTypeDataX); + Operand_Registr(insn.Op2, rY); + break; + // _____________________ END STX ____________________ + + // _____________________ STY ____________________ + // 276 - STore index register Y in memory + // sty dd, X + // Operation data - 16 bits or 8 bits + // [41 FB dd] + case 0xFB:// sty dd,X (DIR,X) + insn.itype = m7900_sty; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR_Y, SetTypeDataX); + Operand_Registr(insn.Op2, rX); + break; + // _____________________ END STX ____________________ + + default: + return 0; + } + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_51(insn_t &insn) +{ + TRACE("Opcode_51"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + //---------------------------BYTE-------------------------------------// + // 105 - ADD immediate and Memory at Byte + // addmb dd, #imm + // Operation data length: 8 bits + // [51 02 dd imm] + case 0x02: + insn.itype = m7900_addmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 105 - ADD immediate and Memory at Byte + // addmb mmll, #imm + // Operation data length: 8 bits + // [51 06 ll mm imm] + case 0x06: + insn.itype = m7900_addmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 114 - logical AND between immediate value and Memory (Byte) + // andmb dd, #imm + // Operation data length: 8 bits + // [51 62 dd imm] + case 0x62: + insn.itype = m7900_andmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 105 - ADD immediate and Memory at Byte + // addmb mmll, #imm + // Operation data length: 8 bits + // [51 66 ll mm imm] + case 0x66: + insn.itype = m7900_andmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 165 - CoMPare immediate with Memory at Byte + // cmpmb dd, #imm + // Operation data length: 8 bits + // [51 22 dd imm] + case 0x22: + insn.itype = m7900_cmpmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 165 - CoMPare immediate with Memory at Byte + // cmpmb mmll, #imm + // Operation data length: 8 bits + // [51 26 ll mm imm] + case 0x26: + insn.itype = m7900_cmpmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 183 - Exclusive OR immediate with Memory at Byte + // eormb dd, #imm + // Operation data length: 8 bits + // [51 72 dd imm] + case 0x72: + insn.itype = m7900_eormb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 183 - Exclusive OR immediate with Memory at Byte + // eormb mmll, #imm + // Operation data length: 8 bits + // [51 76 ll mm imm] + case 0x76: + insn.itype = m7900_eormb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 223 - OR immediAte with Memory at Byte + // oramb dd, #imm + // Operation data length: 8 bits + // [51 32 dd imm] + case 0x32: + insn.itype = m7900_oramb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 223 - OR immediAte with Memory at Byte + // oramb mmll, #imm + // Operation data length: 8 bits + // [51 36 ll mm imm] + case 0x36: + insn.itype = m7900_oramb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 282 - SUBtract immediate from Memory at Byte SUBMB + // submb dd, #imm + // Operation data length: 8 bits + // [51 12 dd imm] + case 0x12: + insn.itype = m7900_submb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 282 - SUBtract immediate from Memory at Byte SUBMB + // submb mmll, #imm + // Operation data length: 8 bits + // [51 16 ll mm imm] + case 0x16: + insn.itype = m7900_submb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + break; + + // __________________________ ADDM ___________________ + // 104 - ADD immediate and Memory + // addm dd, #imm + // Operation data length: 16 bits or 8 bits + // [51 03 dd imm] + case 0x03: + insn.itype = m7900_addm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 104 - ADD immediate and Memory + // addm mmll, #imm + // Operation data length: 16 bits or 8 bits + // [51 07 ll mm imm] + case 0x07: + insn.itype = m7900_addm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _______________________END ADDM ___________________ + + // __________________________ ANDM ___________________ + // 113 - logical AND between immediate value and Memory + // andm dd, #imm + // Operation data length: 16 bits or 8 bits + // [51 63 dd imm] + case 0x63: + insn.itype = m7900_andm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 113 - logical AND between immediate value and Memory + // andm mmll, #imm + // Operation data length: 16 bits or 8 bits + // [51 67 ll mm imm] + case 0x67: + insn.itype = m7900_andm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _______________________END ANDM ___________________ + // __________________________ CMPM ___________________ + // 164 - CoMPare immediate with Memory + // cmpm dd, #imm + // Operation data length: 16 bits or 8 bits + // [51 23 dd imm] + case 0x23: + insn.itype = m7900_cmpm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 164 - CoMPare immediate with Memory + // cmpm mmll, #imm + // Operation data length: 16 bits or 8 bits + // [51 27 ll mm imm] + case 0x27: + insn.itype = m7900_cmpm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _______________________END CMPM ___________________ + + // __________________________ EORM ___________________ + // 182 - Exclusive OR immediate with Memory + // eorm dd, #imm + // Operation data length: 16 bits or 8 bits + // [51 73 dd imm] + case 0x73: + insn.itype = m7900_eorm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 182 - Exclusive OR immediate with Memory + // eorm mmll, #imm + // Operation data length: 16 bits or 8 bits + // [51 77 ll mm imm] + case 0x77: + insn.itype = m7900_eorm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _______________________END EORM ___________________ + + // __________________________ ORAM ___________________ + // 222 - OR immediAte with Memory + // oram dd, #imm + // Operation data length: 16 bits or 8 bits + // [51 33 dd imm] + case 0x33: + insn.itype = m7900_oram; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 222 - OR immediAte with Memory + // oram mmll, #imm + // Operation data length: 16 bits or 8 bits + // [51 37 ll mm imm] + case 0x37: + insn.itype = m7900_oram; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _______________________END oraM ___________________ + + // __________________________ subM ___________________ + // 281 - SUBtract immediate from Memory + // subm dd, #imm + // Operation data length: 16 bits or 8 bits + // [51 13 dd imm] + case 0x13: + insn.itype = m7900_subm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 281 - SUBtract immediate from Memory + // subm mmll, #imm + // Operation data length: 16 bits or 8 bits + // [51 17 ll mm imm] + case 0x17: + insn.itype = m7900_subm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 8, SetTypeDataM); + + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _______________________END subM ___________________ + + // __________________________ ADDMD ___________________ + // 106 - ADD immediate and Memory at Double-word + // addmd dd, #imm32 + // Operation data length: 32 bits + // [51 83 dd imm imm imm imm] + case 0x83: + insn.itype = m7900_addmd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 106 - ADD immediate and Memory at Double-word + // addmd mmll, #imm32 + // Operation data length: 32 bits + // [51 87 ll mm imm imm imm imm] + case 0x87: + insn.itype = m7900_addmd; + RAZOPER = INSN_PREF_D; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + // _______________________END ADDMD ___________________ + + // __________________________ ANDMD ___________________ + // 115 - logical AND between immediate value and Memory (Double word) + // andmd dd, #imm32 + // Operation data length: 32 bits + // [51 E3 dd imm imm imm imm] + case 0xE3: + insn.itype = m7900_andmd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 115 - logical AND between immediate value and Memory (Double word) + // andmd mmll, #imm32 + // Operation data length: 32 bits + // [51 E7 ll mm imm imm imm imm] + case 0xE7: + insn.itype = m7900_andmd; + RAZOPER = INSN_PREF_D; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + // _______________________END ADDMD ___________________ + + // __________________________ CMPMD ___________________ + // 166 - CoMPare immediate with Memory at Double-word + // cmpmd dd, #imm32 + // Operation data length: 32 bits + // [51 A3 dd imm imm imm imm] + case 0xA3: + insn.itype = m7900_cmpmd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 166 - CoMPare immediate with Memory at Double-word + // cmpmd mmll, #imm32 + // Operation data length: 32 bits + // [51 A7 ll mm imm imm imm imm] + case 0xA7: + insn.itype = m7900_cmpmd; + RAZOPER = INSN_PREF_D; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + // _______________________END CMPMD ___________________ + + // __________________________ EORMD ___________________ + // 184 - Exclusive OR immediate with Memory at Double-word + // eormd dd, #imm32 + // Operation data length: 32 bits + // [51 F3 dd imm imm imm imm] + case 0xF3: + insn.itype = m7900_eormd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 184 - Exclusive OR immediate with Memory at Double-word + // eormd mmll, #imm32 + // Operation data length: 32 bits + // [51 F7 ll mm imm imm imm imm] + case 0xF7: + insn.itype = m7900_eormd; + RAZOPER = INSN_PREF_D; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + // _______________________END EORMD ___________________ + + // __________________________ ORAMD ___________________ + // 224 -OR immediAte with Memory at Double-word + // oramd dd, #imm32 + // Operation data length: 32 bits + // [51 B3 dd imm imm imm imm] + case 0xB3: + insn.itype = m7900_oramd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 224 - OR immediAte with Memory at Double-word + // oramd mmll, #imm32 + // Operation data length: 32 bits + // [51 B7 ll mm imm imm imm imm] + case 0xB7: + insn.itype = m7900_oramd; + RAZOPER = INSN_PREF_D; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + // _______________________END ORAMD ___________________ + + // __________________________ SUBMD ___________________ + // 283 - SUBtract immediate from Memory at Double-word + // submd dd, #imm32 + // Operation data length: 32 bits + // [51 93 dd imm imm imm imm] + case 0x93: + insn.itype = m7900_submd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 283 - SUBtract immediate from Memory at Double-word + // submd mmll, #imm32 + // Operation data length: 32 bits + // [51 97 ll mm imm imm imm imm] + case 0x97: + insn.itype = m7900_submd; + RAZOPER = INSN_PREF_D; + Operand_Dir(insn, insn.Op1, TAB_ABS, dt_dword); + Operand_Imm(insn, insn.Op2, 32); + break; + // _______________________END ORAMD ___________________ + + default: + return 0; + } + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_81(insn_t &insn) +{ + TRACE("Opcode_81"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + case 0x85:// phb + insn.itype = m7900_phb; + break; + // [ 81 A4] + case 0xA4:// txb + insn.itype = m7900_txb; + break; + + case 0xB4:// tyb + insn.itype = m7900_tyb; + break; + + case 0x95:// plb + insn.itype = m7900_plb; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + // 116 - Arithmetic Shift to Left + // asl B + // Operation data length: 16 bits or 8 bits + // [81 03] + case 0x03:// asl + insn.itype = m7900_asl; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + + // 119 - Arithmetic Shift to Right + // asr B + // Operation data length: 16 bits or 8 bits + // [64] + case 0x64:// asr + insn.itype = m7900_asr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + + // 94 - Absolute value + // abs B + case 0xE1: + insn.itype = m7900_abs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + + // 185 - EXTension Sign + // exts B + // Operation data length: 16 bits + // [35] + case 0x35:// exts + insn.itype = m7900_exts; + RAZOPER = INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + + // 187 - EXTension Zero + // extz B + // Operation data length: 16 bits + // [34] + case 0x34:// extz + insn.itype = m7900_extz; + RAZOPER = INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + + // 216 - NEGative + // neg B + // Operation data length: 16 bits or 8 bits + // [24] + case 0x24:// neg + insn.itype = m7900_neg; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + + // 293 - Transfer accumulator B to index register X + // tbx + // Operation data length: 16 bits or 8 bits + // [C4] + case 0xC4: + insn.itype = m7900_tbx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + // 294 - Transfer accumulator B to index register Y + // tby + // Operation data length: 16 bits or 8 bits + // [D4] + case 0xD4: + insn.itype = m7900_tby; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + // _____________________ DEC ____________________ + // 170 - DECrement by one + // dec B + // Operation data - 16 bits or 8 bits + // [B3] + case 0xB3: + insn.itype = m7900_dec; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + // _____________________ END DEC ____________________ + + // _____________________ INC ____________________ + // 189 - INCrement by one + // inc B + // Operation data - 16 bits or 8 bits + // [A3] + case 0xA3: + insn.itype = m7900_inc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + // _____________________ END INC ____________________ + + // _____________________ LSR ____________________ + // 204 - Logical Shift Right + // lsr B + // Operation data - 16 bits or 8 bits + // [43] + case 0x43: + insn.itype = m7900_lsr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + // _____________________ END LSR ____________________ + // _____________________ ROL ____________________ + // 254 - ROtate one bit Left + // rol B + // Operation data - 16 bits or 8 bits + // [13] + case 0x13: + insn.itype = m7900_rol; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + // _____________________ END ROL ____________________ + // _____________________ ROR ____________________ + // 255 - ROtate one bit Right + // ror B + // Operation data - 16 bits or 8 bits + // [53] + case 0x53:// ror + insn.itype = m7900_ror; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + // _____________________ END ROR ____________________ + + //---------------------------BYTE/WORD-------------------------------------// + // _____________________ ADD ____________________ + // 101 - ADd + // add B, #imm + // Operation data length: 16 bits or 8 bits + // [26 imm] + case 0x26: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 101 - ADd + // add B, dd + // Operation data length: 16 bits or 8 bits + // [2A dd] + case 0x2A: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR,SetTypeDataM); + break; + + // 101 - ADd + // add B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [2B dd] + case 0x2B: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 101 - ADd + // add B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [2E ll mm] + case 0x2E: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 101 - ADd + // add B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [2F ll mm] + case 0x2F: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END ADD ____________________ + // _____________________ CMP ____________________ + // 161 - CoMPare + // cmp B, #imm + // Operation data length: 16 bits or 8 bits + // [46 imm] + case 0x46: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 161 - CoMPare + // cmp B, dd + // Operation data length: 16 bits or 8 bits + // [4A dd] + case 0x4A: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [4B dd] + case 0x4B: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 161 - CoMPare + // cmp B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [4E ll mm] + case 0x4E: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [4F ll mm] + case 0x4F: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END CMP ____________________ + + // _____________________ AND ____________________ + + // 111 - logical AND + // and B, #imm + // Operation data length: 16 bits or 8 bits + // [66 imm] + case 0x66: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 111 - logical AND + // and B, #imm + // Operation data length: 16 bits or 8 bits + // [6A dd] + case 0x6A: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 111 - logical AND + // and B, #imm + // Operation data length: 16 bits or 8 bits + // [6B dd] + case 0x6B: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 111 - logical AND + // and B, #imm + // Operation data length: 16 bits or 8 bits + // [6E ll mm] + case 0x6E: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 111 - logical AND + // and B, #imm + // Operation data length: 16 bits or 8 bits + // [6F ll mm] + case 0x6F: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END AND ____________________ + + // _____________________ CBEQ ____________________ + + // 145 - Compare immediate and Branch on EQual + // cbeq B, #imm, rr + // Operation data length: 16 bits or 8 bits + // [A6 imm rr] + case 0xA6: + insn.itype = m7900_cbeq; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 4 : 5); + break; + // _____________________ END CBEQ ____________________ + // _____________________ CBNE ____________________ + // 147 - Compare immediate and Branch on Not Equal + // cbne B, #imm, rr + // Operation data length: 16 bits or 8 bits + // [B6 imm rr] + case 0xB6: + insn.itype = m7900_cbne; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 4 : 5); + break; + // _____________________ END CBNE ____________________ + + // _____________________ CLr ____________________ + // 153 - CLeaR accumulator + // clr B + // Operation data length: 16 bits or 8 bits + // [54] + case 0x54:// clr + insn.itype = m7900_clr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + break; + // _____________________ END CLr ____________________ + + // _____________________ EOR ____________________ + // 180 - Exclusive OR memory with accumulator + // eor B, #imm + // Operation data length: 16 bits or 8 bits + // [76 imm] + case 0x76: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, dd + // Operation data length: 16 bits or 8 bits + // [7A dd] + case 0x7A: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [7B dd] + case 0x7B: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [7E ll mm] + case 0x7E: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [7F ll mm] + case 0x7F: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END EOR ____________________ + + // _____________________ LDA ____________________ + // 195 - LoaD Accumulator from memory + // lda B, #imm + // Operation data length: 16 bits or 8 bits + // [16 imm] + case 0x16: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 195 - LoaD Accumulator from memory + // lda B, dd + // Operation data length: 16 bits or 8 bits + // [1A dd] + case 0x1A: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [1B dd] + case 0x1B: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 195 - LoaD Accumulator from memory + // lda B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [18 dd] + case 0x18: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 195 - LoaD Accumulator from memory + // lda B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [19 dd] + case 0x19: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 195 - LoaD Accumulator from memory + // lda B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [1E ll mm] + case 0x1E: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [1F ll mm] + case 0x1F: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 195 - LoaD Accumulator from memory + // lda B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [1C ll mm hh] + case 0x1C: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda B, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [1D ll mm hh] + case 0x1D: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END LDA ____________________ + + // _____________________ LDAB ____________________ + // 196 - LoaD Accumulator from memory at Byte + // ldab B, #imm + // Operation data length: 16 bits + // [28 imm] + case 0x28: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, dd + // Operation data length: 16 bits + // [0A dd] + case 0x0A: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits + // [0B dd] + case 0x0B: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X); + Operand_Registr(insn.Op3, rX); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [08 dd] + case 0x08: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); + Operand_Registr(insn.Op3, rY); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits + // [09 dd] + case 0x09: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [0E ll mm] + case 0x0E: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [0F ll mm] + case 0x0F: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [0C ll mm hh] + case 0x0C: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [0D ll mm hh] + case 0x0D: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END LDAB ____________________ + + // _____________________ ORA ____________________ + // 220 - OR memory with Accumulator + // ora B, #imm + // Operation data length: 16 bits or 8 bits + // [56 imm] + case 0x56: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 220 - OR memory with Accumulator + // ora B, dd + // Operation data length: 16 bits or 8 bits + // [5A dd] + case 0x5A: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [5B dd] + case 0x5B: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 220 - OR memory with Accumulator + // ora B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [5E ll mm] + case 0x5E: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [5F ll mm] + case 0x5F: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END ORA ____________________ + // _____________________ STA ____________________ + // 271 - STore Accumulator in memory + // sta B, dd + // Operation data length: 16 bits or 8 bits + // [DA dd] + case 0xDA: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [DB dd] + case 0xDB: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 271 - STore Accumulator in memory + // sta B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [D8 dd] + case 0xD8: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 271 - STore Accumulator in memory + // sta B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [D9 dd] + case 0xD9: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 271 - STore Accumulator in memory + // sta B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [DE ll mm] + case 0xDE: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [DF ll mm] + case 0xDF: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 271 - STore Accumulator in memory + // sta B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [DC ll mm hh] + case 0xDC: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [DD ll mm hh] + case 0xDD: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END STA ____________________ + // _____________________ STAB ____________________ + // 272 - STore Accumulator in memory at Byte + // stab B, dd + // Operation data length: 16 bits or 8 bits + // [CA dd] + case 0xCA: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [CB dd] + case 0xCB: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [C8 dd] + case 0xC8: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [C9 dd] + case 0xC9: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [CE ll mm] + case 0xCE: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [CF ll mm] + case 0xCF: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [CC ll mm hh] + case 0xCC: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [CD ll mm hh] + case 0xCD: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END STAB ____________________ + + // _____________________ SUB ____________________ + // 278 - SUBtract + // sub B, #imm + // Operation data length: 16 bits or 8 bits + // [36 #imm] + case 0x36: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 278 - SUBtract + // sub B, dd + // Operation data length: 16 bits or 8 bits + // [3A dd] + case 0x3A: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 278 - SUBtract + // sub B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [3B dd] + case 0x3B: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 278 - SUBtract + // sub B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [3E ll mm] + case 0x3E: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 278 - SUBtract + // sub B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [3F ll mm] + case 0x3F: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END SUB ____________________ + + //---------------------------BYTE-------------------------------------// + // 102 - ADD at Byte + // addb B, #imm + // Operation data length: 8 bits + // [81 29 imm] + case 0x29: + insn.itype = m7900_addb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 112 - logical AND between immediate (Byte) + // andb B, #imm + // Operation data length: 8 bits + // [81 23 imm] + case 0x23: + insn.itype = m7900_andb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 146 - Compare immediate and Branch on EQual at Byte + // cbeqb B, #imm, rr (DIR) + // Operation data length: 8 bits + // [A2 imm rr] + case 0xA2: + insn.itype = m7900_cbeqb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); + break; + + // 148 - Compare immediate and Branch on Not Equal at Byte + // cbneb B, #imm, rr () + // Operation data length: 8 bits + // [B2 imm rr] + case 0xB2: + insn.itype = m7900_cbneb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); + break; + + // 154 - CLeaR accumulator at Byte + // clrb B + // Operation data length: 8 bits + // [44] + case 0x44:// clrb + insn.itype = m7900_clrb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + break; + + // 162 - CoMPare at Byte + // cmpb B, #imm + // Operation data length: 8 bits + // [38 imm] + case 0x38: + insn.itype = m7900_cmpb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 181 - Exclusive OR immediate with accumulator at Byte + // eorb B, #imm + // Operation data length: 8 bits + // [33 imm] + case 0x33: + insn.itype = m7900_eorb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 221 - OR immediate with Accumulator at Byte + // orab B, #imm + // Operation data length: 8 bits + // [63 imm] + case 0x63: + insn.itype = m7900_orab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 279 - OR immediate with Accumulator at Byte + // subb B, #imm + // Operation data length: 8 bits + // [81 39 imm] + case 0x39: + insn.itype = m7900_subb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + default: + return 0; + } + + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_A1(insn_t &insn) +{ + TRACE("Opcode_A1"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + // ___________________ ADC _________________________ + // 96 - ADd with Carry + // adc B, dd + // Operation data length: 16 bits or 8 bits + // [A1 8A dd] + case 0x8A: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [A1 8B dd] + case 0x8B: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [A1 80 dd] + case 0x80: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [A1 81 dd] + case 0x81: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [A1 88 dd] + case 0x88: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [A1 82 dd] + case 0x82: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 96 - ADd with Carry + // adc B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [A1 89 dd] + case 0x89: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [A1 83 nn] + case 0x83: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 96 - ADd with Carry + // adc B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [A1 84 nn] + case 0x84: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [A1 8E ll mm] + case 0x8E: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [A1 8F ll mm] + case 0x8F: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 96 - ADd with Carry + // adc B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [A1 86 ll mm] + case 0x86: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 96 - ADd with Carry + // adc B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [A1 8C ll mm hh] + case 0x8C: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 96 - ADd with Carry + // adc B, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [A1 8D ll mm hh] + case 0x8D: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END ADC _________________________ + + // ___________________ SBC _________________________ + // 264 - SuBtract with Carry + // sbc B, dd + // Operation data length: 16 bits or 8 bits + // [21 AA dd] + case 0xAA: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc B, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [21 AB dd] + case 0xAB: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 264 - SuBtract with Carry + // sbc B, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [21 A0 dd] + case 0xA0: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc B, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [21 A1 dd] + case 0xA1: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc B, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [21 A8 dd] + case 0xA8: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc B, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 A2 dd] + case 0xA2: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 264 - SuBtract with Carry + // sbc B, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [21 A9 dd] + case 0xA9: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc B, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [21 A3 nn] + case 0xA3: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 264 - SuBtract with Carry + // sbc B, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 A4 nn] + case 0xA4: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc B, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [21 AE ll mm] + case 0xAE: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc B, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 AF ll mm] + case 0xAF: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 264 - SuBtract with Carry + // sbc B, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [21 A6 ll mm] + case 0xA6: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 264 - SuBtract with Carry + // sbc B, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 AC ll mm hh] + case 0xAC: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 264 - SuBtract with Carry + // sbc B, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 AD ll mm hh] + case 0xAD: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END sbc _________________________ + + default: + return 0; + } + + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_11(insn_t &insn) +{ + TRACE("Opcode_11"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + switch ( code ) + { + // ________________________ ADD________________________ + // 101 - ADd + // add A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 20 dd] + case 0x20: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 101 - ADd + // add A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 21 dd] + case 0x21: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 101 - ADd + // add A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [11 28 dd] + case 0x28: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 22 dd] + case 0x22: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_byte); + break; + + // 101 - ADd + // add A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 29 dd] + case 0x29: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 23 nn] + case 0x23: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 101 - ADd + // add A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 24 nn] + case 0x24: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 26 ll mm] + case 0x26: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 101 - ADd + // add A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 2C ll mm hh] + case 0x2C: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 101 - ADd + // add A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 2D ll mm hh] + case 0x2D: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // ______________________ END ADD _____________________ + // ________________________ CMP________________________ + // 161 - CoMPare + // cmp A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 40 dd] + case 0x40: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 41 dd] + case 0x41: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [11 48 dd] + case 0x48: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 42 dd] + case 0x42: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 161 - CoMPare + // cmp A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 49 dd] + case 0x49: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 43 nn] + case 0x43: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 161 - CoMPare + // cmp A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 44 nn] + case 0x44: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 46 ll mm] + case 0x46: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 161 - CoMPare + // cmp A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 4C ll mm hh] + case 0x4C: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 4D ll mm hh] + case 0x4D: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END CMP _____________________ + + // ________________________ AND________________________ + // 111 - logical AND + // and A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 60 dd] + case 0x60: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 111 - logical AND + // and A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 61 dd] + case 0x61: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 111 - logical AND + // and A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [11 68 dd] + case 0x68: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 62 dd] + case 0x62: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 111 - logical AND + // and A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 69 dd] + case 0x69: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 63 nn] + case 0x63: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 111 - logical AND + // and A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 64 nn] + case 0x64: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 66 ll mm] + case 0x66: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 111 - logical AND + // and A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 6C ll mm hh] + case 0x6C: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 111 - logical AND + // and A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [ 6D ll mm hh] + case 0x6D: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END AND _____________________ + // ________________________ EOR________________________ + // 180 - Exclusive OR memory with accumulator + // eor A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 70 dd] + case 0x70: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 71 dd] + case 0x71: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [11 78 dd] + case 0x78: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 72 dd] + case 0x72: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 79 dd] + case 0x79: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 73 nn] + case 0x73: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 74 nn] + case 0x74: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 76 ll mm] + case 0x76: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [21 7C ll mm hh] + case 0x7C: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [21 7D ll mm hh] + case 0x7D: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END eor _____________________ + + // ___________________ LDA _________________________ + // 195 - LoaD Accumulator from memory + // lda A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 10 dd] + case 0x10: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 11 dd] + case 0x11: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 12 dd] + case 0x12: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 195 - LoaD Accumulator from memory + // lda A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 13 nn] + case 0x13: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 195 - LoaD Accumulator from memory + // lda A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [11 14 nn] + case 0x14: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 195 - LoaD Accumulator from memory + // lda A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 16 ll mm] + case 0x16: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END LDA ____________________ + + // ___________________ LDAB _________________________ + // 196 - LoaD Accumulator from memory at Byte + // ldab a, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 00 dd] + case 0x00: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 01 dd] + case 0x01: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 02 dd] + case 0x02: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 03 nn] + case 0x03: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [11 04 nn] + case 0x04: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 06 ll mm] + case 0x06: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END LDAB ____________________ + + // ___________________ STA _________________________ + // 271 - STore Accumulator in memory + // sta A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [D0 dd] + case 0xD0: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [D1 dd] + case 0xD1: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [D2 dd] + case 0xD2: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 271 - STore Accumulator in memory + // sta A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [D3 nn] + case 0xD3: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 271 - STore Accumulator in memory + // sta A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [D4 nn] + case 0xD4: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 271 - STore Accumulator in memory + // sta A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [D6 ll mm] + case 0xD6: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END STA ____________________ + // _____________________ STAB ____________________ + // 272 - STore Accumulator in memory at Byte + // stab A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [C0 dd] + case 0xC0: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [C1 dd] + case 0xC1: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [C2 dd] + case 0xC2: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [C3 nn] + case 0xC3: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [C4 nn] + case 0xC4: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [C6 ll mm] + case 0xC6: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END STAB ____________________ + + // _____________________ STAD ____________________ + // 273 - STore Accumulator in memory at Double-word + // stad E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 32 bits + // [E0 dd] + case 0xE0: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 32 bits + // [E1 dd] + case 0xE1: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 E2 dd] + case 0xE2: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 32 bits + // [E3 nn] + case 0xE3: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 32 bits + // [E4 nn] + case 0xE4: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 32 bits + // [E6 ll mm] + case 0xE6: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + // _____________________ END STAD ____________________ + + // ________________________ ORA________________________ + // 220 - OR memory with Accumulator + // ora A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 50 dd] + case 0x50: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 51 dd] + case 0x51: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [11 58 dd] + case 0x58: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 52 dd] + case 0x52: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 220 - OR memory with Accumulator + // ora A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 59 dd] + case 0x59: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 53 nn] + case 0x53: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 220 - OR memory with Accumulator + // ora A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 54 nn] + case 0x54: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 56 ll mm] + case 0x56: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 220 - OR memory with Accumulator + // ora A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [11 5C ll mm hh] + case 0x5C: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // ora A, hhmmll, X (Absolute long indexed X addressing mode(ABL,X) + // Operation data length: 16 bits or 8 bits + // [11 5D ll mm hh] + case 0x5D: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END ora _____________________ + + // ________________________ SUB________________________ + // 278 - SUBtract + // sub A, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 16 bits or 8 bits + // [11 30 dd] + case 0x30: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + break; + + // 278 - SUBtract + // sub A, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 16 bits or 8 bits + // [11 31 dd] + case 0x31: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, SetTypeDataM); + break; + + // 278 - SUBtract + // sub A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [11 38 dd] + case 0x38: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub A, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 32 dd] + case 0x32: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 278 - SUBtract + // sub A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [11 39 dd] + case 0x39: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub A, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 16 bits or 8 bits + // [11 33 nn] + case 0x33: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 278 - SUBtract + // sub A, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 16 bits or 8 bits + // [21 34 nn] + case 0x34: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub A, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 16 bits or 8 bits + // [11 36 ll mm] + case 0x36: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 278 - SUBtract + // sub A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [11 3C ll mm hh] + case 0x3C: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 278 - SUBtract + // sub A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [11 3D ll mm hh] + case 0x3D: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // ______________________ END SUB _____________________ + + // ___________________ ADDD _________________________ + + // 101 - ADd Double-word + // addd E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 32 bits + // [11 90 dd] + case 0x90: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 103 - ADd at Double-word + // addd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 32 buts + // [11 91 dd] + case 0x91: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 103 - ADd at Double-word + // addd E, (dd), Y () + // Operation data length: 32 bits + // [11 98 dd] + case 0x98: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 103 - ADd Double-word + // addd E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 92 dd] + case 0x92: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 103 - ADd at Double-word + // addd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 99 dd] + case 0x99: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 103 - ADd at Double-word + // addd E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 32 bits + // [11 93 nn] + case 0x93: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 103 - ADd at Double-word + // addd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 32 bits + // [11 94 nn] + case 0x94: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 103 - ADd at Double-word + // addd E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [11 9E ll mm] + case 0x9E: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 103 - ADd at Double-word + // addd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [11 9F ll mm] + case 0x9F: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 103 - ADd at Double-word + // addd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 32 bits + // [11 96 ll mm] + case 0x96: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 103 - ADd at Double-word + // addd E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [11 9C ll mm hh] + case 0x9C: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 103 - ADd at Double-word + // addd A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [11 9D ll mm hh] + case 0x9D: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END ADCD _________________________ + // ___________________ CMPD _________________________ + + // 163 - CoMPare at Double-word + // cmpd E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 32 bits + // [11 B0 dd] + case 0xB0: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 163 - CoMPare at Double-word + // cmpd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 32 buts + // [11 B1 dd] + case 0xB1: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 163 - CoMPare at Double-word + // cmpd E, (dd), Y () + // Operation data length: 32 bits + // [11 B8 dd] + case 0xB8: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 163 - CoMPare at Double-word + // cmpd E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 B2 dd] + case 0xB2: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 163 - CoMPare at Double-word + // cmpd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 B9 dd] + case 0xB9: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 163 - CoMPare at Double-word + // cmpd E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 32 bits + // [11 B3 nn] + case 0xB3: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 163 - CoMPare at Double-word + // cmpd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 32 bits + // [11 B4 nn] + case 0xB4: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 163 - CoMPare at Double-word + // cmpd E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [11 BE ll mm] + case 0xBE: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 163 - CoMPare at Double-word + // cmpd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [11 BF ll mm] + case 0xBF: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 163 - CoMPare at Double-word + // cmpd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 32 bits + // [11 B6 ll mm] + case 0xB6: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 163 - CoMPare at Double-word + // cmpd E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [11 BC ll mm hh] + case 0xBC: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 163 - CoMPare at Double-word + // cmpd A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [11 BD ll mm hh] + case 0xBD: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END CMPD _________________________ + + // ___________________ LDAD _________________________ + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 32 bits + // [11 80 dd] + case 0x80: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 32 buts + // [11 81 dd] + case 0x81: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 82 dd] + case 0x82: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 32 bits + // [11 83 nn] + case 0x83: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 32 bits + // [11 84 nn] + case 0x84: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 32 bits + // [11 86 ll mm] + case 0x86: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + // ___________________ END LDAD _________________________ + + // ___________________ SUBD _________________________ + + // 280 - SUBtract Double-word + // subd E, (dd) (Direct indirect addressing mode (DIR)) + // Operation data length: 32 bits + // [11 A0 dd] + case 0xA0: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + break; + + // 280 - SUBtract Double-word + // subd E, (dd, X) (Direct index X indirect addressing mode (DIR,X)) + // Operation data length: 32 bits + // [11 A1 dd] + case 0xA1: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR_X, dt_dword); + break; + + // 280 - SUBtract Double-word + // subd E, (dd), Y () + // Operation data length: 32 bits + // [11 A8 dd] + case 0xA8: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 280 - SUBtract Double-word + // subd E, L(dd)(Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 A2 dd] + case 0xA2: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + break; + + // 280 - SUBtract Double-word + // subd E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [11 A9 dd] + case 0xA9: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 280 - SUBtract Double-word + // subd E, nn, S (Stack pointer relative addressing mode(SR)) + // Operation data length: 32 bits + // [11 A3 nn] + case 0xA3: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_SP, 8); + Operand_Registr(insn.Op3, rPS); + break; + + // 280 - SUBtract Double-word + // subd E, (nn,S), Y (Stack pointer relative indexed Y addressing mode((SR),Y)) + // Operation data length: 32 bits + // [11 A4 nn] + case 0xA4: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_SR(insn, insn.Op2, TSP_INDEX_SP_Y, 8); + Operand_Registr(insn.Op3, rY); + break; + + // 280 - SUBtract Double-word + // subd E, mmll, Y (Absolute indexed X addressing mode(ABS,Y)) + // Operation data length: 32 bits + // [11 A6 ll mm] + case 0xA6: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_Y, 16, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 280 - SUBtract Double-word + // subd E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [11 AC ll mm hh] + case 0xAC: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 280 - SUBtract Double-word + // subd A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [11 AD ll mm hh] + case 0xAD: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // ___________________ END SUBD _________________________ + + default: + return 0; + } + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_B1(insn_t &insn) +{ + TRACE("Opcode_B1"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + uchar nib = (code >> 4) & 0xF; + + switch ( code ) + { + + // 292 - Transfer accumulator B to Stack pointer + // tbs + // Operation data length: 8 bits + // [B1 82] + case 0x82: + insn.itype = m7900_tbs; + break; + + // 96 - ADc with Carry + // adc B, #imm + // Operation data length: 16 bits or 8 bits + // [B1 87 imm] + case 0x87: + insn.itype = m7900_adc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 98 - ADd with Carry at Byte + // adcb B, #imm + // Operation data length: 8 bits + // [B1 1A imm] + case 0x1A: + insn.itype = m7900_adcb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 265 - SuBtract with Carry at Byte + // sbcb A, #imm + // Operation data length: 8 bits + // [B1 1B imm] + case 0x1B: + insn.itype = m7900_sbcb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 299 - Transfer Stack pointer to accumulator B + // tsb + // Operation data length: 16 bits or 8 bits + // [B1 92] + case 0x92: + insn.itype = m7900_tsb; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + // _____________________ SBC ____________________ + // 264 - SuBtract with Carry + // sbc B, #imm + // Operation data - 16 bits or 8 bits + // [B1 A7 imm] + case 0xA7: + insn.itype = m7900_sbc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + // _____________________ END SBC ____________________ + + default: + { + uchar cm = code & 0x40; + if ( cm == 0x40 ) + { + insn.itype = m7900_tdbn; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, (((code-0x40) >> 4) & 0xF)+0x1); + } + else + { + insn.itype = m7900_tbdn; + Operand_Imm_Spesh(insn.Op1, dt_byte, nib); + } + } + break; + } + + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_B8(insn_t &insn) +{ + TRACE("Opcode_B8"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + uchar nib = (code >> 4) & 0xF; + uchar cd = code & 0xF; + uchar Nib; + + if ( nib == 0 && cd == 0 ) + return 0; + + if ( nib == 0 ) + { + insn.itype = m7900_phdn; + RAZOPER = INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + return insn.size; + } + else if ( cd == 0 ) + { + insn.itype = m7900_lddn; + RAZOPER = INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, nib); + Nib = nib; + } + else + { + if ( nib != cd ) + return 0; + insn.itype = m7900_phldn; + RAZOPER = INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + Nib = cd; + } + + for ( int i=0; i < 4; ++i ) + if ( GETBIT(Nib, i) == 1 ) + Operand_STK(insn, insn.ops[1+i], 16); + + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_77(insn_t &insn) +{ + TRACE("Opcode_77"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + uchar nib = (code >> 4) & 0xF; + uchar cd = code & 0xF; + + switch ( cd ) + { + case 0xC: + insn.itype = m7900_rtld; + Operand_Imm_Spesh(insn.Op1, dt_byte, nib); + break; + + case 0x0: + insn.itype = m7900_pldn; + RAZOPER = INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, nib); + break; + + case 0x8: + insn.itype = m7900_rtsdn; + Operand_Imm_Spesh(insn.Op1, dt_byte, nib); + break; + + default: + return 0; + } + + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_61(insn_t &insn) +{ + TRACE("Opcode_61"); + + uchar code = insn.get_next_byte(); + TRACE(code); + + uchar nib = (code >> 4) & 0xF; + uchar count = code & 0x0F; + + Operand_Imm_Spesh(insn.Op1, dt_byte, count); + + uchar i; + + switch ( nib ) + { + case 0x0: + insn.itype = m7900_movrb; + // This instruction is unaffected by flag m + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// imm + insn.get_next_byte();// dd + } + break; + + case 0x2: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// imm + insn.get_next_word();// llmm + } + break; + + case 0x4: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// dds1 + insn.get_next_byte();// ddd1 + } + break; + + case 0x6: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// dd + insn.get_next_word();// llmm + } + break; + + case 0x8: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < count; i++ ) + { + insn.get_next_word();// llmm + insn.get_next_byte();// dd + } + break; + + case 0xA: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < count; i++ ) + { + insn.get_next_word();// mmll1 + insn.get_next_word();// mmll2 + } + break; + // ______________________________________________ + + case 0x1: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// dd + + if ( getFlag_M == 0 ) + insn.get_next_word();// imm + else + insn.get_next_byte();// imm + } + break; + + case 0x3: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + + for ( i=0; i < count; i++ ) + { + if ( getFlag_M != 0 ) + { + insn.get_next_byte();// imm + insn.get_next_word();// llmm + } + else + { + insn.get_next_word();// imm + insn.get_next_word();// llmm + } + } + break; + + case 0x5: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// dd1 + insn.get_next_byte();// dd2 + } + break; + + case 0x7: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + for ( i=0; i < count; i++ ) + { + insn.get_next_byte();// dd + insn.get_next_word();// llmm + } + break; + + case 0x9: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + + for ( i=0; i < count; i++ ) + { + insn.get_next_word();// llmm + insn.get_next_byte();// dd + } + break; + + case 0xB: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + for ( i=0; i < count; i++ ) + { + insn.get_next_word();// mmll1 + insn.get_next_word();// mmll2 + } + break; + + default: + return 0; + } + return insn.size; +} + +//---------------------------------------------------------------------- +static int Opcode_71(insn_t &insn) +{ + int i; + TRACE("Opcode_71"); + uchar code = insn.get_next_byte(); + TRACE(code); + + uchar nib = (code >> 4) & 0xF; + uchar cd = code & 0x0F; + + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + + // 140 - Branch on Single bit Clear + // bsc n, dd, rr + // bsc n, mmll, rr + // Operation data length: 16 bits or 8 bits + // [71 n+E0 ll mm rr] + // [71 n+A0 dd rr] + + switch ( nib ) + { + case 0x0: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + + for ( i=0; i < cd; i++ ) + { + insn.get_next_word();// mmll1 + insn.get_next_byte();// dd + } + break; + + case 0x6: + insn.itype = m7900_movrb; + RAZOPER = INSN_PREF_U; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movr; + + for ( i=0; i < cd; i++ ) + { + insn.get_next_word();// mmll1 + insn.get_next_byte();// dd + } + break; + + case 0x1: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < cd; i++ ) + { + insn.get_next_word();// mmll1 + insn.get_next_byte();// dd + } + break; + + case 0x7: + insn.itype = m7900_movr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + insn.Op2.type = o_mem; + insn.Op2.TypeOper = m7900_movrb; + + for ( i=0; i < cd; i++ ) + { + insn.get_next_byte();// dd + insn.get_next_word();// llmm + } + break; + + case 0xA: + insn.itype = m7900_bsc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); + break; + + case 0xE: + insn.itype = m7900_bsc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); + break; + + case 0x8: + insn.itype = m7900_bss; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); + break; + + case 0xC: + insn.itype = m7900_bss; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, dt_byte, cd); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); + break; + + default: + return 0; + } + return insn.size; +} + +//---------------------------------------------------------------------- +int idaapi ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + + TRACE("ana"); + + RAZOPER = 0; + + uchar code = insn.get_next_byte(); + uchar nib = (code >> 4) & 0xF; + uchar imm, com; + + switch ( code ) + { + // 116 - Arithmetic Shift to Left + // asl A + // Operation data length: 16 bits or 8 bits + // [03] + case 0x03:// asl + insn.itype = m7900_asl; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + // 119 - Arithmetic Shift to Right + // asr A + // Operation data length: 16 bits or 8 bits + // [64] + case 0x64:// asr + insn.itype = m7900_asr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + case 0x91: + return Opcode_91(insn); + + case 0x21: + return Opcode_21(insn); + + case 0x31: + return Opcode_31(insn); + + case 0x41: + return Opcode_41(insn); + + case 0x51: + return Opcode_51(insn); + + case 0x81: + return Opcode_81(insn); + + case 0x11: + return Opcode_11(insn); + + case 0xA1: + return Opcode_A1(insn); + + case 0xB1: + return Opcode_B1(insn); + + case 0xB8: + return Opcode_B8(insn); + + // 94 - Absolute value + // abs A + case 0xE1: + insn.itype = m7900_abs; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + //-----------------------------------------------------------// + // 139 - force BReaK + // brk + // Operation data length: - + // [00 74] + case 0x00:// brk (IMP) + if ( get_byte(insn.ea + 1) == 0x74 ) + { + insn.get_next_byte(); + insn.itype = m7900_brk; + Operand_IMP(insn.Op1); + } + else + { + return 0; + } + break; + + case 0x14:// clc + insn.itype = m7900_clc; + break; + + case 0x15:// cli + insn.itype = m7900_cli; + break; + + case 0x65:// clv + insn.itype = m7900_clv; + break; + + // 154 - CLeaR accumulator at Byte + // clrb A + // Operation data length: 8 bits + // [44] + case 0x44:// clrb + insn.itype = m7900_clrb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + break; + + // 153 - CLeaR accumulator + // clr A + // Operation data length: 16 bits or 8 bits + // [54] + case 0x54:// clr + insn.itype = m7900_clr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + case 0xA4:// txa + insn.itype = m7900_txa; + break; + + case 0xB4:// tya + insn.itype = m7900_tya; + break; + + case 0xC4:// tax + insn.itype = m7900_tax; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xD4:// tay + insn.itype = m7900_tay; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0x55:// xab + insn.itype = m7900_xab; + break; + + case 0xE3:// dex + insn.itype = m7900_dex; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xF3:// dey + insn.itype = m7900_dey; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + // 185 - EXTension Sign + // exts A + // Operation data length: 16 bits + // [35] + case 0x35:// exts + insn.itype = m7900_exts; + RAZOPER = INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + // 187 - EXTension Zero + // extz A + // Operation data length: 16 bits + // [34] + case 0x34:// extz + insn.itype = m7900_extz; + RAZOPER = INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + +//********************************************************IN + case 0xC3:// inx (IMP) + insn.itype = m7900_inx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xD3:// iny (IMP) + insn.itype = m7900_iny; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + +//************************************************ + case 0x24:// neg + insn.itype = m7900_neg; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + case 0x74:// nop + insn.itype = m7900_nop; + break; + +//*********************************************************PUSH + + case 0x85:// pha + insn.itype = m7900_pha; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0x83:// phd + insn.itype = m7900_phd; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xA5:// php + insn.itype = m7900_php; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xC5:// phx + insn.itype = m7900_phx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xE5:// phy + insn.itype = m7900_phy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0x95:// pla + insn.itype = m7900_pla; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0x93:// pld + insn.itype = m7900_pld; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xB5:// plp + insn.itype = m7900_plp; + RAZOPER = INSN_PREF_W; + break; + + case 0xD5:// plx + insn.itype = m7900_plx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + case 0xF5:// ply + insn.itype = m7900_ply; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + +//**************************************************************** + case 0xF1:// rti + insn.itype = m7900_rti; + break; + + case 0x94:// rtl + insn.itype = m7900_rtl; + break; + + case 0x84:// rts + insn.itype = m7900_rts; + break; + + case 0x04:// sec + insn.itype = m7900_sec; + break; + + case 0x05:// sei + insn.itype = m7900_sei; + break; + + case 0x45:// clm + insn.itype = m7900_clm; + break; + + case 0x25:// sem + insn.itype = m7900_sem; + break; + + case 0x77:// + return Opcode_77(insn); + + case 0x61: + return Opcode_61(insn); + + case 0x71: + return Opcode_71(insn); + + // 102 - ADD at Byte + // addb A, #imm + // Operation data length: 8 bits + // [29 imm] + case 0x29: + insn.itype = m7900_addb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 112 - logical AND between immediate (Byte) + // andb A, #imm + // Operation data length: 8 bits + // [23 imm] + case 0x23: + insn.itype = m7900_andb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 123 -Branch on Bit Clear (Byte) + // bbcb #imm dd rr (DIR) + // Operation data length: 8 bits + // [52 dd imm rr] + case 0x52: + insn.itype = m7900_bbcb; + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + RAZOPER = INSN_PREF_U; + Operand_Imm(insn, insn.Op1, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); + break; + + // 123 -Branch on Bit Clear (Byte) + // bbcb #imm dd rr (ABS) + // Operation data length: 8 bits + // [57 dd imm rr] + case 0x57: + insn.itype = m7900_bbcb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op2, TAB_ABS, 8, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); + break; + + // 125 - Branch on Bit Set (Byte) + // bbsb #imm dd rr (DIR) + // Operation data length: 8 bits + // [42 dd imm rr] + case 0x42: + insn.itype = m7900_bbsb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 4); + break; + + // 125 - Branch on Bit Set (Byte) + // bbsb #imm dd rr (ABS) + // Operation data length: 8 bits + // [47 dd imm rr] + case 0x47: + insn.itype = m7900_bbsb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op2, TAB_ABS, 8, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 5); + break; + + // 146 - Compare immediate and Branch on EQual at Byte + // cbeqb A, #imm, rr () + // Operation data length: 8 bits + // [A2 imm rr] + case 0xA2: + insn.itype = m7900_cbeqb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); + break; + + // 146 - Compare immediate and Branch on EQual at Byte + // cbeqb A,dd, #imm, rr (DIR) + // Operation data length: 8 bits + // [62 dd imm rr] + case 0x62:// cbeqb dd,#imm,rr + insn.itype = m7900_cbeqb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + Operand_Near(insn, insn.Op3,insn.get_next_byte(), 4); + break; + + // 148 - Compare immediate and Branch on Not Equal at Byte + // cbneb A, #imm, rr (DIR) + // Operation data length: 8 bits + // [B2 imm rr] + case 0xB2: + insn.itype = m7900_cbneb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); + break; + + // 148 - Compare immediate and Branch on Not Equal at Byte + // cbneb A,dd, #imm, rr (DIR) + // Operation data length: 8 bits + // [72 dd imm rr] + case 0x72:// cbneb dd,#imm,rr + insn.itype = m7900_cbneb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op2, 8); + Operand_Near(insn, insn.Op3,insn.get_next_byte(), 4); + break; + + // 156 - CLeaR Memory at Byte + // clrmb dd(DIR) + // Operation data length: 8 bits + // [C2 dd] + case 0xC2: + insn.itype = m7900_clrmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + break; + + // 156 - CLeaR Memory at Byte + // clrmb mmll(ABS) + // Operation data length: 8 bits + // [C2 ll mm] + case 0xC7:// clrmb + insn.itype = m7900_clrmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + break; + + // 162 - CoMPare at Byte + // cmpb A, #imm + // Operation data length: 8 bits + // [38 imm] + case 0x38: + insn.itype = m7900_cmpb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 181 - Exclusive OR immediate with accumulator at Byte + // eorb A, #imm + // Operation data length: 8 bits + // [33 imm] + case 0x33: + insn.itype = m7900_eorb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // __________________________________________________________// + + // 208 - MOVe Memory to memory at Byte + // movmb dd, #imm + // Operation data length: 8 bits + // [A9 imm dd] + case 0xA9: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb dd, mmll + // Operation data length: 8 bits + // [4C imm ll mm] + case 0x4C: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb dd, mmll, X + // Operation data length: 8 bits + // [4D imm ll mm] + case 0x4D: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + Operand_Imm(insn, insn.Op1, 8); + Operand_Registr(insn.Op3, rX); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb mmll, #imm + // Operation data length: 8 bits + // [B9 imm ll mm] + case 0xB9: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Imm(insn, insn.Op2, 8); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb mmll, dd + // Operation data length: 8 bits + // [68 dd ll mm] + case 0x68: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb mmll, dd + // Operation data length: 8 bits + // [69 dd ll mm] + case 0x69: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb mmll, mmll + // Operation data length: 8 bits + // [6C ll mm ll mm] + case 0x6C: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, dt_byte); + break; + + // 208 - MOVe Memory to memory at Byte + // movmb mmll, mmll + // Operation data length: 8 bits + // [48 dd dd] + case 0x48: + insn.itype = m7900_movmb; + RAZOPER = INSN_PREF_U; + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + Operand_Dir(insn, insn.Op1, TDIR_DIR, dt_byte); + break; + + // 221 - OR immediate with Accumulator at Byte + // orab A, #imm + // Operation data length: 8 bits + // [63 imm] + case 0x63: + insn.itype = m7900_orab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 279 - OR immediate with Accumulator at Byte + // subb A, #imm + // Operation data length: 8 bits + // [39 imm] + case 0x39: + insn.itype = m7900_subb; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // _____________________ ADD ____________________ + // 101 - ADd + // add A, #imm + // Operation data length: 16 bits or 8 bits + // [26 imm] + case 0x26: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 101 - ADd + // add A, dd + // Operation data length: 16 bits or 8 bits + // [2A dd] + case 0x2A: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 101 - ADd + // add A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [2B dd] + case 0x2B: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 101 - ADd + // add A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [2E ll mm] + case 0x2E: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 101 - ADd + // add A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [2F ll mm] + case 0x2F: + insn.itype = m7900_add; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END ADD ____________________ + // _____________________ CMP ____________________ + // 161 - CoMPare + // cmp A, #imm + // Operation data length: 16 bits or 8 bits + // [46 imm] + case 0x46: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 161 - CoMPare + // cmp A, dd + // Operation data length: 16 bits or 8 bits + // [4A dd] + case 0x4A: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [4B dd] + case 0x4B: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 161 - CoMPare + // cmp A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [4E ll mm] + case 0x4E: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 161 - CoMPare + // cmp A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [4F ll mm] + case 0x4F: + insn.itype = m7900_cmp; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END CMP ____________________ + + // _____________________ EOR ____________________ + // 180 - Exclusive OR memory with accumulator + // eor A, #imm + // Operation data length: 16 bits or 8 bits + // [76 imm] + case 0x76: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, dd + // Operation data length: 16 bits or 8 bits + // [7A dd] + case 0x7A: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [7B dd] + case 0x7B: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [7E ll mm] + case 0x7E: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 180 - Exclusive OR memory with accumulator + // eor A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [7F ll mm] + case 0x7F: + insn.itype = m7900_eor; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END EOR ____________________ + + // _____________________ LDA ____________________ + // 195 - LoaD Accumulator from memory + // lda A, #imm + // Operation data length: 16 bits or 8 bits + // [16 imm] + case 0x16: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 195 - LoaD Accumulator from memory + // lda A, dd + // Operation data length: 16 bits or 8 bits + // [1A dd] + case 0x1A: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [1B dd] + case 0x1B: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 195 - LoaD Accumulator from memory + // lda A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [18 dd] + case 0x18: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rB); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 195 - LoaD Accumulator from memory + // lda A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [19 dd] + case 0x19: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 195 - LoaD Accumulator from memory + // lda A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [1E ll mm] + case 0x1E: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [1F ll mm] + case 0x1F: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 195 - LoaD Accumulator from memory + // lda A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [1C ll mm hh] + case 0x1C: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 195 - LoaD Accumulator from memory + // lda A, hhmmll, X (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [1D ll mm hh] + case 0x1D: + insn.itype = m7900_lda; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END LDA ____________________ + + // _____________________ LDAB ____________________ + // 196 - LoaD Accumulator from memory at Byte + // ldab A, #imm + // Operation data length: 16 bits + // [28 imm] + case 0x28: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, 8); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, dd + // Operation data length: 16 bits + // [0A dd] + case 0x0A: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits + // [0B dd] + case 0x0B: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X); + Operand_Registr(insn.Op3, rX); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [08 dd] + case 0x08: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR); + Operand_Registr(insn.Op3, rY); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits + // [09 dd] + case 0x09: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [0E ll mm] + case 0x0E: + insn.itype = m7900_ldab; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [0F ll mm] + case 0x0F: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [0C ll mm hh] + case 0x0C: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); + break; + + // 196 - LoaD Accumulator from memory at Byte + // ldab A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [0D ll mm hh] + case 0x0D: + insn.itype = m7900_ldab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END LDAB ____________________ + + // _____________________ STA ____________________ + + // 271 - STore Accumulator in memory + // sta A, dd + // Operation data length: 16 bits or 8 bits + // [DA dd] + case 0xDA: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [DB dd] + case 0xDB: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 271 - STore Accumulator in memory + // sta A, (dd), Y () + // Operation data length: 16 bits or 8 bits + // [D8 dd] + case 0xD8: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rY); + break; + + // 271 - STore Accumulator in memory + // sta A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 16 bits or 8 bits + // [D9 dd] + case 0xD9: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 271 - STore Accumulator in memory + // sta A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [DE ll mm] + case 0xDE: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [DF ll mm] + case 0xDF: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 271 - STore Accumulator in memory + // sta A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [DC ll mm hh] + case 0xDC: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, SetTypeDataM); + break; + + // 271 - STore Accumulator in memory + // sta A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [DD ll mm hh] + case 0xDD: + insn.itype = m7900_sta; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END STA ____________________ + // _____________________ ORA ____________________ + // 220 - OR memory with Accumulator + // ora A, #imm + // Operation data length: 16 bits or 8 bits + // [56 imm] + case 0x56: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 220 - OR memory with Accumulator + // ora A, dd + // Operation data length: 16 bits or 8 bits + // [5A dd] + case 0x5A: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [5B dd] + case 0x5B: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 220 - OR memory with Accumulator + // ora A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [5E ll mm] + case 0x5E: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 220 - OR memory with Accumulator + // ora A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [5F ll mm] + case 0x5F: + insn.itype = m7900_ora; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END ORA ____________________ + // _____________________ ADDD ____________________ + // 103 - ADd at Double-word + // addd E, #imm + // Operation data length: 32 bits + // [2D imm imm imm imm] + case 0x2D: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 103 - ADd at Double-word + // addd E, dd + // Operation data length: 32 bits + // [9A dd] + case 0x9A: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 103 - ADd at Double-word + // addd E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 32 bits + // [9B dd] + case 0x9B: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 103 - ADd at Double-word + // addD E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [9E ll mm] + case 0x9E: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 103 - ADd at Double-word + // add A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [9F ll mm] + case 0x9F: + insn.itype = m7900_addd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END ADDD ____________________ + + // _____________________ LDAD ____________________ + // 197 - LoaD Accumulator from memory at Double-word + // addd E, #imm + // Operation data length: 32 bits + // [2C imm imm imm imm] + case 0x2C: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, dd + // Operation data length: 32 bits + // [8A dd] + case 0x8A: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 32 bits + // [8B dd] + case 0x8B: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, (dd), Y () + // Operation data length: 32 bits + // [88 dd] + case 0x88: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [89 dd] + case 0x89: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldaD E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [8E ll mm] + case 0x8E: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [8F ll mm] + case 0x8F: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 16 bits or 8 bits + // [8C ll mm hh] + case 0x8C: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 197 - LoaD Accumulator from memory at Double-word + // ldad A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [8D ll mm hh] + case 0x8D: + insn.itype = m7900_ldad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END LDAD ____________________ + + // _____________________ CMPD ____________________ + + // 163 - CoMPare at Double-word + // cmpd E, #imm + // Operation data length: 32 bits + // [3C imm imm imm imm] + case 0x3C: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 163 - CoMPare at Double-word + // cmpd E, dd + // Operation data length: 32 bits + // [BA dd] + case 0xBA: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 163 - CoMPare at Double-word + // cmpd E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 32 bits + // [BB dd] + case 0xBB: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 163 - CoMPare at Double-word + // cmpd E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [BE ll mm] + case 0xBE: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 163 - CoMPare at Double-word + // cmpd A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [BF ll mm] + case 0xBF: + insn.itype = m7900_cmpd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END CMPD ____________________ + + // 108 - ADD index register X and immediate + // addx #imm + // Operation data length: 16 bits + // [01 imm] + + // 140 - Branch on Single bit Clear + // bsc n, A, rr + // Operation data length: 16 bits or 8 bits + // [01 n+A0 rr] + + // 142 - Branch on Single bit Set + // bss n, A, rr + // Operation data length: 16 bits or 8 bits + // [01 n+80 rr] + + case 0x01: + imm = insn.get_next_byte(); + switch ( imm & 0xE0 ) + { + case 0x0: /*addx*/ + insn.itype = m7900_addx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, imm); + break; + + case 0x20: /*addy*/ + insn.itype = m7900_addy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x1F)); + break; + + case 0x40: /*subx*/ + insn.itype = m7900_subx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x1F)); + break; + + case 0x60: /*suby*/ + insn.itype = m7900_suby; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x1F)); + break; + + case 0x80: /*bss*/ + insn.itype = m7900_bss; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x0F)); + Operand_Registr(insn.Op2, rA); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); + break; + + case 0xA0: /*bcs*/ + insn.itype = m7900_bsc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm & 0x0F)); + Operand_Registr(insn.Op2, rA); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), 3); + break; + + case 0xC0: /*dxbne*/ + insn.itype = m7900_dxbne; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm -0xC0)); + Operand_Near(insn, insn.Op2, insn.get_next_byte(), 3); + break; + + case 0xE0: /*dybne*/ + insn.itype = m7900_dybne; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op1, SetTypeDataX, (imm - 0xE0)); + Operand_Near(insn, insn.Op2, insn.get_next_byte(), 3); + break; + } + break; + + // _____________________ AND ____________________ + + // 111 - logical AND + // and A, #imm + // Operation data length: 16 bits or 8 bits + // [66 imm] + case 0x66: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 111 - logical AND + // and A, #imm + // Operation data length: 16 bits or 8 bits + // [6A dd] + case 0x6A: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 111 - logical AND + // and A, #imm + // Operation data length: 16 bits or 8 bits + // [6B dd] + case 0x6B: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 111 - logical AND + // and A, #imm + // Operation data length: 16 bits or 8 bits + // [6E ll mm] + case 0x6E: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 111 - logical AND + // and A, #imm + // Operation data length: 16 bits or 8 bits + // [6F ll mm] + case 0x6F: + insn.itype = m7900_and; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // _____________________ END AND ____________________ + + // 117 - Arithmetic Shift to Left by n bits + // asl n A,#imm + // Operation data length: 16 bits or 8 bits + // [C1 imm+40] + + // 120 - Arithmetic Shift to Right by n bits + // asr n A,#imm + // Operation data length: 16 bits or 8 bits + // [C1 imm+80] + + // 169 - DEcrement memory and Branch on Not Equal + // debne dd #imm rr + // Operation data length: 16 bits or 8 bits + // [D1 imm+A0 dd rr] + + // 253 - n bits ROtate Left + // rol n #imm + // Operation data length: 16 bits or 8 bits + // [C1 imm+A0] + + // 256 - n bits ROtate Right + // ror n #imm + // Operation data length: 16 bits or 8 bits + // [C1 imm+20] + + case 0xC1: + imm = insn.get_next_byte(); + com = imm & 0xE0; + if ( com == 0x20 ) + { + insn.itype = m7900_rorn; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); + } + else if ( com == 0x40 ) + { + insn.itype = m7900_asln; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x0F)); + } + else if ( com == 0x60 ) + { + insn.itype = m7900_roln; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); + } + else if ( com == 0x80 ) + { + insn.itype = m7900_asrn; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); + } + else if ( com == 0xA0 ) + { + insn.itype = m7900_debne; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op2, dt_byte, (imm & 0x1F)); + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_DEBNE(insn, insn.Op3, insn.get_next_byte(), 4); + } + else + { + insn.itype = m7900_lsrn; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm_Spesh(insn.Op2, dt_byte, imm); + } + break; + + // 118 - Arithmetic Shift to Left by n bits (Double word) + // asld n E,#imm + // Operation data length: 32 bits + // [D1 imm+40] + + // 169 - DEcrement memory and Branch on Not Equal + // debne mmll #imm rr + // Operation data length: 16 bits or 8 bits + // [D1 imm+E0 ll mm rr] + + // 206 - Logical n bits Shift Right at Double-word + // lsrd E #imm + // Operation data length: 32 bits + // [D1 imm] + + // 254 - n bits ROtate Left at Double-word + // rold E #imm + // Operation data length: 32 bits + // [D1 imm+60] + + // 254 - n bits ROtate Right at Double-word + // rord E #imm + // Operation data length: 32 bits + // [D1 imm+20] + + case 0xD1: + imm = insn.get_next_byte(); + com = imm & 0xE0; + if ( com == 0x20 ) + { + insn.itype = m7900_rordn; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); + } + else if ( com == 0x40 ) + { + insn.itype = m7900_asldn; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); + } + else if ( com == 0x60 ) + { + insn.itype = m7900_roldn; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); + } + else if ( com == 0x80 ) + { + insn.itype = m7900_asrdn; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm_Spesh(insn.Op2, dt_dword, imm & 0x1F); + } + else if ( com == 0xE0 ) + { + insn.itype = m7900_debne; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm_Spesh(insn.Op2, dt_dword, (imm & 0x1F)); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + Operand_DEBNE(insn, insn.Op3, insn.get_next_byte(), 5); + } + else + { + insn.itype = m7900_lsrdn; + RAZOPER = 32; + Operand_Registr(insn.Op1, rE); + Operand_Imm_Spesh(insn.Op2, dt_dword, imm); + } + break; + + // 126 - Branch on Carry Clear + // bcc rr + // Operation data length: - + // [90 rr] + + // 138 - BRanch Always + // bra rr + // Operation data length: - + // [20 rr] + + // 127 - Branch on Carry Set + // bcs rr + // Operation data length: - + // [B0 rr] + + // 128 - Branch on EQual + // beq rr + // Operation data length: - + // [F0 rr] + + // 129 - Branch on Greater or Equal + // bge rr + // Operation data length: - + // [C0 rr] + + // 130 - + // bgt rr + // Operation data length: - + // [80 rr] + + // 131 - Branch on Greater Than with Unsign + // bgtu rr + // Operation data length: - + // [40 rr] + + // 132 - Branch on Less or Equal + // ble rr + // Operation data length: - + // [A0 rr] + + // 133 - Branch on Less Equal with Unsign + // bleu rr + // Operation data length: - + // [60 rr] + + // 134 - Branch on Less Than + // blt rr + // Operation data length: - + // [E0 rr] + + // 135 - Branch on result MInus + // bmi rr + // Operation data length: - + // [30 rr] + + // 136 - Branch on Not Equal + // bne rr + // Operation data length: - + // [D0 rr] + + // 137 - Branch on result PLus + // bpl rr + // Operation data length: - + // [10 rr] + + // 143 - Branch on oVerflow Clear + // bvc rr + // Operation data length: - + // [50 rr] + + // 144 - Branch on oVerflow Set + // bvs rr + // Operation data length: - + // [70 rr] + + case 0x10: + case 0x20: + case 0x30: + case 0x40: + case 0x50: + case 0x60: + case 0x70: + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + case 0xC0: + case 0xD0: + case 0xE0: + case 0xF0: + RAZOPER = 0; + Branch(insn, insn.Op1, nib); + break; + + case 0xA7: + insn.itype = m7900_bral; + RAZOPER = 0; + Bral(insn, insn.Op1, 3); + break; + + // _____________________ CBEQ ____________________ + + // 145 - Compare immediate and Branch on EQual + // cbeq A, #imm, rr + // Operation data length: 16 bits or 8 bits + // [A6 imm rr] + case 0xA6: + insn.itype = m7900_cbeq; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 3 : 4); + break; + // _____________________ END CBEQ ____________________ + // _____________________ CBNE ____________________ + // 147 - Compare immediate and Branch on Not Equal + // cbne A, #imm, rr + // Operation data length: 16 bits or 8 bits + // [B6 imm rr] + case 0xB6: + insn.itype = m7900_cbne; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Near(insn, insn.Op3, insn.get_next_byte(), getFlag_M ? 3 : 4); + break; + // _____________________ END CBNE ____________________ + + // _____________________ CLP ____________________ + // 153 - CLear Processor status + // clp #imm + // Operation data - + // [98 imm] + case 0x98:// clp + insn.itype = m7900_clp; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END CLP ____________________ + + // _____________________ CLPM ____________________ + // 155 - CLeaR Memory + // clpm dd + // Operation data - 16 bits or 8 bits + // [D2 dd] + case 0xD2:// clrm + insn.itype = m7900_clrm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + // 155 - CLeaR Memory + // clpm mmll + // Operation data - 16 bits or 8 bits + // [D7 ll mm] + case 0xD7:// clrm + insn.itype = m7900_clrm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + // _____________________ END CLPM ____________________ + + // _____________________ CLPX ____________________ + // 157 - CLeaR index register X + // clpx + // Operation data - 16 bits or 8 bits + // [E4] + case 0xE4: + insn.itype = m7900_clrx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + + // 158 - CLeaR index register Y + // clpy + // Operation data - 16 bits or 8 bits + // [F4] + case 0xF4: + insn.itype = m7900_clry; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + break; + // _____________________ END CLPX CLPY ____________________ + + // _____________________ CPX ____________________ + // 167 - ComPare memory and index register X + // cpx #imm + // Operation data - 16 bits or 8 bits + // [E6 imm] + case 0xE6:// cpx + insn.itype = m7900_cpx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); + break; + + // 167 - ComPare memory and index register X + // cpx dd + // Operation data - 16 bits or 8 bits + // [22 dd] + case 0x22:// cpx + insn.itype = m7900_cpx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + break; + // _____________________ END CPX ____________________ + + // _____________________ CPY ____________________ + // 168 - ComPare memory and index register Y + // cpy #imm + // Operation data - 16 bits or 8 bits + // [F6 imm] + case 0xF6:// cpy + insn.itype = m7900_cpy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); + break; + + // 168 - ComPare memory and index register Y + // cpy dd + // Operation data - 16 bits or 8 bits + // [32 dd] + case 0x32:// cpy + insn.itype = m7900_cpy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + break; + // _____________________ END CPY ____________________ + // _____________________ DEC ____________________ + // 170 - DECrement by one + // dec A + // Operation data - 16 bits or 8 bits + // [B3] + case 0xB3: + insn.itype = m7900_dec; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + case 0x92: + insn.itype = m7900_dec; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + case 0x97: + insn.itype = m7900_dec; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + // _____________________ END DEC ____________________ + + // _____________________ INC ____________________ + // 189 - INCrement by one + // inc A + // Operation data - 16 bits or 8 bits + // [A3] + case 0xA3: + insn.itype = m7900_inc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + + case 0x82: + insn.itype = m7900_inc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + case 0x87: + insn.itype = m7900_inc; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + // _____________________ END INC ____________________ + + // _____________________ LDX ____________________ + // 200 - load + // ldx #imm + // Operation data - 16 bits or 8 bits + // [C6] + case 0xC6: + insn.itype = m7900_ldx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); + break; + + case 0x02: + insn.itype = m7900_ldx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + break; + + case 0x07: + insn.itype = m7900_ldx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataX); + break; + // _____________________ END LDX ____________________ + // _____________________ LDXB ____________________ + + // 201 - LoaD index register X from memory at Byte + // ldxb #imm + // Operation data - 16 bits + // [27] + case 0x27: + insn.itype = m7900_ldxb; + RAZOPER = INSN_PREF_W; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END LDXB ____________________ + + // _____________________ LDY ____________________ + // 202 - LoaD index register Y from memory + // ldy #imm + // Operation data - 16 bits or 8 bits + // [D6] + case 0xD6: + insn.itype = m7900_ldy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op1, getFlag_X ? 8 : 16); + break; + + case 0x12: + insn.itype = m7900_ldy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + break; + + case 0x17: + insn.itype = m7900_ldy; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16); + break; + // _____________________ END LDY ____________________ + // _____________________ LDYB ____________________ + // 202 - LoaD index register Y from memory at Byte + // ldyb #imm + // Operation data - 16 bits + // [37] + case 0x37: + insn.itype = m7900_ldyb; + RAZOPER = INSN_PREF_U; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END LDX ____________________ + // _____________________ JMP ____________________ + // 192 - JUMP + // jmp mmll + // Operation data - + // [9C ll mm] + case 0x9C: + { + insn.itype = m7900_jmp; + insn.Op1.type = o_near; + uint32 high = insn.get_next_byte(); + uint32 low = insn.get_next_byte(); + uint32 addr = high | (low<<8); + addr = uint32(addr | (getPG<<16)); + insn.Op1.addr = addr; + } + break; + + // [AC ll mm hh] + case 0xAC:// jmpl hhmmll + { + insn.itype = m7900_jmpl; + insn.Op1.type = o_near; + uint32 ll = insn.get_next_byte(); + uint32 mm = insn.get_next_byte(); + uint32 hh = insn.get_next_byte(); + uint32 addr = (ll | (hh<<16)) | (mm<<8); + insn.Op1.addr = addr; + } + break; + + case 0xBC:// jmpl mmll((ABS,X)) + insn.itype = m7900_jmp; + Operand_AB(insn, insn.Op1, TAB_INDIRECTED_ABS_X, 16, dt_word); + break; + // _____________________ END JMP ____________________ + + // _____________________ JSR ____________________ + + case 0x9D:// jsr mmll + insn.itype = m7900_jsr; + Jsr_16(insn, insn.Op1, getPG); + break; + + case 0xAD:// jsrl hhmmll + insn.itype = m7900_jsrl; + Jsr_24(insn, insn.Op1); + break; + + case 0xBD:// jsr mmll((ABS,X)) + insn.itype = m7900_jsr; + Operand_AB(insn, insn.Op1, TAB_INDIRECTED_ABS_X, 16, dt_word); + break; + // _____________________ END JSR ____________________ + + // _____________________ LSR ____________________ + // 204 - Logical Shift Right + // lsr A + // Operation data - 16 bits or 8 bits + // [43] + case 0x43: + insn.itype = m7900_lsr; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + // _____________________ END LSR ____________________ + // _____________________ ROL ____________________ + // 254 - ROtate one bit Left + // rol A + // Operation data - 16 bits or 8 bits + // [13] + case 0x13: + insn.itype = m7900_rol; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + // _____________________ END ROL ____________________ + + // _____________________ ROR ____________________ + // 255 - ROtate one bit Right + // ror A + // Operation data - 16 bits or 8 bits + // [53] + case 0x53:// ror + insn.itype = m7900_ror; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + break; + // _____________________ END ROR ____________________ + + // _____________________ MOVM ____________________ + + case 0x86:// movm dd,#imm(DIR, IMM) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + case 0x5C:// movm dd, mmll(DIR, ABS) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + + case 0x5D:// movm dd, mmll(DIR, ABS,X) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + case 0x96:// movm dd, mmll(ABS, IMM) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + case 0x78:// movm dd, mmll(ABS, DIR) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16,SetTypeDataM); + break; + + case 0x79:// movm dd, mmll(ABS, DIR) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_AB(insn, insn.Op1, TAB_ABS, getFlag_M ? 8 : 16, SetTypeDataM); + break; + + case 0x7C:// movm mmll1,mmll2(ABS, ABS) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataM); + break; + + case 0x58:// movm dd1, dd2(DIR, DIR) + insn.itype = m7900_movm; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataM); + break; + // _____________________ END MOVM ____________________ + + // _____________________ PSH ____________________ + // 246 - PuSH + // psh #imm + // Operation data - 16 bits or 8 bits + // [A8 imm] + case 0xA8: + insn.itype = m7900_psh; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END PSH ____________________ + + // _____________________ PUL ____________________ + // 246 - PuLl + // pul #imm + // Operation data - 16 bits or 8 bits + // [67 imm] + case 0x67: + insn.itype = m7900_pul; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END PUL ____________________ + // _____________________ SEP ____________________ + case 0x99: + insn.itype = m7900_sep; + Operand_Imm(insn, insn.Op1, 8); + break; + // _____________________ END SEP ____________________ + + // _____________________ STAB ____________________ + // 272 - STore Accumulator in memory at Byte + // stab A, dd + // Operation data length: 8 bits + // [CA dd] + case 0xCA: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 8 bits + // [CB dd] + case 0xCB: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, (dd), Y () + // Operation data length: 8 bits + // [C8 dd] + case 0xC8: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_byte); + Operand_Registr(insn.Op3, rY); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 8 bits + // [C9 dd] + case 0xC9: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 8 bits + // [CE ll mm] + case 0xCE: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 8 bits + // [CF ll mm] + case 0xCF: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 8 bits + // [CC ll mm hh] + case 0xCC: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_byte); + break; + + // 272 - STore Accumulator in memory at Byte + // stab A, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 8 bits + // [CD ll mm hh] + case 0xCD: + insn.itype = m7900_stab; + RAZOPER = INSN_PREF_U; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_byte); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END STAB ____________________ + + // _____________________ STAD ____________________ + // 273 - STore Accumulator in memory at Double-word + // stad E, dd + // Operation data length: 32 bits + // [EA dd] + case 0xEA: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 32 bits + // [EB dd] + case 0xEB: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, (dd), Y () + // Operation data length: 32 bits + // [E8 dd] + case 0xE8: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_INDIRECT_DIR, dt_dword); + Operand_Registr(insn.Op3, rY); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, L(dd),Y (Direct indirect long addressing mode L(DIR)) + // Operation data length: 32 bits + // [E9 dd] + case 0xE9: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_L_INDIRECT_DIR, dt_tbyte); + Operand_Registr(insn.Op3, rY); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [EE ll mm] + case 0xEE: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [EF ll mm] + case 0xEF: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, hhmmll, Y (Absolute long addressing mode(ABL)) + // Operation data length: 32 bits + // [EC ll mm hh] + case 0xEC: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL, 24, dt_dword); + break; + + // 273 - STore Accumulator in memory at Double-word + // stad E, hhmmll, Y (Absolute long indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [ED ll mm hh] + case 0xED: + insn.itype = m7900_stad; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABL_X, 24, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END STAD ____________________ + // _____________________ STX ____________________ + // 275 - STore index register X in memory + // stx dd + // Operation data length: 16 bits or 8 bits + // [E2 dd] + case 0xE2:// stx (DIR) + insn.itype = m7900_stx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + break; + + // 275 - STore index register X in memory + // stx mmll + // Operation data length: 16 bits or 8 bits + // [E7 ll mm] + case 0xE7:// stx ABS + insn.itype = m7900_stx; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataX); + break; + // _____________________ END STX ____________________ + // _____________________ STY ____________________ + // 276 - STore index register Y in memory + // sty dd + // Operation data length: 16 bits or 8 bits + // [F2 dd] + case 0xF2:// sty (DIR) + insn.itype = m7900_sty; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_Dir(insn, insn.Op1, TDIR_DIR, SetTypeDataX); + break; + + case 0xF7:// sty ABS + insn.itype = m7900_sty; + RAZOPER = getFlag_X ? INSN_PREF_B : INSN_PREF_W; + Operand_AB(insn, insn.Op1, TAB_ABS, 16, SetTypeDataX); + break; + // _____________________END STY ____________________ + + // _____________________ SUB ____________________ + // 278 - SUBtract + // sub A, #imm + // Operation data length: 16 bits or 8 bits + // [36 #imm] + case 0x36: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Imm(insn, insn.Op2, getFlag_M ? 8 : 16); + break; + + // 278 - SUBtract + // sub A, dd + // Operation data length: 16 bits or 8 bits + // [3A dd] + case 0x3A: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR, SetTypeDataM); + break; + + // 278 - SUBtract + // sub A, dd, X (Direct index X addressing DIR,X) + // Operation data length: 16 bits or 8 bits + // [3B dd] + case 0x3B: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + + // 278 - SUBtract + // sub A, mmll (Absolute addressing mode(ABS)) + // Operation data length: 16 bits or 8 bits + // [3E ll mm] + case 0x3E: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, SetTypeDataM); + break; + + // 278 - SUBtract + // sub A, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 16 bits or 8 bits + // [3F ll mm] + case 0x3F: + insn.itype = m7900_sub; + RAZOPER = getFlag_M ? INSN_PREF_B : INSN_PREF_W; + Operand_Registr(insn.Op1, rA); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, SetTypeDataM); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END SUB ____________________ + // _____________________ SUBD ____________________ + // 280 - SUBtract at Double-word + // subd E, #imm + // Operation data length: 32 bits + // [3D #imm] + case 0x3D: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Imm(insn, insn.Op2, 32); + break; + + // 280 - SUBtract at Double-word + // subd E, dd + // Operation data length: 32 bits + // [AA dd] + case 0xAA: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR, dt_dword); + break; + + // 280 - SUBtract at Double-word + // subd E, dd, X (Direct index X addressing DIR,X) + // Operation data length: 32 bits + // [AB dd] + case 0xAB: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_Dir(insn, insn.Op2, TDIR_DIR_X, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + + // 280 - SUBtract at Double-word + // subd E, mmll (Absolute addressing mode(ABS)) + // Operation data length: 32 bits + // [AE ll mm] + case 0xAE: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS, 16, dt_dword); + break; + + // 280 - SUBtract at Double-word + // subd E, mmll, X (Absolute indexed X addressing mode(ABS,X)) + // Operation data length: 32 bits + // [AF ll mm] + case 0xAF: + insn.itype = m7900_subd; + RAZOPER = INSN_PREF_D; + Operand_Registr(insn.Op1, rE); + Operand_AB(insn, insn.Op2, TAB_ABS_X, 16, dt_dword); + Operand_Registr(insn.Op3, rX); + break; + // _____________________ END SUBD ____________________ + + default: + { + uchar cd = code & 0xF8; + if ( cd == 0xF8 ) + { + // 141 - Branch to SubRoutine + // bsr rr + // Operation data length: - + // [11111 B10-b0] + + insn.itype = m7900_bsr; + uint32 low = insn.get_next_byte(); + uint32 addr = low | (code<<8); + addr&=0x000007FF; + if ( addr & 0x400 ) + addr |= 0xfffff800; + Operand_BSR(insn, insn.Op1, addr, 2); + } + else + { + // msg("ana: %a: bad optype %d\n", insn.ip, code); + return 0; + } + } + break; + } + return insn.size; +} diff --git a/idasdk76/module/m7900/emu.cpp b/idasdk76/module/m7900/emu.cpp new file mode 100644 index 0000000..fba4f90 --- /dev/null +++ b/idasdk76/module/m7900/emu.cpp @@ -0,0 +1,235 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "7900.hpp" + +//------------------------------------------------------------------------ +// convert to data and add cross-ref +static void DataSet(const insn_t &insn, const op_t &x, ea_t EA, int isload) +{ + insn.create_op_data(EA, x); + insn.add_dref(EA, x.offb, isload ? dr_R : dr_W); +} + +//---------------------------------------------------------------------- +void m7900_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) +{ + flags_t F = get_flags(insn.ea); + switch ( x.type ) + { + case o_phrase: + //remember_problem(PR_JUMP, insn.ea); + case o_void: + case o_reg: + break; + + case o_sr: + case o_displ: + set_immd(insn.ea); + if ( !is_forced ) + { + ushort addr = ushort(x.addr); + if ( x.type == o_displ ) + { + addr += (ushort)insn.ip; + addr += insn.size; + uint32 offb = map_code_ea(insn, addr, x.n); + DataSet(insn, x, offb, isload); + } + else if ( op_adds_xrefs(F, x.n) ) + { + insn.add_off_drefs(x, dr_O, 0); + } + } + break; + + case o_stk: + case o_imm: + set_immd(insn.ea); + if ( op_adds_xrefs(F, x.n) ) + insn.add_off_drefs(x, dr_O, 0); + break; + + case o_ab: + if ( x.TypeOper == TAB_INDIRECTED_ABS_X ) + { + ea_t ea = to_ea(insn.cs, x.addr); + insn.create_op_data(ea, x.offb, dt_word); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + + // get data + uint32 Addr; + Addr = get_word(ea); + Addr = uint32(Addr | (getPG<<16)); + insn.add_cref(Addr, 2, fl_JF); + } + else + { + DataSet(insn, x, map_code_ea(insn, x), isload); + } + break; + + case o_mem: + // convert to data, add cross ref + switch ( x.TypeOper ) + { + case TDIR_DIR_Y: + case TDIR_DIR_X: + case TDIR_DIR: + case TDIR_INDIRECT_DIR: + case TDIR_INDIRECT_DIR_X: + case TDIR_INDIRECT_DIR_Y: + case TDIR_L_INDIRECT_DIR: + case TDIR_L_INDIRECT_DIR_Y: + if ( getDPReg == 1 ) + { + insn_t tmp = insn; + op_t &tmpx = tmp.ops[x.n]; + tmpx.addr &= 0xFF3F; + DataSet(tmp, tmpx, map_code_ea(tmp, tmpx), isload); + } + else + { + DataSet(insn, x, map_code_ea(insn, x), isload); + } + break; + default: + DataSet(insn, x, map_code_ea(insn, x), isload); + break; + } + break; + + case o_near: + { + ea_t ea = to_ea(insn.cs, x.addr); + switch ( insn.itype ) + { + case m7900_jsr: + insn.add_cref(ea, x.offb, fl_CN); + if ( !func_does_return(ea) ) + flow = false; + break; + + case m7900_jsrl: + insn.add_cref(ea, x.offb, fl_CF); + if ( !func_does_return(ea) ) + flow = false; + break; + + case m7900_jmpl: + insn.add_cref(ea, x.offb, fl_JF); + break; + + default: + insn.add_cref(ea, x.offb, fl_JN); + break; + } + } + break; + + default: + // warning("%a: %s,%d: bad optype %d", insn.ea, insn.get_canon_mnem(ph), x.n, x.type); + break; + } +} + +//---------------------------------------------------------------------- +static void LDD(const insn_t &ins) +{ + static const int DPR[] = { rDPR0, rDPR1, rDPR2, rDPR3 }; + + for ( int i=0; i < 4; i++ ) + if ( GETBIT(ins.Op1.value, i) == 1 ) + split_sreg_range(ins.ea+ins.size, DPR[i], ins.ops[1+i].value, SR_auto); +} + +//---------------------------------------------------------------------- +int m7900_t::emu(const insn_t &insn) +{ + // Set PG + split_sreg_range(insn.ea, rPG, ( insn.ea & 0xFF0000 ) >> 16, SR_auto); + + uint32 Feature = insn.get_canon_feature(ph); + flow = (Feature & CF_STOP) == 0; + + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + bool flag3 = is_forced_operand(insn.ea, 2); + bool flag4 = is_forced_operand(insn.ea, 3); + bool flag5 = is_forced_operand(insn.ea, 4); + + + if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true); + if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true); + if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, flag3, true); + if ( Feature & CF_USE4 ) handle_operand(insn, insn.Op4, flag4, true); + if ( Feature & CF_USE5 ) handle_operand(insn, insn.Op5, flag5, true); + + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false); + if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false); + if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, flag3, false); + if ( Feature & CF_CHG4 ) handle_operand(insn, insn.Op4, flag4, false); + if ( Feature & CF_CHG5 ) handle_operand(insn, insn.Op5, flag5, false); + + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + switch ( insn.itype ) + { + case m7900_lddn: + //split_sreg_range(insn.ea + insn.size, GetDPR(), insn.Op1.value, SR_auto); + LDD(insn); + break; + + case m7900_ldt: + split_sreg_range(insn.ea + insn.size, rDT, insn.Op1.value, SR_auto); + break; + + // clear m flag + case m7900_clm: + split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); + break; + // set m flag + case m7900_sem: + split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); + break; + + // clear processor status + case m7900_clp: + // clear m flag + if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) + split_sreg_range(insn.ea + insn.size, rfM, 0, SR_auto); + // clear x flag + if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) + split_sreg_range(insn.ea + insn.size, rfX, 0, SR_auto); + break; + + // set processor status + case m7900_sep: + // set m flag + if ( ((insn.Op1.value & 0x20) >> 5) == 1 ) + split_sreg_range(insn.ea + insn.size, rfM, 1, SR_auto); + // set x flag + if ( ((insn.Op1.value & 0x10) >> 4) == 1 ) + split_sreg_range(insn.ea + insn.size, rfX, 1, SR_auto); + break; + + // pull processor status from stack + case m7900_plp: + split_sreg_range(insn.ea + insn.size, rfM, BADSEL, SR_auto); + split_sreg_range(insn.ea + insn.size, rfX, BADSEL, SR_auto); + break; + + } + return 1; +} diff --git a/idasdk76/module/m7900/ins.cpp b/idasdk76/module/m7900/ins.cpp new file mode 100644 index 0000000..b685d09 --- /dev/null +++ b/idasdk76/module/m7900/ins.cpp @@ -0,0 +1,297 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include <ida.hpp> +#include <idp.hpp> +#include "ins.hpp" + + + +const instruc_t Instructions[] = +{ + + { "", 0 }, // Unknown Operation + + { "abs", CF_CHG1 }, // ABSolute + { "absd", CF_CHG1 }, // ABSolute at Double-word + + { "adc", CF_CHG1 | CF_USE2 }, // ADd with Carry + { "adcb", CF_CHG1 | CF_USE2 }, // ADd with Carry at Byte + { "adcd", CF_CHG1 | CF_USE2 }, // ADd with Carry at Double-word + + { "add", CF_CHG1 | CF_USE2 }, // Addition + + { "addb", CF_CHG1 | CF_USE2 }, // ADD at Byte + + { "addd", CF_CHG1 | CF_USE2 }, // ADD at Double-word + { "addm", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory + { "addmb", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory at Byte + { "addmd", CF_CHG1 | CF_USE2 }, // ADD immediate and Memory at Double-word + { "adds", CF_USE1 }, // ADD Stack pointer and immediate + { "addx", CF_USE1 }, // ADD index register X and immediate + { "addy", CF_USE1 }, // ADD index register Y and immediate + + { "and", CF_CHG1 | CF_USE2 }, // Logical AND + { "andb", CF_CHG1 | CF_USE2 }, // logical AND between immediate (Byte) + { "andm", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory + { "andmb", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory (Byte) + { "andmd", CF_CHG1 | CF_USE2 }, // logical AND between immediate value and Memory (Double word) + + + { "asl", CF_CHG1 }, // Arithmetic Shift to Left + { "asl", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Left by n bits + { "asld", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Left by n bits (Double word) + + { "asr", CF_CHG1 }, // Arithmetic Shift to Right + { "asr", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Right by n bits + { "asrd", CF_CHG1 | CF_USE2 }, // Arithmetic Shift to Right by n bits (Double word) + + { "bbc", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Clear + { "bbcb", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Clear (Byte) + { "bbs", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Set + { "bbsb", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Bit Set (Byte) + + { "bcc", CF_USE1 }, // Branch on Carry Clear + { "bcs", CF_USE1 }, // Branch on Carry Set + { "beq", CF_USE1 }, // Branch on EQual + { "bge", CF_USE1 }, // Branch on Greater or Equal + { "bgt", CF_USE1 }, // Branch on Greater Than + { "bgtu", CF_USE1 }, // Branch on Greater Than with Unsign + { "ble", CF_USE1 }, // Branch on Less or Equal + { "bleu", CF_USE1 }, // Branch on Less Equal with Unsign + { "blt", CF_USE1 }, // Branch on Less Than + { "bmi", CF_USE1 }, // Branch on result MInus + { "bne", CF_USE1 }, // Branch on Not Equal + { "bpl", CF_USE1 }, // Branch on result PLus + { "bra", CF_USE1 | CF_JUMP | CF_STOP }, // BRanch Always + { "bral", CF_USE1 | CF_JUMP | CF_STOP }, // BRanch Always + + { "brk", 0 }, // run int 0xFFFA + + { "bsc", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Single bit Clear + { "bsr", CF_USE1 | CF_CALL }, // Branch to SubRoutine + { "bss", CF_USE1 | CF_USE2 | CF_USE3 }, // Branch on Single bit Set + + { "bvc", CF_USE1 }, // Branch on oVerflow Clear + { "bvs", CF_USE1 }, // Branch on oVerflow Set + + { "cbeq", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on EQual + { "cbeqb", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on EQual at Byte + { "cbne", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on Not Equal + { "cbneb", CF_USE1 | CF_USE2 | CF_USE3 }, // Compare immediate and Branch on Not Equal at Byte + + { "clc", 0 }, // CLear Carry flag + { "cli", 0 }, // CLear Interrupt disable status + { "clm", 0 }, // CLear M flag + { "clp", CF_USE1 }, // CLear Processor status + + { "clr", CF_CHG1 }, // CLeaR accumulator + { "clrb", CF_CHG1 }, // CLeaR accumulator at Byte + { "clrm", CF_CHG1 }, // CLeaR Memory + { "clrmb", CF_CHG1 }, // CLeaR Memory at Byte + { "clrx", 0 }, // CLeaR index register X + { "clry", 0 }, // CLeaR index register Y + + { "clv", 0 }, // CLear oVerflow flag + + { "cmp", CF_USE1 | CF_USE2 }, // CoMPare + { "cmpb", CF_USE1 | CF_USE2 }, // CoMPare at Byte + { "cmpd", CF_USE1 | CF_USE2 }, // CoMPare at Double-word + { "cmpm", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory + { "cmpmb", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory at Byte + { "cmpmd", CF_USE1 | CF_USE2 }, // CoMPare immediate with Memory at Double-word + + { "cpx", CF_USE1 }, // ComPare memory and index register X + { "cpy", CF_USE1 }, // ComPare memory and index register Y + + { "debne", CF_USE1 | CF_USE2 | CF_USE3 }, // DEcrement memory and Branch on Not Equal + + { "dec", CF_CHG1 }, // DECrement by one + { "dex", 0 }, // DEcrement index register X by one + { "dey", 0 }, // DEcrement index register Y by one + + { "div", CF_USE1 }, // DIVide unsigned + { "divs", CF_USE1 }, // DIVide with Sign + { "dxbne", CF_USE1 | CF_USE2 }, // Decrement index register X and Branch on Not Equal + { "dybne", CF_USE1 | CF_USE2 }, // Decrement index register Y and Branch on Not Equal + + { "eor", CF_CHG1 | CF_USE2 }, // Exclusive OR memory with accumulator + { "eorb", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with accumulator at Byte + { "eorm", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory + { "eormb", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory at Byte + { "eormd", CF_CHG1 | CF_USE2 }, // Exclusive OR immediate with Memory at Double-word + + { "exts", CF_CHG1 }, // EXTension Sign + { "extsd", CF_CHG1 }, // EXTension Sign at Double-word + { "extz", CF_CHG1 }, // EXTension Zero + { "extzd", CF_CHG1 }, // EXTension Zero at Double-word + + { "inc", CF_CHG1 }, // INCrement by one + { "inx", 0 }, // INcrement index register X by one + { "iny", 0 }, // INcrement index register y by one + + { "jmp", CF_USE1 | CF_JUMP | CF_STOP }, // JuMP16 + { "jmpl", CF_USE1 | CF_JUMP | CF_STOP }, // Jump24 + + { "jsr", CF_USE1 | CF_CALL }, // Jump to SubRoutine16 + { "jsrl", CF_USE1 | CF_CALL }, // Jump to SubRoutine24 + + + { "lda", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory + { "ldab", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory at Byte + { "ldad", CF_CHG1 | CF_USE2 }, // LoaD Accumulator from memory at Double-word + { "ldd", CF_USE1 | CF_USE2 | CF_USE3 | CF_USE4 | CF_USE5 }, // LoaD immediate to Direct page register n + + { "ldt", CF_USE1 }, // LoaD immediate to DaTa bank register + { "ldx", CF_USE1 }, // LoaD index register X from memory + { "ldxb", CF_USE1 }, // LoaD index register X from memory at Byte + { "ldy", CF_USE1 }, // LoaD index register Y from memory + { "ldyb", CF_USE1 }, // LoaD index register Y from memory at Byte + + { "lsr", CF_CHG1 }, // Logical Shift Right + { "lsr", CF_USE2 | CF_CHG1 }, // Logical n bits Shift Right + { "lsrd", CF_USE2 | CF_CHG1 }, // Logical n bits Shift Right at Double-word + + { "movm", CF_USE2 | CF_CHG1 }, // MOVe Memory to memory + { "movmb", CF_USE2 | CF_CHG1 }, // MOVe Memory to memory at Byte + { "movr", CF_USE1 | CF_HLL }, // MOVe Repeat memory to memory + { "movrb", CF_USE1 | CF_HLL }, // MOVe Repeat memory to memory at Byte + + { "mpy", CF_USE1 }, // MultiPlY + { "mpys", CF_USE1 }, // MultiPlY with Sign + + { "mvn", CF_USE1 | CF_USE2 }, // MoVe Negative + { "mvp", CF_USE1 | CF_USE2 }, // MoVe Positive + + { "neg", CF_CHG1 }, // NEGative + { "negd", CF_CHG1 }, // NEGative at Double-word + { "nop", 0 }, // No OPeration + + + { "ora", CF_CHG1 | CF_USE2 }, // OR memory with Accumulator + { "orab", CF_CHG1 | CF_USE2 }, // OR immediate with Accumulator at Byte + { "oram", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory + { "oramb", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory at Byte + { "oramd", CF_CHG1 | CF_USE2 }, // OR immediAte with Memory at Double-word + + + { "pea", CF_USE1 }, // Push Effective Address + { "pei", CF_USE1 }, // Push Effective Indirect address + { "per", CF_USE1 }, // Push Effective program counter Relative address + { "pha", 0 }, // PusH accumulator A on stack + { "phb", 0 }, // PusH accumulator B on stack + { "phd", 0 }, // PusH Direct page register on stack + { "phd", CF_USE1 }, // PusH Direct page register n on stack + { "phg", 0 }, // PusH proGram bank register on stack + + { "phld", CF_USE1 | CF_HLL }, // PusH dpr n to stack and Load immediate to Dpr n + + { "php", 0 }, // PusH Processor status on stack + { "pht", 0 }, // PusH daTa bank register on stack + { "phx", 0 }, // PusH index register X on stack + { "phy", 0 }, // PusH index register Y on stack + + { "pla", 0 }, // PuLl accumulator A from stack + { "plb", 0 }, // PuLl accumulator B from stack + { "pld", 0 }, // PuLl Direct page register from stack + { "pld", CF_USE1 }, // PuLl Direct page register n from stack + { "plp", 0 }, // PuLl Processor status from stack + { "plt", 0 }, // PuLl daTa bank register from stack + { "plx", 0 }, // PuLl index register X from stack + { "ply", 0 }, // PuLl index register Y from stack + + { "psh", CF_USE1 }, // PuSH + { "pul", CF_USE1 }, // PuLl + + { "rla", CF_USE1 }, // Rotate Left accumulator A + { "rmpa", CF_USE1 }, // Repeat Multiply and Accumulate + + { "rol", CF_CHG1 }, // ROtate one bit Left + { "rol", CF_USE2 | CF_CHG1 }, // n bits ROtate Left + { "rold", CF_USE2 | CF_CHG1 }, // n bits ROtate Left at Double-word + + { "ror", CF_CHG1 }, // ROtate one bit Right + { "ror", CF_USE2 | CF_CHG1 }, // n bits ROtate Right + { "rord", CF_USE2 | CF_CHG1 }, // n bits ROtate Right at Double-word + + { "rti", CF_STOP }, // Return from Interrupt + { "rtl", CF_STOP }, // ReTurn from subroutine Long + { "rtld", CF_USE1 | CF_STOP }, // ReTurn from subroutine Long and pull Direct page register n + { "rts", CF_STOP }, // ReTurn from Subroutine + { "rtsd", CF_USE1 | CF_STOP }, // ReTurn from Subroutine and pull Direct page register n + + + { "sbc", CF_USE1 | CF_USE2 }, // SuBtract with Carry + { "sbcb", CF_USE1 | CF_USE2 }, // SuBtract with Carry at Byte + { "sbcd", CF_USE1 | CF_USE2 }, // SuBtract with Carry at Double-word + + + { "sec", 0 }, // SEt Carry flag + { "sei", 0 }, // SEt Interrupt disable status + { "sem", 0 }, // SEt M flag + { "sep", CF_USE1 }, // SEt Processor status + + + { "sta", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory + { "stab", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory at Byte + { "stad", CF_CHG2 | CF_USE1 }, // STore Accumulator in memory at Double-word + + { "stp", 0 }, // SToP + + { "stx", CF_CHG1 }, // STore index register X in memory + { "sty", CF_CHG1 }, // STore index register Y in memory + + { "sub", CF_CHG1 | CF_USE2 }, // SUBtract + { "subb", CF_CHG1 | CF_USE2 }, // SUBtract at Byte + { "subd", CF_CHG1 | CF_USE2 }, // SUBtract at Double-word + { "subm", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory + { "submb", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory at Byte + { "submd", CF_CHG1 | CF_USE2 }, // SUBtract immediate from Memory at Double-word + + { "subs", CF_USE1 }, // SUBtract Stack pointer + { "subx", CF_USE1 }, // SUBtract immediate from index register X + { "suby", CF_USE1 }, // SUBtract immediate from index register Y + + { "tad", CF_USE1 }, // Transfer accumulator A to Direct page register n + + { "tas", 0 }, // Transfer accumulator A to Stack pointer + { "tax", 0 }, // Transfer accumulator A to index register X + { "tay", 0 }, // Transfer accumulator A to index register Y + + { "tbd", CF_USE1 }, // Transfer accumulator B to Direct page register n + + { "tbs", 0 }, // Transfer accumulator B to Stack pointer + { "tbx", 0 }, // Transfer accumulator B to index register X + { "tby", 0 }, // Transfer accumulator B to index register Y + + { "tda", CF_USE1 }, // Transfer Direct page register n to accumulator A + { "tdb", CF_USE1 }, // Transfer Direct page register n to accumulator B + + { "tds", 0 }, // Transfer Direct page register to Stack pointer + { "tsa", 0 }, // Transfer Stack pointer to accumulator A + { "tsb", 0 }, // Transfer Stack pointer to accumulator B + + { "tsd", 0 }, // Transfer Stack pointer to Direct page register + { "tsx", 0 }, // Transfer Stack pointer to index register X + { "txa", 0 }, // Transfer index register X to accumulator A + { "txb", 0 }, // Transfer index register X to accumulator B + { "txs", 0 }, // Transfer index register X to Stack pointer + { "txy", 0 }, // Transfer index register X to Y + { "tya", 0 }, // Transfer index register Y to accumulator A + { "tyb", 0 }, // Transfer index register Y to accumulator B + { "tyx", 0 }, // Transfer index register Y to X + + { "wit", CF_STOP }, // WaIT + + { "xab", 0 }, // eXchange accumulator A and B + +}; + +CASSERT(qnumber(Instructions) == m7900_last); diff --git a/idasdk76/module/m7900/ins.hpp b/idasdk76/module/m7900/ins.hpp new file mode 100644 index 0000000..033e198 --- /dev/null +++ b/idasdk76/module/m7900/ins.hpp @@ -0,0 +1,299 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * MITSUBISHI 7900 Family + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ +m7900_null = 0, // Unknown Operation + + +m7900_abs, // ABSolute +m7900_absd, // ABSolute at Double-word + +m7900_adc, // ADd with Carry +m7900_adcb, // ADd with Carry at Byte +m7900_adcd, // ADd with Carry at Double-word + +m7900_add, // Addition + +m7900_addb, // ADD at Byte +m7900_addd, // ADD at Double-word +m7900_addm, // ADD immediate and Memory +m7900_addmb, // ADD immediate and Memory at Byte +m7900_addmd, // ADD immediate and Memory at Double-word +m7900_adds, // ADD Stack pointer and immediate +m7900_addx, // ADD index register X and immediate +m7900_addy, // ADD index register Y and immediate + +m7900_and, // Logical AND +m7900_andb, // logical AND between immediate (Byte) + +m7900_andm, // logical AND between immediate value and Memory +m7900_andmb, // logical AND between immediate value and Memory (Byte) +m7900_andmd, // logical AND between immediate value and Memory (Double word) + +m7900_asl, // Arithmetic Shift to Left +m7900_asln, // Arithmetic Shift to Left by n bits +m7900_asldn, // Arithmetic Shift to Left by n bits (Double word) + + +m7900_asr, // Arithmeticshift to the right +m7900_asrn, // Arithmetic Shift to Right by n bits +m7900_asrdn, // Arithmetic Shift to Right by n bits (Double word) + +m7900_bbc, // Branch on Bit Clear +m7900_bbcb, // Branch on Bit Clear (Byte) +m7900_bbs, // Branch on Bit Set +m7900_bbsb, // Branch on Bit Set (Byte) + +m7900_bcc, // Branch on Carry Clear +m7900_bcs, // Branch on Carry Set +m7900_beq, // Branch on EQual +m7900_bge, // Branch on Greater or Equal +m7900_bgt, // Branch on Greater Than +m7900_bgtu, // Branch on Greater Than with Unsign +m7900_ble, // Branch on Less or Equal +m7900_bleu, // Branch on Less Equal with Unsign +m7900_blt, // Branch on Less Than +m7900_bmi, // Branch on result MInus +m7900_bne, // Branch on Not Equal +m7900_bpl, // Branch on result PLus +m7900_bra, // BRanch Always +m7900_bral, // BRanch Always + +m7900_brk, // force BReaK + +m7900_bsc, // Branch on Single bit Clear +m7900_bsr, // Branch to SubRoutine +m7900_bss, // Branch on Single bit Set + +m7900_bvc, // Branch on oVerflow Clear +m7900_bvs, // Branch on oVerflow Set + +m7900_cbeq, // Compare immediate and Branch on EQual +m7900_cbeqb, // Compare immediate and Branch on EQual at Byte +m7900_cbne, // Compare immediate and Branch on Not Equal +m7900_cbneb, // Compare immediate and Branch on Not Equal at Byte + +m7900_clc, // CLear Carry flag +m7900_cli, // CLear Interrupt disable status +m7900_clm, // CLear M flag +m7900_clp, // CLear Processor status + +m7900_clr, // CLeaR accumulator +m7900_clrb, // CLeaR accumulator at Byte +m7900_clrm, // CLeaR Memory +m7900_clrmb, // CLeaR Memory at Byte +m7900_clrx, // CLeaR index register X +m7900_clry, // CLeaR index register Y + +m7900_clv, // CLear oVerflow flag + +m7900_cmp, // CoMPare +m7900_cmpb, // CoMPare at Byte +m7900_cmpd, // CoMPare at Double-word +m7900_cmpm, // CoMPare immediate with Memory +m7900_cmpmb, // CoMPare immediate with Memory at Byte +m7900_cmpmd, // CoMPare immediate with Memory at Double-word + +m7900_cpx, // ComPare memory and index register X +m7900_cpy, // ComPare memory and index register Y + +m7900_debne, // DEcrement memory and Branch on Not Equal + +m7900_dec, // DECrement by one +m7900_dex, // DEcrement index register X by one +m7900_dey, // DEcrement index register Y by one + +m7900_div, // DIVide unsigned +m7900_divs, // DIVide with Sign +m7900_dxbne, // Decrement index register X and Branch on Not Equal +m7900_dybne, // Decrement index register Y and Branch on Not Equal + +m7900_eor, // Exclusive OR memory with accumulator +m7900_eorb, // Exclusive OR immediate with accumulator at Byte +m7900_eorm, // Exclusive OR immediate with Memory +m7900_eormb, // Exclusive OR immediate with Memory at Byte +m7900_eormd, // Exclusive OR immediate with Memory at Double-word + +m7900_exts, // EXTension Sign +m7900_extsd, // EXTension Sign at Double-word +m7900_extz, // EXTension Zero +m7900_extzd, // EXTension Zero at Double-word + +m7900_inc, // INCrement by one +m7900_inx, // INcrement index register X by one +m7900_iny, // INcrement index register y by one + +m7900_jmp, // Jump +m7900_jmpl, // Jump + +m7900_jsr, // Jump to SubRoutine +m7900_jsrl, // Jump to SubRoutine + + +m7900_lda, // LoaD Accumulator from memory +m7900_ldab, // LoaD Accumulator from memory at Byte +m7900_ldad, // LoaD Accumulator from memory at Double-word +m7900_lddn, // LoaD immediate to Direct page register n + +m7900_ldt, // LoaD immediate to DaTa bank register +m7900_ldx, // LoaD index register X from memory +m7900_ldxb, // LoaD index register X from memory at Byte +m7900_ldy, // LoaD index register Y from memory +m7900_ldyb, // LoaD index register Y from memory at Byte + +m7900_lsr, // Logical Shift Right +m7900_lsrn, // Logical n bits Shift Right +m7900_lsrdn, // Logical n bits Shift Right at Double-word + +m7900_movm, // MOVe Memory to memory +m7900_movmb, // MOVe Memory to memory at Byte +m7900_movr, // MOVe Repeat memory to memory +m7900_movrb, // MOVe Repeat memory to memory at Byte + +m7900_mpy, // MultiPlY +m7900_mpys, // MultiPlY with Sign + +m7900_mvn, // MoVe Negative +m7900_mvp, // MoVe Positive + +m7900_neg, // NEGative +m7900_negd, // NEGative at Double-word + +m7900_nop, // No OPeration + +m7900_ora, // OR memory with Accumulator +m7900_orab, // OR immediate with Accumulator at Byte +m7900_oram, // OR immediAte with Memory +m7900_oramb, // OR immediAte with Memory at Byte +m7900_oramd, // OR immediAte with Memory at Double-word + +m7900_pea, // Push Effective Address +m7900_pei, // Push Effective Indirect address +m7900_per, // Push Effective program counter Relative address +m7900_pha, // PusH accumulator A on stack +m7900_phb, // PusH accumulator B on stack +m7900_phd, // PusH Direct page register on stack +m7900_phdn, // PusH Direct page register n on stack +m7900_phg, // PusH proGram bank register on stack + +m7900_phldn, // PusH dpr n to stack and Load immediate to Dpr n + +m7900_php, // PusH Processor status on stack +m7900_pht, // PusH daTa bank register on stack +m7900_phx, // PusH index register X on stack +m7900_phy, // PusH index register Y on stack + +m7900_pla, // PuLl accumulator A from stack +m7900_plb, // PuLl accumulator B from stack +m7900_pld, // PuLl Direct page register from stack +m7900_pldn, // PuLl Direct page register n from stack +m7900_plp, // PuLl Processor status from stack +m7900_plt, // PuLl daTa bank register from stack +m7900_plx, // PuLl index register X from stack +m7900_ply, // PuLl index register Y from stack + +m7900_psh, // PuSH +m7900_pul, // PuLl + +m7900_rla, // Rotate Left accumulator A +m7900_rmpa, // Repeat Multiply and Accumulate + +m7900_rol, // ROtate one bit Left +m7900_roln, // n bits ROtate Left + +m7900_roldn, // n bits ROtate Left at Double-word + +m7900_ror, // ROtate one bit Right +m7900_rorn, // n bits ROtate Right +m7900_rordn, // n bits ROtate Right at Double-word + +m7900_rti, // Return from Interrupt +m7900_rtl, // ReTurn from subroutine Long +m7900_rtld, // ReTurn from subroutine Long and pull Direct page register n +m7900_rts, // ReTurn from Subroutine +m7900_rtsdn, // ReTurn from Subroutine and pull Direct page register n + + +m7900_sbc, // SuBtract with Carry +m7900_sbcb, // SuBtract with Carry at Byte +m7900_sbcd, // SuBtract with Carry at Double-word + + +m7900_sec, // SEt Carry flag +m7900_sei, // SEt Interrupt disable status +m7900_sem, // SEt M flag +m7900_sep, // SEt Processor status + + +m7900_sta, // STore Accumulator in memory +m7900_stab, // STore Accumulator in memory at Byte +m7900_stad, // STore Accumulator in memory at Double-word + + +m7900_stp, // SToP +m7900_stx, // STore index register X in memory +m7900_sty, // STore index register Y in memory + +m7900_sub, // SUBtract +m7900_subb, // SUBtract at Byte +m7900_subd, // SUBtract at Double-word +m7900_subm, // SUBtract immediate from Memory +m7900_submb, // SUBtract immediate from Memory at Byte +m7900_submd, // SUBtract immediate from Memory at Double-word +m7900_subs, // SUBtract Stack pointer +m7900_subx, // SUBtract immediate from index register X +m7900_suby, // SUBtract immediate from index register Y + + + +m7900_tadn, // Transfer accumulator A to Direct page register n + + +m7900_tas, // Transfer accumulator A to Stack pointer +m7900_tax, // Transfer accumulator A to index register X +m7900_tay, // Transfer accumulator A to index register Y + +m7900_tbdn, // Transfer accumulator B to Direct page register n + +m7900_tbs, // Transfer accumulator B to Stack pointer +m7900_tbx, // Transfer accumulator B to index register X +m7900_tby, // Transfer accumulator B to index register Y + +m7900_tdan, // Transfer Direct page register n to accumulator A +m7900_tdbn, // Transfer Direct page register n to accumulator B + +m7900_tds, // Transfer Direct page register to Stack pointer + + +m7900_tsa, // Transfer Stack pointer to accumulator A +m7900_tsb, // Transfer Stack pointer to accumulator B +m7900_tsd, // Transfer Stack pointer to Direct page register +m7900_tsx, // Transfer Stack pointer to index register X +m7900_txa, // Transfer index register X to accumulator A +m7900_txb, // Transfer index register X to accumulator B +m7900_txs, // Transfer index register X to Stack pointer +m7900_txy, // Transfer index register X to Y +m7900_tya, // Transfer index register Y to accumulator A +m7900_tyb, // Transfer index register Y to accumulator B +m7900_tyx, // Transfer index register Y to X + +m7900_wit, // WaIT + +m7900_xab, // eXchange accumulator A and B + +m7900_last // + + }; + +#endif diff --git a/idasdk75/module/m7900/m7900.cfg b/idasdk76/module/m7900/m7900.cfg similarity index 100% rename from idasdk75/module/m7900/m7900.cfg rename to idasdk76/module/m7900/m7900.cfg diff --git a/idasdk76/module/m7900/makefile b/idasdk76/module/m7900/makefile new file mode 100644 index 0000000..8fe8107 --- /dev/null +++ b/idasdk76/module/m7900/makefile @@ -0,0 +1,52 @@ +PROC=m7900 +CONFIGS=m7900.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp 7900.hpp ana.cpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp 7900.hpp emu.cpp ins.hpp +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp 7900.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp 7900.hpp ins.hpp reg.cpp diff --git a/idasdk76/module/m7900/out.cpp b/idasdk76/module/m7900/out.cpp new file mode 100644 index 0000000..7b391e5 --- /dev/null +++ b/idasdk76/module/m7900/out.cpp @@ -0,0 +1,846 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "7900.hpp" + +static const char *const BitNamesCPU[] = { "IPL", "N", "V", "m", "x", "D", "I", "Z", "C" }; +static const char *const BitNamesPUL[] = { "PS", "0", "DT", "DP0", "Y", "X", "B", "A" }; + +//---------------------------------------------------------------------- +class out_m7900_t : public outctx_t +{ + out_m7900_t(void) = delete; // not used +public: + void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); } + int OutVarName(const op_t &x); + void SetDP0Plus(const op_t &x) { out_value(x, OOFW_IMM | OOFW_16); } + void GetNumPUL(uval_t data); + void GetNumDPRn(uval_t data); + void GetCLPFlags(uval_t data); + ea_t OutDPRReg(ea_t Addr, uval_t gDPReg); + void OutDPR(uint32 Data); + void OutDT(uint32 Data); + void OutIMM(uint32 Data); + void MOVRB(void); + void MOVR(void); + void MOV(const op_t &x); + + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); +}; +CASSERT(sizeof(out_m7900_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_m7900_t) + +//---------------------------------------------------------------------- +void out_m7900_t::GetNumPUL(uval_t data) +{ + int bitOut = 0; + for ( int i=0; i < 8; i++ ) + { + if ( GETBIT(data, i) == 1 ) + { + if ( bitOut != 0 ) + out_symbol(','); + out_register(BitNamesPUL[7-i]); + if ( bitOut == 0 ) + bitOut++; + } + } +} + +//---------------------------------------------------------------------- +void out_m7900_t::GetNumDPRn(uval_t data) +{ + switch ( data ) + { + case 0x1: + out_symbol('0'); + break; + case 0x2: + out_symbol('1'); + break; + case 0x4: + out_symbol('2'); + break; + case 0x8: + out_symbol('3'); + break; + default: + out_symbol('('); + bool add_comma = false; + for ( int i=0; i < 4; ++i ) + { + if ( GETBIT(data, i) == 1 ) + { + if ( add_comma ) + out_symbol(','); + out_long(i, 10); + add_comma = true; + } + } + out_symbol(')'); + break; + } +} + +//---------------------------------------------------------------------- +void out_m7900_t::GetCLPFlags(uval_t data) +{ + int bitOut = 0; + for ( int i=0; i < 8; i++ ) + { + if ( GETBIT(data, i) == 1 ) + { + if ( bitOut != 0 ) + out_symbol(','); + out_register(BitNamesCPU[8-i]); + if ( bitOut == 0 ) + bitOut++; + } + } +} + +//---------------------------------------------------------------------- +int out_m7900_t::OutVarName(const op_t &x) +{ + return out_name_expr(x, to_ea(insn.cs, x.addr), x.addr); +} + +//---------------------------------------------------------------------- +static int getNumDPR(uval_t iDPR ) +{ + switch ( iDPR ) + { + case 0x0: return 0; + case 0x40: return 1; + case 0x80: return 2; + case 0xC0: return 3; + } + return 0; + +} + +//---------------------------------------------------------------------- +ea_t out_m7900_t::OutDPRReg(ea_t Addr, uval_t gDPReg) +{ + if ( gDPReg == 1 ) + { + char szTemp[5]; + uval_t Data = Addr; + Data &= 0xC0; + qsnprintf(szTemp, sizeof(szTemp), "DP%d", getNumDPR(Data)); + out_register(szTemp); + Addr &= 0xFF3F; + } + else + { + out_keyword("DP0"); + } + return Addr; +} + +//---------------------------------------------------------------------- +static sel_t GetValueDP(const insn_t &insn, int DPR ) +{ + if ( getDPReg == 1 ) + { + switch ( DPR ) + { + case 0x0: return getDPR0; + case 0x40: return getDPR1; + case 0x80: return getDPR2; + case 0xC0: return getDPR3; + } + } + return 0; +} + +//---------------------------------------------------------------------- +void out_m7900_t::OutDPR(uint32 Data) +{ + ea_t Val = Data; + Val = OutDPRReg(Val, getDPReg); + out_symbol(':'); + out_printf(COLSTR("%a",SCOLOR_NUMBER), Val+GetValueDP(insn, Data&0xC0)); +} + +//---------------------------------------------------------------------- +void out_m7900_t::OutDT(uint32 Data) +{ + out_register("DT"); + out_symbol('+'); + out_symbol(':'); + out_printf(COLSTR("%X",SCOLOR_NUMBER), Data); +} + +//---------------------------------------------------------------------- +void out_m7900_t::OutIMM(uint32 Data) +{ + out_symbol('#'); + out_printf(COLSTR("%x",SCOLOR_NUMBER), Data); +} + +//---------------------------------------------------------------------- +void out_m7900_t::MOVRB(void) +{ + int i; + uint32 Val1, Val2; + uchar code = get_byte(insn.ea+1); + uchar nib = (code >> 4) & 0xF; + uchar count = code & 0x0F; + + switch ( nib ) + { + case 0x0: + for ( i=0; i < count; i++ ) + { + Val1 = get_byte(insn.ea+2+(i*2));// imm + Val2 = get_byte(insn.ea+2+(i*2)+1);// dd + + // DPRxx + OutDPR(Val2); + out_symbol(','); + // imm + OutIMM(Val1); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x1: + for ( i=0; i < count; i++ ) + { + Val2 = get_word(insn.ea+2+(i*3));// mmll + Val1 = get_byte(insn.ea+2+(i*3)+2);// dd + + // DPRxx + OutDPR(Val1); + out_symbol(','); + // DPR + OutDT(Val2); + out_symbol(','); + OutReg(rX); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x2: + for ( i=0; i < count; i++ ) + { + Val1 = get_byte(insn.ea+2+(i*3));// imm + Val2 = get_word(insn.ea+2+(i*3)+1);// mmll + + // DPRxx + OutDT(Val2); + out_symbol(','); + // IMM + OutIMM(Val1); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x4: + for ( i=0; i < count; i++ ) + { + Val1 = get_byte(insn.ea+2+(i*2));// dd1 + Val2 = get_byte(insn.ea+2+(i*2)+1);// dd2 + + // DPRxx + OutDPR(Val2); + out_symbol(','); + // DPRxx + OutDPR(Val1); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x6: + for ( i=0; i < count; i++ ) + { + Val1 = get_byte(insn.ea+2+(i*3));// imm + Val2 = get_word(insn.ea+2+(i*3)+1);// mmll + + // DPRxx + OutDT(Val2); + out_symbol(','); + // DPR + OutDPR(Val1); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x7: + for ( i=0; i < count; i++ ) + { + Val2 = get_byte(insn.ea+2+(i*3));// mmll + Val1 = get_word(insn.ea+2+(i*3)+1);// dd + + // DPRxx + OutDT(Val1); + out_symbol(','); + // DPR + OutDPR(Val2); + out_symbol(','); + OutReg(rX); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x8: + for ( i=0; i < count; i++ ) + { + Val2 = get_word(insn.ea+2+(i*3));// mmll + Val1 = get_byte(insn.ea+2+(i*3)+2);// dd + + // DPRxx + OutDPR(Val1); + out_symbol(','); + // DT + OutDT(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0xA: + for ( i=0; i < count; i++ ) + { + Val1 = get_word(insn.ea+2+(i*4));// imm + Val2 = get_word(insn.ea+2+(i*4)+2);// mmll + + // DPRxx + OutDT(Val2); + out_symbol(','); + // DT + OutDT(Val1); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + } +} + +//---------------------------------------------------------------------- +void out_m7900_t::MOVR(void) +{ + int i; + uint32 Val1, Val2; + uchar code = get_byte(insn.ea+1); + uchar nib = (code >> 4) & 0xF; + uchar count = code & 0x0F; + + switch ( nib ) + { + case 0x0: + for ( i=0; i < count; i++ ) + { + Val2 = get_word(insn.ea+2+(i*3));// mmll + Val1 = get_byte(insn.ea+2+(i*3)+2);// dd + + // DPRxx + OutDPR(Val1); + out_symbol(','); + // DT + OutDT(Val2); + out_symbol(','); + OutReg(rX); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x1: + for ( i=0; i < count; i++ ) + { + if ( getFlag_M == 0 ) + { + Val2 = get_word(insn.ea+2+(i*3));// imm + Val1 = get_byte(insn.ea+2+(i*3)+2);// dd + } + else + { + Val2 = get_byte(insn.ea+2+(i*2));// imm + Val1 = get_byte(insn.ea+2+(i*2)+1);// dd + } + + // DPRxx + OutDPR(Val1); + out_symbol(','); + // imm + OutIMM(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x3: + for ( i=0; i < count; i++ ) + { + if ( getFlag_M == 0 ) + { + Val2 = get_word(insn.ea+2+(i*4));// imm + Val1 = get_word(insn.ea+2+(i*4)+2);// llmm + } + else + { + Val2 = get_byte(insn.ea+2+(i*3));// imm + Val1 = get_word(insn.ea+2+(i*3)+1);// llmm + } + + // DPRxx + OutDT(Val1); + out_symbol(','); + // IMM + OutIMM(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x5: + for ( i=0; i < count; i++ ) + { + Val2 = get_byte(insn.ea+2+(i*2));// dd + Val1 = get_byte(insn.ea+2+(i*2)+1);// dd + + // DPRxx + OutDPR(Val1); + out_symbol(','); + // DPR + OutDPR(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x6: + for ( i=0; i < count; i++ ) + { + Val1 = get_byte(insn.ea+2+(i*3));// imm + Val2 = get_word(insn.ea+2+(i*3)+1);// mmll + + // DPRxx + OutDT(Val2); + out_symbol(','); + // DPR + OutDPR(Val1); + out_symbol(','); + OutReg(rX); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x7: + for ( i=0; i < count; i++ ) + { + Val2 = get_byte(insn.ea+2+(i*3));// mmll + Val1 = get_word(insn.ea+2+(i*3)+1);// dd + + // DPRxx + OutDT(Val1); + out_symbol(','); + // DPR + OutDPR(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0x9: + for ( i=0; i < count; i++ ) + { + Val2 = get_word(insn.ea+2+(i*3));// mmll + Val1 = get_byte(insn.ea+2+(i*3)+2);// dd + + // DPRxx + OutDPR(Val1); + out_symbol(','); + // DPR + OutDT(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + + case 0xB: + for ( i=0; i < count; i++ ) + { + Val2 = get_word(insn.ea+2+(i*4));// imm + Val1 = get_word(insn.ea+2+(i*4)+2);// llmm + + // DT + OutDT(Val1); + out_symbol(','); + // DT + OutDT(Val2); + + if ( i != (count-1) ) + out_symbol(','); + } + break; + } +} + +//---------------------------------------------------------------------- +void out_m7900_t::MOV(const op_t &x) +{ + switch ( x.TypeOper ) + { + case m7900_movrb: MOVRB(); break; + case m7900_movr: MOVR(); break; + default: + // msg("out: %a: bad prefix %d\n", insn.ip, RAZOPER); + break; + } +} + +//---------------------------------------------------------------------- +bool out_m7900_t::out_operand(const op_t &x) +{ + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + OutReg(x.reg); + break; + + case o_phrase: + out_line(ph.reg_names[x.reg]); + break; + + case o_ab: + switch ( x.TypeOper ) + { + case TAB_L_INDIRECTED_ABS: + out_symbol('L'); + // fallthrough + + case TAB_INDIRECTED_ABS: + out_symbol('('); + if ( !OutVarName(x) ) + out_value(x, OOF_ADDR | OOFS_NOSIGN); + out_symbol(')'); + break; + + case TAB_INDIRECTED_ABS_X: + out_symbol('('); + + if ( !OutVarName(x) ) + out_value(x, OOF_ADDR | OOFS_NOSIGN); + + out_symbol(','); + OutReg(rX); + out_symbol(')'); + break; + + case TAB_ABS_Y: + case TAB_ABS_X: + case TAB_ABS: + out_register("DT"); + out_symbol(':'); + + if ( !OutVarName(x) ) + out_value(x, OOF_ADDR | OOFS_NOSIGN | OOFW_32); + break; + + case TAB_ABL_X: + case TAB_ABL: + out_register("LG"); + out_symbol(':'); + + if ( !OutVarName(x) ) + out_value(x, OOF_ADDR | OOFS_NOSIGN | OOFW_32); + break; + } + break; + + case o_sr: + if ( x.TypeOper == TSP_INDEX_SP_Y ) + out_symbol('('); + + if ( x.xmode == IMM_32 ) + out_value(x, OOFW_IMM | OOFW_32); + else if ( x.xmode == IMM_16 ) + out_value(x, OOFW_IMM | OOFW_16); + else + out_value(x, OOFW_IMM); + + if ( x.TypeOper == TSP_INDEX_SP_Y ) + { + out_symbol(','); + OutReg(rPS); + out_symbol(')'); + } + break; + + case o_stk: + // there are special cases + switch ( insn.itype ) + { + case m7900_pei: SetDP0Plus(x); break; + case m7900_psh: + case m7900_pul: GetNumPUL(x.value); break; + + default: + out_symbol('#'); + out_value(x, OOFW_IMM | OOFS_NOSIGN); + break; + } + break; + + case o_imm: + // there are special cases + switch ( insn.itype ) + { + case m7900_sep:// Set Processor status + case m7900_clp:// CLear Processor status + GetCLPFlags(x.value); + break; + + case m7900_lddn: + case m7900_tdan: + case m7900_phdn: + case m7900_rtsdn: + case m7900_pldn: + case m7900_rtld: + case m7900_phldn: + GetNumDPRn(x.value); + break; + case m7900_bsc: + case m7900_bss: + out_value(x, OOFW_IMM); + break; + + default: + out_symbol('#'); + out_value(x, OOFW_IMM); + break; + } + break;// case o_imm + + case o_mem: + // output memory variable name (for example 'byte_98') + if ( x.TypeOper == m7900_movr || x.TypeOper == m7900_movrb ) + { + MOV(x); + break; + } + + switch ( x.TypeOper ) + { + case TDIR_DIR_Y: + case TDIR_DIR_X: + case TDIR_DIR: + { + op_t y = x; + y.addr = OutDPRReg(y.addr, getDPReg); + out_symbol(':'); + if ( !OutVarName(y) ) + out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN); + } + break; + + case TDIR_L_INDIRECT_DIR_Y: + case TDIR_L_INDIRECT_DIR: + out_symbol('L'); + // fallthrough + + case TDIR_INDIRECT_DIR_Y: + case TDIR_INDIRECT_DIR: + out_symbol('('); + { + op_t y = x; + y.addr = OutDPRReg(y.addr, getDPReg); + out_symbol(':'); + if ( !OutVarName(y) ) + out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN); + } + out_symbol(')'); + break; + + case TDIR_INDIRECT_DIR_X: + out_symbol('('); + + { + op_t y = x; + y.addr = OutDPRReg(y.addr, getDPReg); + out_symbol(':'); + if ( !OutVarName(y) ) + out_value(y, OOF_ADDR |OOF_NUMBER| OOFS_NOSIGN); + } + + out_symbol(','); + OutReg(rX); + out_symbol(')'); + break; + } + break; + + case o_near: + { + ea_t v = to_ea(insn.cs,x.addr); + if ( !out_name_expr(x, v, x.addr) ) + { + out_value(x, OOF_ADDR | OOFS_NOSIGN); + // remember_problem(PR_NONAME, insn.ea); + } + } + break; + + default: + // warning("out: %a: bad optype %d", insn.ip, x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +static const char *GetPrefics(int Raz) +{ + switch ( Raz ) + { + case INSN_PREF_B: return ".b"; + case INSN_PREF_W: return ""; + case INSN_PREF_D: return ".d"; + case INSN_PREF_U: return ""; + default: + // msg("out: %a: bad prefix %d\n", insn.ip, RAZOPER); + break; + } + return ""; +} + +//---------------------------------------------------------------------- +void out_m7900_t::out_proc_mnem(void) +{ + out_mnem(8, GetPrefics(RAZOPER)); // output instruction mnemonics +} + +//---------------------------------------------------------------------- +void out_m7900_t::out_insn(void) +{ + out_mnemonic(); + + out_one_operand(0); // output the first operand + + if ( insn.Op2.type != o_void ) + { + out_symbol(','); // operand sep + if ( (ash.uflag & UAS_NOSPA) == 0 ) + out_char(' '); + out_one_operand(1); + } + + if ( insn.Op3.type != o_void ) + { + out_symbol(','); + if ( (ash.uflag & UAS_NOSPA) == 0 ) + out_char(' '); + out_one_operand(2); + } + + if ( insn.Op4.type != o_void ) + { + out_symbol(','); + if ( (ash.uflag & UAS_NOSPA) == 0 ) + out_char(' '); + out_one_operand(3); + } + + + if ( insn.Op5.type != o_void ) + { + out_symbol(','); + if ( (ash.uflag & UAS_NOSPA) == 0 ) + out_char(' '); + out_one_operand(4); + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void m7900_t::m7900_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, NULL, ioh.device.c_str()); +} + +//-------------------------------------------------------------------------- +// generate segment header +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Srange) could be made const +void m7900_t::m7900_segstart(outctx_t &ctx, segment_t *Srange) const +{ + qstring sname; + get_visible_segm_name(&sname, Srange); + + if ( ash.uflag & UAS_SEGM ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR("SEGMENT %s", SCOLOR_ASMDIR), sname.c_str()); + else + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".SECTION %s", SCOLOR_ASMDIR), sname.c_str()); + + ea_t orgbase = ctx.insn_ea - get_segm_para(Srange); + if ( orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +void m7900_t::m7900_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + size_t i = strlen(ash.end); + do + ctx.out_char(' '); + while ( ++i < 8 ); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} diff --git a/idasdk76/module/m7900/reg.cpp b/idasdk76/module/m7900/reg.cpp new file mode 100644 index 0000000..68f23bb --- /dev/null +++ b/idasdk76/module/m7900/reg.cpp @@ -0,0 +1,441 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include <ctype.h> +#include "7900.hpp" +#include <diskio.hpp> +#include <entry.hpp> +int data_id; + +//---------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "A", "B", "E", "X", "Y", "PC", "S", + "fIPL", "fN", "fV", "fD", "fI", "fZ", "fC", + "DT", "PG", "DPReg", "DPR0","DPR1", "DPR2","DPR3","fM", "fX", + "cs", "ds" +}; + + + + +//---------------------------------------------------------------------- +static const asm_t AS79 = +{ + AS_COLON // create colons after data names ? + // ASCII directives: + |AS_1TEXT // 1 text per line, no bytes + |ASH_HEXF0 // format of hex numbers:// 34h + |ASD_DECF0 // format of dec numbers:// 34 + |ASB_BINF0 // format of binary numbers:// 010101b + |AS_ONEDUP, // One array definition per line + + UAS_NOSPA | UAS_SEGM, + "Mitsubishi AS79 V4.10", + 0, + NULL, // header + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".BYTE", // ascii string directive + ".BYTE", // byte directive + ".WORD", // word directive + ".DWORD", // no double words + NULL, // no qwords + NULL, // oword (16 bytes) + NULL, // no float + NULL, // no double + NULL, // no tbytes + NULL, // no packreal + NULL, //".db.#s(b,w) #d,#v", // #h - header(.byte,.word) + // #d - size of array + // #v - value of array elements + // #s - size specifier + ".rs %s", // uninited data (reserve space) + ".equ", + NULL, // seg prefix + "*", // a_curip + NULL, // returns function header line + NULL, // returns function footer line + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +#define FAMILY "Mitsubishi series:" + +static const char *const shnames[] = +{ + "m7900", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Mitsubishi 7700 Family / 7900 Series", + NULL +}; + + +static const asm_t *const asms[] = +{ + &AS79, + NULL +}; + +//-------------------------------------------------------------------------- +static const uchar retc_0[] = { 0xF1 }; // rti +static const uchar retc_1[] = { 0x94 }; // rtl +static const uchar retc_2[] = { 0x1C, 0x77 }; // rtld 0 +static const uchar retc_3[] = { 0x2C, 0x77 }; // rtld 1 +static const uchar retc_4[] = { 0x4C, 0x77 }; // rtld 2 +static const uchar retc_5[] = { 0x8C, 0x77 }; // rtld 3 +static const uchar retc_6[] = { 0x84 }; // rts +static const uchar retc_7[] = { 0x18, 0x77 }; // rtsd 0 +static const uchar retc_8[] = { 0x28, 0x77 }; // rtsd 1 +static const uchar retc_9[] = { 0x48, 0x77 }; // rtsd 2 +static const uchar retc_10[] = { 0x88, 0x77 }; // rtsd 3 +static const uchar retc_11[] = { 0x00, 0x74 }; // brk + +static const bytes_t retcodes[] = +{ + { sizeof(retc_0), retc_0 }, + { sizeof(retc_1), retc_1 }, + { sizeof(retc_2), retc_2 }, + { sizeof(retc_3), retc_3 }, + { sizeof(retc_4), retc_4 }, + { sizeof(retc_5), retc_5 }, + { sizeof(retc_6), retc_6 }, + { sizeof(retc_6), retc_7 }, + { sizeof(retc_6), retc_8 }, + { sizeof(retc_9), retc_9 }, + { sizeof(retc_10), retc_10 }, + { sizeof(retc_11), retc_11 }, + { 0, NULL } +}; + + +//---------------------------------------------------------------------- +#define ADDRRESET 0xFFFE + +const char *m7900_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( !choose_ioport_device(&ioh.device, cfgfile) + && ioh.device == NONEPROC ) + { + warning("No devices are defined in the configuration file %s", cfgfile); + } + + ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT); + + return IDPOPT_OK; +} + + +//------------------------------------------------------------------ +bool m7900_t::choose_device() +{ + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + bool ok = choose_ioport_device2(&ioh.device, cfgfile, &cb); + if ( !ok ) + { + ioh.device = NONEPROC; + + segment_t *sptr = get_first_seg(); + if ( sptr != NULL ) + { + //inf_set_start_ea(sptr->start_ea); + //inf_set_start_ip(0); + + // No processor selected, so create RESET. + // According to 7900 manual RESET resides at 0xFFFE address + create_word(ADDRRESET, 2); + ea_t proc = get_word(ADDRRESET); + if ( proc != 0xFFFF && is_mapped(proc) ) + { + op_plain_offset(ADDRRESET, 0, 0); + add_entry(proc, proc, "__RESET", true); + set_cmt(ADDRRESET, "RESET", false); + } + } + } + return ok; +} + +//-------------------------------------------------------------------------- +void m7900_t::load_from_idb() +{ + ioh.restore_device(IORESP_NONE); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t notification_code, va_list va) +{ + switch ( notification_code ) + { + case idb_event::sgr_changed: + // In case of fM or fX segment registers undefine data above current address + { + int reg = va_arg(va, int); + if ( reg == rfM || reg == rfX || reg == rDT || reg == rPG ) + { +// msg("Deleting instructions in range %08a..%08a\n",ea1, ea2); +// for (ea_t x = ea1; x < ea2; x = next_that(x, ea2, is_code)) +// del_items(x, DELIT_SIMPLE); + } + } + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +static const char *const m7900_help_message = + "AUTOHIDE REGISTRY\n" + "You have loaded a file for the Mitsubishi 7900 family processor.\n\n"\ + "This processor can be used in two different 'length modes' : 8-bit and 16-bit.\n"\ + "IDA allows to specify the encoding mode for every single instruction.\n"\ + "For this, IDA uses two virtual segment registers : \n"\ + " - rDPReg(1), - rDPR0(0), rDPR1(0), rDPR2(0), rDPR3(0) \n"\ + " - rDT(0), rPG(0), rPC(0), rPS(0) \n"\ + " - fM, used to specify the data length;(0)\n"\ + " - fX, used to specify the index register length.(0)\n\n"\ + "Switching their state from 0 to 1 will switch the disassembly from 16-bit to 8-bit.\n"\ + "You can change their value using the 'change segment register value' command"\ + "(the canonical hotkey is Alt-G).\n\n"\ + "Note : in the real design, those registers are represented as flags in the\n"\ + "processor status register.\n"; + + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(m7900_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi m7900_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + + case processor_t::ev_init: + hook_event_listener(HT_IDB, &idb_listener, &LPH); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_newfile: + if ( choose_device() ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + + // Set the default segment register values : + // -1 (badsel) for DR + // 0 for fM and fX + for ( segment_t *s=get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) + { + set_default_sreg_value(s, rDPR0, 0x0); + set_default_sreg_value(s, rDPR1, 0x0); + set_default_sreg_value(s, rDPR2, 0x0); + set_default_sreg_value(s, rDPR3, 0x0); + set_default_sreg_value(s, rDT, 0x0); + set_default_sreg_value(s, rPG, 0x0); + set_default_sreg_value(s, rPC, 0xFFFE); + set_default_sreg_value(s, rPS, 0x0FFF); + + set_default_sreg_value(s, rfI, 1); + set_default_sreg_value(s, rfD, 0); + set_default_sreg_value(s, rfX, 0); + set_default_sreg_value(s, rfM, 0); + set_default_sreg_value(s, rfIPL, 0); + + set_default_sreg_value(s, rDPReg, 1); + } + info(m7900_help_message); + break; + + case processor_t::ev_term: + unhook_event_listener(HT_IDB, &idb_listener); + clr_module_data(data_id); + break; + + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: // new segment + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m7900_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + m7900_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + m7900_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_M7900, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_BINMEM // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + | PR_SEGS // has segment registers? + | PR_SGROTHER, // the segment registers don't contain + // the segment selectors, something else + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rDT, + Rds, + 0, // size of a segment register + Rcs,Rds, + + NULL, // No known code start sequences + retcodes, + + 0, + m7900_last, + Instructions, // instruc + 3, // int tbyte_size; -- doesn't exist + + { 0, 0, 0, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + m7900_rts, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/makefile b/idasdk76/module/makefile similarity index 100% rename from idasdk75/module/makefile rename to idasdk76/module/makefile diff --git a/idasdk76/module/mc68xx/notify_codes.hpp b/idasdk76/module/mc68xx/notify_codes.hpp new file mode 100644 index 0000000..48a4960 --- /dev/null +++ b/idasdk76/module/mc68xx/notify_codes.hpp @@ -0,0 +1,34 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __MC68XX_NOTIFY_CODES_HPP +#define __MC68XX_NOTIFY_CODES_HPP + +#include <idp.hpp> + +//---------------------------------------------------------------------- +// The following events are supported by the MC68XX module in the ph.notify() function +namespace mc68xx_module_t +{ + enum event_codes_t + { + ev_notify_flex_format = processor_t::ev_loader, + // tell the module that the file has FLEX format + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline void notify_flex_format() + { + processor_t::notify(idp_ev(ev_notify_flex_format)); + } +} + +#endif // __MC68XX_NOTIFY_CODES_HPP diff --git a/idasdk76/module/mn102/ana.cpp b/idasdk76/module/mn102/ana.cpp new file mode 100644 index 0000000..94cef90 --- /dev/null +++ b/idasdk76/module/mn102/ana.cpp @@ -0,0 +1,1128 @@ +/* + * Panasonic MN102 (PanaXSeries) processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "pan.hpp" + +//--------------------------------------------------------------------------- +// internal use only +static uint32 LoadData(insn_t &insn, int bytes) +{ + uint32 dt = 0; + // load data + for ( int i=0; i < bytes; i++ ) + { + uint32 nb = insn.get_next_byte(); + dt |= nb << (8*i); + } + return dt; +} + +//--------------------------------------------------------------------------- +// load a label's address +static void SetLabel(insn_t &insn, op_t &op, int bytes) +{ + uint32 off; + op.type = o_near; + // load the data + off = LoadData(insn, bytes); + // sign extend + switch ( bytes ) + { + // 1 byte + case 1: + if ( off&0x000080L ) + off |= ~0x00007FL; + break; + + // 2 bytes + case 2: + if ( off&0x008000L ) + off |= ~0x007FFFL; + break; + + // 3 bytes + case 3: + if ( off&0x800000L ) + off |= ~0x7FFFFFL; + break; + } +// sprintf(cc,"%lx",off); +// msg(cc); + op.addr = op.value = (off+(uint32)insn.size+insn.ea) & 0xFFFFFFL; +// sprintf(cc,"==%lx",op.value); +// msg(cc); +// sprintf(cc,"==%lx",insn.ea); +// msg(cc); +// msg("\n"); +} + +//--------------------------------------------------------------------------- +// set immediate operand, only numbers +static void SetImm(insn_t &insn, op_t &op, int bytes) +{ + op.type = o_imm; // immediate + op.dtype = dt_dword; + op.addr = op.value = LoadData(insn, bytes); // number value +} + +//--------------------------------------------------------------------------- +static void SetImmC(op_t &op, int Val) +{ + op.type = o_imm; // immediate + op.dtype = dt_dword; + op.flags |= OF_NUMBER; // number only + op.addr = op.value = Val; // value +} + +//--------------------------------------------------------------------------- +// registe addressing +static void SetReg(op_t &op,uchar Reg) +{ + op.type = o_reg; + op.reg = Reg; + op.addr = op.value = 0; +} + +//--------------------------------------------------------------------------- +// indirect addressing +static void SetRReg(op_t &op,uchar Reg) +{ + op.type = o_reg; + op.reg = Reg|0x80; // indirect + op.addr = op.value = 0; +} + +//--------------------------------------------------------------------------- +// indirect addressing with a displacement +static void SetDisplI(op_t &op,uchar Reg, uchar RegI) +{ + op.type = o_reg; + op.reg = (Reg&0x0F)|0x90|((RegI&3)<<5); + op.addr = op.value = 0; +} + +//--------------------------------------------------------------------------- +// indirect addressing with a displacement +static void SetDispl(insn_t &insn, op_t &op,uchar Reg, int OffSize) +{ + op.type = o_displ; + op.dtype = dt_dword; + op.reg = Reg; + op.addr = op.value = LoadData(insn, OffSize); +} + +//--------------------------------------------------------------------------- +// memory addressing +static void SetMem(insn_t &insn, op_t &op, int AddrSize, uchar DataSize) +{ + op.type = o_mem; + op.addr = op.value = LoadData(insn, AddrSize); + op.dtype = DataSize; +} + +//--------------------------------------------------------------------------- +// analyzer +int idaapi mn102_ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + uchar R1, R2; + // read first byte + uchar code = insn.get_next_byte(); + // analyze high bits + R1 = code&3; + R2 = (code>>2)&3; + insn.Op1.specflag1 = 0; + insn.Op2.specflag1 = 0; + switch ( code>>4 ) + { + // mov Dm, (An) + case 0x00: + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rD0); + SetRReg(insn.Op2,R2+rA0); + break; + + // movb Dm, (An) + case 0x01: + insn.itype = mn102_movb; + SetReg(insn.Op1,R1+rD0); + SetRReg(insn.Op2,R2+rA0); + break; + + // mov (An), Dm + case 0x02: + insn.itype = mn102_mov; + SetReg(insn.Op2,R1+rD0); + SetRReg(insn.Op1,R2+rA0); + break; + + // movbu (An), Dm + case 0x03: + insn.itype = mn102_movbu; + SetReg(insn.Op2,R1+rD0); + SetRReg(insn.Op1,R2+rA0); + break; + + // mov Dm, (d8,An) + case 0x04: + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rD0); + SetDispl(insn, insn.Op2,R2+rA0,1); + break; + + // mov An, (d8,An); + case 0x05: + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rA0); + SetDispl(insn, insn.Op2,R2+rA0,1); + break; + + // mov (d8,An), Dm + case 0x06: + insn.itype = mn102_mov; + SetReg(insn.Op2,R1+rD0); + SetDispl(insn, insn.Op1,R2+rA0,1); + break; + + // mov (d8,An), Am + case 0x07: + insn.itype = mn102_mov; + SetReg(insn.Op2,R1+rA0); + SetDispl(insn, insn.Op1,R2+rA0,1); + break; + + // mov Dn, Dm or mov imm8,Dn + case 0x08: + insn.itype = mn102_mov; + if ( (code&3) == ((code>>2)&3) ) + { + // mov imm, Dn + SetImm(insn, insn.Op1,1); + SetReg(insn.Op2,R1+rD0); + } + else + { + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + } + break; + + // add Dn, Dm + case 0x09: + insn.itype = mn102_add; + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + break; + + // Sub Dn,Dm + case 0x0A: + insn.itype = mn102_sub; + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + break; + + // Extx* Dn + case 0x0B: + switch ( code&0xC ) + { + // extx + case 0x00: + insn.itype = mn102_extx; + break; + case 0x04: + insn.itype = mn102_extxu; + break; + case 0x08: + insn.itype = mn102_extxb; + break; + case 0x0C: + insn.itype = mn102_extxbu; + break; + } + SetReg(insn.Op1,R1+rD0); + break; + + // mov* Dn, (mem) + case 0x0C: + switch ( code&0xC ) + { + // mov Dn, (abs) + case 0x00: + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rD0); + SetMem(insn, insn.Op2, 2, dt_word); + break; + + // movb Dn, (abs) + case 0x04: + insn.itype = mn102_movb; + SetReg(insn.Op1,R1+rD0); + SetMem(insn, insn.Op2, 2, dt_byte); + break; + + // mov (abs), Dn + case 0x08: + insn.itype = mn102_mov; + SetReg(insn.Op2,R1+rD0); + SetMem(insn, insn.Op1, 2, dt_word); + break; + + // movbu (abs), Dn + case 0x0C: + insn.itype = mn102_movbu; + SetReg(insn.Op2,R1+rD0); + SetMem(insn, insn.Op1, 2, dt_byte); + break; + } + break; + // add/cmp,mov + case 0x0D: + switch ( code&0xC ) + { + // add imm8, An + case 0x00: + SetReg(insn.Op2,R1+rA0); + insn.itype = mn102_add; + SetImm(insn, insn.Op1, 1); + break; + + // add imm8, Dn + case 0x04: + SetReg(insn.Op2,R1+rD0); + insn.itype = mn102_add; + SetImm(insn, insn.Op1, 1); + break; + + // cmp imm8, Dn + case 0x08: + SetReg(insn.Op2,R1+rD0); + insn.itype = mn102_cmp; + SetImm(insn, insn.Op1, 1); + break; + + // mov imm16, An + case 0x0c: + SetReg(insn.Op2,R1+rA0); + insn.itype = mn102_mov; + SetImm(insn, insn.Op1, 2); + insn.Op1.specflag1 = URB_ADDR; + break; + } + break; + + // Jmps + case 0x0E: + { + static const uchar Cmd[16] = + { + mn102_blt,mn102_bgt,mn102_bge,mn102_ble, + mn102_bcs,mn102_bhi,mn102_bcc,mn102_bls, + mn102_beq,mn102_bne,mn102_bra,mn102_rti, + mn102_cmp,mn102_cmp,mn102_cmp,mn102_cmp + }; + insn.itype = Cmd[code&0xF]; + switch ( insn.itype ) + { + // rti + case mn102_rti: + break; + // cmp imm16, An + case mn102_cmp: + SetReg(insn.Op2,R1+rA0); + SetImm(insn, insn.Op1, 2); + break; + // jmps + default: + SetLabel(insn, insn.Op1,1); + break; + } + break; + } + // ExtCodes + case 0x0F: + switch ( code & 0xF ) + { + // F0 set + case 0x00: + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + switch ( code&0xC0 ) + { + // complex set + case 0x00: + switch ( code&0x30 ) + { + // one more set + case 0x00: + if ( code & 2 ) + return 0; + SetRReg(insn.Op1,R2+rA0); + if ( code & 1 ) + insn.itype = mn102_jsr; + else + insn.itype = mn102_jmp; + break; + case 0x10: + return 0; + case 0x20: + insn.itype = mn102_bset; + SetReg(insn.Op1,R1+rD0); + SetRReg(insn.Op2,R2+rA0); + break; + case 0x30: + insn.itype = mn102_bclr; + SetReg(insn.Op1,R1+rD0); + SetRReg(insn.Op2,R2+rA0); + break; + } + break; + + // movb (Di,An), Dm + case 0x40: + insn.itype = mn102_movb; + SetReg(insn.Op2,R1+rD0); + SetDisplI(insn.Op1,R2+rA0,code>>4); + break; + // movbu (Di,An), Dm + case 0x80: + insn.itype = mn102_movbu; + SetReg(insn.Op2,R1+rD0); + SetDisplI(insn.Op1,R2+rA0,code>>4); + break; + // movb Dm, (Di, An) + case 0xC0: + insn.itype = mn102_movb; + SetReg(insn.Op1,R1+rD0); + SetDisplI(insn.Op2,R2+rA0,code>>4); + break; + } + break; + // F1 set + case 0x01: + insn.itype = mn102_mov; + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + switch ( code&0xC0 ) + { + // mov (Di, An), Am + case 0x00: + SetReg(insn.Op2,R1+rA0); + SetDisplI(insn.Op1,R2+rA0, code>>4); + break; + + // mov (Di,An), Dm + case 0x40: + SetReg(insn.Op2,R1+rD0); + SetDisplI(insn.Op1,R2+rA0, code>>4); + break; + + // mov Am, (Di, An) + case 0x80: + SetReg(insn.Op1,R1+rD0); + SetDisplI(insn.Op2,R2+rA0, code>>4); + break; + + // mov Dm, (Di, An); + case 0xC0: + SetReg(insn.Op1,R1+rD0); + SetDisplI(insn.Op2,R2+rA0, code>>4); + break; + } + break; + // F2 set + case 0x02: + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + { + static const uchar Cmd[16] = + { + mn102_add, mn102_sub, mn102_cmp, mn102_mov, + mn102_add, mn102_sub, mn102_cmp, mn102_mov, + mn102_addc, mn102_subc, 0, 0, + mn102_add, mn102_sub, mn102_cmp, mn102_mov + }; + insn.itype = Cmd[code>>4]; + if ( insn.itype == 0 ) + return 0; + switch ( code&0xC0 ) + { + case 0x00: + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rA0); + break; + + case 0x40: + SetReg(insn.Op1,R2+rA0); + SetReg(insn.Op2,R1+rA0); + break; + + case 0x80: + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + break; + + case 0xC0: + SetReg(insn.Op1,R2+rA0); + SetReg(insn.Op2,R1+rD0); + break; + } + } + break; + // F3 set + case 0x03: + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + { + static const uchar Cmd[16] = + { + mn102_and, mn102_or, mn102_xor, mn102_rol, + mn102_mul, mn102_mulu, mn102_divu, 0, + 0, mn102_cmp, 0, 0, + mn102_ext, mn102_mov, mn102_not, 255 + }; + insn.itype = Cmd[code>>4]; + switch ( insn.itype ) + { + // bad opcode + case 0: + return 0; + // shifts + case mn102_rol: + SetReg(insn.Op1,R1+rD0); + insn.Op2.type = o_void; + { + static const uchar Cmd2[4] = + { + mn102_rol,mn102_ror,mn102_asr,mn102_lsr + }; + insn.itype = Cmd2[(code>>2)&3]; + } + break; + case mn102_ext: + if ( code & 2 ) + return 0; + if ( code & 1 ) + { + insn.Op2.type = o_void; + } + else + { + insn.itype = mn102_mov; + SetReg(insn.Op2,rMDR); + } + break; + + case mn102_mov: + if ( R1 != 0 ) + return 0; + SetReg(insn.Op2,rPSW); + break; + + case mn102_not: + switch ( R2 ) + { + case 0: + insn.itype = mn102_mov; + SetReg(insn.Op1,rMDR); + break; + case 1: + insn.Op2.type = o_void; + SetReg(insn.Op1,R1+rD0); + break; + default: + return 0; + } + break; + + case 255: + switch ( R2 ) + { + case 0: + insn.itype = mn102_mov; + SetReg(insn.Op1,rPSW); + break; + case 3: + insn.Op2.type = insn.Op1.type = o_void; + switch ( R1 ) + { + case 0: + insn.itype = mn102_pxst; + break; + // F3, FE + case 2: + { + static const uchar lCmd[4] = + { + mn102_tbz, mn102_tbnz, mn102_bset, mn102_bclr + }; + code = insn.get_next_byte(); + if ( code < 0xC0 || code >= 0xE0 ) + return 0; + insn.itype = lCmd[(code>>3)&3]; + SetImmC(insn.Op1,1<<(code&7)); + SetMem(insn, insn.Op2, 3, dt_byte); + // if jump, use label + if ( (code&0xF0) == 0xC0 ) + SetLabel(insn, insn.Op3, 1); + } + break; + // F3, FF + case 3: + { + static const uchar lCmd[4] = + { + mn102_tbz, mn102_bset, mn102_tbnz, mn102_bclr + }; + code = insn.get_next_byte(); + if ( code < 0x80 || code >= 0xC0 ) + return 0; + insn.itype = lCmd[(code>>4)&3]; + SetImmC(insn.Op1,1<<(code&7)); + SetDispl(insn, insn.Op2,(code&0x8)?rA3:rA2, 1); + insn.Op3.dtype = dt_byte; + // if jump, use label + if ( (code & 0x10) == 0 ) + SetLabel(insn, insn.Op3, 1); + } + break; + default: + return 0; + } + break; + default: + return 0; + } + break; + // the rest does not need processing + default: + break; + } + } + break; + + // F4 set - 5 bytes + case 0x04: + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + + switch ( code&0xF0 ) + { + // mov Dm, (D24,An) + case 0x00: + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rD0); + SetDispl(insn, insn.Op2,R2+rA0,3); + break; + + case 0x10: + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rA0); + SetDispl(insn, insn.Op2,R2+rA0,3); + break; + + case 0x20: + insn.itype = mn102_movb; + SetReg(insn.Op1,R1+rD0); + SetDispl(insn, insn.Op2,R2+rA0,3); + break; + + case 0x30: + insn.itype = mn102_movx; + SetReg(insn.Op1,R1+rD0); + SetDispl(insn, insn.Op2,R2+rA0,3); + break; + + case 0x40: + switch ( R2 ) + { + case 0: + insn.itype = mn102_mov; + SetMem(insn, insn.Op2,3,dt_dword); + SetReg(insn.Op1,R1+rD0); + break; + + case 1: + insn.itype = mn102_movb; + SetMem(insn, insn.Op2,3,dt_byte); + SetReg(insn.Op1,R1+rD0); + break; + + default: + if ( code != 0x4B && code != 0x4F ) + return 0; + insn.itype = code == 0x4B ? mn102_bset : mn102_bclr; + SetMem(insn, insn.Op2,3,dt_byte); + SetImm(insn, insn.Op1,1); + break; + } + break; + + case 0x50: + if ( R2 != 0 ) + return 0; + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rA0); + SetMem(insn, insn.Op1,3,dt_tbyte); + break; + + case 0x60: + SetImm(insn, insn.Op1,3); + SetReg(insn.Op2, R1+((R2&1)?rA0:rD0)); + insn.itype = (R2&2)?mn102_sub:mn102_add; + break; + + case 0x70: + SetImm(insn, insn.Op1,3); + insn.Op1.specflag1 = URB_ADDR; + SetReg(insn.Op2,R1+((R2&1)?rA0:rD0)); + insn.itype = (R2&2)?mn102_cmp:mn102_mov; + break; + + case 0x80: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op1,R2+rA0,3); + SetReg(insn.Op2,R1+rD0); + break; + + case 0x90: + insn.itype = mn102_movbu; + SetDispl(insn, insn.Op1,R2+rA0,3); + SetReg(insn.Op2,R1+rD0); + break; + + case 0xA0: + insn.itype = mn102_movb; + SetDispl(insn, insn.Op1,R2+rA0,3); + SetReg(insn.Op2,R1+rD0); + break; + + case 0xB0: + insn.itype = mn102_movx; + SetDispl(insn, insn.Op1,R2+rA0,3); + SetReg(insn.Op2,R1+rD0); + break; + + case 0xC0: + SetReg(insn.Op2,R1+rD0); + switch ( R2 ) + { + case 0: + insn.itype = mn102_mov; + SetMem(insn, insn.Op1,3,dt_word); + break; + + case 1: + insn.itype = mn102_movb; + SetMem(insn, insn.Op1,3,dt_byte); + break; + + case 2: + insn.itype = mn102_movbu; + SetMem(insn, insn.Op1,3,dt_byte); + break; + + default: + return 0; + } + break; + + case 0xD0: + if ( R2 != 0 ) + return 0; + insn.itype = mn102_mov; + SetMem(insn, insn.Op1,3,dt_tbyte); + SetReg(insn.Op2,R1+rA0); + break; + + case 0xE0: + switch ( code ) + { + case 0xE0: + insn.itype = mn102_jmp; + SetLabel(insn, insn.Op1,3); + break; + + case 0xE1: + insn.itype = mn102_jsr; + SetLabel(insn, insn.Op1,3); + break; + + case 0xE3: + case 0xE7: + insn.itype = (code == 0xE3) ? mn102_bset : mn102_bclr; + SetMem(insn, insn.Op2,2,dt_byte); + SetImmC(insn.Op1,1); + break; + + default: + if ( code < 0xE8 ) + return 0; + insn.itype = (code&0x4)?mn102_bclr:mn102_bset; + SetImmC(insn.Op1,1); + SetDispl(insn, insn.Op2,rA0+(code&3),1); + break; + } + break; + + case 0xF0: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op1,R2+rA0,3); + SetReg(insn.Op2,R1+rA0); + break; + } + break; + // F5 set + case 0x05: + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + switch ( code&0xF0 ) + { + case 0x00: + { + static const uchar Cmd[4] = + { + mn102_and, mn102_btst, mn102_or, mn102_addnf + }; + SetImm(insn, insn.Op1,1); + SetReg(insn.Op2,R1+rD0); + insn.itype = Cmd[R2]; + } + break; + // movb Dm,(d8,An) + case 0x10: + insn.itype = mn102_movb; + SetReg(insn.Op1,R1+rD0); + SetDispl(insn, insn.Op2,R2+rA0,1); + break; + + // movb (d8,An), Dm + case 0x20: + insn.itype = mn102_movb; + SetReg(insn.Op2,R1+rD0); + SetDispl(insn, insn.Op1,R2+rA0,1); + break; + + // movbu (d8,An), Dm + case 0x30: + insn.itype = mn102_movbu; + SetReg(insn.Op2,R1+rD0); + SetDispl(insn, insn.Op1,R2+rA0,1); + break; + + // mulql dn, dm + case 0x40: + code = insn.get_next_byte(); + if ( code > 1 ) + return 0; + insn.itype = (code == 0) ? mn102_mulql : mn102_mulqh; + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + break; + + // movx Dm, (d8,An) + case 0x50: + insn.itype = mn102_movx; + SetReg(insn.Op1,R1+rD0); + SetDispl(insn, insn.Op2,R2+rA0,1); + break; + + // mulq dn, dm + case 0x60: + code = insn.get_next_byte(); + if ( code != 0x10 ) + return 0; + insn.itype = mn102_mulq; + SetReg(insn.Op1,R2+rD0); + SetReg(insn.Op2,R1+rD0); + break; + + // movx (d8,An), Dm + case 0x70: + insn.itype = mn102_movx; + SetDispl(insn, insn.Op1,R2+rA0,1); + SetReg(insn.Op2,R1+rD0); + break; + + case 0x80: + case 0x90: + case 0xA0: + case 0xB0: + { + static const uchar Cmd[4] = + { + mn102_tbz, mn102_bset, mn102_tbnz, mn102_bclr + }; + insn.itype = Cmd[(code>>4)&3]; + SetImmC(insn.Op1,1<<(code&7)); + SetDispl(insn, insn.Op2,(code&0x8)?rA1:rA0,1); + if ( (code & 0x10) == 0 ) + SetLabel(insn, insn.Op3, 1); + } + break; + case 0xC0: + case 0xD0: + { + static const uchar Cmd[4] = + { + mn102_tbz, mn102_tbnz, mn102_bset, mn102_bclr + }; + insn.itype = Cmd[(code>>3)&3]; + SetImmC(insn.Op1,1<<(code&7)); + SetMem(insn, insn.Op2,2,dt_byte); + if ( (code & 0x10) == 0 ) + SetLabel(insn, insn.Op3, 1); + } + break; + + case 0xE0: + { + static const uchar Cmd[16] = + { + mn102_bltx,mn102_bgtx,mn102_bgex,mn102_blex, + mn102_bcsx,mn102_bhix,mn102_bccx,mn102_blsx, + mn102_beqx,mn102_bnex,0,0, + mn102_bvcx,mn102_bvsx,mn102_bncx,mn102_bnsx + }; + insn.itype = Cmd[code&0xF]; + if ( insn.itype == 0 ) + return 0; + SetLabel(insn, insn.Op1,1); + } + break; + case 0xF0: + if ( code < 0xFC && code > 0xF8 ) + return 0; + if ( code >= 0xFC ) + { + static const uchar Cmd[4] = + { + mn102_bvc, mn102_bvs, mn102_bnc, mn102_bns + }; + insn.itype = Cmd[R1]; + SetLabel(insn, insn.Op1, 1); + } + else + { + code = insn.get_next_byte(); + switch ( code ) + { + case 0x4: + insn.itype = mn102_mulql; + SetImm(insn, insn.Op1,1); + SetReg(insn.Op2,R1+rD0); + break; + case 0x5: + insn.itype = mn102_mulqh; + SetImm(insn, insn.Op1,1); + SetReg(insn.Op2,R1+rD0); + break; + case 0x8: + insn.itype = mn102_mulql; + SetImm(insn, insn.Op1,2); + SetReg(insn.Op2,R1+rD0); + break; + case 0x9: + insn.itype = mn102_mulqh; + SetImm(insn, insn.Op1,2); + SetReg(insn.Op2,R1+rD0); + break; + default: + return 0; + } + } + break; + default: + return 0; + } + break; + + // NOP + case 0x06: + insn.itype = mn102_nop; + break; + + // F7 set + case 0x07: + code = insn.get_next_byte(); + R1 = (code&3); + R2 = (code>>2)&3; + switch ( code&0xF0 ) + { + case 0x00: + { + static const uchar Cmd[4] = + { + mn102_and, mn102_btst, mn102_add, mn102_sub + }; + + SetImm(insn, insn.Op1,2); + SetReg(insn.Op2,R1+((R2&2)?rA0:rD0)); + insn.itype = Cmd[R2]; + } + break; + + case 0x10: + switch ( R2 ) + { + case 0: + if ( R1 != 0 ) + return 0; + insn.itype = mn102_and; + SetReg(insn.Op2,rPSW); + break; + + case 1: + if ( R1 != 0 ) + return 0; + insn.itype = mn102_or; + SetReg(insn.Op2,rPSW); + break; + + case 2: + insn.itype = mn102_add; + SetReg(insn.Op2,R1+rD0); + break; + + case 3: + insn.itype = mn102_sub; + SetReg(insn.Op2,R1+rD0); + break; + } + SetImm(insn, insn.Op1,2); + break; + + case 0x20: + if ( R2 != 0 ) + return 0; + insn.itype = mn102_mov; + SetReg(insn.Op1,R1+rA0); + SetMem(insn, insn.Op2,2,dt_tbyte); + break; + + case 0x30: + if ( R2 != 0 ) + return 0; + insn.itype = mn102_mov; + SetReg(insn.Op2,R1+rA0); + SetMem(insn, insn.Op1,2,dt_tbyte); + break; + + case 0x40: + { + static const uchar Cmd[4] = + { + mn102_or, 0, mn102_cmp, mn102_xor + }; + insn.itype = Cmd[R2]; + if ( insn.itype == 0 ) + return 0; + SetImm(insn, insn.Op1,2); + SetReg(insn.Op2,R1+rD0); + } + break; + + case 0x50: + insn.itype = mn102_movbu; + SetDispl(insn, insn.Op1,R2+rA0,2); + SetReg(insn.Op2,R1+rD0); + break; + + case 0x60: + insn.itype = mn102_movx; + SetDispl(insn, insn.Op2,R2+rA0,2); + SetReg(insn.Op1,R1+rD0); + break; + + case 0x70: + insn.itype = mn102_movx; + SetDispl(insn, insn.Op1,R2+rA0,2); + SetReg(insn.Op2,R1+rD0); + break; + + case 0x80: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op2,R2+rA0,2); + SetReg(insn.Op1,R1+rD0); + break; + + case 0x90: + insn.itype = mn102_movb; + SetDispl(insn, insn.Op2,R2+rA0,2); + SetReg(insn.Op1,R1+rD0); + break; + + case 0xA0: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op2,R2+rA0,2); + SetReg(insn.Op1,R1+rA0); + break; + + case 0xB0: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op1,R2+rA0,2); + SetReg(insn.Op2,R1+rA0); + break; + + case 0xC0: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op1,R2+rA0,2); + SetReg(insn.Op2,R1+rD0); + break; + + case 0xD0: + insn.itype = mn102_mov; + SetDispl(insn, insn.Op1,R2+rA0,2); + SetReg(insn.Op2,R1+rD0); + break; + + default: + return 0; + } + break; + + // mov imm16, Dn + case 0x08: + case 0x09: + case 0x0A: + case 0x0B: + SetReg(insn.Op2,R1+rD0); + SetImm(insn, insn.Op1, 2); + insn.itype = mn102_mov; + break; + + // jmp label16 + case 0x0C: + insn.itype = mn102_jmp; + SetLabel(insn, insn.Op1,2); + break; + + // jsr label16 + case 0x0D: + insn.itype = mn102_jsr; + SetLabel(insn, insn.Op1,2); + break; + + // rts + case 0x0E: + insn.itype = mn102_rts; + break; + + // illegal code + case 0x0F: + return 0; + } + break; + } + return insn.size; +} diff --git a/idasdk75/module/mn102/emu.cpp b/idasdk76/module/mn102/emu.cpp similarity index 100% rename from idasdk75/module/mn102/emu.cpp rename to idasdk76/module/mn102/emu.cpp diff --git a/idasdk75/module/mn102/ins.cpp b/idasdk76/module/mn102/ins.cpp similarity index 100% rename from idasdk75/module/mn102/ins.cpp rename to idasdk76/module/mn102/ins.cpp diff --git a/idasdk75/module/mn102/ins.hpp b/idasdk76/module/mn102/ins.hpp similarity index 100% rename from idasdk75/module/mn102/ins.hpp rename to idasdk76/module/mn102/ins.hpp diff --git a/idasdk76/module/mn102/makefile b/idasdk76/module/mn102/makefile new file mode 100644 index 0000000..d11f1d2 --- /dev/null +++ b/idasdk76/module/mn102/makefile @@ -0,0 +1,57 @@ +PROC=mn102l00 +CONFIGS=mn102l00.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp pan.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp ins.hpp pan.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp pan.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp out.cpp pan.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp pan.hpp reg.cpp diff --git a/idasdk75/module/mn102/mn102l00.cfg b/idasdk76/module/mn102/mn102l00.cfg similarity index 100% rename from idasdk75/module/mn102/mn102l00.cfg rename to idasdk76/module/mn102/mn102l00.cfg diff --git a/idasdk76/module/mn102/out.cpp b/idasdk76/module/mn102/out.cpp new file mode 100644 index 0000000..be15d4b --- /dev/null +++ b/idasdk76/module/mn102/out.cpp @@ -0,0 +1,198 @@ +/* + * Panasonic MN102 (PanaXSeries) processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "pan.hpp" + +//---------------------------------------------------------------------- +class out_mn102_t : public outctx_t +{ + out_mn102_t(void) = delete; // not used +public: + void OutVarName(const op_t &x); + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_mn102_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_mn102_t) + +//---------------------------------------------------------------------- +void out_mn102_t::OutVarName(const op_t &x) +{ + ea_t toea = map_code_ea(insn, x); + if ( !out_name_expr(x, toea, x.addr) ) + { + out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_32); + remember_problem(PR_NONAME, insn.ea); + } +} + +//---------------------------------------------------------------------- +// print one operand +bool out_mn102_t::out_operand(const op_t & x) +{ + switch ( x.type ) + { + // memory reference with a regsiter + // (disp,Ri) + case o_displ: + out_symbol('('); + out_value(x); + out_symbol(','); + out_register(ph.reg_names[x.reg]); + out_symbol(')'); + break; + + // register + case o_reg: + if ( x.reg&0x80 ) + out_symbol('('); + if ( x.reg&0x10 ) + { + out_register(ph.reg_names[((x.reg>>5)&3)+rD0]); + out_symbol(','); + } + out_register(ph.reg_names[x.reg&0x0F]); + if ( x.reg&0x80 ) + out_symbol(')'); + break; + + // immediate operand + case o_imm: + refinfo_t ri; + // micro bug-fix + if ( get_refinfo(&ri, insn.ea, x.n) ) + { + if ( ri.flags == REF_OFF16 ) + set_refinfo(insn.ea, x.n, REF_OFF32, ri.target, ri.base, ri.tdelta); + } + out_value(x, /*OOFS_NOSIGN | */ OOF_SIGNED | OOFW_IMM); + break; + + // code reference + case o_near: + OutVarName(x); + break; + + // direct memory reference + case o_mem: + out_symbol('('); + OutVarName(x); + out_symbol(')'); + break; + + // nothing for void + case o_void: + return 0; + + // unknown operand + default: + warning("out: %a: bad optype %d",insn.ea,x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +// main instruction printer +void out_mn102_t::out_insn(void) +{ + // print mnemonic + out_mnemonic(); + + // print first operands + if ( insn.Op1.type != o_void ) + out_one_operand(0); + + // second operand + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + // third operand + if ( insn.Op3.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(2); + } + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +// listing header +void mn102_t::mn102_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX, ioh.device.c_str(), ioh.deviceparams.c_str()); +} + +//-------------------------------------------------------------------------- +// segment header +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Sarea) could be made const +void mn102_t::mn102_segstart(outctx_t &ctx, segment_t *Sarea) const +{ + ea_t ea = ctx.insn_ea; + const char *SegType = Sarea->type == SEG_CODE ? "CSEG" + : Sarea->type == SEG_DATA ? "DSEG" + : "RSEG"; + // print RSEG <NAME> + qstring sn; + get_visible_segm_name(&sn, Sarea); + ctx.gen_printf(-1, "%s %s ", SegType, sn.c_str()); + // if org is not zero, print it + if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) + { + ea_t org = ea - get_segm_base(Sarea); + if ( org != 0 ) + { + char bufn[MAX_NUMBUF]; + btoa(bufn, sizeof(bufn), org); + ctx.gen_printf(-1, "%s %s", ash.origin, bufn); + } + } +} + +//-------------------------------------------------------------------------- +// end of listing +void mn102_t::mn102_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + size_t i = strlen(ash.end); + do + ctx.out_char(' '); + while ( ++i < 8 ); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} + +//-------------------------------------------------------------------------- +void idaapi mn102_data(outctx_t &ctx, bool analyze_only) +{ + ea_t ea = ctx.insn_ea; + // micro bug-fix + refinfo_t ri; + if ( get_refinfo(&ri, ea, 0) && ri.flags == REF_OFF16 ) + set_refinfo(ea, 0, REF_OFF32, ri.target, ri.base, ri.tdelta); + + ctx.out_data(analyze_only); +} diff --git a/idasdk76/module/mn102/pan.hpp b/idasdk76/module/mn102/pan.hpp new file mode 100644 index 0000000..2db1678 --- /dev/null +++ b/idasdk76/module/mn102/pan.hpp @@ -0,0 +1,65 @@ +/* + * Panasonic MN102 (PanaXSeries) processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#ifndef _PAN_HPP +#define _PAN_HPP + +#include <ida.hpp> +#include <idp.hpp> + +#include "../idaidp.hpp" +#include "ins.hpp" +#include "../iohandler.hpp" + +//----------------------------------------------- +// additional bits (specflag1) +#define URB_ADDR 0x1 // immediate operand is an address + +//------------------------------------------------------------------------ +#ifdef _MSC_VER +#define ENUM8BIT : uint8 +#else +#define ENUM8BIT +#endif +// list of processor registers +enum mn102_registers ENUM8BIT +{ + rNULLReg, + rD0, rD1, rD2, rD3, + rA0, rA1, rA2, rA3, + rMDR,rPSW, rPC, + rVcs, rVds +}; + +//------------------------------------------------------------------------ +int idaapi mn102_ana(insn_t *_insn); + +void idaapi mn102_data(outctx_t &ctx, bool analyze_only); + +//------------------------------------------------------------------------ +struct mn102_t : public procmod_t +{ + netnode helper; + iohandler_t ioh = iohandler_t(helper); + bool flow = false; // code flow continues flag + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + int mn102_emu(const insn_t &insn); + + void mn102_header(outctx_t &ctx); + void mn102_segstart(outctx_t &ctx, segment_t *Sarea) const; + void mn102_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ MN102" +#define PROCMOD_NAME mn102 + +#endif diff --git a/idasdk76/module/mn102/reg.cpp b/idasdk76/module/mn102/reg.cpp new file mode 100644 index 0000000..b83031e --- /dev/null +++ b/idasdk76/module/mn102/reg.cpp @@ -0,0 +1,251 @@ +/* + * Panasonic MN102 (PanaXSeries) processor module for IDA. + * Copyright (c) 2000-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "pan.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +// register names +static const char *const RegNames[] = +{ + // empty + "", + "D0","D1","D2","D3", + "A0","A1","A2","SP", // SP is alias of A3 + // special + "MDR","PSW","PC", + // pseudo-segment + "cs","ds" +}; + +//---------------------------------------------------------------------- +void mn102_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(mn102_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi mn102_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_be(false); + inf_set_gen_lzero(true); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + mn102_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + mn102_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + mn102_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return mn102_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return mn102_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + mn102_data(*ctx, analyze_only); + return 1; + } + + + default: + break; + } + return code; +} +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const asm_t pseudosam = +{ + AS_COLON | AS_UDATA | ASH_HEXF3 | ASD_DECF0, + 0, + "Generic assembler", // assembeler name + 0, // help topic ID + NULL, // header lines + "org", // org + "end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + "db", // ascii string directive + "DB", // byte directive + "DW", // word directive + "DL", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + "DT", // tbyte (10/12 bytes) + NULL, // packed decimal real + "#d dup(#v)", // arrays (#h,#d,#v,#s(...) + "db ?", // uninited arrays + ".equ", // equ + NULL, // seg prefix + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + NULL, // "public" name keyword + NULL, // "weak" name keyword + NULL, // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // const char *(*get_type_name)(int32 flag,uint32 id); + "align", // "align" keyword + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +// list of assemblers +static const asm_t *const asms[] = { &pseudosam, NULL }; +//----------------------------------------------------------------------- +#define FAMILY "Panasonic MN10200:" +static const char *const shnames[] = { "MN102L00", NULL }; +static const char *const lnames[] = { FAMILY"Panasonic MN102L00", NULL }; + +//-------------------------------------------------------------------------- +// codes of subroutine returns +static const uchar retcode_1[] = { 0xFE }; // ret +static const uchar retcode_2[] = { 0xEB }; // reti +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_MN102L00, // id + // flag + PR_USE32 + | PR_BINMEM + | PR_SEGTRANS + | PR_DEFSEG32, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 2, // size of a segment register + rVcs,rVds, + NULL, // typical code starts + retcodes, // returns + 0,mn102_last, // first, last itype + Instructions, // instruction array + 3, // tbyte size: 24 bits + {0,0,0,0}, // floating point type sizes + 0, // Icode for return + NULL, // micro virtual mashine +}; diff --git a/idasdk75/module/module.mak b/idasdk76/module/module.mak similarity index 100% rename from idasdk75/module/module.mak rename to idasdk76/module/module.mak diff --git a/idasdk76/module/nec850/ana.cpp b/idasdk76/module/nec850/ana.cpp new file mode 100644 index 0000000..0dcb8c3 --- /dev/null +++ b/idasdk76/module/nec850/ana.cpp @@ -0,0 +1,2065 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) Hex-Rays + * ALL RIGHTS RESERVED. + * + * Instruction decoder + * + */ +#include "ins.hpp" + +static const int bcond_map[16] = +{ + NEC850_BV, NEC850_BL, + NEC850_BZ, NEC850_BNH, + NEC850_BN, NEC850_BR, + NEC850_BLT, NEC850_BLE, + NEC850_BNV, NEC850_BNC, + NEC850_BNZ, NEC850_BH, + NEC850_BP, NEC850_BSA, + NEC850_BGE, NEC850_BGT +}; + +//------------------------------------------------------------------------ +// The instruction formats 5 to 10 have bit10 and bit9 on and are a word +// The rest of the instructions are half-word and their format is 1 to 4 +int detect_inst_len(uint16 w) +{ + return ((w & 0x600) == 0x600) ? 4 : 2; +} + +//------------------------------------------------------------------------ +// Fetchs an instruction (uses ua_next_xxx(insn)) of a correct size (ready for decoding) +// Returns the size of the instruction +int fetch_instruction(uint32 *w, insn_t &insn) +{ + uint16 hw = insn.get_next_word(); + int r = detect_inst_len(hw); + if ( r == 4 ) + *w = (insn.get_next_word() << 16) | hw; + else + *w = hw; + return r; +} + +//------------------------------------------------------------------------ +static sval_t fetch_disp32(const uint32 w, insn_t &ins) +{ + // 15 0 31 16 47 32 + // xxxxxxxxxxxxxxxx ddddddddddddddd0 DDDDDDDDDDDDDDDD + uint32 d_low = (w >> 16);// ddddddddddddddd0 + if ( ins.size == 2 ) + d_low = ins.get_next_word(); + else if ( ins.size != 4 ) + { + // bad format + ins.size = 0; + ins.itype = 0; + return 1; + } + uint16 d_high = ins.get_next_word(); // DDDDDDDDDDDDDDDD + int32 addr = (d_high<<16) | d_low; + return sval_t(addr); +} + +//------------------------------------------------------------------------ +static bool decode_disp23(const uint32 w, insn_t &ins, int opidx, op_dtype_t dt) +{ + // LD.B disp23 [reg1] , reg3 + // 00000111100RRRRR wwwwwddddddd0101 DDDDDDDDDDDDDDDD + // ddddddd is the lower 7 bits of disp23. + // DDDDDDDDDDDDDDDD is the higher 16 bits of disp23 + // LD.H disp23[reg1], reg3 + // 00000111100RRRRR wwwwwdddddd00111 DDDDDDDDDDDDDDDD + // dddddd is the lower side bits 6 to 1 of disp23. + // DDDDDDDDDDDDDDDD is the higher 16 bits of disp23. + + // we need at least 32 bits of opcode here + if ( ins.size != 4 ) + return false; + + uint16 d_low = ( w >> 20 ) & 0x7F; // ddddddd + if ( dt != dt_byte && ( d_low & 1 ) != 0 ) + return false; + uint16 d_high = ins.get_next_word(); // DDDDDDDDDDDDDDDD + sval_t addr = ( d_high << 7 ) | d_low; + SIGN_EXTEND(sval_t, addr, 23); + + op_t &op = ins.ops[opidx]; + op.type = o_displ; + op.reg = w & 0x1F; + op.addr = addr; + op.dtype = dt; + op.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED | N850F_VAL32; + return true; +} + +//------------------------------------------------------------------------ +static void set_opreg(op_t &op, int reg, op_dtype_t dtyp = dt_dword) +{ + op.type = o_reg; + op.dtype = dtyp; + op.reg = reg; +} + +//---------------------------------------------------------------------- +// Create operand of condition type +inline void set_opcond(op_t &x, uval_t value) +{ + x.type = o_cond; + x.dtype = dt_qword; + x.value = value; +} + + +//------------------------------------------------------------------------ +static void set_opimm(op_t &op, uval_t value, int dtyp = dt_dword) +{ + op.type = o_imm; + op.dtype = dtyp; + op.value = value; +} + +//------------------------------------------------------------------------ +// Decodes an instruction "w" into cmd structure +bool nec850_t::decode_coprocessor(const uint32 w, insn_t &ins) const +{ // 11111 1 33222 2 222 22 2111 1 + // 54321 098765 43210 10987 6 543 21 0987 6 + // reg2 |opcode|reg1 |reg3 |b|cat|ty|subo|b| + // ..... |111111|.....|.....|1|...|..|....|0| + int r1 = w & 0x1F; + int r2 = ( w & 0xF800 ) >> 11; + int r3 = ( w & 0xF8000000 ) >> 27; + int cat = ( w >> 23 ) & 7; + int typ = ( w >> 21 ) & 3; + int subop = ( w >> 17 ) & 0xF; + ins.itype = NEC850_NULL; + // we only support V850E2M and RH850 FP instructions + if ( !is_v850e2m() ) + return false; + if ( typ == 0 && cat == 0 ) + { + // CMOVF.D: cat = 000, type = 00, subop = 1fff, reg3 != 0 + // CMOVF.S : cat = 000, type = 00, subop = 0fff, reg3 != 0 + // TRFSR: cat = 000, type = 00, subop = 0fff, reg1 = 0, reg3 = 0 + if ( r3 != 0 ) + { + // CMOVF.S|D fcbit, reg1, reg2, reg3 + ins.itype = ( subop & 8 ) ? NEC850_CMOVF_D : NEC850_CMOVF_S; + int fcbit = subop & 7; + set_opimm(ins.Op1, fcbit); + set_opreg(ins.Op2, r1); + set_opreg(ins.Op3, r2); + set_opreg(ins.Op4, r3); + } + else if ( subop < 8 ) + { + ins.itype = NEC850_TRFSR; + int fcbit = subop & 7; + set_opimm(ins.Op1, fcbit); + } + } + else if ( typ == 1 && cat == 0 && r3 < 0x10 ) + { + // CMPF.D: cat = 000, type = 01, subop = 1fff, reg3 = 0FFFF + // CMPF.S : cat = 000, type = 01, subop = 0fff, reg3 = 0FFFF + // CMPF.S|D fcond, reg2, reg1, fcbit + ins.itype = ( subop & 8 ) ? NEC850_CMPF_D : NEC850_CMPF_S; + int fcbit = subop & 7; + set_opcond(ins.Op1, r3); + set_opreg(ins.Op2, r2); + set_opreg(ins.Op3, r1); + set_opimm(ins.Op4, fcbit); + } + else if ( typ == 3 ) + { + // reg1, reg2, reg3 + if ( cat == 0 ) + { + switch ( subop & 7 ) + { + case 0: + ins.itype = ( subop & 8 ) ? NEC850_ADDF_D : NEC850_ADDF_S; + break; + case 1: + ins.itype = ( subop & 8 ) ? NEC850_SUBF_D : NEC850_SUBF_S; + break; + case 2: + ins.itype = ( subop & 8 ) ? NEC850_MULF_D : NEC850_MULF_S; + break; + case 4: + ins.itype = ( subop & 8 ) ? NEC850_MAXF_D : NEC850_MAXF_S; + break; + case 5: + ins.itype = ( subop & 8 ) ? NEC850_MINF_D : NEC850_MINF_S; + break; + case 7: + ins.itype = ( subop & 8 ) ? NEC850_DIVF_D : NEC850_DIVF_S; + break; + + } + } + else if ( cat == 1 && subop < 4 ) + { + if ( is_rh850() ) + { + uint16 itypes[] = { NEC850_FMAF_S, NEC850_FMSF_S, NEC850_FNMAF_S, NEC850_FNMSF_S }; + ins.itype = itypes[subop]; + } + } + if ( ins.itype != NEC850_NULL ) + { + bool dbl = ( subop & 8 ) != 0; + op_dtype_t dt = dbl ? dt_double : dt_float; + set_opreg(ins.Op1, r1, dt); + set_opreg(ins.Op2, r2, dt); + set_opreg(ins.Op3, r3, dt); + } + } + else if ( typ == 2 && cat == 0 ) + { + // reg2, reg3 conversions + op_dtype_t dtsrc = dt_float, dtdst = dt_float; + switch ( subop ) + { + case 0: + { + // TRNCF.SW cat = 0 type = 2 subop = 0 reg1 = 1 + // CEILF.SW cat = 0 type = 2 subop = 0 reg1 = 2 + // FLOORF.SW cat = 0 type = 2 subop = 0 reg1 = 3 + // CVTF.SW cat = 0 type = 2 subop = 0 reg1 = 4 + // TRNCF.SUW cat = 0 type = 2 subop = 0 reg1 = 17 + // CEILF.SUW cat = 0 type = 2 subop = 0 reg1 = 18 + // FLOORF.SUW cat = 0 type = 2 subop = 0 reg1 = 19 + // CVTF.SUW cat = 0 type = 2 subop = 0 reg1 = 20 + static const int ops[] = + { + NEC850_NULL, NEC850_TRNCF_SW, NEC850_CEILF_SW, NEC850_FLOORF_SW, // 0-3 + NEC850_CVTF_SW, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 4-7 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 8-11 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 12-15 + NEC850_NULL, NEC850_TRNCF_SUW, NEC850_CEILF_SUW, NEC850_FLOORF_SUW, // 16-19 + NEC850_CVTF_SUW // 20 + }; + if ( r1 < qnumber(ops) ) + ins.itype = ops[r1]; + dtsrc = dt_float; + dtdst = dt_dword; + } + break; + case 1: + { + // CVTF.WS cat=0 type=2 subop=1 reg1=0 dw f + // CVTF.LS cat=0 type=2 subop=1 reg1=1 dq f + // CVTF.HS cat=0 type=2 subop=1 reg1=2 h f + // CVTF.SH cat=0 type=2 subop=1 reg1=3 f h + // CVTF.UWS cat=0 type=2 subop=1 reg1=16 dw f + // CVTF.ULS cat=0 type=2 subop=1 reg1=17 dq f + static const int ops[] = + { + NEC850_CVTF_WS, NEC850_CVTF_LS, NEC850_CVTF_HS, NEC850_CVTF_SH, // 0-3 + NEC850_CVTF_SW, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 4-7 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 8-11 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 12-15 + NEC850_CVTF_UWS, NEC850_CVTF_ULS // 16-17 + }; + if ( r1 < qnumber(ops) ) + ins.itype = ops[r1]; + // NB: we use dt_float for half-precision + op_dtype_t srct[] = { dt_dword, dt_qword, dt_float, dt_float }; + dtsrc = srct[r1&3]; + dtdst = dt_float; + } + break; + case 2: + { + // TRNCF.SL cat=0 type=2 subop=2 reg1=1 + // CEILF.SL cat=0 type=2 subop=2 reg1=2 + // FLOORF.SL cat=0 type=2 subop=2 reg1=3 + // CVTF.SL cat=0 type=2 subop=2 reg1=4 + // TRNCF.SUL cat=0 type=2 subop=2 reg1=17 + // CEILF.SUL cat=0 type=2 subop=2 reg1=18 + // FLOORF.SUL cat=0 type=2 subop=2 reg1=19 + // CVTF.SUL cat=0 type=2 subop=2 reg1=20 + static const int ops[] = + { + NEC850_NULL, NEC850_TRNCF_SL, NEC850_CEILF_SL, NEC850_FLOORF_SL, // 0-3 + NEC850_CVTF_SL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 4-7 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 8-11 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 12-15 + NEC850_NULL, NEC850_TRNCF_SUL, NEC850_CEILF_SUL, NEC850_FLOORF_SUL, // 16-19 + NEC850_CVTF_SUL // 20 + }; + if ( r1 < qnumber(ops) ) + ins.itype = ops[r1]; + dtsrc = dt_float; + dtdst = dt_qword; + } + break; + case 4: + case 12: + { + // ABSF.S cat = 0 type = 2 subop = 4 reg1 = 0 + // NEGF.S cat = 0 type = 2 subop = 4 reg1 = 1 + // ABSF.D cat = 0 type = 2 subop = 12 reg1 = 0 + // NEGF.D cat = 0 type = 2 subop = 12 reg1 = 1 + if ( r1 == 0 ) + ins.itype = subop == 4 ? NEC850_ABSF_S : NEC850_ABSF_D; + else if ( r1 == 1 ) + ins.itype = subop == 4 ? NEC850_NEGF_S : NEC850_NEGF_D; + + dtsrc = subop == 4 ? dt_float: dt_double; + dtdst = dtsrc; + } + break; + case 7: + case 15: + { + // SQRTF.S cat=0 type=2 subop=7 reg1=0 + // RECIPF.S cat=0 type=2 subop=7 reg1=1 + // RSQRTF.S cat=0 type=2 subop=7 reg1=2 + // SQRTF.D cat=0 type=2 subop=15 reg1=0 + // RECIPF.D cat=0 type=2 subop=15 reg1=1 + // RSQRTF.D cat=0 type=2 subop=15 reg1=2 + + if ( r1 == 0 ) + ins.itype = subop == 7 ? NEC850_SQRTF_S : NEC850_SQRTF_D; + else if ( r1 == 1 ) + ins.itype = subop == 7 ? NEC850_RECIPF_S : NEC850_RECIPF_D; + else if ( r1 == 2 ) + ins.itype = subop == 7 ? NEC850_RSQRTF_S : NEC850_RSQRTF_D; + + dtsrc = subop == 7 ? dt_float : dt_double; + dtdst = dtsrc; + } + break; + case 8: + { + // TRNCF.DW cat=0 type=2 subop=8 reg1=1 + // CEILF.DW cat=0 type=2 subop=8 reg1=2 + // FLOORF.DW cat=0 type=2 subop=8 reg1=3 + // CVTF.DW cat=0 type=2 subop=8 reg1=4 + // TRNCF.DUW cat=0 type=2 subop=8 reg1=17 + // CEILF.DUW cat=0 type=2 subop=8 reg1=18 + // FLOORF.DUW cat=0 type=2 subop=8 reg1=19 + // CVTF.DUW cat=0 type=2 subop=8 reg1=20 + static const int ops[] = + { + NEC850_NULL, NEC850_TRNCF_DW, NEC850_CEILF_DW, NEC850_FLOORF_DW, // 0-3 + NEC850_CVTF_DW, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 4-7 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 8-11 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 12-15 + NEC850_NULL, NEC850_TRNCF_DUW, NEC850_CEILF_DUW, NEC850_FLOORF_DUW, // 16-19 + NEC850_CVTF_DUW // 20 + }; + if ( r1 < qnumber(ops) ) + ins.itype = ops[r1]; + dtsrc = dt_double; + dtdst = dt_dword; + } + break; + case 9: + { + // CVTF.WD cat=0 type=2 subop=9 reg1=0 dw d + // CVTF.LD cat=0 type=2 subop=9 reg1=1 dq d + // CVTF.SD cat=0 type=2 subop=9 reg1=2 f d + // CVTF.DS cat=0 type=2 subop=9 reg1=3 d f + // CVTF.UWD cat=0 type=2 subop=9 reg1=16 dw d + // CVTF.ULD cat=0 type=2 subop=9 reg1=17 dq d + static const int ops[] = + { + NEC850_CVTF_WD, NEC850_CVTF_LD, NEC850_CVTF_SD, NEC850_CVTF_DS, // 0-3 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 4-7 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 8-11 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 12-15 + NEC850_CVTF_UWD, NEC850_CVTF_ULD // 16-17 + }; + if ( r1 < qnumber(ops) ) + ins.itype = ops[r1]; + op_dtype_t srct[] = { dt_dword, dt_qword, dt_float, dt_double }; + dtsrc = srct[r1 & 3]; + dtdst = r1 == 3 ? dt_float : dt_double; + } + break; + case 10: + { + // TRNCF.DL cat=0 type=2 subop=10 reg1=1 + // CEILF.DL cat=0 type=2 subop=10 reg1=2 + // FLOORF.DL cat=0 type=2 subop=10 reg1=3 + // CVTF.DL cat=0 type=2 subop=10 reg1=4 + // TRNCF.DUL cat=0 type=2 subop=10 reg1=17 + // CEILF.DUL cat=0 type=2 subop=10 reg1=18 + // FLOORF.DUL cat=0 type=2 subop=10 reg1=19 + // CVTF.DUL cat=0 type=2 subop=10 reg1=20 + static const int ops[] = + { + NEC850_NULL, NEC850_TRNCF_DL, NEC850_CEILF_DL, NEC850_FLOORF_DL, // 0-3 + NEC850_CVTF_DL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 4-7 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 8-11 + NEC850_NULL, NEC850_NULL, NEC850_NULL, NEC850_NULL, // 12-15 + NEC850_NULL, NEC850_TRNCF_DUL, NEC850_CEILF_DUL, NEC850_FLOORF_DUL, // 16-19 + NEC850_CVTF_DUL // 20 + }; + if ( r1 < qnumber(ops) ) + ins.itype = ops[r1]; + dtsrc = dt_double; + dtdst = dt_qword; + } + break; + } + if ( ins.itype != NEC850_NULL ) + { + set_opreg(ins.Op1, r2, dtsrc); + set_opreg(ins.Op2, r3, dtdst); + } + } + if ( ins.itype == NEC850_NULL && is_v850e2m() && ( cat >> 1 ) == 1 ) + { + // reg1, reg2, reg3, reg4 + // MADDF.S: cat = 01W type = 00, subop = WWWW + // MSUBF.S : cat = 01W type = 01, subop = WWWW + // NMADDF.S : cat = 01W type = 10, subop = WWWW + // NMSUBF.S : cat = 01W type = 11, subop = WWWW + // WWWWW: reg4. (The least significant bit of reg4 is bit 23.) + + int r4 = (subop << 1) | (cat & 1); + static const uint16 itypes[] = { NEC850_MADDF_S, NEC850_MSUBF_S, NEC850_NMADDF_S, NEC850_NMSUBF_S }; + ins.itype = itypes[typ]; + set_opreg(ins.Op1, r1, dt_float); + set_opreg(ins.Op2, r2, dt_float); + set_opreg(ins.Op3, r3, dt_float); + set_opreg(ins.Op4, r4, dt_float); + } + + + if ( ins.itype != NEC850_NULL ) + { + ins.auxpref |= N850F_FP; + return true; + } + return false; +} + + //------------------------------------------------------------------------ +// Decodes an instruction "w" into cmd structure +bool nec850_t::decode_instruction(const uint32 w, insn_t &ins) +{ +#define PARSE_L12 (((w & 1) << 11) | (w >> 21)) +#define PARSE_R1 (w & 0x1F) +#define PARSE_R2 ((w & 0xF800) >> 11) + + typedef struct + { + int itype; + int flags; + } itype_flags_t; + // If an instruction deals with displacement it should + // initialize this pointer to the operand location. + // At the end we will transform the operand to o_mem + // if we know how to resolve its address + op_t *displ_op = NULL; + + do + { + uint32 op; + + // + // Format I + // + op = (w & 0x7E0) >> 5; // Take bit5->bit10 + if ( op <= 0xF ) + { + static const int inst_1[] = + { + /* MOV reg1, reg2 */ NEC850_MOV, /* NOT reg1, reg2 */ NEC850_NOT, + /* DIVH reg1, reg2 */ NEC850_DIVH, /* JMP [reg1] */ NEC850_JMP, + /* SATSUBR reg1, reg2 */ NEC850_SATSUBR, /* SATSUB reg1, reg2 */ NEC850_SATSUB, + /* SATADD reg1, reg2 */ NEC850_SATADD, /* MULH reg1, reg2 */ NEC850_MULH, + /* OR reg1, reg2 */ NEC850_OR, /* XOR reg1, reg2 */ NEC850_XOR, + /* AND reg1, reg2 */ NEC850_AND, /* TST reg1, reg2 */ NEC850_TST, + /* SUBR reg1, reg2 */ NEC850_SUBR, /* SUB reg1, reg2 */ NEC850_SUB, + /* ADD reg1, reg2 */ NEC850_ADD, /* CMP reg1, reg2 */ NEC850_CMP + }; + + // + // NOP, Equivalent to MOV R, r (where R=r=0) + if ( w == 0 ) + { + ins.itype = NEC850_NOP; + ins.Op1.type = o_void; + ins.Op1.dtype = dt_void; + break; + } + + uint16 r1 = PARSE_R1; + uint16 r2 = PARSE_R2; + if ( is_v850e() && op == 2 && r1 == 0 ) + { + switch ( r2 ) + { + case 0: + if ( is_v850e2m() ) + ins.itype = NEC850_RIE; + break; + case 0x1C: + if ( is_rh850() ) + ins.itype = NEC850_DBHVTRAP; + break; + case 0x1D: + if ( is_rh850() ) + ins.itype = NEC850_DBCP; + break; + case 0x1E: + if ( is_v850e2m() ) + ins.itype = NEC850_RMTRAP; + break; + case 0x1F: + ins.itype = NEC850_DBTRAP; + break; + default: + if ( is_v850e2() && r2 < 0x10 ) + { + ins.itype = NEC850_FETRAP; + set_opimm(ins.Op1, r2); + } + break; + } + if ( ins.itype != 0 ) + break; + } + + ins.itype = inst_1[op]; + set_opreg(ins.Op1, r1); + + if ( is_v850e() ) + { + if ( r2 == 0 ) + { + if ( is_v850e2m() && op == 0 ) + { + switch ( r1 ) + { + case 0x1C: + if ( is_rh850() ) + ins.itype = NEC850_SYNCI; + else + ins.itype = NEC850_NULL; + break; + case 0x1D: + ins.itype = NEC850_SYNCE; + break; + case 0x1E: + ins.itype = NEC850_SYNCM; + break; + case 0x1F: + ins.itype = NEC850_SYNCP; + break; + default: + ins.itype = NEC850_NULL; + break; + } + if ( ins.itype != NEC850_NULL ) + { + ins.Op1.type = o_void; + ins.Op2.type = o_void; + break; + } + } + else if ( ins.itype == NEC850_DIVH ) + { + ins.itype = NEC850_SWITCH; + break; + } + else if ( ins.itype == NEC850_SATSUBR ) + { + ins.itype = NEC850_ZXB; + break; + } + else if ( ins.itype == NEC850_SATSUB ) + { + ins.itype = NEC850_SXB; + break; + } + else if ( ins.itype == NEC850_SATADD ) + { + ins.itype = NEC850_ZXH; + break; + } + else if ( ins.itype == NEC850_MULH ) + { + ins.itype = NEC850_SXH; + break; + } + } + // case when r2 != 0 + else + { + // SLD.BU / SLD.HU + if ( ins.itype == NEC850_JMP ) + { + bool sld_hu = (w >> 4) & 1; + uint32 addr = w & 0xF; + + if ( sld_hu ) + { + ins.itype = NEC850_SLD_HU; + ins.Op1.dtype = dt_word; + addr <<= 1; + } + else + { + ins.itype = NEC850_SLD_BU; + ins.Op1.dtype = dt_byte; + } + + ins.Op1.type = o_displ; + displ_op = &ins.Op1; + ins.Op1.reg = rEP; + ins.Op1.addr = addr; + ins.Op1.specflag1 = N850F_USEBRACKETS; + + set_opreg(ins.Op2, r2); + + break; + } + } + } + if ( ins.itype == NEC850_JMP && r2 == 0 ) + { + ins.Op1.specflag1 = N850F_USEBRACKETS; + } + else + { + set_opreg(ins.Op2, r2); + } + break; + } + // Format II + else if ( op <= 0x17 ) + { + if ( PARSE_R2 == 0 && op == 0x17 && is_v850e2m() ) + { + // 48-bit Format VI jr/jarl + // JARL disp32, reg1: 00000010111RRRRR ddddddddddddddd0 DDDDDDDDDDDDDDDD + // JR disp32: 0000001011100000 ddddddddddddddd0 DDDDDDDDDDDDDDDD + uint16 reg = PARSE_R1; + sval_t addr = fetch_disp32(w, ins); + if ( (addr & 1) != 0 ) + return false; + ins.Op1.addr = ins.ip + addr; + ins.Op1.type = o_near; + ins.Op1.specflag1 = N850F_VAL32; + if ( reg == 0 ) + { + ins.itype = NEC850_JR; + } + else + { + ins.itype = NEC850_JARL; + set_opreg(ins.Op2, reg); + } + break; + } + // flag used for sign extension + static const itype_flags_t inst_2[] = + { + { NEC850_MOV, 1 }, /* MOV imm5, reg2 */ + { NEC850_SATADD, 1 }, /* SATADD imm5, reg2 */ + { NEC850_ADD, 1 }, /* ADD imm5, reg2 */ + { NEC850_CMP, 1 }, /* CMP imm5, reg2 */ + { NEC850_SHR, 0 }, /* SHR imm5, reg2 */ + { NEC850_SAR, 0 }, /* SAR imm5, reg2 */ + { NEC850_SHL, 0 }, /* SHL imm5, reg2 */ + { NEC850_MULH, 1 }, /* MULH imm5, reg2 */ + }; + op -= 0x10; + + ins.itype = inst_2[op].itype; + uint16 r2 = PARSE_R2; + + if ( is_v850e() ) + { + // + // CALLT + // + if ( r2 == 0 && (ins.itype == NEC850_SATADD || ins.itype == NEC850_MOV) ) + { + ins.itype = NEC850_CALLT; + set_opimm(ins.Op1, w & 0x3F, dt_byte); + if ( g_ctbp_ea != BADADDR ) + { + // resolve callt addr using ctbp + ea_t ctp = g_ctbp_ea + (ins.Op1.value << 1); + ins.Op1.type = o_near; + ins.Op1.addr = g_ctbp_ea + get_word(ctp); + } + break; + } + } + + sval_t v = PARSE_R1; + if ( inst_2[op].flags == 1 ) + { + SIGN_EXTEND(sval_t, v, 5); + ins.Op1.specflag1 |= N850F_OUTSIGNED; + } + + set_opimm(ins.Op1, v, dt_byte); + set_opreg(ins.Op2, r2); + + // ADD imm, reg -> reg = reg + imm + if ( ins.itype == NEC850_ADD && r2 == rSP ) + ins.auxpref |= N850F_SP; + break; + } + // Format VI + else if ( op >= 0x30 && op <= 0x37 ) + { + static const itype_flags_t inst_6[] = + { // itype flags (1=signed) + { NEC850_ADDI, 1 }, /* ADDI imm16, reg1, reg2 */ + { NEC850_MOVEA, 1 }, /* MOVEA imm16, reg1, reg2 */ + { NEC850_MOVHI, 0 }, /* MOVHI imm16, reg1, reg2 */ + { NEC850_SATSUBI, 1 }, /* SATSUBI imm16, reg1, reg2 */ + { NEC850_ORI, 0 }, /* ORI imm16, reg1, reg2 */ + { NEC850_XORI, 0 }, /* XORI imm16, reg1, reg2 */ + { NEC850_ANDI, 0 }, /* ANDI imm16, reg1, reg2 */ + { NEC850_MULHI, 0 }, /* MULHI imm16, reg1, reg2 */ + }; + op -= 0x30; + ins.itype = inst_6[op].itype; + + uint16 r1 = PARSE_R1; + uint16 r2 = PARSE_R2; + uint32 imm = w >> 16; + + // + // V850E instructions + if ( is_v850e() && r2 == 0 ) + { + if ( ins.itype == NEC850_MULHI ) + { + if ( !is_v850e2() ) + return false; // "Do not specify r0 as the destination register reg2." + if ( ( imm & 1 ) != 0 ) + { + // RH850: LOOP reg1,disp16 + // 00000110111RRRRR ddddddddddddddd1 + if ( !is_rh850() || r1 == 0 ) + return false; // "Do not specify r0 for reg1." + ins.itype = NEC850_LOOP; + set_opreg(ins.Op1, r1); + imm ^= 1; // clear bit 0 + sval_t addr = ins.ip - imm; + ins.Op2.addr = addr; + ins.Op2.type = o_near; + } + else + { + // V850E2: jmp disp32 [reg1] + // 00000110111RRRRR ddddddddddddddd0 DDDDDDDDDDDDDDDD + sval_t addr = fetch_disp32(w, ins); + if ( ( addr & 1 ) != 0 ) + return false; + ins.Op1.addr = addr; + ins.Op1.type = o_displ; + ins.Op1.specflag1 = N850F_OUTSIGNED | N850F_VAL32 | N850F_USEBRACKETS; + ins.Op1.reg = r1; + ins.itype = NEC850_JMP; + } + break; + } + // MOV imm32, R + if ( ins.itype == NEC850_MOVEA ) + { + imm |= ins.get_next_word() << 16; + set_opimm(ins.Op1, imm); + ins.itype = NEC850_MOV; + + set_opreg(ins.Op2, r1); + break; + } + // DISPOSE imm5, list12 (reg1 == 0) + // DISPOSE imm5, list12, [reg1] + else if ( ins.itype == NEC850_SATSUBI || ins.itype == NEC850_MOVHI ) + { + r1 = (w >> 16) & 0x1F; + uint16 L = PARSE_L12; + + ins.auxpref |= N850F_SP; // SP reference + + set_opimm(ins.Op1, (w & 0x3E) >> 1, dt_byte); + + ins.Op2.value = L; + ins.Op2.type = o_reglist; + ins.Op2.dtype = dt_word; + + if ( r1 != 0 ) + { + set_opreg(ins.Op3, r1); + ins.Op3.specflag1 = N850F_USEBRACKETS; + + ins.itype = NEC850_DISPOSE_r; + } + else + { + ins.itype = NEC850_DISPOSE_r0; + } + break; + } + } + bool is_signed = inst_6[op].flags == 1; + set_opimm(ins.Op1, is_signed ? sval_t(int16(imm)) : imm); + ins.Op1.specflag1 |= N850F_OUTSIGNED; + + set_opreg(ins.Op2, r1); + + set_opreg(ins.Op3, r2); + + // (ADDI|MOVEA) imm, sp, sp -> sp = sp + imm + if ( (ins.itype == NEC850_ADDI || ins.itype == NEC850_MOVEA) + && ((r1 == rSP) && (r2 == rSP)) ) + { + ins.auxpref |= N850F_SP; + } + break; + } + // Format VII - LD.x + else if ( op == 0x38 || op == 0x39 ) + { + displ_op = &ins.Op1; + ins.Op1.type = o_displ; + ins.Op1.phrase = PARSE_R1; // R + + set_opreg(ins.Op2, PARSE_R2); + + uint32 addr; + // LD.B + if ( op == 0x38 ) + { + addr = w >> 16; + ins.itype = NEC850_LD_B; + ins.Op1.dtype = dt_byte; + } + else + { + // Bit16 is cleared for LD.H + if ( (w & (1 << 16)) == 0 ) + { + ins.itype = NEC850_LD_H; + ins.Op1.dtype = dt_word; + } + // LD.W + else + { + ins.itype = NEC850_LD_W; + ins.Op1.dtype = dt_dword; + } + addr = ((w & 0xFFFE0000) >> 17) << 1; + } + ins.Op1.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; + ins.Op1.addr = int16(addr); + + break; + } + // Format VII - ST.x + else if ( op == 0x3A || op == 0x3B ) + { + // (1) ST.B reg2, disp16 [reg1] + // (2) ST.H reg2, disp16 [reg1] + // (3) ST.W reg2, disp16 [reg1] + set_opreg(ins.Op1, PARSE_R2); + + ins.Op2.type = o_displ; + displ_op = &ins.Op2; + ins.Op2.reg = PARSE_R1; + ins.Op2.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; + // ST.B + uint32 addr; + if ( op == 0x3A ) + { + addr = w >> 16; + ins.itype = NEC850_ST_B; + ins.Op2.dtype = dt_byte; + } + else + { + // Bit16 is cleared for ST.H + if ( (w & (1 << 16)) == 0 ) + { + ins.itype = NEC850_ST_H; + ins.Op2.dtype = dt_word; + } + else + { + ins.itype = NEC850_ST_W; + ins.Op2.dtype = dt_dword; + } + addr = ((w & 0xFFFE0000) >> 17) << 1; + } + ins.Op2.addr = int16(addr); + break; + } + // Format XIII - PREPARE / LD.BU + else if ( is_v850e() + && ((w >> 16) & 0x1) // this bit is important to differentiate between JARL/JR instructions + && (op == 0x3C || op == 0x3D) ) + { + uint16 r2 = PARSE_R2; + + uint16 subop = (w >> 16) & 0x1F; + // PREPARE + if ( r2 == 0 && (subop == 1 || (subop & 7) == 3) ) + { + ins.auxpref |= N850F_SP; + ins.Op1.value = PARSE_L12; + ins.Op1.type = o_reglist; + ins.Op1.dtype = dt_word; + + set_opimm(ins.Op2, (w & 0x3E) >> 1, dt_byte); + + if ( subop == 1 ) + { + ins.itype = NEC850_PREPARE_i; + } + else + { + ins.itype = NEC850_PREPARE_sp; + uint16 ff = subop >> 3; + switch ( ff ) + { + case 0: + // disassembles as: PREPARE list12, imm5, sp + // meaning: load sp into ep + set_opreg(ins.Op3, rSP); + break; + // the other cases disassemble with imm (the 3rd operand) directly processed: + // f=1->ep=sign_extend(imm16), f=2->ep=imm16 shl 16, f=3->ep=imm32 + case 1: + // c: a8 07 0b 80 prepare {r24}, 20, 0x1 + // 10: 01 00 + set_opimm(ins.Op3, sval_t(int16(ins.get_next_word()))); + break; + case 2: + // 2: a8 07 13 80 prepare {r24}, 20, 0x10000 + // 6: 01 00 + set_opimm(ins.Op3, ins.get_next_word() << 16); + break; + case 3: + // 2: a8 07 1b 80 prepare {r24}, 20, 0x1 + // 6: 01 00 00 00 + set_opimm(ins.Op3, ins.get_next_dword()); + break; + } + } + } + else if ( r2 == 0 && is_v850e2m() ) + { + // disp23 variants ( Format XIV) + // LD.BU disp23 [reg1] , reg3 + // 00000111101RRRRR wwwwwddddddd0101 DDDDDDDDDDDDDDDD + // LD.HU disp23 [reg1] , reg3 + // 00000111101RRRRR wwwwwdddddd00111 DDDDDDDDDDDDDDDD + // ST.H reg3, disp23 [reg1] + // 00000111101RRRRR wwwwwdddddd01101 DDDDDDDDDDDDDDDD + // ST.H reg3, disp23 [reg1] + // 00000111101RRRRR wwwwwdddddd01101 DDDDDDDDDDDDDDDD + // LD.B disp23 [reg1] , reg3 + // 00000111100RRRRR wwwwwddddddd0101 DDDDDDDDDDDDDDDD + // LD.H disp23 [reg1] , reg3 + // 00000111100RRRRR wwwwwdddddd00111 DDDDDDDDDDDDDDDD + // LD.W disp23 [reg1] , reg3 + // 00000111100RRRRR wwwwwdddddd01001 DDDDDDDDDDDDDDDD + // LD.DW disp23[reg1], reg3 + // 00000111101RRRRR wwwwwdddddd01001 DDDDDDDDDDDDDDDD + // ST.B reg3, disp23 [reg1] + // 00000111100RRRRR wwwwwddddddd1101 DDDDDDDDDDDDDDDD + // ST.W reg3, disp23 [reg1] + // 00000111100RRRRR wwwwwdddddd01111 DDDDDDDDDDDDDDDD + // ST.DW reg3, disp23[reg1] + // 00000111101RRRRR wwwwwdddddd01111 DDDDDDDDDDDDDDDD + // RRRRR = reg1, wwwww = reg3. + // ddddddd is the lower 7 bits of disp23. + // DDDDDDDDDDDDDDDD is the higher 16 bits of disp23. + subop = ( w >> 16 ) & 0xF; + bool sign = ( op & 1 ) == 0; + uint32 r3 = ( w & 0xF8000000 ) >> 27; + switch ( subop ) + { + case 5: + ins.itype = sign ? NEC850_LD_B : NEC850_LD_BU; + if ( !decode_disp23(w, ins, 0, dt_byte) ) + return false; + set_opreg(ins.Op2, r3); + break; + case 7: + ins.itype = sign ? NEC850_LD_H : NEC850_LD_HU; + if ( !decode_disp23(w, ins, 0, dt_word) ) + return false; + set_opreg(ins.Op2, r3); + break; + case 9: + if ( !sign && !is_rh850() ) + return false; + ins.itype = sign ? NEC850_LD_W : NEC850_LD_DW; + if ( !decode_disp23(w, ins, 0, dt_dword) ) + return false; + set_opreg(ins.Op2, r3); + break; + case 13: + ins.itype = sign ? NEC850_ST_B : NEC850_ST_H; + if ( !decode_disp23(w, ins, 1, sign ? dt_byte : dt_word) ) + return false; + set_opreg(ins.Op1, r3); + break; + case 15: + if ( !sign && !is_rh850() ) + return false; + ins.itype = sign ? NEC850_ST_W : NEC850_ST_DW; + if ( !decode_disp23(w, ins, 1, dt_dword) ) + return false; + set_opreg(ins.Op1, r3); + break; + } + } + else + { + // LD.BU disp16 [reg1] , reg2 + // rrrrr11110bRRRRR ddddddddddddddd1 + // ddddddddddddddd is the higher 15 bits of disp16, and b is bit 0 of disp16. + // rrrrr != 00000 ( Do not specify r0 for reg2. ) + if ( r2 == 0 ) + return false; + uint16 r1 = PARSE_R1; + + ins.itype = NEC850_LD_BU; + + ins.Op1.type = o_displ; + displ_op = &ins.Op1; + ins.Op1.reg = r1; + ins.Op1.addr = int16(((w >> 16) & ~1) | ((w & 0x20) >> 5)); + ins.Op1.dtype = dt_byte; + ins.Op1.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; + + set_opreg(ins.Op2, r2); + } + break; + } + // Format VIII + else if ( op == 0x3E ) + { + // parse sub-opcode (b15..b14) + op = ((w & 0xC000) >> 14); + static const int inst_8[] = + { + NEC850_SET1, NEC850_NOT1, + NEC850_CLR1, NEC850_TST1 + }; + ins.itype = inst_8[op]; + set_opimm(ins.Op1, ((w & 0x3800) >> 11), dt_byte); + + + ins.Op2.type = o_displ; + displ_op = &ins.Op2; + ins.Op2.addr = int16(w >> 16); + ins.Op2.offb = 2; + ins.Op2.dtype = dt_byte; + ins.Op2.reg = PARSE_R1; // R + ins.Op2.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; + break; + } + // + // Format IX, X + // + else if ( op == 0x3F ) + { + if ( (w & ( 1 << 16 )) == 0 && ( w & ( 1 << 26 ) ) != 0 ) + // coprocessor insn + return decode_coprocessor(w, ins); + // + // Format X + // + + // Const opcodes + if ( w == 0x16087E0 ) // EI + ins.itype = NEC850_EI; + else if ( w == 0x16007E0 ) // DI + ins.itype = NEC850_DI; + else if ( w == 0x14007E0 ) // RETI + ins.itype = NEC850_RETI; + else if ( w == 0x12007E0 ) // HALT + ins.itype = NEC850_HALT; + else if ( w == 0xffffffff ) + ins.itype = NEC850_BREAKPOINT; + else if ( (w >> 5) == 0x8003F ) //lint !e587 predicate always false // TRAP + { + ins.itype = NEC850_TRAP; + set_opimm(ins.Op1, PARSE_R1, dt_byte); + break; + } + if ( ins.itype != 0 ) + break; + if ( is_v850e1f() && !is_v850e2m() ) + { + // E1F opcodes (ref. U16374EJ1V0UM) + int subop = ( w >> 16 ) & 0x7FF; + int r3 = ( w & 0xF8000000 ) >> 27; + switch ( subop ) + { +// Format F:I reg1, reg2, reg3 + case 0x3E0: + ins.itype = NEC850_DIVF_S; + goto OPS_FI; + case 0x3E4: + ins.itype = NEC850_SUBF_S; + goto OPS_FI; + case 0x3E8: + ins.itype = NEC850_ADDF_S; + goto OPS_FI; + case 0x3EC: + ins.itype = NEC850_MULF_S; + goto OPS_FI; + case 0x3F0: + ins.itype = NEC850_MINF_S; + goto OPS_FI; + case 0x3F4: + ins.itype = NEC850_MAXF_S; +OPS_FI: + set_opreg(ins.Op1, PARSE_R1); + set_opreg(ins.Op2, PARSE_R2); + set_opreg(ins.Op3, r3); + break; +// Format F:II reg2, reg3 + case 0x360: + ins.itype = NEC850_CVT_SW; +OPS_FII: + set_opreg(ins.Op1, PARSE_R2); + set_opreg(ins.Op2, r3); + break; + case 0x368: + ins.itype = NEC850_TRNC_SW; + goto OPS_FII; + case 0x370: + ins.itype = NEC850_CVT_WS; + goto OPS_FII; + case 0x3F8: + ins.itype = NEC850_NEGF_S; + goto OPS_FII; + case 0x3FC: + ins.itype = NEC850_ABSF_S; + goto OPS_FII; + +// Format F:IV reg2 or reg3 + case 0x378: + if ( r3 != 0 ) + { + // STFF EFG,reg2 + ins.itype = NEC850_STFF; + set_opreg(ins.Op1, EFG); + set_opreg(ins.Op2, r3); + } + else + { + ins.itype = NEC850_TRFF; + // no operands + } + break; + case 0x37C: + // STFC ECT,reg2 + ins.itype = NEC850_STFC; + set_opreg(ins.Op1, ECT); + set_opreg(ins.Op2, r3); + break; + + case 0x37A: + if ( r3 == 0 ) + { + // LDFF reg2,EFG + ins.itype = NEC850_LDFF; + set_opreg(ins.Op1, PARSE_R2); + set_opreg(ins.Op2, EFG); + } + break; + + case 0x37E: + if ( r3 == 0 ) + { + // LDFC reg2,ECT + ins.itype = NEC850_LDFC; + set_opreg(ins.Op1, PARSE_R2); + set_opreg(ins.Op2, ECT); + } + break; + + } + if ( ins.itype != 0 ) + break; + } + // Still in format 10 (op = 0x3F) + if ( is_v850e() ) + { + if ( is_v850e2m() ) + { + if ( w == 0x14807E0 ) + ins.itype = NEC850_EIRET; + else if ( w == 0x14a07E0 ) + ins.itype = NEC850_FERET; + else if ( ( w & 0xc7ffffe0 ) == 0x0160d7e0 ) + { + ins.itype = NEC850_SYSCALL; + int v8 = (w & 0x1f) | ((w >> (27 - 5)) & 0xe0); + set_opimm(ins.Op1, v8); + } + else if ( is_rh850() ) + { + int subop = ( w >> 16 ) & 0x7FF; + switch ( subop ) + { + case 0x20: + case 0x40: + { + // LDSR reg2, regID, selID + // rrrrr111111RRRRR sssss00000100000 + // rrrrr: regID, sssss: selID, RRRRR: reg2 + // STSR regID, reg2, selID + // rrrrr111111RRRRR sssss00001000000 + // rrrrr: regID, sssss: selID, RRRRR: reg2 + bool is_ld = subop == 0x20; + ins.itype = is_ld ? NEC850_LDSR : NEC850_STSR; + uint32 selid = ( w & 0xF8000000 ) >> 27; + uint32 regid = PARSE_R1; + uint32 r2 = PARSE_R2; + if ( is_ld ) + { + // In this instruction, general-purpose register reg2 is used as the source register, but, for + // mnemonic description convenience, the general - purpose register reg1 field is used in the + // opcode.The meanings of the register specifications in the mnemonic descriptions and + // opcode therefore differ from those of other instructions. + set_opreg(ins.Op1, regid); + set_opreg(ins.Op2, r2 + rSR0); + } + else + { + set_opreg(ins.Op1, regid + rSR0); + set_opreg(ins.Op2, r2); + } + if ( selid != 0 ) + set_opimm(ins.Op3, selid); + } + break; + + case 0x30: + case 0x50: + { + bool is_ld = subop == 0x30; + if ( is_ld ) + { + ins.itype = NEC850_LDTC_SR; + set_opreg(ins.Op1, PARSE_R1); + set_opimm(ins.Op2, PARSE_R2); + } + else + { + ins.itype = NEC850_STTC_SR; + set_opimm(ins.Op1, PARSE_R1); + set_opreg(ins.Op2, PARSE_R2); + } + uint32 selid = ( w & 0xF8000000 ) >> 27; + set_opimm(ins.Op3, selid); + } + break; + + case 0x32: + case 0x52: + { + bool is_ld = subop == 0x32; + uint32 selid = ( w & 0xF8000000 ) >> 27; + switch ( selid ) + { + case 0: + ins.itype = is_ld ? NEC850_LDTC_GR: NEC850_STTC_GR; + set_opreg(ins.Op2, PARSE_R2); + set_opreg(ins.Op1, PARSE_R1); + break; + case 1: + ins.itype = is_ld ? NEC850_LDTC_VR : NEC850_STTC_VR; + set_opreg(ins.Op1, is_ld ? PARSE_R2 : PARSE_R1); + set_opreg(ins.Op2, is_ld ? PARSE_R1 : PARSE_R2); + break; + case 31: + ins.itype = is_ld ? NEC850_LDTC_PC : NEC850_STTC_PC; + set_opreg(ins.Op1, is_ld ? PARSE_R1 : PARSE_R2); + break; + default: + break; + } + } + break; + + case 0x34: + case 0x54: + { + bool is_ld = subop == 0x34; + if ( is_ld ) + { + ins.itype = NEC850_LDVC_SR; + set_opreg(ins.Op1, PARSE_R1); + set_opimm(ins.Op2, PARSE_R2); + } + else + { + ins.itype = NEC850_STVC_SR; + set_opimm(ins.Op1, PARSE_R1); + set_opreg(ins.Op2, PARSE_R2); + + } + uint32 selid = ( w & 0xF8000000 ) >> 27; + set_opimm(ins.Op3, selid); + } + break; + + case 0xC4: + case 0xC6: + { + // ROTL imm5, reg2, reg3 + // rrrrr111111iiiii wwwww00011000100 + // ROTL reg1, reg2, reg3 + // rrrrr111111RRRRR wwwww00011000110 + ins.itype = NEC850_ROTL; + uint32 r1 = PARSE_R1; + uint32 r2 = PARSE_R2; + uint32 r3 = (w & 0xF8000000 ) >> 27; + if ( subop == 0xC4 ) + { + set_opimm(ins.Op1, r1); + } + else + { + set_opreg(ins.Op1, r1); + } + set_opreg(ins.Op2, r2); + set_opreg(ins.Op3, r3); + } + break; + + case 0x110: + ins.itype = NEC850_HVTRAP; + set_opimm(ins.Op1, PARSE_R1, dt_byte); + break; + + case 0x132: + ins.itype = NEC850_EST; + break; + + case 0x134: + ins.itype = NEC850_DST; + break; + + case 0x378: + { + // LDL.W [reg1], reg3 + // 00000111111RRRRR wwwww01101111000 + ins.itype = NEC850_LDL_W; + uint32 r3 = ( w & 0xF8000000 ) >> 27; + set_opreg(ins.Op1, PARSE_R1); + ins.Op1.specflag1 = N850F_USEBRACKETS; + set_opreg(ins.Op2, r3); + break; + } + + case 0x37A: + { + // STC.W reg3, [reg1] + // 00000111111RRRRR wwwww01101111010 + ins.itype = NEC850_STC_W; + uint32 r3 = ( w & 0xF8000000 ) >> 27; + set_opreg(ins.Op1, r3); + set_opreg(ins.Op2, PARSE_R1); + ins.Op2.specflag1 = N850F_USEBRACKETS; + break; + } + case 0x160: + { + uint32 r1 = PARSE_R1; + uint32 r2 = PARSE_R2; + uint32 r3 = ( w & 0xF8000000 ) >> 27; + int w1 = w >> 16; + switch ( r2 ) + { + case 8: // pushsp + case 0xB: // dbpush + case 0xC: // popsp + { + // PUSHSP rh-rt + // 01000111111RRRRR wwwww00101100000 + // POPSP rh-rt + // 01100111111RRRRR wwwww00101100000 + // RRRRR indicates rh. wwwww indicates rt. + ins.itype = r2 == 8 ? NEC850_PUSHSP + : r2 == 0xB ? NEC850_DBPUSH + : NEC850_POPSP; + ins.Op1.type = o_regrange; + ins.Op1.regrange_high = r1; + ins.Op1.regrange_low = r3; + } + break; + + case 0x10: + switch ( w1 ) + { + case 0x8960: + ins.itype = NEC850_TLBAI; + break; + case 0x8160: + ins.itype = NEC850_TLBVI; + break; + case 0xC160: + ins.itype = NEC850_TLBS; + break; + case 0xE960: + ins.itype = NEC850_TLBR; + break; + case 0xE160: + ins.itype = NEC850_TLBW; + break; + } + break; + + case 0x18: + { + // JARL [reg1], reg3 + // 11000111111RRRRR WWWWW00101100000 + set_opreg(ins.Op1, r1); + ins.Op1.specflag1 = N850F_USEBRACKETS; + set_opreg(ins.Op2, r3); + ins.itype = NEC850_JARL; + } + break; + + case 0x19: + { + ins.itype = NEC850_DBTAG; + int v8 = (w & 0x1f) | ((w1 >> 6) & 0xe0); + set_opimm(ins.Op1, v8); + } + break; + + case 0x1A: + { + ins.itype = NEC850_HVCALL; + int v8 = (w & 0x1f) | ((w1 >> 6) & 0xe0); + set_opimm(ins.Op1, v8); + } + break; + + case 0x1B: + { + // PREF prefop, [reg1] + // 11011111111RRRRR PPPPP00101100000 + // PPPPP indicates prefop + ins.itype = NEC850_PREF; + set_opimm(ins.Op1, r3); + set_opreg(ins.Op2, r1); + } + break; + + case 0x1Cu: + case 0x1Du: + case 0x1Eu: + case 0x1Fu: + { + // CACHE cacheop, [reg1] + // 111pp111111RRRRR PPPPP00101100000 + // ppPPPPP indicates cacheop + + int cacheop = ( ( r2 & 3 ) << 5 ) | r3; + if ( r1 == 0x1f && cacheop == 0x7E ) + { + ins.itype = NEC850_CLL; + } + else + { + ins.itype = NEC850_CACHE; + set_opimm(ins.Op1, cacheop); + set_opreg(ins.Op2, r1); + } + } + break; + } + } + break; + + default: + if ( w == 0x1200FE0 ) + ins.itype = NEC850_SNOOZE; + else if ( (w&0x10000) == 0 ) + { + uint o0 = ( w >> 20 ) & 0x7F; + if ( o0 == 9 || o0 == 11 || o0 == 13 ) + { + // BINS reg1, pos, width, reg2 + + // rrrrr111111RRRRR MMMMK 0001001 LLL0 msb >= 16, lsb >= 16 + // rrrrr111111RRRRR MMMMK 0001011 LLL0 msb >= 16, lsb < 16 + // rrrrr111111RRRRR MMMMK 0001101 LLL0 msb < 16, lsb < 16 + // Most significant bit of field to be updated : msb = pos + width - 1 + // Least significant bit of field to be updated : lsb = pos + // MMMM = lower 4 bits of msb, KLLL = lower 4 bits of lsb + uint16 whi = w >> 16; + uint lsb = ( whi >> 1 ) & 7; + lsb |= ( whi >> 8 ) & 8; + uint msb = ( whi >> 12 ) & 0xF; + if ( o0 == 9 || o0 == 11 ) + msb += 16; + if ( o0 == 9 ) + lsb += 16; + uint width = msb - lsb + 1; + + ins.itype = NEC850_BINS; + set_opreg(ins.Op1, PARSE_R1); + set_opimm(ins.Op2, lsb); + set_opimm(ins.Op3, width); + set_opreg(ins.Op4, PARSE_R2); + } + } + break; + + } + if ( ins.itype != 0 ) + break; + } + + if ( ins.itype != 0 ) + break; + } + if ( w == 0x14607E0 ) + { + ins.itype = NEC850_DBRET; + break; + } + else if ( w == 0x14407E0 ) + { + ins.itype = NEC850_CTRET; + break; + } + else if ( (w >> 16) & 0x1 ) + { + int r2 = PARSE_R2; + int r1 = PARSE_R1; + if ( r2 != 0 ) + { + // V850E: LD.HU disp16 [reg1], reg2 + // rrrrr111111RRRRR ddddddddddddddd1 + ins.itype = NEC850_LD_HU; + ins.Op1.type = o_displ; + displ_op = &ins.Op1; + ins.Op1.reg = r1; + ins.Op1.addr = uint32(( w >> 17 ) << 1); + ins.Op1.dtype = dt_word; + ins.Op1.specflag1 = N850F_USEBRACKETS | N850F_OUTSIGNED; + set_opreg(ins.Op2, r2); + } + else if ( is_rh850() ) + { + // RH850: Bcond disp17 + // 00000111111DCCCC ddddddddddddddd1 + sval_t dest = uint32(( w >> 17 ) << 1); + if ( (w & 0x10) != 0 ) + dest += 0x10000; // D + SIGN_EXTEND(sval_t, dest, 17); + ins.itype = bcond_map[w & 0xF]; + ins.Op1.dtype = dt_word; + ins.Op1.type = o_near; + ins.Op1.addr = ea_t(dest + ins.ip); + } + break; + } + // + // XI Group match (reg1, reg2, reg3) + // + uint32 r1 = PARSE_R1; + uint32 r2 = PARSE_R2; + uint32 r3 = ( w & 0xF8000000 ) >> 27; + + op = (w & 0x7FF0000) >> 16; + if ( op == 0x220 ) + ins.itype = NEC850_MUL; + else if ( op == 0x222 ) + ins.itype = NEC850_MULU; + else if ( op == 0x280 ) + ins.itype = NEC850_DIVH_r3; + else if ( op == 0x282 ) + ins.itype = NEC850_DIVHU; + else if ( op == 0x2C0 ) + ins.itype = NEC850_DIV; + else if ( op == 0x2C2 ) + ins.itype = NEC850_DIVU; + else if ( is_v850e2() ) + { + if ( ( op & 1 ) == 0 ) + { + if ( ( op >> 5 ) == 0x1D ) + { + // ADF + int cc = ( op >> 1 ) & 0xF; + if ( cc == CC_SAT ) + { + ins.itype = NEC850_SATADD; + } + else + { + ins.itype = NEC850_ADF; + set_opcond(ins.Op1, cc); + set_opreg(ins.Op2, r1); + set_opreg(ins.Op3, r2); + set_opreg(ins.Op4, r3); + break; + } + } + else if ( ( op >> 5 ) == 0x1C ) + { + // SBF + int cc = ( op >> 1 ) & 0xF; + if ( cc == CC_SAT ) + { + ins.itype = NEC850_SATSUB; + } + else + { + ins.itype = NEC850_SBF; + set_opcond(ins.Op1, cc); + set_opreg(ins.Op2, r1); + set_opreg(ins.Op3, r2); + set_opreg(ins.Op4, r3); + break; + } + } + else if ( ( op >> 6 ) == 0xF ) + { + // MAC rrrrr111111RRRRR wwww0011110mmmm0 + // MACU rrrrr111111RRRRR wwww0011111mmmm0 + ins.itype = ( op & 0x20 ) ? NEC850_MACU : NEC850_MAC; + int r4 = op&0x1F; + set_opreg(ins.Op1, r1); + set_opreg(ins.Op2, r2); + set_opreg(ins.Op3, r3); + set_opreg(ins.Op4, r4); + break; + } + } + switch ( op ) + { + case 0x82: + ins.itype = NEC850_SHR; + break; + case 0xa2: + ins.itype = NEC850_SAR; + break; + case 0xc2: + ins.itype = NEC850_SHL; + break; + case 0xEE: + ins.itype = NEC850_CAXI; + ins.Op1.specflag1 |= N850F_USEBRACKETS; + break; + case 0x2FE: + ins.itype = NEC850_DIVQU; + break; + case 0x2FC: + ins.itype = NEC850_DIVQ; + break; + } + } + // process the match + if ( ins.itype != 0 ) + { + set_opreg(ins.Op1, r1); + set_opreg(ins.Op2, r2); + set_opreg(ins.Op3, r3); + break; + } + + // + // XII/IX Group match (reg2, reg3) + // + if ( op == 0x340 ) + ins.itype = NEC850_BSW; + else if ( op == 0x342 ) + ins.itype = NEC850_BSH; + else if ( op == 0x344 ) + ins.itype = NEC850_HSW; + else if ( is_v850e2() ) + { + switch ( op ) + { + case 0x346: + ins.itype = NEC850_HSH; + break; + case 0x360: + ins.itype = NEC850_SCH0R; + break; + case 0x362: + ins.itype = NEC850_SCH1R; + break; + case 0x364: + ins.itype = NEC850_SCH0L; + break; + case 0x366: + ins.itype = NEC850_SCH1L; + break; + } + } + // process the match + if ( ins.itype != 0 ) + { + set_opreg(ins.Op1, r2); + set_opreg(ins.Op2, r3); + break; + } + + // + // match CMOV + // + op = w >> 16; + op = ((op & 0x7E0) >> 4) | (op & 0x1); + if ( op == 0x30 || op == 0x32 ) + { + uint32 cc = (w & 0x1E0000) >> 17; + ins.itype = NEC850_CMOV; + set_opcond(ins.Op1, cc); + + r1 = PARSE_R1; + r2 = PARSE_R2; + r3 = (w & 0xF8000000) >> 27; + + if ( op == 0x32 ) // CMOV cc, reg1, reg2, reg3 + { + set_opreg(ins.Op2, r1); + } + else + { + // CMOV cc, imm5, reg2, reg3 + sval_t v = r1; + SIGN_EXTEND(sval_t, v, 5); + set_opimm(ins.Op2, v, dt_byte); + ins.Op2.specflag1 |= N850F_OUTSIGNED; + } + set_opreg(ins.Op3, r2); + set_opreg(ins.Op4, r3); + break; + } + // + // match MUL[U]_i9 + // + op = w >> 16; + op = ((op & 0x7C0) >> 4) | (op & 0x3); + if ( op == 0x24 || op == 0x26 ) + { + sval_t imm = (((w & 0x3C0000) >> 18) << 5) | (w & 0x1F); + if ( op == 0x24 ) + { + ins.itype = NEC850_MUL; + SIGN_EXTEND(sval_t, imm, 9); + ins.Op1.specflag1 |= N850F_OUTSIGNED; + } + else + ins.itype = NEC850_MULU; + + set_opimm(ins.Op1, imm); + set_opreg(ins.Op2, PARSE_R2); + set_opreg(ins.Op3, (w & 0xF8000000) >> 27); + break; + } + } + + // + // Format IX + // + op = w >> 16; // take 2nd half-word as the opcode + uint32 reg1 = PARSE_R1; + uint32 reg2 = PARSE_R2; + // SETF + if ( op == 0 ) + { + if ( ( w & 0x10 ) == 0 ) + { + ins.itype = NEC850_SETF; + set_opcond(ins.Op1, w & 0xF); + set_opreg(ins.Op2, reg2); + } + else if ( is_v850e2m() ) + { + ins.itype = NEC850_RIE; + uint imm5 = ( w >> 11 ) & 0x1F; + uint imm4 = w & 0xF; + set_opimm(ins.Op1, imm5); + set_opimm(ins.Op2, imm4); + } + break; + } + + switch ( op ) + { + case 0x20: // LDSR + ins.itype = NEC850_LDSR; + ins.Op2.reg = rSR0; // designate system register + break; + case 0x40: // STSR + ins.itype = NEC850_STSR; + ins.Op1.reg = rSR0; // designate system register + break; + case 0x80: // SHR + ins.itype = NEC850_SHR; + break; + case 0xA0: // SAR + ins.itype = NEC850_SAR; + break; + case 0xC0: // SHL + ins.itype = NEC850_SHL; + break; + } + + if ( ins.itype != 0 ) + { + // Common stuff for the rest of Format 9 instructions + ins.Op1.dtype = ins.Op2.dtype = dt_dword; + ins.Op1.type = ins.Op2.type = o_reg; + ins.Op1.reg += reg1; + ins.Op2.reg += reg2; + break; + } + + // -> ins.itype == 0 + + + // No match? Try V850E + if ( is_v850e() ) + { + // SASF + if ( op == 0x200 ) + { + ins.itype = NEC850_SASF; + set_opcond(ins.Op1, w & 0xF); + set_opreg(ins.Op2, reg2); + break; + } + + switch ( op ) + { + case 0xE0: // NOT1 + ins.itype = NEC850_SET1; + break; + case 0xE2: // NOT1 + ins.itype = NEC850_NOT1; + break; + case 0xE4: // CLR1 + ins.itype = NEC850_CLR1; + break; + case 0xE6: // TST1 + ins.itype = NEC850_TST1; + break; + default: + return 0; // No match! + } + // Common + set_opreg(ins.Op1, reg2, dt_byte); + + ins.Op2.dtype = dt_byte; + displ_op = &ins.Op2; + ins.Op2.type = o_displ; + ins.Op2.addr = 0; + ins.Op2.reg = reg1; + ins.Op2.specflag1 = N850F_USEBRACKETS; + } + + if ( ins.itype == 0 ) + return 0; // unknown instruction + + break; + } + + // + // Format V + // + op = (w & 0x780) >> 6; // Take bit6->bit10 + // JARL and JR + if ( op == 0x1E ) + { + uint32 reg = PARSE_R2; + sval_t addr = uint32((((w & 0x3F) << 15) | ((w & 0xFFFE0000) >> 17)) << 1); + SIGN_EXTEND(sval_t, addr, 22); + + ins.Op1.addr = ins.ip + addr; + ins.Op1.type = o_near; + // per the docs, if reg is zero then JARL turns to JR + if ( reg == 0 ) + { + ins.itype = NEC850_JR; + } + else + { + ins.itype = NEC850_JARL; + set_opreg(ins.Op2, reg); + } + break; + } + + // + // Format III + // + op = (w & 0x780) >> 7; // Take bit7->bit10 + // assert: op in [0, 0xF] + // Bcond disp9 + if ( op == 0xB ) + { + sval_t dest = ( ((w & 0x70) >> 4) | ((w & 0xF800) >> 8) ) << 1; + SIGN_EXTEND(sval_t, dest, 9); + + ins.itype = bcond_map[w & 0xF]; + ins.Op1.dtype = dt_word; + ins.Op1.type = o_near; + ins.Op1.addr = ea_t(dest + ins.ip); + break; + } + // + // Format IV + // + else if ( op >= 6 ) + { + uint32 reg2 = PARSE_R2; + uint32 addr = (w & 0x7F); // zero extended + int idx_d(-1), idx_r(-1); + char dtyp_d(-1); + + // SLD.B + if ( op == 6 ) + { + ins.itype = NEC850_SLD_B; + idx_d = 0; + idx_r = 1; + dtyp_d = dt_byte; + } + // SLD.H + else if ( op == 8 ) + { + ins.itype = NEC850_SLD_H; + idx_d = 0; + idx_r = 1; + dtyp_d = dt_word; + addr <<= 1; + } + // SLD.W + else if ( op == 10 && ((w & 1) == 0) ) + { + ins.itype = NEC850_SLD_W; + idx_d = 0; + idx_r = 1; + dtyp_d = dt_dword; + addr <<= 1; + } + // SST.B + else if ( op == 7 ) + { + ins.itype = NEC850_SST_B; + idx_d = 1; + idx_r = 0; + dtyp_d = dt_byte; + } + // SST.H + else if ( op == 9 ) + { + ins.itype = NEC850_SST_H; + idx_d = 1; + idx_r = 0; + dtyp_d = dt_byte; + // bit0 is already cleared, so the 7bit addr we read + // can be shifted by one to transform it to 8bit + addr <<= 1; + } + // SST.W + else if ( op == 10 && ((w & 1) == 1) ) + { + ins.itype = NEC850_SST_W; + idx_d = 1; + idx_r = 0; + dtyp_d = dt_dword; + // clear lower bit because it is set, and shift by one + // bit 15 0 + // rrrrr1010dddddd1 + addr = (addr & ~1) << 1; + } + if ( idx_d == -1 || idx_r == -1 || dtyp_d == -1 ) + return false; // could not decode + + set_opreg(ins.ops[idx_r], reg2); + + ins.ops[idx_d].type = o_displ; + displ_op = &ins.ops[idx_d]; + ins.ops[idx_d].reg = rEP; + ins.ops[idx_d].addr = addr; + ins.ops[idx_d].dtype = dtyp_d; + ins.ops[idx_d].specflag1 = N850F_USEBRACKETS; + break; + } + // Unknown instructions + ins.itype = NEC850_NULL; + } while ( false ); + + // special cases when we have memory access through displacement + if ( displ_op != NULL ) + { + // A displacement with GP and GP is set? + if ( displ_op->reg == rGP && g_gp_ea != BADADDR ) + { + displ_op->type = o_mem; + if ( ins.itype == NEC850_SLD_BU || ins.itype == NEC850_LD_BU + || ins.itype == NEC850_SLD_HU || ins.itype == NEC850_LD_HU ) + { + displ_op->addr = short(displ_op->addr) + g_gp_ea; + } + else + { + displ_op->addr += g_gp_ea; + } + } + // register zero access? + else if ( displ_op->reg == rZERO ) + { + // since r0 is always 0, we can replace the operand by the complete address + displ_op->type = o_mem; + displ_op->specflag1 &= ~N850F_OUTSIGNED; + if ( ins.itype == NEC850_LD_BU || ins.itype == NEC850_LD_HU ) + displ_op->addr = short(displ_op->addr); + } +#ifdef __EA64__ + if ( displ_op->type == o_mem ) + { + // truncate address to 32 bits if needed + segment_t *s = getseg(displ_op->addr); + if ( s == NULL || !s->is_64bit() ) + displ_op->addr = uint32(displ_op->addr); + } +#endif + } + return ins.itype != 0; +} + +//------------------------------------------------------------------------ +// Analyze one instruction and fill 'insn' structure. +// insn.ea contains address of instruction to analyze. +// Return length of the instruction in bytes, 0 if instruction can't be decoded. +// This function shouldn't change the database, flags or anything else. +// All these actions should be performed only by u_emu() function. +int nec850_t::nec850_ana(insn_t *pinsn) +{ + insn_t &insn = *pinsn; + if ( insn.ea & 0x1 ) + return 0; + + uint32 w; + fetch_instruction(&w, insn); + if ( decode_instruction(w, insn) ) + return insn.size; + else + return 0; +} diff --git a/idasdk76/module/nec850/emu.cpp b/idasdk76/module/nec850/emu.cpp new file mode 100644 index 0000000..4255b5e --- /dev/null +++ b/idasdk76/module/nec850/emu.cpp @@ -0,0 +1,1299 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) Hex-Rays + * ALL RIGHTS RESERVED. + * + * Processor emulator + * + */ +#include <ida.hpp> +#include <auto.hpp> +#include <frame.hpp> +#include <jumptable.hpp> +#include "ins.hpp" +#include "necv850.hpp" + +//---------------------------------------------------------------------- +//#notify.is_sane_insn +// is the instruction sane for the current file type? +// arg: int no_crefs +// 1: the instruction has no code refs to it. +// ida just tries to convert unexplored bytes +// to an instruction (but there is no other +// reason to convert them into an instruction) +// 0: the instruction is created because +// of some coderef, user request or another +// weighty reason. +// The instruction is in 'cmd' +// returns: 1-ok, <=0-no, the instruction isn't likely to appear in the program +int nec850_t::nec850_is_sane_insn(const insn_t &insn, int /*no_crefs*/) const +{ +#define CHECK_R0_WRITE(n) \ + if ( ((Feature & CF_CHG ## n) != 0) \ + && insn.Op ## n.is_reg(rZERO) ) \ + { \ + return 0; \ + } + int Feature = insn.get_canon_feature(ph); + + CHECK_R0_WRITE(1); + CHECK_R0_WRITE(2); + return 1; +} + +//---------------------------------------------------------------------- +int idaapi nec850_is_sp_based(const insn_t &insn, const op_t &x) +{ + int res = OP_SP_ADD; + if ( x.type == o_displ && x.reg == rSP ) + return res | OP_SP_BASED; + + // check for movea 8, sp, r28 + if ( insn.itype == NEC850_MOVEA && insn.Op2.is_reg(rSP) && x.type == o_imm ) + return res | OP_SP_BASED; + + return res | OP_FP_BASED; +} + +//---------------------------------------------------------------------- +bool idaapi nec850_create_func_frame(func_t *pfn) +{ + asize_t frsize; + + insn_t insn; + if ( decode_insn(&insn, pfn->start_ea) != 0 + && (insn.itype == NEC850_PREPARE_i || insn.itype == NEC850_PREPARE_sp) ) + { + frsize = insn.Op2.value * 4; + } + else + { + frsize = 0; + } + return add_frame(pfn, frsize, 0, 0); +} + +//---------------------------------------------------------------------- +int idaapi nec850_get_frame_retsize(const func_t * /*pfn*/) +{ + return 0; +} + +//---------------------------------------------------------------------- +static bool spoils(const insn_t &insn, uint16 reg) +{ + int n; + switch ( insn.itype ) + { + case NEC850_ZXB: + case NEC850_SXB: + case NEC850_ZXH: + case NEC850_SXH: + n = 0; + break; + + case NEC850_XOR: + case NEC850_SUBR: + case NEC850_SUB: + case NEC850_STSR: + case NEC850_SLD_B: + case NEC850_SLD_H: + case NEC850_SLD_W: + case NEC850_SHR: + case NEC850_SHL: + case NEC850_SATSUBR: + case NEC850_SATSUB: + case NEC850_SATADD: + case NEC850_SAR: + case NEC850_OR: + case NEC850_NOT: + case NEC850_MULH: + case NEC850_MOV: + case NEC850_LD_B: + case NEC850_LD_H: + case NEC850_LD_W: + case NEC850_JARL: + case NEC850_AND: + case NEC850_ADD: + case NEC850_DIVH: + case NEC850_BSW: + case NEC850_BSH: + case NEC850_HSW: + case NEC850_SLD_BU: + case NEC850_SLD_HU: + case NEC850_LD_BU: + case NEC850_LD_HU: + n = 1; + break; + + case NEC850_XORI: + case NEC850_SATSUBI: + case NEC850_ORI: + case NEC850_MULHI: + case NEC850_MOVHI: + case NEC850_MOVEA: + case NEC850_ANDI: + case NEC850_ADDI: + case NEC850_SETF: + case NEC850_SASF: + n = 2; + break; + + case NEC850_CMOV: + n = 4; + break; + + case NEC850_MUL: + case NEC850_MULU: + case NEC850_DIVH_r3: + case NEC850_DIVHU: + case NEC850_DIV: + case NEC850_DIVU: + return insn.ops[1].is_reg(reg) || insn.ops[2].is_reg(reg); + + case NEC850_DISPOSE_r0: + case NEC850_DISPOSE_r: + return reg == rSP || reg_in_list12(reg, insn.Op2.value); + + case NEC850_PREPARE_sp: + return reg == rSP; + + case NEC850_PREPARE_i: + return reg == rSP || reg == rEP; + + default: + return false; + } + return insn.ops[n].is_reg(reg); +} + +//---------------------------------------------------------------------- +// does the instruction spoil the flags? +static bool spoils_flags(const insn_t &insn) +{ + switch ( insn.itype ) + { + case NEC850_ADD: + case NEC850_ADDI: + case NEC850_ADF: + case NEC850_AND: + case NEC850_ANDI: + case NEC850_BSH: + case NEC850_BSW: + case NEC850_CAXI: + case NEC850_CLR1: + case NEC850_CMP: + case NEC850_CTRET: + case NEC850_DIV: + case NEC850_DIVH: + case NEC850_DIVHU: + case NEC850_DIVH_r3: + case NEC850_DIVQ: + case NEC850_DIVQU: + case NEC850_DIVU: + case NEC850_EIRET: + case NEC850_FERET: + case NEC850_HSH: + case NEC850_HSW: + case NEC850_NOT: + case NEC850_NOT1: + case NEC850_OR: + case NEC850_ORI: + case NEC850_RETI: + case NEC850_SAR: + case NEC850_SATADD: + case NEC850_SATSUB: + case NEC850_SATSUBI: + case NEC850_SATSUBR: + case NEC850_SBF: + case NEC850_SCH0L: + case NEC850_SCH0R: + case NEC850_SCH1L: + case NEC850_SCH1R: + case NEC850_SET1: + case NEC850_SHL: + case NEC850_SHR: + case NEC850_SUB: + case NEC850_SUBR: + case NEC850_TST: + case NEC850_TST1: + case NEC850_XOR: + case NEC850_XORI: + + case NEC850_BINS: + case NEC850_ROTL: + return true; + + default: + // other insns don't spoil fixed point flags + return false; + } +} + +//---------------------------------------------------------------------- +bool nec850_t::get_gp_based_addr(ea_t *target, const insn_t &_insn, const op_t &op) const +{ + if ( g_gp_ea == BADADDR ) + return false; + if ( op.phrase == rGP ) + { + *target = g_gp_ea; + return true; + } + uint16 op_phrase = op.phrase; + *target = BADADDR; + insn_t tmp = _insn; + while ( true ) + { + flags_t F = get_flags(tmp.ea); + if ( !is_flow(F) || has_xref(F) ) + break; + if ( decode_prev_insn(&tmp, tmp.ea) == BADADDR ) + break; + + if ( tmp.itype == NEC850_MOVEA + && tmp.Op2.reg == rGP + && tmp.Op3.reg == op_phrase ) + { + *target = g_gp_ea + tmp.Op1.value; + break; + } + + if ( spoils(tmp, op_phrase) ) + break; + } + return *target != BADADDR; +} + +//---------------------------------------------------------------------- +void nec850_t::handle_operand(const insn_t &insn, const op_t &op, bool isRead) +{ + ea_t ea; + flags_t F = get_flags(insn.ea); + switch ( op.type ) + { + case o_imm: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, dr_O, 0); + break; + + case o_displ: + set_immd(insn.ea); + if ( !is_defarg(F, op.n) ) + { + if ( may_create_stkvars() && op.reg == rSP ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL && insn.create_stkvar(op, op.addr, STKVAR_VALID_SIZE) ) + op_stkvar(insn.ea, op.n); + } + else if ( get_gp_based_addr(&ea, insn, op) ) + { + refinfo_t ri; + ri.flags = REF_OFF32|REFINFO_PASTEND|REFINFO_NOBASE|REFINFO_SIGNEDOP; + ri.target = BADADDR; + ri.base = ea; + ri.tdelta = 0; + op_offset_ex(insn.ea, op.n, &ri); + F = get_flags(insn.ea); + } + } + + if ( op_adds_xrefs(F, op.n) ) + { // create data xrefs + ea_t base_ea; + if ( get_gp_based_addr(&base_ea, insn, op) ) + { + ea = base_ea + op.addr; + insn.add_dref(ea, op.offb, isRead ? dr_R : dr_W); + } + else + { + int outf = get_displ_outf(insn, op, F); + ea = insn.add_off_drefs(op, isRead ? dr_R : dr_W, outf); + } + if ( ea != BADADDR ) + insn.create_op_data(ea, op); + } + break; + + case o_near: + { + bool iscall = has_insn_feature(insn.itype, CF_CALL); + + ea_t dest = to_ea(insn.cs, op.addr); + if ( dest == insn.ea + insn.size ) + { + // PIC pattern: + // jarl nextaddr, r29 + // nextaddr: + iscall = false; + } + insn.add_cref(dest, op.offb, iscall ? fl_CN : fl_JN); + if ( flow && iscall ) + { + if ( !func_does_return(dest) ) + flow = false; + } + } + break; + + case o_mem: + { + ea = to_ea(insn.cs, op.addr); + insn.create_op_data(ea, op); + insn.add_dref(op.addr, op.offb, isRead ? dr_R : dr_W); + } + break; + } +} + +//---------------------------------------------------------------------- +static void idaapi trace_stack(func_t *pfn, const insn_t &insn) +{ + sval_t delta; + switch ( insn.itype ) + { + case NEC850_PREPARE_i: + case NEC850_PREPARE_sp: + { + delta = -((bitcount(insn.Op1.value) * 4) + (insn.Op2.value << 2)); + + // PATTERN #1 + /* + 00000030 _func3: + 00000030 000 br loc_5E + 00000032 + 00000032 loc_32: -- CODE XREF: _func3+32j + 00000032 000 st.w r6, 4[sp] + 0000005A + 0000005A loc_5A: -- CODE XREF: _func3+10j + 0000005A -- _func3+14j ... + 0000005A 000 dispose 2, {lp}, [lp] + 0000005E -- --------------------------------------------------------------------------- + 0000005E + 0000005E loc_5E: -- CODE XREF: _func3 + 0000005E -0C prepare {lp}, 2 + 00000062 000 br loc_32 + 00000062 -- End of function _func3 + */ + bool farref; + insn_t tmp; + if ( decode_preceding_insn(&tmp, insn.ea, &farref) != BADADDR + && (tmp.itype == NEC850_BR || tmp.itype == NEC850_JR) + && tmp.Op1.addr == insn.ea + && func_contains(pfn, tmp.ea) ) + { + add_auto_stkpnt(pfn, tmp.ea + tmp.size, delta); + } + } + break; + case NEC850_DISPOSE_r: + case NEC850_DISPOSE_r0: + // count registers in LIST12 and use the imm5 for local vars + delta = (bitcount(insn.Op2.value) * 4) + (insn.Op1.value << 2); + break; + case NEC850_ADD: + case NEC850_ADDI: + case NEC850_MOVEA: + delta = insn.Op1.value; + break; + default: + return; + } + add_auto_stkpnt(pfn, insn.ea + insn.size, delta); +} + +//---------------------------------------------------------------------- +// pattern: +// mov #address, lp +// jmp [reg1] +// address: +// flow to the next instruction +static bool indirect_function_call(const insn_t &_insn) +{ + if ( _insn.itype != NEC850_JMP || _insn.Op1.is_reg(rLP) ) + return false; + + insn_t insn = _insn; + ea_t ret_addr = insn.ea + insn.size; // after the jmp + + bool flows = false; + while ( decode_prev_insn(&insn, insn.ea) != BADADDR ) + { + if ( insn.itype == NEC850_MOV + && insn.Op1.type == o_imm + && insn.Op1.dtype == dt_dword + && insn.Op2.is_reg(rLP) ) + { // MOV #address, lp + op_offset(insn.ea, 0, REF_OFF32); + if ( insn.Op1.value == ret_addr ) + { // normal return, after the jmp instruction + flows = true; + } + else + { // add xref to return address + add_cref(_insn.ea, insn.Op1.value, fl_JN); + } + break; + } + + if ( spoils(insn, rLP) ) + break; + + flags_t F = get_flags(insn.ea); + if ( !is_flow(F) || has_xref(F) ) + break; + } + return flows; +} + +//---------------------------------------------------------------------- +int nec850_t::nec850_emu(const insn_t &insn) +{ + int aux = insn.auxpref; + + int Feature = insn.get_canon_feature(ph); + flow = (Feature & CF_STOP) == 0; + + if ( Feature & CF_USE1 ) + handle_operand(insn, insn.Op1, true); + if ( Feature & CF_CHG1 ) + handle_operand(insn, insn.Op1, false); + if ( Feature & CF_USE2 ) + handle_operand(insn, insn.Op2, true); + if ( Feature & CF_CHG2 ) + handle_operand(insn, insn.Op2, false); + if ( Feature & CF_USE3 ) + handle_operand(insn, insn.Op3, true); + if ( Feature & CF_CHG3 ) + handle_operand(insn, insn.Op3, false); + + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + flags_t F = get_flags(insn.ea); + if ( insn.itype == NEC850_MOVEA + && insn.Op1.type == o_imm + && !is_defarg(F, insn.Op1.n) ) + { + // movea imm16, sp, reg (reg != sp) + if ( insn.Op2.is_reg(rSP) + && !insn.Op3.is_reg(rSP) + && may_create_stkvars() + && insn.create_stkvar(insn.Op1, insn.Op1.value, 0) ) + { + op_stkvar(insn.ea, insn.Op1.n); + } + else if ( insn.Op2.is_reg(rGP) + && g_gp_ea != BADADDR ) + { + ea_t ea = g_gp_ea + insn.Op1.value; + + refinfo_t ri; + ri.flags = REF_OFF32|REFINFO_PASTEND|REFINFO_SIGNEDOP|REFINFO_NOBASE; + ri.target = BADADDR; + ri.base = g_gp_ea; + ri.tdelta = 0; + op_offset_ex(insn.ea, insn.Op1.n, &ri); + F = get_flags(insn.ea); + if ( op_adds_xrefs(F, insn.Op1.n) ) + insn.add_dref(ea, insn.Op1.offb, dr_O); + } + } + + // add dref to callt table entry address + if ( insn.itype == NEC850_CALLT + && g_ctbp_ea != BADADDR ) + { + ea_t ea = g_ctbp_ea + (insn.Op1.value << 1); + insn.create_op_data(ea, insn.Op1.offb, dt_word); + insn.add_dref(ea, insn.Op1.offb, dr_R); + } + + if ( indirect_function_call(insn) ) + flow = true; + + if ( (aux & N850F_SP) && may_trace_sp() ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL ) + trace_stack(pfn, insn); + } + + // add flow + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + return 1; +} + +//---------------------------------------------------------------------- +int nec850_may_be_func(const insn_t &insn) +{ + int prop = 0; + if ( insn.itype == NEC850_PREPARE_i || insn.itype == NEC850_PREPARE_sp ) + prop = 100; + return prop; +} + +//---------------------------------------------------------------------- +inline bool is_ret_itype(const insn_t &insn) +{ + return insn.itype == NEC850_RETI + || insn.itype == NEC850_DBRET + || insn.itype == NEC850_CTRET + || insn.itype == NEC850_DISPOSE_r + || insn.itype == NEC850_JMP && insn.Op1.is_reg(rLP); +} + +//---------------------------------------------------------------------- +bool nec850_is_return(const insn_t &insn, bool strict) +{ + if ( is_ret_itype(insn) ) + return true; + if ( insn.itype == NEC850_DISPOSE_r0 ) + return !strict; + return false; +} + +//------------------------------------------------------------------------- +static bool find_set( + ea_t *value, + ea_t *valea, + insn_t insn, // make a copy + int reg) +{ + simple_bfi_t bfi(insn.ea); + while ( true ) + { + cref_t prev_insn_ref = bfi.prev_insn(); + if ( prev_insn_ref == fl_U || decode_insn(&insn, bfi.cur_ea) <= 0 ) + break; + switch ( insn.itype ) + { + case NEC850_MOV: + if ( insn.Op2.is_reg(reg) && insn.Op1.type == o_reg ) + { + reg = insn.Op1.reg; + continue; + } + if ( insn.Op2.is_reg(reg) && insn.Op1.type == o_imm ) + { + *value = insn.Op1.value; + *valea = insn.ea; + return true; + } + break; + case NEC850_ADDI: + case NEC850_MOVEA: + if ( insn.Op3.is_reg(reg) + && insn.Op1.type == o_imm + && insn.Op2.is_reg(rZERO) ) + { + *value = insn.Op1.value; + *valea = insn.ea; + return true; + } + break; + } + if ( spoils(insn, reg) ) + break; + } + return false; +} + +//------------------------------------------------------------------------- +struct nec850_jump_pattern_t : public jump_pattern_t +{ +protected: + enum { rA, rC }; + + nec850_jump_pattern_t(switch_info_t *_si, const char (*_depends)[4]) + : jump_pattern_t(_si, _depends, rC) + { + modifying_r32_spoils_r64 = false; + non_spoiled_reg = rA; + } + +public: + virtual bool handle_mov(tracked_regs_t &_regs) override; + virtual void check_spoiled(tracked_regs_t *_regs) const override; + +protected: + // movea -minv, rA', rA | add -minv, rA + bool jpi_sub_lowcase(); + // cmp followed by the conditional jump + // it calls jpi_condjump() and jpi_cmp_ncases() that can be redefined in + // the derived class. + bool jpi_cmp_ncases_condjump(); + // switch rA + bool jpi_jump(); + + // bh default + virtual bool jpi_condjump() newapi; + // cmp ncases, rA + virtual bool jpi_cmp_ncases() newapi; +}; + +//------------------------------------------------------------------------- +bool nec850_jump_pattern_t::handle_mov(tracked_regs_t &_regs) +{ + if ( insn.itype != NEC850_MOV + && insn.Op1.type != o_reg + && insn.Op2.type != o_reg ) + { + return false; + } + return set_moved(insn.Op2, insn.Op1, _regs); +} + +//------------------------------------------------------------------------- +#define PROC_MAXCHGOP 3 +void nec850_jump_pattern_t::check_spoiled(tracked_regs_t *__regs) const +{ + tracked_regs_t &_regs = *__regs; + for ( uint i = 0; i < _regs.size(); ++i ) + { + const op_t &x = _regs[i]; + if ( x.type == o_reg && spoils(insn, x.reg) + || x.type == o_condjump && spoils_flags(insn) ) + { + set_spoiled(&_regs, x); + } + } + check_spoiled_not_reg(&_regs, PROC_MAXCHGOP); +} + +//---------------------------------------------------------------------- +// movea -minv, rA', rA | add -minv, rA +bool nec850_jump_pattern_t::jpi_sub_lowcase() +{ + if ( insn.itype == NEC850_MOVEA ) + { + if ( insn.Op1.type != o_imm + || insn.Op2.type != o_reg + || !is_equal(insn.Op3, rA) ) + { + return false; + } + trackop(insn.Op2, rA); + } + else if ( insn.itype == NEC850_ADD ) + { + if ( insn.Op1.type != o_imm || !is_equal(insn.Op2, rA) ) + return false; + } + else + { + return false; + } + si->lowcase = uval_t(-uint32(insn.Op1.value)); + return true; +} + +//------------------------------------------------------------------------- +// cmp followed by the conditional jump +bool nec850_jump_pattern_t::jpi_cmp_ncases_condjump(void) +{ + // var should not be spoiled + QASSERT(10317, !is_spoiled(rA)); + + if ( jpi_condjump() // continue matching if found + || is_spoiled(rC) + || !jpi_cmp_ncases() ) + { + return false; + } + + op_t &op = regs[rC]; + // assert: op.type == o_condjump + if ( (op.value & cc_inc_ncases) != 0 ) + ++si->ncases; + si->defjump = op.specval; + si->set_expr(insn.Op1.reg, insn.Op1.dtype); + return true; +} + +//---------------------------------------------------------------------- +// switch rA +bool nec850_jump_pattern_t::jpi_jump() +{ + if ( insn.itype != NEC850_SWITCH + || insn.Op1.type != o_reg + || insn.Op1.reg == rZERO ) + { + return false; + } + + si->jumps = insn.ea + insn.size; + si->set_elbase(si->jumps); + si->flags |= SWI_SIGNED; + si->set_jtable_element_size(2); + si->set_shift(1); + si->set_expr(insn.Op1.reg, dt_dword); + trackop(insn.Op1, rA); + return true; +} + +//---------------------------------------------------------------------- +// bh default +bool nec850_jump_pattern_t::jpi_condjump() +{ + op_t op; + op.type = o_condjump; + op.value = 0; + switch ( insn.itype ) + { + case NEC850_BH: // higher + case NEC850_BNH: // not higher + op.value |= cc_inc_ncases; + break; + case NEC850_BL: // lower + case NEC850_BNC: // no carry (not lower) + break; + default: + return false; + } + ea_t jump = to_ea(insn.cs, insn.Op1.addr); + switch ( insn.itype ) + { + case NEC850_BH: + case NEC850_BNC: + op.specval = jump; + break; + case NEC850_BL: + case NEC850_BNH: + // we have conditional jump to the switch body + // assert: eas[0] != BADADDR + if ( jump > eas[0] ) + return false; + op.specval = insn.ea + insn.size; + + // possibly followed by 'jr default' + { + insn_t deflt; + if ( decode_insn(&deflt, op.specval) > 0 + && deflt.itype == NEC850_JR + && deflt.Op1.type == o_near ) + { + op.specval = deflt.Op1.addr; + } + } + break; + default: + return false; + } + op.addr = insn.ea; + trackop(op, rC); + return true; +} + +//---------------------------------------------------------------------- +// cmp ncases, rA +bool nec850_jump_pattern_t::jpi_cmp_ncases() +{ + if ( insn.itype != NEC850_CMP + || insn.Op1.type != o_imm && insn.Op1.type != o_reg + || !same_value(insn.Op2, rA) ) + { + return false; + } + + const op_t &x = insn.Op1; + uval_t val; + ea_t dummy; + if ( x.type == o_imm ) + val = x.value; + // assert: x.type == o_reg + else if ( !find_set(&val, &dummy, insn, x.reg) ) + return false; + si->ncases = ushort(val); + return true; +} + +//---------------------------------------------------------------------- +// jump pattern #1 +// 2 movea -minv, rA', rA | add -minv, rA (optional) +// 1 cmp ncases, rA | cmp rNcases, rA +// bh default (nearest to "cmp") +// 0 switch rA +// 0 -> 1 -> 2 + +static const char nec850_depends1[][4] = +{ + { 1 }, // 0 + { 2 | JPT_OPT | JPT_NEAR }, // 1 + { 0 }, // 2 optional, near +}; + +//------------------------------------------------------------------------- +class nec850_jump_pattern1_t : public nec850_jump_pattern_t +{ +public: + nec850_jump_pattern1_t(switch_info_t *_si) + : nec850_jump_pattern_t(_si, nec850_depends1) {} + + virtual bool jpi2(void) override { return jpi_sub_lowcase(); } + virtual bool jpi1(void) override { return jpi_cmp_ncases_condjump(); } + virtual bool jpi0(void) override { return jpi_jump(); } +}; + +//---------------------------------------------------------------------- +static int is_jump_pattern1(switch_info_t *si, const insn_t &insn, procmod_t *) +{ + nec850_jump_pattern1_t jp(si); + if ( !jp.match(insn) ) + return JT_NONE; + return JT_SWITCH; +} + +//---------------------------------------------------------------------- +// jump pattern #2 (addi instead of cmp) +// 2 movea -minv, rA', rA | add -minv, rA (optional) +// 1 addi -ncases, rA, r0 +// bl default (nearest to "cmp") +// 0 switch rA +// 0 -> 1 -> 2 + +static const char nec850_depends2[][4] = +{ + { 1 }, // 0 + { 2 | JPT_OPT | JPT_NEAR }, // 1 + { 0 }, // 2 optional, near +}; + +//------------------------------------------------------------------------- +class nec850_jump_pattern2_t : public nec850_jump_pattern_t +{ +public: + nec850_jump_pattern2_t(switch_info_t *_si) + : nec850_jump_pattern_t(_si, nec850_depends2) {} + + bool jpi2(void) override { return jpi_sub_lowcase(); } + bool jpi1(void) override { return jpi_cmp_ncases_condjump(); } + bool jpi0(void) override { return jpi_jump(); } + +protected: + // bl default + bool jpi_condjump() override; + // addi -ncases, rA, r0 + bool jpi_cmp_ncases() override; +}; + +//---------------------------------------------------------------------- +// bl default +bool nec850_jump_pattern2_t::jpi_condjump() +{ + op_t op; + op.type = o_condjump; + op.value = 0; + switch ( insn.itype ) + { + case NEC850_BH: // higher + op.value |= cc_inc_ncases; + break; + case NEC850_BL: // lower + break; + default: + return false; + } + ea_t jump = to_ea(insn.cs, insn.Op1.addr); + switch ( insn.itype ) + { + case NEC850_BL: + op.specval = jump; + break; + case NEC850_BH: + // we have conditional jump to the switch body + // assert: eas[0] != BADADDR + if ( jump > eas[0] ) + return false; + op.specval = insn.ea + insn.size; + break; + default: + return false; + } + op.addr = insn.ea; + trackop(op, rC); + return true; +} + +//---------------------------------------------------------------------- +// addi -ncases, rA, r0 +bool nec850_jump_pattern2_t::jpi_cmp_ncases() +{ + if ( insn.itype != NEC850_ADDI + || insn.Op1.type != o_imm + || !insn.Op3.is_reg(rZERO) + || !same_value(insn.Op2, rA) ) + { + return false; + } + + si->ncases = ushort(-uint32(insn.Op1.value)); + return true; +} + +//---------------------------------------------------------------------- +static int is_jump_pattern2(switch_info_t *si, const insn_t &insn, procmod_t *) +{ + nec850_jump_pattern2_t jp(si); + if ( !jp.match(insn) ) + return JT_NONE; + return JT_SWITCH; +} + +//---------------------------------------------------------------------- +// jump pattern #3 (without 'switch' insn) +// 3 movea -minv, rA', rA | add -minv, rA (optional) +// 2 cmp ncases, rA | cmp rNcases, rA +// bh default (nearest to "cmp") +// 1 shl 2, rA | shl 1, rA +// 0 jmp jumps[rA] +// +// jumps: jr case0 (4 bytes) | (2 bytes) +// jr case1 +// ... +// +// 0 -> 1 -> 2 -> 3 + +static const char nec850_depends3[][4] = +{ + { 1 }, // 0 + { 2 }, // 1 + { 3 | JPT_OPT | JPT_NEAR }, // 2 + { 0 }, // 3 optional, near +}; + +//------------------------------------------------------------------------- +class nec850_jump_pattern3_t : public nec850_jump_pattern_t +{ +public: + nec850_jump_pattern3_t(switch_info_t *_si) + : nec850_jump_pattern_t(_si, nec850_depends3) + { + si->flags |= SWI_JMPINSN; + } + + virtual bool jpi3(void) override { return jpi_sub_lowcase(); } + virtual bool jpi2(void) override { return jpi_cmp_ncases_condjump(); } + virtual bool jpi1(void) override; // shl shift, rA + virtual bool jpi0(void) override; // jmp jumps[rA] +}; + +//---------------------------------------------------------------------- +// shl shift, rA +bool nec850_jump_pattern3_t::jpi1() +{ + if ( insn.itype != NEC850_SHL + || insn.Op1.type != o_imm + || !same_value(insn.Op2, rA) ) + { + return false; + } + int elsize; + if ( insn.Op1.value == 1 ) + elsize = 2; + else if ( insn.Op1.value == 2 ) + elsize = 4; + else + return false; + si->set_jtable_element_size(elsize); + return true; +} + +//---------------------------------------------------------------------- +// jmp jumps[rA] +bool nec850_jump_pattern3_t::jpi0() +{ + if ( insn.itype != NEC850_JMP || insn.Op1.type != o_displ ) + return false; + si->jumps = insn.Op1.addr; + track(insn.Op1.phrase, rA, dt_dword); + return true; +} + +//---------------------------------------------------------------------- +static int is_jump_pattern3(switch_info_t *si, const insn_t &insn, procmod_t *) +{ + nec850_jump_pattern3_t jp(si); + if ( !jp.match(insn) ) + return JT_NONE; + op_offset(jp.eas[0], 0, REFINFO_NOBASE | REF_OFF32); + // rollback data created in handle_operand() + del_items(si->jumps, DELIT_SIMPLE); + return JT_SWITCH; +} + +//---------------------------------------------------------------------- +bool idaapi nec850_is_switch(switch_info_t *si, const insn_t &insn) +{ + if ( insn.itype != NEC850_SWITCH && insn.itype != NEC850_JMP ) + return false; + + static is_pattern_t *const patterns[] = + { + is_jump_pattern1, + is_jump_pattern2, + is_jump_pattern3, + }; + return check_for_table_jump(si, insn, patterns, qnumber(patterns)); +} + +//------------------------------------------------------------------------- +sval_t nec850_t::regval( + const op_t &op, + getreg_t *getreg, + const regval_t *rv) const +{ + if ( op.reg > rSR31 ) + { + warning("Bad register number passed to nec850.get_register_value: %d", op.reg); + return 0; + } + return sval_t(getreg(ph.reg_names[op.reg], rv).ival); +} + +//------------------------------------------------------------------------- +static bool is_bcond(int itype) +{ + return itype == NEC850_BV + || itype == NEC850_BL + || itype == NEC850_BZ + || itype == NEC850_BNH + || itype == NEC850_BN + || itype == NEC850_BR + || itype == NEC850_BLT + || itype == NEC850_BLE + || itype == NEC850_BNV + || itype == NEC850_BNC + || itype == NEC850_BNZ + || itype == NEC850_BH + || itype == NEC850_BP + || itype == NEC850_BSA + || itype == NEC850_BGE + || itype == NEC850_BGT; +} + +//------------------------------------------------------------------------- +ea_t nec850_t::nec850_next_exec_insn( + ea_t ea, + getreg_t *getreg, + const regval_t *regvalues) const +{ + insn_t insn; + if ( decode_insn(&insn, ea) < 1 ) + return BADADDR; + + // First check for Bcond. + if ( is_bcond(insn.itype) ) + { + uint32_t PSW = getreg("PSW", regvalues).ival; + bool Z = (PSW & (1 << 0)) != 0; + bool S = (PSW & (1 << 1)) != 0; + bool OV = (PSW & (1 << 2)) != 0; + bool CY = (PSW & (1 << 3)) != 0; + bool SAT = (PSW & (1 << 4)) != 0; + bool condition = false; + switch ( insn.itype ) + { + case NEC850_BV: condition = OV; break; + case NEC850_BL: condition = CY; break; + case NEC850_BZ: condition = Z; break; + case NEC850_BNH: condition = (CY || Z); break; + case NEC850_BN: condition = S; break; + case NEC850_BR: condition = true; break; + case NEC850_BLT: condition = (S != OV); break; + case NEC850_BLE: condition = ((S != OV) || Z); break; + case NEC850_BNV: condition = !OV; break; + case NEC850_BNC: condition = !CY; break; + case NEC850_BNZ: condition = !Z; break; + case NEC850_BH: condition = !(CY || Z); break; + case NEC850_BP: condition = !S; break; + case NEC850_BSA: condition = SAT; break; + case NEC850_BGE: condition = !(S != OV); break; + case NEC850_BGT: condition = !((S != OV) || Z); break; + } + ea_t target = condition ? insn.Op1.addr : BADADDR; + return target; + } + + // Then check for other instructions. + ea_t target = BADADDR; + switch ( insn.itype ) + { + case NEC850_RETI: + { + uint32_t PSW = getreg("PSW", regvalues).ival; + if ( (PSW & (1 << 6)) != 0 ) // PSW.EP + { + target = getreg("EIPC", regvalues).ival; + } + else + { + if ( (PSW & (1 << 7)) != 0 ) // PSW.NP + target = getreg("FEPC", regvalues).ival; + else + target = getreg("EIPC", regvalues).ival; + } + } + break; + + case NEC850_JR: + target = insn.Op1.addr; + break; + + case NEC850_JMP: + target = regval(insn.Op1, getreg, regvalues) + insn.Op1.addr; + break; + + case NEC850_JARL: + if ( insn.Op1.type == o_reg ) + target = regval(insn.Op1, getreg, regvalues); + else + target = insn.Op1.addr; + break; + + case NEC850_SWITCH: + // TODO + break; + + case NEC850_DISPOSE_r: + target = regval(insn.Op3, getreg, regvalues); + break; + + case NEC850_CALLT: + target = insn.Op1.addr; + break; + + case NEC850_CTRET: + target = getreg("CTPC", regvalues).ival; + break; + + case NEC850_EIRET: + target = getreg("EIPC", regvalues).ival; + break; + + case NEC850_FERET: + target = getreg("FEPC", regvalues).ival; + break; + + case NEC850_LOOP: + if ( regval(insn.Op1, getreg, regvalues) - 1 != 0 ) + target = insn.Op2.addr; + break; + + case NEC850_DBHVTRAP: + case NEC850_DBRET: + case NEC850_DBTRAP: + case NEC850_FETRAP: + case NEC850_HALT: + case NEC850_HVCALL: + case NEC850_HVTRAP: + case NEC850_RIE: + case NEC850_RMTRAP: + case NEC850_SYSCALL: + case NEC850_TRAP: + // TODO + break; + } + + return target; +} + +//------------------------------------------------------------------------- +ea_t nec850_t::nec850_calc_step_over(ea_t ip) const +{ + insn_t insn; + if ( ip == BADADDR || decode_insn(&insn, ip) < 1 ) + return BADADDR; + + bool step_over = is_call_insn(insn) + || insn.itype == NEC850_LOOP; + if ( step_over ) + return insn.ea + insn.size; + + return BADADDR; +} + +//------------------------------------------------------------------------- +bool nec850_t::nec850_get_operand_info( + idd_opinfo_t *opinf, + ea_t ea, + int n, + getreg_t *getreg, + const regval_t *regvalues) +{ + if ( n < 0 || n > 4 ) // check the operand number + return false; + insn_t insn; + if ( decode_insn(&insn, ea) < 1 ) + return false; + + // TODO check for op.type == o_cond? + opinf->modified = has_cf_chg(insn.get_canon_feature(ph), n); + + uint64 v = 0; + const op_t &op = insn.ops[n]; + switch ( op.type ) + { + case o_imm: + v = op.value; + break; + + case o_mem: + case o_near: + opinf->ea = op.addr; + break; + + case o_reg: + v = regval(op, getreg, regvalues); + break; + + case o_displ: + // TODO + break; + + case o_reglist: + case o_regrange: + // TODO how to represent multiple registers? + break; + + default: + return false; + } + opinf->value._set_int(v); + opinf->value_size = get_dtype_size(op.dtype); + return true; +} + +//-------------------------------------------------------------------------- +int nec850_t::nec850_get_reg_index(const char *name) const +{ + if ( name == NULL || name[0] == '\0' ) + return -1; + for ( size_t i = 0; i < ph.regs_num; i++ ) + if ( stricmp(ph.reg_names[i], name) == 0 ) + return i; + return -1; +} + +//-------------------------------------------------------------------------- +bool nec850_t::nec850_get_reg_info( + const char **main_regname, + bitrange_t *bitrange, + const char *regname) +{ + int regnum = nec850_get_reg_index(regname); + if ( regnum == -1 ) + return false; + + if ( bitrange != NULL ) + *bitrange = bitrange_t(0, 32); + + if ( main_regname != NULL ) + *main_regname = ph.reg_names[regnum]; + + return true; +} diff --git a/idasdk76/module/nec850/ins.cpp b/idasdk76/module/nec850/ins.cpp new file mode 100644 index 0000000..0092686 --- /dev/null +++ b/idasdk76/module/nec850/ins.cpp @@ -0,0 +1,299 @@ +/* +* Interactive disassembler (IDA). +* Copyright (c) 1990-2021 Hex-Rays +* ALL RIGHTS RESERVED. +* +*/ + +#include "ins.hpp" + +const instruc_t Instructions[NEC850_LAST_INSTRUCTION] = +{ + { "", 0 }, // Unknown Operation + + { "breakpoint", CF_STOP }, // undefined instruction + { "xori", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive Or Immediate + { "xor", CF_USE1|CF_USE2|CF_CHG2 }, // Exclusive OR + { "tst1", CF_USE1|CF_USE2 }, // Test bit + { "tst", CF_USE1|CF_USE2 }, // Test + { "trap", CF_USE1 }, // Software trap + { "subr", CF_USE1|CF_USE2|CF_CHG2 }, // Substract reverse + { "sub", CF_USE1|CF_USE2|CF_CHG2 }, // Substract + { "stsr", CF_USE1|CF_CHG2 }, // Store Contents of System Register + { "st.b", CF_USE1|CF_USE2|CF_CHG2 }, // Store byte + { "st.h", CF_USE1|CF_USE2|CF_CHG2 }, // Store half-word + { "st.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store word + { "sst.b", CF_USE1|CF_USE2|CF_CHG2 }, // Store byte (use EP) + { "sst.h", CF_USE1|CF_USE2|CF_CHG2 }, // Store half-word (use EP) + { "sst.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store word (use EP) + { "sld.b", CF_USE1|CF_CHG2 }, // Load byte (use EP) + { "sld.h", CF_USE1|CF_CHG2 }, // Load half-word (use EP) + { "sld.w", CF_USE1|CF_CHG2 }, // Load word (use EP) + { "shr", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Logical Right + { "shl", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Logical Left + { "set1", CF_USE1|CF_USE2|CF_CHG2 }, // Set Bit + { "setf", CF_USE1|CF_CHG2 }, // Set register to 1 if condition is satisfied + { "satsubr", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Subtract Reverse + { "satsubi", CF_USE1|CF_USE2|CF_CHG3 }, // Saturated Subtract Immediate + { "satsub", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Subtract + { "satadd", CF_USE1|CF_USE2|CF_CHG2 }, // Saturated Add + { "sar", CF_USE1|CF_USE2|CF_CHG2|CF_SHFT }, // Shift Arithmetic Right + { "reti", CF_STOP }, // Return from Trap or Interrupt + { "ori", CF_USE1|CF_USE2|CF_CHG2 }, // OR immediate + { "or", CF_USE1|CF_USE2|CF_CHG2 }, // OR + { "not1", CF_USE1|CF_USE2|CF_CHG2 }, // Not Bit + { "not", CF_USE1|CF_USE2|CF_CHG2 }, // Not + { "nop", 0 }, // No Operation + { "mulhi", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Half-Word Immediate + { "mulh", CF_USE1|CF_USE2|CF_CHG2 }, // Multiply Half-Word + { "movhi", CF_USE1|CF_USE2|CF_CHG3 }, // Move High Half-Word + { "movea", CF_USE1|CF_USE2|CF_CHG3 }, // Move Effective Address + { "mov", CF_USE1|CF_CHG2 }, // Move + { "ldsr", CF_USE1|CF_CHG2 }, // Load to system register + { "ld.b", CF_USE1|CF_CHG2 }, // Load byte + { "ld.h", CF_USE1|CF_CHG2 }, // Load half-word + { "ld.w", CF_USE1|CF_CHG2 }, // Load word + { "jr", CF_USE1|CF_STOP }, // Jump Relative + { "jmp", CF_USE1|CF_JUMP|CF_STOP }, // Jump Register + { "jarl", CF_CALL|CF_USE1|CF_CHG2 }, // Jump and Register Link + { "halt", CF_STOP }, // Halt + { "ei", 0 }, // Enable interrupt + { "divh", CF_USE1|CF_USE2|CF_CHG2 }, // Divide Half-Word + { "di", 0 }, // Disable Interrupt + { "cmp", CF_USE1|CF_USE2 }, // Compare + { "clr1", CF_USE1|CF_USE2|CF_CHG2 }, // Clear bit + { "bv", CF_USE1 }, // Branch if overflow + { "bl", CF_USE1 }, // Branch if less + { "bz", CF_USE1 }, // Branch if zero + { "bnh", CF_USE1 }, // Branch if not higher + { "bn", CF_USE1 }, // Branch if negative + { "br", CF_USE1|CF_STOP }, // Branch if always + { "blt", CF_USE1 }, // Branch if less than (signed) + { "ble", CF_USE1 }, // Branch if less than or equal (signed) + { "bnv", CF_USE1 }, // Branch if no overflow + { "bnc", CF_USE1 }, // Branch if no carry + { "bnz", CF_USE1 }, // Branch if not zero + { "bh", CF_USE1 }, // Branch if higher than + { "bp", CF_USE1 }, // Branch if positive + { "bsa", CF_USE1 }, // Branch if saturated + { "bge", CF_USE1 }, // Branch if greater than or equal (signed) + { "bgt", CF_USE1 }, // Branch if greater than (signed) + { "andi", CF_USE1|CF_USE2|CF_CHG3 }, // And immediate + { "and", CF_USE1|CF_USE2|CF_CHG2 }, // And + { "addi", CF_USE1|CF_USE2|CF_CHG3 }, // Add Immediate + { "add", CF_USE1|CF_USE2|CF_CHG2 }, // Add + + // + // V850E/E1/ES + // + { "switch", CF_USE1|CF_STOP|CF_JUMP }, // Jump with table look up + { "zxb", CF_USE1|CF_CHG1 }, // + { "sxb", CF_USE1|CF_CHG1 }, // + { "zxh", CF_USE1|CF_CHG1 }, // + { "sxh", CF_USE1|CF_CHG1 }, // + { "dispose", CF_USE1|CF_USE2 }, // + { "dispose", CF_USE1|CF_USE2|CF_USE3|CF_STOP }, // + { "callt", CF_USE1|CF_CALL }, // + { "dbtrap", CF_STOP }, // + { "dbret", CF_STOP }, // + { "ctret", CF_STOP }, // + + { "sasf", CF_USE1|CF_USE2|CF_CHG2 }, // Shift and set flag condition + + { "prepare", CF_USE1|CF_USE2|CF_USE3 }, // Function prepare + { "prepare", CF_USE1|CF_USE2 }, // Function prepare + + { "mul", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Multiply word + { "mulu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Multiply word unsigned + + { "divh", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide halfword + { "divhu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide halfword unsigned + { "div", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word + { "divu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word unsigned + + { "bsw", CF_USE1|CF_CHG2 }, // Byte swap word + { "bsh", CF_USE1|CF_CHG2 }, // Byte swap halfword + { "hsw", CF_USE1|CF_CHG2 }, // Halfword swap word + + { "cmov", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Conditional move + + { "sld.bu", CF_USE1|CF_CHG2 }, // Short format load byte unsigned + { "sld.hu", CF_USE1|CF_CHG2 }, // Short format load halfword unsigned + + { "ld.bu", CF_USE1|CF_CHG2 }, // load byte unsigned + { "ld.hu", CF_USE1|CF_CHG2 }, // load halfword unsigned + + // + // V850E2 + // + { "adf", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Add on condition flag + { "hsh", CF_USE1|CF_CHG2 }, // Halfword swap halfword + { "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Multiply and add word + { "macu", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Multiply and add word unsigned + + { "sbf", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Subtract on condition flag + + { "sch0l", CF_USE1|CF_CHG2 }, // Search zero from left + { "sch0r", CF_USE1|CF_CHG2 }, // Search zero from right + { "sch1l", CF_USE1|CF_CHG2 }, // Search one from left + { "sch1r", CF_USE1|CF_CHG2 }, // Search one from right + + // + // V850E2M + // + { "caxi", CF_USE1|CF_USE2|CF_USE3 }, // Compare and exchange for interlock + { "divq", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word quickly + { "divqu", CF_USE1|CF_USE2|CF_CHG2|CF_CHG3 }, // Divide word unsigned quickly + { "eiret", CF_STOP }, // Return from EI level exception + { "feret", CF_STOP }, // Return from FE level exception + { "fetrap", CF_USE1 }, // FE-level Trap + { "rmtrap", 0 }, // Runtime monitor trap + { "rie", CF_STOP|CF_USE1|CF_USE2 }, // Reserved instruction exception + { "synce", 0 }, // Synchronize exceptions + { "syncm", 0 }, // Synchronize memory + { "syncp", 0 }, // Synchronize pipeline + { "syscall", CF_USE1 }, // System call + + // floating point (E1F only) + { "cvt.sw", CF_USE1|CF_CHG2 }, // Real to integer conversion + { "trnc.sw", CF_USE1|CF_CHG2 }, // Real to integer conversion + { "cvt.ws", CF_USE1|CF_CHG2 }, // Integer to real conversion + { "ldfc", CF_USE1|CF_CHG2 }, // Load to Floating Controls + { "ldff", CF_USE1|CF_CHG2 }, // Load to Floating Flags + { "stfc", CF_USE1|CF_CHG2 }, // Store Floating Controls + { "stff", CF_USE1|CF_CHG2 }, // Store Floating Flags + { "trff", 0 }, // Transfer Floating Flags + + // floating point (E2M+) + { "absf.d", CF_USE1|CF_CHG2 }, // Floating-point Absolute Value (Double) + { "absf.s", CF_USE1|CF_CHG2 }, // Floating-point Absolute Value (Single) + { "addf.d", CF_USE1|CF_CHG2 }, // Floating-point Add (Double) + { "addf.s", CF_USE1|CF_CHG2 }, // Floating-point Add (Single) + { "divf.d", CF_USE1|CF_CHG2 }, // Floating-point Divide (Double) + { "divf.s", CF_USE1|CF_CHG2 }, // Floating-point Divide (Single) + { "maxf.d", CF_USE1|CF_CHG2 }, // Floating-point Maximum (Double) + { "maxf.s", CF_USE1|CF_CHG2 }, // Floating-point Maximum (Single) + { "minf.d", CF_USE1|CF_CHG2 }, // Floating-point Minimum (Double) + { "minf.s", CF_USE1|CF_CHG2 }, // Floating-point Minimum (Single) + { "mulf.d", CF_USE1|CF_CHG2 }, // Floating-point Multiply (Double) + { "mulf.s", CF_USE1|CF_CHG2 }, // Floating-point Multiply (Single) + { "negf.d", CF_USE1|CF_CHG2 }, // Floating-point Negate (Double) + { "negf.s", CF_USE1|CF_CHG2 }, // Floating-point Negate (Single) + { "recipf.d", CF_USE1|CF_CHG2 }, // Reciprocal of a floating-point value (Double) + { "recipf.s", CF_USE1|CF_CHG2 }, // Reciprocal of a floating-point value (Single + + { "rsqrtf.d", CF_USE1|CF_CHG2 }, // Reciprocal of the square root of a floating-point value (Double) + { "rsqrtf.s", CF_USE1|CF_CHG2 }, // Reciprocal of the square root of a floating-point value (Single) + { "sqrtf.d", CF_USE1|CF_CHG2 }, // Floating-point Square Root (Double) + { "sqrtf.s", CF_USE1|CF_CHG2 }, // Floating-point Square Root (Single) + { "subf.d", CF_USE1|CF_CHG2 }, // Floating-point Subtract (Double) + { "subf.s", CF_USE1|CF_CHG2 }, // Floating-point Subtract (Single) + { "maddf.s", CF_USE1|CF_USE2|CF_USE3|CF_CHG4 }, // Floating-point Multiply-Add (Single) + { "msubf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Multiply-Subtract (Single) + { "nmaddf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Negate Multiply-Add (Single) + { "nmsubf.s", CF_USE1|CF_CHG2|CF_USE3|CF_CHG4 }, // Floating-point Negate Multiply-Subtract (Single) + + { "ceilf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double) + { "ceilf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double) + { "ceilf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single) + { "ceilf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single) + { "ceilf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double) + { "ceilf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double) + { "ceilf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single) + { "ceilf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single) + { "cvtf.dl", CF_USE1|CF_CHG2 }, // Floating-point Convert to Long Fixed-point Format (Double) + { "cvtf.ds", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double) + { "cvtf.dul", CF_USE1|CF_CHG2 }, // Floating-point Convert Double to Unsigned-Long (Double) + { "cvtf.duw", CF_USE1|CF_CHG2 }, // Floating-point Convert Double to Unsigned-Word (Double) + { "cvtf.dw", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Fixed-point Format (Double) + { "cvtf.ld", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double) + { "cvtf.ls", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Single) + { "cvtf.sd", CF_USE1|CF_CHG2 }, // Floating-point Convert to Double Floating-point Format (Double) + { "cvtf.sl", CF_USE1|CF_CHG2 }, // Floating-point Convert to Long Fixed-point Format (Single) + { "cvtf.sul", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Unsigned-Long (Single) + { "cvtf.suw", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Unsigned-Word (Single) + { "cvtf.sw", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Fixed-point Format (Single) + { "cvtf.uld", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Long to Double (Double) + { "cvtf.uls", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Long to Single (Single) + { "cvtf.uwd", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Word to Double (Double) + { "cvtf.uws", CF_USE1|CF_CHG2 }, // Floating-point Convert Unsigned-Word to Single (Single) + { "cvtf.wd", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Double) + { "cvtf.ws", CF_USE1|CF_CHG2 }, // Floating-point Convert to Single Floating-point Format (Single) + { "floorf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double) + { "floorf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double) + { "floorf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single) + { "floorf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single) + { "floorf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double) + { "floorf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double) + { "floorf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single) + { "floorf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single) + { "trncf.dl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double) + { "trncf.dul", CF_USE1|CF_CHG2 }, // Floating-point Truncate Double to Unsigned-Long (Double) + { "trncf.duw", CF_USE1|CF_CHG2 }, // Floating-point Truncate Double to Unsigned-Word (Double) + { "trncf.dw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double) + { "trncf.sl", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single) + { "trncf.sul", CF_USE1|CF_CHG2 }, // Floating-point Truncate Single to Unsigned-Long (Single) + { "trncf.suw", CF_USE1|CF_CHG2 }, // Floating-point Truncate Single to Unsigned-Word (Single) + { "trncf.sw", CF_USE1|CF_CHG2 }, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single) + { "cmpf.s", CF_USE1|CF_CHG2 }, // Compares floating-point values (Single) + { "cmpf.d", CF_USE1|CF_CHG2 }, // Compares floating-point values (Double) + { "cmovf.s", CF_USE1|CF_CHG2 }, // Floating-point conditional move (Single) + { "cmovf.d", CF_USE1|CF_CHG2 }, // Floating-point conditional move (Double) + { "trfsr", CF_USE1|CF_CHG2 }, // Transfers specified CC bit to Zero flag in PSW (Single) + + // + // RH850 + // + { "synci", 0 }, // Synchronize instruction pipeline + { "snooze", 0 }, // Snooze + { "bins", CF_USE1|CF_USE2|CF_USE3|CF_USE4|CF_CHG4 }, // Bitfield Insert + { "rotl", CF_USE1|CF_USE2|CF_CHG3 }, // Rotate Left + { "loop", CF_USE1|CF_USE2 }, // Loop + { "ld.dw", CF_USE1|CF_CHG2 }, // Load Double Word + { "st.dw", CF_USE1|CF_USE2|CF_CHG2 }, // Store Double Word + { "ldl.w", CF_USE1|CF_CHG2 }, // Load Linked + { "stc.w", CF_USE1|CF_USE2|CF_CHG2 }, // Store Conditional + { "cll", 0 }, // Clear Load Link + { "cache", CF_USE1|CF_USE2 }, // Cache operation + { "pref", CF_USE1|CF_USE2 }, // Prefetch + { "pushsp", CF_USE1 }, // Push registers to Stack + { "popsp", CF_CHG1 }, // Pop registers from Stack + + // new RH850 FP instructions + { "cvtf.hs", CF_USE1|CF_CHG2 }, // Floating-point Convert Half to Single (Single) + { "cvtf.sh", CF_USE1|CF_CHG2 }, // Floating-point Convert Single to Half (Single) + { "fmaf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Multiply-add (Single) + { "fmsf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Multiply-subtract (Single) + { "fnmaf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Negate-Multiply-add (Single) + { "fnmsf.s", CF_USE1|CF_USE2|CF_CHG3 }, // Floating-point Fused-Negate-Multiply-subtract (Single) + + // debug instructions + { "dbpush", CF_USE1 }, // Output registers as software trace data + { "dbcp", 0 }, // Output current PC value as software trace data + { "dbtag", CF_USE1 }, // Output immediate value as software trace data + { "dbhvtrap", 0 }, // Debug hypervisor trap + + { "est", 0 }, // + { "dst", 0 }, // + { "hvtrap", CF_USE1 }, // Hypervisor trap + { "hvcall", CF_USE1 }, // Hypervisor call + { "ldvc.sr", CF_USE1|CF_USE2 }, // + { "stvc.sr", CF_USE1|CF_USE2 }, // + { "ldtc.gr", CF_USE1|CF_USE2 }, // + { "sttc.gr", CF_USE1|CF_USE2 }, // + { "ldtc.pc", CF_USE1|CF_USE2 }, // + { "sttc.pc", CF_USE1|CF_USE2 }, // + { "ldtc.sr", CF_USE1|CF_USE2 }, // + { "sttc.sr", CF_USE1|CF_USE2 }, // + { "ldtc.vr", CF_USE1|CF_USE2 }, // + { "sttc.vr", CF_USE1|CF_USE2 }, // + + // TLB instructions + { "tlbai", 0 }, // + { "tlbr", 0 }, // + { "tlbs", 0 }, // + { "tlbvi", 0 }, // + { "tlbw", 0 }, // +}; + +CASSERT(qnumber(Instructions) == NEC850_LAST_INSTRUCTION); diff --git a/idasdk76/module/nec850/ins.hpp b/idasdk76/module/nec850/ins.hpp new file mode 100644 index 0000000..82c2222 --- /dev/null +++ b/idasdk76/module/nec850/ins.hpp @@ -0,0 +1,310 @@ +/* +* Interactive disassembler (IDA). +* Copyright (c) 1990-2021 Hex-Rays +* ALL RIGHTS RESERVED. +* +*/ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +#include "necv850.hpp" + +//---------------------------------------------------------------------- + +extern const instruc_t Instructions[]; + +enum NEC850_Instructions +{ + NEC850_NULL = 0, + + NEC850_BREAKPOINT, + NEC850_XORI, + NEC850_XOR, + NEC850_TST1, + NEC850_TST, + NEC850_TRAP, + NEC850_SUBR, + NEC850_SUB, + NEC850_STSR, + NEC850_ST_B, + NEC850_ST_H, + NEC850_ST_W, + NEC850_SST_B, + NEC850_SST_H, + NEC850_SST_W, + NEC850_SLD_B, + NEC850_SLD_H, + NEC850_SLD_W, + NEC850_SHR, + NEC850_SHL, + NEC850_SET1, + NEC850_SETF, + NEC850_SATSUBR, + NEC850_SATSUBI, + NEC850_SATSUB, + NEC850_SATADD, + NEC850_SAR, + NEC850_RETI, + NEC850_ORI, + NEC850_OR, + NEC850_NOT1, + NEC850_NOT, + NEC850_NOP, + NEC850_MULHI, + NEC850_MULH, + NEC850_MOVHI, + NEC850_MOVEA, + NEC850_MOV, + NEC850_LDSR, + NEC850_LD_B, + NEC850_LD_H, + NEC850_LD_W, + NEC850_JR, + NEC850_JMP, + NEC850_JARL, + NEC850_HALT, + NEC850_EI, + NEC850_DIVH, + NEC850_DI, + NEC850_CMP, + NEC850_CLR1, + NEC850_BV, + NEC850_BL, + NEC850_BZ, + NEC850_BNH, + NEC850_BN, + NEC850_BR, + NEC850_BLT, + NEC850_BLE, + NEC850_BNV, + NEC850_BNC, + NEC850_BNZ, + NEC850_BH, + NEC850_BP, + NEC850_BSA, + NEC850_BGE, + NEC850_BGT, + NEC850_ANDI, + NEC850_AND, + NEC850_ADDI, + NEC850_ADD, + + // + // V850E/E1/ES + // + NEC850_SWITCH, + NEC850_ZXB, + NEC850_SXB, + NEC850_ZXH, + NEC850_SXH, + NEC850_DISPOSE_r0, + NEC850_DISPOSE_r, + NEC850_CALLT, + NEC850_DBTRAP, + NEC850_DBRET, + NEC850_CTRET, + + NEC850_SASF, + + NEC850_PREPARE_sp, + NEC850_PREPARE_i, + + NEC850_MUL, + NEC850_MULU, + + NEC850_DIVH_r3, + NEC850_DIVHU, + NEC850_DIV, + NEC850_DIVU, + + NEC850_BSW, + NEC850_BSH, + NEC850_HSW, + + NEC850_CMOV, + + NEC850_SLD_BU, + NEC850_SLD_HU, + NEC850_LD_BU, + NEC850_LD_HU, + + // + // V850E2 + // + NEC850_ADF, // Add on condition flag + + NEC850_HSH, // Halfword swap halfword + NEC850_MAC, // Multiply and add word + NEC850_MACU, // Multiply and add word unsigned + + NEC850_SBF, // Subtract on condition flag + + NEC850_SCH0L, // Search zero from left + NEC850_SCH0R, // Search zero from right + NEC850_SCH1L, // Search one from left + NEC850_SCH1R, // Search one from right + + // + // V850E2M + // + NEC850_CAXI, // Compare and exchange for interlock + NEC850_DIVQ, // Divide word quickly + NEC850_DIVQU, // Divide word unsigned quickly + NEC850_EIRET, // Return from EI level exception + NEC850_FERET, // Return from FE level exception + NEC850_FETRAP, // FE-level Trap + NEC850_RMTRAP, // Runtime monitor trap + NEC850_RIE, // Reserved instruction exception + NEC850_SYNCE, // Synchronize exceptions + NEC850_SYNCM, // Synchronize memory + NEC850_SYNCP, // Synchronize pipeline + NEC850_SYSCALL, // System call + + // floating point (E1F only) + NEC850_CVT_SW, // Real to integer conversion + NEC850_TRNC_SW, // Real to integer conversion + NEC850_CVT_WS, // Integer to real conversion + NEC850_LDFC, // Load to Floating Controls + NEC850_LDFF, // Load to Floating Flags + NEC850_STFC, // Store Floating Controls + NEC850_STFF, // Store Floating Flags + NEC850_TRFF, // Transfer Floating Flags + + // floating point (E2M) + + NEC850_ABSF_D, // Floating-point Absolute Value (Double) + NEC850_ABSF_S, // Floating-point Absolute Value (Single) + NEC850_ADDF_D, // Floating-point Add (Double) + NEC850_ADDF_S, // Floating-point Add (Single) + NEC850_DIVF_D, // Floating-point Divide (Double) + NEC850_DIVF_S, // Floating-point Divide (Single) + NEC850_MAXF_D, // Floating-point Maximum (Double) + NEC850_MAXF_S, // Floating-point Maximum (Single) + NEC850_MINF_D, // Floating-point Minimum (Double) + NEC850_MINF_S, // Floating-point Minimum (Single) + NEC850_MULF_D, // Floating-point Multiply (Double) + NEC850_MULF_S, // Floating-point Multiply (Single) + NEC850_NEGF_D, // Floating-point Negate (Double) + NEC850_NEGF_S, // Floating-point Negate (Single) + NEC850_RECIPF_D, // Reciprocal of a floating-point value (Double) + NEC850_RECIPF_S, // Reciprocal of a floating-point value (Single + + NEC850_RSQRTF_D, // Reciprocal of the square root of a floating-point value (Double) + NEC850_RSQRTF_S, // Reciprocal of the square root of a floating-point value (Single) + NEC850_SQRTF_D, // Floating-point Square Root (Double) + NEC850_SQRTF_S, // Floating-point Square Root (Single) + NEC850_SUBF_D, // Floating-point Subtract (Double) + NEC850_SUBF_S, // Floating-point Subtract (Single) + NEC850_MADDF_S, // Floating-point Multiply-Add (Single) + NEC850_MSUBF_S, // Floating-point Multiply-Subtract (Single) + NEC850_NMADDF_S, // Floating-point Negate Multiply-Add (Single) + NEC850_NMSUBF_S, // Floating-point Negate Multiply-Subtract (Single) + + NEC850_CEILF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Double) + NEC850_CEILF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Double) + NEC850_CEILF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward +inf (Single) + NEC850_CEILF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward +inf (Single) + NEC850_CEILF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Double) + NEC850_CEILF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Double) + NEC850_CEILF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward +inf (Single) + NEC850_CEILF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward +inf (Single) + NEC850_CVTF_DL, // Floating-point Convert to Long Fixed-point Format (Double) + NEC850_CVTF_DS, // Floating-point Convert to Single Floating-point Format (Double) + NEC850_CVTF_DUL, // Floating-point Convert Double to Unsigned-Long (Double) + NEC850_CVTF_DUW, // Floating-point Convert Double to Unsigned-Word (Double) + NEC850_CVTF_DW, // Floating-point Convert to Single Fixed-point Format (Double) + NEC850_CVTF_LD, // Floating-point Convert to Single Floating-point Format (Double) + NEC850_CVTF_LS, // Floating-point Convert to Single Floating-point Format (Single) + NEC850_CVTF_SD, // Floating-point Convert to Double Floating-point Format (Double) + NEC850_CVTF_SL, // Floating-point Convert to Long Fixed-point Format (Single) + NEC850_CVTF_SUL, // Floating-point Convert Single to Unsigned-Long (Single) + NEC850_CVTF_SUW, // Floating-point Convert Single to Unsigned-Word (Single) + NEC850_CVTF_SW, // Floating-point Convert to Single Fixed-point Format (Single) + NEC850_CVTF_ULD, // Floating-point Convert Unsigned-Long to Double (Double) + NEC850_CVTF_ULS, // Floating-point Convert Unsigned-Long to Single (Single) + NEC850_CVTF_UWD, // Floating-point Convert Unsigned-Word to Double (Double) + NEC850_CVTF_UWS, // Floating-point Convert Unsigned-Word to Single (Single) + NEC850_CVTF_WD, // Floating-point Convert to Single Floating-point Format (Double) + NEC850_CVTF_WS, // Floating-point Convert to Single Floating-point Format (Single) + NEC850_FLOORF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Double) + NEC850_FLOORF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Double) + NEC850_FLOORF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded toward -inf (Single) + NEC850_FLOORF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded toward -inf (Single) + NEC850_FLOORF_DUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Double) + NEC850_FLOORF_DUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Double) + NEC850_FLOORF_SUL, // Floating-point Truncate to Unsigned Long, rounded toward -inf (Single) + NEC850_FLOORF_SUW, // Floating-point Truncate to Unsigned Word, rounded toward -inf (Single) + NEC850_TRNCF_DL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Double) + NEC850_TRNCF_DUL, // Floating-point Truncate Double to Unsigned-Long (Double) + NEC850_TRNCF_DUW, // Floating-point Truncate Double to Unsigned-Word (Double) + NEC850_TRNCF_DW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Double) + NEC850_TRNCF_SL, // Floating-point Truncate to Long Fixed-point Format, rounded to zero (Single) + NEC850_TRNCF_SUL, // Floating-point Truncate Single to Unsigned-Long (Single) + NEC850_TRNCF_SUW, // Floating-point Truncate Single to Unsigned-Word (Single) + NEC850_TRNCF_SW, // Floating-point Truncate to Single Fixed-point Format, rounded to zero (Single) + NEC850_CMPF_S, // Compares floating-point values (Single) + NEC850_CMPF_D, // Compares floating-point values (Double) + NEC850_CMOVF_S, // Floating-point conditional move (Single) + NEC850_CMOVF_D, // Floating-point conditional move (Double) + NEC850_TRFSR, // Transfers specified CC bit to Zero flag in PSW (Single) + + // + // RH850 + // + NEC850_SYNCI, // Synchronize instruction pipeline + NEC850_SNOOZE, // Snooze + NEC850_BINS, // Bitfield Insert + NEC850_ROTL, // Rotate Left + NEC850_LOOP, // Loop + NEC850_LD_DW, // Load Double Word + NEC850_ST_DW, // Store Double Word + NEC850_LDL_W, // Load Linked + NEC850_STC_W, // Store Conditional + NEC850_CLL, // Clear Load Link + NEC850_CACHE, // Cache operation + NEC850_PREF, // Prefetch + NEC850_PUSHSP, // Push registers to Stack + NEC850_POPSP, // Pop registers from Stack + + // new RH850 FP instructions + NEC850_CVTF_HS, // Floating-point Convert Half to Single (Single) + NEC850_CVTF_SH, // Floating-point Convert Single to Half (Single) + NEC850_FMAF_S, // Floating-point Fused-Multiply-add (Single) + NEC850_FMSF_S, // Floating-point Fused-Multiply-subtract (Single) + NEC850_FNMAF_S, // Floating-point Fused-Negate-Multiply-add (Single) + NEC850_FNMSF_S, // Floating-point Fused-Negate-Multiply-subtract (Single) + + // debug instructions + NEC850_DBPUSH, // + NEC850_DBCP, // + NEC850_DBTAG, // + NEC850_DBHVTRAP, // + + // virtualization instructions + NEC850_EST, // + NEC850_DST, // + NEC850_HVTRAP, // + NEC850_HVCALL, // + NEC850_LDVC_SR, // + NEC850_STVC_SR, // + NEC850_LDTC_GR, // + NEC850_STTC_GR, // + NEC850_LDTC_PC, // + NEC850_STTC_PC, // + NEC850_LDTC_SR, // + NEC850_STTC_SR, // + NEC850_LDTC_VR, // + NEC850_STTC_VR, // + + // TLB instructions + NEC850_TLBAI, // + NEC850_TLBR, // + NEC850_TLBS, // + NEC850_TLBVI, // + NEC850_TLBW, // + + NEC850_LAST_INSTRUCTION +}; + +#endif diff --git a/idasdk76/module/nec850/makefile b/idasdk76/module/nec850/makefile new file mode 100644 index 0000000..3fb34cd --- /dev/null +++ b/idasdk76/module/nec850/makefile @@ -0,0 +1,52 @@ +PROC=nec850 + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + necv850.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)frame.hpp \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)jumptable.hpp $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \ + necv850.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ + necv850.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp \ + necv850.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp necv850.hpp reg.cpp diff --git a/idasdk76/module/nec850/necv850.hpp b/idasdk76/module/nec850/necv850.hpp new file mode 100644 index 0000000..c96085e --- /dev/null +++ b/idasdk76/module/nec850/necv850.hpp @@ -0,0 +1,211 @@ +#ifndef __NECV850_INC__ +#define __NECV850_INC__ + +#include "../idaidp.hpp" +#include <list> +#include <pro.h> +#include <fpro.h> +#include <idd.hpp> +#include <ida.hpp> +#include <name.hpp> +#include <idp.hpp> +#include <ieee.h> + +#define PROCMOD_NAME nec850 +#define PROCMOD_NODE_NAME "$ prog pointers" + + + #ifndef SIGN_EXTEND + #define SIGN_EXTEND(type, var, nbits) \ + if ( var & (1 << (nbits-1)) ) \ + var |= ~type((1 << nbits)-1) + #endif + + +//---------------------------------------------------------------------- +// Specific flags + +// +// Used in op_t.specflag1 +#define N850F_USEBRACKETS 0x01 // some instructions use [reg] syntax even when there is no actual memory dereference +#define N850F_OUTSIGNED 0x02 // output as signed value +#define N850F_VAL32 0x04 // value/addr is wider than 16-bit + +#define o_reglist o_idpspec1 // Register list (for DISPOSE) + // bitmask of registers is in 'value' field +// +// Used in insn.auxpref +#define N850F_SP 0x00000001 // instruction modifies the stack pointer +#define N850F_FP 0x00000010 // instruction works with floating-point data + +#define o_cond o_idpspec2 // Condition code as operand (for CMOV/CMPF) + // condition stored in 'value' field + +#define o_regrange o_idpspec3 // Register range (rh-rl, for PUSHSP/POPSP) +#define regrange_high specval_shorts.high // high register (rh) +#define regrange_low specval_shorts.low // low register (rl) + +//---------------------------------------------------------------------- +// Registers def +enum NEC850_Registers +{ + rZERO, + rR1, rR2, rSP /* r3 */, rGP /* r4 */, + rR5, rR6, rR7, rR8, + rR9, rR10, rR11, rR12, + rR13, rR14, rR15, rR16, + rR17, rR18, rR19, rR20, + rR21, rR22, rR23, rR24, + rR25, rR26, rR27, rR28, + rR29, rEP, rR31, + rLP = rR31, + + // system registers start here + rSR0, + rEIP=rSR0, rEIPSW, rFEPC, rFEPSW, + rECR, rPSW, rSR6, rSR7, + rSR8, rSR9, rSR10, rSR11, + rSR12, rSR13, rSR14, rSR15, + rSR16, rSR17, rSR18, rSR19, + rSR20, rSR21, rSR22, rSR23, + rSR24, rSR25, rSR26, rSR27, + rSR28, rSR29, rSR30, rSR31, + + // E1F FPU registers + EFG, ECT, + + // segment registers + rVep, // virtual element pointer segment register + rVcs, rVds, + + rLastRegister +}; + +enum NEC850_CCode // for CMOV +{ + CC_V, // 0000: Overflow (OV=1) + CC_CL, // 0001: Carry (CY=1) + CC_Z, // 0010: Zero (Z=1) + CC_NH, // 0011: Not higher (Less than or equal) ((CY or Z) = 1) + CC_SN, // 0100: Negative) S=1 + CC_T, // 0101: Always (true) + CC_LT, // 0110: Less than signed (S xor OV) = 1 + CC_LE, // 0111: Less than or equal signed (((S xor OV) or Z) = 1) + CC_NV, // 1000: no overflow (OV=0) + CC_NCNL,// 1001: no carry (CY=0) + CC_NZ, // 1010: not zero (Z=0) + CC_H, // 0011: Higher (Greater than) ((CY or Z) = 0) + CC_NSP, // 0100: Positive (S=0) + CC_SAT, // 1101: Saturated (SAT=1) + CC_GE, // 1110: Greater than or equal signed (S xor OV) = 0 + CC_GT, // 1111: Greater than signed (((S xor OV) or Z) = 0) +}; + +enum proctype_t +{ + V850, // including V850 + V850E, // + V850ES, // including V850E1 + V850E2M,// including V850E2 + RH850, // +}; +//---------------------------------------------------------------------- +// Prototypes + +// prototypes -- out.cpp +void idaapi nec850_header(outctx_t &ctx); +void idaapi nec850_segstart(outctx_t &ctx, segment_t *seg); +void idaapi nec850_segend(outctx_t &ctx, segment_t *seg); + +bool reg_in_list12(uint16 reg, uint32 L); + +// prototypes -- ana.cpp +int detect_inst_len(uint16 w); +int fetch_instruction(uint32 *w); + +// prototypes -- emu.cpp +bool idaapi nec850_is_switch(switch_info_t *si, const insn_t &insn); +bool idaapi nec850_create_func_frame(func_t *pfn); +int idaapi nec850_get_frame_retsize(const func_t *pfn); +int idaapi nec850_is_sp_based(const insn_t &insn, const op_t &x); +int nec850_may_be_func(const insn_t &insn); +bool nec850_is_return(const insn_t &insn, bool strict); +int get_imm_outf(const insn_t &insn, const op_t &x); +int get_displ_outf(const insn_t &insn, const op_t &x, flags_t F); + +extern const char *const RegNames[]; + +typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); + +//------------------------------------------------------------------ +DECLARE_PROC_LISTENER(idb_listener_t, struct nec850_t); + +struct nec850_t : public procmod_t +{ + // altval(1) -> global pointer + // altval(2) -> CALLT base pointer +#define GP_EA_IDX 1 +#define CTBP_EA_IDX 2 + netnode helper; + + idb_listener_t idb_listener = idb_listener_t(*this); + ea_t g_gp_ea = BADADDR; // global pointer + ea_t g_ctbp_ea = BADADDR; // CALLT base pointer + int ptype = 0; + bool flow = false; + + bool inline idaapi is_v850e() const { return ptype >= (int)V850E; } + bool inline idaapi is_v850es() const { return ptype >= (int)V850ES; } + bool inline idaapi is_v850e1() const { return is_v850es(); } + bool inline idaapi is_v850e1f() const { return is_v850e1(); } + bool inline idaapi is_v850e2m() const { return ptype >= (int)V850E2M; } + bool inline idaapi is_v850e2() const { return is_v850e2m(); } + bool inline idaapi is_rh850() const { return ptype >= (int)RH850; } + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *idaapi set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + + bool decode_instruction(const uint32 w, insn_t &ins); + bool decode_coprocessor(const uint32 w, insn_t &ins) const; + int nec850_ana(insn_t *pinsn); + + bool get_gp_based_addr(ea_t *target, const insn_t &_insn, const op_t &op) const; + void handle_operand(const insn_t &insn, const op_t &op, bool isRead); + int nec850_emu(const insn_t &insn); + int nec850_is_sane_insn(const insn_t &insn, int no_crefs) const; + sval_t regval( + const op_t &op, + getreg_t *getreg, + const regval_t *rv) const; + + // debugger functions + ea_t nec850_next_exec_insn( + ea_t ea, + getreg_t *getreg, + const regval_t *regvalues) const; + ea_t nec850_calc_step_over(ea_t ip) const; + bool nec850_get_operand_info( + idd_opinfo_t *opinf, + ea_t ea, + int n, + getreg_t *getreg, + const regval_t *regvalues); + bool nec850_get_reg_info( + const char **main_regname, + bitrange_t *bitrange, + const char *regname); + int nec850_get_reg_index(const char *name) const; // static + + void nec850_footer(outctx_t &ctx) const; + + void save_all_options(); + void load_from_idb(); +}; +extern int data_id; + +#endif diff --git a/idasdk76/module/nec850/out.cpp b/idasdk76/module/nec850/out.cpp new file mode 100644 index 0000000..af81fff --- /dev/null +++ b/idasdk76/module/nec850/out.cpp @@ -0,0 +1,339 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) Hex-Rays + * ALL RIGHTS RESERVED. + * + * Output + * + */ +#include "necv850.hpp" +#include "ins.hpp" + +//-------------------------------------------------------------------------- +// LIST12 table mapping to corresponding registers +static const int list12_table[] = +{ + rR31, // 0 + rR29, // 1 + rR28, // 2 + rR23, // 3 + rR22, // 4 + rR21, // 5 + rR20, // 6 + rR27, // 7 + rR26, // 8 + rR25, // 9 + rR24, // 10 + rEP // 11 +}; + +// Using the indexes in this table as indexes in list12_table[] +// we can test for bits in List12 in order +static const int list12order_table[] = +{ + 6, // 0 r20 + 5, // 1 r21 + 4, // 2 r22 + 3, // 3 r23 + 10, // 4 r24 + 9, // 5 r25 + 8, // 6 r26 + 7, // 7 r27 + 2, // 8 r28 + 1, // 9 r29 + 11, // 10 r30 + 0, // 11 r31 +}; + +//---------------------------------------------------------------------- +int get_displ_outf(const insn_t &insn, const op_t &x, flags_t F) +{ + qnotused(insn); + qnotused(F); + + int outf = OOF_ADDR; + outf |= ( x.specflag1 & N850F_VAL32 ) ? OOFW_32 : OOFW_16; + if ( ( x.specflag1 & N850F_OUTSIGNED ) != 0 ) + outf |= OOFS_IFSIGN | OOF_SIGNED; + + return outf; +} + +//---------------------------------------------------------------------- +class out_nec850_t : public outctx_t +{ + out_nec850_t(void) = delete; // not used +public: + void OutReg(const op_t &r); + void out_reg_list(uint32 L); + void out_reg_range(const op_t &op); + bool out_operand(const op_t &x); + void out_insn(void); + void out_cond(const op_t &r); + void out_fcond(const op_t &r); +}; +CASSERT(sizeof(out_nec850_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_nec850_t) + +//-------------------------------------------------------------------------- +bool reg_in_list12(uint16 reg, uint32 L) +{ + if ( rR20 <= reg && reg <= rR31 ) + { + uint32 idx = list12order_table[reg - rR20]; //lint !e676 possibly indexing before the beginning of an allocation + return (L & (1 << idx)) != 0; + } + return false; +} + +//-------------------------------------------------------------------------- +void out_nec850_t::out_reg_list(uint32 L) +{ + int last = qnumber(list12_table); + int in_order = 0, c = 0; + const char *last_rn = NULL; + + out_symbol('{'); + for ( int i=0; i < qnumber(list12order_table); i++ ) + { + uint32 idx = list12order_table[i]; + if ( (L & (1 << idx)) == 0 ) + continue; + c++; + const char *rn = RegNames[list12_table[idx]]; + if ( last + 1 == i ) + in_order++; + else + { + if ( in_order > 1 ) + { + out_symbol('-'); + out_register(last_rn); + out_line(", ", COLOR_SYMBOL); + } + else if ( c > 1 ) + { + out_line(", ", COLOR_SYMBOL); + } + out_register(rn); + in_order = 1; + } + last_rn = rn; + last = i; + } + if ( in_order > 1 ) + { + out_symbol('-'); + out_register(last_rn); + } + out_symbol('}'); +} + + +//-------------------------------------------------------------------------- +void out_nec850_t::out_reg_range(const op_t &op) +{ + out_register(RegNames[op.regrange_high]); + out_symbol('-'); + out_register(RegNames[op.regrange_low]); +} +//-------------------------------------------------------------------------- +void idaapi nec850_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_PROC_AND_ASM); +} + +//-------------------------------------------------------------------------- +void nec850_t::nec850_footer(outctx_t &ctx) const +{ + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + ctx.flush_outbuf(DEFAULT_INDENT); + ctx.gen_cmt_line("-------------- end of module --------------"); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, s) could be made const +void idaapi nec850_segstart(outctx_t &ctx, segment_t *s) +{ + qstring sname; + qstring sclass; + + get_visible_segm_name(&sname, s); + get_segm_class(&sclass, s); + + const char *p_class; + if ( (s->perm == (SEGPERM_READ|SEGPERM_WRITE)) && s->type == SEG_BSS ) + p_class = "bss"; + else if ( s->perm == SEGPERM_READ ) + p_class = "const"; + else if ( s->perm == (SEGPERM_READ|SEGPERM_WRITE) ) + p_class = "data"; + else if ( s->perm == (SEGPERM_READ|SEGPERM_EXEC) ) + p_class = "text"; + else if ( s->type == SEG_XTRN ) + p_class = "symtab"; + else + p_class = sclass.c_str(); + + ctx.gen_printf(0, COLSTR(".section \"%s\", %s", SCOLOR_ASMDIR), sname.c_str(), p_class); +} + +//-------------------------------------------------------------------------- +void idaapi nec850_segend(outctx_t &, segment_t *) +{ +} + +//---------------------------------------------------------------------- +void out_nec850_t::OutReg(const op_t &r) +{ + bool brackets = r.specflag1 & N850F_USEBRACKETS; + if ( brackets ) + out_symbol('['); + out_register(ph.reg_names[r.reg]); + if ( brackets ) + out_symbol(']'); +} + +static const char *cond_tbl[16] = +{ + "v", // 0000: Overflow (OV=1) + "c/l", // 0001: Carry (CY=1) + "z", // 0010: Zero (Z=1) + "nh", // 0011: Not higher (Less than or equal) ((CY or Z) = 1) + "s/n", // 0100: Negative) S=1 + "t", // 0101: Always (true) + "lt", // 0110: Less than signed (S xor OV) = 1 + "le", // 0111: Less than or equal signed (((S xor OV) or Z) = 1) + "nv", // 1000: no overflow (OV=0) + "nc/nl",// 1001: no carry (CY=0) + "nz", // 1010: not zero (Z=0) + "h", // 0011: Higher (Greater than) ((CY or Z) = 0) + "ns/p", // 0100: Positive (S=0) + "sat", // 1101: Saturated (SAT=1) + "ge", // 1110: Greater than or equal signed (S xor OV) = 0 + "gt", // 1111: Greater than signed (((S xor OV) or Z) = 0) +}; + +static const char *fcond_tbl[16] = +{ + "f/t", + "un/or", + "eq/neq", + "ueq/ogl", + "olt/uge", + "ult/oge", + "ole/ugt", + "ule/ogt", + "sf/st", + "ngle/gle", + "seq/sne", + "ngl/gl", + "lt/nlt", + "nge/ge", + "le/nle", + "ngt/gt" +}; + +//---------------------------------------------------------------------- +void out_nec850_t::out_cond(const op_t &r) +{ + int cc = r.value; + QASSERT(10327, r.type == o_cond && cc < qnumber(cond_tbl)); + out_keyword(cond_tbl[cc]); +} + +//---------------------------------------------------------------------- +void out_nec850_t::out_fcond(const op_t &r) +{ + int cc = r.value; + QASSERT(10323, r.type == o_cond && cc < qnumber(fcond_tbl)); + out_keyword(fcond_tbl[cc]); +} + +//---------------------------------------------------------------------- +void out_nec850_t::out_insn(void) +{ + out_mnemonic(); + + out_one_operand(0); + + for ( int i=1; i < UA_MAXOP; i++ ) + { + if ( insn.ops[i].type == o_void ) + break; + out_symbol(','); + out_char(' '); + out_one_operand(i); + } + flush_outbuf(); +} + +//---------------------------------------------------------------------- +// Generate text representation of an instructon operand. +// This function shouldn't change the database, flags or anything else. +// All these actions should be performed only by u_emu() function. +// The output text is placed in the output buffer initialized with init_output_buffer() +// This function uses out_...() functions from ua.hpp to generate the operand text +// Returns: 1-ok, 0-operand is hidden. +bool out_nec850_t::out_operand(const op_t &x) +{ + switch ( x.type ) + { + case o_void: + return false; + case o_reglist: + out_reg_list(x.value); + break; + case o_regrange: + out_reg_range(x); + break; + case o_reg: + OutReg(x); + break; + case o_imm: + out_value(x, OOFW_IMM | ((x.specflag1 & N850F_OUTSIGNED) ? OOF_SIGNED : 0)); + break; + case o_near: + case o_mem: + if ( !out_name_expr(x, x.addr, BADADDR) ) + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR | OOFW_IMM | OOFW_32); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + break; + case o_displ: + if ( x.addr != 0 || x.reg == rSP ) + out_value(x, get_displ_outf(insn, x, F)); + OutReg(x); + if ( x.reg != rGP && x.reg != rSP && x.addr == 0 ) + { // add name comment + xrefblk_t xb; + for ( bool ok=xb.first_from(insn.ea, XREF_DATA); ok; ok=xb.next_from() ) + { + if ( has_cmt(F) ) + continue; + if ( xb.type != dr_R && xb.type != dr_W ) + continue; + + qstring qbuf; + if ( get_name_expr(&qbuf, insn.ea, x.n, xb.to, BADADDR) > 0 ) + set_cmt(insn.ea, qbuf.begin(), false); + } + } + break; + case o_cond: + if ( insn.auxpref & N850F_FP ) + out_fcond(x); + else + out_cond(x); + break; + default: + return false; + } + return true; +} diff --git a/idasdk76/module/nec850/reg.cpp b/idasdk76/module/nec850/reg.cpp new file mode 100644 index 0000000..6c75588 --- /dev/null +++ b/idasdk76/module/nec850/reg.cpp @@ -0,0 +1,532 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) Hex-Rays + * ALL RIGHTS RESERVED. + * + * Processor description structures + * + */ +#include "necv850.hpp" +#include "ins.hpp" +#include <loader.hpp> +#include <segregs.hpp> + +int data_id; + +//------------------------------------------------------------------------- +void nec850_t::save_all_options() +{ + helper.altset(GP_EA_IDX, ea2node(g_gp_ea)); + helper.altset(CTBP_EA_IDX, ea2node(g_ctbp_ea)); +} + +//------------------------------------------------------------------------- +// read all procmod data from the idb +void nec850_t::load_from_idb() +{ + g_gp_ea = node2ea(helper.altval(GP_EA_IDX)); + g_ctbp_ea = node2ea(helper.altval(CTBP_EA_IDX)); +} + +//------------------------------------------------------------------ +const char *nec850_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + if ( keyword != NULL ) + { + if ( streq(keyword, "GP_EA") ) + { + if ( value_type != IDPOPT_NUM ) + return IDPOPT_BADTYPE; + g_gp_ea = *((uval_t *)value); + goto SAVE; + } + if ( streq(keyword, "CTBP_EA") ) + { + if ( value_type != IDPOPT_NUM ) + return IDPOPT_BADTYPE; + g_ctbp_ea = *((uval_t *)value); + goto SAVE; + } + return IDPOPT_BADKEY; + } + + static const char form[] = + "NEC V850x analyzer options\n" + "\n" + " <~G~lobal Pointer address:$::18::>\n" + " <CALLT ~B~ase pointer :$::18::>\n" + "\n" + "\n" + "\n"; + CASSERT(sizeof(g_gp_ea) == sizeof(ea_t)); + CASSERT(sizeof(g_ctbp_ea) == sizeof(ea_t)); + if ( ask_form(form, &g_gp_ea, &g_ctbp_ea) == ASKBTN_YES ) + { +SAVE: + if ( idb_loaded ) + save_all_options(); + } + + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +static const asm_t nec850_asm = +{ + ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, // flags + 0, // user flags + "NEC V850 Assembler", // assembler name + 0, // help + NULL, // array of automatically generated header lines + ".org", // org directive + ".end", // end directive + "--", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + ".str", // ascii string directive + ".byte", // byte directive + ".hword", // halfword (16 bits) [IDA: word] + ".word", // word (32 bits) [IDA: dword] + ".dword", // doubleword (64 bits) [IDA: qword] + NULL, // oword (16 bytes) + ".float", // float (4-byte) + ".double", // double (8-byte) + NULL, // no tbytes + NULL, // no packreal + "#d dup(#v)", //".db.#s(b,w) #d,#v" + ".byte (%s) ?", // uninited data (reserve space) ;? + ".set", // 'equ' Used if AS_UNEQU is set + NULL, // seg prefix + "PC", // a_curip + NULL, // returns function header line + NULL, // returns function footer line + ".globl", // public + NULL, // weak + ".extern", // extrn + ".comm", // comm + NULL, // get_type_name + ".align", // align + '(', // lbrace + ')', // rbrace + NULL, // mod + "&", // bit-and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flags2 + NULL, // cmnt2 + NULL, // low8 operation, should contain %s for the operand + NULL, // high8 + NULL, // low16 + NULL, // high16 + ".include %s", // a_include_fmt + NULL, // if a named item is a structure and displayed + NULL // 'rva' keyword for image based offsets +}; + +static const asm_t *const asms[] = { &nec850_asm, NULL }; + +//---------------------------------------------------------------------- +#define FAMILY "NEC/Renesas 850 series:" + +static const char *const shnames[] = +{ + "V850", + "V850E", + "V850E1", + "V850E2M", + "RH850", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"NEC V850", + "NEC V850E", + "NEC/Renesas V850E1/ES", + "NEC/Renesas V850E2/E2M", + "Renesas RH850", + NULL +}; + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list) +{ + switch ( code ) + { + // all options are saved immediately after the change + // case idb_event::savebase: + + case idb_event::segm_moved: // A segment is moved + // Fix processor dependent address sensitive information + // { + // ea_t from = va_arg(va, ea_t); + // ea_t to = va_arg(va, ea_t); + // asize_t size = va_arg(va, asize_t); + // bool changed_netmap = va_argi(va, bool); + // // adjust gp_ea + // } + break; + + default: + break; + } + return 0; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(nec850_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi nec850_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + hook_event_listener(HT_IDB, &idb_listener, &LPH); + inf_set_be(false); + break; + + case processor_t::ev_term: + unhook_event_listener(HT_IDB, &idb_listener); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + save_all_options(); + break; + + case processor_t::ev_newprc: + { + int procnum = va_arg(va, int); + // bool keep_cfg = va_argi(va, bool); + ptype = procnum; + break; + } + + case processor_t::ev_ending_undo: + // restore ptype + ptype = ph.get_proc_index(); + //fall through + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_is_sane_insn: + { + const insn_t &insn = *va_arg(va, insn_t *); + int no_crefs = va_arg(va, int); + code = nec850_is_sane_insn(insn, no_crefs) == 1 ? 1 : -1; + break; + } + + case processor_t::ev_may_be_func: + { + const insn_t &insn = *va_arg(va, insn_t *); + code = nec850_may_be_func(insn); + } + break; + + case processor_t::ev_is_ret_insn: + { + const insn_t &insn = *va_arg(va, insn_t *); + bool strict = va_argi(va, bool); + code = nec850_is_return(insn, strict) ? 1 : -1; + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + nec850_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + nec850_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + nec850_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + nec850_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return nec850_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return nec850_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_is_switch: + { + switch_info_t *si = va_arg(va, switch_info_t *); + const insn_t *insn = va_arg(va, const insn_t *); + return nec850_is_switch(si, *insn) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *op = va_arg(va, const op_t *); + *mode = nec850_is_sp_based(*insn, *op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + nec850_create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = nec850_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + // START OF DEBUGGER CALLBACKS + case processor_t::ev_next_exec_insn: + { + ea_t *target = va_arg(va, ea_t *); + ea_t ea = va_arg(va, ea_t); + int tid = va_arg(va, int); + getreg_t *getreg = va_arg(va, getreg_t *); + const regval_t *regvalues = va_arg(va, const regval_t *); + qnotused(tid); + *target = nec850_next_exec_insn(ea, getreg, regvalues); + return 1; + } + + case processor_t::ev_calc_step_over: + { + ea_t *target = va_arg(va, ea_t *); + ea_t ip = va_arg(va, ea_t); + *target = nec850_calc_step_over(ip); + return 1; + } + + case processor_t::ev_get_idd_opinfo: + { + idd_opinfo_t *opinf = va_arg(va, idd_opinfo_t *); + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + int thread_id = va_arg(va, int); + getreg_t *getreg = va_arg(va, getreg_t *); + const regval_t *regvalues = va_arg(va, const regval_t *); + qnotused(thread_id); + return nec850_get_operand_info(opinf, ea, n, getreg, regvalues) ? 1 : 0; + } + + case processor_t::ev_get_reg_info: + { + const char **main_regname = va_arg(va, const char **); + bitrange_t *bitrange = va_arg(va, bitrange_t *); + const char *regname = va_arg(va, const char *); + return nec850_get_reg_info(main_regname, bitrange, regname) ? 1 : -1; + } + // END OF DEBUGGER CALLBACKS + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// Registers Definition +//----------------------------------------------------------------------- +const char *const RegNames[rLastRegister] = +{ + "r0", + "r1", + "r2", + "sp", + "gp", + "r5", // text pointer - tp + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + "r16", + "r17", + "r18", + "r19", + "r20", + "r21", + "r22", + "r23", + "r24", + "r25", + "r26", + "r27", + "r28", + "r29", + "ep", + "lp", + // system registers start here + "eipc", + "eipsw", + "fepc", + "fepsw", + "ecr", + "psw", + "sr6", + "sr7", + "sr8", + "sr9", + "sr10", + "sr11", + "sr12", + "sr13", + "sr14", + "sr15", + "sr16", + "sr17", + "sr18", + "sr19", + "sr20", + "sr21", + "sr22", + "sr23", + "sr24", + "sr25", + "sr26", + "sr27", + "sr28", + "sr29", + "sr30", + "sr31", + + "EFG", "ECT", + + // + "ep", "cs", "ds" +}; +CASSERT(qnumber(RegNames) == rLastRegister); + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_NEC_V850X, // id + // flag + PR_DEFSEG32 + | PR_USE32 + | PRN_HEX + | PR_RNAMESOK, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // short processor names + lnames, // long processor names + + asms, // assemblers + + notify, + + RegNames, // Regsiter names + rLastRegister, // Number of registers + + rVcs/*rVep*/, // number of first segment register + rVds/*rVcs*/, // number of last segment register + 0 /*4*/, // size of a segment register + rVcs, + rVds, + NULL, // No known code start sequences + NULL, // Array of 'return' instruction opcodes + NEC850_NULL, + NEC850_LAST_INSTRUCTION, + Instructions, // instruc + 0, // size of tbyte + {0,7,15,0}, // real width + 0, // icode_return + NULL, // Micro virtual machine description +}; diff --git a/idasdk76/module/oakdsp/ana.cpp b/idasdk76/module/oakdsp/ana.cpp new file mode 100644 index 0000000..d285ad6 --- /dev/null +++ b/idasdk76/module/oakdsp/ana.cpp @@ -0,0 +1,783 @@ +#include "oakdsp.hpp" + +#define FUNCS_COUNT 5 + +struct funcdesc_t +{ + bool (oakdsp_t:: *func)(insn_t &, int, int); + uint32 mask; + uint32 param; + uint32 shift; +}; + +struct opcode_t +{ + const char *recog; + ushort itype; + funcdesc_t funcs[FUNCS_COUNT]; //lint !e958 padding is required to align members + uchar cycles; // Number of cycles + uint32 mask; //lint !e958 padding is required to align members + uint32 value; +}; + +//---------------------------------------------------------------------- +static uint32 ua_32bits(const insn_t &insn) +{ + return ((get_wide_byte(insn.ea) << 0) & 0x0000FFFF) + | ((get_wide_byte(insn.ea+1) << 16) & 0xFFFF0000); + +} + +//lint -e1762 member function could be made const + +//---------------------------------------------------------------------- +inline void oakdsp_t::opreg(int reg) +{ + op->type = o_reg; + op->reg = uint16(reg); +} + +//---------------------------------------------------------------------- +void oakdsp_t::make_o_mem(const insn_t &insn) +{ + if ( !(op->amode & amode_x) ) + { + switch ( insn.itype ) + { + + case OAK_Dsp_callr: + case OAK_Dsp_call: + case OAK_Dsp_br_u: + case OAK_Dsp_br: + case OAK_Dsp_brr_u: + case OAK_Dsp_brr: + case OAK_Dsp_bkrep: + op->type = o_near; + op->dtype = dt_code; + return; + } + } + op->type = o_mem; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::rrrrr(insn_t &, int value, int param) +{ + uint idx; + if ( param & mix_mode ) + param = (param & 0xff) + value; + idx = param ? param : value; + + if ( idx >= PAGE ) + return false; + opreg(idx); + if ( op->reg == uchar(-1) ) + return false; + + op++; + return true; +} + +//---------------------------------------------------------------------- +//lint -e{1764} 'insn' could be declared const ref +bool oakdsp_t::sdirect(insn_t &insn, int value, int) +{ + op->amode = amode_short; + op->addr = value & 0x00ff; + op->amode |= amode_x; + + make_o_mem(insn); + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::ldirect(insn_t &insn, int value,int) +{ + op->amode = amode_long; + op->addr = value & 0xffff; + insn.size++; + op->amode |= amode_x; + + make_o_mem(insn); + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::A(insn_t &insn, int value,int) +{ + return rrrrr(insn, value & 0x01, A0 + mix_mode); +} + +//---------------------------------------------------------------------- +bool oakdsp_t::B(insn_t &insn, int value,int) +{ + return rrrrr(insn, value & 0x01, B0 + mix_mode); +} + +//---------------------------------------------------------------------- +bool oakdsp_t::mmnnn(insn_t &, int value,int) +{ + if ( (value & 0x07) > 0x05 ) + return false; + + op->type = o_phrase; + op->reg = value & 0x07; + op->phtype = (value & 0x0018) >> 3; + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::nnn(insn_t &insn, int value, int) +{ + return rrrrr(insn, value & 0x07, R0 + mix_mode); +} +//---------------------------------------------------------------------- +bool oakdsp_t::ALU_ALM(insn_t &insn, int value, int param) +{ + if ( param && (value == 0x04 || value == 0x05) ) + return false; + + insn.itype = OAK_Dsp_or + (value & (param ? 0x07 : 0x0f)); + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::ALB(insn_t &insn, int value, int) +{ + insn.itype = OAK_Dsp_set + (value & 0x07); + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::MUL(insn_t &insn, int value, int param) +{ + if ( param && (value > 0x03) ) + return false; + + insn.itype = OAK_Dsp_mpy + ((value & (param ? 0x03 : 0x07)) << (param ? 0x01 : 0x00)); + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::MODA_B(insn_t &insn, int value, int param) +{ + if ( value == 0x07 ) + return false; + + insn.itype = OAK_Dsp_shr + (value & (param ? 0x07 : 0x0f)); + return true; +} + +//---------------------------------------------------------------------- +//lint -e{1764} 'insn' could be declared const ref +bool oakdsp_t::s_Imm(insn_t &insn, int value, int) +{ + op->type = o_imm; + op->value = value; + + switch ( insn.itype ) + { + case OAK_Dsp_mpyi: + op->amode |= amode_signed; + break; + } + + op++; + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::s_ImmS(insn_t &, int value, int param) +{ + uint mask1 = 1 << (param - 1); + uint mask2 = 0; + for ( int i = 0; i < param; i++ ) + mask2 |= (1 << i); + + op->type = o_imm; + op->value = (value & mask2); + op->amode |= amode_signed; + + if ( value & mask1 ) + op->value = - ((value^mask2) + 1); + + op++; + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::l_Imm(insn_t &insn, int value, int) +{ + op->type = o_imm; + op->value = value & 0xffff; + insn.size++; + + switch ( insn.itype ) + { + case OAK_Dsp_maa: + case OAK_Dsp_mac: + case OAK_Dsp_macus: + case OAK_Dsp_mpy: + case OAK_Dsp_msu: + op->amode |= amode_signed; + break; + } + + op++; + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::rb_rel_short(insn_t &, int value, int) +{ + op->type = o_local; + op->phtype = 0; // "rb + #displ" + op->amode |= amode_signed; + + value &= 0x7f; + + if ( value & 0x40 ) + value = - ((value^0x7f) + 1); + + op->addr = value; + op->amode |= amode_x; + + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::rb_rel_long(insn_t &insn, int value, int) +{ + int16 tmp; + + insn.size++; + op->type = o_local; + op->phtype = 0; // "rb + #displ" + op->amode |= amode_signed; + tmp = (value & 0xffff); + op->addr = tmp; + op->amode |= amode_x; + + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::Cond(insn_t &insn, int value, int param) +{ + insn.auxpref |= value & 0x0f; + + if ( (!param) && ((value & 0x0f) > 0x00) ) + insn.auxpref |= aux_comma_cc; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::xe_xt(insn_t &insn, int value, int param) +{ + static const uchar regs[] = { cc_ge, cc_gt, cc_le, cc_lt }; + + insn.auxpref |= regs[(value & 0x01) + (param ? 2 : 0)]; + insn.auxpref |= aux_comma_cc; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::lim_xx(insn_t &, int value, int) +{ + static const uchar regs1[] = { A0, A0, A1, A1 }; + static const uchar regs2[] = { uchar(-1), A1, A0, uchar(-1) }; + + opreg(regs1[value & 0x03]); + + if ( regs2[value & 0x03] != uchar(-1) ) + { + op++; + opreg(regs2[value & 0x03]); + } + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::rJ_rI(insn_t &, int value,int param) +{ + // jjiiwqq + + op->type = o_phrase; + op->reg = param ? (value & 0x03) : ((value & 0x04) >> 2) + 4; + op->phtype = param ? (value & 0x0018) >> 3 : (value & 0x0060) >> 5; + op++; + + op->type = o_phrase; + op->reg = param ? ((value & 0x04) >> 2) + 4 : (value & 0x03); + op->phtype = param ? (value & 0x0060) >> 5 : (value & 0x0018) >> 3; + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::rI(insn_t &, int value,int) +{ + // iiqq + + op->type = o_phrase; + op->reg = (value & 0x03); + op->phtype = (value & 0x0c) >> 2; + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::AB(insn_t &, int value,int) +{ + static const uchar regs[] = { B0, B1, A0, A1 }; + + opreg(regs[value & 0x03]); + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::ABLH(insn_t &, int value,int) +{ + static const uchar regs[] = { B0L, B0H, B1L, B1H, A0L, A0H, A1L, A1H }; + + opreg(regs[value & 0x07]); + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::indir_reg(insn_t &, int value,int param) +{ + op->type = o_phrase; + op->reg = uint16(param + value); + op->phtype = 4; + op++; + + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::laddr_pgm(insn_t &insn, int value,int) +{ + op->amode |= amode_p; + op->addr = value & 0xffff; + insn.size++; + + make_o_mem(insn); + op++; + + return true; +} + +//---------------------------------------------------------------------- +//lint -e{1764} 'insn' could be declared const ref +bool oakdsp_t::addr_rel_pgm(insn_t &insn, int value, int) +{ + value = (value & 0x7f); + op->amode |= amode_p; + + if ( value & 0x40 ) + { + value = (value^0x7f) + 1; + op->addr = insn.ea + 1 - value; + } + else + { + op->addr = insn.ea + 1 + value; + } + + make_o_mem(insn); + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::ext_XX(insn_t &insn, int value, int) +{ + return rrrrr(insn, (value & 0x01) + ((value & 0x04) >> 1), EXT0 + mix_mode); +} + +//---------------------------------------------------------------------- +bool oakdsp_t::context(insn_t &insn, int value,int) +{ + if ( value ) + insn.auxpref |= aux_iret_context; + return true; +} +//---------------------------------------------------------------------- +bool oakdsp_t::swap(insn_t &, int value,int) +{ + op->type = o_textphrase; + op->phrase = value & 0x0f; + op->phtype = text_swap; + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::banke(insn_t &, int value,int) +{ + op->type = o_textphrase; + op->phrase = value & 0x0f; + op->phtype = text_banke; + return true; +} +//---------------------------------------------------------------------- +bool oakdsp_t::cntx(insn_t &, int value,int) +{ + op->type = o_textphrase; + op->phrase = (uint16)value; + op->phtype = text_cntx; + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::dmod(insn_t &, int value,int) +{ + op->type = o_textphrase; + op->phrase = (uint16)value; + op->phtype = text_dmod; + return true; +} + +//---------------------------------------------------------------------- +bool oakdsp_t::eu(insn_t &, int,int) +{ + op->type = o_textphrase; + op->phtype = text_eu; + return true; +} + +//---------------------------------------------------------------------- +// singleton to init table thread-aware +struct table_t +{ + static int count() { return qnumber(table); } + static const opcode_t &get(int opcode) + { + static const table_t instance; //lint !e1788 only by its constructor/destructor + return instance.table[opcode]; //lint !e727 static local symbol 'instance' of type 'const struct table_t' not explicitly initialized + } + +private: + opcode_t table[124] = + { + { "0000000000000000", OAK_Dsp_nop, {{0}}, 1 }, + { "0000000000100000", OAK_Dsp_trap, {{0}}, 1 }, + { "0000000010fmmnnn", OAK_Dsp_modr, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::dmod, 0x0020}}, 1 }, + { "0000000001arrrrr", OAK_Dsp_movp, {{&oakdsp_t::indir_reg, 0x20, A0}, {&oakdsp_t::rrrrr, 0x001f}}, 3 }, + { "000000010abrrrrr", OAK_Dsp_movs, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "000000011abmmnnn", OAK_Dsp_movs, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "00000100vvvvvvvv", OAK_Dsp_lpg, {{&oakdsp_t::s_Imm, 0x00ff}}, 1 }, + { "00001000vvvvvvvv", OAK_Dsp_mpyi, {{&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::s_Imm, 0x00ff}}, 1 }, + { "00000101vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, + { "00001001vvvvvvvv", OAK_Dsp_rets, {{&oakdsp_t::s_Imm, 0x00ff}}, 3 }, + { "00001101---rrrrr", OAK_Dsp_rep, {{&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "00001100vvvvvvvv", OAK_Dsp_rep, {{&oakdsp_t::s_Imm, 0x00ff}}, 1 }, + { "0000011iiqqmmnnn", OAK_Dsp_movp, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::rI, 0x01e0}}, 3 }, + { "0000111adddddddd", OAK_Dsp_divs, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "0000x01vvvvvvvvv", OAK_Dsp_load, {{&oakdsp_t::s_Imm, 0x01ff}, {&oakdsp_t::rrrrr, 0x0800, MODI|mix_mode}}, 1 }, + { "000110rrrrrmmnnn", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x03e0}, {&oakdsp_t::mmnnn, 0x001f}}, 1 }, + { "000111rrrrrmmnnn", OAK_Dsp_mov, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::rrrrr, 0x03e0}}, 1 }, + { "00010ooooooocccc", OAK_Dsp_callr, {{&oakdsp_t::addr_rel_pgm, 0x07f0}, {&oakdsp_t::Cond, 0x000f}}, 2 }, + { "0010nnn0dddddddd", OAK_Dsp_mov, {{&oakdsp_t::nnn, 0x0e00}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, + { "001a0001vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::rrrrr, 0x1000, A0L|mix_mode}}, 1 }, + { "001a0101vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::rrrrr, 0x1000, A0H|mix_mode}}, 1 }, + { "001nnn11vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::nnn, 0x1c00}}, 1 }, + { "001x1x01vvvvvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::ext_XX, 0x1400}}, 1 }, + { "0011ABL0dddddddd", OAK_Dsp_mov, {{&oakdsp_t::ABLH, 0x0e00}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, + { "0100001110000000", OAK_Dsp_eint, {{0}}, 1 }, + { "0100001111000000", OAK_Dsp_dint, {{0}}, 1 }, + { "0100000110000000", OAK_Dsp_br_u, {{&oakdsp_t::laddr_pgm, 0xffff0000}}, 2 }, + { "0100010110000000", OAK_Dsp_ret_u, {{0}}, 2 }, + { "01001101100000vv", OAK_Dsp_load, {{&oakdsp_t::s_Imm, 0x0003}, {&oakdsp_t::rrrrr, 0, PS}}, 1 }, + { "01000101110f0000", OAK_Dsp_reti_u, {{&oakdsp_t::context, 0x0010}}, 2 }, + { "010001011000cccc", OAK_Dsp_ret, {{&oakdsp_t::Cond, 0x000f, 1}}, 2 }, + { "010000011000cccc", OAK_Dsp_br, {{&oakdsp_t::laddr_pgm, 0xffff0000}, {&oakdsp_t::Cond, 0x000f}}, 2 }, + { "010000011100cccc", OAK_Dsp_call, {{&oakdsp_t::laddr_pgm, 0xffff0000}, {&oakdsp_t::Cond, 0x000f}}, 2 }, + { "01000111110rrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0, MIXP}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "01000111111rrrrr", OAK_Dsp_mov, {{&oakdsp_t::indir_reg, 0, SP}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "01000101110fcccc", OAK_Dsp_reti, {{&oakdsp_t::Cond, 0x000f, 1}, {&oakdsp_t::context, 0x0010}}, 1 }, + { "0100100110--swap", OAK_Dsp_swap, {{&oakdsp_t::swap, 0x000f}}, 1 }, + { "0100111111-rrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0, ICR}}, 1 }, + { "0100111110-vvvvv", OAK_Dsp_mov, {{&oakdsp_t::s_Imm, 0x001f}, {&oakdsp_t::rrrrr, 0, ICR}}, 1 }, + { "0100100111xx----", OAK_Dsp_lim, {{&oakdsp_t::lim_xx, 0x0030}}, 1 }, + { "010010111---bank", OAK_Dsp_banke, {{&oakdsp_t::banke, 0x000f}}, 1 }, + { "0100nnn01abvvvvv", OAK_Dsp_movsi, {{&oakdsp_t::nnn, 0x0e00}, {&oakdsp_t::AB, 0x0060}, {&oakdsp_t::s_ImmS, 0x001f, 5}}, 1 }, + { "0100xxxa0ooooooo", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0e00, 1}, {&oakdsp_t::rb_rel_short, 0x007f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "0101111101000000", OAK_Dsp_push, {{&oakdsp_t::l_Imm, 0xffff0000}}, 2 }, + { "01011110010rrrrr", OAK_Dsp_push, {{&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "01011110011rrrrr", OAK_Dsp_pop, {{&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "01011110100rrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0, MIXP}}, 1 }, + { "0101111011brrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::B, 0x0020}}, 1 }, + { "01011101000rrrrr", OAK_Dsp_bkrep, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::laddr_pgm, 0xffff0000}}, 2 }, + { "0101111-000rrrrr", OAK_Dsp_mov, {{&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::rrrrr, 0x001f}}, 2 }, + { "0101111b001-----", OAK_Dsp_mov, {{&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::B, 0x0100}}, 2 }, + { "010111111jjiiwqq", OAK_Dsp_movd, {{&oakdsp_t::rJ_rI, 0x007f, 1}}, 4 }, + { "01011100vvvvvvvv", OAK_Dsp_bkrep, {{&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::laddr_pgm, 0xffff0000}}, 2 }, + { "010110RRRRRrrrrr", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0x03e0}}, 1 }, + { "01010ooooooo0000", OAK_Dsp_brr_u, {{&oakdsp_t::addr_rel_pgm, 0x07f0}}, 2 }, + { "01010ooooooocccc", OAK_Dsp_brr, {{&oakdsp_t::addr_rel_pgm, 0x07f0}, {&oakdsp_t::Cond, 0x000f}}, 2 }, + { "01101101dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, + { "011nnn00dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::nnn, 0x1c00}}, 1 }, + { "011AB001dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::AB, 0x1800}}, 1 }, + { "011ABL10dddddddd", OAK_Dsp_mov, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::ABLH, 0x1c00}}, 1 }, + { "011A0101dddddddd", OAK_Dsp_mov_eu, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x1000}, {&oakdsp_t::eu, 0x0}}, 1 }, + { "011ab011dddddddd", OAK_Dsp_movs, {{&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::AB, 0x1800}}, 1 }, + { "011b11110fffcccc", OAK_Dsp_proc, {{&oakdsp_t::MODA_B, 0x0070, 1}, {&oakdsp_t::B, 0x1000}, {&oakdsp_t::Cond, 0x000f}}, 1 }, + { "011a0111ffffcccc", OAK_Dsp_proc, {{&oakdsp_t::MODA_B, 0x00f0}, {&oakdsp_t::A, 0x1000}, {&oakdsp_t::Cond, 0x000f}}, 1 }, + { "01111101dddddddd", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0, SV}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, + { "100000fa011mm000", OAK_Dsp_maxd, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::xe_xt, 0x0200, 0}}, 1 }, + { "100001fa011mm000", OAK_Dsp_max, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::xe_xt, 0x0200, 0}}, 1 }, + { "10001-fa011mm000", OAK_Dsp_min, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::xe_xt, 0x0200, 1}}, 1 }, + { "1000xxxa11000000", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0e00, 1}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, + { "1000xxx0111mmnnn", OAK_Dsp_proc, {{&oakdsp_t::ALB, 0x0e00}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::mmnnn, 0x001f}}, 2 }, + { "1000xxx1111rrrrr", OAK_Dsp_proc, {{&oakdsp_t::ALB, 0x0e00}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::rrrrr, 0x001f}}, 2 }, + { "1000-00x001mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::mmnnn, 0x001f}}, 1 }, + { "1000axxx001mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0800}}, 1 }, + { "1000-00x010rrrrr", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "1000axxx010rrrrr", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0800}}, 1 }, + { "1000-00x000mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::l_Imm, 0xffff0000}}, 2 }, + { "1000axxx000mmnnn", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::A, 0x0800}}, 2 }, + { "100xxxxa100mmnnn", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x1e00}, {&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "100xxxxa101rrrrr", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x1e00}, {&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1001000a110mmnnn", OAK_Dsp_msu, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, + { "1001010a110mmnnn", OAK_Dsp_norm, {{&oakdsp_t::A, 0x0100}, {&oakdsp_t::mmnnn, 0x001f}}, 2 }, + { "1001bbbb001mmnnn", OAK_Dsp_tstb, {{&oakdsp_t::s_Imm, 0x0f00}, {&oakdsp_t::mmnnn, 0x001f}}, 1 }, + { "1001bbbb000rrrrr", OAK_Dsp_tstb, {{&oakdsp_t::s_Imm, 0x0f00}, {&oakdsp_t::rrrrr, 0x001f}}, 1 }, + { "1001ab1AB1vvvvvv", OAK_Dsp_shfi, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::AB, 0x0180}, {&oakdsp_t::s_ImmS, 0x003f, 6}}, 1 }, + { "1001100a010mmnnn", OAK_Dsp_exp, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1001000a010rrrrr", OAK_Dsp_exp, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1001000a0110000b", OAK_Dsp_exp, {{&oakdsp_t::B, 0x0001}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "10011100010mmnnn", OAK_Dsp_exp, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, + { "10010100010rrrrr", OAK_Dsp_exp, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, + { "100101000110000b", OAK_Dsp_exp, {{&oakdsp_t::B, 0x0001}, {&oakdsp_t::rrrrr, 0, SV}}, 1 }, + { "1001100b110mmnnn", OAK_Dsp_mov, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::B, 0x0100}}, 1 }, + { "1001110a110rrrrr", OAK_Dsp_movr, {{&oakdsp_t::rrrrr, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1001110a111mmnnn", OAK_Dsp_movr, {{&oakdsp_t::mmnnn, 0x001f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "101xxxxadddddddd", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x1e00}, {&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1100xxxavvvvvvvv", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0e00, 1}, {&oakdsp_t::s_Imm, 0x00ff}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1101001111000000", OAK_Dsp_break, {{0}}, 1 }, + { "1101011110000000", OAK_Dsp_retd, {{0}}, 1 }, + { "1101011111000000", OAK_Dsp_retid, {{0}}, 1 }, + { "1101010a10000000", OAK_Dsp_calla, {{&oakdsp_t::A, 0x0100}}, 3 }, + { "11010011100f0000", OAK_Dsp_cntx, {{&oakdsp_t::cntx, 0x0010}}, 1 }, + { "110101001ab10000", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,REPC}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "110101001ab10001", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,DVM}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "110101001ab10010", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,ICR}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "110101001ab10011", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0,X}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "1101010a101110--", OAK_Dsp_mov, {{&oakdsp_t::ldirect, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, + { "1101010a101111--", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x0100, A0L|mix_mode}, {&oakdsp_t::ldirect, 0xffff0000}}, 2 }, + { "1101010a100110--", OAK_Dsp_mov, {{&oakdsp_t::rb_rel_long,0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, + { "1101010a100111--", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x0100, A0L|mix_mode}, {&oakdsp_t::rb_rel_long,0xffff0000}}, 2 }, + { "1101010a11011xxx", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0007, 1}, {&oakdsp_t::rb_rel_long, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, + { "1101010a11111xxx", OAK_Dsp_proc, {{&oakdsp_t::ALU_ALM, 0x0007, 1}, {&oakdsp_t::ldirect, 0xffff0000}, {&oakdsp_t::A, 0x0100}}, 2 }, + { "1101AB1011011000", OAK_Dsp_mov, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::rrrrr, 0x0000, X}}, 1 }, + { "1101AB1010011000", OAK_Dsp_mov, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::rrrrr, 0x0000, DVM}}, 1 }, + { "1101ab101AB10000", OAK_Dsp_mov, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::AB, 0x0060}}, 1 }, + { "1101000a1jjiiwqq", OAK_Dsp_msu, {{&oakdsp_t::rJ_rI, 0x007f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1101ab101AB0cccc", OAK_Dsp_shfc, {{&oakdsp_t::AB, 0x0c00}, {&oakdsp_t::AB, 0x0060}, {&oakdsp_t::Cond, 0x000f}}, 1 }, + { "1101100a1ooooooo", OAK_Dsp_mov, {{&oakdsp_t::rb_rel_short, 0x007f}, {&oakdsp_t::A, 0x0100}}, 1 }, + { "1101110a1ooooooo", OAK_Dsp_mov, {{&oakdsp_t::rrrrr, 0x0100, A0L|mix_mode}, {&oakdsp_t::rb_rel_short, 0x007f}}, 1 }, + { "11011x111vvvvvvv", OAK_Dsp_load, {{&oakdsp_t::s_Imm, 0x007f}, {&oakdsp_t::rrrrr, 0x0400, STEPI|mix_mode}}, 1 }, + { "1101-00x0jjiiwqq", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rJ_rI, 0x007f}}, 1 }, + { "1101axxx0jjiiwqq", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0700}, {&oakdsp_t::rJ_rI, 0x007f}, {&oakdsp_t::A, 0x0800}}, 1 }, + { "1110xxx1dddddddd", OAK_Dsp_proc, {{&oakdsp_t::ALB, 0x0e00}, {&oakdsp_t::l_Imm, 0xffff0000}, {&oakdsp_t::sdirect, 0x00ff}}, 2 }, + { "1110-000dddddddd", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0600, 1}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, + { "1110axx0dddddddd", OAK_Dsp_proc, {{&oakdsp_t::MUL, 0x0600, 1}, {&oakdsp_t::rrrrr, 0, Y}, {&oakdsp_t::sdirect, 0x00ff}, {&oakdsp_t::A, 0x0800}}, 1 }, + { "1111bbbbdddddddd", OAK_Dsp_tstb, {{&oakdsp_t::s_Imm, 0x0f00}, {&oakdsp_t::sdirect, 0x00ff}}, 1 }, + }; + + table_t() + { + gen_masks(); + } + ~table_t() = default; + table_t(const table_t&) = delete; + table_t &operator=(const table_t&) = delete; + + void gen_masks() + { + for ( auto &te : table ) + { + int len = strlen(te.recog); + for ( int b = 0; b < len; b++ ) + { + te.value <<= 1; + te.mask <<= 1; + + if ( te.recog[b] == '1' || te.recog[b] == '0' ) + te.mask++; + + if ( te.recog[b] == '1' ) + te.value++; + } + + for ( int j = 0; j < FUNCS_COUNT; j++ ) + { + if ( te.funcs[j].func ) + { + for ( int b = 0; b < 32; b++ ) + { + if ( te.funcs[j].mask & (1 << b) ) + break; + else + te.funcs[j].shift++; + } + } + } + } + } +}; + +//---------------------------------------------------------------------- +bool oakdsp_t::use_table(insn_t &insn, const opcode_t &ptr, uint code, int start, int end) +{ + for ( int j = start; j <= end; j++ ) + { + if ( !ptr.funcs[j].func ) + break; + int value = (code & ptr.funcs[j].mask) >> ptr.funcs[j].shift; + if ( !(this->*ptr.funcs[j].func)(insn, value, ptr.funcs[j].param) ) + return false; + } + return true; +} + +//---------------------------------------------------------------------- +void oakdsp_t::reset_ops(insn_t &insn) +{ + op = &insn.Op1; + for ( int i=0; i < UA_MAXOP; i++ ) + insn.ops[i].type = o_void; +} + +//---------------------------------------------------------------------- +int oakdsp_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + uint code = ua_32bits(insn); + uint prev_inst_code; + op = &insn.Op1; + int move_rb_to_reg = 0; + + int cnt = table_t::count(); + for ( int i = 0; i < cnt; i++ ) + { + const auto &te = table_t::get(i); + if ( (code & te.mask) == te.value ) + { + insn.itype = te.itype; + insn.cmd_cycles = te.cycles; + insn.size = 1; + + if ( !use_table(insn, te, code, 0, FUNCS_COUNT - 1) ) + { + reset_ops(insn); + continue; + } + + + + // mov #imm, pc --> near jump + if ( insn.itype == OAK_Dsp_mov + && insn.Op1.type == o_imm + && insn.Op2.type == o_reg + && insn.Op2.reg == PC ) + { + insn.Op1.type = o_near; + insn.Op1.dtype = dt_code; + insn.Op1.addr = insn.Op1.value; + insn.Op1.amode = amode_p; + } + + + // add(sub) #imm, reg after mov rb, reg instruction + // #imm --> local var + + if ( insn.ea != 0 ) + { + prev_inst_code = get_wide_byte(insn.ea - 1); + + if ( ((prev_inst_code & 0xfc1f) == 0x5806) + || ((prev_inst_code & 0xffdf) == 0x5ec6) ) + { + if ( (prev_inst_code & 0xfc1f) == 0x5806 ) // mov reg, reg + move_rb_to_reg = (prev_inst_code >> 5) & 0x1f; + else if ( (prev_inst_code & 0xffdf) == 0x5ec6 ) // mov reg, bx + move_rb_to_reg = B0 + ((prev_inst_code >> 5) & 0x01); + + if ( insn.Op1.type == o_imm + && (insn.Op2.reg == move_rb_to_reg + || (insn.Op2.reg == A0L && move_rb_to_reg == A0) + || (insn.Op2.reg == A1L && move_rb_to_reg == A1) + || (insn.Op2.reg == B0L && move_rb_to_reg == B0) + || (insn.Op2.reg == B1L && move_rb_to_reg == B1)) ) + { + int16 tmp = insn.Op1.value; + + switch ( insn.itype ) + { + case OAK_Dsp_sub: + case OAK_Dsp_subv: + tmp = - tmp; + //no break + case OAK_Dsp_add: + case OAK_Dsp_addv: + insn.Op1.addr = tmp; + insn.Op1.type = o_local; + insn.Op1.phtype = 1; // "#" + insn.Op1.amode |= amode_signed; + insn.Op1.amode |= amode_x; + break; + } + } + } + } + + + // add(sub) #imm, SP + // #imm --> signed imm + + if ( insn.Op1.type == o_imm && insn.Op2.type == o_reg && insn.Op2.reg == SP ) + { + switch ( insn.itype ) + { + case OAK_Dsp_add: + case OAK_Dsp_addv: + case OAK_Dsp_sub: + case OAK_Dsp_subv: + insn.Op1.amode |= amode_signed; + break; + } + } + return insn.size; + } + } + return 0; +} + +//-------------------------------------------------------------------------- +void interr(const insn_t &insn, const char *module) +{ + const char *name = NULL; + if ( insn.itype < OAK_Dsp_last ) + name = Instructions[insn.itype].name; + warning("%a(%s): internal error in %s", insn.ea, name, module); +} diff --git a/idasdk76/module/oakdsp/emu.cpp b/idasdk76/module/oakdsp/emu.cpp new file mode 100644 index 0000000..b0eb32a --- /dev/null +++ b/idasdk76/module/oakdsp/emu.cpp @@ -0,0 +1,420 @@ + +#include "oakdsp.hpp" +#include <segregs.hpp> +#include <frame.hpp> + +//---------------------------------------------------------------------- +ea_t oakdsp_t::calc_mem(const insn_t &insn, const op_t &x) const +{ + uint xaddr; + + if ( x.amode & amode_x ) + { + if ( x.amode & amode_short ) + { + sel_t dpage = get_sreg(insn.ea, PAGE); + if ( dpage == BADSEL ) + return BADSEL; + xaddr = ((dpage & 0xFF) << 8) | uint(x.addr); + } + else + { + xaddr = (uint)x.addr; + } + return xmem == BADADDR ? BADADDR : xmem + xaddr; + } + + return to_ea(insn.cs, x.addr); + +} +//------------------------------------------------------------------------ +void oakdsp_t::init_emu(void) +{ + delayed = false; + cycles = 0; +} + +//------------------------------------------------------------------------ +inline bool is_stkreg(int r) +{ + return r == SP; +} + +//------------------------------------------------------------------------ +int idaapi is_sp_based(const insn_t &, const op_t &x) +{ + return OP_SP_ADD | (x.phrase == SP ? OP_SP_BASED : OP_FP_BASED); +} + +//------------------------------------------------------------------------ +static void process_immediate_number(const insn_t &insn, int n) +{ + set_immd(insn.ea); + if ( is_defarg(get_flags(insn.ea), n) ) + return; + switch ( insn.itype ) + { + case OAK_Dsp_shfi: + case OAK_Dsp_movsi: + + op_dec(insn.ea, n); + break; + + case OAK_Dsp_lpg: + case OAK_Dsp_mpyi: + case OAK_Dsp_mov: + case OAK_Dsp_rets: + case OAK_Dsp_rep: + case OAK_Dsp_load: + case OAK_Dsp_push: + case OAK_Dsp_bkrep: + case OAK_Dsp_msu: + case OAK_Dsp_tstb: + case OAK_Dsp_or: + case OAK_Dsp_and: + case OAK_Dsp_xor: + case OAK_Dsp_add: + case OAK_Dsp_alm_tst0: + case OAK_Dsp_alm_tst1: + case OAK_Dsp_cmp: + case OAK_Dsp_sub: + case OAK_Dsp_alm_msu: + case OAK_Dsp_addh: + case OAK_Dsp_addl: + case OAK_Dsp_subh: + case OAK_Dsp_subl: + case OAK_Dsp_sqr: + case OAK_Dsp_sqra: + case OAK_Dsp_cmpu: + case OAK_Dsp_set: + case OAK_Dsp_rst: + case OAK_Dsp_chng: + case OAK_Dsp_addv: + case OAK_Dsp_alb_tst0: + case OAK_Dsp_alb_tst1: + case OAK_Dsp_cmpv: + case OAK_Dsp_subv: + case OAK_Dsp_mpy: + case OAK_Dsp_mpysu: + case OAK_Dsp_mac: + case OAK_Dsp_macus: + case OAK_Dsp_maa: + case OAK_Dsp_macuu: + case OAK_Dsp_macsu: + case OAK_Dsp_maasu: + + op_num(insn.ea, n); + break; + } +} + +//---------------------------------------------------------------------- +void oakdsp_t::add_near_ref(const insn_t &insn, const op_t &x, ea_t ea) +{ + cref_t ftype = fl_JN; + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + if ( !func_does_return(ea) ) + flow = false; + ftype = fl_CN; + } + insn.add_cref(ea, x.offb, ftype); +} + +//---------------------------------------------------------------------- +void oakdsp_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) +{ + switch ( x.type ) + { + case o_reg: + default: + break; + case o_imm: + process_immediate_number(insn, x.n); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, dr_O, x.amode & amode_signed ? OOF_SIGNED : 0); + break; + + case o_phrase: + if ( !is_forced && op_adds_xrefs(get_flags(insn.ea), x.n) ) + { + ea_t ea = insn.add_off_drefs(x, isload ? dr_R : dr_W, OOF_ADDR|OOFW_16); + if ( ea != BADADDR ) + insn.create_op_data(ea, x); + } + break; + case o_mem: + { + ea_t ea = calc_mem(insn, x); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + insn.create_op_data(ea, x); + } + break; + case o_near: + add_near_ref(insn, x, calc_mem(insn, x)); + break; + case o_textphrase: + break; + + case o_local: // local variables + if ( may_create_stkvars() ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL + && (pfn->flags & FUNC_FRAME) != 0 + && insn.create_stkvar(x, x.addr, STKVAR_VALID_SIZE) ) + { + op_stkvar(insn.ea, x.n); + } + } + break; + + } +} + +//---------------------------------------------------------------------- +static bool add_stkpnt(const insn_t &insn, sval_t delta) +{ + func_t *pfn = get_func(insn.ea); + if ( pfn == NULL ) + return false; + + return add_auto_stkpnt(pfn, insn.ea+insn.size, delta); +} + +//---------------------------------------------------------------------- +static void trace_sp(const insn_t &insn) +{ + + int16 frame; + + // trace SP changes + + switch ( insn.itype ) + { + case OAK_Dsp_reti_u: + case OAK_Dsp_retid: + case OAK_Dsp_reti: + add_stkpnt(insn, 1); + break; + + case OAK_Dsp_ret_u: + case OAK_Dsp_retd: + case OAK_Dsp_ret: + add_stkpnt(insn, 1); + break; + + case OAK_Dsp_rets: + add_stkpnt(insn, 1 + insn.Op1.value); + break; + + case OAK_Dsp_pop: + add_stkpnt(insn, 1); + break; + + case OAK_Dsp_push: + add_stkpnt(insn, -1); + break; + + case OAK_Dsp_addv: + if ( insn.Op1.type == o_imm + && insn.Op2.type == o_reg + && insn.Op2.reg == SP ) + { + frame = (uint16)insn.Op1.value; + add_stkpnt(insn, frame); + } + break; + + case OAK_Dsp_subv: + if ( insn.Op1.type == o_imm + && insn.Op2.type == o_reg + && insn.Op2.reg == SP ) + { + frame = (uint16)insn.Op1.value; + add_stkpnt(insn, -frame); + } + break; + + + } +} + +//---------------------------------------------------------------------- +int oakdsp_t::emu(const insn_t &insn) +{ + if ( segtype(insn.ea) == SEG_XTRN ) + return 1; + + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + bool flag3 = is_forced_operand(insn.ea, 2); + + // Determine if the next instruction should be executed + flow = (has_insn_feature(insn.itype, CF_STOP) != true); + + if ( has_insn_feature(insn.itype,CF_USE1) ) handle_operand(insn, insn.Op1, flag1, true); + if ( has_insn_feature(insn.itype,CF_USE2) ) handle_operand(insn, insn.Op2, flag2, true); + if ( has_insn_feature(insn.itype,CF_USE3) ) handle_operand(insn, insn.Op3, flag3, true); + + if ( has_insn_feature(insn.itype,CF_CHG1) ) handle_operand(insn, insn.Op1, flag1, false); + if ( has_insn_feature(insn.itype,CF_CHG2) ) handle_operand(insn, insn.Op2, flag2, false); + if ( has_insn_feature(insn.itype,CF_CHG3) ) handle_operand(insn, insn.Op3, flag3, false); + + + // check for DP changes + if ( insn.itype == OAK_Dsp_lpg ) + split_sreg_range(get_item_end(insn.ea), PAGE, insn.Op1.value & 0xFF, SR_auto); + if ( insn.itype == OAK_Dsp_mov + && insn.Op1.type == o_imm + && insn.Op2.type == o_reg + && insn.Op2.reg == ST1 ) + { + split_sreg_range(get_item_end(insn.ea), PAGE, insn.Op1.value & 0xFF, SR_auto); + } + + // Delayed Return + + cycles = insn.cmd_cycles; + delayed = false; + + insn_t prev_ins; + if ( decode_prev_insn(&prev_ins, insn.ea) != BADADDR ) + { + if ( prev_ins.itype == OAK_Dsp_retd || prev_ins.itype == OAK_Dsp_retid ) + delayed = true; + else + cycles += prev_ins.cmd_cycles; + + if ( !delayed ) + if ( decode_prev_insn(&prev_ins, prev_ins.ea) != BADADDR ) + if ( prev_ins.itype == OAK_Dsp_retd || prev_ins.itype == OAK_Dsp_retid ) + delayed = true; + } + + if ( delayed && (cycles > 1) ) + flow = false; + + // mov #imm, pc + + if ( insn.itype == OAK_Dsp_mov && insn.Op2.type == o_reg && insn.Op2.reg == PC ) + flow = false; + + if ( flow ) + add_cref(insn.ea, insn.ea+insn.size, fl_F); + + if ( may_trace_sp() ) + { + if ( !flow ) + recalc_spd(insn.ea); // recalculate SP register for the next insn + else + trace_sp(insn); + } + + return 1; +} + +//---------------------------------------------------------------------- +int may_be_func(const insn_t &) // can a function start here? + // arg: none, the instruction is in 'insn' + // returns: probability 0..100 +{ + return 0; +} + +//---------------------------------------------------------------------- +int oakdsp_t::is_sane_insn(const insn_t &insn, int /*nocrefs*/) const +{ + // disallow jumps to nowhere + if ( insn.Op1.type == o_near && !is_mapped(calc_mem(insn, insn.Op1)) ) + return 0; + + // disallow many nops in a now + int i = 0; + for ( ea_t ea=insn.ea; i < 32; i++,ea++ ) + if ( get_byte(ea) != 0 ) + break; + if ( i == 32 ) + return 0; + + return 1; +} + +//---------------------------------------------------------------------- +int idaapi is_align_insn(ea_t ea) +{ + insn_t insn; + if ( decode_insn(&insn, ea) < 1 ) + return 0; + switch ( insn.itype ) + { + case OAK_Dsp_nop: + break; + default: + return 0; + } + return insn.size; +} + +//---------------------------------------------------------------------- +bool idaapi create_func_frame(func_t *pfn) // create frame of newly created function +{ + bool std_vars_func = true; + + if ( pfn != NULL ) + { + if ( pfn->frame == BADNODE ) + { + ea_t ea = pfn->start_ea; + int regsize = 0; + + insn_t insn; + while ( ea < pfn->end_ea ) // check for register pushes + { + decode_insn(&insn, ea); + ea += insn.size; // count pushes + if ( (insn.itype == OAK_Dsp_push) && (insn.Op1.type == o_reg) ) + regsize++; + else + break; + } + + ea = pfn->start_ea; + int16 localsize = 0; + while ( ea < pfn->end_ea ) // check for frame creation + { + decode_insn(&insn, ea); + ea += insn.size; // try to detect ADDV #,SP + if ( (insn.itype == OAK_Dsp_addv) && (insn.Op1.type == o_imm) && (insn.Op2.type == o_reg) && (insn.Op2.reg == SP) ) + { + localsize = (uint16)insn.Op1.value; + break; + } + + // if found mov #, rb --> do not create frame + if ( (insn.itype == OAK_Dsp_mov) && (insn.Op1.type == o_imm) && (insn.Op2.type == o_reg) && (insn.Op2.reg == RB) ) + { + std_vars_func = false; + break; + } + + } + + if ( std_vars_func ) + { + pfn->flags |= FUNC_FRAME; + update_func(pfn); + } + + add_frame(pfn, -localsize, (ushort)regsize, 0); + + } + } + return 0; +} + +//---------------------------------------------------------------------- +int idaapi OAK_get_frame_retsize(const func_t * /*pfn*/) +{ + return 1; // 1 'byte' for the return address +} diff --git a/idasdk76/module/oakdsp/ins.cpp b/idasdk76/module/oakdsp/ins.cpp new file mode 100644 index 0000000..181f336 --- /dev/null +++ b/idasdk76/module/oakdsp/ins.cpp @@ -0,0 +1,123 @@ + +#include "oakdsp.hpp" + +const instruc_t Instructions[] = +{ + { "", 0 }, // Unknown Operation + { "", 0 }, // cmd need further process + // ALU-ALM subcodes + { "or", CF_USE1|CF_USE2|CF_CHG2 }, // 000 Logical Or + { "and", CF_USE1|CF_USE2|CF_CHG2 }, // 001 And + { "xor", CF_USE1|CF_USE2|CF_CHG2 }, // 010 Exclusive Or + { "add", CF_USE1|CF_USE2|CF_CHG2 }, // 011 Add + { "tst0", CF_USE1|CF_USE2 }, // 100 Test Bit-field for Zeros + { "tst1", CF_USE1|CF_USE2 }, // 101 Test Bit-field for Ones + { "cmp", CF_USE1|CF_USE2 }, // 110 Compare + { "sub", CF_USE1|CF_USE2|CF_CHG2 }, // 111 Subtract + // ALM subcodes + { "msu", CF_USE1|CF_USE2|CF_CHG2 }, // 1000 Multiply and Subtract Previous Product + { "addh", CF_USE1|CF_USE2|CF_CHG2 }, // 1001 Add to High Accumulator + { "addl", CF_USE1|CF_USE2|CF_CHG2 }, // 1010 Add to Low Accumulator + { "subh", CF_USE1|CF_USE2|CF_CHG2 }, // 1011 Subtract from High Accumulator + { "subl", CF_USE1|CF_USE2|CF_CHG2 }, // 1100 Subtract from Low Accumulator + { "sqr", CF_USE1|CF_USE2|CF_CHG2 }, // 1101 Square + { "sqra", CF_USE1|CF_USE2|CF_CHG2 }, // 1110 Square and Accumulate Previous Product + { "cmpu", CF_USE1|CF_USE2 }, // 1111 Compare Unsigned + // MODA-MODB subcodes conditional + { "shr", CF_USE1|CF_CHG1 }, // 000 Shift Accumulator Right + { "shr4", CF_USE1|CF_CHG1 }, // 001 Shift Accumulator Right by 4 Bits + { "shl", CF_USE1|CF_CHG1 }, // 010 Shift Accumulator Left + { "shl4", CF_USE1|CF_CHG1 }, // 011 Shift Accumulator Left by 4 Bits + { "ror", CF_USE1|CF_CHG1 }, // 100 Rotate Accumulator Right through Carry + { "rol", CF_USE1|CF_CHG1 }, // 101 Rotate Accumulator Left through Carry + { "clr", CF_CHG1 }, // 110 Clear Accumulator + { "", 0 }, // 111 Mod Reserved + // MODA subcodes conditional + { "not", CF_USE1|CF_CHG1 }, // 1000 Logical Not + { "neg", CF_USE1|CF_CHG1 }, // 1001 2's Complement of aX-accumulator + { "rnd", CF_USE1|CF_CHG1 }, // 1010 Round Upper 20 Bits of aX-accumulator + { "pacr", CF_USE1|CF_CHG1 }, // 1011 Product Move and Round to aX-accumulator + { "clrr", CF_USE1|CF_CHG1 }, // 1100 Clear and Round aX-accumulator + { "inc", CF_USE1|CF_CHG1 }, // 1101 Increment Accumulator by One + { "dec", CF_USE1|CF_CHG1 }, // 1110 Decrement aX-accumulator by One + { "copy", CF_USE1|CF_CHG1 }, // 1111 Copy aX-accumulator + // --- + { "norm", CF_USE1|CF_CHG1|CF_USE2 }, // Normalize + { "divs", CF_USE1|CF_USE2|CF_CHG2 }, // Division Step + // ALB subcodes + { "set", CF_USE1|CF_USE2|CF_CHG2 }, // 000 Set Bit-field + { "rst", CF_USE1|CF_USE2|CF_CHG2 }, // 001 Reset Bit-field + { "chng", CF_USE1|CF_USE2|CF_CHG2 }, // 010 Change Bit-field + { "addv", CF_USE1|CF_USE2|CF_CHG2 }, // 011 Add Long Immediate Value or Data Memory Location + { "tst0", CF_USE1|CF_USE2 }, // 100 Test Bit-field for Zeros + { "tst1", CF_USE1|CF_USE2 }, // 101 Test Bit-field for Ones + { "cmpv", CF_USE1|CF_USE2 }, // 110 Compare Long Immediate Value to Register or Data Memory Location + { "subv", CF_USE1|CF_USE2|CF_CHG2 }, // 111 Subtract Long Immediate Value from a Register or a Data Memory Location + // --- + { "maxd", CF_USE1|CF_CHG1|CF_USE2 }, // Maximum between Data Memory Location and Accumulator + { "max", CF_USE1|CF_CHG1|CF_USE2 }, // Maximum between Two Accumulators + { "min", CF_USE1|CF_CHG1|CF_USE2 }, // Minimum between Two Accumulators + { "lim", CF_USE1|CF_CHG1|CF_USE2 }, // Limit Accumulator (lim aX[, aX]) + // MUL subcodes + { "mpy", CF_USE1|CF_USE2 }, // 000 Multiply + { "mpysu", CF_USE1|CF_USE2 }, // 001 Multiply Signed by Unsigned + { "mac", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // 010 Multiply and Accumulate Previous Product + { "macus", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // 011 Multiply Unsigned by Signed and Accumulate Previous Product + { "maa", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // 100 Multiply and Accumulate Aligned Previous Product + { "macuu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // 101 Multiply Unsigned by Unsigned and Accumulate Previous Product + { "macsu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // 110 Multiply Signed by Unsigned and Accumulate Previous Product + { "maasu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // 111 Multiply Signed by Unsigned and Accumulate Aligned Previous Product + //--- + { "mpyi", CF_USE1|CF_USE2 }, // Multiply Signed Short Immediate + { "msu", CF_USE1|CF_USE2|CF_USE3|CF_CHG3 }, // Multiply and Subtract Previous Product + { "tstb", CF_USE1|CF_USE2 }, // Test Specific Bit + { "shfc", CF_USE1|CF_USE2|CF_CHG2 }, // Shift Accumulators according to Shift Value Register + { "shfi", CF_USE1|CF_USE2|CF_CHG2|CF_USE3 }, // Shift Accumulators by an Immediate Shift Value + { "exp", CF_USE1|CF_USE2|CF_CHG2 }, // Evaluate the Exponent Value + //--- + { "mov", CF_USE1|CF_CHG2 }, // Move Data + { "movp", CF_USE1|CF_CHG2 }, // Move from Program Memory into Data Memory + { "movs", CF_USE1|CF_CHG2 }, // Move and Shift According to Shift Value Register + { "movsi", CF_USE1|CF_USE2|CF_CHG2|CF_USE3 }, // Move and Shift According to an Immediate Shift Value + { "movr", CF_USE1|CF_CHG2 }, // Move and Round + { "movd", CF_USE1|CF_CHG2 }, // Move from Data Memory into Program Memory + //--- + { "push", CF_USE1 }, // Push Register or Long Immediate Value onto Stack + { "pop", CF_USE1|CF_CHG1 }, // Pop from Stack into Register + //--- + { "swap", CF_USE1 }, // Swap aX- and bX-accumulators + { "banke", CF_USE1 }, // Bank Exchange + { "rep", CF_USE1 }, // Repeat Next Instruction + { "bkrep", CF_USE1|CF_USE2 }, // Block-Repeat + { "break", 0 }, // Break from Block-repeat + //--- + { "br", CF_USE1|CF_JUMP }, // Conditional Branch + { "brr", CF_USE1|CF_JUMP }, // Relative Conditional Branch + { "br", CF_USE1|CF_STOP|CF_JUMP }, // UnConditional Branch + { "brr", CF_USE1|CF_STOP|CF_JUMP }, // Relative UnConditional Branch + { "call", CF_USE1|CF_CALL }, // Conditional Call Subroutine + { "callr", CF_USE1|CF_CALL }, // Relative Conditional Call Subroutine + { "calla", CF_USE1 }, // Call Subroutine at Location Specified by Accumulator + //--- + { "ret", 0 }, // Return Conditionally + { "ret", CF_STOP }, // Return UnConditionally + { "retd", 0 }, // Delayed Return + { "reti", 0 }, // Return from Interrupt Conditionally + { "reti", CF_STOP }, // Return from Interrupt UnConditionally + { "retid", 0 }, // Delayed Return from Interrupt + { "rets", CF_USE1|CF_STOP }, // Return with Short Immediate Parameter + //--- + { "cntx", CF_USE1 }, // Context Switching Store or Restore + { "nop", 0 }, // No operation + { "modr", CF_USE1|CF_USE2 }, // Modify rN + { "dint", 0 }, // Disable Interrupt + { "eint", 0 }, // Enable Interrupt + //--- + { "trap", CF_STOP }, // Software Interrupt + //--- + { "lpg", CF_USE1 }, // Load the Page Bits + { "load", CF_USE1|CF_CHG2 }, // Load Specific Fields into Registers + { "mov", CF_USE1|CF_CHG2|CF_USE3 }, // Move Data, eu +}; + +CASSERT(qnumber(Instructions) == OAK_Dsp_last); diff --git a/idasdk76/module/oakdsp/ins.hpp b/idasdk76/module/oakdsp/ins.hpp new file mode 100644 index 0000000..e520987 --- /dev/null +++ b/idasdk76/module/oakdsp/ins.hpp @@ -0,0 +1,128 @@ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ +OAK_Dsp_null = 0, // Unknown Operation +OAK_Dsp_proc, // cmd need further process +// ALU-ALM subcodes +OAK_Dsp_or, // 000 Logical Or +OAK_Dsp_and, // 001 And +OAK_Dsp_xor, // 010 Exclusive Or +OAK_Dsp_add, // 011 Add +OAK_Dsp_alm_tst0, // 100 Test Bit-field for Zeros +OAK_Dsp_alm_tst1, // 101 Test Bit-field for Ones +OAK_Dsp_cmp, // 110 Compare +OAK_Dsp_sub, // 111 Subtract +// ALM subcodes +OAK_Dsp_alm_msu, // 1000 Multiply and Subtract Previous Product +OAK_Dsp_addh, // 1001 Add to High Accumulator +OAK_Dsp_addl, // 1010 Add to Low Accumulator +OAK_Dsp_subh, // 1011 Subtract from High Accumulator +OAK_Dsp_subl, // 1100 Subtract from Low Accumulator +OAK_Dsp_sqr, // 1101 Square +OAK_Dsp_sqra, // 1110 Square and Accumulate Previous Product +OAK_Dsp_cmpu, // 1111 Compare Unsigned +// MODA-MODB subcodes conditional +OAK_Dsp_shr, // 000 Shift Accumulator Right +OAK_Dsp_shr4, // 001 Shift Accumulator Right by 4 Bits +OAK_Dsp_shl, // 010 Shift Accumulator Left +OAK_Dsp_shl4, // 011 Shift Accumulator Left by 4 Bits +OAK_Dsp_ror, // 100 Rotate Accumulator Right through Carry +OAK_Dsp_rol, // 101 Rotate Accumulator Left through Carry +OAK_Dsp_clr, // 110 Clear Accumulator +OAK_Dsp_mod_reserved, // 111 Mod Reserved +// MODA subcodes conditional +OAK_Dsp_not, // 1000 Logical Not +OAK_Dsp_neg, // 1001 2's Complement of aX-accumulator +OAK_Dsp_rnd, // 1010 Round Upper 20 Bits of aX-accumulator +OAK_Dsp_pacr, // 1011 Product Move and Round to aX-accumulator +OAK_Dsp_clrr, // 1100 Clear and Round aX-accumulator +OAK_Dsp_inc, // 1101 Increment Accumulator by One +OAK_Dsp_dec, // 1110 Decrement aX-accumulator by One +OAK_Dsp_copy, // 1111 Copy aX-accumulator +// --- +OAK_Dsp_norm, // Normalize +OAK_Dsp_divs, // Division Step +// ALB subcodes +OAK_Dsp_set, // 000 Set Bit-field +OAK_Dsp_rst, // 001 Reset Bit-field +OAK_Dsp_chng, // 010 Change Bit-field +OAK_Dsp_addv, // 011 Add Long Immediate Value or Data Memory Location +OAK_Dsp_alb_tst0, // 100 Test Bit-field for Zeros +OAK_Dsp_alb_tst1, // 101 Test Bit-field for Ones +OAK_Dsp_cmpv, // 110 Compare Long Immediate Value to Register or Data Memory Location +OAK_Dsp_subv, // 111 Subtract Long Immediate Value from a Register or a Data Memory Location +// --- +OAK_Dsp_maxd, // Maximum between Data Memory Location and Accumulator +OAK_Dsp_max, // Maximum between Two Accumulators +OAK_Dsp_min, // Minimum between Two Accumulators +OAK_Dsp_lim, // Limit Accumulator (lim aX[, aX]) +// MUL subcodes +OAK_Dsp_mpy, // 000 Multiply +OAK_Dsp_mpysu, // 001 Multiply Signed by Unsigned +OAK_Dsp_mac, // 010 Multiply and Accumulate Previous Product +OAK_Dsp_macus, // 011 Multiply Unsigned by Signed and Accumulate Previous Product +OAK_Dsp_maa, // 100 Multiply and Accumulate Aligned Previous Product +OAK_Dsp_macuu, // 101 Multiply Unsigned by Unsigned and Accumulate Previous Product +OAK_Dsp_macsu, // 110 Multiply Signed by Unsigned and Accumulate Previous Product +OAK_Dsp_maasu, // 111 Multiply Signed by Unsigned and Accumulate Aligned Previous Product +//--- +OAK_Dsp_mpyi, // Multiply Signed Short Immediate +OAK_Dsp_msu, // Multiply and Subtract Previous Product +OAK_Dsp_tstb, // Test Specific Bit +OAK_Dsp_shfc, // Shift Accumulators according to Shift Value Register +OAK_Dsp_shfi, // Shift Accumulators by an Immediate Shift Value +OAK_Dsp_exp, // Evaluate the Exponent Value +//--- +OAK_Dsp_mov, // Move Data +OAK_Dsp_movp, // Move from Program Memory into Data Memory +OAK_Dsp_movs, // Move and Shift According to Shift Value Register +OAK_Dsp_movsi, // Move and Shift According to an Immediate Shift Value +OAK_Dsp_movr, // Move and Round +OAK_Dsp_movd, // Move from Data Memory into Program Memory +//--- +OAK_Dsp_push, // Push Register or Long Immediate Value onto Stack +OAK_Dsp_pop, // Pop from Stack into Register +//--- +OAK_Dsp_swap, // Swap aX- and bX-accumulators +OAK_Dsp_banke, // Bank Exchange +OAK_Dsp_rep, // Repeat Next Instruction +OAK_Dsp_bkrep, // Block-Repeat +OAK_Dsp_break, // Break from Block-repeat +//--- +OAK_Dsp_br, // Conditional Branch +OAK_Dsp_brr, // Relative Conditional Branch +OAK_Dsp_br_u, // UnConditional Branch +OAK_Dsp_brr_u, // Relative UnConditional Branch +OAK_Dsp_call, // Conditional Call Subroutine +OAK_Dsp_callr, // Relative Conditional Call Subroutine +OAK_Dsp_calla, // Call Subroutine at Location Specified by Accumulator +//--- +OAK_Dsp_ret, // Return Conditionally +OAK_Dsp_ret_u, // Return UnConditionally +OAK_Dsp_retd, // Delayed Return +OAK_Dsp_reti, // Return from Interrupt Conditionally +OAK_Dsp_reti_u, // Return from Interrupt UnConditionally +OAK_Dsp_retid, // Delayed Return from Interrupt +OAK_Dsp_rets, // Return with Short Immediate Parameter +//--- +OAK_Dsp_cntx, // Context Switching Store or Restore +OAK_Dsp_nop, // No operation +OAK_Dsp_modr, // Modify rN +OAK_Dsp_dint, // Disable Interrupt +OAK_Dsp_eint, // Enable Interrupt +//--- +OAK_Dsp_trap, // Software Interrupt +//--- +OAK_Dsp_lpg, // Load the Page Bits +OAK_Dsp_load, // Load Specific Fields into Registers +OAK_Dsp_mov_eu, // Move Data, eu +OAK_Dsp_last, + +}; + +#endif diff --git a/idasdk76/module/oakdsp/makefile b/idasdk76/module/oakdsp/makefile new file mode 100644 index 0000000..0073e7d --- /dev/null +++ b/idasdk76/module/oakdsp/makefile @@ -0,0 +1,58 @@ +PROC=oakdsp +CONFIGS=oakdsp.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp oakdsp.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp oakdsp.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp oakdsp.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp oakdsp.hpp \ + out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp oakdsp.hpp reg.cpp diff --git a/idasdk75/module/oakdsp/oakdsp.cfg b/idasdk76/module/oakdsp/oakdsp.cfg similarity index 100% rename from idasdk75/module/oakdsp/oakdsp.cfg rename to idasdk76/module/oakdsp/oakdsp.cfg diff --git a/idasdk76/module/oakdsp/oakdsp.hpp b/idasdk76/module/oakdsp/oakdsp.hpp new file mode 100644 index 0000000..f14f5c9 --- /dev/null +++ b/idasdk76/module/oakdsp/oakdsp.hpp @@ -0,0 +1,231 @@ + +#ifndef _OAKDSP_HPP +#define _OAKDSP_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include "../iohandler.hpp" + +//------------------------------------------------------------------ + +#define aux_cc 0x000F // condition code +#define aux_comma_cc 0x0010 // comma before cond +#define aux_iret_context 0x0020 + +#define cmd_cycles insnpref + +#define phtype specflag1 // o_phrase: phrase type +// 0 (Rn) +// 1 (Rn)+1 +// 2 (Rn)-1 +// 3 (Rn)+s +// 4 (any_reg) + +#define amode specflag2 // addressing options & other +#define amode_short 0x01 +#define amode_long 0x02 +#define amode_x 0x04 // X: +#define amode_p 0x08 // P: +#define amode_neg 0x10 // - +#define amode_signed 0x10 // - if x<0 + + +#define o_textphrase o_idpspec0 // text type +#define o_local o_idpspec1 + +#define textphtype specflag1 // o_texttype: phrase type + +#define text_swap 0x01 +// (a0, b0) +// (a0, b1) +// (a1, b0) +// (a1, b1) +// (a0, b0), (a1, b1) +// (a0, b1), (a1, b0) +// (a0, b0, a1) +// (a0, b1, a1) +// (a1, b0, a0) +// (a1, b1, a0) +// (b0, a0, b1) +// (b0, a1, b1) +// (b1, a0, b0) +// (b1, a1, b0) + +#define text_banke 0x02 +//[r0], [r1], [r4], [cfgi] + +#define text_cntx 0x03 +// s +// r + +#define text_dmod 0x04 +// dmod + +#define text_eu 0x05 +// eu + +#define mix_mode 0x80000000 // Func rrrrr should use both input value and param + +//------------------------------------------------------------------ +#define UAS_GNU 0x0001 // GNU assembler +//------------------------------------------------------------------ +enum RegNo +{ + R0, R1, R2, R3, R4, R5, // DAAU Registers + RB, // Base Register + Y, // Input Register + ST0, ST1, ST2, // Status Registers + P, // Output Register + PC, // Program Counter + SP, // Software Stack Pointer + CFGI, CFGJ, // DAAU Configuration Registers + B0H, B1H, B0L, B1L, // Accumulator B + EXT0, EXT1, EXT2, EXT3, // External registers + A0, A1, A0L, A1L, A0H, A1H, // Accumulator A + LC, // Loop Counter + SV, // Shift Value Register + X, // Input Register + DVM, // Data Value Match Register + MIXP, // Minimal/Maximal Pointer Register + ICR, // Internal Configuration Register + PS, // Product Shifter Control + REPC, // Internal Repeat Counter + B0, B1, // Accumulator B + MODI,MODJ, // Modulo Modifier + STEPI, STEPJ, // Linear (Step) Modifier + PAGE, // Short Direct Addressing Mode Page + vCS, vDS, // virtual registers for code and data segments +}; + + +//------------------------------------------------------------------ +// condition codes +enum cc_t +{ + cc_true, // Always + cc_eq, // Equal to zero Z = 1 + cc_neq, // Not equal to zero Z = 0 + cc_gt, // Greater than zero M = 0 and Z = 0 + cc_ge, // Greater than or equal to zero M = 0 + cc_lt, // Less than zero M =1 + cc_le, // Less than or equal to zero M = 1 or Z = 1 + cc_nn, // Normalized flag is cleared N = 0 + cc_v, // Overflow flag is set V = 1 + cc_c, // Carry flag is set C = 1 + cc_e, // Extension flag is set E = 1 + cc_l, // Limit flag is set L = 1 + cc_nr, // flag is cleared R = 0 + cc_niu0, // Input user pin 0 is cleared + cc_iu0, // Input user pin 0 is set + cc_iu1, // Input user pin 1 is set +}; + +//------------------------------------------------------------------ +void interr(const insn_t &insn, const char *module); + +int idaapi is_align_insn(ea_t ea); +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_sp_based(const insn_t &insn, const op_t &x); +int idaapi OAK_get_frame_retsize(const func_t *pfn); + +int is_jump_func(const func_t *pfn, ea_t *jump_target); +int may_be_func(const insn_t &insn); // can a function start here? + +//------------------------------------------------------------------ +struct opcode_t; + +struct oakdsp_iohandler_t : public iohandler_t +{ + struct oakdsp_t ± + oakdsp_iohandler_t(oakdsp_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual const char *iocallback(const ioports_t &iop, const char *line) override; +}; + +struct oakdsp_t : public procmod_t +{ + netnode helper; + oakdsp_iohandler_t ioh = oakdsp_iohandler_t(*this, helper); + ea_t xmem = BADADDR; + int xmemsize = 0x1000; + int procnum = -1; + + op_t *op = nullptr; // current operand + + bool flow = false; + bool delayed = false; + int cycles = 0; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const ioport_t *find_port(ea_t address); + void create_xmem(void); + void select_device(const char *dname, int lrespect_info); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + ea_t add_data_segm(size_t size, int offset, const char *name) const; + + inline void opreg(int reg); + void make_o_mem(const insn_t &insn); + bool rrrrr(insn_t &, int value, int param); + bool sdirect(insn_t &insn, int value, int); + bool ldirect(insn_t &insn, int value,int); + bool A(insn_t &insn, int value,int); + bool B(insn_t &insn, int value,int); + bool mmnnn(insn_t &, int value,int); + bool nnn(insn_t &insn, int value, int); + bool ALU_ALM(insn_t &insn, int value, int param); + bool ALB(insn_t &insn, int value, int); + bool MUL(insn_t &insn, int value, int param); + bool MODA_B(insn_t &insn, int value, int param); + bool s_Imm(insn_t &insn, int value, int); + bool s_ImmS(insn_t &, int value, int param); + bool l_Imm(insn_t &insn, int value, int); + bool rb_rel_short(insn_t &, int value, int); + bool rb_rel_long(insn_t &insn, int value, int); + bool Cond(insn_t &insn, int value, int param); + bool xe_xt(insn_t &insn, int value, int param); + bool lim_xx(insn_t &, int value, int); + bool rJ_rI(insn_t &, int value,int param); + bool rI(insn_t &, int value,int); + bool AB(insn_t &, int value,int); + bool ABLH(insn_t &, int value,int); + bool indir_reg(insn_t &, int value,int param); + bool laddr_pgm(insn_t &insn, int value,int); + bool addr_rel_pgm(insn_t &insn, int value, int); + bool ext_XX(insn_t &insn, int value, int); + bool context(insn_t &insn, int value,int); + bool swap(insn_t &, int value,int); + bool banke(insn_t &, int value,int); + bool cntx(insn_t &, int value,int); + bool dmod(insn_t &, int value,int); + bool eu(insn_t &, int,int); + bool use_table(insn_t &insn, const opcode_t &ptr, uint code, int start, int end); + void reset_ops(insn_t &insn); + int ana(insn_t *_insn); + + void init_emu(void); + ea_t calc_mem(const insn_t &insn, const op_t &x) const; + int is_sane_insn(const insn_t &insn, int nocrefs) const; + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + void add_near_ref(const insn_t &insn, const op_t &x, ea_t ea); + int emu(const insn_t &insn); + + void oakdsp_header(outctx_t &ctx); + void oakdsp_assumes(outctx_t &ctx); + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void oakdsp_segstart(outctx_t &ctx, segment_t *Srange) const; + void oakdsp_segend(outctx_t &ctx, segment_t *Srange) const; + void oakdsp_footer(outctx_t &ctx) const; + void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ oakdsp" +#define PROCMOD_NAME oakdsp +#endif // _OAKDSP_HPP diff --git a/idasdk76/module/oakdsp/out.cpp b/idasdk76/module/oakdsp/out.cpp new file mode 100644 index 0000000..06d7476 --- /dev/null +++ b/idasdk76/module/oakdsp/out.cpp @@ -0,0 +1,511 @@ + +#include "oakdsp.hpp" +#include <frame.hpp> +#include <segregs.hpp> +#include <struct.hpp> + +//-------------------------------------------------------------------------- +static const char *const cc_text[] = +{ + "", // Always + "eq", // Equal to zero Z = 1 + "neq", // Not equal to zero Z = 0 + "gt", // Greater than zero M = 0 and Z = 0 + "ge", // Greater than or equal to zero M = 0 + "lt", // Less than zero M =1 + "le", // Less than or equal to zero M = 1 or Z = 1 + "nn", // Normalized flag is cleared N = 0 + "v", // Overflow flag is set V = 1 + "c", // Carry flag is set C = 1 + "e", // Extension flag is set E = 1 + "l", // Limit flag is set L = 1 + "nr", // flag is cleared R = 0 + "niu0", // Input user pin 0 is cleared + "iu0", // Input user pin 0 is set + "iu1", // Input user pin 1 is set + +}; + + +static const char *const formats[] = +{ + COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL), + COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")+1", SCOLOR_SYMBOL), + COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")-1", SCOLOR_SYMBOL), + COLSTR("(", SCOLOR_SYMBOL) COLSTR("r%d", SCOLOR_REG) COLSTR(")+s", SCOLOR_SYMBOL), + COLSTR("(", SCOLOR_SYMBOL) COLSTR("reg", SCOLOR_REG) COLSTR(")", SCOLOR_SYMBOL), +}; + +// 0 (Rn) +// 1 (Rn)+1 +// 2 (Rn)-1 +// 3 (Rn)+s +// 4 (any_reg) + +static const char *const formats2[] = +{ + COLSTR("(", SCOLOR_SYMBOL) COLSTR("rb+#", SCOLOR_REG), + COLSTR("#", SCOLOR_REG), +}; +// 0 (rb + #) +// 1 # + +static const char *const swap_formats[] = +{ + COLSTR("(a0, b0)", SCOLOR_REG), + COLSTR("(a0, b1)", SCOLOR_REG), + COLSTR("(a1, b0)", SCOLOR_REG), + COLSTR("(a1, b1)", SCOLOR_REG), + COLSTR("(a0, b0), (a1, b1)", SCOLOR_REG), + COLSTR("(a0, b1), (a1, b0)", SCOLOR_REG), + COLSTR("(a0, b0, a1)", SCOLOR_REG), + COLSTR("(a0, b1, a1)", SCOLOR_REG), + COLSTR("(a1, b0, a0)", SCOLOR_REG), + COLSTR("(a1, b1, a0)", SCOLOR_REG), + COLSTR("(b0, a0, b1)", SCOLOR_REG), + COLSTR("(b0, a1, b1)", SCOLOR_REG), + COLSTR("(b1, a0, b0)", SCOLOR_REG), + COLSTR("(b1, a1, b0)", SCOLOR_REG), +}; + +// (a0, b0) +// (a0, b1) +// (a1, b0) +// (a1, b1) +// (a0, b0), (a1, b1) +// (a0, b1), (a1, b0) +// (a0, b0, a1) +// (a0, b1, a1) +// (a1, b0, a0) +// (a1, b1, a0) +// (b0, a0, b1) +// (b0, a1, b1) +// (b1, a0, b0) +// (b1, a1, b0) + +//---------------------------------------------------------------------- +class out_oakdsp_t : public outctx_t +{ + out_oakdsp_t(void) = delete; // not used + oakdsp_t &pm() { return *static_cast<oakdsp_t *>(procmod); } +public: + void outreg(int r) { out_register(ph.reg_names[r]); } + bool out_port_address(ea_t addr); + void out_bad_address(ea_t addr); + void out_address(ea_t ea, const op_t &x); + void out_ip_rel(int displ) + { + out_printf(COLSTR("%s+", SCOLOR_SYMBOL) COLSTR("%d", SCOLOR_NUMBER), + ash.a_curip, displ); + } + bool out_operand(const op_t &x); + void out_insn(void); +}; +CASSERT(sizeof(out_oakdsp_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_oakdsp_t) + +//---------------------------------------------------------------------- +bool out_oakdsp_t::out_port_address(ea_t addr) +{ + const ioport_t *port = pm().find_port(addr); + if ( port != NULL && !port->name.empty() ) + { + out_line(port->name.c_str(), COLOR_IMPNAME); + return true; + } + return false; +} + +//---------------------------------------------------------------------- +void out_oakdsp_t::out_bad_address(ea_t addr) +{ + if ( !out_port_address(addr) ) + { + out_tagon(COLOR_ERROR); + out_btoa(addr, 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } +} + +//---------------------------------------------------------------------- +void out_oakdsp_t::out_address(ea_t ea, const op_t &x) +{ + if ( !out_name_expr(x, ea,/* ea */ BADADDR) ) + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFW_16); + out_printf(" (ea = %a)", ea); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + +} + +//---------------------------------------------------------------------- +bool out_oakdsp_t::out_operand(const op_t & x) +{ + ea_t ea; + char buf[MAXSTR]; + + if ( x.type == o_imm ) + out_symbol('#'); + + switch ( x.type ) + { + case o_void: + return 0; + + case o_imm: + if ( x.amode & amode_signed ) + out_value(x, OOF_SIGNED|OOFW_IMM); + else + out_value(x, OOFS_IFSIGN|OOFW_IMM); + break; + + case o_reg: + outreg(x.reg); + break; + + case o_mem: + // no break; + ea = pm().calc_mem(insn, x); + if ( ea != BADADDR ) + out_address(ea, x); + else + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFW_16); + out_tagoff(COLOR_ERROR); + } + break; + + case o_near: + { + ea_t lea = pm().calc_mem(insn, x); + // xmem ioports + if ( x.amode & (amode_x) && out_port_address(x.addr) ) + { + const ioport_t *port = pm().find_port(x.addr); + if ( port != NULL && !has_user_name(get_flags(lea)) ) + set_name(lea, port->name.c_str(), SN_NODUMMY); + break; + } + if ( lea == insn.ea+insn.size ) + out_ip_rel(insn.size); + else if ( !out_name_expr(x, lea, x.addr) ) + out_bad_address(x.addr); + } + break; + + case o_phrase: + { + if ( x.phtype < 4 ) + { + nowarn_qsnprintf(buf, sizeof(buf), formats[uchar(x.phtype)], x.phrase); + out_colored_register_line(buf); + } + if ( x.phtype == 4 ) + { + out_symbol('('); + outreg(x.reg); + out_symbol(')'); + } + } + break; + + case o_local: + { + out_colored_register_line(formats2[uchar(x.phtype)]); + out_value(x, OOF_SIGNED|OOF_ADDR|OOFW_16); + if ( x.phtype == 0 ) + out_symbol(')'); + break; + } + + case o_textphrase: + { + switch ( x.textphtype ) + { + case text_swap: + out_line(swap_formats[x.phrase], COLOR_REG); + break; + + case text_banke: + + int comma; + char r0[10], r1[10], r4[10], cfgi[10]; + comma = 0; + + + r0[0]=r1[0]=r4[0]=cfgi[0]='\0'; + + if ( x.phrase & 0x01 ) // cfgi + { + qsnprintf(cfgi, sizeof(cfgi), "cfgi"); + comma = 1; + } + + if ( x.phrase & 0x02 ) // r4 + { + qsnprintf(r4, sizeof(r4), "r4%s", (comma?", ":"")); + comma = 1; + } + + if ( x.phrase & 0x04 ) // r1 + { + qsnprintf(r1, sizeof(r1), "r1%s", (comma?", ":"")); + comma = 1; + } + + if ( x.phrase & 0x08 ) // r0 + qsnprintf(r0, sizeof(r0), "r0%s", (comma?", ":"")); + + qsnprintf(buf, sizeof(buf), "%s%s%s%s", r0, r1, r4, cfgi); + out_line(buf, COLOR_REG); + + break; + case text_cntx: + out_symbol(x.phrase ? 'r': 's'); + break; + case text_dmod: + if ( x.phrase ) + qsnprintf(buf, sizeof(buf), " no modulo"); + else + qsnprintf(buf, sizeof(buf), " modulo"); + + out_line(buf, COLOR_REG); + + break; + case text_eu: + qsnprintf(buf, sizeof(buf), " eu"); + out_line(buf, COLOR_REG); + break; + } + + } + break; + + + default: + interr(insn, "out"); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +void out_oakdsp_t::out_insn(void) +{ + out_mnemonic(); + + bool comma = out_one_operand(0); + if ( insn.Op2.type != o_void ) + { + if ( comma ) + out_symbol(','); + out_one_operand(1); + } + if ( insn.Op3.type != o_void ) + { + out_symbol(','); + out_one_operand(2); + } + out_immchar_cmts(); + + switch ( insn.itype ) + { + case OAK_Dsp_callr: + case OAK_Dsp_ret: + case OAK_Dsp_br: + case OAK_Dsp_call: + case OAK_Dsp_reti: + case OAK_Dsp_brr: + case OAK_Dsp_shfc: + case OAK_Dsp_shr: + case OAK_Dsp_shr4: + case OAK_Dsp_shl: + case OAK_Dsp_shl4: + case OAK_Dsp_ror: + case OAK_Dsp_rol: + case OAK_Dsp_clr: + case OAK_Dsp_not: + case OAK_Dsp_neg: + case OAK_Dsp_rnd: + case OAK_Dsp_pacr: + case OAK_Dsp_clrr: + case OAK_Dsp_inc: + case OAK_Dsp_dec: + case OAK_Dsp_copy: + case OAK_Dsp_maxd: + case OAK_Dsp_max: + case OAK_Dsp_min: + char buf[MAXSTR]; + qsnprintf(buf, + sizeof(buf), + "%s%s%s", + (insn.auxpref & aux_comma_cc) ? ", ": "", + cc_text[insn.auxpref & aux_cc], + (insn.auxpref & aux_iret_context) ? ", context": ""); + out_line(buf, COLOR_REG); + break; + } + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Srange) could be made const +void oakdsp_t::oakdsp_segstart(outctx_t &ctx, segment_t *Srange) const +{ + ea_t ea = ctx.insn_ea; + if ( is_spec_segm(Srange->type) ) + return; + + qstring sname; + qstring sclas; + get_segm_name(&sname, Srange); + get_segm_class(&sclas, Srange); + + if ( ash.uflag & UAS_GNU ) + { + const char *const predefined[] = + { + ".text", // Text section + ".data", // Data sections + ".rdata", + ".comm", + }; + + if ( !print_predefined_segname(ctx, &sname, predefined, qnumber(predefined)) ) + ctx.gen_printf(DEFAULT_INDENT, + COLSTR(".section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), + sname.c_str(), + ash.cmnt, + sclas.c_str()); + } + else + { + validate_name(&sname, VNT_IDENT); + if ( sname == "XMEM" ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), ea-get_segm_base(Srange)); + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s %c:%s", SCOLOR_ASMDIR), + ash.origin, + qtolower(sname[0]), + buf); + } + else + { + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("section %s", SCOLOR_ASMDIR) " " COLSTR("%s %s", SCOLOR_AUTOCMT), + sname.c_str(), + ash.cmnt, + sclas.c_str()); + } + } +} + +//-------------------------------------------------------------------------- +void oakdsp_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) +{ + if ( reg == ph.reg_data_sreg ) + return; + if ( value != BADADDR ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), value); + ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); + } + else + { + ctx.gen_cmt_line("drop %s", ph.reg_names[reg]); + } +} + +//-------------------------------------------------------------------------- +// function to produce assume directives +void oakdsp_t::oakdsp_assumes(outctx_t &ctx) +{ + ea_t ea = ctx.insn_ea; + segment_t *seg = getseg(ea); + if ( seg == NULL || (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 ) + return; + bool seg_started = (ea == seg->start_ea); + + for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) + { + if ( i == ph.reg_code_sreg ) + continue; + sreg_range_t sra; + if ( !get_sreg_range(&sra, ea, i) ) + continue; + sel_t now = get_sreg(ea, i); + if ( seg_started || sra.start_ea == ea ) + { + sreg_range_t prev_sra; + bool prev_exists = get_sreg_range(&prev_sra, ea - 1, i); + if ( seg_started || (prev_exists && get_sreg(prev_sra.start_ea, i) != now) ) + print_segment_register(ctx, i, now); + } + } +} + +//-------------------------------------------------------------------------- +void oakdsp_t::oakdsp_segend(outctx_t &ctx, segment_t *Srange) const +{ + if ( !is_spec_segm(Srange->type) && (ash.uflag & UAS_GNU) == 0 ) + { + qstring sname; + get_segm_name(&sname, Srange); + if ( sname != "XMEM" ) + ctx.gen_printf(DEFAULT_INDENT, "endsec"); + } +} + +//-------------------------------------------------------------------------- +void oakdsp_t::oakdsp_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL, NULL, ioh.device.c_str()); +} + +//-------------------------------------------------------------------------- +void oakdsp_t::oakdsp_footer(outctx_t &ctx) const +{ + qstring nbuf = get_colored_name(inf_get_start_ea()); + const char *name = nbuf.c_str(); + const char *end = ash.end; + if ( end == NULL ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s",SCOLOR_AUTOCMT), ash.cmnt, name); + else + ctx.gen_printf(DEFAULT_INDENT, + COLSTR("%s",SCOLOR_ASMDIR) " " COLSTR("%s %s",SCOLOR_AUTOCMT), + ash.end, ash.cmnt, name); +} + +//-------------------------------------------------------------------------- +void oakdsp_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const +{ + char sign = ' '; + if ( v < 0 ) + { + sign = '-'; + v = -v; + } + + qstring name = get_member_name(mptr->id); + + char vstr[MAX_NUMBUF]; + btoa(vstr, sizeof(vstr), v); + ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) " " + COLSTR("%c%s",SCOLOR_DNUM) + COLSTR(",",SCOLOR_SYMBOL) " " + COLSTR("%s",SCOLOR_LOCNAME), + ash.a_equ, + sign, + vstr, + name.c_str()); +} diff --git a/idasdk76/module/oakdsp/reg.cpp b/idasdk76/module/oakdsp/reg.cpp new file mode 100644 index 0000000..390f043 --- /dev/null +++ b/idasdk76/module/oakdsp/reg.cpp @@ -0,0 +1,556 @@ +#include "oakdsp.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "r0", "r1", "r2", "r3", "r4", "r5", // DAAU Registers + "rb", // Base Register + "y", // Input Register + "st0", "st1", "st2", // Status Registers + "p", // Output Register + "pc", // Program Counter + "sp", // Software Stack Pointer + "cfgi", "cfgj", // DAAU Configuration Registers + "b0h", "b1h", "b0l", "b1l", // Accumulator B + "ext0","ext1", "ext2", "ext3", // External registers + "a0", "a1", "a0l", "a1l", "a0h", "a1h", // Accumulator A + "lc", // Loop Counter + "sv", // Shift Value Register + "x", // Input Register + "dvm", // Data Value Match Register + "mixp", // Minimal/Maximal Pointer Register + "icr", // Internal Configuration Register + "ps", // Product Shifter Control + "repc", // Internal Repeat Counter + "b0", "b1", // Accumulator B + "modi", "modj", // Modulo Modifier + "stepi","stepj", // Linear (Step) Modifier + "page", // Short Direct Addressing Mode Page + "cs","ds", // virtual registers for code and data segments +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0x45, 0xc0 }; +static const uchar retcode_1[] = { 0x45, 0xd0 }; +static const uchar retcode_2[] = { 0x45, 0x80 }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Dsp Group OAK DSP Assembler +//----------------------------------------------------------------------- +static const asm_t oakasm = +{ + ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASB_BINF2 // %01010 + |ASO_OCTF1 // 0123 + |AS_COLON + |AS_N2CHR + |AS_NCMAS + |AS_ONEDUP, + 0, + "Dsp Group OAK DSP Assembler", + 0, + NULL, // header lines + "org", // org + "end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + "dc", // ascii string directive + "dcb", // byte directive + "dc", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "bs#s(c,) #d, #v", // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "*", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + "global", // "public" name keyword + NULL, // "weak" name keyword + "xref", // "extrn" name keyword + // .extern directive requires an explicit object size + NULL, // "comm" (communal variable) + NULL, // const char *(*get_type_name)(int32 flag,uint32 id); + NULL, // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_BYTE1CHAR,// One symbol per processor byte +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gas = +{ + AS_ASCIIC + |ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASB_BINF3 // 0b01010 + |ASO_OCTF1 // 0123 + |AS_COLON + |AS_N2CHR + |AS_NCMAS + |AS_ONEDUP, + UAS_GNU, + "GNU-like hypothetical assembler", + 0, + NULL, // header lines + ".org", // org + NULL, // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".byte", // byte directive + ".short", // word directive + ".long", // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + ".ds.#s(b,w,l,d) #d, #v", // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + "=", // equ + NULL, // 'seg' prefix (example: push seg seg001) + ".", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".extern", // "extrn" name keyword + // .extern directive requires an explicit object size + ".comm", // "comm" (communal variable) + NULL, // const char *(*get_type_name)(int32 flag,uint32 id); + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "mod", // mod + "and", // and + "or", // or + "xor", // xor + "not", // not + "shl", // shl + "shr", // shr + NULL, // sizeof + AS2_BYTE1CHAR,// One symbol per processor byte + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt +}; + +static const asm_t *const asms[] = { &oakasm, &gas, NULL }; + +//---------------------------------------------------------------------- +ea_t oakdsp_t::add_data_segm(size_t size, int offset, const char *name) const +{ + segment_t s; + s.start_ea = free_chunk(0x1000000, size, 0xF); + s.end_ea = s.start_ea + size; + s.sel = allocate_selector((s.start_ea-offset) >> 4); + s.type = SEG_DATA; + s.bitness = ph.dnbits > 16; + add_segm_ex(&s, name, "DATA", ADDSEG_NOSREG|ADDSEG_OR_DIE); + return s.start_ea - offset; +} + +inline ea_t get_start(const segment_t *s) +{ return s ? s->start_ea : BADADDR; } + +//-------------------------------------------------------------------------- +const char *oakdsp_iohandler_t::iocallback(const ioports_t &lports, const char *line) +{ + int size; + if ( qsscanf(line, "XMEMSIZE = %i", &size) == 1 ) + { + pm.xmemsize = size; + pm.ioh.deviceparams.sprnt("XMEM=0x%X", pm.xmemsize); + return NULL; + } + return standard_callback(lports, line); +} + +const ioport_t *oakdsp_t::find_port(ea_t address) +{ + return find_ioport(ioh.ports, address); +} + +//-------------------------------------------------------------------------- +void oakdsp_t::create_xmem(void) +{ + if ( xmem == BADADDR ) + xmem = add_data_segm(xmemsize, 0, "XMEM"); +} + +//-------------------------------------------------------------------------- +void oakdsp_t::select_device(const char *dname, int lrespect_info) +{ + ioh.set_device_name(dname, lrespect_info); + + create_xmem(); + + for ( int i=0; i < ioh.ports.size(); i++ ) + { + const ioport_t &p = ioh.ports[i]; + ea_t ea = xmem + p.address; + const char *name = p.name.c_str(); + ea_t nameea = get_name_ea(BADADDR, name); + if ( nameea != ea ) + { + set_name(nameea, ""); + if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) + set_cmt(ea, name, 0); + } + } +} + +//-------------------------------------------------------------------------- +const char *oakdsp_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( choose_ioport_device(&ioh.device, cfgfile) ) + select_device(ioh.device.c_str(), IORESP_INT); + return IDPOPT_OK; +} + +//----------------------------------------------------------------------- +// We always return "yes" because of the messy problem that +// there are additional operands with a wrong operand number (always 1) +static bool idaapi can_have_type(const op_t &) +{ + return true; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(oakdsp_t)); + return 0; +} + +//-------------------------------------------------------------------------- +void oakdsp_t::load_from_idb() +{ + xmem = get_start(get_segm_by_name("XMEM")); + char dev[MAXSTR]; + char *pdev = helper.supstr(-1, dev, sizeof(dev)) > 0 ? dev : NULL; + select_device(pdev, IORESP_NONE); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi oakdsp_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + init_emu(); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + { + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + select_device(ioh.device.c_str(), IORESP_AREA|IORESP_INT); + else + create_xmem(); + + segment_t *s0 = get_first_seg(); + if ( s0 != NULL ) + { + segment_t *s1 = get_next_seg(s0->start_ea); + for ( int i = PAGE; i <= vDS; i++ ) + { + set_default_sreg_value(s0, i, BADSEL); + set_default_sreg_value(s1, i, BADSEL); + } + } + } + break; + + case processor_t::ev_ending_undo: + procnum = ph.get_proc_index(); + //fall through + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + { + int n = va_arg(va, int); + // bool keep_cfg = va_argi(va, bool); + if ( procnum == -1 ) + { + procnum = n; + } + else if ( procnum != n ) // can't change the processor type + { // after the initial set up + warning("Sorry, processor type cannot be changed after loading"); + code = -1; + break; + } + } + break; + + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + int nocrefs = va_arg(va, int); + return is_sane_insn(*insn, nocrefs) == 1 ? 1 : -1; + } + + case processor_t::ev_may_be_func: + // can a function start here? + // arg: instruction + // returns: probability 0..100 + { + const insn_t *insn = va_arg(va, insn_t *); + return may_be_func(*insn); + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + oakdsp_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + oakdsp_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + oakdsp_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + oakdsp_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + oakdsp_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *_op = va_arg(va, const op_t *); + return out_opnd(*ctx, *_op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *_op = va_arg(va, const op_t *); + return can_have_type(*_op) ? 1 : -1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + const insn_t *insn = va_arg(va, const insn_t *); + const op_t *_op = va_arg(va, const op_t *); + *mode = is_sp_based(*insn, *_op); + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = OAK_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_gen_stkvar_def: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const member_t *mptr = va_arg(va, const member_t *); + sval_t v = va_arg(va, sval_t); + gen_stkvar_def(*ctx, mptr, v); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "Atmel OAK DSP:" + +static const char *const shnames[] = +{ + "oakdsp", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Dsp Group OAK DSP", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_OAKDSP, // id + // flag + PRN_HEX + | PR_SEGS // has segment registers + | PR_ALIGN // data items must be aligned + | PR_BINMEM // module knows about memory organization + | PR_ALIGN_INSN, // allow align instructions + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 16, // 16 bits in a byte for code segments + 16, // 16 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + PAGE, // first + vDS, // last + 1, // size of a segment register + vCS, vDS, + + NULL, // No known code start sequences + retcodes, + + OAK_Dsp_null, + OAK_Dsp_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + OAK_Dsp_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/pdp11/ana.cpp b/idasdk76/module/pdp11/ana.cpp new file mode 100644 index 0000000..957507f --- /dev/null +++ b/idasdk76/module/pdp11/ana.cpp @@ -0,0 +1,403 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "pdp.hpp" + +//---------------------------------------------------------------------- +static void loadoper(insn_t &insn, op_t *Op, uint16 nibble) +{ + ushort base; + switch ( nibble ) + { + case 027: + { + flags_t F1 = get_flags(insn.ea); + flags_t F2 = get_flags(insn.ea+insn.size); + Op->type = o_imm; + Op->ill_imm = is_head(F1) ? !is_tail(F2) : is_head(F2); + Op->offb = (uchar)insn.size; + Op->value = insn.get_next_word(); + } + break; + case 037: + case 077: + case 067: + Op->type = o_mem; + Op->offb = (uchar)insn.size; + base = insn.get_next_word(); + if ( (Op->phrase = nibble) != 037 ) + base += (short)(insn.ip + insn.size); + Op->addr16 = base; + break; + default: + if ( (nibble & 070) == 0 ) + { + Op->type = o_reg; + Op->reg = nibble; + } + else + { + Op->phrase = nibble; + if ( nibble < 060 ) + { + Op->type = o_phrase; + } + else + { + Op->type = o_displ; + Op->offb = (uchar)insn.size; + Op->addr16 = insn.get_next_word(); + } + } + break; + } +} + +//---------------------------------------------------------------------- +void pdp11_t::jmpoper(insn_t &insn, op_t *Op, uint16 nibble) +{ + loadoper(insn, Op, nibble); + if ( Op->type == o_mem && Op->phrase != 077 ) + Op->type = o_near; + if ( Op->type == o_near + && Op->addr16 >= ml.ovrcallbeg + && Op->addr16 <= ml.ovrcallend ) + { + uint32 trans = (uint32)ovrtrans.altval(Op->addr16); +// msg("addr=%o, trans=%lo\n", Op->addr16, trans); + if ( trans != 0 ) + { + segment_t *S = getseg(trans); + if ( S != NULL ) + { + Op->type = o_far; + Op->segval = (uint16)S->sel; + Op->addr16 = (ushort)(trans - to_ea(Op->segval,0)); + } + } + } +} + +//---------------------------------------------------------------------- +int pdp11_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + + static const char twoop[5] = { pdp_mov, pdp_cmp, pdp_bit, pdp_bic, pdp_bis }; + static const char onecmd[12] = + { + pdp_clr, pdp_com, pdp_inc, pdp_dec, + pdp_neg, pdp_adc, pdp_sbc, pdp_tst, pdp_ror, pdp_rol, + pdp_asr, pdp_asl + }; + static const char cc2com[8] = + { + pdp_bpl, pdp_bmi, pdp_bhi, pdp_blos, + pdp_bvc, pdp_bvs, pdp_bcc, pdp_bcs + }; + + if ( insn.ip & 1 ) + return 0; + + insn.Op1.dtype = insn.Op2.dtype = dt_word; +// insn.bytecmd = 0; + + uint code = insn.get_next_word(); + + uchar nibble0 = (code & 077); + uchar nibble1 = (code >> 6 ) & 077; + uchar nibble2 = (code >> 12) & 017; + uchar nib1swt = nibble1 >> 3; + + switch ( nibble2 ) + { + case 017: + if ( nibble1 == 0 ) + { + switch ( nibble0 ) + { + case 0: insn.itype = pdp_cfcc; break; + case 1: insn.itype = pdp_setf; break; + case 2: insn.itype = pdp_seti; break; + case 011: insn.itype = pdp_setd; break; + case 012: insn.itype = pdp_setl; break; + default: return 0; + } + break; + } + loadoper(insn, &insn.Op1, nibble0); + if ( nib1swt != 0 ) + { + static const char fpcom2[14] = + { + pdp_muld, pdp_modd, pdp_addd, + pdp_ldd, pdp_subd, pdp_cmpd, pdp_std, pdp_divd, pdp_stexp, + pdp_stcdi, pdp_stcdf, pdp_ldexp, pdp_ldcif, pdp_ldcfd + }; + insn.Op2.type = o_fpreg; + insn.Op2.reg = (nibble1 & 3); + insn.Op2.dtype = dt_double; + int idx = (nibble1 >> 2) - 2; + QASSERT(10084, idx >= 0 && idx < qnumber(fpcom2)); + insn.itype = fpcom2[idx]; + if ( insn.itype != pdp_ldexp && insn.itype != pdp_stexp ) + { + if ( insn.Op1.type == o_reg ) + insn.Op1.type = o_fpreg; + if ( insn.itype != pdp_stcdi && insn.itype != pdp_ldcif ) + insn.Op1.dtype = dt_double; + } + if ( insn.itype == pdp_std + || insn.itype == pdp_stexp + || insn.itype == pdp_stcdi + || insn.itype == pdp_stcdf ) + { + op_t temp; + temp = insn.Op2; + insn.Op2 = insn.Op1; + insn.Op1 = temp; + insn.Op1.n = 0; + insn.Op2.n = 1; + } + } + else + { + static const char fpcom1[7] = + { + pdp_ldfps, pdp_stfps, pdp_stst, pdp_clrd, + pdp_tstd, pdp_absd, pdp_negd + }; + if ( nibble1 >= 4 ) + { + insn.Op1.dtype = insn.Op2.dtype = dt_double; + if ( insn.Op1.type == o_reg ) + insn.Op1.type = o_fpreg; + } + QASSERT(10085, (nibble1-1) >= 0 && nibble1-1 < qnumber(fpcom1)); + insn.itype = fpcom1[nibble1 - 1]; //lint !e676 possibly indexing before the beginning of an allocation + } + break; + + case 7: + switch ( nib1swt ) + { + case 6: // CIS + return 0; + case 5: // FIS + { + static const char ficom[4] = { pdp_fadd, pdp_fsub, pdp_fmul, pdp_fdiv }; + if ( nibble1 != 050 || nibble0 >= 040 ) + return 0; + insn.Op1.type = o_reg; + insn.Op1.reg = nibble0 & 7; + insn.itype = ficom[nibble0 >> 3]; + break; + } + case 7: // SOB + insn.itype = pdp_sob; + insn.Op1.type = o_reg; + insn.Op1.reg = nibble1 & 7; + insn.Op2.type = o_near; + insn.Op2.phrase = 0; + insn.Op2.addr16 = (ushort)(insn.ip + 2 - (2*nibble0)); + break; + default: + { + static const char eiscom[5] = { pdp_mul, pdp_div, pdp_ash, pdp_ashc, pdp_xor }; + insn.Op2.type = o_reg; + insn.Op2.reg = nibble1 & 7; + loadoper(insn, &insn.Op1, nibble0); + insn.itype = eiscom[nib1swt]; + break; + } + } + break; + + case 016: + insn.itype = pdp_sub; + goto twoopcmd; + case 6: + insn.itype = pdp_add; + goto twoopcmd; + default: // Normal 2 op + insn.itype = twoop[(nibble2 & 7) - 1]; + insn.bytecmd = ((nibble2 & 010) != 0); +twoopcmd: + loadoper(insn, &insn.Op1, nibble1); + loadoper(insn, &insn.Op2, nibble0); + break; + + case 010: + if ( nibble1 >= 070 ) + return 0; + if ( nibble1 >= 064 ) + { + static const char mt1cmd[4] = { pdp_mtps, pdp_mfpd, pdp_mtpd, pdp_mfps }; + insn.itype = mt1cmd[nibble1 - 064]; + loadoper(insn, &insn.Op1, nibble0); + break; + } + if ( nibble1 >= 050 ) + { + insn.bytecmd = 1; +oneoper: + loadoper(insn, &insn.Op1, nibble0); + insn.itype = onecmd[nibble1 - 050]; + break; + } + if ( nibble1 >= 040 ) + { + insn.Op1.type = o_number; // EMT/TRAP + insn.Op1.value = code & 0377; + insn.itype = (nibble1 >= 044) ? pdp_trap : pdp_emt; + break; + } + insn.itype = cc2com[nibble1 >> 2]; +condoper: + insn.Op1.type = o_near; + insn.Op1.phrase = 0; + insn.Op1.addr16 = (ushort)(insn.ip + insn.size + (2*(short)((char)code))); + break; + + case 0: + if ( nibble1 >= 070 ) + return 0; + if ( nibble1 > 064 ) + { + static const char mt2cmd[3] = { pdp_mfpi, pdp_mtpi, pdp_sxt }; + insn.itype = mt2cmd[nibble1 - 065]; + loadoper(insn, &insn.Op1, nibble0); + break; + } + if ( nibble1 == 064 ) + { + insn.itype = pdp_mark; + insn.Op1.type = o_number; + insn.Op1.value = nibble0; + break; + } + if ( nibble1 >= 050 ) + goto oneoper; + if ( nibble1 >= 040 ) + { + if ( (nibble1 & 7) == 7 ) + { + insn.itype = pdp_call; + jmpoper(insn, &insn.Op1, nibble0); + } + else + { + insn.itype = pdp_jsr; + insn.Op1.type = o_reg; + insn.Op1.reg = nibble1 & 7; + jmpoper(insn, &insn.Op2, nibble0); + } + break; + } + switch ( nibble1 ) + { + case 3: + insn.itype = pdp_swab; + loadoper(insn, &insn.Op1, nibble0); + break; + case 1: + insn.itype = pdp_jmp; + jmpoper(insn, &insn.Op1, nibble0); + break; + case 2: + if ( nibble0 == 7 ) + { + insn.itype = pdp_return; + break; + } + if ( nibble0 < 7 ) + { + insn.itype = pdp_rts; + insn.Op1.type = o_reg; + insn.Op1.reg = nibble0; + break; + } + if ( nibble0 < 030 ) + return 0; + if ( nibble0 < 040 ) + { + insn.itype = pdp_spl; + insn.Op1.value = nibble0 & 7; + insn.Op1.type = o_number; + break; + } + switch ( nibble0 & 037 ) + { + case 000: insn.itype = pdp_nop; break; + case 001: insn.itype = pdp_clc; break; + case 002: insn.itype = pdp_clv; break; + case 004: insn.itype = pdp_clz; break; + case 010: insn.itype = pdp_cln; break; + case 017: insn.itype = pdp_ccc; break; + case 021: insn.itype = pdp_sec; break; + case 022: insn.itype = pdp_sev; break; + case 024: insn.itype = pdp_sez; break; + case 030: insn.itype = pdp_sen; break; + case 037: insn.itype = pdp_scc; break; + default: + insn.itype = pdp_compcc; + insn.Op1.phrase = nibble0 & 037; + break; + } + break; + case 0: + { + static const char misc0[16] = + { + pdp_halt, pdp_wait, pdp_rti, pdp_bpt, + pdp_iot, pdp_reset, pdp_rtt, pdp_mfpt + }; + if ( nibble0 > 7 ) + return 0; + insn.itype = misc0[nibble0]; + break; + } + default: // >=4 + { + static const char lcc2com[7] = + { + pdp_br, pdp_bne, pdp_beq, pdp_bge, + pdp_blt, pdp_bgt, pdp_ble + }; + insn.itype = lcc2com[(nibble1 >> 2) - 1]; + goto condoper; + } + } + break; + } + + if ( insn.bytecmd ) + { + if ( insn.Op1.type == o_mem && insn.Op1.phrase != 077 + || insn.Op1.type == o_displ && (insn.Op1.phrase & 070) == 060 ) + { + insn.Op1.dtype = dt_byte; + } + if ( insn.Op2.type == o_mem && insn.Op2.phrase != 077 + || insn.Op2.type == o_displ && (insn.Op2.phrase & 070) == 060 ) + { + insn.Op2.dtype = dt_byte; + } + } + + if ( insn.Op1.type == o_imm && insn.Op1.ill_imm ) + insn.size -= 2; + if ( insn.Op2.type == o_imm && insn.Op2.ill_imm ) + insn.size -= 2; + + return int(insn.size); +} diff --git a/idasdk76/module/pdp11/emu.cpp b/idasdk76/module/pdp11/emu.cpp new file mode 100644 index 0000000..e60b31d --- /dev/null +++ b/idasdk76/module/pdp11/emu.cpp @@ -0,0 +1,232 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "pdp.hpp" + +//------------------------------------------------------------------------ +void pdp11_t::loadR0data(const insn_t &insn, const op_t *x, int sme) +{ + if ( insn.Op2.type == o_void ) + { + if ( insn.itype != pdp_clr ) + goto undefdat; + if ( sme ) + { + if ( !insn.bytecmd ) + goto undefdat; + emuR0data.b[1] = 0; + return; + } + if ( insn.bytecmd ) + emuR0data.b[0] = 0; + else + emuR0data.w = 0; + return; + } + if ( x != &insn.Op2 ) + return; + if ( insn.Op1.type == o_imm ) + { + if ( insn.itype == pdp_mov ) + { + if ( !insn.bytecmd ) + { + if ( sme ) + goto undefdat; + emuR0data.w = (ushort)insn.Op1.value; + return; + } + if ( !sme ) + emuR0data.b[0] = (uchar)insn.Op1.value; + else + emuR0data.b[1] = (uchar)insn.Op1.value; + return; + } + if ( !insn.bytecmd ) + goto undefdat; +undefbyt: + if ( !sme ) + emuR0data.b[0] = 0xFF; + else + emuR0data.b[1] = 0xFF; + return; + } + if ( insn.bytecmd ) + goto undefbyt; +undefdat: + emuR0data.w = 0xFFFF; +} + +//------------------------------------------------------------------------ +void pdp11_t::handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload) +{ + ea_t jmpa; + switch ( x.type ) + { + case o_near: // Jcc/ [jmp/call 37/67] + case o_mem: // 37/67/77 + case o_far: + jmpa = x.type == o_far + ? to_ea(x.segval, x.addr16) + : map_code_ea(insn, x.addr16, x.n); + if ( x.phrase == 0 ) + { + insn.add_cref(jmpa, x.offb, fl_JN); // Jcc + break; + } +extxref: + if ( (x.phrase & 070) == 070 ) + goto xrefset; + if ( insn.itype == pdp_jmp ) + insn.add_cref(jmpa, x.offb, fl_JF); + else if ( insn.itype == pdp_jsr || insn.itype == pdp_call ) + { + insn.add_cref(jmpa, x.offb, fl_CF); + if ( !func_does_return(jmpa) ) + flow = false; + } + else + { +xrefset: + insn.create_op_data(jmpa, x); + insn.add_dref(jmpa, x.offb, isload ? dr_R : dr_W); + } + break; + case o_displ: // 6x/7x (!67/!77) + set_immd(insn.ea); + if ( !isload && x.phrase == (060 + rR0) && x.addr16 <= 1 ) + loadR0data(insn, &x, x.addr16); + if ( !is_forced + && is_off(get_flags(insn.ea), x.n) + && (jmpa = get_offbase(insn.ea, x.n)) != BADADDR ) + { + jmpa += x.addr16; + goto extxref; + } + break; + case o_imm: // 27 + if ( !x.ill_imm ) + { + set_immd(insn.ea); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, dr_O, OOF_SIGNED); + } + break; + case o_number: // EMT/TRAP/MARK/SPL + if ( insn.itype == pdp_emt && get_cmt(NULL, insn.ea, false) <= 0 ) + { + insn_t tmp = insn; + op_t &tmpx = tmp.ops[x.n]; + if ( tmpx.value >= 0374 && tmpx.value <= 0375 ) + { + tmp.Op2.value = (tmpx.value == 0375) ? emuR0data.b[1] : (emuR0 >> 8); + tmp.Op2.type = o_imm; + } + qstring qbuf; + if ( get_predef_insn_cmt(&qbuf, tmp) > 0 ) + set_cmt(tmp.ea, qbuf.c_str(), false); + } + break; + case o_reg: // 0 + if ( x.reg == rR0 ) + { + if ( insn.Op2.type == o_void ) // one operand insn + { + if ( insn.itype != pdp_clr ) + goto undefall; + if ( insn.bytecmd ) + emuR0 &= 0xFF00; + else + emuR0 = 0; + goto undefdata; + } + if ( &x == &insn.Op2 ) + { + if ( insn.itype != pdp_mov ) + { + if ( insn.bytecmd ) + { + emuR0 |= 0xFF; + goto undefdata; + } + goto undefall; + } + if ( insn.bytecmd ) + goto undefall; + if ( insn.Op1.type == o_imm ) + { + if ( (emuR0 = (ushort)insn.Op1.value) & 1 ) + goto undefdata; + emuR0data.w = get_word(to_ea(insn.cs, emuR0)); + } + else + { +undefall: + emuR0 = 0xFFFF; +undefdata: + emuR0data.w = 0xFFFF; + } + } + } + break; + case o_phrase: // 1x/2x/3x/4x/5x (!27/!37) + if ( (x.phrase & 7) == rR0 ) + { + if ( !isload && x.phrase == (010 + rR0) ) + loadR0data(insn, &x, 0); + else if ( insn.Op2.type == o_void || &x == &insn.Op2 ) + goto undefall; + } + case o_fpreg: // FPP + break; + default: + warning("%" FMT_EA "o (%s): bad optype %d", insn.ip, insn.get_canon_mnem(ph), x.type); + break; + } +} + +//---------------------------------------------------------------------- +int pdp11_t::emu(const insn_t &insn) +{ + bool flag1 = is_forced_operand(insn.ea, 0); + bool flag2 = is_forced_operand(insn.ea, 1); + + uint32 Feature = insn.get_canon_feature(ph); + flow = (Feature & CF_STOP) == 0; + + if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, flag1, true); + if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, flag2, true); + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, flag1, false); + if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, flag2, false); + + ea_t newEA = insn.ea + insn.size; + if ( insn.itype == pdp_emt && insn.Op1.value == 0376 ) + { + create_byte(newEA, 2); + goto prompt2; + } + else if ( flow && !(insn.itype == pdp_emt && insn.Op1.value == 0350) ) + { + if ( insn.Op1.type == o_imm && insn.Op1.ill_imm ) + newEA += 2; + if ( insn.Op2.type == o_imm && insn.Op2.ill_imm ) + { +prompt2: + newEA += 2; + } + add_cref(insn.ea, newEA, fl_F); + } + return 1; +} diff --git a/idasdk76/module/pdp11/float.c b/idasdk76/module/pdp11/float.c new file mode 100644 index 0000000..0ff43a6 --- /dev/null +++ b/idasdk76/module/pdp11/float.c @@ -0,0 +1,86 @@ +#include <ieee.h> +#define E IEEE_E +#define M IEEE_M +#define EXONE IEEE_EXONE + +// one of the many possible NaNs, +// the one produced by the base converter +const fpvalue_t ieee_nan = {{ 0, 0, 0, 0, 0xc000, 0xffff }}; + +fpvalue_error_t idaapi realcvt(void *m, fpvalue_t *e, uint16 swt) +{ + eNI x; + long exp; + uint16 r, msk, *p = (uint16 *)m; + + switch ( swt ) + { + case 1: // in float + case 0: // in trunc. float + case 3: // in double + ecleaz(x); + x[0] = ((r = *p) & 0x8000) ? 0xffff : 0; /* fill in our sign */ + r &= (0377 << 7); + if ( r == 0 ) + { + if ( x[0] ) // negative and zero exponent = Undefined -> transformed to NaN + { + memcpy(e, &ieee_nan, sizeof(fpvalue_t)); + break; + } + // complain on dirty zero + for ( msk = 0x7fff, r = swt + 1; r; r--, msk = 0xffff ) + if ( *p++ & msk ) + return REAL_ERROR_BADDATA; // signed zero accepted + } + else + { + x[E] = (r >> 7) + (EXONE - 0201); /* DEC exponent offset */ + x[M] = (*p++ & 0177) | 0200; /* now do the high order mantissa */ + if ( swt ) + memcpy(&x[M+1], p, swt*sizeof(uint16)); + eshift(x, -8); /* shift our mantissa down 8 bits */ + } + emovo(x, e); // convert to IEEE format + break; + + case 011: // out float + case 010: // out trunc. float + case 013: // out double + emovi(*e, x); + r = swt & 3; + if ( !x[E] ) + goto clear; + if ( x[E] == E_SPECIAL_EXP ) + { + // all of NaN, +/-Inf transformed to "Undefined value" + x[0] = 0xffff; + x[E] = 0; + goto clear; + } + exp = (long )x[E] - (EXONE - 0201); + if ( !emdnorm(x, 0, 0, exp, 56) || x[E] >= 0377 ) + return REAL_ERROR_RANGE; // overfloat + if ( !x[E] ) + { +clear: + memset(p, 0, (r + 1)*sizeof(uint16)); + if ( x[0] ) + *p = 0x8000; // signed zero accepted + } + else + { + *p = (x[0] ? 0100000 : 0) | (x[E] << 7); /* sign & exp */ + eshift(x, 8); + *p++ |= (x[M] & 0177); + if ( r != 0 ) + memcpy(p, &x[M+1], r*sizeof(uint16)); + } + break; + + default: + return REAL_ERROR_FORMAT; + } + + return REAL_ERROR_OK; +} diff --git a/idasdk75/module/pdp11/ins.cpp b/idasdk76/module/pdp11/ins.cpp similarity index 100% rename from idasdk75/module/pdp11/ins.cpp rename to idasdk76/module/pdp11/ins.cpp diff --git a/idasdk76/module/pdp11/ins.hpp b/idasdk76/module/pdp11/ins.hpp new file mode 100644 index 0000000..381c885 --- /dev/null +++ b/idasdk76/module/pdp11/ins.hpp @@ -0,0 +1,134 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-2021 Hex-Rays + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ +pdp_null = 0, // Unknown Operation + +pdp_halt, // Stop CPU +pdp_wait, // Wait interrupt +pdp_rti, // Interrupt return +pdp_bpt, // Trap to Debbuger +pdp_iot, // Trap to 20 (i/o) +pdp_reset, // Reset CPU and device +pdp_rtt, // Interrupt return and ignore dbg-flag +pdp_mfpt, // Load Processor Type (* hi model) +pdp_jmp, // Absolute jmp +pdp_rts, // Return into subroutine +pdp_spl, // Set Prior. +pdp_nop, // Not operation +pdp_clc, // Clear C bit in PSW +pdp_clv, // Clear V bit in PSW +pdp_clz, // Clear Z bit in PSW +pdp_cln, // Clear N bit in PSW +pdp_ccc, // Clear All Condition bits in PSW +pdp_sec, // Set C bit in PSW +pdp_sev, // Set V bit in PSW +pdp_sez, // Set Z bit in PSW +pdp_sen, // Set N bit in PSW +pdp_scc, // Set All Condition bits bit in PSW +pdp_swab, // Exchange byte in word +pdp_br, // Relative jmp +pdp_bne, // Jump if Z=0 +pdp_beq, // Jump if Z=1 +pdp_bge, // Jump if N^V=0 +pdp_blt, // Jump if N^V=1 +pdp_bgt, // Jump if Z|(N^V)=0 +pdp_ble, // Jump if Z|(N^V)=1 +pdp_jsr, // Call procedure +pdp_clr, // Clear operand +pdp_com, // Inverse operand +pdp_inc, // Increment operand +pdp_dec, // Decrement operand +pdp_neg, // op = -op +pdp_adc, // Add with Carry +pdp_sbc, // Substract with Carry +pdp_tst, // Test operand +pdp_ror, // Cyclic shift rignt +pdp_rol, // Cyclic shift left +pdp_asr, // Arifmetic shift rignt +pdp_asl, // Arifmetic shift left +pdp_mark, // Return and empty stack +pdp_mfpi, // Load from previous instruction space (*hi model) +pdp_mtpi, // Store to previous instruction space (*hi model) +pdp_sxt, // N=>op +pdp_mov, // Move operand +pdp_cmp, // Compare operands +pdp_bit, // Check Bit's +pdp_bic, // Clear Bit's +pdp_bis, // Set Bit's +pdp_add, // Add operands +pdp_sub, // Substract operands +pdp_mul, // Multiple Reg (*eis) +pdp_div, // Divide Reg (*eis) +pdp_ash, // Multistep shift (*eis) +pdp_ashc, // Multistep shift 2 reg (*eis) +pdp_xor, // Exclusive or (*eis) +pdp_fadd, // Floating Add (*fis) +pdp_fsub, // Floating Subtract (*fis) +pdp_fmul, // Floating Multiple (*fis) +pdp_fdiv, // Floating Divide (*fis) +pdp_sob, // +pdp_bpl, // Jump if N=0 +pdp_bmi, // Jump if N=1 +pdp_bhi, // Jump if (!C)&(!Z)=0 +pdp_blos, // Jump if C|Z=1 +pdp_bvc, // Jump if V=0 +pdp_bvs, // Jump if V=1 +pdp_bcc, // Jump if C=0 +pdp_bcs, // Jump if C=1 +pdp_emt, // Trap to System +pdp_trap, // Trap to user/compiler +pdp_mtps, // Store PSW (*lsi11 only) +pdp_mfpd, // Load from previous data space (*hi model) +pdp_mtpd, // Store to previous data space (*hi model) +pdp_mfps, // Load PSW (*lsi11 only) + // FPU instruction +pdp_cfcc, // Copy cond.codes into FPS to PSW +pdp_setf, // Set Float +pdp_seti, // Set Integer +pdp_setd, // Set Double +pdp_setl, // Set Long Integer +pdp_ldfps, // Load FPS +pdp_stfps, // Store FPS +pdp_stst, // Load interrupt status +pdp_clrd, // Clear +pdp_tstd, // Test +pdp_absd, // op = mod(op) +pdp_negd, // op = -op +pdp_muld, // Multiple +pdp_modd, // Get int. part +pdp_addd, // Add +pdp_ldd, // Load in Acc +pdp_subd, // Substract +pdp_cmpd, // Compare +pdp_std, // Store into Acc +pdp_divd, // Divide +pdp_stexp, // Store exponent +pdp_stcdi, // Store and convert double/float to integer/long +pdp_stcdf, // Store and convert double/float to float/double +pdp_ldexp, // Load exponent +pdp_ldcif, // Load and convert integer/long to double/float +pdp_ldcfd, // Load and convert float/double to double/float +pdp_call, // Jsr PC, +pdp_return, // RTS PC +pdp_compcc, // Complex Condition Codes + +pdp_last + + }; + +#endif diff --git a/idasdk76/module/pdp11/makefile b/idasdk76/module/pdp11/makefile new file mode 100644 index 0000000..2dffa3b --- /dev/null +++ b/idasdk76/module/pdp11/makefile @@ -0,0 +1,47 @@ +PROC=pdp11 + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + pdp.hpp pdp_ml.h +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \ + pdp.hpp pdp_ml.h +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \ + pdp.hpp pdp_ml.h +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp float.c ins.hpp \ + pdp.hpp pdp_ml.h reg.cpp diff --git a/idasdk76/module/pdp11/out.cpp b/idasdk76/module/pdp11/out.cpp new file mode 100644 index 0000000..2b6d82f --- /dev/null +++ b/idasdk76/module/pdp11/out.cpp @@ -0,0 +1,386 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#include "pdp.hpp" + +//---------------------------------------------------------------------- +class out_pdp_t : public outctx_t +{ + out_pdp_t(void) = delete; // not used + pdp11_t &pm() { return *static_cast<pdp11_t *>(procmod); } +public: + void OutReg(int rgnum) { out_register(ph.reg_names[rgnum]); } + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); +}; +CASSERT(sizeof(out_pdp_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_pdp_t) + +//---------------------------------------------------------------------- +bool out_pdp_t::out_operand(const op_t &x) +{ + ea_t segadr; + switch ( x.type ) + { + case o_void: + return 0; + case o_reg: + OutReg(x.reg); + break; + case o_fpreg: + OutReg(x.reg + 8); + break; + case o_imm: // 27 + if ( x.ill_imm ) + { + out_symbol('('); + OutReg(rPC); + out_symbol(')'); + out_symbol('+'); + } + else + { + out_symbol('#'); + if ( x.dtype == dt_float || x.dtype == dt_double ) + { + char str[MAXSTR]; + if ( print_fpval(str, sizeof(str), &x.value, 2) ) + { + char *p = str; + while ( *p == ' ' ) + p++; + out_symbol('^'); + out_symbol('F'); + out_line(p, COLOR_NUMBER); + } + else + { + out_long(x.value, 8); + } + } + else + { + out_value(x, OOF_SIGNED | OOFW_IMM); + } + } + break; + case o_mem: // 37/67/77 + case o_near: // jcc/ [jmp/call 37/67] + case o_far: + if ( x.phrase != 0 ) + { + if ( x.phrase == 077 || x.phrase == 037 ) + out_symbol('@'); + if ( x.phrase == 037 ) + out_symbol('#'); + if ( x.addr16 < pm().ml.asect_top && !is_off(F, x.n) ) + { + out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16); + break; + } + } + segadr = x.type == o_far + ? to_ea(x.segval, x.addr16) + : map_code_ea(insn, x.addr16, x.n); + if ( !out_name_expr(x, segadr, x.addr16) ) + { + if ( x.type == o_far || x.addr16 < 0160000 ) + remember_problem(PR_NONAME, insn.ea); + out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16); + } + break; + case o_number: // EMT/TRAP/MARK/SPL + out_value(x, OOF_NUMBER | OOFS_NOSIGN | OOFW_8); + break; + case o_displ: // 6x/7x (!67/!77) + if ( x.phrase >= 070 ) + out_symbol('@'); + out_value(x, OOF_ADDR | OOF_SIGNED | OOFW_16); + out_symbol('('); + goto endregout; + case o_phrase: // 1x/2x/3x/4x/5x (!27/!37) + switch ( x.phrase >> 3 ) + { + case 1: + out_symbol('@'); + OutReg(x.phrase & 7); + break; + case 3: + out_symbol('@'); + // fallthrough + case 2: + out_symbol('('); + OutReg(x.phrase & 7); + out_symbol(')'); + out_symbol('+'); + break; + case 5: + out_symbol('@'); + // fallthrough + case 4: + out_symbol('-'); + out_symbol('('); +endregout: + OutReg(x.phrase & 7); + out_symbol(')'); + break; + } + break; + default: + warning("out: %" FMT_EA "o: bad optype %d", insn.ip, x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +void out_pdp_t::out_proc_mnem(void) +{ + static const char *const postfix[] = { "", "b" }; + out_mnem(8, postfix[insn.bytecmd]); +} + +//---------------------------------------------------------------------- +void out_pdp_t::out_insn(void) +{ + out_mnemonic(); + if ( insn.itype == pdp_compcc ) + { + uint i = 0, code, first = 0; + static const uint tabcc[8] = + { + pdp_clc, pdp_clv, pdp_clz, pdp_cln, + pdp_sec, pdp_sev, pdp_sez, pdp_sen + }; + code = insn.Op1.phrase; + out_symbol('<'); + if ( code >= 020 ) + { + if ( (code ^= 020) == 0 ) + out_line(COLSTR("nop!^O20", SCOLOR_INSN)); + i = 4; + } + for ( ; code; i++, code >>= 1 ) + { + if ( code & 1 ) + { + if ( first++ ) + out_symbol('!'); + out_line(ph.instruc[tabcc[i]].name, COLOR_INSN); + } + } + out_symbol('>'); + } + + out_one_operand(0); + + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void idaapi pdp_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL_BUT_BYTESEX); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, seg) could be made const +void pdp11_t::pdp_segstart(outctx_t &ctx, segment_t *seg) +{ + if ( seg->type == SEG_IMEM ) + { + ctx.flush_buf(COLSTR(".ASECT", SCOLOR_ASMDIR), DEFAULT_INDENT); + } + else + { + qstring sname; + get_visible_segm_name(&sname, seg); + ctx.out_printf(COLSTR(".PSECT %s", SCOLOR_ASMDIR), sname.c_str()); + if ( seg->ovrname != 0 ) + { + char bseg[MAX_NUMBUF]; + char breg[MAX_NUMBUF]; + btoa(bseg, sizeof(bseg), seg->ovrname & 0xFFFF, 10); + btoa(breg, sizeof(breg), seg->ovrname >> 16, 10); + ctx.out_printf( + COLSTR(" %s Overlay Segment %s, Region %s", SCOLOR_AUTOCMT), + ash.cmnt, bseg, breg); + } + ctx.flush_outbuf(0); + } + + if ( (inf_get_outflags() & OFLG_GEN_ORG) != 0 ) + { + size_t org = size_t(ctx.insn_ea-get_segm_base(seg)); + if ( org != 0 && org != ml.asect_top && seg->comorg() ) + { + ctx.out_tagon(COLOR_ASMDIR); + ctx.out_line(ash.origin); + ctx.out_line(ash.a_equ); + if ( seg->type != SEG_IMEM ) + { + ctx.out_line(ash.origin); + ctx.out_char('+'); + } + ctx.out_btoa(org); + ctx.out_tagoff(COLOR_ASMDIR); + ctx.flush_outbuf(DEFAULT_INDENT); + } + } +} + +//-------------------------------------------------------------------------- +void pdp11_t::pdp_footer(outctx_t &ctx) const +{ + if ( ash.end != NULL ) + { + ctx.gen_empty_line(); + ctx.out_line(ash.end, COLOR_ASMDIR); + qstring name; + if ( get_colored_name(&name, inf_get_start_ea()) > 0 ) + { + size_t i = strlen(ash.end); + do + ctx.out_char(' '); + while ( ++i < 8 ); + ctx.out_line(name.begin()); + } + ctx.flush_outbuf(DEFAULT_INDENT); + } + else + { + ctx.gen_cmt_line("end of file"); + } +} + +//-------------------------------------------------------------------------- +bool pdp11_t::out_equ(outctx_t &ctx, ea_t ea) const +{ + segment_t *s = getseg(ea); + char buf[MAXSTR]; + if ( s != NULL ) + { + if ( s->type != SEG_IMEM && !is_loaded(ea) ) + { + char num[MAX_NUMBUF]; + btoa(num, sizeof(num), get_item_size(ea)); + nowarn_qsnprintf(buf, sizeof(buf), ash.a_bss, num); + ctx.flush_buf(buf); + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------- +void pdp11_t::pdp_data(outctx_t &ctx, bool analyze_only) const +{ + char buf[MAXSTR]; + ushort v[5]; + ea_t endea; + ushort i, j; + + ea_t ea = ctx.insn_ea; + if ( out_equ(ctx, ea) ) + return; + + i = 0; + flags_t F = ctx.F; + if ( !is_unknown(F) ) + { + if ( is_word(F) && get_radix(F,0) == 16 ) + i = 2; + else if ( is_dword(F) ) + i = 4; + else if ( is_qword(F) ) + i = 8; + else if ( is_tbyte(F) ) + i = 10; + if ( i == 0 ) + { + ctx.out_data(analyze_only); + return; + } + + int radix = get_radix(F, 0); + endea = get_item_end(ea); + for ( ; ea < endea; ea += i ) + { + memset(v, 0, sizeof(v)); + if ( get_bytes(v, i, ea) != i || r50_to_asc(buf, v, i/2) != 0 ) + { + ctx.out_keyword(".word "); + for ( j = 0; j < i/2; j++ ) + { + if ( j ) + ctx.out_symbol(','); + btoa(buf, sizeof(buf), v[j], radix); + ctx.out_line(buf, COLOR_NUMBER); + } + } + else + { + ctx.out_keyword(".rad50 "); + ctx.out_tagon(COLOR_CHAR); + ctx.out_char('/'); + ctx.out_line(buf); + ctx.out_char('/'); + ctx.out_tagoff(COLOR_CHAR); + } + if ( ctx.flush_outbuf() ) + return; // too many lines + } + return; + } +// unknown + if ( !is_loaded(ea) ) + { + ctx.flush_buf(COLSTR(".blkb", SCOLOR_KEYWORD)); + } + else + { + uchar c = get_byte(ea); + + char cbuf[MAX_NUMBUF]; + btoa(cbuf, sizeof(cbuf), c); + ctx.out_printf(COLSTR(".byte ", SCOLOR_KEYWORD) + COLSTR("%4s ", SCOLOR_DNUM) + COLSTR("%s %c", SCOLOR_AUTOCMT), + cbuf, + ash.cmnt, + c >= ' ' ? c : ' '); + if ( !(ea & 1) && (i = get_word(ea)) != 0 ) + { + ctx.out_tagon(COLOR_AUTOCMT); + ctx.out_char(' '); + b2a32(buf, sizeof(buf), i, 2, 0); + ctx.out_line(buf); + ctx.out_char(' '); + ushort w = i; + r50_to_asc(buf, &w, 1); + ctx.out_line(buf); + ctx.out_tagoff(COLOR_AUTOCMT); + } + ctx.flush_outbuf(); + } // undefined +} diff --git a/idasdk76/module/pdp11/pdp.hpp b/idasdk76/module/pdp11/pdp.hpp new file mode 100644 index 0000000..6ea4585 --- /dev/null +++ b/idasdk76/module/pdp11/pdp.hpp @@ -0,0 +1,80 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#ifndef _PDP_HPP +#define _PDP_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include "pdp_ml.h" +//-V::536 octal + +#define UAS_SECT 0x0001 // Segments are named .SECTION + +//---------------------------------------------------------------------- +// Redefine temporary names +// +#define bytecmd auxpref_u8[0] + +#define segval specval_shorts.low +#define addr16 addr_shorts.low +#define ill_imm specflag1 + +#define o_fpreg o_idpspec0 +#define o_number o_idpspec1 +//------------------------------------------------------------------------ +enum pdp_registers +{ + rR0, rR1, rR2, rR3, rR4, rR5, rSP, rPC, + rAC0, rAC1, rAC2, rAC3, rAC4, rAC5, + rVcs, rVds +}; + +//------------------------------------------------------------------------ +void idaapi pdp_header(outctx_t &ctx); + +//------------------------------------------------------------------------ +struct pdp11_t : public procmod_t +{ + netnode ovrtrans; + pdp_ml_t ml = { uint32(BADADDR), 0, 0, 0 }; + bool flow = false; + ushort emuR0 = 0xFFFF; + //lint -e708 'union initialization' + union + { + ushort w; + uchar b[2]; + } emuR0data = { 0xFFFF }; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void jmpoper(insn_t &insn, op_t *Op, uint16 nibble); + int ana(insn_t *_insn); + + void pdp_segstart(outctx_t &ctx, segment_t *seg); + + void loadR0data(const insn_t &insn, const op_t *x, int sme); + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + int emu(const insn_t &insn); + + void pdp_footer(outctx_t &ctx) const; + bool out_equ(outctx_t &ctx, ea_t ea) const; + void pdp_data(outctx_t &ctx, bool analyze_only) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ pdp-11 overlay translations" +#define PROCMOD_NAME pdp11 +#endif diff --git a/idasdk75/module/pdp11/pdp_ml.h b/idasdk76/module/pdp11/pdp_ml.h similarity index 100% rename from idasdk75/module/pdp11/pdp_ml.h rename to idasdk76/module/pdp11/pdp_ml.h diff --git a/idasdk76/module/pdp11/reg.cpp b/idasdk76/module/pdp11/reg.cpp new file mode 100644 index 0000000..ad6d4e0 --- /dev/null +++ b/idasdk76/module/pdp11/reg.cpp @@ -0,0 +1,310 @@ +/* + * Interactive disassembler (IDA) + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * E-mail: ig@datarescue.com + * PDP11 module. + * Copyright (c) 1995-2006 by Iouri Kharon. + * E-mail: yjh@styx.cabel.net + * + * ALL RIGHTS RESERVED. + * + */ + +#define IEEE_SOURCE +#include "pdp.hpp" +int data_id; + +//---------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "R0","R1","R2","R3","R4","R5","SP","PC", + "AC0", "AC1", "AC2", "AC3", "AC4", "AC5", + "cs","ds" +}; + +//----------------------------------------------------------------------- + +static const char *const array_macro[] = +{ + "", + ".macro .array of,type,cnt,val", + ".rept cnt", + " type val", + ".endr", + ".endm .array", + NULL +}; + +static const asm_t macro11 = +{ + /*AS_UNEQU |*/ AS_COLON | AS_2CHRE | AS_NCHRE | ASH_HEXF5 | ASO_OCTF2 | ASD_DECF2 | AS_NCMAS | AS_ONEDUP | ASB_BINF1 | AS_RELSUP, + UAS_SECT, + "Macro-11 Assembler", + 0, + array_macro, // header + ".", // org + ".END", + + ";", // comment string + '\\', // string delimiter + '\'', // char delimiter + "\\\200", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".byte", // byte directive + ".word", // word directive + ".long", // double words + NULL, // no qwords + NULL, // oword (16 bytes) + ".flt2", + ".flt4", + NULL, // no tbytes + NULL, // no packreal + ".array of #hs cnt=#d val=#v", // #h - header(.byte,.word) + // #d - size of array + // #v - value of array elements + ".blkb %s", // uninited data (reserve space) + "=", + NULL, // seg prefix + ".", // a_curip + NULL, // func_header + NULL, // func_footer + ".globl", // public + ".weak", // weak + ".globl", // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '<', '>', // lbrace, rbrace + NULL, // mod + "&", // and + "|", // or + "^", // xor + "!", // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//------------------------------------------------------------------ +// floating point conversion +#include "float.c" + +//---------------------------------------------------------------------- +void pdp11_t::load_from_idb() +{ + ml.asect_top = (ushort)ovrtrans.altval(n_asect); + ml.ovrcallbeg = (ushort)ovrtrans.altval(n_ovrbeg); + ml.ovrcallend = (ushort)ovrtrans.altval(n_ovrend); + ml.ovrtbl_base = (uint32)ovrtrans.altval(n_ovrbas); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(pdp11_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi pdp11_t::on_event(ssize_t msgid, va_list va) +{ + int retcode = 1; + segment_t *sptr; + + switch ( msgid ) + { + case processor_t::ev_creating_segm: + sptr = va_arg(va, segment_t *); + sptr->defsr[rVds-ph.reg_first_sreg] = find_selector(inf_get_start_cs()); //sptr->sel; + break; + + case processor_t::ev_init: + ovrtrans.create(PROCMOD_NODE_NAME); // it makes no harm to create it again + break; + + case processor_t::ev_term: + clr_module_data(data_id); + break; + + case processor_t::ev_newprc: + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case pdp11_module_t::ev_get_ml_ptr: + { + pdp_ml_t **p_ml = va_arg(va, pdp_ml_t **); + netnode **p_mn = va_arg(va, netnode **); + if ( p_ml != NULL && p_mn != NULL ) + { + *p_ml = &ml; + *p_mn = &ovrtrans; + retcode = 0; + } + } + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + pdp_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + pdp_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + pdp_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + pdp_data(*ctx, analyze_only); + return 1; + } + + case processor_t::ev_realcvt: + { + void *m = va_arg(va, void *); + fpvalue_t *e = va_arg(va, fpvalue_t *); + uint16 swt = va_argi(va, uint16); + fpvalue_error_t code = realcvt(m, e, swt); + return code == REAL_ERROR_OK ? 1 : code; + } + + + default: + retcode = 0; + break; + } + return retcode; +} + + +//----------------------------------------------------------------------- +static const asm_t *const asms[] = { ¯o11, NULL }; + +#define FAMILY "DEC series:" +static const char *const shnames[] = { "PDP11", NULL }; +static const char *const lnames[] = { FAMILY"DEC PDP-11", NULL }; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0200, 0000 }; +static const uchar retcode_1[] = { 0201, 0000 }; +static const uchar retcode_2[] = { 0202, 0000 }; +static const uchar retcode_3[] = { 0203, 0000 }; +static const uchar retcode_4[] = { 0204, 0000 }; +static const uchar retcode_5[] = { 0205, 0000 }; +static const uchar retcode_6[] = { 0206, 0000 }; +static const uchar retcode_7[] = { 0207, 0000 }; +static const uchar retcode_8[] = { 0002, 0000 }; +static const uchar retcode_9[] = { 0006, 0000 }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { sizeof(retcode_4), retcode_4 }, + { sizeof(retcode_5), retcode_5 }, + { sizeof(retcode_6), retcode_6 }, + { sizeof(retcode_7), retcode_7 }, + { sizeof(retcode_8), retcode_8 }, + { sizeof(retcode_9), retcode_9 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_PDP, // id + // flag + PR_WORD_INS + | PRN_OCT + | PR_SEGTRANS, + // flag2 + PR2_REALCVT // the module has 'realcvt' event implementation + | PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Register names + qnumber(RegNames), // Number of registers + + rVcs,rVds, + 0, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0,pdp_last, + Instructions, // instruc + 0, // size of tbyte + { 4,7,19,0 }, + +// Icode of return instruction. It is ok to give any of possible return +// instructions + pdp_return, +}; diff --git a/idasdk76/module/pic/ana.cpp b/idasdk76/module/pic/ana.cpp new file mode 100644 index 0000000..60c783f --- /dev/null +++ b/idasdk76/module/pic/ana.cpp @@ -0,0 +1,1061 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Microchip's PIC + * + */ + +#include "pic.hpp" +#include <segregs.hpp> + +#define PIC18_IP_RANGE 0x1FFFFF + +//------------------------------------------------------------------------- +// it can replace one instruction with another without changing its size +void pic_t::simplify(insn_t &insn) const +{ + switch ( insn.itype ) + { + // movfw macro f ; Move Contents of File Reg to W + // movf f,0 + // endm + // tstf macro f ; Test Contents of File Register + // movf f,1 + // endm + case PIC_movf: + insn.itype = (insn.Op2.reg == W) ? PIC_movfw : PIC_tstf; + insn.Op2.type = o_void; + break; + + // b macro k ; Branch to Address + // goto k + // endm + case PIC_goto: + insn.itype = PIC_b; + break; + + // clrc macro ; Clear Carry + // bcf 3,0 + // endm + // clrdc macro ; Clear Digit Carry + // bcf 3,1 + // endm + // clrz macro ; Clear Zero + // bcf 3,2 + // endm + case PIC_bcf: + if ( is_bank(insn) ) switch ( insn.Op2.value ) + { + case 0: insn.itype = PIC_clrc; goto NOOP; + case 1: insn.itype = PIC_clrdc; goto NOOP; + case 2: insn.itype = PIC_clrz; goto NOOP; +NOOP: + insn.Op1.type = o_void; + insn.Op2.type = o_void; + break; + } + break; + + // setc macro ; Set Carry + // bsf 3,0 + // endm + // setdc macro ; Set Digit Carry + // bsf 3,1 + // endm + // setz macro ; Set Zero + // bcf 3,2 + // endm + case PIC_bsf: + if ( is_bank(insn) ) switch ( insn.Op2.value ) + { + case 0: insn.itype = PIC_setc; goto NOOP; + case 1: insn.itype = PIC_setdc; goto NOOP; + case 2: insn.itype = PIC_setz; goto NOOP; + } + break; + + // skpnc macro ; Skip on No Carry + // btfsc 3,0 + // endm + // skpndc macro ; Skip on No Digit Carry + // btfsc 3,1 + // endm + // skpnz macro ; Skip on No Zero + // btfsc 3,2 + // endm + case PIC_btfsc: + if ( is_bank(insn) ) switch ( insn.Op2.value ) + { + case 0: insn.itype = PIC_skpnc; goto NOOP; + case 1: insn.itype = PIC_skpndc; goto NOOP; + case 2: insn.itype = PIC_skpnz; goto NOOP; + } + break; + + // skpc macro ; Skip on Carry + // btfss 3,0 + // endm + // skpdc macro ; Skip on Digit Carry + // btfss 3,1 + // endm + // skpz macro ; Skip on Zero + // btfss 3,2 + // endm + case PIC_btfss: + if ( is_bank(insn) ) switch ( insn.Op2.value ) + { + case 0: insn.itype = PIC_skpc; goto NOOP; + case 1: insn.itype = PIC_skpdc; goto NOOP; + case 2: insn.itype = PIC_skpz; goto NOOP; + } + break; + } +} + +//------------------------------------------------------------------------- +// it returns true if the size of the instruction is changed +// INSN must be simplified +bool pic_t::build_macro(insn_t &insn, bool may_go_forward) +{ + if ( !may_go_forward ) + return false; + switch ( insn.itype ) + { + // negf macro f,d ; Negate File Register Contents + // comf f,1 + // incf f,d + // endm + case PIC_comf: + if ( insn.Op2.reg == F ) + { + insn_t incf; + if ( decode_insn(&incf, insn.ea + insn.size) > 0 + && incf.itype == PIC_incf + && incf.Op1.type == o_mem + && incf.Op1.addr == insn.Op1.addr ) + { + insn.itype = PIC_negf; + insn.Op2.reg = incf.Op2.reg; + insn.size += incf.size; + return true; + } + } + break; + + // bnc macro k ; Branch on No Carry to k + // skpc + // goto k + // endm + // bndc macro k ; Branch on No Digit Carry to k + // skpdc + // goto k + // endm + // bnz macro k ; Branch on No Zero to Address + // skpz + // goto k + // endm + // bc macro k ; Branch on Carry to Address k + // skpnc + // goto k + // endm + // bdc macro k ; Branch on Digit Carry to k + // skpndc + // goto k + // endm + // bz macro k ; Branch on Zero to Address k + // skpnz + // goto k + // endm + // addcf macro f,d ; Add Carry to File Register + // skpnc + // incf f,d + // endm + // adddcf macro f,d ; Add Digit to File Register + // skpndc + // incf f,d + // endm + // subcf macro f,d ; Subtract Carry from File Reg + // skpnc + // decf f,d + // endm + case PIC_skpnc: + case PIC_skpndc: + case PIC_skpnz: + case PIC_skpc: + case PIC_skpdc: + case PIC_skpz: + { + insn_t ins2; + if ( decode_insn(&ins2, insn.ea + insn.size) == 0 ) + break; + if ( ins2.itype == PIC_b ) + { + insn.itype = insn.itype == PIC_skpc ? PIC_bnc + : insn.itype == PIC_skpdc ? PIC_bndc + : insn.itype == PIC_skpz ? PIC_bnz + : insn.itype == PIC_skpnc ? PIC_bc + : insn.itype == PIC_skpndc ? PIC_bdc + : PIC_bz; + insn.Op1 = ins2.Op1; + insn.size += ins2.size; + return true; + } + if ( ins2.itype == PIC_incf || ins2.itype == PIC_decf ) + { + if ( insn.itype == PIC_skpnc && ins2.itype == PIC_incf ) + insn.itype = PIC_addcf; + else if ( insn.itype == PIC_skpndc && ins2.itype == PIC_incf ) + insn.itype = PIC_adddcf; + else if ( insn.itype == PIC_skpnc && ins2.itype == PIC_decf ) + insn.itype = PIC_subcf; + else + break; + insn.Op1 = ins2.Op1; + insn.Op2 = ins2.Op2; + insn.size += ins2.size; + return true; + } + } + break; + } + return false; +} + +//-------------------------------------------------------------------------- +struct pic_mctr_t : public macro_constructor_t +{ + pic_t ± + pic_mctr_t(pic_t &_pm) : pm(_pm) {} + bool idaapi build_macro(insn_t *insn, bool may_go_forward) override + { + return pm.build_macro(*insn, may_go_forward); + } +}; + +//-------------------------------------------------------------------------- +int pic_t::ana(insn_t *_insn) +{ + if ( _insn == NULL ) + return 0; + insn_t &insn = *_insn; + int len = basic_ana(insn); + if ( len == 0 ) + return len; + + if ( dosimple() ) + simplify(insn); + + pic_mctr_t mctr(*this); + mctr.construct_macro(&insn, ph.supports_macros() && inf_macros_enabled()); + + // if the instruction is too long, recreate it: + /*if ( insn.size == 1 && is_tail(get_flags(insn.ea+1)) ) + { + auto_make_code(insn.ea); + auto_make_code(insn.ea+1); + ea_t saved = insn.ea; + del_items(insn.ea, DELIT_SIMPLE); // destroys insn.ea + insn.ea = saved; + }*/ + return insn.size; +} + +//-------------------------------------------------------------------------- +static void opf12(insn_t &insn, int code) +{ + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + sel_t v = get_sreg(insn.ea, BANK); + if ( v == BADSEL ) + v = 0; + insn.Op1.addr = (code & 0x1F) | ((v&1) << 5); +} + +//-------------------------------------------------------------------------- +static void opf14(insn_t &insn, int code) +{ + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + sel_t v = get_sreg(insn.ea, BANK); + if ( v == BADSEL ) + v = 0; + insn.Op1.addr = (code & 0x7F) | ((v&3) << 7); +} + +//-------------------------------------------------------------------------- +static void opfa16(insn_t &insn, int code) +{ + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + if ( code & 0x0100 ) // if a == 1 (BSR) + { + sel_t v = get_sreg(insn.ea, BANK); + if ( v == BADSEL ) + v = 0; + insn.Op1.addr = ((v&0xF) << 8) | (code & 0xFF); + } + else // if a == 0 (access bank) + { + insn.Op1.addr = code & 0xFF; + if ( insn.Op1.addr >= 128 ) + insn.Op1.addr = 3840 + insn.Op1.addr; + } +} + +//-------------------------------------------------------------------------- +static void basic_ana12(insn_t &insn, int code) +{ + int b4; + + switch ( code >> 10 ) + { + case 0: +// 0000 0100 0000 CLRW Clear W +// 0000 0000 0000 NOP No Operation +// 0000 0000 0100 CLRWDT Clear Watchdog Timer +// 0000 0000 0010 OPTION Load OPTION register +// 0000 0000 0011 SLEEP Go into standby mode + if ( code == 0x040 ) + insn.itype = PIC_clrw; + else if ( code == 0x000 ) + insn.itype = PIC_nop; + else if ( code == 0x004 ) + insn.itype = PIC_clrwdt; + else if ( code == 0x002 ) + insn.itype = PIC_option; + else if ( code == 0x003 ) + insn.itype = PIC_sleep; + else if ( ( code & 0xFF8 ) == 0 ) + { +// 0000 0000 0fff TRIS f (4<f<8) Load TRIS Register + insn.itype = PIC_tris; + opf12(insn, code); + } + else if ( ( code & 0xF80 ) == 0 ) +// 0000 001f ffff MOVWF f Move W to f +// 0000 011f ffff CLRF f Clear f + { + static const ushort codes[4] = + { + PIC_null, PIC_movwf, PIC_null, PIC_clrf + }; + insn.itype = codes[(code>>5)&3]; + opf12(insn, code); + } + else + { +// 0000 10df ffff SUBWF f, d Subtract W from f +// 0000 11df ffff DECF f, d Decrement f +// 0001 00df ffff IORWF f, d Inclusive OR W with f +// 0001 01df ffff ANDWF f, d AND W with f +// 0001 10df ffff XORWF f, d Exclusive OR W with f +// 0001 11df ffff ADDWF f, d Add W and f +// 0010 00df ffff MOVF f, d Move f +// 0010 01df ffff COMF f, d Complement f +// 0010 10df ffff INCF f, d Increment f +// 0010 11df ffff DECFSZ f, d Decrement f, Skip if 0 +// 0011 00df ffff RRF f, d Rotate Right f through Carry +// 0011 01df ffff RLF f, d Rotate Left f through Carry +// 0011 10df ffff SWAPF f, d Swap nibbles in f +// 0011 11df ffff INCFSZ f, d Increment f, Skip if 0 + b4 = code >> 6; + static const ushort codes[16] = + { + PIC_null, PIC_null, PIC_subwf, PIC_decf, + PIC_iorwf, PIC_andwf, PIC_xorwf, PIC_addwf, + PIC_movf, PIC_comf, PIC_incf, PIC_decfsz, + PIC_rrf, PIC_rlf, PIC_swapf, PIC_incfsz + }; + insn.itype = codes[b4]; + opf12(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = (code & 0x20) ? F : W; + insn.Op2.dtype = dt_byte; + } + break; + case 1: +// 0100 bbbf ffff BCF f, b Bit Clear f +// 0101 bbbf ffff BSF f, b Bit Set f +// 0110 bbbf ffff BTFSC f, b Bit Test f, Skip if Clear +// 0111 bbbf ffff BTFSS f, b Bit Test f, Skip if Set + { + static const ushort codes[4] = + { + PIC_bcf, PIC_bsf, PIC_btfsc, PIC_btfss + }; + insn.itype = codes[(code>>8)&3]; + opf12(insn, code); + insn.Op2.type = o_imm; + insn.Op2.value = (code >> 5) & 7; + insn.Op2.dtype = dt_byte; + } + break; + case 2: + b4 = (code >> 8) & 0x3; + switch ( b4 ) + { + case 0: +// 1000 kkkk kkkk RETLW k Return with literal in W + insn.itype = PIC_retlw; + insn.Op1.type = o_imm; + insn.Op1.value = code & 0xFF; + insn.Op1.dtype = dt_byte; + break; + case 1: +// 1001 kkkk kkkk CALL k Call subroutine + { + // old databases used status reg (PCLATH) for hight bit of the address + // new code uses BANK for that + // so we get both and try to guess + sel_t status = get_sreg(insn.ea, PCLATH); + sel_t bank = get_sreg(insn.ea, BANK); + if ( (status != BADSEL && status != 0) && (bank == BADSEL || bank == 0) ) + bank = (status >> 5) & 3; + insn.itype = PIC_call; + insn.Op1.type = o_near; + insn.Op1.addr = (bank << 9) | (code & 0xFF); + insn.Op1.dtype = dt_code; + } + break; + default: +// 101k kkkk kkkk GOTO k Go to address + { + sel_t status = get_sreg(insn.ea, PCLATH); + sel_t bank = get_sreg(insn.ea, BANK); + if ( (status != BADSEL && status != 0) && (bank == BADSEL || bank == 0) ) + bank = (status >> 5) & 3; + insn.itype = PIC_goto; + insn.Op1.type = o_near; + insn.Op1.addr = (bank << 9) | (code & 0x1FF); + insn.Op1.dtype = dt_code; + } + break; + } + break; + case 3: +// 1100 kkkk kkkk MOVLW k Move literal to W +// 1101 kkkk kkkk IORLW k Inclusive OR literal with W +// 1110 kkkk kkkk ANDLW k AND literal with W +// 1111 kkkk kkkk XORLW k Exclusive OR literal with W + { + static const ushort codes[4] = + { + PIC_movlw, PIC_iorlw, PIC_andlw, PIC_xorlw + }; + insn.itype = codes[(code>>8)&3]; + insn.Op1.type = o_imm; + insn.Op1.value = (uchar)code; + insn.Op1.dtype = dt_byte; + } + break; + } +} + +//-------------------------------------------------------------------------- +int32 get_signed(int32 byte, uint32 mask) +{ + uint32 bits = mask >> 1; + uint32 sign = bits + 1; + if ( (byte & sign) != 0 ) // byte < 0 + byte = (byte & bits) - sign; + else // byte >= 0 + byte = byte & mask; + return byte; +} + +//-------------------------------------------------------------------------- +static void basic_ana14(insn_t &insn, int code) +{ + int b4 = (code >> 8) & 0xF; + + switch ( code >> 12 ) + { + // 00 xxxx xxxx xxxx + case 0: + if ( b4 == 0 ) // 00 0000 xxxx xxxx + { + // 00 0000 1fff ffff MOVWF f Move W to f + if ( (code & 0x80) != 0 ) + { + insn.itype = PIC_movwf; + opf14(insn, code); + break; + } + + // 00 0000 0001 0nmm MOVIW Move INDFn to W + // 00 0000 0001 1nmm MOVWI Move W to INDFn + if ( (code >> 4) == 1 ) + { + insn.itype = ((code >> 3) & 1) == 0 ? PIC_moviw : PIC_movwi; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code & 0x4) == 0) ? FSR0 : FSR1; + insn.Op1.specflag1 = (code & 3) + 1; + insn.Op1.dtype = dt_byte; + break; + } + + + // 00 0000 001k kkkk MOVLB k Move literal to BSR + if ( (code >> 5) == 1 ) + { + insn.itype = PIC_movlb; + insn.Op1.type = o_imm; + insn.Op1.value = code & 0x1F; + insn.Op1.dtype = dt_byte; + break; + } + + + // 00 0000 0000 0000 NOP No Operation + // 00 0000 0000 0001 RESET Software device Reset + // 00 0000 0000 1000 RETURN Return from Subroutine + // 00 0000 0000 1001 RETFIE Return from interrupt + // 00 0000 0000 1010 CALLW Call Subroutine with W + // 00 0000 0000 1011 BRW Relative Branch with W + // 00 0000 0110 0010 OPTION Load OPTION register + // 00 0000 0110 0011 SLEEP Go into standby mode + // 00 0000 0110 0100 CLRWDT Clear Watchdog Timer + // 00 0000 0110 0fff TRIS f (4<f<8) Load TRIS Register + if ( code == 0x0 ) + { + insn.itype = PIC_nop; + } + else if ( code == 0x0001 ) + { + insn.itype = PIC_reset; + } + else if ( code == 0x0008 ) + { + insn.itype = PIC_return; + } + else if ( code == 0x000A ) + { + insn.itype = PIC_callw; + } + else if ( code == 0x0009 ) + { + insn.itype = PIC_retfie; + } + else if ( code == 0x000B ) + { + insn.itype = PIC_brw; + sel_t w = get_sreg(insn.ea, W); + insn.Op1.type = o_near; + insn.Op1.value = insn.ea + w + 1; // PC + W + 1 + insn.Op1.dtype = dt_code; + } + else if ( code == 0x0062 ) + { + insn.itype = PIC_option; + } + else if ( code == 0x0063 ) + { + insn.itype = PIC_sleep; + } + else if ( code == 0x0064 ) + { + insn.itype = PIC_clrwdt; + } + else if ( code >= 0x0065 && code <= 0x0067 ) + { + insn.itype = PIC_tris; + insn.Op1.type = o_imm; + insn.Op1.dtype = dt_byte; + insn.Op1.value = code & 7; + } + } + else if ( b4 == 1 ) // 00 0001 xxxx xxxx + { + // 00 0001 1fff ffff CLRF f Clear f + if ( code & 0x80 ) + { + insn.itype = PIC_clrf; + opf14(insn, code); + } + // 00 0001 0xxx xxxx CLRW Clear W + else + { + insn.itype = PIC_clrw; + } + } + else + { + // 00 0010 dfff ffff SUBWF f, d Subtract W from f + // 00 0011 dfff ffff DECF f, d Decrement f + // 00 0100 dfff ffff IORWF f, d Inclusive OR W with f + // 00 0101 dfff ffff ANDWF f, d AND W with f + // 00 0110 dfff ffff XORWF f, d Exclusive OR W with f + // 00 0111 dfff ffff ADDWF f, d Add W and f + // 00 1000 dfff ffff MOVF f, d Move f + // 00 1001 dfff ffff COMF f, d Complement f + // 00 1010 dfff ffff INCF f, d Increment f + // 00 1011 dfff ffff DECFSZ f, d Decrement f, Skip if 0 + // 00 1100 dfff ffff RRF f, d Rotate Right f through Carry + // 00 1101 dfff ffff RLF f, d Rotate Left f through Carry + // 00 1110 dfff ffff SWAPF f, d Swap nibbles in f + // 00 1111 dfff ffff INCFSZ f, d Increment f, Skip if 0 + static const ushort codes[16] = + { + PIC_null, PIC_null, PIC_subwf, PIC_decf, + PIC_iorwf, PIC_andwf, PIC_xorwf, PIC_addwf, + PIC_movf, PIC_comf, PIC_incf, PIC_decfsz, + PIC_rrf, PIC_rlf, PIC_swapf, PIC_incfsz + }; + insn.itype = codes[b4]; + opf14(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = (code & 0x80) ? F : W; + insn.Op2.dtype = dt_byte; + } + break; + + // 01 xxxx xxxx xxxx + case 1: + // 01 00bb bfff ffff BCF f, b Bit Clear f + // 01 01bb bfff ffff BSF f, b Bit Set f + // 01 10bb bfff ffff BTFSC f, b Bit Test f, Skip if Clear + // 01 11bb bfff ffff BTFSS f, b Bit Test f, Skip if Set + { + static const ushort codes[4] = + { + PIC_bcf, PIC_bsf, PIC_btfsc, PIC_btfss + }; + insn.itype = codes[(code >> 10) & 3]; + opf14(insn, code); + insn.Op2.type = o_imm; + insn.Op2.value = (code >> 7) & 7; + insn.Op2.dtype = dt_byte; + } + break; + + // 10 xxxx xxxx xxxx + case 2: + // 10 0kkk kkkk kkkk CALL k Call subroutine + // 10 1kkk kkkk kkkk GOTO k Go to address + { + // Get the content of PCLATH segment register. We use a mask to keep only bits 3 et 4. (The upper bits of PC are loaded from PCLATH<4:3>.) + sel_t pclath = get_sreg(insn.ea, PCLATH) & 0x18; // & 00011000b + insn.itype = (code & 0x800) ? PIC_goto : PIC_call; + insn.Op1.type = o_near; + + // We have 000x x000 for pclath and 10 1kkk kkkk kkkk for code + // Operation : 000x x000 0000 0000 | 00 0kkk kkkk kkkk + // Result : 000x xkkk kkkk kkkk + insn.Op1.addr = (pclath << (11 - 3)) | (code & 0x7FF); + insn.Op1.dtype = dt_code; + } + break; + + // 11 xxxx xxxx xxxx + case 3: + // 11 00xx kkkk kkkk MOVLW k Move literal to W + // 11 0001 1kkk kkkk MOVLP k Move literal to PCLATH + // 11 0001 0nkk kkkk ADDFSR n, k Add Literal to FSRn + // 11 001k kkkk kkkk BRA k Relative Branch + // 11 01xx kkkk kkkk RETLW k Return with literal in W + // 11 0111 dfff ffff ASRF f, d Arithmetic Right Shift + // 11 0101 dfff ffff LSLF f, d Logical Left Shift + // 11 0110 dfff ffff LSRF f, d Logical Right Shift + // 11 1000 kkkk kkkk IORLW k Inclusive OR literal with W + // 11 1001 kkkk kkkk ANDLW k AND literal with W + // 11 1010 kkkk kkkk XORLW k Exclusive OR literal with W + // 11 1011 dfff ffff SUBWFB f, d Subtract W from f with Borrow + // 11 1100 kkkk kkkk SUBLW k Subtract W from literal + // 11 1101 dfff ffff ADDWFC f, d Add with Carry W and f + // 11 111x kkkk kkkk ADDLW k Add literal and W + // 11 1111 0nkk kkkk MOVIW ?? Move INDFn to W + // 11 1111 1nkk kkkk MOVWI ?? Move W to INDFn + { + static const ushort codes[16] = + { + PIC_movlw, PIC_movlp, PIC_bra, PIC_bra, + PIC_retlw, PIC_lslf, PIC_lsrf, PIC_asrf, + PIC_iorlw, PIC_andlw, PIC_xorlw, PIC_subwfb, + PIC_sublw, PIC_addwfc, PIC_addlw, PIC_moviw + }; + insn.itype = codes[b4]; + switch ( insn.itype ) + { + case PIC_movlp: + if ( ((code >> 7) & 1) == 0 ) // 11 0001 0nkk kkkk ADDFSR + { + insn.itype = PIC_addfsr; + insn.Op1.type = o_reg; + insn.Op1.reg = ((code & 0x40) == 0) ? FSR0 : FSR1; + insn.Op1.dtype = dt_byte; + + insn.Op2.type = o_imm; + insn.Op2.value = get_signed(code, 0x3F); + insn.Op2.dtype = dt_byte; + } + else // 11 0001 1kkk kkkk MOVLP + { + insn.itype = PIC_movlp; + insn.Op1.type = o_imm; + insn.Op1.value = code & 0x7F; + insn.Op1.dtype = dt_byte; + } + break; + + case PIC_bra: + insn.Op1.type = o_near; + insn.Op1.addr = insn.ea + 1 + get_signed(code, 0x01FF); // PC + 1 + operand value + insn.Op1.dtype = dt_code; + break; + + case PIC_addwfc: + case PIC_asrf: + case PIC_lslf: + case PIC_lsrf: + case PIC_subwfb: + opf14(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = ( (code & 0x80) != 0) ? F : W; + insn.Op2.dtype = dt_byte; + break; + + case PIC_moviw: + if ( ((code >> 7) & 1) == 0 ) // 11 1111 0nkk kkkk MOVIW + insn.itype = PIC_moviw; + else // 11 1111 1nkk kkkk MOVWI + insn.itype = PIC_movwi; + + insn.Op1.type = o_displ; + insn.Op1.phrase = ((code & 0x40) == 0) ? FSR0 : FSR1; + insn.Op1.addr = get_signed(code, 0x3F); + insn.Op1.dtype = dt_byte; + break; + + default: + insn.Op1.type = o_imm; + insn.Op1.value = code & 0xFF; + insn.Op1.dtype = dt_byte; + break; + } + } + break; + } +} + +//-------------------------------------------------------------------------- +static void basic_ana16(insn_t &insn, int code) +{ + if ( ( code >> 12 ) == 0 ) + { + int b3 = code >> 4; + if ( b3 == 0 ) + { +// 0000 0000 0000 0000 NOP No Operation +// 0000 0000 0000 0011 SLEEP Go into standby mode +// 0000 0000 0000 0100 CLRWDT Clear Watchdog Timer +// 0000 0000 0000 0101 PUSH Push top of return stack +// 0000 0000 0000 0110 POP Pop top of return stack +// 0000 0000 0000 0111 DAW Decimal Adjust W +// 0000 0000 0000 1000 TBLRD* Table Read +// 0000 0000 0000 1001 TBLRD*+ Table Read with post-increment +// 0000 0000 0000 1010 TBLRD*- Table Read with post-decrement +// 0000 0000 0000 1011 TBLRD+* Table Read with pre-increment +// 0000 0000 0000 1100 TBLWT* Table Write +// 0000 0000 0000 1101 TBLWT*+ Table Write with post-increment +// 0000 0000 0000 1110 TBLWT*- Table Write with post-decrement +// 0000 0000 0000 1111 TBLWT+* Table Write with pre-increment + static const ushort codes[16] = + { + PIC_nop, PIC_null, PIC_null, PIC_sleep, + PIC_clrwdt, PIC_push0, PIC_pop0, PIC_daw0, + PIC_tblrd0, PIC_tblrd0p, PIC_tblrd0m, PIC_tblrdp0, + PIC_tblwt0, PIC_tblwt0p, PIC_tblwt0m, PIC_tblwtp0 + }; + insn.itype = codes[code & 15]; + } + else if ( b3 < 0x80 ) + { + if ( ( code & 0xFFFC ) == 0x0010 ) + { +// 0000 0000 0001 000s RETFIE s Return from interrupt enable +// 0000 0000 0001 001s RETURN s Return from Subroutine + insn.itype = (code & 0x2) ? PIC_return1 : PIC_retfie1; + if ( code & 1 ) + { + insn.Op1.type = o_reg; + insn.Op1.reg = FAST; + } + else + { + insn.Op1.type = o_imm; + insn.Op1.value = 0; + } + insn.Op1.dtype = dt_byte; + } + else if ( code == 0x00FF ) + { +// 0000 0000 1111 1111 RESET Software device Reset + insn.itype = PIC_reset0; + } + else if ( ( code & 0xFFF0 ) == 0x0100 ) + { +// 0000 0001 0000 kkkk MOVLB k Move literal to BSR + insn.itype = PIC_movlb1; + insn.Op1.type = o_imm; + insn.Op1.value = code & 0xF; + insn.Op1.dtype = dt_byte; + } + else if ( ( code & 0xFE00 ) == 0x0200 ) + { +// 0000 001a ffff ffff MULWF f, a Multiply W with f + insn.itype = PIC_mulwf2; + opfa16(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = (code & 0x100) ? BANKED : ACCESS; + insn.Op2.dtype = dt_byte; + } + else if ( ( code & 0xFC00 ) == 0x0400 ) + { +// 0000 01da ffff ffff DECF f, d, a Decrement f + insn.itype = PIC_decf3; + opfa16(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = (code & 0x200) ? F : W; + insn.Op2.dtype = dt_byte; + insn.Op3.type = o_reg; + insn.Op3.reg = (code & 0x100) ? BANKED : ACCESS; + insn.Op3.dtype = dt_byte; + } + else + { + insn.itype = PIC_null; + } + } + else + { +// 0000 1000 kkkk kkkk SUBLW k Subtract W from literal +// 0000 1001 kkkk kkkk IORLW k Inclusive OR literal with W +// 0000 1010 kkkk kkkk XORLW k Exclusive OR literal with W +// 0000 1011 kkkk kkkk ANDLW k AND literal with W +// 0000 1100 kkkk kkkk RETLW k Return with literal in W +// 0000 1101 kkkk kkkk MULLW k Multiply literal with W +// 0000 1110 kkkk kkkk MOVLW k Move literal to W +// 0000 1111 kkkk kkkk ADDLW k Add literal and W + static const ushort codes[16] = + { + PIC_sublw, PIC_iorlw, PIC_xorlw, PIC_andlw, + PIC_retlw, PIC_mullw1, PIC_movlw, PIC_addlw + }; + insn.itype = codes[(code>>8)&7]; + insn.Op1.type = o_imm; + insn.Op1.value = (char)code; + insn.Op1.dtype = dt_byte; + } + } + else if ( ( code >> 14 ) <= 2 ) + { + int b1 = code >> 12; + if ( b1 <= 5 ) + { +// 0001 00da ffff ffff IORWF f, d, a Inclusive OR W with f +// 0001 01da ffff ffff ANDWF f, d, a AND W with f +// 0001 10da ffff ffff XORWF f, d, a Exclusive OR W with f +// 0001 11da ffff ffff COMF f, d, a Complement f +// 0010 00da ffff ffff ADDWFC f, d, a Add W and Carry to f +// 0010 01da ffff ffff ADDWF f, d, a Add W and f +// 0010 10da ffff ffff INCF f, d, a Increment f +// 0010 11da ffff ffff DECFSZ f, d, a Decrement f, Skip if 0 +// 0011 00da ffff ffff RRCF f, d, a Rotate Right f through Carry +// 0011 01da ffff ffff RLCF f, d, a Rotate Left f through Carry +// 0011 10da ffff ffff SWAPF f, d, a Swap nibbles in f +// 0011 11da ffff ffff INCFSZ f, d, a Increment f, Skip if 0 +// 0100 00da ffff ffff RRNCF f, d, a Rotate Right f +// 0100 01da ffff ffff RLNCF f, d, a Rotate Left f +// 0100 10da ffff ffff INFSNZ f, d, a Increment f, Skip if not 0 +// 0100 11da ffff ffff DCFSNZ f, d, a Decrement f, Skip if not 0 +// 0101 00da ffff ffff MOVF f, d, a Move f +// 0101 01da ffff ffff SUBFWB f, d, a Substract f from W with borrow +// 0101 10da ffff ffff SUBWFB f, d, a Substract W from f with borrow +// 0101 11da ffff ffff SUBWF f, d, a Substract W from f + static const ushort codes[24] = + { + PIC_null, PIC_null, PIC_null, PIC_null, + PIC_iorwf3, PIC_andwf3, PIC_xorwf3, PIC_comf3, + PIC_addwfc3, PIC_addwf3, PIC_incf3, PIC_decfsz3, + PIC_rrcf3, PIC_rlcf3, PIC_swapf3, PIC_incfsz, + PIC_rrncf3, PIC_rlncf3, PIC_infsnz3, PIC_dcfsnz3, + PIC_movf3, PIC_subfwb3, PIC_subwfb3, PIC_subwf3, + }; + QASSERT(10097, (code>>10) < 24); + insn.itype = codes[code>>10]; + opfa16(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = (code & 0x200) ? F : W; + insn.Op2.dtype = dt_byte; + insn.Op3.type = o_reg; + insn.Op3.reg = (code & 0x100) ? BANKED : ACCESS; + insn.Op3.dtype = dt_byte; + } + else if ( b1 == 6 ) + { +// 0110 000a ffff ffff CPFSLT f, a Compare f with W, Skip if < +// 0110 001a ffff ffff CPFSEQ f, a Compare f with W, Skip if == +// 0110 010a ffff ffff CPFSGT f, a Compare f with W, Skip if > +// 0110 011a ffff ffff TSTFSZ f, a Test f, Skip if 0 +// 0110 100a ffff ffff SETF f, a Set f +// 0110 101a ffff ffff CLRF f, a Clear f +// 0110 110a ffff ffff NEGF f, a Negate f +// 0110 111a ffff ffff MOVWF f, a Move W to f + static const ushort codes[8] = + { + PIC_cpfslt2, PIC_cpfseq2, PIC_cpfsgt2, PIC_tstfsz2, + PIC_setf2, PIC_clrf2, PIC_negf2, PIC_movwf2, + }; + insn.itype = codes[(code>>9)&7]; + opfa16(insn, code); + insn.Op2.type = o_reg; + insn.Op2.reg = (code & 0x100) ? BANKED : ACCESS; + insn.Op2.dtype = dt_byte; + } + else + { +// 0111 bbba ffff ffff BTG f, b, a Bit Toggle f +// 1000 bbba ffff ffff BSF f, b, a Bit Set f +// 1001 bbba ffff ffff BCF f, b, a Bit Clear f +// 1010 bbba ffff ffff BTFSS f, b, a Bit Test f, Skip if Set +// 1011 bbba ffff ffff BTFSC f, b, a Bit Test f, Skip if Clear + static const ushort codes[5] = + { + PIC_btg3, PIC_bsf3, PIC_bcf3, PIC_btfss3, PIC_btfsc3 + }; + QASSERT(10098, (b1-7) < 5); + insn.itype = codes[b1-7]; + opfa16(insn, code); + insn.Op2.type = o_imm; + insn.Op2.value = (code >> 9) & 7; + insn.Op2.dtype = dt_byte; + insn.Op3.type = o_reg; + insn.Op3.reg = (code & 0x100) ? BANKED : ACCESS; + insn.Op3.dtype = dt_byte; + } + } + else + { + int b2 = ( code >> 12 ) & 3; + int b3 = ( code >> 8 ) & 0x0F; + switch ( b2 ) + { + case 0: +// 1100 ffff ffff ffff 1111 ffff ffff ffff MOVFF fs, fd Move fs to fd + insn.itype = PIC_movff2; + insn.Op1.type = o_mem; + insn.Op1.dtype = dt_byte; + insn.Op1.addr = code & 0xFFF; + insn.Op2.type = o_mem; + insn.Op2.dtype = dt_byte; + insn.Op2.addr = insn.get_next_word() & 0xFFF; + break; + case 1: +// 1101 0nnn nnnn nnnn BRA n Branch unconditionally +// 1101 1nnn nnnn nnnn RCALL n Relative Call subroutine + insn.itype = (code & 0x800) ? PIC_rcall1 : PIC_bra1; + insn.Op1.type = o_near; + insn.Op1.addr = (insn.ea + 2 + 2 * get_signed(code,0x07FF)) & PIC18_IP_RANGE; + insn.Op1.dtype = dt_code; + break; + case 2: + if ( b3 <= 7 ) + { +// 1110 0000 nnnn nnnn BZ n Branch if Zero +// 1110 0001 nnnn nnnn BNZ n Branch if not Zero +// 1110 0010 nnnn nnnn BC n Branch if Carry +// 1110 0011 nnnn nnnn BNC n Branch if not Carry +// 1110 0100 nnnn nnnn BOV n Branch if Overflow +// 1110 0101 nnnn nnnn BNOV n Branch if not Overflow +// 1110 0110 nnnn nnnn BN n Branch if Negative +// 1110 0111 nnnn nnnn BNN n Branch if not Negative + static const ushort codes[8] = + { + PIC_bz1, PIC_bnz1, PIC_bc1, PIC_bnc1, + PIC_bov1, PIC_bnov1, PIC_bn1, PIC_bnn1 + }; + insn.itype = codes[(code>>8)&7]; + insn.Op1.type = o_near; + insn.Op1.addr = (insn.ea + 2 + 2 * get_signed(code,0x00FF)) & PIC18_IP_RANGE; + insn.Op1.dtype = dt_code; + } + else if ( b3 == 0xC || b3 == 0xD || b3 == 0xF ) + { +// 1110 110s kkkk kkkk 1111 kkkk kkkk kkkk CALL n, s Call subroutine +// 1110 1111 kkkk kkkk 1111 kkkk kkkk kkkk GOTO n Go to address + static const ushort codes[4] = + { + PIC_call2, PIC_call2, PIC_null, PIC_goto + }; + insn.itype = codes[(code>>8)&3]; + insn.Op1.type = o_near; + insn.Op1.addr = ((insn.get_next_word() & 0xFFF) << 9) | ((code & 0x00FF) << 1); + insn.Op1.dtype = dt_code; + if ( insn.itype == PIC_call2 ) + { + if ( code & 0x0100 ) + { + insn.Op2.type = o_reg; + insn.Op2.reg = FAST; + } + else + { + insn.Op2.type = o_imm; + insn.Op2.value = 0; + } + insn.Op2.dtype = dt_byte; + } + } + else if ( ( code & 0xFFC0 ) == 0xEE00 ) + { +// 1110 1110 00ff kkkk 1111 0000 kkkk kkkk LFSR f, k Move literal to FSR + insn.itype = PIC_lfsr2; + insn.Op1.type = o_reg; + insn.Op1.reg = FSR0 + ((code >> 4) & 3); + insn.Op1.dtype = dt_byte; + insn.Op2.type = o_imm; + insn.Op2.value = ((code&0xF) << 8 ) | (insn.get_next_word() & 0xFF); + insn.Op2.dtype = dt_word; + } + else + { + insn.itype = PIC_null; + } + break; + case 3: +// 1111 xxxx xxxx xxxx NOP No Operation + insn.itype = PIC_nop; + break; + } + } +} + +//-------------------------------------------------------------------------- +int pic_t::basic_ana(insn_t &insn) +{ + int code; + + switch ( ptype ) + { + case PIC12: + code = get_wide_byte(insn.ea); insn.size = 1; + basic_ana12(insn, code); + break; + case PIC14: + code = get_wide_byte(insn.ea); insn.size = 1; + basic_ana14(insn, code); + break; + case PIC16: + code = insn.get_next_word(); + basic_ana16(insn, code); + break; + default: + error("interr: ana"); + } + if ( insn.itype == PIC_null ) + return 0; + return insn.size; +} diff --git a/idasdk76/module/pic/emu.cpp b/idasdk76/module/pic/emu.cpp new file mode 100644 index 0000000..f460483 --- /dev/null +++ b/idasdk76/module/pic/emu.cpp @@ -0,0 +1,509 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "pic.hpp" +#include <segregs.hpp> +#include <frame.hpp> + +//------------------------------------------------------------------------ +bool pic_t::is_banked_reg(ea_t addr, int value) const +{ + // on PIC12, bank size is 0x20 + // on PIC14, bank size is 0x80 + if ( ptype == PIC12 ) + return (addr & 0x1F ) == value; + if ( ptype == PIC14 ) + return (addr & 0x7F ) == value; + return false; +} + +//------------------------------------------------------------------------ +// is pcl register? +bool pic_t::is_pcl(const insn_t &insn) const +{ + if ( insn.Op1.type == o_mem ) + { + switch ( ptype ) + { + case PIC12: + case PIC14: return is_banked_reg(insn.Op1.addr, 0x2); + case PIC16: return insn.Op1.addr == PIC16_PCL; + } + } + return false; +} + +//------------------------------------------------------------------------ +// is bank (status or bsr (PIC18Cxx)) register? +bool pic_t::is_bank(const insn_t &insn) const +{ + if ( insn.Op1.type == o_mem ) + { + switch ( ptype ) + { + case PIC12: + case PIC14: return is_banked_reg(insn.Op1.addr, 0x3); + case PIC16: return insn.Op1.addr == PIC16_BANK; + } + } + return false; +} + +//------------------------------------------------------------------------ +// is pclath register? +bool pic_t::is_pclath(const insn_t &insn) const +{ + if ( insn.Op1.type == o_mem ) + { + switch ( ptype ) + { + case PIC12: return false; + case PIC14: return is_banked_reg(insn.Op1.addr, 0xA); + case PIC16: return insn.Op1.addr == PIC16_PCLATH; + } + } + return false; +} + +//------------------------------------------------------------------------ +void pic_t::process_immediate_number(const insn_t &insn, int n) const +{ + set_immd(insn.ea); + if ( is_defarg(get_flags(insn.ea), n) ) + return; + switch ( insn.itype ) + { + case PIC_iorlw: + case PIC_andlw: + case PIC_xorlw: + op_num(insn.ea, n); + break; + case PIC_lfsr2: + // FSRs are used to address the data memory + if ( dataseg != BADADDR ) + op_offset(insn.ea, n, REF_OFF16, BADADDR, dataseg); + break; + } +} + +//---------------------------------------------------------------------- +void pic_t::destroy_if_unnamed_array(ea_t ea) const +{ + flags_t lF = get_flags(ea); + if ( is_tail(lF) && segtype(ea) == SEG_IMEM ) + { + ea_t head = prev_not_tail(ea); + if ( !has_user_name(get_flags(head)) ) + { + del_items(head, DELIT_SIMPLE); + create_byte(head, ea-head); + ea_t end = next_that(ea, inf_get_max_ea(), f_is_head); + if ( end == BADADDR ) + end = getseg(ea)->end_ea; + create_byte(ea+1, end-ea-1); + } + } +} + +//---------------------------------------------------------------------- +// propagate the bank/pclath register value to the destination +void pic_t::propagate_sreg(const insn_t &insn, ea_t ea, int reg) const +{ + if ( is_loaded(ea) ) + { + sel_t v = get_sreg(insn.ea, reg); + split_sreg_range(ea, reg, v, SR_auto); + } +} + +//---------------------------------------------------------------------- +void pic_t::handle_operand(const insn_t &insn, const op_t &x, int, bool isload) +{ + if ( insn.Op2.type == o_reg && insn.Op2.reg == F || insn.itype == PIC_swapf ) + isload = 0; + switch ( x.type ) + { + case o_reg: + return; + case o_imm: + if ( !isload ) + error("interr: emu"); + process_immediate_number(insn, x.n); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, dr_O, calc_outf(x)); + break; + case o_near: + { + cref_t ftype = fl_JN; + ea_t ea = calc_code_mem(insn, x.addr); + if ( has_insn_feature(insn.itype, CF_CALL) ) + { + if ( !func_does_return(ea) ) + flow = false; + ftype = fl_CN; + } + insn.add_cref(ea, x.offb, ftype); + propagate_sreg(insn, ea, BANK); + propagate_sreg(insn, ea, PCLATH); + } + break; + case o_mem: + { + ea_t ea = calc_data_mem(x.addr); + destroy_if_unnamed_array(ea); + insn.add_dref(ea, x.offb, isload ? dr_R : dr_W); + insn.create_op_data(ea, x); + if ( may_create_stkvars() ) + { + if ( x.addr == PIC16_INDF2 ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) + { + insn.create_stkvar(insn.Op1, 0, STKVAR_VALID_SIZE); + } + } + else if ( x.addr == PIC16_PLUSW2 ) + { + insn_t l = insn; + if ( decode_prev_insn(&l, l.ea) != BADADDR + && l.itype == PIC_movlw ) + { + func_t *pfn = get_func(l.ea); + if ( pfn != NULL && (pfn->flags & FUNC_FRAME) != 0 ) + { + if ( l.create_stkvar(l.Op1, l.Op1.value, STKVAR_VALID_SIZE) ) + op_stkvar(l.ea, l.Op1.n); + } + } + } + } + } + break; + case o_displ: + process_immediate_number(insn, x.n); + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + insn.add_off_drefs(x, dr_O, OOF_ADDR | OOFW_8); + break; + default: + INTERR(10310); + } +} + +//---------------------------------------------------------------------- +// change value of virtual register "BANK" and switch to another bank +void pic_t::split(const insn_t &insn, int reg, sel_t v) +{ + if ( reg == -1 ) + { + flow = 0; + if ( v != BADSEL ) + { + sel_t pclath = get_sreg(insn.ea, PCLATH) & 0x1F; + ea_t ea = calc_code_mem(insn, uchar(v) | (pclath<<8)); + add_cref(insn.ea, ea, fl_JN); + propagate_sreg(insn, ea, BANK); + propagate_sreg(insn, ea, PCLATH); + } + } + else + { + if ( v == BADSEL ) + v = 0; // assume bank0 if bank is unknown + if ( reg == BANK ) + { + // banks 0..15 + v &= 0xF; + } + split_sreg_range(get_item_end(insn.ea), reg, v, SR_auto); + } +} + +//---------------------------------------------------------------------- +// tris PORTn (or movwf TRISn) +bool pic_t::is_load_tris_reg(const insn_t &insn) +{ + ea_t addr; + const char *key; + switch ( insn.itype ) + { + case PIC_tris: + addr = insn.Op1.value; + key = "port"; + break; + case PIC_movwf: + addr = insn.Op1.addr; + key = "tris"; + break; + default: + return false; + } + qstring name; + addr = calc_data_mem(addr); + if ( get_name(&name, addr, GN_NOT_DUMMY) <= 0 ) + return false; + return strnieq(name.begin(), key, 4); +} + +//------------------------------------------------------------------ +inline void pic_t::set_plain_offset(ea_t insn_ea, int n, ea_t base) const +{ + if ( base == BADADDR ) + base = calc_offset_base(insn_ea, n); + if ( base != BADADDR ) + op_plain_offset(insn_ea, n, base); +} + +//---------------------------------------------------------------------- +int pic_t::emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + flow = (Feature & CF_STOP) == 0; + + int bit = CF_USE1; + bool use = true; + while ( true ) + { + for ( int i=0; i < 3; i++,bit<<=1 ) + { + if ( (Feature & bit) == 0 ) + continue; + bool forced = is_forced_operand(insn.ea, i); + handle_operand(insn, insn.ops[i], forced, use); + } + if ( !use ) + break; + use = false; + bit = CF_CHG1; + } + + // Check for: + // - the register bank changes + // - PCLATH changes + // - PCL changes + bool check_regs = false; + switch ( insn.itype ) + { + case PIC_movlp: // Move literal to PCLATH + split(insn, PCLATH, insn.Op1.value); + break; + case PIC_movlb: // Move literal to BSR + split(insn, BANK, insn.Op1.value); + break; + default: + check_regs = true; + break; + } + + for ( int i=0; check_regs && i < 3; i++ ) + { + int reg = 0; + switch ( i ) + { + case 0: + reg = BANK; + if ( !is_bank(insn) ) + continue; + break; + case 1: + reg = PCLATH; + if ( !is_pclath(insn) ) + continue; + break; + case 2: + reg = -1; + if ( !is_pcl(insn) ) + continue; + break; + } + sel_t v = (reg == -1) ? insn.ip : get_sreg(insn.ea, reg); + if ( insn.Op2.type == o_reg && insn.Op2.reg == F ) + { +// split(insn, reg, v); + } + else + { + switch ( insn.itype ) + { + case PIC_bcf: + case PIC_bcf3: + case PIC_bsf: + case PIC_bsf3: + if ( (ptype == PIC12 && insn.Op2.value == 5) // bank selector (PA0) + || (ptype == PIC14 + && ((reg == BANK && (insn.Op2.value == 5 || insn.Op2.value == 6)) // bank selector (RP1:RP0) + || (reg == PCLATH && (insn.Op2.value == 3 || insn.Op2.value == 4)))) + || (ptype == PIC16 && sval_t(insn.Op2.value) >= 0 && insn.Op2.value <= 3) ) + { + if ( v == BADSEL ) + v = 0; + int shift = 0; + if ( (ptype == PIC14 || ptype == PIC12) && reg == BANK ) // we use bank selector bits as the bank value + shift = 5; + if ( insn.itype == PIC_bcf ) + v = v & ~(sel_t(1) << (insn.Op2.value-shift)); + else + v = v | (sel_t(1) << (insn.Op2.value-shift)); + split(insn, reg, v); + } + break; + case PIC_clrf: + case PIC_clrf2: + split(insn, reg, 0); + break; + case PIC_swapf: + case PIC_swapf3: + split(insn, reg, ((v>>4) & 15) | ((v & 15) << 4)); + break; + case PIC_movwf: + case PIC_movwf2: + case PIC_addlw: + case PIC_andlw: + case PIC_iorlw: + case PIC_sublw: + case PIC_xorlw: + { + insn_t l = insn; + if ( decode_prev_insn(&l, l.ea) != BADADDR + && l.itype == PIC_movlw ) + { + switch ( insn.itype ) + { + case PIC_movwf: + case PIC_movwf2: + v = l.Op1.value; + break; + case PIC_addlw: + v += l.Op1.value; + break; + case PIC_andlw: + v &= l.Op1.value; + break; + case PIC_iorlw: + v |= l.Op1.value; + break; + case PIC_sublw: + v -= l.Op1.value; + break; + case PIC_xorlw: + v ^= l.Op1.value; + break; + } + } + else + { + v = BADSEL; + } + } + split(insn, reg, v); + break; + case PIC_movlw: + split(insn, reg, insn.Op2.value); + break; + } + } + } + +// Such as, IDA doesn't seem to convert the following: +// tris 6 +// into +// tris PORTB ( or whatever ) + + flags_t flags = get_flags(insn.ea); + if ( insn.itype == PIC_tris && !is_defarg0(flags) ) + set_plain_offset(insn.ea, 0, dataseg); + +// movlw value +// followed by a +// movwf FSR +// should convert value into an offset , because FSR is used as a pointer to +// the INDF (indirect addressing file) + + if ( insn.itype == PIC_movwf + && insn.Op1.type == o_mem + && is_banked_reg(insn.Op1.addr, 0x4) ) // FSR + { + insn_t l = insn; + if ( decode_prev_insn(&l, l.ea) != BADADDR + && l.itype == PIC_movlw ) + { + set_plain_offset(l.ea, 0, dataseg); + } + } + +// Also - it seems to make sense to me that a +// movlw value +// followed by a +// tris PORTn (or movwf TRISn) +// should convert value into a binary , because the bits indicate whether a +// port is defined for input or output. + + if ( is_load_tris_reg(insn) ) + { + insn_t l; + if ( decode_prev_insn(&l, insn.ea) != BADADDR + && l.itype == PIC_movlw ) + { + op_bin(l.ea, 0); + } + } + +// Move litteral to BSR + + if ( insn.itype == PIC_movlb1 ) + split(insn, BANK, insn.Op1.value); + +// +// Determine if the next instruction should be executed +// + if ( !flow ) + { + flags = get_flags(insn.ea); + flow = conditional_insn(insn, flags); + } + if ( segtype(insn.ea) == SEG_XTRN ) + flow = false; + if ( flow ) + add_cref(insn.ea, insn.ea+insn.size, fl_F); + + return 1; +} + +//---------------------------------------------------------------------- +bool pic_t::create_func_frame(func_t *pfn) const +{ + if ( pfn != NULL ) + { + if ( pfn->frame == BADNODE ) + { + ea_t ea = pfn->start_ea; + if ( ea + 12 < pfn->end_ea ) // minimum 4 + 4 + 2 + 2 bytes needed + { + insn_t insn[4]; + for ( int i=0; i < 4; i++ ) + { + int len = decode_insn(&insn[i], ea); + ea += len > 0 ? len : 0; + } + if ( insn[0].itype == PIC_movff2 // movff FSR2L,POSTINC1 + && insn[0].Op1.addr == PIC16_FSR2L && insn[0].Op2.addr == PIC16_POSTINC1 + && insn[1].itype == PIC_movff2 // movff FSR1L,FSR2L + && insn[1].Op1.addr == PIC16_FSR1L && insn[1].Op2.addr == PIC16_FSR2L + && insn[2].itype == PIC_movlw // movlw <size> + && insn[3].itype == PIC_addwf3 // addwf FSR1L,f + && insn[3].Op1.addr == PIC16_FSR1L && insn[3].Op2.reg == F ) + { + pfn->flags |= FUNC_FRAME; + return add_frame(pfn, insn[2].Op1.value, 0, 0); + } + } + } + } + return 0; +} diff --git a/idasdk75/module/pic/ins.cpp b/idasdk76/module/pic/ins.cpp similarity index 100% rename from idasdk75/module/pic/ins.cpp rename to idasdk76/module/pic/ins.cpp diff --git a/idasdk76/module/pic/ins.hpp b/idasdk76/module/pic/ins.hpp new file mode 100644 index 0000000..f9c4610 --- /dev/null +++ b/idasdk76/module/pic/ins.hpp @@ -0,0 +1,211 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + +PIC_null = 0, // Unknown Operation + +// BYTE-ORIENTED FILE REGISTER OPERATIONS + +PIC_addwf, // Add W and f +PIC_andwf, // AND W with f +PIC_clrf, // Clear f +PIC_clrw, // Clear W +PIC_comf, // Complement f +PIC_decf, // Decrement f +PIC_decfsz, // Decrement f, Skip if 0 +PIC_incf, // Increment f +PIC_incfsz, // Increment f, Skip if 0 +PIC_iorwf, // Inclusive OR W with f +PIC_movf, // Move f +PIC_movwf, // Move W to f +PIC_nop, // No Operation +PIC_rlf, // Rotate Left f through Carry +PIC_rrf, // Rotate Right f through Carry +PIC_subwf, // Subtract W from f +PIC_swapf, // Swap nibbles in f +PIC_xorwf, // Exclusive OR W with f + +// BIT-ORIENTED FILE REGISTER OPERATIONS + +PIC_bcf, // Bit Clear f +PIC_bsf, // Bit Set f +PIC_btfsc, // Bit Test f, Skip if Clear +PIC_btfss, // Bit Test f, Skip if Set + + +// LITERAL AND CONTROL OPERATIONS + +PIC_addlw, // Add literal and W +PIC_andlw, // AND literal with W +PIC_call, // Call subroutine +PIC_clrwdt, // Clear Watchdog Timer +PIC_goto, // Go to address +PIC_iorlw, // Inclusive OR literal with W +PIC_movlw, // Move literal to W +PIC_retfie, // Return from interrupt +PIC_retlw, // Return with literal in W +PIC_return, // Return from Subroutine +PIC_sleep, // Go into standby mode +PIC_sublw, // Subtract W from literal +PIC_xorlw, // Exclusive OR literal with W + +// ADDITIONAL INSTRUCTIONS TO MAINTAIN COMPITIBILITY WITH 12C5xx,16C5x + +PIC_option, // Load OPTION register +PIC_tris, // Load TRIS Register + +// MACROS + +PIC_movfw, // Move Contents of File Reg to W +PIC_tstf, // Test Contents of File Register +PIC_negf, // Negate File Register Contents +PIC_b, // Branch to Address +PIC_clrc, // Clear Carry +PIC_clrdc, // Clear Digit Carry +PIC_clrz, // Clear Zero +PIC_setc, // Set Carry +PIC_setdc, // Set Digit Carry +PIC_setz, // Set Zero +PIC_skpc, // Skip on Carry +PIC_skpdc, // Skip on Digit Carry +PIC_skpnc, // Skip on No Carry +PIC_skpndc, // Skip on No Digit Carry +PIC_skpnz, // Skip on No Zero +PIC_skpz, // Skip on Zero +PIC_bc, // Branch on Carry to Address k +PIC_bdc, // Branch on Digit Carry to k +PIC_bnc, // Branch on No Carry to k +PIC_bndc, // Branch on No Digit Carry to k +PIC_bnz, // Branch on No Zero to Address +PIC_bz, // Branch on Zero to Address k +PIC_addcf, // Add Carry to File Register +PIC_adddcf, // Add Digit to File Register +PIC_subcf, // Subtract Carry from File Reg + +// ADDITIONAL INSTRUCTIONS FOR 18Cxx + +// BYTE-ORIENTED FILE REGISTER OPERATIONS + +PIC_addwf3, // Add W and f +PIC_addwfc3, // Add W and Carry to f +PIC_andwf3, // AND W with f +PIC_clrf2, // Clear f +PIC_comf3, // Complement f +PIC_cpfseq2, // Compare f with W, Skip if == +PIC_cpfsgt2, // Compare f with W, Skip if > +PIC_cpfslt2, // Compare f with W, Skip if < +PIC_decf3, // Decrement f +PIC_decfsz3, // Decrement f, Skip if 0 +PIC_dcfsnz3, // Decrement f, Skip if not 0 +PIC_incf3, // Increment f +PIC_incfsz3, // Increment f, Skip if 0 +PIC_infsnz3, // Increment f, Skip if not 0 +PIC_iorwf3, // Inclusive OR W with f +PIC_movf3, // Move f +PIC_movff2, // Move fs to fd +PIC_movwf2, // Move W to f +PIC_mulwf2, // Multiply W with f +PIC_negf2, // Negate f +PIC_rlcf3, // Rotate Left f through Carry +PIC_rlncf3, // Rotate Left f +PIC_rrcf3, // Rotate Right f through Carry +PIC_rrncf3, // Rotate Right f +PIC_setf2, // Set f +PIC_subfwb3, // Substract f from W with borrow +PIC_subwf3, // Substract W from f +PIC_subwfb3, // Substract W from f with borrow +PIC_swapf3, // Swap nibbles in f +PIC_tstfsz2, // Test f, Skip if 0 +PIC_xorwf3, // Exclusive OR W with f + +// BIT-ORIENTED FILE REGISTER OPERATIONS + +PIC_bcf3, // Bit Clear f +PIC_bsf3, // Bit Set f +PIC_btfsc3, // Bit Test f, Skip if Clear +PIC_btfss3, // Bit Test f, Skip if Set +PIC_btg3, // Bit Toggle f + +// CONTROL OPERATIONS + +PIC_bc1, // Branch if Carry +PIC_bn1, // Branch if Negative +PIC_bnc1, // Branch if not Carry +PIC_bnn1, // Branch if not Negative +PIC_bnov1, // Branch if not Overflow +PIC_bnz1, // Branch if not Zero +PIC_bov1, // Branch if Overflow +PIC_bra1, // Branch unconditionally +PIC_bz1, // Branch if Zero +PIC_call2, // Call subroutine +// PIC_clrwdt +PIC_daw0, // Decimal Adjust W +// PIC_goto +// PIC_nop +// PIC_nop +PIC_pop0, // Pop top of return stack +PIC_push0, // Push top of return stack +PIC_rcall1, // Relative Call subroutine +PIC_reset0, // Software device Reset +PIC_retfie1, // Return from interrupt enable +// PIC_retlw +PIC_return1, // Return from Subroutine +// PIC_sleep + +// LITERAL OPERATIONS + +// PIC_addlw +// PIC_andlw +// PIC_iorlw +PIC_lfsr2, // Move literal to FSR +PIC_movlb1, // Move literal to BSR +// PIC_movlw +PIC_mullw1, // Multiply literal with W +// PIC_retlw +// PIC_sublw +// PIC_xorlw + +// DATA MEMORY <-> PROGRAM MEMORY OPERATIONS + +PIC_tblrd0, // Table Read +PIC_tblrd0p, // Table Read with post-increment +PIC_tblrd0m, // Table Read with post-decrement +PIC_tblrdp0, // Table Read with pre-increment +PIC_tblwt0, // Table Write +PIC_tblwt0p, // Table Write with post-increment +PIC_tblwt0m, // Table Write with post-decrement +PIC_tblwtp0, // Table Write with pre-increment + +// ADDITIONAL INSTRUCTIONS FOR 16F1x and 12F1x + +PIC_addwfc, // Add W and Carry to f +PIC_movlp, // Move literal to PCLATH +PIC_movlb, // Move literal to BSR +PIC_addfsr, // Add Literal to FSRn +PIC_asrf, // Arithmetic Right Shift +PIC_lslf, // Logical Left Shift +PIC_lsrf, // Logical Right Shift +PIC_subwfb, // Subtract with Borrow W from f +PIC_bra, // Relative Branch +PIC_brw, // Relative Branch with W +PIC_callw, // Call Subroutine with W +PIC_reset, // Software device Reset +PIC_moviw, // Move INDFn to W +PIC_movwi, // Move W to INDFn + +PIC_last, + + }; + +#endif diff --git a/idasdk76/module/pic/makefile b/idasdk76/module/pic/makefile new file mode 100644 index 0000000..d383f6b --- /dev/null +++ b/idasdk76/module/pic/makefile @@ -0,0 +1,57 @@ +PROC=pic +CONFIGS=pic12.cfg pic14.cfg pic16.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp ins.hpp pic.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp pic.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp pic.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp pic.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp pic.hpp reg.cpp diff --git a/idasdk75/module/pic/out.cpp b/idasdk76/module/pic/out.cpp similarity index 100% rename from idasdk75/module/pic/out.cpp rename to idasdk76/module/pic/out.cpp diff --git a/idasdk76/module/pic/pic.hpp b/idasdk76/module/pic/pic.hpp new file mode 100644 index 0000000..090b292 --- /dev/null +++ b/idasdk76/module/pic/pic.hpp @@ -0,0 +1,169 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _PIC_HPP +#define _PIC_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" +#define PROCMOD_NAME pic +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + +//------------------------------------------------------------------ +enum regnum_t ENUM_SIZE(uint16) +{ + W, F, + ACCESS, // register for PIC18Cxx + BANKED, // register for PIC18Cxx + FAST, // register for PIC18Cxx + FSR0, // register for PIC18Cxx + FSR1, // register for PIC18Cxx + FSR2, // register for PIC18Cxx + BANK, + rVcs, rVds, // virtual registers for code and data segments + PCLATH, + PCLATU // register for PIC18Cxx +}; + +#define PIC16_FSR2L 0xFD9 +#define PIC16_PLUSW2 0xFDB +#define PIC16_INDF2 0xFDF +#define PIC16_BANK 0xFE0 +#define PIC16_FSR1L 0xFE1 +#define PIC16_POSTINC1 0xFE6 +#define PIC16_PCL 0xFF9 +#define PIC16_PCLATH 0xFFA + +//------------------------------------------------------------------ +// processor types + +typedef uchar proctype_t; + +const proctype_t PIC12 = 0; +const proctype_t PIC14 = 1; +const proctype_t PIC16 = 2; + +//------------------------------------------------------------------ +inline bool is_bit_insn(const insn_t &insn) +{ + return insn.itype >= PIC_bcf && insn.itype <= PIC_btfss + || insn.itype >= PIC_bcf3 && insn.itype <= PIC_btg3; +} + +ea_t calc_code_mem(const insn_t &insn, ea_t ea); +int calc_outf(const op_t &x); + +//------------------------------------------------------------------ +void interr(const char *module); + +void idaapi pic_segend(outctx_t &ctx, segment_t *seg); + +int idaapi is_align_insn(ea_t ea); + +int idaapi is_jump_func(const func_t *pfn, ea_t *jump_target); +int idaapi is_sane_insn(int nocrefs); +int idaapi may_be_func(void); // can a function start here? + +//------------------------------------------------------------------ +struct pic_iohandler_t : public iohandler_t +{ + struct pic_t ± + pic_iohandler_t(pic_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + virtual void get_cfg_filename(char *buf, size_t bufsize) override; + virtual bool area_processing(ea_t /*start*/, ea_t /*end*/, const char * /*name*/, const char * /*aclass*/) override; +}; + +struct pic_t : public procmod_t +{ + pic_iohandler_t ioh = pic_iohandler_t(*this, helper); + + netnode helper; + ea_t dataseg = BADADDR; + int sav_respect_info = IORESP_NONE; + + inline void save_idpflags() { helper.altset(-1, idpflags); } + inline void save_dataseg() { helper.altset(0, ea2node(dataseg)); } + +#define IDP_SIMPLIFY 0x0001 // simplify instructions + ushort idpflags = IDP_SIMPLIFY; + inline bool dosimple(void) + { // if macros are enabled, we should simplify insns + return inf_macros_enabled() || (idpflags & IDP_SIMPLIFY) != 0; + } + + proctype_t ptype = PIC12; + const char *cfgname = "pic12.cfg"; + bool set = false; + bool flow = false; + + struct portmap_t + { + ea_t from; + ea_t to; + }; + qvector<portmap_t> map; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void create_mappings(void); + void load_symbols_without_infotype(int _respect_info); + void load_symbols(int _respect_info); + const char *find_sym(ea_t address); + const ioport_bits_t *find_bits(ea_t address); + const char *find_bit(ea_t address, int bit); + void apply_symbols(void); + void setup_device(int lrespect_info); + ea_t AdditionalSegment(size_t size, ea_t offset, const char *name) const; + const char *set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + void set_cpu(int n); + void free_mappings(void); + void add_mapping(ea_t from, ea_t to); + ea_t map_port(ea_t from); + void check_pclath(segment_t *s) const; + + bool build_macro(insn_t &insn, bool may_go_forward); + void simplify(insn_t &insn) const; + int basic_ana(insn_t &insn); + int ana(insn_t *_insn); + + bool is_banked_reg(ea_t addr, int value) const; + bool is_pcl(const insn_t &insn) const; + bool is_bank(const insn_t &insn) const; + bool is_pclath(const insn_t &insn) const; + void process_immediate_number(const insn_t &insn, int n) const; + void destroy_if_unnamed_array(ea_t ea) const; + void propagate_sreg(const insn_t &insn, ea_t ea, int reg) const; + void handle_operand(const insn_t &insn, const op_t &x, int, bool isload); + void split(const insn_t &insn, int reg, sel_t v); + bool is_load_tris_reg(const insn_t &insn); + inline void set_plain_offset(ea_t insn_ea, int n, ea_t base) const; + int emu(const insn_t &insn); + bool create_func_frame(func_t *pfn) const; + + void pic_header(outctx_t &ctx); + int out_equ(outctx_t &ctx); + void out_equ(outctx_t &ctx, bool indent, const char *name, uval_t off); + void pic_data(outctx_t &ctx, bool analyze_only); + ea_t calc_data_mem(ea_t ea); + bool conditional_insn(const insn_t &insn, flags_t F) const; // may instruction be skipped? + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void pic_assumes(outctx_t &ctx); // function to produce assume directives + void pic_segstart(outctx_t &ctx, segment_t *Srange) const; + void pic_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; +#endif // _PIC_HPP diff --git a/idasdk75/module/pic/pic12.cfg b/idasdk76/module/pic/pic12.cfg similarity index 100% rename from idasdk75/module/pic/pic12.cfg rename to idasdk76/module/pic/pic12.cfg diff --git a/idasdk75/module/pic/pic14.cfg b/idasdk76/module/pic/pic14.cfg similarity index 100% rename from idasdk75/module/pic/pic14.cfg rename to idasdk76/module/pic/pic14.cfg diff --git a/idasdk75/module/pic/pic16.cfg b/idasdk76/module/pic/pic16.cfg similarity index 100% rename from idasdk75/module/pic/pic16.cfg rename to idasdk76/module/pic/pic16.cfg diff --git a/idasdk76/module/pic/reg.cpp b/idasdk76/module/pic/reg.cpp new file mode 100644 index 0000000..92e2282 --- /dev/null +++ b/idasdk76/module/pic/reg.cpp @@ -0,0 +1,747 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include <ctype.h> +#include "pic.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names_pic12[] = +{ + "w", "f", + "ACCESS", // register for PIC18Cxx + "BANKED", // register for PIC18Cxx + "FAST", // register for PIC18Cxx + "FSR0", // register for PIC18Cxx + "FSR1", // register for PIC18Cxx + "FSR2", // register for PIC18Cxx + "bank", + "cs","ds", // virtual registers for code and data segments + "status", + "pclatu" // register for PIC18Cxx +}; + +static const char *const register_names_pic14[] = +{ + "w", "f", + "ACCESS", // register for PIC18Cxx + "BANKED", // register for PIC18Cxx + "FAST", // register for PIC18Cxx + "FSR0", // register for PIC18Cxx + "FSR1", // register for PIC18Cxx + "FSR2", // register for PIC18Cxx + "bank", + "cs","ds", // virtual registers for code and data segments + "pclath", + "pclatu" // register for PIC18Cxx +}; + +static const char *const register_names_pic16[] = +{ + "w", "f", + "ACCESS", // register for PIC18Cxx + "BANKED", // register for PIC18Cxx + "FAST", // register for PIC18Cxx + "FSR0", // register for PIC18Cxx + "FSR1", // register for PIC18Cxx + "FSR2", // register for PIC18Cxx + "bsr", + "cs","ds", // virtual registers for code and data segments + "pclath", + "pclatu" // register for PIC18Cxx +}; + +//-------------------------------------------------------------------------- +// 11 01xx kkkk kkkk RETLW k Return with literal in W +static const uchar retcode_0[] = { 0x08, 0x00 }; // return +static const uchar retcode_1[] = { 0x09, 0x00 }; // retfie +static const uchar retcode_2[] = { 0x00, 0x34 }; // retlw 0 +static const uchar retcode_3[] = { 0x01, 0x34 }; // retlw 1 + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Microchip's MPALC +//----------------------------------------------------------------------- +static const asm_t mpalc = +{ + ASH_HEXF2|ASD_DECF3|ASB_BINF5|ASO_OCTF5|AS_N2CHR|AS_NCMAS|AS_ONEDUP, + 0, + "Microchip's MPALC", + 0, + NULL, // header lines + "org", // org + "end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + "data", // ascii string directive + "byte", // byte directive + "data", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "res %s", // uninited arrays + "equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + NULL, // "public" name keyword + NULL, // "weak" name keyword + NULL, // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + NULL, // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &mpalc, NULL }; + +//-------------------------------------------------------------------------- +void pic_t::free_mappings(void) +{ + map.clear(); +} + +void pic_t::add_mapping(ea_t from, ea_t to) +{ + if ( from != to ) + { + deb(IDA_DEBUG_IDP, "add_mapping %a -> %a\n", from, to); + portmap_t &p = map.push_back(); + p.from = from; + p.to = to; + } +} + +ea_t pic_t::map_port(ea_t from) +{ + for ( int i=0; i < map.size(); i++ ) + if ( map[i].from == from ) + return map[i].to; + return from; +} + +//-------------------------------------------------------------------------- +void pic_iohandler_t::get_cfg_filename(char *buf, size_t bufsize) +{ + qstrncpy(buf, pm.cfgname, bufsize); +} + +// create the mapping table +void pic_t::create_mappings(void) +{ + free_mappings(); + for ( int i=0; i < ioh.ports.size(); i++ ) + { + const char *name = ioh.ports[i].name.c_str(); + ea_t nameea = get_name_ea(BADADDR, name); + if ( nameea != BADADDR && nameea > dataseg ) + add_mapping(ioh.ports[i].address, nameea-dataseg); + } +} + +//---------------------------------------------------------------------- +static ea_t AddSegment(ea_t start, size_t size, ea_t base, const char *name, uchar type) +{ + segment_t s; + s.start_ea = start; + s.end_ea = start + size; + s.sel = allocate_selector(base >> 4); + s.type = type; + s.align = saRelByte; + s.comb = scPub; + add_segm_ex(&s, name, NULL, ADDSEG_NOSREG|ADDSEG_OR_DIE); + return s.start_ea; +} + +//---------------------------------------------------------------------- +// special handling for 16-bit PICs +// for CODE segments use addresses as-is +// for DATA segments, start from dataseg base +bool pic_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass) +{ + if ( pm.ptype != PIC16 ) + return false; + if ( strcmp(aclass, "CODE") == 0 ) + { + AddSegment(start, end-start, 0, name, SEG_CODE); + } + else if ( strcmp(aclass, "DATA") == 0 ) + { + if ( pm.dataseg == BADADDR ) + { + pm.dataseg = free_chunk(0, 0x1000, -0xF); + pm.save_dataseg(); + } + uchar type = stristr(name, "FSR") != NULL ? SEG_IMEM : SEG_DATA; + AddSegment(pm.dataseg + start, end-start, pm.dataseg, name, type); + } + else + { + return false; + } + return true; +} + +void pic_t::load_symbols_without_infotype(int _respect_info) +{ + ioh.ports.clear(); + ioh.respect_info = _respect_info; + iohandler_t::ioports_loader_t ldr(&ioh); + read_ioports2(&ioh.ports, &ioh.device, cfgname, &ldr); + create_mappings(); +} + +void pic_t::load_symbols(int _respect_info) +{ + if ( ioh.display_infotype_dialog(IORESP_ALL, &_respect_info, cfgname) ) + load_symbols_without_infotype(_respect_info); +} + +const char *pic_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? port->name.c_str() : NULL; +} + +const ioport_bits_t *pic_t::find_bits(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? (&port->bits) : NULL; +} + +const char *pic_t::find_bit(ea_t address, int bit) +{ + address = map_port(address); + const ioport_bit_t *b = find_ioport_bit(ioh.ports, address, bit); + return b ? b->name.c_str() : NULL; +} + +//---------------------------------------------------------------------- +void pic_t::apply_symbols(void) +{ + free_mappings(); + if ( dataseg != BADADDR ) + { + for ( int i=0; i < ioh.ports.size(); i++ ) + { + ea_t ea = calc_data_mem(ioh.ports[i].address); + segment_t *s = getseg(ea); + if ( s == NULL || s->type != SEG_IMEM ) + continue; + create_byte(ea, 1); + const char *name = ioh.ports[i].name.c_str(); + if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) + set_cmt(ea, name, 0); + } + for ( segment_t *d = getseg(dataseg); d != NULL; d = get_next_seg(d->start_ea) ) + { + if ( d->type != SEG_IMEM ) + continue; + ea_t ea = d->start_ea; + ea_t dataend = d->end_ea; + while ( 1 ) + { + ea = next_unknown(ea, dataend); + if ( ea == BADADDR ) + break; + ea_t end = next_that(ea, dataend, f_is_head); + if ( end == BADADDR ) + end = dataend; + create_byte(ea, end-ea); + } + } + create_mappings(); + } +} + +//------------------------------------------------------------------ +void pic_t::setup_device(int lrespect_info) +{ + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgname, &cb) ) + { + if ( ioh.device != NONEPROC ) + helper.supset(-1, ioh.device.c_str()); + // we don't pass IORESP_PORT because that would rename bytes in the code segment + // we'll handle port renaming ourselves + if ( ioh.display_infotype_dialog(IORESP_ALL, &lrespect_info, cfgname) ) + { + ioh.set_device_name(ioh.device.c_str(), lrespect_info & ~IORESP_PORT); + if ( (lrespect_info & IORESP_PORT) != 0 ) + apply_symbols(); + } + } +} + +//---------------------------------------------------------------------- +ea_t pic_t::AdditionalSegment(size_t size, ea_t offset, const char *name) const +{ + ea_t start = free_chunk(0, size, -0xF); + return AddSegment(start, size, start - offset, name, SEG_IMEM) - offset; +} + +//-------------------------------------------------------------------------- +static const proctype_t ptypes[] = +{ + PIC12, + PIC14, + PIC16 +}; + +//------------------------------------------------------------------------- +static const cfgopt_t options[] = +{ // name varptr type/bit + CFGOPT_B("PIC_SIMPLIFY", pic_t, idpflags, ushort(IDP_SIMPLIFY)), +}; + +//-------------------------------------------------------------------------- +static const cfgopt_t *find_option(const char *name) +{ + for ( int i=0; i < qnumber(options); i++ ) + if ( streq(options[i].name, name) ) + return &options[i]; + return NULL; +} + +//-------------------------------------------------------------------------- +int idaapi optionscb(int field_id, form_actions_t &fa) +{ + // ensure that instruction simplification can't be turned off + // if macros are enabled + if ( field_id == CB_INIT ) + fa.enable_field(1, !inf_macros_enabled()); + return 1; +} + +//-------------------------------------------------------------------------- +static int idaapi choose_device(int, form_actions_t &fa) +{ + pic_t &pm = *(pic_t *)fa.get_ud(); + if ( choose_ioport_device(&pm.ioh.device, pm.cfgname) ) + { + pm.helper.supset(-1, pm.ioh.device.c_str()); + pm.load_symbols(IORESP_ALL); + pm.apply_symbols(); + } + return 0; +} + +const char *pic_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + if ( keyword == NULL ) + { + if ( ptype != PIC16 ) + { + static const char form[] = +"HELP\n" +"PIC specific options\n" +"\n" +" Simplify instructions\n" +"\n" +" If this option is on, IDA will simplify instructions and replace\n" +" them by clearer macro-instructions\n" +" For example,\n" +"\n" +" btfsc 3,0\n" +"\n" +" will be replaced by\n" +"\n" +" skpnc\n" +"\n" +" If macros are enabled, this options should be turned on.\n" +"ENDHELP\n" +"PIC specific options\n" +"%/%*\n" +" <~S~implify instructions:C1>>\n" +"\n" +" <~C~hoose device name:B:0::>\n" +"\n" +"\n"; + if ( inf_macros_enabled() ) + setflag(idpflags, IDP_SIMPLIFY, true); + CASSERT(sizeof(idpflags) == sizeof(ushort)); + if ( ask_form(form, optionscb, this, &idpflags, choose_device) == ASKBTN_YES ) + { +SAVE: + if ( idb_loaded ) + save_idpflags(); + } + } + else + { + static const char form[] = + "PIC specific options\n" + "\n" + " <~C~hoose device name:B:0::>\n" + "\n" + "\n"; + ask_form(form, choose_device); + } + return IDPOPT_OK; + } + else + { + const cfgopt_t *opt = find_option(keyword); + if ( opt == NULL ) + return IDPOPT_BADKEY; + const char *errmsg = opt->apply(value_type, value, this); + if ( errmsg != IDPOPT_OK ) + return errmsg; + // if macros are enabled, we should simplify insns + if ( ph.supports_macros() && inf_macros_enabled() ) + setflag(idpflags, IDP_SIMPLIFY, true); + goto SAVE; + } +} + +//-------------------------------------------------------------------------- +void pic_t::set_cpu(int n) +{ + if ( ptypes[n] != ptype ) + { + ptype = ptypes[n]; + ph.cnbits = 12 + 2*n; + } + switch ( ptype ) + { + case PIC12: + ph.reg_names = register_names_pic12; + cfgname = "pic12.cfg"; + break; + case PIC14: + ph.reg_names = register_names_pic14; + cfgname = "pic14.cfg"; + break; + case PIC16: + ph.reg_names = register_names_pic16; + cfgname = "pic16.cfg"; + ph.cnbits = 8; + ph.reg_last_sreg = PCLATU; + break; + default: + INTERR(10311); + } + setflag(ph.flag2, PR2_MACRO, ptype != PIC16); +} + +//---------------------------------------------------------------------- +void pic_t::check_pclath(segment_t *s) const +{ + if ( s == NULL ) + return; + if ( s->defsr[PCLATH-ph.reg_first_sreg] == BADSEL ) + s->defsr[PCLATH-ph.reg_first_sreg] = 0; +} + +//---------------------------------------------------------------------- +void pic_t::load_from_idb() +{ + idpflags = (ushort)helper.altval(-1); + dataseg = node2ea(helper.altval(0)); + ioh.upgrade_device_index(); + helper.supstr(&ioh.device, -1); + load_symbols_without_infotype(IORESP_PORT); + ioh.respect_info = sav_respect_info; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(pic_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi pic_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + sav_respect_info = ioh.respect_info; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + free_mappings(); + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + { + segment_t *s0 = get_first_seg(); + if ( s0 != NULL ) + { + ea_t firstEA = s0->start_ea; + if ( ptype == PIC12 || ptype == PIC14 ) + { + set_segm_name(s0, "CODE"); + dataseg = AdditionalSegment(0x200, 0, "DATA"); + setup_device(IORESP_INT|IORESP_PORT); + } + else + { + setup_device(IORESP_ALL); + } + s0 = getseg(firstEA); + if ( s0 != NULL ) + { + set_default_sreg_value(s0, BANK, 0); + set_default_sreg_value(s0, PCLATH, 0); + set_default_sreg_value(s0, PCLATU, 0); + } + segment_t *s1 = getseg(dataseg); + if ( s1 != NULL ) + { + set_default_sreg_value(s1, BANK, 0); + set_default_sreg_value(s1, PCLATH, 0); + set_default_sreg_value(s1, PCLATU, 0); + } + } + } + // save info to idb + save_dataseg(); + save_idpflags(); + break; + + case processor_t::ev_ending_undo: + set_cpu(ph.get_proc_index()); + ioh.respect_info = IORESP_NONE; + //fall through + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + // init PCLATH for very old IDBs + check_pclath(get_first_seg()); + check_pclath(getseg(dataseg)); + break; + + case processor_t::ev_newprc: // new processor type + { + int n = va_arg(va, int); + // bool keep_cfg = va_argi(va, bool); + if ( set ) + return 0; + set = true; + set_cpu(n); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + pic_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + pic_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + pic_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + pic_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + pic_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + pic_data(*ctx, analyze_only); + return 1; + } + + case processor_t::ev_is_sp_based: + { + int *mode = va_arg(va, int *); + *mode = OP_SP_ADD | OP_FP_BASED; + return 1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + *frsize = 0; + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "Microchip PIC:" +static const char *const shnames[] = +{ "PIC12Cxx", + "PIC16Cxx", + "PIC18Cxx", + NULL +}; +static const char *const lnames[] = +{ FAMILY "Microchip PIC12Cxx - 12 bit instructions", + "Microchip PIC16Cxx - 14 bit instructions", + "Microchip PIC18Cxx - 16 bit instructions", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_PIC, // id + // flag + PRN_HEX + | PR_SEGS + | PR_SGROTHER + | PR_STACK_UP + | PR_RNAMESOK, + // flag2 + PR2_IDP_OPTS // the module has processor-specific configuration options + | PR2_MACRO, // try to combine several instructions into a macro instruction + 12, // 12/14/16 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names_pic14, // Register names + qnumber(register_names_pic14), // Number of registers + + BANK, // first + PCLATH, // last + 0, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + PIC_null, + PIC_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 0, 0, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + PIC_return, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/ppc/notify_codes.hpp b/idasdk76/module/ppc/notify_codes.hpp new file mode 100644 index 0000000..7c39102 --- /dev/null +++ b/idasdk76/module/ppc/notify_codes.hpp @@ -0,0 +1,173 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __PPC_NOTIFY_CODES_HPP +#define __PPC_NOTIFY_CODES_HPP + +#include <idp.hpp> + +struct pushinfo_t; +//---------------------------------------------------------------------- +// The following events are supported by the PPC module in the ph.notify() function +namespace ppc_module_t +{ + enum event_codes_t + { + ev_dummy = processor_t::ev_loader, // was used before + ev_set_toc, + // obsolete, use processor_t::set_code16_mode() + ev_set_vle_mode, + ev_restore_pushinfo, // Restore function prolog info from the database + // in: pushinfo_t *pi + // ea_t func_start + // Returns: 1-ok, otherwise-failed + ev_save_pushinfo, // Save function prolog info to the database + // in: ea_t func_start + // const pushinfo_t *pi + // Returns: 1-ok, otherwise-failed + // obsolete, use processor_t::get_code16_mode() + ev_get_vle_mode, + ev_set_sda_base, + ev_get_sda_base, + ev_get_toc, + ev_is_gnu_mcount_nc, // Is __gnu_mcount_nc function? + // in: ea_t ea + // Returns: 1-yes, -1-no + ev_set_func_toc, // Set TOC for a function. + // in: ea_t func_start_ea + // ea_t toc_ea + ev_get_fix_gnu_vleadreloc_bug, + // Get config var PPC_FIX_GNU_VLEADRELOC_BUG. + // Used by ELF-loader PPC submodule. + // Returns: 1-yes, -1-no + + ev_get_abi, // returns ABI, \ref abi_type_t + + ev_get_func_toc, // Fet TOC for a function. + // out: ea_t *toc_ea + // in: ea_t func_start_ea + + ev_serialize_pushinfo, // Save function prolog info to the buffer + // in: bytevec_t *buf + // ea_t func_start + // const pushinfo_t *pi + // int flags (reserved) + // Returns: 1-ok, otherwise-failed + ev_deserialize_pushinfo, + // Restore function prolog info from the buffer + // in: pushinfo_t *pi + // memory_deserializer_t *buf + // ea_t func_start + // int flags (reserved) + // Returns: 1-ok, otherwise-failed + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + // set TOC / SDA2_BASE (gpr2) + inline void set_toc(ea_t toc_ea, adiff_t displ = 0) + { + QASSERT(10230, PH.id == PLFM_PPC); + processor_t::notify(idp_ev(ev_set_toc), toc_ea, displ); + } + + // get TOC/SDA2_BASE (gpr2) + inline ea_t get_toc() + { + QASSERT(10241, PH.id == PLFM_PPC); + ea_t toc_ea = BADADDR; // just in case + processor_t::notify(idp_ev(ev_get_toc), &toc_ea); + return toc_ea; + } + + inline bool restore_pushinfo(pushinfo_t *pi, ea_t func_start) + { + return processor_t::notify(idp_ev(ev_restore_pushinfo), pi, func_start) == 1; + } + + inline bool save_pushinfo(ea_t func_start, const pushinfo_t &pi) + { + return processor_t::notify(idp_ev(ev_save_pushinfo), func_start, &pi) == 1; + } + + inline bool is_gnu_mcount_nc(ea_t ea) + { + return processor_t::notify(idp_ev(ev_is_gnu_mcount_nc), ea) == 1; + } + + inline bool get_fix_gnu_vleadreloc_bug() + { + return processor_t::notify(idp_ev(ev_get_fix_gnu_vleadreloc_bug)) == 1; + } + + inline int get_abi() + { + return processor_t::notify(idp_ev(ev_get_abi)); + } + + inline void set_sda_base(ea_t sda_base) + { + QASSERT(10239, PH.id == PLFM_PPC); + processor_t::notify(idp_ev(ev_set_sda_base), sda_base); + } + + // get SDA base (gpr13) + inline ea_t get_sda_base() + { + QASSERT(10240, PH.id == PLFM_PPC); + ea_t sda_base = BADADDR; // just in case + processor_t::notify(idp_ev(ev_get_sda_base), &sda_base); + return sda_base; + } + + // set TOC for a function (gpr2) + inline void set_func_toc(ea_t func_ea, ea_t toc_ea) + { + QASSERT(10247, PH.id == PLFM_PPC); + processor_t::notify(idp_ev(ev_set_func_toc), func_ea, toc_ea); + } + + // get TOC for a function (gpr2) + inline ea_t get_func_toc(ea_t func_ea) + { + QASSERT(10265, PH.id == PLFM_PPC); + ea_t toc_ea = BADADDR; // just in case + processor_t::notify(idp_ev(ev_get_func_toc), &toc_ea, func_ea); + return toc_ea; + } + + inline bool serialize_pushinfo( + bytevec_t *buf, + ea_t func_start, + const pushinfo_t &pi, + int flags = 0) + { + return processor_t::notify(idp_ev(ev_serialize_pushinfo), + buf, + func_start, + &pi, + flags) == 1; + } + + inline bool deserialize_pushinfo( + pushinfo_t *pi, + memory_deserializer_t *buf, + ea_t func_start, + int flags = 0) + { + return processor_t::notify(idp_ev(ev_deserialize_pushinfo), + pi, + buf, + func_start, + flags) == 1; + } +} + +#endif // __PPC_NOTIFY_CODES_HPP diff --git a/idasdk75/module/readme.txt b/idasdk76/module/readme.txt similarity index 100% rename from idasdk75/module/readme.txt rename to idasdk76/module/readme.txt diff --git a/idasdk75/module/sam8/ana.cpp b/idasdk76/module/sam8/ana.cpp similarity index 100% rename from idasdk75/module/sam8/ana.cpp rename to idasdk76/module/sam8/ana.cpp diff --git a/idasdk75/module/sam8/emu.cpp b/idasdk76/module/sam8/emu.cpp similarity index 100% rename from idasdk75/module/sam8/emu.cpp rename to idasdk76/module/sam8/emu.cpp diff --git a/idasdk75/module/sam8/ins.cpp b/idasdk76/module/sam8/ins.cpp similarity index 100% rename from idasdk75/module/sam8/ins.cpp rename to idasdk76/module/sam8/ins.cpp diff --git a/idasdk75/module/sam8/ins.hpp b/idasdk76/module/sam8/ins.hpp similarity index 100% rename from idasdk75/module/sam8/ins.hpp rename to idasdk76/module/sam8/ins.hpp diff --git a/idasdk76/module/sam8/makefile b/idasdk76/module/sam8/makefile new file mode 100644 index 0000000..77128bb --- /dev/null +++ b/idasdk76/module/sam8/makefile @@ -0,0 +1,50 @@ +PROC=sam8 + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + sam8.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \ + sam8.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ + sam8.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \ + sam8.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp reg.cpp sam8.hpp diff --git a/idasdk75/module/sam8/out.cpp b/idasdk76/module/sam8/out.cpp similarity index 100% rename from idasdk75/module/sam8/out.cpp rename to idasdk76/module/sam8/out.cpp diff --git a/idasdk75/module/sam8/readme.txt b/idasdk76/module/sam8/readme.txt similarity index 100% rename from idasdk75/module/sam8/readme.txt rename to idasdk76/module/sam8/readme.txt diff --git a/idasdk75/module/sam8/reg.cpp b/idasdk76/module/sam8/reg.cpp similarity index 100% rename from idasdk75/module/sam8/reg.cpp rename to idasdk76/module/sam8/reg.cpp diff --git a/idasdk75/module/sam8/sam8.hpp b/idasdk76/module/sam8/sam8.hpp similarity index 100% rename from idasdk75/module/sam8/sam8.hpp rename to idasdk76/module/sam8/sam8.hpp diff --git a/idasdk75/module/sam8/test.asm b/idasdk76/module/sam8/test.asm similarity index 100% rename from idasdk75/module/sam8/test.asm rename to idasdk76/module/sam8/test.asm diff --git a/idasdk76/module/script/ebc.py b/idasdk76/module/script/ebc.py new file mode 100644 index 0000000..1ceee18 --- /dev/null +++ b/idasdk76/module/script/ebc.py @@ -0,0 +1,1393 @@ + +# ---------------------------------------------------------------------- +# EFI bytecode processor module +# (c) Hex-Rays +# Please send fixes or improvements to support@hex-rays.com + +import sys +import struct + +from ida_bytes import * +from ida_ua import * +from ida_idp import * +from ida_auto import * +from ida_nalt import * +from ida_funcs import * +from ida_lines import * +from ida_problems import * +from ida_segment import * +from ida_name import * +from ida_netnode import * +from ida_xref import * +from ida_idaapi import * +import ida_frame +import ida_offset +import ida_pro +import idc + +if sys.version_info.major < 3: + range = xrange + +# extract bitfield occupying bits high..low from val (inclusive, start from 0) +def BITS(val, low, high): + return (val>>low)&((1<<(high-low+1))-1) +# extract one bit +def BIT(val, bit): + return (val>>bit) & 1 +# sign extend b low bits in x +# from "Bit Twiddling Hacks" +def SIGNEXT(x, b): + m = 1 << (b - 1) + x = x & ((1 << b) - 1) + return (x ^ m) - m + +# check if operand is register reg +def is_reg(op, reg): + return op.type == o_reg and op.reg == reg + +# check if operand is immediate value val +def is_imm(op, val): + return op.type == o_imm and op.value == val + +# are operands equal? +def same_op(op1, op2): + return op1.type == op2.type and \ + op1.reg == op2.reg and \ + op1.value == op2.value and \ + op1.addr == op2.addr and \ + op1.flags == op2.flags and \ + op1.specval == op2.specval and \ + op1.dtype == op2.dtype + +# is sp delta fixed by the user? +def is_fixed_spd(ea): + return (get_aflags(ea) & AFL_FIXEDSPD) != 0 + +# ---------------------------------------------------------------------- +class ebc_processor_t(processor_t): + # IDP id ( Numbers above 0x8000 are reserved for the third-party modules) + id = PLFM_EBC + + # Processor features + flag = PR_SEGS | PR_DEFSEG32 | PR_USE32 | PRN_HEX | PR_RNAMESOK + + # Number of bits in a byte for code segments (usually 8) + # IDA supports values up to 32 bits (64 for IDA64) + cnbits = 8 + + # Number of bits in a byte for non-code segments (usually 8) + # IDA supports values up to 32 bits (64 for IDA64) + dnbits = 8 + + # short processor names + # Each name should be shorter than 9 characters + psnames = ['ebc'] + + # long processor names + # No restriction on name lengthes. + plnames = ['EFI Byte code'] + + # size of a segment register in bytes + segreg_size = 0 + + # Array of typical code start sequences (optional) + # codestart = ['\x60\x00'] # 60 00 xx xx: MOVqw SP, SP-delta + + # Array of 'return' instruction opcodes (optional) + # retcodes = ['\x04\x00'] # 04 00: RET + + # You should define 2 virtual segment registers for CS and DS. + # Let's call them rVcs and rVds. + + # icode of the first instruction + instruc_start = 0 + + # + # Size of long double (tbyte) for this processor + # (meaningful only if ash.a_tbyte != NULL) + # + tbyte_size = 0 + + # only one assembler is supported + assembler = { + # flag + 'flag' : ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, + + # user defined flags (local only for IDP) + # you may define and use your own bits + 'uflag' : 0, + + # Assembler name (displayed in menus) + 'name': "EFI bytecode assembler", + + # org directive + 'origin': "org", + + # end directive + 'end': "end", + + # comment string (see also cmnt2) + 'cmnt': ";", + + # ASCII string delimiter + 'ascsep': "\"", + + # ASCII char constant delimiter + 'accsep': "'", + + # ASCII special chars (they can't appear in character and ascii constants) + 'esccodes': "\"'", + + # + # Data representation (db,dw,...): + # + # ASCII string directive + 'a_ascii': "db", + + # byte directive + 'a_byte': "db", + + # word directive + 'a_word': "dw", + + # remove if not allowed + 'a_dword': "dd", + + # remove if not allowed + 'a_qword': "dq", + + # remove if not allowed + 'a_oword': "xmmword", + + # float; 4bytes; remove if not allowed + 'a_float': "dd", + + # double; 8bytes; NULL if not allowed + 'a_double': "dq", + + # long double; NULL if not allowed + 'a_tbyte': "dt", + + # array keyword. the following + # sequences may appear: + # #h - header + # #d - size + # #v - value + # #s(b,w,l,q,f,d,o) - size specifiers + # for byte,word, + # dword,qword, + # float,double,oword + 'a_dups': "#d dup(#v)", + + # uninitialized data directive (should include '%s' for the size of data) + 'a_bss': "%s dup ?", + + # 'seg ' prefix (example: push seg seg001) + 'a_seg': "seg", + + # current IP (instruction pointer) symbol in assembler + 'a_curip': "$", + + # "public" name keyword. NULL-gen default, ""-do not generate + 'a_public': "public", + + # "weak" name keyword. NULL-gen default, ""-do not generate + 'a_weak': "weak", + + # "extrn" name keyword + 'a_extrn': "extrn", + + # "comm" (communal variable) + 'a_comdef': "", + + # "align" keyword + 'a_align': "align", + + # Left and right braces used in complex expressions + 'lbrace': "(", + 'rbrace': ")", + + # % mod assembler time operation + 'a_mod': "%", + + # & bit and assembler time operation + 'a_band': "&", + + # | bit or assembler time operation + 'a_bor': "|", + + # ^ bit xor assembler time operation + 'a_xor': "^", + + # ~ bit not assembler time operation + 'a_bnot': "~", + + # << shift left assembler time operation + 'a_shl': "<<", + + # >> shift right assembler time operation + 'a_shr': ">>", + + # size of type (format string) + 'a_sizeof_fmt': "size %s", + } # Assembler + + # ---------------------------------------------------------------------- + # Some internal flags used by the decoder, emulator and output + # operand size or move size; can be in both auxpref and OpN.specval + FL_B = 0x0001 # 8 bits + FL_W = 0x0002 # 16 bits + FL_D = 0x0004 # 32 bits + FL_Q = 0x0008 # 64 bits + + # OpN.specval + FLo_INDIRECT = 0x0010 # This is an indirect access (not immediate value) + FLo_SIGNED = 0x0020 # This is a signed operand + + # insn_t.auxpref flags (NB: only 16 bits!) + FLa_OP1 = 0x0010 # check operand 1 + FLa_32 = 0x0020 # Is 32 + FLa_64 = 0x0040 # Is 64 + FLa_EXTERN = 0x0080 # external call (via thunk) + FLa_ABS = 0x0100 # absolute call + FLa_CS = 0x0200 # Condition flag is set + FLa_NCS = 0x0400 # Condition flag is not set + FLa_CMPMASK = 0xF000 # mask of the CMP[I] comparison + FLa_CMPeq = 0x1000 # compare equal + FLa_CMPlte = 0x2000 # compare signed less than or equal + FLa_CMPgte = 0x3000 # compare signed greater than or equal + FLa_CMPulte = 0x4000 # compare unsigned less than or equal + FLa_CMPugte = 0x5000 # compare unsigned greater than or equal + + IMMDATA_16 = 1 + IMMDATA_32 = 2 + IMMDATA_64 = 3 + + # ---------------------------------------------------------------------- + # Utility functions + # + + # ---------------------------------------------------------------------- + # set comparison kind (eq/lte/gte/ulte/ugte) + def set_cmp(self, insn, no): + insn.auxpref &= ~self.FLa_CMPMASK + insn.auxpref |= [self.FLa_CMPeq, self.FLa_CMPlte, + self.FLa_CMPgte, self.FLa_CMPulte, + self.FLa_CMPugte][no] + + # ---------------------------------------------------------------------- + # get comparison kind (eq/lte/gte/ulte/ugte) + def get_cmp(self, insn): + t = insn.auxpref & self.FLa_CMPMASK + if t: + return { self.FLa_CMPeq: "eq", + self.FLa_CMPlte: "lte", + self.FLa_CMPgte: "gte", + self.FLa_CMPulte: "ulte", + self.FLa_CMPugte: "ugte" } [t] + + # ---------------------------------------------------------------------- + def get_data_width_fl(self, sz): + """Returns a flag given the data width number""" + if sz == 0: return self.FL_B + elif sz == self.IMMDATA_16: return self.FL_W + elif sz == self.IMMDATA_32: return self.FL_D + elif sz == self.IMMDATA_64: return self.FL_Q + + # ---------------------------------------------------------------------- + def next_data_value(self, insn, sz): + """Returns a value depending on the data widh number""" + if sz == 0: return insn.get_next_byte() + elif sz == self.IMMDATA_16: return insn.get_next_word() + elif sz == self.IMMDATA_32: return insn.get_next_dword() + elif sz == self.IMMDATA_64: return insn.get_next_qword() + else: raise Exception("Invalid width!") + + # ---------------------------------------------------------------------- + def get_data_dt(self, sz): + """Returns a dt_xxx on the data widh number""" + if sz == 0: return dt_byte + elif sz == self.IMMDATA_16: return dt_word + elif sz == self.IMMDATA_32: return dt_dword + elif sz == self.IMMDATA_64: return dt_qword + else: raise Exception("Invalid width!") + + # ---------------------------------------------------------------------- + def native_dt(self): + return dt_qword if self.PTRSZ==8 else dt_dword + + # ---------------------------------------------------------------------- + def get_sz_to_bits(self, sz): + """Returns size in bits of the data widh number""" + if sz == self.IMMDATA_16: return 16 + elif sz == self.IMMDATA_32: return 32 + elif sz == self.IMMDATA_64: return 64 + else: return 8 + + # ---------------------------------------------------------------------- + def dt_to_bits(self, dt): + """Returns the size in bits given a dt_xxx""" + if dt == dt_byte: return 8 + elif dt == dt_word: return 16 + elif dt == dt_dword: return 32 + elif dt == dt_qword: return 64 + + # ---------------------------------------------------------------------- + def dt_to_width(self, dt): + """Returns OOFW_xxx flag given a dt_xxx""" + if dt == dt_byte: return OOFW_8 + elif dt == dt_word: return OOFW_16 + elif dt == dt_dword: return OOFW_32 + elif dt == dt_qword: return OOFW_64 + + # ---------------------------------------------------------------------- + def fl_to_str(self, fl): + """Given a flag, it returns a string. (used during output)""" + if fl & self.FL_B != 0: return "b" + elif fl & self.FL_W != 0: return "w" + elif fl & self.FL_D != 0: return "d" + elif fl & self.FL_Q != 0: return "q" + + # ---------------------------------------------------------------------- + def set_ptr_size(self): + """ + Functions checks the database / PE header netnode and sees if the input file + is a PE+ or not. If so, then pointer size is set to 8 bytes. + """ + n = netnode("$ PE header") + s = n.valobj() + if not s: + return + # Extract magic field + t = struct.unpack("<H", s[0x18:0x18+2])[0] + if t == 0x20B: + self.PTRSZ = 8 + + # ---------------------------------------------------------------------- + # Decodes an index and returns all its components in a dictionary + # Refer to "Index Encoding" section + def decode_index(self, index, sz): + N = sz - 1 + s = -1 if BIT(index, N) else 1 + w = BITS(index, N-3, N-1) + t = sz // 8 + A = w * t # width of the natural units field + n = BITS(index, 0, A-1) if A >= 1 else 0 # natural units (n) + c = BITS(index, A, N-4) if N-4 >= A else 0 # constant units (c) + o = (c + (n * self.PTRSZ)) # offset w/o sign + so = o * s # signed final offset + return so + + # ---------------------------------------------------------------------- + def op_reg(self, op, reg): + op.type = o_reg + op.reg = reg + + # ---------------------------------------------------------------------- + def op_disp(self, op, reg, d, direct): + op.type = o_displ + op.phrase = reg + op.addr = d if d else 0 + if not direct: + op.specval |= self.FLo_INDIRECT + else: + op.specval &= ~self.FLo_INDIRECT + op.specval |= self.FLo_SIGNED + + # ---------------------------------------------------------------------- + def decode_index_or_data(self, insn, sz, immed): + bs = self.get_sz_to_bits(sz) + d = self.next_data_value(insn, sz) + if not immed: + d = self.decode_index(d, bs) + else: + d = SIGNEXT(d, bs) + return d + + # ---------------------------------------------------------------------- + def fill_op(self, insn, op, reg, direct, has_imm, immsz, dt = None, index_only = False): + if direct and not has_imm: + self.op_reg(op, reg) + else: + d = self.decode_index_or_data(insn, immsz, direct and not index_only) if has_imm else None + self.op_disp(op, reg, d, direct) + if dt: + insn.Op1.dtype = dt + + # ---------------------------------------------------------------------- + def fill_op1(self, insn, opbyte, has_imm, immsz, dt = None, index_only = False): + op1_direct = (opbyte & 0x08) == 0 + r1 = (opbyte & 0x07) + self.fill_op(insn, insn.Op1, r1, op1_direct, has_imm, immsz, dt, index_only) + + # ---------------------------------------------------------------------- + def fill_op2(self, insn, opbyte, has_imm, immsz, dt = None, index_only = False): + op2_direct = (opbyte & 0x80) == 0 + r2 = (opbyte & 0x70) >> 4 + self.fill_op(insn, insn.Op2, r2, op2_direct, has_imm, immsz, dt, index_only) + + # ---------------------------------------------------------------------- + # Instruction decoding + # + + # ---------------------------------------------------------------------- + def decode_RET(self, insn, opbyte): + # No operands + insn.Op1.type = o_void + # Consume the next byte, and it should be zero + insn.get_next_byte() + return True + + # ---------------------------------------------------------------------- + def decode_STORESP(self, insn, opbyte): + # opbyte (byte0) has nothing meaningful (but the opcode itself) + + # get next byte + opbyte = insn.get_next_byte() + + vm_reg = (opbyte & 0x70) >> 4 + gp_reg = (opbyte & 0x07) + + insn.Op1.type = insn.Op2.type = o_reg + insn.Op1.dtype = insn.Op2.dtype = dt_qword + + insn.Op1.reg = gp_reg + insn.Op2.reg = self.ireg_FLAGS + vm_reg + + return True + + # ---------------------------------------------------------------------- + def decode_LOADSP(self, insn, opbyte): + # opbyte (byte0) has nothing meaningful (but the opcode itself) + + # get next byte + opbyte = insn.get_next_byte() + + gp_reg = (opbyte & 0x70) >> 4 + vm_reg = (opbyte & 0x07) + + insn.Op1.type = insn.Op2.type = o_reg + insn.Op1.dtype = insn.Op2.dtype = dt_qword + + insn.Op1.reg = self.ireg_FLAGS + vm_reg + insn.Op2.reg = gp_reg + + return True + + # ---------------------------------------------------------------------- + def decode_BREAK(self, insn, opbyte): + """ + stx=<BREAK [break code]> + txt=<The BREAK instruction is used to perform special processing by the VM.> + """ + insn.Op1.type = o_imm + insn.Op1.dtype = dt_byte + insn.Op1.value = insn.get_next_byte() + return True + + # ---------------------------------------------------------------------- + def cmt_BREAK(self, insn): + s = "Special processing by VM" + if insn.Op1.value == 0: + s += ": runaway program break (null/bad opcode)" + elif insn.Op1.value == 1: + s += ": get virtual machine version in R7" + elif insn.Op1.value == 3: + s += ": debug breakpoint" + elif insn.Op1.value == 4: + s += ": system call (ignored)" + elif insn.Op1.value == 5: + s += ": create thunk (thunk pointer in R7)" + elif insn.Op1.value == 6: + s += ": set compiler version in R7" + else: + s += ": unknown break code" + return s + + # ---------------------------------------------------------------------- + def decode_PUSH(self, insn, opbyte): + """ + PUSH[32|64] {@}R1 {Index16|Immed16} + PUSHn {@}R1 {Index16|Immed16} + """ + have_data = (opbyte & 0x80) != 0 + is_n = (opbyte & ~0xC0) in [0x35, 0x36] # PUSHn, POPn + if is_n: + dt = self.native_dt() + insn.auxpref = 0 + else: + op_32 = (opbyte & 0x40) == 0 + dt = dt_dword if op_32 else dt_qword + insn.auxpref = self.FLa_32 if op_32 else self.FLa_64 + + opbyte = insn.get_next_byte() + self.fill_op1(insn, opbyte, have_data, self.IMMDATA_16, dt) + return True + + # ---------------------------------------------------------------------- + def decode_JMP(self, insn, opbyte): + """ + stx=<JMP32{cs|cc} {@}R1 {Immed32|Index32}> + stx=<JMP64{cs|cc} Immed64> + """ + have_data = (opbyte & 0x80) != 0 + jmp_32 = (opbyte & 0x40) == 0 + + opbyte = insn.get_next_byte() + conditional = (opbyte & 0x80) != 0 + cs = (opbyte & 0x40) != 0 + abs_jmp = (opbyte & 0x10) == 0 + op1_direct = (opbyte & 0x08) == 0 + r1 = (opbyte & 0x07) + + if jmp_32: + # Indirect and no data specified? + if not op1_direct and not have_data: + return False + + self.fill_op1(insn, opbyte, have_data, self.IMMDATA_32, dt_dword) + if insn.Op1.reg == 0: + if op1_direct: + insn.Op1.type = o_near + else: + insn.Op1.type = o_mem + else: + if not have_data: + return False + insn.Op1.type = o_near + insn.Op1.dtype = dt_qword + insn.Op1.addr = insn.get_next_qword() + + if not abs_jmp: + if jmp_32: + val = SIGNEXT(insn.Op1.addr, 32) + else: + val = insn.Op1.addr + insn.Op1.addr = val + insn.ea + insn.size + + fl = self.FLa_32 if jmp_32 else self.FLa_64 + if conditional: + fl |= self.FLa_CS if cs else self.FLa_NCS + insn.auxpref = fl + + return True + + # ---------------------------------------------------------------------- + def cmt_JMP(self, insn): + s = "Jump to address" + if insn.auxpref & self.FLa_CS: + s += " if condition is true" + elif insn.auxpref & self.FLa_NCS: + s += " if condition is false" + else: + s += " unconditionally" + return s + + # ---------------------------------------------------------------------- + def decode_JMP8(self, insn, opbyte): + """ + stx=<JMP8{cs|cc} Immed8> + """ + conditional = (opbyte & 0x80) != 0 + cs = (opbyte & 0x40) != 0 + insn.Op1.type = o_near + insn.Op1.dtype = dt_byte + addr = insn.get_next_byte() + insn.Op1.addr = (SIGNEXT(addr, 8) * 2) + insn.size + insn.ea + + if conditional: + insn.auxpref = self.FLa_CS if cs else self.FLa_NCS + + return True + + # ---------------------------------------------------------------------- + def decode_MOVI(self, insn, opbyte): + """ + MOVI[b|w|d|q][w|d|q] {@}R1 {Index16}, Immed16|32|64 + MOVIn[w|d|q] {@}R1 {Index16}, Index16|32|64 + + First character specifies the width of the move and is taken from opcode + Second character specifies the immediate data size and is taken from the opbyte + """ + imm_sz = (opbyte & 0xC0) >> 6 + opcode = (opbyte & ~0xC0) + is_MOVIn = opcode == 0x38 + + # Reserved and should not be 0 + if imm_sz == 0: + return False + + # take byte 1 + opbyte = insn.get_next_byte() + + # Bit 7 is reserved and should be 0 + if opbyte & 0x80 != 0: + return False + + have_idx = (opbyte & 0x40) != 0 + move_sz = (opbyte & 0x30) >> 4 + direct = (opbyte & 0x08) == 0 + r1 = (opbyte & 0x07) + + # Cannot have an index with a direct register + if have_idx and direct: + return False + + dt = self.native_dt() if is_MOVIn else self.get_data_dt(move_sz) + self.fill_op1(insn, opbyte, have_idx, self.IMMDATA_16, dt) + + insn.Op2.type = o_imm + insn.Op2.dtype = self.get_data_dt(imm_sz) + v = self.decode_index_or_data(insn, imm_sz, not is_MOVIn) + if imm_sz == self.IMMDATA_64: + insn.Op2.value = SIGNEXT(v, 32) + insn.Op2.addr = int(v >> 32) + else: + insn.Op2.value = v + # save imm size and signal that op1 is defined in first operand + insn.auxpref = self.get_data_width_fl(imm_sz) + if not is_MOVIn: + insn.auxpref |= self.FLa_OP1 + insn.Op1.specval |= self.get_data_width_fl(move_sz) + + return True + + # ---------------------------------------------------------------------- + def decode_MOVREL(self, insn, opbyte): + """ + MOVREL[w|d|q] {@}R1 {Index16}, Immed16|32|64 + """ + + imm_sz = (opbyte & 0xC0) >> 6 + + # Reserved and should not be 0 + if imm_sz == 0: + return False + + # take byte 1 + opbyte = insn.get_next_byte() + + # Bits 7 is reserved and should be 0 + # Bits 4 and 5 are supposed to be 0 too, except in real programs they aren't! + if (opbyte & 0x80) != 0: + return False + + have_idx = (opbyte & 0x40) != 0 + direct = (opbyte & 0x08) == 0 + r1 = (opbyte & 0x07) + + # Cannot have an index with a direct register + if have_idx and direct: + return False + + self.fill_op1(insn, opbyte, have_idx, self.IMMDATA_16, self.get_data_dt(imm_sz)) + insn.Op1.specval = self.get_data_width_fl(imm_sz) + insn.Op2.type = o_mem + insn.Op2.dtype = self.get_data_dt(imm_sz) + insn.Op2.addr = self.next_data_value(insn, imm_sz) + insn.size + insn.ea + + # save imm size + insn.auxpref = self.get_data_width_fl(imm_sz) + + return True + + # ---------------------------------------------------------------------- + def decode_MOV(self, insn, opbyte): + """ + MOV[b|w|d|q]{w|d} {@}R1 {Index16|32}, {@}R2 {Index16|32} + MOVn{w|d} {@}R1 {Index16|32}, {@}R2 {Index16|32} + MOVqq {@}R1 {Index64}, {@}R2 {Index64} + """ + have_idx1 = (opbyte & 0x80) != 0 + have_idx2 = (opbyte & 0x40) != 0 + opcode = (opbyte & ~0xC0) + + # opcode: data move size, index size + m = { + 0x1D: (dt_byte, self.IMMDATA_16), #MOVbw + 0x1E: (dt_word, self.IMMDATA_16), #MOVww + 0x1F: (dt_dword, self.IMMDATA_16), #MOVdw + 0x20: (dt_qword, self.IMMDATA_16), #MOVqw + 0x21: (dt_byte, self.IMMDATA_32), #MOVbd + 0x22: (dt_word, self.IMMDATA_32), #MOVwd + 0x23: (dt_dword, self.IMMDATA_32), #MOVdd + 0x24: (dt_qword, self.IMMDATA_32), #MOVqd + 0x28: (dt_qword, self.IMMDATA_64), #MOVqq + 0x32: (self.native_dt(), self.IMMDATA_16), #MOVnw + 0x33: (self.native_dt(), self.IMMDATA_32), #MOVnd + } + + dt, idx_sz = m[opcode] + # get byte1 + opbyte = insn.get_next_byte() + self.fill_op1(insn, opbyte, have_idx1, idx_sz, dt, True) + self.fill_op2(insn, opbyte, have_idx2, idx_sz, dt, True) + + return True + + # ---------------------------------------------------------------------- + def decode_CMP(self, insn, opbyte): + """ + CMP[32|64][eq|lte|gte|ulte|ugte] R1, {@}R2 {Index16|Immed16} + """ + have_data = (opbyte & 0x80) != 0 + cmp_32 = (opbyte & 0x40) == 0 + opcode = (opbyte & ~0xC0) + + opbyte = insn.get_next_byte() + + if opbyte & 0x08: # operand 1 indirect is not supported + return False + + r1 = (opbyte & 0x07) + dt = dt_dword if cmp_32 else dt_qword + insn.Op1.type = o_reg + insn.Op1.reg = r1 + insn.Op1.dtype = dt + + self.fill_op2(insn, opbyte, have_data, self.IMMDATA_16, dt) + + insn.auxpref = self.FLa_32 if cmp_32 else self.FLa_64 + self.set_cmp(insn, opcode - 0x05) + return True + + # ---------------------------------------------------------------------- + def cmt_CMP(self, insn): + s = "Compare if " + t = insn.auxpref & self.FLa_CMPMASK + s += { self.FLa_CMPeq: "equal", + self.FLa_CMPlte: "less than or equal (signed)", + self.FLa_CMPgte: "greater than or equal (signed)", + self.FLa_CMPulte: "less than or equal (unsigned)", + self.FLa_CMPugte: "greater than or equal (unsigned)" } [t] + return s + + # ---------------------------------------------------------------------- + def decode_CMPI(self, insn, opbyte): + """ + CMPI[32|64]{w|d}[eq|lte|gte|ulte|ugte] {@}R1 {Index16}, Immed16|Immed32 + """ + imm_sz = self.IMMDATA_16 if (opbyte & 0x80) == 0 else self.IMMDATA_32 + cmp_32 = (opbyte & 0x40) == 0 + opcode = (opbyte & ~0xC0) + + opbyte = insn.get_next_byte() + have_idx = (opbyte & 0x10) != 0 + dt = dt_dword if cmp_32 else dt_qword + self.fill_op1(insn, opbyte, have_idx, self.IMMDATA_16, dt) + insn.Op2.type = o_imm + insn.Op2.value = self.next_data_value(insn, imm_sz) + insn.Op2.dtype = dt + + insn.auxpref = (self.FLa_32 if cmp_32 else self.FLa_64) | self.get_data_width_fl(imm_sz) + self.set_cmp(insn, opcode - 0x2D) + return True + + # ---------------------------------------------------------------------- + def decode_CALL(self, insn, opbyte): + """ + stx=<CALL32{EX}{a} {@}R1 {Immed32|Index32}> + stx=<CALL64{EX}{a} Immed64> + """ + have_data = (opbyte & 0x80) != 0 + call_32 = (opbyte & 0x40) == 0 + + opbyte = insn.get_next_byte() + + # Call to EBC or Native code + ebc_call = (opbyte & 0x20) == 0 + # Absolute or Relative address + abs_addr = (opbyte & 0x10) == 0 + # Op1 direct? + op1_direct = (opbyte & 0x08) == 0 + r1 = (opbyte & 0x07) + + if call_32: + self.fill_op1(insn, opbyte, have_data, self.IMMDATA_32, dt_dword) + if have_data and insn.Op1.reg == 0: + insn.Op1.type = o_near + if not abs_addr: + val = SIGNEXT(insn.Op1.addr & 0xFFFFFFFF, 32) + insn.Op1.addr = val + insn.ea + insn.size + # 64-bit + else: + insn.Op1.type = o_near + insn.Op1.dtype = dt_qword + insn.Op1.addr = self.next_data_value(insn, self.IMMDATA_64) # Get 64-bit value + if not abs_addr: + insn.Op1.addr += insn.ea + insn.size + + fl = self.FLa_EXTERN if not ebc_call else 0 + fl |= self.FLa_32 if call_32 else self.FLa_64 + if abs_addr: + fl |= self.FLa_ABS + insn.auxpref = fl + + return True + + # ---------------------------------------------------------------------- + def cmt_CALL(self, insn): + if insn.auxpref & self.FLa_EXTERN: + s = "Call an external subroutine (via thunk)" + else: + s = "Call a subroutine" + if insn.auxpref & self.FLa_ABS: + s += " [absolute addressing]" + return s + + # ---------------------------------------------------------------------- + def decode_BINOP_FORM1(self, insn, opbyte): + """ + op[32|64] {@}R1, {@}R2 {Index16|Immed16} + """ + have_data = (opbyte & 0x80) != 0 + op_32 = (opbyte & 0x40) == 0 + opcode = (opbyte & ~0xC0) + + opbyte = insn.get_next_byte() + + op2_direct = (opbyte & 0x80) == 0 + op1_direct = (opbyte & 0x08) == 0 + r1 = (opbyte & 0x07) + r2 = (opbyte & 0x70) >> 4 + dt = dt_dword if op_32 else dt_qword + + self.fill_op1(insn, opbyte, False, 0, dt) + self.fill_op2(insn, opbyte, have_data, self.IMMDATA_16, dt) + insn.auxpref = self.FLa_32 if op_32 else self.FLa_64 + + return True + + # ---------------------------------------------------------------------- + def decode_MOVSN(self, insn, opbyte): + """ + MOVsn{w} {@}R1 {Index16}, {@}R2 {Index16|Immed16} + MOVsn{d} {@}R1 {Index32}, {@}R2 {Index32|Immed32} + """ + have_idx1 = (opbyte & 0x80) != 0 + have_idx2 = (opbyte & 0x40) != 0 + opcode = (opbyte & ~0xC0) + + if opcode == 0x25: + idx_sz = self.IMMDATA_16 + elif opcode == 0x26: + idx_sz = self.IMMDATA_32 + else: + return False + + opbyte = insn.get_next_byte() + self.fill_op1(insn, opbyte, have_idx1, idx_sz, self.native_dt()) + self.fill_op2(insn, opbyte, have_idx2, idx_sz, self.native_dt()) + + return True + + # ---------------------------------------------------------------------- + # Processor module callbacks + # + # ---------------------------------------------------------------------- + def ev_get_frame_retsize(self, frsize, pfn): + ida_pro.int_pointer.frompointer(frsize).assign(16) + return 1 + + # ---------------------------------------------------------------------- + def ev_get_autocmt(self, insn): + if 'cmt' in self.instruc[insn.itype]: + return self.instruc[insn.itype]['cmt'](insn) + + # ---------------------------------------------------------------------- + def ev_can_have_type(self, op): + return 1 if op.type in [o_imm, o_displ, o_mem] else 0 + + # ---------------------------------------------------------------------- + def ev_is_align_insn(self, ea): + return 2 if get_word(ea) == 0 else 0 + + # ---------------------------------------------------------------------- + def ev_newfile(self, filename): + self.set_ptr_size() + return 0 + + # ---------------------------------------------------------------------- + def ev_oldfile(self, filename): + self.set_ptr_size() + return 0 + + # ---------------------------------------------------------------------- + def ev_out_header(self, ctx): + ctx.out_line("; natural unit size: %d bits" % (self.PTRSZ*8)) + ctx.flush_outbuf(0) + return 1 + + # ---------------------------------------------------------------------- + def ev_may_be_func(self, insn, state): + if is_reg(insn.Op1, self.ireg_SP) and insn.Op2.type == o_displ and\ + insn.Op2.phrase == self.ireg_SP and (insn.Op2.specval & self.FLo_INDIRECT) == 0: + # mov SP, SP+delta + if SIGNEXT(insn.Op2.addr, self.PTRSZ*8) < 0: + return 100 + else: + return 0 + return 10 + + # ---------------------------------------------------------------------- + def check_thunk(self, addr): + """ + Check for EBC thunk at addr + dd fnaddr - (addr+4), 0, 0, 0 + """ + delta = get_dword(addr) + fnaddr = (delta + addr + 4) & 0xFFFFFFFF + if is_off(get_flags(addr), 0): + # already an offset + if ida_offset.get_offbase(addr, 0) == addr + 4: + return fnaddr + else: + return None + # should be followed by three zeroes + if delta == 0 or get_dword(addr+4) != 0 or\ + get_dword(addr+8) != 0 or get_dword(addr+12) != 0: + return None + if segtype(fnaddr) == SEG_CODE: + # looks good, create the offset + idc.create_dword(addr) + if ida_offset.op_offset(addr, 0, REF_OFF32|REFINFO_NOBASE, BADADDR, addr + 4): + return fnaddr + else: + return None + + # ---------------------------------------------------------------------- + def handle_operand(self, insn, op, isRead): + F = get_flags(insn.ea) + is_offs = is_off(F, op.n) + dref_flag = dr_R if isRead else dr_W + def_arg = is_defarg(F, op.n) + optype = op.type + + # create code xrefs + if optype == o_imm: + if is_offs: + insn.add_off_drefs(op, dr_O, 0) + # create data xrefs + elif optype == o_displ: + # reg + delta + if is_offs: + insn.add_off_drefs(op, dref_flag, OOF_ADDR) + elif may_create_stkvars() and not def_arg and op.reg == self.ireg_SP: + # ignore prolog/epilog + # MOVqw SP, SP+delta + if is_reg(insn.Op1, self.ireg_SP): + pass + else: + pfn = get_func(insn.ea) + # [SP+var_x] (indirect) + # SP+var_x (direct) + flag = STKVAR_VALID_SIZE if (op.specval & self.FLo_INDIRECT) else 0 + if pfn and insn.create_stkvar(op, op.addr, flag): + op_stkvar(insn.ea, op.n) + elif optype == o_mem: + if insn.itype == self.itype_MOVREL: + dref_flag = dr_O + self.check_thunk(op.addr) + else: + insn.create_op_data(op.addr, op) + insn.add_dref(op.addr, op.offb, dref_flag) + elif optype == o_near: + itype = insn.itype + if itype == self.itype_CALL: + fl = fl_CN + else: + fl = fl_JN + insn.add_cref(op.addr, op.offb, fl) + + # ---------------------------------------------------------------------- + def add_stkpnt(self, insn, pfn, v): + if pfn: + end = insn.ea + insn.size + if not is_fixed_spd(end): + ida_frame.add_auto_stkpnt(pfn, end, v) + + # ---------------------------------------------------------------------- + def trace_sp(self, insn): + """ + Trace the value of the SP and create an SP change point if the current + instruction modifies the SP. + """ + pfn = get_func(insn.ea) + if not pfn: + return + if is_reg(insn.Op1, self.ireg_SP) and insn.itype in [self.itype_MOVbw, self.itype_MOVww, + self.itype_MOVdw, self.itype_MOVqw, self.itype_MOVbd, + self.itype_MOVwd, self.itype_MOVdd, self.itype_MOVqd, + self.itype_MOVsnw, self.itype_MOVsnd, self.itype_MOVqq]: + # MOVqw SP, SP-0x30 + # MOVqw SP, SP+0x30 + if insn.Op2.type == o_displ and insn.Op2.phrase == self.ireg_SP and (insn.Op2.specval & self.FLo_INDIRECT) == 0: + spofs = SIGNEXT(insn.Op2.addr, self.PTRSZ*8) + self.add_stkpnt(insn, pfn, spofs) + elif insn.itype in [self.itype_PUSH, self.itype_PUSHn]: + spofs = self.dt_to_bits(insn.Op1.dtype) // 8 + self.add_stkpnt(insn, pfn, -spofs) + elif insn.itype in [self.itype_POP, self.itype_POPn]: + spofs = self.dt_to_bits(insn.Op1.dtype) // 8 + self.add_stkpnt(insn, pfn, spofs) + + + # ---------------------------------------------------------------------- + def ev_emu_insn(self, insn): + aux = self.get_auxpref(insn) + Feature = insn.get_canon_feature() + + if Feature & CF_USE1: + self.handle_operand(insn, insn.Op1, 1) + if Feature & CF_CHG1: + self.handle_operand(insn, insn.Op1, 0) + if Feature & CF_USE2: + self.handle_operand(insn, insn.Op2, 1) + if Feature & CF_CHG2: + self.handle_operand(insn, insn.Op2, 0) + if Feature & CF_JUMP: + remember_problem(PR_JUMP, insn.ea) + + # is it an unconditional jump? + uncond_jmp = insn.itype in [self.itype_JMP8, self.itype_JMP] and (aux & (self.FLa_NCS|self.FLa_CS)) == 0 + + # add flow + flow = (Feature & CF_STOP == 0) and not uncond_jmp + if flow: + add_cref(insn.ea, insn.ea + insn.size, fl_F) + + # trace the stack pointer if: + # - it is the second analysis pass + # - the stack pointer tracing is allowed + if may_trace_sp(): + if flow: + self.trace_sp(insn) # trace modification of SP register + else: + idc.recalc_spd(insn.ea) # recalculate SP register for the next insn + + return True + + # ---------------------------------------------------------------------- + def ev_out_operand(self, ctx, op): + """ + Generate text representation of an instructon operand. + This function shouldn't change the database, flags or anything else. + All these actions should be performed only by u_emu() function. + The output text is placed in the output buffer initialized with init_output_buffer() + This function uses out_...() functions from ua.hpp to generate the operand text + Returns: 1-ok, 0-operand is hidden. + """ + optype = op.type + fl = op.specval + signed = OOF_SIGNED if fl & self.FLo_SIGNED != 0 else 0 + def_arg = is_defarg(get_flags(ctx.insn.ea), op.n) + + if optype == o_reg: + ctx.out_register(self.reg_names[op.reg]) + + elif optype == o_imm: + # for immediate loads, use the transfer width (type of first operand) + if op.n == 1: + width = self.dt_to_width(ctx.insn.Op1.dtype) + else: + width = OOFW_32 if self.PTRSZ == 4 else OOFW_64 + ctx.out_value(op, OOFW_IMM | signed | width) + + elif optype in [o_near, o_mem]: + r = ctx.out_name_expr(op, op.addr, BADADDR) + if not r: + ctx.out_tagon(COLOR_ERROR) + ctx.out_btoa(op.addr, 16) + ctx.out_tagoff(COLOR_ERROR) + remember_problem(PR_NONAME, ctx.insn.ea) + + elif optype == o_displ: + indirect = fl & self.FLo_INDIRECT != 0 + if indirect: + ctx.out_symbol('[') + + ctx.out_register(self.reg_names[op.reg]) + + if op.addr != 0 or def_arg: + ctx.out_value(op, OOF_ADDR | (OOFW_32 if self.PTRSZ == 4 else OOFW_64) | signed | OOFS_NEEDSIGN) + + if indirect: + ctx.out_symbol(']') + else: + return False + + return True + + # ---------------------------------------------------------------------- + # Generate the instruction mnemonics + def ev_out_mnem(self, ctx): + # Init output buffer + + postfix = "" + + # First display size of first operand if it exists + if ctx.insn.auxpref & self.FLa_OP1 != 0: + postfix += self.fl_to_str(ctx.insn.Op1.specval) + + # Display opertion size + if ctx.insn.auxpref & self.FLa_32: + postfix += "32" + elif ctx.insn.auxpref & self.FLa_64: + postfix += "64" + + # Display if local or extern CALL + if ctx.insn.auxpref & self.FLa_EXTERN: + postfix += "EX" + + # Display if absolute call + if ctx.insn.auxpref & self.FLa_ABS: + postfix += "a" + + # Display size of instruction + if ctx.insn.auxpref & (self.FL_B | self.FL_W | self.FL_D | self.FL_Q) != 0: + postfix += self.fl_to_str(ctx.insn.auxpref) + + # Display JMP condition + if ctx.insn.auxpref & self.FLa_CS: + postfix += "cs" + elif ctx.insn.auxpref & self.FLa_NCS: + postfix += "cc" + + # Display CMP condition + if ctx.insn.auxpref & self.FLa_CMPMASK: + postfix += self.get_cmp(ctx.insn) + + ctx.out_mnem(12, postfix) + return 1 + + # ---------------------------------------------------------------------- + # Generate text representation of an instruction in 'ctx.insn' structure. + # This function shouldn't change the database, flags or anything else. + # All these actions should be performed only by u_emu() function. + def ev_out_insn(self, ctx): + + ctx.out_mnemonic() + + ctx.out_one_operand(0) + + for i in range(1, 3): + op = ctx.insn[i] + + if op.type == o_void: + break + + ctx.out_symbol(',') + ctx.out_char(' ') + ctx.out_one_operand(i) + + if ctx.insn.itype == self.itype_MOVREL: + fnaddr = self.check_thunk(ctx.insn.Op2.addr) + if fnaddr != None: + nm = get_ea_name(fnaddr, GN_VISIBLE) + if nm: + ctx.out_line("; Thunk to " + nm, COLOR_AUTOCMT) + + ctx.set_gen_cmt() + ctx.flush_outbuf() + return True + + # ---------------------------------------------------------------------- + def ev_ana_insn(self, insn): + """ + Decodes an instruction into insn + """ + # take opcode byte + b = insn.get_next_byte() + + # the 6bit opcode + opcode = b & 0x3F + + # opcode supported? + try: + ins = self.itable[opcode] + # set default itype + insn.itype = getattr(self, 'itype_' + ins.name) + except: + return 0 + # call the decoder + return True if ins.d(insn, b) else False + + # ---------------------------------------------------------------------- + def init_instructions(self): + class idef: + """ + Internal class that describes an instruction by: + - instruction name + - instruction decoding routine + - canonical flags used by IDA + """ + def __init__(self, name, cf, d, cmt = None): + self.name = name + self.cf = cf + self.d = d + self.cmt = cmt + + # + # Instructions table (w/ pointer to decoder) + # + self.itable = { + 0x00: idef(name='BREAK', d=self.decode_BREAK, cf = CF_USE1, cmt = self.cmt_BREAK), + + 0x01: idef(name='JMP', d=self.decode_JMP, cf = CF_USE1 | CF_JUMP, cmt = self.cmt_JMP), + 0x02: idef(name='JMP8', d=self.decode_JMP8, cf = CF_USE1 | CF_JUMP, cmt = self.cmt_JMP), + + 0x03: idef(name='CALL', d=self.decode_CALL, cf = CF_USE1 | CF_CALL, cmt = self.cmt_CALL), + 0x04: idef(name='RET', d=self.decode_RET, cf = CF_STOP, cmt = lambda insn: "Return from subroutine" ), + 0x05: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x06: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x07: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x08: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x09: idef(name='CMP', d=self.decode_CMP, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + + 0x0A: idef(name='NOT', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 = ~Op2" ), + 0x0B: idef(name='NEG', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 = -Op2" ), + 0x0C: idef(name='ADD', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 += Op2" ), + 0x0D: idef(name='SUB', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 -= Op2" ), + 0x0E: idef(name='MUL', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 *= Op2 (signed multiply)" ), + 0x0F: idef(name='MULU', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 *= Op2 (unsigned multiply)" ), + 0x10: idef(name='DIV', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 /= Op2 (signed division)" ), + 0x11: idef(name='DIVU', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 /= Op2 (unsigned division)" ), + 0x12: idef(name='MOD', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 %= Op2 (signed modulo)" ), + 0x13: idef(name='MODU', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 %= Op2 (unsigned modulo)" ), + 0x14: idef(name='AND', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 &= Op2" ), + 0x15: idef(name='OR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 |= Op2" ), + 0x16: idef(name='XOR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Op1 ^= Op2" ), + 0x17: idef(name='SHL', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1 | CF_SHFT, cmt = lambda insn: "Op1 <<= Op2" ), + 0x18: idef(name='SHR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1 | CF_SHFT, cmt = lambda insn: "Op1 >>= Op2 (unsigned shift)" ), + 0x19: idef(name='ASHR', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1 | CF_SHFT, cmt = lambda insn: "Op1 >>= Op2 (signed shift)" ), + + 0x1A: idef(name='EXTNDB', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Sign-extend a byte value" ), + 0x1B: idef(name='EXTNDW', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Sign-extend a word value" ), + 0x1C: idef(name='EXTNDD', d=self.decode_BINOP_FORM1, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Sign-extend a dword value" ), + + 0x1D: idef(name='MOVbw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move byte" ), + 0x1E: idef(name='MOVww', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move word" ), + 0x1F: idef(name='MOVdw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move dword" ), + 0x20: idef(name='MOVqw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move qword" ), + 0x21: idef(name='MOVbd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move byte" ), + 0x22: idef(name='MOVwd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move word" ), + 0x23: idef(name='MOVdd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move dword" ), + 0x24: idef(name='MOVqd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move qword" ), + + 0x25: idef(name='MOVsnw', d=self.decode_MOVSN, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move signed natural value"), + 0x26: idef(name='MOVsnd', d=self.decode_MOVSN, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move signed natural value"), + + # 0x27: reserved + + 0x28: idef(name='MOVqq', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move qword" ), + + 0x29: idef(name='LOADSP', d=self.decode_LOADSP, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Load a VM dedicated register from a general-purpose register"), + 0x2A: idef(name='STORESP', d=self.decode_STORESP, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Store a VM dedicated register into a general-purpose register"), + + # PUSH/POP + 0x2B: idef(name='PUSH', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Push value on the stack" ), + 0x2C: idef(name='POP', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Pop value from the stack" ), + + # CMPI + 0x2D: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x2E: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x2F: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x30: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + 0x31: idef(name='CMPI', d=self.decode_CMPI, cf = CF_USE1 | CF_USE2, cmt = self.cmt_CMP), + + 0x32: idef(name='MOVnw', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move unsigned natural value"), + 0x33: idef(name='MOVnd', d=self.decode_MOV, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move unsigned natural value"), + + # 0x34: reserved + + # PUSHn/POPn + 0x35: idef(name='PUSHn', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Push natural value on the stack" ), + 0x36: idef(name='POPn', d=self.decode_PUSH, cf = CF_USE1, cmt = lambda insn: "Pop natural value from the stack" ), + + 0x37: idef(name='MOVI', d=self.decode_MOVI, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move immediate value"), + 0x38: idef(name='MOVIn', d=self.decode_MOVI, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Move immediate value"), + + 0x39: idef(name='MOVREL', d=self.decode_MOVREL, cf = CF_USE1 | CF_USE2 | CF_CHG1, cmt = lambda insn: "Load IP-relative address") + # 0x3A: reserved + # 0x3B: reserved + # 0x3C: reserved + # 0x3D: reserved + # 0x3E: reserved + # 0x3F: reserved + } + + # Now create an instruction table compatible with IDA processor module requirements + Instructions = [] + i = 0 + for x in self.itable.values(): + d = dict(name=x.name, feature=x.cf) + if x.cmt != None: + d['cmt'] = x.cmt + Instructions.append(d) + setattr(self, 'itype_' + x.name, i) + i += 1 + + # icode of the last instruction + 1 + self.instruc_end = len(Instructions) + + # Array of instructions + self.instruc = Instructions + + # Icode of return instruction. It is ok to give any of possible return + # instructions + self.icode_return = self.itype_RET + + # ---------------------------------------------------------------------- + def init_registers(self): + """This function parses the register table and creates corresponding ireg_XXX constants""" + + # Registers definition + self.reg_names = [ + # General purpose registers + "SP", # aka R0 + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + # VM registers + "FLAGS", # 0 + "IP", # 1 + "VM2", + "VM3", + "VM4", + "VM5", + "VM6", + "VM7", + # Fake segment registers + "CS", + "DS" + ] + + # Create the ireg_XXXX constants + for i in range(len(self.reg_names)): + setattr(self, 'ireg_' + self.reg_names[i], i) + + # Segment register information (use virtual CS and DS registers if your + # processor doesn't have segment registers): + self.reg_first_sreg = self.ireg_CS + self.reg_last_sreg = self.ireg_DS + + # number of CS register + self.reg_code_sreg = self.ireg_CS + + # number of DS register + self.reg_data_sreg = self.ireg_DS + + # ---------------------------------------------------------------------- + def __init__(self): + processor_t.__init__(self) + self.PTRSZ = 4 # Assume PTRSZ = 4 by default + self.init_instructions() + self.init_registers() + +# ---------------------------------------------------------------------- +def PROCESSOR_ENTRY(): + return ebc_processor_t() diff --git a/idasdk76/module/script/makefile b/idasdk76/module/script/makefile new file mode 100644 index 0000000..8cb59d6 --- /dev/null +++ b/idasdk76/module/script/makefile @@ -0,0 +1,14 @@ +include ../../allmake.mak + +SCRIPTS += ebc.py +SCRIPTS += msp430.py +SCRIPTS += proctemplate.py + +BIN_PATH = $(R)procs/ +GOALS += $(addprefix $(BIN_PATH),$(SCRIPTS)) +all: $(GOALS) + + +$(BIN_PATH)%: % + $(CP) $? $@ + diff --git a/idasdk76/module/script/msp430.py b/idasdk76/module/script/msp430.py new file mode 100644 index 0000000..1225944 --- /dev/null +++ b/idasdk76/module/script/msp430.py @@ -0,0 +1,1408 @@ +# ---------------------------------------------------------------------- +# Texas Instruments MSP430 processor module +# Copyright (c) 2010-2021 Hex-Rays +# +# This module demonstrates: +# - instruction decoding and printing +# - simplification of decoded instructions +# - creation of code and data cross-references +# - auto-creation of data items from cross-references +# - tracing of the stack pointer changes +# - creation of the stack variables +# - handling of switch constructs +# +# Please send fixes or improvements to support@hex-rays.com + +import sys +import copy + +from ida_bytes import * +from ida_ua import * +from ida_idp import * +from ida_auto import * +from ida_nalt import * +from ida_funcs import * +from ida_lines import * +from ida_problems import * +from ida_offset import * +from ida_segment import * +from ida_name import * +from ida_netnode import * +from ida_xref import * +from ida_idaapi import * +import ida_frame +import idc + +if sys.version_info.major < 3: + range = xrange + +# extract bitfield occupying bits high..low from val (inclusive, start from 0) +def BITS(val, high, low): + return (val>>low)&((1<<(high-low+1))-1) + +# extract one bit +def BIT(val, bit): + return (val>>bit) & 1 + +# sign extend b low bits in x +# from "Bit Twiddling Hacks" +def SIGNEXT(x, b): + m = 1 << (b - 1) + x = x & ((1 << b) - 1) + return (x ^ m) - m + +# values for specval field for o_phrase operands +FL_INDIRECT = 1 # indirect: @Rn +FL_AUTOINC = 2 # auto-increment: @Rn+ + +# values for specval field for o_mem operands +FL_ABSOLUTE = 1 # absolute: &addr +FL_SYMBOLIC = 2 # symbolic: addr + +# values for insn_t.auxpref +AUX_SIZEMASK = 0x0F +AUX_NOSUF = 0x00 # no suffix (e.g. SWPB) +AUX_WORD = 0x01 # word transfer, .W suffix +AUX_BYTE = 0x02 # byte transfer, .B suffix +AUX_A = 0x03 # 20-bit transfer, .A suffix +AUX_AX = 0x04 # 20-bit immediate/address, no suffix +AUX_REPIMM = 0x10 # immediate repeat count present (in insn_t.segpref) +AUX_REPREG = 0x20 # register repeat count (reg no in in insn_t.segpref) +AUX_ZC = 0x40 # zero carry flag is set + +# addressing mode field in the opcode +AM_REGISTER = 0 # Rn +AM_INDEXED = 1 # X(Rn), also includes symbolic and absolute +AM_INDIRECT = 2 # @Rn +AM_AUTOINC = 3 # @Rn+, also includes immediate (#N = @PC+) +# extra formats +AM_IMM20 = 100 # Rn is imm19:16, imm15:0 follows +AM_ABS20 = 101 # Rn is &abs19:16, &abs15:0 follows +AM_SYM20 = 102 # as IMM20, plus PC value + +# operand data length value +# A/L B/W +DLEN_WORD = 0 # 1 0 16-bit word +DLEN_BYTE = 1 # 1 1 8-bit byte +DLEN_AWORD = 2 # 0 1 20-bit address-word +DLEN_LONG = 3 # 0 0 Reserved + +# check if operand is immediate value val +def is_imm_op(op, val): + if op.type == o_imm: + # workaround for difference between Python and native numbers + op2 = op_t() + op2.value = val + return op.value == op2.value + return False + +# are operands equal? +def same_op(op1, op2): + return op1.type == op2.type and \ + op1.reg == op2.reg and \ + op1.value == op2.value and \ + op1.addr == op2.addr and \ + op1.flags == op2.flags and \ + op1.specval == op2.specval and \ + op1.dtype == op2.dtype + +# is operand auto-increment register reg? +def is_autoinc(op, reg): + return op.type == o_phrase and op.reg == reg and op.specval == FL_AUTOINC + +# is sp delta fixed by the user? +def is_fixed_spd(ea): + return (get_aflags(ea) & AFL_FIXEDSPD) != 0 + +# ---------------------------------------------------------------------- +class msp430_processor_t(processor_t): + """ + Processor module classes must derive from processor_t + """ + + # IDP id ( Numbers above 0x8000 are reserved for the third-party modules) + id = PLFM_MSP430 + + # Processor features + flag = PR_SEGS | PRN_HEX | PR_RNAMESOK | PR_WORD_INS \ + | PR_USE32 | PR_DEFSEG32 + + # Number of bits in a byte for code segments (usually 8) + # IDA supports values up to 32 bits (64 for IDA64) + cnbits = 8 + + # Number of bits in a byte for non-code segments (usually 8) + # IDA supports values up to 32 bits (64 for IDA64) + dnbits = 8 + + # short processor names + # Each name should be shorter than 9 characters + psnames = ['msp430'] + + # long processor names + # No restriction on name lengthes. + plnames = ['Texas Instruments MSP430'] + + # size of a segment register in bytes + segreg_size = 0 + + # Array of typical code start sequences (optional) + codestart = ['\x0B\x12'] # 120B: push R11 + + # Array of 'return' instruction opcodes (optional) + # retcodes = ['\x30\x41'] # 4130: ret (mov.w @SP+, PC) + + # Array of instructions + instruc = [ + {'name': '', 'feature': 0}, # placeholder for "not an instruction" + + # two-operand instructions + {'name': 'mov', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Move source to destination"}, + {'name': 'add', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source to destination"}, + {'name': 'addc', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source and carry to destination"}, + {'name': 'subc', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source with carry from destination"}, + {'name': 'sub', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source from destination"}, + {'name': 'cmp', 'feature': CF_USE1 | CF_USE2, 'cmt': "Compare source and destination"}, + {'name': 'dadd', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source decimally to destination"}, + {'name': 'bit', 'feature': CF_USE1 | CF_USE2, 'cmt': "Test bits set in source in destination"}, + {'name': 'bic', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Clear bits set in source in destination"}, + {'name': 'bis', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Set bits set in source in destination"}, + {'name': 'xor', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Exclusive OR source with destination"}, + {'name': 'and', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Binary AND source and destination"}, + + # MSP430X instructions + {'name': 'movx', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Move source to destination"}, + {'name': 'addx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source to destination"}, + {'name': 'addcx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source and carry to destination"}, + {'name': 'subcx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source with carry from destination"}, + {'name': 'subx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source from destination"}, + {'name': 'cmpx', 'feature': CF_USE1 | CF_USE2, 'cmt': "Compare source and destination"}, + {'name': 'daddx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source decimally to destination"}, + {'name': 'bitx', 'feature': CF_USE1 | CF_USE2, 'cmt': "Test bits set in source in destination"}, + {'name': 'bicx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Clear bits set in source in destination"}, + {'name': 'bisx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Set bits set in source in destination"}, + {'name': 'xorx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Exclusive OR source with destination"}, + {'name': 'andx', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Binary AND source and destination"}, + {'name': 'rrcm', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate right through C"}, + {'name': 'rram', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate right arithmetically"}, + {'name': 'rlam', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate left arithmetically"}, + {'name': 'rrum', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Rotate right unsigned"}, + {'name': 'pushm', 'feature': CF_USE1 | CF_USE2, 'cmt': "Push registers onto stack"}, + {'name': 'popm', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Pop registers from the stack"}, + + # MSP430X address instructions + {'name': 'mova', 'feature': CF_USE1 | CF_CHG2, 'cmt': "Move source to destination"}, + {'name': 'cmpa', 'feature': CF_USE1 | CF_USE2, 'cmt': "Compare source and destination"}, + {'name': 'adda', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Add source to destination"}, + {'name': 'suba', 'feature': CF_USE1 | CF_USE2 | CF_CHG2, 'cmt': "Subtract source from destination"}, + + # one-operand instructions + {'name': 'rrc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right through C"}, + {'name': 'swpb', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Swap bytes"}, + {'name': 'rra', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right arithmetically"}, + {'name': 'sxt', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Extend sign (8 bits to 16)"}, + {'name': 'push', 'feature': CF_USE1 , 'cmt': "Push onto stack"}, + {'name': 'call', 'feature': CF_USE1 | CF_CALL, 'cmt': "Call subroutine"}, + {'name': 'reti', 'feature': CF_STOP , 'cmt': "Return from interrupt"}, + + # MSP430X instructions + {'name': 'rrcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right through carry"}, + {'name': 'swpbx','feature': CF_USE1 | CF_CHG1, 'cmt': "Exchange low byte with high byte"}, + {'name': 'rrax', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right arithmetically"}, + {'name': 'sxtx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Extend sign of lower byte"}, + {'name': 'pushx','feature': CF_USE1 , 'cmt': "Push onto stack"}, + {'name': 'calla','feature': CF_USE1 , 'cmt': "Call subroutine (20-bit)"}, + {'name': 'rrux', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate right unsigned"}, + + # jumps + {'name': 'jnz', 'feature': CF_USE1 , 'cmt': "Jump if not zero/not equal"}, + {'name': 'jz', 'feature': CF_USE1 , 'cmt': "Jump if zero/equal"}, + {'name': 'jnc', 'feature': CF_USE1 , 'cmt': "Jump if no carry/lower (unsigned)"}, + {'name': 'jc', 'feature': CF_USE1 , 'cmt': "Jump if carry/higher or same (unsigned)"}, + {'name': 'jn', 'feature': CF_USE1 , 'cmt': "Jump if negative"}, + {'name': 'jge', 'feature': CF_USE1 , 'cmt': "Jump if greater or equal (signed)"}, + {'name': 'jl', 'feature': CF_USE1 , 'cmt': "Jump if less (signed)"}, + {'name': 'jmp', 'feature': CF_USE1 | CF_STOP, 'cmt': "Jump unconditionally"}, + + # emulated instructions + {'name': 'adc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry to destination"}, + {'name': 'br', 'feature': CF_USE1 | CF_STOP, 'cmt': "Branch to destination"}, + {'name': 'clr', 'feature': CF_CHG1 , 'cmt': "Clear destination"}, + {'name': 'clrc', 'feature': 0 , 'cmt': "Clear carry bit"}, + {'name': 'clrn', 'feature': 0 , 'cmt': "Clear negative bit"}, + {'name': 'clrz', 'feature': 0 , 'cmt': "Clear zero bit"}, + {'name': 'dadc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry decimally to destination"}, + {'name': 'dec', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Decrement destination"}, + {'name': 'decd', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Double-decrement destination"}, + {'name': 'dint', 'feature': 0 , 'cmt': "Disable general interrupts"}, + {'name': 'eint', 'feature': 0 , 'cmt': "Enable general interrupts"}, + {'name': 'inc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Increment destination"}, + {'name': 'incd', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Double-increment destination"}, + {'name': 'inv', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Invert destination"}, + {'name': 'nop', 'feature': 0 , 'cmt': "No operation"}, + {'name': 'pop', 'feature': CF_CHG1 , 'cmt': "Pop from the stack"}, + {'name': 'ret', 'feature': CF_STOP , 'cmt': "Return from subroutine"}, + {'name': 'rla', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left arithmetically"}, + {'name': 'rlc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left through carry"}, + {'name': 'sbc', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Substract borrow (=NOT carry) from destination"}, + {'name': 'setc', 'feature': 0 , 'cmt': "Set carry bit"}, + {'name': 'setn', 'feature': 0 , 'cmt': "Set negative bit"}, + {'name': 'setz', 'feature': 0 , 'cmt': "Set zero bit"}, + {'name': 'tst', 'feature': CF_USE1 , 'cmt': "Test destination"}, + # MSP430X instructions + {'name': 'adcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry to destination"}, + {'name': 'bra', 'feature': CF_USE1 | CF_STOP, 'cmt': "Branch indirect to destination"}, + {'name': 'reta', 'feature': CF_STOP , 'cmt': "Return from subroutine"}, + {'name': 'popa', 'feature': CF_CHG1 , 'cmt': "Pop from the stack"}, + {'name': 'clra', 'feature': CF_CHG1 , 'cmt': "Clear destination"}, + {'name': 'clrx', 'feature': CF_CHG1 , 'cmt': "Clear destination"}, + {'name': 'dadcx','feature': CF_USE1 | CF_CHG1, 'cmt': "Add carry decimally to destination"}, + {'name': 'decx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Decrement destination"}, + {'name': 'decda','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-decrement destination"}, + {'name': 'decdx','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-decrement destination"}, + {'name': 'incx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Increment destination"}, + {'name': 'incda','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-increment destination"}, + {'name': 'incdx','feature': CF_USE1 | CF_CHG1, 'cmt': "Double-increment destination"}, + {'name': 'invx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Invert destination"}, + {'name': 'rlax', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left arithmetically"}, + {'name': 'rlcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Rotate left through carry"}, + {'name': 'sbcx', 'feature': CF_USE1 | CF_CHG1, 'cmt': "Substract borrow (=NOT carry) from destination"}, + {'name': 'tsta', 'feature': CF_USE1 , 'cmt': "Test destination"}, + {'name': 'tstx', 'feature': CF_USE1 , 'cmt': "Test destination"}, + {'name': 'popx', 'feature': CF_CHG1 , 'cmt': "Pop from the stack"}, + ] + + # icode of the first instruction + instruc_start = 0 + + # icode of the last instruction + 1 + instruc_end = len(instruc) + 1 + + # Size of long double (tbyte) for this processor (meaningful only if ash.a_tbyte != NULL) (optional) + # tbyte_size = 0 + + # + # Number of digits in floating numbers after the decimal point. + # If an element of this array equals 0, then the corresponding + # floating point data is not used for the processor. + # This array is used to align numbers in the output. + # real_width[0] - number of digits for short floats (only PDP-11 has them) + # real_width[1] - number of digits for "float" + # real_width[2] - number of digits for "double" + # real_width[3] - number of digits for "long double" + # Example: IBM PC module has { 0,7,15,19 } + # + # (optional) + real_width = (0, 7, 15, 19) + + + # only one assembler is supported + assembler = { + # flag + 'flag' : ASH_HEXF0 | ASD_DECF0 | ASO_OCTF5 | ASB_BINF0 | AS_N2CHR, + + # user defined flags (local only for IDP) (optional) + 'uflag' : 0, + + # Assembler name (displayed in menus) + 'name': "Generic MSP430 assembler", + + # array of automatically generated header lines they appear at the start of disassembled text (optional) + 'header': [".msp430"], + + # org directive + 'origin': ".org", + + # end directive + 'end': ".end", + + # comment string (see also cmnt2) + 'cmnt': ";", + + # ASCII string delimiter + 'ascsep': "\"", + + # ASCII char constant delimiter + 'accsep': "'", + + # ASCII special chars (they can't appear in character and ascii constants) + 'esccodes': "\"'", + + # + # Data representation (db,dw,...): + # + # ASCII string directive + 'a_ascii': ".char", + + # byte directive + 'a_byte': ".byte", + + # word directive + 'a_word': ".short", + + # dword (32 bits) + 'a_dword': ".long", + + # qword (64 bits) + 'a_qword': ".quad", + + # float; 4bytes; remove if not allowed + 'a_float': ".float", + + # double ; 8bytes; remove if not allowed + 'a_double': ".double", + + # uninitialized data directive (should include '%s' for the size of data) + 'a_bss': ".space %s", + + # 'equ' Used if AS_UNEQU is set (optional) + 'a_equ': ".equ", + + # 'seg ' prefix (example: push seg seg001) + 'a_seg': "seg", + + # current IP (instruction pointer) symbol in assembler + 'a_curip': "$", + + # "public" name keyword. NULL-gen default, ""-do not generate + 'a_public': ".def", + + # "weak" name keyword. NULL-gen default, ""-do not generate + 'a_weak': "", + + # "extrn" name keyword + 'a_extrn': ".ref", + + # "comm" (communal variable) + 'a_comdef': "", + + # "align" keyword + 'a_align': ".align", + + # Left and right braces used in complex expressions + 'lbrace': "(", + 'rbrace': ")", + + # % mod assembler time operation + 'a_mod': "%", + + # & bit and assembler time operation + 'a_band': "&", + + # | bit or assembler time operation + 'a_bor': "|", + + # ^ bit xor assembler time operation + 'a_xor': "^", + + # ~ bit not assembler time operation + 'a_bnot': "~", + + # << shift left assembler time operation + 'a_shl': "<<", + + # >> shift right assembler time operation + 'a_shr': ">>", + + # size of type (format string) (optional) + 'a_sizeof_fmt': "size %s", + + 'flag2': 0, + + # the include directive (format string) (optional) + 'a_include_fmt': '.include "%s"', + } # Assembler + + def ev_get_frame_retsize(self, frsize, pfn): + ida_pro.int_pointer.frompointer(frsize).assign(2) + return 1 + + def ev_get_autocmt(self, insn): + if 'cmt' in self.instruc[insn.itype]: + return self.instruc[insn.itype]['cmt'] + + # ---------------------------------------------------------------------- + def ev_is_sane_insn(self, insn, no_crefs): + w = get_wide_word(insn.ea) + if w == 0 or w == 0xFFFF: + return -1 + return 1 + + # ---------------------------------------------------------------------- + def is_movpc(self, insn): + # mov xxx, PC + return insn.itype == self.itype_mov and insn.Op2.is_reg(self.ireg_PC) and insn.auxpref == AUX_WORD + + # ---------------------------------------------------------------------- + def changes_pc(self, insn): + Feature = insn.get_canon_feature() + if (Feature & CF_CHG2) and insn.Op2.is_reg(self.ireg_PC): + return True + if (Feature & CF_CHG1) and insn.Op1.is_reg(self.ireg_PC): + return True + return False + + # ---------------------------------------------------------------------- + def handle_operand(self, insn, op, isRead): + flags = get_flags(insn.ea) + is_offs = is_off(flags, op.n) + dref_flag = dr_R if isRead else dr_W + def_arg = is_defarg(flags, op.n) + optype = op.type + + itype = insn.itype + # create code xrefs + if optype == o_imm: + makeoff = False + if itype in [self.itype_call, self.itype_calla]: + # call #func + insn.add_cref(op.value, op.offb, fl_CN) + makeoff = True + elif self.is_movpc(insn) or insn.itype in [self.itype_br, self.itype_bra]: + # mov #addr, PC + insn.add_cref(op.value, op.offb, fl_JN) + makeoff = True + if makeoff and not def_arg: + op_plain_offset(insn.ea, op.n, insn.cs) + is_offs = True + if is_offs: + insn.add_off_drefs(op, dr_O, 0) + # create data xrefs + elif optype == o_displ: + # delta(reg) + if is_offs: + insn.add_off_drefs(op, dref_flag, OOF_ADDR) + elif may_create_stkvars() and not def_arg and op.reg == self.ireg_SP: + # var_x(SP) + pfn = get_func(insn.ea) + if pfn and insn.create_stkvar(op, op.addr, STKVAR_VALID_SIZE): + op_stkvar(insn.ea, op.n) + elif optype == o_mem: + insn.create_op_data(op.addr, op) + insn.add_dref(op.addr, op.offb, dref_flag) + elif optype == o_near: + insn.add_cref(op.addr, op.offb, fl_JN) + + # ---------------------------------------------------------------------- + def add_stkpnt(self, pfn, insn, v): + if pfn: + end = insn.ea + insn.size + if not is_fixed_spd(end): + ida_frame.add_auto_stkpnt(pfn, end, v) + + # ---------------------------------------------------------------------- + def trace_sp(self, insn): + """ + Trace the value of the SP and create an SP change point if the current + instruction modifies the SP. + """ + pfn = get_func(insn.ea) + if not pfn: + return + spofs = 0 + if insn.itype in [self.itype_add, self.itype_addx, self.itype_adda, self.itype_addc, self.itype_addcx, + self.itype_sub, self.itype_subx, self.itype_suba, self.itype_subc, self.itype_subcx] and \ + insn.Op2.is_reg(self.ireg_SP) and insn.auxpref in [AUX_WORD, AUX_A, AUX_AX] and \ + insn.Op1.type == o_imm: + # add.w #xxx, SP + # subc.w #xxx, SP + if insn.auxpref == AUX_WORD: + spofs = SIGNEXT(insn.Op1.value, 16) + else: + spofs = SIGNEXT(insn.Op1.value, 20) + if insn.itype in [self.itype_sub, self.itype_suba, self.itype_subc, self.itype_subx, self.itype_subcx]: + spofs = -spofs + elif insn.itype in [self.itype_incd, self.itype_decd, self.itype_incdx, + self.itype_decdx, self.itype_incda, self.itype_decda] and \ + insn.Op1.is_reg(self.ireg_SP) and insn.auxpref in [AUX_WORD, AUX_A, AUX_AX]: + spofs = 2 if insn.itype in [self.itype_incd, self.itype_incdx, self.itype_incda] else -2 + self.add_stkpnt(pfn, insn, spofs) + elif insn.itype == self.itype_push: + spofs = -2 + elif insn.itype in [self.itype_popm, self.itype_pushm, self.itype_popx, self.itype_pushx]: + # popm.a #n, reg -> +n*4 + # popm.w #n, reg -> +n*2 + # popx.a reg -> +4 + # popx.w reg -> +2 + if insn.itype in [self.itype_popm, self.itype_pushm]: + count = insn.Op1.value + else: + count = 1 + spofs = 1 if insn.itype == self.itype_popm else -1 + if insn.auxpref == AUX_A: + spofs *= count * 4 + else: + spofs *= count * 2 + elif insn.itype == self.itype_pop or is_autoinc(insn.Op1, self.ireg_SP): + # pop R7 or mov.w @SP+, R7 + if insn.auxpref in [AUX_A, AUX_AX]: + spofs = 4 + else: + spofs = 2 + + if spofs != 0: + self.add_stkpnt(pfn, insn, spofs) + + # ---------------------------------------------------------------------- + def check_switch(self, insn): + # detect switches and set switch info + # + # cmp.w #nn, Rx + # jc default + # [mov.w Rx, Ry] + # rla.w Ry, Ry + # br jtbl(Ry) + # jtbl .short case0, .short case1 + if get_switch_info(insn.ea): + return + ok = False + si = switch_info_t() + + # mov.w jtbl(Ry), PC + if (self.is_movpc(insn) or insn.itype in [self.itype_br, self.itype_bra]) and insn.Op1.type == o_displ: + si.jumps = insn.Op1.addr # jump table address + Ry = insn.Op1.reg + ok = True + # add.w Ry, Ry | rla.w Ry + prev = insn_t() + if decode_prev_insn(prev, insn.ea) != BADADDR and prev.auxpref == AUX_WORD: + ok = prev.itype == self.itype_add and prev.Op1.is_reg(Ry) and prev.Op2.is_reg(Ry) or \ + prev.itype == self.itype_rla and prev.Op1.is_reg(Ry) + else: + ok = False + if ok and decode_prev_insn(prev, prev.ea) != BADADDR: + # mov.w Rx, Ry + if prev.itype == self.itype_mov and \ + prev.Op2.is_reg(Ry) and \ + prev.Op1.type == o_reg and \ + prev.auxpref == AUX_WORD: + Rx = prev.Op1.reg + ok = decode_prev_insn(prev, prev.ea) != BADADDR + else: + Rx = Ry + else: + ok = False + + # jc default + if ok and prev.itype == self.itype_jc: + si.defjump = prev.Op1.addr + else: + ok = False + + # cmp.w #nn, Rx + if ok and decode_prev_insn(prev, prev.ea) == BADADDR or \ + prev.itype != self.itype_cmp or \ + prev.Op1.type != o_imm or \ + not prev.Op2.is_reg(Rx) or \ + prev.auxpref != AUX_WORD: + ok = False + else: + si.ncases = prev.Op1.value + si.lowcase = 0 + si.startea = prev.ea + si.set_expr(Rx, dt_word) + + if ok: + # make offset to the jump table + op_plain_offset(insn.ea, 0, insn.cs) + set_switch_info(insn.ea, si) + create_switch_table(insn.ea, si) + + # ---------------------------------------------------------------------- + # The following callbacks are mandatory + # + def ev_emu_insn(self, insn): + aux = self.get_auxpref(insn) + Feature = insn.get_canon_feature() + + if Feature & CF_USE1: + self.handle_operand(insn, insn.Op1, 1) + if Feature & CF_CHG1: + self.handle_operand(insn, insn.Op1, 0) + if Feature & CF_USE2: + self.handle_operand(insn, insn.Op2, 1) + if Feature & CF_CHG2: + self.handle_operand(insn, insn.Op2, 0) + if Feature & CF_JUMP: + remember_problem(PR_JUMP, insn.ea) + + # is it an unconditional jump? + uncond_jmp = insn.itype in [self.itype_jmp, self.itype_br, self.itype_bra] or self.changes_pc(insn) + + # add flow + flow = (Feature & CF_STOP == 0) and not uncond_jmp + if flow: + add_cref(insn.ea, insn.ea + insn.size, fl_F) + else: + self.check_switch(insn) + + # trace the stack pointer if: + # - it is the second analysis pass + # - the stack pointer tracing is allowed + if may_trace_sp(): + if flow: + self.trace_sp(insn) # trace modification of SP register + else: + idc.recalc_spd(insn.ea) # recalculate SP register for the next insn + + return True + + # ---------------------------------------------------------------------- + def ev_out_operand(self, ctx, op): + optype = op.type + fl = op.specval + signed = 0 + sz = ctx.insn.auxpref & AUX_SIZEMASK + + if optype == o_reg: + ctx.out_register(self.reg_names[op.reg]) + elif optype == o_imm: + ctx.out_symbol('#') + op2 = copy.copy(op) + if sz == AUX_BYTE: + op2.value &= 0xFF + elif sz == AUX_WORD: + op2.value &= 0xFFFF + else: + op2.value &= 0xFFFFF + ctx.out_value(op2, OOFW_IMM | signed ) + elif optype in [o_near, o_mem]: + if optype == o_mem and fl == FL_ABSOLUTE: + ctx.out_symbol('&') + r = ctx.out_name_expr(op, op.addr, BADADDR) + if not r: + ctx.out_tagon(COLOR_ERROR) + ctx.out_btoa(op.addr, 16) + ctx.out_tagoff(COLOR_ERROR) + remember_problem(PR_NONAME, ctx.insn.ea) + elif optype == o_displ: + # 16-bit index is signed + width = OOFW_16 + sign = OOF_SIGNED + if sz in [AUX_A, AUX_AX] or op.dtype == dt_dword: + # 20-bit index is not signed + width = OOFW_24 + sign = 0 + ctx.out_value(op, OOF_ADDR | signed | width ) + ctx.out_symbol('(') + ctx.out_register(self.reg_names[op.reg]) + ctx.out_symbol(')') + elif optype == o_phrase: + ctx.out_symbol('@') + ctx.out_register(self.reg_names[op.reg]) + if fl == FL_AUTOINC: + ctx.out_symbol('+') + else: + return False + + return True + + # ---------------------------------------------------------------------- + def ev_out_mnem(self, ctx): + + postfix = "" + + # add postfix if necessary + sz = ctx.insn.auxpref & AUX_SIZEMASK + if sz == AUX_BYTE: + postfix = ".b" + elif sz == AUX_WORD: + postfix = ".w" + elif sz == AUX_A: + postfix = ".a" + + # first argument (8) is the width of the mnemonic field + ctx.out_mnem(8, postfix) + return 1 + + # ---------------------------------------------------------------------- + def ev_out_insn(self, ctx): + """ + Generate text representation of an instruction in 'ctx.insn' structure. + This function shouldn't change the database, flags or anything else. + All these actions should be performed only by emu() function. + Returns: nothing + """ + # do we need to print a modifier line first? + if ctx.insn.auxpref & (AUX_REPREG | AUX_REPIMM | AUX_ZC): + segpref = ctx.insn.segpref + if sys.version_info.major < 3: + segpref = ord(segpref) + if ctx.insn.auxpref & AUX_ZC: + ctx.out_line(".zc", COLOR_INSN) + ctx.flush_outbuf() + if ctx.insn.auxpref & AUX_REPREG: + ctx.out_line(".rpt", COLOR_INSN) + ctx.out_char(' ') + ctx.out_register(self.reg_names[segpref]) + ctx.flush_outbuf() + if ctx.insn.auxpref & AUX_REPIMM: + ctx.out_line(".rpt", COLOR_INSN) + ctx.out_char(' ') + ctx.out_symbol('#') + ctx.out_long(segpref, 10) + ctx.flush_outbuf() + #ident next line + ctx.out_char(' ') + + ctx.out_mnemonic() + + # output first operand + # kernel will call out_operand() + if ctx.insn.Op1.type != o_void: + ctx.out_one_operand(0) + + # output the rest of operands separated by commas + for i in range(1, 3): + if ctx.insn[i].type == o_void: + break + ctx.out_symbol(',') + ctx.out_char(' ') + ctx.out_one_operand(i) + + ctx.set_gen_cmt() # generate comment at the next call to MakeLine() + ctx.flush_outbuf() + return True + + # ---------------------------------------------------------------------- + # fill operand fields from decoded instruction parts + # op: operand to be filled in + # reg: register number + # A: adressing mode + # BW: value of the B/W (byte/word) field + # can be DLEN_AWORD for 20-bit instructions + # is_source: True if filling source operand + # is_cg: can use constant generator + # extw: 20-bit extension word + def fill_op(self, insn, op, reg, A, BW, is_source, is_cg = False, extw = None): + op.reg = reg + topaddr = 0 # top 4 bits of an address value + if extw: + AL = BIT(extw, 6) + if AL == 0 and BW == 1: + BW = DLEN_AWORD + if is_source: + topaddr = BITS(extw, 10, 7) + else: + topaddr = BITS(extw, 3, 0) + if BW == DLEN_WORD: + op.dtype = dt_word + elif BW == DLEN_BYTE: + op.dtype = dt_byte + else: + # 20-bit + op.dtype = dt_dword + if is_cg: + # check for constant generators + if reg == self.ireg_SR and A >= 2 and A <= 3: + op.type = o_imm + op.value = [4, 8] [A-2] + return + elif reg == self.ireg_R3: + op.type = o_imm + op.value = [0, 1, 2, -1] [A] + return + if A == AM_REGISTER: + # register mode + op.type = o_reg + op.dtype = dt_word + elif A == AM_INDEXED: + # indexed mode + if reg == self.ireg_SR: + # absolute address mode + op.type = o_mem + op.specval = FL_ABSOLUTE + op.offb = insn.size + op.addr = insn.get_next_word() | (topaddr << 16) + else: + # map it to IDA's displacement + op.type = o_displ + op.offb = insn.size + pcval = insn.ip + insn.size + op.addr = insn.get_next_word() | (topaddr << 16) + if reg == self.ireg_PC: + # symbolic addressing mode: address = PC + simm16 + # 1) if PC is below 64K, the result is wrapped to be below 64K + # 2) if PC is above 64K, the result is used as-is (can be below or above 64K) + # 3) for MSP430X instructions delta is simm20, result not wrapped + # apparently the PC value is the address of the index word, not next instruction! + if extw: + op.addr = SIGNEXT(op.addr, 20) + pcval + else: + op.addr = SIGNEXT(op.addr, 16) + pcval + if pcval < 0x10000: + op.addr &= 0xFFFF + op.type = o_mem + op.specval = FL_SYMBOLIC + # slau208p.pdf: All addresses, indexes, and immediate numbers have + # 20-bit values when preceded by the extension word. + if extw: + op.dtype = dt_dword + elif A == AM_INDIRECT: + # Indirect register mode + # map it to o_phrase + op.type = o_phrase + op.specval = FL_INDIRECT + elif A == AM_AUTOINC: + # Indirect autoincrement + # map it to o_phrase + if reg == self.ireg_PC: + #this is actually immediate mode + op.dtype = dt_dword if extw else dt_word + op.type = o_imm + op.offb = insn.size + op.value = insn.get_next_word() | (topaddr << 16) + else: + op.type = o_phrase + op.specval = FL_AUTOINC + elif A in [AM_IMM20, AM_ABS20, AM_SYM20]: + # reg is the high 4 bits, low 16 bits follow + val = (reg << 16) | insn.get_next_word() + if A == AM_IMM20: + op.dtype = dt_dword + op.value = val + op.type = o_imm + else: + # &abs20 + op.addr = val + op.type = o_mem + if A == AM_SYM20: + # symbolic addressing mode: address = PC + imm20 + # no sign-extension or wrapping is done + pcval = insn.ip + insn.size + op.addr += pcval + op.specval = FL_SYMBOLIC + else: + op.specval = FL_ABSOLUTE + else: + warning("bad A(%d) in fill_op" % A) + + # ---------------------------------------------------------------------- + def handle_reg_extw(self, insn, extw): + # Register Mode Extension Word + # 15 ... 12 11 10 9 8 7 6 5 4 3 0 + # +---------+--------+----+---+-----+---+---+------+ + # | 0001 | 1 | 00 | ZC | # | A/L | 0 | 0 | R/n-1| + # +---------+--------+----+---+-----+---+---+------+ + ZC = BIT(extw, 8) + repreg = BIT(extw, 7) + rep = BITS(extw, 3, 0) + if rep: + if repreg: + insn.auxpref |= AUX_REPREG + insn.segpref = rep + else: + insn.auxpref |= AUX_REPIMM + insn.segpref = rep + 1 + if ZC: + if insn.itype == self.itype_rrcx: + insn.itype = self.itype_rrux + else: + insn.auxpref |= AUX_ZC + + # ---------------------------------------------------------------------- + def decode_format_I(self, insn, w, extw): + # Double-Operand (Format I) Instructions + # + # 15 ... 12 11 ... 8 7 6 5 4 3 0 + # +---------+--------+----+-----+----+------+ + # | Op-code | Rsrc | Ad | B/W | As | Rdst | + # +---------+--------+----+-----+----+------+ + # | Source or destination 15:0 | + # +-----------------------------------------+ + # | Destination 15:0 | + # +-----------------------------------------+ + opc = BITS(w, 15, 12) + As = BITS(w, 5, 4) + Ad = BIT(w, 7) + Rsrc = BITS(w, 11, 8) + Rdst = BITS(w, 3, 0) + BW = BIT(w, 6) + if opc < 4: + # something went wrong + insn.size = 0 + else: + if extw: + AL = BIT(extw, 6) + if AL == 0 and BW == 1: + BW = DLEN_AWORD + insn.itype = self.itype_movx + (opc-4) + else: + insn.itype = self.itype_mov + (opc-4) + self.fill_op(insn, insn.Op1, Rsrc, As, BW, True, True, extw) + self.fill_op(insn, insn.Op2, Rdst, Ad, BW, False, False, extw) + insn.auxpref = BW + AUX_WORD + if extw and As == AM_REGISTER and Ad == AM_REGISTER: + self.handle_reg_extw(insn, extw) + + # ---------------------------------------------------------------------- + def decode_format_II(self, insn, w, extw): + # Single-Operand (Format II) Instructions + # + # 15 10 9 7 6 5 4 3 0 + # +-------------+---------+-----+----+------+ + # | 0 0 0 1 0 0 | Op-code | B/W | Ad | Rdst | + # +-------------+---------+-----+----+------+ + # | Destination 15:0 | + # +-----------------------------------------+ + opc = BITS(w, 9, 7) + Ad = BITS(w, 5, 4) + Rdst = BITS(w, 3, 0) + BW = BIT(w, 6) + if opc in [6, 7]: + if extw: + return 0 + return self.decode_430x_calla(insn, w) + if extw: + AL = BIT(extw, 6) + if AL == 0 and BW == 1: + BW = DLEN_AWORD + insn.itype = self.itype_rrcx + opc + else: + insn.itype = self.itype_rrc + opc + self.fill_op(insn, insn.Op1, Rdst, Ad, BW, False, True, extw) + insn.auxpref = BW + AUX_WORD + if insn.itype in [self.itype_swpb, self.itype_sxt, self.itype_call, self.itype_reti]: + # these commands have no suffix and should have BW set to 0 + if BW == 0: + insn.auxpref = AUX_NOSUF + if insn.itype == self.itype_reti: + # Ad and Rdst should be 0 + if Ad == 0 and Rdst == 0: + insn.Op1.type = o_void + else: + # bad instruction + insn.itype = self.itype_null + else: + # bad instruction + insn.itype = self.itype_null + if extw and Ad == AM_REGISTER: + self.handle_reg_extw(insn, extw) + + # ---------------------------------------------------------------------- + def decode_jump(self, insn, w): + # Jump Instructions + # + # 15 13 12 10 9 0 + # +---------+-------+----------------------+ + # | 0 0 1 | C | 10-bit PC offset | + # +---------+-------+----------------------+ + C = BITS(w, 12, 10) + offs = BITS(w, 9, 0) + offs = SIGNEXT(offs, 10) + insn.Op1.type = o_near + insn.Op1.addr = insn.ea + 2 + offs*2 + insn.itype = self.itype_jnz + C + + # ---------------------------------------------------------------------- + def decode_430x_mova(self, insn, w): + # MSP430X Address Instructions + # 15 12 11 8 7 4 3 0 + # 0 0 0 0 src 0 0 0 0 dst MOVA @Rsrc,Rdst + # 0 0 0 0 src 0 0 0 1 dst MOVA @Rsrc+,Rdst + # 0 0 0 0 abs 0 0 1 0 dst MOVA &abs20,Rdst + # 0 0 0 0 src 0 0 1 1 dst MOVA x(Rsrc),Rdst + + # 0 0 0 0 n-1 00 0 1 0 0 dst RRCM.A #n,Rdst + # 0 0 0 0 n-1 01 0 1 0 0 dst RRAM.A #n,Rdst + # 0 0 0 0 n-1 10 0 1 0 0 dst RLAM.A #n,Rdst + # 0 0 0 0 n-1 11 0 1 0 0 dst RRUM.A #n,Rdst + + # 0 0 0 0 n-1 00 0 1 0 1 dst RRCM.W #n,Rdst + # 0 0 0 0 n-1 01 0 1 0 1 dst RRAM.W #n,Rdst + # 0 0 0 0 n-1 10 0 1 0 1 dst RLAM.W #n,Rdst + # 0 0 0 0 n-1 11 0 1 0 1 dst RRUM.W #n,Rdst + + # 0 0 0 0 src 0 1 1 0 abs MOVA Rsrc,&abs20 + # 0 0 0 0 src 0 1 1 1 dst MOVA Rsrc,X(Rdst) + + # 0 0 0 0 imm 1 0 0 0 dst MOVA #imm20,Rdst + # 0 0 0 0 imm 1 0 0 1 dst CMPA #imm20,Rdst + # 0 0 0 0 imm 1 0 1 0 dst ADDA #imm20,Rdst + # 0 0 0 0 imm 1 0 1 1 dst SUBA #imm20,Rdst + # 0 0 0 0 src 1 1 0 0 dst MOVA Rsrc,Rdst + # 0 0 0 0 src 1 1 0 1 dst CMPA Rsrc,Rdst + # 0 0 0 0 src 1 1 1 0 dst ADDA Rsrc,Rdst + # 0 0 0 0 src 1 1 1 1 dst SUBA Rsrc,Rdst + + opc = BITS(w, 7, 4) + Rsrc = BITS(w, 11, 8) + Rdst = BITS(w, 3, 0) + tbl = [ + # itype, operands addressing modes + # indexed by opcode[7:4] + [self.itype_mova, AM_INDIRECT, AM_REGISTER], # 0000 MOVA @Rsrc,Rdst + [self.itype_mova, AM_AUTOINC, AM_REGISTER], # 0001 MOVA @Rsrc+,Rdst + [self.itype_mova, AM_ABS20, AM_REGISTER], # 0010 MOVA &abs20,Rdst + [self.itype_mova, AM_INDEXED, AM_REGISTER], # 0011 MOVA X(Rsrc),Rdst + [-1, -1, -1 ], # 0100 Rxxx.A #n, Rdst + [-1, -1, -1 ], # 0101 Rxxx.W #n, Rdst + [self.itype_mova, AM_REGISTER, AM_ABS20 ], # 0110 MOVA Rsrc, &abs20 + [self.itype_mova, AM_REGISTER, AM_INDEXED ], # 0111 MOVA Rsrc, X(Rdst) + [self.itype_mova, AM_IMM20, AM_REGISTER], # 1000 MOVA #imm20, Rdst + [self.itype_cmpa, AM_IMM20, AM_REGISTER], # 1001 CMPA #imm20, Rdst + [self.itype_adda, AM_IMM20, AM_REGISTER], # 1010 ADDA #imm20, Rdst + [self.itype_suba, AM_IMM20, AM_REGISTER], # 1011 SUBA #imm20, Rdst + [self.itype_mova, AM_REGISTER, AM_REGISTER], # 1100 MOVA Rsrc, Rdst + [self.itype_cmpa, AM_REGISTER, AM_REGISTER], # 1101 CMPA Rsrc, Rdst + [self.itype_adda, AM_REGISTER, AM_REGISTER], # 1110 ADDA Rsrc, Rdst + [self.itype_suba, AM_REGISTER, AM_REGISTER], # 1111 SUBA Rsrc, Rdst + ] + row = tbl[opc] + if row[0] != -1: + insn.itype = row[0] + self.fill_op(insn, insn.Op1, Rsrc, row[1], 2, True, Rdst != 0) + self.fill_op(insn, insn.Op2, Rdst, row[2], 2, False, False) + insn.auxpref = AUX_AX + else: + # src[3:2] == n-1 + # src[1:0] == insn id + insn.itype = self.itype_rrcm + (Rsrc & 0b11) + insn.Op1.type = o_imm + insn.Op1.dtype = dt_byte + insn.Op1.value = (Rsrc>>2) + 1 + # opc[0]: 0=.A, 1=.W + BW = 0 if (opc & 1) else 2 + self.fill_op(insn, insn.Op2, Rdst, AM_REGISTER, BW, False, False) + if opc & 1: + insn.auxpref = AUX_A + else: + insn.auxpref = AUX_WORD + + # ---------------------------------------------------------------------- + def decode_430x_calla(self, insn, w): + # MSP430X CALLA Instruction + opc = BITS(w, 7, 4) + Rdst = BITS(w, 3, 0) + tbl = [ + # itype, dest addressing mode + # indexed by opcode[7:4] + [self.itype_reti, -1 ], # 0000 RETI + [self.itype_null, -1 ], # 0001 ---- + [self.itype_null, -1 ], # 0010 ---- + [self.itype_null, -1 ], # 0011 ---- + [self.itype_calla, AM_REGISTER], # 0100 CALLA Rdst + [self.itype_calla, AM_INDEXED ], # 0101 CALLA X(Rdst) + [self.itype_calla, AM_INDIRECT], # 0110 CALLA @Rdst + [self.itype_calla, AM_AUTOINC ], # 0111 CALLA @Rdst+ + [self.itype_calla, AM_ABS20 ], # 1000 CALLA &abs20 + [self.itype_calla, AM_SYM20 ], # 1001 CALLA sym20 (imm20+PC) + [self.itype_null, -1 ], # 1010 ---- + [self.itype_calla, AM_IMM20 ], # 1011 CALLA #imm20 + [self.itype_null, -1 ], # 1100 ---- + [self.itype_null, -1 ], # 1101 ---- + [self.itype_null, -1 ], # 1110 ---- + [self.itype_null, -1 ], # 1111 ---- + ] + row = tbl[opc] + insn.itype = row[0] + if row[1] != -1: + self.fill_op(insn, insn.Op1, Rdst, row[1], DLEN_AWORD, True, False) + insn.auxpref = AUX_AX + + # ---------------------------------------------------------------------- + def decode_430x_pushm(self, insn, w): + # MSP430X PUSHM/POPM Instructions + # 15 10 98 7 4 3 0 + # 000101 00 n-1 dst PUSHM.A #n,Rdst + # 000101 01 n-1 dst PUSHM.W #n,Rdst + # 000101 10 n-1 dst-n+1 POPM.A #n, Rdst + # 000101 11 n-1 dst-n+1 POPM.W #n, Rdst + opc = BITS(w, 7, 4) + Rdst = BITS(w, 3, 0) + + ispop = BIT(w, 9) + insn.itype = [self.itype_pushm, self.itype_popm] [ispop] + n = BITS(w, 7, 4) + 1 + Rdst = BITS(w, 3, 0) + if ispop: + Rdst += n - 1 + insn.Op1.type = o_imm + insn.Op1.dtype = dt_byte + insn.Op1.value = n + isw = BIT(w, 8) + BW = 0 if isw else 2 + self.fill_op(insn, insn.Op2, Rdst, AM_REGISTER, BW, False, False) + insn.auxpref = [AUX_A, AUX_WORD] [isw] + + # ---------------------------------------------------------------------- + # does operand match tuple m? (type, value) + def match_op(self, op, m): + if m == None: + return True + if op.type != m[0]: + return False + if op.type == o_imm: + return op.value == m[1] + elif op.type in [o_reg, o_phrase]: + return op.reg == m[1] + else: + return false + + # ---------------------------------------------------------------------- + # replace some instructions by simplified mnemonics ("emulated" in TI terms) + def simplify(self, insn): + # source mnemonic mapped to a list of matches: + # match function, new mnemonic, new operand + maptbl = { + self.itype_addc: [ + # addc #0, dst -> adc dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_adc, 2 ], + # addc dst, dst -> rlc dst + [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rlc, 1 ], + ], + self.itype_addcx: [ + # addcx #0, dst -> adcx dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_adcx, 2 ], + # addcx dst, dst -> rlcx dst + [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rlcx, 1 ], + ], + self.itype_mov: [ + # mov #0, R3 -> nop + [ lambda: is_imm_op(insn.Op1, 0) and insn.Op2.is_reg(self.ireg_R3), self.itype_nop, 0 ], + # mov #0, dst -> clr dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_clr, 2 ], + # mov @SP+, PC -> ret + [ lambda: is_autoinc(insn.Op1, self.ireg_SP) and insn.Op2.is_reg(self.ireg_PC), self.itype_ret, 0 ], + # mov @SP+, dst -> pop dst + [ lambda: is_autoinc(insn.Op1, self.ireg_SP), self.itype_pop, 2 ], + # mov dst, PC -> br dst + [ lambda: self.is_movpc(insn), self.itype_br, 1 ], + ], + self.itype_movx: [ + # movx #0, dst -> clrx dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_clrx, 2 ], + # movx @SP+, dst -> popx dst + [ lambda: is_autoinc(insn.Op1, self.ireg_SP), self.itype_popx, 2 ], + ], + self.itype_mova: [ + # mova #0, dst -> clra dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_clra, 2 ], + # mova @SP+, PC -> reta + [ lambda: is_autoinc(insn.Op1, self.ireg_SP) and insn.Op2.is_reg(self.ireg_PC), self.itype_reta, 0 ], + # mova @SP+, dst -> popa dst + [ lambda: is_autoinc(insn.Op1, self.ireg_SP), self.itype_popa, 2 ], + # mova dst, PC -> bra dst + [ lambda: insn.Op2.is_reg(self.ireg_PC), self.itype_bra, 1 ], + ], + self.itype_bic: [ + # bic #1, SR -> clrc + [ lambda: is_imm_op(insn.Op1, 1) and insn.Op2.is_reg(self.ireg_SR), self.itype_clrc, 0 ], + # bic #2, SR -> clrz + [ lambda: is_imm_op(insn.Op1, 2) and insn.Op2.is_reg(self.ireg_SR), self.itype_clrz, 0 ], + # bic #4, SR -> clrn + [ lambda: is_imm_op(insn.Op1, 4) and insn.Op2.is_reg(self.ireg_SR), self.itype_clrn, 0 ], + # bic #8, SR -> dint + [ lambda: is_imm_op(insn.Op1, 8) and insn.Op2.is_reg(self.ireg_SR), self.itype_dint, 0 ], + ], + self.itype_bis: [ + # bis #1, SR -> setc + [ lambda: is_imm_op(insn.Op1, 1) and insn.Op2.is_reg(self.ireg_SR), self.itype_setc, 0 ], + # bis #2, SR -> setz + [ lambda: is_imm_op(insn.Op1, 2) and insn.Op2.is_reg(self.ireg_SR), self.itype_setz, 0 ], + # bis #4, SR -> setn + [ lambda: is_imm_op(insn.Op1, 4) and insn.Op2.is_reg(self.ireg_SR), self.itype_setn, 0 ], + # bis #8, SR -> eint + [ lambda: is_imm_op(insn.Op1, 8) and insn.Op2.is_reg(self.ireg_SR), self.itype_eint, 0 ], + ], + self.itype_dadd: [ + # dadd #0, dst -> dadc dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_dadc, 2 ], + ], + self.itype_daddx: [ + # daddx #0, dst -> dadcx dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_dadcx, 2 ], + ], + self.itype_sub: [ + # sub #1, dst -> dec dst + [ lambda: is_imm_op(insn.Op1, 1), self.itype_dec, 2 ], + # sub #2, dst -> decd dst + [ lambda: is_imm_op(insn.Op1, 2), self.itype_decd, 2 ], + ], + self.itype_subx: [ + # subx #1, dst -> decx dst + [ lambda: is_imm_op(insn.Op1, 1), self.itype_decx, 2 ], + # subx #2, dst -> decdx dst + [ lambda: is_imm_op(insn.Op1, 2), self.itype_decdx, 2 ], + ], + self.itype_suba: [ + # suba #2, dst -> decda dst + [ lambda: is_imm_op(insn.Op1, 2), self.itype_decda, 2 ], + ], + self.itype_subc: [ + # subc #0, dst -> sbc dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_sbc, 2 ], + ], + self.itype_subcx: [ + # subcx #0, dst -> sbcx dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_sbcx, 2 ], + ], + self.itype_add: [ + # add #1, dst -> inc dst + [ lambda: is_imm_op(insn.Op1, 1), self.itype_inc, 2 ], + # add #2, dst -> incd dst + [ lambda: is_imm_op(insn.Op1, 2), self.itype_incd, 2 ], + # add dst, dst -> rla dst + [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rla, 1 ], + ], + self.itype_adda: [ + # adda #2, dst -> incda dst + [ lambda: is_imm_op(insn.Op1, 2), self.itype_incda, 2 ], + ], + self.itype_addx: [ + # addx #1, dst -> incx dst + [ lambda: is_imm_op(insn.Op1, 1), self.itype_incx, 2 ], + # addx #2, dst -> incdx dst + [ lambda: is_imm_op(insn.Op1, 2), self.itype_incdx, 2 ], + # addx dst, dst -> rlax dst + [ lambda: same_op(insn.Op1, insn.Op2), self.itype_rlax, 1 ], + ], + self.itype_xor: [ + # xor #-1, dst -> inv dst + [ lambda: is_imm_op(insn.Op1, -1), self.itype_inv, 2 ], + ], + self.itype_xorx: [ + # xorx #-1, dst -> invx dst + [ lambda: is_imm_op(insn.Op1, -1), self.itype_invx, 2 ], + ], + self.itype_cmp: [ + # cmp #0, dst -> tst dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_tst, 2 ], + ], + self.itype_cmpx: [ + # cmpx #0, dst -> tstx dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_tstx, 2 ], + ], + self.itype_cmpa: [ + # cmpa #0, dst -> tsta dst + [ lambda: is_imm_op(insn.Op1, 0), self.itype_tsta, 2 ], + ], + } + + # instructions which should have no suffix + nosuff = [self.itype_ret, self.itype_reta, self.itype_br, self.itype_bra, + self.itype_clrc, self.itype_clrn, self.itype_clrz, self.itype_dint, + self.itype_eint, self.itype_clrc, self.itype_nop, self.itype_pop, + self.itype_popa, self.itype_setc, self.itype_setn, self.itype_setz, ] + + if insn.itype in maptbl: + for m in maptbl[insn.itype]: + if m[0](): + # matched instruction; replace the itype + insn.itype = m[1] + if m[2] == 0: + # remove the operands + insn.Op1.type = o_void + elif m[2] == 2: + # replace first operand with the second + insn.Op1.assign(insn.Op2) + # remove the second operand, if any + insn.Op2.type = o_void + # remove suffix if necessary + if insn.itype in nosuff and insn.auxpref == AUX_WORD: + insn.auxpref = 0 + break + + # ---------------------------------------------------------------------- + def ev_ana_insn(self, insn): + """ + Decodes an instruction into 'insn'. + Returns: insn.size (=the size of the decoded instruction) or zero + """ + if (insn.ea & 1) != 0: + return 0 + w = insn.get_next_word() + extw = None + if BITS(w, 15, 11) == 0b00011: + # operand extension word + extw = w + w = insn.get_next_word() + if BITS(w, 15, 10) == 0b000100: + self.decode_format_II(insn, w, extw) + elif BITS(w, 15, 10) == 0b000101: + if extw: return 0 + self.decode_430x_pushm(insn, w) + elif BITS(w, 15, 13) == 1: # 001 + if extw: return 0 + self.decode_jump(insn, w) + elif BITS(w, 15, 12) == 0: + if extw: return 0 + self.decode_430x_mova(insn, w) + else: + self.decode_format_I(insn, w, extw) + + self.simplify(insn) + return insn.itype != self.itype_null + + # ---------------------------------------------------------------------- + def init_instructions(self): + Instructions = [] + i = 0 + for x in self.instruc: + if x['name'] != '': + setattr(self, 'itype_' + x['name'], i) + else: + setattr(self, 'itype_null', i) + i += 1 + + # icode of the last instruction + 1 + self.instruc_end = len(self.instruc) + + # Icode of return instruction. It is ok to give any of possible return + # instructions + self.icode_return = self.itype_reti + + # ---------------------------------------------------------------------- + def init_registers(self): + """This function parses the register table and creates corresponding ireg_XXX constants""" + + # Registers definition + self.reg_names = [ + # General purpose registers + "PC", # R0 + "SP", # R1 + "SR", # R2, CG1 + "R3", # CG2 + "R4", + "R5", + "R6", + "R7", + "R8", + "R9", + "R10", + "R11", + "R12", + "R13", + "R14", + "R15", + # Fake segment registers + "CS", + "DS" + ] + + # Create the ireg_XXXX constants + for i in range(len(self.reg_names)): + setattr(self, 'ireg_' + self.reg_names[i], i) + + # Segment register information (use virtual CS and DS registers if your + # processor doesn't have segment registers): + self.reg_first_sreg = self.ireg_CS + self.reg_last_sreg = self.ireg_DS + + # number of CS register + self.reg_code_sreg = self.ireg_CS + + # number of DS register + self.reg_data_sreg = self.ireg_DS + + # ---------------------------------------------------------------------- + def __init__(self): + processor_t.__init__(self) + self.init_instructions() + self.init_registers() + +# ---------------------------------------------------------------------- +# Every processor module script must provide this function. +# It should return a new instance of a class derived from processor_t +def PROCESSOR_ENTRY(): + return msp430_processor_t() diff --git a/idasdk76/module/script/proctemplate.py b/idasdk76/module/script/proctemplate.py new file mode 100644 index 0000000..a1d47d5 --- /dev/null +++ b/idasdk76/module/script/proctemplate.py @@ -0,0 +1,1052 @@ +# ---------------------------------------------------------------------- +# Processor module template script +# (c) Hex-Rays +import sys +import idaapi +from idaapi import * +import ida_pro + +if sys.version_info.major < 3: + range = xrange + +retcode_0 = 0xC3 +retcode_1 = 0xC2 +g_retcodes = [retcode_0, retcode_1] + +# ---------------------------------------------------------------------- +class sample_processor_t(idaapi.processor_t): + """ + Processor module classes must derive from idaapi.processor_t + + A processor_t instance is, conceptually, both an IDP_Hooks and + an IDB_Hooks. This means any callback from those two classes + can be implemented. Below, you'll find a handful of those + as an example (e.g., ev_out_header(), ev_newfile(), ...) + Also note that some IDP_Hooks callbacks must be implemented + """ + + # IDP id ( Numbers above 0x8000 are reserved for the third-party modules) + id = 0x8000 + 1 + + # Processor features + flag = PR_ASSEMBLE | PR_SEGS | PR_DEFSEG32 | PR_USE32 | PRN_HEX | PR_RNAMESOK + + # Number of bits in a byte for code segments (usually 8) + # IDA supports values up to 32 bits (64 for IDA64) + cnbits = 8 + + # Number of bits in a byte for non-code segments (usually 8) + # IDA supports values up to 32 bits (64 for IDA64) + dnbits = 8 + + # short processor names + # Each name should be shorter than 9 characters + psnames = ['myproc'] + + # long processor names + # No restriction on name lengthes. + plnames = ['My processor module'] + + # register names + reg_names = [ + # General purpose registers + "SP", # aka R0 + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + # VM registers + "FLAGS", # 0 + "IP", # 1 + "VM2", + "VM3", + "VM4", + "VM5", + "VM6", + "VM7", + # Fake segment registers + "CS", + "DS" + ] + + # number of registers (optional: deduced from the len(reg_names)) + regs_num = len(reg_names) + + # Segment register information (use virtual CS and DS registers if your + # processor doesn't have segment registers): + reg_first_sreg = 16 # index of CS + reg_last_sreg = 17 # index of DS + + # size of a segment register in bytes + segreg_size = 0 + + # You should define 2 virtual segment registers for CS and DS. + + # number of CS/DS registers + reg_code_sreg = 16 + reg_data_sreg = 17 + + # Array of typical code start sequences (optional) + codestart = ['\x55\x8B', '\x50\x51'] + + # Array of 'return' instruction opcodes (optional) + retcodes = g_retcodes + + # Array of instructions. Since this is only a template, + # this list will be extremely limited. + instruc = [ + {'name': 'ADD', 'feature': CF_USE1 | CF_CHG1 | CF_USE2}, # ADD <reg>, <#imm> -- opcodes [0x00 -> 0x7F] + {'name': 'MOV', 'feature': CF_USE1 | CF_CHG1 | CF_USE2}, # MOV <reg>, <reg> -- opcodes [0x80 -> 0xEF] (but retcodes) + {'name': 'RET', 'feature': 0}, # RET -- opcodes 0xC2, 0xC3 + {'name': 'JMP', 'feature': CF_USE1 | CF_JUMP}, # JMP -- opcodes [0xF0 -> 0xFF] + ] + + # icode of the first instruction + instruc_start = 0 + + # icode of the last instruction + 1 + instruc_end = len(instruc) + + # Size of long double (tbyte) for this processor (meaningful only if ash.a_tbyte != NULL) (optional) + tbyte_size = 0 + + # + # Number of digits in floating numbers after the decimal point. + # If an element of this array equals 0, then the corresponding + # floating point data is not used for the processor. + # This array is used to align numbers in the output. + # real_width[0] - number of digits for short floats (only PDP-11 has them) + # real_width[1] - number of digits for "float" + # real_width[2] - number of digits for "double" + # real_width[3] - number of digits for "long double" + # Example: IBM PC module has { 0,7,15,19 } + # + # (optional) + real_width = (0, 7, 15, 0) + + # icode (or instruction number) of return instruction. It is ok to give any of possible return + # instructions + icode_return = 5 + + # only one assembler is supported + assembler = { + # flag + 'flag' : ASH_HEXF3 | AS_UNEQU | AS_COLON | ASB_BINF4 | AS_N2CHR, + + # user defined flags (local only for IDP) (optional) + 'uflag' : 0, + + # Assembler name (displayed in menus) + 'name': "My processor module bytecode assembler", + + # array of automatically generated header lines they appear at the start of disassembled text (optional) + 'header': ["Line1", "Line2"], + + # org directive + 'origin': "org", + + # end directive + 'end': "end", + + # comment string (see also cmnt2) + 'cmnt': ";", + + # ASCII string delimiter + 'ascsep': "\"", + + # ASCII char constant delimiter + 'accsep': "'", + + # ASCII special chars (they can't appear in character and ascii constants) + 'esccodes': "\"'", + + # + # Data representation (db,dw,...): + # + # ASCII string directive + 'a_ascii': "db", + + # byte directive + 'a_byte': "db", + + # word directive + 'a_word': "dw", + + # remove if not allowed + 'a_dword': "dd", + + # remove if not allowed + 'a_qword': "dq", + + # remove if not allowed + 'a_oword': "xmmword", + + # remove if not allowed + 'a_yword': "ymmword", + + # float; 4bytes; remove if not allowed + 'a_float': "dd", + + # double; 8bytes; NULL if not allowed + 'a_double': "dq", + + # long double; NULL if not allowed + 'a_tbyte': "dt", + + # packed decimal real; remove if not allowed (optional) + 'a_packreal': "", + + # array keyword. the following + # sequences may appear: + # #h - header + # #d - size + # #v - value + # #s(b,w,l,q,f,d,o) - size specifiers + # for byte,word, + # dword,qword, + # float,double,oword + 'a_dups': "#d dup(#v)", + + # uninitialized data directive (should include '%s' for the size of data) + 'a_bss': "%s dup ?", + + # 'equ' Used if AS_UNEQU is set (optional) + 'a_equ': ".equ", + + # 'seg ' prefix (example: push seg seg001) + 'a_seg': "seg", + + # current IP (instruction pointer) symbol in assembler + 'a_curip': "$", + + # "public" name keyword. NULL-gen default, ""-do not generate + 'a_public': "public", + + # "weak" name keyword. NULL-gen default, ""-do not generate + 'a_weak': "weak", + + # "extrn" name keyword + 'a_extrn': "extrn", + + # "comm" (communal variable) + 'a_comdef': "", + + # "align" keyword + 'a_align': "align", + + # Left and right braces used in complex expressions + 'lbrace': "(", + 'rbrace': ")", + + # % mod assembler time operation + 'a_mod': "%", + + # & bit and assembler time operation + 'a_band': "&", + + # | bit or assembler time operation + 'a_bor': "|", + + # ^ bit xor assembler time operation + 'a_xor': "^", + + # ~ bit not assembler time operation + 'a_bnot': "~", + + # << shift left assembler time operation + 'a_shl': "<<", + + # >> shift right assembler time operation + 'a_shr': ">>", + + # size of type (format string) (optional) + 'a_sizeof_fmt': "size %s", + + 'flag2': 0, + + # comment close string (optional) + # this is used to denote a string which closes comments, for example, if the comments are represented with (* ... *) + # then cmnt = "(*" and cmnt2 = "*)" + 'cmnt2': "", + + # low8 operation, should contain %s for the operand (optional fields) + 'low8': "", + 'high8': "", + 'low16': "", + 'high16': "", + + # the include directive (format string) (optional) + 'a_include_fmt': "include %s", + + # if a named item is a structure and displayed in the verbose (multiline) form then display the name + # as printf(a_strucname_fmt, typename) + # (for asms with type checking, e.g. tasm ideal) + # (optional) + 'a_vstruc_fmt': "", + + # 'rva' keyword for image based offsets (optional) + # (see nalt.hpp, REFINFO_RVA) + 'a_rva': "rva" + } # Assembler + + def regname2index(self, regname): + for idx in range(len(self.reg_names)): + if regname == self.reg_names[idx]: + return idx + return -1 + + + OPTION_KEY_OPERAND_SEPARATOR = "PROCTEMPLATE_OPERAND_SEPARATOR" + OPTION_KEY_OPERAND_SPACES = "PROCTEMPLATE_OPERAND_SPACES" + + + # ---------------------------------------------------------------------- + def __init__(self): + idaapi.processor_t.__init__(self) + self.operand_separator = ',' + self.operand_spaces = 1 + + def asm_out_func_header(self, ctx, func_ea): + """generate function header lines""" + pass + + def asm_out_func_footer(self, ctx, func_ea): + """generate function footer lines""" + pass + + def asm_get_type_name(self, flag, ea_or_id): + """ + Get name of type of item at ea or id. + (i.e. one of: byte,word,dword,near,far,etc...) + """ + if is_code(flag): + pfn = get_func(ea_or_id) + # return get func name + elif is_word(flag): + return "word" + return "" + + # + # IDP_Hooks callbacks (the first 4 are mandatory) + # + + def ev_emu_insn(self, insn): + """ + Emulate instruction, create cross-references, plan to analyze + subsequent instructions, modify flags etc. Upon entrance to this function + all information about the instruction is in 'insn' structure. + If zero is returned, the kernel will delete the instruction. + """ + if insn.itype == 4: # JMP + add_cref(insn.ea, insn.Op1.addr, fl_JN) + elif insn.itype != 2: # 2 == RET, 4 == JMP + add_cref(insn.ea, insn.ea + insn.size, fl_F) + return True + + def ev_out_operand(self, ctx, op): + """ + Generate text representation of an instructon operand. + This function shouldn't change the database, flags or anything else. + All these actions should be performed only by u_emu() function. + The output text is placed in the output buffer initialized with init_output_buffer() + This function uses out_...() functions from ua.hpp to generate the operand text + Returns: success + """ + if op.type == o_reg: + ctx.out_register(self.reg_names[op.reg]) + elif op.type == o_imm: + ctx.out_value(op, OOFW_IMM) + elif op.type == o_near: + ctx.out_name_expr(op, op.addr, BADADDR) + else: + return False + return True + + def ev_out_insn(self, ctx): + """ + Generate text representation of an instruction in 'ctx.insn' structure. + This function shouldn't change the database, flags or anything else. + All these actions should be performed only by u_emu() function. + Returns: nothing + """ + ctx.out_mnemonic() + + for i in range(0, 2): + op = ctx.insn[i] + if op.type == o_void: + break; + if i > 0: + ctx.out_symbol(self.operand_separator) + for _ in range(self.operand_spaces): + ctx.out_char(' ') + ctx.out_one_operand(i) + + ctx.set_gen_cmt() + ctx.flush_outbuf() + return True + + def ev_ana_insn(self, insn): + """ + Decodes an instruction into insn + Returns: insn.size (=the size of the decoded instruction) or zero + """ + b = insn.get_next_byte() + if b < 0x80: # ADD + insn.itype = 0 + insn.Op1.type = o_reg + insn.Op1.reg = b & 0xF + insn.Op2.type = o_imm + insn.Op2.dtype = dt_byte + insn.Op2.value = (b >> 4) & 0xF + elif b in g_retcodes: # RET + insn.itype = 2 + elif b < 0xF0: # MOV + insn.itype = 1 + insn.Op1.type = o_reg + insn.Op1.reg = b & 0xF + insn.Op2.type = o_reg + insn.Op2.value = (b >> 4) & 0xF + else: + insn.itype = 3 + insn.Op1.type = o_near + insn.Op1.dtype = dt_dword + insn.Op1.addr = insn.ea + (b & 0xF) + + return True + + # The following callbacks are optional. + # *** Please remove the callbacks that you don't plan to implement *** + + def ev_out_header(self, ctx): + """function to produce start of disassembled text""" + return 0 + + def ev_out_footer(self, ctx): + """function to produce end of disassembled text""" + return 0 + + def ev_out_segstart(self, ctx, segment): + """function to produce start of segment""" + return 0 + + def ev_out_segend(self, ctx, segment): + """function to produce end of segment""" + return 0 + + def ev_out_assumes(self, ctx): + """function to produce assume directives""" + return 0 + + def ev_term(self): + """called when the processor module is unloading""" + return 0 + + def ev_setup_til(self): + """Setup default type libraries (called after loading a new file into the database) + The processor module may load tils, setup memory model and perform other actions required to set up the type system + """ + return 0 + + def ev_newprc(self, nproc, keep_cfg): + """ + Before changing proccesor type + nproc - processor number in the array of processor names + return >=0-ok,<0-prohibit + """ + return 0 + + def ev_newfile(self, filename): + """A new file is loaded (already)""" + return 0 + + def ev_oldfile(self, filename): + """An old file is loaded (already)""" + return 0 + + def ev_newbinary(self, filename, fileoff, basepara, binoff, nbytes): + """ + Before loading a binary file + args: + filename - binary file name + fileoff - offset in the file + basepara - base loading paragraph + binoff - loader offset + nbytes - number of bytes to load + """ + return 0 + + def ev_undefine(self, ea): + """ + An item in the database (insn or data) is being deleted + @param args: ea + @return: >=0-ok, <0 - the kernel should stop + if the return value is not negative: + bit0 - ignored + bit1 - do not delete srareas at the item end + """ + return 0 + + def ev_endbinary(self, ok): + """ + After loading a binary file + args: + ok - file loaded successfully? + """ + return 0 + + def ev_assemble(self, ea, cs, ip, use32, line): + """ + Assemble an instruction + (make sure that PR_ASSEMBLE flag is set in the processor flags) + (display a warning if an error occurs) + args: + ea - linear address of instruction + cs - cs of instruction + ip - ip of instruction + use32 - is 32bit segment? + line - line to assemble + returns the opcode string, or None + """ + return 0 + + def ev_out_data(self, ctx, analyze_only): + """ + Generate text represenation of data items + This function MAY change the database and create cross-references, etc. + """ + ctx.out_data(analyze_only) + return 1 + + def ev_cmp_operands(self, op1, op2): + """ + Compare instruction operands. + Returns 1-equal, -1-not equal, 0-not implemented + """ + return 0 + + def ev_can_have_type(self, op): + """ + Can the operand have a type as offset, segment, decimal, etc. + (for example, a register AX can't have a type, meaning that the user can't + change its representation. see bytes.hpp for information about types and flags) + Returns: 0-unknown, <0-no, 1-yes + """ + return 0 + + def ev_set_idp_options(self, keyword, value_type, value, idb_loaded): + """ + Set IDP-specific option + args: + keyword - the option name + or empty string (check value_type when 0 below) + value_type - one of + IDPOPT_STR string constant + IDPOPT_NUM number + IDPOPT_BIT zero/one + IDPOPT_I64 64bit number + 0 -> You should display a dialog to configure the processor module + value - the actual value + idb_loaded - true if the ev_oldfile/ev_newfile events have been generated + Returns: + 1 ok + 0 not implemented + -1 error + """ + if keyword == self.OPTION_KEY_OPERAND_SEPARATOR and value_type == ida_idp.IDPOPT_STR: + self.operand_separator = value + return 1 + if keyword == self.OPTION_KEY_OPERAND_SPACES and value_type == ida_idp.IDPOPT_NUM: + self.operand_spaces = value + return 1 + else: + return -1 + + def ev_gen_map_file(self, nlines, qfile): + """ + Generate map file. If this function is absent then the kernel will create the map file. + This function returns number of lines in output file. + 0 - not implemented, 1 - ok, -1 - write error + """ + import ida_fpro + qfile = ida_fpro.qfile_t_from_fp(fp) + lines = ["Line 1\n", "Line 2\n!"] + ida_pro.int_pointer.frompointer(nlines).assign(len(lines)) + for l in lines: + qfile.write(l) + return 1 + + def ev_create_func_frame(self, pfn): + """ + Create a function frame for a newly created function. + Set up frame size, its attributes etc. + """ + return 0 + + def ev_is_far_jump(self, icode): + """ + Is indirect far jump or call instruction? + meaningful only if the processor has 'near' and 'far' reference types + """ + return 0 + + def ev_is_align_insn(self, ea): + """ + Is the instruction created only for alignment purposes? + Returns: number of bytes in the instruction + """ + return 0 + + def ev_out_special_item(self, ctx, segtype): + """ + Generate text representation of an item in a special segment + i.e. absolute symbols, externs, communal definitions etc. + Returns: 1-ok, 0-not implemented + """ + return 0 + + def ev_get_frame_retsize(self, frsize, pfn): + """ + Get size of function return address in bytes + If this function is absent, the kernel will assume + 4 bytes for 32-bit function + 2 bytes otherwise + """ + ida_pro.int_pointer.frompointer(frsize).assign(2) + return 1 + + def ev_is_switch(self, swi, insn): + """ + Find 'switch' idiom at instruction 'insn'. + Fills 'swi' structure with information + """ + return 0 + + def ev_is_sp_based(self, mode, insn, op): + """ + Check whether the operand is relative to stack pointer or frame pointer. + This function is used to determine how to output a stack variable + This function may be absent. If it is absent, then all operands + are sp based by default. + Define this function only if some stack references use frame pointer + instead of stack pointer. + returns flags: + OP_FP_BASED operand is FP based + OP_SP_BASED operand is SP based + OP_SP_ADD operand value is added to the pointer + OP_SP_SUB operand value is substracted from the pointer + """ + ida_pro.int_pointer.frompointer(mode).assign(idaapi.OP_FP_BASED) + return 1 + + def ev_get_autocmt(self, insn): + """ + Get instruction comment. 'insn' describes the instruction in question + @return: None or the comment string + """ + return "comment for %d" % insn.itype + + def ev_create_switch_xrefs(self, jumpea, swi): + """Create xrefs for a custom jump table + @param jumpea: address of the jump insn + @param swi: switch information + """ + return 0 + + def ev_calc_step_over(self, target, ip): + ida_pro.ea_pointer.frompointer(target).assign(idaapi.BADADDR) + return 1 + + def ev_may_be_func(self, insn, state): + """ + can a function start here? + the instruction is in 'insn' + arg: state -- autoanalysis phase + state == 0: creating functions + == 1: creating chunks + returns: probability 0..100 + """ + return 0 + + def ev_str2reg(self, regname): + """ + Convert a register name to a register number + args: regname + Returns: register number or -1 if not avail + The register number is the register index in the reg_names array + Most processor modules do not need to implement this callback + It is useful only if ph.reg_names[reg] does not provide + the correct register names + """ + r = self.regname2index(regname) + if r < 0: + return 0 + else: + return r + 1 + + def ev_is_sane_insn(self, insn, no_crefs): + """ + is the instruction sane for the current file type? + args: no_crefs + 1: the instruction has no code refs to it. + ida just tries to convert unexplored bytes + to an instruction (but there is no other + reason to convert them into an instruction) + 0: the instruction is created because + of some coderef, user request or another + weighty reason. + The instruction is in 'insn' + returns: >=0-ok, <0-no, the instruction isn't + likely to appear in the program + """ + return -1 + + def ev_func_bounds(self, code, func_ea, max_func_end_ea): + ida_pro.int_pointer.frompointer(code).assign(FIND_FUNC_OK) + return 1 + + def ev_init(self, idp_file): + return 0 + + def ev_out_label(self, ctx, label): + """ + The kernel is going to generate an instruction label line + or a function header. + args: + ctx - output context + label - label to output + If returns value <0, then the kernel should not generate the label + """ + return 0 + + def ev_rename(self, ea, new_name): + """ + The kernel is going to rename a byte + args: + ea - + new_name - + If returns value <0, then the kernel should not rename it + """ + return 0 + + def ev_may_show_sreg(self, ea): + """ + The kernel wants to display the segment registers + in the messages window. + args: + ea + if this function returns <0 + then the kernel will not show + the segment registers. + (assuming that the module have done it) + """ + return 0 + + def ev_coagulate(self, start_ea): + """ + Try to define some unexplored bytes + This notification will be called if the + kernel tried all possibilities and could + not find anything more useful than to + convert to array of bytes. + The module can help the kernel and convert + the bytes into something more useful. + args: + start_ea - + returns: number of converted bytes + """ + return 0 + + def ev_is_call_insn(self, insn): + """ + Is the instruction a "call"? + args + insn - instruction + returns: 0-unknown, <0-no, 1-yes + """ + return 0 + + def ev_is_ret_insn(self, insn, strict): + """ + Is the instruction a "return"? + insn - instruction + strict - 1: report only ret instructions + 0: include instructions like "leave" + which begins the function epilog + returns: 0-unknown, <0-no, 1-yes + """ + return 0 + + def ev_is_alloca_probe(self, ea): + """ + Does the function at 'ea' behave as __alloca_probe? + args: + ea + returns: 1-yes, 0-false + """ + return 0 + + def ev_gen_src_file_lnnum(self, ctx, filename, lnnum): + """ + Callback: generate analog of + #line "file.c" 123 + directive. + args: + ctx - output context + file - source file (may be NULL) + lnnum - line number + returns: 1-directive has been generated + """ + return 0 + + def ev_is_indirect_jump(self, insn): + """ + Callback: determine if instruction is an indrect jump + If CF_JUMP bit cannot describe all jump types + jumps, please define this callback. + input: insn structure contains the current instruction + returns: 0-use CF_JUMP, 1-no, 2-yes + """ + return 0 + + def ev_validate_flirt_func(self, ea, funcname): + """ + flirt has recognized a library function + this callback can be used by a plugin or proc module + to intercept it and validate such a function + args: + start_ea + funcname + returns: -1-do not create a function, + 0-function is validated + """ + return 0 + + def ev_set_proc_options(self, options, confidence): + """ + called if the user specified an option string in the command line: + -p<processor name>:<options> + can be used for e.g. setting a processor subtype + also called if option string is passed to set_processor_type() + and IDC's set_processor_type() + args: + options + confidence - 0: loader's suggestion, + 1: user's decision + returns: <0 - bad option string + """ + return 0 + + def ev_creating_segm(self, s): + return 0 + + def ev_auto_queue_empty(self, atype): + return 0 + + def ev_gen_regvar_def(self, ctx, v): + return 0 + + def ev_is_basic_block_end(self, insn, call_insn_stops_block): + """ + Is the current instruction end of a basic block? + This function should be defined for processors + with delayed jump slots. The current instruction + is stored in 'insn' + args: + call_insn_stops_block + returns: 0-unknown, -1-no, 1-yes + """ + return 0 + + def ev_moving_segm(self, segment, to, flags): + """ + May the kernel move the segment? + returns: 0-yes, <0-the kernel should stop + """ + return 0 + + def ev_segm_moved(self, from_ea, to_ea, size, changed_netdelta): + """ + A segment is moved + """ + return 0 + + def ev_verify_noreturn(self, pfn): + """ + The kernel wants to set 'noreturn' flags for a function + Returns: 0-ok, <0-do not set 'noreturn' flag + """ + return 0 + + def ev_treat_hindering_item(self, hindering_item_ea, new_item_flags, new_item_ea, new_item_length): + """ + An item hinders creation of another item + args: + hindering_item_ea + new_item_flags + new_item_ea + new_item_length + Returns: 0-no reaction, <0-the kernel may delete the hindering item + """ + return 0 + + def ev_coagulate_dref(self, from_ea, to_ea, may_define, code_ea): + """ + data reference is being analyzed + args: + from_ea, to_ea, may_define, code_ea + plugin may correct code_ea (e.g. for thumb mode refs, we clear the last bit) + Returns: new code_ea or -1 - cancel dref analysis + """ + if False: # some condition + ida_pro.ea_pointer.frompointer(code_ea).assign(0x1337) + return 0 + + # + # IDB_Hooks callbacks + # + + def savebase(self): + """The database is being saved. Processor module should save its local data""" + return 0 + + def closebase(self): + """ + The database will be closed now + """ + return 0 + + def idasgn_loaded(self, short_sig_name): + """ + FLIRT signature have been loaded for normal processing + (not for recognition of startup sequences) + args: + short_sig_name + """ + return 0 + + def auto_empty(self): + """ + Info: all analysis queues are empty. + This callback is called once when the + initial analysis is finished. If the queue is + not empty upon the return from this callback, + it will be called later again + """ + return 0 + + def kernel_config_loaded(self, pass_number): + """ + This callback is called when ida.cfg is parsed + """ + return 0 + + def auto_empty_finally(self): + """ + Info: all analysis queues are empty definitively + """ + return 0 + + def determined_main(self, main_ea): + """ + The main() function has been determined + """ + return 0 + + def sgr_changed(self, start_ea, end_ea, regnum, value, old_value, tag): + return 0 + + def compiler_changed(self, adjust_inf_fields): + return 0 + + def make_code(self, insn): + """ + An instruction is being created + args: + insn + returns: 0-ok, <0-the kernel should stop + """ + return 0 + + def make_data(self, ea, flags, tid, size): + """ + A data item is being created + args: + ea + flags + tid + size + returns: 0-ok, <0-the kernel should stop + """ + return 0 + + def notify_verify_sp(self, pfn): + """ + All function instructions have been analyzed + Now the processor module can analyze the stack pointer + for the whole function + Returns: 0-ok, <0-bad stack pointer + """ + return 0 + + def renamed(self, ea, new_name, is_local_name): + """ + The kernel has renamed a byte + args: + ea + new_name + is_local_name + Returns: nothing. See also the 'rename' event + """ + return 0 + + def set_func_start(self, pfn, new_ea): + """ + Function chunk start address will be changed + args: + pfn + new_ea + Returns: 0-ok,<0-do not change + """ + return 0 + + def set_func_end(self, pfn, new_end_ea): + """ + Function chunk end address will be changed + args: + pfn + new_end_ea + Returns: 0-ok,<0-do not change + """ + return 0 + + def func_added(self, pfn): + """ + The kernel has added a function. + @param pfn: function + """ + return 0 + + def deleting_func(self, pfn): + """ + The kernel is about to delete a function + @param func: function + """ + return 0 + + def translate(self, base, offset): + """ + Translation function for offsets + Currently used in the offset display functions + to calculate the referenced address + Returns: ea_t + """ + return BADADDR + +# ---------------------------------------------------------------------- +# Every processor module script must provide this function. +# It should return a new instance of a class derived from idaapi.processor_t +def PROCESSOR_ENTRY(): + return sample_processor_t() diff --git a/idasdk76/module/sparc/notify_codes.hpp b/idasdk76/module/sparc/notify_codes.hpp new file mode 100644 index 0000000..27b09d1 --- /dev/null +++ b/idasdk76/module/sparc/notify_codes.hpp @@ -0,0 +1,39 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __SPARC_NOTIFY_CODES_HPP +#define __SPARC_NOTIFY_CODES_HPP + +#include <idp.hpp> + +//---------------------------------------------------------------------- +// The following events are supported by the SPARC module in the ph.notify() function +namespace sparc_module_t +{ + enum event_codes_t + { + ev_load_symbols = processor_t::ev_loader, + ev_set_v8, + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline void load_symbols(const char *fname) + { + processor_t::notify(idp_ev(ev_load_symbols), fname); + } + + inline void set_v8(bool is_v8) + { + processor_t::notify(idp_ev(ev_set_v8), is_v8); + } +} + +#endif // __SPARC_NOTIFY_CODES_HPP diff --git a/idasdk75/module/st20/ana.cpp b/idasdk76/module/st20/ana.cpp similarity index 100% rename from idasdk75/module/st20/ana.cpp rename to idasdk76/module/st20/ana.cpp diff --git a/idasdk75/module/st20/emu.cpp b/idasdk76/module/st20/emu.cpp similarity index 100% rename from idasdk75/module/st20/emu.cpp rename to idasdk76/module/st20/emu.cpp diff --git a/idasdk75/module/st20/ins.cpp b/idasdk76/module/st20/ins.cpp similarity index 100% rename from idasdk75/module/st20/ins.cpp rename to idasdk76/module/st20/ins.cpp diff --git a/idasdk76/module/st20/ins.hpp b/idasdk76/module/st20/ins.hpp new file mode 100644 index 0000000..1fdcd6f --- /dev/null +++ b/idasdk76/module/st20/ins.hpp @@ -0,0 +1,243 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ +ST20_null = 0, // Unknown Operation + +// C1 instructions + +ST20_adc, // add constant +ST20_add, // add +ST20_addc, // add with carry +ST20_ajw, // adjust work space +ST20_and, // and +ST20_arot, // anti-rotate stack +ST20_ashr, // arithmetic shift right +ST20_biquad, // biquad IIR filter step +ST20_bitld, // load bit +ST20_bitmask, // create bit mask +ST20_bitst, // store bit +ST20_breakpoint, // breakpoint +ST20_cj, // conditional jump +ST20_dequeue, // dequeue a process +ST20_divstep, // divide step +ST20_dup, // duplicate +ST20_ecall, // exception call +ST20_enqueue, // enqueue a process +ST20_eqc, // equals constant +ST20_eret, // exception return +ST20_fcall, // function call +ST20_gajw, // general adjust workspace +ST20_gt, // greater than +ST20_gtu, // greater than unsigned +ST20_io, // input/output +ST20_j, // jump +ST20_jab, // jump absolute +ST20_lbinc, // load byte and increment +ST20_ldc, // load constant +ST20_ldl, // load local +ST20_ldlp, // load local pointer +ST20_ldnl, // load non-local +ST20_ldnlp, // load non-local pointer +ST20_ldpi, // load pointer to instruction +ST20_ldprodid, // load product identity +ST20_ldtdesc, // load task descriptor +ST20_lsinc, // load sixteen and increment +ST20_lsxinc, // load sixteen sign extended and increment +ST20_lwinc, // load word and increment +ST20_mac, // multiply accumulate +ST20_mul, // multiply +ST20_nfix, // negative prefix +ST20_nop, // no operation +ST20_not, // bitwise not +ST20_opr, // operate +ST20_or, // or +ST20_order, // order +ST20_orderu, // unsigned order +ST20_pfix, // prefix +ST20_rev, // reverse +ST20_rmw, // read modify write +ST20_rot, // rotate stack +ST20_run, // run process +ST20_saturate, // saturate +ST20_sbinc, // store byte and increment +ST20_shl, // shift left +ST20_shr, // shift right +ST20_signal, // signal +ST20_smacinit, // initialize short multiply accumulate loop +ST20_smacloop, // short multiply accumulate loop +ST20_smul, // short multiply +ST20_ssinc, // store sixteen and increment +ST20_statusclr, // clear bits in status register +ST20_statusset, // set bits in status register +ST20_statustst, // test status register +ST20_stl, // store local +ST20_stnl, // store non-local +ST20_stop, // stop process +ST20_sub, // subtract +ST20_subc, // subtract with carry +ST20_swap32, // byte swap 32 +ST20_swinc, // store word and increment +ST20_timeslice, // timeslice +ST20_umac, // unsigned multiply accumulate +ST20_unsign, // unsign argument +ST20_wait, // wait +ST20_wsub, // word subscript +ST20_xbword, // sign extend byte to word +ST20_xor, // exclusive or +ST20_xsword, // sign extend sixteen to word + +// C2-C4 instructions + +ST20_alt, // alt start +ST20_altend, // alt end +ST20_altwt, // alt wait +ST20_bcnt, // byte count +ST20_bitcnt, // count bits set in word +ST20_bitrevnbits, // reverse bottom n bits in word +ST20_bitrevword, // reverse bits in word +ST20_bsub, // byte subscript +ST20_call, // call +ST20_causeerror, // cause error +ST20_cb, // check byte +ST20_cbu, // check byte unsigned +ST20_ccnt1, // check count from 1 +ST20_cflerr, // check floating point error +ST20_cir, // check in range +ST20_ciru, // check in range unsigned +ST20_clockdis, // clock disable +ST20_clockenb, // clock enable +ST20_clrhalterr, // clear halt-on error flag +ST20_crcbyte, // calculate CRC on byte +ST20_crcword, // calculate CRC on word +ST20_cs, // check sixteen +ST20_csngl, // check single +ST20_csu, // check sixteen unsigned +ST20_csub0, // check subscript from 0 +ST20_cword, // check word +ST20_devlb, // device load byte +ST20_devls, // device load sixteen +ST20_devlw, // device load word +ST20_devmove, // device move +ST20_devsb, // device store byte +ST20_devss, // device store sixteen +ST20_devsw, // device store word +ST20_diff, // difference +ST20_disc, // disable channel +ST20_diss, // disable skip +ST20_dist, // disable timer +ST20_div, // divide +ST20_enbc, // enable channel +ST20_enbs, // enable skip +ST20_enbt, // enable timer +ST20_endp, // end process +ST20_fmul, // fractional multiply +ST20_fptesterr, // test for FPU error +ST20_gcall, // general call +ST20_gintdis, // general interrupt disable +ST20_gintenb, // general interrupt enable +ST20_in, // input message +ST20_insertqueue, // insert at front of scheduler queue +ST20_intdis, // (localised) interrupt disable +ST20_intenb, // (localised) interrupt enable +ST20_iret, // interrupt return +ST20_ladd, // long add +ST20_lb, // load byte +ST20_lbx, // load byte and sign extend +ST20_ldclock, // load clock +ST20_lddevid, // load device identity +ST20_ldiff, // long diff +ST20_ldinf, // load infinity +ST20_ldiv, // long divide +ST20_ldmemstartval, // load value of MemStart address +ST20_ldpri, // load current priority +ST20_ldshadow, // load shadow registers +ST20_ldtimer, // load timer +ST20_ldtraph, // load trap handler +ST20_ldtrapped, // load trapped process status +ST20_lend, // loop end +ST20_lmul, // long multiply +ST20_ls, // load sixteen +ST20_lshl, // long shift left +ST20_lshr, // long shift right +ST20_lsub, // long subtract +ST20_lsum, // long sum +ST20_lsx, // load sixteen and sign extend +ST20_mint, // minimum integer +ST20_move, // move message +ST20_move2dall, // 2D block copy +ST20_move2dinit, // initialize data for 2D block move +ST20_move2dnonzero, // 2D block copy non-zero bytes +ST20_move2dzero, // 2D block copy zero bytes +ST20_norm, // normalize +ST20_out, // output message +ST20_outbyte, // output byte +ST20_outword, // output word +ST20_pop, // pop processor stack +ST20_postnormsn, // post-normalize correction of single length fp number +ST20_prod, // product +ST20_reboot, // reboot +ST20_rem, // remainder +ST20_resetch, // reset channel +ST20_restart, // restart +ST20_ret, // return +ST20_roundsn, // round single length floating point number +ST20_runp, // run process +ST20_satadd, // saturating add +ST20_satmul, // saturating multiply +ST20_satsub, // saturating subtract +ST20_saveh, // save high priority queue registers +ST20_savel, // save low priority queue registers +ST20_sb, // store byte +ST20_seterr, // set error flags +ST20_sethalterr, // set halt-on error flag +ST20_settimeslice, // set timeslicing status +ST20_slmul, // signed long multiply +ST20_ss, // store sixteen +ST20_ssub, // sixteen subscript +ST20_startp, // start process +ST20_stclock, // store clock register +ST20_sthb, // store high priority back pointer +ST20_sthf, // store high priority front pointer +ST20_stlb, // store low priority back pointer +ST20_stlf, // store low priority front pointer +ST20_stoperr, // stop on error +ST20_stopp, // stop process +ST20_stshadow, // store shadow registers +ST20_sttimer, // store timer +ST20_sttraph, // store trap handler +ST20_sttrapped, // store trapped process +ST20_sulmul, // signed timer unsigned long multiply +ST20_sum, // sum +ST20_swapqueue, // swap scheduler queue +ST20_swaptimer, // swap timer queue +ST20_talt, // timer alt start +ST20_taltwt, // timer alt wait +ST20_testerr, // test error flag +ST20_testhalterr, // test halt-on error flag +ST20_testpranal, // test processor analysing +ST20_tin, // timer input +ST20_trapdis, // trap disable +ST20_trapenb, // trap enable +ST20_tret, // trap return +ST20_unpacksn, // unpack single length fp number +ST20_wcnt, // word count +ST20_wsubdb, // form double word subscript +ST20_xdble, // extend to double +ST20_xword, // extend word + +ST20_last, + + }; + +#endif diff --git a/idasdk76/module/st20/makefile b/idasdk76/module/st20/makefile new file mode 100644 index 0000000..09cc8a1 --- /dev/null +++ b/idasdk76/module/st20/makefile @@ -0,0 +1,57 @@ +PROC=st20 +CONFIGS=st20.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp st20.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp ins.hpp st20.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp st20.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp out.cpp st20.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp reg.cpp st20.hpp diff --git a/idasdk75/module/st20/out.cpp b/idasdk76/module/st20/out.cpp similarity index 100% rename from idasdk75/module/st20/out.cpp rename to idasdk76/module/st20/out.cpp diff --git a/idasdk76/module/st20/reg.cpp b/idasdk76/module/st20/reg.cpp new file mode 100644 index 0000000..c9abfe6 --- /dev/null +++ b/idasdk76/module/st20/reg.cpp @@ -0,0 +1,338 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2000 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "st20.hpp" +#include <diskio.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "Areg", // Evaluation stack register A + "Breg", // Evaluation stack register B + "Creg", // Evaluation stack register C + "Iptr", // Instruction pointer register, pointing to the next instruction to be executed + "Status", // Status register + "Wptr", // Work space pointer, pointing to the stack of the currently executing process + "Tdesc", // Task descriptor + "IOreg", // Input and output register + "cs", "ds", +}; + +//-------------------------------------------------------------------------- +static const uchar ret0[] = { 0x23, 0x22 }; // eret +static const uchar ret1[] = { 0x24, 0xF5 }; // altend +static const uchar ret2[] = { 0x20, 0xF3 }; // endp +static const uchar ret3[] = { 0x61, 0xFF }; // iret +static const uchar ret4[] = { 0x68, 0xFD }; // reboot +static const uchar ret5[] = { 0x62, 0xFE }; // restart +static const uchar ret6[] = { 0x22, 0xF0 }; // ret +static const uchar ret7[] = { 0x60, 0xFB }; // tret + +static const bytes_t retcodes1[] = +{ + { qnumber(ret0), ret0, }, + { 0, NULL } +}; + +static const bytes_t retcodes4[] = +{ + { qnumber(ret1), ret1, }, + { qnumber(ret2), ret2, }, + { qnumber(ret3), ret3, }, + { qnumber(ret4), ret4, }, + { qnumber(ret5), ret5, }, + { qnumber(ret6), ret6, }, + { qnumber(ret7), ret7, }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Hypthetical assembler +//----------------------------------------------------------------------- +static const asm_t hypasm = +{ + ASH_HEXF0 // 1234h + |ASD_DECF0 // 1234 + |ASB_BINF0 // 1010b + |ASO_OCTF0 // 1234o + |AS_COLON // create colons after data names + |AS_ONEDUP, // one array definition per line + 0, + "Hypthetical assembler", + 0, + NULL, // header lines + "org", // org + "end", // end + + ";", // comment string + '\"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + "dd", // double words + "dq", // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + "public", // "public" name keyword + NULL, // "weak" name keyword + "extrn", // "extrn" name keyword + // .extern directive requires an explicit object size + NULL, // "comm" (communal variable) + NULL, // get_type_name + NULL, // "align" keyword + '(', ')', // lbrace, rbrace + "mod", // mod + "&", // and + "|", // or + "^", // xor + "not", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &hypasm, NULL }; + +//-------------------------------------------------------------------------- +static const char cfgname[] = "st20.cfg"; + +//-------------------------------------------------------------------------- +const char *st20_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + if ( choose_ioport_device(&ioh.device, cfgname) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +void st20_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(st20_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi st20_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + clr_module_data(data_id); + break; + + case processor_t::ev_ending_undo: + procnum = ph.get_proc_index(); + if ( isc4() ) + ph.retcodes = retcodes4; + //fall through + case processor_t::ev_oldfile: + if ( msgid == processor_t::ev_oldfile ) + ioh.upgrade_device_index(); // upgrade device index from 0 to -1 + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + procnum = va_arg(va, int); + // bool keep_cfg = va_argi(va, bool); + if ( isc4() ) + ph.retcodes = retcodes4; + break; + + case processor_t::ev_is_jump_func: + { + const func_t *pfn = va_arg(va, const func_t *); + ea_t *jump_target = va_arg(va, ea_t *); + return is_jump_func(pfn, jump_target); + } + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + int no_crefs = va_arg(va, int); + return is_sane_insn(*insn, no_crefs) == 1 ? 1 : -1; + } + + case processor_t::ev_may_be_func: + { + const insn_t *insn = va_arg(va, insn_t *); + return may_be_func(*insn); + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st20_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st20_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + st20_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + st20_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return st20_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return st20_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "SGS-Thomson ST20:" +static const char *const shnames[] = { "st20", "st20c4", NULL }; +static const char *const lnames[] = +{ + FAMILY"SGS-Thomson ST20/C1", + "SGS-Thomson ST20/C2-C4", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_ST20, // id + // flag + PRN_HEX + | PR_RNAMESOK, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + cs, // first + ds, // last + 2, // size of a segment register + cs, ds, + + NULL, // No known code start sequences + retcodes1, + + ST20_null, + ST20_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + ST20_eret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/st20/st20.cfg b/idasdk76/module/st20/st20.cfg similarity index 100% rename from idasdk75/module/st20/st20.cfg rename to idasdk76/module/st20/st20.cfg diff --git a/idasdk76/module/st20/st20.hpp b/idasdk76/module/st20/st20.hpp new file mode 100644 index 0000000..f4b1d23 --- /dev/null +++ b/idasdk76/module/st20/st20.hpp @@ -0,0 +1,90 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2000 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _ST20_HPP +#define _ST20_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + +#define PROCMOD_NAME st20 +#define PROCMOD_NODE_NAME "$ st20" + +//------------------------------------------------------------------ +enum regnum_t +{ + Areg, // Evaluation stack register A + Breg, // Evaluation stack register B + Creg, // Evaluation stack register C + Iptr, // Instruction pointer register, pointing to the next instruction to be executed + Status, // Status register + Wptr, // Work space pointer, pointing to the stack of the currently executing process + Tdesc, // Task descriptor + IOreg, // Input and output register + cs, + ds, + +}; + +//------------------------------------------------------------------ +#define PROC_C1 0 +#define PROC_C4 1 + +//------------------------------------------------------------------ +struct st20_iohandler_t : public iohandler_t +{ + st20_iohandler_t(netnode &nn) : iohandler_t(nn) {} +}; + +struct st20_t : public procmod_t +{ + netnode helper; + st20_iohandler_t ioh = st20_iohandler_t(helper); + + int procnum; + bool flow; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *idaapi set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + + int st20_ana(insn_t *insn); + + int st20_emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &x, bool isload); + + bool isc4(void) { return procnum == PROC_C4; } + + void st20_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; + +ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea +//------------------------------------------------------------------ +void idaapi st20_header(outctx_t &ctx); + +void idaapi st20_segstart(outctx_t &ctx, segment_t *seg); +void idaapi st20_segend(outctx_t &ctx, segment_t *seg); +void idaapi st20_assumes(outctx_t &ctx); // function to produce assume directives + +int idaapi is_align_insn(ea_t ea); + +int is_jump_func(const func_t *pfn, ea_t *jump_target); +int is_sane_insn(const insn_t &insn, int nocrefs); +int may_be_func(const insn_t &insn); // can a function start here? + +#endif // _ST20_HPP diff --git a/idasdk75/module/st7/ana.cpp b/idasdk76/module/st7/ana.cpp similarity index 100% rename from idasdk75/module/st7/ana.cpp rename to idasdk76/module/st7/ana.cpp diff --git a/idasdk75/module/st7/emu.cpp b/idasdk76/module/st7/emu.cpp similarity index 100% rename from idasdk75/module/st7/emu.cpp rename to idasdk76/module/st7/emu.cpp diff --git a/idasdk75/module/st7/ins.cpp b/idasdk76/module/st7/ins.cpp similarity index 100% rename from idasdk75/module/st7/ins.cpp rename to idasdk76/module/st7/ins.cpp diff --git a/idasdk76/module/st7/ins.hpp b/idasdk76/module/st7/ins.hpp new file mode 100644 index 0000000..0243798 --- /dev/null +++ b/idasdk76/module/st7/ins.hpp @@ -0,0 +1,85 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ +ST7_null = 0, // Unknown Operation + +ST7_adc, // Add with Carry +ST7_add, // Addition +ST7_and, // Logical And +ST7_bcp, // Bit compare +ST7_bres, // Bit Reset +ST7_bset, // Bit Set +ST7_btjf, // Jump if bit is false +ST7_btjt, // Jump if bit is true +ST7_call, // Call subroutine +ST7_callr, // Call subroutine relative +ST7_clr, // Clear +ST7_cp, // Arithmetic Compare +ST7_cpl, // One Complement +ST7_dec, // Decrement +ST7_halt, // Halt +ST7_iret, // Interrupt routine return +ST7_inc, // Increment +ST7_jp, // Absolute Jump +ST7_jra, // Jump relative always +ST7_jrt, // Jump relative +ST7_jrf, // Never jump +ST7_jrih, // Jump if Port INT pin = 1 +ST7_jril, // Jump if Port INT pin = 0 +ST7_jrh, // Jump if H = 1 +ST7_jrnh, // Jump if H = 0 +ST7_jrm, // Jump if I = 1 +ST7_jrnm, // Jump if I = 0 +ST7_jrmi, // Jump if N = 1 (minus) +ST7_jrpl, // Jump if N = 0 (plus) +ST7_jreq, // Jump if Z = 1 (equal) +ST7_jrne, // Jump if Z = 0 (not equal) +ST7_jrc, // Jump if C = 1 +ST7_jrnc, // Jump if C = 0 +ST7_jrult, // Jump if C = 1 +ST7_jruge, // Jump if C = 0 +ST7_jrugt, // Jump if (C + Z = 0) +ST7_jrule, // Jump if (C + Z = 1) +ST7_ld, // Load +ST7_mul, // Multiply +ST7_neg, // Negate +ST7_nop, // No Operation +ST7_or, // OR Operation +ST7_pop, // Pop from the Stack +ST7_push, // Push onto the Stack +ST7_rcf, // Reset carry flag +ST7_ret, // Subroutine Return +ST7_rim, // Enable Interrupts +ST7_rlc, // Rotate left true +ST7_rrc, // Rotate right true +ST7_rsp, // Reset Stack Pointer +ST7_sbc, // Subtract with Carry +ST7_scf, // Set carry flag +ST7_sim, // Disable Interrupts +ST7_sla, // Shift left Arithmetic +ST7_sll, // Shift left Logic +ST7_srl, // Shift right Logic +ST7_sra, // Shift right Arithmetic +ST7_sub, // Substraction +ST7_swap, // SWAP nibbles +ST7_tnz, // Test for Neg & Zero +ST7_trap, // S/W trap +ST7_wfi, // Wait for Interrupt +ST7_xor, // Exclusive OR + +ST7_last, + + }; + +#endif diff --git a/idasdk76/module/st7/makefile b/idasdk76/module/st7/makefile new file mode 100644 index 0000000..8edb37f --- /dev/null +++ b/idasdk76/module/st7/makefile @@ -0,0 +1,57 @@ +PROC=st7 +CONFIGS=st7.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp st7.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp ins.hpp st7.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp st7.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp out.cpp st7.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp reg.cpp st7.hpp diff --git a/idasdk75/module/st7/out.cpp b/idasdk76/module/st7/out.cpp similarity index 100% rename from idasdk75/module/st7/out.cpp rename to idasdk76/module/st7/out.cpp diff --git a/idasdk76/module/st7/reg.cpp b/idasdk76/module/st7/reg.cpp new file mode 100644 index 0000000..df99ffc --- /dev/null +++ b/idasdk76/module/st7/reg.cpp @@ -0,0 +1,341 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2000 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "st7.hpp" +#include <diskio.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "a", "x", "y", "cc", "s", + "ds", "cs", +}; + +//-------------------------------------------------------------------------- +static const uchar retcode0[] = { 0x80 }; // iret 80 +static const uchar retcode1[] = { 0x81 }; // ret 81 +static const bytes_t retcodes[] = +{ + { sizeof(retcode0), retcode0 }, + { sizeof(retcode1), retcode1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// STMicroelectronics - Assembler - rel. 4.10 +// We support Motorola format +//----------------------------------------------------------------------- +static const char *const st7_headers[] = +{ + "st7/", + "", + NULL +}; + +static const asm_t stasm = +{ + ASH_HEXF4 // $1234 + |ASD_DECF0 // 1234 + |ASB_BINF2 // %1010 + |ASO_OCTF6 // ~1234 + |AS_NOXRF // Disable xrefs during the output file generation + |AS_ONEDUP, // one array definition per line + 0, + "STMicroelectronics - Assembler", + 0, + st7_headers, // header lines + "org", // org + "end", // end + + ";", // comment string + '\"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + "dc.b", // ascii string directive + "dc.b", // byte directive + "dc.w", // word directive + "dc.l", // double words + NULL, // qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "skip#s( )#d, #v", // arrays (#h,#d,#v,#s(...) ONLY BYTE ARRAYS!!! + "ds.b %s", // uninited arrays + "equ", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "*", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + "public", // "public" name keyword + NULL, // "weak" name keyword + "extern", // "extrn" name keyword + // .extern directive requires an explicit object size + NULL, // "comm" (communal variable) + NULL, // get_type_name + NULL, // "align" keyword + '{', '}', // lbrace, rbrace + NULL, // mod + "and", // and + "or", // or + "xor", // xor + NULL, // not + "shl", // shl + "shr", // shr + NULL, // sizeof + AS2_BRACE, +}; + +static const asm_t *const asms[] = { &stasm, NULL }; + +//-------------------------------------------------------------------------- +//static const char cfgname[] = "st7.cfg"; + +//---------------------------------------------------------------------- +const ioport_t *st7_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port; +} + +//---------------------------------------------------------------------- +void st7_t::create_words(void) +{ + for ( int i=0; i < ioh.ports.size(); i++ ) + { + ea_t ea = ioh.ports[i].address; + if ( is_tail(get_flags(ea)) ) + del_items(ea, DELIT_SIMPLE); + create_word(ea, 2); + } +} + +//-------------------------------------------------------------------------- +const char *st7_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( choose_ioport_device(&ioh.device, cfgfile) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_PORT|IORESP_INT); + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +void st7_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(st7_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi st7_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + { + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( choose_ioport_device(&ioh.device, cfgfile) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + create_words(); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_is_jump_func: + { + const func_t *pfn = va_arg(va, const func_t *); + ea_t *jump_target = va_arg(va, ea_t *); + return is_jump_func(pfn, jump_target); + } + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, insn_t *); + int no_crefs = va_arg(va, int); + return is_sane_insn(*insn, no_crefs) == 1 ? 1 : -1; + } + + case processor_t::ev_may_be_func: + { + const insn_t *insn = va_arg(va, insn_t *); + return may_be_func(*insn); + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st7_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st7_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + st7_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + st7_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return st7_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return st7_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "SGS-Thomson ST7:" +static const char *const shnames[] = { "st7", NULL }; +static const char *const lnames[] = +{ + FAMILY"SGS-Thomson ST7", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_ST7, // id + // flag + PRN_HEX + | PR_RNAMESOK, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + ds, // first + cs, // last + 2, // size of a segment register + cs, ds, + + NULL, // No known code start sequences + retcodes, + + ST7_null, + ST7_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + ST7_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/st7/st7.cfg b/idasdk76/module/st7/st7.cfg similarity index 100% rename from idasdk75/module/st7/st7.cfg rename to idasdk76/module/st7/st7.cfg diff --git a/idasdk76/module/st7/st7.hpp b/idasdk76/module/st7/st7.hpp new file mode 100644 index 0000000..4ba215a --- /dev/null +++ b/idasdk76/module/st7/st7.hpp @@ -0,0 +1,116 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2000 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _ST7_HPP +#define _ST7_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + +#define PROCMOD_NAME st7 +#define PROCMOD_NODE_NAME "$ st7" + +// o_void Inherent nop +// o_imm Immediate ld A,#$55 +// o_mem Direct ld A,$55 +// o_displ Indexed ld A,($55,X) +// o_mem Indirect ld A,([$55],X) +// o_near Relative jrne loop +// o_mem Bit operation bset byte,#5 + +// type Mode Syntax Destination Ptradr PtrSz Len +// ------- --------------------------- ------------------------ ---------- ------ ---- --- +// o_void Inherent nop + 0 +// o_imm Immediate ld A,#$55 + 1 +// o_mem Short Direct ld A,$10 00..FF + 1 +// o_mem Long Direct ld A,$1000 0000..FFFF + 2 +// o_phras No Offset Direct Indexed ld A,(X) 00..FF + 0 +// o_displ Short Direct Indexed ld A,($10,X) 00..1FE + 1 +// o_displ Long Direct Indexed ld A,($1000,X) 0000..FFFF + 2 +// o_mem Short Indirect ld A,[$10] 00..FF 00..FF byte + 2 +// o_mem Long Indirect ld A,[$10.w] 0000..FFFF 00..FF word + 2 +// o_mem Short Indirect Indexed ld A,([$10],X) 00..1FE 00..FF byte + 2 +// o_mem Long Indirect Indexed ld A,([$10.w],X) 0000..FFFF 00..FF word + 2 +// o_near Relative Direct jrne loop PC+/-127 + 1 +// o_mem Relative Indirect jrne [$10] PC+/-127 00..FF byte + 2 +// o_mem Bit Direct bset $10,#7 00..FF + 1 +// o_mem Bit Indirect bset [$10],#7 00..FF 00..FF byte + 2 +// o_mem Bit Direct Relative btjt $10,#7,skip 00..FF + 2 +// o_mem Bit Indirect Relative btjt [$10],#7,skip 00..FF 00..FF byte + 3 + +#define aux_long 0x0001 // long addressing mode +#define aux_indir 0x0002 // o_mem: indirect addressing mode +#define aux_index 0x0004 // o_mem: indexed addressing mode +#define aux_16 0x0008 // 16bit displacement + +//------------------------------------------------------------------ +#ifdef _MSC_VER +#define ENUM8BIT : uint8 +#else +#define ENUM8BIT +#endif +enum regnum_t ENUM8BIT +{ + A, X, Y, CC, S, + ds, cs, +}; + +//------------------------------------------------------------------ +struct st7_iohandler_t : public iohandler_t +{ + st7_iohandler_t(netnode &nn) : iohandler_t(nn) {} +}; + +struct st7_t : public procmod_t +{ + netnode helper; + st7_iohandler_t ioh = st7_iohandler_t(helper); + + bool flow; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const ioport_t *find_sym(ea_t address); + void create_words(void); + const char *idaapi set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + + int st7_emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &x, bool isload); + + void st7_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; + +//------------------------------------------------------------------ +ea_t calc_mem(const insn_t &insn, ea_t ea); // map virtual to physical ea + +//------------------------------------------------------------------ +void idaapi st7_header(outctx_t &ctx); + +void idaapi st7_segstart(outctx_t &ctx, segment_t *seg); +void idaapi st7_segend(outctx_t &ctx, segment_t *seg); +void idaapi st7_assumes(outctx_t &ctx); // function to produce assume directives + +int idaapi st7_ana(insn_t *insn); + +int idaapi is_align_insn(ea_t ea); + +int is_jump_func(const func_t *pfn, ea_t *jump_target); +int is_sane_insn(const insn_t &insn, int nocrefs); +int may_be_func(const insn_t &insn); // can a function start here? + +#endif // _ST7_HPP diff --git a/idasdk76/module/st9/ana.cpp b/idasdk76/module/st9/ana.cpp new file mode 100644 index 0000000..2f55d8e --- /dev/null +++ b/idasdk76/module/st9/ana.cpp @@ -0,0 +1,1796 @@ + +#include "st9.hpp" + +enum st9_addressing_modes ENUM_SIZE(uint16) +{ + A_IMPL, // implied + A_wrd_wrs, // rd,rs + A_wrd_wrsi, // rd,(rs) + A_wrdi_wrs, // (rd),rs + A_wrdi_grs, // (rd),Rs + A_grd_wrsi, // Rd,(rs) + A_grd_grs, // Rd,Rs + A_grs_grd, // Rs,Rd + A_grd_8q, // Rd,#N + A_grpd_grps, // RRd,RRs + A_grpd_16q_0, // RRd,#NN with first byte mask xxxxxxx0 + A_grpd_16q_1, // RRd,#NN with first byte mask xxxxxxx1 + A_grp_8q, // RR,#N + A_grs, // Rs + A_grsi, // (Rs) + A_grd, // Rd + A_grdi, // (Rd) + A_grp_0, // RR with first byte mask xxxxxxx0 + A_grp_1, // RR with first byte mask xxxxxxx1 + A_grpi, // (RR) + A_8q, // N + A_16q, // NN + A_grps, // RRs + A_grpd_0, // RRd with first byte mask xxxxxxx0 + A_grpd_1, // RRd with first byte mask xxxxxxx1 + A_grpdi, // (RRd) + A_wrpd_wrps, // rrd,rrs + A_wrpdi_wrps, // (rrd),rrs + A_wrpd_wrpsi, // rrd,(rrs) + A_wrpdi_wrpsi, // (rrd),(rrs) + + A_wrpdip_wrpsip_00, // (rrd)+,(rrs)+ with first byte mask xxx0xxx0 + A_wrpdip_wrpsip_10, // (rrd)+,(rrs)+ with first byte mask xxx1xxx0 + A_wrpdip_wrpsip_01, // (rrd)+,(rrs)+ with first byte mask xxx0xxx1 + A_wrpdip_wrpsip_11, // (rrd)+,(rrs)+ with first byte mask xxx1xxx1 + + A_wrpd_wrs, // rrd,rs + A_8qxwrp_16q, // Nd(rr),#NNs + A_16qxwrp_16q, // NNd(rr),#NNs + A_8qxwrp_gr, // N(rr),R + A_16qxwrp_gr, // NN(rr),R + A_16q_8q, // NNd,#Ns + A_16q_16q, // NNd,#NNs + A_wr_wrpxwrp, // rd,rrs(rrx) + A_wrpxwrp_wr, // rrd(rrx),rs + A_wrp_wrpxwrp, // rrd,rrs(rrx) + A_wrpxwrp_wrp, // rrd(rrx),rrs + + A_gr_wrpi, // Rd,(rrs) + A_wrip_gr, // (rrd),Rs + A_grpi_wrip, // (RRd),(rrs) + A_gri_wrip_01, // (R),(rr) with first byte mask 0100xxxx + A_gri_wrip_11, // (R),(rr) with first byte mask 1100xxxx + A_gr_8qxwrp, // Rd,N(rrx) + A_gr_16qxwrp, // Rd,NN(rrx) + A_grp_wrpi, // RRd,(rrs) + + A_8qxwrp_grp, // N(rrx),RRs + A_grp_8qxwrp, // RRs,N(rrx) + A_16qxwrp_grp, // NN(rrx),RRs + A_grp_16qxwrp, // RRs,NN(rrx) + + A_8qxgrpi, // N(RRx) + A_16qxgrpi, // NN(RRx) + + A_wrd_wrpsi_8q_0, // rd,(rrs),N with first byte mask xxx0xxxx + A_wrd_wrpsi_8q_1, // rd,(rrs),N with first byte mask xxx1xxxx + + A_grpd_wrsi, // RRd,(rs) + + A_8qxwr_wrs, // N(rx),rs + A_wrs_8qxwr, // rs,N(rx) + A_grd_wrpip, // Rd,(rrs)+ + A_wrpip_grd, // (rrs)+,Rd + A_wrd_wrpi, // rd,(rrs) + A_wrpi_wrd, // (rrs),rd + + A_wrpi_grp, // (rr),RR + A_wrpi_16q, // (rr),#NN + + A_grd_wrpim, // Rd,-(rrs) + A_wrpim_grd, // -(rrs),Rd + A_grpd_wrpim, // RRd,-(rrs) + A_wrpim_grpd, // -(rrs),RRd + A_16q_wrs, // NN,rs + A_wrd_16q, // rd,NN + + A_grpd_wrpip, // RRd,(rrs)+ + A_wrpip_grpd, // (rrd)+,RRs + + A_wrip_wrpip, // (rd)+,(rrs)+ + A_wrpip_wrip, // (rrs)+,(rd)+ + + A_8qxwrip_wrp, // N(rx),rrs + A_wrp_8qxwrip, // rrd,N(rx) + + A_wrp_16q, // rrd,NN + A_16q_wrp, // NN,rrs + + A_wrp_wrp_grp, // rrh,rrl,RRs + A_wrdi_grp, // (rd),RRs + A_wrpi_8q, // (rrd),#N + + A_wrb_wrb_10, // rd.b,rs.b with first word mask xxx1xxxx xxx0xxxx + A_wrb_wrb_11, // rd.b,rs.b with first word mask xxx1xxxx xxx1xxxx + A_wrb_nwrb_10, // rd.b,!rs.b with first word mask xxx1xxxx xxx0xxxx + A_wrb_nwrb_11, // rd.b,!rs.b with first word mask xxx1xxxx xxx1xxxx + A_wrb, // rd.b + A_wrbi, // (rr).bd + A_bwr_8q_0, // b.rd,N with first byte mask xxx0xxxx + A_bwr_8q_1, // b.rd,N with first byte mask xxx1xxxx + + A_seg_16q_01, // nnnnnn,NN with first byte mask 01xxxxxx + A_seg_16q_11, // nnnnnn,NN with first byte mask 11xxxxxx + + A_rwn_000, // wwwww with first byte mask xxxxx000 + A_rwn_100, // wwwww with first byte mask xxxxx100 + A_rwn_101, // wwwww with first byte mask xxxxx101 + A_rpn, // pppppp +}; + +struct opcode +{ + uint16 code; // opcode + uint16 insn; // insn mnemonic + uint16 addr; // addressing mode +}; + +static const opcode opcodes[] = +{ + { 0x00, st9_ei, A_IMPL }, + { 0x01, st9_scf, A_IMPL }, + { 0x02, st9_or, A_wrd_wrs }, + { 0x03, st9_or, A_wrd_wrsi }, + { 0x04, st9_or, A_grd_grs }, + { 0x05, st9_or, A_grd_8q }, + { 0x06, st9_aldw, A_8qxwrp_16q }, + { 0x06, st9_aldw, A_16qxwrp_16q }, + { 0x07, st9_orw, A_grpd_grps }, + { 0x07, st9_orw, A_grpd_16q_1 }, + { 0x08, st9_ld, A_grs }, + { 0x09, st9_ld, A_grd }, + { 0x0A, st9_djnz, A_8q }, + { 0x0B, st9_jrcc, A_8q }, + { 0x0C, st9_ld, A_8q }, + { 0x0D, st9_jpcc, A_16q }, + { 0x0E, st9_orw, A_wrpd_wrps }, + { 0x0E, st9_orw, A_wrpdi_wrps }, + { 0x0E, st9_orw, A_wrpd_wrpsi }, + { 0x0E, st9_orw, A_wrpdi_wrpsi }, + { 0x0F, st9_bor, A_wrb_wrb_10 }, + { 0x0F, st9_bor, A_wrb_nwrb_11 }, + { 0x0F, st9_bset, A_wrb }, + { 0x10, st9_di, A_IMPL }, + { 0x11, st9_rcf, A_IMPL }, + { 0x12, st9_and, A_wrd_wrs }, + { 0x13, st9_and, A_wrd_wrsi }, + { 0x14, st9_and, A_grd_grs }, + { 0x15, st9_and, A_grd_8q }, + { 0x16, st9_xch, A_grs_grd }, + { 0x17, st9_andw, A_grpd_grps }, + { 0x17, st9_andw, A_grpd_16q_1 }, + { 0x18, st9_ld, A_grs }, + { 0x19, st9_ld, A_grd }, + { 0x1A, st9_djnz, A_8q }, + { 0x1B, st9_jrcc, A_8q }, + { 0x1C, st9_ld, A_8q }, + { 0x1D, st9_jpcc, A_16q }, + { 0x1E, st9_andw, A_wrpd_wrps }, + { 0x1E, st9_andw, A_wrpdi_wrps }, + { 0x1E, st9_andw, A_wrpd_wrpsi }, + { 0x1E, st9_andw, A_wrpdi_wrpsi }, + { 0x1F, st9_band, A_wrb_wrb_11 }, + { 0x1F, st9_band, A_wrb_nwrb_10 }, + { 0x1F, st9_bres, A_wrb }, + { 0x20, st9_popu, A_grd }, + { 0x21, st9_popu, A_grdi }, + { 0x22, st9_sbc, A_wrd_wrs }, + { 0x23, st9_sbc, A_wrd_wrsi }, + { 0x24, st9_sbc, A_grd_grs }, + { 0x25, st9_sbc, A_grd_8q }, + { 0x26, st9_ald, A_8qxwrp_gr }, + { 0x26, st9_ald, A_16qxwrp_gr }, + { 0x27, st9_sbcw, A_grpd_grps }, + { 0x27, st9_sbcw, A_grpd_16q_1 }, + { 0x28, st9_ld, A_grs }, + { 0x29, st9_ld, A_grd }, + { 0x2A, st9_djnz, A_8q }, + { 0x2B, st9_jrcc, A_8q }, + { 0x2C, st9_ld, A_8q }, + { 0x2D, st9_jpcc, A_16q }, + { 0x2E, st9_sbcw, A_wrpd_wrps }, + { 0x2E, st9_sbcw, A_wrpdi_wrps }, + { 0x2E, st9_sbcw, A_wrpd_wrpsi }, + { 0x2E, st9_sbcw, A_wrpdi_wrpsi }, + { 0x2F, st9_sraw, A_grp_0 }, + { 0x2F, st9_ald, A_16q_8q }, + { 0x30, st9_pushu, A_grd }, + { 0x31, st9_pushu, A_grdi }, + { 0x32, st9_adc, A_wrd_wrs }, + { 0x33, st9_adc, A_wrd_wrsi }, + { 0x34, st9_adc, A_grd_grs }, + { 0x35, st9_adc, A_grd_8q }, + { 0x36, st9_rrcw, A_grp_0 }, + { 0x36, st9_aldw, A_16q_16q }, + { 0x37, st9_adcw, A_grpd_grps }, + { 0x37, st9_adcw, A_grpd_16q_1 }, + { 0x38, st9_ld, A_grs }, + { 0x39, st9_ld, A_grd }, + { 0x3A, st9_djnz, A_8q }, + { 0x3B, st9_jrcc, A_8q }, + { 0x3C, st9_ld, A_8q }, + { 0x3D, st9_jpcc, A_16q }, + { 0x3E, st9_adcw, A_wrpd_wrps }, + { 0x3E, st9_adcw, A_wrpdi_wrps }, + { 0x3E, st9_adcw, A_wrpd_wrpsi }, + { 0x3E, st9_adcw, A_wrpdi_wrpsi }, + { 0x3F, st9_calls, A_seg_16q_01 }, + { 0x3F, st9_jps, A_seg_16q_11 }, + { 0x40, st9_dec, A_grd }, + { 0x41, st9_dec, A_grdi }, + { 0x42, st9_add, A_wrd_wrs }, + { 0x43, st9_add, A_wrd_wrsi }, + { 0x44, st9_add, A_grd_grs }, + { 0x45, st9_add, A_grd_8q }, + { 0x46, st9_ret, A_IMPL }, + { 0x47, st9_addw, A_grpd_grps }, + { 0x47, st9_addw, A_grpd_16q_1 }, + { 0x48, st9_ld, A_grs }, + { 0x49, st9_ld, A_grd }, + { 0x4A, st9_djnz, A_8q }, + { 0x4B, st9_jrcc, A_8q }, + { 0x4C, st9_ld, A_8q }, + { 0x4D, st9_jpcc, A_16q }, + { 0x4E, st9_addw, A_wrpd_wrps }, + { 0x4E, st9_addw, A_wrpdi_wrps }, + { 0x4E, st9_addw, A_wrpd_wrpsi }, + { 0x4E, st9_addw, A_wrpdi_wrpsi }, + { 0x4F, st9_mul, A_wrpd_wrs }, + { 0x50, st9_inc, A_grd }, + { 0x51, st9_inc, A_grdi }, + { 0x52, st9_sub, A_wrd_wrs }, + { 0x53, st9_sub, A_wrd_wrsi }, + { 0x54, st9_sub, A_grd_grs }, + { 0x55, st9_sub, A_grd_8q }, + { 0x56, st9_divws, A_wrp_wrp_grp }, + { 0x57, st9_subw, A_grpd_grps }, + { 0x57, st9_subw, A_grpd_16q_1 }, + { 0x58, st9_ld, A_grs }, + { 0x59, st9_ld, A_grd }, + { 0x5A, st9_djnz, A_8q }, + { 0x5B, st9_jrcc, A_8q }, + { 0x5C, st9_ld, A_8q }, + { 0x5D, st9_jpcc, A_16q }, + { 0x5E, st9_subw, A_wrpd_wrps }, + { 0x5E, st9_subw, A_wrpdi_wrps }, + { 0x5E, st9_subw, A_wrpd_wrpsi }, + { 0x5E, st9_subw, A_wrpdi_wrpsi }, + { 0x5F, st9_div, A_wrpd_wrs }, + { 0x60, st9_ald, A_wr_wrpxwrp }, + { 0x60, st9_ald, A_wrpxwrp_wr }, + { 0x60, st9_aldw, A_wrp_wrpxwrp }, + { 0x60, st9_aldw, A_wrpxwrp_wrp }, + { 0x61, st9_ccf, A_IMPL }, + { 0x62, st9_xor, A_wrd_wrs }, + { 0x63, st9_xor, A_wrd_wrsi }, + { 0x64, st9_xor, A_grd_grs }, + { 0x65, st9_xor, A_grd_8q }, + { 0x66, st9_push, A_grd }, + { 0x67, st9_xorw, A_grpd_grps }, + { 0x67, st9_xorw, A_grpd_16q_1 }, + { 0x68, st9_ld, A_grs }, + { 0x69, st9_ld, A_grd }, + { 0x6A, st9_djnz, A_8q }, + { 0x6B, st9_jrcc, A_8q }, + { 0x6C, st9_ld, A_8q }, + { 0x6D, st9_jpcc, A_16q }, + { 0x6E, st9_xorw, A_wrpd_wrps }, + { 0x6E, st9_xorw, A_wrpdi_wrps }, + { 0x6E, st9_xorw, A_wrpd_wrpsi }, + { 0x6E, st9_xorw, A_wrpdi_wrpsi }, + { 0x6F, st9_bxor, A_wrb_wrb_10 }, + { 0x6F, st9_bxor, A_wrb_nwrb_11 }, + { 0x6F, st9_bcpl, A_wrb }, + { 0x70, st9_da, A_grd }, + { 0x71, st9_da, A_grdi }, + { 0x72, st9_ald, A_gr_wrpi }, + { 0x72, st9_ald, A_wrip_gr }, + { 0x73, st9_calls, A_gri_wrip_01 }, + { 0x73, st9_jps, A_gri_wrip_11 }, + { 0x73, st9_ald, A_grpi_wrip }, + { 0x74, st9_call, A_grpdi }, + { 0x74, st9_pushw, A_grps }, + { 0x75, st9_popw, A_grpd_0 }, + { 0x75, st9_unlink, A_grpd_1 }, + { 0x76, st9_pop, A_grd }, + { 0x77, st9_pop, A_grdi }, + { 0x78, st9_ld, A_grs }, + { 0x79, st9_ld, A_grd }, + { 0x7A, st9_djnz, A_8q }, + { 0x7B, st9_jrcc, A_8q }, + { 0x7C, st9_ld, A_8q }, + { 0x7D, st9_jpcc, A_16q }, + { 0x7E, st9_aldw, A_grp_wrpi }, + { 0x7F, st9_ald, A_gr_8qxwrp }, + { 0x7F, st9_ald, A_gr_16qxwrp }, + { 0x80, st9_cpl, A_grd }, + { 0x81, st9_cpl, A_grdi }, + { 0x82, st9_cp, A_wrd_wrs }, + { 0x83, st9_cp, A_wrd_wrsi }, + { 0x84, st9_cp, A_grd_grs }, + { 0x85, st9_cp, A_grd_8q }, + { 0x86, st9_aldw, A_8qxwrp_grp }, + { 0x86, st9_aldw, A_grp_8qxwrp }, + { 0x86, st9_aldw, A_16qxwrp_grp }, + { 0x86, st9_aldw, A_grp_16qxwrp }, + { 0x87, st9_cpw, A_grpd_grps }, + { 0x87, st9_cpw, A_grpd_16q_1 }, + { 0x88, st9_ld, A_grs }, + { 0x89, st9_ld, A_grd }, + { 0x8A, st9_djnz, A_8q }, + { 0x8B, st9_jrcc, A_8q }, + { 0x8C, st9_ld, A_8q }, + { 0x8D, st9_jpcc, A_16q }, + { 0x8E, st9_cpw, A_wrpd_wrps }, + { 0x8E, st9_cpw, A_wrpdi_wrps }, + { 0x8E, st9_cpw, A_wrpd_wrpsi }, + { 0x8E, st9_cpw, A_wrpdi_wrpsi }, + { 0x8FF1, st9_push, A_8q }, + { 0x8FF3, st9_pushu, A_8q }, + { 0x8FC1, st9_pushw, A_16q }, + { 0x8FC3, st9_pushuw, A_16q }, + { 0x8F01, st9_pea, A_8qxgrpi }, + { 0x8F01, st9_pea, A_16qxgrpi }, + { 0x8F03, st9_peau, A_8qxgrpi }, + { 0x8F03, st9_peau, A_16qxgrpi }, + { 0x8F, st9_rlcw, A_grpd_0 }, + { 0x90, st9_clr, A_grd }, + { 0x91, st9_clr, A_grdi }, + { 0x92, st9_cp, A_wrd_wrs }, + { 0x93, st9_cp, A_wrd_wrsi }, + { 0x94, st9_cp, A_grd_grs }, + { 0x95, st9_cp, A_grd_8q }, + { 0x96, st9_aldw, A_wrdi_grp }, + { 0x97, st9_cpw, A_grpd_grps }, + { 0x97, st9_cpw, A_grpd_16q_1 }, + { 0x98, st9_ld, A_grs }, + { 0x99, st9_ld, A_grd }, + { 0x9A, st9_djnz, A_8q }, + { 0x9B, st9_jrcc, A_8q }, + { 0x9C, st9_ld, A_8q }, + { 0x9D, st9_jpcc, A_16q }, + { 0x9E, st9_cpw, A_wrpd_wrps }, + { 0x9E, st9_cpw, A_wrpdi_wrps }, + { 0x9E, st9_cpw, A_wrpd_wrpsi }, + { 0x9E, st9_cpw, A_wrpdi_wrpsi }, + { 0x9F, st9_cpjfi, A_wrd_wrpsi_8q_0 }, + { 0x9F, st9_cpjti, A_wrd_wrpsi_8q_1 }, + { 0xA0, st9_rol, A_grd }, + { 0xA1, st9_rol, A_grdi }, + { 0xA2, st9_tm, A_wrd_wrs }, + { 0xA3, st9_tm, A_wrd_wrsi }, + { 0xA4, st9_tm, A_grd_grs }, + { 0xA5, st9_tm, A_grd_8q }, + { 0xA6, st9_aldw, A_grpd_wrsi }, + { 0xA7, st9_tmw, A_grpd_grps }, + { 0xA7, st9_tmw, A_grpd_16q_1 }, + { 0xA8, st9_ld, A_grs }, + { 0xA9, st9_ld, A_grd }, + { 0xAA, st9_djnz, A_8q }, + { 0xAB, st9_jrcc, A_8q }, + { 0xAC, st9_ld, A_8q }, + { 0xAD, st9_jpcc, A_16q }, + { 0xAE, st9_tmw, A_wrpd_wrps }, + { 0xAE, st9_tmw, A_wrpdi_wrps }, + { 0xAE, st9_tmw, A_wrpd_wrpsi }, + { 0xAE, st9_tmw, A_wrpdi_wrpsi }, + { 0xAF, st9_btjt, A_bwr_8q_0 }, + { 0xAF, st9_btjf, A_bwr_8q_1 }, + { 0xB0, st9_rlc, A_grd }, + { 0xB1, st9_rlc, A_grdi }, + { 0xB2, st9_ld, A_8qxwr_wrs }, + { 0xB3, st9_ld, A_wrs_8qxwr }, + { 0xB4, st9_ald, A_grd_wrpip }, + { 0xB4, st9_ald, A_wrpip_grd }, + { 0xB5, st9_ld, A_wrd_wrpi }, + { 0xB5, st9_ld, A_wrpi_wrd }, + { 0xB6, st9_pushuw, A_grp_0 }, + { 0xB6, st9_linku, A_grp_8q }, + { 0xB7, st9_popuw, A_grp_0 }, + { 0xB7, st9_unlinku, A_grp_1 }, + { 0xB8, st9_ld, A_grs }, + { 0xB9, st9_ld, A_grd }, + { 0xBA, st9_djnz, A_8q }, + { 0xBB, st9_jrcc, A_8q }, + { 0xBC, st9_ld, A_8q }, + { 0xBD, st9_jpcc, A_16q }, + { 0xBE, st9_aldw, A_wrpi_grp }, + { 0xBE, st9_aldw, A_wrpi_16q }, + { 0xBF01, st9_halt, A_IMPL }, + { 0xBF, st9_ldw, A_grpd_16q_0 }, + { 0xC0, st9_ror, A_grd }, + { 0xC1, st9_ror, A_grdi }, + { 0xC2, st9_ald, A_grd_wrpim }, + { 0xC2, st9_ald, A_wrpim_grd }, + { 0xC3, st9_aldw, A_grpd_wrpim }, + { 0xC3, st9_aldw, A_wrpim_grpd }, + { 0xC4, st9_ald, A_wrd_16q }, + { 0xC5, st9_ald, A_16q_wrs }, + { 0xC6, st9_ext, A_grp_1 }, + { 0xC6, st9_dwjnz, A_grp_8q }, + { 0xC7, st9_srp, A_rwn_000 }, + { 0xC7, st9_srp0, A_rwn_100 }, + { 0xC7, st9_srp1, A_rwn_101 }, + { 0xC7, st9_spp, A_rpn }, + { 0xC8, st9_ld, A_grs }, + { 0xC9, st9_ld, A_grd }, + { 0xCA, st9_djnz, A_8q }, + { 0xCB, st9_jrcc, A_8q }, + { 0xCC, st9_ld, A_8q }, + { 0xCD, st9_jpcc, A_16q }, + { 0xCE, st9_etrap, A_IMPL }, + { 0xCF, st9_decw, A_grpd_0 }, + { 0xD0, st9_rrc, A_grd }, + { 0xD1, st9_rrc, A_grdi }, + { 0xD2, st9_call, A_16q }, + { 0xD3, st9_iret, A_IMPL }, + { 0xD4, st9_jp, A_grpi }, + { 0xD4, st9_link, A_grp_8q }, + { 0xD5, st9_aldw, A_grpd_wrpip }, + { 0xD5, st9_aldw, A_wrpip_grpd }, + { 0xD6, st9_ldpp, A_wrpdip_wrpsip_00 }, + { 0xD6, st9_lddp, A_wrpdip_wrpsip_10 }, + { 0xD6, st9_ldpd, A_wrpdip_wrpsip_01 }, + { 0xD6, st9_lddd, A_wrpdip_wrpsip_11 }, + { 0xD7, st9_ld, A_wrip_wrpip }, + { 0xD7, st9_ld, A_wrpip_wrip }, + { 0xD8, st9_ld, A_grs }, + { 0xD9, st9_ld, A_grd }, + { 0xDA, st9_djnz, A_8q }, + { 0xDB, st9_jrcc, A_8q }, + { 0xDC, st9_ld, A_8q }, + { 0xDD, st9_jpcc, A_16q }, + { 0xDE, st9_ldw, A_8qxwrip_wrp }, + { 0xDE, st9_ldw, A_wrp_8qxwrip }, + { 0xDF, st9_incw, A_grpd_0 }, + { 0xE0, st9_sra, A_grd }, + { 0xE1, st9_sra, A_grdi }, + { 0xE2, st9_aldw, A_wrp_16q }, + { 0xE2, st9_aldw, A_16q_wrp }, + { 0xE3, st9_ldw, A_wrpd_wrps }, + { 0xE3, st9_ldw, A_wrpdi_wrps }, + { 0xE3, st9_ldw, A_wrpd_wrpsi }, + { 0xE3, st9_ldw, A_wrpdi_wrpsi }, + { 0xE4, st9_ld, A_wrd_wrsi }, + { 0xE5, st9_ld, A_wrdi_wrs }, + { 0xE6, st9_ald, A_wrdi_grs }, + { 0xE7, st9_ald, A_grd_wrsi }, + { 0xE8, st9_ld, A_grs }, + { 0xE9, st9_ld, A_grd }, + { 0xEA, st9_djnz, A_8q }, + { 0xEB, st9_jrcc, A_8q }, + { 0xEC, st9_ld, A_8q }, + { 0xED, st9_jpcc, A_16q }, + { 0xEE, st9_spm, A_IMPL }, + { 0xEF01, st9_wfi, A_IMPL }, + { 0xEF31, st9_eret, A_IMPL }, + { 0xEF, st9_ldw, A_grpd_grps }, + { 0xF0, st9_swap, A_grd }, + { 0xF1, st9_swap, A_grdi }, + { 0xF2, st9_bld, A_wrb_wrb_10 }, + { 0xF2, st9_bld, A_wrb_nwrb_11 }, + { 0xF2, st9_btset, A_wrb }, + { 0xF3, st9_ald, A_wrpi_8q }, + { 0xF4, st9_ld, A_grd_grs }, + { 0xF5, st9_ld, A_grd_8q }, + { 0xF601, st9_rets, A_IMPL }, + { 0xF6, st9_btset, A_wrbi }, + { 0xF7, st9_push, A_grsi }, + { 0xF8, st9_ld, A_grs }, + { 0xF9, st9_ld, A_grd }, + { 0xFA, st9_djnz, A_8q }, + { 0xFB, st9_jrcc, A_8q }, + { 0xFC, st9_ld, A_8q }, + { 0xFD, st9_jpcc, A_16q }, + { 0xFE, st9_sdm, A_IMPL }, + { 0xFF, st9_nop, A_IMPL } +}; + +//---------------------------------------------------------------------- +static const opcode *find_opcode(insn_t &insn, int _code) +{ + for ( int i = 0; i < qnumber(opcodes); i++ ) + { + // is the opcode coded in a word ? + bool need_another_byte = ((opcodes[i].code & 0xFF00) >> 8) != 0; + + int code = need_another_byte + ? (_code << 8) | get_byte(insn.ea + insn.size) + : _code; + + // opcode is wrong + if ( opcodes[i].code != code ) + continue; + + int next_byte = get_byte(insn.ea + insn.size + (need_another_byte ? 1 : 0)); + int mask = 0; + int value = 0; + + switch ( opcodes[i].addr ) + { + // 0000000X (X == 0) + case A_grpd_grps: + case A_16qxwrp_16q: + case A_16qxwrp_gr: + case A_wrip_gr: + case A_gr_16qxwrp: + case A_grpd_0: + case A_grps: + case A_wrpip_grd: + case A_wrd_wrpi: + case A_grp_0: + case A_wrpi_16q: + case A_grpd_16q_0: + case A_wrpim_grd: + case A_wrpim_grpd: + case A_grpi: + case A_wrpip_grpd: + case A_wrpip_wrip: + case A_wrp_16q: + mask = 0x01; + value = 0x00; + break; + + case A_wrb: + mask = 0x10; + value = 0x00; + break; + + // 0000000X (X == 1) + case A_grpd_16q_1: + case A_8qxwrp_16q: + case A_8qxwrp_gr: + case A_gr_wrpi: + case A_gr_8qxwrp: + case A_grpd_1: + case A_grpdi: + case A_grd_wrpip: + case A_wrpi_wrd: + case A_grp_1: + case A_wrpi_grp: + case A_grd_wrpim: + case A_grpd_wrpim: + case A_grpd_wrpip: + case A_wrip_wrpip: + case A_16q_wrp: + mask = 0x01; + value = 0x01; + break; + + // 00000XXX (XXX = 000) + case A_rwn_000: + mask = 0x07; + value = 0x00; + break; + + // 00000XXX (XXX = 100) + case A_rwn_100: + mask = 0x07; + value = 0x04; + break; + + // 00000XXX (XXX = 101) + case A_rwn_101: + mask = 0x07; + value = 0x05; + break; + + // XY000000 (XY == 01) + case A_seg_16q_01: + mask = 0xC0; + value = 0x40; + break; + + // XY000000 (XY == 11) + case A_seg_16q_11: + mask = 0xC0; + value = 0xC0; + break; + + // 000000XY (XY = 10) + case A_rpn: + mask = 0x03; + value = 0x02; + break; + + // 000X0000 (X == 0) + case A_wrd_wrpsi_8q_0: + case A_wrp_8qxwrip: + case A_bwr_8q_0: + mask = 0x10; + value = 0x00; + break; + + // 000X0000 (X == 1) + case A_wrd_wrpsi_8q_1: + case A_8qxwrip_wrp: + case A_bwr_8q_1: + mask = 0x10; + value = 0x10; + break; + + // XXXX0000 (XXXX = 0100) + case A_gri_wrip_01: + mask = 0xF0; + value = 0x40; + break; + + // XXXX0000 (XXXX = 1100) + case A_gri_wrip_11: + mask = 0xF0; + value = 0xC0; + break; + + // 000X000Y (X == 0 && Y == 0) + case A_wrpd_wrps: + case A_wrpdip_wrpsip_00: + case A_wrp_wrpxwrp: + case A_wrbi: + mask = 0x11; + value = 0x00; + break; + + // 000X000Y (X == 1 && Y == 0) + case A_wrpdi_wrps: + case A_wrpdip_wrpsip_10: + case A_wr_wrpxwrp: + mask = 0x11; + value = 0x10; + break; + + // 000X000Y (X == 0 && Y == 1) + case A_wrpd_wrpsi: + case A_wrpdip_wrpsip_01: + case A_wrpxwrp_wrp: + mask = 0x11; + value = 0x01; + break; + + // 000X000Y (X == 1 && Y == 1) + case A_wrpdi_wrpsi: + case A_wrpdip_wrpsip_11: + case A_wrpxwrp_wr: + mask = 0x11; + value = 0x11; + break; + + // 0000X (X = 0001) + case A_16q_8q: + case A_16q_16q: + mask = 0x0F; + value = 0x01; + break; + + // 0000000X (X == 1) && 3th byte MSB == 1 + case A_8qxwrp_grp: + if ( (get_byte(insn.ea + insn.size + 2) & 0x01) == 1 ) + { + mask = 0x01; + value = 0x01; + } + else + mask = -1; + break; + + // 0000000X (X == 1) && 3th byte MSB == 0 + case A_grp_8qxwrp: + if ( (get_byte(insn.ea + insn.size + 2) & 0x01) == 0 ) + { + mask = 0x01; + value = 0x01; + } + else + mask = -1; + break; + + // 0000000X (X == 1) && 4th byte MSB == 1 + case A_16qxwrp_grp: + if ( (get_byte(insn.ea + insn.size + 3) & 0x01) == 1 ) + { + mask = 0x01; + value = 0x00; + } + else + mask = -1; + break; + + // 0000000X (X == 1) && 4th byte MSB == 0 + case A_grp_16qxwrp: + if ( (get_byte(insn.ea + insn.size + 3) & 0x01) == 0 ) + { + mask = 0x01; + value = 0x00; + } + else + mask = -1; + break; + + // 2nd byte MSB == 0 + case A_8qxgrpi: + if ( (get_byte(insn.ea + insn.size + 1) & 0x01) != 0 ) + mask = -1; + break; + + // 2nd byte MSB == 1 + case A_16qxgrpi: + if ( (get_byte(insn.ea + insn.size + 1) & 0x01) != 1 ) + mask = -1; + break; + + // NOTE: it seems that there is an error in the manual : + // rd.b,rs.b and rd.b,rs.!b opcodes are inversed ! + + // 000X0000 (X == 1) + 0x000Y0000 (Y == 0) + case A_wrb_wrb_10: + case A_wrb_nwrb_10: + if ( (get_byte(insn.ea + insn.size + 1) & 0x10) == 0 ) + { + mask = 0x10; + value = 0x10; + } + else + mask = -1; + break; + + // 000X0000 (X == 1) + 0x000Y0000 (Y == 1) + case A_wrb_wrb_11: + case A_wrb_nwrb_11: + if ( (get_byte(insn.ea + insn.size + 1) & 0x10) == 0x10 ) + { + mask = 0x10; + value = 0x10; + } + else + mask = -1; + break; + + } + + // addr mode is wrong + if ( mask != 0 && (mask == -1 || (next_byte & mask) != value) ) + continue; + + // Yahoo ! + if ( need_another_byte ) + insn.size++; + + return &opcodes[i]; + } + return NULL; +} + +//---------------------------------------------------------------------- +static int get_condition_code(int code) +{ + switch ( code ) + { + case 0x0B: // JR F,N + case 0x0D: // JP F,NN + return cF; + + case 0x1B: // JR LT,N + case 0x1D: // JP LT,NN + return cLT; + + case 0x2B: // JR LE,N + case 0x2D: // JP LE,NN + return cLE; + + case 0x3B: // JR ULE,N + case 0x3D: // JP ULE,NN + return cULE; + + case 0x4B: // JR OV,N + case 0x4D: // JP OV,NN + return cOV; + + case 0x5B: // JR MI,N + case 0x5D: // JP MI,NN + return cMI; + + case 0x6B: // JR EQ,N + case 0x6D: // JP EQ,NN + return cEQ; + + // XXX + // According to the manual, 0x7X is related + // to the UL condition code. + // JRUL/JPUL cannot be assembled (unknown instruction). + // objdump9 disassemble 0x7X with the C condition code, + // therefore we use it instead of UL. + case 0x7B: // JR C,N + case 0x7D: // JP C,NN + return cC; + + case 0x8B: // JR T,N + case 0x8D: // JP T,NN + return cT; + + case 0x9B: // JR GE,N + case 0x9D: // JP GE,NN + return cGE; + + case 0xAB: // JR GT,N + case 0xAD: // JP GT,NN + return cGT; + + case 0xBB: // JR UGT,N + case 0xBD: // JP UGT,NN + return cUGT; + + case 0xCB: // JR NOV,N + case 0xCD: // JP NOV,NN + return cNOV; + + case 0xDB: // JR PL,N + case 0xDD: // JP PL,NN + return cPL; + + case 0xEB: // JR NE,N + case 0xED: // JP NE,NN + return cNE; + + case 0xFB: // JR NC,N + case 0xFD: // JP NC,NN + return cNC; + } + return cUNKNOWN; +} + +//---------------------------------------------------------------------- +static uint16 get_working_register(int code) +{ + uchar reg_id = (code & 0xF0) >> 4; + return rr0 + reg_id; +} + +//---------------------------------------------------------------------- +// general register: if the 4 Most Significant Bits (MSB) are Dh then the 4 Least Significant +// Bits (LSB) specify a working register +static uint16 get_general_register(int code, bool pair = false) +{ + uchar reg_grp = (code & 0xF0) >> 4; + // group D (R208-R223) refers to working registers + + if ( reg_grp == 0xD ) + return (pair ? rrr0 : rr0) + (code & 0x0F); + else + return (pair ? rRR0 : rR0) + code; +} + +//---------------------------------------------------------------------- +static uint16 get_alu_insn(const insn_t &insn, int code) +{ + int insn_id = (code & 0xF0) >> 4; + + QASSERT(10031, insn.itype == st9_ald || insn.itype == st9_aldw); + + bool long_insn = insn.itype == st9_aldw; + + if ( !long_insn ) + { + switch ( insn_id ) + { + case 0x0: return st9_or; + case 0x1: return st9_and; + case 0x2: return st9_sbc; + case 0x3: return st9_adc; + case 0x4: return st9_add; + case 0x5: return st9_sub; + case 0x6: return st9_xor; + case 0x8: return st9_cp; + case 0x9: return st9_cp; + case 0xA: return st9_tm; + case 0xF: return st9_ld; + } + } + else + { + switch ( insn_id ) + { + case 0x0: return st9_orw; + case 0x1: return st9_andw; + case 0x2: return st9_sbcw; + case 0x3: return st9_adcw; + case 0x4: return st9_addw; + case 0x5: return st9_subw; + case 0x6: return st9_xorw; + case 0x8: return st9_cpw; + case 0x9: return st9_cpw; + case 0xA: return st9_tmw; + case 0xF: return st9_ldw; + } + } + return st9_null; +} + +//---------------------------------------------------------------------- +// fill instruction flag +static void set_flag(insn_t &insn, int flag) +{ + insn.auxpref |= flag; +} + +//---------------------------------------------------------------------- +// fill operand flag +static void set_flag(op_t &x, int flag) +{ + x.specflag1 |= flag; +} + +//---------------------------------------------------------------------- +// fill an operand as a register +static void set_reg(op_t &op, uint16 reg, int flag = 0) +{ + op.type = o_reg; + op.reg = reg; + op.dtype = dt_byte; + if ( flag ) + set_flag(op, flag); +} + +//---------------------------------------------------------------------- +// fill an operand as an immediate value +static void set_imm(op_t &op, int val, char d_typ, int flag = 0) +{ + op.type = o_imm; + op.value = val; + op.dtype = d_typ; + if ( flag ) + set_flag(op, flag); +} + +//---------------------------------------------------------------------- +// fill an operand as a displacement +static void set_displ(op_t &op, optype_t a1_t, uint16 a1, optype_t a2_t, uint16 a2, char dtyp = dt_byte) +{ + op.type = o_displ; + op.reg = 0; + switch ( a1_t ) + { + case o_reg: + op.reg = a1; + break; + + case o_mem: + op.addr = a1; + break; + + default: + INTERR(10032); + } + switch ( a2_t ) + { + case o_reg: + if ( op.reg == 0 ) + op.reg = a2; + else + INTERR(10033); + break; + + default: + INTERR(10034); + } + op.dtype = dtyp; +} + +//---------------------------------------------------------------------- +// fill an operand as a phrase +static void set_phrase(op_t &op, st9_phrases phrase, uint16 reg1, int reg2 = -1, char dtyp = dt_byte) +{ + op.type = o_phrase; + op.reg = reg1; + op.specflag2 = phrase; + op.dtype = dtyp; + if ( reg2 != -1 ) + { + op.specflag2 = (reg2 & 0xFF00) >> 8; + op.specflag3 = (reg2 & 0x00FF); + } +} + +//---------------------------------------------------------------------- +// add a bit number to a register operand +static void set_bit(op_t &op, int bit, int flag = 0) +{ + op.value = bit; + if ( flag ) + set_flag(op, flag); +} + +//---------------------------------------------------------------------- +// fill an operand as an address (data or code) +static void set_addr(op_t &op, optype_t type, ea_t addr, char dtyp = dt_byte) +{ + QASSERT(10035, type == o_mem || type == o_near || type == o_far); // bad optype_t in set_addr() + op.type = type; + op.addr = addr; + op.dtype = dtyp; +} + +//---------------------------------------------------------------------- +static uint16 my_next_word(insn_t &insn) +{ + uchar b1 = insn.get_next_byte(); + uchar b2 = insn.get_next_byte(); + return b1 | (b2 << 8); +} + +//---------------------------------------------------------------------- +static void fill_cmd(insn_t &insn, int byte, const opcode *op) +{ + QASSERT(10036, op != NULL); + insn.itype = op->insn; + + switch ( op->addr ) + { + // Implied + case A_IMPL: + // Nothing to do ! + break; + + // rd,rs + case A_wrd_wrs: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); + set_reg(insn.Op2, rr0 + (byte & 0x0F)); + break; + + // rd,(rs) + case A_wrd_wrsi: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); + set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND); + break; + + // (rd),rs + case A_wrdi_wrs: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4), OP_IS_IND); + set_reg(insn.Op2, rr0 + (byte & 0x0F)); + break; + + // (rd),Rs + case A_wrdi_grs: + QASSERT(10037, insn.itype == st9_ald); + set_reg(insn.Op2, get_general_register(insn.get_next_byte())); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_IS_IND); + break; + + // Rd,(rs) + case A_grd_wrsi: + QASSERT(10038, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // Rs,Rd + case A_grs_grd: + // Rd,Rs + case A_grd_grs: + set_reg(insn.Op2, get_general_register(insn.get_next_byte())); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // Rd,#N + case A_grd_8q: + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + set_imm(insn.Op2, insn.get_next_byte(), dt_byte); + break; + + // RRd,RRs + case A_grpd_grps: + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // RRd,#NN + case A_grpd_16q_0: + case A_grpd_16q_1: + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + set_imm(insn.Op2, insn.get_next_word(), dt_word); + break; + + // RR,N + case A_grp_8q: + { + byte = insn.get_next_byte(); + uint16 reg = get_general_register(byte & 0xFE, true); + if ( insn.itype == st9_dwjnz ) + { + set_addr(insn.Op2, o_near, insn.get_next_byte()); + insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; + } + else + { // link or linku + set_imm(insn.Op2, 0xFF - insn.get_next_byte(), dt_byte); + } + set_reg(insn.Op1, reg); + } + break; + + // Rs + case A_grs: + if ( insn.itype == st9_ld ) + { + set_reg(insn.Op1, get_working_register(byte)); + set_reg(insn.Op2, get_general_register(insn.get_next_byte())); + } + else + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // Rd + case A_grd: + if ( insn.itype == st9_ld ) + { + set_reg(insn.Op2, get_working_register(byte)); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + } + else + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // (R) + case A_grdi: + case A_grsi: + set_reg(insn.Op1, get_general_register(insn.get_next_byte()), OP_IS_IND); + break; + + // RR + case A_grp_0: + case A_grp_1: + case A_grps: + case A_grpd_0: + case A_grpd_1: + { + byte = insn.get_next_byte(); + uint16 reg = get_general_register((byte & 0xFE), true); + set_reg(insn.Op1, reg); + } + break; + + // (RR) + case A_grpi: + case A_grpdi: + set_reg(insn.Op1, get_general_register((insn.get_next_byte() & 0xFE), true), OP_IS_IND); + break; + + // N + case A_8q: + if ( is_jmp_cc(insn.itype) ) + { + set_flag(insn, get_condition_code(byte)); + set_addr(insn.Op1, o_near, insn.get_next_byte()); + insn.Op1.addr = (signed char) insn.Op1.addr + insn.ip + insn.size; + } + else if ( insn.itype == st9_djnz ) + { + set_reg(insn.Op1, get_working_register(byte)); + set_addr(insn.Op2, o_near, insn.get_next_byte()); + insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; + } + else if ( insn.itype == st9_ld ) + { + set_reg(insn.Op1, get_working_register(byte)); + set_imm(insn.Op2, insn.get_next_byte(), dt_byte); + insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; + } + else if ( insn.itype == st9_push + || insn.itype == st9_pushu + || insn.itype == st9_pushw ) + { + set_imm(insn.Op1, insn.get_next_byte(), dt_byte); + } + else + { + set_addr(insn.Op1, o_mem, insn.get_next_byte()); + insn.Op1.addr = (signed char) insn.Op1.addr + insn.ip + insn.size; + } + break; + + // NN + case A_16q: + if ( is_jmp_cc(insn.itype) || insn.itype == st9_call ) + { + if ( is_jmp_cc(insn.itype) ) + set_flag(insn, get_condition_code(byte)); + set_addr(insn.Op1, o_near, insn.get_next_word()); + } + else if ( insn.itype == st9_push + || insn.itype == st9_pushu + || insn.itype == st9_pushw + || insn.itype == st9_pushuw ) + { + set_imm(insn.Op1, insn.get_next_word(), dt_word); + } + else + { + set_addr(insn.Op1, o_mem, insn.get_next_word()); + } + break; + + // rrd,rrs + case A_wrpd_wrps: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); + set_reg(insn.Op2, rrr0 + (byte & 0x0E)); + break; + + // (rrd),rrs + case A_wrpdi_wrps: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND); + set_reg(insn.Op2, rrr0 + (byte & 0x0E)); + break; + + // rrd,(rrs) + case A_wrpd_wrpsi: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); + set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); + break; + + // (rrd),(rrs) + case A_wrpdi_wrpsi: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND); + set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); + break; + + // rrd,rs + case A_wrpd_wrs: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); + set_reg(insn.Op2, rr0 + (byte & 0x0F)); + break; + + // rd,(rrs) + case A_wrd_wrpi: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); + set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); + break; + + // (rrs),rd + case A_wrpi_wrd: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); + set_reg(insn.Op2, rr0 + ((byte & 0xF0) >> 4)); + break; + + // Nd(rr),#NNs + case A_8qxwrp_16q: + QASSERT(10039, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word); + set_imm(insn.Op2, insn.get_next_word(), dt_word); + break; + + // NNd(rr),#NNs + case A_16qxwrp_16q: + QASSERT(10040, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word); + set_imm(insn.Op2, insn.get_next_word(), dt_word); + break; + + // N(rr),R + case A_8qxwrp_gr: + QASSERT(10041, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E)); + set_reg(insn.Op2, get_general_register(insn.get_next_byte())); + break; + + // NN(rr),R + case A_16qxwrp_gr: + QASSERT(10042, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E)); + set_reg(insn.Op2, get_general_register(insn.get_next_byte())); + break; + + // NNd,#Ns + case A_16q_8q: + QASSERT(10043, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_imm(insn.Op2, insn.get_next_byte(), dt_byte); + set_addr(insn.Op1, o_mem, insn.get_next_word()); + break; + + // NNd,#NNs + case A_16q_16q: + QASSERT(10044, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_imm(insn.Op2, insn.get_next_word(), dt_word); + set_addr(insn.Op1, o_mem, insn.get_next_word(), dt_word); + break; + + // rd,rrs(rrx) + case A_wr_wrpxwrp: + QASSERT(10045, insn.itype == st9_ald); + byte = insn.get_next_byte(); + set_phrase(insn.Op2, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E)); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rr0 + (byte & 0x0F)); + break; + + // rrd(rrx),rs + case A_wrpxwrp_wr: + QASSERT(10046, insn.itype == st9_ald); + byte = insn.get_next_byte(); + set_phrase(insn.Op1, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E)); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rr0 + (byte & 0x0F)); + break; + + // rrd,rrs(rrx) + case A_wrp_wrpxwrp: + QASSERT(10047, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + set_phrase(insn.Op2, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E), dt_word); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rrr0 + (byte & 0x0E)); + break; + + // rrd(rrx),rrs + case A_wrpxwrp_wrp: + QASSERT(10048, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + set_phrase(insn.Op1, fDISP, rrr0 + ((byte & 0xE0) >> 4), rrr0 + (byte & 0x0E), dt_word); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rrr0 + (byte & 0x0E)); + break; + + // Rd,(rrs) + case A_gr_wrpi: + QASSERT(10049, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // (rrd),Rs + case A_wrip_gr: + QASSERT(10050, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); + set_reg(insn.Op2, get_general_register(insn.get_next_byte())); + break; + + // (RRd),(rrs) + case A_grpi_wrip: + QASSERT(10051, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true), OP_IS_IND); + break; + + // (R),(rr) + case A_gri_wrip_01: + case A_gri_wrip_11: + set_reg(insn.Op2, rrr0 + (insn.get_next_byte() & 0x0E), OP_IS_IND); + set_reg(insn.Op1, get_general_register(insn.get_next_byte()), OP_IS_IND); + break; + + // Rd,N(rrx) + case A_gr_8qxwrp: + QASSERT(10052, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E)); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // Rd,NN(rrx) + case A_gr_16qxwrp: + QASSERT(10053, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op2, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E)); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // RRd,(rrs) + case A_grp_wrpi: + QASSERT(10054, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rrr0 + (byte & 0x0E), OP_IS_IND); + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // N(rrx),RRs + case A_8qxwrp_grp: + QASSERT(10055, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word); + set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // RRd,N(rrx) + case A_grp_8qxwrp: + QASSERT(10056, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rrr0 + (byte & 0x0E), dt_word); + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // NN(rrx),RRs + case A_16qxwrp_grp: + QASSERT(10057, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op1, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word); + set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // RRd,NN(rrx) + case A_grp_16qxwrp: + QASSERT(10058, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_displ(insn.Op2, o_mem, short(insn.get_next_word()), o_reg, rrr0 + (byte & 0x0E), dt_word); + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // N(RRx) + case A_8qxgrpi: + byte = insn.get_next_byte(); + set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, get_general_register(byte & 0xFE, true)); + break; + + // NN(RRx) + case A_16qxgrpi: + byte = insn.get_next_byte(); + // this word is coded with little endian + set_displ(insn.Op1, o_mem, short(my_next_word(insn)), o_reg, get_general_register(byte & 0xFE, true)); + break; + + // rd,(rrs),N + case A_wrd_wrpsi_8q_0: + case A_wrd_wrpsi_8q_1: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + (byte & 0x0F)); + set_reg(insn.Op2, rrr0 + ((byte & 0xE0) >> 4), OP_IS_IND); + set_imm(insn.Op3, insn.get_next_byte(), dt_byte); + break; + + // RRd,(rs) + case A_grpd_wrsi: + QASSERT(10059, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rr0 + (byte & 0x0F), OP_IS_IND); + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // N(rx),rs + case A_8qxwr_wrs: + byte = insn.get_next_byte(); + set_reg(insn.Op2, rr0 + ((byte & 0xF0) >> 4)); + set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); + break; + + // rs,N(rx) + case A_wrs_8qxwr: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + ((byte & 0xF0) >> 4)); + set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); + break; + + // Rd,(rrs)+ + case A_grd_wrpip: + QASSERT(10060, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E)); + set_reg(insn.Op1, get_general_register(insn.get_next_byte())); + break; + + // (rrs)+,Rd + case A_wrpip_grd: + QASSERT(10061, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E)); + set_reg(insn.Op2, rR0 + insn.get_next_byte()); + break; + + // (rr),RR + case A_wrpi_grp: + QASSERT(10062, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); + set_reg(insn.Op2, rRR0 + (insn.get_next_byte() & 0x0E)); + break; + + // (rr),#NN + case A_wrpi_16q: + QASSERT(10063, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); + set_imm(insn.Op2, insn.get_next_word(), dt_word); + break; + + // Rd,-(rrs) + case A_grd_wrpim: + QASSERT(10064, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op2, fPD, rrr0 + (byte & 0x0E)); + set_reg(insn.Op1, rR0 + insn.get_next_byte()); + break; + + // -(rrs),Rd + case A_wrpim_grd: + QASSERT(10065, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op1, fPD, rrr0 + (byte & 0x0E)); + set_reg(insn.Op2, rR0 + insn.get_next_byte()); + break; + + // RRd,-(rrs) + case A_grpd_wrpim: + QASSERT(10066, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op2, fPD, rrr0 + (byte & 0x0E), -1, dt_word); + set_reg(insn.Op1, rRR0 + insn.get_next_byte()); + break; + + // -(rrs),RRd + case A_wrpim_grpd: + QASSERT(10067, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op1, fPD, rrr0 + (byte & 0x0E), -1, dt_word); + set_reg(insn.Op2, rRR0 + insn.get_next_byte()); + break; + + // NN,rs + case A_16q_wrs: + QASSERT(10068, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rr0 + (byte & 0x0F)); + set_addr(insn.Op1, o_mem, insn.get_next_word()); + break; + + // rd,NN + case A_wrd_16q: + QASSERT(10069, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rr0 + (byte & 0x0F)); + set_addr(insn.Op2, o_mem, insn.get_next_word()); + break; + + // (rd)+,(rrs)+ + case A_wrip_wrpip: + byte = insn.get_next_byte(); + set_phrase(insn.Op1, fPI, rr0 + ((byte & 0xE0) >> 4)); + set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E)); + break; + + // (rrs)+,(rd)+ + case A_wrpip_wrip: + byte = insn.get_next_byte(); + set_phrase(insn.Op2, fPI, rr0 + ((byte & 0xE0) >> 4)); + set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E)); + break; + + // (rrd)+,(rrs)+ + case A_wrpdip_wrpsip_00: + case A_wrpdip_wrpsip_10: + case A_wrpdip_wrpsip_01: + case A_wrpdip_wrpsip_11: + byte = insn.get_next_byte(); + set_phrase(insn.Op1, fPI, rrr0 + ((byte & 0xE0) >> 4)); + set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E)); + break; + + // RRd,(rrs)+ + case A_grpd_wrpip: + QASSERT(10070, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op2, fPI, rrr0 + (byte & 0x0E), -1, dt_word); + set_reg(insn.Op1, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // (rrd)+,RRs + case A_wrpip_grpd: + QASSERT(10071, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_phrase(insn.Op1, fPI, rrr0 + (byte & 0x0E), -1, dt_word); + set_reg(insn.Op2, get_general_register(insn.get_next_byte() & 0xFE, true)); + break; + + // N(rx),rrs + case A_8qxwrip_wrp: + byte = insn.get_next_byte(); + set_displ(insn.Op1, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); + set_reg(insn.Op2, rrr0 + ((byte & 0xE0) >> 4)); + break; + + // rrd,N(rx) + case A_wrp_8qxwrip: + byte = insn.get_next_byte(); + set_displ(insn.Op2, o_mem, char(insn.get_next_byte()), o_reg, rr0 + (byte & 0x0F)); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); + break; + + // rrd,NN + case A_wrp_16q: + QASSERT(10072, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rrr0 + (byte & 0x0E)); + set_addr(insn.Op2, o_mem, insn.get_next_word(), dt_word); + break; + + // NN,rrs + case A_16q_wrp: + QASSERT(10073, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op2, rrr0 + (byte & 0x0E)); + set_addr(insn.Op1, o_mem, insn.get_next_word(), dt_word); + break; + + // rrh,rrl,RRs + case A_wrp_wrp_grp: + set_reg(insn.Op3, rRR0 + (insn.get_next_byte() & 0x0E)); + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + ((byte & 0xE0) >> 4)); + set_reg(insn.Op2, rrr0 + (byte & 0x0E)); + break; + + // (rd),RRs + case A_wrdi_grp: + QASSERT(10074, insn.itype == st9_aldw); + byte = insn.get_next_byte(); + set_reg(insn.Op2, rRR0 + (byte & 0x0E)); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_IS_IND); + break; + + // (rrd),#N + case A_wrpi_8q: + QASSERT(10075, insn.itype == st9_ald); + byte = insn.get_next_byte(); + insn.itype = get_alu_insn(insn, byte); + set_reg(insn.Op1, rrr0 + (byte & 0x0E), OP_IS_IND); + set_imm(insn.Op2, insn.get_next_byte(), dt_byte); + break; + +#define BIT_OP_1 (insn.itype != st9_bld ? insn.Op1 : insn.Op2) +#define BIT_OP_2 (insn.itype != st9_bld ? insn.Op2 : insn.Op1) + + // rd.b,rs.b + case A_wrb_wrb_10: + case A_wrb_wrb_11: + byte = insn.get_next_byte(); + set_reg(BIT_OP_1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); + set_bit(BIT_OP_1, (byte & 0xE0) >> 5); + byte = insn.get_next_byte(); + set_reg(BIT_OP_2, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); + set_bit(BIT_OP_2, (byte & 0xE0) >> 5); + break; + + // rd.b,rs.!b + case A_wrb_nwrb_10: + case A_wrb_nwrb_11: + byte = insn.get_next_byte(); + set_reg(BIT_OP_1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); + set_bit(BIT_OP_1, (byte & 0xE0) >> 5, insn.itype == st9_bld ? OP_BIT_COMPL : 0); + byte = insn.get_next_byte(); + set_reg(BIT_OP_2, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); + set_bit(BIT_OP_2, (byte & 0xE0) >> 5, insn.itype != st9_bld ? OP_BIT_COMPL : 0); + break; + + // rd.b + case A_wrb: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); + set_bit(insn.Op1, (byte & 0xE0) >> 5); + break; + + // (rr).bd + case A_wrbi: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rrr0 + (byte & 0x0F), OP_REG_WITH_BIT | OP_IS_IND); + set_bit(insn.Op1, (byte & 0xE0) >> 5); + break; + + // b.rd,N + case A_bwr_8q_0: + case A_bwr_8q_1: + byte = insn.get_next_byte(); + set_reg(insn.Op1, rr0 + (byte & 0x0F), OP_REG_WITH_BIT); + set_bit(insn.Op1, (byte & 0xE0) >> 5); + set_addr(insn.Op2, o_near, insn.get_next_byte()); + insn.Op2.addr = (signed char) insn.Op2.addr + insn.ip + insn.size; + break; + + // nnnnnn,NN (calls, jps) + case A_seg_16q_01: + case A_seg_16q_11: + { + uint8 seg = insn.get_next_byte() & 0x3F; + uint16 dst = insn.get_next_word(); + ea_t fardest = (seg<<16) |dst; + if ( is_mapped(fardest) ) + { + set_addr(insn.Op1, o_far, fardest); + } + else + { + set_imm(insn.Op1, seg, dt_byte, OP_IMM_NO_SHIFT); + set_addr(insn.Op2, o_near, dst); + } + + } + break; + + // wwwww + case A_rwn_000: + case A_rwn_100: + case A_rwn_101: + set_imm(insn.Op1, (insn.get_next_byte() & 0xF8) >> 3, dt_byte); + break; + + // pppppp + case A_rpn: + set_imm(insn.Op1, (insn.get_next_byte() & 0xFC) >> 2, dt_byte); + break; + } +} + +//---------------------------------------------------------------------- +// analyze an instruction +int idaapi st9_ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + int byte = insn.get_next_byte(); + + const opcode *op = find_opcode(insn, byte); + if ( op == NULL ) + return 0; + + fill_cmd(insn, byte, op); + + return insn.size; +} diff --git a/idasdk76/module/st9/emu.cpp b/idasdk76/module/st9/emu.cpp new file mode 100644 index 0000000..3458c41 --- /dev/null +++ b/idasdk76/module/st9/emu.cpp @@ -0,0 +1,489 @@ + +#include "st9.hpp" + +//---------------------------------------------------------------------- +static sel_t calc_page(ea_t insn_ea, ushort addr) +{ + return get_sreg(insn_ea, rDPR0+(addr>>14)); +} + +//---------------------------------------------------------------------- +static ea_t calc_data_mem_without_mapping(ea_t insn_ea, ea_t addr) +{ + sel_t page = calc_page(insn_ea, (ushort)addr); + if ( page == BADSEL ) + return BADADDR; + ea_t ea = use_mapping((page<<14) + (addr & 0x3FFF)); + return ea; +} + +//---------------------------------------------------------------------- +ea_t get_dest_addr(const insn_t &insn, const op_t &x) +{ + if ( x.type == o_far ) + return x.addr; + else if ( x.type == o_mem ) + return calc_data_mem_without_mapping(insn.ea, x.addr); + else if ( x.type == o_near ) + return to_ea(insn.cs, x.addr); + else + return BADADDR; +} + +//---------------------------------------------------------------------- +// Emulate an operand. +void st9_t::handle_operand(const insn_t &insn, const op_t &op, bool lwrite) +{ + switch ( op.type ) + { + // Code address + case o_near: + case o_far: + { + cref_t mode; + ea_t ea = get_dest_addr(insn, op); + + // call or jump ? + if ( is_call_insn(insn) ) + { + if ( !func_does_return(ea) ) + flow = false; + mode = op.type == o_near ? fl_CN: fl_CF; + } + else + { + mode = op.type == o_near ? fl_JN: fl_JF; + } + insn.add_cref(ea, op.offb, mode); + } + break; + + // Memory address + case o_mem: + { + ea_t ea = get_dest_addr(insn, op); + insn.add_dref(ea, op.offb, lwrite ? dr_W : dr_R); + insn.create_op_data(ea, op); + } + break; + + // Immediate value + case o_imm: + { + set_immd(insn.ea); + flags_t F = get_flags(insn.ea); + // create a comment if this immediate is represented in the .cfg file + { + const ioport_t * port = find_sym(op.value); + if ( port != NULL && !has_cmt(F) ) + set_cmt(insn.ea, port->cmt.c_str(), false); + } + // if the value was converted to an offset, then create a data xref: + if ( op_adds_xrefs(F, op.n) ) + insn.add_off_drefs(op, dr_O, 0); + } + break; + + // Displacement + case o_displ: + { + set_immd(insn.ea); + flags_t F = get_flags(insn.ea); + if ( op_adds_xrefs(F, op.n) ) + { + ea_t ea = insn.add_off_drefs(op, dr_O, OOF_ADDR); + insn.create_op_data(ea, op); + } + + // create stack variables if required + if ( may_create_stkvars() && !is_defarg(F, op.n) && op.reg == rrr14 ) + { + func_t *pfn = get_func(insn.ea); + if ( pfn != NULL && pfn->flags & FUNC_FRAME ) + { + adiff_t displ = (int16)op.addr; + if ( insn.create_stkvar(op, displ, STKVAR_VALID_SIZE) ) + { + op_stkvar(insn.ea, op.n); + if ( insn.Op2.type == o_reg ) + { + regvar_t *r = find_regvar(pfn, insn.ea, ph.reg_names[insn.Op2.reg]); + if ( r != NULL ) + { + struc_t *s = get_frame(pfn); + member_t *m = get_stkvar(NULL, insn, op, displ); + if ( s != NULL && m != NULL ) + { + char b[20]; + qsnprintf(b, sizeof b, "%scopy", r->user); + set_member_name(s, m->soff, b); + } + } + } + } + } + } + } + break; + + // Register - Phrase - Void: do nothing + case o_reg: + case o_phrase: + case o_void: + break; + + default: + INTERR(10076); + } +} + +//---------------------------------------------------------------------- +// Emulate an instruction. +int st9_t::st9_emu(const insn_t &insn) +{ + uint32 feature = insn.get_canon_feature(ph); + flow = ((feature & CF_STOP) == 0); + // is it "jump always"? + if ( is_jmp_cc(insn.itype) && insn.auxpref == cT ) + flow = false; + + if ( insn.Op1.type != o_void) handle_operand(insn, insn.Op1, (feature & CF_CHG1) != 0); + if ( insn.Op2.type != o_void) handle_operand(insn, insn.Op2, (feature & CF_CHG2) != 0); + if ( insn.Op3.type != o_void) handle_operand(insn, insn.Op3, (feature & CF_CHG3) != 0); + + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + + // Following code will update the current value of the two virtual + // segment registers: RW (register window) and RP (register page). + + bool rw_has_changed = false; + bool rp_has_changed = false; + + switch ( insn.itype ) + { + case st9_srp: + { + sel_t val = insn.Op1.value; + if ( val % 2 ) + val--; // even reduced + split_sreg_range(insn.ea+insn.size, rRW, val | (val << 8), SR_auto); + } + rw_has_changed = true; + break; + + case st9_srp0: + { + sel_t RW = get_sreg(insn.ea, rRW); + split_sreg_range(insn.ea+insn.size, rRW, insn.Op1.value | (RW & 0xFF00), SR_auto); + } + rw_has_changed = true; + break; + + case st9_srp1: + { + sel_t RW = get_sreg(insn.ea, rRW); + split_sreg_range(insn.ea+insn.size, rRW, (insn.Op1.value << 8) | (RW & 0x00FF), SR_auto); + } + rw_has_changed = true; + break; + + case st9_spp: + split_sreg_range(insn.ea+insn.size, rRP, insn.Op1.value, SR_auto); + rp_has_changed = true; + break; + } + + // If RW / RP registers have changed, print a comment which explains the new mapping of + // the general registers. + + flags_t F = get_flags(insn.ea); + if ( rw_has_changed && !has_cmt(F) ) + { + char buf[MAXSTR]; + sel_t RW = get_sreg(insn.ea+insn.size, rRW); + int low = RW & 0x00FF; + int high = (RW & 0xFF00) >> 8; + + low *= 8; + high *= 8; + + const char *const fmt = + "r0 -> R%d, r1 -> R%d, r2 -> R%d, r3 -> R%d, r4 -> R%d, r5 -> R%d, r6 -> R%d, r7 -> R%d,\n" + "r8 -> R%d, r9 -> R%d, r10 -> R%d, r11 -> R%d, r12 -> R%d, r13 -> R%d, r14 -> R%d, r15 -> R%d"; + + qsnprintf(buf, sizeof buf, fmt, + 0 + low, + 1 + low, + 2 + low, + 3 + low, + 4 + low, + 5 + low, + 6 + low, + 7 + low, + 8 + high, + 9 + high, + 10 + high, + 11 + high, + 12 + high, + 13 + high, + 14 + high, + 15 + high); + + set_cmt(insn.ea, buf, false); + } + + if ( rp_has_changed && !has_cmt(F) ) + { + char buf[MAXSTR]; + int rpval = get_sreg(insn.ea+insn.size, rRP); + qsnprintf(buf, sizeof buf, "Registers R240-R255 will now be referred to the page %d of paged registers", + rpval); + set_cmt(insn.ea, buf, false); + } + + // reanalyze switch info + if ( insn.itype == st9_jp && get_auto_state() == AU_USED ) + { + switch_info_t si; + if ( get_switch_info(&si, insn.ea) > 0 && !si.is_user_defined() ) + { + delete_switch_table(insn.ea, si); + if ( st9_is_switch(&si, insn) ) + { + set_switch_info(insn.ea, si); + create_switch_table(insn.ea, si); + } + else + { + del_switch_info(insn.ea); + } + } + } + + return 1; +} + +//---------------------------------------------------------------------- +// Analyze an instruction +static ea_t next_insn(insn_t *insn, ea_t ea) +{ + if ( decode_insn(insn, ea) == 0 ) + return 0; + ea += insn->size; + return ea; +} + +//------------------------------------------------------------------------ +// does a far return instruction precede 'ea'? +static bool is_far_return(ea_t ea) +{ + insn_t insn; + if ( decode_prev_insn(&insn, ea) != BADADDR ) + return insn.itype == st9_rets; + return false; +} + +//---------------------------------------------------------------------- +// if a function ends with a far return, mark it as such +// NB: we only handle regular (non-chunked) functions +static void setup_far_func(func_t *pfn) +{ + if ( (pfn->flags & FUNC_FAR) == 0 ) + { + if ( is_far_return(pfn->end_ea) ) + { + pfn->flags |= FUNC_FAR; + update_func(pfn); + } + } +} + + +//---------------------------------------------------------------------- +// Create a function frame +bool st9_t::create_func_frame(func_t *pfn) const +{ + setup_far_func(pfn); + + ea_t ea = pfn->start_ea; + + insn_t insn; + ea = next_insn(&insn, ea); + if ( !ea ) + return 0; + + /* + * Get the total frame size + * + * LINK rr14, #size + */ + + if ( insn.itype != st9_link ) + return 0; + + int link_register = insn.Op1.reg; + size_t total_size = (size_t)insn.Op2.value; + + /* + * Get arguments size + * + * LDW 0x??(rr14), RR??? a word + * LD '' a byte + */ + + int args_size = 0; + + for ( int i = 0; true; i++ ) + { + insn_t ldi; + ea = next_insn(&ldi, ea); + if ( !ea ) + return 0; + + if ( ldi.Op1.type != o_displ || ldi.Op2.type != o_reg ) + break; + + if ( ldi.Op1.reg != link_register ) + break; + + if ( ldi.itype == st9_ld ) // byte + args_size++; + else if ( ldi.itype == st9_ldw ) // word + args_size += 2; + else + break; + + char regvar[10]; + qsnprintf(regvar, sizeof regvar, "arg_%d", i); + int err = add_regvar(pfn, ldi.ea, ldi.ea + ldi.size, + ph.reg_names[ldi.Op2.reg], regvar, NULL); + if ( err ) + msg("add_regvar() failed : error %d\n", err); + } + + //msg("LOCAL: %d\nARGS: %d\n", total_size - args_size, args_size); + + pfn->flags |= FUNC_FRAME; + return add_frame(pfn, total_size - args_size, 0, args_size); +} + +//------------------------------------------------------------------------ +/* +GCC?-produced switch: + + ldw ridx, rin [optional] + cpw rin, #n + jpugt default | jrugt default + addw ridx, ridx + spm + ldw rjmp, jtbl(ridx) + sdm + jp (rjmp) +jtbl: .word case0, case1, ... +*/ + +static ea_t check_prev_insn(int itype, insn_t &insn) +{ + ea_t ea = decode_prev_insn(&insn, insn.ea); + if ( ea == BADADDR || insn.itype != itype ) + return BADADDR; + return ea; +} + +//-------------------------------------------------------------------------- +static bool is_gcc_switch(switch_info_t *_si, insn_t &insn) +{ + switch_info_t &si = *_si; + int rjmp, ridx; + // si.flags |= SWI_J32; + ea_t ea, jtbl_insn; + // + // Check jump insn and get register number + // jp (rjmp) + if ( insn.itype != st9_jp + || insn.Op1.type != o_reg + || !is_ind(insn.Op1) ) + { + return false; + } + rjmp = insn.Op1.reg; + // sdm + ea = check_prev_insn(st9_sdm, insn); + if ( ea == BADADDR ) + return false; + // ldw rjmp, jtbl(ridx) + ea = check_prev_insn(st9_ldw, insn); + if ( ea == BADADDR + || !insn.Op1.is_reg(rjmp) + || insn.Op2.type != o_displ ) + return false; + ridx = insn.Op2.reg; + jtbl_insn = ea; + // this addr is offset in current code segment because of spm + si.jumps = to_ea(insn.cs, insn.Op2.addr); + // spm + ea = check_prev_insn(st9_spm, insn); + if ( ea == BADADDR ) + return false; + + // addw ridx, ridx + ea = check_prev_insn(st9_addw, insn); + if ( ea == BADADDR + || !insn.Op1.is_reg(ridx) + || !insn.Op2.is_reg(ridx) ) + return false; + + // jpugt default | jrugt default + ea = decode_prev_insn(&insn, ea); + if ( ea != BADADDR + && is_jmp_cc(insn.itype) + && insn.auxpref == cUGT ) + { + si.defjump = get_dest_addr(insn, insn.Op1); + // cpw rin, #n + ea = check_prev_insn(st9_cpw, insn); + if ( ea == BADADDR + || insn.Op2.type != o_imm ) + return false; + int rin = insn.Op1.reg; + si.ncases = ushort(insn.Op2.value+1); + // is rin the same as ridx? + bool ok = insn.Op1.is_reg(ridx); + if ( !ok ) + { + // check for preceding ldw ridx, rin + ea_t ea2 = decode_prev_insn(&insn, ea); + if ( ea2 != BADADDR + && insn.itype == st9_ldw + && insn.Op1.is_reg(ridx) + && insn.Op2.is_reg(rin) ) + ok = true; + } + if ( !ok ) + return false; + si.set_expr(rin, insn.Op1.dtype); + } + // + // Everything ok. + // + msg("SWITCH %a: gcc_switch\n", insn.ea); + si.startea = ea; + si.set_jtable_element_size(2); + si.set_shift(0); + op_num(ea, 1); // cpw rin, #n + op_plain_offset(jtbl_insn, 1, to_ea(insn.cs, 0)); // ldw rjmp, jtbl(ridx) + return true; +} + +bool st9_is_switch(switch_info_t *si, const insn_t &insn) +{ + if ( insn.itype == st9_jp ) + { + insn_t copy = insn; + return is_gcc_switch(si, copy); + } + return false; +} + + diff --git a/idasdk75/module/st9/ins.cpp b/idasdk76/module/st9/ins.cpp similarity index 100% rename from idasdk75/module/st9/ins.cpp rename to idasdk76/module/st9/ins.cpp diff --git a/idasdk75/module/st9/ins.hpp b/idasdk76/module/st9/ins.hpp similarity index 100% rename from idasdk75/module/st9/ins.hpp rename to idasdk76/module/st9/ins.hpp diff --git a/idasdk76/module/st9/makefile b/idasdk76/module/st9/makefile new file mode 100644 index 0000000..ecda9fd --- /dev/null +++ b/idasdk76/module/st9/makefile @@ -0,0 +1,57 @@ +PROC=st9 +CONFIGS=st9.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ana.cpp ins.hpp st9.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp emu.cpp ins.hpp st9.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.cpp ins.hpp st9.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp st9.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp reg.cpp st9.hpp diff --git a/idasdk75/module/st9/out.cpp b/idasdk76/module/st9/out.cpp similarity index 100% rename from idasdk75/module/st9/out.cpp rename to idasdk76/module/st9/out.cpp diff --git a/idasdk76/module/st9/reg.cpp b/idasdk76/module/st9/reg.cpp new file mode 100644 index 0000000..b4356e3 --- /dev/null +++ b/idasdk76/module/st9/reg.cpp @@ -0,0 +1,1237 @@ + +#include "st9.hpp" + +#include <segregs.hpp> +int data_id; + +const char *const ConditionCodes[] = +{ + "UNKNOWN", + "f", // always false + "t", // always true + "c", // carry + "nc", // not carry + "z", // zero + "nz", // not zero + "pl", // plus + "mi", // minus + "ov", // overflow + "nov", // no overflow + "eq", // equal + "ne", // not equal + "ge", // greater than or equal + "lt", // less than + "gt", // greater than + "le", // less than or equal + "uge", // unsigned greated than or equal + "ul", // unsigned less than + "ugt", // unsigned greater than + "ule" // unsigned less than or equal +}; + +// ST9 registers names +static const char *const src_RegNames[] = +{ + "R0", + "R1", + "R2", + "R3", + "R4", + "R5", + "R6", + "R7", + "R8", + "R9", + "R10", + "R11", + "R12", + "R13", + "R14", + "R15", + "R16", + "R17", + "R18", + "R19", + "R20", + "R21", + "R22", + "R23", + "R24", + "R25", + "R26", + "R27", + "R28", + "R29", + "R30", + "R31", + "R32", + "R33", + "R34", + "R35", + "R36", + "R37", + "R38", + "R39", + "R40", + "R41", + "R42", + "R43", + "R44", + "R45", + "R46", + "R47", + "R48", + "R49", + "R50", + "R51", + "R52", + "R53", + "R54", + "R55", + "R56", + "R57", + "R58", + "R59", + "R60", + "R61", + "R62", + "R63", + "R64", + "R65", + "R66", + "R67", + "R68", + "R69", + "R70", + "R71", + "R72", + "R73", + "R74", + "R75", + "R76", + "R77", + "R78", + "R79", + "R80", + "R81", + "R82", + "R83", + "R84", + "R85", + "R86", + "R87", + "R88", + "R89", + "R90", + "R91", + "R92", + "R93", + "R94", + "R95", + "R96", + "R97", + "R98", + "R99", + "R100", + "R101", + "R102", + "R103", + "R104", + "R105", + "R106", + "R107", + "R108", + "R109", + "R110", + "R111", + "R112", + "R113", + "R114", + "R115", + "R116", + "R117", + "R118", + "R119", + "R120", + "R121", + "R122", + "R123", + "R124", + "R125", + "R126", + "R127", + "R128", + "R129", + "R130", + "R131", + "R132", + "R133", + "R134", + "R135", + "R136", + "R137", + "R138", + "R139", + "R140", + "R141", + "R142", + "R143", + "R144", + "R145", + "R146", + "R147", + "R148", + "R149", + "R150", + "R151", + "R152", + "R153", + "R154", + "R155", + "R156", + "R157", + "R158", + "R159", + "R160", + "R161", + "R162", + "R163", + "R164", + "R165", + "R166", + "R167", + "R168", + "R169", + "R170", + "R171", + "R172", + "R173", + "R174", + "R175", + "R176", + "R177", + "R178", + "R179", + "R180", + "R181", + "R182", + "R183", + "R184", + "R185", + "R186", + "R187", + "R188", + "R189", + "R190", + "R191", + "R192", + "R193", + "R194", + "R195", + "R196", + "R197", + "R198", + "R199", + "R200", + "R201", + "R202", + "R203", + "R204", + "R205", + "R206", + "R207", + "R208", + "R209", + "R210", + "R211", + "R212", + "R213", + "R214", + "R215", + "R216", + "R217", + "R218", + "R219", + "R220", + "R221", + "R222", + "R223", + "R224", + "R225", + "R226", + "R227", + "R228", + "R229", + "R230", + "R231", + "R232", + "R233", + "R234", + "R235", + "R236", + "R237", + "R238", + "R239", + "R240", + "R241", + "R242", + "R243", + "R244", + "R245", + "R246", + "R247", + "R248", + "R249", + "R250", + "R251", + "R252", + "R253", + "R254", + "R255", + "RR0", + "RR1", + "RR2", + "RR3", + "RR4", + "RR5", + "RR6", + "RR7", + "RR8", + "RR9", + "RR10", + "RR11", + "RR12", + "RR13", + "RR14", + "RR15", + "RR16", + "RR17", + "RR18", + "RR19", + "RR20", + "RR21", + "RR22", + "RR23", + "RR24", + "RR25", + "RR26", + "RR27", + "RR28", + "RR29", + "RR30", + "RR31", + "RR32", + "RR33", + "RR34", + "RR35", + "RR36", + "RR37", + "RR38", + "RR39", + "RR40", + "RR41", + "RR42", + "RR43", + "RR44", + "RR45", + "RR46", + "RR47", + "RR48", + "RR49", + "RR50", + "RR51", + "RR52", + "RR53", + "RR54", + "RR55", + "RR56", + "RR57", + "RR58", + "RR59", + "RR60", + "RR61", + "RR62", + "RR63", + "RR64", + "RR65", + "RR66", + "RR67", + "RR68", + "RR69", + "RR70", + "RR71", + "RR72", + "RR73", + "RR74", + "RR75", + "RR76", + "RR77", + "RR78", + "RR79", + "RR80", + "RR81", + "RR82", + "RR83", + "RR84", + "RR85", + "RR86", + "RR87", + "RR88", + "RR89", + "RR90", + "RR91", + "RR92", + "RR93", + "RR94", + "RR95", + "RR96", + "RR97", + "RR98", + "RR99", + "RR100", + "RR101", + "RR102", + "RR103", + "RR104", + "RR105", + "RR106", + "RR107", + "RR108", + "RR109", + "RR110", + "RR111", + "RR112", + "RR113", + "RR114", + "RR115", + "RR116", + "RR117", + "RR118", + "RR119", + "RR120", + "RR121", + "RR122", + "RR123", + "RR124", + "RR125", + "RR126", + "RR127", + "RR128", + "RR129", + "RR130", + "RR131", + "RR132", + "RR133", + "RR134", + "RR135", + "RR136", + "RR137", + "RR138", + "RR139", + "RR140", + "RR141", + "RR142", + "RR143", + "RR144", + "RR145", + "RR146", + "RR147", + "RR148", + "RR149", + "RR150", + "RR151", + "RR152", + "RR153", + "RR154", + "RR155", + "RR156", + "RR157", + "RR158", + "RR159", + "RR160", + "RR161", + "RR162", + "RR163", + "RR164", + "RR165", + "RR166", + "RR167", + "RR168", + "RR169", + "RR170", + "RR171", + "RR172", + "RR173", + "RR174", + "RR175", + "RR176", + "RR177", + "RR178", + "RR179", + "RR180", + "RR181", + "RR182", + "RR183", + "RR184", + "RR185", + "RR186", + "RR187", + "RR188", + "RR189", + "RR190", + "RR191", + "RR192", + "RR193", + "RR194", + "RR195", + "RR196", + "RR197", + "RR198", + "RR199", + "RR200", + "RR201", + "RR202", + "RR203", + "RR204", + "RR205", + "RR206", + "RR207", + "RR208", + "RR209", + "RR210", + "RR211", + "RR212", + "RR213", + "RR214", + "RR215", + "RR216", + "RR217", + "RR218", + "RR219", + "RR220", + "RR221", + "RR222", + "RR223", + "RR224", + "RR225", + "RR226", + "RR227", + "RR228", + "RR229", + "RR230", + "RR231", + "RR232", + "RR233", + "RR234", + "RR235", + "RR236", + "RR237", + "RR238", + "RR239", + "RR240", + "RR241", + "RR242", + "RR243", + "RR244", + "RR245", + "RR246", + "RR247", + "RR248", + "RR249", + "RR250", + "RR251", + "RR252", + "RR253", + "RR254", + "RR255", + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + "r8", + "r9", + "r10", + "r11", + "r12", + "r13", + "r14", + "r15", + "rr0", + "rr1", + "rr2", + "rr3", + "rr4", + "rr5", + "rr6", + "rr7", + "rr8", + "rr9", + "rr10", + "rr11", + "rr12", + "rr13", + "rr14", + "rr15", + "RW", + "RP", + "csr", + "dpr0", "dpr1", "dpr2", "dpr3", +}; + +//---------------------------------------------------------------------- +// returns a pointer to a ioport_t object if address was found in the config file. +// otherwise, returns NULL. +const ioport_t *st9_t::find_sym(ea_t address) +{ + return find_ioport(ioh.ports, address); +} + +//---------------------------------------------------------------------- +void st9_t::patch_general_registers() +{ + char b[15]; + b[0] = '\0'; + + ushort style = idpflags & IDP_GR_DEC ? 0 + : idpflags & IDP_GR_HEX ? 1 + : idpflags & IDP_GR_BIN ? 2 + : 3; + + QASSERT(10079, style != 3); + + msg("General register print style: %s\n", + style == 0 ? "decimal" + : style == 1 ? "hexadecimal" + : "binary"); + + CASSERT(sizeof(RegNames) == sizeof(src_RegNames)); + memcpy(RegNames, src_RegNames, sizeof(src_RegNames)); + dynamic_rgnames.resize(rR255 - rR1 + 1); + for ( int i = rR1; i <= rR255; i++ ) + { + switch ( style ) + { + // decimal + case 0: + qsnprintf(b, sizeof b, "R%d", i); + break; + + // hexadecimal + case 1: + qsnprintf(b, sizeof b, "R0x%X", i); + break; + + // binary + case 2: + { + static const int bits[] = { 128, 64, 32, 16, 8, 4, 2, 1 }; + b[0] = 'R'; + for ( int k = 0; k < 8; k++ ) + b[k + 1] = (i & bits[k]) ? '1' : '0'; + b[9] = 'b'; + b[10] = '\0'; + } + break; + } + dynamic_rgnames[i-rR1] = b; + RegNames[i] = dynamic_rgnames[i-rR1].begin(); + } + ph.reg_names = RegNames; +} + +//---------------------------------------------------------------------- +// read all procmod data from the idb +void st9_t::load_from_idb() +{ + idpflags = (uint32)helper.altval(-1); + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +const char *st9_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool idb_loaded) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + + static const char form[] = + "HELP\n" + "ST9 Related options :\n" + "\n" + " General registers print style\n" + "\n" + " Select the format which will be used by IDA to\n" + " to print general registers.\n" + "\n" + " For example,\n" + "\n" + " R10 (decimal) \n" + " R0x0A (hexadecimal) \n" + " R00001010b (binary) \n" + "\n" + "ENDHELP\n" + "ST9 related options\n" + "<##General registers print style##~D~ecimal (default):R>\n" + "<~H~exadecimal:R>\n" + "<~B~inary:R>>\n"; + + CASSERT(sizeof(print_style) == sizeof(ushort)); + if ( ask_form(form, &print_style) ) + { + idpflags = 0; + switch ( print_style ) + { + case 0: idpflags |= IDP_GR_DEC; break; + case 1: idpflags |= IDP_GR_HEX; break; + case 2: idpflags |= IDP_GR_BIN; break; + } + if ( idpflags ) + patch_general_registers(); + } + if ( idb_loaded ) + save_idpflags(); + return IDPOPT_OK; +} + +//-------------------------------------------------------------------------- +// get reference data from ri, +// check compliance of opval and the full value +static bool idaapi dpr_calc_reference_data( + ea_t *target, + ea_t *base, + ea_t from, + const refinfo_t &ri, + adiff_t opval) +{ + if ( ri.base == BADADDR || ri.is_subtract() ) + return false; + + int dpr_reg = rDPR0 + ((opval >> 14) & 3); + sel_t page = get_sreg(from, dpr_reg); + if ( page == BADSEL ) + return false; + + ea_t addr = (page << 14) + (opval & 0x3FFF); + ea_t op_target = ri.base - ri.tdelta + addr; + if ( ri.target != BADADDR && ri.target != op_target ) + return false; + + *target = op_target; + *base = ri.base; + return true; +} + +// complex format with DPR prefix +//lint -e{818} ... parameter 'opval' could be declared as pointing to const +static int idaapi dpr_gen_expr( + qstring * /*buf*/, + qstring *format, + ea_t /*ea*/, + int /*numop*/, + const refinfo_t &/*ri*/, + ea_t /*from*/, + adiff_t *opval, + ea_t * /*target*/, + ea_t * /*fullvalue*/, + int /*getn_flags*/) +{ + int dpr_reg_num = (*opval >> 14) & 3; + format->sprnt(COLSTR("DPR%d:pof", SCOLOR_KEYWORD) "(%%s)", dpr_reg_num); + return 4; // continue standard processing +} + +static const custom_refinfo_handler_t ref_dpr = +{ + sizeof(custom_refinfo_handler_t), + "DPR", + "16-bit offset using DPRx register", + RHF_TGTOPT, // properties: the target can be BADADDR + dpr_gen_expr, // gen_expr + dpr_calc_reference_data, // calc_reference_data + NULL, // get_format +}; + + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(st9_t)); + return 0; +} + +//---------------------------------------------------------------------- +// The kernel event notifications +// Here you may take desired actions upon some kernel events +ssize_t idaapi st9_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + // this processor is big endian + inf_set_be(true); + helper.create(PROCMOD_NODE_NAME); + ref_dpr_id = register_custom_refinfo(&ref_dpr); + break; + + case processor_t::ev_term: + unregister_custom_refinfo(ref_dpr_id); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + if ( inf_like_binary() + && ask_yn(ASKBTN_YES, + "Do you want to split the loaded file contents into 64K banks?") == ASKBTN_YES ) + { + segment_t *s = get_first_seg(); + if ( s != NULL ) + { + ssize_t total = (ssize_t)s->size(); + ea_t ea = s->start_ea; + // align the segment start at the memory bank start + if ( (ea & 0xFFFF) != 0 ) + { + ea_t start = ea & ~0xFFFF; + set_segm_start(ea, start, 0); + ea = start; + } + // each memory bank gets its own segment + while ( 1 ) + { + set_segm_end(ea, ea+0x10000, 0); + total -= 0x10000; + ea += 0x10000; + if ( total <= 0 ) + break; + add_segm(ea>>4, ea, ea+total, NULL, "CODE"); + s = getseg(ea); + if ( !s->is_16bit() ) + { + s->bitness = 0; // use 16-bit segments + s->update(); + } + } + } + // check that a segment at 0...10000 exists + // if not, create it + s = get_first_seg(); + if ( s == NULL || s->start_ea > 0x10000 ) + add_segm(0, 0, 0x10000, NULL, "DATA"); + } + // select_device(inf_like_binary() ? IORESP_ALL : (IORESP_ALL & ~IORESP_AREA)); + // file_loaded = true; + save_idpflags(); + patch_general_registers(); + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // set RW/RP segment registers initial values + s->defsr[rRW-ph.reg_first_sreg] = 0; + s->defsr[rRP-ph.reg_first_sreg] = BADSEL; + } + break; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st9_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st9_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + st9_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + st9_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return st9_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return st9_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_switch: + { + switch_info_t *si = va_arg(va, switch_info_t *); + const insn_t *insn = va_arg(va, const insn_t *); + return st9_is_switch(si, *insn) ? 1 : -1; + } + + case processor_t::ev_is_cond_insn: + ///< Is conditional instruction? + ///< \param insn (const ::insn_t) instruction address + ///< \retval 1 yes + ///< \retval 0 not implemented + ///< \retval -1 no + { + const insn_t *insn = va_arg(va, insn_t *); + return is_jmp_cc(insn->itype) ? 1 : -1; + } + + case processor_t::ev_is_indirect_jump: + { + // jp, call, calls can have indirect register operands (rr), (RR) + const insn_t *insn = va_arg(va, insn_t *); + if ( insn->Op1.type != o_reg || !is_ind(insn->Op1) ) + return 1; // no + if ( insn->itype == st9_jp || insn->itype == st9_call || insn->itype == st9_calls ) + return 2; // yes + else + return 1; // no + } + + + default: + break; + } + return code; +} + +//---------------------------------------------------------------------- +// +// GNU ST9+ Assembler description +// + +// gets a function name +static bool gnu_get_func_name(qstring *name, const func_t *pfn) +{ + ea_t ea = pfn->start_ea; + if ( get_demangled_name(name, ea, inf_get_long_demnames(), DEMNAM_NAME) <= 0 ) + return false; + + tag_addr(name, ea, true); + return true; +} + +//---------------------------------------------------------------------- +// prints function header +static void idaapi gnu_func_header(outctx_t &ctx, func_t *pfn) +{ + ctx.gen_func_header(pfn); + + qstring name; + if ( gnu_get_func_name(&name, pfn) ) + { + int saved_flags = ctx.forbid_annotations(); + ctx.gen_printf(DEFAULT_INDENT, + COLSTR(".desc %s, %s", SCOLOR_ASMDIR), + name.begin(), + pfn->is_far() ? "far" : "near"); + ctx.restore_ctxflags(saved_flags); + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".proc %s", SCOLOR_ASMDIR), name.begin()); + ctx.ctxflags |= CTXF_LABEL_OK; + } + ctx.gen_printf(0, COLSTR("%s:", SCOLOR_ASMDIR), name.begin()); +} + +//---------------------------------------------------------------------- +// prints function footer +//lint -esym(818,pfn) +static void idaapi gnu_func_footer(outctx_t &ctx, func_t *pfn) +{ + qstring name; + if ( gnu_get_func_name(&name, pfn) ) + { + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".endproc", SCOLOR_ASMDIR) COLSTR("%s %s", SCOLOR_ASMDIR), ASH.cmnt, name.begin()); + } +} + +//---------------------------------------------------------------------- +static const asm_t gnu_asm = +{ + AS_COLON + |ASH_HEXF3 // hex 0x123 format + |ASB_BINF0 // bin 0110b format + |ASO_OCTF1 // oct 012345 format + |AS_ASCIIZ // don't display the final 0 in string declarations + |AS_ASCIIC // allow C-style escape sequences + |AS_1TEXT, // 1 text per line, no bytes + 0, + "ST9 GNU Assembler", + 0, + NULL, // no headers + ".org", // origin directive + NULL, // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".byte", // byte directive + ".word", // word directive + ".long", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + +// XXX +// +// .float and .double directives are supposed to be supported by the +// assembler, but when we try to assemble a file including those directives, +// we get this error message : +// +// /vob/st9plus/toolset/src/binutils/gas/config/tc-st9.c(4167): !!! STOP !!! +// -> !(Floating point convertion) + + ".float", // float (4 bytes) + ".double", // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + gnu_func_header, // func_header + gnu_func_footer, // func_footer + ".global", // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +//---------------------------------------------------------------------- +// +// Alfred Arnold's Macro Assembler definition +// + +static const asm_t asw_asm = +{ + AS_COLON + |ASH_HEXF0 // hex 123h format + |ASB_BINF3 // bin 0b010 format + |ASO_OCTF5 // oct 123q format + |AS_1TEXT, // 1 text per line, no bytes + UAS_ASW, + "Alfred Arnold's Macro Assembler", + 0, + NULL, // no headers + "ORG", // origin directive + "END", // end directive + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + "DB", // ascii string directive + "DB", // byte directive (alias: DB) + "DW", // word directive (alias: DW) + "DD", // dword (4 bytes, alias: DD) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + "equ", // Equ + NULL, // seg prefix + "$", // current IP (instruction pointer) symbol in assembler + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + 0, // flag2 ??? + NULL, // comment close string + NULL, // low8 op + NULL, // high8 op + NULL, // low16 op + NULL // high16 op +}; + +static const asm_t *const asms[] = { &gnu_asm, &asw_asm, NULL }; + +// +// Short and long name for our module +// +#define FAMILY "ST9 Family:" + +static const char *const shnames[] = +{ + "st9", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"SGS-Thomson ST9", + NULL +}; + +static const uchar retcode_1[] = { 0x46 }; // ret +static const uchar retcode_2[] = { 0xD3 }; // iret +static const uchar retcode_3[] = { 0xF6, 01 }; // rets +static const uchar retcode_4[] = { 0xEF, 31 }; // eret + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { sizeof(retcode_4), retcode_4 }, + { 0, NULL } // NULL terminated array +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_ST9, // id + // flag + PR_RNAMESOK // can use register names for byte names + | PR_BINMEM // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + | PR_SEGS // has segment registers? + | PR_SGROTHER, // the segment registers don't contain + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // array of short processor names + // the short names are used to specify the processor + // with the -p command line switch) + lnames, // array of long processor names + // the long names are used to build the processor type + // selection menu + + asms, // array of target assemblers + + notify, // the kernel event notification callback + + src_RegNames, // Regsiter names + qnumber(src_RegNames),// Number of registers + + rRW, rDPR3, + 0, // size of a segment register + rCSR, rDPR0, + + NULL, // No known code start sequences + retcodes, + + 0, st9_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 7, 15, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + st9_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/st9/st9.cfg b/idasdk76/module/st9/st9.cfg similarity index 100% rename from idasdk75/module/st9/st9.cfg rename to idasdk76/module/st9/st9.cfg diff --git a/idasdk76/module/st9/st9.hpp b/idasdk76/module/st9/st9.hpp new file mode 100644 index 0000000..709311c --- /dev/null +++ b/idasdk76/module/st9/st9.hpp @@ -0,0 +1,700 @@ + +#ifndef __ST9_HPP +#define __ST9_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include <frame.hpp> +#include <segregs.hpp> +#include <struct.hpp> +#include "../iohandler.hpp" + +#define PROCMOD_NAME st9 +#define PROCMOD_NODE_NAME "$ st9" + +// Operand flags +#define OP_IS_IND 0x00000001 // Operand is indirect, and should be + // printed between (). +#define OP_IMM_NO_SHIFT 0x00000002 // Operand is immediate, and should not + // be prefixed by the '#' character. +#define OP_REG_WITH_BIT 0x00000004 // Operand is register, and a bit number can be + // found in the "value" field. +#define OP_BIT_COMPL 0x00000008 // Bit number is a complement, and should be + // prefixed by the '!' character. +#define OP_DISPL_FUNC_ARG 0x00000010 // Operand is a displacement, and should be considered + // as a function argument variable. +// Flags for ash.uFlag +#define UAS_ASW 0x00000001 // current assembler is ASW. + +inline bool is_ind(const op_t &op) +{ + return (op.specflag1 & OP_IS_IND) != 0; +} + +inline bool is_imm_no_shift(const op_t &op) +{ + return op.type == o_imm && (op.specflag1 & OP_IMM_NO_SHIFT) != 0; +} + +inline bool is_reg_with_bit(const op_t &op) +{ + return op.type == o_reg && (op.specflag1 & OP_REG_WITH_BIT) != 0; +} + +inline bool is_bit_compl(const op_t &op) +{ + return (op.specflag1 & OP_BIT_COMPL) != 0; +} + +// ST9+ registers : +enum st9_registers +{ + rR0, + rR1, + rR2, + rR3, + rR4, + rR5, + rR6, + rR7, + rR8, + rR9, + rR10, + rR11, + rR12, + rR13, + rR14, + rR15, + rR16, + rR17, + rR18, + rR19, + rR20, + rR21, + rR22, + rR23, + rR24, + rR25, + rR26, + rR27, + rR28, + rR29, + rR30, + rR31, + rR32, + rR33, + rR34, + rR35, + rR36, + rR37, + rR38, + rR39, + rR40, + rR41, + rR42, + rR43, + rR44, + rR45, + rR46, + rR47, + rR48, + rR49, + rR50, + rR51, + rR52, + rR53, + rR54, + rR55, + rR56, + rR57, + rR58, + rR59, + rR60, + rR61, + rR62, + rR63, + rR64, + rR65, + rR66, + rR67, + rR68, + rR69, + rR70, + rR71, + rR72, + rR73, + rR74, + rR75, + rR76, + rR77, + rR78, + rR79, + rR80, + rR81, + rR82, + rR83, + rR84, + rR85, + rR86, + rR87, + rR88, + rR89, + rR90, + rR91, + rR92, + rR93, + rR94, + rR95, + rR96, + rR97, + rR98, + rR99, + rR100, + rR101, + rR102, + rR103, + rR104, + rR105, + rR106, + rR107, + rR108, + rR109, + rR110, + rR111, + rR112, + rR113, + rR114, + rR115, + rR116, + rR117, + rR118, + rR119, + rR120, + rR121, + rR122, + rR123, + rR124, + rR125, + rR126, + rR127, + rR128, + rR129, + rR130, + rR131, + rR132, + rR133, + rR134, + rR135, + rR136, + rR137, + rR138, + rR139, + rR140, + rR141, + rR142, + rR143, + rR144, + rR145, + rR146, + rR147, + rR148, + rR149, + rR150, + rR151, + rR152, + rR153, + rR154, + rR155, + rR156, + rR157, + rR158, + rR159, + rR160, + rR161, + rR162, + rR163, + rR164, + rR165, + rR166, + rR167, + rR168, + rR169, + rR170, + rR171, + rR172, + rR173, + rR174, + rR175, + rR176, + rR177, + rR178, + rR179, + rR180, + rR181, + rR182, + rR183, + rR184, + rR185, + rR186, + rR187, + rR188, + rR189, + rR190, + rR191, + rR192, + rR193, + rR194, + rR195, + rR196, + rR197, + rR198, + rR199, + rR200, + rR201, + rR202, + rR203, + rR204, + rR205, + rR206, + rR207, + rR208, + rR209, + rR210, + rR211, + rR212, + rR213, + rR214, + rR215, + rR216, + rR217, + rR218, + rR219, + rR220, + rR221, + rR222, + rR223, + rR224, + rR225, + rR226, + rR227, + rR228, + rR229, + rR230, + rR231, + rR232, + rR233, + rR234, + rR235, + rR236, + rR237, + rR238, + rR239, + rR240, + rR241, + rR242, + rR243, + rR244, + rR245, + rR246, + rR247, + rR248, + rR249, + rR250, + rR251, + rR252, + rR253, + rR254, + rR255, + rRR0, + rRR1, + rRR2, + rRR3, + rRR4, + rRR5, + rRR6, + rRR7, + rRR8, + rRR9, + rRR10, + rRR11, + rRR12, + rRR13, + rRR14, + rRR15, + rRR16, + rRR17, + rRR18, + rRR19, + rRR20, + rRR21, + rRR22, + rRR23, + rRR24, + rRR25, + rRR26, + rRR27, + rRR28, + rRR29, + rRR30, + rRR31, + rRR32, + rRR33, + rRR34, + rRR35, + rRR36, + rRR37, + rRR38, + rRR39, + rRR40, + rRR41, + rRR42, + rRR43, + rRR44, + rRR45, + rRR46, + rRR47, + rRR48, + rRR49, + rRR50, + rRR51, + rRR52, + rRR53, + rRR54, + rRR55, + rRR56, + rRR57, + rRR58, + rRR59, + rRR60, + rRR61, + rRR62, + rRR63, + rRR64, + rRR65, + rRR66, + rRR67, + rRR68, + rRR69, + rRR70, + rRR71, + rRR72, + rRR73, + rRR74, + rRR75, + rRR76, + rRR77, + rRR78, + rRR79, + rRR80, + rRR81, + rRR82, + rRR83, + rRR84, + rRR85, + rRR86, + rRR87, + rRR88, + rRR89, + rRR90, + rRR91, + rRR92, + rRR93, + rRR94, + rRR95, + rRR96, + rRR97, + rRR98, + rRR99, + rRR100, + rRR101, + rRR102, + rRR103, + rRR104, + rRR105, + rRR106, + rRR107, + rRR108, + rRR109, + rRR110, + rRR111, + rRR112, + rRR113, + rRR114, + rRR115, + rRR116, + rRR117, + rRR118, + rRR119, + rRR120, + rRR121, + rRR122, + rRR123, + rRR124, + rRR125, + rRR126, + rRR127, + rRR128, + rRR129, + rRR130, + rRR131, + rRR132, + rRR133, + rRR134, + rRR135, + rRR136, + rRR137, + rRR138, + rRR139, + rRR140, + rRR141, + rRR142, + rRR143, + rRR144, + rRR145, + rRR146, + rRR147, + rRR148, + rRR149, + rRR150, + rRR151, + rRR152, + rRR153, + rRR154, + rRR155, + rRR156, + rRR157, + rRR158, + rRR159, + rRR160, + rRR161, + rRR162, + rRR163, + rRR164, + rRR165, + rRR166, + rRR167, + rRR168, + rRR169, + rRR170, + rRR171, + rRR172, + rRR173, + rRR174, + rRR175, + rRR176, + rRR177, + rRR178, + rRR179, + rRR180, + rRR181, + rRR182, + rRR183, + rRR184, + rRR185, + rRR186, + rRR187, + rRR188, + rRR189, + rRR190, + rRR191, + rRR192, + rRR193, + rRR194, + rRR195, + rRR196, + rRR197, + rRR198, + rRR199, + rRR200, + rRR201, + rRR202, + rRR203, + rRR204, + rRR205, + rRR206, + rRR207, + rRR208, + rRR209, + rRR210, + rRR211, + rRR212, + rRR213, + rRR214, + rRR215, + rRR216, + rRR217, + rRR218, + rRR219, + rRR220, + rRR221, + rRR222, + rRR223, + rRR224, + rRR225, + rRR226, + rRR227, + rRR228, + rRR229, + rRR230, + rRR231, + rRR232, + rRR233, + rRR234, + rRR235, + rRR236, + rRR237, + rRR238, + rRR239, + rRR240, + rRR241, + rRR242, + rRR243, + rRR244, + rRR245, + rRR246, + rRR247, + rRR248, + rRR249, + rRR250, + rRR251, + rRR252, + rRR253, + rRR254, + rRR255, + rr0, + rr1, + rr2, + rr3, + rr4, + rr5, + rr6, + rr7, + rr8, + rr9, + rr10, + rr11, + rr12, + rr13, + rr14, + rr15, + rrr0, + rrr1, + rrr2, + rrr3, + rrr4, + rrr5, + rrr6, + rrr7, + rrr8, + rrr9, + rrr10, + rrr11, + rrr12, + rrr13, + rrr14, + rrr15, + rRW, // register window number + rRP, // register page + rCSR, // code segment register + rDPR0, rDPR1, rDPR2, rDPR3, // Data page registers + st9_lastreg = rDPR3, +}; + +// ST9 condition codes +enum st9_cond_codes +{ + cUNKNOWN, + cF, // always false + cT, // always true + cC, // carry + cNC, // not carry + cZ, // zero + cNZ, // not zero + cPL, // plus + cMI, // minus + cOV, // overflow + cNOV, // no overflow + cEQ, // equal + cNE, // not equal + cGE, // greater than or equal + cLT, // less than + cGT, // greater than + cLE, // less than or equal + cUGE, // unsigned greated than or equal + cUL, // unsigned less than + cUGT, // unsigned greater than + cULE // unsigned less than or equal +}; + +enum st9_phrases ENUM_SIZE(uint8) +{ + fPI, // post incrementation (rr)+ + fPD, // pre decrementation -(rr) + fDISP // displacement rrx(rry) +}; + +inline bool is_jmp_cc(int insn) +{ + return insn == st9_jpcc || insn == st9_jrcc; +} + +//------------------------------------------------------------------ +struct st9_iohandler_t : public iohandler_t +{ + struct st9_t ± + st9_iohandler_t(st9_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} +}; + +struct st9_t : public procmod_t +{ + // The netnode helper. + // Using this node we will save current configuration information in the + // IDA database. + netnode helper; + st9_iohandler_t ioh = st9_iohandler_t(*this, helper); + + const char *RegNames[st9_lastreg + 1]; + qstrvec_t dynamic_rgnames; // dynamically generated names for rR1..rR255 + + const char *gr_cmt = nullptr; + int ref_dpr_id; // id of refinfo handler +#define IDP_GR_DEC 0x0001 // print general registers in decimal format +#define IDP_GR_HEX 0x0002 // print general registers in hexadecimal format +#define IDP_GR_BIN 0x0004 // print general registers in binary format + uint32 idpflags = IDP_GR_DEC; + ushort print_style = 3; + bool flow; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const ioport_t *find_sym(ea_t address); + void patch_general_registers(); + const char *set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool idb_loaded); + + int st9_emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &op, bool lwrite); + bool create_func_frame(func_t *pfn) const; + + void st9_assumes(outctx_t &ctx); + void st9_footer(outctx_t &ctx) const; + void st9_segstart(outctx_t &ctx, segment_t *Sarea) const; + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); +}; +extern int data_id; + +// exporting our routines +void idaapi st9_header(outctx_t &ctx); +int idaapi st9_ana(insn_t *insn); +ea_t get_dest_addr(const insn_t &insn, const op_t &x); +bool st9_is_switch(switch_info_t *si, const insn_t &insn); + +extern const char *const ConditionCodes[]; + +#endif /* __ST9_HPP */ diff --git a/idasdk76/module/tlcs900/ana.cpp b/idasdk76/module/tlcs900/ana.cpp new file mode 100644 index 0000000..5add3e6 --- /dev/null +++ b/idasdk76/module/tlcs900/ana.cpp @@ -0,0 +1,1106 @@ +/* + * TLCS900 processor module for IDA. + * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "tosh.hpp" + +// (number of bytes -1) -> dtype +static const uchar bt_type[4]= { dt_byte, dt_word, dt_tbyte, dt_dword }; + +// power of 2 -> dtype +static const uchar btp_type[4]= { dt_byte, dt_word, dt_dword, uchar(-1) }; + +// memory reference (o_mem/o_displ) +struct MemRefDef +{ + uint32 disp; // offset + ushort off_pos; // place of offset in insn (if any) + optype_t type; // dtype: o_mem/o_displ + uchar flags; // flags + uchar base_reg; // base reg + uchar add_reg; // additional reg (DAfull number) + uchar inc_size; // increment size (+/-4) + uchar dtype; +}; + +//----------------------------------------------------------------------------- +// short reg to full reg +static uchar Reg7ToFull(uchar reg7, uchar size) +{ + reg7&=7; // fix reg number + // byte reg + if ( size == 0 ) + return 0xE0+(1-(reg7&1))+(reg7&6)*2; + // word or double wor dreg + return 0xE0+reg7*4; +} + +//----------------------------------------------------------------------------- +// set number of the reg into operand +// reg_code - byte reg num +// size - 0,1,2 (2^x bytes) +static void SetRegistr(op_t &op, uchar reg_code, uchar size) +{ + op.type=o_reg; + op.addr=op.value=reg_code; + op.dtype = btp_type[size&3]; +} + +//----------------------------------------------------------------------------- +// set register +// regcode - reg number (3 bits) +// size - 0,1,2 (2^x bytes) +static void SetRegistr7(op_t &op, uchar regcode, uchar size) +{ + SetRegistr(op, Reg7ToFull(regcode, size), size); +} + +//----------------------------------------------------------------------------- +// load N ibytes and return result +static uint32 LoadDataValue(insn_t &insn, int bytes) +{ + uint32 val=0; + for ( int i=0; i < bytes; i++ ) + val |= ((uint32)insn.get_next_byte())<<(8*i); + return val; +} + +//----------------------------------------------------------------------------- +// currnet bytes are the memory address +// len - number of bytes +static void SetDirectMemRef(insn_t &insn, op_t &op, int len) +{ + op.type = o_mem; + // elem offset + op.offb = (uchar)insn.size; + // size of offset + op.dtype = bt_type[(len-1)&3]; + // elem value + op.addr = op.value = LoadDataValue(insn, len); +} + +//----------------------------------------------------------------------------- +// code ref +static void SetJmp(insn_t &insn, op_t &op, int len) +{ + op.type = o_near; + op.offb = (uchar)insn.size; + op.dtype = dt_dword; + if ( len > 0 ) + { + // absolute + op.addr = op.value = LoadDataValue(insn, len); + } + else + { + // relative + len = -len; + op.addr = LoadDataValue(insn, len); + // sig + if ( op.addr & (uval_t(1)<<(8*len-1)) ) + { + op.addr |= BADADDR<<(8*len); + } + // target offset + op.addr += insn.ip + insn.size; + op.value = op.addr; + } +} + +//----------------------------------------------------------------------------- +// MemRef to Operand +static void MemRefToOp(op_t &op, const MemRefDef &mr) +{ + op.value = mr.disp; + op.addr = mr.disp; + op.dtype = mr.dtype; + op.reg = mr.base_reg; + op.specflag2 = mr.inc_size; + op.offb = (uchar)mr.off_pos; + op.specval_shorts.low = mr.add_reg; + op.specflag1 = mr.flags; + op.type = mr.type; +} + +//----------------------------------------------------------------------------- +// load memory ref +// first_code - firt insn byte +static int LoadMemRef(insn_t &insn, MemRefDef &mr, uchar first_code) +{ + memset(&mr, 0, sizeof(mr)); + mr.dtype = btp_type[(first_code>>4)&3]; + if ( (first_code&0x40) == 0 ) + { + // ref is reg (with offset or not) + mr.type = o_displ; + // reg name + mr.base_reg = Reg7ToFull(first_code, 2); + if ( first_code&0x8 ) + { + // offset + mr.off_pos = insn.size; + mr.disp = insn.get_next_byte(); + } + } + else + { + switch ( first_code & 7 ) + { + // direct, byte + case 0: + mr.off_pos = insn.size; + mr.disp = LoadDataValue(insn, 1); + mr.type = o_mem; + break; + // direct, word + case 1: + mr.off_pos = insn.size; + mr.disp = LoadDataValue(insn, 2); + mr.type = o_mem; + break; + // direct, 24 bit + case 2: + mr.off_pos=insn.size; + mr.disp=LoadDataValue(insn, 3); + mr.type=o_mem; + break; + // two regs + case 3: + { + uchar mem_val; + mr.type = o_displ; + mem_val = insn.get_next_byte(); + if ( (mem_val&2) == 0 ) + { + // with reg + mr.base_reg = mem_val & 0xFC; + // and ofsset? + if ( mem_val&1 ) + { + mr.off_pos = insn.size; + mr.disp = LoadDataValue(insn, 2); + } + } + else + { // two regs + if ( (mem_val&1) == 0 ) + return 0; // wrong + if ( (mem_val>>2) > 1 ) + { + // LDAR! + // check for F3/13 + //msg("Ldar Op"); + if ( first_code == 0xF3 && mem_val == 0x13 ) + { + // yes! + insn.itype=T900_ldar; + // elem offset + insn.Op2.offb=(uchar)insn.size; + uint32 target=LoadDataValue(insn, 2); + target+=uint32(insn.ea+4); + insn.Op2.type=o_mem; + // size of offset + insn.Op2.dtype = dt_word; + // elem value + insn.Op2.addr = insn.Op2.value = target; + // get reg + mem_val=insn.get_next_byte(); + // available? + if ( (mem_val&0xE8) != 0x20 ) + return 0; + SetRegistr7(insn.Op1, mem_val, ((mem_val>>4)-1)&3); + //msg("ldar ok"); + return 1; + } + return 0; + } + mr.base_reg = insn.get_next_byte(); // 1st reg + mr.add_reg = insn.get_next_byte(); // 2nd reg + if ( mem_val & 0x4 ) + mr.flags|=URB_WORD;// 2nd reg - word + } + } + break; + // inc/dec + case 4: + case 5: + { + uchar regg = insn.get_next_byte(); + if ( (regg&3) == 3 ) + return 0; + mr.type = o_displ; + mr.base_reg = regg&0xFC; + mr.inc_size = 1<<(regg&3); + // negative inc + if ( (first_code&1) == 0 ) + mr.inc_size|=URB_DECR; + } + break; + } + } + return 1; +} + +//----------------------------------------------------------------------------- +static void SetImmData(insn_t &insn, op_t &op, int bytes) +{ + op.type = o_imm; + op.offb = (uchar)insn.size; + op.dtype = bt_type[(bytes-1)&3]; + op.addr = op.value = LoadDataValue(insn, bytes); +} + +//----------------------------------------------------------------------------- +static void SetImm8Op(op_t &op, uchar code) +{ + op.type = o_imm; + op.dtype = dt_byte; // actually, it is not a byte + op.flags |= OF_NUMBER; + op.addr = op.value = code; +} + +//----------------------------------------------------------------------------- +// set imm3 for inc/dec +static void SetImm3Op(op_t &op, uchar code) +{ + code &= 7; + SetImm8Op(op, code ? code : 8); +} + +//----------------------------------------------------------------------------- +// condition phrase +static void SetCondOp(op_t &op, int cond) +{ + static const uchar cond_p[16] = + { + fCF, fCLT, fCLE, fCULE, fCPE, fCMI, fCZ, fCC, + fCT, fCGE, fCGT, fCUGT, fCPO, fCPL, fCNZ, fCNC + }; + op.type = o_phrase; + op.phrase = cond_p[cond&0xf]; +} + +//----------------------------------------------------------------------------- +// arith insns +static const uchar Add_List[8] = +{ + T900_add, T900_adc, T900_sub, T900_sbc, + T900_and, T900_xor, T900_or, T900_cp +}; + +// shift insns (not simple) +static const uchar Shift_List[8] = +{ + T900_rlc, T900_rrc, T900_rl, T900_rr, + T900_sla, T900_sra, T900_sll, T900_srl +}; + +// shift for memory cells +static const uchar Shift_List1[8] = +{ + T900_rlc_mem, T900_rrc_mem, T900_rl_mem, T900_rr_mem, + T900_sla_mem, T900_sra_mem, T900_sll_mem, T900_srl_mem +}; + +// flag C +static const uchar COp_List[5] = +{ + T900_andcf, T900_orcf, T900_xorcf, T900_ldcf, T900_stcf +}; + +// other flag C +static const uchar COp2_List[5] = +{ + T900_res, T900_set, T900_chg, T900_bit, T900_tset +}; + +//----------------------------------------------------------------------------- +// parse regs +static int RegAnalyser(insn_t &insn, uchar code) +{ + static const uchar reg_codes[32] = + { + 255, 255, 255, 255, + T900_andcf, T900_andcf, T900_res, T900_minc1, + T900_mul, T900_muls, T900_div, T900_divs, + T900_inc, T900_dec, T900_scc, T900_scc, + T900_add, T900_ld, T900_adc, T900_ld, + T900_sub, T900_ld, T900_sbc, T900_ex, + T900_and, 254, T900_xor, 253, + T900_or, T900_rlc, T900_cp, T900_rlc + }; + uchar reg_size = (code>>4) & 3; // 0 - byte, 1 - word, 2 - long + uchar reg_num; // byte reg number + if ( code & 8 ) + { + reg_num = Reg7ToFull(code, reg_size); + } + else + { // aux byte + reg_num = insn.get_next_byte(); + } + uchar reg_op = 0; // Op1 is reg by default + uchar reg_byte = insn.get_next_byte(); + insn.itype = reg_codes[(reg_byte>>3)&0x1F]; + switch ( insn.itype ) + { + case T900_ex: + case T900_add: + case T900_adc: + case T900_sub: + case T900_sbc: + case T900_and: + case T900_xor: + case T900_or: + case T900_cp: + SetRegistr7(insn.Op1, reg_byte, reg_size); + reg_op=1; + break; + + case 255: + { + static const uchar LCodes[] = + { + 0, 0, 0, T900_ld, + T900_push, T900_pop, T900_cpl, T900_neg, + T900_mul, T900_muls, T900_div, T900_divs, + T900_link, T900_unlk, T900_bs1f, T900_bs1b, + T900_daa, 0, T900_extz, T900_exts, + T900_paa, 0, T900_mirr, 0, + 0, T900_mula, 0, 0, + T900_djnz, 0, 0, 0 + }; + + if ( reg_byte >= qnumber(LCodes) ) + return 0; + + insn.itype = LCodes[reg_byte]; + switch ( insn.itype ) + { + // illegal + case 0: + return 0; + + // LD r, # + case T900_ld: + SetImmData(insn, insn.Op2, 1<<reg_size); + break; + + // MUL rr, # + // DIV rr, # + case T900_div: + case T900_divs: + case T900_mul: + case T900_muls: + SetImmData(insn, insn.Op2, 1<<reg_size); + // hig reg used + reg_size++; + if ( reg_size == 3 ) + return 0; + break; + + // LINK r, dd + case T900_link: + SetImmData(insn, insn.Op2, 2); + break; + + // BS1F A,r + case T900_bs1f: + case T900_bs1b: + SetRegistr7(insn.Op1, 1, 0); + reg_op=1; + break; + // MULA r + case T900_mula: + // high reg used + reg_size++; + if ( reg_size == 3 ) + return 0; + break; + // DJNZ r, d + case T900_djnz: + SetJmp(insn, insn.Op2, -1); + break; + } + } + break; + + // ANDCF-STCF XXX #, r + case T900_andcf: + if ( reg_byte > 0x2C ) + { + switch ( reg_byte ) + { + case 0x2D: + return 0; + // compilcated insn LDC - skip it for now + case 0x2E: + SetImmData(insn, insn.Op1, 1); + reg_op=1; + break; + case 0x2F: + SetImmData(insn, insn.Op2, 1); + break; + } + insn.itype=T900_ldc; + } + else if ( (reg_byte&7) < 5 ) // not an LDC + { + reg_op = 1; + insn.itype = COp_List[reg_byte&7]; + if ( reg_byte & 8 ) + SetRegistr7(insn.Op1, 1, 0); + else + SetImmData(insn, insn.Op1, 1); + } + else + { + return 0; + } + break; + + // RES-TSET + case T900_res: + if ( (reg_byte&7) > 4 ) + return 0; + insn.itype = COp2_List[reg_byte&7]; + SetImmData(insn, insn.Op1, 1); + reg_op = 1; + break; + + // MINC/MDEC + case T900_minc1: + { + static const uchar dinc[8] = + { + T900_minc1, T900_minc2, T900_minc4, 0, + T900_mdec1, T900_mdec2, T900_mdec4, 0 + }; + if ( (insn.itype=dinc[reg_byte&7]) == 0 ) + return 0; + SetImmData(insn, insn.Op1, 2); + // fix op + insn.Op1.value += uval_t(1)<<(reg_byte&3); + insn.Op1.addr = insn.Op1.value; + reg_op = 1; + } + break; + // mul/div XXX R, r + case T900_mul: + case T900_muls: + case T900_div: + case T900_divs: + SetRegistr7(insn.Op1, reg_size == 0 ? (reg_byte&7)/2 : reg_byte, reg_size+1); + reg_op=1; + break; + + // INC/DEC #3, r + case T900_inc: + case T900_dec: + SetImm3Op(insn.Op1, reg_byte); + reg_op=1; + break; + + // set SCC, r + case T900_scc: + SetCondOp(insn.Op1, reg_byte&0xF); + reg_op=1; + break; + // LD + case T900_ld: + if ( reg_byte < 0x90 ) + reg_op = 1; + if ( reg_byte < 0xA0 ) + SetRegistr7(insn.ops[1-reg_op], reg_byte, reg_size); + else + SetImm8Op(insn.Op2, reg_byte&7); + break; + + // another arithmetics XXX r, #) + case 254: + insn.itype=Add_List[reg_byte&7]; + SetImmData(insn, insn.Op2, 1<<reg_size); + break; + // CP r, #3 + case 253: + insn.itype=T900_cp; + SetImm8Op(insn.Op2, reg_byte&7); + break; + // shifts + case T900_rlc: + insn.itype=Shift_List[reg_byte&7]; + if ( reg_byte >= 0xF8 ) + { + SetRegistr7(insn.Op1, 1, 0); + } + else + { + uchar ShL = insn.get_next_byte(); + SetImm8Op(insn.Op1, ShL == 0 ? 16 : ShL); + } + reg_op = 1; + break; + default: + return 0; + } + // set reg + SetRegistr(insn.ops[reg_op], reg_num, reg_size); + return insn.size; +} + +//----------------------------------------------------------------------------- +// parse 2nd byte DST +static int DSTAnalyser(insn_t &insn, uchar code) +{ + // memory op number + char memrefop = 1; + MemRefDef mr; // memory ref + // main opcodes + static const uchar dst_codes[32] = + { + 255, 0, 255, 0, + T900_lda, 255, T900_lda, 0, + T900_ld, 0, T900_ldw, 0, + T900_ld, 0, 0, 0, + T900_andcf, T900_orcf, T900_xorcf, T900_ldcf, + T900_stcf, T900_tset, T900_res, T900_set, + T900_chg, T900_bit, T900_jp_cond, T900_jp_cond, + T900_call, T900_call, T900_ret_cond, T900_ret_cond + }; + // get mem ref + if ( LoadMemRef(insn, mr, code) == 0 ) + return 0; + // check for LDAR + if ( insn.itype == T900_ldar ) + return insn.size; + // opcode + uchar dst_byte = insn.get_next_byte(); + // need to check for mr.dtyp - byte by default + mr.dtype = dt_byte; + + insn.itype=dst_codes[(dst_byte>>3)&0x1F]; + switch ( insn.itype ) + { + case 0: + return 0; + + // go further + case 255: + if ( dst_byte < 0x2D && dst_byte >= 0x28 ) + { + // bit insn + insn.itype = COp_List[dst_byte-0x28]; + // reg A + SetRegistr7(insn.Op1, 1, 0); + // mem ref + break; + } + + switch ( dst_byte ) + { + // ld byte + case 0x00: + insn.itype=T900_ld; + SetImmData(insn, insn.Op2, 1); + memrefop=0; + break; + + // ld word + case 0x02: + insn.itype = T900_ldw; + SetImmData(insn, insn.Op2, 2); + mr.dtype = dt_word; + memrefop = 0; + break; + + // pop byte + case 0x04: + insn.itype=T900_pop; + memrefop=0; + break; + + // pop word + case 0x06: + insn.itype = T900_popw; + mr.dtype = dt_word; + memrefop = 0; + break; + + // ld byte xx + case 0x14: + insn.itype = T900_ld; + SetDirectMemRef(insn, insn.Op2, 2); + memrefop = 0; + break; + + // ld word + case 0x16: + insn.itype = T900_ldw; + SetDirectMemRef(insn, insn.Op2, 2); + mr.dtype = dt_word; + memrefop = 0; + break; + + + default: + return 0; + } + break; + // load 40, 50, 60 + case T900_ldw: + case T900_ld: + SetRegistr7(insn.Op2, dst_byte, (dst_byte>>4)&0x3); + mr.dtype = btp_type[(dst_byte>>4)&3]; + memrefop = 0; + break; + // load 20, 30 + case T900_lda: + { + uchar size = ((dst_byte>>4)&0x3)-1; + SetRegistr7(insn.Op1, dst_byte, size); + mr.dtype = btp_type[size]; + mr.flags |= URB_LDA|URB_LDA2;// address, not data! + } + break; + // branches + case T900_jp_cond: + if ( (dst_byte&0xF) == 0x8 ) + insn.itype=T900_jp; + // fallthrough + case T900_call: // set cond code + SetCondOp(insn.Op1, dst_byte&0xF); + mr.flags |= URB_LDA; // address, not data! + break; + // return + case T900_ret_cond: // 1st byte == 0xb0 + if ( code != 0xB0 ) + return 0; + if ( (dst_byte&0xF) == 0x8 ) + insn.itype=T900_ret; + SetCondOp(insn.Op1, dst_byte&0xF); + return insn.size; + + // ANDCF, .... + default: + SetImm8Op(insn.Op1, dst_byte&7); + break; + } + MemRefToOp(insn.ops[uchar(memrefop)], mr); + return insn.size; +} + +//----------------------------------------------------------------------------- +static int SRCAnalyser(insn_t &insn, uchar code) +{ + uchar memrefop=1; // number of operand with mem ref + MemRefDef mr; + static const uchar aa[] = + { + 255, 0, 255, 255, + T900_ld, 0, T900_ex, 254, + T900_mul, T900_muls, T900_div, T900_divs, + T900_inc, T900_dec, 0, 253, + T900_add, T900_add, T900_adc, T900_adc, + T900_sub, T900_sub, T900_sbc, T900_sbc, + T900_and, T900_and, T900_xor, T900_xor, + T900_or, T900_or, T900_cp, T900_cp + }; + + if ( LoadMemRef(insn, mr, code) == 0 ) + return 0; + uchar src_byte = insn.get_next_byte(); + insn.itype=aa[(src_byte>>3)&0x1F]; + uchar reg_size = (code>>4)&3; // 0, 1, 2 + switch ( insn.itype ) + { + case 0: + return 0; + + case 255: + switch ( src_byte ) + { + default: + return 0; + // push + case 4: + insn.itype=T900_push; + memrefop=0; + break; + // rld + case 6: + insn.itype=T900_rld; + SetRegistr7(insn.Op1, 1, 0); + break; + // rrd + case 7: + insn.itype=T900_rrd; + SetRegistr7(insn.Op1, 1, 0); + break; + // ldi + case 0x10: + insn.itype=T900_ldi; + mr.inc_size|=URB_UINC; + mr.base_reg--; + MemRefToOp(insn.Op1, mr); + mr.base_reg++; + if ( reg_size ) + insn.itype++; + break; + // ldir + case 0x11: + insn.itype=T900_ldir; + mr.inc_size|=URB_UINC; + mr.base_reg--; + MemRefToOp(insn.Op1, mr); + mr.base_reg++; + if ( reg_size ) + insn.itype++; + break; + // ldd + case 0x12: + insn.itype=T900_ldd; + mr.inc_size|=URB_UDEC; + mr.base_reg--; + MemRefToOp(insn.Op1, mr); + mr.base_reg++; + if ( reg_size ) + insn.itype++; + break; + // lddr + case 0x13: + insn.itype=T900_lddr; + mr.inc_size|=URB_UDEC; + mr.base_reg--; + MemRefToOp(insn.Op1, mr); + mr.base_reg++; + if ( reg_size ) + insn.itype++; + break; + // cpi + case 0x14: + insn.itype=T900_cpi; + mr.inc_size|=URB_UINC; + if ( reg_size ) + SetRegistr7(insn.Op1, 0, 1); + else + SetRegistr7(insn.Op1, 1, 0); + break; + // cpir + case 0x15: + insn.itype=T900_cpir; + mr.inc_size|=URB_UINC; + if ( reg_size ) + SetRegistr7(insn.Op1, 0, 1); + else + SetRegistr7(insn.Op1, 1, 0); + break; + // cpd + case 0x16: + insn.itype=T900_cpd; + mr.inc_size|=URB_UDEC; + if ( reg_size ) + SetRegistr7(insn.Op1, 0, 1); + else + SetRegistr7(insn.Op1, 1, 0); + break; + // cpdr + case 0x17: + insn.itype=T900_cpdr; + mr.inc_size|=URB_UDEC; + if ( reg_size ) + SetRegistr7(insn.Op1, 0, 1); + else + SetRegistr7(insn.Op1, 1, 0); + break; + // ld + case 0x19: + if ( code&0x10 ) + insn.itype=T900_ldw; + else + insn.itype=T900_ld; + SetDirectMemRef(insn, insn.Op1, 2); + break; + } + break; + // add and others + case 254: + insn.itype=Add_List[src_byte&7]; + SetImmData(insn, insn.Op2, 1<<((code>>4)&3)); + // word size + if ( reg_size != 0 ) + insn.itype++; + memrefop=0; + break; + // shifts xxxx (mem) + case 253: + insn.itype=Shift_List1[src_byte&7]; + // word size + if ( reg_size != 0 ) + insn.itype++; + memrefop=0; + break; + // inc + case T900_inc: + case T900_dec: + SetImm3Op(insn.Op1, src_byte); + // wor size + if ( reg_size != 0 ) + insn.itype++; + break; + + case T900_ld: + SetRegistr7(insn.Op1, src_byte, reg_size); + break; + // mul/div + case T900_mul: + case T900_div: + case T900_muls: + case T900_divs: + SetRegistr7(insn.Op1, reg_size == 0 ? (src_byte&7)/2 : src_byte, reg_size+1); + break; + // ex + case T900_ex: + SetRegistr7(insn.Op2, src_byte, reg_size); + memrefop=0; + break; + // add and others + case T900_add: + case T900_adc: + case T900_sub: + case T900_sbc: + case T900_and: + case T900_xor: + case T900_or: + case T900_cp: + if ( src_byte&0x8 ) + memrefop=0; + SetRegistr7(insn.ops[1-memrefop], src_byte, reg_size); + break; + } + MemRefToOp(insn.ops[memrefop], mr); + return insn.size; +} + +//----------------------------------------------------------------------------- +static void ClearOperand(op_t &op) +{ + op.dtype = dt_byte; + op.type = o_void; + op.specflag1 = 0; + op.specflag2 = 0; + op.offb = 0; + op.offo = 0; + op.reg = 0; + op.value = 0; + op.addr = 0; + op.specval = 0; +} + +//----------------------------------------------------------------------------- +int idaapi T900_ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + + ClearOperand(insn.Op1); + ClearOperand(insn.Op2); + ClearOperand(insn.Op3); + + uchar code = insn.get_next_byte(); + // split u pto two parts + if ( code&0x80 ) + { + // check for illegal + if ( (code&0xF8) == 0xF8 ) + { + // SWI (F8-FF) + insn.itype=T900_swi; + // trap number + SetImm8Op(insn.Op1, code&7); + // trap addres - is not working for now + insn.Op1.addr = 0xFFFF00+(code&7)*4; + insn.Op1.value = insn.Op1.addr; + return insn.size; + } + if ( code == 0xF7 ) + { + // LDX + insn.itype=T900_ldx; + // skip zero byte + if ( insn.get_next_byte() != 0 ) + return 0; + // address is in regs + SetDirectMemRef(insn, insn.Op1, 1); + // skip zero byte + if ( insn.get_next_byte() != 0 ) + return 0; + // data + SetImmData(insn, insn.Op2, 1); + // length is 6 bytes + insn.size = 6; + return insn.size; + } + // unknow codes (C6, D6, E6, F6) + if ( (code & 0xCF) == 0xC6 ) + return 0; + // large general reg (C8, D8, E8) + if ( (code & 0x48) == 0x48 ) + return RegAnalyser(insn, code); + // is smart reg ? (C7, D7, E7, F7) + if ( (code & 0xCF) == 0xC7 ) + return RegAnalyser(insn, code); + // memref + // segments dst (B0, B8, F0) + if ( (code & 0xB0) == 0xB0 ) + return DSTAnalyser(insn, code); + // src + return SRCAnalyser(insn, code); + } + // low part + else if ( code < 0x20 ) + { + static const uchar FirstOp[] = + { + T900_nop, T900_normal, T900_push, T900_pop, + T900_max, T900_halt, T900_ei, T900_reti, + T900_ld, T900_push, T900_ldw, T900_pushw, + T900_incf, T900_decf, T900_ret, T900_retd, + T900_rcf, T900_scf, T900_ccf, T900_zcf, + T900_push, T900_pop, T900_ex, T900_ldf, + T900_push, T900_pop, T900_jp, T900_jp, + T900_call, T900_call, T900_calr, 0 + }; + insn.itype = FirstOp[code]; + switch ( insn.itype ) + { + case 0x00: + return 0; + + case T900_push: + case T900_pop: + switch ( code&0x18 ) + { + case 0x00: + insn.Op1.type=o_phrase; + insn.Op1.phrase=fSR; + break; + // push only + case 0x08: + SetImmData(insn, insn.Op1, 1); + break; + // xxx A + case 0x10: + SetRegistr7(insn.Op1, 1, 0); + break; + // xxx F + case 0x18: + insn.Op1.type=o_phrase; + insn.Op1.phrase=fSF; + break; + } + break; + // ei + case T900_ei: // next byte is imm + SetImmData(insn, insn.Op1, 1); + if ( insn.Op1.value == 7 ) + { + insn.itype=T900_di; + insn.Op1.type=o_void; + } + break; + // ld (n), n + case T900_ld: + SetDirectMemRef(insn, insn.Op1, 1); + SetImmData(insn, insn.Op2, 1); + break; + + // ldw + case T900_ldw: + SetDirectMemRef(insn, insn.Op1, 1); + SetImmData(insn, insn.Op2, 2); + break; + // pushW + // retd + case T900_pushw: + case T900_retd: + SetImmData(insn, insn.Op1, 2); + break; + // ex F, F' + case T900_ex: + insn.Op1.type = o_phrase; + insn.Op1.phrase = fSF; + insn.Op2.type = o_phrase; + insn.Op2.phrase = fSF1; + break; + // ldf + case T900_ldf: + SetImmData(insn, insn.Op1, 1); + break; + + case T900_jp: + case T900_call: + SetJmp(insn, insn.Op1, 2+(code&1)); + insn.Op1.specflag1 |= URB_LDA; + break; + + // callr 16 + case T900_calr: + SetJmp(insn, insn.Op1, -2); + insn.Op1.specflag1 |= URB_LDA; + break; + } + } + else + { + switch ( code & 0x78 ) + { + // ld + case 0x20: + case 0x30: + case 0x40: + insn.itype=T900_ld; + SetRegistr7(insn.Op1, code, (code>>4)-2); + SetImmData(insn, insn.Op2, 1<<((code>>4)-2)); + break; + // push + case 0x28: + case 0x38: + insn.itype=T900_push; + SetRegistr7(insn.Op1, code, (code>>4)-1); + break; + // pop + case 0x48: + case 0x58: + insn.itype=T900_pop; + SetRegistr7(insn.Op1, code, (code>>4)-3); + break; + // reserved + case 0x50: + return 0; + // JR + case 0x60: + case 0x68: + if ( (code&0xF) == 0x8 ) + insn.itype = T900_jr; + else + insn.itype = T900_jr_cond; + SetCondOp(insn.Op1, code&0xF); + SetJmp(insn, insn.Op2, -1); + insn.Op2.specflag1|=URB_LDA; + break; + // JRL + case 0x70: + case 0x78: + if ( (code&0xF) == 0x8 ) + insn.itype=T900_jrl; + else + insn.itype=T900_jrl_cond; + SetCondOp(insn.Op1, code&0xF); + SetJmp(insn, insn.Op2, -2); + insn.Op2.specflag1 |= URB_LDA; + break; + } + } + return insn.size; +} diff --git a/idasdk75/module/tlcs900/emu.cpp b/idasdk76/module/tlcs900/emu.cpp similarity index 100% rename from idasdk75/module/tlcs900/emu.cpp rename to idasdk76/module/tlcs900/emu.cpp diff --git a/idasdk75/module/tlcs900/ins.cpp b/idasdk76/module/tlcs900/ins.cpp similarity index 100% rename from idasdk75/module/tlcs900/ins.cpp rename to idasdk76/module/tlcs900/ins.cpp diff --git a/idasdk75/module/tlcs900/ins.hpp b/idasdk76/module/tlcs900/ins.hpp similarity index 100% rename from idasdk75/module/tlcs900/ins.hpp rename to idasdk76/module/tlcs900/ins.hpp diff --git a/idasdk76/module/tlcs900/makefile b/idasdk76/module/tlcs900/makefile new file mode 100644 index 0000000..e5f208d --- /dev/null +++ b/idasdk76/module/tlcs900/makefile @@ -0,0 +1,57 @@ +PROC=tlcs900 +CONFIGS=tlcs900.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp tosh.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp ins.hpp tosh.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp tosh.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.hpp out.cpp tosh.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp reg.cpp tosh.hpp diff --git a/idasdk75/module/tlcs900/out.cpp b/idasdk76/module/tlcs900/out.cpp similarity index 100% rename from idasdk75/module/tlcs900/out.cpp rename to idasdk76/module/tlcs900/out.cpp diff --git a/idasdk76/module/tlcs900/reg.cpp b/idasdk76/module/tlcs900/reg.cpp new file mode 100644 index 0000000..2aa88d9 --- /dev/null +++ b/idasdk76/module/tlcs900/reg.cpp @@ -0,0 +1,256 @@ +/* + * TLCS900 processor module for IDA. + * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#include "tosh.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +int data_id; + +//-------------------------------------------------------------------------- +// registers +static const char *const RegNames[] = +{ + // zero reg + "", + // byte regs + "W", "A", "B", "C", "D", "E", "H", "L", + // word regs + "WA", "BC", "DE", "HL", "IX", "IY", "IZ", "SP", + // Double word regs + "XWA", "XBC", "XDE", "XHL", "XIX", "XIY", "XIZ", "XSP", + // strange regs + "IXL", "IXH", "IYL", "IYH", "IZL", "IZH", "SPL", "SPH", + // pesudo-seg regs + "cs", "ds" +}; + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(tlcs900_t)); + return 0; +} + +//---------------------------------------------------------------------- +void tlcs900_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +ssize_t idaapi tlcs900_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + inf_set_be(false); + inf_set_gen_lzero(true); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), IORESP_ALL); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_creating_segm: + { + segment_t *s = va_arg(va, segment_t *); + // Set default value of DS register for all segments + set_default_dataseg(s->sel); + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + T900_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + T900_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + T900_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return T900_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return T900_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + T900_data(*ctx, analyze_only); + return 1; + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +// PseudoSam +//----------------------------------------------------------------------- +static const asm_t pseudosam = +{ + AS_COLON | AS_UDATA | ASH_HEXF3, + 0, + "Generic IAR-style assembler", + 0, + NULL, + "org", + "end", + + ";", + '"', + '\'', + "\\\"'", + + "db", // ascii string directive + "DB", // byte directive + "DW", // word directive + "DL", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "#d dup(#v)", // arrays (#h,#d,#v,#s(...) + "db ?", // uninited arrays + ".equ", // equ + NULL, // seg prefix + "$", + NULL, + NULL, + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, + "align", + '(', // lbrace + ')', // rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &pseudosam, NULL }; +//----------------------------------------------------------------------- +#define FAMILY "Toshiba TLCS-900 series:" +static const char *const shnames[] = { "TLCS900", NULL }; +static const char *const lnames[] = { FAMILY"Toshiba TLCS900", NULL }; + +//-------------------------------------------------------------------------- +static const uchar retcode_1[] = { 0x0E }; // ret +static const uchar retcode_2[] = { 0x0F }; // ret d +static const uchar retcode_3[] = { 0x07 }; // reti +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_TLCS900, // id + // flag + PR_USE32 + | PR_BINMEM + | PR_SEGTRANS + | PR_DEFSEG32, + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Regsiter names + qnumber(RegNames), // Number of registers + + rVcs, rVds, + 2, // size of a segment register + rVcs, rVds, + NULL, + retcodes, + T900_null, T900_last, + Instructions, // instruc + 3, // tbyte - 24 bit + {0,0,0,0}, + 0, + NULL, +}; diff --git a/idasdk75/module/tlcs900/tlcs900.cfg b/idasdk76/module/tlcs900/tlcs900.cfg similarity index 100% rename from idasdk75/module/tlcs900/tlcs900.cfg rename to idasdk76/module/tlcs900/tlcs900.cfg diff --git a/idasdk76/module/tlcs900/tosh.hpp b/idasdk76/module/tlcs900/tosh.hpp new file mode 100644 index 0000000..8bc27df --- /dev/null +++ b/idasdk76/module/tlcs900/tosh.hpp @@ -0,0 +1,83 @@ +/* + * TLCS900 processor module for IDA. + * Copyright (c) 1998-2006 Konstantin Norvatoff, <konnor@bk.ru> + * Freeware. + */ + +#ifndef _TOSH_HPP +#define _TOSH_HPP + +#include <ida.hpp> +#include <idp.hpp> + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include "../iohandler.hpp" +#define PROCMOD_NAME tlcs900 +#define PROCMOD_NODE_NAME "$ TLCS900" + +//----------------------------------------------- +// Increment/decrement +#define URB_DECR (0x80) // decrement +#define URB_DCMASK (0x07) // mask or decrement +#define URB_UDEC (0x40) // singleton decrement +#define URB_UINC (0x20) // signleto increment + +// specflag1 bits +#define URB_WORD (1) // second index register is word +#define URB_LDA (2) // insn uses address not the content +#define URB_LDA2 (4) // same, but may constant! + +//------------------------------------------------------------------------ +enum T900_registers +{ + rNULLReg, + rW, rA, rB, rC, rD, rE, rH, rL, + rWA, rBC, rDE, rHL, rIX, rIY, rIZ, rSP, + rXWA, rXBC, rXDE, rXHL, rXIX, rXIY, rXIZ, rXSP, + rIXL, rIXH, rIYL, rIYH, rIZL, rIZH, rSPL, rSPH, + rVcs, rVds +}; + +// phrases +enum T900_phrases +{ + rNULLPh, + fCF,fCLT,fCLE,fCULE,fCPE,fCMI,fCZ,fCC, + fCT,fCGE,fCGT,fCUGT,fCPO,fCPL,fCNZ,fCNC, + fSF,fSF1, + fSR, fPC +}; + +//------------------------------------------------------------------ +struct tlcs900_iohandler_t : public iohandler_t +{ + tlcs900_iohandler_t(netnode &nn) : iohandler_t(nn) {} +}; + +struct tlcs900_t : public procmod_t +{ + netnode helper; + tlcs900_iohandler_t ioh = tlcs900_iohandler_t(helper); + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + void handle_operand(const insn_t &insn, const op_t &x, bool is_forced, bool isload); + + int T900_emu(const insn_t &insn); + void T900_header(outctx_t &ctx); + void T900_segstart(outctx_t &ctx, segment_t *Sarea) const; + void T900_footer(outctx_t &ctx) const; + + void load_from_idb(); +}; +extern int data_id; + +//------------------------------------------------------------------------ +int idaapi T900_ana(insn_t *_insn); + +void idaapi T900_data(outctx_t &ctx, bool analyze_only); + +#endif diff --git a/idasdk75/module/tms320c1/ana.cpp b/idasdk76/module/tms320c1/ana.cpp similarity index 100% rename from idasdk75/module/tms320c1/ana.cpp rename to idasdk76/module/tms320c1/ana.cpp diff --git a/idasdk75/module/tms320c1/ana.hpp b/idasdk76/module/tms320c1/ana.hpp similarity index 100% rename from idasdk75/module/tms320c1/ana.hpp rename to idasdk76/module/tms320c1/ana.hpp diff --git a/idasdk75/module/tms320c1/asms.cpp b/idasdk76/module/tms320c1/asms.cpp similarity index 100% rename from idasdk75/module/tms320c1/asms.cpp rename to idasdk76/module/tms320c1/asms.cpp diff --git a/idasdk75/module/tms320c1/asms.hpp b/idasdk76/module/tms320c1/asms.hpp similarity index 100% rename from idasdk75/module/tms320c1/asms.hpp rename to idasdk76/module/tms320c1/asms.hpp diff --git a/idasdk75/module/tms320c1/emu.cpp b/idasdk76/module/tms320c1/emu.cpp similarity index 100% rename from idasdk75/module/tms320c1/emu.cpp rename to idasdk76/module/tms320c1/emu.cpp diff --git a/idasdk75/module/tms320c1/emu.hpp b/idasdk76/module/tms320c1/emu.hpp similarity index 100% rename from idasdk75/module/tms320c1/emu.hpp rename to idasdk76/module/tms320c1/emu.hpp diff --git a/idasdk75/module/tms320c1/idp.cpp b/idasdk76/module/tms320c1/idp.cpp similarity index 100% rename from idasdk75/module/tms320c1/idp.cpp rename to idasdk76/module/tms320c1/idp.cpp diff --git a/idasdk75/module/tms320c1/ins.cpp b/idasdk76/module/tms320c1/ins.cpp similarity index 100% rename from idasdk75/module/tms320c1/ins.cpp rename to idasdk76/module/tms320c1/ins.cpp diff --git a/idasdk75/module/tms320c1/ins.hpp b/idasdk76/module/tms320c1/ins.hpp similarity index 100% rename from idasdk75/module/tms320c1/ins.hpp rename to idasdk76/module/tms320c1/ins.hpp diff --git a/idasdk76/module/tms320c1/makefile b/idasdk76/module/tms320c1/makefile new file mode 100644 index 0000000..c67e302 --- /dev/null +++ b/idasdk76/module/tms320c1/makefile @@ -0,0 +1,60 @@ +PROC=tms320c1 +O1=idp +O2=asms + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + reg.hpp tms320c1.hpp +$(F)asms$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp asms.cpp asms.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + emu.cpp ins.hpp reg.hpp tms320c1.hpp +$(F)idp$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.hpp asms.hpp \ + idp.cpp ins.hpp out.hpp reg.hpp tms320c1.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp out.cpp out.hpp reg.hpp +$(F)reg$(O) : reg.cpp reg.hpp diff --git a/idasdk75/module/tms320c1/out.cpp b/idasdk76/module/tms320c1/out.cpp similarity index 100% rename from idasdk75/module/tms320c1/out.cpp rename to idasdk76/module/tms320c1/out.cpp diff --git a/idasdk75/module/tms320c1/out.hpp b/idasdk76/module/tms320c1/out.hpp similarity index 100% rename from idasdk75/module/tms320c1/out.hpp rename to idasdk76/module/tms320c1/out.hpp diff --git a/idasdk75/module/tms320c1/reg.cpp b/idasdk76/module/tms320c1/reg.cpp similarity index 100% rename from idasdk75/module/tms320c1/reg.cpp rename to idasdk76/module/tms320c1/reg.cpp diff --git a/idasdk75/module/tms320c1/reg.hpp b/idasdk76/module/tms320c1/reg.hpp similarity index 100% rename from idasdk75/module/tms320c1/reg.hpp rename to idasdk76/module/tms320c1/reg.hpp diff --git a/idasdk76/module/tms320c1/tms320c1.hpp b/idasdk76/module/tms320c1/tms320c1.hpp new file mode 100644 index 0000000..e8429ef --- /dev/null +++ b/idasdk76/module/tms320c1/tms320c1.hpp @@ -0,0 +1,210 @@ +// $Id: tms320c1.hpp,v 1.8 2000/11/06 22:11:17 jeremy Exp $ +// +// Copyright (c) 2000 Jeremy Cooper. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. All advertising materials mentioning features or use of this software +// must display the following acknowledgement: +// This product includes software developed by Jeremy Cooper. +// 4. The name of the author may not be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// +// IDA TMS320C1X processor module. +// TMS320C1X constants, etc. +// +#ifndef _IDP_TMS320C1X_H +#define _IDP_TMS320C1X_H + +////////////////////////////////////////////////////////////////////////////// +// TMS320C1X Instruction Opcodes +// +// To ease decoding requirements, we have classified each TMS320C1X +// instruction by the number of significant bits that need to be scanned in +// the instruction opcode in order to uniquely identify it. +// + +// +// Bit scanning masks +// +#define ISN_3_BIT_MASK 0xe000 // 111x xxxx xxxx xxxx +#define ISN_4_BIT_MASK 0xf000 // 1111 xxxx xxxx xxxx +#define ISN_5_BIT_MASK 0xf800 // 1111 1xxx xxxx xxxx +#define ISN_7_BIT_MASK 0xfe00 // 1111 111x xxxx xxxx +#define ISN_8_BIT_MASK 0xff00 // 1111 1111 xxxx xxxx +#define ISN_15_BIT_MASK 0xfffe // 1111 1111 1111 111x +#define ISN_16_BIT_MASK 0xffff // 1111 1111 1111 1111 + +// +// 3 bit Opcodes +// +enum isn_3bit +{ + ISN3_MPYK = 0x8000, // 100... +}; +// +// 4 bit Opcodes +// +enum isn_4bit +{ + ISN4_ADD = 0x0000, // 0000... + ISN4_LAC = 0x2000, // 0100... + ISN4_SUB = 0x1000, // 0001... +}; +// +// 5 bit Opcodes +// +enum isn_5bit +{ + ISN5_SACH = 0x5800, // 0101 1... + ISN5_IN = 0x4000, // 0100 0... + ISN5_OUT = 0x4800, // 0100 1... +}; +// +// 7 bit Opcodes +// +enum isn_7bit +{ + ISN7_LAR = 0x3800, // 0011 100... + ISN7_LARK = 0x7000, // 0111 000... + ISN7_SAR = 0x3000, // 0011 000... +}; +// +// 8 bit Opcodes +// +enum isn_8bit +{ + ISN8_ADDH = 0x6000, // 0110 0000 ... + ISN8_ADDS = 0x6100, // 0110 0001 ... + ISN8_AND = 0x7900, // 0111 1001 ... + ISN8_LACK = 0x7e00, // 0111 1110 ... + ISN8_OR = 0x7a00, // 0111 1010 ... + ISN8_SACL = 0x5000, // 0101 0000 ... + ISN8_SUBC = 0x6400, // 0110 0100 ... + ISN8_SUBH = 0x6200, // 0110 0010 ... + ISN8_SUBS = 0x6300, // 0110 0011 ... + ISN8_XOR = 0x7800, // 0111 1000 ... + ISN8_ZALH = 0x6500, // 0110 0101 ... + ISN8_ZALS = 0x6600, // 0110 0110 ... + ISN8_LDP = 0x6f00, // 0110 1111 ... + ISN8_MAR = 0x6800, // 0110 1000 ... + ISN8_LT = 0x6a00, // 0110 1010 ... + ISN8_LTA = 0x6c00, // 0110 1100 ... + ISN8_LTD = 0x6b00, // 0110 1011 ... + ISN8_MPY = 0x6d00, // 0110 1101 ... + ISN8_LST = 0x7b00, // 0111 1101 ... + ISN8_SST = 0x7c00, // 0111 1100 ... + ISN8_DMOV = 0x6900, // 0110 1001 ... + ISN8_TBLR = 0x6700, // 0110 0111 ... + ISN8_TBLW = 0x7d00, // 0111 1101 ... +}; +// +// 15 bit Opcodes +// +enum isn_15bit +{ +// LARP is a synonym for a special case of MAR +// ISN15_LARP = 0x6880, // 0110 1000 1000 000. + ISN15_LDPK = 0x6e00, // 0110 1110 0000 000. +}; +// +// 16 bit Opcodes +// +enum isn_16bit +{ + ISN16_ABS = 0x7f88, // 0111 1111 1000 1000 + ISN16_ZAC = 0x7f89, // 0111 1111 1000 0101 + ISN16_APAC = 0x7f8f, // 0111 1111 1000 1111 + ISN16_PAC = 0x7f8e, // 0111 1111 1000 1110 + ISN16_SPAC = 0x7f90, // 0111 1111 1001 0000 + ISN16_B = 0xf900, // 1111 1001 0000 0000 + ISN16_BANZ = 0xf400, // 1111 0100 0000 0000 + ISN16_BGEZ = 0xfd00, // 1111 1101 0000 0000 + ISN16_BGZ = 0xfc00, // 1111 1100 0000 0000 + ISN16_BIOZ = 0xf600, // 1111 0110 0000 0000 + ISN16_BLEZ = 0xfb00, // 1111 1011 0000 0000 + ISN16_BLZ = 0xfa00, // 1111 1010 0000 0000 + ISN16_BNZ = 0xfe00, // 1111 1110 0000 0000 + ISN16_BV = 0xf500, // 1111 0101 0000 0000 + ISN16_BZ = 0xff00, // 1111 1111 0000 0000 + ISN16_CALA = 0x7f8c, // 0111 1111 1000 1100 + ISN16_CALL = 0xf800, // 1111 1000 0000 0000 + ISN16_RET = 0x7f8d, // 0111 1111 1000 1101 + ISN16_DINT = 0x7f81, // 0111 1111 1000 0001 + ISN16_EINT = 0x7f82, // 0111 1111 1000 0010 + ISN16_NOP = 0x7f80, // 0111 1111 1000 0000 + ISN16_POP = 0x7f9d, // 0111 1111 1001 1101 + ISN16_PUSH = 0x7f9c, // 0111 1111 1001 1100 + ISN16_ROVM = 0x7f8a, // 0111 1111 1000 1010 + ISN16_SOVM = 0x7f8b, // 0111 1111 1000 1011 +}; + +// +// Instruction property macros. +// These macros deduce certain facts about the instruction. +// +#define ISN_IMM1(op) ((op) & 0x0001) // Immediate 1 bit value +#define ISN_IMM8(op) ((op) & 0x00ff) // Immediate 8 bit value +#define ISN_IMM13(op) ((op) & 0x1fff) // Immediate 13 bit value +#define ISN_DIRECT(op) (!((op) & 0x0080)) // Direct/Indirect reference flag +#define ISN_DIR_ADDR(op) ((op) & 0x007f) // Direct memory location +#define ISN_INDIR_INCR(op) ((op) & 0x0020) // Aux reg. post-increment flag +#define ISN_INDIR_DECR(op) ((op) & 0x0010) // Aux reg. post-decrement flag +#define ISN_INDIR_NARP(op) ((op) & 0x0008) // Aux reg. change flag +#define ISN_INDIR_ARP(op) ((op) & 0x0001) // New aux reg. pointer value +#define ISN_AUX_AR(op) ((op) & 0x0100) // Aux register index +#define ISN_SHIFT(o) (((o)&0x0f00)>>8) // Data bit shift amount +#define ISN_PORT(o) (((o)&0x0700)>>8) // I/O port number + +// +// TMS320C1X environment facts. +// These macros define the size of the TMS320C1X's addressable +// data RAM. +// +#define TMS320C1X_DATA_RAM_SIZE 256 // 256 bytes + +// +// Reference type. Used between emu() and handle_operand() to +// flag whether an operand is written to or read from. +// +enum opRefType +{ + hop_READ, + hop_WRITE, +}; + +struct tms320c1_t : public procmod_t +{ + sel_t tms320c1x_dpage0; // Data page 0 selector + sel_t tms320c1x_dpage1; // Data page 1 selector + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + // Kernel message handlers. + void tms320c1x_Init() const; + void tms320c1x_NewFile(); + + int emu(const insn_t &insn) const; + bool handle_operand(const insn_t &insn, const op_t &op, opRefType ref_type) const; +}; + +#endif // IDP_TMS320C1X_H diff --git a/idasdk76/module/tms320c3/ana.cpp b/idasdk76/module/tms320c3/ana.cpp new file mode 100644 index 0000000..ec7b030 --- /dev/null +++ b/idasdk76/module/tms320c3/ana.cpp @@ -0,0 +1,932 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Texas Instruments's TMS5320C3X + * + */ + +#include "tms320c3x.hpp" + +#define FUNCS_COUNT 3 + +struct ctx_t +{ + insn_t &insn; + op_t *op; + ctx_t(insn_t *i) : insn(*i) { op = &i->Op1; } +}; + +struct funcdesc_t +{ + bool (*func)(ctx_t &ctx, int); + uint32 mask; + uint32 shift; +}; + +struct opcode_t +{ + uint16 itype; + unsigned int insnidx; //lint !e958 padding is required to align members + funcdesc_t funcs[FUNCS_COUNT]; + uchar itype2; + funcdesc_t funcs2[FUNCS_COUNT]; //lint !e958 padding is required to align members + bool ispar; +}; + +//---------------------------------------------------------------------- +//lint -esym(1764, ctx) could be declared const +inline void opreg(ctx_t &ctx, uint16 reg) +{ + ctx.op->type = o_reg; + ctx.op->dtype = dt_byte; + ctx.op->reg = reg; +} + +//---------------------------------------------------------------------- +static void make_o_mem(ctx_t &ctx) +{ + switch ( ctx.insn.itype ) + { + case TMS320C3X_BR: + case TMS320C3X_BRD: + case TMS320C3X_CALL: + case TMS320C3X_RPTB: + case TMS320C3X_Bcond: + case TMS320C3X_DBcond: + case TMS320C3X_CALLcond: + ctx.op->type = o_near; + ctx.op->dtype = dt_code; + return; + } + ctx.op->type = o_mem; + ctx.op->dtype = dt_byte; +} + +//---------------------------------------------------------------------- +static bool D_adr24(ctx_t &ctx, int value) +{ + ctx.op->addr = value & 0xffffff; + make_o_mem(ctx); + return true; +} + +//---------------------------------------------------------------------- +static bool D_PC_Displ(ctx_t &ctx, int value) +{ + int16 disp = value & 0xffff; + + if ( value & 0x200000 ) + D_adr24(ctx, ctx.insn.ea + disp + 3); // delayed branch + else + D_adr24(ctx, ctx.insn.ea + disp + 1); + + return true; +} + +//---------------------------------------------------------------------- +static bool imm8(ctx_t &ctx, int value) +{ + ctx.op->type = o_imm; + ctx.op->dtype = dt_byte; + ctx.op->value = value & 0xff; + return true; +} + +//---------------------------------------------------------------------- +static bool D_regs(ctx_t &ctx, int value) // interpret register numbers +{ + if ( (value & 0x1f) > 0x1b ) + return false; + + if ( (value & 0x1f) == 0x10 ) + value = 0x1b; // remap DP reg + else if ( (value & 0x1f) > 0x10 ) + value = (value & 0x1f) - 1; + opreg(ctx, value & 0x1f); + return true; +} + +//---------------------------------------------------------------------- +static bool S_regs(ctx_t &ctx, int value) +{ + if ( D_regs(ctx, value) ) + { + ctx.op++; + return true; + } + return false; +} +//---------------------------------------------------------------------- +static bool D_R(ctx_t &ctx, int value) // interpret Rx register numbers +{ + if ( D_regs(ctx, value & 0x07) ) + return true; + else + return false; +} + +//---------------------------------------------------------------------- +static bool S_R(ctx_t &ctx, int value) +{ + if ( D_R(ctx, value) ) + { + ctx.op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +static bool D_R2(ctx_t &ctx, int value) +{ + return D_regs(ctx, r2 + (value & 0x07)); +} + +//---------------------------------------------------------------------- +static bool D_ar(ctx_t &ctx, int value) +{ + return D_regs(ctx, ar0 + (value & 0x07)); +} + +//---------------------------------------------------------------------- +static bool S_ar(ctx_t &ctx, int value) // interpret ARx register numbers +{ + if ( D_ar(ctx, value) ) + { + ctx.op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +static bool D_indir(ctx_t &ctx, int value) // indirect addressing +{ + ctx.op->type = o_phrase; + ctx.op->dtype = dt_byte; + ctx.op->phrase = ( value & 0xf800 ) >> 11; + ctx.op->phtype = ar0 + ((value >> 8) & 0x07); + ctx.op->addr = value & 0xff; + return true; +} + +//---------------------------------------------------------------------- +static bool S_indir(ctx_t &ctx, int value) +{ + if ( D_indir(ctx, value) ) + { + ctx.op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +static bool D_indir3(ctx_t &ctx, int value) // indirect addressing for 3-operand and parallel instructions +{ + ctx.op->type = o_phrase; + ctx.op->dtype = dt_byte; + ctx.op->phrase = ( value & 0xf8 ) >> 3; // indirect addressing type + ctx.op->phtype = ar0 + (value & 0x07); // register no + ctx.op->addr = 1; // offset (if present) + return true; + +} +//---------------------------------------------------------------------- +static bool S_indir3(ctx_t &ctx, int value) +{ + if ( D_indir3(ctx, value) ) + { + ctx.op++; + return true; + } + return false; +} + +//---------------------------------------------------------------------- +static bool SSD_src3(ctx_t &ctx, int value) // 3-operand instructions parsing +{ + switch ( (value >> 16) & 0x60 ) + { + case 0x00: + S_regs(ctx, value & 0xff); + S_regs(ctx, (value >> 8) & 0xff); + D_regs(ctx, (value >> 16) & 0x1f); + break; + + case 0x20: + S_regs(ctx, value & 0xff); + S_indir3(ctx, (value >> 8) & 0xff); + D_regs(ctx, (value >> 16) & 0x1f); + break; + + case 0x40: + S_indir3(ctx, value & 0xff); + S_regs(ctx, (value >> 8) & 0xff); + D_regs(ctx, (value >> 16) & 0x1f); + break; + + case 0x60: + S_indir3(ctx, value & 0xff); + S_indir3(ctx, (value >> 8) & 0xff); + D_regs(ctx, (value >> 16) & 0x1f); + break; + + default: + return false; + } + return true; +} + +//---------------------------------------------------------------------- +static bool SD_src3_2op(ctx_t &ctx, int value) // parsing of 3-operand instructions which use only two +{ + switch ( (value >> 16) & 0x60 ) + { + case 0x00: + S_regs(ctx, value & 0xff); + D_regs(ctx, (value >> 8) & 0xff); + break; + case 0x20: + S_regs(ctx, value & 0xff); + D_indir3(ctx, (value >> 8) & 0xff); + break; + case 0x40: + S_indir3(ctx, value & 0xff); + D_regs(ctx, (value >> 8) & 0xff); + break; + case 0x60: + S_indir3(ctx, value & 0xff); + D_indir3(ctx, (value >> 8) & 0xff); + break; + default: + return false; + } + return true; +} + +//---------------------------------------------------------------------- +static bool DBranch(ctx_t &ctx, int /*value*/) // set delayed branch flag +{ + ctx.insn.auxpref |= DBrFlag; + return true; +} + +//---------------------------------------------------------------------- +static bool ImmFlt(ctx_t &ctx, int /*value*/) // set floating-point constand flag +{ + ctx.insn.auxpref |= ImmFltFlag; + return true; +} + +//---------------------------------------------------------------------- +static bool cond(ctx_t &ctx, int value) // parse condition codes +{ + if ( ((value & 0x1f) > 0x14 ) || ((value & 0x1f) == 0x0b ) ) + return false; + + ctx.insn.auxpref |= value & 0x1f; + + if ( (ctx.insn.auxpref & 0x1f) == 0 ) // Upgrade retscond to retsu + { + switch ( ctx.insn.itype ) + { + case TMS320C3X_RETIcond: + ctx.insn.itype = TMS320C3X_RETIU; + break; + + case TMS320C3X_RETScond: + ctx.insn.itype = TMS320C3X_RETSU; + break; + } + } + if ( value & 0x20 ) + DBranch(ctx, 0); // delayed branch + return true; +} +//---------------------------------------------------------------------- +static bool SD_adres(ctx_t &ctx, int value) // main addressing +{ + switch ( (value >> 16) & 0x60 ) + { + case 0x00: + S_regs(ctx, value & 0xff); + D_regs(ctx, (value >> 16) & 0x1f); + break; + + case 0x20: + ctx.op->addr = value & 0xffff; + make_o_mem(ctx); + ctx.op++; + D_regs(ctx, (value >> 16) & 0x1f); + break; + + case 0x40: + S_indir(ctx, value & 0xffff); + D_regs(ctx, (value >> 16) & 0x1f); + break; + + case 0x60: + ctx.op->type = o_imm; + ctx.op->dtype = dt_byte; + ctx.op->value = value & 0xffff; + ctx.op++; + D_regs(ctx, (value >> 16) & 0x1f); + break; + + default: + return false; + } + return true; +} + +//---------------------------------------------------------------------- +static bool SD_adresRev(ctx_t &ctx, int value) // main addressing with reversed operands +{ + switch ( (value >> 16) & 0x60 ) + { + case 0x00: + S_regs(ctx, (value >> 16) & 0x1f); + D_regs(ctx, value & 0xff); + break; + + case 0x20: + S_regs(ctx, (value >> 16) & 0x1f); + ctx.op->addr = value & 0xffff; + make_o_mem(ctx); + break; + + case 0x40: + S_regs(ctx, (value >> 16) & 0x1f); + D_indir(ctx, value & 0xffff); + break; + + case 0x60: + S_regs(ctx, (value >> 16) & 0x1f); + ctx.op->type = o_imm; + ctx.op->dtype = dt_byte; + ctx.op->value = value & 0xffff; + break; + + default: + return false; + } + return true; +} +//---------------------------------------------------------------------- +static bool D_adres_1Op(ctx_t &ctx, int value) // main addressing using only one operand +{ + switch ( (value >> 16) & 0x60 ) + { + case 0x00: + D_regs(ctx, value & 0xffff); + break; + case 0x20: + ctx.op->addr = value & 0xffff; + make_o_mem(ctx); + break; + case 0x40: + D_indir(ctx, value & 0xffff); + break; + case 0x60: + ctx.op->type = o_imm; + ctx.op->dtype = dt_byte; + ctx.op->value = value & 0xffff; + break; + default: + return false; + } + return true; +} + +//---------------------------------------------------------------------- +static bool idle_1_2(ctx_t &ctx, int value) +{ + if ( value & 0x01 ) + ctx.insn.itype = TMS320C3X_IDLE2; + else + ctx.insn.itype = TMS320C3X_IDLE; + return true; +} + +//---------------------------------------------------------------------- +static bool speedctrl(ctx_t &ctx, int value) +{ + if ( value & 0x01 ) + ctx.insn.itype = TMS320C3X_LOPOWER; + else + ctx.insn.itype = TMS320C3X_MAXSPEED; + return true; +} + +//---------------------------------------------------------------------- +static bool nopcases(ctx_t &ctx, int value) +{ + if ( ((value>>16) & 0x60) == 0x40 ) + D_adres_1Op(ctx, value); + return true; +} +//---------------------------------------------------------------------- +static const opcode_t table_pattern[] = +{ + { TMS320C3X_ABSF, 0x000, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_ABSI, 0x001, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_ADDC, 0x002, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_ADDF, 0x003, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_ADDI, 0x004, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_AND, 0x005, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_ANDN, 0x006, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_ASH, 0x007, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_CMPF, 0x008, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_CMPI, 0x009, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_FIX, 0x00a, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_FLOAT, 0x00b, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_NONE, 0x00c, {{ idle_1_2, 0xffffffff } }},// multiple case, mask should be checked further + { TMS320C3X_LDE, 0x00d, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_LDF, 0x00e, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_LDFI, 0x00f, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_LDI, 0x010, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_LDII, 0x011, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_LDM, 0x012, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_LSH, 0x013, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_MPYF, 0x014, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_MPYI, 0x015, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_NEGB, 0x016, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_NEGF, 0x017, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_NEGI, 0x018, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_NOP, 0x019, {{ nopcases, 0x007fffff } }},// possible update registers case + { TMS320C3X_NORM, 0x01a, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_NOT, 0x01b, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_POP, 0x01c, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_POPF, 0x01d, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_PUSH, 0x01e, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_PUSHF, 0x01f, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_OR, 0x020, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_NONE, 0x021, {{ speedctrl, 0xffffffff } }},// multiple case, mask should be checked further + { TMS320C3X_RND, 0x022, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_ROL, 0x023, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_ROLC, 0x024, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_ROR, 0x025, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_RORC, 0x026, {{ D_regs, 0x001f0000 } }}, + { TMS320C3X_RPTS, 0x027, {{ D_adres_1Op, 0x007fffff } }}, + { TMS320C3X_STF, 0x028, {{ SD_adresRev, 0x007fffff } }}, + { TMS320C3X_STFI, 0x029, {{ SD_adresRev, 0x007fffff } }}, + { TMS320C3X_STI, 0x02a, {{ SD_adresRev, 0x007fffff } }}, + { TMS320C3X_STII, 0x02b, {{ SD_adresRev, 0x007fffff } }}, + { TMS320C3X_SIGI, 0x02c }, + { TMS320C3X_SUBB, 0x02d, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_SUBC, 0x02e, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_SUBF, 0x02f, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_SUBI, 0x030, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_SUBRB, 0x031, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_SUBRF, 0x032, {{ SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, + { TMS320C3X_SUBRI, 0x033, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_TSTB, 0x034, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_XOR, 0x035, {{ SD_adres, 0x007fffff } }}, + { TMS320C3X_IACK, 0x036 }, + { TMS320C3X_null, 0x037 },{ TMS320C3X_null, 0x038 }, { TMS320C3X_null, 0x039 }, { TMS320C3X_null, 0x03a },// invalid + { TMS320C3X_null, 0x03b },{ TMS320C3X_null, 0x03c }, { TMS320C3X_null, 0x03d }, { TMS320C3X_null, 0x03e },// invalid + { TMS320C3X_null, 0x03f },// invalid +// 3 operand insns + { TMS320C3X_ADDC3, 0x040, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_ADDF3, 0x041, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_ADDI3, 0x042, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_AND3, 0x043, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_ANDN3, 0x044, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_ASH3, 0x045, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_CMPF3, 0x046, {{ SD_src3_2op, 0x007fffff } }}, + { TMS320C3X_CMPI3, 0x047, {{ SD_src3_2op, 0x007fffff } }}, + { TMS320C3X_LSH3, 0x048, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_MPYF3, 0x049, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_MPYI3, 0x04a, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_OR3, 0x04b, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_SUBB3, 0x04c, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_SUBF3, 0x04d, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_SUBI3, 0x04e, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_TSTB3, 0x04f, {{ SD_src3_2op, 0x007fffff } }}, + { TMS320C3X_XOR3, 0x050, {{ SSD_src3, 0x007fffff } }}, + { TMS320C3X_null, 0x051 },{ TMS320C3X_null, 0x052 },{ TMS320C3X_null, 0x053 },{ TMS320C3X_null, 0x054 },// invalid + { TMS320C3X_null, 0x055 },{ TMS320C3X_null, 0x056 },{ TMS320C3X_null, 0x057 },{ TMS320C3X_null, 0x058 },// invalid + { TMS320C3X_null, 0x059 },{ TMS320C3X_null, 0x05a },{ TMS320C3X_null, 0x05b },{ TMS320C3X_null, 0x05c },// invalid + { TMS320C3X_null, 0x05d },{ TMS320C3X_null, 0x05e },{ TMS320C3X_null, 0x05f },{ TMS320C3X_null, 0x060 },// invalid + { TMS320C3X_null, 0x061 },{ TMS320C3X_null, 0x062 },{ TMS320C3X_null, 0x063 },{ TMS320C3X_null, 0x064 },// invalid + { TMS320C3X_null, 0x065 },{ TMS320C3X_null, 0x066 },{ TMS320C3X_null, 0x067 },{ TMS320C3X_null, 0x068 },// invalid + { TMS320C3X_null, 0x069 },{ TMS320C3X_null, 0x06a },{ TMS320C3X_null, 0x06b },{ TMS320C3X_null, 0x06c },// invalid + { TMS320C3X_null, 0x06d },{ TMS320C3X_null, 0x06e },{ TMS320C3X_null, 0x06f },{ TMS320C3X_null, 0x070 },// invalid + { TMS320C3X_null, 0x071 },{ TMS320C3X_null, 0x072 },{ TMS320C3X_null, 0x073 },{ TMS320C3X_null, 0x074 },// invalid + { TMS320C3X_null, 0x075 },{ TMS320C3X_null, 0x076 },{ TMS320C3X_null, 0x077 },{ TMS320C3X_null, 0x078 },// invalid + { TMS320C3X_null, 0x079 },{ TMS320C3X_null, 0x07a },{ TMS320C3X_null, 0x07b },{ TMS320C3X_null, 0x07c },// invalid + { TMS320C3X_null, 0x07d },{ TMS320C3X_null, 0x07e },{ TMS320C3X_null, 0x07f },// invalid +// 0x80 - 0x8f LDFcond + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, +// 0x90 - 0x9f LDFcond + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_MV_IDX, 0x09f },{ TMS320C3X_MV_IDX, 0x09f }, { TMS320C3X_MV_IDX, 0x09f }, + { TMS320C3X_LDFcond, 0x09f, {{ cond, 0x0f800000 }, { SD_adres, 0x007fffff }, { ImmFlt, 0x00000000 } }}, +// 0xa0 - 0xaf LDIcond + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, +// 0xb0 - 0xbf LDIcond + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf },{ TMS320C3X_MV_IDX, 0x0bf }, + { TMS320C3X_LDIcond, 0x0bf, {{ cond, 0x0f800000 }, { SD_adres, 0x007fffff } }}, +// 0xc0 - 0xc1 BR + { TMS320C3X_MV_IDX, 0x0c1 }, + { TMS320C3X_BR, 0x0c1, {{ D_adr24, 0x00ffffff } }}, +// 0xc2 - 0xc3 BR + { TMS320C3X_MV_IDX, 0x0c3 }, + { TMS320C3X_BRD, 0x0c3, {{ DBranch, 0x00000000 }, { D_adr24, 0x00ffffff } }}, +// 0xc4 - 0xc5 CALL + { TMS320C3X_MV_IDX, 0x0c5 }, + { TMS320C3X_CALL, 0x0c5, {{ D_adr24, 0x00ffffff } }}, + { TMS320C3X_null, 0x0c6 },// invalid + { TMS320C3X_null, 0x0c7 },// invalid +// 0xc8 - 0xc9 RPTB + { TMS320C3X_MV_IDX, 0x0c9 }, + { TMS320C3X_RPTB, 0x0c9, {{ D_adr24, 0x00ffffff } }}, + { TMS320C3X_null, 0x0ca },// invalid + { TMS320C3X_null, 0x0cb },// invalid + { TMS320C3X_SWI, 0x0cc }, + { TMS320C3X_null, 0x0cd },// invalid + { TMS320C3X_null, 0x0ce },// invalid + { TMS320C3X_null, 0x0cf },// invalid + { TMS320C3X_Bcond, 0x0d0, {{ cond, 0x003f0000 }, { D_regs, 0x0000ffff } }}, + { TMS320C3X_null, 0x0d1 },// invalid + { TMS320C3X_null, 0x0d2 },// invalid + { TMS320C3X_null, 0x0d3 },// invalid + { TMS320C3X_Bcond, 0x0d4, {{ cond, 0x003f0000 }, { D_PC_Displ, 0x0020ffff } }}, + { TMS320C3X_null, 0x0d5 },// invalid + { TMS320C3X_null, 0x0d6 },// invalid + { TMS320C3X_null, 0x0d7 },// invalid +// 0xd8 - 0xdb DBcond + { TMS320C3X_MV_IDX, 0x0db }, + { TMS320C3X_MV_IDX, 0x0db }, + { TMS320C3X_MV_IDX, 0x0db }, + { TMS320C3X_DBcond, 0x0db, {{ cond, 0x003f0000 }, { S_ar, 0x01c00000 }, { D_regs, 0x0000ffff } }}, +// 0xdc - 0xdf DBcond + { TMS320C3X_MV_IDX, 0x0df }, + { TMS320C3X_MV_IDX, 0x0df }, + { TMS320C3X_MV_IDX, 0x0df }, + { TMS320C3X_DBcond, 0x0df, {{ cond, 0x003f0000 }, { S_ar, 0x01c00000 }, { D_PC_Displ, 0x0020ffff } }}, + { TMS320C3X_CALLcond, 0x0e0, {{ cond, 0x001f0000 }, { D_regs, 0x0000ffff } }}, + { TMS320C3X_null, 0x0e1 },// invalid + { TMS320C3X_null, 0x0e2 },// invalid + { TMS320C3X_null, 0x0e3 },// invalid + { TMS320C3X_CALLcond, 0x0e4, {{ cond, 0x001f0000 }, { D_PC_Displ, 0x0000ffff } }}, + { TMS320C3X_null, 0x0e5 },// invalid + { TMS320C3X_null, 0x0e6 },// invalid + { TMS320C3X_null, 0x0e7 },// invalid + { TMS320C3X_TRAPcond, 0x0e8, {{ cond, 0x001f0000 }, { imm8, 0x0000001f } }}, + { TMS320C3X_null, 0x0e9 },// invalid + { TMS320C3X_null, 0x0ea },// invalid + { TMS320C3X_null, 0x0eb },// invalid + { TMS320C3X_null, 0x0ec },// invalid + { TMS320C3X_null, 0x0ed },// invalid + { TMS320C3X_null, 0x0ee },// invalid + { TMS320C3X_null, 0x0ef },// invalid + { TMS320C3X_RETIcond, 0x0f0, {{ cond, 0x001f0000 } }}, + { TMS320C3X_RETScond, 0x0f1, {{ cond, 0x001f0000 } }}, + { TMS320C3X_null, 0x0f2 }, { TMS320C3X_null, 0x0f3 }, { TMS320C3X_null, 0x0f4 }, { TMS320C3X_null, 0x0f5 },// invalid + { TMS320C3X_null, 0x0f6 }, { TMS320C3X_null, 0x0f7 }, { TMS320C3X_null, 0x0f8 }, { TMS320C3X_null, 0x0f9 },// invalid + { TMS320C3X_null, 0x0fa }, { TMS320C3X_null, 0x0fb }, { TMS320C3X_null, 0x0fc }, { TMS320C3X_null, 0x0fd },// invalid + { TMS320C3X_null, 0x0fe }, { TMS320C3X_null, 0x0ff },// invalid + { TMS320C3X_MV_IDX, 0x101 }, + { TMS320C3X_MPYF3, 0x101, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, + TMS320C3X_ADDF3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x103 }, + { TMS320C3X_MPYF3, 0x103, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_ADDF3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x105 }, + { TMS320C3X_MPYF3, 0x105, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, + TMS320C3X_ADDF3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x107 }, + { TMS320C3X_MPYF3, 0x107, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_ADDF3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x109 }, + { TMS320C3X_MPYF3, 0x109, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, + TMS320C3X_SUBF3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x10b }, + { TMS320C3X_MPYF3, 0x10b, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_SUBF3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x10d }, + { TMS320C3X_MPYF3, 0x10d, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, + TMS320C3X_SUBF3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x10f }, + { TMS320C3X_MPYF3, 0x10f, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_SUBF3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x111 }, + { TMS320C3X_MPYI3, 0x111, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, + TMS320C3X_ADDI3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x113 }, + { TMS320C3X_MPYI3, 0x113, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_ADDI3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x115 }, + { TMS320C3X_MPYI3, 0x115, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, + TMS320C3X_ADDI3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x117 }, + { TMS320C3X_MPYI3, 0x117, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_ADDI3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x119 }, + { TMS320C3X_MPYI3, 0x119, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R, 0x00800000 }}, + TMS320C3X_SUBI3, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x11b }, + { TMS320C3X_MPYI3, 0x11b, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_SUBI3, {{ S_indir3, 0x000000ff }, { S_R, 0x00070000 }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x11d }, + { TMS320C3X_MPYI3, 0x11d, {{ S_R, 0x00380000 }, { S_R, 0x00070000 }, { D_R, 0x00800000 }}, + TMS320C3X_SUBI3, {{ S_indir3, 0x0000ff00 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + { TMS320C3X_MV_IDX, 0x11f }, + { TMS320C3X_MPYI3, 0x11f, {{ S_indir3, 0x0000ff00 }, { S_R, 0x00380000 }, { D_R, 0x00800000 }}, + TMS320C3X_SUBI3, {{ S_R, 0x00070000 }, { S_indir3, 0x000000ff }, { D_R2, 0x00400000 }}}, + + { TMS320C3X_null, 0x120 }, { TMS320C3X_null, 0x121 }, { TMS320C3X_null, 0x122 }, { TMS320C3X_null, 0x123 },// invalid + { TMS320C3X_null, 0x124 }, { TMS320C3X_null, 0x125 }, { TMS320C3X_null, 0x126 }, { TMS320C3X_null, 0x127 },// invalid + { TMS320C3X_null, 0x128 }, { TMS320C3X_null, 0x129 }, { TMS320C3X_null, 0x12a }, { TMS320C3X_null, 0x12b },// invalid + { TMS320C3X_null, 0x12c }, { TMS320C3X_null, 0x12d }, { TMS320C3X_null, 0x12e }, { TMS320C3X_null, 0x12f },// invalid + { TMS320C3X_null, 0x130 }, { TMS320C3X_null, 0x131 }, { TMS320C3X_null, 0x132 }, { TMS320C3X_null, 0x133 },// invalid + { TMS320C3X_null, 0x134 }, { TMS320C3X_null, 0x135 }, { TMS320C3X_null, 0x136 }, { TMS320C3X_null, 0x137 },// invalid + { TMS320C3X_null, 0x138 }, { TMS320C3X_null, 0x139 }, { TMS320C3X_null, 0x13a }, { TMS320C3X_null, 0x13b },// invalid + { TMS320C3X_null, 0x13c }, { TMS320C3X_null, 0x13d }, { TMS320C3X_null, 0x13e }, { TMS320C3X_null, 0x13f },// invalid + { TMS320C3X_null, 0x140 }, { TMS320C3X_null, 0x141 }, { TMS320C3X_null, 0x142 }, { TMS320C3X_null, 0x143 },// invalid + { TMS320C3X_null, 0x144 }, { TMS320C3X_null, 0x145 }, { TMS320C3X_null, 0x146 }, { TMS320C3X_null, 0x147 },// invalid + { TMS320C3X_null, 0x148 }, { TMS320C3X_null, 0x149 }, { TMS320C3X_null, 0x14a }, { TMS320C3X_null, 0x14b },// invalid + { TMS320C3X_null, 0x14c }, { TMS320C3X_null, 0x14d }, { TMS320C3X_null, 0x14e }, { TMS320C3X_null, 0x14f },// invalid + { TMS320C3X_null, 0x150 }, { TMS320C3X_null, 0x151 }, { TMS320C3X_null, 0x152 }, { TMS320C3X_null, 0x153 },// invalid + { TMS320C3X_null, 0x154 }, { TMS320C3X_null, 0x155 }, { TMS320C3X_null, 0x156 }, { TMS320C3X_null, 0x157 },// invalid + { TMS320C3X_null, 0x158 }, { TMS320C3X_null, 0x159 }, { TMS320C3X_null, 0x15a }, { TMS320C3X_null, 0x15b },// invalid + { TMS320C3X_null, 0x15c }, { TMS320C3X_null, 0x15d }, { TMS320C3X_null, 0x15e }, { TMS320C3X_null, 0x15f },// invalid + { TMS320C3X_null, 0x160 }, { TMS320C3X_null, 0x161 }, { TMS320C3X_null, 0x162 }, { TMS320C3X_null, 0x163 },// invalid + { TMS320C3X_null, 0x164 }, { TMS320C3X_null, 0x165 }, { TMS320C3X_null, 0x166 }, { TMS320C3X_null, 0x167 },// invalid + { TMS320C3X_null, 0x168 }, { TMS320C3X_null, 0x169 }, { TMS320C3X_null, 0x16a }, { TMS320C3X_null, 0x16b },// invalid + { TMS320C3X_null, 0x16c }, { TMS320C3X_null, 0x16d }, { TMS320C3X_null, 0x16e }, { TMS320C3X_null, 0x16f },// invalid + { TMS320C3X_null, 0x170 }, { TMS320C3X_null, 0x171 }, { TMS320C3X_null, 0x172 }, { TMS320C3X_null, 0x123 },// invalid + { TMS320C3X_null, 0x174 }, { TMS320C3X_null, 0x175 }, { TMS320C3X_null, 0x176 }, { TMS320C3X_null, 0x127 },// invalid + { TMS320C3X_null, 0x178 }, { TMS320C3X_null, 0x179 }, { TMS320C3X_null, 0x17a }, { TMS320C3X_null, 0x12b },// invalid + { TMS320C3X_null, 0x17c }, { TMS320C3X_null, 0x17d }, { TMS320C3X_null, 0x17e }, { TMS320C3X_null, 0x12f },// invalid + + { TMS320C3X_MV_IDX, 0x183 }, + { TMS320C3X_MV_IDX, 0x183 }, + { TMS320C3X_MV_IDX, 0x183 }, + { TMS320C3X_STF, 0x183, {{ S_R, 0x01c00000 }, { D_indir3, 0x000000ff }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x187 }, + { TMS320C3X_MV_IDX, 0x187 }, + { TMS320C3X_MV_IDX, 0x187 }, + { TMS320C3X_STI, 0x187, {{ S_R, 0x01c00000 }, { D_indir3, 0x000000ff }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x18b }, + { TMS320C3X_MV_IDX, 0x18b }, + { TMS320C3X_MV_IDX, 0x18b }, + { TMS320C3X_LDF, 0x18b, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_LDF, {{ S_indir3, 0x0000ff00 }, { D_R, 0x00380000 }}}, + { TMS320C3X_MV_IDX, 0x18f }, + { TMS320C3X_MV_IDX, 0x18f }, + { TMS320C3X_MV_IDX, 0x18f }, + { TMS320C3X_LDI, 0x18f, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_LDI, {{ S_indir3, 0x0000ff00 }, { D_R, 0x00380000 }}}, + { TMS320C3X_MV_IDX, 0x193 }, + { TMS320C3X_MV_IDX, 0x193 }, + { TMS320C3X_MV_IDX, 0x193 }, + { TMS320C3X_ABSF, 0x193, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x197 }, + { TMS320C3X_MV_IDX, 0x197 }, + { TMS320C3X_MV_IDX, 0x197 }, + { TMS320C3X_ABSI, 0x197, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x19b }, + { TMS320C3X_MV_IDX, 0x19b }, + { TMS320C3X_MV_IDX, 0x19b }, + { TMS320C3X_ADDF3, 0x19b, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x19f }, + { TMS320C3X_MV_IDX, 0x19f }, + { TMS320C3X_MV_IDX, 0x19f }, + { TMS320C3X_ADDI3, 0x19f, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1a3 }, + { TMS320C3X_MV_IDX, 0x1a3 }, + { TMS320C3X_MV_IDX, 0x1a3 }, + { TMS320C3X_AND3, 0x1a3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1a7 }, + { TMS320C3X_MV_IDX, 0x1a7 }, + { TMS320C3X_MV_IDX, 0x1a7 }, + { TMS320C3X_ASH3, 0x1a7, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1ab }, + { TMS320C3X_MV_IDX, 0x1ab }, + { TMS320C3X_MV_IDX, 0x1ab }, + { TMS320C3X_FIX, 0x1ab, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1af }, + { TMS320C3X_MV_IDX, 0x1af }, + { TMS320C3X_MV_IDX, 0x1af }, + { TMS320C3X_FLOAT, 0x1af, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1b3 }, + { TMS320C3X_MV_IDX, 0x1b3 }, + { TMS320C3X_MV_IDX, 0x1b3 }, + { TMS320C3X_LDF, 0x1b3, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1b7 }, + { TMS320C3X_MV_IDX, 0x1b7 }, + { TMS320C3X_MV_IDX, 0x1b7 }, + { TMS320C3X_LDI, 0x1b7, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1bb }, + { TMS320C3X_MV_IDX, 0x1bb }, + { TMS320C3X_MV_IDX, 0x1bb }, + { TMS320C3X_LSH3, 0x1bb, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1bf }, + { TMS320C3X_MV_IDX, 0x1bf }, + { TMS320C3X_MV_IDX, 0x1bf }, + { TMS320C3X_MPYF3, 0x1bf, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1c3 }, + { TMS320C3X_MV_IDX, 0x1c3 }, + { TMS320C3X_MV_IDX, 0x1c3 }, + { TMS320C3X_MPYI3, 0x1c3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1c7 }, + { TMS320C3X_MV_IDX, 0x1c7 }, + { TMS320C3X_MV_IDX, 0x1c7 }, + { TMS320C3X_NEGF, 0x1c7, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1cb }, + { TMS320C3X_MV_IDX, 0x1cb }, + { TMS320C3X_MV_IDX, 0x1cb }, + { TMS320C3X_NEGI, 0x1cb, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1cf }, + { TMS320C3X_MV_IDX, 0x1cf }, + { TMS320C3X_MV_IDX, 0x1cf }, + { TMS320C3X_NOT, 0x1cf, {{ S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1d3 }, + { TMS320C3X_MV_IDX, 0x1d3 }, + { TMS320C3X_MV_IDX, 0x1d3 }, + { TMS320C3X_OR3, 0x1d3, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1d7 }, + { TMS320C3X_MV_IDX, 0x1d7 }, + { TMS320C3X_MV_IDX, 0x1d7 }, + { TMS320C3X_SUBF3, 0x1d7, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STF, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1db }, + { TMS320C3X_MV_IDX, 0x1db }, + { TMS320C3X_MV_IDX, 0x1db }, + { TMS320C3X_SUBI3, 0x1db, {{ S_R, 0x00380000 }, { S_indir3, 0x000000ff }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, + { TMS320C3X_MV_IDX, 0x1df }, + { TMS320C3X_MV_IDX, 0x1df }, + { TMS320C3X_MV_IDX, 0x1df }, + { TMS320C3X_XOR3, 0x1df, {{ S_indir3, 0x000000ff }, { S_R, 0x00380000 }, { D_R, 0x01c00000 }}, + TMS320C3X_STI, {{ S_R, 0x00070000 }, { D_indir3, 0x0000ff00 }}}, +}; + +//-------------------------------------------------------------------------- +int tms320c3x_t::run_functions(ctx_t &ctx, int value, int entry, int start, int end) +{ + const opcode_t &opcode = table[entry]; + for ( int j = start; j <= end; j++ ) + { + const funcdesc_t &fd = opcode.funcs[j]; + if ( fd.func == NULL ) + break; + if ( !fd.func(ctx, (value & fd.mask) >> fd.shift) ) + return false; + } + return true; +} + +//-------------------------------------------------------------------------- +int tms320c3x_t::run_functions2(ctx_t &ctx, int value, int entry, int start, int end) +{ + const opcode_t &opcode = table[entry]; + for ( int j = start; j <= end; j++ ) + { + const funcdesc_t &fd = opcode.funcs2[j]; + if ( fd.func == NULL ) + break; + if ( !fd.func(ctx, (value & fd.mask) >> fd.shift) ) + return false; + } + return true; +} + +//-------------------------------------------------------------------------- +int tms320c3x_t::ana(insn_t *insn) +{ + ctx_t ctx(insn); + + int value = get_wide_byte(insn->ea); + insn->size++; + + int idx = (value >> 23) & 0x1ff; + + // check for known opcode + insn->itype = idx >= table.size ? TMS320C3X_null : table[idx].itype; + + if ( insn->itype == TMS320C3X_MV_IDX ) // for this opcode use the next table line + insn->itype = table[ idx = table[idx].insnidx ].itype; + + if ( insn->itype != TMS320C3X_null ) + { + if ( !run_functions(ctx, value, idx, 0, FUNCS_COUNT - 1) ) + return 0; + + if ( table[idx].ispar ) + { + ctx.op++; + insn->itype2 = table[ idx = table[idx].insnidx ].itype2; // second (parallel) insn opcode + insn->i2op = ctx.op->n; // location for operand of the second insn + + if ( !run_functions2(ctx, value, idx, 0, FUNCS_COUNT - 1) ) + return 0; + } + return insn->size; // length is always 1 + } + else + { + return 0; + } +} + +//-------------------------------------------------------------------------- +void tms320c3x_t::gen_masks(void) +{ + for ( int i = 0; i < table.size; i++ ) + { + table[i].ispar = (table[i].insnidx & 0x100) != 0; + for ( int j = 0; j < FUNCS_COUNT; j++ ) + { + if ( table[i].funcs[j].func != NULL ) + { + for ( int b = 0; b < 32; b++ ) + { + if ( table[i].funcs[j].mask & (1 << b) ) + break; + else + table[i].funcs[j].shift++; + } + } + } + + if ( table[i].insnidx & 0x100 ) + for ( int j = 0; j < FUNCS_COUNT; j++ ) + { + if ( table[i].funcs2[j].func != NULL ) + { + for ( int b = 0; b < 32; b++ ) + { + if ( table[i].funcs2[j].mask & (1 << b) ) + break; + else + table[i].funcs2[j].shift++; + } + } + } + } +} + +//---------------------------------------------------------------------- +void tms320c3x_t::init_analyzer(void) +{ + table.create(table_pattern, qnumber(table_pattern)); + gen_masks(); +} + +//---------------------------------------------------------------------- +void tms320c3_table_t::create(const opcode_t src_table[], int src_table_size) +{ + size = src_table_size; + entries = qalloc_array<opcode_t>(size); + memcpy(entries, src_table, sizeof(opcode_t) * size); +} + +//---------------------------------------------------------------------- +tms320c3_table_t::~tms320c3_table_t() +{ + qfree(entries); + entries = nullptr; +} + +//---------------------------------------------------------------------- +opcode_t &tms320c3_table_t::operator[](size_t i) +{ + return entries[i]; +} diff --git a/idasdk75/module/tms320c3/emu.cpp b/idasdk76/module/tms320c3/emu.cpp similarity index 100% rename from idasdk75/module/tms320c3/emu.cpp rename to idasdk76/module/tms320c3/emu.cpp diff --git a/idasdk75/module/tms320c3/ins.cpp b/idasdk76/module/tms320c3/ins.cpp similarity index 100% rename from idasdk75/module/tms320c3/ins.cpp rename to idasdk76/module/tms320c3/ins.cpp diff --git a/idasdk76/module/tms320c3/ins.hpp b/idasdk76/module/tms320c3/ins.hpp new file mode 100644 index 0000000..eb1bf97 --- /dev/null +++ b/idasdk76/module/tms320c3/ins.hpp @@ -0,0 +1,116 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum +{ +TMS320C3X_null = 0, // Unknown Operation + +TMS320C3X_ABSF, // Absolute value of a floating-point number +TMS320C3X_ABSI, // Absolute value of an integer +TMS320C3X_ADDC, // Add integers with carry +TMS320C3X_ADDF, // Add Floating-Point Values +TMS320C3X_ADDI, // Add Integer +TMS320C3X_AND, // Bitwise-Logical AND +TMS320C3X_ANDN, // Bitwise-Logical AND With Complement +TMS320C3X_ASH, // Arithmetic Shift +TMS320C3X_CMPF, // Compare Floating-Point Value +TMS320C3X_CMPI, // Compare Integer +TMS320C3X_FIX, // Floating-Point-to-Integer Conversion +TMS320C3X_FLOAT, // Integer-to-Floating-Point Conversion +TMS320C3X_IDLE, // Idle Until Interrupt +TMS320C3X_IDLE2, // Low-Power Idle +TMS320C3X_LDE, // Load Floating-Point Exponent +TMS320C3X_LDF, // Load Floating-Point Value +TMS320C3X_LDFI, // Load Floating-Point Value, Interlocked +TMS320C3X_LDI, // Load Integer +TMS320C3X_LDII, // Load Integer, Interlocked +TMS320C3X_LDM, // Load Floating-Point Mantissa +TMS320C3X_LSH, // Logical Shift +TMS320C3X_MPYF, // Multiply Floating-Point Value +TMS320C3X_MPYI, // Multiply Integer +TMS320C3X_NEGB, // Negative Integer With Borrow +TMS320C3X_NEGF, // Negate Floating-Point Value +TMS320C3X_NEGI, // Negate Integer +TMS320C3X_NOP, // No Operation +TMS320C3X_NORM, // Normalize +TMS320C3X_NOT, // Bitwise-Logical Complement +TMS320C3X_POP, // Pop Integer +TMS320C3X_POPF, // Pop Floating-Point Value +TMS320C3X_PUSH, // PUSH Integer +TMS320C3X_PUSHF, // PUSH Floating-Point Value +TMS320C3X_OR, // Bitwise-Logical OR +TMS320C3X_LOPOWER, // Divide Clock by 16 +TMS320C3X_MAXSPEED, // Restore Clock to Regular Speed +TMS320C3X_RND, // Round Floating-Point Value +TMS320C3X_ROL, // Rotate Left +TMS320C3X_ROLC, // Rotate Left Through Carry +TMS320C3X_ROR, // Rotate Right +TMS320C3X_RORC, // Rotate Right Through Carry +TMS320C3X_RPTS, // Repeat Single Instruction +TMS320C3X_STF, // Store Floating-Point Value +TMS320C3X_STFI, // Store Floating-Point Value, Interlocked +TMS320C3X_STI, // Store Integer +TMS320C3X_STII, // Store Integer, Interlocked +TMS320C3X_SIGI, // Signal, Interlocked +TMS320C3X_SUBB, // Subtract Integer With Borrow +TMS320C3X_SUBC, // Subtract Integer Conditionally +TMS320C3X_SUBF, // Subtract Floating-Point Value +TMS320C3X_SUBI, // Subtract Integer +TMS320C3X_SUBRB, // Subtract Reverse Integer With Borrow +TMS320C3X_SUBRF, // Subtract Reverse Floating-Point Value +TMS320C3X_SUBRI, // Subtract Reverse Integer +TMS320C3X_TSTB, // Test Bit Fields +TMS320C3X_XOR, // Bitwise-Exclusive OR +TMS320C3X_IACK, // Interrupt acknowledge + +TMS320C3X_ADDC3, // Add integers with carry (3-operand) +TMS320C3X_ADDF3, // Add floating-point values (3-operand) +TMS320C3X_ADDI3, // Add integers (3 operand) +TMS320C3X_AND3, // Bitwise-logical AND (3-operand) +TMS320C3X_ANDN3, // Bitwise-logical ANDN (3-operand) +TMS320C3X_ASH3, // Arithmetic shift (3-operand) +TMS320C3X_CMPF3, // Compare floating-point values (3-operand) +TMS320C3X_CMPI3, // Compare integers (3-operand) +TMS320C3X_LSH3, // Logical shift (3-operand) +TMS320C3X_MPYF3, // Multiply floating-point value (3-operand) +TMS320C3X_MPYI3, // Multiply integers (3-operand) +TMS320C3X_OR3, // Bitwise-logical OR (3-operand) +TMS320C3X_SUBB3, // Subtract integers with borrow (3-operand) +TMS320C3X_SUBF3, // Subtract floating-point values (3-operand) +TMS320C3X_SUBI3, // Subtract integers (3-operand) +TMS320C3X_TSTB3, // Test Bit Fields, 3-Operand +TMS320C3X_XOR3, // Bitwise-Exclusive OR, 3-Operand + +TMS320C3X_LDFcond, // Load floating-point value conditionally +TMS320C3X_LDIcond, // Load integer conditionally +TMS320C3X_BR, // Branch unconditionally (standard) +TMS320C3X_BRD, // Branch unconditionally (delayed) +TMS320C3X_CALL, // Call subroutine +TMS320C3X_RPTB, // Repeat block of instructions +TMS320C3X_SWI, // Software Interrupt +TMS320C3X_Bcond, // Branch conditionally +TMS320C3X_DBcond, // Decrement and branch conditionally +TMS320C3X_CALLcond, // Call subroutine conditionally +TMS320C3X_TRAPcond, // Trap Conditionally +TMS320C3X_RETIcond, // Return from interrupt conditionally +TMS320C3X_RETScond, // Return from subroutine conditionally +TMS320C3X_RETIU, // Return from interrupt unconditionally +TMS320C3X_RETSU, // Return from subroutine unconditionally + +TMS320C3X_NONE, // Pseudo insn (more accurate definition need) +TMS320C3X_MV_IDX, // Pseudo insn (move to next index need) +TMS320C3X_last, // last ID + +}; + + +#endif diff --git a/idasdk76/module/tms320c3/makefile b/idasdk76/module/tms320c3/makefile new file mode 100644 index 0000000..57f0015 --- /dev/null +++ b/idasdk76/module/tms320c3/makefile @@ -0,0 +1,58 @@ +PROC=tms320c3 +CONFIGS=tms320c3.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp ins.hpp tms320c3x.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp tms320c3x.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp tms320c3x.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp \ + tms320c3x.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp reg.cpp tms320c3x.hpp diff --git a/idasdk76/module/tms320c3/out.cpp b/idasdk76/module/tms320c3/out.cpp new file mode 100644 index 0000000..1586c29 --- /dev/null +++ b/idasdk76/module/tms320c3/out.cpp @@ -0,0 +1,418 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "tms320c3x.hpp" +#include <frame.hpp> +#include <segregs.hpp> +#include <struct.hpp> + +// simple wrapper class for syntactic sugar of member functions +// this class may have only simple member functions. +// virtual functions and data fields are forbidden, otherwise the class +// layout may change +class out_tms320c3_t : public outctx_t +{ + out_tms320c3_t(void) = delete; // not used +public: + bool out_operand(const op_t &x); + void out_insn(void); + void out_proc_mnem(void); + void out_address(ea_t ea, const op_t &x, bool at); +}; +CASSERT(sizeof(out_tms320c3_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS(out_tms320c3_t) + +//---------------------------------------------------------------------- +#define SYM(x) COLSTR(x, SCOLOR_SYMBOL) +#define REG(x) COLSTR(x, SCOLOR_REG) +#define REGP(x) SYM("(") REG(x) SYM(")") + +// o_phrase output format strings, indexed by phtype +static const char *const formats[0x1a] = +{ + SYM("*+") REG("%s"), // 0 "*+arn(NN)" + SYM("*-") REG("%s"), // 1 "*-arn(NN)" + SYM("*++") REG("%s"), // 2 "*++arn(NN)" + SYM("*--") REG("%s"), // 3 "*--arn(NN)" + SYM("*") REG("%s") SYM("++"), // 4 "*arn++(NN)" + SYM("*") REG("%s") SYM("--"), // 5 "*arn--(NN)" + SYM("*") REG("%s") SYM("++"), // 6 "*arn++(NN)%" + SYM("*") REG("%s") SYM("--"), // 7 "*arn--(NN)%" + SYM("*+") REG("%s") REGP("ir0"), // 8 "*+arn(ir0)" + SYM("*-") REG("%s") REGP("ir0"), // 9 "*-arn(ir0)" + SYM("*++") REG("%s") REGP("ir0"), // a "*++arn(ir0)" + SYM("*--") REG("%s") REGP("ir0"), // b "*--arn(ir0)" + SYM("*") REG("%s") SYM("++") REGP("ir0"), // c "*arn++(ir0)" + SYM("*") REG("%s") SYM("--") REGP("ir0"), // d "*arn--(ir0)" + SYM("*") REG("%s") SYM("++") REGP("ir0") SYM("%%"), // e "*arn++(ir0)%" + SYM("*") REG("%s") SYM("--") REGP("ir0") SYM("%%"), // f "*arn--(ir0)%" + SYM("*+") REG("%s") REGP("ir1"), // 10 "*+arn(ir1)" + SYM("*-") REG("%s") REGP("ir1"), // 11 "*-arn(ir1)" + SYM("*++") REG("%s") REGP("ir1"), // 12 "*++arn(ir1)" + SYM("*--") REG("%s") REGP("ir1"), // 13 "*--arn(ir1)" + SYM("*") REG("%s") SYM("++") REGP("ir1"), // 14 "*arn++(ir1)" + SYM("*") REG("%s") SYM("--") REGP("ir1"), // 15 "*arn--(ir1)" + SYM("*") REG("%s") SYM("++") REGP("ir1") SYM("%%"), // 16 "*arn++(ir1)%" + SYM("*") REG("%s") SYM("--") REGP("ir1") SYM("%%"), // 17 "*arn--(ir1)%" + SYM("*") REG("%s"), // 18 "*arn" + SYM("*") REG("%s") SYM("++") REGP("ir0") SYM("B"), // 19 "*arn++(ir0)B" +}; + +//-------------------------------------------------------------------------- +static const char *const cc_text[] = +{ + // Unconditional compares + "u", // Unconditional + + // Unsigned compares + "lo", // Lower than + "ls", // Lower than or same as + "hi", // Higher than + "hs", // Higher than or same as + "e", // Equal to + "ne", // Not equal to + + // Signed compares + "lt", // Less than + "le", // Less than or equal to + "gt", // Greater than + "ge", // Greater than or equal to + + // Unknown + "?", // Unknown + + // Compare to condition flags + "nv", // No overflow + "v", // Overflow + "nuf", // No underflow + "uf", // Underflow + "nlv", // No latched overflow + "lv", // Latched overflow + "nluf", // No latched floating-point underflow + "luf", // Latched floating-point underflow + "zuf" // Zero or floating-point underflow +}; + +//---------------------------------------------------------------------- +void out_tms320c3_t::out_address(ea_t ea, const op_t &x, bool at) +{ + qstring qbuf; + if ( get_name_expr(&qbuf, insn.ea+x.offb, x.n, ea, ea) > 0 ) + { + if ( at ) + out_symbol('@'); + out_line(qbuf.begin()); + } + else + { + if ( at ) + out_symbol('@'); + out_tagon(COLOR_ERROR); + out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16); + out_printf(" (ea = %a)", ea); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + +} + +//---------------------------------------------------------------------- +bool out_tms320c3_t::out_operand(const op_t &x) +{ + ea_t ea; + char buf[MAXSTR]; + + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + out_register(ph.reg_names[x.reg]); + break; + + case o_near: + out_address(calc_code_mem(insn, x), x, false); + break; + + case o_imm: + if ( insn.itype != TMS320C3X_TRAPcond ) + out_symbol('#'); + + if ( insn.auxpref & ImmFltFlag ) + { + int16 v = int16(x.value); + print_fpval(buf, sizeof(buf), &v, 2); + out_line(buf[0] == ' ' ? &buf[1] : buf, COLOR_NUMBER); + } + else + { + out_value(x, OOFW_IMM); + } + break; + + case o_mem: + ea = calc_data_mem(insn, x); + if ( ea != BADADDR ) + { + out_address(ea, x, true); + } + else + { + out_tagon(COLOR_ERROR); + out_value(x, OOFW_IMM|OOF_ADDR|OOFW_16); + out_tagoff(COLOR_ERROR); + } + break; + + case o_phrase: // Indirect addressing mode + { + if ( x.phrase < qnumber(formats) ) + { + op_t y = x; + bool outdisp = x.phrase < 8; + bool printmod = x.phrase >= 6; + if ( x.phrase == 0x18 ) + { + // this is *arn phrase + // check if we need to print the displacement + int n = x.n; + if ( is_off(F, n) || is_stkvar(F, n) || is_enum(F, n) || is_stroff(F, n) ) + { + outdisp = true; + y.addr = 0; + printmod = false; + y.phrase = 0; // use '*+arn(NN)' syntax + } + } + + // print the base part + const char *reg = ph.reg_names[uchar(y.phtype)]; + nowarn_qsnprintf(buf, sizeof(buf), formats[uchar(y.phrase)], reg); + out_colored_register_line(buf); + + // print the displacement + if ( outdisp ) + { + out_symbol('('); + out_value(y, OOFS_IFSIGN|OOF_ADDR|OOFW_32); + out_symbol(')'); + if ( printmod ) + out_symbol('%'); // %: circular modify + } + } + else + { + out_line("<bad indirect>", COLOR_ERROR); + } + break; + } + + default: + INTERR(10261); + } + return 1; +} + +//---------------------------------------------------------------------- +void out_tms320c3_t::out_proc_mnem(void) +{ + char postfix[8]; + postfix[0] = '\0'; + switch ( insn.itype ) + { + case TMS320C3X_LDFcond: + case TMS320C3X_LDIcond: + case TMS320C3X_Bcond: + case TMS320C3X_DBcond: + case TMS320C3X_CALLcond: + case TMS320C3X_TRAPcond: + case TMS320C3X_RETIcond: + case TMS320C3X_RETScond: + qstrncpy(postfix, cc_text[insn.auxpref & 0x1f ], sizeof(postfix)); + if ( insn.auxpref & DBrFlag ) // delayed branch? + qstrncat(postfix, "d", sizeof(postfix)); + break; + } + + out_mnem(8, postfix); +} + +//---------------------------------------------------------------------- +void out_tms320c3_t::out_insn(void) +{ + out_mnemonic(); + + // following operand combinations exist: + // 0, 1, 2, 3 for non-parallel + // 2+2, 3+2, 3+3 for parallel + + out_one_operand(0); // two operands can be printed always + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_one_operand(1); + } + if ( insn.itype2 ) // Parallel + { + if ( insn.i2op > 2 ) // 3rd operand is for first instruction half + { + out_symbol(','); + out_one_operand(2); + } + flush_outbuf(); + + char insn2[MAXSTR]; + qsnprintf(insn2, sizeof(insn2), "||%s", ph.instruc[uchar(insn.itype2)].name); + ::add_spaces(insn2, sizeof(insn2), 8); + out_line(insn2, COLOR_INSN); + + if ( insn.i2op == 2 ) // 3rd operand is for second instruction half + { + out_one_operand(2); + out_symbol(','); + } + + if ( insn.Op4.type != o_void ) + out_one_operand(3); + + if ( insn.Op5.type != o_void ) + { + out_symbol(','); + out_one_operand(4); + } + + if ( insn.Op6.type != o_void ) + { + out_symbol(','); + out_one_operand(5); + } + } + else if ( insn.Op3.type != o_void ) + { + out_symbol(','); + out_one_operand(2); + } + + out_immchar_cmts(); + + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void tms320c3x_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) +{ + if ( reg == ph.reg_data_sreg ) + return; + if ( value != BADADDR ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), value); + ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); + } + else + { + ctx.gen_cmt_line("drop %s", ph.reg_names[reg]); + } +} + +//-------------------------------------------------------------------------- +// function to produce assume directives +//lint -e{1764} ctx could be const +void tms320c3x_t::assumes(outctx_t &ctx) +{ + ea_t ea = ctx.insn_ea; + segment_t *seg = getseg(ea); + if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) + return; + bool seg_started = (ea == seg->start_ea); + + for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) + { + if ( i == ph.reg_code_sreg ) + continue; + sreg_range_t sra; + if ( !get_sreg_range(&sra, ea, i) ) + continue; + if ( seg_started || sra.start_ea == ea ) + { + sel_t now = get_sreg(ea, i); + sreg_range_t prev; + bool prev_exists = get_sreg_range(&prev, ea-1, i); + if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) ) + print_segment_register(ctx, i, now); + } + } +} + +//-------------------------------------------------------------------------- +//lint -e{818} seg could be const +void tms320c3x_t::segstart(outctx_t &ctx, segment_t *seg) const +{ + if ( is_spec_segm(seg->type) ) + return; + + qstring sclas; + get_segm_class(&sclas, seg); + + if ( sclas == "CODE" ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR)); + else if ( sclas == "DATA" ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR)); + + if ( seg->orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), seg->orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +void idaapi segend(outctx_t &, segment_t *) +{ +} + +//-------------------------------------------------------------------------- +void tms320c3x_t::header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL | GH_BYTESEX_HAS_HIGHBYTE, NULL, ioh.device.c_str()); + ctx.gen_empty_line(); +} + +//-------------------------------------------------------------------------- +void tms320c3x_t::footer(outctx_t &ctx) const +{ + ctx.gen_printf(DEFAULT_INDENT,COLSTR("%s",SCOLOR_ASMDIR),ash.end); +} + +//-------------------------------------------------------------------------- +void tms320c3x_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const +{ + char sign = ' '; + if ( v < 0 ) + { + sign = '-'; + v = -v; + } + + qstring name = get_member_name(mptr->id); + + char vstr[MAX_NUMBUF]; + btoa(vstr, sizeof(vstr), v); + ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) + COLSTR("%c%s",SCOLOR_DNUM) + COLSTR(",",SCOLOR_SYMBOL) " " + COLSTR("%s",SCOLOR_LOCNAME), + ash.a_equ, + sign, + vstr, + name.c_str()); +} diff --git a/idasdk76/module/tms320c3/reg.cpp b/idasdk76/module/tms320c3/reg.cpp new file mode 100644 index 0000000..d50dc4b --- /dev/null +++ b/idasdk76/module/tms320c3/reg.cpp @@ -0,0 +1,614 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include <math.h> +#include "tms320c3x.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +#include <ieee.h> +int data_id; + +static const char *const register_names[] = +{ + // Extended-precision registers + "r0", + "r1", + "r2", + "r3", + "r4", + "r5", + "r6", + "r7", + // Auxiliary registers + "ar0", + "ar1", + "ar2", + "ar3", + "ar4", + "ar5", + "ar6", + "ar7", + + // Index register n + "ir0", + "ir1", + + "bk", // Block-size register + "sp", // System-stack pointer + "st", // Status register + "ie", // CPU/DMA interrupt-enable register + "if", // CPU interrupt flag + "iof", // I/O flag + "rs", // Repeat start-address + "re", // Repeat end-address + "rc", // Repeat counter + + // segment registers + "dp", // Data-page pointer + "cs","ds", // virtual registers for code and data segments + +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0x78, 0x80, 0x00, 0x00 }; // 0x78800000 //retsu +static const uchar retcode_1[] = { 0x78, 0x00, 0x00, 0x00 }; // 0x78000000 //retiu + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// TMS320C3X ASM +//----------------------------------------------------------------------- +static const asm_t fasm = +{ + AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON, + 0, + "ASM500", + 0, + NULL, // header lines + NULL, // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".pstring", // ascii string directive + ".word", // byte directive + ".long", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".space 32*%s",// uninited arrays + ".asg", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".ref", // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_BYTE1CHAR,// one character per byte +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gnuasm = +{ + AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON|AS_ASCIIC, + 0, + "GNU assembler", + 0, + NULL, // header lines + NULL, // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".pstring", // ascii string directive + ".word", // byte directive + ".long", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".zero 2*%s", // uninited arrays + ".asg", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + ".weak", // "weak" name keyword + ".extern", // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_BYTE1CHAR,// one character per byte + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt +}; + +static const asm_t *const asms[] = { &fasm, &gnuasm, NULL }; + +//-------------------------------------------------------------------------- +bool tms320c3x_iohandler_t::entry_processing(ea_t &ea, const char *name, const char *cmt) +{ + set_name(ea, name, SN_NODUMMY); + set_cmt(ea, cmt, 0); + return true; +} + +//---------------------------------------------------------------------- +bool tms320c3x_t::select_device(int lrespect_info) +{ + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( !choose_ioport_device(&ioh.device, cfgfile) ) + { + ioh.device = NONEPROC; + return false; + } + + if ( !ioh.display_infotype_dialog(IORESP_ALL, &lrespect_info, cfgfile) ) + return false; + + ioh.set_device_name(ioh.device.c_str(), lrespect_info); + return true; +} + +//---------------------------------------------------------------------- +static float conv32(int32 A) // convertion of 32 bit TMS float -> double +{ + int32 mask, f, i, s; + float mant; + int8 e; + + // exponent, signed 8 bit + e = A >> 24; + + // sign, boolean 1 bit + s = (A & 0x00800000) >> 23; + + // fraction, unsigned 23 bit + f = A & 0x007FFFFF; + + // NaN, Inf + if ( (e & 0xFF) == 0xFF ) + { + uint32 i32 = (s << 31) | (0xFF << 23) | f; + + return *reinterpret_cast<float*>(&i32); + } + + if ( s ) + { + f ^= 0x007FFFFF; + f++; + } + + mant = 1; // mantissa (1<M<2) + mask = 0x00800000; // bit mask of the current bit, + // started from the sign position + + for ( i = 0; i <= 23; i++ ) + { + if ( f & mask ) + mant += (float)pow(double(2), -i); + mask >>= 1; + } + + if ( e == -128 && f == 0 && s == 0 ) + mant = 0; + + return float(pow(double(-1), s) * mant * pow(double(2), e)); +} + +//---------------------------------------------------------------------- +// A short floating-point format for immediate floating-point operands, consisting +// of a 4-bit exponent, a sign bit, and an 11-bit fraction +// x = 01.f * 2^e if s = 0 +// x = 10.f * 2^e if s = 1 +// x = 0 if e = -8 +static float conv16(int16 A) // Convertion of 16 bit TMS float to double +{ + int16 mask, f, i, s; + float mant; + int8 e; + + // exponent, signed 4 bit + e = A >> 12; + + // sign, boolean 1 bit + s = (A & 0x0800) >> 11; + + // fraction, unsigned 11 bit + f = A & 0x07FF; + + // Apparently the 16-bit format does not include + // NaN of Inf at all (the exponent is too small anyway); + // though this is a guess by omission (the documentation + // mention appropriate conversions for 32-bits but not for 16-bits). + // I think the 16-bit format is intended for short immediate values + // rather than FPU operations, so it makes some sense. + // + // Therefore, no account for NaN of Inf is done in the 16-bit format. + + if ( s ) + { + f ^= 0x07FF; + f++; + } + + mant = 1; // mantissa (1<M<2) + mask = 0x0800; // bit mask for the current bit + + for ( i = 0; i <= 11; i++ ) + { + if ( f & mask ) + mant += (float)pow(double(2), -i); + mask >>= 1; + } + + if ( e == -8 && f == 0 && s == 0 ) + mant = 0; + + return float(pow(double(-1), s) * mant * pow(double(2), e)); +} + +//-------------------------------------------------------------------------- +//lint -esym(818, m) +fpvalue_error_t idaapi tms_realcvt(void *m, fpvalue_t *e, ushort swt) +{ + fpvalue_error_t ret; + int32 A; + int16 B; + + union + { + float pfl; + int32 pint; + }; + + switch ( swt ) + { + case 0: // TmsFloat 16bit to e + memcpy(&B, m, 2); + pfl = conv16(B); + pint = swap32(pint); + ret = ieee_realcvt(&pint, e, 1); + break; + + case 1: // TmsFloat 32bit to e + memcpy(&A, m, 4); + pfl = conv32(A); + pint = swap32(pint); + ret = ieee_realcvt(&pint, e, 1); + break; + + default: + msg("real_cvt_error swt = %d \n", swt); + return REAL_ERROR_FORMAT; + } + return ret; +} + +//-------------------------------------------------------------------------- +const char *tms320c3x_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + select_device(IORESP_PORT|IORESP_INT); + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +void tms320c3x_t::load_from_idb() +{ + inf_set_wide_high_byte_first(false); + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(tms320c3x_t)); + return 0; +} + +//---------------------------------------------------------------------- +ssize_t idaapi tms320c3x_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); // MSB first + inf_set_wide_high_byte_first(true); + init_analyzer(); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + inf_set_wide_high_byte_first(false); + if ( inf_like_binary() ) + { + segment_t *s0 = get_first_seg(); + if ( s0 != NULL ) + { + set_segm_name(s0, "CODE"); + segment_t *s1 = get_next_seg(s0->start_ea); + for ( int i = dp; i <= rVds; i++ ) + { + set_default_sreg_value(s0, i, BADSEL); + set_default_sreg_value(s1, i, BADSEL); + } + } + select_device(IORESP_ALL); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: // old file loaded + load_from_idb(); + break; + + case processor_t::ev_is_basic_block_end: + { + const insn_t &insn = *va_arg(va, const insn_t *); + return is_basic_block_end(insn) ? 1 : 0; + } + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *op = va_arg(va, const op_t *); + return can_have_type(*op) ? 1 : -1; + } + + case processor_t::ev_realcvt: + { + void *m = va_arg(va, void *); + fpvalue_t *e = va_arg(va, fpvalue_t *); + uint16 swt = va_argi(va, uint16); + fpvalue_error_t code1 = tms_realcvt(m, e, swt); + return code1 == REAL_ERROR_OK ? 1 : code1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_gen_stkvar_def: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const member_t *mptr = va_arg(va, const member_t *); + sval_t v = va_arg(va, sval_t); + gen_stkvar_def(*ctx, mptr, v); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "TMS320C3x Series:" +static const char *const shnames[] = +{ + "TMS320C3", + NULL +}; +static const char *const lnames[] = +{ + FAMILY"Texas Instruments TMS320C3X", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_TMS320C3, // id + // flag + PRN_HEX + | PR_SEGS + | PR_SGROTHER + | PR_ALIGN + | PR_USE32 + | PR_DEFSEG32 + | PR_DELAYED, + // flag2 + PR2_REALCVT // the module has 'realcvt' event implementation + | PR2_IDP_OPTS, // the module has processor-specific configuration options + 32, // 32 bits in a byte for code segments + 32, // 32 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + dp, // first + rVds, // last + 1, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + TMS320C3X_null, + TMS320C3X_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 4,7,15,19 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + TMS320C3X_RETSU, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/tms320c3/tms320c3.cfg b/idasdk76/module/tms320c3/tms320c3.cfg similarity index 100% rename from idasdk75/module/tms320c3/tms320c3.cfg rename to idasdk76/module/tms320c3/tms320c3.cfg diff --git a/idasdk76/module/tms320c3/tms320c3x.hpp b/idasdk76/module/tms320c3/tms320c3x.hpp new file mode 100644 index 0000000..c592e5d --- /dev/null +++ b/idasdk76/module/tms320c3/tms320c3x.hpp @@ -0,0 +1,173 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _TMS320C3X_HPP +#define _TMS320C3X_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" + + + +enum regnum_t +{ + // Extended-precision registers + r0 = 0, + r1, + r2, + r3, + r4, + r5, + r6, + r7, + // Auxiliary registers + ar0, + ar1, + ar2, + ar3, + ar4, + ar5, + ar6, + ar7, + + // Index register n + ir0, + ir1, + bk, // Block-size register + sp, // System-stack pointer + st, // Status register + ie, // CPU/DMA interrupt-enable register + if_reg, // CPU interrupt flag + iof, // I/O flag + rs, // Repeat start-address + re, // Repeat end-address + rc, // Repeat counter + // segment registers + dp, // DP register + rVcs, rVds // virtual registers for code and data segments +}; + + +//------------------------------------------------------------------ +// specific processor records + +#define phtype specflag1 // o_phrase: phrase type +// 0 "*+arn(NN)" +// 1 "*-arn(NN)" +// 2 "*++arn(NN)" +// 3 "*--arn(NN)" +// 4 "*arn++(NN)" +// 5 "*arn--(NN)" +// 6 "*arn++(NN)%%" +// 7 "*arn--(NN)%%" +// 8 "*+arn(ir0)" +// 9 "*-arn(ir0)" +// a "*++arn(ir0)" +// b "*--arn(ir0)" +// c "*arn++(ir0)" +// d "*arn--(ir0)" +// e "*arn++(ir0)%%" +// f "*arn--(ir0)%%" +// 10 "*+arn(ir1)" +// 11 "*-arn(ir1)" +// 12 "*++arn(ir1)" +// 13 "*--arn(ir1)" +// 14 "*arn++(ir1)" +// 15 "*arn--(ir1)" +// 16 "*arn++(ir1)%%" +// 17 "*arn--(ir1)%%" +// 18 "*arn" +// 19 "*arn++(ir0)B" + +#define itype2 segpref // 2-nd command type (within parallel instruction) +#define i2op insnpref // number of first operand that belong to 2-nd insn of parallel instruction +// auxpref flags: +#define DBrFlag 0x80 // Delayed branch flag +#define ImmFltFlag 0x40 // Imm float Value + +#include "../iohandler.hpp" + +//------------------------------------------------------------------ +struct tms320c3x_iohandler_t : public iohandler_t +{ + tms320c3x_iohandler_t(netnode &nn) : iohandler_t(nn) {} + virtual bool entry_processing(ea_t &ea, const char *name, const char *cmt) override; +}; + +struct ctx_t; +struct opcode_t; +struct tms320c3_table_t +{ + opcode_t *entries; + int size; + opcode_t &operator[](size_t i); + void create(const opcode_t src_table[], int src_table_size); + ~tms320c3_table_t(); +}; + +struct tms320c3x_t : public procmod_t +{ + netnode helper; + tms320c3x_iohandler_t ioh = tms320c3x_iohandler_t(helper); + + tms320c3_table_t table; + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + bool select_device(int lrespect_info); + const char *idaapi set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + + int ana(insn_t *insn); + void init_analyzer(void); + void gen_masks(void); + int run_functions(ctx_t &ctx, int value, int entry, int start, int end); + int run_functions2(ctx_t &ctx, int value, int entry, int start, int end); + + int emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use); + + void header(outctx_t &ctx); + void assumes(outctx_t &ctx); + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void segstart(outctx_t &ctx, segment_t *seg) const; + void footer(outctx_t &ctx) const; + void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; + + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ tms320c3x" +#define PROCMOD_NAME tms320c3x + +//------------------------------------------------------------------ +ea_t calc_code_mem(const insn_t &insn, const op_t &x); +ea_t calc_data_mem(const insn_t &insn, const op_t &x); + +regnum_t get_mapped_register(ea_t ea); +const char *get_cond8(char value); +int get_signed(int byte,int mask); + +//------------------------------------------------------------------ +void idaapi segend(outctx_t &, segment_t *seg); + +void idaapi data(outctx_t &ctx); + +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_align_insn(ea_t ea); +bool is_basic_block_end(const insn_t &insn); +bool idaapi can_have_type(const op_t &op); + +#endif // _TMS320C3X_HPP diff --git a/idasdk76/module/tms320c5/ana.cpp b/idasdk76/module/tms320c5/ana.cpp new file mode 100644 index 0000000..94d69a3 --- /dev/null +++ b/idasdk76/module/tms320c5/ana.cpp @@ -0,0 +1,1176 @@ +/* + * Interactive disassembler (IDA). + * Version 3.05 + * Copyright (c) 1990-95 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "tms.hpp" + +//---------------------------------------------------------------------- +inline ushort get_next_byte(insn_t &insn) +{ + return (ushort)get_wide_byte(insn.ea + insn.size++); +} + +//---------------------------------------------------------------------- +inline void op_daddr(insn_t &insn, op_t &o) // 16-bit address data +{ + o.type = o_mem; + o.addr = get_next_byte(insn); + o.sib = 1; +} + +//---------------------------------------------------------------------- +inline void op_paddr(insn_t &insn, op_t &o) // 16-bit address prog +{ + o.type = o_near; + o.addr = get_next_byte(insn); +} + +//---------------------------------------------------------------------- +inline void op_ioaddr(insn_t &insn, op_t &o) // 16-bit port address +{ + o.dtype = dt_word; + o.type = o_imm; + o.value = get_next_byte(insn); + o.sib = 1; +} + +//---------------------------------------------------------------------- +int tms320c5_t::op_iaa(const insn_t &insn, op_t &o) const // direct or indirect address +{ + if ( code & 0x80 ) + { + o.type = o_phrase; + o.phrase = (code & 0x7F); + if ( (o.phrase & 0x70) == 0x30 ) + return 0; + } + else + { + o.type = o_mem; + o.addr = (get_sreg(insn.ea, rDP)<<7) + (code & 0x7F); + o.sib = 0; + } + return 1; +} + +//---------------------------------------------------------------------- +int tms320c5_t::op_indir(op_t &o) // direct or indirect address +{ // optional + o.type = o_phrase; + o.phrase = (code & 0x7F); + if ( (o.phrase & 0x70) == 0x30 ) + return 0; + if ( (o.phrase & 0x70) == 0 ) + o.clr_shown(); + return 1; +} + +//---------------------------------------------------------------------- +int tms320c5_t::op_maa(const insn_t &insn, op_t &o) const // memory-mapped register from code +{ + if ( !op_iaa(insn, o) ) + return 0; + if ( o.type == o_mem ) + o.addr = (code & 0x7F); + return 1; +} + +//---------------------------------------------------------------------- +inline void op_ar(op_t &o, uint16 ar) // aux register +{ + o.type = o_reg; + o.reg = rAr0 + ar; +} + +//---------------------------------------------------------------------- +inline void op_imm(insn_t &insn, op_t &o) // 16-bit immediate +{ + o.dtype = dt_word; + o.type = o_imm; + o.value = get_next_byte(insn); + o.sib = 0; +} + +//---------------------------------------------------------------------- +inline void op_shift(op_t &o, int shift) // shift +{ + o.type = o_imm; + o.value = shift; + o.sib = 2; + if ( o.value == 0 ) + o.clr_shown(); +} + +//---------------------------------------------------------------------- +void tms320c5_t::op_short(op_t &o) const // short immediate +{ + o.dtype = dt_byte; + o.type = o_imm; + o.value = code & 0xFF; + o.sib = 0; +} + +//---------------------------------------------------------------------- +inline void op_cbit(op_t &o, int bit) +{ + o.type = o_bit; + o.value = bit; +} + +//---------------------------------------------------------------------- +int tms320c5_t::op_cond(op_t &o) const +{ + o.type = o_cond; + o.Cond = uint16(o.value = (code & 0x3FF)); + int mask = int(o.value>>0) & 0xF; + int cond = int(o.value>>4) & 0xF; + if ( ((mask>>2) & 3) == 3 ) // Z L + { + switch ( (cond>>2)&3 ) + { + case 0: + case 1: + return 0; + } + } + return 1; +} + +//---------------------------------------------------------------------- +void tms320c5_t::op_bit(op_t &o) const +{ + o.type = o_imm; +// strange? documentation say this way: o.value = 15 - ((code >> 8) & 0xF); +// assembler works this way: + o.value = (code >> 8) & 0xF; + o.sib = 3; +} + +//---------------------------------------------------------------------- +int tms320c5_t::ana_c2(insn_t &insn) +{ + uchar subcode = (code >> 8) & 0xF; + switch ( code >> 12 ) + { +// 0000 SSSS MDDD DDDD TMS2_add +// 0001 SSSS MDDD DDDD TMS2_sub +// 0010 SSSS MDDD DDDD TMS2_lac + case 0: + insn.itype = TMS2_add; + goto iaa_shift; + case 1: + insn.itype = TMS2_sub; + goto iaa_shift; + case 2: + insn.itype = TMS2_lac; +iaa_shift: + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_shift(insn.Op2, subcode); + break; + +// 0011 0RRR MDDD DDDD TMS2_lar +// 0011 1000 MDDD DDDD TMS2_mpy +// 0011 1001 MDDD DDDD TMS2_sqra +// 0011 1010 MDDD DDDD TMS2_mpya +// 0011 1011 MDDD DDDD TMS2_mpys +// 0011 1100 MDDD DDDD TMS2_lt +// 0011 1101 MDDD DDDD TMS2_lta +// 0011 1110 MDDD DDDD TMS2_ltp +// 0011 1111 MDDD DDDD TMS2_ltd + case 3: + if ( subcode < 8 ) + { + insn.itype = TMS2_lar; + op_ar(insn.Op1, subcode); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + } + else + { + static const uchar codes[8] = + { + TMS2_mpy, TMS2_sqra, TMS2_mpya, TMS2_mpys, + TMS2_lt, TMS2_lta, TMS2_ltp, TMS2_ltd + }; + insn.itype = codes[subcode-8]; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + } + break; + +// 0100 0000 MDDD DDDD TMS2_zalh +// 0100 0001 MDDD DDDD TMS2_zals +// 0100 0010 MDDD DDDD TMS2_lact +// 0100 0011 MDDD DDDD TMS2_addc +// 0100 0100 MDDD DDDD TMS2_subh +// 0100 0101 MDDD DDDD TMS2_subs +// 0100 0110 MDDD DDDD TMS2_subt +// 0100 0111 MDDD DDDD TMS2_subc +// 0100 1000 MDDD DDDD TMS2_addh +// 0100 1001 MDDD DDDD TMS2_adds +// 0100 1010 MDDD DDDD TMS2_addt +// 0100 1011 MDDD DDDD TMS2_rpt +// 0100 1100 MDDD DDDD TMS2_xor +// 0100 1101 MDDD DDDD TMS2_or +// 0100 1110 MDDD DDDD TMS2_and +// 0100 1111 MDDD DDDD TMS2_subb + case 4: + { + static const ushort codes[16] = + { + TMS2_zalh, TMS2_zals, TMS2_lact, TMS2_addc, + TMS2_subh, TMS2_subs, TMS2_subt, TMS2_subc, + TMS2_addh, TMS2_adds, TMS2_addt, TMS2_rpt, + TMS2_xor, TMS2_or, TMS2_and, TMS2_subb + }; + insn.itype = codes[subcode]; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + } + break; + +// 0101 0000 MDDD DDDD TMS2_lst +// 0101 0001 MDDD DDDD TMS2_lst1 +// 0101 0010 MDDD DDDD TMS2_ldp +// 0101 0011 MDDD DDDD TMS2_lph +// 0101 0100 MDDD DDDD TMS2_pshd +// 0101 0101 0000 0000 TMS2_nop +// 0101 0101 1000 1RRR TMS2_larp +// 0101 0101 MDDD DDDD TMS2_mar +// 0101 0110 MDDD DDDD TMS2_dmov +// 0101 0111 MDDD DDDD TMS2_bitt +// 0101 1000 MDDD DDDD TMS2_tblr +// 0101 1001 MDDD DDDD TMS2_tblw +// 0101 1010 MDDD DDDD TMS2_sqrs +// 0101 1011 MDDD DDDD TMS2_lts +// 0101 1100 MDDD DDDD +1 TMS2_macd +// 0101 1101 MDDD DDDD +1 TMS2_mac +// 0101 1110 1DDD DDDD +1 TMS2_bc +// 0101 1111 1DDD DDDD +1 TMS2_bnc + case 5: + { + static const ushort codes[16] = + { + TMS2_lst, TMS2_lst1, TMS2_ldp, TMS2_lph, + TMS2_pshd, TMS2_mar, TMS2_dmov, TMS2_bitt, + TMS2_tblr, TMS2_tblw, TMS2_sqrs, TMS2_lts, + TMS2_macd, TMS2_mac, TMS2_bc, TMS2_bnc + }; + insn.itype = codes[subcode]; + if ( subcode >= 12 ) + { + op_paddr(insn, insn.Op1); + if ( subcode >= 14 ) + { + if ( !op_indir(insn.Op2) ) + return 0; + } + else + { + if ( !op_iaa(insn, insn.Op2) ) + return 0; + } + } + else + { + if ( subcode == 5 ) + { + if ( (code & 0x80) == 0 ) + { + insn.itype = TMS2_nop; + insn.Op1.type = o_void; + break; + } + else if ( (code & 0xF8) == 0x88 ) + { + insn.itype = TMS2_larp; + insn.Op1.type = o_reg; + insn.Op1.reg = rAr0 + (code & 7); + break; + } + } + if ( !op_iaa(insn, insn.Op1) ) + return 0; + } + } + break; + +// 0110 0XXX MDDD DDDD TMS2_sacl +// 0110 1XXX MDDD DDDD TMS2_sach + case 6: + insn.itype = (subcode & 8) ? TMS2_sach : TMS2_sacl; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_shift(insn.Op2, subcode & 7); + break; + +// 0111 0RRR MDDD DDDD TMS2_sar +// 0111 1000 MDDD DDDD TMS2_sst +// 0111 1001 MDDD DDDD TMS2_sst1 +// 0111 1010 MDDD DDDD TMS2_popd +// 0111 1011 MDDD DDDD TMS2_zalr +// 0111 1100 MDDD DDDD TMS2_spl +// 0111 1101 MDDD DDDD TMS2_sph +// 0111 1110 KKKK KKKK TMS2_adrk +// 0111 1111 KKKK KKKK TMS2_sbrk + case 7: + if ( subcode < 8 ) + { + insn.itype = TMS2_sar; + op_ar(insn.Op1, subcode); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + } + else + { + static const ushort codes[8] = + { + TMS2_sst, TMS2_sst1, TMS2_popd, TMS2_zalr, + TMS2_spl, TMS2_sph, TMS2_adrk, TMS2_sbrk + }; + insn.itype = codes[subcode-8]; + if ( subcode >= 14 ) + op_short(insn.Op1); + else if ( !op_iaa(insn, insn.Op1) ) + return 0; + } + break; + +// 1000 AAAA MDDD DDDD TMS2_in + case 8: + insn.itype = TMS2_in; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + insn.Op2.value = subcode; + insn.Op2.type = o_imm; + insn.Op2.sib = 1; + break; + +// 1001 BBBB MDDD DDDD TMS2_bit + case 9: + insn.itype = TMS2_bit; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + insn.Op2.value = subcode; + insn.Op2.type = o_imm; + insn.Op2.sib = 0; + break; + +// 101K KKKK KKKK KKKK TMS2_mpyk + case 0xA: + case 0xB: + insn.itype = TMS2_mpyk; + insn.Op1.value = code & 0x1FFF; + if ( (insn.Op1.value & 0x1000) != 0 ) + insn.Op1.value |= ~0x1FFF; // extend sign + insn.Op1.type = o_imm; + insn.Op1.sib = 0; + break; + +// 1100 0RRR KKKK KKKK TMS2_lark +// 1100 100K KKKK KKKK TMS2_ldpk +// 1100 1010 0000 0000 TMS2_zac +// 1100 1010 KKKK KKKK TMS2_lack +// 1100 1011 KKKK KKKK TMS2_rptk +// 1100 1100 KKKK KKKK TMS2_addk +// 1100 1101 KKKK KKKK TMS2_subk +// 1100 1110 0000 0000 TMS2_eint +// 1100 1110 0000 0001 TMS2_dint +// 1100 1110 0000 0010 TMS2_rovm +// 1100 1110 0000 0011 TMS2_sovm +// 1100 1110 0000 0100 TMS2_cnfd +// 1100 1110 0000 0101 TMS2_cnfp +// 1100 1110 0000 0110 TMS2_rsxm +// 1100 1110 0000 0111 TMS2_ssxm +// 1100 1110 0000 10KK TMS2_spm +// 1100 1110 0000 1100 TMS2_rxf +// 1100 1110 0000 1101 TMS2_sxf +// 1100 1110 0000 111K TMS2_fort +// 1100 1110 0001 0100 TMS2_pac +// 1100 1110 0001 0101 TMS2_apac +// 1100 1110 0001 0110 TMS2_spac +// 1100 1110 0001 1000 TMS2_sfl +// 1100 1110 0001 1001 TMS2_sfr +// 1100 1110 0001 1011 TMS2_abs +// 1100 1110 0001 1100 TMS2_push +// 1100 1110 0001 1101 TMS2_pop +// 1100 1110 0001 1110 TMS2_trap +// 1100 1110 0001 1111 TMS2_idle +// 1100 1110 0010 0000 TMS2_rtxm +// 1100 1110 0010 0001 TMS2_stxm +// 1100 1110 0010 0011 TMS2_neg +// 1100 1110 0010 0100 TMS2_cala +// 1100 1110 0010 0101 TMS2_bacc +// 1100 1110 0010 0110 TMS2_ret +// 1100 1110 0010 0111 TMS2_cmpl +// 1100 1110 0011 0000 TMS2_rc +// 1100 1110 0011 0001 TMS2_sc +// 1100 1110 0011 0010 TMS2_rtc +// 1100 1110 0011 0011 TMS2_stc +// 1100 1110 0011 0100 TMS2_rol +// 1100 1110 0011 0101 TMS2_ror +// 1100 1110 0011 0110 TMS2_rfsm +// 1100 1110 0011 0111 TMS2_sfsm +// 1100 1110 0011 1000 TMS2_rhm +// 1100 1110 0011 1001 TMS2_shm +// 1100 1110 0011 11KK TMS2_conf +// 1100 1110 0101 00KK TMS2_cmpr +// 1100 1110 1AAA 0010 TMS2_norm +// 1100 1111 MDDD DDDD TMS2_mpyu + case 0xC: + switch ( subcode ) + { + default: // 1100 0RRR KKKK KKKK TMS2_lark + insn.itype = TMS2_lark; + op_ar(insn.Op1, subcode); + op_short(insn.Op2); + break; + case 8: + case 9: // 1100 100K KKKK KKKK TMS2_ldpk + insn.itype = TMS2_ldpk; + insn.Op1.dtype = dt_word; + insn.Op1.value = code & 0x1FF; + insn.Op1.type = o_imm; + insn.Op1.sib = 0; + break; + case 0xA: + if ( code == 0xCA00 ) + { + insn.itype = TMS2_zac; + break; + } + insn.itype = TMS2_lack; + goto LOAD_SHORT; + case 0xB: + insn.itype = TMS2_rptk; + op_short(insn.Op1); + insn.Op1.sib = 1; + break; + case 0xC: + insn.itype = TMS2_addk; + goto LOAD_SHORT; + case 0xD: + insn.itype = TMS2_subk; +LOAD_SHORT: + op_short(insn.Op1); + break; + case 0xE: + switch ( (code>>4) & 0xF ) + { + // 0000 0000 TMS2_eint + // 0000 0001 TMS2_dint + // 0000 0010 TMS2_rovm + // 0000 0011 TMS2_sovm + // 0000 0100 TMS2_cnfd + // 0000 0101 TMS2_cnfp + // 0000 0110 TMS2_rsxm + // 0000 0111 TMS2_ssxm + // 0000 10KK TMS2_spm + // 0000 1100 TMS2_rxf + // 0000 1101 TMS2_sxf + // 0000 111K TMS2_fort + case 0: + { + static const ushort codes[] = + { + TMS2_eint, TMS2_dint, TMS2_rovm, TMS2_sovm, + TMS2_cnfd, TMS2_cnfp, TMS2_rsxm, TMS2_ssxm, + TMS2_spm, TMS2_spm, TMS2_spm, TMS2_spm, + TMS2_rxf, TMS2_sxf, TMS2_fort, TMS2_fort + }; + insn.itype = codes[code & 0xF]; + if ( insn.itype == TMS2_spm ) + { + insn.Op1.value = code & 3; + insn.Op1.type = o_imm; + insn.Op1.sib = 0; + } + else if ( insn.itype == TMS2_fort ) + { + insn.Op1.value = code & 1; + insn.Op1.type = o_imm; + insn.Op1.sib = 0; + } + } + break; + + // 0001 0100 TMS2_pac + // 0001 0101 TMS2_apac + // 0001 0110 TMS2_spac + // 0001 1000 TMS2_sfl + // 0001 1001 TMS2_sfr + // 0001 1011 TMS2_abs + // 0001 1100 TMS2_push + // 0001 1101 TMS2_pop + // 0001 1110 TMS2_trap + // 0001 1111 TMS2_idle + case 1: + { + static const ushort codes[] = + { + TMS_null, TMS_null, TMS_null, TMS_null, + TMS2_pac, TMS2_apac, TMS2_spac, TMS_null, + TMS2_sfl, TMS2_sfr, TMS_null, TMS2_abs, + TMS2_push, TMS2_pop, TMS2_trap, TMS2_idle + }; + insn.itype = codes[code & 0xF]; + } + break; + + // 0010 0000 TMS2_rtxm + // 0010 0001 TMS2_stxm + // 0010 0011 TMS2_neg + // 0010 0100 TMS2_cala + // 0010 0101 TMS2_bacc + // 0010 0110 TMS2_ret + // 0010 0111 TMS2_cmpl + case 2: + if ( (code & 0xF) < 8 ) + { + static const ushort codes[] = + { + TMS2_rtxm, TMS2_stxm, TMS_null, TMS2_neg, + TMS2_cala, TMS2_bacc, TMS2_ret, TMS2_cmpl + }; + insn.itype = codes[code & 0xF]; + } + break; + + // 0011 0000 TMS2_rc + // 0011 0001 TMS2_sc + // 0011 0010 TMS2_rtc + // 0011 0011 TMS2_stc + // 0011 0100 TMS2_rol + // 0011 0101 TMS2_ror + // 0011 0110 TMS2_rfsm + // 0011 0111 TMS2_sfsm + // 0011 1000 TMS2_rhm + // 0011 1001 TMS2_shm + // 0011 11KK TMS2_conf + case 3: + if ( (code & 0xF) >= 0xC ) + { + insn.itype = TMS2_conf; + insn.Op1.value = code & 3; + insn.Op1.type = o_imm; + insn.Op1.sib = 0; + } + else + { + static const ushort codes[] = + { + TMS2_rc, TMS2_sc, TMS2_rtc, TMS2_stc, + TMS2_rol, TMS2_ror, TMS2_rfsm, TMS2_sfsm, + TMS2_rhm, TMS2_shm, TMS_null, TMS_null, + }; + insn.itype = codes[code & 0xF]; + } + break; + + // 0101 00KK TMS2_cmpr + case 5: + if ( (code & 0xC) == 0 ) + { + insn.itype = TMS2_cmpr; + insn.Op1.value = code & 3; + insn.Op1.type = o_imm; + insn.Op1.sib = 0; + } + break; + + // 1AAA 0010 TMS2_norm + case 0x8: + case 0x9: + case 0xA: + case 0xB: + case 0xC: + case 0xD: + case 0xE: + case 0xF: + insn.itype = TMS2_norm; + op_indir(insn.Op1); + break; + + default: + return 0; + } + break; + case 0xF: // 1100 1111 MDDD DDDD TMS2_mpyu + insn.itype = TMS2_mpyu; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + break; + } + break; + +// 1101 0RRR 0000 0000 +1 TMS2_lrlk +// 1101 SSSS 0000 0001 +1 TMS2_lalk +// 1101 SSSS 0000 0010 +1 TMS2_adlk +// 1101 SSSS 0000 0011 +1 TMS2_sblk +// 1101 SSSS 0000 0100 +1 TMS2_andk +// 1101 SSSS 0000 0101 +1 TMS2_ork +// 1101 SSSS 0000 0110 +1 TMS2_xork + case 0xD: + { + uint opcode = code & 0xFF; + if ( opcode == 0 ) + { + if ( subcode >= 8 ) + return 0; + insn.itype = TMS2_lrlk; + op_ar(insn.Op1, subcode); + op_imm(insn, insn.Op2); + } + else if ( opcode < 7 ) + { + static const ushort codes[] = + { + 0, TMS2_lalk, TMS2_adlk, TMS2_sblk, + TMS2_andk, TMS2_ork, TMS2_xork, + }; + insn.itype = codes[opcode]; + op_imm(insn, insn.Op1); + op_shift(insn.Op2, subcode); + } + else + { + return 0; + } + } + break; + +// 1110 AAAA MDDD DDDD TMS2_out + case 0xE: + insn.itype = TMS2_out; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + insn.Op2.value = subcode; + insn.Op2.type = o_imm; + insn.Op2.sib = 1; + break; + + // 1111 0000 1DDD DDDD +1 TMS2_bv + // 1111 0001 1DDD DDDD +1 TMS2_bgz + // 1111 0010 1DDD DDDD +1 TMS2_blez + // 1111 0011 1DDD DDDD +1 TMS2_blz + // 1111 0100 1DDD DDDD +1 TMS2_bgez + // 1111 0101 1DDD DDDD +1 TMS2_bnz + // 1111 0110 1DDD DDDD +1 TMS2_bz + // 1111 0111 1DDD DDDD +1 TMS2_bnv + // 1111 1000 1DDD DDDD +1 TMS2_bbz + // 1111 1001 1DDD DDDD +1 TMS2_bbnz + // 1111 1010 1DDD DDDD +1 TMS2_bioz + // 1111 1011 1DDD DDDD +1 TMS2_banz + // 1111 1100 MDDD DDDD +1 TMS2_blkp + // 1111 1101 MDDD DDDD +1 TMS2_blkd + // 1111 1110 1DDD DDDD +1 TMS2_call + // 1111 1111 1DDD DDDD +1 TMS2_b + case 0xF: + { + static const ushort codes[16] = + { + TMS2_bv, TMS2_bgz, TMS2_blez, TMS2_blz, + TMS2_bgez, TMS2_bnz, TMS2_bz, TMS2_bnv, + TMS2_bbz, TMS2_bbnz, TMS2_bioz, TMS2_banz, + TMS2_blkp, TMS2_blkd, TMS2_call, TMS2_b + }; + insn.itype = codes[subcode]; + op_paddr(insn, insn.Op1); + switch ( insn.itype ) + { + case TMS2_blkd: + insn.Op1.type = o_mem; + insn.Op1.sib = 1; + // fallthrough + case TMS2_blkp: + if ( !op_iaa(insn, insn.Op2) ) + return 0; + break; + default: + if ( !op_indir(insn.Op2) ) + return 0; + break; + } + } + break; + } + return 1; +} + +//---------------------------------------------------------------------- +//---------------------------------------------------------------------- +int tms320c5_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + code = get_next_byte(insn); + uchar subcode = (code >> 8) & 0xF; + uint nibble; + + if ( isC2() ) + { + if ( !ana_c2(insn) ) + return 0; + } + else + { + switch ( code >> 12 ) + { + case 0: + if ( subcode < 8 ) + { + insn.itype = TMS_lar; + op_ar(insn.Op1, subcode); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + } + else + { + { + static const uchar codes[8] = + { + TMS_lamm, TMS_smmr, TMS_subc, TMS_rpt, + TMS_out, TMS_ldp, TMS_lst, TMS_lst + }; + insn.itype = codes[subcode-8]; + } + if ( subcode == 0xC ) + op_ioaddr(insn, insn.Op2); + case08_common: + { + int ok = (subcode == 0x8 || subcode == 0x9) + ? op_maa(insn, insn.Op1) + : op_iaa(insn, insn.Op1); + if ( !ok ) + return 0; + } + if ( subcode == 0x9 ) + op_daddr(insn, insn.Op2); + if ( subcode >= 0xE ) + { + if ( insn.itype == TMS_sst ) + op_maa(insn, insn.Op1); + insn.Op2 = insn.Op1; + insn.Op2.n = 1; + insn.Op1.type = o_imm; + insn.Op1.value = subcode & 1; + insn.Op1.sib = 0; + } + } + break; + case 8: + if ( subcode < 8 ) + { + insn.itype = TMS_sar; + op_ar(insn.Op1, subcode); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + } + else + { + static const uchar codes[8] = + { + TMS_samm, TMS_lmmr, TMS_popd, TMS_mar, + TMS_spl, TMS_sph, TMS_sst, TMS_sst + }; + insn.itype = codes[subcode-8]; + if ( subcode == 0xB && (code & 0xFF) == 0 ) + { + insn.itype = TMS_nop; + insn.Op1.type = o_void; + break; + } + goto case08_common; + } + break; + case 1: + insn.itype = TMS_lacc; + goto iaa_shift; + case 2: + insn.itype = TMS_add; + goto iaa_shift; + case 3: + insn.itype = TMS_sub; + iaa_shift: + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_shift(insn.Op2, subcode); + break; + case 4: + insn.itype = TMS_bit; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_bit(insn.Op2); + break; + case 5: + { + static const uchar codes[16] = + { + TMS_mpya, TMS_mpys, TMS_sqra, TMS_sqrs, + TMS_mpy, TMS_mpyu, TMS_null, TMS_bldp, + TMS_xpl, TMS_opl, TMS_apl, TMS_cpl, + TMS_xpl2, TMS_opl2, TMS_apl2, TMS_cpl2 + }; + insn.itype = codes[subcode]; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_t *o; + if ( subcode >= 0xC ) + { + op_imm(insn, insn.Op1); + o = &insn.Op2; + } + else + { + o = &insn.Op1; + } + if ( !op_iaa(insn, *o) ) + return 0; + } + break; + case 6: + { + static const uchar codes[16] = + { + TMS_addc, TMS_add, TMS_adds, TMS_addt, + TMS_subb, TMS_sub, TMS_subs, TMS_subt, + TMS_zalr, TMS_lacl, TMS_lacc, TMS_lact, + TMS_xor, TMS_or, TMS_and, TMS_bitt + }; + insn.itype = codes[subcode]; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + if ( insn.itype == TMS_lacc + || insn.itype == TMS_add + || insn.itype == TMS_sub ) + { + op_shift(insn.Op2, 16); + } + } + break; + case 7: + { + static const uchar codes[16] = + { + TMS_lta, TMS_ltp, TMS_ltd, TMS_lt, + TMS_lts, TMS_lph, TMS_pshd, TMS_dmov, + TMS_adrk, TMS_b, TMS_call, TMS_banz, + TMS_sbrk, TMS_bd, TMS_calld, TMS_banzd + }; + insn.itype = codes[subcode]; + if ( subcode < 8 ) + { + if ( !op_iaa(insn, insn.Op1) ) + return 0; + } + else + { + if ( subcode != 8 && subcode != 0xC ) + { + op_paddr(insn, insn.Op1); + if ( !op_iaa(insn, insn.Op2) || insn.Op2.type != o_phrase ) + insn.itype = TMS_null; + } + else + { + op_short(insn.Op1); + } + } + } + break; + case 9: + insn.itype = (subcode & 8) ? TMS_sach : TMS_sacl; + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_shift(insn.Op2, subcode&7); + break; + case 0xA: + { + static const uchar codes[16] = + { + TMS_norm, TMS_null, TMS_mac, TMS_macd, + TMS_blpd, TMS_blpd, TMS_tblr, TMS_tblw, + TMS_bldd, TMS_bldd, TMS_mads, TMS_madd, + TMS_bldd, TMS_bldd, TMS_splk, TMS_in + }; + insn.itype = codes[subcode]; + switch ( subcode ) + { + case 0: + if ( !op_iaa(insn, insn.Op1) ) + return 0; + if ( (code & 0x80) == 0 ) + insn.itype = TMS_null; + break; + case 4: // blpd bmar, ? + case 0xC: // bldd bmar, ? + insn.Op1.type = o_reg; + insn.Op1.reg = rBMAR; + if ( !op_iaa(insn, insn.Op2) ) + return 0; + break; + case 0xD: // bldd ?, bmar + if ( !op_iaa(insn, insn.Op1) ) + return 0; + insn.Op2.type = o_reg; + insn.Op2.reg = rBMAR; + break; + case 2: // mac + case 3: // macd + case 5: // blpd + op_paddr(insn, insn.Op1); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + break; + case 8: + op_daddr(insn, insn.Op1); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + break; + case 9: + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_daddr(insn, insn.Op2); + break; + case 0xE: + op_imm(insn, insn.Op1); + if ( !op_iaa(insn, insn.Op2) ) + return 0; + break; + case 0xF: + if ( !op_iaa(insn, insn.Op1) ) + return 0; + op_ioaddr(insn, insn.Op2); + break; + default: + if ( !op_iaa(insn, insn.Op1) ) + return 0; + break; + } + } + break; + + case 0xB: + switch ( subcode ) + { + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + insn.itype = TMS_lar; + op_ar(insn.Op1, subcode); + op_short(insn.Op2); + break; + case 8: case 9: case 0xA: case 0xB: + case 0xC: + { + static const uchar codes[] = + { + TMS_add, TMS_lacl, TMS_sub, TMS_rpt, TMS_ldp + }; + insn.itype = codes[subcode-8]; //lint !e676 possibly indexing before the beginning of an allocation + op_short(insn.Op1); + } + break; + case 0xD: + insn.itype = TMS_ldp; + op_short(insn.Op1); + insn.Op1.value |= 0x100; + break; + case 0xE: + nibble = (code & 0xF); + switch ( (code >> 4) & 0xF ) + { + case 0: case 1: case 2: case 3: + { + static const uchar codes[] = + { + TMS_abs, TMS_cmpl, TMS_neg, TMS_pac, + TMS_apac, TMS_spac, TMS_null, TMS_null, + TMS_null, TMS_sfl, TMS_sfr, TMS_null, + TMS_rol, TMS_ror, TMS_null, TMS_null, + + TMS_addb, TMS_adcb, TMS_andb, TMS_orb, + TMS_rolb, TMS_rorb, TMS_sflb, TMS_sfrb, + TMS_sbb, TMS_sbbb, TMS_xorb, TMS_crgt, + TMS_crlt, TMS_exar, TMS_sacb, TMS_lacb, + + TMS_bacc, TMS_baccd, TMS_idle, TMS_idle2, + TMS_null, TMS_null, TMS_null, TMS_null, + TMS_null, TMS_null, TMS_null, TMS_null, + TMS_null, TMS_null, TMS_null, TMS_null, + + TMS_cala, TMS_null, TMS_pop, TMS_null, + TMS_null, TMS_null, TMS_null, TMS_null, + TMS_reti, TMS_null, TMS_rete, TMS_null, + TMS_push, TMS_calad, TMS_null, TMS_null + }; + insn.itype = codes[code & 0x3F]; + } + break; + case 4: + insn.itype = (code & 1) ? TMS_setc : TMS_clrc; + op_cbit(insn.Op1, (code>>1)&7); + break; + case 5: + { + static const uchar codes[] = + { + TMS_null, TMS_trap, TMS_nmi, TMS_null, + TMS_null, TMS_null, TMS_null, TMS_null, + TMS_zpr, TMS_zap, TMS_sath, TMS_satl, + TMS_null, TMS_null, TMS_null, TMS_null + }; + insn.itype = codes[nibble]; + } + break; + case 6: + case 7: + insn.itype = TMS_intr; + insn.Op1.type = o_imm; + insn.Op1.value = (code & 0x1F); + insn.Op1.sib = 1; + break; + case 8: + if ( nibble < 4 ) + { + static const uchar codes[] = + { + TMS_mpy, TMS_and, TMS_or, TMS_xor + }; + insn.itype = codes[nibble]; + op_imm(insn, insn.Op1); + if ( nibble != 0 ) + op_shift(insn.Op2, 16); + } + break; + case 9: + if ( nibble == 0 ) + insn.itype = TMS_estop; + break; + case 0xC: + switch ( nibble ) + { + case 4: + insn.itype = TMS_rpt; + op_imm(insn, insn.Op1); + break; + case 5: + insn.itype = TMS_rptz; + op_imm(insn, insn.Op1); + break; + case 6: + insn.itype = TMS_rptb; + op_paddr(insn, insn.Op1); + break; + } + break; + } + break; + case 0xF: + nibble = (code & 0xF); + switch ( (code>>4) & 0xF ) + { + case 0: + if ( code & 8 ) + { + insn.itype = TMS_lar; + op_ar(insn.Op1, code & 7); + op_imm(insn, insn.Op2); + } + else + { + insn.itype = TMS_spm; + op_short(insn.Op1); + insn.Op1.sib = 1; + } + break; + case 4: + if ( (nibble & 0xC) == 4 ) + { + insn.itype = TMS_cmpr; + insn.Op1.type = o_imm; + insn.Op1.value = nibble & 3; + insn.Op1.sib = 1; + } + break; + case 0xE: + insn.itype = TMS_bsar; + op_shift(insn.Op1, nibble+1); + break; + case 8: + case 9: + case 0xA: + case 0xB: + case 0xC: + case 0xD: + { + static const uchar codes[] = + { + TMS_lacc, TMS_add, TMS_sub, TMS_and, TMS_or, TMS_xor + }; + insn.itype = codes[(code>>4) & 0x7]; + op_imm(insn, insn.Op1); + op_shift(insn.Op2, nibble); + } + break; + } + break; + } + break; + case 0xC: + case 0xD: + insn.itype = TMS_mpy; + insn.Op1.dtype = dt_word; + insn.Op1.type = o_imm; + insn.Op1.value = (code & 0x1FFF); + if ( (insn.Op1.value & 0x1000) != 0 ) + insn.Op1.value |= ~0x1FFF; // extend sign + insn.Op1.sib = 0; + break; + case 0xE: + case 0xF: + switch ( subcode>>2 ) + { + case 0: + insn.itype = (code & 0x1000) ? TMS_bcndd : TMS_bcnd; + op_paddr(insn, insn.Op1); + if ( !op_cond(insn.Op2) ) + return 0; + break; + case 1: + insn.itype = TMS_xc; + insn.Op1.type = o_imm; + insn.Op1.value = (code & 0x1000) ? 2 : 1; + insn.Op1.sib = 1; + if ( !op_cond(insn.Op2) ) + return 0; + break; + case 2: + insn.itype = (code & 0x1000) ? TMS_ccd : TMS_cc; + op_paddr(insn, insn.Op1); + if ( !op_cond(insn.Op2) ) + return 0; + break; + case 3: + if ( (code & 0xEFFF) == 0xEF00 ) + insn.itype = (code & 0x1000) ? TMS_retd : TMS_ret; + else + { + insn.itype = (code & 0x1000) ? TMS_retcd : TMS_retc; + if ( !op_cond(insn.Op1) ) + return 0; + } + break; + } + break; + } + } + if ( insn.itype == TMS_null ) + return 0; + return insn.size; +} diff --git a/idasdk75/module/tms320c5/emu.cpp b/idasdk76/module/tms320c5/emu.cpp similarity index 100% rename from idasdk75/module/tms320c5/emu.cpp rename to idasdk76/module/tms320c5/emu.cpp diff --git a/idasdk75/module/tms320c5/ins.cpp b/idasdk76/module/tms320c5/ins.cpp similarity index 100% rename from idasdk75/module/tms320c5/ins.cpp rename to idasdk76/module/tms320c5/ins.cpp diff --git a/idasdk76/module/tms320c5/ins.hpp b/idasdk76/module/tms320c5/ins.hpp new file mode 100644 index 0000000..2e29239 --- /dev/null +++ b/idasdk76/module/tms320c5/ins.hpp @@ -0,0 +1,298 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ +TMS_null = 0, // Unknown Operation +TMS_abs, // Absolute value of Acc +TMS_adcb, // Add ACCB to Acc With Carry +TMS_add, // Add to Acc +TMS_addb, // Add ACCB to Acc +TMS_addc, // Add to Acc With Carry +TMS_adds, // Add to Acc With Sign-Extension Suppressed +TMS_addt, // Add to Acc With Shift Specified by TREG1 +TMS_adrk, // Add to Aux Register With Short Immediate +TMS_and, // AND With Acc +TMS_andb, // AND ACCD With Acc +TMS_apac, // Add P Register to Acc +TMS_apl, // AND Data Memory Value With DBMR +TMS_apl2, // AND Data Memory Value With Long Constant +TMS_b, // Branch Unconditionally +TMS_bacc, // Branch to Location (Acc) +TMS_baccd, // Branch to Location (Acc) Delayed +TMS_banz, // Branch on Aux Register Not Zero +TMS_banzd, // Branch on Aux Register Not Zero Delayed +TMS_bcnd, // Branch Conditionally +TMS_bcndd, // Branch Conditionally Delayed +TMS_bd, // Branch Unconditionally Delayed +TMS_bit, // Test Bit +TMS_bitt, // Test Bit Specified by TREG2 +TMS_bldd, // Block Move From Data Memory to Data Memory +TMS_bldp, // Block Move From Data Memory to Program Memory +TMS_blpd, // Block Move From Program Memory to Data Memory +TMS_bsar, // Barrel Shift +TMS_cala, // Call Subroutine at (Acc) +TMS_calad, // Call Subroutine at (Acc) Delayed +TMS_call, // Call Unconditionally +TMS_calld, // Call Unconditionally Delayed +TMS_cc, // Call Conditionally +TMS_ccd, // Call Conditionally Delayed +TMS_clrc, // Clear Control Bit +TMS_cmpl, // Complement Acc +TMS_cmpr, // Compare Aux Register With ARCR +TMS_cpl, // Compare DBMR With Data Value +TMS_cpl2, // Compare Long Immediate With Data Value +TMS_crgt, // Test for Acc Greater Than ACCB +TMS_crlt, // Test for Acc Smaller Than ACCB +TMS_dmov, // Data Move in Data Memory +TMS_estop, // Emulator Stop +TMS_exar, // Exchange ACCB With Acc +TMS_idle, // Idle Until Interrupt +TMS_idle2, // Idle Until Interrupt - Low Power Mode +TMS_in, // Input Data From Port +TMS_intr, // Soft Interrupt +TMS_lacb, // Load Acc With ACCB +TMS_lacc, // Load Acc With Shift +TMS_lacl, // Load Low Acc and Clear High Acc +TMS_lact, // Load Acc With Shift Specified by TREG1 +TMS_lamm, // Load Acc With Memory-Mapped Register +TMS_lar, // Load Aux Register +TMS_ldp, // Load Data Memory Pointer +TMS_lmmr, // Load Memory-Mapped Register +TMS_lph, // Load Product High Register +TMS_lst, // Load Status Register +TMS_lt, // Load TREG0 +TMS_lta, // Load TREG0 and Accumulate Previous Product +TMS_ltd, // Load TREG0,Accumulate Previous Product and Move Data +TMS_ltp, // Load TREG0 and Store P -> Acc +TMS_lts, // Load TREG0 and Subtract Previous Product +TMS_mac, // Multiply and Accumulate +TMS_macd, // Multiply and Accumulate With Data Move +TMS_madd, // Multiply and Accumulate With Data Move and Dynamic Addressing +TMS_mads, // Multiply and Accumulate With Dynamic Addressing +TMS_mar, // Modify Aux Register +TMS_mpy, // Multiply +TMS_mpya, // Multiply and Accumulate Previous Product +TMS_mpys, // Multiply and Subtract Previous Product +TMS_mpyu, // Multiply Unsigned +TMS_neg, // Negate Acc +TMS_nmi, // Nonmaskable Interrupt +TMS_nop, // No Operation +TMS_norm, // Normalize Contents of Acc +TMS_opl, // OR With DBMS +TMS_opl2, // OR With Long Immediate +TMS_or, // OR With Acc +TMS_orb, // OR ACCB With Accumulator +TMS_out, // Out Data to Port +TMS_pac, // Load Acc <- P +TMS_pop, // Pop Top of Stack to Low Acc +TMS_popd, // Pop Top of Stack to Data Memory +TMS_pshd, // Push Data Memory Value Onto Stack +TMS_push, // Push Low Acc Onto Stack +TMS_ret, // Return From Subroutine +TMS_retc, // Return Conditionally +TMS_retcd, // Return Conditionally Delayed +TMS_retd, // Return From Subroutine Delayed +TMS_rete, // Enable Interrupts and Return From Interrupt +TMS_reti, // Return From Interrupt +TMS_rol, // Rotate Acc Left +TMS_rolb, // Rotate ACCB and Acc Left +TMS_ror, // Rotate Acc Right +TMS_rorb, // Rotate ACCB and Acc Right +TMS_rpt, // Repeat Next Instruction +TMS_rptb, // Repeat Block +TMS_rptz, // Repeat Preceded by Clearing Acc and P +TMS_sacb, // Store Acc in ACCB +TMS_sach, // Store High Acc With Shift +TMS_sacl, // Store Low Acc With Shift +TMS_samm, // Store Acc in Memory-Mapped Register +TMS_sar, // Store Aux Register +TMS_sath, // Barrel Shift Acc as Specified by TREG1(4) +TMS_satl, // Barrel Shift Acc as Specified by TREG1(3-0) +TMS_sbb, // Subtract ACCB From Acc +TMS_sbbb, // Subtract ACCB From Acc With Borrow +TMS_sbrk, // Subtract From Aux Register Short Immediate +TMS_setc, // Set Control Bit +TMS_sfl, // Shift Acc Left +TMS_sflb, // Shift ACCB and Acc Left +TMS_sfr, // Shift Acc Right +TMS_sfrb, // Shift ACCB and Acc Right +TMS_smmr, // Store Memory-Mapped Register +TMS_spac, // Subtract P From Acc +TMS_sph, // Store High P Register +TMS_spl, // Store Low P Register +TMS_splk, // Store Parallel Long Immediate +TMS_spm, // Store ACCB and Acc Right +TMS_sqra, // Square and Accumulate Previous Product +TMS_sqrs, // Square and Subtract Previous Product +TMS_sst, // Store Status Register +TMS_sub, // Subtract From Acc +TMS_subb, // Subtract From Acc With Borrow +TMS_subc, // Conditional Subtract +TMS_subs, // Subtract From Acc With Sign-Extension Suppressed +TMS_subt, // Subtract From Acc With Shift Specified by TREG1 +TMS_tblr, // Table Read +TMS_tblw, // Table Write +TMS_trap, // Software Interrupt +TMS_xc, // Execute Conditionally +TMS_xor, // Exclusive-OR With Acc +TMS_xorb, // Exclusive-OR of ACCB With Acc +TMS_xpl, // Exclusive-OR Data Memory Value +TMS_xpl2, // Exclusive-OR Data Memory Value +TMS_zalr, // Zero Low Acc Load High Acc With Rounding +TMS_zap, // Zero Acc and P +TMS_zpr, // Zero P Register + +// +// TMS320C2x instructions +// + +TMS2_abs, // Absolute value of accumulator +TMS2_add, // Add to accumulator with shift +TMS2_addc, // Add to accumulator with carry +TMS2_addh, // Add to high accumulator +TMS2_addk, // Add to accumulator short immediate +TMS2_adds, // Add to low accumulator with sign extension suppressed +TMS2_addt, // Add to accumulator with shift specified by T register +TMS2_adlk, // Add to accumulator long immediate with shift +TMS2_adrk, // Add to auxiliary register short immediate +TMS2_and, // And with accumulator +TMS2_andk, // And immediate with accumulator with shift +TMS2_apac, // App P register to accumulator +TMS2_b, // Branch unconditionally +TMS2_bacc, // Branch to address specified by accumulator +TMS2_banz, // Bnrach on auxiliary register not zero +TMS2_bbnz, // Branch if tc bit != 0 +TMS2_bbz, // Branch if tc bit = 0 +TMS2_bc, // Branch on carry +TMS2_bgez, // Branch if accumulator >= 0 +TMS2_bgz, // Branch if accumulator > 0 +TMS2_bioz, // Branch on i/o status = 0 +TMS2_bit, // Test bit +TMS2_bitt, // Test bit specifed by T register +TMS2_blez, // Branch if accumulator <= 0 +TMS2_blkd, // Block move from data memory to data memory +TMS2_blkp, // Block move from program memory to data memory +TMS2_blz, // Branch if accumulator < 0 +TMS2_bnc, // Branch on no carry +TMS2_bnv, // Branch if no overflow +TMS2_bnz, // Branch if accumulator != 0 +TMS2_bv, // Branch on overflow +TMS2_bz, // Branch if accumulator = 0 +TMS2_cala, // Call subroutine indirect +TMS2_call, // Call subroutine +TMS2_cmpl, // Complement accumulator +TMS2_cmpr, // Compare auxiliary register with auxiliary register ar0 +TMS2_cnfd, // Configure block as data memory +TMS2_cnfp, // Configure block as program memory +TMS2_conf, // Configure block as data/program memory +TMS2_dint, // Disable interrupt +TMS2_dmov, // Data move in data memory +TMS2_eint, // Enable interrupt +TMS2_fort, // Format serial port registers +TMS2_idle, // Idle until interrupt +TMS2_in, // Input data from port +TMS2_lac, // Load accumulator with shift +TMS2_lack, // Load accumulator short immediate +TMS2_lact, // Load accumulator with shift specified by T register +TMS2_lalk, // Load accumulator long immediate with shift +TMS2_lar, // Load auxiliary register +TMS2_lark, // Load auxiliary register short immediate +TMS2_larp, // Load auxiliary register pointer +TMS2_ldp, // Load data memory page pointer +TMS2_ldpk, // Load data memory page pointer immediate +TMS2_lph, // Load high P register +TMS2_lrlk, // Load auxiliary register long immediate +TMS2_lst, // Load status register ST0 +TMS2_lst1, // Load status register ST1 +TMS2_lt, // Load T register +TMS2_lta, // Load T register and accumulate previous product +TMS2_ltd, // Load T register, accumulate previous product and move data +TMS2_ltp, // Load T register and store P register in accumulator +TMS2_lts, // Load T register and subtract previous product +TMS2_mac, // Multiply and accumulate +TMS2_macd, // Multiply and accumulate with data move +TMS2_mar, // Modify auxiliary register +TMS2_mpy, // Multiply (with T register, store product in P register) +TMS2_mpya, // Multiply and accumulate previous product +TMS2_mpyk, // Multiply immediate +TMS2_mpys, // Multiply and subtract previous product +TMS2_mpyu, // Multiply unsigned +TMS2_neg, // Negate accumulator +TMS2_nop, // No operation +TMS2_norm, // Normalize contents of accumulator +TMS2_or, // Or with accumulator +TMS2_ork, // Or immediate with accumulator with shift +TMS2_out, // Output data to port +TMS2_pac, // Load accumulator with P register +TMS2_pop, // Pop top of stack to low accumulator +TMS2_popd, // Pop top of stack to data memory +TMS2_pshd, // Push data memory value onto stack +TMS2_push, // Push low accumulator onto stack +TMS2_rc, // Reset carry bit +TMS2_ret, // Return from subroutine +TMS2_rfsm, // Reset serial port frame synchronization mode +TMS2_rhm, // Reset hold mode +TMS2_rol, // Rotate accumulator left +TMS2_ror, // Rotate acuumulator right +TMS2_rovm, // Reset overflow mode +TMS2_rpt, // Repeat instruction as specified by data memory value +TMS2_rptk, // Repeat instruction as specified by immediate value +TMS2_rsxm, // Reset sign extension mode +TMS2_rtc, // Reset test/control flag +TMS2_rtxm, // Reset serial port transmit mode +TMS2_rxf, // Reset external flag +TMS2_sach, // Store high accumulator with shift +TMS2_sacl, // Store low accumulator with shift +TMS2_sar, // Store auxiliary register +TMS2_sblk, // Subtract from accumulator long immediate with shift +TMS2_sbrk, // Subtract from auxiliary register short immediate +TMS2_sc, // Set carry bit +TMS2_sfl, // Shift accumulator left +TMS2_sfr, // Shift accumulator right +TMS2_sfsm, // Set serial port frame synchronization mode +TMS2_shm, // Set hold mode +TMS2_sovm, // Set overflow mode +TMS2_spac, // Subtract P register from accumulator +TMS2_sph, // Store high P register +TMS2_spl, // Store low P register +TMS2_spm, // Set P register output shift mode +TMS2_sqra, // Square and accumulate +TMS2_sqrs, // Square and subtract previous product +TMS2_sst, // Store status register ST0 +TMS2_sst1, // Store status register ST1 +TMS2_ssxm, // Set sign extension mode +TMS2_stc, // Set test/control flag +TMS2_stxm, // Set serial port transmit mode +TMS2_sub, // Subtract from accumulator with shift +TMS2_subb, // Subtract from accumulator with borrow +TMS2_subc, // Conditional subtract +TMS2_subh, // Subtract from high accumulator +TMS2_subk, // Subtract from accumulator shoft immediate +TMS2_subs, // Subtract from low accumulator with sign extension suppressed +TMS2_subt, // Subtract from accumulator with shift specified by T register +TMS2_sxf, // Set external flag +TMS2_tblr, // Table read +TMS2_tblw, // Table write +TMS2_trap, // Software interrupt +TMS2_xor, // Exclusive or with accumulator +TMS2_xork, // Exclusive or immediate with accumulator with shift +TMS2_zac, // Zero accumulator +TMS2_zalh, // Zero low accumulator and load high accumulator +TMS2_zalr, // Zero low accumulator and load high accumulator with rounding +TMS2_zals, // Zero low accumulator and load high accumulator with sign extension suppressed + +TMS_last, + + }; + +#endif diff --git a/idasdk76/module/tms320c5/makefile b/idasdk76/module/tms320c5/makefile new file mode 100644 index 0000000..bea15c4 --- /dev/null +++ b/idasdk76/module/tms320c5/makefile @@ -0,0 +1,46 @@ +PROC=tms320c5 + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ana.cpp ins.hpp tms.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + emu.cpp ins.hpp tms.hpp +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp out.cpp tms.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp reg.cpp tms.hpp diff --git a/idasdk75/module/tms320c5/out.cpp b/idasdk76/module/tms320c5/out.cpp similarity index 100% rename from idasdk75/module/tms320c5/out.cpp rename to idasdk76/module/tms320c5/out.cpp diff --git a/idasdk75/module/tms320c5/reg.cpp b/idasdk76/module/tms320c5/reg.cpp similarity index 100% rename from idasdk75/module/tms320c5/reg.cpp rename to idasdk76/module/tms320c5/reg.cpp diff --git a/idasdk75/module/tms320c5/tms.hpp b/idasdk76/module/tms320c5/tms.hpp similarity index 100% rename from idasdk75/module/tms320c5/tms.hpp rename to idasdk76/module/tms320c5/tms.hpp diff --git a/idasdk75/module/tms320c54/ana.cpp b/idasdk76/module/tms320c54/ana.cpp similarity index 100% rename from idasdk75/module/tms320c54/ana.cpp rename to idasdk76/module/tms320c54/ana.cpp diff --git a/idasdk75/module/tms320c54/emu.cpp b/idasdk76/module/tms320c54/emu.cpp similarity index 100% rename from idasdk75/module/tms320c54/emu.cpp rename to idasdk76/module/tms320c54/emu.cpp diff --git a/idasdk76/module/tms320c54/ins.cpp b/idasdk76/module/tms320c54/ins.cpp new file mode 100644 index 0000000..ccb3c4d --- /dev/null +++ b/idasdk76/module/tms320c54/ins.cpp @@ -0,0 +1,307 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "tms320c54.hpp" + +const instruc_t Instructions[] = +{ + + { "", 0 }, // Unknown Operation + + // ARITHMETIC OPERATIONS + + // ADD INSTRUCTIONS + + { "add", CF_CHG1 }, // Add to Accumulator + { "add", CF_USE1|CF_CHG2 }, // Add to Accumulator + { "add", CF_USE1|CF_USE2|CF_CHG3 }, // Add to Accumulator + { "addc", CF_USE1|CF_CHG2 }, // Add to Accumulator With Carry + { "addm", CF_USE1|CF_CHG2 }, // Add Long-Immediate Value to Memory + { "adds", CF_USE1|CF_CHG2 }, // Add to Accumulator With Sign-Extension Suppressed + + // SUBTRACT INSTRUCTIONS + + { "sub", CF_CHG1 }, // Sub From Accumulator + { "sub", CF_USE1|CF_CHG2 }, // Sub From Accumulator + { "sub", CF_USE1|CF_USE2|CF_CHG3 }, // Sub From Accumulator + { "subb", CF_USE1|CF_CHG2 }, // Sub From Accumulator With Borrow + { "subc", CF_USE1|CF_CHG2 }, // Subtract Conditionally + { "subs", CF_USE1|CF_CHG2 }, // Subtract From Accumulator With Sign Extension Suppressed + + // MULTIPLY INSTRUCTIONS + + { "mpy", CF_USE1|CF_CHG2 }, // Multiply Without Rounding + { "mpy", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Without Rounding + { "mpyr", CF_USE1|CF_CHG2 }, // Multiply With Rounding + { "mpya", CF_CHG1 }, // Multiply by Accumulator A + { "mpyu", CF_USE1|CF_CHG2 }, // Multiply Unsigned + { "squr", CF_USE1|CF_CHG2 }, // Square + + // MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS + + { "mac", CF_USE1|CF_CHG2 }, // Multiply Accumulate Without Rounding + { "mac", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Accumulate Without Rounding + { "macr", CF_USE1|CF_CHG2 }, // Multiply Accumulate With Rounding + { "macr", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Accumulate With Rounding + { "maca", CF_CHG1 }, // Multiply by Accumulator A and Accumulate Without Rounding + { "maca", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Accumulate Without Rounding + { "maca", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Accumulate Without Rounding + { "macar", CF_CHG1 }, // Multiply by Accumulator A and Accumulate With Rounding + { "macar", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Accumulate With Rounding + { "macar", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Accumulate With Rounding + { "macd", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Program Memory and Accumulate With Delay + { "macp", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Program Memory and Accumulate + { "macsu", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply Signed by Unsigned and Accumulate + { "mas", CF_USE1|CF_CHG2 }, // Multiply and Subtract Without Rounding + { "mas", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply and Subtract Without Rounding + { "masr", CF_USE1|CF_CHG2 }, // Multiply and Subtract With Rounding + { "masr", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply and Subtract With Rounding + // TMS320C54_mas, + { "masa", CF_CHG1 }, // Multiply by Accumulator A and Subtract Without Rounding + { "masa", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Subtract Without Rounding + { "masa", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Subtract Without Rounding + { "masar", CF_CHG1 }, // Multiply by Accumulator A and Subtract With Rounding + { "masar", CF_USE1|CF_CHG2 }, // Multiply by Accumulator A and Subtract With Rounding + { "masar", CF_USE1|CF_USE2|CF_CHG3 }, // Multiply by Accumulator A and Subtract With Rounding + { "squra", CF_USE1|CF_CHG2 }, // Square and Accumulate + { "squrs", CF_USE1|CF_CHG2 }, // Square and Subtract + + // DOUBLE INSTRUCTIONS + + { "dadd", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Add to Accumulator + { "dadd", CF_USE1|CF_USE2|CF_CHG3 }, // Double-Precision/Dual 16-Bit Add to Accumulator + { "dadst", CF_USE1|CF_CHG2 }, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract + { "drsub", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Subtract From Long Word + { "dsadt", CF_USE1|CF_CHG2 }, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add + { "dsub", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Subtract From Accumulator + { "dsubt", CF_USE1|CF_CHG2 }, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract + + // APPLICATION-SPECIFIC INSTRUCTIONS + + { "abdst", CF_USE1|CF_USE2 }, // Absolute distance + { "abs", CF_CHG1 }, // Absolute Value of Accumulator + { "abs", CF_USE1|CF_CHG2 }, // Absolute Value of Accumulator + { "cmpl", CF_CHG1 }, // Complement Accumulator + { "cmpl", CF_USE1|CF_CHG2 }, // Complement Accumulator + { "delay", CF_USE1 }, // Memory Delay + { "exp", CF_USE1 }, // Accumulator Exponent + { "firs", CF_USE1|CF_USE2 }, // Symmetrical Finite Impulse Response Filter + { "lms", CF_USE1|CF_USE2 }, // Least Mean Square + { "max", CF_CHG1 }, // Accumulator Maximum + { "min", CF_CHG1 }, // Accumulator Minimum + { "neg", CF_CHG1 }, // Negate Accumulator + { "neg", CF_USE1|CF_CHG2 }, // Negate Accumulator + { "norm", CF_CHG1 }, // Normalization + { "norm", CF_USE1|CF_CHG2 }, // Normalization + { "poly", CF_USE1 }, // Polynominal Evaluation + { "rnd", CF_CHG1 }, // Round Accumulator + { "rnd", CF_USE1|CF_CHG2 }, // Round Accumulator + { "sat", CF_CHG1 }, // Saturate Accumulator + { "sqdst", CF_USE1|CF_USE2 }, // Square Distance + + // LOGICAL OPERATIONS + + // AND INSTRUCTIONS + { "and", CF_CHG1 }, // AND With Accumulator + { "and", CF_USE1|CF_CHG2 }, // AND With Accumulator + { "and", CF_USE1|CF_USE2|CF_CHG3 }, // AND With Accumulator + { "andm", CF_USE1|CF_CHG2 }, // AND Memory With Long Immediate + + // OR INSTRUCTIONS + + { "or", CF_CHG1 }, // OR With Accumulator + { "or", CF_USE1|CF_CHG2 }, // OR With Accumulator + { "or", CF_USE1|CF_USE2|CF_CHG3 }, // OR With Accumulator + { "orm", CF_USE1|CF_CHG2 }, // OR Memory With Constant + + // XOR INSTRUCTIONS + + { "xor", CF_CHG1 }, // Exclusive OR With Accumulator + { "xor", CF_USE1|CF_CHG2 }, // Exclusive OR With Accumulator + { "xor", CF_USE1|CF_USE2|CF_CHG3 }, // Exclusive OR With Accumulator + { "xorm", CF_USE1|CF_CHG2 }, // Exclusive OR Memory With Constant + + // SHIFT INSTRUCTIONS + + { "rol", CF_CHG1 }, // Rotate Accumulator + { "roltc", CF_CHG1 }, // Rotate Accumulator Left Using TC + { "ror", CF_CHG1 }, // Rotate Accumulator Right + { "sfta", CF_CHG1|CF_USE2 }, // Shift Accumulator Arithmetically + { "sfta", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Accumulator Arithmetically + { "sftc", CF_CHG1 }, // Shift Accumulator Conditionally + { "sftl", CF_CHG1|CF_USE2 }, // Shift Accumulator Logically + { "sftl", CF_USE1|CF_USE2|CF_CHG3 }, // Shift Accumulator Logically + + // TEST INSTRUCTIONS + + { "bit", CF_USE1|CF_USE2 }, // Test Bit + { "bitf", CF_USE1|CF_USE2 }, // Test Bit Field Specified by Immediate Value + { "bitt", CF_USE1 }, // Test Bit Specified by T + { "cmpm", CF_USE1|CF_USE2 }, // Compare Memory With Long Immediate + { "cmpr", CF_USE1|CF_USE2 }, // Compare Auxiliary Register with AR0 + + // PROGRAM CONTROL OPERATIONS + + // BRANCH INSTRUCTIONS + + { "b", CF_USE1|CF_STOP }, // Branch Unconditionally + { "bd", CF_USE1 }, // Branch Unconditionally + { "bacc", CF_USE1|CF_STOP }, // Branch to Location Specified by Accumulator + { "baccd", CF_USE1 }, // Branch to Location Specified by Accumulator + { "banz", CF_USE1|CF_USE2 }, // Branch on Auxiliary Register Not Zero + { "banzd", CF_USE1|CF_USE2 }, // Branch on Auxiliary Register Not Zero + { "bc", CF_USE1|CF_USE2 }, // Branch Conditionally + { "bc", CF_USE1|CF_USE2|CF_USE3 }, // Branch Conditionally + { "bcd", CF_USE1|CF_USE2 }, // Branch Conditionally + { "bcd", CF_USE1|CF_USE2|CF_USE3 }, // Branch Conditionally + { "fb", CF_USE1|CF_STOP }, // Far Branch Unconditionally + { "fbd", CF_USE1 }, // Far Branch Unconditionally + { "fbacc", CF_USE1 }, // Far Branch to Location Specified by Accumulator + { "fbaccd", CF_USE1 }, // Far Branch to Location Specified by Accumulator + + // CALL INSTRUCTIONS + + { "cala", CF_USE1|CF_CALL }, // Call Subroutine at Location Specified by Accumulator + { "calad", CF_USE1|CF_CALL }, // Call Subroutine at Location Specified by Accumulator + { "call", CF_USE1|CF_CALL }, // Call Unconditionally + { "calld", CF_USE1|CF_CALL }, // Call Unconditionally + { "cc", CF_USE1|CF_USE2|CF_CALL }, // Call Conditionally + { "cc", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Call Conditionally + { "ccd", CF_USE1|CF_USE2|CF_CALL }, // Call Conditionally + { "ccd", CF_USE1|CF_USE2|CF_USE3|CF_CALL }, // Call Conditionally + { "fcala", CF_USE1|CF_CALL }, // Far Call Subroutine at Location Specified by Accumulator + { "fcalad", CF_USE1|CF_CALL }, // Far Call Subroutine at Location Specified by Accumulator + { "fcall", CF_USE1|CF_CALL }, // Far Call Unconditionally + { "fcalld", CF_USE1|CF_CALL }, // Far Call Unconditionally + + // INTERRUPT INSTRUCTIONS + + { "intr", CF_USE1|CF_CALL }, // Software Interrupt + { "trap", CF_USE1|CF_CALL }, // Software Interrupt + + // RETURN INSTRUCTIONS + + { "fret", CF_STOP }, // Far Return + { "fretd", 0 }, // Far Return + { "frete", CF_STOP }, // Enable Interrupts and Far Return From Interrupt + { "freted", 0 }, // Enable Interrupts and Far Return From Interrupt + { "rc", CF_USE1 }, // Return Conditionally + { "rc", CF_USE1|CF_USE2 }, // Return Conditionally + { "rc", CF_USE1|CF_USE2|CF_USE3 }, // Return Conditionally + { "rcd", CF_USE1 }, // Return Conditionally + { "rcd", CF_USE1|CF_USE2 }, // Return Conditionally + { "rcd", CF_USE1|CF_USE2|CF_USE3 }, // Return Conditionally + { "ret", CF_STOP }, // Return + { "retd", 0 }, // Return + { "rete", CF_STOP }, // Enable Interrupts and Far Return From Interrupt + { "reted", 0 }, // Enable Interrupts and Far Return From Interrupt + { "retf", CF_STOP }, // Enable Interrupts and Fast Return From Interrupt + { "retfd", 0 }, // Enable Interrupts and Fast Return From Interrupt + + // REPEAT INSTRUCTIONS + + { "rpt", CF_USE1 }, // Repeat Next Instruction + { "rptb", CF_USE1 }, // Block Repeat + { "rptbd", CF_USE1 }, // Block Repeat + { "rptz", CF_CHG1|CF_USE2 }, // Repeat Next Instruction And Clear Accumulator + + // STACK MANIPULATING INSTRUCTIONS + + { "frame", CF_USE1 }, // Stack Pointer Immediate Offset + { "popd", CF_CHG1 }, // Pop Top of Stack to Data Memory + { "popm", CF_CHG1 }, // Pop Top of Stack to Memory-Mapped Register + { "pshd", CF_USE1 }, // Push Data-Memory Value Onto Stack + { "pshm", CF_USE1 }, // Push Memory-Mapped Register Onto Stack + + // MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS + + { "idle", CF_USE1 }, // Idle Until Interrupt + { "mar", CF_USE1 }, // Modify Auxiliary Register + { "nop", 0 }, // No Operation + { "reset", 0 }, // Software Reset + { "rsbx", CF_CHG1 }, // Reset Status Register Bit + { "rsbx", CF_USE1|CF_USE2 }, // Reset Status Register Bit + { "ssbx", CF_CHG1 }, // Set Status Register Bit + { "ssbx", CF_USE1|CF_USE2 }, // Set Status Register Bit + { "xc", CF_USE1|CF_USE2 }, // Execute Conditionally + { "xc", CF_USE1|CF_USE2|CF_USE3 }, // Execute Conditionally + + // LOAD AND STORE OPERATIONS + + // LOAD INSTRUCTIONS + + { "dld", CF_USE1|CF_CHG2 }, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator + { "ld", CF_CHG1 }, // Load Accumulator With Shift + { "ld", CF_USE1|CF_CHG2 }, // Load Accumulator With Shift + { "ld", CF_USE1|CF_USE2|CF_CHG3 }, // Load Accumulator With Shift + { "ldm", CF_USE1|CF_CHG2 }, // Load Memory-Mapped Register + { "ldr", CF_USE1|CF_CHG2 }, // Load Memory Value in Accumulator High With Rounding + { "ldu", CF_USE1|CF_CHG2 }, // Load Unsigned Memory Value + { "ltd", CF_USE1 }, // Load T and insert Delay + + // STORE INSTRUCTIONS + + { "dst", CF_USE1|CF_CHG2 }, // Store Accumulator in Long Word + { "st", CF_USE1|CF_CHG2 }, // Store T, TRN, or Immediate Value into Memory + { "sth", CF_USE1|CF_CHG2 }, // Store Accumulator High Into Memory + { "sth", CF_USE1|CF_USE2|CF_CHG3 }, // Store Accumulator High Into Memory + { "stl", CF_USE1|CF_CHG2 }, // Store Accumulator Low Into Memory + { "stl", CF_USE1|CF_USE2|CF_CHG3 }, // Store Accumulator Low Into Memory + { "stlm", CF_USE1|CF_CHG2 }, // Store Accumulator Low Into Memory-Mapped Register + { "stm", CF_USE1|CF_CHG2 }, // Store Immediate Value Into Memory-Mapped Register + + // CONDITIONAL STORE INSTRUCTIONS + + { "cmps", CF_USE1|CF_CHG2 }, // Compare, Select and Store Maximum + { "saccd", CF_USE1|CF_CHG2|CF_USE3 }, // Store Accumulator Conditionally + { "srccd", CF_CHG1|CF_USE2 }, // Store Block Repeat Counter Conditionally + { "strcd", CF_CHG1|CF_USE2 }, // Store T Conditionally + + // PARALLEL LOAD AND STORE INSTRUCTIONS + + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Load // TMS320C54_st_ld + + // PARALLEL LOAD AND MULTIPLY INSTRUCTIONS + + { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Accumulate Without Rounding // TMS320C54_ld_mac + { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Accumulate With Rounding // TMS320C54_ld_macr + { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Subtract Without Rounding // TMS320C54_ld_mas + { "ld", CF_USE1|CF_CHG2|CF_CHG3 }, // Load Accumulator With Parallel Multiply Subtract With Rounding // TMS320C54_ld_masr + + // PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS + + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Add // TMS320C54_st_add + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Subtract // TMS320C54_st_sub + + // PARALLEL STORE AND MULTIPLY INSTRUCTIONS + + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Accumulate Without Rounding // TMS320C54_st_mac + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Accumulate With Rounding // TMS320C54_st_macr + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Subtract Without Rounding // TMS320C54_st_mas + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply Subtract With Rounding // TMS320C54_st_masr + { "st", CF_USE1|CF_CHG2|CF_CHG3 }, // Store Accumulator With Parallel Multiply // TMS320C54_st_mpy + + // MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS + + { "mvdd", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With X,Y Addressing + { "mvdk", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With Destination Addressing + { "mvdm", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Memory-Mapped Register + { "mvdp", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Program Memory + { "mvkd", CF_USE1|CF_CHG2 }, // Move Data From Data Memory to Data Memory With Source Addressing + { "mvmd", CF_USE1|CF_CHG2 }, // Move Data From Memory-Mapped Register to Data Memory + { "mvmm", CF_USE1|CF_CHG2 }, // Move Data From Memory-Mapped Register to Memory-Mapped Register + { "mvpd", CF_USE1|CF_CHG2 }, // Move Data From Program Memory to Data Memory + { "portr", CF_USE1|CF_USE2 }, // Read Data From Port + { "portw", CF_USE1|CF_USE2 }, // Write Data to Port + { "reada", CF_CHG1 }, // Read Program Memory Addressed by Accumulator A and Store in Data Memory + { "writa", CF_USE1 }, // Write Data to Program Memory Addressed by Accumulator A + +}; + +CASSERT(qnumber(Instructions) == TMS320C54_last); diff --git a/idasdk76/module/tms320c54/ins.hpp b/idasdk76/module/tms320c54/ins.hpp new file mode 100644 index 0000000..dadf3b9 --- /dev/null +++ b/idasdk76/module/tms320c54/ins.hpp @@ -0,0 +1,311 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + +TMS320C54_null = 0, // Unknown Operation + +// ARITHMETIC OPERATIONS + +// ADD INSTRUCTIONS + +TMS320C54_add1, // Add to Accumulator +TMS320C54_add2, // Add to Accumulator +TMS320C54_add3, // Add to Accumulator +TMS320C54_addc, // Add to Accumulator With Carry +TMS320C54_addm, // Add Long-Immediate Value to Memory +TMS320C54_adds, // Add to Accumulator With Sign-Extension Suppressed + +// SUBTRACT INSTRUCTIONS + +TMS320C54_sub1, // Sub From Accumulator +TMS320C54_sub2, // Sub From Accumulator +TMS320C54_sub3, // Sub From Accumulator +TMS320C54_subb, // Sub From Accumulator With Borrow +TMS320C54_subc, // Subtract Conditionally +TMS320C54_subs, // Subtract From Accumulator With Sign Extension Suppressed + +// MULTIPLY INSTRUCTIONS + +TMS320C54_mpy2, // Multiply Without Rounding +TMS320C54_mpy3, // Multiply Without Rounding +TMS320C54_mpyr2, // Multiply With Rounding +TMS320C54_mpya, // Multiply by Accumulator A +TMS320C54_mpyu, // Multiply Unsigned +TMS320C54_squr, // Square + +// MULTIPLY-ACCUMULATE AND MULTIPLY-SUBTRACT INSTRUCTIONS + +TMS320C54_mac2, // Multiply Accumulate Without Rounding +TMS320C54_mac3, // Multiply Accumulate Without Rounding +TMS320C54_macr2, // Multiply Accumulate With Rounding +TMS320C54_macr3, // Multiply Accumulate With Rounding +TMS320C54_maca1, // Multiply by Accumulator A and Accumulate Without Rounding +TMS320C54_maca2, // Multiply by Accumulator A and Accumulate Without Rounding +TMS320C54_maca3, // Multiply by Accumulator A and Accumulate Without Rounding +TMS320C54_macar1, // Multiply by Accumulator A and Accumulate With Rounding +TMS320C54_macar2, // Multiply by Accumulator A and Accumulate With Rounding +TMS320C54_macar3, // Multiply by Accumulator A and Accumulate With Rounding +TMS320C54_macd, // Multiply by Program Memory and Accumulate With Delay +TMS320C54_macp, // Multiply by Program Memory and Accumulate +TMS320C54_macsu, // Multiply Signed by Unsigned and Accumulate +TMS320C54_mas2, // Multiply and Subtract Without Rounding +TMS320C54_mas3, // Multiply and Subtract Without Rounding +TMS320C54_masr2, // Multiply and Subtract With Rounding +TMS320C54_masr3, // Multiply and Subtract With Rounding +// TMS320C54_mas, +TMS320C54_masa1, // Multiply by Accumulator A and Subtract Without Rounding +TMS320C54_masa2, // Multiply by Accumulator A and Subtract Without Rounding +TMS320C54_masa3, // Multiply by Accumulator A and Subtract Without Rounding +TMS320C54_masar1, // Multiply by Accumulator A and Subtract With Rounding +TMS320C54_masar2, // Multiply by Accumulator A and Subtract With Rounding +TMS320C54_masar3, // Multiply by Accumulator A and Subtract With Rounding +TMS320C54_squra, // Square and Accumulate +TMS320C54_squrs, // Square and Subtract + +// DOUBLE INSTRUCTIONS + +TMS320C54_dadd2, // Double-Precision/Dual 16-Bit Add to Accumulator +TMS320C54_dadd3, // Double-Precision/Dual 16-Bit Add to Accumulator +TMS320C54_dadst, // Double-Precision Load With T Add/Dual 16-Bit Load With T Add/Subtract +TMS320C54_drsub, // Double-Precision/Dual 16-Bit Subtract From Long Word +TMS320C54_dsadt, // Long-Word Load With T Add/Dual 16-Bit Load With T Subtract/Add +TMS320C54_dsub, // Double-Precision/Dual 16-Bit Subtract From Accumulator +TMS320C54_dsubt, // Long-Word Load With T Subtract/Dual 16-Bit Load With T Subtract + +// APPLICATION-SPECIFIC INSTRUCTIONS + +TMS320C54_abdst, // Absolute distance +TMS320C54_abs1, // Absolute Value of Accumulator +TMS320C54_abs2, // Absolute Value of Accumulator +TMS320C54_cmpl1, // Complement Accumulator +TMS320C54_cmpl2, // Complement Accumulator +TMS320C54_delay, // Memory Delay +TMS320C54_exp, // Accumulator Exponent +TMS320C54_firs, // Symmetrical Finite Impulse Response Filter +TMS320C54_lms, // Least Mean Square +TMS320C54_max, // Accumulator Maximum +TMS320C54_min, // Accumulator Minimum +TMS320C54_neg1, // Negate Accumulator +TMS320C54_neg2, // Negate Accumulator +TMS320C54_norm1, // Normalization +TMS320C54_norm2, // Normalization +TMS320C54_poly, // Polynominal Evaluation +TMS320C54_rnd1, // Round Accumulator +TMS320C54_rnd2, // Round Accumulator +TMS320C54_sat, // Saturate Accumulator +TMS320C54_sqdst, // Square Distance + +// LOGICAL OPERATIONS + +// AND INSTRUCTIONS + +TMS320C54_and1, // AND With Accumulator +TMS320C54_and2, // AND With Accumulator +TMS320C54_and3, // AND With Accumulator +TMS320C54_andm, // AND Memory With Long Immediate + +// OR INSTRUCTIONS + +TMS320C54_or1, // OR With Accumulator +TMS320C54_or2, // OR With Accumulator +TMS320C54_or3, // OR With Accumulator +TMS320C54_orm, // OR Memory With Constant + +// XOR INSTRUCTIONS + +TMS320C54_xor1, // Exclusive OR With Accumulator +TMS320C54_xor2, // Exclusive OR With Accumulator +TMS320C54_xor3, // Exclusive OR With Accumulator +TMS320C54_xorm, // Exclusive OR Memory With Constant + +// SHIFT INSTRUCTIONS + +TMS320C54_rol, // Rotate Accumulator +TMS320C54_roltc, // Rotate Accumulator Left Using TC +TMS320C54_ror, // Rotate Accumulator Right +TMS320C54_sfta2, // Shift Accumulator Arithmetically +TMS320C54_sfta3, // Shift Accumulator Arithmetically +TMS320C54_sftc, // Shift Accumulator Conditionally +TMS320C54_sftl2, // Shift Accumulator Logically +TMS320C54_sftl3, // Shift Accumulator Logically + +// TEST INSTRUCTIONS + +TMS320C54_bit, // Test Bit +TMS320C54_bitf, // Test Bit Field Specified by Immediate Value +TMS320C54_bitt, // Test Bit Specified by T +TMS320C54_cmpm, // Compare Memory With Long Immediate +TMS320C54_cmpr, // Compare Auxiliary Register with AR0 + +// PROGRAM CONTROL OPERATIONS + +// BRANCH INSTRUCTIONS + +TMS320C54_b, // Branch Unconditionally +TMS320C54_bd, // Branch Unconditionally +TMS320C54_bacc, // Branch to Location Specified by Accumulator +TMS320C54_baccd, // Branch to Location Specified by Accumulator +TMS320C54_banz, // Branch on Auxiliary Register Not Zero +TMS320C54_banzd, // Branch on Auxiliary Register Not Zero +TMS320C54_bc2, // Branch Conditionally +TMS320C54_bc3, // Branch Conditionally +TMS320C54_bcd2, // Branch Conditionally +TMS320C54_bcd3, // Branch Conditionally +TMS320C54_fb, // Far Branch Unconditionally +TMS320C54_fbd, // Far Branch Unconditionally +TMS320C54_fbacc, // Far Branch to Location Specified by Accumulator +TMS320C54_fbaccd, // Far Branch to Location Specified by Accumulator + +// CALL INSTRUCTIONS + +TMS320C54_cala, // Call Subroutine at Location Specified by Accumulator +TMS320C54_calad, // Call Subroutine at Location Specified by Accumulator +TMS320C54_call, // Call Unconditionally +TMS320C54_calld, // Call Unconditionally +TMS320C54_cc2, // Call Conditionally +TMS320C54_cc3, // Call Conditionally +TMS320C54_ccd2, // Call Conditionally +TMS320C54_ccd3, // Call Conditionally +TMS320C54_fcala, // Far Call Subroutine at Location Specified by Accumulator +TMS320C54_fcalad, // Far Call Subroutine at Location Specified by Accumulator +TMS320C54_fcall, // Far Call Unconditionally +TMS320C54_fcalld, // Far Call Unconditionally + +// INTERRUPT INSTRUCTIONS + +TMS320C54_intr, // Software Interrupt +TMS320C54_trap, // Software Interrupt + +// RETURN INSTRUCTIONS + +TMS320C54_fret, // Far Return +TMS320C54_fretd, // Far Return +TMS320C54_frete, // Enable Interrupts and Far Return From Interrupt +TMS320C54_freted, // Enable Interrupts and Far Return From Interrupt +TMS320C54_rc1, // Return Conditionally +TMS320C54_rc2, // Return Conditionally +TMS320C54_rc3, // Return Conditionally +TMS320C54_rcd1, // Return Conditionally +TMS320C54_rcd2, // Return Conditionally +TMS320C54_rcd3, // Return Conditionally +TMS320C54_ret, // Return +TMS320C54_retd, // Return +TMS320C54_rete, // Enable Interrupts and Return From Interrupt +TMS320C54_reted, // Enable Interrupts and Return From Interrupt +TMS320C54_retf, // Enable Interrupts and Fast Return From Interrupt +TMS320C54_retfd, // Enable Interrupts and Fast Return From Interrupt + +// REPEAT INSTRUCTIONS + +TMS320C54_rpt, // Repeat Next Instruction +TMS320C54_rptb, // Block Repeat +TMS320C54_rptbd, // Block Repeat +TMS320C54_rptz, // Repeat Next Instruction And Clear Accumulator + +// STACK MANIPULATING INSTRUCTIONS + +TMS320C54_frame, // Stack Pointer Immediate Offset +TMS320C54_popd, // Pop Top of Stack to Data Memory +TMS320C54_popm, // Pop Top of Stack to Memory-Mapped Register +TMS320C54_pshd, // Push Data-Memory Value Onto Stack +TMS320C54_pshm, // Push Memory-Mapped Register Onto Stack + +// MISCELLANEOUS PROGRAM-CONTROL INSTRUCTIONS + +TMS320C54_idle, // Idle Until Interrupt +TMS320C54_mar, // Modify Auxiliary Register +TMS320C54_nop, // No Operation +TMS320C54_reset, // Software Reset +TMS320C54_rsbx1, // Reset Status Register Bit +TMS320C54_rsbx2, // Reset Status Register Bit +TMS320C54_ssbx1, // Set Status Register Bit +TMS320C54_ssbx2, // Set Status Register Bit +TMS320C54_xc2, // Execute Conditionally +TMS320C54_xc3, // Execute Conditionally + +// LOAD AND STORE OPERATIONS + +// LOAD INSTRUCTIONS + +TMS320C54_dld, // Double-Precision/Dual 16-Bit Long-Word Load to Accumulator +TMS320C54_ld1, // Load Accumulator With Shift +TMS320C54_ld2, // Load Accumulator With Shift +TMS320C54_ld3, // Load Accumulator With Shift +TMS320C54_ldm, // Load Memory-Mapped Register +TMS320C54_ldr, // Load Memory Value in Accumulator High With Rounding +TMS320C54_ldu, // Load Unsigned Memory Value +TMS320C54_ltd, // Load T and insert Delay + +// STORE INSTRUCTIONS + +TMS320C54_dst, // Store Accumulator in Long Word +TMS320C54_st, // Store T, TRN, or Immediate Value into Memory +TMS320C54_sth2, // Store Accumulator High Into Memory +TMS320C54_sth3, // Store Accumulator High Into Memory +TMS320C54_stl2, // Store Accumulator Low Into Memory +TMS320C54_stl3, // Store Accumulator Low Into Memory +TMS320C54_stlm, // Store Accumulator Low Into Memory-Mapped Register +TMS320C54_stm, // Store Immediate Value Into Memory-Mapped Register + +// CONDITIONAL STORE INSTRUCTIONS + +TMS320C54_cmps, // Compare, Select and Store Maximum +TMS320C54_saccd, // Store Accumulator Conditionally +TMS320C54_srccd, // Store Block Repeat Counter Conditionally +TMS320C54_strcd, // Store T Conditionally + +// PARALLEL LOAD AND STORE INSTRUCTIONS + +TMS320C54_st_ld, // Store Accumulator With Parallel Load + +// PARALLEL LOAD AND MULTIPLY INSTRUCTIONS + +TMS320C54_ld_mac, // Load Accumulator With Parallel Multiply Accumulate Without Rounding +TMS320C54_ld_macr, // Load Accumulator With Parallel Multiply Accumulate With Rounding +TMS320C54_ld_mas, // Load Accumulator With Parallel Multiply Subtract Without Rounding +TMS320C54_ld_masr, // Load Accumulator With Parallel Multiply Subtract With Rounding + +// PARALLEL STORE AND ADD/SUBSTRACT INSTRUCTIONS + +TMS320C54_st_add, // Store Accumulator With Parallel Add +TMS320C54_st_sub, // Store Accumulator With Parallel Subtract + +// PARALLEL STORE AND MULTIPLY INSTRUCTIONS + +TMS320C54_st_mac, // Store Accumulator With Parallel Multiply Accumulate Without Rounding +TMS320C54_st_macr, // Store Accumulator With Parallel Multiply Accumulate With Rounding +TMS320C54_st_mas, // Store Accumulator With Parallel Multiply Subtract Without Rounding +TMS320C54_st_masr, // Store Accumulator With Parallel Multiply Subtract With Rounding +TMS320C54_st_mpy, // Store Accumulator With Parallel Multiply + +// MISCELLANEOUS LOAD-TYPE AND STORE-TYPE INSTRUCTIONS + +TMS320C54_mvdd, // Move Data From Data Memory to Data Memory With X,Y Addressing +TMS320C54_mvdk, // Move Data From Data Memory to Data Memory With Destination Addressing +TMS320C54_mvdm, // Move Data From Data Memory to Memory-Mapped Register +TMS320C54_mvdp, // Move Data From Data Memory to Program Memory +TMS320C54_mvkd, // Move Data From Data Memory to Data Memory With Source Addressing +TMS320C54_mvmd, // Move Data From Memory-Mapped Register to Data Memory +TMS320C54_mvmm, // Move Data From Memory-Mapped Register to Memory-Mapped Register +TMS320C54_mvpd, // Move Data From Program Memory to Data Memory +TMS320C54_portr, // Read Data From Port +TMS320C54_portw, // Write Data to Port +TMS320C54_reada, // Read Program Memory Addressed by Accumulator A and Store in Data Memory +TMS320C54_writa, // Write Data to Program Memory Addressed by Accumulator A + +TMS320C54_last + +}; + +#endif diff --git a/idasdk76/module/tms320c54/makefile b/idasdk76/module/tms320c54/makefile new file mode 100644 index 0000000..7496799 --- /dev/null +++ b/idasdk76/module/tms320c54/makefile @@ -0,0 +1,60 @@ +PROC=tms32054 +CONFIGS=tms320c54.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)OBJS$(O) : +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp ins.hpp tms320c54.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp tms320c54.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp tms320c54.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp \ + tms320c54.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp notify_codes.hpp reg.cpp \ + tms320c54.hpp diff --git a/idasdk76/module/tms320c54/notify_codes.hpp b/idasdk76/module/tms320c54/notify_codes.hpp new file mode 100644 index 0000000..22bc82e --- /dev/null +++ b/idasdk76/module/tms320c54/notify_codes.hpp @@ -0,0 +1,33 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __TMS320C54_NOTIFY_CODES_HPP +#define __TMS320C54_NOTIFY_CODES_HPP + +#include <idp.hpp> + +//---------------------------------------------------------------------- +// The following events are supported by the TMS320C54 module in the ph.notify() function +namespace tms320c54_module_t +{ + enum event_codes_t + { + ev_set_dataseg = processor_t::ev_loader + 2, + }; + + inline processor_t::event_t idp_ev(event_codes_t ev) + { + return processor_t::event_t(ev); + } + + inline void set_dataseg(ea_t ea) + { + processor_t::notify(idp_ev(ev_set_dataseg), ea); + } +} + +#endif // __TMS320C54_NOTIFY_CODES_HPP diff --git a/idasdk76/module/tms320c54/out.cpp b/idasdk76/module/tms320c54/out.cpp new file mode 100644 index 0000000..1a9ca39 --- /dev/null +++ b/idasdk76/module/tms320c54/out.cpp @@ -0,0 +1,467 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "tms320c54.hpp" +#include <frame.hpp> +#include <segregs.hpp> +#include <struct.hpp> + +// simple wrapper class for syntactic sugar of member functions +// this class may have only simple member functions. +// virtual functions and data fields are forbidden, otherwise the class +// layout may change +class out_tms320c54_t : public outctx_t +{ + out_tms320c54_t(void) = delete; // not used + + tms320c54_t &pm() { return *static_cast<tms320c54_t *>(procmod); } +public: + bool out_operand(const op_t &x); + void out_insn(void); + void out_address(ea_t ea, const op_t &x, bool mapping, bool at); + void out_cond8(char value); +}; +CASSERT(sizeof(out_tms320c54_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c54_t) + +//---------------------------------------------------------------------- +void out_tms320c54_t::out_address(ea_t ea, const op_t &x, bool mapping, bool at) +{ + regnum_t reg = pm().get_mapped_register(ea); + if ( mapping && reg != rnone ) + { + out_register(ph.reg_names[reg]); + } + else + { +#ifndef TMS320C54_NO_NAME_NO_REF + qstring qbuf; + // since tms320c54 uses memory mapping, we turn off verification + // of name expression values (4th arg of get_name_expr is BADADDR) + if ( get_name_expr(&qbuf, insn.ea+x.offb, x.n, ea, BADADDR) > 0 ) + { + if ( at ) + out_symbol('@'); + out_line(qbuf.begin()); + } + else +#endif + { + out_tagon(COLOR_ERROR); + out_value(x, OOF_ADDR|OOFW_32); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + } +} + +//---------------------------------------------------------------------- +const char *get_cond8(char value) +{ + switch ( value ) + { + case COND8_UNC: return "unc"; + case COND8_NBIO: return "nbio"; + case COND8_BIO: return "bio"; + case COND8_NC: return "nc"; + case COND8_C: return "c"; + case COND8_NTC: return "ntc"; + case COND8_TC: return "tc"; + case COND8_AGEQ: return "ageq"; + case COND8_ALT: return "alt"; + case COND8_ANEQ: return "aneq"; + case COND8_AEQ: return "aeq"; + case COND8_AGT: return "agt"; + case COND8_ALEQ: return "aleq"; + case COND8_ANOV: return "anov"; + case COND8_AOV: return "aov"; + case COND8_BGEQ: return "bgeq"; + case COND8_BLT: return "blt"; + case COND8_BNEQ: return "bneq"; + case COND8_BEQ: return "beq"; + case COND8_BGT: return "bgt"; + case COND8_BLEQ: return "bleq"; + case COND8_BNOV: return "bnov"; + case COND8_BOV: return "bov"; + default: return NULL; + } +} + +//---------------------------------------------------------------------- +void out_tms320c54_t::out_cond8(char value) +{ + const char *cond = get_cond8(value); + QASSERT(256, cond != NULL); + out_line(cond, COLOR_REG); +} + +//---------------------------------------------------------------------- +bool out_tms320c54_t::out_operand(const op_t &x) +{ + ea_t ea; + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + out_register(ph.reg_names[x.reg]); + break; + + case o_near: + case o_far: + ea = calc_code_mem(insn, x.addr, x.type == o_near); + out_address(ea, x, false, false); + break; + + case o_imm: + { + const char *name = NULL; + if ( pm().idpflags & TMS320C54_IO && x.IOimm ) + name = pm().find_sym(x.value); + if ( !x.NoCardinal ) + out_symbol('#'); + if ( name != NULL && name[0] != '\0' ) + { + out_line(name, COLOR_IMPNAME); + } + else + { + if ( !x.Signed ) + out_value(x, OOFW_IMM); + else + out_value(x, OOFS_IFSIGN|OOF_SIGNED|OOF_NUMBER|OOFW_IMM); + } + break; + } + + case o_local: + out_value(x, OOF_ADDR|OOFW_32); + break; + + case o_mmr: + case o_mem: + case o_farmem: + if ( x.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING ) + { + out_symbol('*'); + out_symbol('('); + } + ea = pm().calc_data_mem(insn, x.addr, x.type == o_mem); + if ( ea != BADADDR ) + { + // no '@' if absolute "indirect" adressing + bool at = x.IndirectAddressingMOD != ABSOLUTE_INDIRECT_ADRESSING; + out_address(ea, x, true, at); + } + else + { + out_value(x, OOF_ADDR|OOFW_32); + } + if ( x.IndirectAddressingMOD == ABSOLUTE_INDIRECT_ADRESSING ) + out_symbol(')'); + break; + + case o_displ: // Indirect addressing mode + { + char buf[8]; + const char *reg = ph.reg_names[x.reg]; + switch ( x.IndirectAddressingMOD ) + { + case 0: + qsnprintf(buf, sizeof(buf), "*%s",reg); + out_register(buf); + break; + case 1: + qsnprintf(buf, sizeof(buf), "*%s-",reg); + out_register(buf); + break; + case 2: + qsnprintf(buf, sizeof(buf), "*%s+",reg); + out_register(buf); + break; + case 3: + qsnprintf(buf, sizeof(buf), "*+%s",reg); + out_register(buf); + break; + case 4: + qsnprintf(buf, sizeof(buf), "*%s-0B",reg); + out_register(buf); + break; + case 5: + qsnprintf(buf, sizeof(buf), "*%s-0",reg); + out_register(buf); + break; + case 6: + qsnprintf(buf, sizeof(buf), "*%s+0",reg); + out_register(buf); + break; + case 7: + qsnprintf(buf, sizeof(buf), "*%s+0B",reg); + out_register(buf); + break; + case 8: + qsnprintf(buf, sizeof(buf), "*%s-%%",reg); + out_register(buf); + break; + case 9: + qsnprintf(buf, sizeof(buf), "*%s-0%%",reg); + out_register(buf); + break; + case 0xA: + qsnprintf(buf, sizeof(buf), "*%s+%%",reg); + out_register(buf); + break; + case 0xB: + qsnprintf(buf, sizeof(buf), "*%s+0%%",reg); + out_register(buf); + break; + case 0xC: + qsnprintf(buf, sizeof(buf), "*%s(",reg); + out_register(buf); + out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); + out_symbol(')'); + break; + case 0xD: + qsnprintf(buf, sizeof(buf), "*+%s(",reg); + out_register(buf); + out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); + out_symbol(')'); + break; + case 0xE: + qsnprintf(buf, sizeof(buf), "*+%s(",reg); + out_register(buf); + out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); + out_symbol(')'); + out_symbol('%'); + break; + // this special adressing mode is now defined as o_farmem ! + // case ABSOLUTE_INDIRECT_ADRESSING: + // out_symbol('*'); + // out_symbol('('); + // out_value(x, OOF_ADDR|OOF_SIGNED|OOFW_16); + // out_symbol(')'); + // break; + default: + error("interr: out: o_displ"); + } + break; + } + + case o_bit: + { + if ( !x.NoCardinal ) + out_symbol('#'); + char buf[20]; + qsnprintf(buf, sizeof(buf), "%d", int(x.value)); + out_line(buf, COLOR_REG); + break; + } + + case o_cond8: + out_cond8((uchar)x.value); + break; + + case o_cond2: + { + const char *cond = ""; + switch ( x.value ) + { + case 0: cond = "eq"; break; + case 1: cond = "lt"; break; + case 2: cond = "gt"; break; + case 3: cond = "neq"; break; + default: warning("interr: out 2-bit condition"); + } + out_line(cond, COLOR_REG); + break; + } + + default: + error("interr: out"); + } + return 1; +} + +//---------------------------------------------------------------------- +void out_tms320c54_t::out_insn(void) +{ + out_mnemonic(); + out_one_operand(0); + if ( insn.Op2.type != o_void ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + if ( insn.IsParallel ) + { // new line for Parallel instructions + flush_outbuf(); + out_line("|| ", COLOR_INSN); + const char *insn2 = NULL; + switch ( insn.itype ) + { + case TMS320C54_ld_mac: insn2 = "mac "; break; + case TMS320C54_ld_macr: insn2 = "macr "; break; + case TMS320C54_ld_mas: insn2 = "mas "; break; + case TMS320C54_ld_masr: insn2 = "masr "; break; + case TMS320C54_st_add: insn2 = "add "; break; + case TMS320C54_st_sub: insn2 = "sub "; break; + case TMS320C54_st_ld: insn2 = "ld "; break; + case TMS320C54_st_mpy: insn2 = "mpy "; break; + case TMS320C54_st_mac: insn2 = "mac "; break; + case TMS320C54_st_macr: insn2 = "macr "; break; + case TMS320C54_st_mas: insn2 = "mas "; break; + case TMS320C54_st_masr: insn2 = "masr "; break; + default: warning("interr: out parallel instruction"); + } + out_line(insn2, COLOR_INSN); + } + if ( insn.Op3.type != o_void ) + { + if ( !insn.IsParallel ) + { + out_symbol(','); + out_char(' '); + } + out_one_operand(2); + if ( insn.Op4_type != 0 ) + { + out_symbol(','); + out_char(' '); + switch ( insn.Op4_type ) + { + case o_reg: + out_register(ph.reg_names[insn.Op4_value]); + break; + case o_cond8: + out_cond8(insn.Op4_value); + break; + default: + break; + } + } + } + } + + out_immchar_cmts(); + flush_outbuf(); +} + +//-------------------------------------------------------------------------- +void tms320c54_t::print_segment_register(outctx_t &ctx, int reg, sel_t value) +{ + if ( reg == ph.reg_data_sreg ) + return; + if ( value != BADADDR ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), value); + ctx.gen_cmt_line("assume %s = %s", ph.reg_names[reg], buf); + } + else + { + ctx.gen_cmt_line("drop %s", ph.reg_names[reg]); + } +} + +//-------------------------------------------------------------------------- +// function to produce assume directives +//lint -e{1764} ctx could be const +void tms320c54_t::assumes(outctx_t &ctx) +{ + ea_t ea = ctx.insn_ea; + segment_t *seg = getseg(ea); + if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) + return; + bool seg_started = (ea == seg->start_ea); + + for ( int i = ph.reg_first_sreg; i <= ph.reg_last_sreg; ++i ) + { + if ( i == ph.reg_code_sreg ) + continue; + sreg_range_t sra; + if ( !get_sreg_range(&sra, ea, i) ) + continue; + if ( seg_started || sra.start_ea == ea ) + { + sel_t now = get_sreg(ea, i); + sreg_range_t prev; + bool prev_exists = get_sreg_range(&prev, ea-1, i); + if ( seg_started || (prev_exists && get_sreg(prev.start_ea, i) != now) ) + print_segment_register(ctx, i, now); + } + } +} + +//-------------------------------------------------------------------------- +//lint -e{818} seg could be const +void tms320c54_t::segstart(outctx_t &ctx, segment_t *seg) const +{ + if ( is_spec_segm(seg->type) ) + return; + + qstring sclas; + get_segm_class(&sclas, seg); + + if ( sclas == "CODE" ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".text", SCOLOR_ASMDIR)); + else if ( sclas == "DATA" ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".data", SCOLOR_ASMDIR)); + + if ( seg->orgbase != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), seg->orgbase); + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s %s", SCOLOR_ASMDIR), ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +void idaapi segend(outctx_t &, segment_t *) +{ +} + +//-------------------------------------------------------------------------- +void idaapi header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL | GH_BYTESEX_HAS_HIGHBYTE); + ctx.gen_empty_line(); +} + +//-------------------------------------------------------------------------- +void tms320c54_t::footer(outctx_t &ctx) const +{ + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s",SCOLOR_ASMDIR), ash.end); +} + +//-------------------------------------------------------------------------- +void tms320c54_t::gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const +{ + char sign = ' '; + if ( v < 0 ) + { + sign = '-'; + v = -v; + } + + qstring name = get_member_name(mptr->id); + + char vstr[MAX_NUMBUF]; + btoa(vstr, sizeof(vstr), v); + ctx.out_printf(COLSTR("%s",SCOLOR_KEYWORD) " " + COLSTR("%c%s",SCOLOR_DNUM) + COLSTR(",",SCOLOR_SYMBOL) " " + COLSTR("%s",SCOLOR_LOCNAME), + ash.a_equ, + sign, + vstr, + name.c_str()); +} + diff --git a/idasdk76/module/tms320c54/reg.cpp b/idasdk76/module/tms320c54/reg.cpp new file mode 100644 index 0000000..d82fbe3 --- /dev/null +++ b/idasdk76/module/tms320c54/reg.cpp @@ -0,0 +1,687 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include "tms320c54.hpp" +#include "notify_codes.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +#include <ieee.h> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "PC", // program counter + "A", // accumulator + "B", // accumulator + + // flags + "ASM", // 5-bit accumulator shift mode field in ST1 + "ARP", // auxiliary register pointer + "TS", // shift value (bits 5-0 of T) + "OVB", + "OVA", + "C", + "TC", + "CMPT", + "FRCT", + "C16", + "SXM", + "OVM", + "INTM", + "HM", + "XF", + "BRAF", + + // CPU memory mapped registers + "IMR", + "IFR", + "ST0", + "ST1", + "AL", + "AH", + "AG", + "BL", + "BH", + "BG", + "T", // temporary register + "TRN", // transition register + "AR0", + "AR1", + "AR2", + "AR3", + "AR4", + "AR5", + "AR6", + "AR7", + "SP", // stack pointer + "BK", + "BRC", + "RSA", + "REA", + "PMST", + + // segment registers + "XPC", // program counter extension register + "CPL", // compiler mode + "DP", // data page pointer + "cs","ds", // virtual registers for code and data segments +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0xF4, 0xE4 }; // fret +static const uchar retcode_1[] = { 0xF6, 0xE4 }; // fretd +static const uchar retcode_2[] = { 0xF4, 0xE5 }; // frete +static const uchar retcode_3[] = { 0xF6, 0xE5 }; // freted +static const uchar retcode_4[] = { 0xFC }; // rc +static const uchar retcode_5[] = { 0xFE }; // rcd +static const uchar retcode_6[] = { 0xFC, 0x00 }; // ret +static const uchar retcode_7[] = { 0xFE, 0x00 }; // retd +static const uchar retcode_8[] = { 0xF4, 0xEA }; // rete +static const uchar retcode_9[] = { 0xF6, 0xEA }; // reted +static const uchar retcode_10[] = { 0xF4, 0x9A }; // retf +static const uchar retcode_11[] = { 0xF6, 0x9A }; // retfd + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { sizeof(retcode_4), retcode_4 }, + { sizeof(retcode_5), retcode_5 }, + { sizeof(retcode_6), retcode_6 }, + { sizeof(retcode_7), retcode_7 }, + { sizeof(retcode_8), retcode_8 }, + { sizeof(retcode_9), retcode_9 }, + { sizeof(retcode_10), retcode_10 }, + { sizeof(retcode_11), retcode_11 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// TMS320C54 ASM +//----------------------------------------------------------------------- +static const asm_t fasm = +{ + AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON, + 0, + "ASM500", + 0, + NULL, // header lines + NULL, // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".pstring", // ascii string directive + ".word", // byte directive + ".long", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".space 16*%s",// uninited arrays + ".asg", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".ref", // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_STRINV // invert string byte order +}; + +//----------------------------------------------------------------------- +// GNU ASM +//----------------------------------------------------------------------- +static const asm_t gnuasm = +{ + AS_N2CHR|ASH_HEXF3|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP|AS_COLON|AS_ASCIIC, + 0, + "GNU assembler", + 0, + NULL, // header lines + NULL, // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".pstring", // ascii string directive + ".word", // byte directive + ".long", // word directive + NULL, // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".zero 2*%s", // uninited arrays + ".asg", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + ".weak", // "weak" name keyword + ".extern", // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_STRINV, // invert string byte order + NULL, // cmnt2 + NULL, // low8 + NULL, // high8 + NULL, // low16 + NULL, // high16 + "#include \"%s\"", // a_include_fmt +}; + +static const asm_t *const asms[] = { &fasm, &gnuasm, NULL }; + +//-------------------------------------------------------------------------- + +const char *tms320c54_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? port->name.c_str() : NULL; +} + +//---------------------------------------------------------------------- +void tms320c54_t::apply_symbols(void) +{ + insn_t dummy; + for ( int i=0; i < ioh.ports.size(); i++ ) + { + ea_t ea = calc_data_mem(dummy, ioh.ports[i].address, false); + segment_t *s = getseg(ea); + if ( s == NULL || s->type != SEG_IMEM ) + continue; + create_byte(ea, 1); + const char *name = ioh.ports[i].name.c_str(); + if ( !set_name(ea, name, SN_NOCHECK|SN_NOWARN|SN_NODUMMY) ) + set_cmt(ea, name, 0); + } +} + +//-------------------------------------------------------------------------- +inline void swap(unsigned char &c1, unsigned char &c2) +{ + unsigned char tmp = c1; + c1 = c2; + c2 = tmp; +} + +fpvalue_error_t idaapi tms_realcvt(void *m, fpvalue_t *e, ushort swt) +{ + fpvalue_error_t ret; + switch ( swt ) + { + case 1: // float to e + { + unsigned char p[4]; + memcpy(p, m, 4); + swap(p[0], p[1]); + swap(p[2], p[3]); + ret = ieee_realcvt(p, e, swt); + break; + } + case 011: // float output //-V536 octal + { + ret = ieee_realcvt(m, e, swt); + unsigned char *p = (unsigned char*)m; + swap(p[0], p[1]); + swap(p[2], p[3]); + break; + } + default: + ret = ieee_realcvt(m, e, swt); + break; + } + return ret; +} + +//-------------------------------------------------------------------------- +static int idaapi choose_device(int, form_actions_t &fa) +{ + tms320c54_t &pm = *(tms320c54_t *)fa.get_ud(); + if ( choose_ioport_device(&pm.ioh.device, cfgname) ) + pm.ioh.set_device_name(pm.ioh.device.c_str(), IORESP_ALL); + return 0; +} + +//-------------------------------------------------------------------------- +const char *tms320c54_t::set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded) +{ + if ( keyword == NULL ) + { + static const char form[] = + "HELP\n" + "TMS320C54 specific options\n" + "\n" + " Use I/O definitions\n" + "\n" + " If this option is on, IDA will use I/O definitions\n" + " from the configuration file into a macro instruction.\n" + "\n" + " Detect memory mapped registers\n" + "\n" + " If this option is on, IDA will replace addresses\n" + " by an equivalent memory mapped register.\n" + "\n" + " Device name\n" + "\n" + " Choose the exact device name for the processor.\n" + " If you don't see the name you want, you can add\n" + " a section about it to the tms320c54.cfg file\n" + "\n" + " Data segment address\n" + "\n" + " The data segment linear address.\n" + "\n" + "ENDHELP\n" + "TMS320C54 specific options\n" + "%*\n" + " <Use ~I~/O definitions:C>\n" + " <Detect memory mapped ~r~egisters:C>>\n" + "\n" + " <~C~hoose device name:B:0:::>\n" + "\n" + " <~D~ata segment address:N::18::>\n" + "\n"; + CASSERT(sizeof(idpflags) == sizeof(ushort)); + CASSERT(sizeof(dataseg) == sizeof(ea_t)); + ask_form(form, this, &idpflags, choose_device, &dataseg); + } + else + { + if ( strcmp(keyword, "TMS320C54_DSEG") == 0 ) + { + if ( value_type != IDPOPT_NUM ) + return IDPOPT_BADTYPE; + dataseg = *(uval_t *)value; + } + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + if ( strcmp(keyword, "TMS320C54_IO") == 0 ) + { + setflag(idpflags, TMS320C54_IO, *(int*)value != 0); + } + else if ( strcmp(keyword, "TMS320C54_MMR") == 0 ) + { + setflag(idpflags, TMS320C54_MMR, *(int*)value != 0); + } + else + { + return IDPOPT_BADKEY; + } + } + if ( idb_loaded ) + { + save_idpflags(); + save_dataseg(); + } + return IDPOPT_OK; +} + +//-------------------------------------------------------------------------- +static const proctype_t ptypes[] = +{ + TMS320C54 +}; + +void tms320c54_t::load_from_idb() +{ + ptype = ptypes[ph.get_proc_index()]; + ioh.restore_device(); + if ( ioh.device.empty() ) + { + read_ioports(&ioh.ports, &ioh.device, cfgname); + helper.supset(-1, ioh.device.c_str()); + } + inf_set_wide_high_byte_first(false); + idpflags = (ushort)helper.altval(-1); + dataseg = helper.altval(0); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(tms320c54_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi tms320c54_t::on_event(ssize_t msgid, va_list va) +{ +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable : 4063) +#endif + int code = 0; + switch ( msgid ) // Cast to avoid lint complaining. + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); // MSB first + inf_set_wide_high_byte_first(true); + dataseg = helper.altval(0); + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + read_ioports(&ioh.ports, &ioh.device, cfgname); + helper.supset(-1, ioh.device.c_str()); + save_idpflags(); + save_dataseg(); + inf_set_wide_high_byte_first(false); + { + segment_t *s = get_first_seg(); + if ( s != NULL ) + apply_symbols(); + while ( s != NULL ) + { + qstring sclas; + get_segm_class(&sclas, s); + for ( int i = XPC; i <= rVds; i++ ) + set_default_sreg_value(s, i, BADSEL); + if ( sclas == "CODE" ) + set_default_sreg_value(s, XPC, s->start_ea >> 16); + s = get_next_seg(s->start_ea); + } + } + break; + + case tms320c54_module_t::ev_set_dataseg: + dataseg = va_arg(va, ea_t); + save_dataseg(); + break; + + case processor_t::ev_oldfile: // old file loaded + ioh.upgrade_device_index(); + //fall through + case processor_t::ev_ending_undo: + load_from_idb(); + break; + + case processor_t::ev_newbinary: + inf_set_wide_high_byte_first(true); + break; + case processor_t::ev_endbinary: + inf_set_wide_high_byte_first(false); + break; + + case processor_t::ev_newprc: // new processor type + { + ptype = ptypes[va_arg(va, int)]; + // bool keep_cfg = va_argi(va, bool); + switch ( ptype ) + { + case TMS320C54: + break; + default: + error("interr: setprc"); + } + } + break; + + case processor_t::ev_newasm: // new assembler type + break; + + case processor_t::ev_creating_segm: // new segment + break; + + case processor_t::ev_is_basic_block_end: + { + const insn_t *insn = va_arg(va, const insn_t *); + return is_basic_block_end(*insn) ? 1 : -1; + } + + case processor_t::ev_is_sane_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + int no_crefs = va_arg(va, int); + // add 0, a is not a sane instruction without crefs to it + code = no_crefs && get_wide_byte(insn->ea) == 0 ? -1 : 1; + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_realcvt: + { + void *m = va_arg(va, void *); + fpvalue_t *e = va_arg(va, fpvalue_t *); + uint16 swt = va_argi(va, uint16); + fpvalue_error_t code1 = tms_realcvt(m, e, swt); + return code1 == REAL_ERROR_OK ? 1 : code1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_get_frame_retsize: + { + int *frsize = va_arg(va, int *); + const func_t *pfn = va_arg(va, const func_t *); + *frsize = tms_get_frame_retsize(pfn); + return 1; + } + + case processor_t::ev_gen_stkvar_def: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const member_t *mptr = va_arg(va, const member_t *); + sval_t v = va_arg(va, sval_t); + gen_stkvar_def(*ctx, mptr, v); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } +#ifdef _MSC_VER +#pragma warning(pop) +#endif + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "TMS320C54x Series:" +static const char *const shnames[] = +{ + "TMS32054", + NULL +}; +static const char *const lnames[] = +{ + FAMILY"Texas Instruments TMS320C54", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_TMS320C54, // id + // flag + PRN_HEX + | PR_SEGS + | PR_SGROTHER + | PR_ALIGN, + // flag2 + PR2_MAPPINGS // use memory mapping + | PR2_REALCVT // the module has 'realcvt' event implementation + | PR2_IDP_OPTS, // the module has processor-specific configuration options + 16, // 16 bits in a byte for code segments + 16, // 16 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + XPC, // first + rVds, // last + 1, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + TMS320C54_null, + TMS320C54_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0,7,15,19 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + TMS320C54_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/tms320c54/tms320c54.cfg b/idasdk76/module/tms320c54/tms320c54.cfg similarity index 100% rename from idasdk75/module/tms320c54/tms320c54.cfg rename to idasdk76/module/tms320c54/tms320c54.cfg diff --git a/idasdk76/module/tms320c54/tms320c54.hpp b/idasdk76/module/tms320c54/tms320c54.hpp new file mode 100644 index 0000000..3e118d9 --- /dev/null +++ b/idasdk76/module/tms320c54/tms320c54.hpp @@ -0,0 +1,243 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _TMS320C54_HPP +#define _TMS320C54_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + + +// #define TMS320C54_NO_NAME_NO_REF + +//------------------------------------------------------------------ +#ifdef _MSC_VER +#define ENUM8BIT : uint8 +#else +#define ENUM8BIT +#endif +enum regnum_t ENUM8BIT +{ + PC, // program counter + A, // accumulator + B, // accumulator + + // flags + ASM, // 5-bit accumulator shift mode field in ST1 + ARP, // auxiliary register pointer + TS, // shift value (bits 5-0 of T) + OVB, + OVA, + C, + TC, + CMPT, + FRCT, + C16, + SXM, + OVM, + INTM, + HM, + XF, + BRAF, + + // CPU memory mapped registers + IMR, + IFR, + ST0, + ST1, + AL, + AH, + AG, + BL, + BH, + BG, + T, // temporary register + TRN, // transition register + AR0, + AR1, + AR2, + AR3, + AR4, + AR5, + AR6, + AR7, + SP, // stack pointer + BK, + BRC, + RSA, + REA, + PMST, + + // segment registers + XPC, // program counter extension register + CPL, // compiler mode + DP, // data page pointer + rVcs, rVds, // virtual registers for code and data segments + rnone = 0xFF, // no register +}; + +//------------------------------------------------------------------ +// specific condition codes +#define COND_A 0x0 +#define COND_B 0x8 + +#define COND_GEQ 0x2 +#define COND_LT 0x3 +#define COND_NEQ 0x4 +#define COND_EQ 0x5 +#define COND_GT 0x6 +#define COND_LEQ 0x7 + + +#define COND4_AGEQ (COND_A | COND_GEQ) +#define COND4_ALT (COND_A | COND_LT) +#define COND4_ANEQ (COND_A | COND_NEQ) +#define COND4_AEQ (COND_A | COND_EQ) +#define COND4_AGT (COND_A | COND_GT) +#define COND4_ALEQ (COND_A | COND_LEQ) + +#define COND4_BGEQ (COND_B | COND_GEQ) +#define COND4_BLT (COND_B | COND_LT) +#define COND4_BNEQ (COND_B | COND_NEQ) +#define COND4_BEQ (COND_B | COND_EQ) +#define COND4_BGT (COND_B | COND_GT) +#define COND4_BLEQ (COND_B | COND_LEQ) + + +#define COND8_FROM_COND4 0x40 + +#define COND8_UNC 0x00 +#define COND8_NBIO 0x02 +#define COND8_BIO 0x03 +#define COND8_NC 0x08 +#define COND8_C 0x0C +#define COND8_NTC 0x20 +#define COND8_TC 0x30 +#define COND8_AGEQ (COND8_FROM_COND4 | COND4_AGEQ) +#define COND8_ALT (COND8_FROM_COND4 | COND4_ALT) +#define COND8_ANEQ (COND8_FROM_COND4 | COND4_ANEQ) +#define COND8_AEQ (COND8_FROM_COND4 | COND4_AEQ) +#define COND8_AGT (COND8_FROM_COND4 | COND4_AGT) +#define COND8_ALEQ (COND8_FROM_COND4 | COND4_ALEQ) +#define COND8_ANOV 0x60 +#define COND8_AOV 0x70 +#define COND8_BGEQ (COND8_FROM_COND4 | COND4_BGEQ) +#define COND8_BLT (COND8_FROM_COND4 | COND4_BLT) +#define COND8_BNEQ (COND8_FROM_COND4 | COND4_BNEQ) +#define COND8_BEQ (COND8_FROM_COND4 | COND4_BEQ) +#define COND8_BGT (COND8_FROM_COND4 | COND4_BGT) +#define COND8_BLEQ (COND8_FROM_COND4 | COND4_BLEQ) +#define COND8_BNOV (COND_B | COND8_ANOV) +#define COND8_BOV (COND_B | COND8_AOV) + +//------------------------------------------------------------------ +// specific processor records + +#define o_bit o_idpspec0 +#define o_cond8 o_idpspec1 +#define o_cond2 o_idpspec2 +#define o_local o_idpspec3 +#define o_mmr o_idpspec4 +#define o_farmem o_idpspec5 + +#define Op4_type auxpref_u8[0] +#define Op4_value auxpref_u8[1] +#define IsParallel segpref + +// != 0 => MOD = IndirectAddressingMOD-1 +#define IndirectAddressingMOD specflag1 +#define ABSOLUTE_INDIRECT_ADRESSING 0xF // special "indirect" adressing + // (in fact absolute adressing) +#define Signed specflag1 +#define NoCardinal specflag2 +#define IOimm specflag3 + +//------------------------------------------------------------------ +// processor types + +typedef uchar proctype_t; + +const proctype_t TMS320C54 = 0; + +#define TMS320C54_IO 0x0001 // use I/O definitions +#define TMS320C54_MMR 0x0002 // use memory mapped registers + +//------------------------------------------------------------------ +const char *const cfgname = "tms320c54.cfg"; + +struct tms320c54_iohandler_t : public iohandler_t +{ + tms320c54_iohandler_t(netnode &nn) : iohandler_t(nn) {} + void get_cfg_filename(char *buf, size_t bufsize) override + { + qstrncpy(buf, cfgname, bufsize); + } +}; + +struct tms320c54_t : public procmod_t +{ + netnode helper; + tms320c54_iohandler_t ioh = tms320c54_iohandler_t(helper); + + ea_t dataseg; + ushort idpflags = TMS320C54_IO|TMS320C54_MMR; + proctype_t ptype = TMS320C54; + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *find_sym(ea_t address); + void apply_symbols(void); + const char *idaapi set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + + int ana(insn_t *insn); + + int emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool use); + ea_t calc_data_mem(const insn_t &insn, ea_t ea, bool is_mem) const; + bool create_func_frame(func_t *pfn) const; + regnum_t get_mapped_register(ea_t ea) const; + + void assumes(outctx_t &ctx); + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void segstart(outctx_t &ctx, segment_t *seg) const; + void footer(outctx_t &ctx) const; + void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; + + void save_idpflags() { helper.altset(-1, idpflags); } + void save_dataseg() { helper.altset(0, dataseg); } + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ tms320c54" +#define PROCMOD_NAME tms320c54 + +ea_t calc_code_mem(const insn_t &insn, ea_t ea, bool is_near = true); + +const char *get_cond8(char value); + +//------------------------------------------------------------------ +void idaapi header(outctx_t &ctx); + +void idaapi segend(outctx_t &ctx, segment_t *seg); + +void idaapi data(ea_t ea); + +int idaapi tms_get_frame_retsize(const func_t *pfn); +int idaapi is_align_insn(ea_t ea); +bool is_basic_block_end(const insn_t &insn); // 0-no, 2-yes + +#endif // _TMS320C54_HPP diff --git a/idasdk76/module/tms320c55/ana.cpp b/idasdk76/module/tms320c55/ana.cpp new file mode 100644 index 0000000..1257dd2 --- /dev/null +++ b/idasdk76/module/tms320c55/ana.cpp @@ -0,0 +1,1896 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * Texas Instruments's TMS5320C55 + * + */ + +//lint -e704 shift right of signed quantity +//lint -e1764 could be declared const + +#include "tms320c55.hpp" +#include <segregs.hpp> + +#define MAX_BYTE_USER_PARALLELIZED 0x5F +#define BYTE_MMAP 0x98 +#define BYTE_PORT1 0x99 +#define BYTE_PORT2 0x9A +#define BYTE_LR 0x9C +#define BYTE_CR 0x9D + +//-------------------------------------------------------------------------- +// class to store a bytes cache +#define BYTES_SIZE 32 // maximum cache size (maximum number of bytes) +class bytes_c +{ +public: + bytes_c(insn_t &_insn) : insn(_insn), size(0), i(0) + { + memset(bytes, 0, sizeof(bytes)); + } +private: + insn_t &insn; + int bytes[BYTES_SIZE]; + int size; + int i; +public: + void reset(void) { i = 0; } + int get_next(void); + int get(int j) const { return bytes[j]; } + void set_cache(bytevec_t &bytes); +}; + +//-------------------------------------------------------------------------- +// get the next byte +int bytes_c::get_next(void) +{ + if ( i == size ) + { + // if ( size >= CACHE_SIZE ) return NULL; + // load a new byte into the cache + bytes[size] = get_byte(insn.ea+size); + size++; + } + return bytes[i++]; +} + +//-------------------------------------------------------------------------- +// set cache contents +void bytes_c::set_cache(bytevec_t &_bytes) +{ + int n = _bytes.size(); + n = qmin(n, qnumber(bytes)); //lint !e666 expression with side effects + for ( size_t j=0; j < n; j++ ) + bytes[j] = _bytes[j]; + size = n; + reset(); +} + +#define OP_MASK_N 15 // maximum nomber of op_mask_t for an instruction + +struct mask_t; + +// function to generate an operand +typedef void (*func_op_mask_t)(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &optional_op); + +typedef struct +{ + func_op_mask_t func; // function to set operand + int64 mask; // mask of operand +} op_mask_t; + +struct mask_t +{ + int64 code; // full opcode of instruction + int64 mask; // full mask of instruction + char size; // number of bytes for instruction + ushort itype; //lint !e958 padding is required to align members + op_mask_t op_mask[OP_MASK_N]; //lint !e958 padding is required to align members + // function and mask to set operands +}; + +//-------------------------------------------------------------------------- +// verify if a given byte match a byte (0 <= n <= mask_t.size-1) from a code and mask +static bool byte_match_code_mask(const mask_t *mask, int64 byte, char n, char lbytesize = 8) +{ + // compute nshift and nmask + int nshift = (mask->size - 1 - n) * lbytesize; + int64 nmask = 0; + for ( int i = 0; i < lbytesize; i++ ) + nmask = (nmask << 1) | 1; + + // shift code and mask to get current byte + int64 mask_code = (mask->code >> nshift) & nmask; + int64 mask_mask = (mask->mask >> nshift) & nmask; + byte &= nmask; + + return (mask_code & mask_mask) == (byte & mask_mask); +} + +//-------------------------------------------------------------------------- +#define OP_BITS 30 // bits effectively reserved for masks (other bits are reserved for special operators) +#define OP_MASK (~(int64(0xFFFFFFFF) << OP_BITS)) // effective mask +#define OP_MASK_5 (~(make_ulonglong(0x3FFFFFF, 0) << (OP_BITS+8))) // effective mask +#define OP_MASK_6 (~(make_ulonglong(0x3FFFF, 0) << (OP_BITS+16))) // effective mask +#define OP_OP_NULL 0 +#define OP_OP_IMM 1 +#define OP_IMM(imm) ((OP_OP_IMM << OP_BITS)|(imm)) // return offset = imm +#define OP_TRUE OP_IMM(1) // return offset = 1 +#define OP_OP_NOT 2 +#define OP_NOT(mask) ((OP_OP_NOT << OP_BITS)|(mask)) // return (~offset) & 1 +// return a masked operand or the result of a special operation +#define OP_IMM_5(imm) (make_longlong(0x00000000, 0x40)|(imm)) // return offset = imm +#define OP_IMM_6(imm) (make_longlong(0x00000000, 0x4000)|(imm)) // return offset = imm +#define OP_TRUE_5 OP_IMM_5(1) // return offset = 1 +#define OP_TRUE_6 OP_IMM_6(1) // return offset = 1 + +static int64 get_masked_operand(int64 code, int64 mask) +{ + if ( mask == 0 ) + return 0; + bool no = false; + // special operations + switch ( mask >> OP_BITS ) + { + case OP_OP_NULL: + break; + case OP_OP_IMM: + return mask & OP_MASK; + case OP_OP_NOT: + no = true; + break; + default: + break; + } + code &= (mask & OP_MASK); + while ( (mask & 1) == 0 ) + { + code = code >> 1; + mask = mask >> 1; + } + if ( no ) + code = (~code) & 1; + return code; +} + + +//-------------------------------------------------------------------------- +static int get_signed(int byte, int mask) +{ + int bits = mask >> 1; + int sign = bits + 1; + if ( byte & sign ) // offset < 0 + byte = ( byte & bits ) - sign; + else // offset >= 0 + byte = byte & mask; + return byte; +} + +//-------------------------------------------------------------------------- +inline int get_signed64(int64 byte, int mask) +{ + return get_signed((int)byte, mask); +} + +//-------------------------------------------------------------------------- +inline int get_unsigned(int byte, int mask) +{ + byte = byte & mask; + return byte; +} + +//-------------------------------------------------------------------------- +static int64 get_masked_operand_5(int64 code, int64 mask) +{ + if ( mask == 0 ) + return 0; + bool no = false; + // special operations + int Switch=mask >> (OP_BITS+8); + switch ( Switch ) + { + case OP_OP_NULL: break; + case OP_OP_IMM: + return mask & OP_MASK_5; + case OP_OP_NOT: + no = true; + break; + default: + INTERR(10262); + } + code &= (mask & OP_MASK_5); + while ( (mask & 1) == 0 ) + { + code = code >> 1; + mask = mask >> 1; + } + if ( no ) + code = (~code) & 1; + return code; +} + +//-------------------------------------------------------------------------- +static int64 get_masked_operand_6(int64 code, int64 mask, bool /*bTest*/) +{ + if ( mask == 0 ) + return 0; + bool no = false; + // special operations + int Switch = mask >> (OP_BITS+16); + switch ( Switch ) + { + case OP_OP_NULL: break; + case OP_OP_IMM: + return mask & OP_MASK_6; + case OP_OP_NOT: + no = true; + break; + default: + INTERR(10263); + } + code &= mask & OP_MASK_6; + while ( (mask & 1) == 0 ) + { + code = code >> 1; + mask = mask >> 1; + } + if ( no ) + code = (~code) & 1; + return code; +} + +//-------------------------------------------------------------------------- +// process mask->op_mask[op_mask_n] on insn.ops[op_n] (if op.n not modified) and eventually modify op_n +bool tms320c55_t::process_masks_operand( + insn_t &insn, + const mask_t *mask, + int64 code, + int64 op_mask_n, + unsigned *p_opnum, + bool bTest) +{ + // initialize an operand to work on + op_t work; + unsigned opnum = *p_opnum; + if ( opnum < UA_MAXOP ) + work = insn.ops[opnum]; + else + work = insn.ops[UA_MAXOP-1]; + + const op_mask_t *op_mask = &mask->op_mask[int(op_mask_n)]; + if ( op_mask->func == NULL ) + return false; + + int64 opv = mask->size == 5 ? get_masked_operand_5(code, op_mask->mask) + : mask->size == 6 ? get_masked_operand_6(code, op_mask->mask, bTest) + : get_masked_operand(code, op_mask->mask); + op_mask->func(mask, opv, &work, insn, optional_op); + + if ( work.type != o_void ) // if the operand was modified + { + if ( work.n == opnum ) // the function worked on the current operand + { + if ( opnum >= UA_MAXOP ) + return false; // error if not enough operands in insn + insn.ops[opnum] = work; // save the new operand + *p_opnum = ++opnum; // go to the next operand + } + else // the function modified the previous operand + { + if ( work.n >= UA_MAXOP ) + return false; + insn.ops[work.n] = work; // save the new precedent operand (modified) + } + } + return true; +} + +//-------------------------------------------------------------------------- +// get number of bytes for a given instruction opcode (left-aligned in dword) +static int get_insn_size(const mask_t *masks, uint32 opcode) +{ + const mask_t *p = masks; + while ( p->mask != 0 ) + { + if ( p->size <= 4 && (p->mask & (opcode>>(8*(4-p->size)))) == p->code ) + return p->size; + p++; + } + return 0; +} + +//-------------------------------------------------------------------------- +// analyze code by processing all necessary masks +void tms320c55_t::process_masks( + insn_t &insn, + const mask_t *masks, + ushort itype_null, + bytes_c &bytes, + char lbytesize) +{ + insn.itype = itype_null; + insn.size = 1; + + const mask_t *p = masks; + while ( p->mask != 0 ) + { + bytes.reset(); + ushort nbytes = 0; + while ( nbytes < p->size + && byte_match_code_mask(p, bytes.get_next(), (uchar &)nbytes, lbytesize) ) + { + nbytes++; + } + if ( nbytes == p->size ) // if bytes matches all bytes from code and mask + { + int i; + insn.itype = p->itype; + insn.size = nbytes; + // compute full code + int64 code = 0; + for ( i = 0; i < nbytes; i++ ) + code = (code << lbytesize) | bytes.get(i); + // process operands + unsigned opnum = 0; + for ( i = 0; i < OP_MASK_N; i++ ) + { + bool bTest = p->size == 6 && i == 2; + if ( !process_masks_operand(insn, p, code, i, &opnum, bTest) ) + break; + } + return; + } + p++; + } +} + +//-------------------------------------------------------------------------- +// permit a mask_func_n to work on the last operand +static bool get_last_op(op_t *op, const insn_t &insn) +{ + int n; + for ( n = 0; n < 6; n++ ) // find the first o_void operand + if ( insn.ops[n].type == o_void ) + break; + + if ( n == 0 ) + return false; // no precedent operand + *op = insn.ops[n-1]; // copy the precedent operand to the current position + return true; +} + +//-------------------------------------------------------------------------- +// format instruction name +static void get_name_chars( + char *buf, + size_t bufsize, + bool incl_chars, + const char *name, + const char *chars) +{ + char *bufend = qstpncpy(buf, name, bufsize); + if ( incl_chars ) + qstrncpy(bufend, chars, bufsize - (bufend-buf)); +} + +//-------------------------------------------------------------------------- +// instructions + +// find instruction insn+"chars" with same operands: +// parallel indicate an instructions on 2 lines +// name1_chars indicate if we must have "chars" added to the first line +// name2_chars indicate if we must have "chars" added to the second line +// instructions in instruc_t Instructions[] must be sorted as follow: +// insn1 - insn2 - ... - insn"chars"1 - insn"chars"2 - ... +static bool find_insn_suffix( + insn_t &insn, + const char *chars, + ushort itype_last, + bool parallel, + bool name1_chars, + bool name2_chars) +{ + const char *insn_name1 = Instructions[insn.itype].name; + char insn_name1_chars[MAXSTR]; + get_name_chars(insn_name1_chars, sizeof(insn_name1_chars), name1_chars, insn_name1, chars); + + const char *insn_name2 = NULL; + char insn_name2_chars[MAXSTR]; + insn_name2_chars[0] = '\0'; + if ( parallel ) + { + insn_name2 = strchr(insn_name1, 0)+1; + get_name_chars(insn_name2_chars, sizeof(insn_name2_chars), name2_chars, insn_name2, chars); + } + + ushort i = insn.itype + 1; + // jump over same instruction names (but eventually different number of params) + while ( streq(Instructions[i].name, insn_name1) + && (!parallel || streq(strchr(Instructions[i].name, 0)+1, insn_name2)) ) //-V575 potential null pointer + { + if ( ++i == itype_last ) + return false; + } + + // loop until current instruction names are the same as what we are searching for (name or name+chars) + while ( !streq(Instructions[i].name, insn_name1_chars) + || (parallel && !streq(strchr(Instructions[i].name, 0)+1, insn_name2_chars)) ) + { + if ( ++i == itype_last ) + return false; + } + + // loop until current instruction has same params + uint32 insn_feature = Instructions[insn.itype].feature; + while ( Instructions[i].feature != insn_feature ) + { + if ( ++i == itype_last ) + return false; + } + + insn.itype = i; + return true; +} + +#define insn_chars(NAME, CHARS, PARALLEL, NAME1_CHARS, NAME2_CHARS) \ + static void NAME(const mask_t *, int64 offset, op_t *, insn_t &insn, char &) \ + { \ + if ( (offset & 1) != 0 ) \ + { \ + bool ok = find_insn_suffix(insn, CHARS, TMS320C55_last, PARALLEL,\ + NAME1_CHARS, NAME2_CHARS); \ + if ( !ok ) \ + error("interr: ana: adjust_insn_suffix"); \ + } \ + } + +insn_chars(insn_1_R_2_R, "r", true, true, true) // insn_1_R_2_R % +insn_chars(insn_1_40_2_40, "40", true, true, true) // insn_1_40_2_40 g +insn_chars(insn_1_2_R, "r", true, false, true) // insn_1_2_R % +insn_chars(insn_1_2_40, "40", true, false, true) // insn_1_2_40 g +insn_chars(insn_1_R, "r", false, true, false) // insn_1_R % +insn_chars(insn_1_40, "40", false, true, false) // insn_1_40 g +insn_chars(insn_1_R_2, "r", true, true, false) // insn_1_R_2 % +insn_chars(insn_1_U, "u", false, true, false) // insn_1_U u +insn_chars(insn_1_P, "p", false, true, false) // insn_1_P swap() +insn_chars(insn_1_4, "4", false, true, false) // insn_1_4 swap() + +// set user parellel +static void insn_UP(const mask_t *, int64, op_t *, insn_t &insn, char &) +{ + insn.SpecialModes |= TMS_MODE_USER_PARALLEL; +} + +// built-in parallelism +static void blt_prll(const mask_t *, int64, op_t *, insn_t &insn, char &) +{ // count the number of actual operands + insn.Parallel = 0; + for ( int i = 0; i < UA_MAXOP; i++ ) + { + if ( insn.ops[i].type == o_void ) + break; + insn.Parallel++; + } +} + +// simulated user parallelism +// static void usr_prll(const mask_t *mask, int64 offset, op_t *op) +// { +// if ( offset & 1 ) +// { +// blt_prll(mask, offset, op); +// insn.SpecialModes |= TMS_MODE_SIMULATE_USER_PARALLEL; +// } +// } +// ? actually not used, but will probably be used for non-documented opcodes +// need also to add new instructions "ins1\nins2" in ins.hpp & ins.cpp + +// immediates + +#define op_imm(NAME, DTYP) \ + static void op_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &, char &) \ + { \ + op->type = o_imm; \ + op->value = (uval_t)offset; \ + op->dtype = dt_##DTYP; \ + } + +op_imm(k8, byte) // op_k8 +op_imm(k16, word) // op_k16 +#define op_k4 op_k8 +#define op_k5 op_k8 +#define op_k7 op_k8 +#define op_k9 op_k16 +#define op_k12 op_k16 + +//-------------------------------------------------------------------------- +static void op_min_k4(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_imm; + op->value = (uval_t)-offset; + op->dtype = dt_byte; + op->tms_signed = true; +} + +//-------------------------------------------------------------------------- +static void op_K8(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_imm; + op->value = get_signed64(offset, 0xFF); + op->dtype = dt_byte; + op->tms_signed = true; +} + +//-------------------------------------------------------------------------- +static void op_K16(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_imm; + op->value = get_signed64(offset, 0xFFFF); + op->dtype = dt_word; + op->tms_signed = true; +} + +//-------------------------------------------------------------------------- +/* +static void op_K23(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_imm; + op->value = get_unsigned(offset, 0x7FFFFF); + op->dtype = dt_3byte; +} +*/ + +//-------------------------------------------------------------------------- +static void op_1(const mask_t *, int64, op_t *op, insn_t &, char &) +{ + op->type = o_imm; + op->value = 1; + op->dtype = dt_byte; +} + +//-------------------------------------------------------------------------- +static void op_min_1(const mask_t *, int64, op_t *op, insn_t &, char &) +{ + op->type = o_imm; + op->value = uval_t(-1); + op->dtype = dt_byte; + op->tms_signed = true; +} + +//-------------------------------------------------------------------------- +// registers + +static void op_src(const mask_t *, int64 offset, op_t *op, insn_t &, char &optional_op) // FSSS, FDDD +{ + op->type = o_reg; + op->dtype = dt_word; + op->reg = AC0 + uint16(offset); + optional_op = op->n; +} + +#define op_dst op_src +#define op_ACw op_src +#define op_ACx op_src +#define op_ACy op_src +#define op_ACz op_src +#define op_TAx op_src // ARx or Tx +#define op_TAy op_src // ARy or Ty + +// optional operand +static void opt_src(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // FSSS, FDDD +{ + if ( optional_op != -1 + && insn.ops[uchar(optional_op)].type == o_reg + && insn.ops[uchar(optional_op)].reg == AC0 + offset ) + { + return; // no operand if same than the source + } + // add the operand + op_src(mask, offset, op, insn, optional_op); + optional_op = -1; + insn.itype++; +} + +#define opt_dst opt_src +#define opt_ACy opt_src + + +#define op_reg(NAME, REG) \ + static void op_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &, char &)\ + { \ + op->type = o_reg; \ + op->dtype = dt_word; \ + op->reg = REG + uint16(offset); \ + } + +op_reg(Tx, T0) // op_Tx +op_reg(TCx, TC1) // op_TCx +op_reg(TRNx, TRN0) // op_TRNx +#define op_TCy op_TCx +op_reg(ARx, AR0) // op_ARx +op_reg(DPH, DPH) // op_DPH +op_reg(PDP, PDP) // op_PDP +op_reg(BK03, BK03) // op_BK03 +op_reg(BK47, BK47) // op_BK47 +op_reg(BKC, BKC) // op_BKC +op_reg(CSR, CSR) // op_CSR +op_reg(BRC0, BRC0) // op_BRC0 +op_reg(BRC1, BRC1) // op_BRC1 +op_reg(SP, SP) // op_SP +op_reg(SSP, SSP) // op_SSP +op_reg(CDP, CDP) // op_CDP +op_reg(RPTC, RPTC) // op_RPTC +op_reg(STx_55, ST0_55) // op_STx_55 +op_reg(DP, DP) // op_DP +op_reg(BSA01, BSA01) // op_BSA01 +op_reg(BSA23, BSA23) // op_BSA23 +op_reg(BSA45, BSA45) // op_BSA45 +op_reg(BSA67, BSA67) // op_BSA67 +op_reg(BSAC, BSAC) // op_BSAC +op_reg(TRN0, TRN0) // op_TRN0 +op_reg(TRN1, TRN1) // op_TRN1 +op_reg(TC1, TC1) // op_TC1 +op_reg(TC2, TC2) // op_TC2 +op_reg(CARRY, CARRY) // op_CARRY +op_reg(BORROW, BORROW) // op_BORROW +op_reg(RETA, RETA) // op_RETA +op_reg(MDP05, MDP05) // op_MDP05 +op_reg(MDP67, MDP67) // op_MDP67 + +//-------------------------------------------------------------------------- +static void op_xsrc(const mask_t *, int64 offset, op_t *op, insn_t &, char &) // XSSS, XDDD +{ // AC0 AC1 AC2 AC3 XSP XSSP XDP XCDP XAR0 -> XAR7 + static const ushort regs[] = + { + AC0, AC1, AC2, AC3, XSP, XSSP, XDP, XCDP, + XAR0, XAR1, XAR2, XAR3, XAR4, XAR5, XAR6, XAR7 + }; + op->type = o_reg; + op->dtype = dt_dword; + op->reg = regs[int(offset)]; +} +#define op_xdst op_xsrc + +//-------------------------------------------------------------------------- +static void op_Xmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // XXXMMM, YYYMMM +{ + op_ARx(mask, offset >> 3, op, insn, optional_op); + op->tms_modifier = TMS_MODIFIER_REG + (offset & 0x7); +} +#define op_Ymem op_Xmem + +//-------------------------------------------------------------------------- +static void op_Cmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // mm +{ + op_CDP(mask, 0, op, insn, optional_op); + op->tms_modifier = TMS_MODIFIER_REG + (offset & 0x3); +} + +//-------------------------------------------------------------------------- +static void op_mem( + const mask_t *mask, + int64 offset, + op_t *op, + op_dtype_t dtype, + insn_t &insn, + char optional_op, + bool ARn_mod = false) // AAAAAAAI +{ + insn.OpMem = 1 + op->n; + if ( !(offset & 1) ) // @dma + { // direct memory address + sel_t cpl = get_sreg(insn.ea, CPL); + if ( cpl == BADSEL ) + cpl = 0; + if ( !cpl ) + { // use DP + op->type = o_mem; + op->tms_regH = DPH; + op->tms_regP = DP; + op->addr = ea_t(offset >> 1); + op->tms_modifier = TMS_MODIFIER_DMA; + } + else + { // use SP + op->type = o_reg; + op->reg = SP; + op->value = ea_t(offset >> 1); + op->tms_modifier = TMS_MODIFIER_REG_OFFSET; + } + } + else + { // indirect memory access + if ( (offset & 0x1F) == 0x11 ) // xxx1 0001 + { + int bits = int(offset >> 5); + switch ( bits ) + { + case 0: // *ABS16(#k16) + op->type = o_mem; + op->tms_regH = DPH; + op->addr = (get_byte(insn.ea+insn.size) << 8) + | get_byte(insn.ea+insn.size+1); + op->tms_modifier = TMS_MODIFIER_ABS16; + insn.size += 2; + break; + case 1: // *(#k23) + op->type = o_mem; + op->addr = (get_byte(insn.ea+insn.size) << 16) + | (get_byte(insn.ea+insn.size+1) << 8) + | get_byte(insn.ea+insn.size+2); + op->tms_modifier = TMS_MODIFIER_PTR; + insn.size += 3; + break; + case 2: // port(#k16) + op->type = o_io; + op->addr = (get_byte(insn.ea+insn.size) << 8) + | get_byte(insn.ea+insn.size+1); + op->tms_modifier = TMS_MODIFIER_PORT; + insn.size += 2; + break; + case 3: // *CDP + case 4: // *CDP+ + case 5: // *CDP- + op_CDP(mask, 0, op, insn, optional_op); + op->tms_modifier= TMS_MODIFIER_REG + uchar(bits)-3; + break; + case 6: // *CDP(#K16) + case 7: // *+CDP(#K16) + op_CDP(mask, 0, op, insn, optional_op); + op->value = get_signed((get_byte(insn.ea+insn.size) << 8) + | get_byte(insn.ea+insn.size+1), 0xFFFF); + op->tms_modifier = TMS_MODIFIER_REG_OFFSET + uchar(bits)-6; + insn.size += 2; + break; + } + } + else + { + op_ARx(mask, offset >> 5, op, insn, optional_op); + int bits = (offset >> 1) & 0xF; + if ( (offset & 0x11) == 0x01 ) // xxx0 xxx1 + { + switch ( bits ) + { + case 0: // *ARn + case 1: // *ARn+ + case 2: // *ARn- + op->tms_modifier= TMS_MODIFIER_REG + uchar(bits); + break; + case 3: // *(ARn+T0) + op->tms_modifier= TMS_MODIFIER_REG_P_T0; + break; + case 4: // *(ARn-T0) + op->tms_modifier= TMS_MODIFIER_REG_M_T0; + break; + case 5: // *ARn(T0) + op->tms_modifier= TMS_MODIFIER_REG_T0; + break; + case 6: // *ARn(#K16) + case 7: // *+ARn(#K16) + op->value = get_signed((get_byte(insn.ea+insn.size) << 8) + | get_byte(insn.ea+insn.size+1), 0xFFFF); + op->tms_modifier = TMS_MODIFIER_REG_OFFSET + uchar(bits)-6; + insn.size += 2; + break; + } + } + else // xxx1 xxx1 + { + int lbits = (offset >> 1) & 0x7; + sel_t arms = get_sreg(insn.ea, ARMS); + if ( arms == BADSEL ) + arms = 0; + if ( ARn_mod || !arms ) + { + switch ( lbits ) + { + case 1: // *(ARn+T1) + op->tms_modifier= TMS_MODIFIER_REG_P_T1; + break; + case 2: // *(ARn-T1) + op->tms_modifier= TMS_MODIFIER_REG_M_T1; + break; + case 3: // *ARn(T1) + case 4: // *+ARn + case 5: // *-ARn + case 6: // *(ARn+T0B) + case 7: // *(ARn-T0B) + op->tms_modifier= TMS_MODIFIER_REG_T1 + uchar(lbits)-3; + break; + } + } + else + { // *ARn(short(#value)) + op->value = lbits; + op->tms_modifier = TMS_MODIFIER_REG_SHORT_OFFSET; + } + } + } + } + op->dtype = dtype; +} + +//-------------------------------------------------------------------------- +static void op_Smem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference +{ + op_mem(mask, offset, op, dt_word, insn, optional_op); +} + +//-------------------------------------------------------------------------- +static void op_Lmem(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference +{ + op_mem(mask, offset, op, dt_dword, insn, optional_op); +} + +//-------------------------------------------------------------------------- +static void op_ARn_mod(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference +{ + op_mem(mask, offset, op, dt_word, insn, optional_op, true); +} + +//-------------------------------------------------------------------------- +// @dma = bit number +static void op_Baddr(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // AAAAAAAI //-V669 'optional_op' argument is a non-constant reference +{ + if ( !(offset & 1) ) // @dma + { + op->type = o_imm; + op->value = ea_t(offset >> 1); + op->dtype = dt_byte; + op->tms_prefix = '@'; + op->tms_signed = false; + } + else + { + op_mem(mask, offset, op, dt_byte, insn, optional_op); + } +} + +//lint -emacro(572,fn_operator) excessive shift value +#define fn_operator(NAME, OPERATOR) \ + static void fn_##NAME(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) \ + { \ + if ( offset & 1 ) \ + { \ + get_last_op(op, insn); \ + op->tms_operator1 |= TMS_OPERATOR_##OPERATOR & 0xFF; \ + /*lint -e572 Excessive shift value*/ \ + op->tms_operator2 |= (TMS_OPERATOR_##OPERATOR >> 8); \ + } \ + } + +fn_operator(not, NOT) // fn_not +fn_operator(T3, T3) // fn_T3 U +fn_operator(uns, UNS) // fn_uns u +fn_operator(rnd, RND) // fn_rnd % +fn_operator(hb, HB) // fn_hb +fn_operator(lb, LB) // fn_lb +fn_operator(hi, HI) // fn_hi +fn_operator(lo, LO) // fn_lo +fn_operator(sat, SAT) // fn_sat = fn_uns +fn_operator(dbl, DBL) // fn_dbl +fn_operator(pair, PAIR) // fn_pair +fn_operator(dual, DUAL) // fn_dual + +//-------------------------------------------------------------------------- +static void op_BitIn(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_reg; + op->dtype = dt_byte; + op->reg = (offset & 1) ? TC2 : CARRY; +} +#define op_BitOut op_BitIn + +//-------------------------------------------------------------------------- +static void op_swap(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) +{ + insn.Op1.type = o_reg; + insn.Op1.dtype = dt_word; + insn.Op2.type = o_reg; + insn.Op2.dtype = dt_word; + switch ( offset ) + { + case 0x00: insn.Op1.reg = AC0; insn.Op2.reg = AC2; break; + case 0x01: insn.Op1.reg = AC1; insn.Op2.reg = AC3; break; + case 0x04: insn.Op1.reg = T0; insn.Op2.reg = T2; break; + case 0x05: insn.Op1.reg = T1; insn.Op2.reg = T3; break; + case 0x08: insn.Op1.reg = AR0; insn.Op2.reg = AR2; break; + case 0x09: insn.Op1.reg = AR1; insn.Op2.reg = AR3; break; + case 0x0C: insn.Op1.reg = AR4; insn.Op2.reg = T0; break; + case 0x0D: insn.Op1.reg = AR5; insn.Op2.reg = T1; break; + case 0x0E: insn.Op1.reg = AR6; insn.Op2.reg = T2; break; + case 0x0F: insn.Op1.reg = AR7; insn.Op2.reg = T3; break; + case 0x10: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AC0; insn.Op2.reg = AC2; break; + case 0x14: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = T0; insn.Op2.reg = T2; break; + case 0x18: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR0; insn.Op2.reg = AR2; break; + case 0x1C: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR4; insn.Op2.reg = T0; break; + case 0x1E: insn_1_P(mask, 1, op, insn, optional_op); insn.Op1.reg = AR6; insn.Op2.reg = T2; break; + case 0x2C: insn_1_4(mask, 1, op, insn, optional_op); insn.Op1.reg = AR4; insn.Op2.reg = T0; break; + case 0x38: insn.Op1.reg = AR0; insn.Op2.reg = AR1; break; + default: insn.itype = TMS320C55_null; + } +} + +//-------------------------------------------------------------------------- +// get address for the branch offset base +// in case of parallel execution, this is the end of the second, parallel instruction +static ea_t get_next_ip(insn_t &insn) +{ + ea_t next = insn.ip + insn.size; + if ( insn.size <= 3 ) + { + uchar nextbyte = get_byte(insn.ea + insn.size); + if ( nextbyte <= MAX_BYTE_USER_PARALLELIZED && (nextbyte & 1) ) + { + // next instruction is executed in parallel, so take it into account + insn_t tmp; + next += decode_insn(&tmp, insn.ea + insn.size); + } + } + return next; +} + +//-------------------------------------------------------------------------- +// code addresses + +static void op_l4(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // llll +{ + op->type = o_near; + op->addr = (get_next_ip(insn) + offset) & 0xFFFFFF; + op->dtype = dt_code; +} + +static void op_L7(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLL +{ + op->type = o_near; + op->addr = (get_next_ip(insn) + get_signed64(offset, 0x7F)) & 0xFFFFFF; + op->dtype = dt_code; +} + +static void op_L8(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLLL +{ + op->type = o_near; + op->addr = (get_next_ip(insn) + get_signed64(offset, 0xFF)) & 0xFFFFFF; + op->dtype = dt_code; +} + +static void op_L16(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // LLLLLLLL LLLLLLLL +{ + op->type = o_near; + op->addr = (get_next_ip(insn) + get_signed64(offset, 0xFFFF)) & 0xFFFFFF; + op->dtype = dt_code; +} + +static void op_pmad(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) +{ + op->type = o_near; + op->addr = (get_next_ip(insn) + offset) & 0xFFFFFF; + op->dtype = dt_code; +} + +static void op_P24(const mask_t *, int64, op_t *op, insn_t &insn, char &) // get_byte included +{ + op->type = o_near; + op->addr = (get_byte(insn.ea+insn.size+0) << 16) + | (get_byte(insn.ea+insn.size+1) << 8) + | get_byte(insn.ea+insn.size+2); + op->dtype = dt_code; + insn.size += 3; +} + +// data addresses + +static void op_D16(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_mem; + op->addr = ea_t(offset); + op->dtype = dt_word; +} + +// various + +static void op_SHIFTW(const mask_t *, int64 offset, op_t *op, insn_t &, char &) +{ + op->type = o_shift; + op->value = (signed short)get_signed64(offset, 0x3F); +} + +//-------------------------------------------------------------------------- +// shift left +static void shl_SHIFTW(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_SHIFTL_IMM; + op->tms_shift_value = (signed short)get_signed64(offset, 0x3F); + if ( short(op->tms_shift_value) < 0 ) + { + op->tms_shift = TMS_OP_SHIFTR_IMM; + op->tms_shift_value = -op->tms_shift_value; //lint !e2501 negation of value of unsigned type + } +} + +//-------------------------------------------------------------------------- +// shift left out of brackets +static void slo_SHIFTW(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) +{ + shl_SHIFTW(mask, offset, op, insn, optional_op); + op->tms_shift |= TMS_OP_SHIFT_OUT; +} + +//-------------------------------------------------------------------------- +// shift right +static void shl_SHFT(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_SHIFTL_IMM; + op->tms_shift_value = (uint16)offset; +} + +//-------------------------------------------------------------------------- +static void shl_Tx(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_SHIFTL_REG; + op->tms_shift_value = T0 + uint16(offset); +} + +//-------------------------------------------------------------------------- +static void shl_T2(const mask_t *, int64, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_SHIFTL_REG; + op->tms_shift_value = T2; +} + +//-------------------------------------------------------------------------- +static void shl_16(const mask_t *, int64, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_SHIFTL_IMM; + op->tms_shift_value = 16; +} + +//-------------------------------------------------------------------------- +static void shr(const mask_t *, int64 imm, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_SHIFTR_IMM; + op->tms_shift_value = uint16(imm); +} + +//-------------------------------------------------------------------------- +static void eq_K16(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_EQ; + op->tms_shift_value = (uint16)get_signed64(offset, 0xFFFF); +} + +//-------------------------------------------------------------------------- +static void neq_0(const mask_t *, int64, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_shift = TMS_OP_NEQ; + op->tms_shift_value = 0; +} + +//-------------------------------------------------------------------------- +static void RELOP(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) // cc +{ + get_last_op(op, insn); + op->type = o_relop; + op->tms_relop = offset & 0x3; +} + +//-------------------------------------------------------------------------- +static void RELOP_dst(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) +{ + get_last_op(op, insn); + op->tms_relop_type = TMS_RELOP_REG; + ushort sav = op->reg; + op_src(mask, offset, op, insn, optional_op); + op->type = o_relop; + op->value = op->reg; + op->reg = sav; +} + +//-------------------------------------------------------------------------- +static void RELOP_K8(const mask_t *, int64 offset, op_t *op, insn_t &insn, char &) +{ + get_last_op(op, insn); + op->tms_relop_type = TMS_RELOP_IMM; + op->value = (signed short)get_signed64(offset, 0xFF); +} + +//-------------------------------------------------------------------------- +static void op_cond(const mask_t *mask, int64 offset, op_t *op, insn_t &insn, char &optional_op) // CCC CCCC +{ + op->reg = 0; + if ( (offset>>4) <= 0x5 ) // <= 101 xxxx + { // src <comparison operator> 0 + op_src(mask, offset & 0xF, op, insn, optional_op); + op->type = o_cond; + op->value = offset & 0x70; + } + else if ( (offset>>2) == 0x18 ) // == 110 00xx + { // overflow(ACx) + op_src(mask, offset & 0x3, op, insn, optional_op); + op->type = o_cond; + op->value = offset & 0x7C; + } + else if ( (offset>>2) == 0x19 ) // == 110 01xx + { // TC1, TC2, CARRY, reserved + if ( offset == 0x67 ) // 110 0111 + insn.itype = TMS320C55_null; // reserved + else + { + op->type = o_cond; + op->value = (uval_t)offset; + } + } + else if ( (offset>>2) == 0x1A ) // == 110 10xx + { // TC1 & TC2, TC1 & !TC2, !TC1 & TC2, !TC1 & !TC2 + op->type = o_cond; + op->value = (uval_t)offset; + } + else if ( (offset>>2) == 0x1B ) // == 110 11xx + { + insn.itype = TMS320C55_null; // reserved + } + else if ( (offset>>2) == 0x1C ) // == 111 00xx + { // !overflow(ACx) + op_src(mask, offset & 0x3, op, insn, optional_op); + op->type = o_cond; + op->value = offset & 0x7C; + } + else + { + if ( offset == 0x77 ) // 111 0111 + insn.itype = TMS320C55_null; // reserved + else + { + op->type = o_cond; + op->value = (uval_t)offset; + } + } +} + +//-------------------------------------------------------------------------- +//lint -e648 overflow in computing constant for operator '<<': signed shift result (0x80000000) sets the sign bit of the shift expression's type ('int') and becomes negative expanded from macro 'OP_NOT' +static const mask_t masks[] = +{ + // 0000000E XDDDX000 error manual + { 0x000000, 0xFE0000, 3, TMS320C55_rptcc, {{ op_k8, 0x0000FF }, { op_cond, 0x007F00 }}}, + { 0x020000, 0xFE0000, 3, TMS320C55_retcc, {{ op_cond, 0x007F00 }}}, + { 0x040000, 0xFE0000, 3, TMS320C55_bcc, {{ op_L8, 0x0000FF }, { op_cond, 0x007F00 }}}, + { 0x060000, 0xFE0000, 3, TMS320C55_b, {{ op_L16, 0x00FFFF }}}, + { 0x080000, 0xFE0000, 3, TMS320C55_call, {{ op_L16, 0x00FFFF }}}, + // 0000101E GGGGGGGG Glllllll error manual + { 0x0C0000, 0xFE0000, 3, TMS320C55_rpt, {{ op_k16, 0x00FFFF }}}, + { 0x0E0000, 0xFE0000, 3, TMS320C55_rptb, {{ op_pmad, 0x00FFFF }}}, + { 0x100000, 0xFE0F00, 3, TMS320C55_and1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, + { 0x100100, 0xFE0F00, 3, TMS320C55_or1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, + { 0x100200, 0xFE0F00, 3, TMS320C55_xor1, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, + { 0x100300, 0xFE0F00, 3, TMS320C55_add2, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { op_ACy, 0x00C000 }}}, + { 0x100400, 0xFE0F00, 3, TMS320C55_sub2, {{ op_ACx, 0x003000 }, { shl_SHIFTW, 0x00003F }, { op_ACy, 0x00C000 }}}, + { 0x100500, 0xFE0F00, 3, TMS320C55_sfts2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, + { 0x100600, 0xFE0F00, 3, TMS320C55_sftsc2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, // SFTA + { 0x100700, 0xFE0F00, 3, TMS320C55_sftl2, {{ op_ACx, 0x003000 }, { op_SHIFTW, 0x00003F }, { opt_ACy, 0x00C000 }}}, + { 0x100800, 0xFE0F00, 3, TMS320C55_exp, {{ op_ACx, 0x003000 }, { op_Tx, 0x000030 }}}, + { 0x100900, 0xFE0F00, 3, TMS320C55_mant_nexp, {{ op_ACx, 0x003000 }, { op_ACy, 0x00C000 }, { blt_prll, 0 }, { op_ACx, 0x003000 }, { op_Tx, 0x000030 }}}, + { 0x100A00, 0xFE0F00, 3, TMS320C55_bcnt, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_TCx, 0x000001 }, { op_Tx, 0x000030 }}}, + { 0x100C00, 0xFE0F00, 3, TMS320C55_maxdiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }}}, + { 0x100D00, 0xFE0F00, 3, TMS320C55_dmaxdiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }, { op_TRNx, 0x000001 }}}, + { 0x100E00, 0xFE0F00, 3, TMS320C55_mindiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }}}, + { 0x100F00, 0xFE0F00, 3, TMS320C55_dmindiff, {{ op_ACx, 0x003000 }, { op_ACy, 0x0000C0 }, { op_ACz, 0x00C000 }, { op_ACw, 0x000030 }, { op_TRNx, 0x000001 }}}, + { 0x120000, 0xFE0300, 3, TMS320C55_cmp, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCx, 0x000001 }}}, + { 0x120100, 0xFE0308, 3, TMS320C55_cmpand, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { op_TCx, 0x000001 }}}, + { 0x120108, 0xFE0308, 3, TMS320C55_cmpand, {{ insn_1_U, 0x000004 }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { fn_not, OP_TRUE }, { op_TCx, 0x000001 }}}, + { 0x120200, 0xFE0308, 3, TMS320C55_cmpor, {{ insn_1_U, OP_NOT(0x000004) }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { op_TCx, 0x000001 }}}, + { 0x120208, 0xFE0308, 3, TMS320C55_cmpor, {{ insn_1_U, OP_NOT(0x000004) }, { op_src, 0x00F000 }, { RELOP, 0x000C00 }, { RELOP_dst, 0x0000F0 }, { op_TCy, 0x000002 }, { fn_not, OP_TRUE }, { op_TCx, 0x000001 }}}, + { 0x120300, 0xFE0308, 3, TMS320C55_rol, {{ op_BitOut, 0x000001 }, { op_src, 0x00F000 }, { op_BitIn, 0x000002 }, { op_dst, 0x0000F0 }}}, + { 0x120308, 0xFE0308, 3, TMS320C55_ror, {{ op_BitIn, 0x000002 }, { op_src, 0x00F000 }, { op_BitOut, 0x000001 }, { op_dst, 0x0000F0 }}}, + { 0x140000, 0xFE000F, 3, TMS320C55_aadd, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, + { 0x140001, 0xFE000F, 3, TMS320C55_amov, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, + { 0x140002, 0xFE000F, 3, TMS320C55_asub, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, + { 0x140004, 0xFE000F, 3, TMS320C55_aadd, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, + { 0x140005, 0xFE000F, 3, TMS320C55_amov, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, + { 0x140006, 0xFE000F, 3, TMS320C55_asub, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, + { 0x140008, 0xFE000F, 3, TMS320C55_aadd, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, + { 0x140009, 0xFE000F, 3, TMS320C55_amov, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, + { 0x14000A, 0xFE000F, 3, TMS320C55_asub, {{ op_TAx, 0x00F000 }, { op_TAy, 0x0000F0 }}}, + { 0x14000C, 0xFE000F, 3, TMS320C55_aadd, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, + { 0x14000D, 0xFE000F, 3, TMS320C55_amov, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, + { 0x14000E, 0xFE000F, 3, TMS320C55_asub, {{ op_k8, 0x00FF00 }, { op_TAx, 0x0000F0 }}}, + { 0x160000, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_DPH, 0 }}}, + { 0x160001, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_MDP05, 0 }}}, + { 0x160002, 0xFE000F, 3, TMS320C55_mov2, {{ op_k7, 0x0007F0 }, { op_MDP67, 0 }}}, + { 0x160003, 0xFE000F, 3, TMS320C55_mov2, {{ op_k9, 0x001FF0 }, { op_PDP, 0 }}}, + { 0x160004, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BK03, 0 }}}, + { 0x160005, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BK47, 0 }}}, + { 0x160006, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BKC, 0 }}}, + { 0x160008, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_CSR, 0 }}}, + { 0x160009, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BRC0, 0 }}}, + { 0x16000A, 0xFE000F, 3, TMS320C55_mov2, {{ op_k12, 0x00FFF0 }, { op_BRC1, 0 }}}, + // 0001011E xxxxxxxk kkkk11xx error manual + { 0x180000, 0xFE0000, 3, TMS320C55_and3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, + { 0x1A0000, 0xFE0000, 3, TMS320C55_or3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, + { 0x1C0000, 0xFE0000, 3, TMS320C55_xor3, {{ op_k8, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, + { 0x1E0000, 0xFE0002, 3, TMS320C55_mpyk2, {{ insn_1_R, 0x000001 }, { op_K8, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0x1E0002, 0xFE0002, 3, TMS320C55_mack3, {{ insn_1_R, 0x000001 }, { op_Tx, 0x00000C }, { op_K8, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0x20, 0xFE, 1, TMS320C55_nop }, + { 0x2200, 0xFE00, 2, TMS320C55_mov2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x2400, 0xFE00, 2, TMS320C55_add1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, + { 0x2600, 0xFE00, 2, TMS320C55_sub1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, + { 0x2800, 0xFE00, 2, TMS320C55_and2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x2A00, 0xFE00, 2, TMS320C55_or2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x2C00, 0xFE00, 2, TMS320C55_xor2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x2E00, 0xFE00, 2, TMS320C55_max1, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x3000, 0xFE00, 2, TMS320C55_min1, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x3200, 0xFE00, 2, TMS320C55_abs1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, + { 0x3400, 0xFE00, 2, TMS320C55_neg1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, + { 0x3600, 0xFE00, 2, TMS320C55_not1, {{ op_src, 0x00F0 }, { opt_dst, 0x000F }}}, + { 0x3800, 0xFE00, 2, TMS320C55_psh2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x3A00, 0xFE00, 2, TMS320C55_pop2, {{ op_src, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x3C00, 0xFE00, 2, TMS320C55_mov2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x3E00, 0xFE00, 2, TMS320C55_mov2, {{ op_min_k4, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x4000, 0xFE00, 2, TMS320C55_add2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x4200, 0xFE00, 2, TMS320C55_sub2, {{ op_k4, 0x00F0 }, { op_dst, 0x000F }}}, + { 0x4400, 0xFEC0, 2, TMS320C55_mov2, {{ op_ACx, 0x0030 }, { fn_hi, OP_TRUE }, { op_TAx, 0x000F }}}, + { 0x4440, 0xFED0, 2, TMS320C55_sfts2, {{ op_dst, 0x000F }, { op_min_1, 0 }}}, + { 0x4450, 0xFED0, 2, TMS320C55_sfts2, {{ op_dst, 0x000F }, { op_1, 0 }}}, + { 0x4480, 0xFEF0, 2, TMS320C55_mov2, {{ op_SP, 0 }, { op_TAx, 0x000F }}}, + { 0x4490, 0xFEF0, 2, TMS320C55_mov2, {{ op_SSP, 0 }, { op_TAx, 0x000F }}}, + { 0x44A0, 0xFEF0, 2, TMS320C55_mov2, {{ op_CDP, 0 }, { op_TAx, 0x000F }}}, + { 0x44C0, 0xFEF0, 2, TMS320C55_mov2, {{ op_BRC0, 0 }, { op_TAx, 0x000F }}}, + { 0x44D0, 0xFEF0, 2, TMS320C55_mov2, {{ op_BRC1, 0 }, { op_TAx, 0x000F }}}, + { 0x44E0, 0xFEF0, 2, TMS320C55_mov2, {{ op_RPTC, 0 }, { op_TAx, 0x000F }}}, + { 0x4600, 0xFE09, 2, TMS320C55_bclr2, {{ op_k4, 0x00F0 }, { op_STx_55, 0x0006 }}}, + { 0x4601, 0xFE09, 2, TMS320C55_bset2, {{ op_k4, 0x00F0 }, { op_STx_55, 0x0006 }}}, + // 0100011E xxxx1000 error manual + // 0100011E xxxx1001 error manual + // 0100011E xxxx1010 error manual + // 0100011E xxxx1100 error manual + { 0x4800, 0xFE07, 2, TMS320C55_rpt, {{ op_CSR, 0 }}}, + { 0x4801, 0xFE07, 2, TMS320C55_rptadd, {{ op_CSR, 0 }, { op_TAx, 0x00F0 }}}, + { 0x4802, 0xFE07, 2, TMS320C55_rptadd, {{ op_CSR, 0 }, { op_k4, 0x00F0 }}}, + { 0x4803, 0xFE07, 2, TMS320C55_rptsub, {{ op_CSR, 0 }, { op_k4, 0x00F0 }}}, + { 0x4804, 0xFE07, 2, TMS320C55_ret }, + { 0x4805, 0xFE07, 2, TMS320C55_reti }, + { 0x4A00, 0xFE80, 2, TMS320C55_b, {{ op_L7, 0x007F }}}, + { 0x4A80, 0xFE80, 2, TMS320C55_rptblocal, {{ op_pmad, 0x007F }}}, + { 0x4C00, 0xFE00, 2, TMS320C55_rpt, {{ op_k8, 0x00FF }}}, + { 0x4E00, 0xFE00, 2, TMS320C55_aadd, {{ op_K8, 0x00FF }, { op_SP, 0 }}}, + { 0x5000, 0xFE07, 2, TMS320C55_sftl2, {{ op_dst, 0x00F0 }, { op_1, 0 }}}, + { 0x5001, 0xFE07, 2, TMS320C55_sftl2, {{ op_dst, 0x00F0 }, { op_min_1, 0 }}}, + { 0x5002, 0xFE07, 2, TMS320C55_pop1, {{ op_dst, 0x00F0 }}}, + { 0x5003, 0xFE07, 2, TMS320C55_pop1, {{ op_ACx, 0x0030 }, { fn_dbl, OP_TRUE }}}, + { 0x5004, 0xFE07, 2, TMS320C55_popboth, {{ op_xsrc, 0x00F0 }}}, // not in documentation + { 0x5005, 0xFE07, 2, TMS320C55_pshboth, {{ op_xsrc, 0x00F0 }}}, // not in documentation + { 0x5006, 0xFE07, 2, TMS320C55_psh1, {{ op_dst, 0x00F0 }}}, + { 0x5007, 0xFE07, 2, TMS320C55_psh1, {{ op_ACx, 0x0030 }, { fn_dbl, OP_TRUE }}}, + { 0x5200, 0xFE0C, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_ACx, 0x0003 }, { fn_hi, OP_TRUE }}}, + { 0x5208, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_SP, 0 }}}, + { 0x5209, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_SSP, 0 }}}, + { 0x520A, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_CDP, 0 }}}, + { 0x520C, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_CSR, 0 }}}, + { 0x520D, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_BRC1, 0 }}}, + { 0x520E, 0xFE0F, 2, TMS320C55_mov2, {{ op_TAx, 0x00F0 }, { op_BRC0, 0 }}}, + { 0x5400, 0xFE0F, 2, TMS320C55_addv1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5401, 0xFE0F, 2, TMS320C55_addrv1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5402, 0xFE0E, 2, TMS320C55_sqa1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5404, 0xFE0E, 2, TMS320C55_sqs1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5406, 0xFE0E, 2, TMS320C55_mpy1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5408, 0xFE0E, 2, TMS320C55_sqr1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x540A, 0xFE0E, 2, TMS320C55_round1, {{ op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, // error manual: unused bits + { 0x540C, 0xFE0E, 2, TMS320C55_sat1, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5600, 0xFE02, 2, TMS320C55_mac3, {{ insn_1_R, 0x0001 }, { op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }, { op_ACy, 0x00C0 }}}, + { 0x5602, 0xFE02, 2, TMS320C55_mas2, {{ insn_1_R, 0x0001 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5800, 0xFE02, 2, TMS320C55_mpy2, {{ insn_1_R, 0x0001 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { opt_ACy, 0x00C0 }}}, + { 0x5802, 0xFE02, 2, TMS320C55_mac4, {{ insn_1_R, 0x0001 }, { op_ACy, 0x00C0 }, { op_Tx, 0x000C }, { op_ACx, 0x0030 }, { op_ACy, 0x00C0 }}}, + { 0x5A00, 0xFE03, 2, TMS320C55_add2, {{ op_ACx, 0x0030 }, { shl_Tx, 0x000C }, { op_ACy, 0x00C0 }}}, + { 0x5A01, 0xFE03, 2, TMS320C55_sub2, {{ op_ACx, 0x0030 }, { shl_Tx, 0x000C }, { op_ACy, 0x00C0 }}}, + { 0x5A02, 0xFE02, 2, TMS320C55_sftcc, {{ op_ACx, 0x00C0 }, { op_TCx, 0x0001 }}}, + { 0x5C00, 0xFE03, 2, TMS320C55_sftl2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}}, + { 0x5C01, 0xFE03, 2, TMS320C55_sfts2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}}, + { 0x5C02, 0xFE03, 2, TMS320C55_sftsc2, {{ op_ACx, 0x0030 }, { op_Tx, 0x000C }, { opt_ACy, 0x00C0 }}}, + { 0x5E00, 0xFEC0, 2, TMS320C55_swap, {{ op_swap, 0x003F }}}, + { 0x5E80, 0xFEC0, 2, TMS320C55_nop_16 }, + { 0x6000, 0xF800, 2, TMS320C55_bcc, {{ op_l4, 0x0780 }, { op_cond, 0x007F }}}, + { 0x6800, 0xFF00, 2, TMS320C55_bcc, {{ op_P24, 0 }, { op_cond, 0x007F }}}, // compiler bug + { 0x6900, 0xFF00, 2, TMS320C55_callcc, {{ op_P24, 0 }, { op_cond, 0x007F }}}, + { 0x6A, 0xFF, 1, TMS320C55_b, {{ op_P24, 0 }}}, + { 0x6C, 0xFF, 1, TMS320C55_call, {{ op_P24, 0 }}}, + { 0x6D000000, 0xFF000000, 4, TMS320C55_bcc, {{ op_L16, 0x0000FFFF }, { op_cond, 0x007F0000 }}}, + { 0x6E000000, 0xFF000000, 4, TMS320C55_callcc, {{ op_L16, 0x0000FFFF }, { op_cond, 0x007F0000 }}}, + { 0x6F000000, 0xFF000000, 4, TMS320C55_bcc, {{ insn_1_U, 0x00010000 }, { op_L8, 0x000000FF }, { op_src, 0x00F00000 }, { RELOP, 0x000C0000 }, { RELOP_K8, 0x0000FF00 }}}, + { 0x70000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x71000000, 0xFF000000, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x72000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x73000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x74000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x75000000, 0xFF000000, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { shl_SHFT, 0x0000000F }, { op_ACx, 0x00000030 }}}, + { 0x76000000, 0xFF00000C, 4, TMS320C55_bfxtr, {{ op_k16, 0x00FFFF00 }, { op_ACx, 0x00000003 }, { op_dst, 0x000000F0 }}}, + { 0x76000004, 0xFF00000C, 4, TMS320C55_bfxpa, {{ op_k16, 0x00FFFF00 }, { op_ACx, 0x00000003 }, { op_dst, 0x000000F0 }}}, + { 0x76000008, 0xFF00000C, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { op_dst, 0x000000F0 }}}, + { 0x77000000, 0xFF000000, 4, TMS320C55_amov, {{ op_D16, 0x00FFFF00 }, { op_TAx, 0x000000F0 }}}, + { 0x78000000, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_DP, 0 }}}, + { 0x78000002, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_SSP, 0 }}}, + { 0x78000004, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_CDP, 0 }}}, + { 0x78000006, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA01, 0 }}}, + { 0x78000008, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA23, 0 }}}, + { 0x7800000A, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA45, 0 }}}, + { 0x7800000C, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSA67, 0 }}}, + { 0x7800000E, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_BSAC, 0 }}}, + { 0x78000010, 0xFF00001E, 4, TMS320C55_mov2, {{ op_k16, 0x00FFFF00 }, { op_SP, 0 }}}, + { 0x79000000, 0xFF000002, 4, TMS320C55_mpyk2, {{ insn_1_R, 0x00000001 }, { op_K16, 0x00FFFF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x79000002, 0xFF000002, 4, TMS320C55_mack3, {{ insn_1_R, 0x00000001 }, { op_Tx, 0x0000000C }, { op_K16, 0x00FFFF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x7A000000, 0xFF00000E, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x7A000002, 0xFF00000E, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x7A000004, 0xFF00000E, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x7A000006, 0xFF00000E, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x7A000008, 0xFF00000E, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0x7A00000A, 0xFF00000E, 4, TMS320C55_mov2, {{ op_K16, 0x00FFFF00 }, { shl_16, 0, }, { op_ACx, 0x00000030 }}}, + { 0x7A00000C, 0xFF00000E, 4, TMS320C55_idle }, + { 0x7B000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x00FFFF00 }, { op_src, 0x0000000F }, { opt_dst, 0x000000F0 }}}, + { 0x7C000000, 0xFF000000, 4, TMS320C55_sub2, {{ op_K16, 0x00FFFF00 }, { op_src, 0x0000000F }, { opt_dst, 0x000000F0 }}}, + { 0x7D000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}}, + { 0x7E000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}}, + { 0x7F000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x00FFFF00 }, { op_src, 0x0000000F }, { op_dst, 0x000000F0 }}}, + { 0x800000, 0xFF000C, 3, TMS320C55_mov2, {{ op_Xmem, 0x00FC00 }, { fn_dbl, OP_TRUE, }, { op_Ymem, 0x0003F0 }, { fn_dbl, OP_TRUE }}}, + { 0x800004, 0xFF000C, 3, TMS320C55_mov2, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0 }}}, + { 0x800008, 0xFF000C, 3, TMS320C55_mov3, {{ op_ACx, 0x000003 }, { op_Xmem, 0x00FC00, }, { op_Ymem, 0x0003F0 }}}, + { 0x810000, 0xFF000C, 3, TMS320C55_add3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}}, + { 0x810004, 0xFF000C, 3, TMS320C55_sub3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}}, + { 0x810008, 0xFF000C, 3, TMS320C55_mov3, {{ op_Xmem, 0x00FC00 }, { op_Ymem, 0x0003F0, }, { op_ACx, 0x000003 }}}, + { 0x82000000, 0xFF000C00, 4, TMS320C55_mpy_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x82000400, 0xFF000C00, 4, TMS320C55_mac_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x82000800, 0xFF000C00, 4, TMS320C55_mas_mpy, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x82000C00, 0xFF000C00, 4, TMS320C55_amar_mpy, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}}, + { 0x83000000, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x83000400, 0xFF000C00, 4, TMS320C55_mas_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x83000800, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { shr, OP_IMM(16) }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x83000C00, 0xFF000C00, 4, TMS320C55_amar_mac, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}}, + { 0x84000000, 0xFF000C00, 4, TMS320C55_mas_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}}, + { 0x84000400, 0xFF000C00, 4, TMS320C55_amar_mac, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }, { shr, OP_IMM(16) }}}, + { 0x84000800, 0xFF000C00, 4, TMS320C55_mpy_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}}, + { 0x84000C00, 0xFF000C00, 4, TMS320C55_mac_mac, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { shr, OP_IMM(16) }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }, { shr, OP_IMM(16) }}}, + { 0x85000000, 0xFF000C00, 4, TMS320C55_amar_mas, {{ insn_1_2_R, 0x00000001 }, { insn_1_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x0000000C }}}, + { 0x85000400, 0xFF000C00, 4, TMS320C55_mas_mas, {{ insn_1_R_2_R, 0x00000001 }, { insn_1_40_2_40, 0x00000002 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACx, 0x00000030 }, { blt_prll, 0 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000080 }, { op_Cmem, 0x00000300 }, { fn_uns, 0x00000040 }, { op_ACy, 0x0000000C }}}, + { 0x85000800, 0xFF000C00, 4, TMS320C55_amar3, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }}}, + { 0x85000C00, 0xFF000C10, 4, TMS320C55_firsadd, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }, { op_ACx, 0x000000C0 }, { op_ACy, 0x0000000C }}}, // error manual: unused bits: DDx0DDU% p552 + { 0x85000C10, 0xFF000C10, 4, TMS320C55_firssub, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_Cmem, 0x00000300 }, { op_ACx, 0x000000C0 }, { op_ACy, 0x0000000C }}}, // error manual: unused bits: DDx0DDU% p552 + { 0x86000000, 0xFF0000E0, 4, TMS320C55_mpym3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000300 }}}, + { 0x86000020, 0xFF0000E0, 4, TMS320C55_macm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { opt_ACy, 0x00000300 }}}, + { 0x86000040, 0xFF0000E0, 4, TMS320C55_macm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { shr, OP_IMM(16) }, { opt_ACy, 0x00000300 }}}, + { 0x86000060, 0xFF0000E0, 4, TMS320C55_masm3, {{ insn_1_R, 0x00000001 }, { insn_1_40, 0x00000010 }, { op_Xmem, 0x00FC0000 }, { fn_uns, 0x00000008 }, { fn_T3, 0x00000002 }, { op_Ymem, 0x0003F000 }, { fn_uns, 0x00000004 }, { op_ACx, 0x00000C00 }, { opt_ACy, 0x00000300 }}}, + { 0x86000080, 0xFF0000E0, 4, TMS320C55_masm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACx, 0x00000C00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { shl_16, 0 }, { op_ACy, 0x00000300 }}}, + { 0x860000A0, 0xFF0000E0, 4, TMS320C55_macm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACx, 0x00000C00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { shl_16, 0 }, { op_ACy, 0x00000300 }}}, + { 0x860000C0, 0xFF0000E0, 4, TMS320C55_lms, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}}, + { 0x860000E0, 0xFF0000F0, 4, TMS320C55_sqdst, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}}, + { 0x860000F0, 0xFF0000F0, 4, TMS320C55_abdst, {{ op_Xmem, 0x00FC0000 }, { op_Ymem, 0x0003F000 }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }}}, + { 0x87000000, 0xFF0000E0, 4, TMS320C55_mpym_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, + { 0x87000020, 0xFF0000E0, 4, TMS320C55_macm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, + { 0x87000040, 0xFF0000E0, 4, TMS320C55_masm_mov, {{ insn_1_R_2, 0x00000001 }, { op_Xmem, 0x00FC0000 }, { fn_T3, 0x00000002 }, { op_Tx, 0x0000000C }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, + { 0x87000080, 0xFF0000E0, 4, TMS320C55_add_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACy, 0x00000300 }, { fn_hi, OP_TRUE, }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, + { 0x870000A0, 0xFF0000E0, 4, TMS320C55_sub_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACx, 0x00000C00 }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACy, 0x00000300 }, { fn_hi, OP_TRUE, }, { shl_T2, 0 }, { op_Ymem, 0x0003F000 }}}, + { 0x870000C0, 0xFF0000E0, 4, TMS320C55_mov_mov, {{ op_Xmem, 0x00FC0000 }, { shl_16, 0, }, { op_ACy, 0x00000300 }, { blt_prll, 0, }, { op_ACx, 0x00000C00 }, { fn_hi, OP_TRUE }, { shl_T2, 0, }, { op_Ymem, 0x0003F000 }}}, + { 0x8A0000A0, 0xFF0000F0, 4, TMS320C55_mov_mov, {{ op_Xmem, 0x00FC0000 }, { op_dst, 0x00000F00 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }, { op_dst, 0x0000000F }}}, + { make_longlong(0x00001000, 0x008A), make_longlong(0x0000F700, 0x00FF), 5, TMS320C55_mov_aadd, {{ op_Smem, 0xFF000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_src, 0x00000000F0 }, { op_dst, 0x0000F00000 }}}, + { make_longlong(0x0000D600, 0x008A), make_longlong(0x0000FF00, 0x00FF), 5, TMS320C55_mov_add, {{ op_Xmem, 0xFC000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_Ymem, 0x0003F00000 }, { op_dst, 0x00000000F0 }, { op_src, 0x000000000F }}}, + { make_longlong(0x0000E708, 0x008A), make_longlong(0x0000FF0C, 0x00FF), 5, TMS320C55_mov_mov, {{ op_Xmem, 0xFC000000 }, { op_dst, 0x000F0000 }, { blt_prll, 0 }, { op_ACx, 0x00000000C0 }, { shl_Tx, 0x0000000030 }, { fn_hi, OP_TRUE_5 }, { fn_rnd, 0x0000000001 }, { op_Ymem, 0x0003F00000 }}}, + { 0x8B0004B4, 0xFF000FFF, 4, TMS320C55_amar_amar, {{ op_Xmem, 0x00FC0000 }, { blt_prll, 0, }, { op_Ymem, 0x0003F000 }}}, + { make_longlong(0x00001400, 0x008C), make_longlong(0x0000F700, 0x00FF), 5, TMS320C55_mov_aadd, {{ op_src, 0x000F0000 }, { op_Smem, 0xFF000000 }, { blt_prll, 0 }, { op_k8, 0x00000000FF }, { op_dst, 0x0000F00000 }}}, + { make_longlong(0x000CB000, 0x008D), make_longlong(0x000FFC03, 0x00FF), 5, TMS320C55_btst_mov, {{ op_k4, 0x000000F0 }, { op_Xmem, 0xFC000000 }, { op_TCx, 0x00000001 }, { blt_prll, 0 }, { op_Ymem, 0x0003F00000 }, { shl_16, 0 }, { op_ACx, 0x00000300 }}}, + { make_longlong(0x061A0000, 0x8D00), make_longlong(0x0FF70000, 0xFF00), 6, TMS320C55_add_asub, {{ op_Smem, make_longlong(0x00000000, 0x00FF) }, { op_dst, make_longlong(0x0000F000, 0x0000) }, { op_src, 0x000000000F00 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0B100500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0B160500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_asub, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0D100800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { op_ACx, 0x000000003000 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0B140500, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_xdst, make_longlong(0x0000F000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0B140800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_ACx, make_longlong(0x00003000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0B100800, 0x8E00), make_longlong(0x0FF70F00, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_ACx, make_longlong(0x00003000, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { fn_dbl, OP_TRUE_6 }, { blt_prll, 0 }, { op_src, 0x0000000000F0 }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x06140000, 0x8E00), make_longlong(0x0FF70000, 0xFF00), 6, TMS320C55_mov_aadd, {{ op_k8, make_longlong(0x0000FF00, 0x0000) }, { op_Lmem, make_longlong(0x00000000, 0x00FF) }, { blt_prll, 0 }, { op_k8, 0x0000000000FF }, { op_dst, 0x0000F0000000 }}}, + { make_longlong(0x0DEB080D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_mov_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dbl, OP_TRUE_6 }, { op_ACx, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1) }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dual, OP_TRUE_6 }}}, + { make_longlong(0x0EEB040D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_sub_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1 ) }, { op_Ymem, make_longlong(0xF0000000, 0x03) }, { fn_dual, OP_TRUE_6 }}}, + { make_longlong(0x0EEB000D, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_add_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { shr, OP_IMM_6(1 ) }, { op_Ymem, make_longlong(0xF0000000, 0x03) }, { fn_dual, OP_TRUE_6 }}}, + { make_longlong(0x0EEB0408, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_sub_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dbl, OP_TRUE_6 }}}, + { make_longlong(0x0EEB0008, 0x8E00), make_longlong(0x0FFF0F0F, 0xFF00), 6, TMS320C55_add_mov, {{ op_Xmem, make_longlong(0x00000000, 0x00FC) }, { fn_dual, OP_TRUE_6 }, { op_ACx, 0x00000000C000 }, { op_ACy, 0x000000003000 }, { blt_prll, 0 }, { op_ACx, 0x000000000030 }, { op_Ymem, make_longlong(0xF0000000, 0x0003) }, { fn_dbl, OP_TRUE_6 }}}, + + // 10001xxx error manual + { 0x9000, 0xFF00, 2, TMS320C55_mov2, {{op_xsrc, 0x00F0 }, {op_xdst, 0x000F}}}, + { 0x9100, 0xFF00, 2, TMS320C55_b, {{ op_ACx, 0x0003 }}}, + { 0x9200, 0xFF00, 2, TMS320C55_call, {{ op_ACx, 0x0003 }}}, + { 0x9400, 0xFF00, 2, TMS320C55_reset }, + { 0x9500, 0xFF80, 2, TMS320C55_intr, {{ op_k5, 0x001F }}}, + { 0x9580, 0xFF80, 2, TMS320C55_trap, {{ op_k5, 0x001F }}}, + { 0x9600, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }}}, + { 0x9680, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}}, + // 10010111 error manual + // mmap() + // port() + // <instruction>.LR + // <instruction>.CR + { 0x9E00, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }, { insn_UP, 0 }}}, + { 0x9E80, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}}, + { 0x9F00, 0xFF80, 2, TMS320C55_xcc, {{ op_cond, 0x007F }}}, + { 0x9F80, 0xFF80, 2, TMS320C55_xccpart, {{ op_cond, 0x007F }}}, + { 0xA000, 0xF000, 2, TMS320C55_mov2, {{ op_Smem, 0x00FF }, { op_dst, 0x0F00 }}}, + { 0xB000, 0xFC00, 2, TMS320C55_mov2, {{ op_Smem, 0x00FF }, { shl_16, 0 }, { op_ACx, 0x0300 }}}, + { 0xB400, 0xFF00, 2, TMS320C55_amar1, {{ op_Smem, 0x00FF }}}, + { 0xB500, 0xFF00, 2, TMS320C55_psh1, {{ op_Smem, 0x00FF }}}, + { 0xB600, 0xFF00, 2, TMS320C55_delay, {{ op_Smem, 0x00FF }}}, + { 0xB700, 0xFF00, 2, TMS320C55_psh1, {{ op_Lmem, 0x00FF }, { fn_dbl, OP_TRUE }}}, + { 0xB800, 0xFF00, 2, TMS320C55_pop1, {{ op_Lmem, 0x00FF }, { fn_dbl, OP_TRUE }}}, + { 0xBB00, 0xFF00, 2, TMS320C55_pop1, {{ op_Smem, 0x00FF }}}, + { 0xBC00, 0xFC00, 2, TMS320C55_mov2, {{ op_ACx, 0x0300 }, { fn_hi, OP_TRUE }, { op_Smem, 0x00FF }}}, + { 0xC000, 0xF000, 2, TMS320C55_mov2, {{ op_src, 0x0F00 }, { op_Smem, 0x00FF }}}, + { 0xD00000, 0xFF0040, 3, TMS320C55_macmz, {{ op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, + { 0xD00040, 0xFF0040, 3, TMS320C55_macmrz, {{ op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, + { 0xD10000, 0xFF000C, 3, TMS320C55_mpym3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, + { 0xD10004, 0xFF000C, 3, TMS320C55_macm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, + { 0xD10008, 0xFF000C, 3, TMS320C55_masm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Cmem, 0x000003 }, { op_ACx, 0x000030 }}}, + { 0xD20000, 0xFF000C, 3, TMS320C55_macm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD20004, 0xFF000C, 3, TMS320C55_masm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD20008, 0xFF000C, 3, TMS320C55_sqam2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD2000C, 0xFF000C, 3, TMS320C55_sqsm2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD30000, 0xFF000C, 3, TMS320C55_mpym2, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD30008, 0xFF000C, 3, TMS320C55_sqrm, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_ACx, 0x000030 }}}, + { 0xD30004, 0xFF0004, 3, TMS320C55_mpym3, {{ insn_1_R, 0x000040 }, { insn_1_U, 0x000008 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x000003 }, { op_ACx, 0x000030 }}}, + { 0xD40000, 0xFF0000, 3, TMS320C55_macm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x00000C }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD50000, 0xFF0000, 3, TMS320C55_masm3, {{ insn_1_R, 0x000040 }, { op_Smem, 0x00FF00 }, { fn_T3, 0x000080 }, { op_Tx, 0x00000C }, { op_ACx, 0x000003 }, { opt_ACy, 0x000030 }}}, + { 0xD60000, 0xFF0000, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { opt_dst, 0x0000F0 }}}, + { 0xD70000, 0xFF0000, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { opt_dst, 0x0000F0 }}}, + { 0xD80000, 0xFF0000, 3, TMS320C55_sub3, {{ op_src, 0x00000F }, { op_Smem, 0x00FF00 }, { op_dst, 0x0000F0 }}}, + { 0xD90000, 0xFF0000, 3, TMS320C55_and3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, + { 0xDA0000, 0xFF0000, 3, TMS320C55_or3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, + { 0xDB0000, 0xFF0000, 3, TMS320C55_xor3, {{ op_Smem, 0x00FF00 }, { op_src, 0x00000F }, { op_dst, 0x0000F0 }}}, + { 0xDC0000, 0xFF0002, 3, TMS320C55_btst, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TCx, 0x000001 }}}, + { 0xDC0002, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_DP, 0 }}}, + { 0xDC0012, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_CDP, 0 }}}, + { 0xDC0022, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA01, 0 }}}, + { 0xDC0032, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA23, 0 }}}, + { 0xDC0042, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA45, 0 }}}, + { 0xDC0052, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSA67, 0 }}}, + { 0xDC0062, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BSAC, 0 }}}, + { 0xDC0072, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_SP, 0 }}}, + { 0xDC0082, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_SSP, 0 }}}, + { 0xDC0092, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BK03, 0 }}}, + { 0xDC00A2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BK47, 0 }}}, + { 0xDC00B2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BKC, 0 }}}, + { 0xDC00C2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_DPH, 0 }}}, + { 0xDC00D2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_MDP05, 0 }}}, + { 0xDC00E2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_MDP67, 0 }}}, + { 0xDC00F2, 0xFF00F3, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_PDP, 0 }}}, + { 0xDC0003, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_CSR, 0 }}}, + { 0xDC0013, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BRC0, 0 }}}, + { 0xDC0023, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_BRC1, 0 }}}, + { 0xDC0033, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_TRN0, 0 }}}, + { 0xDC0043, 0xFF0073, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_TRN1, 0 }}}, + { 0xDD0000, 0xFF0003, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDD0001, 0xFF0003, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDD0002, 0xFF0003, 3, TMS320C55_addsub2cc, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_Tx, 0x00000C }, { op_TC1, 0, }, { op_TC2, 0, }, { op_ACy, 0x000030 }}}, + { 0xDD0003, 0xFF0003, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { shl_Tx, 0x00000C }, { fn_rnd, 0x000040 }, { op_ACx, 0x000030 }}}, + { 0xDE0000, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC1, 0 }, { op_ACy, 0x000030 }}}, + { 0xDE0001, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC2, 0 }, { op_ACy, 0x000030 }}}, + { 0xDE0002, 0xFF000F, 3, TMS320C55_addsubcc4, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { op_TC1, 0 }, { op_TC2, 0, }, { op_ACy, 0x000030 }}}, + { 0xDE0003, 0xFF000F, 3, TMS320C55_subc2, {{ op_Smem, 0x00FF00 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDE0004, 0xFF000F, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDE0005, 0xFF000F, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDE0006, 0xFF000F, 3, TMS320C55_sub3, {{ op_ACx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { shl_16, 0 }, { op_ACy, 0x000030 }}}, + { 0xDE0008, 0xFF000F, 3, TMS320C55_addsub, {{ op_Tx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { op_ACx, 0x000030 }}}, + { 0xDE0009, 0xFF000F, 3, TMS320C55_subadd, {{ op_Tx, 0x0000C0 }, { op_Smem, 0x00FF00 }, { op_ACx, 0x000030 }}}, + { 0xDF0000, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }, { fn_uns, OP_NOT(0x000001) }, { op_dst, 0x0000F0 }}}, + { 0xDF0002, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }, { fn_uns, OP_NOT(0x000001) }, { op_dst, 0x0000F0 }}}, + { 0xDF0004, 0xFF000E, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x000030 }}}, + { 0xDF0008, 0xFF000E, 3, TMS320C55_add3, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_CARRY, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDF000A, 0xFF000E, 3, TMS320C55_sub3, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_BORROW, 0 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDF000C, 0xFF000E, 3, TMS320C55_add2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xDF000E, 0xFF000E, 3, TMS320C55_sub2, {{ op_Smem, 0x00FF00 }, { fn_uns, 0x000001 }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xE00000, 0xFF0000, 3, TMS320C55_btst, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TCx, 0x000001 }}}, + { 0xE10000, 0xFF0000, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }, { slo_SHIFTW, 0x00003F }, { op_ACx, 0x0000C0 }}}, + { 0xE20000, 0xFF0000, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }, { slo_SHIFTW, 0x00003F }, { op_ACx, 0x0000C0 }}}, + { 0xE30000, 0xFF000E, 3, TMS320C55_btstset, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}}, + { 0xE30002, 0xFF000E, 3, TMS320C55_btstset, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}}, + { 0xE30004, 0xFF000E, 3, TMS320C55_btstclr, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}}, + { 0xE30006, 0xFF000E, 3, TMS320C55_btstclr, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}}, + { 0xE30008, 0xFF000E, 3, TMS320C55_btstnot, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC1 }}}, + { 0xE3000A, 0xFF000E, 3, TMS320C55_btstnot, {{ op_k4, 0x0000F0 }, { op_Smem, 0x00FF00 }, { op_TC2 }}}, + { 0xE3000C, 0xFF000F, 3, TMS320C55_bset2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, + { 0xE3000D, 0xFF000F, 3, TMS320C55_bclr2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, + { 0xE3000E, 0xFF000E, 3, TMS320C55_bnot, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, + { 0xE40000, 0xFF0004, 3, TMS320C55_psh2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, + { 0xE40004, 0xFF0004, 3, TMS320C55_pop2, {{ op_dst, 0x0000F0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50004, 0xFF000D, 3, TMS320C55_mov2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { fn_hb, OP_TRUE }}}, + { 0xE50005, 0xFF000D, 3, TMS320C55_mov2, {{ op_src, 0x0000F0 }, { op_Smem, 0x00FF00 }, { fn_lb, OP_TRUE }}}, + { 0xE50008, 0xFF00FC, 3, TMS320C55_mov2, {{ op_DP, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50018, 0xFF00FC, 3, TMS320C55_mov2, {{ op_CDP, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50028, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA01, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50038, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA23, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50048, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA45, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50058, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSA67, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50068, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BSAC, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50078, 0xFF00FC, 3, TMS320C55_mov2, {{ op_SP, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50088, 0xFF00FC, 3, TMS320C55_mov2, {{ op_SSP, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE50098, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BK03, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE500A8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BK47, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE500B8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_BKC, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE500C8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_DPH, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE500D8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_MDP05, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE500E8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_MDP67, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE500F8, 0xFF00FC, 3, TMS320C55_mov2, {{ op_PDP, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE5000C, 0xFF007C, 3, TMS320C55_mov2, {{ op_CSR, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE5001C, 0xFF007C, 3, TMS320C55_mov2, {{ op_BRC0, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE5002C, 0xFF007C, 3, TMS320C55_mov2, {{ op_BRC1, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE5003C, 0xFF007C, 3, TMS320C55_mov2, {{ op_TRN0, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE5004C, 0xFF007C, 3, TMS320C55_mov2, {{ op_TRN1, 0 }, { op_Smem, 0x00FF00 }}}, + { 0xE60000, 0xFF0000, 3, TMS320C55_mov2, {{ op_K8, 0x0000FF }, { op_Smem, 0x00FF00 }}}, + { 0xE70000, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { op_Smem, 0x00FF00 }}}, + { 0xE70008, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { fn_hi, OP_TRUE, }, { fn_rnd, 0x000001 }, { op_Smem, 0x00FF00 }}}, + { 0xE7000C, 0xFF000C, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_Tx, 0x000030 }, { fn_sat, OP_TRUE, }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { fn_uns, 0x000002 }, { op_Smem, 0x00FF00 }}}, + { 0xE80000, 0xFF0004, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { op_Smem, 0x00FF00 }}}, + { 0xE80004, 0xFF0004, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { fn_sat, OP_TRUE }, { fn_hi, OP_TRUE }, { fn_rnd, 0x000001 }, { fn_uns, 0x000002 }, { op_Smem, 0x00FF00 }}}, + { 0xE90000, 0xFF0000, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_SHIFTW, 0x00003F }, { op_Smem, 0x00FF00 }}}, + { 0xEA0000, 0xFF0000, 3, TMS320C55_mov2, {{ op_ACx, 0x0000C0 }, { shl_SHIFTW, 0x00003F }, { fn_hi, OP_TRUE }, { op_Smem, 0x00FF00 }}}, + { 0xEB0004, 0xFF000D, 3, TMS320C55_mov2, {{ op_RETA, 0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEB0005, 0xFF000D, 3, TMS320C55_mov2, {{ op_xsrc, 0x0000F0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, // not in documentation + { 0xEB0008, 0xFF000D, 3, TMS320C55_mov2, {{ op_ACx, 0x000030 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEB0009, 0xFF000D, 3, TMS320C55_mov2, {{ op_ACx, 0x000030 }, { fn_sat, OP_TRUE }, { fn_uns, 0x000002 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEB000C, 0xFF000F, 3, TMS320C55_mov2, {{ op_TAx, 0x0000F0 }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEB000D, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { shr, OP_IMM(1) }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }}}, + { 0xEB000E, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { fn_hi, OP_TRUE }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEB000F, 0xFF000F, 3, TMS320C55_mov2, {{ op_ACx, 0x0000F0 }, { fn_lo, OP_TRUE }, { fn_pair, OP_TRUE }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEC0000, 0xFF000E, 3, TMS320C55_bset2, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, + { 0xEC0002, 0xFF000E, 3, TMS320C55_bclr2, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, + { 0xEC0004, 0xFF000E, 3, TMS320C55_btstp, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, + { 0xEC0006, 0xFF000E, 3, TMS320C55_bnot, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }}}, + { 0xEC0008, 0xFF000E, 3, TMS320C55_btst, {{ op_Baddr, 0x00FF00 }, { op_src, 0x0000F0 }, { op_TCx, 0x000001 }}}, + { 0xEC000E, 0xFF000F, 3, TMS320C55_amar2, {{ op_Smem, 0x00FF00 }, { op_xdst, 0x0000F0 }}}, + { 0xED0000, 0xFF000E, 3, TMS320C55_add2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xED0002, 0xFF000E, 3, TMS320C55_sub2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xED0004, 0xFF000E, 3, TMS320C55_sub3, {{ op_ACx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACy, 0x000030 }}}, + { 0xED0006, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_RETA, 0 }}}, + { 0xED0008, 0xFF000E, 3, TMS320C55_mov2, {{ insn_1_40, 0x000001 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }}}, + { 0xED000A, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }, { fn_hi, OP_TRUE, }, { fn_pair, OP_TRUE }}}, + { 0xED000C, 0xFF000E, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_ACx, 0x000030 }, { fn_lo, OP_TRUE, }, { fn_pair, OP_TRUE }}}, + { 0xED000E, 0xFF000F, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_TAx, 0x0000F0 }, { fn_pair, OP_TRUE }}}, + { 0xED000F, 0xFF000F, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_xdst, 0x0000F0 }}}, + { 0xEE0000, 0xFF000E, 3, TMS320C55_add2, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xEE0002, 0xFF000E, 3, TMS320C55_sub2, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { opt_ACy, 0x000030 }}}, + { 0xEE0004, 0xFF000E, 3, TMS320C55_sub3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x0000C0 }, { op_ACy, 0x000030 }}}, + { 0xEE0006, 0xFF000E, 3, TMS320C55_sub3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_Tx, 0x0000C0 }, { op_ACx, 0x000030 }}}, + { 0xEE0008, 0xFF000E, 3, TMS320C55_add3, {{ op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_Tx, 0x0000C0 }, { op_ACx, 0x000030 }}}, + { 0xEE000A, 0xFF000E, 3, TMS320C55_sub3, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}}, + { 0xEE000C, 0xFF000E, 3, TMS320C55_addsub, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}}, + { 0xEE000E, 0xFF000E, 3, TMS320C55_subadd, {{ op_Tx, 0x0000C0 }, { op_Lmem, 0x00FF00 }, { fn_dual, OP_TRUE }, { op_ACx, 0x000030 }}}, + { 0xEF0000, 0xFF000C, 3, TMS320C55_mov2, {{ op_Cmem, 0x000003 }, { op_Smem, 0x00FF00 }}}, + { 0xEF0004, 0xFF000C, 3, TMS320C55_mov2, {{ op_Smem, 0x00FF00 }, { op_Cmem, 0x000003 }}}, + { 0xEF0008, 0xFF000C, 3, TMS320C55_mov2, {{ op_Cmem, 0x000003 }, { op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }}}, + { 0xEF000C, 0xFF000C, 3, TMS320C55_mov2, {{ op_Lmem, 0x00FF00 }, { fn_dbl, OP_TRUE }, { op_Cmem, 0x000003 }}}, + { 0xF0000000, 0xFF000000, 4, TMS320C55_cmp, {{ op_Smem, 0x00FF0000 }, { eq_K16, 0x0000FFFF }, { op_TC1, 0 }}}, + { 0xF1000000, 0xFF000000, 4, TMS320C55_cmp, {{ op_Smem, 0x00FF0000 }, { eq_K16, 0x0000FFFF }, { op_TC2, 0 }}}, + { 0xF2000000, 0xFF000000, 4, TMS320C55_band, {{ op_Smem, 0x00FF0000 }, { op_k16, 0x0000FFFF }, { op_TC1, 0 }}}, + { 0xF3000000, 0xFF000000, 4, TMS320C55_band, {{ op_Smem, 0x00FF0000 }, { op_k16, 0x0000FFFF }, { op_TC2, 0 }}}, + { 0xF4000000, 0xFF000000, 4, TMS320C55_and2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, + { 0xF5000000, 0xFF000000, 4, TMS320C55_or2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, + { 0xF6000000, 0xFF000000, 4, TMS320C55_xor2, {{ op_k16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, + { 0xF7000000, 0xFF000000, 4, TMS320C55_add2, {{ op_K16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, + { 0xF8000000, 0xFF000004, 4, TMS320C55_mpymk, {{ insn_1_R, 0x00000001 }, { op_Smem, 0x00FF0000 }, { fn_T3, 0x00000002 }, { op_K8, 0x0000FF00 }, { op_ACx, 0x00000030 }}}, + { 0xF8000004, 0xFF000004, 4, TMS320C55_macmk3, {{ insn_1_R, 0x00000001 }, { op_Smem, 0x00FF0000 }, { fn_T3, 0x00000002 }, { op_K8, 0x0000FF00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0xF9000000, 0xFF00000C, 4, TMS320C55_add2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0xF9000004, 0xFF00000C, 4, TMS320C55_sub2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x000000C0 }, { opt_ACy, 0x00000030 }}}, + { 0xF9000008, 0xFF00000C, 4, TMS320C55_mov2, {{ op_Smem, 0x00FF0000 }, { fn_uns, 0x00008000 }, { slo_SHIFTW, 0x00003F00 }, { op_ACx, 0x00000030 }}}, + { 0xFA000000, 0xFF000004, 4, TMS320C55_mov2, {{ op_ACx, 0x000000C0 }, { shl_SHIFTW, 0x00003F00 }, { fn_hi, OP_TRUE }, { fn_rnd, 0x00000001 }, { op_Smem, 0x00FF0000 }}}, + { 0xFA000004, 0xFF000004, 4, TMS320C55_mov2, {{ op_ACx, 0x000000C0 }, { shl_SHIFTW, 0x00003F00 }, { fn_sat, OP_TRUE }, { fn_hi, OP_TRUE }, { fn_rnd, 0x00000001 }, { fn_uns, 0x00008000 }, { op_Smem, 0x00FF0000 }}}, + { 0xFB000000, 0xFF000000, 4, TMS320C55_mov2, {{ op_K16, 0x0000FFFF }, { op_Smem, 0x00FF0000 }}}, + { 0xFC000000, 0xFF000000, 4, TMS320C55_bcc, {{ op_L16, 0x0000FFFF }, { op_ARn_mod, 0x00FF0000 }, { neq_0, OP_TRUE }}}, + { 0, 0, 0, TMS320C55_null } +}; + +//-------------------------------------------------------------------------- +// unpack an "sdual" instruction operand ( 6->8 bits ) +static uchar unpack_opsdual(uchar packed) +{ + static const uchar lowpart[8] = { 0, 1, 2, 3, 9, 4, 10, 5 }; + return ((lowpart[packed&7] | ((packed<<1) & 0x70)) << 1) | 1; +} + +//-------------------------------------------------------------------------- +// unpack an "sdual" instruction +// these are probably instructions from C55x+ processor +static bool unpack_sdual(ea_t ea, bytevec_t *insn1, bytevec_t *insn2) +{ + // sdual instruction packs two parallel instructions + uint32 word = 0; + for ( int i=0; i < 4; i++ ) + word = (word << 8) | get_byte(ea + i); + uchar opc1 = ((word >> 20) & 0xF0) | ((word >> 8) & 0x0F); + uchar opc2 = (word & 0xFF); + if ( opc2 & 0x80 ) + { + // 3 | 2 | 1 | + // 1098 7654|321098 76|5432 1098|76543210 + // | | | + // 1000 1011|100010 10|1001 1100|11000001 + // o1h | opd1 opd2 o1l| opc2 + // + // opcode1 = o1h:o1l + // opcode2 = opc2 + // opd1 and opd2 are packed operand parts + + uchar ops1 = (word >> 18) & 0x3F; + uchar ops2 = (word >> 12) & 0x3F; + int insn1_len = get_insn_size(masks, opc1<<24); + if ( insn1_len < 2 ) + return false; + int insn2_len = get_insn_size(masks, opc2<<24); + if ( insn2_len < 2 ) + { + // try to add extra bytes (skip operand byte) + uint32 w2 = (opc2<<24) | (get_byte(ea + insn1_len+2) << 8); + insn2_len = get_insn_size(masks, w2); + if ( insn2_len < 2 ) + { + w2 |= get_byte(ea + insn1_len+3); + insn2_len = get_insn_size(masks, w2); + } + } + if ( insn2_len < 2 ) + return false; + if ( insn1 ) + { + insn1->clear(); + // add real opcode and operands + insn1->push_back(opc1); + insn1->push_back(unpack_opsdual(ops1)); + // add extra bytes + for ( int i=4; i < insn1_len+2; i++ ) + insn1->push_back(get_byte(ea + i)); + } + if ( insn2 ) + { + insn2->clear(); + insn2->push_back(opc2); + insn2->push_back(unpack_opsdual(ops2)); + for ( int i=insn1_len+2; i < (insn1_len+insn2_len); i++ ) + insn2->push_back(get_byte(ea + i)); + } + } + else + { + // unpacked insn1 can be 2, 3, or 4 bytes + // insn2 is always 3 bytes + // + // source bytes: ab cd ef gh ij kl mn op + // case 2+3: + // insn1 = bf cd + // insn2 = g4 ij eh + // case 3+3: + // insn1 = bf cd ij + // insn2 = g4 kl eh + // case 4+3: + // insn1 = bf cd ij kl + // insn2 = g4 mn eh + uint32 w1 = (opc1<<24) | (word & 0x00FF0000); // bfcd0000 + uint32 w2 = (((word&0xF0)|4)<<24) | (word&0xF000) | ((word&0x0F)<<8); // g400eh00 + int insn1_len = get_insn_size(masks, w1); + if ( insn1_len == 0 ) + { + // try to add one byte + w1 |= (get_byte(ea + 4) << 8); + insn1_len = get_insn_size(masks, w1); + if ( insn1_len == 0 || insn1_len < 3 ) + { + w1 |= get_byte(ea + 5); + insn1_len = get_insn_size(masks, w1); + if ( insn1_len != 4 ) + return false; + } + } + int insn2_len = get_insn_size(masks, w2); + if ( insn1_len < 2 || insn2_len != 3 ) + return false; + if ( insn1 ) + { + insn1->clear(); + insn1->push_back((w1>>24)&0xFF); + insn1->push_back((w1>>16)&0xFF); + // add extra bytes + for ( int i=4; i < insn1_len + 2; i++ ) + insn1->push_back(get_byte(ea + i)); + } + if ( insn2 ) + { + insn2->clear(); + insn2->push_back((w2>>24)&0xFF); + insn2->push_back(get_byte(ea + insn1_len + 2)); + insn2->push_back((w2>>8)&0xFF); + } + } + return true; +} + +//-------------------------------------------------------------------------- +void ana_status_bits(insn_t &insn) +{ + if ( (insn.itype == TMS320C55_bclr2 || insn.itype == TMS320C55_bset2) + && insn.Op2.type == o_reg + && insn.Op1.type == o_imm ) + { + int reg = -1; + switch ( insn.Op2.reg ) + { + case ST0_55: + { + static const int regs[] = + { + -1, -1, -1, -1, -1, -1, -1, -1, + -1, ACOV1, ACOV0, CARRY, TC2, TC1, ACOV3, ACOV2 + }; + reg = regs[int(insn.Op1.value)]; + break; + } + case ST1_55: + { + static const int regs[] = + { + -1, -1, -1, -1, -1, C54CM, FRCT, C16, + SXMD, SATD, M40, INTM, HM, XF, CPL, BRAF + }; + reg = regs[int(insn.Op1.value)]; + break; + } + case ST2_55: + { + static const int regs[] = + { + AR0LC, AR1LC, AR2LC, AR3LC, AR4LC, AR5LC, AR6LC, AR7LC, + CDPLC, -1, RDM, EALLOW, DBGM, -1, -1, ARMS + }; + reg = regs[int(insn.Op1.value)]; + break; + } + case ST3_55: + { + static const int regs[] = + { + SST, SMUL, CLKOFF, -1, -1, SATA, MPNMC, CBERR, + -1, -1, -1, -1, HINT, CACLR, CAEN, CAFRZ + }; + reg = regs[int(insn.Op1.value)]; + break; + } + } + if ( reg != -1 ) + { + insn.itype = (insn.itype == TMS320C55_bclr2) ? TMS320C55_bclr1 : TMS320C55_bset1; + insn.Op1.type = o_reg; + insn.Op1.reg = uint16(reg); + insn.Op2.type = o_void; + } + } +} + +//-------------------------------------------------------------------------- +int tms320c55_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + optional_op = -1; + bytes_c bytes(insn); + uchar firstbyte = bytes.get_next(); + + int sdual_len = helper.altval_ea(insn.ea, TAG_SDUAL); + if ( sdual_len != 0 ) + { + // this is a second part of sdual instruction + bytevec_t insn_bytes; + if ( !unpack_sdual(insn.ea - sdual_len, NULL, &insn_bytes) ) + return 0; + bytes.set_cache(insn_bytes); + process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode + if ( insn.itype == TMS320C55_null || insn.size != insn_bytes.size() ) + return 0; + ana_status_bits(insn); + insn.SpecialModes |= TMS_MODE_USER_PARALLEL; + return insn.size; + } + else + { + // a normal instruction ? + process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode + if ( insn.size != 0 && insn.itype != TMS320C55_null ) + { + helper.altdel_ea(insn.ea + insn.size, TAG_SDUAL); + } + else if ( (firstbyte & 0xF8) == 0x88 ) + { + // "sdual" instruction; unpack it + bytevec_t insn_bytes; + if ( !unpack_sdual(insn.ea, &insn_bytes, NULL) ) + return 0; + bytes.set_cache(insn_bytes); + process_masks(insn, masks, TMS320C55_null, bytes, 8); // analyze opcode + if ( insn.itype != TMS320C55_null && insn.size == insn_bytes.size() ) + { + ana_status_bits(insn); + // remember that next address is the second part + helper.altset_ea(insn.ea + insn.size, insn.size, TAG_SDUAL); + return insn.size; + } + } + } + + // analyze special bits access + ana_status_bits(insn); + + // analyze user-parallelized instructions + if ( firstbyte <= MAX_BYTE_USER_PARALLELIZED && (firstbyte & 1) ) // instruction has E bit set + insn.SpecialModes |= TMS_MODE_USER_PARALLEL; + + // analyze postfixes + uchar nextbyte = get_byte(insn.ea+insn.size); // is_mapped() not necessary here + switch ( nextbyte ) + { + case BYTE_MMAP: // mmap() + if ( insn.OpMem != 0 ) + { + int n = insn.OpMem - 1; + if ( insn.ops[n].type == o_mem + && insn.ops[n].tms_regH == DPH + && insn.ops[n].tms_regP == DP + && insn.ops[n].tms_modifier == TMS_MODIFIER_DMA ) + { // @dma using DP + insn.ops[n].tms_regH = 0; + insn.ops[n].tms_regP = 0; + insn.ops[n].tms_modifier = TMS_MODIFIER_MMAP; + insn.size++; + } + else if ( insn.ops[n].type == o_reg + && insn.ops[n].reg == SP + && insn.ops[n].tms_modifier == TMS_MODIFIER_REG_OFFSET ) + { // @dma using SP + insn.ops[n].addr = insn.ops[n].value; + insn.ops[n].type = o_mem; + insn.ops[n].tms_regH = 0; + insn.ops[n].tms_regP = 0; + insn.ops[n].tms_modifier = TMS_MODIFIER_MMAP; + insn.size++; + } + } + break; + case BYTE_PORT1: + case BYTE_PORT2: // port() + if ( insn.OpMem != 0 ) + { + int n = insn.OpMem - 1; + switch ( insn.ops[n].type ) + { + case o_mem: + insn.ops[n].type = o_io; + insn.ops[n].tms_regH = 0; + insn.ops[n].tms_regP = PDP; + insn.ops[n].addr = insn.ops[n].addr >> 1; + insn.ops[n].tms_modifier = TMS_MODIFIER_PORT_AT; + insn.size++; + break; + case o_reg: + insn.ops[n].tms_operator1 |= TMS_OPERATOR_PORT & 0xFF; + insn.ops[n].tms_operator2 |= (TMS_OPERATOR_PORT >> 8); + insn.size++; + break; + } + } + break; + case BYTE_LR: + case BYTE_CR: // .lr & .cr + insn.SpecialModes |= nextbyte == BYTE_LR ? TMS_MODE_LR : TMS_MODE_CR; + insn.size++; + break; + } + if ( insn.itype == TMS320C55_null ) + return 0; + return insn.size; +} diff --git a/idasdk75/module/tms320c55/emu.cpp b/idasdk76/module/tms320c55/emu.cpp similarity index 100% rename from idasdk75/module/tms320c55/emu.cpp rename to idasdk76/module/tms320c55/emu.cpp diff --git a/idasdk75/module/tms320c55/ins.cpp b/idasdk76/module/tms320c55/ins.cpp similarity index 100% rename from idasdk75/module/tms320c55/ins.cpp rename to idasdk76/module/tms320c55/ins.cpp diff --git a/idasdk76/module/tms320c55/ins.hpp b/idasdk76/module/tms320c55/ins.hpp new file mode 100644 index 0000000..c70ccd7 --- /dev/null +++ b/idasdk76/module/tms320c55/ins.hpp @@ -0,0 +1,350 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ + +TMS320C55_null = 0, // Unknown Operation + +// ARITHMETICAL OPERATIONS + +TMS320C55_abdst, // Absolute Distance +TMS320C55_abs1, // Absolute Value +TMS320C55_abs2, // Absolute Value + +TMS320C55_add1, // Addition +TMS320C55_add2, // Addition +TMS320C55_add3, // Addition +TMS320C55_add4, // Addition +TMS320C55_addv1, // Addition +TMS320C55_addv2, // Addition +TMS320C55_addrv1, // Addition and Round +TMS320C55_addrv2, // Addition and Round + +TMS320C55_maxdiff, // Compare and Select Maximum +TMS320C55_dmaxdiff, // Compare and Select 40-bit Maximum +TMS320C55_mindiff, // Compare and Select Minimum +TMS320C55_dmindiff, // Compare and Select 40-bit Minimum + +TMS320C55_addsubcc4, // Conditional Add or Subtract +TMS320C55_addsubcc5, // Conditional Add or Subtract +TMS320C55_addsub2cc, // Conditional Add or Subtract + +TMS320C55_sftcc, // Conditional Shift + +TMS320C55_subc2, // Conditional Subtract +TMS320C55_subc3, // Conditional Subtract + +TMS320C55_addsub, // Paralleled Add - Subtract +TMS320C55_subadd, // Parallel Subtract - Add + +TMS320C55_mpy_mpy, // Two Parallel Multiply +TMS320C55_mpy_mpyr, // Two Parallel Multiply, and Round +TMS320C55_mpy_mpy40, // Two Parallel Multiply, on 40 bits +TMS320C55_mpy_mpyr40, // Two Parallel Multiply, and Round on 40 bits +TMS320C55_mac_mpy, // Parallel Multiply - Accumulate +TMS320C55_macr_mpyr, // Parallel Multiply - Accumulate, and Round +TMS320C55_mac40_mpy40, // Parallel Multiply - Accumulate, on 40 bits +TMS320C55_macr40_mpyr40, // Parallel Multiply - Accumulate, and Round on 40 bits +TMS320C55_mas_mpy, // Parallel Multiply - Subtract +TMS320C55_masr_mpyr, // Parallel Multiply - Subtract, and Round +TMS320C55_mas40_mpy40, // Parallel Multiply - Subtract, on 40 bits +TMS320C55_masr40_mpyr40, // Parallel Multiply - Subtract, and Round on 40 bits +TMS320C55_amar_mpy, // Parallel Modify Auxiliary Register - Multiply +TMS320C55_amar_mpyr, // Parallel Modify Auxiliary Register - Multiply, and Round +TMS320C55_amar_mpy40, // Parallel Modify Auxiliary Register - Multiply, on 40 bits +TMS320C55_amar_mpyr40, // Parallel Modify Auxiliary Register - Multiply, and Round on 40 bits +TMS320C55_mac_mac, // Two Parallel Multiply and Accumulate +TMS320C55_macr_macr, // Two Parallel Multiply and Accumulate, and Round +TMS320C55_mac40_mac40, // Two Parallel Multiply and Accumulate, on 40 bits +TMS320C55_macr40_macr40, // Two Parallel Multiply and Accumulate, and Round on 40 bits +TMS320C55_mas_mac, // Parallel Multiply and Subtract - Multiply and Accumulate +TMS320C55_masr_macr, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round +TMS320C55_mas40_mac40, // Parallel Multiply and Subtract - Multiply and Accumulate, on 40 bits +TMS320C55_masr40_macr40, // Parallel Multiply and Subtract - Multiply and Accumulate, and Round on 40 bits +TMS320C55_amar_mac, // Parallel Modify Auxiliary Register - Multiply and Accumulate +TMS320C55_amar_macr, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round +TMS320C55_amar_mac40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, on 40 bits +TMS320C55_amar_macr40, // Parallel Modify Auxiliary Register - Multiply and Accumulate, and Round on 40 bits +TMS320C55_mas_mas, // Two Parallel Multiply and Subtract +TMS320C55_masr_masr, // Two Parallel Multiply and Subtract, and Round +TMS320C55_mas40_mas40, // Two Parallel Multiply and Subtract, on 40 bits +TMS320C55_masr40_masr40, // Two Parallel Multiply and Subtract, and Round on 40 bits +TMS320C55_amar_mas, // Parallel Modify Auxiliary Register - Multiply and Subtract +TMS320C55_amar_masr, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round +TMS320C55_amar_mas40, // Parallel Modify Auxiliary Register - Multiply and Subtract, on 40 bits +TMS320C55_amar_masr40, // Parallel Modify Auxiliary Register - Multiply and Subtract, and Round on 40 bits +TMS320C55_mpy_mac, // Parallel Multiply - Multiply and Accumulate +TMS320C55_mpyr_macr, // Parallel Multiply - Multiply and Accumulate, and Round +TMS320C55_mpy40_mac40, // Parallel Multiply - Multiply and Accumulate, on 40 bits +TMS320C55_mpyr40_macr40, // Parallel Multiply - Multiply and Accumulate, and Round on 40 bits +TMS320C55_amar3, // Three Parallel Modify Auxiliary Registers + +TMS320C55_firsadd, // Parallel Multiply and Accumulate - Add +TMS320C55_firssub, // Parallel Multiply and Accumulate - Subtract + +TMS320C55_mpym_mov, // Parallel Multiply - Store +TMS320C55_mpymr_mov, // Parallel Multiply - Store, and Round +TMS320C55_macm_mov, // Parallel Multiply and Accumulate - Store +TMS320C55_macmr_mov, // Parallel Multiply and Accumulate - Store, and Round +TMS320C55_masm_mov, // Parallel Multiply and Subtract - Store +TMS320C55_masmr_mov, // Parallel Multiply and Subtract - Store, and Round +TMS320C55_add_mov, // Parallel Add - Store +TMS320C55_sub_mov, // Parallel Subtract - Store +TMS320C55_mov_mov, // Parallel Load - Store +TMS320C55_mov_aadd, // Parallel Store - aadd +TMS320C55_mov_add, // Parallel Store - Add +TMS320C55_amar_amar, // Parallel Modify Auxiliary Register - Modify Auxiliary Register +TMS320C55_add_asub, // Parallel Add - asub +TMS320C55_btst_mov, // Parallel Bit Test - Store +TMS320C55_mov_asub, // Parallel Store - asub + +TMS320C55_lms, // Least Mean Square + +TMS320C55_max1, // Maximum Comparison +TMS320C55_max2, // Maximum Comparison +TMS320C55_min1, // Minimum Comparison +TMS320C55_min2, // Minimum Comparison + +TMS320C55_cmp, // Memory Comparison +TMS320C55_cmpu, // Unsigned memory Comparison + +TMS320C55_aadd, // Add Two Registers +TMS320C55_asub, // Subtract Two Registers +TMS320C55_amov, // Move From Register to Register +TMS320C55_amar1, // Auxiliary Register Modification + +TMS320C55_sqr1, // Square +TMS320C55_sqr2, // Square +TMS320C55_sqrr1, // Square and Round +TMS320C55_sqrr2, // Square and Round +TMS320C55_mpy1, // Multiply +TMS320C55_mpy2, // Multiply +TMS320C55_mpy3, // Multiply +TMS320C55_mpyr1, // Multiply and Round +TMS320C55_mpyr2, // Multiply and Round +TMS320C55_mpyr3, // Multiply and Round +TMS320C55_mpyk2, // Multiply by Constant +TMS320C55_mpyk3, // Multiply by Constant +TMS320C55_mpykr2, // Multiply by Constant and Round +TMS320C55_mpykr3, // Multiply by Constant and Round +TMS320C55_mpym2, // Multiply Memory Value +TMS320C55_mpym3, // Multiply Memory Values +TMS320C55_mpymr2, // Multiply Memory Value and Round +TMS320C55_mpymr3, // Multiply Memory Values and Round +TMS320C55_mpym403, // Multiply Memory Values on 40 bits +TMS320C55_mpymr403, // Multiply Memory Values and Round on 40 bits +TMS320C55_mpymu3, // Unsigned multiply Memory Values +TMS320C55_mpymru3, // Unsigned multiply Memory Values and Round +TMS320C55_sqrm, // Square Memory Value +TMS320C55_sqrmr, // Square Memory Value, and Round +TMS320C55_mpymk, // Multiply Memory Value by Constant +TMS320C55_mpymkr, // Multiply Memory Value by Constant and Round + +TMS320C55_sqa1, // Square and Accumulate +TMS320C55_sqa2, // Square and Accumulate +TMS320C55_sqar1, // Square, Accumulate and Round +TMS320C55_sqar2, // Square, Accumulate and Round +TMS320C55_mac3, // Multiply and Accumulate +TMS320C55_mac4, // Multiply and Accumulate +TMS320C55_macr3, // Multiply, Accumulate and Round +TMS320C55_macr4, // Multiply, Accumulate and Round +TMS320C55_mack3, // Multiply by Constant and Accumulate +TMS320C55_mack4, // Multiply by Constant and Accumulate +TMS320C55_mackr3, // Multiply by Constant, Round and Accumulate +TMS320C55_mackr4, // Multiply by Constant, Round and Accumulate +TMS320C55_macm2, // Multiply and Accumulate Memory Values +TMS320C55_macm3, // Multiply and Accumulate Memory Values +TMS320C55_macm4, // Multiply and Accumulate Memory Values +TMS320C55_macmr2, // Multiply and Accumulate Memory Values, and Round +TMS320C55_macmr3, // Multiply and Accumulate Memory Values, and Round +TMS320C55_macmr4, // Multiply and Accumulate Memory Values, and Round +TMS320C55_macm403, // Multiply and Accumulate Memory Values, on 40 bits +TMS320C55_macm404, // Multiply and Accumulate Memory Values, on 40 bits +TMS320C55_macmr403, // Multiply and Accumulate Memory Values, and Round on 40 bits +TMS320C55_macmr404, // Multiply and Accumulate Memory Values, and Round on 40 bits +TMS320C55_macmz, // Multiply and Accumulate Memory Values +TMS320C55_macmrz, // Multiply and Accumulate Memory Values, and Round +TMS320C55_sqam2, // Square and Accumulate Memory Value +TMS320C55_sqam3, // Square and Accumulate Memory Values +TMS320C55_sqamr2, // Square and Accumulate Memory Value, and Round +TMS320C55_sqamr3, // Square and Accumulate Memory Values, and Round +TMS320C55_macmk3, // Multiply Memory Value by Constant and Accumulate +TMS320C55_macmk4, // Multiply Memory Value by Constant and Accumulate +TMS320C55_macmkr3, // Multiply Memory Value by Constant - Accumulate, and Round +TMS320C55_macmkr4, // Multiply Memory Value by Constant - Accumulate, and Round + +TMS320C55_sqs1, // Square and Subtract +TMS320C55_sqs2, // Square and Subtract +TMS320C55_sqsr1, // Square, Subtract and Round +TMS320C55_sqsr2, // Square, Subtract and Round + +TMS320C55_mas2, // Multiply and Subtract +TMS320C55_mas3, // Multiply and Subtract +TMS320C55_masr2, // Multiply, Subtract and Round +TMS320C55_masr3, // Multiply, Subtract and Round +TMS320C55_masm2, // Multiply and Subtract Memory Value +TMS320C55_masm3, // Multiply and Subtract Memory Values +TMS320C55_masm4, // Multiply and Subtract Memory Values +TMS320C55_masmr2, // Multiply and Subtract Memory Values, and Round +TMS320C55_masmr3, // Multiply and Subtract Memory Values, and Round +TMS320C55_masmr4, // Multiply and Subtract Memory Values, and Round +TMS320C55_masm403, // Multiply and Subtract Memory Values, on 40 bits +TMS320C55_masm404, // Multiply and Subtract Memory Values, on 40 bits +TMS320C55_masmr403, // Multiply and Subtract Memory Values, and Round on 40 bits +TMS320C55_masmr404, // Multiply and Subtract Memory Values, and Round on 40 bits +TMS320C55_sqsm2, // Square and Subtract Memory Values +TMS320C55_sqsm3, // Square and Subtract Memory Values +TMS320C55_sqsmr2, // Square and Subtract Memory Values, and Round +TMS320C55_sqsmr3, // Square and Subtract Memory Values, and Round + +TMS320C55_neg1, // Negation +TMS320C55_neg2, // Negation + +TMS320C55_mant_nexp, // Exponent and Mantissa +TMS320C55_exp, // Exponent + +TMS320C55_cmpand, // Compare and AND +TMS320C55_cmpandu, // Unsigned compare and AND +TMS320C55_cmpor, // Compare and OR +TMS320C55_cmporu, // Unsigned compare and OR + +TMS320C55_round1, // Round +TMS320C55_round2, // Round + +TMS320C55_sat1, // Saturate +TMS320C55_sat2, // Saturate +TMS320C55_satr1, // Saturate and Round +TMS320C55_satr2, // Saturate and Round + +TMS320C55_sfts2, // Signed Shift +TMS320C55_sfts3, // Signed Shift +TMS320C55_sftsc2, // Signed Shift with Carry +TMS320C55_sftsc3, // Signed Shift with Carry + +TMS320C55_sqdst, // Square distance + +TMS320C55_sub1, // Subtract +TMS320C55_sub2, // Subtract +TMS320C55_sub3, // Subtract +TMS320C55_sub4, // Subtract + +TMS320C55_band, // Bit Field Comparison + +TMS320C55_bfxpa, // Bit Field Expand + +TMS320C55_bfxtr, // Bit Field Extract + +TMS320C55_btst, // Bit Test +TMS320C55_bnot, // Bit NOT +TMS320C55_bclr2, // Bit Clear +TMS320C55_bset2, // Bit Set +TMS320C55_btstset, // Bit Test and Set +TMS320C55_btstclr, // Bit Test and Clear +TMS320C55_btstnot, // Bit Test and NOT +TMS320C55_btstp, // Bit Pair Test +TMS320C55_bclr1, // Bit Clear +TMS320C55_bset1, // Bit Set + +TMS320C55_amar2, // Load Effective Address to Extended Auxiliary Register +TMS320C55_popboth, // Pop Extended Auxiliary Register from Stack Pointers +TMS320C55_pshboth, // Push Extended Auxiliary Register to Stack Pointers + +// LOGICAL OPERATIONS + +TMS320C55_bcnt, // Count Bit Field + +TMS320C55_not1, // NOT +TMS320C55_not2, // NOT + +TMS320C55_and1, // AND +TMS320C55_and2, // AND +TMS320C55_and3, // AND + +TMS320C55_or1, // OR +TMS320C55_or2, // OR +TMS320C55_or3, // OR + +TMS320C55_xor1, // XOR +TMS320C55_xor2, // XOR +TMS320C55_xor3, // XOR + +TMS320C55_sftl2, // Logical Shift +TMS320C55_sftl3, // Logical Shift + +TMS320C55_rol, // Rotate Left + +TMS320C55_ror, // Rotate Right + +// MISCELLANEOUS OPERATIONS + +// MOVE OPERATIONS + +TMS320C55_swap, // Swap Registers +TMS320C55_swapp, // Swap Pair Registers +TMS320C55_swap4, // Swap 4 Registers + +TMS320C55_mov2, // Move Data +TMS320C55_mov3, // Move 2 Data +TMS320C55_mov402, // Move Data on 40 bits + +TMS320C55_delay, // Memory Delay + +TMS320C55_pop1, // Pop Top of Stack1 +TMS320C55_pop2, // Pop Top of Stack2 + +TMS320C55_psh1, // Pop Top of Stack3 +TMS320C55_psh2, // Pop Top of Stack4 + +// PROGRAM CONTROL OPERATIONS + +TMS320C55_bcc, // Branch Conditionally +TMS320C55_bccu, // Branch Conditionally + +TMS320C55_b, // Branch Unconditionally + +TMS320C55_callcc, // Call Conditionally + +TMS320C55_call, // Call Unconditionally + +TMS320C55_xcc, // Execute Conditionally +TMS320C55_xccpart, // Execute Conditionally + +TMS320C55_idle, // Idle + +TMS320C55_nop, // No Operation +TMS320C55_nop_16, // No Operation + +TMS320C55_rptblocal, // Repeat Block of Instructions Unconditionally +TMS320C55_rptb, // Repeat Block of Instructions Unconditionally + +TMS320C55_rptcc, // Repeat Single Instruction Conditionally + +TMS320C55_rpt, // Repeat Single Instruction Unconditionally +TMS320C55_rptadd, // Repeat Single Instruction Unconditionally and Add to Register +TMS320C55_rptsub, // Repeat Single Instruction Unconditionally and Subtract to Register + +TMS320C55_retcc, // Return Conditionally +TMS320C55_ret, // Return Unconditionally +TMS320C55_reti, // Return from Interrupt + +TMS320C55_intr, // Software Interrupt + +TMS320C55_reset, // Software Reset + +TMS320C55_trap, // Software Trap + +TMS320C55_last + +}; + +#endif diff --git a/idasdk76/module/tms320c55/makefile b/idasdk76/module/tms320c55/makefile new file mode 100644 index 0000000..c5487a2 --- /dev/null +++ b/idasdk76/module/tms320c55/makefile @@ -0,0 +1,58 @@ +PROC=tms32055 +CONFIGS=tms320c55.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp ins.hpp tms320c55.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp tms320c55.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ins.cpp ins.hpp tms320c55.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)frame.hpp $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp \ + ../idaidp.hpp ../iohandler.hpp ins.hpp out.cpp \ + tms320c55.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp reg.cpp tms320c55.hpp diff --git a/idasdk75/module/tms320c55/out.cpp b/idasdk76/module/tms320c55/out.cpp similarity index 100% rename from idasdk75/module/tms320c55/out.cpp rename to idasdk76/module/tms320c55/out.cpp diff --git a/idasdk76/module/tms320c55/reg.cpp b/idasdk76/module/tms320c55/reg.cpp new file mode 100644 index 0000000..5703d0b --- /dev/null +++ b/idasdk76/module/tms320c55/reg.cpp @@ -0,0 +1,592 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#include <ctype.h> +#include "tms320c55.hpp" +#include <diskio.hpp> +#include <segregs.hpp> +#include <ieee.h> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const register_names[] = +{ + "AC0", // Accumulator + "AC1", // Accumulator + "AC2", // Accumulator + "AC3", // Accumulator + "T0", // Temporary register + "T1", // Temporary register + "T2", // Temporary register + "T3", // Temporary register + "AR0", // Auxiliary register + "AR1", // Auxiliary register + "AR2", // Auxiliary register + "AR3", // Auxiliary register + "AR4", // Auxiliary register + "AR5", // Auxiliary register + "AR6", // Auxiliary register + "AR7", // Auxiliary register + + "AC0L", // Accumulator + "AC0H", // Accumulator + "AC0G", // Accumulator + "AC1L", // Accumulator + "AC1H", // Accumulator + "AC1G", // Accumulator + "AC2L", // Accumulator + "AC2H", // Accumulator + "AC2G", // Accumulator + "AC3L", // Accumulator + "AC3H", // Accumulator + "AC3G", // Accumulator + "BK03", // Circular buffer size register + "BK47", // Circular buffer size register + "BKC", // Circular buffer size register + "BRC0", // Block-repeat counter + "BRC1", // Block-repeat counter + "BRS1", // BRC1 save register + "BSA01", // Circulat buffer start address register + "BSA23", // Circulat buffer start address register + "BSA45", // Circulat buffer start address register + "BSA67", // Circulat buffer start address register + "BSAC", // Circulat buffer start address register + "CDP", // Coefficient data pointer (low part of XCDP) + "CDPH", // High part of XCDP + "CFCT", // Control-flow contect register + "CSR", // Computed single-repeat register + "DBIER0", // Debug interrupt enable register + "DBIER1", // Debug interrupt enable register + // DP Data page register (low part of XDP) + // DPH High part of XDP + "IER0", // Interrupt enable register + "IER1", // Interrupt enable register + "IFR0", // Interrupt flag register + "IFR1", // Interrupt flag register + "IVPD", + "IVPH", + "PC", // Program counter + // PDP Peripheral data page register + "PMST", + "REA0", // Block-repeat end address register + "REA0L", // Block-repeat end address register + "REA0H", // Block-repeat end address register + "REA1", // Block-repeat end address register + "REA1L", // Block-repeat end address register + "REA1H", // Block-repeat end address register + "RETA", // Return address register + "RPTC", // Single-repeat counter + "RSA0", // Block-repeat start address register + "RSA0L", // Block-repeat start address register + "RSA0H", // Block-repeat start address register + "RSA1", // Block-repeat start address register + "RSA1L", // Block-repeat start address register + "RSA1H", // Block-repeat start address register + "SP", // Data stack pointer + "SPH", // High part of XSP and XSSP + "SSP", // System stack pointer + "ST0", // Status register + "ST1", // Status register + "ST0_55", // Status register + "ST1_55", // Status register + "ST2_55", // Status register + "ST3_55", // Status register + "TRN0", // Transition register + "TRN1", // Transition register + + "XAR0", // Extended auxiliary register + "XAR1", // Extended auxiliary register + "XAR2", // Extended auxiliary register + "XAR3", // Extended auxiliary register + "XAR4", // Extended auxiliary register + "XAR5", // Extended auxiliary register + "XAR6", // Extended auxiliary register + "XAR7", // Extended auxiliary register + + "XCDP", // Extended coefficient data pointer + "XDP", // Extended data page register + "XPC", // Extended program counter + "XSP", // Extended data stack pointer + "XSSP", // Extended system stack pointer + + "MDP", // Main Data page pointer (direct memory access / indirect from CDP) + "MDP05", // Main Data page pointer (indirect AR[0-5]) + "MDP67", // Main Data page pointer (indirect AR[6-7]) + + // flags + "ACOV2", + "ACOV3", + "TC1", + "TC2", + "CARRY", + "ACOV0", + "ACOV1", + "BRAF", + "XF", + "HM", + "INTM", + "M40", + "SATD", + "SXMD", + "C16", + "FRCT", + "C54CM", + "DBGM", + "EALLOW", + "RDM", + "CDPLC", + "AR7LC", + "AR6LC", + "AR5LC", + "AR4LC", + "AR3LC", + "AR2LC", + "AR1LC", + "AR0LC", + "CAFRZ", + "CAEN", + "CACLR", + "HINT", + "CBERR", + "MPNMC", + "SATA", + "CLKOFF", + "SMUL", + "SST", + + "BORROW", + + // segment registers + "ARMS", // AR indirect operands available + "CPL", // Compiler mode + "DP", // Data page pointer + "DPH", // Data page + "PDP", // Peripheral data page register + "cs","ds" // virtual registers for code and data segments +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_0[] = { 0x48, 0x04 }; // ret +static const uchar retcode_1[] = { 0x48, 0x05 }; // reti + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_0), retcode_0 }, + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// TMS320C55 ASM +//----------------------------------------------------------------------- +static const asm_t masm55 = +{ + AS_COLON|AS_N2CHR|ASH_HEXF0|ASD_DECF0|ASO_OCTF5|ASB_BINF0|AS_ONEDUP, + 0, + "MASM55", + 0, + NULL, // header lines + NULL, // org + ".end", // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".pstring", // ascii string directive + "MY_BYTE", // byte directive + ".word", // word directive + ".long", // double words + NULL, // qwords + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".space 8*%s",// uninited arrays + ".asg", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".global", // "public" name keyword + NULL, // "weak" name keyword + ".ref", // "extrn" name keyword + NULL, // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof + AS2_STRINV // invert string byte order +}; + +static const asm_t *const asms[] = { &masm55, NULL }; + +//-------------------------------------------------------------------------- +const char *tms320c55_t::find_sym(ea_t address) +{ + const ioport_t *port = find_ioport(ioh.ports, address); + return port ? port->name.c_str() : NULL; +} + +//-------------------------------------------------------------------------- +static int idaapi choose_device(int, form_actions_t &fa) +{ + tms320c55_t &pm = *(tms320c55_t *)fa.get_ud(); + if ( choose_ioport_device(&pm.ioh.device, cfgname) ) + pm.ioh.set_device_name(pm.ioh.device.c_str(), IORESP_ALL); + return 0; +} + +//-------------------------------------------------------------------------- +const char *tms320c55_t::set_idp_options( + const char *keyword, + int value_type, + const void *value, + bool idb_loaded) +{ + if ( keyword == NULL ) + { + static const char form[] = + "HELP\n" + "TMS320C55 specific options\n" + "\n" + " Use I/O definitions \n" + "\n" + " If this option is on, IDA will use I/O definitions\n" + " from the configuration file into a macro instruction.\n" + "\n" + " Detect memory mapped registers \n" + "\n" + " If this option is on, IDA will replace addresses\n" + " by an equivalent memory mapped register.\n" + "\n" + "ENDHELP\n" + "TMS320C55 specific options\n" + "%*\n" + " <Use ~I~/O definitions:C>\n" + " <Detect memory mapped ~r~egisters:C>>\n" + "\n" + " <~C~hoose device name:B:0::>\n" + "\n" + "\n"; + CASSERT(sizeof(idpflags) == sizeof(ushort)); + ask_form(form, this, &idpflags, choose_device); + } + else + { + if ( value_type != IDPOPT_BIT ) + return IDPOPT_BADTYPE; + if ( strcmp(keyword, "TMS320C55_IO") == 0 ) + { + setflag(idpflags, TMS320C55_IO, *(int*)value != 0); + } + else if ( strcmp(keyword, "TMS320C55_MMR") == 0 ) + { + setflag(idpflags, TMS320C55_MMR, *(int*)value != 0); + } + else + { + return IDPOPT_BADKEY; + } + } + if ( idb_loaded ) + save_idpflags(); + return IDPOPT_OK; +} + +//-------------------------------------------------------------------------- +static const proctype_t ptypes[] = +{ + TMS320C55 +}; + +//-------------------------------------------------------------------------- +void tms320c55_t::load_from_idb() +{ + ptype = ptypes[ph.get_proc_index()]; + ioh.restore_device(); + if ( ioh.device.empty() ) + { + read_ioports(&ioh.ports, &ioh.device, cfgname); + helper.supset(-1, ioh.device.c_str()); + } + idpflags = (ushort)helper.altval(-1); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(tms320c55_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi tms320c55_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); // MSB first + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: // new file loaded + { + read_ioports(&ioh.ports, &ioh.device, cfgname); + helper.supset(-1, ioh.device.c_str()); + save_idpflags(); + { + set_default_sreg_value(NULL, ARMS, 0); + set_default_sreg_value(NULL, CPL, 1); + for ( int i = DP; i <= rVds; i++ ) + set_default_sreg_value(NULL, i, 0); + } + static const char *const informations = + "AUTOHIDE REGISTRY\n" + "Default values of flags and registers:\n" + "\n" + "ARMS bit = 0 (DSP mode operands).\n" + "CPL bit = 1 (SP direct addressing mode).\n" + "DP register = 0 (Data Page register)\n" + "DPH register = 0 (High part of EXTENDED Data Page Register)\n" + "PDP register = 0 (Peripheral Data Page register)\n" + "\n" + "You can change the register values by pressing Alt-G\n" + "(Edit, Segments, Change segment register value)\n"; + info(informations); + break; + } + + case processor_t::ev_oldfile: // old file loaded + ioh.upgrade_device_index(); + // fall through + case processor_t::ev_ending_undo: + load_from_idb(); + break; + + case processor_t::ev_newprc: // new processor type + { + ptype = ptypes[va_arg(va, int)]; + // bool keep_cfg = va_argi(va, bool); + switch ( ptype ) + { + case TMS320C55: + break; + default: + error("interr: setprc"); + } + } + break; + + case processor_t::ev_newasm: // new assembler type + break; + + case processor_t::ev_creating_segm: // new segment + break; + + case processor_t::ev_get_stkvar_scale_factor: + return 2; + + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_mnem(*ctx); + return 1; + } + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *op = va_arg(va, const op_t *); + return can_have_type(*op) ? 1 : -1; + } + + case processor_t::ev_create_func_frame: + { + func_t *pfn = va_arg(va, func_t *); + create_func_frame(pfn); + return 1; + } + + case processor_t::ev_gen_stkvar_def: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const member_t *mptr = va_arg(va, const member_t *); + sval_t v = va_arg(va, sval_t); + gen_stkvar_def(*ctx, mptr, v); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//----------------------------------------------------------------------- +#define FAMILY "TMS320C55x Series:" +static const char *const shnames[] = +{ "TMS32055", + NULL +}; +static const char *const lnames[] = +{ + FAMILY"Texas Instruments TMS320C55", + NULL +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_TMS320C55, // id + // flag + PRN_HEX + | PR_SEGS + | PR_SGROTHER + | PR_SCALE_STKVARS, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + register_names, // Register names + qnumber(register_names), // Number of registers + + ARMS, // first + rVds, // last + 1, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + TMS320C55_null, + TMS320C55_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0,7,15,19 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + TMS320C55_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/tms320c55/tms320c55.cfg b/idasdk76/module/tms320c55/tms320c55.cfg similarity index 100% rename from idasdk75/module/tms320c55/tms320c55.cfg rename to idasdk76/module/tms320c55/tms320c55.cfg diff --git a/idasdk76/module/tms320c55/tms320c55.hpp b/idasdk76/module/tms320c55/tms320c55.hpp new file mode 100644 index 0000000..9c6e40d --- /dev/null +++ b/idasdk76/module/tms320c55/tms320c55.hpp @@ -0,0 +1,423 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-99 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@datarescue.com + * + * + */ + +#ifndef _TMS320C55_HPP +#define _TMS320C55_HPP + +#include "../idaidp.hpp" +#include <diskio.hpp> +#include "ins.hpp" +#include "../iohandler.hpp" + +// #define TMS320C55_NO_NAME_NO_REF + +//------------------------------------------------------------------ +enum regnum_t ENUM_SIZE(uint16) +{ + AC0, // Accumulator + AC1, // Accumulator + AC2, // Accumulator + AC3, // Accumulator + T0, // Temporary register + T1, // Temporary register + T2, // Temporary register + T3, // Temporary register + AR0, // Auxiliary register + AR1, // Auxiliary register + AR2, // Auxiliary register + AR3, // Auxiliary register + AR4, // Auxiliary register + AR5, // Auxiliary register + AR6, // Auxiliary register + AR7, // Auxiliary register + + AC0L, // Accumulator + AC0H, // Accumulator + AC0G, // Accumulator + AC1L, // Accumulator + AC1H, // Accumulator + AC1G, // Accumulator + AC2L, // Accumulator + AC2H, // Accumulator + AC2G, // Accumulator + AC3L, // Accumulator + AC3H, // Accumulator + AC3G, // Accumulator + BK03, // Circular buffer size register + BK47, // Circular buffer size register + BKC, // Circular buffer size register + BRC0, // Block-repeat counter + BRC1, // Block-repeat counter + BRS1, // BRC1 save register + BSA01, // Circulat buffer start address register + BSA23, // Circulat buffer start address register + BSA45, // Circulat buffer start address register + BSA67, // Circulat buffer start address register + BSAC, // Circulat buffer start address register + CDP, // Coefficient data pointer (low part of XCDP) + CDPH, // High part of XCDP + CFCT, // Control-flow contect register + CSR, // Computed single-repeat register + DBIER0, // Debug interrupt enable register + DBIER1, // Debug interrupt enable register + // DP Data page register (low part of XDP) + // DPH High part of XDP + IER0, // Interrupt enable register + IER1, // Interrupt enable register + IFR0, // Interrupt flag register + IFR1, // Interrupt flag register + IVPD, + IVPH, + PC, // Program counter + // PDP Peripheral data page register + PMST, + REA0, // Block-repeat end address register + REA0L, // Block-repeat end address register + REA0H, // Block-repeat end address register + REA1, // Block-repeat end address register + REA1L, // Block-repeat end address register + REA1H, // Block-repeat end address register + RETA, // Return address register + RPTC, // Single-repeat counter + RSA0, // Block-repeat start address register + RSA0L, // Block-repeat start address register + RSA0H, // Block-repeat start address register + RSA1, // Block-repeat start address register + RSA1L, // Block-repeat start address register + RSA1H, // Block-repeat start address register + SP, // Data stack pointer + SPH, // High part of XSP and XSSP + SSP, // System stack pointer + ST0, // Status register + ST1, // Status register + ST0_55, // Status register + ST1_55, // Status register + ST2_55, // Status register + ST3_55, // Status register + TRN0, // Transition register + TRN1, // Transition register + + XAR0, // Extended auxiliary register + XAR1, // Extended auxiliary register + XAR2, // Extended auxiliary register + XAR3, // Extended auxiliary register + XAR4, // Extended auxiliary register + XAR5, // Extended auxiliary register + XAR6, // Extended auxiliary register + XAR7, // Extended auxiliary register + + XCDP, // Extended coefficient data pointer + XDP, // Extended data page register + XPC, // Extended program counter + XSP, // Extended data stack pointer + XSSP, // Extended system stack pointer + + // these seem to be an old way of what is now DPH/CDPH/AR0H..AR7H + // i.e. supply bits 22:16 of the address for specific situations) + MDP, // Main Data page pointer (direct memory access / indirect from CDP) + MDP05, // Main Data page pointer (indirect AR[0-5]) + MDP67, // Main Data page pointer (indirect AR[6-7]) + + // flags + ACOV2, + ACOV3, + TC1, + TC2, + CARRY, + ACOV0, + ACOV1, + BRAF, + XF, + HM, + INTM, + M40, + SATD, + SXMD, + C16, + FRCT, + C54CM, + DBGM, + EALLOW, + RDM, + CDPLC, + AR7LC, + AR6LC, + AR5LC, + AR4LC, + AR3LC, + AR2LC, + AR1LC, + AR0LC, + CAFRZ, + CAEN, + CACLR, + HINT, + CBERR, + MPNMC, + SATA, + CLKOFF, + SMUL, + SST, + + BORROW, + + // segment registers + ARMS, // AR indirect operands available + CPL, // Compiler mode + DP, // Data page pointer + DPH, // Data page + PDP, // Peripheral data page register + rVcs, rVds, // virtual registers for code and data segments +}; + +//------------------------------------------------------------------ +// specific condition codes +#define COND_A 0x0 +#define COND_B 0x8 + +#define COND_GEQ 0x2 +#define COND_LT 0x3 +#define COND_NEQ 0x4 +#define COND_EQ 0x5 +#define COND_GT 0x6 +#define COND_LEQ 0x7 + + +#define COND4_AGEQ (COND_A | COND_GEQ) +#define COND4_ALT (COND_A | COND_LT) +#define COND4_ANEQ (COND_A | COND_NEQ) +#define COND4_AEQ (COND_A | COND_EQ) +#define COND4_AGT (COND_A | COND_GT) +#define COND4_ALEQ (COND_A | COND_LEQ) + +#define COND4_BGEQ (COND_B | COND_GEQ) +#define COND4_BLT (COND_B | COND_LT) +#define COND4_BNEQ (COND_B | COND_NEQ) +#define COND4_BEQ (COND_B | COND_EQ) +#define COND4_BGT (COND_B | COND_GT) +#define COND4_BLEQ (COND_B | COND_LEQ) + + +#define COND8_FROM_COND4 0x40 + +#define COND8_UNC 0x00 +#define COND8_NBIO 0x02 +#define COND8_BIO 0x03 +#define COND8_NC 0x08 +#define COND8_C 0x0C +#define COND8_NTC 0x20 +#define COND8_TC 0x30 +#define COND8_AGEQ (COND8_FROM_COND4 | COND4_AGEQ) +#define COND8_ALT (COND8_FROM_COND4 | COND4_ALT) +#define COND8_ANEQ (COND8_FROM_COND4 | COND4_ANEQ) +#define COND8_AEQ (COND8_FROM_COND4 | COND4_AEQ) +#define COND8_AGT (COND8_FROM_COND4 | COND4_AGT) +#define COND8_ALEQ (COND8_FROM_COND4 | COND4_ALEQ) +#define COND8_ANOV 0x60 +#define COND8_AOV 0x70 +#define COND8_BGEQ (COND8_FROM_COND4 | COND4_BGEQ) +#define COND8_BLT (COND8_FROM_COND4 | COND4_BLT) +#define COND8_BNEQ (COND8_FROM_COND4 | COND4_BNEQ) +#define COND8_BEQ (COND8_FROM_COND4 | COND4_BEQ) +#define COND8_BGT (COND8_FROM_COND4 | COND4_BGT) +#define COND8_BLEQ (COND8_FROM_COND4 | COND4_BLEQ) +#define COND8_BNOV (COND_B | COND8_ANOV) +#define COND8_BOV (COND_B | COND8_AOV) + +//------------------------------------------------------------------ +#define Parallel segpref // number of operands for the first line of a parallel instruction + #define TMS_PARALLEL_BIT -1 +#define SpecialModes auxpref_u8[0] + #define TMS_MODE_USER_PARALLEL 0x1 // user parallel bit (E) is set + #define TMS_MODE_LR 0x2 // LR postfix + #define TMS_MODE_CR 0x4 // CR postfix + #define TMS_MODE_SIMULATE_USER_PARALLEL 0x8 // the instruction simulate two instructions linked by a user parallelism +#define OpMem auxpref_u8[1] + +// complex operands + +// for o_reg, o_imm, o_mem +#define tms_shift specval_shorts.low // operand << value + #define TMS_OP_SHIFT_NULL 0 // no shift + #define TMS_OP_SHIFT_TYPE 0x7FFF + #define TMS_OP_SHIFTL_IMM 1 // operand << #... + #define TMS_OP_SHIFTL_REG 2 // operand << reg + #define TMS_OP_SHIFTR_IMM 3 // operand >> #... + #define TMS_OP_EQ 4 // operand == #... + #define TMS_OP_NEQ 5 // operand != #... + #define TMS_OP_SHIFT_OUT 0x8000 // functions(...) << ... (default = functions(... << ...)) + +#define tms_shift_value specval_shorts.high + +// for o_reg, o_mem +#define tms_modifier specflag2 + #define TMS_MODIFIER_NULL 0 + // o_reg + #define TMS_MODIFIER_REG 1 // *reg + #define TMS_MODIFIER_REG_P 2 // *reg+ + #define TMS_MODIFIER_REG_M 3 // *reg- + #define TMS_MODIFIER_REG_P_T0 4 // *(reg+T0) + #define TMS_MODIFIER_REG_P_T1 5 // *(reg+T1) + #define TMS_MODIFIER_REG_M_T0 6 // *(reg-T0) + #define TMS_MODIFIER_REG_M_T1 7 // *(reg-T1) + #define TMS_MODIFIER_REG_T0 8 // *reg(T0) + #define TMS_MODIFIER_REG_OFFSET 9 // *reg(#value) + #define TMS_MODIFIER_P_REG_OFFSET 10 // *+reg(#value) + #define TMS_MODIFIER_REG_SHORT_OFFSET 11 // *reg(short(#value)) + #define TMS_MODIFIER_REG_T1 12 // *reg(T1) + #define TMS_MODIFIER_P_REG 13 // *+reg + #define TMS_MODIFIER_M_REG 14 // *-reg + #define TMS_MODIFIER_REG_P_T0B 15 // *(reg+T0B) + #define TMS_MODIFIER_REG_M_T0B 16 // *(reg-T0B) + // o_mem, o_io + #define TMS_MODIFIER_DMA 1 // @addr + #define TMS_MODIFIER_ABS16 2 // *abs16(#addr) + #define TMS_MODIFIER_PTR 3 // *(#addr) + #define TMS_MODIFIER_MMAP 4 // mmap() + #define TMS_MODIFIER_PORT 5 // port(#addr) + #define TMS_MODIFIER_PORT_AT 6 // port(@addr) + +// for o_reg, o_mem, o_io +#define tms_operator1 specflag3 // operators sorted by priority order +#define tms_operator2 specflag4 + #define TMS_OPERATORS_SIZE 13 + #define TMS_OPERATOR_NULL 0x0000 + #define TMS_OPERATOR_T3 0x0001 // T3=xxx + #define TMS_OPERATOR_NOT 0x0002 // !xxx + #define TMS_OPERATOR_UNS 0x0004 // uns(xxx) + #define TMS_OPERATOR_DBL 0x0008 // dbl(xxx) + #define TMS_OPERATOR_RND 0x0010 // rnd(xxx) + #define TMS_OPERATOR_PAIR 0x0020 // pair(xxx) + #define TMS_OPERATOR_LO 0x0040 // lo(xxx) + #define TMS_OPERATOR_HI 0x0080 // hi(xxx) + #define TMS_OPERATOR_LB 0x0100 // low_byte(xxx) + #define TMS_OPERATOR_HB 0x0200 // high_byte(xxx) + #define TMS_OPERATOR_SAT 0x0400 // saturate(xxx) + #define TMS_OPERATOR_DUAL 0x0800 // dual(xxx) + #define TMS_OPERATOR_PORT 0x1000 // port(xxx) + +// for o_imm +#define tms_signed specflag1 +#define tms_prefix specflag2 + +// for o_mem (real address = tms_reg_h : tms_reg_p + addr) +#define tms_regH value_shorts.low +#define tms_regP value_shorts.high + +#define o_cond o_idpspec0 +#define o_shift o_idpspec1 +#define o_relop o_idpspec2 + #define tms_relop specflag1 // relational operator + #define tms_relop_type specflag2 // o_reg, o_imm + #define TMS_RELOP_REG 1 // operand << #... + #define TMS_RELOP_IMM 2 // operand << reg + // value will contain register or immediate +#define o_io o_idpspec3 + +//------------------------------------------------------------------ +// processor types + +typedef uchar proctype_t; + +const proctype_t TMS320C55 = 0; + +//------------------------------------------------------------------ +#define TAG_SDUAL '2' // helper.altval(ea, '2') == length of the first part of sdual instruction + +#define TMS320C55_IO 0x0001 // use I/O definitions +#define TMS320C55_MMR 0x0002 // use memory mapped registers + +//------------------------------------------------------------------ +const char *const cfgname = "tms320c55.cfg"; + +struct tms320c55_iohandler_t : public iohandler_t +{ + struct tms320c55_t ± + qstring errbuf; + + tms320c55_iohandler_t(tms320c55_t &_pm, netnode &nn) : iohandler_t(nn), pm(_pm) {} + void get_cfg_filename(char *buf, size_t bufsize) override + { + qstrncpy(buf, cfgname, bufsize); + } +}; + +struct mask_t; +class bytes_c; +struct tms320c55_t : public procmod_t +{ + netnode helper; + tms320c55_iohandler_t ioh = tms320c55_iohandler_t(*this, helper); + ushort idpflags = TMS320C55_IO|TMS320C55_MMR; + proctype_t ptype = TMS320C55; // contains processor type + bool flow = false; + char optional_op = -1; // ana: index of an optional operand + + ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + const char *find_sym(ea_t address); + const char *idaapi set_idp_options( + const char *keyword, + int value_type, + const void * value, + bool idb_loaded); + + int ana(insn_t *insn); + void process_masks( + insn_t &insn, + const mask_t *masks, + ushort itype_null, + bytes_c &bytes, + char lbytesize = 8); + bool process_masks_operand( + insn_t &insn, + const mask_t *mask, + int64 code, + int64 op_mask_n, + unsigned *p_opnum, + bool bTest); + + int emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &op, flags_t F, bool use); + int get_mapped_register(ea_t ea) const; + + void assumes(outctx_t &ctx); + void print_segment_register(outctx_t &ctx, int reg, sel_t value); + void segstart(outctx_t &ctx, segment_t *seg) const; + void footer(outctx_t &ctx) const; + void gen_stkvar_def(outctx_t &ctx, const member_t *mptr, sval_t v) const; + + void save_idpflags() { helper.altset(-1, idpflags); } + void load_from_idb(); +}; + +extern int data_id; +#define PROCMOD_NODE_NAME "$ tms320c54" +#define PROCMOD_NAME tms320c55 + + +const char *find_sym(ea_t address); +//------------------------------------------------------------------ +void idaapi header(outctx_t &ctx); + +void idaapi segend(outctx_t &ctx, segment_t *seg); + +void idaapi data(outctx_t &ctx); + +bool idaapi create_func_frame(func_t *pfn); +int idaapi is_align_insn(ea_t ea); +bool idaapi can_have_type(const op_t &op); + +ea_t calc_io_mem(const insn_t &insn, const op_t &op); +ea_t calc_data_mem(const insn_t &insn, const op_t &op); +inline ea_t calc_code_mem(const insn_t &insn, ea_t ea) +{ + return to_ea(insn.cs, ea); +} + +#endif // _TMS320C55_HPP diff --git a/idasdk75/module/tms320c6/ana.cpp b/idasdk76/module/tms320c6/ana.cpp similarity index 100% rename from idasdk75/module/tms320c6/ana.cpp rename to idasdk76/module/tms320c6/ana.cpp diff --git a/idasdk76/module/tms320c6/emu.cpp b/idasdk76/module/tms320c6/emu.cpp new file mode 100644 index 0000000..bc445de --- /dev/null +++ b/idasdk76/module/tms320c6/emu.cpp @@ -0,0 +1,375 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + * + * TMS320C6xx - VLIW (very long instruction word) architecture + * + */ + +#include "tms6.hpp" + +//------------------------------------------------------------------------ +static void set_immd_bit(const insn_t &insn, int n, flags_t F) +{ + set_immd(insn.ea); + if ( is_defarg(F, n) ) + return; + switch ( insn.itype ) + { + case TMS6_mvk: + if ( is_mvk_scst16_form(insn.ea) ) + { + op_hex(insn.ea, n); + break; + } + // fallthrough for scst5 form + case TMS6_addk: + case TMS6_and: // Rd = Op1 & Op2 + case TMS6_xor: // Rd = Op1 ^ Op2 + case TMS6_or: // Rd = Op2 | Op1 + case TMS6_cmpeq: + case TMS6_cmpgt: + case TMS6_cmplt: + case TMS6_mpy: + case TMS6_mpyi: + case TMS6_mpyid: + case TMS6_mpysu: + case TMS6_sadd: + case TMS6_ssub: + case TMS6_sub: + case TMS6_set: // Rd = Op1 & ~Op2 + case TMS6_clr: // Rd = Op1 & ~Op2 + case TMS6_ext: // Rd = Op1 & ~Op2 + case TMS6_extu: // Rd = Op1 & ~Op2 + op_dec(insn.ea, n); + break; + } +} + +//---------------------------------------------------------------------- +static void handle_operand(const insn_t &insn, const op_t &x, flags_t F, bool isload) +{ + switch ( x.type ) + { + case o_regpair: + case o_reg: + case o_phrase: + case o_spmask: + case o_stgcyc: + break; + case o_imm: + if ( !isload ) + goto badTouch; + /* no break */ + case o_displ: + set_immd_bit(insn, x.n, F); + if ( op_adds_xrefs(F, x.n) ) + { + int outf = x.type != o_imm ? OOF_ADDR : 0; + if ( x.dtype == dt_word ) + outf |= OOF_SIGNED; + insn.add_off_drefs(x, dr_O, outf); + } + break; + case o_near: + { + ea_t ea = to_ea(insn.cs, x.addr); + ea_t ref = find_first_insn_in_packet(ea); + insn.add_cref(ref, x.offb, fl_JN); + } + break; + default: +badTouch: + INTERR(10380); + } +} + +//---------------------------------------------------------------------- +ea_t find_first_insn_in_packet(ea_t ea) +{ + if ( !is_spec_ea(ea) ) + { + while ( (ea & 0x1F) != 0 ) + { + ea_t ea2 = prev_not_tail(ea); + if ( ea2 == BADADDR + || !is_code(get_flags(ea2)) + || (get_dword(ea2) & BIT0) == 0 ) + { + break; + } + ea = ea2; + } + } + return ea; +} + +//---------------------------------------------------------------------- +inline bool is_tms6_nop(uint32 code) +{ + return (code & 0x21FFEL) == 0; +} + +//---------------------------------------------------------------------- +inline bool is_tms6_bnop(uint32 code) +{ + return (code & 0x00001FFC) == 0x00000120 // Branch Using a Displacement With NOP + || (code & 0x0F830FFE) == 0x00800362; // Branch Using a Register With NOP +} + +//---------------------------------------------------------------------- +static int get_delay(uint32 code) +{ + if ( is_tms6_nop(code) ) // NOP + return int((code >> 13) & 0xF) + 1; + if ( is_tms6_bnop(code) ) // BNOP + return int((code >> 13) & 0x7); + return 1; +} + +//---------------------------------------------------------------------- +struct call_info_t +{ + ea_t mvk; + ea_t mvkh; + uint32 next; + int reg; + call_info_t(ea_t n) : mvk(BADADDR), mvkh(BADADDR), next(n), reg(rB3) {} + bool call_is_present(void) const { return mvk != BADADDR && mvkh != BADADDR; } + void test(ea_t ea, uint32 code); +}; + +//---------------------------------------------------------------------- +inline ushort get_mvk_op(uint32 code) { return ushort(code >> 7); } + +void call_info_t::test(ea_t ea, uint32 code) +{ + if ( (code & 0xF000007CL) == 0x28 && mvk == BADADDR ) + { // unconditional MVK.S + int mvk_reg = int(code >> 23) & 0x1F; + if ( code & BIT1 ) + mvk_reg += rB0; + if ( (reg == -1 || reg == mvk_reg) && ushort(next) == get_mvk_op(code) ) + { + reg = mvk_reg; + mvk = ea; + } + } + else if ( (code & 0xF000007CL) == 0x68 && mvkh == BADADDR ) + { // unconditional MVKH.S + int mvk_reg = int(code >> 23) & 0x1F; + if ( code & BIT1 ) + mvk_reg += rB0; + if ( (reg == -1 || reg == mvk_reg) && ushort(next>>16) == get_mvk_op(code) ) + { + reg = mvk_reg; + mvkh = ea; + } + } +} + +//---------------------------------------------------------------------- +static int calc_packet_delay(ea_t ea, call_info_t *ci) +{ + int delay = 1; + while ( true ) + { + uint32 code = get_dword(ea); + int d2 = get_delay(code); + if ( d2 > delay ) + delay = d2; + ci->test(ea, code); + if ( (code & BIT0) == 0 ) + break; + ea += 4; + if ( !is_code(get_flags(ea)) ) + break; + } + return delay; +} + +//---------------------------------------------------------------------- +static ea_t find_prev_packet(ea_t ea) +{ + ea_t res = BADADDR; + while ( 1 ) + { + ea_t ea2 = prev_not_tail(res != BADADDR ? res : ea); + if ( ea2 == BADADDR ) + break; + if ( !is_code(get_flags(ea2)) ) + break; + res = ea2; + if ( (get_dword(ea2) & BIT0) == 0 ) + break; + } + return res; +} + +//---------------------------------------------------------------------- +static ea_t get_branch_ea(ea_t ea) +{ + while ( 1 ) + { + uint32 code = get_dword(ea); + if ( (code >> 28) == cAL ) + { + switch ( (code >> 2) & 0x1F ) + { + case 0x04: // bcond() + return ea; + case 0x08: // S unit + case 0x18: + { + int opcode = int(code >> 6) & 0x3F; + switch ( opcode ) + { + case 0: // bdec/bpos + case 3: // b irp + case 4: // bnop + case 13: // b + return ea; + } + } + break; + } + } + if ( (code & BIT0) == 0 ) + break; + ea += 4; + if ( !is_code(get_flags(ea)) ) + break; + } + return BADADDR; +} + +//---------------------------------------------------------------------- +int tms6_t::emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + flow = ((Feature & CF_STOP) == 0); + + if ( segtype(insn.ea) == SEG_XTRN ) + { + flow = false; + } + else if ( (insn.cflags & aux_para) == 0 ) // the last instruction of packet + { + // From spru732j.pdf: + // Although branch instructions take one execute phase, there are five + // delay slots between the execution of the branch and execution of the + // target code. + + // We look backwards for five delay slots to check for an unconditionnal + // branch instruction. + + ea_t ea = find_first_insn_in_packet(insn.ea); + int delay = 0; + call_info_t ci(insn.ea+insn.size); + while ( 1 ) + { + // If there are any crefs to this address, we cannot guarantee that + // the branch instruction really got executed. + if ( has_xref(get_flags(ea)) ) + break; + + // Increment delay count for this packet. + delay += calc_packet_delay(ea, &ci); + if ( delay > 5 ) + break; + + // Unless we have a bnop instruction, seek to the previous packet. + bool is_bnop = is_tms6_bnop(get_dword(ea)); + if ( !is_bnop ) + { + ea = find_prev_packet(ea); + if ( ea == BADADDR ) + break; + ea = find_first_insn_in_packet(ea); + } + + ea_t brea; + if ( delay == 5 && (brea=get_branch_ea(ea)) != BADADDR ) + { + // We seeked to the previous packet and it was a bnop. The check + // for delay == 5 is no longer correct, since we did not take into + // account the delays of the bnop instruction itself. + if ( is_tms6_bnop(get_dword(ea)) && !is_bnop ) + break; + + insn_t brins; + calc_packet_delay(ea, &ci); // just to test for MVK/MVKH + bool iscall = ci.call_is_present(); + decode_insn(&brins, brea); + tgtinfo_t tgt; + if ( brins.Op1.type == o_near ) + { + ea_t target = to_ea(brins.cs, brins.Op1.addr); + if ( iscall ) + { + target = find_first_insn_in_packet(target); + brins.add_cref(target, brins.Op1.offb, fl_CN); + if ( !func_does_return(target) ) + flow = false; + } + tgt.type = iscall ? tgtinfo_t::CALL : tgtinfo_t::BRANCH; + tgt.target = target; + } + else + { + tgt.type = iscall ? tgtinfo_t::IND_CALL : tgtinfo_t::IND_BRANCH; + } + if ( !iscall ) + flow = false; + tgt.save_to_idb(*this, insn.ea); + if ( iscall ) + { + if ( !is_off0(get_flags(ci.mvk)) ) + op_offset(ci.mvk, 0, REF_LOW16, ci.next, brins.cs, 0); + if ( !is_off0(get_flags(ci.mvkh)) ) + op_offset(ci.mvkh, 0, REF_HIGH16, ci.next, brins.cs, 0); + } + break; + } + + // We don't check past one bnop instruction. + if ( is_bnop ) + break; + } + } + + flags_t F = get_flags(insn.ea); + if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, F, true); + if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, F, true); + if ( Feature & CF_USE3 ) handle_operand(insn, insn.Op3, F, true); + + if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, F, false); + if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, F, false); + if ( Feature & CF_CHG3 ) handle_operand(insn, insn.Op3, F, false); + + if ( flow ) + add_cref(insn.ea, insn.ea + insn.size, fl_F); + return 1; +} + +//---------------------------------------------------------------------- +int idaapi is_align_insn(ea_t ea) +{ + insn_t insn; + decode_insn(&insn, ea); + switch ( insn.itype ) + { + case TMS6_mv: + if ( insn.Op1.reg == insn.Op2.reg ) + break; + default: + return 0; + case TMS6_nop: + break; + } + return insn.size; +} diff --git a/idasdk75/module/tms320c6/ins.cpp b/idasdk76/module/tms320c6/ins.cpp similarity index 100% rename from idasdk75/module/tms320c6/ins.cpp rename to idasdk76/module/tms320c6/ins.cpp diff --git a/idasdk76/module/tms320c6/ins.hpp b/idasdk76/module/tms320c6/ins.hpp new file mode 100644 index 0000000..2ed4154 --- /dev/null +++ b/idasdk76/module/tms320c6/ins.hpp @@ -0,0 +1,257 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + * TMS320C6xx - VLIW (very long instruction word) architecture + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ +// Original TMS320C62x instructions + +TMS6_null = 0, // Unknown Operation +TMS6_abs, // Absolute value +TMS6_add, // Integer addition without saturation (signed) +TMS6_addu, // Integer addition without saturation (unsigned) +TMS6_addab, // Integer addition using addressing mode (byte) +TMS6_addah, // Integer addition using addressing mode (halfword) +TMS6_addaw, // Integer addition using addressing mode (word) +TMS6_addk, // Integer addition 16bit signed constant +TMS6_add2, // Two 16bit Integer adds on register halves +TMS6_and, // Logical AND +TMS6_b, // Branch +TMS6_clr, // Clear a bit field +TMS6_cmpeq, // Compare for equality +TMS6_cmpgt, // Compare for greater than (signed) +TMS6_cmpgtu, // Compare for greater than (unsigned) +TMS6_cmplt, // Compare for less than (signed) +TMS6_cmpltu, // Compare for less than (unsigned) +TMS6_ext, // Extract and sign-extend a bit filed +TMS6_extu, // Extract an unsigned bit field +TMS6_idle, // Multicycle NOP with no termination until interrupt +TMS6_ldb, // Load from memory (signed 8bit) +TMS6_ldbu, // Load from memory (unsigned 8bit) +TMS6_ldh, // Load from memory (signed 16bit) +TMS6_ldhu, // Load from memory (unsigned 16bit) +TMS6_ldw, // Load from memory (32bit) +TMS6_lmbd, // Leftmost bit detection +TMS6_mpy, // Signed Integer Multiply (LSB16 x LSB16) +TMS6_mpyu, // Unsigned Integer Multiply (LSB16 x LSB16) +TMS6_mpyus, // Integer Multiply Signed*Unsigned (LSB16 x LSB16) +TMS6_mpysu, // Integer Multiply Unsigned*Signed (LSB16 x LSB16) +TMS6_mpyh, // Signed Integer Multiply (MSB16 x MSB16) +TMS6_mpyhu, // Unsigned Integer Multiply (MSB16 x MSB16) +TMS6_mpyhus, // Integer Multiply Unsigned*Signed (MSB16 x MSB16) +TMS6_mpyhsu, // Integer Multiply Signed*Unsigned (MSB16 x MSB16) +TMS6_mpyhl, // Signed Integer Multiply (MSB16 x LSB16) +TMS6_mpyhlu, // Unsigned Integer Multiply (MSB16 x LSB16) +TMS6_mpyhuls, // Integer Multiply Signed*Unsigned (MSB16 x LSB16) +TMS6_mpyhslu, // Integer Multiply Unsigned*Signed (MSB16 x LSB16) +TMS6_mpylh, // Signed Integer Multiply (LSB16 x MB16) +TMS6_mpylhu, // Unsigned Integer Multiply (LSB16 x MSB16) +TMS6_mpyluhs, // Integer Multiply Signed*Unsigned (LSB16 x MSB16) +TMS6_mpylshu, // Integer Multiply Unsigned*Signed (LSB16 x MSB16) +TMS6_mv, // Move from register to register +TMS6_mvc, // Move between the control file & register file +TMS6_mvk, // Move a 16bit signed constant into register +TMS6_mvkh, // Move a 16bit constant into the upper bits of a register +TMS6_mvklh, // Move a 16bit constant into the upper bits of a register +TMS6_neg, // Negate +TMS6_nop, // No operation +TMS6_norm, // Normalize +TMS6_not, // Bitwise NOT +TMS6_or, // Logical or +TMS6_sadd, // Integer addition with saturation +TMS6_sat, // Saturate 40bit value to 32bits +TMS6_set, // Set a bit field +TMS6_shl, // Arithmetic shift left +TMS6_shr, // Arithmetic shift right +TMS6_shru, // Logical shift left +TMS6_smpy, // Integer multiply with left shift & saturation (LSB16*LSB16) +TMS6_smpyhl, // Integer multiply with left shift & saturation (MSB16*LSB16) +TMS6_smpylh, // Integer multiply with left shift & saturation (LSB16*MSB16) +TMS6_smpyh, // Integer multiply with left shift & saturation (MSB16*MSB16) +TMS6_sshl, // Shift left with saturation +TMS6_ssub, // Integer substraction with saturation +TMS6_stb, // Store to memory (signed 8bit) +TMS6_stbu, // Store to memory (unsigned 8bit) +TMS6_sth, // Store to memory (signed 16bit) +TMS6_sthu, // Store to memory (unsigned 16bit) +TMS6_stw, // Store to memory (32bit) +TMS6_sub, // Integer substaraction without saturation (signed) +TMS6_subu, // Integer substaraction without saturation (unsigned) +TMS6_subab, // Integer subtraction using addressing mode (byte) +TMS6_subah, // Integer subtraction using addressing mode (halfword) +TMS6_subaw, // Integer subtraction using addressing mode (word) +TMS6_subc, // Conditional subtract & shift (for division) +TMS6_sub2, // Two 16bit integer subtractions on register halves +TMS6_xor, // Exclusive OR +TMS6_zero, // Zero a register + +// New TMS320C674x instructions + +TMS6_abs2, // Absolute Value With Saturation, Signed, Packed 16-bit +TMS6_absdp, // Absolute Value, Double-Precision Floating-Point +TMS6_abssp, // Absolute Value, Single-Precision Floating-Point +TMS6_add4, // Add Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_addad, // Add Using Doubleword Addressing Mode +TMS6_adddp, // Add Two Double-Precision Floating-Point Values +TMS6_addkpc, // Add Signed 7-bit Constant to Program Counter +TMS6_addsp, // Add Two Single-Precision Floating-Point Values +TMS6_addsub, // Parallel ADD and SUB Operations On Common Inputs +TMS6_addsub2, // Parallel ADD2 and SUB2 Operations On Common Inputs +TMS6_andn, // Bitwise AND Invert +TMS6_avg2, // Average, Signed, Packed 16-bit +TMS6_avgu4, // Average, Unsigned, Packed 16-bit +TMS6_bdec, // Branch and Decrement +TMS6_bitc4, // Bit Count, Packed 8-bit +TMS6_bitr, // Bit Reverse +TMS6_bnop, // Branch With NOP +TMS6_bpos, // Branch Positive +TMS6_callp, // Call Using a Displacement +TMS6_cmpeq2, // Compare for Equality, Packed 16-bit +TMS6_cmpeq4, // Compare for Equality, Packed 8-bit +TMS6_cmpeqdp, // Compare for Equality, Double-Precision Floating-Point Values +TMS6_cmpeqsp, // Compare for Equality, Single-Precision Floating-Point Values +TMS6_cmpgt2, // Compare for Greater Than, Packed 16-bit +TMS6_cmpgtdp, // Compare for Greater Than, Double-Precision Floating-Point Values +TMS6_cmpgtsp, // Compare for Greater Than, Single-Precision Floating-Point Values +TMS6_cmpgtu4, // Compare for Greater Than, Unsigned, Packed 8-bit +TMS6_cmplt2, // Compare for Less Than, Packed 16-bit +TMS6_cmpltdp, // Compare for Less Than, Double-Precision Floating-Point Values +TMS6_cmpltsp, // Compare for Less Than, Single-Precision Floating-Point Values +TMS6_cmpltu4, // Compare for Less Than, Unsigned, Packed 8-bit +TMS6_cmpy, // Complex Multiply Two Pairs, Signed, Packed 16-bit +TMS6_cmpyr, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding +TMS6_cmpyr1, // Complex Multiply Two Pairs, Signed, Packed 16-bit With Rounding +TMS6_ddotp4, // Double Dot Product, Signed, Packed 16-Bit and Signed, Packed 8-Bit +TMS6_ddotph2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit +TMS6_ddotph2r, // Double Dot Product With Rounding, Two Pairs, Signed, Packed 16-Bit +TMS6_ddotpl2, // Double Dot Product, Two Pairs, Signed, Packed 16-Bit +TMS6_ddotpl2r, // Double Dot Product With Rounding, Two Pairs, Signed Packed 16-Bit +TMS6_deal, // Deinterleave and Pack +TMS6_dint, // Disable Interrupts and Save Previous Enable State +TMS6_dmv, // Move Two Independent Registers to Register Pair +TMS6_dotp2, // Dot Product, Signed, Packed 16-Bit +TMS6_dotpn2, // Dot Product With Negate, Signed, Packed 16-Bit +TMS6_dotpnrsu2, // Dot Product With Negate, Shift and Round, Signed by Unsigned, Packed 16-Bit +TMS6_dotpnrus2, // Dot Product With Negate, Shift and Round, Unsigned by Signed, Packed 16-Bit +TMS6_dotprsu2, // Dot Product With Shift and Round, Signed by Unsigned, Packed 16-Bit +TMS6_dotprus2, // Dot Product With Shift and Round, Unsigned by Signed, Packed 16-Bit +TMS6_dotpsu4, // Dot Product, Signed by Unsigned, Packed 8-Bit +TMS6_dotpu4, // Dot Product, Unsigned, Packed 8-Bit +TMS6_dotpus4, // Dot Product, Unsigned by Signed, Packed 8-Bit +TMS6_dpack2, // Parallel PACK2 and PACKH2 Operations +TMS6_dpackx2, // Parallel PACKLH2 Operations +TMS6_dpint, // Convert Double-Precision Floating-Point Value to Integer +TMS6_dpsp, // Convert Double-Precision Floating-Point Value to Single-Precision Floating-Point Value +TMS6_dptrunc, // Convert Double-Precision Floating-Point Value to Integer With Truncation +TMS6_gmpy, // Galois Field Multiply +TMS6_gmpy4, // Galois Field Multiply, Packed 8-Bit +TMS6_intdp, // Convert Signed Integer to Double-Precision Floating-Point Value +TMS6_intdpu, // Convert Unsigned Integer to Double-Precision Floating-Point Value +TMS6_intsp, // Convert Signed Integer to Single-Precision Floating-Point Value +TMS6_intspu, // Convert Unsigned Integer to Single-Precision Floating-Point Value +TMS6_lddw, // Load Doubleword From Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_ldndw, // Load Nonaligned Doubleword From Memory With Constant or Register Offset +TMS6_ldnw, // Load Nonaligned Word From Memory With Constant or Register Offset +TMS6_max2, // Maximum, Signed, Packed 16-Bit +TMS6_maxu4, // Maximum, Unsigned, Packed 8-Bit +TMS6_min2, // Minimum, Signed, Packed 16-Bit +TMS6_minu4, // Minimum, Unsigned, Packed 8-Bit +TMS6_mpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB +TMS6_mpy2ir, // Multiply Two 16-Bit x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 32-Bit Result +TMS6_mpy32su, // Multiply Signed 32-Bit x Unsigned 32-Bit Into Signed 64-Bit Result +TMS6_mpy32u, // Multiply Unsigned 32-Bit x Unsigned 32-Bit Into Unsigned 64-Bit Result +TMS6_mpy32us, // Multiply Unsigned 32-Bit x Signed 32-Bit Into Signed 64-Bit Result +TMS6_mpydp, // Multiply Two Double-Precision Floating-Point Values +TMS6_mpyhi, // Multiply 16 MSB x 32-Bit Into 64-Bit Result +TMS6_mpyhir, // Multiply 16 MSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpyi, // Multiply 32-Bit x 32-Bit Into 32-Bit Result +TMS6_mpyid, // Multiply 32-Bit x 32-Bit Into 64-Bit Result +TMS6_mpyih, // Multiply 32-Bit x 16-MSB Into 64-Bit Result +TMS6_mpyihr, // Multiply 32-Bit x 16 MSB, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpyil, // Multiply 32-Bit x 16 LSB Into 64-Bit Result +TMS6_mpyilr, // Multiply 32-Bit x 16 LSB, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpyli, // Multiply 16 LSB x 32-Bit Into 64-Bit Result +TMS6_mpylir, // Multiply 16 LSB x 32-Bit, Shifted by 15 to Produce a Rounded 32-Bit Result +TMS6_mpysp, // Multiply Two Single-Precision Floating-Point Values +TMS6_mpysp2dp, // Multiply Two Single-Precision Floating-Point Values for Double-Precision Result +TMS6_mpyspdp, // Multiply Single-Precision Floating-Point Value x Double-Precision Floating-Point Value +TMS6_mpysu4, // Multiply Signed x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_mpyu4, // Multiply Unsigned x Unsigned, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_mpyus4, // Multiply Unsigned x Signed, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_mvd, // Move From Register to Register, Delayed +TMS6_mvkl, // Move Signed Constant Into Register and Sign Extend +TMS6_pack2, // Pack Two 16 LSBs Into Upper and Lower Register Halves +TMS6_packh2, // Pack Two 16 MSBs Into Upper and Lower Register Halves +TMS6_packh4, // Pack Four High Bytes Into Four 8-Bit Halfwords +TMS6_packhl2, // Pack 16 MSB Into Upper and 16 LSB Into Lower Register Halves +TMS6_packl4, // Pack Four Low Bytes Into Four 8-Bit Halfwords +TMS6_packlh2, // Pack 16 LSB Into Upper and 16 MSB Into Lower Register Halves +TMS6_rcpdp, // Double-Precision Floating-Point Reciprocal Approximation +TMS6_rcpsp, // Single-Precision Floating-Point Reciprocal Approximation +TMS6_rint, // Restore Previous Enable State +TMS6_rotl, // Rotate Left +TMS6_rpack2, // Shift With Saturation and Pack Two 16 MSBs Into Upper and Lower Register Halves +TMS6_rsqrdp, // Double-Precision Floating-Point Square-Root Reciprocal Approximation +TMS6_rsqrsp, // Single-Precision Floating-Point Square-Root Reciprocal Approximation +TMS6_sadd2, // Add Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation +TMS6_saddsu2, // Add Two Signed and Unsigned 16-Bit Integers on Register Halves With Saturation +TMS6_saddsub, // Parallel SADD and SSUB Operations On Common Inputs +TMS6_saddsub2, // Parallel SADD2 and SSUB2 Operations On Common Inputs +TMS6_saddu4, // Add With Saturation, Four Unsigned 8-Bit Pairs for Four 8-Bit Results +TMS6_saddus2, // Add Two Unsigned and Signed 16-Bit Integers on Register Halves With Saturation +TMS6_shfl, // Shuffle +TMS6_shfl3, // 3-Way Bit Interleave On Three 16-Bit Values Into a 48-Bit Result +TMS6_shlmb, // Shift Left and Merge Byte +TMS6_shr2, // Arithmetic Shift Right, Signed, Packed 16-Bit +TMS6_shrmb, // Shift Right and Merge Byte +TMS6_shru2, // Arithmetic Shift Right, Unsigned, Packed 16-Bit +TMS6_smpy2, // Multiply Signed by Signed, 16 LSB x 16 LSB and 16 MSB x 16 MSB With Left Shift and Saturation +TMS6_smpy32, // Multiply Signed 32-Bit x Signed 32-Bit Into 64-Bit Result With Left Shift and Saturation +TMS6_spack2, // Saturate and Pack Two 16 LSBs Into Upper and Lower Register Halves +TMS6_spacku4, // Saturate and Pack Four Signed 16-Bit Integers Into Four Unsigned 8-Bit Halfwords +TMS6_spdp, // Convert Single-Precision Floating-Point Value to Double-Precision Floating-Point Value +TMS6_spint, // Convert Single-Precision Floating-Point Value to Integer +TMS6_spkernel, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary +TMS6_spkernelr, // Software Pipelined Loop (SPLOOP) Buffer Operation Code Boundary +TMS6_sploop, // Software Pipelined Loop (SPLOOP) Buffer Operation +TMS6_sploopd, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing +TMS6_sploopw, // Software Pipelined Loop (SPLOOP) Buffer Operation With Delayed Testing and No Epilog +TMS6_spmask, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control +TMS6_spmaskr, // Software Pipelined Loop (SPLOOP) Buffer Operation Load/Execution Control +TMS6_sptrunc, // Convert Single-Precision Floating-Point Value to Integer With Truncation +TMS6_sshvl, // Variable Shift Left +TMS6_sshvr, // Variable Shift Right +TMS6_ssub2, // Subtract Two Signed 16-Bit Integers on Upper and Lower Register Halves With Saturation +TMS6_stdw, // Store Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_stndw, // Store Nonaligned Doubleword to Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_stnw, // Store Nonaligned Word to Memory With a 5-Bit Unsigned Constant Offset or Register Offset +TMS6_sub4, // Subtract Without Saturation, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_subabs4, // Subtract With Absolute Value, Four 8-Bit Pairs for Four 8-Bit Results +TMS6_subdp, // Subtract Two Double-Precision Floating-Point Values +TMS6_subsp, // Subtract Two Single-Precision Floating-Point Values +TMS6_swap2, // Swap Bytes in Upper and Lower Register Halves +TMS6_swap4, // Swap Byte Pairs in Upper and Lower Register Halves +TMS6_swe, // Software Exception +TMS6_swenr, // Software Exception, no Return +TMS6_unpkhu4, // Unpack 16 MSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves +TMS6_unpklu4, // Unpack 16 LSB Into Two Lower 8-Bit Halfwords of Upper and Lower Register Halves +TMS6_xormpy, // Galois Field Multiply With Zero Polynomial +TMS6_xpnd2, // Expand Bits to Packed 16-Bit Masks +TMS6_xpnd4, // Expand Bits to Packed 8-Bit Masks + +TMS6_last, + + }; + +#endif diff --git a/idasdk76/module/tms320c6/makefile b/idasdk76/module/tms320c6/makefile new file mode 100644 index 0000000..2155de9 --- /dev/null +++ b/idasdk76/module/tms320c6/makefile @@ -0,0 +1,51 @@ +PROC=tms320c6 + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + tms6.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp emu.cpp ins.hpp \ + tms6.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ + tms6.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \ + tms6.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp reg.cpp \ + tms6.hpp diff --git a/idasdk76/module/tms320c6/out.cpp b/idasdk76/module/tms320c6/out.cpp new file mode 100644 index 0000000..64a560f --- /dev/null +++ b/idasdk76/module/tms320c6/out.cpp @@ -0,0 +1,505 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + * + * TMS320C6xx - VLIW (very long instruction word) architecture + * + */ + +#include "tms6.hpp" + +// simple wrapper class for syntactic sugar of member functions +// this class may have only simple member functions. +// virtual functions and data fields are forbidden, otherwise the class +// layout may change +class out_tms320c6_t : public outctx_t +{ + out_tms320c6_t(void) = delete; // not used +public: + bool out_operand(const op_t &x); + void out_insn(void); + void outreg(int r) { out_register(ph.reg_names[r]); } + void out_pre_mode(int mode); + void out_post_mode(int mode); + void print_stg_cyc(ea_t ea, int stgcyc); + bool tms6_out_name_expr(const op_t &x, uval_t opval); +}; +CASSERT(sizeof(out_tms320c6_t) == sizeof(outctx_t)); + +DECLARE_OUT_FUNCS_WITHOUT_OUTMNEM(out_tms320c6_t) + +//---------------------------------------------------------------------- +static bool is_first_insn_in_exec_packet(ea_t ea) +{ +// if ( (ea & 0x1F) == 0 ) +// return 1; + ea = prev_not_tail(ea); + return ea == BADADDR + || !is_code(get_flags(ea)) + || (get_dword(ea) & BIT0) == 0; +} + +//---------------------------------------------------------------------- +static bool prev_complex(const insn_t &insn) +{ + ea_t ea = prev_not_tail(insn.ea); + if ( ea == BADADDR || !is_code(get_flags(ea)) ) + return 0; + return !is_first_insn_in_exec_packet(ea); +} + +//---------------------------------------------------------------------- +void out_tms320c6_t::out_pre_mode(int mode) +{ + out_symbol('*'); + switch ( mode ) + { + case 0x08: // 1000 *--R[cst] + case 0x0C: // 1100 *--Rb[Ro] + out_symbol('-'); + // fallthrough + case 0x00: // 0000 *-R[cst] + case 0x04: // 0100 *-Rb[Ro] + out_symbol('-'); + break; + case 0x09: // 1001 *++R[cst] + case 0x0D: // 1101 *++Rb[Ro] + out_symbol('+'); + out_symbol('+'); + break; + case 0x01: // 0001 *+R[cst] + case 0x05: // 0101 *+Rb[Ro] +// out_symbol('+'); + break; + case 0x0A: // 1010 *R--[cst] + case 0x0B: // 1011 *R++[cst] + case 0x0E: // 1110 *Rb--[Ro] + case 0x0F: // 1111 *Rb++[Ro] + break; + } +} + +//---------------------------------------------------------------------- +void out_tms320c6_t::out_post_mode(int mode) +{ + switch ( mode ) + { + case 0x08: // 1000 *--R[cst] + case 0x0C: // 1100 *--Rb[Ro] + case 0x00: // 0000 *-R[cst] + case 0x04: // 0100 *-Rb[Ro] + case 0x09: // 1001 *++R[cst] + case 0x0D: // 1101 *++Rb[Ro] + case 0x01: // 0001 *+R[cst] + case 0x05: // 0101 *+Rb[Ro] + break; + case 0x0A: // 1010 *R--[cst] + case 0x0E: // 1110 *Rb--[Ro] + out_symbol('-'); + out_symbol('-'); + break; + case 0x0B: // 1011 *R++[cst] + case 0x0F: // 1111 *Rb++[Ro] + out_symbol('+'); + out_symbol('+'); + break; + } +} + +//---------------------------------------------------------------------- +struct ii_info_t +{ + char ii; + char cyc; +}; + +static const ii_info_t ii_info[] = +{ + { 1, 0 }, + { 2, 1 }, + { 4, 2 }, + { 8, 3 }, + { 14, 4 }, +}; + +void out_tms320c6_t::print_stg_cyc(ea_t ea, int stgcyc) +{ + int ii = 1; + insn_t prev; + for ( int i=0; i < 14 && decode_prev_insn(&prev, ea) != BADADDR; i++ ) + { + if ( prev.itype == TMS6_sploop + || prev.itype == TMS6_sploopd + || prev.itype == TMS6_sploopw ) + { + ii = prev.Op1.value; + break; + } + ea = prev.ea; + } + for ( int i=0; i < qnumber(ii_info); i++ ) + { + if ( ii_info[i].ii >= ii ) + { + int cyc = ii_info[i].cyc; + int stg = 0; + int stgbits = 6 - cyc; + int bit = 1 << cyc; + for ( int j=0; j < stgbits; j++, bit<<=1 ) + { + stg <<= 1; + if ( stgcyc & bit ) + stg |= 1; + } + cyc = stgcyc & ((1<<cyc)-1); + out_long(stg, 10); + out_symbol(','); + out_long(cyc, 10); + break; + } + } +} + +//---------------------------------------------------------------------- +bool out_tms320c6_t::tms6_out_name_expr(const op_t &x, uval_t opval) +{ + ea_t ea = to_ea(insn.cs, opval); + ea_t safe = find_first_insn_in_packet(ea); + adiff_t delta = ea - safe; + if ( !out_name_expr(x, safe, opval - delta) ) + return false; + if ( delta > 0 ) + { + out_symbol('+'); + out_long(delta, 16); + } + return true; +} + +//---------------------------------------------------------------------- +bool out_tms320c6_t::out_operand(const op_t &x) +{ + switch ( x.type ) + { + case o_void: + return 0; + + case o_reg: + outreg(x.reg); + break; + + case o_regpair: + outreg(x.reg + 1); + out_symbol(':'); + outreg(x.reg); + break; + + case o_imm: + { + uchar sign = insn.itype == TMS6_mvkh + || insn.itype == TMS6_mvklh + || (insn.itype == TMS6_mvk && is_mvk_scst16_form(insn.ea)) + ? 0 + : OOF_SIGNED; + out_value(x, OOFS_IFSIGN|OOFW_IMM|sign); + break; + } + + case o_stgcyc: + print_stg_cyc(insn.ea, x.value); + break; + + case o_near: + if ( !tms6_out_name_expr(x, x.addr) ) + { + out_tagon(COLOR_ERROR); + out_btoa(x.addr, 16); + out_tagoff(COLOR_ERROR); + remember_problem(PR_NONAME, insn.ea); + } + break; + + case o_phrase: + out_pre_mode(x.mode); + outreg(x.reg); + out_post_mode(x.mode); + out_symbol('['); + outreg(x.secreg); + out_symbol(']'); + break; + + case o_displ: + out_pre_mode(x.mode); + outreg(x.reg); + out_post_mode(x.mode); + { + if ( x.addr != 0 || is_off(F, x.n) ) + { + if ( is_off(F, x.n) ) + { + out_symbol('('); + out_value(x, OOF_ADDR|OOFS_IFSIGN|OOFW_IMM|OOF_SIGNED|OOFW_32); + out_symbol(')'); + } + else + { + out_symbol('['); + out_value(x, OOF_ADDR|OOFS_IFSIGN|OOFW_IMM|OOF_SIGNED|OOFW_32); + out_symbol(']'); + } + } + } + break; + + case o_spmask: + { + static const char units[] = "LLSSDDMM"; + uchar mask = x.reg; + bool need_comma = false; + for ( int i=0; i < 8; i++, mask>>=1 ) + { + if ( mask & 1 ) + { + if ( need_comma ) + out_symbol(','); + out_tagon(COLOR_KEYWORD); + out_char(units[i]); + out_char('1'+(i&1)); + out_tagoff(COLOR_KEYWORD); + need_comma = true; + } + } + } + break; + + default: + warning("out: %a: bad optype %d", insn.ea, x.type); + break; + } + return 1; +} + +//---------------------------------------------------------------------- +void out_tms320c6_t::out_insn(void) +{ +// +// Parallel instructions +// + ea_t ea = insn.ea; + if ( !is_first_insn_in_exec_packet(ea) ) + { + out_symbol('|'); + out_symbol('|'); + } + else + { + if ( !has_any_name(F) + && (prev_complex(insn) || insn.cflags & aux_para) ) + { + gen_empty_line(); + } + out_char(' '); + out_char(' '); + } + +// +// Condition code +// + static const char *const conds[] = + { + " ", " ", "[B0] ", "[!B0]", + "[B1] ", "[!B1]", "[B2] ", "[!B2]", + "[A1] ", "[!A1]", "[A2] ", "[!A2]", + "[A0] ", "[!A0]", " ", " " + }; + out_keyword(conds[insn.cond]); + out_char(' '); + +// +// Instruction name +// + out_mnemonic(); +// +// Functional unit +// + static const char *const units[] = + { + NULL, + ".L1", ".L2", + ".S1", ".S2", + ".M1", ".M2", + ".D1", ".D2", + }; + if ( insn.funit != FU_NONE ) + out_keyword(units[uchar(insn.funit)]); + else + out_line(" "); + if ( insn.cflags & aux_xp ) + out_keyword("X"); + else + out_char(' '); + out_line(" "); + +// +// Operands +// + if ( (insn.cflags & aux_src2) != 0 ) + { + outreg(insn.Op1.src2); + out_symbol(','); + out_char(' '); + } + + if ( insn.Op1.shown() ) + out_one_operand(0); + + if ( insn.Op2.type != o_void && insn.Op2.shown() ) + { + out_symbol(','); + out_char(' '); + out_one_operand(1); + } + + + if ( insn.Op3.type != o_void && insn.Op3.shown() ) + { + out_symbol(','); + out_char(' '); + out_one_operand(2); + } + + out_immchar_cmts(); + + int indent = inf_get_indent() - 8; // reserve space for conditions + if ( indent <= 1 ) // too little space? + indent = 2; // pass -2, which means one space + // (-1 would mean 'use DEFAULT_INDENT') + flush_outbuf(-indent); // negative value means 'print opcodes here' + + if ( (insn.cflags & aux_para) == 0 ) + { + tms6_t &pm = *static_cast<tms6_t *>(procmod); + tgtinfo_t tgt; + if ( tgt.restore_from_idb(pm, ea) ) + { + qstring buf = tgt.get_type_name(); + if ( tgt.has_target() ) + { + qstring name = get_colored_name(tgt.target); + buf.append(" "); + buf.append(name); + } + gen_printf(DEFAULT_INDENT, + COLSTR("; %s OCCURS", SCOLOR_AUTOCMT), + buf.c_str()); + } + } +} + +//-------------------------------------------------------------------------- +//lint -e{818} seg could be const +void idaapi segstart(outctx_t &ctx, segment_t *seg) +{ + if ( is_spec_segm(seg->type) ) + return; + + qstring sname; + get_segm_name(&sname, seg); + + if ( sname == ".bss" ) + return; + if ( sname == ".text" || sname == ".data" ) + { + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR), sname.c_str()); + } + else + { + validate_name(&sname, VNT_IDENT); + ctx.gen_printf(DEFAULT_INDENT, COLSTR(".sect \"%s\"", SCOLOR_ASMDIR), sname.c_str()); + } +} + +//-------------------------------------------------------------------------- +void idaapi segend(outctx_t &, segment_t *) +{ +} + +//-------------------------------------------------------------------------- +void idaapi header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_ALL); +} + +//-------------------------------------------------------------------------- +void tms6_t::footer(outctx_t &ctx) const +{ + qstring nbuf = get_colored_name(inf_get_start_ea()); + const char *name = nbuf.c_str(); + const char *end = ash.end; + if ( end == NULL ) + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s end %s", SCOLOR_AUTOCMT), ash.cmnt, name); + else + ctx.gen_printf(DEFAULT_INDENT, COLSTR("%s", SCOLOR_ASMDIR) + " " + COLSTR("%s %s", SCOLOR_AUTOCMT), ash.end, ash.cmnt, name); +} + +//-------------------------------------------------------------------------- +void idaapi data(outctx_t &ctx, bool analyze_only) +{ + ea_t ea = ctx.insn_ea; + segment_t *s = getseg(ea); + if ( s != NULL ) + { + qstring sname; + if ( get_segm_name(&sname, s) > 0 && sname == ".bss" ) + { + qstring name; + if ( get_colored_name(&name, ea) <= 0 ) + name.sprnt(COLSTR("bss_dummy_name_%a", SCOLOR_UNKNAME), ea); + char num[MAX_NUMBUF]; + btoa(num, sizeof(num), get_item_size(ea), get_radix(ctx.F, 0)); + ctx.ctxflags |= CTXF_LABEL_OK; + ctx.gen_printf(-1, + COLSTR(".bss", SCOLOR_KEYWORD) + " %s, " + COLSTR("%s", SCOLOR_DNUM), + name.begin(), + num); + return; + } + } + ctx.out_data(analyze_only); +} + +//-------------------------------------------------------------------------- +//lint -e{1764} ctx could be const +bool tms6_t::outspec(outctx_t &ctx, uchar stype) const +{ + ea_t ea = ctx.insn_ea; + qstring nbuf; + if ( get_colored_name(&nbuf, ea) <= 0 ) + return false; + const char *name = nbuf.begin(); + char buf[MAX_NUMBUF]; + switch ( stype ) + { + case SEG_XTRN: + return ctx.gen_printf(-1, COLSTR("%s %s", SCOLOR_ASMDIR), ash.a_extrn,name); + case SEG_ABSSYM: + // i don't know how to declare absolute symbols. + // perhaps, like this? + btoa(buf, sizeof(buf), get_dword(ea)); + return ctx.gen_printf(-1, COLSTR("%s = %s", SCOLOR_ASMDIR), name, buf); + case SEG_COMM: + btoa(buf, sizeof(buf), get_dword(ea)); + ctx.gen_printf(-1, + COLSTR("%s \"%s\", %s", SCOLOR_ASMDIR), + ash.a_comdef, name, buf); + } + return false; +} diff --git a/idasdk76/module/tms320c6/reg.cpp b/idasdk76/module/tms320c6/reg.cpp new file mode 100644 index 0000000..34b6c64 --- /dev/null +++ b/idasdk76/module/tms320c6/reg.cpp @@ -0,0 +1,415 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + * + * TMS320C6xx - VLIW (very long instruction word) architecture + * + */ + +#include "tms6.hpp" +int data_id; + +//-------------------------------------------------------------------------- +// B14 - data page pointer +// B15 - stack pointer +static const char *const RegNames[] = +{ + "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", + "A8", "A9", "A10", "A11", "A12", "A13", "A14", "A15", + "A16", "A17", "A18", "A19", "A20", "A21", "A22", "A23", + "A24", "A25", "A26", "A27", "A28", "A29", "A30", "A31", + "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", + "B8", "B9", "B10", "B11", "B12", "B13", "B14", "B15", + "B16", "B17", "B18", "B19", "B20", "B21", "B22", "B23", + "B24", "B25", "B26", "B27", "B28", "B29", "B30", "B31", + "AMR", + "CSR", + "IFR", + "ISR", + "ICR", + "IER", + "ISTP", + "IRP", + "NRP", + "ACR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com> + "ADR", // undocumented, info from Jeff Bailey <jeff_bailey@infinitek.com> + "PCE1", + "FADCR", + "FAUCR", + "FMCR", + "TSCL", + "TSCH", + "ILC", + "RILC", + "REP", + "DNUM", + "SSR", + "GPLYA", + "GPLYB", + "GFPGFR", + "TSR", + "ITSR", + "NTSR", + "ECR", + "EFR", + "IERR", + "CS", "DS" +}; + +//-------------------------------------------------------------------------- +ssize_t idaapi idb_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case idb_event::segm_moved: // A segment is moved + // Fix processor dependent address sensitive information + { + ea_t from = va_arg(va, ea_t); + ea_t to = va_arg(va, ea_t); + asize_t size = va_arg(va, asize_t); + bool changed_netmap = va_argi(va, bool); + if ( !changed_netmap ) + { + nodeidx_t ndx1 = ea2node(from); + nodeidx_t ndx2 = ea2node(to); + pm.helper.altshift(ndx1, ndx2, size); + // like altadjust() + for ( nodeidx_t ndx = pm.helper.supfirst(); + ndx != BADADDR; + ndx = pm.helper.supnext(ndx) ) + { + tgtinfo_t tgt; + ea_t ea = node2ea(ndx); + tgt.restore_from_idb(pm, ea); + if ( tgt.has_target() ) + { + tgt.target = correct_address(tgt.target, from, to, size); + tgt.save_to_idb(pm, ea); + } + } + } + } + break; + } + return 0; +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(tms6_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi tms6_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + hook_event_listener(HT_IDB, &idb_listener, &LPH); + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + unhook_event_listener(HT_IDB, &idb_listener); + clr_module_data(data_id); + break; + + case processor_t::ev_oldfile: + { + netnode old_tnode("$ tms node"); + if ( old_tnode != BADNODE ) + { + upgrade_tnode(old_tnode); + old_tnode.kill(); + } + } + // no break + case processor_t::ev_ending_undo: + case processor_t::ev_newfile: + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + segend(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + data(*ctx, analyze_only); + return 1; + } + + case processor_t::ev_out_special_item: + { + outctx_t *ctx = va_arg(va, outctx_t *); + uchar seg_type = va_argi(va, uchar); + outspec(*ctx, seg_type); + return 1; + } + + case processor_t::ev_is_align_insn: + { + ea_t ea = va_arg(va, ea_t); + return is_align_insn(ea); + } + + + default: + break; + } + return code; +} + +//------------------------------------------------------------------------- +void tms6_t::upgrade_tnode(const netnode &old_tnode) +{ + // copy branch/call info to HELPER + for ( nodeidx_t ndx = old_tnode.altfirst(); + ndx != BADADDR; + ndx = old_tnode.altnext(ndx) ) + { + nodeidx_t ndx2 = old_tnode.altval(ndx); + if ( ndx2 == 0 ) + continue; + tgtinfo_t tgt; + switch ( ndx2 ) + { + case 1: + tgt.type = tgtinfo_t::IND_BRANCH; + break; + case 2: + tgt.type = tgtinfo_t::IND_CALL; + break; + default: + { + ea_t target = node2ea(ndx2); + tgt.type = (target & 1) != 0 + ? tgtinfo_t::BRANCH + : tgtinfo_t::CALL; + tgt.target = target & ~1; + } + break; + } + tgt.save_to_idb(*this, node2ea(ndx)); + } +} + +//------------------------------------------------------------------------- +const char *tgtinfo_t::get_type_name() const +{ + switch ( type ) + { + case tgtinfo_t::CALL: return "CALL"; + case tgtinfo_t::BRANCH: return "BRANCH"; + case tgtinfo_t::IND_CALL: return "INDIRECT CALL"; + case tgtinfo_t::IND_BRANCH: return "INDIRECT BRANCH"; + } + return ""; +} + +//------------------------------------------------------------------------- +#define TGTINFO_MAX_SIZE (1 + ea_packed_size) +void tgtinfo_t::save_to_idb(tms6_t &pm, ea_t ea) const +{ + uchar buf[TGTINFO_MAX_SIZE]; + uchar *ptr = buf; + uchar *end = buf + sizeof(buf); + ptr = pack_db(ptr, end, uchar(type)); + if ( has_target() ) + ptr = pack_ea(ptr, end, ea2node(target)); + pm.helper.supset_ea(ea, buf, ptr - buf); +} + +//------------------------------------------------------------------------- +bool tgtinfo_t::restore_from_idb(const tms6_t &pm, ea_t ea) +{ + uchar buf[TGTINFO_MAX_SIZE]; + ssize_t code = pm.helper.supval_ea(ea, buf, sizeof(buf)); + if ( code < 1 ) + return false; + memory_deserializer_t mmdsr(buf, code); + uchar t = mmdsr.unpack_db(); + if ( t > IND_BRANCH ) + return false; + type = type_t(t); + if ( has_target() ) + target = node2ea(mmdsr.unpack_ea()); + return true; +} + +//----------------------------------------------------------------------- +// TMS320C6x COFF Assembler +//----------------------------------------------------------------------- +static const asm_t dspasm = +{ + AS_COLON | ASH_HEXF0 | ASD_DECF0 | ASB_BINF0 | ASO_OCTF5, + 0, + "TMS320C6x COFF Assembler", + 0, + NULL, // header lines + NULL, // org + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".string", // ascii string directive + ".char", // byte directive + ".short", // word directive + ".long", // double words + NULL, // no qwords + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".space %s", // uninited arrays + ".set", // equ + NULL, // 'seg' prefix (example: push seg seg001) + "$", // current IP (instruction pointer) + NULL, // func_header + NULL, // func_footer + ".def", // "public" name keyword + NULL, // "weak" name keyword + ".ref", // "extrn" name keyword + ".usect", // "comm" (communal variable) + NULL, // get_type_name + ".align", // "align" keyword + '(', ')', // lbrace, rbrace + NULL, // mod + "&", // and + "|", // or + "^", // xor + "!", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + + +static const asm_t *const asms[] = { &dspasm, NULL }; +//----------------------------------------------------------------------- +#define FAMILY "TMS320C6 series:" +static const char *const shnames[] = { "TMS320C6", NULL }; +static const char *const lnames[] = +{ + FAMILY"Texas Instruments TMS320C6xxx", + NULL +}; + +//-------------------------------------------------------------------------- +static const uchar retcode_1[] = { 0x62, 0x63, 0x0C, 0x00 }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_TMSC6, // id + // flag + PR_USE32 + | PR_DEFSEG32 + | PR_DELAYED + | PR_ALIGN_INSN, // allow align instructions + // flag2 + 0, + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + asms, + + notify, + + RegNames, // Register names + qnumber(RegNames), // Number of registers + + rVcs, // first + rVds, // last + 0, // size of a segment register + rVcs, rVds, + + NULL, // No known code start sequences + retcodes, + + TMS6_null, + TMS6_last, + Instructions, // instruc + 0, // int tbyte_size; + { 2, 4, 8, 12 }, // char real_width[4]; + TMS6_null, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/tms320c6/tms6.hpp b/idasdk76/module/tms320c6/tms6.hpp new file mode 100644 index 0000000..6a07212 --- /dev/null +++ b/idasdk76/module/tms320c6/tms6.hpp @@ -0,0 +1,225 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-98 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * E-mail: ig@estar.msk.su + * FIDO: 2:5020/209 + * + * + * TMS320C6xx - VLIW (very long instruction word) architecture + * + */ + +#ifndef _TMS6_HPP +#define _TMS6_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" + +#define PROCMOD_NAME tms6 +#define PROCMOD_NODE_NAME "$ tms" + +//------------------------------------------------------------------------- +DECLARE_PROC_LISTENER(idb_listener_t, struct tms6_t); + +struct tms6_t : public procmod_t +{ + netnode helper; // supval(ea) -> branch/call info, see tgtinfo_t + idb_listener_t idb_listener = idb_listener_t(*this); + bool flow = false; + + ssize_t idaapi on_event(ssize_t msgid, va_list va); + int emu(const insn_t &insn); + void footer(outctx_t &ctx) const; + bool outspec(outctx_t &ctx, uchar stype) const; + + void upgrade_tnode(const netnode &old_tnode); +}; +extern int data_id; + +//------------------------------------------------------------------------- +struct tgtinfo_t +{ + enum type_t { CALL, BRANCH, IND_CALL, IND_BRANCH }; + type_t type; + ea_t target; + bool has_target() const { return type == CALL || type == BRANCH; } + const char *get_type_name() const; + void save_to_idb(tms6_t &pm, ea_t ea) const; + bool restore_from_idb(const tms6_t &pm, ea_t ea); +}; + +//--------------------------------- +// Functional units: + +#ifdef _MSC_VER +#define ENUM8BIT : uint8 +#else +#define ENUM8BIT +#endif +enum funit_t ENUM8BIT +{ + FU_NONE, // No unit (NOP, IDLE) + FU_L1, FU_L2, // 32/40-bit arithmetic and compare operations + // Leftmost 1 or 0 bit counting for 32 bits + // Normalization count for 32 and 40 bits + // 32-bit logical operations + + FU_S1, FU_S2, // 32-bit arithmetic operations + // 32/40-bit shifts and 32-bit bit-field operations + // 32-bit logical operations + // Branches + // Constant generation + // Register transfers to/from the control register file (.S2 only) + + FU_M1, FU_M2, // 16 x 16 bit multiply operations + + FU_D1, FU_D2, // 32-bit add, subtract, linear and circular address calculation + // Loads and stores with a 5-bit constant offset + // Loads and stores with 15-bit constant offset (.D2 only) +}; + +//--------------------------------- +// Operand types: +#define o_regpair o_idpspec0 // Register pair (A1:A0..B15:B14) + // Register pair is denoted by its + // even register in op.reg + // (Odd register keeps MSB) + +#define o_spmask o_idpspec1 // unit mask (reg) +#define o_stgcyc o_idpspec2 // fstg/fcyc (value) + + +// o_phrase: the second register is held in secreg (specflag1) +#define secreg specflag1 +// o_phrase, o_displ: mode +#define mode specflag2 + +#define src2 specflag2 // for field instructions + +//------------------------------------------------------------------ +#define funit segpref // Functional unit for insn +#define cond auxpref_u8[0] // The condition code of instruction +#define cflags auxpref_u8[1] // Various bit definitions: +# define aux_para 0x0001 // parallel execution with the next insn +# define aux_src2 0x0002 // src2 register for immediate form of + // field instructions is present at "Op1.src2" +# define aux_xp 0x0004 // X path is used +# define aux_pseudo 0x0008 // Pseudo instruction + +//------------------------------------------------------------------ +// condition codes: +#define cAL 0x0 // unconditional +#define cB0 0x2 // B0 +#define cnB0 0x3 // !B0 +#define cB1 0x4 // B1 +#define cnB1 0x5 // !B1 +#define cB2 0x6 // B2 +#define cnB2 0x7 // !B2 +#define cA1 0x8 // A1 +#define cnA1 0x9 // !A1 +#define cA2 0xA // A2 +#define cnA2 0xB // !A2 + +//------------------------------------------------------------------ +// Bit definitions. Just for convenience: +#define BIT0 0x00000001L +#define BIT1 0x00000002L +#define BIT2 0x00000004L +#define BIT3 0x00000008L +#define BIT4 0x00000010L +#define BIT5 0x00000020L +#define BIT6 0x00000040L +#define BIT7 0x00000080L +#define BIT8 0x00000100L +#define BIT9 0x00000200L +#define BIT10 0x00000400L +#define BIT11 0x00000800L +#define BIT12 0x00001000L +#define BIT13 0x00002000L +#define BIT14 0x00004000L +#define BIT15 0x00008000L +#define BIT16 0x00010000L +#define BIT17 0x00020000L +#define BIT18 0x00040000L +#define BIT19 0x00080000L +#define BIT20 0x00100000L +#define BIT21 0x00200000L +#define BIT22 0x00400000L +#define BIT23 0x00800000L +#define BIT24 0x01000000L +#define BIT25 0x02000000L +#define BIT26 0x04000000L +#define BIT27 0x08000000L +#define BIT28 0x10000000L +#define BIT29 0x20000000L +#define BIT30 0x40000000L +#define BIT31 0x80000000L + +//------------------------------------------------------------------ +enum RegNo ENUM8BIT +{ + rA0, rA1, rA2, rA3, rA4, rA5, rA6, rA7, + rA8, rA9, rA10, rA11, rA12, rA13, rA14, rA15, + rA16, rA17, rA18, rA19, rA20, rA21, rA22, rA23, + rA24, rA25, rA26, rA27, rA28, rA29, rA30, rA31, + rB0, rB1, rB2, rB3, rB4, rB5, rB6, rB7, + rB8, rB9, rB10, rB11, rB12, rB13, rB14, rB15, + rB16, rB17, rB18, rB19, rB20, rB21, rB22, rB23, + rB24, rB25, rB26, rB27, rB28, rB29, rB30, rB31, + rAMR, + rCSR, + rIFR, + rISR, + rICR, + rIER, + rISTP, + rIRP, + rNRP, + rACR, + rADR, + rPCE1, + rFADCR, + rFAUCR, + rFMCR, + rTSCL, + rTSCH, + rILC, + rRILC, + rREP, + rDNUM, + rSSR, + rGPLYA, + rGPLYB, + rGFPGFR, + rTSR, + rITSR, + rNTSR, + rECR, + rEFR, + rIERR, + rVcs, rVds, // virtual registers for code and data segments +}; + +//------------------------------------------------------------------ +// XXX this assumes the non-compact encoding +inline bool is_mvk_scst16_form(ea_t ea) +{ + return ((get_dword(ea) >> 2) & 0x1F) == 0xA; +} + +//------------------------------------------------------------------ +void idaapi header(outctx_t &ctx); + +void idaapi segstart(outctx_t &ctx, segment_t *seg); +void idaapi segend(outctx_t &ctx, segment_t *seg); + +void idaapi data(outctx_t &ctx, bool analyze_only); + +int idaapi ana(insn_t *insn); + +int idaapi is_align_insn(ea_t ea); + +ea_t find_first_insn_in_packet(ea_t ea); + +#endif // _TMS6_HPP diff --git a/idasdk76/module/xa/ana.cpp b/idasdk76/module/xa/ana.cpp new file mode 100644 index 0000000..e757c7f --- /dev/null +++ b/idasdk76/module/xa/ana.cpp @@ -0,0 +1,942 @@ +/* + This module has been created by Petr Novak + */ + +#include "xa.hpp" + +static int ana_basic(insn_t &insn); + +//---------------------------------------------------------------------- +inline int ua_next_word_be(insn_t &insn) +{ + int32 result; + result = ((uchar)insn.get_next_byte()) << 8; + result += (uchar)insn.get_next_byte(); + return (int)result; +} + +//---------------------------------------------------------------------- +inline void opC(op_t &op) +{ + op.type = o_reg; + op.reg = rC; +} + +//---------------------------------------------------------------------- +// register direct +static int op_rd(op_t &x, int reg, int dtype) +{ + x.type = o_reg; + x.dtype = uchar(dtype); + x.reg = uint16((dtype == dt_byte ? rR0L : rR0) + reg); + return 1; +} + +//---------------------------------------------------------------------- +// register indirect +static int op_ph(op_t &x, uint16 phrase, int reg, int dtype) +{ + x.type = o_phrase; + x.dtype = uchar(dtype); + x.phrase = phrase; // union with x.reg + x.indreg = (uchar)reg; + if ( (phrase != fRlistL) && (phrase != fRlistH) ) + x.indreg += rR0; + return 1; +} + +//---------------------------------------------------------------------- +// register indirect with displacement +static int op_ds(op_t &x, uint16 phrase, int ireg, sval_t disp, int dtype) +{ + if ( disp > 0xFD00L ) + { + disp = disp - 0x10000L; // heuristics: treat large values from -300h as negative + } + x.type = o_displ; + x.dtype = uchar(dtype); + x.phrase = phrase; + x.indreg = rR0 + (uchar)ireg; + x.addr = disp; + return 1; +} + +//---------------------------------------------------------------------- +inline void op_mm(op_t &x, uval_t addr, int dtype) +{ + x.type = o_mem; + x.dtype = uchar(dtype); + x.addr = addr; +} + +//---------------------------------------------------------------------- +inline void op_rel(const insn_t &insn, op_t &x, sval_t addr) +{ + if ( addr > 32767 ) + addr -= 0x10000L; + x.type = o_near; + x.dtype = dt_code; + x.addr = (insn.ip + insn.size + 2*addr) & (~1L); +} + +//---------------------------------------------------------------------- +inline void op_near(op_t &x, uval_t addr) +{ + x.type = o_near; + x.dtype = dt_word; + x.addr = addr; +} + +//---------------------------------------------------------------------- +inline void op_im(op_t &x, uval_t value, int dtype) +{ + x.type = o_imm; + x.dtype = uchar(dtype); + x.value = value; +} + +//---------------------------------------------------------------------- +inline void op_bit(op_t &x, int type, uval_t addr) +{ + x.type = optype_t(type); + x.dtype = dt_word; + x.addr = addr; +} + +//---------------------------------------------------------------------- +// analyze an basic instruction +static int ana_basic(insn_t &insn) +{ + + static const nameNum xa_basic[16] = + { + XA_add, XA_addc, XA_sub, XA_subb, XA_cmp, XA_and, XA_or, XA_xor, + XA_mov, XA_null, XA_null, XA_null, XA_null, XA_null, XA_null, XA_null, + }; + + static const nameNum xa_branches[16] = + { + XA_bcc, XA_bcs, XA_bne, XA_beq, XA_bnv, XA_bov, XA_bpl, XA_bmi, + XA_bg, XA_bl, XA_bge, XA_blt, XA_bgt, XA_ble, XA_br, XA_bkpt, + }; + + static const nameNum xa_pushpop[] = + { + XA_push, XA_pushu, XA_pop, XA_popu, + }; + + static const nameNum xa_bitops[] = + { + XA_clr, XA_setb, XA_mov, XA_mov, XA_anl, XA_anl, XA_orl, XA_orl, + }; + + static const nameNum xa_Jxx[] = + { + XA_jb, XA_jnb, XA_jbc, XA_null, + }; + + static const nameNum xa_misc[] = + { + XA_da, XA_sext, XA_cpl, XA_neg, + }; + + static const nameNum xa_shifts[] = + { + XA_lsr, XA_asl, XA_asr, XA_norm, + }; + + ushort code = insn.get_next_byte(); + + ushort nibble0 = (code & 0xF); + ushort nibble1 = (code >> 4); + signed char off; + int size = 0; + ushort b1; + + if ( nibble1 <= 0xB ) + { + switch ( nibble0 & 0x7 ) + { + case 0: // Specials + case 7: // dtto + switch ( code ) + { + case 0x00: // 00 - NOP + insn.itype = XA_nop; + break; + + case 0x07: // PUSH.B Rlist + case 0x0F: // PUSH.W Rlist + case 0x17: // PUSHU.B Rlist + case 0x1F: // PUSHU.W Rlist + case 0x27: // POP.B Rlist + case 0x2F: // POP.W Rlist + case 0x37: // POPU.B Rlist + case 0x3F: // POPU.W Rlist + case 0x47: // PUSH.B Rlist + case 0x4F: // PUSH.W Rlist + case 0x57: // PUSHU.B Rlist + case 0x5F: // PUSHU.W Rlist + case 0x67: // POP.B Rlist + case 0x6F: // POP.W Rlist + case 0x77: // POPU.B Rlist + case 0x7F: // POPU.W Rlist + size = (nibble0 < 8) ? dt_byte : dt_word; + b1 = insn.get_next_byte(); // Rlist + insn.itype = xa_pushpop[nibble1 & 3]; + if ( nibble1 & 4 ) // High + op_ph(insn.Op1, fRlistH, b1, size); + else + op_ph(insn.Op1, fRlistL, b1, size); + break; + + case 0x08: // 08 - misc + b1 = insn.get_next_byte(); + switch ( b1 & 0xfc ) + { + case 0x00: // CLR + case 0x10: // SETB + insn.itype = xa_bitops[(b1>>4) & 7]; + op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); + break; + case 0x20: // MOV C,bit + insn.itype = xa_bitops[(b1>>4) & 7]; + opC(insn.Op1); + op_bit(insn.Op2, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); + break; + case 0x30: // MOV bit,C + insn.itype = xa_bitops[(b1>>4) & 7]; + op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); + opC(insn.Op2); + break; + case 0x40: // ANL C, bit + case 0x50: // ANL C, /bit + case 0x60: // ORL C, bit + case 0x70: // ORL C, /bit + insn.itype = xa_bitops[(b1>>4) & 7]; + opC(insn.Op1); + op_bit(insn.Op2, + (b1&0x10)?o_bitnot:o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); + break; + default: // undefined + return 0; + } + break; + + case 0x40: // LEA + case 0x48: // LEA + insn.itype = XA_lea; + b1 = insn.get_next_byte(); + if ( b1 & 0x88 ) + return 0; + op_rd(insn.Op1, b1>>4, dt_word); + if ( code & 0x8 ) // 16bit offset + op_ds(insn.Op2, fRid16, b1&0x07, (int32)ua_next_word_be(insn), dt_word); + else + op_ds(insn.Op2, fRid8, b1&0x07, (signed char)insn.get_next_byte(), dt_word); + break; + + case 0x50: // XCH.B Rd,[Rs] + case 0x58: // XCH.W Rd,[Rs] + case 0x60: // XCH.B Rd,Rs + case 0x68: // XCH.W Rd,Rs + insn.itype = XA_xch; + size = (nibble0 < 8) ? dt_byte : dt_word; + b1 = insn.get_next_byte(); + op_rd(insn.Op1, b1>>4, size); + switch ( nibble1 ) + { + case 0x5: // Rd,[Rs] + if ( b1 & 8 ) + return 0; + op_ds(insn.Op2, fRi, b1&7, 0, size); + break; + case 0x6: // Rd,Rs + op_rd(insn.Op2, b1&0xf, size); + break; + } + break; + + case 0x80: // MOVC + case 0x88: // MOVC + b1 = insn.get_next_byte(); + size = (nibble0 < 8) ? dt_byte : dt_word; + if ( b1 & 8 ) + return 0; + insn.itype = XA_movc; + op_rd(insn.Op1, b1>>4, size); + op_ph(insn.Op2, fRip, b1&7, size); + break; + + case 0x87: // DJNZ Rd, rel8 + case 0x8F: // POP, POPU, PUSH, PUSHU direct + b1 = insn.get_next_byte(); + size = (nibble0 < 8) ? dt_byte : dt_word; + if ( b1 & 8 ) // DJNZ + { + if ( b1 & 7 ) + return 0; + insn.itype = XA_djnz; + op_rd(insn.Op1, b1>>4, size); + op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); + } + else + { // POP, POPU, PUSH, PUSHU + if ( b1 & 0xc0 ) + return 0; + insn.itype = xa_pushpop[3-((b1>>4)&3)]; + op_mm(insn.Op1, ((b1 & 7) << 8) + insn.get_next_byte(), size); + } + break; + + case 0x90: // CPL, DA, SEXT + case 0x98: // CPL & MOV [Rd+], [Rs+] & MOV direct, [Rs] + b1 = insn.get_next_byte(); + size = (nibble0 < 8) ? dt_byte : dt_word; + switch ( b1 & 0x0f ) + { + case 0x0: // MOV [Rd+], [Rs+] + case 0x1: + case 0x2: + case 0x3: + case 0x4: + case 0x5: + case 0x6: + case 0x7: // MOV [Rd+], [Rs+] + if ( b1 & 0x80 ) + return 0; + insn.itype = XA_mov; + op_ph(insn.Op1, fRip, (b1>>4)&7, size); + op_ph(insn.Op2, fRip, (b1&7), size); + break; + + case 0x8: // DA + case 0x9: // SEXT + case 0xA: // CPL + case 0xB: // NEG + insn.itype = xa_misc[b1&3]; + op_rd(insn.Op1, b1>>4, size); + if ( (nibble0&8) != 0 && insn.itype == XA_da ) + return 0; + break; + + case 0xC: // MOVC A,[A+PC] 904C + if ( (nibble0 != 0) & ((b1&0xf0) != 0xc0) ) + return 0; + insn.itype = XA_movc; + op_rd(insn.Op1, rA, dt_byte); + op_ph(insn.Op2, fApc, 0, dt_byte); + break; + + case 0xE: // MOVC A,[A+DPTR] 904E + if ( (nibble0 != 0) & ((b1&0xf0) != 0xc0) ) + return 0; + insn.itype = XA_movc; + op_rd(insn.Op1, rA, dt_byte); + op_ph(insn.Op2, fAdptr, 0, dt_byte); + break; + + case 0xF: // MOV Rd,USP & MOV USP, Rs + insn.itype = XA_mov; + if ( nibble0&8 ) // USP,Rs + { + op_rd(insn.Op1, rUSP-rR0, dt_word); + op_rd(insn.Op2, b1>>4, dt_word); + } + else + { + op_rd(insn.Op1, b1>>4, dt_word); + op_rd(insn.Op2, rUSP-rR0, dt_word); + } + break; + + default: + return 0; + } + break; + + case 0x97: // {JB,JBC,JNB} bit, rel8 & MOV direct, direct + case 0x9F: // {JB,JBC,JNB} bit, rel8 & MOV direct, direct + b1 = insn.get_next_byte(); + if ( (b1 & 0x88) == 0x00 ) // MOV direct, direct + { + insn.itype = XA_mov; + size = (nibble0 < 8) ? dt_byte : dt_word; + op_mm(insn.Op1, ((b1 & 0x70) << 4) + (uchar)insn.get_next_byte(), size); + op_mm(insn.Op2, ((b1 & 0x7) << 8) + (uchar)insn.get_next_byte(), size); + } + else + { + if ( nibble0 & 8 ) + return 0; + switch ( b1 & 0xfc ) + { + case 0x80: // JB + case 0xA0: // JNB + case 0xC0: // JBC + insn.itype = xa_Jxx[(b1>>5)&3]; + op_bit(insn.Op1, o_bit, ((b1&3)<<8) + (uchar)insn.get_next_byte()); + op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); + break; + default: + return 0; + } + } + break; + + case 0xA0: // MOV.B direct, [Rs] & [Rd], direct & XCH + case 0xA8: // MOV.W direct, [Rs] & [Rd], direct & XCH + b1 = insn.get_next_byte(); + size = (nibble0 < 8) ? dt_byte : dt_word; + if ( b1 & 8 ) // XCH + { + insn.itype = XA_xch; + op_rd(insn.Op1, b1>>4, size); + op_mm(insn.Op2, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); + } + else + { // MOV + insn.itype = XA_mov; + if ( b1 & 0x80 ) // direct, [Rs] + { + op_mm(insn.Op1, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); + op_ds(insn.Op2, fRi, (b1>>4)&7, 0, size); + } + else + { + op_ds(insn.Op1, fRi, (b1>>4)&7, 0, size); + op_mm(insn.Op2, ((b1 & 7) << 8) + (uchar)insn.get_next_byte(), size); + } + } + break; + + case 0xA7: // MOVX + case 0xAF: // MOVX + insn.itype = XA_movx; + size = (nibble0 < 8) ? dt_byte : dt_word; + b1 = insn.get_next_byte(); + if ( b1 & 8 ) // [Rd],Rs + { + op_ds(insn.Op1, fRi, b1&0x7, 0, size); + op_rd(insn.Op2, b1>>4, size); + } + else + { // Rd,[Rs] + op_rd(insn.Op1, b1>>4, size); + op_ds(insn.Op2, fRi, b1&0x7, 0, size); + } + break; + + case 0xB0: // RR + case 0xB7: // RRC + case 0xB8: // RR + case 0xBF: // RRC + insn.itype = (nibble0 & 7) ? XA_rrc : XA_rr; + size = (nibble0 < 8) ? dt_byte : dt_word; + b1 = insn.get_next_byte(); + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, b1&0xf, size); + break; + + default: + return 0; + } + break; + + default: + switch ( nibble1 ) + { + case 0: // ADD + case 1: // ADDC + case 2: // SUB + case 3: // SUBB + case 4: // CMP + case 5: // AND + case 6: // OR + case 7: // XOR + case 8: // MOV + insn.itype = xa_basic[nibble1]; + size = (nibble0 < 8) ? dt_byte : dt_word; + b1 = insn.get_next_byte(); + switch ( nibble0 & 0x7 ) + { + case 0x1: // OP Rd,Rs + op_rd(insn.Op1, b1>>4, size); + op_rd(insn.Op2, b1&0xF, size); + break; + + case 0x2: // OP Rd,[Rs] + if ( b1 & 8 ) // [Rd], Rs + { + op_ds(insn.Op1, fRi, b1&7, 0, size); + op_rd(insn.Op2, b1>>4, size); + } + else + { + op_rd(insn.Op1, b1>>4, size); + op_ds(insn.Op2, fRi, b1&7, 0, size); + } + break; + + case 0x3: // OP Rd,[Rs+] + if ( b1 & 8 ) // [Rd], Rs + { + op_ph(insn.Op1, fRip, (b1&7), size); + op_rd(insn.Op2, b1>>4, size); + } + else + { + op_rd(insn.Op1, b1>>4, size); + op_ph(insn.Op2, fRip, (b1&7), size); + } + break; + + case 0x4: // OP Rd,[Rs+o8] + if ( b1 & 8 ) // [Rd], Rs + { + op_ds(insn.Op1, fRid8, (b1&7), (signed char)insn.get_next_byte(), size); + op_rd(insn.Op2, b1>>4, size); + } + else + { + op_rd(insn.Op1, b1>>4, size); + op_ds(insn.Op2, fRid8, (b1&7), (signed char)insn.get_next_byte(), size); + } + break; + + case 0x5: // OP Rd,[Rs+o16] + if ( b1 & 8 ) // [Rd], Rs + { + op_ds(insn.Op1, fRid16, (b1&7), (int)ua_next_word_be(insn), size); + op_rd(insn.Op2, b1>>4, size); + } + else + { + op_rd(insn.Op1, b1>>4, size); + op_ds(insn.Op2, fRid16, (b1&7), (int)ua_next_word_be(insn), size); + } + break; + + case 0x6: // OP Rd,direct + if ( b1 & 8 ) // direct, Rs + { + op_mm(insn.Op1, ((b1 & 7) << 8) + insn.get_next_byte(), size); + op_rd(insn.Op2, b1>>4, size); + } + else + { + op_rd(insn.Op1, b1>>4, size); + op_mm(insn.Op2, ((b1 & 7) << 8) + insn.get_next_byte(), size); + } + break; + } + break; + + case 9: // Immediate operations + b1 = insn.get_next_byte(); + insn.itype = xa_basic[b1 & 0x0f]; + size = (nibble0 < 8) ? dt_byte : dt_word; + switch ( nibble0 & 0x7 ) + { + case 0x1: + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); + break; + + case 0x2: + op_ds(insn.Op1, fRi, (b1>>4) & 0x7, 0, size); + op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); + break; + + case 0x3: + op_ph(insn.Op1, fRip, (b1>>4) & 0x7, size); + op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); + break; + + case 0x4: + op_ds(insn.Op1, fRid8, (b1>>4) & 0x7, (signed char)insn.get_next_byte(), size); + op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); + break; + + case 0x5: + op_ds(insn.Op1, fRid16, (b1>>4) & 0x7, (int)ua_next_word_be(insn), size); + op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); + break; + + case 0x6: + op_mm(insn.Op1, (((b1>>4) & 0x7) << 8) + insn.get_next_byte(), size); + op_im(insn.Op2, (size == dt_byte) ? insn.get_next_byte() : ua_next_word_be(insn), size); + break; + } + break; + + case 0xA: // ADDS + case 0xB: // MOVS + b1 = insn.get_next_byte(); + insn.itype = (nibble1 == 0x0A) ? XA_adds : XA_movs; + size = (nibble0 < 8) ? dt_byte : dt_word; + off = b1 & 0xf; + if ( off > 7 ) + off -= 16; + op_im(insn.Op2, (int32)off, size); + switch ( nibble0 & 0x7 ) + { + case 0x1: + op_rd(insn.Op1, b1>>4, size); + break; + + case 0x2: + op_ds(insn.Op1, fRi, (b1>>4) & 0x7, 0, size); + break; + + case 0x3: + op_ph(insn.Op1, fRip, (b1>>4) & 0x7, size); + break; + + case 0x4: + op_ds(insn.Op1, fRid8, (b1>>4) & 0x7, (signed char)insn.get_next_byte(), size); + break; + + case 0x5: + op_ds(insn.Op1, fRid16, (b1>>4) & 0x7, (int)ua_next_word_be(insn), size); + break; + + case 0x6: + op_mm(insn.Op1, (((b1>>4) & 0x7) << 8) + (uchar)insn.get_next_byte(), size); + break; + } + break; + } + } + } + else + { // nibble1 > B + switch ( nibble1 ) + { + case 0xC: // Shifts, CALL, FCALL + switch ( nibble0 & 0xc ) + { + case 0x0: + size = dt_byte; + break; + case 0x8: + size = dt_word; + break; + case 0xC: + size = dt_dword; + break; + case 0x4: // Special instructions + switch ( nibble0 ) + { + case 4: // FCALL addr24 + insn.itype = XA_fcall; + insn.Op1.type = o_far; + insn.Op1.dtype = dt_code; + insn.Op1.addr = (ushort)ua_next_word_be(insn); + insn.Op1.specval = (uchar)insn.get_next_byte(); + break; + case 5: // CALL rel16 + insn.itype = XA_call; + op_rel(insn, insn.Op1, (int)ua_next_word_be(insn)); + break; + case 6: // CALL [Rs] + b1 = insn.get_next_byte(); + if ( b1 & 0xf8 ) + return 0; + insn.itype = XA_call; + op_ds(insn.Op1, fRi, b1&7, 0, dt_word); + break; + default: + return 0; + } + break; + } + if ( insn.itype == XA_null ) + { + insn.itype = xa_shifts[nibble0 & 3]; + b1 = insn.get_next_byte(); + op_rd(insn.Op1, b1>>4, size); + op_rd(insn.Op2, b1&0xf, size); + } + break; + + case 0xD: // JMP, FJMP, rotations & shifts with #d4/#d5 + switch ( nibble0 & 0xC ) + { + case 0x4: // Special instructions + switch ( nibble0 ) + { + case 7: // rotate + break; + case 4: // FJMP addr24 + insn.itype = XA_fjmp; + insn.Op1.type = o_far; + insn.Op1.dtype = dt_code; + insn.Op1.addr = (ushort)ua_next_word_be(insn); + insn.Op1.specval = (uchar)insn.get_next_byte(); + break; + case 5: // JMP rel16 + insn.itype = XA_jmp; + op_rel(insn, insn.Op1, (int)ua_next_word_be(insn)); + break; + case 6: // specials + insn.itype = XA_jmp; + b1 = insn.get_next_byte(); + switch ( b1 & 0xf8 ) + { + case 0x10: // RESET + if ( b1 & 7 ) + return 0; + insn.itype = XA_reset; + break; + case 0x30: // TRAP + case 0x38: // TRAP + insn.itype = XA_trap; + op_im(insn.Op1, b1 & 0xf, dt_byte); + break; + case 0x40: // JMP [A+DPTR] + if ( (b1&7) != 6 ) + return 0; + op_ph(insn.Op1, fAdptr, 0, dt_word); + break; + case 0x60: // JMP [[Rs+]] + op_ph(insn.Op1, fRipi, b1&7, dt_word); + break; + case 0x70: // JMP [Rs] + op_ph(insn.Op1, fRi, b1&7, dt_word); + break; + case 0x80: // RET + if ( b1 & 7 ) + return 0; + insn.itype = XA_ret; + break; + case 0x90: // RETI + if ( b1 & 7 ) + return 0; + insn.itype = XA_reti; + break; + default: + return 0; + } + break; + default: + return 0; + } + break; + + case 0x0: + size = dt_byte; + break; + + case 0x8: + size = dt_word; + break; + + case 0xC: + size = dt_dword; + break; + } + if ( insn.itype == XA_null ) + { + insn.itype = xa_shifts[nibble0 & 3]; + if ( insn.itype == XA_norm ) + { // rotations + size = (nibble0 < 8) ? dt_byte : dt_word; + insn.itype = (nibble0 & 4) ? XA_rlc : XA_rl; + b1 = insn.get_next_byte(); + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, b1&0xf, size); + } + else + { // shifts + b1 = insn.get_next_byte(); + if ( size == dt_dword ) + { + op_rd(insn.Op1, (b1>>4)&0x0e, size); // Only even registers allowed + op_im(insn.Op2, b1&0x1f, size); + } + else + { + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, b1&0xf, size); + } + } + } + break; + + case 0xE: // DIV & MUL & cjne & jz/jnz + b1 = insn.get_next_byte(); + switch ( nibble0 ) + { + case 0x0: // MULU.B Rd,Rs + insn.itype = XA_mulu; + op_rd(insn.Op1, b1>>4, dt_byte); + op_rd(insn.Op2, b1&0xf, dt_byte); + break; + case 0x1: // DIVU.B Rd,Rs + insn.itype = XA_divu; + op_rd(insn.Op1, b1>>4, dt_byte); + op_rd(insn.Op2, b1&0xf, dt_byte); + break; + case 0x4: // MULU.W Rd,Rs + insn.itype = XA_mulu; + op_rd(insn.Op1, b1>>4, dt_word); + op_rd(insn.Op2, b1&0xf, dt_word); + break; + case 0x5: // DIVU.W Rd,Rs + insn.itype = XA_divu; + op_rd(insn.Op1, b1>>4, dt_word); + op_rd(insn.Op2, b1&0xf, dt_word); + break; + case 0x6: // MUL.W Rd,Rs + insn.itype = XA_mul; + op_rd(insn.Op1, b1>>4, dt_word); + op_rd(insn.Op2, b1&0xf, dt_word); + break; + case 0x7: // DIV.W Rd, Rs + insn.itype = XA_div; + op_rd(insn.Op1, b1>>4, dt_word); + op_rd(insn.Op2, b1&0xf, dt_word); + break; + case 0x8: // MUL & DIV Rd,#8 + switch ( b1 & 0xf ) + { + case 0x0: // MULU.B Rd,#d8 + insn.itype = XA_mulu; + size = dt_byte; + break; + case 0x1: // DIVU.B Rd,#d8 + insn.itype = XA_divu; + size = dt_byte; + break; + case 0x3: // DIVU.W Rd,#d8 + insn.itype = XA_divu; + size = dt_word; + break; + case 0xB: // DIV.W Rd,#d8 + insn.itype = XA_div; + size = dt_word; + break; + default: + return 0; + } + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, insn.get_next_byte(), dt_word); + break; + case 0x9: // MUL & DIV Rd,#16 + switch ( b1 & 0xf ) + { + case 0x0: // MULU.W Rd,#d16 + insn.itype = XA_mulu; + size = dt_word; + break; + case 0x1: // DIVU.D Rd,#d16 + if ( b1&0x10 ) + return 0; + insn.itype = XA_divu; + size = dt_dword; + break; + case 0x8: // MUL.W Rd,#d16 + insn.itype = XA_mul; + size = dt_word; + break; + case 0x9: // DIV.D Rd,#d16 + if ( b1&0x10 ) + return 0; + insn.itype = XA_div; + size = dt_dword; + break; + default: + return 0; + } + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, ua_next_word_be(insn), dt_byte); + break; + case 0xD: // DIVU.D Rd,Rs + if ( b1&0x10 ) + return 0; + insn.itype = XA_divu; + op_rd(insn.Op1, b1>>4, dt_dword); + op_rd(insn.Op2, b1&0xf, dt_dword); + break; + case 0xF: // DIV.D Rd, Rs + if ( b1&0x10 ) + return 0; + insn.itype = XA_div; + op_rd(insn.Op1, b1>>4, dt_dword); + op_rd(insn.Op2, b1&0xf, dt_dword); + break; + case 0x2: // cjne direct & [Rd] & DJNZ direct + case 0xA: // cjne direct & [Rd] & DJNZ direct + size = (nibble0 < 8) ? dt_byte : dt_word; + if ( b1 & 8 ) + { // DJNZ direct, rel8 + insn.itype = XA_djnz; + op_mm(insn.Op1, ((b1&7)<<8)+(uchar)insn.get_next_byte(), size); + op_rel(insn, insn.Op2, (signed char)insn.get_next_byte()); + } + else + { // CJNE.s Rd, direct, rel8 + insn.itype = XA_cjne; + op_rd(insn.Op1, b1>>4, size); + op_mm(insn.Op2, ((b1&7)<<8)+(uchar)insn.get_next_byte(), size); + op_rel(insn, insn.Op3, (signed char)insn.get_next_byte()); + } + break; + case 0x3: // cjne #,rel + case 0xB: // cjne #,rel + if ( b1 & 7 ) + return 0; + insn.itype = XA_cjne; + size = (nibble0 < 8) ? dt_byte : dt_word; + off = insn.get_next_byte(); + if ( b1 & 0x8 ) + op_ds(insn.Op1, fRi, b1>>4, 0, size); + else + op_rd(insn.Op1, b1>>4, size); + op_im(insn.Op2, size == dt_byte ? insn.get_next_byte() : ua_next_word_be(insn), size); + op_rel(insn, insn.Op3, off); + break; + case 0xC: // JZ rel8 + insn.itype = XA_jz; + op_rel(insn, insn.Op1, (signed char)b1); + break; + case 0xE: // JNZ rel8 + insn.itype = XA_jnz; + op_rel(insn, insn.Op1, (signed char)b1); + break; + default: + return 0; + } + break; + + case 0xF: // Bxx + insn.itype = xa_branches[nibble0]; + if ( nibble0 != 0xF ) + { + op_rel(insn, insn.Op1, (signed char)insn.get_next_byte()); + } + break; + } + } + return insn.size; +} + +//---------------------------------------------------------------------- +// analyze an instruction +int xa_t::ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + + insn.itype = XA_null; + insn.Op1.dtype = dt_byte; + insn.Op2.dtype = dt_byte; + insn.Op3.dtype = dt_byte; + + switch ( ptype ) //-V785 Constant expression in switch statement + { + case prc_xaG3: + return ana_basic(insn); + } + return 0; //lint !e527 statement is unreachable +} diff --git a/idasdk75/module/xa/emu.cpp b/idasdk76/module/xa/emu.cpp similarity index 100% rename from idasdk75/module/xa/emu.cpp rename to idasdk76/module/xa/emu.cpp diff --git a/idasdk75/module/xa/ins.cpp b/idasdk76/module/xa/ins.cpp similarity index 100% rename from idasdk75/module/xa/ins.cpp rename to idasdk76/module/xa/ins.cpp diff --git a/idasdk75/module/xa/ins.hpp b/idasdk76/module/xa/ins.hpp similarity index 100% rename from idasdk75/module/xa/ins.hpp rename to idasdk76/module/xa/ins.hpp diff --git a/idasdk76/module/xa/makefile b/idasdk76/module/xa/makefile new file mode 100644 index 0000000..d82c5ef --- /dev/null +++ b/idasdk76/module/xa/makefile @@ -0,0 +1,50 @@ +PROC=xa + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ana.cpp ins.hpp \ + xa.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)frame.hpp \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)struct.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + emu.cpp ins.hpp xa.hpp +$(F)ins$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.cpp ins.hpp \ + xa.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ins.hpp out.cpp \ + xa.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)entry.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)offset.hpp \ + $(I)pro.h $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ins.hpp reg.cpp xa.hpp diff --git a/idasdk75/module/xa/out.cpp b/idasdk76/module/xa/out.cpp similarity index 100% rename from idasdk75/module/xa/out.cpp rename to idasdk76/module/xa/out.cpp diff --git a/idasdk75/module/xa/reg.cpp b/idasdk76/module/xa/reg.cpp similarity index 100% rename from idasdk75/module/xa/reg.cpp rename to idasdk76/module/xa/reg.cpp diff --git a/idasdk75/module/xa/xa.hpp b/idasdk76/module/xa/xa.hpp similarity index 100% rename from idasdk75/module/xa/xa.hpp rename to idasdk76/module/xa/xa.hpp diff --git a/idasdk75/module/z8/ana.cpp b/idasdk76/module/z8/ana.cpp similarity index 100% rename from idasdk75/module/z8/ana.cpp rename to idasdk76/module/z8/ana.cpp diff --git a/idasdk76/module/z8/emu.cpp b/idasdk76/module/z8/emu.cpp new file mode 100644 index 0000000..5cb888e --- /dev/null +++ b/idasdk76/module/z8/emu.cpp @@ -0,0 +1,117 @@ +/* + * Interactive disassembler (IDA). + * Zilog Z8 module + * + */ + +#include "z8.hpp" + +//---------------------------------------------------------------------- +// Calculate the target data address +ea_t z8_t::map_addr(const insn_t &insn, asize_t off, int opnum, bool isdata) const +{ + if ( isdata ) + { + if ( is_off(get_flags(insn.ea), opnum) ) + return get_offbase(insn.ea, opnum) >> 4; + return intmem + off; + } + return map_code_ea(insn, off, opnum); +} + +//---------------------------------------------------------------------- +void z8_t::handle_operand(const insn_t &insn, const op_t &x, bool isload) +{ + switch ( x.type ) + { + case o_displ: + case o_imm: + if ( op_adds_xrefs(get_flags(insn.ea), x.n) ) + { + int outf = x.type != o_imm ? OOF_ADDR|OOFW_16 : 0; + insn.add_off_drefs(x, dr_O, outf|OOF_SIGNED); + } + break; + + case o_mem: + case o_ind_mem: + case o_reg: + case o_ind_reg: + { + ea_t dea; + if ( x.type == o_mem || x.type == o_ind_mem ) + { + dea = map_addr(insn, x.addr, x.n, true); + } + else + { + if ( x.reg >= rRR0 ) + dea = map_addr(insn, x.reg - rRR0, x.n, true); + else + dea = map_addr(insn, x.reg - rR0, x.n, true); + } + insn.create_op_data(dea, x); + insn.add_dref(dea, x.offb, isload ? dr_R : dr_W); + if ( !has_user_name(get_flags(dea)) && dea > intmem ) + { + char buf[10]; + int num = dea - intmem; + if ( num < 0x100 ) + { + qsnprintf(buf, sizeof(buf), "R%d", num); + } + else if ( num < 0x1000 ) + { + qsnprintf(buf, sizeof(buf), "ERF_%X_%d", num >> 8, num & 0xFF); + } + else + { + int reg_no = ((num >> 4) & 0xF0) + (num & 0xF); + int subbank_no = ((num >> 4) & 0xF) + 1; + qsnprintf(buf, sizeof(buf), "R%d_%X", reg_no, subbank_no); + } + set_name(dea, buf, SN_NOCHECK|SN_NOWARN|SN_NODUMMY); + } + } + break; + + case o_near: + { + ea_t ea = map_code_ea(insn, x); + int iscall = has_insn_feature(insn.itype, CF_CALL); + insn.add_cref(ea, x.offb, iscall ? fl_CN : fl_JN); + if ( flow && iscall ) + flow = func_does_return(ea); + } + break; + + } +} + +//---------------------------------------------------------------------- +int z8_t::z8_emu(const insn_t &insn) +{ + uint32 Feature = insn.get_canon_feature(ph); + + flow = (Feature & CF_STOP) == 0; + + if ( Feature & CF_USE1 ) handle_operand(insn, insn.Op1, true); + if ( Feature & CF_USE2 ) handle_operand(insn, insn.Op2, true); + if ( Feature & CF_JUMP ) + remember_problem(PR_JUMP, insn.ea); + + if ( Feature & CF_CHG1 ) handle_operand(insn, insn.Op1, false); + if ( Feature & CF_CHG2 ) handle_operand(insn, insn.Op2, false); + + if ( flow ) + add_cref(insn.ea, insn.ea+insn.size, fl_F); + + if ( insn.itype == Z8_srp // Set register pointer + || (insn.itype == Z8_pop && insn.Op1.type == o_mem && insn.Op1.addr == 0xFD) ) // popping RP + { + // set the RP value + sel_t val = insn.itype == Z8_srp ? (insn.Op1.value & 0xFF) : BADSEL; + split_sreg_range(insn.ea + insn.size, rRp, val, SR_auto, true); + } + return 1; +} diff --git a/idasdk75/module/z8/ins.cpp b/idasdk76/module/z8/ins.cpp similarity index 100% rename from idasdk75/module/z8/ins.cpp rename to idasdk76/module/z8/ins.cpp diff --git a/idasdk75/module/z8/ins.hpp b/idasdk76/module/z8/ins.hpp similarity index 100% rename from idasdk75/module/z8/ins.hpp rename to idasdk76/module/z8/ins.hpp diff --git a/idasdk76/module/z8/makefile b/idasdk76/module/z8/makefile new file mode 100644 index 0000000..488cc18 --- /dev/null +++ b/idasdk76/module/z8/makefile @@ -0,0 +1,52 @@ +PROC=z8 +CONFIGS=z8.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ana.cpp ins.hpp z8.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp emu.cpp ins.hpp z8.hpp +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp out.cpp z8.hpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp \ + ../iohandler.hpp ins.hpp reg.cpp z8.hpp diff --git a/idasdk76/module/z8/out.cpp b/idasdk76/module/z8/out.cpp new file mode 100644 index 0000000..651ea37 --- /dev/null +++ b/idasdk76/module/z8/out.cpp @@ -0,0 +1,211 @@ +/* + * Interactive disassembler (IDA). + * Zilog Z8 module + * + */ + +#include "z8.hpp" + +static const char *const phrases[] = +{ + "F", "LT", "LE", "ULE", "OV", "MI", "Z", "C", + "T", "GE", "GT", "UGT", "NOV", "PL", "NZ", "NC" +}; + +//---------------------------------------------------------------------- +inline void z8_t::out_reg(outctx_t &ctx, int rgnum) +{ + ctx.out_register(ph.reg_names[rgnum]); +} + +//-------------------------------------------------------------------------- +void z8_t::z8_header(outctx_t &ctx) +{ + ctx.gen_header(GH_PRINT_PROC_ASM_AND_BYTESEX); +} + +//-------------------------------------------------------------------------- +void z8_t::z8_footer(outctx_t &ctx) +{ + ctx.gen_empty_line(); + + ctx.out_line(ash.end, COLOR_ASMDIR); + ctx.flush_outbuf(DEFAULT_INDENT); + + ctx.gen_cmt_line("end of file"); +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +//lint -esym(818, Srange) could be made const +void z8_t::z8_segstart(outctx_t &ctx, segment_t *Srange) +{ + qstring sname; + get_visible_segm_name(&sname, Srange); + + ctx.gen_cmt_line(COLSTR("segment %s", SCOLOR_AUTOCMT), sname.c_str()); + + ea_t org = ctx.insn_ea - get_segm_base(Srange); + if ( org != 0 ) + { + char buf[MAX_NUMBUF]; + btoa(buf, sizeof(buf), org); + ctx.gen_cmt_line("%s %s", ash.origin, buf); + } +} + +//-------------------------------------------------------------------------- +//lint -esym(818, seg) could be made const +void z8_t::z8_segend(outctx_t &ctx, segment_t *seg) +{ + qstring sname; + get_visible_segm_name(&sname, seg); + ctx.gen_cmt_line("end of '%s'", sname.c_str()); +} + +//---------------------------------------------------------------------- +void idaapi out_insn(outctx_t &ctx) +{ + ctx.out_mnemonic(); + + ctx.out_one_operand(0); + + if ( ctx.insn.Op2.type != o_void ) + { + ctx.out_symbol(','); + ctx.out_char(' '); + ctx.out_one_operand(1); + } + + ctx.out_immchar_cmts(); + ctx.flush_outbuf(); +} + +//---------------------------------------------------------------------- +bool z8_t::out_opnd(outctx_t &ctx, const op_t &x) +{ + uval_t v; + + z8_t &pm = *static_cast<z8_t *>(ctx.procmod); + switch ( x.type ) + { + case o_imm: + ctx.out_symbol('#'); + ctx.out_value(x, OOFW_IMM); + break; + + case o_ind_reg: + ctx.out_symbol('@'); + // fallthrough + + case o_reg: + out_reg(ctx, x.reg); + break; + + case o_phrase: + ctx.out_keyword(phrases[x.phrase]); + break; + + case o_displ: + ctx.out_value(x, OOF_ADDR | OOFW_16); + ctx.out_symbol('('); + out_reg(ctx, x.reg); + ctx.out_symbol(')'); + break; + + case o_ind_mem: + ctx.out_symbol('@'); + // fallthrough + + case o_mem: + case o_near: + v = pm.map_addr(ctx.insn, x.addr, x.n, x.type != o_near); + if ( !ctx.out_name_expr(x, v, x.addr) ) + { + const char *name = pm.find_ioport(v); + if ( name != NULL ) + { + ctx.out_line(name, COLOR_IMPNAME); + } + else + { + ctx.out_value(x, OOF_ADDR | OOF_NUMBER | OOFS_NOSIGN | OOFW_16); + remember_problem(PR_NONAME, ctx.insn.ea); + } + } + break; + + case o_void: + return 0; + + default: + warning("out: %a: bad optype %d", ctx.insn.ea, x.type); + } + + return 1; +} + +//-------------------------------------------------------------------------- +static void out_equ(outctx_t &ctx, const char *name, const char *equ, uchar off) +{ + ctx.out_line(name, COLOR_DNAME); + ctx.out_char(' '); + ctx.out_line(equ, COLOR_KEYWORD); + ctx.out_char(' '); + ctx.out_tagon(COLOR_NUMBER); + ctx.out_btoa(off); + ctx.out_tagoff(COLOR_NUMBER); + ctx.ctxflags |= CTXF_LABEL_OK; + ctx.flush_outbuf(0x80000000); +} + +//-------------------------------------------------------------------------- +void z8_t::z8_data(outctx_t &ctx, bool analyze_only) +{ + ea_t ea = ctx.insn_ea; + segment_t *s = getseg(ea); + if ( s != NULL && s->type == SEG_IMEM ) + { + qstring name; + if ( get_visible_name(&name, ea) > 0 ) + out_equ(ctx, name.begin(), ash.a_equ, uint16(ea - get_segm_base(s))); + } + else + { + ctx.out_data(analyze_only); + } +} + +//-------------------------------------------------------------------------- +//lint -esym(1764, ctx) could be made const +void z8_t::z8_assumes(outctx_t &ctx) +{ + ea_t ea = ctx.insn_ea; + segment_t *seg = getseg(ea); + if ( (inf_get_outflags() & OFLG_GEN_ASSUME) == 0 || seg == NULL ) + return; + // always show at the start of code segments + bool seg_started = (ea == seg->start_ea) && (seg->type == SEG_CODE); + + sreg_range_t sra; + if ( !get_sreg_range(&sra, ea, rRp) ) + return; + bool show = sra.start_ea == ea; + if ( show ) + { + sreg_range_t prev_sra; + if ( get_prev_sreg_range(&prev_sra, ea, rRp) ) + show = sra.val != prev_sra.val; + } + if ( seg_started || show ) + { + sel_t rp = sra.val; + if ( rp == BADSEL ) + rp = 0; + char num[MAX_NUMBUF]; + btoa(num, sizeof(num), rp); + char nbuf[MAXSTR]; + qsnprintf(nbuf, sizeof(nbuf), COLSTR(".rp %s", SCOLOR_ASMDIR), num); + ctx.flush_buf(nbuf, DEFAULT_INDENT); + } +} diff --git a/idasdk76/module/z8/reg.cpp b/idasdk76/module/z8/reg.cpp new file mode 100644 index 0000000..ed21b31 --- /dev/null +++ b/idasdk76/module/z8/reg.cpp @@ -0,0 +1,460 @@ +/* + * Interactive disassembler (IDA). + * Zilog Z8 module + * + */ + +#include "z8.hpp" +#include <diskio.hpp> +int data_id; + +//-------------------------------------------------------------------------- +static const char *const RegNames[] = +{ + "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", + "RR0", "RR1", "RR2", "RR3", "RR4", "RR5", "RR6", "RR7", + "RR8", "RR9", "RR10", "RR11", "RR12", "RR13", "RR14", "RR15", + "cs", "ds", "rp", +}; + +//---------------------------------------------------------------------- +typedef struct +{ + int off; + const char *name; //lint !e958 padding is required to align members + const char *cmt; +} entry_t; + +static const entry_t entries[] = +{ + { 0, "irq0", "DAV0, IRQ0, Comparator" }, + { 2, "irq1", "DAV1, IRQ1" }, + { 4, "irq2", "DAV2, IRQ2, TIN, Comparator" }, + { 6, "irq3", "IRQ3, Serial in" }, + { 8, "irq4", "T0, Serial out" }, + { 10, "irq5", "T1" }, +}; + +//---------------------------------------------------------------------- +static ea_t AdditionalSegment(size_t size, size_t offset, const char *name, const char *sclass, uchar stype) +{ + segment_t s; + s.start_ea = free_chunk(0, size, -0xF); + s.end_ea = s.start_ea + size; + s.sel = allocate_selector((s.start_ea-offset) >> 4); + s.type = stype; + add_segm_ex(&s, name, sclass, ADDSEG_NOSREG|ADDSEG_OR_DIE); + return s.start_ea - offset; +} + +//---------------------------------------------------------------------- +// special handling for areas +bool z8_iohandler_t::area_processing(ea_t start, ea_t end, const char *name, const char *aclass) +{ + if ( start >= end ) + { + warning("Error in definition of segment %s %s", aclass, name); + return false; + } + if ( strcmp(aclass, "CODE") == 0 ) + { + AdditionalSegment(end-start, start, name, aclass, SEG_CODE); + } + else if ( strcmp(aclass, "DATA") == 0 ) + { + uchar type = stristr(name, "FSR") != NULL ? SEG_IMEM : SEG_DATA; + AdditionalSegment(end-start, start, name, aclass, type); + } + else + { + return false; + } + return true; +} + +//------------------------------------------------------------------ +const char *z8_t::find_ioport(uval_t port) +{ + const ioport_t *p = ::find_ioport(ioh.ports, port); + return p ? p->name.c_str() : NULL; +} + +//---------------------------------------------------------------------- +static ea_t specialSeg(sel_t sel, bool make_imem = true) +{ + segment_t *s = get_segm_by_sel(sel); + + if ( s != NULL ) + { + if ( make_imem && s->type != SEG_IMEM ) + { + s->type = SEG_IMEM; + s->update(); + } + return s->start_ea; + } + return BADADDR; +} + +//---------------------------------------------------------------------- +void z8_t::setup_data_segment_pointers(void) +{ + sel_t sel; + if ( atos(&sel, "INTMEM") || atos(&sel, "RAM") ) + intmem = specialSeg(sel); + else + intmem = BADADDR; +} + +//---------------------------------------------------------------------- +bool z8_t::select_device(int resp_info) +{ + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + if ( !choose_ioport_device(&ioh.device, cfgfile) ) + { + ioh.device = NONEPROC; + return false; + } + + if ( !ioh.display_infotype_dialog(IORESP_ALL, &resp_info, cfgfile) ) + return false; + + ioh.set_device_name(ioh.device.c_str(), resp_info & ~IORESP_PORT); + setup_data_segment_pointers(); + + if ( (resp_info & IORESP_PORT) != 0 ) + { + if ( intmem == BADADDR ) + { + AdditionalSegment(0x1000, 0, "INTMEM", NULL, SEG_IMEM); + setup_data_segment_pointers(); + } + for ( int i=0; i < ioh.ports.size(); i++ ) + { + const ioport_t &p = ioh.ports[i]; + ea_t ea = p.address + intmem; + ea_t oldea = get_name_ea(BADADDR, p.name.c_str()); + if ( oldea != ea ) + { + if ( oldea != BADADDR ) + set_name(oldea, NULL); + del_items(ea, DELIT_EXPAND); + set_name(ea, p.name.c_str(), SN_NODUMMY); + } + if ( !p.cmt.empty() ) + set_cmt(ea, p.cmt.c_str(), true); + } + } + return true; +} + +//-------------------------------------------------------------------------- +const char *z8_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + select_device(IORESP_PORT|IORESP_INT); + return IDPOPT_OK; +} + +//---------------------------------------------------------------------- +void z8_t::load_from_idb() +{ + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(z8_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi z8_t::on_event(ssize_t msgid, va_list va) +{ + int code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + inf_set_be(true); // MSB first + break; + + case processor_t::ev_term: + ioh.ports.clear(); + clr_module_data(data_id); + break; + + case processor_t::ev_newfile: + { + segment_t *sptr = get_first_seg(); + if ( sptr != NULL ) + { + if ( sptr->start_ea - get_segm_base(sptr) == 0 ) + { + inf_set_start_ea(sptr->start_ea + 0xC); + inf_set_start_ip(0xC); + if ( !inf_like_binary() ) + { + // set default entries + for ( int i = 0; i < qnumber(entries); i++ ) + { + ea_t ea = sptr->start_ea + entries[i].off; + if ( is_mapped(ea) ) + { + create_word(ea, 2); + op_plain_offset(ea, 0, sptr->start_ea); + ea_t ea1 = sptr->start_ea + get_word(ea); + auto_make_proc(ea1); + set_name(ea, entries[i].name, SN_NODUMMY); + set_cmt(sptr->start_ea+get_word(ea), entries[i].cmt, 1); + } + } + } + } + set_segm_class(sptr, "CODE"); + } + + select_device(IORESP_ALL); + + if ( intmem == BADADDR ) + { + AdditionalSegment(0x1000, 0, "INTMEM", NULL, SEG_IMEM); + setup_data_segment_pointers(); + } + } + break; + + case processor_t::ev_oldfile: + load_from_idb(); + setup_data_segment_pointers(); + break; + + case processor_t::ev_creating_segm: + { // default DS is equal to CS + segment_t *sptr = va_arg(va, segment_t *); + sptr->defsr[rVds-ph.reg_first_sreg] = sptr->sel; + } + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + z8_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + z8_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + z8_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_out_segend: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + z8_segend(*ctx, seg); + return 1; + } + + case processor_t::ev_out_assumes: + { + outctx_t *ctx = va_arg(va, outctx_t *); + z8_assumes(*ctx); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return z8_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return z8_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_out_data: + { + outctx_t *ctx = va_arg(va, outctx_t *); + bool analyze_only = va_argi(va, bool); + z8_data(*ctx, analyze_only); + return 1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + default: + break; + } + return code; +} + +//-------------------------------------------------------------------------- +static const asm_t Z8asm = +{ + AS_COLON, + 0, + "Zilog Z8 assembler", + 0, + NULL, + ".org", + ".end", + + ";", // comment string + '\'', // string delimiter + '\0', // char delimiter (no char consts) + "\\\"'", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".byte", // byte directive + ".word", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".block %s", // uninited arrays + ".equ", // Equ + NULL, // seg prefix + "$", + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + '(', ')', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +static const asm_t *const asms[] = { &Z8asm, NULL }; + +//-------------------------------------------------------------------------- + +#define FAMILY "Zilog Z8 series:" +static const char *const shnames[] = { "Z8", NULL }; +static const char *const lnames[] = { FAMILY"Zilog Z8 MCU", NULL }; + +//-------------------------------------------------------------------------- + +static const uchar retcode[] = { 0xAF }; // ret +static const uchar iretcode[] = { 0xBF }; // iret + +static const bytes_t retcodes[] = +{ + { sizeof(retcode), retcode }, + { sizeof(iretcode), iretcode }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Processor Definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_Z8, // id + // flag + PRN_HEX + | PR_RNAMESOK // can use register names for byte names + | PR_SEGTRANS // segment translation is supported (map_code_ea) + | PR_BINMEM // The module creates RAM/ROM segments for binary files + // (the kernel shouldn't ask the user about their sizes and addresses) + | PR_SEGS // has segment registers? + | PR_SGROTHER, // the segment registers don't contain + // the segment selectors, something else + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, // short processor names (null term) + lnames, // long processor names (null term) + + asms, // array of enabled assemblers + + notify, // Various messages: + + RegNames, // Register names + qnumber(RegNames), // Number of registers + + rVcs,rRp, + 1, // size of a segment register + rVcs,rVds, + + NULL, // No known code start sequences + retcodes, + + 0, Z8_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 0, 0, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + Z8_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk75/module/z8/z8.cfg b/idasdk76/module/z8/z8.cfg similarity index 100% rename from idasdk75/module/z8/z8.cfg rename to idasdk76/module/z8/z8.cfg diff --git a/idasdk76/module/z8/z8.hpp b/idasdk76/module/z8/z8.hpp new file mode 100644 index 0000000..1c01728 --- /dev/null +++ b/idasdk76/module/z8/z8.hpp @@ -0,0 +1,123 @@ +/* +* .org +* .word + .equ +* .end +* .ascii +* .byte +* .block + +*+ IM o_imm 12h +* Ir o_ind_reg @R1 +* r o_reg R1 +* Irr o_ind_reg @RR1 +* RR o_reg RR1 +* cond o_phrase +*+ IRR o_ind_mem @INTMEM_12 +*+ IR o_ind_mem @INTMEM_12 +*+ DA/RA o_near loc_1234 +*+ R o_mem INTMEM_12 +*+ X o_displ INTMEM_12(R1) + + * + * Interactive disassembler (IDA). + * Zilog Z8 module + * + */ + +#ifndef _Z8_HPP +#define _Z8_HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <segregs.hpp> +#include <diskio.hpp> +#include "../iohandler.hpp" + +#define PROCMOD_NAME z8 +#define PROCMOD_NODE_NAME "$ Zilog Z8" + +//------------------------------------------------------------------ +struct z8_iohandler_t : public iohandler_t +{ + z8_iohandler_t(netnode &nn) : iohandler_t(nn) {} + virtual bool area_processing(ea_t start, ea_t end, const char *name, const char *aclass) override; +}; + +struct z8_t : public procmod_t +{ + netnode helper; + z8_iohandler_t ioh = z8_iohandler_t(helper); + ea_t intmem = BADADDR; // linear EA of the internal memory/registers segment + bool flow = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *find_ioport(uval_t port); + void setup_data_segment_pointers(void); + bool select_device(int resp_info); + const char *idaapi set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/); + void load_from_idb(); + + // ana.cpp + int z8_ana(insn_t *insn); + + // emu.cpp + int z8_emu(const insn_t &insn); + void handle_operand(const insn_t &insn, const op_t &x, bool isload); + ea_t map_addr(const insn_t &insn, asize_t off, int opnum, bool isdata) const; + + // out.cpp + void out_reg(outctx_t &ctx, int rgnum); + bool out_opnd(outctx_t &ctx, const op_t &x); + void z8_header(outctx_t &ctx); + void z8_footer(outctx_t &ctx); + void z8_segstart(outctx_t &ctx, segment_t *seg); + void z8_segend(outctx_t &ctx, segment_t *seg); + void z8_data(outctx_t &ctx, bool analyze_only); + void z8_assumes(outctx_t &ctx); +}; +extern int data_id; + +//------------------------------------------------------------------------ +// customization of insn_t structure: + +#define o_ind_mem o_idpspec0 // @intmem +#define o_ind_reg o_idpspec1 // @Rx + +//------------------------------------------------------------------------ + +enum z8_registers +{ + rR0, rR1, rR2, rR3, rR4, rR5, rR6, rR7, + rR8, rR9, rR10, rR11, rR12, rR13, rR14, rR15, + rRR0, rRR1, rRR2, rRR3, rRR4, rRR5, rRR6, rRR7, + rRR8, rRR9, rRR10, rRR11, rRR12, rRR13, rRR14, rRR15, + rVcs, rVds, rRp, +}; + +enum z8_phrases +{ + fF, fLT, fLE, fULE, fOV, fMI, fZ, fC, + fTrue, fGE, fGT, fUGT, fNOV, fPL, fNZ, fNC +}; + +struct predefined_t +{ + uchar addr; + const char *name; + const char *cmt; +}; + +//------------------------------------------------------------------------ +inline uint16 get_rp(ea_t ea) +{ + sel_t t = get_sreg(ea, rRp); + return t != BADSEL ? t : 0; +} + +#endif diff --git a/idasdk76/module/z80/ana.cpp b/idasdk76/module/z80/ana.cpp new file mode 100644 index 0000000..ce15412 --- /dev/null +++ b/idasdk76/module/z80/ana.cpp @@ -0,0 +1,2631 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-96 by Ilfak Guilfanov. + * ALL RIGHTS RESERVED. + * FIDO: 2:5020/209 + * E-mail: ig@estar.msk.su + * + */ + +#include "i5.hpp" + +//---------------------------------------------------------------------- +inline void GetImm(insn_t &insn, op_t &x) +{ + x.type = o_imm; + x.value = insn.get_next_byte(); +} + +//------------------------------------------------------------------------ +inline void op_c(op_t &x) +{ + x.type = o_phrase; + x.phrase = R_c; +} + +//------------------------------------------------------------------------ +static void op_ad(insn_t &insn, op_t &x) +{ + x.type = o_near; + x.addr = insn.get_next_word(); +} + +static void op_a(op_t &x); +static void op_e(insn_t &insn, op_t &x); +static void op_nn(insn_t &insn, op_t &x); +static void op_ad(insn_t &insn, op_t &x); +static void op_n(insn_t &insn, op_t &x); +static void op_mm(insn_t &insn, op_t &x); + +static const uint16 W [] = { I5_add,I5_adc,I5_sub,I5_sbb,I5_ana,I5_xra,I5_ora,I5_cmp }; +static const uint16 Wi [] = { I5_adi,I5_aci,I5_sui,I5_sbi,I5_ani,I5_xri,I5_ori,I5_cpi }; +static const uint16 calls[] = { I5_cnz,I5_cz, I5_cnc,I5_cc, I5_cpo,I5_cpe,I5_cp, I5_cm }; +static const uint16 jumps[] = { I5_jnz,I5_jz, I5_jnc,I5_jc, I5_jpo,I5_jpe,I5_jp, I5_jm }; +static const uint16 rets [] = { I5_rnz,I5_rz, I5_rnc,I5_rc, I5_rpo,I5_rpe,I5_rp, I5_rm }; +static const uint16 rols [] = { I5_rlc,I5_rrc,I5_ral,I5_rar,I5_daa,I5_cma,I5_stc,I5_cmc }; +static const uint16 CBrols[]= { Z80_rlc,Z80_rrc,Z80_rl,Z80_rr,Z80_sla,Z80_sra,Z80_srr,Z80_srl }; +static const uint16 Zrols[] = { Z80_rlca,Z80_rrca,Z80_rla,Z80_rra,I5_daa,Z80_cpl,Z80_scf,Z80_ccf }; + +//---------------------------------------------------------------------- +static void ConvertToFunny(insn_t &insn) +{ + switch ( insn.itype ) + { + case I5_mov: + insn.Op1.set_shown(); + insn.Op2.set_shown(); + if ( insn.Op1.type == o_reg && insn.Op2.type == o_mem ) + { + switch ( insn.Op1.reg ) + { + case R_bc: + insn.itype = A80_lbcd; + insn.Op1.clr_shown(); + break; + case R_de: + insn.itype = A80_lded; + insn.Op1.clr_shown(); + break; + case R_sp: + insn.itype = A80_lspd; + insn.Op1.clr_shown(); + break; + case R_ix: + insn.itype = A80_lixd; + insn.Op1.clr_shown(); + break; + case R_iy: + insn.itype = A80_liyd; + insn.Op1.clr_shown(); + break; + } + } + if ( insn.Op1.type == o_mem && insn.Op2.type == o_reg ) + { + switch ( insn.Op2.reg ) + { + case R_bc: + insn.itype = A80_sbcd; + insn.Op2.clr_shown(); + break; + case R_de: + insn.itype = A80_sded; + insn.Op2.clr_shown(); + break; + case R_sp: + insn.itype = A80_sspd; + insn.Op2.clr_shown(); + break; + case R_ix: + insn.itype = A80_sixd; + insn.Op2.clr_shown(); + break; + case R_iy: + insn.itype = A80_siyd; + insn.Op2.clr_shown(); + break; + } + } + if ( insn.Op1.type == o_reg && insn.Op2.type == o_reg ) + { + switch ( insn.Op1.reg ) + { + case R_sp: + if ( insn.Op2.reg == R_ix ) + { + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + insn.itype = A80_spix; + } + if ( insn.Op2.reg == R_iy ) + { + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + insn.itype = A80_spiy; + } + break; + case R_r: + insn.itype = A80_mvra; + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + break; + case R_i: + insn.itype = A80_mvia; + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + break; + case R_a: + if ( insn.Op2.reg == R_r ) + { + insn.itype = A80_mvar; + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + } + if ( insn.Op2.reg == R_i ) + { + insn.itype = A80_mvai; + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + } + break; + } + } + break; /* mov */ + case Z80_jp: + if ( insn.Op2.type == o_phrase && insn.Op2.phrase == R_ix ) + { + insn.itype = A80_pcix; + insn.Op2.clr_shown(); + break; + } + if ( insn.Op2.type == o_phrase && insn.Op2.phrase == R_iy ) + { + insn.itype = A80_pciy; + insn.Op2.clr_shown(); + break; + } + break; /* jp */ + case Z80_ex: + insn.Op1.clr_shown(); + insn.Op2.clr_shown(); + if ( insn.Op2.reg == R_ix ) + insn.itype = A80_xtix; + if ( insn.Op2.reg == R_iy ) + insn.itype = A80_xtiy; + break; /* ex */ + case I5_in: + if ( insn.Op2.type == o_phrase && insn.Op2.reg == R_c ) + { + insn.itype = Z80_inp; + insn.Op2.clr_shown(); + } + break; + case I5_out: + if ( insn.Op1.type == o_phrase && insn.Op1.reg == R_c ) + { + insn.itype = Z80_outp; + insn.Op1.clr_shown(); + } + break; + case Z80_cpl: + insn.itype = I5_cma; + break; + case Z80_scf: + insn.itype = I5_stc; + break; + case Z80_ccf: + insn.itype = I5_cmc; + break; + case I5_add: + if ( insn.Op1.type == o_reg && insn.Op1.reg == R_ix ) + { + insn.itype = A80_addix; + insn.Op1.clr_shown(); + if ( insn.Op2.type == o_reg && insn.Op2.reg == R_ix ) + insn.Op2.reg = R_hl; + break; + } + if ( insn.Op1.type == o_reg && insn.Op1.reg == R_iy ) + { + insn.itype = A80_addiy; + insn.Op1.clr_shown(); + if ( insn.Op2.type == o_reg && insn.Op2.reg == R_iy ) + insn.Op2.reg = R_hl; + break; + } + break; + case I5_adc: + if ( insn.Op1.dtype == dt_word && insn.Op1.type == o_reg ) + { + insn.itype = A80_addc; + insn.Op1.clr_shown(); + if ( insn.Op1.reg == R_ix ) + insn.itype = A80_addcix; + if ( insn.Op1.reg == R_iy ) + insn.itype = A80_addciy; + if ( insn.Op2.type == o_reg && insn.Op1.reg == insn.Op2.reg ) + insn.Op2.reg = R_hl; + } + break; + case Z80_sbc: + if ( insn.Op1.dtype == dt_word && insn.Op1.type == o_reg ) + { + insn.itype = A80_subc; + insn.Op1.clr_shown(); + if ( insn.Op1.reg == R_ix ) + insn.itype = A80_subcix; + if ( insn.Op1.reg == R_iy ) + insn.itype = A80_subciy; + if ( insn.Op2.type == o_reg && insn.Op1.reg == insn.Op2.reg ) + insn.Op2.reg = R_hl; + } + break; + case Z80_jr: + insn.Op1.clr_shown(); + switch ( insn.Op1.Cond ) + { + case oc_c: insn.itype = A80_jrc; break; + case oc_nc: insn.itype = A80_jrnc; break; + case oc_z: insn.itype = A80_jrz; break; + case oc_nz: insn.itype = A80_jrnz; break; + } + break; + case Z80_rrca: insn.itype = I5_rrc; break; + case Z80_rlca: insn.itype = I5_rlc; break; + case Z80_rla: insn.itype = I5_ral; break; + case Z80_rl: insn.itype = I5_ral; break; + case Z80_rra: insn.itype = I5_rar; break; + case Z80_rr: insn.itype = I5_rar; break; + case Z80_cpi: insn.itype = A80_cmpi; break; + case Z80_cpd: insn.itype = A80_cmpd; break; + case Z80_outi: insn.itype = A80_oti; break; + case Z80_outd: insn.itype = A80_otd; break; + case Z80_inc: insn.itype = I5_inr; break; + case Z80_dec: insn.itype = I5_dcr; break; + case Z80_im: + if ( insn.Op1.value == 0 ) + insn.itype = A80_im0; + else if ( insn.Op1.value == 1 ) + insn.itype = A80_im1; + else + insn.itype = A80_im2; + insn.Op1.clr_shown(); + break; + } +} + +//---------------------------------------------------------------------- +void z80_t::ConvertToZ80(insn_t &insn) +{ + uint16 cc; + if ( insn.itype < Z80_and ) + { + insn.Op1.set_shown(); + insn.Op2.set_shown(); + } + switch ( insn.itype ) + { + case I5_aci: + insn.itype = I5_adc; + break; + case I5_adi: + case I5_dad: + insn.itype = I5_add; + break; + case I5_cmp: + case I5_cpi: + insn.itype = Z80_cp; + if ( !isZ380() ) + insn.Op1.clr_shown(); + break; + case I5_ana: + case I5_ani: + insn.itype = Z80_and; + if ( !isZ380() ) + insn.Op1.clr_shown(); + break; + case I5_ora: + case I5_ori: + insn.itype = Z80_or; + if ( !isZ380() ) + insn.Op1.clr_shown(); + break; + case I5_xra: + case I5_xri: + insn.itype = Z80_xor; + if ( !isZ380() ) + insn.Op1.clr_shown(); + break; + case I5_sbi: + case I5_sbb: + insn.itype = Z80_sbc; + break; + case I5_sui: + case I5_sub: + insn.itype = I5_sub; + if ( !isZ380() ) + insn.Op1.clr_shown(); + break; + case I5_dcr: + case I5_dcx: + insn.itype = Z80_dec; + break; + case I5_inr: + case I5_inx: + insn.itype = Z80_inc; + break; + case I5_halt: + insn.itype = Z80_halt; + break; + case I5_sphl: + case I5_mov: + case I5_mvi: + case I5_ldax: + case I5_lxi: + case I5_lhld: + case I5_shld: + case I5_sta: + case I5_stax: + case I5_lda: + insn.itype = Z80_ld; + break; + case I5_xchg: + case I5_xthl: + insn.itype = Z80_ex; + break; + case I5_pchl: + insn.Op1.type = o_phrase; + insn.Op1.reg = R_hl; + cc = oc_not; + goto zjump; + + case I5_call: cc = oc_not;goto zcall; + case I5_cnz: cc = oc_nz; goto zcall; + case I5_cz: cc = oc_z; goto zcall; + case I5_cnc: cc = oc_nc; goto zcall; + case I5_cc: cc = oc_c; goto zcall; + case I5_cpo: cc = oc_po; goto zcall; + case I5_cpe: cc = oc_pe; goto zcall; + case I5_cp: cc = oc_p; goto zcall; + case I5_cm: cc = oc_m; goto zcall; + case I5_jmp: cc = oc_not;goto zjump; + case I5_jnz: cc = oc_nz; goto zjump; + case I5_jz: cc = oc_z; goto zjump; + case I5_jnc: cc = oc_nc; goto zjump; + case I5_jc: cc = oc_c; goto zjump; + case I5_jpo: cc = oc_po; goto zjump; + case I5_jpe: cc = oc_pe; goto zjump; + case I5_jp: cc = oc_p; goto zjump; + case I5_jm: cc = oc_m; goto zjump; + case I5_ret: cc = oc_not;goto zret; + case I5_rnz: cc = oc_nz; goto zret; + case I5_rz: cc = oc_z; goto zret; + case I5_rnc: cc = oc_nc; goto zret; + case I5_rc: cc = oc_c; goto zret; + case I5_rpo: cc = oc_po; goto zret; + case I5_rpe: cc = oc_pe; goto zret; + case I5_rp: cc = oc_p; goto zret; + case I5_rm: cc = oc_m; goto zret; + +zret: + insn.itype = Z80_ret; + goto zcc; +zjump: + insn.itype = Z80_jp; + goto zcc; +zcall: + insn.itype = Z80_call; + goto zcc; +zcc: + insn.Op2 = insn.Op1; + insn.Op2.n = 1; + insn.Op1.type = o_cond; + insn.Op1.Cond = cc; + break; + + } +} + +//---------------------------------------------------------------------- +static bool is_gameboy_insn(const insn_t &insn) +{ + switch ( insn.itype ) + { + case Z80_adc: + case Z80_add: + case Z80_and: + case Z80_bit: + case Z80_call: + case Z80_ccf: + case Z80_cp: + case Z80_cpl: + case I5_daa: + case Z80_dec: + case Z80_di: + case Z80_ei: + case Z80_halt: + case Z80_inc: + case Z80_jp: + case Z80_jr: + case Z80_ld: + case Z80_ldd: + case GB_ldh: + case Z80_ldi: + case I5_nop: + case Z80_or: + case Z80_pop: + case Z80_push: + case Z80_res: + case Z80_ret: + case Z80_reti: + case Z80_rl: + case Z80_rla: + case Z80_rlc: + case Z80_rlca: + case Z80_rr: + case Z80_rra: + case Z80_rrc: + case Z80_rrca: + case I5_rst: + case Z80_sbc: + case Z80_scf: + case Z80_set: + case Z80_sla: + case Z80_sra: + case Z80_srl: + case GB_stop: + case Z80_sub: + case Z80_swap: + case Z80_xor: + break; + default: + return false; + } + return true; +} + +//---------------------------------------------------------------------- +static void swap_operands(insn_t &insn) +{ + op_t op = insn.Op1; + insn.Op1 = insn.Op2; + insn.Op2 = op; +} + +//---------------------------------------------------------------------- +int z80_t::i5_ana(insn_t *_insn) +{ + insn_t &insn = *_insn; + + insn.Op1.dtype = dt_byte; + insn.Op2.dtype = dt_byte; + insn.itype = I5_null; + + code = insn.get_next_byte(); + + switch ( code & 0xC0 ) + { + case 0x00: + switch ( code & 0xF ) + { + case 0: + case 8: + { + int sub = ( code >> 3 ) & 7; + switch ( sub ) + { + case 0: + insn.itype = I5_nop; + break; + case 1: // 08 + if ( isGB() ) // 08 bb aa LD ($aabb),SP + { + insn.itype = Z80_ld; + op_mm(insn, insn.Op1); + insn.Op1.dtype = dt_word; + insn.Op2.type = o_reg; + insn.Op2.reg = R_sp; + } + else if ( isZ80() ) + { + insn.itype = Z80_ex; + insn.Op1.type = o_reg; + insn.Op1.reg = R_af; + insn.Op2.type = o_reg; + insn.Op2.reg = R_af2; + } + else + { + insn.itype = I5_dsub; // undoc + } + break; + case 2: // 10 + if ( isGB() ) // 10 00 STOP + { + if ( insn.get_next_byte() ) + return 0; + insn.itype = GB_stop; + } + else if ( isZ80() ) + { + insn.itype = Z80_djnz; + op_e(insn, insn.Op1); + } + else + { + insn.itype = I5_arhl; // undoc + } + break; + case 3: // 18 + if ( isZ80() ) + { +Z80_COMMON: + static const uint16 conds[] = { 0,1,2,oc_not,oc_nz,oc_z,oc_nc,oc_c }; + insn.Op1.Cond = conds[sub]; + insn.itype = Z80_jr; + insn.Op1.type = o_cond; + op_e(insn, insn.Op2); + break; + } + insn.itype = I5_rdel; // undoc + break; + case 4: // 20 + if ( isZ80() ) + goto Z80_COMMON; + insn.itype = I5_rim; + break; + case 5: // 28 + if ( isZ80() ) + goto Z80_COMMON; + insn.itype = I5_ldhi; // undoc + GetImm(insn, insn.Op1); + break; + case 6: // 30 + if ( isZ80() ) + goto Z80_COMMON; + insn.itype = I5_sim; + break; + case 7: // 38 + if ( isZ80() ) + goto Z80_COMMON; + insn.itype = I5_ldsi; + GetImm(insn, insn.Op1); + break; + } + } + break; + case 1: + insn.itype = I5_lxi; + op_ss(insn.Op1); + op_nn(insn, insn.Op2); + break; + + case 9: + insn.itype = I5_dad; + insn.Op1.reg = R_hl; + insn.Op1.dtype = dt_word; + insn.Op1.type = o_reg; + insn.Op1.clr_shown(); + op_ss(insn.Op2); + break; + case 0xA: + if ( (code & 0x20) == 0 ) + { + insn.itype = I5_ldax; + insn.Op2.type = o_phrase; + insn.Op2.phrase = R_bc + ((code >> 4) & 1); + op_a(insn.Op1); + } + else + { + if ( isGB() ) + { + insn.itype = (code & 0x10) ? Z80_ldd : Z80_ldi; + insn.Op1.type = o_reg; + insn.Op1.reg = R_a; + insn.Op2.type = o_phrase; + insn.Op2.phrase = R_hl; + break; + } + insn.Op1.type = o_reg; + if ( (code & 0x10) == 0 ) + { + insn.itype = I5_lhld; + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + insn.Op1.reg = R_hl; + } + else + { + insn.itype = I5_lda; + insn.Op1.reg = R_a; + } + op_mm(insn, insn.Op2); + } + insn.Op1.clr_shown(); + break; + case 2: + if ( (code & 0x20) == 0 ) + { + insn.itype = I5_stax; + insn.Op1.type = o_phrase; + insn.Op1.phrase = R_bc + ((code >> 4) & 1); + op_a(insn.Op2); + } + else + { + if ( isGB() ) + { + insn.itype = (code & 0x10) ? Z80_ldd : Z80_ldi; + insn.Op1.type = o_phrase; + insn.Op1.phrase = R_hl; + insn.Op2.type = o_reg; + insn.Op2.reg = R_a; + break; + } + insn.Op2.type = o_reg; + if ( (code & 0x10) == 0 ) + { + insn.itype = I5_shld; + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + insn.Op2.reg = R_hl; + } + else + { + insn.itype = I5_sta; + insn.Op2.reg = R_a; + } + op_mm(insn, insn.Op1); + } + insn.Op2.clr_shown(); + break; + case 3: + insn.itype = I5_inx; + op_ss(insn.Op1); + break; + case 0xB: + insn.itype = I5_dcx; + op_ss(insn.Op1); + break; + case 4: + case 0xC: + insn.itype = I5_inr; + op_r1(insn.Op1); + break; + case 5: + case 0xD: + insn.itype = I5_dcr; + op_r1(insn.Op1); + break; + case 6: + case 0xE: + insn.itype = I5_mvi; + op_r1(insn.Op1); + op_n (insn, insn.Op2); + break; + case 7: + case 0xF: + insn.itype = (isZ80() ? Zrols : rols)[ (code >> 3) & 7 ]; + break; + } + break; + case 0x40: + insn.itype = I5_halt; + if ( code != 0x76 ) + { + insn.itype = I5_mov; + op_r1(insn.Op1); + op_r2(insn.Op2); + } + break; + case 0x80: + op_r2(insn.Op2); +common: + insn.Op1.type = o_reg; + insn.Op1.reg = R_a; + insn.itype = (insn.Op2.type == o_imm ? Wi : W)[ (code >> 3) & 7 ]; + insn.Op1.clr_shown(); + break; + case 0xC0: /* 11?????? */ + switch ( code & 0xF ) + { + case 0x0: + case 0x8: /* 11???000 */ + if ( isGB() ) + { + switch ( code ) + { + case 0xE0: + case 0xF0: + insn.itype = Z80_ld; + insn.Op1.type = o_mem; + insn.Op1.addr = 0xFF00 + insn.get_next_byte(); + insn.Op2.type = o_reg; + insn.Op2.reg = R_a; + if ( code & 0x10 ) + swap_operands(insn); + break; + case 0xE8: + insn.itype = Z80_add; + insn.Op1.type = o_reg; + insn.Op1.reg = R_sp; + GetImm(insn, insn.Op2); + break; + case 0xF8: // docs say this is "ld hl, sp" + // Daniel Filner <danf@codefrog.cx> says + // this is "ld hl, sp+immbyte" + insn.itype = Z80_ld; + insn.Op1.type = o_reg; + insn.Op1.reg = R_hl; + insn.Op2.type = o_displ; + insn.Op2.phrase = R_sp; + insn.Op2.addr = insn.get_next_byte(); + break; + default: + goto RETS; + } + break; + } +RETS: + insn.itype = rets[ (code >> 3) & 7 ]; + break; + case 0x2: + case 0xA: /* 11???010 */ + if ( isGB() ) + { + switch ( code ) + { + case 0xE2: + case 0xF2: + insn.itype = Z80_ld; + insn.auxpref |= aux_off16; + op_c(insn.Op1); + insn.Op2.type = o_reg; + insn.Op2.reg = R_a; + if ( code & 0x10 ) + swap_operands(insn); + break; + case 0xEA: + case 0xFA: + insn.itype = Z80_ld; + op_mm(insn, insn.Op1); + insn.Op2.type = o_reg; + insn.Op2.reg = R_a; + if ( code & 0x10 ) + swap_operands(insn); + break; + default: + goto JUMPS; + } + break; + } +JUMPS: + insn.itype = jumps[ (code >> 3) & 7 ]; + op_ad(insn, insn.Op1); + break; + case 0x3: + case 0xB: /* 11???011 */ + switch ( ( code >> 3 ) & 7 ) + { + case 0: /* 11000011=C3 */ + insn.itype = I5_jmp; + op_ad(insn, insn.Op1); + break; + case 1: // 11001011=CB - Z80 extensions + if ( isZ80() ) + { + code = insn.get_next_byte(); + int fn = (code>>6); + if ( fn == 0 ) + { + op_r2(insn.Op1); + insn.itype = CBrols[ (code>>3) & 7 ]; + if ( insn.itype == Z80_srr ) + { + if ( isZ380() ) + { + insn.itype = Z80_ex; + op_r2(insn.Op2); + insn.Op2.reg += R_b2; + } + else if ( isGB() ) + { + insn.itype = Z80_swap; + } + } + } + else + { + static const uint16 brs[] = { 0, Z80_bit,Z80_res,Z80_set }; + insn.itype = brs[fn]; + insn.Op1.type = o_imm; + insn.Op1.value = (code>>3) & 7; + op_r2(insn.Op2); + } + } + else + { + insn.itype = I5_rstv; // undoc + } + break; + case 2: /* 11010011=D3 */ + insn.itype = I5_out; + op_a(insn.Op2); + op_n(insn, insn.Op1); + break; + case 3: // DB + insn.itype = I5_in; + op_a(insn.Op1); + op_n(insn, insn.Op2); + break; + case 4: // E3 + insn.itype = I5_xthl; + insn.Op1.type = o_phrase; + insn.Op1.reg = R_sp; + insn.Op1.clr_shown(); + insn.Op2.type = o_reg; + insn.Op2.reg = R_hl; + insn.Op2.clr_shown(); + break; + case 5: // EB + insn.itype = I5_xchg; + insn.Op1.type = o_reg; + insn.Op1.reg = R_de; + insn.Op1.clr_shown(); + insn.Op2.type = o_reg; + insn.Op2.reg = R_hl; + insn.Op2.clr_shown(); + break; + case 6: // F3 + insn.itype = I5_di; + break; + case 7: // FB + insn.itype = I5_ei; + break; + } + break; + case 0x4: + case 0xC: /* 11???100 */ + insn.itype = calls[ (code >> 3) & 7 ]; + op_ad(insn, insn.Op1); + break; + case 0x1: + case 0x5: // 11????01 + insn.itype = (code & 4) ? I5_push : I5_pop; + op_dd(insn.Op1); + break; + case 0x6: + case 0xE: // 11???110 + op_n(insn, insn.Op2); + goto common; + case 0x7: + case 0xF: // 11???111 + insn.itype = I5_rst; + insn.Op1.type = o_imm; + insn.Op1.value = (code >> 3) & 7; + if ( isZ80() ) + { // workaround for bcb6 bug: + uval_t x = insn.Op1.value; + x <<= 3; + insn.Op1.value = x; + } + break; + case 0x9: + switch ( (code >> 4) & 3 ) + { + case 0: + insn.itype = I5_ret; // 11001001 = C9 + break; + case 1: // 11011001 = D9 + if ( isGB() ) + insn.itype = Z80_reti; + else if ( isZ80() ) + insn.itype = Z80_exx; + else + insn.itype = I5_shlx; // undoc + break; + case 2: + insn.itype = I5_pchl; + break; + case 3: + insn.itype = I5_sphl; + insn.Op1.type = o_reg; + insn.Op1.reg = R_sp; + insn.Op1.clr_shown(); + insn.Op2.type = o_reg; + insn.Op2.reg = R_hl; + insn.Op2.clr_shown(); + break; + } + break; + case 0xD: /* 11??1101 */ + switch ( (code >> 4) & 3 ) + { + case 0: + insn.itype = I5_call; + op_ad(insn, insn.Op1); + break; + case 1: // 11011101 = DD - Z80 extensions + if ( is8085() ) + { + insn.itype = I5_jnx5; // undoc + op_ad(insn, insn.Op1); + } + else + { + z80_ixcommands(insn, true); + } + break; + case 2: // 11101101 = ED - Z80 extensions + if ( isGB() ) + return 0; + else if ( isZ380() ) + z380_ED(insn); + else if ( is8085() ) + insn.itype = I5_lhlx; // undoc + else + z80_misc(insn); + break; + case 3: // 11111101 = FD - Z80 extensions + if ( is8085() ) + { + insn.itype = I5_jx5; // undoc + op_ad(insn, insn.Op1); + } + else + { + z80_ixcommands(insn, false); + } + break; + } + break; + } + break; + } + + if ( insn.itype == I5_null ) + return 0; + + if ( isZ80() ) + { + if ( ash.uflag & UAS_FUNNY ) + ConvertToFunny(insn); + else + ConvertToZ80(insn); + if ( isGB() && !is_gameboy_insn(insn) ) + return 0; + } + + return insn.size; + +} + +//------------------------------------------------------------------------ +void z80_t::op_r1(op_t &x) const +{ + uint16 mode = (code >> 3) & 7; + if ( mode == 6 ) + { + x.type = o_phrase; + x.phrase = R_hl; + } + else + { + x.type = o_reg; + x.reg = mode; + } +} + +//------------------------------------------------------------------------ +void z80_t::op_r2(op_t &x) const +{ + uint16 mode = code & 7; + if ( mode == 6 ) + { + x.type = o_phrase; + x.phrase = R_hl; + } + else + { + x.type = o_reg; + x.reg = mode; + } +} + +//------------------------------------------------------------------------ +void z80_t::op_ss(op_t &x) const +{ + uint16 ss = (code >> 4) & 3; + x.type = o_reg; + x.dtype = dt_word; + x.reg = ss + R_bc; + if ( ss == 3 ) + x.reg = R_sp; +} + +//------------------------------------------------------------------------ +void z80_t::op_dd(op_t &x) const +{ + uint16 ss = (code >> 4) & 3; + x.type = o_reg; + x.dtype = dt_word; + x.reg = ss + R_bc; +} + +//------------------------------------------------------------------------ +static void op_nn(insn_t &insn, op_t &x) +{ + x.type = o_imm; + x.dtype = dt_word; + x.value = insn.get_next_word(); +} + +//------------------------------------------------------------------------ +static void op_n(insn_t &insn, op_t &x) +{ + x.type = o_imm; + x.value = insn.get_next_byte(); +} + +//------------------------------------------------------------------------ +static void op_e(insn_t &insn, op_t &x) +{ + x.type = o_near; + sval_t rel = char(insn.get_next_byte()); + x.addr = ushort(insn.ip + insn.size + rel); +} + +//------------------------------------------------------------------------ +static void op_a(op_t &x) +{ + x.type = o_reg; + x.reg = R_a; + x.clr_shown(); +} + +//------------------------------------------------------------------------ +static void op_mm(insn_t &insn, op_t &x) +{ + x.type = o_mem; + x.addr = insn.get_next_word(); +} + +//------------------------------------------------------------------------ +static void op_f(op_t &x) +{ + x.type = o_reg; + x.dtype = dt_byte; + x.reg = R_f; +} + +//------------------------------------------------------------------------ +void z80_t::op_xdispl(insn_t &insn, op_t &x) const +{ + x.type = o_displ; + x.phrase = isx ? R_ix : R_iy; + x.addr = insn.get_next_byte(); +} + +//------------------------------------------------------------------------ +void z80_t::op_ix(op_t &x) const +{ + x.type = o_reg; + x.reg = isx ? R_ix : R_iy; + x.dtype = dt_word; +} + +//------------------------------------------------------------------------ +void z80_t::op_ibyte(op_t &x,int low) const +{ + x.type = o_reg; + x.reg = isx + ? (low ? R_xl : R_xh) + : (low ? R_yl : R_yh); +} + +//------------------------------------------------------------------------ +int z80_t::op_xbytereg(op_t &x,uint16 mode) const +{ + if ( mode == 6 ) + { + x.type = o_phrase; + x.phrase = R_hl; + return 1; + } + else + { + if ( mode == R_h ) + { + op_ibyte(x,0); + } + else if ( mode == R_l ) + { + op_ibyte(x,1); + } + else + { + x.type = o_reg; + x.reg = mode; + } + return 0; + } +} + +//------------------------------------------------------------------------ +int z80_t::op_xr1(op_t &x) const +{ + return op_xbytereg(x,(code >> 3) & 7); +} + +//------------------------------------------------------------------------ +int z80_t::op_xr2(op_t &x) const +{ + return op_xbytereg(x,code & 7); +} + +//------------------------------------------------------------------------ +struct insndesc_t +{ + uchar code; + ushort itype; //lint !e958 padding is required to align members + uchar op1; + uchar op2; +}; + +#define rA (R_a+1) +#define rB (R_b+1) +#define rC (R_c+1) +#define rD (R_d+1) +#define rE (R_e+1) +#define rH (R_h+1) +#define rL (R_l+1) +#define rI (R_i+1) +#define rW (R_w+1) +#define rR (R_r+1) +#define rBC (R_bc+1) +#define rDE (R_de+1) +#define rHL (R_hl+1) +#define rIX (R_ix+1) +#define rIY (R_iy+1) +#define rSP (R_sp+1) +#define rLW (R_lw+1) +#define rIXL (R_ixl+1) +#define rIXU (R_ixu+1) +#define rDSR (R_dsr+1) +#define rXSR (R_xsr+1) +#define rIYL (R_iyl+1) +#define rIYU (R_iyu+1) +#define rYSR (R_ysr+1) +#define rSR (R_sr+1) +#define rIB (R_ib+1) +#define rIW (R_iw+1) +#define rXM (R_xm+1) +#define rLCK (R_lck+1) +#define rBC2 (R_bc2+1) +#define rDE2 (R_de2+1) +#define rHL2 (R_hl2+1) +#define rIX2 (R_ix2+1) +#define rIY2 (R_iy2+1) + +#define atBC 0x30 +#define atDE 0x31 +#define atHL 0x32 +#define atSP 0x33 +#define atIX 0x34 +#define atIY 0x35 +#define atC 0x36 +#define rip8 0x37 // ip relative displ 8bits +#define rip16 0x38 // ip relative displ 16bits +#define rip24 0x39 // ip relative displ 24bits +#define imm8 0x3A // 8bit immval +#define imm16 0x3B // 16bit immval +#define mem16 0x3C // (1234h) + +#define ix8 0x40 // (IX+12) +#define iy8 0x41 // (IY+12) +#define ixs 0x42 // (IX+saved_value) +#define iys 0x43 // (IY+saved_value) +#define sps 0x44 // (SP+saved_value) + +// condition codes +#define ccNZ 0x50 +#define ccZ 0x51 +#define ccNC 0x52 +#define ccC 0x53 +#define ccPO 0x54 +#define ccPE 0x55 +#define ccP 0x56 +#define ccM 0x57 + +#define c0 0x60 +#define c1 0x61 +#define c2 0x62 +#define c3 0x63 +#define c4 0x64 +#define c5 0x65 +#define c6 0x66 +#define c7 0x67 + +static const insndesc_t cmdsDD[] = +{ + { 0x01, Z80_ld, atBC, rIX }, + { 0x02, Z80_ld, rBC, rDE }, + { 0x03, Z80_ld, rIX, atBC }, + { 0x07, Z80_ld, rIX, rBC }, + { 0x09, Z80_add, rIX, rBC }, + { 0x0B, Z80_ld, rBC, rIX }, + { 0x0C, Z80_ld, rBC, atBC }, + { 0x0D, Z80_ld, rBC, atDE }, + { 0x0F, Z80_ld, rBC, atHL }, + { 0x10, Z80_djnz, rip16 }, + { 0x11, Z80_ld, atDE, rIX }, + { 0x12, Z80_ld, rDE, rDE }, + { 0x13, Z80_ld, rIX, atDE }, + { 0x17, Z80_ld, rIX, rDE }, + { 0x18, Z80_jr, rip16 }, + { 0x19, Z80_add, rIX, rDE }, + { 0x1B, Z80_ld, rDE, rIX }, + { 0x1C, Z80_ld, rDE, atBC }, + { 0x1D, Z80_ld, rDE, atDE }, + { 0x1F, Z80_ld, rDE, atHL }, + { 0x20, Z80_jr, ccNZ, rip16 }, + { 0x21, Z80_ld, rIX, imm16 }, + { 0x22, Z80_ld, mem16, rIX }, + { 0x23, Z80_inc, rIX }, + { 0x24, Z80_inc, rIXU }, + { 0x25, Z80_dec, rIXU }, + { 0x26, Z80_ld, rIXU, imm8 }, + { 0x27, Z80_ld, rIX, rIY }, + { 0x28, Z80_jr, ccZ, rip16 }, + { 0x29, Z80_add, rIX, rIX }, + { 0x2A, Z80_ld, rIX, mem16 }, + { 0x2B, Z80_dec, rIX }, + { 0x2C, Z80_inc, rIXL }, + { 0x2D, Z80_dec, rIXL }, + { 0x2E, Z80_ld, rIXL, imm8 }, + { 0x2F, Z80_cplw, rHL }, + { 0x30, Z80_jr, ccNC, rip16 }, + { 0x31, Z80_ld, atHL, rIX }, + { 0x32, Z80_ld, rHL, rDE }, + { 0x33, Z80_ld, rIX, atHL }, + { 0x34, Z80_inc, ix8 }, + { 0x35, Z80_dec, ix8 }, + { 0x36, Z80_ld, ix8, imm8 }, + { 0x37, Z80_ld, rIX, rHL }, + { 0x38, Z80_jr, ccC, rip16 }, + { 0x39, Z80_add, rIX, rSP }, + { 0x3B, Z80_ld, rHL, rIX }, + { 0x3C, Z80_ld, rHL, atBC }, + { 0x3D, Z80_ld, rHL, atDE }, + { 0x3E, Z80_swap, rIX }, + { 0x3F, Z80_ld, rHL, atHL }, + { 0x40, Z80_inw, rBC, atC }, + { 0x41, Z80_outw, atC, rBC }, + { 0x44, Z80_ld, rB, rIXU }, + { 0x45, Z80_ld, rB, rIXL }, + { 0x46, Z80_ld, rB, ix8 }, + { 0x47, Z80_ldw, rI, rHL }, + { 0x4C, Z80_ld, rC, rIXU }, + { 0x4D, Z80_ld, rC, rIXL }, + { 0x4E, Z80_ld, rC, ix8 }, + { 0x50, Z80_inw, rDE, atC }, + { 0x51, Z80_outw, atC, rDE }, + { 0x54, Z80_ld, rD, rIXU }, + { 0x55, Z80_ld, rD, rIXL }, + { 0x56, Z80_ld, rD, ix8 }, + { 0x57, Z80_ldw, rHL, rI }, + { 0x5D, Z80_ld, rE, rIXL }, + { 0x5E, Z80_ld, rE, ix8 }, + { 0x60, Z80_ld, rIXU, rB }, + { 0x61, Z80_ld, rIXU, rC }, + { 0x62, Z80_ld, rIXU, rD }, + { 0x63, Z80_ld, rIXU, rE }, + { 0x64, Z80_ld, rIXU, rIXU }, + { 0x65, Z80_ld, rIXU, rIXL }, + { 0x66, Z80_ld, rH, ix8 }, + { 0x67, Z80_ld, rIXU, rA }, + { 0x68, Z80_ld, rIXL, rB }, + { 0x69, Z80_ld, rIXL, rC }, + { 0x6A, Z80_ld, rIXL, rD }, + { 0x6B, Z80_ld, rIXL, rE }, + { 0x6C, Z80_ld, rIXL, rIXU }, + { 0x6D, Z80_ld, rIXL, rIXL }, + { 0x6E, Z80_ld, rL, ix8 }, + { 0x6F, Z80_ld, rIXL, rA }, + { 0x70, Z80_ld, ix8, rB }, + { 0x71, Z80_ld, ix8, rC }, + { 0x72, Z80_ld, ix8, rD }, + { 0x73, Z80_ld, ix8, rE }, + { 0x74, Z80_ld, ix8, rH }, + { 0x75, Z80_ld, ix8, rL }, + { 0x77, Z80_ld, ix8, rA }, + { 0x78, Z80_inw, rHL, atC }, + { 0x79, Z80_outw, atC, rHL }, + { 0x7C, Z80_ld, rA, rIXU }, + { 0x7D, Z80_ld, rA, rIXL }, + { 0x7E, Z80_ld, rA, ix8 }, + { 0x84, Z80_add, rA, rIXU }, + { 0x85, Z80_add, rA, rIXL }, + { 0x86, Z80_add, rA, ix8 }, + { 0x87, Z80_addw, rHL, rIX }, + { 0x8C, Z80_adc, rA, rIXU }, + { 0x8D, Z80_adc, rA, rIXL }, + { 0x8E, Z80_adc, rA, ix8 }, + { 0x8F, Z80_adcw, rHL, rIX }, + { 0x94, Z80_sub, rA, rIXU }, + { 0x95, Z80_sub, rA, rIXL }, + { 0x96, Z80_sub, rA, ix8 }, + { 0x97, Z80_subw, rHL, rIX }, + { 0x9C, Z80_sbc, rA, rIXU }, + { 0x9D, Z80_sbc, rA, rIXL }, + { 0x9E, Z80_sbc, rA, ix8 }, + { 0x9F, Z80_sbcw, rHL, rIX }, + { 0xA4, Z80_and, rA, rIXU }, + { 0xA5, Z80_and, rA, rIXL }, + { 0xA6, Z80_and, rA, ix8 }, + { 0xA7, Z80_andw, rHL, rIX }, + { 0xAC, Z80_xor, rA, rIXU }, + { 0xAD, Z80_xor, rA, rIXL }, + { 0xAE, Z80_xor, rA, ix8 }, + { 0xAF, Z80_xorw, rHL, rIX }, + { 0xB4, Z80_or, rA, rIXU }, + { 0xB5, Z80_or, rA, rIXL }, + { 0xB6, Z80_or, rA, ix8 }, + { 0xB7, Z80_orw, rHL, rIX }, + { 0xBC, Z80_cp, rA, rIXU }, + { 0xBD, Z80_cp, rA, rIXL }, + { 0xBE, Z80_cp, rA, ix8 }, + { 0xBF, Z80_cpw, rHL, rIX }, + { 0xC0, Z80_ddir, rW }, + { 0xC1, Z80_ddir, rIB, rW }, + { 0xC2, Z80_ddir, rIW, rW }, + { 0xC3, Z80_ddir, rIB }, + { 0xC4, Z80_calr, ccNZ, rip16 }, + { 0xC6, Z80_addw, rHL, ix8 }, + { 0xC8, Z80_ldctl, rSR, rA }, + { 0xCA, Z80_ldctl, rSR, imm8 }, + { 0xCC, Z80_calr, ccZ, rip16 }, + { 0xCD, Z80_calr, rip16 }, + { 0xCE, Z80_adcw, rHL, ix8 }, + { 0xCF, Z80_mtest, }, + { 0xD0, Z80_ldctl, rA, rXSR }, + { 0xD4, Z80_calr, ccNC, rip16 }, + { 0xD6, Z80_subw, rHL, ix8 }, + { 0xD8, Z80_ldctl, rXSR, rA }, + { 0xD9, Z80_exxx, }, + { 0xDA, Z80_ldctl, rXSR, imm8 }, + { 0xDC, Z80_calr, ccC, rip16 }, + { 0xDE, Z80_sbcw, rHL, ix8 }, + { 0xE1, Z80_pop, rIX }, + { 0xE3, Z80_ex, atSP, rIX }, + { 0xE4, Z80_calr, ccPO, rip16 }, + { 0xE5, Z80_push, rIX }, + { 0xE6, Z80_andw, rHL, ix8 }, + { 0xE9, Z80_jp, atIX }, + { 0xEC, Z80_calr, ccPE, rip16 }, + { 0xEE, Z80_xorw, rHL, ix8 }, + { 0xF3, Z80_di, imm8 }, + { 0xF4, Z80_calr, ccP, rip16 }, + { 0xF6, Z80_orw, rHL, ix8 }, + { 0xF7, Z80_setc, rLW }, + { 0xF9, Z80_ld, rSP, rIX }, + { 0xFB, Z80_ei, imm8 }, + { 0xFC, Z80_calr, ccM, rip16 }, + { 0xFE, Z80_cpw, rHL, ix8 }, + { 0xFF, Z80_resc, rLW }, + { 0x00, 0 }, +}; + +// the next byte after DDBC is in saved_value +static const insndesc_t cmdsDDCB[] = +{ + { 0x01, Z80_ld, rBC, sps }, + { 0x02, Z80_rlcw, ixs }, + { 0x03, Z80_ld, rBC, ixs }, + { 0x06, Z80_rlc, ixs }, + { 0x09, Z80_ld, sps, rBC }, + { 0x0A, Z80_rrcw, ixs }, + { 0x0B, Z80_ld, ixs, rBC }, + { 0x0E, Z80_rrc, ixs }, + { 0x11, Z80_ld, rDE, sps }, + { 0x12, Z80_rlw, ixs }, + { 0x13, Z80_ld, rDE, ixs }, + { 0x16, Z80_rl, ixs }, + { 0x19, Z80_ld, sps, rDE }, + { 0x1A, Z80_rrw, ixs }, + { 0x1B, Z80_ld, ixs, rDE }, + { 0x1E, Z80_rr, ixs }, + { 0x21, Z80_ld, rIX, sps }, + { 0x22, Z80_slaw, ixs }, + { 0x23, Z80_ld, rIY, ixs }, + { 0x26, Z80_sla, ixs }, + { 0x29, Z80_ld, sps, rIX }, + { 0x2A, Z80_sraw, ixs }, + { 0x2B, Z80_ld, ixs, rIY }, + { 0x2E, Z80_sra, ixs }, + { 0x31, Z80_ld, rHL, sps }, + { 0x33, Z80_ld, rHL, ixs }, + { 0x39, Z80_ld, sps, rHL }, + { 0x3A, Z80_srlw, ixs }, + { 0x3B, Z80_ld, ixs, rHL }, + { 0x3E, Z80_srl, ixs }, + { 0x46, Z80_bit, c0, ixs }, + { 0x4E, Z80_bit, c1, ixs }, + { 0x56, Z80_bit, c2, ixs }, + { 0x5E, Z80_bit, c3, ixs }, + { 0x66, Z80_bit, c4, ixs }, + { 0x6E, Z80_bit, c5, ixs }, + { 0x76, Z80_bit, c6, ixs }, + { 0x7E, Z80_bit, c7, ixs }, + { 0x86, Z80_res, c0, ixs }, + { 0x8E, Z80_res, c1, ixs }, + { 0x92, Z80_multw, ixs }, + { 0x92, Z80_multw, rHL, ixs }, + { 0x96, Z80_res, c2, ixs }, + { 0x9A, Z80_multuw, ixs }, + { 0x9A, Z80_multuw, rHL, ixs }, + { 0x9E, Z80_res, c3, ixs }, + { 0xA6, Z80_res, c4, ixs }, + { 0xAE, Z80_res, c5, ixs }, + { 0xB6, Z80_res, c6, ixs }, + { 0xBA, Z80_divuw, ixs }, + { 0xBA, Z80_divuw, rHL, ixs }, + { 0xBE, Z80_res, c7, ixs }, + { 0xC6, Z80_set, c0, ixs }, + { 0xCE, Z80_set, c1, ixs }, + { 0xD6, Z80_set, c2, ixs }, + { 0xDE, Z80_set, c3, ixs }, + { 0xE6, Z80_set, c4, ixs }, + { 0xEE, Z80_set, c5, ixs }, + { 0xF6, Z80_set, c6, ixs }, + { 0xFE, Z80_set, c7, ixs }, + { 0x00, 0 }, +}; + + +static const insndesc_t cmdsFD[] = +{ + { 0x01, Z80_ld, atBC, rIY }, + { 0x02, Z80_ld, rBC, rHL }, + { 0x03, Z80_ld, rIY, atBC }, + { 0x07, Z80_ld, rIY, rBC }, + { 0x09, Z80_add, rIY, rBC }, + { 0x0B, Z80_ld, rBC, rIY }, + { 0x0C, Z80_ld, atBC, rBC }, + { 0x0D, Z80_ld, atDE, rBC }, + { 0x0F, Z80_ld, atHL, rBC }, + { 0x10, Z80_djnz, rip24 }, + { 0x11, Z80_ld, atDE, rIY }, + { 0x12, Z80_ld, rDE, rHL }, + { 0x13, Z80_ld, rIY, atDE }, + { 0x17, Z80_ld, rIY, rDE }, + { 0x18, Z80_jr, rip24 }, + { 0x19, Z80_add, rIY, rDE }, + { 0x1B, Z80_ld, rDE, rIY }, + { 0x1C, Z80_ld, atBC, rDE }, + { 0x1D, Z80_ld, atDE, rDE }, + { 0x1F, Z80_ld, atHL, rDE }, + { 0x20, Z80_jr, ccNZ, rip24 }, + { 0x21, Z80_ld, rIY, imm16 }, + { 0x22, Z80_ld, mem16, rIY }, + { 0x23, Z80_inc, rIY }, + { 0x24, Z80_inc, rIYU }, + { 0x25, Z80_dec, rIYU }, + { 0x26, Z80_ld, rIYU, imm8 }, + { 0x27, Z80_ld, rIY, rIX }, + { 0x28, Z80_jr, ccZ, rip24 }, + { 0x29, Z80_add, rIY, rIY }, + { 0x2A, Z80_ld, rIY, mem16 }, + { 0x2B, Z80_dec, rIY }, + { 0x2C, Z80_inc, rIYL }, + { 0x2D, Z80_dec, rIYL }, + { 0x2E, Z80_ld, rIYL, imm8 }, + { 0x30, Z80_jr, ccNC, rip24 }, + { 0x31, Z80_ld, atHL, rIY }, + { 0x32, Z80_ld, rHL, rHL }, + { 0x33, Z80_ld, rIY, atHL }, + { 0x34, Z80_inc, iy8 }, + { 0x35, Z80_dec, iy8 }, + { 0x36, Z80_ld, iy8, imm8 }, + { 0x26, Z80_ld, rIYU, imm8 }, + { 0x37, Z80_ld, rIY, rHL }, + { 0x38, Z80_jr, ccC, rip24 }, + { 0x39, Z80_add, rIY, rSP }, + { 0x3B, Z80_ld, rHL, rIY }, + { 0x3C, Z80_ld, atBC, rHL }, + { 0x3D, Z80_ld, atDE, rHL }, + { 0x3E, Z80_swap, rIY }, + { 0x3F, Z80_ld, atHL, rHL }, + { 0x44, Z80_ld, rB, rIYU }, + { 0x45, Z80_ld, rB, rIYL }, + { 0x46, Z80_ld, rB, iy8 }, + { 0x4C, Z80_ld, rC, rIYU }, + { 0x4D, Z80_ld, rC, rIYL }, + { 0x4E, Z80_ld, rC, iy8 }, + { 0x54, Z80_ld, rD, rIYU }, + { 0x55, Z80_ld, rD, rIYL }, + { 0x56, Z80_ld, rD, iy8 }, + { 0x5C, Z80_ld, rE, rIYU }, + { 0x5D, Z80_ld, rE, rIYL }, + { 0x5E, Z80_ld, rE, iy8 }, + { 0x60, Z80_ld, rIYU, rB }, + { 0x61, Z80_ld, rIYU, rC }, + { 0x62, Z80_ld, rIYU, rD }, + { 0x63, Z80_ld, rIYU, rE }, + { 0x64, Z80_ld, rIYU, rIYU }, + { 0x65, Z80_ld, rIYU, rIYL }, + { 0x66, Z80_ld, rH, iy8 }, + { 0x67, Z80_ld, rIYU, rA }, + { 0x68, Z80_ld, rIYL, rB }, + { 0x69, Z80_ld, rIYL, rC }, + { 0x6A, Z80_ld, rIYL, rD }, + { 0x6B, Z80_ld, rIYL, rE }, + { 0x6C, Z80_ld, rIYL, rIYU }, + { 0x6D, Z80_ld, rIYL, rIYL }, + { 0x6E, Z80_ld, rL, iy8 }, + { 0x6F, Z80_ld, rIYL, rA }, + { 0x70, Z80_ld, iy8, rB }, + { 0x71, Z80_ld, iy8, rC }, + { 0x72, Z80_ld, iy8, rD }, + { 0x73, Z80_ld, iy8, rE }, + { 0x74, Z80_ld, iy8, rH }, + { 0x75, Z80_ld, iy8, rL }, + { 0x77, Z80_ld, iy8, rA }, + { 0x79, Z80_outw, atC, imm16 }, + { 0x7C, Z80_ld, rA, rIYU }, + { 0x7D, Z80_ld, rA, rIYL }, + { 0x7E, Z80_ld, rA, iy8 }, + { 0x84, Z80_add, rA, rIYU }, + { 0x85, Z80_add, rA, rIYL }, + { 0x86, Z80_add, rA, iy8 }, + { 0x87, Z80_addw, rHL, rIY }, + { 0x8C, Z80_adc, rA, rIYU }, + { 0x8D, Z80_adc, rA, rIYL }, + { 0x8E, Z80_adc, rA, iy8 }, + { 0x8F, Z80_adcw, rHL, rIY }, + { 0x8F, Z80_adcw, rIY }, + { 0x94, Z80_sub, rA, rIYU }, + { 0x95, Z80_sub, rA, rIYL }, + { 0x96, Z80_sub, rA, iy8 }, + { 0x97, Z80_subw, rHL, rIY }, + { 0x9C, Z80_sbc, rA, rIYU }, + { 0x9D, Z80_sbc, rA, rIYL }, + { 0x9E, Z80_sbc, rA, iy8 }, + { 0x9F, Z80_sbcw, rHL, rIY }, + { 0xA4, Z80_and, rA, rIYU }, + { 0xA5, Z80_and, rA, rIYL }, + { 0xA6, Z80_and, rA, iy8 }, + { 0xA7, Z80_andw, rHL, rIY }, + { 0xAC, Z80_xor, rA, rIYU }, + { 0xAD, Z80_xor, rA, rIYL }, + { 0xAE, Z80_xor, rA, iy8 }, + { 0xAF, Z80_xorw, rHL, rIY }, + { 0xB4, Z80_or, rA, rIYU }, + { 0xB5, Z80_or, rA, rIYL }, + { 0xB6, Z80_or, rA, iy8 }, + { 0xB7, Z80_orw, rHL, rIY }, + { 0xBC, Z80_cp, rA, rIYU }, + { 0xBD, Z80_cp, rA, rIYL }, + { 0xBE, Z80_cp, rA, iy8 }, + { 0xBF, Z80_cpw, rHL, rIY }, + { 0xC0, Z80_ddir, rLW }, + { 0xC1, Z80_ddir, rIB, rLW }, + { 0xC2, Z80_ddir, rIW, rLW }, + { 0xC3, Z80_ddir, rIW }, + { 0xC4, Z80_calr, ccNZ, rip24 }, + { 0xC6, Z80_addw, iy8 }, + { 0xC6, Z80_addw, rHL, iy8 }, + { 0xCC, Z80_calr, ccZ, rip24 }, + { 0xCD, Z80_calr, rip24 }, + { 0xCE, Z80_adcw, rHL, iy8 }, + { 0xD0, Z80_ldctl, rA, rYSR }, + { 0xD3, Z80_outaw, imm16, rHL }, + { 0xD4, Z80_calr, ccNC, rip24 }, + { 0xD6, Z80_subw, rHL, iy8 }, + { 0xD8, Z80_ldctl, rYSR, rA }, + { 0xD9, Z80_exxy, }, + { 0xDA, Z80_ldctl, rYSR, imm8 }, + { 0xDB, Z80_inaw, rHL, imm16 }, + { 0xDC, Z80_calr, ccC, rip24 }, + { 0xDE, Z80_sbcw, rHL, iy8 }, + { 0xE1, Z80_pop, rIY }, + { 0xE3, Z80_ex, atSP, rIY }, + { 0xE4, Z80_calr, ccPO, rip24 }, + { 0xE5, Z80_push, rIY }, + { 0xE6, Z80_andw, rHL, iy8 }, + { 0xE9, Z80_jp, atIY }, + { 0xEC, Z80_calr, ccPE, rip24 }, + { 0xEE, Z80_xorw, rHL, iy8 }, + { 0xF4, Z80_calr, ccP, rip24 }, + { 0xF5, Z80_push, imm16 }, + { 0xF6, Z80_orw, rHL, iy8 }, + { 0xF7, Z80_setc, rXM }, + { 0xF9, Z80_ld, rSP, rIY }, + { 0xFC, Z80_calr, ccM, rip24 }, + { 0xFE, Z80_cpw, rHL, iy8 }, + { 0x00, 0 }, +}; + +// the next byte after FDBC is in saved_value +static const insndesc_t cmdsFDCB[] = +{ + { 0x02, Z80_rlcw, iys }, + { 0x03, Z80_ld, rBC, iys }, + { 0x06, Z80_rlc, iys }, + { 0x0A, Z80_rrcw, iys }, + { 0x0B, Z80_ld, iys, rBC }, + { 0x0E, Z80_rrc, iys }, + { 0x12, Z80_rlw, iys }, + { 0x13, Z80_ld, rDE, iys }, + { 0x16, Z80_rl, iys }, + { 0x1A, Z80_rrw, iys }, + { 0x1B, Z80_ld, iys, rDE }, + { 0x1E, Z80_rr, iys }, + { 0x21, Z80_ld, rIY, sps }, + { 0x22, Z80_slaw, iys }, + { 0x23, Z80_ld, rIX, iys }, + { 0x26, Z80_sla, iys }, + { 0x29, Z80_ld, sps, rIY }, + { 0x2A, Z80_sraw, iys }, + { 0x2B, Z80_ld, iys, rIX }, + { 0x2E, Z80_sra, iys }, + { 0x33, Z80_ld, rHL, iys }, + { 0x3A, Z80_srlw, iys }, + { 0x3B, Z80_ld, iys, rHL }, + { 0x3E, Z80_srl, iys }, + { 0x46, Z80_bit, c0, iys }, + { 0x4E, Z80_bit, c1, iys }, + { 0x56, Z80_bit, c2, iys }, + { 0x5E, Z80_bit, c3, iys }, + { 0x66, Z80_bit, c4, iys }, + { 0x6E, Z80_bit, c5, iys }, + { 0x76, Z80_bit, c6, iys }, + { 0x7E, Z80_bit, c7, iys }, + { 0x86, Z80_res, c0, iys }, + { 0x8E, Z80_res, c1, iys }, + { 0x92, Z80_multw, iys }, + { 0x92, Z80_multw, rHL, iys }, + { 0x96, Z80_res, c2, iys }, + { 0x9A, Z80_multuw, iys }, + { 0x9A, Z80_multuw, rHL, iys }, + { 0x9E, Z80_res, c3, iys }, + { 0xA6, Z80_res, c4, iys }, + { 0xAE, Z80_res, c5, iys }, + { 0xB6, Z80_res, c6, iys }, + { 0xBA, Z80_divuw, iys }, + { 0xBA, Z80_divuw, rHL, iys }, + { 0xBE, Z80_res, c7, iys }, + { 0xC6, Z80_set, c0, iys }, + { 0xCE, Z80_set, c1, iys }, + { 0xD6, Z80_set, c2, iys }, + { 0xDE, Z80_set, c3, iys }, + { 0xE6, Z80_set, c4, iys }, + { 0xEE, Z80_set, c5, iys }, + { 0xF6, Z80_set, c6, iys }, + { 0xFE, Z80_set, c7, iys }, + { 0x00, 0 }, +}; + +static const insndesc_t cmdsED[] = +{ + { 0x00, Z80_in0, rB, imm8 }, + { 0x01, Z80_out0, imm8, rB }, + { 0x02, Z80_ld, rBC, rBC }, + { 0x03, Z80_ex, rBC, rIX }, + { 0x04, Z80_tst, rB }, + { 0x05, Z80_ex, rBC, rDE }, + { 0x06, Z80_ldw, atBC, imm16 }, + { 0x07, Z80_ex, rA, rB }, + { 0x08, Z80_in0, rC, imm8 }, + { 0x09, Z80_out0, imm8, rC }, + { 0x0B, Z80_ex, rBC, rIY }, + { 0x0C, Z80_tst, rC }, + { 0x0D, Z80_ex, rBC, rHL }, + { 0x0E, Z80_swap, rBC }, + { 0x0F, Z80_ex, rA, rC }, + { 0x10, Z80_in0, rD, imm8 }, + { 0x11, Z80_out0, imm8, rD }, + { 0x12, Z80_ld, rDE, rBC }, + { 0x13, Z80_ex, rDE, rIX }, + { 0x14, Z80_tst, rD }, + { 0x16, Z80_ldw, atDE, imm16 }, + { 0x17, Z80_ex, rA, rD }, + { 0x18, Z80_in0, rE, imm8 }, + { 0x19, Z80_out0, imm8, rE }, + { 0x1B, Z80_ex, rDE, rIY }, + { 0x1C, Z80_tst, rE }, + { 0x1E, Z80_swap, rDE }, + { 0x1F, Z80_ex, rA, rE }, + { 0x20, Z80_in0, rH, imm8 }, + { 0x21, Z80_out0, imm8, rH }, + { 0x24, Z80_tst, rH }, + { 0x27, Z80_ex, rA, rH }, + { 0x28, Z80_in0, rL, imm8 }, + { 0x29, Z80_out0, imm8, rL }, + { 0x2B, Z80_ex, rIX, rIY }, + { 0x2C, Z80_tst, rL }, + { 0x2F, Z80_ex, rA, rL }, + { 0x30, Z80_in0, imm8 }, + { 0x32, Z80_ld, rHL, rBC }, + { 0x33, Z80_ex, rHL, rIX }, + { 0x34, Z80_tst, atHL }, + { 0x36, Z80_ldw, atHL, imm16 }, + { 0x37, Z80_ex, rA, atHL }, + { 0x38, Z80_in0, rA, imm8 }, + { 0x39, Z80_out0, imm8, rA }, + { 0x3B, Z80_ex, rHL, rIY }, + { 0x3C, Z80_tst, rA }, + { 0x3E, Z80_swap, rHL }, + { 0x3F, Z80_ex, rA, rA }, + { 0x40, Z80_in, rB, atC }, + { 0x41, Z80_out, atC, rB }, + { 0x42, Z80_sbc, rHL, rBC }, + { 0x43, Z80_ld, mem16, rBC }, + { 0x44, Z80_neg, rA }, + { 0x45, Z80_retn, }, + { 0x46, Z80_im, c0 }, + { 0x47, Z80_ld, rI, rA }, + { 0x48, Z80_in, rC, atC }, + { 0x49, Z80_out, atC, rC }, + { 0x4A, Z80_adc, rHL, rBC }, + { 0x4B, Z80_ld, rBC, mem16 }, + { 0x4C, Z80_mlt, rBC }, + { 0x4D, Z80_reti, }, + { 0x4E, Z80_im, c3 }, + { 0x4F, Z80_ld, rR, rA }, + { 0x50, Z80_in, rD, atC }, + { 0x51, Z80_out, atC, rD }, + { 0x52, Z80_sbc, rHL, rDE }, + { 0x53, Z80_ld, mem16, rDE }, + { 0x54, Z80_negw, rHL }, + { 0x56, Z80_im, c1 }, + { 0x57, Z80_ld, rA, rI }, + { 0x58, Z80_in, rE, atC }, + { 0x59, Z80_out, atC, rE }, + { 0x5A, Z80_adc, rHL, rDE }, + { 0x5B, Z80_ld, rDE, mem16 }, + { 0x5C, Z80_mlt, rDE }, + { 0x5E, Z80_im, c2 }, + { 0x5F, Z80_ld, rA, rR }, + { 0x60, Z80_in, rH, atC }, + { 0x61, Z80_out, atC, rH }, + { 0x62, Z80_sbc, rHL, rHL }, + { 0x64, Z80_tst, imm8 }, + { 0x65, Z80_exts, rA }, + { 0x67, Z80_rrd, }, + { 0x68, Z80_in, rL, atC }, + { 0x69, Z80_out, atC, rL }, + { 0x6A, Z80_adc, rHL, rHL }, + { 0x6C, Z80_mlt, rHL }, + { 0x6F, Z80_rld, }, + { 0x71, Z80_out, atC, imm8 }, + { 0x72, Z80_sbc, rHL, rSP }, + { 0x73, Z80_ld, mem16, rSP }, + { 0x74, Z80_tstio, imm8 }, + { 0x75, Z80_extsw, rHL }, + { 0x76, Z80_slp, }, + { 0x78, Z80_in, rA, atC }, + { 0x79, Z80_out, atC, rA }, + { 0x7A, Z80_adc, rHL, rSP }, + { 0x7B, Z80_ld, rSP, mem16 }, + { 0x7C, Z80_mlt, rSP }, + { 0x82, Z80_add, rSP, imm16 }, + { 0x83, Z80_otim, }, + { 0x84, Z80_addw, rHL, rBC }, + { 0x85, Z80_addw, rHL, rDE }, + { 0x86, Z80_addw, rHL, imm16 }, + { 0x87, Z80_addw, rHL, rHL }, + { 0x8B, Z80_otdm, }, + { 0x8C, Z80_adcw, rHL, rBC }, + { 0x8D, Z80_adcw, rHL, rDE }, + { 0x8E, Z80_adcw, rHL, imm16 }, + { 0x8F, Z80_adcw, rHL, rHL }, + { 0x92, Z80_sub, rSP, imm16 }, + { 0x93, Z80_otimr, }, + { 0x94, Z80_subw, rHL, rBC }, + { 0x95, Z80_subw, rHL, rDE }, + { 0x96, Z80_subw, rHL, imm16 }, + { 0x97, Z80_subw, rHL, rHL }, + { 0x9B, Z80_otdmr, }, + { 0x9C, Z80_sbcw, rHL, rBC }, + { 0x9D, Z80_sbcw, rHL, rDE }, + { 0x9E, Z80_sbcw, rHL, imm16 }, + { 0x9F, Z80_sbcw, rHL, rHL }, + { 0xA0, Z80_ldi, }, + { 0xA1, Z80_cpi, }, + { 0xA2, Z80_ini, }, + { 0xA3, Z80_outi, }, + { 0xA4, Z80_andw, rHL, rBC }, + { 0xA5, Z80_andw, rHL, rDE }, + { 0xA6, Z80_andw, rHL, imm16 }, + { 0xA7, Z80_andw, rHL, rHL }, + { 0xA8, Z80_ldd, }, + { 0xA9, Z80_cpd, }, + { 0xAA, Z80_ind, }, + { 0xAB, Z80_outd, }, + { 0xAC, Z80_xorw, rHL, rBC }, + { 0xAD, Z80_xorw, rHL, rDE }, + { 0xAE, Z80_xorw, rHL, imm16 }, + { 0xAF, Z80_xorw, rHL, rHL }, + { 0xB0, Z80_ldir, }, + { 0xB1, Z80_cpir, }, + { 0xB2, Z80_inir, }, + { 0xB3, Z80_otir, }, + { 0xB4, Z80_orw, rHL, rBC }, + { 0xB5, Z80_orw, rHL, rDE }, + { 0xB6, Z80_orw, rHL, imm16 }, + { 0xB7, Z80_orw, rHL, rHL }, + { 0xB8, Z80_lddr, }, + { 0xB9, Z80_cpdr, }, + { 0xBA, Z80_indr, }, + { 0xBB, Z80_otdr, }, + { 0xBC, Z80_cpw, rHL, rBC }, + { 0xBD, Z80_cpw, rHL, rDE }, + { 0xBE, Z80_cpw, rHL, imm16 }, + { 0xBF, Z80_cpw, rHL, rHL }, + { 0xC0, Z80_ldctl, rHL, rSR }, + { 0xC1, Z80_pop, rSR }, + { 0xC4, Z80_calr, ccNZ, rip8 }, + { 0xC5, Z80_push, rSR }, + { 0xC6, Z80_add, rHL, mem16 }, + { 0xC8, Z80_ldctl, rSR, rHL }, + { 0xCC, Z80_calr, ccZ, rip8 }, + { 0xCD, Z80_calr, rip8 }, + { 0xCF, Z80_btest, }, + { 0xD0, Z80_ldctl, rA, rDSR }, + { 0xD3, Z80_outa, mem16, rA }, + { 0xD4, Z80_calr, ccNC, rip8 }, + { 0xD6, Z80_sub, rHL, mem16 }, + { 0xD8, Z80_ldctl, rDSR, rA }, + { 0xD9, Z80_exall, }, + { 0xDA, Z80_ldctl, rDSR, imm8 }, + { 0xDB, Z80_ina, rA, mem16 }, + { 0xDC, Z80_calr, ccC, rip8 }, + { 0xE0, Z80_ldiw, }, + { 0xE2, Z80_iniw, }, + { 0xE3, Z80_outiw, }, + { 0xE4, Z80_calr, ccPO, rip8 }, + { 0xE8, Z80_lddw, }, + { 0xEA, Z80_indw, }, + { 0xEB, Z80_outdw, }, + { 0xEC, Z80_calr, ccPE, rip8 }, + { 0xF0, Z80_ldirw, }, + { 0xF2, Z80_inirw, }, + { 0xF3, Z80_otirw, }, + { 0xF4, Z80_calr, ccP, rip8 }, + { 0xF7, Z80_setc, rLCK }, + { 0xF8, Z80_lddrw, }, + { 0xFA, Z80_indrw, }, + { 0xFB, Z80_otdrw, }, + { 0xFC, Z80_calr, ccM, rip8 }, + { 0xFF, Z80_resc, rLCK }, +}; + +static const insndesc_t cmdsEDCB[] = +{ + { 0x00, Z80_rlcw, rBC }, + { 0x01, Z80_rlcw, rDE }, + { 0x02, Z80_rlcw, atHL }, + { 0x03, Z80_rlcw, rHL }, + { 0x04, Z80_rlcw, rIX }, + { 0x05, Z80_rlcw, rIY }, + { 0x08, Z80_rrcw, rBC }, + { 0x09, Z80_rrcw, rDE }, + { 0x0A, Z80_rrcw, atHL }, + { 0x0B, Z80_rrcw, rHL }, + { 0x0C, Z80_rrcw, rIX }, + { 0x0D, Z80_rrcw, rIY }, + { 0x10, Z80_rlw, rBC }, + { 0x11, Z80_rlw, rDE }, + { 0x12, Z80_rlw, atHL }, + { 0x13, Z80_rlw, rHL }, + { 0x14, Z80_rlw, rIX }, + { 0x15, Z80_rlw, rIY }, + { 0x18, Z80_rrw, rBC }, + { 0x19, Z80_rrw, rDE }, + { 0x1A, Z80_rrw, atHL }, + { 0x1B, Z80_rrw, rHL }, + { 0x1C, Z80_rrw, rIX }, + { 0x1D, Z80_rrw, rIY }, + { 0x20, Z80_slaw, rBC }, + { 0x21, Z80_slaw, rDE }, + { 0x22, Z80_slaw, atHL }, + { 0x23, Z80_slaw, rHL }, + { 0x24, Z80_slaw, rIX }, + { 0x25, Z80_slaw, rIY }, + { 0x28, Z80_sraw, rBC }, + { 0x29, Z80_sraw, rDE }, + { 0x2A, Z80_sraw, atHL }, + { 0x2B, Z80_sraw, rHL }, + { 0x2C, Z80_sraw, rIX }, + { 0x2D, Z80_sraw, rIY }, + { 0x30, Z80_ex, rBC, rBC2 }, + { 0x31, Z80_ex, rDE, rDE2 }, + { 0x33, Z80_ex, rHL, rHL2 }, + { 0x34, Z80_ex, rIX, rIX2 }, + { 0x35, Z80_ex, rIY, rIY2 }, + { 0x38, Z80_srlw, rBC }, + { 0x39, Z80_srlw, rDE }, + { 0x3A, Z80_srlw, atHL }, + { 0x3B, Z80_srlw, rHL }, + { 0x3C, Z80_srlw, rIX }, + { 0x3D, Z80_srlw, rIY }, + { 0x90, Z80_multw, rHL, rBC }, + { 0x91, Z80_multw, rHL, rDE }, + { 0x93, Z80_multw, rHL, rHL }, + { 0x94, Z80_multw, rHL, rIX }, + { 0x95, Z80_multw, rHL, rIY }, + { 0x97, Z80_multw, rHL, imm16 }, + { 0x98, Z80_multuw, rHL, rBC }, + { 0x99, Z80_multuw, rHL, rDE }, + { 0x9B, Z80_multuw, rHL, rHL }, + { 0x9C, Z80_multuw, rHL, rIX }, + { 0x9D, Z80_multuw, rHL, rIY }, + { 0x9F, Z80_multuw, rHL, imm16 }, + { 0xB8, Z80_divuw, rHL, rBC }, + { 0xB9, Z80_divuw, rHL, rDE }, + { 0xBB, Z80_divuw, rHL, rHL }, + { 0xBC, Z80_divuw, rHL, rIX }, + { 0xBD, Z80_divuw, rHL, rIY }, + { 0xBF, Z80_divuw, rHL, imm16 }, +}; + +//------------------------------------------------------------------------ +void z80_t::load_z80_operand(insn_t &insn, op_t &x, uchar op) +{ + if ( op == 0 ) + return; + switch ( op ) + { + case rBC: + case rDE: + case rHL: + case rIX: + case rIY: + case rBC2: + case rDE2: + case rHL2: + case rIX2: + case rIY2: + case rSP: + case rLW: + case rIXL: + case rIXU: + case rDSR: + case rXSR: + case rIYL: + case rIYU: + case rYSR: + case rSR: + case rIB: + case rIW: + case rXM: + case rLCK: + x.dtype = dt_word; + // fallthrough + case rA: + case rB: + case rC: + case rD: + case rE: + case rH: + case rL: + case rI: + case rW: + case rR: + x.type = o_reg; + x.reg = op - 1; + break; + + case atBC: + x.type = o_phrase; + x.phrase = R_bc; + break; + case atDE: + x.type = o_phrase; + x.phrase = R_de; + break; + case atHL: + x.type = o_phrase; + x.phrase = R_hl; + break; + case atSP: + x.type = o_phrase; + x.phrase = R_sp; + break; + case atIX: + x.type = o_phrase; + x.phrase = R_ix; + break; + case atIY: + x.type = o_phrase; + x.phrase = R_iy; + break; + case atC: + x.type = o_phrase; + x.phrase = R_c; + break; + + case rip8: + { + sval_t disp = char(insn.get_next_byte()); + x.type = o_near; + x.addr = insn.ip + insn.size + disp; + } + break; + case rip16: + { + sval_t disp = short(insn.get_next_word()); + x.type = o_near; + x.addr = insn.ip + insn.size + disp; + } + break; + case rip24: + { + sval_t disp = insn.get_next_word(); + disp |= (sval_t((char)(insn.get_next_byte())) << 16); + x.type = o_near; + x.addr = insn.ip + insn.size + disp; + } + break; + + case imm8: + x.type = o_imm; + x.value = insn.get_next_byte(); + break; + + case imm16: + x.type = o_imm; + x.dtype = dt_word; + x.value = insn.get_next_word(); + break; + + case mem16: + x.type = o_mem; + x.addr = insn.get_next_word(); + break; + + case ix8: + x.type = o_displ; + x.phrase = R_ix; + x.addr = insn.get_next_byte(); + break; + case iy8: + x.type = o_displ; + x.phrase = R_iy; + x.addr = insn.get_next_byte(); + break; + case ixs: + x.type = o_displ; + x.phrase = R_ix; + x.addr = saved_value; + break; + case iys: + x.type = o_displ; + x.phrase = R_iy; + x.addr = saved_value; + break; + case sps: + x.type = o_displ; + x.phrase = R_sp; + x.addr = saved_value; + break; + + case ccNZ: + case ccZ: + case ccNC: + case ccC: + case ccPO: + case ccPE: + case ccP: + case ccM: + x.type = o_cond; + x.Cond = op - ccNZ; + break; + + case c0: + case c1: + case c2: + case c3: + case c4: + case c5: + case c6: + case c7: + x.type = o_imm; + x.value = op - c0; + break; + + default: + warning("%a: interr in z380, code=%x", insn.ea, code); + } +} + +//------------------------------------------------------------------------ +bool z80_t::search_map(insn_t &insn, const insndesc_t *map, uchar _code) +{ + for ( int i=0; map[i].itype; i++ ) + { + if ( map[i].code > _code ) + break; + if ( map[i].code == _code ) + { + insn.itype = map[i].itype; + load_z80_operand(insn, insn.Op1, map[i].op1); + load_z80_operand(insn, insn.Op2, map[i].op2); + return true; + } + } + return false; +} + +//------------------------------------------------------------------------ +bool z80_t::z380_insns(insn_t &insn, const insndesc_t *map, const insndesc_t *cb) +{ + code = insn.get_next_byte(); + if ( code == 0xCB ) + { + map = cb; + saved_value = insn.get_next_byte(); + code = insn.get_next_byte(); + } + return search_map(insn, map, (uchar)code); +} + +//------------------------------------------------------------------------ +bool z80_t::z380_ED(insn_t &insn) +{ + const insndesc_t *map = cmdsED; + code = insn.get_next_byte(); + if ( code == 0xCB ) + { + map = cmdsEDCB; + code = insn.get_next_byte(); + } + return search_map(insn, map, (uchar)code); +} + +//------------------------------------------------------------------------ +void z80_t::z80_ixcommands(insn_t &insn, bool _isx) +{ + if ( isGB() ) + return; + if ( isZ380() ) + { + if ( _isx ) + z380_insns(insn, cmdsDD, cmdsDDCB); + else + z380_insns(insn, cmdsFD, cmdsFDCB); + return; + } + + isx = _isx; + code = insn.get_next_byte(); + switch ( (code>>4) & 0xF ) + { + case 0: /* 0000???? */ + case 1: /* 0001???? */ + if ( (code & 0xF) == 9 ) + { + insn.itype = I5_add; + op_ix(insn.Op1); + op_ss(insn.Op2); + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + } + break; + case 2: /* 0010???? */ + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + (code & 4) ? op_ibyte(insn.Op1,code & 8) : op_ix(insn.Op1); + switch ( code & 0xF ) + { + case 1: + insn.itype = I5_lxi; + op_nn(insn, insn.Op2); + break; + case 2: + insn.itype = I5_mov; + op_mm(insn, insn.Op1); + op_ix(insn.Op2); + break; + case 3: + insn.itype = I5_inx; + break; + case 4: + case 0xC: + insn.itype = I5_inr; + break; + case 5: + case 0xD: + insn.itype = I5_dcr; + break; + case 6: + case 0xE: + insn.itype = I5_mvi; + op_n(insn, insn.Op2); + break; + case 9: + insn.itype = I5_add; + op_ix(insn.Op2); + break; + case 0xA: + insn.itype = I5_mov; + op_mm(insn, insn.Op2); + break; + case 0xB: + insn.itype = I5_dcx; + break; + } + break; + case 3: + switch ( code & 0xF ) + { + case 4: + insn.itype = I5_inr; + op_xdispl(insn, insn.Op1); + break; + case 5: + insn.itype = I5_dcr; + op_xdispl(insn, insn.Op1); + break; + case 6: + insn.itype = I5_mvi; + op_xdispl(insn, insn.Op1); + op_n(insn, insn.Op2); + break; + case 9: + insn.itype = I5_add; + op_ix(insn.Op1); + op_ss(insn.Op2); + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + break; + } + break; + case 4: + case 5: + if ( (code & 6) == 4 ) + { + insn.itype = I5_mov; + op_xr1(insn.Op1); + op_ibyte(insn.Op2,code & 1); + break; + } + /* no break */ + case 6: + if ( (code & 6) == 4 ) + break; + if ( (code & 7) == 6 ) + { + if ( op_xr1(insn.Op1) ) + break; // mem,mem not allowed + if ( code == 0x66 ) + insn.Op1.reg = R_h; + if ( code == 0x6E ) + insn.Op1.reg = R_l; + op_xdispl(insn, insn.Op2); + insn.itype = I5_mov; + break; + } + if ( (code & 0xF0) == 0x60 ) + { + op_ibyte(insn.Op1,code & 8); + op_xr2(insn.Op2); + insn.itype = I5_mov; + } + break; + case 7: + switch ( code & 0xF ) + { + case 0: case 1: case 2: case 3: case 4: case 5: case 7: + op_xdispl(insn, insn.Op1); + if ( !op_xr2(insn.Op2) ) + insn.itype = I5_mov; + if ( code == 0x74 ) + insn.Op2.reg = R_h; + if ( code == 0x75 ) + insn.Op2.reg = R_l; + break; + case 0xE: + op_xdispl(insn, insn.Op2); + op_a(insn.Op1); + insn.itype = I5_mov; // to show all regs + break; + case 0xC: + case 0xD: + op_ibyte(insn.Op2,code & 1); + op_a(insn.Op1); + insn.itype = I5_mov; // to show all regs + break; + } + break; + case 8: + case 9: + case 0xA: + case 0xB: + if ( (code & 4) == 4 && (code & 7) != 7 ) + { + int type = (code >> 3) & 7; + insn.itype = W[type]; + op_a(insn.Op1); + ((code & 7) == 6) ? op_xdispl(insn, insn.Op2) + : op_ibyte(insn.Op2,code & 1); +// if ( type == 0 || type == 1 || type == 3 ) insn.Op1.clr_show(); + } + break; + case 0xC: + if ( code == 0xCB ) + { + op_xdispl(insn, insn.Op2); + code = insn.get_next_byte(); + if ( (code & 7) == 6 ) + { + int type = (code>>6) & 3; + if ( type == 0 ) + { + insn.itype = CBrols[ (code >> 3) & 7 ]; + op_a(insn.Op1); + } + else + { + static const uint16 brs[] = { I5_null, Z80_bit, Z80_res, Z80_set }; + insn.itype = brs[type]; + insn.Op1.type = o_imm; + insn.Op1.value = (code >> 3) & 7; + } + } + } + break; + case 0xE: + switch ( code & 0xF ) + { + case 1: + insn.itype = I5_pop; + op_ix(insn.Op1); + break; + case 3: + insn.itype = Z80_ex; + insn.Op1.type = o_phrase; + insn.Op1.phrase = R_sp; + insn.Op1.dtype = dt_word; + op_ix(insn.Op2); + break; + case 5: + insn.itype = I5_push; + op_ix(insn.Op1); + break; + case 9: + insn.itype = Z80_jp; + insn.Op1.type = o_cond; + insn.Op1.Cond = oc_not; + insn.Op2.type = o_phrase; + insn.Op2.phrase = isx ? R_ix : R_iy; + insn.Op2.dtype = dt_code; + break; + case 0xD: + code = insn.get_next_byte(); + switch ( code ) + { + case 0x42: + case 0x4A: + case 0x52: + case 0x5A: + case 0x62: + case 0x6A: + case 0x72: + case 0x7A: + insn.itype = (code & 8) ? I5_adc : Z80_sbc; + op_ix(insn.Op1); + op_ss(insn.Op2); + if ( insn.Op2.reg == R_hl ) + op_ix(insn.Op2); + break; + case 0x60: + case 0x68: + insn.itype = I5_in; + op_ibyte(insn.Op1,code & 8); + op_c(insn.Op2); + break; + case 0x61: + case 0x69: + insn.itype = I5_out; + op_c(insn.Op1); + op_ibyte(insn.Op2,code & 8); + break; + } + break; + } + // fallthrough + case 0xF: + if ( code == 0xF9 ) + { + insn.itype = I5_mov; + insn.Op1.type = o_reg; + insn.Op1.phrase = R_sp; + insn.Op1.dtype = dt_word; + op_ix(insn.Op2); + } + break; + } +} + + +//------------------------------------------------------------------------ +void z80_t::z80_misc(insn_t &insn) +{ + code = insn.get_next_byte(); + switch ( code ) + { + case 0x40: + case 0x48: + case 0x50: + case 0x58: + case 0x60: + case 0x68: + case 0x78: + insn.itype = I5_in; + op_r1(insn.Op1); + op_c(insn.Op2); + break; + case 0x41: + case 0x49: + case 0x51: + case 0x59: + case 0x61: + case 0x69: + case 0x79: + insn.itype = I5_out; + op_c(insn.Op1); + op_r1(insn.Op2); + break; + case 0x42: + case 0x4A: + case 0x52: + case 0x5A: + case 0x62: + case 0x6A: + case 0x72: + case 0x7A: + insn.itype = (code & 8) ? I5_adc : Z80_sbc; + insn.Op1.type = o_reg; + insn.Op1.reg = R_hl; + insn.Op1.dtype = dt_word; + op_ss(insn.Op2); + break; + case 0x43: + case 0x53: + case 0x73: + insn.itype = I5_mov; + op_mm(insn, insn.Op1); + op_ss(insn.Op2); + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + break; + case 0x44: insn.itype = Z80_neg; break; + case 0x45: insn.itype = Z80_retn; break; + case 0x46: + insn.itype = Z80_im; + insn.Op1.type = o_imm; + insn.Op1.value = 0; + break; + case 0x47: + insn.itype = I5_mov; // to show all regs + insn.Op1.type = o_reg; + insn.Op1.reg = R_i; + op_a(insn.Op2); + break; + case 0x4B: + case 0x5B: + case 0x7B: + insn.itype = I5_mov; + op_ss(insn.Op1); + op_mm(insn, insn.Op2); + insn.Op1.dtype = dt_word; + insn.Op2.dtype = dt_word; + break; + case 0x4D: + insn.itype = Z80_reti; + break; + case 0x4F: + insn.itype = I5_mov; // to show all regs + insn.Op1.type = o_reg; + insn.Op1.reg = R_r; + op_a(insn.Op2); + break; + case 0x56: + insn.itype = Z80_im; + insn.Op1.type = o_imm; + insn.Op1.value = 1; + break; + case 0x5E: + insn.itype = Z80_im; + insn.Op1.type = o_imm; + insn.Op1.value = 2; + break; + case 0x57: + insn.itype = I5_mov; // to show all regs + op_a(insn.Op1); + insn.Op2.type = o_reg; + insn.Op2.reg = R_i; + break; + case 0x5F: + insn.itype = I5_mov; // to show all regs + op_a(insn.Op1); + insn.Op2.type = o_reg; + insn.Op2.reg = R_r; + break; + case 0x67: insn.itype = Z80_rrd; break; + case 0x6F: insn.itype = Z80_rld; break; + + case 0xA0: insn.itype = Z80_ldi; break; + case 0xA1: insn.itype = Z80_cpi; break; + case 0xA2: insn.itype = Z80_ini; break; + case 0xA3: insn.itype = Z80_outi; break; + case 0xA8: insn.itype = Z80_ldd; break; + case 0xA9: insn.itype = Z80_cpd; break; + case 0xAA: insn.itype = Z80_ind; break; + case 0xAB: insn.itype = Z80_outd; break; + case 0xB0: insn.itype = Z80_ldir; break; + case 0xB1: insn.itype = Z80_cpir; break; + case 0xB2: insn.itype = Z80_inir; break; + case 0xB3: insn.itype = Z80_otir; break; + case 0xB8: insn.itype = Z80_lddr; break; + case 0xB9: insn.itype = Z80_cpdr; break; + case 0xBA: insn.itype = Z80_indr; break; + case 0xBB: insn.itype = Z80_otdr; break; +// +// HD64180 extensions +// + case 0x76: if ( is64180() ) insn.itype = HD_slp; break; + case 0x83: if ( is64180() ) insn.itype = HD_otim; break; + case 0x93: if ( is64180() ) insn.itype = HD_otimr; break; + case 0x8B: if ( is64180() ) insn.itype = HD_otdm; break; + case 0x9B: if ( is64180() ) insn.itype = HD_otdmr; break; + case 0x64: + if ( is64180() ) + { + insn.itype = HD_tst; + op_n(insn, insn.Op1); + } + break; + case 0x74: + if ( is64180() ) + { + insn.itype = HD_tstio; + op_n(insn, insn.Op1); + } + break; + default: +// I did not find an assembler that understands this... +// if ( (code & 0xC0) == 0x40 && (code & 6) == 0 ) // undocumented +// { +// insn.itype = (code & 1) ? I5_out : I5_in; +// op_r1(insn.Op1); +// break; +// } +//-------- + if ( is64180() ) + { + switch ( code & 0xC0 ) + { + case 0: + switch ( code & 7 ) + { + case 0: + insn.itype = HD_in0; + op_r1(insn.Op1); + op_n(insn, insn.Op2); + if ( insn.Op1.type == o_phrase ) + op_f(insn.Op1); + break; + case 1: + insn.itype = HD_out0; + op_n(insn, insn.Op1); + op_r1(insn.Op2); + break; + case 4: + insn.itype = HD_tst; + op_r1(insn.Op1); + break; + } + break; + case 0x40: + if ( code == 0x70 ) + { + insn.itype = I5_in; + op_f(insn.Op1); + op_c(insn.Op2); + break; + } + if ( (code & 0xF) == 0xC ) + { + insn.itype = HD_mlt; + op_ss(insn.Op1); + } + break; + } + } + break; + } +} diff --git a/idasdk75/module/z80/emu.cpp b/idasdk76/module/z80/emu.cpp similarity index 100% rename from idasdk75/module/z80/emu.cpp rename to idasdk76/module/z80/emu.cpp diff --git a/idasdk76/module/z80/i5.hpp b/idasdk76/module/z80/i5.hpp new file mode 100644 index 0000000..cfc8c92 --- /dev/null +++ b/idasdk76/module/z80/i5.hpp @@ -0,0 +1,230 @@ +/* + * Interactive disassembler (IDA). + * Version 2.06 + * Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet) + * ALL RIGHTS RESERVED. + * + */ + +#ifndef I5HPP +#define I5HPP + +#include "../idaidp.hpp" +#include "ins.hpp" +#include <diskio.hpp> +#include "../iohandler.hpp" + +//------------------------------------------------------------------ +// debugger functions +typedef const regval_t &idaapi getreg_t(const char *name, const regval_t *regvalues); + +//------------------------------------------------------------------ +// customization of insn_t structure: +#define o_cond o_idpspec0 + +#define Cond reg + + +//------------------------------------------------------------------ +enum opcond_t // condition code types +{ + oc_nz, + oc_z, + oc_nc, + oc_c, + oc_po, + oc_pe, + oc_p, + oc_m, + oc_not +}; + +//------------------------------------------------------------------ +#define _PT_64180 0x01 // HD64180 +#define _PT_Z80 0x02 // Z80 +#define _PT_8085 0x04 // Intel 8085 +#define _PT_Z180 0x08 // Z180 +#define _PT_Z380 0x10 // Z380 +#define _PT_GB 0x20 // GameBoy + +#define PT_GB _PT_GB +#define PT_Z380 _PT_Z380 +#define PT_Z180 ( PT_Z380 | _PT_Z180) +#define PT_64180 ( PT_Z180 | _PT_64180) +#define PT_Z80 ( PT_64180| _PT_Z80 | _PT_GB) +#define PT_8085 ( PT_Z80 | _PT_8085 ) + +extern int pflag; + +enum RegNo ENUM_SIZE(uint16) +{ + R_b = 0, + R_c = 1, + R_d = 2, + R_e = 3, + R_h = 4, + R_l = 5, + R_a = 7, + R_bc = 8, + R_de = 9, + R_hl = 10, + R_af = 11, + R_sp = 12, + R_ix = 13, + R_iy = 14, + R_af2 = 15, + R_r = 16, + R_i = 17, + R_f = 18, + R_xl = 19, + R_xh = 20, + R_yl = 21, + R_yh = 22, + + R_w, + R_lw, + R_ixl, + R_ixu, + R_dsr, + R_xsr, + R_iyl, + R_iyu, + R_ysr, + R_sr, + R_ib, + R_iw, + R_xm, + R_lck, + R_bc2, + R_de2, + R_hl2, + R_ix2, + R_iy2, + R_b2, + R_c2, + R_d2, + R_e2, + R_h2, + R_l2, + R_m2, + R_a2, + + R_vcs, // virtual code segment register + R_vds // virtual data segment register +}; + + +//------------------------------------------------------------------ +#define UAS_NOENS 0x0001 // I5: don't specify start addr in the .end directive +#define UAS_NPAIR 0x0002 // I5: pairs are denoted by 1 char ('b') +#define UAS_UNDOC 0x0004 // I5: does assembler support undoc-d instrs? +#define UAS_MKIMM 0x0008 // I5: place # in front of imm operand +#define UAS_MKOFF 0x0010 // I5: offset(ix) form +#define UAS_CNDUP 0x0020 // I5: conditions UPPERCASE +#define UAS_FUNNY 0x0040 // I5: special for A80 +#define UAS_CSEGS 0x0080 // I5: generate 'cseg' directives +#define UAS_TOFF 0x0100 // I5: (ix+-10) +#define UAS_ZMASM 0x0200 // ZMASM +#define UAS_GBASM 0x0400 // RGBASM + + +#define aux_off16 0x0001 // o_displ: off16 + +//------------------------------------------------------------------ +struct z80_iohandler_t : public iohandler_t +{ + z80_iohandler_t(netnode &nn) : iohandler_t(nn) {} +}; + +struct insndesc_t; +struct z80_t : public procmod_t +{ + netnode helper; + z80_iohandler_t ioh = z80_iohandler_t(helper); + + int pflag = 0; + int code; + + uchar saved_value = 0; + bool flow = false; + bool isx = false; + + virtual ssize_t idaapi on_event(ssize_t msgid, va_list va) override; + + const char *find_ioport(uval_t port); + const char *find_ioport_bit(int port, int bit); + void choose_device(int respinfo); + + void set_cpu(int np); + void load_from_idb(); + + const char *set_idp_options(const char *keyword, int /*value_type*/, const void * /*value*/, bool /*idb_loaded*/); + + // out.cpp + inline bool isFunny(void) { return (ash.uflag & UAS_FUNNY) != 0; } + void i5_header(outctx_t &ctx); + void i5_footer(outctx_t &ctx); + void i5_segstart(outctx_t &ctx, segment_t *); + + // ana.cpp + int i5_ana(insn_t *_insn); + void load_z80_operand(insn_t &insn, op_t &x, uchar op); + bool search_map(insn_t &insn, const insndesc_t *map, uchar _code); + bool z380_insns(insn_t &insn, const insndesc_t *map, const insndesc_t *cb); + bool z380_ED(insn_t &insn); + void z80_ixcommands(insn_t &insn, bool _isx); + void z80_misc(insn_t &insn); + void ConvertToZ80(insn_t &insn); + void op_r1(op_t &x) const; + void op_r2(op_t &x) const; + void op_ss(op_t &x) const; + void op_dd(op_t &x) const; + void op_xdispl(insn_t &insn, op_t &x) const; + void op_ix(op_t &x) const; + void op_ibyte(op_t &x,int low) const; + int op_xbytereg(op_t &x,uint16 mode) const; + int op_xr1(op_t &x) const; + int op_xr2(op_t &x) const; + inline bool isGB(void); + inline bool isZ380(void); + inline bool isZ180(void); + inline bool isZ80(void); + inline bool is64180(void); + inline bool is8085(void); + + // emu.cpp + int i5_emu(const insn_t &insn); + void load_operand(const insn_t &insn, const op_t &x); + sval_t named_regval(const char *regname, getreg_t *getreg, const regval_t *rv); + sval_t regval(const op_t &op, getreg_t *getreg, const regval_t *rv); + bool check_cond(uint16_t cc, getreg_t *getreg, const regval_t *regvalues); + ea_t next_exec_insn( + ea_t ea, + getreg_t *getreg, + const regval_t *regvalues); + ea_t calc_step_over(ea_t ip) const; + bool get_operand_info( + idd_opinfo_t *opinf, + ea_t ea, + int n, + getreg_t *getreg, + const regval_t *regvalues); + bool get_reg_info( + const char **main_regname, + bitrange_t *bitrange, + const char *regname); +}; + +extern int data_id; +#define PROCMOD_NAME z80 +#define PROCMOD_NODE_NAME "$ " QSTRINGIZE(PROCMOD_NAME) + + +inline bool z80_t::isGB(void) { return (pflag & PT_GB) != 0; } +inline bool z80_t::isZ380(void) { return (pflag & PT_Z380) != 0; } +inline bool z80_t::isZ180(void) { return (pflag & PT_Z180) != 0; } +inline bool z80_t::isZ80(void) { return (pflag & PT_Z80) != 0; } +inline bool z80_t::is64180(void) { return (pflag & PT_64180) != 0; } +inline bool z80_t::is8085(void) { return !isZ80(); } + +#endif // I5HPP diff --git a/idasdk75/module/z80/ins.cpp b/idasdk76/module/z80/ins.cpp similarity index 100% rename from idasdk75/module/z80/ins.cpp rename to idasdk76/module/z80/ins.cpp diff --git a/idasdk76/module/z80/ins.hpp b/idasdk76/module/z80/ins.hpp new file mode 100644 index 0000000..675ec90 --- /dev/null +++ b/idasdk76/module/z80/ins.hpp @@ -0,0 +1,303 @@ +/* + * Interactive disassembler (IDA). + * Copyright (c) 1990-2021 Hex-Rays + * ALL RIGHTS RESERVED. + * + */ + +#ifndef __INSTRS_HPP +#define __INSTRS_HPP + +extern const instruc_t Instructions[]; + +enum nameNum ENUM_SIZE(uint16) +{ +I5_null = 0, // Unknown Operation + +// +// Intel 8080-8085 instructions +// + +I5_aci, +I5_adc, Z80_adc = I5_adc, +I5_add, Z80_add = I5_add, +I5_adi, +I5_ana, +I5_ani, +I5_call, +I5_cnz, +I5_cz, +I5_cnc, +I5_cc, +I5_cpo, +I5_cpe, +I5_cp, +I5_cm, +I5_cmc, +I5_cmp, +I5_cpi, +I5_cma, +I5_daa, +I5_dad, +I5_dcr, +I5_dcx, +I5_di, Z80_di = I5_di, +I5_ei, Z80_ei = I5_ei, +I5_halt, +I5_in, Z80_in = I5_in, +I5_inr, +I5_inx, +I5_jmp, +I5_jnz, +I5_jz, +I5_jnc, +I5_jc, +I5_jpo, +I5_jpe, +I5_jp, +I5_jm, +I5_lda, +I5_ldax, +I5_lhld, +I5_lxi, +I5_mov, +I5_mvi, +I5_nop, +I5_ora, +I5_ori, +I5_out, Z80_out = I5_out, +I5_pchl, +I5_pop, Z80_pop = I5_pop, +I5_push, Z80_push = I5_push, +I5_ret, +I5_rnz, +I5_rz, +I5_rnc, +I5_rc, +I5_rpo, +I5_rpe, +I5_rp, +I5_rm, +I5_ral, +I5_rlc, +I5_rar, +I5_rrc, +I5_rst, +I5_sbb, +I5_sbi, +I5_stc, +I5_sphl, +I5_sta, +I5_stax, +I5_shld, +I5_sui, +I5_sub, Z80_sub = I5_sub, +I5_xra, +I5_xri, +I5_xchg, +I5_xthl, + +I5_rim, +I5_sim, + +// +// Z80 extensions +// + +Z80_and, +Z80_bit, +Z80_call, +Z80_ccf, +Z80_cp, +Z80_cpd, +Z80_cpdr, +Z80_cpi, +Z80_cpir, +Z80_cpl, +Z80_dec, +Z80_djnz, +Z80_ex, +Z80_exx, +Z80_halt, +Z80_im, +Z80_inc, +Z80_ind, +Z80_indr, +Z80_ini, +Z80_inir, +Z80_jp, +Z80_jr, +Z80_ld, +Z80_ldd, +Z80_lddr, +Z80_ldi, +Z80_ldir, +Z80_neg, +Z80_or, +Z80_otdr, +Z80_otir, +Z80_outd, +Z80_outi, +Z80_res, +Z80_ret, +Z80_reti, +Z80_retn, +Z80_rl, +Z80_rla, +Z80_rlc, +Z80_rlca, +Z80_rld, +Z80_rr, +Z80_rra, +Z80_rrc, +Z80_rrca, +Z80_rrd, +Z80_scf, +Z80_sbc, +Z80_set, +Z80_sla, +Z80_sra, +Z80_srl, +Z80_xor, +Z80_inp, // undocumented +Z80_outp, // undocumented +Z80_srr, // undocumented + +// +// HD64180 extensions +// + +HD_in0, Z80_in0 = HD_in0, +HD_mlt, Z80_mlt = HD_mlt, +HD_otim, Z80_otim = HD_otim, +HD_otimr, Z80_otimr = HD_otimr, +HD_otdm, Z80_otdm = HD_otdm, +HD_otdmr, Z80_otdmr = HD_otdmr, +HD_out0, Z80_out0 = HD_out0, +HD_slp, Z80_slp = HD_slp, +HD_tst, Z80_tst = HD_tst, +HD_tstio, Z80_tstio = HD_tstio, + +// +// A80 special instructions +// + +A80_lbcd, +A80_lded, +A80_lspd, +A80_lixd, +A80_liyd, +A80_sbcd, +A80_sded, +A80_sspd, +A80_sixd, +A80_siyd, +A80_xtix, +A80_xtiy, +A80_spix, +A80_spiy, +A80_pcix, +A80_pciy, +A80_mvra, +A80_mvia, +A80_mvar, +A80_mvai, +A80_addix, +A80_addiy, +A80_addc, +A80_addcix, +A80_addciy, +A80_subc, +A80_subcix, +A80_subciy, +A80_jrc, +A80_jrnc, +A80_jrz, +A80_jrnz, +A80_cmpi, +A80_cmpd, +A80_im0, +A80_im1, +A80_im2, +A80_otd, +A80_oti, + +// Intel 8085 undocumented instructions +// (info from http://oak.oakland.edu/pub/cpm/maclib/i8085.lib) + +I5_dsub, // (HL) <- (HL)-(BC), affects all flags +I5_arhl, // SHIFT HL RIGHT ONE BIT, (H7 IS DUPLICATED, L0 IS SHIFTED INTO CY) +I5_rdel, // ROTATE DE LEFT ONE BIT THRU CY, (E0 RECEIVES CY, CY RECEIVES D7) +I5_ldhi, // (DE) <- (HL)+arg +I5_ldsi, // (DE) <- (SP)+arg +I5_shlx, // ((DE)) <- (HL) +I5_lhlx, // (HL) <- ((DE)) +I5_rstv, // RESTART 40H ON V (OVERFLOW) +I5_jx5, // JUMP IF X5 SET +I5_jnx5, // JUMP IF NOT X5 SET + +// Z380 instructions + +Z80_cplw, // Complement HL register +Z80_swap, // Swap upper register word with lower register word +Z80_inw, // Input word +Z80_outw, // Output word +Z80_ldw, // Load word +Z80_addw, // Add word +Z80_subw, // Subtract word +Z80_adcw, // Add with carry word +Z80_sbcw, // Subtract with borrow word +Z80_andw, // AND logical word +Z80_xorw, // XOR logical word +Z80_orw, // OR logical word +Z80_cpw, // Compare word +Z80_ddir, // Decoder directive +Z80_calr, // Call relative +Z80_ldctl, // Load control register +Z80_mtest, // Mode test +Z80_exxx, // Exchange Index Register with Alternate Bank +Z80_exxy, // Exchange Index Register with Alternate Bank +Z80_exall, // Exchange all registers with Alternate Bank +Z80_setc, // Set control bit +Z80_resc, // Reset control bit +Z80_rlcw, // Rotate Left Circular Word +Z80_rrcw, // Rotate Right Circular Word +Z80_rlw, // Rotate Left Word +Z80_rrw, // Rotate Right Word +Z80_slaw, // Shift Left Arithmetic Word +Z80_sraw, // Shift Right Arithmetic Word +Z80_srlw, // Shift Right Logical Word +Z80_multw, // Multiply Word +Z80_multuw, // Multiply Word Unsigned +Z80_divuw, // Divide unsigned +Z80_outaw, // Output word direct to port address +Z80_inaw, // Input word direct from port address +Z80_outa, // Output byte direct to port address +Z80_ina, // Input byte direct from port address +Z80_negw, // Negate word +Z80_exts, // Extend byte sign +Z80_extsw, // Extend word sign +Z80_btest, // Bank test +Z80_ldiw, // Load and increment (word) +Z80_ldirw, // Load and increment, repeat (word) +Z80_lddw, // Load and decrement (word) +Z80_lddrw, // Load and decrement, repeat (word) +Z80_iniw, // Input and increment (word) +Z80_inirw, // Input and increment, repeat (word) +Z80_indw, // Input and decrement (word) +Z80_indrw, // Input and decrement, repeat (word) +Z80_outiw, // Output and increment (word) +Z80_otirw, // Output and increment, repeat (word) +Z80_outdw, // Output and decrement (word) +Z80_otdrw, // Output and decrement, repeat (word) + +// Gameboy instructions + +GB_ldh, +GB_stop, + +I5_last, + + }; + +#endif diff --git a/idasdk76/module/z80/makefile b/idasdk76/module/z80/makefile new file mode 100644 index 0000000..cda6204 --- /dev/null +++ b/idasdk76/module/z80/makefile @@ -0,0 +1,52 @@ +PROC=z80 +CONFIGS=z180.cfg + + +include ../module.mak + +# MAKEDEP dependency list ------------------ +$(F)ana$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + ana.cpp i5.hpp ins.hpp +$(F)emu$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + emu.cpp i5.hpp ins.hpp +$(F)ins$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ins.cpp ins.hpp +$(F)out$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + i5.hpp ins.hpp out.cpp +$(F)reg$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)diskio.hpp \ + $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ../idaidp.hpp ../iohandler.hpp \ + i5.hpp ins.hpp reg.cpp diff --git a/idasdk75/module/z80/out.cpp b/idasdk76/module/z80/out.cpp similarity index 100% rename from idasdk75/module/z80/out.cpp rename to idasdk76/module/z80/out.cpp diff --git a/idasdk76/module/z80/reg.cpp b/idasdk76/module/z80/reg.cpp new file mode 100644 index 0000000..8862b96 --- /dev/null +++ b/idasdk76/module/z80/reg.cpp @@ -0,0 +1,1084 @@ +/* + * Interactive disassembler (IDA). + * Version 2.06 + * Copyright (c) 1990-93 by Ilfak Guilfanov. (2:5020/209@fidonet) + * ALL RIGHTS RESERVED. + * + */ + +#include "i5.hpp" +#include <diskio.hpp> + +int data_id; + +static const char *const RegNames[] = +{ + "b", "c", "d", "e", "h", "l", "m", "a", // 0..7 + "bc", "de", "hl","psw","sp","ix","iy","af'", // 8..15 + "r", "i", "f", "xl", "xh","yl","yh", // 16..22 + + "w", "lw", "ixl", "ixu", "dsr", "xsr", "iyl", + "iyu", "ysr", "sr", "ib", "iw", "xm", "lck", + "bc'", "de'", "hl'","ix'","iy'", + "b'", "c'", "d'", "e'", "h'", "l'", "m'", "a'", + + "cs","ds" +}; + +//----------------------------------------------------------------------- +// PseudoSam assembler definiton +//----------------------------------------------------------------------- +static const char *const ps_headers[] = +{ + ".code", + NULL +}; + +static const asm_t pseudosam = +{ + AS_COLON | ASH_HEXF1 | AS_N2CHR, + 0, + "PseudoSam by PseudoCode", + 0, + ps_headers, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".db", // ascii string directive + ".db", // byte directive + ".drw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".rs %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// TASM assembler definiton for 8085 +//----------------------------------------------------------------------- +static const char tasmname[] = "Table Driven Assembler (TASM) by Speech Technology Inc."; +static const asm_t tasm = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_NPAIR | UAS_NOENS, + tasmname, + 0, + NULL, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".text", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".block %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// TASM assembler definiton for Z80 +//----------------------------------------------------------------------- +static const asm_t tasmz80 = +{ + AS_COLON | AS_N2CHR | AS_1TEXT, + UAS_NOENS | UAS_TOFF, + "Table Driven Assembler (TASM) by Speech Technology Inc.", + 0, + NULL, + ".org", + ".end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\\\"'", // special symbols in char and string constants + + ".text", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".block %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// Cross-16 assembler definiton (8085) +//----------------------------------------------------------------------- +static const char *const cross16_headers[] = +{ + "cpu \"8085.tbl\"", + NULL +}; + +static const asm_t cross16 = +{ + AS_COLON | AS_NHIAS, + UAS_NPAIR, + "Cross-16 by Universal Cross-Assemblers", + 0, + cross16_headers, + "org", + "end", + + ";", // comment string + '"', // string delimiter + '\0', // char delimiter (no char consts) + "\\\"'", // special symbols in char and string constants + + "dfb", // ascii string directive + "dfb", // byte directive + "dwl", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// Cross-16 assembler definiton (z80) +//----------------------------------------------------------------------- +static const char *const cross16z80_headers[] = +{ + "cpu \"z80.tbl\"", + NULL +}; + +static const asm_t cross16z80 = +{ + AS_COLON | AS_NHIAS, + UAS_MKIMM, + "Cross-16 by Universal Cross-Assemblers", + 0, + cross16z80_headers, + "org", + "end", + + ";", // comment string + '"', // string delimiter + '\0', // char delimiter (no char consts) + "\\\"'", // special symbols in char and string constants + + "dfb", // ascii string directive + "dfb", // byte directive + "dwl", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "dfs %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// A80 assembler definiton +//----------------------------------------------------------------------- +static const asm_t a80 = +{ + AS_COLON | ASD_DECF1 | ASH_HEXF2 | AS_UNEQU, + UAS_NPAIR, + "A80 by ANTA electronics", + 0, + NULL, + "org", + NULL, + + ";", // comment string + '\'', // string delimiter + '\0', // char delimiter (no char consts) + "'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + NULL, // uninited arrays + "equ", + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// A80 assembler definiton (Z80) +//----------------------------------------------------------------------- +static const asm_t a80z = +{ + AS_COLON | ASD_DECF1 | ASH_HEXF2 | AS_UNEQU, + UAS_NPAIR | UAS_UNDOC | UAS_FUNNY, + "A80 by ANTA electronics", + 0, + NULL, + "adr", + NULL, + + ";", // comment string + '\'', // string delimiter + '\0', // char delimiter (no char consts) + "'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + NULL, // uninited arrays + "equ", + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// Avocet Macro Preprocessor v1.0 by Avocet Systems, Inc. +//----------------------------------------------------------------------- +static const char *const avocet_headers[] = +{ + "; $chip(HD64180) ; please uncomment and place as first line for HD64180", + " defseg allseg, absolute ; make avocet think that we have", + " seg allseg ; one big absolute segment", + NULL +}; + +static const asm_t avocet = +{ + AS_NHIAS, + 0, + "Avocet Macro Preprocessor v1.0 by Avocet Systems, Inc.", + 0, + avocet_headers, + "org", + "end", + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "\"'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//----------------------------------------------------------------------- +// ASxxxx by Alan R. Baldwin +//----------------------------------------------------------------------- +static const char *const asxxxx_headers[] = +{ + " .area idaseg (ABS)", + " .hd64 ; this is needed only for HD64180", + NULL +}; + +static const asm_t asxxxx = +{ + AS_NHIAS | AS_COLON | AS_NCHRE | AS_N2CHR | AS_1TEXT | ASH_HEXF3, + UAS_MKIMM | UAS_MKOFF | UAS_CNDUP, + "ASxxxx by Alan R. Baldwin v1.5", + 0, + asxxxx_headers, + ".org", + NULL, + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "'", // special symbols in char and string constants + + ".ascii", // ascii string directive + ".db", // byte directive + ".dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + ".ds %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//----------------------------------------------------------------------- +// X-M-80 by Leo Sandy, (8080) +//----------------------------------------------------------------------- +static const char *const xm80_headers[] = +{ + ".8080", + NULL +}; + +static const asm_t xm80 = +{ + AS_COLON | AS_NHIAS, + UAS_CSEGS, + "X-M-80 by Leo Sandy", + 0, + xm80_headers, + "org", + "end", + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// X-M-80 by Leo Sandy, (Z80) +//----------------------------------------------------------------------- +static const char *const xm80z_headers[] = +{ + ".Z80", + NULL +}; + +static const asm_t xm80z = +{ + AS_COLON | AS_NHIAS, + UAS_CSEGS, + "X-M-80 by Leo Sandy", + 0, + xm80z_headers, + "org", + "end", + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "'", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + NULL, // equ + NULL, // seg prefix + NULL, // curip + NULL, // func_header + NULL, // func_footer + NULL, // public + NULL, // weak + NULL, // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + NULL, // mod + NULL, // and + NULL, // or + NULL, // xor + NULL, // not + NULL, // shl + NULL, // shr + NULL, // sizeof +}; + + +//----------------------------------------------------------------------- +// Zilog Macro Assembler (ZMASM) +//----------------------------------------------------------------------- +static const asm_t zmasm = +{ + ASH_HEXF0 // 34h + |ASD_DECF0 // 34 + |ASO_OCTF0 // 123o + |ASB_BINF0 // 010101b + |AS_N2CHR // can't have 2 byte char consts + |AS_COLON // ':' after all labels + |AS_ASCIIC // ascii directive accepts C-like strings + |AS_ONEDUP, // one dup directive per line + UAS_ZMASM, + "Zilog Macro Assembler", + 0, + NULL, // headers + "org", + "end", + + ";", // comment string + '\'', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + ".ascii", // ascii string directive + "db", // byte directive + "dw", // word directive + "dl", // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + ".float", // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + "#h [ #d ], #v", // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // equ + NULL, // seg prefix + "$", // curip + NULL, // func_header + NULL, // func_footer + "public", // public + NULL, // weak + "extern", // extrn + NULL, // comm + NULL, // get_type_name + "align", // align + ' ', ' ', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +//----------------------------------------------------------------------- +// RGBAsm v1.11 (part of ASMotor 1.10) +//----------------------------------------------------------------------- +static const asm_t rgbasm = +{ + ASH_HEXF4 // $34 + |ASD_DECF0 // 34 + |ASO_OCTF3 // @123 (in fact this should be &123) + |ASB_BINF2 // %010101 + |AS_N2CHR // can't have 2 byte char consts + |AS_COLON, // ':' after all labels + UAS_GBASM, + "RGBAsm (part of ASMotor)", + 0, + NULL, // headers + "org", + NULL, // end + + ";", // comment string + '"', // string delimiter + '\'', // char delimiter + "'\"", // special symbols in char and string constants + + "db", // ascii string directive + "db", // byte directive + "dw", // word directive + NULL, // dword (4 bytes) + NULL, // qword (8 bytes) + NULL, // oword (16 bytes) + NULL, // float (4 bytes) + NULL, // double (8 bytes) + NULL, // tbyte (10/12 bytes) + NULL, // packed decimal real + NULL, // arrays (#h,#d,#v,#s(...) + "ds %s", // uninited arrays + "equ", // equ + NULL, // seg prefix + "@", // curip + NULL, // func_header + NULL, // func_footer + "export", // public + NULL, // weak + "import", // extrn + NULL, // comm + NULL, // get_type_name + NULL, // align + ' ', ' ', // lbrace, rbrace + "%", // mod + "&", // and + "|", // or + "^", // xor + "~", // not + "<<", // shl + ">>", // shr + NULL, // sizeof +}; + +static const asm_t *const i8085asms[] = { &tasm, &xm80, &pseudosam, &cross16, &a80, NULL }; +static const asm_t *const Z80asms[] = { &zmasm, &tasmz80, &xm80z, &pseudosam, &cross16z80, &a80z, &avocet, &asxxxx, NULL }; +static const asm_t *const HD64180asms[] = { &zmasm, &tasmz80, &avocet, &asxxxx, NULL }; +static const asm_t *const GBasms[] = { &rgbasm, NULL }; + +//------------------------------------------------------------------ +const char *z80_t::find_ioport(uval_t port) +{ + const ioport_t *p = ::find_ioport(ioh.ports, port); + return p ? p->name.c_str() : NULL; +} + +//------------------------------------------------------------------ +const char *z80_t::find_ioport_bit(int port, int bit) +{ + const ioport_bit_t *p = ::find_ioport_bit(ioh.ports, port, bit); + return p ? p->name.c_str() : NULL; +} + +//------------------------------------------------------------------ +void z80_t::choose_device(int respinfo) +{ + char cfgfile[QMAXFILE]; + ioh.get_cfg_filename(cfgfile, sizeof(cfgfile)); + iohandler_t::parse_area_line0_t cb(ioh); + if ( choose_ioport_device2(&ioh.device, cfgfile, &cb) ) + ioh.set_device_name(ioh.device.c_str(), respinfo); +} + +//------------------------------------------------------------------ +const char *z80_t::set_idp_options( + const char *keyword, + int /*value_type*/, + const void * /*value*/, + bool /*idb_loaded*/) +{ + if ( keyword != NULL ) + return IDPOPT_BADKEY; + choose_device(IORESP_NONE); + return IDPOPT_OK; +} + +//----------------------------------------------------------------------- +static bool idaapi can_have_type(const op_t &x) // returns 1 - operand can have +{ + switch ( x.type ) + { + case o_void: // No Operand + case o_reg: // General Register + case o_phrase: // Base Reg + Index Reg + case o_cond: // FPP register + return 0; + } + return 1; +} + + +//---------------------------------------------------------------------- +static char const features[] = { _PT_8085, _PT_Z80, _PT_64180, _PT_Z180, _PT_Z380, _PT_GB }; + +//---------------------------------------------------------------------- +void z80_t::set_cpu(int np) +{ + pflag = features[np]; + ph.assemblers = i8085asms; + if ( isZ80() ) + ph.assemblers = Z80asms; + if ( is64180() ) + ph.assemblers = HD64180asms; + if ( isGB() ) + ph.assemblers = GBasms; +} + +//---------------------------------------------------------------------- +void z80_t::load_from_idb() +{ + set_cpu(ph.get_proc_index()); + ioh.restore_device(); +} + +//---------------------------------------------------------------------- +// This old-style callback only returns the processor module object. +static ssize_t idaapi notify(void *, int msgid, va_list) +{ + if ( msgid == processor_t::ev_get_procmod ) + return size_t(SET_MODULE_DATA(z80_t)); + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi z80_t::on_event(ssize_t msgid, va_list va) +{ + int _code = 0; + switch ( msgid ) + { + case processor_t::ev_init: + helper.create(PROCMOD_NODE_NAME); + break; + + case processor_t::ev_term: + clr_module_data(data_id); + break; + + case processor_t::ev_newprc: + { + int np = va_arg(va, int); + // bool keep_cfg = va_argi(va, bool); + set_cpu(np); + } + break; + + case processor_t::ev_ending_undo: + case processor_t::ev_oldfile: + load_from_idb(); + break; + + case processor_t::ev_newfile: + if ( inf_get_procname() == "z180" ) + choose_device(IORESP_AREA); + break; + + case processor_t::ev_out_header: + { + outctx_t *ctx = va_arg(va, outctx_t *); + i5_header(*ctx); + return 1; + } + + case processor_t::ev_out_footer: + { + outctx_t *ctx = va_arg(va, outctx_t *); + i5_footer(*ctx); + return 1; + } + + case processor_t::ev_out_segstart: + { + outctx_t *ctx = va_arg(va, outctx_t *); + segment_t *seg = va_arg(va, segment_t *); + i5_segstart(*ctx, seg); + return 1; + } + + case processor_t::ev_ana_insn: + { + insn_t *out = va_arg(va, insn_t *); + return i5_ana(out); + } + + case processor_t::ev_emu_insn: + { + const insn_t *insn = va_arg(va, const insn_t *); + return i5_emu(*insn) ? 1 : -1; + } + + case processor_t::ev_out_insn: + { + outctx_t *ctx = va_arg(va, outctx_t *); + out_insn(*ctx); + return 1; + } + + case processor_t::ev_out_operand: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const op_t *op = va_arg(va, const op_t *); + return out_opnd(*ctx, *op) ? 1 : -1; + } + + case processor_t::ev_can_have_type: + { + const op_t *op = va_arg(va, const op_t *); + return can_have_type(*op) ? 1 : -1; + } + + case processor_t::ev_set_idp_options: + { + const char *keyword = va_arg(va, const char *); + int value_type = va_arg(va, int); + const char *value = va_arg(va, const char *); + const char **errmsg = va_arg(va, const char **); + bool idb_loaded = va_argi(va, bool); + const char *ret = set_idp_options(keyword, value_type, value, idb_loaded); + if ( ret == IDPOPT_OK ) + return 1; + if ( errmsg != NULL ) + *errmsg = ret; + return -1; + } + + + // START OF DEBUGGER CALLBACKS + case processor_t::ev_next_exec_insn: + { + ea_t *target = va_arg(va, ea_t *); + ea_t ea = va_arg(va, ea_t); + int tid = va_arg(va, int); + getreg_t *getreg = va_arg(va, getreg_t *); + const regval_t *regvalues = va_arg(va, const regval_t *); + qnotused(tid); + *target = next_exec_insn(ea, getreg, regvalues); + return 1; + } + + case processor_t::ev_calc_step_over: + { + ea_t *target = va_arg(va, ea_t *); + ea_t ip = va_arg(va, ea_t); + *target = calc_step_over(ip); + return 1; + } + + case processor_t::ev_get_idd_opinfo: + { + idd_opinfo_t *opinf = va_arg(va, idd_opinfo_t *); + ea_t ea = va_arg(va, ea_t); + int n = va_arg(va, int); + int thread_id = va_arg(va, int); + getreg_t *getreg = va_arg(va, getreg_t *); + const regval_t *regvalues = va_arg(va, const regval_t *); + qnotused(thread_id); + return get_operand_info(opinf, ea, n, getreg, regvalues) ? 1 : 0; + } + + case processor_t::ev_get_reg_info: + { + const char **main_regname = va_arg(va, const char **); + bitrange_t *bitrange = va_arg(va, bitrange_t *); + const char *regname = va_arg(va, const char *); + return get_reg_info(main_regname, bitrange, regname) ? 1 : -1; + } + // END OF DEBUGGER CALLBACKS + + default: + break; + } + return _code; +} + +//----------------------------------------------------------------------- +#define FAMILY "Z80 processors:" + +static const char *const shnames[] = +{ + "8085", + "z80", + "64180", + "z180", + "z380", + "gb", + NULL +}; + +static const char *const lnames[] = +{ + FAMILY"Intel 8085", + "Zilog 80", + "Hitachi HD64180", + "Zilog Z180", + "Zilog Z380", + "GameBoy", + NULL +}; + +//----------------------------------------------------------------------- +static const uchar retcode_1[] = { 0xC9 }; +static const uchar retcode_2[] = { 0xED, 0x45 }; +static const uchar retcode_3[] = { 0xED, 0x4D }; + +static const bytes_t retcodes[] = +{ + { sizeof(retcode_1), retcode_1 }, + { sizeof(retcode_2), retcode_2 }, + { sizeof(retcode_3), retcode_3 }, + { 0, NULL } +}; + +//----------------------------------------------------------------------- +// Intel 8080/8085 processor definition +//----------------------------------------------------------------------- +processor_t LPH = +{ + IDP_INTERFACE_VERSION, // version + PLFM_Z80, // id + // flag + PRN_HEX + | PR_SEGTRANS, + // flag2 + PR2_IDP_OPTS, // the module has processor-specific configuration options + 8, // 8 bits in a byte for code segments + 8, // 8 bits in a byte for other segments + + shnames, + lnames, + + i8085asms, + + notify, + + RegNames, + R_vds+1, // number of registers + + R_vcs,R_vds, // first, last + 0, // size of a segment register + R_vcs,R_vds, // CS,DS + + NULL, // No known code start sequences + retcodes, // 'Return' instruction codes + + 0,I5_last, + Instructions, // instruc + 0, // int tbyte_size; -- doesn't exist + { 0, 0, 0, 0 }, // char real_width[4]; + // number of symbols after decimal point + // 2byte float (0-does not exist) + // normal float + // normal double + // long double + I5_ret, // Icode of return instruction. It is ok to give any of possible return instructions +}; diff --git a/idasdk76/module/z80/z180.cfg b/idasdk76/module/z80/z180.cfg new file mode 100644 index 0000000..5c26c1a --- /dev/null +++ b/idasdk76/module/z80/z180.cfg @@ -0,0 +1,239 @@ +.Z80180 +; Enhanced Z80 Megacell +; http://www.zilog.com/products/partdetails.asp?id=Z80180 + + +; INPUT/ OUTPUT PORTS + +CNTLA0 0x0000 ASCI Channel Control Register A 0 +CNTLA0.MPE 7 Multi-Processor Mode Enable +CNTLA0.RE 6 Receiver Enable +CNTLA0.TE 5 Transmitter Enable +CNTLA0._RTS0 4 Request to Send Channel 0 +CNTLA0.MPBR_EFR 3 Multiprocessor Bit Receive/Error Flag Reset +CNTLA0.MOD2 2 ASCI Data Format Mode 2 +CNTLA0.MOD1 1 ASCI Data Format Mode 1 +CNTLA0.MOD0 0 ASCI Data Format Mode 0 + +CNTLA1 0x0001 ASCI Channel Control Register A 0 +CNTLA1.MPE 7 Multi-Processor Mode Enable +CNTLA1.RE 6 Receiver Enable +CNTLA1.TE 5 Transmitter Enable +CNTLA1._RTS0 4 Request to Send Channel 0 +CNTLA1.MPBR_EFR 3 Multiprocessor Bit Receive/Error Flag Reset +CNTLA1.MOD2 2 ASCI Data Format Mode 2 +CNTLA1.MOD1 1 ASCI Data Format Mode 1 +CNTLA1.MOD0 0 ASCI Data Format Mode 0 + +CNTLB0 0x0002 ASCI Channel Control Register B 0 +CNTLB0.MPBT 7 Multiprocessor Bit Transmit +CNTLB0.MP 6 Multiprocessor Mode +CNTLB0.__CTS_PS 5 Clear to Send/Prescale +CNTLB0.PEO 4 Parity Even Odd +CNTLB0.DR 3 Divide Ratio +CNTLB0.SS2 2 Source/Speed Select 2 +CNTLB0.SS1 1 Source/Speed Select 1 +CNTLB0.SS0 0 Source/Speed Select 0 + +CNTLB1 0x0003 ASCI Channel Control Register B 1 +CNTLB1.MPBT 7 Multiprocessor Bit Transmit +CNTLB1.MP 6 Multiprocessor Mode +CNTLB1.__CTS_PS 5 Clear to Send/Prescale +CNTLB1.PEO 4 Parity Even Odd +CNTLB1.DR 3 Divide Ratio +CNTLB1.SS2 2 Source/Speed Select 2 +CNTLB1.SS1 1 Source/Speed Select 1 +CNTLB1.SS0 0 Source/Speed Select 0 + +STAT0 0x0004 ASCI Status Register 0 +STAT0.RDRF 7 Receive Data Register Full +STAT0.OVRN 6 Overrun Error +STAT0.PE 5 Parity Error +STAT0.FE 4 Framing Error +STAT0.REI 3 Receive Interrupt Enable +STAT0._DCD0 2 Data Carrier Detect +STAT0.TDRE 1 Transmit Data Register Empty +STAT0.TIE 0 Transmit Interrupt Enable + +STAT1 0x0005 ASCI Status Register 1 +STAT1.RDRF 7 Receive Data Register Full +STAT1.OVRN 6 Overrun Error +STAT1.PE 5 Parity Error +STAT1.FE 4 Framing Error +STAT1.REI 3 Receive Interrupt Enable +STAT1.TDRE 1 Transmit Data Register Empty +STAT1.TIE 0 Transmit Interrupt Enable + +TDR0 0x0006 +TDR1 0x0007 +RDR0 0x0008 +RDR1 0x0009 + +CNTR 0x000A CSIO Control/Status Register +CNTR.EF 7 End Flag +CNTR.EIE 6 End Interrupt Enable +CNTR.RE 5 Receive Enable +CNTR.TE 4 Transmit Enable +CNTR.SS2 2 Speed Select 2 +CNTR.SS1 1 Speed Select 1 +CNTR.SS0 0 Speed Select 0 + +TRDR 0x000B CSIO Transmit/Receive Data Register +TMDR0L 0x000C Timer Data Register Channel 0L +TMDR0H 0x000D Timer Data Register Channel 0H +RLDR0L 0x000E Timer Reload Register 0L +RLDR0H 0x000F Timer Reload Register 0H + +TCR 0x0010 Timer Control Register +TCR.TIF1 7 Timer Interrupt Flag 1 +TCR.TIF0 6 Timer Interrupt Flag 0 +TCR.TIE1 5 Timer Interrupt Enable 1 +TCR.TIE0 4 Timer Interrupt Enable 0 +TCR.TOC1 3 Timer Output Control +TCR.TOC0 2 Timer Output Control +TCR.TDE1 1 +TCR.TDE0 0 + +TMDR1L 0x0014 Timer Data Register Channel 1L +TMDR1H 0x0015 Timer Data Register Channel 1H +RLDR1L 0x0016 Timer Reload Register 1L +RLDR1H 0x0017 Timer Reload Register 1H +FRC 0x0018 Free Running Counter +SAR0L 0x0020 DMA Source Address Register Channel 0L +SAR0H 0x0021 DMA Source Address Register Channel 0H +SAR0B 0x0022 DMA Source Address Register Channel 0B +DAR0L 0x0023 DMA Destination Address Register Channel 0L +DAR0H 0x0024 DMA Destination Address Register Channel 0H +DAR0B 0x0025 DMA Destination Address Register Channel 0B +BCR0L 0x0026 DMA Byte Count Register Channel 0L +BCR0H 0x0027 DMA Byte Count Register Channel 0H +MAR1L 0x0028 DMA Memory Address Register, Channel 1L +MAR1H 0x0029 DMA Memory Address Register, Channel 1H +MAR1B 0x002A DMA Memory Address Register, Channel 1B +IAR1L 0x002B DMA I/O Address Register Channel 1L +IAR1H 0x002C DMA I/O Address Register Channel 1H +BCR1L 0x002E DMA Byte Count Register Channel 1L +BCR1H 0x002F DMA Byte Count Register Channel 1H + +DSTAT 0x0030 DMA Status Register +DSTAT.DE1 7 DE1: DMA Enable Channel 1 +DSTAT.DE0 6 DE0: DMA Enable Channel 0 +DSTAT.DWE1 5 DE1 Bit WRITE Enable +DSTAT.DWE0 4 DE0 Bit WRITE Enable +DSTAT.DIE1 3 DMA Interrupt Enable Channel +DSTAT.DIE0 2 DMA Interrupt Enable Channel +DSTAT.DME 0 DMA Main Enable + +DMODE 0x0031 DMA Mode Register +DMODE.DM1 5 Destination Mode Channel 0 +DMODE.DM0 4 Destination Mode Channel 0 +DMODE.SM1 3 Source Mode Channel 0 +DMODE.SM0 2 Source Mode Channel 0 +DMODE.MMOD 1 Memory Mode Channel 0 + +DCNTL 0x0032 DMA/WAIT Control Register +DCNTL.MWI1 7 Memory Wait Insertion +DCNTL.MWI0 6 Memory Wait Insertion +DCNTL.IWI1 5 I/O Wait Insertion +DCNTL.IWI0 4 I/O Wait Insertion +DCNTL.DMS1 3 DMA Request Sense +DCNTL.DMS0 2 DMA Request Sense +DCNTL.DIM1 1 DMA Channel 1 I/O and Memory Mode +DCNTL.DIM0 0 DMA Channel 1 I/O and Memory Mode + +IL 0x0033 Interrupt Vector Low Register +IL.IL7 7 +IL.IL6 6 +IL.IL5 5 + +ITC 0x0034 Int/TRAP Control Register +ITC.TRAP 7 +ITC.UFO 6 Undefined Fetch Object +ITC.ITE2 2 Interrupt Enable 2 +ITC.ITE1 1 Interrupt Enable 1 +ITC.ITE0 0 Interrupt Enable 0 + +RCR 0x0036 Refresh Control Register +RCR.REFE 7 Refresh Enable +RCR.REFW 6 Refresh Wait +RCR.CYC1 1 Cycle Interval +RCR.CYC0 0 Cycle Interval + +CBR 0x0038 MMU Common Base Register (CBR) +CBR.CB7 7 +CBR.CB6 6 +CBR.CB5 5 +CBR.CB4 4 +CBR.CB3 3 +CBR.CB2 2 +CBR.CB1 1 +CBR.CB0 0 + +BBR 0x0039 MMU Bank Base Register (BBR) +BBR.BB7 7 +BBR.BB6 6 +BBR.BB5 5 +BBR.BB4 4 +BBR.BB3 3 +BBR.BB2 2 +BBR.BB1 1 +BBR.BB0 0 + +CBAR 0x003A MMU Common/Bank Area Register (CBAR) +CBAR.CA3 7 +CBAR.CA2 6 +CBAR.CA1 5 +CBAR.CA0 4 +CBAR.BA3 3 +CBAR.BA2 2 +CBAR.BA1 1 +CBAR.BA0 0 + +OMCR 0x003E Operation Mode Control Register +OMCR.MIE 7 +OMCR._MITE 6 +OMCR._IOC 5 + +ICR 0x003F I/O Control Register (ICR) +ICR.IOA7 7 +ICR.IOA6 6 +ICR.IOSTP 5 + + + +.Z80181 +; Smart Access Controller + +.Z80182 +; ZiLOG Intelligent Peripheral (ZIPT) + +.Z80189 + +.Z8S180 +; + Parallel I/O + +.Z80195 +; Smart Peripheral Controller (ROMless) + +.Z80L183 +; Mixed-Signal Z183 Internet Processor + +.Z80S183 +; Mixed-Signal Z183 Internet Processor + +.Z8L180 +; Enhanced Z80 Megacell + +.Z8L180 +; Low-Voltage Version (3.3 V) + +.Z8L182 +; ZiLOG Intelligent Peripheral (ZIPT) - Low Voltage Version + +.Z8S180 +; Enhanced Z80 Megacell + +.Z8L180 +; Low-Voltage Version (3.3 V) + + diff --git a/idasdk75/objdir.mak b/idasdk76/objdir.mak similarity index 100% rename from idasdk75/objdir.mak rename to idasdk76/objdir.mak diff --git a/idasdk75/pdb/x64_win_vc_32/readme.txt b/idasdk76/pdb/x64_win_vc_32/readme.txt similarity index 100% rename from idasdk75/pdb/x64_win_vc_32/readme.txt rename to idasdk76/pdb/x64_win_vc_32/readme.txt diff --git a/idasdk75/pdb/x64_win_vc_64/readme.txt b/idasdk76/pdb/x64_win_vc_64/readme.txt similarity index 100% rename from idasdk75/pdb/x64_win_vc_64/readme.txt rename to idasdk76/pdb/x64_win_vc_64/readme.txt diff --git a/idasdk75/pdb/x86_win_vc_32/readme.txt b/idasdk76/pdb/x86_win_vc_32/readme.txt similarity index 100% rename from idasdk75/pdb/x86_win_vc_32/readme.txt rename to idasdk76/pdb/x86_win_vc_32/readme.txt diff --git a/idasdk75/pdb/x86_win_vc_64/readme.txt b/idasdk76/pdb/x86_win_vc_64/readme.txt similarity index 100% rename from idasdk75/pdb/x86_win_vc_64/readme.txt rename to idasdk76/pdb/x86_win_vc_64/readme.txt diff --git a/idasdk75/plugins/callee/callee.cpp b/idasdk76/plugins/callee/callee.cpp similarity index 100% rename from idasdk75/plugins/callee/callee.cpp rename to idasdk76/plugins/callee/callee.cpp diff --git a/idasdk76/plugins/callee/makefile b/idasdk76/plugins/callee/makefile new file mode 100644 index 0000000..680f745 --- /dev/null +++ b/idasdk76/plugins/callee/makefile @@ -0,0 +1,20 @@ +PROC=callee + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)callee$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)dbg.hpp $(I)fixup.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h \ + $(I)problems.hpp $(I)range.hpp $(I)segment.hpp \ + $(I)segregs.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + \ + ../../module/arm/../idaidp.hpp \ + \ + \ + ../../module/arm/arm.hpp \ + callee.cpp diff --git a/idasdk76/plugins/callgraph/callgraph.cpp b/idasdk76/plugins/callgraph/callgraph.cpp new file mode 100644 index 0000000..b2d772c --- /dev/null +++ b/idasdk76/plugins/callgraph/callgraph.cpp @@ -0,0 +1,1457 @@ +#include "callgraph.h" + + +int data_id; + +static bool get_graph_title(ea_t ea, qstring *out); + +//------------------------------------------------------------------------- +#define ACTION_NAME "callgraph:ShowCallgraph" +#define ACTION_LABEL "Function call graph" + +plugin_ctx_t::plugin_ctx_t() + : main_action(ACTION_DESC_LITERAL_PLUGMOD( + ACTION_NAME, + ACTION_LABEL, + &show_callgraph_ah, + this, + "Ctrl+Shift+B", + nullptr, -1)) +{ + ::hook_event_listener(HT_IDP, &idp_merge_listener, this); + ::hook_event_listener(HT_VIEW, &view_listener, this); +} + +bool plugin_ctx_t::register_main_action() +{ + return register_action(main_action) + && attach_action_to_menu("View/Open subviews/Function calls", + ACTION_NAME, SETMENU_APP); +} + +plugin_ctx_t::~plugin_ctx_t() +{ + clr_module_data(data_id); +} + +//-------------------------------------------------------------------------- +int idaapi show_callgraph_ah_t::activate(action_activation_ctx_t *) +{ + ctx.run(0); + return 0; +} + +//-------------------------------------------------------------------------- +// Checks if a function is visited already +// If it is visited then true is returned and nid contains the node ID +bool callgraph_t::visited(ea_t func_ea, int *nid) +{ + ea_int_map_t::const_iterator it = ea2node.find(func_ea); + if ( it != ea2node.end() ) + { + if ( nid != nullptr ) + *nid = it->second; + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +void callgraph_t::add_fathers( + func_t * /*func*/, + ea_t func_start, + int id, + funcs_walk_options_t *opt, + int level) +{ + if ( level >= (opt->callers_recurse_limit+2) ) + { + return; + } + + //msg("Level %d, node 0x%08x\n", level, func_start); + xrefblk_t xb_to; + + for ( bool xb_to_ok = xb_to.first_to(func_start, XREF_FAR); + xb_to_ok && xb_to.iscode; + xb_to_ok = xb_to.next_to() ) + { + func_t *f_from = get_func(xb_to.from); + if ( f_from == nullptr ) + continue; + + int idto = add(f_from->start_ea); + //msg("Adding XREF to 1st node %d\n", idto); + create_edge(idto, id); + + add_fathers(f_from, f_from->start_ea, idto, opt, level+1); + } +} + +//-------------------------------------------------------------------------- +int callgraph_t::walk_func( + eavec_t *hide_nodes, + func_t *func, + funcs_walk_options_t *opt, + int level) +{ + // add a node for this function + ea_t func_start = func->start_ea; + + int id = add(func_start); + + // Add the callers of the 1st function + if ( level == 2 ) + { + add_fathers(func, func_start, id, opt, 2); + } + + int total = 0; + func_item_iterator_t fii; + + for ( bool fi_ok=fii.set(func); fi_ok; fi_ok=fii.next_code() ) + { + xrefblk_t xb; + for ( bool xb_ok = xb.first_from(fii.current(), XREF_FAR); + xb_ok && xb.iscode; + xb_ok = xb.next_from() ) + { + bool is_func_lib; + ea_t ea; + + func_t *f = get_func(xb.to); + if ( f == nullptr ) + { + ea = xb.to; + is_func_lib = true; + + if ( (opt->flags & FWO_SKIPLIB) != 0 ) + continue; + } + else + { + ea = f->start_ea; + is_func_lib = false; + } + + eavec_t::iterator hide_nodes_it; + + // Any node to hide? + if ( !hide_nodes->empty() ) + { + hide_nodes_it = std::find(hide_nodes->begin(), hide_nodes->end(), ea); + if ( *hide_nodes_it == ea ) + { + //msg("Hiding node 0x%08x\n", *hide_nodes_it); + continue; + } + } + + int id2 = -1; + if ( !visited(ea, &id2) ) + { + if ( func_contains(func, xb.to) ) + continue; + + bool skip = false; + + if ( opt != nullptr ) + { + skip = is_func_lib && (opt->flags & FWO_SKIPLIB) != 0 // skip lib funcs? + || ((opt->flags & FWO_CALLEE_RECURSE_UNLIM) == 0 // max recursion is off, and limit is reached? + && level > opt->callees_recurse_limit); + } + + // More nodes in this level than the maximum specified? + if ( total++ >= ctx.fg_opts.max_nodes ) + { + id2 = add((ea_t)VERTEX_HIDDEN_NODES); + create_edge(id, id2); + break; + } + + if ( skip ) + id2 = add(ea); + else if ( !is_func_lib ) + id2 = walk_func(hide_nodes, f, opt, level+1); + else if ( (opt->flags & FWO_SKIPLIB) == 0 ) + id2 = add(ea); + + if ( id2 != -1 ) + create_edge(id, id2); + } + //msg("Adding edge between %d and %d\n", id, id2); + } + } + return id; +} + +//-------------------------------------------------------------------------- +int callgraph_t::find_first(const char *text) +{ + if ( text == nullptr || text[0] == '\0' ) + return -1; + + qstrncpy(cur_text, text, sizeof(cur_text)); + cur_node = 0; + return find_next(); +} + +//-------------------------------------------------------------------------- +int callgraph_t::find_next() +{ + for ( int i = cur_node; i < node_count; i++ ) + { + const char *s = get_name(i); + if ( stristr(s, cur_text) != nullptr ) + { + cur_node = i + 1; + return i; + } + } + // reset search + cur_node = 0; + // nothing is found + return -1; +} + +//-------------------------------------------------------------------------- +void callgraph_t::create_edge(int id1, int id2) +{ + edges.push_back(edge_t(id1, id2)); +} + +//-------------------------------------------------------------------------- +void callgraph_t::reset() +{ + node_count = 0; + cur_node = 0; + cur_text[0] = '\0'; + ea2node.clear(); + node2ea.clear(); + cached_funcs.clear(); + edges.clear(); +} + +//-------------------------------------------------------------------------- +ea_t callgraph_t::get_addr(int nid) const +{ + int_ea_map_t::const_iterator it = node2ea.find(nid); + return it == node2ea.end() ? BADADDR : it->second; +} + +//-------------------------------------------------------------------------- +// Given an address, this function first returns ASCII string if found +// otherwise it returns a UNICODE string +// FIXME: not comprehensive, better follow the settings in strings options +size_t get_string(ea_t ea, qstring *out) +{ + const char *encodings[2] = + { + encoding_from_strtype(STRTYPE_C), + inf_is_be() ? ENC_UTF16BE : ENC_UTF16LE + }; + for ( int i = 0; i < qnumber(encodings); i++ ) + { + int enc_idx = add_encoding(encodings[i]); + uint32 strtype = STRTYPE_C | (enc_idx << 24); + size_t len = get_max_strlit_length(ea, strtype); + if ( len > 4 && get_strlit_contents(out, ea, len, strtype) > 0 ) + break; + out->qclear(); + } + return out->size(); +} + +//-------------------------------------------------------------------------- +bool get_strings(ea_t ea, qstring *out) +{ + qstring tmp; + + func_t *func = get_func(ea); + func_item_iterator_t fii; + for ( bool fi_ok=fii.set(func); fi_ok; fi_ok=fii.next_code() ) + { + xrefblk_t xb; + for ( bool xb_ok = xb.first_from(fii.current(), XREF_DATA); + xb_ok; + xb_ok = xb.next_from() ) + { + if ( get_string(xb.to, &tmp) > 0 ) + *out += tmp + "\n"; + } + } + + if ( out->size() > 1 ) + out->insert("\n\nStrings:\n"); + + return !out->empty(); +} + +//-------------------------------------------------------------------------- +callgraph_t::funcinfo_t *callgraph_t::get_info(int nid) +{ + funcinfo_t *ret = nullptr; + + do + { + // returned cached name + int_funcinfo_map_t::iterator it = cached_funcs.find(nid); + + if ( it != cached_funcs.end() ) + { + ret = &it->second; + break; + } + + // node does not exist? + int_ea_map_t::const_iterator it_ea = node2ea.find(nid); + if ( it_ea == node2ea.end() ) + break; + + funcinfo_t fi; + + qstring buf; + if ( ::get_name(&buf, it_ea->second) <= 0 ) + { + /* + ** NOTE: With patched databases it may fail for a reason unknown (ATM). + ** To test it, open an Objective-C app and patch it with the following + ** script: https://github.com/zynamics/objc-helper-plugin-ida + */ + if ( (int32)it_ea->second == VERTEX_HIDDEN_NODES ) + { + fi.name = "More nodes hidden..."; + } + else + { + msg("%a: Invalid address\n", it_ea->second); + fi.name = "?"; + } + } + else + { + qstring outbuf = buf; + qstring demangled; + if ( demangle_name(&demangled, buf.begin(), MNG_SHORT_FORM) > 0 ) + { + outbuf.append("\n"); + outbuf.append(demangled); + } + + // Assign the name + fi.name = outbuf; + + // Add the strings reference if set + qstring strings; + if ( (ctx.fg_opts.flags & FWO_SHOWSTRING) != 0 && get_strings(it_ea->second, &strings) ) + fi.strings = strings; + } + + // XXX: FIXME: UGLY HACK + // Use a special color for the selected node + if ( nid == 0 ) + { + fi.color = 0x44FF55; + } + else + { + // Is it an imported function? + segment_t *seg = getseg(it_ea->second); + if ( seg != nullptr && seg->type == SEG_XTRN ) + { + fi.color = 0xf000f0; + } + else + { + // XXX: FIXME Horrible... + func_t *f = get_func(it_ea->second); + if ( f != nullptr + && ((f->flags & FUNC_LIB) != 0 || buf[0] == '.') ) + { + fi.color = 0xfff000; + } + else + { + fi.color = calc_bg_color(it_ea->second); + } + } + } + + fi.ea = it_ea->second; + + it = cached_funcs.insert(cached_funcs.end(), std::make_pair(nid, fi)); //-V783 Dereferencing of the invalid iterator + ret = &it->second; + } while ( false ); + + return ret; +} + +//-------------------------------------------------------------------------- +const char *callgraph_t::get_name(int nid) +{ + funcinfo_t *fi = get_info(nid); + if ( fi == nullptr ) + return "?"; + else + return fi->name.c_str(); +} + +//-------------------------------------------------------------------------- +int callgraph_t::add(ea_t func_ea) +{ + ea_int_map_t::const_iterator it = ea2node.find(func_ea); + if ( it != ea2node.end() ) + return it->second; + + ea2node[func_ea] = node_count; + node2ea[node_count] = func_ea; + return node_count++; +} + +//-------------------------------------------------------------------------- +callgraph_t::callgraph_t(plugin_ctx_t &_ctx) : ctx(_ctx) +{ + cur_text[0] = '\0'; +} + +//-------------------------------------------------------------------------- +void callgraph_t::clear_edges() +{ + edges.clear(); +} + +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +bool graph_info_t::find(plugin_ctx_t &ctx, ea_t ea, iterator *out) +{ + iterator end = ctx.instances.end(); + for ( iterator it = ctx.instances.begin(); it != end; ++it ) + { + if ( (*it)->func_ea == ea ) + { + if ( out != nullptr ) + *out = it; + return true; + } + } + return false; +} + +//-------------------------------------------------------------------------- +graph_info_t *graph_info_t::find(plugin_ctx_t &ctx, ea_t ea) +{ + iterator it; + return find(ctx, ea, &it) ? *it : nullptr; +} + +//-------------------------------------------------------------------------- +graph_info_t *graph_info_t::find(plugin_ctx_t &ctx, const char *_title) +{ + for ( auto &gi : ctx.instances ) + if ( gi->title == _title ) + return gi; + return nullptr; +} + +//------------------------------------------------------------------------- +graph_info_t *graph_info_t::find(plugin_ctx_t &ctx, const graph_viewer_t *v) +{ + for ( auto &gi : ctx.instances ) + if ( gi->gv == v ) + return gi; + return nullptr; +} + +//-------------------------------------------------------------------------- +graph_info_t *graph_info_t::create(plugin_ctx_t &ctx, ea_t ea) +{ + graph_info_t *r = find(ctx, ea); + + // not there? create it + if ( r == nullptr ) + { + // we need a function! + func_t *pfn = get_func(ea); + if ( pfn == nullptr ) + return nullptr; + + r = new graph_info_t(ctx); + get_graph_title(ea, &r->title); + r->func_ea = pfn->start_ea; + ctx.instances.push_back(r); + + r->install_hooks(); + } + return r; +} + +//-------------------------------------------------------------------------- +// Check if the user changed any of the functions in the current graph +static void check_func_changed(ea_t ea, graph_info_t &gi) +{ + ea_int_map_t::const_iterator it = gi.fg.ea2node.find(ea); + if ( it != gi.fg.ea2node.end() ) + { + // The center node has been changed, destroy the current callgraph + if ( it->second == 0 ) + close_widget(gi.widget, WCLS_SAVE); + else + // A function shown in the callgraph has been changed, refresh + // the callgraph + gi.refresh(); + } +} + +//-------------------------------------------------------------------------- +// We hook to IDP event to receive processor module notifications +ssize_t idaapi idb_gi_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case idb_event::func_added: + case idb_event::func_updated: + case idb_event::deleting_func: + case idb_event::set_func_start: + case idb_event::set_func_end: + { + func_t *pfn = va_arg(va, func_t *); + check_func_changed(pfn->start_ea, gi); + break; + } + } + + return 0; +} + +//-------------------------------------------------------------------------- +// We hook to IDP event to receive processor module notifications +ssize_t idaapi idp_gi_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case processor_t::ev_create_switch_xrefs: + case processor_t::ev_add_cref: + case processor_t::ev_del_cref: + { + ea_t ea = va_arg(va, ea_t); + check_func_changed(ea, gi); + } + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idp_merge_listener_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + } + return 0; +} + +//-------------------------------------------------------------------------- +void graph_info_t::install_hooks() +{ + hook_event_listener(HT_IDP, &idp_gi_listener, &ctx); + hook_event_listener(HT_IDB, &idb_gi_listener, &ctx); +} + +//-------------------------------------------------------------------------- +void graph_info_t::remove_hooks() +{ + unhook_event_listener(HT_IDP, &idp_gi_listener); + unhook_event_listener(HT_IDB, &idb_gi_listener); +} + +//-------------------------------------------------------------------------- +void graph_info_t::destroy_graph(plugin_ctx_t &ctx, graph_info_t *gi) +{ + iterator it; + if ( find(ctx, gi->func_ea, &it) ) + { + ctx.instances.erase(it); + gi->remove_hooks(); + delete gi; + } +} + +//-------------------------------------------------------------------------- +// Get a new title for the form to be opened +qstring plugin_ctx_t::gen_graph_title(ea_t ea) +{ + // We should succeed in getting the name + qstring func_name; + if ( get_func_name(&func_name, ea) > 0 ) + { + qstring tmp; + for ( int i=1; i < 255; i++ ) + { + tmp.sprnt("Call graph: %s (%d)", func_name.begin(), i); + if ( find_widget(tmp.c_str()) == nullptr ) + return tmp; + } + } + return qstring(); +} + +//-------------------------------------------------------------------------- +static bool get_graph_title(ea_t ea, qstring *out) +{ + // we should succeed in getting the name + qstring func_name; + if ( get_func_name(&func_name, ea) <= 0 ) + return false; + + out->sprnt("Call graph: %s", func_name.begin()); + return true; +} + +//-------------------------------------------------------------------------- +void graph_info_t::mark_for_refresh() +{ + refresh_needed = true; +} + +//-------------------------------------------------------------------------- +void graph_info_t::mark_as_refreshed() +{ + refresh_needed = false; +} + +//-------------------------------------------------------------------------- +void graph_info_t::refresh() +{ + mark_for_refresh(); + refresh_viewer(gv); +} + +//-------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------- +void idaapi callgraph_t::user_refresh( + void *ud, + int code, + va_list va, + int current_node) +{ + graph_info_t *gi = (graph_info_t *) ud; + callgraph_t *fg = &gi->fg; + qnotused(code); + qnotused(current_node); + if ( !gi->is_refresh_needed() ) + return; + + gi->mark_as_refreshed(); + fg->reset(); + + func_t *f = get_func(gi->func_ea); + if ( f == nullptr ) + { + msg("%a: Invalid function\n", gi->func_ea); + return; + } + + fg->walk_func(&gi->hide_nodes, f, &fg->ctx.fg_opts, 2); + + mutable_graph_t *mg = va_arg(va, mutable_graph_t *); + + // we have to resize + mg->reset(); + mg->resize(fg->count()); + + callgraph_t::edge_iterator it; + callgraph_t::edge_iterator end = fg->end_edges(); + + for ( it=fg->begin_edges(); it != end; ++it ) + mg->add_edge(it->id1, it->id2, nullptr); + + fg->clear_edges(); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi callgraph_t::gr_callback(void *ud, int code, va_list va) +{ + bool result = false; + graph_info_t *gi = (graph_info_t *) ud; + callgraph_t *fg = &gi->fg; + switch ( code ) + { + // a graph node has been double clicked + // in: graph_viewer_t *gv + // selection_item_t *current_item + // out: 0-ok, 1-ignore click + case grcode_dblclicked: + result = fg->center(gi); + break; + // refresh user-defined graph nodes and edges + // in: mutable_graph_t *g + // out: success + case grcode_user_refresh: + user_refresh(ud, code, va, -1); + result = true; + break; + + // retrieve text for user-defined graph node + // in: mutable_graph_t *g + // int node + // const char **result + // bgcolor_t *bg_color (maybe nullptr) + // out: must return 0, result must be filled + case grcode_user_text: + { + va_arg(va, mutable_graph_t *); + int node = va_arg(va, int); + const char **text = va_arg(va, const char **); + bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); + + callgraph_t::funcinfo_t *fi = fg->get_info(node); + result = fi != nullptr; + if ( result ) + { + qstring hint; + + hint = fi->name + fi->strings; + *text = hint.extract(); + //*text = fi->name.c_str(); + if ( bgcolor != nullptr ) + *bgcolor = fi->color; + } + break; + } + + // retrieve hint for the user-defined graph + // in: mutable_graph_t *g + // int mousenode + // int mouseedge_src + // int mouseedge_dst + // char **hint + // 'hint' must be allocated by qalloc() or qstrdup() + // out: 0-use default hint, 1-use proposed hint + case grcode_user_hint: + { + va_arg(va, mutable_graph_t *); + + int mousenode = va_argi(va, int); + int to = va_argi(va, int); + int from = va_argi(va, int); + char **hint = va_arg(va, char **); + + result = true; + + ea_t addr; + if ( mousenode != -1 && (addr = fg->get_addr(mousenode)) != BADADDR ) + { + qstrvec_t lines; + qstring all_lines; + + for ( int j=0; j < 16; j++ ) + { + int nl = generate_disassembly(&lines, nullptr, addr, 1024, false); + + for ( int i = 0; i < nl; i++ ) + { + all_lines.append(lines[i]); + all_lines.append('\n'); + } + addr = get_item_end(addr); + } + + *hint = all_lines.extract(); + } + else if ( mousenode == -1 ) + { + qstring line; + + if ( from != -1 && to != -1 ) + { + funcinfo_t *fifrom = fg->get_info(from); + funcinfo_t *fito = fg->get_info(to); + + // XXX: FIXME: Hack. It should be fixed hooking to del_func, etc... + if ( fifrom == nullptr || fito == nullptr ) + { + msg("Invalid function\n"); + result = false; + } + else + { + line.insert(fifrom->name.c_str()); + line.insert(" -> "); + line.insert(fito->name.c_str()); + + *hint = line.extract(); + } + } + } + break; + } + } + return (int)result; +} + +//-------------------------------------------------------------------------- +bool plugin_ctx_t::load_options() +{ + funcs_walk_options_t opt; + netnode n(PROCMOD_NODE_NAME); + if ( !exist(n) ) + return false; + + n.supval(1, &opt, sizeof(opt)); + + if ( opt.version != FWO_VERSION ) + return false; + + fg_opts = opt; + return true; +} + +//-------------------------------------------------------------------------- +void plugin_ctx_t::save_options() +{ + netnode n; + n.create(PROCMOD_NODE_NAME); + n.supset(1, &fg_opts, sizeof(fg_opts)); +} + +//-------------------------------------------------------------------------- +static int idaapi options_cb(int fid, form_actions_t &fa) +{ + ushort opt = 0; + + if ( fid == FIELD_ID_CHILDS || fid == CB_INIT ) + { + if ( !fa.get_checkbox_value(FIELD_ID_CHILDS, &opt) ) + INTERR(562); + + // Disable recursion level textbox + fa.enable_field(FIELD_ID_CHILDS_LEVEL, !opt);//(opt & FWO_CALLEE_RECURSE_UNLIM) == 0); + } + + if ( fid == FIELD_ID_FATHERS ) + { + if ( !fa.get_checkbox_value(FIELD_ID_FATHERS, &opt) ) + INTERR(563); + + if ( opt > MAX_CALLERS_LEVEL ) + { + info("Sorry, value is too big: %d", opt); + opt = MAX_CALLERS_LEVEL; + fa.set_checkbox_value(FIELD_ID_FATHERS, &opt); + } + } + + return 1; +} + +//-------------------------------------------------------------------------- +bool plugin_ctx_t::show_options() +{ + static const char opt_form[] = + "Call graph configuration\n" + "%/" + "<##Show ~s~tring references:C1>\n" + "<##Options##Hide ~l~ibrary functions:C2>\n" + "<##Max ~p~arents recursion level:D3:5:5::>\n" + "<##Unlimited children recursion:C4>5>\n" + "<##Max ~c~hildren recursion level:D6:5:5::>\n" + "<##~L~imit of nodes per level:D7:5:5::>\n" + ; + + ushort opt = fg_opts.flags; + + // When analyzing big functions, fg_opts.recurse_limit is too big + sval_t callers_limit = fg_opts.callers_recurse_limit; + sval_t callees_limit = fg_opts.callees_recurse_limit; + sval_t max_nodes = fg_opts.max_nodes; + + if ( !ask_form(opt_form, + options_cb, + &callers_limit, + &opt, + &callees_limit, + &max_nodes) ) + { + return false; + } + + if ( callees_limit <= 0 ) + { + callers_limit = 0; + opt |= FWO_CALLEE_RECURSE_UNLIM; + } + + fg_opts.flags = opt; + fg_opts.callees_recurse_limit = callees_limit; + fg_opts.callers_recurse_limit = callers_limit; + fg_opts.max_nodes = max_nodes; + + save_options(); + return true; +} + +//-------------------------------------------------------------------------- +static void jump_to_node(const graph_info_t *gi, const int nid) +{ + viewer_center_on(gi->gv, nid); + int x, y; + + // will return a place only when a node was previously selected + place_t *old_pl = get_custom_viewer_place(gi->gv, false, &x, &y); + if ( old_pl != nullptr ) + { + user_graph_place_t *new_pl = (user_graph_place_t *) old_pl->clone(); + new_pl->node = nid; + jumpto(gi->gv, new_pl, x, y); + ::qfree(new_pl); + } +} + +//-------------------------------------------------------------------------- +static int findfirst_node(callgraph_t *fg) +{ + static const char form[] = + "Enter search substring\n" + "\n" + " <#Search is not case sensitive#Function name:q:1000:50::>\n\n"; + + CASSERT(IS_QSTRING(fg->ctx.last_text)); + if ( !ask_form(form, &fg->ctx.last_text) ) + return -2; + + return fg->find_first(fg->ctx.last_text.c_str()); +} + +//-------------------------------------------------------------------------- +static void display_node_search_result(graph_info_t *gi, int nid) +{ + // search was cancelled + if ( nid == -2 ) + return; + + const char *txt = gi->fg.get_findtext(); + if ( nid == -1 ) + { + msg("No match for '%s'\n", txt); + } + else + { + msg("%a: matched '%s'\n", gi->fg.get_addr(nid), txt); + jump_to_node(gi, nid); + } +} + +//-------------------------------------------------------------------------- +bool callgraph_t::options(graph_info_t *gi) const +{ + if ( ctx.show_options() ) + gi->refresh(); + + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::refresh(graph_info_t *gi) const +{ + gi->refresh(); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::jumpxref(graph_info_t *gi) const +{ + int node; + ea_t addr; + + node = viewer_get_curnode(gi->gv); + if ( node != -1 ) + { + addr = gi->fg.get_addr(node); + ea_t xref = choose_xref(addr); + + if ( xref != 0 && xref != BADADDR ) + navigate(gi, xref); + + } + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::jumpaddr(graph_info_t *gi) const +{ + ea_t addr; + + if ( ask_addr(&addr, "Jump address") ) + { + func_t *pfn = get_func(addr); + if ( pfn == nullptr ) + { + warning("You have entered an invalid address"); + return false; + } + navigate(gi, addr); + } + + return true; +} + + +//-------------------------------------------------------------------------- +bool callgraph_t::jump(const graph_info_t *gi) const +{ + int node; + ea_t addr; + + node = viewer_get_curnode(gi->gv); + if ( node != -1 ) + { + addr = gi->fg.get_addr(node); + jumpto(addr); + } + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::back(graph_info_t *gi) const +{ + if ( gi->queue.empty() ) + close_widget(gi->widget, WCLS_SAVE); + else + go_back(gi); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::forward(graph_info_t *gi) const +{ + if ( !gi->forward_queue.empty() ) + go_forward(gi); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::center(graph_info_t *gi) const +{ + int node; + ea_t addr; + + node = viewer_get_curnode(gi->gv); + if ( node != -1 ) + { + addr = gi->fg.get_addr(node); + return navigate(gi, addr); + } + else + return false; + +} + +//------------------------------------------------------------------------- +// node chooser's helper +struct node_chooser_t : public chooser_t +{ +protected: + static const int widths_[]; + static const char *const header_[]; + +public: + // this chooser is modal + node_chooser_t(const char * title); +}; + +const int node_chooser_t::widths_[] = +{ + CHCOL_HEX | 32, // Function + 10, // Address +}; +const char *const node_chooser_t::header_[] = +{ + "Function", // 0 + "Address", // 1 +}; + +inline node_chooser_t::node_chooser_t(const char *title_) + : chooser_t(CH_MODAL | CH_KEEP, + qnumber(widths_), widths_, header_, + title_) +{ + CASSERT(qnumber(widths_) == qnumber(header_)); +} + + +//------------------------------------------------------------------------- +// modal call node chooser +struct call_node_chooser_t : public node_chooser_t +{ + const callgraph_t &fg; + + // this chooser is modal + call_node_chooser_t(const callgraph_t &fg_) + : node_chooser_t("Select function"), fg(fg_) {} + + virtual size_t idaapi get_count() const override { return fg.count(); } + virtual void idaapi get_row( + qstrvec_t *cols, + int *icon_, + chooser_item_attrs_t *attrs, + size_t n) const override; +}; + +void idaapi call_node_chooser_t::get_row( + qstrvec_t *cols_, + int *, + chooser_item_attrs_t *, + size_t n) const +{ + ea_t ea = fg.get_addr(n); + + qstrvec_t &cols = *cols_; + if ( get_name(&cols[0], ea) > 0 ) + cols[1].sprnt("%a", ea); + CASSERT(qnumber(header_) == 2); +} + +//-------------------------------------------------------------------------- +bool callgraph_t::select(const graph_info_t *gi) const +{ + call_node_chooser_t ch(gi->fg); + ssize_t n = ch.choose(chooser_base_t::NO_SELECTION); // why? + if ( n >= 0 ) + jump_to_node(gi, n); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::home(const graph_info_t *gi) const +{ + if ( count() > 1 ) + jump_to_node(gi, 0); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::searchfirst(graph_info_t *gi) +{ + display_node_search_result(gi, findfirst_node(this)); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::searchnext(graph_info_t *gi) +{ + display_node_search_result(gi, find_next()); + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::hidenode(graph_info_t *gi) const +{ + int node; + ea_t addr; + + node = viewer_get_curnode(gi->gv); + if ( node != -1 ) + { + addr = gi->fg.get_addr(node); + //msg("Should hide 0x%08x\n", addr); + gi->hide_nodes.push_back(addr); + gi->refresh(); + } + + return true; +} + +//------------------------------------------------------------------------- +// modal hidden node chooser +struct hidden_node_chooser_t : public node_chooser_t +{ + const eavec_t &hn; + + // this chooser is modal + hidden_node_chooser_t(const eavec_t &hn_) + : node_chooser_t("Show function"), hn(hn_) {} + + virtual size_t idaapi get_count() const override { return hn.size(); } + virtual void idaapi get_row( + qstrvec_t *cols, + int *icon_, + chooser_item_attrs_t *attrs, + size_t n) const override; +}; + +void idaapi hidden_node_chooser_t::get_row( + qstrvec_t *cols_, + int *, + chooser_item_attrs_t *, + size_t n) const +{ + ea_t ea = hn[n]; + + qstrvec_t &cols = *cols_; + if ( get_name(&cols[0], ea) > 0 ) + cols[1].sprnt("%a", ea); + CASSERT(qnumber(header_) == 2); +} + +//-------------------------------------------------------------------------- +bool callgraph_t::showhidden(graph_info_t *gi) const +{ + if ( gi->hide_nodes.empty() ) + { + info("No functions hidden\n"); + return true; + } + + hidden_node_chooser_t ch(gi->hide_nodes); + ssize_t n = ch.choose(chooser_base_t::NO_SELECTION); // why? + if ( n >= 0 ) + { + eavec_t::iterator it = gi->hide_nodes.begin() + n; + gi->hide_nodes.erase(it); + gi->refresh(); + } + + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::showall(graph_info_t *gi) const +{ + gi->hide_nodes.clear(); + gi->refresh(); + + return true; +} + +//-------------------------------------------------------------------------- +bool callgraph_t::navigate(graph_info_t *gi, ea_t addr) const +{ + ea_t func_ea; + + func_ea = gi->fg.get_addr(0); + + // Is it a function? + func_t *pfn = get_func(addr); + if ( pfn != nullptr ) + { + // Is it the same function? + if ( gi->func_ea != addr ) + { + // Clear the forward queue + gi->forward_queue.clear(); + + // Enqueue the current center node + gi->queue.push_front(func_ea); + + gi->func_ea = addr; + gi->refresh(); + + jump_to_node(gi, 0); + return true; + } + } + else + { + return true; + } + + return false; +} + +//-------------------------------------------------------------------------- +void callgraph_t::go_back(graph_info_t *gi) const +{ + gi->forward_queue.push_front(gi->func_ea); + gi->func_ea = gi->queue.front(); + gi->queue.pop_front(); + gi->refresh(); + + jump_to_node(gi, 0); +} + +//-------------------------------------------------------------------------- +void callgraph_t::go_forward(graph_info_t *gi) const +{ + ea_t ea; + + ea = gi->forward_queue.front(); + gi->forward_queue.pop_front(); + gi->queue.push_front(gi->func_ea); + gi->func_ea = ea; + gi->refresh(); + + jump_to_node(gi, 0); +} + +//------------------------------------------------------------------------- +void plugin_ctx_t::ensure_actions_registered() +{ + if ( !actions_registered ) + { + for ( int i = 0, n = qnumber(actions); i < n; ++i ) + register_action(actions[i]); + + actions_registered = true; + } +} + +//-------------------------------------------------------------------------- +bool idaapi plugin_ctx_t::run(size_t arg) +{ + if ( ssize_t(arg) == -1 ) + { + load_options(); + show_options(); + return true; + } + + func_t *pfn = get_func(get_screen_ea()); + if ( pfn == nullptr ) + { + warning("Please position the cursor in a function first!"); + return true; + } + + load_options(); + qstring title = gen_graph_title(pfn->start_ea); + TWidget *form = find_widget(title.c_str()); + if ( form == nullptr ) + { + // no current window, but instance is in the list? + graph_info_t *gi = graph_info_t::find(*this, title.c_str()); + if ( gi != nullptr ) + { + // In that case let us "recycle" the instance + gi->func_ea = pfn->start_ea; + } + else + { + // we create a new instance + gi = graph_info_t::create(*this, pfn->start_ea); + } + + if ( gi != nullptr ) + { + // get a unique graph id + netnode id; + id.create("$ callgraph sample"); + + gi->hide_nodes.begin(); + + gi->mark_for_refresh(); + // gi->form = form; + gi->gv = create_graph_viewer(title.c_str(), id, callgraph_t::gr_callback, gi, 0); + if ( gi->gv != nullptr ) + { + display_widget(/*form*/ gi->gv, WOPN_DP_TAB); + + ensure_actions_registered(); + + viewer_fit_window(gi->gv); +#define ADD_POPUP(Method) viewer_attach_menu_item(gi->gv, "callgraph:" #Method) +#define ADD_SEPARATOR() viewer_attach_menu_item(gi->gv, nullptr) + ADD_POPUP(options); + ADD_POPUP(refresh); + ADD_SEPARATOR(); + ADD_POPUP(jumpxref); + ADD_POPUP(jumpaddr); + ADD_POPUP(jump); + ADD_POPUP(back); + ADD_POPUP(forward); + ADD_SEPARATOR(); + ADD_POPUP(center); + ADD_POPUP(select); + ADD_POPUP(home); + ADD_POPUP(searchfirst); + ADD_POPUP(searchnext); + ADD_POPUP(hidenode); + ADD_POPUP(showhidden); + ADD_POPUP(showall); +#undef ADD_SEPARATOR +#undef ADD_POPUP + } + else + { + graph_info_t::destroy_graph(*this, gi); + gi = nullptr; + } + } + + // Failed to create a graph view? + if ( gi == nullptr ) + { + warning("Failed to create call graph window!"); + return true; + } + } + else + { + graph_info_t *gi = graph_info_t::find(*this, title.c_str()); + if ( gi != nullptr ) + { + gi->refresh(); + display_widget(gi->gv, WOPN_DP_TAB); + } + } + return true; +} + +//------------------------------------------------------------------------- +ssize_t idaapi view_listener_t::on_event(ssize_t code, va_list va) +{ + if ( code == view_close ) + { + TWidget *cc = va_arg(va, TWidget *); + graph_info_t *gi = graph_info_t::find(ctx, (graph_viewer_t *) cc); + if ( gi != nullptr ) + graph_info_t::destroy_graph(ctx, gi); + } + return 0; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + if ( !is_idaq() ) // GUI version? + return nullptr; + plugin_ctx_t *ctx = new plugin_ctx_t; + if ( !ctx->register_main_action() ) + { + msg("Failed to register menu item for <" ACTION_LABEL "> plugin!\n"); + delete ctx; + return nullptr; + } + set_module_data(&data_id, ctx); + return ctx; +} + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_HIDE|PLUGIN_MULTI, // plugin flags + init, // initialize + + nullptr, // terminate. this pointer may be nullptr. + nullptr, // invoke plugin + + // long comment about the plugin + "Proximity browser plugin.", + // it could appear in the status line + // or as a hint + + // multiline help about the plugin + "Proximity browser using the graph SDK\n" + "\n" + "Position the cursor in a function and run the plugin.", + + ACTION_LABEL, // the preferred short name of the plugin + "" // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/callgraph/callgraph.h b/idasdk76/plugins/callgraph/callgraph.h new file mode 100644 index 0000000..12dc353 --- /dev/null +++ b/idasdk76/plugins/callgraph/callgraph.h @@ -0,0 +1,332 @@ +#ifndef __CALLGRAPH__06192009__ +#define __CALLGRAPH__06192009__ + +#include <deque> +#include <ida.hpp> +#include <idp.hpp> +#include <name.hpp> +#include <bytes.hpp> +#include <graph.hpp> +#include <loader.hpp> +#include <kernwin.hpp> +#include <demangle.hpp> + +#define MAX_CALLERS_LEVEL 10 + +#define FIELD_ID_STRINGS 1 +#define FIELD_ID_LIBS 2 +#define FIELD_ID_FATHERS 3 +#define FIELD_ID_CHILDS 4 +#define FIELD_ID_CHILDS_LEVEL 6 + +#define VERTEX_HIDDEN_NODES -1 + +struct plugin_ctx_t; +typedef std::deque<int> int_queue_t; +typedef std::map<ea_t, int> ea_int_map_t; + +//-------------------------------------------------------------------------- +struct funcs_walk_options_t +{ + int32 version; +#define FWO_VERSION 1 // current version of options block + int32 flags; +#define FWO_SHOWSTRING 0x0001 // show string references +#define FWO_SKIPLIB 0x0002 // skip library functions +#define FWO_CALLEE_RECURSE_UNLIM 0x0004 // unlimited callees recursion + int32 callees_recurse_limit; // how deep to recurse callees (0 = unlimited) + int32 callers_recurse_limit; // how deep to recurse callers (0 = unlimited) + int32 max_nodes; // maximum number of nodes per level +}; + +class graph_info_t; + +//-------------------------------------------------------------------------- +// function call graph creator class +class callgraph_t +{ +public: + plugin_ctx_t &ctx; + +private: + int node_count = 0; + + // node id to func addr and reverse lookup + typedef std::map<int, ea_t> int_ea_map_t; + int_ea_map_t node2ea; + + // current node search ptr + int cur_node = 0; + char cur_text[MAXSTR]; + + bool visited(ea_t func_ea, int *nid); + int add(ea_t func_ea); + +public: + + ea_int_map_t ea2node; + // edge structure + struct edge_t + { + int id1; + int id2; + edge_t(int i1, int i2): id1(i1), id2(i2) {} + edge_t(): id1(0), id2(0) {} + }; + typedef qlist<edge_t> edges_t; + + // edge manipulation + typedef edges_t::iterator edge_iterator; + void create_edge(int id1, int id2); + edge_iterator begin_edges() { return edges.begin(); } + edge_iterator end_edges() { return edges.end(); } + void clear_edges(); + + // find nodes by text + int find_first(const char *text); + int find_next(); + const char *get_findtext() { return cur_text; } + callgraph_t(plugin_ctx_t &ctx); + int count() const { return node_count; } + void reset(); + + // node / func info + struct funcinfo_t + { + qstring name; + bgcolor_t color; + ea_t ea; + qstring strings; + }; + typedef std::map<int, funcinfo_t> int_funcinfo_map_t; + int_funcinfo_map_t cached_funcs; + funcinfo_t *get_info(int nid); + + // function name manipulation + ea_t get_addr(int nid) const; + const char *get_name(int nid); + + int walk_func(eavec_t *hide_nodes, func_t *func, funcs_walk_options_t *o=NULL, int level=1); + void add_fathers(func_t *func, ea_t func_start, int id, funcs_walk_options_t *opt, int level); + + bool navigate(graph_info_t *gi, ea_t addr) const; + + void go_back(graph_info_t *gi) const; + void go_forward(graph_info_t *gi) const; + + bool options(graph_info_t *gi) const; + bool refresh(graph_info_t *gi) const; + + bool jumpxref(graph_info_t *gi) const; + bool jumpaddr(graph_info_t *gi) const; + bool jump(const graph_info_t *gi) const; + bool back(graph_info_t *gi) const; + bool forward(graph_info_t *gi) const; + + bool center(graph_info_t *gi) const; + bool select(const graph_info_t *gi) const; + bool home(const graph_info_t *gi) const; + bool searchfirst(graph_info_t *gi); + bool searchnext(graph_info_t *gi); + bool hidenode(graph_info_t *gi) const; + bool showhidden(graph_info_t *gi) const; + bool showall(graph_info_t *gi) const; + + static ssize_t idaapi gr_callback(void *ud, int code, va_list va); + static void idaapi user_refresh(void *ud, int code, va_list va, int current_node); +private: + edges_t edges; +}; + +//-------------------------------------------------------------------------- +DECLARE_LISTENER(view_listener_t, plugin_ctx_t, ctx); +DECLARE_LISTENER(idp_gi_listener_t, graph_info_t, gi); +DECLARE_LISTENER(idb_gi_listener_t, graph_info_t, gi); + +struct idp_merge_listener_t : public event_listener_t +{ + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; +}; + +//-------------------------------------------------------------------------- +// Per function call graph context +typedef qlist<class graph_info_t *> graphinfo_list_t; +class graph_info_t +{ + plugin_ctx_t &ctx; + idp_gi_listener_t idp_gi_listener = idp_gi_listener_t(*this); + idb_gi_listener_t idb_gi_listener = idb_gi_listener_t(*this); + +public: + typedef graphinfo_list_t::iterator iterator; + + callgraph_t fg; // associated call graph maker + graph_viewer_t *gv = nullptr; // associated graph_view + TWidget *widget = nullptr; // associated widget + ea_t func_ea = BADADDR; // function ea in question + qstring title; // the title + + int_queue_t queue; + int_queue_t forward_queue; + + eavec_t hide_nodes; + +private: + bool refresh_needed = true; // schedule a refresh + + graph_info_t(plugin_ctx_t &_ctx) : ctx(_ctx), fg(_ctx) {} + static bool find(plugin_ctx_t &ctx, ea_t func_ea, iterator *out); +public: + static graph_info_t *find(plugin_ctx_t &ctx, ea_t func_ea); + static graph_info_t *find(plugin_ctx_t &ctx, const char *title); + static graph_info_t *find(plugin_ctx_t &ctx, const graph_viewer_t *v); + static graph_info_t *create(plugin_ctx_t &ctx, ea_t func_ea); + static void destroy_graph(plugin_ctx_t &ctx, graph_info_t *gi); + void install_hooks(); + void remove_hooks(); + void mark_for_refresh(void); + void mark_as_refreshed(void); + void refresh(void); + bool is_refresh_needed(void) const { return refresh_needed; } +}; + +//------------------------------------------------------------------------- +// The main action to invoke the plugin +struct show_callgraph_ah_t : public action_handler_t +{ + plugin_ctx_t &ctx; + show_callgraph_ah_t(plugin_ctx_t &_ctx) : ctx(_ctx) {} + virtual int idaapi activate(action_activation_ctx_t *) override; + virtual action_state_t idaapi update(action_update_ctx_t *) override + { + return AST_ENABLE_ALWAYS; + } +}; + +//------------------------------------------------------------------------- +// Base class for additional actions in the graph view +struct cg_ah_t : public action_handler_t +{ + plugin_ctx_t &plg; + cg_ah_t(plugin_ctx_t &p) : plg(p) {} + virtual int act(graph_info_t *gi) = 0; + + virtual int idaapi activate(action_activation_ctx_t *ctx) override + { + graph_info_t *gi = graph_info_t::find(plg, (graph_viewer_t *) ctx->widget); + return gi != nullptr ? act(gi) : 0; + } + + virtual action_state_t idaapi update(action_update_ctx_t *ctx) override + { + return graph_info_t::find(plg, (graph_viewer_t *) ctx->widget) != nullptr + ? AST_ENABLE_FOR_WIDGET + : AST_DISABLE_FOR_WIDGET; + } +}; + +//------------------------------------------------------------------------- +#define DECLARE_ACTION_HANDLER(Method) \ +struct Method##_ah_t : public cg_ah_t \ +{ \ + Method##_ah_t(plugin_ctx_t &p) : cg_ah_t(p) {} \ + virtual int act(graph_info_t *gi) override \ + { \ + return int(gi->fg.Method(gi)); \ + } \ +} +DECLARE_ACTION_HANDLER(options); +DECLARE_ACTION_HANDLER(refresh); +DECLARE_ACTION_HANDLER(jumpxref); +DECLARE_ACTION_HANDLER(jumpaddr); +DECLARE_ACTION_HANDLER(jump); +DECLARE_ACTION_HANDLER(back); +DECLARE_ACTION_HANDLER(forward); +DECLARE_ACTION_HANDLER(center); +DECLARE_ACTION_HANDLER(select); +DECLARE_ACTION_HANDLER(home); +DECLARE_ACTION_HANDLER(searchfirst); +DECLARE_ACTION_HANDLER(searchnext); +DECLARE_ACTION_HANDLER(hidenode); +DECLARE_ACTION_HANDLER(showhidden); +DECLARE_ACTION_HANDLER(showall); +#undef DECLARE_ACTION_HANDLER + +//-------------------------------------------------------------------------- +#define PROCMOD_NODE_NAME "$ proximity browser" + +struct plugin_ctx_t : public plugmod_t +{ + view_listener_t view_listener = view_listener_t(*this); + idp_merge_listener_t idp_merge_listener; + + show_callgraph_ah_t show_callgraph_ah = show_callgraph_ah_t(*this); + const action_desc_t main_action; +#define DEFINE_ACTION_HANDLER(Method) Method##_ah_t Method##_ah = Method##_ah_t(*this) //lint !e773 macro not parenthized + DEFINE_ACTION_HANDLER(options); + DEFINE_ACTION_HANDLER(refresh); + DEFINE_ACTION_HANDLER(jumpxref); + DEFINE_ACTION_HANDLER(jumpaddr); + DEFINE_ACTION_HANDLER(jump); + DEFINE_ACTION_HANDLER(back); + DEFINE_ACTION_HANDLER(forward); + DEFINE_ACTION_HANDLER(center); + DEFINE_ACTION_HANDLER(select); + DEFINE_ACTION_HANDLER(home); + DEFINE_ACTION_HANDLER(searchfirst); + DEFINE_ACTION_HANDLER(searchnext); + DEFINE_ACTION_HANDLER(hidenode); + DEFINE_ACTION_HANDLER(showhidden); + DEFINE_ACTION_HANDLER(showall); +#undef DEFINE_ACTION_HANDLER + const action_desc_t actions[15] = + { +#define ROW(Method, Label, Shortcut) \ + ACTION_DESC_LITERAL_PLUGMOD("callgraph:" #Method, Label, &Method##_ah, this, Shortcut, nullptr, -1) + ROW(options, "Options", "O"), // 1 + ROW(refresh, "Refresh", "R"), // 2 + ROW(jumpxref, "Jump to xref", "X"), // 3 + ROW(jumpaddr, "Jump to address", "G"), // 4 + ROW(jump, "Jump to function", "SPACE"), // 5 + ROW(back, "Jump to previous node", "ESC"), // 6 + ROW(forward, "Jump to next node", "Ctrl+Enter"), // 7 + ROW(center, "Center node", "Enter"), // 8 + ROW(select, "Select node", "Ctrl+L"), // 9 + ROW(home, "Goto to first node", "H"), // 0 + ROW(searchfirst, "Search first", "S"), // 1 + ROW(searchnext, "Search next", "N"), // 2 + ROW(hidenode, "Hide selected node", nullptr), // 3 + ROW(showhidden, "Show hidden node", nullptr), // 4 + ROW(showall, "Show all nodes", nullptr), // 5 +#undef ROW + }; + + graphinfo_list_t instances; + funcs_walk_options_t fg_opts = + { + FWO_VERSION, // version + FWO_CALLEE_RECURSE_UNLIM, // flags + 2, // max callees recursion + 1, // max callers recursion + 255 // max nodes per level + }; + + bool actions_registered = false; + + qstring last_text; //lint !e958 padding // see findfirst_node() + + + virtual bool idaapi run(size_t arg) override; + plugin_ctx_t(); + bool register_main_action(); + ~plugin_ctx_t(); + qstring gen_graph_title(ea_t ea); + bool load_options(); + void save_options(); + bool show_options(); + void ensure_actions_registered(); +}; + +extern int data_id; + +#endif diff --git a/idasdk76/plugins/callgraph/makefile b/idasdk76/plugins/callgraph/makefile new file mode 100644 index 0000000..2c2faea --- /dev/null +++ b/idasdk76/plugins/callgraph/makefile @@ -0,0 +1,15 @@ +PROC=callgraph + + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)callgraph$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)demangle.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + callgraph.cpp callgraph.h + diff --git a/idasdk75/plugins/choose/choose.cpp b/idasdk76/plugins/choose/choose.cpp similarity index 100% rename from idasdk75/plugins/choose/choose.cpp rename to idasdk76/plugins/choose/choose.cpp diff --git a/idasdk76/plugins/choose/makefile b/idasdk76/plugins/choose/makefile new file mode 100644 index 0000000..611f6aa --- /dev/null +++ b/idasdk76/plugins/choose/makefile @@ -0,0 +1,11 @@ +PROC=choose + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)choose$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + choose.cpp diff --git a/idasdk76/plugins/custdata/custdata.cpp b/idasdk76/plugins/custdata/custdata.cpp new file mode 100644 index 0000000..a5bbcef --- /dev/null +++ b/idasdk76/plugins/custdata/custdata.cpp @@ -0,0 +1,177 @@ +/* Custom data type sample plugin. + * Copyright (c) 2010-2021 Hex-Rays, support@hex-rays.com + * Feel free to do whatever you want with this code. + * + * This sample plugin demonstates how to install a custom data type + * and a custom data format in IDA v5.7 + * + * Custom data types can be used to create your own data types. + * A custom data type basically defines the data size. It can be fixed + * or variable. This plugin defines a variable size data type: a pascal + * string. Pascal strings start with a count byte: + * db len, '....' + * + * Custom data formats are used to render data values on the screen. + * Multiple data formats can be registered for a custom data type. + * The data formats with non-NULL menu_names will be listed in the 'Operand type' + * menu and the user will be able to select them. + * + */ + +#include <ida.hpp> +#include <idp.hpp> +#include <struct.hpp> +#include <loader.hpp> +#include <kernwin.hpp> + +struct plugin_ctx_t : public plugmod_t +{ + int psid = 0; // id of the 'pascal string' data type + int psfid = 0; // id of the 'pascal string' data format + + plugin_ctx_t(); + ~plugin_ctx_t(); + virtual bool idaapi run(size_t) override { return false; } +}; + +//--------------------------------------------------------------------------- +// We define a variable size data type. For fixed size types this function +// must be omitted. +static asize_t idaapi calc_pascal_string_length(void *, ea_t ea, asize_t maxsize) +{ + if ( is_member_id(ea) ) + { // Custom data types may be used in structure definitions. If this case + // ea is a member id. Check for this situation and return 1 + return 1; + } + ushort n = get_byte(ea); + if ( n+1 > maxsize ) + return 0; // string would be too big + return n+1; // ok, we accept any pascal string +} + +//--------------------------------------------------------------------------- +// Definition of the data type +static const data_type_t pascal_string_type = +{ + sizeof(data_type_t), // size of this structure + NULL, // user defined data + 0, // properties + "pascal_string", // internal name of the data type + // must be unique for the current database + "Pascal string", // Menu name. If NULL, the type won't be visible in the Edit menu. + NULL, // Hotkey + "pstr", // Keyword to use in the assembly listing + 2, // value size. For varsize types, specify the + // minimal size of the value + NULL, // may_create_at? NULL means the type can be created anywhere + calc_pascal_string_length, // for varsize types: calculate the exact size of an item +}; + +//--------------------------------------------------------------------------- +// Print contents of a pascal string +static bool idaapi print_pascal_string( + void *, // user defined data, not used here + qstring *out, // output buffer. may be NULL + const void *value, // value to print. may not be NULL + asize_t size, // value size in bytes + ea_t, // current ea + int, // operand number + int) // data type id +{ + const char *vptr = (const char *)value; + int n = *vptr++; + if ( n+1 > size ) + return false; + + if ( out != NULL ) + { + *out = "\""; + for ( int i=0; i < n; i++ ) + { + if ( qisprint(*vptr) ) + out->append(*vptr++); + else + out->cat_sprnt("\\x%02X", uchar(*vptr++)); + } + out->append('"'); + } + return true; +} + +//--------------------------------------------------------------------------- +// Definition of the data format +static const data_format_t pascal_string_format = +{ + sizeof(data_format_t), // size of this structure + NULL, // user defined data + 0, // properties + "pascal_string", // internal name of the data format + NULL, // Menu name of the format. NULL means 'do not create menu item' + NULL, // Hotkey + 0, // value size. 0 means that this format accepts any value size + 0, // Text width of the value. Unknown, specify 0 + print_pascal_string, // callback to render colored text for the data + NULL, // scan + NULL, // analyze +}; + + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + processor_t &ph = PH; + if ( ph.id != PLFM_386 ) + return nullptr; + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +plugin_ctx_t::plugin_ctx_t() +{ + // Register custom data type + psid = register_custom_data_type(&pascal_string_type); + // Register custom data format for it + psfid = register_custom_data_format(&pascal_string_format); + attach_custom_data_format(psid, psfid); +} + +//-------------------------------------------------------------------------- +plugin_ctx_t::~plugin_ctx_t() +{ + // unregister data type + if ( psid > 0 ) + { + // IDA would detach the data format automatically. + unregister_custom_data_type(psid); + } + // unregister data format + if ( psfid > 0 ) + unregister_custom_data_format(psfid); +} + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_PROC // plugin flags + // we want the plugin to load as soon as possible + // immediately after the processor module + |PLUGIN_HIDE // we want to hide the plugin because it there will + // be a menu item in the Edit submenu + |PLUGIN_MULTI, // this plugin can work with multiple idbs in parallel + init, // initialize + nullptr, + nullptr, + "", // long comment about the plugin + // it could appear in the status line + // or as a hint + "", // multiline help about the plugin + + "Sample custdata", // the preferred short name of the plugin + "" // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/custdata/makefile b/idasdk76/plugins/custdata/makefile new file mode 100644 index 0000000..4b4aa1c --- /dev/null +++ b/idasdk76/plugins/custdata/makefile @@ -0,0 +1,11 @@ +PROC=custdata + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)custdata$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)struct.hpp $(I)ua.hpp \ + $(I)xref.hpp custdata.cpp diff --git a/idasdk76/plugins/custview/custview.cpp b/idasdk76/plugins/custview/custview.cpp new file mode 100644 index 0000000..e99976e --- /dev/null +++ b/idasdk76/plugins/custview/custview.cpp @@ -0,0 +1,282 @@ +/* Custom viewer sample plugin. + * Copyright (c) 2007 by Ilfak Guilfanov, ig@hexblog.com + * Feel free to do whatever you want with this code. + * + * This sample plugin demonstates how to create and manipulate a simple + * custom viewer in IDA v5.1 + * + * Custom viewers allow you to create a view which displays colored lines. + * These colored lines are dynamically created by callback functions. + * + * Custom viewers are used in IDA itself to display + * the disassembly listng, structure, and enumeration windows. + * + * This sample plugin just displays several sample lines on the screen. + * It displays a hint with the current line number. + * The right-click menu contains one sample command. + * It reacts to one hotkey. + * + * This plugin uses the simpleline_place_t class for the locations. + * Custom viewers can use any decendant of the place_t class. + * The place_t is responsible for supplying data to the viewer. + */ + +//--------------------------------------------------------------------------- +#include <ida.hpp> +#include <idp.hpp> +#include <loader.hpp> +#include <kernwin.hpp> + +#define ACTION_NAME "custview:SampleMenuItem" + +struct plugin_ctx_t; +struct sample_action_t : public action_handler_t +{ + plugin_ctx_t &plg; + sample_action_t(plugin_ctx_t &p) : plg(p) {} + virtual int idaapi activate(action_activation_ctx_t *) override; + virtual action_state_t idaapi update(action_update_ctx_t *) override + { + return AST_ENABLE_ALWAYS; + } +}; + +//------------------------------------------------------------------------- +static struct +{ + const char *text; + bgcolor_t color; +} const sample_text[] = +{ + { "This is a sample text", 0xFFFFFF }, + { "It will be displayed in the custom view", 0xFFC0C0 }, + { COLSTR("This line will be colored as erroneous", SCOLOR_ERROR), 0xC0FFC0 }, + { COLSTR("Every", SCOLOR_AUTOCMT) " " + COLSTR("word", SCOLOR_DNAME) " " + COLSTR("can", SCOLOR_IMPNAME) " " + COLSTR("be", SCOLOR_NUMBER) " " + COLSTR("colored!", SCOLOR_EXTRA), 0xC0C0FF }, + { " No limit on the number of lines.", 0xC0FFFF }, +}; + +// Structure to keep all information about the our sample view +struct sample_info_t +{ + TWidget *cv; + strvec_t sv; + sample_info_t() : cv(NULL) {} +}; + +struct plugin_ctx_t : public plugmod_t, public event_listener_t +{ + sample_info_t *si = NULL; + const sample_info_t *last_si = NULL; + + sample_action_t sample_ah = sample_action_t(*this); + const action_desc_t sample_action = ACTION_DESC_LITERAL_PLUGMOD( + ACTION_NAME, + "Sample menu item", + &sample_ah, + this, + "N", + NULL, + -1); + + virtual bool idaapi run(size_t) override; + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; +}; + +//--------------------------------------------------------------------------- +// get the word under the (keyboard or mouse) cursor +static bool get_current_word(TWidget *v, bool mouse, qstring &word) +{ + // query the cursor position + int x, y; + if ( get_custom_viewer_place(v, mouse, &x, &y) == NULL ) + return false; + + // query the line at the cursor + qstring buf; + tag_remove(&buf, get_custom_viewer_curline(v, mouse)); + if ( x >= buf.length() ) + return false; + + // find the beginning of the word + char *ptr = buf.begin() + x; + while ( ptr > buf.begin() && !qisspace(ptr[-1]) ) + ptr--; + + // find the end of the word + char *begin = ptr; + ptr = buf.begin() + x; + while ( !qisspace(*ptr) && *ptr != '\0' ) + ptr++; + + word = qstring(begin, ptr-begin); + return true; +} + +//--------------------------------------------------------------------------- +int idaapi sample_action_t::activate(action_activation_ctx_t *) +{ + qstring word; + if ( !get_current_word(plg.last_si->cv, false, word) ) + return 0; + + info("The current word is: %s", word.c_str()); + return 1; +} + +//--------------------------------------------------------------------------- +// Keyboard callback +static bool idaapi ct_keyboard(TWidget * /*v*/, int key, int shift, void *ud) +{ + if ( shift == 0 ) + { + sample_info_t *si = (sample_info_t *)ud; + switch ( key ) + { + case 'N': + warning("The hotkey 'N' has been pressed"); + return true; + case IK_ESCAPE: + close_widget(si->cv, WCLS_SAVE | WCLS_CLOSE_LATER); + return true; + } + } + return false; +} + +//--------------------------------------------------------------------------- +// This callback will be called each time the keyboard cursor position +// is changed +static void idaapi ct_curpos(TWidget *v, void *) +{ + qstring word; + if ( get_current_word(v, false, word) ) + msg("Current word is: %s\n", word.c_str()); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + // how to implement a simple hint callback + case ui_get_custom_viewer_hint: + { + qstring &hint = *va_arg(va, qstring *); + TWidget *viewer = va_arg(va, TWidget *); + place_t *place = va_arg(va, place_t *); + int *important_lines = va_arg(va, int *); + if ( si->cv == viewer ) // our viewer + { + if ( place == NULL ) + return 0; + simpleline_place_t *spl = (simpleline_place_t *)place; + hint.cat_sprnt("Hint for line %u\n", spl->n); + *important_lines += 1; + } + break; + } + case ui_widget_invisible: + { + TWidget *f = va_arg(va, TWidget *); + if ( f == si->cv ) + { + delete si; + si = nullptr; + unhook_event_listener(HT_UI, this); + } + } + break; + case ui_populating_widget_popup: + { + TWidget *f = va_arg(va, TWidget *); + if ( f == si->cv ) + { + TPopupMenu *p = va_arg(va, TPopupMenu *); + // Create right-click menu on the fly + attach_action_to_popup(f, p, ACTION_NAME); + } + } + break; + } + return 0; +} + +//------------------------------------------------------------------------- +static const custom_viewer_handlers_t handlers( + ct_keyboard, + NULL, // popup + NULL, // mouse_moved + NULL, // click + NULL, // dblclick + ct_curpos, + NULL, // close + NULL, // help + NULL);// adjust_place + +//--------------------------------------------------------------------------- +// Create a custom view window +bool idaapi plugin_ctx_t::run(size_t) +{ + TWidget *widget = find_widget("Sample custom view"); + if ( widget != NULL ) + { + activate_widget(widget, true); + return true; + } + + // allocate block to hold info about our sample view + si = new sample_info_t(); + last_si = si; + // prepare the data to display. we could prepare it on the fly too. + // but for that we have to use our own custom place_t class decendant. + for ( int i=0; i < qnumber(sample_text); i++ ) + { + si->sv.push_back(simpleline_t("")); // add empty line + si->sv.push_back(simpleline_t(sample_text[i].text)); + si->sv.back().bgcolor = sample_text[i].color; + } + // create two place_t objects: for the minimal and maximal locations + simpleline_place_t s1; + simpleline_place_t s2(si->sv.size()-1); + // create a custom viewer + si->cv = create_custom_viewer("Sample custom view", &s1, &s2, &s1, NULL, &si->sv, &handlers, si); + // also set the ui event callback + hook_event_listener(HT_UI, this); + // finally display the form on the screen + display_widget(si->cv, WOPN_DP_TAB|WOPN_RESTORE); + + // Register the action. This one will be attached + // live, to the popup menu. + register_action(sample_action); + return true; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI, // plugin flags + init, // initialize + + nullptr, + nullptr, + + "", // long comment about the plugin + "", // multiline help about the plugin + "Sample custview", // the preferred short name of the plugin + "" // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/custview/makefile b/idasdk76/plugins/custview/makefile new file mode 100644 index 0000000..c4bc4ee --- /dev/null +++ b/idasdk76/plugins/custview/makefile @@ -0,0 +1,11 @@ +PROC=custview + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)custview$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + custview.cpp diff --git a/idasdk75/plugins/dwarf/look_for_debug_file.cpp b/idasdk76/plugins/dwarf/look_for_debug_file.cpp similarity index 100% rename from idasdk75/plugins/dwarf/look_for_debug_file.cpp rename to idasdk76/plugins/dwarf/look_for_debug_file.cpp diff --git a/idasdk76/plugins/ex_debidc/ex_debidc.cpp b/idasdk76/plugins/ex_debidc/ex_debidc.cpp new file mode 100644 index 0000000..9a4dffd --- /dev/null +++ b/idasdk76/plugins/ex_debidc/ex_debidc.cpp @@ -0,0 +1,143 @@ +// Debugger IDC Helper +// Executes IDC script when the process is launched +// In fact, this approach can be used to hook IDC scripts to various debugger +// events. + +#include <ida.hpp> +#include <idp.hpp> +#include <dbg.hpp> +#include <expr.hpp> +#include <loader.hpp> + +int data_id; + +//-------------------------------------------------------------------------- +// The plugin stores the IDC file name in the database +// It will create a node for this purpose +static const char node_name[] = "$ debugger idc file"; + + +//-------------------------------------------------------------------------- +struct plugin_ctx_t; + +DECLARE_LISTENER(dbg_listener_t, plugin_ctx_t, ctx); +DECLARE_LISTENER(idp_listener_t, plugin_ctx_t, ctx); + +struct plugin_ctx_t : public plugmod_t +{ + dbg_listener_t dbg_listener = dbg_listener_t(*this); + idp_listener_t idp_listener = idp_listener_t(*this); + plugin_ctx_t() + { + hook_event_listener(HT_DBG, &dbg_listener); + hook_event_listener(HT_IDP, &idp_listener); + set_module_data(&data_id, this); + } + ~plugin_ctx_t() + { + clr_module_data(data_id); + // listeners are uninstalled automatically + // when the owner module is unloaded + } + + virtual bool idaapi run(size_t) override; +}; + +//-------------------------------------------------------------------------- +// Get the IDC file name from the database +static bool get_idc_name(char *buf, size_t bufsize) +{ + // access the node + netnode mynode(node_name); + // retrieve the value + return mynode.valstr(buf, bufsize) > 0; +} + +//-------------------------------------------------------------------------- +// Store the IDC file name in the database +static void set_idc_name(const char *idc) +{ + // access the node + netnode mynode; + // if it doesn't exist yet, create it + // otherwise get its id + mynode.create(node_name); + // store the value + mynode.set(idc, strlen(idc)+1); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idp_listener_t::on_event(ssize_t code, va_list va) +{ + return 0; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi dbg_listener_t::on_event(ssize_t code, va_list /*va*/) +{ + switch ( code ) + { + case dbg_process_start: + case dbg_process_attach: + // it is time to run the script + char idc[QMAXPATH]; + if ( get_idc_name(idc, sizeof(idc)) ) + { + qstring errbuf; + if ( !exec_idc_script(NULL, idc, "main", NULL, 0, &errbuf) ) + warning("%s", errbuf.c_str()); + } + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +bool idaapi plugin_ctx_t::run(size_t) +{ + // retrieve the old IDC name from the database + char idc[QMAXPATH]; + if ( !get_idc_name(idc, sizeof(idc)) ) + qstrncpy(idc, "*.idc", sizeof(idc)); + + char *newidc = ask_file(false, idc, "Specify the script to run upon debugger launch"); + if ( newidc != NULL ) + { + // store it back in the database + set_idc_name(newidc); + msg("Script %s will be run when the debugger is launched\n", newidc); + } + return true; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + // Our plugin works only for x86 PE executables + processor_t &ph = PH; + if ( ph.id != PLFM_386 || inf_get_filetype() != f_PE ) + return nullptr; + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +static const char wanted_name[] = "Specify Debugger IDC Script"; +static const char wanted_hotkey[] = ""; + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel + init, // initialize + nullptr, + nullptr, + wanted_name, // long comment about the plugin + wanted_name, // multiline help about the plugin + wanted_name, // the preferred short name of the plugin + wanted_hotkey // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/ex_debidc/makefile b/idasdk76/plugins/ex_debidc/makefile new file mode 100644 index 0000000..c0f9580 --- /dev/null +++ b/idasdk76/plugins/ex_debidc/makefile @@ -0,0 +1,12 @@ +PROC=ex_debidc + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ex_debidc$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)expr.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp \ + $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h $(I)range.hpp \ + $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp ex_debidc.cpp diff --git a/idasdk75/plugins/ex_events1/ex_events1.cpp b/idasdk76/plugins/ex_events1/ex_events1.cpp similarity index 100% rename from idasdk75/plugins/ex_events1/ex_events1.cpp rename to idasdk76/plugins/ex_events1/ex_events1.cpp diff --git a/idasdk76/plugins/ex_events1/makefile b/idasdk76/plugins/ex_events1/makefile new file mode 100644 index 0000000..d289025 --- /dev/null +++ b/idasdk76/plugins/ex_events1/makefile @@ -0,0 +1,11 @@ +PROC=ex_events1 + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ex_events1$(O): $(I)allins.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ex_events1.cpp diff --git a/idasdk75/plugins/exports.def b/idasdk76/plugins/exports.def similarity index 100% rename from idasdk75/plugins/exports.def rename to idasdk76/plugins/exports.def diff --git a/idasdk75/plugins/extlang/extlang.cpp b/idasdk76/plugins/extlang/extlang.cpp similarity index 100% rename from idasdk75/plugins/extlang/extlang.cpp rename to idasdk76/plugins/extlang/extlang.cpp diff --git a/idasdk76/plugins/extlang/makefile b/idasdk76/plugins/extlang/makefile new file mode 100644 index 0000000..1a19aa2 --- /dev/null +++ b/idasdk76/plugins/extlang/makefile @@ -0,0 +1,11 @@ +PROC=extlang + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)extlang$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp extlang.cpp diff --git a/idasdk75/plugins/findcrypt2/consts.cpp b/idasdk76/plugins/findcrypt2/consts.cpp similarity index 100% rename from idasdk75/plugins/findcrypt2/consts.cpp rename to idasdk76/plugins/findcrypt2/consts.cpp diff --git a/idasdk75/plugins/findcrypt2/findcrypt.cpp b/idasdk76/plugins/findcrypt2/findcrypt.cpp similarity index 100% rename from idasdk75/plugins/findcrypt2/findcrypt.cpp rename to idasdk76/plugins/findcrypt2/findcrypt.cpp diff --git a/idasdk75/plugins/findcrypt2/findcrypt.hpp b/idasdk76/plugins/findcrypt2/findcrypt.hpp similarity index 100% rename from idasdk75/plugins/findcrypt2/findcrypt.hpp rename to idasdk76/plugins/findcrypt2/findcrypt.hpp diff --git a/idasdk76/plugins/findcrypt2/makefile b/idasdk76/plugins/findcrypt2/makefile new file mode 100644 index 0000000..a6fdbac --- /dev/null +++ b/idasdk76/plugins/findcrypt2/makefile @@ -0,0 +1,16 @@ +PROC=findcrypt +O1=consts +O2=sparse + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)consts$(O) : $(I)llong.hpp $(I)pro.h consts.cpp findcrypt.hpp +$(F)findcrypt$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)dirtree.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)moves.hpp \ + $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ + $(I)xref.hpp findcrypt.cpp findcrypt.hpp +$(F)sparse$(O) : $(I)llong.hpp $(I)pro.h findcrypt.hpp sparse.cpp diff --git a/idasdk75/plugins/findcrypt2/sparse.cpp b/idasdk76/plugins/findcrypt2/sparse.cpp similarity index 100% rename from idasdk75/plugins/findcrypt2/sparse.cpp rename to idasdk76/plugins/findcrypt2/sparse.cpp diff --git a/idasdk75/plugins/formchooser/formchooser.cpp b/idasdk76/plugins/formchooser/formchooser.cpp similarity index 100% rename from idasdk75/plugins/formchooser/formchooser.cpp rename to idasdk76/plugins/formchooser/formchooser.cpp diff --git a/idasdk75/plugins/formchooser/formchooser.py b/idasdk76/plugins/formchooser/formchooser.py similarity index 100% rename from idasdk75/plugins/formchooser/formchooser.py rename to idasdk76/plugins/formchooser/formchooser.py diff --git a/idasdk76/plugins/formchooser/makefile b/idasdk76/plugins/formchooser/makefile new file mode 100644 index 0000000..78ec91b --- /dev/null +++ b/idasdk76/plugins/formchooser/makefile @@ -0,0 +1,11 @@ +PROC=formchooser + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)formchooser$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + formchooser.cpp diff --git a/idasdk75/plugins/formchooser/smile.png b/idasdk76/plugins/formchooser/smile.png similarity index 100% rename from idasdk75/plugins/formchooser/smile.png rename to idasdk76/plugins/formchooser/smile.png diff --git a/idasdk75/plugins/formsample/formsample.cpp b/idasdk76/plugins/formsample/formsample.cpp similarity index 100% rename from idasdk75/plugins/formsample/formsample.cpp rename to idasdk76/plugins/formsample/formsample.cpp diff --git a/idasdk76/plugins/formsample/makefile b/idasdk76/plugins/formsample/makefile new file mode 100644 index 0000000..856d554 --- /dev/null +++ b/idasdk76/plugins/formsample/makefile @@ -0,0 +1,11 @@ +PROC=formsample + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)formsample$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + formsample.cpp diff --git a/idasdk75/plugins/funclist/funclist.cpp b/idasdk76/plugins/funclist/funclist.cpp similarity index 100% rename from idasdk75/plugins/funclist/funclist.cpp rename to idasdk76/plugins/funclist/funclist.cpp diff --git a/idasdk76/plugins/funclist/makefile b/idasdk76/plugins/funclist/makefile new file mode 100644 index 0000000..760e0de --- /dev/null +++ b/idasdk76/plugins/funclist/makefile @@ -0,0 +1,12 @@ +PROC=funclist + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)funclist$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)entry.hpp $(I)fpro.h $(I)funcs.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)name.hpp $(I)netnode.hpp $(I)pro.h $(I)range.hpp \ + $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp $(I)xref.hpp \ + funclist.cpp diff --git a/idasdk75/plugins/getlines/getlines.cpp b/idasdk76/plugins/getlines/getlines.cpp similarity index 100% rename from idasdk75/plugins/getlines/getlines.cpp rename to idasdk76/plugins/getlines/getlines.cpp diff --git a/idasdk76/plugins/getlines/makefile b/idasdk76/plugins/getlines/makefile new file mode 100644 index 0000000..50eff02 --- /dev/null +++ b/idasdk76/plugins/getlines/makefile @@ -0,0 +1,11 @@ +PROC=getlines + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)getlines$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + getlines.cpp diff --git a/idasdk75/plugins/hello/hello.cpp b/idasdk76/plugins/hello/hello.cpp similarity index 100% rename from idasdk75/plugins/hello/hello.cpp rename to idasdk76/plugins/hello/hello.cpp diff --git a/idasdk75/plugins/hello/hello.idc b/idasdk76/plugins/hello/hello.idc similarity index 100% rename from idasdk75/plugins/hello/hello.idc rename to idasdk76/plugins/hello/hello.idc diff --git a/idasdk75/plugins/hello/hello.py b/idasdk76/plugins/hello/hello.py similarity index 100% rename from idasdk75/plugins/hello/hello.py rename to idasdk76/plugins/hello/hello.py diff --git a/idasdk76/plugins/hello/makefile b/idasdk76/plugins/hello/makefile new file mode 100644 index 0000000..0ae8f58 --- /dev/null +++ b/idasdk76/plugins/hello/makefile @@ -0,0 +1,26 @@ +PROC=hello + +include ../plugin.mak + +all: scripts + +SCRIPTS := $(addprefix $(BIN_PATH),idchello.idc pyhello.py) + +.PHONY: scripts +scripts: $(SCRIPTS) + +$(BIN_PATH)%.idc: %.idc + $(CP) $? $@ +$(BIN_PATH)%.py: %.py + $(CP) $? $@ + +uninstall:: + rm -rf $(SCRIPTS) + +# MAKEDEP dependency list ------------------ +$(F)hello$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + hello.cpp diff --git a/idasdk75/plugins/hexview/hexplace.cpp b/idasdk76/plugins/hexview/hexplace.cpp similarity index 100% rename from idasdk75/plugins/hexview/hexplace.cpp rename to idasdk76/plugins/hexview/hexplace.cpp diff --git a/idasdk75/plugins/hexview/hexview.cpp b/idasdk76/plugins/hexview/hexview.cpp similarity index 100% rename from idasdk75/plugins/hexview/hexview.cpp rename to idasdk76/plugins/hexview/hexview.cpp diff --git a/idasdk76/plugins/hexview/makefile b/idasdk76/plugins/hexview/makefile new file mode 100644 index 0000000..cc84756 --- /dev/null +++ b/idasdk76/plugins/hexview/makefile @@ -0,0 +1,11 @@ +PROC=hexview + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)hexview$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + hexplace.cpp hexview.cpp diff --git a/idasdk76/plugins/highlighter/highlighter.cpp b/idasdk76/plugins/highlighter/highlighter.cpp new file mode 100644 index 0000000..b2aee3c --- /dev/null +++ b/idasdk76/plugins/highlighter/highlighter.cpp @@ -0,0 +1,193 @@ +// Highlighter plugin v1.0 +// Highlights executed instructions + +// This plugin will display a colored box at the executed instructions. +// It will take into account only the instructions where the application +// has been suspended. + +// http://www.hexblog.com/2005/11/the_highlighter.html + +// Copyright 2005 Ilfak Guilfanov, <ig@hexblog.com> + +#include <ida.hpp> +#include <idp.hpp> +#include <dbg.hpp> +#include <loader.hpp> +#include <kernwin.hpp> + +//-------------------------------------------------------------------------- +struct plugin_ctx_t; +struct idd_post_events_t : public post_event_visitor_t +{ + plugin_ctx_t &ctx; + idd_post_events_t(plugin_ctx_t &_ctx) : ctx(_ctx) {} + virtual ssize_t idaapi handle_post_event( + ssize_t code, + int notification_code, + va_list va) override; +}; + +//-------------------------------------------------------------------------- +struct exec_prefix_t : public user_defined_prefix_t +{ + static const int prefix_width = 1; + + plugin_ctx_t &ctx; + exec_prefix_t(plugin_ctx_t &_ctx) + : user_defined_prefix_t(prefix_width, &_ctx), ctx(_ctx) {} + + virtual void idaapi get_user_defined_prefix( + qstring *out, + ea_t ea, + const insn_t &insn, + int lnnum, + int indent, + const char *line) override; +}; + +//-------------------------------------------------------------------------- +typedef std::set<ea_t> easet_t; +struct plugin_ctx_t : public plugmod_t, public event_listener_t +{ + idd_post_events_t idd_post_events = idd_post_events_t(*this); + + exec_prefix_t *exec_prefix = nullptr; + + // List of executed addresses + easet_t execset; + + ea_t old_ea = BADADDR; + int old_lnnum = 0; + + plugin_ctx_t() + { + hook_event_listener(HT_DBG, this); + } + ~plugin_ctx_t() + { + // listeners are uninstalled automatically + // when the owner module is unloaded + exec_prefix = nullptr; // make lint happy + } + + virtual bool idaapi run(size_t) override; + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; +}; + +//-------------------------------------------------------------------------- +// A sample how to generate user-defined line prefixes +static const char highlight_prefix[] = { COLOR_INV, ' ', COLOR_INV, 0 }; +void idaapi exec_prefix_t::get_user_defined_prefix( + qstring *buf, + ea_t ea, + const insn_t &, + int lnnum, + int indent, + const char *line) +{ + buf->qclear(); // empty prefix by default + + // We want to display the prefix only the lines which + // contain the instruction itself + + if ( indent != -1 ) + return; // a directive + if ( line[0] == '\0' ) + return; // empty line + if ( tag_advance(line,1)[-1] == ASH.cmnt[0] ) + return; // comment line... + + // We don't want the prefix to be printed again for other lines of the + // same instruction/data. For that we remember the line number + // and compare it before generating the prefix + + if ( ctx.old_ea == ea && ctx.old_lnnum == lnnum ) + return; + + if ( ctx.execset.find(ea) != ctx.execset.end() ) + *buf = highlight_prefix; + + // Remember the address and line number we produced the line prefix for: + ctx.old_ea = ea; + ctx.old_lnnum = lnnum; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi idd_post_events_t::handle_post_event( + ssize_t retcode, + int notification_code, + va_list va) +{ + switch ( notification_code ) + { + case debugger_t::ev_get_debug_event: + { + gdecode_t *code = va_arg(va, gdecode_t *); + debug_event_t *event = va_arg(va, debug_event_t *); + if ( *code == GDE_ONE_EVENT ) // got an event? + ctx.execset.insert(event->ea); + } + break; + } + return retcode; +} + +//-------------------------------------------------------------------------- +bool idaapi plugin_ctx_t::run(size_t) +{ + info("AUTOHIDE NONE\n" + "This is the highlighter plugin.\n" + "It highlights executed instructions if a debug event occurs at them.\n" + "The plugins is fully automatic and has no parameters.\n"); + return true; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list /*va*/) +{ + // We set our debug event handler at the beginning and remove it at the end + // of a debug session + switch ( code ) + { + case dbg_process_start: + case dbg_process_attach: + exec_prefix = new exec_prefix_t(*this); + register_post_event_visitor(HT_IDD, &idd_post_events, this); + break; + case dbg_process_exit: + // do not unregister idd_post_events - it should be removed automatically + delete exec_prefix; + exec_prefix = nullptr; + execset.clear(); + break; + } + return 0; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +static const char wanted_name[] = "Highlighter"; +static const char wanted_hotkey[] = ""; + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel + init, // initialize + nullptr, + nullptr, + wanted_name, // long comment about the plugin + wanted_name, // multiline help about the plugin + wanted_name, // the preferred short name of the plugin + wanted_hotkey, // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/highlighter/makefile b/idasdk76/plugins/highlighter/makefile new file mode 100644 index 0000000..6016025 --- /dev/null +++ b/idasdk76/plugins/highlighter/makefile @@ -0,0 +1,11 @@ +PROC=highlighter + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)highlighter$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp highlighter.cpp diff --git a/idasdk75/plugins/ht_output/ht_output.cpp b/idasdk76/plugins/ht_output/ht_output.cpp similarity index 100% rename from idasdk75/plugins/ht_output/ht_output.cpp rename to idasdk76/plugins/ht_output/ht_output.cpp diff --git a/idasdk76/plugins/ht_output/makefile b/idasdk76/plugins/ht_output/makefile new file mode 100644 index 0000000..cb1f4c3 --- /dev/null +++ b/idasdk76/plugins/ht_output/makefile @@ -0,0 +1,11 @@ +PROC=ht_output + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ht_output$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + ht_output.cpp diff --git a/idasdk75/plugins/ht_view/ht_view.cpp b/idasdk76/plugins/ht_view/ht_view.cpp similarity index 100% rename from idasdk75/plugins/ht_view/ht_view.cpp rename to idasdk76/plugins/ht_view/ht_view.cpp diff --git a/idasdk76/plugins/ht_view/makefile b/idasdk76/plugins/ht_view/makefile new file mode 100644 index 0000000..9be07cc --- /dev/null +++ b/idasdk76/plugins/ht_view/makefile @@ -0,0 +1,11 @@ +PROC=ht_view + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ht_view$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ht_view.cpp diff --git a/idasdk76/plugins/makefile b/idasdk76/plugins/makefile new file mode 100644 index 0000000..39f6d31 --- /dev/null +++ b/idasdk76/plugins/makefile @@ -0,0 +1,70 @@ +include ../allmake.mak + +GOALS += plugins +GOALS += samples +ifeq ($(or $(IDAHOME),$(DEMO_OR_FREE)),) + GOALS += examples +endif +.PHONY: $(GOALS) +all: $(GOALS) + +#---------------------------------------------------------------------- +PLUGINS += callee +PLUGINS += callgraph +PLUGINS += choose +PLUGINS += findcrypt2 +PLUGINS += ht_output +PLUGINS += ht_view +PLUGINS += pdb +PLUGINS += tracing_api +PLUGINS += uiswitch +PLUGINS-$(__NT__) += uunp +PLUGINS += $(PLUGINS-1) +plugins: $(PLUGINS) + +#---------------------------------------------------------------------- +SAMPLES += custdata +SAMPLES += custview +SAMPLES += formchooser +SAMPLES += formsample +SAMPLES += funclist +SAMPLES += getlines +SAMPLES += hexview +SAMPLES += mtsample +SAMPLES += openform +SAMPLES += procext +SAMPLES += ugraph +SAMPLES += ugraph3 +SAMPLES += vcsample +samples: $(SAMPLES) + +#---------------------------------------------------------------------- +# Note: examples are not installed in the plugins/ directory by default. +# to install them there, run 'make' from the plugin subdirectory. +# to uninstall the plugin afterwards, run 'make uninstall' from +# the plugin subdirectory or 'make examples_uninstall' from the +# 'plugins' directory. +HAS_QT := $(call ls,$(QTDIR)) +EXAMPLES += ex_debidc +EXAMPLES += ex_events1 +EXAMPLES += script_plg +EXAMPLES-$(HAS_QT) += qproject +EXAMPLES-$(HAS_QT) += qwindow +# do not include ugraph2 in the samples because it is buggy: +# in some cases it combines blocks in such a way that switching to +# graph view becomes impossible +EXAMPLES += ugraph2 +# the z80dbg plugin will conflict with functionality already submitted +# to the z80 processor module, so we don't install it +EXAMPLES += z80dbg +EXAMPLES += $(EXAMPLES-1) +examples: $(EXAMPLES) + +#---------------------------------------------------------------------- +.PHONY: $(PLUGINS) $(SAMPLES) $(EXAMPLES) +$(PLUGINS) $(SAMPLES) $(EXAMPLES): + $(Q)$(MAKE) -C $@ + +#---------------------------------------------------------------------- +clean:: + $(foreach dir,$(PLUGINS) $(SAMPLES) $(EXAMPLES),$(MAKE) -C $(dir) clean;) diff --git a/idasdk76/plugins/mtsample/makefile b/idasdk76/plugins/mtsample/makefile new file mode 100644 index 0000000..e020135 --- /dev/null +++ b/idasdk76/plugins/mtsample/makefile @@ -0,0 +1,11 @@ +PROC=mtsample + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)mtsample$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + mtsample.cpp diff --git a/idasdk75/plugins/mtsample/mtsample.cpp b/idasdk76/plugins/mtsample/mtsample.cpp similarity index 100% rename from idasdk75/plugins/mtsample/mtsample.cpp rename to idasdk76/plugins/mtsample/mtsample.cpp diff --git a/idasdk76/plugins/navcolor/makefile b/idasdk76/plugins/navcolor/makefile new file mode 100644 index 0000000..27e76ca --- /dev/null +++ b/idasdk76/plugins/navcolor/makefile @@ -0,0 +1,11 @@ +PROC=navcolor + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)navcolor$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + navcolor.cpp diff --git a/idasdk75/plugins/navcolor/navcolor.cpp b/idasdk76/plugins/navcolor/navcolor.cpp similarity index 100% rename from idasdk75/plugins/navcolor/navcolor.cpp rename to idasdk76/plugins/navcolor/navcolor.cpp diff --git a/idasdk76/plugins/openform/makefile b/idasdk76/plugins/openform/makefile new file mode 100644 index 0000000..0694733 --- /dev/null +++ b/idasdk76/plugins/openform/makefile @@ -0,0 +1,11 @@ +PROC=openform + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)openform$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + openform.cpp diff --git a/idasdk75/plugins/openform/openform.cpp b/idasdk76/plugins/openform/openform.cpp similarity index 100% rename from idasdk75/plugins/openform/openform.cpp rename to idasdk76/plugins/openform/openform.cpp diff --git a/idasdk76/plugins/pdb/common.cpp b/idasdk76/plugins/pdb/common.cpp new file mode 100644 index 0000000..098b441 --- /dev/null +++ b/idasdk76/plugins/pdb/common.cpp @@ -0,0 +1,2546 @@ + +#include "pdbaccess.hpp" + +//---------------------------------------------------------------------------- +static const char g_spath_prefix[] = "srv*"; +static const char g_spath_suffix[] = "*http://msdl.microsoft.com/download/symbols"; + +//---------------------------------------------------------------------------- +HRESULT pdb_access_t::iterate_subtags( + pdb_sym_t &sym, + enum SymTagEnum type, + children_visitor_t &visitor) +{ + struct subtag_helper_t : children_visitor_t + { + pdb_access_t *tb; + enum SymTagEnum type; + children_visitor_t &visitor; + virtual HRESULT visit_child(pdb_sym_t &_sym) override + { + return tb->iterate_children(_sym, type, visitor); + } + subtag_helper_t(pdb_access_t *_tb, enum SymTagEnum t, children_visitor_t &_visitor) + : tb(_tb), + type(t), + visitor(_visitor) {} + }; + subtag_helper_t helper(this, type, visitor); + return iterate_children(sym, SymTagCompiland, helper); +} + +//---------------------------------------------------------------------------- +HRESULT pdb_access_t::iterate_children( + pdb_sym_t &sym, + enum SymTagEnum type, + children_visitor_t &visitor) +{ + visitor.parent = &sym; + return do_iterate_children(sym, type, visitor); +} + +//---------------------------------------------------------------------- +void print_pdb_register(qstring *out, int machine, int reg) +{ + // Register subset shared by all processor types, + switch ( reg ) + { + case CV_ALLREG_ERR: *out = "[*err*]"; return; + case CV_ALLREG_TEB: *out = "[*teb*]"; return; + case CV_ALLREG_TIMER: *out = "[*timer*]"; return; + case CV_ALLREG_EFAD1: *out = "[*efad1*]"; return; + case CV_ALLREG_EFAD2: *out = "[*efad2*]"; return; + case CV_ALLREG_EFAD3: *out = "[*efad3*]"; return; + case CV_ALLREG_VFRAME: *out = "[*vframe*]"; return; + case CV_ALLREG_HANDLE: *out = "[*handle*]"; return; + case CV_ALLREG_PARAMS: *out = "[*params*]"; return; + case CV_ALLREG_LOCALS: *out = "[*locals*]"; return; + case CV_ALLREG_TID: *out = "[*tid*]"; return; + case CV_ALLREG_ENV: *out = "[*env*]"; return; + case CV_ALLREG_CMDLN: *out = "[*cmdln*]"; return; + } + + // Processor specific subsets + switch ( machine ) + { + case CV_CFL_8080: + case CV_CFL_8086: + case CV_CFL_80286: + case CV_CFL_80386: + case CV_CFL_80486: + case CV_CFL_PENTIUM: + case CV_CFL_PENTIUMII: + case CV_CFL_PENTIUMIII: + // Register set for the Intel 80x86 and ix86 processor series + // (plus PCODE registers) + switch ( reg ) + { + case CV_REG_NONE: *out = "none"; return; + case CV_REG_AL: *out = "al"; return; + case CV_REG_CL: *out = "cl"; return; + case CV_REG_DL: *out = "dl"; return; + case CV_REG_BL: *out = "bl"; return; + case CV_REG_AH: *out = "ah"; return; + case CV_REG_CH: *out = "ch"; return; + case CV_REG_DH: *out = "dh"; return; + case CV_REG_BH: *out = "bh"; return; + case CV_REG_AX: *out = "ax"; return; + case CV_REG_CX: *out = "cx"; return; + case CV_REG_DX: *out = "dx"; return; + case CV_REG_BX: *out = "bx"; return; + case CV_REG_SP: *out = "sp"; return; + case CV_REG_BP: *out = "bp"; return; + case CV_REG_SI: *out = "si"; return; + case CV_REG_DI: *out = "di"; return; + case CV_REG_EAX: *out = "eax"; return; + case CV_REG_ECX: *out = "ecx"; return; + case CV_REG_EDX: *out = "edx"; return; + case CV_REG_EBX: *out = "ebx"; return; + case CV_REG_ESP: *out = "esp"; return; + case CV_REG_EBP: *out = "ebp"; return; + case CV_REG_ESI: *out = "esi"; return; + case CV_REG_EDI: *out = "edi"; return; + case CV_REG_ES: *out = "es"; return; + case CV_REG_CS: *out = "cs"; return; + case CV_REG_SS: *out = "ss"; return; + case CV_REG_DS: *out = "ds"; return; + case CV_REG_FS: *out = "fs"; return; + case CV_REG_GS: *out = "gs"; return; + case CV_REG_IP: *out = "ip"; return; + case CV_REG_FLAGS: *out = "flags"; return; + case CV_REG_EIP: *out = "eip"; return; + case CV_REG_EFLAGS: *out = "eflags"; return; + case CV_REG_TEMP: *out = "temp"; return; // PCODE Temp return; + case CV_REG_TEMPH: *out = "temph"; return; // PCODE TempH return; + case CV_REG_QUOTE: *out = "quote"; return; // PCODE Quote return; + case CV_REG_PCDR3: *out = "pcdr3"; return; // PCODE reserved return; + case CV_REG_PCDR4: *out = "pcdr4"; return; // PCODE reserved return; + case CV_REG_PCDR5: *out = "pcdr5"; return; // PCODE reserved return; + case CV_REG_PCDR6: *out = "pcdr6"; return; // PCODE reserved return; + case CV_REG_PCDR7: *out = "pcdr7"; return; // PCODE reserved return; + case CV_REG_CR0: *out = "cr0"; return; // CR0 -- control registers return; + case CV_REG_CR1: *out = "cr1"; return; + case CV_REG_CR2: *out = "cr2"; return; + case CV_REG_CR3: *out = "cr3"; return; + case CV_REG_CR4: *out = "cr4"; return; // Pentium return; + case CV_REG_DR0: *out = "dr0"; return; // Debug register return; + case CV_REG_DR1: *out = "dr1"; return; + case CV_REG_DR2: *out = "dr2"; return; + case CV_REG_DR3: *out = "dr3"; return; + case CV_REG_DR4: *out = "dr4"; return; + case CV_REG_DR5: *out = "dr5"; return; + case CV_REG_DR6: *out = "dr6"; return; + case CV_REG_DR7: *out = "dr7"; return; + case CV_REG_GDTR: *out = "gdtr"; return; + case CV_REG_GDTL: *out = "gdtl"; return; + case CV_REG_IDTR: *out = "idtr"; return; + case CV_REG_IDTL: *out = "idtl"; return; + case CV_REG_LDTR: *out = "ldtr"; return; + case CV_REG_TR: *out = "tr"; return; + + case CV_REG_PSEUDO1: *out = "pseudo1"; return; + case CV_REG_PSEUDO2: *out = "pseudo2"; return; + case CV_REG_PSEUDO3: *out = "pseudo3"; return; + case CV_REG_PSEUDO4: *out = "pseudo4"; return; + case CV_REG_PSEUDO5: *out = "pseudo5"; return; + case CV_REG_PSEUDO6: *out = "pseudo6"; return; + case CV_REG_PSEUDO7: *out = "pseudo7"; return; + case CV_REG_PSEUDO8: *out = "pseudo8"; return; + case CV_REG_PSEUDO9: *out = "pseudo9"; return; + + case CV_REG_ST0: *out = "st0"; return; + case CV_REG_ST1: *out = "st1"; return; + case CV_REG_ST2: *out = "st2"; return; + case CV_REG_ST3: *out = "st3"; return; + case CV_REG_ST4: *out = "st4"; return; + case CV_REG_ST5: *out = "st5"; return; + case CV_REG_ST6: *out = "st6"; return; + case CV_REG_ST7: *out = "st7"; return; + case CV_REG_CTRL: *out = "ctrl"; return; + case CV_REG_STAT: *out = "stat"; return; + case CV_REG_TAG: *out = "tag"; return; + case CV_REG_FPIP: *out = "fpip"; return; + case CV_REG_FPCS: *out = "fpcs"; return; + case CV_REG_FPDO: *out = "fpdo"; return; + case CV_REG_FPDS: *out = "fpds"; return; + case CV_REG_ISEM: *out = "isem"; return; + case CV_REG_FPEIP: *out = "fpeip"; return; + case CV_REG_FPEDO: *out = "fpedo"; return; + + case CV_REG_MM0: *out = "mm0"; return; + case CV_REG_MM1: *out = "mm1"; return; + case CV_REG_MM2: *out = "mm2"; return; + case CV_REG_MM3: *out = "mm3"; return; + case CV_REG_MM4: *out = "mm4"; return; + case CV_REG_MM5: *out = "mm5"; return; + case CV_REG_MM6: *out = "mm6"; return; + case CV_REG_MM7: *out = "mm7"; return; + + case CV_REG_XMM0: *out = "xmm0"; return; // KATMAI registers return; + case CV_REG_XMM1: *out = "xmm1"; return; + case CV_REG_XMM2: *out = "xmm2"; return; + case CV_REG_XMM3: *out = "xmm3"; return; + case CV_REG_XMM4: *out = "xmm4"; return; + case CV_REG_XMM5: *out = "xmm5"; return; + case CV_REG_XMM6: *out = "xmm6"; return; + case CV_REG_XMM7: *out = "xmm7"; return; + + case CV_REG_XMM00: *out = "xmm00"; return; // KATMAI sub-registers return; + case CV_REG_XMM01: *out = "xmm01"; return; + case CV_REG_XMM02: *out = "xmm02"; return; + case CV_REG_XMM03: *out = "xmm03"; return; + case CV_REG_XMM10: *out = "xmm10"; return; + case CV_REG_XMM11: *out = "xmm11"; return; + case CV_REG_XMM12: *out = "xmm12"; return; + case CV_REG_XMM13: *out = "xmm13"; return; + case CV_REG_XMM20: *out = "xmm20"; return; + case CV_REG_XMM21: *out = "xmm21"; return; + case CV_REG_XMM22: *out = "xmm22"; return; + case CV_REG_XMM23: *out = "xmm23"; return; + case CV_REG_XMM30: *out = "xmm30"; return; + case CV_REG_XMM31: *out = "xmm31"; return; + case CV_REG_XMM32: *out = "xmm32"; return; + case CV_REG_XMM33: *out = "xmm33"; return; + case CV_REG_XMM40: *out = "xmm40"; return; + case CV_REG_XMM41: *out = "xmm41"; return; + case CV_REG_XMM42: *out = "xmm42"; return; + case CV_REG_XMM43: *out = "xmm43"; return; + case CV_REG_XMM50: *out = "xmm50"; return; + case CV_REG_XMM51: *out = "xmm51"; return; + case CV_REG_XMM52: *out = "xmm52"; return; + case CV_REG_XMM53: *out = "xmm53"; return; + case CV_REG_XMM60: *out = "xmm60"; return; + case CV_REG_XMM61: *out = "xmm61"; return; + case CV_REG_XMM62: *out = "xmm62"; return; + case CV_REG_XMM63: *out = "xmm63"; return; + case CV_REG_XMM70: *out = "xmm70"; return; + case CV_REG_XMM71: *out = "xmm71"; return; + case CV_REG_XMM72: *out = "xmm72"; return; + case CV_REG_XMM73: *out = "xmm73"; return; + + case CV_REG_XMM0L: *out = "xmm0l"; return; + case CV_REG_XMM1L: *out = "xmm1l"; return; + case CV_REG_XMM2L: *out = "xmm2l"; return; + case CV_REG_XMM3L: *out = "xmm3l"; return; + case CV_REG_XMM4L: *out = "xmm4l"; return; + case CV_REG_XMM5L: *out = "xmm5l"; return; + case CV_REG_XMM6L: *out = "xmm6l"; return; + case CV_REG_XMM7L: *out = "xmm7l"; return; + + case CV_REG_XMM0H: *out = "xmm0h"; return; + case CV_REG_XMM1H: *out = "xmm1h"; return; + case CV_REG_XMM2H: *out = "xmm2h"; return; + case CV_REG_XMM3H: *out = "xmm3h"; return; + case CV_REG_XMM4H: *out = "xmm4h"; return; + case CV_REG_XMM5H: *out = "xmm5h"; return; + case CV_REG_XMM6H: *out = "xmm6h"; return; + case CV_REG_XMM7H: *out = "xmm7h"; return; + + case CV_REG_MXCSR: *out = "mxcsr"; return; // XMM status register + + case CV_REG_EDXEAX: *out = "edxeax"; return; // EDX";EAX pair + + case CV_REG_EMM0L: *out = "emm0l"; return; // XMM sub-registers (WNI integer) + case CV_REG_EMM1L: *out = "emm1l"; return; + case CV_REG_EMM2L: *out = "emm2l"; return; + case CV_REG_EMM3L: *out = "emm3l"; return; + case CV_REG_EMM4L: *out = "emm4l"; return; + case CV_REG_EMM5L: *out = "emm5l"; return; + case CV_REG_EMM6L: *out = "emm6l"; return; + case CV_REG_EMM7L: *out = "emm7l"; return; + + case CV_REG_EMM0H: *out = "emm0h"; return; + case CV_REG_EMM1H: *out = "emm1h"; return; + case CV_REG_EMM2H: *out = "emm2h"; return; + case CV_REG_EMM3H: *out = "emm3h"; return; + case CV_REG_EMM4H: *out = "emm4h"; return; + case CV_REG_EMM5H: *out = "emm5h"; return; + case CV_REG_EMM6H: *out = "emm6h"; return; + case CV_REG_EMM7H: *out = "emm7h"; return; + + + case CV_REG_MM00: *out = "mm00"; return; // do not change the order of these regs, first one must be even too + case CV_REG_MM01: *out = "mm01"; return; + case CV_REG_MM10: *out = "mm10"; return; + case CV_REG_MM11: *out = "mm11"; return; + case CV_REG_MM20: *out = "mm20"; return; + case CV_REG_MM21: *out = "mm21"; return; + case CV_REG_MM30: *out = "mm30"; return; + case CV_REG_MM31: *out = "mm31"; return; + case CV_REG_MM40: *out = "mm40"; return; + case CV_REG_MM41: *out = "mm41"; return; + case CV_REG_MM50: *out = "mm50"; return; + case CV_REG_MM51: *out = "mm51"; return; + case CV_REG_MM60: *out = "mm60"; return; + case CV_REG_MM61: *out = "mm61"; return; + case CV_REG_MM70: *out = "mm70"; return; + case CV_REG_MM71: *out = "mm71"; return; + } + break; + + // registers for the 68K processors + case CV_CFL_M68000: + case CV_CFL_M68010: + case CV_CFL_M68020: + case CV_CFL_M68030: + case CV_CFL_M68040: + switch ( reg ) + { + case CV_R68_D0: *out = "D0"; return; + case CV_R68_D1: *out = "D1"; return; + case CV_R68_D2: *out = "D2"; return; + case CV_R68_D3: *out = "D3"; return; + case CV_R68_D4: *out = "D4"; return; + case CV_R68_D5: *out = "D5"; return; + case CV_R68_D6: *out = "D6"; return; + case CV_R68_D7: *out = "D7"; return; + case CV_R68_A0: *out = "A0"; return; + case CV_R68_A1: *out = "A1"; return; + case CV_R68_A2: *out = "A2"; return; + case CV_R68_A3: *out = "A3"; return; + case CV_R68_A4: *out = "A4"; return; + case CV_R68_A5: *out = "A5"; return; + case CV_R68_A6: *out = "A6"; return; + case CV_R68_A7: *out = "A7"; return; + case CV_R68_CCR: *out = "CCR"; return; + case CV_R68_SR: *out = "SR"; return; + case CV_R68_USP: *out = "USP"; return; + case CV_R68_MSP: *out = "MSP"; return; + case CV_R68_SFC: *out = "SFC"; return; + case CV_R68_DFC: *out = "DFC"; return; + case CV_R68_CACR: *out = "CACR"; return; + case CV_R68_VBR: *out = "VBR"; return; + case CV_R68_CAAR: *out = "CAAR"; return; + case CV_R68_ISP: *out = "ISP"; return; + case CV_R68_PC: *out = "PC"; return; + // reserved 27 + case CV_R68_FPCR: *out = "FPCR"; return; + case CV_R68_FPSR: *out = "FPSR"; return; + case CV_R68_FPIAR: *out = "FPIAR"; return; + // reserved 31 + case CV_R68_FP0: *out = "FP0"; return; + case CV_R68_FP1: *out = "FP1"; return; + case CV_R68_FP2: *out = "FP2"; return; + case CV_R68_FP3: *out = "FP3"; return; + case CV_R68_FP4: *out = "FP4"; return; + case CV_R68_FP5: *out = "FP5"; return; + case CV_R68_FP6: *out = "FP6"; return; + case CV_R68_FP7: *out = "FP7"; return; + // reserved 40 + case CV_R68_MMUSR030:*out = "MMUSR030"; return; + case CV_R68_MMUSR: *out = "MMUSR"; return; + case CV_R68_URP: *out = "URP"; return; + case CV_R68_DTT0: *out = "DTT0"; return; + case CV_R68_DTT1: *out = "DTT1"; return; + case CV_R68_ITT0: *out = "ITT0"; return; + case CV_R68_ITT1: *out = "ITT1"; return; + // reserved 50 + case CV_R68_PSR: *out = "PSR"; return; + case CV_R68_PCSR: *out = "PCSR"; return; + case CV_R68_VAL: *out = "VAL"; return; + case CV_R68_CRP: *out = "CRP"; return; + case CV_R68_SRP: *out = "SRP"; return; + case CV_R68_DRP: *out = "DRP"; return; + case CV_R68_TC: *out = "TC"; return; + case CV_R68_AC: *out = "AC"; return; + case CV_R68_SCC: *out = "SCC"; return; + case CV_R68_CAL: *out = "CAL"; return; + case CV_R68_TT0: *out = "TT0"; return; + case CV_R68_TT1: *out = "TT1"; return; + // reserved 63 + case CV_R68_BAD0: *out = "BAD0"; return; + case CV_R68_BAD1: *out = "BAD1"; return; + case CV_R68_BAD2: *out = "BAD2"; return; + case CV_R68_BAD3: *out = "BAD3"; return; + case CV_R68_BAD4: *out = "BAD4"; return; + case CV_R68_BAD5: *out = "BAD5"; return; + case CV_R68_BAD6: *out = "BAD6"; return; + case CV_R68_BAD7: *out = "BAD7"; return; + case CV_R68_BAC0: *out = "BAC0"; return; + case CV_R68_BAC1: *out = "BAC1"; return; + case CV_R68_BAC2: *out = "BAC2"; return; + case CV_R68_BAC3: *out = "BAC3"; return; + case CV_R68_BAC4: *out = "BAC4"; return; + case CV_R68_BAC5: *out = "BAC5"; return; + case CV_R68_BAC6: *out = "BAC6"; return; + case CV_R68_BAC7: *out = "BAC7"; return; + } + break; + + case CV_CFL_MIPS: + case CV_CFL_MIPS16: + case CV_CFL_MIPS32: + case CV_CFL_MIPS64: + case CV_CFL_MIPSI: + case CV_CFL_MIPSII: + case CV_CFL_MIPSIII: + case CV_CFL_MIPSIV: + case CV_CFL_MIPSV: + switch ( reg ) + { + // Register set for the MIPS 4000 + case CV_M4_NOREG: *out = "NOREG"; return; + case CV_M4_IntZERO: *out = "IntZERO"; return; /* CPU REGISTER */ + case CV_M4_IntAT: *out = "IntAT"; return; + case CV_M4_IntV0: *out = "IntV0"; return; + case CV_M4_IntV1: *out = "IntV1"; return; + case CV_M4_IntA0: *out = "IntA0"; return; + case CV_M4_IntA1: *out = "IntA1"; return; + case CV_M4_IntA2: *out = "IntA2"; return; + case CV_M4_IntA3: *out = "IntA3"; return; + case CV_M4_IntT0: *out = "IntT0"; return; + case CV_M4_IntT1: *out = "IntT1"; return; + case CV_M4_IntT2: *out = "IntT2"; return; + case CV_M4_IntT3: *out = "IntT3"; return; + case CV_M4_IntT4: *out = "IntT4"; return; + case CV_M4_IntT5: *out = "IntT5"; return; + case CV_M4_IntT6: *out = "IntT6"; return; + case CV_M4_IntT7: *out = "IntT7"; return; + case CV_M4_IntS0: *out = "IntS0"; return; + case CV_M4_IntS1: *out = "IntS1"; return; + case CV_M4_IntS2: *out = "IntS2"; return; + case CV_M4_IntS3: *out = "IntS3"; return; + case CV_M4_IntS4: *out = "IntS4"; return; + case CV_M4_IntS5: *out = "IntS5"; return; + case CV_M4_IntS6: *out = "IntS6"; return; + case CV_M4_IntS7: *out = "IntS7"; return; + case CV_M4_IntT8: *out = "IntT8"; return; + case CV_M4_IntT9: *out = "IntT9"; return; + case CV_M4_IntKT0: *out = "IntKT0"; return; + case CV_M4_IntKT1: *out = "IntKT1"; return; + case CV_M4_IntGP: *out = "IntGP"; return; + case CV_M4_IntSP: *out = "IntSP"; return; + case CV_M4_IntS8: *out = "IntS8"; return; + case CV_M4_IntRA: *out = "IntRA"; return; + case CV_M4_IntLO: *out = "IntLO"; return; + case CV_M4_IntHI: *out = "IntHI"; return; + + case CV_M4_Fir: + case CV_M4_Psr: + + case CV_M4_FltF0: *out = "FltF0"; return; /* Floating point registers */ + case CV_M4_FltF1: *out = "FltF1"; return; + case CV_M4_FltF2: *out = "FltF2"; return; + case CV_M4_FltF3: *out = "FltF3"; return; + case CV_M4_FltF4: *out = "FltF4"; return; + case CV_M4_FltF5: *out = "FltF5"; return; + case CV_M4_FltF6: *out = "FltF6"; return; + case CV_M4_FltF7: *out = "FltF7"; return; + case CV_M4_FltF8: *out = "FltF8"; return; + case CV_M4_FltF9: *out = "FltF9"; return; + case CV_M4_FltF10: *out = "FltF10"; return; + case CV_M4_FltF11: *out = "FltF11"; return; + case CV_M4_FltF12: *out = "FltF12"; return; + case CV_M4_FltF13: *out = "FltF13"; return; + case CV_M4_FltF14: *out = "FltF14"; return; + case CV_M4_FltF15: *out = "FltF15"; return; + case CV_M4_FltF16: *out = "FltF16"; return; + case CV_M4_FltF17: *out = "FltF17"; return; + case CV_M4_FltF18: *out = "FltF18"; return; + case CV_M4_FltF19: *out = "FltF19"; return; + case CV_M4_FltF20: *out = "FltF20"; return; + case CV_M4_FltF21: *out = "FltF21"; return; + case CV_M4_FltF22: *out = "FltF22"; return; + case CV_M4_FltF23: *out = "FltF23"; return; + case CV_M4_FltF24: *out = "FltF24"; return; + case CV_M4_FltF25: *out = "FltF25"; return; + case CV_M4_FltF26: *out = "FltF26"; return; + case CV_M4_FltF27: *out = "FltF27"; return; + case CV_M4_FltF28: *out = "FltF28"; return; + case CV_M4_FltF29: *out = "FltF29"; return; + case CV_M4_FltF30: *out = "FltF30"; return; + case CV_M4_FltF31: *out = "FltF31"; return; + case CV_M4_FltFsr: *out = "FltFsr"; return; + } + break; + + case CV_CFL_ALPHA: +// case CV_CFL_ALPHA_21064: + case CV_CFL_ALPHA_21164: + case CV_CFL_ALPHA_21164A: + case CV_CFL_ALPHA_21264: + case CV_CFL_ALPHA_21364: + // Register set for the ALPHA AXP + switch ( reg ) + { + case CV_ALPHA_NOREG: *out = "NOREG"; return; + case CV_ALPHA_FltF0: *out = "FltF0"; return; // Floating point registers + case CV_ALPHA_FltF1: *out = "FltF1"; return; + case CV_ALPHA_FltF2: *out = "FltF2"; return; + case CV_ALPHA_FltF3: *out = "FltF3"; return; + case CV_ALPHA_FltF4: *out = "FltF4"; return; + case CV_ALPHA_FltF5: *out = "FltF5"; return; + case CV_ALPHA_FltF6: *out = "FltF6"; return; + case CV_ALPHA_FltF7: *out = "FltF7"; return; + case CV_ALPHA_FltF8: *out = "FltF8"; return; + case CV_ALPHA_FltF9: *out = "FltF9"; return; + case CV_ALPHA_FltF10:*out = "FltF10"; return; + case CV_ALPHA_FltF11:*out = "FltF11"; return; + case CV_ALPHA_FltF12:*out = "FltF12"; return; + case CV_ALPHA_FltF13:*out = "FltF13"; return; + case CV_ALPHA_FltF14:*out = "FltF14"; return; + case CV_ALPHA_FltF15:*out = "FltF15"; return; + case CV_ALPHA_FltF16:*out = "FltF16"; return; + case CV_ALPHA_FltF17:*out = "FltF17"; return; + case CV_ALPHA_FltF18:*out = "FltF18"; return; + case CV_ALPHA_FltF19:*out = "FltF19"; return; + case CV_ALPHA_FltF20:*out = "FltF20"; return; + case CV_ALPHA_FltF21:*out = "FltF21"; return; + case CV_ALPHA_FltF22:*out = "FltF22"; return; + case CV_ALPHA_FltF23:*out = "FltF23"; return; + case CV_ALPHA_FltF24:*out = "FltF24"; return; + case CV_ALPHA_FltF25:*out = "FltF25"; return; + case CV_ALPHA_FltF26:*out = "FltF26"; return; + case CV_ALPHA_FltF27:*out = "FltF27"; return; + case CV_ALPHA_FltF28:*out = "FltF28"; return; + case CV_ALPHA_FltF29:*out = "FltF29"; return; + case CV_ALPHA_FltF30:*out = "FltF30"; return; + case CV_ALPHA_FltF31:*out = "FltF31"; return; + + case CV_ALPHA_IntV0: *out = "IntV0"; return; // Integer registers + case CV_ALPHA_IntT0: *out = "IntT0"; return; + case CV_ALPHA_IntT1: *out = "IntT1"; return; + case CV_ALPHA_IntT2: *out = "IntT2"; return; + case CV_ALPHA_IntT3: *out = "IntT3"; return; + case CV_ALPHA_IntT4: *out = "IntT4"; return; + case CV_ALPHA_IntT5: *out = "IntT5"; return; + case CV_ALPHA_IntT6: *out = "IntT6"; return; + case CV_ALPHA_IntT7: *out = "IntT7"; return; + case CV_ALPHA_IntS0: *out = "IntS0"; return; + case CV_ALPHA_IntS1: *out = "IntS1"; return; + case CV_ALPHA_IntS2: *out = "IntS2"; return; + case CV_ALPHA_IntS3: *out = "IntS3"; return; + case CV_ALPHA_IntS4: *out = "IntS4"; return; + case CV_ALPHA_IntS5: *out = "IntS5"; return; + case CV_ALPHA_IntFP: *out = "IntFP"; return; + case CV_ALPHA_IntA0: *out = "IntA0"; return; + case CV_ALPHA_IntA1: *out = "IntA1"; return; + case CV_ALPHA_IntA2: *out = "IntA2"; return; + case CV_ALPHA_IntA3: *out = "IntA3"; return; + case CV_ALPHA_IntA4: *out = "IntA4"; return; + case CV_ALPHA_IntA5: *out = "IntA5"; return; + case CV_ALPHA_IntT8: *out = "IntT8"; return; + case CV_ALPHA_IntT9: *out = "IntT9"; return; + case CV_ALPHA_IntT10:*out = "IntT10"; return; + case CV_ALPHA_IntT11:*out = "IntT11"; return; + case CV_ALPHA_IntRA: *out = "IntRA"; return; + case CV_ALPHA_IntT12:*out = "IntT12"; return; + case CV_ALPHA_IntAT: *out = "IntAT"; return; + case CV_ALPHA_IntGP: *out = "IntGP"; return; + case CV_ALPHA_IntSP: *out = "IntSP"; return; + case CV_ALPHA_IntZERO:*out = "IntZERO"; return; + + case CV_ALPHA_Fpcr: *out = "Fpcr"; return; // Control registers + case CV_ALPHA_Fir: *out = "Fir"; return; + case CV_ALPHA_Psr: *out = "Psr"; return; + case CV_ALPHA_FltFsr:*out = "FltFsr"; return; + case CV_ALPHA_SoftFpcr:*out = "SoftFpcr"; return; + } + break; + + case CV_CFL_PPC601: + case CV_CFL_PPC603: + case CV_CFL_PPC604: + case CV_CFL_PPC620: + case CV_CFL_PPCFP: + case CV_CFL_PPCBE: + // Register Set for Motorola/IBM PowerPC + switch ( reg ) + { + /* + ** PowerPC General Registers ( User Level ) + */ + case CV_PPC_GPR0: *out = "gpr0"; return; + case CV_PPC_GPR1: *out = "gpr1"; return; + case CV_PPC_GPR2: *out = "gpr2"; return; + case CV_PPC_GPR3: *out = "gpr3"; return; + case CV_PPC_GPR4: *out = "gpr4"; return; + case CV_PPC_GPR5: *out = "gpr5"; return; + case CV_PPC_GPR6: *out = "gpr6"; return; + case CV_PPC_GPR7: *out = "gpr7"; return; + case CV_PPC_GPR8: *out = "gpr8"; return; + case CV_PPC_GPR9: *out = "gpr9"; return; + case CV_PPC_GPR10: *out = "gpr10"; return; + case CV_PPC_GPR11: *out = "gpr11"; return; + case CV_PPC_GPR12: *out = "gpr12"; return; + case CV_PPC_GPR13: *out = "gpr13"; return; + case CV_PPC_GPR14: *out = "gpr14"; return; + case CV_PPC_GPR15: *out = "gpr15"; return; + case CV_PPC_GPR16: *out = "gpr16"; return; + case CV_PPC_GPR17: *out = "gpr17"; return; + case CV_PPC_GPR18: *out = "gpr18"; return; + case CV_PPC_GPR19: *out = "gpr19"; return; + case CV_PPC_GPR20: *out = "gpr20"; return; + case CV_PPC_GPR21: *out = "gpr21"; return; + case CV_PPC_GPR22: *out = "gpr22"; return; + case CV_PPC_GPR23: *out = "gpr23"; return; + case CV_PPC_GPR24: *out = "gpr24"; return; + case CV_PPC_GPR25: *out = "gpr25"; return; + case CV_PPC_GPR26: *out = "gpr26"; return; + case CV_PPC_GPR27: *out = "gpr27"; return; + case CV_PPC_GPR28: *out = "gpr28"; return; + case CV_PPC_GPR29: *out = "gpr29"; return; + case CV_PPC_GPR30: *out = "gpr30"; return; + case CV_PPC_GPR31: *out = "gpr31"; return; + + /* + ** PowerPC Condition Register ( user level ) + */ + case CV_PPC_CR: *out = "cr"; return; + case CV_PPC_CR0: *out = "cr0"; return; + case CV_PPC_CR1: *out = "cr1"; return; + case CV_PPC_CR2: *out = "cr2"; return; + case CV_PPC_CR3: *out = "cr3"; return; + case CV_PPC_CR4: *out = "cr4"; return; + case CV_PPC_CR5: *out = "cr5"; return; + case CV_PPC_CR6: *out = "cr6"; return; + case CV_PPC_CR7: *out = "cr7"; return; + + /* + ** PowerPC Floating Point Registers ( user Level ) + */ + case CV_PPC_FPR0: *out = "fpr0"; return; + case CV_PPC_FPR1: *out = "fpr1"; return; + case CV_PPC_FPR2: *out = "fpr2"; return; + case CV_PPC_FPR3: *out = "fpr3"; return; + case CV_PPC_FPR4: *out = "fpr4"; return; + case CV_PPC_FPR5: *out = "fpr5"; return; + case CV_PPC_FPR6: *out = "fpr6"; return; + case CV_PPC_FPR7: *out = "fpr7"; return; + case CV_PPC_FPR8: *out = "fpr8"; return; + case CV_PPC_FPR9: *out = "fpr9"; return; + case CV_PPC_FPR10: *out = "fpr10"; return; + case CV_PPC_FPR11: *out = "fpr11"; return; + case CV_PPC_FPR12: *out = "fpr12"; return; + case CV_PPC_FPR13: *out = "fpr13"; return; + case CV_PPC_FPR14: *out = "fpr14"; return; + case CV_PPC_FPR15: *out = "fpr15"; return; + case CV_PPC_FPR16: *out = "fpr16"; return; + case CV_PPC_FPR17: *out = "fpr17"; return; + case CV_PPC_FPR18: *out = "fpr18"; return; + case CV_PPC_FPR19: *out = "fpr19"; return; + case CV_PPC_FPR20: *out = "fpr20"; return; + case CV_PPC_FPR21: *out = "fpr21"; return; + case CV_PPC_FPR22: *out = "fpr22"; return; + case CV_PPC_FPR23: *out = "fpr23"; return; + case CV_PPC_FPR24: *out = "fpr24"; return; + case CV_PPC_FPR25: *out = "fpr25"; return; + case CV_PPC_FPR26: *out = "fpr26"; return; + case CV_PPC_FPR27: *out = "fpr27"; return; + case CV_PPC_FPR28: *out = "fpr28"; return; + case CV_PPC_FPR29: *out = "fpr29"; return; + case CV_PPC_FPR30: *out = "fpr30"; return; + case CV_PPC_FPR31: *out = "fpr31"; return; + + /* + ** PowerPC Floating Point Status and Control Register ( User Level ) + */ + case CV_PPC_FPSCR: *out = "FPSCR"; return; + + /* + ** PowerPC Machine State Register ( Supervisor Level ) + */ + case CV_PPC_MSR: *out = "msr"; return; + + /* + ** PowerPC Segment Registers ( Supervisor Level ) + */ + case CV_PPC_SR0: *out = "sr0"; return; + case CV_PPC_SR1: *out = "sr1"; return; + case CV_PPC_SR2: *out = "sr2"; return; + case CV_PPC_SR3: *out = "sr3"; return; + case CV_PPC_SR4: *out = "sr4"; return; + case CV_PPC_SR5: *out = "sr5"; return; + case CV_PPC_SR6: *out = "sr6"; return; + case CV_PPC_SR7: *out = "sr7"; return; + case CV_PPC_SR8: *out = "sr8"; return; + case CV_PPC_SR9: *out = "sr9"; return; + case CV_PPC_SR10: *out = "sr10"; return; + case CV_PPC_SR11: *out = "sr11"; return; + case CV_PPC_SR12: *out = "sr12"; return; + case CV_PPC_SR13: *out = "sr13"; return; + case CV_PPC_SR14: *out = "sr14"; return; + case CV_PPC_SR15: *out = "sr15"; return; + + /* + ** For all of the special purpose registers add 100 to the SPR# that the + ** Motorola/IBM documentation gives with the exception of any imaginary + ** registers. + */ + + /* + ** PowerPC Special Purpose Registers ( User Level ) + */ + case CV_PPC_PC: *out = "pc"; return; // PC (imaginary register) + + case CV_PPC_MQ: *out = "mq"; return; // MPC601 + case CV_PPC_XER: *out = "xer"; return; + case CV_PPC_RTCU: *out = "rtcu"; return; // MPC601 + case CV_PPC_RTCL: *out = "rtcl"; return; // MPC601 + case CV_PPC_LR: *out = "lr"; return; + case CV_PPC_CTR: *out = "ctr"; return; + + case CV_PPC_COMPARE: *out = "compare"; return;// part of XER (internal to the debugger only) + case CV_PPC_COUNT: *out = "count"; return;// part of XER (internal to the debugger only) + + /* + ** PowerPC Special Purpose Registers ( supervisor Level ) + */ + case CV_PPC_DSISR: *out = "dsisr"; return; + case CV_PPC_DAR: *out = "dar"; return; + case CV_PPC_DEC: *out = "dec"; return; + case CV_PPC_SDR1: *out = "sdr1"; return; + case CV_PPC_SRR0: *out = "srr0"; return; + case CV_PPC_SRR1: *out = "srr1"; return; + case CV_PPC_SPRG0: *out = "sprg0"; return; + case CV_PPC_SPRG1: *out = "sprg1"; return; + case CV_PPC_SPRG2: *out = "sprg2"; return; + case CV_PPC_SPRG3: *out = "sprg3"; return; + case CV_PPC_ASR: *out = "asr"; return;// 64-bit implementations only + case CV_PPC_EAR: *out = "ear"; return; + case CV_PPC_PVR: *out = "pvr"; return; + case CV_PPC_BAT0U: *out = "bat0u"; return; + case CV_PPC_BAT0L: *out = "bat0l"; return; + case CV_PPC_BAT1U: *out = "bat1u"; return; + case CV_PPC_BAT1L: *out = "bat1l"; return; + case CV_PPC_BAT2U: *out = "bat2u"; return; + case CV_PPC_BAT2L: *out = "bat2l"; return; + case CV_PPC_BAT3U: *out = "bat3u"; return; + case CV_PPC_BAT3L: *out = "bat3l"; return; + case CV_PPC_DBAT0U: *out = "dbat0u"; return; + case CV_PPC_DBAT0L: *out = "dbat0l"; return; + case CV_PPC_DBAT1U: *out = "dbat1u"; return; + case CV_PPC_DBAT1L: *out = "dbat1l"; return; + case CV_PPC_DBAT2U: *out = "dbat2u"; return; + case CV_PPC_DBAT2L: *out = "dbat2l"; return; + case CV_PPC_DBAT3U: *out = "dbat3u"; return; + case CV_PPC_DBAT3L: *out = "dbat3l"; return; + + /* + ** PowerPC Special Purpose Registers implementation Dependent ( Supervisor Level ) + */ + + /* + ** Doesn't appear that IBM/Motorola has finished defining these. + */ + + case CV_PPC_PMR0: *out = "pmr0"; return;// MPC620, + case CV_PPC_PMR1: *out = "pmr1"; return;// MPC620, + case CV_PPC_PMR2: *out = "pmr2"; return;// MPC620, + case CV_PPC_PMR3: *out = "pmr3"; return;// MPC620, + case CV_PPC_PMR4: *out = "pmr4"; return;// MPC620, + case CV_PPC_PMR5: *out = "pmr5"; return;// MPC620, + case CV_PPC_PMR6: *out = "pmr6"; return;// MPC620, + case CV_PPC_PMR7: *out = "pmr7"; return;// MPC620, + case CV_PPC_PMR8: *out = "pmr8"; return;// MPC620, + case CV_PPC_PMR9: *out = "pmr9"; return;// MPC620, + case CV_PPC_PMR10: *out = "pmr10"; return;// MPC620, + case CV_PPC_PMR11: *out = "pmr11"; return;// MPC620, + case CV_PPC_PMR12: *out = "pmr12"; return;// MPC620, + case CV_PPC_PMR13: *out = "pmr13"; return;// MPC620, + case CV_PPC_PMR14: *out = "pmr14"; return;// MPC620, + case CV_PPC_PMR15: *out = "pmr15"; return;// MPC620, + + case CV_PPC_DMISS: *out = "dmiss"; return;// MPC603 + case CV_PPC_DCMP: *out = "dcmp"; return;// MPC603 + case CV_PPC_HASH1: *out = "hash1"; return;// MPC603 + case CV_PPC_HASH2: *out = "hash2"; return;// MPC603 + case CV_PPC_IMISS: *out = "imiss"; return;// MPC603 + case CV_PPC_ICMP: *out = "icmp"; return;// MPC603 + case CV_PPC_RPA: *out = "rpa"; return;// MPC603 + + case CV_PPC_HID0: *out = "hid0"; return;// MPC601, MPC603, MPC620 + case CV_PPC_HID1: *out = "hid1"; return;// MPC601 + case CV_PPC_HID2: *out = "hid2"; return;// MPC601, MPC603, MPC620 ( IABR ) + case CV_PPC_HID3: *out = "hid3"; return;// Not Defined + case CV_PPC_HID4: *out = "hid4"; return;// Not Defined + case CV_PPC_HID5: *out = "hid5"; return;// MPC601, MPC604, MPC620 ( DABR ) + case CV_PPC_HID6: *out = "hid6"; return;// Not Defined + case CV_PPC_HID7: *out = "hid7"; return;// Not Defined + case CV_PPC_HID8: *out = "hid8"; return;// MPC620 ( BUSCSR ) + case CV_PPC_HID9: *out = "hid9"; return;// MPC620 ( L2CSR ) + case CV_PPC_HID10: *out = "hid10"; return;// Not Defined + case CV_PPC_HID11: *out = "hid11"; return;// Not Defined + case CV_PPC_HID12: *out = "hid12"; return;// Not Defined + case CV_PPC_HID13: *out = "hid13"; return;// MPC604 ( HCR ) + case CV_PPC_HID14: *out = "hid14"; return;// Not Defined + case CV_PPC_HID15: *out = "hid15"; return;// MPC601, MPC604, MPC620 ( PIR ) + } + break; + + // + // JAVA VM registers + // + + // case CV_JAVA_PC: *out = "PC"; return; + + case CV_CFL_SH3: + case CV_CFL_SH3E: + case CV_CFL_SH3DSP: + case CV_CFL_SH4: + // + // Register set for the Hitachi SH3 + // + switch ( reg ) + { + case CV_SH3_NOREG: *out = "NOREG"; return; + + case CV_SH3_IntR0: *out = "IntR0"; return;// CPU REGISTER + case CV_SH3_IntR1: *out = "IntR1"; return; + case CV_SH3_IntR2: *out = "IntR2"; return; + case CV_SH3_IntR3: *out = "IntR3"; return; + case CV_SH3_IntR4: *out = "IntR4"; return; + case CV_SH3_IntR5: *out = "IntR5"; return; + case CV_SH3_IntR6: *out = "IntR6"; return; + case CV_SH3_IntR7: *out = "IntR7"; return; + case CV_SH3_IntR8: *out = "IntR8"; return; + case CV_SH3_IntR9: *out = "IntR9"; return; + case CV_SH3_IntR10: *out = "IntR10"; return; + case CV_SH3_IntR11: *out = "IntR11"; return; + case CV_SH3_IntR12: *out = "IntR12"; return; + case CV_SH3_IntR13: *out = "IntR13"; return; + case CV_SH3_IntFp: *out = "IntFp"; return; + case CV_SH3_IntSp: *out = "IntSp"; return; + case CV_SH3_Gbr: *out = "Gbr"; return; + case CV_SH3_Pr: *out = "Pr"; return; + case CV_SH3_Mach: *out = "Mach"; return; + case CV_SH3_Macl: *out = "Macl"; return; + + case CV_SH3_Pc: *out = "Pc"; return; + case CV_SH3_Sr: *out = "Sr"; return; + + case CV_SH3_BarA: *out = "BarA"; return; + case CV_SH3_BasrA: *out = "BasrA"; return; + case CV_SH3_BamrA: *out = "BamrA"; return; + case CV_SH3_BbrA: *out = "BbrA"; return; + case CV_SH3_BarB: *out = "BarB"; return; + case CV_SH3_BasrB: *out = "BasrB"; return; + case CV_SH3_BamrB: *out = "BamrB"; return; + case CV_SH3_BbrB: *out = "BbrB"; return; + case CV_SH3_BdrB: *out = "BdrB"; return; + case CV_SH3_BdmrB: *out = "BdmrB"; return; + case CV_SH3_Brcr: *out = "Brcr"; return; + + // + // Additional registers for Hitachi SH processors + // + + case CV_SH_Fpscr: *out = "Fpscr"; return;// floating point status/control register + case CV_SH_Fpul: *out = "Fpul"; return;// floating point communication register + + case CV_SH_FpR0: *out = "FpR0"; return;// Floating point registers + case CV_SH_FpR1: *out = "FpR1"; return; + case CV_SH_FpR2: *out = "FpR2"; return; + case CV_SH_FpR3: *out = "FpR3"; return; + case CV_SH_FpR4: *out = "FpR4"; return; + case CV_SH_FpR5: *out = "FpR5"; return; + case CV_SH_FpR6: *out = "FpR6"; return; + case CV_SH_FpR7: *out = "FpR7"; return; + case CV_SH_FpR8: *out = "FpR8"; return; + case CV_SH_FpR9: *out = "FpR9"; return; + case CV_SH_FpR10: *out = "FpR10"; return; + case CV_SH_FpR11: *out = "FpR11"; return; + case CV_SH_FpR12: *out = "FpR12"; return; + case CV_SH_FpR13: *out = "FpR13"; return; + case CV_SH_FpR14: *out = "FpR14"; return; + case CV_SH_FpR15: *out = "FpR15"; return; + + case CV_SH_XFpR0: *out = "XFpR0"; return; + case CV_SH_XFpR1: *out = "XFpR1"; return; + case CV_SH_XFpR2: *out = "XFpR2"; return; + case CV_SH_XFpR3: *out = "XFpR3"; return; + case CV_SH_XFpR4: *out = "XFpR4"; return; + case CV_SH_XFpR5: *out = "XFpR5"; return; + case CV_SH_XFpR6: *out = "XFpR6"; return; + case CV_SH_XFpR7: *out = "XFpR7"; return; + case CV_SH_XFpR8: *out = "XFpR8"; return; + case CV_SH_XFpR9: *out = "XFpR9"; return; + case CV_SH_XFpR10: *out = "XFpR10"; return; + case CV_SH_XFpR11: *out = "XFpR11"; return; + case CV_SH_XFpR12: *out = "XFpR12"; return; + case CV_SH_XFpR13: *out = "XFpR13"; return; + case CV_SH_XFpR14: *out = "XFpR14"; return; + case CV_SH_XFpR15: *out = "XFpR15"; return; + } + break; + + case CV_CFL_ARM3: + case CV_CFL_ARM4: + case CV_CFL_ARM4T: + case CV_CFL_ARM5: + case CV_CFL_ARM5T: + case CV_CFL_ARM6: + case CV_CFL_ARM_XMAC: + case CV_CFL_ARM_WMMX: + case CV_CFL_THUMB: + // + // Register set for the ARM processor. + // + switch ( reg ) + { + case CV_ARM_NOREG: *out = "noreg"; return; + case CV_ARM_R0: *out = "r0"; return; + case CV_ARM_R1: *out = "r1"; return; + case CV_ARM_R2: *out = "r2"; return; + case CV_ARM_R3: *out = "r3"; return; + case CV_ARM_R4: *out = "r4"; return; + case CV_ARM_R5: *out = "r5"; return; + case CV_ARM_R6: *out = "r6"; return; + case CV_ARM_R7: *out = "r7"; return; + case CV_ARM_R8: *out = "r8"; return; + case CV_ARM_R9: *out = "r9"; return; + case CV_ARM_R10: *out = "r10"; return; + case CV_ARM_R11: *out = "r11"; return;// Frame pointer, if allocated + case CV_ARM_R12: *out = "r12"; return; + case CV_ARM_SP: *out = "sp"; return;// Stack pointer + case CV_ARM_LR: *out = "lr"; return;// Link Register + case CV_ARM_PC: *out = "pc"; return;// Program counter + case CV_ARM_CPSR: *out = "cpsr"; return;// Current program status register + } + break; + + case CV_CFL_IA64: +// case CV_CFL_IA64_1: + case CV_CFL_IA64_2: + // + // Register set for Intel IA64 + // + switch ( reg ) + { + case CV_IA64_NOREG: *out = "noreg"; return; + + // Branch Registers + + case CV_IA64_Br0: *out = "br0"; return; + case CV_IA64_Br1: *out = "br1"; return; + case CV_IA64_Br2: *out = "br2"; return; + case CV_IA64_Br3: *out = "br3"; return; + case CV_IA64_Br4: *out = "br4"; return; + case CV_IA64_Br5: *out = "br5"; return; + case CV_IA64_Br6: *out = "br6"; return; + case CV_IA64_Br7: *out = "br7"; return; + + // Predicate Registers + + case CV_IA64_P0: *out = "p0"; return; + case CV_IA64_P1: *out = "p1"; return; + case CV_IA64_P2: *out = "p2"; return; + case CV_IA64_P3: *out = "p3"; return; + case CV_IA64_P4: *out = "p4"; return; + case CV_IA64_P5: *out = "p5"; return; + case CV_IA64_P6: *out = "p6"; return; + case CV_IA64_P7: *out = "p7"; return; + case CV_IA64_P8: *out = "p8"; return; + case CV_IA64_P9: *out = "p9"; return; + case CV_IA64_P10: *out = "p10"; return; + case CV_IA64_P11: *out = "p11"; return; + case CV_IA64_P12: *out = "p12"; return; + case CV_IA64_P13: *out = "p13"; return; + case CV_IA64_P14: *out = "p14"; return; + case CV_IA64_P15: *out = "p15"; return; + case CV_IA64_P16: *out = "p16"; return; + case CV_IA64_P17: *out = "p17"; return; + case CV_IA64_P18: *out = "p18"; return; + case CV_IA64_P19: *out = "p19"; return; + case CV_IA64_P20: *out = "p20"; return; + case CV_IA64_P21: *out = "p21"; return; + case CV_IA64_P22: *out = "p22"; return; + case CV_IA64_P23: *out = "p23"; return; + case CV_IA64_P24: *out = "p24"; return; + case CV_IA64_P25: *out = "p25"; return; + case CV_IA64_P26: *out = "p26"; return; + case CV_IA64_P27: *out = "p27"; return; + case CV_IA64_P28: *out = "p28"; return; + case CV_IA64_P29: *out = "p29"; return; + case CV_IA64_P30: *out = "p30"; return; + case CV_IA64_P31: *out = "p31"; return; + case CV_IA64_P32: *out = "p32"; return; + case CV_IA64_P33: *out = "p33"; return; + case CV_IA64_P34: *out = "p34"; return; + case CV_IA64_P35: *out = "p35"; return; + case CV_IA64_P36: *out = "p36"; return; + case CV_IA64_P37: *out = "p37"; return; + case CV_IA64_P38: *out = "p38"; return; + case CV_IA64_P39: *out = "p39"; return; + case CV_IA64_P40: *out = "p40"; return; + case CV_IA64_P41: *out = "p41"; return; + case CV_IA64_P42: *out = "p42"; return; + case CV_IA64_P43: *out = "p43"; return; + case CV_IA64_P44: *out = "p44"; return; + case CV_IA64_P45: *out = "p45"; return; + case CV_IA64_P46: *out = "p46"; return; + case CV_IA64_P47: *out = "p47"; return; + case CV_IA64_P48: *out = "p48"; return; + case CV_IA64_P49: *out = "p49"; return; + case CV_IA64_P50: *out = "p50"; return; + case CV_IA64_P51: *out = "p51"; return; + case CV_IA64_P52: *out = "p52"; return; + case CV_IA64_P53: *out = "p53"; return; + case CV_IA64_P54: *out = "p54"; return; + case CV_IA64_P55: *out = "p55"; return; + case CV_IA64_P56: *out = "p56"; return; + case CV_IA64_P57: *out = "p57"; return; + case CV_IA64_P58: *out = "p58"; return; + case CV_IA64_P59: *out = "p59"; return; + case CV_IA64_P60: *out = "p60"; return; + case CV_IA64_P61: *out = "p61"; return; + case CV_IA64_P62: *out = "p62"; return; + case CV_IA64_P63: *out = "p63"; return; + + case CV_IA64_Preds: *out = "Preds"; return; + + // Banked General Registers + + case CV_IA64_IntH0: *out = "IntH0"; return; + case CV_IA64_IntH1: *out = "IntH1"; return; + case CV_IA64_IntH2: *out = "IntH2"; return; + case CV_IA64_IntH3: *out = "IntH3"; return; + case CV_IA64_IntH4: *out = "IntH4"; return; + case CV_IA64_IntH5: *out = "IntH5"; return; + case CV_IA64_IntH6: *out = "IntH6"; return; + case CV_IA64_IntH7: *out = "IntH7"; return; + case CV_IA64_IntH8: *out = "IntH8"; return; + case CV_IA64_IntH9: *out = "IntH9"; return; + case CV_IA64_IntH10: *out = "IntH10"; return; + case CV_IA64_IntH11: *out = "IntH11"; return; + case CV_IA64_IntH12: *out = "IntH12"; return; + case CV_IA64_IntH13: *out = "IntH13"; return; + case CV_IA64_IntH14: *out = "IntH14"; return; + case CV_IA64_IntH15: *out = "IntH15"; return; + + // Special Registers + + case CV_IA64_Ip: *out = "Ip"; return; + case CV_IA64_Umask: *out = "Umask"; return; + case CV_IA64_Cfm: *out = "Cfm"; return; + case CV_IA64_Psr: *out = "Psr"; return; + + // Banked General Registers + + case CV_IA64_Nats: *out = "Nats"; return; + case CV_IA64_Nats2: *out = "Nats2"; return; + case CV_IA64_Nats3: *out = "Nats3"; return; + + // General-Purpose Registers + + // Integer registers + case CV_IA64_IntR0: *out = "IntR0"; return; + case CV_IA64_IntR1: *out = "IntR1"; return; + case CV_IA64_IntR2: *out = "IntR2"; return; + case CV_IA64_IntR3: *out = "IntR3"; return; + case CV_IA64_IntR4: *out = "IntR4"; return; + case CV_IA64_IntR5: *out = "IntR5"; return; + case CV_IA64_IntR6: *out = "IntR6"; return; + case CV_IA64_IntR7: *out = "IntR7"; return; + case CV_IA64_IntR8: *out = "IntR8"; return; + case CV_IA64_IntR9: *out = "IntR9"; return; + case CV_IA64_IntR10: *out = "IntR10"; return; + case CV_IA64_IntR11: *out = "IntR11"; return; + case CV_IA64_IntR12: *out = "IntR12"; return; + case CV_IA64_IntR13: *out = "IntR13"; return; + case CV_IA64_IntR14: *out = "IntR14"; return; + case CV_IA64_IntR15: *out = "IntR15"; return; + case CV_IA64_IntR16: *out = "IntR16"; return; + case CV_IA64_IntR17: *out = "IntR17"; return; + case CV_IA64_IntR18: *out = "IntR18"; return; + case CV_IA64_IntR19: *out = "IntR19"; return; + case CV_IA64_IntR20: *out = "IntR20"; return; + case CV_IA64_IntR21: *out = "IntR21"; return; + case CV_IA64_IntR22: *out = "IntR22"; return; + case CV_IA64_IntR23: *out = "IntR23"; return; + case CV_IA64_IntR24: *out = "IntR24"; return; + case CV_IA64_IntR25: *out = "IntR25"; return; + case CV_IA64_IntR26: *out = "IntR26"; return; + case CV_IA64_IntR27: *out = "IntR27"; return; + case CV_IA64_IntR28: *out = "IntR28"; return; + case CV_IA64_IntR29: *out = "IntR29"; return; + case CV_IA64_IntR30: *out = "IntR30"; return; + case CV_IA64_IntR31: *out = "IntR31"; return; + + // Register Stack + case CV_IA64_IntR32: *out = "IntR32"; return; + case CV_IA64_IntR33: *out = "IntR33"; return; + case CV_IA64_IntR34: *out = "IntR34"; return; + case CV_IA64_IntR35: *out = "IntR35"; return; + case CV_IA64_IntR36: *out = "IntR36"; return; + case CV_IA64_IntR37: *out = "IntR37"; return; + case CV_IA64_IntR38: *out = "IntR38"; return; + case CV_IA64_IntR39: *out = "IntR39"; return; + case CV_IA64_IntR40: *out = "IntR40"; return; + case CV_IA64_IntR41: *out = "IntR41"; return; + case CV_IA64_IntR42: *out = "IntR42"; return; + case CV_IA64_IntR43: *out = "IntR43"; return; + case CV_IA64_IntR44: *out = "IntR44"; return; + case CV_IA64_IntR45: *out = "IntR45"; return; + case CV_IA64_IntR46: *out = "IntR46"; return; + case CV_IA64_IntR47: *out = "IntR47"; return; + case CV_IA64_IntR48: *out = "IntR48"; return; + case CV_IA64_IntR49: *out = "IntR49"; return; + case CV_IA64_IntR50: *out = "IntR50"; return; + case CV_IA64_IntR51: *out = "IntR51"; return; + case CV_IA64_IntR52: *out = "IntR52"; return; + case CV_IA64_IntR53: *out = "IntR53"; return; + case CV_IA64_IntR54: *out = "IntR54"; return; + case CV_IA64_IntR55: *out = "IntR55"; return; + case CV_IA64_IntR56: *out = "IntR56"; return; + case CV_IA64_IntR57: *out = "IntR57"; return; + case CV_IA64_IntR58: *out = "IntR58"; return; + case CV_IA64_IntR59: *out = "IntR59"; return; + case CV_IA64_IntR60: *out = "IntR60"; return; + case CV_IA64_IntR61: *out = "IntR61"; return; + case CV_IA64_IntR62: *out = "IntR62"; return; + case CV_IA64_IntR63: *out = "IntR63"; return; + case CV_IA64_IntR64: *out = "IntR64"; return; + case CV_IA64_IntR65: *out = "IntR65"; return; + case CV_IA64_IntR66: *out = "IntR66"; return; + case CV_IA64_IntR67: *out = "IntR67"; return; + case CV_IA64_IntR68: *out = "IntR68"; return; + case CV_IA64_IntR69: *out = "IntR69"; return; + case CV_IA64_IntR70: *out = "IntR70"; return; + case CV_IA64_IntR71: *out = "IntR71"; return; + case CV_IA64_IntR72: *out = "IntR72"; return; + case CV_IA64_IntR73: *out = "IntR73"; return; + case CV_IA64_IntR74: *out = "IntR74"; return; + case CV_IA64_IntR75: *out = "IntR75"; return; + case CV_IA64_IntR76: *out = "IntR76"; return; + case CV_IA64_IntR77: *out = "IntR77"; return; + case CV_IA64_IntR78: *out = "IntR78"; return; + case CV_IA64_IntR79: *out = "IntR79"; return; + case CV_IA64_IntR80: *out = "IntR80"; return; + case CV_IA64_IntR81: *out = "IntR81"; return; + case CV_IA64_IntR82: *out = "IntR82"; return; + case CV_IA64_IntR83: *out = "IntR83"; return; + case CV_IA64_IntR84: *out = "IntR84"; return; + case CV_IA64_IntR85: *out = "IntR85"; return; + case CV_IA64_IntR86: *out = "IntR86"; return; + case CV_IA64_IntR87: *out = "IntR87"; return; + case CV_IA64_IntR88: *out = "IntR88"; return; + case CV_IA64_IntR89: *out = "IntR89"; return; + case CV_IA64_IntR90: *out = "IntR90"; return; + case CV_IA64_IntR91: *out = "IntR91"; return; + case CV_IA64_IntR92: *out = "IntR92"; return; + case CV_IA64_IntR93: *out = "IntR93"; return; + case CV_IA64_IntR94: *out = "IntR94"; return; + case CV_IA64_IntR95: *out = "IntR95"; return; + case CV_IA64_IntR96: *out = "IntR96"; return; + case CV_IA64_IntR97: *out = "IntR97"; return; + case CV_IA64_IntR98: *out = "IntR98"; return; + case CV_IA64_IntR99: *out = "IntR99"; return; + case CV_IA64_IntR100:*out = "IntR100"; return; + case CV_IA64_IntR101:*out = "IntR101"; return; + case CV_IA64_IntR102:*out = "IntR102"; return; + case CV_IA64_IntR103:*out = "IntR103"; return; + case CV_IA64_IntR104:*out = "IntR104"; return; + case CV_IA64_IntR105:*out = "IntR105"; return; + case CV_IA64_IntR106:*out = "IntR106"; return; + case CV_IA64_IntR107:*out = "IntR107"; return; + case CV_IA64_IntR108:*out = "IntR108"; return; + case CV_IA64_IntR109:*out = "IntR109"; return; + case CV_IA64_IntR110:*out = "IntR110"; return; + case CV_IA64_IntR111:*out = "IntR111"; return; + case CV_IA64_IntR112:*out = "IntR112"; return; + case CV_IA64_IntR113:*out = "IntR113"; return; + case CV_IA64_IntR114:*out = "IntR114"; return; + case CV_IA64_IntR115:*out = "IntR115"; return; + case CV_IA64_IntR116:*out = "IntR116"; return; + case CV_IA64_IntR117:*out = "IntR117"; return; + case CV_IA64_IntR118:*out = "IntR118"; return; + case CV_IA64_IntR119:*out = "IntR119"; return; + case CV_IA64_IntR120:*out = "IntR120"; return; + case CV_IA64_IntR121:*out = "IntR121"; return; + case CV_IA64_IntR122:*out = "IntR122"; return; + case CV_IA64_IntR123:*out = "IntR123"; return; + case CV_IA64_IntR124:*out = "IntR124"; return; + case CV_IA64_IntR125:*out = "IntR125"; return; + case CV_IA64_IntR126:*out = "IntR126"; return; + case CV_IA64_IntR127:*out = "IntR127"; return; + + // Floating-Point Registers + + // Low Floating Point Registers + case CV_IA64_FltF0: *out = "FltF0"; return; + case CV_IA64_FltF1: *out = "FltF1"; return; + case CV_IA64_FltF2: *out = "FltF2"; return; + case CV_IA64_FltF3: *out = "FltF3"; return; + case CV_IA64_FltF4: *out = "FltF4"; return; + case CV_IA64_FltF5: *out = "FltF5"; return; + case CV_IA64_FltF6: *out = "FltF6"; return; + case CV_IA64_FltF7: *out = "FltF7"; return; + case CV_IA64_FltF8: *out = "FltF8"; return; + case CV_IA64_FltF9: *out = "FltF9"; return; + case CV_IA64_FltF10: *out = "FltF10"; return; + case CV_IA64_FltF11: *out = "FltF11"; return; + case CV_IA64_FltF12: *out = "FltF12"; return; + case CV_IA64_FltF13: *out = "FltF13"; return; + case CV_IA64_FltF14: *out = "FltF14"; return; + case CV_IA64_FltF15: *out = "FltF15"; return; + case CV_IA64_FltF16: *out = "FltF16"; return; + case CV_IA64_FltF17: *out = "FltF17"; return; + case CV_IA64_FltF18: *out = "FltF18"; return; + case CV_IA64_FltF19: *out = "FltF19"; return; + case CV_IA64_FltF20: *out = "FltF20"; return; + case CV_IA64_FltF21: *out = "FltF21"; return; + case CV_IA64_FltF22: *out = "FltF22"; return; + case CV_IA64_FltF23: *out = "FltF23"; return; + case CV_IA64_FltF24: *out = "FltF24"; return; + case CV_IA64_FltF25: *out = "FltF25"; return; + case CV_IA64_FltF26: *out = "FltF26"; return; + case CV_IA64_FltF27: *out = "FltF27"; return; + case CV_IA64_FltF28: *out = "FltF28"; return; + case CV_IA64_FltF29: *out = "FltF29"; return; + case CV_IA64_FltF30: *out = "FltF30"; return; + case CV_IA64_FltF31: *out = "FltF31"; return; + + // High Floating Point Registers + case CV_IA64_FltF32: *out = "FltF32"; return; + case CV_IA64_FltF33: *out = "FltF33"; return; + case CV_IA64_FltF34: *out = "FltF34"; return; + case CV_IA64_FltF35: *out = "FltF35"; return; + case CV_IA64_FltF36: *out = "FltF36"; return; + case CV_IA64_FltF37: *out = "FltF37"; return; + case CV_IA64_FltF38: *out = "FltF38"; return; + case CV_IA64_FltF39: *out = "FltF39"; return; + case CV_IA64_FltF40: *out = "FltF40"; return; + case CV_IA64_FltF41: *out = "FltF41"; return; + case CV_IA64_FltF42: *out = "FltF42"; return; + case CV_IA64_FltF43: *out = "FltF43"; return; + case CV_IA64_FltF44: *out = "FltF44"; return; + case CV_IA64_FltF45: *out = "FltF45"; return; + case CV_IA64_FltF46: *out = "FltF46"; return; + case CV_IA64_FltF47: *out = "FltF47"; return; + case CV_IA64_FltF48: *out = "FltF48"; return; + case CV_IA64_FltF49: *out = "FltF49"; return; + case CV_IA64_FltF50: *out = "FltF50"; return; + case CV_IA64_FltF51: *out = "FltF51"; return; + case CV_IA64_FltF52: *out = "FltF52"; return; + case CV_IA64_FltF53: *out = "FltF53"; return; + case CV_IA64_FltF54: *out = "FltF54"; return; + case CV_IA64_FltF55: *out = "FltF55"; return; + case CV_IA64_FltF56: *out = "FltF56"; return; + case CV_IA64_FltF57: *out = "FltF57"; return; + case CV_IA64_FltF58: *out = "FltF58"; return; + case CV_IA64_FltF59: *out = "FltF59"; return; + case CV_IA64_FltF60: *out = "FltF60"; return; + case CV_IA64_FltF61: *out = "FltF61"; return; + case CV_IA64_FltF62: *out = "FltF62"; return; + case CV_IA64_FltF63: *out = "FltF63"; return; + case CV_IA64_FltF64: *out = "FltF64"; return; + case CV_IA64_FltF65: *out = "FltF65"; return; + case CV_IA64_FltF66: *out = "FltF66"; return; + case CV_IA64_FltF67: *out = "FltF67"; return; + case CV_IA64_FltF68: *out = "FltF68"; return; + case CV_IA64_FltF69: *out = "FltF69"; return; + case CV_IA64_FltF70: *out = "FltF70"; return; + case CV_IA64_FltF71: *out = "FltF71"; return; + case CV_IA64_FltF72: *out = "FltF72"; return; + case CV_IA64_FltF73: *out = "FltF73"; return; + case CV_IA64_FltF74: *out = "FltF74"; return; + case CV_IA64_FltF75: *out = "FltF75"; return; + case CV_IA64_FltF76: *out = "FltF76"; return; + case CV_IA64_FltF77: *out = "FltF77"; return; + case CV_IA64_FltF78: *out = "FltF78"; return; + case CV_IA64_FltF79: *out = "FltF79"; return; + case CV_IA64_FltF80: *out = "FltF80"; return; + case CV_IA64_FltF81: *out = "FltF81"; return; + case CV_IA64_FltF82: *out = "FltF82"; return; + case CV_IA64_FltF83: *out = "FltF83"; return; + case CV_IA64_FltF84: *out = "FltF84"; return; + case CV_IA64_FltF85: *out = "FltF85"; return; + case CV_IA64_FltF86: *out = "FltF86"; return; + case CV_IA64_FltF87: *out = "FltF87"; return; + case CV_IA64_FltF88: *out = "FltF88"; return; + case CV_IA64_FltF89: *out = "FltF89"; return; + case CV_IA64_FltF90: *out = "FltF90"; return; + case CV_IA64_FltF91: *out = "FltF91"; return; + case CV_IA64_FltF92: *out = "FltF92"; return; + case CV_IA64_FltF93: *out = "FltF93"; return; + case CV_IA64_FltF94: *out = "FltF94"; return; + case CV_IA64_FltF95: *out = "FltF95"; return; + case CV_IA64_FltF96: *out = "FltF96"; return; + case CV_IA64_FltF97: *out = "FltF97"; return; + case CV_IA64_FltF98: *out = "FltF98"; return; + case CV_IA64_FltF99: *out = "FltF99"; return; + case CV_IA64_FltF100:*out = "FltF100"; return; + case CV_IA64_FltF101:*out = "FltF101"; return; + case CV_IA64_FltF102:*out = "FltF102"; return; + case CV_IA64_FltF103:*out = "FltF103"; return; + case CV_IA64_FltF104:*out = "FltF104"; return; + case CV_IA64_FltF105:*out = "FltF105"; return; + case CV_IA64_FltF106:*out = "FltF106"; return; + case CV_IA64_FltF107:*out = "FltF107"; return; + case CV_IA64_FltF108:*out = "FltF108"; return; + case CV_IA64_FltF109:*out = "FltF109"; return; + case CV_IA64_FltF110:*out = "FltF110"; return; + case CV_IA64_FltF111:*out = "FltF111"; return; + case CV_IA64_FltF112:*out = "FltF112"; return; + case CV_IA64_FltF113:*out = "FltF113"; return; + case CV_IA64_FltF114:*out = "FltF114"; return; + case CV_IA64_FltF115:*out = "FltF115"; return; + case CV_IA64_FltF116:*out = "FltF116"; return; + case CV_IA64_FltF117:*out = "FltF117"; return; + case CV_IA64_FltF118:*out = "FltF118"; return; + case CV_IA64_FltF119:*out = "FltF119"; return; + case CV_IA64_FltF120:*out = "FltF120"; return; + case CV_IA64_FltF121:*out = "FltF121"; return; + case CV_IA64_FltF122:*out = "FltF122"; return; + case CV_IA64_FltF123:*out = "FltF123"; return; + case CV_IA64_FltF124:*out = "FltF124"; return; + case CV_IA64_FltF125:*out = "FltF125"; return; + case CV_IA64_FltF126:*out = "FltF126"; return; + case CV_IA64_FltF127:*out = "FltF127"; return; + + // Application Registers + + case CV_IA64_ApKR0: *out = "ApKR0"; return; + case CV_IA64_ApKR1: *out = "ApKR1"; return; + case CV_IA64_ApKR2: *out = "ApKR2"; return; + case CV_IA64_ApKR3: *out = "ApKR3"; return; + case CV_IA64_ApKR4: *out = "ApKR4"; return; + case CV_IA64_ApKR5: *out = "ApKR5"; return; + case CV_IA64_ApKR6: *out = "ApKR6"; return; + case CV_IA64_ApKR7: *out = "ApKR7"; return; + case CV_IA64_AR8: *out = "AR8"; return; + case CV_IA64_AR9: *out = "AR9"; return; + case CV_IA64_AR10: *out = "AR10"; return; + case CV_IA64_AR11: *out = "AR11"; return; + case CV_IA64_AR12: *out = "AR12"; return; + case CV_IA64_AR13: *out = "AR13"; return; + case CV_IA64_AR14: *out = "AR14"; return; + case CV_IA64_AR15: *out = "AR15"; return; + case CV_IA64_RsRSC: *out = "RsRSC"; return; + case CV_IA64_RsBSP: *out = "RsBSP"; return; + case CV_IA64_RsBSPSTORE:*out = "RsBSPSTORE"; return; + case CV_IA64_RsRNAT: *out = "rsrnat"; return; + case CV_IA64_AR20: *out = "ar20"; return; + case CV_IA64_StFCR: *out = "stfcr"; return; + case CV_IA64_AR22: *out = "ar22"; return; + case CV_IA64_AR23: *out = "ar23"; return; + case CV_IA64_EFLAG: *out = "eflag"; return; + case CV_IA64_CSD: *out = "csd"; return; + case CV_IA64_SSD: *out = "ssd"; return; + case CV_IA64_CFLG: *out = "cflg"; return; + case CV_IA64_StFSR: *out = "stfsr"; return; + case CV_IA64_StFIR: *out = "stfir"; return; + case CV_IA64_StFDR: *out = "stfdr"; return; + case CV_IA64_AR31: *out = "ar31"; return; + case CV_IA64_ApCCV: *out = "apccv"; return; + case CV_IA64_AR33: *out = "ar33"; return; + case CV_IA64_AR34: *out = "ar34"; return; + case CV_IA64_AR35: *out = "ar35"; return; + case CV_IA64_ApUNAT: *out = "apunat"; return; + case CV_IA64_AR37: *out = "ar37"; return; + case CV_IA64_AR38: *out = "ar38"; return; + case CV_IA64_AR39: *out = "ar39"; return; + case CV_IA64_StFPSR: *out = "stfpsr"; return; + case CV_IA64_AR41: *out = "ar41"; return; + case CV_IA64_AR42: *out = "ar42"; return; + case CV_IA64_AR43: *out = "ar43"; return; + case CV_IA64_ApITC: *out = "apitc"; return; + case CV_IA64_AR45: *out = "ar45"; return; + case CV_IA64_AR46: *out = "ar46"; return; + case CV_IA64_AR47: *out = "ar47"; return; + case CV_IA64_AR48: *out = "ar48"; return; + case CV_IA64_AR49: *out = "ar49"; return; + case CV_IA64_AR50: *out = "ar50"; return; + case CV_IA64_AR51: *out = "ar51"; return; + case CV_IA64_AR52: *out = "ar52"; return; + case CV_IA64_AR53: *out = "ar53"; return; + case CV_IA64_AR54: *out = "ar54"; return; + case CV_IA64_AR55: *out = "ar55"; return; + case CV_IA64_AR56: *out = "ar56"; return; + case CV_IA64_AR57: *out = "ar57"; return; + case CV_IA64_AR58: *out = "ar58"; return; + case CV_IA64_AR59: *out = "ar59"; return; + case CV_IA64_AR60: *out = "ar60"; return; + case CV_IA64_AR61: *out = "ar61"; return; + case CV_IA64_AR62: *out = "ar62"; return; + case CV_IA64_AR63: *out = "ar63"; return; + case CV_IA64_RsPFS: *out = "rspfs"; return; + case CV_IA64_ApLC: *out = "aplc"; return; + case CV_IA64_ApEC: *out = "apec"; return; + case CV_IA64_AR67: *out = "ar67"; return; + case CV_IA64_AR68: *out = "ar68"; return; + case CV_IA64_AR69: *out = "ar69"; return; + case CV_IA64_AR70: *out = "ar70"; return; + case CV_IA64_AR71: *out = "ar71"; return; + case CV_IA64_AR72: *out = "ar72"; return; + case CV_IA64_AR73: *out = "ar73"; return; + case CV_IA64_AR74: *out = "ar74"; return; + case CV_IA64_AR75: *out = "ar75"; return; + case CV_IA64_AR76: *out = "ar76"; return; + case CV_IA64_AR77: *out = "ar77"; return; + case CV_IA64_AR78: *out = "ar78"; return; + case CV_IA64_AR79: *out = "ar79"; return; + case CV_IA64_AR80: *out = "ar80"; return; + case CV_IA64_AR81: *out = "ar81"; return; + case CV_IA64_AR82: *out = "ar82"; return; + case CV_IA64_AR83: *out = "ar83"; return; + case CV_IA64_AR84: *out = "ar84"; return; + case CV_IA64_AR85: *out = "ar85"; return; + case CV_IA64_AR86: *out = "ar86"; return; + case CV_IA64_AR87: *out = "ar87"; return; + case CV_IA64_AR88: *out = "ar88"; return; + case CV_IA64_AR89: *out = "ar89"; return; + case CV_IA64_AR90: *out = "ar90"; return; + case CV_IA64_AR91: *out = "ar91"; return; + case CV_IA64_AR92: *out = "ar92"; return; + case CV_IA64_AR93: *out = "ar93"; return; + case CV_IA64_AR94: *out = "ar94"; return; + case CV_IA64_AR95: *out = "ar95"; return; + case CV_IA64_AR96: *out = "ar96"; return; + case CV_IA64_AR97: *out = "ar97"; return; + case CV_IA64_AR98: *out = "ar98"; return; + case CV_IA64_AR99: *out = "ar99"; return; + case CV_IA64_AR100: *out = "ar100"; return; + case CV_IA64_AR101: *out = "ar101"; return; + case CV_IA64_AR102: *out = "ar102"; return; + case CV_IA64_AR103: *out = "ar103"; return; + case CV_IA64_AR104: *out = "ar104"; return; + case CV_IA64_AR105: *out = "ar105"; return; + case CV_IA64_AR106: *out = "ar106"; return; + case CV_IA64_AR107: *out = "ar107"; return; + case CV_IA64_AR108: *out = "ar108"; return; + case CV_IA64_AR109: *out = "ar109"; return; + case CV_IA64_AR110: *out = "ar110"; return; + case CV_IA64_AR111: *out = "ar111"; return; + case CV_IA64_AR112: *out = "ar112"; return; + case CV_IA64_AR113: *out = "ar113"; return; + case CV_IA64_AR114: *out = "ar114"; return; + case CV_IA64_AR115: *out = "ar115"; return; + case CV_IA64_AR116: *out = "ar116"; return; + case CV_IA64_AR117: *out = "ar117"; return; + case CV_IA64_AR118: *out = "ar118"; return; + case CV_IA64_AR119: *out = "ar119"; return; + case CV_IA64_AR120: *out = "ar120"; return; + case CV_IA64_AR121: *out = "ar121"; return; + case CV_IA64_AR122: *out = "ar122"; return; + case CV_IA64_AR123: *out = "ar123"; return; + case CV_IA64_AR124: *out = "ar124"; return; + case CV_IA64_AR125: *out = "ar125"; return; + case CV_IA64_AR126: *out = "ar126"; return; + case CV_IA64_AR127: *out = "ar127"; return; + + // CPUID Registers + + case CV_IA64_CPUID0: *out = "cpuid0"; return; + case CV_IA64_CPUID1: *out = "cpuid1"; return; + case CV_IA64_CPUID2: *out = "cpuid2"; return; + case CV_IA64_CPUID3: *out = "cpuid3"; return; + case CV_IA64_CPUID4: *out = "cpuid4"; return; + + // Control Registers + + case CV_IA64_ApDCR: *out = "apdcr"; return; + case CV_IA64_ApITM: *out = "apitm"; return; + case CV_IA64_ApIVA: *out = "apiva"; return; + case CV_IA64_CR3: *out = "cr3"; return; + case CV_IA64_CR4: *out = "cr4"; return; + case CV_IA64_CR5: *out = "cr5"; return; + case CV_IA64_CR6: *out = "cr6"; return; + case CV_IA64_CR7: *out = "cr7"; return; + case CV_IA64_ApPTA: *out = "appta"; return; + case CV_IA64_ApGPTA: *out = "apgpta"; return; + case CV_IA64_CR10: *out = "cr10"; return; + case CV_IA64_CR11: *out = "cr11"; return; + case CV_IA64_CR12: *out = "cr12"; return; + case CV_IA64_CR13: *out = "cr13"; return; + case CV_IA64_CR14: *out = "cr14"; return; + case CV_IA64_CR15: *out = "cr15"; return; + case CV_IA64_StIPSR: *out = "stipsr"; return; + case CV_IA64_StISR: *out = "stisr"; return; + case CV_IA64_CR18: *out = "cr18"; return; + case CV_IA64_StIIP: *out = "stiip"; return; + case CV_IA64_StIFA: *out = "stifa"; return; + case CV_IA64_StITIR: *out = "stitir"; return; + case CV_IA64_StIIPA: *out = "stiipa"; return; + case CV_IA64_StIFS: *out = "stifs"; return; + case CV_IA64_StIIM: *out = "stiim"; return; + case CV_IA64_StIHA: *out = "stiha"; return; + case CV_IA64_CR26: *out = "cr26"; return; + case CV_IA64_CR27: *out = "cr27"; return; + case CV_IA64_CR28: *out = "cr28"; return; + case CV_IA64_CR29: *out = "cr29"; return; + case CV_IA64_CR30: *out = "cr30"; return; + case CV_IA64_CR31: *out = "cr31"; return; + case CV_IA64_CR32: *out = "cr32"; return; + case CV_IA64_CR33: *out = "cr33"; return; + case CV_IA64_CR34: *out = "cr34"; return; + case CV_IA64_CR35: *out = "cr35"; return; + case CV_IA64_CR36: *out = "cr36"; return; + case CV_IA64_CR37: *out = "cr37"; return; + case CV_IA64_CR38: *out = "cr38"; return; + case CV_IA64_CR39: *out = "cr39"; return; + case CV_IA64_CR40: *out = "cr40"; return; + case CV_IA64_CR41: *out = "cr41"; return; + case CV_IA64_CR42: *out = "cr42"; return; + case CV_IA64_CR43: *out = "cr43"; return; + case CV_IA64_CR44: *out = "cr44"; return; + case CV_IA64_CR45: *out = "cr45"; return; + case CV_IA64_CR46: *out = "cr46"; return; + case CV_IA64_CR47: *out = "cr47"; return; + case CV_IA64_CR48: *out = "cr48"; return; + case CV_IA64_CR49: *out = "cr49"; return; + case CV_IA64_CR50: *out = "cr50"; return; + case CV_IA64_CR51: *out = "cr51"; return; + case CV_IA64_CR52: *out = "cr52"; return; + case CV_IA64_CR53: *out = "cr53"; return; + case CV_IA64_CR54: *out = "cr54"; return; + case CV_IA64_CR55: *out = "cr55"; return; + case CV_IA64_CR56: *out = "cr56"; return; + case CV_IA64_CR57: *out = "cr57"; return; + case CV_IA64_CR58: *out = "cr58"; return; + case CV_IA64_CR59: *out = "cr59"; return; + case CV_IA64_CR60: *out = "cr60"; return; + case CV_IA64_CR61: *out = "cr61"; return; + case CV_IA64_CR62: *out = "cr62"; return; + case CV_IA64_CR63: *out = "cr63"; return; + case CV_IA64_SaLID: *out = "salid"; return; + case CV_IA64_SaIVR: *out = "saivr"; return; + case CV_IA64_SaTPR: *out = "satpr"; return; + case CV_IA64_SaEOI: *out = "saeoi"; return; + case CV_IA64_SaIRR0: *out = "sairr0"; return; + case CV_IA64_SaIRR1: *out = "sairr1"; return; + case CV_IA64_SaIRR2: *out = "sairr2"; return; + case CV_IA64_SaIRR3: *out = "sairr3"; return; + case CV_IA64_SaITV: *out = "saitv"; return; + case CV_IA64_SaPMV: *out = "sapmv"; return; + case CV_IA64_SaCMCV: *out = "sacmcv"; return; + case CV_IA64_CR75: *out = "cr75"; return; + case CV_IA64_CR76: *out = "cr76"; return; + case CV_IA64_CR77: *out = "cr77"; return; + case CV_IA64_CR78: *out = "cr78"; return; + case CV_IA64_CR79: *out = "cr79"; return; + case CV_IA64_SaLRR0: *out = "salrr0"; return; + case CV_IA64_SaLRR1: *out = "salrr1"; return; + case CV_IA64_CR82: *out = "cr82"; return; + case CV_IA64_CR83: *out = "cr83"; return; + case CV_IA64_CR84: *out = "cr84"; return; + case CV_IA64_CR85: *out = "cr85"; return; + case CV_IA64_CR86: *out = "cr86"; return; + case CV_IA64_CR87: *out = "cr87"; return; + case CV_IA64_CR88: *out = "cr88"; return; + case CV_IA64_CR89: *out = "cr89"; return; + case CV_IA64_CR90: *out = "cr90"; return; + case CV_IA64_CR91: *out = "cr91"; return; + case CV_IA64_CR92: *out = "cr92"; return; + case CV_IA64_CR93: *out = "cr93"; return; + case CV_IA64_CR94: *out = "cr94"; return; + case CV_IA64_CR95: *out = "cr95"; return; + case CV_IA64_CR96: *out = "cr96"; return; + case CV_IA64_CR97: *out = "cr97"; return; + case CV_IA64_CR98: *out = "cr98"; return; + case CV_IA64_CR99: *out = "cr99"; return; + case CV_IA64_CR100: *out = "cr100"; return; + case CV_IA64_CR101: *out = "cr101"; return; + case CV_IA64_CR102: *out = "cr102"; return; + case CV_IA64_CR103: *out = "cr103"; return; + case CV_IA64_CR104: *out = "cr104"; return; + case CV_IA64_CR105: *out = "cr105"; return; + case CV_IA64_CR106: *out = "cr106"; return; + case CV_IA64_CR107: *out = "cr107"; return; + case CV_IA64_CR108: *out = "cr108"; return; + case CV_IA64_CR109: *out = "cr109"; return; + case CV_IA64_CR110: *out = "cr110"; return; + case CV_IA64_CR111: *out = "cr111"; return; + case CV_IA64_CR112: *out = "cr112"; return; + case CV_IA64_CR113: *out = "cr113"; return; + case CV_IA64_CR114: *out = "cr114"; return; + case CV_IA64_CR115: *out = "cr115"; return; + case CV_IA64_CR116: *out = "cr116"; return; + case CV_IA64_CR117: *out = "cr117"; return; + case CV_IA64_CR118: *out = "cr118"; return; + case CV_IA64_CR119: *out = "cr119"; return; + case CV_IA64_CR120: *out = "cr120"; return; + case CV_IA64_CR121: *out = "cr121"; return; + case CV_IA64_CR122: *out = "cr122"; return; + case CV_IA64_CR123: *out = "cr123"; return; + case CV_IA64_CR124: *out = "cr124"; return; + case CV_IA64_CR125: *out = "cr125"; return; + case CV_IA64_CR126: *out = "cr126"; return; + case CV_IA64_CR127: *out = "cr127"; return; + + // Protection Key Registers + + case CV_IA64_Pkr0: *out = "pkr0"; return; + case CV_IA64_Pkr1: *out = "pkr1"; return; + case CV_IA64_Pkr2: *out = "pkr2"; return; + case CV_IA64_Pkr3: *out = "pkr3"; return; + case CV_IA64_Pkr4: *out = "pkr4"; return; + case CV_IA64_Pkr5: *out = "pkr5"; return; + case CV_IA64_Pkr6: *out = "pkr6"; return; + case CV_IA64_Pkr7: *out = "pkr7"; return; + case CV_IA64_Pkr8: *out = "pkr8"; return; + case CV_IA64_Pkr9: *out = "pkr9"; return; + case CV_IA64_Pkr10: *out = "pkr10"; return; + case CV_IA64_Pkr11: *out = "pkr11"; return; + case CV_IA64_Pkr12: *out = "pkr12"; return; + case CV_IA64_Pkr13: *out = "pkr13"; return; + case CV_IA64_Pkr14: *out = "pkr14"; return; + case CV_IA64_Pkr15: *out = "pkr15"; return; + + // Region Registers + + case CV_IA64_Rr0: *out = "rr0"; return; + case CV_IA64_Rr1: *out = "rr1"; return; + case CV_IA64_Rr2: *out = "rr2"; return; + case CV_IA64_Rr3: *out = "rr3"; return; + case CV_IA64_Rr4: *out = "rr4"; return; + case CV_IA64_Rr5: *out = "rr5"; return; + case CV_IA64_Rr6: *out = "rr6"; return; + case CV_IA64_Rr7: *out = "rr7"; return; + + // Performance Monitor Data Registers + + case CV_IA64_PFD0: *out = "pfd0"; return; + case CV_IA64_PFD1: *out = "pfd1"; return; + case CV_IA64_PFD2: *out = "pfd2"; return; + case CV_IA64_PFD3: *out = "pfd3"; return; + case CV_IA64_PFD4: *out = "pfd4"; return; + case CV_IA64_PFD5: *out = "pfd5"; return; + case CV_IA64_PFD6: *out = "pfd6"; return; + case CV_IA64_PFD7: *out = "pfd7"; return; + case CV_IA64_PFD8: *out = "pfd8"; return; + case CV_IA64_PFD9: *out = "pfd9"; return; + case CV_IA64_PFD10: *out = "pfd10"; return; + case CV_IA64_PFD11: *out = "pfd11"; return; + case CV_IA64_PFD12: *out = "pfd12"; return; + case CV_IA64_PFD13: *out = "pfd13"; return; + case CV_IA64_PFD14: *out = "pfd14"; return; + case CV_IA64_PFD15: *out = "pfd15"; return; + case CV_IA64_PFD16: *out = "pfd16"; return; + case CV_IA64_PFD17: *out = "pfd17"; return; + + // Performance Monitor Config Registers + + case CV_IA64_PFC0: *out = "pfc0"; return; + case CV_IA64_PFC1: *out = "pfc1"; return; + case CV_IA64_PFC2: *out = "pfc2"; return; + case CV_IA64_PFC3: *out = "pfc3"; return; + case CV_IA64_PFC4: *out = "pfc4"; return; + case CV_IA64_PFC5: *out = "pfc5"; return; + case CV_IA64_PFC6: *out = "pfc6"; return; + case CV_IA64_PFC7: *out = "pfc7"; return; + case CV_IA64_PFC8: *out = "pfc8"; return; + case CV_IA64_PFC9: *out = "pfc9"; return; + case CV_IA64_PFC10: *out = "pfc10"; return; + case CV_IA64_PFC11: *out = "pfc11"; return; + case CV_IA64_PFC12: *out = "pfc12"; return; + case CV_IA64_PFC13: *out = "pfc13"; return; + case CV_IA64_PFC14: *out = "pfc14"; return; + case CV_IA64_PFC15: *out = "pfc15"; return; + + // Instruction Translation Registers + + case CV_IA64_TrI0: *out = "tri0"; return; + case CV_IA64_TrI1: *out = "tri1"; return; + case CV_IA64_TrI2: *out = "tri2"; return; + case CV_IA64_TrI3: *out = "tri3"; return; + case CV_IA64_TrI4: *out = "tri4"; return; + case CV_IA64_TrI5: *out = "tri5"; return; + case CV_IA64_TrI6: *out = "tri6"; return; + case CV_IA64_TrI7: *out = "tri7"; return; + + // Data Translation Registers + + case CV_IA64_TrD0: *out = "trd0"; return; + case CV_IA64_TrD1: *out = "trd1"; return; + case CV_IA64_TrD2: *out = "trd2"; return; + case CV_IA64_TrD3: *out = "trd3"; return; + case CV_IA64_TrD4: *out = "trd4"; return; + case CV_IA64_TrD5: *out = "trd5"; return; + case CV_IA64_TrD6: *out = "trd6"; return; + case CV_IA64_TrD7: *out = "trd7"; return; + + // Instruction Breakpoint Registers + + case CV_IA64_DbI0: *out = "dbi0"; return; + case CV_IA64_DbI1: *out = "dbi1"; return; + case CV_IA64_DbI2: *out = "dbi2"; return; + case CV_IA64_DbI3: *out = "dbi3"; return; + case CV_IA64_DbI4: *out = "dbi4"; return; + case CV_IA64_DbI5: *out = "dbi5"; return; + case CV_IA64_DbI6: *out = "dbi6"; return; + case CV_IA64_DbI7: *out = "dbi7"; return; + + // Data Breakpoint Registers + + case CV_IA64_DbD0: *out = "dbd0"; return; + case CV_IA64_DbD1: *out = "dbd1"; return; + case CV_IA64_DbD2: *out = "dbd2"; return; + case CV_IA64_DbD3: *out = "dbd3"; return; + case CV_IA64_DbD4: *out = "dbd4"; return; + case CV_IA64_DbD5: *out = "dbd5"; return; + case CV_IA64_DbD6: *out = "dbd6"; return; + case CV_IA64_DbD7: *out = "dbd7"; return; + } + break; + + + case CV_CFL_TRICORE: + // + // Register set for the TriCore processor. + // + switch ( reg ) + { + case CV_TRI_NOREG: *out = "noreg"; return; + + // General Purpose Data Registers + + case CV_TRI_D0: *out = "d0"; return; + case CV_TRI_D1: *out = "d1"; return; + case CV_TRI_D2: *out = "d2"; return; + case CV_TRI_D3: *out = "d3"; return; + case CV_TRI_D4: *out = "d4"; return; + case CV_TRI_D5: *out = "d5"; return; + case CV_TRI_D6: *out = "d6"; return; + case CV_TRI_D7: *out = "d7"; return; + case CV_TRI_D8: *out = "d8"; return; + case CV_TRI_D9: *out = "d9"; return; + case CV_TRI_D10: *out = "d10"; return; + case CV_TRI_D11: *out = "d11"; return; + case CV_TRI_D12: *out = "d12"; return; + case CV_TRI_D13: *out = "d13"; return; + case CV_TRI_D14: *out = "d14"; return; + case CV_TRI_D15: *out = "d15"; return; + + // General Purpose Address Registers + + case CV_TRI_A0: *out = "a0"; return; + case CV_TRI_A1: *out = "a1"; return; + case CV_TRI_A2: *out = "a2"; return; + case CV_TRI_A3: *out = "a3"; return; + case CV_TRI_A4: *out = "a4"; return; + case CV_TRI_A5: *out = "a5"; return; + case CV_TRI_A6: *out = "a6"; return; + case CV_TRI_A7: *out = "a7"; return; + case CV_TRI_A8: *out = "a8"; return; + case CV_TRI_A9: *out = "a9"; return; + case CV_TRI_A10: *out = "a10"; return; + case CV_TRI_A11: *out = "a11"; return; + case CV_TRI_A12: *out = "a12"; return; + case CV_TRI_A13: *out = "a13"; return; + case CV_TRI_A14: *out = "a14"; return; + case CV_TRI_A15: *out = "a15"; return; + + // Extended (64-bit) data registers + + case CV_TRI_E0: *out = "e0"; return; + case CV_TRI_E2: *out = "e2"; return; + case CV_TRI_E4: *out = "e4"; return; + case CV_TRI_E6: *out = "e6"; return; + case CV_TRI_E8: *out = "e8"; return; + case CV_TRI_E10: *out = "e10"; return; + case CV_TRI_E12: *out = "e12"; return; + case CV_TRI_E14: *out = "e14"; return; + + // Extended (64-bit) address registers + + case CV_TRI_EA0: *out = "ea0"; return; + case CV_TRI_EA2: *out = "ea2"; return; + case CV_TRI_EA4: *out = "ea4"; return; + case CV_TRI_EA6: *out = "ea6"; return; + case CV_TRI_EA8: *out = "ea8"; return; + case CV_TRI_EA10: *out = "ea10"; return; + case CV_TRI_EA12: *out = "ea12"; return; + case CV_TRI_EA14: *out = "ea14"; return; + + case CV_TRI_PSW: *out = "psw"; return; + case CV_TRI_PCXI: *out = "pcxi"; return; + case CV_TRI_PC: *out = "pc"; return; + case CV_TRI_FCX: *out = "fcx"; return; + case CV_TRI_LCX: *out = "lcx"; return; + case CV_TRI_ISP: *out = "isp"; return; + case CV_TRI_ICR: *out = "icr"; return; + case CV_TRI_BIV: *out = "biv"; return; + case CV_TRI_BTV: *out = "btv"; return; + case CV_TRI_SYSCON: *out = "syscon"; return; + case CV_TRI_DPRx_0: *out = "dprx_0"; return; + case CV_TRI_DPRx_1: *out = "dprx_1"; return; + case CV_TRI_DPRx_2: *out = "dprx_2"; return; + case CV_TRI_DPRx_3: *out = "dprx_3"; return; +// case CV_TRI_CPRx_0: *out = "cprx_0"; return; +// case CV_TRI_CPRx_1: *out = "cprx_1"; return; +// case CV_TRI_CPRx_2: *out = "cprx_2"; return; +// case CV_TRI_CPRx_3: *out = "cprx_3"; return; +// case CV_TRI_DPMx_0: *out = "dpmx_0"; return; +// case CV_TRI_DPMx_1: *out = "dpmx_1"; return; +// case CV_TRI_DPMx_2: *out = "dpmx_2"; return; +// case CV_TRI_DPMx_3: *out = "dpmx_3"; return; +// case CV_TRI_CPMx_0: *out = "cpmx_0"; return; +// case CV_TRI_CPMx_1: *out = "cpmx_1"; return; +// case CV_TRI_CPMx_2: *out = "cpmx_2"; return; +// case CV_TRI_CPMx_3: *out = "cpmx_3"; return; + case CV_TRI_DBGSSR: *out = "dbgssr"; return; + case CV_TRI_EXEVT: *out = "exevt"; return; + case CV_TRI_SWEVT: *out = "swevt"; return; + case CV_TRI_CREVT: *out = "crevt"; return; + case CV_TRI_TRnEVT: *out = "trnevt"; return; + case CV_TRI_MMUCON: *out = "mmucon"; return; + case CV_TRI_ASI: *out = "asi"; return; + case CV_TRI_TVA: *out = "tva"; return; + case CV_TRI_TPA: *out = "tpa"; return; + case CV_TRI_TPX: *out = "tpx"; return; + case CV_TRI_TFA: *out = "tfa"; return; + } + break; + + case CV_CFL_AM33: + // + // Register set for the AM33 and related processors. + // + switch ( reg ) + { + case CV_AM33_NOREG: *out = "noreg"; return; + + // "Extended" (general purpose integer) registers + case CV_AM33_E0: *out = "e0"; return; + case CV_AM33_E1: *out = "e1"; return; + case CV_AM33_E2: *out = "e2"; return; + case CV_AM33_E3: *out = "e3"; return; + case CV_AM33_E4: *out = "e4"; return; + case CV_AM33_E5: *out = "e5"; return; + case CV_AM33_E6: *out = "e6"; return; + case CV_AM33_E7: *out = "e7"; return; + + // Address registers + case CV_AM33_A0: *out = "a0"; return; + case CV_AM33_A1: *out = "a1"; return; + case CV_AM33_A2: *out = "a2"; return; + case CV_AM33_A3: *out = "a3"; return; + + // Integer data registers + case CV_AM33_D0: *out = "d0"; return; + case CV_AM33_D1: *out = "d1"; return; + case CV_AM33_D2: *out = "d2"; return; + case CV_AM33_D3: *out = "d3"; return; + + // (Single-precision) floating-point registers + case CV_AM33_FS0: *out = "fs0"; return; + case CV_AM33_FS1: *out = "fs1"; return; + case CV_AM33_FS2: *out = "fs2"; return; + case CV_AM33_FS3: *out = "fs3"; return; + case CV_AM33_FS4: *out = "fs4"; return; + case CV_AM33_FS5: *out = "fs5"; return; + case CV_AM33_FS6: *out = "fs6"; return; + case CV_AM33_FS7: *out = "fs7"; return; + case CV_AM33_FS8: *out = "fs8"; return; + case CV_AM33_FS9: *out = "fs9"; return; + case CV_AM33_FS10: *out = "fs10"; return; + case CV_AM33_FS11: *out = "fs11"; return; + case CV_AM33_FS12: *out = "fs12"; return; + case CV_AM33_FS13: *out = "fs13"; return; + case CV_AM33_FS14: *out = "fs14"; return; + case CV_AM33_FS15: *out = "fs15"; return; + case CV_AM33_FS16: *out = "fs16"; return; + case CV_AM33_FS17: *out = "fs17"; return; + case CV_AM33_FS18: *out = "fs18"; return; + case CV_AM33_FS19: *out = "fs19"; return; + case CV_AM33_FS20: *out = "fs20"; return; + case CV_AM33_FS21: *out = "fs21"; return; + case CV_AM33_FS22: *out = "fs22"; return; + case CV_AM33_FS23: *out = "fs23"; return; + case CV_AM33_FS24: *out = "fs24"; return; + case CV_AM33_FS25: *out = "fs25"; return; + case CV_AM33_FS26: *out = "fs26"; return; + case CV_AM33_FS27: *out = "fs27"; return; + case CV_AM33_FS28: *out = "fs28"; return; + case CV_AM33_FS29: *out = "fs29"; return; + case CV_AM33_FS30: *out = "fs30"; return; + case CV_AM33_FS31: *out = "fs31"; return; + + // Special purpose registers + + // Stack pointer + case CV_AM33_SP: *out = "sp"; return; + + // Program counter + case CV_AM33_PC: *out = "pc"; return; + + // Multiply-divide/accumulate registers + case CV_AM33_MDR: *out = "mdr"; return; + case CV_AM33_MDRQ: *out = "mdrq"; return; + case CV_AM33_MCRH: *out = "mcrh"; return; + case CV_AM33_MCRL: *out = "mcrl"; return; + case CV_AM33_MCVF: *out = "mcvf"; return; + + // CPU status words + case CV_AM33_EPSW: *out = "epsw"; return; + case CV_AM33_FPCR: *out = "fpcr"; return; + + // Loop buffer registers + case CV_AM33_LIR: *out = "lir"; return; + case CV_AM33_LAR: *out = "lar"; return; + } + break; + + case CV_CFL_M32R: + // + // Register set for the Mitsubishi M32R + // + switch ( reg ) + { + case CV_M32R_NOREG: *out = "noreg"; return; + case CV_M32R_R0: *out = "r0"; return; + case CV_M32R_R1: *out = "r1"; return; + case CV_M32R_R2: *out = "r2"; return; + case CV_M32R_R3: *out = "r3"; return; + case CV_M32R_R4: *out = "r4"; return; + case CV_M32R_R5: *out = "r5"; return; + case CV_M32R_R6: *out = "r6"; return; + case CV_M32R_R7: *out = "r7"; return; + case CV_M32R_R8: *out = "r8"; return; + case CV_M32R_R9: *out = "r9"; return; + case CV_M32R_R10: *out = "r10"; return; + case CV_M32R_R11: *out = "r11"; return; + case CV_M32R_R12: *out = "r12"; return;// Gloabal Pointer, if used + case CV_M32R_R13: *out = "r13"; return;// Frame Pointer, if allocated + case CV_M32R_R14: *out = "r14"; return;// Link Register + case CV_M32R_R15: *out = "r15"; return;// Stack Pointer + case CV_M32R_PSW: *out = "psw"; return;// Preocessor Status Register + case CV_M32R_CBR: *out = "cbr"; return;// Condition Bit Register + case CV_M32R_SPI: *out = "spi"; return;// Interrupt Stack Pointer + case CV_M32R_SPU: *out = "spu"; return;// User Stack Pointer + case CV_M32R_SPO: *out = "spo"; return;// OS Stack Pointer + case CV_M32R_BPC: *out = "bpc"; return;// Backup Program Counter + case CV_M32R_ACHI: *out = "achi"; return;// Accumulator High + case CV_M32R_ACLO: *out = "aclo"; return;// Accumulator Low + case CV_M32R_PC: *out = "pc"; return;// Program Counter + } + break; + + // + // Register set for the SuperH SHMedia processor including compact + // mode + // + case CV_CFL_SHMEDIA: + switch ( reg ) + { + // Integer - 64 bit general registers + case CV_SHMEDIA_NOREG:*out = "noreg"; return; + case CV_SHMEDIA_R0: *out = "r0"; return; + case CV_SHMEDIA_R1: *out = "r1"; return; + case CV_SHMEDIA_R2: *out = "r2"; return; + case CV_SHMEDIA_R3: *out = "r3"; return; + case CV_SHMEDIA_R4: *out = "r4"; return; + case CV_SHMEDIA_R5: *out = "r5"; return; + case CV_SHMEDIA_R6: *out = "r6"; return; + case CV_SHMEDIA_R7: *out = "r7"; return; + case CV_SHMEDIA_R8: *out = "r8"; return; + case CV_SHMEDIA_R9: *out = "r9"; return; + case CV_SHMEDIA_R10: *out = "r10"; return; + case CV_SHMEDIA_R11: *out = "r11"; return; + case CV_SHMEDIA_R12: *out = "r12"; return; + case CV_SHMEDIA_R13: *out = "r13"; return; + case CV_SHMEDIA_R14: *out = "r14"; return; + case CV_SHMEDIA_R15: *out = "r15"; return; + case CV_SHMEDIA_R16: *out = "r16"; return; + case CV_SHMEDIA_R17: *out = "r17"; return; + case CV_SHMEDIA_R18: *out = "r18"; return; + case CV_SHMEDIA_R19: *out = "r19"; return; + case CV_SHMEDIA_R20: *out = "r20"; return; + case CV_SHMEDIA_R21: *out = "r21"; return; + case CV_SHMEDIA_R22: *out = "r22"; return; + case CV_SHMEDIA_R23: *out = "r23"; return; + case CV_SHMEDIA_R24: *out = "r24"; return; + case CV_SHMEDIA_R25: *out = "r25"; return; + case CV_SHMEDIA_R26: *out = "r26"; return; + case CV_SHMEDIA_R27: *out = "r27"; return; + case CV_SHMEDIA_R28: *out = "r28"; return; + case CV_SHMEDIA_R29: *out = "r29"; return; + case CV_SHMEDIA_R30: *out = "r30"; return; + case CV_SHMEDIA_R31: *out = "r31"; return; + case CV_SHMEDIA_R32: *out = "r32"; return; + case CV_SHMEDIA_R33: *out = "r33"; return; + case CV_SHMEDIA_R34: *out = "r34"; return; + case CV_SHMEDIA_R35: *out = "r35"; return; + case CV_SHMEDIA_R36: *out = "r36"; return; + case CV_SHMEDIA_R37: *out = "r37"; return; + case CV_SHMEDIA_R38: *out = "r38"; return; + case CV_SHMEDIA_R39: *out = "r39"; return; + case CV_SHMEDIA_R40: *out = "r40"; return; + case CV_SHMEDIA_R41: *out = "r41"; return; + case CV_SHMEDIA_R42: *out = "r42"; return; + case CV_SHMEDIA_R43: *out = "r43"; return; + case CV_SHMEDIA_R44: *out = "r44"; return; + case CV_SHMEDIA_R45: *out = "r45"; return; + case CV_SHMEDIA_R46: *out = "r46"; return; + case CV_SHMEDIA_R47: *out = "r47"; return; + case CV_SHMEDIA_R48: *out = "r48"; return; + case CV_SHMEDIA_R49: *out = "r49"; return; + case CV_SHMEDIA_R50: *out = "r50"; return; + case CV_SHMEDIA_R51: *out = "r51"; return; + case CV_SHMEDIA_R52: *out = "r52"; return; + case CV_SHMEDIA_R53: *out = "r53"; return; + case CV_SHMEDIA_R54: *out = "r54"; return; + case CV_SHMEDIA_R55: *out = "r55"; return; + case CV_SHMEDIA_R56: *out = "r56"; return; + case CV_SHMEDIA_R57: *out = "r57"; return; + case CV_SHMEDIA_R58: *out = "r58"; return; + case CV_SHMEDIA_R59: *out = "r59"; return; + case CV_SHMEDIA_R60: *out = "r60"; return; + case CV_SHMEDIA_R61: *out = "r61"; return; + case CV_SHMEDIA_R62: *out = "r62"; return; + case CV_SHMEDIA_R63: *out = "r63"; return; + + // Target Registers - 32 bit + case CV_SHMEDIA_TR0: *out = "tr0"; return; + case CV_SHMEDIA_TR1: *out = "tr1"; return; + case CV_SHMEDIA_TR2: *out = "tr2"; return; + case CV_SHMEDIA_TR3: *out = "tr3"; return; + case CV_SHMEDIA_TR4: *out = "tr4"; return; + case CV_SHMEDIA_TR5: *out = "tr5"; return; + case CV_SHMEDIA_TR6: *out = "tr6"; return; + case CV_SHMEDIA_TR7: *out = "tr7"; return; + case CV_SHMEDIA_TR8: *out = "tr8"; return; // future-proof + case CV_SHMEDIA_TR9: *out = "tr9"; return; // future-proof + case CV_SHMEDIA_TR10:*out = "tr10"; return; // future-proof + case CV_SHMEDIA_TR11:*out = "tr11"; return; // future-proof + case CV_SHMEDIA_TR12:*out = "tr12"; return; // future-proof + case CV_SHMEDIA_TR13:*out = "tr13"; return; // future-proof + case CV_SHMEDIA_TR14:*out = "tr14"; return; // future-proof + case CV_SHMEDIA_TR15:*out = "tr15"; return; // future-proof + + // Single - 32 bit fp registers + case CV_SHMEDIA_FR0: *out = "fr0"; return; + case CV_SHMEDIA_FR1: *out = "fr1"; return; + case CV_SHMEDIA_FR2: *out = "fr2"; return; + case CV_SHMEDIA_FR3: *out = "fr3"; return; + case CV_SHMEDIA_FR4: *out = "fr4"; return; + case CV_SHMEDIA_FR5: *out = "fr5"; return; + case CV_SHMEDIA_FR6: *out = "fr6"; return; + case CV_SHMEDIA_FR7: *out = "fr7"; return; + case CV_SHMEDIA_FR8: *out = "fr8"; return; + case CV_SHMEDIA_FR9: *out = "fr9"; return; + case CV_SHMEDIA_FR10:*out = "fr10"; return; + case CV_SHMEDIA_FR11:*out = "fr11"; return; + case CV_SHMEDIA_FR12:*out = "fr12"; return; + case CV_SHMEDIA_FR13:*out = "fr13"; return; + case CV_SHMEDIA_FR14:*out = "fr14"; return; + case CV_SHMEDIA_FR15:*out = "fr15"; return; + case CV_SHMEDIA_FR16:*out = "fr16"; return; + case CV_SHMEDIA_FR17:*out = "fr17"; return; + case CV_SHMEDIA_FR18:*out = "fr18"; return; + case CV_SHMEDIA_FR19:*out = "fr19"; return; + case CV_SHMEDIA_FR20:*out = "fr20"; return; + case CV_SHMEDIA_FR21:*out = "fr21"; return; + case CV_SHMEDIA_FR22:*out = "fr22"; return; + case CV_SHMEDIA_FR23:*out = "fr23"; return; + case CV_SHMEDIA_FR24:*out = "fr24"; return; + case CV_SHMEDIA_FR25:*out = "fr25"; return; + case CV_SHMEDIA_FR26:*out = "fr26"; return; + case CV_SHMEDIA_FR27:*out = "fr27"; return; + case CV_SHMEDIA_FR28:*out = "fr28"; return; + case CV_SHMEDIA_FR29:*out = "fr29"; return; + case CV_SHMEDIA_FR30:*out = "fr30"; return; + case CV_SHMEDIA_FR31:*out = "fr31"; return; + case CV_SHMEDIA_FR32:*out = "fr32"; return; + case CV_SHMEDIA_FR33:*out = "fr33"; return; + case CV_SHMEDIA_FR34:*out = "fr34"; return; + case CV_SHMEDIA_FR35:*out = "fr35"; return; + case CV_SHMEDIA_FR36:*out = "fr36"; return; + case CV_SHMEDIA_FR37:*out = "fr37"; return; + case CV_SHMEDIA_FR38:*out = "fr38"; return; + case CV_SHMEDIA_FR39:*out = "fr39"; return; + case CV_SHMEDIA_FR40:*out = "fr40"; return; + case CV_SHMEDIA_FR41:*out = "fr41"; return; + case CV_SHMEDIA_FR42:*out = "fr42"; return; + case CV_SHMEDIA_FR43:*out = "fr43"; return; + case CV_SHMEDIA_FR44:*out = "fr44"; return; + case CV_SHMEDIA_FR45:*out = "fr45"; return; + case CV_SHMEDIA_FR46:*out = "fr46"; return; + case CV_SHMEDIA_FR47:*out = "fr47"; return; + case CV_SHMEDIA_FR48:*out = "fr48"; return; + case CV_SHMEDIA_FR49:*out = "fr49"; return; + case CV_SHMEDIA_FR50:*out = "fr50"; return; + case CV_SHMEDIA_FR51:*out = "fr51"; return; + case CV_SHMEDIA_FR52:*out = "fr52"; return; + case CV_SHMEDIA_FR53:*out = "fr53"; return; + case CV_SHMEDIA_FR54:*out = "fr54"; return; + case CV_SHMEDIA_FR55:*out = "fr55"; return; + case CV_SHMEDIA_FR56:*out = "fr56"; return; + case CV_SHMEDIA_FR57:*out = "fr57"; return; + case CV_SHMEDIA_FR58:*out = "fr58"; return; + case CV_SHMEDIA_FR59:*out = "fr59"; return; + case CV_SHMEDIA_FR60:*out = "fr60"; return; + case CV_SHMEDIA_FR61:*out = "fr61"; return; + case CV_SHMEDIA_FR62:*out = "fr62"; return; + case CV_SHMEDIA_FR63:*out = "fr63"; return; + + // Double - 64 bit synonyms for 32bit fp register pairs + // subtract 128 to find first base single register + case CV_SHMEDIA_DR0: *out = "dr0"; return; + case CV_SHMEDIA_DR2: *out = "dr2"; return; + case CV_SHMEDIA_DR4: *out = "dr4"; return; + case CV_SHMEDIA_DR6: *out = "dr6"; return; + case CV_SHMEDIA_DR8: *out = "dr8"; return; + case CV_SHMEDIA_DR10:*out = "dr10"; return; + case CV_SHMEDIA_DR12:*out = "dr12"; return; + case CV_SHMEDIA_DR14:*out = "dr14"; return; + case CV_SHMEDIA_DR16:*out = "dr16"; return; + case CV_SHMEDIA_DR18:*out = "dr18"; return; + case CV_SHMEDIA_DR20:*out = "dr20"; return; + case CV_SHMEDIA_DR22:*out = "dr22"; return; + case CV_SHMEDIA_DR24:*out = "dr24"; return; + case CV_SHMEDIA_DR26:*out = "dr26"; return; + case CV_SHMEDIA_DR28:*out = "dr28"; return; + case CV_SHMEDIA_DR30:*out = "dr30"; return; + case CV_SHMEDIA_DR32:*out = "dr32"; return; + case CV_SHMEDIA_DR34:*out = "dr34"; return; + case CV_SHMEDIA_DR36:*out = "dr36"; return; + case CV_SHMEDIA_DR38:*out = "dr38"; return; + case CV_SHMEDIA_DR40:*out = "dr40"; return; + case CV_SHMEDIA_DR42:*out = "dr42"; return; + case CV_SHMEDIA_DR44:*out = "dr44"; return; + case CV_SHMEDIA_DR46:*out = "dr46"; return; + case CV_SHMEDIA_DR48:*out = "dr48"; return; + case CV_SHMEDIA_DR50:*out = "dr50"; return; + case CV_SHMEDIA_DR52:*out = "dr52"; return; + case CV_SHMEDIA_DR54:*out = "dr54"; return; + case CV_SHMEDIA_DR56:*out = "dr56"; return; + case CV_SHMEDIA_DR58:*out = "dr58"; return; + case CV_SHMEDIA_DR60:*out = "dr60"; return; + case CV_SHMEDIA_DR62:*out = "dr62"; return; + + // Vector - 128 bit synonyms for 32bit fp register quads + // subtract 384 to find first base single register + case CV_SHMEDIA_FV0: *out = "fv0"; return; + case CV_SHMEDIA_FV4: *out = "fv4"; return; + case CV_SHMEDIA_FV8: *out = "fv8"; return; + case CV_SHMEDIA_FV12:*out = "fv12"; return; + case CV_SHMEDIA_FV16:*out = "fv16"; return; + case CV_SHMEDIA_FV20:*out = "fv20"; return; + case CV_SHMEDIA_FV24:*out = "fv24"; return; + case CV_SHMEDIA_FV28:*out = "fv28"; return; + case CV_SHMEDIA_FV32:*out = "fv32"; return; + case CV_SHMEDIA_FV36:*out = "fv36"; return; + case CV_SHMEDIA_FV40:*out = "fv40"; return; + case CV_SHMEDIA_FV44:*out = "fv44"; return; + case CV_SHMEDIA_FV48:*out = "fv48"; return; + case CV_SHMEDIA_FV52:*out = "fv52"; return; + case CV_SHMEDIA_FV56:*out = "fv56"; return; + case CV_SHMEDIA_FV60:*out = "fv60"; return; + + // Matrix - 512 bit synonyms for 16 adjacent 32bit fp registers + // subtract 896 to find first base single register + case CV_SHMEDIA_MTRX0: *out = "mtrx0"; return; + case CV_SHMEDIA_MTRX16:*out = "mtrx16"; return; + case CV_SHMEDIA_MTRX32:*out = "mtrx32"; return; + case CV_SHMEDIA_MTRX48:*out = "mtrx48"; return; + + // Control - Implementation defined 64bit control registers + case CV_SHMEDIA_CR0: *out = "cr0"; return; + case CV_SHMEDIA_CR1: *out = "cr1"; return; + case CV_SHMEDIA_CR2: *out = "cr2"; return; + case CV_SHMEDIA_CR3: *out = "cr3"; return; + case CV_SHMEDIA_CR4: *out = "cr4"; return; + case CV_SHMEDIA_CR5: *out = "cr5"; return; + case CV_SHMEDIA_CR6: *out = "cr6"; return; + case CV_SHMEDIA_CR7: *out = "cr7"; return; + case CV_SHMEDIA_CR8: *out = "cr8"; return; + case CV_SHMEDIA_CR9: *out = "cr9"; return; + case CV_SHMEDIA_CR10:*out = "cr10"; return; + case CV_SHMEDIA_CR11:*out = "cr11"; return; + case CV_SHMEDIA_CR12:*out = "cr12"; return; + case CV_SHMEDIA_CR13:*out = "cr13"; return; + case CV_SHMEDIA_CR14:*out = "cr14"; return; + case CV_SHMEDIA_CR15:*out = "cr15"; return; + case CV_SHMEDIA_CR16:*out = "cr16"; return; + case CV_SHMEDIA_CR17:*out = "cr17"; return; + case CV_SHMEDIA_CR18:*out = "cr18"; return; + case CV_SHMEDIA_CR19:*out = "cr19"; return; + case CV_SHMEDIA_CR20:*out = "cr20"; return; + case CV_SHMEDIA_CR21:*out = "cr21"; return; + case CV_SHMEDIA_CR22:*out = "cr22"; return; + case CV_SHMEDIA_CR23:*out = "cr23"; return; + case CV_SHMEDIA_CR24:*out = "cr24"; return; + case CV_SHMEDIA_CR25:*out = "cr25"; return; + case CV_SHMEDIA_CR26:*out = "cr26"; return; + case CV_SHMEDIA_CR27:*out = "cr27"; return; + case CV_SHMEDIA_CR28:*out = "cr28"; return; + case CV_SHMEDIA_CR29:*out = "cr29"; return; + case CV_SHMEDIA_CR30:*out = "cr30"; return; + case CV_SHMEDIA_CR31:*out = "cr31"; return; + case CV_SHMEDIA_CR32:*out = "cr32"; return; + case CV_SHMEDIA_CR33:*out = "cr33"; return; + case CV_SHMEDIA_CR34:*out = "cr34"; return; + case CV_SHMEDIA_CR35:*out = "cr35"; return; + case CV_SHMEDIA_CR36:*out = "cr36"; return; + case CV_SHMEDIA_CR37:*out = "cr37"; return; + case CV_SHMEDIA_CR38:*out = "cr38"; return; + case CV_SHMEDIA_CR39:*out = "cr39"; return; + case CV_SHMEDIA_CR40:*out = "cr40"; return; + case CV_SHMEDIA_CR41:*out = "cr41"; return; + case CV_SHMEDIA_CR42:*out = "cr42"; return; + case CV_SHMEDIA_CR43:*out = "cr43"; return; + case CV_SHMEDIA_CR44:*out = "cr44"; return; + case CV_SHMEDIA_CR45:*out = "cr45"; return; + case CV_SHMEDIA_CR46:*out = "cr46"; return; + case CV_SHMEDIA_CR47:*out = "cr47"; return; + case CV_SHMEDIA_CR48:*out = "cr48"; return; + case CV_SHMEDIA_CR49:*out = "cr49"; return; + case CV_SHMEDIA_CR50:*out = "cr50"; return; + case CV_SHMEDIA_CR51:*out = "cr51"; return; + case CV_SHMEDIA_CR52:*out = "cr52"; return; + case CV_SHMEDIA_CR53:*out = "cr53"; return; + case CV_SHMEDIA_CR54:*out = "cr54"; return; + case CV_SHMEDIA_CR55:*out = "cr55"; return; + case CV_SHMEDIA_CR56:*out = "cr56"; return; + case CV_SHMEDIA_CR57:*out = "cr57"; return; + case CV_SHMEDIA_CR58:*out = "cr58"; return; + case CV_SHMEDIA_CR59:*out = "cr59"; return; + case CV_SHMEDIA_CR60:*out = "cr60"; return; + case CV_SHMEDIA_CR61:*out = "cr61"; return; + case CV_SHMEDIA_CR62:*out = "cr62"; return; + case CV_SHMEDIA_CR63:*out = "cr63"; return; + + case CV_SHMEDIA_FPSCR: *out = "fpscr"; return; + + // Compact mode synonyms +// case CV_SHMEDIA_GBR: *out = "gbr"; return; + case CV_SHMEDIA_MACL: *out = "macl"; return;// synonym for lower 32bits of media R17 + case CV_SHMEDIA_MACH: *out = "mach"; return;// synonym for upper 32bits of media R17 +// case CV_SHMEDIA_PR: *out = "pr"; return; + case CV_SHMEDIA_T: *out = "t"; return;// synonym for lowest bit of media R19 +// case CV_SHMEDIA_FPUL: *out = "fpul"; return; + case CV_SHMEDIA_PC: *out = "pc"; return; +// case CV_SHMEDIA_SR: *out = "sr"; return; + } + break; + + case CV_CFL_AMD64: + // + // AMD64 registers + // + switch ( reg ) + { + case CV_AMD64_AL: *out = "al"; return; + case CV_AMD64_CL: *out = "cl"; return; + case CV_AMD64_DL: *out = "dl"; return; + case CV_AMD64_BL: *out = "bl"; return; + case CV_AMD64_AH: *out = "ah"; return; + case CV_AMD64_CH: *out = "ch"; return; + case CV_AMD64_DH: *out = "dh"; return; + case CV_AMD64_BH: *out = "bh"; return; + case CV_AMD64_AX: *out = "ax"; return; + case CV_AMD64_CX: *out = "cx"; return; + case CV_AMD64_DX: *out = "dx"; return; + case CV_AMD64_BX: *out = "bx"; return; + case CV_AMD64_SP: *out = "sp"; return; + case CV_AMD64_BP: *out = "bp"; return; + case CV_AMD64_SI: *out = "si"; return; + case CV_AMD64_DI: *out = "di"; return; + case CV_AMD64_EAX: *out = "eax"; return; + case CV_AMD64_ECX: *out = "ecx"; return; + case CV_AMD64_EDX: *out = "edx"; return; + case CV_AMD64_EBX: *out = "ebx"; return; + case CV_AMD64_ESP: *out = "esp"; return; + case CV_AMD64_EBP: *out = "ebp"; return; + case CV_AMD64_ESI: *out = "esi"; return; + case CV_AMD64_EDI: *out = "edi"; return; + case CV_AMD64_ES: *out = "es"; return; + case CV_AMD64_CS: *out = "cs"; return; + case CV_AMD64_SS: *out = "ss"; return; + case CV_AMD64_DS: *out = "ds"; return; + case CV_AMD64_FS: *out = "fs"; return; + case CV_AMD64_GS: *out = "gs"; return; + case CV_AMD64_FLAGS: *out = "flags"; return; + case CV_AMD64_RIP: *out = "rip"; return; + case CV_AMD64_EFLAGS: *out = "eflags"; return; + + // Control registers + case CV_AMD64_CR0: *out = "cr0"; return; + case CV_AMD64_CR1: *out = "cr1"; return; + case CV_AMD64_CR2: *out = "cr2"; return; + case CV_AMD64_CR3: *out = "cr3"; return; + case CV_AMD64_CR4: *out = "cr4"; return; + case CV_AMD64_CR8: *out = "cr8"; return; + + // Debug registers + case CV_AMD64_DR0: *out = "dr0"; return; + case CV_AMD64_DR1: *out = "dr1"; return; + case CV_AMD64_DR2: *out = "dr2"; return; + case CV_AMD64_DR3: *out = "dr3"; return; + case CV_AMD64_DR4: *out = "dr4"; return; + case CV_AMD64_DR5: *out = "dr5"; return; + case CV_AMD64_DR6: *out = "dr6"; return; + case CV_AMD64_DR7: *out = "dr7"; return; + case CV_AMD64_DR8: *out = "dr8"; return; + case CV_AMD64_DR9: *out = "dr9"; return; + case CV_AMD64_DR10: *out = "dr10"; return; + case CV_AMD64_DR11: *out = "dr11"; return; + case CV_AMD64_DR12: *out = "dr12"; return; + case CV_AMD64_DR13: *out = "dr13"; return; + case CV_AMD64_DR14: *out = "dr14"; return; + case CV_AMD64_DR15: *out = "dr15"; return; + + case CV_AMD64_GDTR: *out = "gdtr"; return; + case CV_AMD64_GDTL: *out = "gdtl"; return; + case CV_AMD64_IDTR: *out = "idtr"; return; + case CV_AMD64_IDTL: *out = "idtl"; return; + case CV_AMD64_LDTR: *out = "ldtr"; return; + case CV_AMD64_TR: *out = "tr"; return; + + case CV_AMD64_ST0: *out = "st0"; return; + case CV_AMD64_ST1: *out = "st1"; return; + case CV_AMD64_ST2: *out = "st2"; return; + case CV_AMD64_ST3: *out = "st3"; return; + case CV_AMD64_ST4: *out = "st4"; return; + case CV_AMD64_ST5: *out = "st5"; return; + case CV_AMD64_ST6: *out = "st6"; return; + case CV_AMD64_ST7: *out = "st7"; return; + case CV_AMD64_CTRL: *out = "ctrl"; return; + case CV_AMD64_STAT: *out = "stat"; return; + case CV_AMD64_TAG: *out = "tag"; return; + case CV_AMD64_FPIP: *out = "fpip"; return; + case CV_AMD64_FPCS: *out = "fpcs"; return; + case CV_AMD64_FPDO: *out = "fpdo"; return; + case CV_AMD64_FPDS: *out = "fpds"; return; + case CV_AMD64_ISEM: *out = "isem"; return; + case CV_AMD64_FPEIP: *out = "fpeip"; return; + case CV_AMD64_FPEDO: *out = "fpedo"; return; + + case CV_AMD64_MM0: *out = "mm0"; return; + case CV_AMD64_MM1: *out = "mm1"; return; + case CV_AMD64_MM2: *out = "mm2"; return; + case CV_AMD64_MM3: *out = "mm3"; return; + case CV_AMD64_MM4: *out = "mm4"; return; + case CV_AMD64_MM5: *out = "mm5"; return; + case CV_AMD64_MM6: *out = "mm6"; return; + case CV_AMD64_MM7: *out = "mm7"; return; + + case CV_AMD64_XMM0: *out = "xmm0"; return;// KATMAI registers + case CV_AMD64_XMM1: *out = "xmm1"; return; + case CV_AMD64_XMM2: *out = "xmm2"; return; + case CV_AMD64_XMM3: *out = "xmm3"; return; + case CV_AMD64_XMM4: *out = "xmm4"; return; + case CV_AMD64_XMM5: *out = "xmm5"; return; + case CV_AMD64_XMM6: *out = "xmm6"; return; + case CV_AMD64_XMM7: *out = "xmm7"; return; + + case CV_AMD64_XMM0_0: *out = "xmm0_0"; return; // KATMAI sub-registers + case CV_AMD64_XMM0_1: *out = "xmm0_1"; return; + case CV_AMD64_XMM0_2: *out = "xmm0_2"; return; + case CV_AMD64_XMM0_3: *out = "xmm0_3"; return; + case CV_AMD64_XMM1_0: *out = "xmm1_0"; return; + case CV_AMD64_XMM1_1: *out = "xmm1_1"; return; + case CV_AMD64_XMM1_2: *out = "xmm1_2"; return; + case CV_AMD64_XMM1_3: *out = "xmm1_3"; return; + case CV_AMD64_XMM2_0: *out = "xmm2_0"; return; + case CV_AMD64_XMM2_1: *out = "xmm2_1"; return; + case CV_AMD64_XMM2_2: *out = "xmm2_2"; return; + case CV_AMD64_XMM2_3: *out = "xmm2_3"; return; + case CV_AMD64_XMM3_0: *out = "xmm3_0"; return; + case CV_AMD64_XMM3_1: *out = "xmm3_1"; return; + case CV_AMD64_XMM3_2: *out = "xmm3_2"; return; + case CV_AMD64_XMM3_3: *out = "xmm3_3"; return; + case CV_AMD64_XMM4_0: *out = "xmm4_0"; return; + case CV_AMD64_XMM4_1: *out = "xmm4_1"; return; + case CV_AMD64_XMM4_2: *out = "xmm4_2"; return; + case CV_AMD64_XMM4_3: *out = "xmm4_3"; return; + case CV_AMD64_XMM5_0: *out = "xmm5_0"; return; + case CV_AMD64_XMM5_1: *out = "xmm5_1"; return; + case CV_AMD64_XMM5_2: *out = "xmm5_2"; return; + case CV_AMD64_XMM5_3: *out = "xmm5_3"; return; + case CV_AMD64_XMM6_0: *out = "xmm6_0"; return; + case CV_AMD64_XMM6_1: *out = "xmm6_1"; return; + case CV_AMD64_XMM6_2: *out = "xmm6_2"; return; + case CV_AMD64_XMM6_3: *out = "xmm6_3"; return; + case CV_AMD64_XMM7_0: *out = "xmm7_0"; return; + case CV_AMD64_XMM7_1: *out = "xmm7_1"; return; + case CV_AMD64_XMM7_2: *out = "xmm7_2"; return; + case CV_AMD64_XMM7_3: *out = "xmm7_3"; return; + + case CV_AMD64_XMM0L: *out = "xmm0l"; return; + case CV_AMD64_XMM1L: *out = "xmm1l"; return; + case CV_AMD64_XMM2L: *out = "xmm2l"; return; + case CV_AMD64_XMM3L: *out = "xmm3l"; return; + case CV_AMD64_XMM4L: *out = "xmm4l"; return; + case CV_AMD64_XMM5L: *out = "xmm5l"; return; + case CV_AMD64_XMM6L: *out = "xmm6l"; return; + case CV_AMD64_XMM7L: *out = "xmm7l"; return; + + case CV_AMD64_XMM0H: *out = "xmm0h"; return; + case CV_AMD64_XMM1H: *out = "xmm1h"; return; + case CV_AMD64_XMM2H: *out = "xmm2h"; return; + case CV_AMD64_XMM3H: *out = "xmm3h"; return; + case CV_AMD64_XMM4H: *out = "xmm4h"; return; + case CV_AMD64_XMM5H: *out = "xmm5h"; return; + case CV_AMD64_XMM6H: *out = "xmm6h"; return; + case CV_AMD64_XMM7H: *out = "xmm7h"; return; + + case CV_AMD64_MXCSR: *out = "mxcsr"; return; // XMM status register + + case CV_AMD64_EMM0L: *out = "emm0l"; return; // XMM sub-registers (WNI integer) + case CV_AMD64_EMM1L: *out = "emm1l"; return; + case CV_AMD64_EMM2L: *out = "emm2l"; return; + case CV_AMD64_EMM3L: *out = "emm3l"; return; + case CV_AMD64_EMM4L: *out = "emm4l"; return; + case CV_AMD64_EMM5L: *out = "emm5l"; return; + case CV_AMD64_EMM6L: *out = "emm6l"; return; + case CV_AMD64_EMM7L: *out = "emm7l"; return; + + case CV_AMD64_EMM0H: *out = "emm0h"; return; + case CV_AMD64_EMM1H: *out = "emm1h"; return; + case CV_AMD64_EMM2H: *out = "emm2h"; return; + case CV_AMD64_EMM3H: *out = "emm3h"; return; + case CV_AMD64_EMM4H: *out = "emm4h"; return; + case CV_AMD64_EMM5H: *out = "emm5h"; return; + case CV_AMD64_EMM6H: *out = "emm6h"; return; + case CV_AMD64_EMM7H: *out = "emm7h"; return; + + // do not change the order of these regs, first one must be even too + case CV_AMD64_MM00: *out = "mm00"; return; + case CV_AMD64_MM01: *out = "mm01"; return; + case CV_AMD64_MM10: *out = "mm10"; return; + case CV_AMD64_MM11: *out = "mm11"; return; + case CV_AMD64_MM20: *out = "mm20"; return; + case CV_AMD64_MM21: *out = "mm21"; return; + case CV_AMD64_MM30: *out = "mm30"; return; + case CV_AMD64_MM31: *out = "mm31"; return; + case CV_AMD64_MM40: *out = "mm40"; return; + case CV_AMD64_MM41: *out = "mm41"; return; + case CV_AMD64_MM50: *out = "mm50"; return; + case CV_AMD64_MM51: *out = "mm51"; return; + case CV_AMD64_MM60: *out = "mm60"; return; + case CV_AMD64_MM61: *out = "mm61"; return; + case CV_AMD64_MM70: *out = "mm70"; return; + case CV_AMD64_MM71: *out = "mm71"; return; + + // Extended KATMAI registers + case CV_AMD64_XMM8: *out = "xmm8"; return;// KATMAI registers + case CV_AMD64_XMM9: *out = "xmm9"; return; + case CV_AMD64_XMM10: *out = "xmm10"; return; + case CV_AMD64_XMM11: *out = "xmm11"; return; + case CV_AMD64_XMM12: *out = "xmm12"; return; + case CV_AMD64_XMM13: *out = "xmm13"; return; + case CV_AMD64_XMM14: *out = "xmm14"; return; + case CV_AMD64_XMM15: *out = "xmm15"; return; + + case CV_AMD64_XMM8_0: *out = "xmm8_0"; return; // KATMAI sub-registers + case CV_AMD64_XMM8_1: *out = "xmm8_1"; return; + case CV_AMD64_XMM8_2: *out = "xmm8_2"; return; + case CV_AMD64_XMM8_3: *out = "xmm8_3"; return; + case CV_AMD64_XMM9_0: *out = "xmm9_0"; return; + case CV_AMD64_XMM9_1: *out = "xmm9_1"; return; + case CV_AMD64_XMM9_2: *out = "xmm9_2"; return; + case CV_AMD64_XMM9_3: *out = "xmm9_3"; return; + case CV_AMD64_XMM10_0:*out = "xmm10_0"; return; + case CV_AMD64_XMM10_1:*out = "xmm10_1"; return; + case CV_AMD64_XMM10_2:*out = "xmm10_2"; return; + case CV_AMD64_XMM10_3:*out = "xmm10_3"; return; + case CV_AMD64_XMM11_0:*out = "xmm11_0"; return; + case CV_AMD64_XMM11_1:*out = "xmm11_1"; return; + case CV_AMD64_XMM11_2:*out = "xmm11_2"; return; + case CV_AMD64_XMM11_3:*out = "xmm11_3"; return; + case CV_AMD64_XMM12_0:*out = "xmm12_0"; return; + case CV_AMD64_XMM12_1:*out = "xmm12_1"; return; + case CV_AMD64_XMM12_2:*out = "xmm12_2"; return; + case CV_AMD64_XMM12_3:*out = "xmm12_3"; return; + case CV_AMD64_XMM13_0:*out = "xmm13_0"; return; + case CV_AMD64_XMM13_1:*out = "xmm13_1"; return; + case CV_AMD64_XMM13_2:*out = "xmm13_2"; return; + case CV_AMD64_XMM13_3:*out = "xmm13_3"; return; + case CV_AMD64_XMM14_0:*out = "xmm14_0"; return; + case CV_AMD64_XMM14_1:*out = "xmm14_1"; return; + case CV_AMD64_XMM14_2:*out = "xmm14_2"; return; + case CV_AMD64_XMM14_3:*out = "xmm14_3"; return; + case CV_AMD64_XMM15_0:*out = "xmm15_0"; return; + case CV_AMD64_XMM15_1:*out = "xmm15_1"; return; + case CV_AMD64_XMM15_2:*out = "xmm15_2"; return; + case CV_AMD64_XMM15_3:*out = "xmm15_3"; return; + + case CV_AMD64_XMM8L: *out = "xmm8l"; return; + case CV_AMD64_XMM9L: *out = "xmm9l"; return; + case CV_AMD64_XMM10L: *out = "xmm10l"; return; + case CV_AMD64_XMM11L: *out = "xmm11l"; return; + case CV_AMD64_XMM12L: *out = "xmm12l"; return; + case CV_AMD64_XMM13L: *out = "xmm13l"; return; + case CV_AMD64_XMM14L: *out = "xmm14l"; return; + case CV_AMD64_XMM15L: *out = "xmm15l"; return; + + case CV_AMD64_XMM8H: *out = "xmm8h"; return; + case CV_AMD64_XMM9H: *out = "xmm9h"; return; + case CV_AMD64_XMM10H: *out = "xmm10h"; return; + case CV_AMD64_XMM11H: *out = "xmm11h"; return; + case CV_AMD64_XMM12H: *out = "xmm12h"; return; + case CV_AMD64_XMM13H: *out = "xmm13h"; return; + case CV_AMD64_XMM14H: *out = "xmm14h"; return; + case CV_AMD64_XMM15H: *out = "xmm15h"; return; + + case CV_AMD64_EMM8L: *out = "emm8l"; return; // XMM sub-registers (WNI integer) + case CV_AMD64_EMM9L: *out = "emm9l"; return; + case CV_AMD64_EMM10L: *out = "emm10l"; return; + case CV_AMD64_EMM11L: *out = "emm11l"; return; + case CV_AMD64_EMM12L: *out = "emm12l"; return; + case CV_AMD64_EMM13L: *out = "emm13l"; return; + case CV_AMD64_EMM14L: *out = "emm14l"; return; + case CV_AMD64_EMM15L: *out = "emm15l"; return; + + case CV_AMD64_EMM8H: *out = "emm8h"; return; + case CV_AMD64_EMM9H: *out = "emm9h"; return; + case CV_AMD64_EMM10H: *out = "emm10h"; return; + case CV_AMD64_EMM11H: *out = "emm11h"; return; + case CV_AMD64_EMM12H: *out = "emm12h"; return; + case CV_AMD64_EMM13H: *out = "emm13h"; return; + case CV_AMD64_EMM14H: *out = "emm14h"; return; + case CV_AMD64_EMM15H: *out = "emm15h"; return; + + // Low byte forms of some standard registers + case CV_AMD64_SIL: *out = "sil"; return; + case CV_AMD64_DIL: *out = "dil"; return; + case CV_AMD64_BPL: *out = "bpl"; return; + case CV_AMD64_SPL: *out = "spl"; return; + + // 64-bit regular registers + case CV_AMD64_RAX: *out = "rax"; return; + case CV_AMD64_RBX: *out = "rbx"; return; + case CV_AMD64_RCX: *out = "rcx"; return; + case CV_AMD64_RDX: *out = "rdx"; return; + case CV_AMD64_RSI: *out = "rsi"; return; + case CV_AMD64_RDI: *out = "rdi"; return; + case CV_AMD64_RBP: *out = "rbp"; return; + case CV_AMD64_RSP: *out = "rsp"; return; + + // 64-bit integer registers with 8-, 16-, and 32-bit forms (B, W, and D) + case CV_AMD64_R8: *out = "r8"; return; + case CV_AMD64_R9: *out = "r9"; return; + case CV_AMD64_R10: *out = "r10"; return; + case CV_AMD64_R11: *out = "r11"; return; + case CV_AMD64_R12: *out = "r12"; return; + case CV_AMD64_R13: *out = "r13"; return; + case CV_AMD64_R14: *out = "r14"; return; + case CV_AMD64_R15: *out = "r15"; return; + + case CV_AMD64_R8B: *out = "r8b"; return; + case CV_AMD64_R9B: *out = "r9b"; return; + case CV_AMD64_R10B: *out = "r10b"; return; + case CV_AMD64_R11B: *out = "r11b"; return; + case CV_AMD64_R12B: *out = "r12b"; return; + case CV_AMD64_R13B: *out = "r13b"; return; + case CV_AMD64_R14B: *out = "r14b"; return; + case CV_AMD64_R15B: *out = "r15b"; return; + + case CV_AMD64_R8W: *out = "r8w"; return; + case CV_AMD64_R9W: *out = "r9w"; return; + case CV_AMD64_R10W: *out = "r10w"; return; + case CV_AMD64_R11W: *out = "r11w"; return; + case CV_AMD64_R12W: *out = "r12w"; return; + case CV_AMD64_R13W: *out = "r13w"; return; + case CV_AMD64_R14W: *out = "r14w"; return; + case CV_AMD64_R15W: *out = "r15w"; return; + + case CV_AMD64_R8D: *out = "r8d"; return; + case CV_AMD64_R9D: *out = "r9d"; return; + case CV_AMD64_R10D: *out = "r10d"; return; + case CV_AMD64_R11D: *out = "r11d"; return; + case CV_AMD64_R12D: *out = "r12d"; return; + case CV_AMD64_R13D: *out = "r13d"; return; + case CV_AMD64_R14D: *out = "r14d"; return; + case CV_AMD64_R15D: *out = "r15d"; return; + } + + default: + break; + } + out->sprnt("reg %d", reg); +} diff --git a/idasdk75/plugins/pdb/cvconst.h b/idasdk76/plugins/pdb/cvconst.h similarity index 100% rename from idasdk75/plugins/pdb/cvconst.h rename to idasdk76/plugins/pdb/cvconst.h diff --git a/idasdk75/plugins/pdb/dbghelp.h b/idasdk76/plugins/pdb/dbghelp.h similarity index 100% rename from idasdk75/plugins/pdb/dbghelp.h rename to idasdk76/plugins/pdb/dbghelp.h diff --git a/idasdk75/plugins/pdb/dia2.h b/idasdk76/plugins/pdb/dia2.h similarity index 100% rename from idasdk75/plugins/pdb/dia2.h rename to idasdk76/plugins/pdb/dia2.h diff --git a/idasdk76/plugins/pdb/makefile b/idasdk76/plugins/pdb/makefile new file mode 100644 index 0000000..2242694 --- /dev/null +++ b/idasdk76/plugins/pdb/makefile @@ -0,0 +1,15 @@ +PROC=pdb +CONFIGS=pdb.cfg + +ifdef __NT__ + O1=old + STDLIBS += ole32.lib + STDLIBS += oleaut32.lib +else + LIBS += $(L)network$(A) +endif + +include ../plugin.mak + +$(F)pdb$(O): CC_WNO-$(call gte,$(GCC_VERSION),6.1) += -Wno-null-dereference + diff --git a/idasdk75/plugins/pdb/misc.cpp b/idasdk76/plugins/pdb/misc.cpp similarity index 100% rename from idasdk75/plugins/pdb/misc.cpp rename to idasdk76/plugins/pdb/misc.cpp diff --git a/idasdk76/plugins/pdb/msdia.cpp b/idasdk76/plugins/pdb/msdia.cpp new file mode 100644 index 0000000..6372835 --- /dev/null +++ b/idasdk76/plugins/pdb/msdia.cpp @@ -0,0 +1,1150 @@ + +// This file is included from 4 places: +// - efd/pdb.cpp efd: to dump pdb contents +// - base/pdb2til.cpp tilib: to convert pdb to til +// - plugins/pdb/pdb.cpp ida: read pdb info and populate idb +// - dbg/win32_server/tilfuncs.cpp win32_server: read pdb info and send it to ida +// +// The following symbols may be defined: +// PDB_PLUGIN pdb +// PDB_WIN32_SERVER win32_server + +#include <diskio.hpp> + +#include "msdia.hpp" + +#include "../../ldr/pe/pe.h" +#include "pdblocal.cpp" + +//lint -esym(843, g_diadlls, g_pdb_errors, PathIsUNC) could be declared as const + +int pdb_session_t::session_count = 0; +bool pdb_session_t::co_initialized = false; + +typedef BOOL (__stdcall *PathIsUNC_t)(LPCTSTR pszPath); +static PathIsUNC_t PathIsUNC = NULL; + +static bool check_for_odd_paths(const char *fname); + +//--------------------------------------------------------------------------- +class msdia_reader_t +{ +public: + virtual ~msdia_reader_t() {} + virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) = 0; + virtual bool setup(void) { return true; } +}; + +//--------------------------------------------------------------------------- +class local_exe_msdia_reader_t : public msdia_reader_t +{ + LPCWSTR FileName; + HANDLE hFile; + +public: + local_exe_msdia_reader_t(LPCWSTR _FileName) + { + FileName = _FileName; + hFile = INVALID_HANDLE_VALUE; + } + + ~local_exe_msdia_reader_t(void) + { + if ( hFile != INVALID_HANDLE_VALUE ) + CloseHandle(hFile); + } + + virtual bool setup(void) override + { + hFile = CreateFileW( + FileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + return hFile != INVALID_HANDLE_VALUE; + } + + virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) override + { + if ( hFile == INVALID_HANDLE_VALUE ) + return false; + + LARGE_INTEGER pos; + pos.QuadPart = (LONGLONG) offset; + if ( SetFilePointerEx(hFile, pos, NULL, FILE_BEGIN) == 0 ) + return false; + + if ( ReadFile(hFile, buf, count, (DWORD *) nread, NULL) == 0 ) + return false; + + return true; + } +}; + +#ifdef PDB_PLUGIN +//--------------------------------------------------------------------------- +class local_mem_msdia_reader_t : public msdia_reader_t +{ +public: + virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) override + { + if ( get_bytes(buf, count, offset) != count ) + return false; + *nread = count; + return true; + } +}; + +#elif defined(PDB_WIN32_SERVER) +//--------------------------------------------------------------------------- +class win32_msdia_reader_t : public msdia_reader_t +{ + pdb_remote_session_t *pdb_rsess; + pdb_rr_kind_t kind; +public: + win32_msdia_reader_t(void *_pdb_rsess, pdb_rr_kind_t _kind) + { + pdb_rsess = (pdb_remote_session_t *) _pdb_rsess; + kind = _kind; + } + + virtual bool read(uint64 offset, void *buf, uint32 count, uint32 *nread) override + { + return pdb_rsess->client_read_request.request_read(kind, offset, count, buf, nread); + } +}; + +#endif + +//---------------------------------------------------------------------- +// Common code for PDB handling +//---------------------------------------------------------------------- +class CCallback : public IDiaLoadCallback2, + public IDiaReadExeAtRVACallback, + public IDiaReadExeAtOffsetCallback +{ + unsigned int m_nRefCount; + ea_t m_load_address; + msdia_reader_t *msdia_reader; + pdb_session_t *pdb_session; + DWORDLONG last_cv_off; + ea_t last_cv_rva; +public: + CCallback(pdb_session_t *_pdb_session, + msdia_reader_t *_msdia_reader, + ea_t _load_address) + : msdia_reader(_msdia_reader), + m_load_address(_load_address), + // Note: we initialize the reference count to 1 since the only + // instance of this object is created in the stack, and + // the destructor will take care of the cleanup. + m_nRefCount(1), + pdb_session(_pdb_session), + last_cv_off(0), + last_cv_rva(BADADDR) + { + } + + // IUnknown + ULONG STDMETHODCALLTYPE AddRef() + { + return InterlockedIncrement(&m_nRefCount); + } + + ULONG STDMETHODCALLTYPE Release() + { + // Note: we don't check the reference count and delete the object + // (see comment for the m_nRefCount field). + return InterlockedDecrement(&m_nRefCount); + } + + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID rid, void **ppUnk) + { + if ( ppUnk == NULL ) + return E_INVALIDARG; + + *ppUnk = NULL; + if ( rid == __uuidof(IDiaLoadCallback2) || rid == __uuidof(IDiaLoadCallback) ) + { + *ppUnk = (IDiaLoadCallback2 *)this; + } + else if ( rid == __uuidof(IDiaReadExeAtRVACallback) ) + { + // we may use only one of IDiaReadExeAtRVACallback and IDiaReadExeAtOffsetCallback + // claiming that both are supported will lead to crashes in MSDIA + if ( m_load_address != BADADDR ) + *ppUnk = (IDiaReadExeAtRVACallback *)this; + } + else if ( rid == __uuidof(IDiaReadExeAtOffsetCallback) ) + { + // see the comment above about IDiaReadExeAtRVACallback + if ( m_load_address == BADADDR ) + *ppUnk = (IDiaReadExeAtOffsetCallback *)this; + } + else if ( rid == __uuidof(IUnknown) ) + { + *ppUnk = (IUnknown *)(IDiaLoadCallback *)this; + } + if ( *ppUnk == NULL ) + return E_NOINTERFACE; + AddRef(); + return S_OK; + } + + HRESULT STDMETHODCALLTYPE NotifyDebugDir( + BOOL fExecutable, + DWORD cbData, + BYTE data[]) + { + // msdia90.dll can crash on bogus CV data + // so we remember the offset here and check it in ReadFileAt + if ( fExecutable && cbData >= sizeof(debug_entry_t) ) + { + debug_entry_t &de = *(debug_entry_t *)data; + if ( de.type == DBG_CV ) + { + last_cv_off = de.seek; + last_cv_rva = de.rva; + } + } + return S_OK; + } + HRESULT STDMETHODCALLTYPE NotifyOpenDBG( + LPCOLESTR dbgPath, + HRESULT resultCode) + { + if ( resultCode == S_OK ) + deb(IDA_DEBUG_DEBUGGER, "MSDIA: dbg file \"%S\" matched\n", dbgPath); + else + deb(IDA_DEBUG_DEBUGGER, "MSDIA: \"%S\": %s\n", dbgPath, pdberr(resultCode)); + + return S_OK; + } + + HRESULT STDMETHODCALLTYPE NotifyOpenPDB( + LPCOLESTR pdbPath, + HRESULT resultCode) + { + if ( resultCode == S_OK ) + deb(IDA_DEBUG_DEBUGGER, "MSDIA: pdb file \"%S\" matched\n", pdbPath); + else + deb(IDA_DEBUG_DEBUGGER, "MSDIA: \"%S\": %s\n", pdbPath, pdberr(resultCode)); +#ifdef _DEBUG + qstring spath; + utf16_utf8(&spath, pdbPath); + pdb_session->_pdb_path = spath; +#endif + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictRegistryAccess() + { + // return hr != S_OK to prevent querying the registry for symbol search paths + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictSymbolServerAccess() + { + // return hr != S_OK to prevent accessing a symbol server + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictOriginalPathAccess() + { + // return hr != S_OK to prevent querying the registry for symbol search paths + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictReferencePathAccess() + { + // return hr != S_OK to prevent accessing a symbol server + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictDBGAccess() + { + return S_OK; + } + HRESULT STDMETHODCALLTYPE RestrictSystemRootAccess() + { + return S_OK; + } + + bool check_codeview_data(BYTE pbData[], DWORD cbData) + { + bool ok = true; + if ( cbData > 4 ) + { + // check that the data has a valid NB or RSDS signature and PDB path doesn't look suspicious + ok = false; + if ( pbData[0] == 'N' && pbData[1] == 'B' && cbData >= sizeof(cv_info_pdb20_t) ) + { + char *pdbname = (char*)pbData + sizeof(cv_info_pdb20_t); + pbData[cbData-1] = '\0'; + ok = check_for_odd_paths(pdbname); + } + else if ( memcmp(pbData, "RSDS", 4) == 0 && cbData >= sizeof(rsds_t) ) + { + char *pdbname = (char*)pbData + sizeof(rsds_t); + pbData[cbData-1] = '\0'; + ok = check_for_odd_paths(pdbname); + } + } + return ok; + } + + // IDiaReadExeAtRVACallback + HRESULT STDMETHODCALLTYPE ReadExecutableAtRVA( + DWORD relativeVirtualAddress, + DWORD cbData, + DWORD *pcbData, + BYTE data[]) + { + ea_t ea = m_load_address + relativeVirtualAddress; + if ( !msdia_reader->read(ea, data, cbData, (uint32 *) pcbData) ) + return E_FAIL; + // are we reading the CV debug directory entry? + if ( relativeVirtualAddress == last_cv_rva ) + return check_codeview_data(data, cbData) ? S_OK : E_FAIL; + return S_OK; + } + + // IDiaReadExeAtOffsetCallback + HRESULT STDMETHODCALLTYPE ReadExecutableAt( + DWORDLONG fileOffset, + DWORD cbData, + DWORD *pcbData, + BYTE data[]) + { + if ( !msdia_reader->read(fileOffset, data, cbData, (uint32 *) pcbData) ) + return E_FAIL; + // are we reading the CV debug directory entry? + if ( fileOffset != 0 && last_cv_off == fileOffset ) + return check_codeview_data(data, cbData) ? S_OK : E_FAIL; + return S_OK; + } +}; + +//--------------------------------------------------------------------------- +template<class T> void print_generic(T t) +{ + IDiaPropertyStorage *pPropertyStorage; + HRESULT hr = t->QueryInterface(__uuidof(IDiaPropertyStorage), (void **)&pPropertyStorage); + if ( hr == S_OK ) + { + print_property_storage(pPropertyStorage); + pPropertyStorage->Release(); + } +} + +//--------------------------------------------------------------------------- +static const char *const g_pdb_errors[] = +{ + "Operation successful (E_PDB_OK)", + "(E_PDB_USAGE)", + "Out of memory (E_PDB_OUT_OF_MEMORY)", + "(E_PDB_FILE_SYSTEM)", + "Failed to open the file, or the file has an invalid format (E_PDB_NOT_FOUND)", + "Signature does not match (E_PDB_INVALID_SIG)", + "Age does not match (E_PDB_INVALID_AGE)", + "(E_PDB_PRECOMP_REQUIRED)", + "(E_PDB_OUT_OF_TI)", + "(E_PDB_NOT_IMPLEMENTED)", + "(E_PDB_V1_PDB)", + "Attempted to access a file with an obsolete format (E_PDB_FORMAT)", + "(E_PDB_LIMIT)", + "(E_PDB_CORRUPT)", + "(E_PDB_TI16)", + "(E_PDB_ACCESS_DENIED)", + "(E_PDB_ILLEGAL_TYPE_EDIT)", + "(E_PDB_INVALID_EXECUTABLE)", + "(E_PDB_DBG_NOT_FOUND)", + "(E_PDB_NO_DEBUG_INFO)", + "(E_PDB_INVALID_EXE_TIMESTAMP)", + "(E_PDB_RESERVED)", + "(E_PDB_DEBUG_INFO_NOT_IN_PDB)", + "(E_PDB_SYMSRV_BAD_CACHE_PATH)", + "(E_PDB_SYMSRV_CACHE_FULL)", +}; + +//--------------------------------------------------------------------------- +inline void pdberr_suggest_vs_runtime(HRESULT hr) +{ + if ( hr == E_NOINTERFACE ) + { + msg("<< It appears that MS DIA SDK is not installed.\n"); +#ifdef __X86__ + msg("Please try installing \"Microsoft Visual C++ 2008 Redistributable Package / x86\" >>\n"); +#else + msg("Please try installing \"Microsoft Visual C++ 2008 Redistributable Package / x64\" >>\n"); +#endif + } +} + +//--------------------------------------------------------------------------- +const char *pdberr(int code) +{ + switch ( code ) + { // tab in first pos is flag for replace warning to msg + case E_INVALIDARG: return "Invalid parameter."; + case E_UNEXPECTED: return "Data source has already been prepared."; + default: + if ( code >= E_PDB_OK && (code - E_PDB_OK) < qnumber(g_pdb_errors) ) + return g_pdb_errors[code - E_PDB_OK]; + } + return winerr(code); +} + +//---------------------------------------------------------------------- +class DECLSPEC_UUID("4C41678E-887B-4365-A09E-925D28DB33C2") DiaSource90; +class DECLSPEC_UUID("1fbd5ec4-b8e4-4d94-9efe-7ccaf9132c98") DiaSource80; +class DECLSPEC_UUID("31495af6-0897-4f1e-8dac-1447f10174a1") DiaSource71; +static const GUID *const g_d90 = &__uuidof(DiaSource90); // msdia90.dll +static const GUID *const g_d80 = &__uuidof(DiaSource80); // msdia80.dll +static const GUID *const g_d71 = &__uuidof(DiaSource71); // msdia71.dll +static const GUID *const g_msdiav[] = { g_d90, g_d80, g_d71 }; +static const int g_diaver[] = { 900, 800, 710 }; +static const char *const g_diadlls[] = { "msdia90.dll", "msdia80.dll", "msdia71.dll" }; + +//---------------------------------------------------------------------- +HRESULT __stdcall CoCreateInstanceNoReg( + LPCTSTR szDllName, + IN REFCLSID rclsid, + IUnknown *pUnkOuter, + IN REFIID riid, + OUT LPVOID FAR *ppv, + OUT HMODULE *phMod) +{ + // http://lallousx86.wordpress.com/2007/01/29/emulating-cocreateinstance/ + HRESULT hr = REGDB_E_CLASSNOTREG; + HMODULE hDll; + do + { + hDll = LoadLibrary(szDllName); + if ( hDll == NULL ) + break; + + HRESULT (__stdcall *GetClassObject)(REFCLSID rclsid, REFIID riid, LPVOID FAR *ppv); + *(FARPROC*)&GetClassObject = GetProcAddress(hDll, "DllGetClassObject"); + if ( GetClassObject == NULL ) + break; + + IClassFactory *pIFactory; + hr = GetClassObject(rclsid, IID_IClassFactory, (LPVOID *)&pIFactory); + if ( FAILED(hr) ) + break; + + hr = pIFactory->CreateInstance(pUnkOuter, riid, ppv); + pIFactory->Release(); + } + while ( false ); + + if ( FAILED(hr) && hDll != NULL ) + FreeLibrary(hDll); + else + *phMod = hDll; + + return hr; +} + +//---------------------------------------------------------------------------- +// Note: This will return the machine type, as it is known +// by the IDB, which might not be what you think. For example, +// if you need to tell x86 and x64 apart, you're out of luck. +// You may want to consider looking at pdbaccess_t's +// get_machine_type(). +static DWORD get_machine_type(DWORD dwMachType) +{ + DWORD machine; + switch ( dwMachType ) + { + default: + machine = CV_CFL_80386; + break; + case IMAGE_FILE_MACHINE_IA64: + machine = CV_CFL_IA64; + break; + case IMAGE_FILE_MACHINE_AMD64: + machine = CV_CFL_AMD64; + break; + case IMAGE_FILE_MACHINE_THUMB: + case IMAGE_FILE_MACHINE_ARM: + machine = CV_CFL_ARM6; + break; + case PECPU_ARMV7: + machine = CV_CFL_ARM7; + break; + case PECPU_PPC: + machine = CV_CFL_PPC620; + break; + case PECPU_PPCFP: + machine = CV_CFL_PPCFP; + break; + case PECPU_PPCBE: + machine = CV_CFL_PPCBE; + break; + } + return machine; +} + +//---------------------------------------------------------------------- +pdb_session_t::~pdb_session_t() +{ + if ( --session_count == 0 && co_initialized ) + { + CoUninitialize(); + co_initialized = false; + } +} + +//---------------------------------------------------------------------- +void pdb_session_t::close() +{ + if ( pdb_access != NULL ) + { + delete pdb_access; + pdb_access = NULL; + } + + if ( dia_hmod != NULL ) + { + FreeLibrary(dia_hmod); + dia_hmod = NULL; + } + +#ifdef _DEBUG + if ( !_pdb_path.empty() && qfileexist(_pdb_path.begin() ) ) + { + HANDLE hFile = CreateFileA(_pdb_path.begin(), GENERIC_READ, /*FILE_SHARE_READ*/ 0, 0, OPEN_EXISTING, 0, 0); + if ( hFile == INVALID_HANDLE_VALUE ) + warning("Couldn't acquire probing lock to \"%s\"; file might be still locked by IDA", _pdb_path.begin()); + else + CloseHandle(hFile); + } +#endif +} + +//---------------------------------------------------------------------- +typedef BOOL (CALLBACK *SymbolServerSetOptions_t)(UINT_PTR options, ULONG64 data); +typedef BOOL (CALLBACK *SymbolServerGetOptionData_t)(UINT_PTR option, PULONG64 pData); + +#include "dbghelp.h" +// copied from dbghelp.h +#ifndef SSRVOPT_CALLBACK +#define SSRVOPT_CALLBACK 0x000001 +#endif +#ifndef SSRVOPT_SETCONTEXT +#define SSRVOPT_SETCONTEXT 0x000800 +#endif +#ifndef SSRVOPT_TRACE +#define SSRVOPT_TRACE 0x000400 +#endif +#ifndef SSRVACTION_TRACE +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 +#define SSRVACTION_EVENTW 4 +#endif +#ifndef SSRVACTION_SIZE +#define SSRVACTION_SIZE 5 +#endif + +//---------------------------------------------------------------------- +static void symsrv_dprint(const char *str) +{ + qstring qbuf(str); + qbuf.replace("\b", ""); // remove backspaces + if ( qbuf.empty() ) + return; + // strings usually already start with "SYMSRV: " + if ( strncmp(qbuf.c_str(), "SYMSRV: ", 9) != 0 ) + qbuf.insert(0, "SYMSRV: "); + // strings usually already end with '\n' + if ( qbuf.last() != '\n' ) + qbuf.append('\n'); + deb(IDA_DEBUG_DEBUGGER, "%s", qbuf.c_str()); +} + +//---------------------------------------------------------------------- +static BOOL CALLBACK SymbolServerCallback( + UINT_PTR action, + ULONG64 data, + ULONG64 context) +{ + switch ( action ) + { + case SSRVACTION_SIZE: + { + bool *wait_box_shown = (bool *) context; + if ( !*wait_box_shown ) + show_wait_box("Downloading pdb..."); + *wait_box_shown = true; + } + break; + case SSRVACTION_QUERYCANCEL: + { + BOOL *do_cancel = (BOOL *) data; + if ( user_cancelled() ) + *do_cancel = TRUE; + } + break; + case SSRVACTION_TRACE: + symsrv_dprint((const char *)data); + break; + case SSRVACTION_EVENT: + IMAGEHLP_CBA_EVENT *pev = (IMAGEHLP_CBA_EVENT*)data; + // Event information is usually all zero. + if ( pev->severity != 0 || pev->code != 0 || pev->object != NULL ) + deb(IDA_DEBUG_DEBUGGER, "SYMSRV: event severity: %d code: %d object: %p\n", pev->severity, pev->code, pev->object); + symsrv_dprint(pev->desc); + break; + } + return TRUE; +} + +//---------------------------------------------------------------------------- +class symsrv_cb_t +{ + HMODULE symsrv_hmod; + bool wait_box_shown; + SymbolServerGetOptionData_t get_option_data; // "DbgHelp.dll 10.0 or later" + SymbolServerSetOptions_t set_options; + ULONG64 was_context; + ULONG64 was_callback; + +public: + symsrv_cb_t(void) + { + symsrv_hmod = LoadLibrary("symsrv.dll"); + wait_box_shown = false; + get_option_data = NULL; + set_options = NULL; + was_context = 0; + was_callback = 0; + } + + void init(void) + { + if ( symsrv_hmod != NULL ) + { + get_option_data = (SymbolServerGetOptionData_t)(void *)GetProcAddress(symsrv_hmod, "SymbolServerGetOptionData"); + if ( get_option_data != NULL ) + { + was_context = get_option_data(SSRVOPT_SETCONTEXT, &was_context); + was_callback = get_option_data(SSRVOPT_CALLBACK, &was_callback); + } + + set_options = (SymbolServerSetOptions_t)(void *)GetProcAddress(symsrv_hmod, "SymbolServerSetOptions"); + if ( set_options != NULL ) + { + set_options(SSRVOPT_SETCONTEXT, (ULONG64) (intptr_t) &wait_box_shown); + set_options(SSRVOPT_CALLBACK, (ULONG64) SymbolServerCallback); + if ( (debug & IDA_DEBUG_DEBUGGER) != 0 ) + { + set_options(SSRVOPT_TRACE, (ULONG64) TRUE); + } + } + } + } + + void term(void) + { + if ( symsrv_hmod != NULL ) + { + if ( set_options != NULL ) + { + set_options(SSRVOPT_SETCONTEXT, was_context); + set_options(SSRVOPT_CALLBACK, was_callback); + } + FreeLibrary(symsrv_hmod); + symsrv_hmod = NULL; + if ( wait_box_shown ) + hide_wait_box(); + } + } +}; + +//---------------------------------------------------------------------------- +static qstring print_guid(GUID *guid) +{ + qstring guid_str; + if ( guid != NULL ) + { + OLECHAR *guid_wstr = NULL; + StringFromCLSID(*guid, &guid_wstr); + if ( guid_wstr != NULL ) + { + utf16_utf8(&guid_str, guid_wstr); + CoTaskMemFree(guid_wstr); + } + } + if ( guid_str.empty() ) + guid_str = "{00000000-0000-0000-0000-000000000000}"; + return guid_str; +} + +//---------------------------------------------------------------------------- +static HRESULT check_and_load_pdb( + IDiaDataSource *pSource, + LPCOLESTR pdb_path, + const pdb_signature_t &pdb_sign, + bool load_anyway) +{ + HRESULT hr = E_FAIL; + if ( !load_anyway ) + { + uint32 sig = pdb_sign.sig; + uint32 age = pdb_sign.age; + GUID *pcsig70 = NULL; + for ( int i=0; i < qnumber(pdb_sign.guid); i++ ) + { + if ( pdb_sign.guid[i] != 0 ) + { + pcsig70 = (GUID *)&pdb_sign.guid; + break; + } + } + if ( sig == 0 && age == 0 && pcsig70 == NULL ) + return E_FAIL; + qstring guid_str = print_guid(pcsig70); + deb(IDA_DEBUG_DEBUGGER, "PDB: Trying to load PDB \"%S\" (guid %s, sig 0x%08X, age 0x%08X)\n", pdb_path, guid_str.c_str(), sig, age); + hr = pSource->loadAndValidateDataFromPdb(pdb_path, pcsig70, sig, age); + deb(IDA_DEBUG_DEBUGGER, "PDB: loadAndValidateDataFromPdb(\"%S\"): %s\n", pdb_path, pdberr(hr)); + if ( hr == E_PDB_INVALID_SIG || hr == E_PDB_INVALID_AGE ) + { + load_anyway = ask_yn(ASKBTN_NO, + "HIDECANCEL\nICON WARNING\nAUTOHIDE NONE\n" + "PDB signature and/or age does not match the input file.\n" + "Do you want to load it anyway?") == ASKBTN_YES; + } + } + if ( load_anyway ) + { + hr = pSource->loadDataFromPdb(pdb_path); + deb(IDA_DEBUG_DEBUGGER, "PDB: loadDataFromPdb(\"%S\"): %s\n", pdb_path, pdberr(hr)); + } + return hr; +} + +//---------------------------------------------------------------------------- +// warn the user about eventual UNC or other problematic paths +static bool check_for_odd_paths(const char *fname) +{ + if ( PathIsUNC == NULL ) + { + HMODULE h = GetModuleHandle("shlwapi.dll"); + if ( h != NULL ) + PathIsUNC = (PathIsUNC_t)(void*)GetProcAddress(h, "PathIsUNCA"); + } + if ( fname[0] == '\\' + || fname[0] == '/' + || PathIsUNC != NULL && PathIsUNC(fname) ) + { + if ( ask_yn(ASKBTN_NO, + "AUTOHIDE NONE\nHIDECANCEL\n" + "Please be careful, the debug path looks odd!\n" + "\"%s\"\n" + "Do you really want IDA to access this path (possibly a remote server)?", + fname) != ASKBTN_YES ) + { + return false; + } + } + return true; +} + +//--------------------------------------------------------------------------- +HRESULT pdb_session_t::load_data_for_exe( + const pdbargs_t &pdbargs, + load_data_type_t type) +{ + // First check for load address. + ea_t load_address = BADADDR; + if ( type == MEM_LOCAL || type == MEM_WIN32 ) + { + load_address = pdbargs.loaded_base; + if ( load_address == BADADDR ) + return E_FAIL; + } + + msdia_reader_t *msdia_reader = NULL; + HRESULT hr = E_FAIL; + switch ( type ) + { + case EXE_LOCAL: + msdia_reader = new local_exe_msdia_reader_t(winput.c_str()); + break; +#ifdef PDB_PLUGIN + case MEM_LOCAL: + msdia_reader = new local_mem_msdia_reader_t; + break; +#elif defined(PDB_WIN32_SERVER) + case EXE_WIN32: + msdia_reader = new win32_msdia_reader_t(pdbargs.user_data, READ_INPUT_FILE); + break; + case MEM_WIN32: + msdia_reader = new win32_msdia_reader_t(pdbargs.user_data, READ_MEMORY); + break; +#endif + default: + break; + } + if ( msdia_reader->setup() ) + { + qstring buf; + if ( load_address != BADADDR ) + buf.sprnt(" with load address %a", load_address); + deb(IDA_DEBUG_DEBUGGER, "PDB: Trying loadDataForExe(\"%S\", \"%S\")%s\n", winput.c_str(), wspath.c_str(), buf.c_str()); + + CCallback callback(this, msdia_reader, load_address); + hr = pSource->loadDataForExe(winput.c_str(), wspath.c_str(), (IDiaLoadCallback *)&callback); + + deb(IDA_DEBUG_DEBUGGER, "PDB: %s\n", pdberr(hr)); + } + delete msdia_reader; + + return hr; +} + +//---------------------------------------------------------------------------- +HRESULT pdb_session_t::load_input_path( + const pdbargs_t &pdbargs, + const char *input_path) +{ + utf8_utf16(&wspath, pdbargs.spath.c_str()); + utf8_utf16(&winput, input_path); + + qvector<load_data_type_t> methods; +#ifdef PDB_PLUGIN + // Is the debugger active? + if ( get_process_state() != DSTATE_NOTASK ) + { + // First try using program data from debugger memory. + methods.push_back(MEM_LOCAL); + // Then try reading the executable (unless we're remote debugging). + if ( !dbg->is_remote() ) + methods.push_back(EXE_LOCAL); + } + else // debugger not active + { + // First try reading the executable. + methods.push_back(EXE_LOCAL); + // Then try using program data from the IDB. + methods.push_back(MEM_LOCAL); + } +#elif defined(PDB_WIN32_SERVER) + // First try reading the executable. + if ( pdbargs.is_dbg_module() ) + { + // If the module has been loaded by the debugger itself, we can + // read the file locally on the server side. + // TODO isn't this a security issue? the user can specify + // any input_path to be read on the server. + methods.push_back(EXE_LOCAL); + } + else + { + // Otherwise we want to read the input file from the remote stub. + methods.push_back(EXE_WIN32); + } + // Then try reading memory locally on the server side (the process + // being debugged). + methods.push_back(MEM_WIN32); +#else + // For efd and tilib, only try loading the executable locally. + methods.push_back(EXE_LOCAL); +#endif + + HRESULT hr = E_FAIL; + for ( size_t i = 0; i < methods.size(); i++ ) + { + hr = load_data_for_exe(pdbargs, methods[i]); + if ( hr == S_OK ) + break; + if ( hr == E_PDB_NOT_FOUND ) + break; // another address won't help + } + + return hr; +} + +//---------------------------------------------------------------------------- +HRESULT pdb_session_t::open_session(const pdbargs_t &pdbargs) +{ + // Already open? + if ( pdb_access != NULL ) + return S_OK; + + // Not initialized yet? + if ( !co_initialized ) + { + // Initialize COM + CoInitialize(NULL); + co_initialized = true; + } + + int dia_version; + HRESULT hr; + IDiaSession *pSession = NULL; + IDiaSymbol *pGlobal = NULL; + bool pdb_loaded = false; + + // No interface was created? + hr = create_dia_source(&dia_version); + if ( FAILED(hr) ) + goto fail; + + // First try to open PDB file if it was specified. + const qstring &pdb_path = pdbargs.pdb_path; + if ( !pdb_path.empty() + && check_for_odd_paths(pdb_path.c_str()) + && qfileexist(pdb_path.c_str()) ) + { + qwstring wpdb_path; + utf8_utf16(&wpdb_path, pdb_path.c_str()); + bool force_load = (pdbargs.flags & (PDBFLG_ONLY_TYPES|PDBFLG_EFD)) != 0; + hr = check_and_load_pdb(pSource, wpdb_path.c_str(), pdbargs.pdb_sign, force_load); + if ( hr == E_PDB_INVALID_SIG || hr == E_PDB_INVALID_AGE ) // Mismatching PDB + goto fail; + pdb_loaded = (hr == S_OK); + used_fname = pdb_path; // TODO is this needed? + } + + // Failed? Try to load input_path as EXE if it was specified. + const qstring &input_path = pdbargs.input_path; + if ( !pdb_loaded && !input_path.empty() ) + { + qstring path = input_path; + if ( !qfileexist(path.c_str()) ) + { + // If the input path came from a remote system, it is unlikely to be + // correct on our system. DIA does not care about the exact file name + // but uses the directory path to locate the PDB file. It combines + // the name of the pdb file from the debug directory and the directory + // from the input path. + // Since we cannot rely on remote paths, we simply use the current dir + char buf[QMAXPATH]; + qgetcwd(buf, sizeof(buf)); + path.sprnt("%s\\%s", buf, qbasename(input_path.c_str())); + msg("PDB: \"%s\": not found, trying \"%s\"\n", path.c_str(), buf); + } + if ( !check_for_odd_paths(path.c_str()) ) + return E_PDB_NOT_FOUND; + + used_fname = path; + + // Setup symsrv callback to show wait box for pdb downloading + symsrv_cb_t symsrv_cb; + symsrv_cb.init(); + + // Try searching for PDB information from the debug directory in a + // PE file. Either the input file is read directly or the contents + // of a loaded module are read from memory. + hr = load_input_path(pdbargs, path.c_str()); + pdb_loaded = (hr == S_OK); + + // Hide wait box for pdb downloading if needed + symsrv_cb.term(); + } + + // Failed? Then nothing else to try, quit + if ( !pdb_loaded ) + { + // make sure we do return an error + if ( hr == S_OK ) + hr = E_FAIL; + goto fail; + } + + // Open a session for querying symbols + hr = pSource->openSession(&pSession); + deb(IDA_DEBUG_DEBUGGER, "PDB: openSession(): %s\n", pdberr(hr)); + if ( FAILED(hr) ) + goto fail; + + // Set load address + // TODO check if load_address should be set when loading PDB works directly. + ea_t load_address = pdbargs.loaded_base; + if ( load_address != BADADDR ) + { + msg("PDB: using load address %a\n", load_address); + pSession->put_loadAddress(load_address); + } + + // Retrieve a reference to the global scope + hr = pSession->get_globalScope(&pGlobal); //-V595 The 'pSession' pointer was utilized before it was verified against nullptr + if ( hr != S_OK ) + goto fail; + + pdb_access = new local_pdb_access_t(pdbargs, pSource, pSession, pGlobal); + + DWORD pdb_machType, machType; + if ( pGlobal->get_machineType(&pdb_machType) != S_OK ) //-V595 The 'pGlobal' pointer was utilized before it was verified against nullptr + pdb_machType = IMAGE_FILE_MACHINE_I386; + machType = get_machine_type(pdb_machType); + + pdb_access->set_machine_type(machType); + pdb_access->set_dia_version(dia_version); + + hr = pdb_access->init(); + if ( hr == S_OK ) + return hr; + + // TODO clear pdb_access since above test failed + +fail: + // In the event of an error, this will be reached. + if ( pdb_access == NULL ) + { + if ( pGlobal != NULL ) + pGlobal->Release(); + if ( pSession != NULL ) + pSession->Release(); + if ( pSource != NULL ) + pSource->Release(); + } + return hr; +} + +//---------------------------------------------------------------------- +HRESULT pdb_session_t::create_dia_source(int *dia_version) +{ + HRESULT hr; + // VC80/90 CRT installs msdiaNN.dll in this folder: + // "C:\Program Files (x86)\Common Files\microsoft shared\VC" + char common_files[QMAXPATH]; + qstring vc_shared; + if ( get_special_folder(common_files, sizeof(common_files), CSIDL_PROGRAM_FILES_COMMON) ) + { + vc_shared = common_files; + vc_shared.append("\\Microsoft Shared\\VC"); + } + + for ( size_t i=0; i < qnumber(g_msdiav); i++ ) + { + // Try to create using CoCreateInstance() + hr = CoCreateInstance(*g_msdiav[i], + NULL, + CLSCTX_INPROC_SERVER, + __uuidof(IDiaDataSource), + (void**)&pSource); + + // Try to create with CoCreateInstanceNoReg() + if ( FAILED(hr) ) + { + // Search for this interface in DIA dlls + char path[QMAXPATH]; + if ( !search_path(path, sizeof(path), g_diadlls[i], false) + && (vc_shared.empty() + || SearchPathA(vc_shared.c_str(), g_diadlls[i], NULL, + qnumber(path), path, NULL) == 0) ) + { + continue; + } + + for ( size_t j=0; j < qnumber(g_msdiav); j++ ) + { + hr = CoCreateInstanceNoReg(path, + *g_msdiav[j], + NULL, + __uuidof(IDiaDataSource), + (void**)&pSource, + &dia_hmod); + + if ( hr == S_OK ) + { + static bool displayed = false; + if ( !displayed ) + { + displayed = true; + msg("PDB: using DIA dll \"%s\"\n", path); + } + i = j; + break; + } + } + } + + if ( hr == S_OK ) + { + *dia_version = g_diaver[i]; + static bool displayed = false; + if ( !displayed ) + { + displayed = true; + msg("PDB: DIA interface version %d.%d\n", (*dia_version)/100, (*dia_version)%100); + } + return hr; + } + else + { + *dia_version = 0; + } + } + return E_NOINTERFACE; +} + +//---------------------------------------------------------------------- +pdb_session_ref_t::pdb_session_ref_t(const pdb_session_ref_t &r) + : session(r.session) +{ + if ( session != NULL ) + session->refcount++; +} + +//---------------------------------------------------------------------- +pdb_session_ref_t &pdb_session_ref_t::operator=(const pdb_session_ref_t &r) +{ + if ( &r != this ) + { + this->~pdb_session_ref_t(); + new (this) pdb_session_ref_t(r); + } + return *this; +} + +//---------------------------------------------------------------------------- +pdb_session_ref_t::~pdb_session_ref_t() +{ + close(); + if ( session != NULL ) + { + delete session; + session = NULL; + } +} + +//---------------------------------------------------------------------- +void pdb_session_ref_t::create_session(void) +{ + QASSERT(30462, session == NULL); + session = new pdb_session_t(); +} + +//---------------------------------------------------------------------- +void pdb_session_ref_t::close() +{ + if ( session != NULL ) + { + // shared instance? then detach + if ( session->refcount > 1 ) + { // unlink + session->refcount--; + session = NULL; + } + else + { + session->close(); + } + } +} + +//---------------------------------------------------------------------- +HRESULT pdb_session_ref_t::open_session(const pdbargs_t &pdbargs) +{ + if ( opened() ) + return S_OK; + + if ( empty() ) + create_session(); + + return session->open_session(pdbargs); +} diff --git a/idasdk75/plugins/pdb/msdia.hpp b/idasdk76/plugins/pdb/msdia.hpp similarity index 100% rename from idasdk75/plugins/pdb/msdia.hpp rename to idasdk76/plugins/pdb/msdia.hpp diff --git a/idasdk75/plugins/pdb/old.cpp b/idasdk76/plugins/pdb/old.cpp similarity index 100% rename from idasdk75/plugins/pdb/old.cpp rename to idasdk76/plugins/pdb/old.cpp diff --git a/idasdk75/plugins/pdb/oldpdb.h b/idasdk76/plugins/pdb/oldpdb.h similarity index 100% rename from idasdk75/plugins/pdb/oldpdb.h rename to idasdk76/plugins/pdb/oldpdb.h diff --git a/idasdk76/plugins/pdb/pdb.cfg b/idasdk76/plugins/pdb/pdb.cfg new file mode 100644 index 0000000..16c84c3 --- /dev/null +++ b/idasdk76/plugins/pdb/pdb.cfg @@ -0,0 +1,47 @@ +// PDB plugin + +// PDB information provider +#define PDB_PROVIDER_MSDIA 1 // use MSDIA local/remote provider +#define PDB_PROVIDER_PDBIDA 2 // use PDBIDA provider +//PDB_PROVIDER = PDB_PROVIDER_PDBIDA + +// it is possible to specify the desired provider in the command line: +// ida -Opdb:off input_file +// ida -Opdb:msdia input_file +// ida -Opdb:pdbida input_file + +// Symbol search path +// The _NT_SYMBOL_PATH environment variable overrides this setting. +// If none of these variables is set then the default value will be used: +// "SRV*CACHEDIR*http://msdl.microsoft.com/download/symbols" +// where +// CACHEDIR=%TEMP%\ida for Windows +// CACHEDIR=$TMPDIR/ida or $TMP/ida or /tmp/ida for non-Windows OSes +// +//_NT_SYMBOL_PATH = "SRV*c:\\symbols*http://symbols.mozilla.org/firefox;SRV*c:\\symbols*http://msdl.microsoft.com/download/symbols"; + +// Network communications while looking for PDB file can be restricted. +// Valid only for PDBIDA provider. +#define PDB_NETWORK_OFF 0 // local directories search only +#define PDB_NETWORK_PE 1 // local directories search for COFF, full search for PE +#define PDB_NETWORK_ON 2 // no restrictions +//PDB_NETWORK = PDB_NETWORK_PE + +// PDBIDA is able to load MSF 7.0 PDB files only. +// MSDIA can load all PDB files, including old MSF 2.0 files. +// If you set the following option to YES, IDA will automatically switch +// to MSDIA for old files. +// Please note that under Linux/macOS the MSDIA provider requires you to configure +// the win32_remote.exe server because it can run only on Windows. +// It is possible to specify the desired behavior in the command line: +// ida -Opdb:fallback input_file +// ida -Opdb:nofallback input_file +PDB_MSDIA_FALLBACK = NO + +// remote server where win32_remote.exe is running +// used when loading PDB symbols on non-Windows platforms +// NB: it will be used only if there is not already an existing debugging session started +PDB_REMOTE_SERVER = "localhost"; +PDB_REMOTE_PORT = 23946 +// password for the remote server +PDB_REMOTE_PASSWD = ""; diff --git a/idasdk76/plugins/pdb/pdb.cpp b/idasdk76/plugins/pdb/pdb.cpp new file mode 100644 index 0000000..bb89e38 --- /dev/null +++ b/idasdk76/plugins/pdb/pdb.cpp @@ -0,0 +1,1414 @@ + +// IDA plugin to load function name information from PDB files +// 26-02-2008 Complete rewrite to use DIA API + +#ifdef __NT__ +# define WIN32_LEAN_AND_MEAN +# include <windows.h> +# include <objidl.h> +# define PDB_PLUGIN +#else +# define ENABLE_REMOTEPDB +#endif + +#include <memory> + +#include <ida.hpp> +#include <idp.hpp> +#include <err.h> +#include <md5.h> +#include <dbg.hpp> +#include <auto.hpp> +#include <name.hpp> +#include <frame.hpp> +#include <loader.hpp> +#include <diskio.hpp> +#include <struct.hpp> +#include <typeinf.hpp> +#include <demangle.hpp> + +#include <intel.hpp> +#include <network.hpp> +#include <workarounds.hpp> +int data_id; + +#include "pdb.hpp" +#include "common.cpp" +#ifdef ENABLE_REMOTEPDB +// We only enable remote PDB fetching in case +// we are building the plugin, for the moment. +// While this is an annoying limitation, it's mostly +// because the pdbremote code requires that +// the 'win32' (stub) debugger be loadable, in order +// to work: Ideally, we should only use an rpc_client +// instance, but currently we channel PDB requests +// through the remote debugger connection. +// (Neither efd.exe, nor tilib.exe can use of a +// running win32_remote.exe debugger instance for the +// moment) +# include "pdbremote.cpp" +#else +# include "oldpdb.h" +# include "msdia.cpp" +#endif +#include "tilbuild.cpp" + + +#include "sip.cpp" + + +//---------------------------------------------------------------------- +static bool looks_like_function_name(const char *name) +{ + // this is not quite correct: the presence of an opening brace + // in the demangled name indicates a function + // we can have a pointer to a function and there will be a brace + // but this logic is not applied to data segments + if ( strchr(name, '(') != NULL ) + return true; + + // check various function keywords + static const char *const keywords[] = + { + "__cdecl ", + "public: ", + "virtual ", + "operator ", + "__pascal ", + "__stdcall ", + "__thiscall ", + }; + for ( int i=0; i < qnumber(keywords); i++ ) + if ( strstr(name, keywords[i]) != NULL ) + return true; + return false; +} + +//---------------------------------------------------------------------- +bool pdb_ctx_t::check_for_ids(ea_t ea, const char *name, bool has_typeinfo) +{ + // Seems to be a GUID? + const char *ptr = name; + while ( *ptr == '_' ) + ptr++; + + static const char *const guids[] = { "IID", "DIID", "GUID", "CLSID", "LIBID", NULL }; + static const char *const sids[] = { "SID", NULL }; + + struct id_info_t + { + const char *const *names; + const char *type; + }; + static const id_info_t ids[] = + { + { guids, "GUID x;" }, + { sids, "SID x;" }, + }; + if ( !checked_types ) + { + if ( get_named_type(NULL, "GUID", NTF_TYPE) == 0 ) + { + static const char decl[] = "typedef struct _GUID { unsigned long Data1; unsigned short Data2; unsigned short Data3; unsigned char Data4[8];} GUID;"; + h2ti(NULL, NULL, decl, HTI_DCL, NULL, NULL, msg); + } + // SID type is pretty complex, so we won't add it manually but just check if it exists + has_sid = get_named_type(NULL, "SID", NTF_TYPE) != 0; + checked_types = true; + } + for ( int k=0; k < qnumber(ids); k++ ) + { + if ( k == 1 && !has_sid ) + continue; + for ( const char *const *p2=ids[k].names; *p2; p2++ ) + { + const char *guid = *p2; + size_t len = strlen(guid); + if ( strncmp(ptr, guid, len) == 0 + && (ptr[len] == '_' || ptr[len] == ' ') ) // space can be in demangled names + { + if ( has_typeinfo ) + apply_cdecl(NULL, ea, ids[k].type); + return true; + } + } + } + if ( strncmp(name, "_guid", 5) == 0 ) + { + if ( has_typeinfo ) + apply_cdecl(NULL, ea, ids[0].type); + return true; + } + return false; +} + +//---------------------------------------------------------------------- +static bool is_data_prefix(ea_t ea, const char *name) +{ + static const char *const data_prefixes[] = + { + "__IMPORT_DESCRIPTOR", + //"__imp_", // imported function pointer + }; + for ( int i=0; i < qnumber(data_prefixes); i++ ) + if ( strncmp(name, data_prefixes[i], strlen(data_prefixes[i])) == 0 ) + return true; + + // __real@xxxxxxxx - floating point number, 4 bytes + // __real@xxxxxxxxxxxxxxxx - floating point number, 8 bytes + if ( strncmp(name, "__real@", 7) == 0 ) + { + const char *ptr = name + 7; + const char *hex = ptr; + while ( qisxdigit(*ptr) ) + ptr++; + size_t len = ptr - hex; + if ( len == 8 ) + { + create_float(ea, 4); + return true; + } + if ( len == 16 ) + { + create_double(ea, 8); + return true; + } + if ( len == 20 ) + { // i haven't seen this, but probably it exists too + create_tbyte(ea, 10); + return true; + } + } + return false; +} + +//------------------------------------------------------------------------- +// Names that we prefer to ignore +static bool ignore_name(const char *name) +{ + struct ida_local sfxlen_t + { + const char *const sfx; + size_t len; // strlen(sfx) + }; + + static const sfxlen_t unwanted_suffixes[] = + { + { "_epilog1_start", 14 }, + }; + + size_t len = qstrlen(name); + + for ( auto &sfx : unwanted_suffixes ) + { + if ( len > sfx.len && streq(&name[len-sfx.len], sfx.sfx) ) + return true; + } + + // MSVS debug symbols may contain the temporary labels "Temp.00000001" + if ( strneq(name, "Temp.", 5) ) + { + const char *p = &name[5]; + if ( *p != '\0' ) + { + for ( ; *p != '\0' && isdigit(*p); ++p ) + ; + if ( *p == '\0' ) + return true; + } + } + + // _lc002_004933_ + if ( strneq(name, "_lc", 3) ) + { + const char *p = &name[3]; + if ( isdigit(p[0]) + && isdigit(p[1]) + && isdigit(p[2]) + && p[3] == '_' + && isdigit(p[4]) + && isdigit(p[5]) + && isdigit(p[6]) + && isdigit(p[7]) + && isdigit(p[8]) + && isdigit(p[9]) + && p[10] == '_' ) + { + return true; + } + } + + return false; +} + +//------------------------------------------------------------------------- +int pdb_ctx_t::get_utf16_encoding_idx() +{ + if ( utf16_encidx < 0 ) + utf16_encidx = add_encoding(inf_is_be() ? "UTF-16BE" : "UTF-16LE"); + return utf16_encidx; +} + +//---------------------------------------------------------------------- +// maybe_func: -1:no, 0-maybe, 1-yes, 2:no,but iscode +bool pdb_ctx_t::apply_name_in_idb(ea_t ea, const qstring &name, int maybe_func, uint32 the_machine_type) +{ + show_addr(ea); // so the user doesn't get bored + + if ( ignore_name(name.c_str()) ) + return true; + + // check for meaningless 'string' names + if ( strncmp(name.c_str(), "??_C@_", 6) == 0 ) + { + // ansi: ??_C@_0<len>@xxx + // unicode: ??_C@_1<len>@xxx + // TODO: parse length? + uint32 strtype = STRTYPE_C; + if ( name[6] == '1' ) + strtype = STRTYPE_C_16 | (get_utf16_encoding_idx() << 24); + create_strlit(ea, 0, strtype); + return true; + } + + qstring demangled; + if ( maybe_func <= 0 && demangle_name(&demangled, name.c_str(), MNG_SHORT_FORM) > 0 ) + { + if ( demangled == "`string'" ) + { + uint32 utf16_strtype = STRTYPE_C_16 | (get_utf16_encoding_idx() << 24); + size_t s1 = get_max_strlit_length(ea, STRTYPE_C); + size_t s2 = get_max_strlit_length(ea, utf16_strtype); + create_strlit(ea, 0, s1 >= s2 ? STRTYPE_C : utf16_strtype); + return true; + } + } + + // Renaming things immediately right here can lead to bad things. + // For example, if the name is a well known function name, then + // ida will immediately try to create a function. This is a bad idea + // because IDA does not know exact function boundaries and will try + // to guess them. Since the database has little information yet, there + // is a big chance that the function will end up to be way too long. + // That's why we collect names here and will rename them later. + namelist[ea] = name; + + bool has_typeinfo = ph.ti(); + if ( check_for_ids(ea, name.c_str(), has_typeinfo) + || check_for_ids(ea, demangled.c_str(), has_typeinfo) + || is_data_prefix(ea, name.c_str()) + || maybe_func < 0 ) + { + set_notcode(ea); // should not be code + return true; + } + if ( maybe_func == 0 && get_mangled_name_type(name.c_str()) == MANGLED_DATA ) + { + // NB: don't call set_notcode() here + // since demangler may give false positives + return true; + } + + // do not automatically create functions in debugger segments + segment_t *s = getseg(ea); + if ( s == NULL || !s->is_loader_segm() ) + return true; + + // ARMv7 PDBs don't use bit 0 for Thumb mode + if ( ph.has_code16_bit() && the_machine_type != CV_CFL_ARM7 ) + { + // low bit is Thumb/MIPS16 mode + bool func16 = (ea & 1) != 0; + ea &= ~1; + if ( func16 ) + { + // move the entry in namelist + namelist.erase(ea|1); + namelist[ea] = name; + } + } + + if ( maybe_func == 0 ) + { + do + { + // check for function telltales + if ( segtype(ea) != SEG_DATA + && demangle_name(&demangled, name.c_str(), MNG_LONG_FORM) > 0 + && looks_like_function_name(demangled.c_str()) ) + { + maybe_func = 1; + break; + } + + int stype = segtype(ea); + if ( stype != SEG_NORM && stype != SEG_CODE ) // only for code or normal segments + break; + + insn_t insn; + if ( decode_insn(&insn, ea) == 0 ) + break; + + if ( processor_t::is_sane_insn(insn, 1) < 0 ) + break; + maybe_func = 1; + } while ( false ); + } + if ( maybe_func == 1 ) + auto_make_proc(ea); // fixme: when we will implement lvars, we have to process these request + // before handling lvars + return true; +} + +//---------------------------------------------------------------------------- +// These two funcs for old.cpp only +bool apply_name(ea_t ea, const qstring &name, int maybe_func) +{ + pdb_ctx_t &pv = *GET_MODULE_DATA(pdb_ctx_t); + return pv.apply_name_in_idb(ea, name, maybe_func, pv.g_machine_type); +} + +void load_vc_til(void) +{ + pdb_ctx_t &pv = *GET_MODULE_DATA(pdb_ctx_t); + pv.load_vc_til(); +} + +//---------------------------------------------------------------------- +void pdb_ctx_t::load_vc_til(void) const +{ + // We managed to load the PDB file. + // It is very probably that the file comes from VC + // Load the corresponding type library immediately + if ( ph.id == PLFM_386 && pe.signature == PEEXE_ID ) + { + if ( pe.is_userland() ) + add_til(pe.is_pe_plus() ? "mssdk64_win7" : "mssdk_win7", ADDTIL_INCOMP); + else + add_til(pe.is_pe_plus() ? "ntddk64_win7" : "ntddk_win7", ADDTIL_INCOMP); + } +} + +//---------------------------------------------------------------------------- +class pdb_til_builder_t : public til_builder_t +{ + int npass; +public: + pdb_til_builder_t(pdb_ctx_t &_pv, til_t *_ti, pdb_access_t *_pa) + : til_builder_t(_pv, _ti, _pa), npass(0) {} + + virtual HRESULT before_iterating(pdb_sym_t &global_sym) override; + virtual bool iterate_symbols_once_more(pdb_sym_t & /*global_sym*/) override + { + handled.clear(); + return ++npass == 1; + } + virtual void type_created(ea_t ea, int id, const char *name, const tinfo_t &tif) const override; + virtual bool handle_symbol_at_ea(pdb_sym_t &sym, DWORD tag, ea_t ea, qstring &name) override; + virtual void handle_function_type(pdb_sym_t &fun_sym, ea_t ea) override; + virtual HRESULT handle_function_child( + pdb_sym_t &fun_sym, + ea_t ea, + pdb_sym_t &child_sym, + DWORD child_tag, + DWORD child_loc_type) override; +}; + +//---------------------------------------------------------------------------- +HRESULT pdb_til_builder_t::before_iterating(pdb_sym_t &) +{ + pv.load_vc_til(); + if ( default_compiler() == COMP_UNK ) + set_compiler_id(COMP_MS); + return S_OK; +} + +//---------------------------------------------------------------------------- +void pdb_til_builder_t::type_created(ea_t ea, int id, const char *name, const tinfo_t &tif) const +{ + pv.check_tinfo(ea, id, name, tif); +} + +//---------------------------------------------------------------------------- +// add the annotation strings to 'ea' +// following types are commonly used in windows drivers +// 1) assertion: +// #define NT_ASSERT(_exp) +// ((!(_exp)) ? +// (__annotation(L"Debug", L"AssertFail", L#_exp), +// DbgRaiseAssertionFailure(), FALSE) : +// TRUE) +// 2) trace message +// +// TMF: +// 2158e7d3-9867-cde3-18b5-9713c628abdf TEEDriver // SRC=Queue.c MJ= MN= +// #typev Queue_c2319 207 "%0PowerDown = %10!x!" // LEVEL=TRACE_LEVEL_VERBOSE FLAGS=TRACE_QUEUE +// { +// devExt->powerDown, ItemLong -- 10 +// }, Constant +// +// 3) trace message control +// WPP_DEFINE_CONTROL_GUID(Name,Guid,Bits) __annotation(L"TMC:", WPP_GUID_WTEXT Guid, _WPPW(WPP_STRINGIZE(Name)) Bits WPP_TMC_ANNOT_SUFIX); +// expands into: +// +// TMC: +// 0b67e6f7-ae91-470c-b4b6-dcd6a9034e18 +// TEEDriverTraceGuid +// MYDRIVER_ALL_INFO +// TRACE_DRIVER +// TRACE_DEVICE +// [..] +// TRACE_BUS_DRIVER_LAYER +// +// In all other cases we just use plain __annotation(a,b,c,...) +// TODO: use anterior lines for big annotations (over 1KB) +static void apply_annotation(ea_t ea, const qstrvec_t ¶ms) +{ + if ( params.empty() ) + return; + + qstring full_cmt; + if ( params.size() >= 3 && params[0] == "Debug" && params[1] == "AssertFail" ) + { + full_cmt.sprnt("NT_ASSERT(\"%s\"", params[2].c_str()); + for ( size_t i = 3; i < params.size(); i++ ) + full_cmt.cat_sprnt(",\n \"%s\"", params[i].c_str()); + full_cmt.append(")"); + } + else if ( params[0] == "TMF:" ) + { + full_cmt = "__annotation(\"TMF:\""; + bool add_newline = true; + for ( size_t i = 1; i < params.size(); i++ ) + { + full_cmt.cat_sprnt(",%s\"%s\"", add_newline ? "\n " : " ", params[i].c_str()); + // print args betwen { } on one line + if ( params[i] == "{" ) + add_newline = false; + else if ( params[i] == "}" ) + add_newline = true; + } + full_cmt.append(")"); + } + else + { + full_cmt.sprnt("__annotation(\"%s\"", params[0].c_str()); + for ( size_t i = 1; i < params.size(); i++ ) + full_cmt.cat_sprnt(", \"%s\"", params[i].c_str()); + full_cmt.append(")"); + } + set_cmt(ea, full_cmt.c_str(), false); +} + +//---------------------------------------------------------------------------- +bool pdb_til_builder_t::handle_symbol_at_ea( + pdb_sym_t &sym, + DWORD tag, + ea_t ea, + qstring &name) +{ + int maybe_func = 0; + switch ( tag ) + { + case SymTagFunction: + case SymTagThunk: + maybe_func = 1; + break; + case SymTagBlock: + case SymTagLabel: + case SymTagFuncDebugStart: + case SymTagFuncDebugEnd: + maybe_func = 2; + break; + case SymTagData: + case SymTagVTable: + maybe_func = -1; + break; + case SymTagPublicSymbol: + { + BOOL b; + if ( sym.get_function(&b) == S_OK && b ) + maybe_func = 1; + } + break; + case SymTagAnnotation: + { + struct annotation_value_collector_t : public pdb_access_t::children_visitor_t + { + const til_builder_t *tb; + qstrvec_t ann_params; + HRESULT visit_child(pdb_sym_t &child) override + { + qstring v; + if ( tb->get_variant_string_value(&v, child) ) + // set_cmt(ea, v.c_str(), false); + ann_params.push_back(v); + return S_OK; + } + annotation_value_collector_t(const til_builder_t *_tb) + : tb(_tb) {} + }; + annotation_value_collector_t avc(this); + pdb_access->iterate_children(sym, SymTagNull, avc); + apply_annotation(ea, avc.ann_params); + maybe_func = segtype(ea) == SEG_CODE ? 2 /*no func, but code*/ : 0 /*unclear*/; + } + break; + default: + break; + } + + // symbols starting with __imp__ cannot be functions + if ( strncmp(name.c_str(), "__imp__", 7) == 0 ) + { + if ( inf_is_64bit() ) + create_qword(ea, 8); + else + create_dword(ea, 4); + maybe_func = -1; + } + + BOOL iscode; + if ( sym.get_code(&iscode) == S_OK ) + { + if ( iscode ) + { + if ( is_notcode(ea) ) + { + // clear wrong notcode mark + // (was seen happening with bogus SymTagData symbol for _guard_dispatch_icall_nop) + clr_notcode(ea); + create_insn(ea); + } + } + else + { + // not a function + maybe_func = -1; + } + } + + tpinfo_t tpi; + if ( get_symbol_type(&tpi, sym, NULL) ) + { + // Apparently _NAME_ is a wrong symbol generated for file names + // It has wrong type information, so correct it + if ( tag == SymTagData && name == "_NAME_" && tpi.type.get_decltype() == BTF_CHAR ) + tpi.type = tinfo_t::get_stock(STI_ACHAR); // char [] + if ( tag == SymTagFunction ) + { + // convert the type again, this time passing function symbol + // this allows us to get parameter names and handle static class methods + pdb_sym_t *func_sym = pdb_access->create_sym(); + pdb_sym_janitor_t janitor_pType(func_sym); + if ( sym.get_type(func_sym) == S_OK ) + { + tpinfo_t tpi2; + if ( really_convert_type(&tpi2, *func_sym, &sym, SymTagFunctionType) == cvt_ok ) + tpi.type.swap(tpi2.type); // successfully retrieved + } + } + if ( tpi.type.is_func() || tag == SymTagFunction ) + { + maybe_func = 1; + handle_function_type(sym, ea); + } + else + { + maybe_func = -1; + } + if ( npass != 0 ) + { + bool use_ti = true; + func_type_data_t fti; + if ( tpi.type.get_func_details(&fti) + && fti.empty() + && fti.rettype.is_decl_void() ) + { // sometimes there are functions with linked FunctionType but no parameter or return type info in it + // we get better results by not forcing type info on them + use_ti = false; + } + if ( use_ti ) + { + type_created(ea, 0, NULL, tpi.type); + apply_tinfo(ea, tpi.type, TINFO_STRICT); + } + } + } + else if ( maybe_func == 1 ) + { + auto_make_proc(ea); // certainly a func + } + pv.apply_name_in_idb(ea, name, maybe_func, pdb_access->get_machine_type()); + return true; +} + +//--------------------------------------------------------------------------- +HRESULT pdb_til_builder_t::handle_function_child( + pdb_sym_t &fun_sym, + ea_t ea, + pdb_sym_t &child_sym, + DWORD child_tag, + DWORD child_loc_type) +{ + LONG offset; + DWORD reg_id; + switch ( child_loc_type ) + { + case LocIsEnregistered: + if ( child_sym.get_registerId(®_id) == S_OK ) + { + if ( enregistered_bug && reg_id > 0 ) + reg_id--; + func_t *pfn = get_func(ea); + qstring name; + child_sym.get_name(&name); + qstring canon; + print_pdb_register(&canon, pdb_access->get_machine_type(), reg_id); + if ( pfn != NULL ) + add_regvar(pfn, pfn->start_ea, pfn->end_ea, canon.c_str(), name.c_str(), NULL); + } + break; + + case LocIsRegRel: + if ( child_sym.get_registerId(®_id) == S_OK + && child_sym.get_offset(&offset) == S_OK + && reg_id == CV_REG_EBP ) // we can handle only ebp for the moment + { + func_t *pfn = get_func(ea); + if ( pfn != NULL ) + { + qstring name; + child_sym.get_name(&name); + tpinfo_t tpi; + if ( get_symbol_type(&tpi, child_sym, NULL) ) + { + opinfo_t mt; + size_t size; + flags_t flags; + if ( get_idainfo_by_type(&size, &flags, &mt, tpi.type) ) + { + // DIA's offset is bp-based, not frame-based like in IDA + offset -= pfn->fpd; + // make sure the new variable is not overwriting the return address + // for some reason some PDBs have bogus offsets for some params/locals... + if ( !is_intel386(pdb_access->get_machine_type()) + || offset > 0 + || size <= -offset ) + { + if ( define_stkvar(pfn, name.c_str(), offset, flags, &mt, size) ) + { + insn_t insn; + insn.ea = pfn->start_ea; + member_t *mptr = get_stkvar(NULL, insn, *(op_t*)NULL, offset); //lint !e413 deref null ptr + if ( mptr != NULL ) + { + struc_t *sptr = get_frame(pfn); + set_member_tinfo(sptr, mptr, 0, tpi.type, 0); + set_userti(mptr->id); + } + } + } + } + } + else // no type info... + { + msg("%a: stkvar '%s' with no type info\n", ea, name.c_str()); + } + } + } + break; + default: + return til_builder_t::handle_function_child(fun_sym, ea, child_sym, + child_tag, child_loc_type); + } + return S_OK; +} + +//--------------------------------------------------------------------------- +void pdb_til_builder_t::handle_function_type(pdb_sym_t &sym, ea_t ea) +{ + if ( npass == 0 ) + { + if ( !create_insn(ea) ) + return; + + // add the address to the queue - this will help to determine better function boundaries + auto_make_proc(ea); + } + else + { + ea_t end = BADADDR; + DWORD64 ulLen; + if ( sym.get_length(&ulLen) == S_OK ) + end = ea + asize_t(ulLen); + ea_t next_planned = peek_auto_queue(ea+1, AU_PROC); + + // before adding a function, try to create all its instructions. + // without this the frame analysis may fail. + func_t fn(ea); + find_func_bounds(&fn, FIND_FUNC_DEFINE); + + bool created = false; + bool acceptable_end = end <= next_planned; // end is wrong for fragmented functions + if ( acceptable_end ) + created = add_func(ea, end); + if ( !created ) + add_func(ea); + + til_builder_t::handle_function_type(sym, ea); + } +} + +//--------------------------------------------------------------------------- +static HRESULT common_handler(pdb_ctx_t &pv, pdb_access_t &pdb_access) +{ + try + { + pdb_til_builder_t builder(pv, CONST_CAST(til_t *)(get_idati()), &pdb_access); + pdb_sym_t *global = pdb_access.create_sym(pdb_access.get_global_symbol_id()); + pdb_sym_janitor_t janitor_global(global); + return builder.build(*global); + } + catch ( const pdb_exception_t &e ) + { + msg("Couldn't parse PDB data: %s\n", e.what.c_str()); + return E_FAIL; + } +} + +//--------------------------------------------------------------------------- +#ifdef ENABLE_REMOTEPDB +// On Unix computers use remote_pdb_access +static HRESULT remote_handler(pdb_ctx_t &pv, const pdbargs_t &args) +{ + int chosen_remote_port = pv.pdb_remote_port; + if ( pv.pdb_remote_port_64 != -1 && inf_is_64bit() ) + chosen_remote_port = pv.pdb_remote_port_64; + remote_pdb_access_t remote_pdb_access(args, + pv.pdb_remote_server.c_str(), + chosen_remote_port, + pv.pdb_remote_passwd.c_str()); + HRESULT hr = remote_pdb_access.open_connection(); + if ( hr == S_OK ) + hr = common_handler(pv, remote_pdb_access); + return hr; +} +#endif + + +/*==================================================================== + IDA PRO INTERFACE START HERE +====================================================================*/ + +//------------------------------------------------------------------------- +static const cfgopt_t g_opts[] = +{ + CFGOPT_R ("PDB_REMOTE_PORT", pdb_ctx_t, pdb_remote_port, 0, 65535), + CFGOPT_R ("PDB_REMOTE_PORT_64", pdb_ctx_t, pdb_remote_port_64, 0, 65535), + CFGOPT_QS("_NT_SYMBOL_PATH", pdb_ctx_t, full_sympath, true), + CFGOPT_QS("PDB_REMOTE_SERVER", pdb_ctx_t, pdb_remote_server, true), + CFGOPT_QS("PDB_REMOTE_PASSWD", pdb_ctx_t, pdb_remote_passwd, true), + CFGOPT_R ("PDB_NETWORK", pdb_ctx_t, pdb_network, PDB_NETWORK_OFF, PDB_NETWORK_ON), +}; + +//---------------------------------------------------------------------- +#ifndef ENABLE_REMOTEPDB +static uint32 get_machine_from_idb(const processor_t &ph) +{ + uint32 mt; + switch ( ph.id ) + { + case PLFM_ARM: + mt = CV_CFL_ARM6; + break; + case PLFM_MIPS: + mt = CV_CFL_MIPSR4000; + break; + case PLFM_PPC: + mt = inf_is_be() ? CV_CFL_PPCBE : CV_CFL_PPCFP; + break; + case PLFM_SH: + mt = CV_CFL_SH4; + break; + case PLFM_IA64: + mt = CV_CFL_IA64; + break; + case PLFM_386: + default: + mt = CV_CFL_80386; + break; + } + return mt; +} +#endif + +//---------------------------------------------------------------------- +void pdb_ctx_t::init_sympaths() +{ + // user specified symbol path? + full_sympath.qclear(); + read_config_file2("pdb", g_opts, qnumber(g_opts), nullptr, nullptr, 0, this); + + qstring env_sympath; + if ( qgetenv("_NT_SYMBOL_PATH", &env_sympath) ) + full_sympath.swap(env_sympath); + + // default symbol search path + if ( full_sympath.empty() ) + { + char cache_path[QMAXPATH]; + + #ifdef __NT__ + if ( !GetTempPath(sizeof(cache_path), cache_path) ) + cache_path[0] = '\0'; + else + qstrncat(cache_path, "ida", sizeof(cache_path)); + #else + qstring tmpdir; + if ( !qgetenv("TMPDIR", &tmpdir) && !qgetenv("TMP", &tmpdir) ) + tmpdir = "/tmp"; + qmakepath(cache_path, sizeof(cache_path), tmpdir.c_str(), "ida", NULL); + if ( !qisdir(cache_path) && qmkdir(cache_path, 0777) != 0 ) + cache_path[0] = '\0'; + #endif + + full_sympath.sprnt("%s%s%s", g_spath_prefix, cache_path, g_spath_suffix); + } + deb(IDA_DEBUG_DBGINFO, "PDB: _NT_SYMBOL_PATH=%s\n", full_sympath.c_str()); + + if ( opt_provider != 0 ) + pdb_provider = opt_provider; +} + +//---------------------------------------------------------------------- +#define MAX_DISP_PATH 80 +// If path name is too long then replace some directories with "...." +static qstring truncate_path(const qstring &path) +{ + qstring str = path; + int len = str.length(); + if ( len > MAX_DISP_PATH ) + { + char slash = '\\'; + size_t start = str.find(slash); + if ( start == qstring::npos ) + { + slash = '/'; + start = str.find(slash); + } + if ( start != qstring::npos ) + { + size_t end = str.rfind(slash); + size_t prev_start; + do + { + prev_start = start; + start = str.find(slash, start + 1); + } while ( len - (end - start) < MAX_DISP_PATH ); + start = prev_start + 1; + if ( end > start ) + { + str.remove(start, end - start); + str.insert(start, "...."); + } + } + } + return str; +} + +//---------------------------------------------------------------------------- +static bool read_pdb_signature(pdb_signature_t *pdb_sign) +{ + netnode penode(PE_NODE); + rsds_t rsds; + size_t size = sizeof(rsds_t); + if ( penode.getblob(&rsds, &size, 0, RSDS_TAG) != NULL && size == sizeof(rsds_t) ) // RSDS + { + pdb_sign->age = rsds.age; + pdb_sign->sig = 0; + memcpy(pdb_sign->guid, &rsds.guid, sizeof(pdb_sign->guid)); + CASSERT(sizeof(pdb_sign->guid) == sizeof(rsds.guid)); + } + else + { + cv_info_pdb20_t nb10; + size = sizeof(nb10); + if ( penode.getblob(&nb10, &size, 0, NB10_TAG) != NULL && size == sizeof(nb10) ) // NB10 + { + pdb_sign->age = nb10.age; + pdb_sign->sig = nb10.signature; + } + else + { + return false; + } + } + return true; +} + +//---------------------------------------------------------------------------- +// moved into a separate function to diminish the stack consumption +static qstring get_input_path() +{ + char input_path[QMAXPATH]; + if ( get_input_file_path(input_path, sizeof(input_path)) <= 0 ) + input_path[0] = '\0'; + return input_path; +} + +//-------------------------------------------------------------------------- +static int idaapi details_modcb(int fid, form_actions_t &fa) +{ + switch ( fid ) + { + // "Types only" + case 20: + { + ushort c; + if ( fa.get_checkbox_value(20, &c) ) + fa.enable_field(10, c == 0); // enable/disable address field + } + break; + } + + return 1; +} + +//------------------------------------------------------------------------- +static void set_file_by_ext(pdbargs_t *args, const char *buf) +{ + const char *ext = get_file_ext(buf); + if ( ext != NULL && strieq(ext, "pdb") ) + { + args->pdb_path = buf; + args->input_path.clear(); + } + else + { + args->input_path = buf; + args->pdb_path.clear(); + } +} + +//---------------------------------------------------------------------------- +static bool ask_pdb_details(pdbargs_t *args) +{ + netnode penode(PE_NODE); + args->loaded_base = penode.altval(PE_ALT_IMAGEBASE); + + static const char form[] = + "Load PDB file\n" + "%/" + "<#Specify the path to the file to load symbols for#~I~nput file:f:0:64::>\n" + "<#Specify the loading address of the exe/dll file#~A~ddress :N10::64::>\n" + "<#Load only types, do not rename program locations#~T~ypes only:C20>>\n" + "Note: you can specify either a .pdb, or an .exe/.dll file name.\n" + "In the latter case, IDA will try to find and load\n" + "the PDB specified in its debug directory.\n" + "\n"; + + char buf[QMAXPATH]; + const char *src = NULL; + if ( !args->pdb_path.empty() ) + src = args->pdb_path.begin(); + else if ( !args->input_path.empty() ) + src = args->input_path.begin(); + if ( src == NULL ) + src = "*.pdb"; + + qstrncpy(buf, src, sizeof(buf)); + + CASSERT(sizeof(args->loaded_base) == sizeof(ea_t)); + sval_t typesonly = (args->flags & PDBFLG_ONLY_TYPES) != 0; + if ( !ask_form(form, details_modcb, buf, &args->loaded_base, &typesonly) ) + return false; + + set_file_by_ext(args, buf); + + setflag(args->flags, PDBFLG_ONLY_TYPES, typesonly != 0); + + return true; +} + +//------------------------------------------------------------------------- +static bool get_details_from_netnode(pdbargs_t *args) +{ + netnode pdbnode; + pdbnode.create(PDB_NODE_NAME); + + args->loaded_base = pdbnode.altval(PDB_DLLBASE_NODE_IDX); + if ( args->loaded_base == 0 ) + { + msg("PDB: PDB_CC_USER_WITH_DATA called without an imagebase, cannot proceed\n"); +fail: + // set failure result + pdbnode.altset(PDB_DLLBASE_NODE_IDX, 0); + return false; + } + + // TODO dllname shouldn't be needed when we're reading from debugger memory + qstring tmp; + pdbnode.supstr(&tmp, PDB_DLLNAME_NODE_IDX); + if ( tmp.empty() ) + { + msg("PDB: PDB_CC_USER_WITH_DATA called without a filename, cannot proceed\n"); + goto fail; + } + + set_file_by_ext(args, tmp.c_str()); + + bool typesonly = pdbnode.altval(PDB_TYPESONLY_NODE_IDX) != 0; + setflag(args->flags, PDBFLG_ONLY_TYPES, typesonly); + + return true; +} + +//------------------------------------------------------------------------- +static bool get_pdb_path(pdbargs_t *args, netnode penode) +{ + penode.supstr(&args->pdb_path, PE_SUPSTR_PDBNM); + + return !args->pdb_path.empty(); // do not ask to load pdb with empty name +} + +//------------------------------------------------------------------------- +static bool get_details_from_pe(pdbargs_t *args) +{ + netnode penode(PE_NODE); + if ( !get_pdb_path(args, penode) ) + return false; + args->input_path = get_input_path(); + args->loaded_base = penode.altval(PE_ALT_IMAGEBASE); + + return ask_yn(ASKBTN_YES, + "AUTOHIDE REGISTRY\nHIDECANCEL\n" + "The input file was linked with debug information\n" + " and the symbol filename is:\n" + "\"%s\"\n" + "Do you want to look for this file at the specified path\n" + "and the Microsoft Symbol Server?\n", + args->pdb_path.c_str()) == ASKBTN_YES; +} + +//------------------------------------------------------------------------- +static bool ask_for_pdb_file(pdbargs_t *pdbargs, const char *err_str) +{ + qstring disp_path = truncate_path(pdbargs->input_path); + if ( ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "AUTOHIDE REGISTRY\n" + "%s: failed to load pdb info.\n%s\n" + "Do you want to browse for the pdb file on disk?", + disp_path.c_str(), + err_str == NULL ? "" : err_str) == ASKBTN_YES ) + { + char *pdb_file = ask_file(false, "*.pdb", "Choose PDB file"); + if ( pdb_file != NULL ) + { + pdbargs->pdb_path = pdb_file; + return true; + } + } + return false; +} + +//------------------------------------------------------------------------- +bool pdb_ctx_t::apply_debug_info(pdbargs_t &pdbargs) +{ + // we may run out of memory on huge pdb files. prefer to keep the partial + // idb file in this case. + bool restore_kill_flag = is_database_flag(DBFL_KILL); + clr_database_flag(DBFL_KILL); + + netnode pdbnode; + if ( pdbargs.is_pdbfile() ) + pdbnode.create(PDB_NODE_NAME); + + init_sympaths(); + pdbargs.spath = full_sympath; + + setflag(pdbargs.flags, PDBFLG_USE_HTTP, use_http(pdbargs.is_pdbfile())); + + bool ok = true; + HRESULT hr = E_FAIL; + + { + msg("PDB: using MSDIA provider\n"); +#ifdef ENABLE_REMOTEPDB + hr = remote_handler(*this, pdbargs); +#else + bool was_load_error = false; +LOAD_PDB: + try + { + pdb_session_ref_t ref; + hr = ref.open_session(pdbargs); + if ( hr == S_OK ) + hr = common_handler(*this, *ref.session->pdb_access); + } + catch ( const std::bad_alloc & ) + { + warning("It appears IDA has run out of memory while loading the PDB file.\n" + "This can happen when using the DIA SDK dll with big and/or corrupt PDBs.\n" + "While you will now be able to continue your work, IDA cannot proceed with PDB parsing, sorry.\n\n" + "It is also HIGHLY recommended that you save the database as soon as possible,\n" + "quit, and restart IDA with that database."); + hr = E_PDB_OUT_OF_MEMORY; + was_load_error = true; + } +#endif + + if ( pdbargs.input_path.empty() ) + pdbargs.input_path = pdbargs.pdb_path; + + if ( FAILED(hr) ) + { + ok = false; +#ifndef ENABLE_REMOTEPDB + const char *err_str = pdberr(hr); + msg("PDB: could not process file \"%s\" with DIA: %s\n", pdbargs.input_path.c_str(), err_str); + pdberr_suggest_vs_runtime(hr); + + // DIA interface failed, try the old methods + if ( hr != E_PDB_INVALID_SIG + && hr != E_PDB_INVALID_AGE + && hr != E_PDB_NOT_FOUND + && hr != E_PDB_INVALID_EXECUTABLE + && !inf_test_mode() ) + { + g_machine_type = get_machine_from_idb(ph); // See 'g_machine_type' comment above + ok = old_pdb_plugin(pdbargs.loaded_base, pdbargs.input_path.c_str(), pdbargs.spath.c_str()); + if ( ok ) + msg("Old method of loading PDB files (dbghelp) was successful\n"); + } + if ( !was_load_error && !ok ) + { + was_load_error = true; + if ( ask_for_pdb_file(&pdbargs, err_str) ) + { + ok = true; // reset to default + goto LOAD_PDB; + } + } +#else + if ( !pdbargs.is_dbg_module() ) // called as main plugin routine + warning("IDA could not open \"%s\". Please check that the file " + "exists on the remote computer.", pdbargs.fname()); + else + msg("No PDB information found for \"%s\"\n", pdbargs.fname()); +#endif + } + } + + if ( ok && (pdbargs.flags & PDBFLG_ONLY_TYPES) == 0 ) + { + // Now all information is loaded into the database (except names) + // We are ready to use names. + int counter = 0; + for ( namelist_t::iterator p=namelist.begin(); p != namelist.end(); ++p ) + { + ea_t ea = p->first; + // do not override name for COFF file + if ( pdbargs.is_pdbfile() || !has_name(get_flags(ea)) ) + { + if ( pdbargs.is_dbg_module() ) + counter += set_debug_name(ea, p->second.c_str()); + else + counter += force_name(ea, p->second.c_str()); + } + // Every now & then, make sure the UI has had a chance to refresh. + if ( (counter % 10) == 0 ) + user_cancelled(); + } + namelist.clear(); + msg("PDB: total %d symbol%s loaded for \"%s\"\n", + counter, + counter != 1 ? "s" : "", + pdbargs.input_path.c_str()); + } + + pdbnode.altset(PDB_DLLBASE_NODE_IDX, ok); + check_added_types(); + + // we have to restore the kill flag; otherwise the logic of the other parts + // of ida may change. for example, in the absence of DBFL_KILL we remember + // the idb path in the idb history (displayed in the File menu) + if ( restore_kill_flag ) + set_database_flag(DBFL_KILL); + + return ok; +} + +//---------------------------------------------------------------------------- +bool idaapi pdb_ctx_t::run(size_t _call_code) +{ + + + // PDB + pdbargs_t pdbargs; + if ( inf_get_filetype() != f_PE && !is_miniidb() ) + pdbargs.flags |= PDBFLG_ONLY_TYPES; + + netnode penode(PE_NODE); + penode.valobj(&pe, sizeof(pe)); + + bool ok = false; + switch ( (pdb_callcode_t)_call_code ) + { + case PDB_CC_USER: + // user explicitly invoked the plugin + ok = ask_pdb_details(&pdbargs); + // pdb_path, input_path: only one is set (depending on the file + // extension), the other is cleared + // loaded_base: specified by user (default obtained from PE) + break; + case PDB_CC_USER_WITH_DATA: + // user invoked the plugin programmatically + ok = get_details_from_netnode(&pdbargs); + // pdb_path, input_path: only one is set (depending on the file + // extension), the other is cleared + // loaded_base: specified by user + break; + case PDB_CC_IDA: + // IDA decided to call the plugin + ok = get_details_from_pe(&pdbargs); + // pdb_path: obtained from PE + // input_path: IDA's input file name + // loaded_base: obtained from PE + break; + default: + break; + } + + if ( ok ) + { + // read pdb signature from the database, if any + if ( !read_pdb_signature(&pdbargs.pdb_sign) ) + { + // make it invalid but not empty + // so that check_and_load_pdb() does not fail silently + pdbargs.pdb_sign.age = 0xFFFFFFFF; + } + + apply_debug_info(pdbargs); + } + + return true; +} + +//-------------------------------------------------------------------------- +void pdb_ctx_t::parse_options(bool *opt_skip) +{ + *opt_skip = false; + qstring opts(get_plugin_options("pdb")); + if ( opts.empty() ) + return; + char *opt = opts.begin(); + opt_provider = 0; + opt_fallback = -1; + do + { + char *end = qstrchr(opt, ':'); + if ( end != NULL ) + *end++ = '\0'; + + if ( streq(opt, "off") ) + { + *opt_skip = true; + } + else if ( streq(opt, "msdia") ) + { + opt_provider = PDB_PROVIDER_MSDIA; + } + else + { + error("AUTOHIDE NONE\n" + "Wrong option for the PDB plugin.\n" + "\n" + "The valid options are:\n" + "off do not load plugin\n" + "msdia use MSDIA provider\n"); + } + + if ( end == NULL ) + break; + opt = end; + } while ( true ); +} + +//-------------------------------------------------------------------------- +// initialize plugin +static plugmod_t *idaapi init() +{ + auto pv = std::unique_ptr<pdb_ctx_t>(new pdb_ctx_t); + bool opt_skip; + pv->parse_options(&opt_skip); + if ( opt_skip ) + return nullptr; + register_srcinfo_provider(pv->pdb_srcinfo_provider); + + auto plugmod = pv.release(); + set_module_data(&data_id, plugmod); + return plugmod; +} + +//-------------------------------------------------------------------------- +ssize_t idaapi pdb_ctx_t::on_event(ssize_t event_id, va_list va) +{ + return 0; // event is not processed +} + +//-------------------------------------------------------------------------- +pdb_ctx_t::pdb_ctx_t() : ph(PH) +{ + hook_event_listener(HT_IDP, this); + memset(&pe, 0, sizeof(pe)); + alloc_pdb_srcinfo_provider(); + g_machine_type = CV_CFL_80386; +} + +//-------------------------------------------------------------------------- +// terminate +pdb_ctx_t::~pdb_ctx_t() +{ + namelist.clear(); + unregister_srcinfo_provider(pdb_srcinfo_provider); + free_pdb_srcinfo_provider(); + clr_module_data(data_id); +} + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MOD | PLUGIN_HIDE | PLUGIN_MULTI, // plugin flags: + init, // initialize + nullptr, // terminate. this pointer may be NULL. + nullptr, // invoke plugin + + // long comment about the plugin + // it could appear in the status line + // or as a hint + "Load debug information from a PDB file", + + // multiline help about the plugin + "PDB file loader\n" + "\n" + "This module allows you to load debug information about function names\n" + "from a PDB file.\n" + "\n" + "The PDB file should be in the same directory as the input file\n", + + // the preferred short name of the plugin + "Load PDB file (dbghelp 4.1+)", + // the preferred hotkey to run the plugin + "" +}; + + +//lint -esym(766, md5.h, diskio.hpp) Unused header files. diff --git a/idasdk76/plugins/pdb/pdb.hpp b/idasdk76/plugins/pdb/pdb.hpp new file mode 100644 index 0000000..ccaf75e --- /dev/null +++ b/idasdk76/plugins/pdb/pdb.hpp @@ -0,0 +1,217 @@ +// +// Copyright (c) 2005-2021 Hex-Rays SA <support@hex-rays.com> +// ALL RIGHTS RESERVED. +// +#pragma once +#include <idp.hpp> +#include <idd.hpp> +#include <typeinf.hpp> +#include "../../ldr/pe/pe.h" + +#define PDB_NODE_NAME "$ pdb" +#define PDB_DLLBASE_NODE_IDX 0 +#define PDB_DLLNAME_NODE_IDX 0 +#define PDB_LOADING_WIN32_DBG 1 +#define PDB_TYPESONLY_NODE_IDX 2 + +enum pdb_callcode_t +{ + // user invoked 'load pdb' command, load pdb for the input file. + // after invocation, result (boolean) is stored in: netnode(PDB_NODE_NAME).altval(PDB_DLLBASE_NODE_IDX) + PDB_CC_USER = 0, + // ida decided to call the plugin itself + PDB_CC_IDA = 1, + // load additional pdb. This is semantically the same as + // PDB_CC_USER (i.e., "File > Load file > PDB file..."), except + // it won't ask the user for the data; rather it expects it in + // netnode(PDB_NODE_NAME): + // load_addr: netnode(PDB_NODE_NAME).altval(PDB_DLLBASE_NODE_IDX) + // dll_name: netnode(PDB_NODE_NAME).supstr(PDB_DLLNAME_NODE_IDX) + PDB_CC_USER_WITH_DATA = 3, + // load debug info from the COFF file + // ida decided to call the plugin itself + // dbginfo_params_t: netnode(DBGINFO_PARAM_NODE_NAME).supval(DBGINFO_PARAMS_KEY) + PDB_CC_IDA_COFF = 4, +}; + +//---------------------------------------------------------------------- +struct pdb_signature_t +{ + uint32 guid[4]; // if all zeroes, then consider as non-existing + uint32 sig; + uint32 age; + pdb_signature_t(void) { memset(this, 0, sizeof(*this)); } +}; + +//---------------------------------------------------------------------------- +struct pdbargs_t +{ + qstring pdb_path; // Path to PDB file. + qstring input_path; // Path to PE file with associated PDB. + pdb_signature_t pdb_sign; + qstring spath; + ea_t loaded_base; + void *user_data; + uint32 flags; +#define PDBFLG_DBG_MODULE 0x0001 +#define PDBFLG_ONLY_TYPES 0x0002 +#define PDBFLG_EFD 0x0004 +#define PDBFLG_COFF_FILE 0x0008 +#define PDBFLG_USE_HTTP 0x0100 + + pdbargs_t(void) + : loaded_base(BADADDR), + user_data(NULL), + flags(0) + {} + + // If true, we are in a debugging session and the file specified by + // input_path is an additional module that has been loaded by the + // debugger itself. + bool is_dbg_module(void) const + { + return (flags & PDBFLG_DBG_MODULE) != 0; + } + // PDB? + bool is_pdbfile(void) const { return (flags & PDBFLG_COFF_FILE) == 0; } + bool use_http() const { return (flags & PDBFLG_USE_HTTP) != 0; } + + const char *fname(void) const + { + return !pdb_path.empty() ? pdb_path.begin() : input_path.c_str(); + } +}; + +//---------------------------------------------------------------------------- +struct pdb_ctx_t : public plugmod_t, public event_listener_t +{ + processor_t &ph; + + // PDB search path (in _NT_SYMBOL_PATH format) + qstring full_sympath; + + peheader_t pe; + + // config options + int pdb_remote_port = DEBUGGER_PORT_NUMBER; + int pdb_remote_port_64 = -1; + qstring pdb_remote_server; + qstring pdb_remote_passwd; +#define PDB_PROVIDER_MSDIA 1 + uint pdb_provider = PDB_PROVIDER_MSDIA; +#define PDB_NETWORK_OFF 0 // local directories search only +#define PDB_NETWORK_PE 1 // local directories search for COFF, full search for PE +#define PDB_NETWORK_ON 2 // no restrictions + uint pdb_network = PDB_NETWORK_PE; + bool use_http(bool is_pe) const + { + bool ok = pdb_network == PDB_NETWORK_PE && is_pe + || pdb_network == PDB_NETWORK_ON; + deb(IDA_DEBUG_DBGINFO, ok ? "PDB: symbol servers will be used\n" + : "PDB: local directories search only\n"); + return ok; + } + + // Plugin options + uint opt_provider = 0; + // -1 don't specified + // 0 set PDB_FALLBACK to false + // 1 set PDB_FALLBACK to true + int opt_fallback = -1; + + using namelist_t = std::map<ea_t, qstring>; + namelist_t namelist; + + // srcinfo provider + class pdb_provider_t *pdb_srcinfo_provider = nullptr; + + pdb_ctx_t(); + virtual ~pdb_ctx_t(); + virtual bool idaapi run(size_t arg) override; + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; + + void parse_options(bool *opt_skip); + + void init_sympaths(); + void load_vc_til(void) const; + + // maybe_func: -1:no, 0-maybe, 1-yes, 2:no,but iscode + bool apply_name_in_idb(ea_t ea, const qstring &name, int maybe_func, uint32 the_machine_type); + bool apply_debug_info(pdbargs_t &pdbargs); + + // printable register name + bool get_pdb_register_info(int *p_reg, uint64 *p_mask, int machine, int reg); + + // Because we need to be able to call the 'old' pdb plugin + // code, which knows nothing about the til_builder_t (and + // thus its 'machine_type' field, and also because, at the + // very time we call the old pdb code, our til_builder_t + // instance will have been long forgotten and destroyed, + // we must keep this machine type information somewhere. + uint32 g_machine_type = 0; // will be set to CV_CFL_80386 in ctor + +private: + //------------------------------------------------------------------------- + int utf16_encidx = -1; + int get_utf16_encoding_idx(); + + bool checked_types = false; + bool has_sid = false; + bool check_for_ids(ea_t ea, const char *name, bool has_typeinfo); + + void alloc_pdb_srcinfo_provider(); + void free_pdb_srcinfo_provider(); + +public: + //------------------------------------------------------------------------- + //#define CHECK_CREATED_TYPES +#ifdef CHECK_CREATED_TYPES + struct type_to_check_t + { + // one of the following 3 will be valid: + ea_t ea; + int id; + qstring name; + + // the type itself + tinfo_t type; + }; + + qvector<type_to_check_t> types_to_check; + int check_n = 0; + + void check_tinfo(ea_t ea, int id, const char *name, const tinfo_t &tif) + { + type_to_check_t &tc = types_to_check.push_back(); + tc.ea = ea; + tc.id = id; + tc.name = name; + tc.type = tif; + } + + void check_added_types(void) + { + for ( const auto &tc : types_to_check ) + { + if ( !tc.type.is_correct() ) + { + msg("%d: INCORRECT TYPE ", check_n); + if ( !tc.name.empty() ) + msg("%s", tc.name.begin()); + else if ( tc.ea != BADADDR ) + msg("%a", tc.ea); + else + msg("#%d", tc.id); + qstring res; + tc.type.print(&res); + msg(": %s\n", res.c_str()); + check_n++; + } + } + } +#else + inline void check_tinfo(ea_t,int,const char*,const tinfo_t &) {} + inline void check_added_types(void) {} +#endif +}; +extern int data_id; diff --git a/idasdk76/plugins/pdb/pdbaccess.hpp b/idasdk76/plugins/pdb/pdbaccess.hpp new file mode 100644 index 0000000..d5bb377 --- /dev/null +++ b/idasdk76/plugins/pdb/pdbaccess.hpp @@ -0,0 +1,661 @@ + + +#ifndef PDBACCESS__H +#define PDBACCESS__H + +#include <pro.h> +#include "cvconst.h" + +#ifdef __NT__ +#include <windows.h> +#include <oaidl.h> +#include "dia2.h" +#else +// FIXME: It'd be good if those windows declarations for non-windows +// systems were somewhere else than in the PE loader. +#include "../../ldr/pe/mycor.h" +#endif +#include "pdb.hpp" + +//---------------------------------------------------------------------------- +class pdb_access_t; +class local_pdb_access_t; +class remote_pdb_access_t; + +struct pdb_exception_t +{ + pdb_exception_t(const qstring &_what) : what(_what) {} + qstring what; +}; + +//---------------------------------------------------------------------------- +#ifdef __NT__ +enum sym_token_t : uint64 +#else +enum sym_token_t +#endif +{ + t_start = 1 << 0, + // bool + t_bool_start = t_start, + t_constType = t_bool_start, + t_isStatic = 1 << 1, + t_virtual = 1 << 2, + t_volatileType = 1 << 3, + t_code = 1 << 4, + t_hasAssignmentOperator = 1 << 5, + t_hasCastOperator = 1 << 6, + t_function = 1 << 7, // FIXME! + t_constructor = 1 << 8, + t_isVirtualBaseClass = 1 << 9, + t_bool_end = t_isVirtualBaseClass, + + // dword + t_dword_start = 1 << 10, + t_backEndMajor = t_dword_start, + t_baseType = 1 << 11, + t_bitPosition = 1 << 12, + t_callingConvention = 1 << 13, + t_count = 1 << 14, + t_dataKind = 1 << 15, + t_locationType = 1 << 16, + t_registerId = 1 << 17, + t_relativeVirtualAddress = 1 << 18, + t_symIndexId = 1 << 19, + t_symTag = 1 << 20, + t_udtKind = 1 << 21, + t_virtualBaseOffset = 1 << 22, + t_machineType = 1 << 23, + t_classParentId = 1 << 24, + t_typeId = 1 << 25, + t_lexicalParentId = 1 << 26, + t_dword_end = t_lexicalParentId, + + // dword64 + t_dword64_start = 1 << 27, + t_length = t_dword64_start, + t_dword64_end = t_length, + + // string + t_string_start = 1 << 28, + t_name = t_string_start, + t_string_end = t_name, + + // long + t_long_start = 1 << 29, + t_offset = t_long_start, + t_long_end = t_offset, + + // ulonglong + t_ulonglong_start = 1 << 30, + t_virtualAddress = t_ulonglong_start, + t_ulonglong_end = t_virtualAddress, + + // variant + t_variant_start = 1ULL << 31, + t_value = t_variant_start, + t_variant_end = t_value, + + t_end = 1ULL << 32, +}; +CASSERT(sizeof(sym_token_t) == 8); + +inline bool is_sym_token_bool(sym_token_t t) { return t >= t_bool_start && t <= t_bool_end; } +inline bool is_sym_token_dword(sym_token_t t) { return t >= t_dword_start && t <= t_dword_end; } +inline bool is_sym_token_dword64(sym_token_t t) { return t >= t_dword64_start && t <= t_dword64_end; } +// inline bool is_sym_token_pdb_sym(sym_token_t t) { return t >= t_pdb_sym_start && t <= t_pdb_sym_end; } +inline bool is_sym_token_string(sym_token_t t) { return t >= t_string_start && t <= t_string_end; } +inline bool is_sym_token_long(sym_token_t t) { return t >= t_long_start && t <= t_long_end; } +inline bool is_sym_token_ulonglong(sym_token_t t) { return t >= t_ulonglong_start && t <= t_ulonglong_end; } +inline bool is_sym_token_variant(sym_token_t t) { return t >= t_variant_start && t <= t_variant_end; } //-V560 is always true + + +typedef uint64 token_mask_t; +#define TOKEN_MASK_FULL token_mask_t(-1) + +//---------------------------------------------------------------------------- +// engine PDB symbol implementation identity +enum pdb_sym_id_t +{ + DIA_PDB_SYM, + REMOTE_PDB_SYM, + OWN_PDB_SYM, +}; + +//---------------------------------------------------------------------------- +struct pdb_sym_t +{ + virtual HRESULT get_backEndMajor(DWORD *out) = 0; + virtual HRESULT get_baseType(DWORD *out) = 0; + virtual HRESULT get_bitPosition(DWORD *out) = 0; + virtual HRESULT get_callingConvention(DWORD *out) = 0; + virtual HRESULT get_code(BOOL *out) = 0; + virtual HRESULT get_constructor(BOOL *out) = 0; + virtual HRESULT get_isVirtualBaseClass(BOOL *out) = 0; + virtual HRESULT get_constType(BOOL *out) = 0; + virtual HRESULT get_count(DWORD *out) = 0; + virtual HRESULT get_dataKind(DWORD *out) = 0; + virtual HRESULT get_function(BOOL *out) = 0; + virtual HRESULT get_hasAssignmentOperator(BOOL *out) = 0; + virtual HRESULT get_hasCastOperator(BOOL *out) = 0; + virtual HRESULT get_isStatic(BOOL *out) = 0; + virtual HRESULT get_length(DWORD64 *out) = 0; + virtual HRESULT get_lexicalParent(pdb_sym_t *out) = 0; + virtual HRESULT get_locationType(DWORD *out) = 0; + virtual HRESULT get_machineType(DWORD *out) = 0; + virtual HRESULT get_name(qstring *out) = 0; + virtual HRESULT get_offset(LONG *out) = 0; + virtual HRESULT get_registerId(DWORD *out) = 0; + virtual HRESULT get_relativeVirtualAddress(DWORD *out) = 0; + virtual HRESULT get_symIndexId(DWORD *out) = 0; + virtual HRESULT get_symTag(DWORD *out) = 0; + virtual HRESULT get_udtKind(DWORD *out) = 0; + virtual HRESULT get_value(VARIANT *out) = 0; + virtual HRESULT get_virtual(BOOL *out) = 0; + virtual HRESULT get_virtualAddress(ULONGLONG *out) = 0; + virtual HRESULT get_virtualBaseOffset(DWORD *out) = 0; + virtual HRESULT get_volatileType(BOOL *out) = 0; + // Be very, very careful to _not_ use classParent if you can avoid it: + // In case the symbol was *not* resolved through get_type(), the link + // to the parent might be lost, and a bug in the DIA SDK will + // return S_FALSE. + virtual HRESULT get_classParent(pdb_sym_t *out) = 0; + virtual HRESULT get_type(pdb_sym_t *out) = 0; + //------------------------------------------------------------ + virtual HRESULT get_ordinal(DWORD *pRetVal) = 0; + + // careful with this! + virtual void steal_data(pdb_sym_t &other) = 0; + + virtual pdb_sym_id_t whoami(void) = 0; + virtual bool empty(void) = 0; + + virtual ~pdb_sym_t() {} + + // Declare, but ***don't*** define: we don't want + // that to happen, and thus we'll have a linker + // error if that would happen in the code. + DECLARE_UNCOPYABLE(pdb_sym_t); + +protected: + pdb_sym_t() {} +}; +DECLARE_TYPE_AS_MOVABLE(pdb_sym_t); + +typedef janitor_t<pdb_sym_t*> pdb_sym_janitor_t; +template <> inline pdb_sym_janitor_t::~janitor_t() +{ + delete resource; + resource = NULL; +} + +//---------------------------------------------------------------------------- +enum packing_info_t +{ + SYMDAT_PACKED = 1, + SYMDAT_UNPACKED +}; + +//---------------------------------------------------------------------------- +struct sym_data_t +{ + sym_data_t(token_mask_t _tokens, const uchar *buf, size_t bufsize, packing_info_t _packing, bool *_warned); + ~sym_data_t(); + + DWORD get_id() const + { + DWORD id; + if ( get_dword(t_symIndexId, &id) != S_OK ) + INTERR(30211); + return id; + } + HRESULT get_bool(sym_token_t token, BOOL *out) const; + HRESULT get_dword(sym_token_t token, DWORD *out) const; + HRESULT get_dword64(sym_token_t token, DWORD64 *out) const; + HRESULT get_pdb_sym(sym_token_t token, pdb_sym_t *out) const; + HRESULT get_string(sym_token_t token, qstring *out) const; + HRESULT get_dword(sym_token_t token, LONG *out) const; + HRESULT get_ulonglong(sym_token_t token, ULONGLONG *out) const; + HRESULT get_variant(sym_token_t token, VARIANT *out) const; + +private: + sym_data_t(); + + bool token_present(sym_token_t token) const + { + return (present & token) == token; + } + + void assert_token(sym_token_t token) const + { + if ( !token_present(token) ) + INTERR(30210); + } + + const BOOL *bool_ptr(sym_token_t token) const + { + return (const BOOL *)any_ptr(token, t_bool_start, t_bool_end); + } + + const DWORD *dword_ptr(sym_token_t token) const + { + return (const DWORD *)any_ptr(token, t_dword_start, t_dword_end); + } + + const DWORD64 *dword64_ptr(sym_token_t token) const + { + return (const DWORD64 *)any_ptr(token, t_dword64_start, t_dword64_end); + } + + const LONG *long_ptr(sym_token_t token) const + { + return (const LONG *)any_ptr(token, t_long_start, t_long_end); + } + + const ULONGLONG *uint64_ptr(sym_token_t token) const + { + return (const ULONGLONG *)any_ptr(token, t_ulonglong_start, t_ulonglong_end); + } + + const char **string_ptr(sym_token_t token) const + { + return (const char **)any_ptr(token, t_string_start, t_string_end); + } + + const VARIANT *variant_ptr(sym_token_t token) const + { + return (const VARIANT *)any_ptr(token, t_variant_start, t_variant_end); + } + + enum type_t + { + t_bool = 0, + t_dword, + t_dword64, + t_string, + t_long, + t_ulonglong, + t_variant, + t_max + }; + + static const uint32 sizes[]; + + const void *any_ptr(sym_token_t token, sym_token_t start, sym_token_t end) const; + + token_mask_t present; // The tokens that are present in this instance. + bytevec_t data; + uint8 counters[t_max]; + + struct children_t + { + DWORD *ids; + uint32 cnt; + }; + children_t children_infos[SymTagMax]; + friend class remote_pdb_access_t; // accesses children_infos directly + bool *warned; +}; + + +//---------------------------------------------------------------------------- +#ifdef __NT__ +struct dia_pdb_sym_t : public pdb_sym_t +{ + dia_pdb_sym_t(pdb_access_t *_pdb_access, IDiaSymbol *_data, bool _own_sym) + : pdb_access(_pdb_access), + data(_data), + own_sym(_own_sym) + {} + + ~dia_pdb_sym_t() + { + if ( data != NULL && own_sym ) + { + data->Release(); + data = NULL; + } + pdb_access = NULL; + } + + pdb_access_t *pdb_access; + IDiaSymbol *data; + bool own_sym; + + pdb_sym_id_t whoami(void) { return DIA_PDB_SYM; } + void set_symbol_data(IDiaSymbol *s, bool own) + { + data = s; + own_sym = own; + } + bool empty(void) { return data == NULL; } + + HRESULT get_backEndMajor(DWORD *out) { return data->get_backEndMajor(out); } + HRESULT get_baseType(DWORD *out) { return data->get_baseType(out); } + HRESULT get_bitPosition(DWORD *out) { return data->get_bitPosition(out); } + HRESULT get_callingConvention(DWORD *out) { return data->get_callingConvention(out); } + HRESULT get_code(BOOL *out) { return data->get_code(out); } + HRESULT get_constType(BOOL *out) { return data->get_constType(out); } + HRESULT get_count(DWORD *out) { return data->get_count(out); } + HRESULT get_constructor(BOOL *out) { return data->get_constructor(out); } + HRESULT get_isVirtualBaseClass(BOOL *out) { return data->get_virtualBaseClass(out); } + HRESULT get_dataKind(DWORD *out) { return data->get_dataKind(out); } + HRESULT get_function(BOOL *out) { return data->get_function(out); } + HRESULT get_hasAssignmentOperator(BOOL *out) { return data->get_hasAssignmentOperator(out); } + HRESULT get_hasCastOperator(BOOL *out) { return data->get_hasCastOperator(out); } + HRESULT get_isStatic(BOOL *out) { return data->get_isStatic(out); } + HRESULT get_length(DWORD64 *out) { return data->get_length(out); } + HRESULT get_lexicalParent(pdb_sym_t *out) + { + IDiaSymbol *t; + HRESULT res = data->get_lexicalParent(&t); + return handle_related_symbol(res, t, out); + } + HRESULT get_locationType(DWORD *out) { return data->get_locationType(out); } + HRESULT get_machineType(DWORD *out) { return data->get_machineType(out); } + HRESULT get_name(qstring *out) + { + BSTR name; + HRESULT hr = data->get_name(&name); + return maybe_convert_bstr(out, hr, &name); + } + HRESULT get_offset(LONG *out) { return data->get_offset(out); } + HRESULT get_registerId(DWORD *out) { return data->get_registerId(out); } + HRESULT get_relativeVirtualAddress(DWORD *out) { return data->get_relativeVirtualAddress(out); } + HRESULT get_symIndexId(DWORD *out) { return data->get_symIndexId(out); } + HRESULT get_symTag(DWORD *out) { return data->get_symTag(out); } + HRESULT get_udtKind(DWORD *out) { return data->get_udtKind(out); } + HRESULT get_value(VARIANT *out) { return data->get_value(out); } + HRESULT get_virtual(BOOL *out) { return data->get_virtual(out); } + HRESULT get_virtualAddress(ULONGLONG *out) { return data->get_virtualAddress(out); } + HRESULT get_virtualBaseOffset(DWORD *out) { return data->get_virtualBaseOffset(out); } + HRESULT get_volatileType(BOOL *out) { return data->get_volatileType(out); } + HRESULT get_classParent(pdb_sym_t *out) + { + IDiaSymbol *t; + HRESULT res = data->get_classParent(&t); + return handle_related_symbol(res, t, out); + } + + HRESULT get_type(pdb_sym_t *out) + { + IDiaSymbol *t; + HRESULT res = data->get_type(&t); + return handle_related_symbol(res, t, out); + } + + //------------------------------------------------------------ + virtual HRESULT get_ordinal(DWORD *) override { return S_FALSE; } + + HRESULT handle_related_symbol(HRESULT fetch_success, IDiaSymbol *t, pdb_sym_t *out) + { + if ( out == NULL ) + return S_FALSE; + QASSERT(30545, out->whoami() == DIA_PDB_SYM); + dia_pdb_sym_t *sym = (dia_pdb_sym_t *)out; + sym->set_symbol_data(fetch_success == S_OK ? t : NULL, true); + return fetch_success; + } + + // careful with this! + void steal_data(pdb_sym_t &other) + { + QASSERT(30541, whoami() == other.whoami()); + dia_pdb_sym_t &other_dia = (dia_pdb_sym_t &)other; + QASSERT(30503, other_dia.own_sym && other_dia.data != NULL && data == NULL); + data = other_dia.data; + own_sym = true; + other_dia.own_sym = false; + other_dia.data = NULL; + } + +private: + dia_pdb_sym_t(); + + HRESULT maybe_convert_bstr(qstring *out, HRESULT hr, BSTR *s) + { + if ( hr == S_OK ) + { + utf16_utf8(out, *s); + SysFreeString(*s); + } + return hr; + } +}; +DECLARE_TYPE_AS_MOVABLE(dia_pdb_sym_t); + +//---------------------------------------------------------------------------- +#else // __NT__ +struct remote_pdb_sym_t : public pdb_sym_t +{ + remote_pdb_sym_t(pdb_access_t *_pdb_access, sym_data_t *_data) + : pdb_access(_pdb_access), + data(_data) + {} + + ~remote_pdb_sym_t() + { + data = NULL; + pdb_access = NULL; + } + + void set_symbol_data(sym_data_t *s) { data = s; } + + HRESULT get_backEndMajor(DWORD *out) override { return data->get_dword(t_backEndMajor, out); } + HRESULT get_baseType(DWORD *out) override { return data->get_dword(t_baseType, out); } + HRESULT get_bitPosition(DWORD *out) override { return data->get_dword(t_bitPosition, out); } + HRESULT get_callingConvention(DWORD *out) override { return data->get_dword(t_callingConvention, out); } + HRESULT get_code(BOOL *out) override { return data->get_bool(t_code, out); } + HRESULT get_constructor(BOOL *out) override { return data->get_bool(t_constructor, out); } + HRESULT get_isVirtualBaseClass(BOOL *out) override { return data->get_bool(t_isVirtualBaseClass, out); } + HRESULT get_constType(BOOL *out) override { return data->get_bool(t_constType, out); } + HRESULT get_count(DWORD *out) override { return data->get_dword(t_count, out); } + HRESULT get_dataKind(DWORD *out) override { return data->get_dword(t_dataKind, out); } + HRESULT get_function(BOOL *out) override { return data->get_bool(t_function, out); } + HRESULT get_hasAssignmentOperator(BOOL *out) override { return data->get_bool(t_hasAssignmentOperator, out); } + HRESULT get_hasCastOperator(BOOL *out) override { return data->get_bool(t_hasCastOperator, out); } + HRESULT get_isStatic(BOOL *out) override { return data->get_bool(t_isStatic, out); } + HRESULT get_length(DWORD64 *out) override { return data->get_dword64(t_length, out); } + HRESULT get_lexicalParent(pdb_sym_t *out) override; + HRESULT get_locationType(DWORD *out) override { return data->get_dword(t_locationType, out); } + HRESULT get_machineType(DWORD *out) override { return data->get_dword(t_machineType, out); } + HRESULT get_name(qstring *out) override { return data->get_string(t_name, out); } + HRESULT get_offset(LONG *out) override { return data->get_dword(t_offset, out); } + HRESULT get_registerId(DWORD *out) override { return data->get_dword(t_registerId, out); } + HRESULT get_relativeVirtualAddress(DWORD *out) override { return data->get_dword(t_relativeVirtualAddress, out); } + HRESULT get_symIndexId(DWORD *out) override { return data->get_dword(t_symIndexId, out); } + HRESULT get_symTag(DWORD *out) override { return data->get_dword(t_symTag, out); } + HRESULT get_udtKind(DWORD *out) override { return data->get_dword(t_udtKind, out); } + HRESULT get_value(VARIANT *out) override { return data->get_variant(t_value, out); } + HRESULT get_virtual(BOOL *out) override { return data->get_bool(t_virtual, out); } + HRESULT get_virtualAddress(ULONGLONG *out) override { return data->get_ulonglong(t_virtualAddress, out); } + HRESULT get_virtualBaseOffset(DWORD *out) override { return data->get_dword(t_virtualBaseOffset, out); } + HRESULT get_volatileType(BOOL *out) override { return data->get_bool(t_volatileType, out); } + HRESULT get_classParent(pdb_sym_t *out) override; + HRESULT get_type(pdb_sym_t *out) override; + //------------------------------------------------------------ + virtual HRESULT get_ordinal(DWORD *) override { return S_FALSE; } + + // careful with this! + void steal_data(pdb_sym_t &other) override + { + QASSERT(30542, whoami() == other.whoami()); + remote_pdb_sym_t &other_rem = (remote_pdb_sym_t &)other; + QASSERT(30492, other_rem.data != NULL && data == NULL); + data = other_rem.data; + // we don't want to set 'other.data = NULL', because in remote access, + // the pdb_sym_t doesn't actually own the data anyway: it's part of + // the cache. + } + + pdb_sym_id_t whoami(void) override { return REMOTE_PDB_SYM; } + bool empty(void) override { return data == NULL; } + + pdb_access_t *pdb_access; + sym_data_t *data; + +private: + remote_pdb_sym_t(); +}; +DECLARE_TYPE_AS_MOVABLE(remote_pdb_sym_t); +#endif // !__NT__ + +//---------------------------------------------------------------------------- +#define BAD_MACHINE_TYPE ((uint32) -1) + +#define BADSYM ((uint32) -1) + +//------------------------------------------------------------------------- +struct pdb_lnnum_t +{ + pdb_lnnum_t() + : va(BADADDR), length(0), + columnNumber(0), columnNumberEnd(0), + lineNumber(0), lineNumberEnd(0), + file_id(DWORD(-1)), statement(0) {} + ULONGLONG va; + DWORD length; + DWORD columnNumber; + DWORD columnNumberEnd; + DWORD lineNumber; + DWORD lineNumberEnd; + DWORD file_id; + BOOL statement; +}; + +//-------------------------------------------------------------------------- +typedef qvector<pdb_lnnum_t> pdb_lnnum_vec_t; +typedef std::map<int, pdb_lnnum_vec_t> lnmap_t; + +//------------------------------------------------------------------------- +struct pdb_lnnums_t : pdb_lnnum_vec_t +{ + pdb_lnnums_t() : inited(false) {} + + bool get_item_bounds(rangeset_t *set) const; + int get_lnnum() const; + int get_colnum() const; + int get_end_lnnum() const; + int get_end_colnum() const; + + bool inited; +}; + +//---------------------------------------------------------------------------- +class pdb_access_t +{ +public: + pdb_access_t(const pdbargs_t &args) + : pdbargs(args), + machine_type((uint32) -1), + dia_version(0), + base_address(BADADDR), + global_sym_id(BADSYM) + { + } + virtual ~pdb_access_t() {} + + //---------------------------------------------------------------------- + struct children_visitor_t + { + children_visitor_t() + : parent(NULL) {} + + virtual HRESULT visit_child(pdb_sym_t &child) = 0; + virtual ~children_visitor_t() {} + + pdb_sym_t *parent; + }; + + //------------------------------------------------------------------------- + struct dummy_visitor_t : public children_visitor_t + { + virtual HRESULT visit_child(pdb_sym_t &) override { return S_OK; } + }; + + //---------------------------------------------------------------------------- + HRESULT iterate_children( + pdb_sym_t &sym, + enum SymTagEnum type, + children_visitor_t &visitor); + + //---------------------------------------------------------------------------- + virtual HRESULT do_iterate_children( + pdb_sym_t &sym, + enum SymTagEnum type, + children_visitor_t &visitor) = 0; + virtual HRESULT iterate_subtags( + pdb_sym_t &sym, + enum SymTagEnum type, + children_visitor_t &visitor); + virtual HRESULT load(pdb_sym_t &sym, DWORD id) = 0; + + // source-level debugging-specific + virtual HRESULT sip_retrieve_lines_by_va( + pdb_lnnums_t *out, + ULONGLONG va, + ULONGLONG length) = 0; + virtual HRESULT sip_retrieve_lines_by_coords( + pdb_lnnums_t *out, + DWORD file_id, + int lnnum, + int colnum) = 0; + virtual HRESULT sip_iterate_symbols_at_ea( + ULONGLONG va, + ULONGLONG size, + enum SymTagEnum tag, + children_visitor_t &visitor) = 0; + virtual HRESULT sip_iterate_file_compilands( + DWORD file_id, + children_visitor_t &visitor) = 0; + virtual HRESULT sip_retrieve_file_path( + qstring *out, + qstring *errbuf, + DWORD file_id) = 0; + virtual HRESULT sip_retrieve_symbol_files( + qvector<DWORD> *out, + pdb_sym_t &sym) = 0; + virtual HRESULT sip_find_files( + qvector<DWORD> *out, + const char *filename) = 0; // case insensitive search + // /source-level debugging-specific + + //---------------------------------------------------------------------------- + virtual DWORD get_global_symbol_id() const { return global_sym_id; } + virtual ea_t get_base_address() const { return base_address; } + virtual uint32 get_machine_type() const { return machine_type; } + virtual int get_dia_version() const { return dia_version; } + + void set_global_symbol_id(DWORD _global_sym_id) { global_sym_id = _global_sym_id; } + void set_machine_type(uint32 _machine_type) { machine_type = _machine_type; } + void set_base_address(ea_t _base_address) { base_address = _base_address; } + void set_dia_version(int _dia_version) { dia_version = _dia_version; } + + //---------------------------------------------------------------------------- + virtual pdb_sym_t *create_sym(void *data=NULL, bool own=false) = 0; + pdb_sym_t *create_sym(DWORD sym_id) + { + pdb_sym_t *sym = create_sym(); + if ( load(*sym, sym_id) != S_OK ) + { + qstring err; + err.sprnt("Failed loading symbol data for ID %u", sym_id); + delete sym; + throw pdb_exception_t(err.c_str()); + } + return sym; + } + + //---------------------------------------------------------------------------- + const pdbargs_t &pdbargs; + +private: + uint32 machine_type; + int dia_version; + ea_t base_address; + DWORD global_sym_id; + DECLARE_UNCOPYABLE(pdb_access_t) +}; + + +#endif // PDBACCESS__H diff --git a/idasdk75/plugins/pdb/pdblocal.cpp b/idasdk76/plugins/pdb/pdblocal.cpp similarity index 100% rename from idasdk75/plugins/pdb/pdblocal.cpp rename to idasdk76/plugins/pdb/pdblocal.cpp diff --git a/idasdk75/plugins/pdb/pdblocal.hpp b/idasdk76/plugins/pdb/pdblocal.hpp similarity index 100% rename from idasdk75/plugins/pdb/pdblocal.hpp rename to idasdk76/plugins/pdb/pdblocal.hpp diff --git a/idasdk75/plugins/pdb/pdbremote.cpp b/idasdk76/plugins/pdb/pdbremote.cpp similarity index 100% rename from idasdk75/plugins/pdb/pdbremote.cpp rename to idasdk76/plugins/pdb/pdbremote.cpp diff --git a/idasdk76/plugins/pdb/pdbremote.hpp b/idasdk76/plugins/pdb/pdbremote.hpp new file mode 100644 index 0000000..3308799 --- /dev/null +++ b/idasdk76/plugins/pdb/pdbremote.hpp @@ -0,0 +1,163 @@ + +#ifndef PDBREMOTE_HPP +#define PDBREMOTE_HPP + +#include <network.hpp> +#include "../../dbg/win32/win32_rpc.h" +#include "pdbaccess.hpp" + +// The PDB related code that works on Unix +// It connects to a Windows computer and asks to retrieve PDB info + +//---------------------------------------------------------------------------- +bool is_win32_remote_debugger_loaded(); + +//---------------------------------------------------------------------------- +//-V:remote_pdb_access_t:730 not all members of a class are initialized inside the constructor +class remote_pdb_access_t : public pdb_access_t +{ +public: + remote_pdb_access_t( + const pdbargs_t &args, + const char *_host, + int _port, + const char *_pwd) + : pdb_access_t(args), + host(_host), + port(_port), + pwd(_pwd), + remote_session_id(-1) + { + set_base_address(args.loaded_base); + } + + virtual ~remote_pdb_access_t(); + + // Open connection, create PDB session. + HRESULT open_connection(); + // Close PDB session, close connection. + void close_connection(); + + virtual HRESULT do_iterate_children( + pdb_sym_t &sym, + enum SymTagEnum type, + children_visitor_t &visitor) override; + virtual HRESULT load(pdb_sym_t &sym, DWORD id) override; + + virtual HRESULT sip_retrieve_lines_by_va( + pdb_lnnums_t *out, + ULONGLONG va, + ULONGLONG length) override; + virtual HRESULT sip_retrieve_lines_by_coords( + pdb_lnnums_t *out, + DWORD file_id, + int lnnum, + int colnum) override; + virtual HRESULT sip_iterate_symbols_at_ea( + ULONGLONG va, + ULONGLONG size, + enum SymTagEnum tag, + children_visitor_t &visitor) override; + virtual HRESULT sip_iterate_file_compilands( + DWORD file_id, + children_visitor_t &visitor) override; + virtual HRESULT sip_retrieve_file_path( + qstring *out, + qstring *errbuf, + DWORD file_id) override; + virtual HRESULT sip_retrieve_symbol_files( + qvector<DWORD> *out, + pdb_sym_t &sym) override; + virtual HRESULT sip_find_files( + qvector<DWORD> *out, + const char *name) override; + + virtual pdb_sym_t *create_sym(void *data, bool) override + { + sym_data_t *sym = (sym_data_t *)data; + return new remote_pdb_sym_t(this, sym); + } + pdb_sym_t *create_sym(DWORD sym_id) { return pdb_access_t::create_sym(sym_id); } + + // Possibly remote operation. + // If NULL is returned, it means the symbol is not available, nor + // could it be fetched remotely. + ioctl_pdb_code_t get_sym_data(pdb_sym_t &sym, sym_data_t **); + ioctl_pdb_code_t get_sym_data(DWORD sym_id, sym_data_t **); + + +private: + HRESULT _do_iterate_symbols_ids( + const DWORD *ids, + size_t count, + enum SymTagEnum type, + children_visitor_t &visitor); + +#define SAFE_GET(type) \ + sym_data_t *sym_data; \ + ioctl_pdb_code_t result = get_sym_data(sym, &sym_data); \ + if ( result == pdb_ok ) \ + return sym_data->get_##type(token, out); \ + else \ + return E_FAIL + + // Build sym_data_t instance, and register it into the 'cache'. + DWORD build_and_register_sym_data(const uchar **raw, const uchar *end); + + // Whenever fetch_children_infos() or get_sym_data() performs + // a remote operation, this is used to handle the response + // and add the fetched symbol data to the cache. + void handle_fetch_response( + const uchar **ptr, + const uchar *end, + qvector<DWORD> *ids_storage); + + // Remote operation. + ioctl_pdb_code_t fetch_children_infos( + pdb_sym_t &sym, + enum SymTagEnum type, + qvector<DWORD> *children_ids); + + HRESULT handle_fetch_lnnums( + pdb_lnnums_t *out, + const bytevec_t &resp) const; + + HRESULT handle_fetch_file_ids( + qvector<DWORD> *out, + const bytevec_t &resp) const; + + sym_data_t *get_sym_data_from_cache(DWORD id); + + // Low-level interface used by open_connection(), fetch_children_infos(), and get_sym_data(). + // 'fetch_type' is one of + // WIN32_IOCTL_PDB_OPEN, + // WIN32_IOCTL_PDB_FETCH_SYMBOL, + // WIN32_IOCTL_PDB_FETCH_CHILDREN + ioctl_pdb_code_t perform_op(int op_type, const bytevec_t &oper, void *data); + + ioctl_pdb_code_t send_ioctl( + int fn, + const void *buf, + size_t size, + void **poutbuf, + ssize_t *poutsize); + + std::map<DWORD, sym_data_t*> cache; + const char *user_spath; + char errbuf[MAXSTR]; + + // For the moment, we'll channel all IOCTL requests + // through the debugger. Ideally, we should be able to just + // use a RPC client. + bool load_win32_debugger(void); + + const char *host; + int port; + const char *pwd; + bool was_connected; + bool is_dbg_module; + int remote_session_id; + bool warned = false; +}; + +#endif // PDBREMOTE_HPP diff --git a/idasdk75/plugins/pdb/sip.cpp b/idasdk76/plugins/pdb/sip.cpp similarity index 100% rename from idasdk75/plugins/pdb/sip.cpp rename to idasdk76/plugins/pdb/sip.cpp diff --git a/idasdk75/plugins/pdb/sip.hpp b/idasdk76/plugins/pdb/sip.hpp similarity index 100% rename from idasdk75/plugins/pdb/sip.hpp rename to idasdk76/plugins/pdb/sip.hpp diff --git a/idasdk76/plugins/pdb/tilbuild.cpp b/idasdk76/plugins/pdb/tilbuild.cpp new file mode 100644 index 0000000..a9d168f --- /dev/null +++ b/idasdk76/plugins/pdb/tilbuild.cpp @@ -0,0 +1,2424 @@ + +#include "tilbuild.hpp" +#include "misc.cpp" + +//#define PDEB +//#define PDEBSYM +#ifdef PDEB +#define ddeb(x) _ddeb x +AS_PRINTF(1, 2) inline void _ddeb(const char *format, ...) +{ + va_list va; + va_start(va, format); + vmsg(format, va); + va_end(va); +} +#else +#define ddeb(x) (void)0 +#endif +#ifndef TESTABLE_BUILD +#undef PDEB +#undef PDEBSYM +#endif + +static const char fake_vtable_type[] = "$vt"; + +//---------------------------------------------------------------------------- +void til_builder_t::remove_anonymous_namespaces(qstring &buf) +{ + char *p = buf.begin(); + while ( true ) + { // 1234567890 + p = strstr(p, "`anonymous"); + if ( p == NULL ) + break; + const char *q = p + 10; + if ( *q != '-' && *q != ' ' ) + break; + if ( strncmp(q+1, "namespace'::", 12) != 0 ) + break; // 123456789012 + size_t idx = p - buf.begin(); + buf.remove(idx, 10+1+12); + p = buf.begin() + idx; + } +} + +//------------------------------------------------------------------------- +static inline bool ident_char(char c) +{ + return c == '_' || qisalnum(c); +} + +//---------------------------------------------------------------------------- +bool til_builder_t::get_symbol_name(pdb_sym_t &sym, qstring &buf) +{ + bool is_unnamed = false; + sym.get_name(&buf); + if ( buf.empty() ) + { + is_unnamed = true; + } + else + { + // + remove_anonymous_namespaces(buf); + + // <unnamed-tag> => <unnamed_tag> + // <unnamed-type-xxx> => <unnamed_type_xxx> + char *p = buf.begin(); + while ( true ) + { + // 012345678 + p = strstr(p, "<unnamed"); + if ( p == NULL ) + break; + if ( p == buf.begin() ) + is_unnamed = true; + p += 8; + while ( *p != '\0' ) + { + if ( *p == '>' ) + { + p++; + break; + } + else if ( *p == '-' ) + { + *p = '_'; + } + p++; + } + } + if ( !is_unnamed ) + { + const char *marker = strstr(buf.begin(), "__unnamed"); + if ( marker != NULL + // Is prev char not a valid identifier char? + && (marker == buf.begin() || !ident_char(marker[-1])) + // Is next char not a valid identifier char? + && !ident_char(marker[9]) ) + { + is_unnamed = true; + } + } + } + return is_unnamed; +} + +//---------------------------------------------------------------------------- +bool til_builder_t::get_symbol_type(tpinfo_t *out, pdb_sym_t &sym, int *p_id) +{ +#ifdef PDEBSYM + static int zz=0; ++zz; + int zzz = zz; + qstring sym_name; + sym.get_name(&sym_name); + DWORD sym_id = 0; + sym.get_symIndexId(&sym_id); + msg("PDEB: %d: get_symbol_type sym_id=%d '%s'\n", zzz, sym_id, sym_name.c_str()); +#endif + pdb_sym_t *pType = pdb_access->create_sym(); + pdb_sym_janitor_t janitor_pType(pType); + if ( p_id != NULL ) + *p_id = -1; + if ( sym.get_type(pType) != S_OK ) + return false; + bool ok = retrieve_type(out, *pType, NULL, p_id); +#ifdef PDEBSYM + DWORD typsym_id = 0; + pType->get_symIndexId(&typsym_id); + msg("PDEB: %d: get_symbol_type typsym_id=%d tif='%s' ok=%d\n", zzz, typsym_id, out->type.dstr(), ok); +#endif + return ok; +} + +//---------------------------------------------------------------------------- +size_t til_builder_t::get_symbol_type_length(pdb_sym_t &sym) const +{ + DWORD64 size = 0; + DWORD tag = 0; + + sym.get_symTag(&tag); + if ( tag == SymTagData ) + { + pdb_sym_t *pType = pdb_access->create_sym(); + pdb_sym_janitor_t janitor_pType(pType); + if ( sym.get_type(pType) == S_OK ) + pType->get_length(&size); + } + else + { + sym.get_length(&size); + } + return size_t(size); +} + +//---------------------------------------------------------------------- +cvt_code_t til_builder_t::convert_basetype( + tpinfo_t *out, + DWORD baseType, + int size) const +{ + type_t bt = BTF_TYPEDEF; + const char *name = NULL; + switch ( baseType ) + { + case btNoType: + out->is_notype = true; + // Fallthrough. + default: + case 0x12c304: // "impdir_entry" (guessed) + case btBCD: + case btBit: + return cvt_failed; + case btVoid: + bt = BTF_VOID; + break; + case btChar: + bt = BT_INT8|BTMT_CHAR; + break; + case btBool: + bt = BT_BOOL; + if ( size != inf_get_cc_size_b() ) + { + switch ( size ) + { + case 1: + bt |= BTMT_BOOL1; + break; + case 2: + if ( inf_is_64bit() ) + goto MAKE_INT; // 64bit apps do not have BOOL2 + bt |= BTMT_BOOL2; + break; + case 4: + bt |= BTMT_BOOL4; + break; + case 8: + if ( !inf_is_64bit() ) + goto MAKE_INT; // 32bit apps do not have BOOL8 + bt |= BTMT_BOOL8; + break; + default: + // can't make this bool size; make an int + goto MAKE_INT; + } + } + break; +MAKE_INT: + case btInt: + case btLong: + bt = get_scalar_bt(size); + if ( bt == BT_UNK ) + return cvt_failed; + break; + case btUInt: + case btULong: + if ( size == 1 ) + { + bt = BTF_UCHAR; // get_scalar_bt returns 'char', or'ing it with BTMT_USIGNED + // does not help + } + else + { + bt = get_scalar_bt(size); + if ( bt == BT_UNK ) + return cvt_failed; + bt |= BTMT_USIGNED; + } + break; + case btFloat: + if ( size == pv.ph.sizeof_ldbl() ) + { + bt = BTMT_LNGDBL; + } + else + { + switch ( size ) + { + case 4: bt = BTMT_FLOAT; break; + default: + case 8: bt = BTMT_DOUBLE; break; + case 10: bt = BTMT_SPECFLT; break; + } + } + bt |= BT_FLOAT; + break; + case btWChar: name = "wchar_t"; break; + case btBSTR: name = "BSTR"; break; + case btHresult: name = "HRESULT"; break; + case btCurrency: name = "CURRENCY"; break; + case btVariant: name = "VARIANT"; break; + case btComplex: name = "complex"; break; + case btDate: name = "DATE"; break; + } + if ( name != NULL ) + { + out->type.create_typedef(ti, name); + return cvt_typedef; + } + else + { + out->type = tinfo_t(bt); + return cvt_ok; + } +} + +//---------------------------------------------------------------------- +bool til_builder_t::retrieve_arguments( + pdb_sym_t &_sym, + func_type_data_t &fi, + pdb_sym_t *funcSym) +{ + struct type_name_collector_t : public pdb_access_t::children_visitor_t + { + func_type_data_t &fi; + til_builder_t *tb; + til_t *ti; + HRESULT visit_child(pdb_sym_t &sym) override + { + // check that it's a parameter + DWORD dwDataKind; + if ( sym.get_dataKind(&dwDataKind) == S_OK + && dwDataKind != DataIsParam + && dwDataKind != DataIsObjectPtr ) + { + return S_OK; + } + tpinfo_t tpi; + bool cvt_succeeded = tb->retrieve_type(&tpi, sym, parent, NULL); + if ( cvt_succeeded || tpi.is_notype ) + { + funcarg_t &arg = fi.push_back(); + arg.type = tpi.type; + sym.get_name(&arg.name); + } + return S_OK; + } + type_name_collector_t(til_t *_ti, til_builder_t *_tb, func_type_data_t &_fi) + : fi(_fi), tb(_tb), ti(_ti) {} + }; + fi.clear(); + type_name_collector_t pp(ti, this, fi); + HRESULT hr = pdb_access->iterate_children(_sym, SymTagNull, pp); + if ( hr == S_OK && funcSym != NULL ) + { + // get parameter names from the function symbol + func_type_data_t args; + args.flags = 0; + enum_function_args(*funcSym, args); +// QASSERT(497, args.empty() || args.size() == fi.size() ); + bool custom_cc = false; + for ( int i = 0; i < fi.size(); i++ ) + { + if ( i < args.size() ) + { + if ( fi[i].name.empty() ) + fi[i].name = args[i].name; + argloc_t &cur_argloc = args[i].argloc; + fi[i].argloc = cur_argloc; + if ( !custom_cc && cur_argloc.is_reg1() ) + { + if ( is_intel386(pdb_access->get_machine_type()) ) + { + if ( fi.cc == CM_CC_FASTCALL + && cur_argloc.regoff() == 0 + && (cur_argloc.reg1() == R_cx && i == 0 + || cur_argloc.reg1() == R_dx && i == 1) ) + { + // ignore ecx and edx for fastcall + } + else if ( fi.cc == CM_CC_THISCALL + && cur_argloc.regoff() == 0 + && cur_argloc.reg1() == R_cx && i == 0 ) + { + // ignore ecx for thiscall + } + else + { + custom_cc = true; + } + } + } + //ask_for_feedback("pdb: register arguments are not supported for machine type %d", machine_type); + } + } + if ( custom_cc ) + { + // we have some register params; need to convert function to custom cc + fi.cc = (is_purging_cc(fi.cc) || fi.cc == CM_CC_THISCALL || fi.cc == CM_CC_FASTCALL) + ? CM_CC_SPECIALP + : CM_CC_SPECIAL; + } + return true; + } + return false; +} + +//---------------------------------------------------------------------- +cm_t til_builder_t::convert_cc(DWORD cc0) const +{ + switch ( cc0 ) + { + case CV_CALL_GENERIC : + case CV_CALL_NEAR_C : + case CV_CALL_FAR_C : + return inf_is_64bit() ? CM_CC_FASTCALL : CM_CC_CDECL; + case CV_CALL_NEAR_PASCAL: + case CV_CALL_FAR_PASCAL : return CM_CC_PASCAL; + case CV_CALL_NEAR_FAST : + case CV_CALL_FAR_FAST : return CM_CC_FASTCALL; +// case CV_CALL_SKIPPED : + case CV_CALL_NEAR_STD : + case CV_CALL_FAR_STD : + case CV_CALL_ARMCALL : return CM_CC_STDCALL; + case CV_CALL_THISCALL : return CM_CC_THISCALL; +// case CV_CALL_NEAR_SYS : +// case CV_CALL_FAR_SYS : +// case CV_CALL_MIPSCALL : +// case CV_CALL_ALPHACALL : +// case CV_CALL_PPCCALL : +// case CV_CALL_SHCALL : +// case CV_CALL_ARMCALL : +// case CV_CALL_AM33CALL : +// case CV_CALL_TRICALL : +// case CV_CALL_SH5CALL : +// case CV_CALL_M32RCALL : + } + return CM_CC_UNKNOWN; +} + +//---------------------------------------------------------------------- +bool til_builder_t::get_variant_string_value(qstring *out, pdb_sym_t &sym) const +{ + bool ok = false; + VARIANT value; + VariantInit(&value); + if ( sym.get_value(&value) == S_OK ) + { + if ( value.vt == VT_BSTR ) + { + utf16_utf8(out, (wchar16_t*) value.bstrVal); + ok = true; + } + else if ( value.vt == VT_LPSTR ) + { + qstring str((const char *)value.byref); + out->swap(str); + ok = true; + } + } + VariantClear(&value); + return ok; +} + +//---------------------------------------------------------------------- +uint32 til_builder_t::get_variant_long_value(pdb_sym_t &sym) const +{ + uint32 v = 0; + VARIANT value; + VariantInit(&value); + if ( sym.get_value(&value) == S_OK ) + { + switch ( value.vt ) + { + case VT_I1: v = value.cVal; break; + case VT_I2: v = value.iVal; break; + case VT_I4: v = value.lVal; break; + case VT_I8: v = value.llVal; break; + case VT_INT: v = value.intVal; break; + case VT_UI1: v = value.bVal; break; + case VT_UI2: v = value.uiVal; break; + case VT_UI4: v = value.ulVal; break; + case VT_UI8: v = value.ullVal; break; + case VT_UINT: v = value.uintVal; break; + default: + ask_for_feedback("pdb: unsupported VARIANT type %d", value.vt); + break; + } + } + VariantClear(&value); + return v; +} + +//---------------------------------------------------------------------- +// funcSym is Function, typeSym is FunctionType +bool til_builder_t::is_member_func(tinfo_t *class_type, pdb_sym_t &typeSym, pdb_sym_t *funcSym) +{ + // make sure we retrieve class type first + pdb_sym_t *pParent = pdb_access->create_sym(); + pdb_sym_janitor_t janitor_pParent(pParent); + if ( typeSym.get_classParent(pParent) != S_OK || pParent->empty() ) + return false; + + tpinfo_t tpi; + if ( !retrieve_type(&tpi, *pParent, NULL, NULL) ) + return false; // failed to retrieve the parent's type + + class_type->swap(tpi.type); + + // then check if it's static + if ( funcSym != NULL + && pdb_access->get_dia_version() >= 800 ) + { + BOOL bIsStatic = false; + HRESULT hr = funcSym->get_isStatic(&bIsStatic); + if ( hr == S_OK ) + return !bIsStatic; + } + return true; +} + +//---------------------------------------------------------------------------- +bool til_builder_t::is_intel386(DWORD machine_type) const +{ + return machine_type == CV_CFL_80386 + || machine_type == CV_CFL_80486 + || machine_type == CV_CFL_PENTIUM + || machine_type == CV_CFL_PENTIUMII + || machine_type == CV_CFL_PENTIUMIII; +} + +//---------------------------------------------------------------------------- +bool til_builder_t::is_arm(DWORD machine_type) const +{ + return machine_type == CV_CFL_ARM3 + || machine_type == CV_CFL_ARM4 + || machine_type == CV_CFL_ARM4T + || machine_type == CV_CFL_ARM5 + || machine_type == CV_CFL_ARM5T + || machine_type == CV_CFL_ARM6 + || machine_type == CV_CFL_ARM7 + || machine_type == CV_CFL_ARMNT + || machine_type == CV_CFL_ARM_XMAC + || machine_type == CV_CFL_ARM_WMMX + || machine_type == CV_CFL_THUMB; +} + +//---------------------------------------------------------------------- +bool til_builder_t::is_frame_reg(int reg) const +{ + if ( is_intel386(pdb_access->get_machine_type()) ) + return reg == CV_REG_EBP; + else if ( is_arm(pdb_access->get_machine_type()) ) + return reg == CV_ARM_R11 || reg == CV_ARM_SP; + return false; +} + +//---------------------------------------------------------------------------- +int til_builder_t::get_symbol_funcarg_info( + funcarg_t *out, + pdb_sym_t &sym, + DWORD /*dwDataKind*/, + DWORD locType, + int stack_off) +{ + sym.get_name(&out->name); + tpinfo_t tpi; + get_symbol_type(&tpi, sym, NULL); + out->type = tpi.type; + if ( locType == LocIsEnregistered ) + { + DWORD dwReg; + if ( sym.get_registerId(&dwReg) == S_OK ) + { + if ( enregistered_bug && dwReg > 0 ) + dwReg--; + qstring regname; + print_pdb_register(®name, pdb_access->get_machine_type(), dwReg); + out->argloc._set_reg1(str2reg(regname.c_str())); + } + } + else if ( locType == LocIsRegRel ) + { + DWORD dwReg; + LONG lOffset; + if ( sym.get_registerId(&dwReg) == S_OK + && sym.get_offset(&lOffset) == S_OK + && is_frame_reg(dwReg) ) + { + uint32 align; + out->argloc._set_stkoff(stack_off); + size_t argsz = out->type.get_size(&align); + if ( align > argsz ) + argsz = align; + stack_off += argsz; + } + } + else + { + ask_for_feedback("pdb: unsupported location type %d", locType); + } + return stack_off; +} + +//---------------------------------------------------------------------- +void til_builder_t::enum_function_args(pdb_sym_t &_sym, func_type_data_t &args) +{ + // enumerate all function parameters and gather their names + struct param_enumerator_t : public pdb_access_t::children_visitor_t + { + func_type_data_t &args; + til_builder_t *tb; + int stack_off; + virtual HRESULT visit_child(pdb_sym_t &sym) override + { + DWORD tag = 0; + HRESULT hr = sym.get_symTag(&tag); + if ( FAILED(hr) ) + return hr; + + switch ( tag ) + { + case SymTagBlock: // nested blocks + return tb->pdb_access->iterate_children(sym, SymTagNull, *this); + case SymTagFuncDebugStart: + case SymTagFuncDebugEnd: + return S_OK; // ignore these for the moment + } + + DWORD dwDataKind, locType; + if ( sym.get_dataKind(&dwDataKind) == S_OK + && dwDataKind == DataIsParam + && sym.get_locationType(&locType) == S_OK ) + { + funcarg_t &fa = args.push_back(); + stack_off = tb->get_symbol_funcarg_info(&fa, sym, dwDataKind, locType, stack_off); + } + return S_OK; // continue enumeration + } + param_enumerator_t(func_type_data_t &_args, til_builder_t *_tb) + : args(_args), tb(_tb), stack_off(0) {} + }; + param_enumerator_t pen(args, this); + pdb_access->iterate_children(_sym, SymTagData, pen); +} + +//---------------------------------------------------------------------- +// corrupted PDB may produce the strange results +cvt_code_t til_builder_t::verify_struct(pdb_udt_type_data_t &udt) const +{ + for ( auto &udm : udt ) + { + if ( !udm.is_bitfield() && (udm.offset % 8) != 0 ) + return cvt_failed; + } + return cvt_ok; +} + +//---------------------------------------------------------------------- +// verify unions that would be created out of [p1, p2) members. +// The [p1, p2) members are spoiled by the function. +// Create substructures if necessary. Returns the result in out (can be the same +// vector as [p1, p2) +cvt_code_t til_builder_t::verify_union( + pdb_udt_type_data_t *out, + pdb_udt_type_data_t::iterator p1, + pdb_udt_type_data_t::const_iterator p2) const +{ + if ( p1 == p2 ) + return cvt_ok; + + QASSERT(498, p2 > p1); + uint64 off = p1->offset; + typedef qvector<pdb_udt_type_data_t> stems_t; + stems_t stems; // each stem is a member of the future union + for ( pdb_udt_type_data_t::iterator q=p1; q != p2; ++q ) + { + pdb_udt_type_data_t *best = NULL; + q->offset -= off; + if ( q->offset != 0 ) + { // find best suited stem: the one with end() closest to our offset + uint64 bestend = 0; + for ( stems_t::iterator s=stems.begin(); s != stems.end(); ++s ) + { + pdb_udt_type_data_t &sm = *s; + pdb_udt_member_t &lastmem = sm.back(); + uint64 smend = lastmem.end(); + if ( (lastmem.is_bitfield() == q->is_bitfield() || q->bit_offset == 0) + && smend <= q->begin() + && (best == NULL || bestend < smend) ) + { + best = &sm; + bestend = smend; + } + } + } + if ( best == NULL ) + best = &stems.push_back(); + uint64 qend; + if ( q->is_bitfield() ) + { + bitfield_type_data_t bi; + q->type.get_bitfield_details(&bi); + size_t size = bi.nbytes * 8; + QASSERT(30385, size == 8 || size == 16 || size == 32 || size == 64); + qend = q->offset - q->bit_offset + size; + } + else + { + qend = q->offset + q->size + 7; + } + qend /= 8; + if ( best->total_size < qend ) + best->total_size = qend; + qswap(best->push_back(), *q); + } + + // all non-trivial stems must be converted to structures + for ( stems_t::iterator s=stems.begin(); s != stems.end(); ++s ) + { + if ( s->size() == 1 && s->begin()->offset == 0 && !s->begin()->is_bitfield() ) + continue; +#ifdef PDEB + msg("CREATE STEM\n"); + for ( pdb_udt_type_data_t::iterator p=s->begin(); p != s->end(); ++p ) + msg(" %" FMT_64 "x %s %s\n", p->offset, p->type.dstr(), p->name.c_str()); +#endif + if ( verify_struct(*s) != cvt_ok ) + return cvt_failed; + tinfo_t tif; + int total_size = s->total_size; + cvt_code_t code = create_udt_ref(&tif, s, UdtStruct); + if ( code != cvt_ok ) + return code; + s->resize(1); + pdb_udt_member_t &sm = s->front(); + sm.offset = 0; + sm.size = uint64(total_size) * 8; + sm.name.sprnt("__s%u", uint(s-stems.begin())); + sm.type = tif; + } + + // collect the results + out->resize(stems.size()); + for ( int i=0; i < stems.size(); i++ ) + { + QASSERT(499, stems[i].size() == 1); + qswap(out->at(i), *stems[i].begin()); + } + return cvt_ok; +} + +//---------------------------------------------------------------------- +// create a union out of [p1, p2) members. they are spoiled by the function. +// returns type of the new union and its fields +// this function also creates substructures if necessary +cvt_code_t til_builder_t::create_union( + tinfo_t *out, + size_t *p_total_size, + pdb_udt_type_data_t::iterator p1, + pdb_udt_type_data_t::const_iterator p2) const +{ +#ifdef PDEB + msg("CREATE UNION\n"); + for ( pdb_udt_type_data_t::iterator p=p1; p != p2; ++p ) + msg(" %" FMT_64 "x %s %s\n", p->offset, p->type.dstr(), p->name.c_str()); +#endif + pdb_udt_type_data_t unimems; + cvt_code_t code = verify_union(&unimems, p1, p2); + if ( code != cvt_ok ) + return code; + // calculate the total size + for ( int i=0; i < unimems.size(); i++ ) + { + pdb_udt_member_t &udm = unimems[i]; + size_t nbytes = (udm.end() + 7) / 8; + if ( nbytes > unimems.total_size ) + unimems.total_size = nbytes; + } + if ( p_total_size != NULL ) + *p_total_size = unimems.total_size; + return create_udt_ref(out, &unimems, UdtUnion); +} + +//---------------------------------------------------------------------- +inline void ida_vft_name(qstring *vftn, const char *ns, uint32_t offset=0) +{ + qstring new_vft_name(ns); + if ( offset != 0 ) + new_vft_name.cat_sprnt("_%04X", offset); + new_vft_name.append(VTBL_SUFFIX); + vftn->swap(new_vft_name); +} + +//---------------------------------------------------------------------- +#define MS_VTBL_SUFFIX "Vtbl" +inline void ms_vft_name(qstring *vftn, const char *ns) +{ + qstring new_vft_name(ns); + new_vft_name.append(MS_VTBL_SUFFIX); + vftn->swap(new_vft_name); +} + +//---------------------------------------------------------------------- +inline bool is_ms_vft_name(const qstring &udt_name) +{ + size_t len = udt_name.length(); + return len > sizeof(MS_VTBL_SUFFIX) + && streq(udt_name.begin() + (len - sizeof(MS_VTBL_SUFFIX) + 1), MS_VTBL_SUFFIX); +} + +//---------------------------------------------------------------------- +inline void ida_vft_name_from_ms(qstring *ivftnm, const qstring &msvftnm) +{ + qstring tmp(msvftnm); + if ( is_ms_vft_name(msvftnm) ) + tmp.remove(tmp.length()-4, 4); + ida_vft_name(ivftnm, tmp.c_str()); +} + +//---------------------------------------------------------------------- +bool til_builder_t::get_vft_name(qstring *vftn, uint32 *ord, const char *ns, uint32_t offset) +{ + bool vft_creating = false; + qstring new_vft_name; + // check for MS vftable + ms_vft_name(&new_vft_name, ns); + uint32 id = get_type_ordinal(ti, new_vft_name.c_str()); + if ( id == 0 ) + { + // maybe creating? + vft_creating = creating.find(new_vft_name.c_str()) != creating.end(); + if ( !vft_creating ) + { + ida_vft_name(&new_vft_name, ns, offset); + if ( ord != nullptr ) + id = get_type_ordinal(ti, new_vft_name.c_str()); + } + } + vftn->swap(new_vft_name); + if ( ord != nullptr ) + *ord = id; + return vft_creating; +} + +//---------------------------------------------------------------------- +void pdb_udt_type_data_t::convert_to_tinfo_udt(udt_type_data_t *out) +{ + out->total_size = total_size; + out->taudt_bits = taudt_bits; + out->is_union = is_union; + out->reserve(size()); + for ( size_t i = 0; i < size(); i++ ) + { + udt_member_t &udm = at(i); + out->push_back().swap(udm); + } +} + +//---------------------------------------------------------------------- +// insert si into the destination type +inline void merge_vft_udm(int *j, udt_type_data_t *dst_udt, const udt_member_t &si, bool replace) +{ + bool insert_src = true; + for ( ; *j < dst_udt->size(); (*j)++ ) + { + udt_member_t &dj = (*dst_udt)[*j]; + if ( dj.offset + dj.size <= si.offset ) + continue; + if ( dj.offset >= si.offset + si.size ) + break; // should insert before dj + // Looks like an overlap, + // fields may differ in type and name only. + // Ignore "__vecDelDtor", + // this often happens when virtual class::~class + // is later redefined as __vecDelDtor() + if ( replace && si.name != "__vecDelDtor" + || dj.name == "__vecDelDtor" ) + { + dj.type = si.type; + dj.name = si.name; + } + insert_src = false; + break; + } + if ( insert_src ) + dst_udt->insert(dst_udt->begin()+*j, si); +} + +//---------------------------------------------------------------------- +// merge two vftables into one +// dst_udt gets all fields of srctype in addition to its own fields. +// dst_udt preserves or overrides the coinciding field. +static void merge_vftables(udt_type_data_t *dst_udt, const tinfo_t &srcvft, bool replace) +{ + udt_type_data_t src_udt; + if ( !srcvft.get_udt_details(&src_udt) ) + { + deb(IDA_DEBUG_DBGINFO, "PDB: failed to merge type '%s' to vftable\n", srcvft.dstr()); +#if defined(TESTABLE_BUILD) && !defined(__FUZZER__) + INTERR(30585); +#else + return; +#endif + } + + int j(0); + for ( const auto &si : src_udt ) + merge_vft_udm(&j, dst_udt, si, replace); + dst_udt->total_size = (dst_udt->back().end() + 7) / 8; +} + +//---------------------------------------------------------------------- +static void add_vftable_member( + udt_type_data_t *dst_udt, + const tinfo_t &member, + const char *name, + DWORD vfptr_offset) +{ + tinfo_t ptr_member; + ptr_member.create_ptr(member); // the field is a pointer to function + asize_t size = ptr_member.get_size(); + + udt_member_t udm; + udm.offset = uint64(vfptr_offset) * 8; + udm.size = uint64(size) * 8; + udm.type = ptr_member; + udm.effalign = size; + udm.name = name; + + int j(0); + merge_vft_udm(&j, dst_udt, udm, true); + dst_udt->total_size = (dst_udt->back().end() + 7) / 8; +} + +//---------------------------------------------------------------------- +inline bool get_vfptr_offset(DWORD *vfptr_offset, pdb_sym_t &sym) +{ + BOOL is_virtual; + return sym.get_virtual(&is_virtual) == S_OK + && is_virtual + && sym.get_virtualBaseOffset(vfptr_offset) == S_OK; +} + +//---------------------------------------------------------------------- +// enumerate virtual functions of class sym and create a vtable structure +// with function pointers +cvt_code_t til_builder_t::make_vtable_struct(tinfo_t *out, pdb_sym_t &_sym) +{ + struct virtual_func_visitor_t : public pdb_access_t::children_visitor_t + { + til_builder_t *tb; + vft_info_t *vftinfo; // vftable info + virtual HRESULT visit_child(pdb_sym_t &sym) override + { + qstring name; + sym.get_name(&name); + + // is introducing virtual? + DWORD vfptr_offset = -1; + bool is_intro_virtual = get_vfptr_offset(&vfptr_offset, sym); + + tpinfo_t tpi; + if ( is_intro_virtual && tb->retrieve_type(&tpi, sym, parent, NULL) ) + { + ddeb(("PDEB: make_vtable_struct add '%s' vptr offset %u\n", tpi.type.dstr(), vfptr_offset)); + add_vftable_member(&vftinfo->udt, tpi.type, name.c_str(), vfptr_offset); + } + return S_OK; + } + virtual_func_visitor_t(til_builder_t *_tb, vft_info_t *_vftinfo) + : tb(_tb), + vftinfo(_vftinfo) + {} + }; + + qstring udt_name; + _sym.get_name(&udt_name); + // FIXME: should we remove classprefix (name + "::") ? + #ifdef PDEB + static int zzlevel = 0; + msg("PDEB: %d{ make_vtable_struct '%s'\n", ++zzlevel, udt_name.c_str()); + #endif + vft_info_t vftinfo; + virtual_func_visitor_t pp(this, &vftinfo); + pdb_access->iterate_children(_sym, SymTagFunction, pp); + + bool ok = false; + if ( !vftinfo.udt.empty() ) + { + out->create_udt(vftinfo.udt, BTF_STRUCT); + ddeb(("PDEB: %d make_vtable_struct collected vftable '%s'\n", zzlevel, out->dstr())); + ok = out->calc_udt_aligns(); + } + #ifdef PDEB + if ( !ok ) + msg("PDEB: make_vtable_struct failed to create vftable\n"); + msg("PDEB: %d} make_vtable_struct '%s'\n", zzlevel--, udt_name.c_str()); + #endif + return ok ? cvt_ok : cvt_failed; +} + +//---------------------------------------------------------------------- +inline bool is_fake_vftable(tinfo_t vft_tif) +{ + qstring tname; + return vft_tif.get_final_type_name(&tname) && tname == fake_vtable_type; +} + +//---------------------------------------------------------------------- +cvt_code_t til_builder_t::convert_udt( + tinfo_t *out, + pdb_sym_t &_sym, + DWORD64 size) +{ + DWORD udtKind; + if ( _sym.get_udtKind(&udtKind) != S_OK ) + return cvt_failed; + + // retrieve member names, types, offsets + struct type_name_collector_t : public pdb_access_t::children_visitor_t + { + til_builder_t *tb; + pdb_udt_type_data_t &udt; + const char *vftname; // vftable name + vft_info_t *vftinfo; // vftable info, maybe nullptr if we don't want + // to collect vftable + bool mark_lpVtbl; // mark "lpVtbl" as pointer to vftable + bool has_virtbases; + HRESULT visit_child(pdb_sym_t &sym) override + { + qstring name; + sym.get_name(&name); + + // is introducing virtual? + DWORD vfptr_offset = -1; + bool is_intro_virtual = get_vfptr_offset(&vfptr_offset, sym); + + LONG offset = 0; + if ( !is_intro_virtual && sym.get_offset(&offset) != S_OK ) + return S_OK; + // assert: intro virtual or data member + + tpinfo_t tpi; + if ( !tb->retrieve_type(&tpi, sym, parent, NULL) ) + return S_OK; + + if ( is_intro_virtual ) + { + if ( vftinfo != nullptr ) + { + ddeb(("PDEB: convert_udt vtable %s add '%s' of '%s' vptr offset %u\n", vftname, name.c_str(), tpi.type.dstr(), vfptr_offset)); + add_vftable_member(&vftinfo->udt, tpi.type, name.c_str(), vfptr_offset); + } + return S_OK; + } + + ddeb(("PDEB: convert_udt adding member '%s' of type '%s'\n", name.c_str(), tpi.type.dstr())); + asize_t memsize = tb->get_symbol_type_length(sym); + + pdb_udt_member_t &udm = udt.push_back(); + + DWORD tag = SymTagNull; + sym.get_symTag(&tag); + if ( tag == SymTagBaseClass ) + { + udm.set_baseclass(); + // determine if the base is virtual + BOOL is_virtbase = false; + sym.get_isVirtualBaseClass(&is_virtbase); + if ( is_virtbase ) + { + udm.set_virtbase(); + has_virtbases = true; + } + + // we are interested only in baseclass at offset 0 + if ( offset == 0 && vftinfo != nullptr ) + { + // get baseclass vftable + qstring bcvft_name; + uint32 bcvft_ord; + tb->get_vft_name(&bcvft_name, &bcvft_ord, name.c_str()); + if ( bcvft_ord != 0 ) + { + tinfo_t bcvft_tif; + bcvft_tif.get_numbered_type(tb->ti, bcvft_ord); + if ( !is_fake_vftable(bcvft_tif) ) + { + ddeb(("PDEB: convert_udt vtable %s add baseclass %s vtable '%s'\n", vftname, bcvft_name.c_str(), bcvft_tif.dstr())); + merge_vftables(&vftinfo->udt, bcvft_tif, false); + } + else + { + ddeb(("PDEB: convert_udt vtable %s baseclass %s vtable is fake\n", vftname, bcvft_name.c_str())); + } + } + else + { + ddeb(("PDEB: convert_udt vtable %s baseclass %s vtable not found\n", vftname, bcvft_name.c_str())); + vftinfo->base0.swap(bcvft_name); + } + } + name.clear(); // no name for baseclass member + } + else if ( tag == SymTagVTable ) + { + ddeb(("PDEB: convert_udt our vtable '%s'\n", tpi.type.dstr())); + if ( is_fake_vftable(tpi.type) ) + { + tpi.type = tinfo_t::get_stock(STI_PVOID); + } + else + { + if ( vftinfo != nullptr ) + merge_vftables(&vftinfo->udt, tpi.type, true); + // type is a structure, while the field is a pointer to it + tpi.type.create_ptr(tpi.type); + } + name = VTBL_MEMNAME; // we need only this name + memsize = tpi.type.get_size(); + udm.set_vftable(); + } + // mark MS vftable pointer + if ( mark_lpVtbl && tpi.type.is_ptr() && name == "lpVtbl" ) + { // no need to rename it + udm.set_vftable(); + } + mark_lpVtbl = false; // pointer to vftable maybe the first field only + + DWORD64 ulLen = DWORD64(memsize) * 8; + DWORD dwBitPos = 0; + DWORD dwLocType = LocIsNull; + sym.get_locationType(&dwLocType); // may fail, just ignore + if ( dwLocType == LocIsBitField ) + { + sym.get_bitPosition(&dwBitPos); + sym.get_length(&ulLen); + if ( dwBitPos + ulLen > DWORD64(memsize) * 8 ) + return E_FAIL; + bool is_unsigned = tpi.type.is_unsigned(); + udm.type.create_bitfield(memsize, ulLen, is_unsigned); + } + else + { + udm.type = tpi.type; + } + udm.size = ulLen; + udm.offset = uint64(offset) * 8 + dwBitPos; + udm.bit_offset = dwBitPos; + udm.name.swap(name); + ddeb(("PDEB: convert_udt adding member size %" FMT_64 "u offset %" FMT_64 "u bit_offset %u\n", udm.size, udm.offset, udm.bit_offset)); + return S_OK; + } + type_name_collector_t( + til_builder_t *_tb, + pdb_udt_type_data_t &m, + const char *_vftname, + vft_info_t *_vftinfo) + : tb(_tb), + udt(m), + vftname(_vftname), + vftinfo(_vftinfo), + mark_lpVtbl(true), + has_virtbases(false) + {} + }; + + qstring udt_name; + _sym.get_name(&udt_name); + + bool is_vtbl_udt = is_ms_vft_name(udt_name); + qstring udt_vft_name; + uint32 udt_vft_ord(0); + bool vft_creating = false; + if ( !is_vtbl_udt ) + vft_creating = get_vft_name(&udt_vft_name, &udt_vft_ord, udt_name.c_str()); + bool collect_vft = !vft_creating && !is_vtbl_udt && udt_vft_ord == 0; + + #ifdef PDEB + static int zzlevel = 0; + msg("PDEB: %d{ convert_udt '%s' assuming vftable '%s'\n", ++zzlevel, udt_name.c_str(), udt_vft_name.c_str()); + #endif + pdb_udt_type_data_t udt; + if ( is_vtbl_udt ) + udt.taudt_bits |= TAUDT_VFTABLE; + vft_info_t vtinfo; + type_name_collector_t pp( + this, + udt, + udt_vft_name.c_str(), + collect_vft ? &vtinfo : nullptr); + pdb_access->iterate_children(_sym, SymTagNull, pp); + + bool is_cppobj = false; + if ( collect_vft && !vtinfo.udt.empty() ) + { + if ( vtinfo.base0.empty() ) + { + tinfo_t vft_tif; + if ( vft_tif.create_udt(vtinfo.udt, BTF_STRUCT) + && vft_tif.calc_udt_aligns() ) + { + ddeb(("PDEB: convert_udt %d collected vftable '%s' '%s'\n", zzlevel, udt_vft_name.c_str(), vft_tif.dstr())); + uint32 id = get_type_ordinal(ti, udt_vft_name.c_str()); + if ( id == 0 ) + vft_tif.set_named_type(ti, udt_vft_name.c_str(), NTF_NOBASE); + else + ddeb(("PDEB: convert_udt '%s' exists\n", udt_vft_name.c_str())); + is_cppobj = true; // there is a vftable, so it is a C++ object + } + else + { // ignore failure, continue w/o vftable + ddeb(("PDEB: convert_udt failed to create vftable\n")); + } + } + else + { + vftmap.emplace(std::make_pair(udt_vft_name.c_str(), vtinfo)); + } + } + #ifdef PDEB + msg("PDEB: %d} convert_udt '%s'\n", zzlevel--, udt_name.c_str()); + #endif + + // if we will use MS Vtbl then create IDA synonym + if ( is_vtbl_udt ) + { + tinfo_t tif; + tif.create_typedef(ti, udt_name.c_str()); + qstring ivftnm; + ida_vft_name_from_ms(&ivftnm, udt_name.c_str()); + tif.set_named_type(ti, ivftnm.c_str(), NTF_NOBASE); + } + + // if we inherit from c++ object, we are too a c++ object + if ( size > 0 ) + { + if ( udt.empty() ) + is_cppobj = true; + if ( udt.size() == 1 + && udt[0].is_baseclass() + && udt[0].type.is_empty_udt() ) + { + is_cppobj = true; + } + } + if ( is_cppobj ) + { + udt.taudt_bits |= TAUDT_CPPOBJ; + } + else if ( udt.empty() ) + { // create forward ref + qstring name; + get_symbol_name(_sym, name); + type_t bt = udtKind == UdtUnion ? BTF_UNION : BTF_STRUCT; + out->create_typedef(ti, name.c_str(), bt); + return cvt_typedef; + } + udt.total_size = size; + std::stable_sort(udt.begin(), udt.end()); + BOOL cppobj; + if ( _sym.get_constructor(&cppobj) == S_OK && cppobj > 0 ) + udt.taudt_bits |= TAUDT_CPPOBJ; + return create_udt(out, &udt, udtKind, udt_name.c_str()); +} + +//---------------------------------------------------------------------- +inline void get_empty_vft_tif(tinfo_t *vtif) +{ + udt_type_data_t empty_udt; + empty_udt.taudt_bits |= TAUDT_VFTABLE; + vtif->create_udt(empty_udt, BTF_STRUCT); +} + +//---------------------------------------------------------------------- +// fill the empty start slots of vftable, +// the holes will be filled latter, see SUDT_GAPS +static void fill_vft_empty_splots(udt_type_data_t *udt) +{ + if ( udt->empty() ) + return; + + uint64 offset = udt->begin()->offset; + if ( offset == 0 ) + return; + uint32 nbytes = offset / 8; + + udt_member_t gap; + gap.type.create_array(tinfo_t(BTF_BYTE), nbytes); + gap.offset = 0; + gap.size = offset; + gap.effalign = 1; + gap.name = "gap0"; + udt->insert(udt->begin(), gap); + // assert: no need to fix udt->total_size +} + +//---------------------------------------------------------------------- +void til_builder_t::create_vftables() +{ + while ( !vftmap.empty() ) + { + bool changed = false; + for ( auto p=vftmap.begin(); p != vftmap.end(); ) + { + auto &name = p->first; + auto &info = p->second; + ddeb(("PDB: create_vftables checking %s base0 %s\n", name.c_str(), info.base0.c_str())); + const char *b0name = info.base0.c_str(); + uint32 id = get_type_ordinal(ti, b0name); + if ( id != 0 ) + { // merge the known base class vftable + ddeb(("PDB: merge %s to %s\n", b0name, name.c_str())); + tinfo_t btif; + btif.get_numbered_type(ti, id); + merge_vftables(&info.udt, btif, false); + info.base0.clear(); + changed = true; + } + else + { + auto r = vftmap.find(b0name); + if ( r == vftmap.end() || r->second.empty() ) + { // ordinary class + ddeb(("PDB: ignore %s for %s\n", b0name, name.c_str())); + info.base0.clear(); + changed = true; + } + else + { + ddeb(("PDB: skip %s for %s\n", b0name, name.c_str())); + } + } + if ( info.base0.empty() ) + { // all base classes references are resolved, create vftable + ddeb(("PDB: create_vftables creating %s\n", name.c_str())); + tinfo_t vtif; + if ( !vtif.create_udt(info.udt, BTF_STRUCT) + || !vtif.calc_udt_aligns() ) + { // something wrong with vftable udt, + // create an empty vftable + ddeb(("PDEB: create_vftables failed to create vftable %s\n", name.c_str())); + get_empty_vft_tif(&vtif); + } + ddeb(("PDB: create_vftables created %s '%s'\n", name.c_str(), vtif.dstr())); + vtif.set_named_type(ti, name.c_str(), NTF_NOBASE); + p = vftmap.erase(p); + changed = true; + } + else + { + ++p; + } + } + if ( !changed ) + break; + } + + if ( !vftmap.empty() ) + { // Something wrong or not: + // base class w/o virtual functions + // cyclic references, + // missed types + // Create the vftables ASIS + for ( auto p : vftmap ) + { + auto &name = p.first; + auto &info = p.second; + ddeb(("PDEB: create_vftables create vftable %s ASIS, base0 %s\n", name.c_str(), info.base0.c_str())); + fill_vft_empty_splots(&info.udt); + tinfo_t vtif; + vtif.create_udt(info.udt, BTF_STRUCT); + vtif.calc_udt_aligns(); + ddeb(("PDB: create_vftables created %s '%s'\n", name.c_str(), vtif.dstr())); + vtif.set_named_type(ti, name.c_str(), NTF_NOBASE); + } + vftmap.clear(); + } +} + +//---------------------------------------------------------------------- +static bool set_array_type(pdb_udt_member_t *udm, int nbytes) +{ + bool ok = udm->type.create_array(tinfo_t(BT_UNK_BYTE), nbytes); + if ( ok ) + udm->size = nbytes * 8; + return ok; +} + +//---------------------------------------------------------------------- +// the real UDT should have non-zero size, +// detect a forward reference to a UDT without a real definition +inline bool is_fwdref_baseclass(pdb_udt_member_t &udm) +{ + return udm.is_baseclass() && udm.size == 0; +} + +//---------------------------------------------------------------------- +cvt_code_t til_builder_t::create_udt(tinfo_t *out, pdb_udt_type_data_t *udt, int udtKind, const char *udt_name) const +{ + cvt_code_t code; + if ( udtKind == UdtUnion ) + { + udt->is_union = true; + code = verify_union(udt, udt->begin(), udt->end()); + } + else + { + // find overlapping members and convert into subunions (anonymous union would be great) + udt->is_union = false; + code = handle_overlapping_members(udt); + } + if ( code != cvt_ok ) + return code; + + // validate the type sizes, for the following reasons: + // - pdb information may be misleading (see pc_pdb_redefined_type.pe) + // - the same type name can be used for different types + // - invalid arrays happen (pc_pdb_wow.pe) + for ( int i=0; i < udt->size(); i++ ) + { + pdb_udt_member_t &udm = udt->at(i); + if ( udm.is_bitfield() ) + continue; + int gts_code = GTS_NESTED | (udm.is_baseclass() ? GTS_BASECLASS : 0); + size_t nbytes = udm.type.get_size(NULL, gts_code); + if ( nbytes == BADSIZE && !is_fwdref_baseclass(udm) ) + continue; // cannot verify, the type is not ready yet + if ( uint64(nbytes)*8 != udm.size ) + { + if ( nbytes != 0 ) + { + if ( !set_array_type(&udm, udm.size/8) ) + return cvt_failed; + } + else if ( udm.is_baseclass() || udm.type.is_array() ) + { // nbytes==0 + udm.size = 0; // correct the base class size + } + } + } + + if ( udt->total_size == 0 && !udt->empty() ) + { // msdia did not provide the udt size. use the end of the last element + pdb_udt_member_t &udm = udt->back(); + udt->total_size = (udm.end() + 7) / 8; + } + + // the kernel cannot handle virtual base classes yet, so we remove them + // also check for overlapping members and members that go past the udt end + uint64 last = 0; + uint64 total_bits = uint64(udt->total_size) * 8; + for ( int i=0; i < udt->size(); i++ ) + { + pdb_udt_member_t &udm = udt->at(i); + if ( udm.offset < last || udm.end() > total_bits ) + { + if ( udm.end() > total_bits ) + udm.size = total_bits - udm.offset; + int nbytes = (udm.end() + 7 - last) / 8; + if ( nbytes > 0 ) + { // replace with byte array + if ( !set_array_type(&udm, nbytes) ) + return cvt_failed; + if ( udm.name.empty() ) + udm.name.sprnt("_bytes_%" FMT_64 "x", last/8); + udm.offset = last; + udm.clr_baseclass(); + udm.clr_virtbase(); + } + else + { // we do not need this member + udt->erase(udt->begin()+i); + --i; + continue; + } + } + if ( udtKind != UdtUnion ) + last = udm.end(); + } + + type_t bt = udt->is_union ? BTF_UNION : BTF_STRUCT; + udt_type_data_t tinfo_udt; + udt->convert_to_tinfo_udt(&tinfo_udt); + out->create_udt(tinfo_udt, bt); + if ( !out->calc_udt_aligns(SUDT_GAPS|SUDT_UNEX) ) + { +#if defined(TESTABLE_BUILD) && !defined(__FUZZER__) + QASSERT(30380, !inf_test_mode() && out->get_size() == BADSIZE); +#endif + deb(IDA_DEBUG_DBGINFO, "PDB: Failed to calculate struct '%s' member alignments\n", udt_name != nullptr ? udt_name : ""); + ask_for_feedback("Failed to calculate struct member alignments"); + } + return cvt_ok; +} + +//---------------------------------------------------------------------- +// is the return type complex? +// if so, a pointer to return value will be passed as a hidden parameter +bool til_builder_t::is_complex_return(pdb_sym_t &sym) const +{ + pdb_sym_t *pType = pdb_access->create_sym(); + pdb_sym_janitor_t janitor_pType(pType); + bool complex = false; + if ( sym.get_type(pType) == S_OK ) + { + DWORD tag = 0; + complex = pType->get_symTag(&tag) == S_OK && tag == SymTagUDT; + if ( complex ) + { + ULONGLONG size; + complex = pType->get_length(&size) == S_OK && size > 8; + } + if ( !complex && tag == SymTagUDT ) + { + // we've got a small UDT which possibly fits into a register (or two) + // but it has to be a POD for that, i.e. should have no constructor or assignment operators + BOOL b; + if ( (pType->get_constructor (&b) == S_OK) && b + || (pType->get_hasAssignmentOperator(&b) == S_OK) && b + || (pType->get_hasCastOperator (&b) == S_OK) && b ) + complex = true; + } + } + return complex; +} + + +//---------------------------------------------------------------------------- +bool til_builder_t::is_unnamed_tag_typedef(const tinfo_t &tif) const +{ + uint32 id = tif.get_ordinal(); + if ( id == 0 ) + return false; + + return unnamed_types.find(id) != unnamed_types.end(); +} + + +//---------------------------------------------------------------------- +// borland does not like this structure to be defined inside a function. +// this is the only reason why it is in the file scope. +struct this_seeker_t : public pdb_access_t::children_visitor_t +{ + funcarg_t thisarg; + til_builder_t *tb; + bool found; + virtual HRESULT visit_child(pdb_sym_t &sym) override + { + DWORD dwDataKind, locType; + if ( sym.get_dataKind(&dwDataKind) == S_OK + && dwDataKind == DataIsObjectPtr + && sym.get_locationType(&locType) == S_OK ) + { + tb->get_symbol_funcarg_info(&thisarg, sym, dwDataKind, locType, 0); + found = true; + return S_FALSE; // Stop enum. + } + return S_OK; + } + this_seeker_t(til_builder_t *_tb) : thisarg(), tb(_tb), found(false) {} +}; + +//---------------------------------------------------------------------------- +inline type_t get_sym_modifiers(pdb_sym_t &sym) +{ + type_t type_mod = 0; + BOOL sym_mod; + if ( sym.get_constType(&sym_mod) == S_OK && sym_mod ) + type_mod |= BTM_CONST; + if ( sym.get_volatileType(&sym_mod) == S_OK && sym_mod ) + type_mod |= BTM_VOLATILE; + return type_mod; +} + +//---------------------------------------------------------------------- +cvt_code_t til_builder_t::really_convert_type( + tpinfo_t *out, + pdb_sym_t &sym, + pdb_sym_t *parent, + DWORD tag) +{ + // retrieve type modifiers + type_t mods = get_sym_modifiers(sym); + + DWORD64 size = 0; + sym.get_length(&size); + DWORD bt, count; + cvt_code_t code = cvt_ok; + switch ( tag ) + { + default: + case SymTagNull: + deb(IDA_DEBUG_DBGINFO, "PDB: unsupported tag %s\n", symtag_to_string(tag)); + code = cvt_failed; + break; + + case SymTagBaseType: + if ( sym.get_baseType(&bt) != S_OK ) + code = cvt_failed; + else + code = convert_basetype(out, bt, int(size)); + break; + + case SymTagPointerType: + { + tpinfo_t obj; + if ( !get_symbol_type(&obj, sym, NULL) ) + { + code = cvt_failed; + break; + } + tinfo_t tif; + tif.create_ptr(obj.type); + int s2 = tif.get_size(); + if ( size != s2 ) + { + if ( size == 4 || size == 8 ) + { // use __ptr32 or __ptr64 + ptr_type_data_t pi; + pi.obj_type = obj.type; + pi.taptr_bits = size == 4 ? TAPTR_PTR32 : TAPTR_PTR64; + tif.create_ptr(pi); + } + else + { // revert to int + type_t inttype = get_scalar_bt(size); + if ( inttype == BT_UNK ) + { + code = cvt_failed; + break; + } + tif = tinfo_t(inttype); + } + } + out->type.swap(tif); + } + break; + + case SymTagArrayType: + { + tpinfo_t el; + if ( !get_symbol_type(&el, sym, NULL) ) + { +FAILED_ARRAY: + code = cvt_failed; + break; + } + if ( sym.get_count(&count) != S_OK ) + goto FAILED_ARRAY; + mods |= el.type.get_modifiers(); // propagate element type to array + if ( !out->type.create_array(el.type, count) ) + goto FAILED_ARRAY; + } + break; + + case SymTagFunctionType: + { + tpinfo_t itp2; + if ( !get_symbol_type(&itp2, sym, NULL) ) // return type + { + code = cvt_failed; + break; + } + func_type_data_t fi; + fi.rettype = itp2.type; + if ( fi.rettype.is_array() ) + { + code = cvt_failed; // arrays cannot be returned + break; + } + DWORD cc0; + fi.cc = CM_CC_UNKNOWN; + if ( sym.get_callingConvention(&cc0) == S_OK ) + fi.cc = convert_cc(cc0); + + if ( get_cc(fi.cc) != CM_CC_VOIDARG ) + { + retrieve_arguments(sym, fi, parent); + // if arg has unknown/invalid argument => convert to ellipsis + for ( func_type_data_t::iterator i = fi.begin(); i != fi.end(); i++ ) + { + if ( i->type.empty() ) + { + // If the CC is cdecl, empty arguments represent an ellipsis. + // Otherwise, it's likely to be a C-type function + // with unknown number of arguments, such as 'foo()' + // (as opposed to 'foo(void)'), and which might not have a cdecl + // calling convention. E.g., pc_win32_appcall.pe's 'FARPROC': + // "int (FAR WINAPI * FARPROC) ()", which is a stdcall. + cm_t cc = get_cc(fi.cc); + if ( cc == CM_CC_CDECL || inf_is_64bit() && cc == CM_CC_FASTCALL ) + fi.cc = CM_CC_ELLIPSIS; + // remove the ellipsis and any trailing arguments + fi.erase(i, fi.end()); + break; + } + } + // is there an implicit "result" pointer passed? + if ( is_complex_return(sym) ) + { + // complex return type: what's returned is actually a pointer + fi.rettype.create_ptr(fi.rettype); + funcarg_t retarg; + retarg.type = fi.rettype; + retarg.name = "result"; + fi.insert(fi.begin(), retarg); + } + // is there an implicit "this" passed? + // N.B.: 'this' is passed before the implicit result, if both are present + tinfo_t class_type; + if ( is_member_func(&class_type, sym, parent) ) + { + class_type.create_ptr(class_type); + funcarg_t thisarg; + thisarg.type = class_type; + thisarg.name = "this"; + // due to MSDIA error sometimes it is failed to answer correctly + // for the get_isStatic() request (S_FALSE). + // So we need to check does 'this' pointer present in the function parameters. + bool add_this = true; + if ( parent != NULL ) + { + this_seeker_t ts(this); + pdb_access->iterate_children(*parent, SymTagData, ts); + thisarg.argloc = ts.thisarg.argloc; + if ( thisarg.argloc.is_stkoff() ) + { // shift the remaining stkargs + int delta = thisarg.type.get_size(); + for ( int i=0; i < fi.size(); i++ ) + { + funcarg_t &fa = fi[i]; + if ( fa.argloc.is_stkoff() ) + fa.argloc.set_stkoff(fa.argloc.stkoff()+delta); + } + } + add_this = ts.found; + } + if ( add_this ) + fi.insert(fi.begin(), thisarg); + } + if ( is_user_cc(fi.cc) ) + { + // specify argloc for the return value + size_t retsize = fi.rettype.get_size(); + if ( retsize <= 1 ) + fi.retloc._set_reg1(R_al); + else if ( retsize <= 4 ) + fi.retloc._set_reg1(R_ax); + else + fi.retloc._set_reg2(R_ax, R_dx); + + // __usercall must have all its arguments location + // specified. + // It happens that some PDB information, + // generated at compile-time, does _not_ hold info + // about all the parameters. For example, + // a function declared as: + // void BlockOpVPSDec(char *p, uint32 dwLength, char btXorKey, char /*foo*/) + // will end up having only its first three arguments + // properly defined in the PDB (because the fourth is + // not used, its location is not defined.) + // Still, in order for 'build_func_type2()' to work, + // it requires all valid argloc_t instances. Thus, + // we remove invalid ones completely. + for ( int i = fi.size() - 1; i >= 0; --i ) + if ( fi[i].argloc.is_badloc() ) + fi.erase(fi.begin() + i); + } + out->type.create_func(fi); + } + } + break; + + case SymTagUDT: + case SymTagBaseClass: + code = convert_udt(&out->type, sym, size); + break; + case SymTagEnum: + { + struct name_value_collector_t : public pdb_access_t::children_visitor_t + { + const til_builder_t *tb; + enum_type_data_t ei; + const type_t *idatype; + HRESULT visit_child(pdb_sym_t &child) override + { + enum_member_t &em = ei.push_back(); + child.get_name(&em.name); + em.value = tb->get_variant_long_value(child); + if ( em.name.empty() + || get_named_type(tb->ti, em.name.c_str(), NTF_SYMM, &idatype) == 1 ) + { + return E_FAIL; + } + return S_OK; + } + name_value_collector_t(const til_builder_t *_tb) + : tb(_tb), idatype(NULL) {} + }; + name_value_collector_t nvc(this); + if ( size != 0 && size <= 64 ) + { + int bte_size = log2ceil(size) + 1; + nvc.ei.bte |= bte_size & BTE_SIZE_MASK; + } + HRESULT hr = pdb_access->iterate_children(sym, SymTagNull, nvc); + if ( FAILED(hr) ) + { // symbol already exists or + // corrupted name or + // iterate_children failed to read any child + if ( nvc.ei.empty() || nvc.ei.back().name.empty() ) + { + code = cvt_failed; + break; + } + // just reuse the existing enum + if ( !out->type.deserialize(ti, &nvc.idatype) ) // this is not quite correct + INTERR(30407); + qstring n1; + if ( out->type.get_type_name(&n1) ) + { + qstring nm; + get_symbol_name(sym, nm); + if ( nm == n1 ) + code = cvt_typedef; // avoid circular dependencies + } + } + else + { + out->type.create_enum(nvc.ei); + } + } + break; + + case SymTagTypedef: + case SymTagFunctionArgType: + case SymTagFunction: + case SymTagData: + if ( !get_symbol_type(out, sym, NULL) ) + code = cvt_failed; + else if ( out->type.is_decl_typedef() ) + code = cvt_typedef; // signal that this is a typedef + break; + + case SymTagVTable: + if ( parent == NULL || make_vtable_struct(&out->type, *parent) != cvt_ok ) + out->type.create_typedef(ti, fake_vtable_type); + break; + } + if ( code != cvt_failed && mods != 0 ) + out->type.set_modifiers(mods); + // todo: check that the type has the expected size + return code; +} + +//---------------------------------------------------------------------- +cvt_code_t til_builder_t::convert_type( + tpinfo_t *out, + pdb_sym_t &sym, + pdb_sym_t *parent, + DWORD type, + DWORD tag) +{ + if ( level == 500 ) + { + deb(IDA_DEBUG_DBGINFO, "PDB: the maximum recursion level was reached\n"); + return cvt_failed; + } + ddeb(("PDEB: convert_type tag %d sym_id %d\n", tag, type)); + level++; + typemap_t::iterator p = typemap.find(type); + if ( p == typemap.end() ) + { + tpinfo_t tpi; + tpi.cvt_code = really_convert_type(&tpi, sym, parent, tag); + p = typemap.insert(std::make_pair(type, tpi)).first; + } + tpinfo_t &tpi = p->second; + *out = tpi; + level--; + return tpi.cvt_code; +} + +//---------------------------------------------------------------------- +bool til_builder_t::begin_creation(DWORD tag, const qstring &name, uint32 *p_id) +{ + if ( tag != SymTagFunction ) + { + uint32 id = *p_id; + creating_t::iterator c = creating.find(name); + if ( c != creating.end() ) // recursive call + { + if ( !c->second ) // allocated? + { + if ( id == 0 ) + id = alloc_type_ordinal(ti); // have to create the type id immediately + c->second = id; + QASSERT(490, id != 0); +// msg("%d %s: prematurely mapped to %d\n", type, name.c_str(), c->second); + } + *p_id = c->second; + return false; + } + creating.insert(std::make_pair(name, id)); // add to the 'creating' list + } + return true; +} + +//---------------------------------------------------------------------------- +uint32 til_builder_t::end_creation(const qstring &name) +{ + uint32 id = 0; + creating_t::iterator c = creating.find(name); + if ( c != creating.end() ) + { + id = c->second; + creating.erase(c); + } + if ( id == 0 ) + { + id = alloc_type_ordinal(ti); // have to create the type id immediately + QASSERT(491, id != 0); +// msg("%d %s: mapped to %d\n", type, name.c_str(), id); + } + return id; +} + + +//---------------------------------------------------------------------------- +cvt_code_t til_builder_t::handle_overlapping_members(pdb_udt_type_data_t *udt) const +{ + qstack<qstring> union_names; + pdb_udt_type_data_t::iterator end = udt->end(); + pdb_udt_type_data_t::iterator first = end; // !=end => collecting union members + pdb_udt_type_data_t::iterator last = end; // member with highest ending offset so far + for ( pdb_udt_type_data_t::iterator p=udt->begin(); ; ++p ) + { + if ( p != udt->end() ) + { + if ( is_unnamed_tag_typedef(p->type) ) + handle_unnamed_overlapping_member(udt, &union_names, &p->name); + if ( last == end ) + { + last = p; + continue; + } + if ( last->end() > p->begin() ) + { // found an overlap. however, we ignore base classes, in order + // not to convert them into unions + if ( first == end && !last->is_baseclass() ) + first = last; + goto NEXT; + } + } + if ( first != end ) + { + int fidx = first - udt->begin(); + uval_t off = first->offset; + // if we have a bitfield, include the adjacent bitfields in the new type + int bf_typesize = 0; + for ( pdb_udt_type_data_t::iterator q=first; q != p; ++q ) + { + if ( q->is_bitfield() ) + { + bf_typesize = q->type.get_size(); + break; + } + } + if ( bf_typesize != 0 ) + { + while ( fidx > 0 + && (first-1)->is_bitfield() + && (first-1)->type.get_size() == bf_typesize ) + { + --fidx; + --first; + off = first->offset; + } + while ( p != end + && p->is_bitfield() + && p->type.get_size() == bf_typesize ) + { + ++p; + } + } + // range [first, p) is overlapping, create a new type for it + tinfo_t unitif; + size_t union_size; + cvt_code_t code = create_union(&unitif, &union_size, first, p); + if ( code != cvt_ok ) + return code; + udt->erase(first+1, p); + end = udt->end(); + first = end; + last = end; + p = udt->begin() + fidx; + p->offset = off & ~7; + p->size = uint64(union_size) * 8; + if ( union_names.empty() ) + p->name.sprnt("___u%d", fidx); + else + p->name = union_names.pop(); + p->type = unitif; + } + if ( p == end ) + break; +NEXT: + if ( last->end() < p->end() ) + last = p; + } + return cvt_ok; +} + + +//---------------------------------------------------------------------------- +void til_builder_t::handle_function_type(pdb_sym_t &fun_sym, ea_t ea) +{ + struct local_data_creator_t : public pdb_access_t::children_visitor_t + { + virtual HRESULT visit_child(pdb_sym_t &sym) override + { + DWORD tag = 0; + HRESULT hr = sym.get_symTag(&tag); + if ( FAILED(hr) ) + return hr; + + switch ( tag ) + { + case SymTagBlock: // nested blocks + return tb->pdb_access->iterate_children(sym, SymTagNull, *this); + case SymTagFuncDebugStart: + case SymTagFuncDebugEnd: + return S_OK; // ignore these for the moment + } + + DWORD loc_type; + if ( sym.get_locationType(&loc_type) != S_OK ) + return S_OK; // optimized away? + + return tb->handle_function_child(fun_sym, ea, sym, tag, loc_type); + } + local_data_creator_t(til_builder_t *_tb, pdb_sym_t &_fun_sym, ea_t _ea) : + tb(_tb), fun_sym(_fun_sym), ea(_ea) {} + til_builder_t *tb; + pdb_sym_t &fun_sym; + ea_t ea; + }; + local_data_creator_t ldc(this, fun_sym, ea); + pdb_access->iterate_children(fun_sym, SymTagNull, ldc); +} + + +//---------------------------------------------------------------------------- +void til_builder_t::type_created( + ea_t /*ea*/, + int /*id*/, + const char * /*name*/, + const tinfo_t & /*ptr*/) const +{ +} + + +//---------------------------------------------------------------------------- +HRESULT til_builder_t::handle_function_child( + pdb_sym_t & /*fun_sym*/, + ea_t ea, + pdb_sym_t &child_sym, + DWORD child_tag, + DWORD child_loc_type) +{ + switch ( child_loc_type ) + { + case LocIsConstant: + break; // we ignore function level constants + + case LocIsStatic: + case LocIsTLS: // not tested + handle_symbol(child_sym); + break; + + case LocIsEnregistered: + case LocIsRegRel: + break; + + default: + ask_for_feedback("pdb: unsupported location type %d, tag %d at %a", child_loc_type, child_tag, ea); + break; + } + return S_OK; +} + + +//---------------------------------------------------------------------------- +cvt_code_t til_builder_t::create_udt_ref(tinfo_t *out, pdb_udt_type_data_t *udt, int udt_kind) const +{ + tinfo_t tif; + cvt_code_t code = create_udt(&tif, udt, udt_kind, nullptr); + if ( code != cvt_ok ) + return code; + + qtype type, fields; + tif.serialize(&type, &fields); + + qstring name; + build_anon_type_name(&name, type.begin(), fields.begin()); + uint32 id = get_type_ordinal(ti, name.c_str()); + if ( id == 0 ) + { + id = alloc_type_ordinal(ti); + if ( set_numbered_type(ti, id, NTF_NOBASE|NTF_FIXNAME, name.c_str(), type.begin(), fields.begin()) != TERR_OK ) + return cvt_failed; + type_created(BADADDR, id, NULL, tif); + } + + out->create_typedef(ti, id); + return cvt_ok; +} + +//---------------------------------------------------------------------------- +bool til_builder_t::retrieve_type( + tpinfo_t *out, + pdb_sym_t &sym, + pdb_sym_t *parent, + int *p_id) +{ + if ( p_id != NULL ) + *p_id = -1; + + // id -> unknown typedef? + DWORD sym_id = 0; + sym.get_symIndexId(&sym_id); + tpdefs_t::iterator q = tpdefs.find(sym_id); + if ( q != tpdefs.end() ) + { + out->type = q->second; + return true; + } + + DWORD tag = 0; + HRESULT hr = sym.get_symTag(&tag); + if ( FAILED(hr) ) + return false; + + qstring ns; + bool is_unnamed = get_symbol_name(sym, ns); + //msg("ID: %d -> %s\n", sym_id, ns.begin()); + uint32 id(0); + bool id_set = false; + if ( tag == SymTagVTable && ns.empty() ) + { + if ( parent != NULL ) + get_symbol_name(*parent, ns); + LONG offset = 0; + sym.get_offset(&offset); + get_vft_name(&ns, &id, ns.c_str(), offset); + + is_unnamed = false; + id_set = true; + } + + // udt fields and simple types are converted without allocating + // an ordinal number + if ( tag == SymTagData || ns.empty() ) + return convert_type(out, sym, parent, sym_id, tag) != cvt_failed; + + // give a unique name to unnamed types so they can be told apart + // this is a temporary name, it will be replaced by $hex.. + if ( is_unnamed ) + ns.sprnt("unnamed-%d", unnamed_idx++); + else + validate_name(&ns, VNT_TYPE); + + // some types can be defined multiple times. check if the name is already defined + bool defined_correctly = false; + bool defined_wrongly = false; + type_t tif_mod = 0; + if ( !id_set ) + id = get_type_ordinal(ti, ns.c_str()); + if ( id != 0 ) + { + tinfo_t tif; + tif.create_typedef(ti, id); + tif_mod = get_sym_modifiers(sym); + if ( tif.get_realtype() == BT_UNK ) + defined_wrongly = true; + else + defined_correctly = true; + } + if ( !defined_correctly ) + { + if ( begin_creation(tag, ns, &id) ) + { + // now convert the type information, recursive types won't bomb + tpinfo_t tpi2; + cvt_code_t cc = convert_type(&tpi2, sym, parent, sym_id, tag); + if ( cc != cvt_ok ) // failed or typedef + { + creating.erase(ns); + if ( cc == cvt_failed ) + return false; + // cvt_typedef + { + tinfo_t tif; + tif.create_typedef(ti, ns.c_str()); + tif.set_modifiers(tpi2.type.get_modifiers()); + tpdefs[sym_id] = tif; // reference to unknown typedef + } +RETT2: + out->type = tpi2.type; + return true; + } + + qtype type, fields; + if ( !tpi2.type.serialize(&type, &fields) ) + INTERR(30408); + + // Function types are saved as symbols + if ( tag == SymTagFunction ) + { + // the following may fail because of c++ overloaded functions + // do not check the error code - we cannot help it + tpi2.type.set_symbol_type(ti, ns.c_str(), NTF_SYMM); + type_created(BADADDR, 0, ns.c_str(), tpi2.type); + goto RETT2; + } + + bool reuse_anon_type = false; + if ( is_unnamed ) // this type will be referenced, so create a name for it + { + build_anon_type_name(&ns, type.begin(), fields.begin()); + id = get_type_ordinal(ti, ns.c_str()); + if ( id != 0 ) // this type already exists, just reuse it + { + creating.erase(ns); + reuse_anon_type = true; + } + tif_mod = get_sym_modifiers(sym); + } + if ( !reuse_anon_type ) + { + id = end_creation(ns); + int ntf_flags = NTF_NOBASE|NTF_FIXNAME; + if ( defined_wrongly ) + ntf_flags |= NTF_REPLACE; + if ( set_numbered_type(ti, id, ntf_flags, + ns.empty() ? NULL : ns.c_str(), + type.begin(), + fields.begin()) != TERR_OK ) + { + return 0; + } + tif_mod = tpi2.type.get_modifiers(); + } + if ( is_unnamed ) + unnamed_types.insert(id); + // msg("%d: %s\n name: %s\n", id, tpi2.dstr(), ns.c_str()); + type_created(BADADDR, id, NULL, tpi2.type); + } + else + { // in case of recursive call we need to preserve modifiers + tif_mod = get_sym_modifiers(sym); + } + } + if ( p_id != NULL ) + *p_id = id; + out->type.create_typedef(ti, id); + if ( tif_mod != 0 ) + out->type.set_modifiers(tif_mod); + return true; +} + + +//---------------------------------------------------------------------------- +bool til_builder_t::handle_symbol_at_ea(pdb_sym_t &/*sym*/, DWORD /*tag*/, ea_t /*ea*/, qstring & /*name*/) +{ + return true; +} + + +//---------------------------------------------------------------------------- +HRESULT til_builder_t::handle_symbol(pdb_sym_t &sym) +{ + DWORD id; + HRESULT hr = sym.get_symIndexId(&id); + if ( FAILED(hr) ) + return hr; + + if ( handled.find(id) != handled.end() ) + return S_OK; + handled.insert(id); + + DWORD tag = 0; + hr = sym.get_symTag(&tag); + if ( FAILED(hr) ) + return hr; + + switch ( tag ) + { + case SymTagNull: + case SymTagExe: + case SymTagCompiland: + case SymTagCompilandEnv: + case SymTagCustom: + case SymTagCustomType: + case SymTagManagedType: + case SymTagUDT: + case SymTagEnum: + case SymTagFunctionType: + case SymTagPointerType: + case SymTagArrayType: + case SymTagBaseType: + case SymTagTypedef: + case SymTagBaseClass: + case SymTagFunctionArgType: + case SymTagUsingNamespace: + case SymTagVTableShape: + case SymTagDimension: + return S_OK; + case SymTagCompilandDetails: + { + DWORD backEndVer; + if ( is_intel386(pdb_access->get_machine_type()) && sym.get_backEndMajor(&backEndVer) == S_OK ) + enregistered_bug = backEndVer <= 13; + } + return S_OK; + // new tags for msdia140 + case SymTagCoffGroup: + return S_OK; + default: + break; + } + + DWORD off = 0; + hr = sym.get_relativeVirtualAddress(&off); + if ( hr == S_OK ) + { + ea_t ea = get_load_address() + off; + qstring name; + sym.get_name(&name); + handle_symbol_at_ea(sym, tag, ea, name); + } + return S_OK; +} + + +//---------------------------------------------------------------------- +// Each time we encounter a toplevel type/func/whatever, we want to make +// sure the UI has had a chance to refresh itself. +struct toplevel_children_visitor_t : public pdb_access_t::children_visitor_t +{ + virtual HRESULT visit_child(pdb_sym_t &sym) override + { + user_cancelled(); + return do_visit_child(sym); + } + + virtual HRESULT do_visit_child(pdb_sym_t &sym) = 0; +}; + +//------------------------------------------------------------------------- +struct symbol_handler_t : public toplevel_children_visitor_t +{ + virtual HRESULT do_visit_child(pdb_sym_t &sym) override + { + return tb->handle_symbol(sym); + } + symbol_handler_t(til_builder_t *_tb) : tb(_tb) {} + til_builder_t *tb; +}; + +//------------------------------------------------------------------------- +HRESULT til_builder_t::handle_symbols(pdb_sym_t &global_sym) +{ + symbol_handler_t cp(this); + HRESULT hr; + while ( true ) + { + hr = pdb_access->iterate_subtags(global_sym, SymTagNull, cp); + if ( FAILED(hr) ) + break; + if ( !iterate_symbols_once_more(global_sym) ) + break; + } + return hr; +} + +//------------------------------------------------------------------------- +HRESULT til_builder_t::handle_publics(pdb_sym_t &global_sym) +{ + symbol_handler_t cp(this); + return pdb_access->iterate_children(global_sym, SymTagPublicSymbol, cp); +} + +//------------------------------------------------------------------------- +HRESULT til_builder_t::handle_globals(pdb_sym_t &global_sym) +{ + symbol_handler_t cp(this); + return pdb_access->iterate_children(global_sym, SymTagData, cp); +} + + +//---------------------------------------------------------------------- +HRESULT til_builder_t::handle_types(pdb_sym_t &global_sym) +{ + struct type_importer_t : public toplevel_children_visitor_t + { + til_builder_t *tb; + int counter; + virtual HRESULT do_visit_child(pdb_sym_t &sym) override + { + tpinfo_t tpi; + if ( tb->retrieve_type(&tpi, sym, parent, NULL) ) + counter++; + return S_OK; + } + type_importer_t(til_builder_t *_tb) : tb(_tb), counter(0) {} + }; + type_importer_t timp(this); + HRESULT hr = pdb_access->iterate_children(global_sym, SymTagEnum, timp); + if ( hr == S_OK ) + hr = pdb_access->iterate_children(global_sym, SymTagUDT, timp); + if ( hr == S_OK ) + hr = pdb_access->iterate_children(global_sym, SymTagTypedef, timp); + msg("PDB: loaded %d type%s\n", timp.counter, timp.counter != 1 ? "s" : ""); + return hr; +} + + +//---------------------------------------------------------------------------- +HRESULT til_builder_t::before_iterating(pdb_sym_t &) +{ + return S_OK; +} + + +//---------------------------------------------------------------------------- +HRESULT til_builder_t::after_iterating(pdb_sym_t &) +{ + return S_OK; +} + +//---------------------------------------------------------------------------- +HRESULT til_builder_t::build(pdb_sym_t &global_sym) +{ + HRESULT hr = before_iterating(global_sym); + if ( hr == S_OK ) + hr = handle_types(global_sym); + if ( (pdb_access->pdbargs.flags & PDBFLG_ONLY_TYPES) == 0 ) + { + if ( hr == S_OK ) + hr = handle_symbols(global_sym); + if ( hr == S_OK ) + hr = handle_globals(global_sym); + // handle_globals() will set the type and undecorated name for globals, + // and handle_publics() will set the decorated name for public symbols. + // We want both the type (from handle_globals()) and the decorated symbol + // name (from handle_publics()), since that gives the user more information + // about the variable and enables FLIRT to match rulefuncs based on the + // symbol name. + // For example, @__security_check_cookie@4 is used as a rulefunc by FLIRT, + // and that won't match with the undecorated name __security_check_cookie. + // Therefore, handle_publics() must be called *after* handle_globals(). + if ( hr == S_OK ) + hr = handle_publics(global_sym); + } + if ( hr == S_OK ) + { + create_vftables(); + hr = after_iterating(global_sym); + } + return hr; +} diff --git a/idasdk76/plugins/pdb/tilbuild.hpp b/idasdk76/plugins/pdb/tilbuild.hpp new file mode 100644 index 0000000..f5e90e9 --- /dev/null +++ b/idasdk76/plugins/pdb/tilbuild.hpp @@ -0,0 +1,216 @@ +#pragma once + +//---------------------------------------------------------------------------- +enum cvt_code_t +{ + cvt_failed, + cvt_ok, + cvt_typedef // conversion resulted in a typedef to a named type +}; + +//---------------------------------------------------------------------------- +// PBD provides the offset of a bitfield inside a bitfield group. +// We subclass udt_member_t in order to keep that information separate from +// the 'offset' field. +struct pdb_udt_member_t : public udt_member_t +{ + uint32 bit_offset; ///< member offset in bits from start of bitfield group +}; +DECLARE_TYPE_AS_MOVABLE(pdb_udt_member_t); +typedef qvector<pdb_udt_member_t> pdbudtmembervec_t; ///< vector of pdb udt member objects + +//---------------------------------------------------------------------------- +// stripped-down version of udt_type_data_t with only the fields used by pdb. +struct pdb_udt_type_data_t : public pdbudtmembervec_t +{ + size_t total_size; ///< total structure size in bytes + uint32 taudt_bits; ///< TA... and TAUDT... bits + bool is_union; ///< is union or struct? + + pdb_udt_type_data_t(void) + : total_size(0), + taudt_bits(0), + is_union(false) + { + } + + void convert_to_tinfo_udt(udt_type_data_t *out); +}; +DECLARE_TYPE_AS_MOVABLE(pdb_udt_type_data_t); + +//---------------------------------------------------------------------------- +class til_builder_t +{ +protected: + pdb_ctx_t &pv; +public: + + //---------------------------------------------------------------------------- + struct tpinfo_t + { + cvt_code_t cvt_code; + bool is_notype; + tinfo_t type; + til_t *ti; // FIXME: do we need this? + tpinfo_t(void) : cvt_code(cvt_ok), is_notype(false), ti(NULL) {} + tpinfo_t(til_t *_ti, const tinfo_t &t) : cvt_code(cvt_ok), is_notype(false), type(t), ti(_ti) {} + const char *dstr(void) const + { + if ( cvt_code == cvt_failed ) + return "#cvt_failed"; + + static qstring res; + if ( !type.print(&res) ) + res = "#print_failed"; + return res.c_str(); + } + }; + + //---------------------------------------------------------------------------- + til_builder_t(pdb_ctx_t &_pv, til_t *_ti, pdb_access_t *_pa) + : pv(_pv), + unnamed_idx(0), + level(0), + ti(_ti), + pdb_access(NULL), + enregistered_bug(false) + { + set_pdb_access(_pa); + } + + virtual ~til_builder_t() + { + typemap.clear(); + tpdefs.clear(); + handled.clear(); + creating.clear(); + unnamed_types.clear(); + } + + void set_pdb_access(pdb_access_t *_pdb_access) + { + pdb_access = _pdb_access; + } + + typedef std::map<DWORD, tpinfo_t> typemap_t; + typedef std::map<DWORD, tinfo_t> tpdefs_t; + typedef std::set<DWORD> idset_t; + typedef std::map<qstring, int> creating_t; + typedef std::set<uint32> unnamed_t; + + struct vft_info_t + { + udt_type_data_t udt; // collected vft members + qstring base0; // base vftable at offset 0 + + vft_info_t() { udt.taudt_bits |= TAUDT_VFTABLE; } + bool empty() const { return udt.empty() && base0.empty(); } + }; + typedef std::map<qstring, vft_info_t> vftmap_t; + + // remove `anonymous-namespace':: + // also remove `anonymous namespace':: + void remove_anonymous_namespaces(qstring &storage); + + bool get_symbol_type(tpinfo_t *out, pdb_sym_t &sym, int *p_id); + bool retrieve_type(tpinfo_t *out, pdb_sym_t &sym, pdb_sym_t *parent, int *p_id); + bool retrieve_arguments( + pdb_sym_t &sym, + func_type_data_t &fi, + pdb_sym_t *funcSym); + cm_t convert_cc(DWORD cc0) const; + bool get_variant_string_value(qstring *out, pdb_sym_t &sym) const; + uint32 get_variant_long_value(pdb_sym_t &sym) const; + bool begin_creation(DWORD tag, const qstring &name, uint32 *p_id); + uint32 end_creation(const qstring &name); + bool is_member_func(tinfo_t *class_type, pdb_sym_t &typeSym, pdb_sym_t *funcSym); + bool is_frame_reg(int regnum) const; + bool is_complex_return(pdb_sym_t &sym) const; + bool is_unnamed_tag_typedef(const tinfo_t &tif) const; + bool is_intel386(DWORD machine_type) const; + bool is_arm(DWORD machine_type) const; + int get_symbol_funcarg_info( + funcarg_t *out, + pdb_sym_t &sym, + DWORD /*dwDataKind*/, + DWORD locType, + int stack_off); + void enum_function_args(pdb_sym_t &sym, func_type_data_t &args); + cvt_code_t verify_struct(pdb_udt_type_data_t &udt) const; + cvt_code_t verify_union( + pdb_udt_type_data_t *out, + pdb_udt_type_data_t::iterator p1, + pdb_udt_type_data_t::const_iterator p2) const; + cvt_code_t create_union( + tinfo_t *out, + size_t *p_total_size, + pdb_udt_type_data_t::iterator p1, + pdb_udt_type_data_t::const_iterator p2) const; + cvt_code_t convert_basetype(tpinfo_t *out, DWORD baseType, int size) const; + cvt_code_t make_vtable_struct(tinfo_t *out, pdb_sym_t &sym); + cvt_code_t convert_udt(tinfo_t *out, pdb_sym_t &sym, DWORD64 size); + cvt_code_t create_udt(tinfo_t *out, pdb_udt_type_data_t *udt, int udtKind, const char *udt_name) const; + cvt_code_t create_udt_ref(tinfo_t *out, pdb_udt_type_data_t *udt, int udt_kind) const; + cvt_code_t really_convert_type(tpinfo_t *out, pdb_sym_t &sym, pdb_sym_t *parent, DWORD tag); + cvt_code_t convert_type( + tpinfo_t *out, + pdb_sym_t &sym, + pdb_sym_t *parent, + DWORD type, + DWORD tag); + cvt_code_t handle_overlapping_members(pdb_udt_type_data_t *udt) const; + // Will iterate on children, and call handle_function_child() + HRESULT handle_symbols(pdb_sym_t &pGlobal); + HRESULT handle_globals(pdb_sym_t &pGlobal); + HRESULT handle_publics(pdb_sym_t &pGlobal); + HRESULT handle_types(pdb_sym_t &pGlobal); + HRESULT build(pdb_sym_t &pGlobal); + ea_t get_load_address() const { return pdb_access->get_base_address(); } + HRESULT handle_symbol(pdb_sym_t &sym); + size_t get_symbol_type_length(pdb_sym_t &sym) const; + void create_vftables(); + // check for MS or IDA vftable name, + // get type ordinal of vftable + // returns the type is creating + bool get_vft_name(qstring *vft_name, uint32 *ord, const char *udt_name, uint32_t offset=0); + + virtual HRESULT before_iterating(pdb_sym_t &global_sym); + virtual HRESULT after_iterating(pdb_sym_t &global_sym); + virtual bool iterate_symbols_once_more(pdb_sym_t & /*global_sym*/) { return false; } + virtual bool get_symbol_name(pdb_sym_t &sym, qstring &storage); + virtual bool handle_symbol_at_ea( + pdb_sym_t &sym, + DWORD tag, + ea_t ea, + qstring &name); + virtual void type_created(ea_t /*ea*/, int /*id*/, const char * /*name*/, const tinfo_t & /*ptr*/) const; + virtual void handle_function_type(pdb_sym_t &fun_sym, ea_t ea); + virtual HRESULT handle_function_child( + pdb_sym_t &fun_sym, + ea_t ea, + pdb_sym_t &child_sym, + DWORD child_tag, + DWORD child_loc_type); + virtual cvt_code_t handle_unnamed_overlapping_member( + pdb_udt_type_data_t * /*udt*/, + qstack<qstring> * /*union_names*/, + qstring * /*name*/) const + { + return cvt_ok; + } + +protected: + typemap_t typemap; // id -> type info + tpdefs_t tpdefs; // id -> enum type defined in base til + idset_t handled; // set of handled symbols + creating_t creating; + unnamed_t unnamed_types; + vftmap_t vftmap; // vftable name -> vft info + int unnamed_idx; + int level; + +public: + til_t *ti; + pdb_access_t *pdb_access; + bool enregistered_bug; +}; diff --git a/idasdk75/plugins/pdb/varser.hpp b/idasdk76/plugins/pdb/varser.hpp similarity index 100% rename from idasdk75/plugins/pdb/varser.hpp rename to idasdk76/plugins/pdb/varser.hpp diff --git a/idasdk76/plugins/plugin.mak b/idasdk76/plugins/plugin.mak new file mode 100644 index 0000000..52953ab --- /dev/null +++ b/idasdk76/plugins/plugin.mak @@ -0,0 +1,21 @@ + +__FUZZ_PLUGINS__=1 + +SRC_PATH = $(IDA)plugins/ +ifdef EXAMPLE + BIN_PATH = $(R)plugins-examples/ +else + BIN_PATH = $(R)plugins/ +endif + +ifndef NO_DEFAULT_TARGETS + BASE_OBJS += $(F)$(PROC)$(O) +endif + +include ../../module.mak + +ifdef __NT__ + ifndef NDEBUG + $(MODULES): PDBFLAGS = /PDB:$(@:$(DLLEXT)=.pdb) + endif +endif diff --git a/idasdk76/plugins/procext/makefile b/idasdk76/plugins/procext/makefile new file mode 100644 index 0000000..c790bd9 --- /dev/null +++ b/idasdk76/plugins/procext/makefile @@ -0,0 +1,12 @@ +PROC=nec + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)nec$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + nec.cpp diff --git a/idasdk76/plugins/procext/nec.cpp b/idasdk76/plugins/procext/nec.cpp new file mode 100644 index 0000000..1a3ed6f --- /dev/null +++ b/idasdk76/plugins/procext/nec.cpp @@ -0,0 +1,317 @@ +/* + * This is a sample plugin module + * It extends the IBM PC processor module to disassemble some NEC V20 instructions + * This is a sample file, it supports just two instructions! + * + */ + +#include <ida.hpp> +#include <idp.hpp> +#include <bytes.hpp> +#include <loader.hpp> +#include <kernwin.hpp> + +int data_id; + +//-------------------------------------------------------------------------- +// Context data for the plugin. This object is created by the init() +// function and hold all local data. +struct plugin_ctx_t : public plugmod_t, public event_listener_t +{ + ea_t ea = 0; // current address within the instruction + + netnode nec_node; + bool hooked = false; + + plugin_ctx_t(); + ~plugin_ctx_t(); + + // This function is called when the user invokes the plugin. + virtual bool idaapi run(size_t) override; + // This function is called upon some events. + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; + + size_t ana(insn_t &insn); + void process_rm(insn_t &insn, op_t &x, uchar postbyte); +}; + +static const char node_name[] = "$ sample NEC processor extender parameters"; + + +// Some definitions from IBM PC: + +#define segrg specval_shorts.high // IBM PC expects the segment address + // to be here +#define aux_short 0x0020 // short (byte) displacement used +#define aux_basess 0x0200 // SS based instruction + +#define R_ss 18 +#define R_ds 19 +//-------------------------------------------------------------------------- +// This plugin supports just 2 instructions: +// Feel free to add more... + +// 0FH 20H ADD4S ; Addition for packed BCD strings +// 0FH 12H Postbyte CLEAR1 reg/mem8,CL ; Clear one bit + +enum nec_insn_type_t +{ + NEC_add4s = CUSTOM_INSN_ITYPE, + NEC_clear1, +}; + +//---------------------------------------------------------------------- +static int get_dataseg(insn_t &insn, int defseg) +{ + if ( defseg == R_ss ) + insn.auxpref |= aux_basess; + return defseg; +} + +//-------------------------------------------------------------------------- +// +// process r/m byte of the instruction +// +void plugin_ctx_t::process_rm(insn_t &insn, op_t &x, uchar postbyte) +{ + int Mod = (postbyte >> 6) & 3; + x.reg = postbyte & 7; + if ( Mod == 3 ) // register + { + if ( x.dtype == dt_byte ) + x.reg += 8; + x.type = o_reg; + } + else // memory + { + if ( Mod == 0 && x.reg == 6 ) + { + x.type = o_mem; + x.offb = uchar(ea-insn.ea); + x.addr = get_word(ea); ea+=2; + x.segrg = (uint16)get_dataseg(insn, R_ds); + } + else + { + x.type = o_phrase; // x.phrase contains the base register + x.addr = 0; + int reg = (x.phrase == 2 || x.phrase == 3 || x.phrase == 6) ? R_ss : R_ds; + x.segrg = (uint16)get_dataseg(insn, reg); + // [bp+si],[bp+di],[bp] by SS + if ( Mod != 0 ) + { + x.type = o_displ; // i.e. phrase + offset + x.offb = uchar(ea-insn.ea); + if ( Mod == 1 ) + { + x.addr = char(get_byte(ea++)); + insn.auxpref |= aux_short; + } + else + { + x.addr = get_word(ea); ea+=2; + } + } + } + } +} + +//-------------------------------------------------------------------------- +// Analyze an instruction and fill the 'insn' structure +size_t plugin_ctx_t::ana(insn_t &insn) +{ + int code = get_byte(ea++); + if ( code != 0x0F ) + return 0; + code = get_byte(ea++); + switch ( code ) + { + case 0x20: + insn.itype = NEC_add4s; + return 2; + case 0x12: + insn.itype = NEC_clear1; + { + uchar postbyte = get_byte(ea++); + process_rm(insn, insn.Op1, postbyte); + insn.Op2.type = o_reg; + insn.Op2.reg = 9; // 9 is CL for IBM PC + return size_t(ea - insn.ea); + } + default: + return 0; + } +} + +//-------------------------------------------------------------------------- +// Return the instruction mnemonics +const char *get_insn_mnem(const insn_t &insn) +{ + if ( insn.itype == NEC_add4s ) + return "add4s"; + return "clear1"; +} + +//-------------------------------------------------------------------------- +// This function can be hooked to various kernel events. +// In this particular plugin we hook to the HT_IDP group. +// As soon the kernel needs to decode and print an instruction, it will +// generate some events that we intercept and provide our own response. +// +// We extend the processor module to disassemble opcode 0x0F +// (This is a hypothetical example) +// There are 2 different possible approaches for the processor extensions: +// A. Quick & dirty +// Implement reaction to ev_ana_insn and ev_out_insn. +// The first checks if the instruction is valid. +// The second generates its text. +// B. Thourough and clean +// Implement all relevant callbacks. +// ev_ana_insn fills the 'insn' structure. +// ev_emu_insn creates all xrefs using ua_add_[cd]ref functions. +// ev_out_insn generates the textual representation of the instruction. +// It is required only if the instruction requires special processing +// or the processor module cannot handle the custom instruction for +// any reason. +// ev_out_operand generates the operand representation (only if the +// operand requires special processing). +// ev_out_mnem generates the instruction mnemonics. +// The main difference between these 2 approaches is in the creation of +// cross-references and the amount of special processing required by the +// new instructions. + +// The quick & dirty approach. +// We just produce the instruction mnemonics along with its operands. +// No cross-references are created. No special processing. +ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case processor_t::ev_ana_insn: + { + insn_t *insn = va_arg(va, insn_t *); + ea = insn->ea; + size_t length = ana(*insn); + if ( length ) + { + insn->size = (uint16)length; + return insn->size; // event processed + } + } + break; + case processor_t::ev_out_mnem: + { + outctx_t *ctx = va_arg(va, outctx_t *); + const insn_t &insn = ctx->insn; + if ( insn.itype >= CUSTOM_INSN_ITYPE ) + { + ctx->out_line(get_insn_mnem(insn), COLOR_INSN); + return 1; + } + } + break; + } + return 0; // event is not processed +} + +//-------------------------------------------------------------------------- +// Initialize the plugin. +// IDA will call this function only once. +// If this function returns nullptr, IDA will unload the plugin. +// Otherwise the plugin returns a pointer to a newly created context structure. +// +// In this example we check the processor type and make the decision. +// You may or may not check any other conditions to decide what you do: +// whether your plugin wants to work with the database or not. + +static plugmod_t *idaapi init() +{ + processor_t &ph = PH; + if ( ph.id != PLFM_386 ) + return nullptr; + auto plugmod = new plugin_ctx_t; + set_module_data(&data_id, plugmod); + return plugmod; +} + +//------------------------------------------------------------------------- +plugin_ctx_t::plugin_ctx_t() +{ + nec_node.create(node_name); + hooked = nec_node.altval(0) != 0; + if ( hooked ) + { + hook_event_listener(HT_IDP, this); + msg("NEC V20 processor extender is enabled\n"); + } +} + +//-------------------------------------------------------------------------- +// Terminate the plugin. +// This destructor will be called before unloading the plugin. +plugin_ctx_t::~plugin_ctx_t() +{ + clr_module_data(data_id); + // listeners are uninstalled automatically + // when the owner module is unloaded +} + +//-------------------------------------------------------------------------- +// The plugin method +// This is the main function of plugin. +// It will be called when the user selects the plugin from the menu. +// The input argument is usually zero. Non-zero values can be specified +// by using load_and_run_plugin() or through plugins.cfg file (discouraged). +bool idaapi plugin_ctx_t::run(size_t) +{ + if ( hooked ) + unhook_event_listener(HT_IDP, this); + else + hook_event_listener(HT_IDP, this); + hooked = !hooked; + nec_node.create(node_name); + nec_node.altset(0, hooked); + info("AUTOHIDE NONE\n" + "NEC V20 processor extender now is %s", hooked ? "enabled" : "disabled"); + return true; +} + +//-------------------------------------------------------------------------- +static const char comment[] = "NEC V20 processor extender"; +static const char help[] = + "A sample plugin module\n" + "\n" + "This module shows you how to create plugin modules.\n" + "\n" + "It supports some NEC V20 instructions\n" + "and shows the current address.\n"; + +//-------------------------------------------------------------------------- +// This is the preferred name of the plugin module in the menu system +// The preferred name may be overridden in plugins.cfg file + +static const char desired_name[] = "NEC V20 processor extender"; + +// This is the preferred hotkey for the plugin module +// The preferred hotkey may be overridden in plugins.cfg file + +static const char desired_hotkey[] = ""; + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_PROC // this is a processor extension plugin +| PLUGIN_MULTI, // this plugin can work with multiple idbs in parallel + init, // initialize + nullptr, + nullptr, + comment, // long comment about the plugin. not used. + help, // multiline help about the plugin. not used. + desired_name, // the preferred short name of the plugin + desired_hotkey // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/pyplg.mak b/idasdk76/plugins/pyplg.mak new file mode 100644 index 0000000..c486c7f --- /dev/null +++ b/idasdk76/plugins/pyplg.mak @@ -0,0 +1,26 @@ + +# definitions for idapython (& other plugins dynamically linked to Python) +ifdef __NT__ + PYTHON_CFLAGS := -I"$(PYTHON_ROOT)/include" + ifeq ($(PYTHON_VERSION_MAJOR),3) + PYTHON_LDFLAGS := "$(PYTHON_ROOT)/libs/python$(PYTHON_VERSION_MAJOR).lib" + else + PYTHON_LDFLAGS := "$(PYTHON_ROOT)/libs/python$(PYTHON_VERSION_MAJOR)$(PYTHON_VERSION_MINOR).lib" + endif +else + PYTHON_CFLAGS := $(shell $(PYTHON)-config --includes) + ifdef __APPLE_SILICON__ + # to avoid codesigning complications on arm64 macs, we link against a stub tbd file. see plugins/idapython/tbd.readme + PYTHON_LDFLAGS := -L$(R) -lpython$(PYTHON_VERSION_MAJOR) -ldl -framework CoreFoundation + else + # Yay! https://bugs.python.org/issue36721 + ifeq ($(PYTHON_VERSION_MAJOR),3) + USE_EMBED := $(shell [ $(PYTHON_VERSION_MINOR) -ge 8 ] && echo true) + endif + ifeq ($(USE_EMBED),true) + PYTHON_LDFLAGS := $(shell $(PYTHON)-config --ldflags --embed) + else + PYTHON_LDFLAGS := $(shell $(PYTHON)-config --ldflags) + endif + endif +endif diff --git a/idasdk75/plugins/qproject/edge.cpp b/idasdk76/plugins/qproject/edge.cpp similarity index 100% rename from idasdk75/plugins/qproject/edge.cpp rename to idasdk76/plugins/qproject/edge.cpp diff --git a/idasdk75/plugins/qproject/edge.h b/idasdk76/plugins/qproject/edge.h similarity index 100% rename from idasdk75/plugins/qproject/edge.h rename to idasdk76/plugins/qproject/edge.h diff --git a/idasdk75/plugins/qproject/graphwidget.cpp b/idasdk76/plugins/qproject/graphwidget.cpp similarity index 100% rename from idasdk75/plugins/qproject/graphwidget.cpp rename to idasdk76/plugins/qproject/graphwidget.cpp diff --git a/idasdk75/plugins/qproject/graphwidget.h b/idasdk76/plugins/qproject/graphwidget.h similarity index 100% rename from idasdk75/plugins/qproject/graphwidget.h rename to idasdk76/plugins/qproject/graphwidget.h diff --git a/idasdk75/plugins/qproject/makefile b/idasdk76/plugins/qproject/makefile similarity index 100% rename from idasdk75/plugins/qproject/makefile rename to idasdk76/plugins/qproject/makefile diff --git a/idasdk75/plugins/qproject/node.cpp b/idasdk76/plugins/qproject/node.cpp similarity index 100% rename from idasdk75/plugins/qproject/node.cpp rename to idasdk76/plugins/qproject/node.cpp diff --git a/idasdk75/plugins/qproject/node.h b/idasdk76/plugins/qproject/node.h similarity index 100% rename from idasdk75/plugins/qproject/node.h rename to idasdk76/plugins/qproject/node.h diff --git a/idasdk75/plugins/qproject/qproject.cpp b/idasdk76/plugins/qproject/qproject.cpp similarity index 100% rename from idasdk75/plugins/qproject/qproject.cpp rename to idasdk76/plugins/qproject/qproject.cpp diff --git a/idasdk75/plugins/qtplugin.mak b/idasdk76/plugins/qtplugin.mak similarity index 100% rename from idasdk75/plugins/qtplugin.mak rename to idasdk76/plugins/qtplugin.mak diff --git a/idasdk76/plugins/qwindow/makefile b/idasdk76/plugins/qwindow/makefile new file mode 100644 index 0000000..b8e514d --- /dev/null +++ b/idasdk76/plugins/qwindow/makefile @@ -0,0 +1,13 @@ +PROC=qwindow +O1=moc_myactions + +include ../qtplugin.mak + +# MAKEDEP dependency list ------------------ +$(F)moc_myactions$(O): $(F)moc_myactions.cpp myactions.h +$(F)qwindow$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + qwindow.cpp diff --git a/idasdk75/plugins/qwindow/myactions.h b/idasdk76/plugins/qwindow/myactions.h similarity index 100% rename from idasdk75/plugins/qwindow/myactions.h rename to idasdk76/plugins/qwindow/myactions.h diff --git a/idasdk75/plugins/qwindow/qwindow.cpp b/idasdk76/plugins/qwindow/qwindow.cpp similarity index 100% rename from idasdk75/plugins/qwindow/qwindow.cpp rename to idasdk76/plugins/qwindow/qwindow.cpp diff --git a/idasdk76/plugins/readme.txt b/idasdk76/plugins/readme.txt new file mode 100644 index 0000000..fbf073a --- /dev/null +++ b/idasdk76/plugins/readme.txt @@ -0,0 +1,34 @@ + + + This directory contains sample plugin modules for IDA. + + Plugin modules are accessible by the user in two ways: + + - they appear as menu items in menu Edit|Plugins + - they can be invoked by hotkeys + + A plugin has full access to the database and can interact with + the user. + + IDA looks for plugins in PLUGINS subdirectory. + In this directory there is also a configuration file. + It is not necessary for a plugin to appear in the configuration file. + Even if a plugin is not there IDA will load it. + The configuration file allows the user to reassign the hotkeys, + to change the plugin name as it appears in the menu or to change + the argument passed to the plugin. + + A plugin has one exported entry (it should have the "PLUGIN" name). + The entry is a plugin descriptor (plugin_t). + It contains pointers to the following functions: + + - init: is called when the plugin is loaded + - run: is called when the user calls the plugin + - term: is called before the plugin is unloaded + + run() function is the function which will do the real work. + It has full access to the database (see include files for the + description of IDA API). Also it can interact with the user + (most of these functions are in kernwin.hpp file). + + diff --git a/idasdk75/plugins/script_plg.mak b/idasdk76/plugins/script_plg.mak similarity index 100% rename from idasdk75/plugins/script_plg.mak rename to idasdk76/plugins/script_plg.mak diff --git a/idasdk75/plugins/script_plg/idcplugin.idc b/idasdk76/plugins/script_plg/idcplugin.idc similarity index 100% rename from idasdk75/plugins/script_plg/idcplugin.idc rename to idasdk76/plugins/script_plg/idcplugin.idc diff --git a/idasdk75/plugins/script_plg/makefile b/idasdk76/plugins/script_plg/makefile similarity index 100% rename from idasdk75/plugins/script_plg/makefile rename to idasdk76/plugins/script_plg/makefile diff --git a/idasdk75/plugins/script_plg/procext.py b/idasdk76/plugins/script_plg/procext.py similarity index 100% rename from idasdk75/plugins/script_plg/procext.py rename to idasdk76/plugins/script_plg/procext.py diff --git a/idasdk75/plugins/script_plg/pyplugin.py b/idasdk76/plugins/script_plg/pyplugin.py similarity index 100% rename from idasdk75/plugins/script_plg/pyplugin.py rename to idasdk76/plugins/script_plg/pyplugin.py diff --git a/idasdk76/plugins/snapshots/makefile b/idasdk76/plugins/snapshots/makefile new file mode 100644 index 0000000..03fc877 --- /dev/null +++ b/idasdk76/plugins/snapshots/makefile @@ -0,0 +1,11 @@ +PROC=snapshots + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)snapshots$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp \ + $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)range.hpp $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp \ + snapshots.cpp diff --git a/idasdk76/plugins/snapshots/snapshots.cpp b/idasdk76/plugins/snapshots/snapshots.cpp new file mode 100644 index 0000000..c8f6e14 --- /dev/null +++ b/idasdk76/plugins/snapshots/snapshots.cpp @@ -0,0 +1,269 @@ +/* +* This is a sample plugin to demonstrate the snapshot management API +*/ + +#include <ida.hpp> +#include <idp.hpp> +#include <loader.hpp> +#include <kernwin.hpp> + +//-------------------------------------------------------------------------- +class snapman_t : public chooser_t +{ + struct snapdesc_t + { + snapshot_t *ss; + qstring title; + qstring date; + }; + typedef qvector<snapdesc_t> sdlist_t; + snapshot_t root; + sdlist_t sdlist; + + static const int widths_[2]; + static const char *const header_[2]; + + static void idaapi done_restore(const char *err_msg, void *) + { + if ( err_msg != NULL ) + warning("ICON ERROR\nError restoring: %s", err_msg); + else + warning("Restored successfully!"); + } + + void build_tree_list(snapshot_t *n, int level = 0) + { + if ( n != &root ) + { + // Insert new description record + snapdesc_t &sd = sdlist.push_back(); + + // Compute title + for ( int i=0; i < level; i++ ) + sd.title += " "; + if ( n->id == root.id ) + sd.title += "->"; + sd.title += n->desc; + + // Compute date + char ss_date[MAXSTR]; + qstrftime64(ss_date, sizeof(ss_date), "%Y-%m-%d %H:%M:%S", n->id); + sd.date = ss_date; + // Store ss + sd.ss = n; + } + for ( snapshots_t::iterator it=n->children.begin(); it != n->children.end(); ++it ) + build_tree_list(*it, level+1); + } + + snapdesc_t *get_item(uint32 n) + { + return n >= sdlist.size() ? NULL : &sdlist[n]; + } + const snapdesc_t *get_item(uint32 n) const + { + return n >= sdlist.size() ? NULL : &sdlist[n]; + } + +public: + bool init() override + { + sdlist.clear(); + root.clear(); + if ( !build_snapshot_tree(&root) ) + { + warning("Snapshot tree cannot be built.\nNo snapshots exist?"); + return false; + } + + // Convert the tree to a list + build_tree_list(&root); + if ( sdlist.empty() ) + { + warning("Snapshot tree empty!"); + return false; + } + return true; + } + + snapman_t() + : chooser_t(CH_MODAL | CH_KEEP | CH_CAN_INS | CH_CAN_DEL | CH_CAN_EDIT, + qnumber(widths_), widths_, header_, + "Simple snapshot manager"), + root(), + sdlist() {} + + virtual size_t idaapi get_count() const override + { + return sdlist.size(); + } + + virtual void idaapi get_row( + qstrvec_t *cols_, + int *, + chooser_item_attrs_t *, + size_t n) const override + { + const snapdesc_t *sd = get_item(n); + QASSERT(561, sd != NULL); + + qstrvec_t &cols = *cols_; + cols[0] = sd->date; + cols[1] = sd->title; + } + + virtual cbret_t idaapi ins(ssize_t n) override + { + qstring desc = "snapshot description"; + if ( !ask_str(&desc, HIST_CMT, "Enter snapshot description") ) + return cbret_t(); // nothing changed + + qstring err_msg; + snapshot_t new_attr; + qstrncpy(new_attr.desc, desc.c_str(), sizeof(new_attr.desc)); + if ( !take_database_snapshot(&new_attr, &err_msg) ) + { + warning("Failed to create a snapshot, error: %s", err_msg.c_str()); + return cbret_t(); // nothing changed + } + msg("Created new snapshot: %s\n", new_attr.filename); + init(); + // we preserve the selection + // FIXME use get_item_index() + return n; + } + + virtual cbret_t idaapi del(size_t n) override + { + const snapdesc_t *sd = get_item(n); + if ( sd == NULL ) + return cbret_t(); + + // Simply delete the file + qunlink(sd->ss->filename); + + // Rebuild the list + init(); + + return adjust_last_item(n); // take in account deleting of the last item + } + + virtual cbret_t idaapi edit(size_t n) override + { + snapdesc_t *sd = get_item(n); + if ( sd == NULL ) + return cbret_t(); + + qstring desc = sd->ss->desc; + if ( !ask_str(&desc, HIST_CMT, "Enter new snapshot description") ) + return cbret_t(); + + // Update the description + qstrncpy(sd->ss->desc, desc.c_str(), sizeof(sd->ss->desc)); + update_snapshot_attributes(sd->ss->filename, &root, sd->ss, SSUF_DESC); + return n; + } + + // calculate the location of the default item only, + // `item_data` is a pointer to a snapshot ID + virtual ssize_t idaapi get_item_index(const void *item_data) const override + { + qtime64_t item_id = *(const qtime64_t *)item_data; + for ( size_t i = 0; i < sdlist.size(); ++i ) + { + if ( sdlist[i].ss->id == item_id ) + return i; + } + return NO_SELECTION; + } + + void show() + { + // now open the window + ssize_t n = ::choose(this, &root.id); + if ( n >= 0 ) + { + snapdesc_t *sd = get_item(n); + if ( sd != NULL && sd->ss != NULL ) + restore_database_snapshot(sd->ss, done_restore, NULL); + } + } +}; +DECLARE_TYPE_AS_MOVABLE(snapman_t::snapdesc_t); + +// column widths +const int snapman_t::widths_[2] = +{ + 12, // Date + 70, // Description +}; + +// column headers +const char *const snapman_t::header_[2] = +{ + "Date", // 0 + "Description", // 1 +}; + + +//-------------------------------------------------------------------------- +struct plugin_ctx_t : public plugmod_t +{ + virtual bool idaapi run(size_t) override; +}; + +//-------------------------------------------------------------------------- +bool idaapi plugin_ctx_t::run(size_t) +{ + snapman_t sm; + if ( !sm.init() ) + return false; + + sm.show(); + return true; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + // Display help + msg( + "Simple snapshot manager loaded!\n" + "Press Shift+F8 to toggle the plugin\n" + "Inside the snapshots window, press:\n" + " - Insert: to take a snapshot\n" + " - Delete: to delete\n" + " - Edit: to edit the snapshot description\n" + "\n" + "Click on:\n" + " - Ok: to restore the selected snapshot\n" + " - Cancel: close without doing anything\n"); + + // The plugin flags must include PLUGIN_FIX as well + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + // plugin flags + PLUGIN_FIX // Load plugin when IDA starts and keep it in the + // memory until IDA stops + | PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel + init, // initialize + nullptr, + nullptr, + "This is a sample plugin. It displays the list of snapshots", + // long comment about the plugin + "A snapshot manager sample plugin\n" + "\n" + "This plugin allows you to list and restore snapshots.\n", + // multiline help about the plugin + "Simple snapshot manager", // the preferred short name of the plugin + "Shift-F8", // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/tracer/makefile b/idasdk76/plugins/tracer/makefile new file mode 100644 index 0000000..5eba7b4 --- /dev/null +++ b/idasdk76/plugins/tracer/makefile @@ -0,0 +1,11 @@ +PROC=tracer + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)tracer$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp tracer.cpp diff --git a/idasdk75/plugins/tracer/tracer.cpp b/idasdk76/plugins/tracer/tracer.cpp similarity index 100% rename from idasdk75/plugins/tracer/tracer.cpp rename to idasdk76/plugins/tracer/tracer.cpp diff --git a/idasdk76/plugins/tracing_api/makefile b/idasdk76/plugins/tracing_api/makefile new file mode 100644 index 0000000..2bdbd94 --- /dev/null +++ b/idasdk76/plugins/tracing_api/makefile @@ -0,0 +1,11 @@ +PROC=tracing_api + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)tracing_api$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp tracing_api.cpp diff --git a/idasdk76/plugins/tracing_api/tracing_api.cpp b/idasdk76/plugins/tracing_api/tracing_api.cpp new file mode 100644 index 0000000..85fdc9c --- /dev/null +++ b/idasdk76/plugins/tracing_api/tracing_api.cpp @@ -0,0 +1,160 @@ +/* Tracing API sample plugin. + * + * Copyright (c) 2012-2021 Hex-Rays, support@hex-rays.com + * + * This sample plugin demonstrates how to use the tracing events API + * in IDA v6.3 + * + * The tracing events API allow you to record, save and load traces, + * find register values as well as memory pointed by registers. + * + * This sample plugin looks for an ASCII string in the recorded + * trace's memory + * + */ + +//--------------------------------------------------------------------------- +#include <idp.hpp> +#include <dbg.hpp> +#include <loader.hpp> + +//-------------------------------------------------------------------------- +struct plugin_ctx_t : public plugmod_t +{ + bytevec_t last_found; // last found buffer + + virtual bool idaapi run(size_t) override; + bool find_memory_tev(int i, const char *mem); +}; + +//-------------------------------------------------------------------------- +inline bool __memmem( + const unsigned char *where, + size_t size1, + const char *what, + size_t size2) +{ + if ( size2 > size1 ) + return false; + else if ( size2 == size1 ) + return memcmp(where, what, size1) == 0; + + int i = size1 - size2; + do + { + if ( where[i] == what[0] ) + { + if ( memcmp(where+i, what, size2) == 0 ) + return true; + } + } + while ( --i >= 0 ); + + return false; +} + +//-------------------------------------------------------------------------- +static void dump_memreg(const unsigned char *buf, size_t size) +{ + msg("Memory found: "); + for ( int i = 0; i < size; i++ ) + { + if ( isprint(buf[i]) ) + msg("%c", buf[i]); + else + msg("."); + } + msg("\n"); +} + +//-------------------------------------------------------------------------- +bool plugin_ctx_t::find_memory_tev(int i, const char *mem) +{ + // retrieve the memory map + memreg_infos_t memmap; + if ( get_insn_tev_reg_mem(i, &memmap) ) + { + // iterate over all elements in the map + memreg_infos_t::iterator p; + for ( p = memmap.begin(); p != memmap.end(); ++p ) + { + memreg_info_t reg = *p; + // compare the memory of this memreg_info_t object with the given + // string mem + if ( last_found != reg.bytes && __memmem(reg.bytes.begin(), reg.bytes.size(), mem, strlen(mem)) ) + { + last_found = reg.bytes; + // if found, print it to the output window + dump_memreg(reg.bytes.begin(), reg.bytes.size()); + return true; + } + } + } + return false; +} + +//-------------------------------------------------------------------------- +bool idaapi plugin_ctx_t::run(size_t) +{ + // clear the last found buffer + last_found.clear(); + + // get the number of recorded events + size_t total = get_tev_qty(); + if ( total == 0 ) + { + msg("No recorded events."); + return true; + } + + qstring mem_search; + if ( !ask_str(&mem_search, + HIST_SRCH, + "Enter the string to search in the recorded trace:") + || mem_search.empty() ) + { + return true; + } + + // iterate over all the recorded events + for ( int i = total; i != 0; i-- ) + { + // if the recorded event is an instruction trace event + // search the string mem_search in the recorded memory + tev_info_t tev; + if ( get_tev_info(i, &tev) && tev.type == tev_insn ) + { + // if the string is found in this instruction trace event's memory + // print the tev object address, thread and number if the output + // window + const char *str = mem_search.begin(); + if ( find_memory_tev(i, str) ) + msg("%a: tid %d: string '%s' found in tev %d.\n", tev.ea, tev.tid, str, i); + } + } + return true; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel + init, // initialize + nullptr, + nullptr, + "Search for a string in the recorded trace memory", // long comment about the plugin + "", // multiline help about the plugin + "Trace search", // the preferred short name of the plugin + "" // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/ugraph/makefile b/idasdk76/plugins/ugraph/makefile new file mode 100644 index 0000000..d135aca --- /dev/null +++ b/idasdk76/plugins/ugraph/makefile @@ -0,0 +1,11 @@ +PROC=ugraph + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ugraph$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ugraph.cpp diff --git a/idasdk76/plugins/ugraph/ugraph.cpp b/idasdk76/plugins/ugraph/ugraph.cpp new file mode 100644 index 0000000..08c5e19 --- /dev/null +++ b/idasdk76/plugins/ugraph/ugraph.cpp @@ -0,0 +1,778 @@ +/* + * This plugin demonstrates how one can create a graph viewer, and + * manipulate the graph that is being displayed (by adding nodes & + * edges.) + * + * To illustrate this functionality, we will be showing the a subset + * of the "family tree" of the elvish characters described in JRR + * Tolkien's "Lord of the rings" books. + * + * That "family tree" was found at: + * https://i.pinimg.com/originals/aa/36/0b/aa360b00a0f309f56e6b7f48ff92de2d.jpg + * and please note that we didn't check that it is actually correct + * since this is not exactly relevant to the functionality being + * showcased. + * We'll limit ourselves to 4 "generations" of characters, and provide + * the graph user the ability to show, or hide generations (thus + * modifying the underlying graph.) + * + * The following actions will be available in the graph's + * context menu: + * - change the layout type + * - show & hide generations + * - modify the character's name + * - modify the character name's background color + */ + +#include <ida.hpp> +#include <idp.hpp> +#include <graph.hpp> +#include <loader.hpp> +#include <kernwin.hpp> + +// +// Dramatis personae +// +#define Finarfin "Finarfin" +#define Earwen "Earwen" +#define Eldalote "Eldalote" +#define Finrod "Finrod" +#define Angrod "Angrod" +#define Aegnor "Aegnor" +#define Galadriel "Galadriel" +#define Celeborn "Celeborn" +#define Orodreth "Orodreth" +#define Unknown_name "Purple dress lady\n(name unknown)" +#define Celebrian "Celebrian" +#define Gil_Galad "Gil-Galad" +#define Finduilas "Finduilas" + +static const char *characters[] = +{ + // Generation 0 + Finarfin, Earwen, + + // Generation 1 + Eldalote, Finrod, Angrod, Aegnor, Galadriel, Celeborn, + + // Generation 2 + Orodreth, Unknown_name, Celebrian, + + // Generation 3 + Gil_Galad, Finduilas, +}; +static const size_t ncharacters = qnumber(characters); +static const size_t nlevels = 4; +static const size_t levels_offsets[] = +{ + 0, + 2, + 2 + 6, + 2 + 6 + 3, + 2 + 6 + 3 + 2, +}; +CASSERT(qnumber(levels_offsets) == nlevels+1); + +//------------------------------------------------------------------------- +static int character_to_node_number(const char *name) +{ + for ( size_t i = 0; i < ncharacters; ++i ) + if ( streq(characters[i], name) ) + return int(i); + INTERR(0); // This shouldn't happen +} + +//------------------------------------------------------------------------- +static const char *node_number_to_character(int n) +{ + QASSERT(0, n >= 0 && n < ncharacters); + return characters[n]; +} + +//------------------------------------------------------------------------- +// Relationship between the characters +struct parenthood_t +{ + const char *parent0; + const char *parent1; + const char *child; +}; +DECLARE_TYPE_AS_MOVABLE(parenthood_t); +static const parenthood_t parenthood_data[] = +{ + // level 0 + { Finarfin, Earwen, Finrod }, + { Finarfin, Earwen, Angrod }, + { Finarfin, Earwen, Aegnor }, + { Finarfin, Earwen, Galadriel }, + + // level 1 + { Eldalote, Angrod, Orodreth }, + { Galadriel, Celeborn, Celebrian }, + + // level 2 + { Orodreth, Unknown_name, Gil_Galad }, + { Orodreth, Unknown_name, Finduilas }, +}; +static const size_t nparenthood = qnumber(parenthood_data); + +//------------------------------------------------------------------------- +// Optional coloring of character names' text +struct character_name_decoration_t +{ + const char *name; + const char *color; + const char *name_subset; +}; +DECLARE_TYPE_AS_MOVABLE(character_name_decoration_t); +static const character_name_decoration_t character_name_decorations[] = +{ + { Finarfin, SCOLOR_MACRO, "Fin" }, + { Finrod, SCOLOR_MACRO, "Fin" }, + { Finduilas, SCOLOR_MACRO, "Fin" }, + + { Earwen, SCOLOR_CNAME, nullptr }, + { Unknown_name, SCOLOR_ERROR, "name unknown" }, + + { Galadriel, SCOLOR_IMPNAME, "Gal" }, + { Gil_Galad, SCOLOR_IMPNAME, "Gal" }, + + { Celeborn, SCOLOR_DNUM, "Celeb" }, + { Celebrian, SCOLOR_DNUM, "Celeb" }, +}; + +//-------------------------------------------------------------------------- +static void gen_character_name(qstring *out, const char *name) +{ + *out = name; + + for ( size_t i = 0; i < qnumber(character_name_decorations); ++i ) + { + if ( streq(character_name_decorations[i].name, name) ) + { + const character_name_decoration_t *d = &character_name_decorations[i]; + qstring token; + token.append(SCOLOR_ON); + token.append(d->color); + const char *token_s = d->name_subset != nullptr ? d->name_subset : d->name; + token.append(token_s); + token.append(SCOLOR_OFF); + token.append(d->color); + out->replace(token_s, token.c_str()); + break; + } + } +} + +//------------------------------------------------------------------------- +struct graph_data_t +{ + // Currently shown nodes data. Since we want to have some + // nodes show a special color, we keep a 'live' version of + // their text, which contains that information. + qstrvec_t live; + size_t levels_shown = 4; + + void refresh(mutable_graph_t *g); +}; + +//------------------------------------------------------------------------- +void graph_data_t::refresh(mutable_graph_t *g) +{ + QASSERT(0, levels_shown < qnumber(levels_offsets)); + + // Clear nodes & edges information + g->clear(); + + // Add nodes + const size_t nnodes = levels_offsets[levels_shown]; + g->resize(nnodes); + + // Add edges + for ( size_t i = 0; i < nparenthood; ++i ) + { + const parenthood_t &p = parenthood_data[i]; + int c_n = character_to_node_number(p.child); + if ( c_n >= g->size() ) + break; // means we are not showing this (and the following) level(s) + int p0_n = character_to_node_number(p.parent0); + int p1_n = character_to_node_number(p.parent1); + g->add_edge(p0_n, c_n, nullptr); + g->add_edge(p1_n, c_n, nullptr); + } + + // Generate names w/ possible colors + live.resize(nnodes); + for ( size_t i = 0; i < nnodes; ++i ) + gen_character_name(&live[i], node_number_to_character(i)); + + // Clear previously-registered custom text & background color. + // (We could be smarter and move those from old nodes to new + // nodes, but this would only bring little benefit in the + // context of this sample.) + for ( size_t i = 0; i < nnodes; ++i ) + del_node_info(g->gid, i); +} + +//------------------------------------------------------------------------- +struct plugin_ctx_t; + +//------------------------------------------------------------------------- +// A base action handler, ensuring the action is only available on the +// right widget, and possibly only if a (or more) node(s) is(are) +// selected. +struct base_ugraph_ah_t : public action_handler_t +{ + plugin_ctx_t &plg; + bool requires_node; + + base_ugraph_ah_t( + plugin_ctx_t &_plg, + bool _requires_node=false) + : plg(_plg), + requires_node(_requires_node) {} + virtual action_state_t idaapi update(action_update_ctx_t *ctx) override; + + struct node_visitor_t + { + virtual ~node_visitor_t() {} + virtual bool on_node(int node, node_info_t &ni) newapi = 0; + }; + +protected: + bool get_nodes( + intvec_t *out, + const action_ctx_base_t &ctx) const; + + bool for_each_node( + const action_ctx_base_t &ctx, + node_visitor_t &visitor); +}; + +//------------------------------------------------------------------------- +struct change_layout_ah_t : public base_ugraph_ah_t +{ + change_layout_ah_t(plugin_ctx_t &_plg) + : base_ugraph_ah_t(_plg) {} + + virtual int idaapi activate(action_activation_ctx_t *ctx) override; +}; + +//------------------------------------------------------------------------- +struct modify_levels_ah_t : public base_ugraph_ah_t +{ + int inc; + + modify_levels_ah_t(plugin_ctx_t &_plg, int _inc) + : base_ugraph_ah_t(_plg), + inc(_inc) {} + + virtual int idaapi activate(action_activation_ctx_t *ctx) override; + virtual action_state_t idaapi update(action_update_ctx_t *ctx) override; + +private: + size_t compute_levels_to_show() const; +}; + +//------------------------------------------------------------------------- +struct set_custom_text_ah_t : public base_ugraph_ah_t +{ + set_custom_text_ah_t(plugin_ctx_t &_plg) + : base_ugraph_ah_t(_plg, /*_requires_node=*/ true) {} + + virtual int idaapi activate(action_activation_ctx_t *ctx) override; +}; + +//------------------------------------------------------------------------- +struct set_custom_bgcolor_ah_t : public base_ugraph_ah_t +{ + set_custom_bgcolor_ah_t(plugin_ctx_t &_plg) + : base_ugraph_ah_t(_plg, /*_requires_node=*/ true) {} + + virtual int idaapi activate(action_activation_ctx_t *ctx) override; +}; + +#define ANAME_CHANGE_LAYOUT "ugraph:ChangeLayout" +#define ANAME_INC_LEVELS "ugraph:IncVisibleLevels" +#define ANAME_DEC_LEVELS "ugraph:DecVisibleLevels" +#define ANAME_SET_CUSTOM_TEXT "ugraph:SetCustomText" +#define ANAME_SET_CUSTOM_BGCOLOR "ugraph:SetCustomBgcolor" + +//-------------------------------------------------------------------------- +struct plugin_ctx_t : public plugmod_t, public event_listener_t +{ + change_layout_ah_t change_layout_ah = change_layout_ah_t(*this); + const action_desc_t change_layout_desc = ACTION_DESC_LITERAL_PLUGMOD( + ANAME_CHANGE_LAYOUT, + "Change layout type", + &change_layout_ah, + this, + NULL, + NULL, + -1); + + modify_levels_ah_t inc_levels_ah = modify_levels_ah_t(*this, 1); + const action_desc_t inc_levels_desc = ACTION_DESC_LITERAL_PLUGMOD( + ANAME_INC_LEVELS, + "Add level", + &inc_levels_ah, + this, + NULL, + NULL, + -1); + + modify_levels_ah_t dec_levels_ah = modify_levels_ah_t(*this, -1); + const action_desc_t dec_levels_desc = ACTION_DESC_LITERAL_PLUGMOD( + ANAME_DEC_LEVELS, + "Remove level", + &dec_levels_ah, + this, + NULL, + NULL, + -1); + + set_custom_text_ah_t set_custom_text_ah = set_custom_text_ah_t(*this); + const action_desc_t set_custom_text_desc = ACTION_DESC_LITERAL_PLUGMOD( + ANAME_SET_CUSTOM_TEXT, + "Custom text", + &set_custom_text_ah, + this, + NULL, + NULL, + -1); + + set_custom_bgcolor_ah_t set_custom_bgcolor_ah = set_custom_bgcolor_ah_t(*this); + const action_desc_t set_custom_bgcolor_desc = ACTION_DESC_LITERAL_PLUGMOD( + ANAME_SET_CUSTOM_BGCOLOR, + "Custom background color", + &set_custom_bgcolor_ah, + this, + NULL, + NULL, + -1); + + graph_data_t data; + graph_viewer_t *gv = nullptr; + + plugin_ctx_t() + { + hook_event_listener(HT_VIEW, this); + } + ~plugin_ctx_t() + { + // listeners are uninstalled automatically + // when the owner module is unloaded + } + + virtual bool idaapi run(size_t) override; + virtual ssize_t idaapi on_event(ssize_t code, va_list va) override; + static ssize_t idaapi gr_callback(void *ud, int code, va_list va); +}; + +//-------------------------------------------------------------------------- +ssize_t idaapi plugin_ctx_t::gr_callback(void *ud, int code, va_list va) +{ + // Please refer to the SDK's graph.hpp for an explanation + // of the notifications, and their parameters + + plugin_ctx_t &ctx = *(plugin_ctx_t *)ud; + ssize_t result = 0; + switch ( code ) + { + case grcode_calculating_layout: + msg("calculating graph layout...\n"); + break; + + case grcode_clicked: + { + graph_viewer_t *v = va_arg(va, graph_viewer_t *); qnotused(v); + selection_item_t *it = va_arg(va, selection_item_t *); qnotused(it); + graph_item_t *m = va_arg(va, graph_item_t *); + msg("clicked on "); + switch ( m->type ) + { + case git_none: + msg("background\n"); + break; + case git_edge: + msg("edge (%d, %d)\n", m->e.src, m->e.dst); + break; + case git_node: + msg("node %d\n", m->n); + break; + case git_tool: + msg("toolbutton %d\n", m->b); + break; + case git_text: + msg("text (x,y)=(%d,%d)\n", m->p.x, m->p.y); + break; + case git_elp: + msg("edge layout point (%d, %d) #%d\n", m->elp.e.src, m->elp.e.dst, m->elp.pidx); + break; + } + } + break; + + case grcode_dblclicked: + { + graph_viewer_t *v = va_arg(va, graph_viewer_t *); + selection_item_t *s = va_arg(va, selection_item_t *); + msg("%p: dblclicked on ", v); + if ( s == NULL ) + msg("background\n"); + else if ( s->is_node ) + msg("node %d\n", s->node); + else + msg("edge (%d, %d) layout point #%d\n", s->elp.e.src, s->elp.e.dst, s->elp.pidx); + } + break; + + case grcode_creating_group: + { + mutable_graph_t *g = va_arg(va, mutable_graph_t *); + intvec_t &nodes = *va_arg(va, intvec_t *); + msg("%p: creating group", g); + for ( intvec_t::iterator p=nodes.begin(); p != nodes.end(); ++p ) + msg(" %d", *p); + msg("...\n"); + } + break; + + case grcode_deleting_group: + { + mutable_graph_t *g = va_arg(va, mutable_graph_t *); + int group = va_argi(va, int); + msg("%p: deleting group %d\n", g, group); + } + break; + + case grcode_group_visibility: + { + mutable_graph_t *g = va_arg(va, mutable_graph_t *); + int group = va_argi(va, int); + bool expand = va_argi(va, bool); + msg("%p: %scollapsing group %d\n", g, expand ? "un" : "", group); + } + break; + + case grcode_gotfocus: + { + graph_viewer_t *g = va_arg(va, graph_viewer_t *); + msg("%p: got focus\n", g); + } + break; + + case grcode_lostfocus: + { + graph_viewer_t *g = va_arg(va, graph_viewer_t *); + msg("%p: lost focus\n", g); + } + break; + + case grcode_user_refresh: + { + mutable_graph_t *g = va_arg(va, mutable_graph_t *); + msg("%p: refresh\n", g); + ctx.data.refresh(g); + result = true; + } + break; + + case grcode_user_text: + { + mutable_graph_t *g = va_arg(va, mutable_graph_t *); + int node = va_arg(va, int); + const char **text = va_arg(va, const char **); + bgcolor_t *bgcolor = va_arg(va, bgcolor_t *); + *text = ctx.data.live[node].c_str(); + if ( bgcolor != NULL ) + *bgcolor = DEFCOLOR; + result = true; + qnotused(g); + } + break; + + + case grcode_user_size: + // result is 0 -> ida will calculate the node size based on the node text + break; + + case grcode_user_title: + // result is 0 -> ida will draw the node title itself + break; + + case grcode_user_draw: + // result is 0 -> ida will draw the node text itself + break; + + case grcode_user_hint: + { + mutable_graph_t *g = va_arg(va, mutable_graph_t *); + int mousenode = va_argi(va, int); + int mouseedge_src = va_argi(va, int); + int mouseedge_dst = va_argi(va, int); + char **hint = va_arg(va, char **); + char buf[MAXSTR]; + buf[0] = '\0'; + if ( mousenode != -1 ) + qsnprintf(buf, sizeof(buf), "My fancy hint for node %d", mousenode); + else if ( mouseedge_src != -1 ) + qsnprintf(buf, sizeof(buf), "Hovering on (%d,%d)", mouseedge_src, mouseedge_dst); + if ( buf[0] != '\0' ) + *hint = qstrdup(buf); + result = true; // use our hint + qnotused(g); + } + break; + } + return result; +} + +//------------------------------------------------------------------------- +ssize_t idaapi plugin_ctx_t::on_event(ssize_t code, va_list va) +{ + if ( code == view_close ) + { + TWidget *view = va_arg(va, TWidget *); + if ( view == (TWidget *)gv ) + gv = nullptr; + } + return 0; +} + +//------------------------------------------------------------------------- +action_state_t idaapi base_ugraph_ah_t::update(action_update_ctx_t *ctx) +{ + if ( ctx->widget != (TWidget *) plg.gv ) + return AST_DISABLE_FOR_WIDGET; + if ( requires_node ) + { + // If this requires nodes, we want to be called again as + // soon as something (i.e., the selection) changes + return get_nodes(nullptr, *ctx) ? AST_ENABLE : AST_DISABLE; + } + else + { + return AST_ENABLE_FOR_WIDGET; + } +} + +//------------------------------------------------------------------------- +bool base_ugraph_ah_t::get_nodes( + intvec_t *out, + const action_ctx_base_t &ctx) const +{ + screen_graph_selection_t *s = ctx.graph_selection; + if ( s == nullptr ) + return false; + intvec_t tmp; + size_t nitems = s->size(); + for ( size_t i = 0; i < nitems; ++i ) + { + const selection_item_t &item = s->at(i); + if ( item.is_node ) + tmp.push_back(item.node); + } + bool ok = !tmp.empty(); + if ( out != nullptr ) + out->swap(tmp); + return ok; +} + +//------------------------------------------------------------------------- +bool base_ugraph_ah_t::for_each_node( + const action_ctx_base_t &ctx, + node_visitor_t &visitor) +{ + mutable_graph_t *g = get_viewer_graph(plg.gv); + intvec_t nodes; + bool ok = get_nodes(&nodes, ctx); + if ( ok ) + { + size_t nnodes = nodes.size(); + for ( size_t i = 0; i < nnodes; ++i ) + { + int node = nodes[i]; + node_info_t ni; + get_node_info(&ni, g->gid, node); + visitor.on_node(node, ni); + uint32 niflags = ni.get_flags_for_valid(); + if ( niflags != 0 ) + set_node_info(g->gid, node, ni, niflags); + else + del_node_info(g->gid, node); + } + } + return ok; +} + +//------------------------------------------------------------------------- +int idaapi change_layout_ah_t::activate(action_activation_ctx_t *) +{ + mutable_graph_t *g = get_viewer_graph(plg.gv); + int code = ask_buttons( + "Circle", "Tree", "Digraph", 1, "Please select layout type"); + g->current_layout = code + 2; + g->circle_center = point_t(200, 200); + g->circle_radius = 200; + refresh_viewer(plg.gv); + return 1; +} + +//------------------------------------------------------------------------- +int idaapi modify_levels_ah_t::activate(action_activation_ctx_t *) +{ + plg.data.levels_shown = compute_levels_to_show(); + refresh_viewer(plg.gv); + return 1; +} + +//------------------------------------------------------------------------- +action_state_t idaapi modify_levels_ah_t::update(action_update_ctx_t *ctx) +{ + action_state_t state = base_ugraph_ah_t::update(ctx); + if ( !is_action_enabled(state) ) + return state; + const size_t next = compute_levels_to_show(); + return next > 0 && next <= nlevels ? AST_ENABLE : AST_DISABLE; +} + +//------------------------------------------------------------------------- +size_t modify_levels_ah_t::compute_levels_to_show() const +{ + return plg.data.levels_shown + inc; +} + +//------------------------------------------------------------------------- +int idaapi set_custom_text_ah_t::activate(action_activation_ctx_t *ctx) +{ + struct ida_local visitor_t : public node_visitor_t + { + qstring text; + + virtual ~visitor_t() {} + virtual bool on_node(int, node_info_t &ni) override + { + ni.text = text; + return true; + } + }; + visitor_t visitor; + return ask_text(&visitor.text, 256, nullptr, "Please enter node custom text") + && for_each_node(*ctx, visitor); +} + +//------------------------------------------------------------------------- +int idaapi set_custom_bgcolor_ah_t::activate(action_activation_ctx_t *ctx) +{ + struct ida_local visitor_t : public node_visitor_t + { + bgcolor_t bg_color = DEFCOLOR; + + virtual ~visitor_t() {} + virtual bool on_node(int, node_info_t &ni) override + { + ni.bg_color = bg_color; + return true; + } + }; + visitor_t visitor; + static const char form[] = + "Please pick a color\n" + "\n" + "<~C~olor:K::6::>\n"; + + CASSERT(sizeof(visitor.bg_color) == sizeof(bgcolor_t)); + return ask_form(form, &visitor.bg_color) + && for_each_node(*ctx, visitor); +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + if ( !is_idaq() ) + return nullptr; + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +static const char wanted_title[] = "Sample graph"; +bool idaapi plugin_ctx_t::run(size_t) +{ + TWidget *widget = find_widget(wanted_title); + if ( widget == nullptr ) + { + // get a unique graph id + netnode id; + id.create("$ ugraph sample"); + gv = create_graph_viewer(wanted_title, id, gr_callback, this, 0); + if ( gv != nullptr ) + { + display_widget(gv, WOPN_DP_TAB); + viewer_fit_window(gv); + register_action(change_layout_desc); + register_action(inc_levels_desc); + register_action(dec_levels_desc); + register_action(set_custom_text_desc); + register_action(set_custom_bgcolor_desc); + widget = find_widget(wanted_title); + attach_action_to_popup(widget, nullptr, change_layout_desc.name); + attach_action_to_popup(widget, nullptr, inc_levels_desc.name); + attach_action_to_popup(widget, nullptr, dec_levels_desc.name); + attach_action_to_popup(widget, nullptr, set_custom_text_desc.name, "Set/"); + attach_action_to_popup(widget, nullptr, set_custom_bgcolor_desc.name, "Set/"); + } + } + else + { + close_widget(widget, 0); + } + + return true; +} + +//-------------------------------------------------------------------------- +static const char comment[] = "This is a sample graph plugin."; + +static const char help[] = + "A sample graph plugin module\n" + "\n" + "This module shows you how to create a graph viewer."; + +//-------------------------------------------------------------------------- +// This is the preferred name of the plugin module in the menu system +// The preferred name may be overridden in plugins.cfg file + +static const char wanted_name[] = "Create sample graph view"; + + +// This is the preferred hotkey for the plugin module +// The preferred hotkey may be overridden in plugins.cfg file + +static const char wanted_hotkey[] = ""; + + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel + init, // initialize + + nullptr, + + nullptr, // invoke plugin + + comment, // long comment about the plugin + // it could appear in the status line + // or as a hint + + help, // multiline help about the plugin + + wanted_name, // the preferred short name of the plugin + wanted_hotkey // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/ugraph2/makefile b/idasdk76/plugins/ugraph2/makefile new file mode 100644 index 0000000..0687610 --- /dev/null +++ b/idasdk76/plugins/ugraph2/makefile @@ -0,0 +1,11 @@ +PROC=ugraph2 + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ugraph2$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ugraph2.cpp diff --git a/idasdk75/plugins/ugraph2/ugraph2.cpp b/idasdk76/plugins/ugraph2/ugraph2.cpp similarity index 100% rename from idasdk75/plugins/ugraph2/ugraph2.cpp rename to idasdk76/plugins/ugraph2/ugraph2.cpp diff --git a/idasdk76/plugins/ugraph3/makefile b/idasdk76/plugins/ugraph3/makefile new file mode 100644 index 0000000..8aeadd3 --- /dev/null +++ b/idasdk76/plugins/ugraph3/makefile @@ -0,0 +1,11 @@ +PROC=ugraph3 + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ugraph3$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ugraph3.cpp diff --git a/idasdk75/plugins/ugraph3/ugraph3.cpp b/idasdk76/plugins/ugraph3/ugraph3.cpp similarity index 100% rename from idasdk75/plugins/ugraph3/ugraph3.cpp rename to idasdk76/plugins/ugraph3/ugraph3.cpp diff --git a/idasdk76/plugins/ui_requests/makefile b/idasdk76/plugins/ui_requests/makefile new file mode 100644 index 0000000..e3aaba2 --- /dev/null +++ b/idasdk76/plugins/ui_requests/makefile @@ -0,0 +1,11 @@ +PROC=ui_requests + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)ui_requests$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp \ + $(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp ui_requests.cpp diff --git a/idasdk75/plugins/ui_requests/ui_requests.cpp b/idasdk76/plugins/ui_requests/ui_requests.cpp similarity index 100% rename from idasdk75/plugins/ui_requests/ui_requests.cpp rename to idasdk76/plugins/ui_requests/ui_requests.cpp diff --git a/idasdk76/plugins/uiswitch/makefile b/idasdk76/plugins/uiswitch/makefile new file mode 100644 index 0000000..7a5c0d1 --- /dev/null +++ b/idasdk76/plugins/uiswitch/makefile @@ -0,0 +1,11 @@ +PROC=uiswitch + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)uiswitch$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)jumptable.hpp $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp uiswitch.cpp diff --git a/idasdk76/plugins/uiswitch/uiswitch.cpp b/idasdk76/plugins/uiswitch/uiswitch.cpp new file mode 100644 index 0000000..7f17f4a --- /dev/null +++ b/idasdk76/plugins/uiswitch/uiswitch.cpp @@ -0,0 +1,397 @@ +/* + + Plugin that allows the user to specify the exact + address and shape of a jump table (switch idiom). + + It displays a dialog box with the most important + attributes of the switch idiom. If the idiom is + complex and has more attributes, then more + dialog boxes are displayed. + + All collected information is validated and then + stored in the database in the switch_info_t structure. + The last step is to reanalyze the switch idiom. + + Please note that this plugin supports the most + common switch idiom but some idiom types are not + handled, for example, custom switches are not. + +*/ + +#include <ida.hpp> +#include <idp.hpp> +#include <loader.hpp> +#include <jumptable.hpp> + +//------------------------------------------------------------------------- +struct plugin_ctx_t; +#define ACTION_NAME "uiswitch:SpecSwitchIdiom" +struct uiswitch_ah_t : public action_handler_t +{ + plugin_ctx_t &plg; + uiswitch_ah_t(plugin_ctx_t &_plg) : plg(_plg) {} + virtual int idaapi activate(action_activation_ctx_t *) override; + virtual action_state_t idaapi update(action_update_ctx_t *ctx) override + { + return ctx->widget_type == BWN_DISASM + ? AST_ENABLE_FOR_WIDGET + : AST_DISABLE_FOR_WIDGET; + } +}; + +//-------------------------------------------------------------------------- +struct plugin_ctx_t : public plugmod_t, public ignore_micro_t +{ + uiswitch_ah_t uiswitch_ah = uiswitch_ah_t(*this); + plugin_ctx_t(); + virtual bool idaapi run(size_t) override; + bool callback(); +}; + +//------------------------------------------------------------------------- +int idaapi uiswitch_ah_t::activate(action_activation_ctx_t *) +{ + return plg.callback(); +} + +//--------------------------------------------------------------------------- +// The main form +// hotkeys: abdefginpstu +static const char main_form[] = + "HELP\n" + "Please specify the jump table address, the number of its\n" + "elements and their widths(1,2,4,8). The element shift amount and base value\n" + "should be specified only if the table elements are not\n" + "plain target addresses but must be converted using the following\n" + "formula:\n" + "\n" + " target = base +/- (table_element << shift)\n" + "\n" + "(only this formula is supported by the kernel; other cases must be\n" + "handled by plugins and 'custom' switch idioms).\n" + "\n" + "If you specify BADADDR as the element base then the base of the\n" + "switch segment will be used\n" + "\n" + "The start of the switch idiom is the address of the first instruction\n" + "in the switch idiom.\n" + "\n" + "Subtraction is used instead of addition if \"Subtract table elements\"\n" + "is selected.\n" + "\n" + "When table element is an instruction then you should select\n" + "\"Table element is insn\".\n" + "\n" + "If you specify that a separate value table is present, an additional\n" + "dialog box with its attributes will be displayed.\n" + "ENDHELP\n" + // ansebtifdpgul + "Manual switch declaration - Main features\n" + "\n" + "<~A~ddress of jump table :N::18::>\n" + "<~N~umber of elements :D::18::>\n" + "<~S~ize of table element :D::18::>\n" + "<~E~lement shift amount :D::18::>\n" + "<Element ~b~ase value :N::18::>\n" + "\n" + "<S~t~art of the switch idiom:N::18::>\n" + "<~I~nput register of switch :q:511:18::>\n" + "<~F~irst(lowest) input value:D::18::>(if value table is absent)\n" + "<~D~efault jump address :N::18::>\n" + "\n" + "<Se~p~arate value table is present:C>\n" + "<Si~g~ned jump table elements :C>\n" + "<S~u~btract table elements :C>\n" + "<Tab~l~e element is insn :C>>\n" + "\n" + "\n"; + +// this form displayed if the value table is present +// shortcuts: afinus +static const char value_form[] = + "HELP\n" + "Direct value table holds values of the switch 'case's.\n" + "Each value maps to the corresponding target of the jump table\n" + "Indirect value table holds indexes into jump table.\n" + "\n" + "Inversed value table maps the first element of the value table\n" + "to the last element of the jump table.\n" + "\n" + "For direct table the size of the value table is equal\n" + "to the size of the jump table.\n" + "\n" + "Example of switch idiom with indirect value table:\n" + "\n" + " cmp ecx, 0Fh\n" + " ja short defjump\n" + " movzx ecx, ds:indirect_value_table[ecx]\n" + " jmp ds:jump_table[ecx*4]\n" + "\n" + " jump_table dd offset target_1\n" + " dd offset target_2\n" + " indirect_value_table db 0, 0, 1, 0\n" + " db 1, 1, 1, 0\n" + " db 1, 1, 1, 1\n" + " db 1, 1, 1, 0\n" + "\n" + "ENDHELP\n" + "Manual switch declaration - Value table\n" + "\n" + "<~I~ndirect value table:C>\n" + "<I~n~versed value table:C>>\n" + "<~A~ddress of value table:N::18::>\n" + "<N~u~mber of elements :D::18::> (only for indirect table)\n" + "<~S~ize of table element :D::18::>\n" + "<~F~irst(lowest) input value:D::18::> (only for indirect table)\n" + "\n" + "\n"; + +//--------------------------------------------------------------------------- +// Validate table attributes +static bool check_table(ea_t table, uval_t elsize, uval_t tsize) +{ + flags_t F; + if ( getseg(table) == NULL || is_code((F=get_flags(table))) || is_tail(F) ) + { + warning("AUTOHIDE NONE\nIncorrect table address %a", table); + return false; + } + if ( elsize != 1 && elsize != 2 && elsize != 4 && elsize != 8 ) + { + warning("AUTOHIDE NONE\nIncorrect table element size %" FMT_EA "u", elsize); + return false; + } + flags_t DF = get_flags_by_size((size_t)elsize); + if ( !can_define_item(table, elsize*tsize, DF) ) + { + warning("AUTOHIDE NONE\nCannot create table at %a size %" FMT_EA "u", table, tsize); + return false; + } + return true; +} + +//--------------------------------------------------------------------------- +// The main function - called when the user selects the menu item +bool plugin_ctx_t::callback() +{ + // Calculate the default values to display in the form + ea_t screen_ea = get_screen_ea(); + segment_t *s = getseg(screen_ea); + if ( s == NULL || !is_code(get_flags(screen_ea)) ) + { + warning("AUTOHIDE NONE\nThe cursor must be on the table jump instruction"); + return false; + } + + // If switch information is present in the database, use it for defaults + switch_info_t si; + if ( get_switch_info(&si, screen_ea) <= 0 ) + { + si.jumps = get_first_dref_from(screen_ea); + unsigned int jsize = (int)s->abytes(); + si.set_jtable_element_size(jsize); + // calculate NCASES + if ( si.jumps != BADADDR ) + { + const segment_t *jtable_seg = getseg(si.jumps); + ea_t jtable_end = jtable_seg != nullptr ? jtable_seg->end_ea : BADADDR; + int size = int((jtable_end - si.jumps) / jsize); + si.ncases = size > USHRT_MAX ? USHRT_MAX : size; + trim_jtable(&si, screen_ea, false); + } + // calculate STARTEA + si.startea = screen_ea; + while ( true ) + { + ea_t prev = prev_not_tail(si.startea); + if ( !is_switch_insn(prev) ) + break; + si.startea = prev; + } + } + + ea_t jumps = si.jumps; + uval_t jtsize = si.ncases; + ea_t startea = si.startea; + uval_t elbase = si.elbase; + uval_t jelsize = si.get_jtable_element_size(); + uval_t shift = si.get_shift(); + ea_t defea = si.defjump; + qstring input; + if ( si.regnum != -1 ) + get_reg_name(&input, si.regnum, get_dtype_size(si.regdtype)); + ushort jflags = 0; + if ( si.flags & SWI_SIGNED ) + jflags |= 2; + if ( si.flags & SWI_SUBTRACT ) + jflags |= 4; + if ( si.flags & SWI_JMPINSN ) + jflags |= 8; + uval_t lowcase = 0; + ushort vflags = 0; + ea_t vtable = BADADDR; + ea_t vtsize = 0; + ea_t velsize = 0; + ea_t vlowcase = 0; + if ( si.flags & SWI_SPARSE ) + { + jflags |= 1; + vtable = si.values; + vtsize = jtsize; + velsize = si.get_vtable_element_size(); + if ( si.flags & SWI_INDIRECT ) + { + vlowcase = si.get_lowcase(); + vflags |= 1; + jtsize = si.jcases; + } + if ( si.flags & SWI_JMP_INV ) + vflags |= 2; + } + else + { + lowcase = si.lowcase; + } + // TODO allow to change these fields + ea_t expr_ea = si.expr_ea; + eavec_t marks = si.marks; + + // Now display the form and let the user edit the attributes + while ( ask_form(main_form, &jumps, &jtsize, &jelsize, &shift, &elbase, + &startea, &input, &lowcase, &defea, &jflags) ) + { + if ( !check_table(jumps, jelsize, jtsize) ) + continue; + if ( shift > 3 ) + { + warning("AUTOHIDE NONE\nInvalid shift value (allowed values are 0..3)"); + continue; + } + if ( !is_code(get_flags(startea)) ) + { + warning("AUTOHIDE NONE\nInvalid switch idiom start %a (must be an instruction", startea); + continue; + } + reg_info_t ri; + ri.reg = -1; + ri.size = 0; + if ( !input.empty() && !parse_reg_name(&ri, input.c_str()) ) + { + warning("AUTOHIDE NONE\nUnknown input register: %s", input.c_str()); + continue; + } + if ( defea != BADADDR && !is_code(get_flags(defea)) ) + { + warning("AUTOHIDE NONE\nInvalid default jump %a (must be an instruction", defea); + continue; + } + if ( jflags & 1 ) // value table is present + { + bool vok = false; + while ( ask_form(value_form, &vflags, &vtable, &vtsize, &velsize, &vlowcase) ) + { + if ( (vflags & 1) == 0 ) + vtsize = jtsize; + if ( check_table(vtable, velsize, vtsize) ) + { + vok = true; + break; + } + } + if ( !vok ) + break; + } + // ok, got and validated all params -- fill the structure + si.clear(); + if ( jflags & 2 ) + si.flags |= SWI_SIGNED; + if ( jflags & 4 ) + si.flags |= SWI_SUBTRACT; + if ( jflags & 8 ) + si.flags |= SWI_JMPINSN; + si.jumps = jumps; + si.ncases = ushort(jtsize); + si.startea = startea; + if ( elbase != BADADDR ) + si.set_elbase(elbase); + si.set_jtable_element_size((int)jelsize); + si.set_shift((int)shift); + si.defjump = defea; + if ( ri.reg != -1 ) + si.set_expr(ri.reg, get_dtype_by_size(ri.size)); + if ( jflags & 1 ) // value table is present + { + si.flags |= SWI_SPARSE; + si.values = vtable; + si.set_vtable_element_size((int)velsize); + if ( (vflags & 1) != 0 ) + { + si.flags |= SWI_INDIRECT; + si.jcases = (int)jtsize; + si.ncases = (ushort)vtsize; + si.ind_lowcase = vlowcase; + } + if ( (vflags & 2) != 0 ) + si.flags |= SWI_JMP_INV; + } + else + { + si.lowcase = lowcase; + } + si.expr_ea = expr_ea; + si.marks = marks; + si.flags |= SWI_USER; + // ready, store it + set_switch_info(screen_ea, si); + create_switch_table(screen_ea, si); + create_insn(screen_ea); + info("AUTOHIDE REGISTRY\nSwitch information has been stored"); + break; + } + return true; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + return new plugin_ctx_t; +} + +//-------------------------------------------------------------------------- +plugin_ctx_t::plugin_ctx_t() +{ + register_and_attach_to_menu( + "Edit/Other/Create", ACTION_NAME, "Specify switch idiom...", + NULL, SETMENU_INS, + &uiswitch_ah, + this, + ADF_OT_PLUGMOD); + init_ignore_micro(); +} + +//-------------------------------------------------------------------------- +bool idaapi plugin_ctx_t::run(size_t) +{ + callback(); + return true; +} + +//-------------------------------------------------------------------------- +static const char help[] = ""; +static const char comment[] = ""; +static const char wanted_name[] = "Specify switch idiom"; +static const char wanted_hotkey[] = ""; + +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI // The plugin can work with multiple idbs in parallel + | PLUGIN_HIDE, // Plugin should not appear in the Edit, Plugins menu + init, // initialize + nullptr, + nullptr, + comment, // long comment about the plugin + help, // multiline help about the plugin + wanted_name, // the preferred short name of the plugin + wanted_hotkey // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/uunp/makefile b/idasdk76/plugins/uunp/makefile new file mode 100644 index 0000000..2978752 --- /dev/null +++ b/idasdk76/plugins/uunp/makefile @@ -0,0 +1,29 @@ +PROC=uunp +O1=resext +O2=win9x + + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)resext$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp $(I)fpro.h \ + $(I)funcs.hpp $(I)ida.hpp $(I)idp.hpp $(I)ieee.h \ + $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \ + $(I)loader.hpp $(I)nalt.hpp $(I)netnode.hpp $(I)pro.h \ + $(I)prodir.h $(I)range.hpp $(I)segment.hpp $(I)ua.hpp \ + $(I)xref.hpp resext.cpp uunp.hpp +$(F)uunp$(O) : $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)dbg.hpp $(I)entry.hpp \ + $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp $(I)idd.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp \ + $(I)nalt.hpp $(I)name.hpp \ + $(I)netnode.hpp $(I)offset.hpp $(I)pro.h $(I)range.hpp \ + $(I)segment.hpp $(I)ua.hpp $(I)xref.hpp uunp.cpp \ + uunp.hpp +$(F)win9x$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)dbg.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp uunp.hpp win9x.cpp diff --git a/idasdk75/plugins/uunp/resext.cpp b/idasdk76/plugins/uunp/resext.cpp similarity index 100% rename from idasdk75/plugins/uunp/resext.cpp rename to idasdk76/plugins/uunp/resext.cpp diff --git a/idasdk76/plugins/uunp/uunp.cpp b/idasdk76/plugins/uunp/uunp.cpp new file mode 100644 index 0000000..815e7de --- /dev/null +++ b/idasdk76/plugins/uunp/uunp.cpp @@ -0,0 +1,825 @@ +// Universal Unpacker based on IDA debugger 1.2 +// Unpacks PE files + +// The algorithm of this plugin is: + +// 1. start the process until the entry point of the packed program +// 2. add a breakpoint at kernel32.GetProcAddress +// 3. resume the execution and wait until the packer calls GetProcAddress +// if the function name passed to GetProcAddress is not in the ignore-list, +// then switch to the trace mode +// A call to GetProcAddress() most likely means that the program has been +// unpacked in the memory and now it setting up its import table +// 4. trace the program in the single step mode until we jump to +// the range with the original entry point. +// 5. as soon as the current ip belongs OEP range, suspend the execution and +// inform the user +// +// So, in short, we allow the unpacker to do its job full speed until +// it starts to setup the import table. At this moment we switch to the single +// step mode and try to find the original entry point. +// +// While this algorithm works with UPX, aspack, and several other packers, +// it might fail and execution of the packed program might go out of control. +// So please use this plugin with precaution. +// +// Ilfak Guilfanov, Yury Haron + +#include <windows.h> + +#ifdef _MSC_VER +# pragma warning(disable: 4996) // GetVersion was declared deprecated +#endif + +#include <ida.hpp> +#include <dbg.hpp> +#include <loader.hpp> +#include <kernwin.hpp> +#include <bytes.hpp> +#include <offset.hpp> +#include <auto.hpp> +#include <entry.hpp> +#include <name.hpp> +#include "uunp.hpp" + + +//-------------------------------------------------------------------------- +#define REGNAME_EAX (inf_is_64bit() ? "rax" : "eax") +#define REGNAME_ECX (inf_is_64bit() ? "rcx" : "ecx") +#define REGVALUE_MASK (inf_is_64bit() ? ea_t(-1) : ea_t(0xffffffffu)) + +//-------------------------------------------------------------------------- +static size_t get_ptrsize(void) +{ +#ifndef __EA64__ + return sizeof(ea_t); +#else + static size_t ptr_sz = 0; + if ( ptr_sz == 0 ) + ptr_sz = inf_is_64bit() ? 8 : 4; + return ptr_sz; +#endif +} + +//-------------------------------------------------------------------------- +bool doPtr(ea_t ea) +{ + bool ok = get_ptrsize() == 4 ? create_dword(ea, 4) : create_qword(ea, 8); + return ok && op_plain_offset(ea, 0, 0); +} + +//-------------------------------------------------------------------------- +ea_t getPtr(ea_t ea) +{ + return get_ptrsize() == 4 ? get_dword(ea) : get_qword(ea); +} + +//-------------------------------------------------------------------------- +inline bool my_add_bpt(uunp_ctx_t &ctx, ea_t ea) +{ + ctx.bpt_ea = ea; + return add_bpt(ea); +} + +//-------------------------------------------------------------------------- +inline bool my_del_bpt(uunp_ctx_t &ctx, ea_t ea) +{ + ctx.bpt_ea = BADADDR; + return del_bpt(ea); +} + +//--------------------------------------------------------------------------- +inline void uunp_ctx_t::_hide_wait_box() +{ + if ( wait_box_visible ) + { + wait_box_visible = false; + hide_wait_box(); + } +} + +//-------------------------------------------------------------------------- +inline void uunp_ctx_t::set_wait_box(const char *mesg) +{ + if ( wait_box_visible ) + { + replace_wait_box("HIDECANCEL\n%s", mesg); + } + else + { + wait_box_visible = true; + show_wait_box("HIDECANCEL\n%s", mesg); + } +} + +//-------------------------------------------------------------------------- +static void move_entry(uunp_ctx_t &ctx, ea_t rstart) +{ + // remove old start + set_name(inf_get_start_ea(), ""); + + // patch inf struct + inf_set_start_ea(rstart); + inf_set_start_ip(rstart); + + // add new entry point + add_entry(rstart, rstart, "start", true); + ctx.success = true; + + segment_t *ps = getseg(rstart); + if ( ps != NULL ) + { + ps->set_loader_segm(true); + ps->update(); + } +} + +//-------------------------------------------------------------------------- +// Unpacker might use some Win32 functions to perform their function +// This function verifies whether we must switch to the trace mode +// or continue to wait for GetProcAddress() of some other interesting function +static bool ignore_win32_api(const char *name) +{ + static const char *const ignore_names[] = { "VirtualAlloc", "VirtualFree" }; + for ( size_t i=0; i < qnumber(ignore_names); i++ ) + { + if ( strcmp(name, ignore_names[i]) == 0 ) + return true; + } + return false; +} + +//-------------------------------------------------------------------------- +inline bool is_library_entry(const uunp_ctx_t &ctx, ea_t ea) +{ + return !ctx.curmod.contains(ea); +} + +//-------------------------------------------------------------------------- +static bool find_module(ea_t ea, modinfo_t *mi) +{ + bool ok; + for ( ok=get_first_module(mi); ok; ok=get_next_module(mi) ) + { + if ( range_t(mi->base, mi->base+mi->size).contains(ea) ) + break; + } + return ok; +} + +//-------------------------------------------------------------------------- +static bool create_idata_segm(const range_t &impdir) +{ + segment_t ns; + segment_t *s = getseg(impdir.start_ea); + if ( s != NULL ) + ns = *s; + else + ns.sel = setup_selector(0); + + ns.start_ea = impdir.start_ea; + ns.end_ea = impdir.end_ea; + ns.type = SEG_XTRN; + ns.set_loader_segm(true); + bool ok = add_segm_ex(&ns, ".idata", "XTRN", ADDSEG_NOSREG) != 0; + if ( !ok ) + ok = ask_yn(ASKBTN_NO, + "HIDECANCEL\n" + "Cannot create the import segment. Continue anyway?") > ASKBTN_NO; + + return ok; +} + +//-------------------------------------------------------------------------- +static bool find_impdir(uunp_ctx_t &ctx, range_t *impdir) +{ + impdir->start_ea = impdir->end_ea = 0; + + uint32 ea32 = uint32(ctx.an_imported_func); + for ( ea_t pos = ctx.curmod.start_ea; + pos <= ctx.curmod.end_ea; + pos += sizeof(DWORD) ) + { + pos = bin_search2(pos, ctx.curmod.end_ea, (uchar *)&ea32, NULL, 4, + BIN_SEARCH_NOBREAK|BIN_SEARCH_CASE|BIN_SEARCH_FORWARD); + if ( pos == BADADDR ) + break; + + // skip unaligned matches + if ( (pos & 3) != 0 ) + continue; + + // cool, we found a pointer to an imported function + // now try to determine the impdir bounds + ea_t bounds[2] = { pos, pos }; + + for ( int k=0; k < 2; k++ ) + { + ea_t ea = pos; + while ( true ) + { + if ( k == 1 ) + ea += get_ptrsize(); + else + ea -= get_ptrsize(); + + ea_t func = ctx.is_9x ? ctx.win9x_find_thunk(ea) : getPtr(ea); + if ( func == 0 ) + continue; + + if ( !is_mapped(func) ) + break; + + if ( ctx.curmod.contains(func) ) + break; + + modinfo_t mi; + if ( !find_module(func, &mi) ) + break; + + bounds[k] = ea; + } + } + + bounds[1] += get_ptrsize(); + + asize_t bsize = bounds[1] - bounds[0]; + if ( bsize > impdir->size() ) + *impdir = range_t(bounds[0], bounds[1]); + } + return impdir->start_ea != 0; +} + +//-------------------------------------------------------------------------- +static bool create_impdir(uunp_ctx_t &ctx, const range_t &impdir) +{ + // now rename all entries in impdir + del_items(impdir.start_ea, DELIT_EXPAND, impdir.size()); + if ( !create_idata_segm(impdir) ) + return false; + + char dll[MAXSTR]; + qstring buf; + dll[0] = '\0'; + modinfo_t mi; + mi.base = BADADDR; + mi.size = 0; + size_t len = 0; + for ( ea_t ea=impdir.start_ea; ea < impdir.end_ea; ea += get_ptrsize() ) + { + doPtr(ea); + ea_t func = ctx.is_9x ? ctx.win9x_find_thunk(ea) : getPtr(ea); + if ( get_name(&buf, func) <= 0 ) + continue; + + if ( !range_t(mi.base, mi.base+mi.size).contains(func) ) + { + find_module(func, &mi); + qstrncpy(dll, qbasename(mi.name.c_str()), sizeof(dll)); + char *ptr = strrchr(dll, '.'); + if ( ptr != NULL ) + *ptr = '\0'; + if ( streq(dll, "ntdll32") ) // ntdll32 -> ntdll + dll[5] = '\0'; + len = strlen(dll); + } + const char *name = buf.begin(); + if ( strnicmp(dll, name, len) == 0 && name[len] == '_' ) + name += len + 1; + if ( !force_name(ea, name, SN_IDBENC) ) + msg("%a: cannot rename to imported name '%s'\n", ea, name); + } + + return true; +} + +//-------------------------------------------------------------------------- +static void create_impdir(uunp_ctx_t &ctx) +{ + // refresh dll entry point names + dbg->suspended(true); + + // refresh memory configuration + invalidate_dbgmem_config(); + + // found impdir? + range_t impdir; + if ( !find_impdir(ctx, &impdir) ) + return; + + msg("Uunp: Import directory bounds %a..%a\n", impdir.start_ea, impdir.end_ea); + create_impdir(ctx, impdir); +} + +//-------------------------------------------------------------------------- +static void tell_about_failure(void) +{ + warning("The plugin failed to unpack the program, sorry.\n" + "If you want to improve it, the source code is in the SDK!"); +} + +//-------------------------------------------------------------------------- +ssize_t idaapi dbg_listener_t::on_event(ssize_t code, va_list va) +{ + return ctx.on_dbg_event(code, va); +} + +ssize_t idaapi uunp_ctx_t::on_dbg_event(ssize_t code, va_list va) +{ + switch ( code ) + { + case dbg_process_start: + case dbg_process_attach: + get_input_file_path(needed_file, sizeof(needed_file)); + // no break + case dbg_library_load: + if ( stage == 0 ) + { + const debug_event_t *pev = va_arg(va, const debug_event_t *); + const char *modname = pev->modinfo().name.c_str(); + const char *myname = needed_file; + if ( !inf_is_dll() ) + { // ignore the full path for exe names (to handle subst drives) + modname = qbasename(modname); + myname = qbasename(myname); + } + if ( !strieq(modname, myname) ) + break; + if ( code == dbg_library_load ) + is_dll = true; + // remember the current module bounds + if ( pev->modinfo().rebase_to != BADADDR ) + curmod.start_ea = pev->modinfo().rebase_to; + else + curmod.start_ea = pev->modinfo().base; + curmod.end_ea = curmod.start_ea + pev->modinfo().size; + deb(IDA_DEBUG_DBGINFO, "UUNP: module space %a-%a\n", curmod.start_ea, curmod.end_ea); + ++stage; + } + break; + + case dbg_library_unload: + if ( stage != 0 && is_dll ) + { + const debug_event_t *pev = va_arg(va, const debug_event_t *); + if ( curmod.start_ea == pev->modinfo().base + || curmod.start_ea == pev->modinfo().rebase_to ) + { + deb(IDA_DEBUG_DBGINFO, "UUNP: unload unpacked module\n"); + if ( stage > 2 ) + enable_step_trace(false); + stage = 0; + curmod.start_ea = 0; + curmod.end_ea = 0; + _hide_wait_box(); + } + } + break; + + case dbg_run_to: // Parameters: const debug_event_t *event + dbg->suspended(true); + bp_gpa = get_name_ea(BADADDR, "kernel32_GetProcAddress"); + if ( (LONG)GetVersion() < 0 ) // win9x mode -- use thunk's + { + is_9x = true; + win9x_resolve_gpa_thunk(); + } + if ( bp_gpa == BADADDR ) + { + bring_debugger_to_front(); + warning("Sorry, could not find kernel32.GetProcAddress"); +FORCE_STOP: + stage = 4; // last stage + clear_requests_queue(); + request_exit_process(); + run_requests(); + break; + } + else if ( !my_add_bpt(*this, bp_gpa) ) + { + bring_debugger_to_front(); + warning("Sorry, cannot set bpt to kernel32.GetProcAddress"); + goto FORCE_STOP; + } + else + { + ++stage; + set_wait_box("Waiting for a call to GetProcAddress()"); + } + continue_process(); + break; + + case dbg_bpt: // A user defined breakpoint was reached. + // Parameters: thid_t tid + // ea_t breakpoint_ea + // int *warn = -1 + // Return (in *warn): + // -1 - to display a breakpoint warning dialog + // if the process is suspended. + // 0 - to never display a breakpoint warning dialog. + // 1 - to always display a breakpoint warning dialog. + { + thid_t tid = va_arg(va, thid_t); qnotused(tid); + ea_t ea = va_arg(va, ea_t); + ea &= REGVALUE_MASK; + //int *warn = va_arg(va, int*); + if ( stage == 2 ) + { + if ( ea == bp_gpa ) + { + ea_t esp; + if ( get_sp_val(&esp) ) + { + invalidate_dbgmem_contents(esp, 1024); + ea_t gpa_caller = getPtr(esp); + if ( !is_library_entry(*this, gpa_caller) ) + { + ea_t nameaddr; + if ( get_ptrsize() == 4 ) + { + nameaddr = get_dword(esp+8); + } + else + { + regval_t rv; + get_reg_val(REGNAME_ECX, &rv); + nameaddr = ea_t(rv.ival) & REGVALUE_MASK; + } + invalidate_dbgmem_contents(nameaddr, 1024); + qstring name; + size_t len = get_max_strlit_length(nameaddr, STRTYPE_C, ALOPT_IGNHEADS); + get_strlit_contents(&name, nameaddr, len, STRTYPE_C); + if ( !ignore_win32_api(name.c_str()) ) + { + deb(IDA_DEBUG_DBGINFO, "%a: found a call to GetProcAddress(%s)\n", gpa_caller, name.c_str()); + if ( !my_del_bpt(*this, bp_gpa) || !my_add_bpt(*this, gpa_caller) ) + error("Cannot modify breakpoint"); + } + } + } + } + else if ( ea == bpt_ea ) + { + my_del_bpt(*this, ea); + if ( !is_library_entry(*this, ea) ) + { + msg("Uunp: reached unpacker code at %a, switching to trace mode\n", ea); + enable_step_trace(true); + ++stage; + uint64 eax = 0; + if ( get_reg_val(REGNAME_EAX, &eax) ) + an_imported_func = ea_t(eax) & REGVALUE_MASK; + set_wait_box("Waiting for the unpacker to finish"); + } + else + { + warning("%a: bpt in library code", ea); // how can it be? + my_add_bpt(*this, bp_gpa); + } + } + // not our bpt? skip it + else + { + // hide the wait box to allow others plugins to properly stop + _hide_wait_box(); + break; + } + } + } + // while continue_process() would work here too, request+run is more universal + // because they do not ignore the request queue + request_continue_process(); + run_requests(); + break; + + case dbg_trace: // A step occurred (one instruction was executed). This event + // notification is only generated if step tracing is enabled. + // Parameter: none + if ( stage == 3 ) + { + thid_t tid = va_arg(va, thid_t); qnotused(tid); + ea_t ip = va_arg(va, ea_t); + ip &= REGVALUE_MASK; + + // ip reached the OEP range? + if ( oep_range.contains(ip) ) + { + // stop the trace mode + enable_step_trace(false); + msg("Uunp: reached OEP %a\n", ip); + set_wait_box("Reanalyzing the unpacked code"); + + // reanalyze the unpacked code + del_items(oep_range.start_ea, DELIT_EXPAND, oep_range.size()); + auto_make_code(ip); // plan to make code + plan_range(oep_range.start_ea, oep_range.end_ea); // plan to reanalyze + auto_mark_range(oep_range.start_ea, oep_range.end_ea, AU_FINAL); // plan to analyze + move_entry(*this, ip); // mark the program's entry point + + _hide_wait_box(); + + // inform the user + bring_debugger_to_front(); + if ( ask_yn(ASKBTN_YES, + "HIDECANCEL\n" + "The universal unpacker has finished its work.\n" + "Do you want to take a memory snapshot and stop now?\n" + "(you can do it yourself if you want)\n") > ASKBTN_NO ) + { + set_wait_box("Recreating the import table"); + invalidate_dbgmem_config(); + + if ( is_9x ) + find_thunked_imports(); + + create_impdir(*this); + + set_wait_box("Extracting resources"); + if ( !resfile.empty() ) + extract_resource(resfile.c_str()); + + _hide_wait_box(); + if ( take_memory_snapshot(true) ) + goto FORCE_STOP; + } + suspend_process(); + unhook_event_listener(HT_DBG, &dbg_listener); + } + } + break; + + case dbg_process_exit: + { + stage = 0; + // stop the tracing + _hide_wait_box(); + unhook_event_listener(HT_DBG, &dbg_listener); + if ( success ) + jumpto(inf_get_start_ea(), -1); + else + tell_about_failure(); + } + break; + + case dbg_exception:// Parameters: const debug_event_t *event + // int *warn = -1 + // Return (in *warn): + // -1 - to display an exception warning dialog + // if the process is suspended. + // 0 - to never display an exception warning dialog. + // 1 - to always display an exception warning dialog. + + { +// const debug_event_t *event = va_arg(va, const debug_event_t *); +// int *warn = va_arg(va, int *); + // FIXME: handle code which uses SEH to unpack itself + if ( ask_yn(ASKBTN_YES, + "AUTOHIDE DATABASE\n" + "HIDECANCEL\n" + "An exception occurred in the program.\n" + "UUNP does not support exceptions yet.\n" + "The execution has been suspended.\n" + "Do you want to continue the unpacking?") <= ASKBTN_NO ) + { + _hide_wait_box(); + stage = 0; + enable_step_trace(false); // stop the trace mode + suspend_process(); + } + else + { + continue_process(); + } + } + break; + + case dbg_request_error: + // An error occurred during the processing of a request. + // Parameters: ui_notification_t failed_command + // dbg_notification_t failed_dbg_notification + { + ui_notification_t failed_cmd = va_arg(va, ui_notification_t); + dbg_notification_t failed_dbg_notification = va_arg(va, dbg_notification_t); + _hide_wait_box(); + stage = 0; + warning("dbg request error: command: %d notification: %d", + failed_cmd, failed_dbg_notification); + } + break; + } + return 0; +} + +//-------------------------------------------------------------------------- + +//-------------------------------------------------------------------------- +// 0 - run uunp interactively +// 1 - run without questions +// 2 - run manual reconstruction +bool idaapi uunp_ctx_t::run(size_t arg) +{ + if ( arg == 2 ) + { + range_t impdir = range_t(0, 0); + ea_t oep; + + netnode n; + + // Settings never stored before? + if ( n.create(UUNP_NODE_NAME) ) + { + // Populate default values + oep = get_screen_ea(); + segment_t *s = getseg(oep); + if ( s != NULL ) + { + oep_range.start_ea = s->start_ea; + oep_range.end_ea = s->end_ea; + } + } + else + { + // Restore previous settings + oep = n.altval(0); + oep_range.start_ea = n.altval(1); + oep_range.end_ea = n.altval(2); + impdir.start_ea = n.altval(3); + impdir.end_ea = n.altval(4); + } + CASSERT(sizeof(oep_range.start_ea) == sizeof(ea_t)); + CASSERT(sizeof(oep_range.end_ea) == sizeof(ea_t)); + if ( !ask_form("Reconstruction parameters\n" + "\n" + " <~O~riginal entrypoint:N::32::>\n" + " <Code ~s~tart address:N::32::>\n" + " <Code ~e~nd address :N::32::>\n" + "\n" + " <IAT s~t~art address:N::32::>\n" + " <IAT e~n~d address:N::32::>\n" + "\n", + &oep, + &oep_range.start_ea, &oep_range.end_ea, + &impdir.start_ea, &impdir.end_ea) ) + { + // Cancelled? + return true; + } + + // Invalid settings? + if ( impdir.start_ea == 0 || impdir.end_ea == 0 ) + { + msg("Invalid import address table boundaries\n"); + return true; + } + + // Store settings + n.altset(0, oep); + n.altset(1, oep_range.start_ea); + n.altset(2, oep_range.end_ea); + n.altset(3, impdir.start_ea); + n.altset(4, impdir.end_ea); + + if ( !create_impdir(*this, impdir) ) + return false; + + // reanalyze the unpacked code + del_items(oep_range.start_ea, DELIT_EXPAND, oep_range.size()); + auto_make_code(oep); + plan_range(oep_range.start_ea, oep_range.end_ea); + auto_mark_range(oep_range.start_ea, oep_range.end_ea, AU_FINAL); + + // mark the program's entry point + move_entry(*this, oep); + + take_memory_snapshot(true); + arg = 0; + goto oep_setted; + } + + // Determine the original entry point range + for ( segment_t *s = get_first_seg(); s != NULL; s=get_next_seg(s->start_ea) ) + { + if ( s->type != SEG_GRP ) + { + oep_range = *s; + break; + } + } + +oep_setted: + if ( arg == 0 + && ask_yn(ASKBTN_NO, + "HIDECANCEL\n" + "AUTOHIDE REGISTRY\n" + "Universal PE unpacker\n" + "\n" + "IMPORTANT INFORMATION, PLEASE READ CAREFULLY!\n" + "\n" + "This plugin will start the program execution and try to suspend it\n" + "as soon as the packer finishes its work. Since there might be many\n" + "variations in packers and packing methods, the execution might go out\n" + "of control. There are many ways how things can go wrong, but since you\n" + "have the source code of this plugin, you can modify it as you wish.\n" + "\n" + "Do you really want to launch the program?\n") <= 0 ) + { + return true; + } + + success = false; + + char resfile_[QMAXPATH]; + set_file_ext(resfile_, sizeof(resfile_), get_path(PATH_TYPE_IDB), "res"); + if ( arg == 0 + && !ask_form("Uunp parameters\n" + "IDA will suspend the program when the execution reaches\n" + "the original entry point range. The default values are in\n" + "this dialog box. Please verify them and correct if you wish.\n" + "\n" + "ORIGINAL ENTRY POINT AREA\n" + " <~S~tart address:N::32::>\n" + " <~E~nd address :N::32::>\n" + "\n" + "OUTPUT RESOURCE FILE NAME\n" + " <~R~esource file:f:1:32::>\n" + "\n", + &oep_range.start_ea, + &oep_range.end_ea, + resfile_) ) + { + return true; + } + resfile = resfile_; + + if ( !hook_event_listener(HT_DBG, &dbg_listener) ) + { + warning("Could not hook to notification point"); + return true; + } + + if ( dbg == NULL ) + load_debugger("win32", false); + + // Let's start the debugger + if ( !run_to(inf_get_start_ea()) ) + { + warning("Sorry, could not start the process"); + unhook_event_listener(HT_DBG, &dbg_listener); + } + return true; +} + +//-------------------------------------------------------------------------- +static plugmod_t *idaapi init() +{ + // Our plugin works only for x86 PE executables + processor_t &ph = PH; + if ( ph.id != PLFM_386 || inf_get_filetype() != f_PE ) + return nullptr; + + return new uunp_ctx_t; +} + +//-------------------------------------------------------------------------- +uunp_ctx_t::uunp_ctx_t() +{ +} + +uunp_ctx_t::~uunp_ctx_t() +{ + // listeners are uninstalled automatically + // when the owner module is unloaded + + // just to be safe + _hide_wait_box(); + fr = nullptr; + +} + +//-------------------------------------------------------------------------- +static const char wanted_name[] = "Universal PE unpacker"; + +//-------------------------------------------------------------------------- +// +// PLUGIN DESCRIPTION BLOCK +// +//-------------------------------------------------------------------------- +plugin_t PLUGIN = +{ + IDP_INTERFACE_VERSION, + PLUGIN_MULTI, // The plugin can work with multiple idbs in parallel + init, // initialize + + nullptr, + + nullptr, + + wanted_name, // long comment about the plugin + // it could appear in the status line + // or as a hint + + wanted_name, // multiline help about the plugin + + wanted_name, // the preferred short name of the plugin + "" // the preferred hotkey to run the plugin +}; diff --git a/idasdk76/plugins/uunp/uunp.hpp b/idasdk76/plugins/uunp/uunp.hpp new file mode 100644 index 0000000..bf56171 --- /dev/null +++ b/idasdk76/plugins/uunp/uunp.hpp @@ -0,0 +1,89 @@ +#include <idp.hpp> +#include <loader.hpp> + +#define UUNP_NODE_NAME "$ uunp" + +//---------------------------------------------------------------------- +struct uunp_ctx_t; +DECLARE_LISTENER(dbg_listener_t, uunp_ctx_t, ctx); + +struct uunp_ctx_t : public plugmod_t +{ + dbg_listener_t dbg_listener = dbg_listener_t(*this); + + ea_t bp_gpa = BADADDR; // address of GetProcAddress() + range_t curmod; // current module range + bool wait_box_visible = false; + range_t oep_range; // original entry point range + qstring resfile; // resource file name + ea_t an_imported_func = BADADDR; // an imported function + bool success = false; + bool is_9x = false; + ea_t bpt_ea = BADADDR; // our bpt address + + // win9x.cpp + typedef std::map<ea_t, ea_t> thunks_t; + thunks_t thunks; + + // resext.cpp + FILE *fr = NULL; + ea_t ResBase = 0; + uint32 ResTop = 0; + asize_t ImgSize = 0; + struct + { + union + { + wchar_t *name = nullptr; + uint16 Id; + }; + uint32 len = 0; + } Names[3]; + +#pragma pack(push, 1) + struct rhdr_end_t + { + uint32 DataVersion; + uint16 MemoryFlags; + uint16 LanguageId; + uint32 Version; + uint32 Characteristrics; + }; + union rhdr_name_t + { + struct + { + uint16 prefix; // = 0xFFFF if number entry + uint16 Id; // for number entry + }; + wchar_t Name[1]; // zero terminated + }; +#pragma pack() + rhdr_end_t re = { 0 }; + rhdr_name_t zname = { { 0xFFFF } }; + + // on_event() + int stage = 0; + bool is_dll = false; + char needed_file[QMAXPATH] = ""; + + uunp_ctx_t(); + ~uunp_ctx_t(); + virtual bool idaapi run(size_t) override; + ssize_t idaapi on_dbg_event(ssize_t code, va_list va); + + inline void set_wait_box(const char *mesg); + inline void _hide_wait_box(); + + // Windows9x specific functions + void win9x_resolve_gpa_thunk(); + ea_t win9x_find_thunk(ea_t ea); + void find_thunked_imports(); + + // Resource extractor function + void extract_resource(const char *fname); + void store(const void *Data, uint32 size); +}; + +extern int data_id; + diff --git a/idasdk75/plugins/uunp/uunp.idc b/idasdk76/plugins/uunp/uunp.idc similarity index 100% rename from idasdk75/plugins/uunp/uunp.idc rename to idasdk76/plugins/uunp/uunp.idc diff --git a/idasdk76/plugins/uunp/win9x.cpp b/idasdk76/plugins/uunp/win9x.cpp new file mode 100644 index 0000000..5fefd75 --- /dev/null +++ b/idasdk76/plugins/uunp/win9x.cpp @@ -0,0 +1,172 @@ +/* + This file contains Win9x (95, 98) specific stuff. + + It can be safely ignored if you are only interested in XP systems. + +*/ + +#include <windows.h> + +#include <ida.hpp> +#include <idp.hpp> +#include <dbg.hpp> + +#include "uunp.hpp" + +#pragma pack(push, 1) +//lint --e{958} Padding required +struct push_insn_t +{ + BYTE push; // must be 0x68 + DWORD ea; +}; + +//lint -estring(958,member) padding is required to align members +struct push_jump_insns_t +{ + BYTE push; // must be 0x68 + DWORD ea; + BYTE jmp; // must be 0xE9 + DWORD reloff; //lint !e754 not referenced +}; +#pragma pack(pop) + +//-------------------------------------------------------------------------- +// find the address of the thunk for GetProcessAddress() under Windows 9x +void uunp_ctx_t::win9x_resolve_gpa_thunk() +{ + DWORD off; + + ea_t ea = curmod.start_ea + offsetof(IMAGE_DOS_HEADER, e_lfanew); + if ( read_dbg_memory(ea, &off, sizeof(off)) != sizeof(off) ) + return; + +#define _OI offsetof(IMAGE_NT_HEADERS32, OptionalHeader.DataDirectory[ \ + IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress) + if ( read_dbg_memory((DWORD)curmod.start_ea + off + _OI, &off, sizeof(off)) != sizeof(off) ) + return; +#undef _OI + + IMAGE_IMPORT_DESCRIPTOR imp; + DWORD hK32 = DWORD(size_t(GetModuleHandle("kernel32"))); + + bool found = false; + for ( off += (DWORD)curmod.start_ea; + read_dbg_memory(off, &imp, sizeof(imp)) == sizeof(imp) && imp.Name; + off += sizeof(imp) ) + { + if ( imp.ForwarderChain == hK32 ) + { + found = true; + break; + } + } + if ( found ) + { + DWORD tmp; + for ( off = imp.FirstThunk + (DWORD)curmod.start_ea; + read_dbg_memory(off, &tmp, sizeof(tmp)) == sizeof(tmp) && tmp != 0; + off += sizeof(DWORD) ) + { + if ( tmp >= hK32 ) + continue; // for TH_xxx entries + + push_insn_t thunk; + if ( read_dbg_memory(tmp, &thunk, sizeof(thunk)) != sizeof(thunk) + || thunk.push != 0x68 ) + { + break; + } + + if ( thunk.ea == bp_gpa ) + { + bp_gpa = tmp; + break; + } + } + } +} + +//-------------------------------------------------------------------------- +// find all dwords equal to 'ea' and remember their translations +// search in the current module +static bool calc_thunk_target(uunp_ctx_t &ctx, uint32 ea32, uint32 imp32) +{ + bool matched = false; + + for ( ea_t pos = ctx.curmod.start_ea; + pos <= ctx.curmod.end_ea; + pos += sizeof(DWORD) ) + { + pos = bin_search2(pos, ctx.curmod.end_ea, (uchar *)&ea32, NULL, + 4, BIN_SEARCH_NOBREAK|BIN_SEARCH_CASE|BIN_SEARCH_FORWARD); + if ( pos == BADADDR ) + break; + if ( pos & 3 ) + continue; + + flags_t F = get_flags(pos); + if ( is_tail(F) ) + continue; + + matched = true; + ctx.thunks[pos] = imp32; + } + return matched; +} + +//-------------------------------------------------------------------------- +// find Windows 9x import thunk +static bool resolve_thunk(uunp_ctx_t &ctx, ea_t ea) +{ + push_jump_insns_t thunk; + + if ( get_bytes(&thunk, sizeof(thunk), ea) != sizeof(thunk) + || thunk.push != 0x68 || thunk.jmp != 0xE9 + || thunk.ea < 0x80000000 || thunk.ea >= 0xC0000000 ) + { + return false; + } + + if ( !calc_thunk_target(ctx, uint32(ea), thunk.ea) ) + msg("%a: Thunked import (%08a) without references\n", ea, ea_t(thunk.ea)); + return true; +} + +//-------------------------------------------------------------------------- +// Windows 9x: find thunked imports and their targets +void uunp_ctx_t::find_thunked_imports() +{ + if ( (DWORD)bp_gpa & 0xF ) + { + warning("Non-standard thunk address"); + return; + } + + // find the thunk area for our module + invalidate_dbgmem_contents(curmod.start_ea, curmod.end_ea); // for bin-search + invalidate_dbgmem_contents(0x80000000, 0xC0000000); + + for ( ea_t ea = bp_gpa; ea > 0x80000000; ea -= 0x10 ) + { + if ( !resolve_thunk(*this, ea) ) + break; + } + + for ( ea_t ea = bp_gpa + 0x10; ea < 0xC0000000; ea += 0x10 ) + { + if ( !resolve_thunk(*this, ea) ) + break; + } + + if ( thunks.empty() ) + warning("Could not find thunk area"); +} + +//-------------------------------------------------------------------------- +ea_t uunp_ctx_t::win9x_find_thunk(ea_t ea) +{ + thunks_t::iterator p = thunks.find(ea); + ea_t func = p != thunks.end() ? p->second : get_dword(ea); + return func; +} diff --git a/idasdk76/plugins/vcsample/makefile b/idasdk76/plugins/vcsample/makefile new file mode 100644 index 0000000..d11c0fc --- /dev/null +++ b/idasdk76/plugins/vcsample/makefile @@ -0,0 +1,11 @@ +PROC=strings + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)strings$(O) : $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \ + $(I)expr.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp \ + $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp strings.cpp diff --git a/idasdk75/plugins/vcsample/strings.cpp b/idasdk76/plugins/vcsample/strings.cpp similarity index 100% rename from idasdk75/plugins/vcsample/strings.cpp rename to idasdk76/plugins/vcsample/strings.cpp diff --git a/idasdk76/plugins/z80dbg/makefile b/idasdk76/plugins/z80dbg/makefile new file mode 100644 index 0000000..e06a22d --- /dev/null +++ b/idasdk76/plugins/z80dbg/makefile @@ -0,0 +1,11 @@ +PROC=z80dbg + +include ../plugin.mak + +# MAKEDEP dependency list ------------------ +$(F)z80dbg$(O) : $(I)allins.hpp $(I)bitrange.hpp $(I)bytes.hpp \ + $(I)config.hpp $(I)fpro.h $(I)funcs.hpp $(I)ida.hpp \ + $(I)idd.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \ + $(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp \ + $(I)netnode.hpp $(I)pro.h $(I)range.hpp $(I)segment.hpp \ + $(I)ua.hpp $(I)xref.hpp z80dbg.cpp diff --git a/idasdk75/plugins/z80dbg/z80dbg.cpp b/idasdk76/plugins/z80dbg/z80dbg.cpp similarity index 100% rename from idasdk75/plugins/z80dbg/z80dbg.cpp rename to idasdk76/plugins/z80dbg/z80dbg.cpp diff --git a/idasdk75/readme.txt b/idasdk76/readme.txt similarity index 100% rename from idasdk75/readme.txt rename to idasdk76/readme.txt